From 9e158e253b812e093e5f6063092b3c8e8b3d56a8 Mon Sep 17 00:00:00 2001 From: Bill Goehrig <33036725+wgoehrig@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:36:38 -0400 Subject: [PATCH 1/2] Install and configure dprint --- .dprint.jsonc | 28 +++++++ .vscode/extensions.json | 2 +- .vscode/settings.json | 45 ++++------ common/config/dprint/dprint.schema.json | 27 ++++++ .../rush/browser-approved-packages.json | 4 + common/config/rush/command-line.json | 7 ++ common/config/rush/pnpm-lock.yaml | 83 ++++++++++++++++++- tools/build/package.json | 3 +- 8 files changed, 165 insertions(+), 34 deletions(-) create mode 100644 .dprint.jsonc create mode 100644 common/config/dprint/dprint.schema.json diff --git a/.dprint.jsonc b/.dprint.jsonc new file mode 100644 index 000000000000..c925c165f21d --- /dev/null +++ b/.dprint.jsonc @@ -0,0 +1,28 @@ +{ + "typescript": { + "lineWidth": 150, + "quoteStyle": "preferDouble", + "newLineKind": "auto", + "useBraces": "maintain", + "bracePosition": "sameLine", + "nextControlFlowPosition": "maintain", + "operatorPosition": "maintain", + "arrowFunction.useParentheses": "force", + "module.sortExportDeclarations": "maintain", + "typeLiteral.separatorKind.singleLine": "comma" + }, + "json": { + "trailingCommas": "never" + }, + "excludes": [ + // Note that everything gitignored is already excluded by default. + "**/*-lock.json", + "common/changes/**/*", + "common/config/rush/**/*", + "common/scripts/**/*" + ], + "plugins": [ + "https://plugins.dprint.dev/typescript-0.93.0.wasm", + "https://plugins.dprint.dev/json-0.19.3.wasm" + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 828c6245fc25..3e146dea829b 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,6 +3,6 @@ "streetsidesoftware.code-spell-checker", "dbaeumer.vscode-eslint", "davidanson.vscode-markdownlint", - "mike-co.import-sorter" + "dprint.dprint" ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 482e278de22d..4cbdcad57217 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,11 @@ // Place your settings in this file to overwrite default and user settings. { + "[typescript][typescriptreact][javascript][javascriptreact][json][jsonc]": { + "editor.defaultFormatter": "dprint.dprint" + }, "debug.internalConsoleOptions": "openOnSessionStart", + "dprint.verbose": true, + "dprint.path": "tools/build/node_modules/dprint/dprint", "editor.codeActionsOnSave": { "editor.action.fixAll": "explicit", "source.fixAll.eslint": "explicit", @@ -10,7 +15,7 @@ "editor.formatOnSave": true, "editor.tabSize": 2, "eslint.enable": true, - "eslint.format.enable": true, + "eslint.format.enable": false, "eslint.lintTask.enable": true, "eslint.experimental.useFlatConfig": true, "eslint.validate": [ @@ -44,40 +49,18 @@ "common/temp": true }, "files.trimTrailingWhitespace": true, - "importSorter.generalConfiguration.sortImportsInDirectory": false, - "importSorter.generalConfiguration.sortOnBeforeSave": false, - "importSorter.importStringConfiguration.maximumNumberOfImportExpressionsPerLine.count": 150, - "importSorter.importStringConfiguration.quoteMark": "double", - "importSorter.importStringConfiguration.tabSize": 2, - "importSorter.importStringConfiguration.trailingComma": "multiLine", - "importSorter.sortConfiguration.customOrderingRules.defaultNumberOfEmptyLinesAfterGroup": 0, - "importSorter.sortConfiguration.customOrderingRules.rules": [ - { - "disableSort": true, - "orderLevel": 5, - "regex": "^$", - "type": "importMember" - }, - { - "orderLevel": 10, - "regex": "^[^.@]" - }, - { - "orderLevel": 15, - "regex": "^[@]" - }, - { - "orderLevel": 30, - "regex": "^[.]" - } - ], - "importSorter.sortConfiguration.removeUnusedImports": true, "json.schemas": [ { "fileMatch": [ "certa.json" ], "url": "./tools/certa/certa.schema.json" + }, + { + "fileMatch": [ + ".dprint.jsonc" + ], + "url": "./common/config/dprint/dprint.schema.json" } ], "markdownlint.config": { @@ -103,5 +86,5 @@ "terminal.integrated.env.windows": { "NODE_ENV": "development" }, - "typescript.tsdk": "common/temp/node_modules/typescript/lib", -} \ No newline at end of file + "typescript.tsdk": "common/temp/node_modules/typescript/lib" +} diff --git a/common/config/dprint/dprint.schema.json b/common/config/dprint/dprint.schema.json new file mode 100644 index 000000000000..7b55405893b7 --- /dev/null +++ b/common/config/dprint/dprint.schema.json @@ -0,0 +1,27 @@ +{ + "type": "object", + "properties": { + "typescript": { + "$ref": "https://plugins.dprint.dev/dprint/dprint-plugin-typescript/latest/schema.json" + }, + "json": { + "$ref": "https://plugins.dprint.dev/dprint/dprint-plugin-json/latest/schema.json" + }, + "markdown": { + "$ref": "https://plugins.dprint.dev/dprint/dprint-plugin-markdown/latest/schema.json" + }, + "excludes": { + "type": "array", + "items": { + "type": "string" + } + }, + "plugins": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + } + } + } +} diff --git a/common/config/rush/browser-approved-packages.json b/common/config/rush/browser-approved-packages.json index bf7bae1000de..649fe9d04c88 100644 --- a/common/config/rush/browser-approved-packages.json +++ b/common/config/rush/browser-approved-packages.json @@ -526,6 +526,10 @@ "name": "dotenv-expand", "allowedCategories": [ "backend", "integration-testing", "internal" ] }, + { + "name": "dprint", + "allowedCategories": [ "tools" ] + }, { "name": "electron", "allowedCategories": [ "backend", "internal", "tools" ] diff --git a/common/config/rush/command-line.json b/common/config/rush/command-line.json index ec99a3b1d93b..e4baf2e8588a 100644 --- a/common/config/rush/command-line.json +++ b/common/config/rush/command-line.json @@ -15,6 +15,13 @@ "description": "Manually runs the new copyright linter on all files changed between the current branch and master.", "shellCommand": "node common/scripts/copyright-linter.js --fix" }, + { + "name": "fmt", + "commandKind": "global", + "summary": "Runs dprint fmt for the entire monorepo", + "description": "Runs the dprint code formatter on all TypeScript and JSON files in the monorepo.", + "shellCommand": "node tools/build/node_modules/dprint/bin.js fmt" + }, { "name": "clean", "commandKind": "bulk", diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 6076bc296e5e..7b6417bc97b7 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -2895,6 +2895,7 @@ importers: chalk: ^3.0.0 cpx2: ^3.0.0 cross-spawn: ^7.0.1 + dprint: ~0.47.2 eslint: ^8.56.0 fs-extra: ^8.1.0 glob: ^10.3.12 @@ -2912,6 +2913,7 @@ importers: chalk: 3.0.0 cpx2: 3.0.0 cross-spawn: 7.0.1 + dprint: 0.47.2 fs-extra: 8.1.0 glob: 10.3.12 mocha: 10.2.0 @@ -3761,6 +3763,70 @@ packages: engines: {node: '>=10.0.0'} dev: true + /@dprint/darwin-arm64/0.47.2: + resolution: {integrity: sha512-mVPFBJsXxGDKHHCAY8wbqOyS4028g1bN15H9tivCnPAjwaZhkUimZHXWejXADjhGn+Xm2SlakugY9PY/68pH3Q==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@dprint/darwin-x64/0.47.2: + resolution: {integrity: sha512-T7wzlc+rBV+6BRRiBjoqoy5Hj4TR2Nv2p2s9+ycyPGs10Kj/JXOWD8dnEHeBgUr2r4qe/ZdcxmsFQ5Hf2n0WuA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@dprint/linux-arm64-glibc/0.47.2: + resolution: {integrity: sha512-B0m1vT5LdVtrNOVdkqpLPrSxuCD+l5bTIgRzPaDoIB1ChWQkler9IlX8C+RStpujjPj6SYvwo5vTzjQSvRdQkA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@dprint/linux-arm64-musl/0.47.2: + resolution: {integrity: sha512-zID6wZZqpg2/Q2Us+ERQkbhLwlW3p3xaeEr00MPf49bpydmEjMiPuSjWPkNv+slQSIyIsVovOxF4lbNZjsdtvw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@dprint/linux-x64-glibc/0.47.2: + resolution: {integrity: sha512-rB3WXMdINnRd33DItIp7mObS7dzHW90ZzeJSsoKJLPp+Z7wXjjb27UUowfqVI4baa/1pd7sdbX54DPohMtfu/A==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@dprint/linux-x64-musl/0.47.2: + resolution: {integrity: sha512-E0+TNbzYdTXJ/jCVjUctVxkda/faw++aDQLfyWGcmdMJnbM7NZz+W4fUpDXzMPsjy+zTWxXcPK7/q2DZz2gnbg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@dprint/win32-arm64/0.47.2: + resolution: {integrity: sha512-K1EieTCFjfOCmyIhw9zFSduE6qVCNHEveupqZEfbSkVGw5T9MJQ1I9+n7MDb3RIDYEUk0enJ58/w82q8oDKCyA==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: false + optional: true + + /@dprint/win32-x64/0.47.2: + resolution: {integrity: sha512-LhizWr8VrhHvq4ump8HwOERyFmdLiE8C6A42QSntGXzKdaa2nEOq20x/o56ZIiDcesiV+1TmosMKimPcOZHa+Q==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: false + optional: true + /@electron/get/2.0.3: resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} engines: {node: '>=12'} @@ -7471,6 +7537,21 @@ packages: resolution: {integrity: sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==} dev: false + /dprint/0.47.2: + resolution: {integrity: sha512-geUcVIIrmLaY+YtuOl4gD7J/QCjsXZa5gUqre9sO6cgH0X/Fa9heBN3l/AWVII6rKPw45ATuCSDWz1pyO+HkPQ==} + hasBin: true + requiresBuild: true + optionalDependencies: + '@dprint/darwin-arm64': 0.47.2 + '@dprint/darwin-x64': 0.47.2 + '@dprint/linux-arm64-glibc': 0.47.2 + '@dprint/linux-arm64-musl': 0.47.2 + '@dprint/linux-x64-glibc': 0.47.2 + '@dprint/linux-x64-musl': 0.47.2 + '@dprint/win32-arm64': 0.47.2 + '@dprint/win32-x64': 0.47.2 + dev: false + /draco3d/1.4.1: resolution: {integrity: sha512-9Rxonc70xiovBC+Bq1h57SNZIHzWTibU1VfIGp5z3Xx8dPtv4yT5uGhiH7P5uvJRR2jkrvHafRxR7bTANkvfpg==} dev: false @@ -13435,7 +13516,7 @@ packages: perfect-debounce: 1.0.0 picocolors: 1.0.1 sirv: 2.0.4 - vite: 5.4.6_@types+node@18.16.20 + vite: 5.4.6 transitivePeerDependencies: - rollup - supports-color diff --git a/tools/build/package.json b/tools/build/package.json index 8efff9f11e84..4e95ae87e792 100644 --- a/tools/build/package.json +++ b/tools/build/package.json @@ -43,7 +43,8 @@ "typedoc-plugin-merge-modules": "^5.1.0", "typescript": "~5.3.3", "wtfnode": "^0.9.1", - "yargs": "^17.4.0" + "yargs": "^17.4.0", + "dprint": "~0.47.2" }, "devDependencies": { "@itwin/eslint-plugin": "^4.0.2", From 9ec42d92bacc7cf6b43d7bc899d369de68495b4b Mon Sep 17 00:00:00 2001 From: Bill Goehrig <33036725+wgoehrig@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:14:08 -0400 Subject: [PATCH 2/2] rush fmt --- .devcontainer/devcontainer.json | 2 +- .../invalidate-status-checks.mjs | 38 +- .../automation-scripts/update-changelogs.mjs | 62 +- .mocharc.jsonc | 2 +- .vscode/extensions.json | 2 +- .vscode/launch.json | 95 +- .vscode/tasks.json | 2 +- common/config/eslint/eslint.config.base.js | 12 +- core/backend/eslint.config.js | 10 +- core/backend/runUnitTestsIosSimulator.ts | 34 +- core/backend/src/BackendHubAccess.ts | 22 +- core/backend/src/BisCoreSchema.ts | 12 +- core/backend/src/BlobContainerService.ts | 3 +- core/backend/src/BriefcaseManager.ts | 80 +- core/backend/src/Category.ts | 90 +- core/backend/src/ChangeSummaryManager.ts | 148 +- core/backend/src/ChangedElementsDb.ts | 26 +- core/backend/src/ChangedElementsManager.ts | 4 +- core/backend/src/ChangesetECAdaptor.ts | 41 +- core/backend/src/ChannelControl.ts | 1 - core/backend/src/CheckpointManager.ts | 102 +- core/backend/src/ClassRegistry.ts | 61 +- core/backend/src/CloudSqlite.ts | 119 +- core/backend/src/CodeService.ts | 54 +- core/backend/src/CodeSpecs.ts | 8 +- core/backend/src/CustomViewState3dCreator.ts | 3 +- core/backend/src/DevTools.ts | 10 +- core/backend/src/DisplayStyle.ts | 60 +- core/backend/src/ECDb.ts | 18 +- core/backend/src/ECSchemaXmlContext.ts | 2 +- core/backend/src/ECSqlStatement.ts | 255 +- core/backend/src/Element.ts | 472 +- core/backend/src/ElementAspect.ts | 52 +- core/backend/src/ElementGraphics.ts | 2 +- core/backend/src/ElementTreeWalker.ts | 75 +- core/backend/src/Entity.ts | 41 +- core/backend/src/EntityReferences.ts | 8 +- core/backend/src/ExportGraphics.ts | 35 +- core/backend/src/ExternalSource.ts | 30 +- core/backend/src/GeoCoordConfig.ts | 11 +- core/backend/src/GeographicCRSServices.ts | 4 +- core/backend/src/GeometrySummary.ts | 48 +- core/backend/src/HubMock.ts | 37 +- core/backend/src/IModelDb.ts | 491 +- core/backend/src/IModelElementCloneContext.ts | 16 +- core/backend/src/IModelHost.ts | 80 +- core/backend/src/IModelJsFs.ts | 46 +- core/backend/src/IpcHost.ts | 61 +- core/backend/src/LineStyle.ts | 21 +- core/backend/src/LocalHub.ts | 115 +- core/backend/src/LocalhostIpcHost.ts | 10 +- core/backend/src/Material.ts | 31 +- core/backend/src/Model.ts | 193 +- core/backend/src/NativeAppStorage.ts | 49 +- core/backend/src/NativeHost.ts | 38 +- core/backend/src/NavigationRelationship.ts | 4 +- core/backend/src/PromiseMemoizer.ts | 12 +- core/backend/src/PropertyStore.ts | 41 +- core/backend/src/Relationship.ts | 103 +- core/backend/src/SQLiteDb.ts | 75 +- core/backend/src/Schema.ts | 18 +- core/backend/src/SchemaSync.ts | 30 +- core/backend/src/SheetIndex.ts | 50 +- core/backend/src/SqliteChangesetReader.ts | 40 +- core/backend/src/SqliteStatement.ts | 107 +- core/backend/src/TextAnnotationElement.ts | 20 +- core/backend/src/TextAnnotationGeometry.ts | 8 +- core/backend/src/TextAnnotationLayout.ts | 51 +- core/backend/src/Texture.ts | 26 +- core/backend/src/TileStorage.ts | 24 +- core/backend/src/TxnManager.ts | 141 +- core/backend/src/ViewDefinition.ts | 267 +- core/backend/src/ViewStateHydrator.ts | 26 +- core/backend/src/ViewStore.ts | 190 +- .../assets/Settings/Schemas/Base.Schema.json | 2 +- .../assets/Settings/Schemas/Gcs.schema.json | 2 +- .../Settings/Schemas/Workspace.Schema.json | 2 +- core/backend/src/core-backend.ts | 13 +- .../backend/src/domains/FunctionalElements.ts | 47 +- core/backend/src/domains/FunctionalSchema.ts | 12 +- core/backend/src/domains/GenericElements.ts | 99 +- core/backend/src/domains/GenericSchema.ts | 8 +- .../src/internal/ChangesetConflictArgs.ts | 1 - core/backend/src/internal/ChannelAdmin.ts | 3 +- core/backend/src/internal/NativePlatform.ts | 4 +- core/backend/src/internal/NoLocks.ts | 28 +- core/backend/src/internal/ServerBasedLocks.ts | 40 +- core/backend/src/internal/cross-package.ts | 4 +- .../src/internal/workspace/SettingsImpl.ts | 25 +- .../internal/workspace/SettingsSchemasImpl.ts | 9 +- .../src/internal/workspace/WorkspaceImpl.ts | 99 +- .../internal/workspace/WorkspaceSqliteDb.ts | 5 +- core/backend/src/linebreak.d.ts | 1 - core/backend/src/rpc-impl/DevToolsRpcImpl.ts | 4 +- .../backend/src/rpc-impl/IModelReadRpcImpl.ts | 115 +- .../backend/src/rpc-impl/IModelTileRpcImpl.ts | 79 +- .../src/rpc-impl/RpcBriefcaseUtility.ts | 46 +- .../src/rpc-impl/SnapshotIModelRpcImpl.ts | 12 +- core/backend/src/rpc-impl/WipRpcImpl.ts | 15 +- core/backend/src/rpc/multipart.ts | 2 +- core/backend/src/rpc/tracing.ts | 4 +- core/backend/src/rpc/web/logging.ts | 15 +- core/backend/src/rpc/web/response.ts | 16 +- core/backend/src/test/AdvancedEqual.ts | 21 +- core/backend/src/test/GeometryTestUtil.ts | 8 +- core/backend/src/test/IModelHost.test.ts | 24 +- core/backend/src/test/IModelTestUtils.ts | 545 +- core/backend/src/test/KnownTestLocations.ts | 5 +- core/backend/src/test/PrintElementTree.ts | 2 +- core/backend/src/test/PropertyDb.test.ts | 4 +- core/backend/src/test/RevisionUtility.ts | 9 +- core/backend/src/test/SchemaUtils.test.ts | 28 +- core/backend/src/test/SequentialLogMatcher.ts | 4 +- core/backend/src/test/TestChangeSetUtility.ts | 20 +- core/backend/src/test/TestUtils.ts | 3 +- .../test/annotations/TextAnnotation.test.ts | 128 +- .../src/test/assets/TestSettings.schema.json | 2 +- .../NoVersionsTest/NoVersionsTest.json | 16 +- .../NoVersionsTestChangeSets.json | 2 +- .../_mocks_/Projects/NodeJsTestProject.json | 2 +- .../_mocks_/ReadOnlyTest/ReadOnlyTest.json | 16 +- .../ReadOnlyTest/ReadOnlyTestBriefcase.json | 20 +- .../ReadOnlyTest/ReadOnlyTestChangeSets.json | 83 +- .../versions/ReadOnlyTestFirstVersion.json | 8 +- .../versions/ReadOnlyTestSecondVersion.json | 8 +- .../versions/ReadOnlyTestThirdVersion.json | 8 +- .../_mocks_/ReadWriteTest/ReadWriteTest.json | 16 +- .../ReadWriteTest/ReadWriteTestBriefcase.json | 20 +- .../ReadWriteTestChangeSets.json | 23 +- .../src/test/categories/Category.test.ts | 6 +- .../src/test/codespec/CodeSpec.test.ts | 4 +- core/backend/src/test/ecdb/CTE.test.ts | 103 +- core/backend/src/test/ecdb/ECDb.test.ts | 62 +- core/backend/src/test/ecdb/ECDbTestHelper.ts | 3 +- .../src/test/ecdb/ECSchemaXmlContext.test.ts | 1 - core/backend/src/test/ecdb/ECSqlAst.test.ts | 106 +- core/backend/src/test/ecdb/ECSqlQuery.test.ts | 118 +- .../backend/src/test/ecdb/ECSqlReader.test.ts | 215 +- .../src/test/ecdb/ECSqlStatement.test.ts | 5822 +- .../src/test/ecdb/SqliteStatement.test.ts | 61 +- .../element/DeleteDefinitionElements.test.ts | 32 +- .../src/test/element/ElementAspect.test.ts | 160 +- .../element/ElementDependencyGraph.test.ts | 40 +- .../src/test/element/ElementRoundTrip.test.ts | 112 +- .../src/test/element/ExcludedElements.test.ts | 13 +- .../src/test/element/ExternalSource.test.ts | 53 +- .../src/test/element/NullStructArray.test.ts | 26 +- core/backend/src/test/element/UrlLink.test.ts | 2 +- .../test/hubaccess/BriefcaseManager.test.ts | 6 +- .../test/hubaccess/CheckpointManager.test.ts | 7 +- core/backend/src/test/imageData.ts | 134 +- .../src/test/imodel/ElementTreeWalker.test.ts | 125 +- .../src/test/imodel/GetTextureImage.test.ts | 19 +- core/backend/src/test/imodel/IModel.test.ts | 533 +- .../src/test/imodel/ProjectExtents.test.ts | 7 +- .../src/test/imodel/SchemaXmlImport.test.ts | 3 +- core/backend/src/test/misc/DevTools.test.ts | 5 +- .../backend/src/test/misc/GeoServices.test.ts | 173 +- .../src/test/misc/PromiseMemoizer.test.ts | 4 +- .../src/test/native/DgnDbWorker.test.ts | 68 +- core/backend/src/test/rpc/response.test.ts | 15 +- .../src/test/schema/ClassRegistry.test.ts | 154 +- .../src/test/schema/FunctionalDomain.test.ts | 105 +- .../src/test/schema/GenericDomain.test.ts | 36 +- .../src/test/sheetindex/SheetIndex.test.ts | 204 +- .../standalone/ChangeConflictHandler.test.ts | 101 +- .../test/standalone/ChangesetReader.test.ts | 107 +- .../CustomViewState3dCreator.test.ts | 21 +- .../src/test/standalone/DisplayStyle.test.ts | 37 +- .../test/standalone/ElementGraphics.test.ts | 18 +- .../src/test/standalone/ElementMesh.test.ts | 42 +- .../test/standalone/ExportGraphics.test.ts | 534 +- .../standalone/GeometryChangeEvents.test.ts | 17 +- .../test/standalone/GeometryStream.test.ts | 980 +- .../src/test/standalone/HubMock.test.ts | 79 +- .../src/test/standalone/IModelWrite.test.ts | 154 +- .../InlineGeometryPartReferences.test.ts | 73 +- .../src/test/standalone/MergeConflict.test.ts | 71 +- .../test/standalone/NativeAppStorage.test.ts | 2 +- .../standalone/RenderMaterialElement.test.ts | 205 +- .../test/standalone/RenderTimeline.test.ts | 2 +- .../src/test/standalone/SQLiteDb.test.ts | 12 +- .../src/test/standalone/SchemaUtils.test.ts | 3 +- .../test/standalone/SectionDrawing.test.ts | 6 +- .../test/standalone/ServerBasedLocks.test.ts | 12 +- .../src/test/standalone/Setting.test.ts | 2 +- .../src/test/standalone/Settings.test.ts | 27 +- .../test/standalone/SettingsSchemas.test.ts | 4 +- .../src/test/standalone/SnapshotDb.test.ts | 34 +- .../src/test/standalone/Texture.test.ts | 748 +- .../src/test/standalone/TileCache.test.ts | 26 +- .../src/test/standalone/TileTree.test.ts | 25 +- .../src/test/standalone/TxnManager.test.ts | 28 +- .../test/standalone/ViewDefinition.test.ts | 222 +- .../src/test/standalone/ViewStoreDb.test.ts | 126 +- .../src/test/standalone/Workspace.test.ts | 33 +- core/backend/src/workspace/Settings.ts | 4 +- core/backend/src/workspace/SettingsSchemas.ts | 84 +- core/backend/src/workspace/Workspace.ts | 47 +- core/backend/src/workspace/WorkspaceEditor.ts | 26 +- core/backend/tsconfig.json | 2 +- core/bentley/eslint.config.js | 2 +- core/bentley/src/AccessToken.ts | 1 - core/bentley/src/BeEvent.ts | 24 +- core/bentley/src/BentleyError.ts | 813 +- core/bentley/src/ByteStream.ts | 78 +- core/bentley/src/ClassUtils.ts | 12 +- core/bentley/src/CompressedId64Set.ts | 26 +- core/bentley/src/Dictionary.ts | 12 +- core/bentley/src/Disposable.ts | 8 +- core/bentley/src/Id.ts | 37 +- core/bentley/src/IndexMap.ts | 20 +- core/bentley/src/JsonUtils.ts | 1 - core/bentley/src/LRUMap.ts | 6 +- core/bentley/src/Logger.ts | 54 +- core/bentley/src/OneAtATimeAction.ts | 4 +- core/bentley/src/PriorityQueue.ts | 12 +- core/bentley/src/ProcessDetector.ts | 76 +- core/bentley/src/SortedArray.ts | 40 +- core/bentley/src/StatusCategory.ts | 768 +- core/bentley/src/Time.ts | 106 +- core/bentley/src/Tracing.ts | 8 +- core/bentley/src/TupleKeyedMap.ts | 5 +- core/bentley/src/TypedArrayBuilder.ts | 2 +- core/bentley/src/UnexpectedErrors.ts | 11 +- core/bentley/src/UtilityTypes.ts | 6 +- core/bentley/src/internal/BeSQLiteInternal.ts | 5 +- core/bentley/src/internal/RepositoryStatus.ts | 1 - core/bentley/src/test/BeEvent.test.ts | 39 +- core/bentley/src/test/BentleyError.test.ts | 8 +- core/bentley/src/test/ClassUtils.test.ts | 32 +- core/bentley/src/test/Disposable.test.ts | 22 +- core/bentley/src/test/Id.test.ts | 82 +- core/bentley/src/test/IndexMap.test.ts | 4 +- core/bentley/src/test/InstanceOf.test.ts | 4 +- core/bentley/src/test/LRUMap.test.ts | 2 - core/bentley/src/test/Logger.test.ts | 57 +- core/bentley/src/test/ObservableSet.test.ts | 20 +- core/bentley/src/test/OneAtATime.test.ts | 1 - core/bentley/src/test/SortedArray.test.ts | 12 +- core/bentley/src/test/Time.test.ts | 2 - core/bentley/src/test/TupleKeyedMap.test.ts | 6 +- .../bentley/src/test/UnexpectedErrors.test.ts | 1 - core/bentley/src/test/YieldManager.test.ts | 1 - core/bentley/src/test/partitionArray.test.ts | 34 +- core/bentley/vitest.config.mts | 14 +- core/common/eslint.config.js | 12 +- core/common/extraction.eslint.config.js | 4 +- core/common/src/AmbientOcclusion.ts | 4 +- core/common/src/AnalysisStyle.ts | 2 +- core/common/src/Atmosphere.ts | 1 - core/common/src/BackendTypes.ts | 2 +- core/common/src/BackgroundMapSettings.ts | 8 +- core/common/src/BlobReader.ts | 35 +- core/common/src/BriefcaseTypes.ts | 1 - core/common/src/Camera.ts | 48 +- core/common/src/ChangedElements.ts | 2 +- core/common/src/ChangesetProps.ts | 19 +- core/common/src/ClipStyle.ts | 45 +- core/common/src/Code.ts | 48 +- core/common/src/ColorDef.ts | 73 +- core/common/src/ConcurrentQuery.ts | 67 +- core/common/src/ContextRealityModel.ts | 31 +- core/common/src/ContourDisplay.ts | 17 +- core/common/src/DisplayStyleSettings.ts | 141 +- core/common/src/ECSqlReader.ts | 38 +- core/common/src/ECSqlTypes.ts | 5 +- core/common/src/ElementProps.ts | 15 +- core/common/src/EntityReference.ts | 16 +- core/common/src/FeatureIndex.ts | 28 +- core/common/src/FeatureSymbology.ts | 224 +- core/common/src/FeatureTable.ts | 117 +- core/common/src/Fonts.ts | 10 +- core/common/src/Frustum.ts | 70 +- core/common/src/GenericInstanceFilter.ts | 3 +- core/common/src/GeoCoordinateServices.ts | 32 +- core/common/src/GeometryContainment.ts | 2 +- core/common/src/Gradient.ts | 27 +- core/common/src/GraphicParams.ts | 8 +- core/common/src/HiddenLine.ts | 8 +- core/common/src/Hilite.ts | 4 +- core/common/src/IModel.ts | 70 +- core/common/src/IModelError.ts | 24 +- core/common/src/IModelVersion.ts | 37 +- core/common/src/Image.ts | 17 +- core/common/src/IpcAppProps.ts | 1 - core/common/src/LightSettings.ts | 23 +- core/common/src/Localization.ts | 30 +- core/common/src/MapImagerySettings.ts | 21 +- core/common/src/MapLayerSettings.ts | 69 +- core/common/src/ModelGeometryChanges.ts | 3 +- core/common/src/NativeAppProps.ts | 3 +- core/common/src/OctEncodedNormal.ts | 2 +- core/common/src/PlanProjectionSettings.ts | 7 +- core/common/src/PlanarClipMask.ts | 31 +- core/common/src/QPoint.ts | 63 +- core/common/src/RealityDataAccessProps.ts | 2 +- .../common/src/RealityModelDisplaySettings.ts | 14 +- core/common/src/Render.ts | 34 +- core/common/src/RenderMaterial.ts | 17 +- core/common/src/RenderSchedule.ts | 74 +- core/common/src/RenderTexture.ts | 24 +- core/common/src/RpcInterface.ts | 53 +- core/common/src/RpcManager.ts | 17 +- core/common/src/SessionProps.ts | 1 - core/common/src/SkyBox.ts | 5 +- core/common/src/SolarCalculate.ts | 34 +- core/common/src/SpatialClassification.ts | 10 +- core/common/src/SubCategoryAppearance.ts | 18 +- core/common/src/SubCategoryOverride.ts | 9 +- core/common/src/TerrainSettings.ts | 24 +- core/common/src/TextureMapping.ts | 29 +- core/common/src/TextureProps.ts | 2 +- core/common/src/ThematicDisplay.ts | 35 +- core/common/src/TileProps.ts | 2 +- core/common/src/Tween.ts | 45 +- core/common/src/ViewDetails.ts | 2 +- core/common/src/ViewProps.ts | 7 +- core/common/src/annotation/TextBlock.ts | 11 +- .../src/annotation/TextBlockLayoutResult.ts | 2 +- core/common/src/annotation/TextStyle.ts | 3 +- .../src/geometry/AdditionalTransform.ts | 12 +- core/common/src/geometry/AreaPattern.ts | 20 +- core/common/src/geometry/BoundingSphere.ts | 3 +- core/common/src/geometry/Cartographic.ts | 30 +- .../src/geometry/CoordinateReferenceSystem.ts | 25 +- core/common/src/geometry/ElementGeometry.ts | 334 +- core/common/src/geometry/ElementGeometryFB.ts | 305 +- core/common/src/geometry/GeodeticDatum.ts | 57 +- core/common/src/geometry/GeodeticEllipsoid.ts | 3 +- core/common/src/geometry/GeometryStream.ts | 71 +- core/common/src/geometry/LineStyle.ts | 9 +- core/common/src/geometry/Placement.ts | 56 +- core/common/src/geometry/Projection.ts | 117 +- core/common/src/geometry/TextString.ts | 6 +- core/common/src/internal/cross-package.ts | 1 - core/common/src/ipc/IpcSession.ts | 4 +- core/common/src/ipc/IpcSocket.ts | 10 +- core/common/src/ipc/IpcWebSocket.ts | 6 +- core/common/src/ipc/IpcWebSocketTransport.ts | 16 +- core/common/src/rpc/DevToolsRpcInterface.ts | 16 +- core/common/src/rpc/IModelReadRpcInterface.ts | 171 +- core/common/src/rpc/IModelTileRpcInterface.ts | 25 +- .../src/rpc/SnapshotIModelRpcInterface.ts | 20 +- core/common/src/rpc/WipRpcInterface.ts | 28 +- core/common/src/rpc/core/RpcConfiguration.ts | 16 +- core/common/src/rpc/core/RpcConstants.ts | 4 +- core/common/src/rpc/core/RpcControl.ts | 11 +- core/common/src/rpc/core/RpcInvocation.ts | 85 +- core/common/src/rpc/core/RpcMarshaling.ts | 8 +- core/common/src/rpc/core/RpcOperation.ts | 42 +- core/common/src/rpc/core/RpcPendingQueue.ts | 2 +- core/common/src/rpc/core/RpcProtocol.ts | 14 +- core/common/src/rpc/core/RpcPush.ts | 8 +- core/common/src/rpc/core/RpcRegistry.ts | 34 +- core/common/src/rpc/core/RpcRequest.ts | 115 +- .../src/rpc/core/RpcSessionInvocation.ts | 8 +- .../src/rpc/web/BentleyCloudRpcManager.ts | 17 +- .../src/rpc/web/BentleyCloudRpcProtocol.ts | 13 +- .../web/BentleyCloudRpcRouting.swagger.json | 2 +- core/common/src/rpc/web/RpcMultipart.ts | 3 +- core/common/src/rpc/web/WebAppRpcLogging.ts | 34 +- core/common/src/rpc/web/WebAppRpcProtocol.ts | 72 +- core/common/src/rpc/web/WebAppRpcRequest.ts | 18 +- core/common/src/test/AnalysisStyle.test.ts | 40 +- .../src/test/BackgroundMapSettings.test.ts | 2 +- core/common/src/test/Cartographic.test.ts | 2 +- core/common/src/test/ClipStyle.test.ts | 14 +- core/common/src/test/ColorDef.test.ts | 1 - core/common/src/test/ConcurrentQuery.test.ts | 2 +- .../src/test/ContextRealityModel.test.ts | 160 +- core/common/src/test/ContourDisplay.test.ts | 26 +- .../test/CoordinateReferenceSystem.test.ts | 47 +- core/common/src/test/CutStyle.test.ts | 4 +- core/common/src/test/DisplayStyle.test.ts | 102 +- core/common/src/test/ElementMesh.test.ts | 3 +- core/common/src/test/FeatureIndex.test.ts | 22 +- core/common/src/test/FeatureSymbology.test.ts | 160 +- core/common/src/test/FeatureTable.test.ts | 60 +- core/common/src/test/FrustumPlanes.test.ts | 42 +- .../src/test/GenericInstanceFilter.test.ts | 6 +- core/common/src/test/Gradient.test.ts | 2 +- core/common/src/test/IModel.test.ts | 40 +- .../common/src/test/IntersectionStyle.test.ts | 4 +- core/common/src/test/LightSettings.test.ts | 4 +- core/common/src/test/MapLayerSettings.test.ts | 33 +- .../src/test/ModelGeometryChanges.test.ts | 6 +- .../src/test/ModelMapLayerSettings.test.ts | 1 - core/common/src/test/OctEncodedNormal.test.ts | 2 +- core/common/src/test/Placement.test.ts | 16 +- .../src/test/PlanProjectionSettings.test.ts | 7 +- .../src/test/PlanarClipMaskSettings.test.ts | 46 +- core/common/src/test/QPoint.test.ts | 2 +- .../test/RealityModelDisplaySettings.test.ts | 59 +- core/common/src/test/Render.test.ts | 2 +- core/common/src/test/RenderSchedule.test.ts | 102 +- core/common/src/test/SolarCalculate.test.ts | 37 +- .../src/test/SpatialClassification.test.ts | 28 +- .../src/test/SubCategoryAppearance.test.ts | 2 +- core/common/src/test/ThematicDisplay.test.ts | 9 +- .../src/test/ThematicGradientSettings.test.ts | 27 +- core/common/src/test/TileMetadata.test.ts | 330 +- core/common/src/test/Tween.test.ts | 61 +- .../common/src/test/VersionCompatible.test.ts | 2 +- core/common/src/test/ViewDetails.test.ts | 9 +- core/common/src/test/ViewFlags.test.ts | 20 +- .../test/annotations/TextAnnotation.test.ts | 11 +- .../src/test/annotations/TextBlock.test.ts | 16 +- .../src/test/annotations/TextStyle.test.ts | 2 +- core/common/src/tile/B3dmTileIO.ts | 4 +- core/common/src/tile/CompositeTileIO.ts | 4 +- core/common/src/tile/I3dmTileIO.ts | 4 +- core/common/src/tile/IModelTileIO.ts | 16 +- core/common/src/tile/PntsTileIO.ts | 4 +- core/common/src/tile/TileIO.ts | 14 +- core/common/src/tile/TileMetadata.ts | 61 +- core/common/src/tile/Tileset3dSchema.ts | 48 +- core/common/vitest.config.mts | 14 +- core/ecschema-editing/eslint.config.js | 6 +- .../public/locales/en/ECSchemaEditing.json | 2 +- .../scripts/createLocalization.js | 10 +- .../src/Differencing/SchemaConflicts.ts | 1 - .../Differencing/SchemaDiagnosticVisitor.ts | 33 +- .../src/Differencing/SchemaDifference.ts | 96 +- .../Differencing/SchemaDifferenceValidator.ts | 57 +- .../Differencing/SchemaDifferenceVisitor.ts | 7 +- .../ecschema-editing/src/Editing/Constants.ts | 34 +- .../src/Editing/CustomAttributes.ts | 34 +- .../ecschema-editing/src/Editing/ECClasses.ts | 168 +- core/ecschema-editing/src/Editing/Editor.ts | 53 +- core/ecschema-editing/src/Editing/Entities.ts | 87 +- .../src/Editing/Enumerations.ts | 37 +- .../ecschema-editing/src/Editing/Exception.ts | 84 +- core/ecschema-editing/src/Editing/Formats.ts | 33 +- .../src/Editing/InvertedUnits.ts | 44 +- .../src/Editing/KindOfQuantities.ts | 41 +- core/ecschema-editing/src/Editing/Mixins.ts | 54 +- .../src/Editing/Mutable/MutableClass.ts | 15 +- .../src/Editing/Mutable/MutableEntityClass.ts | 17 +- .../src/Editing/Mutable/MutableFormat.ts | 2 +- .../Editing/Mutable/MutableKindOfQuantity.ts | 6 +- .../src/Editing/Mutable/MutableMixin.ts | 12 +- .../Mutable/MutableRelationshipClass.ts | 36 +- .../src/Editing/Mutable/MutableSchema.ts | 23 +- .../src/Editing/Mutable/MutableSchemaItem.ts | 2 +- .../ecschema-editing/src/Editing/Phenomena.ts | 22 +- .../src/Editing/Properties.ts | 128 +- .../src/Editing/PropertyCategories.ts | 24 +- .../src/Editing/RelationshipClasses.ts | 117 +- .../src/Editing/SchemaItems.ts | 32 +- core/ecschema-editing/src/Editing/Structs.ts | 19 +- .../src/Editing/UnitSystems.ts | 23 +- core/ecschema-editing/src/Editing/Units.ts | 29 +- .../src/Merging/ClassMerger.ts | 25 +- .../src/Merging/ConstantMerger.ts | 4 +- .../src/Merging/CustomAttributeClassMerger.ts | 4 +- .../src/Merging/CustomAttributeMerger.ts | 14 +- .../src/Merging/Edits/RenameEditHandler.ts | 50 +- .../src/Merging/Edits/SchemaEdits.ts | 7 +- .../src/Merging/Edits/SkipEditHandler.ts | 1 - .../src/Merging/EntityClassMerger.ts | 10 +- .../src/Merging/EnumerationMerger.ts | 16 +- .../src/Merging/EnumeratorMerger.ts | 8 +- .../src/Merging/KindOfQuantityMerger.ts | 22 +- .../src/Merging/MixinMerger.ts | 6 +- .../src/Merging/PhenomenonMerger.ts | 8 +- .../src/Merging/PropertyCategoryMerger.ts | 8 +- .../src/Merging/PropertyMerger.ts | 29 +- .../src/Merging/RelationshipClassMerger.ts | 47 +- .../src/Merging/SchemaMerger.ts | 7 +- .../src/Merging/SchemaMergingVisitor.ts | 95 +- .../src/Merging/SchemaMergingWalker.ts | 4 +- .../src/Merging/SchemaReferenceMerger.ts | 19 +- .../src/Merging/StructClassMerger.ts | 4 +- .../src/Merging/UnitSystemMerger.ts | 6 +- core/ecschema-editing/src/Merging/Utils.ts | 4 +- .../src/Validation/Diagnostic.ts | 102 +- .../src/Validation/ECRules.ts | 294 +- .../Validation/LoggingDiagnosticReporter.ts | 11 +- .../src/Validation/RuleSuppressionSet.ts | 28 +- core/ecschema-editing/src/Validation/Rules.ts | 28 +- .../src/Validation/SchemaChanges.ts | 166 +- .../Validation/SchemaCompareDiagnostics.ts | 49 +- .../Validation/SchemaCompareResultDelegate.ts | 210 +- .../src/Validation/SchemaCompareVisitor.ts | 31 +- .../src/Validation/SchemaComparer.ts | 213 +- .../src/Validation/SchemaValidater.ts | 6 +- .../src/Validation/SchemaValidationVisitor.ts | 39 +- .../src/Validation/SchemaWalker.ts | 10 +- core/ecschema-editing/src/ecschema-editing.ts | 2 +- .../src/test/Differencing/Conflicts.test.ts | 15 +- .../src/test/Differencing/Difference.test.ts | 52 +- .../test/Differencing/sourceSchema.json.ts | 6 +- .../test/Differencing/targetSchema.json.ts | 10 +- .../src/test/Editing/Constants.test.ts | 28 +- .../src/test/Editing/CustomAttributes.test.ts | 108 +- .../src/test/Editing/ECClasses.test.ts | 68 +- .../src/test/Editing/Editor.test.ts | 53 +- .../src/test/Editing/Entities.test.ts | 120 +- .../src/test/Editing/Enumerations.test.ts | 37 +- .../src/test/Editing/Exception.test.ts | 56 +- .../src/test/Editing/Formats.test.ts | 25 +- .../src/test/Editing/InvertedUnits.test.ts | 54 +- .../src/test/Editing/KindOfQuantities.test.ts | 11 +- .../src/test/Editing/Mixins.test.ts | 72 +- .../src/test/Editing/Phenomena.test.ts | 13 +- .../src/test/Editing/Properties.test.ts | 229 +- .../test/Editing/PropertyCategories.test.ts | 13 +- .../test/Editing/RelationshipClasses.test.ts | 320 +- .../src/test/Editing/SchemaItems.test.ts | 4 +- .../src/test/Editing/Structs.test.ts | 39 +- .../src/test/Editing/UnitSystems.test.ts | 13 +- .../src/test/Editing/Units.test.ts | 28 +- .../src/test/Editing/mvp.test.ts | 122 +- .../src/test/Merging/ClassMergerOrder.test.ts | 7 +- .../src/test/Merging/ConstantMerger.test.ts | 5 +- .../CustomAttributeClassMerger.test.ts | 4 +- .../Merging/CustomAttributeMerger.test.ts | 4 +- .../src/test/Merging/Edits/RenameEdit.test.ts | 20 +- .../src/test/Merging/Edits/SchemaEdit.test.ts | 2 +- .../test/Merging/EntityClassMerger.test.ts | 16 +- .../test/Merging/EnumerationMerger.test.ts | 12 +- .../test/Merging/KindOfQuantityMerger.test.ts | 2 +- .../src/test/Merging/MixinMerger.test.ts | 5 +- .../src/test/Merging/PhenomenonMerger.test.ts | 2 +- .../Merging/PropertyCategoryMerger.test.ts | 2 +- .../src/test/Merging/PropertyMerger.test.ts | 16 +- .../Merging/RelationshipClassMerger.test.ts | 37 +- .../src/test/Merging/SchemaMerger.test.ts | 6 +- .../Merging/SchemaReferenceMerger.test.ts | 5 +- .../test/Merging/StructClassMerger.test.ts | 5 +- .../src/test/Merging/UnitSystemMerger.test.ts | 2 +- .../src/test/TestUtils/BisTestHelper.ts | 12 +- .../test/TestUtils/DeserializationHelpers.ts | 8 +- .../src/test/TestUtils/DiagnosticHelpers.ts | 273 +- .../Validation/DiagnosticReporters.test.ts | 5 +- .../src/test/Validation/Diagnostics.test.ts | 12 +- .../Validation/ECRules/ClassRules.test.ts | 14 +- .../ECRules/CustomAttributeRules.test.ts | 6 +- .../ECRules/EnumerationRules.test.ts | 4 +- .../Validation/ECRules/MixinRules.test.ts | 2 +- .../Validation/ECRules/PropertyRules.test.ts | 212 +- .../RelationshipConstraintRules.test.ts | 4 +- .../ECRules/RelationshipRules.test.ts | 48 +- .../Validation/ECRules/SchemaRules.test.ts | 18 +- .../src/test/Validation/SchemaChanges.test.ts | 23 +- .../test/Validation/SchemaComparer.test.ts | 821 +- .../test/Validation/SchemaComparison.test.ts | 327 +- .../SchemaComparisonCustomAttributes.test.ts | 11 +- .../Validation/SchemaComparisonMixin.test.ts | 16 +- .../SchemaComparisonRelationshipClass.test.ts | 26 +- .../SchemaComparisonSameNameVersion.test.ts | 29 +- .../test/Validation/SchemaValidater.test.ts | 6 +- .../SchemaValidationVisitor.test.ts | 55 +- .../src/test/Validation/SchemaWalker.test.ts | 4 +- core/ecschema-editing/tsconfig.json | 2 +- core/ecschema-locaters/eslint.config.js | 8 +- .../src/SchemaFileLocater.ts | 35 +- .../src/SchemaJsonFileLocater.ts | 27 +- core/ecschema-locaters/src/SchemaXml.ts | 5 +- .../src/SchemaXmlFileLocater.ts | 28 +- .../src/SchemaXmlStringLocater.ts | 28 +- .../src/StubSchemaXmlFileLocater.ts | 34 +- .../src/test/ConcurrentGetSchemaJson.test.ts | 62 +- .../src/test/ConcurrentGetSchemaXml.test.ts | 21 +- .../src/test/SchemaJsonFileLocator.test.ts | 2 +- .../src/test/SchemaXml.test.ts | 6 +- .../src/test/SchemaXmlFileLocator.test.ts | 22 +- .../src/test/SchemaXmlStringLocater.test.ts | 31 +- .../src/test/StubSchemaXmlFileLocater.test.ts | 30 +- .../test/assets/BadSchemaName.ecschema.json | 2 +- .../assets/BadSchemaVersion.ecschema.json | 2 +- .../assets/SchemaA.02.00.02.ecschema.json | 2 +- .../src/test/assets/SchemaA.ecschema.json | 2 +- .../assets/SchemaB.03.00.03.ecschema.json | 2 +- .../src/test/assets/SchemaB.ecschema.json | 2 +- .../assets/SchemaC.04.00.04.ecschema.json | 2 +- .../src/test/assets/SchemaC.ecschema.json | 2 +- .../assets/SchemaD.05.00.05.ecschema.json | 2 +- .../src/test/assets/SchemaD.ecschema.json | 2 +- core/ecschema-locaters/tsconfig.json | 2 +- core/ecschema-metadata/eslint.config.js | 12 +- core/ecschema-metadata/src/Context.ts | 60 +- core/ecschema-metadata/src/DelayedPromise.ts | 14 +- .../src/Deserialization/AbstractParser.ts | 38 +- .../src/Deserialization/Helper.ts | 76 +- .../src/Deserialization/JsonParser.ts | 727 +- .../src/Deserialization/JsonProps.ts | 21 +- .../src/Deserialization/XmlParser.ts | 617 +- .../Deserialization/XmlSerializationUtils.ts | 42 +- core/ecschema-metadata/src/ECName.ts | 2 +- core/ecschema-metadata/src/ECObjects.ts | 224 +- core/ecschema-metadata/src/Exception.ts | 66 +- core/ecschema-metadata/src/Interfaces.ts | 24 +- core/ecschema-metadata/src/Metadata/Class.ts | 113 +- .../src/Metadata/Constant.ts | 37 +- .../src/Metadata/CustomAttributeClass.ts | 13 +- .../src/Metadata/EntityClass.ts | 84 +- .../src/Metadata/Enumeration.ts | 54 +- core/ecschema-metadata/src/Metadata/Format.ts | 91 +- .../src/Metadata/InvertedUnit.ts | 34 +- .../src/Metadata/KindOfQuantity.ts | 79 +- core/ecschema-metadata/src/Metadata/Mixin.ts | 38 +- .../src/Metadata/OverrideFormat.ts | 79 +- .../src/Metadata/Phenomenon.ts | 4 +- .../src/Metadata/Property.ts | 199 +- .../src/Metadata/PropertyCategory.ts | 4 +- .../src/Metadata/RelationshipClass.ts | 148 +- core/ecschema-metadata/src/Metadata/Schema.ts | 83 +- .../src/Metadata/SchemaItem.ts | 46 +- core/ecschema-metadata/src/Metadata/Unit.ts | 62 +- .../src/SchemaJsonLocater.ts | 9 +- core/ecschema-metadata/src/SchemaKey.ts | 60 +- .../src/UnitConversion/UnitConversion.ts | 4 +- .../src/UnitConversion/UnitTree.ts | 15 +- .../src/UnitProvider/SchemaUnitProvider.ts | 19 +- .../src/ecschema-metadata.ts | 20 +- .../src/test/Context/SchemaLoader.test.ts | 3 +- .../test/Deserialization/JsonParser.test.ts | 356 +- .../test/Deserialization/XmlParser.test.ts | 386 +- .../src/test/Metadata/Class.test.ts | 71 +- .../src/test/Metadata/Constant.test.ts | 56 +- .../Metadata/CustomAttributeClass.test.ts | 5 +- .../src/test/Metadata/DelayedPromise.test.ts | 24 +- .../src/test/Metadata/Deserialization.test.ts | 172 +- .../src/test/Metadata/ECName.test.ts | 22 +- .../src/test/Metadata/EntityClass.test.ts | 94 +- .../src/test/Metadata/Enumeration.test.ts | 45 +- .../src/test/Metadata/Format.test.ts | 366 +- .../src/test/Metadata/InvertedUnit.test.ts | 5 +- .../src/test/Metadata/KindOfQuantity.test.ts | 111 +- .../src/test/Metadata/Mixin.test.ts | 6 +- .../src/test/Metadata/OverrideFormat.test.ts | 2 +- .../src/test/Metadata/Property.test.ts | 25 +- .../test/Metadata/PropertyCategory.test.ts | 2 +- .../test/Metadata/PropertyInheritance.test.ts | 32 +- .../src/test/Metadata/Quantity.test.ts | 12 +- .../src/test/Metadata/Relationship.test.ts | 31 +- .../src/test/Metadata/Schema.test.ts | 139 +- .../src/test/Metadata/SchemaFromJson.test.ts | 17 +- .../src/test/Metadata/SchemaItem.test.ts | 2 +- .../src/test/Metadata/Unit.test.ts | 100 +- .../src/test/ParseUtils.test.ts | 31 +- .../src/test/SchemaKey.test.ts | 7 +- .../test/SchemaPartVisitorDelegate.test.ts | 2 +- .../src/test/TestUtils/BisTestHelper.ts | 6 +- .../test/TestUtils/DeserializationHelpers.ts | 8 +- .../src/test/TestUtils/PerfTestHelper.ts | 5 +- .../src/test/UnitConversion/Convert.test.ts | 6 +- .../test/UnitConversion/CrossSchema.test.ts | 6 +- .../src/test/UnitConversion/Parser.test.ts | 2 +- .../test/UnitConversion/Validation.test.ts | 4 +- .../src/test/UnitProvider/UnitData.ts | 2 +- .../test/UnitProvider/UnitProvider.test.ts | 25 +- .../src/test/Validation/SchemaWalker.test.ts | 2 +- .../src/test/assets/CrossSchemaTests.json | 2 +- .../src/test/assets/ParserTests.json | 2 +- .../src/test/assets/UnitTests.json | 2 +- .../src/utils/SchemaGraph.ts | 15 +- core/ecschema-metadata/tsconfig.json | 2 +- core/ecschema-rpc/common/eslint.config.js | 4 +- .../common/src/ECSchemaRpcInterface.ts | 1 - .../common/src/ECSchemaRpcLocater.ts | 26 +- core/ecschema-rpc/impl/eslint.config.js | 4 +- core/ecschema-rpc/impl/src/ECSchemaRpcImpl.ts | 4 +- core/ecschema-rpc/impl/tsconfig.json | 2 +- core/ecsql/common/eslint.config.js | 2 +- core/ecsql/common/src/ECSqlAst.ts | 271 +- core/ecsql/common/src/test/ECSqlAst.test.ts | 24 +- core/electron/eslint.config.js | 2 +- core/electron/src/__DOC_ONLY__.ts | 2 +- core/electron/src/backend/ElectronHost.ts | 40 +- .../src/common/ElectronIpcTransport.ts | 31 +- core/electron/src/common/ElectronPush.ts | 4 +- .../electron/src/common/ElectronRpcManager.ts | 11 +- core/electron/src/frontend/ElectronApp.ts | 4 +- .../src/test/backend/ElectronHost.test.ts | 10 +- .../src/test/frontend/ElectronApp.test.ts | 2 +- .../src/test/frontend/utils/webpack.config.js | 18 +- core/express-server/eslint.config.js | 4 +- core/express-server/src/ExpressServer.ts | 8 +- .../src/test/ExpressServer.test.ts | 3 +- core/express-server/src/test/Mocks.ts | 5 +- core/extension/codeGen/generate-exports.js | 28 +- core/extension/eslint.config.js | 2 +- core/extension/index.d.ts | 1203 +- core/extension/index.js | 508 +- core/frontend-devtools/eslint.config.js | 4 +- .../public/locales/en/FrontendDevTools.json | 2 +- .../frontend-devtools/src/FrontEndDevTools.ts | 122 +- .../src/effects/Convolution.ts | 108 +- .../src/effects/EffectTools.ts | 12 +- .../src/effects/Explosion.ts | 28 +- .../src/effects/FlipImage.ts | 16 +- .../src/effects/LensDistortion.ts | 18 +- .../src/effects/Saturation.ts | 17 +- core/frontend-devtools/src/effects/Snow.ts | 24 +- .../frontend-devtools/src/effects/Vignette.ts | 16 +- .../src/tools/AnimationIntervalTool.ts | 8 +- .../src/tools/ChangeUnitsTool.ts | 8 +- core/frontend-devtools/src/tools/ClipTools.ts | 50 +- .../src/tools/DisplayStyleTools.ts | 167 +- .../src/tools/EmphasizeElementsTool.ts | 40 +- .../src/tools/FrustumDecoration.ts | 68 +- .../src/tools/InspectElementTool.ts | 50 +- .../src/tools/MapLayerTool.ts | 178 +- .../src/tools/MeasureTileLoadTime.ts | 4 +- .../src/tools/ModelAppearanceTools.ts | 105 +- .../src/tools/PlanProjectionTools.ts | 32 +- .../src/tools/PlanarMaskTools.ts | 260 +- .../src/tools/ProjectExtents.ts | 12 +- .../src/tools/RealityModelTools.ts | 104 +- .../src/tools/RealityTransitionTool.ts | 41 +- .../src/tools/RenderSystemTools.ts | 15 +- .../src/tools/RenderTargetTools.ts | 74 +- .../frontend-devtools/src/tools/SavedViews.ts | 38 +- .../src/tools/ScheduleScriptTools.ts | 27 +- .../src/tools/SelectionTools.ts | 16 +- .../src/tools/SetGpuMemoryLimitTool.ts | 8 +- .../src/tools/SourceAspectIdTools.ts | 15 +- .../src/tools/TileRequestDecoration.ts | 8 +- .../src/tools/TileTreeBoundsDecoration.ts | 8 +- .../src/tools/ToolTipProvider.ts | 8 +- .../src/tools/ViewportTools.ts | 100 +- .../src/tools/parseBoolean.ts | 15 +- .../src/tools/parseToggle.ts | 12 +- core/frontend-devtools/src/ui/ColorInput.ts | 13 +- .../src/widgets/DiagnosticsPanel.ts | 4 +- .../src/widgets/GpuProfiler.ts | 6 +- .../src/widgets/KeyinField.ts | 20 +- .../src/widgets/MemoryTracker.ts | 31 +- .../src/widgets/TileMemoryBreakdown.ts | 6 +- .../src/widgets/ToolSettingsTracker.ts | 2 +- core/frontend-devtools/tsconfig.json | 2 +- core/frontend/eslint.config.js | 18 +- core/frontend/extraction.eslint.config.js | 4 +- core/frontend/src/AccuDraw.ts | 487 +- core/frontend/src/AccuSnap.ts | 143 +- .../frontend/src/ApproximateTerrainHeights.ts | 10 +- core/frontend/src/AuxCoordSys.ts | 102 +- core/frontend/src/BackgroundMapGeometry.ts | 94 +- core/frontend/src/BingLocation.ts | 2 +- core/frontend/src/BriefcaseConnection.ts | 36 +- core/frontend/src/BriefcaseTxns.ts | 22 +- core/frontend/src/CategorySelectorState.ts | 16 +- core/frontend/src/ChangeFlags.ts | 92 +- core/frontend/src/CheckpointConnection.ts | 54 +- core/frontend/src/ContextRealityModelState.ts | 4 +- core/frontend/src/DecorationsCache.ts | 10 +- core/frontend/src/DevTools.ts | 4 +- core/frontend/src/DisplayStyleState.ts | 160 +- core/frontend/src/DrawingViewState.ts | 33 +- core/frontend/src/ElementLocateManager.ts | 88 +- core/frontend/src/EmphasizeElements.ts | 67 +- core/frontend/src/EntityState.ts | 32 +- core/frontend/src/EnvironmentDecorations.ts | 55 +- core/frontend/src/FeatureOverrideProvider.ts | 2 +- core/frontend/src/FrustumAnimator.ts | 25 +- core/frontend/src/FuzzySearch.ts | 9 +- core/frontend/src/GeoServices.ts | 31 +- core/frontend/src/GlobeAnimator.ts | 38 +- core/frontend/src/GraphicalEditingScope.ts | 17 +- core/frontend/src/HitDetail.ts | 193 +- core/frontend/src/IModelApp.ts | 137 +- core/frontend/src/IModelConnection.ts | 296 +- core/frontend/src/IModelRoutingContext.ts | 4 +- core/frontend/src/IpcApp.ts | 40 +- core/frontend/src/LinePlaneIntersect.ts | 9 +- core/frontend/src/LocalhostIpcApp.ts | 14 +- core/frontend/src/Marker.ts | 32 +- core/frontend/src/ModelSelectorState.ts | 16 +- core/frontend/src/ModelState.ts | 121 +- core/frontend/src/NativeApp.ts | 70 +- core/frontend/src/NoRenderApp.ts | 112 +- core/frontend/src/NotificationManager.ts | 100 +- .../src/PerModelCategoryVisibility.ts | 4 +- core/frontend/src/PlanarClipMaskState.ts | 24 +- core/frontend/src/RealityDataSource.ts | 32 +- .../RealityDataSourceCesiumIonAssetImpl.ts | 11 +- .../src/RealityDataSourceContextShareImpl.ts | 17 +- .../src/RealityDataSourceTilesetUrlImpl.ts | 13 +- core/frontend/src/SelectionSet.ts | 42 +- core/frontend/src/SheetViewState.ts | 100 +- core/frontend/src/SpatialClassifiersState.ts | 1 - core/frontend/src/SpatialViewState.ts | 82 +- core/frontend/src/Sprites.ts | 20 +- core/frontend/src/StandardView.ts | 58 +- core/frontend/src/SubCategoriesCache.ts | 37 +- core/frontend/src/TentativePoint.ts | 29 +- core/frontend/src/Tiles.ts | 24 +- core/frontend/src/TxnEntityChanges.ts | 16 +- core/frontend/src/ViewAnimation.ts | 4 +- core/frontend/src/ViewContext.ts | 64 +- core/frontend/src/ViewCreator2d.ts | 42 +- core/frontend/src/ViewCreator3d.ts | 34 +- core/frontend/src/ViewGlobalLocation.ts | 27 +- core/frontend/src/ViewManager.ts | 63 +- core/frontend/src/ViewPose.ts | 10 +- core/frontend/src/ViewState.ts | 393 +- core/frontend/src/ViewingSpace.ts | 119 +- core/frontend/src/Viewport.ts | 536 +- core/frontend/src/common/ImageUtil.ts | 35 +- core/frontend/src/common/ViewRect.ts | 104 +- core/frontend/src/common/WorkerProxy.ts | 21 +- core/frontend/src/common/gltf/GltfParser.ts | 64 +- core/frontend/src/common/gltf/GltfSchema.ts | 40 +- core/frontend/src/common/imdl/CompactEdges.ts | 18 +- core/frontend/src/common/imdl/ImdlModel.ts | 15 +- core/frontend/src/common/imdl/ImdlSchema.ts | 11 +- .../src/common/imdl/ParseImdlDocument.ts | 245 +- .../common/internal/render/AuxChannelTable.ts | 14 +- .../src/common/internal/render/ColorMap.ts | 16 +- .../common/internal/render/DisplayParams.ts | 64 +- .../src/common/internal/render/EdgeParams.ts | 22 +- .../internal/render/GeometryAccumulator.ts | 32 +- .../common/internal/render/GeometryList.ts | 22 +- .../internal/render/GeometryPrimitives.ts | 101 +- .../render/GraphicDescriptionBuilderImpl.ts | 28 +- .../render/GraphicDescriptionContextImpl.ts | 52 +- .../render/InstancedGraphicPropsBuilder.ts | 11 +- .../src/common/internal/render/LineCode.ts | 33 +- .../src/common/internal/render/MeshBuilder.ts | 59 +- .../common/internal/render/MeshBuilderMap.ts | 45 +- .../src/common/internal/render/MeshParams.ts | 4 +- .../common/internal/render/MeshPrimitive.ts | 2 +- .../common/internal/render/MeshPrimitives.ts | 42 +- .../src/common/internal/render/OvrFlags.ts | 1 - .../internal/render/PointStringParams.ts | 4 +- .../src/common/internal/render/Polyface.ts | 12 +- .../common/internal/render/PolylineParams.ts | 14 +- .../src/common/internal/render/Primitives.ts | 18 +- .../src/common/internal/render/Strokes.ts | 4 +- .../common/internal/render/VertexIndices.ts | 6 +- .../src/common/internal/render/VertexKey.ts | 2 +- .../internal/render/VertexTableBuilder.ts | 88 +- .../internal/render/VertexTableSplitter.ts | 114 +- .../src/common/render/BatchOptions.ts | 1 - .../src/common/render/GraphicAssembler.ts | 62 +- .../render/GraphicDescriptionBuilder.ts | 72 +- .../render/GraphicDescriptionContext.ts | 5 +- .../src/common/render/GraphicPrimitive.ts | 14 +- .../src/common/render/MaterialParams.ts | 1 - .../common/render/RenderInstancesParams.ts | 4 +- core/frontend/src/core-frontend.ts | 4 +- core/frontend/src/extension/ExtensionHost.ts | 34 +- .../src/extension/ExtensionRuntime.ts | 186 +- .../providers/ExtensionLoadScript.ts | 2 +- .../providers/LocalExtensionProvider.ts | 8 +- .../providers/RemoteExtensionProvider.ts | 6 +- .../src/internal/render/PrimitiveBuilder.ts | 30 +- .../src/internal/render/RenderGeometry.ts | 3 +- .../render/RenderInstancesParamsImpl.ts | 11 +- .../src/properties/AngleDescription.ts | 12 +- .../FormattedQuantityDescription.ts | 2 +- .../src/properties/LengthDescription.ts | 37 +- .../src/public/assets/MapLayerSources.json | 2 +- .../src/public/locales/en/CoreTools.json | 2 +- .../src/public/locales/en/iModelJs.json | 2 +- .../BaseUnitFormattingSettingsProvider.ts | 45 +- .../quantity-formatting/BasicUnitsProvider.ts | 301 +- .../LocalUnitFormatProvider.ts | 16 +- .../quantity-formatting/QuantityFormatter.ts | 140 +- .../QuantityTypesEditorSpecs.ts | 4 +- .../src/quantity-formatting/UnitsData.ts | 2 +- .../src/render/CreateRenderMaterialArgs.ts | 2 +- core/frontend/src/render/CreateTextureArgs.ts | 2 +- core/frontend/src/render/Decorations.ts | 30 +- core/frontend/src/render/FrameStats.ts | 4 +- core/frontend/src/render/GraphicBranch.ts | 18 +- core/frontend/src/render/GraphicBuilder.ts | 13 +- core/frontend/src/render/GraphicTemplate.ts | 6 +- core/frontend/src/render/MeshArgs.ts | 3 +- core/frontend/src/render/MockRender.ts | 207 +- .../src/render/ParticleCollectionBuilder.ts | 31 +- core/frontend/src/render/Pixel.ts | 2 +- core/frontend/src/render/PolylineArgs.ts | 1 - .../src/render/RealityMeshGraphicParams.ts | 2 +- core/frontend/src/render/RealityMeshParams.ts | 25 +- core/frontend/src/render/RenderGraphic.ts | 20 +- core/frontend/src/render/RenderMemory.ts | 168 +- core/frontend/src/render/RenderPlan.ts | 23 +- .../src/render/RenderPlanarClassifier.ts | 7 +- core/frontend/src/render/RenderSystem.ts | 260 +- core/frontend/src/render/RenderTarget.ts | 86 +- core/frontend/src/render/Scene.ts | 2 +- .../src/render/UpsampleRealityMeshParams.ts | 29 +- core/frontend/src/render/VisibleFeature.ts | 9 +- .../src/render/webgl/AtmosphereUniforms.ts | 6 +- .../src/render/webgl/AttributeBuffers.ts | 54 +- .../src/render/webgl/BackgroundMapDrape.ts | 66 +- core/frontend/src/render/webgl/BatchState.ts | 24 +- .../src/render/webgl/BatchUniforms.ts | 12 +- core/frontend/src/render/webgl/BranchStack.ts | 12 +- core/frontend/src/render/webgl/BranchState.ts | 117 +- .../src/render/webgl/BranchUniforms.ts | 21 +- .../src/render/webgl/CachedGeometry.ts | 457 +- core/frontend/src/render/webgl/ClipStack.ts | 38 +- core/frontend/src/render/webgl/ClipVolume.ts | 4 +- .../src/render/webgl/ClippingProgram.ts | 2 +- core/frontend/src/render/webgl/ColorInfo.ts | 22 +- .../src/render/webgl/ContourUniforms.ts | 27 +- core/frontend/src/render/webgl/Contours.ts | 20 +- core/frontend/src/render/webgl/Diagnostics.ts | 4 +- core/frontend/src/render/webgl/DrawCommand.ts | 88 +- core/frontend/src/render/webgl/EDL.ts | 99 +- .../frontend/src/render/webgl/EdgeGeometry.ts | 124 +- .../frontend/src/render/webgl/EdgeSettings.ts | 6 +- .../src/render/webgl/FeatureOverrides.ts | 135 +- core/frontend/src/render/webgl/FloatRGBA.ts | 32 +- core/frontend/src/render/webgl/FrameBuffer.ts | 91 +- .../src/render/webgl/FrustumUniforms.ts | 82 +- core/frontend/src/render/webgl/GL.ts | 2 +- core/frontend/src/render/webgl/GLTimer.ts | 26 +- core/frontend/src/render/webgl/Graphic.ts | 58 +- .../src/render/webgl/HiliteUniforms.ts | 14 +- .../src/render/webgl/IndexedEdgeGeometry.ts | 50 +- .../src/render/webgl/InstancedGeometry.ts | 198 +- core/frontend/src/render/webgl/Layer.ts | 2 +- .../src/render/webgl/LayerCommands.ts | 31 +- .../src/render/webgl/LightingUniforms.ts | 2 +- core/frontend/src/render/webgl/LineCode.ts | 529 +- core/frontend/src/render/webgl/Material.ts | 16 +- core/frontend/src/render/webgl/Matrix.ts | 447 +- core/frontend/src/render/webgl/Mesh.ts | 36 +- core/frontend/src/render/webgl/MeshData.ts | 18 +- .../frontend/src/render/webgl/MeshGeometry.ts | 62 +- .../src/render/webgl/PerformanceMetrics.ts | 8 +- .../src/render/webgl/PlanarClassifier.ts | 186 +- core/frontend/src/render/webgl/PlanarGrid.ts | 30 +- .../render/webgl/PlanarTextureProjection.ts | 56 +- core/frontend/src/render/webgl/PointCloud.ts | 58 +- core/frontend/src/render/webgl/PointString.ts | 44 +- core/frontend/src/render/webgl/Polyline.ts | 64 +- core/frontend/src/render/webgl/Primitive.ts | 58 +- core/frontend/src/render/webgl/RealityMesh.ts | 158 +- .../src/render/webgl/RealityModelUniforms.ts | 15 +- .../frontend/src/render/webgl/RenderBuffer.ts | 62 +- .../src/render/webgl/RenderCommands.ts | 73 +- core/frontend/src/render/webgl/RenderFlags.ts | 83 +- core/frontend/src/render/webgl/RenderState.ts | 7 +- .../src/render/webgl/SceneCompositor.ts | 260 +- .../src/render/webgl/ScreenSpaceEffect.ts | 52 +- .../src/render/webgl/ShaderBuilder.ts | 159 +- .../src/render/webgl/ShaderProgram.ts | 88 +- .../src/render/webgl/ShadowUniforms.ts | 4 +- .../src/render/webgl/SolarShadowMap.ts | 153 +- .../src/render/webgl/StyleUniforms.ts | 2 +- .../src/render/webgl/SurfaceGeometry.ts | 70 +- core/frontend/src/render/webgl/System.ts | 255 +- core/frontend/src/render/webgl/Target.ts | 252 +- .../src/render/webgl/TargetGraphics.ts | 12 +- .../src/render/webgl/TargetUniforms.ts | 8 +- core/frontend/src/render/webgl/Technique.ts | 235 +- .../src/render/webgl/TechniqueFlags.ts | 75 +- core/frontend/src/render/webgl/Texture.ts | 286 +- .../frontend/src/render/webgl/TextureDrape.ts | 16 +- .../src/render/webgl/ThematicSensors.ts | 48 +- .../src/render/webgl/ThematicUniforms.ts | 26 +- .../src/render/webgl/UniformHandle.ts | 6 +- core/frontend/src/render/webgl/VertexLUT.ts | 42 +- .../src/render/webgl/ViewRectUniforms.ts | 37 +- .../src/render/webgl/VisibleTileFeatures.ts | 15 +- .../src/render/webgl/glsl/AmbientOcclusion.ts | 12 +- .../src/render/webgl/glsl/Animation.ts | 11 +- core/frontend/src/render/webgl/glsl/Blur.ts | 3 +- core/frontend/src/render/webgl/glsl/Common.ts | 2 +- .../src/render/webgl/glsl/Contours.ts | 4 +- .../src/render/webgl/glsl/CopyColor.ts | 2 +- core/frontend/src/render/webgl/glsl/Edge.ts | 9 +- .../src/render/webgl/glsl/FeatureSymbology.ts | 15 +- .../src/render/webgl/glsl/Instancing.ts | 39 +- .../src/render/webgl/glsl/Monochrome.ts | 4 +- .../render/webgl/glsl/PlanarClassification.ts | 36 +- .../src/render/webgl/glsl/PlanarGrid.ts | 10 +- .../src/render/webgl/glsl/PointCloud.ts | 6 +- .../src/render/webgl/glsl/Polyline.ts | 13 +- .../src/render/webgl/glsl/RealityMesh.ts | 18 +- .../render/webgl/glsl/ScreenSpaceEffect.ts | 2 +- .../src/render/webgl/glsl/SkySphere.ts | 16 +- .../frontend/src/render/webgl/glsl/Surface.ts | 64 +- .../src/render/webgl/glsl/Thematic.ts | 7 +- core/frontend/src/render/webgl/glsl/Vertex.ts | 4 +- core/frontend/src/request/Request.ts | 1 - core/frontend/src/request/utils.ts | 17 +- core/frontend/src/test/AccuSnap.test.ts | 65 +- .../src/test/BackgroundMapGeometry.test.ts | 31 +- core/frontend/src/test/BearingQuantityType.ts | 49 +- .../frontend/src/test/BlankConnection.test.ts | 2 +- .../src/test/ContextRealityModelState.test.ts | 17 +- .../src/test/CoordinateConverter.test.ts | 70 +- .../test/DeferredMarkerHtmlRemoval.test.ts | 10 +- .../src/test/DisplayStyleState.test.ts | 8 +- core/frontend/src/test/ExpectColors.ts | 4 +- core/frontend/src/test/ExtensionAdmin.test.ts | 18 +- .../test/FeatureSymbologyOverrides.test.ts | 4 +- core/frontend/src/test/FlashSettings.test.ts | 42 +- core/frontend/src/test/GeoServices.test.ts | 8 +- core/frontend/src/test/IModelApp.test.ts | 38 +- .../src/test/IModelConnection.test.ts | 4 +- core/frontend/src/test/LookAt.test.ts | 23 +- .../src/test/QuantityFormatter.test.ts | 17 +- .../src/test/RealityDataSource.test.ts | 51 +- .../test/RealityDataSourceTilesetUrl.test.ts | 8 +- core/frontend/src/test/Request.test.ts | 4 +- .../src/test/SpatialViewState.test.ts | 23 +- core/frontend/src/test/TestDecorators.ts | 11 +- core/frontend/src/test/ToolRegistry.test.ts | 19 +- .../src/test/TxnEntityChanges.test.ts | 15 +- core/frontend/src/test/ViewManager.test.ts | 4 +- core/frontend/src/test/ViewRect.test.ts | 4 +- core/frontend/src/test/Viewport.test.ts | 122 +- core/frontend/src/test/ViewportSync.test.ts | 9 +- .../src/test/createBlankConnection.ts | 8 +- core/frontend/src/test/openBlankViewport.ts | 88 +- .../src/test/public/locales/en/TestApp.json | 2 +- .../render/EnvironmentDecorations.test.ts | 176 +- .../src/test/render/FrameStats.test.ts | 6 +- .../src/test/render/GraphicBuilder.test.ts | 57 +- .../test/render/GraphicDescription.test.ts | 263 +- .../src/test/render/GraphicPrimitive.test.ts | 99 +- .../src/test/render/GraphicTemplate.test.ts | 26 +- .../InstancedGraphicPropsBuilder.test.ts | 27 +- .../src/test/render/MockRender.test.ts | 14 +- .../src/test/render/RealityMeshParams.test.ts | 6 +- .../src/test/render/RenderGraphic.test.ts | 4 +- .../src/test/render/RenderInstances.test.ts | 22 +- .../src/test/render/VisibleFeature.test.ts | 4 +- .../render/primitives/AuxChannelTable.test.ts | 6 +- .../render/primitives/DisplayParams.test.ts | 9 +- .../test/render/primitives/Geometry.test.ts | 6 +- .../primitives/GeometryAccumulator.test.ts | 20 +- .../render/primitives/MeshBuilder.test.ts | 95 +- .../render/primitives/MeshBuilderMap.test.ts | 26 +- .../render/primitives/MeshPrimitives.test.ts | 8 +- .../primitives/PolylineTesselator.test.ts | 308 +- .../primitives/PrimitiveBuilder.test.ts | 4 +- .../test/render/primitives/Primitives.test.ts | 35 +- .../test/render/primitives/Strokes.test.ts | 2 +- .../test/render/primitives/VertexKey.test.ts | 4 +- .../render/primitives/VertexTable.test.ts | 178 +- .../primitives/VertexTableSplitter.test.ts | 257 +- .../test/render/webgl/BranchUniforms.test.ts | 110 +- .../test/render/webgl/BufferHandle.test.ts | 4 +- .../src/test/render/webgl/ClipStack.test.ts | 45 +- .../src/test/render/webgl/ClipVolume.test.ts | 10 +- .../src/test/render/webgl/ColorMap.test.ts | 2 +- .../src/test/render/webgl/Decorations.test.ts | 14 +- .../render/webgl/EarlyZBugWorkaround.test.ts | 6 +- .../test/render/webgl/EdgeSettings.test.ts | 24 +- .../render/webgl/FeatureOverrides.test.ts | 34 +- .../src/test/render/webgl/FloatRGBA.test.ts | 2 +- .../src/test/render/webgl/FrameBuffer.test.ts | 2 +- .../test/render/webgl/FrustumUniforms.test.ts | 28 +- .../src/test/render/webgl/Graphic.test.ts | 10 +- .../test/render/webgl/IndexedEdges.test.ts | 234 +- .../src/test/render/webgl/LineCode.test.ts | 2 +- .../src/test/render/webgl/Material.test.ts | 2 +- .../src/test/render/webgl/Matrix.test.ts | 33 +- .../render/webgl/PickableDecorations.test.ts | 4 +- .../render/webgl/PickableGraphics.test.ts | 14 +- .../webgl/RenderGraphicTileTree.test.ts | 6 +- .../test/render/webgl/RenderMemory.test.ts | 31 +- .../src/test/render/webgl/RenderState.test.ts | 28 +- .../webgl/ScreenSpaceEffectBuilder.test.ts | 4 +- .../test/render/webgl/ShaderBuilder.test.ts | 6 +- .../src/test/render/webgl/SkyRender.test.ts | 170 +- .../render/webgl/SurfaceTransparency.test.ts | 39 +- .../src/test/render/webgl/SyncToken.test.ts | 2 +- .../src/test/render/webgl/System.test.ts | 169 +- .../src/test/render/webgl/Technique.test.ts | 14 +- .../src/test/render/webgl/Texture.test.ts | 263 +- .../frontend/src/test/tile/GltfReader.test.ts | 219 +- .../frontend/src/test/tile/ImdlParser.test.ts | 1978 +- .../src/test/tile/LRUTileList.test.ts | 28 +- core/frontend/src/test/tile/TileAdmin.test.ts | 54 +- .../src/test/tile/TileRequestChannel.test.ts | 55 +- .../src/test/tile/TileRequestChannels.test.ts | 6 +- .../src/test/tile/TileUserIdSet.test.ts | 14 +- .../test/tile/TiledGraphicsProvider.test.ts | 59 +- core/frontend/src/test/tile/Tiles.test.ts | 38 +- .../tile/map/ArcGISImageryProvider.test.ts | 42 +- .../test/tile/map/ArcGISMapLayerDataset.ts | 184 +- .../map/ArcGISMapLayerImageryProvider.test.ts | 81 +- .../src/test/tile/map/ArcGISTileMap.test.ts | 784 +- .../src/test/tile/map/ArcGisUtilities.test.ts | 98 +- .../tile/map/FeatureGraphicsRenderer.test.ts | 170 +- .../src/test/tile/map/ImageryTileTree.test.ts | 36 +- .../src/test/tile/map/MapLayerFormat.test.ts | 11 +- .../tile/map/MapLayerImageryFormats.test.ts | 25 +- .../src/test/tile/map/MapLayerSources.test.ts | 13 +- .../test/tile/map/MapLayerTestUtilities.ts | 24 +- .../tile/map/TileUrlImageryProvider.test.ts | 18 +- core/frontend/src/test/tile/map/Wgs84Lods.ts | 90 +- .../src/test/tile/map/WmsCapabilities.test.ts | 14 +- .../map/WmsMapLayerImageryProvider.test.ts | 160 +- .../test/tile/map/WmtsCapabilities.test.ts | 31 +- .../map/WmtsMapLayerImageryProvider.test.ts | 46 +- .../frontend/src/test/utils/webpack.config.js | 26 +- core/frontend/src/test/worker/test-worker.ts | 15 +- .../src/test/worker/webpack.config.js | 7 +- core/frontend/src/tile/B3dmReader.ts | 88 +- core/frontend/src/tile/BatchedTileIdMap.ts | 2 +- core/frontend/src/tile/CesiumAssetProvider.ts | 2 +- core/frontend/src/tile/ClassifierTileTree.ts | 54 +- .../frontend/src/tile/ContextShareProvider.ts | 30 +- core/frontend/src/tile/DynamicIModelTile.ts | 60 +- core/frontend/src/tile/FetchCloudStorage.ts | 10 +- core/frontend/src/tile/GltfReader.ts | 478 +- core/frontend/src/tile/GraphicsCollector.ts | 18 +- core/frontend/src/tile/I3dmReader.ts | 75 +- core/frontend/src/tile/IModelTile.ts | 48 +- .../src/tile/IModelTileRequestChannels.ts | 2 +- core/frontend/src/tile/IModelTileTree.ts | 84 +- core/frontend/src/tile/ImdlDecoder.ts | 4 +- core/frontend/src/tile/ImdlGraphicsCreator.ts | 64 +- core/frontend/src/tile/ImdlParser.ts | 13 +- core/frontend/src/tile/ImdlReader.ts | 28 +- core/frontend/src/tile/LRUTileList.ts | 5 +- core/frontend/src/tile/MeshoptCompression.ts | 2 +- .../frontend/src/tile/OPCFormatInterpreter.ts | 31 +- core/frontend/src/tile/OrbitGtTileTree.ts | 177 +- core/frontend/src/tile/PntsReader.ts | 13 +- core/frontend/src/tile/PrimaryTileTree.ts | 114 +- .../frontend/src/tile/RealityModelTileTree.ts | 219 +- core/frontend/src/tile/RealityTile.ts | 156 +- core/frontend/src/tile/RealityTileDrawArgs.ts | 20 +- core/frontend/src/tile/RealityTileLoader.ts | 134 +- core/frontend/src/tile/RealityTileTree.ts | 122 +- .../src/tile/RenderGraphicTileTree.ts | 36 +- .../src/tile/ThreeDTileFormatInterpreter.ts | 37 +- core/frontend/src/tile/Tile.ts | 108 +- core/frontend/src/tile/TileAdmin.ts | 104 +- core/frontend/src/tile/TileDrawArgs.ts | 48 +- .../src/tile/TileGeometryCollector.ts | 4 +- core/frontend/src/tile/TileRequest.ts | 14 +- core/frontend/src/tile/TileRequestChannel.ts | 6 +- core/frontend/src/tile/TileRequestChannels.ts | 6 +- core/frontend/src/tile/TileStorage.ts | 17 +- core/frontend/src/tile/TileTree.ts | 35 +- core/frontend/src/tile/TileTreeParams.ts | 2 +- core/frontend/src/tile/TileTreeReference.ts | 49 +- core/frontend/src/tile/TileUser.ts | 2 +- core/frontend/src/tile/TileUserSet.ts | 12 +- .../src/tile/TiledGraphicsProvider.ts | 2 +- core/frontend/src/tile/ViewFlagOverrides.ts | 4 +- core/frontend/src/tile/map/ArcGISTileMap.ts | 90 +- core/frontend/src/tile/map/ArcGisUtilities.ts | 153 +- core/frontend/src/tile/map/BingElevation.ts | 23 +- .../src/tile/map/CesiumTerrainProvider.ts | 66 +- .../src/tile/map/EllipsoidTerrainProvider.ts | 17 +- .../ImageryProviders/ArcGISImageryProvider.ts | 116 +- .../ArcGISMapLayerImageryProvider.ts | 134 +- .../ArcGisGeometryReaderJSON.ts | 1 - .../AzureMapsLayerImageryProvider.ts | 11 +- .../ImageryProviders/BingImageryProvider.ts | 38 +- .../map/ImageryProviders/CoordinatesUtils.ts | 8 +- .../FeatureGeometryRenderer.ts | 16 +- .../FeatureGraphicsRenderer.ts | 23 +- .../FeatureSymbologyRenderer.ts | 1 - .../MapBoxLayerImageryProvider.ts | 22 +- .../TileUrlImageryProvider.ts | 10 +- .../tile/map/ImageryProviders/WebMercator.ts | 5 +- .../WmsMapLayerImageryProvider.ts | 65 +- .../WmtsMapLayerImageryProvider.ts | 41 +- core/frontend/src/tile/map/ImageryTileTree.ts | 168 +- .../src/tile/map/MapCartoRectangle.ts | 42 +- core/frontend/src/tile/map/MapFeatureInfo.ts | 2 +- .../src/tile/map/MapLayerAuthentication.ts | 1 - .../src/tile/map/MapLayerFormatRegistry.ts | 72 +- .../src/tile/map/MapLayerImageryFormats.ts | 96 +- .../src/tile/map/MapLayerImageryProvider.ts | 129 +- core/frontend/src/tile/map/MapLayerSources.ts | 94 +- .../src/tile/map/MapLayerTileTreeReference.ts | 39 +- core/frontend/src/tile/map/MapTile.ts | 267 +- .../src/tile/map/MapTileAvailability.ts | 12 +- core/frontend/src/tile/map/MapTileLoader.ts | 63 +- core/frontend/src/tile/map/MapTileTree.ts | 380 +- .../src/tile/map/MapTiledGraphicsProvider.ts | 62 +- core/frontend/src/tile/map/MapTilingScheme.ts | 13 +- core/frontend/src/tile/map/QuadId.ts | 4 +- .../src/tile/map/TerrainMeshProvider.ts | 16 +- core/frontend/src/tile/map/UrlUtils.ts | 14 +- core/frontend/src/tile/map/WmsCapabilities.ts | 57 +- core/frontend/src/tile/map/WmsUtilities.ts | 13 +- .../frontend/src/tile/map/WmtsCapabilities.ts | 43 +- .../src/tile/map/wms-capabilities.d.ts | 2 +- core/frontend/src/tools/AccuDrawTool.ts | 113 +- core/frontend/src/tools/ClipViewTool.ts | 546 +- core/frontend/src/tools/EditManipulator.ts | 56 +- core/frontend/src/tools/ElementSetTool.ts | 204 +- core/frontend/src/tools/EventController.ts | 13 +- core/frontend/src/tools/IdleTool.ts | 10 +- core/frontend/src/tools/MeasureTool.ts | 474 +- core/frontend/src/tools/PrimitiveTool.ts | 38 +- core/frontend/src/tools/SelectTool.ts | 259 +- core/frontend/src/tools/Tool.ts | 321 +- core/frontend/src/tools/ToolAdmin.ts | 285 +- core/frontend/src/tools/ToolAssistance.ts | 67 +- core/frontend/src/tools/ViewTool.ts | 803 +- .../src/workers/ImdlParser/webpack.config.js | 6 +- core/geometry/eslint.config.js | 6 +- core/geometry/src/Geometry.ts | 174 +- core/geometry/src/bspline/AkimaCurve3d.ts | 61 +- core/geometry/src/bspline/BSpline1dNd.ts | 46 +- core/geometry/src/bspline/BSplineCurve.ts | 167 +- core/geometry/src/bspline/BSplineCurve3dH.ts | 94 +- core/geometry/src/bspline/BSplineCurveOps.ts | 138 +- core/geometry/src/bspline/BSplineSurface.ts | 209 +- core/geometry/src/bspline/Bezier1dNd.ts | 26 +- core/geometry/src/bspline/BezierCurve3d.ts | 18 +- core/geometry/src/bspline/BezierCurve3dH.ts | 97 +- core/geometry/src/bspline/BezierCurveBase.ts | 54 +- .../src/bspline/InterpolationCurve3d.ts | 112 +- core/geometry/src/bspline/KnotVector.ts | 69 +- .../src/bspline/SurfaceLocationDetail.ts | 1 - .../src/clipping/AlternatingConvexClipTree.ts | 88 +- core/geometry/src/clipping/BooleanClipNode.ts | 37 +- core/geometry/src/clipping/ClipPlane.ts | 76 +- core/geometry/src/clipping/ClipPrimitive.ts | 60 +- core/geometry/src/clipping/ClipUtils.ts | 170 +- core/geometry/src/clipping/ClipVector.ts | 35 +- .../src/clipping/ConvexClipPlaneSet.ts | 103 +- .../clipping/UnionOfConvexClipPlaneSets.ts | 31 +- .../LineStringOffsetClipperContext.ts | 46 +- core/geometry/src/core-geometry.ts | 1 - core/geometry/src/curve/Arc3d.ts | 181 +- .../src/curve/ConstructCurveBetweenCurves.ts | 7 +- .../src/curve/CurveChainWithDistanceIndex.ts | 103 +- core/geometry/src/curve/CurveCollection.ts | 21 +- core/geometry/src/curve/CurveCurve.ts | 12 +- core/geometry/src/curve/CurveExtendMode.ts | 4 +- core/geometry/src/curve/CurveFactory.ts | 224 +- .../geometry/src/curve/CurveLocationDetail.ts | 49 +- core/geometry/src/curve/CurveOps.ts | 25 +- core/geometry/src/curve/CurvePrimitive.ts | 98 +- core/geometry/src/curve/CurveProcessor.ts | 18 +- core/geometry/src/curve/CurveTypes.ts | 2 +- .../geometry/src/curve/CurveWireMomentsXYZ.ts | 22 +- core/geometry/src/curve/LineSegment3d.ts | 44 +- core/geometry/src/curve/LineString3d.ts | 157 +- core/geometry/src/curve/Loop.ts | 5 +- core/geometry/src/curve/OffsetOptions.ts | 14 +- core/geometry/src/curve/ParityRegion.ts | 2 +- core/geometry/src/curve/ProxyCurve.ts | 9 +- .../ConsolidateAdjacentPrimitivesContext.ts | 16 +- .../src/curve/Query/CurveSplitContext.ts | 9 +- .../src/curve/Query/CylindricalRange.ts | 4 +- core/geometry/src/curve/Query/InOutTests.ts | 11 +- .../src/curve/Query/PlanarSubdivision.ts | 55 +- .../src/curve/Query/StrokeCountChain.ts | 47 +- .../src/curve/Query/StrokeCountMap.ts | 20 +- core/geometry/src/curve/RegionMomentsXY.ts | 16 +- core/geometry/src/curve/RegionOps.ts | 84 +- .../curve/RegionOpsClassificationSweeps.ts | 62 +- core/geometry/src/curve/StrokeOptions.ts | 19 +- core/geometry/src/curve/UnionRegion.ts | 2 +- .../AppendPlaneIntersectionStrokeHandler.ts | 8 +- .../internalContexts/ChainCollectorContext.ts | 9 +- .../internalContexts/CloneCurvesContext.ts | 6 +- .../CloneWithExpandedLineStrings.ts | 4 +- .../ClosestPointStrokeHandler.ts | 9 +- .../CurveCurveCloseApproachXY.ts | 167 +- .../internalContexts/CurveCurveIntersectXY.ts | 508 +- .../CurveCurveIntersectXYZ.ts | 298 +- .../internalContexts/CurveLengthContext.ts | 9 +- .../internalContexts/CurveOffsetXYHandler.ts | 26 +- .../EllipticalArcApproximationContext.ts | 103 +- .../internalContexts/MultiChainCollector.ts | 4 +- .../PlaneAltitudeRangeContext.ts | 29 +- .../internalContexts/PolygonOffsetContext.ts | 59 +- .../TransformInPlaceContext.ts | 7 +- .../spiral/AustralianRailCorpXYEvaluator.ts | 34 +- .../src/curve/spiral/ClothoidSeries.ts | 44 +- .../src/curve/spiral/CubicEvaluator.ts | 30 +- .../src/curve/spiral/CzechSpiralEvaluator.ts | 49 +- .../spiral/DirectHalfCosineSpiralEvaluator.ts | 28 +- .../src/curve/spiral/DirectSpiral3d.ts | 177 +- .../src/curve/spiral/IntegratedSpiral3d.ts | 113 +- .../spiral/MXCubicAlongArcSpiralEvaluator.ts | 4 +- .../src/curve/spiral/NormalizedTransition.ts | 46 +- .../spiral/PolishCubicSpiralEvaluator.ts | 12 +- .../spiral/TransitionConditionalProperties.ts | 27 +- .../src/curve/spiral/TransitionSpiral3d.ts | 58 +- .../src/curve/spiral/XYCurveEvaluator.ts | 48 +- core/geometry/src/geometry3d/Angle.ts | 36 +- core/geometry/src/geometry3d/AngleSweep.ts | 19 +- .../src/geometry3d/BarycentricTriangle.ts | 69 +- core/geometry/src/geometry3d/BilinearPatch.ts | 34 +- .../src/geometry3d/CoincidentGeometryOps.ts | 90 +- core/geometry/src/geometry3d/Ellipsoid.ts | 286 +- core/geometry/src/geometry3d/FrameBuilder.ts | 9 +- .../src/geometry3d/FrustumAnimation.ts | 26 +- .../src/geometry3d/GeometryHandler.ts | 27 +- .../src/geometry3d/GrowableBlockedArray.ts | 41 +- .../src/geometry3d/GrowableFloat64Array.ts | 9 +- .../src/geometry3d/GrowableXYArray.ts | 85 +- .../src/geometry3d/GrowableXYZArray.ts | 151 +- .../geometry3d/IndexedCollectionInterval.ts | 1 - .../src/geometry3d/IndexedXYCollection.ts | 4 +- .../src/geometry3d/IndexedXYZCollection.ts | 41 +- .../geometry3d/LongitudeLatitudeAltitude.ts | 59 +- core/geometry/src/geometry3d/Matrix3d.ts | 810 +- .../src/geometry3d/OrderedRotationAngles.ts | 125 +- core/geometry/src/geometry3d/Plane3d.ts | 7 +- .../Plane3dByOriginAndUnitNormal.ts | 53 +- .../geometry3d/Plane3dByOriginAndVectors.ts | 156 +- .../src/geometry3d/Point2dArrayCarrier.ts | 2 +- .../src/geometry3d/Point2dVector2d.ts | 37 +- .../src/geometry3d/Point3dArrayCarrier.ts | 22 +- .../src/geometry3d/Point3dVector3d.ts | 209 +- core/geometry/src/geometry3d/PointHelpers.ts | 104 +- .../geometry/src/geometry3d/PointStreaming.ts | 10 +- core/geometry/src/geometry3d/PolygonOps.ts | 285 +- .../PolylineCompressionByEdgeOffset.ts | 1 - core/geometry/src/geometry3d/PolylineOps.ts | 40 +- core/geometry/src/geometry3d/Range.ts | 265 +- core/geometry/src/geometry3d/Ray2d.ts | 8 +- core/geometry/src/geometry3d/Ray3d.ts | 70 +- .../src/geometry3d/ReusableObjectCache.ts | 13 +- core/geometry/src/geometry3d/Segment1d.ts | 46 +- .../src/geometry3d/SortablePolygon.ts | 16 +- core/geometry/src/geometry3d/Transform.ts | 71 +- core/geometry/src/geometry3d/UVSurfaceOps.ts | 12 +- core/geometry/src/geometry3d/XYZProps.ts | 10 +- .../src/geometry3d/YawPitchRollAngles.ts | 56 +- core/geometry/src/geometry4d/Map4d.ts | 12 +- core/geometry/src/geometry4d/Matrix4d.ts | 265 +- core/geometry/src/geometry4d/MomentData.ts | 123 +- .../geometry4d/PlaneByOriginAndVectors4d.ts | 61 +- core/geometry/src/geometry4d/Point4d.ts | 258 +- core/geometry/src/numerics/BandedSystem.ts | 19 +- .../src/numerics/BezierPolynomials.ts | 70 +- .../geometry/src/numerics/ClusterableArray.ts | 30 +- core/geometry/src/numerics/Complex.ts | 79 +- core/geometry/src/numerics/ConvexPolygon2d.ts | 2 +- core/geometry/src/numerics/Newton.ts | 16 +- .../src/numerics/PascalCoefficients.ts | 6 +- core/geometry/src/numerics/PolarData.ts | 25 +- core/geometry/src/numerics/Polynomials.ts | 385 +- core/geometry/src/numerics/Quadrature.ts | 48 +- core/geometry/src/numerics/Range1dArray.ts | 23 +- .../src/numerics/TriDiagonalSystem.ts | 28 +- core/geometry/src/numerics/UnionFind.ts | 4 +- core/geometry/src/numerics/UsageSums.ts | 20 +- core/geometry/src/polyface/AuxData.ts | 14 +- core/geometry/src/polyface/BoxTopology.ts | 24 +- core/geometry/src/polyface/FacetFaceData.ts | 32 +- .../src/polyface/FacetLocationDetail.ts | 71 +- .../geometry/src/polyface/FacetOrientation.ts | 5 +- .../GreedyTriangulationBetweenLineStrings.ts | 156 +- .../src/polyface/IndexedEdgeMatcher.ts | 46 +- .../src/polyface/IndexedPolyfaceVisitor.ts | 16 +- core/geometry/src/polyface/PolyfaceBuilder.ts | 314 +- core/geometry/src/polyface/PolyfaceClip.ts | 132 +- core/geometry/src/polyface/PolyfaceData.ts | 47 +- core/geometry/src/polyface/PolyfaceQuery.ts | 327 +- .../RangeTree/LineString3dRangeTreeContext.ts | 27 +- .../polyface/RangeTree/MinimumValueTester.ts | 2 +- .../RangeTree/Point3dArrayRangeTreeContext.ts | 26 +- .../RangeTree/PolyfaceRangeTreeContext.ts | 31 +- .../src/polyface/RangeTree/RangeTreeNode.ts | 65 +- .../RangeTree/RangeTreeSearchHandlers.ts | 25 +- .../src/polyface/TaggedNumericData.ts | 67 +- .../src/polyface/TriangleCandidate.ts | 15 +- .../multiclip/BuildAverageNormalsContext.ts | 20 +- .../multiclip/LinearSearchRange2dArray.ts | 6 +- .../polyface/multiclip/OffsetMeshContext.ts | 333 +- .../src/polyface/multiclip/RangeSearch.ts | 27 +- .../SweepLineStringToFacetContext.ts | 43 +- .../src/polyface/multiclip/XYPointBuckets.ts | 15 +- .../src/serialization/BGFBAccessors.ts | 566 +- core/geometry/src/serialization/BGFBReader.ts | 304 +- core/geometry/src/serialization/BGFBWriter.ts | 420 +- .../BentleyGeometryFlatBuffer.ts | 2 +- .../geometry/src/serialization/DeepCompare.ts | 13 +- .../src/serialization/GeometrySamples.ts | 722 +- .../src/serialization/IModelJsonSchema.ts | 250 +- .../src/serialization/SerializationHelpers.ts | 114 +- core/geometry/src/solid/Box.ts | 81 +- core/geometry/src/solid/Cone.ts | 67 +- core/geometry/src/solid/LinearSweep.ts | 18 +- core/geometry/src/solid/RotationalSweep.ts | 40 +- core/geometry/src/solid/RuledSweep.ts | 24 +- core/geometry/src/solid/SolidPrimitive.ts | 13 +- core/geometry/src/solid/Sphere.ts | 71 +- core/geometry/src/solid/SweepContour.ts | 15 +- core/geometry/src/solid/TorusPipe.ts | 64 +- core/geometry/src/test/Checker.ts | 32 +- core/geometry/src/test/Geometry.test.ts | 2 +- core/geometry/src/test/GeometryCoreTestIO.ts | 45 +- core/geometry/src/test/SimpleFactory.ts | 62 +- .../src/test/bspline/AkimaCurve3d.test.ts | 6 +- .../src/test/bspline/BSplineSurface.test.ts | 281 +- .../src/test/bspline/BezierCurve.test.ts | 27 +- .../src/test/bspline/BsplineCurve.test.ts | 244 +- .../test/bspline/ConvexClipPlaneSet.test.ts | 48 +- .../src/test/bspline/ConvexPolygon2d.test.ts | 11 +- .../test/bspline/InterpolationCurve3d.test.ts | 184 +- .../AlternatingConvexClipTree.test.ts | 75 +- .../src/test/clipping/ClipNode.test.ts | 117 +- .../src/test/clipping/ClipPlanes.test.ts | 315 +- .../src/test/clipping/ClipPrimitives.test.ts | 163 +- .../src/test/clipping/ClipUtilities.test.ts | 241 +- .../src/test/clipping/ClipVector.test.ts | 307 +- .../src/test/clipping/CutFill.test.ts | 34 +- .../src/test/clipping/PolyfaceClip.test.ts | 1685 +- .../test/clipping/XYOffsetAsClipper.test.ts | 238 +- core/geometry/src/test/curve/Arc3d.test.ts | 338 +- .../curve/AustralianRailCorpSpiral.test.ts | 1 - .../src/test/curve/BuildingCodeOffsetOps.ts | 21 +- .../curve/CoincidentGeometryQuery.test.ts | 6 +- core/geometry/src/test/curve/Curve.test.ts | 301 +- .../curve/CurveChainWithDistanceIndex.test.ts | 69 +- .../src/test/curve/CurveCollection.test.ts | 23 +- .../curve/CurveCurveCloseApproachXY.test.ts | 405 +- .../test/curve/CurveCurveIntersectXY.test.ts | 578 +- .../test/curve/CurveCurveIntersectXYZ.test.ts | 621 +- .../src/test/curve/CurveExtendMode.test.ts | 11 +- .../src/test/curve/CurveFactory.test.ts | 111 +- .../test/curve/CurveLocationDetail.test.ts | 12 +- .../src/test/curve/EmitStrokableParts.test.ts | 19 +- .../src/test/curve/GeometryQuery.test.ts | 102 +- .../src/test/curve/LineSegment3d.test.ts | 29 +- .../src/test/curve/LineString3d.test.ts | 125 +- .../src/test/curve/RegionBoolean.test.ts | 293 +- .../src/test/curve/StrokeOptions.test.ts | 1 - .../src/test/curve/TransitionSpiral3d.test.ts | 386 +- .../sectionData00/MadhavInput.json | 1971 +- .../sectionData00/sectionA.json | 762 +- .../sectionData00/sectionB.json | 530 +- .../sectionData00/sectionC.json | 435 +- .../sectionData00/sectionD.json | 435 +- .../sectionData00/sectionE.json | 435 +- .../sectionData00/sectionF.json | 2204 +- .../clipping/arnoldasInOut/case1/clipper.json | 23 +- .../clipping/arnoldasInOut/case1/inside.json | 497 +- .../clipping/arnoldasInOut/case1/outside.json | 5455 +- .../clipping/arnoldasInOut/case1/source.json | 5783 +- .../clipping/arnoldasInOut/case2/clipper.json | 43 +- .../clipping/arnoldasInOut/case2/inside.json | 9263 ++- .../clipping/arnoldasInOut/case2/outside.json | 59679 ++++++++++++++- .../clipping/arnoldasInOut/case2/source.json | 62989 +++++++++++++++- .../differentStructureArrayLengthChange.json | 68 +- .../differentStructureExtraProperty.json | 68 +- .../differentStructureMissingProperty.json | 61 +- .../differentStructurePropertyNameChange.json | 68 +- .../deepComparisonTestFiles/original.json | 66 +- .../sameStructureAndValues.json | 66 +- .../sameStructureDifferentValues.json | 66 +- .../data/synchro/082020B/insertedMesh.json | 5 +- .../test/data/synchro/082020B/polyface.json | 5 +- .../data/synchro/082020B/synchromesh.json | 5 +- .../src/test/docSnippets/snippet.test.ts | 20 +- .../src/test/geometry3d/Angle.test.ts | 60 +- .../geometry3d/BarycentricTriangle.test.ts | 106 +- .../src/test/geometry3d/BilinearPatch.test.ts | 30 +- .../test/geometry3d/EllipsoidPatch.test.ts | 587 +- .../src/test/geometry3d/FrameBuilder.test.ts | 106 +- .../test/geometry3d/FrustumAnimation.test.ts | 192 +- .../src/test/geometry3d/GrowableArray.test.ts | 213 +- .../test/geometry3d/GrowableXYArray.test.ts | 98 +- .../IndexedXYZCollectionInterval.test.ts | 3 +- .../LongitudeLatitudeAltidue.test.ts | 7 +- .../src/test/geometry3d/Matrix3d.test.ts | 419 +- .../geometry3d/OrderedRotationAngles.test.ts | 441 +- .../Plane3dByOriginAndUnitNormal.test.ts | 29 +- .../Plane3dByOriginAndVectors.test.ts | 80 +- .../PlaneAltitudeEvaluators.test.ts | 15 +- .../test/geometry3d/Point2dVector2d.test.ts | 9 +- .../test/geometry3d/Point3dVector3d.test.ts | 30 +- .../src/test/geometry3d/PointHelper.test.ts | 161 +- .../src/test/geometry3d/PolygonOps.test.ts | 79 +- .../geometry3d/PolylineCompression.test.ts | 34 +- .../src/test/geometry3d/Quaternion.test.ts | 47 +- .../src/test/geometry3d/Range1dArray.test.ts | 62 +- .../src/test/geometry3d/Range3d.test.ts | 105 +- .../src/test/geometry3d/RangeTree.test.ts | 215 +- .../src/test/geometry3d/Ray3d.test.ts | 142 +- .../src/test/geometry3d/Segment1d.test.ts | 1 - .../src/test/geometry3d/Transform.test.ts | 32 +- .../src/test/geometry3d/ViewBox.test.ts | 107 +- .../geometry3d/YawPitchRollAngles.test.ts | 95 +- .../src/test/geometry4d/Geometry4d.test.ts | 511 +- .../src/test/geometry4d/MomentData.test.ts | 57 +- .../src/test/geometry4d/Point4d.test.ts | 84 +- .../src/test/misc/DeepCompare.test.ts | 3 +- core/geometry/src/test/misc/Geometry.test.ts | 24 +- .../src/test/misc/performance.test.ts | 89 +- .../src/test/numerics/AnalyticRoots.test.ts | 179 +- .../src/test/numerics/BandedSystem.test.ts | 41 +- .../geometry/src/test/numerics/Bezier.test.ts | 99 +- .../geometry/src/test/numerics/Newton.test.ts | 52 +- .../src/test/numerics/PolarData.test.ts | 127 +- .../src/test/numerics/Polynomial.test.ts | 216 +- .../test/numerics/TriDiagonalSystem.test.ts | 10 +- .../src/test/numerics/UnionFind.test.ts | 2 +- .../src/test/numerics/UsageSums.test.ts | 2 +- .../src/test/polyface/DrapeLinestring.test.ts | 173 +- .../src/test/polyface/FacetFaceData.test.ts | 17 +- ...edyTriangulationBetweenLineStrings.test.ts | 9 +- .../src/test/polyface/GridSample.test.ts | 5 +- .../test/polyface/OffsetMeshContext.test.ts | 115 +- .../test/polyface/ParityRegionSweep.test.ts | 47 +- .../src/test/polyface/Polyface.test.ts | 236 +- .../src/test/polyface/PolyfaceAuxData.test.ts | 88 +- .../src/test/polyface/PolyfaceData.test.ts | 22 +- .../src/test/polyface/PolyfaceQuery.test.ts | 274 +- .../polyface/SearchableSetOfRange2d.test.ts | 170 +- .../test/polyface/SortableEdgeCluster.test.ts | 16 +- .../src/test/polyface/XYPointBuckets.test.ts | 42 +- .../geometry/src/test/polyface/sample.test.ts | 24 +- .../src/test/serialization/BSIJSON.test.ts | 61 +- .../src/test/serialization/FlatBuffer.test.ts | 1558 +- .../src/test/serialization/IModelJson.test.ts | 49 +- .../SerializationHelpers.test.ts | 382 +- .../constructorsAndIModelJson.test.ts | 63 +- .../test/serialization/crossPlatform.test.ts | 47 +- .../src/test/serialization/fromJSON.test.ts | 1 - core/geometry/src/test/solid/PipePath.test.ts | 50 +- core/geometry/src/test/solid/Solid.test.ts | 108 +- .../src/test/topology/ChainCollector.test.ts | 41 +- .../src/test/topology/CurveWireOffset.test.ts | 88 +- core/geometry/src/test/topology/Graph.test.ts | 40 +- ...lfEdgeGraphFromIndexedLoopsContext.test.ts | 22 +- .../test/topology/HalfEdgeGraphSearch.test.ts | 6 +- .../HalfEdgeGraphSpineContext.test.ts | 47 +- .../src/test/topology/HalfEdgeMarkSet.test.ts | 5 +- .../InsertAndRetriangulateContext.test.ts | 128 +- .../src/test/topology/MaskManager.test.ts | 2 - core/geometry/src/test/topology/Merge.test.ts | 23 +- .../src/test/topology/RegionOps.test.ts | 376 +- .../src/test/topology/RegularizeFace.test.ts | 343 +- .../src/test/topology/Triangulator.test.ts | 318 +- core/geometry/src/topology/ChainMerge.ts | 45 +- core/geometry/src/topology/Graph.ts | 127 +- .../HalfEdgeGraphFromIndexedLoopsContext.ts | 42 +- .../src/topology/HalfEdgeGraphSearch.ts | 20 +- .../src/topology/HalfEdgeGraphSpineContext.ts | 98 +- core/geometry/src/topology/HalfEdgeMarkSet.ts | 18 +- .../src/topology/HalfEdgeNodeXYZUV.ts | 7 +- .../topology/HalfEdgePointInGraphSearch.ts | 8 +- .../src/topology/HalfEdgePositionDetail.ts | 12 +- .../src/topology/HalfEdgePriorityQueue.ts | 3 +- .../topology/InsertAndRetriangulateContext.ts | 15 +- core/geometry/src/topology/MaskManager.ts | 2 +- core/geometry/src/topology/Merging.ts | 70 +- core/geometry/src/topology/RegularizeFace.ts | 28 +- .../src/topology/SpaceTriangulation.ts | 111 +- core/geometry/src/topology/Triangulation.ts | 130 +- .../src/topology/XYParitySearchContext.ts | 16 +- core/geometry/vitest.config.mts | 16 +- core/hypermodeling/certa.json | 2 +- core/hypermodeling/eslint.config.js | 4 +- core/hypermodeling/src/HyperModeling.ts | 4 +- .../src/HyperModelingDecorator.ts | 20 +- core/hypermodeling/src/PopupToolbar.ts | 2 +- .../src/SectionDrawingLocationState.ts | 12 +- .../src/SectionGraphicsProvider.ts | 98 +- .../hypermodeling/src/SectionMarkerHandler.ts | 10 +- core/hypermodeling/src/SectionMarkers.ts | 29 +- core/hypermodeling/src/Tools.ts | 36 +- .../src/test/HyperModeling.test.ts | 29 +- .../src/test/utils/webpack.config.js | 20 +- core/hypermodeling/tsconfig.json | 2 +- core/i18n/certa.json | 2 +- core/i18n/eslint.config.js | 4 +- core/i18n/src/ITwinLocalization.ts | 17 +- core/i18n/src/test/ITwinLocalization.test.ts | 411 +- .../src/test/public/locales/de/Default.json | 2 +- .../i18n/src/test/public/locales/de/Test.json | 2 +- .../test/public/locales/en-US/Default.json | 2 +- .../src/test/public/locales/en-US/Test.json | 2 +- .../src/test/public/locales/en/Default.json | 2 +- .../i18n/src/test/public/locales/en/Test.json | 2 +- core/i18n/src/test/utils/webpack.config.js | 20 +- core/i18n/tsconfig.json | 2 +- core/markup/certa.json | 4 +- core/markup/eslint.config.js | 4 +- core/markup/src/Markup.ts | 144 +- core/markup/src/MarkupTool.ts | 43 +- core/markup/src/RedlineTool.ts | 123 +- core/markup/src/SelectTool.ts | 211 +- core/markup/src/SvgJsExt.ts | 82 +- core/markup/src/TextEdit.ts | 32 +- core/markup/src/Undo.ts | 50 +- core/markup/src/test/Markup.test.ts | 5 +- core/markup/src/test/utils/webpack.config.js | 20 +- core/mobile/eslint.config.js | 4 +- core/mobile/src/backend/MobileFileHandler.ts | 46 +- core/mobile/src/backend/MobileHost.ts | 58 +- core/mobile/src/backend/MobileRpcServer.ts | 28 +- core/mobile/src/backend/Request.ts | 16 +- core/mobile/src/common/MobileAppProps.ts | 14 +- core/mobile/src/common/MobileEventLoop.ts | 2 +- core/mobile/src/common/MobileIpc.ts | 11 +- core/mobile/src/common/MobilePush.ts | 4 +- core/mobile/src/common/MobileRpcManager.ts | 9 +- core/mobile/src/common/MobileRpcProtocol.ts | 22 +- core/mobile/src/frontend/MobileApp.ts | 16 +- .../src/test/ios/MobilePlatform.test.ts | 1 - core/mobile/src/test/ios/config/ignoreTest.js | 2 +- .../test/ios/config/mobile.webpack.config.js | 55 +- .../AppIcon.appiconset/Contents.json | 118 +- .../Assets.xcassets/Contents.json | 8 +- .../src/test/ios/runMochaTestsDirectly.js | 40 +- .../test/ios/scripts/checkAppCenterLogs.js | 158 +- .../test/ios/scripts/generateTestBarrel.js | 20 +- .../test/ios/scripts/installIosNativeLib.js | 6 +- core/orbitgt/eslint.config.js | 4 +- core/orbitgt/src/core-orbitgt.ts | 2 +- .../pointcloud/format/opc/AttributeMask.ts | 59 +- .../pointcloud/format/opc/AttributeReader.ts | 104 +- .../src/pointcloud/format/opc/BlockRecord.ts | 126 +- .../pointcloud/format/opc/ContainerFile.ts | 353 +- .../format/opc/ContainerFilePart.ts | 138 +- .../pointcloud/format/opc/DirectoryReader.ts | 304 +- .../pointcloud/format/opc/DirectoryRecord.ts | 150 +- .../format/opc/EmbeddedAttributeReader.ts | 391 +- .../src/pointcloud/format/opc/FileAccess.ts | 72 +- .../src/pointcloud/format/opc/FileReader.ts | 469 +- .../src/pointcloud/format/opc/FileRecord.ts | 248 +- .../pointcloud/format/opc/GeometryReader.ts | 297 +- .../pointcloud/format/opc/GeometryRecord.ts | 176 +- .../src/pointcloud/format/opc/OPCReader.ts | 562 +- .../src/pointcloud/format/opc/PointReader.ts | 293 +- .../pointcloud/format/opc/TileReadBuffer.ts | 148 +- .../src/pointcloud/format/opc/TileRecord.ts | 252 +- .../src/pointcloud/model/AttributeTypes.ts | 78 +- .../src/pointcloud/model/AttributeValue.ts | 934 +- .../src/pointcloud/model/BlockIndex.ts | 97 +- .../src/pointcloud/model/CloudPoint.ts | 693 +- core/orbitgt/src/pointcloud/model/Grid.ts | 223 +- .../orbitgt/src/pointcloud/model/GridIndex.ts | 168 +- .../src/pointcloud/model/PointAttribute.ts | 684 +- .../src/pointcloud/model/PointCloudReader.ts | 367 +- .../orbitgt/src/pointcloud/model/PointData.ts | 25 +- .../src/pointcloud/model/PointDataRaw.ts | 110 +- .../src/pointcloud/model/ReadRequest.ts | 536 +- .../pointcloud/model/StandardAttributes.ts | 85 +- .../orbitgt/src/pointcloud/model/TileIndex.ts | 91 +- .../src/pointcloud/render/AViewRequest.ts | 48 +- core/orbitgt/src/pointcloud/render/Block.ts | 202 +- .../src/pointcloud/render/DataManager.ts | 675 +- .../src/pointcloud/render/FrameData.ts | 55 +- core/orbitgt/src/pointcloud/render/Level.ts | 218 +- .../src/pointcloud/render/TileLoadSorter.ts | 11 +- .../orbitgt/src/pointcloud/render/ViewTree.ts | 662 +- core/orbitgt/src/spatial/crs/CRSEngine.ts | 148 +- core/orbitgt/src/spatial/crs/CRSManager.ts | 163 +- core/orbitgt/src/spatial/ecrs/Axis.ts | 161 +- core/orbitgt/src/spatial/ecrs/CRS.ts | 1877 +- .../src/spatial/ecrs/CoordinateSystem.ts | 574 +- core/orbitgt/src/spatial/ecrs/DataFileUnit.ts | 180 +- core/orbitgt/src/spatial/ecrs/Datum.ts | 314 +- core/orbitgt/src/spatial/ecrs/Ellipsoid.ts | 630 +- core/orbitgt/src/spatial/ecrs/OnlineEngine.ts | 154 +- .../src/spatial/ecrs/OnlineRegistry.ts | 102 +- core/orbitgt/src/spatial/ecrs/Operation.ts | 621 +- .../src/spatial/ecrs/OperationMethod.ts | 148 +- .../src/spatial/ecrs/ParameterValue.ts | 100 +- .../src/spatial/ecrs/ParameterValueList.ts | 188 +- .../orbitgt/src/spatial/ecrs/PrimeMeridian.ts | 170 +- core/orbitgt/src/spatial/ecrs/Registry.ts | 358 +- core/orbitgt/src/spatial/ecrs/Transform.ts | 700 +- core/orbitgt/src/spatial/ecrs/Unit.ts | 608 +- .../orbitgt/src/spatial/ecrs/VerticalModel.ts | 140 +- .../orbitgt/src/spatial/ecrs/WellKnownText.ts | 796 +- .../src/spatial/ecrs/WellKnownTextNode.ts | 205 +- .../ecrs/projection/HotineObliqueMercator.ts | 323 +- .../projection/KrovakObliqueConformalConic.ts | 230 +- .../KrovakObliqueConformalConicEN.ts | 98 +- .../ecrs/projection/LambertConical1SP.ts | 213 +- .../ecrs/projection/LambertConical2SP.ts | 366 +- .../spatial/ecrs/projection/Mercator1SP.ts | 174 +- .../ecrs/projection/ObliqueMercator.ts | 336 +- .../ecrs/projection/ObliqueStereographic.ts | 404 +- .../ecrs/projection/TransverseMercator.ts | 380 +- .../ecrs/transformation/PositionVector.ts | 216 +- core/orbitgt/src/spatial/geom/Bounds.ts | 277 +- core/orbitgt/src/spatial/geom/Coordinate.ts | 386 +- core/orbitgt/src/spatial/geom/Line.ts | 889 +- core/orbitgt/src/spatial/geom/Transform.ts | 1524 +- core/orbitgt/src/system/buffer/ABuffer.ts | 144 +- .../src/system/buffer/Float32Buffer.ts | 94 +- .../orbitgt/src/system/buffer/LittleEndian.ts | 619 +- .../orbitgt/src/system/buffer/Uint16Buffer.ts | 106 +- core/orbitgt/src/system/buffer/Uint8Buffer.ts | 106 +- core/orbitgt/src/system/collection/AList.ts | 107 +- core/orbitgt/src/system/collection/IntMap.ts | 41 +- .../src/system/collection/StringMap.ts | 117 +- core/orbitgt/src/system/io/ABufferInStream.ts | 76 +- core/orbitgt/src/system/io/InStream.ts | 36 +- core/orbitgt/src/system/io/OutStream.ts | 34 +- core/orbitgt/src/system/runtime/ALong.ts | 1353 +- core/orbitgt/src/system/runtime/ASystem.ts | 24 +- core/orbitgt/src/system/runtime/Downloader.ts | 66 +- .../src/system/runtime/DownloaderNode.ts | 233 +- .../src/system/runtime/DownloaderXhr.ts | 226 +- core/orbitgt/src/system/runtime/Message.ts | 34 +- core/orbitgt/src/system/runtime/Numbers.ts | 154 +- core/orbitgt/src/system/runtime/Strings.ts | 354 +- .../orbitgt/src/system/runtime/iComparator.ts | 4 +- core/orbitgt/src/system/storage/CacheList.ts | 137 +- core/orbitgt/src/system/storage/CachedItem.ts | 33 +- .../src/system/storage/ContentLoader.ts | 198 +- .../orbitgt/src/system/storage/FileContent.ts | 24 +- core/orbitgt/src/system/storage/FileRange.ts | 24 +- .../orbitgt/src/system/storage/FileStorage.ts | 90 +- core/orbitgt/src/system/storage/NodeFS.ts | 111 +- .../src/system/storage/PageCachedFile.ts | 286 +- core/orbitgt/src/system/storage/UrlFS.ts | 191 +- core/orbitgt/src/test/CrsEngine.test.ts | 2 - core/orbitgt/src/test/OpcReader.test.ts | 4 +- core/quantity/eslint.config.js | 2 +- core/quantity/src/Formatter/Format.ts | 356 +- core/quantity/src/Formatter/FormatEnums.ts | 171 +- core/quantity/src/Formatter/Formatter.ts | 81 +- core/quantity/src/Formatter/FormatterSpec.ts | 42 +- core/quantity/src/Interfaces.ts | 2 +- core/quantity/src/Parser.ts | 221 +- core/quantity/src/ParserSpec.ts | 30 +- core/quantity/src/Quantity.ts | 12 +- core/quantity/src/test/BearingAzimuth.test.ts | 130 +- .../src/test/CompositeFormats.test.ts | 100 +- core/quantity/src/test/Formatting.test.ts | 71 +- core/quantity/src/test/NumericFormat.test.ts | 50 +- core/quantity/src/test/Parsing.test.ts | 210 +- core/quantity/src/test/Ratio.test.ts | 61 +- .../quantity/src/test/TestUtils/TestHelper.ts | 375 +- core/telemetry/certa.json | 2 +- core/telemetry/eslint.config.js | 4 +- core/telemetry/src/TelemetryClient.ts | 1 - core/webgl-compatibility/certa.json | 4 +- core/webgl-compatibility/eslint.config.js | 4 +- core/webgl-compatibility/src/Capabilities.ts | 199 +- .../src/RenderCompatibility.ts | 14 +- .../src/test/Compatibility.test.ts | 80 +- .../src/test/utils/webpack.config.js | 20 +- docs/bis/.vscode/settings.json | 32 +- domains/analytical/backend/eslint.config.js | 2 +- .../backend/src/AnalyticalElements.ts | 20 +- .../backend/src/AnalyticalModels.ts | 4 +- .../backend/src/AnalyticalRelationships.ts | 4 +- .../backend/src/AnalyticalSchema.ts | 10 +- .../backend/src/test/AnalyticalSchema.test.ts | 59 +- .../backend/eslint.config.js | 2 +- .../src/LinearReferencingElementAspects.ts | 66 +- .../backend/src/LinearReferencingElements.ts | 188 +- .../src/LinearReferencingRelationships.ts | 10 +- .../backend/src/LinearReferencingSchema.ts | 10 +- .../src/test/LinearReferencingSchema.test.ts | 82 +- .../common/eslint.config.js | 4 +- .../common/src/LinearReferencingCommon.ts | 11 +- .../backend/eslint.config.js | 2 +- .../backend/src/PhysicalMaterialElements.ts | 40 +- .../backend/src/PhysicalMaterialSchema.ts | 10 +- .../src/test/PhysicalMaterialSchema.test.ts | 6 +- editor/backend/eslint.config.js | 4 +- editor/backend/src/EditBuiltInCommand.ts | 25 +- editor/backend/src/EditCommand.ts | 18 +- editor/common/eslint.config.js | 4 +- editor/common/src/EditorBuiltInIpc.ts | 9 +- editor/common/src/EditorIpc.ts | 1 - editor/frontend/eslint.config.js | 4 +- editor/frontend/src/CreateElementTool.ts | 120 +- editor/frontend/src/EditTool.ts | 10 +- editor/frontend/src/EditToolIpc.ts | 1 - editor/frontend/src/ModifyElementTool.ts | 56 +- .../ProjectExtentsDecoration.ts | 146 +- .../src/ProjectLocation/ProjectGeolocation.ts | 165 +- editor/frontend/src/TransformElementsTool.ts | 78 +- editor/frontend/src/UndoRedoTool.ts | 1 - .../src/public/locales/en/Editor.json | 2 +- example-code/app/RobotWorldEngine.config.json | 21 +- example-code/app/eslint.config.js | 4 +- .../app/src/backend/BarrierElement.ts | 12 +- .../app/src/backend/GeometryStreamBuilder.ts | 2 +- example-code/app/src/backend/RobotElement.ts | 8 +- .../app/src/backend/RobotWorldEngine.ts | 17 +- .../app/src/backend/RobotWorldRpcImpl.ts | 17 +- .../app/src/backend/RobotWorldSchema.ts | 7 +- .../assets/RobotWorldEngine.config.json | 2 +- .../src/backend/test/KnownTestLocations.ts | 5 +- .../app/src/backend/test/RobotWorld.test.ts | 6 +- .../src/backend/test/RobotWorldRpc.test.ts | 24 +- example-code/app/src/backend/test/Utils.ts | 2 +- .../app/src/common/RobotWorldRpcInterface.ts | 42 +- .../app/src/frontend/BlankConnection.ts | 5 +- example-code/app/src/frontend/RobotWorldUI.ts | 2 - example-code/snippets/eslint.config.js | 4 +- .../snippets/src/backend/AzuriteTest.ts | 26 +- .../snippets/src/backend/DumpIModel.test.ts | 4 +- .../src/backend/ECSQL-queries.test.ts | 41 +- .../src/backend/ECSQL-spatial-queries.test.ts | 38 +- .../snippets/src/backend/ExampleCode.test.ts | 16 +- .../snippets/src/backend/ExampleOpenIModel.ts | 2 +- .../snippets/src/backend/ExecutingECSQL.ts | 50 +- .../backend/IModelBranchingOperations.test.ts | 21 +- .../src/backend/IModelExporter.test.ts | 2 +- .../snippets/src/backend/IModelTestUtils.ts | 12 +- .../backend/LoadAndEditiModelSchemas.test.ts | 18 +- .../src/backend/SchemaXmlFileLocater.test.ts | 12 +- .../src/backend/SerializingXmlSchemas.ts | 7 +- .../snippets/src/backend/WireFormat.test.ts | 300 +- .../src/backend/WorkspaceExamples.test.ts | 23 +- .../src/extensions/SmartDeviceDecorator.ts | 9 +- .../src/extensions/SmartDeviceMarker.ts | 7 +- .../snippets/src/frontend/ContourDisplay.ts | 4 +- .../snippets/src/frontend/ExecutingECSQL.ts | 123 +- .../snippets/src/frontend/InteractiveTools.ts | 20 +- .../src/frontend/RealityMeshParamsBuilder.ts | 10 +- .../snippets/src/frontend/ViewDecorations.ts | 37 +- example-code/snippets/src/frontend/Worker.ts | 23 +- .../snippets/src/pcf/DynamicSchema.ts | 9 +- example-code/snippets/src/pcf/pcf.ts | 6 +- example-code/snippets/tsconfig.json | 2 +- extensions/frontend-tiles/certa.json | 1 - extensions/frontend-tiles/eslint.config.js | 4 +- .../frontend-tiles/src/BatchedModelGroups.ts | 17 +- .../frontend-tiles/src/BatchedModels.ts | 2 +- .../src/BatchedSpatialTileTreeRefs.ts | 50 +- extensions/frontend-tiles/src/BatchedTile.ts | 25 +- .../src/BatchedTileContentReader.ts | 6 +- .../frontend-tiles/src/BatchedTileTree.ts | 6 +- .../src/BatchedTileTreeReference.ts | 27 +- .../src/BatchedTileTreeSupplier.ts | 6 +- .../src/BatchedTilesetReader.ts | 22 +- .../frontend-tiles/src/FrontendTiles.ts | 26 +- .../GraphicRepresentationProvider.ts | 83 +- .../src/GraphicsProvider/GraphicsProvider.ts | 5 +- .../url-providers/GeoscienceUrlProvider.ts | 2 +- .../frontend-tiles/src/IndexedDBCache.ts | 17 +- .../frontend-tiles/src/LoggerCategory.ts | 1 - .../src/ModelGroupDisplayTransforms.ts | 4 +- .../src/test/FrontendTiles.test.ts | 2 +- .../GraphicRepresentationProvider.test.ts | 34 +- .../GraphicsProvider/GraphicsProvider.test.ts | 18 +- .../src/test/IndexedDBCache.test.ts | 11 +- .../src/test/ModelGroup.test.ts | 104 +- .../test/ModelGroupDisplayTransforms.test.ts | 6 +- .../src/test/utils/webpack-config.js | 21 +- extensions/frontend-tiles/tsconfig.json | 2 +- extensions/map-layers-auth/eslint.config.js | 2 +- .../src/ArcGis/ArcGisAccessClient.ts | 68 +- .../src/ArcGis/ArcGisOAuth2Endpoint.ts | 15 +- .../src/ArcGis/ArcGisTokenGenerator.ts | 7 +- .../src/ArcGis/ArcGisTokenManager.ts | 17 +- .../map-layers-auth/src/ArcGis/ArcGisUrl.ts | 3 - .../src/test/ArcGisAccessClient.test.ts | 20 +- .../src/test/ArcGisTokenGenerator.test.ts | 16 +- .../src/test/ArcGisUrl.test.ts | 3 - .../map-layers-formats/eslint.config.js | 2 +- .../src/ArcGisFeature/ArcGisFeatureFormat.ts | 32 +- .../ArcGisFeature/ArcGisFeatureProvider.ts | 183 +- .../src/ArcGisFeature/ArcGisFeatureQuery.ts | 98 +- .../src/ArcGisFeature/ArcGisFeatureReader.ts | 10 +- .../ArcGisFeature/ArcGisFeatureResponse.ts | 16 +- .../ArcGisFeature/ArcGisJsonFeatureReader.ts | 24 +- .../ArcGisFeature/ArcGisPbfFeatureReader.ts | 50 +- .../ArcGisFeature/ArcGisSymbologyRenderer.ts | 193 +- .../src/ArcGisFeature/EsriSymbology.ts | 198 +- .../src/ArcGisFeature/esriPBuffer.gen.ts | 4929 +- .../src/Feature/DefaultMarkerIcon.ts | 1 - .../src/Feature/FeatureCanvasRenderer.ts | 8 +- .../src/Feature/FeatureInfoReader.ts | 10 +- .../src/Feature/FeatureSymbology.ts | 1 - .../src/Feature/RandomMapColor.ts | 83 +- .../src/GeoJSON/GeoJSONGeometry.ts | 15 +- .../src/GeoJSON/GeoJSONGeometryReader.ts | 11 +- .../src/Icons/MapInfoIcon.ts | 3 +- .../OgcApiFeatures/OgcApiFeaturesFormat.ts | 26 +- .../OgcApiFeatures/OgcApiFeaturesProvider.ts | 177 +- .../OgcApiFeatures/OgcApiFeaturesReader.ts | 33 +- .../src/Tools/GeometryTerrainDraper.ts | 59 +- .../src/Tools/MapFeatureInfoDecorator.ts | 81 +- .../src/Tools/MapFeatureInfoTool.ts | 65 +- .../src/mapLayersFormats.ts | 6 +- .../public/locales/en/mapLayersFormats.json | 2 +- .../ArcGisFeatureFormats.test.ts | 26 +- .../ArcGisFeatureProvider.test.ts | 590 +- .../ArcGisFeature/ArcGisFeatureQuery.test.ts | 99 +- .../ArcGisFeatureRenderer.test.ts | 85 +- .../ArcGisFeatureResponse.test.ts | 74 +- .../ArcGisJsonFeatureReader.test.ts | 130 +- .../ArcGisPbfFeatureReader.test.ts | 103 +- .../ArcGisSymbologyRenderer.test.ts | 212 +- .../EarthquakeSince1970Dataset.ts | 17 +- .../test/ArcGisFeature/EsriSymbology.test.ts | 8 +- .../src/test/ArcGisFeature/Mocks.ts | 15 +- .../ArcGisFeature/NeptuneCoastlineDataset.ts | 5 +- .../src/test/ArcGisFeature/NewYorkDataset.ts | 865 +- .../ArcGisFeature/PhillyLandmarksDataset.ts | 1934 +- .../src/test/ArcGisFeature/TestUtils.ts | 5 +- .../src/test/OGCFeatures/CountriesDataset.ts | 352 +- .../OGCFeatures/GeoJSONGeometryReader.test.ts | 34 +- .../src/test/OGCFeatures/Mocks.ts | 31 +- .../OGCFeatures/OgcFeaturesProvider.test.ts | 154 +- .../OGCFeatures/OgcFeaturesReader.test.ts | 18 +- .../src/test/OGCFeatures/PhillyDataset.ts | 109 +- extensions/test-extension/eslint.config.js | 4 +- extensions/test-extension/package.json | 2 +- extensions/test-extension/src/SelectTool.ts | 25 +- extensions/test-extension/src/loader.ts | 2 +- extensions/test-extension/src/tsconfig.json | 2 +- extensions/test-extension/tsconfig.json | 2 +- full-stack-tests/backend/eslint.config.js | 4 +- full-stack-tests/backend/src/HubUtility.ts | 36 +- .../src/integration/ApplyChangeSets.test.ts | 10 +- .../backend/src/integration/AzuriteTest.ts | 28 +- .../src/integration/BriefcaseManager.test.ts | 76 +- .../src/integration/ChangeSummary.test.ts | 311 +- .../src/integration/ChangedElements.test.ts | 44 +- .../src/integration/Checkpoints.test.ts | 29 +- .../src/integration/CloudSqlite.test.ts | 53 +- .../src/integration/CloudWorkspace.test.ts | 94 +- .../src/integration/IModelOpen.test.ts | 12 +- .../src/integration/PropertyStore.test.ts | 7 +- .../src/integration/SchemaSync.test.ts | 185 +- .../src/integration/StartupShutdown.ts | 4 +- .../src/integration/TileUpload.test.ts | 23 +- .../backend/src/integration/ViewStore.test.ts | 135 +- .../backend/src/perftest/CRUDConfig.json | 2 +- .../backend/src/perftest/CSPerfConfig.json | 2 +- .../perftest/CloseIModalPerformance.test.ts | 41 +- .../backend/src/perftest/ConcurrencyQueue.ts | 14 +- .../backend/src/perftest/ECSqlRow.test.ts | 63 +- .../backend/src/perftest/ECSqlRowConfig.json | 2 +- .../src/perftest/ElementAspect.test.ts | 98 +- .../backend/src/perftest/ElementCRUD.test.ts | 131 +- .../backend/src/perftest/MixinImpact.test.ts | 32 +- .../backend/src/perftest/PerfTestUtils.ts | 40 +- .../src/perftest/PolymorphicQuery.test.ts | 59 +- .../src/perftest/PropertiesImpact.test.ts | 88 +- .../src/perftest/RelationshipImpact.test.ts | 100 +- .../backend/src/perftest/SchemaImport.test.ts | 7 +- .../backend/src/perftest/SchemaLoader.test.ts | 65 +- .../src/perftest/SchemaPerfConfig.json | 2 +- .../backend/src/perftest/Sqlite.test.ts | 28 +- full-stack-tests/backend/tsconfig.json | 2 +- full-stack-tests/core/eslint.config.js | 4 +- .../core/src/backend/AzuriteTest.ts | 26 +- full-stack-tests/core/src/backend/RpcImpl.ts | 6 +- .../core/src/backend/TestEditCommands.ts | 4 +- full-stack-tests/core/src/backend/backend.ts | 44 +- .../core/src/certa/certaBackend.ts | 8 +- .../core/src/certa/certaCommon.ts | 2 +- .../core/src/common/FullStackTestIpc.ts | 9 +- .../core/src/common/IModelHubUserMgr.ts | 2 +- .../src/common/ITwinAccessClientWrapper.ts | 2 +- .../core/src/common/RpcInterfaces.ts | 12 +- full-stack-tests/core/src/frontend/Editing.ts | 21 +- .../core/src/frontend/HttpRequestHook.ts | 3 +- .../core/src/frontend/TestUtility.ts | 19 +- .../core/src/frontend/TestViewport.ts | 135 +- .../src/frontend/ViewportChangedHandler.ts | 6 +- .../core/src/frontend/_Setup.test.ts | 10 +- .../core/src/frontend/app/NativeApp.test.ts | 8 +- .../src/frontend/hub/ExternalTextures.test.ts | 83 +- .../src/frontend/hub/HyperModeling.test.ts | 28 +- .../src/frontend/hub/IModelConnection.test.ts | 14 +- .../core/src/frontend/hub/ITwinPlatformEnv.ts | 17 +- .../src/frontend/hub/ScheduleScript.test.ts | 6 +- .../src/frontend/hub/SectionDrawing.test.ts | 2 +- .../src/frontend/hub/SheetViewState.test.ts | 4 +- .../src/frontend/map/BackgroundMap.test.ts | 12 +- .../src/frontend/map/PlanProjection.test.ts | 2 +- .../src/frontend/map/PlanarClipMask.test.ts | 65 +- .../frontend/standalone/AttachView.test.ts | 2 +- .../frontend/standalone/BackgroundMap.test.ts | 10 +- .../standalone/BlankConnection.test.ts | 4 +- .../standalone/BriefcaseConnection.test.ts | 2 - .../frontend/standalone/BriefcaseTxns.test.ts | 99 +- .../standalone/CachedDecorations.test.ts | 20 +- .../standalone/CartographicRange.test.ts | 7 +- .../frontend/standalone/Categories.test.ts | 2 +- .../src/frontend/standalone/CodeSpecs.test.ts | 2 +- .../standalone/DisplayStyleState.test.ts | 61 +- .../src/frontend/standalone/ECSqlAst.test.ts | 92 +- .../frontend/standalone/ECSqlQuery.test.ts | 18 +- .../src/frontend/standalone/EditTool.test.ts | 16 +- .../src/frontend/standalone/Elements.test.ts | 2 +- .../standalone/EmphasizeElements.test.ts | 15 +- .../FeatureOverrideProvider.test.ts | 10 +- .../standalone/FeatureOverrides.test.ts | 15 +- .../standalone/FeatureSymbology.test.ts | 113 +- .../src/frontend/standalone/GeoCoord.test.ts | 28 +- .../standalone/GraphicalEditingScope.test.ts | 53 +- .../src/frontend/standalone/Markup.test.ts | 2 +- .../standalone/ModelChangeMonitor.test.ts | 11 +- .../frontend/standalone/ModelState.test.ts | 10 +- .../frontend/standalone/Monochrome.test.ts | 4 +- .../standalone/OpenStandalone.test.ts | 6 +- .../PerModelCategoryVisibility.test.ts | 36 +- .../standalone/PrimitiveBuilder.test.ts | 13 +- .../standalone/QuantityFormatter.test.ts | 2 +- .../standalone/RealityDataAccess.test.ts | 63 +- .../frontend/standalone/RenderTarget.test.ts | 59 +- .../standalone/ScreenSpaceEffects.test.ts | 2 +- .../standalone/SnapshotConnection.test.ts | 2 +- .../standalone/SubCategoriesCache.test.ts | 18 +- .../standalone/ThematicDisplay.test.ts | 45 +- .../core/src/frontend/standalone/Tool.test.ts | 10 +- .../frontend/standalone/Transparency.test.ts | 76 +- .../frontend/standalone/ViewCreator3d.test.ts | 5 +- .../src/frontend/standalone/ViewState.test.ts | 81 +- .../src/frontend/standalone/Viewport.test.ts | 47 +- .../standalone/ViewportChangedEvents.test.ts | 177 +- .../standalone/WaitForSceneCompletion.test.ts | 2 +- .../standalone/WatchForChanges.test.ts | 49 +- .../standalone/WhiteOnWhiteReversal.test.ts | 8 +- .../standalone/tile/B3dmTileIO.test.ts | 4519 +- .../standalone/tile/Disposable.test.ts | 126 +- .../standalone/tile/ElementGraphics.test.ts | 9 +- .../tile/SectionCutTileTree.test.ts | 4 +- .../frontend/standalone/tile/TileIO.test.ts | 83 +- .../standalone/tile/TileRequest.test.ts | 23 +- .../frontend/standalone/tile/TileTree.test.ts | 40 +- .../standalone/tile/Tolerance.test.ts | 51 +- .../standalone/tile/Unloading.test.ts | 13 +- .../tile/VerifyTileVersionInfo.test.ts | 6 +- .../standalone/tile/data/TileIO.data.1.1.ts | 40205 +++++++++- .../standalone/tile/data/TileIO.data.1.2.ts | 34782 ++++++++- .../standalone/tile/data/TileIO.data.1.3.ts | 34782 ++++++++- .../standalone/tile/data/TileIO.data.1.4.ts | 27041 ++++++- .../standalone/tile/data/TileIO.data.2.0.ts | 27382 ++++++- .../standalone/tile/data/TileIO.data.fake.ts | 8 +- full-stack-tests/core/tsconfig.json | 2 +- full-stack-tests/core/webpack.config.js | 14 +- .../ecschema-rpc-interface/certa.json | 2 +- .../ecschema-rpc-interface/eslint.config.js | 4 +- .../src/common/Settings.ts | 12 +- .../src/frontend/SchemaRpcInterface.test.ts | 3 +- .../src/frontend/setup/IModelSession.ts | 11 +- .../src/frontend/setup/TestContext.ts | 20 +- .../src/test/backend.ts | 12 +- .../ecschema-rpc-interface/tsconfig.json | 4 +- .../presentation/public/locales/en/Test.json | 2 +- .../presentation/scripts/setup-tests.js | 2 +- .../presentation/src/ECClasHierarchy.ts | 3 +- .../presentation/src/IModelSetupUtils.ts | 36 +- .../presentation/src/IntegrationTests.ts | 14 +- full-stack-tests/presentation/src/Utils.ts | 2 +- .../backend/DefaultSupplementalRules.test.ts | 16 +- .../src/backend/Diagnostics.test.ts | 14 +- .../src/backend/IModelUpdates.test.ts | 10 +- .../src/backend/NativePlatform.test.ts | 7 +- .../src/backend/PresentationManager.test.ts | 18 +- .../src/backend/ReadWrite.test.ts | 4 +- .../src/backend/RulesetsEmbedding.test.ts | 8 +- .../src/frontend/Diagnostics.test.ts | 4 +- .../src/frontend/Localization.test.ts | 6 +- .../src/frontend/RulesetVariables.test.ts | 8 +- .../src/frontend/Rulesets.test.ts | 10 +- .../src/frontend/SelectionScopes.test.ts | 2 +- .../frontend/content/ArrayProperties.test.ts | 4 +- .../content/CalculatedProperties.test.ts | 2 +- .../frontend/content/ClassDescriptor.test.ts | 12 +- .../content/ContentDisplayLabels.test.ts | 21 +- .../content/ContentInstanceKeys.test.ts | 2 +- .../frontend/content/ContentSources.test.ts | 4 +- .../frontend/content/CustomCategories.test.ts | 14 +- .../frontend/content/DistinctValues.test.ts | 63 +- .../content/ElementProperties.test.ts | 2 +- .../content/FieldsCustomization.test.ts | 10 +- .../frontend/content/FieldsSelector.test.ts | 2 +- .../frontend/content/GuidProperties.test.ts | 6 +- .../frontend/content/Infrastructure.test.ts | 23 +- .../src/frontend/content/InputKeys.test.ts | 2 +- .../content/InstanceFiltering.test.ts | 2 +- .../content/NavigationProperties.test.ts | 2 +- .../content/PropertyValueFormatting.test.ts | 25 +- .../src/frontend/content/Utils.ts | 22 +- .../GettingNodeInstancesCount.test.ts | 16 +- .../hierarchies/GettingNodePaths.test.ts | 2 +- .../HierarchyLevelDescriptors.test.ts | 12 +- .../HierarchyLevelFiltering.test.ts | 16 +- .../HierarchyLevelSizeLimiting.test.ts | 21 +- .../hierarchies/HierarchyValidation.ts | 12 +- .../hierarchies/Infrastructure.test.ts | 2 +- .../ContentCustomization.test.ts | 2 +- .../PresentationManagerBackend.test.ts | 12 +- .../RulesetVariables.test.ts | 4 +- .../common/MultiSchemaClasses.test.ts | 4 +- .../RelatedInstanceSpecification.test.ts | 2 +- .../RelationshipPathSpecification.test.ts | 2 +- ...tableRelationshipPathSpecification.test.ts | 4 +- .../CalculatedPropertiesSpecification.test.ts | 8 +- .../DefaultPropertyCategoryOverride.test.ts | 2 +- .../PropertyCategorySpecification.test.ts | 2 +- .../PropertySpecification.test.ts | 2 +- .../RelatedPropertiesSpecification.test.ts | 2 +- .../content/rules/ContentModifier.test.ts | 5 +- .../content/rules/ContentRule.test.ts | 4 +- .../ContentInstancesOfSpecificClasses.test.ts | 2 +- .../ContentRelatedInstances.test.ts | 2 +- .../SelectedNodeInstances.test.ts | 4 +- .../content/specifications/Shared.test.ts | 7 +- .../customization/DisabledSortingRule.test.ts | 2 +- .../customization/ExtendedDataRule.test.ts | 4 +- .../InstanceLabelOverride.test.ts | 8 +- .../customization/PropertySortingRule.test.ts | 4 +- .../customization/SortingShared.test.ts | 4 +- .../hierarchies/grouping/ClassGroup.test.ts | 4 +- .../grouping/PropertyGroup.test.ts | 4 +- .../grouping/SameLabelInstanceGroup.test.ts | 8 +- .../hierarchies/grouping/Shared.test.ts | 4 +- .../hierarchies/rules/NodeArtifacts.test.ts | 4 +- .../hierarchies/rules/NodeRules.test.ts | 4 +- .../CustomNodeSpecification.test.ts | 4 +- ...tomQueryInstanceNodesSpecification.test.ts | 8 +- ...odesOfSpecificClassesSpecification.test.ts | 16 +- .../RelatedInstanceNodesSpecification.test.ts | 4 +- .../hierarchies/specifications/Shared.test.ts | 12 +- .../src/performance/DataViz.test.ts | 60 +- .../performance/GetElementProperties.test.ts | 16 +- .../src/rpc/PresentationRpcInterface.test.ts | 2 +- full-stack-tests/rpc-interface/certa.json | 2 +- .../rpc-interface/eslint.config.js | 4 +- .../rpc-interface/src/backend/BackendInit.ts | 2 +- .../rpc-interface/src/common/Settings.ts | 45 +- .../rpc-interface/src/common/SideChannels.ts | 2 +- .../src/frontend/CodeSpecs.test.ts | 5 +- .../src/frontend/DevToolsRpc.test.ts | 4 +- .../src/frontend/Elements.test.ts | 7 +- .../rpc-interface/src/frontend/IModel.test.ts | 5 +- .../src/frontend/IModelConnection.test.ts | 36 +- .../rpc-interface/src/frontend/Models.test.ts | 4 +- .../src/frontend/PresentationRpc.test.ts | 6 +- .../rpc-interface/src/frontend/Views.test.ts | 4 +- .../src/frontend/setup/IModelSession.ts | 19 +- .../src/frontend/setup/TestContext.ts | 21 +- .../frontend/workflows/BasicScenarios.test.ts | 12 +- .../rpc-interface/src/test/backend.ts | 8 +- .../rpc-interface/webpack.config.js | 2 +- full-stack-tests/rpc/certa.json | 2 +- full-stack-tests/rpc/eslint.config.js | 4 +- .../rpc/src/backend/CommonBackendSetup.ts | 6 +- .../rpc/src/backend/TestRpcImpl.ts | 24 +- full-stack-tests/rpc/src/backend/electron.ts | 2 +- full-stack-tests/rpc/src/backend/ipc.ts | 2 +- .../rpc/src/common/SideChannels.ts | 2 +- .../rpc/src/common/TestRpcInterface.ts | 42 +- full-stack-tests/rpc/src/frontend/Ipc.test.ts | 2 +- .../rpc/src/frontend/Routing.test.ts | 49 +- .../src/frontend/Rpc.ElectronProtocol.test.ts | 14 +- .../rpc/src/frontend/Rpc.HttpProtocol.test.ts | 2 +- .../rpc/src/frontend/RpcInterface.test.ts | 85 +- full-stack-tests/rpc/tsconfig.json | 2 +- full-stack-tests/rpc/webpack.config.js | 1 - package.json | 2 +- presentation/.mocharc.json | 2 +- .../ElementPropertiesHelper.ts | 4 +- .../presentation-backend/NativePlatform.ts | 2 +- .../src/presentation-backend/Presentation.ts | 7 +- .../PresentationManager.ts | 57 +- .../PresentationManagerDetail.ts | 57 +- .../PresentationRpcImpl.ts | 36 +- .../presentation-backend/RulesetEmbedder.ts | 14 +- .../backend/src/presentation-backend/Utils.ts | 7 +- .../domain/RulesetElements.ts | 2 +- .../src/test/ElementPropertiesHelper.test.ts | 8 +- .../backend/src/test/NativePlatform.test.ts | 22 +- .../backend/src/test/Presentation.test.ts | 8 +- .../src/test/PresentationIpcHandler.test.ts | 4 +- .../src/test/PresentationManager.test.ts | 89 +- .../src/test/PresentationRpcImpl.test.ts | 14 +- .../backend/src/test/RulesetEmbedder.test.ts | 12 +- .../backend/src/test/RulesetManager.test.ts | 2 +- .../src/test/RulesetVariablesManager.test.ts | 6 +- .../src/test/SelectionScopesHelper.test.ts | 76 +- .../backend/src/test/TemporaryStorage.test.ts | 6 +- presentation/backend/src/test/Utils.test.ts | 14 +- presentation/common/Ruleset.schema.json | 2 +- .../scripts/post-process-json-schema.js | 4 +- .../src/presentation-common/Diagnostics.ts | 29 +- .../common/src/presentation-common/EC.ts | 14 +- .../presentation-common/ElementProperties.ts | 5 +- .../InstanceFilterDefinition.ts | 5 +- .../common/src/presentation-common/KeySet.ts | 5 +- .../KoqPropertyValueFormatter.ts | 17 +- .../PresentationManagerOptions.ts | 9 +- .../PresentationRpcInterface.ts | 41 +- .../presentation-common/RpcRequestsHandler.ts | 31 +- .../presentation-common/RulesetsFactory.ts | 8 +- .../content/ContentTraverser.ts | 4 +- .../presentation-common/content/Descriptor.ts | 45 +- .../src/presentation-common/content/Fields.ts | 40 +- .../content/PropertyValueFormatter.ts | 23 +- .../src/presentation-common/content/Value.ts | 4 +- .../src/presentation-common/hierarchy/Key.ts | 7 +- .../customization/InstanceLabelOverride.ts | 2 +- .../common/src/test/AsyncTasks.test.ts | 2 +- presentation/common/src/test/EC.test.ts | 2 +- .../common/src/test/ElementProperties.test.ts | 12 +- presentation/common/src/test/KeySet.test.ts | 2 +- .../test/KoqPropertyValueFormatter.test.ts | 2 +- .../src/test/LocalizationHelper.test.ts | 7 +- .../src/test/PresentationRpcInterface.test.ts | 4 +- .../src/test/RpcRequestsHandler.test.ts | 13 +- .../common/src/test/RulesetVariable.test.ts | 2 +- .../common/src/test/RulesetsFactory.test.ts | 272 +- .../common/src/test/_helpers/Content.ts | 3 +- .../src/test/_helpers/random/IModelJs.ts | 2 +- .../common/src/test/_helpers/random/Misc.ts | 2 +- .../src/test/content/ContentTraverser.test.ts | 12 +- .../src/test/content/Descriptor.test.ts | 2 +- .../common/src/test/content/Item.test.ts | 10 +- .../test/content/PropertyFormatter.test.ts | 6 +- presentation/common/tsconfig.cjs.json | 4 +- presentation/common/tsconfig.esm.json | 6 +- .../ConnectivityInformationProvider.ts | 4 +- .../src/presentation-frontend/Presentation.ts | 5 +- .../PresentationManager.ts | 50 +- .../StreamedResponseGenerator.ts | 8 +- .../FavoritePropertiesManager.ts | 21 +- .../FavoritePropertiesStorage.ts | 10 +- .../selection/HiliteSetProvider.ts | 19 +- .../selection/SelectionManager.ts | 20 +- .../ConnectivityInformationProvider.test.ts | 8 +- .../frontend/src/test/Diagnostics.test.ts | 2 +- .../src/test/IpcRequestsHandler.test.ts | 4 +- .../frontend/src/test/Presentation.test.ts | 4 +- .../src/test/PresentationManager.test.ts | 60 +- .../frontend/src/test/RulesetManager.test.ts | 4 +- .../src/test/RulesetVariablesManager.test.ts | 16 +- .../test/StreamedResponseGenerator.test.ts | 16 +- .../FavoritePropertiesManager.test.ts | 28 +- .../FavoritePropertiesStorage.test.ts | 16 +- .../test/selection/HiliteSetProvider.test.ts | 16 +- .../test/selection/SelectionHandler.test.ts | 4 +- .../test/selection/SelectionHelper.test.ts | 2 +- .../test/selection/SelectionManager.test.ts | 49 +- .../selection/SelectionScopesManager.test.ts | 18 +- presentation/frontend/tsconfig.cjs.json | 4 +- presentation/frontend/tsconfig.esm.json | 6 +- presentation/scripts/copy-test-setup.js | 10 +- presentation/scripts/setup-tests.js | 6 +- .../eslint.config.js | 10 +- .../mobile.backend.webpack.config.js | 20 +- .../mobile.frontend.webpack.config.js | 14 +- .../display-performance-test-app/package.json | 2 +- .../src/backend/CsvWriter.ts | 20 +- .../src/backend/DefaultConfig.json | 2 +- .../src/backend/DisplayPerfRpcImpl.ts | 15 +- .../src/backend/ElectronMain.ts | 3 +- .../src/backend/WebMain.ts | 19 +- .../src/backend/backend.ts | 28 +- .../src/common/DisplayPerfEnvConfig.ts | 1 - .../src/common/DisplayPerfRpcInterface.ts | 50 +- .../src/frontend/DisplayPerformanceTestApp.ts | 28 +- .../src/frontend/SavedViewsFetcher.ts | 11 +- .../src/frontend/TestConfig.ts | 14 +- .../src/frontend/TestRunner.ts | 94 +- .../tsconfig.json | 2 +- .../vite.config.mts | 43 +- .../display-test-app/.vscode/settings.json | 10 +- test-apps/display-test-app/buildEnvJson.ts | 4 +- test-apps/display-test-app/eslint.config.js | 8 +- .../AppIcon.appiconset/Contents.json | 118 +- .../Assets.xcassets/Contents.json | 8 +- test-apps/display-test-app/package.json | 2 +- .../public/locales/en/SVTTools.json | 2 +- test-apps/display-test-app/runIosSimulator.ts | 32 +- .../display-test-app/src/backend/Backend.ts | 42 +- .../src/backend/DtaElectronMain.ts | 10 +- .../src/backend/MobileMain.ts | 4 +- .../src/backend/SectionDrawingImpl.ts | 26 +- .../src/backend/SetToStandalone.ts | 6 +- .../display-test-app/src/backend/WebMain.ts | 16 +- .../src/common/DtaConfiguration.ts | 4 +- .../src/common/DtaRpcInterface.ts | 48 +- .../src/frontend/AmbientOcclusion.ts | 58 +- .../src/frontend/AnalysisStyleExample.ts | 61 +- .../display-test-app/src/frontend/App.ts | 142 +- .../src/frontend/AspectRatioSkewDecorator.ts | 10 +- .../src/frontend/Atmosphere.ts | 127 +- .../src/frontend/BingTerrainProvider.ts | 34 +- .../src/frontend/CameraPaths.ts | 55 +- .../src/frontend/Cantilever.ts | 2 +- .../src/frontend/ClassificationsPanel.ts | 54 +- .../display-test-app/src/frontend/Contours.ts | 63 +- .../src/frontend/CreateSectionDrawingTool.ts | 32 +- .../src/frontend/DebugWindow.ts | 10 +- .../src/frontend/DecorationGeometryExample.ts | 45 +- .../src/frontend/DisplayScale.ts | 16 +- .../src/frontend/DisplayTestApp.ts | 28 +- .../src/frontend/DisplayTransform.ts | 20 +- .../src/frontend/DrawingAidTestTool.ts | 21 +- .../src/frontend/DynamicClassifierTool.ts | 45 +- .../src/frontend/EditingTools.ts | 95 +- .../src/frontend/EnvironmentEditor.ts | 42 +- .../src/frontend/FeatureOverrides.ts | 64 +- .../display-test-app/src/frontend/Fence.ts | 12 +- .../display-test-app/src/frontend/FileOpen.ts | 1 - .../src/frontend/FpsMonitor.ts | 21 +- .../src/frontend/FrameStatsTool.ts | 8 +- .../src/frontend/GltfDecoration.ts | 34 +- .../display-test-app/src/frontend/Grid.ts | 10 +- .../src/frontend/HubPicker.ts | 12 +- .../display-test-app/src/frontend/IdPicker.ts | 66 +- .../src/frontend/IncidentMarkerDemo.ts | 25 +- .../src/frontend/LightingEditor.ts | 44 +- .../src/frontend/MacroTools.ts | 28 +- .../src/frontend/NamedViews.ts | 21 +- .../src/frontend/Notifications.ts | 26 +- .../src/frontend/OutputShadersTool.ts | 15 +- .../src/frontend/PathDecorationTest.ts | 10 +- .../src/frontend/RealityDataModel.ts | 17 +- .../src/frontend/RealityDataProvider.ts | 36 +- .../RealityModelDisplaySettingsWidget.ts | 184 +- .../src/frontend/SaveImageTool.ts | 10 +- .../src/frontend/SavedViews.ts | 22 +- .../src/frontend/SectionTools.ts | 32 +- .../src/frontend/ShadowMapDecoration.ts | 24 +- .../src/frontend/SimpleViewState.ts | 2 +- .../src/frontend/SnapModes.ts | 2 +- .../src/frontend/StandardRotations.ts | 12 +- .../display-test-app/src/frontend/Surface.ts | 74 +- .../src/frontend/SyncViewportsTool.ts | 20 +- .../src/frontend/TerrainDrapeTool.ts | 63 +- .../src/frontend/TextDecoration.ts | 40 +- .../src/frontend/ThematicDisplay.ts | 391 +- .../src/frontend/TileContentTool.ts | 26 +- .../src/frontend/TileSizeRecorder.ts | 12 +- .../src/frontend/TiledGraphics.ts | 48 +- .../src/frontend/TimePointComparison.ts | 13 +- .../display-test-app/src/frontend/Timeline.ts | 6 +- .../display-test-app/src/frontend/ToolBar.ts | 6 +- .../src/frontend/UiManager.ts | 31 +- .../src/frontend/ViewAttributes.ts | 113 +- .../frontend/ViewClipByElementGeometryTool.ts | 21 +- .../src/frontend/ViewPicker.ts | 8 +- .../display-test-app/src/frontend/Viewer.ts | 49 +- .../display-test-app/src/frontend/Window.ts | 64 +- .../display-test-app/src/frontend/signIn.ts | 13 +- .../tsconfig.buildScripts.json | 2 +- test-apps/display-test-app/tsconfig.json | 4 +- test-apps/display-test-app/vite.config.mts | 44 +- test-apps/export-gltf/eslint.config.js | 4 +- test-apps/export-gltf/package.json | 2 +- test-apps/export-gltf/src/ExportGltf.ts | 49 +- test-apps/export-gltf/src/GltfTypes.ts | 2 +- test-apps/export-gltf/tsconfig.json | 4 +- test-apps/imjs-importer/eslint.config.js | 4 +- test-apps/imjs-importer/package.json | 2 +- test-apps/imjs-importer/src/ImportIMJS.ts | 55 +- test-apps/imjs-importer/src/byDirectory.ts | 12 +- test-apps/imjs-importer/src/main.ts | 17 +- .../test/unit/ImportIMJS.test.ts | 216 +- test-apps/imjs-importer/tsconfig.json | 28 +- .../imodel-from-geojson/.vscode/launch.json | 4 +- .../imodel-from-geojson/.vscode/settings.json | 2 +- .../imodel-from-geojson/eslint.config.js | 4 +- test-apps/imodel-from-geojson/package.json | 2 +- .../src/ClassifyRealityModel.ts | 53 +- .../src/GeoJsonImporter.ts | 111 +- test-apps/imodel-from-geojson/src/Main.ts | 22 +- .../imodel-from-orbitgt/eslint.config.js | 4 +- test-apps/imodel-from-orbitgt/package.json | 2 +- test-apps/imodel-from-orbitgt/src/Main.ts | 4 +- .../src/OrbitGtContextModelCreator.ts | 59 +- .../eslint.config.js | 4 +- .../imodel-from-reality-model/package.json | 2 +- .../imodel-from-reality-model/src/Main.ts | 4 +- .../src/RealityModelContextIModelCreator.ts | 56 +- .../bin/backend-webpack-tools.js | 18 +- .../config/getWebpackConfig.js | 4 +- tools/backend-webpack/scripts/build.js | 14 +- tools/backend-webpack/scripts/start.js | 44 +- .../scripts/utils/initialize.js | 4 +- .../scripts/utils/webpackWrappers.js | 6 +- tools/build/bin/betools.js | 189 +- tools/build/eslint.config.js | 6 +- tools/build/scripts/config/paths.js | 32 +- tools/build/scripts/copy-assets.js | 10 +- tools/build/scripts/docs.js | 36 +- tools/build/scripts/extract-api-summary.js | 10 +- tools/build/scripts/extract-api.js | 45 +- tools/build/scripts/pseudolocalize.js | 12 +- .../build/scripts/utils/addPackageMetadata.js | 4 +- tools/build/scripts/utils/recursiveReaddir.js | 18 +- tools/build/scripts/utils/simpleSpawn.js | 34 +- tools/build/scripts/utils/utils.js | 6 +- tools/build/scripts/utils/validateTags.js | 30 +- tools/build/src/mocha-reporter/index.ts | 20 +- tools/certa/bin/certa.js | 14 +- tools/certa/certa.schema.json | 2 +- tools/certa/eslint.config.js | 8 +- tools/certa/src/CertaConfig.ts | 5 +- tools/certa/src/CertaCore.ts | 4 +- .../src/runners/chrome/ChromeTestRunner.ts | 6 +- .../src/runners/chrome/MochaSerializer.ts | 2 +- tools/certa/src/runners/chrome/webserver.ts | 7 +- .../runners/electron/ElectronTestRunner.ts | 7 +- tools/certa/src/utils/CallbackUtils.ts | 18 +- tools/certa/src/utils/SpawnUtils.ts | 2 +- tools/certa/src/utils/initMocha.ts | 2 +- tools/certa/src/utils/initSourceMaps.ts | 2 +- tools/certa/tsconfig.json | 2 +- tools/ecschema2ts/eslint.config.js | 4 +- tools/ecschema2ts/src/ecschema2ts.ts | 17 +- tools/ecschema2ts/src/ecschema2ts_cli.ts | 6 +- tools/ecschema2ts/src/ecschema2ts_io.ts | 45 +- tools/ecschema2ts/src/test/bis.test.ts | 27 +- .../ecschema2ts/src/test/ecschema2ts.test.ts | 117 +- .../src/test/ecschema2ts_cache.test.ts | 12 +- .../src/test/ecschema2ts_file.test.ts | 12 +- .../src/test/ecschema2ts_property.test.ts | 60 +- .../src/test/ecschema2ts_xml.test.ts | 135 +- tools/ecschema2ts/src/test/utilities/utils.ts | 9 +- tools/ecschema2ts/tsconfig.json | 2 +- .../AccentColor.colorset/Contents.json | 10 +- .../AppIcon.appiconset/Contents.json | 116 +- .../Assets.xcassets/Contents.json | 6 +- .../Preview Assets.xcassets/Contents.json | 6 +- tools/internal/ios/ios.webpack.config.js | 22 +- tools/internal/ios/scripts/configureMocha.js | 2 +- .../ios/scripts/processAppCenterLogs.js | 64 +- tools/internal/ios/scripts/runMocha.js | 6 +- tools/internal/scripts/copyConfig.js | 14 +- tools/internal/scripts/linkextensions.js | 19 +- tools/perf-tools/eslint.config.js | 4 +- tools/perf-tools/tsconfig.json | 2 +- tools/webpack-core/eslint.config.js | 8 +- .../src/plugins/BackendDefaultsPlugin.ts | 11 +- .../src/plugins/FrontendDefaultsPlugin.ts | 2 +- .../src/plugins/PrettyLoggingPlugin.ts | 14 +- .../src/plugins/RequireMagicCommentsPlugin.ts | 18 +- .../src/plugins/WatchBackendPlugin.ts | 2 +- .../CopyBentleyStaticResourcesPlugin.test.ts | 9 +- .../src/test/CopyExternalsPlugin.test.ts | 6 +- .../test/OptionalDependenciesPlugin.test.ts | 11 +- .../test/RequireMagicCommentsPlugin.test.ts | 53 +- tools/webpack-core/src/test/TestUtils.ts | 4 +- tools/webpack-core/src/test/setup.test.ts | 4 +- .../src/utils/resolve-recurse/resolve.d.ts | 1 - .../src/utils/resolve-recurse/resolve.js | 15 +- tools/webpack-core/tsconfig.json | 4 +- ui/appui-abstract/certa.json | 2 +- ui/appui-abstract/eslint.config.js | 10 +- .../src/appui-abstract/BaseUiItemsProvider.ts | 58 +- .../src/appui-abstract/UiAdmin.ts | 167 +- .../src/appui-abstract/UiItemsManager.ts | 39 +- .../src/appui-abstract/UiItemsProvider.ts | 18 +- .../appui-abstract/backstage/BackstageItem.ts | 19 +- .../backstage/BackstageItemsManager.ts | 10 +- .../content/StandardContentLayouts.ts | 41 +- .../src/appui-abstract/dialogs/DialogItem.ts | 7 +- .../appui-abstract/dialogs/UiDataProvider.ts | 6 +- .../dialogs/UiLayoutDataProvider.ts | 15 +- .../appui-abstract/items/AbstractItemProps.ts | 4 +- .../items/AbstractToolbarProps.ts | 2 +- .../notification/MessagePresenter.ts | 14 +- .../notification/MessageSeverity.ts | 4 +- .../appui-abstract/properties/Description.ts | 46 +- .../appui-abstract/properties/EditorParams.ts | 1 - .../properties/StandardTypeNames.ts | 2 +- .../quantity/BaseQuantityDescription.ts | 6 +- .../appui-abstract/statusbar/StatusBarItem.ts | 40 +- .../statusbar/StatusBarItemsManager.ts | 12 +- .../appui-abstract/toolbars/ToolbarItem.ts | 30 +- .../toolbars/ToolbarItemsManager.ts | 24 +- .../appui-abstract/utils/IconSpecUtilities.ts | 9 +- .../src/appui-abstract/utils/UiError.ts | 1 - .../src/appui-abstract/utils/UiEvent.ts | 2 +- .../appui-abstract/utils/UiEventDispatcher.ts | 18 +- .../appui-abstract/utils/filter/filters.ts | 10 +- .../src/appui-abstract/utils/misc.ts | 1 - .../widget/AbstractWidgetProps.ts | 8 +- .../src/appui-abstract/widget/WidgetState.ts | 2 +- .../src/test/BaseUiItemsProvider.test.ts | 70 +- ui/appui-abstract/src/test/UiAdmin.test.ts | 106 +- .../src/test/UiItemsManager.test.ts | 98 +- .../backstage/BackstageItemsManager.test.ts | 44 +- .../src/test/dialogs/DialogItem.test.ts | 13 +- .../test/dialogs/UiLayoutDataProvider.test.ts | 35 +- .../src/test/properties/EditorParams.test.ts | 32 +- .../PropertyDescriptionHelper.test.ts | 12 +- .../test/properties/PropertyRecord.test.ts | 7 +- .../quantity/BaseQuantityDescription.test.ts | 8 +- .../statusbar/StatusBarItemsManager.test.ts | 157 +- .../test/toolbar/ToolbarItemsManager.test.ts | 93 +- .../src/test/utils/IconSpecUtilities.test.ts | 1 - .../src/test/utils/UiEvent.test.ts | 4 +- .../src/test/utils/UiEventDispatcher.test.ts | 1 - .../src/test/utils/filter.test.ts | 8 +- .../src/test/utils/getClassName.test.ts | 1 - .../src/test/utils/webpack.config.js | 24 +- utils/workspace-editor/eslint.config.js | 4 +- utils/workspace-editor/src/WorkspaceEditor.ts | 58 +- 2490 files changed, 422759 insertions(+), 65479 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index eaf8fe101bea..d7a9a4394075 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -14,4 +14,4 @@ ] } } -} \ No newline at end of file +} diff --git a/.github/workflows/automation-scripts/invalidate-status-checks.mjs b/.github/workflows/automation-scripts/invalidate-status-checks.mjs index 2e4d2de40240..8a16771b06c0 100644 --- a/.github/workflows/automation-scripts/invalidate-status-checks.mjs +++ b/.github/workflows/automation-scripts/invalidate-status-checks.mjs @@ -2,37 +2,37 @@ // This is specifically to catch changes to @bentley/imodeljs-native and should only invalidate PRs that target master branch // This will also invalidate PRs if there's a new nightly build, however our 3 hour rule should also invalidate the same PRs -import { Octokit, App } from "octokit" -import dotenv from 'dotenv' +import dotenv from "dotenv"; +import { App, Octokit } from "octokit"; dotenv.config(); const octokit = new Octokit({ - auth: `${process.env.GITHUB_TOKEN}` + auth: `${process.env.GITHUB_TOKEN}`, }); -let pull_requests = await octokit.request('GET /repos/{owner}/{repo}/pulls', { - owner: 'iTwin', - repo: 'itwinjs-core', +let pull_requests = await octokit.request("GET /repos/{owner}/{repo}/pulls", { + owner: "iTwin", + repo: "itwinjs-core", headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } -}) + "X-GitHub-Api-Version": "2022-11-28", + }, +}); for (let i = 0; i < pull_requests.data.length; i++) { let pr_sha = pull_requests.data[i].head.sha; - if (!pull_requests.data[i].draft && pull_requests.data[i].base.ref === 'master') { - await octokit.request('POST /repos/{owner}/{repo}/statuses/{sha}', { - owner: 'iTwin', - repo: 'itwinjs-core', + if (!pull_requests.data[i].draft && pull_requests.data[i].base.ref === "master") { + await octokit.request("POST /repos/{owner}/{repo}/statuses/{sha}", { + owner: "iTwin", + repo: "itwinjs-core", sha: `${pr_sha}`, - state: 'failure', - description: '@bentley/imodeljs-native may be out of date with master, please merge', - context: 'iTwin.js', + state: "failure", + description: "@bentley/imodeljs-native may be out of date with master, please merge", + context: "iTwin.js", headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }) + "X-GitHub-Api-Version": "2022-11-28", + }, + }); } } diff --git a/.github/workflows/automation-scripts/update-changelogs.mjs b/.github/workflows/automation-scripts/update-changelogs.mjs index c0eecfec2771..57f41d929081 100644 --- a/.github/workflows/automation-scripts/update-changelogs.mjs +++ b/.github/workflows/automation-scripts/update-changelogs.mjs @@ -2,23 +2,23 @@ "use strict"; -import 'zx/globals' +import "zx/globals"; /**************************************************************** -* To run manually: -* install zx package -* git checkout target branch (master or latest release); git pull -* git checkout release/X.X.x; git pull (this is the branch that was just patched) -* uncomment git checkout -b cmd and fix branch name -* run this file using `zx --install .github/workflows/automation-scripts/update-changelogs.mjs` -* open PR into target branch -*****************************************************************/ + * To run manually: + * install zx package + * git checkout target branch (master or latest release); git pull + * git checkout release/X.X.x; git pull (this is the branch that was just patched) + * uncomment git checkout -b cmd and fix branch name + * run this file using `zx --install .github/workflows/automation-scripts/update-changelogs.mjs` + * open PR into target branch + *****************************************************************/ // Sort entries based on version numbers formatted as 'major.minor.patch' function sortByVersion(entries) { return entries.sort((a, b) => { - const versionA = a.version.split('.').map(Number); - const versionB = b.version.split('.').map(Number); + const versionA = a.version.split(".").map(Number); + const versionB = b.version.split(".").map(Number); for (let i = 0; i < 3; i++) { if (versionA[i] < versionB[i]) return 1; @@ -35,7 +35,7 @@ function fixChangeLogs(files) { const currentJson = fs.readJsonSync(`temp-target-changelogs/${files[i]}`); const incomingJson = fs.readJsonSync(`temp-incoming-changelogs/${files[i]}`); // .map creates an array of [changelog version string, changelog entry] tuples, which is passed into Map and creates a key value pair of the two elements. - let combinedEntries = [...currentJson.entries, ...incomingJson.entries].map((obj) => [obj['version'], obj]); + let combinedEntries = [...currentJson.entries, ...incomingJson.entries].map((obj) => [obj["version"], obj]); // Map objects do not allow duplicate keys, so this will remove duplicate version numbers let completeEntries = new Map(combinedEntries); // convert entries back into an array and sort by version number @@ -48,21 +48,21 @@ function fixChangeLogs(files) { function editFileInPlaceSynchronously(filePath, stringToSearch, stringToReplace) { try { - const contentRead = fs.readFileSync(filePath, { encoding: 'utf-8' }); + const contentRead = fs.readFileSync(filePath, { encoding: "utf-8" }); const contentToWrite = contentRead.replace(stringToSearch, stringToReplace); - fs.writeFileSync(filePath, contentToWrite, { encoding: 'utf-8' }); + fs.writeFileSync(filePath, contentToWrite, { encoding: "utf-8" }); } catch (err) { - console.log(`Error while reading or writing to "${filePath}": ${err}`) + console.log(`Error while reading or writing to "${filePath}": ${err}`); } } -const targetPath = "./temp-target-changelogs" -const incomingPath = "./temp-incoming-changelogs" +const targetPath = "./temp-target-changelogs"; +const incomingPath = "./temp-incoming-changelogs"; // To run shell commands using zx use "await $`cmd`" -await $`mkdir ${targetPath}` -await $`mkdir ${incomingPath}` +await $`mkdir ${targetPath}`; +await $`mkdir ${incomingPath}`; // find the latest release branch, and make that the target for the changelogs let targetBranch = await $`git branch -a --list "origin/release/[0-9]*.[0-9]*.x" | tail -n1 | sed 's/ remotes\\///'`; @@ -71,12 +71,12 @@ let currentBranch = await $`git branch --show-current`; let commitMessage = await $`git log --grep="^[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+[^-]*$" -n 1 --pretty=format:%s`; // remove extra null and new line characters from git cmds -targetBranch = String(targetBranch).replace(/\n/g, ''); -currentBranch = String(currentBranch).replace(/\n/g, ''); -commitMessage = String(commitMessage).replace(/\n/g, ''); +targetBranch = String(targetBranch).replace(/\n/g, ""); +currentBranch = String(currentBranch).replace(/\n/g, ""); +commitMessage = String(commitMessage).replace(/\n/g, ""); const substring = " Changelogs"; if (commitMessage.includes(substring)) { - commitMessage = commitMessage.replace(substring, ''); + commitMessage = commitMessage.replace(substring, ""); } console.log(`target branch: ${targetBranch}`); @@ -84,10 +84,10 @@ console.log(`current branch: ${currentBranch}`); console.log(`commit msg: ${commitMessage}`); if (targetBranch === `origin/${currentBranch}`) { - console.log("The current branch is the latest release, so the target will be master branch") - targetBranch = 'master' + console.log("The current branch is the latest release, so the target will be master branch"); + targetBranch = "master"; } else { - console.log(`The current branch is ${currentBranch}, so the target will be ${targetBranch} branch`) + console.log(`The current branch is ${currentBranch}, so the target will be ${targetBranch} branch`); } // copy all changelogs from the current branch to ./temp-incoming-changelogs, the files will be named: package_name_CHANGELOG.json await $`find ./ -type f -name "CHANGELOG.json" -not -path "*/node_modules/*" -exec sh -c 'cp "{}" "./temp-incoming-changelogs/$(echo "{}" | sed "s/^.\\///; s/\\//_/g")"' \\;`; @@ -118,7 +118,7 @@ const targetFiles = allTargetFiles.filter((file) => { else { console.log(`${file} is not a package in ${currentBranch}. Skipping this package.`); } -}) +}); fixChangeLogs(targetFiles); @@ -130,7 +130,7 @@ await $`rm -r ${incomingPath}`; // after already checking out to target branch // copy {release-version}.md to target branch if the commit that triggered this script run is from a major or minor version bump if (commitMessage.endsWith(".0")) { - await $`git checkout ${currentBranch} docs/changehistory/${commitMessage}.md` + await $`git checkout ${currentBranch} docs/changehistory/${commitMessage}.md`; // also need to add reference to this new md in leftNav.md const leftNavMdPath = "docs/changehistory/leftNav.md"; @@ -139,9 +139,9 @@ if (commitMessage.endsWith(".0")) { // # regen CHANGELOG.md await $`rush publish --regenerate-changelogs`; /********************************************************************* -* Uncomment For Manual runs and fix branch name to appropriate version -* the version should match your incoming branch -*********************************************************************/ + * Uncomment For Manual runs and fix branch name to appropriate version + * the version should match your incoming branch + *********************************************************************/ // await $`git checkout -b finalize-release-X.X.X`; // targetBranch = "finalize-release-X.X.X" await $`git add .`; diff --git a/.mocharc.jsonc b/.mocharc.jsonc index 1f2246e27b48..b6358ca0f036 100644 --- a/.mocharc.jsonc +++ b/.mocharc.jsonc @@ -8,4 +8,4 @@ "reporter": "node_modules/@itwin/build-tools/mocha-reporter", "reporter-options": "mochaFile=lib/test/junit_results.xml", "timeout": 999999 -} \ No newline at end of file +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 3e146dea829b..4684b98f66c6 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,4 +5,4 @@ "davidanson.vscode-markdownlint", "dprint.dprint" ] -} \ No newline at end of file +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 5213182fa286..530c83754289 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -202,7 +202,8 @@ "${workspaceFolder}/extensions/frontend-tiles/lib/**/*.js" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for Frontend Tests", "presentation": { "hidden": true @@ -224,7 +225,8 @@ "[BROWSER] Frontend Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BROWSER] Frontend Tests", "presentation": { "hidden": true @@ -240,7 +242,8 @@ "[NODE] Certa Test Runner for Frontend Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for i18n Tests", "presentation": { "hidden": true @@ -262,7 +265,8 @@ "[BROWSER] i18n Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BROWSER] i18n Tests", "presentation": { "hidden": true @@ -298,7 +302,8 @@ "NODE_ENV": "development" // needed for asserts to fire } }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for HyperModeling Tests", "presentation": { "hidden": true @@ -320,7 +325,8 @@ "[BROWSER] HyperModeling Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BROWSER] HyperModeling Tests", "presentation": { "hidden": true @@ -336,7 +342,8 @@ "[NODE] Certa Test Runner for HyperModeling Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for Markup Tests", "presentation": { "hidden": true @@ -351,7 +358,7 @@ ], "outFiles": [ "${workspaceFolder}/core/*/lib/**/*.js", - "${workspaceFolder}/tools/certa/lib/**/*.js", + "${workspaceFolder}/tools/certa/lib/**/*.js" ], "outputCapture": "std", "attachSimplePort": 5858, // NB: This must match ports.debugging in core/markup/certa.json @@ -359,7 +366,8 @@ "[BROWSER] Markup Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BROWSER] Markup Tests", "presentation": { "hidden": true @@ -393,7 +401,8 @@ ] }, // UI TESTS - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for AppUI Abstract Tests", "presentation": { "hidden": true @@ -417,7 +426,8 @@ "[BROWSER] AppUI Abstract Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BROWSER] AppUI Abstract Tests", "presentation": { "hidden": true @@ -690,10 +700,10 @@ ], "outFiles": [ "${workspaceFolder}/utils/workspace-editor/lib/**/*.js", - "${workspaceFolder}/core/*/lib/**/*.js", + "${workspaceFolder}/core/*/lib/**/*.js" ], "env": { - "WORKSPACE_EDITOR_LOGGING": "false", + "WORKSPACE_EDITOR_LOGGING": "false" } }, { @@ -710,7 +720,8 @@ ] }, // TEST APPS - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] display-test-app (chrome)", "presentation": { "hidden": true @@ -730,7 +741,8 @@ "[FRONTEND] display-test-app (chrome)" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] display-test-app (chrome)", "presentation": { "hidden": true @@ -746,7 +758,8 @@ "[BACKEND] display-test-app (chrome)" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] display-test-app (electron)", "presentation": { "hidden": true @@ -773,7 +786,8 @@ "[FRONTEND] display-test-app (electron)" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] display-test-app (electron)", "presentation": { "hidden": true @@ -789,7 +803,8 @@ "[BACKEND] display-test-app (electron)" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] display-performance-test-app (chrome)", "presentation": { "hidden": true @@ -806,7 +821,8 @@ "[FRONTEND] display-performance-test-app (chrome)" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] display-performance-test-app (chrome)", "presentation": { "hidden": true @@ -823,7 +839,8 @@ ] }, // FULLSTACK TESTS - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] Full Stack Core Tests", "presentation": { "hidden": true @@ -847,7 +864,8 @@ "[FRONTEND] Full Stack Core Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] Full Stack Core Tests", "presentation": { "hidden": true @@ -865,7 +883,8 @@ "[BACKEND] Full Stack Core Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] Full Stack Core Integration Tests", "presentation": { "hidden": true @@ -891,7 +910,8 @@ "[FRONTEND] Full Stack Core Integration Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] Full Stack Core Integration Tests", "presentation": { "hidden": true @@ -909,7 +929,8 @@ "[BACKEND] Full Stack Core Integration Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] Full Stack RPC Tests", "presentation": { "hidden": true @@ -935,7 +956,8 @@ "[FRONTEND] Full Stack RPC Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] Full Stack RPC Tests", "presentation": { "hidden": true @@ -953,7 +975,8 @@ "[BACKEND] Full Stack RPC Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[NODE] Certa Test Runner for Full Stack RPC Interface Tests", "presentation": { "hidden": true @@ -980,7 +1003,8 @@ "[FRONTEND] Full Stack RPC Interface Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] Local Backend for Full Stack RPC Interface Tests", "presentation": { "hidden": true @@ -999,7 +1023,8 @@ "[FRONTEND] Full Stack RPC Interface Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] Full Stack RPC Interface Tests", "presentation": { "hidden": true @@ -1018,7 +1043,8 @@ "[BACKEND] Local Backend for Full Stack RPC Interface Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[BACKEND] Electron Frontend Tests", "presentation": { "hidden": true @@ -1043,7 +1069,8 @@ "[FRONTEND] Electron Frontend Tests" ] }, - { /* PARTIAL */ + { + /* PARTIAL */ "name": "[FRONTEND] Electron Frontend Tests", "presentation": { "hidden": true @@ -1069,7 +1096,7 @@ "runtimeArgs": [ "run", "generate" - ], + ] }, { "name": "Electron Backend Tests", @@ -1092,7 +1119,7 @@ "${workspaceFolder}/core/backend/lib/**/*.js" ], "autoAttachChildProcesses": true - }, + } ], "compounds": [ { @@ -1237,7 +1264,7 @@ "[BROWSER] AppUI Abstract Tests", "[NODE] Certa Test Runner for AppUI Abstract Tests" ] - }, + } ], "inputs": [ { @@ -1263,4 +1290,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff71359d0dab..a03160b1aaa1 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -27,4 +27,4 @@ "isBackground": true } ] -} \ No newline at end of file +} diff --git a/common/config/eslint/eslint.config.base.js b/common/config/eslint/eslint.config.base.js index bc6c6a1b745f..f26194f726bf 100644 --- a/common/config/eslint/eslint.config.base.js +++ b/common/config/eslint/eslint.config.base.js @@ -2,13 +2,13 @@ module.exports = [ { files: ["**/test/**/*.ts"], rules: { - "@itwin/no-internal-barrel-imports": "off" - } + "@itwin/no-internal-barrel-imports": "off", + }, }, { files: ["**/*.ts"], rules: { - "@typescript-eslint/no-unsafe-enum-comparison": "off" - } - } -] \ No newline at end of file + "@typescript-eslint/no-unsafe-enum-comparison": "off", + }, + }, +]; diff --git a/core/backend/eslint.config.js b/core/backend/eslint.config.js index 5059385bcb2f..2c571bff67f2 100644 --- a/core/backend/eslint.config.js +++ b/core/backend/eslint.config.js @@ -9,14 +9,14 @@ module.exports = [ { files: ["**/*.ts"], rules: { - "@typescript-eslint/no-non-null-assertion": "error" - } + "@typescript-eslint/no-non-null-assertion": "error", + }, }, { files: ["**/test/**/*.ts"], rules: { - "@typescript-eslint/no-non-null-assertion": "off" - } + "@typescript-eslint/no-non-null-assertion": "off", + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/backend/runUnitTestsIosSimulator.ts b/core/backend/runUnitTestsIosSimulator.ts index f8802db23fcb..c6c64b1b7292 100644 --- a/core/backend/runUnitTestsIosSimulator.ts +++ b/core/backend/runUnitTestsIosSimulator.ts @@ -9,7 +9,7 @@ import { createWriteStream } from "fs"; const Simctl = require("node-simctl").default; // Constants used in the script for convenience -const appName = "core-test-runner" +const appName = "core-test-runner"; const bundleId = `com.bentley.${appName}`; const xmlFilter = "[Mocha_Result_XML]: "; @@ -17,16 +17,16 @@ const xmlFilter = "[Mocha_Result_XML]: "; const numericCompareDescending = (a: string, b: string) => b.localeCompare(a, undefined, { numeric: true }); // Similar to the launchApp function but doesn't retry, adds options before the launch command, and allows for args. -Simctl.prototype.launchAppWithOptions = async function (bundleId: string, options: string[], args: string[]) { - const { stdout } = await this.exec('launch', { - args: [...options, this.requireUdid('launch'), bundleId, ...args], +Simctl.prototype.launchAppWithOptions = async function(bundleId: string, options: string[], args: string[]) { + const { stdout } = await this.exec("launch", { + args: [...options, this.requireUdid("launch"), bundleId, ...args], architectures: "x86_64", }); return stdout.trim(); -} +}; -Simctl.prototype.getLatestRuntimeVersion = async function (majorVersion: string, platform = 'iOS') { - const { stdout } = await this.exec('list', { args: ['runtimes', '--json'] }); +Simctl.prototype.getLatestRuntimeVersion = async function(majorVersion: string, platform = "iOS") { + const { stdout } = await this.exec("list", { args: ["runtimes", "--json"] }); const runtimes: [{ version: string, identifier: string, name: string }] = JSON.parse(stdout).runtimes; runtimes.sort((a, b) => numericCompareDescending(a.version, b.version)); for (const { version, name } of runtimes) { @@ -42,8 +42,8 @@ function log(message: string) { } function extractXML(xmlFilter: string, inputLog: string, outputXmlFile: string) { - const lines = inputLog.split(/\r?\n/) - const outputStream = createWriteStream(outputXmlFile) + const lines = inputLog.split(/\r?\n/); + const outputStream = createWriteStream(outputXmlFile); for (const line of lines) { if (line.includes(xmlFilter)) { @@ -55,7 +55,7 @@ function extractXML(xmlFilter: string, inputLog: string, outputXmlFile: string) outputStream.write(cleanedXmlLine + "\n", "utf-8"); // console.log(cleanedXmlLine); } - }; + } } async function main() { @@ -66,7 +66,7 @@ async function main() { // get all iOS devices log("Getting iOS devices"); - const allResults = await simctl.getDevices(undefined, 'iOS'); + const allResults = await simctl.getDevices(undefined, "iOS"); // If xcode-select picks an earlier Xcode, allResults can contain entries for newer iOS versions with // no actual data. The below filters out the empty entries. const results = Object.assign({}, ...Object.entries(allResults).filter(([_k, v]) => (v as [any]).length > 0).map(([k, v]) => ({ [k]: v }))); @@ -77,18 +77,18 @@ async function main() { var desiredDevice = `${deviceBaseName} (2nd generation)`; var desiredRuntime = keys.length > 0 ? keys[0] : "16"; - keys = keys.filter(key => key.startsWith(desiredRuntime)); - var device: { name: string; sdk: string; udid: string; state: string; } | undefined; + keys = keys.filter((key) => key.startsWith(desiredRuntime)); + var device: { name: string, sdk: string, udid: string, state: string } | undefined; if (keys.length) { // Look for a booted simulator for (const key of keys) { - device = results[key].find((curr: { state: string; }) => curr.state === "Booted"); + device = results[key].find((curr: { state: string }) => curr.state === "Booted"); if (device) break; } // If none are booted, use the deviceBaseName or fall back to the first one if (!device) { - device = results[keys[0]].find((device: { name: string; }) => device.name.startsWith(deviceBaseName)) ?? results[keys[0]][0]; + device = results[keys[0]].find((device: { name: string }) => device.name.startsWith(deviceBaseName)) ?? results[keys[0]][0]; } } else { // try to create a simulator @@ -100,12 +100,12 @@ async function main() { log(`Creating simulator: ${desiredDevice} sdk: ${sdk}`); const udid = await simctl.createDevice(desiredDevice, desiredDevice, sdk); if (udid) { - device = { name: desiredDevice, sdk, udid, state: 'Inactive' }; + device = { name: desiredDevice, sdk, udid, state: "Inactive" }; } } if (!device) { - log(`Unable to find an iOS ${desiredRuntime} simulator.`) + log(`Unable to find an iOS ${desiredRuntime} simulator.`); return; } diff --git a/core/backend/src/BackendHubAccess.ts b/core/backend/src/BackendHubAccess.ts index 1f1933cca413..042b6a47b1d1 100644 --- a/core/backend/src/BackendHubAccess.ts +++ b/core/backend/src/BackendHubAccess.ts @@ -8,16 +8,26 @@ import { AccessToken, GuidString, Id64String, IModelHubStatus } from "@itwin/core-bentley"; import { - BriefcaseId, ChangesetFileProps, ChangesetIdWithIndex, ChangesetIndex, ChangesetIndexAndId, ChangesetIndexOrId, ChangesetProps, ChangesetRange, - LockState as CommonLockState, IModelError, IModelVersion, - LocalDirName, LocalFileName, + BriefcaseId, + ChangesetFileProps, + ChangesetIdWithIndex, + ChangesetIndex, + ChangesetIndexAndId, + ChangesetIndexOrId, + ChangesetProps, + ChangesetRange, + IModelError, + IModelVersion, + LocalDirName, + LocalFileName, + LockState as CommonLockState, } from "@itwin/core-common"; import { CheckpointProps, DownloadRequest, ProgressFunction } from "./CheckpointManager"; import type { TokenArg } from "./IModelDb"; /** Exception thrown if lock cannot be acquired. * @beta -*/ + */ export class LockConflict extends IModelError { public constructor( /** Id of Briefcase holding lock */ @@ -209,8 +219,8 @@ export interface BackendHubAccess { getChangesetFromNamedVersion: (arg: IModelIdArg & { versionName: string }) => Promise; /** Acquire a new briefcaseId for the supplied iModelId - * @note usually there should only be one briefcase per iModel per user. - */ + * @note usually there should only be one briefcase per iModel per user. + */ acquireNewBriefcaseId: (arg: AcquireNewBriefcaseIdArg) => Promise; /** Release a briefcaseId. After this call it is illegal to generate changesets for the released briefcaseId. */ releaseBriefcase: (arg: BriefcaseIdArg) => Promise; diff --git a/core/backend/src/BisCoreSchema.ts b/core/backend/src/BisCoreSchema.ts index cf20ed787789..4301c18964be 100644 --- a/core/backend/src/BisCoreSchema.ts +++ b/core/backend/src/BisCoreSchema.ts @@ -9,6 +9,7 @@ import * as path from "path"; import * as categoryMod from "./Category"; import { ClassRegistry } from "./ClassRegistry"; +import * as displayStyleMod from "./DisplayStyle"; import * as elementMod from "./Element"; import * as aspectMod from "./ElementAspect"; import * as externalSourceMod from "./ExternalSource"; @@ -17,10 +18,9 @@ import * as materialMod from "./Material"; import * as modelMod from "./Model"; import * as linkMod from "./Relationship"; import { Schema, Schemas } from "./Schema"; +import * as annotationsMod from "./TextAnnotationElement"; import * as textureMod from "./Texture"; import * as viewMod from "./ViewDefinition"; -import * as displayStyleMod from "./DisplayStyle"; -import * as annotationsMod from "./TextAnnotationElement"; /** * The [BisCore]($docs/bis/guide/fundamentals/schemas-domains.md) schema is the lowest level Schema in an iModel. @@ -34,8 +34,12 @@ import * as annotationsMod from "./TextAnnotationElement"; * @public */ export class BisCoreSchema extends Schema { - public static override get schemaName(): string { return "BisCore"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Dgn", `${BisCoreSchema.schemaName}.ecschema.xml`); } + public static override get schemaName(): string { + return "BisCore"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Dgn", `${BisCoreSchema.schemaName}.ecschema.xml`); + } /** @internal */ public static registerSchema() { diff --git a/core/backend/src/BlobContainerService.ts b/core/backend/src/BlobContainerService.ts index e9c24d098b5b..4d5cfa1ab3d4 100644 --- a/core/backend/src/BlobContainerService.ts +++ b/core/backend/src/BlobContainerService.ts @@ -16,7 +16,6 @@ import { SettingsContainer } from "./workspace/Settings"; * @beta */ export namespace BlobContainer { - /** Object that implements the methods to create, delete, and request access to a container. */ export let service: BlobContainer.ContainerService | undefined; @@ -115,7 +114,7 @@ export namespace BlobContainer { export type RequestAccessLevel = "write" | "read" | "admin" | "writeIfPossible"; /** Information required to request an access token for a container. */ - export interface RequestTokenProps extends Omit { + export interface RequestTokenProps extends Omit { /** the level of access requested. If not specified, defaults to `"writeIfPossible"`. */ accessLevel?: RequestAccessLevel; /** the number of seconds before the token should expire. diff --git a/core/backend/src/BriefcaseManager.ts b/core/backend/src/BriefcaseManager.ts index 9dfe6a08426e..2bc533320421 100644 --- a/core/backend/src/BriefcaseManager.ts +++ b/core/backend/src/BriefcaseManager.ts @@ -8,29 +8,51 @@ // cspell:ignore cset csets ecchanges -import * as path from "path"; import { - AccessToken, BeDuration, ChangeSetStatus, GuidString, IModelHubStatus, IModelStatus, Logger, OpenMode, Optional, StopWatch, + AccessToken, + BeDuration, + ChangeSetStatus, + GuidString, + IModelHubStatus, + IModelStatus, + Logger, + OpenMode, + Optional, + StopWatch, } from "@itwin/core-bentley"; import { - BriefcaseId, BriefcaseIdValue, BriefcaseProps, ChangesetFileProps, ChangesetIndex, ChangesetIndexOrId, ChangesetProps, ChangesetRange, ChangesetType, IModelError, IModelVersion, LocalBriefcaseProps, - LocalDirName, LocalFileName, RequestNewBriefcaseProps, + BriefcaseId, + BriefcaseIdValue, + BriefcaseProps, + ChangesetFileProps, + ChangesetIndex, + ChangesetIndexOrId, + ChangesetProps, + ChangesetRange, + ChangesetType, + IModelError, + IModelVersion, + LocalBriefcaseProps, + LocalDirName, + LocalFileName, + RequestNewBriefcaseProps, } from "@itwin/core-common"; +import * as path from "path"; import { AcquireNewBriefcaseIdArg, IModelNameArg } from "./BackendHubAccess"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { CheckpointManager, CheckpointProps, ProgressFunction } from "./CheckpointManager"; import { BriefcaseDb, IModelDb, TokenArg } from "./IModelDb"; import { IModelHost } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; -import { SchemaSync } from "./SchemaSync"; -import { _nativeDb, _releaseAllLocks } from "./internal/Symbols"; import { IModelNative } from "./internal/NativePlatform"; +import { _nativeDb, _releaseAllLocks } from "./internal/Symbols"; +import { SchemaSync } from "./SchemaSync"; const loggerCategory = BackendLoggerCategory.IModelDb; /** The argument for [[BriefcaseManager.downloadBriefcase]] * @public -*/ + */ export interface RequestNewBriefcaseArg extends TokenArg, RequestNewBriefcaseProps { /** If present, a function called periodically during the download to indicate progress. * @note return non-zero from this function to abort the download. @@ -95,16 +117,24 @@ export type RevertChangesArgs = Optional & { */ export class BriefcaseManager { /** Get the local path of the folder storing files that are associated with an imodel */ - public static getIModelPath(iModelId: GuidString): LocalDirName { return path.join(this._cacheDir, iModelId); } + public static getIModelPath(iModelId: GuidString): LocalDirName { + return path.join(this._cacheDir, iModelId); + } /** @internal */ - public static getChangeSetsPath(iModelId: GuidString): LocalDirName { return path.join(this.getIModelPath(iModelId), "changesets"); } + public static getChangeSetsPath(iModelId: GuidString): LocalDirName { + return path.join(this.getIModelPath(iModelId), "changesets"); + } /** @internal */ - public static getChangeCachePathName(iModelId: GuidString): LocalFileName { return path.join(this.getIModelPath(iModelId), iModelId.concat(".bim.ecchanges")); } + public static getChangeCachePathName(iModelId: GuidString): LocalFileName { + return path.join(this.getIModelPath(iModelId), iModelId.concat(".bim.ecchanges")); + } /** @internal */ - public static getChangedElementsPathName(iModelId: GuidString): LocalFileName { return path.join(this.getIModelPath(iModelId), iModelId.concat(".bim.elems")); } + public static getChangedElementsPathName(iModelId: GuidString): LocalFileName { + return path.join(this.getIModelPath(iModelId), iModelId.concat(".bim.elems")); + } private static _briefcaseSubDir = "briefcases"; /** Get the local path of the folder storing briefcases associated with the specified iModel. */ @@ -170,7 +200,14 @@ export class BriefcaseManager { const fileName = path.join(bcPath, briefcaseName); const fileSize = IModelJsFs.lstatSync(fileName)?.size ?? 0; const db = IModelDb.openDgnDb({ path: fileName }, OpenMode.Readonly); - briefcaseList.push({ fileName, iTwinId: db.getITwinId(), iModelId: db.getIModelId(), briefcaseId: db.getBriefcaseId(), changeset: db.getCurrentChangeset(), fileSize }); + briefcaseList.push({ + fileName, + iTwinId: db.getITwinId(), + iModelId: db.getIModelId(), + briefcaseId: db.getBriefcaseId(), + changeset: db.getCurrentChangeset(), + fileSize, + }); db.closeFile(); } catch (_err) { } @@ -182,7 +219,9 @@ export class BriefcaseManager { private static _cacheDir: LocalDirName; /** Get the root directory for the briefcase cache */ - public static get cacheDir(): LocalDirName { return this._cacheDir; } + public static get cacheDir(): LocalDirName { + return this._cacheDir; + } /** Determine whether the supplied briefcaseId is in the range of assigned BriefcaseIds issued by iModelHub * @note this does check whether the id was actually acquired by the caller. @@ -388,7 +427,9 @@ export class BriefcaseManager { const files = IModelJsFs.readdirSync(folderPathname); for (const file of files) { const curPath = path.join(folderPathname, file); - const locStatus = (IModelJsFs.lstatSync(curPath)?.isDirectory) ? BriefcaseManager.deleteFolderAndContents(curPath) : BriefcaseManager.deleteFile(curPath); + const locStatus = (IModelJsFs.lstatSync(curPath)?.isDirectory) + ? BriefcaseManager.deleteFolderAndContents(curPath) + : BriefcaseManager.deleteFile(curPath); if (!locStatus) status = false; } @@ -453,7 +494,9 @@ export class BriefcaseManager { let currentIndex = db.changeset.index; if (currentIndex === undefined) - currentIndex = (await IModelHost.hubAccess.queryChangeset({ accessToken: arg.accessToken, iModelId: db.iModelId, changeset: { id: db.changeset.id } })).index; + currentIndex = + (await IModelHost.hubAccess.queryChangeset({ accessToken: arg.accessToken, iModelId: db.iModelId, changeset: { id: db.changeset.id } })) + .index; if (!arg.toIndex) { throw new IModelError(ChangeSetStatus.ApplyError, "toIndex must be specified to revert changesets"); @@ -506,7 +549,9 @@ export class BriefcaseManager { let currentIndex = db.changeset.index; if (currentIndex === undefined) - currentIndex = (await IModelHost.hubAccess.queryChangeset({ accessToken: arg.accessToken, iModelId: db.iModelId, changeset: { id: db.changeset.id } })).index; + currentIndex = + (await IModelHost.hubAccess.queryChangeset({ accessToken: arg.accessToken, iModelId: db.iModelId, changeset: { id: db.changeset.id } })) + .index; const reverse = (arg.toIndex && arg.toIndex < currentIndex) ? true : false; @@ -592,10 +637,9 @@ export class BriefcaseManager { return await BriefcaseManager.pushChanges(db, arg); } catch (err: any) { if (retryCount-- <= 0 || err.errorNumber !== IModelHubStatus.PullIsRequired) - throw (err); + throw err; await (arg.mergeRetryDelay ?? BeDuration.fromSeconds(3)).wait(); } } } - } diff --git a/core/backend/src/Category.ts b/core/backend/src/Category.ts index 50cf1b0d9d2a..e3ea25098811 100644 --- a/core/backend/src/Category.ts +++ b/core/backend/src/Category.ts @@ -8,7 +8,15 @@ import { Id64, Id64String, JsonUtils } from "@itwin/core-bentley"; import { - BisCodeSpec, CategoryProps, Code, CodeScopeProps, CodeSpec, ElementProps, Rank, SubCategoryAppearance, SubCategoryProps, + BisCodeSpec, + CategoryProps, + Code, + CodeScopeProps, + CodeSpec, + ElementProps, + Rank, + SubCategoryAppearance, + SubCategoryProps, } from "@itwin/core-common"; import { DefinitionElement } from "./Element"; import { IModelDb } from "./IModelDb"; @@ -18,7 +26,9 @@ import { CategoryOwnsSubCategories } from "./NavigationRelationship"; * @public */ export class SubCategory extends DefinitionElement { - public static override get className(): string { return "SubCategory"; } + public static override get className(): string { + return "SubCategory"; + } /** The Appearance parameters for this SubCategory */ public appearance: SubCategoryAppearance; /** Optional description of this SubCategory. */ @@ -39,13 +49,21 @@ export class SubCategory extends DefinitionElement { } /** Get the SubCategory's name (its Code value). */ - public getSubCategoryName(): string { return this.code.value; } + public getSubCategoryName(): string { + return this.code.value; + } /** Get the Id of the SubCategory. */ - public getSubCategoryId(): Id64String { return this.id; } + public getSubCategoryId(): Id64String { + return this.id; + } /** Get the Id of this SubCategory's parent Category. */ - public getCategoryId(): Id64String { return this.parent ? this.parent.id : Id64.invalid; } + public getCategoryId(): Id64String { + return this.parent ? this.parent.id : Id64.invalid; + } /** Check if this is the default SubCategory of its parent Category. */ - public get isDefaultSubCategory(): boolean { return IModelDb.getDefaultSubCategoryId(this.getCategoryId()) === this.getSubCategoryId(); } + public get isDefaultSubCategory(): boolean { + return IModelDb.getDefaultSubCategoryId(this.getCategoryId()) === this.getSubCategoryId(); + } /** Create a Code for a SubCategory given a name that is meant to be unique within the scope of the specified parent Category. * @param iModel The IModel @@ -65,7 +83,12 @@ export class SubCategory extends DefinitionElement { * @returns The newly constructed SubCategory element. * @throws [[IModelError]] if unable to create the element. */ - public static create(iModelDb: IModelDb, parentCategoryId: Id64String, name: string, appearance: SubCategoryAppearance.Props | SubCategoryAppearance): SubCategory { + public static create( + iModelDb: IModelDb, + parentCategoryId: Id64String, + name: string, + appearance: SubCategoryAppearance.Props | SubCategoryAppearance, + ): SubCategory { if (appearance instanceof SubCategoryAppearance) appearance = appearance.toJSON(); @@ -88,7 +111,12 @@ export class SubCategory extends DefinitionElement { * @returns The Id of the newly inserted SubCategory element. * @throws [[IModelError]] if unable to insert the element. */ - public static insert(iModelDb: IModelDb, parentCategoryId: Id64String, name: string, appearance: SubCategoryAppearance.Props | SubCategoryAppearance): Id64String { + public static insert( + iModelDb: IModelDb, + parentCategoryId: Id64String, + name: string, + appearance: SubCategoryAppearance.Props | SubCategoryAppearance, + ): Id64String { const subCategory = this.create(iModelDb, parentCategoryId, name, appearance); return iModelDb.elements.insertElement(subCategory.toJSON()); } @@ -98,7 +126,9 @@ export class SubCategory extends DefinitionElement { * @public */ export class Category extends DefinitionElement { - public static override get className(): string { return "Category"; } + public static override get className(): string { + return "Category"; + } public rank: Rank = Rank.User; public description?: string; @@ -117,7 +147,9 @@ export class Category extends DefinitionElement { } /** Get the Id of the default SubCategory for this Category. */ - public myDefaultSubCategoryId(): Id64String { return IModelDb.getDefaultSubCategoryId(this.id); } + public myDefaultSubCategoryId(): Id64String { + return IModelDb.getDefaultSubCategoryId(this.id); + } /** Set the appearance of the default SubCategory for this Category */ public setDefaultAppearance(props: SubCategoryAppearance.Props | SubCategoryAppearance): void { @@ -134,12 +166,18 @@ export class Category extends DefinitionElement { * @public */ export class DrawingCategory extends Category { - public static override get className(): string { return "DrawingCategory"; } + public static override get className(): string { + return "DrawingCategory"; + } - protected constructor(opts: ElementProps, iModel: IModelDb) { super(opts, iModel); } + protected constructor(opts: ElementProps, iModel: IModelDb) { + super(opts, iModel); + } /** Get the name of the CodeSpec that is used by DrawingCategory objects. */ - public static getCodeSpecName(): string { return BisCodeSpec.drawingCategory; } + public static getCodeSpecName(): string { + return BisCodeSpec.drawingCategory; + } /** Looks up the CategoryId of a DrawingCategory by model and name */ public static queryCategoryIdByName(iModel: IModelDb, scopeModelId: Id64String, categoryName: string): Id64String | undefined { @@ -183,7 +221,12 @@ export class DrawingCategory extends Category { * @returns The Id of the newly inserted DrawingCategory element. * @throws [[IModelError]] if unable to insert the element. */ - public static insert(iModelDb: IModelDb, definitionModelId: Id64String, name: string, defaultAppearance: SubCategoryAppearance.Props | SubCategoryAppearance): Id64String { + public static insert( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + defaultAppearance: SubCategoryAppearance.Props | SubCategoryAppearance, + ): Id64String { const category = this.create(iModelDb, definitionModelId, name); const elements = iModelDb.elements; category.id = elements.insertElement(category.toJSON()); @@ -196,11 +239,17 @@ export class DrawingCategory extends Category { * @public */ export class SpatialCategory extends Category { - public static override get className(): string { return "SpatialCategory"; } - protected constructor(opts: ElementProps, iModel: IModelDb) { super(opts, iModel); } + public static override get className(): string { + return "SpatialCategory"; + } + protected constructor(opts: ElementProps, iModel: IModelDb) { + super(opts, iModel); + } /** Get the name of the CodeSpec that is used by SpatialCategory objects. */ - public static getCodeSpecName(): string { return BisCodeSpec.spatialCategory; } + public static getCodeSpecName(): string { + return BisCodeSpec.spatialCategory; + } /** Looks up the CategoryId of a SpatialCategory by model and name */ public static queryCategoryIdByName(iModel: IModelDb, scopeModelId: Id64String, categoryName: string): Id64String | undefined { @@ -244,7 +293,12 @@ export class SpatialCategory extends Category { * @returns The Id of the newly inserted SpatialCategory element. * @throws [[IModelError]] if unable to insert the element. */ - public static insert(iModelDb: IModelDb, definitionModelId: Id64String, name: string, defaultAppearance: SubCategoryAppearance.Props | SubCategoryAppearance): Id64String { + public static insert( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + defaultAppearance: SubCategoryAppearance.Props | SubCategoryAppearance, + ): Id64String { const category = this.create(iModelDb, definitionModelId, name); category.id = iModelDb.elements.insertElement(category.toJSON()); category.setDefaultAppearance(defaultAppearance); diff --git a/core/backend/src/ChangeSummaryManager.ts b/core/backend/src/ChangeSummaryManager.ts index fb8cce70ca97..bd075b2494b9 100644 --- a/core/backend/src/ChangeSummaryManager.ts +++ b/core/backend/src/ChangeSummaryManager.ts @@ -165,37 +165,51 @@ export class ChangeSummaryManager { private static openChangeCacheFile(changesFile: ECDb, changeCacheFilePath: string): void { changesFile.openDb(changeCacheFilePath, ECDbOpenMode.FileUpgrade); - const actualSchemaVersion: { read: number, write: number, minor: number } = changesFile.withPreparedStatement("SELECT VersionMajor read,VersionWrite write,VersionMinor minor FROM meta.ECSchemaDef WHERE Name='IModelChange'", + const actualSchemaVersion: { read: number, write: number, minor: number } = changesFile.withPreparedStatement( + "SELECT VersionMajor read,VersionWrite write,VersionMinor minor FROM meta.ECSchemaDef WHERE Name='IModelChange'", (stmt: ECSqlStatement) => { if (stmt.step() !== DbResult.BE_SQLITE_ROW) throw new IModelError(DbResult.BE_SQLITE_ERROR, "File is not a valid Change Cache file."); return stmt.getRow(); - }); + }, + ); - if (actualSchemaVersion.read === ChangeSummaryManager._currentIModelChangeSchemaVersion.read && + if ( + actualSchemaVersion.read === ChangeSummaryManager._currentIModelChangeSchemaVersion.read && actualSchemaVersion.write === ChangeSummaryManager._currentIModelChangeSchemaVersion.write && - actualSchemaVersion.minor === ChangeSummaryManager._currentIModelChangeSchemaVersion.minor) + actualSchemaVersion.minor === ChangeSummaryManager._currentIModelChangeSchemaVersion.minor + ) return; changesFile.importSchema(ChangeSummaryManager.getExtendedSchemaPath()); } - private static getExtendedSchemaPath(): string { return path.join(KnownLocations.packageAssetsDir, "IModelChange.02.00.00.ecschema.xml"); } + private static getExtendedSchemaPath(): string { + return path.join(KnownLocations.packageAssetsDir, "IModelChange.02.00.00.ecschema.xml"); + } private static isSummaryAlreadyExtracted(changesFile: ECDb, changeSetId: GuidString): Id64String | undefined { - return changesFile.withPreparedStatement("SELECT Summary.Id summaryid FROM imodelchange.ChangeSet WHERE WsgId=?", - (stmt: ECSqlStatement) => { - stmt.bindString(1, changeSetId); - if (DbResult.BE_SQLITE_ROW === stmt.step()) - return stmt.getValue(0).getId(); + return changesFile.withPreparedStatement("SELECT Summary.Id summaryid FROM imodelchange.ChangeSet WHERE WsgId=?", (stmt: ECSqlStatement) => { + stmt.bindString(1, changeSetId); + if (DbResult.BE_SQLITE_ROW === stmt.step()) + return stmt.getValue(0).getId(); - return undefined; - }); + return undefined; + }); } - private static addExtendedInfos(changesFile: ECDb, changeSummaryId: Id64String, changesetWsgId: GuidString, changesetParentWsgId?: GuidString, description?: string, changesetPushDate?: string, changeSetUserCreated?: GuidString): void { - changesFile.withPreparedStatement("INSERT INTO imodelchange.ChangeSet(Summary.Id,WsgId,ParentWsgId,Description,PushDate,UserCreated) VALUES(?,?,?,?,?,?)", + private static addExtendedInfos( + changesFile: ECDb, + changeSummaryId: Id64String, + changesetWsgId: GuidString, + changesetParentWsgId?: GuidString, + description?: string, + changesetPushDate?: string, + changeSetUserCreated?: GuidString, + ): void { + changesFile.withPreparedStatement( + "INSERT INTO imodelchange.ChangeSet(Summary.Id,WsgId,ParentWsgId,Description,PushDate,UserCreated) VALUES(?,?,?,?,?,?)", (stmt: ECSqlStatement) => { stmt.bindId(1, changeSummaryId); stmt.bindString(2, changesetWsgId); @@ -214,7 +228,8 @@ export class ChangeSummaryManager { const r: DbResult = stmt.step(); if (r !== DbResult.BE_SQLITE_DONE) throw new IModelError(r, `Failed to add changeset information to extracted change summary ${changeSummaryId}`); - }); + }, + ); } /** Queries the ChangeSummary for the specified change summary id @@ -232,15 +247,26 @@ export class ChangeSummaryManager { if (!ChangeSummaryManager.isChangeCacheAttached(iModel)) throw new IModelError(IModelStatus.BadArg, "Change Cache file must be attached to iModel."); - return iModel.withPreparedStatement("SELECT WsgId,ParentWsgId,Description,PushDate,UserCreated FROM ecchange.imodelchange.ChangeSet WHERE Summary.Id=?", + return iModel.withPreparedStatement( + "SELECT WsgId,ParentWsgId,Description,PushDate,UserCreated FROM ecchange.imodelchange.ChangeSet WHERE Summary.Id=?", (stmt: ECSqlStatement) => { stmt.bindId(1, changeSummaryId); if (stmt.step() !== DbResult.BE_SQLITE_ROW) throw new IModelError(IModelStatus.BadArg, `No ChangeSet information found for ChangeSummary ${changeSummaryId}.`); const row = stmt.getRow(); - return { id: changeSummaryId, changeSet: { wsgId: row.wsgId, parentWsgId: row.parentWsgId, description: row.description, pushDate: row.pushDate, userCreated: row.userCreated } }; - }); + return { + id: changeSummaryId, + changeSet: { + wsgId: row.wsgId, + parentWsgId: row.parentWsgId, + description: row.description, + pushDate: row.pushDate, + userCreated: row.userCreated, + }, + }; + }, + ); } /** Queries the InstanceChange for the specified instance change id. @@ -259,23 +285,29 @@ export class ChangeSummaryManager { throw new IModelError(IModelStatus.BadArg, "Change Cache file must be attached to iModel."); // query instance changes - const instanceChange: InstanceChange = iModel.withPreparedStatement(`SELECT ic.Summary.Id summaryId, s.Name changedInstanceSchemaName, c.Name changedInstanceClassName, ic.ChangedInstance.Id changedInstanceId, + const instanceChange: InstanceChange = iModel.withPreparedStatement( + `SELECT ic.Summary.Id summaryId, s.Name changedInstanceSchemaName, c.Name changedInstanceClassName, ic.ChangedInstance.Id changedInstanceId, ic.OpCode, ic.IsIndirect FROM ecchange.change.InstanceChange ic JOIN main.meta.ECClassDef c ON c.ECInstanceId = ic.ChangedInstance.ClassId - JOIN main.meta.ECSchemaDef s ON c.Schema.Id = s.ECInstanceId WHERE ic.ECInstanceId =? `, (stmt: ECSqlStatement) => { - stmt.bindId(1, instanceChangeId); - if (stmt.step() !== DbResult.BE_SQLITE_ROW) - throw new IModelError(IModelStatus.BadArg, `No InstanceChange found for id ${instanceChangeId}.`); - - const row = stmt.getRow(); - const changedInstanceId: Id64String = row.changedInstanceId; - const changedInstanceClassName: string = `[${row.changedInstanceSchemaName}].[${row.changedInstanceClassName}]`; - const op: ChangeOpCode = row.opCode as ChangeOpCode; - - return { - id: instanceChangeId, summaryId: row.summaryId, changedInstance: { id: changedInstanceId, className: changedInstanceClassName }, - opCode: op, isIndirect: row.isIndirect, - }; - }); + JOIN main.meta.ECSchemaDef s ON c.Schema.Id = s.ECInstanceId WHERE ic.ECInstanceId =? `, + (stmt: ECSqlStatement) => { + stmt.bindId(1, instanceChangeId); + if (stmt.step() !== DbResult.BE_SQLITE_ROW) + throw new IModelError(IModelStatus.BadArg, `No InstanceChange found for id ${instanceChangeId}.`); + + const row = stmt.getRow(); + const changedInstanceId: Id64String = row.changedInstanceId; + const changedInstanceClassName: string = `[${row.changedInstanceSchemaName}].[${row.changedInstanceClassName}]`; + const op: ChangeOpCode = row.opCode as ChangeOpCode; + + return { + id: instanceChangeId, + summaryId: row.summaryId, + changedInstance: { id: changedInstanceId, className: changedInstanceClassName }, + opCode: op, + isIndirect: row.isIndirect, + }; + }, + ); return instanceChange; } @@ -289,7 +321,8 @@ export class ChangeSummaryManager { * @throws [IModelError]($common) if the change cache file hasn't been attached, or in case of other errors. */ public static getChangedPropertyValueNames(iModel: IModelDb, instanceChangeId: Id64String): string[] { - return iModel.withPreparedStatement("SELECT AccessString FROM ecchange.change.PropertyValueChange WHERE InstanceChange.Id=?", + return iModel.withPreparedStatement( + "SELECT AccessString FROM ecchange.change.PropertyValueChange WHERE InstanceChange.Id=?", (stmt: ECSqlStatement) => { stmt.bindId(1, instanceChangeId); @@ -313,7 +346,8 @@ export class ChangeSummaryManager { } return selectClauseItems; - }); + }, + ); } /** Builds the ECSQL to query the property value changes for the specified instance change and the specified ChangedValueState. @@ -332,7 +366,12 @@ export class ChangeSummaryManager { * @throws [IModelError]($common) if instance change does not exist, if there are not property value changes for the instance change, * if the change cache file hasn't been attached, or in case of other errors. */ - public static buildPropertyValueChangesECSql(iModel: IModelDb, instanceChangeInfo: { id: Id64String, summaryId: Id64String, changedInstance: { id: Id64String, className: string } }, changedValueState: ChangedValueState, changedPropertyNames?: string[]): string { + public static buildPropertyValueChangesECSql( + iModel: IModelDb, + instanceChangeInfo: { id: Id64String, summaryId: Id64String, changedInstance: { id: Id64String, className: string } }, + changedValueState: ChangedValueState, + changedPropertyNames?: string[], + ): string { let selectClauseItems: string[]; if (!changedPropertyNames) { // query property value changes just to build a SELECT statement against the class of the changed instance @@ -353,7 +392,8 @@ export class ChangeSummaryManager { // Avoiding parameters in the Changes function speeds up performance because ECDb can do optimizations // if it knows the function args at prepare time - ecsql += ` FROM main.${instanceChangeInfo.changedInstance.className}.Changes(${instanceChangeInfo.summaryId},${changedValueState}) WHERE ECInstanceId=${instanceChangeInfo.changedInstance.id}`; + ecsql += + ` FROM main.${instanceChangeInfo.changedInstance.className}.Changes(${instanceChangeInfo.summaryId},${changedValueState}) WHERE ECInstanceId=${instanceChangeInfo.changedInstance.id}`; return ecsql; } @@ -375,7 +415,12 @@ export class ChangeSummaryManager { const iModelId = iModel.iModelId; const changesetsFolder: string = BriefcaseManager.getChangeSetsPath(iModelId); - const changeset = await IModelHost.hubAccess.downloadChangeset({ accessToken: IModelHost.authorizationClient ? undefined : accessToken, iModelId, changeset: { id: iModel.changeset.id }, targetDir: changesetsFolder }); + const changeset = await IModelHost.hubAccess.downloadChangeset({ + accessToken: IModelHost.authorizationClient ? undefined : accessToken, + iModelId, + changeset: { id: iModel.changeset.id }, + targetDir: changesetsFolder, + }); if (!IModelJsFs.existsSync(changeset.pathname)) throw new IModelError(IModelStatus.FileNotFound, `Failed to download change set: ${changeset.pathname}`); @@ -387,7 +432,11 @@ export class ChangeSummaryManager { let changeSummaryId = ChangeSummaryManager.isSummaryAlreadyExtracted(changesFile, changesetId); if (changeSummaryId !== undefined) { - Logger.logInfo(loggerCategory, `Change Summary for changeset already exists. It is not extracted again.`, () => ({ iModelId, changeSetId: changesetId })); + Logger.logInfo( + loggerCategory, + `Change Summary for changeset already exists. It is not extracted again.`, + () => ({ iModelId, changeSetId: changesetId }), + ); return changeSummaryId; } @@ -397,7 +446,15 @@ export class ChangeSummaryManager { assert(undefined !== stat.result); changeSummaryId = stat.result; - ChangeSummaryManager.addExtendedInfos(changesFile, changeSummaryId, changesetId, changeset.parentId, changeset.description, changeset.pushDate, changeset.userCreated); + ChangeSummaryManager.addExtendedInfos( + changesFile, + changeSummaryId, + changesetId, + changeset.parentId, + changeset.description, + changeset.pushDate, + changeset.userCreated, + ); changesFile.saveChanges(); return changeSummaryId; @@ -434,7 +491,14 @@ export class ChangeSummaryManager { let iModel: BriefcaseDb | undefined; try { // Download a version that has the first change set applied - const props = await BriefcaseManager.downloadBriefcase({ accessToken, iTwinId, iModelId, asOf: { afterChangeSetId: changesets[0].id }, briefcaseId: 0, fileName }); + const props = await BriefcaseManager.downloadBriefcase({ + accessToken, + iTwinId, + iModelId, + asOf: { afterChangeSetId: changesets[0].id }, + briefcaseId: 0, + fileName, + }); iModel = await BriefcaseDb.open({ fileName: props.fileName }); const summaryIds = new Array(); diff --git a/core/backend/src/ChangedElementsDb.ts b/core/backend/src/ChangedElementsDb.ts index 22fa9feefe54..82afc3c96545 100644 --- a/core/backend/src/ChangedElementsDb.ts +++ b/core/backend/src/ChangedElementsDb.ts @@ -6,9 +6,9 @@ * @module ChangedElementsDb */ +import { IModelJsNative } from "@bentley/imodeljs-native"; import { AccessToken, DbResult, IDisposable, IModelStatus, OpenMode } from "@itwin/core-bentley"; import { ChangeData, ChangedElements, ChangedModels, IModelError } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; import { BriefcaseManager } from "./BriefcaseManager"; import { ECDbOpenMode } from "./ECDb"; import { IModelDb } from "./IModelDb"; @@ -19,7 +19,7 @@ import { _nativeDb } from "./internal/Symbols"; /** * Options for processChangesets function * @internal - * */ + */ export interface ProcessChangesetOptions { startChangesetId: string; endChangesetId: string; @@ -107,7 +107,12 @@ export class ChangedElementsDb implements IDisposable { const iModelId = briefcase.iModelId; const first = (await IModelHost.hubAccess.queryChangeset({ iModelId, changeset: { id: options.startChangesetId }, accessToken })).index; const end = (await IModelHost.hubAccess.queryChangeset({ iModelId, changeset: { id: options.endChangesetId }, accessToken })).index; - const changesets = await IModelHost.hubAccess.downloadChangesets({ accessToken, iModelId, range: { first, end }, targetDir: BriefcaseManager.getChangeSetsPath(iModelId) }); + const changesets = await IModelHost.hubAccess.downloadChangesets({ + accessToken, + iModelId, + range: { first, end }, + targetDir: BriefcaseManager.getChangeSetsPath(iModelId), + }); // ChangeSets need to be processed from newest to oldest changesets.reverse(); @@ -136,7 +141,12 @@ export class ChangedElementsDb implements IDisposable { const iModelId = briefcase.iModelId; const first = (await IModelHost.hubAccess.queryChangeset({ iModelId, changeset: { id: options.startChangesetId }, accessToken })).index; const end = (await IModelHost.hubAccess.queryChangeset({ iModelId, changeset: { id: options.endChangesetId }, accessToken })).index; - const changesets = await IModelHost.hubAccess.downloadChangesets({ accessToken, iModelId, range: { first, end }, targetDir: BriefcaseManager.getChangeSetsPath(iModelId) }); + const changesets = await IModelHost.hubAccess.downloadChangesets({ + accessToken, + iModelId, + range: { first, end }, + targetDir: BriefcaseManager.getChangeSetsPath(iModelId), + }); // ChangeSets need to be processed from newest to oldest changesets.reverse(); @@ -205,10 +215,14 @@ export class ChangedElementsDb implements IDisposable { } /** Returns true if the Changed Elements Db is open */ - public get isOpen(): boolean { return this.nativeDb.isOpen(); } + public get isOpen(): boolean { + return this.nativeDb.isOpen(); + } /** Returns true if the cache already contains this changeset Id */ - public isProcessed(changesetId: string): boolean { return this.nativeDb.isProcessed(changesetId); } + public isProcessed(changesetId: string): boolean { + return this.nativeDb.isProcessed(changesetId); + } /** Close the Db after saving any uncommitted changes. * @throws [IModelError]($common) if the database is not open. diff --git a/core/backend/src/ChangedElementsManager.ts b/core/backend/src/ChangedElementsManager.ts index ca8721d69a2a..75a2e1cb8197 100644 --- a/core/backend/src/ChangedElementsManager.ts +++ b/core/backend/src/ChangedElementsManager.ts @@ -24,7 +24,9 @@ export class ChangedElementsManager { /** Maintains a single entry since we will only have a cache per iModel, which means a ChangedElementsDb per backend instance */ private static _entry: ChangedElementsDbCacheEntry | undefined; - public static getChangedElementsPathName(iModelId: GuidString): string { return BriefcaseManager.getChangedElementsPathName(iModelId); } + public static getChangedElementsPathName(iModelId: GuidString): string { + return BriefcaseManager.getChangedElementsPathName(iModelId); + } /** Get changed elements Db */ private static getChangedElementsDb(iModelId: GuidString): ChangedElementsDb | undefined { diff --git a/core/backend/src/ChangesetECAdaptor.ts b/core/backend/src/ChangesetECAdaptor.ts index 11623f218e89..ccd4ed2ae244 100644 --- a/core/backend/src/ChangesetECAdaptor.ts +++ b/core/backend/src/ChangesetECAdaptor.ts @@ -37,7 +37,6 @@ interface IProperty { readonly structClass?: IClassRef; readonly dateTimeInfo?: IDateTimeInfo; readonly columns: IColumn[]; - } interface IColumn { @@ -60,7 +59,7 @@ interface ITable { class ECDbMap { private _cachedClassMaps = new Map(); private _cacheTables = new Map(); - public constructor(public readonly db: AnyDb) { } + public constructor(public readonly db: AnyDb) {} public getAllDerivedClasses(classFullName: string) { const sql = ` SELECT format('0x%x', ch.ClassId) @@ -349,7 +348,7 @@ class ECDbMap { /** * Record meta data for the change. * @beta - * */ + */ export interface ChangeMetaData { /** list of tables making up this EC change */ tables: string[]; @@ -381,7 +380,7 @@ export interface ChangedECInstance { /** * Helper function to convert between JS DateTime & SQLite JulianDay values. * @beta - * */ + */ namespace DateTime { /** * Convert JS date to JulianDay value. @@ -544,7 +543,9 @@ export class PartialECChangeUnifier { * Returns complete EC change instances. * @beta */ - public get instances(): IterableIterator { return this._cache.values(); } + public get instances(): IterableIterator { + return this._cache.values(); + } } /** @@ -552,8 +553,7 @@ export class PartialECChangeUnifier { * it is per table while a single instance can span multiple table. * @note PrimitiveArray and StructArray are not supported types. * @beta - * -*/ + */ export class ChangesetECAdaptor implements IDisposable { private readonly _mapCache: ECDbMap; private readonly _tableFilter = new Set(); @@ -661,8 +661,9 @@ export class ChangesetECAdaptor implements IDisposable { // Convert each element to a two-digit hexadecimal string const hex = Array.from(binaryGUID, (byte) => byte.toString(16).padStart(2, "0")); // Join the hexadecimal strings and insert hyphens - return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10, 16).join("")}`; - + return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${ + hex.slice(10, 16).join("") + }`; } /** * Set value use access string in a JS object. @@ -714,13 +715,21 @@ export class ChangesetECAdaptor implements IDisposable { } } /** helper method around reader.op */ - public get op() { return this.reader.op; } + public get op() { + return this.reader.op; + } /** Return true if current change is of type "Inserted" */ - public get isInserted() { return this.op === "Inserted"; } + public get isInserted() { + return this.op === "Inserted"; + } /** Return true if current change is of type "Deleted" */ - public get isDeleted() { return this.op === "Deleted"; } + public get isDeleted() { + return this.op === "Deleted"; + } /** Return true if current change is of type "Updated" */ - public get isUpdated() { return this.op === "Updated"; } + public get isUpdated() { + return this.op === "Updated"; + } /** * Advance reader to next change or a change that meets the filter set in the current adaptor @@ -897,7 +906,11 @@ export class ChangesetECAdaptor implements IDisposable { continue; } if (prop.extendedTypeName === "BeGuid") { - ChangesetECAdaptor.setValue(out, col.accessString, this.debugFlags.replaceGuidWithEllipsis ? "..." : ChangesetECAdaptor.convertBinaryToGuid(columnValue)); + ChangesetECAdaptor.setValue( + out, + col.accessString, + this.debugFlags.replaceGuidWithEllipsis ? "..." : ChangesetECAdaptor.convertBinaryToGuid(columnValue), + ); continue; } if (prop.extendedTypeName === "GeometryStream") { diff --git a/core/backend/src/ChannelControl.ts b/core/backend/src/ChannelControl.ts index f604e5305139..c50545d44f70 100644 --- a/core/backend/src/ChannelControl.ts +++ b/core/backend/src/ChannelControl.ts @@ -72,4 +72,3 @@ export namespace ChannelControl { /** the name of the special "shared" channel holding information that is editable by any application. */ export const sharedChannelName = "shared"; } - diff --git a/core/backend/src/CheckpointManager.ts b/core/backend/src/CheckpointManager.ts index 7537c002e1a6..f8709a7c1062 100644 --- a/core/backend/src/CheckpointManager.ts +++ b/core/backend/src/CheckpointManager.ts @@ -8,19 +8,39 @@ // cspell:ignore BLOCKCACHE -import * as path from "path"; import { NativeLoggerCategory } from "@bentley/imodeljs-native"; -import { AccessToken, BeEvent, ChangeSetStatus, Guid, GuidString, IModelStatus, Logger, LogLevel, Mutable, OpenMode, StopWatch } from "@itwin/core-bentley"; import { - BriefcaseIdValue, ChangesetId, ChangesetIdWithIndex, ChangesetIndexAndId, IModelError, IModelVersion, LocalDirName, LocalFileName, OpenCheckpointArgs, + AccessToken, + BeEvent, + ChangeSetStatus, + Guid, + GuidString, + IModelStatus, + Logger, + LogLevel, + Mutable, + OpenMode, + StopWatch, +} from "@itwin/core-bentley"; +import { + BriefcaseIdValue, + ChangesetId, + ChangesetIdWithIndex, + ChangesetIndexAndId, + IModelError, + IModelVersion, + LocalDirName, + LocalFileName, + OpenCheckpointArgs, } from "@itwin/core-common"; +import * as path from "path"; import { V2CheckpointAccessProps } from "./BackendHubAccess"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { BriefcaseManager } from "./BriefcaseManager"; import { CloudSqlite } from "./CloudSqlite"; +import { SnapshotDb, TokenArg } from "./IModelDb"; import { IModelHost } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; -import { SnapshotDb, TokenArg } from "./IModelDb"; import { IModelNative } from "./internal/NativePlatform"; import { _nativeDb } from "./internal/Symbols"; @@ -125,7 +145,7 @@ export class Downloads { /** * Utility class for opening V2 checkpoints from cloud containers, and also for downloading them. * @internal -*/ + */ export class V2CheckpointManager { public static readonly cloudCacheName = "Checkpoints"; private static _cloudCache?: CloudSqlite.CloudCache; @@ -180,7 +200,12 @@ export class V2CheckpointManager { tokenFn = async () => (await IModelHost.hubAccess.queryV2Checkpoint(checkpoint))?.sasToken ?? ""; tokenRefreshSeconds = undefined; } - container = CloudSqlite.createCloudContainer({ ...this.toCloudContainerProps(v2Props), tokenRefreshSeconds, logId: process.env.POD_NAME, tokenFn }); + container = CloudSqlite.createCloudContainer({ + ...this.toCloudContainerProps(v2Props), + tokenRefreshSeconds, + logId: process.env.POD_NAME, + tokenFn, + }); this.containers.set(v2Props.containerId, container); } return container; @@ -204,7 +229,8 @@ export class V2CheckpointManager { container.checkForChanges(); const dbStats = container.queryDatabase(dbName); if (IModelHost.appWorkspace.settings.getBoolean("Checkpoints/prefetch", false)) { - const getPrefetchConfig = (name: string, defaultVal: number) => IModelHost.appWorkspace.settings.getNumber(`Checkpoints/prefetch/${name}`, defaultVal); + const getPrefetchConfig = (name: string, defaultVal: number) => + IModelHost.appWorkspace.settings.getNumber(`Checkpoints/prefetch/${name}`, defaultVal); const minRequests = getPrefetchConfig("minRequests", 3); const maxRequests = getPrefetchConfig("maxRequests", 6); const timeout = getPrefetchConfig("timeout", 100); @@ -214,12 +240,21 @@ export class V2CheckpointManager { const stopwatch = new StopWatch(`[${container.containerId}/${dbName}]`, true); Logger.logInfo(loggerCategory, `Starting prefetch of ${stopwatch.description}`, { minRequests, maxRequests, timeout }); const done = await prefetch.promise; - Logger.logInfo(loggerCategory, `Prefetch of ${stopwatch.description} complete=${done} (${stopwatch.elapsedSeconds} seconds)`, { minRequests, maxRequests, timeout }); + Logger.logInfo(loggerCategory, `Prefetch of ${stopwatch.description} complete=${done} (${stopwatch.elapsedSeconds} seconds)`, { + minRequests, + maxRequests, + timeout, + }); }; // eslint-disable-next-line @typescript-eslint/no-floating-promises logPrefetch(CloudSqlite.startCloudPrefetch(container, dbName, { minRequests, nRequests: maxRequests, timeout })); } else { - Logger.logInfo(loggerCategory, `Skipping prefetch due to size limits or ongoing prefetch.`, { maxBlocks, numPrefetches: dbStats?.nPrefetch, totalBlocksInDb: dbStats?.totalBlocks, v2props }); + Logger.logInfo(loggerCategory, `Skipping prefetch due to size limits or ongoing prefetch.`, { + maxBlocks, + numPrefetches: dbStats?.nPrefetch, + totalBlocksInDb: dbStats?.totalBlocks, + v2props, + }); } } return { dbName, container }; @@ -234,7 +269,10 @@ export class V2CheckpointManager { private static async performDownload(job: DownloadJob): Promise { const request = job.request; - const v2props: V2CheckpointAccessProps | undefined = await IModelHost.hubAccess.queryV2Checkpoint({ ...request.checkpoint, allowPreceding: true }); + const v2props: V2CheckpointAccessProps | undefined = await IModelHost.hubAccess.queryV2Checkpoint({ + ...request.checkpoint, + allowPreceding: true, + }); if (!v2props) throw new IModelError(IModelStatus.NotFound, "V2 checkpoint not found"); @@ -302,7 +340,9 @@ export class V1CheckpointManager { export class CheckpointManager { public static readonly onDownloadV1 = new BeEvent<(job: DownloadJob) => void>(); public static readonly onDownloadV2 = new BeEvent<(job: DownloadJob) => void>(); - public static getKey(checkpoint: CheckpointProps) { return `${checkpoint.iModelId}:${checkpoint.changeset.id}`; } + public static getKey(checkpoint: CheckpointProps) { + return `${checkpoint.iModelId}:${checkpoint.changeset.id}`; + } private static async doDownload(request: DownloadRequest): Promise { try { @@ -312,14 +352,29 @@ export class CheckpointManager { const changesetId = await V2CheckpointManager.downloadCheckpoint(request); Logger.logInfo(loggerCategory, `Downloaded V2 checkpoint with id ${stopwatch.description} (${stopwatch.elapsedSeconds} seconds)`); if (changesetId !== request.checkpoint.changeset.id) - Logger.logInfo(loggerCategory, `Downloaded previous v2 checkpoint because requested checkpoint not found.`, { requestedChangesetId: request.checkpoint.changeset.id, iModelId: request.checkpoint.iModelId, changesetId, iTwinId: request.checkpoint.iTwinId }); + Logger.logInfo(loggerCategory, `Downloaded previous v2 checkpoint because requested checkpoint not found.`, { + requestedChangesetId: request.checkpoint.changeset.id, + iModelId: request.checkpoint.iModelId, + changesetId, + iTwinId: request.checkpoint.iTwinId, + }); else - Logger.logInfo(loggerCategory, `Downloaded v2 checkpoint.`, { iModelId: request.checkpoint.iModelId, changesetId: request.checkpoint.changeset.id, iTwinId: request.checkpoint.iTwinId }); + Logger.logInfo(loggerCategory, `Downloaded v2 checkpoint.`, { + iModelId: request.checkpoint.iModelId, + changesetId: request.checkpoint.changeset.id, + iTwinId: request.checkpoint.iTwinId, + }); return changesetId; } catch (error: any) { if (error.errorNumber === IModelStatus.NotFound) { // No V2 checkpoint available, try a v1 checkpoint const changeset = await V1CheckpointManager.downloadCheckpoint(request); - Logger.logWarning(loggerCategory, `Got an error downloading v2 checkpoint, but downloaded v1 checkpoint successfully!`, { error, iModelId: request.checkpoint.iModelId, iTwinId: request.checkpoint.iTwinId, requestedChangesetId: request.checkpoint.changeset.id, changesetId: changeset }); + Logger.logWarning(loggerCategory, `Got an error downloading v2 checkpoint, but downloaded v1 checkpoint successfully!`, { + error, + iModelId: request.checkpoint.iModelId, + iTwinId: request.checkpoint.iTwinId, + requestedChangesetId: request.checkpoint.changeset.id, + changesetId: changeset, + }); return changeset; } throw error; // most likely, was aborted @@ -337,7 +392,6 @@ export class CheckpointManager { const db = SnapshotDb.openForApplyChangesets(targetFile); const nativeDb = db[_nativeDb]; try { - if (nativeDb.hasPendingTxns()) { Logger.logWarning(loggerCategory, "Checkpoint with Txns found - deleting them", () => traceInfo); nativeDb.deleteAllTxns(); @@ -352,7 +406,11 @@ export class CheckpointManager { if (currentChangeset.id !== checkpoint.changeset.id) { const accessToken = checkpoint.accessToken; const toIndex = checkpoint.changeset.index ?? - (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken, iModelId: checkpoint.iModelId, version: IModelVersion.asOfChangeSet(checkpoint.changeset.id) })).index; + (await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken, + iModelId: checkpoint.iModelId, + version: IModelVersion.asOfChangeSet(checkpoint.changeset.id), + })).index; await BriefcaseManager.pullAndApplyChangesets(db, { accessToken, toIndex }); } else { // make sure the parent changeset index is saved in the file - old versions didn't have it. @@ -365,11 +423,13 @@ export class CheckpointManager { db.close(); } } catch (error: any) { - Logger.logError(loggerCategory, "Error downloading checkpoint - deleting it", () => traceInfo); IModelJsFs.removeSync(targetFile); - if (error.errorNumber === ChangeSetStatus.CorruptedChangeStream || error.errorNumber === ChangeSetStatus.InvalidId || error.errorNumber === ChangeSetStatus.InvalidVersion) { + if ( + error.errorNumber === ChangeSetStatus.CorruptedChangeStream || error.errorNumber === ChangeSetStatus.InvalidId || + error.errorNumber === ChangeSetStatus.InvalidVersion + ) { Logger.logError(loggerCategory, "Detected potential corruption of change sets. Deleting them to enable retries", () => traceInfo); BriefcaseManager.deleteChangeSetsFromLocalDisk(checkpoint.iModelId); } @@ -406,7 +466,11 @@ export class CheckpointManager { if (nativeDb.isReadonly()) throw new IModelError(IModelStatus.ValidationFailed, "iModelId is not properly set up in the checkpoint"); - Logger.logWarning(loggerCategory, "iModelId is not properly set up in the checkpoint. Updated checkpoint to the correct iModelId.", () => ({ ...traceInfo, dbGuid: iModelId })); + Logger.logWarning( + loggerCategory, + "iModelId is not properly set up in the checkpoint. Updated checkpoint to the correct iModelId.", + () => ({ ...traceInfo, dbGuid: iModelId }), + ); const iModelIdNormalized = Guid.normalize(checkpoint.iModelId); nativeDb.setIModelId(iModelIdNormalized); (snapshotDb as any)._iModelId = iModelIdNormalized; diff --git a/core/backend/src/ClassRegistry.ts b/core/backend/src/ClassRegistry.ts index b85ef54df17b..f2b8a3ec2ad2 100644 --- a/core/backend/src/ClassRegistry.ts +++ b/core/backend/src/ClassRegistry.ts @@ -8,12 +8,12 @@ import { DbResult, Id64, Id64String, IModelStatus, Logger } from "@itwin/core-bentley"; import { EntityMetaData, EntityReferenceSet, IModelError, RelatedElement } from "@itwin/core-common"; +import * as assert from "assert"; import { Entity } from "./Entity"; -import { IModelDb } from "./IModelDb"; -import { Schema, Schemas } from "./Schema"; import { EntityReferences } from "./EntityReferences"; -import * as assert from "assert"; +import { IModelDb } from "./IModelDb"; import { _nativeDb } from "./internal/Symbols"; +import { Schema, Schemas } from "./Schema"; const isGeneratedClassTag = Symbol("isGeneratedClassTag"); @@ -25,9 +25,13 @@ const isGeneratedClassTag = Symbol("isGeneratedClassTag"); export class ClassRegistry { private static readonly _classMap = new Map(); /** @internal */ - public static isNotFoundError(err: any) { return (err instanceof IModelError) && (err.errorNumber === IModelStatus.NotFound); } + public static isNotFoundError(err: any) { + return (err instanceof IModelError) && (err.errorNumber === IModelStatus.NotFound); + } /** @internal */ - public static makeMetaDataNotFoundError(className: string): IModelError { return new IModelError(IModelStatus.NotFound, `metadata not found for ${className}`); } + public static makeMetaDataNotFoundError(className: string): IModelError { + return new IModelError(IModelStatus.NotFound, `metadata not found for ${className}`); + } /** Register a single `entityClass` defined in the specified `schema`. * @see [[registerModule]] to register multiple classes. * @public @@ -46,20 +50,27 @@ export class ClassRegistry { /** Generate a proxy Schema for a domain that has not been registered. */ private static generateProxySchema(domain: string, iModel: IModelDb): typeof Schema { - const hasBehavior = iModel.withPreparedSqliteStatement(` + const hasBehavior = iModel.withPreparedSqliteStatement( + ` SELECT NULL FROM [ec_CustomAttribute] [c] JOIN [ec_schema] [s] ON [s].[Id] = [c].[ContainerId] JOIN [ec_class] [e] ON [e].[Id] = [c].[ClassId] JOIN [ec_schema] [b] ON [e].[SchemaId] = [b].[Id] - WHERE [c].[ContainerType] = 1 AND [s].[Name] = ? AND [b].[Name] || '.' || [e].[name] = ?`, (stmt) => { - stmt.bindString(1, domain); - stmt.bindString(2, "BisCore.SchemaHasBehavior"); - return stmt.step() === DbResult.BE_SQLITE_ROW; - }); + WHERE [c].[ContainerType] = 1 AND [s].[Name] = ? AND [b].[Name] || '.' || [e].[name] = ?`, + (stmt) => { + stmt.bindString(1, domain); + stmt.bindString(2, "BisCore.SchemaHasBehavior"); + return stmt.step() === DbResult.BE_SQLITE_ROW; + }, + ); const schemaClass = class extends Schema { - public static override get schemaName() { return domain; } - public static override get missingRequiredBehavior() { return hasBehavior; } + public static override get schemaName() { + return domain; + } + public static override get missingRequiredBehavior() { + return hasBehavior; + } }; Schemas.registerSchema(schemaClass); // register the class before we return it. @@ -126,21 +137,31 @@ export class ClassRegistry { } const superclassMetaData = iModel.classMetaDataRegistry.find(currentSuperclass.classFullName); if (superclassMetaData === undefined) - throw new IModelError(IModelStatus.BadSchema, `could not find the metadata for class '${currentSuperclass.name}', class metadata should be loaded by now`); + throw new IModelError( + IModelStatus.BadSchema, + `could not find the metadata for class '${currentSuperclass.name}', class metadata should be loaded by now`, + ); const maybeNextSuperclass = this.getClass(superclassMetaData.baseClasses[0], iModel); if (maybeNextSuperclass === undefined) - throw new IModelError(IModelStatus.BadSchema, `could not find the base class of '${currentSuperclass.name}', all generated classes must have a base class`); + throw new IModelError( + IModelStatus.BadSchema, + `could not find the base class of '${currentSuperclass.name}', all generated classes must have a base class`, + ); currentSuperclass = maybeNextSuperclass; } const generatedClass = class extends superclass { - public static override get className() { return className; } + public static override get className() { + return className; + } private static [isGeneratedClassTag] = true; - public static override get isGeneratedClass() { return this.hasOwnProperty(isGeneratedClassTag); } + public static override get isGeneratedClass() { + return this.hasOwnProperty(isGeneratedClassTag); + } }; // the above creates an anonymous class. For help debugging, set the "constructor.name" property to be the same as the bisClassName. - Object.defineProperty(generatedClass, "name", { get: () => className }); // this is the (only) way to change that readonly property. + Object.defineProperty(generatedClass, "name", { get: () => className }); // this is the (only) way to change that readonly property. // a class only gets an automatic `collectReferenceIds` implementation if: // - it is not in the `BisCore` schema @@ -255,7 +276,9 @@ export class ClassRegistry { * @return true if the class was unregistered * @internal */ - public static unregisterCLass(classFullName: string) { return this._classMap.delete(classFullName.toLowerCase()); } + public static unregisterCLass(classFullName: string) { + return this._classMap.delete(classFullName.toLowerCase()); + } /** Unregister all classes from a schema. * This function is not normally needed, but is useful for cases where a generated *proxy* schema needs to be replaced by the *real* schema. * @param schema Name of the schema to unregister diff --git a/core/backend/src/CloudSqlite.ts b/core/backend/src/CloudSqlite.ts index bea0319f373a..dc1e23dd5891 100644 --- a/core/backend/src/CloudSqlite.ts +++ b/core/backend/src/CloudSqlite.ts @@ -6,13 +6,24 @@ * @module SQLiteDb */ -import { mkdirSync, unlinkSync } from "fs"; -import { dirname, join } from "path"; import { NativeLibrary } from "@bentley/imodeljs-native"; import { - AccessToken, BeDuration, BriefcaseStatus, Constructor, GuidString, Logger, LogLevel, OpenMode, Optional, PickAsyncMethods, PickMethods, StopWatch, + AccessToken, + BeDuration, + BriefcaseStatus, + Constructor, + GuidString, + Logger, + LogLevel, + OpenMode, + Optional, + PickAsyncMethods, + PickMethods, + StopWatch, } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; +import { mkdirSync, unlinkSync } from "fs"; +import { dirname, join } from "path"; import { BlobContainer } from "./BlobContainerService"; import { IModelHost, KnownLocations } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; @@ -27,7 +38,6 @@ import type { SQLiteDb, VersionedSqliteDb } from "./SQLiteDb"; * @beta */ export namespace CloudSqlite { - const logInfo = (msg: string) => Logger.logInfo("CloudSqlite", msg); const logError = (msg: string) => Logger.logError("CloudSqlite", msg); @@ -61,7 +71,9 @@ export namespace CloudSqlite { * @note After the container is successfully connected to a CloudCache, it will begin auto-refreshing its accessToken every `tokenRefreshSeconds` seconds (default is 1 hour) * until it is disconnected. However, if the container is public, or if `tokenRefreshSeconds` is <=0, auto-refresh is not enabled. */ - export function createCloudContainer(args: ContainerAccessProps & { accessLevel?: BlobContainer.RequestAccessLevel, tokenFn?: (args: RequestTokenArgs) => Promise }): CloudContainer { + export function createCloudContainer( + args: ContainerAccessProps & { accessLevel?: BlobContainer.RequestAccessLevel, tokenFn?: (args: RequestTokenArgs) => Promise }, + ): CloudContainer { const container = new NativeLibrary.nativeLib.CloudContainer(args) as CloudContainerInternal; const refreshSeconds = (undefined !== args.tokenRefreshSeconds) ? args.tokenRefreshSeconds : 60 * 60; // default is 1 hour container.lockExpireSeconds = args.lockExpireSeconds ?? 60 * 60; // default is 1 hour @@ -188,7 +200,7 @@ export namespace CloudSqlite { /** Filter options passed to 'CloudContainer.queryBcvStats' * @internal - */ + */ interface BcvStatsFilterOptions { /** if true, adds activeClients, totalClients, ongoingPrefetches, and attachedContainers to the result. */ addClientInformation?: boolean; @@ -201,7 +213,7 @@ export namespace CloudSqlite { export interface BcvStats { /** The total number of cache slots that are currently in use or 'locked' by ongoing client read transactions. In daemonless mode, this value is always 0. * A locked cache slot implies that it is not eligible for eviction in the event of a full cachefile. - */ + */ readonly lockedCacheslots: number; /** The current number of slots with data in them in the cache. */ readonly populatedCacheslots: number; @@ -220,7 +232,7 @@ export namespace CloudSqlite { /** The name of a CloudSqlite database within a CloudContainer. */ export interface DbNameProp { /** the name of the database within the CloudContainer. - * @note names of databases within a CloudContainer are always **case sensitive** on all platforms.*/ + * @note names of databases within a CloudContainer are always **case sensitive** on all platforms. */ dbName: string; } @@ -362,7 +374,7 @@ export namespace CloudSqlite { nSeconds?: number; /** if enabled, outputs verbose logs about the cleanup process. Output includes blocks determined eligible for deletion. * @default false - */ + */ debugLogging?: boolean; /** If true, iterates over all blobs in the cloud container to add blocks that are 'orphaned' to the delete list in the manifest. * Orphaned blocks are created when a client abruptly halts, is disconnected, or encounters an error while uploading a change. @@ -650,7 +662,6 @@ export namespace CloudSqlite { } finally { if (timer) clearInterval(timer); - } } @@ -683,14 +694,14 @@ export namespace CloudSqlite { export type WriteLockBusyHandler = (lockedBy: string, expires: string) => Promise; /** - * Attempt to acquire the write lock for a container, with retries. - * If write lock is held by another user, call busyHandler if supplied. If no busyHandler, or handler returns "stop", throw. Otherwise try again. - * @note if write lock is already held by the same user, this function will refresh the write lock's expiry time. - * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us - * @param container the CloudContainer for which the lock is to be acquired - * @param busyHandler if present, function called when the write lock is currently held by another user. - * @throws if [[container]] is not connected to a CloudCache. - */ + * Attempt to acquire the write lock for a container, with retries. + * If write lock is held by another user, call busyHandler if supplied. If no busyHandler, or handler returns "stop", throw. Otherwise try again. + * @note if write lock is already held by the same user, this function will refresh the write lock's expiry time. + * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us + * @param container the CloudContainer for which the lock is to be acquired + * @param busyHandler if present, function called when the write lock is currently held by another user. + * @throws if [[container]] is not connected to a CloudCache. + */ export async function acquireWriteLock(args: { user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler }) { const container = args.container as CloudContainerInternal; while (true) { @@ -706,7 +717,6 @@ export namespace CloudSqlite { throw err; } return container.acquireWriteLock(args.user); - } catch (e: any) { if (e.errorNumber === 5 && args.busyHandler && "stop" !== await args.busyHandler(e.lockedBy, e.expires)) // 5 === BE_SQLITE_BUSY continue; // busy handler wants to try again @@ -716,20 +726,23 @@ export namespace CloudSqlite { } /** - * Perform an asynchronous write operation on a CloudContainer with the write lock held. - * 1. if write lock is already held by the current user, refresh write lock's expiry time, call operation and return. - * 2. attempt to acquire the write lock, with retries. Throw if unable to obtain write lock. - * 3. perform the operation - * 3.a if the operation throws, abandon all changes and re-throw - * 4. release the write lock. - * 5. return value from operation - * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us - * @param container the CloudContainer for which the lock is to be acquired - * @param operation an asynchronous operation performed with the write lock held. - * @param busyHandler if present, function called when the write lock is currently held by another user. - * @returns a Promise with the result of `operation` - */ - export async function withWriteLock(args: { user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler }, operation: () => Promise): Promise { + * Perform an asynchronous write operation on a CloudContainer with the write lock held. + * 1. if write lock is already held by the current user, refresh write lock's expiry time, call operation and return. + * 2. attempt to acquire the write lock, with retries. Throw if unable to obtain write lock. + * 3. perform the operation + * 3.a if the operation throws, abandon all changes and re-throw + * 4. release the write lock. + * 5. return value from operation + * @param user the name to be displayed to other users in the event they attempt to obtain the lock while it is held by us + * @param container the CloudContainer for which the lock is to be acquired + * @param operation an asynchronous operation performed with the write lock held. + * @param busyHandler if present, function called when the write lock is currently held by another user. + * @returns a Promise with the result of `operation` + */ + export async function withWriteLock( + args: { user: string, container: CloudContainer, busyHandler?: WriteLockBusyHandler }, + operation: () => Promise, + ): Promise { await acquireWriteLock(args); const containerInternal = args.container as CloudContainerInternal; try { @@ -742,7 +755,7 @@ export namespace CloudSqlite { containerInternal.writeLockHeldBy = undefined; return val; } catch (e) { - args.container.abandonChanges(); // if operation threw, abandon all changes + args.container.abandonChanges(); // if operation threw, abandon all changes containerInternal.writeLockHeldBy = undefined; throw e; } @@ -817,7 +830,9 @@ export namespace CloudSqlite { protected _cloudDb: DbType; private _writeLockProxy?: PickAsyncMethods; private _readerProxy?: PickMethods; - private get _ctor() { return this.constructor as typeof DbAccess; } + private get _ctor() { + return this.constructor as typeof DbAccess; + } /** @internal */ public static getCacheForClass() { @@ -843,8 +858,12 @@ export namespace CloudSqlite { * The token that grants access to the cloud container for this DbAccess. If it does not grant write permissions, all * write operations will fail. It should be refreshed (via a timer) before it expires. */ - public get sasToken() { return this._container.accessToken; } - public set sasToken(token: AccessToken) { this._container.accessToken = token; } + public get sasToken() { + return this._container.accessToken; + } + public set sasToken(token: AccessToken) { + this._container.accessToken = token; + } /** the container for this DbAccess. It is automatically connected to the CloudCache whenever it is accessed. */ public get container(): CloudContainer { @@ -891,8 +910,14 @@ export namespace CloudSqlite { * This function creates and uploads an empty database into the container. * @note this deletes any existing content in the container. */ - protected static async _initializeDb(args: { dbType: typeof VersionedSqliteDb, props: ContainerProps, dbName: string, blockSize?: "64K" | "4M" }) { - const container = createCloudContainer({ ...args.props, writeable: true, accessToken: args.props.accessToken ?? await CloudSqlite.requestToken(args.props) }); + protected static async _initializeDb( + args: { dbType: typeof VersionedSqliteDb, props: ContainerProps, dbName: string, blockSize?: "64K" | "4M" }, + ) { + const container = createCloudContainer({ + ...args.props, + writeable: true, + accessToken: args.props.accessToken ?? await CloudSqlite.requestToken(args.props), + }); container.initializeContainer({ blockSize: args.blockSize === "4M" ? 4 * 1024 * 1024 : 64 * 1024 }); container.connect(CloudCaches.getCache({ cacheName: this._cacheName })); await withWriteLock({ user: "initialize", container }, async () => { @@ -976,11 +1001,14 @@ export namespace CloudSqlite { let lockObtained = false; const operationName = args.operationName; try { - return await this._cloudDb.withLockedContainer({ user, dbName: this.dbName, container: this.container, busyHandler, openMode: args.openMode }, async () => { - lockObtained = true; - logInfo(`lock acquired by ${cacheGuid} for ${operationName} ${showMs()}`); - return operation(); - }); + return await this._cloudDb.withLockedContainer( + { user, dbName: this.dbName, container: this.container, busyHandler, openMode: args.openMode }, + async () => { + lockObtained = true; + logInfo(`lock acquired by ${cacheGuid} for ${operationName} ${showMs()}`); + return operation(); + }, + ); } finally { if (lockObtained) logInfo(`lock released by ${cacheGuid} after ${operationName} ${showMs()} `); @@ -1014,7 +1042,8 @@ export namespace CloudSqlite { return this._writeLockProxy ??= new Proxy(this, { get(access, operationName: string) { const fn = access.getDbMethod(operationName); - return async (...args: any[]) => access.withLockedDb({ operationName, user: RpcTrace.currentActivity?.user }, fn.bind(access._cloudDb, ...args)); + return async (...args: any[]) => + access.withLockedDb({ operationName, user: RpcTrace.currentActivity?.user }, fn.bind(access._cloudDb, ...args)); }, }) as PickAsyncMethods; } diff --git a/core/backend/src/CodeService.ts b/core/backend/src/CodeService.ts index ff08b190e1be..0164f613ba66 100644 --- a/core/backend/src/CodeService.ts +++ b/core/backend/src/CodeService.ts @@ -7,8 +7,8 @@ import { BentleyError, GuidString, IModelStatus, MarkRequired, Mutable } from "@ import { CodeProps, FontId, FontType } from "@itwin/core-common"; import { CloudSqlite } from "./CloudSqlite"; import { IModelDb } from "./IModelDb"; -import { SettingsContainer } from "./workspace/Settings"; import { VersionedSqliteDb } from "./SQLiteDb"; +import { SettingsContainer } from "./workspace/Settings"; /** * The services for querying, reserving, updating, and deleting codes for a BriefcaseDb (available via `BriefcaseDb.codeService`) whenever it is opened for write access. @@ -46,7 +46,6 @@ export interface CodeService { /** @alpha */ export namespace CodeService { - export interface WriteMethods { /** Add a new code spec to this code service. */ @@ -495,30 +494,29 @@ export namespace CodeService { * @see [[CodeService.Error.errorId]] */ export type ErrorId = - "BadIndexProps" | - "CorruptIModel" | - "CorruptIndex" | - "DuplicateValue" | - "GuidIsInUse" | - "GuidMismatch" | - "IllegalValue" | - "InconsistentIModels" | - "IndexReadonly" | - "InvalidCodeScope" | - "InvalidGuid" | - "InvalidSequence" | - "MissingCode" | - "MissingGuid" | - "MissingInput" | - "MissingSpec" | - "NoCodeIndex" | - "NotAuthorized" | - "SequenceFull" | - "ReserveErrors" | - "SequenceNotFound" | - "SqlLogicError" | - "UpdateErrors" | - "ValueIsInUse" | - "WrongVersion"; - + | "BadIndexProps" + | "CorruptIModel" + | "CorruptIndex" + | "DuplicateValue" + | "GuidIsInUse" + | "GuidMismatch" + | "IllegalValue" + | "InconsistentIModels" + | "IndexReadonly" + | "InvalidCodeScope" + | "InvalidGuid" + | "InvalidSequence" + | "MissingCode" + | "MissingGuid" + | "MissingInput" + | "MissingSpec" + | "NoCodeIndex" + | "NotAuthorized" + | "SequenceFull" + | "ReserveErrors" + | "SequenceNotFound" + | "SqlLogicError" + | "UpdateErrors" + | "ValueIsInUse" + | "WrongVersion"; } diff --git a/core/backend/src/CodeSpecs.ts b/core/backend/src/CodeSpecs.ts index 0065354e4f84..c29d73680f3b 100644 --- a/core/backend/src/CodeSpecs.ts +++ b/core/backend/src/CodeSpecs.ts @@ -8,8 +8,8 @@ import { BentleyError, DbResult, Id64, Id64String, IModelStatus } from "@itwin/core-bentley"; import { CodeScopeSpec, CodeSpec, CodeSpecProperties, IModelError } from "@itwin/core-common"; -import { IModelDb } from "./IModelDb"; import { CodeService } from "./CodeService"; +import { IModelDb } from "./IModelDb"; /** Manages [CodeSpecs]($docs/BIS/guide/fundamentals/element-fundamentals.md#codespec) within an [[IModelDb]] * @public @@ -156,9 +156,9 @@ export class CodeSpecs { } /** Update the Json properties of an existing CodeSpec. - * @param codeSpec The codeSpec holding Json properties values to update - * @throws if unable to update the codeSpec. - */ + * @param codeSpec The codeSpec holding Json properties values to update + * @throws if unable to update the codeSpec. + */ public updateProperties(codeSpec: CodeSpec): void { this._imodel.withSqliteStatement(`UPDATE ${CodeSpecs.tableName} SET JsonProperties=? WHERE Id=?`, (stmt) => { stmt.bindString(1, JSON.stringify(codeSpec.properties)); diff --git a/core/backend/src/CustomViewState3dCreator.ts b/core/backend/src/CustomViewState3dCreator.ts index d3723fb3cd13..6777b875cd61 100644 --- a/core/backend/src/CustomViewState3dCreator.ts +++ b/core/backend/src/CustomViewState3dCreator.ts @@ -42,7 +42,8 @@ export class CustomViewState3dCreator { private async _getAllCategories(): Promise { // Only use categories with elements in them Logger.logInfo(loggerCategory, "Starting getAllCategories query."); - const query = `SELECT DISTINCT Category.Id AS id FROM BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId FROM BisCore.SpatialCategory)`; + const query = + `SELECT DISTINCT Category.Id AS id FROM BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId FROM BisCore.SpatialCategory)`; const categories: Id64Array = await this._executeQuery(query); Logger.logInfo(loggerCategory, "Finished getAllCategories query."); return categories; diff --git a/core/backend/src/DevTools.ts b/core/backend/src/DevTools.ts index 6075c0e8f064..f126024ec652 100644 --- a/core/backend/src/DevTools.ts +++ b/core/backend/src/DevTools.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger, LogLevel } from "@itwin/core-bentley"; +import { RpcInterfaceEndpoints } from "@itwin/core-common"; import * as os from "os"; import * as process from "process"; -import { Logger, LogLevel } from "@itwin/core-bentley"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { IModelHost } from "./IModelHost"; import { IModelNative } from "./internal/NativePlatform"; -import { RpcInterfaceEndpoints } from "@itwin/core-common"; // cspell:ignore ppid elap @@ -90,7 +90,6 @@ export class DevToolsStatsFormatter { * @internal */ export class DevTools { - /** Receives a ping and returns true */ public static ping(): boolean { Logger.logInfo(loggerCategory, "Received ping at backend"); @@ -113,8 +112,7 @@ export class DevTools { // spin the CPU for 500 milliseconds const now = Date.now(); - while (Date.now() - now < 500) - ; + while (Date.now() - now < 500); const elapTime = process.hrtime(startTime); const elapUsage = process.cpuUsage(startUsage); @@ -123,7 +121,7 @@ export class DevTools { const elapUserMS = elapUsage.user / 1000; // microseconds to milliseconds const elapSystMS = elapUsage.system / 1000; - const cpuPercent = Math.round((100 * (elapUserMS + elapSystMS) / elapTimeMS / NUMBER_OF_CPUS)); + const cpuPercent = Math.round(100 * (elapUserMS + elapSystMS) / elapTimeMS / NUMBER_OF_CPUS); return cpuPercent; } diff --git a/core/backend/src/DisplayStyle.ts b/core/backend/src/DisplayStyle.ts index 1cf16d7e65d9..099347a4bf12 100644 --- a/core/backend/src/DisplayStyle.ts +++ b/core/backend/src/DisplayStyle.ts @@ -8,8 +8,22 @@ import { CompressedId64Set, Id64, Id64Array, Id64String, OrderedId64Iterable } from "@itwin/core-bentley"; import { - BisCodeSpec, Code, CodeScopeProps, CodeSpec, ColorDef, DisplayStyle3dProps, DisplayStyle3dSettings, DisplayStyle3dSettingsProps, - DisplayStyleProps, DisplayStyleSettings, DisplayStyleSubCategoryProps, EntityReferenceSet, PlanProjectionSettingsProps, RenderSchedule, SkyBoxImageProps, ViewFlags, + BisCodeSpec, + Code, + CodeScopeProps, + CodeSpec, + ColorDef, + DisplayStyle3dProps, + DisplayStyle3dSettings, + DisplayStyle3dSettingsProps, + DisplayStyleProps, + DisplayStyleSettings, + DisplayStyleSubCategoryProps, + EntityReferenceSet, + PlanProjectionSettingsProps, + RenderSchedule, + SkyBoxImageProps, + ViewFlags, } from "@itwin/core-common"; import { DefinitionElement, RenderTimeline } from "./Element"; import { IModelDb } from "./IModelDb"; @@ -21,7 +35,9 @@ import { IModelElementCloneContext } from "./IModelElementCloneContext"; * @public */ export abstract class DisplayStyle extends DefinitionElement { - public static override get className(): string { return "DisplayStyle"; } + public static override get className(): string { + return "DisplayStyle"; + } public abstract get settings(): DisplayStyleSettings; protected constructor(props: DisplayStyleProps, iModel: IModelDb) { @@ -57,7 +73,11 @@ export abstract class DisplayStyle extends DefinitionElement { } /** @alpha */ - protected static override onCloned(context: IModelElementCloneContext, sourceElementProps: DisplayStyleProps, targetElementProps: DisplayStyleProps): void { + protected static override onCloned( + context: IModelElementCloneContext, + sourceElementProps: DisplayStyleProps, + targetElementProps: DisplayStyleProps, + ): void { super.onCloned(context, sourceElementProps, targetElementProps); if (!context.isBetweenIModels || !targetElementProps.jsonProperties?.styles) @@ -70,13 +90,15 @@ export abstract class DisplayStyle extends DefinitionElement { ovr.subCategory; const targetSubCategoryId = context.findTargetElementId(Id64.fromJSON(ovr.subCategory)); if (Id64.isValid(targetSubCategoryId)) - targetOverrides.push({...ovr, subCategory: targetSubCategoryId}); + targetOverrides.push({ ...ovr, subCategory: targetSubCategoryId }); } settings.subCategoryOvr = targetOverrides; } if (settings.excludedElements) { - const excluded: Id64Array = "string" === typeof settings.excludedElements ? CompressedId64Set.decompressArray(settings.excludedElements) : settings.excludedElements; + const excluded: Id64Array = "string" === typeof settings.excludedElements + ? CompressedId64Set.decompressArray(settings.excludedElements) + : settings.excludedElements; const excludedTargetElements: Id64Array = []; for (const excludedElement of excluded) { const remapped = context.findTargetElementId(excludedElement); @@ -127,10 +149,14 @@ export abstract class DisplayStyle extends DefinitionElement { * @public */ export class DisplayStyle2d extends DisplayStyle { - public static override get className(): string { return "DisplayStyle2d"; } + public static override get className(): string { + return "DisplayStyle2d"; + } private readonly _settings: DisplayStyleSettings; - public get settings(): DisplayStyleSettings { return this._settings; } + public get settings(): DisplayStyleSettings { + return this._settings; + } protected constructor(props: DisplayStyleProps, iModel: IModelDb) { super(props, iModel); @@ -193,10 +219,14 @@ export interface DisplayStyleCreationOptions extends Omit Id64.isValidId64(id) ? context.findTargetElementId(id) : id; @@ -297,7 +332,6 @@ export class DisplayStyle3d extends DisplayStyle { model: definitionModelId, jsonProperties: { styles: settings }, isPrivate: false, - }; return new DisplayStyle3d(displayStyleProps, iModelDb); diff --git a/core/backend/src/ECDb.ts b/core/backend/src/ECDb.ts index 7299b2dd2523..a7e2761caa47 100644 --- a/core/backend/src/ECDb.ts +++ b/core/backend/src/ECDb.ts @@ -5,15 +5,15 @@ /** @packageDocumentation * @module ECDb */ -import { assert, DbResult, IDisposable, Logger, OpenMode } from "@itwin/core-bentley"; import { IModelJsNative } from "@bentley/imodeljs-native"; +import { assert, DbResult, IDisposable, Logger, OpenMode } from "@itwin/core-bentley"; import { DbQueryRequest, ECSchemaProps, ECSqlReader, IModelError, QueryBinder, QueryOptions, QueryOptionsBuilder } from "@itwin/core-common"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { ConcurrentQuery } from "./ConcurrentQuery"; import { ECSqlStatement } from "./ECSqlStatement"; import { IModelNative } from "./internal/NativePlatform"; -import { SqliteStatement, StatementCache } from "./SqliteStatement"; import { _nativeDb } from "./internal/Symbols"; +import { SqliteStatement, StatementCache } from "./SqliteStatement"; const loggerCategory: string = BackendLoggerCategory.ECDb; @@ -82,7 +82,9 @@ export class ECDb implements IDisposable { } /** Returns true if the ECDb is open */ - public get isOpen(): boolean { return this[_nativeDb].isOpen(); } + public get isOpen(): boolean { + return this[_nativeDb].isOpen(); + } /** Close the Db after saving any uncommitted changes. * @throws [IModelError]($common) if the database is not open. @@ -287,7 +289,9 @@ export class ECDb implements IDisposable { /** @internal * @deprecated in 4.8. This internal API will be removed in 5.0. Use ECDb's public API instead. */ - public get nativeDb(): IModelJsNative.ECDb { return this[_nativeDb]; } + public get nativeDb(): IModelJsNative.ECDb { + return this[_nativeDb]; + } /** @internal */ public get [_nativeDb](): IModelJsNative.ECDb { @@ -306,7 +310,7 @@ export class ECDb implements IDisposable { * @param config Allow to specify certain flags which control how query is executed. * @returns Returns an [ECSqlReader]($common) which helps iterate over the result set and also give access to metadata. * @public - * */ + */ public createQueryReader(ecsql: string, params?: QueryBinder, config?: QueryOptions): ECSqlReader { if (!this._nativeDb || !this._nativeDb.isOpen()) { throw new IModelError(DbResult.BE_SQLITE_ERROR, "db not open"); @@ -335,7 +339,7 @@ export class ECDb implements IDisposable { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead; it accepts the same parameters. */ - public async * query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { const builder = new QueryOptionsBuilder(options); const reader = this.createQueryReader(ecsql, params, builder.getOptions()); while (await reader.step()) @@ -379,7 +383,7 @@ export class ECDb implements IDisposable { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead. Pass in the restart token as part of the `config` argument; e.g., `{ restartToken: myToken }` or `new QueryOptionsBuilder().setRestartToken(myToken).getOptions()`. */ - public async * restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { for await (const row of this.createQueryReader(ecsql, params, new QueryOptionsBuilder(options).setRestartToken(token).getOptions())) { yield row; } diff --git a/core/backend/src/ECSchemaXmlContext.ts b/core/backend/src/ECSchemaXmlContext.ts index 45b067ef7213..a3a5774edeb5 100644 --- a/core/backend/src/ECSchemaXmlContext.ts +++ b/core/backend/src/ECSchemaXmlContext.ts @@ -6,9 +6,9 @@ * @module Schema */ +import { IModelJsNative } from "@bentley/imodeljs-native"; import { assert } from "@itwin/core-bentley"; import { IModelError } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; import { IModelNative } from "./internal/NativePlatform"; /** @internal */ diff --git a/core/backend/src/ECSqlStatement.ts b/core/backend/src/ECSqlStatement.ts index 24d14db4ec7c..427b05123c55 100644 --- a/core/backend/src/ECSqlStatement.ts +++ b/core/backend/src/ECSqlStatement.ts @@ -6,10 +6,18 @@ * @module ECSQL */ +import { IModelJsNative } from "@bentley/imodeljs-native"; import { assert, DbResult, GuidString, Id64String, IDisposable } from "@itwin/core-bentley"; +import { + ECJsNames, + ECSqlValueType, + IModelError, + NavigationBindingValue, + NavigationValue, + PropertyMetaDataMap, + QueryRowFormat, +} from "@itwin/core-common"; import { LowAndHighXYZ, Range3d, XAndY, XYAndZ, XYZ } from "@itwin/core-geometry"; -import { ECJsNames, ECSqlValueType, IModelError, NavigationBindingValue, NavigationValue, PropertyMetaDataMap, QueryRowFormat } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; import { ECDb } from "./ECDb"; import { IModelNative } from "./internal/NativePlatform"; @@ -24,13 +32,13 @@ import { IModelNative } from "./internal/NativePlatform"; * @public */ export class ECSqlInsertResult { - public constructor(public status: DbResult, public id?: Id64String) { } + public constructor(public status: DbResult, public id?: Id64String) {} } /** * Arguments supplied to [[ECSqlStatement.getRow]]. * @public - * */ + */ export interface ECSqlRowArg { /** Determine row format. */ rowFormat?: QueryRowFormat; @@ -69,10 +77,14 @@ export class ECSqlStatement implements IterableIterator, IDisposable { private _sql: string | undefined; private _props = new PropertyMetaDataMap([]); - public get sql() { return this._sql!; } // eslint-disable-line @typescript-eslint/no-non-null-assertion + public get sql() { + return this._sql!; + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** Check if this statement has been prepared successfully or not */ - public get isPrepared(): boolean { return !!this._stmt; } + public get isPrepared(): boolean { + return !!this._stmt; + } /** Prepare this statement prior to first use. * @param db The DgnDb or ECDb to prepare the statement against @@ -135,99 +147,133 @@ export class ECSqlStatement implements IterableIterator, IDisposable { * iTwin.js types to be used for the different ECSQL parameter types. * @param parameter Index (1-based) or name of the parameter */ - public bindValue(parameter: number | string, val: any): void { this.getBinder(parameter).bind(val); } + public bindValue(parameter: number | string, val: any): void { + this.getBinder(parameter).bind(val); + } /** Binds null to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter */ - public bindNull(parameter: number | string): void { this.getBinder(parameter).bindNull(); } + public bindNull(parameter: number | string): void { + this.getBinder(parameter).bindNull(); + } /** Binds a BLOB value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param BLOB value as either a Uint8Array, ArrayBuffer or a Base64 string */ - public bindBlob(parameter: number | string, blob: string | Uint8Array | ArrayBuffer | SharedArrayBuffer): void { this.getBinder(parameter).bindBlob(blob); } + public bindBlob(parameter: number | string, blob: string | Uint8Array | ArrayBuffer | SharedArrayBuffer): void { + this.getBinder(parameter).bindBlob(blob); + } /** Binds a boolean value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Boolean value */ - public bindBoolean(parameter: number | string, val: boolean): void { this.getBinder(parameter).bindBoolean(val); } + public bindBoolean(parameter: number | string, val: boolean): void { + this.getBinder(parameter).bindBoolean(val); + } /** Binds a DateTime value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param isoDateTimeString DateTime value as ISO8601 string */ - public bindDateTime(parameter: number | string, isoDateTimeString: string): void { this.getBinder(parameter).bindDateTime(isoDateTimeString); } + public bindDateTime(parameter: number | string, isoDateTimeString: string): void { + this.getBinder(parameter).bindDateTime(isoDateTimeString); + } /** Binds a double value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Double value */ - public bindDouble(parameter: number | string, val: number): void { this.getBinder(parameter).bindDouble(val); } + public bindDouble(parameter: number | string, val: number): void { + this.getBinder(parameter).bindDouble(val); + } /** Binds an GUID value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val GUID value */ - public bindGuid(parameter: number | string, val: GuidString): void { this.getBinder(parameter).bindGuid(val); } + public bindGuid(parameter: number | string, val: GuidString): void { + this.getBinder(parameter).bindGuid(val); + } /** Binds an Id value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Id value */ - public bindId(parameter: number | string, val: Id64String): void { this.getBinder(parameter).bindId(val); } + public bindId(parameter: number | string, val: Id64String): void { + this.getBinder(parameter).bindId(val); + } /** Binds an integer value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Integer value as number, decimal string or hexadecimal string. */ - public bindInteger(parameter: number | string, val: number | string): void { this.getBinder(parameter).bindInteger(val); } + public bindInteger(parameter: number | string, val: number | string): void { + this.getBinder(parameter).bindInteger(val); + } /** Binds an Point2d value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Point2d value */ - public bindPoint2d(parameter: number | string, val: XAndY): void { this.getBinder(parameter).bindPoint2d(val); } + public bindPoint2d(parameter: number | string, val: XAndY): void { + this.getBinder(parameter).bindPoint2d(val); + } /** Binds an Point3d value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Point3d value */ - public bindPoint3d(parameter: number | string, val: XYAndZ): void { this.getBinder(parameter).bindPoint3d(val); } + public bindPoint3d(parameter: number | string, val: XYAndZ): void { + this.getBinder(parameter).bindPoint3d(val); + } /** Binds a Range3d as a blob to the specified ECSQL parameter * @param parameter Index(1-based) or name of the parameter * @param val Range3d value */ - public bindRange3d(parameter: number | string, val: LowAndHighXYZ): void { this.getBinder(parameter).bindRange3d(val); } + public bindRange3d(parameter: number | string, val: LowAndHighXYZ): void { + this.getBinder(parameter).bindRange3d(val); + } /** Binds an string to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val String value */ - public bindString(parameter: number | string, val: string): void { this.getBinder(parameter).bindString(val); } + public bindString(parameter: number | string, val: string): void { + this.getBinder(parameter).bindString(val); + } /** Binds a navigation property value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Navigation property value */ - public bindNavigation(parameter: number | string, val: NavigationBindingValue): void { this.getBinder(parameter).bindNavigation(val); } + public bindNavigation(parameter: number | string, val: NavigationBindingValue): void { + this.getBinder(parameter).bindNavigation(val); + } /** Binds a struct property value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Struct value. The struct value is an object composed of pairs of a struct member property name and its value * (of one of the supported types) */ - public bindStruct(parameter: number | string, val: object): void { this.getBinder(parameter).bindStruct(val); } + public bindStruct(parameter: number | string, val: object): void { + this.getBinder(parameter).bindStruct(val); + } /** Binds an array value to the specified ECSQL parameter. * @param parameter Index (1-based) or name of the parameter * @param val Array value. The array value is an array of values of the supported types */ - public bindArray(parameter: number | string, val: any[]): void { this.getBinder(parameter).bindArray(val); } + public bindArray(parameter: number | string, val: any[]): void { + this.getBinder(parameter).bindArray(val); + } - public bindIdSet(parameter: number | string, val: Id64String[]): void { this.getBinder(parameter).bindIdSet(val); } + public bindIdSet(parameter: number | string, val: Id64String[]): void { + this.getBinder(parameter).bindIdSet(val); + } /** * Gets a binder to bind a value for an ECSQL parameter * > This is the most low-level API to bind a value to a specific parameter. Alternatively you can use the ECSqlStatement.bindXX methods @@ -299,7 +345,9 @@ export class ECSqlStatement implements IterableIterator, IDisposable { * * See also: [Code Samples]($docs/learning/backend/ECSQLCodeExamples) */ - public step(): DbResult { return this._stmt!.step(); } // eslint-disable-line @typescript-eslint/no-non-null-assertion + public step(): DbResult { + return this._stmt!.step(); + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** @internal added this back in for testing purposes */ public async stepAsync(): Promise { @@ -326,7 +374,9 @@ export class ECSqlStatement implements IterableIterator, IDisposable { } /** Get the query result's column count (only for ECSQL SELECT statements). */ - public getColumnCount(): number { return this._stmt!.getColumnCount(); } // eslint-disable-line @typescript-eslint/no-non-null-assertion + public getColumnCount(): number { + return this._stmt!.getColumnCount(); + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** Get the current row. * The returned row is formatted as JavaScript object where every SELECT clause item becomes a property in the JavaScript object. @@ -401,7 +451,9 @@ export class ECSqlStatement implements IterableIterator, IDisposable { } /** The iterator that will step through the results of this statement. */ - public [Symbol.iterator](): IterableIterator { return this; } + public [Symbol.iterator](): IterableIterator { + return this; + } /** Get the value for the column at the given index in the query result. * @param columnIx Index of ECSQL column in query result (0-based) @@ -427,7 +479,9 @@ export class ECSqlBinder { private _binder: IModelJsNative.ECSqlBinder; /** @internal */ - public constructor(binder: IModelJsNative.ECSqlBinder) { this._binder = binder; } + public constructor(binder: IModelJsNative.ECSqlBinder) { + this._binder = binder; + } /** Binds the specified value to the ECSQL parameter. * The section "[iTwin.js Types used in ECSQL Parameter Bindings]($docs/learning/ECSQLParameterTypes)" describes the @@ -557,14 +611,18 @@ export class ECSqlBinder { * @param val Struct value. The struct value is an object composed of pairs of a struct member property name and its value * (of one of the supported types) */ - public bindStruct(val: object): void { ECSqlBindingHelper.bindStruct(this, val); } + public bindStruct(val: object): void { + ECSqlBindingHelper.bindStruct(this, val); + } /** Gets the binder for the specified member of a struct parameter * * > This is the most low-level way to bind struct parameters with most flexibility. A simpler alternative is * > to just call [ECSqlBinder.bindStruct]($backend). */ - public bindMember(memberName: string): ECSqlBinder { return new ECSqlBinder(this._binder.bindMember(memberName)); } + public bindMember(memberName: string): ECSqlBinder { + return new ECSqlBinder(this._binder.bindMember(memberName)); + } /** Binds a set of Id strings to the ECSQL parameter. * @param val array of Id values. If passed as string they must be the hexadecimal representation of the Ids. @@ -578,14 +636,18 @@ export class ECSqlBinder { /** Binds an array value to the ECSQL parameter. * @param val Array value. The array value is an array of values of the supported types */ - public bindArray(val: any[]): void { ECSqlBindingHelper.bindArray(this, val); } + public bindArray(val: any[]): void { + ECSqlBindingHelper.bindArray(this, val); + } /** Adds a new array element to the array parameter and returns the binder for the new array element * * > This is the most low-level way to bind array parameters with most flexibility. A simpler alternative is * > to just call [ECSqlBinder.bindArray]($backend). */ - public addArrayElement(): ECSqlBinder { return new ECSqlBinder(this._binder.addArrayElement()); } + public addArrayElement(): ECSqlBinder { + return new ECSqlBinder(this._binder.addArrayElement()); + } } /** Represents the value of an ECEnumeration. @@ -616,42 +678,74 @@ export class ECSqlValue { private _val: IModelJsNative.ECSqlValue; /** @internal */ - public constructor(val: IModelJsNative.ECSqlValue) { this._val = val; } + public constructor(val: IModelJsNative.ECSqlValue) { + this._val = val; + } /** Get information about the query result's column this value refers to. */ - public get columnInfo(): ECSqlColumnInfo { return this._val.getColumnInfo() as ECSqlColumnInfo; } + public get columnInfo(): ECSqlColumnInfo { + return this._val.getColumnInfo() as ECSqlColumnInfo; + } /** Get the value of this ECSQL value */ - public get value(): any { return ECSqlValueHelper.getValue(this); } + public get value(): any { + return ECSqlValueHelper.getValue(this); + } /** Indicates whether the value is NULL or not. */ - public get isNull(): boolean { return this._val.isNull(); } + public get isNull(): boolean { + return this._val.isNull(); + } /** Get the value as BLOB */ - public getBlob(): Uint8Array { return this._val.getBlob(); } + public getBlob(): Uint8Array { + return this._val.getBlob(); + } /** Get the value as a boolean value */ - public getBoolean(): boolean { return this._val.getBoolean(); } + public getBoolean(): boolean { + return this._val.getBoolean(); + } /** Get the value as a DateTime value (formatted as ISO8601 string) */ - public getDateTime(): string { return this._val.getDateTime(); } + public getDateTime(): string { + return this._val.getDateTime(); + } /** Get the value as a double value */ - public getDouble(): number { return this._val.getDouble(); } + public getDouble(): number { + return this._val.getDouble(); + } /** Get the value as a IGeometry value (as ECJSON IGeometry) */ - public getGeometry(): any { return JSON.parse(this._val.getGeometry()); } + public getGeometry(): any { + return JSON.parse(this._val.getGeometry()); + } /** Get the value as a GUID (formatted as GUID string). * See [GuidString]($core-bentley) */ - public getGuid(): GuidString { return this._val.getGuid(); } + public getGuid(): GuidString { + return this._val.getGuid(); + } /** Get the value as a Id (formatted as hexadecimal string). */ - public getId(): Id64String { return this._val.getId(); } + public getId(): Id64String { + return this._val.getId(); + } /** Get the ClassId value formatted as fully qualified class name. */ - public getClassNameForClassId(): string { return this._val.getClassNameForClassId(); } + public getClassNameForClassId(): string { + return this._val.getClassNameForClassId(); + } /** Get the value as a integer value */ - public getInteger(): number { return this._val.getInt64(); } + public getInteger(): number { + return this._val.getInt64(); + } /** Get the value as a string value */ - public getString(): string { return this._val.getString(); } + public getString(): string { + return this._val.getString(); + } /** Get the value as [XAndY]($core-geometry) */ - public getXAndY(): XAndY { return this._val.getPoint2d(); } + public getXAndY(): XAndY { + return this._val.getPoint2d(); + } /** Get the value as [XYAndZ]($core-geometry) */ - public getXYAndZ(): XYAndZ { return this._val.getPoint3d(); } + public getXYAndZ(): XYAndZ { + return this._val.getPoint3d(); + } /** Get the value as ECEnumeration value * Note: This method is optional. Using [[ECSqlValue.getInteger]] for integral enums and * [[ECSqlValue.getString]] for string enums respectively are the usual way to get @@ -665,22 +759,34 @@ export class ECSqlValue { * @return ECEnumeration value(s) or undefined if the ECSqlValue does not represent an ECEnumeration. * or is not a strict match of an ECEnumerator or a combination of them. */ - public getEnum(): ECEnumValue[] | undefined { return this._val.getEnum(); } + public getEnum(): ECEnumValue[] | undefined { + return this._val.getEnum(); + } /** Get the value as [NavigationValue]($common) */ - public getNavigation(): NavigationValue { return this._val.getNavigation(); } + public getNavigation(): NavigationValue { + return this._val.getNavigation(); + } /** Get an iterator for iterating the struct members of this struct value. */ - public getStructIterator(): ECSqlValueIterator { return new ECSqlValueIterator(this._val.getStructIterator()); } + public getStructIterator(): ECSqlValueIterator { + return new ECSqlValueIterator(this._val.getStructIterator()); + } /** Get this struct value's content as object literal */ - public getStruct(): any { return ECSqlValueHelper.getStruct(this); } + public getStruct(): any { + return ECSqlValueHelper.getStruct(this); + } /** Get an iterator for iterating the array elements of this array value. */ - public getArrayIterator(): ECSqlValueIterator { return new ECSqlValueIterator(this._val.getArrayIterator()); } + public getArrayIterator(): ECSqlValueIterator { + return new ECSqlValueIterator(this._val.getArrayIterator()); + } /** Get this array value as JavaScript array */ - public getArray(): any[] { return ECSqlValueHelper.getArray(this); } + public getArray(): any[] { + return ECSqlValueHelper.getArray(this); + } } /** Iterator over members of a struct [ECSqlValue]($backend) or the elements of an array [ECSqlValue]($backend). @@ -691,7 +797,9 @@ export class ECSqlValueIterator implements IterableIterator { private _it: IModelJsNative.ECSqlValueIterator; /** @internal */ - public constructor(it: IModelJsNative.ECSqlValueIterator) { this._it = it; } + public constructor(it: IModelJsNative.ECSqlValueIterator) { + this._it = it; + } public next(): IteratorResult { if (this._it.moveNext()) @@ -700,7 +808,9 @@ export class ECSqlValueIterator implements IterableIterator { return { done: true, value: undefined }; } - public [Symbol.iterator](): IterableIterator { return this; } + public [Symbol.iterator](): IterableIterator { + return this; + } } /** Information about an ECSQL column in an ECSQL query result. @@ -759,7 +869,6 @@ export interface ECSqlColumnInfo { } class ECSqlBindingHelper { - /** Binds the specified value to the specified binder * @param binder Parameter Binder to bind to * @param val Value to be bound. (See [iTwin.js Types used in ECSQL Parameter Bindings]($docs/learning/ECSQLParameterTypes)) @@ -775,7 +884,7 @@ class ECSqlBindingHelper { return; } - if (typeof (val) === "object") { + if (typeof val === "object") { ECSqlBindingHelper.bindStruct(binder, val); return; } @@ -837,7 +946,7 @@ class ECSqlBindingHelper { return true; } - if (typeof (val) === "number") { + if (typeof val === "number") { if (Number.isInteger(val)) binder.bindInteger(val); else @@ -846,12 +955,12 @@ class ECSqlBindingHelper { return true; } - if (typeof (val) === "boolean") { + if (typeof val === "boolean") { binder.bindBoolean(val); return true; } - if (typeof (val) === "string") { + if (typeof val === "string") { binder.bindString(val); return true; } @@ -983,23 +1092,35 @@ class ECSqlValueHelper { if (!tableSpace) tableSpace = "main"; - return ecdb.withPreparedStatement(`SELECT s.Name, c.Name FROM [${tableSpace}].meta.ECSchemaDef s, JOIN [${tableSpace}].meta.ECClassDef c ON s.ECInstanceId=c.SchemaId WHERE c.ECInstanceId=?`, + return ecdb.withPreparedStatement( + `SELECT s.Name, c.Name FROM [${tableSpace}].meta.ECSchemaDef s, JOIN [${tableSpace}].meta.ECClassDef c ON s.ECInstanceId=c.SchemaId WHERE c.ECInstanceId=?`, (stmt: ECSqlStatement) => { stmt.bindId(1, classId); if (stmt.step() !== DbResult.BE_SQLITE_ROW) throw new IModelError(DbResult.BE_SQLITE_ERROR, `No class found with ECClassId ${classId} in table space ${tableSpace}.`); return `${stmt.getValue(0).getString()}.${stmt.getValue(1).getString()}`; - }); + }, + ); } } class ECSqlTypeHelper { - public static isBlob(val: any): val is Uint8Array { return val instanceof Uint8Array; } + public static isBlob(val: any): val is Uint8Array { + return val instanceof Uint8Array; + } - public static isXAndY(val: any): val is XAndY { return XYZ.isXAndY(val); } - public static isXYAndZ(val: any): val is XYAndZ { return XYZ.isXYAndZ(val); } - public static isLowAndHighXYZ(arg: any): arg is LowAndHighXYZ { return arg.low !== undefined && ECSqlTypeHelper.isXYAndZ(arg.low) && arg.high !== undefined && ECSqlTypeHelper.isXYAndZ(arg.high); } + public static isXAndY(val: any): val is XAndY { + return XYZ.isXAndY(val); + } + public static isXYAndZ(val: any): val is XYAndZ { + return XYZ.isXYAndZ(val); + } + public static isLowAndHighXYZ(arg: any): arg is LowAndHighXYZ { + return arg.low !== undefined && ECSqlTypeHelper.isXYAndZ(arg.low) && arg.high !== undefined && ECSqlTypeHelper.isXYAndZ(arg.high); + } - public static isNavigationBindingValue(val: any): val is NavigationBindingValue { return val.id !== undefined && typeof (val.id) === "string"; } + public static isNavigationBindingValue(val: any): val is NavigationBindingValue { + return val.id !== undefined && typeof (val.id) === "string"; + } } diff --git a/core/backend/src/Element.ts b/core/backend/src/Element.ts index e7af31e8ee77..b19abd49d3a8 100644 --- a/core/backend/src/Element.ts +++ b/core/backend/src/Element.ts @@ -8,20 +8,56 @@ import { CompressedId64Set, GuidString, Id64, Id64Set, Id64String, JsonUtils, OrderedId64Array } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, BisCodeSpec, Code, CodeScopeProps, CodeSpec, ConcreteEntityTypes, DefinitionElementProps, ElementAlignedBox3d, ElementGeometryBuilderParams, - ElementGeometryBuilderParamsForPart, ElementProps, EntityMetaData, EntityReferenceSet, GeometricElement2dProps, GeometricElement3dProps, GeometricElementProps, - GeometricModel2dProps, GeometricModel3dProps, GeometryPartProps, GeometryStreamProps, IModel, InformationPartitionElementProps, LineStyleProps, - ModelProps, PhysicalElementProps, PhysicalTypeProps, Placement2d, Placement3d, RelatedElement, RenderSchedule, RenderTimelineProps, - RepositoryLinkProps, SectionDrawingLocationProps, SectionDrawingProps, SectionType, SheetBorderTemplateProps, - SheetProps, SheetTemplateProps, SubjectProps, TypeDefinition, TypeDefinitionElementProps, UrlLinkProps, + AxisAlignedBox3d, + BisCodeSpec, + Code, + CodeScopeProps, + CodeSpec, + ConcreteEntityTypes, + DefinitionElementProps, + ElementAlignedBox3d, + ElementGeometryBuilderParams, + ElementGeometryBuilderParamsForPart, + ElementProps, + EntityMetaData, + EntityReferenceSet, + GeometricElement2dProps, + GeometricElement3dProps, + GeometricElementProps, + GeometricModel2dProps, + GeometricModel3dProps, + GeometryPartProps, + GeometryStreamProps, + IModel, + InformationPartitionElementProps, + LineStyleProps, + ModelProps, + PhysicalElementProps, + PhysicalTypeProps, + Placement2d, + Placement3d, + RelatedElement, + RenderSchedule, + RenderTimelineProps, + RepositoryLinkProps, + SectionDrawingLocationProps, + SectionDrawingProps, + SectionType, + SheetBorderTemplateProps, + SheetProps, + SheetTemplateProps, + SubjectProps, + TypeDefinition, + TypeDefinitionElementProps, + UrlLinkProps, } from "@itwin/core-common"; import { ClipVector, Range3d, Transform } from "@itwin/core-geometry"; import { Entity } from "./Entity"; import { IModelDb } from "./IModelDb"; import { IModelElementCloneContext } from "./IModelElementCloneContext"; +import { _elementWasCreated, _verifyChannel } from "./internal/Symbols"; import { DefinitionModel, DrawingModel, PhysicalModel, SectionDrawingModel } from "./Model"; import { SubjectOwnsSubjects } from "./NavigationRelationship"; -import { _elementWasCreated, _verifyChannel } from "./internal/Symbols"; /** Argument for the `Element.onXxx` static methods * @beta @@ -117,9 +153,13 @@ export interface OnSubModelIdArg extends OnElementArg { * @public */ export class Element extends Entity { - public static override get className(): string { return "Element"; } + public static override get className(): string { + return "Element"; + } /** @internal */ - public static override get protectedOperations() { return ["onInsert", "onUpdate", "onDelete"]; } + public static override get protectedOperations() { + return ["onInsert", "onUpdate", "onDelete"]; + } /** The ModelId of the [Model]($docs/bis/guide/fundamentals/model-fundamentals.md) containing this element */ public readonly model: Id64String; @@ -136,7 +176,7 @@ export class Element extends Entity { protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); - this.code = Code.fromJSON(props.code); // TODO: Validate props.code - don't silently fail if it is the wrong type + this.code = Code.fromJSON(props.code); // TODO: Validate props.code - don't silently fail if it is the wrong type this.model = RelatedElement.idFromJson(props.model); this.parent = RelatedElement.fromJSON(props.parent); this.federationGuid = props.federationGuid; @@ -155,7 +195,7 @@ export class Element extends Entity { const operation = "insert"; iModel.channels[_verifyChannel](arg.props.model); iModel.locks.checkSharedLock(props.model, "model", operation); // inserting requires shared lock on model - if (props.parent) // inserting requires shared lock on parent, if present + if (props.parent) // inserting requires shared lock on parent, if present iModel.locks.checkSharedLock(props.parent.id, "parent", operation); iModel.codeService?.verifyCode(arg); } @@ -189,7 +229,7 @@ export class Element extends Entity { * @note `this` is the class of the Element that was updated * @beta */ - protected static onUpdated(_arg: OnElementIdArg): void { } + protected static onUpdated(_arg: OnElementIdArg): void {} /** Called before an Element is deleted. * @note throw an exception to disallow the delete @@ -207,7 +247,7 @@ export class Element extends Entity { * @note `this` is the class of the Element that was deleted * @beta */ - protected static onDeleted(_arg: OnElementIdArg): void { } + protected static onDeleted(_arg: OnElementIdArg): void {} /** Called when an element with an instance of this class as its parent is about to be deleted. * @note throw an exception if the element should not be deleted @@ -216,91 +256,91 @@ export class Element extends Entity { * @note `this` is the class of the parent Element whose child will be deleted * @beta */ - protected static onChildDelete(_arg: OnChildElementIdArg): void { } + protected static onChildDelete(_arg: OnChildElementIdArg): void {} /** Called after an element with an instance of this class as its parent was successfully deleted. * @note `this` is the class of the parent Element whose child was deleted * @beta */ - protected static onChildDeleted(_arg: OnChildElementIdArg): void { } + protected static onChildDeleted(_arg: OnChildElementIdArg): void {} /** Called when a *new element* with an instance of this class as its parent is about to be inserted. * @note throw an exception if the element should not be inserted * @note `this` is the class of the prospective parent Element. * @beta */ - protected static onChildInsert(_arg: OnChildElementPropsArg): void { } + protected static onChildInsert(_arg: OnChildElementPropsArg): void {} /** Called after a *new element* with an instance of this class as its parent was inserted. * @note `this` is the class of the parent Element. * @beta */ - protected static onChildInserted(_arg: OnChildElementIdArg): void { } + protected static onChildInserted(_arg: OnChildElementIdArg): void {} /** Called when an element with an instance of this class as its parent is about to be updated. * @note throw an exception if the element should not be updated * @note `this` is the class of the parent Element. * @beta */ - protected static onChildUpdate(_arg: OnChildElementPropsArg): void { } + protected static onChildUpdate(_arg: OnChildElementPropsArg): void {} /** Called after an element with an instance of this the class as its parent was updated. * @note `this` is the class of the parent Element. * @beta */ - protected static onChildUpdated(_arg: OnChildElementIdArg): void { } + protected static onChildUpdated(_arg: OnChildElementIdArg): void {} /** Called when an *existing element* is about to be updated so that an instance of this class will become its new parent. * @note throw an exception if the element should not be added * @note `this` is the class of the prospective parent Element. * @beta */ - protected static onChildAdd(_arg: OnChildElementPropsArg): void { } + protected static onChildAdd(_arg: OnChildElementPropsArg): void {} /** Called after an *existing element* has been updated so that an instance of this class is its new parent. * @note `this` is the class of the new parent Element. * @beta */ - protected static onChildAdded(_arg: OnChildElementIdArg): void { } + protected static onChildAdded(_arg: OnChildElementIdArg): void {} /** Called when an element with an instance of this class as its parent is about to be updated change to a different parent. * @note throw an exception if the element should not be dropped * @note `this` is the class of the parent Element. * @beta */ - protected static onChildDrop(_arg: OnChildElementIdArg): void { } + protected static onChildDrop(_arg: OnChildElementIdArg): void {} /** Called after an element with an instance of this class as its previous parent was updated to have a new parent. * @note `this` is the class of the previous parent Element. * @beta */ - protected static onChildDropped(_arg: OnChildElementIdArg): void { } + protected static onChildDropped(_arg: OnChildElementIdArg): void {} /** Called when an instance of this class is being *sub-modeled* by a new Model. * @note throw an exception if model should not be inserted * @note `this` is the class of Element to be sub-modeled. * @beta */ - protected static onSubModelInsert(_arg: OnSubModelPropsArg): void { } + protected static onSubModelInsert(_arg: OnSubModelPropsArg): void {} /** Called after an instance of this class was *sub-modeled* by a new Model. * @note `this` is the class of Element that is now sub-modeled. * @beta */ - protected static onSubModelInserted(_arg: OnSubModelIdArg): void { } + protected static onSubModelInserted(_arg: OnSubModelIdArg): void {} /** Called when a sub-model of an instance of this class is being deleted. * @note throw an exception if model should not be deleted * @note `this` is the class of Element that is sub-modeled. * @beta */ - protected static onSubModelDelete(_arg: OnSubModelIdArg): void { } + protected static onSubModelDelete(_arg: OnSubModelIdArg): void {} /** Called after a sub-model of an instance of this class was deleted. * @note `this` is the class of Element that was sub-modeled. * @beta */ - protected static onSubModelDeleted(_arg: OnSubModelIdArg): void { } + protected static onSubModelDeleted(_arg: OnSubModelIdArg): void {} /** Called during the iModel transformation process after an Element from the source iModel was *cloned* for the target iModel. * The transformation process automatically handles remapping BisCore properties and those that are properly described in ECSchema. @@ -311,7 +351,7 @@ export class Element extends Entity { * @note If you override this method, you must call super. * @beta */ - protected static onCloned(_context: IModelElementCloneContext, _sourceProps: ElementProps, _targetProps: ElementProps): void { } + protected static onCloned(_context: IModelElementCloneContext, _sourceProps: ElementProps, _targetProps: ElementProps): void {} /** Called when a *root* element in a subgraph is changed and before its outputs are processed. * This special callback is made when: @@ -321,7 +361,7 @@ export class Element extends Entity { * @see [[ElementDrivesElement]] for more on element dependency graphs. * @beta */ - protected static onBeforeOutputsHandled(_id: Id64String, _iModel: IModelDb): void { } + protected static onBeforeOutputsHandled(_id: Id64String, _iModel: IModelDb): void {} /** Called on an element in a graph after all of its inputs have been processed and before its outputs are processed. * This callback is made when: @@ -333,7 +373,7 @@ export class Element extends Entity { * @see [[ElementDrivesElement]] for more on element dependency graphs. * @beta */ - protected static onAllInputsHandled(_id: Id64String, _iModel: IModelDb): void { } + protected static onAllInputsHandled(_id: Id64String, _iModel: IModelDb): void {} public override toJSON(): ElementProps { const val = super.toJSON() as ElementProps; @@ -399,7 +439,9 @@ export class Element extends Entity { }; /** Get the class metadata for this element. */ - public getClassMetaData(): EntityMetaData | undefined { return this.iModel.classMetaDataRegistry.find(this.classFullName); } + public getClassMetaData(): EntityMetaData | undefined { + return this.iModel.classMetaDataRegistry.find(this.classFullName); + } private getAllUserProperties(): any { if (!this.jsonProperties.UserProps) @@ -409,20 +451,32 @@ export class Element extends Entity { } /** Get a set of JSON user properties by namespace */ - public getUserProperties(namespace: string) { return this.getAllUserProperties()[namespace]; } + public getUserProperties(namespace: string) { + return this.getAllUserProperties()[namespace]; + } /** Change a set of user JSON properties of this Element by namespace. */ - public setUserProperties(nameSpace: string, value: any) { this.getAllUserProperties()[nameSpace] = value; } + public setUserProperties(nameSpace: string, value: any) { + this.getAllUserProperties()[nameSpace] = value; + } /** Remove a set of JSON user properties, specified by namespace, from this Element */ - public removeUserProperties(nameSpace: string) { delete this.getAllUserProperties()[nameSpace]; } + public removeUserProperties(nameSpace: string) { + delete this.getAllUserProperties()[nameSpace]; + } /** Get a JSON property of this element, by namespace */ - public getJsonProperty(nameSpace: string): any { return this.jsonProperties[nameSpace]; } - public setJsonProperty(nameSpace: string, value: any) { this.jsonProperties[nameSpace] = value; } + public getJsonProperty(nameSpace: string): any { + return this.jsonProperties[nameSpace]; + } + public setJsonProperty(nameSpace: string, value: any) { + this.jsonProperties[nameSpace] = value; + } /** Get a display label for this Element. By default returns userLabel if present, otherwise code value. */ - public getDisplayLabel(): string { return this.userLabel ?? this.code.value; } + public getDisplayLabel(): string { + return this.userLabel ?? this.code.value; + } /** Get a list of HTML strings that describe this Element for the tooltip. Strings will be listed on separate lines in the tooltip. * Any instances of the pattern `%{tag}` will be replaced by the localized value of tag. @@ -452,16 +506,22 @@ export class Element extends Entity { return this.id = this.iModel.elements.insertElement(this.toJSON()); } /** Update this Element in the iModel. */ - public update() { this.iModel.elements.updateElement(this.toJSON()); } + public update() { + this.iModel.elements.updateElement(this.toJSON()); + } /** Delete this Element from the iModel. */ - public delete() { this.iModel.elements.deleteElement(this.id); } + public delete() { + this.iModel.elements.deleteElement(this.id); + } } /** An abstract base class to model real world entities that intrinsically have geometry. * @public */ export abstract class GeometricElement extends Element { - public static override get className(): string { return "GeometricElement"; } + public static override get className(): string { + return "GeometricElement"; + } /** The Id of the [[Category]] for this GeometricElement. */ public category: Id64String; /** The GeometryStream for this GeometricElement. */ @@ -480,12 +540,20 @@ export abstract class GeometricElement extends Element { } /** Type guard for instanceof [[GeometricElement3d]] */ - public is3d(): this is GeometricElement3d { return this instanceof GeometricElement3d; } + public is3d(): this is GeometricElement3d { + return this instanceof GeometricElement3d; + } /** Type guard for instanceof [[GeometricElement2d]] */ - public is2d(): this is GeometricElement2d { return this instanceof GeometricElement2d; } + public is2d(): this is GeometricElement2d { + return this instanceof GeometricElement2d; + } /** Get the [Transform]($geometry) from the Placement of this GeometricElement */ - public getPlacementTransform(): Transform { return this.placement.transform; } - public calculateRange3d(): AxisAlignedBox3d { return this.placement.calculateRange(); } + public getPlacementTransform(): Transform { + return this.placement.transform; + } + public calculateRange3d(): AxisAlignedBox3d { + return this.placement.calculateRange(); + } public override toJSON(): GeometricElementProps { const val = super.toJSON() as GeometricElementProps; @@ -515,7 +583,9 @@ export abstract class GeometricElement extends Element { * @public */ export abstract class GeometricElement3d extends GeometricElement { - public static override get className(): string { return "GeometricElement3d"; } + public static override get className(): string { + return "GeometricElement3d"; + } public placement: Placement3d; public typeDefinition?: TypeDefinition; @@ -546,15 +616,21 @@ export abstract class GeometricElement3d extends GeometricElement { * @public */ export abstract class GraphicalElement3d extends GeometricElement3d { - public static override get className(): string { return "GraphicalElement3d"; } - protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "GraphicalElement3d"; + } + protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } /** An abstract base class to model information entities that intrinsically have 2d geometry. * @public */ export abstract class GeometricElement2d extends GeometricElement { - public static override get className(): string { return "GeometricElement2d"; } + public static override get className(): string { + return "GeometricElement2d"; + } public placement: Placement2d; public typeDefinition?: TypeDefinition; @@ -585,39 +661,57 @@ export abstract class GeometricElement2d extends GeometricElement { * @public */ export abstract class GraphicalElement2d extends GeometricElement2d { - public static override get className(): string { return "GraphicalElement2d"; } - protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "GraphicalElement2d"; + } + protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { + super(props, iModel); + } } /** 2d element used to annotate drawings and sheets. * @public */ export class AnnotationElement2d extends GraphicalElement2d { - public static override get className(): string { return "AnnotationElement2d"; } - protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "AnnotationElement2d"; + } + protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { + super(props, iModel); + } } /** 2d element used to persist graphics for use in drawings. * @public */ export class DrawingGraphic extends GraphicalElement2d { - public static override get className(): string { return "DrawingGraphic"; } - protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "DrawingGraphic"; + } + protected constructor(props: GeometricElement2dProps, iModel: IModelDb) { + super(props, iModel); + } } /** An Element that occupies real world space. Its coordinates are in the project space of its iModel. * @public */ export abstract class SpatialElement extends GeometricElement3d { - public static override get className(): string { return "SpatialElement"; } - protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "SpatialElement"; + } + protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } /** An Element that is spatially located, has mass, and can be *touched*. * @public */ export abstract class PhysicalElement extends SpatialElement { - public static override get className(): string { return "PhysicalElement"; } + public static override get className(): string { + return "PhysicalElement"; + } /** If defined, the [[PhysicalMaterial]] that makes up this PhysicalElement. */ public physicalMaterial?: RelatedElement; protected constructor(props: PhysicalElementProps, iModel: IModelDb) { @@ -636,16 +730,24 @@ export abstract class PhysicalElement extends SpatialElement { * @public */ export abstract class SpatialLocationElement extends SpatialElement { - public static override get className(): string { return "SpatialLocationElement"; } - protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "SpatialLocationElement"; + } + protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } /** A Volume Element is a Spatial Location Element that is restricted to defining a volume. * @public */ export class VolumeElement extends SpatialLocationElement { - public static override get className(): string { return "VolumeElement"; } - protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "VolumeElement"; + } + protected constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } /** A SectionDrawingLocation element identifies the location of a [[SectionDrawing]] in the context of a [[SpatialModel]], @@ -657,7 +759,9 @@ export class SectionDrawingLocation extends SpatialLocationElement { /** The Id of the [[ViewDefinition]] to which this location refers. */ public sectionView: RelatedElement; - public static override get className(): string { return "SectionDrawingLocation"; } + public static override get className(): string { + return "SectionDrawingLocation"; + } public constructor(props: SectionDrawingLocationProps, iModel: IModelDb) { super(props, iModel); @@ -678,8 +782,12 @@ export class SectionDrawingLocation extends SpatialLocationElement { * @public */ export abstract class InformationContentElement extends Element { - public static override get className(): string { return "InformationContentElement"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "InformationContentElement"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Element used in conjunction with bis:ElementDrivesElement relationships to bundle multiple inputs before @@ -687,17 +795,25 @@ export abstract class InformationContentElement extends Element { * @beta */ export abstract class DriverBundleElement extends InformationContentElement { - public static override get className(): string { return "DriverBundleElement"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "DriverBundleElement"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Information Reference is an abstract base class for modeling entities whose main purpose is to reference something else. * @public */ export abstract class InformationReferenceElement extends InformationContentElement { - public static override get className(): string { return "InformationReferenceElement"; } + public static override get className(): string { + return "InformationReferenceElement"; + } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** A Subject is an information element that describes what this repository (or part thereof) is about. @@ -705,9 +821,13 @@ export abstract class InformationReferenceElement extends InformationContentElem * @public */ export class Subject extends InformationReferenceElement { - public static override get className(): string { return "Subject"; } + public static override get className(): string { + return "Subject"; + } public description?: string; - protected constructor(props: SubjectProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: SubjectProps, iModel: IModelDb) { + super(props, iModel); + } public override toJSON(): SubjectProps { // This override only specializes the return type return super.toJSON() as SubjectProps; // Entity.toJSON takes care of auto-handled properties @@ -762,19 +882,29 @@ export class Subject extends InformationReferenceElement { * @public */ export abstract class Document extends InformationContentElement { - public static override get className(): string { return "Document"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Document"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** A document that represents a drawing, that is, a two-dimensional graphical representation of engineering data. A Drawing element is usually modelled by a [[DrawingModel]]. * @public */ export class Drawing extends Document { - public static override get className(): string { return "Drawing"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Drawing"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } /** The name of the DrawingModel class modeled by this element type. */ - protected static get drawingModelFullClassName(): string { return DrawingModel.classFullName; } + protected static get drawingModelFullClassName(): string { + return DrawingModel.classFullName; + } /** Create a Code for a Drawing given a name that is meant to be unique within the scope of the specified DocumentListModel. * @param iModel The IModelDb @@ -830,9 +960,13 @@ export class SectionDrawing extends Drawing { /** If true, when displaying the section drawing as a [DrawingViewState]($frontend), the [[spatialView]] will also be displayed. */ public displaySpatialView: boolean; - public static override get className(): string { return "SectionDrawing"; } + public static override get className(): string { + return "SectionDrawing"; + } - protected static override get drawingModelFullClassName(): string { return SectionDrawingModel.classFullName; } + protected static override get drawingModelFullClassName(): string { + return SectionDrawingModel.classFullName; + } protected constructor(props: SectionDrawingProps, iModel: IModelDb) { super(props, iModel); @@ -877,22 +1011,30 @@ export class SectionDrawing extends Drawing { * @public */ export class SheetBorderTemplate extends Document { - public static override get className(): string { return "SheetBorderTemplate"; } + public static override get className(): string { + return "SheetBorderTemplate"; + } public height?: number; public width?: number; - protected constructor(props: SheetBorderTemplateProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: SheetBorderTemplateProps, iModel: IModelDb) { + super(props, iModel); + } } /** The template for a [[Sheet]] * @public */ export class SheetTemplate extends Document { - public static override get className(): string { return "SheetTemplate"; } + public static override get className(): string { + return "SheetTemplate"; + } public height?: number; public width?: number; public border?: Id64String; - protected constructor(props: SheetTemplateProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: SheetTemplateProps, iModel: IModelDb) { + super(props, iModel); + } protected override collectReferenceIds(referenceIds: EntityReferenceSet): void { super.collectReferenceIds(referenceIds); @@ -905,7 +1047,9 @@ export class SheetTemplate extends Document { * @public */ export class Sheet extends Document { - public static override get className(): string { return "Sheet"; } + public static override get className(): string { + return "Sheet"; + } public height: number; public width: number; public scale?: number; @@ -941,16 +1085,22 @@ export class Sheet extends Document { * @public */ export abstract class InformationRecordElement extends InformationContentElement { - public static override get className(): string { return "InformationRecordElement"; } + public static override get className(): string { + return "InformationRecordElement"; + } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** A Definition Element holds configuration-related information that is meant to be referenced / shared. * @public */ export abstract class DefinitionElement extends InformationContentElement { - public static override get className(): string { return "DefinitionElement"; } + public static override get className(): string { + return "DefinitionElement"; + } /** If true, don't show this DefinitionElement in user interface lists. */ public isPrivate: boolean; @@ -971,7 +1121,9 @@ export abstract class DefinitionElement extends InformationContentElement { * @public */ export abstract class DefinitionSet extends DefinitionElement { - public static override get className(): string { return "DefinitionSet"; } + public static override get className(): string { + return "DefinitionSet"; + } } /** A DefinitionContainer exclusively owns a set of DefinitionElements contained within its sub-model (of type DefinitionModel). @@ -979,7 +1131,9 @@ export abstract class DefinitionSet extends DefinitionElement { * @public */ export class DefinitionContainer extends DefinitionSet { - public static override get className(): string { return "DefinitionContainer"; } + public static override get className(): string { + return "DefinitionContainer"; + } /** Create a DefinitionContainer * @param iModelDb The IModelDb * @param definitionModelId The Id of the [DefinitionModel]($backend) that will contain this DefinitionContainer element. @@ -1025,7 +1179,9 @@ export class DefinitionContainer extends DefinitionSet { * @public */ export class DefinitionGroup extends DefinitionSet { - public static override get className(): string { return "DefinitionGroup"; } + public static override get className(): string { + return "DefinitionGroup"; + } /** Create a DefinitionGroup * @param iModelDb The IModelDb * @param definitionModelId The Id of the [DefinitionModel]($backend) that will contain this DefinitionGroup element. @@ -1050,10 +1206,14 @@ export class DefinitionGroup extends DefinitionSet { * @public */ export abstract class TypeDefinitionElement extends DefinitionElement { - public static override get className(): string { return "TypeDefinitionElement"; } + public static override get className(): string { + return "TypeDefinitionElement"; + } public recipe?: RelatedElement; - protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } protected override collectReferenceIds(referenceIds: EntityReferenceSet): void { super.collectReferenceIds(referenceIds); @@ -1066,8 +1226,12 @@ export abstract class TypeDefinitionElement extends DefinitionElement { * @beta */ export abstract class RecipeDefinitionElement extends DefinitionElement { - public static override get className(): string { return "RecipeDefinitionElement"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "RecipeDefinitionElement"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Defines a set of properties (the *type*) that can be associated with a Physical Element. A Physical @@ -1076,7 +1240,9 @@ export abstract class RecipeDefinitionElement extends DefinitionElement { * @public */ export abstract class PhysicalType extends TypeDefinitionElement { - public static override get className(): string { return "PhysicalType"; } + public static override get className(): string { + return "PhysicalType"; + } /** If defined, the [[PhysicalMaterial]] that makes up this PhysicalType. */ public physicalMaterial?: RelatedElement; protected constructor(props: PhysicalTypeProps, iModel: IModelDb) { @@ -1104,8 +1270,12 @@ export abstract class PhysicalType extends TypeDefinitionElement { * @public */ export abstract class SpatialLocationType extends TypeDefinitionElement { - public static override get className(): string { return "SpatialLocationType"; } - protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "SpatialLocationType"; + } + protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a SpatialLocationType element given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb @@ -1122,9 +1292,13 @@ export abstract class SpatialLocationType extends TypeDefinitionElement { * @beta */ export class TemplateRecipe3d extends RecipeDefinitionElement { - public static override get className(): string { return "TemplateRecipe3d"; } + public static override get className(): string { + return "TemplateRecipe3d"; + } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a TemplateRecipe3d given a name that is meant to be unique within the scope of its Model. * @param iModelDb The IModelDb @@ -1175,9 +1349,13 @@ export class TemplateRecipe3d extends RecipeDefinitionElement { * @public */ export abstract class GraphicalType2d extends TypeDefinitionElement { - public static override get className(): string { return "GraphicalType2d"; } + public static override get className(): string { + return "GraphicalType2d"; + } - protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a GraphicalType2d element given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb @@ -1194,8 +1372,12 @@ export abstract class GraphicalType2d extends TypeDefinitionElement { * @beta */ export class TemplateRecipe2d extends RecipeDefinitionElement { - public static override get className(): string { return "TemplateRecipe2d"; } - protected constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "TemplateRecipe2d"; + } + protected constructor(props: ElementProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a TemplateRecipe2d given a name that is meant to be unique within the scope of its Model. * @param iModelDb The IModelDb @@ -1248,11 +1430,15 @@ export class TemplateRecipe2d extends RecipeDefinitionElement { * @public */ export abstract class InformationPartitionElement extends InformationContentElement { - public static override get className(): string { return "InformationPartitionElement"; } + public static override get className(): string { + return "InformationPartitionElement"; + } /** A human-readable string describing the intent of the partition. */ public description?: string; - protected constructor(props: InformationPartitionElementProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: InformationPartitionElementProps, iModel: IModelDb) { + super(props, iModel); + } public override toJSON(): InformationPartitionElementProps { // This override only specializes the return type return super.toJSON() as InformationPartitionElementProps; // Entity.toJSON takes care of auto-handled properties @@ -1274,7 +1460,9 @@ export abstract class InformationPartitionElement extends InformationContentElem * @public */ export class DefinitionPartition extends InformationPartitionElement { - public static override get className(): string { return "DefinitionPartition"; } + public static override get className(): string { + return "DefinitionPartition"; + } } /** A DocumentPartition element establishes a *Document* modeling perspective for its parent Subject. @@ -1283,7 +1471,9 @@ export class DefinitionPartition extends InformationPartitionElement { * @public */ export class DocumentPartition extends InformationPartitionElement { - public static override get className(): string { return "DocumentPartition"; } + public static override get className(): string { + return "DocumentPartition"; + } } /** A GroupInformationPartition element establishes a *Group Information* modeling perspective for its parent Subject. @@ -1292,7 +1482,9 @@ export class DocumentPartition extends InformationPartitionElement { * @public */ export class GroupInformationPartition extends InformationPartitionElement { - public static override get className(): string { return "GroupInformationPartition"; } + public static override get className(): string { + return "GroupInformationPartition"; + } } /** A GraphicalPartition3d element establishes a *3D Graphical* modeling perspective for its parent Subject. @@ -1302,7 +1494,9 @@ export class GroupInformationPartition extends InformationPartitionElement { * @public */ export class GraphicalPartition3d extends InformationPartitionElement { - public static override get className(): string { return "GraphicalPartition3d"; } + public static override get className(): string { + return "GraphicalPartition3d"; + } } /** An InformationRecordPartition element establishes a *Information Record* modeling perspective for its parent Subject. @@ -1311,7 +1505,9 @@ export class GraphicalPartition3d extends InformationPartitionElement { * @public */ export class InformationRecordPartition extends InformationPartitionElement { - public static override get className(): string { return "InformationRecordPartition"; } + public static override get className(): string { + return "InformationRecordPartition"; + } } /** A LinkPartition element establishes a *Link* modeling perspective for its parent Subject. A LinkPartition is always sub-modeled by a LinkModel. @@ -1319,7 +1515,9 @@ export class InformationRecordPartition extends InformationPartitionElement { * @public */ export class LinkPartition extends InformationPartitionElement { - public static override get className(): string { return "LinkPartition"; } + public static override get className(): string { + return "LinkPartition"; + } } /** A PhysicalPartition element establishes a *Physical* modeling perspective for its parent Subject. A PhysicalPartition is always sub-modeled by a PhysicalModel. @@ -1327,7 +1525,9 @@ export class LinkPartition extends InformationPartitionElement { * @public */ export class PhysicalPartition extends InformationPartitionElement { - public static override get className(): string { return "PhysicalPartition"; } + public static override get className(): string { + return "PhysicalPartition"; + } } /** A SpatialLocationPartition element establishes a *SpatialLocation* modeling perspective for its parent Subject. @@ -1336,7 +1536,9 @@ export class PhysicalPartition extends InformationPartitionElement { * @public */ export class SpatialLocationPartition extends InformationPartitionElement { - public static override get className(): string { return "SpatialLocationPartition"; } + public static override get className(): string { + return "SpatialLocationPartition"; + } } /** A SheetIndexPartition element establishes a [[SheetIndex]] modeling perspective for its parent [[Subject]]. @@ -1344,21 +1546,27 @@ export class SpatialLocationPartition extends InformationPartitionElement { * @beta */ export class SheetIndexPartition extends InformationPartitionElement { - public static override get className(): string { return "SheetIndexPartition"; } + public static override get className(): string { + return "SheetIndexPartition"; + } } /** Group Information is an abstract base class for modeling entities whose main purpose is to reference a group of related elements. * @public */ export abstract class GroupInformationElement extends InformationReferenceElement { - public static override get className(): string { return "GroupInformationElement"; } + public static override get className(): string { + return "GroupInformationElement"; + } } /** An information element that specifies a link. * @public */ export abstract class LinkElement extends InformationReferenceElement { - public static override get className(): string { return "LinkElement"; } + public static override get className(): string { + return "LinkElement"; + } /** Create a Code for a LinkElement given a name that is meant to be unique within the scope of the specified Model. * @param iModel The IModelDb * @param scopeModelId The Id of the Model that contains the LinkElement and provides the scope for its name. @@ -1374,7 +1582,9 @@ export abstract class LinkElement extends InformationReferenceElement { * @public */ export class UrlLink extends LinkElement { - public static override get className(): string { return "UrlLink"; } + public static override get className(): string { + return "UrlLink"; + } public description?: string; public url?: string; @@ -1397,14 +1607,18 @@ export class UrlLink extends LinkElement { * @alpha */ export class FolderLink extends UrlLink { - public static override get className(): string { return "FolderLink"; } + public static override get className(): string { + return "FolderLink"; + } } /** An information element that links to a repository. * @public */ export class RepositoryLink extends UrlLink { - public static override get className(): string { return "RepositoryLink"; } + public static override get className(): string { + return "RepositoryLink"; + } public repositoryGuid?: GuidString; /** @note This property was added to the BisCore schema in version 1.0.13 */ public format?: string; @@ -1427,7 +1641,9 @@ export class RepositoryLink extends UrlLink { * @public */ export class EmbeddedFileLink extends LinkElement { - public static override get className(): string { return "EmbeddedFileLink"; } + public static override get className(): string { + return "EmbeddedFileLink"; + } } /** A real world entity is modeled as a Role Element when a set of external circumstances define an important @@ -1436,7 +1652,9 @@ export class EmbeddedFileLink extends LinkElement { * @public */ export abstract class RoleElement extends Element { - public static override get className(): string { return "RoleElement"; } + public static override get className(): string { + return "RoleElement"; + } } /** A Definition Element that specifies a collection of geometry that is meant to be reused across Geometric @@ -1444,7 +1662,9 @@ export abstract class RoleElement extends Element { * @public */ export class GeometryPart extends DefinitionElement { - public static override get className(): string { return "GeometryPart"; } + public static override get className(): string { + return "GeometryPart"; + } public geom?: GeometryStreamProps; /** How to build the part's GeometryStream. This is used for insert and update only. It is not a persistent property. It will be undefined in the properties returned by functions that read a persistent element. It may be specified as an alternative to `geom` when inserting or updating an element. * @beta @@ -1481,11 +1701,15 @@ export class GeometryPart extends DefinitionElement { * @public */ export class LineStyle extends DefinitionElement { - public static override get className(): string { return "LineStyle"; } + public static override get className(): string { + return "LineStyle"; + } public description?: string; public data!: string; - protected constructor(props: LineStyleProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: LineStyleProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a LineStyle definition given a name that is meant to be unique within the scope of the specified model. * @param iModel The IModel @@ -1503,7 +1727,9 @@ export class LineStyle extends DefinitionElement { * @public */ export class RenderTimeline extends InformationRecordElement { - public static override get className(): string { return "RenderTimeline"; } + public static override get className(): string { + return "RenderTimeline"; + } /** A human-readable description of the timeline, which may be an empty string. */ public description: string; /** The JSON representation of the instructions for visualizing change over time. diff --git a/core/backend/src/ElementAspect.ts b/core/backend/src/ElementAspect.ts index feb820c6d662..208abf86bc8a 100644 --- a/core/backend/src/ElementAspect.ts +++ b/core/backend/src/ElementAspect.ts @@ -6,11 +6,11 @@ * @module ElementAspects */ +import { DbResult, Id64String } from "@itwin/core-bentley"; import { ChannelRootAspectProps, ElementAspectProps, EntityReferenceSet, ExternalSourceAspectProps, RelatedElement } from "@itwin/core-common"; +import { ECSqlStatement } from "./ECSqlStatement"; import { Entity } from "./Entity"; import { IModelDb } from "./IModelDb"; -import { ECSqlStatement } from "./ECSqlStatement"; -import { DbResult, Id64String } from "@itwin/core-bentley"; import { _verifyChannel } from "./internal/Symbols"; /** Argument for the `ElementAspect.onXxx` static methods @@ -43,7 +43,9 @@ export interface OnAspectIdArg extends OnAspectArg { * @public */ export class ElementAspect extends Entity { - public static override get className(): string { return "ElementAspect"; } + public static override get className(): string { + return "ElementAspect"; + } public element: RelatedElement; /** Construct an aspect from its JSON representation and its containing iModel. */ @@ -73,7 +75,7 @@ export class ElementAspect extends Entity { * @note If you override this method, you must call super. * @beta */ - protected static onInserted(_arg: OnAspectPropsArg): void { } + protected static onInserted(_arg: OnAspectPropsArg): void {} /** Called before an ElementAspect is updated. * @note throw an exception to disallow the update @@ -90,7 +92,7 @@ export class ElementAspect extends Entity { * @note If you override this method, you must call super. * @beta */ - protected static onUpdated(_arg: OnAspectPropsArg): void { } + protected static onUpdated(_arg: OnAspectPropsArg): void {} /** Called before an ElementAspect is deleted. * @note throw an exception to disallow the delete @@ -108,27 +110,33 @@ export class ElementAspect extends Entity { * @note If you override this method, you must call super. * @beta */ - protected static onDeleted(_arg: OnAspectIdArg): void { } + protected static onDeleted(_arg: OnAspectIdArg): void {} } /** An Element Unique Aspect is an ElementAspect where there can be only zero or one instance of the Element Aspect class per Element. * @public */ export class ElementUniqueAspect extends ElementAspect { - public static override get className(): string { return "ElementUniqueAspect"; } + public static override get className(): string { + return "ElementUniqueAspect"; + } } /** An Element Multi-Aspect is an ElementAspect where there can be **n** instances of the Element Aspect class per Element. * @public */ export class ElementMultiAspect extends ElementAspect { - public static override get className(): string { return "ElementMultiAspect"; } + public static override get className(): string { + return "ElementMultiAspect"; + } } /** * @public */ export class ChannelRootAspect extends ElementUniqueAspect { - public static override get className(): string { return "ChannelRootAspect"; } + public static override get className(): string { + return "ChannelRootAspect"; + } /** Insert a ChannelRootAspect on the specified element. * @deprecated in 4.0 use [[ChannelControl.makeChannelRoot]]. This method does not enforce the rule that channels may not nest and is therefore dangerous. */ @@ -143,7 +151,9 @@ export class ChannelRootAspect extends ElementUniqueAspect { * @public */ export class ExternalSourceAspect extends ElementMultiAspect { - public static override get className(): string { return "ExternalSourceAspect"; } + public static override get className(): string { + return "ExternalSourceAspect"; + } /** An element that scopes the combination of `kind` and `identifier` to uniquely identify the object from the external source. * @note Warning: in a future major release the `scope` property will be optional, since the scope is intended to be potentially invalid. @@ -182,8 +192,14 @@ export class ExternalSourceAspect extends ElementMultiAspect { } /** @deprecated in 3.x. findAllBySource */ - public static findBySource(iModelDb: IModelDb, scope: Id64String, kind: string, identifier: string): { elementId?: Id64String, aspectId?: Id64String } { - const sql = `SELECT Element.Id, ECInstanceId FROM ${ExternalSourceAspect.classFullName} WHERE (Scope.Id=:scope AND Kind=:kind AND Identifier=:identifier)`; + public static findBySource( + iModelDb: IModelDb, + scope: Id64String, + kind: string, + identifier: string, + ): { elementId?: Id64String, aspectId?: Id64String } { + const sql = + `SELECT Element.Id, ECInstanceId FROM ${ExternalSourceAspect.classFullName} WHERE (Scope.Id=:scope AND Kind=:kind AND Identifier=:identifier)`; let elementId: Id64String | undefined; let aspectId: Id64String | undefined; iModelDb.withPreparedStatement(sql, (statement: ECSqlStatement) => { @@ -209,9 +225,15 @@ export class ExternalSourceAspect extends ElementMultiAspect { * @param kind The kind of the ExternalSourceAspects to find * @param identifier The identifier of the ExternalSourceAspects to find * @returns the query results - */ - public static findAllBySource(iModelDb: IModelDb, scope: Id64String, kind: string, identifier: string): Array<{ elementId: Id64String, aspectId: Id64String }> { - const sql = `SELECT Element.Id, ECInstanceId FROM ${ExternalSourceAspect.classFullName} WHERE (Scope.Id=:scope AND Kind=:kind AND Identifier=:identifier)`; + */ + public static findAllBySource( + iModelDb: IModelDb, + scope: Id64String, + kind: string, + identifier: string, + ): Array<{ elementId: Id64String, aspectId: Id64String }> { + const sql = + `SELECT Element.Id, ECInstanceId FROM ${ExternalSourceAspect.classFullName} WHERE (Scope.Id=:scope AND Kind=:kind AND Identifier=:identifier)`; const found: Array<{ elementId: Id64String, aspectId: Id64String }> = []; iModelDb.withPreparedStatement(sql, (statement: ECSqlStatement) => { statement.bindId("scope", scope); diff --git a/core/backend/src/ElementGraphics.ts b/core/backend/src/ElementGraphics.ts index 9b23598d3330..a8e9f236156f 100644 --- a/core/backend/src/ElementGraphics.ts +++ b/core/backend/src/ElementGraphics.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ElementGraphicsStatus } from "@bentley/imodeljs-native"; import { assert, IModelStatus } from "@itwin/core-bentley"; import { ElementGraphicsRequestProps, IModelError } from "@itwin/core-common"; -import { ElementGraphicsStatus } from "@bentley/imodeljs-native"; import { IModelDb } from "./IModelDb"; import { _nativeDb } from "./internal/Symbols"; diff --git a/core/backend/src/ElementTreeWalker.ts b/core/backend/src/ElementTreeWalker.ts index bc83aec030e6..9e04ce0e51be 100644 --- a/core/backend/src/ElementTreeWalker.ts +++ b/core/backend/src/ElementTreeWalker.ts @@ -15,7 +15,10 @@ import { DefinitionModel, Model } from "./Model"; const loggerCategory = `${BackendLoggerCategory.IModelDb}.ElementTreeWalker`; /** @beta */ -export interface ElementTreeWalkerModelInfo { model: Model, isDefinitionModel: boolean } +export interface ElementTreeWalkerModelInfo { + model: Model; + isDefinitionModel: boolean; +} function sortChildrenBeforeParents(iModel: IModelDb, ids: Id64Array): Array { const children: Id64Array = []; @@ -46,7 +49,12 @@ function isDefinitionModel(model: Model): boolean { return (model.id !== IModel.repositoryModelId) && (model instanceof DefinitionModel); } -enum ElementPruningClassification { PRUNING_CLASS_Normal = 0, PRUNING_CLASS_Subject = 1, PRUNING_CLASS_Definition = 2, PRUNING_CLASS_DefinitionPartition = 3, } +enum ElementPruningClassification { + PRUNING_CLASS_Normal = 0, + PRUNING_CLASS_Subject = 1, + PRUNING_CLASS_Definition = 2, + PRUNING_CLASS_DefinitionPartition = 3, +} function classifyElementForPruning(iModel: IModelDb, elementId: Id64String): ElementPruningClassification { const el = iModel.elements.getElement(elementId); @@ -55,10 +63,13 @@ function classifyElementForPruning(iModel: IModelDb, elementId: Id64String): Ele // That is why we special-case it here. if (el instanceof DefinitionContainer) return ElementPruningClassification.PRUNING_CLASS_DefinitionPartition; - return (el instanceof Subject) ? ElementPruningClassification.PRUNING_CLASS_Subject : - (el instanceof DefinitionElement) ? ElementPruningClassification.PRUNING_CLASS_Definition : - (el instanceof DefinitionPartition) ? ElementPruningClassification.PRUNING_CLASS_DefinitionPartition : - ElementPruningClassification.PRUNING_CLASS_Normal; + return (el instanceof Subject) ? + ElementPruningClassification.PRUNING_CLASS_Subject : + (el instanceof DefinitionElement) ? + ElementPruningClassification.PRUNING_CLASS_Definition : + (el instanceof DefinitionPartition) ? + ElementPruningClassification.PRUNING_CLASS_DefinitionPartition : + ElementPruningClassification.PRUNING_CLASS_Normal; } /** Records the path that a tree search took to reach an element or model. This object is immutable. @@ -96,9 +107,15 @@ export class ElementTreeWalkerScope { } } - public get enclosingModel(): Model { return this.enclosingModelInfo.model; } - public get inDefinitionModel(): boolean { return this.enclosingModelInfo.isDefinitionModel; } // NB: this will return false for the RepositoryModel! - public get inRepositoryModel(): boolean { return this.enclosingModelInfo.model.id === IModelDb.repositoryModelId; } + public get enclosingModel(): Model { + return this.enclosingModelInfo.model; + } + public get inDefinitionModel(): boolean { + return this.enclosingModelInfo.isDefinitionModel; + } // NB: this will return false for the RepositoryModel! + public get inRepositoryModel(): boolean { + return this.enclosingModelInfo.model.id === IModelDb.repositoryModelId; + } public static createTopScope(iModel: IModelDb, topElementId: Id64String) { const topElement = iModel.elements.getElement(topElementId); @@ -172,16 +189,24 @@ function logModel(op: string, iModel: IModelDb, modelId: Id64String, scope?: Ele * @beta */ export abstract class ElementTreeBottomUp { - constructor(protected _iModel: IModelDb) { } + constructor(protected _iModel: IModelDb) {} /** Return true if the search should recurse into this model */ - protected shouldExploreModel(_model: Model, _scope: ElementTreeWalkerScope): boolean { return true; } + protected shouldExploreModel(_model: Model, _scope: ElementTreeWalkerScope): boolean { + return true; + } /** Return true if the search should recurse into the children (if any) of this element */ - protected shouldExploreChildren(_parentId: Id64String, _scope: ElementTreeWalkerScope): boolean { return true; } + protected shouldExploreChildren(_parentId: Id64String, _scope: ElementTreeWalkerScope): boolean { + return true; + } /** Return true if the search should visit this element */ - protected shouldVisitElement(_elementId: Id64String, _scope: ElementTreeWalkerScope): boolean { return true; } + protected shouldVisitElement(_elementId: Id64String, _scope: ElementTreeWalkerScope): boolean { + return true; + } /** Return true if the search should visit this model */ - protected shouldVisitModel(_model: Model, _scope: ElementTreeWalkerScope): boolean { return true; } + protected shouldVisitModel(_model: Model, _scope: ElementTreeWalkerScope): boolean { + return true; + } /** Called to visit a model */ protected abstract visitModel(model: Model, scope: ElementTreeWalkerScope): void; @@ -294,7 +319,6 @@ class SpecialElements { } } } - } /** Deletes an entire element tree, including sub-models and child elements. @@ -306,8 +330,12 @@ class SpecialElements { export class ElementTreeDeleter extends ElementTreeBottomUp { protected _special: SpecialElements = new SpecialElements(); - protected override shouldExploreModel(_model: Model): boolean { return true; } - protected override shouldVisitElement(_elementId: Id64String): boolean { return true; } + protected override shouldExploreModel(_model: Model): boolean { + return true; + } + protected override shouldVisitElement(_elementId: Id64String): boolean { + return true; + } protected override visitModel(model: Model, _scope: ElementTreeWalkerScope): void { if (isDefinitionModel(model)) @@ -342,7 +370,6 @@ export class ElementTreeDeleter extends ElementTreeBottomUp { public deleteSpecialElements(): void { this._special.deleteSpecialElements(this._iModel); } - } /** Does a breadth-first search on the tree defined by an element and its sub-models and children. @@ -352,15 +379,16 @@ export class ElementTreeDeleter extends ElementTreeBottomUp { * @beta */ abstract class ElementTreeTopDown { - constructor(protected _iModel: IModelDb) { } + constructor(protected _iModel: IModelDb) {} /** Should the search *not* recurse into this sub-tree? */ - protected shouldPrune(_elementId: Id64String, _scope: ElementTreeWalkerScope): boolean { return false; } + protected shouldPrune(_elementId: Id64String, _scope: ElementTreeWalkerScope): boolean { + return false; + } protected abstract prune(_elementId: Id64String, _scope: ElementTreeWalkerScope): void; protected processElementTree(element: Id64String, scope: ElementTreeWalkerScope) { - if (this.shouldPrune(element, scope)) { this.prune(element, scope); return; @@ -394,7 +422,6 @@ abstract class ElementTreeTopDown { } }); } - } /** Signature of the filter function used by ElementSubTreeDeleter. @@ -425,7 +452,9 @@ export class ElementSubTreeDeleter extends ElementTreeTopDown { this._shouldPruneCb = shouldPruneCb; } - protected override shouldPrune(elementId: Id64String, scope: ElementTreeWalkerScope): boolean { return this._shouldPruneCb(elementId, scope); } + protected override shouldPrune(elementId: Id64String, scope: ElementTreeWalkerScope): boolean { + return this._shouldPruneCb(elementId, scope); + } protected prune(elementId: Id64String, scope: ElementTreeWalkerScope): void { this._treeDeleter.deleteNormalElements(elementId, scope); diff --git a/core/backend/src/Entity.ts b/core/backend/src/Entity.ts index b613b968b656..9cf9e42cfbb4 100644 --- a/core/backend/src/Entity.ts +++ b/core/backend/src/Entity.ts @@ -24,26 +24,36 @@ export class Entity { /** The Schema that defines this class. */ public static schema: typeof Schema; - private get _ctor(): typeof Entity { return this.constructor as typeof Entity; } + private get _ctor(): typeof Entity { + return this.constructor as typeof Entity; + } /** The name of the BIS class associated with this class. * @note Every subclass of Entity **MUST** override this method to identify its BIS class. * Failure to do so will ordinarily result in an error when the class is registered, since there may only * be one JavaScript class for a given BIS class (usually the errant class will collide with its superclass.) */ - public static get className(): string { return "Entity"; } + public static get className(): string { + return "Entity"; + } /** When working with an Entity it can be useful to set property values directly, bypassing the compiler's type checking. * This property makes such code slightly less tedious to read and write. * @internal */ - public get asAny(): any { return this; } + public get asAny(): any { + return this; + } /** The name of the BIS Schema that defines this class */ - public get schemaName(): string { return this._ctor.schema.schemaName; } + public get schemaName(): string { + return this._ctor.schema.schemaName; + } /** The name of the BIS class associated with this class. */ - public get className(): string { return this._ctor.className; } + public get className(): string { + return this._ctor.className; + } /** The [[IModelDb]] that contains this Entity */ public iModel: IModelDb; @@ -55,7 +65,10 @@ export class Entity { this.iModel = iModel; this.id = Id64.fromJSON(props.id); // copy all auto-handled properties from input to the object being constructed - this.forEachProperty((propName: string, meta: PropertyMetaData) => (this as any)[propName] = meta.createProperty((props as any)[propName]), false); + this.forEachProperty( + (propName: string, meta: PropertyMetaData) => (this as any)[propName] = meta.createProperty((props as any)[propName]), + false, + ); } /** Invoke the constructor of the specified `Entity` subclass. @@ -87,13 +100,19 @@ export class Entity { } /** Get the full BIS class name of this Entity in the form "schema:class" */ - public static get classFullName(): string { return `${this.schema.schemaName}:${this.className}`; } + public static get classFullName(): string { + return `${this.schema.schemaName}:${this.className}`; + } /** Get the full BIS class name of this Entity in the form "schema:class". */ - public get classFullName(): string { return this._ctor.classFullName; } + public get classFullName(): string { + return this._ctor.classFullName; + } /** @internal */ - public static get protectedOperations(): string[] { return []; } + public static get protectedOperations(): string[] { + return []; + } /** return whether this Entity class is a subclass of another Entity class * @note the subclass-ness is checked according to JavaScript inheritance, to check the underlying raw EC class's @@ -110,7 +129,9 @@ export class Entity { * ClassRegistry overrides this when generating a class * @internal */ - public static get isGeneratedClass() { return false; } + public static get isGeneratedClass() { + return false; + } /** Get the set of this entity's *entity references*, [EntityReferenceSet]($backend). An *entity reference* is any id * stored on the entity, in its EC properties or json fields. diff --git a/core/backend/src/EntityReferences.ts b/core/backend/src/EntityReferences.ts index ecd40aa6c94a..5756560a06ed 100644 --- a/core/backend/src/EntityReferences.ts +++ b/core/backend/src/EntityReferences.ts @@ -6,14 +6,14 @@ * @module Schema */ -import { ConcreteEntityTypes, ElementAspectProps, ElementProps, EntityReference, ModelProps } from "@itwin/core-common"; import { Id64, Id64String } from "@itwin/core-bentley"; -import type { Entity } from "./Entity"; -import { Model } from "./Model"; +import { ConcreteEntityTypes, ElementAspectProps, ElementProps, EntityReference, ModelProps } from "@itwin/core-common"; +import * as assert from "assert"; import { Element } from "./Element"; import { ElementAspect } from "./ElementAspect"; +import type { Entity } from "./Entity"; +import { Model } from "./Model"; import { Relationship, RelationshipProps } from "./Relationship"; -import * as assert from "assert"; /** Concrete classes that can be created, with the notable exception of CodeSpecs since it is does not derive from Entity * other entity classes. In the future if there is a need diff --git a/core/backend/src/ExportGraphics.ts b/core/backend/src/ExportGraphics.ts index 26aaa8b7d1fc..aa1cb6bedbd6 100644 --- a/core/backend/src/ExportGraphics.ts +++ b/core/backend/src/ExportGraphics.ts @@ -7,8 +7,8 @@ */ import { assert, Id64Array, Id64String } from "@itwin/core-bentley"; -import { IndexedPolyface, Polyface, PolyfaceData, PolyfaceVisitor } from "@itwin/core-geometry"; import { ColorDefProps, GeometryClass } from "@itwin/core-common"; +import { IndexedPolyface, Polyface, PolyfaceData, PolyfaceVisitor } from "@itwin/core-geometry"; /** A collection of line segments, suitable for direct use with graphics APIs. * The structure of this data matches GL_LINES in OpenGL. @@ -420,27 +420,43 @@ export class ExportGraphicsMeshVisitor extends PolyfaceData implements PolyfaceV return this.moveToReadIndex(this._nextFacetIndex); } /** Set the number of vertices to replicate in visitor arrays. */ - public setNumWrap(numWrap: number): void { this._numWrap = numWrap; } + public setNumWrap(numWrap: number): void { + this._numWrap = numWrap; + } /** Return the index (in the client polyface) of the current facet */ - public currentReadIndex(): number { return this._currentFacetIndex; } + public currentReadIndex(): number { + return this._currentFacetIndex; + } /** Return the point index of vertex i within the currently loaded facet */ - public clientPointIndex(i: number): number { return this.pointIndex[i]; } + public clientPointIndex(i: number): number { + return this.pointIndex[i]; + } /** Return the param index of vertex i within the currently loaded facet. * Use the artificial paramIndex, which matches pointIndex. */ - public clientParamIndex(i: number): number { return this.paramIndex ? this.paramIndex[i] : -1; } + public clientParamIndex(i: number): number { + return this.paramIndex ? this.paramIndex[i] : -1; + } /** Return the normal index of vertex i within the currently loaded facet. * Use the artificial paramIndex, which matches pointIndex. */ - public clientNormalIndex(i: number): number { return this.normalIndex ? this.normalIndex[i] : -1; } + public clientNormalIndex(i: number): number { + return this.normalIndex ? this.normalIndex[i] : -1; + } /** Return the color index of vertex i within the currently loaded facet */ - public clientColorIndex(_i: number): number { return 1; } + public clientColorIndex(_i: number): number { + return 1; + } /** Return the aux data index of vertex i within the currently loaded facet */ - public clientAuxIndex(_i: number): number { return -1; } + public clientAuxIndex(_i: number): number { + return -1; + } /** return the client polyface */ - public clientPolyface(): Polyface { return (undefined as unknown) as Polyface; } + public clientPolyface(): Polyface { + return (undefined as unknown) as Polyface; + } /** clear the contents of all arrays. Use this along with transferDataFrom methods to build up new facets */ public clearArrays(): void { if (this.point !== undefined) @@ -471,5 +487,4 @@ export class ExportGraphicsMeshVisitor extends PolyfaceData implements PolyfaceV if (this.normal && other.normal && index < other.normal.length) this.normal.pushFromGrowableXYZArray(other.normal, index); } - } diff --git a/core/backend/src/ExternalSource.ts b/core/backend/src/ExternalSource.ts index 80d824dfbaba..f198dacc9d5e 100644 --- a/core/backend/src/ExternalSource.ts +++ b/core/backend/src/ExternalSource.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. @@ -8,11 +7,19 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { - BisCodeSpec, Code, CodeScopeSpec, EntityReferenceSet, ExternalSourceAttachmentProps, ExternalSourceAttachmentRole, ExternalSourceProps, IModel, RelatedElement, + BisCodeSpec, + Code, + CodeScopeSpec, + EntityReferenceSet, + ExternalSourceAttachmentProps, + ExternalSourceAttachmentRole, + ExternalSourceProps, + IModel, + RelatedElement, SynchronizationConfigLinkProps, } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { InformationReferenceElement, UrlLink } from "./Element"; import { IModelDb } from "./IModelDb"; import { ExternalSourceAttachmentAttachesSource, ExternalSourceIsInRepository } from "./NavigationRelationship"; @@ -29,7 +36,9 @@ export class ExternalSource extends InformationReferenceElement { /** The version of the iModel Connecter that processed this ExternalSource. */ public connectorVersion?: string; /** @internal */ - public static override get className(): string { return "ExternalSource"; } + public static override get className(): string { + return "ExternalSource"; + } protected constructor(props: ExternalSourceProps, iModel: IModelDb) { super(props, iModel); @@ -86,7 +95,9 @@ export class ExternalSourceAttachment extends InformationReferenceElement { /** The scale of the attached [[ExternalSource]] relative to the ExternalSource that attaches it. */ public scale?: Point3d; /** @internal */ - public static override get className(): string { return "ExternalSourceAttachment"; } + public static override get className(): string { + return "ExternalSourceAttachment"; + } protected constructor(props: ExternalSourceAttachmentProps, iModel: IModelDb) { super(props, iModel); @@ -130,7 +141,9 @@ export class ExternalSourceAttachment extends InformationReferenceElement { */ export class ExternalSourceGroup extends ExternalSource { /** @internal */ - public static override get className(): string { return "ExternalSourceGroup"; } + public static override get className(): string { + return "ExternalSourceGroup"; + } protected constructor(props: ExternalSourceProps, iModel: IModelDb) { super(props, iModel); @@ -145,7 +158,9 @@ export class SynchronizationConfigLink extends UrlLink { /** Date/Time of last successful run of this synchronization configuration */ public lastSuccessfulRun?: string; /** @internal */ - public static override get className(): string { return "SynchronizationConfigLink"; } + public static override get className(): string { + return "SynchronizationConfigLink"; + } protected constructor(props: SynchronizationConfigLinkProps, iModel: IModelDb) { super(props, iModel); @@ -155,4 +170,3 @@ export class SynchronizationConfigLink extends UrlLink { return super.toJSON() as SynchronizationConfigLinkProps; // Entity.toJSON takes care of auto-handled properties } } - diff --git a/core/backend/src/GeoCoordConfig.ts b/core/backend/src/GeoCoordConfig.ts index e81eb069b376..0edd02da8b65 100644 --- a/core/backend/src/GeoCoordConfig.ts +++ b/core/backend/src/GeoCoordConfig.ts @@ -9,9 +9,9 @@ import { BentleyError, Logger } from "@itwin/core-bentley"; import { CloudSqlite } from "./CloudSqlite"; import { IModelHost } from "./IModelHost"; +import { IModelNative } from "./internal/NativePlatform"; import { Settings } from "./workspace/Settings"; import { WorkspaceDbCloudProps } from "./workspace/Workspace"; -import { IModelNative } from "./internal/NativePlatform"; const loggerCat = "GeoCoord"; @@ -56,14 +56,17 @@ export class GeoCoordConfig { if (!IModelNative.platform.addGcsWorkspaceDb(gcsDbName, cloudContainer, dbProps.priority)) return; // already had this db - Logger.logInfo(loggerCat, `loaded gcsDb "${gcsDbName}", from "${dbProps.baseUri}/${dbProps.containerId}" size=${gcsDbProps.totalBlocks}, local=${gcsDbProps.localBlocks}`); + Logger.logInfo( + loggerCat, + `loaded gcsDb "${gcsDbName}", from "${dbProps.baseUri}/${dbProps.containerId}" size=${gcsDbProps.totalBlocks}, local=${gcsDbProps.localBlocks}`, + ); if (true === dbProps.prefetch) this.prefetches.push(CloudSqlite.startCloudPrefetch(cloudContainer, gcsDbName)); - } catch (e: any) { let msg = `Cannot load GCS workspace (${e.errorNumber}): ${BentleyError.getErrorMessage(e)}`; - msg += `,container=${dbProps.baseUri}/${dbProps.containerId}, storage=${dbProps.storageType}, public=${dbProps.isPublic}, cacheDir=${IModelHost.cacheDir}`; + msg += + `,container=${dbProps.baseUri}/${dbProps.containerId}, storage=${dbProps.storageType}, public=${dbProps.isPublic}, cacheDir=${IModelHost.cacheDir}`; Logger.logError(loggerCat, msg); } } diff --git a/core/backend/src/GeographicCRSServices.ts b/core/backend/src/GeographicCRSServices.ts index 0e15f4905464..cc50c6ed5540 100644 --- a/core/backend/src/GeographicCRSServices.ts +++ b/core/backend/src/GeographicCRSServices.ts @@ -45,6 +45,8 @@ export interface GetAvailableCoordinateReferenceSystemsArgs { * @returns The list of Geographic Coordinate Reference Systems, according to the supplied parameters. * @beta */ -export async function getAvailableCoordinateReferenceSystems(args: GetAvailableCoordinateReferenceSystemsArgs): Promise { +export async function getAvailableCoordinateReferenceSystems( + args: GetAvailableCoordinateReferenceSystemsArgs, +): Promise { return IModelNative.platform.GeoServices.getListOfCRS(args.extent); } diff --git a/core/backend/src/GeometrySummary.ts b/core/backend/src/GeometrySummary.ts index 008c59b7d0c4..bfca06e16881 100644 --- a/core/backend/src/GeometrySummary.ts +++ b/core/backend/src/GeometrySummary.ts @@ -5,15 +5,43 @@ import { assert, BentleyError, Id64Array, Id64String, IModelStatus } from "@itwin/core-bentley"; import { - AkimaCurve3d, AnyGeometryQuery, Arc3d, BezierCurveBase, Box, BSplineCurve3d, Cone, CurveChainWithDistanceIndex, CurveCollection, CurvePrimitive, IModelJson, + BRepEntity, + GeometryParams, + GeometryStreamIterator, + GeometrySummaryRequestProps, + GeometrySummaryVerbosity, + ImagePrimitive, + IModelError, + TextStringPrimitive, +} from "@itwin/core-common"; +import { + AkimaCurve3d, + AnyGeometryQuery, + Arc3d, + BezierCurveBase, + Box, + BSplineCurve3d, + Cone, + CurveChainWithDistanceIndex, + CurveCollection, + CurvePrimitive, + IModelJson, InterpolationCurve3d, - LinearSweep, LineSegment3d, LineString3d, Loop, Path, Range3d, RotationalSweep, RuledSweep, SolidPrimitive, Sphere, TorusPipe, Transform, - TransitionSpiral3d, UVSelect, + LinearSweep, + LineSegment3d, + LineString3d, + Loop, + Path, + Range3d, + RotationalSweep, + RuledSweep, + SolidPrimitive, + Sphere, + TorusPipe, + Transform, + TransitionSpiral3d, + UVSelect, } from "@itwin/core-geometry"; -import { - BRepEntity, GeometryParams, GeometryStreamIterator, GeometrySummaryRequestProps, GeometrySummaryVerbosity, ImagePrimitive, - IModelError, TextStringPrimitive, -} from "@itwin/core-common"; import { Element, GeometricElement, GeometryPart } from "./Element"; import { IModelDb } from "./IModelDb"; import { _nativeDb } from "./internal/Symbols"; @@ -34,7 +62,9 @@ class ResponseGenerator { public elementIds: Id64Array; public iModel: IModelDb; - public get wantSquish() { return GeometrySummaryVerbosity.Full !== this.verbosity; } + public get wantSquish() { + return GeometrySummaryVerbosity.Full !== this.verbosity; + } public constructor(request: GeometrySummaryRequestProps, iModel: IModelDb) { this.elementIds = request.elementIds; @@ -283,7 +313,7 @@ class ResponseGenerator { const summary: string = solid.capped ? " capped" : " uncapped"; switch (solid.solidPrimitiveType) { case "box": - const box: Box = (solid as Box); + const box: Box = solid as Box; return `${summary}' ' origin: ${JSON.stringify(box.getBaseOrigin().toJSON())}' ' topOrigin: ${JSON.stringify(box.getTopOrigin().toJSON())}' diff --git a/core/backend/src/HubMock.ts b/core/backend/src/HubMock.ts index 61f112845f25..c86ec0c76ef1 100644 --- a/core/backend/src/HubMock.ts +++ b/core/backend/src/HubMock.ts @@ -3,21 +3,38 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { join } from "path"; import { Guid, GuidString } from "@itwin/core-bentley"; import { - ChangesetFileProps, ChangesetIndex, ChangesetIndexAndId, ChangesetProps, ChangesetRange, IModelVersion, LocalDirName, + ChangesetFileProps, + ChangesetIndex, + ChangesetIndexAndId, + ChangesetProps, + ChangesetRange, + IModelVersion, + LocalDirName, } from "@itwin/core-common"; +import { join } from "path"; import { AcquireNewBriefcaseIdArg, - BackendHubAccess, BriefcaseDbArg, BriefcaseIdArg, ChangesetArg, CheckpointArg, CreateNewIModelProps, DownloadChangesetArg, DownloadChangesetRangeArg, IModelIdArg, IModelNameArg, - LockMap, LockProps, V2CheckpointAccessProps, + BackendHubAccess, + BriefcaseDbArg, + BriefcaseIdArg, + ChangesetArg, + CheckpointArg, + CreateNewIModelProps, + DownloadChangesetArg, + DownloadChangesetRangeArg, + IModelIdArg, + IModelNameArg, + LockMap, + LockProps, + V2CheckpointAccessProps, } from "./BackendHubAccess"; import { CheckpointProps, ProgressFunction, ProgressStatus } from "./CheckpointManager"; +import { TokenArg } from "./IModelDb"; import { IModelHost } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; import { LocalHub } from "./LocalHub"; -import { TokenArg } from "./IModelDb"; function wasStarted(val: string | undefined): asserts val is string { if (undefined === val) @@ -63,7 +80,9 @@ export class HubMock { private static _iTwinId: GuidString | undefined; /** Determine whether a test us currently being run under HubMock */ - public static get isValid() { return undefined !== this.mockRoot; } + public static get isValid() { + return undefined !== this.mockRoot; + } public static get iTwinId() { wasStarted(this._iTwinId); return this._iTwinId; @@ -76,7 +95,9 @@ export class HubMock { */ public static startup(mockName: LocalDirName, outputDir: string) { if (this.isValid) - throw new Error("Either a previous test did not call HubMock.shutdown() properly, or more than one test is simultaneously attempting to use HubMock, which is not allowed"); + throw new Error( + "Either a previous test did not call HubMock.shutdown() properly, or more than one test is simultaneously attempting to use HubMock, which is not allowed", + ); this.hubs.clear(); this.mockRoot = join(outputDir, "HubMock", mockName); @@ -254,7 +275,7 @@ export class HubMock { const mockProgress = (index: number) => { const bytesDownloaded = Math.floor(totalSize * (index / 4)); - if (!rejected && progressCallback(bytesDownloaded, totalSize) === ProgressStatus.Abort){ + if (!rejected && progressCallback(bytesDownloaded, totalSize) === ProgressStatus.Abort) { rejected = true; reject(new Error("AbortError")); } diff --git a/core/backend/src/IModelDb.ts b/core/backend/src/IModelDb.ts index 0336ce040dcf..ba8615f4dabc 100644 --- a/core/backend/src/IModelDb.ts +++ b/core/backend/src/IModelDb.ts @@ -6,32 +6,118 @@ * @module iModels */ -import * as fs from "fs"; -import { join } from "path"; -import * as touch from "touch"; import { IModelJsNative } from "@bentley/imodeljs-native"; import { - AccessToken, assert, BeEvent, BentleyStatus, ChangeSetStatus, DbChangeStage, DbConflictCause, DbConflictResolution, DbResult, - Guid, GuidString, Id64, Id64Arg, Id64Array, Id64Set, Id64String, IModelStatus, JsonUtils, Logger, LogLevel, OpenMode, + AccessToken, + assert, + BeEvent, + BentleyStatus, + ChangeSetStatus, + DbChangeStage, + DbConflictCause, + DbConflictResolution, + DbResult, + Guid, + GuidString, + Id64, + Id64Arg, + Id64Array, + Id64Set, + Id64String, + IModelStatus, + JsonUtils, + Logger, + LogLevel, + OpenMode, } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, BRepGeometryCreate, BriefcaseId, BriefcaseIdValue, CategorySelectorProps, ChangesetIdWithIndex, ChangesetIndexAndId, Code, - CodeProps, CreateEmptySnapshotIModelProps, CreateEmptyStandaloneIModelProps, CreateSnapshotIModelProps, DbQueryRequest, DisplayStyleProps, - DomainOptions, EcefLocation, ECJsNames, ECSchemaProps, ECSqlReader, ElementAspectProps, ElementGeometryCacheOperationRequestProps, ElementGeometryCacheRequestProps, ElementGeometryCacheResponseProps, ElementGeometryRequest, ElementGraphicsRequestProps, - ElementLoadProps, ElementProps, EntityMetaData, EntityProps, EntityQueryParams, FilePropertyProps, FontId, FontMap, FontType, - GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, GeometryContainmentRequestProps, GeometryContainmentResponseProps, IModel, - IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, IModelError, IModelNotFoundResponse, IModelTileTreeProps, LocalFileName, - MassPropertiesRequestProps, MassPropertiesResponseProps, ModelExtentsProps, ModelLoadProps, ModelProps, ModelSelectorProps, OpenBriefcaseProps, - OpenCheckpointArgs, OpenSqliteArgs, ProfileOptions, PropertyCallback, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat, SchemaState, - SheetProps, SnapRequestProps, SnapResponseProps, SnapshotOpenOptions, SpatialViewDefinitionProps, SubCategoryResultRow, TextureData, - TextureLoadProps, ThumbnailProps, UpgradeOptions, ViewDefinition2dProps, ViewDefinitionProps, ViewIdString, ViewQueryParams, ViewStateLoadProps, - ViewStateProps, ViewStoreRpc, + AxisAlignedBox3d, + BRepGeometryCreate, + BriefcaseId, + BriefcaseIdValue, + CategorySelectorProps, + ChangesetIdWithIndex, + ChangesetIndexAndId, + Code, + CodeProps, + CreateEmptySnapshotIModelProps, + CreateEmptyStandaloneIModelProps, + CreateSnapshotIModelProps, + DbQueryRequest, + DisplayStyleProps, + DomainOptions, + EcefLocation, + ECJsNames, + ECSchemaProps, + ECSqlReader, + ElementAspectProps, + ElementGeometryCacheOperationRequestProps, + ElementGeometryCacheRequestProps, + ElementGeometryCacheResponseProps, + ElementGeometryRequest, + ElementGraphicsRequestProps, + ElementLoadProps, + ElementProps, + EntityMetaData, + EntityProps, + EntityQueryParams, + FilePropertyProps, + FontId, + FontMap, + FontType, + GeoCoordinatesRequestProps, + GeoCoordinatesResponseProps, + GeometryContainmentRequestProps, + GeometryContainmentResponseProps, + IModel, + IModelCoordinatesRequestProps, + IModelCoordinatesResponseProps, + IModelError, + IModelNotFoundResponse, + IModelTileTreeProps, + LocalFileName, + MassPropertiesRequestProps, + MassPropertiesResponseProps, + ModelExtentsProps, + ModelLoadProps, + ModelProps, + ModelSelectorProps, + OpenBriefcaseProps, + OpenCheckpointArgs, + OpenSqliteArgs, + ProfileOptions, + PropertyCallback, + QueryBinder, + QueryOptions, + QueryOptionsBuilder, + QueryRowFormat, + SchemaState, + SheetProps, + SnapRequestProps, + SnapResponseProps, + SnapshotOpenOptions, + SpatialViewDefinitionProps, + SubCategoryResultRow, + TextureData, + TextureLoadProps, + ThumbnailProps, + UpgradeOptions, + ViewDefinition2dProps, + ViewDefinitionProps, + ViewIdString, + ViewQueryParams, + ViewStateLoadProps, + ViewStateProps, + ViewStoreRpc, } from "@itwin/core-common"; import { Range2d, Range3d } from "@itwin/core-geometry"; +import * as fs from "fs"; +import { join } from "path"; +import * as touch from "touch"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; +import type { BlobContainer } from "./BlobContainerService"; import { BriefcaseManager, PullChangesArgs, PushChangesArgs, RevertChangesArgs } from "./BriefcaseManager"; import { ChannelControl } from "./ChannelControl"; -import { createChannelControl } from "./internal/ChannelAdmin"; import { CheckpointManager, CheckpointProps, V2CheckpointManager } from "./CheckpointManager"; import { ClassRegistry, MetaDataRegistry } from "./ClassRegistry"; import { CloudSqlite } from "./CloudSqlite"; @@ -48,11 +134,19 @@ import { ExportGraphicsOptions, ExportPartGraphicsOptions } from "./ExportGraphi import { GeoCoordConfig } from "./GeoCoordConfig"; import { IModelHost } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; +import { ChangesetConflictArgs } from "./internal/ChangesetConflictArgs"; +import { createChannelControl } from "./internal/ChannelAdmin"; +import { IModelNative } from "./internal/NativePlatform"; +import { createNoOpLockControl } from "./internal/NoLocks"; +import { createServerBasedLocks } from "./internal/ServerBasedLocks"; +import { _close, _nativeDb, _releaseAllLocks } from "./internal/Symbols"; +import { SettingsImpl } from "./internal/workspace/SettingsImpl"; +import { constructWorkspace, OwnedWorkspace, throwWorkspaceDbLoadErrors } from "./internal/workspace/WorkspaceImpl"; import { IpcHost } from "./IpcHost"; +import { LockControl } from "./LockControl"; import { Model } from "./Model"; import { Relationships } from "./Relationship"; import { SchemaSync } from "./SchemaSync"; -import { createServerBasedLocks } from "./internal/ServerBasedLocks"; import { SqliteStatement, StatementCache } from "./SqliteStatement"; import { ComputeRangesForTextLayoutArgs, TextLayoutRanges } from "./TextAnnotationLayout"; import { TxnManager } from "./TxnManager"; @@ -60,14 +154,6 @@ import { DrawingViewDefinition, SheetViewDefinition, ViewDefinition } from "./Vi import { ViewStore } from "./ViewStore"; import { Setting, SettingsContainer, SettingsDictionary, SettingsPriority } from "./workspace/Settings"; import { Workspace, WorkspaceDbLoadError, WorkspaceDbLoadErrors, WorkspaceDbSettingsProps, WorkspaceSettingNames } from "./workspace/Workspace"; -import { constructWorkspace, OwnedWorkspace, throwWorkspaceDbLoadErrors } from "./internal/workspace/WorkspaceImpl"; -import { SettingsImpl } from "./internal/workspace/SettingsImpl"; -import { ChangesetConflictArgs } from "./internal/ChangesetConflictArgs"; -import { LockControl } from "./LockControl"; -import { IModelNative } from "./internal/NativePlatform"; -import type { BlobContainer } from "./BlobContainerService"; -import { createNoOpLockControl } from "./internal/NoLocks"; -import { _close, _nativeDb, _releaseAllLocks } from "./internal/Symbols"; // spell:ignore fontid fontmap @@ -122,7 +208,7 @@ export interface SchemaImportOptions { /** @internal */ export enum BriefcaseLocalValue { StandaloneEdit = "StandaloneEdit", - NoLocking = "NoLocking" + NoLocking = "NoLocking", } // function to open an briefcaseDb, perform an operation, and then close it. @@ -145,7 +231,7 @@ class IModelSettings extends SettingsImpl { throw new Error("Use IModelHost.appSettings to access settings of priority 'application' or lower"); } - public override * getSettingEntries(name: string): Iterable<{ value: T, dictionary: SettingsDictionary }> { + public override *getSettingEntries(name: string): Iterable<{ value: T, dictionary: SettingsDictionary }> { yield* super.getSettingEntries(name); yield* IModelHost.appWorkspace.settings.getSettingEntries(name); } @@ -185,10 +271,14 @@ export abstract class IModelDb extends IModel { protected _codeService?: CodeService; /** @alpha */ - public get codeService() { return this._codeService; } + public get codeService() { + return this._codeService; + } /** The [[LockControl]] that orchestrates [concurrent editing]($docs/learning/backend/ConcurrencyControl.md) of this iModel. */ - public get locks(): LockControl { return this._locks!; } // eslint-disable-line @typescript-eslint/no-non-null-assertion + public get locks(): LockControl { + return this._locks!; + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** * Get the [[Workspace]] for this iModel. @@ -250,7 +340,9 @@ export abstract class IModelDb extends IModel { } /** Check if this iModel has been opened read-only or not. */ - public get isReadonly(): boolean { return this.openMode === OpenMode.Readonly; } + public get isReadonly(): boolean { + return this.openMode === OpenMode.Readonly; + } /** The Guid that identifies this iModel. */ public override get iModelId(): GuidString { @@ -261,7 +353,9 @@ export abstract class IModelDb extends IModel { /** @internal * @deprecated in 4.8. This internal API will be removed in 5.0. Use IModelDb's public API instead. */ - public get nativeDb(): IModelJsNative.DgnDb { return this[_nativeDb]; } + public get nativeDb(): IModelJsNative.DgnDb { + return this[_nativeDb]; + } /** @internal*/ public readonly [_nativeDb]: IModelJsNative.DgnDb; @@ -269,7 +363,9 @@ export abstract class IModelDb extends IModel { /** Get the full path fileName of this iModelDb * @note this member is only valid while the iModel is opened. */ - public get pathName(): LocalFileName { return this[_nativeDb].getFilePath(); } + public get pathName(): LocalFileName { + return this[_nativeDb].getFilePath(); + } /** Get the full path to this iModel's "watch file". * A read-only briefcase opened with `watchForChanges: true` creates this file next to the briefcase file on open, if it doesn't already exist. @@ -278,7 +374,9 @@ export abstract class IModelDb extends IModel { * This is more reliable than watching the sqlite WAL file. * @internal */ - public get watchFilePathName(): LocalFileName { return `${this.pathName}-watch`; } + public get watchFilePathName(): LocalFileName { + return `${this.pathName}-watch`; + } /** @internal */ protected constructor(args: { nativeDb: IModelJsNative.DgnDb, key: string, changeset?: ChangesetIdWithIndex }) { @@ -313,7 +411,7 @@ export abstract class IModelDb extends IModel { try { db.abandonChanges(); db.close(); - } catch { } + } catch {} }); }); } @@ -337,7 +435,7 @@ export abstract class IModelDb extends IModel { } /** @internal */ - public async refreshContainerForRpc(_userAccessToken: AccessToken): Promise { } + public async refreshContainerForRpc(_userAccessToken: AccessToken): Promise {} /** Event called when the iModel is about to be closed. */ public readonly onBeforeClose = new BeEvent<() => void>(); @@ -369,38 +467,56 @@ export abstract class IModelDb extends IModel { db.onProjectExtentsChanged.addListener(() => IpcHost.notifyTxns(db, "notifyProjectExtentsChanged", db.projectExtents.toJSON())); db.onGlobalOriginChanged.addListener(() => IpcHost.notifyTxns(db, "notifyGlobalOriginChanged", db.globalOrigin.toJSON())); db.onEcefLocationChanged.addListener(() => IpcHost.notifyTxns(db, "notifyEcefLocationChanged", db.ecefLocation?.toJSON())); - db.onGeographicCoordinateSystemChanged.addListener(() => IpcHost.notifyTxns(db, "notifyGeographicCoordinateSystemChanged", db.geographicCoordinateSystem?.toJSON())); + db.onGeographicCoordinateSystemChanged.addListener(() => + IpcHost.notifyTxns(db, "notifyGeographicCoordinateSystemChanged", db.geographicCoordinateSystem?.toJSON()) + ); } /** Returns true if this is a BriefcaseDb * @see [[BriefcaseDb.open]] */ - public get isBriefcase(): boolean { return false; } + public get isBriefcase(): boolean { + return false; + } /** Type guard for instanceof [[BriefcaseDb]] */ - public isBriefcaseDb(): this is BriefcaseDb { return this.isBriefcase; } + public isBriefcaseDb(): this is BriefcaseDb { + return this.isBriefcase; + } /** Returns true if this is a SnapshotDb * @see [[SnapshotDb.open]] */ - public get isSnapshot(): boolean { return false; } + public get isSnapshot(): boolean { + return false; + } /** Type guard for instanceof [[SnapshotDb]] */ - public isSnapshotDb(): this is SnapshotDb { return this.isSnapshot; } + public isSnapshotDb(): this is SnapshotDb { + return this.isSnapshot; + } /** Returns true if this is a *standalone* iModel * @see [[StandaloneDb.open]] * @internal */ - public get isStandalone(): boolean { return false; } + public get isStandalone(): boolean { + return false; + } /** Type guard for instanceof [[StandaloneDb]]. */ - public isStandaloneDb(): this is StandaloneDb { return this.isStandalone; } + public isStandaloneDb(): this is StandaloneDb { + return this.isStandalone; + } /** Return `true` if the underlying nativeDb is open and valid. * @internal */ - public get isOpen(): boolean { return this[_nativeDb].isOpen(); } + public get isOpen(): boolean { + return this[_nativeDb].isOpen(); + } /** Get the briefcase Id of this iModel */ - public getBriefcaseId(): BriefcaseId { return this.isOpen ? this[_nativeDb].getBriefcaseId() : BriefcaseIdValue.Illegal; } + public getBriefcaseId(): BriefcaseId { + return this.isOpen ? this[_nativeDb].getBriefcaseId() : BriefcaseIdValue.Illegal; + } /** * Use a prepared ECSQL statement, potentially from the statement cache. If the requested statement doesn't exist @@ -470,7 +586,7 @@ export abstract class IModelDb extends IModel { * @param config Allow to specify certain flags which control how query is executed. * @returns Returns an [ECSqlReader]($common) which helps iterate over the result set and also give access to metadata. * @public - * */ + */ public createQueryReader(ecsql: string, params?: QueryBinder, config?: QueryOptions): ECSqlReader { if (!this[_nativeDb].isOpen()) throw new IModelError(DbResult.BE_SQLITE_ERROR, "db not open"); @@ -498,12 +614,11 @@ export abstract class IModelDb extends IModel { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead; it accepts the same parameters. */ - public async * query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { const builder = new QueryOptionsBuilder(options); const reader = this.createQueryReader(ecsql, params, builder.getOptions()); while (await reader.step()) yield reader.formatCurrentRow(); - } /** Compute number of rows that would be returned by the ECSQL. @@ -544,7 +659,7 @@ export abstract class IModelDb extends IModel { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead. Pass in the restart token as part of the `config` argument; e.g., `{ restartToken: myToken }` or `new QueryOptionsBuilder().setRestartToken(myToken).getOptions()`. */ - public async * restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { for await (const row of this.createQueryReader(ecsql, params, new QueryOptionsBuilder(options).setRestartToken(token).getOptions())) { yield row; } @@ -625,11 +740,12 @@ export abstract class IModelDb extends IModel { */ public async queryAllUsedSpatialSubCategories(): Promise { const result: SubCategoryResultRow[] = []; - const parentCategoriesQuery = `SELECT DISTINCT Category.Id AS id FROM BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId FROM BisCore.SpatialCategory)`; + const parentCategoriesQuery = + `SELECT DISTINCT Category.Id AS id FROM BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId FROM BisCore.SpatialCategory)`; const parentCategories: Id64Array = []; for await (const row of this.createQueryReader(parentCategoriesQuery)) { parentCategories.push(row.id); - }; + } const where = [...parentCategories].join(","); const query = `SELECT ECInstanceId as id, Parent.Id as parentId, Properties as appearance FROM BisCore.SubCategory WHERE Parent.Id IN (${where})`; @@ -822,7 +938,6 @@ export abstract class IModelDb extends IModel { const maybeCustomNativeContext = options?.ecSchemaXmlContext?.nativeContext; if (this[_nativeDb].schemaSyncEnabled()) { - await SchemaSync.withLockedAccess(this, { openMode: OpenMode.Readonly, operationName: "schema sync" }, async (syncAccess) => { const schemaSyncDbUri = syncAccess.getUri(); this.saveChanges(); @@ -911,7 +1026,7 @@ export abstract class IModelDb extends IModel { /** Find an opened instance of any subclass of IModelDb, by filename * @note this method returns an IModelDb if the filename is open for *any* subclass of IModelDb - */ + */ public static findByFilename(fileName: LocalFileName): IModelDb | undefined { for (const entry of this._openDbs) { // It shouldn't be possible for anything in _openDbs to not be open, but if so just skip them because `pathName` will throw an exception. @@ -942,7 +1057,12 @@ export abstract class IModelDb extends IModel { } /** @internal */ - public static openDgnDb(file: { path: LocalFileName, key?: string }, openMode: OpenMode, upgradeOptions?: UpgradeOptions, props?: SnapshotOpenOptions & CloudContainerArgs & OpenSqliteArgs): IModelJsNative.DgnDb { + public static openDgnDb( + file: { path: LocalFileName, key?: string }, + openMode: OpenMode, + upgradeOptions?: UpgradeOptions, + props?: SnapshotOpenOptions & CloudContainerArgs & OpenSqliteArgs, + ): IModelJsNative.DgnDb { file.key = file.key ?? Guid.createValue(); if (this.tryFindByKey(file.key)) throw new IModelError(IModelStatus.AlreadyOpen, `key [${file.key}] for file [${file.path}] is already in use`); @@ -1237,7 +1357,9 @@ export abstract class IModelDb extends IModel { * @param prop the FilePropertyProps that describes the property * @returns the next available (that is, an unused) id for prop. If none are present, will return 0. */ - public queryNextAvailableFileProperty(prop: FilePropertyProps) { return this[_nativeDb].queryNextAvailableFileProperty(prop); } + public queryNextAvailableFileProperty(prop: FilePropertyProps) { + return this[_nativeDb].queryNextAvailableFileProperty(prop); + } /** @internal */ public async requestSnap(sessionId: string, props: SnapRequestProps): Promise { @@ -1355,9 +1477,9 @@ export abstract class IModelDb extends IModel { } /** Request operation using the backend geometry cache populated by first calling elementGeometryRequest. - * @returns SUCCESS if requested operation could be applied. - * @beta - */ + * @returns SUCCESS if requested operation could be applied. + * @beta + */ public elementGeometryCacheOperation(requestProps: ElementGeometryCacheOperationRequestProps): BentleyStatus { return this[_nativeDb].elementGeometryCacheOperation(requestProps); } @@ -1481,13 +1603,12 @@ export abstract class IModelDb extends IModel { /** @public */ export namespace IModelDb { // eslint-disable-line no-redeclare - /** The collection of models in an [[IModelDb]]. * @public */ export class Models { /** @internal */ - public constructor(private _iModel: IModelDb) { } + public constructor(private _iModel: IModelDb) {} /** Get the ModelProps with the specified identifier. * @param modelId The Model identifier. @@ -1620,7 +1741,9 @@ export namespace IModelDb { // eslint-disable-line no-redeclare * @param modelProps The properties to use when creating the model. * @throws [[IModelError]] if there is a problem creating the model. */ - public createModel(modelProps: ModelProps): T { return this._iModel.constructEntity(modelProps); } + public createModel(modelProps: ModelProps): T { + return this._iModel.constructEntity(modelProps); + } /** Insert a new model. * @param props The data for the new model. @@ -1713,7 +1836,7 @@ export namespace IModelDb { // eslint-disable-line no-redeclare */ export class Elements implements GuidMapper { /** @internal */ - public constructor(private _iModel: IModelDb) { } + public constructor(private _iModel: IModelDb) {} public getFederationGuidFromId(id: Id64String): GuidString | undefined { return this._iModel.withPreparedSqliteStatement(`SELECT FederationGuid FROM bis_Element WHERE Id=?`, (stmt) => { @@ -1723,10 +1846,12 @@ export namespace IModelDb { // eslint-disable-line no-redeclare } public getIdFromFederationGuid(guid?: GuidString): Id64String | undefined { - return guid ? this._iModel.withPreparedSqliteStatement(`SELECT Id FROM bis_Element WHERE FederationGuid=?`, (stmt) => { - stmt.bindGuid(1, guid); - return !stmt.nextRow() ? undefined : stmt.getValueId(0); - }) : undefined; + return guid ? + this._iModel.withPreparedSqliteStatement(`SELECT Id FROM bis_Element WHERE FederationGuid=?`, (stmt) => { + stmt.bindGuid(1, guid); + return !stmt.nextRow() ? undefined : stmt.getValueId(0); + }) : + undefined; } /** Read element data from the iModel as JSON @@ -1739,7 +1864,10 @@ export namespace IModelDb { // eslint-disable-line no-redeclare public getElementJson(elementId: ElementLoadProps): T { const elementProps = this.tryGetElementJson(elementId); if (undefined === elementProps) - throw new IModelError(IModelStatus.NotFound, `reading element={id: ${elementId.id} federationGuid: ${elementId.federationGuid}, code: ${elementId.code}}`); + throw new IModelError( + IModelStatus.NotFound, + `reading element={id: ${elementId.id} federationGuid: ${elementId.federationGuid}, code: ${elementId.code}}`, + ); return elementProps; } @@ -1801,7 +1929,10 @@ export namespace IModelDb { // eslint-disable-line no-redeclare if (typeof elementId === "string" || elementId instanceof Code) throw new IModelError(IModelStatus.NotFound, `Element=${elementId}`); else - throw new IModelError(IModelStatus.NotFound, `Element={id: ${elementId.id} federationGuid: ${elementId.federationGuid}, code: ${elementId.code}}`); + throw new IModelError( + IModelStatus.NotFound, + `Element={id: ${elementId.id} federationGuid: ${elementId.federationGuid}, code: ${elementId.code}}`, + ); } return element; } @@ -1814,7 +1945,10 @@ export namespace IModelDb { // eslint-disable-line no-redeclare * @note Useful for cases when an element may or may not exist and throwing an `Error` would be overkill. * @see getElement */ - public tryGetElement(elementId: Id64String | GuidString | Code | ElementLoadProps, elementClass?: EntityClassType): T | undefined { + public tryGetElement( + elementId: Id64String | GuidString | Code | ElementLoadProps, + elementClass?: EntityClassType, + ): T | undefined { if (typeof elementId === "string") elementId = Id64.isId64(elementId) ? { id: elementId } : { federationGuid: elementId }; else if (elementId instanceof Code) @@ -1851,15 +1985,18 @@ export namespace IModelDb { // eslint-disable-line no-redeclare if (code.value === undefined) throw new IModelError(IModelStatus.InvalidCode, "Invalid Code"); - return this._iModel.withPreparedStatement("SELECT ECInstanceId FROM BisCore:Element WHERE CodeSpec.Id=? AND CodeScope.Id=? AND CodeValue=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, code.spec); - stmt.bindId(2, Id64.fromString(code.scope)); - stmt.bindString(3, code.value); - if (DbResult.BE_SQLITE_ROW !== stmt.step()) - return undefined; + return this._iModel.withPreparedStatement( + "SELECT ECInstanceId FROM BisCore:Element WHERE CodeSpec.Id=? AND CodeScope.Id=? AND CodeValue=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, code.spec); + stmt.bindId(2, Id64.fromString(code.scope)); + stmt.bindString(3, code.value); + if (DbResult.BE_SQLITE_ROW !== stmt.step()) + return undefined; - return stmt.getValue(0).getId(); - }); + return stmt.getValue(0).getId(); + }, + ); } /** Query for an [[Element]]'s last modified time. @@ -1880,7 +2017,9 @@ export namespace IModelDb { // eslint-disable-line no-redeclare * @param elProps The properties of the new element. * @throws [[IModelError]] if there is a problem creating the element. */ - public createElement(elProps: ElementProps): T { return this._iModel.constructEntity(elProps); } + public createElement(elProps: ElementProps): T { + return this._iModel.constructEntity(elProps); + } /** Insert a new element into the iModel. * @param elProps The properties of the new element. @@ -2069,7 +2208,9 @@ export namespace IModelDb { // eslint-disable-line no-redeclare } /** Get the root subject element. */ - public getRootSubject(): Subject { return this.getElement(IModel.rootSubjectId); } + public getRootSubject(): Subject { + return this.getElement(IModel.rootSubjectId); + } /** Query for aspects of a particular class (polymorphically) associated with this element. * @throws [[IModelError]] @@ -2097,16 +2238,19 @@ export namespace IModelDb { // eslint-disable-line no-redeclare */ private _queryAspect(aspectInstanceId: Id64String, aspectClassName: string): ElementAspect { const sql = `SELECT * FROM ${aspectClassName} WHERE ECInstanceId=:aspectInstanceId`; - const aspect: ElementAspectProps | undefined = this._iModel.withPreparedStatement(sql, (statement: ECSqlStatement): ElementAspectProps | undefined => { - statement.bindId("aspectInstanceId", aspectInstanceId); - if (DbResult.BE_SQLITE_ROW === statement.step()) { - const aspectProps: ElementAspectProps = statement.getRow(); // start with everything that SELECT * returned - aspectProps.classFullName = (aspectProps as any).className.replace(".", ":"); // add in property required by EntityProps - (aspectProps as any).className = undefined; // clear property from SELECT * that we don't want in the final instance - return aspectProps; - } - return undefined; - }); + const aspect: ElementAspectProps | undefined = this._iModel.withPreparedStatement( + sql, + (statement: ECSqlStatement): ElementAspectProps | undefined => { + statement.bindId("aspectInstanceId", aspectInstanceId); + if (DbResult.BE_SQLITE_ROW === statement.step()) { + const aspectProps: ElementAspectProps = statement.getRow(); // start with everything that SELECT * returned + aspectProps.classFullName = (aspectProps as any).className.replace(".", ":"); // add in property required by EntityProps + (aspectProps as any).className = undefined; // clear property from SELECT * that we don't want in the final instance + return aspectProps; + } + return undefined; + }, + ); if (undefined === aspect) { throw new IModelError(IModelStatus.NotFound, `ElementAspect not found ${aspectInstanceId}, ${aspectClassName}`); } @@ -2160,10 +2304,14 @@ export namespace IModelDb { // eslint-disable-line no-redeclare */ public getAspects(elementId: Id64String, aspectClassFullName?: string, excludedClassFullNames?: Set): ElementAspect[] { if (aspectClassFullName === undefined) { - const allAspects: ElementAspect[] = this.runInstanceQuery(`SELECT $ FROM ( + const allAspects: ElementAspect[] = this.runInstanceQuery( + `SELECT $ FROM ( SELECT ECInstanceId, ECClassId FROM Bis.ElementMultiAspect WHERE Element.Id = :elementId UNION ALL - SELECT ECInstanceId, ECClassId FROM Bis.ElementUniqueAspect WHERE Element.Id = :elementId) OPTIONS USE_JS_PROP_NAMES DO_NOT_TRUNCATE_BLOB`, elementId, excludedClassFullNames); + SELECT ECInstanceId, ECClassId FROM Bis.ElementUniqueAspect WHERE Element.Id = :elementId) OPTIONS USE_JS_PROP_NAMES DO_NOT_TRUNCATE_BLOB`, + elementId, + excludedClassFullNames, + ); if (allAspects.length === 0) Logger.logInfo(BackendLoggerCategory.ECDb, `No aspects found for class ${aspectClassFullName} and element ${elementId}`); return allAspects; @@ -2181,11 +2329,16 @@ export namespace IModelDb { // eslint-disable-line no-redeclare let classIdList = IModelDb.Elements.classMap.get(aspectClassFullName); if (classIdList === undefined) { const classIds: string[] = []; - this._iModel.withPreparedStatement(`select SourceECInstanceId from meta.ClassHasAllBaseClasses where TargetECInstanceId = (select ECInstanceId from meta.ECClassDef where Name='${fullClassName[1]}' - and Schema.Id = (select ECInstanceId from meta.ECSchemaDef where Name='${fullClassName[0]}')) and SourceECInstanceId != TargetECInstanceId`, (statement: ECSqlStatement) => { - while (statement.step() === DbResult.BE_SQLITE_ROW) - classIds.push(statement.getValue(0).getId()); - }); + this._iModel.withPreparedStatement( + `select SourceECInstanceId from meta.ClassHasAllBaseClasses where TargetECInstanceId = (select ECInstanceId from meta.ECClassDef where Name='${ + fullClassName[1] + }' + and Schema.Id = (select ECInstanceId from meta.ECSchemaDef where Name='${fullClassName[0]}')) and SourceECInstanceId != TargetECInstanceId`, + (statement: ECSqlStatement) => { + while (statement.step() === DbResult.BE_SQLITE_ROW) + classIds.push(statement.getValue(0).getId()); + }, + ); if (classIds.length > 0) { classIdList = classIds.join(","); IModelDb.Elements.classMap.set(aspectClassFullName, classIdList); @@ -2196,11 +2349,15 @@ export namespace IModelDb { // eslint-disable-line no-redeclare return []; } // Execute an instance query to retrieve all aspects from all the derived classes - const aspects: ElementAspect[] = this.runInstanceQuery(`SELECT $ FROM ( + const aspects: ElementAspect[] = this.runInstanceQuery( + `SELECT $ FROM ( SELECT ECInstanceId, ECClassId FROM Bis.ElementMultiAspect WHERE Element.Id = :elementId AND ECClassId IN (${classIdList}) UNION ALL SELECT ECInstanceId, ECClassId FROM Bis.ElementUniqueAspect WHERE Element.Id = :elementId AND ECClassId IN (${classIdList}) - ) OPTIONS USE_JS_PROP_NAMES DO_NOT_TRUNCATE_BLOB`, elementId, excludedClassFullNames); + ) OPTIONS USE_JS_PROP_NAMES DO_NOT_TRUNCATE_BLOB`, + elementId, + excludedClassFullNames, + ); if (aspects.length === 0) Logger.logInfo(BackendLoggerCategory.ECDb, `No aspects found for class ${aspectClassFullName} and element ${elementId}`); return aspects; @@ -2254,10 +2411,12 @@ export namespace IModelDb { // eslint-disable-line no-redeclare */ export class Views { /** @internal */ - public constructor(private _iModel: IModelDb) { } + public constructor(private _iModel: IModelDb) {} private static viewStoreProperty = { namespace: "itwinjs", name: "DefaultViewStore" }; private _viewStore?: ViewStore.CloudAccess; - public get hasViewStore(): boolean { return undefined !== this._viewStore; } + public get hasViewStore(): boolean { + return undefined !== this._viewStore; + } /** @beta */ public get viewStore(): ViewStore.CloudAccess { @@ -2269,7 +2428,9 @@ export namespace IModelDb { // eslint-disable-line no-redeclare this._viewStore = viewStore; } /** @beta */ - public async accessViewStore(args: { props?: CloudSqlite.ContainerProps, accessLevel?: BlobContainer.RequestAccessLevel }): Promise { + public async accessViewStore( + args: { props?: CloudSqlite.ContainerProps, accessLevel?: BlobContainer.RequestAccessLevel }, + ): Promise { let props = args.props; if (undefined === props) { const propsString = this._iModel.queryFilePropertyString(Views.viewStoreProperty); @@ -2300,7 +2461,12 @@ export namespace IModelDb { // eslint-disable-line no-redeclare * @param className Query for view definitions of this class. * @param wantPrivate If true, include private view definitions. */ - public queryViewDefinitionProps(className: string = "BisCore.ViewDefinition", limit = IModelDb.defaultLimit, offset = 0, wantPrivate: boolean = false): ViewDefinitionProps[] { + public queryViewDefinitionProps( + className: string = "BisCore.ViewDefinition", + limit = IModelDb.defaultLimit, + offset = 0, + wantPrivate: boolean = false, + ): ViewDefinitionProps[] { const where = (wantPrivate === false) ? "IsPrivate=FALSE" : ""; const ids = this._iModel.queryEntityIds({ from: className, limit, offset, where }); @@ -2309,7 +2475,7 @@ export namespace IModelDb { // eslint-disable-line no-redeclare ids.forEach((id) => { try { props.push(imodel.elements.getElementProps(id)); - } catch (err: any) { } + } catch (err: any) {} }); return props; @@ -2334,7 +2500,7 @@ export namespace IModelDb { // eslint-disable-line no-redeclare if (!finished) break; } - } catch (err: any) { } + } catch (err: any) {} } return finished; @@ -2466,9 +2632,9 @@ export namespace IModelDb { // eslint-disable-line no-redeclare } /** Represents the current state of a pollable tile content request. - * Note: lack of a "completed" state because polling a completed request returns the content as a Uint8Array. - * @internal - */ + * Note: lack of a "completed" state because polling a completed request returns the content as a Uint8Array. + * @internal + */ export enum TileContentState { New, // Request was just created and enqueued. Pending, // Request is enqueued but not yet being processed. @@ -2478,11 +2644,10 @@ export namespace IModelDb { // eslint-disable-line no-redeclare /** @internal */ export class Tiles { /** @internal */ - public constructor(private _iModel: IModelDb) { } + public constructor(private _iModel: IModelDb) {} /** @internal */ public async requestTileTreeProps(id: string): Promise { - return new Promise((resolve, reject) => { this._iModel[_nativeDb].getTileTree(id, (ret: IModelJsNative.ErrorStatusOrResult) => { if (undefined !== ret.error) @@ -2494,7 +2659,6 @@ export namespace IModelDb { // eslint-disable-line no-redeclare } private pollTileContent(resolve: (arg0: IModelJsNative.TileContent) => void, reject: (err: unknown) => void, treeId: string, tileId: string) { - let ret; try { ret = this._iModel[_nativeDb].pollTileContent(treeId, tileId); @@ -2513,13 +2677,21 @@ export namespace IModelDb { // eslint-disable-line no-redeclare const tileSizeThreshold = IModelHost.logTileSizeThreshold; const tileSize = res.content.length; if (tileSize > tileSizeThreshold) { - Logger.logWarning(loggerCategory, "Tile size (in bytes) larger than specified threshold", () => ({ tileSize, tileSizeThreshold, treeId, tileId, iModelId })); + Logger.logWarning( + loggerCategory, + "Tile size (in bytes) larger than specified threshold", + () => ({ tileSize, tileSizeThreshold, treeId, tileId, iModelId }), + ); } const loadTimeThreshold = IModelHost.logTileLoadTimeThreshold; const loadTime = res.elapsedSeconds; if (loadTime > loadTimeThreshold) { - Logger.logWarning(loggerCategory, "Tile load time (in seconds) greater than specified threshold", () => ({ loadTime, loadTimeThreshold, treeId, tileId, iModelId })); + Logger.logWarning( + loggerCategory, + "Tile load time (in seconds) greater than specified threshold", + () => ({ loadTime, loadTimeThreshold, treeId, tileId, iModelId }), + ); } resolve(res); @@ -2591,7 +2763,9 @@ export class BriefcaseDb extends IModelDb { public readonly txns: TxnManager = new TxnManager(this); /** override superclass method */ - public override get isBriefcase(): boolean { return true; } + public override get isBriefcase(): boolean { + return true; + } /* the BriefcaseId of the briefcase opened with this BriefcaseDb */ public readonly briefcaseId: BriefcaseId; @@ -2599,7 +2773,9 @@ export class BriefcaseDb extends IModelDb { private _skipSyncSchemasOnPullAndPush?: true; /** @internal */ - public get skipSyncSchemasOnPullAndPush() { return this._skipSyncSchemasOnPullAndPush ?? false; } + public get skipSyncSchemasOnPullAndPush() { + return this._skipSyncSchemasOnPullAndPush ?? false; + } /** * Event raised just before a BriefcaseDb is opened. Supplies the arguments that will be used to open the BriefcaseDb. @@ -2640,8 +2816,10 @@ export class BriefcaseDb extends IModelDb { /** * The Guid that identifies the *context* that owns this iModel. * GuidString | undefined for the superclass, but required for BriefcaseDb - * */ - public override get iTwinId(): GuidString { return super.iTwinId!; } // eslint-disable-line @typescript-eslint/no-non-null-assertion + */ + public override get iTwinId(): GuidString { + return super.iTwinId!; + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** * Determine whether this BriefcaseDb should use a lock server. @@ -2651,7 +2829,8 @@ export class BriefcaseDb extends IModelDb { * - the "no locking" flag is not present. This is a property of an iModel, established when the iModel is created in IModelHub. */ protected get useLockServer(): boolean { - return !this[_nativeDb].isReadonly() && (this.briefcaseId !== BriefcaseIdValue.Unassigned) && (undefined === this[_nativeDb].queryLocalValue(BriefcaseLocalValue.NoLocking)); + return !this[_nativeDb].isReadonly() && (this.briefcaseId !== BriefcaseIdValue.Unassigned) && + (undefined === this[_nativeDb].queryLocalValue(BriefcaseLocalValue.NoLocking)); } // if the iModel uses a lock server, create a ServerBasedLocks LockControl for this BriefcaseDb. @@ -2706,7 +2885,7 @@ export class BriefcaseDb extends IModelDb { * Note that the upgrade requires that the local briefcase be closed, and may result in one or two change sets depending on whether both * profile and domain schemas need to get upgraded. * @see ($docs/learning/backend/IModelDb.md#upgrading-schemas-in-an-imodel) - */ + */ public static async upgradeSchemas(briefcase: OpenBriefcaseArgs): Promise { // upgrading schemas involves closing and reopening the file repeatedly. That's because the process of upgrading // happens on a file open. We have to open-and-close the file at *each* of these steps: @@ -2788,11 +2967,18 @@ export class BriefcaseDb extends IModelDb { this.onCodeServiceCreated.raiseEvent(briefcaseDb); } catch (e: any) { if ((e as CodeService.Error).errorId !== "NoCodeIndex") { // no code index means iModel isn't enforcing codes. - Logger.logWarning(loggerCategory, `The CodeService is not available for this briefcase: errorId: ${(e as CodeService.Error).errorId}, errorMessage; ${e.message}. Proceeding with BriefcaseDb.open(), but all operations involving codes will fail.`); + Logger.logWarning( + loggerCategory, + `The CodeService is not available for this briefcase: errorId: ${ + (e as CodeService.Error).errorId + }, errorMessage; ${e.message}. Proceeding with BriefcaseDb.open(), but all operations involving codes will fail.`, + ); briefcaseDb._codeService = { verifyCode: (props: CodeService.ElementCodeProps) => { if (!Code.isEmpty(props.props.code)) { - e.message = `The CodeService is not available for this briefcase: errorId: ${(e as CodeService.Error).errorId}, errorMessage; ${e.message}.`; + e.message = `The CodeService is not available for this briefcase: errorId: ${ + (e as CodeService.Error).errorId + }, errorMessage; ${e.message}.`; throw e; } }, @@ -2800,8 +2986,8 @@ export class BriefcaseDb extends IModelDb { author: { name: "unknown" }, origin: { name: "unknown" }, }, - close: () => { }, - initialize: async () => { }, + close: () => {}, + initialize: async () => {}, }; } } @@ -2833,19 +3019,19 @@ export class BriefcaseDb extends IModelDb { if (args.cause === DbConflictCause.Data && !args.indirect) { /* - * From SQLite Docs CHANGESET_DATA as the second argument - * when processing a DELETE or UPDATE change if a row with the required - * PRIMARY KEY fields is present in the database, but one or more other - * (non primary-key) fields modified by the update do not contain the - * expected "before" values. - * - * The conflicting row, in this case, is the database row with the matching - * primary key. - * - * Another reason this will be invoked is when SQLITE_CHANGESETAPPLY_FKNOACTION - * is passed ApplyChangeset(). The flag will disable CASCADE action and treat - * them as CASCADE NONE resulting in conflict handler been called. - */ + * From SQLite Docs CHANGESET_DATA as the second argument + * when processing a DELETE or UPDATE change if a row with the required + * PRIMARY KEY fields is present in the database, but one or more other + * (non primary-key) fields modified by the update do not contain the + * expected "before" values. + * + * The conflicting row, in this case, is the database row with the matching + * primary key. + * + * Another reason this will be invoked is when SQLITE_CHANGESETAPPLY_FKNOACTION + * is passed ApplyChangeset(). The flag will disable CASCADE action and treat + * them as CASCADE NONE resulting in conflict handler been called. + */ if (!this.txns.hasPendingTxns) { // This changeset is bad. However, it is already in the timeline. We must allow services such as // checkpoint-creation, change history, and other apps to apply any changeset that is in the timeline. @@ -2898,7 +3084,10 @@ export class BriefcaseDb extends IModelDb { // Note: There is no performance implication of follow code as it happen toward end of // apply_changeset only once so we be querying value for 'DebugAllowFkViolations' only once. if (this[_nativeDb].queryLocalValue("DebugAllowFkViolations")) { - Logger.logError(category, `Detected ${nConflicts} foreign key conflicts in changeset. Continuing merge as 'DebugAllowFkViolations' flag is set. Run 'PRAGMA foreign_key_check' to get list of violations.`); + Logger.logError( + category, + `Detected ${nConflicts} foreign key conflicts in changeset. Continuing merge as 'DebugAllowFkViolations' flag is set. Run 'PRAGMA foreign_key_check' to get list of violations.`, + ); return DbConflictResolution.Skip; } else { const msg = `Detected ${nConflicts} foreign key conflicts in ChangeSet. Aborting merge.`; @@ -2922,7 +3111,10 @@ export class BriefcaseDb extends IModelDb { args.dump(); } - Logger.logWarning(category, "Constraint conflict handled by rejecting incoming change. Constraint conflicts are NOT expected. These happen most often when two clients both insert elements with the same code. That indicates a bug in the client or the code server."); + Logger.logWarning( + category, + "Constraint conflict handled by rejecting incoming change. Constraint conflicts are NOT expected. These happen most often when two clients both insert elements with the same code. That indicates a bug in the client or the code server.", + ); return DbConflictResolution.Skip; } @@ -3052,7 +3244,9 @@ export class BriefcaseDb extends IModelDb { await BriefcaseManager.revertTimelineChanges(this, arg); this.saveChanges("Revert changes"); if (!arg.description) { - arg.description = `Reverted changes from ${this.changeset.index} to ${arg.toIndex}${arg.skipSchemaChanges ? " (schema changes skipped)" : ""}`; + arg.description = `Reverted changes from ${this.changeset.index} to ${arg.toIndex}${ + arg.skipSchemaChanges ? " (schema changes skipped)" : "" + }`; } const pushArgs = { description: arg.description, @@ -3136,7 +3330,12 @@ class RefreshV2CheckpointSas { throw new Error("checkpoint is not from a cloud container"); assert(undefined !== iModel.iTwinId); - const props = await IModelHost.hubAccess.queryV2Checkpoint({ accessToken, iTwinId: iModel.iTwinId, iModelId: iModel.iModelId, changeset: iModel.changeset }); + const props = await IModelHost.hubAccess.queryV2Checkpoint({ + accessToken, + iTwinId: iModel.iTwinId, + iModelId: iModel.iModelId, + changeset: iModel.changeset, + }); if (!props) throw new Error("can't reset checkpoint sas token"); @@ -3166,7 +3365,6 @@ class RefreshV2CheckpointSas { return this._promise; } - } /** A *snapshot* iModel database file that is used for archival and data transfer purposes. * @see [Snapshot iModels]($docs/learning/backend/AccessingIModels.md#snapshot-imodels) @@ -3174,7 +3372,9 @@ class RefreshV2CheckpointSas { * @public */ export class SnapshotDb extends IModelDb { - public override get isSnapshot() { return true; } + public override get isSnapshot() { + return true; + } private _refreshSas: RefreshV2CheckpointSas | undefined; /** Timer used to restart the default txn on the SnapshotDb after some inactivity. This is only used for checkpoints. * Restarting the default txn lets CloudSqlite know that any blocks that may have been read may now be ejected. @@ -3362,8 +3562,12 @@ export class SnapshotDb extends IModelDb { * @public */ export class StandaloneDb extends BriefcaseDb { - public override get isStandalone(): boolean { return true; } - protected override get useLockServer() { return false; } // standalone iModels have no lock server + public override get isStandalone(): boolean { + return true; + } + protected override get useLockServer() { + return false; + } // standalone iModels have no lock server public static override findByKey(key: string): StandaloneDb { return super.findByKey(key) as StandaloneDb; } @@ -3440,6 +3644,5 @@ export class StandaloneDb extends BriefcaseDb { nativeDb.closeFile(); throw error; } - } } diff --git a/core/backend/src/IModelElementCloneContext.ts b/core/backend/src/IModelElementCloneContext.ts index a86d365e49ed..cf6b2b82a29e 100644 --- a/core/backend/src/IModelElementCloneContext.ts +++ b/core/backend/src/IModelElementCloneContext.ts @@ -5,15 +5,15 @@ /** @packageDocumentation * @module iModels */ +import { IModelJsNative } from "@bentley/imodeljs-native"; import { Id64, Id64String } from "@itwin/core-bentley"; import { Code, CodeScopeSpec, CodeSpec, ElementProps, IModel, PropertyMetaData, RelatedElement } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; import { SubCategory } from "./Category"; import { Element } from "./Element"; import { IModelDb } from "./IModelDb"; import { IModelNative } from "./internal/NativePlatform"; -import { SQLiteDb } from "./SQLiteDb"; import { _nativeDb } from "./internal/Symbols"; +import { SQLiteDb } from "./SQLiteDb"; /** The context for transforming a *source* Element to a *target* Element and remapping internal identifiers to the target iModel. * @beta @@ -48,15 +48,21 @@ export class IModelElementCloneContext { } /** Returns `true` if this context is for transforming between 2 iModels and `false` if it for transforming within the same iModel. */ - public get isBetweenIModels(): boolean { return this.sourceDb !== this.targetDb; } + public get isBetweenIModels(): boolean { + return this.sourceDb !== this.targetDb; + } /** Dispose any native resources associated with this IModelElementCloneContext. */ - public dispose(): void { this._nativeContext.dispose(); } + public dispose(): void { + this._nativeContext.dispose(); + } /** Debugging aid that dumps the Id remapping details and other information to the specified output file. * @internal */ - public dump(outputFileName: string): void { this._nativeContext.dump(outputFileName); } + public dump(outputFileName: string): void { + this._nativeContext.dump(outputFileName); + } /** Add a rule that remaps the specified source [CodeSpec]($common) to the specified target [CodeSpec]($common). * @param sourceCodeSpecName The name of the CodeSpec from the source iModel. diff --git a/core/backend/src/IModelHost.ts b/core/backend/src/IModelHost.ts index 1e2775f0e5bb..ac48a5afd41a 100644 --- a/core/backend/src/IModelHost.ts +++ b/core/backend/src/IModelHost.ts @@ -9,8 +9,8 @@ // To avoid circular load errors, the "Element" classes must be loaded before IModelHost. import "./IModelDb"; // DO NOT REMOVE OR MOVE THIS LINE! -import { IModelNative, loadNativePlatform } from "./internal/NativePlatform"; import * as os from "os"; +import { IModelNative, loadNativePlatform } from "./internal/NativePlatform"; import "reflect-metadata"; // this has to be before @itwin/object-storage-* and @itwin/cloud-agnostic-core imports because those packages contain decorators that use this polyfill. import { IModelJsNative, NativeLibrary } from "@bentley/imodeljs-native"; import { DependenciesConfig, Types as ExtensionTypes } from "@itwin/cloud-agnostic-core"; @@ -18,6 +18,8 @@ import { AccessToken, assert, BeEvent, DbResult, Guid, GuidString, IModelStatus, import { AuthorizationClient, BentleyStatus, IModelError, LocalDirName, SessionProps } from "@itwin/core-common"; import { AzureServerStorageBindings } from "@itwin/object-storage-azure"; import { ServerStorage } from "@itwin/object-storage-core"; +import { Container } from "inversify"; +import { join, normalize as normalizeDir } from "path"; import { BackendHubAccess } from "./BackendHubAccess"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { BisCoreSchema } from "./BisCoreSchema"; @@ -27,6 +29,9 @@ import { FunctionalSchema } from "./domains/FunctionalSchema"; import { GenericSchema } from "./domains/GenericSchema"; import { GeoCoordConfig } from "./GeoCoordConfig"; import { IModelJsFs } from "./IModelJsFs"; +import { SettingsImpl } from "./internal/workspace/SettingsImpl"; +import { constructSettingsSchemas } from "./internal/workspace/SettingsSchemasImpl"; +import { constructWorkspace, OwnedWorkspace } from "./internal/workspace/WorkspaceImpl"; import { DevToolsRpcImpl } from "./rpc-impl/DevToolsRpcImpl"; import { IModelReadRpcImpl } from "./rpc-impl/IModelReadRpcImpl"; import { IModelTileRpcImpl } from "./rpc-impl/IModelTileRpcImpl"; @@ -37,11 +42,6 @@ import { TileStorage } from "./TileStorage"; import { SettingsContainer, SettingsPriority } from "./workspace/Settings"; import { SettingsSchemas } from "./workspace/SettingsSchemas"; import { Workspace, WorkspaceOpts } from "./workspace/Workspace"; -import { Container } from "inversify"; -import { join, normalize as normalizeDir } from "path"; -import { constructWorkspace, OwnedWorkspace } from "./internal/workspace/WorkspaceImpl"; -import { SettingsImpl } from "./internal/workspace/SettingsImpl"; -import { constructSettingsSchemas } from "./internal/workspace/SettingsSchemasImpl"; const loggerCategory = BackendLoggerCategory.IModelHost; @@ -278,7 +278,7 @@ const definedInStartup = (obj: T | undefined): T => { * @public */ export class IModelHost { - private constructor() { } + private constructor() {} /** The AuthorizationClient used to obtain [AccessToken]($bentley)s. */ public static authorizationClient?: AuthorizationClient; @@ -294,7 +294,9 @@ export class IModelHost { * @deprecated in 4.8. This internal API will be removed in 5.0. Use IModelHost's public API instead. * @internal */ - public static get platform(): typeof IModelJsNative { return IModelNative.platform; } + public static get platform(): typeof IModelJsNative { + return IModelNative.platform; + } public static configuration?: IModelHostOptions; @@ -334,22 +336,36 @@ export class IModelHost { public static readonly session: Mutable = { applicationId: "2686", applicationVersion: "1.0.0", sessionId: "" }; /** A uniqueId for this session */ - public static get sessionId() { return this.session.sessionId; } - public static set sessionId(id: GuidString) { this.session.sessionId = id; } + public static get sessionId() { + return this.session.sessionId; + } + public static set sessionId(id: GuidString) { + this.session.sessionId = id; + } /** The Id of this application - needs to be set only if it is an agent application. The applicationId will otherwise originate at the frontend. */ - public static get applicationId() { return this.session.applicationId; } - public static set applicationId(id: string) { this.session.applicationId = id; } + public static get applicationId() { + return this.session.applicationId; + } + public static set applicationId(id: string) { + this.session.applicationId = id; + } /** The version of this application - needs to be set if is an agent application. The applicationVersion will otherwise originate at the frontend. */ - public static get applicationVersion() { return this.session.applicationVersion; } - public static set applicationVersion(version: string) { this.session.applicationVersion = version; } + public static get applicationVersion() { + return this.session.applicationVersion; + } + public static set applicationVersion(version: string) { + this.session.applicationVersion = version; + } /** A string that can identify the current user to other users when collaborating. */ public static userMoniker = "unknown"; /** Root directory holding files that iTwin.js caches */ - public static get cacheDir(): LocalDirName { return this._cacheDir; } + public static get cacheDir(): LocalDirName { + return this._cacheDir; + } /** The application [[Workspace]] for this `IModelHost` * @note this `Workspace` only holds [[WorkspaceContainer]]s and [[Settings]] scoped to the currently loaded application(s). @@ -357,13 +373,17 @@ export class IModelHost { * attempting to add them to this Workspace will fail. * @beta */ - public static get appWorkspace(): Workspace { return definedInStartup(this._appWorkspace); } + public static get appWorkspace(): Workspace { + return definedInStartup(this._appWorkspace); + } /** The registry of schemas describing the [[Setting]]s for the application session. * Applications should register their schemas via methods like [[SettingsSchemas.addGroup]]. * @beta */ - public static get settingsSchemas(): SettingsSchemas { return definedInStartup(this._settingsSchemas); } + public static get settingsSchemas(): SettingsSchemas { + return definedInStartup(this._settingsSchemas); + } /** The optional [[FileNameResolver]] that resolves keys and partial file names for snapshot iModels. * @deprecated in 4.10. When opening a snapshot by file name, ensure to pass already resolved path. Using a key to open a snapshot is now deprecated. @@ -388,7 +408,10 @@ export class IModelHost { private static loadNative(options: IModelHostOptions) { loadNativePlatform(); - if (options.crashReportingConfig && options.crashReportingConfig.crashDir && !ProcessDetector.isElectronAppBackend && !ProcessDetector.isMobileAppBackend) { + if ( + options.crashReportingConfig && options.crashReportingConfig.crashDir && !ProcessDetector.isElectronAppBackend && + !ProcessDetector.isMobileAppBackend + ) { IModelNative.platform.setCrashReporting(options.crashReportingConfig); Logger.logTrace(loggerCategory, "Configured crash reporting", { @@ -416,12 +439,16 @@ export class IModelHost { private static _hubAccess?: BackendHubAccess; /** @internal */ - public static setHubAccess(hubAccess: BackendHubAccess | undefined) { this._hubAccess = hubAccess; } + public static setHubAccess(hubAccess: BackendHubAccess | undefined) { + this._hubAccess = hubAccess; + } /** get the current hubAccess, if present. * @internal */ - public static getHubAccess(): BackendHubAccess | undefined { return this._hubAccess; } + public static getHubAccess(): BackendHubAccess | undefined { + return this._hubAccess; + } /** Provides access to the IModelHub for this IModelHost * @internal @@ -444,7 +471,9 @@ export class IModelHost { try { this.appWorkspace.getCloudCache(); } catch (e: any) { - throw (e.errorNumber === DbResult.BE_SQLITE_BUSY) ? new IModelError(DbResult.BE_SQLITE_BUSY, `Profile [${this.profileDir}] is already in use by another process`) : e; + throw (e.errorNumber === DbResult.BE_SQLITE_BUSY) + ? new IModelError(DbResult.BE_SQLITE_BUSY, `Profile [${this.profileDir}] is already in use by another process`) + : e; } this.appWorkspace.settings.addDirectory(settingAssets, SettingsPriority.defaults); @@ -672,7 +701,6 @@ export class Platform { * @public */ export class KnownLocations { - /** The directory where the imodeljs-native assets are stored. */ public static get nativeAssetsDir(): LocalDirName { return IModelNative.platform.DgnDb.getAssetsDir(); @@ -700,7 +728,9 @@ export abstract class FileNameResolver { * @param _fileKey The key that identifies the file name in a `Map` or other similar data structure. * @returns The resolved file name or `undefined` if not found. */ - public tryResolveKey(_fileKey: string): string | undefined { return undefined; } + public tryResolveKey(_fileKey: string): string | undefined { + return undefined; + } /** Resolve a file name from the specified key. * @param fileKey The key that identifies the file name in a `Map` or other similar data structure. * @returns The resolved file name. @@ -717,7 +747,9 @@ export abstract class FileNameResolver { * @param inFileName The partial file name. * @returns The resolved full path file name or `undefined` if not found. */ - public tryResolveFileName(inFileName: string): string | undefined { return inFileName; } + public tryResolveFileName(inFileName: string): string | undefined { + return inFileName; + } /** Resolve the input file name, which may be a partial name, into a full path file name. * @param inFileName The partial file name. * @returns The resolved full path file name. diff --git a/core/backend/src/IModelJsFs.ts b/core/backend/src/IModelJsFs.ts index 34816d3e7b14..3b4bcdd842d2 100644 --- a/core/backend/src/IModelJsFs.ts +++ b/core/backend/src/IModelJsFs.ts @@ -27,43 +27,62 @@ export class IModelJsFsStats { public isSocket: boolean, public isSymbolicLink: boolean, public isReadOnly: boolean, - ) { } + ) {} } /** File system operations that are defined on all platforms. See also [[Platform]] and [[KnownLocations]] * @public */ export class IModelJsFs { - /** Does file or directory exist? */ - public static existsSync(pathname: string): boolean { return fs.existsSync(pathname); } + public static existsSync(pathname: string): boolean { + return fs.existsSync(pathname); + } /** Delete a file. */ - public static unlinkSync(pathname: string): void { fs.unlinkSync(pathname); } + public static unlinkSync(pathname: string): void { + fs.unlinkSync(pathname); + } /** Delete a file or remove a directory (rm -r). */ - public static removeSync(pathname: string): void { fs.removeSync(pathname); } + public static removeSync(pathname: string): void { + fs.removeSync(pathname); + } /** Create a directory. */ - public static mkdirSync(pathname: string): void { fs.mkdirSync(pathname); } + public static mkdirSync(pathname: string): void { + fs.mkdirSync(pathname); + } /** Remove a directory. */ - public static rmdirSync(pathname: string): void { fs.rmdirSync(pathname); } + public static rmdirSync(pathname: string): void { + fs.rmdirSync(pathname); + } /** Write to a file. */ - public static writeFileSync(pathname: string, data: string | Uint8Array, wflag: string = "w"): void { fs.writeFileSync(pathname, data, { flag: wflag }); } + public static writeFileSync(pathname: string, data: string | Uint8Array, wflag: string = "w"): void { + fs.writeFileSync(pathname, data, { flag: wflag }); + } /** Append to a file. */ - public static appendFileSync(pathname: string, str: string): void { fs.appendFileSync(pathname, str); } + public static appendFileSync(pathname: string, str: string): void { + fs.appendFileSync(pathname, str); + } /** Make a copy of a file */ - public static copySync(src: string, dest: string, opts?: any): void { fs.copySync(src, dest, opts); } + public static copySync(src: string, dest: string, opts?: any): void { + fs.copySync(src, dest, opts); + } /** Gets the file and directory names in the specified directory. Excludes "." and "..". Returns an empty array if the specified directory does not exist. */ - public static readdirSync(pathname: string): string[] { return fs.existsSync(pathname) ? fs.readdirSync(pathname) : []; } + public static readdirSync(pathname: string): string[] { + return fs.existsSync(pathname) ? fs.readdirSync(pathname) : []; + } /** Read file */ - public static readFileSync(pathname: string): string | Buffer { return fs.readFileSync(pathname); } + public static readFileSync(pathname: string): string | Buffer { + return fs.readFileSync(pathname); + } /** Test if the current user has permission to write to a file. */ private static isFileWritable(pathname: string): boolean { @@ -90,7 +109,8 @@ export class IModelJsFs { stats.isFile(), stats.isSocket(), stats.isSymbolicLink(), - !IModelJsFs.isFileWritable(pathname)); + !IModelJsFs.isFileWritable(pathname), + ); } /** diff --git a/core/backend/src/IpcHost.ts b/core/backend/src/IpcHost.ts index 571ca49626c8..e7abe1b33184 100644 --- a/core/backend/src/IpcHost.ts +++ b/core/backend/src/IpcHost.ts @@ -9,21 +9,39 @@ import { IModelJsNative } from "@bentley/imodeljs-native"; import { assert, BentleyError, IModelStatus, Logger, LogLevel, OpenMode } from "@itwin/core-bentley"; import { - ChangesetIndex, ChangesetIndexAndId, EditingScopeNotifications, getPullChangesIpcChannel, IModelConnectionProps, IModelError, IModelRpcProps, - ipcAppChannels, IpcAppFunctions, IpcAppNotifications, IpcInvokeReturn, IpcListener, IpcSocketBackend, iTwinChannel, - OpenBriefcaseProps, OpenCheckpointArgs, PullChangesOptions, RemoveFunction, StandaloneOpenOptions, TileTreeContentIds, TxnNotifications, + ChangesetIndex, + ChangesetIndexAndId, + EditingScopeNotifications, + getPullChangesIpcChannel, + IModelConnectionProps, + IModelError, + IModelRpcProps, + ipcAppChannels, + IpcAppFunctions, + IpcAppNotifications, + IpcInvokeReturn, + IpcListener, + IpcSocketBackend, + iTwinChannel, + OpenBriefcaseProps, + OpenCheckpointArgs, + PullChangesOptions, + RemoveFunction, + StandaloneOpenOptions, + TileTreeContentIds, + TxnNotifications, } from "@itwin/core-common"; import { ProgressFunction, ProgressStatus } from "./CheckpointManager"; import { BriefcaseDb, IModelDb, SnapshotDb, StandaloneDb } from "./IModelDb"; import { IModelHost, IModelHostOptions } from "./IModelHost"; -import { cancelTileContentRequests } from "./rpc-impl/IModelTileRpcImpl"; import { IModelNative } from "./internal/NativePlatform"; import { _nativeDb } from "./internal/Symbols"; +import { cancelTileContentRequests } from "./rpc-impl/IModelTileRpcImpl"; /** - * Options for [[IpcHost.startup]] - * @public - */ + * Options for [[IpcHost.startup]] + * @public + */ export interface IpcHostOpts { iModelHost?: IModelHostOptions; ipcHost?: { @@ -46,9 +64,13 @@ export class IpcHost { public static noStack = false; private static _ipc: IpcSocketBackend | undefined; /** Get the implementation of the [IpcSocketBackend]($common) interface. */ - private static get ipc(): IpcSocketBackend { return this._ipc!; } // eslint-disable-line @typescript-eslint/no-non-null-assertion + private static get ipc(): IpcSocketBackend { + return this._ipc!; + } // eslint-disable-line @typescript-eslint/no-non-null-assertion /** Determine whether Ipc is available for this backend. This will only be true if [[startup]] has been called on this class. */ - public static get isValid(): boolean { return undefined !== this._ipc; } + public static get isValid(): boolean { + return undefined !== this._ipc; + } /** * Send a message to the frontend over an Ipc channel. @@ -97,12 +119,20 @@ export class IpcHost { } /** @internal */ - public static notifyTxns(briefcase: BriefcaseDb | StandaloneDb, methodName: T, ...args: Parameters) { + public static notifyTxns( + briefcase: BriefcaseDb | StandaloneDb, + methodName: T, + ...args: Parameters + ) { this.notify(ipcAppChannels.txns, briefcase, methodName, ...args); } /** @internal */ - public static notifyEditingScope(briefcase: BriefcaseDb | StandaloneDb, methodName: T, ...args: Parameters) { + public static notifyEditingScope( + briefcase: BriefcaseDb | StandaloneDb, + methodName: T, + ...args: Parameters + ) { this.notify(ipcAppChannels.editingScope, briefcase, methodName, ...args); } @@ -164,7 +194,10 @@ export abstract class IpcHandler { try { const func = (impl as any)[funcName]; if (typeof func !== "function") - throw new IModelError(IModelStatus.FunctionNotFound, `Method "${impl.constructor.name}.${funcName}" not found on IpcHandler registered for channel: ${impl.channelName}`); + throw new IModelError( + IModelStatus.FunctionNotFound, + `Method "${impl.constructor.name}.${funcName}" not found on IpcHandler registered for channel: ${impl.channelName}`, + ); return { result: await func.call(impl, ...args) }; } catch (err: any) { @@ -187,7 +220,9 @@ export abstract class IpcHandler { * Implementation of IpcAppFunctions */ class IpcAppHandler extends IpcHandler implements IpcAppFunctions { - public get channelName() { return ipcAppChannels.functions; } + public get channelName() { + return ipcAppChannels.functions; + } private _iModelKeyToPullStatus = new Map(); diff --git a/core/backend/src/LineStyle.ts b/core/backend/src/LineStyle.ts index 6f604918a70a..e3c745c8dc60 100644 --- a/core/backend/src/LineStyle.ts +++ b/core/backend/src/LineStyle.ts @@ -22,7 +22,6 @@ import { IModelDb } from "./IModelDb"; * @public */ export namespace LineStyleDefinition { - /** Line style component type identifiers */ export enum ComponentType { /** Component type for [[LineStyleDefinition.PointSymbolProps]] */ @@ -301,7 +300,6 @@ export namespace LineStyleDefinition { /** Helper methods for creating and querying line styles */ export class Utils { - /** Create a file property for a new stroke pattern component. */ public static createStrokePatternComponent(iModel: IModelDb, props: StrokePatternProps): StyleProps { const fileProps: FilePropertyProps = { name: "LineCodeV1", namespace: "dgn_LStyle" }; @@ -398,7 +396,13 @@ export namespace LineStyleDefinition { if (width === undefined) { const name0 = "Continuous"; const lsId0 = this.queryStyle(imodel, scopeModelId, name0); - return (undefined === lsId0 ? this.createStyle(imodel, scopeModelId, name0, { compId: 0, compType: ComponentType.Internal, flags: StyleFlags.Continuous | StyleFlags.NoSnap }) : lsId0); + return (undefined === lsId0 + ? this.createStyle(imodel, scopeModelId, name0, { + compId: 0, + compType: ComponentType.Internal, + flags: StyleFlags.Continuous | StyleFlags.NoSnap, + }) + : lsId0); } const name = `Continuous-${width}`; @@ -406,11 +410,18 @@ export namespace LineStyleDefinition { if (undefined !== lsId) return lsId; - const strokePatternData = this.createStrokePatternComponent(imodel, { descr: name, strokes: [{ length: 1e37, orgWidth: width, strokeMode: StrokeMode.Dash, widthMode: StrokeWidth.Full }] }); + const strokePatternData = this.createStrokePatternComponent(imodel, { + descr: name, + strokes: [{ length: 1e37, orgWidth: width, strokeMode: StrokeMode.Dash, widthMode: StrokeWidth.Full }], + }); if (undefined === strokePatternData) throw new IModelError(IModelStatus.BadArg, "Unable to insert stroke component"); - return this.createStyle(imodel, scopeModelId, name, { compId: strokePatternData.compId, compType: strokePatternData.compType, flags: StyleFlags.Continuous | StyleFlags.NoSnap }); + return this.createStyle(imodel, scopeModelId, name, { + compId: strokePatternData.compId, + compType: strokePatternData.compType, + flags: StyleFlags.Continuous | StyleFlags.NoSnap, + }); } /** Query for a line style using the supplied [[LinePixels]] value (Code1-Code7) and create one if it does not already exist. diff --git a/core/backend/src/LocalHub.ts b/core/backend/src/LocalHub.ts index d3a6e57d4a51..b4d5a4d7f71d 100644 --- a/core/backend/src/LocalHub.ts +++ b/core/backend/src/LocalHub.ts @@ -3,12 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { join } from "path"; import { DbResult, GuidString, Id64String, IModelHubStatus, IModelStatus, OpenMode } from "@itwin/core-bentley"; import { - BriefcaseId, BriefcaseIdValue, ChangesetFileProps, ChangesetId, ChangesetIdWithIndex, ChangesetIndex, ChangesetIndexOrId, ChangesetProps, - ChangesetRange, IModelError, LocalDirName, LocalFileName, LockState, + BriefcaseId, + BriefcaseIdValue, + ChangesetFileProps, + ChangesetId, + ChangesetIdWithIndex, + ChangesetIndex, + ChangesetIndexOrId, + ChangesetProps, + ChangesetRange, + IModelError, + LocalDirName, + LocalFileName, + LockState, } from "@itwin/core-common"; +import { join } from "path"; import { LockConflict, LockMap, LockProps } from "./BackendHubAccess"; import { BriefcaseManager } from "./BriefcaseManager"; import { BriefcaseLocalValue, IModelDb, SnapshotDb } from "./IModelDb"; @@ -80,7 +91,9 @@ export class LocalHub { private _hubDb?: SQLiteDb; private _nextBriefcaseId = BriefcaseIdValue.FirstValid; private _latestChangesetIndex = 0; - public get latestChangesetIndex() { return this._latestChangesetIndex; } + public get latestChangesetIndex() { + return this._latestChangesetIndex; + } public constructor(public readonly rootDir: LocalDirName, arg: LocalHubProps) { this.iTwinId = arg.iTwinId; @@ -97,8 +110,10 @@ export class LocalHub { const db = this._hubDb = new SQLiteDb(); db.createDb(this.mockDbName); db.executeSQL("CREATE TABLE briefcases(id INTEGER PRIMARY KEY NOT NULL,user TEXT NOT NULL,alias TEXT NOT NULL,assigned INTEGER DEFAULT 1)"); - db.executeSQL("CREATE TABLE timeline(csIndex INTEGER PRIMARY KEY NOT NULL,csId TEXT NOT NULL UNIQUE,description TEXT,user TEXT,size BIGINT,type INTEGER,pushDate TEXT,briefcaseId INTEGER,\ - FOREIGN KEY(briefcaseId) REFERENCES briefcases(id))"); + db.executeSQL( + "CREATE TABLE timeline(csIndex INTEGER PRIMARY KEY NOT NULL,csId TEXT NOT NULL UNIQUE,description TEXT,user TEXT,size BIGINT,type INTEGER,pushDate TEXT,briefcaseId INTEGER,\ + FOREIGN KEY(briefcaseId) REFERENCES briefcases(id))", + ); db.executeSQL("CREATE TABLE checkpoints(csIndex INTEGER PRIMARY KEY NOT NULL)"); db.executeSQL("CREATE TABLE versions(name TEXT PRIMARY KEY NOT NULL,csIndex TEXT,FOREIGN KEY(csIndex) REFERENCES timeline(csIndex))"); db.executeSQL("CREATE TABLE locks(id INTEGER PRIMARY KEY NOT NULL,level INTEGER NOT NULL,lastCSetIndex INTEGER,briefcaseId INTEGER)"); @@ -135,10 +150,18 @@ export class LocalHub { } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - private get db(): SQLiteDb { return this._hubDb!; } // eslint-disable-line @typescript-eslint/naming-convention - public get changesetDir() { return join(this.rootDir, "changesets"); } - public get checkpointDir() { return join(this.rootDir, "checkpoints"); } - public get mockDbName() { return join(this.rootDir, "localHub.db"); } + private get db(): SQLiteDb { + return this._hubDb!; + } // eslint-disable-line @typescript-eslint/naming-convention + public get changesetDir() { + return join(this.rootDir, "changesets"); + } + public get checkpointDir() { + return join(this.rootDir, "checkpoints"); + } + public get mockDbName() { + return join(this.rootDir, "localHub.db"); + } /** Acquire the next available briefcaseId and assign it to the supplied user */ public acquireNewBriefcaseId(user: string, alias?: string): BriefcaseId { @@ -298,24 +321,27 @@ export class LocalHub { if (index <= 0) return { id: "", changesType: 0, description: "version0", parentId: "", briefcaseId: 0, pushDate: "", userCreated: "", index: 0, size: 0 }; - return this.db.withPreparedSqliteStatement("SELECT description,size,type,pushDate,user,csId,briefcaseId FROM timeline WHERE csIndex=?", (stmt) => { - stmt.bindInteger(1, index); - const rc = stmt.step(); - if (DbResult.BE_SQLITE_ROW !== rc) - throw new IModelError(rc, `changeset at index ${index} not found`); - - return { - description: stmt.getValueString(0), - size: stmt.getValueDouble(1), - changesType: stmt.getValueInteger(2), - pushDate: stmt.getValueString(3), - userCreated: stmt.getValueString(4), - id: stmt.getValueString(5), - briefcaseId: stmt.getValueInteger(6), - index, - parentId: this.getParentId(index), - }; - }); + return this.db.withPreparedSqliteStatement( + "SELECT description,size,type,pushDate,user,csId,briefcaseId FROM timeline WHERE csIndex=?", + (stmt) => { + stmt.bindInteger(1, index); + const rc = stmt.step(); + if (DbResult.BE_SQLITE_ROW !== rc) + throw new IModelError(rc, `changeset at index ${index} not found`); + + return { + description: stmt.getValueString(0), + size: stmt.getValueDouble(1), + changesType: stmt.getValueInteger(2), + pushDate: stmt.getValueString(3), + userCreated: stmt.getValueString(4), + id: stmt.getValueString(5), + briefcaseId: stmt.getValueInteger(6), + index, + parentId: this.getParentId(index), + }; + }, + ); } public getLatestChangeset(): ChangesetProps { @@ -408,7 +434,6 @@ export class LocalHub { stmt.bindInteger(2, last); while (DbResult.BE_SQLITE_ROW === stmt.step()) checkpoints.push(stmt.getValueInteger(0)); - }); return checkpoints; } @@ -516,14 +541,17 @@ export class LocalHub { if (wantShared && (currStatus.state === LockState.Exclusive)) throw new Error("cannot acquire shared lock because an exclusive lock is already held"); - this.db.withPreparedSqliteStatement("INSERT INTO locks(id,level,briefcaseId) VALUES(?,?,?) ON CONFLICT(id) DO UPDATE SET briefcaseId=excluded.briefcaseId,level=excluded.level", (stmt) => { - stmt.bindId(1, props.id); - stmt.bindInteger(2, props.state); - stmt.bindValue(3, wantShared ? undefined : briefcase.briefcaseId); - const rc = stmt.step(); - if (rc !== DbResult.BE_SQLITE_DONE) - throw new IModelError(rc, "cannot insert lock"); - }); + this.db.withPreparedSqliteStatement( + "INSERT INTO locks(id,level,briefcaseId) VALUES(?,?,?) ON CONFLICT(id) DO UPDATE SET briefcaseId=excluded.briefcaseId,level=excluded.level", + (stmt) => { + stmt.bindId(1, props.id); + stmt.bindInteger(2, props.state); + stmt.bindValue(3, wantShared ? undefined : briefcase.briefcaseId); + const rc = stmt.step(); + if (rc !== DbResult.BE_SQLITE_DONE) + throw new IModelError(rc, "cannot insert lock"); + }, + ); if (wantShared) { this.db.withPreparedSqliteStatement("INSERT INTO sharedLocks(lockId,briefcaseId) VALUES(?,?)", (stmt) => { @@ -660,9 +688,13 @@ export class LocalHub { } // for debugging - public countSharedLocks(): number { return this.countTable("sharedLocks"); } + public countSharedLocks(): number { + return this.countTable("sharedLocks"); + } // for debugging - public countLocks(): number { return this.countTable("locks"); } + public countLocks(): number { + return this.countTable("locks"); + } // for debugging public queryAllSharedLocks(): { id: Id64String, briefcaseId: BriefcaseId }[] { @@ -694,7 +726,6 @@ export class LocalHub { IModelJsFs.purgeDirSync(dirName); IModelJsFs.rmdirSync(dirName); } - } public cleanup() { if (this._hubDb) { @@ -706,7 +737,9 @@ export class LocalHub { this.removeDir(this.rootDir); } catch (err) { // eslint-disable-next-line no-console - console.log(`ERROR: test left an iModel open for [${this.iModelName}]. LocalMock cannot clean up - make sure you call imodel.close() in your test`); + console.log( + `ERROR: test left an iModel open for [${this.iModelName}]. LocalMock cannot clean up - make sure you call imodel.close() in your test`, + ); } } } diff --git a/core/backend/src/LocalhostIpcHost.ts b/core/backend/src/LocalhostIpcHost.ts index 75902f4f6e03..f68e71292890 100644 --- a/core/backend/src/LocalhostIpcHost.ts +++ b/core/backend/src/LocalhostIpcHost.ts @@ -6,10 +6,16 @@ * @module IModelHost */ -import * as ws from "ws"; import { - InterceptedRpcRequest, IpcWebSocket, IpcWebSocketBackend, IpcWebSocketMessage, IpcWebSocketTransport, rpcOverIpcStrings, RpcSessionInvocation, + InterceptedRpcRequest, + IpcWebSocket, + IpcWebSocketBackend, + IpcWebSocketMessage, + IpcWebSocketTransport, + rpcOverIpcStrings, + RpcSessionInvocation, } from "@itwin/core-common"; +import * as ws from "ws"; import { IModelHostOptions } from "./IModelHost"; import { IpcHandler, IpcHost } from "./IpcHost"; diff --git a/core/backend/src/Material.ts b/core/backend/src/Material.ts index 27b5cd39b2bc..b8971942993f 100644 --- a/core/backend/src/Material.ts +++ b/core/backend/src/Material.ts @@ -8,7 +8,17 @@ import { Id64, Id64String } from "@itwin/core-bentley"; import { - BisCodeSpec, Code, CodeScopeProps, CodeSpec, DefinitionElementProps, ElementProps, NormalMapProps, RenderMaterialAssetMapsProps, RenderMaterialProps, RgbFactorProps, TextureMapProps, + BisCodeSpec, + Code, + CodeScopeProps, + CodeSpec, + DefinitionElementProps, + ElementProps, + NormalMapProps, + RenderMaterialAssetMapsProps, + RenderMaterialProps, + RgbFactorProps, + TextureMapProps, } from "@itwin/core-common"; import { DefinitionElement } from "./Element"; import { IModelDb } from "./IModelDb"; @@ -21,7 +31,9 @@ import { IModelElementCloneContext } from "./IModelElementCloneContext"; * @public */ export abstract class PhysicalMaterial extends DefinitionElement { - public static override get className(): string { return "PhysicalMaterial"; } + public static override get className(): string { + return "PhysicalMaterial"; + } /** Create a Code for a PhysicalMaterial given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb * @param definitionModelId The Id of the DefinitionModel that will contain the PhysicalMaterial and provide the scope for its name. @@ -53,7 +65,9 @@ export abstract class PhysicalMaterial extends DefinitionElement { * @public */ export class RenderMaterialElement extends DefinitionElement { - public static override get className(): string { return "RenderMaterial"; } + public static override get className(): string { + return "RenderMaterial"; + } /** The name of a palette that can be used to categorize multiple materials. */ public paletteName: string; @@ -90,7 +104,12 @@ export class RenderMaterialElement extends DefinitionElement { * @returns The newly constructed RenderMaterial element. * @throws [[IModelError]] if unable to create the element. */ - public static create(iModelDb: IModelDb, definitionModelId: Id64String, materialName: string, params: RenderMaterialElementParams): RenderMaterialElement { + public static create( + iModelDb: IModelDb, + definitionModelId: Id64String, + materialName: string, + params: RenderMaterialElementParams, + ): RenderMaterialElement { let maps: RenderMaterialAssetMapsProps | undefined; const pbr_normal = params.normalMap?.scale; if (params.patternMap || params.normalMap) { @@ -198,7 +217,9 @@ export class RenderMaterialElement extends DefinitionElement { } if (!Id64.isValid(sourceMap.TextureId) || sourceMap.TextureId === undefined) continue; - targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName].TextureId = context.findTargetElementId(sourceMap.TextureId ?? Id64.invalid); + targetProps.jsonProperties.materialAssets.renderMaterial.Map[mapName].TextureId = context.findTargetElementId( + sourceMap.TextureId ?? Id64.invalid, + ); } } } diff --git a/core/backend/src/Model.ts b/core/backend/src/Model.ts index 690d2d279815..9a46e9847370 100644 --- a/core/backend/src/Model.ts +++ b/core/backend/src/Model.ts @@ -9,16 +9,31 @@ // cspell:ignore elid import { GuidString, Id64String, JsonUtils } from "@itwin/core-bentley"; -import { Point2d, Range3d } from "@itwin/core-geometry"; import { - AxisAlignedBox3d, ElementProps, EntityReferenceSet, GeometricModel2dProps, GeometricModel3dProps, GeometricModelProps, IModel, - InformationPartitionElementProps, ModelProps, RelatedElement, + AxisAlignedBox3d, + ElementProps, + EntityReferenceSet, + GeometricModel2dProps, + GeometricModel3dProps, + GeometricModelProps, + IModel, + InformationPartitionElementProps, + ModelProps, + RelatedElement, } from "@itwin/core-common"; -import { DefinitionPartition, DocumentPartition, InformationRecordPartition, PhysicalPartition, SheetIndexPartition, SpatialLocationPartition } from "./Element"; +import { Point2d, Range3d } from "@itwin/core-geometry"; +import { + DefinitionPartition, + DocumentPartition, + InformationRecordPartition, + PhysicalPartition, + SheetIndexPartition, + SpatialLocationPartition, +} from "./Element"; import { Entity } from "./Entity"; import { IModelDb } from "./IModelDb"; -import { SubjectOwnsPartitionElements } from "./NavigationRelationship"; import { _nativeDb, _verifyChannel } from "./internal/Symbols"; +import { SubjectOwnsPartitionElements } from "./NavigationRelationship"; /** Argument for the `Model.onXxx` static methods * @beta @@ -66,9 +81,13 @@ export interface OnElementInModelIdArg extends OnModelIdArg { * @public */ export class Model extends Entity { - public static override get className(): string { return "Model"; } + public static override get className(): string { + return "Model"; + } /** @internal */ - public static override get protectedOperations() { return ["onInsert", "onUpdate", "onDelete"]; } + public static override get protectedOperations() { + return ["onInsert", "onUpdate", "onDelete"]; + } public readonly modeledElement!: RelatedElement; public readonly name: string; public readonly parentModel!: Id64String; @@ -99,7 +118,7 @@ export class Model extends Entity { protected static onInsert(arg: OnModelPropsArg): void { const { props, iModel } = arg; iModel.channels[_verifyChannel](props.modeledElement.id); - if (props.parentModel) // inserting requires shared lock on parent, if present + if (props.parentModel) // inserting requires shared lock on parent, if present iModel.locks.checkSharedLock(props.parentModel, "parent model", "insert"); } @@ -148,7 +167,7 @@ export class Model extends Entity { * @note `this` is the class of the Model that was deleted * @beta */ - protected static onDeleted(_arg: OnModelIdArg): void { } + protected static onDeleted(_arg: OnModelIdArg): void {} /** Called before a prospective Element is to be inserted into an instance of a Model of this class. * @note throw an exception to disallow the insert @@ -156,14 +175,14 @@ export class Model extends Entity { * @note `this` is the class of the Model to hold the element * @beta */ - protected static onInsertElement(_arg: OnElementInModelPropsArg): void { } + protected static onInsertElement(_arg: OnElementInModelPropsArg): void {} /** Called after an Element has been inserted into an instance of a Model of this class. * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ - protected static onInsertedElement(_arg: OnElementInModelIdArg): void { } + protected static onInsertedElement(_arg: OnElementInModelIdArg): void {} /** Called when an Element in an instance of a Model of this class is about to be updated. * @note throw an exception to disallow the update @@ -171,14 +190,14 @@ export class Model extends Entity { * @note `this` is the class of the Model holding the element * @beta */ - protected static onUpdateElement(_arg: OnElementInModelPropsArg): void { } + protected static onUpdateElement(_arg: OnElementInModelPropsArg): void {} /** Called after an Element in an instance of a Model of this class has been updated. * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ - protected static onUpdatedElement(_arg: OnElementInModelIdArg): void { } + protected static onUpdatedElement(_arg: OnElementInModelIdArg): void {} /** Called when an Element in an instance of a Model of this class is about to be deleted. * @note throw an exception to disallow the delete @@ -186,14 +205,14 @@ export class Model extends Entity { * @note `this` is the class of the Model holding the element * @beta */ - protected static onDeleteElement(_arg: OnElementInModelIdArg): void { } + protected static onDeleteElement(_arg: OnElementInModelIdArg): void {} /** Called after an Element in an instance of a Model of this class has been deleted. * @note If you override this method, you must call super. * @note `this` is the class of the Model that held the element * @beta */ - protected static onDeletedElement(_arg: OnElementInModelIdArg): void { } + protected static onDeletedElement(_arg: OnElementInModelIdArg): void {} private getAllUserProperties(): any { if (!this.jsonProperties.UserProps) @@ -203,23 +222,39 @@ export class Model extends Entity { } /** Get a set of JSON user properties by namespace */ - public getUserProperties(namespace: string) { return this.getAllUserProperties()[namespace]; } + public getUserProperties(namespace: string) { + return this.getAllUserProperties()[namespace]; + } /** Change a set of user JSON properties of this Element by namespace. */ - public setUserProperties(nameSpace: string, value: any) { this.getAllUserProperties()[nameSpace] = value; } + public setUserProperties(nameSpace: string, value: any) { + this.getAllUserProperties()[nameSpace] = value; + } /** Remove a set of JSON user properties, specified by namespace, from this Element */ - public removeUserProperties(nameSpace: string) { delete this.getAllUserProperties()[nameSpace]; } + public removeUserProperties(nameSpace: string) { + delete this.getAllUserProperties()[nameSpace]; + } - public getJsonProperty(name: string): any { return this.jsonProperties[name]; } - public setJsonProperty(name: string, value: any) { this.jsonProperties[name] = value; } + public getJsonProperty(name: string): any { + return this.jsonProperties[name]; + } + public setJsonProperty(name: string, value: any) { + this.jsonProperties[name] = value; + } /** Insert this Model in the iModel */ - public insert() { return this.id = this.iModel.models.insertModel(this.toJSON()); } + public insert() { + return this.id = this.iModel.models.insertModel(this.toJSON()); + } /** Update this Model in the iModel. */ - public update() { this.iModel.models.updateModel(this.toJSON()); } + public update() { + this.iModel.models.updateModel(this.toJSON()); + } /** Delete this Model from the iModel. */ - public delete() { this.iModel.models.deleteModel(this.id); } + public delete() { + this.iModel.models.deleteModel(this.id); + } protected override collectReferenceIds(referenceIds: EntityReferenceSet): void { super.collectReferenceIds(referenceIds); @@ -235,9 +270,13 @@ export class Model extends Entity { export class GeometricModel extends Model { public geometryGuid?: GuidString; // Initialized by the Entity constructor - public static override get className(): string { return "GeometricModel"; } + public static override get className(): string { + return "GeometricModel"; + } - protected constructor(props: GeometricModelProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: GeometricModelProps, iModel: IModelDb) { + super(props, iModel); + } /** Query for the union of the extents of the elements contained by this model. * @note This function blocks the JavaScript event loop. Consider using [[queryRange]] instead. @@ -266,9 +305,13 @@ export abstract class GeometricModel3d extends GeometricModel { */ public readonly isNotSpatiallyLocated: boolean; /** If true, then the elements in this GeometricModel3d are in real-world coordinates and will be in the spatial index. */ - public get isSpatiallyLocated(): boolean { return !this.isNotSpatiallyLocated; } + public get isSpatiallyLocated(): boolean { + return !this.isNotSpatiallyLocated; + } - public static override get className(): string { return "GeometricModel3d"; } + public static override get className(): string { + return "GeometricModel3d"; + } protected constructor(props: GeometricModel3dProps, iModel: IModelDb) { super(props, iModel); @@ -294,9 +337,13 @@ export abstract class GeometricModel3d extends GeometricModel { export abstract class GeometricModel2d extends GeometricModel { /** The actual coordinates of (0,0) in modeling coordinates. An offset applied to all modeling coordinates. */ public globalOrigin?: Point2d; // Initialized by the Entity constructor - public static override get className(): string { return "GeometricModel2d"; } + public static override get className(): string { + return "GeometricModel2d"; + } - protected constructor(props: GeometricModel2dProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: GeometricModel2dProps, iModel: IModelDb) { + super(props, iModel); + } public override toJSON(): GeometricModel2dProps { const val = super.toJSON() as GeometricModel2dProps; @@ -311,7 +358,9 @@ export abstract class GeometricModel2d extends GeometricModel { * @public */ export abstract class GraphicalModel2d extends GeometricModel2d { - public static override get className(): string { return "GraphicalModel2d"; } + public static override get className(): string { + return "GraphicalModel2d"; + } } /** A container for persisting GraphicalElement3d instances. @@ -320,14 +369,18 @@ export abstract class GraphicalModel2d extends GeometricModel2d { * @public */ export abstract class GraphicalModel3d extends GeometricModel3d { - public static override get className(): string { return "GraphicalModel3d"; } + public static override get className(): string { + return "GraphicalModel3d"; + } } /** A container for persisting 3d geometric elements that are spatially located. * @public */ export abstract class SpatialModel extends GeometricModel3d { - public static override get className(): string { return "SpatialModel"; } + public static override get className(): string { + return "SpatialModel"; + } } /** A container for persisting physical elements that model physical space. @@ -335,7 +388,9 @@ export abstract class SpatialModel extends GeometricModel3d { * @public */ export class PhysicalModel extends SpatialModel { - public static override get className(): string { return "PhysicalModel"; } + public static override get className(): string { + return "PhysicalModel"; + } /** Insert a PhysicalPartition and a PhysicalModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The PhysicalPartition will be inserted as a child of this Subject element. @@ -366,7 +421,9 @@ export class PhysicalModel extends SpatialModel { * @public */ export class SpatialLocationModel extends SpatialModel { - public static override get className(): string { return "SpatialLocationModel"; } + public static override get className(): string { + return "SpatialLocationModel"; + } /** Insert a SpatialLocationPartition and a SpatialLocationModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The SpatialLocationPartition will be inserted as a child of this Subject element. @@ -396,14 +453,18 @@ export class SpatialLocationModel extends SpatialModel { * @public */ export class DrawingModel extends GraphicalModel2d { - public static override get className(): string { return "DrawingModel"; } + public static override get className(): string { + return "DrawingModel"; + } } /** A container for persisting section [[DrawingGraphic]]s. * @public */ export class SectionDrawingModel extends DrawingModel { - public static override get className(): string { return "SectionDrawingModel"; } + public static override get className(): string { + return "SectionDrawingModel"; + } } /** A container for persisting [[ViewAttachment]]s and [[DrawingGraphic]]s. @@ -412,21 +473,27 @@ export class SectionDrawingModel extends DrawingModel { * @public */ export class SheetModel extends GraphicalModel2d { - public static override get className(): string { return "SheetModel"; } + public static override get className(): string { + return "SheetModel"; + } } /** A container for persisting role elements. * @public */ export class RoleModel extends Model { - public static override get className(): string { return "RoleModel"; } + public static override get className(): string { + return "RoleModel"; + } } /** A container for persisting information elements. * @public */ export abstract class InformationModel extends Model { - public static override get className(): string { return "InformationModel"; } + public static override get className(): string { + return "InformationModel"; + } } /** A container for persisting group information elements. @@ -434,22 +501,26 @@ export abstract class InformationModel extends Model { * @public */ export abstract class GroupInformationModel extends InformationModel { - public static override get className(): string { return "GroupInformationModel"; } + public static override get className(): string { + return "GroupInformationModel"; + } } /** A sub-model of a [[SheetIndexPartition]] serving as a container for persisting [[SheetIndexEntry]] and [[SheetIndex]] elements. * @beta */ export class SheetIndexModel extends InformationModel { - public static override get className(): string { return "SheetIndexModel"; } + public static override get className(): string { + return "SheetIndexModel"; + } /** Insert a SheetIndex and a SheetIndexModel that sub-models it. - * @param iModelDb Insert into this iModel - * @param parentSubjectId The SheetIndex will be inserted as a child of this Subject element. - * @param name The name of the SheetIndex that the new SheetIndexModel will sub-model. - * @returns The Id of the newly inserted SheetIndexModel. - * @throws [[IModelError]] if there is an insert problem. - */ + * @param iModelDb Insert into this iModel + * @param parentSubjectId The SheetIndex will be inserted as a child of this Subject element. + * @param name The name of the SheetIndex that the new SheetIndexModel will sub-model. + * @returns The Id of the newly inserted SheetIndexModel. + * @throws [[IModelError]] if there is an insert problem. + */ public static insert(iModelDb: IModelDb, parentSubjectId: Id64String, name: string): Id64String { const sheetIndex: InformationPartitionElementProps = { classFullName: SheetIndexPartition.classFullName, @@ -470,7 +541,9 @@ export class SheetIndexModel extends InformationModel { * @public */ export class InformationRecordModel extends InformationModel { - public static override get className(): string { return "InformationRecordModel"; } + public static override get className(): string { + return "InformationRecordModel"; + } /** Insert a InformationRecordPartition and a InformationRecordModel that sub-models it. * @param iModelDb Insert into this iModel @@ -499,7 +572,9 @@ export class InformationRecordModel extends InformationModel { * @public */ export class DefinitionModel extends InformationModel { - public static override get className(): string { return "DefinitionModel"; } + public static override get className(): string { + return "DefinitionModel"; + } /** Insert a DefinitionPartition and a DefinitionModel that sub-models it. * @param iModelDb Insert into this iModel @@ -527,7 +602,9 @@ export class DefinitionModel extends InformationModel { * @public */ export class RepositoryModel extends DefinitionModel { - public static override get className(): string { return "RepositoryModel"; } + public static override get className(): string { + return "RepositoryModel"; + } } /** Contains a list of document elements. @@ -535,7 +612,9 @@ export class RepositoryModel extends DefinitionModel { * @public */ export class DocumentListModel extends InformationModel { - public static override get className(): string { return "DocumentListModel"; } + public static override get className(): string { + return "DocumentListModel"; + } /** Insert a DocumentPartition and a DocumentListModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The DocumentPartition will be inserted as a child of this Subject element. @@ -563,19 +642,25 @@ export class DocumentListModel extends InformationModel { * @public */ export class LinkModel extends InformationModel { - public static override get className(): string { return "LinkModel"; } + public static override get className(): string { + return "LinkModel"; + } } /** The singleton container for repository-specific definition elements. * @public */ export class DictionaryModel extends DefinitionModel { - public static override get className(): string { return "DictionaryModel"; } + public static override get className(): string { + return "DictionaryModel"; + } } /** Obtains and displays multi-resolution tiled raster organized according to the WebMercator tiling system. * @public */ export class WebMercatorModel extends SpatialModel { - public static override get className(): string { return "WebMercatorModel"; } + public static override get className(): string { + return "WebMercatorModel"; + } } diff --git a/core/backend/src/NativeAppStorage.ts b/core/backend/src/NativeAppStorage.ts index b63acde38a96..158574384c9d 100644 --- a/core/backend/src/NativeAppStorage.ts +++ b/core/backend/src/NativeAppStorage.ts @@ -6,9 +6,9 @@ * @module NativeApp */ -import { join, relative } from "node:path"; import { DbResult, IModelStatus } from "@itwin/core-bentley"; import { IModelError, StorageValue } from "@itwin/core-common"; +import { join, relative } from "node:path"; import { ECDb, ECDbOpenMode } from "./ECDb"; import { IModelHost } from "./IModelHost"; import { IModelJsFs } from "./IModelJsFs"; @@ -24,31 +24,34 @@ export class NativeAppStorage { private static readonly _ext = ".settings-db"; private static _storages = new Map(); private static _init: boolean = false; - private constructor(private _ecdb: ECDb, public readonly id: string) { } + private constructor(private _ecdb: ECDb, public readonly id: string) {} /** Set the value for a key */ public setData(key: string, value: StorageValue): void { - const rc = this._ecdb.withPreparedSqliteStatement("INSERT INTO app_setting(key,type,val)VALUES(?,?,?) ON CONFLICT(key) DO UPDATE SET type=excluded.type,val=excluded.val", (stmt) => { - let valType = (value === undefined || value === null) ? "null" : typeof value; - if (valType === "object" && (value instanceof Uint8Array)) - valType = "Uint8Array"; - - switch (valType) { - case "null": - case "number": - case "string": - case "boolean": - case "Uint8Array": - break; - default: - throw new IModelError(DbResult.BE_SQLITE_ERROR, `Unsupported type ${valType} for value for key='${key}`); - } - - stmt.bindValue(1, key); - stmt.bindValue(2, valType); - stmt.bindValue(3, value); - return stmt.step(); - }); + const rc = this._ecdb.withPreparedSqliteStatement( + "INSERT INTO app_setting(key,type,val)VALUES(?,?,?) ON CONFLICT(key) DO UPDATE SET type=excluded.type,val=excluded.val", + (stmt) => { + let valType = (value === undefined || value === null) ? "null" : typeof value; + if (valType === "object" && (value instanceof Uint8Array)) + valType = "Uint8Array"; + + switch (valType) { + case "null": + case "number": + case "string": + case "boolean": + case "Uint8Array": + break; + default: + throw new IModelError(DbResult.BE_SQLITE_ERROR, `Unsupported type ${valType} for value for key='${key}`); + } + + stmt.bindValue(1, key); + stmt.bindValue(2, valType); + stmt.bindValue(3, value); + return stmt.step(); + }, + ); if (rc !== DbResult.BE_SQLITE_DONE) throw new IModelError(rc, "SQLite error"); diff --git a/core/backend/src/NativeHost.ts b/core/backend/src/NativeHost.ts index 43b939a9514e..17b7202a1397 100644 --- a/core/backend/src/NativeHost.ts +++ b/core/backend/src/NativeHost.ts @@ -6,12 +6,19 @@ * @module NativeApp */ -import { join } from "path"; import { AccessToken, assert, BeEvent, GuidString } from "@itwin/core-bentley"; import { - BriefcaseProps, InternetConnectivityStatus, LocalBriefcaseProps, NativeAppFunctions, nativeAppIpcStrings, NativeAppNotifications, - OverriddenBy, RequestNewBriefcaseProps, StorageValue, + BriefcaseProps, + InternetConnectivityStatus, + LocalBriefcaseProps, + NativeAppFunctions, + nativeAppIpcStrings, + NativeAppNotifications, + OverriddenBy, + RequestNewBriefcaseProps, + StorageValue, } from "@itwin/core-common"; +import { join } from "path"; import { BriefcaseManager, RequestNewBriefcaseArg } from "./BriefcaseManager"; import { Downloads, ProgressFunction, ProgressStatus } from "./CheckpointManager"; import { IModelHost } from "./IModelHost"; @@ -22,7 +29,9 @@ import { NativeAppStorage } from "./NativeAppStorage"; * Implementation of NativeAppFunctions */ class NativeAppHandler extends IpcHandler implements NativeAppFunctions { - public get channelName() { return nativeAppIpcStrings.channelName; } + public get channelName() { + return nativeAppIpcStrings.channelName; + } public async getAccessToken(): Promise { return IModelHost.authorizationClient?.getAccessToken(); @@ -40,7 +49,11 @@ class NativeAppHandler extends IpcHandler implements NativeAppFunctions { public async getBriefcaseFileName(props: BriefcaseProps): Promise { return BriefcaseManager.getFileName(props); } - public async downloadBriefcase(request: RequestNewBriefcaseProps, reportProgress: boolean, progressInterval?: number): Promise { + public async downloadBriefcase( + request: RequestNewBriefcaseProps, + reportProgress: boolean, + progressInterval?: number, + ): Promise { const args: RequestNewBriefcaseArg = { ...request, accessToken: await this.getAccessToken(), @@ -133,7 +146,7 @@ export interface NativeHostOpts extends IpcHostOpts { export class NativeHost { private static _reachability?: InternetConnectivityStatus; private static _applicationName: string; - private constructor() { } // no instances - static methods only + private constructor() {} // no instances - static methods only /** Event called when the internet connectivity changes, if known. */ public static readonly onInternetConnectivityChanged = new BeEvent<(status: InternetConnectivityStatus) => void>(); @@ -151,8 +164,12 @@ export class NativeHost { } private static _isValid = false; - public static get isValid(): boolean { return this._isValid; } - public static get applicationName() { return this._applicationName; } + public static get isValid(): boolean { + return this._isValid; + } + public static get applicationName() { + return this._applicationName; + } /** Get the settings store for this NativeHost. */ public static get settingsStore() { return NativeAppStorage.open(this.applicationName); @@ -166,12 +183,13 @@ export class NativeHost { if (!this.isValid) { this._isValid = true; this.onInternetConnectivityChanged.addListener((status: InternetConnectivityStatus) => - NativeHost.notifyNativeFrontend("notifyInternetConnectivityChanged", status)); + NativeHost.notifyNativeFrontend("notifyInternetConnectivityChanged", status) + ); this._applicationName = opt?.nativeHost?.applicationName ?? "iTwinApp"; } await IpcHost.startup(opt); - if (IpcHost.isValid) // for tests, we use NativeHost but don't have a frontend + if (IpcHost.isValid) // for tests, we use NativeHost but don't have a frontend NativeAppHandler.register(); } diff --git a/core/backend/src/NavigationRelationship.ts b/core/backend/src/NavigationRelationship.ts index e2468b0a0c1b..78e939bd0ce9 100644 --- a/core/backend/src/NavigationRelationship.ts +++ b/core/backend/src/NavigationRelationship.ts @@ -110,7 +110,7 @@ export class FolderContainsRepositories extends ElementOwnsChildElements { export class SheetIndexFolderOwnsEntries extends ElementOwnsChildElements { public static override classFullName = "BisCore:SheetIndexFolderOwnsEntries"; public constructor(parentId: Id64String, relClassName: string = SheetIndexFolderOwnsEntries.classFullName) { - super(parentId, relClassName ); + super(parentId, relClassName); } } @@ -120,7 +120,7 @@ export class SheetIndexFolderOwnsEntries extends ElementOwnsChildElements { export class SheetIndexOwnsEntries extends ElementOwnsChildElements { public static override classFullName = "BisCore:SheetIndexOwnsEntries"; public constructor(parentId: Id64String, relClassName: string = SheetIndexOwnsEntries.classFullName) { - super(parentId, relClassName ); + super(parentId, relClassName); } } diff --git a/core/backend/src/PromiseMemoizer.ts b/core/backend/src/PromiseMemoizer.ts index 673982baeaee..4fd258b75e28 100644 --- a/core/backend/src/PromiseMemoizer.ts +++ b/core/backend/src/PromiseMemoizer.ts @@ -15,9 +15,15 @@ export class QueryablePromise { private _fulfilled: boolean = false; private _rejected: boolean = false; - public get isPending(): boolean { return !this.isFulfilled && !this.isRejected; } - public get isFulfilled(): boolean { return this._fulfilled; } - public get isRejected(): boolean { return this._rejected; } + public get isPending(): boolean { + return !this.isFulfilled && !this.isRejected; + } + public get isFulfilled(): boolean { + return this._fulfilled; + } + public get isRejected(): boolean { + return this._rejected; + } public constructor(public readonly promise: Promise) { this.promise.then((res: T) => { this.result = res; diff --git a/core/backend/src/PropertyStore.ts b/core/backend/src/PropertyStore.ts index f45852602f55..b1bdc3c84193 100644 --- a/core/backend/src/PropertyStore.ts +++ b/core/backend/src/PropertyStore.ts @@ -14,7 +14,6 @@ import { SettingsContainer } from "./workspace/Settings"; /** @beta */ export namespace PropertyStore { - /** The set of valid types for properties in a PropertyStore. */ export type PropertyType = string | number | boolean | Uint8Array | SettingsContainer; /** The case-sensitive name of a Property. May not have leading or trailing spaces, and must be between 3 and 2048 characters long. */ @@ -72,60 +71,60 @@ export namespace PropertyStore { }); } /** Get the value of a string property by name. - * @returns the property's value if it exists and is a string, `undefined` otherwise. - */ + * @returns the property's value if it exists and is a string, `undefined` otherwise. + */ public getString(name: PropertyName, defaultValue: string): string; /** Get the value of a string property by name. - * @returns the property's value if it exists and is a string, otherwise the supplied default value. - */ + * @returns the property's value if it exists and is a string, otherwise the supplied default value. + */ public getString(name: PropertyName): string | undefined; public getString(name: PropertyName, defaultValue?: string): string | undefined { const out = this.getProperty(name); return typeof out === "string" ? out : defaultValue; } /** Get the value of a boolean property by name. - * @returns the property's value if it exists and is a boolean, `undefined` otherwise. - */ + * @returns the property's value if it exists and is a boolean, `undefined` otherwise. + */ public getBoolean(name: PropertyName): boolean | undefined; /** Get the value of a boolean property by name. - * @returns the property's value if it exists and is a boolean, otherwise the supplied default value. - */ + * @returns the property's value if it exists and is a boolean, otherwise the supplied default value. + */ public getBoolean(name: PropertyName, defaultValue: boolean): boolean; public getBoolean(name: PropertyName, defaultValue?: boolean): boolean | undefined { const out = this.getProperty(name); return typeof out === "boolean" ? out : defaultValue; } /** Get the value of a number property by name. - * @returns the property's value if it exists and is a number, `undefined` otherwise. - */ + * @returns the property's value if it exists and is a number, `undefined` otherwise. + */ public getNumber(name: PropertyName): number | undefined; /** Get the value of a number property by name. - * @returns the property's value if it exists and is a number, otherwise the supplied default value. - */ + * @returns the property's value if it exists and is a number, otherwise the supplied default value. + */ public getNumber(name: PropertyName, defaultValue: number): number; public getNumber(name: PropertyName, defaultValue?: number): number | undefined { const out = this.getProperty(name); return typeof out === "number" ? out : defaultValue; } /** Get the value of a blob property by name. - * @returns the property's value if it exists and is a blob, `undefined` otherwise. - */ + * @returns the property's value if it exists and is a blob, `undefined` otherwise. + */ public getBlob(name: PropertyName): Uint8Array | undefined; /** Get the value of a blob property by name. - * @returns the property's value if it exists and is a blob, otherwise the supplied default value. - */ + * @returns the property's value if it exists and is a blob, otherwise the supplied default value. + */ public getBlob(name: PropertyName, defaultValue: Uint8Array): Uint8Array; public getBlob(name: PropertyName, defaultValue?: Uint8Array): Uint8Array | undefined { const out = this.getProperty(name); return out instanceof Uint8Array ? out : defaultValue; } /** Get the value of an object property by name. - * @returns the property's value if it exists and is an object, `undefined` otherwise. - */ + * @returns the property's value if it exists and is an object, `undefined` otherwise. + */ public getObject(name: PropertyName): SettingsContainer | undefined; /** Get the value of an object property by name. - * @returns the property's value if it exists and is an object, otherwise the supplied default value. - */ + * @returns the property's value if it exists and is an object, otherwise the supplied default value. + */ public getObject(name: PropertyName, defaultValue: SettingsContainer): SettingsContainer; public getObject(name: PropertyName, defaultValue?: SettingsContainer): SettingsContainer | undefined { const out = this.getProperty(name); diff --git a/core/backend/src/Relationship.ts b/core/backend/src/Relationship.ts index c62f590eed2e..f960d4b78aed 100644 --- a/core/backend/src/Relationship.ts +++ b/core/backend/src/Relationship.ts @@ -13,13 +13,15 @@ import { Entity } from "./Entity"; import { IModelDb } from "./IModelDb"; import { _nativeDb } from "./internal/Symbols"; -export type { SourceAndTarget, RelationshipProps } from "@itwin/core-common"; // for backwards compatibility +export type { RelationshipProps, SourceAndTarget } from "@itwin/core-common"; // for backwards compatibility /** Base class for all link table ECRelationships * @public */ export class Relationship extends Entity { - public static override get className(): string { return "Relationship"; } + public static override get className(): string { + return "Relationship"; + } public readonly sourceId: Id64String; public readonly targetId: Id64String; @@ -43,7 +45,7 @@ export class Relationship extends Entity { * @param _props The ElementDrivesElement relationship instance. * @param _iModel The iModel */ - public static onRootChanged(_props: RelationshipProps, _iModel: IModelDb): void { } + public static onRootChanged(_props: RelationshipProps, _iModel: IModelDb): void {} /** * Callback invoked by saveChanges on an ElementDrivesElement relationship when the relationship instance has been deleted. @@ -51,23 +53,33 @@ export class Relationship extends Entity { * @param _props The deleted ElementDrivesElement relationship instance. * @param _iModel The iModel */ - public static onDeletedDependency(_props: RelationshipProps, _iModel: IModelDb): void { } + public static onDeletedDependency(_props: RelationshipProps, _iModel: IModelDb): void {} /** Insert this Relationship into the iModel. */ - public insert(): Id64String { return this.id = this.iModel.relationships.insertInstance(this.toJSON()); } + public insert(): Id64String { + return this.id = this.iModel.relationships.insertInstance(this.toJSON()); + } /** Update this Relationship in the iModel. */ - public update() { this.iModel.relationships.updateInstance(this.toJSON()); } + public update() { + this.iModel.relationships.updateInstance(this.toJSON()); + } /** Delete this Relationship from the iModel. */ - public delete() { this.iModel.relationships.deleteInstance(this.toJSON()); } + public delete() { + this.iModel.relationships.deleteInstance(this.toJSON()); + } - public static getInstance(iModel: IModelDb, criteria: Id64String | SourceAndTarget): T { return iModel.relationships.getInstance(this.classFullName, criteria); } + public static getInstance(iModel: IModelDb, criteria: Id64String | SourceAndTarget): T { + return iModel.relationships.getInstance(this.classFullName, criteria); + } } /** A Relationship where one Element refers to another Element * @public */ export class ElementRefersToElements extends Relationship { - public static override get className(): string { return "ElementRefersToElements"; } + public static override get className(): string { + return "ElementRefersToElements"; + } /** Create an instance of the Relationship. * @param iModel The iModel that will contain the relationship * @param sourceId The sourceId of the relationship, that is, the driver element @@ -99,14 +111,18 @@ export class ElementRefersToElements extends Relationship { * @public */ export class DrawingGraphicRepresentsElement extends ElementRefersToElements { - public static override get className(): string { return "DrawingGraphicRepresentsElement"; } + public static override get className(): string { + return "DrawingGraphicRepresentsElement"; + } } /** Relates a [[GraphicalElement3d]] to the [[Element]] that it represents * @public */ export class GraphicalElement3dRepresentsElement extends ElementRefersToElements { - public static override get className(): string { return "GraphicalElement3dRepresentsElement"; } + public static override get className(): string { + return "GraphicalElement3dRepresentsElement"; + } } /** Relates a [[SynchronizationConfigLink]] to N [[ExternalSource]] instances. @@ -115,7 +131,9 @@ export class GraphicalElement3dRepresentsElement extends ElementRefersToElements * @beta */ export class SynchronizationConfigProcessesSources extends ElementRefersToElements { - public static override get className(): string { return "SynchronizationConfigProcessesSources"; } + public static override get className(): string { + return "SynchronizationConfigProcessesSources"; + } } /** Relates a [[SynchronizationConfigLink]] to *root* [[ExternalSource]] instances. @@ -123,7 +141,9 @@ export class SynchronizationConfigProcessesSources extends ElementRefersToElemen * @beta */ export class SynchronizationConfigSpecifiesRootSources extends SynchronizationConfigProcessesSources { - public static override get className(): string { return "SynchronizationConfigSpecifiesRootSources"; } + public static override get className(): string { + return "SynchronizationConfigSpecifiesRootSources"; + } } /** Properties that are common to all types of link table ECRelationships @@ -137,7 +157,9 @@ export interface ElementGroupsMembersProps extends RelationshipProps { * @public */ export class ElementGroupsMembers extends ElementRefersToElements { - public static override get className(): string { return "ElementGroupsMembers"; } + public static override get className(): string { + return "ElementGroupsMembers"; + } public memberPriority: number; constructor(props: ElementGroupsMembersProps, iModel: IModelDb) { @@ -145,7 +167,12 @@ export class ElementGroupsMembers extends ElementRefersToElements { this.memberPriority = props.memberPriority; } - public static override create(iModel: IModelDb, sourceId: Id64String, targetId: Id64String, memberPriority: number = 0): T { + public static override create( + iModel: IModelDb, + sourceId: Id64String, + targetId: Id64String, + memberPriority: number = 0, + ): T { const props: ElementGroupsMembersProps = { sourceId, targetId, memberPriority, classFullName: this.classFullName }; return iModel.relationships.createInstance(props) as T; } @@ -156,7 +183,9 @@ export class ElementGroupsMembers extends ElementRefersToElements { * @public */ export class DefinitionGroupGroupsDefinitions extends ElementGroupsMembers { - public static override get className(): string { return "DefinitionGroupGroupsDefinitions"; } + public static override get className(): string { + return "DefinitionGroupGroupsDefinitions"; + } } /** Represents group membership where the group Element (and its properties) impart information about the member Elements above mere membership. @@ -165,7 +194,9 @@ export class DefinitionGroupGroupsDefinitions extends ElementGroupsMembers { * @public */ export class GroupImpartsToMembers extends ElementGroupsMembers { - public static override get className(): string { return "GroupImpartsToMembers"; } + public static override get className(): string { + return "GroupImpartsToMembers"; + } } /** Relates an [[ExternalSourceGroup]] to its [[ExternalSource]] members. @@ -173,7 +204,9 @@ export class GroupImpartsToMembers extends ElementGroupsMembers { * @beta */ export class ExternalSourceGroupGroupsSources extends ElementGroupsMembers { - public static override get className(): string { return "ExternalSourceGroupGroupsSources"; } + public static override get className(): string { + return "ExternalSourceGroupGroupsSources"; + } } /** Properties that are common to all types of ElementDrivesElements @@ -369,7 +402,9 @@ export interface ElementDrivesElementProps extends RelationshipProps { * @beta */ export class ElementDrivesElement extends Relationship { - public static override get className(): string { return "ElementDrivesElement"; } + public static override get className(): string { + return "ElementDrivesElement"; + } /** Relationship status * * 0 indicates no errors. Set after a successful evaluation. * * 1 indicates that this driving relationship could not be evaluated. The callback itself can set this to indicate that it failed to process the input changes. Also, it is set if the relationship is part of a circular dependency. @@ -411,7 +446,9 @@ export class ElementDrivesElement extends Relationship { * @internal */ export class ModelSelectorRefersToModels extends Relationship { - public static override get className(): string { return "ModelSelectorRefersToModels"; } + public static override get className(): string { + return "ModelSelectorRefersToModels"; + } protected override collectReferenceIds(referenceIds: EntityReferenceSet): void { super.collectReferenceIds(referenceIds); referenceIds.addElement(this.sourceId); @@ -426,18 +463,25 @@ export class Relationships { private _iModel: IModelDb; /** @internal */ - public constructor(iModel: IModelDb) { this._iModel = iModel; } + public constructor(iModel: IModelDb) { + this._iModel = iModel; + } /** Create a new instance of a Relationship. * @param props The properties of the new Relationship. * @throws [[IModelError]] if there is a problem creating the Relationship. */ - public createInstance(props: RelationshipProps): Relationship { return this._iModel.constructEntity(props); } + public createInstance(props: RelationshipProps): Relationship { + return this._iModel.constructEntity(props); + } /** Check classFullName to ensure it is a link table relationship class. */ private checkRelationshipClass(classFullName: string) { if (!this._iModel[_nativeDb].isLinkTableRelationship(classFullName.replace(".", ":"))) { - throw new IModelError(DbResult.BE_SQLITE_ERROR, `Class '${classFullName}' must be a relationship class and it should be subclass of BisCore:ElementRefersToElements or BisCore:ElementDrivesElement.`); + throw new IModelError( + DbResult.BE_SQLITE_ERROR, + `Class '${classFullName}' must be a relationship class and it should be subclass of BisCore:ElementRefersToElements or BisCore:ElementDrivesElement.`, + ); } } @@ -492,11 +536,14 @@ export class Relationships { return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getRow() as T : undefined; }); } else { - props = this._iModel.withPreparedStatement(`SELECT * FROM ${relClassFullName} WHERE SourceECInstanceId=? AND TargetECInstanceId=?`, (stmt: ECSqlStatement) => { - stmt.bindId(1, criteria.sourceId); - stmt.bindId(2, criteria.targetId); - return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getRow() as T : undefined; - }); + props = this._iModel.withPreparedStatement( + `SELECT * FROM ${relClassFullName} WHERE SourceECInstanceId=? AND TargetECInstanceId=?`, + (stmt: ECSqlStatement) => { + stmt.bindId(1, criteria.sourceId); + stmt.bindId(2, criteria.targetId); + return DbResult.BE_SQLITE_ROW === stmt.step() ? stmt.getRow() as T : undefined; + }, + ); } if (undefined !== props) { props.classFullName = (props as any).className.replace(".", ":"); diff --git a/core/backend/src/SQLiteDb.ts b/core/backend/src/SQLiteDb.ts index b487586da4a5..8b06581a8504 100644 --- a/core/backend/src/SQLiteDb.ts +++ b/core/backend/src/SQLiteDb.ts @@ -6,17 +6,17 @@ * @module SQLiteDb */ -import * as fs from "fs"; -import { dirname } from "path"; -import * as semver from "semver"; import { IModelJsNative } from "@bentley/imodeljs-native"; import { DbResult, OpenMode } from "@itwin/core-bentley"; import { LocalFileName } from "@itwin/core-common"; +import * as fs from "fs"; +import { dirname } from "path"; +import * as semver from "semver"; import { CloudSqlite } from "./CloudSqlite"; -import { IModelNative } from "./internal/NativePlatform"; import { IModelJsFs } from "./IModelJsFs"; -import { SqliteStatement, StatementCache } from "./SqliteStatement"; +import { IModelNative } from "./internal/NativePlatform"; import { _nativeDb } from "./internal/Symbols"; +import { SqliteStatement, StatementCache } from "./SqliteStatement"; // cspell:ignore savepoint julianday rowid @@ -30,7 +30,9 @@ export class SQLiteDb { /** @internal * @deprecated in 4.8. This internal API will be removed in 5.0. Use SQLiteDb's public API instead. */ - public get nativeDb(): IModelJsNative.SQLiteDb { return this[_nativeDb]; } + public get nativeDb(): IModelJsNative.SQLiteDb { + return this[_nativeDb]; + } /** @internal */ public readonly [_nativeDb] = new IModelNative.platform.SQLiteDb(); @@ -82,10 +84,14 @@ export class SQLiteDb { } /** Returns true if this SQLiteDb is open */ - public get isOpen(): boolean { return this[_nativeDb].isOpen(); } + public get isOpen(): boolean { + return this[_nativeDb].isOpen(); + } /** Returns true if this SQLiteDb is open readonly */ - public get isReadonly(): boolean { return this[_nativeDb].isReadonly(); } + public get isReadonly(): boolean { + return this[_nativeDb].isReadonly(); + } /** Create a new table in this database. */ protected createTable(args: { @@ -102,13 +108,15 @@ export class SQLiteDb { const constraints = args.constraints ? `,${args.constraints}` : ""; this.executeSQL(`CREATE TABLE ${args.tableName}(${args.columns}${timestampCol}${constraints})`); if (args.addTimestamp) - this.executeSQL(`CREATE TRIGGER ${args.tableName}_timestamp AFTER UPDATE ON ${args.tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${args.tableName} SET lastMod=julianday('now') WHERE rowid=new.rowid; END`); + this.executeSQL( + `CREATE TRIGGER ${args.tableName}_timestamp AFTER UPDATE ON ${args.tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${args.tableName} SET lastMod=julianday('now') WHERE rowid=new.rowid; END`, + ); } /** * Get the last modified date for a row in a table of this database. * @note the table must have been created with `addTimestamp: true` - */ + */ public readLastModTime(tableName: string, rowId: number): Date { return this.withSqliteStatement(`SELECT lastMod from ${tableName} WHERE rowid=?`, (stmt) => { stmt.bindInteger(1, rowId); @@ -242,10 +250,10 @@ export class SQLiteDb { } /** Prepare an SQL statement. - * @param sql The SQLite SQL statement to prepare - * @param logErrors Determine if errors are logged or not - * @internal - */ + * @param sql The SQLite SQL statement to prepare + * @param logErrors Determine if errors are logged or not + * @internal + */ public prepareSqliteStatement(sql: string, logErrors = true): SqliteStatement { const stmt = new SqliteStatement(sql); stmt.prepare(this[_nativeDb], logErrors); @@ -285,7 +293,7 @@ export abstract class VersionedSqliteDb extends SQLiteDb { * software. Likewise, if a new version of the package is asked to open an older VersionedSqliteDb that has not been upgraded to the lowest version * supported by it, the user will be informed that they need to upgrade their software. * @note this identifier is independent of versions in `package.json` files. - */ + */ public abstract myVersion: string; /** @@ -296,7 +304,10 @@ export abstract class VersionedSqliteDb extends SQLiteDb { */ public setRequiredVersions(versions: SQLiteDb.RequiredVersionRanges) { // NOTE: It might look tempting to just stringify the supplied `versions` object, but we only include required members - there may be others. - this[_nativeDb].saveFileProperty(VersionedSqliteDb._versionProps, JSON.stringify({ readVersion: versions.readVersion, writeVersion: versions.writeVersion })); + this[_nativeDb].saveFileProperty( + VersionedSqliteDb._versionProps, + JSON.stringify({ readVersion: versions.readVersion, writeVersion: versions.writeVersion }), + ); } /** Get the required version ranges necessary to open this VersionedSqliteDb. */ @@ -348,8 +359,11 @@ export abstract class VersionedSqliteDb extends SQLiteDb { this.closeDb(); const tooNew = semver.gtr(this.myVersion, range); - throw new Error(`${this[_nativeDb].getFilePath()} requires ${tooNew ? "older" : "newer"} version of ${this.constructor.name} for ${isReadonly ? "read" : "write"}`); - + throw new Error( + `${this[_nativeDb].getFilePath()} requires ${tooNew ? "older" : "newer"} version of ${this.constructor.name} for ${ + isReadonly ? "read" : "write" + }`, + ); } /** @@ -362,7 +376,9 @@ export abstract class VersionedSqliteDb extends SQLiteDb { this.verifyVersions(); } - public async upgradeSchema(arg: { dbName: string, lockContainer?: { container: CloudSqlite.CloudContainer, user: string }, upgradeFn: () => void }) { + public async upgradeSchema( + arg: { dbName: string, lockContainer?: { container: CloudSqlite.CloudContainer, user: string }, upgradeFn: () => void }, + ) { // can't use "this" because it checks for version, which we don't want here return (arg.lockContainer) ? super.withLockedContainer({ dbName: arg.dbName, ...arg.lockContainer }, async () => arg.upgradeFn) : @@ -393,8 +409,8 @@ export namespace SQLiteDb { */ export interface BlobIO { /** Close this BlobIO if it is opened. - * @note this BlobIO *may* be reused after this call by calling `open` again. - */ + * @note this BlobIO *may* be reused after this call by calling `open` again. + */ close(): void; /** get the total number of bytes in the blob */ getNumBytes(): number; @@ -413,10 +429,11 @@ export namespace SQLiteDb { row: number; /** If true, open this BlobIO for write access */ writeable?: boolean; - }): void; + }, + ): void; /** Read from a blob - * @returns the contents of the requested byte range - */ + * @returns the contents of the requested byte range + */ read(args: { /** The number of bytes to read */ numBytes: number; @@ -426,8 +443,8 @@ export namespace SQLiteDb { blob?: ArrayBuffer; }): Uint8Array; /** Reposition this BlobIO to a new rowId - * @note this BlobIO must be valid when this methods is called. - */ + * @note this BlobIO must be valid when this methods is called. + */ changeRow(row: number): void; /** Write to a blob */ write(args: { @@ -451,7 +468,7 @@ export namespace SQLiteDb { /** An immediate transaction is started when the file is first opened. */ Immediate = 2, /** An exclusive transaction is started when the file is first opened. */ - Exclusive = 3 + Exclusive = 3, } /** parameters common to opening or creating a new SQLiteDb */ @@ -463,8 +480,8 @@ export namespace SQLiteDb { /** Do not attempt to verify that the file is a valid sQLite file before opening. */ skipFileCheck?: boolean; /** the default transaction mode - * @see [[SQLiteDb.DefaultTxnMode]] - */ + * @see [[SQLiteDb.DefaultTxnMode]] + */ defaultTxn?: 0 | 1 | 2 | 3; /** see query parameters from 'URI Filenames' in https://www.sqlite.org/c3ref/open.html */ queryParam?: string; diff --git a/core/backend/src/Schema.ts b/core/backend/src/Schema.ts index e77cabff73a9..a6b26ddafd4c 100644 --- a/core/backend/src/Schema.ts +++ b/core/backend/src/Schema.ts @@ -19,13 +19,17 @@ export class Schema { * Failure to do so will ordinarily result in an error when the schema is registered, since there may only * be one JavaScript class for a given BIS schema (usually the errant schema will collide with its superclass.) */ - public static get schemaName(): string { throw new Error(`you must override static schemaName in ${this.name}`); } + public static get schemaName(): string { + throw new Error(`you must override static schemaName in ${this.name}`); + } /** if true, this Schema is a proxy for a missing Domain marked with the `BisCore.SchemaHasBehavior` customAttribute. * Classes generated for this Schema will disallow protected operations. * @internal */ - public static get missingRequiredBehavior(): boolean { return false; } + public static get missingRequiredBehavior(): boolean { + return false; + } /** Get a semver-compatible string from a padded version string. * works on unpadded version strings as well @@ -46,7 +50,9 @@ export class Schema { * error if it is ever called. * @internal */ - protected constructor() { throw new Error(`cannot create an instance of a Schema ${this.constructor.name}`); } + protected constructor() { + throw new Error(`cannot create an instance of a Schema ${this.constructor.name}`); + } } /** Manages registered schemas @@ -54,7 +60,7 @@ export class Schema { */ export class Schemas { private static readonly _registeredSchemas = new Map(); - private constructor() { } // this is a singleton + private constructor() {} // this is a singleton /** Register a schema prior to using it. * @throws [[IModelError]] if a schema of the same name is already registered. @@ -83,5 +89,7 @@ export class Schemas { * @param schemaName The name of the schema * @returns the previously registered schema or undefined if not registered. */ - public static getRegisteredSchema(schemaName: string): typeof Schema | undefined { return this._registeredSchemas.get(schemaName.toLowerCase()); } + public static getRegisteredSchema(schemaName: string): typeof Schema | undefined { + return this._registeredSchemas.get(schemaName.toLowerCase()); + } } diff --git a/core/backend/src/SchemaSync.ts b/core/backend/src/SchemaSync.ts index 0be49a5b1032..6c12cda0d9f5 100644 --- a/core/backend/src/SchemaSync.ts +++ b/core/backend/src/SchemaSync.ts @@ -7,14 +7,14 @@ * @module SQLiteDb */ -import { CloudSqlite } from "./CloudSqlite"; -import { VersionedSqliteDb } from "./SQLiteDb"; -import { BriefcaseDb, IModelDb } from "./IModelDb"; +import { IModelJsNative } from "@bentley/imodeljs-native"; import { DbResult, OpenMode } from "@itwin/core-bentley"; import { IModelError, LocalFileName } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; +import { CloudSqlite } from "./CloudSqlite"; +import { BriefcaseDb, IModelDb } from "./IModelDb"; import { IModelNative } from "./internal/NativePlatform"; import { _nativeDb } from "./internal/Symbols"; +import { VersionedSqliteDb } from "./SQLiteDb"; /** @internal */ export namespace SchemaSync { @@ -23,7 +23,7 @@ export namespace SchemaSync { /** A CloudSqlite database for synchronizing schema changes across briefcases. */ export class SchemaSyncDb extends VersionedSqliteDb { public override readonly myVersion = "4.0.0"; - protected override createDDL() { } + protected override createDDL() {} } const syncProperty = { namespace: "itwinjs", name: "SchemaSync" }; @@ -66,7 +66,11 @@ export namespace SchemaSync { } }; - export const withLockedAccess = async (iModel: IModelDb | { readonly fileName: LocalFileName }, args: { operationName: string, openMode?: OpenMode, user?: string }, operation: (access: CloudAccess) => Promise): Promise => { + export const withLockedAccess = async ( + iModel: IModelDb | { readonly fileName: LocalFileName }, + args: { operationName: string, openMode?: OpenMode, user?: string }, + operation: (access: CloudAccess) => Promise, + ): Promise => { const access = await getCloudAccess(iModel); try { await access.withLockedDb(args, async () => operation(access)); @@ -75,7 +79,10 @@ export namespace SchemaSync { } }; - export const withReadonlyAccess = async (iModel: IModelDb | { readonly fileName: LocalFileName }, operation: (access: CloudAccess) => Promise): Promise => { + export const withReadonlyAccess = async ( + iModel: IModelDb | { readonly fileName: LocalFileName }, + operation: (access: CloudAccess) => Promise, + ): Promise => { const access = await getCloudAccess(iModel); access.synchronizeWithCloud(); access.openForRead(); @@ -143,13 +150,12 @@ export namespace SchemaSync { return `${this.getCloudDb()[_nativeDb].getFilePath()}?vfs=${this.container.cache?.name}&writable=${this.container.isWriteable ? 1 : 0}`; } /** - * Initialize a cloud container for use as a SchemaSync. The container must first be created via its storage supplier api (e.g. Azure, or AWS). - * A valid sasToken that grants write access must be supplied. This function creates and uploads an empty ChannelDb into the container. - * @note this deletes any existing content in the container. - */ + * Initialize a cloud container for use as a SchemaSync. The container must first be created via its storage supplier api (e.g. Azure, or AWS). + * A valid sasToken that grants write access must be supplied. This function creates and uploads an empty ChannelDb into the container. + * @note this deletes any existing content in the container. + */ public static async initializeDb(props: CloudSqlite.ContainerProps) { return super._initializeDb({ props, dbType: SchemaSyncDb, dbName: defaultDbName }); } } } - diff --git a/core/backend/src/SheetIndex.ts b/core/backend/src/SheetIndex.ts index 8f682a57d189..cdee0fcd0816 100644 --- a/core/backend/src/SheetIndex.ts +++ b/core/backend/src/SheetIndex.ts @@ -6,11 +6,29 @@ * @module Elements */ -import { BisCodeSpec, Code, CodeScopeProps, CodeSpec, ElementProps, EntityReferenceSet, IModelError, RelatedElementProps, SheetIndexEntryProps, SheetIndexFolderProps, SheetIndexReferenceProps, SheetReferenceProps } from "@itwin/core-common"; +import { Id64String, IModelStatus } from "@itwin/core-bentley"; +import { + BisCodeSpec, + Code, + CodeScopeProps, + CodeSpec, + ElementProps, + EntityReferenceSet, + IModelError, + RelatedElementProps, + SheetIndexEntryProps, + SheetIndexFolderProps, + SheetIndexReferenceProps, + SheetReferenceProps, +} from "@itwin/core-common"; import { InformationReferenceElement, Sheet } from "./Element"; import { IModelDb } from "./IModelDb"; -import { Id64String, IModelStatus } from "@itwin/core-bentley"; -import { SheetIndexFolderOwnsEntries, SheetIndexOwnsEntries, SheetIndexReferenceRefersToSheetIndex, SheetReferenceRefersToSheet } from "./NavigationRelationship"; +import { + SheetIndexFolderOwnsEntries, + SheetIndexOwnsEntries, + SheetIndexReferenceRefersToSheetIndex, + SheetReferenceRefersToSheet, +} from "./NavigationRelationship"; /** Arguments used to create a [[SheetIndexEntry]]. * @beta @@ -50,7 +68,9 @@ export interface SheetReferenceCreateArgs extends SheetIndexEntryCreateArgs { * @beta */ export class SheetIndex extends InformationReferenceElement { - public static override get className(): string { return "SheetIndex"; } + public static override get className(): string { + return "SheetIndex"; + } /** Create a Code for a SheetIndex given a name that is meant to be unique within the scope of the specified SheetIndexModel. * @param iModel The IModelDb @@ -95,9 +115,11 @@ export class SheetIndex extends InformationReferenceElement { /** The base class for all elements that can participate in a [[SheetIndex]] hierarchy. * @beta -*/ + */ export abstract class SheetIndexEntry extends InformationReferenceElement { - public static override get className(): string { return "SheetIndexEntry"; } + public static override get className(): string { + return "SheetIndexEntry"; + } /** Can be used to prioritize or order members within a SheetIndex or SheetIndexFolder. */ public entryPriority: number; @@ -144,7 +166,9 @@ export abstract class SheetIndexEntry extends InformationReferenceElement { * @beta */ export class SheetIndexFolder extends SheetIndexEntry { - public static override get className(): string { return "SheetIndexFolder"; } + public static override get className(): string { + return "SheetIndexFolder"; + } /** Create a new SheetIndexFolder * @returns The newly constructed SheetIndexFolder element. @@ -169,9 +193,11 @@ export class SheetIndexFolder extends SheetIndexEntry { /** A node within one [[SheetIndex]] that incorporates another [[SheetIndex]] as a sub-tree. * @beta -*/ + */ export class SheetIndexReference extends SheetIndexEntry { - public static override get className(): string { return "SheetIndexReference"; } + public static override get className(): string { + return "SheetIndexReference"; + } /** The bis:SheetIndex that this bis:SheetIndexReference is pointing to. */ public sheetIndex?: SheetIndexReferenceRefersToSheetIndex; @@ -231,9 +257,11 @@ export class SheetIndexReference extends SheetIndexEntry { /** A leaf node in a [[SheetIndex]] that refers to a specific [[Sheet]]. * @beta -*/ + */ export class SheetReference extends SheetIndexEntry { - public static override get className(): string { return "SheetReference"; } + public static override get className(): string { + return "SheetReference"; + } /** The bis:Sheet that this bis:SheetReference is pointing to. */ public sheet: SheetReferenceRefersToSheet | undefined; diff --git a/core/backend/src/SqliteChangesetReader.ts b/core/backend/src/SqliteChangesetReader.ts index a449ae905aa6..205038c6b0fd 100644 --- a/core/backend/src/SqliteChangesetReader.ts +++ b/core/backend/src/SqliteChangesetReader.ts @@ -13,12 +13,12 @@ import { _nativeDb } from "./internal/Symbols"; /** Changed value type * @beta -*/ + */ type SqliteValue = Uint8Array | number | string | null | undefined; /** Array of changed values * @beta -*/ + */ type SqliteValueArray = SqliteValue[]; /** * Format option when converting change from array to column/value object. @@ -39,22 +39,22 @@ export interface ChangeFormatArgs { /** Operation that cause the change * @beta -*/ + */ export type SqliteChangeOp = "Inserted" | "Updated" | "Deleted"; /** Stage is version of value that needed to be read * @beta -*/ + */ export type SqliteValueStage = "Old" | "New"; /** Db from which schema will be read. It should be from timeline to which changeset belong. * @beta -*/ + */ export type AnyDb = IModelDb | ECDb; /** Arg to open a changeset file from disk * @beta -*/ + */ export interface SqliteChangesetReaderArgs { /** db from which schema will be read. It should be at or ahead of the latest changeset being opened.*/ readonly db: AnyDb; @@ -91,7 +91,7 @@ export class SqliteChangesetReader implements IDisposable { protected constructor( /** db from where sql schema will be read */ public readonly db: AnyDb, - ) { } + ) {} /** * Open changeset file from disk @@ -135,18 +135,22 @@ export class SqliteChangesetReader implements IDisposable { * @param args.db must be of type IModelDb * @returns SqliteChangesetReader instance */ - public static openLocalChanges(args: Omit & { db: IModelDb, includeInMemoryChanges?: true }): SqliteChangesetReader { + public static openLocalChanges( + args: Omit & { db: IModelDb, includeInMemoryChanges?: true }, + ): SqliteChangesetReader { const reader = new SqliteChangesetReader(args.db); reader._disableSchemaCheck = args.disableSchemaCheck ?? false; reader._nativeReader.openLocalChanges(args.db[_nativeDb], args.includeInMemoryChanges ?? false, args.invert ?? false); return reader; } /** check if schema check is disabled or not */ - public get disableSchemaCheck(): boolean { return this._disableSchemaCheck; } + public get disableSchemaCheck(): boolean { + return this._disableSchemaCheck; + } /** Move to next change in changeset * @returns true if there is current change false if reader is end of changeset. * @beta - */ + */ public step(): boolean { if (this._nativeReader.step()) { this._changeIndex++; @@ -156,25 +160,25 @@ export class SqliteChangesetReader implements IDisposable { } /** Check if reader current on a row * @beta - */ + */ public get hasRow(): boolean { return this._nativeReader.hasRow(); } /** Check if its current change is indirect * @beta - */ + */ public get isIndirect(): boolean { return this._nativeReader.isIndirectChange(); } /** Get count of columns in current change * @beta - */ + */ public get columnCount(): number { return this._nativeReader.getColumnCount(); } /** Get operation that caused the change * @beta - */ + */ public get op(): SqliteChangeOp { if (this._nativeReader.getOpCode() === DbOpcode.Insert) return "Inserted"; @@ -186,7 +190,7 @@ export class SqliteChangesetReader implements IDisposable { } /** Get primary key value array * @beta - */ + */ public get primaryKeyValues(): SqliteValueArray { return this._nativeReader.getPrimaryKeys(); } @@ -203,7 +207,7 @@ export class SqliteChangesetReader implements IDisposable { } /** Get current change table. * @beta - */ + */ public get tableName(): string { return this._nativeReader.getTableName(); } @@ -387,7 +391,9 @@ export class SqliteChangesetReader implements IDisposable { /** index of current change * @beta */ - public get changeIndex() { return this._changeIndex; } + public get changeIndex() { + return this._changeIndex; + } /** * Close changeset * @beta diff --git a/core/backend/src/SqliteStatement.ts b/core/backend/src/SqliteStatement.ts index aa04c469b291..c678f6294bf9 100644 --- a/core/backend/src/SqliteStatement.ts +++ b/core/backend/src/SqliteStatement.ts @@ -6,9 +6,9 @@ * @module SQLite */ +import { IModelJsNative } from "@bentley/imodeljs-native"; import { assert, BentleyError, DbResult, GuidString, Id64String, IDisposable, LRUMap } from "@itwin/core-bentley"; import { ECJsNames, IModelError } from "@itwin/core-common"; -import { IModelJsNative } from "@bentley/imodeljs-native"; import { IModelNative } from "./internal/NativePlatform"; // spell:ignore julianday @@ -60,12 +60,18 @@ export class SqliteStatement implements IterableIterator, IDisposable { private _stmt: IModelJsNative.SqliteStatement | undefined; private _db: IModelJsNative.AnyDb | undefined; - public constructor(private _sql: string) { } - public get stmt(): IModelJsNative.SqliteStatement { return this._stmt!; } - public get sql() { return this._sql; } + public constructor(private _sql: string) {} + public get stmt(): IModelJsNative.SqliteStatement { + return this._stmt!; + } + public get sql() { + return this._sql; + } /** Check if this statement has been prepared successfully or not */ - public get isPrepared(): boolean { return undefined !== this._stmt; } + public get isPrepared(): boolean { + return undefined !== this._stmt; + } /** Prepare this statement prior to first use. * @param db The DgnDb or ECDb to prepare the statement against @@ -125,9 +131,14 @@ export class SqliteStatement implements IterableIterator, IDisposable { public throwSqlError(rc: DbResult) { throw new SqliteStatement.DbError( - rc === DbResult.BE_SQLITE_CONSTRAINT_FOREIGNKEY ? "ValueIsInUse" : - rc === DbResult.BE_SQLITE_CONSTRAINT_UNIQUE ? "DuplicateValue" : - "SqlLogicError", rc, `SQL error: ${this._db!.getLastError()}`); + rc === DbResult.BE_SQLITE_CONSTRAINT_FOREIGNKEY ? + "ValueIsInUse" : + rc === DbResult.BE_SQLITE_CONSTRAINT_UNIQUE ? + "DuplicateValue" : + "SqlLogicError", + rc, + `SQL error: ${this._db!.getLastError()}`, + ); } public stepForWrite(): void { @@ -157,14 +168,14 @@ export class SqliteStatement implements IterableIterator, IDisposable { let stat: DbResult; if (value === undefined || value === null) { stat = this.stmt.bindNull(parameter); - } else if (typeof (value) === "number") { + } else if (typeof value === "number") { if (Number.isInteger(value)) stat = this.stmt.bindInteger(parameter, value); else stat = this.stmt.bindDouble(parameter, value); - } else if (typeof (value) === "boolean") { + } else if (typeof value === "boolean") { stat = this.stmt.bindInteger(parameter, value ? 1 : 0); - } else if (typeof (value) === "string") { + } else if (typeof value === "string") { stat = this.stmt.bindString(parameter, value); } else if (!!value.id) { stat = this.stmt.bindId(parameter, value.id); @@ -380,8 +391,8 @@ export class SqliteStatement implements IterableIterator, IDisposable { return this.isValueNull(colIndex) ? undefined : this.getValueBlob(colIndex); } /** Get a value as a double - * @param colIndex Index of SQL column in query result (0-based) - */ + * @param colIndex Index of SQL column in query result (0-based) + */ public getValueDouble(colIndex: number): number { return this.stmt.getValueDouble(colIndex); } @@ -392,8 +403,8 @@ export class SqliteStatement implements IterableIterator, IDisposable { return this.isValueNull(colIndex) ? undefined : this.getValueDouble(colIndex); } /** Get a value as a integer - * @param colIndex Index of SQL column in query result (0-based) - */ + * @param colIndex Index of SQL column in query result (0-based) + */ public getValueInteger(colIndex: number): number { return this.stmt.getValueInteger(colIndex); } @@ -404,8 +415,8 @@ export class SqliteStatement implements IterableIterator, IDisposable { return this.isValueNull(colIndex) ? undefined : this.getValueInteger(colIndex); } /** Get a value as a string - * @param colIndex Index of SQL column in query result (0-based) - */ + * @param colIndex Index of SQL column in query result (0-based) + */ public getValueString(colIndex: number): string { return this.stmt.getValueString(colIndex); } @@ -416,14 +427,14 @@ export class SqliteStatement implements IterableIterator, IDisposable { return this.isValueNull(colIndex) ? undefined : this.getValueString(colIndex); } /** Get a value as an Id - * @param colIndex Index of SQL column in query result (0-based) - */ + * @param colIndex Index of SQL column in query result (0-based) + */ public getValueId(colIndex: number): Id64String { return this.stmt.getValueId(colIndex); } /** Get a value as a Guid - * @param colIndex Index of SQL column in query result (0-based) - */ + * @param colIndex Index of SQL column in query result (0-based) + */ public getValueGuid(colIndex: number): GuidString { return this.stmt.getValueGuid(colIndex); } @@ -443,7 +454,7 @@ export class SqliteStatement implements IterableIterator, IDisposable { /** Get the value as a "props" JSON string, then parse it and return the object * @param colIndex Index of SQL column in query result (0-based) * @internal - */ + */ public getProps(colIndex: number): T { return JSON.parse(this.getValueString(colIndex)); } @@ -451,7 +462,7 @@ export class SqliteStatement implements IterableIterator, IDisposable { * If the column is null, return undefined. * @param colIndex Index of SQL column in query result (0-based) * @internal - */ + */ public getPropsMaybe(colIndex: number): T | undefined { return this.isValueNull(colIndex) ? undefined : this.getProps(colIndex); } @@ -525,7 +536,9 @@ export class SqliteStatement implements IterableIterator, IDisposable { } /** The iterator that will step through the results of this statement. */ - public [Symbol.iterator](): IterableIterator { return this; } + public [Symbol.iterator](): IterableIterator { + return this; + } } /** Data type of a value in in an SQLite SQL query result. @@ -561,13 +574,19 @@ export class SqliteValue { } /** Indicates whether the value is NULL or not. */ - public get isNull(): boolean { return this._stmt.isValueNull(this._colIndex); } + public get isNull(): boolean { + return this._stmt.isValueNull(this._colIndex); + } /** Gets the data type of the value. */ - public get type(): SqliteValueType { return this._stmt.getColumnType(this._colIndex); } + public get type(): SqliteValueType { + return this._stmt.getColumnType(this._colIndex); + } /** Gets the name of the column of the value. */ - public get columnName(): string { return this._stmt.getColumnName(this._colIndex); } + public get columnName(): string { + return this._stmt.getColumnName(this._colIndex); + } /** Gets the SqlValue as JavaScript value. * @@ -597,17 +616,29 @@ export class SqliteValue { } /** Get the value as Blob */ - public getBlob(): Uint8Array { return this._stmt.getValueBlob(this._colIndex); } + public getBlob(): Uint8Array { + return this._stmt.getValueBlob(this._colIndex); + } /** Get the value as a double value */ - public getDouble(): number { return this._stmt.getValueDouble(this._colIndex); } + public getDouble(): number { + return this._stmt.getValueDouble(this._colIndex); + } /** Get the value as a integer value */ - public getInteger(): number { return this._stmt.getValueInteger(this._colIndex); } + public getInteger(): number { + return this._stmt.getValueInteger(this._colIndex); + } /** Get the value as a string value */ - public getString(): string { return this._stmt.getValueString(this._colIndex); } + public getString(): string { + return this._stmt.getValueString(this._colIndex); + } /** Get the value as an Id value */ - public getId(): Id64String { return this._stmt.getValueId(this._colIndex); } + public getId(): Id64String { + return this._stmt.getValueId(this._colIndex); + } /** Get the value as a Guid value */ - public getGuid(): GuidString { return this._stmt.getValueGuid(this._colIndex); } + public getGuid(): GuidString { + return this._stmt.getValueGuid(this._colIndex); + } } interface Statement { @@ -630,7 +661,9 @@ export class StatementCache { this._cache = new LRUMap(maxCount); } - public get size() { return this._cache.size; } + public get size() { + return this._cache.size; + } public addOrDispose(stmt: Stmt): void { assert(stmt.isPrepared); @@ -672,7 +705,7 @@ export namespace SqliteStatement { } export type ErrorId = - "DuplicateValue" | - "SqlLogicError" | - "ValueIsInUse"; + | "DuplicateValue" + | "SqlLogicError" + | "ValueIsInUse"; } diff --git a/core/backend/src/TextAnnotationElement.ts b/core/backend/src/TextAnnotationElement.ts index 789920baa4b5..ec3f54ac8458 100644 --- a/core/backend/src/TextAnnotationElement.ts +++ b/core/backend/src/TextAnnotationElement.ts @@ -6,11 +6,11 @@ * @module Elements */ +import { Id64String } from "@itwin/core-bentley"; import { GeometryParams, GeometryStreamBuilder, TextAnnotation, TextAnnotation2dProps, TextAnnotation3dProps } from "@itwin/core-common"; -import { IModelDb } from "./IModelDb"; import { AnnotationElement2d, GraphicalElement3d } from "./Element"; +import { IModelDb } from "./IModelDb"; import { produceTextAnnotationGeometry } from "./TextAnnotationGeometry"; -import { Id64String } from "@itwin/core-bentley"; function updateAnnotation(element: TextAnnotation2d | TextAnnotation3d, annotation: TextAnnotation, subCategory: Id64String | undefined): boolean { const builder = new GeometryStreamBuilder(); @@ -38,8 +38,12 @@ function updateAnnotation(element: TextAnnotation2d | TextAnnotation3d, annotati */ export class TextAnnotation2d extends AnnotationElement2d { /** @internal */ - public static override get className(): string { return "TextAnnotation2d"; } - protected constructor(props: TextAnnotation2dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "TextAnnotation2d"; + } + protected constructor(props: TextAnnotation2dProps, iModel: IModelDb) { + super(props, iModel); + } public static fromJSON(props: TextAnnotation2dProps, iModel: IModelDb): TextAnnotation2d { return new TextAnnotation2d(props, iModel); @@ -75,8 +79,12 @@ export class TextAnnotation2d extends AnnotationElement2d { */ export class TextAnnotation3d extends GraphicalElement3d { /** @internal */ - public static override get className(): string { return "TextAnnotation3d"; } - protected constructor(props: TextAnnotation3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "TextAnnotation3d"; + } + protected constructor(props: TextAnnotation3dProps, iModel: IModelDb) { + super(props, iModel); + } public static fromJSON(props: TextAnnotation3dProps, iModel: IModelDb): TextAnnotation3d { return new TextAnnotation3d(props, iModel); diff --git a/core/backend/src/TextAnnotationGeometry.ts b/core/backend/src/TextAnnotationGeometry.ts index 110a7bdd7257..c911afffd040 100644 --- a/core/backend/src/TextAnnotationGeometry.ts +++ b/core/backend/src/TextAnnotationGeometry.ts @@ -6,11 +6,11 @@ * @module ElementGeometry */ +import { assert } from "@itwin/core-bentley"; import { ColorDef, TextAnnotation, TextBlockGeometryProps, TextBlockGeometryPropsEntry, TextString, TextStyleColor } from "@itwin/core-common"; -import { ComputeRangesForTextLayout, FindFontId, FindTextStyle, layoutTextBlock, RunLayout, TextBlockLayout } from "./TextAnnotationLayout"; import { LineSegment3d, Point3d, Range2d, Transform, Vector2d } from "@itwin/core-geometry"; -import { assert } from "@itwin/core-bentley"; import { IModelDb } from "./IModelDb"; +import { ComputeRangesForTextLayout, FindFontId, FindTextStyle, layoutTextBlock, RunLayout, TextBlockLayout } from "./TextAnnotationLayout"; interface GeometryContext { curColor?: TextStyleColor; @@ -61,7 +61,7 @@ function processTextRun(run: RunLayout, transform: Transform, context: GeometryC ts.transformInPlace(transform); setColor(run.style.color, context); - context.entries.push({ text: ts}); + context.entries.push({ text: ts }); } function createFractionTextString(text: string, run: RunLayout, origin: Point3d, transform: Transform): TextString { @@ -121,7 +121,7 @@ function processFractionRun(run: RunLayout, transform: Transform, context: Geome }); if (source.denominator.length > 0) { - context.entries.push({ text: createFractionTextString(source.denominator, run,denominatorOffset, transform) }); + context.entries.push({ text: createFractionTextString(source.denominator, run, denominatorOffset, transform) }); } } diff --git a/core/backend/src/TextAnnotationLayout.ts b/core/backend/src/TextAnnotationLayout.ts index 1bcd85b3d3d3..78326be7c3f6 100644 --- a/core/backend/src/TextAnnotationLayout.ts +++ b/core/backend/src/TextAnnotationLayout.ts @@ -6,11 +6,24 @@ * @module ElementGeometry */ -import { BaselineShift, FontId, FractionRun, LineLayoutResult, Paragraph, Run, RunLayoutResult, TextBlock, TextBlockLayoutResult, TextRun, TextStyleSettings, TextStyleSettingsProps } from "@itwin/core-common"; -import { Range2d } from "@itwin/core-geometry"; -import { IModelDb } from "./IModelDb"; import { assert, NonFunctionPropertiesOf } from "@itwin/core-bentley"; +import { + BaselineShift, + FontId, + FractionRun, + LineLayoutResult, + Paragraph, + Run, + RunLayoutResult, + TextBlock, + TextBlockLayoutResult, + TextRun, + TextStyleSettings, + TextStyleSettingsProps, +} from "@itwin/core-common"; +import { Range2d } from "@itwin/core-geometry"; import * as LineBreaker from "linebreak"; +import { IModelDb } from "./IModelDb"; /** @internal */ export interface TextLayoutRanges { @@ -100,7 +113,7 @@ export interface ComputeGraphemeOffsetsArgs extends LayoutTextBlockArgs { runLayoutResult: RunLayoutResult; /** An array of starting character indexes for each grapheme. Each entry represents the index of the first character in a grapheme. */ graphemeCharIndexes: number[]; -}; +} /** * Computes the range from the start of a [RunLayoutResult]($common) to the trailing edge of each grapheme. @@ -158,7 +171,12 @@ class LayoutContext { private readonly _fontIds = new Map(); public readonly blockSettings: TextStyleSettings; - public constructor(block: TextBlock, private readonly _computeTextRange: ComputeRangesForTextLayout, private readonly _findTextStyle: FindTextStyle, private readonly _findFontId: FindFontId) { + public constructor( + block: TextBlock, + private readonly _computeTextRange: ComputeRangesForTextLayout, + private readonly _findTextStyle: FindTextStyle, + private readonly _findFontId: FindFontId, + ) { const settings = this.findTextStyle(block.styleName); this.blockSettings = applyBlockSettings(settings, block.styleOverrides); } @@ -345,7 +363,18 @@ export class RunLayout { } } - return new RunLayout({ source, charOffset, numChars, range, justificationRange, denominatorRange, numeratorRange, offsetFromLine, style, fontId }); + return new RunLayout({ + source, + charOffset, + numChars, + range, + justificationRange, + denominatorRange, + numeratorRange, + offsetFromLine, + style, + fontId, + }); } /** Compute a string representation, primarily for debugging purposes. */ @@ -357,7 +386,7 @@ export class RunLayout { return this.source.type === "text"; } - private cloneForWrap(args: { ranges: TextLayoutRanges, charOffset: number, numChars: number}): RunLayout { + private cloneForWrap(args: { ranges: TextLayoutRanges, charOffset: number, numChars: number }): RunLayout { assert(this.canWrap()); return new RunLayout({ @@ -437,8 +466,12 @@ export class LineLayout { return `${runs.join("")}`; } - public get runs(): ReadonlyArray { return this._runs; } - public get isEmpty() { return this._runs.length === 0; } + public get runs(): ReadonlyArray { + return this._runs; + } + public get isEmpty() { + return this._runs.length === 0; + } public get back(): RunLayout { assert(!this.isEmpty); return this._runs[this._runs.length - 1]; diff --git a/core/backend/src/Texture.ts b/core/backend/src/Texture.ts index 2c781f29c37f..9acd43760e57 100644 --- a/core/backend/src/Texture.ts +++ b/core/backend/src/Texture.ts @@ -7,9 +7,7 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { - Base64EncodedString, BisCodeSpec, Code, CodeScopeProps, CodeSpec, ImageSourceFormat, TextureProps, -} from "@itwin/core-common"; +import { Base64EncodedString, BisCodeSpec, Code, CodeScopeProps, CodeSpec, ImageSourceFormat, TextureProps } from "@itwin/core-common"; import { DefinitionElement } from "./Element"; import { IModelDb } from "./IModelDb"; @@ -26,7 +24,9 @@ export interface TextureCreateProps extends Omit { */ export class Texture extends DefinitionElement { /** @internal */ - public static override get className(): string { return "Texture"; } + public static override get className(): string { + return "Texture"; + } public format: ImageSourceFormat; public data: Uint8Array; public description?: string; @@ -68,7 +68,14 @@ export class Texture extends DefinitionElement { * @throws [[IModelError]] if unable to create the element. * @see [[insertTexture]] to insert a new texture into the iModel. */ - public static createTexture(iModelDb: IModelDb, definitionModelId: Id64String, name: string, format: ImageSourceFormat, data: Uint8Array | Base64EncodedString, description?: string): Texture { + public static createTexture( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + format: ImageSourceFormat, + data: Uint8Array | Base64EncodedString, + description?: string, + ): Texture { const textureProps: TextureCreateProps = { classFullName: this.classFullName, code: this.createCode(iModelDb, definitionModelId, name), @@ -93,7 +100,14 @@ export class Texture extends DefinitionElement { * @throws [[IModelError]] if unable to insert the element. * @see [[insertTexture]] to insert a new texture into the iModel. */ - public static insertTexture(iModelDb: IModelDb, definitionModelId: Id64String, name: string, format: ImageSourceFormat, data: Uint8Array | Base64EncodedString, description?: string): Id64String { + public static insertTexture( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + format: ImageSourceFormat, + data: Uint8Array | Base64EncodedString, + description?: string, + ): Id64String { const texture = this.createTexture(iModelDb, definitionModelId, name, format, data, description); return iModelDb.elements.insertElement(texture.toJSON()); } diff --git a/core/backend/src/TileStorage.ts b/core/backend/src/TileStorage.ts index 75ffd9cdf861..6b8282fca7d2 100644 --- a/core/backend/src/TileStorage.ts +++ b/core/backend/src/TileStorage.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { gunzip, gzip } from "zlib"; -import { promisify } from "util"; -import { Metadata, ObjectReference, ServerStorage, TransferConfig } from "@itwin/object-storage-core"; -import { getTileObjectReference } from "@itwin/core-common"; import { Logger } from "@itwin/core-bentley"; +import { getTileObjectReference } from "@itwin/core-common"; +import { Metadata, ObjectReference, ServerStorage, TransferConfig } from "@itwin/object-storage-core"; +import { promisify } from "util"; +import { gunzip, gzip } from "zlib"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { IModelHost } from "./IModelHost"; @@ -49,7 +49,7 @@ export class TileStorage { } catch (e: any) { // Ignore 409 errors. This is what Azure blob storage returns when the container already exists. // Usually this means multiple backends tried to initialize tile storage at the same time. - if(e.statusCode !== 409) + if (e.statusCode !== 409) throw e; } } @@ -80,7 +80,15 @@ export class TileStorage { /** * Uploads a tile to the cloud cache. */ - public async uploadTile(iModelId: string, changesetId: string, treeId: string, contentId: string, content: Uint8Array, guid?: string, metadata?: Metadata): Promise { + public async uploadTile( + iModelId: string, + changesetId: string, + treeId: string, + contentId: string, + content: Uint8Array, + guid?: string, + metadata?: Metadata, + ): Promise { try { await this.storage.upload( getTileObjectReference(iModelId, changesetId, treeId, contentId, guid), @@ -146,7 +154,9 @@ export class TileStorage { if (parts[0] !== "tiles") return false; if (parts.length !== 3) { - Logger.logWarning(BackendLoggerCategory.IModelTileStorage, "Malformed tile id found in tile cache: {tileId}", { tileId: [...parts, objectName].join("/") }); + Logger.logWarning(BackendLoggerCategory.IModelTileStorage, "Malformed tile id found in tile cache: {tileId}", { + tileId: [...parts, objectName].join("/"), + }); return false; } return true; diff --git a/core/backend/src/TxnManager.ts b/core/backend/src/TxnManager.ts index f7774e161e8b..6bbff3b0837e 100644 --- a/core/backend/src/TxnManager.ts +++ b/core/backend/src/TxnManager.ts @@ -6,17 +6,34 @@ * @module iModels */ -import * as touch from "touch"; import { - assert, BeEvent, BentleyError, compareStrings, CompressedId64Set, DbResult, Id64Array, Id64String, IModelStatus, IndexMap, Logger, OrderedId64Array, + assert, + BeEvent, + BentleyError, + compareStrings, + CompressedId64Set, + DbResult, + Id64Array, + Id64String, + IModelStatus, + IndexMap, + Logger, + OrderedId64Array, } from "@itwin/core-bentley"; -import { EntityIdAndClassIdIterable, ModelGeometryChangesProps, ModelIdAndGeometryGuid, NotifyEntitiesChangedArgs, NotifyEntitiesChangedMetadata } from "@itwin/core-common"; +import { + EntityIdAndClassIdIterable, + ModelGeometryChangesProps, + ModelIdAndGeometryGuid, + NotifyEntitiesChangedArgs, + NotifyEntitiesChangedMetadata, +} from "@itwin/core-common"; +import * as touch from "touch"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { BriefcaseDb, StandaloneDb } from "./IModelDb"; +import { _nativeDb } from "./internal/Symbols"; import { IpcHost } from "./IpcHost"; import { Relationship, RelationshipProps } from "./Relationship"; import { SqliteStatement } from "./SqliteStatement"; -import { _nativeDb } from "./internal/Symbols"; /** A string that identifies a Txn. * @public @@ -61,8 +78,8 @@ export interface QueryLocalChangesArgs { /** Represents a change (insertion, deletion, or modification) to a single EC instance made in a local [[BriefcaseDb]]. * @see [[TxnManager.queryLocalChanges]] to iterate all of the changed instances. -* @beta -*/ + * @beta + */ export interface ChangeInstanceKey { /** ECInstanceId of the instance. */ id: Id64String; @@ -159,7 +176,8 @@ class ChangedEntitiesProc { const classIdsToLoad = classIds.filter((x) => undefined === db.classMetaDataRegistry.findByClassId(x)); if (classIdsToLoad.length > 0) { const classIdsStr = classIdsToLoad.join(","); - const sql = `SELECT ec_class.Name, ec_class.Id, ec_schema.Name FROM ec_class JOIN ec_schema WHERE ec_schema.Id = ec_class.SchemaId AND ec_class.Id IN (${classIdsStr})`; + const sql = + `SELECT ec_class.Name, ec_class.Id, ec_schema.Name FROM ec_class JOIN ec_schema WHERE ec_schema.Id = ec_class.SchemaId AND ec_class.Id IN (${classIdsStr})`; db.withPreparedSqliteStatement(sql, (stmt) => { while (stmt.step() === DbResult.BE_SQLITE_ROW) { const classFullName = `${stmt.getValueString(2)}:${stmt.getValueString(0)}`; @@ -246,7 +264,11 @@ class ChangedEntitiesProc { this._currSize = 0; } - private static processChanges(iModel: BriefcaseDb | StandaloneDb, changedEvent: EntitiesChangedEvent, evtName: "notifyElementsChanged" | "notifyModelsChanged") { + private static processChanges( + iModel: BriefcaseDb | StandaloneDb, + changedEvent: EntitiesChangedEvent, + evtName: "notifyElementsChanged" | "notifyModelsChanged", + ) { try { const maxSize = this.maxPerEvent; const changes = new ChangedEntitiesProc(); @@ -304,7 +326,9 @@ export class TxnManager { /** Array of errors from dependency propagation */ public readonly validationErrors: ValidationError[] = []; - private get _nativeDb() { return this._iModel[_nativeDb]; } + private get _nativeDb() { + return this._iModel[_nativeDb]; + } private _getElementClass(elClassName: string): typeof Element { return this._iModel.getJsClass(elClassName) as unknown as typeof Element; } @@ -339,7 +363,9 @@ export class TxnManager { this._getRelationshipClass(props.classFullName).onDeletedDependency(props, this._iModel); } /** @internal */ - protected _onBeginValidate() { this.validationErrors.length = 0; } + protected _onBeginValidate() { + this.validationErrors.length = 0; + } /** called from native code after validation of a Txn, either from saveChanges or apply changeset. * @internal @@ -416,7 +442,9 @@ export class TxnManager { } /** Determine whether any fatal validation errors have occurred during dependency propagation. */ - public get hasFatalError(): boolean { return this._nativeDb.hasFatalTxnError(); } + public get hasFatalError(): boolean { + return this._nativeDb.hasFatalTxnError(); + } /** @internal */ public readonly onEndValidation = new BeEvent<() => void>(); @@ -475,23 +503,33 @@ export class TxnManager { } /** Determine whether current txn is propagating indirect changes or not. */ - public get isIndirectChanges(): boolean { return this._nativeDb.isIndirectChanges(); } + public get isIndirectChanges(): boolean { + return this._nativeDb.isIndirectChanges(); + } /** Determine if there are currently any reversible (undoable) changes from this editing session. */ - public get isUndoPossible(): boolean { return this._nativeDb.isUndoPossible(); } + public get isUndoPossible(): boolean { + return this._nativeDb.isUndoPossible(); + } /** Determine if there are currently any reinstatable (redoable) changes */ - public get isRedoPossible(): boolean { return this._nativeDb.isRedoPossible(); } + public get isRedoPossible(): boolean { + return this._nativeDb.isRedoPossible(); + } /** Get the description of the operation that would be reversed by calling reverseTxns(1). * This is useful for showing the operation that would be undone, for example in a menu. */ - public getUndoString(): string { return this._nativeDb.getUndoString(); } + public getUndoString(): string { + return this._nativeDb.getUndoString(); + } /** Get a description of the operation that would be reinstated by calling reinstateTxn. * This is useful for showing the operation that would be redone, in a pull-down menu for example. */ - public getRedoString(): string { return this._nativeDb.getRedoString(); } + public getRedoString(): string { + return this._nativeDb.getRedoString(); + } /** Begin a new multi-Txn operation. This can be used to cause a series of Txns that would normally * be considered separate actions for undo to be grouped into a single undoable operation. This means that when reverseTxns(1) is called, @@ -499,13 +537,19 @@ export class TxnManager { * all changes constitute a single operation. * @note This method must always be paired with a call to endMultiTxnAction. */ - public beginMultiTxnOperation(): DbResult { return this._nativeDb.beginMultiTxnOperation(); } + public beginMultiTxnOperation(): DbResult { + return this._nativeDb.beginMultiTxnOperation(); + } /** End a multi-Txn operation */ - public endMultiTxnOperation(): DbResult { return this._nativeDb.endMultiTxnOperation(); } + public endMultiTxnOperation(): DbResult { + return this._nativeDb.endMultiTxnOperation(); + } /** Return the depth of the multi-Txn stack. Generally for diagnostic use only. */ - public getMultiTxnOperationDepth(): number { return this._nativeDb.getMultiTxnOperationDepth(); } + public getMultiTxnOperationDepth(): number { + return this._nativeDb.getMultiTxnOperationDepth(); + } /** Reverse (undo) the most recent operation(s) to this IModelDb. * @param numOperations the number of operations to reverse. If this is greater than 1, the entire set of operations will @@ -520,62 +564,90 @@ export class TxnManager { } /** Reverse the most recent operation. */ - public reverseSingleTxn(): IModelStatus { return this.reverseTxns(1); } + public reverseSingleTxn(): IModelStatus { + return this.reverseTxns(1); + } /** Reverse all changes back to the beginning of the session. */ - public reverseAll(): IModelStatus { return this._nativeDb.reverseAll(); } + public reverseAll(): IModelStatus { + return this._nativeDb.reverseAll(); + } /** Reverse all changes back to a previously saved TxnId. * @param txnId a TxnId obtained from a previous call to GetCurrentTxnId. * @returns Success if the transactions were reversed, error status otherwise. * @see [[getCurrentTxnId]] [[cancelTo]] */ - public reverseTo(txnId: TxnIdString): IModelStatus { return this._nativeDb.reverseTo(txnId); } + public reverseTo(txnId: TxnIdString): IModelStatus { + return this._nativeDb.reverseTo(txnId); + } /** Reverse and then cancel (make non-reinstatable) all changes back to a previous TxnId. * @param txnId a TxnId obtained from a previous call to [[getCurrentTxnId]] * @returns Success if the transactions were reversed and cleared, error status otherwise. */ - public cancelTo(txnId: TxnIdString): IModelStatus { return this._nativeDb.cancelTo(txnId); } + public cancelTo(txnId: TxnIdString): IModelStatus { + return this._nativeDb.cancelTo(txnId); + } /** Reinstate the most recently reversed transaction. Since at any time multiple transactions can be reversed, it * may take multiple calls to this method to reinstate all reversed operations. * @returns Success if a reversed transaction was reinstated, error status otherwise. * @note If there are any outstanding uncommitted changes, they are canceled before the Txn is reinstated. */ - public reinstateTxn(): IModelStatus { return this._iModel.reinstateTxn(); } + public reinstateTxn(): IModelStatus { + return this._iModel.reinstateTxn(); + } /** Get the Id of the first transaction, if any. */ - public queryFirstTxnId(): TxnIdString { return this._nativeDb.queryFirstTxnId(); } + public queryFirstTxnId(): TxnIdString { + return this._nativeDb.queryFirstTxnId(); + } /** Get the successor of the specified TxnId */ - public queryNextTxnId(txnId: TxnIdString): TxnIdString { return this._nativeDb.queryNextTxnId(txnId); } + public queryNextTxnId(txnId: TxnIdString): TxnIdString { + return this._nativeDb.queryNextTxnId(txnId); + } /** Get the predecessor of the specified TxnId */ - public queryPreviousTxnId(txnId: TxnIdString): TxnIdString { return this._nativeDb.queryPreviousTxnId(txnId); } + public queryPreviousTxnId(txnId: TxnIdString): TxnIdString { + return this._nativeDb.queryPreviousTxnId(txnId); + } /** Get the Id of the current (tip) transaction. */ - public getCurrentTxnId(): TxnIdString { return this._nativeDb.getCurrentTxnId(); } + public getCurrentTxnId(): TxnIdString { + return this._nativeDb.getCurrentTxnId(); + } /** Get the description that was supplied when the specified transaction was saved. */ - public getTxnDescription(txnId: TxnIdString): string { return this._nativeDb.getTxnDescription(txnId); } + public getTxnDescription(txnId: TxnIdString): string { + return this._nativeDb.getTxnDescription(txnId); + } /** Test if a TxnId is valid */ - public isTxnIdValid(txnId: TxnIdString): boolean { return this._nativeDb.isTxnIdValid(txnId); } + public isTxnIdValid(txnId: TxnIdString): boolean { + return this._nativeDb.isTxnIdValid(txnId); + } /** Query if there are any pending Txns in this IModelDb that are waiting to be pushed. */ - public get hasPendingTxns(): boolean { return this._nativeDb.hasPendingTxns(); } + public get hasPendingTxns(): boolean { + return this._nativeDb.hasPendingTxns(); + } /** Query if there are any changes in memory that have yet to be saved to the IModelDb. */ - public get hasUnsavedChanges(): boolean { return this._nativeDb.hasUnsavedChanges(); } + public get hasUnsavedChanges(): boolean { + return this._nativeDb.hasUnsavedChanges(); + } /** Query if there are un-saved or un-pushed local changes. */ - public get hasLocalChanges(): boolean { return this.hasUnsavedChanges || this.hasPendingTxns; } + public get hasLocalChanges(): boolean { + return this.hasUnsavedChanges || this.hasPendingTxns; + } /** Obtain a list of the EC instances that have been changed locally by the [[BriefcaseDb]] associated with this `TxnManager` and have not yet been pushed to the iModel. * @beta - */ + */ public queryLocalChanges(args?: QueryLocalChangesArgs): Iterable { if (!args) { args = { includedClasses: [], includeUnsavedChanges: false }; @@ -583,4 +655,3 @@ export class TxnManager { return this._nativeDb.getLocalChanges(args.includedClasses ?? [], args.includeUnsavedChanges ?? false); } } - diff --git a/core/backend/src/ViewDefinition.ts b/core/backend/src/ViewDefinition.ts index 438bc46c6e13..2d3ae8189df9 100644 --- a/core/backend/src/ViewDefinition.ts +++ b/core/backend/src/ViewDefinition.ts @@ -8,17 +8,44 @@ import { Id64, Id64Array, Id64String, IModelStatus, JsonUtils } from "@itwin/core-bentley"; import { - Angle, Matrix3d, Point2d, Point3d, Range2d, Range3d, StandardViewIndex, Transform, Vector3d, YawPitchRollAngles, -} from "@itwin/core-geometry"; -import { - AuxCoordSystem2dProps, AuxCoordSystem3dProps, AuxCoordSystemProps, BisCodeSpec, Camera, CategorySelectorProps, Code, CodeScopeProps, - CodeSpec, ConcreteEntityTypes, EntityReferenceSet, IModelError, LightLocationProps, ModelSelectorProps, RelatedElement, - SpatialViewDefinitionProps, ViewAttachmentProps, ViewDefinition2dProps, ViewDefinition3dProps, ViewDefinitionProps, ViewDetails, + AuxCoordSystem2dProps, + AuxCoordSystem3dProps, + AuxCoordSystemProps, + BisCodeSpec, + Camera, + CategorySelectorProps, + Code, + CodeScopeProps, + CodeSpec, + ConcreteEntityTypes, + EntityReferenceSet, + IModelError, + LightLocationProps, + ModelSelectorProps, + RelatedElement, + SpatialViewDefinitionProps, + ViewAttachmentProps, + ViewDefinition2dProps, + ViewDefinition3dProps, + ViewDefinitionProps, + ViewDetails, ViewDetails3d, } from "@itwin/core-common"; +import { + Angle, + Matrix3d, + Point2d, + Point3d, + Range2d, + Range3d, + StandardViewIndex, + Transform, + Vector3d, + YawPitchRollAngles, +} from "@itwin/core-geometry"; +import { DisplayStyle, DisplayStyle2d, DisplayStyle3d } from "./DisplayStyle"; import { DefinitionElement, GraphicalElement2d, SpatialLocationElement } from "./Element"; import { IModelDb } from "./IModelDb"; -import { DisplayStyle, DisplayStyle2d, DisplayStyle3d } from "./DisplayStyle"; import { IModelElementCloneContext } from "./IModelElementCloneContext"; /** Holds the list of Ids of GeometricModels displayed by a [[SpatialViewDefinition]]. Multiple SpatialViewDefinitions may point to the same ModelSelector. @@ -27,7 +54,9 @@ import { IModelElementCloneContext } from "./IModelElementCloneContext"; * @public */ export class ModelSelector extends DefinitionElement { - public static override get className(): string { return "ModelSelector"; } + public static override get className(): string { + return "ModelSelector"; + } /** The array of modelIds of the GeometricModels displayed by this ModelSelector */ public models: Id64String[]; @@ -98,7 +127,9 @@ export class ModelSelector extends DefinitionElement { * @public */ export class CategorySelector extends DefinitionElement { - public static override get className(): string { return "CategorySelector"; } + public static override get className(): string { + return "CategorySelector"; + } /** The array of element Ids of the Categories selected by this CategorySelector */ public categories: Id64String[]; @@ -171,7 +202,9 @@ export class CategorySelector extends DefinitionElement { * @public */ export abstract class ViewDefinition extends DefinitionElement { - public static override get className(): string { return "ViewDefinition"; } + public static override get className(): string { + return "ViewDefinition"; + } /** The element Id of the [[CategorySelector]] for this ViewDefinition */ public categorySelectorId: Id64String; /** The element Id of the [[DisplayStyle]] for this ViewDefinition */ @@ -207,7 +240,11 @@ export abstract class ViewDefinition extends DefinitionElement { } /** @beta */ - public static override readonly requiredReferenceKeys: ReadonlyArray = [...super.requiredReferenceKeys, "categorySelectorId", "displayStyleId"]; + public static override readonly requiredReferenceKeys: ReadonlyArray = [ + ...super.requiredReferenceKeys, + "categorySelectorId", + "displayStyleId", + ]; /** @alpha */ public static override readonly requiredReferenceKeyTypeMap: Record = { ...super.requiredReferenceKeyTypeMap, @@ -216,7 +253,11 @@ export abstract class ViewDefinition extends DefinitionElement { }; /** @beta */ - protected static override onCloned(context: IModelElementCloneContext, sourceElementProps: ViewDefinitionProps, targetElementProps: ViewDefinitionProps): void { + protected static override onCloned( + context: IModelElementCloneContext, + sourceElementProps: ViewDefinitionProps, + targetElementProps: ViewDefinitionProps, + ): void { super.onCloned(context, sourceElementProps, targetElementProps); if (context.isBetweenIModels && targetElementProps.jsonProperties && targetElementProps.jsonProperties.viewDetails) { const acsId: Id64String = Id64.fromJSON(targetElementProps.jsonProperties.viewDetails.acs); @@ -227,19 +268,31 @@ export abstract class ViewDefinition extends DefinitionElement { } /** Type guard for `instanceof ViewDefinition3d` */ - public isView3d(): this is ViewDefinition3d { return this instanceof ViewDefinition3d; } + public isView3d(): this is ViewDefinition3d { + return this instanceof ViewDefinition3d; + } /** Type guard for 'instanceof ViewDefinition2d` */ - public isView2d(): this is ViewDefinition2d { return this instanceof ViewDefinition2d; } + public isView2d(): this is ViewDefinition2d { + return this instanceof ViewDefinition2d; + } /** Type guard for `instanceof SpatialViewDefinition` */ - public isSpatialView(): this is SpatialViewDefinition { return this instanceof SpatialViewDefinition; } + public isSpatialView(): this is SpatialViewDefinition { + return this instanceof SpatialViewDefinition; + } /** Type guard for 'instanceof DrawingViewDefinition' */ - public isDrawingView(): this is DrawingViewDefinition { return this instanceof DrawingViewDefinition; } + public isDrawingView(): this is DrawingViewDefinition { + return this instanceof DrawingViewDefinition; + } /** Load this view's DisplayStyle from the IModelDb. */ - public loadDisplayStyle(): DisplayStyle { return this.iModel.elements.getElement(this.displayStyleId); } + public loadDisplayStyle(): DisplayStyle { + return this.iModel.elements.getElement(this.displayStyleId); + } /** Load this view's CategorySelector from the IModelDb. */ - public loadCategorySelector(): CategorySelector { return this.iModel.elements.getElement(this.categorySelectorId); } + public loadCategorySelector(): CategorySelector { + return this.iModel.elements.getElement(this.categorySelectorId); + } /** Provides access to optional detail settings for this view. */ public abstract get details(): ViewDetails; @@ -272,7 +325,9 @@ export abstract class ViewDefinition extends DefinitionElement { */ export abstract class ViewDefinition3d extends ViewDefinition { private readonly _details: ViewDetails3d; - public static override get className(): string { return "ViewDefinition3d"; } + public static override get className(): string { + return "ViewDefinition3d"; + } /** If true, camera is used. Otherwise, use an orthographic projection. */ public cameraOn: boolean; /** The lower left back corner of the view frustum. */ @@ -305,10 +360,14 @@ export abstract class ViewDefinition3d extends ViewDefinition { } /** Provides access to optional detail settings for this view. */ - public get details(): ViewDetails3d { return this._details; } + public get details(): ViewDetails3d { + return this._details; + } /** Load this view's DisplayStyle3d from the IModelDb. */ - public loadDisplayStyle3d(): DisplayStyle3d { return this.iModel.elements.getElement(this.displayStyleId); } + public loadDisplayStyle3d(): DisplayStyle3d { + return this.iModel.elements.getElement(this.displayStyleId); + } } /** Defines a view of one or more SpatialModels. @@ -324,7 +383,9 @@ export abstract class ViewDefinition3d extends ViewDefinition { * @public */ export class SpatialViewDefinition extends ViewDefinition3d { - public static override get className(): string { return "SpatialViewDefinition"; } + public static override get className(): string { + return "SpatialViewDefinition"; + } /** The Id of the [[ModelSelector]] for this SpatialViewDefinition. */ public modelSelectorId: Id64String; @@ -361,7 +422,9 @@ export class SpatialViewDefinition extends ViewDefinition3d { }; /** Load this view's ModelSelector from the IModelDb. */ - public loadModelSelector(): ModelSelector { return this.iModel.elements.getElement(this.modelSelectorId); } + public loadModelSelector(): ModelSelector { + return this.iModel.elements.getElement(this.modelSelectorId); + } /** * Create a SpatialViewDefinition with the camera turned on. * @param iModelDb The iModel @@ -376,14 +439,24 @@ export class SpatialViewDefinition extends ViewDefinition3d { * @returns The newly constructed SpatialViewDefinition element * @throws [[IModelError]] if there is a problem creating the view */ - public static createWithCamera(iModelDb: IModelDb, definitionModelId: Id64String, name: string, modelSelectorId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range3d, standardView = StandardViewIndex.Iso, cameraAngle = Angle.piOver2Radians): SpatialViewDefinition { + public static createWithCamera( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + modelSelectorId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range3d, + standardView = StandardViewIndex.Iso, + cameraAngle = Angle.piOver2Radians, + ): SpatialViewDefinition { const rotation = Matrix3d.createStandardWorldToView(standardView); const angles = YawPitchRollAngles.createFromMatrix3d(rotation); const rotationTransform = Transform.createOriginAndMatrix(undefined, rotation); const rotatedRange = rotationTransform.multiplyRange(range); const cameraDistance = 2 * (rotatedRange.diagonal().magnitudeXY() / 2.0) / Math.tan(cameraAngle / 2.0); - const cameraLocation = rotatedRange.diagonalFractionToPoint(.5); // Start at center. - cameraLocation.z += cameraDistance; // Back up by camera distance. + const cameraLocation = rotatedRange.diagonalFractionToPoint(.5); // Start at center. + cameraLocation.z += cameraDistance; // Back up by camera distance. rotation.multiplyTransposeVectorInPlace(cameraLocation); const viewDefinitionProps: SpatialViewDefinitionProps = { @@ -408,8 +481,28 @@ export class SpatialViewDefinition extends ViewDefinition3d { * @returns The Id of the newly inserted SpatialViewDefinition element * @throws [[IModelError]] if there is an insert problem. */ - public static insertWithCamera(iModelDb: IModelDb, definitionModelId: Id64String, name: string, modelSelectorId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range3d, standardView = StandardViewIndex.Iso, cameraAngle = Angle.piOver2Radians): Id64String { - const viewDefinition = this.createWithCamera(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView, cameraAngle); + public static insertWithCamera( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + modelSelectorId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range3d, + standardView = StandardViewIndex.Iso, + cameraAngle = Angle.piOver2Radians, + ): Id64String { + const viewDefinition = this.createWithCamera( + iModelDb, + definitionModelId, + name, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + standardView, + cameraAngle, + ); return iModelDb.elements.insertElement(viewDefinition.toJSON()); } } @@ -419,9 +512,13 @@ export class SpatialViewDefinition extends ViewDefinition3d { * @public */ export class OrthographicViewDefinition extends SpatialViewDefinition { - public static override get className(): string { return "OrthographicViewDefinition"; } + public static override get className(): string { + return "OrthographicViewDefinition"; + } - constructor(props: SpatialViewDefinitionProps, iModel: IModelDb) { super(props, iModel); } + constructor(props: SpatialViewDefinitionProps, iModel: IModelDb) { + super(props, iModel); + } /** * Create an OrthographicViewDefinition @@ -436,7 +533,16 @@ export class OrthographicViewDefinition extends SpatialViewDefinition { * @returns The newly constructed OrthographicViewDefinition element * @throws [[IModelError]] if there is a problem creating the view */ - public static create(iModelDb: IModelDb, definitionModelId: Id64String, name: string, modelSelectorId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range3d, standardView = StandardViewIndex.Iso): OrthographicViewDefinition { + public static create( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + modelSelectorId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range3d, + standardView = StandardViewIndex.Iso, + ): OrthographicViewDefinition { const rotation = Matrix3d.createStandardWorldToView(standardView); const angles = YawPitchRollAngles.createFromMatrix3d(rotation); const rotationTransform = Transform.createOriginAndMatrix(undefined, rotation); @@ -470,7 +576,16 @@ export class OrthographicViewDefinition extends SpatialViewDefinition { * @returns The Id of the newly inserted OrthographicViewDefinition element * @throws [[IModelError]] if there is an insert problem. */ - public static insert(iModelDb: IModelDb, definitionModelId: Id64String, name: string, modelSelectorId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range3d, standardView = StandardViewIndex.Iso): Id64String { + public static insert( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + modelSelectorId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range3d, + standardView = StandardViewIndex.Iso, + ): Id64String { const viewDefinition = this.create(iModelDb, definitionModelId, name, modelSelectorId, categorySelectorId, displayStyleId, range, standardView); return iModelDb.elements.insertElement(viewDefinition.toJSON()); } @@ -491,7 +606,9 @@ export class OrthographicViewDefinition extends SpatialViewDefinition { export class ViewDefinition2d extends ViewDefinition { private readonly _details: ViewDetails; - public static override get className(): string { return "ViewDefinition2d"; } + public static override get className(): string { + return "ViewDefinition2d"; + } /** The Id of the Model displayed by this view. */ public baseModelId: Id64String; /** The lower-left corner of this view in Model coordinates. */ @@ -525,17 +642,23 @@ export class ViewDefinition2d extends ViewDefinition { } /** Provides access to optional detail settings for this view. */ - public get details(): ViewDetails { return this._details; } + public get details(): ViewDetails { + return this._details; + } /** Load this view's DisplayStyle2d from the IModelDb. */ - public loadDisplayStyle2d(): DisplayStyle2d { return this.iModel.elements.getElement(this.displayStyleId); } + public loadDisplayStyle2d(): DisplayStyle2d { + return this.iModel.elements.getElement(this.displayStyleId); + } } /** Defines a view of a [[DrawingModel]]. * @public */ export class DrawingViewDefinition extends ViewDefinition2d { - public static override get className(): string { return "DrawingViewDefinition"; } + public static override get className(): string { + return "DrawingViewDefinition"; + } protected constructor(props: ViewDefinition2dProps, iModel: IModelDb) { super(props, iModel); @@ -551,7 +674,15 @@ export class DrawingViewDefinition extends ViewDefinition2d { * @param range Defines the view origin and extents * @throws [[IModelError]] if there is a problem creating the element. */ - public static create(iModelDb: IModelDb, definitionModelId: Id64String, name: string, baseModelId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range2d): DrawingViewDefinition { + public static create( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + baseModelId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range2d, + ): DrawingViewDefinition { const viewDefinitionProps: ViewDefinition2dProps = { classFullName: this.classFullName, model: definitionModelId, @@ -581,7 +712,15 @@ export class DrawingViewDefinition extends ViewDefinition2d { * @param range Defines the view origin and extents * @throws [[IModelError]] if there is an insert problem. */ - public static insert(iModelDb: IModelDb, definitionModelId: Id64String, name: string, baseModelId: Id64String, categorySelectorId: Id64String, displayStyleId: Id64String, range: Range2d): Id64String { + public static insert( + iModelDb: IModelDb, + definitionModelId: Id64String, + name: string, + baseModelId: Id64String, + categorySelectorId: Id64String, + displayStyleId: Id64String, + range: Range2d, + ): Id64String { const viewDefinition = this.create(iModelDb, definitionModelId, name, baseModelId, categorySelectorId, displayStyleId, range); return iModelDb.elements.insertElement(viewDefinition.toJSON()); } @@ -591,21 +730,27 @@ export class DrawingViewDefinition extends ViewDefinition2d { * @public */ export class SheetViewDefinition extends ViewDefinition2d { - public static override get className(): string { return "SheetViewDefinition"; } + public static override get className(): string { + return "SheetViewDefinition"; + } } /** A ViewDefinition used to display a 2d template model. * @internal */ export class TemplateViewDefinition2d extends ViewDefinition2d { - public static override get className(): string { return "TemplateViewDefinition2d"; } + public static override get className(): string { + return "TemplateViewDefinition2d"; + } } /** A ViewDefinition used to display a 3d template model. * @internal */ export class TemplateViewDefinition3d extends ViewDefinition3d { - public static override get className(): string { return "TemplateViewDefinition3d"; } + public static override get className(): string { + return "TemplateViewDefinition3d"; + } } /** An auxiliary coordinate system element. Auxiliary coordinate systems can be used by views to show @@ -613,20 +758,28 @@ export class TemplateViewDefinition3d extends ViewDefinition3d { * @public */ export abstract class AuxCoordSystem extends DefinitionElement { - public static override get className(): string { return "AuxCoordSystem"; } + public static override get className(): string { + return "AuxCoordSystem"; + } public type!: number; public description?: string; - public constructor(props: AuxCoordSystemProps, iModel: IModelDb) { super(props, iModel); } + public constructor(props: AuxCoordSystemProps, iModel: IModelDb) { + super(props, iModel); + } } /** A 2d auxiliary coordinate system. * @public */ export class AuxCoordSystem2d extends AuxCoordSystem { - public static override get className(): string { return "AuxCoordSystem2d"; } + public static override get className(): string { + return "AuxCoordSystem2d"; + } public origin?: Point2d; public angle!: number; - public constructor(props: AuxCoordSystem2dProps, iModel: IModelDb) { super(props, iModel); } + public constructor(props: AuxCoordSystem2dProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a AuxCoordSystem2d element given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb @@ -643,12 +796,16 @@ export class AuxCoordSystem2d extends AuxCoordSystem { * @public */ export class AuxCoordSystem3d extends AuxCoordSystem { - public static override get className(): string { return "AuxCoordSystem3d"; } + public static override get className(): string { + return "AuxCoordSystem3d"; + } public origin?: Point3d; public yaw!: number; public pitch!: number; public roll!: number; - public constructor(props: AuxCoordSystem3dProps, iModel: IModelDb) { super(props, iModel); } + public constructor(props: AuxCoordSystem3dProps, iModel: IModelDb) { + super(props, iModel); + } /** Create a Code for a AuxCoordSystem3d element given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb @@ -665,7 +822,9 @@ export class AuxCoordSystem3d extends AuxCoordSystem { * @public */ export class AuxCoordSystemSpatial extends AuxCoordSystem3d { - public static override get className(): string { return "AuxCoordSystemSpatial"; } + public static override get className(): string { + return "AuxCoordSystemSpatial"; + } /** Create a Code for a AuxCoordSystemSpatial element given a name that is meant to be unique within the scope of the specified DefinitionModel. * @param iModel The IModelDb * @param scopeModelId The Id of the DefinitionModel that contains the AuxCoordSystemSpatial element and provides the scope for its name. @@ -681,7 +840,9 @@ export class AuxCoordSystemSpatial extends AuxCoordSystem3d { * @public */ export class ViewAttachment extends GraphicalElement2d { - public static override get className(): string { return "ViewAttachment"; } + public static override get className(): string { + return "ViewAttachment"; + } public view: RelatedElement; public constructor(props: ViewAttachmentProps, iModel: IModelDb) { super(props, iModel); @@ -698,9 +859,13 @@ export class ViewAttachment extends GraphicalElement2d { * @internal */ export class LightLocation extends SpatialLocationElement { - public static override get className(): string { return "LightLocation"; } + public static override get className(): string { + return "LightLocation"; + } /** Whether this light is currently turned on. */ public enabled!: boolean; - protected constructor(props: LightLocationProps, iModel: IModelDb) { super(props, iModel); } + protected constructor(props: LightLocationProps, iModel: IModelDb) { + super(props, iModel); + } } diff --git a/core/backend/src/ViewStateHydrator.ts b/core/backend/src/ViewStateHydrator.ts index f9b0830aa4a1..f3c321e00479 100644 --- a/core/backend/src/ViewStateHydrator.ts +++ b/core/backend/src/ViewStateHydrator.ts @@ -3,7 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { BentleyError, CompressedId64Set, Id64String, Logger } from "@itwin/core-bentley"; -import { HydrateViewStateRequestProps, HydrateViewStateResponseProps, ModelProps, SubCategoryResultRow, ViewAttachmentProps, ViewStateLoadProps } from "@itwin/core-common"; +import { + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + ModelProps, + SubCategoryResultRow, + ViewAttachmentProps, + ViewStateLoadProps, +} from "@itwin/core-common"; import { BackendLoggerCategory } from "./BackendLoggerCategory"; import { IModelDb } from "./IModelDb"; @@ -49,7 +56,11 @@ export class ViewStateHydrator { try { modelProps = this._imodel.models.getModelJson({ id: baseModelId }); } catch (err) { - Logger.logError(BackendLoggerCategory.ViewStateHydrator, `Error getting modelProps for baseModelId: ${baseModelId}`, () => ({error: BentleyError.getErrorProps(err)})); + Logger.logError( + BackendLoggerCategory.ViewStateHydrator, + `Error getting modelProps for baseModelId: ${baseModelId}`, + () => ({ error: BentleyError.getErrorProps(err) }), + ); } response.baseModelProps = modelProps; } @@ -77,15 +88,19 @@ export class ViewStateHydrator { try { const props = this._imodel.elements.getElementProps(acsId); response.acsElementProps = props; - } catch { } + } catch {} } - private async handleSheetViewAttachmentIds(response: HydrateViewStateResponseProps, sheetViewAttachmentIds: CompressedId64Set, viewStateLoadProps?: ViewStateLoadProps) { + private async handleSheetViewAttachmentIds( + response: HydrateViewStateResponseProps, + sheetViewAttachmentIds: CompressedId64Set, + viewStateLoadProps?: ViewStateLoadProps, + ) { const decompressedIds = CompressedId64Set.decompressSet(sheetViewAttachmentIds); const attachmentProps: ViewAttachmentProps[] = []; for (const id of decompressedIds) { try { - attachmentProps.push(this._imodel.elements.getElementJson({ id }) ); + attachmentProps.push(this._imodel.elements.getElementJson({ id })); } catch (error) { } } @@ -109,5 +124,4 @@ export class ViewStateHydrator { return; } - } diff --git a/core/backend/src/ViewStore.ts b/core/backend/src/ViewStore.ts index 2178dbeeba6f..75c0ab60c7f0 100644 --- a/core/backend/src/ViewStore.ts +++ b/core/backend/src/ViewStore.ts @@ -8,19 +8,33 @@ import { CompressedId64Set, GuidString, Id64, Id64Array, Id64String, Logger, MarkRequired, Optional } from "@itwin/core-bentley"; import { - CategorySelectorProps, DisplayStyle3dSettingsProps, DisplayStyleLoadProps, DisplayStyleProps, DisplayStyleSettingsProps, - DisplayStyleSubCategoryProps, ElementProps, IModel, ModelSelectorProps, PlanProjectionSettingsProps, RenderSchedule, - RenderTimelineProps, SpatialViewDefinitionProps, ThumbnailFormatProps, ThumbnailProps, ViewDefinitionProps, ViewStoreRpc, + CategorySelectorProps, + DisplayStyle3dSettingsProps, + DisplayStyleLoadProps, + DisplayStyleProps, + DisplayStyleSettingsProps, + DisplayStyleSubCategoryProps, + ElementProps, + IModel, + ModelSelectorProps, + PlanProjectionSettingsProps, + RenderSchedule, + RenderTimelineProps, + SpatialViewDefinitionProps, + ThumbnailFormatProps, + ThumbnailProps, + ViewDefinitionProps, + ViewStoreRpc, } from "@itwin/core-common"; -import { CloudSqlite } from "./CloudSqlite"; -import { VersionedSqliteDb } from "./SQLiteDb"; -import { SqliteStatement } from "./SqliteStatement"; -import { IModelDb } from "./IModelDb"; +import { BlobContainer } from "./BlobContainerService"; import { Category } from "./Category"; -import { Model } from "./Model"; +import { CloudSqlite } from "./CloudSqlite"; import { Entity } from "./Entity"; -import { BlobContainer } from "./BlobContainerService"; +import { IModelDb } from "./IModelDb"; import { _nativeDb } from "./internal/Symbols"; +import { Model } from "./Model"; +import { VersionedSqliteDb } from "./SQLiteDb"; +import { SqliteStatement } from "./SqliteStatement"; /* eslint-disable @typescript-eslint/no-non-null-assertion */ @@ -75,7 +89,6 @@ import { _nativeDb } from "./internal/Symbols"; * @beta */ export namespace ViewStore { - export const tableName = { categorySelectors: "categorySelectors", displayStyles: "displayStyles", @@ -188,10 +201,18 @@ export namespace ViewStore { public override myVersion = "4.0.0"; private _iModel?: IModelDb; private _guidMap?: IModelDb.GuidMapper; - public get guidMap(): IModelDb.GuidMapper { return this._guidMap!; } - public set guidMap(guidMap: IModelDb.GuidMapper) { this._guidMap = guidMap; } - public get iModel(): IModelDb { return this._iModel!; } - public set iModel(iModel: IModelDb) { this._iModel = iModel; } + public get guidMap(): IModelDb.GuidMapper { + return this._guidMap!; + } + public set guidMap(guidMap: IModelDb.GuidMapper) { + this._guidMap = guidMap; + } + public get iModel(): IModelDb { + return this._iModel!; + } + public set iModel(iModel: IModelDb) { + this._iModel = iModel; + } public constructor(arg?: ViewDbCtorArgs) { super(); @@ -231,9 +252,13 @@ export namespace ViewStore { makeTable(tableName.timelines); makeTable(tableName.tags); makeTable(tableName.searches); - this.createTable({ tableName: tableName.thumbnails, columns: `Id INTEGER PRIMARY KEY REFERENCES ${tableName.views} (Id) ON DELETE CASCADE,json,owner,data BLOB NOT NULL` }); this.createTable({ - tableName: tableName.taggedViews, columns: `viewId INTEGER NOT NULL REFERENCES ${tableName.views} (Id) ON DELETE CASCADE,` + + tableName: tableName.thumbnails, + columns: `Id INTEGER PRIMARY KEY REFERENCES ${tableName.views} (Id) ON DELETE CASCADE,json,owner,data BLOB NOT NULL`, + }); + this.createTable({ + tableName: tableName.taggedViews, + columns: `viewId INTEGER NOT NULL REFERENCES ${tableName.views} (Id) ON DELETE CASCADE,` + `tagId INTEGER NOT NULL REFERENCES ${tableName.tags} (Id) ON DELETE CASCADE`, constraints: `UNIQUE(tagId,viewId)`, }); @@ -280,19 +305,22 @@ export namespace ViewStore { /** @internal */ public addViewRow(args: ViewRow): RowId { validateName(args.name, "view"); - return this.withSqliteStatement(`INSERT INTO ${tableName.views} (className,name,json,owner,private,groupId,modelSel,categorySel,displayStyle) VALUES(?,?,?,?,?,?,?,?,?)`, (stmt) => { - stmt.bindString(1, args.className); - stmt.bindString(2, args.name); - stmt.bindString(3, args.json); - stmt.maybeBindString(4, args.owner); - stmt.bindBoolean(5, args.isPrivate ?? false); - stmt.bindInteger(6, args.groupId ?? 1); - stmt.maybeBindInteger(7, args.modelSel); - stmt.bindInteger(8, args.categorySel); - stmt.bindInteger(9, args.displayStyle); - stmt.stepForWrite(); - return this[_nativeDb].getLastInsertRowId(); - }); + return this.withSqliteStatement( + `INSERT INTO ${tableName.views} (className,name,json,owner,private,groupId,modelSel,categorySel,displayStyle) VALUES(?,?,?,?,?,?,?,?,?)`, + (stmt) => { + stmt.bindString(1, args.className); + stmt.bindString(2, args.name); + stmt.bindString(3, args.json); + stmt.maybeBindString(4, args.owner); + stmt.bindBoolean(5, args.isPrivate ?? false); + stmt.bindInteger(6, args.groupId ?? 1); + stmt.maybeBindInteger(7, args.modelSel); + stmt.bindInteger(8, args.categorySel); + stmt.bindInteger(9, args.displayStyle); + stmt.stepForWrite(); + return this[_nativeDb].getLastInsertRowId(); + }, + ); } /** @internal */ @@ -428,20 +456,23 @@ export namespace ViewStore { * @internal */ public getViewRow(viewId: RowId): undefined | ViewRow { - return this.withSqliteStatement(`SELECT className,name,json,owner,private,groupId,modelSel,categorySel,displayStyle FROM ${tableName.views} WHERE Id=?`, (stmt) => { - stmt.bindInteger(1, viewId); - return !stmt.nextRow() ? undefined : { - className: stmt.getValueString(0), - name: stmt.getValueString(1), - json: stmt.getValueString(2), - owner: stmt.getValueStringMaybe(3), - isPrivate: stmt.getValueBoolean(4), - groupId: stmt.getValueInteger(5), - modelSel: stmt.getValueIntegerMaybe(6), - categorySel: stmt.getValueInteger(7), - displayStyle: stmt.getValueInteger(8), - }; - }); + return this.withSqliteStatement( + `SELECT className,name,json,owner,private,groupId,modelSel,categorySel,displayStyle FROM ${tableName.views} WHERE Id=?`, + (stmt) => { + stmt.bindInteger(1, viewId); + return !stmt.nextRow() ? undefined : { + className: stmt.getValueString(0), + name: stmt.getValueString(1), + json: stmt.getValueString(2), + owner: stmt.getValueStringMaybe(3), + isPrivate: stmt.getValueBoolean(4), + groupId: stmt.getValueInteger(5), + modelSel: stmt.getValueIntegerMaybe(6), + categorySel: stmt.getValueInteger(7), + displayStyle: stmt.getValueInteger(8), + }; + }, + ); } /** @internal */ public getThumbnailRow(viewId: RowId): undefined | ThumbnailRow { @@ -654,22 +685,27 @@ export namespace ViewStore { private getViewInfoSync(id: RowIdOrString): ViewStoreRpc.ViewInfo | undefined { const maybeId = (rowId?: RowId): string | undefined => rowId ? fromRowId(rowId) : undefined; - return this.withPreparedSqliteStatement(`SELECT owner,className,name,private,groupId,modelSel,categorySel,displayStyle FROM ${tableName.views} WHERE id=?`, (stmt) => { - const viewId = toRowId(id); - stmt.bindInteger(1, viewId); - return stmt.nextRow() ? { - id: fromRowId(viewId), - owner: stmt.getValueString(0), - className: stmt.getValueString(1), - name: stmt.getValueStringMaybe(2), - isPrivate: stmt.getValueBoolean(3), - groupId: fromRowId(stmt.getValueInteger(4)), - modelSelectorId: maybeId(stmt.getValueInteger(5)), - categorySelectorId: fromRowId(stmt.getValueInteger(6)), - displayStyleId: fromRowId(stmt.getValueInteger(7)), - tags: this.getTagsForView(viewId), - } : undefined; - }); + return this.withPreparedSqliteStatement( + `SELECT owner,className,name,private,groupId,modelSel,categorySel,displayStyle FROM ${tableName.views} WHERE id=?`, + (stmt) => { + const viewId = toRowId(id); + stmt.bindInteger(1, viewId); + return stmt.nextRow() ? + { + id: fromRowId(viewId), + owner: stmt.getValueString(0), + className: stmt.getValueString(1), + name: stmt.getValueStringMaybe(2), + isPrivate: stmt.getValueBoolean(3), + groupId: fromRowId(stmt.getValueInteger(4)), + modelSelectorId: maybeId(stmt.getValueInteger(5)), + categorySelectorId: fromRowId(stmt.getValueInteger(6)), + displayStyleId: fromRowId(stmt.getValueInteger(7)), + tags: this.getTagsForView(viewId), + } : + undefined; + }, + ); } public async getViewInfo(args: { viewId: RowIdOrString }): Promise { return this.getViewInfoSync(args.viewId); @@ -1005,7 +1041,9 @@ export namespace ViewStore { } return JSON.stringify({ settings, className: args.className }); } - public async addDisplayStyle(args: { name?: string, className: string, settings: DisplayStyleSettingsProps, owner?: string }): Promise { + public async addDisplayStyle( + args: { name?: string, className: string, settings: DisplayStyleSettingsProps, owner?: string }, + ): Promise { const json = this.makeDisplayStyleJson(args); return fromRowId(this.addDisplayStyleRow({ name: args.name, owner: args.owner, json })); } @@ -1084,7 +1122,9 @@ export namespace ViewStore { return viewDef; } - private addViewDefinition(args: { readonly viewDefinition: ViewDefinitionProps, group?: ViewStoreRpc.ViewGroupSpec, owner?: string, isPrivate?: boolean }): RowId { + private addViewDefinition( + args: { readonly viewDefinition: ViewDefinitionProps, group?: ViewStoreRpc.ViewGroupSpec, owner?: string, isPrivate?: boolean }, + ): RowId { const name = args.viewDefinition.code.value; if (name === undefined) throw new Error("ViewDefinition must have a name"); @@ -1241,23 +1281,30 @@ export namespace ViewStore { /** get the array of tags for the specified view. Returns undefined if the view has no tags. */ public getTagsForView(viewId: RowIdOrString): ViewStoreRpc.TagName[] | undefined { const tags: ViewStoreRpc.TagName[] = []; - this.withPreparedSqliteStatement(`SELECT t.name FROM ${tableName.tags} t JOIN ${tableName.taggedViews} v ON t.Id = v.tagId WHERE v.viewId=?`, (stmt) => { - stmt.bindInteger(1, toRowId(viewId)); - while (stmt.nextRow()) - tags.push(stmt.getValueString(0)); - }); + this.withPreparedSqliteStatement( + `SELECT t.name FROM ${tableName.tags} t JOIN ${tableName.taggedViews} v ON t.Id = v.tagId WHERE v.viewId=?`, + (stmt) => { + stmt.bindInteger(1, toRowId(viewId)); + while (stmt.nextRow()) + tags.push(stmt.getValueString(0)); + }, + ); return tags.length === 0 ? undefined : tags; } private iterateViewQuery(queryParams: ViewStoreRpc.QueryParams, callback: (rowId: RowId) => void) { const groupId = queryParams.group ? this.findViewGroup(queryParams.group) : defaultViewGroupId; - let sql = `SELECT Id,className,name,owner,private FROM ${tableName.views} WHERE groupId=? ${queryParams.owner ? " AND (owner=@owner OR private!=1)" : " AND private!=1"}`; + let sql = `SELECT Id,className,name,owner,private FROM ${tableName.views} WHERE groupId=? ${ + queryParams.owner ? " AND (owner=@owner OR private!=1)" : " AND private!=1" + }`; if (queryParams.classNames) sql += ` AND className IN(${queryParams.classNames.map((className) => `'${className}'`).join(",")})`; if (queryParams.nameSearch) sql += ` AND name ${queryParams.nameCompare ?? "="} @name`; if (queryParams.tags) - sql += ` AND Id IN(SELECT viewId FROM ${tableName.taggedViews} WHERE tagId IN(SELECT Id FROM ${tableName.tags} WHERE name IN(${queryParams.tags.map((tag) => `'${tag}'`).join(",")})))`; + sql += ` AND Id IN(SELECT viewId FROM ${tableName.taggedViews} WHERE tagId IN(SELECT Id FROM ${tableName.tags} WHERE name IN(${ + queryParams.tags.map((tag) => `'${tag}'`).join(",") + })))`; sql += " ORDER BY name"; if (queryParams.limit) sql += ` LIMIT ${queryParams.limit} `; @@ -1327,7 +1374,11 @@ export namespace ViewStore { } else { if (args.displayStyleProps === undefined || args.displayStyleProps.jsonProperties?.styles === undefined) throw new Error("Must supply valid displayStyle"); - spatialDef.displayStyleId = await this.addDisplayStyle({ className: args.displayStyleProps.classFullName, settings: args.displayStyleProps.jsonProperties.styles, owner }); + spatialDef.displayStyleId = await this.addDisplayStyle({ + className: args.displayStyleProps.classFullName, + settings: args.displayStyleProps.jsonProperties.styles, + owner, + }); } const viewId = this.addViewDefinition(args); if (args.tags) @@ -1414,6 +1465,5 @@ export namespace ViewStore { await this.initializeDb(props); return props; } - } } diff --git a/core/backend/src/assets/Settings/Schemas/Base.Schema.json b/core/backend/src/assets/Settings/Schemas/Base.Schema.json index 74a1c29ba2e7..3cc7baaaa959 100644 --- a/core/backend/src/assets/Settings/Schemas/Base.Schema.json +++ b/core/backend/src/assets/Settings/Schemas/Base.Schema.json @@ -30,4 +30,4 @@ "description": "An integer value used to sort the schema in a user interface list of multiple schemas, where schemas of lower order are sorted before those with higher order." } } -} \ No newline at end of file +} diff --git a/core/backend/src/assets/Settings/Schemas/Gcs.schema.json b/core/backend/src/assets/Settings/Schemas/Gcs.schema.json index 04394d60235f..c50a1d376b8a 100644 --- a/core/backend/src/assets/Settings/Schemas/Gcs.schema.json +++ b/core/backend/src/assets/Settings/Schemas/Gcs.schema.json @@ -25,4 +25,4 @@ "default": false } } -} \ No newline at end of file +} diff --git a/core/backend/src/assets/Settings/Schemas/Workspace.Schema.json b/core/backend/src/assets/Settings/Schemas/Workspace.Schema.json index c4e5b7bc5633..0b690bb3936a 100644 --- a/core/backend/src/assets/Settings/Schemas/Workspace.Schema.json +++ b/core/backend/src/assets/Settings/Schemas/Workspace.Schema.json @@ -92,4 +92,4 @@ } } } -} \ No newline at end of file +} diff --git a/core/backend/src/core-backend.ts b/core/backend/src/core-backend.ts index 9b1807596383..401d90bddda0 100644 --- a/core/backend/src/core-backend.ts +++ b/core/backend/src/core-backend.ts @@ -62,12 +62,7 @@ export * from "./SheetIndex"; export * from "./SQLiteDb"; export * from "./SqliteStatement"; export * from "./TextAnnotationElement"; -export { - computeGraphemeOffsets, - computeLayoutTextBlockResult, - ComputeGraphemeOffsetsArgs, - LayoutTextBlockArgs, -} from "./TextAnnotationLayout"; +export { computeGraphemeOffsets, ComputeGraphemeOffsetsArgs, computeLayoutTextBlockResult, LayoutTextBlockArgs } from "./TextAnnotationLayout"; export * from "./TextAnnotationGeometry"; export * from "./Texture"; export * from "./TileStorage"; @@ -128,9 +123,9 @@ export * from "./internal/cross-package"; */ /** - * @docs-group-description ExportGraphics - * APIs for producing low-level graphics primitives from element geometry. - */ + * @docs-group-description ExportGraphics + * APIs for producing low-level graphics primitives from element geometry. + */ /** * @docs-group-description HubAccess diff --git a/core/backend/src/domains/FunctionalElements.ts b/core/backend/src/domains/FunctionalElements.ts index 22aef18a321e..e23c06e3ac33 100644 --- a/core/backend/src/domains/FunctionalElements.ts +++ b/core/backend/src/domains/FunctionalElements.ts @@ -8,7 +8,12 @@ import { Id64String } from "@itwin/core-bentley"; import { - FunctionalElementProps, IModel, InformationPartitionElementProps, ModelProps, RelatedElement, TypeDefinitionElementProps, + FunctionalElementProps, + IModel, + InformationPartitionElementProps, + ModelProps, + RelatedElement, + TypeDefinitionElementProps, } from "@itwin/core-common"; import { InformationPartitionElement, RoleElement, TypeDefinitionElement } from "../Element"; import { IModelDb } from "../IModelDb"; @@ -21,7 +26,9 @@ import { DrawingGraphicRepresentsElement, ElementRefersToElements } from "../Rel * @public */ export class FunctionalPartition extends InformationPartitionElement { - public static override get className(): string { return "FunctionalPartition"; } + public static override get className(): string { + return "FunctionalPartition"; + } protected constructor(props: InformationPartitionElementProps, iModel: IModelDb) { super(props, iModel); @@ -32,7 +39,9 @@ export class FunctionalPartition extends InformationPartitionElement { * @public */ export class FunctionalModel extends RoleModel { - public static override get className(): string { return "FunctionalModel"; } + public static override get className(): string { + return "FunctionalModel"; + } public constructor(props: ModelProps, iModel: IModelDb) { super(props, iModel); @@ -64,7 +73,9 @@ export class FunctionalModel extends RoleModel { * @public */ export abstract class FunctionalElement extends RoleElement { - public static override get className(): string { return "FunctionalElement"; } + public static override get className(): string { + return "FunctionalElement"; + } protected constructor(props: FunctionalElementProps, iModel: IModelDb) { super(props, iModel); @@ -75,7 +86,9 @@ export abstract class FunctionalElement extends RoleElement { * @public */ export abstract class FunctionalBreakdownElement extends FunctionalElement { - public static override get className(): string { return "FunctionalBreakdownElement"; } + public static override get className(): string { + return "FunctionalBreakdownElement"; + } protected constructor(props: FunctionalElementProps, iModel: IModelDb) { super(props, iModel); @@ -84,7 +97,9 @@ export abstract class FunctionalBreakdownElement extends FunctionalElement { /** @public */ export class FunctionalComposite extends FunctionalBreakdownElement { - public static override get className(): string { return "FunctionalComposite"; } + public static override get className(): string { + return "FunctionalComposite"; + } protected constructor(props: FunctionalElementProps, iModel: IModelDb) { super(props, iModel); @@ -95,7 +110,9 @@ export class FunctionalComposite extends FunctionalBreakdownElement { * @public */ export abstract class FunctionalComponentElement extends FunctionalElement { - public static override get className(): string { return "FunctionalComponentElement"; } + public static override get className(): string { + return "FunctionalComponentElement"; + } protected constructor(props: FunctionalElementProps, iModel: IModelDb) { super(props, iModel); @@ -106,7 +123,9 @@ export abstract class FunctionalComponentElement extends FunctionalElement { * @public */ export abstract class FunctionalType extends TypeDefinitionElement { - public static override get className(): string { return "FunctionalType"; } + public static override get className(): string { + return "FunctionalType"; + } protected constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); @@ -117,7 +136,9 @@ export abstract class FunctionalType extends TypeDefinitionElement { * @public */ export class FunctionalElementIsOfType extends RelatedElement { - public static get className(): string { return "FunctionalElementIsOfType"; } + public static get className(): string { + return "FunctionalElementIsOfType"; + } public static classFullName = "Functional:FunctionalElementIsOfType"; public constructor(id: Id64String, relClassName: string = FunctionalElementIsOfType.classFullName) { super({ id, relClassName }); @@ -128,12 +149,16 @@ export class FunctionalElementIsOfType extends RelatedElement { * @public */ export class PhysicalElementFulfillsFunction extends ElementRefersToElements { - public static override get className(): string { return "PhysicalElementFulfillsFunction"; } + public static override get className(): string { + return "PhysicalElementFulfillsFunction"; + } } /** Relates a [[DrawingGraphic]] to the [[FunctionalElement]] that it represents * @public */ export class DrawingGraphicRepresentsFunctionalElement extends DrawingGraphicRepresentsElement { - public static override get className(): string { return "DrawingGraphicRepresentsFunctionalElement"; } + public static override get className(): string { + return "DrawingGraphicRepresentsFunctionalElement"; + } } diff --git a/core/backend/src/domains/FunctionalSchema.ts b/core/backend/src/domains/FunctionalSchema.ts index 4b7917a67ebc..1671735fb6a7 100644 --- a/core/backend/src/domains/FunctionalSchema.ts +++ b/core/backend/src/domains/FunctionalSchema.ts @@ -6,20 +6,24 @@ * @module Schema */ -import * as path from "path"; import { DbResult } from "@itwin/core-bentley"; import { IModelError } from "@itwin/core-common"; +import * as path from "path"; import { ClassRegistry } from "../ClassRegistry"; import { IModelDb } from "../IModelDb"; import { KnownLocations } from "../IModelHost"; +import { _nativeDb } from "../internal/Symbols"; import { Schema, Schemas } from "../Schema"; import * as elementsModule from "./FunctionalElements"; -import { _nativeDb } from "../internal/Symbols"; /** @public */ export class FunctionalSchema extends Schema { - public static override get schemaName(): string { return "Functional"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", `${FunctionalSchema.schemaName}.ecschema.xml`); } + public static override get schemaName(): string { + return "Functional"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", `${FunctionalSchema.schemaName}.ecschema.xml`); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); diff --git a/core/backend/src/domains/GenericElements.ts b/core/backend/src/domains/GenericElements.ts index 0698c7b93450..50df3d3c63fe 100644 --- a/core/backend/src/domains/GenericElements.ts +++ b/core/backend/src/domains/GenericElements.ts @@ -8,12 +8,31 @@ import { Id64String } from "@itwin/core-bentley"; import { - CalloutProps, DefinitionElementProps, ElementProps, GeometricElement2dProps, GeometricElement3dProps, GeometricModel3dProps, IModel, - InformationPartitionElementProps, ModelProps, PhysicalElementProps, PhysicalTypeProps, TypeDefinitionElementProps, ViewAttachmentLabelProps, + CalloutProps, + DefinitionElementProps, + ElementProps, + GeometricElement2dProps, + GeometricElement3dProps, + GeometricModel3dProps, + IModel, + InformationPartitionElementProps, + ModelProps, + PhysicalElementProps, + PhysicalTypeProps, + TypeDefinitionElementProps, + ViewAttachmentLabelProps, } from "@itwin/core-common"; import { - Document, GraphicalElement2d, GraphicalElement3d, GraphicalPartition3d, GraphicalType2d, GroupInformationElement, GroupInformationPartition, - PhysicalElement, PhysicalType, SpatialLocationElement, + Document, + GraphicalElement2d, + GraphicalElement3d, + GraphicalPartition3d, + GraphicalType2d, + GroupInformationElement, + GroupInformationPartition, + PhysicalElement, + PhysicalType, + SpatialLocationElement, } from "../Element"; import { IModelDb } from "../IModelDb"; import { PhysicalMaterial } from "../Material"; @@ -24,7 +43,9 @@ import { SubjectOwnsPartitionElements } from "../NavigationRelationship"; * @public */ export abstract class DetailingSymbol extends GraphicalElement2d { - public static override get className(): string { return "DetailingSymbol"; } + public static override get className(): string { + return "DetailingSymbol"; + } public constructor(props: GeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } @@ -34,7 +55,9 @@ export abstract class DetailingSymbol extends GraphicalElement2d { * @public */ export class TitleText extends DetailingSymbol { - public static override get className(): string { return "TitleText"; } + public static override get className(): string { + return "TitleText"; + } public constructor(props: GeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } @@ -44,7 +67,9 @@ export class TitleText extends DetailingSymbol { * @public */ export class ViewAttachmentLabel extends DetailingSymbol { - public static override get className(): string { return "ViewAttachmentLabel"; } + public static override get className(): string { + return "ViewAttachmentLabel"; + } public constructor(props: ViewAttachmentLabelProps, iModel: IModelDb) { super(props, iModel); } @@ -54,7 +79,9 @@ export class ViewAttachmentLabel extends DetailingSymbol { * @public */ export abstract class Callout extends DetailingSymbol { - public static override get className(): string { return "Callout"; } + public static override get className(): string { + return "Callout"; + } public constructor(props: CalloutProps, iModel: IModelDb) { super(props, iModel); } @@ -64,7 +91,9 @@ export abstract class Callout extends DetailingSymbol { * @public */ export class SectionCallout extends Callout { - public static override get className(): string { return "SectionCallout"; } + public static override get className(): string { + return "SectionCallout"; + } public constructor(props: CalloutProps, iModel: IModelDb) { super(props, iModel); } @@ -74,7 +103,9 @@ export class SectionCallout extends Callout { * @public */ export class ElevationCallout extends Callout { - public static override get className(): string { return "ElevationCallout"; } + public static override get className(): string { + return "ElevationCallout"; + } public constructor(props: CalloutProps, iModel: IModelDb) { super(props, iModel); } @@ -84,7 +115,9 @@ export class ElevationCallout extends Callout { * @public */ export class PlanCallout extends Callout { - public static override get className(): string { return "PlanCallout"; } + public static override get className(): string { + return "PlanCallout"; + } public constructor(props: CalloutProps, iModel: IModelDb) { super(props, iModel); } @@ -94,7 +127,9 @@ export class PlanCallout extends Callout { * @public */ export class DetailCallout extends Callout { - public static override get className(): string { return "DetailCallout"; } + public static override get className(): string { + return "DetailCallout"; + } public constructor(props: CalloutProps, iModel: IModelDb) { super(props, iModel); } @@ -104,7 +139,9 @@ export class DetailCallout extends Callout { * @public */ export class GenericGraphicalModel3d extends GraphicalModel3d { - public static override get className(): string { return "GraphicalModel3d"; } + public static override get className(): string { + return "GraphicalModel3d"; + } public constructor(props: GeometricModel3dProps, iModel: IModelDb) { super(props, iModel); } @@ -138,7 +175,9 @@ export class GenericGraphicalModel3d extends GraphicalModel3d { * @public */ export class Graphic3d extends GraphicalElement3d { - public static override get className(): string { return "Graphic3d"; } + public static override get className(): string { + return "Graphic3d"; + } public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } @@ -149,7 +188,9 @@ export class Graphic3d extends GraphicalElement3d { * @public */ export class PhysicalObject extends PhysicalElement { - public static override get className(): string { return "PhysicalObject"; } + public static override get className(): string { + return "PhysicalObject"; + } public constructor(props: PhysicalElementProps, iModel: IModelDb) { super(props, iModel); } @@ -160,7 +201,9 @@ export class PhysicalObject extends PhysicalElement { * @public */ export class SpatialLocation extends SpatialLocationElement { - public static override get className(): string { return "SpatialLocation"; } + public static override get className(): string { + return "SpatialLocation"; + } public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } @@ -170,7 +213,9 @@ export class SpatialLocation extends SpatialLocationElement { * @public */ export class GroupModel extends GroupInformationModel { - public static override get className(): string { return "GroupModel"; } + public static override get className(): string { + return "GroupModel"; + } public constructor(props: ModelProps, iModel: IModelDb) { super(props, iModel); } @@ -200,7 +245,9 @@ export class GroupModel extends GroupInformationModel { * @public */ export class Group extends GroupInformationElement { - public static override get className(): string { return "Group"; } + public static override get className(): string { + return "Group"; + } public constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } @@ -211,7 +258,9 @@ export class Group extends GroupInformationElement { * @public */ export class GenericDocument extends Document { - public static override get className(): string { return "Document"; } + public static override get className(): string { + return "Document"; + } public constructor(props: ElementProps, iModel: IModelDb) { super(props, iModel); } @@ -222,7 +271,9 @@ export class GenericDocument extends Document { * @public */ export class GenericPhysicalMaterial extends PhysicalMaterial { - public static override get className(): string { return "PhysicalMaterial"; } + public static override get className(): string { + return "PhysicalMaterial"; + } public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } @@ -233,7 +284,9 @@ export class GenericPhysicalMaterial extends PhysicalMaterial { * @public */ export class GenericPhysicalType extends PhysicalType { - public static override get className(): string { return "PhysicalType"; } + public static override get className(): string { + return "PhysicalType"; + } public constructor(props: PhysicalTypeProps, iModel: IModelDb) { super(props, iModel); } @@ -244,7 +297,9 @@ export class GenericPhysicalType extends PhysicalType { * @public */ export class GenericGraphicalType2d extends GraphicalType2d { - public static override get className(): string { return "GraphicalType2d"; } + public static override get className(): string { + return "GraphicalType2d"; + } public constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); } diff --git a/core/backend/src/domains/GenericSchema.ts b/core/backend/src/domains/GenericSchema.ts index 2fe1794acae1..c89539f02a80 100644 --- a/core/backend/src/domains/GenericSchema.ts +++ b/core/backend/src/domains/GenericSchema.ts @@ -14,8 +14,12 @@ import * as elementsModule from "./GenericElements"; /** @public */ export class GenericSchema extends Schema { - public static override get schemaName(): string { return "Generic"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Dgn", `${GenericSchema.schemaName}.ecschema.xml`); } + public static override get schemaName(): string { + return "Generic"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Dgn", `${GenericSchema.schemaName}.ecschema.xml`); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); diff --git a/core/backend/src/internal/ChangesetConflictArgs.ts b/core/backend/src/internal/ChangesetConflictArgs.ts index 35528031101f..01b7e4bbf2b9 100644 --- a/core/backend/src/internal/ChangesetConflictArgs.ts +++ b/core/backend/src/internal/ChangesetConflictArgs.ts @@ -28,4 +28,3 @@ export interface ChangesetConflictArgs { getValueDouble: (columnIndex: number, stage: DbChangeStage) => number | null | undefined; isValueNull: (columnIndex: number, stage: DbChangeStage) => boolean | undefined; } - diff --git a/core/backend/src/internal/ChannelAdmin.ts b/core/backend/src/internal/ChannelAdmin.ts index 79791b6c45b7..9eddaa4fb46b 100644 --- a/core/backend/src/internal/ChannelAdmin.ts +++ b/core/backend/src/internal/ChannelAdmin.ts @@ -8,10 +8,10 @@ import { DbResult, Id64String, IModelStatus } from "@itwin/core-bentley"; import { ChannelRootAspectProps, IModel, IModelError } from "@itwin/core-common"; +import { ChannelControl, ChannelKey } from "../ChannelControl"; import { Subject } from "../Element"; import { IModelDb } from "../IModelDb"; import { IModelHost } from "../IModelHost"; -import { ChannelControl, ChannelKey } from "../ChannelControl"; import { _implementationProhibited, _nativeDb, _verifyChannel } from "./Symbols"; class ChannelAdmin implements ChannelControl { @@ -125,7 +125,6 @@ class ChannelAdmin implements ChannelControl { // In that case all data in such iModel is assumed to be in the shared channel. return undefined; } - } } diff --git a/core/backend/src/internal/NativePlatform.ts b/core/backend/src/internal/NativePlatform.ts index 7e1bae5e4672..5b82e20e9700 100644 --- a/core/backend/src/internal/NativePlatform.ts +++ b/core/backend/src/internal/NativePlatform.ts @@ -37,7 +37,9 @@ export class IModelNative { /** @internal Strictly to be called by IModelHost.startup. */ export function loadNativePlatform(): void { if (undefined === nativePlatform) { - nativePlatform = ProcessDetector.isMobileAppBackend ? (process as any)._linkedBinding("iModelJsNative") as typeof IModelJsNative : NativeLibrary.load(); + nativePlatform = ProcessDetector.isMobileAppBackend + ? (process as any)._linkedBinding("iModelJsNative") as typeof IModelJsNative + : NativeLibrary.load(); nativePlatform.logger = Logger; Logger.onLogLevelChanged.addListener(() => syncNativeLogLevels()); } diff --git a/core/backend/src/internal/NoLocks.ts b/core/backend/src/internal/NoLocks.ts index 857703a43375..aa1f267656c7 100644 --- a/core/backend/src/internal/NoLocks.ts +++ b/core/backend/src/internal/NoLocks.ts @@ -13,17 +13,23 @@ import { _close, _elementWasCreated, _implementationProhibited, _releaseAllLocks /** A null-implementation of LockControl that does not attempt to limit access between briefcases. This relies on change-merging to resolve conflicts. */ class NoLocks implements LockControl { public readonly [_implementationProhibited] = undefined; - public get isServerBased() { return false; } - public [_close](): void { } - public clearAllLocks(): void { } - public holdsExclusiveLock(): boolean { return false; } - public holdsSharedLock(): boolean { return false; } - public checkExclusiveLock(): void { } - public checkSharedLock(): void { } - public [_elementWasCreated](): void { } - public async acquireLocks() { } - public async [_releaseAllLocks](): Promise { } - public async releaseAllLocks(): Promise { } + public get isServerBased() { + return false; + } + public [_close](): void {} + public clearAllLocks(): void {} + public holdsExclusiveLock(): boolean { + return false; + } + public holdsSharedLock(): boolean { + return false; + } + public checkExclusiveLock(): void {} + public checkSharedLock(): void {} + public [_elementWasCreated](): void {} + public async acquireLocks() {} + public async [_releaseAllLocks](): Promise {} + public async releaseAllLocks(): Promise {} } export function createNoOpLockControl(): LockControl { diff --git a/core/backend/src/internal/ServerBasedLocks.ts b/core/backend/src/internal/ServerBasedLocks.ts index 2a14c356b5cc..96fec0714f0e 100644 --- a/core/backend/src/internal/ServerBasedLocks.ts +++ b/core/backend/src/internal/ServerBasedLocks.ts @@ -11,8 +11,8 @@ import { DbResult, Id64, Id64Arg, Id64String, IModelStatus, OpenMode } from "@it import { IModel, IModelError, LockState } from "@itwin/core-common"; import { LockMap } from "../BackendHubAccess"; import { BriefcaseDb } from "../IModelDb"; -import { LockControl } from "../LockControl"; import { IModelHost } from "../IModelHost"; +import { LockControl } from "../LockControl"; import { SQLiteDb } from "../SQLiteDb"; import { _close, _elementWasCreated, _implementationProhibited, _nativeDb, _releaseAllLocks } from "./Symbols"; @@ -36,7 +36,9 @@ const enum LockOrigin { export class ServerBasedLocks implements LockControl { public readonly [_implementationProhibited] = undefined; - public get isServerBased() { return true; } + public get isServerBased() { + return true; + } protected readonly lockDb = new SQLiteDb(); protected readonly briefcase: BriefcaseDb; @@ -69,10 +71,12 @@ export class ServerBasedLocks implements LockControl { } private getLockState(id?: Id64String): LockState | undefined { - return (id === undefined || !Id64.isValid(id)) ? undefined : this.lockDb.withPreparedSqliteStatement("SELECT state FROM locks WHERE id=?", (stmt) => { - stmt.bindId(1, id); - return (DbResult.BE_SQLITE_ROW === stmt.step()) ? stmt.getValueInteger(0) : undefined; - }); + return (id === undefined || !Id64.isValid(id)) ? + undefined : + this.lockDb.withPreparedSqliteStatement("SELECT state FROM locks WHERE id=?", (stmt) => { + stmt.bindId(1, id); + return (DbResult.BE_SQLITE_ROW === stmt.step()) ? stmt.getValueInteger(0) : undefined; + }); } /** Clear the cache of locally held locks. @@ -106,14 +110,17 @@ export class ServerBasedLocks implements LockControl { } private insertLock(id: Id64String, state: LockState, origin: LockOrigin): true { - this.lockDb.withPreparedSqliteStatement("INSERT INTO locks(id,state,origin) VALUES (?,?,?) ON CONFLICT(id) DO UPDATE SET state=excluded.state,origin=excluded.origin", (stmt) => { - stmt.bindId(1, id); - stmt.bindInteger(2, state); - stmt.bindInteger(3, origin); - const rc = stmt.step(); - if (DbResult.BE_SQLITE_DONE !== rc) - throw new IModelError(rc, "can't insert lock into database"); - }); + this.lockDb.withPreparedSqliteStatement( + "INSERT INTO locks(id,state,origin) VALUES (?,?,?) ON CONFLICT(id) DO UPDATE SET state=excluded.state,origin=excluded.origin", + (stmt) => { + stmt.bindId(1, id); + stmt.bindInteger(2, state); + stmt.bindInteger(3, origin); + const rc = stmt.step(); + if (DbResult.BE_SQLITE_DONE !== rc) + throw new IModelError(rc, "can't insert lock into database"); + }, + ); return true; } @@ -207,7 +214,9 @@ export class ServerBasedLocks implements LockControl { } /** locks are not necessary during change propagation. */ - private get _locksAreRequired() { return !this.briefcase.txns.isIndirectChanges; } + private get _locksAreRequired() { + return !this.briefcase.txns.isIndirectChanges; + } /** throw if locks are currently required and the exclusive lock is not held on the supplied element */ public checkExclusiveLock(id: Id64String, type: string, operation: string) { @@ -220,7 +229,6 @@ export class ServerBasedLocks implements LockControl { if (this._locksAreRequired && !this.holdsSharedLock(id)) throw new IModelError(IModelStatus.LockNotHeld, `shared lock not held on ${type} for ${operation} (id=${id})`); } - } export function createServerBasedLocks(iModel: BriefcaseDb): LockControl { diff --git a/core/backend/src/internal/cross-package.ts b/core/backend/src/internal/cross-package.ts index 5c39d899bb11..67f6af46b84c 100644 --- a/core/backend/src/internal/cross-package.ts +++ b/core/backend/src/internal/cross-package.ts @@ -5,6 +5,4 @@ export { IModelJsNative, NativeCloudSqlite, NativeLoggerCategory } from "@bentley/imodeljs-native"; export { IModelNative } from "./NativePlatform"; -export { - _nativeDb, -} from "./Symbols"; +export { _nativeDb } from "./Symbols"; diff --git a/core/backend/src/internal/workspace/SettingsImpl.ts b/core/backend/src/internal/workspace/SettingsImpl.ts index 2dc7b83cc9c0..ae41d2befc09 100644 --- a/core/backend/src/internal/workspace/SettingsImpl.ts +++ b/core/backend/src/internal/workspace/SettingsImpl.ts @@ -6,14 +6,23 @@ * @module Workspace */ +import { BeEvent } from "@itwin/core-bentley"; +import { LocalDirName, LocalFileName } from "@itwin/core-common"; import * as fs from "fs-extra"; import { parse } from "json5"; import { extname, join } from "path"; -import { BeEvent } from "@itwin/core-bentley"; -import { LocalDirName, LocalFileName } from "@itwin/core-common"; -import { IModelJsFs } from "../../IModelJsFs"; -import { Setting, SettingName, Settings, SettingsContainer, SettingsDictionary, SettingsDictionaryProps, SettingsDictionarySource, SettingsPriority } from "../../workspace/Settings"; import { IModelHost } from "../../IModelHost"; +import { IModelJsFs } from "../../IModelJsFs"; +import { + Setting, + SettingName, + Settings, + SettingsContainer, + SettingsDictionary, + SettingsDictionaryProps, + SettingsDictionarySource, + SettingsPriority, +} from "../../workspace/Settings"; import { _implementationProhibited } from "../Symbols"; const dictionaryMatches = (d1: SettingsDictionarySource, d2: SettingsDictionarySource): boolean => { @@ -43,8 +52,8 @@ class SettingsDictionaryImpl implements SettingsDictionary { export class SettingsImpl implements Settings { public readonly [_implementationProhibited] = undefined; public dictionaries: SettingsDictionary[] = []; - protected verifyPriority(_priority: SettingsPriority) { } - public close() { } + protected verifyPriority(_priority: SettingsPriority) {} + public close() {} public readonly onSettingsChanged = new BeEvent<() => void>(); public addFile(fileName: LocalFileName, priority: SettingsPriority) { @@ -100,7 +109,7 @@ export class SettingsImpl implements Settings { return false; } - public * getSettingEntries(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary}> { + public *getSettingEntries(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary }> { for (const dictionary of this.dictionaries) { const value = dictionary.getSetting(settingName); if (undefined !== value) { @@ -109,7 +118,7 @@ export class SettingsImpl implements Settings { } } - public * getSettingValues(settingName: SettingName): Iterable { + public *getSettingValues(settingName: SettingName): Iterable { for (const entry of this.getSettingEntries(settingName)) { yield entry.value; } diff --git a/core/backend/src/internal/workspace/SettingsSchemasImpl.ts b/core/backend/src/internal/workspace/SettingsSchemasImpl.ts index ecac6a959a7f..67cbabf8e75f 100644 --- a/core/backend/src/internal/workspace/SettingsSchemasImpl.ts +++ b/core/backend/src/internal/workspace/SettingsSchemasImpl.ts @@ -6,11 +6,11 @@ * @module Workspace */ +import { assert, BeEvent, JSONSchemaType, JSONSchemaTypeName, Mutable } from "@itwin/core-bentley"; +import { LocalDirName, LocalFileName } from "@itwin/core-common"; import * as fs from "fs-extra"; import { parse } from "json5"; import { extname, join } from "path"; -import { assert, BeEvent, JSONSchemaType, JSONSchemaTypeName, Mutable } from "@itwin/core-bentley"; -import { LocalDirName, LocalFileName } from "@itwin/core-common"; import { IModelJsFs } from "../../IModelJsFs"; import { SettingGroupSchema, SettingSchema, SettingsSchemas } from "../../workspace/SettingsSchemas"; import { _implementationProhibited } from "../Symbols"; @@ -48,7 +48,10 @@ class SettingsSchemasImpl implements SettingsSchemas { } /** @internal */ - public getObjectProperties(propDef: Readonly, scope: string): { required?: string[], properties: { [name: string]: SettingSchema } } { + public getObjectProperties( + propDef: Readonly, + scope: string, + ): { required?: string[], properties: { [name: string]: SettingSchema } } { let required = propDef.required; let properties = propDef.properties; diff --git a/core/backend/src/internal/workspace/WorkspaceImpl.ts b/core/backend/src/internal/workspace/WorkspaceImpl.ts index be97919ca769..8e1c5a5d0caf 100644 --- a/core/backend/src/internal/workspace/WorkspaceImpl.ts +++ b/core/backend/src/internal/workspace/WorkspaceImpl.ts @@ -6,28 +6,51 @@ * @module Workspace */ +import type { IModelJsNative } from "@bentley/imodeljs-native"; +import { AccessToken, assert, BeEvent, DbResult, Mutable, OpenMode } from "@itwin/core-bentley"; +import { FilePropertyProps, IModelError, LocalDirName, LocalFileName } from "@itwin/core-common"; import { createHash } from "crypto"; import * as fs from "fs-extra"; import { dirname, extname, join } from "path"; import * as semver from "semver"; -import { AccessToken, assert, BeEvent, DbResult, Mutable, OpenMode } from "@itwin/core-bentley"; -import { FilePropertyProps, IModelError, LocalDirName, LocalFileName } from "@itwin/core-common"; import { CloudSqlite } from "../../CloudSqlite"; import { IModelHost, KnownLocations } from "../../IModelHost"; import { IModelJsFs } from "../../IModelJsFs"; import { SQLiteDb } from "../../SQLiteDb"; import { SqliteStatement } from "../../SqliteStatement"; import { SettingName, Settings, SettingsContainer, SettingsDictionaryProps, SettingsPriority } from "../../workspace/Settings"; -import type { IModelJsNative } from "@bentley/imodeljs-native"; import { - GetWorkspaceContainerArgs, Workspace, WorkspaceContainer, WorkspaceContainerId, WorkspaceContainerProps, WorkspaceDb, WorkspaceDbCloudProps, - WorkspaceDbFullName, WorkspaceDbLoadError, WorkspaceDbLoadErrors, WorkspaceDbManifest, WorkspaceDbName, WorkspaceDbNameAndVersion, WorkspaceDbProps, - WorkspaceDbQueryResourcesArgs, WorkspaceDbSettingsProps, WorkspaceDbVersion, WorkspaceOpts, WorkspaceResourceName, WorkspaceSettingNames, + GetWorkspaceContainerArgs, + Workspace, + WorkspaceContainer, + WorkspaceContainerId, + WorkspaceContainerProps, + WorkspaceDb, + WorkspaceDbCloudProps, + WorkspaceDbFullName, + WorkspaceDbLoadError, + WorkspaceDbLoadErrors, + WorkspaceDbManifest, + WorkspaceDbName, + WorkspaceDbNameAndVersion, + WorkspaceDbProps, + WorkspaceDbQueryResourcesArgs, + WorkspaceDbSettingsProps, + WorkspaceDbVersion, + WorkspaceOpts, + WorkspaceResourceName, + WorkspaceSettingNames, } from "../../workspace/Workspace"; -import { CreateNewWorkspaceContainerArgs, CreateNewWorkspaceDbVersionArgs, EditableWorkspaceContainer, EditableWorkspaceDb, WorkspaceEditor } from "../../workspace/WorkspaceEditor"; -import { WorkspaceSqliteDb } from "./WorkspaceSqliteDb"; -import { SettingsImpl } from "./SettingsImpl"; +import { + CreateNewWorkspaceContainerArgs, + CreateNewWorkspaceDbVersionArgs, + EditableWorkspaceContainer, + EditableWorkspaceDb, + WorkspaceEditor, +} from "../../workspace/WorkspaceEditor"; import { _implementationProhibited, _nativeDb } from "../Symbols"; +import { SettingsImpl } from "./SettingsImpl"; +import { WorkspaceSqliteDb } from "./WorkspaceSqliteDb"; function workspaceDbNameWithDefault(dbName?: WorkspaceDbName): WorkspaceDbName { return dbName ?? "workspace-db"; @@ -66,7 +89,7 @@ function getWorkspaceCloudContainer(props: CloudSqlite.ContainerAccessProps, cac cloudContainer = CloudSqlite.createCloudContainer(props) as WorkspaceCloudContainer; cache.workspaceContainers.set(id, cloudContainer); cloudContainer.connectCount = 0; - cloudContainer.sharedConnect = function (this: WorkspaceCloudContainer) { + cloudContainer.sharedConnect = function(this: WorkspaceCloudContainer) { if (this.connectCount++ === 0) { this.connect(cache); return true; @@ -75,7 +98,7 @@ function getWorkspaceCloudContainer(props: CloudSqlite.ContainerAccessProps, cac return false; }; - cloudContainer.sharedDisconnect = function (this: WorkspaceCloudContainer) { + cloudContainer.sharedDisconnect = function(this: WorkspaceCloudContainer) { if (--this.connectCount <= 0) { this.disconnect(); cache.workspaceContainers.delete(id); @@ -99,7 +122,9 @@ class WorkspaceContainerImpl implements WorkspaceContainer { } protected _wsDbs = new Map(); - public get dirName() { return join(this.workspace.containerDir, this.id); } + public get dirName() { + return join(this.workspace.containerDir, this.id); + } public constructor(workspace: WorkspaceImpl, props: WorkspaceContainerProps & { accessToken: AccessToken }) { validateWorkspaceContainerId(props.containerId); @@ -193,8 +218,12 @@ class WorkspaceDbImpl implements WorkspaceDb { protected _manifest?: WorkspaceDbManifest; /** true if this WorkspaceDb is currently open */ - public get isOpen() { return this.sqliteDb.isOpen; } - public get container(): WorkspaceContainer { return this._container; } + public get isOpen() { + return this.sqliteDb.isOpen; + } + public get container(): WorkspaceContainer { + return this._container; + } public queryFileResource(rscName: WorkspaceResourceName): { localFileName: LocalFileName, info: IModelJsNative.EmbedFileQuery } | undefined { const info = this.sqliteDb[_nativeDb].queryEmbeddedFile(rscName); if (undefined === info) @@ -243,7 +272,7 @@ class WorkspaceDbImpl implements WorkspaceDb { } private withOpenDb(operation: (db: WorkspaceSqliteDb) => T): T { - const done = this.isOpen ? () => { } : (this.open(), () => this.close()); + const done = this.isOpen ? () => {} : (this.open(), () => this.close()); try { return operation(this.sqliteDb); } finally { @@ -371,7 +400,9 @@ class WorkspaceImpl implements Workspace { } public async getContainerAsync(props: WorkspaceContainerProps): Promise { - const accessToken = props.accessToken ?? ((props.baseUri === "") || props.isPublic) ? "" : await CloudSqlite.requestToken({ ...props, accessLevel: "read" }); + const accessToken = props.accessToken ?? ((props.baseUri === "") || props.isPublic) + ? "" + : await CloudSqlite.requestToken({ ...props, accessLevel: "read" }); return this.getContainer({ ...props, accessToken }); } @@ -398,7 +429,11 @@ class WorkspaceImpl implements Workspace { if (undefined === this.settings.getDictionary(dictProps)) { const settingsJson = db.getString(prop.resourceName); if (undefined === settingsJson) - throwWorkspaceDbLoadError(`could not load setting dictionary resource '${prop.resourceName}' from: '${manifest.workspaceName}'`, prop, db); + throwWorkspaceDbLoadError( + `could not load setting dictionary resource '${prop.resourceName}' from: '${manifest.workspaceName}'`, + prop, + db, + ); db.close(); // don't leave this db open in case we're going to find another dictionary in it recursively. @@ -448,7 +483,9 @@ class WorkspaceImpl implements Workspace { return result; } - public async getWorkspaceDbs(args: Workspace.DbListOrSettingName & { filter?: Workspace.DbListFilter, problems?: WorkspaceDbLoadError[] }): Promise { + public async getWorkspaceDbs( + args: Workspace.DbListOrSettingName & { filter?: Workspace.DbListFilter, problems?: WorkspaceDbLoadError[] }, + ): Promise { const dbList = (args.settingName !== undefined) ? this.resolveWorkspaceDbSetting(args.settingName, args.filter) : args.dbs; const result: WorkspaceDb[] = []; const pushUnique = (wsDb: WorkspaceDb) => { @@ -506,7 +543,8 @@ class EditorImpl implements WorkspaceEditor { } public getContainer(props: GetWorkspaceContainerArgs): EditableWorkspaceContainer { - return this.workspace.findContainer(props.containerId) as EditableWorkspaceContainer | undefined ?? new EditorContainerImpl(this.workspace, props); + return this.workspace.findContainer(props.containerId) as EditableWorkspaceContainer | undefined ?? + new EditorContainerImpl(this.workspace, props); } public async getContainerAsync(props: WorkspaceContainerProps): Promise { const accessToken = props.accessToken ?? (props.baseUri === "") ? "" : await CloudSqlite.requestToken({ ...props, accessLevel: "write" }); @@ -519,7 +557,7 @@ class EditorImpl implements WorkspaceEditor { } interface EditCloudContainer extends WorkspaceCloudContainer { - writeLockHeldBy?: string; // added by acquireWriteLock + writeLockHeldBy?: string; // added by acquireWriteLock } class EditorContainerImpl extends WorkspaceContainerImpl implements EditableWorkspaceContainer { @@ -539,7 +577,9 @@ class EditorContainerImpl extends WorkspaceContainerImpl implements EditableWork }; } - public async createNewWorkspaceDbVersion(args: CreateNewWorkspaceDbVersionArgs): Promise<{ oldDb: WorkspaceDbNameAndVersion, newDb: WorkspaceDbNameAndVersion }> { + public async createNewWorkspaceDbVersion( + args: CreateNewWorkspaceDbVersionArgs, + ): Promise<{ oldDb: WorkspaceDbNameAndVersion, newDb: WorkspaceDbNameAndVersion }> { const cloudContainer = this.cloudContainer; if (undefined === cloudContainer) throw new Error("versions require cloud containers"); @@ -602,7 +642,10 @@ class EditorContainerImpl extends WorkspaceContainerImpl implements EditableWork IModelJsFs.removeSync(tempDbFile); WorkspaceEditor.createEmptyDb({ localFileName: tempDbFile, manifest: args.manifest }); - await CloudSqlite.uploadDb(this.cloudContainer, { localFileName: tempDbFile, dbName: makeWorkspaceDbFileName(workspaceDbNameWithDefault(args.dbName)) }); + await CloudSqlite.uploadDb(this.cloudContainer, { + localFileName: tempDbFile, + dbName: makeWorkspaceDbFileName(workspaceDbNameWithDefault(args.dbName)), + }); IModelJsFs.removeSync(tempDbFile); } @@ -690,7 +733,11 @@ class EditableDbImpl extends WorkspaceDbImpl implements EditableWorkspaceDb { } public updateString(rscName: WorkspaceResourceName, val: string): void { this.validateResourceSize(val); - this.performWriteSql(rscName, "INSERT INTO strings(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", (stmt) => stmt.bindString(2, val)); + this.performWriteSql( + rscName, + "INSERT INTO strings(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", + (stmt) => stmt.bindString(2, val), + ); } public removeString(rscName: WorkspaceResourceName): void { this.performWriteSql(rscName, "DELETE FROM strings WHERE id=?"); @@ -702,7 +749,11 @@ class EditableDbImpl extends WorkspaceDbImpl implements EditableWorkspaceDb { } public updateBlob(rscName: WorkspaceResourceName, val: Uint8Array): void { this.validateResourceSize(val); - this.performWriteSql(rscName, "INSERT INTO blobs(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", (stmt) => stmt.bindBlob(2, val)); + this.performWriteSql( + rscName, + "INSERT INTO blobs(id,value) VALUES(?,?) ON CONFLICT(id) DO UPDATE SET value=excluded.value WHERE value!=excluded.value", + (stmt) => stmt.bindBlob(2, val), + ); } public getBlobWriter(rscName: WorkspaceResourceName): SQLiteDb.BlobIO { return this.sqliteDb.withSqliteStatement("SELECT rowid from blobs WHERE id=?", (stmt) => { diff --git a/core/backend/src/internal/workspace/WorkspaceSqliteDb.ts b/core/backend/src/internal/workspace/WorkspaceSqliteDb.ts index e40e45edc77a..5b754cd74e27 100644 --- a/core/backend/src/internal/workspace/WorkspaceSqliteDb.ts +++ b/core/backend/src/internal/workspace/WorkspaceSqliteDb.ts @@ -26,7 +26,9 @@ export class WorkspaceSqliteDb extends VersionedSqliteDb { this.executeSQL(`CREATE TABLE strings(id TEXT PRIMARY KEY NOT NULL,value TEXT,${timeStampCol})`); this.executeSQL(`CREATE TABLE blobs(id TEXT PRIMARY KEY NOT NULL,value BLOB,${timeStampCol})`); const createTrigger = (tableName: string) => { - this.executeSQL(`CREATE TRIGGER ${tableName}_timeStamp AFTER UPDATE ON ${tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${tableName} SET lastMod=julianday('now') WHERE id=new.id; END`); + this.executeSQL( + `CREATE TRIGGER ${tableName}_timeStamp AFTER UPDATE ON ${tableName} WHEN old.lastMod=new.lastMod AND old.lastMod != julianday('now') BEGIN UPDATE ${tableName} SET lastMod=julianday('now') WHERE id=new.id; END`, + ); }; createTrigger("strings"); createTrigger("blobs"); @@ -34,4 +36,3 @@ export class WorkspaceSqliteDb extends VersionedSqliteDb { this[_nativeDb].saveFileProperty(workspaceManifestProperty, JSON.stringify(args.manifest)); } } - diff --git a/core/backend/src/linebreak.d.ts b/core/backend/src/linebreak.d.ts index 2af2ec6c3abd..78fd578a1dbf 100644 --- a/core/backend/src/linebreak.d.ts +++ b/core/backend/src/linebreak.d.ts @@ -10,4 +10,3 @@ declare module "linebreak" { public nextBreak(): { position: number, required: boolean }; } } - diff --git a/core/backend/src/rpc-impl/DevToolsRpcImpl.ts b/core/backend/src/rpc-impl/DevToolsRpcImpl.ts index ed5f75c570cd..48132b60fc4e 100644 --- a/core/backend/src/rpc-impl/DevToolsRpcImpl.ts +++ b/core/backend/src/rpc-impl/DevToolsRpcImpl.ts @@ -13,7 +13,9 @@ import { DevTools, DevToolsStatsFormatter } from "../DevTools"; * @internal */ export class DevToolsRpcImpl extends RpcInterface implements DevToolsRpcInterface { // eslint-disable-line deprecation/deprecation - public static register() { RpcManager.registerImpl(DevToolsRpcInterface, DevToolsRpcImpl); } + public static register() { + RpcManager.registerImpl(DevToolsRpcInterface, DevToolsRpcImpl); + } // Returns true if the backend received the ping public async ping(_tokenProps: IModelRpcProps): Promise { diff --git a/core/backend/src/rpc-impl/IModelReadRpcImpl.ts b/core/backend/src/rpc-impl/IModelReadRpcImpl.ts index a9fc93bc624a..042fd9f540bd 100644 --- a/core/backend/src/rpc-impl/IModelReadRpcImpl.ts +++ b/core/backend/src/rpc-impl/IModelReadRpcImpl.ts @@ -7,17 +7,67 @@ */ import { - AccessToken, assert, BeDuration, BentleyStatus, CompressedId64Set, GuidString, Id64, Id64String, IModelStatus, Logger, + AccessToken, + assert, + BeDuration, + BentleyStatus, + CompressedId64Set, + GuidString, + Id64, + Id64String, + IModelStatus, + Logger, } from "@itwin/core-bentley"; import { - Code, CodeProps, CustomViewState3dCreatorOptions, CustomViewState3dProps, DbBlobRequest, DbBlobResponse, DbQueryRequest, DbQueryResponse, - ElementLoadOptions, ElementLoadProps, ElementMeshRequestProps, ElementProps, EntityMetaData, EntityQueryParams, FontMapProps, - GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, GeometryContainmentRequestProps, GeometryContainmentResponseProps, - GeometrySummaryRequestProps, HydrateViewStateRequestProps, HydrateViewStateResponseProps, ImageSourceFormat, IModel, IModelConnectionProps, - IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, IModelError, IModelReadRpcInterface, IModelRpcOpenProps, IModelRpcProps, - MassPropertiesPerCandidateRequestProps, MassPropertiesPerCandidateResponseProps, MassPropertiesRequestProps, MassPropertiesResponseProps, - ModelExtentsProps, ModelProps, NoContentError, RpcInterface, RpcManager, RpcPendingResponse, SnapRequestProps, SnapResponseProps, - SubCategoryResultRow, SyncMode, TextureData, TextureLoadProps, ViewStateLoadProps, ViewStateProps, + Code, + CodeProps, + CustomViewState3dCreatorOptions, + CustomViewState3dProps, + DbBlobRequest, + DbBlobResponse, + DbQueryRequest, + DbQueryResponse, + ElementLoadOptions, + ElementLoadProps, + ElementMeshRequestProps, + ElementProps, + EntityMetaData, + EntityQueryParams, + FontMapProps, + GeoCoordinatesRequestProps, + GeoCoordinatesResponseProps, + GeometryContainmentRequestProps, + GeometryContainmentResponseProps, + GeometrySummaryRequestProps, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + ImageSourceFormat, + IModel, + IModelConnectionProps, + IModelCoordinatesRequestProps, + IModelCoordinatesResponseProps, + IModelError, + IModelReadRpcInterface, + IModelRpcOpenProps, + IModelRpcProps, + MassPropertiesPerCandidateRequestProps, + MassPropertiesPerCandidateResponseProps, + MassPropertiesRequestProps, + MassPropertiesResponseProps, + ModelExtentsProps, + ModelProps, + NoContentError, + RpcInterface, + RpcManager, + RpcPendingResponse, + SnapRequestProps, + SnapResponseProps, + SubCategoryResultRow, + SyncMode, + TextureData, + TextureLoadProps, + ViewStateLoadProps, + ViewStateProps, ViewStoreRpc, } from "@itwin/core-common"; import { Range3dProps } from "@itwin/core-geometry"; @@ -27,12 +77,12 @@ import { ConcurrentQuery } from "../ConcurrentQuery"; import { CustomViewState3dCreator } from "../CustomViewState3dCreator"; import { generateGeometrySummaries } from "../GeometrySummary"; import { IModelDb } from "../IModelDb"; +import { _nativeDb } from "../internal/Symbols"; import { DictionaryModel } from "../Model"; import { PromiseMemoizer } from "../PromiseMemoizer"; import { RpcTrace } from "../rpc/tracing"; import { ViewStateHydrator } from "../ViewStateHydrator"; import { RpcBriefcaseUtility } from "./RpcBriefcaseUtility"; -import { _nativeDb } from "../internal/Symbols"; interface ViewStateRequestProps { accessToken: AccessToken; @@ -101,8 +151,9 @@ async function getIModelForRpc(tokenProps: IModelRpcProps): Promise { * @internal */ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInterface { // eslint-disable-line deprecation/deprecation - - public static register() { RpcManager.registerImpl(IModelReadRpcInterface, IModelReadRpcImpl); } + public static register() { + RpcManager.registerImpl(IModelReadRpcInterface, IModelReadRpcImpl); + } public async getConnectionProps(tokenProps: IModelRpcOpenProps): Promise { return RpcBriefcaseUtility.openWithTimeout(currentActivity(), tokenProps, SyncMode.FixedVersion); @@ -133,7 +184,11 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte public async queryRows(tokenProps: IModelRpcProps, request: DbQueryRequest): Promise { const iModelDb = await getIModelForRpc(tokenProps); if (iModelDb.isReadonly && request.usePrimaryConn === true) { - Logger.logWarning(BackendLoggerCategory.IModelDb, "usePrimaryConn is only supported on imodel that is opened in read/write mode. The option will be ignored.", request); + Logger.logWarning( + BackendLoggerCategory.IModelDb, + "usePrimaryConn is only supported on imodel that is opened in read/write mode. The option will be ignored.", + request, + ); request.usePrimaryConn = false; } return ConcurrentQuery.executeQueryRequest(iModelDb[_nativeDb], request); @@ -142,7 +197,11 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte public async queryBlob(tokenProps: IModelRpcProps, request: DbBlobRequest): Promise { const iModelDb = await getIModelForRpc(tokenProps); if (iModelDb.isReadonly && request.usePrimaryConn === true) { - Logger.logWarning(BackendLoggerCategory.IModelDb, "usePrimaryConn is only supported on imodel that is opened in read/write mode. The option will be ignored.", request); + Logger.logWarning( + BackendLoggerCategory.IModelDb, + "usePrimaryConn is only supported on imodel that is opened in read/write mode. The option will be ignored.", + request, + ); request.usePrimaryConn = false; } return ConcurrentQuery.executeBlobRequest(iModelDb[_nativeDb], request); @@ -197,7 +256,11 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte return elementProps; } - public async loadElementProps(tokenProps: IModelRpcProps, identifier: Id64String | GuidString | CodeProps, options?: ElementLoadOptions): Promise { + public async loadElementProps( + tokenProps: IModelRpcProps, + identifier: Id64String | GuidString | CodeProps, + options?: ElementLoadOptions, + ): Promise { const props: ElementLoadProps = options ? { ...options } : {}; if (typeof identifier === "string") { if (Id64.isId64(identifier)) @@ -283,7 +346,10 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte return iModelDb.getMassProperties(props); } - public async getMassPropertiesPerCandidate(tokenProps: IModelRpcProps, props: MassPropertiesPerCandidateRequestProps): Promise { + public async getMassPropertiesPerCandidate( + tokenProps: IModelRpcProps, + props: MassPropertiesPerCandidateRequestProps, + ): Promise { const iModelDb = await getIModelForRpc(tokenProps); const getSingleCandidateMassProperties = async (candidate: string) => { @@ -336,7 +402,12 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte throw new NoContentError(); const val = new Uint8Array(thumbnail.image.length + 16); // allocate a new buffer 16 bytes larger than the image size - new Uint32Array(val.buffer, 0, 4).set([thumbnail.image.length, thumbnail.format === "jpeg" ? ImageSourceFormat.Jpeg : ImageSourceFormat.Png, thumbnail.width, thumbnail.height]); // Put the metadata in the first 16 bytes. + new Uint32Array(val.buffer, 0, 4).set([ + thumbnail.image.length, + thumbnail.format === "jpeg" ? ImageSourceFormat.Jpeg : ImageSourceFormat.Png, + thumbnail.width, + thumbnail.height, + ]); // Put the metadata in the first 16 bytes. val.set(thumbnail.image, 16); // put the image data at offset 16 after metadata return val; } @@ -357,12 +428,18 @@ export class IModelReadRpcImpl extends RpcInterface implements IModelReadRpcInte return SpatialCategory.queryCategoryIdByName(iModelDb, dictionary.id, categoryName); } - public async getIModelCoordinatesFromGeoCoordinates(tokenProps: IModelRpcProps, props: IModelCoordinatesRequestProps): Promise { + public async getIModelCoordinatesFromGeoCoordinates( + tokenProps: IModelRpcProps, + props: IModelCoordinatesRequestProps, + ): Promise { const iModelDb = await getIModelForRpc(tokenProps); return iModelDb.getIModelCoordinatesFromGeoCoordinates(props); } - public async getGeoCoordinatesFromIModelCoordinates(tokenProps: IModelRpcProps, props: GeoCoordinatesRequestProps): Promise { + public async getGeoCoordinatesFromIModelCoordinates( + tokenProps: IModelRpcProps, + props: GeoCoordinatesRequestProps, + ): Promise { const iModelDb = await getIModelForRpc(tokenProps); return iModelDb.getGeoCoordinatesFromIModelCoordinates(props); } diff --git a/core/backend/src/rpc-impl/IModelTileRpcImpl.ts b/core/backend/src/rpc-impl/IModelTileRpcImpl.ts index 9c12b9b7713e..bfbe6ffa6295 100644 --- a/core/backend/src/rpc-impl/IModelTileRpcImpl.ts +++ b/core/backend/src/rpc-impl/IModelTileRpcImpl.ts @@ -7,16 +7,28 @@ */ import { AccessToken, assert, BeDuration, Id64Array, Logger } from "@itwin/core-bentley"; -import { ElementGraphicsRequestProps, IModelRpcProps, IModelTileRpcInterface, IModelTileTreeProps, RpcInterface, RpcManager, RpcPendingResponse, TileContentIdentifier, TileContentSource, TileTreeContentIds, TileVersionInfo } from "@itwin/core-common"; +import { + ElementGraphicsRequestProps, + IModelRpcProps, + IModelTileRpcInterface, + IModelTileTreeProps, + RpcInterface, + RpcManager, + RpcPendingResponse, + TileContentIdentifier, + TileContentSource, + TileTreeContentIds, + TileVersionInfo, +} from "@itwin/core-common"; import type { Metadata, TransferConfig } from "@itwin/object-storage-core"; import { BackendLoggerCategory } from "../BackendLoggerCategory"; import { IModelDb } from "../IModelDb"; import { IModelHost } from "../IModelHost"; +import { IModelNative } from "../internal/NativePlatform"; +import { _nativeDb } from "../internal/Symbols"; import { PromiseMemoizer, QueryablePromise } from "../PromiseMemoizer"; import { RpcTrace } from "../rpc/tracing"; import { RpcBriefcaseUtility } from "./RpcBriefcaseUtility"; -import { IModelNative } from "../internal/NativePlatform"; -import { _nativeDb } from "../internal/Symbols"; interface TileRequestProps { accessToken?: AccessToken; @@ -26,12 +38,14 @@ interface TileRequestProps { function generateTileRequestKey(props: TileRequestProps): string { const token = props.tokenProps; - return `${JSON.stringify({ - key: token.key, - iTwinId: token.iTwinId, - iModelId: token.iModelId, - changesetId: token.changeset?.id, - })}:${props.treeId}`; + return `${ + JSON.stringify({ + key: token.key, + iTwinId: token.iTwinId, + iModelId: token.iModelId, + changesetId: token.changeset?.id, + }) + }:${props.treeId}`; } abstract class TileRequestMemoizer extends PromiseMemoizer { @@ -69,7 +83,7 @@ abstract class TileRequestMemoizer exten const tileQP = this.memoize(props); - await BeDuration.race(this._timeoutMilliseconds, tileQP.promise).catch(() => { }); + await BeDuration.race(this._timeoutMilliseconds, tileQP.promise).catch(() => {}); // Note: Rejections must be caught so that the memoization entry can be deleted if (tileQP.isPending) { @@ -98,9 +112,15 @@ async function getTileTreeProps(props: TileRequestProps): Promise { - protected get _timeoutMilliseconds() { return IModelHost.tileTreeRequestTimeout; } - protected get _operationName() { return "requestTileTreeProps"; } - protected stringify(props: TileRequestProps): string { return props.treeId; } + protected get _timeoutMilliseconds() { + return IModelHost.tileTreeRequestTimeout; + } + protected get _operationName() { + return "requestTileTreeProps"; + } + protected stringify(props: TileRequestProps): string { + return props.treeId; + } protected addMetadata(meta: any, props: TileRequestProps): void { meta.treeId = props.treeId; } @@ -140,7 +160,15 @@ async function getTileContent(props: TileContentRequestProps): Promise { - protected get _timeoutMilliseconds() { return IModelHost.tileContentRequestTimeout; } - protected get _operationName() { return "requestTileContent"; } - protected stringify(props: TileContentRequestProps): string { return `${props.treeId}:${props.contentId}`; } + protected get _timeoutMilliseconds() { + return IModelHost.tileContentRequestTimeout; + } + protected get _operationName() { + return "requestTileContent"; + } + protected stringify(props: TileContentRequestProps): string { + return `${props.treeId}:${props.contentId}`; + } protected addMetadata(meta: any, props: TileContentRequestProps): void { meta.treeId = props.treeId; meta.contentId = props.contentId; @@ -191,7 +225,9 @@ function currentActivity() { /** @internal */ export class IModelTileRpcImpl extends RpcInterface implements IModelTileRpcInterface { // eslint-disable-line deprecation/deprecation - public static register() { RpcManager.registerImpl(IModelTileRpcInterface, IModelTileRpcImpl); } + public static register() { + RpcManager.registerImpl(IModelTileRpcInterface, IModelTileRpcImpl); + } public async requestTileTreeProps(tokenProps: IModelRpcProps, treeId: string): Promise { return RequestTileTreePropsMemoizer.perform({ accessToken: currentActivity().accessToken, tokenProps, treeId }); @@ -210,7 +246,12 @@ export class IModelTileRpcImpl extends RpcInterface implements IModelTileRpcInte return db[_nativeDb].purgeTileTrees(modelIds); } - public async generateTileContent(tokenProps: IModelRpcProps, treeId: string, contentId: string, guid: string | undefined): Promise { + public async generateTileContent( + tokenProps: IModelRpcProps, + treeId: string, + contentId: string, + guid: string | undefined, + ): Promise { return RequestTileContentMemoizer.perform({ accessToken: currentActivity().accessToken, tokenProps, treeId, contentId, guid }); } diff --git a/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts b/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts index ceeb6abbf5cb..89e9aecb4c4f 100644 --- a/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts +++ b/core/backend/src/rpc-impl/RpcBriefcaseUtility.ts @@ -8,7 +8,15 @@ import { AccessToken, assert, BeDuration, BentleyError, IModelStatus, Logger } from "@itwin/core-bentley"; import { - BriefcaseProps, IModelConnectionProps, IModelError, IModelRpcOpenProps, IModelRpcProps, IModelVersion, RpcActivity, RpcPendingResponse, SyncMode, + BriefcaseProps, + IModelConnectionProps, + IModelError, + IModelRpcOpenProps, + IModelRpcProps, + IModelVersion, + RpcActivity, + RpcPendingResponse, + SyncMode, } from "@itwin/core-common"; import { BackendLoggerCategory } from "../BackendLoggerCategory"; import { BriefcaseManager, RequestNewBriefcaseArg } from "../BriefcaseManager"; @@ -33,7 +41,6 @@ export interface DownloadAndOpenArgs { * @internal */ export class RpcBriefcaseUtility { - private static async downloadAndOpen(args: DownloadAndOpenArgs): Promise { const { activity, tokenProps } = args; const accessToken = activity.accessToken; @@ -66,7 +73,11 @@ export class RpcBriefcaseUtility { if (db.changeset.id !== tokenProps.changeset?.id) { assert(undefined !== tokenProps.changeset); const toIndex = tokenProps.changeset?.index ?? - (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken, iModelId, version: IModelVersion.asOfChangeSet(tokenProps.changeset.id) })).index; + (await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken, + iModelId, + version: IModelVersion.asOfChangeSet(tokenProps.changeset.id), + })).index; await BriefcaseManager.pullAndApplyChangesets(db, { accessToken, toIndex }); } return db; @@ -105,7 +116,7 @@ export class RpcBriefcaseUtility { this._briefcasePromises.set(key, briefcasePromise); return await briefcasePromise; } finally { - this._briefcasePromises.delete(key); // the download and open is now done + this._briefcasePromises.delete(key); // the download and open is now done } } @@ -171,7 +182,10 @@ export class RpcBriefcaseUtility { db = await SnapshotDb.openCheckpointFromRpc(checkpoint); Logger.logTrace(loggerCategory, "using V2 checkpoint", tokenProps); } catch (e) { - Logger.logTrace(loggerCategory, "unable to open V2 checkpoint - falling back to V1 checkpoint", { error: BentleyError.getErrorProps(e), ...tokenProps }); + Logger.logTrace(loggerCategory, "unable to open V2 checkpoint - falling back to V1 checkpoint", { + error: BentleyError.getErrorProps(e), + ...tokenProps, + }); // this isn't a v2 checkpoint. Set up a race between the specified timeout period and the open. Throw an RpcPendingResponse exception if the timeout happens first. const request = { @@ -191,17 +205,31 @@ export class RpcBriefcaseUtility { return db; } - public static async openWithTimeout(activity: RpcActivity, tokenProps: IModelRpcOpenProps, syncMode: SyncMode.FixedVersion, timeout?: number): Promise; + public static async openWithTimeout( + activity: RpcActivity, + tokenProps: IModelRpcOpenProps, + syncMode: SyncMode.FixedVersion, + timeout?: number, + ): Promise; /** * @deprecated in 4.4.0 - only `SyncMode.FixedVersion` should be used in RPC backends */ // eslint-disable-next-line @typescript-eslint/unified-signatures -- these are separate to explicitly deprecate some SyncMode members. - public static async openWithTimeout(activity: RpcActivity, tokenProps: IModelRpcOpenProps, syncMode: Exclude, timeout?: number): Promise; - public static async openWithTimeout(activity: RpcActivity, tokenProps: IModelRpcOpenProps, syncMode: SyncMode, timeout: number = 1000): Promise { // eslint-disable-line deprecation/deprecation + public static async openWithTimeout( + activity: RpcActivity, + tokenProps: IModelRpcOpenProps, + syncMode: Exclude, + timeout?: number, + ): Promise; + public static async openWithTimeout( + activity: RpcActivity, + tokenProps: IModelRpcOpenProps, + syncMode: SyncMode, + timeout: number = 1000, + ): Promise { // eslint-disable-line deprecation/deprecation if (tokenProps.iModelId) await IModelHost.tileStorage?.initialize(tokenProps.iModelId); // eslint-disable-next-line deprecation/deprecation return (await this.open({ activity, tokenProps, syncMode, timeout })).toJSON(); } - } diff --git a/core/backend/src/rpc-impl/SnapshotIModelRpcImpl.ts b/core/backend/src/rpc-impl/SnapshotIModelRpcImpl.ts index 83bbd36707c8..0e9ede15a7a1 100644 --- a/core/backend/src/rpc-impl/SnapshotIModelRpcImpl.ts +++ b/core/backend/src/rpc-impl/SnapshotIModelRpcImpl.ts @@ -7,7 +7,13 @@ */ import { - IModelConnectionProps, IModelNotFoundResponse, IModelRpcProps, RpcInterface, RpcManager, SnapshotIModelRpcInterface, SnapshotOpenOptions, + IModelConnectionProps, + IModelNotFoundResponse, + IModelRpcProps, + RpcInterface, + RpcManager, + SnapshotIModelRpcInterface, + SnapshotOpenOptions, } from "@itwin/core-common"; import { SnapshotDb } from "../IModelDb"; import { IModelHost } from "../IModelHost"; @@ -18,7 +24,9 @@ import { IModelHost } from "../IModelHost"; * @internal */ export class SnapshotIModelRpcImpl extends RpcInterface implements SnapshotIModelRpcInterface { // eslint-disable-line deprecation/deprecation - public static register() { RpcManager.registerImpl(SnapshotIModelRpcInterface, SnapshotIModelRpcImpl); } + public static register() { + RpcManager.registerImpl(SnapshotIModelRpcInterface, SnapshotIModelRpcImpl); + } /** Ask the backend to open a snapshot iModel from a file name that is resolved by the backend. */ public async openFile(filePath: string, opts?: SnapshotOpenOptions): Promise { diff --git a/core/backend/src/rpc-impl/WipRpcImpl.ts b/core/backend/src/rpc-impl/WipRpcImpl.ts index 87ec2d060556..f51d5b630b60 100644 --- a/core/backend/src/rpc-impl/WipRpcImpl.ts +++ b/core/backend/src/rpc-impl/WipRpcImpl.ts @@ -19,9 +19,12 @@ import { BriefcaseDb } from "../IModelDb"; * @deprecated in 4.10. If any of these methods are needed in the frontend, they should be rewritten using IPC or HTTP protocol. */ export class WipRpcImpl extends RpcInterface implements WipRpcInterface { - - public static register() { RpcManager.registerImpl(WipRpcInterface, WipRpcImpl); } - public async placeholder(_tokenProps: IModelRpcProps): Promise { return "placeholder"; } + public static register() { + RpcManager.registerImpl(WipRpcInterface, WipRpcImpl); + } + public async placeholder(_tokenProps: IModelRpcProps): Promise { + return "placeholder"; + } public async isChangeCacheAttached(tokenProps: IModelRpcProps): Promise { return ChangeSummaryManager.isChangeCacheAttached(BriefcaseDb.findByKey(tokenProps.key)); @@ -31,7 +34,11 @@ export class WipRpcImpl extends RpcInterface implements WipRpcInterface { ChangeSummaryManager.attachChangeCache(BriefcaseDb.findByKey(tokenProps.key)); } - public async getChangedElements(tokenProps: IModelRpcProps, startChangesetId: string, endChangesetId: string): Promise { + public async getChangedElements( + tokenProps: IModelRpcProps, + startChangesetId: string, + endChangesetId: string, + ): Promise { assert(undefined !== tokenProps.iModelId); return ChangedElementsManager.getChangedElements(tokenProps.iModelId, startChangesetId, endChangesetId); } diff --git a/core/backend/src/rpc/multipart.ts b/core/backend/src/rpc/multipart.ts index f61dc0a349b1..f6d4129ab2f3 100644 --- a/core/backend/src/rpc/multipart.ts +++ b/core/backend/src/rpc/multipart.ts @@ -51,7 +51,7 @@ export async function parseMultipartRequest(req: HttpServerRequest) { form.on("close", () => { let i = 0; - for (; ;) { + for (;;) { const part = data[`data-${i}`]; if (!part) { break; diff --git a/core/backend/src/rpc/tracing.ts b/core/backend/src/rpc/tracing.ts index 95c8d1b1676e..753b8d504b8b 100644 --- a/core/backend/src/rpc/tracing.ts +++ b/core/backend/src/rpc/tracing.ts @@ -28,14 +28,14 @@ export class RpcTrace { /** Get the [RpcActivity]($common) for the currently executing async, or `undefined` if there is no * RpcActivity in the current call stack. - * */ + */ public static get currentActivity(): RpcActivity | undefined { return RpcTrace._storage.getStore() as RpcActivity | undefined; } /** Get the [RpcActivity]($common) for the currently executing async. Asserts that the RpcActivity * exists in the current call stack. - * */ + */ public static get expectCurrentActivity(): RpcActivity { assert(undefined !== RpcTrace.currentActivity); return RpcTrace.currentActivity; diff --git a/core/backend/src/rpc/web/logging.ts b/core/backend/src/rpc/web/logging.ts index 1a44bfc21de9..899eebbd6741 100644 --- a/core/backend/src/rpc/web/logging.ts +++ b/core/backend/src/rpc/web/logging.ts @@ -15,9 +15,18 @@ import * as os from "os"; export class WebAppRpcLoggingBackend extends WebAppRpcLogging { protected override async logProtocolEvent(event: RpcProtocolEvent, object: RpcInvocation): Promise { switch (event) { - case RpcProtocolEvent.RequestReceived: return this.logRequest(CommonLoggerCategory.RpcInterfaceBackend, "RpcInterface.backend.request", object.request); - case RpcProtocolEvent.BackendErrorOccurred: return this.logErrorBackend("RpcInterface.backend.error", object); - case RpcProtocolEvent.BackendResponseCreated: return this.logResponse(CommonLoggerCategory.RpcInterfaceBackend, "RpcInterface.backend.response", object.request, object.status, object.elapsed); + case RpcProtocolEvent.RequestReceived: + return this.logRequest(CommonLoggerCategory.RpcInterfaceBackend, "RpcInterface.backend.request", object.request); + case RpcProtocolEvent.BackendErrorOccurred: + return this.logErrorBackend("RpcInterface.backend.error", object); + case RpcProtocolEvent.BackendResponseCreated: + return this.logResponse( + CommonLoggerCategory.RpcInterfaceBackend, + "RpcInterface.backend.response", + object.request, + object.status, + object.elapsed, + ); } } diff --git a/core/backend/src/rpc/web/response.ts b/core/backend/src/rpc/web/response.ts index 1485e66d0d81..e5456bc3921c 100644 --- a/core/backend/src/rpc/web/response.ts +++ b/core/backend/src/rpc/web/response.ts @@ -26,7 +26,7 @@ import { import { Readable, Stream } from "node:stream"; import { promisify } from "node:util"; -import { brotliCompress, BrotliOptions, createBrotliCompress, createGzip, gzip, constants as zlibConstants } from "node:zlib"; +import { brotliCompress, BrotliOptions, constants as zlibConstants, createBrotliCompress, createGzip, gzip } from "node:zlib"; /* eslint-disable deprecation/deprecation */ @@ -87,7 +87,11 @@ function configureStream(fulfillment: RpcRequestFulfillment) { return fulfillment.result.stream!; } -async function configureEncoding(req: HttpServerRequest, res: HttpServerResponse, responseBody: string | Buffer | Readable): Promise { +async function configureEncoding( + req: HttpServerRequest, + res: HttpServerResponse, + responseBody: string | Buffer | Readable, +): Promise { const acceptedEncodings = req.header("Accept-Encoding")?.split(",").map((value) => value.trim()); if (!acceptedEncodings) return responseBody; @@ -115,7 +119,13 @@ async function configureEncoding(req: HttpServerRequest, res: HttpServerResponse } /** @internal */ -export async function sendResponse(protocol: WebAppRpcProtocol, request: SerializedRpcRequest, fulfillment: RpcRequestFulfillment, req: HttpServerRequest, res: HttpServerResponse) { +export async function sendResponse( + protocol: WebAppRpcProtocol, + request: SerializedRpcRequest, + fulfillment: RpcRequestFulfillment, + req: HttpServerRequest, + res: HttpServerResponse, +) { logResponse(request, fulfillment.status, fulfillment.rawResult); const versionHeader = protocol.protocolVersionHeaderName; diff --git a/core/backend/src/test/AdvancedEqual.ts b/core/backend/src/test/AdvancedEqual.ts index cb1e79a1dbb3..f35967d7aeed 100644 --- a/core/backend/src/test/AdvancedEqual.ts +++ b/core/backend/src/test/AdvancedEqual.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Assertion, util } from "chai"; import { Geometry } from "@itwin/core-geometry"; +import { Assertion, util } from "chai"; interface DeepEqualOpts { /** @@ -56,10 +56,9 @@ export function advancedDeepEqual( a: any, options: AdvancedEqualFuncOpts = {}, ): boolean { - const normalizedClassNameProps - = options.normalizeClassNameProps === true - ? ["classFullName", "relClassName"] - : options.normalizeClassNameProps || []; + const normalizedClassNameProps = options.normalizeClassNameProps === true + ? ["classFullName", "relClassName"] + : options.normalizeClassNameProps || []; if (options.tolerance === undefined) options.tolerance = defaultOpts.tolerance; if (e === a) @@ -83,7 +82,7 @@ export function advancedDeepEqual( return (eSize === aSize || !!options.useSubsetEquality) && Object.keys(e).every( (keyOfE) => (keyOfE in a || options.considerNonExistingAndUndefinedEqual) && - normalizedClassNameProps.includes(keyOfE) + normalizedClassNameProps.includes(keyOfE) ? advancedDeepEqual(normalizeClassName(e[keyOfE]), normalizeClassName(a[keyOfE])) : advancedDeepEqual(e[keyOfE], a[keyOfE], options), ); @@ -106,12 +105,8 @@ Assertion.addMethod( isDeep ? advancedDeepEqual(expected, actual, options) : isAlmostEqualNumber(expected, actual, options.tolerance), - `expected ${ - isDeep ? "deep equality of " : " " - }#{exp} and #{act} with a tolerance of ${options.tolerance}`, - `expected ${ - isDeep ? "deep inequality of " : " " - }#{exp} and #{act} with a tolerance of ${options.tolerance}`, + `expected ${isDeep ? "deep equality of " : " "}#{exp} and #{act} with a tolerance of ${options.tolerance}`, + `expected ${isDeep ? "deep inequality of " : " "}#{exp} and #{act} with a tolerance of ${options.tolerance}`, expected, actual, ); @@ -128,7 +123,7 @@ Assertion.addMethod( options.tolerance = 1e-10; const actual = this._obj; this.assert( - advancedDeepEqual(expected, actual, {...options, useSubsetEquality: true }), + advancedDeepEqual(expected, actual, { ...options, useSubsetEquality: true }), `expected #{act} to contain as a subset #{exp}`, `expected #{act} not to contain as a subset #{exp}`, expected, diff --git a/core/backend/src/test/GeometryTestUtil.ts b/core/backend/src/test/GeometryTestUtil.ts index ca45f4452948..a3f704ef6bf4 100644 --- a/core/backend/src/test/GeometryTestUtil.ts +++ b/core/backend/src/test/GeometryTestUtil.ts @@ -3,13 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BRepEntity, ColorDef } from "@itwin/core-common"; +import { Point3d, Transform, YawPitchRollAngles } from "@itwin/core-geometry"; import * as fs from "fs"; -import { - Point3d, Transform, YawPitchRollAngles, -} from "@itwin/core-geometry"; -import { - BRepEntity, ColorDef, -} from "@itwin/core-common"; import { IModelTestUtils } from "./IModelTestUtils"; export const brepData: { data: string } = JSON.parse( diff --git a/core/backend/src/test/IModelHost.test.ts b/core/backend/src/test/IModelHost.test.ts index 8055054bcd96..d9c2f38683d8 100644 --- a/core/backend/src/test/IModelHost.test.ts +++ b/core/backend/src/test/IModelHost.test.ts @@ -2,21 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger, LogLevel } from "@itwin/core-bentley"; +import { RpcRegistry } from "@itwin/core-common"; +import { AzureServerStorage, AzureServerStorageBindings, AzureServerStorageBindingsConfig } from "@itwin/object-storage-azure"; +import { ServerStorage } from "@itwin/object-storage-core"; import { assert, expect } from "chai"; import * as path from "path"; import * as sinon from "sinon"; -import { RpcRegistry } from "@itwin/core-common"; import { BriefcaseManager } from "../BriefcaseManager"; import { SnapshotDb } from "../IModelDb"; import { IModelHost, IModelHostOptions, KnownLocations } from "../IModelHost"; +import { overrideSyncNativeLogLevels } from "../internal/NativePlatform"; import { Schemas } from "../Schema"; +import { IModelTestUtils } from "./IModelTestUtils"; import { KnownTestLocations } from "./KnownTestLocations"; -import { AzureServerStorage, AzureServerStorageBindings, AzureServerStorageBindingsConfig } from "@itwin/object-storage-azure"; -import { ServerStorage } from "@itwin/object-storage-core"; import { TestUtils } from "./TestUtils"; -import { IModelTestUtils } from "./IModelTestUtils"; -import { Logger, LogLevel } from "@itwin/core-bentley"; -import { overrideSyncNativeLogLevels } from "../internal/NativePlatform"; describe("IModelHost", () => { const opts = { cacheDir: TestUtils.getCacheDir() }; @@ -53,7 +53,6 @@ describe("IModelHost", () => { for (let i = 0; i <= 15; i++) { await IModelHost.startup(); await IModelHost.shutdown(); - } const afterCount = process.listenerCount("beforeExit"); expect(beforeCount).to.be.equal(afterCount); @@ -82,7 +81,7 @@ describe("IModelHost", () => { IModelHost.onBeforeShutdown.addOnce(eventHandler); const filename = IModelTestUtils.resolveAssetFile("GetSetAutoHandledStructProperties.bim"); - const workspaceClose = sinon.spy((IModelHost.appWorkspace as any), "close"); + const workspaceClose = sinon.spy(IModelHost.appWorkspace as any, "close"); const saveSettings = IModelHost.appWorkspace.settings as any; const settingClose = sinon.spy(saveSettings, "close"); expect(workspaceClose.callCount).eq(0); @@ -158,7 +157,10 @@ describe("IModelHost", () => { assert.isTrue(registerStub.calledOnce); assert.equal((registerStub.firstCall.lastArg as AzureServerStorageBindingsConfig).accountName, config.tileCacheAzureCredentials.account); assert.equal((registerStub.firstCall.lastArg as AzureServerStorageBindingsConfig).accountKey, config.tileCacheAzureCredentials.accessKey); - assert.equal((registerStub.firstCall.lastArg as AzureServerStorageBindingsConfig).baseUrl, `https://${config.tileCacheAzureCredentials.account}.blob.core.windows.net`); + assert.equal( + (registerStub.firstCall.lastArg as AzureServerStorageBindingsConfig).baseUrl, + `https://${config.tileCacheAzureCredentials.account}.blob.core.windows.net`, + ); }); it("should set custom cloud storage provider for tile cache", async () => { @@ -214,7 +216,9 @@ describe("IModelHost", () => { let sha1 = IModelHost.computeSchemaChecksum({ schemaXmlPath, referencePaths }); expect(sha1).equal("3ac6578060902aa0b8426b61d62045fdf7fa0b2b"); - expect(() => IModelHost.computeSchemaChecksum({ schemaXmlPath, referencePaths, exactMatch: true })).throws("Failed to read schema SchemaA.ecschema"); + expect(() => IModelHost.computeSchemaChecksum({ schemaXmlPath, referencePaths, exactMatch: true })).throws( + "Failed to read schema SchemaA.ecschema", + ); referencePaths = [path.join(assetsDir, "exact-match")]; sha1 = IModelHost.computeSchemaChecksum({ schemaXmlPath, referencePaths, exactMatch: true }); diff --git a/core/backend/src/test/IModelTestUtils.ts b/core/backend/src/test/IModelTestUtils.ts index 0f5feb077dc4..2f4eb2a51c91 100644 --- a/core/backend/src/test/IModelTestUtils.ts +++ b/core/backend/src/test/IModelTestUtils.ts @@ -3,38 +3,104 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Buffer } from "node:buffer"; -import * as chai from "chai"; -import { assert, expect } from "chai"; -import * as chaiAsPromised from "chai-as-promised"; -import * as path from "path"; import { AccessToken, BeEvent, DbResult, Guid, GuidString, Id64, Id64String, IModelStatus, omit, OpenMode } from "@itwin/core-bentley"; import { - AuxCoordSystem2dProps, Base64EncodedString, ChangesetIdWithIndex, Code, CodeProps, CodeScopeSpec, CodeSpec, ColorDef, ElementAspectProps, - ElementProps, Environment, ExternalSourceProps, GeometricElement2dProps, GeometryParams, GeometryPartProps, GeometryStreamBuilder, - GeometryStreamProps, ImageSourceFormat, IModel, IModelError, IModelReadRpcInterface, IModelVersion, IModelVersionProps, LocalFileName, - PhysicalElementProps, PlanProjectionSettings, RelatedElement, RepositoryLinkProps, RequestNewBriefcaseProps, RpcConfiguration, RpcManager, - RpcPendingResponse, SkyBoxImageType, SubCategoryAppearance, SubCategoryOverride, SyncMode, + AuxCoordSystem2dProps, + Base64EncodedString, + ChangesetIdWithIndex, + Code, + CodeProps, + CodeScopeSpec, + CodeSpec, + ColorDef, + ElementAspectProps, + ElementProps, + Environment, + ExternalSourceProps, + GeometricElement2dProps, + GeometryParams, + GeometryPartProps, + GeometryStreamBuilder, + GeometryStreamProps, + ImageSourceFormat, + IModel, + IModelError, + IModelReadRpcInterface, + IModelVersion, + IModelVersionProps, + LocalFileName, + PhysicalElementProps, + PlanProjectionSettings, + RelatedElement, + RepositoryLinkProps, + RequestNewBriefcaseProps, + RpcConfiguration, + RpcManager, + RpcPendingResponse, + SkyBoxImageType, + SubCategoryAppearance, + SubCategoryOverride, + SyncMode, } from "@itwin/core-common"; import { Box, Cone, LineString3d, Point2d, Point3d, Range2d, Range3d, StandardViewIndex, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import * as chai from "chai"; +import { assert, expect } from "chai"; +import * as chaiAsPromised from "chai-as-promised"; +import { Buffer } from "node:buffer"; +import * as path from "path"; +import { BackendHubAccess } from "../BackendHubAccess"; import { RequestNewBriefcaseArg } from "../BriefcaseManager"; import { CheckpointProps, V1CheckpointManager } from "../CheckpointManager"; import { ClassRegistry } from "../ClassRegistry"; import { - _nativeDb, AuxCoordSystem2d, BriefcaseDb, BriefcaseLocalValue, BriefcaseManager, CategorySelector, ChannelControl, DisplayStyle2d, DisplayStyle3d, DrawingCategory, - DrawingViewDefinition, ECSqlStatement, Element, ElementAspect, ElementOwnsChildElements, ElementOwnsMultiAspects, ElementOwnsUniqueAspect, - ElementUniqueAspect, ExternalSource, ExternalSourceIsInRepository, FunctionalModel, FunctionalSchema, GroupModel, IModelDb, IModelHost, - IModelJsFs, InformationPartitionElement, Model, ModelSelector, OrthographicViewDefinition, PhysicalModel, PhysicalObject, - PhysicalPartition, RenderMaterialElement, SnapshotDb, SpatialCategory, SubCategory, SubjectOwnsPartitionElements, Texture, ViewDefinition, + _nativeDb, + AuxCoordSystem2d, + BriefcaseDb, + BriefcaseLocalValue, + BriefcaseManager, + CategorySelector, + ChannelControl, + DisplayStyle2d, + DisplayStyle3d, + DrawingCategory, + DrawingViewDefinition, + ECSqlStatement, + Element, + ElementAspect, + ElementOwnsChildElements, + ElementOwnsMultiAspects, + ElementOwnsUniqueAspect, + ElementUniqueAspect, + ExternalSource, + ExternalSourceIsInRepository, + FunctionalModel, + FunctionalSchema, + GroupModel, + IModelDb, + IModelHost, + IModelJsFs, + InformationPartitionElement, + Model, + ModelSelector, + OrthographicViewDefinition, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + RenderMaterialElement, + SnapshotDb, + SpatialCategory, + SubCategory, + SubjectOwnsPartitionElements, + Texture, + ViewDefinition, } from "../core-backend"; import { DefinitionPartition, Drawing, DrawingGraphic, GeometryPart, LinkElement, PhysicalElement, RepositoryLink, Subject } from "../Element"; +import { HubMock } from "../HubMock"; import { DefinitionModel, DocumentListModel, DrawingModel, InformationRecordModel, SpatialLocationModel } from "../Model"; import { DrawingGraphicRepresentsElement, ElementDrivesElement, Relationship, RelationshipProps } from "../Relationship"; import { DownloadAndOpenArgs, RpcBriefcaseUtility } from "../rpc-impl/RpcBriefcaseUtility"; import { Schema, Schemas } from "../Schema"; -import { HubMock } from "../HubMock"; import { KnownTestLocations } from "./KnownTestLocations"; -import { BackendHubAccess } from "../BackendHubAccess"; chai.use(chaiAsPromised); @@ -52,30 +118,43 @@ export interface IModelTestUtilsOpenOptions { } export class TestBim extends Schema { - public static override get schemaName(): string { return "TestBim"; } - + public static override get schemaName(): string { + return "TestBim"; + } } export interface TestRelationshipProps extends RelationshipProps { property1: string; } export class TestElementDrivesElement extends ElementDrivesElement { - public static override get className(): string { return "TestElementDrivesElement"; } + public static override get className(): string { + return "TestElementDrivesElement"; + } public property1!: string; public static rootChanged = new BeEvent<(props: RelationshipProps, imodel: IModelDb) => void>(); public static deletedDependency = new BeEvent<(props: RelationshipProps, imodel: IModelDb) => void>(); - public static override onRootChanged(props: RelationshipProps, imodel: IModelDb): void { this.rootChanged.raiseEvent(props, imodel); } - public static override onDeletedDependency(props: RelationshipProps, imodel: IModelDb): void { this.deletedDependency.raiseEvent(props, imodel); } + public static override onRootChanged(props: RelationshipProps, imodel: IModelDb): void { + this.rootChanged.raiseEvent(props, imodel); + } + public static override onDeletedDependency(props: RelationshipProps, imodel: IModelDb): void { + this.deletedDependency.raiseEvent(props, imodel); + } } export interface TestPhysicalObjectProps extends PhysicalElementProps { intProperty: number; } export class TestPhysicalObject extends PhysicalElement { - public static override get className(): string { return "TestPhysicalObject"; } + public static override get className(): string { + return "TestPhysicalObject"; + } public intProperty!: number; public static beforeOutputsHandled = new BeEvent<(id: Id64String, imodel: IModelDb) => void>(); public static allInputsHandled = new BeEvent<(id: Id64String, imodel: IModelDb) => void>(); - public static override onBeforeOutputsHandled(id: Id64String, imodel: IModelDb): void { this.beforeOutputsHandled.raiseEvent(id, imodel); } - public static override onAllInputsHandled(id: Id64String, imodel: IModelDb): void { this.allInputsHandled.raiseEvent(id, imodel); } + public static override onBeforeOutputsHandled(id: Id64String, imodel: IModelDb): void { + this.beforeOutputsHandled.raiseEvent(id, imodel); + } + public static override onAllInputsHandled(id: Id64String, imodel: IModelDb): void { + this.allInputsHandled.raiseEvent(id, imodel); + } } /** the types of users available for tests */ @@ -83,7 +162,7 @@ export enum TestUserType { Regular, Manager, Super, - SuperManager + SuperManager, } /** A wrapper around the BackendHubAccess API through IModelHost.hubAccess. @@ -91,7 +170,9 @@ export enum TestUserType { * All methods in this class should be usable with any BackendHubAccess implementation (i.e. HubMock and IModelHubBackend). */ export class HubWrappers { - protected static get hubMock() { return HubMock; } + protected static get hubMock() { + return HubMock; + } public static async getAccessToken(user: TestUserType) { return TestUserType[user]; @@ -108,7 +189,7 @@ export class HubWrappers { /** Deletes and re-creates an iModel with the provided name in the iTwin. * @returns the iModelId of the newly created iModel. - */ + */ public static async recreateIModel(...[arg]: Parameters): Promise { assert.isTrue(this.hubMock.isValid, "Must use HubMock for tests that modify iModels"); const deleteIModel = await IModelHost.hubAccess.queryIModelByName(arg); @@ -129,7 +210,13 @@ export class HubWrappers { } /** Push an iModel to the Hub */ - public static async pushIModel(accessToken: AccessToken, iTwinId: string, pathname: string, iModelName?: string, overwrite?: boolean): Promise { + public static async pushIModel( + accessToken: AccessToken, + iTwinId: string, + pathname: string, + iModelName?: string, + overwrite?: boolean, + ): Promise { // Delete any existing iModels with the same name as the required iModel const locIModelName = iModelName || path.basename(pathname, ".bim"); const iModelId = await IModelHost.hubAccess.queryIModelByName({ accessToken, iTwinId, iModelName: locIModelName }); @@ -156,7 +243,9 @@ export class HubWrappers { } /** Opens the specific iModel as a Briefcase through the same workflow the IModelReadRpc.getConnectionProps method will use. Replicates the way a frontend would open the iModel. */ - public static async openBriefcaseUsingRpc(args: RequestNewBriefcaseProps & { accessToken: AccessToken, deleteFirst?: boolean }): Promise { + public static async openBriefcaseUsingRpc( + args: RequestNewBriefcaseProps & { accessToken: AccessToken, deleteFirst?: boolean }, + ): Promise { if (undefined === args.asOf) args.asOf = IModelVersion.latest().toJSON(); @@ -164,7 +253,11 @@ export class HubWrappers { tokenProps: { iTwinId: args.iTwinId, iModelId: args.iModelId, - changeset: (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken: args.accessToken, version: IModelVersion.fromJSON(args.asOf), iModelId: args.iModelId })), + changeset: (await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken: args.accessToken, + version: IModelVersion.fromJSON(args.asOf), + iModelId: args.iModelId, + })), }, activity: { accessToken: args.accessToken, activityId: "", applicationId: "", applicationVersion: "", sessionId: "" }, syncMode: args.briefcaseId === 0 ? SyncMode.PullOnly : SyncMode.PullAndPush, @@ -184,7 +277,9 @@ export class HubWrappers { } /** Downloads and opens a v1 checkpoint */ - public static async downloadAndOpenCheckpoint(args: { accessToken: AccessToken, iTwinId: GuidString, iModelId: GuidString, asOf?: IModelVersionProps }): Promise { + public static async downloadAndOpenCheckpoint( + args: { accessToken: AccessToken, iTwinId: GuidString, iModelId: GuidString, asOf?: IModelVersionProps }, + ): Promise { if (undefined === args.asOf) args.asOf = IModelVersion.latest().toJSON(); @@ -192,18 +287,28 @@ export class HubWrappers { iTwinId: args.iTwinId, iModelId: args.iModelId, accessToken: args.accessToken, - changeset: (await IModelHost.hubAccess.getChangesetFromVersion({ accessToken: args.accessToken, version: IModelVersion.fromJSON(args.asOf), iModelId: args.iModelId })), + changeset: (await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken: args.accessToken, + version: IModelVersion.fromJSON(args.asOf), + iModelId: args.iModelId, + })), }; return V1CheckpointManager.getCheckpointDb({ checkpoint, localFile: V1CheckpointManager.getFileName(checkpoint) }); } /** Opens the specific Checkpoint iModel, `SyncMode.FixedVersion`, through the same workflow the IModelReadRpc.getConnectionProps method will use. Replicates the way a frontend would open the iModel. */ - public static async openCheckpointUsingRpc(args: RequestNewBriefcaseProps & { accessToken: AccessToken, deleteFirst?: boolean }): Promise { + public static async openCheckpointUsingRpc( + args: RequestNewBriefcaseProps & { accessToken: AccessToken, deleteFirst?: boolean }, + ): Promise { if (undefined === args.asOf) args.asOf = IModelVersion.latest().toJSON(); - const changeset = await IModelHost.hubAccess.getChangesetFromVersion({ accessToken: args.accessToken, version: IModelVersion.fromJSON(args.asOf), iModelId: args.iModelId }); + const changeset = await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken: args.accessToken, + version: IModelVersion.fromJSON(args.asOf), + iModelId: args.iModelId, + }); const openArgs = { tokenProps: { iTwinId: args.iTwinId, @@ -228,7 +333,12 @@ export class HubWrappers { /** * Purges all acquired briefcases for the specified iModel (and user), if the specified threshold of acquired briefcases is exceeded */ - public static async purgeAcquiredBriefcasesById(accessToken: AccessToken, iModelId: GuidString, onReachThreshold: () => void = () => { }, acquireThreshold: number = 16): Promise { + public static async purgeAcquiredBriefcasesById( + accessToken: AccessToken, + iModelId: GuidString, + onReachThreshold: () => void = () => {}, + acquireThreshold: number = 16, + ): Promise { const briefcases = await IModelHost.hubAccess.getMyBriefcaseIds({ accessToken, iModelId }); if (briefcases.length > acquireThreshold) { if (undefined !== onReachThreshold) @@ -261,8 +371,9 @@ export class HubWrappers { } export class IModelTestUtils { - - protected static get knownTestLocations(): { outputDir: string, assetsDir: string } { return KnownTestLocations; } + protected static get knownTestLocations(): { outputDir: string, assetsDir: string } { + return KnownTestLocations; + } /** Generate a name for an iModel that's unique using the baseName provided and appending a new GUID. */ public static generateUniqueName(baseName: string) { @@ -361,7 +472,11 @@ export class IModelTestUtils { /** Create and insert a PhysicalPartition element (in the repositoryModel) and an associated PhysicalModel. */ public static createAndInsertPhysicalModel(testDb: IModelDb, modeledElementRef: RelatedElement, privateModel: boolean = false): Id64String { - const newModel = testDb.models.createModel({ modeledElement: modeledElementRef, classFullName: PhysicalModel.classFullName, isPrivate: privateModel }); + const newModel = testDb.models.createModel({ + modeledElement: modeledElementRef, + classFullName: PhysicalModel.classFullName, + isPrivate: privateModel, + }); const newModelId = newModel.id = testDb.models.insertModel(newModel.toJSON()); assert.isTrue(Id64.isValidId64(newModelId)); assert.isTrue(Id64.isValidId64(newModel.id)); @@ -370,8 +485,16 @@ export class IModelTestUtils { } /** Create and insert a PhysicalPartition element (in the repositoryModel) and an associated PhysicalModel. */ - public static async createAndInsertPhysicalModelAsync(testDb: IModelDb, modeledElementRef: RelatedElement, privateModel: boolean = false): Promise { - const newModel = testDb.models.createModel({ modeledElement: modeledElementRef, classFullName: PhysicalModel.classFullName, isPrivate: privateModel }); + public static async createAndInsertPhysicalModelAsync( + testDb: IModelDb, + modeledElementRef: RelatedElement, + privateModel: boolean = false, + ): Promise { + const newModel = testDb.models.createModel({ + modeledElement: modeledElementRef, + classFullName: PhysicalModel.classFullName, + isPrivate: privateModel, + }); const newModelId = newModel.insert(); assert.isTrue(Id64.isValidId64(newModelId)); assert.isTrue(Id64.isValidId64(newModel.id)); @@ -383,7 +506,12 @@ export class IModelTestUtils { * Create and insert a PhysicalPartition element (in the repositoryModel) and an associated PhysicalModel. * @return [modeledElementId, modelId] */ - public static createAndInsertPhysicalPartitionAndModel(testImodel: IModelDb, newModelCode: CodeProps, privateModel: boolean = false, parent?: Id64String): Id64String[] { + public static createAndInsertPhysicalPartitionAndModel( + testImodel: IModelDb, + newModelCode: CodeProps, + privateModel: boolean = false, + parent?: Id64String, + ): Id64String[] { const eid = IModelTestUtils.createAndInsertPhysicalPartition(testImodel, newModelCode, parent); const modeledElementRef = new RelatedElement({ id: eid }); const mid = IModelTestUtils.createAndInsertPhysicalModel(testImodel, modeledElementRef, privateModel); @@ -394,7 +522,12 @@ export class IModelTestUtils { * Create and insert a PhysicalPartition element (in the repositoryModel) and an associated PhysicalModel. * @return [modeledElementId, modelId] */ - public static async createAndInsertPhysicalPartitionAndModelAsync(testImodel: IModelDb, newModelCode: CodeProps, privateModel: boolean = false, parentId?: Id64String): Promise { + public static async createAndInsertPhysicalPartitionAndModelAsync( + testImodel: IModelDb, + newModelCode: CodeProps, + privateModel: boolean = false, + parentId?: Id64String, + ): Promise { const eid = await IModelTestUtils.createAndInsertPhysicalPartitionAsync(testImodel, newModelCode, parentId); const modeledElementRef = new RelatedElement({ id: eid }); const mid = await IModelTestUtils.createAndInsertPhysicalModelAsync(testImodel, modeledElementRef, privateModel); @@ -418,7 +551,11 @@ export class IModelTestUtils { /** Create and insert a DrawingModel associated with Drawing Partition. */ public static createAndInsertDrawingModel(testDb: IModelDb, modeledElementRef: RelatedElement, privateModel: boolean = false): Id64String { - const newModel = testDb.models.createModel({ modeledElement: modeledElementRef, classFullName: DrawingModel.classFullName, isPrivate: privateModel }); + const newModel = testDb.models.createModel({ + modeledElement: modeledElementRef, + classFullName: DrawingModel.classFullName, + isPrivate: privateModel, + }); const newModelId = newModel.insert(); assert.isTrue(Id64.isValidId64(newModelId)); assert.isTrue(Id64.isValidId64(newModel.id)); @@ -430,7 +567,12 @@ export class IModelTestUtils { * Create and insert a Drawing Partition element (in the repositoryModel) and an associated DrawingModel. * @return [modeledElementId, modelId] */ - public static createAndInsertDrawingPartitionAndModel(testImodel: IModelDb, newModelCode: CodeProps, privateModel: boolean = false, parent?: Id64String): Id64String[] { + public static createAndInsertDrawingPartitionAndModel( + testImodel: IModelDb, + newModelCode: CodeProps, + privateModel: boolean = false, + parent?: Id64String, + ): Id64String[] { const eid = IModelTestUtils.createAndInsertDrawingPartition(testImodel, newModelCode, parent); const modeledElementRef = new RelatedElement({ id: eid }); const mid = IModelTestUtils.createAndInsertDrawingModel(testImodel, modeledElementRef, privateModel); @@ -545,22 +687,46 @@ export class IModelTestUtils { const length = 1.0; const entryOrigin = Point3d.createZero(); const geometryStreamBuilder = new GeometryStreamBuilder(); - geometryStreamBuilder.appendGeometry(Box.createDgnBox( - entryOrigin, Vector3d.unitX(), Vector3d.unitY(), new Point3d(0, 0, length), - length, length, length, length, true, - )!); + geometryStreamBuilder.appendGeometry( + Box.createDgnBox( + entryOrigin, + Vector3d.unitX(), + Vector3d.unitY(), + new Point3d(0, 0, length), + length, + length, + length, + length, + true, + )!, + ); for (const subCategoryId of subCategoryIds) { entryOrigin.addInPlace({ x: 1, y: 1, z: 1 }); geometryStreamBuilder.appendSubCategoryChange(subCategoryId); - geometryStreamBuilder.appendGeometry(Box.createDgnBox( - entryOrigin, Vector3d.unitX(), Vector3d.unitY(), new Point3d(0, 0, length), - length, length, length, length, true, - )!); + geometryStreamBuilder.appendGeometry( + Box.createDgnBox( + entryOrigin, + Vector3d.unitX(), + Vector3d.unitY(), + new Point3d(0, 0, length), + length, + length, + length, + length, + true, + )!, + ); } return geometryStreamBuilder.geometryStream; } - public static createBox(size: Point3d, categoryId?: Id64String, subCategoryId?: Id64String, renderMaterialId?: Id64String, geometryPartId?: Id64String): GeometryStreamProps { + public static createBox( + size: Point3d, + categoryId?: Id64String, + subCategoryId?: Id64String, + renderMaterialId?: Id64String, + geometryPartId?: Id64String, + ): GeometryStreamProps { const geometryStreamBuilder = new GeometryStreamBuilder(); if ((undefined !== categoryId) && (undefined !== subCategoryId)) { geometryStreamBuilder.appendSubCategoryChange(subCategoryId); @@ -570,10 +736,19 @@ export class IModelTestUtils { geometryStreamBuilder.appendGeometryParamsChange(geometryParams); } } - geometryStreamBuilder.appendGeometry(Box.createDgnBox( - Point3d.createZero(), Vector3d.unitX(), Vector3d.unitY(), new Point3d(0, 0, size.z), - size.x, size.y, size.x, size.y, true, - )!); + geometryStreamBuilder.appendGeometry( + Box.createDgnBox( + Point3d.createZero(), + Vector3d.unitX(), + Vector3d.unitY(), + new Point3d(0, 0, size.z), + size.x, + size.y, + size.x, + size.y, + true, + )!, + ); if (undefined !== geometryPartId) { geometryStreamBuilder.appendGeometryPart3d(geometryPartId); } @@ -603,23 +778,161 @@ export class IModelTestUtils { public static insertTextureElement(iModelDb: IModelDb, modelId: Id64String, textureName: string): Id64String { // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in bottom right pixel. The rest of the square is red. - const pngData = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]; + const pngData = [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]; const textureData = Buffer.from(pngData).toString("base64"); return Texture.insertTexture(iModelDb, modelId, textureName, ImageSourceFormat.Png, textureData, `Description for ${textureName}`); } public static queryByUserLabel(iModelDb: IModelDb, userLabel: string): Id64String { - return iModelDb.withPreparedStatement(`SELECT ECInstanceId FROM ${Element.classFullName} WHERE UserLabel=:userLabel`, (statement: ECSqlStatement): Id64String => { - statement.bindString("userLabel", userLabel); - return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getId() : Id64.invalid; - }); + return iModelDb.withPreparedStatement( + `SELECT ECInstanceId FROM ${Element.classFullName} WHERE UserLabel=:userLabel`, + (statement: ECSqlStatement): Id64String => { + statement.bindString("userLabel", userLabel); + return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getId() : Id64.invalid; + }, + ); } public static queryByCodeValue(iModelDb: IModelDb, codeValue: string): Id64String { - return iModelDb.withPreparedStatement(`SELECT ECInstanceId FROM ${Element.classFullName} WHERE CodeValue=:codeValue`, (statement: ECSqlStatement): Id64String => { - statement.bindString("codeValue", codeValue); - return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getId() : Id64.invalid; - }); + return iModelDb.withPreparedStatement( + `SELECT ECInstanceId FROM ${Element.classFullName} WHERE CodeValue=:codeValue`, + (statement: ECSqlStatement): Id64String => { + statement.bindString("codeValue", codeValue); + return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getId() : Id64.invalid; + }, + ); } public static insertRepositoryLink(iModelDb: IModelDb, codeValue: string, url: string, format: string): Id64String { @@ -676,13 +989,16 @@ export class IModelTestUtils { } }); IModelJsFs.appendFileSync(outputFileName, "\n=== ViewDefinitions ===\n"); - iModelDb.withPreparedStatement(`SELECT ECInstanceId FROM ${ViewDefinition.classFullName} ORDER BY ECInstanceId`, (statement: ECSqlStatement): void => { - while (DbResult.BE_SQLITE_ROW === statement.step()) { - const viewDefinitionId = statement.getValue(0).getId(); - const viewDefinition: ViewDefinition = iModelDb.elements.getElement(viewDefinitionId); - IModelJsFs.appendFileSync(outputFileName, `${viewDefinitionId}, ${viewDefinition.code.value}, ${viewDefinition.classFullName}\n`); - } - }); + iModelDb.withPreparedStatement( + `SELECT ECInstanceId FROM ${ViewDefinition.classFullName} ORDER BY ECInstanceId`, + (statement: ECSqlStatement): void => { + while (DbResult.BE_SQLITE_ROW === statement.step()) { + const viewDefinitionId = statement.getValue(0).getId(); + const viewDefinition: ViewDefinition = iModelDb.elements.getElement(viewDefinitionId); + IModelJsFs.appendFileSync(outputFileName, `${viewDefinitionId}, ${viewDefinition.code.value}, ${viewDefinition.classFullName}\n`); + } + }, + ); IModelJsFs.appendFileSync(outputFileName, "\n=== Elements ===\n"); iModelDb.withPreparedStatement(`SELECT COUNT(*) FROM ${Element.classFullName}`, (statement: ECSqlStatement): void => { if (DbResult.BE_SQLITE_ROW === statement.step()) { @@ -717,7 +1033,6 @@ export class ExtensiveTestScenario { } public static populateDb(sourceDb: IModelDb): void { - // make sure Arial is in the font table sourceDb.addNewFont("Arial"); assert.exists(sourceDb.fontMap.getFont("Arial")); @@ -766,7 +1081,10 @@ export class ExtensiveTestScenario { assert.isTrue(Id64.isValidId64(filteredSubCategoryId)); const drawingCategoryId = DrawingCategory.insert(sourceDb, definitionModelId, "DrawingCategory", new SubCategoryAppearance()); assert.isTrue(Id64.isValidId64(drawingCategoryId)); - const spatialCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "SpatialCategories", [spatialCategoryId, sourcePhysicalCategoryId]); + const spatialCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "SpatialCategories", [ + spatialCategoryId, + sourcePhysicalCategoryId, + ]); assert.isTrue(Id64.isValidId64(spatialCategorySelectorId)); const drawingCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "DrawingCategories", [drawingCategoryId]); assert.isTrue(Id64.isValidId64(drawingCategorySelectorId)); @@ -1007,10 +1325,27 @@ export class ExtensiveTestScenario { const displayStyle3dId = displayStyle3d.insert(); assert.isTrue(Id64.isValidId64(displayStyle3dId)); // Insert ViewDefinitions - const viewId = OrthographicViewDefinition.insert(sourceDb, definitionModelId, "Orthographic View", modelSelectorId, spatialCategorySelectorId, displayStyle3dId, projectExtents, StandardViewIndex.Iso); + const viewId = OrthographicViewDefinition.insert( + sourceDb, + definitionModelId, + "Orthographic View", + modelSelectorId, + spatialCategorySelectorId, + displayStyle3dId, + projectExtents, + StandardViewIndex.Iso, + ); assert.isTrue(Id64.isValidId64(viewId)); const drawingViewRange = new Range2d(0, 0, 100, 100); - const drawingViewId = DrawingViewDefinition.insert(sourceDb, definitionModelId, "Drawing View", drawingId, drawingCategorySelectorId, displayStyle2dId, drawingViewRange); + const drawingViewId = DrawingViewDefinition.insert( + sourceDb, + definitionModelId, + "Drawing View", + drawingId, + drawingCategorySelectorId, + displayStyle2dId, + drawingViewRange, + ); assert.isTrue(Id64.isValidId64(drawingViewId)); // Insert instance of SourceRelToExclude to test relationship exclusion by class const relationship1: Relationship = sourceDb.relationships.createInstance({ @@ -1050,9 +1385,13 @@ export class ExtensiveTestScenario { spatialCategory.federationGuid = Guid.createValue(); sourceDb.elements.updateElement(spatialCategory.toJSON()); // Update relationship properties - const spatialCategorySelectorId = sourceDb.elements.queryElementIdByCode(CategorySelector.createCode(sourceDb, definitionModelId, "SpatialCategories"))!; + const spatialCategorySelectorId = sourceDb.elements.queryElementIdByCode( + CategorySelector.createCode(sourceDb, definitionModelId, "SpatialCategories"), + )!; assert.isTrue(Id64.isValidId64(spatialCategorySelectorId)); - const drawingCategorySelectorId = sourceDb.elements.queryElementIdByCode(CategorySelector.createCode(sourceDb, definitionModelId, "DrawingCategories"))!; + const drawingCategorySelectorId = sourceDb.elements.queryElementIdByCode( + CategorySelector.createCode(sourceDb, definitionModelId, "DrawingCategories"), + )!; assert.isTrue(Id64.isValidId64(drawingCategorySelectorId)); const relWithProps: any = sourceDb.relationships.getInstanceProps( "ExtensiveTestScenario:SourceRelWithProps", @@ -1105,7 +1444,10 @@ export class ExtensiveTestScenario { // delete relationship const drawingGraphicId1 = IModelTestUtils.queryByUserLabel(sourceDb, "DrawingGraphic1"); const drawingGraphicId2 = IModelTestUtils.queryByUserLabel(sourceDb, "DrawingGraphic2"); - const relationship: Relationship = sourceDb.relationships.getInstance(DrawingGraphicRepresentsElement.classFullName, { sourceId: drawingGraphicId2, targetId: physicalObjectId1 }); + const relationship: Relationship = sourceDb.relationships.getInstance(DrawingGraphicRepresentsElement.classFullName, { + sourceId: drawingGraphicId2, + targetId: physicalObjectId1, + }); relationship.delete(); // insert relationships DrawingGraphicRepresentsElement.insert(sourceDb, drawingGraphicId1, physicalObjectId5); @@ -1145,9 +1487,13 @@ export class ExtensiveTestScenario { const spatialCategory: SpatialCategory = iModelDb.elements.getElement(spatialCategoryId); assert.exists(spatialCategory.federationGuid); // assert TargetRelWithProps was updated - const spatialCategorySelectorId = iModelDb.elements.queryElementIdByCode(CategorySelector.createCode(iModelDb, definitionModelId, "SpatialCategories"))!; + const spatialCategorySelectorId = iModelDb.elements.queryElementIdByCode( + CategorySelector.createCode(iModelDb, definitionModelId, "SpatialCategories"), + )!; assert.isTrue(Id64.isValidId64(spatialCategorySelectorId)); - const drawingCategorySelectorId = iModelDb.elements.queryElementIdByCode(CategorySelector.createCode(iModelDb, definitionModelId, "DrawingCategories"))!; + const drawingCategorySelectorId = iModelDb.elements.queryElementIdByCode( + CategorySelector.createCode(iModelDb, definitionModelId, "DrawingCategories"), + )!; assert.isTrue(Id64.isValidId64(drawingCategorySelectorId)); const relClassFullName = testTargetSchema ? "ExtensiveTestScenarioTarget:TargetRelWithProps" : "ExtensiveTestScenario:SourceRelWithProps"; const relWithProps: any = iModelDb.relationships.getInstanceProps( @@ -1158,7 +1504,9 @@ export class ExtensiveTestScenario { assert.equal(testTargetSchema ? relWithProps.targetDouble : relWithProps.sourceDouble, 1.2); // assert ElementAspect properties const physicalObjectId1 = IModelTestUtils.queryByUserLabel(iModelDb, "PhysicalObject1"); - const uniqueAspectClassFullName = testTargetSchema ? "ExtensiveTestScenarioTarget:TargetUniqueAspect" : "ExtensiveTestScenario:SourceUniqueAspect"; + const uniqueAspectClassFullName = testTargetSchema + ? "ExtensiveTestScenarioTarget:TargetUniqueAspect" + : "ExtensiveTestScenario:SourceUniqueAspect"; const uniqueAspects: ElementAspect[] = iModelDb.elements.getAspects(physicalObjectId1, uniqueAspectClassFullName); assert.equal(uniqueAspects.length, 1); const uniqueAspect = uniqueAspects[0].asAny; @@ -1212,19 +1560,38 @@ export class ExtensiveTestScenario { // assert InformationRecord2 was updated const informationRecordCodeSpec: CodeSpec = iModelDb.codeSpecs.getByName("InformationRecords"); const informationModelId = iModelDb.elements.queryElementIdByCode(InformationPartitionElement.createCode(iModelDb, subjectId, "Information"))!; - const informationRecordId2 = iModelDb.elements.queryElementIdByCode(new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord2" })); + const informationRecordId2 = iModelDb.elements.queryElementIdByCode( + new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord2" }), + ); assert.isTrue(Id64.isValidId64(informationRecordId2!)); const informationRecord2: any = iModelDb.elements.getElement(informationRecordId2!); assert.equal(informationRecord2.commonString, "Common2-Updated"); assert.equal(testTargetSchema ? informationRecord2.targetString : informationRecord2.sourceString, "Two-Updated"); // assert InformationRecord3 was deleted - assert.isDefined(iModelDb.elements.queryElementIdByCode(new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord1" }))); - assert.isDefined(iModelDb.elements.queryElementIdByCode(new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord2" }))); + assert.isDefined( + iModelDb.elements.queryElementIdByCode( + new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord1" }), + ), + ); + assert.isDefined( + iModelDb.elements.queryElementIdByCode( + new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord2" }), + ), + ); // detect deletes if possible - cannot detect during processAll when isReverseSynchronization is true if (assertDeletes) { assert.equal(Id64.invalid, IModelTestUtils.queryByUserLabel(iModelDb, "PhysicalObject3")); - assert.throws(() => iModelDb.relationships.getInstanceProps(DrawingGraphicRepresentsElement.classFullName, { sourceId: drawingGraphicId2, targetId: physicalObjectId1 })); - assert.isUndefined(iModelDb.elements.queryElementIdByCode(new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord3" }))); + assert.throws(() => + iModelDb.relationships.getInstanceProps(DrawingGraphicRepresentsElement.classFullName, { + sourceId: drawingGraphicId2, + targetId: physicalObjectId1, + }) + ); + assert.isUndefined( + iModelDb.elements.queryElementIdByCode( + new Code({ spec: informationRecordCodeSpec.id, scope: informationModelId, value: "InformationRecord3" }), + ), + ); } } } diff --git a/core/backend/src/test/KnownTestLocations.ts b/core/backend/src/test/KnownTestLocations.ts index d148fdfbc958..3ffeb35d8083 100644 --- a/core/backend/src/test/KnownTestLocations.ts +++ b/core/backend/src/test/KnownTestLocations.ts @@ -2,12 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { join } from "path"; -import { tmpdir } from "os"; import { ProcessDetector } from "@itwin/core-bentley"; +import { tmpdir } from "os"; +import { join } from "path"; export class KnownTestLocations { - /** The directory where test assets are stored. Keep in mind that the test is playing the role of the app. */ public static get assetsDir(): string { if (ProcessDetector.isMobileAppBackend) { diff --git a/core/backend/src/test/PrintElementTree.ts b/core/backend/src/test/PrintElementTree.ts index 1d73d7c2dfe2..55079cf160e1 100644 --- a/core/backend/src/test/PrintElementTree.ts +++ b/core/backend/src/test/PrintElementTree.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { DbResult, Id64String, Logger } from "@itwin/core-bentley"; +import { Element } from "../Element"; import { IModelDb } from "../IModelDb"; import { Model } from "../Model"; -import { Element } from "../Element"; export function fmtElement(iModel: IModelDb, elementId: Id64String): string { const el = iModel.elements.getElement(elementId); diff --git a/core/backend/src/test/PropertyDb.test.ts b/core/backend/src/test/PropertyDb.test.ts index da0465466237..dcdc85766217 100644 --- a/core/backend/src/test/PropertyDb.test.ts +++ b/core/backend/src/test/PropertyDb.test.ts @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { OpenMode } from "@itwin/core-bentley"; import { expect } from "chai"; import { existsSync } from "fs"; import { Suite } from "mocha"; import { join } from "path"; -import { OpenMode } from "@itwin/core-bentley"; import { IModelHost } from "../IModelHost"; import { PropertyStore } from "../PropertyStore"; import { KnownTestLocations } from "./KnownTestLocations"; -describe("PropertyDb", function (this: Suite) { +describe("PropertyDb", function(this: Suite) { this.timeout(0); const outputDir = KnownTestLocations.outputDir; diff --git a/core/backend/src/test/RevisionUtility.ts b/core/backend/src/test/RevisionUtility.ts index 4f2e239e9c43..b451258a2eb6 100644 --- a/core/backend/src/test/RevisionUtility.ts +++ b/core/backend/src/test/RevisionUtility.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { BentleyStatus } from "@itwin/core-bentley"; -import { IModelNative } from "../internal/NativePlatform"; import { IModelJsFs } from "../IModelJsFs"; +import { IModelNative } from "../internal/NativePlatform"; export interface LzmaParams { dictSize?: number; @@ -64,7 +64,12 @@ export class RevisionUtility { throw new Error("RawChangesetFile does not exists"); if (prefixFile && !IModelJsFs.existsSync(prefixFile)) throw new Error("prefixFile does not exists"); - return IModelNative.platform.RevisionUtility.assembleRevision(targetFile, rawChangesetFile, prefixFile, lzmaProps ? JSON.stringify(lzmaProps) : undefined); + return IModelNative.platform.RevisionUtility.assembleRevision( + targetFile, + rawChangesetFile, + prefixFile, + lzmaProps ? JSON.stringify(lzmaProps) : undefined, + ); } public static normalizeLzmaParams(lzmaProps?: LzmaParams): LzmaParams { return JSON.parse(IModelNative.platform.RevisionUtility.normalizeLzmaParams(lzmaProps ? JSON.stringify(lzmaProps) : undefined)) as LzmaParams; diff --git a/core/backend/src/test/SchemaUtils.test.ts b/core/backend/src/test/SchemaUtils.test.ts index 9bea71222bcb..8e0c13e0d2f6 100644 --- a/core/backend/src/test/SchemaUtils.test.ts +++ b/core/backend/src/test/SchemaUtils.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { DbResult } from "@itwin/core-bentley"; import { assert } from "chai"; import { convertEC2SchemasToEC3Schemas, ECDb, ECSqlStatement, upgradeCustomAttributesToEC3 } from "../core-backend"; -import { KnownTestLocations } from "./KnownTestLocations"; import { ECDbTestHelper } from "./ecdb/ECDbTestHelper"; -import { DbResult } from "@itwin/core-bentley"; +import { KnownTestLocations } from "./KnownTestLocations"; describe("convertEC2Schemas", () => { it("verify namespace", () => { @@ -63,7 +63,9 @@ describe("convertEC2Schemas", () => { assert.isTrue(db.isOpen); const propNamesInEntityClass = []; - let stmt: ECSqlStatement = db.prepareStatement("SELECT p.Name FROM meta.ECPropertyDef p JOIN meta.ECClassDef c USING meta.ClassOwnsLocalProperties JOIN meta.ECSchemaDef s USING meta.SchemaOwnsClasses WHERE s.Name='TestSchema' AND c.Name='TestEntityClass' ORDER BY p.Ordinal"); + let stmt: ECSqlStatement = db.prepareStatement( + "SELECT p.Name FROM meta.ECPropertyDef p JOIN meta.ECClassDef c USING meta.ClassOwnsLocalProperties JOIN meta.ECSchemaDef s USING meta.SchemaOwnsClasses WHERE s.Name='TestSchema' AND c.Name='TestEntityClass' ORDER BY p.Ordinal", + ); let rowCount = 0; while (stmt.step() === DbResult.BE_SQLITE_ROW) { rowCount++; @@ -73,21 +75,23 @@ describe("convertEC2Schemas", () => { stmt.dispose(); assert.equal(rowCount, 9); - assert.isFalse(propNamesInEntityClass.includes("Id")); // The Id property is a reserved keyword and should have been renamed + assert.isFalse(propNamesInEntityClass.includes("Id")); // The Id property is a reserved keyword and should have been renamed assert.isFalse(propNamesInEntityClass.includes("ECClassId")); // The ECClassId property is a reserved keyword and should have been renamed - assert.isFalse(propNamesInEntityClass.includes("ECInstanceId")); // The ECInstanceId property is a reserved keyword and should have been renamed + assert.isFalse(propNamesInEntityClass.includes("ECInstanceId")); // The ECInstanceId property is a reserved keyword and should have been renamed assert.isTrue(propNamesInEntityClass.includes("TestSchema_Id_")); // The Id property is a reserved keyword and should have been renamed - assert.isTrue(propNamesInEntityClass.includes("TestSchema_ECClassId_")); // The ECClassId property is a reserved keyword and should have been renamed + assert.isTrue(propNamesInEntityClass.includes("TestSchema_ECClassId_")); // The ECClassId property is a reserved keyword and should have been renamed assert.isTrue(propNamesInEntityClass.includes("TestSchema_ECInstanceId_")); // The ECInstanceId property is a reserved keyword and should have been renamed assert.isTrue(propNamesInEntityClass.includes("SourceECInstanceId")); // The SourceECInstanceId property is allowed on Entity classes and should not be renamed assert.isTrue(propNamesInEntityClass.includes("SourceId")); // The SourceId property is allowed on Entity classes and should not be renamed - assert.isTrue(propNamesInEntityClass.includes("SourceECClassId")); // The SourceECClassId property is allowed on Entity classes and should not be renamed + assert.isTrue(propNamesInEntityClass.includes("SourceECClassId")); // The SourceECClassId property is allowed on Entity classes and should not be renamed assert.isTrue(propNamesInEntityClass.includes("TargetECInstanceId")); // The TargetECInstanceId property is allowed on Entity classes and should not be renamed assert.isTrue(propNamesInEntityClass.includes("TargetId")); // The TargetId property is allowed on Entity classes and should not be renamed - assert.isTrue(propNamesInEntityClass.includes("TargetECClassId")); // The TargetECClassId property is allowed on Entity classes and should not be renamed + assert.isTrue(propNamesInEntityClass.includes("TargetECClassId")); // The TargetECClassId property is allowed on Entity classes and should not be renamed const propNamesInStructClass = []; - stmt = db.prepareStatement("SELECT p.Name FROM meta.ECPropertyDef p JOIN meta.ECClassDef c USING meta.ClassOwnsLocalProperties JOIN meta.ECSchemaDef s USING meta.SchemaOwnsClasses WHERE s.Name='TestSchema' AND c.Name='TestStructClass' ORDER BY p.Ordinal"); + stmt = db.prepareStatement( + "SELECT p.Name FROM meta.ECPropertyDef p JOIN meta.ECClassDef c USING meta.ClassOwnsLocalProperties JOIN meta.ECSchemaDef s USING meta.SchemaOwnsClasses WHERE s.Name='TestSchema' AND c.Name='TestStructClass' ORDER BY p.Ordinal", + ); rowCount = 0; while (stmt.step() === DbResult.BE_SQLITE_ROW) { rowCount++; @@ -98,10 +102,10 @@ describe("convertEC2Schemas", () => { assert.equal(rowCount, 3); assert.isTrue(propNamesInStructClass.includes("Id")); // The Id property is not a reserved keyword for Struct classes and should not be renamed - assert.isTrue(propNamesInStructClass.includes("ECClassId")); // The ECClassId property is not a reserved keyword for Struct classes and should not be renamed + assert.isTrue(propNamesInStructClass.includes("ECClassId")); // The ECClassId property is not a reserved keyword for Struct classes and should not be renamed assert.isTrue(propNamesInStructClass.includes("ECInstanceId")); // The ECInstanceId property is not a reserved keyword for Struct classes and should not be renamed - assert.isFalse(propNamesInStructClass.includes("TestSchema_Id_")); // The Id property is not a reserved keyword for Struct classes and should not be renamed + assert.isFalse(propNamesInStructClass.includes("TestSchema_Id_")); // The Id property is not a reserved keyword for Struct classes and should not be renamed assert.isFalse(propNamesInStructClass.includes("TestSchema_ECClassId_")); // The ECClassId property is not a reserved keyword for Struct classes and should not be renamed - assert.isFalse(propNamesInStructClass.includes("TestSchema_ECInstanceId_")); // The ECInstanceId property is not a reserved keyword for Struct classes and should not be renamed + assert.isFalse(propNamesInStructClass.includes("TestSchema_ECInstanceId_")); // The ECInstanceId property is not a reserved keyword for Struct classes and should not be renamed }); }); diff --git a/core/backend/src/test/SequentialLogMatcher.ts b/core/backend/src/test/SequentialLogMatcher.ts index 1a7974ab1df9..8848986f3fb6 100644 --- a/core/backend/src/test/SequentialLogMatcher.ts +++ b/core/backend/src/test/SequentialLogMatcher.ts @@ -71,7 +71,9 @@ export class SequentialLogMatcher extends Logger { Logger._logTrace = this._originalLogTrace; return rc; } - public get length(): number { return this._rules.length; } + public get length(): number { + return this._rules.length; + } } export class LogMatchRule { diff --git a/core/backend/src/test/TestChangeSetUtility.ts b/core/backend/src/test/TestChangeSetUtility.ts index aa4f574283f8..e15dc62360e2 100644 --- a/core/backend/src/test/TestChangeSetUtility.ts +++ b/core/backend/src/test/TestChangeSetUtility.ts @@ -27,12 +27,21 @@ export class TestChangeSetUtility { } private async addTestModel(): Promise { - [, this._modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(this._iModel, IModelTestUtils.getUniqueModelCode(this._iModel, "TestPhysicalModel"), true); + [, this._modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( + this._iModel, + IModelTestUtils.getUniqueModelCode(this._iModel, "TestPhysicalModel"), + true, + ); this._iModel.saveChanges("Added test model"); } private async addTestCategory(): Promise { - this._categoryId = SpatialCategory.insert(this._iModel, IModel.dictionaryId, "TestSpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + this._categoryId = SpatialCategory.insert( + this._iModel, + IModel.dictionaryId, + "TestSpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); this._iModel.saveChanges("Added test category"); } @@ -49,7 +58,12 @@ export class TestChangeSetUtility { this.iTwinId = HubMock.iTwinId; // Re-create iModel on iModelHub - this.iModelId = await HubWrappers.recreateIModel({ accessToken: this._accessToken, iTwinId: this.iTwinId, iModelName: this._iModelName, noLocks: true }); + this.iModelId = await HubWrappers.recreateIModel({ + accessToken: this._accessToken, + iTwinId: this.iTwinId, + iModelName: this._iModelName, + noLocks: true, + }); this._iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken: this._accessToken, iTwinId: this.iTwinId, iModelId: this.iModelId }); this._iModel.channels.addAllowedChannel(ChannelControl.sharedChannelName); diff --git a/core/backend/src/test/TestUtils.ts b/core/backend/src/test/TestUtils.ts index 6dcad49c14e8..814e00ff7495 100644 --- a/core/backend/src/test/TestUtils.ts +++ b/core/backend/src/test/TestUtils.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import { IModelJsNative, NativeLoggerCategory } from "@bentley/imodeljs-native"; import { BentleyLoggerCategory, IDisposable, Logger, LogLevel, ProcessDetector } from "@itwin/core-bentley"; +import * as path from "path"; import { BackendLoggerCategory } from "../BackendLoggerCategory"; import { IModelHost, IModelHostOptions } from "../IModelHost"; import { IModelNative } from "../internal/NativePlatform"; @@ -108,4 +108,3 @@ before(async () => { after(async () => { await TestUtils.shutdownBackend(); }); - diff --git a/core/backend/src/test/annotations/TextAnnotation.test.ts b/core/backend/src/test/annotations/TextAnnotation.test.ts index 4795ce3bc00e..015469fa5d34 100644 --- a/core/backend/src/test/annotations/TextAnnotation.test.ts +++ b/core/backend/src/test/annotations/TextAnnotation.test.ts @@ -2,16 +2,43 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { computeGraphemeOffsets, ComputeGraphemeOffsetsArgs, ComputeRangesForTextLayout, ComputeRangesForTextLayoutArgs, FindFontId, FindTextStyle, layoutTextBlock, LineLayout, RunLayout, TextBlockLayout, TextLayoutRanges } from "../../TextAnnotationLayout"; +import { Id64, ProcessDetector } from "@itwin/core-bentley"; +import { + ColorDef, + FontMap, + FractionRun, + LineBreakRun, + LineLayoutResult, + Run, + RunLayoutResult, + TextAnnotation, + TextAnnotation2dProps, + TextAnnotation3dProps, + TextBlock, + TextBlockGeometryPropsEntry, + TextRun, + TextStyleSettings, +} from "@itwin/core-common"; import { Range2d } from "@itwin/core-geometry"; -import { ColorDef, FontMap, FractionRun, LineBreakRun, LineLayoutResult, Run, RunLayoutResult, TextAnnotation, TextAnnotation2dProps, TextAnnotation3dProps, TextBlock, TextBlockGeometryPropsEntry, TextRun, TextStyleSettings } from "@itwin/core-common"; +import { assert, expect } from "chai"; +import { GeometricElement3d } from "../../Element"; import { IModelDb, SnapshotDb } from "../../IModelDb"; import { TextAnnotation2d, TextAnnotation3d } from "../../TextAnnotationElement"; import { produceTextAnnotationGeometry } from "../../TextAnnotationGeometry"; +import { + computeGraphemeOffsets, + ComputeGraphemeOffsetsArgs, + ComputeRangesForTextLayout, + ComputeRangesForTextLayoutArgs, + FindFontId, + FindTextStyle, + layoutTextBlock, + LineLayout, + RunLayout, + TextBlockLayout, + TextLayoutRanges, +} from "../../TextAnnotationLayout"; import { IModelTestUtils } from "../IModelTestUtils"; -import { GeometricElement3d } from "../../Element"; -import { Id64, ProcessDetector } from "@itwin/core-bentley"; function computeTextRangeAsStringLength(args: ComputeRangesForTextLayoutArgs): TextLayoutRanges { const range = new Range2d(0, 0, args.chars.length, args.lineHeight); @@ -47,14 +74,15 @@ function isIntlSupported(): boolean { describe("layoutTextBlock", () => { it("resolves TextStyleSettings from combination of TextBlock and Run", () => { - const textBlock = TextBlock.create({ styleName: "block", styleOverrides: { widthFactor: 34, color: 0x00ff00 }}); - const run0 = TextRun.create({ content: "run0", styleName: "run", styleOverrides: { lineHeight: 56, color: 0xff0000 }}); - const run1 = TextRun.create({ content: "run1", styleName: "run", styleOverrides: { widthFactor: 78, fontName: "run1" }}); + const textBlock = TextBlock.create({ styleName: "block", styleOverrides: { widthFactor: 34, color: 0x00ff00 } }); + const run0 = TextRun.create({ content: "run0", styleName: "run", styleOverrides: { lineHeight: 56, color: 0xff0000 } }); + const run1 = TextRun.create({ content: "run1", styleName: "run", styleOverrides: { widthFactor: 78, fontName: "run1" } }); textBlock.appendRun(run0); textBlock.appendRun(run1); - const tb = doLayout(textBlock,{ - findTextStyle: (name: string) => TextStyleSettings.fromJSON(name === "block" ? { lineSpacingFactor: 12, fontName: "block" } : { lineSpacingFactor: 99, fontName: "run" }), + const tb = doLayout(textBlock, { + findTextStyle: (name: string) => + TextStyleSettings.fromJSON(name === "block" ? { lineSpacingFactor: 12, fontName: "block" } : { lineSpacingFactor: 99, fontName: "run" }), }); expect(tb.lines.length).to.equal(1); @@ -119,7 +147,7 @@ describe("layoutTextBlock", () => { expect(line.range.low.y).to.equal(0); expect(line.range.high.y).to.equal(1); expect(line.range.high.x).to.equal(3 * (l + 1)); - for (const run of line.runs){ + for (const run of line.runs) { expect(run.charOffset).to.equal(0); expect(run.numChars).to.equal(3); expect(run.range.low.x).to.equal(0); @@ -145,7 +173,7 @@ describe("layoutTextBlock", () => { textBlock.appendRun(TextRun.create({ styleName: "", content: "def" })); textBlock.appendRun(TextRun.create({ styleName: "", content: "ghi" })); textBlock.appendRun(LineBreakRun.create({ styleName: "" })); - textBlock.appendRun(TextRun.create({ styleName: "", content: "jkl"})); + textBlock.appendRun(TextRun.create({ styleName: "", content: "jkl" })); const tb = doLayout(textBlock); expect(tb.lines.length).to.equal(3); @@ -168,7 +196,7 @@ describe("layoutTextBlock", () => { textBlock.appendRun(TextRun.create({ styleName: "", content: "def" })); textBlock.appendRun(TextRun.create({ styleName: "", content: "ghi" })); textBlock.appendRun(LineBreakRun.create({ styleName: "" })); - textBlock.appendRun(TextRun.create({ styleName: "", content: "jkl"})); + textBlock.appendRun(TextRun.create({ styleName: "", content: "jkl" })); const tb = doLayout(textBlock); expect(tb.lines.length).to.equal(3); @@ -188,7 +216,7 @@ describe("layoutTextBlock", () => { expect(tb.lines.every((line) => line.offsetFromDocument.x === 0)).to.be.true; }); - it("splits paragraphs into multiple lines if runs exceed the document width", function () { + it("splits paragraphs into multiple lines if runs exceed the document width", function() { if (!isIntlSupported()) { this.skip(); } @@ -224,7 +252,7 @@ describe("layoutTextBlock", () => { expect(range.yLength()).to.equal(height); } - it("computes range for wrapped lines", function () { + it("computes range for wrapped lines", function() { if (!isIntlSupported()) { this.skip(); } @@ -257,7 +285,7 @@ describe("layoutTextBlock", () => { expectBlockRange(10, 2); }); - it("computes range for split runs", function () { + it("computes range for split runs", function() { if (!isIntlSupported()) { this.skip(); } @@ -280,7 +308,7 @@ describe("layoutTextBlock", () => { expectBlockRange(10, 2); }); - it("justifies lines", function () { + it("justifies lines", function() { if (!isIntlSupported()) { this.skip(); } @@ -363,13 +391,16 @@ describe("layoutTextBlock", () => { const layout = doLayout(textBlock); expect(layout.lines.every((line) => line.runs.every((r) => r.source === run))).to.be.true; - const actual = layout.lines.map((line) => line.runs.map((runLayout) => (runLayout.source as TextRun).content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)).join("")); + const actual = layout.lines.map((line) => + line.runs.map((runLayout) => (runLayout.source as TextRun).content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)) + .join("") + ); expect(actual).to.deep.equal(expectedLines); return layout; } - it("splits a single TextRun at word boundaries if it exceeds the document width", function () { + it("splits a single TextRun at word boundaries if it exceeds the document width", function() { if (!isIntlSupported()) { this.skip(); } @@ -415,7 +446,7 @@ describe("layoutTextBlock", () => { ]); }); - it("considers consecutive whitespace part of a single 'word'", function () { + it("considers consecutive whitespace part of a single 'word'", function() { if (!isIntlSupported()) { this.skip(); } @@ -430,16 +461,16 @@ describe("layoutTextBlock", () => { ]); }); - it("wraps Japanese text", function () { + it("wraps Japanese text", function() { if (!isIntlSupported()) { this.skip(); } // "I am a cat. The name is Tanuki." - expectLines("吾輩は猫である。名前はたぬき。", 1, ["吾","輩","は","猫","で","あ","る。","名","前","は","た","ぬ","き。"]); + expectLines("吾輩は猫である。名前はたぬき。", 1, ["吾", "輩", "は", "猫", "で", "あ", "る。", "名", "前", "は", "た", "ぬ", "き。"]); }); - it("performs word-wrapping with punctuation", function () { + it("performs word-wrapping with punctuation", function() { if (!isIntlSupported()) { this.skip(); } @@ -459,7 +490,7 @@ describe("layoutTextBlock", () => { ]); }); - it("performs word-wrapping and line-splitting with multiple runs", function () { + it("performs word-wrapping and line-splitting with multiple runs", function() { if (!isIntlSupported()) { this.skip(); } @@ -472,7 +503,10 @@ describe("layoutTextBlock", () => { function test(width: number, expected: string[]): void { textBlock.width = width; const layout = doLayout(textBlock); - const actual = layout.lines.map((line) => line.runs.map((runLayout) => (runLayout.source as TextRun).content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)).join("")); + const actual = layout.lines.map((line) => + line.runs.map((runLayout) => (runLayout.source as TextRun).content.substring(runLayout.charOffset, runLayout.charOffset + runLayout.numChars)) + .join("") + ); expect(actual).to.deep.equal(expected); } @@ -507,7 +541,7 @@ describe("layoutTextBlock", () => { ]); }); - it("wraps multiple runs", function () { + it("wraps multiple runs", function() { if (!isIntlSupported()) { this.skip(); } @@ -551,13 +585,13 @@ describe("layoutTextBlock", () => { expectLayout(-2, "aabb ccc d eeff ggg h"); }); - it("has consistent data when converted to a layout result", function () { + it("has consistent data when converted to a layout result", function() { if (!isIntlSupported()) { this.skip(); } // Initialize a new TextBlockLayout object - const textBlock = TextBlock.create({ width: 50, styleName: "", styleOverrides: { widthFactor: 34, color: 0x00ff00, fontName: "arial" }}); + const textBlock = TextBlock.create({ width: 50, styleName: "", styleOverrides: { widthFactor: 34, color: 0x00ff00, fontName: "arial" } }); const run0 = TextRun.create({ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium mi sit amet magna malesuada, at venenatis ante eleifend.", styleName: "", @@ -569,7 +603,8 @@ describe("layoutTextBlock", () => { styleOverrides: { widthFactor: 78, fontName: "run1" }, }); const run2 = TextRun.create({ - content: "Duis dui quam, suscipit quis feugiat id, fermentum ut augue. Mauris iaculis odio rhoncus lorem eleifend, posuere viverra turpis elementum.", + content: + "Duis dui quam, suscipit quis feugiat id, fermentum ut augue. Mauris iaculis odio rhoncus lorem eleifend, posuere viverra turpis elementum.", styleName: "", styleOverrides: {}, }); @@ -592,7 +627,8 @@ describe("layoutTextBlock", () => { } return 0; }, - }); + }, + ); const result = textBlockLayout.toResult(); // Assert that the result object has the same data as the original TextBlockLayout object @@ -600,7 +636,7 @@ describe("layoutTextBlock", () => { expect(result.lines.length).to.equal(textBlockLayout.lines.length); // Loop through each line in the result and the original object - for(let i = 0; i < result.lines.length; i++) { + for (let i = 0; i < result.lines.length; i++) { const resultLine: LineLayoutResult = result.lines[i]; const originalLine: LineLayout = textBlockLayout.lines[i]; @@ -612,7 +648,7 @@ describe("layoutTextBlock", () => { // Offset matches expect(resultLine.offsetFromDocument).to.deep.equal(originalLine.offsetFromDocument); - for(let j = 0; j < resultLine.runs.length; j++) { + for (let j = 0; j < resultLine.runs.length; j++) { const resultRun: RunLayoutResult = resultLine.runs[j]; const originalRun: RunLayout = originalLine.runs[j]; @@ -668,7 +704,7 @@ describe("layoutTextBlock", () => { }); describe("grapheme offsets", () => { - it("should return an empty array if source type is not text", function () { + it("should return an empty array if source type is not text", function() { const textBlock = TextBlock.create({ styleName: "" }); const fractionRun = FractionRun.create({ numerator: "1", denominator: "2", styleName: "fraction" }); textBlock.appendRun(fractionRun); @@ -690,7 +726,7 @@ describe("layoutTextBlock", () => { expect(graphemeRanges).to.be.an("array").that.is.empty; }); - it("should handle empty text content", function () { + it("should handle empty text content", function() { const textBlock = TextBlock.create({ styleName: "" }); const textRun = TextRun.create({ content: "", styleName: "text" }); textBlock.appendRun(textRun); @@ -712,7 +748,7 @@ describe("layoutTextBlock", () => { expect(graphemeRanges).to.be.an("array").that.is.empty; }); - it("should compute grapheme offsets correctly for a given text", function () { + it("should compute grapheme offsets correctly for a given text", function() { const textBlock = TextBlock.create({ styleName: "" }); const textRun = TextRun.create({ content: "hello", styleName: "text" }); textBlock.appendRun(textRun); @@ -736,7 +772,7 @@ describe("layoutTextBlock", () => { expect(graphemeRanges[4].high.x).to.equal(5); }); - it("should compute grapheme offsets correctly for non-English text", function () { + it("should compute grapheme offsets correctly for non-English text", function() { const textBlock = TextBlock.create({ styleName: "" }); // Hindi - "Paragraph" const textRun = TextRun.create({ content: "अनुच्छेद", styleName: "text" }); @@ -763,7 +799,7 @@ describe("layoutTextBlock", () => { expect(graphemeRanges[3].high.x).to.equal(8); }); - it("should compute grapheme offsets correctly for emoji content", function () { + it("should compute grapheme offsets correctly for emoji content", function() { const textBlock = TextBlock.create({ styleName: "" }); const textRun = TextRun.create({ content: "👨‍👦", styleName: "text" }); textBlock.appendRun(textRun); @@ -831,7 +867,9 @@ describe("layoutTextBlock", () => { // test("aRIaL", arial); }); - function computeDimensions(args: { content?: string, bold?: boolean, italic?: boolean, font?: string, height?: number, width?: number }): { x: number, y: number } { + function computeDimensions( + args: { content?: string, bold?: boolean, italic?: boolean, font?: string, height?: number, width?: number }, + ): { x: number, y: number } { const textBlock = TextBlock.create({ styleName: "", styleOverrides: { @@ -889,7 +927,7 @@ describe("layoutTextBlock", () => { } function test(chars: string, expectEqualRanges: boolean): void { - const { justification, layout }= computeRanges(chars); + const { justification, layout } = computeRanges(chars); expect(layout.low.x).to.equal(justification.low.x); expect(layout.high.y).to.equal(justification.high.y); expect(layout.low.y).to.equal(justification.low.y); @@ -926,7 +964,9 @@ describe("layoutTextBlock", () => { function mockIModel(): IModelDb { const iModel: Pick = { fontMap: new FontMap(), - computeRangesForText: () => { return { layout: new Range2d(0, 0, 1, 1), justification: new Range2d(0, 0, 1, 1) }; }, + computeRangesForText: () => { + return { layout: new Range2d(0, 0, 1, 1), justification: new Range2d(0, 0, 1, 1) }; + }, forEachMetaData: () => undefined, }; @@ -1012,7 +1052,9 @@ describe("produceTextAnnotationGeometry", () => { makeText(ColorDef.green), makeBreak(ColorDef.black), makeText(ColorDef.green), - ]).map((entry) => entry.text ? "text" : (entry.separator ? "sep" : (typeof entry.color === "number" ? ColorDef.fromJSON(entry.color) : entry.color))); + ]).map((entry) => + entry.text ? "text" : (entry.separator ? "sep" : (typeof entry.color === "number" ? ColorDef.fromJSON(entry.color) : entry.color)) + ); expect(geom).to.deep.equal([ ColorDef.blue, @@ -1026,7 +1068,9 @@ describe("produceTextAnnotationGeometry", () => { "text", "text", ColorDef.green, - "text", "sep", "text", + "text", + "sep", + "text", "text", "text", ]); diff --git a/core/backend/src/test/assets/TestSettings.schema.json b/core/backend/src/test/assets/TestSettings.schema.json index e37507b30530..7c4ad78f4c5c 100644 --- a/core/backend/src/test/assets/TestSettings.schema.json +++ b/core/backend/src/test/assets/TestSettings.schema.json @@ -92,4 +92,4 @@ } } } -} \ No newline at end of file +} diff --git a/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTest.json b/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTest.json index 88809b6df1d8..49e257cfc082 100644 --- a/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTest.json +++ b/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTest.json @@ -1 +1,15 @@ -[{"instanceId":"0aea4c09-09f4-449d-bf47-045228d259ba","schemaName":"ContextScope","className":"iModel","properties":{"Description":"","Name":"NoVersionsTest","UserCreated":"fae2f5d1-abb1-4b0b-96c7-87259f4efe70","CreatedDate":"2018-03-06T11:34:24.357Z","Initialized":true},"eTag":"\"J1mxwZQ/ttLnwP7+m5ijxlU38V4=\""}] \ No newline at end of file +[ + { + "instanceId": "0aea4c09-09f4-449d-bf47-045228d259ba", + "schemaName": "ContextScope", + "className": "iModel", + "properties": { + "Description": "", + "Name": "NoVersionsTest", + "UserCreated": "fae2f5d1-abb1-4b0b-96c7-87259f4efe70", + "CreatedDate": "2018-03-06T11:34:24.357Z", + "Initialized": true + }, + "eTag": "\"J1mxwZQ/ttLnwP7+m5ijxlU38V4=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTestChangeSets.json b/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTestChangeSets.json index 0637a088a01e..fe51488c7066 100644 --- a/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTestChangeSets.json +++ b/core/backend/src/test/assets/_mocks_/NoVersionsTest/NoVersionsTestChangeSets.json @@ -1 +1 @@ -[] \ No newline at end of file +[] diff --git a/core/backend/src/test/assets/_mocks_/Projects/NodeJsTestProject.json b/core/backend/src/test/assets/_mocks_/Projects/NodeJsTestProject.json index 1724812155d2..a9f5bc32b4b8 100644 --- a/core/backend/src/test/assets/_mocks_/Projects/NodeJsTestProject.json +++ b/core/backend/src/test/assets/_mocks_/Projects/NodeJsTestProject.json @@ -24,4 +24,4 @@ }, "eTag": "\"v2ELJ1vHcg9tGemvRcv+JoRtdPM=\"" } -] \ No newline at end of file +] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTest.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTest.json index 64115ac940f8..126c346bbd86 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTest.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTest.json @@ -1 +1,15 @@ -[{"instanceId":"233e1f55-561d-42a4-8e80-d6f91743863e","schemaName":"ContextScope","className":"iModel","properties":{"Description":null,"Name":"ReadOnlyTest","UserCreated":"596c0d8b-eac2-46a0-aa4a-b590c3314e7c","CreatedDate":"2018-04-04T10:50:54.657Z","Initialized":true},"eTag":"\"/ulqWhqyydUQkq2UlszIJ0+Fkuo=\""}] \ No newline at end of file +[ + { + "instanceId": "233e1f55-561d-42a4-8e80-d6f91743863e", + "schemaName": "ContextScope", + "className": "iModel", + "properties": { + "Description": null, + "Name": "ReadOnlyTest", + "UserCreated": "596c0d8b-eac2-46a0-aa4a-b590c3314e7c", + "CreatedDate": "2018-04-04T10:50:54.657Z", + "Initialized": true + }, + "eTag": "\"/ulqWhqyydUQkq2UlszIJ0+Fkuo=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestBriefcase.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestBriefcase.json index 8a089639dd12..77e986a1677d 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestBriefcase.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestBriefcase.json @@ -1 +1,19 @@ -[{"instanceId":"677","schemaName":"iModelScope","className":"Briefcase","properties":{"FileName":"ReadOnlyTest.bim","FileDescription":"","FileSize":"1114112","FileId":"e304ea1d-31ce-4dbf-b6c4-ba5888e3fec1","BriefcaseId":677,"MergedChangeSetId":"1b186c485d182c46c02b99aff4fb12637263438f","UserOwned":"596c0d8b-eac2-46a0-aa4a-b590c3314e7c","AcquiredDate":"2018-04-12T15:30:36.773Z","IsReadOnly":false},"eTag":"\"txjtAuM9DJR7nqT4Nnok5HExw8U=\""}] \ No newline at end of file +[ + { + "instanceId": "677", + "schemaName": "iModelScope", + "className": "Briefcase", + "properties": { + "FileName": "ReadOnlyTest.bim", + "FileDescription": "", + "FileSize": "1114112", + "FileId": "e304ea1d-31ce-4dbf-b6c4-ba5888e3fec1", + "BriefcaseId": 677, + "MergedChangeSetId": "1b186c485d182c46c02b99aff4fb12637263438f", + "UserOwned": "596c0d8b-eac2-46a0-aa4a-b590c3314e7c", + "AcquiredDate": "2018-04-12T15:30:36.773Z", + "IsReadOnly": false + }, + "eTag": "\"txjtAuM9DJR7nqT4Nnok5HExw8U=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestChangeSets.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestChangeSets.json index c3e72d7fb3c1..8df49cb1d331 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestChangeSets.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/ReadOnlyTestChangeSets.json @@ -1 +1,82 @@ -[{"instanceId":"dbe4b3824129f99e4eb485fb7cd9d2fea2354be1","schemaName":"iModelScope","className":"ChangeSet","properties":{"FileName":"dbe4b3824129f99e4eb485fb7cd9d2fea2354be1.cs","Description":"Import Gist Domian","FileSize":"3436","Index":"1","Id":"dbe4b3824129f99e4eb485fb7cd9d2fea2354be1","ParentId":"","SeedFileId":"370cea34-8415-4f81-b54c-85040eb3111e","BriefcaseId":6,"UserCreated":"fae2f5d1-abb1-4b0b-96c7-87259f4efe70","PushDate":"2018-04-04T15:01:48.103Z","ContainingChanges":1,"IsUploaded":true},"eTag":"\"XciMLjhkeRYZin9KTyhxO4brw/k=\""},{"instanceId":"20f94790e4a67782c2bafb93fa9b3955311c3fdb","schemaName":"iModelScope","className":"ChangeSet","properties":{"FileName":"20f94790e4a67782c2bafb93fa9b3955311c3fdb.cs","Description":"$ÿñçhröñìzé ¢hâñgês wîth sêrvér","FileSize":"285","Index":"2","Id":"20f94790e4a67782c2bafb93fa9b3955311c3fdb","ParentId":"dbe4b3824129f99e4eb485fb7cd9d2fea2354be1","SeedFileId":"370cea34-8415-4f81-b54c-85040eb3111e","BriefcaseId":6,"UserCreated":"fae2f5d1-abb1-4b0b-96c7-87259f4efe70","PushDate":"2018-04-04T15:03:48.62Z","ContainingChanges":0,"IsUploaded":true},"eTag":"\"n4crrIEpRs2JUNRgRfTa5tKUWKs=\""},{"instanceId":"eb5075bd61a77c773b4a1e82c89087ba28b31aec","schemaName":"iModelScope","className":"ChangeSet","properties":{"FileName":"eb5075bd61a77c773b4a1e82c89087ba28b31aec.cs","Description":"$ÿñçhröñìzé ¢hâñgês wîth sêrvér","FileSize":"284","Index":"3","Id":"eb5075bd61a77c773b4a1e82c89087ba28b31aec","ParentId":"20f94790e4a67782c2bafb93fa9b3955311c3fdb","SeedFileId":"370cea34-8415-4f81-b54c-85040eb3111e","BriefcaseId":6,"UserCreated":"fae2f5d1-abb1-4b0b-96c7-87259f4efe70","PushDate":"2018-04-04T15:04:35.96Z","ContainingChanges":0,"IsUploaded":true},"eTag":"\"LU8t1u1xog442EDtmHr4ahpw0vg=\""},{"instanceId":"1b186c485d182c46c02b99aff4fb12637263438f","schemaName":"iModelScope","className":"ChangeSet","properties":{"FileName":"1b186c485d182c46c02b99aff4fb12637263438f.cs","Description":"$ÿñçhröñìzé ¢hâñgês wîth sêrvér","FileSize":"283","Index":"4","Id":"1b186c485d182c46c02b99aff4fb12637263438f","ParentId":"eb5075bd61a77c773b4a1e82c89087ba28b31aec","SeedFileId":"370cea34-8415-4f81-b54c-85040eb3111e","BriefcaseId":6,"UserCreated":"fae2f5d1-abb1-4b0b-96c7-87259f4efe70","PushDate":"2018-04-04T15:05:11.993Z","ContainingChanges":0,"IsUploaded":true},"eTag":"\"o5EO6NfPSVv7vo6RuwBEbFRqPGI=\""}] \ No newline at end of file +[ + { + "instanceId": "dbe4b3824129f99e4eb485fb7cd9d2fea2354be1", + "schemaName": "iModelScope", + "className": "ChangeSet", + "properties": { + "FileName": "dbe4b3824129f99e4eb485fb7cd9d2fea2354be1.cs", + "Description": "Import Gist Domian", + "FileSize": "3436", + "Index": "1", + "Id": "dbe4b3824129f99e4eb485fb7cd9d2fea2354be1", + "ParentId": "", + "SeedFileId": "370cea34-8415-4f81-b54c-85040eb3111e", + "BriefcaseId": 6, + "UserCreated": "fae2f5d1-abb1-4b0b-96c7-87259f4efe70", + "PushDate": "2018-04-04T15:01:48.103Z", + "ContainingChanges": 1, + "IsUploaded": true + }, + "eTag": "\"XciMLjhkeRYZin9KTyhxO4brw/k=\"" + }, + { + "instanceId": "20f94790e4a67782c2bafb93fa9b3955311c3fdb", + "schemaName": "iModelScope", + "className": "ChangeSet", + "properties": { + "FileName": "20f94790e4a67782c2bafb93fa9b3955311c3fdb.cs", + "Description": "$ÿñçhröñìzé ¢hâñgês wîth sêrvér", + "FileSize": "285", + "Index": "2", + "Id": "20f94790e4a67782c2bafb93fa9b3955311c3fdb", + "ParentId": "dbe4b3824129f99e4eb485fb7cd9d2fea2354be1", + "SeedFileId": "370cea34-8415-4f81-b54c-85040eb3111e", + "BriefcaseId": 6, + "UserCreated": "fae2f5d1-abb1-4b0b-96c7-87259f4efe70", + "PushDate": "2018-04-04T15:03:48.62Z", + "ContainingChanges": 0, + "IsUploaded": true + }, + "eTag": "\"n4crrIEpRs2JUNRgRfTa5tKUWKs=\"" + }, + { + "instanceId": "eb5075bd61a77c773b4a1e82c89087ba28b31aec", + "schemaName": "iModelScope", + "className": "ChangeSet", + "properties": { + "FileName": "eb5075bd61a77c773b4a1e82c89087ba28b31aec.cs", + "Description": "$ÿñçhröñìzé ¢hâñgês wîth sêrvér", + "FileSize": "284", + "Index": "3", + "Id": "eb5075bd61a77c773b4a1e82c89087ba28b31aec", + "ParentId": "20f94790e4a67782c2bafb93fa9b3955311c3fdb", + "SeedFileId": "370cea34-8415-4f81-b54c-85040eb3111e", + "BriefcaseId": 6, + "UserCreated": "fae2f5d1-abb1-4b0b-96c7-87259f4efe70", + "PushDate": "2018-04-04T15:04:35.96Z", + "ContainingChanges": 0, + "IsUploaded": true + }, + "eTag": "\"LU8t1u1xog442EDtmHr4ahpw0vg=\"" + }, + { + "instanceId": "1b186c485d182c46c02b99aff4fb12637263438f", + "schemaName": "iModelScope", + "className": "ChangeSet", + "properties": { + "FileName": "1b186c485d182c46c02b99aff4fb12637263438f.cs", + "Description": "$ÿñçhröñìzé ¢hâñgês wîth sêrvér", + "FileSize": "283", + "Index": "4", + "Id": "1b186c485d182c46c02b99aff4fb12637263438f", + "ParentId": "eb5075bd61a77c773b4a1e82c89087ba28b31aec", + "SeedFileId": "370cea34-8415-4f81-b54c-85040eb3111e", + "BriefcaseId": 6, + "UserCreated": "fae2f5d1-abb1-4b0b-96c7-87259f4efe70", + "PushDate": "2018-04-04T15:05:11.993Z", + "ContainingChanges": 0, + "IsUploaded": true + }, + "eTag": "\"o5EO6NfPSVv7vo6RuwBEbFRqPGI=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestFirstVersion.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestFirstVersion.json index e3e84c095354..65da3181711b 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestFirstVersion.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestFirstVersion.json @@ -1 +1,7 @@ -[{"instanceId":"28f9056b-58cc-4f69-8d71-dd44da41177a","schemaName":"iModelScope","className":"Version","properties":{"ChangeSetId":"20f94790e4a67782c2bafb93fa9b3955311c3fdb"},"eTag":"\"OZ8aCN8Z0lroS9NbPiVccXO17AU=\""}] \ No newline at end of file +[{ + "instanceId": "28f9056b-58cc-4f69-8d71-dd44da41177a", + "schemaName": "iModelScope", + "className": "Version", + "properties": { "ChangeSetId": "20f94790e4a67782c2bafb93fa9b3955311c3fdb" }, + "eTag": "\"OZ8aCN8Z0lroS9NbPiVccXO17AU=\"" +}] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestSecondVersion.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestSecondVersion.json index 50dc9917d809..893046fa83de 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestSecondVersion.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestSecondVersion.json @@ -1 +1,7 @@ -[{"instanceId":"ecb276b3-04af-4fb2-89c6-10595050ac61","schemaName":"iModelScope","className":"Version","properties":{"ChangeSetId":"eb5075bd61a77c773b4a1e82c89087ba28b31aec"},"eTag":"\"IyIbQRvU9SG/Urk0gRSRSThXrSQ=\""}] \ No newline at end of file +[{ + "instanceId": "ecb276b3-04af-4fb2-89c6-10595050ac61", + "schemaName": "iModelScope", + "className": "Version", + "properties": { "ChangeSetId": "eb5075bd61a77c773b4a1e82c89087ba28b31aec" }, + "eTag": "\"IyIbQRvU9SG/Urk0gRSRSThXrSQ=\"" +}] diff --git a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestThirdVersion.json b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestThirdVersion.json index 49e214316c23..9df28aee90f1 100644 --- a/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestThirdVersion.json +++ b/core/backend/src/test/assets/_mocks_/ReadOnlyTest/versions/ReadOnlyTestThirdVersion.json @@ -1 +1,7 @@ -[{"instanceId":"81ca0d20-d9ea-4fc5-be70-62d82a8fd9e5","schemaName":"iModelScope","className":"Version","properties":{"ChangeSetId":"1b186c485d182c46c02b99aff4fb12637263438f"},"eTag":"\"NBgN3No1BQUOCWY/crR5++pOjMs=\""}] \ No newline at end of file +[{ + "instanceId": "81ca0d20-d9ea-4fc5-be70-62d82a8fd9e5", + "schemaName": "iModelScope", + "className": "Version", + "properties": { "ChangeSetId": "1b186c485d182c46c02b99aff4fb12637263438f" }, + "eTag": "\"NBgN3No1BQUOCWY/crR5++pOjMs=\"" +}] diff --git a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTest.json b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTest.json index 24fcec32a193..a21de516fb6d 100644 --- a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTest.json +++ b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTest.json @@ -1 +1,15 @@ -[{"instanceId":"c8060470-c5d0-4288-a1a2-4c98efaa474e","schemaName":"ContextScope","className":"iModel","properties":{"Description":null,"Name":"ReadWriteTest","UserCreated":"596c0d8b-eac2-46a0-aa4a-b590c3314e7c","CreatedDate":"2018-03-22T14:23:38.057Z","Initialized":true},"eTag":"\"xfxFHTkr0anGtiOkRMIwsKnNJto=\""}] \ No newline at end of file +[ + { + "instanceId": "c8060470-c5d0-4288-a1a2-4c98efaa474e", + "schemaName": "ContextScope", + "className": "iModel", + "properties": { + "Description": null, + "Name": "ReadWriteTest", + "UserCreated": "596c0d8b-eac2-46a0-aa4a-b590c3314e7c", + "CreatedDate": "2018-03-22T14:23:38.057Z", + "Initialized": true + }, + "eTag": "\"xfxFHTkr0anGtiOkRMIwsKnNJto=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestBriefcase.json b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestBriefcase.json index dd3877b98133..e4aba65d2eab 100644 --- a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestBriefcase.json +++ b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestBriefcase.json @@ -1 +1,19 @@ -[{"instanceId":"12","schemaName":"iModelScope","className":"Briefcase","properties":{"FileName":"ReadWriteTest.bim","FileDescription":null,"FileSize":"1118208","FileId":"d26bb58e-9e31-41e1-ab7c-362027ff7a5c","BriefcaseId":12,"MergedChangeSetId":"c7c44724278d3568a9c9b3c1f0626ce0c897f427","UserOwned":"596c0d8b-eac2-46a0-aa4a-b590c3314e7c","AcquiredDate":"2018-04-18T12:43:02.713Z","IsReadOnly":false},"eTag":"\"5q3gcFFPreRxLS+uBC9T07GyZFE=\""}] \ No newline at end of file +[ + { + "instanceId": "12", + "schemaName": "iModelScope", + "className": "Briefcase", + "properties": { + "FileName": "ReadWriteTest.bim", + "FileDescription": null, + "FileSize": "1118208", + "FileId": "d26bb58e-9e31-41e1-ab7c-362027ff7a5c", + "BriefcaseId": 12, + "MergedChangeSetId": "c7c44724278d3568a9c9b3c1f0626ce0c897f427", + "UserOwned": "596c0d8b-eac2-46a0-aa4a-b590c3314e7c", + "AcquiredDate": "2018-04-18T12:43:02.713Z", + "IsReadOnly": false + }, + "eTag": "\"5q3gcFFPreRxLS+uBC9T07GyZFE=\"" + } +] diff --git a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestChangeSets.json b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestChangeSets.json index 27346b00b5e5..8532d8a7405e 100644 --- a/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestChangeSets.json +++ b/core/backend/src/test/assets/_mocks_/ReadWriteTest/ReadWriteTestChangeSets.json @@ -1 +1,22 @@ -[{"instanceId":"c7c44724278d3568a9c9b3c1f0626ce0c897f427","schemaName":"iModelScope","className":"ChangeSet","properties":{"FileName":"c7c44724278d3568a9c9b3c1f0626ce0c897f427.cs","Description":"[\"{\\\"userid\\\":\\\"user1\\\",\\\"description\\\":\\\"changed a userLabel\\\"}\",\"{\\\"userid\\\":\\\"user1\\\",\\\"description\\\":\\\"inserted generic objects\\\"}\"]","FileSize":"440","Index":"1","Id":"c7c44724278d3568a9c9b3c1f0626ce0c897f427","ParentId":"","SeedFileId":"d26bb58e-9e31-41e1-ab7c-362027ff7a5c","BriefcaseId":2,"UserCreated":"596c0d8b-eac2-46a0-aa4a-b590c3314e7c","PushDate":"2018-03-22T14:24:05.213Z","ContainingChanges":0,"IsUploaded":true},"eTag":"\"Pf5Z6LhsKjUVqbneRHpTeSa3ONI=\""}] \ No newline at end of file +[ + { + "instanceId": "c7c44724278d3568a9c9b3c1f0626ce0c897f427", + "schemaName": "iModelScope", + "className": "ChangeSet", + "properties": { + "FileName": "c7c44724278d3568a9c9b3c1f0626ce0c897f427.cs", + "Description": "[\"{\\\"userid\\\":\\\"user1\\\",\\\"description\\\":\\\"changed a userLabel\\\"}\",\"{\\\"userid\\\":\\\"user1\\\",\\\"description\\\":\\\"inserted generic objects\\\"}\"]", + "FileSize": "440", + "Index": "1", + "Id": "c7c44724278d3568a9c9b3c1f0626ce0c897f427", + "ParentId": "", + "SeedFileId": "d26bb58e-9e31-41e1-ab7c-362027ff7a5c", + "BriefcaseId": 2, + "UserCreated": "596c0d8b-eac2-46a0-aa4a-b590c3314e7c", + "PushDate": "2018-03-22T14:24:05.213Z", + "ContainingChanges": 0, + "IsUploaded": true + }, + "eTag": "\"Pf5Z6LhsKjUVqbneRHpTeSa3ONI=\"" + } +] diff --git a/core/backend/src/test/categories/Category.test.ts b/core/backend/src/test/categories/Category.test.ts index 9b324ff12d2b..523e842442f4 100644 --- a/core/backend/src/test/categories/Category.test.ts +++ b/core/backend/src/test/categories/Category.test.ts @@ -2,12 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; import { SubCategoryAppearance } from "@itwin/core-common"; -import { - IModelDb, RenderMaterialElement, RenderMaterialElementParams, SpatialCategory, StandaloneDb, SubCategory, -} from "../../core-backend"; +import { expect } from "chai"; +import { IModelDb, RenderMaterialElement, RenderMaterialElementParams, SpatialCategory, StandaloneDb, SubCategory } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; describe("Category", () => { diff --git a/core/backend/src/test/codespec/CodeSpec.test.ts b/core/backend/src/test/codespec/CodeSpec.test.ts index 156aa21a1560..9322131e5f99 100644 --- a/core/backend/src/test/codespec/CodeSpec.test.ts +++ b/core/backend/src/test/codespec/CodeSpec.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; import { CodeScopeSpec, CodeSpec } from "@itwin/core-common"; -import { IModelTestUtils } from "../IModelTestUtils"; +import { expect } from "chai"; import { StandaloneDb } from "../../IModelDb"; +import { IModelTestUtils } from "../IModelTestUtils"; describe("CodeSpec", () => { let imodel: StandaloneDb; diff --git a/core/backend/src/test/ecdb/CTE.test.ts b/core/backend/src/test/ecdb/CTE.test.ts index 0e9b36644ba4..d4e32b3cca72 100644 --- a/core/backend/src/test/ecdb/CTE.test.ts +++ b/core/backend/src/test/ecdb/CTE.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { QueryBinder, QueryRowFormat } from "@itwin/core-common"; +import { assert } from "chai"; import { IModelDb, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; @@ -12,7 +12,9 @@ import { SequentialLogMatcher } from "../SequentialLogMatcher"; async function executeQuery(iModel: IModelDb, ecsql: string, bindings?: any[] | object, abbreviateBlobs?: boolean): Promise { const rows: any[] = []; - for await (const queryRow of iModel.createQueryReader(ecsql, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs })) { + for await ( + const queryRow of iModel.createQueryReader(ecsql, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs }) + ) { rows.push(queryRow.toRow()); } return rows; @@ -40,15 +42,72 @@ describe("Common table expression support in ECSQL", () => { JOIN base_classes ON aId = cbc.TargetECInstanceId ORDER BY 1 ) - SELECT p.Name prop from base_classes join meta.ECPropertyDef p on p.Class.id = aId GROUP BY p.Name` ; + SELECT p.Name prop from base_classes join meta.ECPropertyDef p on p.Class.id = aId GROUP BY p.Name`; const rows = await executeQuery(imodel1, query, ["Element"]); - const expected = ["Angle", "BaseModel", "BBoxHigh", "BBoxLow", "Border", "BorderTemplate", "Category", "CategorySelector", "CodeScope", "CodeSpec", "CodeValue", "Data", "Description", "DisplayStyle", "DrawingModel", "Enabled", "Extents", "EyePoint", "FederationGuid", "Flags", "FocusDistance", "Format", "GeometryStream", "Height", "InSpatialIndex", "IsCameraOn", "IsPrivate", "JsonProperties", "LastMod", "LensAngle", "Model", "ModelSelector", "Name", "Origin", "PaletteName", "Parent", "Pitch", "Properties", "Rank", "Recipe", "RepositoryGuid", "Roll", "Rotation", "RotationAngle", "Scale", "SheetTemplate", "Type", "TypeDefinition", "Url", "UserLabel", "View", "ViewAttachment", "Width", "Yaw"]; + const expected = [ + "Angle", + "BaseModel", + "BBoxHigh", + "BBoxLow", + "Border", + "BorderTemplate", + "Category", + "CategorySelector", + "CodeScope", + "CodeSpec", + "CodeValue", + "Data", + "Description", + "DisplayStyle", + "DrawingModel", + "Enabled", + "Extents", + "EyePoint", + "FederationGuid", + "Flags", + "FocusDistance", + "Format", + "GeometryStream", + "Height", + "InSpatialIndex", + "IsCameraOn", + "IsPrivate", + "JsonProperties", + "LastMod", + "LensAngle", + "Model", + "ModelSelector", + "Name", + "Origin", + "PaletteName", + "Parent", + "Pitch", + "Properties", + "Rank", + "Recipe", + "RepositoryGuid", + "Roll", + "Rotation", + "RotationAngle", + "Scale", + "SheetTemplate", + "Type", + "TypeDefinition", + "Url", + "UserLabel", + "View", + "ViewAttachment", + "Width", + "Yaw", + ]; const actual = rows.map((r) => r.prop); assert.sameOrderedMembers(actual, expected); }); it("generate mandelbrot set", async () => { - const rows = await executeQuery(imodel1, ` + const rows = await executeQuery( + imodel1, + ` WITH RECURSIVE [xaxis]([x]) AS( VALUES (- 2.0) @@ -100,10 +159,10 @@ describe("Common table expression support in ECSQL", () => { ) SELECT GROUP_CONCAT (RTRIM ([t]), CHAR (0xa)) mandelbrot_set FROM [a]; - `); + `, + ); - const expected = - " ....#\n" + + const expected = " ....#\n" + " ..#*..\n" + " ..+####+.\n" + " .......+####.... +\n" + @@ -130,29 +189,37 @@ describe("Common table expression support in ECSQL", () => { it("basic cte test", async () => { let rows = []; - rows = await executeQuery(imodel1, ` + rows = await executeQuery( + imodel1, + ` WITH RECURSIVE cnt (x,y) AS ( SELECT 100, 200 UNION ALL SELECT x+1, 200 FROM cnt WHERE x<210 ) - SELECT * from cnt`); + SELECT * from cnt`, + ); assert(rows.length === 111); - rows = await executeQuery(imodel1, ` + rows = await executeQuery( + imodel1, + ` WITH RECURSIVE cnt (x,y) AS ( SELECT 100, 200 ) - SELECT * from cnt`); + SELECT * from cnt`, + ); let slm = new SequentialLogMatcher(); // these two are generated by sqlite slm.append().error().category("ECDb").message(/BE_SQLITE_ERROR duplicate WITH table name/gm); assert(rows.length === 1); try { - rows = await executeQuery(imodel1, ` + rows = await executeQuery( + imodel1, + ` WITH cte_1 (a,b,c) AS ( SELECT 100, 400, 300 @@ -160,7 +227,8 @@ describe("Common table expression support in ECSQL", () => { cte_1 (a,b,c) AS ( SELECT 100, 400, 300 ) - SELECT * from cte_1`); + SELECT * from cte_1`, + ); assert(false); } catch { assert(true); // should fail as cte_1 is used for two ct expression. @@ -170,12 +238,15 @@ describe("Common table expression support in ECSQL", () => { // these two are generated by ECSQL. Its not clear why this message is logged twice. slm.append().error().category("ECDb").message(/Common table 'cte_1' has 3 values for columns 2/gm); try { - rows = await executeQuery(imodel1, ` + rows = await executeQuery( + imodel1, + ` WITH cte_1 (a,b,c) AS ( SELECT 100, 400 ) - SELECT * from cte_1`); + SELECT * from cte_1`, + ); assert(false); } catch { assert(true); // number are to ct expression does not match select diff --git a/core/backend/src/test/ecdb/ECDb.test.ts b/core/backend/src/test/ecdb/ECDb.test.ts index 876f65d19689..d0ed37d5bf0f 100644 --- a/core/backend/src/test/ecdb/ECDb.test.ts +++ b/core/backend/src/test/ecdb/ECDb.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { DbResult, Id64, Id64String, Logger, using } from "@itwin/core-bentley"; import { assert, expect } from "chai"; import * as path from "path"; import * as sinon from "sinon"; -import { DbResult, Id64, Id64String, Logger, using } from "@itwin/core-bentley"; import { ECDb, ECDbOpenMode, ECSqlInsertResult, ECSqlStatement, IModelJsFs, SqliteStatement, SqliteValue, SqliteValueType } from "../../core-backend"; import { KnownTestLocations } from "../KnownTestLocations"; import { ECDbTestHelper } from "./ECDbTestHelper"; @@ -63,23 +63,29 @@ describe("ECDb", () => { const fileName = "schemaimport.ecdb"; const ecdbPath: string = path.join(outDir, fileName); let id: Id64String; - using(ECDbTestHelper.createECDb(outDir, fileName, - ` + using( + ECDbTestHelper.createECDb( + outDir, + fileName, + ` - `), (testECDb: ECDb) => { - assert.isTrue(testECDb.isOpen); - id = testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - assert.isTrue(Id64.isValidId64(res.id!)); - return res.id!; - }); - testECDb.saveChanges(); - }); + `, + ), + (testECDb: ECDb) => { + assert.isTrue(testECDb.isOpen); + id = testECDb.withPreparedStatement("INSERT INTO test.Person(Name,Age) VALUES('Mary', 45)", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + assert.isTrue(Id64.isValidId64(res.id!)); + return res.id!; + }); + testECDb.saveChanges(); + }, + ); using(new ECDb(), (ecdb: ECDb) => { ecdb.openDb(ecdbPath, ECDbOpenMode.Readonly); @@ -183,7 +189,9 @@ describe("ECDb", () => { const ecdb: ECDb = ECDbTestHelper.createECDb(outDir, "TestCompositeFormats.ecdb"); const xmlpathOriginal = path.join(outDir, "compositeFormats1.ecschema.xml"); - IModelJsFs.writeFileSync(xmlpathOriginal, ` + IModelJsFs.writeFileSync( + xmlpathOriginal, + ` @@ -196,7 +204,8 @@ describe("ECDb", () => { - `); + `, + ); ecdb.importSchema(xmlpathOriginal); ecdb.saveChanges(); @@ -210,7 +219,9 @@ describe("ECDb", () => { }); const xmlpathUpdated = path.join(outDir, "compositeFormats2.ecschema.xml"); - IModelJsFs.writeFileSync(xmlpathUpdated, ` + IModelJsFs.writeFileSync( + xmlpathUpdated, + ` @@ -223,7 +234,8 @@ describe("ECDb", () => { - `); + `, + ); ecdb.importSchema(xmlpathUpdated); ecdb.saveChanges(); @@ -244,25 +256,31 @@ describe("ECDb", () => { const ecdb: ECDb = ECDbTestHelper.createECDb(outDir, "importSchemaNoVersionBump.ecdb"); const xmlpathOriginal = path.join(outDir, "importSchemaNoVersionBump1.ecschema.xml"); - IModelJsFs.writeFileSync(xmlpathOriginal, ` + IModelJsFs.writeFileSync( + xmlpathOriginal, + ` - `); + `, + ); ecdb.importSchema(xmlpathOriginal); ecdb.saveChanges(); const xmlpathUpdated = path.join(outDir, "importSchemaNoVersionBump2.ecschema.xml"); - IModelJsFs.writeFileSync(xmlpathUpdated, ` + IModelJsFs.writeFileSync( + xmlpathUpdated, + ` - `); + `, + ); let calledCategory = ""; let calledMessage = ""; diff --git a/core/backend/src/test/ecdb/ECDbTestHelper.ts b/core/backend/src/test/ecdb/ECDbTestHelper.ts index 69f662c8f85a..da41ac8ee1fd 100644 --- a/core/backend/src/test/ecdb/ECDbTestHelper.ts +++ b/core/backend/src/test/ecdb/ECDbTestHelper.ts @@ -2,13 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import { Guid } from "@itwin/core-bentley"; +import * as path from "path"; import { ECDb } from "../../ECDb"; import { IModelJsFs } from "../../IModelJsFs"; export class ECDbTestHelper { - public static createECDb(outDir: string, fileName: string, schemaXml?: string): ECDb { if (!IModelJsFs.existsSync(outDir)) IModelJsFs.mkdirSync(outDir); diff --git a/core/backend/src/test/ecdb/ECSchemaXmlContext.test.ts b/core/backend/src/test/ecdb/ECSchemaXmlContext.test.ts index 95dc5540a3b9..b73825f9daee 100644 --- a/core/backend/src/test/ecdb/ECSchemaXmlContext.test.ts +++ b/core/backend/src/test/ecdb/ECSchemaXmlContext.test.ts @@ -10,7 +10,6 @@ import { KnownTestLocations } from "../KnownTestLocations"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; describe("ECSchemaXmlContext", () => { - it("should be able to convert schema XML to JSON", () => { const testSchemaXmlPath = path.join(KnownTestLocations.assetsDir, "TestSchema.ecschema.xml"); const testSchemaJsonPath = path.join(KnownTestLocations.assetsDir, "TestSchema.ecschema.json"); diff --git a/core/backend/src/test/ecdb/ECSqlAst.test.ts b/core/backend/src/test/ecdb/ECSqlAst.test.ts index 20fb152b0833..eed0bf47ed20 100644 --- a/core/backend/src/test/ecdb/ECSqlAst.test.ts +++ b/core/backend/src/test/ecdb/ECSqlAst.test.ts @@ -6,11 +6,12 @@ * @module ECSqlExpr */ -import { assert } from "chai"; +import { DbResult } from "@itwin/core-bentley"; import { AssignmentExpr, BetweenExpr, - BinaryBooleanExpr, BinaryValueExpr, + BinaryBooleanExpr, + BinaryValueExpr, CastExpr, ClassNameExpr, CteBlockExpr, @@ -56,9 +57,9 @@ import { UsingRelationshipJoinExpr, WhereClauseExp, } from "@itwin/ecsql-common"; +import { assert } from "chai"; import { ECDb, ECDbOpenMode, IModelHost } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; -import { DbResult } from "@itwin/core-bentley"; describe("ECSql Abstract Syntax Tree", () => { let ecdb: ECDb; @@ -198,8 +199,7 @@ describe("ECSql Abstract Syntax Tree", () => { { orignalECSql: "select IIF(('Hello, World' LIKE '%World') , 2, 3)", expectedECSql: "SELECT IIF('Hello, World' LIKE '%World', 2, 3)", - } - , + }, { orignalECSql: "select IIF(('Hello, World' NOT LIKE '%World') , 2, 3)", expectedECSql: "SELECT IIF('Hello, World' NOT LIKE '%World', 2, 3)", @@ -219,8 +219,7 @@ describe("ECSql Abstract Syntax Tree", () => { { orignalECSql: "SELECT IIF( 3 IN (1,2,3), 'True', 'False')", expectedECSql: "SELECT IIF(3 IN (1, 2, 3), 'True', 'False')", - } - , + }, { orignalECSql: "SELECT IIF( 3 NOT IN (1,2,3), 'True', 'False')", expectedECSql: "SELECT IIF(3 NOT IN (1, 2, 3), 'True', 'False')", @@ -462,12 +461,15 @@ describe("ECSql Abstract Syntax Tree", () => { expectedECSql: "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1) SELECT [i] FROM [c]", }, { - orignalECSql: "WITH c(i) AS (SELECT 1 UNION SELECT i+1 FROM c WHERE i < 10 ORDER BY 1), d(i) AS (SELECT 1 UNION SELECT i+1 FROM d WHERE i < 100 ORDER BY 1) SELECT * FROM c,d", - expectedECSql: "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1), [d]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [d] WHERE ([i] < 100) ORDER BY 1) SELECT [c].[i], [d].[i] FROM [c], [d]", + orignalECSql: + "WITH c(i) AS (SELECT 1 UNION SELECT i+1 FROM c WHERE i < 10 ORDER BY 1), d(i) AS (SELECT 1 UNION SELECT i+1 FROM d WHERE i < 100 ORDER BY 1) SELECT * FROM c,d", + expectedECSql: + "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1), [d]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [d] WHERE ([i] < 100) ORDER BY 1) SELECT [c].[i], [d].[i] FROM [c], [d]", }, { orignalECSql: "WITH c(a,b,c) AS (SELECT ECInstanceId, ECClassId, Name FROM meta.ECClassDef) SELECT * FROM c", - expectedECSql: "WITH [c]([a], [b], [c]) AS (SELECT [ECInstanceId], [ECClassId], [Name] FROM [ECDbMeta].[ECClassDef]) SELECT [c].[a], [c].[b], [c].[c] FROM [c]", + expectedECSql: + "WITH [c]([a], [b], [c]) AS (SELECT [ECInstanceId], [ECClassId], [Name] FROM [ECDbMeta].[ECClassDef]) SELECT [c].[a], [c].[b], [c].[c] FROM [c]", }, ]; for (const test of tests) { @@ -539,11 +541,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef INNER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -555,11 +559,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef RIGHT JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef RIGHT OUTER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -571,11 +577,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef FULL JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef FULL OUTER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -587,21 +595,24 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a UNION SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a UNION ALL SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION ALL SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION ALL SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a INTERSECT SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] INTERSECT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] INTERSECT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a EXCEPT SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] EXCEPT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] EXCEPT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, - ]; for (const test of tests) { assert.equal(test.expectedECSql, await toNormalizeECSql(test.orignalECSql)); @@ -612,11 +623,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "WITH cte AS (SELECT * FROM meta.ECClassDef) SELECT * FROM cte", - expectedECSql: "WITH [cte] AS (SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [ECDbMeta].[ECClassDef]) SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [cte]", + expectedECSql: + "WITH [cte] AS (SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [ECDbMeta].[ECClassDef]) SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [cte]", }, { orignalECSql: "WITH cte AS (SELECT * FROM meta.ECClassDef) SELECT cte.ECInstanceId FROM cte", - expectedECSql: "WITH [cte] AS (SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [ECDbMeta].[ECClassDef]) SELECT [cte].[ECInstanceId] FROM [cte]", + expectedECSql: + "WITH [cte] AS (SELECT [ECInstanceId], [ECClassId], [Schema], [Name], [DisplayLabel], [Description], [Type], [Modifier], [CustomAttributeContainerType], [RelationshipStrength], [RelationshipStrengthDirection] FROM [ECDbMeta].[ECClassDef]) SELECT [cte].[ECInstanceId] FROM [cte]", }, ]; for (const test of tests) { @@ -632,7 +645,8 @@ describe("ECSql Abstract Syntax Tree", () => { }, { orignalECSql: "SELECT (WITH C(iD) AS (SELECT b.ECInstanceId FROM meta.ECPropertyDef b) SELECT * FROM C) AS S FROM [ECDbMeta].[ECClassDef] a", - expectedECSql: "SELECT (WITH [C]([iD]) AS (SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) SELECT [C].[iD] FROM [C]) [S] FROM [ECDbMeta].[ECClassDef] [a]", + expectedECSql: + "SELECT (WITH [C]([iD]) AS (SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) SELECT [C].[iD] FROM [C]) [S] FROM [ECDbMeta].[ECClassDef] [a]", }, { orignalECSql: "SELECT (SELECT 1 UNION SELECT 2) FROM meta.ECClassDef a", @@ -643,8 +657,10 @@ describe("ECSql Abstract Syntax Tree", () => { expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE ((SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) = 1)", }, { - orignalECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE (WITH temp(Id) AS (SELECT [b].[ECInstanceId] FROM meta.ECPropertyDef b) SELECT * FROM temp) = 1", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE ((WITH [temp]([Id]) AS (SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) SELECT [temp].[Id] FROM [temp]) = 1)", + orignalECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE (WITH temp(Id) AS (SELECT [b].[ECInstanceId] FROM meta.ECPropertyDef b) SELECT * FROM temp) = 1", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE ((WITH [temp]([Id]) AS (SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) SELECT [temp].[Id] FROM [temp]) = 1)", }, ]; for (const test of tests) { @@ -674,7 +690,6 @@ describe("ECSql Abstract Syntax Tree", () => { orignalECSql: "SELECT 1 FROM +ONLY [ECDbMeta].[ECClassDef]", expectedECSql: "SELECT 1 FROM +ONLY [ECDbMeta].[ECClassDef]", }, - ]; for (const test of tests) { assert.equal(test.expectedECSql, await toNormalizeECSql(test.orignalECSql)); @@ -700,8 +715,10 @@ describe("ECSql Abstract Syntax Tree", () => { it("parse SELECT, WHERE, FROM, GROUP BY, HAVING, ORDER BY, LIMIT & ECSQLOPTIONS", async () => { const tests = [ { - orignalECSql: "select count(*) from bis.element where codevalue lIKE '%s' group by ecclassid having count(*)>0 order by UserLabel limit 1 offset 10 ECSQLOPTIONS x=3", - expectedECSql: "SELECT COUNT(*) FROM [BisCore].[Element] WHERE [codevalue] LIKE '%s' GROUP BY [ecclassid] HAVING (COUNT(*) > 0) ORDER BY [UserLabel] LIMIT 1 OFFSET 10 ECSQLOPTIONS x = 3", + orignalECSql: + "select count(*) from bis.element where codevalue lIKE '%s' group by ecclassid having count(*)>0 order by UserLabel limit 1 offset 10 ECSQLOPTIONS x=3", + expectedECSql: + "SELECT COUNT(*) FROM [BisCore].[Element] WHERE [codevalue] LIKE '%s' GROUP BY [ecclassid] HAVING (COUNT(*) > 0) ORDER BY [UserLabel] LIMIT 1 OFFSET 10 ECSQLOPTIONS x = 3", }, ]; for (const test of tests) { @@ -892,7 +909,8 @@ describe("ECSql Abstract Syntax Tree", () => { ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3 */ - const expected = "WITH RECURSIVE [f0]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [f0] WHERE ([i] < 10) ORDER BY 1), [f1]([i]) AS (SELECT 3.14159265358), [f2]([i]) AS (SELECT IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [i]), [f3]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] FORWARD), [f4]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] BACKWARD), [f5]([i]) AS (SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId]) WHERE ([ECClassDef].[ECInstanceId] = :param1)) SELECT (((1 & 2) | (3 << 4)) >> ((((((5 / 6) * (7 + 8)) + (4 % 9)) + -10) + +20) - ~45)) [c0], TIMESTAMP '2013-02-09T12:00:00' [c1], DATE '2012-01-18' [c2], TIME '13:35:16' [c3], TRUE [c4], FALSE [c5], 3.14159265358 [c6], 314159 [c7], 'Hello, World' [c8], (('Hello' || ',') || 'World') [c9], IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [c10], CASE WHEN (4 > 5) THEN NULL WHEN (1 IS NOT NULL) THEN 'Hello' ELSE 'Bye' END [c11], IIF('Hello, World' LIKE '\\%World' ESCAPE '\\', 2, 3) [c12], IIF('Hello, World' LIKE '%World', 2, 3) [c13], IIF('Hello, World' NOT LIKE '%World', 2, 3) [c14], IIF(3 IN (SELECT 1 [N] UNION SELECT 2), 'True', 'False') [c15], IIF(3 IN (1, 2, 3), 'True', 'False') [c16], IIF(3 NOT IN (1, 2, 3), 'True', 'False') [c17], IIF((NULL IS NULL), 'True', 'False') [c18], IIF((NULL IS NOT NULL), 'True', 'False') [c19], IIF((1 IS NOT NULL), 'True', 'False') [c20], IIF(3 IS (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c21], IIF(3 IS NOT (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c22], IIF((NOT 3), 'True', 'False') [c23], IIF((NOT (NOT (NOT (NOT 3)))), 'True', 'False') [c24], IIF(EXISTS(SELECT 1), 'True', 'False') [c25], IIF((NOT EXISTS(SELECT 1)), 'True', 'False') [c26], CAST(1 AS TEXT) [c27], CAST(1 AS INTEGER) [c28], CAST(1 AS REAL) [c29], CAST(1 AS BLOB) [c30], CAST(1 AS TIMESTAMP) [c31], INSTR('First', 'Second') [c32], [f0].[i] [c33], [f1].[i] [c34], [f2].[i] [c35], [k0].[ECInstanceId] [c36] FROM [f0], [f1], [f2], [f3], [f4], [f5], [ECDbMeta].[ECClassDef] [k0], (SELECT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION SELECT DISTINCT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION ALL SELECT ALL [ECInstanceId] FROM [ECDbMeta].[ECClassDef] EXCEPT SELECT SUM(DISTINCT [ECInstanceId]) FROM [ECDbMeta].[ECClassDef] INTERSECT SELECT SUM([ECInstanceId]) FROM [ECDbMeta].[ECClassDef] GROUP BY [ECClassId] HAVING (COUNT(*) > 1)) [k1] WHERE (([f0].[i] = [f1].[i]) AND ([k0].[ECInstanceId] = (? + 2))) GROUP BY [k0].[ECClassId], [k0].[DisplayLabel] HAVING (COUNT(*) > 1) ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3"; + const expected = + "WITH RECURSIVE [f0]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [f0] WHERE ([i] < 10) ORDER BY 1), [f1]([i]) AS (SELECT 3.14159265358), [f2]([i]) AS (SELECT IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [i]), [f3]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] FORWARD), [f4]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] BACKWARD), [f5]([i]) AS (SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId]) WHERE ([ECClassDef].[ECInstanceId] = :param1)) SELECT (((1 & 2) | (3 << 4)) >> ((((((5 / 6) * (7 + 8)) + (4 % 9)) + -10) + +20) - ~45)) [c0], TIMESTAMP '2013-02-09T12:00:00' [c1], DATE '2012-01-18' [c2], TIME '13:35:16' [c3], TRUE [c4], FALSE [c5], 3.14159265358 [c6], 314159 [c7], 'Hello, World' [c8], (('Hello' || ',') || 'World') [c9], IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [c10], CASE WHEN (4 > 5) THEN NULL WHEN (1 IS NOT NULL) THEN 'Hello' ELSE 'Bye' END [c11], IIF('Hello, World' LIKE '\\%World' ESCAPE '\\', 2, 3) [c12], IIF('Hello, World' LIKE '%World', 2, 3) [c13], IIF('Hello, World' NOT LIKE '%World', 2, 3) [c14], IIF(3 IN (SELECT 1 [N] UNION SELECT 2), 'True', 'False') [c15], IIF(3 IN (1, 2, 3), 'True', 'False') [c16], IIF(3 NOT IN (1, 2, 3), 'True', 'False') [c17], IIF((NULL IS NULL), 'True', 'False') [c18], IIF((NULL IS NOT NULL), 'True', 'False') [c19], IIF((1 IS NOT NULL), 'True', 'False') [c20], IIF(3 IS (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c21], IIF(3 IS NOT (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c22], IIF((NOT 3), 'True', 'False') [c23], IIF((NOT (NOT (NOT (NOT 3)))), 'True', 'False') [c24], IIF(EXISTS(SELECT 1), 'True', 'False') [c25], IIF((NOT EXISTS(SELECT 1)), 'True', 'False') [c26], CAST(1 AS TEXT) [c27], CAST(1 AS INTEGER) [c28], CAST(1 AS REAL) [c29], CAST(1 AS BLOB) [c30], CAST(1 AS TIMESTAMP) [c31], INSTR('First', 'Second') [c32], [f0].[i] [c33], [f1].[i] [c34], [f2].[i] [c35], [k0].[ECInstanceId] [c36] FROM [f0], [f1], [f2], [f3], [f4], [f5], [ECDbMeta].[ECClassDef] [k0], (SELECT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION SELECT DISTINCT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION ALL SELECT ALL [ECInstanceId] FROM [ECDbMeta].[ECClassDef] EXCEPT SELECT SUM(DISTINCT [ECInstanceId]) FROM [ECDbMeta].[ECClassDef] INTERSECT SELECT SUM([ECInstanceId]) FROM [ECDbMeta].[ECClassDef] GROUP BY [ECClassId] HAVING (COUNT(*) > 1)) [k1] WHERE (([f0].[i] = [f1].[i]) AND ([k0].[ECInstanceId] = (? + 2))) GROUP BY [k0].[ECClassId], [k0].[DisplayLabel] HAVING (COUNT(*) > 1) ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3"; assert.equal(expected, await toNormalizeECSql(ecsql)); }); describe("test methods", () => { @@ -901,9 +919,12 @@ describe("ECSql Abstract Syntax Tree", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), "ALL", new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -912,7 +933,10 @@ describe("ECSql Abstract Syntax Tree", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new LiteralExpr(LiteralValueType.Raw, "1")))), + new LiteralExpr(LiteralValueType.Raw, "1"), + ), + ), + ), ); const expected = "SELECT ALL [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = 1)"; assert.equal(stmt.toECSql(), expected); @@ -931,9 +955,12 @@ describe("ECSql Abstract Syntax Tree", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), undefined, new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -942,7 +969,10 @@ describe("ECSql Abstract Syntax Tree", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new ParameterExpr()))), + new ParameterExpr(), + ), + ), + ), ); const expected = "SELECT [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = ?)"; assert.equal(stmt.toECSql(), expected); @@ -1012,10 +1042,10 @@ describe("ECSql Abstract Syntax Tree", () => { assert.equal(ExprType.WhereClause, WhereClauseExp.type); }); it.skip("test print tree", async () => { - const ecsql = "select el.ECInstanceId as id, count(*) as instances from bis.element el where el.codevalue lIKE '%s' group by el.ecclassid having count(*)>0 order by el.UserLabel limit 1 offset 10 ECSQLOPTIONS x=3"; + const ecsql = + "select el.ECInstanceId as id, count(*) as instances from bis.element el where el.codevalue lIKE '%s' group by el.ecclassid having count(*)>0 order by el.UserLabel limit 1 offset 10 ECSQLOPTIONS x=3"; const selectStmt = await parseECSql(ecsql); printTree(selectStmt); - }); it("test ClassNameExpr.fromECSql()", async () => { assert.equal(ClassNameExpr.fromECSql("+all Bis.Element").toECSql(), "+ALL [Bis].[Element]"); diff --git a/core/backend/src/test/ecdb/ECSqlQuery.test.ts b/core/backend/src/test/ecdb/ECSqlQuery.test.ts index 1716415a7578..7745753b8337 100644 --- a/core/backend/src/test/ecdb/ECSqlQuery.test.ts +++ b/core/backend/src/test/ecdb/ECSqlQuery.test.ts @@ -2,20 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { DbResult, Id64 } from "@itwin/core-bentley"; -import { DbQueryRequest, DbQueryResponse, DbRequestExecutor, DbRequestKind, ECSqlReader, QueryBinder, QueryOptionsBuilder, QueryPropertyMetaData, QueryRowFormat } from "@itwin/core-common"; +import { + DbQueryRequest, + DbQueryResponse, + DbRequestExecutor, + DbRequestKind, + ECSqlReader, + QueryBinder, + QueryOptionsBuilder, + QueryPropertyMetaData, + QueryRowFormat, +} from "@itwin/core-common"; +import { assert } from "chai"; +import * as path from "path"; import { ConcurrentQuery } from "../../ConcurrentQuery"; import { _nativeDb, ECSqlStatement, IModelDb, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; -import * as path from "path"; // cspell:ignore mirukuru ibim async function executeQuery(iModel: IModelDb, ecsql: string, bindings?: any[] | object, abbreviateBlobs?: boolean): Promise { const rows: any[] = []; - for await (const queryRow of iModel.createQueryReader(ecsql, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs })) { + for await ( + const queryRow of iModel.createQueryReader(ecsql, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs }) + ) { rows.push(queryRow.toRow()); } return rows; @@ -30,7 +42,6 @@ describe("ECSql Query", () => { let imodel6: SnapshotDb; before(async () => { - imodel1 = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("test.bim")); imodel2 = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim")); imodel3 = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("GetSetAutoHandledStructProperties.bim")); @@ -69,7 +80,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM BisCore.Element WHERE Parent.Id IS NOT NULL LIMIT 1", + query: + "SELECT Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM BisCore.Element WHERE Parent.Id IS NOT NULL LIMIT 1", statementResult: { "myParentId": "0x1", "myParentRelClassId": "0xcf", @@ -106,7 +118,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT ECInstanceId, ECClassId, SourceECInstanceId, SourceECClassId, TargetECInstanceid, TargetECClassId FROM Bis.ElementRefersToElements LIMIT 1", + query: + "SELECT ECInstanceId, ECClassId, SourceECInstanceId, SourceECClassId, TargetECInstanceid, TargetECClassId FROM Bis.ElementRefersToElements LIMIT 1", statementResult: { id: "0x1", className: "BisCore.PartitionOriginatesFromRepository", @@ -125,7 +138,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT ECInstanceId, ECClassId, SourceECInstanceId, SourceECClassId, TargetECInstanceid, TargetECClassId FROM Bis.ElementRefersToElements) LIMIT 1", + query: + "SELECT * FROM (SELECT ECInstanceId, ECClassId, SourceECInstanceId, SourceECClassId, TargetECInstanceid, TargetECClassId FROM Bis.ElementRefersToElements) LIMIT 1", statementResult: { id: "0x1", className: "BisCore.PartitionOriginatesFromRepository", @@ -188,7 +202,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT ECInstanceId a, ECClassId b, SourceECInstanceId c, SourceECClassId d, TargetECInstanceid e, TargetECClassId f FROM Bis.ElementRefersToElements LIMIT 1", + query: + "SELECT ECInstanceId a, ECClassId b, SourceECInstanceId c, SourceECClassId d, TargetECInstanceid e, TargetECClassId f FROM Bis.ElementRefersToElements LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -207,7 +222,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT ECInstanceId a, ECClassId b, SourceECInstanceId c, SourceECClassId d, TargetECInstanceid e, TargetECClassId f FROM Bis.ElementRefersToElements) LIMIT 1", + query: + "SELECT * FROM (SELECT ECInstanceId a, ECClassId b, SourceECInstanceId c, SourceECClassId d, TargetECInstanceid e, TargetECClassId f FROM Bis.ElementRefersToElements) LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -226,7 +242,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT ECInstanceId A, ECClassId B, SourceECInstanceId C, SourceECClassId D, TargetECInstanceid E, TargetECClassId F FROM Bis.ElementRefersToElements LIMIT 1", + query: + "SELECT ECInstanceId A, ECClassId B, SourceECInstanceId C, SourceECClassId D, TargetECInstanceid E, TargetECClassId F FROM Bis.ElementRefersToElements LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -245,7 +262,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT ECInstanceId A, ECClassId B, SourceECInstanceId C, SourceECClassId D, TargetECInstanceid E, TargetECClassId F FROM Bis.ElementRefersToElements) LIMIT 1", + query: + "SELECT * FROM (SELECT ECInstanceId A, ECClassId B, SourceECInstanceId C, SourceECClassId D, TargetECInstanceid E, TargetECClassId F FROM Bis.ElementRefersToElements) LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -302,7 +320,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT r.ECInstanceId, r.ECClassId, r.SourceECInstanceId, r.SourceECClassId, r.TargetECInstanceid, r.TargetECClassId, ele.Model, ele.Model.Id, ele.Model.RelECClassId FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", + query: + "SELECT r.ECInstanceId, r.ECClassId, r.SourceECInstanceId, r.SourceECClassId, r.TargetECInstanceid, r.TargetECClassId, ele.Model, ele.Model.Id, ele.Model.RelECClassId FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", statementResult: { "id": "0x1", "className": "BisCore.PartitionOriginatesFromRepository", @@ -333,7 +352,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT r.ECInstanceId, r.ECClassId, r.SourceECInstanceId, r.SourceECClassId, r.TargetECInstanceid, r.TargetECClassId, ele.Model, ele.Model.Id, ele.Model.RelECClassId FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", + query: + "SELECT * FROM (SELECT r.ECInstanceId, r.ECClassId, r.SourceECInstanceId, r.SourceECClassId, r.TargetECInstanceid, r.TargetECClassId, ele.Model, ele.Model.Id, ele.Model.RelECClassId FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", statementResult: { "id": "0x1", "className": "BisCore.PartitionOriginatesFromRepository", @@ -364,7 +384,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT r.ECInstanceId a, r.ECClassId b, r.SourceECInstanceId c, r.SourceECClassId d, r.TargetECInstanceid e, r.TargetECClassId f, ele.Model g, ele.Model.Id h, ele.Model.RelECClassId i FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", + query: + "SELECT r.ECInstanceId a, r.ECClassId b, r.SourceECInstanceId c, r.SourceECClassId d, r.TargetECInstanceid e, r.TargetECClassId f, ele.Model g, ele.Model.Id h, ele.Model.RelECClassId i FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -395,7 +416,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT r.ECInstanceId a, r.ECClassId b, r.SourceECInstanceId c, r.SourceECClassId d, r.TargetECInstanceid e, r.TargetECClassId f, ele.Model g, ele.Model.Id h, ele.Model.RelECClassId i FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", + query: + "SELECT * FROM (SELECT r.ECInstanceId a, r.ECClassId b, r.SourceECInstanceId c, r.SourceECClassId d, r.TargetECInstanceid e, r.TargetECClassId f, ele.Model g, ele.Model.Id h, ele.Model.RelECClassId i FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -426,7 +448,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT r.ECInstanceId A, r.ECClassId B, r.SourceECInstanceId C, r.SourceECClassId D, r.TargetECInstanceid E, r.TargetECClassId F, ele.Model G, ele.Model.Id H, ele.Model.RelECClassId I FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", + query: + "SELECT r.ECInstanceId A, r.ECClassId B, r.SourceECInstanceId C, r.SourceECClassId D, r.TargetECInstanceid E, r.TargetECClassId F, ele.Model G, ele.Model.Id H, ele.Model.RelECClassId I FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -457,7 +480,8 @@ describe("ECSql Query", () => { }, }, { - query: "SELECT * FROM (SELECT r.ECInstanceId A, r.ECClassId B, r.SourceECInstanceId C, r.SourceECClassId D, r.TargetECInstanceid E, r.TargetECClassId F, ele.Model G, ele.Model.Id H, ele.Model.RelECClassId I FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", + query: + "SELECT * FROM (SELECT r.ECInstanceId A, r.ECClassId B, r.SourceECInstanceId C, r.SourceECClassId D, r.TargetECInstanceid E, r.TargetECClassId F, ele.Model G, ele.Model.Id H, ele.Model.RelECClassId I FROM Bis.ElementRefersToElements r JOIN Bis.Element ele ON ele.ECInstanceId = r.SourceECInstanceId) LIMIT 1", statementResult: { a: "0x1", b: doNotConvertClassIdsToClassNamesWhenAliased ? "0xa8" : "BisCore.PartitionOriginatesFromRepository", @@ -496,12 +520,20 @@ describe("ECSql Query", () => { for (const testQuery of testQueries) { imodel1.withPreparedStatement(testQuery.query, (stmt: ECSqlStatement) => { assert.equal(DbResult.BE_SQLITE_ROW, stmt.step(), "expected DbResult.BE_SQLITE_ROW"); - assert.deepEqual(stmt.getRow(), testQuery.statementResult, `(ECSqlStatement) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`); + assert.deepEqual( + stmt.getRow(), + testQuery.statementResult, + `(ECSqlStatement) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`, + ); }); let hasRow = false; for await (const row of imodel1.createQueryReader(testQuery.query, undefined, builder.getOptions())) { - assert.deepEqual(row.toRow(), testQuery.readerResult, `(ECSqlReader) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`); + assert.deepEqual( + row.toRow(), + testQuery.readerResult, + `(ECSqlReader) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`, + ); hasRow = true; } assert.isTrue(hasRow, "imodel1.query() must return latest one row"); @@ -510,11 +542,19 @@ describe("ECSql Query", () => { for (const testQuery of testQueries) { imodel6.withPreparedStatement(testQuery.query, (stmt: ECSqlStatement) => { assert.equal(DbResult.BE_SQLITE_ROW, stmt.step(), "expected DbResult.BE_SQLITE_ROW"); - assert.deepEqual(stmt.getRow(), testQuery.statementResult, `(ECSqlStatement) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`); + assert.deepEqual( + stmt.getRow(), + testQuery.statementResult, + `(ECSqlStatement) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`, + ); }); let hasRow = false; for await (const row of imodel6.createQueryReader(testQuery.query, undefined, builder.getOptions())) { - assert.deepEqual(row.toRow(), testQuery.readerResult, `(ECSqlReader) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`); + assert.deepEqual( + row.toRow(), + testQuery.readerResult, + `(ECSqlReader) "${testQuery.query}" does not match expected result (${path.basename(imodel1[_nativeDb].getFilePath())})`, + ); hasRow = true; } assert.isTrue(hasRow, "imodel1.query() must return latest one row"); @@ -536,7 +576,12 @@ describe("ECSql Query", () => { rows = await executeQuery(imodel1, "SELECT 1 FROM bis.GeometricElement3d WHERE GeometryStream=?", [geomStream]); assert.equal(rows.length, 1); - rows = await executeQuery(imodel1, "SELECT ECInstanceId,GeometryStream FROM bis.GeometricElement3d WHERE GeometryStream IS NOT NULL LIMIT 1", undefined, true); + rows = await executeQuery( + imodel1, + "SELECT ECInstanceId,GeometryStream FROM bis.GeometricElement3d WHERE GeometryStream IS NOT NULL LIMIT 1", + undefined, + true, + ); assert.equal(rows.length, 1); assert.isTrue(Id64.isValidId64(rows[0].id)); assert.isDefined(rows[0].geometryStream); @@ -545,26 +590,26 @@ describe("ECSql Query", () => { const ecdb = imodel1; // expect log message when statement fails let slm = new SequentialLogMatcher(); - slm.append().error().category("BeSQLite").message("Error \"no such table: def (BE_SQLITE_ERROR)\" preparing SQL: SELECT abc FROM def"); - assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => { }), "no such table: def (BE_SQLITE_ERROR)"); + slm.append().error().category("BeSQLite").message('Error "no such table: def (BE_SQLITE_ERROR)" preparing SQL: SELECT abc FROM def'); + assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => {}), "no such table: def (BE_SQLITE_ERROR)"); assert.isTrue(slm.finishAndDispose(), "logMatcher should detect log"); // now pass suppress log error which mean we should not get the error slm = new SequentialLogMatcher(); - slm.append().error().category("BeSQLite").message("Error \"no such table: def (BE_SQLITE_ERROR)\" preparing SQL: SELECT abc FROM def"); - assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => { }, /* logErrors = */ false), "no such table: def (BE_SQLITE_ERROR)"); + slm.append().error().category("BeSQLite").message('Error "no such table: def (BE_SQLITE_ERROR)" preparing SQL: SELECT abc FROM def'); + assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => {}, /* logErrors = */ false), "no such table: def (BE_SQLITE_ERROR)"); assert.isFalse(slm.finishAndDispose(), "logMatcher should not detect log"); // expect log message when statement fails slm = new SequentialLogMatcher(); slm.append().error().category("ECDb").message("ECClass 'abc.def' does not exist or could not be loaded."); - assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => { }), "ECClass 'abc.def' does not exist or could not be loaded."); + assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => {}), "ECClass 'abc.def' does not exist or could not be loaded."); assert.isTrue(slm.finishAndDispose(), "logMatcher should detect log"); // now pass suppress log error which mean we should not get the error slm = new SequentialLogMatcher(); slm.append().error().category("ECDb").message("ECClass 'abc.def' does not exist or could not be loaded."); - assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => { }, /* logErrors = */ false), ""); + assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => {}, /* logErrors = */ false), ""); assert.isFalse(slm.finishAndDispose(), "logMatcher should not detect log"); }); it("restart query", async () => { @@ -581,7 +626,11 @@ describe("ECSql Query", () => { const options = new QueryOptionsBuilder(); options.setDelay(delay); options.setRestartToken("tag"); - const reader = imodel1.createQueryReader("SELECT ECInstanceId as Id, Parent.Id as ParentId FROM BisCore.element", undefined, options.getOptions()); + const reader = imodel1.createQueryReader( + "SELECT ECInstanceId as Id, Parent.Id as ParentId FROM BisCore.element", + undefined, + options.getOptions(), + ); while (await reader.step()) { rowCount++; } @@ -633,11 +682,11 @@ describe("ECSql Query", () => { const request: DbQueryRequest = { kind: DbRequestKind.ECSql, query: "SELECT * FROM BisCore.element", - delay: 5000, // Set delay to a value > timeout + delay: 5000, // Set delay to a value > timeout }; try { await new MockECSqlReader(executor, request.query).mockReadRows(request); - assert(false); // We expect this scenario to always throw + assert(false); // We expect this scenario to always throw } catch (error: any) { // Query should give up after max retry count has been reached assert(error.message === "query too long to execute or server is too busy"); @@ -773,7 +822,10 @@ describe("ECSql Query", () => { const i = dbs.indexOf(db); const rowPerPage = getRowPerPage(pageSize, expected[i]); for (let k = 0; k < rowPerPage.length; k++) { - const rs = await db.createQueryReader(query, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames, limit: { count: pageSize, offset: k * pageSize } }).toArray(); + const rs = await db.createQueryReader(query, undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + limit: { count: pageSize, offset: k * pageSize }, + }).toArray(); assert.equal(rs.length, rowPerPage[k]); } } diff --git a/core/backend/src/test/ecdb/ECSqlReader.test.ts b/core/backend/src/test/ecdb/ECSqlReader.test.ts index 6e0f85ec6634..5348537fc1c9 100644 --- a/core/backend/src/test/ecdb/ECSqlReader.test.ts +++ b/core/backend/src/test/ecdb/ECSqlReader.test.ts @@ -12,7 +12,7 @@ import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; import { ECDbTestHelper } from "./ECDbTestHelper"; -describe("ECSqlReader", (() => { +describe("ECSqlReader", () => { let iModel: SnapshotDb; let reader: ECSqlReader; @@ -28,66 +28,81 @@ describe("ECSqlReader", (() => { const outDir = KnownTestLocations.outputDir; it("ecsql reader simple", async () => { - await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "test.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - ecdb.saveChanges(); - const params = new QueryBinder(); - params.bindIdSet(1, ["0x32"]); - const optionBuilder = new QueryOptionsBuilder(); - optionBuilder.setRowFormat(QueryRowFormat.UseJsPropertyNames); - reader = ecdb.createQueryReader("SELECT ECInstanceId, Name FROM meta.ECClassDef WHERE InVirtualSet(?, ECInstanceId)", params, optionBuilder.getOptions()); - const rows = await reader.toArray(); - assert.equal(rows[0].id, "0x32"); - assert.equal(rows.length, 1); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + ecdb.saveChanges(); + const params = new QueryBinder(); + params.bindIdSet(1, ["0x32"]); + const optionBuilder = new QueryOptionsBuilder(); + optionBuilder.setRowFormat(QueryRowFormat.UseJsPropertyNames); + reader = ecdb.createQueryReader( + "SELECT ECInstanceId, Name FROM meta.ECClassDef WHERE InVirtualSet(?, ECInstanceId)", + params, + optionBuilder.getOptions(), + ); + const rows = await reader.toArray(); + assert.equal(rows[0].id, "0x32"); + assert.equal(rows.length, 1); + }, + ); }); it("ecsql reader simple using query reader", async () => { - await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "test.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const r = await ecdb.withStatement("INSERT INTO ts.Foo(n) VALUES(20)", async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - assert.equal(r.id, "0x1"); - - const params = new QueryBinder(); - params.bindId("firstId", r.id!); - - reader = ecdb.createQueryReader("SELECT ECInstanceId, n FROM ts.Foo WHERE ECInstanceId=:firstId", params, { limit: { count: 1 } }); - assert.isTrue(await reader.step()); - // eslint-disable-next-line no-console - assert.equal(reader.current.id, "0x1"); - assert.equal(reader.current.ecinstanceid, "0x1"); - assert.equal(reader.current.n, 20); - assert.equal(reader.current.ID, "0x1"); - assert.equal(reader.current.ECINSTANCEID, "0x1"); - assert.equal(reader.current[0], "0x1"); - assert.equal(reader.current[1], 20); - - const row0 = reader.current.toRow(); - assert.equal(row0.ECInstanceId, "0x1"); - assert.equal(row0.n, 20); - - assert.isFalse(await reader.step()); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const r = await ecdb.withStatement("INSERT INTO ts.Foo(n) VALUES(20)", async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.equal(r.id, "0x1"); + + const params = new QueryBinder(); + params.bindId("firstId", r.id!); + + reader = ecdb.createQueryReader("SELECT ECInstanceId, n FROM ts.Foo WHERE ECInstanceId=:firstId", params, { limit: { count: 1 } }); + assert.isTrue(await reader.step()); + // eslint-disable-next-line no-console + assert.equal(reader.current.id, "0x1"); + assert.equal(reader.current.ecinstanceid, "0x1"); + assert.equal(reader.current.n, 20); + assert.equal(reader.current.ID, "0x1"); + assert.equal(reader.current.ECINSTANCEID, "0x1"); + assert.equal(reader.current[0], "0x1"); + assert.equal(reader.current[1], 20); + + const row0 = reader.current.toRow(); + assert.equal(row0.ECInstanceId, "0x1"); + assert.equal(row0.n, 20); + + assert.isFalse(await reader.step()); + }, + ); }); }); describe("Works as iterable iterator", () => { - it("iterable in for loop", async () => { let actualRowCount = 0; const expectedRowCount = 46; // 46 Elements in test.bim @@ -143,11 +158,9 @@ describe("ECSqlReader", (() => { actualRowCount = rows.length; assert.equal(actualRowCount, expectedRowCount); }); - }); describe("Get id from each row", () => { - it("Get id using iterable iterator with unspecified rowFormat", async () => { let counter = 1; for await (const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 } })) { @@ -167,7 +180,12 @@ describe("ECSqlReader", (() => { it("Get id using iterable iterator with UseJsPropertyNames rowFormat", async () => { let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { const currentExpectedId = `0x${counter}`; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -184,7 +202,12 @@ describe("ECSqlReader", (() => { it("Get id using iterable iterator with UseECSqlPropertyNames rowFormat", async () => { let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyNames, + }) + ) { const currentExpectedId = `0x${counter}`; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -201,7 +224,12 @@ describe("ECSqlReader", (() => { it("Get id using iterable iterator with UseECSqlPropertyIndexes rowFormat", async () => { let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyIndexes, + }) + ) { const currentExpectedId = `0x${counter}`; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -236,7 +264,10 @@ describe("ECSqlReader", (() => { it("Get id using step with UseJsPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseJsPropertyNames }); + reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseJsPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -254,7 +285,10 @@ describe("ECSqlReader", (() => { it("Get id using step with UseECSqlPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyNames }); + reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -272,7 +306,10 @@ describe("ECSqlReader", (() => { it("Get id using step with UseECSqlPropertyIndexes rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes }); + reader = iModel.createQueryReader("SELECT * FROM meta.ECSchemaDef", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyIndexes, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -290,11 +327,14 @@ describe("ECSqlReader", (() => { }); describe("Get duplicate property names", () => { - it("Get duplicate property names using iterable iterator with unspecified rowFormat", async () => { const expectedIds = ["0x1", "0xe", "0x10", "0x11", "0x12"]; let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { limit: { count: 5 } })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { + limit: { count: 5 }, + }) + ) { const currentExpectedId = expectedIds[counter - 1]; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -312,7 +352,12 @@ describe("ECSqlReader", (() => { it("Get duplicate property names using iterable iterator with UseJsPropertyNames rowFormat", async () => { const expectedIds = ["0x1", "0xe", "0x10", "0x11", "0x12"]; let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { const currentExpectedId = expectedIds[counter - 1]; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -330,7 +375,12 @@ describe("ECSqlReader", (() => { it("Get duplicate property names using iterable iterator with UseECSqlPropertyNames rowFormat", async () => { const expectedIds = ["0x1", "0xe", "0x10", "0x11", "0x12"]; let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyNames, + }) + ) { const currentExpectedId = expectedIds[counter - 1]; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -348,7 +398,12 @@ describe("ECSqlReader", (() => { it("Get duplicate property names using iterable iterator with UseECSqlPropertyIndexes rowFormat", async () => { const expectedIds = ["0x1", "0xe", "0x10", "0x11", "0x12"]; let counter = 1; - for await (const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM bis.Element c JOIN bis.Element p ON p.ECInstanceId = c.ECInstanceId", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyIndexes, + }) + ) { const currentExpectedId = expectedIds[counter - 1]; assert.equal(row[0], currentExpectedId); assert.equal(row.id, currentExpectedId); @@ -365,7 +420,6 @@ describe("ECSqlReader", (() => { }); describe("Get specific values", () => { - it("Get only ECInstanceId with unspecified rowFormat", async () => { let counter = 1; reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 } }); @@ -386,7 +440,10 @@ describe("ECSqlReader", (() => { it("Get only ECInstanceId with UseJsPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseJsPropertyNames }); + reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseJsPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -404,7 +461,10 @@ describe("ECSqlReader", (() => { it("Get only ECInstanceId with UseECSqlPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyNames }); + reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -422,7 +482,10 @@ describe("ECSqlReader", (() => { it("Get only ECInstanceId with UseECSqlPropertyIndexes rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes }); + reader = iModel.createQueryReader("SELECT ECInstanceId FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyIndexes, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -440,7 +503,9 @@ describe("ECSqlReader", (() => { it("Get one column with custom name with unspecified rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 } }); + reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -455,7 +520,10 @@ describe("ECSqlReader", (() => { it("Get one column with custom name with UseJsPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseJsPropertyNames }); + reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseJsPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -470,7 +538,10 @@ describe("ECSqlReader", (() => { it("Get one column with custom name with UseECSqlPropertyNames rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyNames }); + reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyNames, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -485,7 +556,10 @@ describe("ECSqlReader", (() => { it("Get one column with custom name with UseECSqlPropertyIndexes rowFormat", async () => { let counter = 1; - reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { limit: { count: 5 }, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes }); + reader = iModel.createQueryReader("SELECT ECInstanceId customColumnName FROM meta.ECSchemaDef ORDER BY ECInstanceId ASC", undefined, { + limit: { count: 5 }, + rowFormat: QueryRowFormat.UseECSqlPropertyIndexes, + }); while (await reader.step()) { const currentExpectedId = `0x${counter}`; assert.equal(reader.current[0], currentExpectedId); @@ -550,7 +624,6 @@ describe("ECSqlReader", (() => { } assert.equal(actualRowCount, expectedRowCount); }); - }); }); -})); +}); diff --git a/core/backend/src/test/ecdb/ECSqlStatement.test.ts b/core/backend/src/test/ecdb/ECSqlStatement.test.ts index 0f16a4aa3b3b..bb04ccfc1168 100644 --- a/core/backend/src/test/ecdb/ECSqlStatement.test.ts +++ b/core/backend/src/test/ecdb/ECSqlStatement.test.ts @@ -2,16 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { DbResult, Guid, GuidString, Id64, Id64String, using } from "@itwin/core-bentley"; import { NavigationValue, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat } from "@itwin/core-common"; import { Point2d, Point3d, Range3d, XAndY, XYAndZ } from "@itwin/core-geometry"; +import { assert } from "chai"; +import { ConcurrentQuery } from "../../ConcurrentQuery"; import { _nativeDb, ECDb, ECEnumValue, ECSqlColumnInfo, ECSqlInsertResult, ECSqlStatement, ECSqlValue, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; import { ECDbTestHelper } from "./ECDbTestHelper"; -import { ConcurrentQuery } from "../../ConcurrentQuery"; /* eslint-disable @typescript-eslint/naming-convention */ const selectSingleRow = new QueryOptionsBuilder().setLimit({ count: 1, offset: -1 }).setRowFormat(QueryRowFormat.UseJsPropertyNames).getOptions(); @@ -32,7 +32,9 @@ async function queryRows(ecdb: ECDb, ecsql: string, params?: QueryBinder, config } async function queryCount(ecdb: ECDb, ecsql: string, params?: QueryBinder, config?: QueryOptions): Promise { ecdb.saveChanges(); - for await (const row of ecdb.createQueryReader(`SELECT COUNT(*) FROM (${ecsql})`, params, { ...config, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes })) { + for await ( + const row of ecdb.createQueryReader(`SELECT COUNT(*) FROM (${ecsql})`, params, { ...config, rowFormat: QueryRowFormat.UseECSqlPropertyIndexes }) + ) { return row[0] as number; } return -1; @@ -58,57 +60,72 @@ describe("ECSqlStatement", () => { const abbreviatedBlobVal = `{"bytes":${blobVal.byteLength}}`; it("check asynchronous step and stepForInsert methods", async () => { - await using(ECDbTestHelper.createECDb(outDir, "asyncmethodtest.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "asyncmethodtest.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const r = await ecdb.withStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - assert.equal(r.id, "0x1"); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const r = await ecdb.withStatement( + "INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", + async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }, + ); + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.equal(r.id, "0x1"); + }, + ); }); it("concurrent query get meta data", async () => { - await using(ECDbTestHelper.createECDb(outDir, "asyncmethodtest.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "asyncmethodtest.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); - await ecdb.withStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", async (stmt: ECSqlStatement) => { - stmt.stepForInsert(); - }); - await ecdb.withStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(30,TIMESTAMP '2019-10-18T12:00:00Z',30)", async (stmt: ECSqlStatement) => { - stmt.stepForInsert(); - }); - ecdb.saveChanges(); - const reader = ecdb.createQueryReader("SELECT * FROM ts.Foo"); - let props = await reader.getMetaData(); - assert.equal(props.length, 5); - let rows = 0; - while (await reader.step()) { - rows++; - } - assert.equal(rows, 2); - props = await reader.getMetaData(); - assert.equal(props.length, 5); - }); + await ecdb.withStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", async (stmt: ECSqlStatement) => { + stmt.stepForInsert(); + }); + await ecdb.withStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(30,TIMESTAMP '2019-10-18T12:00:00Z',30)", async (stmt: ECSqlStatement) => { + stmt.stepForInsert(); + }); + ecdb.saveChanges(); + const reader = ecdb.createQueryReader("SELECT * FROM ts.Foo"); + let props = await reader.getMetaData(); + assert.equal(props.length, 5); + let rows = 0; + while (await reader.step()) { + rows++; + } + assert.equal(rows, 2); + props = await reader.getMetaData(); + assert.equal(props.length, 5); + }, + ); }); it("null string accessor", async () => { - await using(ECDbTestHelper.createECDb(outDir, "nullstring.ecdb"), async (ecdb: ECDb) => { + using(ECDbTestHelper.createECDb(outDir, "nullstring.ecdb"), async (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); await ecdb.withPreparedStatement(`VALUES(NULL)`, async (stmt: ECSqlStatement) => { stmt.step(); @@ -118,307 +135,419 @@ describe("ECSqlStatement", () => { }); }); it("should page results", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - const ROW_COUNT = 27; - // insert test rows - for (let i = 1; i <= ROW_COUNT; i++) { - const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - for (let i = 1; i < ROW_COUNT; i++) { - const rowCount = await queryCount(ecdb, "SELECT ECInstanceId, ECClassId, n FROM ts.Foo WHERE n <= ?", new QueryBinder().bindInt(1, i)); - assert.equal(rowCount, i); - } - - const temp = await queryRows(ecdb, "SELECT ECInstanceId FROM ONLY ts.Foo"); - assert.equal(temp.length, ROW_COUNT); - // query page by page - const PAGE_SIZE = 5; - const QUERY = "SELECT n FROM ts.Foo"; - const EXPECTED_ROW_COUNT = [5, 5, 5, 5, 5, 2]; - const ready = []; - for (let i = 0; i < EXPECTED_ROW_COUNT.length; i++) { - ready.push(queryRows(ecdb, QUERY, undefined, new QueryOptionsBuilder().setLimit({ offset: i * PAGE_SIZE, count: PAGE_SIZE }).getOptions())); - } - // verify if each page has right count of rows - const results = await Promise.all(ready); - for (let i = 0; i < EXPECTED_ROW_COUNT.length; i++) { - assert.equal(results[i].length, EXPECTED_ROW_COUNT[i]); - } - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + const ROW_COUNT = 27; + // insert test rows + for (let i = 1; i <= ROW_COUNT; i++) { + const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + } + ecdb.saveChanges(); + for (let i = 1; i < ROW_COUNT; i++) { + const rowCount = await queryCount(ecdb, "SELECT ECInstanceId, ECClassId, n FROM ts.Foo WHERE n <= ?", new QueryBinder().bindInt(1, i)); + assert.equal(rowCount, i); + } + + const temp = await queryRows(ecdb, "SELECT ECInstanceId FROM ONLY ts.Foo"); + assert.equal(temp.length, ROW_COUNT); + // query page by page + const PAGE_SIZE = 5; + const QUERY = "SELECT n FROM ts.Foo"; + const EXPECTED_ROW_COUNT = [5, 5, 5, 5, 5, 2]; + const ready = []; + for (let i = 0; i < EXPECTED_ROW_COUNT.length; i++) { + ready.push(queryRows(ecdb, QUERY, undefined, new QueryOptionsBuilder().setLimit({ offset: i * PAGE_SIZE, count: PAGE_SIZE }).getOptions())); + } + // verify if each page has right count of rows + const results = await Promise.all(ready); + for (let i = 0; i < EXPECTED_ROW_COUNT.length; i++) { + assert.equal(results[i].length, EXPECTED_ROW_COUNT[i]); + } + }, + ); }); it("paging use cache statement queryRows()", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - const ROW_COUNT = 100; - // insert test rows - for (let i = 1; i <= ROW_COUNT; i++) { - const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - // check if varying page number does not require prepare new statements - ecdb.clearStatementCache(); - const rca = await queryRows(ecdb, "SELECT count(*) as nRows FROM ts.Foo"); - assert.equal(rca[0].nRows, 100); // expe - const rc = await queryCount(ecdb, "SELECT * FROM ts.Foo"); - assert.equal(rc, 100); // expe - let rowNo = 0; - for await (const row of ecdb.createQueryReader("SELECT * FROM ts.Foo", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { - assert.equal(row.n, rowNo + 1); - rowNo = rowNo + 1; - } - assert.equal(rowNo, 100); // expect all rows - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + const ROW_COUNT = 100; + // insert test rows + for (let i = 1; i <= ROW_COUNT; i++) { + const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + } + ecdb.saveChanges(); + // check if varying page number does not require prepare new statements + ecdb.clearStatementCache(); + const rca = await queryRows(ecdb, "SELECT count(*) as nRows FROM ts.Foo"); + assert.equal(rca[0].nRows, 100); // expe + const rc = await queryCount(ecdb, "SELECT * FROM ts.Foo"); + assert.equal(rc, 100); // expe + let rowNo = 0; + for await (const row of ecdb.createQueryReader("SELECT * FROM ts.Foo", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + assert.equal(row.n, rowNo + 1); + rowNo = rowNo + 1; + } + assert.equal(rowNo, 100); // expect all rows + }, + ); }); it("should restart query", async () => { - await using(ECDbTestHelper.createECDb(outDir, "cancelquery.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "cancelquery.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - const ROW_COUNT = 100; - // insert test rows - for (let i = 1; i <= ROW_COUNT; i++) { - const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - ConcurrentQuery.resetConfig(ecdb[_nativeDb], { globalQuota: { time: 1 }, ignoreDelay: false }); - - let cancelled = 0; - let successful = 0; - let rowCount = 0; - const scheduleQuery = async (delay: number) => { - return new Promise(async (resolve, reject) => { - try { - const options = new QueryOptionsBuilder(); - options.setDelay(delay); - options.setRowFormat(QueryRowFormat.UseJsPropertyNames); - options.setRestartToken("tag"); - for await (const _row of ecdb.createQueryReader("SELECT * FROM ts.Foo", undefined, options.getOptions())) { - rowCount++; - } - successful++; - resolve(); - } catch (err: any) { - // we expect query to be cancelled - if (err.errorNumber === DbResult.BE_SQLITE_INTERRUPT) { - cancelled++; + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + const ROW_COUNT = 100; + // insert test rows + for (let i = 1; i <= ROW_COUNT; i++) { + const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + } + ecdb.saveChanges(); + ConcurrentQuery.resetConfig(ecdb[_nativeDb], { globalQuota: { time: 1 }, ignoreDelay: false }); + + let cancelled = 0; + let successful = 0; + let rowCount = 0; + const scheduleQuery = async (delay: number) => { + return new Promise(async (resolve, reject) => { + try { + const options = new QueryOptionsBuilder(); + options.setDelay(delay); + options.setRowFormat(QueryRowFormat.UseJsPropertyNames); + options.setRestartToken("tag"); + for await (const _row of ecdb.createQueryReader("SELECT * FROM ts.Foo", undefined, options.getOptions())) { + rowCount++; + } + successful++; resolve(); - } else { - reject(new Error("rejected")); + } catch (err: any) { + // we expect query to be cancelled + if (err.errorNumber === DbResult.BE_SQLITE_INTERRUPT) { + cancelled++; + resolve(); + } else { + reject(new Error("rejected")); + } } - } - }); - }; - - const queries = []; - queries.push(scheduleQuery(5000)); - queries.push(scheduleQuery(0)); - - await Promise.all(queries); - // We expect at least one query to be cancelled - assert.isAtLeast(cancelled, 1); - assert.isAtLeast(successful, 1); - assert.isAtLeast(rowCount, 1); - }); + }); + }; + + const queries = []; + queries.push(scheduleQuery(5000)); + queries.push(scheduleQuery(0)); + + await Promise.all(queries); + // We expect at least one query to be cancelled + assert.isAtLeast(cancelled, 1); + assert.isAtLeast(successful, 1); + assert.isAtLeast(rowCount, 1); + }, + ); }); it("should use cache statement for query()", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - const ROW_COUNT = 27; - // insert test rows - for (let i = 1; i <= ROW_COUNT; i++) { - const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - // check if varying page number does not require prepare new statements - ecdb.clearStatementCache(); - for (const _testPageSize of [1, 2, 4, 5, 6, 7, 10, ROW_COUNT]) { // eslint-disable-line @typescript-eslint/no-unused-vars - let rowNo = 1; - for await (const row of ecdb.createQueryReader("SELECT n FROM ts.Foo WHERE n != ? and ECInstanceId < ?", new QueryBinder().bindInt(1, 123).bindInt(2, 30), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { - assert.equal(row.n, rowNo); - rowNo = rowNo + 1; + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + const ROW_COUNT = 27; + // insert test rows + for (let i = 1; i <= ROW_COUNT; i++) { + const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); } - assert.equal(rowNo, 28); // expect all rows - assert.equal(0, ecdb.getCachedStatementCount()); // there must be single cached statement used with different size pages. - } - }); + ecdb.saveChanges(); + // check if varying page number does not require prepare new statements + ecdb.clearStatementCache(); + for (const _testPageSize of [1, 2, 4, 5, 6, 7, 10, ROW_COUNT]) { // eslint-disable-line @typescript-eslint/no-unused-vars + let rowNo = 1; + for await ( + const row of ecdb.createQueryReader( + "SELECT n FROM ts.Foo WHERE n != ? and ECInstanceId < ?", + new QueryBinder().bindInt(1, 123).bindInt(2, 30), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { + assert.equal(row.n, rowNo); + rowNo = rowNo + 1; + } + assert.equal(rowNo, 28); // expect all rows + assert.equal(0, ecdb.getCachedStatementCount()); // there must be single cached statement used with different size pages. + } + }, + ); }); it("concurrent query binding", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - for (let i = 1; i <= 5; i++) { - const r = await ecdb.withPreparedStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - for await (const row of ecdb.createQueryReader("SELECT count(*) as cnt FROM ts.Foo WHERE n in (:a, :b, :c)", new QueryBinder().bindInt("a", 1).bindInt("b", 2).bindInt("c", 3), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { - assert.equal(row.cnt, 3); - } - for await (const row of ecdb.createQueryReader("SELECT count(*) as cnt FROM ts.Foo WHERE n in (?, ?, ?)", new QueryBinder().bindInt(1, 1).bindInt(2, 2).bindInt(3, 3), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { - assert.equal(row.cnt, 3); - } - const slm = new SequentialLogMatcher(); - slm.append().error().category("ECDb").message("No parameter index found for parameter name: d."); - try { - for await (const row of ecdb.createQueryReader("SELECT count(*) as cnt FROM ts.Foo WHERE n in (:a, :b, :c)", new QueryBinder().bindInt("a", 1).bindInt("b", 2).bindInt("c", 3).bindInt("d", 3), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + for (let i = 1; i <= 5; i++) { + const r = await ecdb.withPreparedStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + } + ecdb.saveChanges(); + for await ( + const row of ecdb.createQueryReader( + "SELECT count(*) as cnt FROM ts.Foo WHERE n in (:a, :b, :c)", + new QueryBinder().bindInt("a", 1).bindInt("b", 2).bindInt("c", 3), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { assert.equal(row.cnt, 3); } - assert.isFalse(true); - } catch (e) { assert.isNotNull(e); } - assert.isTrue(slm.finishAndDispose()); - }); + for await ( + const row of ecdb.createQueryReader( + "SELECT count(*) as cnt FROM ts.Foo WHERE n in (?, ?, ?)", + new QueryBinder().bindInt(1, 1).bindInt(2, 2).bindInt(3, 3), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { + assert.equal(row.cnt, 3); + } + const slm = new SequentialLogMatcher(); + slm.append().error().category("ECDb").message("No parameter index found for parameter name: d."); + try { + for await ( + const row of ecdb.createQueryReader( + "SELECT count(*) as cnt FROM ts.Foo WHERE n in (:a, :b, :c)", + new QueryBinder().bindInt("a", 1).bindInt("b", 2).bindInt("c", 3).bindInt("d", 3), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { + assert.equal(row.cnt, 3); + } + assert.isFalse(true); + } catch (e) { + assert.isNotNull(e); + } + assert.isTrue(slm.finishAndDispose()); + }, + ); }); it("check HextoId() and IdToHex() ecsql functions", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - for (let i = 1; i <= 2; i++) { - const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - for await (const row of ecdb.createQueryReader("SELECT IdToHex(ECInstanceId) as hexId, ECInstanceId, HexToId('0x1') as idhex FROM ts.Foo WHERE n = ?", new QueryBinder().bindInt(1, 1), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { - assert.equal(row.hexId, row.id); - assert.equal(row.hexId, row.idhex); - } - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + for (let i = 1; i <= 2; i++) { + const r = await ecdb.withStatement(`insert into ts.Foo(n) values(${i})`, async (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + } + ecdb.saveChanges(); + for await ( + const row of ecdb.createQueryReader( + "SELECT IdToHex(ECInstanceId) as hexId, ECInstanceId, HexToId('0x1') as idhex FROM ts.Foo WHERE n = ?", + new QueryBinder().bindInt(1, 1), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { + assert.equal(row.hexId, row.id); + assert.equal(row.hexId, row.idhex); + } + }, + ); }); it("should bind BeGuid", async () => { - await using(ECDbTestHelper.createECDb(outDir, "pagingresultset.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "pagingresultset.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - const maxRows = 10; - const guids: GuidString[] = []; - for (let i = 0; i < maxRows; i++) { - const r = await ecdb.withPreparedStatement(`insert into ts.Foo(guid) values(?)`, async (stmt: ECSqlStatement) => { - guids.push(Guid.createValue()); - stmt.bindGuid(1, guids[i]); - return stmt.stepForInsert(); - }); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - } - ecdb.saveChanges(); - - const uint8arrayToGuid = (guidArray: any) => { - if (!(guidArray instanceof Uint8Array)) - throw new Error("Expecting a Uint8Array type argument"); - - if (guidArray.byteLength !== 16) - throw new Error("Expecting a Uint8Array of length 16"); - - let guidStr: string = ""; - const part = [0, 4, 6, 8, 10, 16]; - for (let z = 0; z < part.length - 1; z++) { - guidArray.subarray(part[z], part[z + 1]).forEach((c) => { - guidStr += (`00${c.toString(16)}`).slice(-2); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + const maxRows = 10; + const guids: GuidString[] = []; + for (let i = 0; i < maxRows; i++) { + const r = await ecdb.withPreparedStatement(`insert into ts.Foo(guid) values(?)`, async (stmt: ECSqlStatement) => { + guids.push(Guid.createValue()); + stmt.bindGuid(1, guids[i]); + return stmt.stepForInsert(); }); - if (z < part.length - 2) - guidStr += "-"; + assert.equal(r.status, DbResult.BE_SQLITE_DONE); } - return guidStr; - }; - const guidToUint8Array = (v: GuidString) => { - if (v.length !== 36) - throw new Error("Guid is expected to have 36 characters xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); - - const ar = new Uint8Array(16); - const t = v.split("-").join(""); - let i = 0; - for (let z = 0; z < 32; z += 2) { - ar[i++] = parseInt(t.substring(z, z + 2), 16); + ecdb.saveChanges(); + + const uint8arrayToGuid = (guidArray: any) => { + if (!(guidArray instanceof Uint8Array)) + throw new Error("Expecting a Uint8Array type argument"); + + if (guidArray.byteLength !== 16) + throw new Error("Expecting a Uint8Array of length 16"); + + let guidStr: string = ""; + const part = [0, 4, 6, 8, 10, 16]; + for (let z = 0; z < part.length - 1; z++) { + guidArray.subarray(part[z], part[z + 1]).forEach((c) => { + guidStr += (`00${c.toString(16)}`).slice(-2); + }); + if (z < part.length - 2) + guidStr += "-"; + } + return guidStr; + }; + const guidToUint8Array = (v: GuidString) => { + if (v.length !== 36) + throw new Error("Guid is expected to have 36 characters xxxxxxxx-xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + + const ar = new Uint8Array(16); + const t = v.split("-").join(""); + let i = 0; + for (let z = 0; z < 32; z += 2) { + ar[i++] = parseInt(t.substring(z, z + 2), 16); + } + return ar; + }; + + const testGuid = "74da899a-6dde-406c-bf45-f4547d948f00"; + assert.equal(testGuid, uint8arrayToGuid(guidToUint8Array(testGuid))); + let k = 0; + assert.equal( + await query(ecdb, "SELECT guid FROM ts.Foo ORDER BY ECInstanceId", undefined, undefined, (row: any) => { + assert.equal(row.guid, guids[k++]); + }), + maxRows, + ); + + // following will not return any guid BLOB ? = STRING + for (const guid of guids) { + assert.equal( + await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=?", new QueryBinder().bindString(1, guid), undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 1, + ); + assert.equal( + await query(ecdb, `SELECT guid FROM ts.Foo WHERE guid='${guid}'`, undefined, undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 0, + ); + assert.equal( + await query(ecdb, `SELECT guid FROM ts.Foo WHERE guid=StrToGuid('${guid}')`, undefined, undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 1, + ); + assert.equal( + await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=StrToGuid(?)", new QueryBinder().bindString(1, guid), undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 1, + ); + assert.equal( + await query(ecdb, "SELECT guid FROM ts.Foo WHERE GuidToStr(guid)=?", new QueryBinder().bindString(1, guid), undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 1, + ); + assert.equal( + await query( + ecdb, + "SELECT guid FROM ts.Foo WHERE guid=?", + new QueryBinder().bindBlob(1, guidToUint8Array(guid)), + undefined, + (row: any) => { + assert.equal(row.guid, guid); + }, + ), + 1, + ); + assert.equal( + await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=StrToGuid(?)", new QueryBinder().bindString(1, guid), undefined, (row: any) => { + assert.equal(row.guid, guid); + }), + 1, + ); + assert.equal( + await query( + ecdb, + "SELECT GuidToStr(guid) as gstr FROM ts.Foo WHERE guid=StrToGuid(?)", + new QueryBinder().bindString(1, guid), + undefined, + (row: any) => { + assert.equal(row.gstr, guid); + }, + ), + 1, + ); } - return ar; - }; - - const testGuid = "74da899a-6dde-406c-bf45-f4547d948f00"; - assert.equal(testGuid, uint8arrayToGuid(guidToUint8Array(testGuid))); - let k = 0; - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo ORDER BY ECInstanceId", undefined, undefined, (row: any) => { - assert.equal(row.guid, guids[k++]); - }), maxRows); - - // following will not return any guid BLOB ? = STRING - for (const guid of guids) { - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=?", new QueryBinder().bindString(1, guid), undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, `SELECT guid FROM ts.Foo WHERE guid='${guid}'`, undefined, undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 0); - assert.equal(await query(ecdb, `SELECT guid FROM ts.Foo WHERE guid=StrToGuid('${guid}')`, undefined, undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=StrToGuid(?)", new QueryBinder().bindString(1, guid), undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo WHERE GuidToStr(guid)=?", new QueryBinder().bindString(1, guid), undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=?", new QueryBinder().bindBlob(1, guidToUint8Array(guid)), undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, "SELECT guid FROM ts.Foo WHERE guid=StrToGuid(?)", new QueryBinder().bindString(1, guid), undefined, (row: any) => { - assert.equal(row.guid, guid); - }), 1); - assert.equal(await query(ecdb, "SELECT GuidToStr(guid) as gstr FROM ts.Foo WHERE guid=StrToGuid(?)", new QueryBinder().bindString(1, guid), undefined, (row: any) => { - assert.equal(row.gstr, guid); - }), 1); - } - }); + }, + ); }); it("should bind Ids", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { - + using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); const verify = async (ecdbToVerify: ECDb, actualRes: ECSqlInsertResult, expectedECInstanceId?: Id64String) => { @@ -432,27 +561,42 @@ describe("ECSqlStatement", () => { assert.isDefined(actualRes.id); assert.equal(actualRes.id!, expectedECInstanceId); - ecdbToVerify.withPreparedStatement("SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, expectedId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.id, expectedECInstanceId); - assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); - assert.equal(row.name, `${Id64.getLocalId(expectedECInstanceId).toString()}.txt`); - }); - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=?", new QueryBinder().bindString(1, expectedId), new QueryOptionsBuilder().setLimit({ count: 1, offset: -1 }).getOptions(), (row) => { - assert.equal(row.id, expectedECInstanceId); - assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); - assert.equal(row.name, `${Id64.getLocalId(expectedECInstanceId).toString()}.txt`); - }), 1); + ecdbToVerify.withPreparedStatement( + "SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, expectedId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.id, expectedECInstanceId); + assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); + assert.equal(row.name, `${Id64.getLocalId(expectedECInstanceId).toString()}.txt`); + }, + ); + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=?", + new QueryBinder().bindString(1, expectedId), + new QueryOptionsBuilder().setLimit({ count: 1, offset: -1 }).getOptions(), + (row) => { + assert.equal(row.id, expectedECInstanceId); + assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); + assert.equal(row.name, `${Id64.getLocalId(expectedECInstanceId).toString()}.txt`); + }, + ), + 1, + ); }; let expectedId = Id64.fromLocalAndBriefcaseIds(4444, 0); - let r: ECSqlInsertResult = ecdb.withPreparedStatement("INSERT INTO ecdbf.ExternalFileInfo(ECInstanceId,Name) VALUES(?,?)", (stmt: ECSqlStatement) => { - stmt.bindId(1, expectedId); - stmt.bindString(2, "4444.txt"); - return stmt.stepForInsert(); - }); + let r: ECSqlInsertResult = ecdb.withPreparedStatement( + "INSERT INTO ecdbf.ExternalFileInfo(ECInstanceId,Name) VALUES(?,?)", + (stmt: ECSqlStatement) => { + stmt.bindId(1, expectedId); + stmt.bindString(2, "4444.txt"); + return stmt.stepForInsert(); + }, + ); await verify(ecdb, r, expectedId); expectedId = Id64.fromLocalAndBriefcaseIds(4445, 0); @@ -501,779 +645,948 @@ describe("ECSqlStatement", () => { slm.append().error().category("ECDb").message(/String must be a valid ISO 8601 date, time or timestamp/gm); slm.append().error().category("ECDb").message(/only BindDateTime or BindText can be called for a column of the DateTime type/gm); - await using(ECDbTestHelper.createECDb(outDir, "bindnumericanddatestrings.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindnumericanddatestrings.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const r: ECSqlInsertResult = ecdb.withPreparedStatement( + "INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", + (stmt: ECSqlStatement) => { + return stmt.stepForInsert(); + }, + ); + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + const ecsqln = "SELECT 1 FROM ts.Foo WHERE n=?"; + await ecdb.withPreparedStatement(ecsqln, async (stmt: ECSqlStatement) => { + const nNum: number = 20; + const nStr: string = "20"; + const nDt: string = "2019-01-21T12:00:00Z"; + const nHexStr: string = "0x14"; + + stmt.bindInteger(1, nNum); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); + assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindInt(1, nNum), selectSingleRow), 1); - const r: ECSqlInsertResult = ecdb.withPreparedStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", (stmt: ECSqlStatement) => { - return stmt.stepForInsert(); - }); - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - const ecsqln = "SELECT 1 FROM ts.Foo WHERE n=?"; - await ecdb.withPreparedStatement(ecsqln, async (stmt: ECSqlStatement) => { - const nNum: number = 20; - const nStr: string = "20"; - const nDt: string = "2019-01-21T12:00:00Z"; - const nHexStr: string = "0x14"; - - stmt.bindInteger(1, nNum); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindInt(1, nNum), selectSingleRow), 1); - - stmt.bindValue(1, nNum); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(nNum); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([nNum]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, nStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nStr), selectSingleRow), 1); - - stmt.bindValue(1, nStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(nStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([nStr]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, nDt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Date time string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nDt), selectSingleRow), 0); - - stmt.bindValue(1, nDt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Date time string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(nDt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Date time string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([nDt]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Date time string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, nHexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nHexStr), selectSingleRow), 0); - - stmt.bindValue(1, nHexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(nHexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([nHexStr]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); - stmt.reset(); - stmt.clearBindings(); - }); + stmt.bindValue(1, nNum); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - const ecsqldt = "SELECT 1 FROM ts.Foo WHERE dt=?"; - await ecdb.withPreparedStatement(ecsqldt, async (stmt: ECSqlStatement) => { - const dtStr: string = "2018-10-18T12:00:00Z"; - const num: number = 2458410; - const str: string = "2458410"; - const hexStr: string = "0x25832a"; + stmt.getBinder(1).bind(nNum); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - stmt.bindDateTime(1, dtStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); + stmt.bindValues([nNum]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await queryCount(ecdb, ecsqldt, new QueryBinder().bindString(1, dtStr)), 1); - stmt.bindString(1, dtStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); + stmt.bindString(1, nStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - stmt.bindValue(1, dtStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); + assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nStr), selectSingleRow), 1); - stmt.getBinder(1).bind(dtStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); + stmt.bindValue(1, nStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - stmt.bindValues([dtStr]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); + stmt.getBinder(1).bind(nStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.bindInteger(1, num)); - stmt.clearBindings(); + stmt.bindValues([nStr]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([num])), 0); - assert.throw(() => stmt.bindValue(1, num)); - stmt.clearBindings(); + stmt.bindString(1, nDt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "Date time string is not parsed. SQLite just converts it to something which does not match", + ); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.getBinder(1).bind(num)); - stmt.clearBindings(); + assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nDt), selectSingleRow), 0); - assert.throw(() => stmt.bindValues([num])); - stmt.clearBindings(); + stmt.bindValue(1, nDt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "Date time string is not parsed. SQLite just converts it to something which does not match", + ); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.bindString(1, str)); - stmt.clearBindings(); + stmt.getBinder(1).bind(nDt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "Date time string is not parsed. SQLite just converts it to something which does not match", + ); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.bindValue(1, str)); - stmt.clearBindings(); + stmt.bindValues([nDt]); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "Date time string is not parsed. SQLite just converts it to something which does not match", + ); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([str])), 0); + stmt.bindString(1, nHexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.getBinder(1).bind(str)); - stmt.clearBindings(); + assert.equal(await queryCount(ecdb, ecsqln, new QueryBinder().bindString(1, nHexStr), selectSingleRow), 0); - assert.throw(() => stmt.bindValues([str])); - stmt.clearBindings(); + stmt.bindValue(1, nHexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.bindString(1, hexStr)); - stmt.clearBindings(); + stmt.getBinder(1).bind(nHexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([hexStr])), 0); + stmt.bindValues([nHexStr]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "Hex string is not parsed. SQLite just converts it to something which does not match"); + stmt.reset(); + stmt.clearBindings(); + }); - assert.throw(() => stmt.bindValue(1, hexStr)); - stmt.clearBindings(); + const ecsqldt = "SELECT 1 FROM ts.Foo WHERE dt=?"; + await ecdb.withPreparedStatement(ecsqldt, async (stmt: ECSqlStatement) => { + const dtStr: string = "2018-10-18T12:00:00Z"; + const num: number = 2458410; + const str: string = "2458410"; + const hexStr: string = "0x25832a"; - assert.throw(() => stmt.getBinder(1).bind(hexStr)); - stmt.clearBindings(); + stmt.bindDateTime(1, dtStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.throw(() => stmt.bindValues([hexStr])); - stmt.clearBindings(); - }); + assert.equal(await queryCount(ecdb, ecsqldt, new QueryBinder().bindString(1, dtStr)), 1); + stmt.bindString(1, dtStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - const ecsqlfooId = "SELECT 1 FROM ts.Foo WHERE fooId=?"; - await ecdb.withPreparedStatement(ecsqlfooId, async (stmt: ECSqlStatement) => { - const num: number = 20; - const str: string = "20"; - const dt: string = "2019-01-21T12:00:00Z"; - const hexStr: string = "0x14"; - - stmt.bindId(1, hexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([hexStr])), 0); - - stmt.bindValues([hexStr]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, hexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValue(1, hexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(hexStr); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([hexStr]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, str); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([str])), 0); - - stmt.bindValue(1, str); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(str); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([str]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindInteger(1, num); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([num])), 0); - - stmt.bindValue(1, num); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(num); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([num]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindString(1, dt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here"); - stmt.reset(); - stmt.clearBindings(); - - assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([dt])), 0); - - stmt.bindValue(1, dt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here"); - stmt.reset(); - stmt.clearBindings(); - - stmt.getBinder(1).bind(dt); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here"); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues([dt]); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE, "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here"); - stmt.reset(); - stmt.clearBindings(); - }); - }); - assert.isTrue(slm.finishAndDispose()); - }); + stmt.bindValue(1, dtStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - it("should bind numbers", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindnumbers.ecdb", - ` - - - - - - - - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); + stmt.getBinder(1).bind(dtStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - const doubleVal: number = 3.5; - let id = await ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindDouble')", async (stmt: ECSqlStatement) => { - stmt.bindDouble(1, doubleVal); - stmt.bindDouble(2, doubleVal); - stmt.bindDouble(3, doubleVal); - stmt.bindDouble(4, doubleVal); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindValues([dtStr]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - await ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, doubleVal); - assert.equal(row.i, 3); - assert.equal(row.l, 3); - assert.equal(row.s, "3.5"); - }); + assert.throw(() => stmt.bindInteger(1, num)); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { limit: { count: 1 } }, (row: any) => { - assert.equal(row.d, doubleVal); - assert.equal(row.i, 3); - assert.equal(row.l, 3); - assert.equal(row.s, "3.5"); - }), 1); - - const smallIntVal: number = 3; - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, small int')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, smallIntVal); - stmt.bindInteger(2, smallIntVal); - stmt.bindInteger(3, smallIntVal); - stmt.bindInteger(4, smallIntVal); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([num])), 0); + assert.throw(() => stmt.bindValue(1, num)); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, smallIntVal); - assert.equal(row.i, smallIntVal); - assert.equal(row.l, smallIntVal); - assert.equal(row.s, "3"); - }); + assert.throw(() => stmt.getBinder(1).bind(num)); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, smallIntVal); - assert.equal(row.i, smallIntVal); - assert.equal(row.l, smallIntVal); - assert.equal(row.s, "3"); - }), 1); - - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - const largeUnsafeNumber: number = 12312312312312323654; // too large for int64, but fits into uint64 - assert.isFalse(Number.isSafeInteger(largeUnsafeNumber)); - const largeUnsafeNumberStr: string = "12312312312312323654"; - const largeUnsafeNumberHexStr: string = "0xaade1ed08b0b5e46"; - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large unsafe number as string')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeUnsafeNumberStr); - stmt.bindInteger(2, largeUnsafeNumberStr); - stmt.bindInteger(3, largeUnsafeNumberStr); - stmt.bindInteger(4, largeUnsafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.bindValues([num])); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.si, largeUnsafeNumberStr); - assert.equal(row.hi, largeUnsafeNumberHexStr); - assert.equal(row.sl, largeUnsafeNumberStr); - assert.equal(row.hl, largeUnsafeNumberHexStr); - }); + assert.throw(() => stmt.bindString(1, str)); + stmt.clearBindings(); - // assert.equal(await query(ecdb, "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { - // assert.equal(row.si, largeUnsafeNumberStr); - // assert.equal(row.hi, largeUnsafeNumberHexStr); - // assert.equal(row.sl, largeUnsafeNumberStr); - // assert.equal(row.hl, largeUnsafeNumberHexStr); - // }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large unsafe number as hexstring')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeUnsafeNumberHexStr); - stmt.bindInteger(2, largeUnsafeNumberHexStr); - stmt.bindInteger(3, largeUnsafeNumberHexStr); - stmt.bindInteger(4, largeUnsafeNumberHexStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.bindValue(1, str)); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.si, largeUnsafeNumberStr); - assert.equal(row.hi, largeUnsafeNumberHexStr); - assert.equal(row.sl, largeUnsafeNumberStr); - assert.equal(row.hl, largeUnsafeNumberHexStr); - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([str])), 0); - // assert.equal(await query(ecdb, "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { - // assert.equal(row.si, largeUnsafeNumberStr); - // assert.equal(row.hi, largeUnsafeNumberHexStr); - // assert.equal(row.sl, largeUnsafeNumberStr); - // assert.equal(row.hl, largeUnsafeNumberHexStr); - // }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large unsafe number as string')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeUnsafeNumberStr); - stmt.bindString(2, largeUnsafeNumberStr); - stmt.bindString(3, largeUnsafeNumberStr); - stmt.bindString(4, largeUnsafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.getBinder(1).bind(str)); + stmt.clearBindings(); - // uint64 cannot be bound as string in SQLite. They get converted to reals - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.isNumber(row.d); - assert.isNumber(row.i); - assert.isNumber(row.l); - assert.equal(row.s, largeUnsafeNumberStr); - }); + assert.throw(() => stmt.bindValues([str])); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.isNumber(row.d); - assert.isNumber(row.i); - assert.isNumber(row.l); - assert.equal(row.s, largeUnsafeNumberStr); - }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large unsafe number as hexstring')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeUnsafeNumberHexStr); - stmt.bindString(2, largeUnsafeNumberHexStr); - stmt.bindString(3, largeUnsafeNumberHexStr); - stmt.bindString(4, largeUnsafeNumberHexStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.bindString(1, hexStr)); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeUnsafeNumberHexStr); - assert.equal(row.i, largeUnsafeNumberHexStr); - assert.equal(row.l, largeUnsafeNumberHexStr); - assert.equal(row.s, largeUnsafeNumberHexStr); - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([hexStr])), 0); - assert.equal(await query(ecdb, "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeUnsafeNumberHexStr); - assert.equal(row.i, largeUnsafeNumberHexStr); - assert.equal(row.l, largeUnsafeNumberHexStr); - assert.equal(row.s, largeUnsafeNumberHexStr); - }), 1); - - // eslint-disable-next-line @typescript-eslint/no-loss-of-precision - const largeNegUnsafeNumber: number = -123123123123123236; - assert.isFalse(Number.isSafeInteger(largeNegUnsafeNumber)); - const largeNegUnsafeNumberStr: string = "-123123123123123236"; - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative unsafe number as string')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeNegUnsafeNumberStr); - stmt.bindInteger(2, largeNegUnsafeNumberStr); - stmt.bindInteger(3, largeNegUnsafeNumberStr); - stmt.bindInteger(4, largeNegUnsafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.bindValue(1, hexStr)); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.i, largeNegUnsafeNumberStr); - assert.equal(row.l, largeNegUnsafeNumberStr); - assert.equal(row.s, largeNegUnsafeNumberStr); - }); + assert.throw(() => stmt.getBinder(1).bind(hexStr)); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.i, largeNegUnsafeNumberStr); - assert.equal(row.l, largeNegUnsafeNumberStr); - assert.equal(row.s, largeNegUnsafeNumberStr); - }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large negative unsafe number as string')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeNegUnsafeNumberStr); - stmt.bindString(2, largeNegUnsafeNumberStr); - stmt.bindString(3, largeNegUnsafeNumberStr); - stmt.bindString(4, largeNegUnsafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.throw(() => stmt.bindValues([hexStr])); + stmt.clearBindings(); + }); - ecdb.withPreparedStatement("SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.i, largeNegUnsafeNumberStr); - assert.equal(row.l, largeNegUnsafeNumberStr); - assert.equal(row.s, largeNegUnsafeNumberStr); - }); + const ecsqlfooId = "SELECT 1 FROM ts.Foo WHERE fooId=?"; + await ecdb.withPreparedStatement(ecsqlfooId, async (stmt: ECSqlStatement) => { + const num: number = 20; + const str: string = "20"; + const dt: string = "2019-01-21T12:00:00Z"; + const hexStr: string = "0x14"; - assert.equal(await query(ecdb, "SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.i, largeNegUnsafeNumberStr); - assert.equal(row.l, largeNegUnsafeNumberStr); - assert.equal(row.s, largeNegUnsafeNumberStr); - }), 1); - - const largeSafeNumber: number = 1231231231231232; - assert.isTrue(Number.isSafeInteger(largeSafeNumber)); - const largeSafeNumberStr: string = largeSafeNumber.toString(); - const largeSafeNumberHexStr: string = "0x45fcc5c2c8500"; - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeSafeNumber); - stmt.bindInteger(2, largeSafeNumber); - stmt.bindInteger(3, largeSafeNumber); - stmt.bindInteger(4, largeSafeNumber); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindId(1, hexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I, Str(I) si, HexStr(I) hi, L, Str(L) sl, HexStr(L) hl,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.si, largeSafeNumberStr); - assert.equal(row.hi, largeSafeNumberHexStr); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.sl, largeSafeNumberStr); - assert.equal(row.hl, largeSafeNumberHexStr); - assert.equal(row.s, largeSafeNumberStr); - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([hexStr])), 0); - // await query(ecdb, "SELECT D,I, Str(I) si, HexStr(I) hi, L, Str(L) sl, HexStr(L) hl,S FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { - // assert.equal(row.d, largeSafeNumber); - // assert.equal(row.i, largeSafeNumber); - // assert.equal(row.si, largeSafeNumberStr); - // assert.equal(row.hi, largeSafeNumberHexStr); - // assert.equal(row.l, largeSafeNumber); - // assert.equal(row.sl, largeSafeNumberStr); - // assert.equal(row.hl, largeSafeNumberHexStr); - // assert.equal(row.s, largeSafeNumberStr); - // }); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number as string')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeSafeNumberStr); - stmt.bindInteger(2, largeSafeNumberStr); - stmt.bindInteger(3, largeSafeNumberStr); - stmt.bindInteger(4, largeSafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindValues([hexStr]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); - }); + stmt.bindString(1, hexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); - }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number as hexstring')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeSafeNumberHexStr); - stmt.bindInteger(2, largeSafeNumberHexStr); - stmt.bindInteger(3, largeSafeNumberHexStr); - stmt.bindInteger(4, largeSafeNumberHexStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindValue(1, hexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting - }); + stmt.getBinder(1).bind(hexStr); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting - }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large safe number as string')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeSafeNumberStr); - stmt.bindString(2, largeSafeNumberStr); - stmt.bindString(3, largeSafeNumberStr); - stmt.bindString(4, largeSafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindValues([hexStr]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); - }); + stmt.bindString(1, str); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeSafeNumber); - assert.equal(row.i, largeSafeNumber); - assert.equal(row.l, largeSafeNumber); - assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting - }), 1); - - // SQLite does not parse hex strs bound as strings. - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large safe number as hexstring')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeSafeNumberHexStr); - stmt.bindString(2, largeSafeNumberHexStr); - stmt.bindString(3, largeSafeNumberHexStr); - stmt.bindString(4, largeSafeNumberHexStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([str])), 0); - ecdb.withPreparedStatement("SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeSafeNumberHexStr); - assert.equal(row.i, largeSafeNumberHexStr); - assert.equal(row.l, largeSafeNumberHexStr); - assert.equal(row.s, largeSafeNumberHexStr); - }); + stmt.bindValue(1, str); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeSafeNumberHexStr); - assert.equal(row.i, largeSafeNumberHexStr); - assert.equal(row.l, largeSafeNumberHexStr); - assert.equal(row.s, largeSafeNumberHexStr); - }), 1); - - const largeNegSafeNumber: number = -1231231231231232; - assert.isTrue(Number.isSafeInteger(largeNegSafeNumber)); - const largeNegSafeNumberStr: string = largeNegSafeNumber.toString(); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative safe number')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeNegSafeNumber); - stmt.bindInteger(2, largeNegSafeNumber); - stmt.bindInteger(3, largeNegSafeNumber); - stmt.bindInteger(4, largeNegSafeNumber); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.getBinder(1).bind(str); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }); + stmt.bindValues([str]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }), 1); - - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative safe number as string')", (stmt: ECSqlStatement) => { - stmt.bindInteger(1, largeNegSafeNumberStr); - stmt.bindInteger(2, largeNegSafeNumberStr); - stmt.bindInteger(3, largeNegSafeNumberStr); - stmt.bindInteger(4, largeNegSafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.bindInteger(1, num); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([num])), 0); - await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }); + stmt.bindValue(1, num); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - id = ecdb.withPreparedStatement("INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large negative safe number as string')", (stmt: ECSqlStatement) => { - stmt.bindString(1, largeNegSafeNumberStr); - stmt.bindString(2, largeNegSafeNumberStr); - stmt.bindString(3, largeNegSafeNumberStr); - stmt.bindString(4, largeNegSafeNumberStr); - const r: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - return r.id!; - }); + stmt.getBinder(1).bind(num); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }); + stmt.bindValues([num]); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + stmt.reset(); + stmt.clearBindings(); - await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { - assert.equal(row.d, largeNegSafeNumber); - assert.equal(row.i, largeNegSafeNumber); - assert.equal(row.l, largeNegSafeNumber); - assert.equal(row.s, largeNegSafeNumberStr); - }); + stmt.bindString(1, dt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here", + ); + stmt.reset(); + stmt.clearBindings(); - }); + assert.equal(await queryCount(ecdb, ecsqldt, QueryBinder.from([dt])), 0); + + stmt.bindValue(1, dt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here", + ); + stmt.reset(); + stmt.clearBindings(); + + stmt.getBinder(1).bind(dt); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here", + ); + stmt.reset(); + stmt.clearBindings(); + + stmt.bindValues([dt]); + assert.equal( + stmt.step(), + DbResult.BE_SQLITE_DONE, + "DateTime string is not parsed into what it means. SQlite just uses its regular string conversion routines which don't match here", + ); + stmt.reset(); + stmt.clearBindings(); + }); + }, + ); + assert.isTrue(slm.finishAndDispose()); + }); + + it("should bind numbers", async () => { + using( + ECDbTestHelper.createECDb( + outDir, + "bindnumbers.ecdb", + ` + + + + + + + + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const doubleVal: number = 3.5; + let id = await ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindDouble')", + async (stmt: ECSqlStatement) => { + stmt.bindDouble(1, doubleVal); + stmt.bindDouble(2, doubleVal); + stmt.bindDouble(3, doubleVal); + stmt.bindDouble(4, doubleVal); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + await ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, doubleVal); + assert.equal(row.i, 3); + assert.equal(row.l, 3); + assert.equal(row.s, "3.5"); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { limit: { count: 1 } }, (row: any) => { + assert.equal(row.d, doubleVal); + assert.equal(row.i, 3); + assert.equal(row.l, 3); + assert.equal(row.s, "3.5"); + }), + 1, + ); + + const smallIntVal: number = 3; + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, small int')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, smallIntVal); + stmt.bindInteger(2, smallIntVal); + stmt.bindInteger(3, smallIntVal); + stmt.bindInteger(4, smallIntVal); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, smallIntVal); + assert.equal(row.i, smallIntVal); + assert.equal(row.l, smallIntVal); + assert.equal(row.s, "3"); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, smallIntVal); + assert.equal(row.i, smallIntVal); + assert.equal(row.l, smallIntVal); + assert.equal(row.s, "3"); + }), + 1, + ); + + // eslint-disable-next-line @typescript-eslint/no-loss-of-precision + const largeUnsafeNumber: number = 12312312312312323654; // too large for int64, but fits into uint64 + assert.isFalse(Number.isSafeInteger(largeUnsafeNumber)); + const largeUnsafeNumberStr: string = "12312312312312323654"; + const largeUnsafeNumberHexStr: string = "0xaade1ed08b0b5e46"; + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large unsafe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeUnsafeNumberStr); + stmt.bindInteger(2, largeUnsafeNumberStr); + stmt.bindInteger(3, largeUnsafeNumberStr); + stmt.bindInteger(4, largeUnsafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.si, largeUnsafeNumberStr); + assert.equal(row.hi, largeUnsafeNumberHexStr); + assert.equal(row.sl, largeUnsafeNumberStr); + assert.equal(row.hl, largeUnsafeNumberHexStr); + }, + ); + + // assert.equal(await query(ecdb, "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { + // assert.equal(row.si, largeUnsafeNumberStr); + // assert.equal(row.hi, largeUnsafeNumberHexStr); + // assert.equal(row.sl, largeUnsafeNumberStr); + // assert.equal(row.hl, largeUnsafeNumberHexStr); + // }), 1); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large unsafe number as hexstring')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeUnsafeNumberHexStr); + stmt.bindInteger(2, largeUnsafeNumberHexStr); + stmt.bindInteger(3, largeUnsafeNumberHexStr); + stmt.bindInteger(4, largeUnsafeNumberHexStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.si, largeUnsafeNumberStr); + assert.equal(row.hi, largeUnsafeNumberHexStr); + assert.equal(row.sl, largeUnsafeNumberStr); + assert.equal(row.hl, largeUnsafeNumberHexStr); + }, + ); + + // assert.equal(await query(ecdb, "SELECT Str(I) si, HexStr(I) hi, Str(L) sl, HexStr(L) hl FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { + // assert.equal(row.si, largeUnsafeNumberStr); + // assert.equal(row.hi, largeUnsafeNumberHexStr); + // assert.equal(row.sl, largeUnsafeNumberStr); + // assert.equal(row.hl, largeUnsafeNumberHexStr); + // }), 1); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large unsafe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeUnsafeNumberStr); + stmt.bindString(2, largeUnsafeNumberStr); + stmt.bindString(3, largeUnsafeNumberStr); + stmt.bindString(4, largeUnsafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + // uint64 cannot be bound as string in SQLite. They get converted to reals + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.isNumber(row.d); + assert.isNumber(row.i); + assert.isNumber(row.l); + assert.equal(row.s, largeUnsafeNumberStr); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.isNumber(row.d); + assert.isNumber(row.i); + assert.isNumber(row.l); + assert.equal(row.s, largeUnsafeNumberStr); + }), + 1, + ); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large unsafe number as hexstring')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeUnsafeNumberHexStr); + stmt.bindString(2, largeUnsafeNumberHexStr); + stmt.bindString(3, largeUnsafeNumberHexStr); + stmt.bindString(4, largeUnsafeNumberHexStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeUnsafeNumberHexStr); + assert.equal(row.i, largeUnsafeNumberHexStr); + assert.equal(row.l, largeUnsafeNumberHexStr); + assert.equal(row.s, largeUnsafeNumberHexStr); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + selectSingleRow, + (row: any) => { + assert.equal(row.d, largeUnsafeNumberHexStr); + assert.equal(row.i, largeUnsafeNumberHexStr); + assert.equal(row.l, largeUnsafeNumberHexStr); + assert.equal(row.s, largeUnsafeNumberHexStr); + }, + ), + 1, + ); + + // eslint-disable-next-line @typescript-eslint/no-loss-of-precision + const largeNegUnsafeNumber: number = -123123123123123236; + assert.isFalse(Number.isSafeInteger(largeNegUnsafeNumber)); + const largeNegUnsafeNumberStr: string = "-123123123123123236"; + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative unsafe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeNegUnsafeNumberStr); + stmt.bindInteger(2, largeNegUnsafeNumberStr); + stmt.bindInteger(3, largeNegUnsafeNumberStr); + stmt.bindInteger(4, largeNegUnsafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.i, largeNegUnsafeNumberStr); + assert.equal(row.l, largeNegUnsafeNumberStr); + assert.equal(row.s, largeNegUnsafeNumberStr); + }); + + assert.equal( + await query( + ecdb, + "SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + selectSingleRow, + (row: any) => { + assert.equal(row.i, largeNegUnsafeNumberStr); + assert.equal(row.l, largeNegUnsafeNumberStr); + assert.equal(row.s, largeNegUnsafeNumberStr); + }, + ), + 1, + ); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large negative unsafe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeNegUnsafeNumberStr); + stmt.bindString(2, largeNegUnsafeNumberStr); + stmt.bindString(3, largeNegUnsafeNumberStr); + stmt.bindString(4, largeNegUnsafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.i, largeNegUnsafeNumberStr); + assert.equal(row.l, largeNegUnsafeNumberStr); + assert.equal(row.s, largeNegUnsafeNumberStr); + }); + + assert.equal( + await query( + ecdb, + "SELECT CAST(I AS TEXT) i, CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + selectSingleRow, + (row: any) => { + assert.equal(row.i, largeNegUnsafeNumberStr); + assert.equal(row.l, largeNegUnsafeNumberStr); + assert.equal(row.s, largeNegUnsafeNumberStr); + }, + ), + 1, + ); + + const largeSafeNumber: number = 1231231231231232; + assert.isTrue(Number.isSafeInteger(largeSafeNumber)); + const largeSafeNumberStr: string = largeSafeNumber.toString(); + const largeSafeNumberHexStr: string = "0x45fcc5c2c8500"; + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeSafeNumber); + stmt.bindInteger(2, largeSafeNumber); + stmt.bindInteger(3, largeSafeNumber); + stmt.bindInteger(4, largeSafeNumber); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT D,I, Str(I) si, HexStr(I) hi, L, Str(L) sl, HexStr(L) hl,S FROM Test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.si, largeSafeNumberStr); + assert.equal(row.hi, largeSafeNumberHexStr); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.sl, largeSafeNumberStr); + assert.equal(row.hl, largeSafeNumberHexStr); + assert.equal(row.s, largeSafeNumberStr); + }, + ); + + // await query(ecdb, "SELECT D,I, Str(I) si, HexStr(I) hi, L, Str(L) sl, HexStr(L) hl,S FROM Test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { + // assert.equal(row.d, largeSafeNumber); + // assert.equal(row.i, largeSafeNumber); + // assert.equal(row.si, largeSafeNumberStr); + // assert.equal(row.hi, largeSafeNumberHexStr); + // assert.equal(row.l, largeSafeNumber); + // assert.equal(row.sl, largeSafeNumberStr); + // assert.equal(row.hl, largeSafeNumberHexStr); + // assert.equal(row.s, largeSafeNumberStr); + // }); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeSafeNumberStr); + stmt.bindInteger(2, largeSafeNumberStr); + stmt.bindInteger(3, largeSafeNumberStr); + stmt.bindInteger(4, largeSafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); + }), + 1, + ); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large safe number as hexstring')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeSafeNumberHexStr); + stmt.bindInteger(2, largeSafeNumberHexStr); + stmt.bindInteger(3, largeSafeNumberHexStr); + stmt.bindInteger(4, largeSafeNumberHexStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting + }), + 1, + ); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large safe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeSafeNumberStr); + stmt.bindString(2, largeSafeNumberStr); + stmt.bindString(3, largeSafeNumberStr); + stmt.bindString(4, largeSafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeSafeNumber); + assert.equal(row.i, largeSafeNumber); + assert.equal(row.l, largeSafeNumber); + assert.equal(row.s, largeSafeNumberStr); // even though it was bound as hex str, it gets converted to int64 before persisting + }), + 1, + ); + + // SQLite does not parse hex strs bound as strings. + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large safe number as hexstring')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeSafeNumberHexStr); + stmt.bindString(2, largeSafeNumberHexStr); + stmt.bindString(3, largeSafeNumberHexStr); + stmt.bindString(4, largeSafeNumberHexStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeSafeNumberHexStr); + assert.equal(row.i, largeSafeNumberHexStr); + assert.equal(row.l, largeSafeNumberHexStr); + assert.equal(row.s, largeSafeNumberHexStr); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT CAST(D AS TEXT) d,CAST(I AS TEXT) i,CAST(L AS TEXT) l,S FROM Test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + selectSingleRow, + (row: any) => { + assert.equal(row.d, largeSafeNumberHexStr); + assert.equal(row.i, largeSafeNumberHexStr); + assert.equal(row.l, largeSafeNumberHexStr); + assert.equal(row.s, largeSafeNumberHexStr); + }, + ), + 1, + ); + + const largeNegSafeNumber: number = -1231231231231232; + assert.isTrue(Number.isSafeInteger(largeNegSafeNumber)); + const largeNegSafeNumberStr: string = largeNegSafeNumber.toString(); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative safe number')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeNegSafeNumber); + stmt.bindInteger(2, largeNegSafeNumber); + stmt.bindInteger(3, largeNegSafeNumber); + stmt.bindInteger(4, largeNegSafeNumber); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }); + + assert.equal( + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }), + 1, + ); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindInteger, large negative safe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindInteger(1, largeNegSafeNumberStr); + stmt.bindInteger(2, largeNegSafeNumberStr); + stmt.bindInteger(3, largeNegSafeNumberStr); + stmt.bindInteger(4, largeNegSafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }); + + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }); + + id = ecdb.withPreparedStatement( + "INSERT INTO Test.Foo(D,I,L,S,Description) VALUES(?,?,?,?,'bindString, large negative safe number as string')", + (stmt: ECSqlStatement) => { + stmt.bindString(1, largeNegSafeNumberStr); + stmt.bindString(2, largeNegSafeNumberStr); + stmt.bindString(3, largeNegSafeNumberStr); + stmt.bindString(4, largeNegSafeNumberStr); + const r: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + return r.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }); + + await query(ecdb, "SELECT D,I,L,S FROM Test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), selectSingleRow, (row: any) => { + assert.equal(row.d, largeNegSafeNumber); + assert.equal(row.i, largeNegSafeNumber); + assert.equal(row.l, largeNegSafeNumber); + assert.equal(row.s, largeNegSafeNumberStr); + }); + }, + ); }); it("should bind primitives", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindprimitives.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindprimitives.ecdb", + ` @@ -1299,156 +1612,209 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - - const boolVal = true; - const doubleVal = 3.5; - const dtVal: string = "2018-01-23T12:24:00.000"; - const intVal = 3; - const p2dVal = new Point2d(1, 2); - const p3dVal = new Point3d(1, 2, 3); - const strVal: string = "Hello world"; - - const verify = async (expectedId: Id64String) => { - await ecdb.withPreparedStatement("SELECT Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl s_bl,Struct.Bo s_bo,Struct.D s_d,Struct.Dt s_dt,Struct.I s_i,Struct.P2d s_p2d,Struct.P3d s_p3d,Struct.S s_s FROM test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { - stmt.bindId(1, expectedId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.deepEqual(row.bl, blobVal); - const f64 = new Float64Array(row.bl.buffer); - const r2 = new Range3d(...f64); - assert.deepEqual(r2, testRange); - assert.equal(row.bo, boolVal); - assert.equal(row.d, doubleVal); - assert.equal(row.dt, dtVal); - assert.equal(row.i, intVal); - assert.equal(row.p2d.x, p2dVal.x); - assert.equal(row.p2d.y, p2dVal.y); - assert.equal(row.p3d.x, p3dVal.x); - assert.equal(row.p3d.y, p3dVal.y); - assert.equal(row.p3d.z, p3dVal.z); - assert.equal(row.s, strVal); - - assert.deepEqual(row.s_bl, blobVal); - assert.equal(row.s_bo, boolVal); - assert.equal(row.s_d, doubleVal); - assert.equal(row.s_dt, dtVal); - assert.equal(row.s_i, intVal); - assert.equal(row.s_p2d.x, p2dVal.x); - assert.equal(row.s_p2d.y, p2dVal.y); - assert.equal(row.s_p3d.x, p3dVal.x); - assert.equal(row.s_p3d.y, p3dVal.y); - assert.equal(row.s_p3d.z, p3dVal.z); - assert.equal(row.s_s, strVal); - - assert.equal(await query(ecdb, "SELECT Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl s_bl,Struct.Bo s_bo,Struct.D s_d,Struct.Dt s_dt,Struct.I s_i,Struct.P2d s_p2d,Struct.P3d s_p3d,Struct.S s_s FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([expectedId]), selectSingleRow, (row1: any) => { - assert.deepEqual(row1.bl, blobVal); - const f64a = new Float64Array(row1.bl.buffer); - const r2a = new Range3d(...f64a); - assert.deepEqual(r2a, testRange); - assert.equal(row1.bo, boolVal); - assert.equal(row1.d, doubleVal); - assert.equal(row1.dt, dtVal); - assert.equal(row1.i, intVal); - assert.equal(row1.p2d.x, p2dVal.x); - assert.equal(row1.p2d.y, p2dVal.y); - assert.equal(row1.p3d.x, p3dVal.x); - assert.equal(row1.p3d.y, p3dVal.y); - assert.equal(row1.p3d.z, p3dVal.z); - assert.equal(row1.s, strVal); - - assert.deepEqual(row1.s_bl, blobVal); - assert.equal(row1.s_bo, boolVal); - assert.equal(row1.s_d, doubleVal); - assert.equal(row1.s_dt, dtVal); - assert.equal(row1.s_i, intVal); - assert.equal(row1.s_p2d.x, p2dVal.x); - assert.equal(row1.s_p2d.y, p2dVal.y); - assert.equal(row1.s_p3d.x, p3dVal.x); - assert.equal(row1.s_p3d.y, p3dVal.y); - assert.equal(row1.s_p3d.z, p3dVal.z); - assert.equal(row1.s_s, strVal); - }), 1); - }); - }; - - const ids = new Array(); - ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl,Struct.Bo,Struct.D,Struct.Dt,Struct.I,Struct.P2d,Struct.P3d,Struct.S) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", (stmt: ECSqlStatement) => { - stmt.bindBlob(1, blobVal); - stmt.bindBoolean(2, boolVal); - stmt.bindDouble(3, doubleVal); - stmt.bindDateTime(4, dtVal); - stmt.bindInteger(5, intVal); - stmt.bindPoint2d(6, p2dVal); - stmt.bindPoint3d(7, p3dVal); - stmt.bindString(8, strVal); - stmt.bindBlob(9, blobVal); - stmt.bindBoolean(10, boolVal); - stmt.bindDouble(11, doubleVal); - stmt.bindDateTime(12, dtVal); - stmt.bindInteger(13, intVal); - stmt.bindPoint2d(14, p2dVal); - stmt.bindPoint3d(15, p3dVal); - stmt.bindString(16, strVal); - - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - ids.push(res.id!); - stmt.reset(); - stmt.clearBindings(); - stmt.bindValues([blobVal, boolVal, doubleVal, dtVal, intVal, p2dVal, p3dVal, strVal, blobVal, boolVal, doubleVal, dtVal, intVal, p2dVal, p3dVal, strVal]); - - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - ids.push(res.id!); - }); - - ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl,Struct.Bo,Struct.D,Struct.Dt,Struct.I,Struct.P2d,Struct.P3d,Struct.S) VALUES(:bl,:bo,:d,:dt,:i,:p2d,:p3d,:s,:s_bl,:s_bo,:s_d,:s_dt,:s_i,:s_p2d,:s_p3d,:s_s)", (stmt: ECSqlStatement) => { - stmt.bindBlob("bl", blobVal); - stmt.bindBoolean("bo", boolVal); - stmt.bindDouble("d", doubleVal); - stmt.bindDateTime("dt", dtVal); - stmt.bindInteger("i", intVal); - stmt.bindPoint2d("p2d", p2dVal); - stmt.bindPoint3d("p3d", p3dVal); - stmt.bindString("s", strVal); - - stmt.bindBlob("s_bl", blobVal); - stmt.bindBoolean("s_bo", boolVal); - stmt.bindDouble("s_d", doubleVal); - stmt.bindDateTime("s_dt", dtVal); - stmt.bindInteger("s_i", intVal); - stmt.bindPoint2d("s_p2d", p2dVal); - stmt.bindPoint3d("s_p3d", p3dVal); - stmt.bindString("s_s", strVal); - - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - ids.push(res.id!); - stmt.reset(); - stmt.clearBindings(); - stmt.bindValues({ - bl: blobVal, bo: boolVal, d: doubleVal, dt: dtVal, - i: intVal, p2d: p2dVal, p3d: p3dVal, s: strVal, - s_bl: blobVal, s_bo: boolVal, s_d: doubleVal, s_dt: dtVal, - s_i: intVal, s_p2d: p2dVal, s_p3d: p3dVal, s_s: strVal, - }); - - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - ids.push(res.id!); - }); - - for (const id of ids) { - await verify(id); - } - }); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const boolVal = true; + const doubleVal = 3.5; + const dtVal: string = "2018-01-23T12:24:00.000"; + const intVal = 3; + const p2dVal = new Point2d(1, 2); + const p3dVal = new Point3d(1, 2, 3); + const strVal: string = "Hello world"; + + const verify = async (expectedId: Id64String) => { + await ecdb.withPreparedStatement( + "SELECT Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl s_bl,Struct.Bo s_bo,Struct.D s_d,Struct.Dt s_dt,Struct.I s_i,Struct.P2d s_p2d,Struct.P3d s_p3d,Struct.S s_s FROM test.Foo WHERE ECInstanceId=?", + async (stmt: ECSqlStatement) => { + stmt.bindId(1, expectedId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.deepEqual(row.bl, blobVal); + const f64 = new Float64Array(row.bl.buffer); + const r2 = new Range3d(...f64); + assert.deepEqual(r2, testRange); + assert.equal(row.bo, boolVal); + assert.equal(row.d, doubleVal); + assert.equal(row.dt, dtVal); + assert.equal(row.i, intVal); + assert.equal(row.p2d.x, p2dVal.x); + assert.equal(row.p2d.y, p2dVal.y); + assert.equal(row.p3d.x, p3dVal.x); + assert.equal(row.p3d.y, p3dVal.y); + assert.equal(row.p3d.z, p3dVal.z); + assert.equal(row.s, strVal); + + assert.deepEqual(row.s_bl, blobVal); + assert.equal(row.s_bo, boolVal); + assert.equal(row.s_d, doubleVal); + assert.equal(row.s_dt, dtVal); + assert.equal(row.s_i, intVal); + assert.equal(row.s_p2d.x, p2dVal.x); + assert.equal(row.s_p2d.y, p2dVal.y); + assert.equal(row.s_p3d.x, p3dVal.x); + assert.equal(row.s_p3d.y, p3dVal.y); + assert.equal(row.s_p3d.z, p3dVal.z); + assert.equal(row.s_s, strVal); + + assert.equal( + await query( + ecdb, + "SELECT Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl s_bl,Struct.Bo s_bo,Struct.D s_d,Struct.Dt s_dt,Struct.I s_i,Struct.P2d s_p2d,Struct.P3d s_p3d,Struct.S s_s FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([expectedId]), + selectSingleRow, + (row1: any) => { + assert.deepEqual(row1.bl, blobVal); + const f64a = new Float64Array(row1.bl.buffer); + const r2a = new Range3d(...f64a); + assert.deepEqual(r2a, testRange); + assert.equal(row1.bo, boolVal); + assert.equal(row1.d, doubleVal); + assert.equal(row1.dt, dtVal); + assert.equal(row1.i, intVal); + assert.equal(row1.p2d.x, p2dVal.x); + assert.equal(row1.p2d.y, p2dVal.y); + assert.equal(row1.p3d.x, p3dVal.x); + assert.equal(row1.p3d.y, p3dVal.y); + assert.equal(row1.p3d.z, p3dVal.z); + assert.equal(row1.s, strVal); + + assert.deepEqual(row1.s_bl, blobVal); + assert.equal(row1.s_bo, boolVal); + assert.equal(row1.s_d, doubleVal); + assert.equal(row1.s_dt, dtVal); + assert.equal(row1.s_i, intVal); + assert.equal(row1.s_p2d.x, p2dVal.x); + assert.equal(row1.s_p2d.y, p2dVal.y); + assert.equal(row1.s_p3d.x, p3dVal.x); + assert.equal(row1.s_p3d.y, p3dVal.y); + assert.equal(row1.s_p3d.z, p3dVal.z); + assert.equal(row1.s_s, strVal); + }, + ), + 1, + ); + }, + ); + }; + + const ids = new Array(); + ecdb.withPreparedStatement( + "INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl,Struct.Bo,Struct.D,Struct.Dt,Struct.I,Struct.P2d,Struct.P3d,Struct.S) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", + (stmt: ECSqlStatement) => { + stmt.bindBlob(1, blobVal); + stmt.bindBoolean(2, boolVal); + stmt.bindDouble(3, doubleVal); + stmt.bindDateTime(4, dtVal); + stmt.bindInteger(5, intVal); + stmt.bindPoint2d(6, p2dVal); + stmt.bindPoint3d(7, p3dVal); + stmt.bindString(8, strVal); + stmt.bindBlob(9, blobVal); + stmt.bindBoolean(10, boolVal); + stmt.bindDouble(11, doubleVal); + stmt.bindDateTime(12, dtVal); + stmt.bindInteger(13, intVal); + stmt.bindPoint2d(14, p2dVal); + stmt.bindPoint3d(15, p3dVal); + stmt.bindString(16, strVal); + + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + ids.push(res.id!); + stmt.reset(); + stmt.clearBindings(); + stmt.bindValues([ + blobVal, + boolVal, + doubleVal, + dtVal, + intVal, + p2dVal, + p3dVal, + strVal, + blobVal, + boolVal, + doubleVal, + dtVal, + intVal, + p2dVal, + p3dVal, + strVal, + ]); + + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + ids.push(res.id!); + }, + ); + + ecdb.withPreparedStatement( + "INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S,Struct.Bl,Struct.Bo,Struct.D,Struct.Dt,Struct.I,Struct.P2d,Struct.P3d,Struct.S) VALUES(:bl,:bo,:d,:dt,:i,:p2d,:p3d,:s,:s_bl,:s_bo,:s_d,:s_dt,:s_i,:s_p2d,:s_p3d,:s_s)", + (stmt: ECSqlStatement) => { + stmt.bindBlob("bl", blobVal); + stmt.bindBoolean("bo", boolVal); + stmt.bindDouble("d", doubleVal); + stmt.bindDateTime("dt", dtVal); + stmt.bindInteger("i", intVal); + stmt.bindPoint2d("p2d", p2dVal); + stmt.bindPoint3d("p3d", p3dVal); + stmt.bindString("s", strVal); + + stmt.bindBlob("s_bl", blobVal); + stmt.bindBoolean("s_bo", boolVal); + stmt.bindDouble("s_d", doubleVal); + stmt.bindDateTime("s_dt", dtVal); + stmt.bindInteger("s_i", intVal); + stmt.bindPoint2d("s_p2d", p2dVal); + stmt.bindPoint3d("s_p3d", p3dVal); + stmt.bindString("s_s", strVal); + + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + ids.push(res.id!); + stmt.reset(); + stmt.clearBindings(); + stmt.bindValues({ + bl: blobVal, + bo: boolVal, + d: doubleVal, + dt: dtVal, + i: intVal, + p2d: p2dVal, + p3d: p3dVal, + s: strVal, + s_bl: blobVal, + s_bo: boolVal, + s_d: doubleVal, + s_dt: dtVal, + s_i: intVal, + s_p2d: p2dVal, + s_p3d: p3dVal, + s_s: strVal, + }); + + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + ids.push(res.id!); + }, + ); + + for (const id of ids) { + await verify(id); + } + }, + ); }); it("should bind structs", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindstructs.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindstructs.ecdb", + ` @@ -1464,186 +1830,220 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - - const structVal = { - bl: blobVal, bo: true, d: 3.5, - dt: "2018-01-23T12:24:00.000", - i: 3, p2d: new Point2d(1, 2), p3d: new Point3d(1, 2, 3), s: "Hello World", - }; - - const verify = async (expectedId: Id64String) => { - await ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { - stmt.bindId(1, expectedId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.isTrue(blobEqual(row.struct.bl, structVal.bl)); - assert.equal(row.struct.bo, structVal.bo); - assert.equal(row.struct.d, structVal.d); - assert.equal(row.struct.dt, structVal.dt); - assert.equal(row.struct.i, structVal.i); - assert.equal(row.struct.p2d.x, structVal.p2d.x); - assert.equal(row.struct.p2d.y, structVal.p2d.y); - assert.equal(row.struct.p3d.x, structVal.p3d.x); - assert.equal(row.struct.p3d.y, structVal.p3d.y); - assert.equal(row.struct.p3d.z, structVal.p3d.z); - assert.equal(row.struct.s, structVal.s); - - assert.equal(await query(ecdb, "SELECT Struct FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([expectedId]), selectSingleRow, (row1: any) => { - assert.isTrue(blobEqual(row1.struct.bl, structVal.bl)); - assert.equal(row1.struct.bo, structVal.bo); - assert.equal(row1.struct.d, structVal.d); - assert.equal(row1.struct.dt, structVal.dt); - assert.equal(row1.struct.i, structVal.i); - assert.equal(row1.struct.p2d.x, structVal.p2d.x); - assert.equal(row1.struct.p2d.y, structVal.p2d.y); - assert.equal(row1.struct.p3d.x, structVal.p3d.x); - assert.equal(row1.struct.p3d.y, structVal.p3d.y); - assert.equal(row1.struct.p3d.z, structVal.p3d.z); - assert.equal(row1.struct.s, structVal.s); - }), 1); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const structVal = { + bl: blobVal, + bo: true, + d: 3.5, + dt: "2018-01-23T12:24:00.000", + i: 3, + p2d: new Point2d(1, 2), + p3d: new Point3d(1, 2, 3), + s: "Hello World", + }; + + const verify = async (expectedId: Id64String) => { + await ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { + stmt.bindId(1, expectedId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.isTrue(blobEqual(row.struct.bl, structVal.bl)); + assert.equal(row.struct.bo, structVal.bo); + assert.equal(row.struct.d, structVal.d); + assert.equal(row.struct.dt, structVal.dt); + assert.equal(row.struct.i, structVal.i); + assert.equal(row.struct.p2d.x, structVal.p2d.x); + assert.equal(row.struct.p2d.y, structVal.p2d.y); + assert.equal(row.struct.p3d.x, structVal.p3d.x); + assert.equal(row.struct.p3d.y, structVal.p3d.y); + assert.equal(row.struct.p3d.z, structVal.p3d.z); + assert.equal(row.struct.s, structVal.s); + + assert.equal( + await query(ecdb, "SELECT Struct FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([expectedId]), selectSingleRow, (row1: any) => { + assert.isTrue(blobEqual(row1.struct.bl, structVal.bl)); + assert.equal(row1.struct.bo, structVal.bo); + assert.equal(row1.struct.d, structVal.d); + assert.equal(row1.struct.dt, structVal.dt); + assert.equal(row1.struct.i, structVal.i); + assert.equal(row1.struct.p2d.x, structVal.p2d.x); + assert.equal(row1.struct.p2d.y, structVal.p2d.y); + assert.equal(row1.struct.p3d.x, structVal.p3d.x); + assert.equal(row1.struct.p3d.y, structVal.p3d.y); + assert.equal(row1.struct.p3d.z, structVal.p3d.z); + assert.equal(row1.struct.s, structVal.s); + }), + 1, + ); + }); + }; + await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", async (stmt: ECSqlStatement) => { + stmt.bindStruct(1, structVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); }); - }; - await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", async (stmt: ECSqlStatement) => { - stmt.bindStruct(1, structVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); - - await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", async (stmt: ECSqlStatement) => { - stmt.bindValues([structVal]); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); - await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(:str)", async (stmt: ECSqlStatement) => { - stmt.bindStruct("str", structVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); + await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", async (stmt: ECSqlStatement) => { + stmt.bindValues([structVal]); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }); - await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(:str)", async (stmt: ECSqlStatement) => { - stmt.bindValues({ str: structVal }); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); + await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(:str)", async (stmt: ECSqlStatement) => { + stmt.bindStruct("str", structVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }); - }); + await ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(:str)", async (stmt: ECSqlStatement) => { + stmt.bindValues({ str: structVal }); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }); + }, + ); }); it("should bind arrays", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindarrays.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindarrays.ecdb", + ` - - - - - - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - - const intArray = [1, 2, 3]; - const dtArray = ["2018-01-23T00:00:00.000", "2018-01-23T16:39:00.000"]; - const addressArray = [{ city: "London", zip: 10000 }, { city: "Manchester", zip: 20000 }, { city: "Edinburgh", zip: 30000 }]; - - const verify = async (expectedId: Id64String) => { - await ecdb.withPreparedStatement("SELECT I_Array, Dt_Array, Addresses FROM test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { - stmt.bindId(1, expectedId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - - // don't know why assert.equal doesn't work on arrays directly - assert.equal(row.i_Array.length, intArray.length); - for (let i = 0; i < intArray.length; i++) { - assert.equal(row.i_Array[i], intArray[i]); - } - - assert.equal(row.dt_Array.length, dtArray.length); - for (let i = 0; i < dtArray.length; i++) { - assert.equal(row.dt_Array[i], dtArray[i]); - } - - assert.equal(row.addresses.length, addressArray.length); - for (let i = 0; i < addressArray.length; i++) { - assert.equal(row.addresses[i].city, addressArray[i].city); - assert.equal(row.addresses[i].zip, addressArray[i].zip); - } - }); - - assert.equal(await query(ecdb, "SELECT I_Array, Dt_Array, Addresses FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([expectedId]), selectSingleRow, (row: any) => { - // don't know why assert.equal doesn't work on arrays directly - assert.equal(row.i_Array.length, intArray.length); - for (let i = 0; i < intArray.length; i++) { - assert.equal(row.i_Array[i], intArray[i]); - } - - assert.equal(row.dt_Array.length, dtArray.length); - for (let i = 0; i < dtArray.length; i++) { - assert.equal(row.dt_Array[i], dtArray[i]); - } + + + + + + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const intArray = [1, 2, 3]; + const dtArray = ["2018-01-23T00:00:00.000", "2018-01-23T16:39:00.000"]; + const addressArray = [{ city: "London", zip: 10000 }, { city: "Manchester", zip: 20000 }, { city: "Edinburgh", zip: 30000 }]; + + const verify = async (expectedId: Id64String) => { + await ecdb.withPreparedStatement("SELECT I_Array, Dt_Array, Addresses FROM test.Foo WHERE ECInstanceId=?", async (stmt: ECSqlStatement) => { + stmt.bindId(1, expectedId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + + // don't know why assert.equal doesn't work on arrays directly + assert.equal(row.i_Array.length, intArray.length); + for (let i = 0; i < intArray.length; i++) { + assert.equal(row.i_Array[i], intArray[i]); + } - assert.equal(row.addresses.length, addressArray.length); - for (let i = 0; i < addressArray.length; i++) { - assert.equal(row.addresses[i].city, addressArray[i].city); - assert.equal(row.addresses[i].zip, addressArray[i].zip); - } - }), 1); - }; + assert.equal(row.dt_Array.length, dtArray.length); + for (let i = 0; i < dtArray.length; i++) { + assert.equal(row.dt_Array[i], dtArray[i]); + } - await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(?,?,?)", async (stmt: ECSqlStatement) => { - stmt.bindArray(1, intArray); - stmt.bindArray(2, dtArray); - stmt.bindArray(3, addressArray); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); + assert.equal(row.addresses.length, addressArray.length); + for (let i = 0; i < addressArray.length; i++) { + assert.equal(row.addresses[i].city, addressArray[i].city); + assert.equal(row.addresses[i].zip, addressArray[i].zip); + } + }); - await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(?,?,?)", async (stmt: ECSqlStatement) => { - stmt.bindValues([intArray, dtArray, addressArray]); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); + assert.equal( + await query( + ecdb, + "SELECT I_Array, Dt_Array, Addresses FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([expectedId]), + selectSingleRow, + (row: any) => { + // don't know why assert.equal doesn't work on arrays directly + assert.equal(row.i_Array.length, intArray.length); + for (let i = 0; i < intArray.length; i++) { + assert.equal(row.i_Array[i], intArray[i]); + } + + assert.equal(row.dt_Array.length, dtArray.length); + for (let i = 0; i < dtArray.length; i++) { + assert.equal(row.dt_Array[i], dtArray[i]); + } + + assert.equal(row.addresses.length, addressArray.length); + for (let i = 0; i < addressArray.length; i++) { + assert.equal(row.addresses[i].city, addressArray[i].city); + assert.equal(row.addresses[i].zip, addressArray[i].zip); + } + }, + ), + 1, + ); + }; + + await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(?,?,?)", async (stmt: ECSqlStatement) => { + stmt.bindArray(1, intArray); + stmt.bindArray(2, dtArray); + stmt.bindArray(3, addressArray); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }); - await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(:iarray,:dtarray,:addresses)", async (stmt: ECSqlStatement) => { - stmt.bindArray("iarray", intArray); - stmt.bindArray("dtarray", dtArray); - stmt.bindArray("addresses", addressArray); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); + await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(?,?,?)", async (stmt: ECSqlStatement) => { + stmt.bindValues([intArray, dtArray, addressArray]); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }); - await ecdb.withPreparedStatement("INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(:iarray,:dtarray,:addresses)", async (stmt: ECSqlStatement) => { - stmt.bindValues({ iarray: intArray, dtarray: dtArray, addresses: addressArray }); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - await verify(res.id!); - }); - }); + await ecdb.withPreparedStatement( + "INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(:iarray,:dtarray,:addresses)", + async (stmt: ECSqlStatement) => { + stmt.bindArray("iarray", intArray); + stmt.bindArray("dtarray", dtArray); + stmt.bindArray("addresses", addressArray); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }, + ); + + await ecdb.withPreparedStatement( + "INSERT INTO test.Foo(I_Array,Dt_Array,Addresses) VALUES(:iarray,:dtarray,:addresses)", + async (stmt: ECSqlStatement) => { + stmt.bindValues({ iarray: intArray, dtarray: dtArray, addresses: addressArray }); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + await verify(res.id!); + }, + ); + }, + ); }); it("should bind navigation", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindnavigation.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindnavigation.ecdb", + ` @@ -1659,93 +2059,103 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const parentId: Id64String = ecdb.withStatement("INSERT INTO test.Parent(Code) VALUES('Parent 1')", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }); - assert.isTrue(ecdb.isOpen); + const childIds = new Array(); + ecdb.withStatement("INSERT INTO test.Child(Name,Parent) VALUES(?,?)", (stmt: ECSqlStatement) => { + stmt.bindString(1, "Child 1"); + stmt.bindNavigation(2, { id: parentId, relClassName: "Test.ParentHasChildren" }); + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); - const parentId: Id64String = ecdb.withStatement("INSERT INTO test.Parent(Code) VALUES('Parent 1')", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); + stmt.reset(); + stmt.clearBindings(); - const childIds = new Array(); - ecdb.withStatement("INSERT INTO test.Child(Name,Parent) VALUES(?,?)", (stmt: ECSqlStatement) => { - stmt.bindString(1, "Child 1"); - stmt.bindNavigation(2, { id: parentId, relClassName: "Test.ParentHasChildren" }); - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues(["Child 2", { id: parentId, relClassName: "Test.ParentHasChildren" }]); - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - }); + stmt.bindValues(["Child 2", { id: parentId, relClassName: "Test.ParentHasChildren" }]); + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); + }); - ecdb.withStatement("INSERT INTO test.Child(Name,Parent) VALUES(:name,:parent)", (stmt: ECSqlStatement) => { - stmt.bindString("name", "Child 3"); - stmt.bindNavigation("parent", { id: parentId, relClassName: "Test.ParentHasChildren" }); - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues({ name: "Child 4", parent: { id: parentId, relClassName: "Test.ParentHasChildren" } }); - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - }); + ecdb.withStatement("INSERT INTO test.Child(Name,Parent) VALUES(:name,:parent)", (stmt: ECSqlStatement) => { + stmt.bindString("name", "Child 3"); + stmt.bindNavigation("parent", { id: parentId, relClassName: "Test.ParentHasChildren" }); + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); - ecdb.withPreparedStatement("SELECT Name,Parent FROM test.Child ORDER BY Name", (stmt: ECSqlStatement) => { - let rowCount: number = 0; - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row = stmt.getRow(); - assert.equal(row.name, `Child ${rowCount}`); - const parent: NavigationValue = row.parent as NavigationValue; - assert.equal(parent.id, parentId); - assert.equal(parent.relClassName, "Test.ParentHasChildren"); - } - assert.equal(rowCount, 4); - }); + stmt.reset(); + stmt.clearBindings(); - let rowCount2: number = 0; - assert.equal(await query(ecdb, "SELECT Name,Parent FROM test.Child ORDER BY Name", QueryBinder.from([]), undefined, (row: any) => { - rowCount2++; - assert.equal(row.name, `Child ${rowCount2}`); - const parent: NavigationValue = row.parent as NavigationValue; - assert.equal(parent.id, parentId); - assert.equal(parent.relClassName, "Test.ParentHasChildren"); - }), 4); - }); + stmt.bindValues({ name: "Child 4", parent: { id: parentId, relClassName: "Test.ParentHasChildren" } }); + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); + }); + + ecdb.withPreparedStatement("SELECT Name,Parent FROM test.Child ORDER BY Name", (stmt: ECSqlStatement) => { + let rowCount: number = 0; + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row = stmt.getRow(); + assert.equal(row.name, `Child ${rowCount}`); + const parent: NavigationValue = row.parent as NavigationValue; + assert.equal(parent.id, parentId); + assert.equal(parent.relClassName, "Test.ParentHasChildren"); + } + assert.equal(rowCount, 4); + }); + + let rowCount2: number = 0; + assert.equal( + await query(ecdb, "SELECT Name,Parent FROM test.Child ORDER BY Name", QueryBinder.from([]), undefined, (row: any) => { + rowCount2++; + assert.equal(row.name, `Child ${rowCount2}`); + const parent: NavigationValue = row.parent as NavigationValue; + assert.equal(parent.id, parentId); + assert.equal(parent.relClassName, "Test.ParentHasChildren"); + }), + 4, + ); + }, + ); }); it("should bind Range3d for parameter in spatial sql function", async () => { - const iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlStatement", "BindRange3d.bim"), { rootSubject: { name: "BindRange3d" } }); + const iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlStatement", "BindRange3d.bim"), { + rootSubject: { name: "BindRange3d" }, + }); try { - iModel.withPreparedStatement("SELECT e.ECInstanceId FROM bis.Element e, bis.SpatialIndex rt WHERE rt.ECInstanceId MATCH DGN_spatial_overlap_aabb(?) AND e.ECInstanceId=rt.ECInstanceId", + iModel.withPreparedStatement( + "SELECT e.ECInstanceId FROM bis.Element e, bis.SpatialIndex rt WHERE rt.ECInstanceId MATCH DGN_spatial_overlap_aabb(?) AND e.ECInstanceId=rt.ECInstanceId", (stmt: ECSqlStatement) => { stmt.bindRange3d(1, new Range3d(0.0, 0.0, 0.0, 1000.0, 1000.0, 1000.0)); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); + }, + ); - iModel.withPreparedStatement("SELECT e.ECInstanceId FROM bis.Element e, bis.SpatialIndex rt WHERE rt.ECInstanceId MATCH DGN_spatial_overlap_aabb(?) AND e.ECInstanceId=rt.ECInstanceId", + iModel.withPreparedStatement( + "SELECT e.ECInstanceId FROM bis.Element e, bis.SpatialIndex rt WHERE rt.ECInstanceId MATCH DGN_spatial_overlap_aabb(?) AND e.ECInstanceId=rt.ECInstanceId", (stmt: ECSqlStatement) => { stmt.bindValues([new Range3d(0.0, 0.0, 0.0, 1000.0, 1000.0, 1000.0)]); assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); - + }, + ); } finally { iModel.saveChanges(); iModel.close(); @@ -1753,37 +2163,42 @@ describe("ECSqlStatement", () => { }); it("should bind Range3d", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindrange3d.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "bindrange3d.ecdb", + ` - `), async (ecdb) => { - - assert.isTrue(ecdb.isOpen); - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo([Range3d]) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindRange3d(1, testRange); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); - ecdb.saveChanges(); - ecdb.withPreparedStatement("SELECT [Range3d] FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const rangeBlob: Uint8Array = stmt.getValue(0).getBlob(); - const rangeFloatArray = new Float64Array(rangeBlob.buffer); - assert.equal(rangeFloatArray.length, 6); - const actualRange = new Range3d(...rangeFloatArray); - assert.isTrue(actualRange.isAlmostEqual(testRange)); - }); - }); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo([Range3d]) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindRange3d(1, testRange); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }); + ecdb.saveChanges(); + ecdb.withPreparedStatement("SELECT [Range3d] FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const rangeBlob: Uint8Array = stmt.getValue(0).getBlob(); + const rangeFloatArray = new Float64Array(rangeBlob.buffer); + assert.equal(rangeFloatArray.length, 6); + const actualRange = new Range3d(...rangeFloatArray); + assert.isTrue(actualRange.isAlmostEqual(testRange)); + }); + }, + ); }); it("should bind IdSets", async () => { - await using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { + using(ECDbTestHelper.createECDb(outDir, "bindids.ecdb"), async (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); const idNumbers: number[] = [4444, 4545, 1234, 6758, 1312]; @@ -1798,54 +2213,63 @@ describe("ECSqlStatement", () => { assert.equal(r.id!, expectedId); ecdb.saveChanges(); - ecdb.withStatement(`SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=${expectedId}`, (confstmt: ECSqlStatement) => { - assert.equal(confstmt.step(), DbResult.BE_SQLITE_ROW); - const row = confstmt.getRow(); - assert.equal(row.id, expectedId); - assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); - assert.equal(row.name, `${Id64.getLocalId(expectedId).toString()}.txt`); - }); + ecdb.withStatement( + `SELECT ECInstanceId, ECClassId, Name FROM ecdbf.ExternalFileInfo WHERE ECInstanceId=${expectedId}`, + (confstmt: ECSqlStatement) => { + assert.equal(confstmt.step(), DbResult.BE_SQLITE_ROW); + const row = confstmt.getRow(); + assert.equal(row.id, expectedId); + assert.equal(row.className, "ECDbFileInfo.ExternalFileInfo"); + assert.equal(row.name, `${Id64.getLocalId(expectedId).toString()}.txt`); + }, + ); stmt.reset(); stmt.clearBindings(); }); }); - ecdb.withPreparedStatement("SELECT ECInstanceId, ECClassId, Name from ecdbf.ExternalFileInfo WHERE InVirtualSet(?, ECInstanceId)", (stmt: ECSqlStatement) => { - let idSet: Id64String[] = []; - stmt.bindIdSet(1, idSet); - let result = stmt.step(); - assert.equal(result, DbResult.BE_SQLITE_DONE); - stmt.reset(); - stmt.clearBindings(); - - idSet = [Id64.fromLocalAndBriefcaseIds(idNumbers[2], 0)]; - stmt.bindIdSet(1, idSet); - result = stmt.step(); - assert.equal(result, DbResult.BE_SQLITE_ROW); - let row = stmt.getRow(); - assert.equal(row.name, `${idNumbers[2]}.txt`); - stmt.reset(); - stmt.clearBindings(); - - idSet.push(idNumbers[0].toString()); - stmt.bindIdSet(1, idSet); - result = stmt.step(); - assert.equal(result, DbResult.BE_SQLITE_ROW); - row = stmt.getRow(); - assert.equal(row.name, `${idNumbers[2]}.txt`); - result = stmt.step(); - assert.equal(result, DbResult.BE_SQLITE_ROW); - row = stmt.getRow(); - assert.equal(row.name, `${idNumbers[0]}.txt`); - }); + ecdb.withPreparedStatement( + "SELECT ECInstanceId, ECClassId, Name from ecdbf.ExternalFileInfo WHERE InVirtualSet(?, ECInstanceId)", + (stmt: ECSqlStatement) => { + let idSet: Id64String[] = []; + stmt.bindIdSet(1, idSet); + let result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_DONE); + stmt.reset(); + stmt.clearBindings(); + + idSet = [Id64.fromLocalAndBriefcaseIds(idNumbers[2], 0)]; + stmt.bindIdSet(1, idSet); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + let row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[2]}.txt`); + stmt.reset(); + stmt.clearBindings(); + + idSet.push(idNumbers[0].toString()); + stmt.bindIdSet(1, idSet); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[2]}.txt`); + result = stmt.step(); + assert.equal(result, DbResult.BE_SQLITE_ROW); + row = stmt.getRow(); + assert.equal(row.name, `${idNumbers[0]}.txt`); + }, + ); }); }); /* This test doesn't do anything specific with the binder life time but just runs a few scenarios with and without statement cache to test that stuff works fine */ it("check ECSqlBinder life time", async () => { - await using(ECDbTestHelper.createECDb(outDir, "ecsqlbinderlifetime.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "ecsqlbinderlifetime.ecdb", + ` @@ -1856,79 +2280,96 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - - assert.isTrue(ecdb.isOpen); - - let id1: Id64String, id2: Id64String; - - // *** test without statement cache - using(ecdb.prepareStatement("INSERT INTO test.Person(Name,Age,Location) VALUES(?,?,?)"), (stmt: ECSqlStatement) => { - stmt.bindString(1, "Mary Miller"); - stmt.bindInteger(2, 30); - stmt.bindStruct(3, { Street: "2000 Main Street", City: "New York", Zip: 12311 }); - - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - id1 = res.id!; - assert.isTrue(Id64.isValidId64(id1)); - }); - - // *** test withstatement cache - ecdb.withPreparedStatement("INSERT INTO test.Person(Name,Age,Location) VALUES(?,?,?)", (stmt: ECSqlStatement) => { - stmt.bindString(1, "Mary Miller"); - stmt.bindInteger(2, 30); - stmt.bindStruct(3, { Street: "2000 Main Street", City: "New York", Zip: 12311 }); - - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - id2 = res.id!; - assert.isTrue(Id64.isValidId64(id2)); - }); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + let id1: Id64String, id2: Id64String; + + // *** test without statement cache + using(ecdb.prepareStatement("INSERT INTO test.Person(Name,Age,Location) VALUES(?,?,?)"), (stmt: ECSqlStatement) => { + stmt.bindString(1, "Mary Miller"); + stmt.bindInteger(2, 30); + stmt.bindStruct(3, { Street: "2000 Main Street", City: "New York", Zip: 12311 }); + + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + id1 = res.id!; + assert.isTrue(Id64.isValidId64(id1)); + }); - using(ecdb.prepareStatement("SELECT ECInstanceId,ECClassId,Name,Age,Location FROM test.Person ORDER BY ECInstanceId"), (stmt: ECSqlStatement) => { - let rowCount = 0; - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row = stmt.getRow(); - if (rowCount === 1) - assert.equal(row.id, id1); - else - assert.equal(row.id, id2); - - assert.equal(row.className, "Test.Person"); - assert.equal(row.name, "Mary Miller"); - assert.equal(row.age, 30); - assert.equal(row.location.street, "2000 Main Street"); - assert.equal(row.location.city, "New York"); - assert.equal(row.location.zip, 12311); - } - assert.equal(rowCount, 2); - }); + // *** test withstatement cache + ecdb.withPreparedStatement("INSERT INTO test.Person(Name,Age,Location) VALUES(?,?,?)", (stmt: ECSqlStatement) => { + stmt.bindString(1, "Mary Miller"); + stmt.bindInteger(2, 30); + stmt.bindStruct(3, { Street: "2000 Main Street", City: "New York", Zip: 12311 }); + + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + id2 = res.id!; + assert.isTrue(Id64.isValidId64(id2)); + }); - let rowCount2: number = 0; - assert.equal(await query(ecdb, "SELECT ECInstanceId,ECClassId,Name,Age,Location FROM test.Person ORDER BY ECInstanceId", QueryBinder.from([]), undefined, (row: any) => { - rowCount2++; - if (rowCount2 === 1) - assert.equal(row.id, id1); - else - assert.equal(row.id, id2); - - assert.equal(row.className, "Test.Person"); - assert.equal(row.name, "Mary Miller"); - assert.equal(row.age, 30); - assert.equal(row.location.street, "2000 Main Street"); - assert.equal(row.location.city, "New York"); - assert.equal(row.location.zip, 12311); - }), 2); - }); + using( + ecdb.prepareStatement("SELECT ECInstanceId,ECClassId,Name,Age,Location FROM test.Person ORDER BY ECInstanceId"), + (stmt: ECSqlStatement) => { + let rowCount = 0; + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row = stmt.getRow(); + if (rowCount === 1) + assert.equal(row.id, id1); + else + assert.equal(row.id, id2); + + assert.equal(row.className, "Test.Person"); + assert.equal(row.name, "Mary Miller"); + assert.equal(row.age, 30); + assert.equal(row.location.street, "2000 Main Street"); + assert.equal(row.location.city, "New York"); + assert.equal(row.location.zip, 12311); + } + assert.equal(rowCount, 2); + }, + ); + + let rowCount2: number = 0; + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId,ECClassId,Name,Age,Location FROM test.Person ORDER BY ECInstanceId", + QueryBinder.from([]), + undefined, + (row: any) => { + rowCount2++; + if (rowCount2 === 1) + assert.equal(row.id, id1); + else + assert.equal(row.id, id2); + + assert.equal(row.className, "Test.Person"); + assert.equal(row.name, "Mary Miller"); + assert.equal(row.age, 30); + assert.equal(row.location.street, "2000 Main Street"); + assert.equal(row.location.city, "New York"); + assert.equal(row.location.zip, 12311); + }, + ), + 2, + ); + }, + ); }); it("getRow() with primitives values", async () => { - await using(ECDbTestHelper.createECDb(outDir, "getprimitives.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "getprimitives.ecdb", + ` @@ -1941,277 +2382,417 @@ describe("ECSqlStatement", () => { - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const boolVal: boolean = true; - const doubleVal: number = 3.5; - const dtVal: string = "2018-01-23T12:24:00.000"; - const intVal: number = 3; - const p2dVal = new Point2d(1, 2); - const p3dVal = new Point3d(1, 2, 3); - const strVal: string = "Hello world"; - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S) VALUES(?,?,?,?,?,?,?,?)", (stmt: ECSqlStatement) => { - stmt.bindBlob(1, blobVal); - stmt.bindBoolean(2, boolVal); - stmt.bindDouble(3, doubleVal); - stmt.bindDateTime(4, dtVal); - stmt.bindInteger(5, intVal); - stmt.bindPoint2d(6, p2dVal); - stmt.bindPoint3d(7, p3dVal); - stmt.bindString(8, strVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - return res.id!; - }); - - ecdb.withPreparedStatement("SELECT ECInstanceId, ECClassId, Bl,Bo,D,Dt,I,P2d,P3d,S FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.id, id); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, blobVal); - assert.equal(row.bo, boolVal); - assert.equal(row.d, doubleVal); - assert.equal(row.dt, dtVal); - assert.equal(row.i, intVal); - assert.equal(row.p2d.x, p2dVal.x); - assert.equal(row.p2d.y, p2dVal.y); - assert.equal(row.p3d.x, p3dVal.x); - assert.equal(row.p3d.y, p3dVal.y); - assert.equal(row.p3d.z, p3dVal.z); - assert.equal(row.s, strVal); - }); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { abbreviateBlobs: true, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, id); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, abbreviatedBlobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { abbreviateBlobs: false, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, id); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, blobVal); - }), 1); - - // assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl,Bo,D,Dt,I,P2d,P3d,S FROM test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { - // assert.equal(row.id, id); - // assert.equal(row.className, "Test.Foo"); - // assert.deepEqual(row.bl, blobVal); - // assert.equal(row.bo, boolVal); - // assert.equal(row.d, doubleVal); - // assert.equal(row.dt, dtVal); - // assert.equal(row.i, intVal); - // assert.equal(row.p2d.x, p2dVal.x); - // assert.equal(row.p2d.y, p2dVal.y); - // assert.equal(row.p3d.x, p3dVal.x); - // assert.equal(row.p3d.y, p3dVal.y); - // assert.equal(row.p3d.z, p3dVal.z); - // assert.equal(row.s, strVal); - // }), 1); - - ecdb.withPreparedStatement("SELECT Bl AS Blobby, I+10, Lower(S), Upper(S) CapitalS FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.deepEqual(row.blobby, blobVal); - assert.equal(row["[I] + 10"], intVal + 10); - assert.equal(row["lower([S])"], strVal.toLowerCase()); - assert.equal(row.capitalS, strVal.toUpperCase()); - }); - - // assert.equal(await query(ecdb, "SELECT Bl AS Blobby, I+10, Lower(S), Upper(S) CapitalS FROM test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { - // assert.deepEqual(row.blobby, blobVal); - // assert.equal(row["[I] + 10"], intVal + 10); - // assert.equal(row["lower([S])"], strVal.toLowerCase()); - // assert.equal(row.capitalS, strVal.toUpperCase()); - // }), 1); - - const testSchemaId: Id64String = ecdb.withPreparedStatement("SELECT ECInstanceId FROM meta.ECSchemaDef WHERE Name='Test'", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - return Id64.fromJSON(row.id); - }); - - const fooClassId: Id64String = ecdb.withPreparedStatement("SELECT ECInstanceId FROM meta.ECClassDef WHERE Name='Foo'", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - return Id64.fromJSON(row.id); - }); - - ecdb.withPreparedStatement("SELECT s.ECInstanceId, c.ECInstanceId, c.Name, s.Name FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON c.Schema.Id=s.ECInstanceId WHERE s.Name='Test' AND c.Name='Foo'", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.id, testSchemaId); - assert.equal(row.id_1, fooClassId); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const boolVal: boolean = true; + const doubleVal: number = 3.5; + const dtVal: string = "2018-01-23T12:24:00.000"; + const intVal: number = 3; + const p2dVal = new Point2d(1, 2); + const p3dVal = new Point3d(1, 2, 3); + const strVal: string = "Hello world"; + + const id: Id64String = ecdb.withPreparedStatement( + "INSERT INTO test.Foo(Bl,Bo,D,Dt,I,P2d,P3d,S) VALUES(?,?,?,?,?,?,?,?)", + (stmt: ECSqlStatement) => { + stmt.bindBlob(1, blobVal); + stmt.bindBoolean(2, boolVal); + stmt.bindDouble(3, doubleVal); + stmt.bindDateTime(4, dtVal); + stmt.bindInteger(5, intVal); + stmt.bindPoint2d(6, p2dVal); + stmt.bindPoint3d(7, p3dVal); + stmt.bindString(8, strVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + return res.id!; + }, + ); + + ecdb.withPreparedStatement( + "SELECT ECInstanceId, ECClassId, Bl,Bo,D,Dt,I,P2d,P3d,S FROM test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.id, id); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, blobVal); + assert.equal(row.bo, boolVal); + assert.equal(row.d, doubleVal); + assert.equal(row.dt, dtVal); + assert.equal(row.i, intVal); + assert.equal(row.p2d.x, p2dVal.x); + assert.equal(row.p2d.y, p2dVal.y); + assert.equal(row.p3d.x, p3dVal.x); + assert.equal(row.p3d.y, p3dVal.y); + assert.equal(row.p3d.z, p3dVal.z); + assert.equal(row.s, strVal); + }, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { + abbreviateBlobs: true, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, id); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, abbreviatedBlobVal); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), { + abbreviateBlobs: false, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, id); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, blobVal); + }), + 1, + ); + + // assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl,Bo,D,Dt,I,P2d,P3d,S FROM test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { + // assert.equal(row.id, id); + // assert.equal(row.className, "Test.Foo"); + // assert.deepEqual(row.bl, blobVal); + // assert.equal(row.bo, boolVal); + // assert.equal(row.d, doubleVal); + // assert.equal(row.dt, dtVal); + // assert.equal(row.i, intVal); + // assert.equal(row.p2d.x, p2dVal.x); + // assert.equal(row.p2d.y, p2dVal.y); + // assert.equal(row.p3d.x, p3dVal.x); + // assert.equal(row.p3d.y, p3dVal.y); + // assert.equal(row.p3d.z, p3dVal.z); + // assert.equal(row.s, strVal); + // }), 1); + + ecdb.withPreparedStatement( + "SELECT Bl AS Blobby, I+10, Lower(S), Upper(S) CapitalS FROM test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.deepEqual(row.blobby, blobVal); + assert.equal(row["[I] + 10"], intVal + 10); + assert.equal(row["lower([S])"], strVal.toLowerCase()); + assert.equal(row.capitalS, strVal.toUpperCase()); + }, + ); + + // assert.equal(await query(ecdb, "SELECT Bl AS Blobby, I+10, Lower(S), Upper(S) CapitalS FROM test.Foo WHERE ECInstanceId=?", [id], 1, (row: any) => { + // assert.deepEqual(row.blobby, blobVal); + // assert.equal(row["[I] + 10"], intVal + 10); + // assert.equal(row["lower([S])"], strVal.toLowerCase()); + // assert.equal(row.capitalS, strVal.toUpperCase()); + // }), 1); + + const testSchemaId: Id64String = ecdb.withPreparedStatement( + "SELECT ECInstanceId FROM meta.ECSchemaDef WHERE Name='Test'", + (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + return Id64.fromJSON(row.id); + }, + ); + + const fooClassId: Id64String = ecdb.withPreparedStatement( + "SELECT ECInstanceId FROM meta.ECClassDef WHERE Name='Foo'", + (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + return Id64.fromJSON(row.id); + }, + ); + + ecdb.withPreparedStatement( + "SELECT s.ECInstanceId, c.ECInstanceId, c.Name, s.Name FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON c.Schema.Id=s.ECInstanceId WHERE s.Name='Test' AND c.Name='Foo'", + (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.id, testSchemaId); + assert.equal(row.id_1, fooClassId); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT s.ECInstanceId, c.ECInstanceId, c.Name, s.Name FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON c.Schema.Id=s.ECInstanceId WHERE s.Name='Test' AND c.Name='Foo'", + QueryBinder.from([]), + selectSingleRow, + (row: any) => { + assert.equal(row.id, testSchemaId); + assert.equal(row.id_1, fooClassId); + }, + ), + 1, + ); + + ecdb.withPreparedStatement("SELECT count(*) cnt FROM meta.ECSchemaDef", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.isDefined(row.cnt); + assert.equal(typeof (row.cnt), "number"); + assert.equal(row.cnt, 6); + }); - assert.equal(await query(ecdb, "SELECT s.ECInstanceId, c.ECInstanceId, c.Name, s.Name FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON c.Schema.Id=s.ECInstanceId WHERE s.Name='Test' AND c.Name='Foo'", QueryBinder.from([]), selectSingleRow, (row: any) => { - assert.equal(row.id, testSchemaId); - assert.equal(row.id_1, fooClassId); - }), 1); - - ecdb.withPreparedStatement("SELECT count(*) cnt FROM meta.ECSchemaDef", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.isDefined(row.cnt); - assert.equal(typeof (row.cnt), "number"); - assert.equal(row.cnt, 6); - }); + assert.equal( + await query(ecdb, "SELECT count(*) cnt FROM meta.ECSchemaDef", QueryBinder.from([]), selectSingleRow, (row: any) => { + assert.isDefined(row.cnt); + assert.equal(typeof (row.cnt), "number"); + assert.equal(row.cnt, 6); + }), + 1, + ); - assert.equal(await query(ecdb, "SELECT count(*) cnt FROM meta.ECSchemaDef", QueryBinder.from([]), selectSingleRow, (row: any) => { - assert.isDefined(row.cnt); - assert.equal(typeof (row.cnt), "number"); - assert.equal(row.cnt, 6); - }), 1); - - ecdb.withPreparedStatement("SELECT 1 FROM meta.ECSchemaDef LIMIT 1", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(typeof (row["1"]), "number"); - assert.equal(row["1"], 1); - }); + ecdb.withPreparedStatement("SELECT 1 FROM meta.ECSchemaDef LIMIT 1", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(typeof (row["1"]), "number"); + assert.equal(row["1"], 1); + }); - assert.equal(await query(ecdb, "SELECT 1 FROM meta.ECSchemaDef LIMIT 1", QueryBinder.from([]), undefined, (row: any) => { - assert.equal(typeof (row["1"]), "number"); - assert.equal(row["1"], 1); - }), 1); + assert.equal( + await query(ecdb, "SELECT 1 FROM meta.ECSchemaDef LIMIT 1", QueryBinder.from([]), undefined, (row: any) => { + assert.equal(typeof (row["1"]), "number"); + assert.equal(row["1"], 1); + }), + 1, + ); - ecdb.withPreparedStatement("SELECT NULL FROM meta.ECSchemaDef LIMIT 1", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(Object.entries(row).length, 0); - }); + ecdb.withPreparedStatement("SELECT NULL FROM meta.ECSchemaDef LIMIT 1", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(Object.entries(row).length, 0); + }); - assert.equal(await query(ecdb, "SELECT NULL FROM meta.ECSchemaDef LIMIT 1", QueryBinder.from([]), undefined, (row: any) => { - assert.equal(Object.entries(row).length, 0); - }), 1); - }); + assert.equal( + await query(ecdb, "SELECT NULL FROM meta.ECSchemaDef LIMIT 1", QueryBinder.from([]), undefined, (row: any) => { + assert.equal(Object.entries(row).length, 0); + }), + 1, + ); + }, + ); }); it("getRow() with abbreviated blobs", async () => { - await using(ECDbTestHelper.createECDb(outDir, "getblobs.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "getblobs.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const singleBlobVal = blobVal.slice(0, 1); - const abbreviatedSingleBlobVal = `{"bytes":${singleBlobVal.byteLength}}`; - const emptyBlobVal = new Uint8Array(); - - const fullId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindBlob(1, blobVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - return res.id!; - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const singleBlobVal = blobVal.slice(0, 1); + const abbreviatedSingleBlobVal = `{"bytes":${singleBlobVal.byteLength}}`; + const emptyBlobVal = new Uint8Array(); + + const fullId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindBlob(1, blobVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + return res.id!; + }); - const singleId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindBlob(1, singleBlobVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - return res.id!; - }); + const singleId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindBlob(1, singleBlobVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + return res.id!; + }); - const emptyId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindBlob(1, emptyBlobVal); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - return res.id!; - }); + const emptyId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindBlob(1, emptyBlobVal); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + return res.id!; + }); - const nullId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindNull(1); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - return res.id!; - }); + const nullId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindNull(1); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + return res.id!; + }); - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([fullId]), { abbreviateBlobs: true, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, fullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, abbreviatedBlobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([fullId]), { abbreviateBlobs: false, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, fullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, blobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([fullId]), selectSingleRow, (row: any) => { - assert.equal(row.id, fullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, blobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { abbreviateBlobs: true, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, singleId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, abbreviatedSingleBlobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { abbreviateBlobs: false, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, singleId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, singleBlobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { ...selectSingleRow }, (row: any) => { - assert.equal(row.id, singleId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, singleBlobVal); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([emptyId]), { abbreviateBlobs: true, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, emptyId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, "{\"bytes\":0}"); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([emptyId]), { abbreviateBlobs: false, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, emptyId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl.length, 0); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([emptyId]), selectSingleRow, (row: any) => { - assert.equal(row.id, emptyId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl.length, 0); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([nullId]), { abbreviateBlobs: true, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, nullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, undefined); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([nullId]), { abbreviateBlobs: false, ...selectSingleRow }, (row: any) => { - assert.equal(row.id, nullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, undefined); - }), 1); - - assert.equal(await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([nullId]), selectSingleRow, (row: any) => { - assert.equal(row.id, nullId); - assert.equal(row.className, "Test.Foo"); - assert.deepEqual(row.bl, undefined); - }), 1); - }); + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([fullId]), { + abbreviateBlobs: true, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, fullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, abbreviatedBlobVal); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([fullId]), { + abbreviateBlobs: false, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, fullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, blobVal); + }), + 1, + ); + + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([fullId]), + selectSingleRow, + (row: any) => { + assert.equal(row.id, fullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, blobVal); + }, + ), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { + abbreviateBlobs: true, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, singleId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, abbreviatedSingleBlobVal); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { + abbreviateBlobs: false, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, singleId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, singleBlobVal); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([singleId]), { + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, singleId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, singleBlobVal); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([emptyId]), { + abbreviateBlobs: true, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, emptyId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, '{"bytes":0}'); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([emptyId]), { + abbreviateBlobs: false, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, emptyId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl.length, 0); + }), + 1, + ); + + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([emptyId]), + selectSingleRow, + (row: any) => { + assert.equal(row.id, emptyId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl.length, 0); + }, + ), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([nullId]), { + abbreviateBlobs: true, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, nullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, undefined); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([nullId]), { + abbreviateBlobs: false, + ...selectSingleRow, + }, (row: any) => { + assert.equal(row.id, nullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, undefined); + }), + 1, + ); + + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId, ECClassId, Bl FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([nullId]), + selectSingleRow, + (row: any) => { + assert.equal(row.id, nullId); + assert.equal(row.className, "Test.Foo"); + assert.deepEqual(row.bl, undefined); + }, + ), + 1, + ); + }, + ); }); it("getRow() with navigation properties and relationships", async () => { - await using(ECDbTestHelper.createECDb(outDir, "getnavandrels.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "getnavandrels.ecdb", + ` @@ -2227,129 +2808,173 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - let rowCount: number; - const parentId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Parent(Code) VALUES('Parent 1')", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); - - const childIds = new Array(); - ecdb.withPreparedStatement("INSERT INTO test.Child(Name,Parent) VALUES(?,?)", (stmt: ECSqlStatement) => { - stmt.bindString(1, "Child 1"); - stmt.bindNavigation(2, { id: parentId, relClassName: "Test.ParentHasChildren" }); - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValues(["Child 2", { id: parentId, relClassName: "Test.ParentHasChildren" }]); - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - childIds.push(res.id!); - }); - - ecdb.withPreparedStatement("SELECT Name,Parent FROM test.Child ORDER BY Name", (stmt: ECSqlStatement) => { - rowCount = 0; - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row = stmt.getRow(); - assert.equal(row.name, `Child ${rowCount}`); - assert.equal(row.parent.id, parentId); - assert.equal(row.parent.relClassName, "Test.ParentHasChildren"); - } - assert.equal(rowCount, 2); - }); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + let rowCount: number; + const parentId: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Parent(Code) VALUES('Parent 1')", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }); - rowCount = 0; - assert.equal(await query(ecdb, "SELECT Name,Parent FROM test.Child ORDER BY Name", QueryBinder.from([]), undefined, (row: any) => { - rowCount++; - assert.equal(row.name, `Child ${rowCount}`); - assert.equal(row.parent.id, parentId); - assert.equal(row.parent.relClassName, "Test.ParentHasChildren"); - }), 2); + const childIds = new Array(); + ecdb.withPreparedStatement("INSERT INTO test.Child(Name,Parent) VALUES(?,?)", (stmt: ECSqlStatement) => { + stmt.bindString(1, "Child 1"); + stmt.bindNavigation(2, { id: parentId, relClassName: "Test.ParentHasChildren" }); + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); - ecdb.withPreparedStatement("SELECT Name,Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM test.Child ORDER BY Name", (stmt: ECSqlStatement) => { - rowCount = 0; - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row = stmt.getRow(); - assert.equal(row.name, `Child ${rowCount}`); - assert.equal(row["parent.id"], parentId); - assert.equal(row["parent.relClassName"], "Test.ParentHasChildren"); - assert.equal(row.myParentId, parentId); - assert.isTrue(Id64.isValidId64(row.myParentRelClassId)); - } - assert.equal(rowCount, 2); - }); + stmt.reset(); + stmt.clearBindings(); - rowCount = 0; - assert.equal(await query(ecdb, "SELECT Name,Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM test.Child ORDER BY Name", QueryBinder.from([]), undefined, (row: any) => { - rowCount++; - assert.equal(row.name, `Child ${rowCount}`); - assert.equal(row["parent.id"], parentId); - assert.equal(row["parent.relClassName"], "Test.ParentHasChildren"); - assert.equal(row.myParentId, parentId); - assert.isFalse(Id64.isValidId64(row.myParentRelClassId)); - }), 2); - - const childId: Id64String = childIds[0]; - ecdb.withPreparedStatement("SELECT ECInstanceId,ECClassId,SourceECInstanceId,SourceECClassId,TargetECInstanceId,TargetECClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, childId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.id, childId); - assert.equal(row.className, "Test.ParentHasChildren"); - assert.equal(row.sourceId, parentId); - assert.equal(row.sourceClassName, "Test.Parent"); - assert.equal(row.targetId, childId); - assert.equal(row.targetClassName, "Test.Child"); - }); + stmt.bindValues(["Child 2", { id: parentId, relClassName: "Test.ParentHasChildren" }]); + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + childIds.push(res.id!); + }); - assert.equal(await query(ecdb, "SELECT ECInstanceId,ECClassId,SourceECInstanceId,SourceECClassId,TargetECInstanceId,TargetECClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", QueryBinder.from([childId]), undefined, (row: any) => { - assert.equal(row.id, childId); - assert.equal(row.className, "Test.ParentHasChildren"); - assert.equal(row.sourceId, parentId); - assert.equal(row.sourceClassName, "Test.Parent"); - assert.equal(row.targetId, childId); - assert.equal(row.targetClassName, "Test.Child"); - }), 1); - - ecdb.withPreparedStatement("SELECT ECInstanceId as MyId,ECClassId as MyClassId,SourceECInstanceId As MySourceId,SourceECClassId As MySourceClassId,TargetECInstanceId As MyTargetId,TargetECClassId As MyTargetClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, childId); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row = stmt.getRow(); - assert.equal(row.myId, childId); - assert.isTrue(Id64.isValidId64(row.myClassId)); - assert.equal(row.mySourceId, parentId); - assert.isTrue(Id64.isValidId64(row.mySourceClassId)); - assert.equal(row.myTargetId, childId); - assert.isTrue(Id64.isValidId64(row.myTargetClassId)); - }); + ecdb.withPreparedStatement("SELECT Name,Parent FROM test.Child ORDER BY Name", (stmt: ECSqlStatement) => { + rowCount = 0; + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row = stmt.getRow(); + assert.equal(row.name, `Child ${rowCount}`); + assert.equal(row.parent.id, parentId); + assert.equal(row.parent.relClassName, "Test.ParentHasChildren"); + } + assert.equal(rowCount, 2); + }); - assert.equal(await query(ecdb, "SELECT ECInstanceId as MyId,ECClassId as MyClassId,SourceECInstanceId As MySourceId,SourceECClassId As MySourceClassId,TargetECInstanceId As MyTargetId,TargetECClassId As MyTargetClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", QueryBinder.from([childId]), undefined, (row: any) => { - rowCount++; - assert.equal(row.myId, childId); - assert.isFalse(Id64.isValidId64(row.myClassId)); - assert.equal(row.mySourceId, parentId); - assert.isFalse(Id64.isValidId64(row.mySourceClassId)); - assert.equal(row.myTargetId, childId); - assert.isFalse(Id64.isValidId64(row.myTargetClassId)); - }), 1); + rowCount = 0; + assert.equal( + await query(ecdb, "SELECT Name,Parent FROM test.Child ORDER BY Name", QueryBinder.from([]), undefined, (row: any) => { + rowCount++; + assert.equal(row.name, `Child ${rowCount}`); + assert.equal(row.parent.id, parentId); + assert.equal(row.parent.relClassName, "Test.ParentHasChildren"); + }), + 2, + ); + + ecdb.withPreparedStatement( + "SELECT Name,Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM test.Child ORDER BY Name", + (stmt: ECSqlStatement) => { + rowCount = 0; + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row = stmt.getRow(); + assert.equal(row.name, `Child ${rowCount}`); + assert.equal(row["parent.id"], parentId); + assert.equal(row["parent.relClassName"], "Test.ParentHasChildren"); + assert.equal(row.myParentId, parentId); + assert.isTrue(Id64.isValidId64(row.myParentRelClassId)); + } + assert.equal(rowCount, 2); + }, + ); - }); + rowCount = 0; + assert.equal( + await query( + ecdb, + "SELECT Name,Parent.Id,Parent.RelECClassId, Parent.Id myParentId, Parent.RelECClassId myParentRelClassId FROM test.Child ORDER BY Name", + QueryBinder.from([]), + undefined, + (row: any) => { + rowCount++; + assert.equal(row.name, `Child ${rowCount}`); + assert.equal(row["parent.id"], parentId); + assert.equal(row["parent.relClassName"], "Test.ParentHasChildren"); + assert.equal(row.myParentId, parentId); + assert.isFalse(Id64.isValidId64(row.myParentRelClassId)); + }, + ), + 2, + ); + + const childId: Id64String = childIds[0]; + ecdb.withPreparedStatement( + "SELECT ECInstanceId,ECClassId,SourceECInstanceId,SourceECClassId,TargetECInstanceId,TargetECClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, childId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.id, childId); + assert.equal(row.className, "Test.ParentHasChildren"); + assert.equal(row.sourceId, parentId); + assert.equal(row.sourceClassName, "Test.Parent"); + assert.equal(row.targetId, childId); + assert.equal(row.targetClassName, "Test.Child"); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId,ECClassId,SourceECInstanceId,SourceECClassId,TargetECInstanceId,TargetECClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", + QueryBinder.from([childId]), + undefined, + (row: any) => { + assert.equal(row.id, childId); + assert.equal(row.className, "Test.ParentHasChildren"); + assert.equal(row.sourceId, parentId); + assert.equal(row.sourceClassName, "Test.Parent"); + assert.equal(row.targetId, childId); + assert.equal(row.targetClassName, "Test.Child"); + }, + ), + 1, + ); + + ecdb.withPreparedStatement( + "SELECT ECInstanceId as MyId,ECClassId as MyClassId,SourceECInstanceId As MySourceId,SourceECClassId As MySourceClassId,TargetECInstanceId As MyTargetId,TargetECClassId As MyTargetClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, childId); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row = stmt.getRow(); + assert.equal(row.myId, childId); + assert.isTrue(Id64.isValidId64(row.myClassId)); + assert.equal(row.mySourceId, parentId); + assert.isTrue(Id64.isValidId64(row.mySourceClassId)); + assert.equal(row.myTargetId, childId); + assert.isTrue(Id64.isValidId64(row.myTargetClassId)); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT ECInstanceId as MyId,ECClassId as MyClassId,SourceECInstanceId As MySourceId,SourceECClassId As MySourceClassId,TargetECInstanceId As MyTargetId,TargetECClassId As MyTargetClassId FROM test.ParentHasChildren WHERE TargetECInstanceId=?", + QueryBinder.from([childId]), + undefined, + (row: any) => { + rowCount++; + assert.equal(row.myId, childId); + assert.isFalse(Id64.isValidId64(row.myClassId)); + assert.equal(row.mySourceId, parentId); + assert.isFalse(Id64.isValidId64(row.mySourceClassId)); + assert.equal(row.myTargetId, childId); + assert.isFalse(Id64.isValidId64(row.myTargetClassId)); + }, + ), + 1, + ); + }, + ); }); it("getRow() with structs", async () => { - await using(ECDbTestHelper.createECDb(outDir, "getstructs.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "getstructs.ecdb", + ` @@ -2365,105 +2990,123 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - - const boolVal: boolean = true; - const doubleVal: number = 3.5; - const dtVal: string = "2018-01-23T12:24:00.000"; - const intVal: number = 3; - const p2dVal: XAndY = { x: 1, y: 2 }; - const p3dVal: XYAndZ = { x: 1, y: 2, z: 3 }; - const stringVal: string = "Hello World"; - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", (stmt: ECSqlStatement) => { - stmt.bindStruct(1, { bl: blobVal, bo: boolVal, d: doubleVal, dt: dtVal, i: intVal, p2d: p2dVal, p3d: p3dVal, s: stringVal }); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); - - const expectedStruct = { bl: blobVal, bo: boolVal, d: doubleVal, dt: dtVal, i: intVal, p2d: p2dVal, p3d: p3dVal, s: stringVal }; - ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.deepEqual(row.struct.bl, expectedStruct.bl); - assert.equal(row.struct.bo, expectedStruct.bo); - assert.equal(row.struct.d, expectedStruct.d); - assert.equal(row.struct.dt, expectedStruct.dt); - assert.equal(row.struct.i, expectedStruct.i); - assert.equal(row.struct.p2d.x, expectedStruct.p2d.x); - assert.equal(row.struct.p2d.y, expectedStruct.p2d.y); - assert.equal(row.struct.p3d.x, expectedStruct.p3d.x); - assert.equal(row.struct.p3d.y, expectedStruct.p3d.y); - assert.equal(row.struct.p3d.z, expectedStruct.p3d.z); - assert.equal(row.struct.s, expectedStruct.s); - }); + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const boolVal: boolean = true; + const doubleVal: number = 3.5; + const dtVal: string = "2018-01-23T12:24:00.000"; + const intVal: number = 3; + const p2dVal: XAndY = { x: 1, y: 2 }; + const p3dVal: XYAndZ = { x: 1, y: 2, z: 3 }; + const stringVal: string = "Hello World"; + + const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Struct) VALUES(?)", (stmt: ECSqlStatement) => { + stmt.bindStruct(1, { bl: blobVal, bo: boolVal, d: doubleVal, dt: dtVal, i: intVal, p2d: p2dVal, p3d: p3dVal, s: stringVal }); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }); - assert.equal(await query(ecdb, "SELECT Struct FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), undefined, (row: any) => { - assert.deepEqual(row.struct.bl, expectedStruct.bl); - assert.equal(row.struct.bo, expectedStruct.bo); - assert.equal(row.struct.d, expectedStruct.d); - assert.equal(row.struct.dt, expectedStruct.dt); - assert.equal(row.struct.i, expectedStruct.i); - assert.equal(row.struct.p2d.x, expectedStruct.p2d.x); - assert.equal(row.struct.p2d.y, expectedStruct.p2d.y); - assert.equal(row.struct.p3d.x, expectedStruct.p3d.x); - assert.equal(row.struct.p3d.y, expectedStruct.p3d.y); - assert.equal(row.struct.p3d.z, expectedStruct.p3d.z); - assert.equal(row.struct.s, expectedStruct.s); - }), 1); - - ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const actualStruct: any = stmt.getValue(0).getStruct(); - assert.deepEqual(actualStruct.bl, expectedStruct.bl); - assert.equal(actualStruct.bo, expectedStruct.bo); - assert.equal(actualStruct.d, expectedStruct.d); - assert.equal(actualStruct.dt, expectedStruct.dt); - assert.equal(actualStruct.i, expectedStruct.i); - assert.equal(actualStruct.p2d.x, expectedStruct.p2d.x); - assert.equal(actualStruct.p2d.y, expectedStruct.p2d.y); - assert.equal(actualStruct.p3d.x, expectedStruct.p3d.x); - assert.equal(actualStruct.p3d.y, expectedStruct.p3d.y); - assert.equal(actualStruct.p3d.z, expectedStruct.p3d.z); - assert.equal(actualStruct.s, expectedStruct.s); - }); + const expectedStruct = { bl: blobVal, bo: boolVal, d: doubleVal, dt: dtVal, i: intVal, p2d: p2dVal, p3d: p3dVal, s: stringVal }; + ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.deepEqual(row.struct.bl, expectedStruct.bl); + assert.equal(row.struct.bo, expectedStruct.bo); + assert.equal(row.struct.d, expectedStruct.d); + assert.equal(row.struct.dt, expectedStruct.dt); + assert.equal(row.struct.i, expectedStruct.i); + assert.equal(row.struct.p2d.x, expectedStruct.p2d.x); + assert.equal(row.struct.p2d.y, expectedStruct.p2d.y); + assert.equal(row.struct.p3d.x, expectedStruct.p3d.x); + assert.equal(row.struct.p3d.y, expectedStruct.p3d.y); + assert.equal(row.struct.p3d.z, expectedStruct.p3d.z); + assert.equal(row.struct.s, expectedStruct.s); + }); - ecdb.withPreparedStatement("SELECT Struct.Bl, Struct.Bo, Struct.D, Struct.Dt, Struct.I, Struct.P2d, Struct.P3d, Struct.S FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.deepEqual(row["struct.Bl"], expectedStruct.bl); - assert.equal(row["struct.Bo"], expectedStruct.bo); - assert.equal(row["struct.D"], expectedStruct.d); - assert.equal(row["struct.Dt"], expectedStruct.dt); - assert.equal(row["struct.I"], expectedStruct.i); - assert.equal(row["struct.P2d"].x, expectedStruct.p2d.x); - assert.equal(row["struct.P2d"].y, expectedStruct.p2d.y); - assert.equal(row["struct.P3d"].x, expectedStruct.p3d.x); - assert.equal(row["struct.P3d"].y, expectedStruct.p3d.y); - assert.equal(row["struct.P3d"].z, expectedStruct.p3d.z); - assert.equal(row["struct.S"], expectedStruct.s); - }); + assert.equal( + await query(ecdb, "SELECT Struct FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), undefined, (row: any) => { + assert.deepEqual(row.struct.bl, expectedStruct.bl); + assert.equal(row.struct.bo, expectedStruct.bo); + assert.equal(row.struct.d, expectedStruct.d); + assert.equal(row.struct.dt, expectedStruct.dt); + assert.equal(row.struct.i, expectedStruct.i); + assert.equal(row.struct.p2d.x, expectedStruct.p2d.x); + assert.equal(row.struct.p2d.y, expectedStruct.p2d.y); + assert.equal(row.struct.p3d.x, expectedStruct.p3d.x); + assert.equal(row.struct.p3d.y, expectedStruct.p3d.y); + assert.equal(row.struct.p3d.z, expectedStruct.p3d.z); + assert.equal(row.struct.s, expectedStruct.s); + }), + 1, + ); + + ecdb.withPreparedStatement("SELECT Struct FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const actualStruct: any = stmt.getValue(0).getStruct(); + assert.deepEqual(actualStruct.bl, expectedStruct.bl); + assert.equal(actualStruct.bo, expectedStruct.bo); + assert.equal(actualStruct.d, expectedStruct.d); + assert.equal(actualStruct.dt, expectedStruct.dt); + assert.equal(actualStruct.i, expectedStruct.i); + assert.equal(actualStruct.p2d.x, expectedStruct.p2d.x); + assert.equal(actualStruct.p2d.y, expectedStruct.p2d.y); + assert.equal(actualStruct.p3d.x, expectedStruct.p3d.x); + assert.equal(actualStruct.p3d.y, expectedStruct.p3d.y); + assert.equal(actualStruct.p3d.z, expectedStruct.p3d.z); + assert.equal(actualStruct.s, expectedStruct.s); + }); - assert.equal(await query(ecdb, "SELECT Struct.Bl, Struct.Bo, Struct.D, Struct.Dt, Struct.I, Struct.P2d, Struct.P3d, Struct.S FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), undefined, (row: any) => { - assert.deepEqual(row["struct.Bl"], expectedStruct.bl); - assert.equal(row["struct.Bo"], expectedStruct.bo); - assert.equal(row["struct.D"], expectedStruct.d); - assert.equal(row["struct.Dt"], expectedStruct.dt); - assert.equal(row["struct.I"], expectedStruct.i); - assert.equal(row["struct.P2d"].x, expectedStruct.p2d.x); - assert.equal(row["struct.P2d"].y, expectedStruct.p2d.y); - assert.equal(row["struct.P3d"].x, expectedStruct.p3d.x); - assert.equal(row["struct.P3d"].y, expectedStruct.p3d.y); - assert.equal(row["struct.P3d"].z, expectedStruct.p3d.z); - assert.equal(row["struct.S"], expectedStruct.s); - }), 1); - }); + ecdb.withPreparedStatement( + "SELECT Struct.Bl, Struct.Bo, Struct.D, Struct.Dt, Struct.I, Struct.P2d, Struct.P3d, Struct.S FROM test.Foo WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.deepEqual(row["struct.Bl"], expectedStruct.bl); + assert.equal(row["struct.Bo"], expectedStruct.bo); + assert.equal(row["struct.D"], expectedStruct.d); + assert.equal(row["struct.Dt"], expectedStruct.dt); + assert.equal(row["struct.I"], expectedStruct.i); + assert.equal(row["struct.P2d"].x, expectedStruct.p2d.x); + assert.equal(row["struct.P2d"].y, expectedStruct.p2d.y); + assert.equal(row["struct.P3d"].x, expectedStruct.p3d.x); + assert.equal(row["struct.P3d"].y, expectedStruct.p3d.y); + assert.equal(row["struct.P3d"].z, expectedStruct.p3d.z); + assert.equal(row["struct.S"], expectedStruct.s); + }, + ); + + assert.equal( + await query( + ecdb, + "SELECT Struct.Bl, Struct.Bo, Struct.D, Struct.Dt, Struct.I, Struct.P2d, Struct.P3d, Struct.S FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + undefined, + (row: any) => { + assert.deepEqual(row["struct.Bl"], expectedStruct.bl); + assert.equal(row["struct.Bo"], expectedStruct.bo); + assert.equal(row["struct.D"], expectedStruct.d); + assert.equal(row["struct.Dt"], expectedStruct.dt); + assert.equal(row["struct.I"], expectedStruct.i); + assert.equal(row["struct.P2d"].x, expectedStruct.p2d.x); + assert.equal(row["struct.P2d"].y, expectedStruct.p2d.y); + assert.equal(row["struct.P3d"].x, expectedStruct.p3d.x); + assert.equal(row["struct.P3d"].y, expectedStruct.p3d.y); + assert.equal(row["struct.P3d"].z, expectedStruct.p3d.z); + assert.equal(row["struct.S"], expectedStruct.s); + }, + ), + 1, + ); + }, + ); }); it("check HexStr() sql function", async () => { @@ -2475,8 +3118,11 @@ describe("ECSqlStatement", () => { slm.append().error().category("ECDb").message(/Failed to prepare function expression/gm); slm.append().error().category("ECDb").message(/Step failed for ECSQL/gm); - await using(ECDbTestHelper.createECDb(outDir, "hexstrfunction.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "hexstrfunction.ecdb", + ` @@ -2489,86 +3135,113 @@ describe("ECSqlStatement", () => { - `), async (ecdb) => { - assert.isTrue(ecdb.isOpen); - - const expectedRow = { - bl: blobVal, bo: true, d: 3.5, dt: "2018-01-23T12:24:00.000", - i: 3, l: 12312312312312, p2d: { x: 1, y: 2 }, p3d: { x: 1, y: 2, z: 3 }, s: "Hello World", - }; - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(Bl,Bo,D,Dt,I,L,P2d,P3d,S) VALUES(:bl,:bo,:d,:dt,:i,:l,:p2d,:p3d,:s)", (stmt: ECSqlStatement) => { - stmt.bindValues({ - bl: blobVal, bo: expectedRow.bo, d: expectedRow.d, - dt: expectedRow.dt, i: expectedRow.i, l: expectedRow.l, p2d: expectedRow.p2d, p3d: expectedRow.p3d, s: expectedRow.s, + `, + ), + async (ecdb) => { + assert.isTrue(ecdb.isOpen); + + const expectedRow = { + bl: blobVal, + bo: true, + d: 3.5, + dt: "2018-01-23T12:24:00.000", + i: 3, + l: 12312312312312, + p2d: { x: 1, y: 2 }, + p3d: { x: 1, y: 2, z: 3 }, + s: "Hello World", + }; + + const id: Id64String = ecdb.withPreparedStatement( + "INSERT INTO test.Foo(Bl,Bo,D,Dt,I,L,P2d,P3d,S) VALUES(:bl,:bo,:d,:dt,:i,:l,:p2d,:p3d,:s)", + (stmt: ECSqlStatement) => { + stmt.bindValues({ + bl: blobVal, + bo: expectedRow.bo, + d: expectedRow.d, + dt: expectedRow.dt, + i: expectedRow.i, + l: expectedRow.l, + p2d: expectedRow.p2d, + p3d: expectedRow.p3d, + s: expectedRow.s, + }); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }, + ); + + ecdb.saveChanges(); + ecdb.withPreparedStatement("SELECT I, HexStr(I) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.equal(row.i, expectedRow.i); + assert.equal(row.hex, "0x3"); }); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); - ecdb.saveChanges(); - ecdb.withPreparedStatement("SELECT I, HexStr(I) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.equal(row.i, expectedRow.i); - assert.equal(row.hex, "0x3"); - }); - - ecdb.withPreparedStatement("SELECT L, HexStr(L) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.equal(row.l, expectedRow.l); - assert.equal(row.hex, "0xb32af0071f8"); - }); - - ecdb.withPreparedStatement("SELECT Bl, HexStr(Bl) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); - }); - - ecdb.withPreparedStatement("SELECT Bo, HexStr(Bo) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.equal(row.bo, expectedRow.bo); - assert.equal(row.hex, "0x1"); - }); + ecdb.withPreparedStatement("SELECT L, HexStr(L) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.equal(row.l, expectedRow.l); + assert.equal(row.hex, "0xb32af0071f8"); + }); - ecdb.withPreparedStatement("SELECT D, HexStr(D) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); - }); + ecdb.withPreparedStatement("SELECT Bl, HexStr(Bl) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); + }); - ecdb.withPreparedStatement("SELECT Dt, HexStr(Dt) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); - }); + ecdb.withPreparedStatement("SELECT Bo, HexStr(Bo) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.equal(row.bo, expectedRow.bo); + assert.equal(row.hex, "0x1"); + }); - // SQL functions cannot take points. So here preparation already fails - assert.throw(() => ecdb.withPreparedStatement("SELECT P2d, HexStr(P2d) hex FROM test.Foo WHERE ECInstanceId=?", () => { - assert.fail(); - })); + ecdb.withPreparedStatement("SELECT D, HexStr(D) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); + }); - // SQL functions cannot take points. So here preparation already fails - assert.throw(() => ecdb.withPreparedStatement("SELECT P3d, HexStr(P3d) hex FROM test.Foo WHERE ECInstanceId=?", () => { - assert.fail(); - })); + ecdb.withPreparedStatement("SELECT Dt, HexStr(Dt) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); + }); - ecdb.withPreparedStatement("SELECT S, HexStr(S) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); - }); - }); + // SQL functions cannot take points. So here preparation already fails + assert.throw(() => + ecdb.withPreparedStatement("SELECT P2d, HexStr(P2d) hex FROM test.Foo WHERE ECInstanceId=?", () => { + assert.fail(); + }) + ); + + // SQL functions cannot take points. So here preparation already fails + assert.throw(() => + ecdb.withPreparedStatement("SELECT P3d, HexStr(P3d) hex FROM test.Foo WHERE ECInstanceId=?", () => { + assert.fail(); + }) + ); + + ecdb.withPreparedStatement("SELECT S, HexStr(S) hex FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ERROR); + }); + }, + ); assert.isTrue(slm.finishAndDispose()); }); it("check ec enums", async () => { - await using(ECDbTestHelper.createECDb(outDir, "ecenums.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "ecenums.ecdb", + ` @@ -2583,96 +3256,114 @@ describe("ECSqlStatement", () => { - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.Foo(MyStat,MyStats,MyDomain,MyDomains) VALUES(test.Status.[On],?,test.Domain.Org,?)", (stmt: ECSqlStatement) => { - stmt.bindValue(1, [1, 2]); - stmt.bindValue(2, ["Org", "Com"]); - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); - - ecdb.withPreparedStatement("SELECT MyStat,MyStats, MyDomain,MyDomains FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - const row: any = stmt.getRow(); - assert.equal(row.myStat, 1); - assert.deepEqual(row.myStats, [1, 2]); - assert.equal(row.myDomain, "Org"); - assert.deepEqual(row.myDomains, ["Org", "Com"]); - - const myStatVal: ECSqlValue = stmt.getValue(0); - assert.isFalse(myStatVal.isNull); - assert.isTrue(myStatVal.columnInfo.isEnum()); - assert.equal(myStatVal.getInteger(), 1); - assert.deepEqual(myStatVal.getEnum(), [{ schema: "Test", name: "Status", key: "On", value: 1 }]); - - const myStatsVal: ECSqlValue = stmt.getValue(1); - assert.isFalse(myStatsVal.isNull); - assert.isTrue(myStatsVal.columnInfo.isEnum()); - assert.deepEqual(myStatsVal.getArray(), [1, 2]); - const actualStatsEnums: ECEnumValue[][] = []; - for (const arrayElement of myStatsVal.getArrayIterator()) { - actualStatsEnums.push(arrayElement.getEnum()!); - } - assert.equal(actualStatsEnums.length, 2); - assert.deepEqual(actualStatsEnums[0], [{ schema: "Test", name: "Status", key: "On", value: 1 }]); - assert.deepEqual(actualStatsEnums[1], [{ schema: "Test", name: "Status", key: "Off", value: 2 }]); - - const myDomainVal: ECSqlValue = stmt.getValue(2); - assert.isFalse(myDomainVal.isNull); - assert.isTrue(myDomainVal.columnInfo.isEnum()); - assert.equal(myDomainVal.getString(), "Org"); - assert.deepEqual(myDomainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Org", value: "Org" }]); - - const myDomainsVal: ECSqlValue = stmt.getValue(3); - assert.isFalse(myDomainsVal.isNull); - assert.isTrue(myDomainsVal.columnInfo.isEnum()); - assert.deepEqual(myDomainsVal.getArray(), ["Org", "Com"]); - const actualDomainsEnums: ECEnumValue[][] = []; - for (const arrayElement of myDomainsVal.getArrayIterator()) { - actualDomainsEnums.push(arrayElement.getEnum()!); - } - assert.equal(actualDomainsEnums.length, 2); - assert.deepEqual(actualDomainsEnums[0], [{ schema: "Test", name: "Domain", key: "Org", value: "Org" }]); - assert.deepEqual(actualDomainsEnums[1], [{ schema: "Test", name: "Domain", key: "Com", value: "Com" }]); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const id: Id64String = ecdb.withPreparedStatement( + "INSERT INTO test.Foo(MyStat,MyStats,MyDomain,MyDomains) VALUES(test.Status.[On],?,test.Domain.Org,?)", + (stmt: ECSqlStatement) => { + stmt.bindValue(1, [1, 2]); + stmt.bindValue(2, ["Org", "Com"]); + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }, + ); + + ecdb.withPreparedStatement("SELECT MyStat,MyStats, MyDomain,MyDomains FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + const row: any = stmt.getRow(); + assert.equal(row.myStat, 1); + assert.deepEqual(row.myStats, [1, 2]); + assert.equal(row.myDomain, "Org"); + assert.deepEqual(row.myDomains, ["Org", "Com"]); + + const myStatVal: ECSqlValue = stmt.getValue(0); + assert.isFalse(myStatVal.isNull); + assert.isTrue(myStatVal.columnInfo.isEnum()); + assert.equal(myStatVal.getInteger(), 1); + assert.deepEqual(myStatVal.getEnum(), [{ schema: "Test", name: "Status", key: "On", value: 1 }]); + + const myStatsVal: ECSqlValue = stmt.getValue(1); + assert.isFalse(myStatsVal.isNull); + assert.isTrue(myStatsVal.columnInfo.isEnum()); + assert.deepEqual(myStatsVal.getArray(), [1, 2]); + const actualStatsEnums: ECEnumValue[][] = []; + for (const arrayElement of myStatsVal.getArrayIterator()) { + actualStatsEnums.push(arrayElement.getEnum()!); + } + assert.equal(actualStatsEnums.length, 2); + assert.deepEqual(actualStatsEnums[0], [{ schema: "Test", name: "Status", key: "On", value: 1 }]); + assert.deepEqual(actualStatsEnums[1], [{ schema: "Test", name: "Status", key: "Off", value: 2 }]); + + const myDomainVal: ECSqlValue = stmt.getValue(2); + assert.isFalse(myDomainVal.isNull); + assert.isTrue(myDomainVal.columnInfo.isEnum()); + assert.equal(myDomainVal.getString(), "Org"); + assert.deepEqual(myDomainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Org", value: "Org" }]); + + const myDomainsVal: ECSqlValue = stmt.getValue(3); + assert.isFalse(myDomainsVal.isNull); + assert.isTrue(myDomainsVal.columnInfo.isEnum()); + assert.deepEqual(myDomainsVal.getArray(), ["Org", "Com"]); + const actualDomainsEnums: ECEnumValue[][] = []; + for (const arrayElement of myDomainsVal.getArrayIterator()) { + actualDomainsEnums.push(arrayElement.getEnum()!); + } + assert.equal(actualDomainsEnums.length, 2); + assert.deepEqual(actualDomainsEnums[0], [{ schema: "Test", name: "Domain", key: "Org", value: "Org" }]); + assert.deepEqual(actualDomainsEnums[1], [{ schema: "Test", name: "Domain", key: "Com", value: "Com" }]); + }); - assert.equal(await query(ecdb, "SELECT MyStat,MyStats, MyDomain,MyDomains FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([id]), undefined, (row: any) => { - assert.equal(row.myStat, 1); - assert.deepEqual(row.myStats, [1, 2]); - assert.equal(row.myDomain, "Org"); - assert.deepEqual(row.myDomains, ["Org", "Com"]); - }), 1); - - // test some enums in the built-in schemas - ecdb.withPreparedStatement("SELECT Type,Modifier FROM meta.ECClassDef WHERE Name='Foo'", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - const row: any = stmt.getRow(); - assert.deepEqual(row, { type: 0, modifier: 2 }); - - const typeVal: ECSqlValue = stmt.getValue(0); - assert.isFalse(typeVal.isNull); - assert.isTrue(typeVal.columnInfo.isEnum()); - assert.equal(typeVal.getInteger(), 0); - assert.deepEqual(typeVal.getEnum(), [{ schema: "ECDbMeta", name: "ECClassType", key: "Entity", value: 0 }]); - - const modifierVal: ECSqlValue = stmt.getValue(1); - assert.isFalse(modifierVal.isNull); - assert.isTrue(modifierVal.columnInfo.isEnum()); - assert.equal(modifierVal.getInteger(), 2); - assert.deepEqual(modifierVal.getEnum(), [{ schema: "ECDbMeta", name: "ECClassModifier", key: "Sealed", value: 2 }]); - }); + assert.equal( + await query( + ecdb, + "SELECT MyStat,MyStats, MyDomain,MyDomains FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([id]), + undefined, + (row: any) => { + assert.equal(row.myStat, 1); + assert.deepEqual(row.myStats, [1, 2]); + assert.equal(row.myDomain, "Org"); + assert.deepEqual(row.myDomains, ["Org", "Com"]); + }, + ), + 1, + ); + + // test some enums in the built-in schemas + ecdb.withPreparedStatement("SELECT Type,Modifier FROM meta.ECClassDef WHERE Name='Foo'", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + const row: any = stmt.getRow(); + assert.deepEqual(row, { type: 0, modifier: 2 }); + + const typeVal: ECSqlValue = stmt.getValue(0); + assert.isFalse(typeVal.isNull); + assert.isTrue(typeVal.columnInfo.isEnum()); + assert.equal(typeVal.getInteger(), 0); + assert.deepEqual(typeVal.getEnum(), [{ schema: "ECDbMeta", name: "ECClassType", key: "Entity", value: 0 }]); + + const modifierVal: ECSqlValue = stmt.getValue(1); + assert.isFalse(modifierVal.isNull); + assert.isTrue(modifierVal.columnInfo.isEnum()); + assert.equal(modifierVal.getInteger(), 2); + assert.deepEqual(modifierVal.getEnum(), [{ schema: "ECDbMeta", name: "ECClassModifier", key: "Sealed", value: 2 }]); + }); - assert.equal(await query(ecdb, "SELECT Type,Modifier FROM meta.ECClassDef WHERE Name='Foo'", QueryBinder.from([id]), undefined, (row: any) => { - assert.deepEqual(row, { type: 0, modifier: 2 }); - }), 1); - }); + assert.equal( + await query(ecdb, "SELECT Type,Modifier FROM meta.ECClassDef WHERE Name='Foo'", QueryBinder.from([id]), undefined, (row: any) => { + assert.deepEqual(row, { type: 0, modifier: 2 }); + }), + 1, + ); + }, + ); }); it("check ORed ECEnums", async () => { @@ -2680,8 +3371,11 @@ describe("ECSqlStatement", () => { slm.append().error().category("ECDb").message(/The value 9 cannot be broken down into a combination of ECEnumerators/gm); slm.append().error().category("ECDb").message(/The value 'gov,de' cannot be broken down into a combination of ECEnumerators/gm); - await using(ECDbTestHelper.createECDb(outDir, "oredecenums.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "oredecenums.ecdb", + ` @@ -2696,210 +3390,275 @@ describe("ECSqlStatement", () => { - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const ids: { unored: Id64String, ored: Id64String, unmatched: Id64String } = ecdb.withPreparedStatement( + "INSERT INTO test.Foo(MyColor,MyDomain) VALUES(?,?)", + (stmt: ECSqlStatement) => { + stmt.bindValue(1, 4); + stmt.bindValue(2, "com"); + let res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + const unored: Id64String = res.id!; + stmt.reset(); + stmt.clearBindings(); + + stmt.bindValue(1, 5); + stmt.bindValue(2, "gov,com"); + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + const ored: Id64String = res.id!; + stmt.reset(); + stmt.clearBindings(); + + stmt.bindValue(1, 9); + stmt.bindValue(2, "gov,de"); + res = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + const unmatched: Id64String = res.id!; + stmt.reset(); + stmt.clearBindings(); + + return { unored, ored, unmatched }; + }, + ); + + ecdb.withPreparedStatement("SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { + stmt.bindId(1, ids.unored); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + let row: any = stmt.getRow(); + assert.equal(row.myColor, 4); + assert.equal(row.myDomain, "com"); + + let colVal: ECSqlValue = stmt.getValue(0); + assert.isFalse(colVal.isNull); + assert.isTrue(colVal.columnInfo.isEnum()); + assert.equal(colVal.getInteger(), 4); + assert.deepEqual(colVal.getEnum(), [{ schema: "Test", name: "Color", key: "Blue", value: 4 }]); + + let domainVal: ECSqlValue = stmt.getValue(1); + assert.isFalse(domainVal.isNull); + assert.isTrue(domainVal.columnInfo.isEnum()); + assert.equal(domainVal.getString(), "com"); + assert.deepEqual(domainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Com", value: "com" }]); + stmt.reset(); + stmt.clearBindings(); - const ids: { unored: Id64String, ored: Id64String, unmatched: Id64String } = ecdb.withPreparedStatement("INSERT INTO test.Foo(MyColor,MyDomain) VALUES(?,?)", (stmt: ECSqlStatement) => { - stmt.bindValue(1, 4); - stmt.bindValue(2, "com"); - let res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - const unored: Id64String = res.id!; - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValue(1, 5); - stmt.bindValue(2, "gov,com"); - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - const ored: Id64String = res.id!; - stmt.reset(); - stmt.clearBindings(); - - stmt.bindValue(1, 9); - stmt.bindValue(2, "gov,de"); - res = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - const unmatched: Id64String = res.id!; - stmt.reset(); - stmt.clearBindings(); - - return { unored, ored, unmatched }; - }); + stmt.bindId(1, ids.ored); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + row = stmt.getRow(); + assert.equal(row.myColor, 5); + assert.equal(row.myDomain, "gov,com"); + + colVal = stmt.getValue(0); + assert.isFalse(colVal.isNull); + assert.isTrue(colVal.columnInfo.isEnum()); + assert.equal(colVal.getInteger(), 5); + assert.deepEqual(colVal.getEnum(), [{ schema: "Test", name: "Color", key: "Red", value: 1 }, { + schema: "Test", + name: "Color", + key: "Blue", + value: 4, + }]); + + domainVal = stmt.getValue(1); + assert.isFalse(domainVal.isNull); + assert.isTrue(domainVal.columnInfo.isEnum()); + assert.equal(domainVal.getString(), "gov,com"); + assert.deepEqual(domainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Com", value: "com" }, { + schema: "Test", + name: "Domain", + key: "Gov", + value: "gov", + }]); - ecdb.withPreparedStatement("SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, ids.unored); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - let row: any = stmt.getRow(); - assert.equal(row.myColor, 4); - assert.equal(row.myDomain, "com"); - - let colVal: ECSqlValue = stmt.getValue(0); - assert.isFalse(colVal.isNull); - assert.isTrue(colVal.columnInfo.isEnum()); - assert.equal(colVal.getInteger(), 4); - assert.deepEqual(colVal.getEnum(), [{ schema: "Test", name: "Color", key: "Blue", value: 4 }]); - - let domainVal: ECSqlValue = stmt.getValue(1); - assert.isFalse(domainVal.isNull); - assert.isTrue(domainVal.columnInfo.isEnum()); - assert.equal(domainVal.getString(), "com"); - assert.deepEqual(domainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Com", value: "com" }]); - stmt.reset(); - stmt.clearBindings(); - - stmt.bindId(1, ids.ored); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - row = stmt.getRow(); - assert.equal(row.myColor, 5); - assert.equal(row.myDomain, "gov,com"); - - colVal = stmt.getValue(0); - assert.isFalse(colVal.isNull); - assert.isTrue(colVal.columnInfo.isEnum()); - assert.equal(colVal.getInteger(), 5); - assert.deepEqual(colVal.getEnum(), [{ schema: "Test", name: "Color", key: "Red", value: 1 }, { schema: "Test", name: "Color", key: "Blue", value: 4 }]); - - domainVal = stmt.getValue(1); - assert.isFalse(domainVal.isNull); - assert.isTrue(domainVal.columnInfo.isEnum()); - assert.equal(domainVal.getString(), "gov,com"); - assert.deepEqual(domainVal.getEnum(), [{ schema: "Test", name: "Domain", key: "Com", value: "com" }, { schema: "Test", name: "Domain", key: "Gov", value: "gov" }]); - - stmt.reset(); - stmt.clearBindings(); - - stmt.bindId(1, ids.unmatched); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - row = stmt.getRow(); - assert.equal(row.myColor, 9); - assert.equal(row.myDomain, "gov,de"); - - colVal = stmt.getValue(0); - assert.isFalse(colVal.isNull); - assert.isTrue(colVal.columnInfo.isEnum()); - assert.equal(colVal.getInteger(), 9); - assert.isUndefined(colVal.getEnum()); - - domainVal = stmt.getValue(1); - assert.isFalse(domainVal.isNull); - assert.isTrue(domainVal.columnInfo.isEnum()); - assert.equal(domainVal.getString(), "gov,de"); - assert.isUndefined(domainVal.getEnum()); - }); + stmt.reset(); + stmt.clearBindings(); - assert.equal(await query(ecdb, "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([ids.unored]), undefined, (row: any) => { - assert.equal(row.myColor, 4); - assert.equal(row.myDomain, "com"); - }), 1); - - assert.equal(await query(ecdb, "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([ids.ored]), undefined, (row: any) => { - assert.equal(row.myColor, 5); - assert.equal(row.myDomain, "gov,com"); - }), 1); - - assert.equal(await query(ecdb, "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([ids.unmatched]), undefined, (row: any) => { - assert.equal(row.myColor, 9); - assert.equal(row.myDomain, "gov,de"); - }), 1); - - // test some enums in the built-in schemas - ecdb.withPreparedStatement("SELECT CustomAttributeContainerType caType FROM meta.ECClassDef WHERE Type=meta.ECClassType.CustomAttribute AND Name='DateTimeInfo'", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - const row: any = stmt.getRow(); - assert.equal(row.caType, 160); - - const caTypeVal: ECSqlValue = stmt.getValue(0); - assert.isFalse(caTypeVal.isNull); - assert.isTrue(caTypeVal.columnInfo.isEnum()); - assert.equal(caTypeVal.getInteger(), 160); - assert.deepEqual(caTypeVal.getEnum(), [ - { schema: "ECDbMeta", name: "ECCustomAttributeContainerType", key: "PrimitiveProperty", value: 32 }, - { schema: "ECDbMeta", name: "ECCustomAttributeContainerType", key: "PrimitiveArrayProperty", value: 128 }]); - }); - assert.equal(await query(ecdb, "SELECT CustomAttributeContainerType caType FROM meta.ECClassDef WHERE Type=meta.ECClassType.CustomAttribute AND Name='DateTimeInfo'", QueryBinder.from([ids.unmatched]), undefined, (row: any) => { - assert.equal(row.caType, 160); - }), 1); - }); + stmt.bindId(1, ids.unmatched); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + row = stmt.getRow(); + assert.equal(row.myColor, 9); + assert.equal(row.myDomain, "gov,de"); + + colVal = stmt.getValue(0); + assert.isFalse(colVal.isNull); + assert.isTrue(colVal.columnInfo.isEnum()); + assert.equal(colVal.getInteger(), 9); + assert.isUndefined(colVal.getEnum()); + + domainVal = stmt.getValue(1); + assert.isFalse(domainVal.isNull); + assert.isTrue(domainVal.columnInfo.isEnum()); + assert.equal(domainVal.getString(), "gov,de"); + assert.isUndefined(domainVal.getEnum()); + }); + + assert.equal( + await query(ecdb, "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([ids.unored]), undefined, (row: any) => { + assert.equal(row.myColor, 4); + assert.equal(row.myDomain, "com"); + }), + 1, + ); + + assert.equal( + await query(ecdb, "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", QueryBinder.from([ids.ored]), undefined, (row: any) => { + assert.equal(row.myColor, 5); + assert.equal(row.myDomain, "gov,com"); + }), + 1, + ); + + assert.equal( + await query( + ecdb, + "SELECT MyColor,MyDomain FROM test.Foo WHERE ECInstanceId=?", + QueryBinder.from([ids.unmatched]), + undefined, + (row: any) => { + assert.equal(row.myColor, 9); + assert.equal(row.myDomain, "gov,de"); + }, + ), + 1, + ); + + // test some enums in the built-in schemas + ecdb.withPreparedStatement( + "SELECT CustomAttributeContainerType caType FROM meta.ECClassDef WHERE Type=meta.ECClassType.CustomAttribute AND Name='DateTimeInfo'", + (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + const row: any = stmt.getRow(); + assert.equal(row.caType, 160); + + const caTypeVal: ECSqlValue = stmt.getValue(0); + assert.isFalse(caTypeVal.isNull); + assert.isTrue(caTypeVal.columnInfo.isEnum()); + assert.equal(caTypeVal.getInteger(), 160); + assert.deepEqual(caTypeVal.getEnum(), [ + { schema: "ECDbMeta", name: "ECCustomAttributeContainerType", key: "PrimitiveProperty", value: 32 }, + { schema: "ECDbMeta", name: "ECCustomAttributeContainerType", key: "PrimitiveArrayProperty", value: 128 }, + ]); + }, + ); + assert.equal( + await query( + ecdb, + "SELECT CustomAttributeContainerType caType FROM meta.ECClassDef WHERE Type=meta.ECClassType.CustomAttribute AND Name='DateTimeInfo'", + QueryBinder.from([ids.unmatched]), + undefined, + (row: any) => { + assert.equal(row.caType, 160); + }, + ), + 1, + ); + }, + ); assert.isTrue(slm.finishAndDispose()); }); it("should get native sql", async () => { - await using(ECDbTestHelper.createECDb(outDir, "asyncmethodtest.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "asyncmethodtest.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const r = await ecdb.withPreparedStatement("INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", async (stmt: ECSqlStatement) => { - const nativesql: string = stmt.getNativeSql(); - assert.isTrue(nativesql.startsWith("INSERT INTO [ts_Foo]")); - return stmt.stepForInsert(); - }); - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - assert.equal(r.id, "0x1"); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const r = await ecdb.withPreparedStatement( + "INSERT INTO ts.Foo(n,dt,fooId) VALUES(20,TIMESTAMP '2018-10-18T12:00:00Z',20)", + async (stmt: ECSqlStatement) => { + const nativesql: string = stmt.getNativeSql(); + assert.isTrue(nativesql.startsWith("INSERT INTO [ts_Foo]")); + return stmt.stepForInsert(); + }, + ); + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.equal(r.id, "0x1"); + }, + ); }); it("check column info", async () => { - await using(ECDbTestHelper.createECDb(outDir, "columnInfo.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "columnInfo.ecdb", + ` - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.MyClass(MyProperty) VALUES('Value')", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - return res.id!; - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const id: Id64String = ecdb.withPreparedStatement("INSERT INTO test.MyClass(MyProperty) VALUES('Value')", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + return res.id!; + }); - ecdb.withPreparedStatement("SELECT MyProperty as MyAlias, 1 as MyGenerated FROM test.MyClass WHERE ECInstanceId=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, id); - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - const row: any = stmt.getRow(); - assert.equal(row.myAlias, "Value"); - assert.equal(row.myGenerated, 1); - - const val0: ECSqlValue = stmt.getValue(0); - const colInfo0: ECSqlColumnInfo = val0.columnInfo; - - assert.equal(colInfo0.getPropertyName(), "MyAlias"); - const accessString0 = colInfo0.getAccessString(); - assert.equal(accessString0, "MyAlias"); - const originPropertyName = colInfo0.getOriginPropertyName(); - assert.isDefined(originPropertyName); - assert.equal(originPropertyName, "MyProperty"); - - const val1: ECSqlValue = stmt.getValue(1); - const colInfo1: ECSqlColumnInfo = val1.columnInfo; - - assert.equal(colInfo1.getPropertyName(), "MyGenerated"); - const accessString1 = colInfo1.getAccessString(); - assert.equal(accessString1, "MyGenerated"); - assert.isUndefined(colInfo1.getOriginPropertyName()); - }); - }); + ecdb.withPreparedStatement( + "SELECT MyProperty as MyAlias, 1 as MyGenerated FROM test.MyClass WHERE ECInstanceId=?", + (stmt: ECSqlStatement) => { + stmt.bindId(1, id); + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + const row: any = stmt.getRow(); + assert.equal(row.myAlias, "Value"); + assert.equal(row.myGenerated, 1); + + const val0: ECSqlValue = stmt.getValue(0); + const colInfo0: ECSqlColumnInfo = val0.columnInfo; + + assert.equal(colInfo0.getPropertyName(), "MyAlias"); + const accessString0 = colInfo0.getAccessString(); + assert.equal(accessString0, "MyAlias"); + const originPropertyName = colInfo0.getOriginPropertyName(); + assert.isDefined(originPropertyName); + assert.equal(originPropertyName, "MyProperty"); + + const val1: ECSqlValue = stmt.getValue(1); + const colInfo1: ECSqlColumnInfo = val1.columnInfo; + + assert.equal(colInfo1.getPropertyName(), "MyGenerated"); + const accessString1 = colInfo1.getAccessString(); + assert.equal(accessString1, "MyGenerated"); + assert.isUndefined(colInfo1.getOriginPropertyName()); + }, + ); + }, + ); }); it("check access string metadata in nested struct", async () => { - await using(ECDbTestHelper.createECDb(outDir, "columnInfo.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "columnInfo.ecdb", + ` @@ -2929,115 +3688,121 @@ describe("ECSqlStatement", () => { - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - ecdb.withPreparedStatement("INSERT INTO Test.A (f.c.a, f.c.b, f.d, g) VALUES ('f.c.a' ,'f.c.b', 'f.d', 'g')", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - }); + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + ecdb.withPreparedStatement("INSERT INTO Test.A (f.c.a, f.c.b, f.d, g) VALUES ('f.c.a' ,'f.c.b', 'f.d', 'g')", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + }); - ecdb.withPreparedStatement("SELECT f, f.c.a, f.c.b, f.d, g FROM Test.A", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - const row: any = stmt.getRow(); - assert.equal(row.f.c.a, "f.c.a"); - assert.equal(row.f.c.b, "f.c.b"); - assert.equal(row.f.d, "f.d"); - assert.equal(row.g, "g"); - - const val0: ECSqlValue = stmt.getValue(0); - const colInfo0: ECSqlColumnInfo = val0.columnInfo; - - assert.equal(colInfo0.getPropertyName(), "f"); - const accessString0 = colInfo0.getAccessString(); - assert.equal(accessString0, "f"); - const originPropertyName0 = colInfo0.getOriginPropertyName(); - assert.isDefined(originPropertyName0); - assert.equal(originPropertyName0, "f"); - - const val1: ECSqlValue = stmt.getValue(1); - const colInfo1: ECSqlColumnInfo = val1.columnInfo; - - assert.equal(colInfo1.getPropertyName(), "a"); - const accessString1 = colInfo1.getAccessString(); - assert.equal(accessString1, "f.c.a"); - const originPropertyName1 = colInfo1.getOriginPropertyName(); - assert.isDefined(originPropertyName1); - assert.equal(originPropertyName1, "a"); - - const val2: ECSqlValue = stmt.getValue(2); - const colInfo2: ECSqlColumnInfo = val2.columnInfo; - - assert.equal(colInfo2.getPropertyName(), "b"); - const accessString2 = colInfo2.getAccessString(); - assert.equal(accessString2, "f.c.b"); - const originPropertyName2 = colInfo2.getOriginPropertyName(); - assert.isDefined(originPropertyName2); - assert.equal(originPropertyName2, "b"); - - const val3: ECSqlValue = stmt.getValue(3); - const colInfo3: ECSqlColumnInfo = val3.columnInfo; - - assert.equal(colInfo3.getPropertyName(), "d"); - const accessString3 = colInfo3.getAccessString(); - assert.equal(accessString3, "f.d"); - const originPropertyName3 = colInfo3.getOriginPropertyName(); - assert.isDefined(originPropertyName3); - assert.equal(originPropertyName3, "d"); - - const val4: ECSqlValue = stmt.getValue(4); - const colInfo4: ECSqlColumnInfo = val4.columnInfo; - - assert.equal(colInfo4.getPropertyName(), "g"); - const accessString4 = colInfo4.getAccessString(); - assert.equal(accessString4, "g"); - const originPropertyName4 = colInfo4.getOriginPropertyName(); - assert.isDefined(originPropertyName4); - assert.equal(originPropertyName4, "g"); - }); + ecdb.withPreparedStatement("SELECT f, f.c.a, f.c.b, f.d, g FROM Test.A", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + const row: any = stmt.getRow(); + assert.equal(row.f.c.a, "f.c.a"); + assert.equal(row.f.c.b, "f.c.b"); + assert.equal(row.f.d, "f.d"); + assert.equal(row.g, "g"); + + const val0: ECSqlValue = stmt.getValue(0); + const colInfo0: ECSqlColumnInfo = val0.columnInfo; + + assert.equal(colInfo0.getPropertyName(), "f"); + const accessString0 = colInfo0.getAccessString(); + assert.equal(accessString0, "f"); + const originPropertyName0 = colInfo0.getOriginPropertyName(); + assert.isDefined(originPropertyName0); + assert.equal(originPropertyName0, "f"); + + const val1: ECSqlValue = stmt.getValue(1); + const colInfo1: ECSqlColumnInfo = val1.columnInfo; + + assert.equal(colInfo1.getPropertyName(), "a"); + const accessString1 = colInfo1.getAccessString(); + assert.equal(accessString1, "f.c.a"); + const originPropertyName1 = colInfo1.getOriginPropertyName(); + assert.isDefined(originPropertyName1); + assert.equal(originPropertyName1, "a"); + + const val2: ECSqlValue = stmt.getValue(2); + const colInfo2: ECSqlColumnInfo = val2.columnInfo; + + assert.equal(colInfo2.getPropertyName(), "b"); + const accessString2 = colInfo2.getAccessString(); + assert.equal(accessString2, "f.c.b"); + const originPropertyName2 = colInfo2.getOriginPropertyName(); + assert.isDefined(originPropertyName2); + assert.equal(originPropertyName2, "b"); + + const val3: ECSqlValue = stmt.getValue(3); + const colInfo3: ECSqlColumnInfo = val3.columnInfo; + + assert.equal(colInfo3.getPropertyName(), "d"); + const accessString3 = colInfo3.getAccessString(); + assert.equal(accessString3, "f.d"); + const originPropertyName3 = colInfo3.getOriginPropertyName(); + assert.isDefined(originPropertyName3); + assert.equal(originPropertyName3, "d"); + + const val4: ECSqlValue = stmt.getValue(4); + const colInfo4: ECSqlColumnInfo = val4.columnInfo; + + assert.equal(colInfo4.getPropertyName(), "g"); + const accessString4 = colInfo4.getAccessString(); + assert.equal(accessString4, "g"); + const originPropertyName4 = colInfo4.getOriginPropertyName(); + assert.isDefined(originPropertyName4); + assert.equal(originPropertyName4, "g"); + }); - ecdb.withPreparedStatement("INSERT INTO Test.B (h.a, h.b, i) VALUES ('h.a' ,'h.b', 'i')", (stmt: ECSqlStatement) => { - const res: ECSqlInsertResult = stmt.stepForInsert(); - assert.equal(res.status, DbResult.BE_SQLITE_DONE); - assert.isDefined(res.id); - }); + ecdb.withPreparedStatement("INSERT INTO Test.B (h.a, h.b, i) VALUES ('h.a' ,'h.b', 'i')", (stmt: ECSqlStatement) => { + const res: ECSqlInsertResult = stmt.stepForInsert(); + assert.equal(res.status, DbResult.BE_SQLITE_DONE); + assert.isDefined(res.id); + }); - ecdb.withPreparedStatement("SELECT h, i FROM Test.B", (stmt: ECSqlStatement) => { - assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); - // getRow just returns the enum values - const row: any = stmt.getRow(); - assert.equal(row.h.a, "h.a"); - assert.equal(row.h.b, "h.b"); - assert.equal(row.i, "i"); - - const val0: ECSqlValue = stmt.getValue(0); - const colInfo0: ECSqlColumnInfo = val0.columnInfo; - - assert.equal(colInfo0.getPropertyName(), "h"); - const accessString0 = colInfo0.getAccessString(); - assert.equal(accessString0, "h"); - const originPropertyName0 = colInfo0.getOriginPropertyName(); - assert.isDefined(originPropertyName0); - assert.equal(originPropertyName0, "h"); - - const val1: ECSqlValue = stmt.getValue(1); - const colInfo1: ECSqlColumnInfo = val1.columnInfo; - - assert.equal(colInfo1.getPropertyName(), "i"); - const accessString1 = colInfo1.getAccessString(); - assert.equal(accessString1, "i"); - const originPropertyName1 = colInfo1.getOriginPropertyName(); - assert.isDefined(originPropertyName1); - assert.equal(originPropertyName1, "i"); - }); - }); + ecdb.withPreparedStatement("SELECT h, i FROM Test.B", (stmt: ECSqlStatement) => { + assert.equal(stmt.step(), DbResult.BE_SQLITE_ROW); + // getRow just returns the enum values + const row: any = stmt.getRow(); + assert.equal(row.h.a, "h.a"); + assert.equal(row.h.b, "h.b"); + assert.equal(row.i, "i"); + + const val0: ECSqlValue = stmt.getValue(0); + const colInfo0: ECSqlColumnInfo = val0.columnInfo; + + assert.equal(colInfo0.getPropertyName(), "h"); + const accessString0 = colInfo0.getAccessString(); + assert.equal(accessString0, "h"); + const originPropertyName0 = colInfo0.getOriginPropertyName(); + assert.isDefined(originPropertyName0); + assert.equal(originPropertyName0, "h"); + + const val1: ECSqlValue = stmt.getValue(1); + const colInfo1: ECSqlColumnInfo = val1.columnInfo; + + assert.equal(colInfo1.getPropertyName(), "i"); + const accessString1 = colInfo1.getAccessString(); + assert.equal(accessString1, "i"); + const originPropertyName1 = colInfo1.getOriginPropertyName(); + assert.isDefined(originPropertyName1); + assert.equal(originPropertyName1, "i"); + }); + }, + ); }); it("ecsql statements with QueryBinder", async () => { - await using(ECDbTestHelper.createECDb(outDir, "test.ecdb", - ` + using( + ECDbTestHelper.createECDb( + outDir, + "test.ecdb", + ` @@ -3057,104 +3822,107 @@ describe("ECSqlStatement", () => { - `), async (ecdb: ECDb) => { - assert.isTrue(ecdb.isOpen); - - const booleanValue = true; - const blobValue = new Uint8Array([0, 0, 0]); - const doubleValue = 12.12; - const customIdValue = "1234"; - const customIdSetValue = ["0x9"]; - const intValue = 10; - const longValue = 1e9; - const stringValue = "test string value"; - const point2dValue = new Point2d(10, 20); - const point3dValue = new Point3d(15, 30, 45); - const structValue = { structClassProperty: "test string value for struct property" }; - - let r = await ecdb.withPreparedStatement( - `INSERT INTO ts.Foo(booleanProperty, blobProperty, doubleProperty, customIdProperty, customIdSetProperty, intProperty, longProperty, stringProperty, nullProperty, point2dProperty, point3dProperty) + `, + ), + async (ecdb: ECDb) => { + assert.isTrue(ecdb.isOpen); + + const booleanValue = true; + const blobValue = new Uint8Array([0, 0, 0]); + const doubleValue = 12.12; + const customIdValue = "1234"; + const customIdSetValue = ["0x9"]; + const intValue = 10; + const longValue = 1e9; + const stringValue = "test string value"; + const point2dValue = new Point2d(10, 20); + const point3dValue = new Point3d(15, 30, 45); + const structValue = { structClassProperty: "test string value for struct property" }; + + let r = await ecdb.withPreparedStatement( + `INSERT INTO ts.Foo(booleanProperty, blobProperty, doubleProperty, customIdProperty, customIdSetProperty, intProperty, longProperty, stringProperty, nullProperty, point2dProperty, point3dProperty) VALUES(:booleanValue, :blobValue, :doubleValue, :customIdValue, :customIdSetValue, :intValue, :longValue, :stringValue, :nullValue, :point2dValue, :point3dValue)`, - async (stmt: ECSqlStatement) => { - stmt.bindBoolean("booleanValue", booleanValue); - stmt.bindBlob("blobValue", blobValue); - stmt.bindDouble("doubleValue", doubleValue); - stmt.bindId("customIdValue", customIdValue); - stmt.bindId("customIdSetValue", customIdSetValue[0]); - stmt.bindInteger("intValue", intValue); - stmt.bindInteger("longValue", longValue); - stmt.bindString("stringValue", stringValue); - stmt.bindNull("nullValue"); - stmt.bindPoint2d("point2dValue", point2dValue); - stmt.bindPoint3d("point3dValue", point3dValue); - return stmt.stepForInsert(); - }, - ); - - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - assert.equal(r.id, "0x1"); - - const params = new QueryBinder(); - params.bindBoolean("booleanValue", booleanValue); - params.bindBlob("blobValue", blobValue); - params.bindDouble("doubleValue", doubleValue); - params.bindId("customIdValue", customIdValue); - params.bindInt("intValue", intValue); - params.bindLong("longValue", longValue); - params.bindString("stringValue", stringValue); - params.bindPoint2d("point2dValue", point2dValue); - params.bindPoint3d("point3dValue", point3dValue); - params.bindIdSet("customIdSetValue", customIdSetValue); - - let reader = ecdb.createQueryReader( - `SELECT booleanProperty, blobProperty, doubleProperty, customIdProperty, customIdSetProperty, intProperty, longProperty, stringProperty, nullProperty, point2dProperty, point3dProperty FROM ts.Foo + async (stmt: ECSqlStatement) => { + stmt.bindBoolean("booleanValue", booleanValue); + stmt.bindBlob("blobValue", blobValue); + stmt.bindDouble("doubleValue", doubleValue); + stmt.bindId("customIdValue", customIdValue); + stmt.bindId("customIdSetValue", customIdSetValue[0]); + stmt.bindInteger("intValue", intValue); + stmt.bindInteger("longValue", longValue); + stmt.bindString("stringValue", stringValue); + stmt.bindNull("nullValue"); + stmt.bindPoint2d("point2dValue", point2dValue); + stmt.bindPoint3d("point3dValue", point3dValue); + return stmt.stepForInsert(); + }, + ); + + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.equal(r.id, "0x1"); + + const params = new QueryBinder(); + params.bindBoolean("booleanValue", booleanValue); + params.bindBlob("blobValue", blobValue); + params.bindDouble("doubleValue", doubleValue); + params.bindId("customIdValue", customIdValue); + params.bindInt("intValue", intValue); + params.bindLong("longValue", longValue); + params.bindString("stringValue", stringValue); + params.bindPoint2d("point2dValue", point2dValue); + params.bindPoint3d("point3dValue", point3dValue); + params.bindIdSet("customIdSetValue", customIdSetValue); + + let reader = ecdb.createQueryReader( + `SELECT booleanProperty, blobProperty, doubleProperty, customIdProperty, customIdSetProperty, intProperty, longProperty, stringProperty, nullProperty, point2dProperty, point3dProperty FROM ts.Foo WHERE booleanProperty = :booleanValue AND blobProperty = :blobValue AND doubleProperty = :doubleValue AND customIdProperty = :customIdValue AND InVirtualSet(:customIdSetValue, customIdSetProperty) AND intProperty = :intValue AND longProperty = :longValue AND stringProperty = :stringValue AND point2dProperty = :point2dValue AND point3dProperty = :point3dValue`, - params, - ); - const row = (await reader.toArray())[0]; - - assert.isNotNull(row); - assert.equal(row[0], booleanValue); - assert.deepEqual(row[1], blobValue); - assert.equal(row[2], doubleValue); - assert.equal(row[3], customIdValue); - assert.equal(row[4], "9"); - assert.equal(row[5], intValue); - assert.equal(row[6], longValue); - assert.equal(row[7], stringValue); - assert.equal(row[8], null); - assert.deepEqual(row[9], { X: 10, Y: 20 }); - assert.deepEqual(row[10], { X: 15, Y: 30, Z: 45 }); - - assert.isFalse(await reader.step()); - - r = await ecdb.withPreparedStatement( - "INSERT INTO ts.Baz(structProperty) VALUES(:structValue)", - async (stmt: ECSqlStatement) => { - stmt.bindStruct("structValue", structValue); - return stmt.stepForInsert(); - }, - ); - - ecdb.saveChanges(); - assert.equal(r.status, DbResult.BE_SQLITE_DONE); - assert.equal(r.id, "0x2"); + params, + ); + const row = (await reader.toArray())[0]; + + assert.isNotNull(row); + assert.equal(row[0], booleanValue); + assert.deepEqual(row[1], blobValue); + assert.equal(row[2], doubleValue); + assert.equal(row[3], customIdValue); + assert.equal(row[4], "9"); + assert.equal(row[5], intValue); + assert.equal(row[6], longValue); + assert.equal(row[7], stringValue); + assert.equal(row[8], null); + assert.deepEqual(row[9], { X: 10, Y: 20 }); + assert.deepEqual(row[10], { X: 15, Y: 30, Z: 45 }); + + assert.isFalse(await reader.step()); + + r = await ecdb.withPreparedStatement( + "INSERT INTO ts.Baz(structProperty) VALUES(:structValue)", + async (stmt: ECSqlStatement) => { + stmt.bindStruct("structValue", structValue); + return stmt.stepForInsert(); + }, + ); + + ecdb.saveChanges(); + assert.equal(r.status, DbResult.BE_SQLITE_DONE); + assert.equal(r.id, "0x2"); - reader = ecdb.createQueryReader( - `SELECT * FROM ts.Baz`, - ); + reader = ecdb.createQueryReader( + `SELECT * FROM ts.Baz`, + ); - await reader.step(); + await reader.step(); - assert.deepEqual(reader.current.structProperty, structValue); + assert.deepEqual(reader.current.structProperty, structValue); - const paramsWithStruct = new QueryBinder(); - paramsWithStruct.bindStruct("structValue", structValue); - reader = ecdb.createQueryReader("SELECT * FROM ts.Baz WHERE structProperty = :structValue", paramsWithStruct); + const paramsWithStruct = new QueryBinder(); + paramsWithStruct.bindStruct("structValue", structValue); + reader = ecdb.createQueryReader("SELECT * FROM ts.Baz WHERE structProperty = :structValue", paramsWithStruct); - await assert.isRejected(reader.toArray(), "Struct type binding not supported"); - }); + await assert.isRejected(reader.toArray(), "Struct type binding not supported"); + }, + ); }); }); diff --git a/core/backend/src/test/ecdb/SqliteStatement.test.ts b/core/backend/src/test/ecdb/SqliteStatement.test.ts index 767833d8cf74..de3bea88b08e 100644 --- a/core/backend/src/test/ecdb/SqliteStatement.test.ts +++ b/core/backend/src/test/ecdb/SqliteStatement.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; import { DbResult, using } from "@itwin/core-bentley"; import { Range3d } from "@itwin/core-geometry"; +import { assert } from "chai"; +import * as path from "path"; import { ECDb, ECDbOpenMode, SqliteStatement, SqliteValueType } from "../../core-backend"; import { KnownTestLocations } from "../KnownTestLocations"; -import { ECDbTestHelper } from "./ECDbTestHelper"; import { SequentialLogMatcher } from "../SequentialLogMatcher"; +import { ECDbTestHelper } from "./ECDbTestHelper"; describe("SqliteStatement", () => { const outDir = KnownTestLocations.outputDir; @@ -22,10 +22,13 @@ describe("SqliteStatement", () => { using(ECDbTestHelper.createECDb(outDir, "sqlitestatement.ecdb"), (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); - ecdb.withSqliteStatement("CREATE TABLE MyTable(id INTEGER PRIMARY KEY, stringcol TEXT, intcol INTEGER, doublecol REAL, blobcol)", (stmt: SqliteStatement) => { - assert.isFalse(stmt.isReadonly); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); + ecdb.withSqliteStatement( + "CREATE TABLE MyTable(id INTEGER PRIMARY KEY, stringcol TEXT, intcol INTEGER, doublecol REAL, blobcol)", + (stmt: SqliteStatement) => { + assert.isFalse(stmt.isReadonly); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + }, + ); const stmt1 = "INSERT INTO MyTable(stringcol,intcol,doublecol,blobcol) VALUES(?,?,?,?)"; ecdb.withPreparedSqliteStatement(stmt1, (stmt) => { @@ -171,10 +174,13 @@ describe("SqliteStatement", () => { using(ECDbTestHelper.createECDb(outDir, "bindnull.ecdb"), (ecdb: ECDb) => { assert.isTrue(ecdb.isOpen); - ecdb.withSqliteStatement("CREATE TABLE MyTable(id INTEGER PRIMARY KEY, stringcol TEXT, intcol INTEGER, doublecol REAL, blobcol)", (stmt: SqliteStatement) => { - assert.isFalse(stmt.isReadonly); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); + ecdb.withSqliteStatement( + "CREATE TABLE MyTable(id INTEGER PRIMARY KEY, stringcol TEXT, intcol INTEGER, doublecol REAL, blobcol)", + (stmt: SqliteStatement) => { + assert.isFalse(stmt.isReadonly); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + }, + ); ecdb.withPreparedSqliteStatement("INSERT INTO MyTable(stringcol,intcol,doublecol,blobcol) VALUES(?,?,?,?)", (stmt: SqliteStatement) => { assert.isFalse(stmt.isReadonly); @@ -197,14 +203,17 @@ describe("SqliteStatement", () => { assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); - ecdb.withPreparedSqliteStatement("INSERT INTO MyTable(stringcol,intcol,doublecol,blobcol) VALUES(:string,:int,:double,:blob)", (stmt: SqliteStatement) => { - assert.isFalse(stmt.isReadonly); - stmt.bindValue(":string", undefined); - stmt.bindValue(":int", undefined); - stmt.bindValue(":double", undefined); - stmt.bindValue(":blob", undefined); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); + ecdb.withPreparedSqliteStatement( + "INSERT INTO MyTable(stringcol,intcol,doublecol,blobcol) VALUES(:string,:int,:double,:blob)", + (stmt: SqliteStatement) => { + assert.isFalse(stmt.isReadonly); + stmt.bindValue(":string", undefined); + stmt.bindValue(":int", undefined); + stmt.bindValue(":double", undefined); + stmt.bindValue(":blob", undefined); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + }, + ); ecdb.withPreparedSqliteStatement("INSERT INTO MyTable(stringcol,intcol,doublecol,blobcol) VALUES(?,?,?,?)", (stmt: SqliteStatement) => { assert.isFalse(stmt.isReadonly); @@ -369,7 +378,7 @@ describe("SqliteStatement", () => { }); assert.isTrue(stmt0?.isPrepared, "stmt0 is in the cache"); - ecdb.resetSqliteCache(3); // reset the statement cache to only hold 3 members so we can exercise overflowing it + ecdb.resetSqliteCache(3); // reset the statement cache to only hold 3 members so we can exercise overflowing it assert.isFalse(stmt0?.isPrepared, "reset cache clears stmt0"); let stmt1: SqliteStatement | undefined; @@ -418,26 +427,26 @@ describe("SqliteStatement", () => { assert.isTrue(ecdb.isOpen); // expect log message when statement fails let slm = new SequentialLogMatcher(); - slm.append().error().category("BeSQLite").message("Error \"no such table: def (BE_SQLITE_ERROR)\" preparing SQL: SELECT abc FROM def"); - assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => { }), "no such table: def (BE_SQLITE_ERROR)"); + slm.append().error().category("BeSQLite").message('Error "no such table: def (BE_SQLITE_ERROR)" preparing SQL: SELECT abc FROM def'); + assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => {}), "no such table: def (BE_SQLITE_ERROR)"); assert.isTrue(slm.finishAndDispose(), "logMatcher should detect log"); // now pass suppress log error which mean we should not get the error slm = new SequentialLogMatcher(); - slm.append().error().category("BeSQLite").message("Error \"no such table: def (BE_SQLITE_ERROR)\" preparing SQL: SELECT abc FROM def"); - assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => { }, /* logErrors = */ false), "no such table: def (BE_SQLITE_ERROR)"); + slm.append().error().category("BeSQLite").message('Error "no such table: def (BE_SQLITE_ERROR)" preparing SQL: SELECT abc FROM def'); + assert.throw(() => ecdb.withSqliteStatement("SELECT abc FROM def", () => {}, /* logErrors = */ false), "no such table: def (BE_SQLITE_ERROR)"); assert.isFalse(slm.finishAndDispose(), "logMatcher should not detect log"); // expect log message when statement fails slm = new SequentialLogMatcher(); slm.append().error().category("ECDb").message("ECClass 'abc.def' does not exist or could not be loaded."); - assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => { }), "ECClass 'abc.def' does not exist or could not be loaded."); + assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => {}), "ECClass 'abc.def' does not exist or could not be loaded."); assert.isTrue(slm.finishAndDispose(), "logMatcher should detect log"); // now pass suppress log error which mean we should not get the error slm = new SequentialLogMatcher(); slm.append().error().category("ECDb").message("ECClass 'abc.def' does not exist or could not be loaded."); - assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => { }, /* logErrors = */ false), ""); // BUG: we do not see error message + assert.throw(() => ecdb.withPreparedStatement("SELECT abc FROM abc.def", () => {}, /* logErrors = */ false), ""); // BUG: we do not see error message assert.isFalse(slm.finishAndDispose(), "logMatcher should not detect log"); }); }); diff --git a/core/backend/src/test/element/DeleteDefinitionElements.test.ts b/core/backend/src/test/element/DeleteDefinitionElements.test.ts index c6f64aa4f58a..7e4e036f7185 100644 --- a/core/backend/src/test/element/DeleteDefinitionElements.test.ts +++ b/core/backend/src/test/element/DeleteDefinitionElements.test.ts @@ -3,14 +3,28 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; import { Id64, Id64Set } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { GeometryPartProps, IModel } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; +import { assert } from "chai"; +import * as path from "path"; import { - CategorySelector, DisplayStyle2d, DisplayStyle3d, DrawingCategory, DrawingViewDefinition, GeometryPart, IModelJsFs, InformationPartitionElement, - ModelSelector, OrthographicViewDefinition, RenderMaterialElement, SnapshotDb, SpatialCategory, SubCategory, Subject, Texture, + CategorySelector, + DisplayStyle2d, + DisplayStyle3d, + DrawingCategory, + DrawingViewDefinition, + GeometryPart, + IModelJsFs, + InformationPartitionElement, + ModelSelector, + OrthographicViewDefinition, + RenderMaterialElement, + SnapshotDb, + SpatialCategory, + SubCategory, + Subject, + Texture, } from "../../core-backend"; import { ExtensiveTestScenario, IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; @@ -38,12 +52,16 @@ describe("DeleteDefinitionElements", () => { const definitionModelId = iModelDb.elements.queryElementIdByCode(InformationPartitionElement.createCode(iModelDb, subjectId, "Definition"))!; const spatialCategoryId = iModelDb.elements.queryElementIdByCode(SpatialCategory.createCode(iModelDb, definitionModelId, "SpatialCategory"))!; const subCategoryId = iModelDb.elements.queryElementIdByCode(SubCategory.createCode(iModelDb, spatialCategoryId, "SubCategory"))!; - const spatialCategorySelectorId = iModelDb.elements.queryElementIdByCode(CategorySelector.createCode(iModelDb, definitionModelId, "SpatialCategories"))!; + const spatialCategorySelectorId = iModelDb.elements.queryElementIdByCode( + CategorySelector.createCode(iModelDb, definitionModelId, "SpatialCategories"), + )!; const modelSelectorId = iModelDb.elements.queryElementIdByCode(ModelSelector.createCode(iModelDb, definitionModelId, "SpatialModels"))!; const displayStyle3dId = iModelDb.elements.queryElementIdByCode(DisplayStyle3d.createCode(iModelDb, definitionModelId, "DisplayStyle3d"))!; const viewId = iModelDb.elements.queryElementIdByCode(OrthographicViewDefinition.createCode(iModelDb, definitionModelId, "Orthographic View"))!; const drawingCategoryId = iModelDb.elements.queryElementIdByCode(DrawingCategory.createCode(iModelDb, definitionModelId, "DrawingCategory"))!; - const drawingCategorySelectorId = iModelDb.elements.queryElementIdByCode(CategorySelector.createCode(iModelDb, definitionModelId, "DrawingCategories"))!; + const drawingCategorySelectorId = iModelDb.elements.queryElementIdByCode( + CategorySelector.createCode(iModelDb, definitionModelId, "DrawingCategories"), + )!; const displayStyle2dId = iModelDb.elements.queryElementIdByCode(DisplayStyle2d.createCode(iModelDb, definitionModelId, "DisplayStyle2d"))!; const drawingViewId = iModelDb.elements.queryElementIdByCode(DrawingViewDefinition.createCode(iModelDb, definitionModelId, "Drawing View"))!; const geometryPartId = iModelDb.elements.queryElementIdByCode(GeometryPart.createCode(iModelDb, definitionModelId, "GeometryPart"))!; diff --git a/core/backend/src/test/element/ElementAspect.test.ts b/core/backend/src/test/element/ElementAspect.test.ts index 54d64a5a3906..5cbb1f5d7078 100644 --- a/core/backend/src/test/element/ElementAspect.test.ts +++ b/core/backend/src/test/element/ElementAspect.test.ts @@ -2,16 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64, Id64String } from "@itwin/core-bentley"; import { ElementAspectProps, ExternalSourceAspectProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; +import { assert, expect } from "chai"; import { - Element, ElementAspect, ElementMultiAspect, ElementUniqueAspect, ExternalSourceAspect, PhysicalElement, SnapshotDb, SpatialCategory, + Element, + ElementAspect, + ElementMultiAspect, + ElementUniqueAspect, + ExternalSourceAspect, + PhysicalElement, + SnapshotDb, + SpatialCategory, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; describe("ElementAspect", () => { - let iModel: SnapshotDb; before(() => { @@ -36,7 +42,10 @@ describe("ElementAspect", () => { assert.equal(aspect1.classFullName, "DgnPlatformTest:TestUniqueAspectNoHandler"); assert.equal(aspect1.asAny.testUniqueAspectProperty, "Aspect1-Updated"); assert.equal(aspect1.asAny.length, 1); - assert.equal(JSON.stringify(aspect1), `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect1), + `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); // Test getAspects with dot separator const aspect1DotSeparator: ElementAspect = iModel.elements.getAspects(element.id, "DgnPlatformTest.TestUniqueAspectNoHandler")[0]; @@ -45,7 +54,10 @@ describe("ElementAspect", () => { assert.equal(aspect1DotSeparator.classFullName, "DgnPlatformTest:TestUniqueAspectNoHandler"); assert.equal(aspect1DotSeparator.asAny.testUniqueAspectProperty, "Aspect1-Updated"); assert.equal(aspect1DotSeparator.asAny.length, 1); - assert.equal(JSON.stringify(aspect1DotSeparator), `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect1DotSeparator), + `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); // cross-check getAspects against getAspect const aspect1X: ElementAspect = iModel.elements.getAspect(aspect1.id); @@ -54,7 +66,10 @@ describe("ElementAspect", () => { assert.equal(aspect1X.classFullName, "DgnPlatformTest:TestUniqueAspectNoHandler"); assert.equal(aspect1X.asAny.testUniqueAspectProperty, "Aspect1-Updated"); assert.equal(aspect1X.asAny.length, 1); - assert.equal(JSON.stringify(aspect1X), `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect1X), + `{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); const aspect2: ElementAspect = iModel.elements.getAspects(element.id, "DgnPlatformTest:TestUniqueAspect")[0]; assert.exists(aspect2); @@ -62,7 +77,10 @@ describe("ElementAspect", () => { assert.equal(aspect2.classFullName, "DgnPlatformTest:TestUniqueAspect"); assert.equal(aspect2.asAny.testUniqueAspectProperty, "Aspect2-Updated"); assert.isUndefined(aspect2.asAny.length); - assert.equal(JSON.stringify(aspect2), `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect2), + `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); // Test getAspects with dot separator const aspect2DotSeparator: ElementAspect = iModel.elements.getAspects(element.id, "DgnPlatformTest.TestUniqueAspect")[0]; @@ -71,7 +89,10 @@ describe("ElementAspect", () => { assert.equal(aspect2DotSeparator.classFullName, "DgnPlatformTest:TestUniqueAspect"); assert.equal(aspect2DotSeparator.asAny.testUniqueAspectProperty, "Aspect2-Updated"); assert.isUndefined(aspect2DotSeparator.asAny.length); - assert.equal(JSON.stringify(aspect2DotSeparator), `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect2DotSeparator), + `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); // cross-check getAspects against getAspect const aspect2X: ElementAspect = iModel.elements.getAspect(aspect2.id); @@ -80,7 +101,10 @@ describe("ElementAspect", () => { assert.equal(aspect2X.classFullName, "DgnPlatformTest:TestUniqueAspect"); assert.equal(aspect2X.asAny.testUniqueAspectProperty, "Aspect2-Updated"); assert.isUndefined(aspect2X.asAny.length); - assert.equal(JSON.stringify(aspect2X), `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`); + assert.equal( + JSON.stringify(aspect2X), + `{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}`, + ); const uniqueAspects: ElementUniqueAspect[] = iModel.elements.getAspects(element.id, ElementUniqueAspect.classFullName); assert.equal(uniqueAspects.length, 2); @@ -92,8 +116,12 @@ describe("ElementAspect", () => { assert.equal(aspectX.schemaName, aspect.schemaName); assert.equal(aspectX.className, aspect.className); }); - assert.equal(JSON.stringify(uniqueAspects), `[{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}, - {"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(uniqueAspects), + `[{"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}, + {"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]` + .replace(/\s+/g, ""), + ); const multiAspectsA: ElementAspect[] = iModel.elements.getAspects(element.id, "DgnPlatformTest:TestMultiAspectNoHandler"); assert.exists(multiAspectsA); @@ -112,8 +140,12 @@ describe("ElementAspect", () => { assert.exists(aspectX.asAny.testMultiAspectProperty); assert.equal(aspectX.asAny.testMultiAspectProperty, aspect.asAny.testMultiAspectProperty); }); - assert.equal(JSON.stringify(multiAspectsA), `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(multiAspectsA), + `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]` + .replace(/\s+/g, ""), + ); // Test getAspects with dot separator const multiAspectsADotSeparator: ElementAspect[] = iModel.elements.getAspects(element.id, "DgnPlatformTest.TestMultiAspectNoHandler"); @@ -133,8 +165,12 @@ describe("ElementAspect", () => { assert.exists(aspectX.asAny.testMultiAspectProperty); assert.equal(aspectX.asAny.testMultiAspectProperty, aspect.asAny.testMultiAspectProperty); }); - assert.equal(JSON.stringify(multiAspectsADotSeparator), `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(multiAspectsADotSeparator), + `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]` + .replace(/\s+/g, ""), + ); const multiAspectsB: ElementAspect[] = iModel.elements.getAspects(element.id, "DgnPlatformTest:TestMultiAspect"); assert.exists(multiAspectsB); @@ -152,8 +188,12 @@ describe("ElementAspect", () => { assert.equal(aspectX.className, "TestMultiAspect"); assert.exists(aspectX.asAny.testMultiAspectProperty); }); - assert.equal(JSON.stringify(multiAspectsB), `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x3","testMultiAspectProperty":"Aspect6-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(multiAspectsB), + `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, + {"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x3","testMultiAspectProperty":"Aspect6-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]` + .replace(/\s+/g, ""), + ); const multiAspects: ElementAspect[] = iModel.elements.getAspects(element.id, ElementMultiAspect.classFullName); assert.equal(multiAspects.length, 4); @@ -165,24 +205,38 @@ describe("ElementAspect", () => { assert.equal(aspectX.schemaName, aspect.schemaName); assert.equal(aspectX.className, aspect.className); }); - assert.equal(JSON.stringify(multiAspects), `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, + assert.equal( + JSON.stringify(multiAspects), + `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x3","testMultiAspectProperty":"Aspect6-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]`.replace(/\s+/g, "")); + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]` + .replace(/\s+/g, ""), + ); const rootSubject = iModel.elements.getRootSubject(); - assert.equal(0, iModel.elements.getAspects(rootSubject.id, "DgnPlatformTest:TestUniqueAspect").length, "Don't expect DgnPlatformTest:TestUniqueAspect aspects on the root Subject"); - assert.equal(0, iModel.elements.getAspects(rootSubject.id, "DgnPlatformTest:TestMultiAspect").length, "Don't expect DgnPlatformTest:TestMultiAspect aspects on the root Subject"); + assert.equal( + 0, + iModel.elements.getAspects(rootSubject.id, "DgnPlatformTest:TestUniqueAspect").length, + "Don't expect DgnPlatformTest:TestUniqueAspect aspects on the root Subject", + ); + assert.equal( + 0, + iModel.elements.getAspects(rootSubject.id, "DgnPlatformTest:TestMultiAspect").length, + "Don't expect DgnPlatformTest:TestMultiAspect aspects on the root Subject", + ); assert.equal(0, iModel.elements.getAspects(rootSubject.id).length, "Don't expect any aspects on the root Subject"); // The 'Element' property is introduced by ElementUniqueAspect and ElementMultiAspect, but is not available at the ElementAspect base class. // Since we're now using instance queries to query ElementUniqueAspect and ElementMultiAspect directly in getAspects(), we can provide ElementAspect to the function as well. - const aspectList = `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, + const aspectList = + `[{"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x2","testMultiAspectProperty":"Aspect5-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"DgnPlatformTest:TestMultiAspect","id":"0x3","testMultiAspectProperty":"Aspect6-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, {"classFullName":"DgnPlatformTest:TestUniqueAspect","id":"0x1","testUniqueAspectProperty":"Aspect2-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}, - {"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`.replace(/\s+/g, ""); + {"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"Aspect1-Updated","length":1,"element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]` + .replace(/\s+/g, ""); const aspects: ElementAspect[] = iModel.elements.getAspects(element.id, ElementAspect.classFullName); assert.equal(aspects.length, 6); @@ -198,7 +252,9 @@ describe("ElementAspect", () => { assert.exists(element); assert.isTrue(element instanceof PhysicalElement); - interface Props extends ElementAspectProps { testMultiAspectProperty: string } + interface Props extends ElementAspectProps { + testMultiAspectProperty: string; + } const aspectProps: Props = { classFullName: "DgnPlatformTest:TestMultiAspectNoHandler", element: { id: element.id }, @@ -207,9 +263,13 @@ describe("ElementAspect", () => { iModel.elements.insertAspect(aspectProps); let aspects: ElementAspect[] = iModel.elements.getAspects(element.id, aspectProps.classFullName); assert.isAtLeast(aspects.length, 1); - assert.equal(JSON.stringify(aspects), `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, + assert.equal( + JSON.stringify(aspects), + `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x21","testMultiAspectProperty":"MultiAspectInsertTest1","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`.replace(/\s+/g, "")); + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x21","testMultiAspectProperty":"MultiAspectInsertTest1","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]` + .replace(/\s+/g, ""), + ); const numAspects = aspects.length; let found: boolean = false; @@ -230,16 +290,24 @@ describe("ElementAspect", () => { assert.equal(aspectsUpdated.length, aspects.length); assert.equal(aspectsUpdated[foundIndex].asAny.testMultiAspectProperty, "MultiAspectInsertTest1-Updated"); // Check if aspect was updated - assert.equal(JSON.stringify(aspectsUpdated), `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, + assert.equal( + JSON.stringify(aspectsUpdated), + `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x21","testMultiAspectProperty":"MultiAspectInsertTest1-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`.replace(/\s+/g, "")); + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x21","testMultiAspectProperty":"MultiAspectInsertTest1-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsMultiAspects"}}]` + .replace(/\s+/g, ""), + ); iModel.elements.deleteAspect(aspects[foundIndex].id); aspects = iModel.elements.getAspects(element.id, aspectProps.classFullName); assert.equal(numAspects, aspects.length + 1); // Check if aspect was deleted - assert.equal(JSON.stringify(aspects), `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, - {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(aspects), + `[{"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x4","testMultiAspectProperty":"Aspect3-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}, + {"classFullName":"DgnPlatformTest:TestMultiAspectNoHandler","id":"0x5","testMultiAspectProperty":"Aspect4-Updated","element":{"id":"0x17","relClassName":"DgnPlatformTest.TestElement"}}]` + .replace(/\s+/g, ""), + ); }); it("should be able to insert, update, and delete UniqueAspects", () => { @@ -256,14 +324,20 @@ describe("ElementAspect", () => { const aspects: ElementAspect[] = iModel.elements.getAspects(element.id, aspectProps.classFullName); assert.isTrue(aspects.length === 1); assert.equal(aspects[0].asAny.testUniqueAspectProperty, aspectProps.testUniqueAspectProperty); - assert.equal(JSON.stringify(aspects), `[{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"UniqueAspectInsertTest1","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`); + assert.equal( + JSON.stringify(aspects), + `[{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"UniqueAspectInsertTest1","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`, + ); aspects[0].asAny.testUniqueAspectProperty = "UniqueAspectInsertTest1-Updated"; iModel.elements.updateAspect(aspects[0].toJSON()); const aspectsUpdated: ElementAspect[] = iModel.elements.getAspects(element.id, aspectProps.classFullName); assert.equal(aspectsUpdated.length, 1); assert.equal(aspectsUpdated[0].asAny.testUniqueAspectProperty, "UniqueAspectInsertTest1-Updated"); - assert.equal(JSON.stringify(aspectsUpdated), `[{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"UniqueAspectInsertTest1-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`); + assert.equal( + JSON.stringify(aspectsUpdated), + `[{"classFullName":"DgnPlatformTest:TestUniqueAspectNoHandler","id":"0x6","testUniqueAspectProperty":"UniqueAspectInsertTest1-Updated","element":{"id":"0x17","relClassName":"BisCore.ElementOwnsUniqueAspect"}}]`, + ); iModel.elements.deleteAspect(aspects[0].id); try { @@ -301,7 +375,10 @@ describe("ElementAspect", () => { const aspects: ElementAspect[] = iModelDb.elements.getAspects(elementId, aspectProps.classFullName); assert.equal(aspects.length, 1); - assert.equal(JSON.stringify(aspects), `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x21","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","version":"1.0","checksum":"1","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`); + assert.equal( + JSON.stringify(aspects), + `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x21","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","version":"1.0","checksum":"1","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`, + ); expect(aspects[0]).to.deep.subsetEqual(aspectProps, { normalizeClassNameProps: true }); expect(aspectJson).to.deep.subsetEqual(aspectProps, { normalizeClassNameProps: true }); @@ -373,19 +450,27 @@ describe("ElementAspect", () => { e1Aspects.forEach((x) => { assert.isTrue(findInProps(x, e1AspectProps)); }); - assert.equal(JSON.stringify(e1Aspects), `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x21","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}, + assert.equal( + JSON.stringify(e1Aspects), + `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x21","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"BisCore:ExternalSourceAspect","id":"0x22","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"BisCore:ExternalSourceAspect","id":"0x23","scope":{"id":"0x11","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}, {"classFullName":"BisCore:ExternalSourceAspect","id":"0x24","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"B","kind":"Letter","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}, - {"classFullName":"BisCore:ExternalSourceAspect","id":"0x25","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"C","kind":"Kind2","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`.replace(/\s+/g, "")); + {"classFullName":"BisCore:ExternalSourceAspect","id":"0x25","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"C","kind":"Kind2","element":{"id":"0x11","relClassName":"BisCore.ElementOwnsMultiAspects"}}]` + .replace(/\s+/g, ""), + ); const e2Aspects: ElementAspect[] = iModelDb.elements.getAspects(e2, aspectProps.classFullName); assert.equal(e2Aspects.length, e2AspectProps.length); e2Aspects.forEach((x) => { assert.isTrue(findInProps(x, e2AspectProps)); }); - assert.equal(JSON.stringify(e2Aspects), `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x26","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x13","relClassName":"BisCore.ElementOwnsMultiAspects"}}, - {"classFullName":"BisCore:ExternalSourceAspect","id":"0x27","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"C","kind":"Letter","element":{"id":"0x13","relClassName":"BisCore.ElementOwnsMultiAspects"}}]`.replace(/\s+/g, "")); + assert.equal( + JSON.stringify(e2Aspects), + `[{"classFullName":"BisCore:ExternalSourceAspect","id":"0x26","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"A","kind":"Letter","element":{"id":"0x13","relClassName":"BisCore.ElementOwnsMultiAspects"}}, + {"classFullName":"BisCore:ExternalSourceAspect","id":"0x27","scope":{"id":"0x1","relClassName":"BisCore.ElementScopesExternalSourceIdentifier"},"identifier":"C","kind":"Letter","element":{"id":"0x13","relClassName":"BisCore.ElementOwnsMultiAspects"}}]` + .replace(/\s+/g, ""), + ); const allA = ExternalSourceAspect.findAllBySource(iModelDb, scopeId1, kind, "A"); assert.equal(allA.filter((x) => x.elementId === e1).length, 2, "there are two A's in scope 1 on e1"); @@ -410,5 +495,4 @@ describe("ElementAspect", () => { assert.equal(ExternalSourceAspect.findAllBySource(iModelDb, scopeId1, kind, "").length, 0); }); - }); diff --git a/core/backend/src/test/element/ElementDependencyGraph.test.ts b/core/backend/src/test/element/ElementDependencyGraph.test.ts index 1467dc85ea06..06c09aa444ea 100644 --- a/core/backend/src/test/element/ElementDependencyGraph.test.ts +++ b/core/backend/src/test/element/ElementDependencyGraph.test.ts @@ -4,18 +4,26 @@ *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/naming-convention */ -import { assert } from "chai"; -import * as fs from "fs"; -import * as path from "path"; import { Guid, Id64Array, Id64String, Logger, OpenMode } from "@itwin/core-bentley"; import { - CodeScopeSpec, CodeSpec, ColorByName, DomainOptions, GeometryStreamBuilder, IModel, RelatedElementProps, RelationshipProps, SubCategoryAppearance, + CodeScopeSpec, + CodeSpec, + ColorByName, + DomainOptions, + GeometryStreamBuilder, + IModel, + RelatedElementProps, + RelationshipProps, + SubCategoryAppearance, UpgradeOptions, } from "@itwin/core-common"; import { LineSegment3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert } from "chai"; +import * as fs from "fs"; +import * as path from "path"; import { _nativeDb, ChannelControl, ElementDrivesElementProps, IModelJsFs, PhysicalModel, SpatialCategory, StandaloneDb } from "../../core-backend"; -import { IModelTestUtils, TestElementDrivesElement, TestPhysicalObject, TestPhysicalObjectProps } from "../IModelTestUtils"; import { IModelNative } from "../../internal/NativePlatform"; +import { IModelTestUtils, TestElementDrivesElement, TestPhysicalObject, TestPhysicalObjectProps } from "../IModelTestUtils"; export function copyFile(newName: string, pathToCopy: string): string { const newPath = path.join(path.dirname(pathToCopy), newName); @@ -106,8 +114,12 @@ class TestHelper { this.db.elements.updateElement(ed2.toJSON()); } - public fmtElem(elId: Id64String) { return this.db.elements.getElement(elId).code.value; } - public fmtRel(props: RelationshipProps) { return `${props.classFullName} ${this.fmtElem(props.sourceId)} --> ${this.fmtElem(props.targetId)}`; } + public fmtElem(elId: Id64String) { + return this.db.elements.getElement(elId).code.value; + } + public fmtRel(props: RelationshipProps) { + return `${props.classFullName} ${this.fmtElem(props.sourceId)} --> ${this.fmtElem(props.targetId)}`; + } public resetDependencyResults() { this.dres = new DependencyCallbackResults(); @@ -165,7 +177,12 @@ describe("ElementDependencyGraph", () => { imodel.channels.addAllowedChannel(ChannelControl.sharedChannelName); const physicalModelId = PhysicalModel.insert(imodel, IModel.rootSubjectId, "EDGTestModel"); const codeSpecId = imodel.codeSpecs.insert(CodeSpec.create(imodel, "EDGTestCodeSpec", CodeScopeSpec.Type.Model)); - const spatialCategoryId = SpatialCategory.insert(imodel, IModel.dictionaryId, "EDGTestSpatialCategory", new SubCategoryAppearance({ color: ColorByName.darkRed })); + const spatialCategoryId = SpatialCategory.insert( + imodel, + IModel.dictionaryId, + "EDGTestSpatialCategory", + new SubCategoryAppearance({ color: ColorByName.darkRed }), + ); dbInfo = { physicalModelId, codeSpecId, spatialCategoryId, seedFileName: testFileName }; imodel.saveChanges(""); imodel[_nativeDb].deleteAllTxns(); @@ -328,7 +345,11 @@ describe("ElementDependencyGraph", () => { helper.db.saveChanges(); // get the elements into the iModel const ede_material_materialDepthRange = TestElementDrivesElement.create(helper.db, material, materialDepthRange); - const ede_boreholeSource_groundGeneration = TestElementDrivesElement.create(helper.db, boreholeSource, groundGeneration); + const ede_boreholeSource_groundGeneration = TestElementDrivesElement.create( + helper.db, + boreholeSource, + groundGeneration, + ); for (const ede of [ede_material_materialDepthRange, ede_boreholeSource_groundGeneration]) { ede.insert(); } @@ -473,5 +494,4 @@ describe("ElementDependencyGraph", () => { helper.terminate(); }); - }); diff --git a/core/backend/src/test/element/ElementRoundTrip.test.ts b/core/backend/src/test/element/ElementRoundTrip.test.ts index 9cacb1dccc2e..43f24ca1e9cb 100644 --- a/core/backend/src/test/element/ElementRoundTrip.test.ts +++ b/core/backend/src/test/element/ElementRoundTrip.test.ts @@ -2,13 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; import { - BriefcaseIdValue, Code, ColorDef, ElementAspectProps, ElementGeometry, GeometricElementProps, GeometryStreamProps, IModel, PhysicalElementProps, - Placement3dProps, QueryRowFormat, SubCategoryAppearance, + BriefcaseIdValue, + Code, + ColorDef, + ElementAspectProps, + ElementGeometry, + GeometricElementProps, + GeometryStreamProps, + IModel, + PhysicalElementProps, + Placement3dProps, + QueryRowFormat, + SubCategoryAppearance, } from "@itwin/core-common"; import { Angle, Arc3d, Cone, IModelJson as GeomJson, LineSegment3d, Point2d, Point3d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, PhysicalModel, PhysicalObject, SnapshotDb, SpatialCategory } from "../../core-backend"; import { ElementRefersToElements } from "../../Relationship"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -50,13 +60,13 @@ interface IPrimitiveArray extends IPrimitiveArrayBase { array_st?: ComplexStruct[]; } -interface ComplexStruct extends IPrimitiveArrayBase, IPrimitiveBase { } +interface ComplexStruct extends IPrimitiveArrayBase, IPrimitiveBase {} -interface TestElement extends IPrimitive, IPrimitiveArray, GeometricElementProps { } +interface TestElement extends IPrimitive, IPrimitiveArray, GeometricElementProps {} -interface TestElementAspect extends IPrimitive, IPrimitiveArray, ElementAspectProps { } +interface TestElementAspect extends IPrimitive, IPrimitiveArray, ElementAspectProps {} -interface TestElementRefersToElements extends IPrimitive, IPrimitiveArray, ElementRefersToElements { } +interface TestElementRefersToElements extends IPrimitive, IPrimitiveArray, ElementRefersToElements {} function verifyPrimitiveBase(actualValue: IPrimitiveBase, expectedValue: IPrimitiveBase) { if (expectedValue.i !== undefined) @@ -74,24 +84,24 @@ function verifyPrimitiveBase(actualValue: IPrimitiveBase, expectedValue: IPrimit if (expectedValue.p2d) { assert.equal(actualValue.p2d?.x, expectedValue.p2d.x, "'Point2d.x' type property did not roundtrip as expected"); assert.equal(actualValue.p2d?.y, expectedValue.p2d.y, "'Point2d.y' type property did not roundtrip as expected"); - } else if(expectedValue.p2d === null) { + } else if (expectedValue.p2d === null) { assert.equal(actualValue.p2d, expectedValue.p2d, "'Point2d' type property did not roundtrip as expected."); } if (expectedValue.p3d) { assert.equal(actualValue.p3d?.x, expectedValue.p3d.x, "'Point3d.x' type property did not roundtrip as expected"); assert.equal(actualValue.p3d?.y, expectedValue.p3d.y, "'Point3d.y' type property did not roundtrip as expected"); assert.equal(actualValue.p3d?.z, expectedValue.p3d.z, "'Point3d.z' type property did not roundtrip as expected"); - } else if(expectedValue.p3d === null) { + } else if (expectedValue.p3d === null) { assert.equal(actualValue.p3d, expectedValue.p3d, "'Point3d' type property did not roundtrip as expected."); } if (expectedValue.bin) { assert.isTrue(blobEqual(actualValue.bin, expectedValue.bin), "'binary' type property did not roundtrip as expected"); - } else if(expectedValue.bin === null) { + } else if (expectedValue.bin === null) { assert.equal(actualValue.bin, expectedValue.bin, "'binary' type property did not roundtrip as expected."); } if (expectedValue.g) { expect(actualValue.g, "'geometry' type property did not roundtrip as expected.").to.deep.equal(expectedValue.g); - } else if(expectedValue.g === null) { + } else if (expectedValue.g === null) { assert.equal(actualValue.g, expectedValue.g, "'geometry' type property did not roundtrip as expected."); } } @@ -100,13 +110,13 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu if (expectedValue.array_bin) { assert.equal(actualValue.array_bin!.length, expectedValue.array_bin.length, "'binary[].length' array length mismatch"); expectedValue.array_bin.forEach((value, index) => { - if(value) { + if (value) { assert.isTrue(blobEqual(actualValue.array_bin![index], value), "'binary[]' type property did not roundtrip as expected"); - } else if(value === null) { + } else if (value === null) { assert.equal(actualValue.array_bin![index], value, "'binary[]' type property did not roundtrip as expected"); } }); - } else if(expectedValue.array_bin === null) { + } else if (expectedValue.array_bin === null) { assert.equal(actualValue.array_bin, expectedValue.array_bin, "'binary[]' type property did not roundtrip as expected."); } @@ -115,7 +125,7 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_i.forEach((value, index) => { assert.equal(actualValue.array_i![index], value, "'integer[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_i === null) { + } else if (expectedValue.array_i === null) { assert.equal(actualValue.array_i, expectedValue.array_i, "'integer[]' type property did not roundtrip as expected."); } @@ -124,7 +134,7 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_l.forEach((value, index) => { assert.equal(actualValue.array_l![index], value, "'long[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_l === null) { + } else if (expectedValue.array_l === null) { assert.equal(actualValue.array_l, expectedValue.array_l, "'long[]' type property did not roundtrip as expected."); } @@ -133,7 +143,7 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_d.forEach((value, index) => { assert.equal(actualValue.array_d![index], value, "'double[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_d === null) { + } else if (expectedValue.array_d === null) { assert.equal(actualValue.array_d, expectedValue.array_d, "'double[]' type property did not roundtrip as expected."); } @@ -142,7 +152,7 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_b.forEach((value, index) => { assert.equal(actualValue.array_b![index], value, "'boolean[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_b === null) { + } else if (expectedValue.array_b === null) { assert.equal(actualValue.array_b, expectedValue.array_b, "'boolean[]' type property did not roundtrip as expected."); } @@ -151,20 +161,20 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_dt.forEach((value, index) => { assert.equal(actualValue.array_dt![index], value, "'dateTime[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_dt === null) { + } else if (expectedValue.array_dt === null) { assert.equal(actualValue.array_dt, expectedValue.array_dt, "'dateTime[]' type property did not roundtrip as expected."); } if (expectedValue.array_g) { assert.equal(actualValue.array_g!.length, expectedValue.array_g.length, "'geometry[].length' array length mismatch"); expectedValue.array_g.forEach((value, index) => { - if(value) { + if (value) { expect(actualValue.array_g![index], "'geometry[]' type property did not roundtrip as expected").to.deep.equal(value); - } else if(value === null) { + } else if (value === null) { assert.equal(actualValue.array_g![index], value, "'geometry[]' type property did not roundtrip as expected"); } }); - } else if(expectedValue.array_g === null) { + } else if (expectedValue.array_g === null) { assert.equal(actualValue.array_g, expectedValue.array_g, "'geometry[]' type property did not roundtrip as expected."); } @@ -173,7 +183,7 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu expectedValue.array_s.forEach((value, index) => { assert.equal(actualValue.array_s![index], value, "'string[]' type property did not roundtrip as expected"); }); - } else if(expectedValue.array_s === null) { + } else if (expectedValue.array_s === null) { assert.equal(actualValue.array_s, expectedValue.array_s, "'string[]' type property did not roundtrip as expected."); } @@ -187,22 +197,22 @@ function verifyPrimitiveArrayBase(actualValue: IPrimitiveArrayBase, expectedValu assert.equal(actualValue.array_p2d![index], value, "'point2d[]' type property did not roundtrip as expected."); } }); - } else if(expectedValue.array_p2d === null) { + } else if (expectedValue.array_p2d === null) { assert.equal(actualValue.array_p2d, expectedValue.array_p2d, "'point2d[]' type property did not roundtrip as expected."); } if (expectedValue.array_p3d) { assert.equal(actualValue.array_p3d!.length, expectedValue.array_p3d.length, "'point3d[].length' array length mismatch"); expectedValue.array_p3d.forEach((value, index) => { - if(value) { + if (value) { assert.equal(actualValue.array_p3d![index].x, value.x, "'point3d[].x' type property did not roundtrip as expected"); assert.equal(actualValue.array_p3d![index].y, value.y, "'point3d[].y' type property did not roundtrip as expected"); assert.equal(actualValue.array_p3d![index].z, value.z, "'point3d[].z' type property did not roundtrip as expected"); - } else if(value === null) { + } else if (value === null) { assert.equal(actualValue.array_p3d![index], value, "'point3d[]' type property did not roundtrip as expected."); } }); - } else if(expectedValue.array_p3d === null) { + } else if (expectedValue.array_p3d === null) { assert.equal(actualValue.array_p3d, expectedValue.array_p3d, "'point3d[]' type property did not roundtrip as expected."); } } @@ -212,7 +222,7 @@ function verifyPrimitive(actualValue: IPrimitive, expectedValue: IPrimitive) { if (expectedValue.st) { verifyPrimitive(actualValue.st!, expectedValue.st); verifyPrimitiveArray(actualValue.st!, expectedValue.st); - } else if(expectedValue.st === null) { + } else if (expectedValue.st === null) { assert.equal(actualValue.st, expectedValue.st, "'ComplexStruct' type property did not roundtrip as expected."); } } @@ -225,7 +235,7 @@ function verifyPrimitiveArray(actualValue: IPrimitiveArray, expectedValue: IPrim verifyPrimitiveBase(lhs, expectedValue.array_st![i]); verifyPrimitiveArrayBase(lhs, expectedValue.array_st![i]); }); - } else if(expectedValue.array_st === null) { + } else if (expectedValue.array_st === null) { assert.equal(actualValue.array_st, expectedValue.array_st, "'ComplexStruct[]' type property did not roundtrip as expected."); } } @@ -294,7 +304,13 @@ function blobEqual(lhs: any, rhs: any) { return true; } -function initElementRefersToElementsProps(className: string, _iModelName: IModelDb, elId1: Id64String, elId2: Id64String, autoHandledProp: any): TestElementRefersToElements { +function initElementRefersToElementsProps( + className: string, + _iModelName: IModelDb, + elId1: Id64String, + elId2: Id64String, + autoHandledProp: any, +): TestElementRefersToElements { // Create props const result: TestElementRefersToElements = { classFullName: `ElementRoundTripTest:${className}`, @@ -525,8 +541,12 @@ describe("Element and ElementAspect roundtrip test for all type of properties", IModelTestUtils.createAndInsertPhysicalPartitionAndModel(imodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(imodel, IModel.dictionaryId, categoryName); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(imodel, IModel.dictionaryId, categoryName, - new SubCategoryAppearance({ color: ColorDef.create("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + imodel, + IModel.dictionaryId, + categoryName, + new SubCategoryAppearance({ color: ColorDef.create("rgb(255,0,0)").toJSON() }), + ); imodel.saveChanges(); imodel.close(); @@ -605,7 +625,12 @@ describe("Element and ElementAspect roundtrip test for all type of properties", imodel.close(); }); - async function verifyElementAspect(elementAspect: ElementAspectProps, elementId: string, expectedAspectFullName: string, iModel: SnapshotDb): Promise{ + async function verifyElementAspect( + elementAspect: ElementAspectProps, + elementId: string, + expectedAspectFullName: string, + iModel: SnapshotDb, + ): Promise { // Verify updated values const updatedAspectValue: ElementAspectProps[] = iModel.elements.getAspects(elementId, expectedAspectFullName).map((x) => x.toJSON()); assert.equal(updatedAspectValue.length, 1); @@ -613,7 +638,9 @@ describe("Element and ElementAspect roundtrip test for all type of properties", // Verify via a concurrent query let rowCount = 0; - for await (const row of iModel.createQueryReader("SELECT * FROM ts.TestElementAspect", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT * FROM ts.TestElementAspect", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }) + ) { verifyTestElementAspect(row.toRow() as TestElementAspect, elementAspect); rowCount++; } @@ -712,14 +739,21 @@ describe("Element and ElementAspect roundtrip test for all type of properties", imodel.saveChanges(); // verify inserted properties - const actualRelationshipValue = imodel.relationships.getInstance(expectedRelationshipValue.classFullName, relationshipId); + const actualRelationshipValue = imodel.relationships.getInstance( + expectedRelationshipValue.classFullName, + relationshipId, + ); assert.exists(actualRelationshipValue); verifyTestElementRefersToElements(actualRelationshipValue, expectedRelationshipValue); // verify via concurrent query let rowCount = 0; - for await (const row of imodel.createQueryReader("SELECT * FROM ts.TestElementRefersToElements", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of imodel.createQueryReader("SELECT * FROM ts.TestElementRefersToElements", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { const val = row.toRow() as TestElementRefersToElements; verifyTestElementRefersToElements(val, expectedRelationshipValue); rowCount++; @@ -752,7 +786,11 @@ describe("Element and ElementAspect roundtrip test for all type of properties", // verify via concurrent query rowCount = 0; - for await (const row of imodel.createQueryReader("SELECT * FROM ts.TestElementRefersToElements", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of imodel.createQueryReader("SELECT * FROM ts.TestElementRefersToElements", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { verifyTestElementRefersToElements(row.toRow() as TestElementRefersToElements, updatedExpectedValue); rowCount++; } diff --git a/core/backend/src/test/element/ExcludedElements.test.ts b/core/backend/src/test/element/ExcludedElements.test.ts index dc7d225df25f..db7953e6dbc9 100644 --- a/core/backend/src/test/element/ExcludedElements.test.ts +++ b/core/backend/src/test/element/ExcludedElements.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { BisCodeSpec, DisplayStyleProps, IModel, QueryBinder, QueryRowFormat } from "@itwin/core-common"; +import { expect } from "chai"; import { DisplayStyle3d, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -14,7 +14,10 @@ describe("ExcludedElements", () => { let imodel: SnapshotDb; before(() => { - imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "test.bim"), IModelTestUtils.resolveAssetFile("test.bim")); + imodel = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "test.bim"), + IModelTestUtils.resolveAssetFile("test.bim"), + ); }); after(() => { @@ -42,7 +45,11 @@ describe("ExcludedElements", () => { imodel.saveChanges(); const rows: any[] = []; - for await (const queryRow of imodel.createQueryReader("SELECT jsonProperties FROM bis.Element WHERE ECInstanceId=?", QueryBinder.from([styleId]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) + for await ( + const queryRow of imodel.createQueryReader("SELECT jsonProperties FROM bis.Element WHERE ECInstanceId=?", QueryBinder.from([styleId]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) rows.push(queryRow.toRow()); expect(rows.length).to.equal(1); diff --git a/core/backend/src/test/element/ExternalSource.test.ts b/core/backend/src/test/element/ExternalSource.test.ts index a788e177a736..d8aacf54376d 100644 --- a/core/backend/src/test/element/ExternalSource.test.ts +++ b/core/backend/src/test/element/ExternalSource.test.ts @@ -3,20 +3,37 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Id64String } from "@itwin/core-bentley"; import { - Code, ExternalSourceAttachmentProps, ExternalSourceProps, IModel, RepositoryLinkProps, SynchronizationConfigLinkProps, + Code, + ExternalSourceAttachmentProps, + ExternalSourceProps, + IModel, + RepositoryLinkProps, + SynchronizationConfigLinkProps, } from "@itwin/core-common"; +import { assert } from "chai"; import { - ExternalSource, ExternalSourceAttachment, ExternalSourceAttachmentAttachesSource, ExternalSourceGroup, ExternalSourceGroupGroupsSources, - ExternalSourceIsInRepository, ExternalSourceOwnsAttachments, FolderContainsRepositories, FolderLink, IModelDb, LinkElement, RepositoryLink, - SnapshotDb, SynchronizationConfigLink, SynchronizationConfigProcessesSources, SynchronizationConfigSpecifiesRootSources, + ExternalSource, + ExternalSourceAttachment, + ExternalSourceAttachmentAttachesSource, + ExternalSourceGroup, + ExternalSourceGroupGroupsSources, + ExternalSourceIsInRepository, + ExternalSourceOwnsAttachments, + FolderContainsRepositories, + FolderLink, + IModelDb, + LinkElement, + RepositoryLink, + SnapshotDb, + SynchronizationConfigLink, + SynchronizationConfigProcessesSources, + SynchronizationConfigSpecifiesRootSources, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; describe("ExternalSource", () => { - it("should create elements and relationships like an iModel Connector would", () => { const iModelFileName = IModelTestUtils.prepareOutputFile("ExternalSource", "ExternalSource.bim"); const iModelDb = SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: "ExternalSource Test" } }); @@ -41,10 +58,26 @@ describe("ExternalSource", () => { const modelB = insertExternalSource(iModelDb, repositoryB, "B"); const modelC = insertExternalSource(iModelDb, repositoryC, "C"); - iModelDb.relationships.insertInstance({ classFullName: SynchronizationConfigSpecifiesRootSources.classFullName, sourceId: syncJob, targetId: modelM }); - iModelDb.relationships.insertInstance({ classFullName: SynchronizationConfigProcessesSources.classFullName, sourceId: syncJob, targetId: modelA }); - iModelDb.relationships.insertInstance({ classFullName: SynchronizationConfigProcessesSources.classFullName, sourceId: syncJob, targetId: modelB }); - iModelDb.relationships.insertInstance({ classFullName: SynchronizationConfigProcessesSources.classFullName, sourceId: syncJob, targetId: modelC }); + iModelDb.relationships.insertInstance({ + classFullName: SynchronizationConfigSpecifiesRootSources.classFullName, + sourceId: syncJob, + targetId: modelM, + }); + iModelDb.relationships.insertInstance({ + classFullName: SynchronizationConfigProcessesSources.classFullName, + sourceId: syncJob, + targetId: modelA, + }); + iModelDb.relationships.insertInstance({ + classFullName: SynchronizationConfigProcessesSources.classFullName, + sourceId: syncJob, + targetId: modelB, + }); + iModelDb.relationships.insertInstance({ + classFullName: SynchronizationConfigProcessesSources.classFullName, + sourceId: syncJob, + targetId: modelC, + }); const group1 = insertExternalSourceGroup(iModelDb, "Group1"); iModelDb.relationships.insertInstance({ classFullName: ExternalSourceGroupGroupsSources.classFullName, sourceId: group1, targetId: modelA }); diff --git a/core/backend/src/test/element/NullStructArray.test.ts b/core/backend/src/test/element/NullStructArray.test.ts index 04ddd82e1bb9..1cbb443a70a5 100644 --- a/core/backend/src/test/element/NullStructArray.test.ts +++ b/core/backend/src/test/element/NullStructArray.test.ts @@ -2,20 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64, Id64String } from "@itwin/core-bentley"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, IModel, - SubCategoryAppearance, -} from "@itwin/core-common"; -import { _nativeDb, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "../../core-backend"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; +import { assert, expect } from "chai"; +import { _nativeDb, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; interface TestElement extends GeometricElementProps { - addresses: [null, {city: "Pune", zip: 28}]; + addresses: [null, { city: "Pune", zip: 28 }]; } -function initElemProps( _iModelName: IModelDb, modId: Id64String, catId: Id64String, autoHandledProp: any): GeometricElementProps { +function initElemProps(_iModelName: IModelDb, modId: Id64String, catId: Id64String, autoHandledProp: any): GeometricElementProps { // Create props const elementProps: GeometricElementProps = { classFullName: "Test:Foo", @@ -62,8 +59,12 @@ describe("Insert Null elements in Struct Array, and ensure they are returned whi let spatialCategoryId = SpatialCategory.queryCategoryIdByName(imodel, IModel.dictionaryId, categoryName); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(imodel, IModel.dictionaryId, categoryName, - new SubCategoryAppearance({ color: ColorDef.create("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + imodel, + IModel.dictionaryId, + categoryName, + new SubCategoryAppearance({ color: ColorDef.create("rgb(255,0,0)").toJSON() }), + ); imodel.saveChanges(); imodel.close(); @@ -76,8 +77,8 @@ describe("Insert Null elements in Struct Array, and ensure they are returned whi const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(imodel, Code.createEmpty(), true); // create element with auto handled properties - const expectedValue = initElemProps( imodel, newModelId, spatialCategoryId!, { - addresses: [null, {city: "Pune", zip: 28}], + const expectedValue = initElemProps(imodel, newModelId, spatialCategoryId!, { + addresses: [null, { city: "Pune", zip: 28 }], }) as TestElement; // insert a element @@ -93,5 +94,4 @@ describe("Insert Null elements in Struct Array, and ensure they are returned whi imodel.close(); }); - }); diff --git a/core/backend/src/test/element/UrlLink.test.ts b/core/backend/src/test/element/UrlLink.test.ts index 291bee58be20..90a7904deecf 100644 --- a/core/backend/src/test/element/UrlLink.test.ts +++ b/core/backend/src/test/element/UrlLink.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; +import { assert } from "chai"; import { IModelTestUtils } from "../IModelTestUtils"; import { IModel, RepositoryLinkProps } from "@itwin/core-common"; diff --git a/core/backend/src/test/hubaccess/BriefcaseManager.test.ts b/core/backend/src/test/hubaccess/BriefcaseManager.test.ts index 50c83d7ed0ef..a69a1cfc76f3 100644 --- a/core/backend/src/test/hubaccess/BriefcaseManager.test.ts +++ b/core/backend/src/test/hubaccess/BriefcaseManager.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Guid } from "@itwin/core-bentley"; import { BriefcaseIdValue } from "@itwin/core-common"; +import { assert } from "chai"; +import { _nativeDb, ChannelControl } from "../../core-backend"; import { Element } from "../../Element"; +import { HubMock } from "../../HubMock"; import { HubWrappers, IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; -import { HubMock } from "../../HubMock"; import { TestChangeSetUtility } from "../TestChangeSetUtility"; -import { _nativeDb, ChannelControl } from "../../core-backend"; describe("BriefcaseManager", async () => { const testITwinId: string = Guid.createValue(); diff --git a/core/backend/src/test/hubaccess/CheckpointManager.test.ts b/core/backend/src/test/hubaccess/CheckpointManager.test.ts index 25cbc0488a2a..5c158f91a702 100644 --- a/core/backend/src/test/hubaccess/CheckpointManager.test.ts +++ b/core/backend/src/test/hubaccess/CheckpointManager.test.ts @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Guid } from "@itwin/core-bentley"; import { assert } from "chai"; import * as path from "path"; import * as sinon from "sinon"; -import { Guid } from "@itwin/core-bentley"; import { CheckpointManager, V1CheckpointManager, V2CheckpointManager } from "../../CheckpointManager"; import { _nativeDb, IModelHost } from "../../core-backend"; +import { HubMock } from "../../HubMock"; import { SnapshotDb } from "../../IModelDb"; import { IModelJsFs } from "../../IModelJsFs"; import { IModelTestUtils } from "../IModelTestUtils"; -import { HubMock } from "../../HubMock"; describe("V1 Checkpoint Manager", () => { it("empty props", async () => { @@ -59,7 +59,7 @@ describe("V1 Checkpoint Manager", () => { it("should fix invalid dbGuid during download", async () => { const dbPath = IModelTestUtils.prepareOutputFile("IModel", "TestCheckpoint.bim"); const snapshot = SnapshotDb.createEmpty(dbPath, { rootSubject: { name: "test" } }); - const iModelId = Guid.createValue(); // This is wrong - it should be `snapshot.getGuid()`! + const iModelId = Guid.createValue(); // This is wrong - it should be `snapshot.getGuid()`! const iTwinId = Guid.createValue(); const changeset = IModelTestUtils.generateChangeSetId(); snapshot[_nativeDb].setITwinId(iTwinId); @@ -85,7 +85,6 @@ describe("V1 Checkpoint Manager", () => { }); describe("Checkpoint Manager", () => { - afterEach(() => { sinon.restore(); }); diff --git a/core/backend/src/test/imageData.ts b/core/backend/src/test/imageData.ts index 289453acf827..37f6b40eb9cc 100644 --- a/core/backend/src/test/imageData.ts +++ b/core/backend/src/test/imageData.ts @@ -5,7 +5,139 @@ import { Buffer } from "node:buffer"; -const samplePngTextureData = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]; +const samplePngTextureData = [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, +]; const samplePngTextureDataBase64 = Buffer.from(samplePngTextureData).toString("base64"); /** diff --git a/core/backend/src/test/imodel/ElementTreeWalker.test.ts b/core/backend/src/test/imodel/ElementTreeWalker.test.ts index 1a3aa76168a8..c7a8a037b5da 100644 --- a/core/backend/src/test/imodel/ElementTreeWalker.test.ts +++ b/core/backend/src/test/imodel/ElementTreeWalker.test.ts @@ -8,7 +8,25 @@ import { Point2d } from "@itwin/core-geometry"; import { assert } from "chai"; import * as path from "path"; import * as sinon from "sinon"; -import { DefinitionContainer, DefinitionModel, DocumentListModel, Drawing, DrawingCategory, DrawingGraphic, ElementGroupsMembers, ElementOwnsChildElements, ExternalSource, ExternalSourceGroup, IModelDb, Model, PhysicalPartition, SnapshotDb, SpatialCategory, SubCategory, Subject } from "../../core-backend"; +import { + DefinitionContainer, + DefinitionModel, + DocumentListModel, + Drawing, + DrawingCategory, + DrawingGraphic, + ElementGroupsMembers, + ElementOwnsChildElements, + ExternalSource, + ExternalSourceGroup, + IModelDb, + Model, + PhysicalPartition, + SnapshotDb, + SpatialCategory, + SubCategory, + Subject, +} from "../../core-backend"; import { deleteElementSubTrees, deleteElementTree, ElementTreeBottomUp, ElementTreeWalkerScope } from "../../ElementTreeWalker"; import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; @@ -20,7 +38,9 @@ class ElementTreeCollector extends ElementTreeBottomUp { public elements: Id64Array = []; public definitions: Id64Array = []; - public constructor(iModel: IModelDb) { super(iModel); } + public constructor(iModel: IModelDb) { + super(iModel); + } public visitModel(model: Model, _scope: ElementTreeWalkerScope): void { if (model instanceof DefinitionModel) @@ -42,10 +62,18 @@ class ElementTreeCollector extends ElementTreeBottomUp { } class SelectedElementCollector extends ElementTreeCollector { - public constructor(iModel: IModelDb, private _elementsToReport: Id64Array) { super(iModel); } - public override shouldExploreModel(_model: Model): boolean { return true; } - public override shouldVisitModel(_model: Model): boolean { return false; } - public override shouldVisitElement(elementId: Id64String): boolean { return this._elementsToReport.includes(elementId); } + public constructor(iModel: IModelDb, private _elementsToReport: Id64Array) { + super(iModel); + } + public override shouldExploreModel(_model: Model): boolean { + return true; + } + public override shouldVisitModel(_model: Model): boolean { + return false; + } + public override shouldVisitElement(elementId: Id64String): boolean { + return this._elementsToReport.includes(elementId); + } } function doesElementExist(iModel: IModelDb, elementId: Id64String): boolean { @@ -57,12 +85,15 @@ function doesModelExist(iModel: IModelDb, mid: Id64String): boolean { } function doesGroupRelationshipExist(iModel: IModelDb, source: Id64String, target: Id64String): boolean { - return iModel.withPreparedStatement(`select count(*) from ${ElementGroupsMembers.classFullName} where sourceecinstanceid=? and targetecinstanceid=?`, (stmt) => { - stmt.bindId(1, source); - stmt.bindId(2, target); - stmt.step(); - return stmt.getValue(0).getInteger() !== 0; - }); + return iModel.withPreparedStatement( + `select count(*) from ${ElementGroupsMembers.classFullName} where sourceecinstanceid=? and targetecinstanceid=?`, + (stmt) => { + stmt.bindId(1, source); + stmt.bindId(2, target); + stmt.step(); + return stmt.getValue(0).getInteger() !== 0; + }, + ); } describe("ElementTreeWalker", () => { @@ -148,8 +179,17 @@ describe("ElementTreeWalker", () => { definitionContainerId = DefinitionContainer.insert(iModel, definitionModelId, Code.createEmpty()); nestedSpatialCategoryId = SpatialCategory.insert(iModel, definitionContainerId, "nested", {}); - xsGroup = iModel.elements.insertElement({ classFullName: ExternalSourceGroup.classFullName, model: drawingDefinitionModelId, code: Code.createEmpty() }); - xsElement = iModel.elements.insertElement({ classFullName: ExternalSource.classFullName, model: drawingDefinitionModelId, parent: new ElementOwnsChildElements(xsGroup), code: Code.createEmpty() }); + xsGroup = iModel.elements.insertElement({ + classFullName: ExternalSourceGroup.classFullName, + model: drawingDefinitionModelId, + code: Code.createEmpty(), + }); + xsElement = iModel.elements.insertElement({ + classFullName: ExternalSource.classFullName, + model: drawingDefinitionModelId, + parent: new ElementOwnsChildElements(xsGroup), + code: Code.createEmpty(), + }); documentListModelId = DocumentListModel.insert(iModel, jobSubjectId, "Document"); assert.isTrue(Id64.isValidId64(documentListModelId)); @@ -165,7 +205,12 @@ describe("ElementTreeWalker", () => { }; drawingGraphicId1 = iModel.elements.insertElement(drawingGraphicProps1); - [, physicalModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(iModel, PhysicalPartition.createCode(iModel, childSubject, "Physical"), false, childSubject); + [, physicalModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( + iModel, + PhysicalPartition.createCode(iModel, childSubject, "Physical"), + false, + childSubject, + ); const elementProps: GeometricElementProps = { classFullName: "TestBim:TestPhysicalObject", model: physicalModelId, @@ -225,7 +270,10 @@ describe("ElementTreeWalker", () => { assert.isTrue(collector1.subModels.includes(physicalModelId)); assert.isTrue(collector1.subModels.includes(drawingModelId)); assert.isTrue(collector1.subModels.includes(documentListModelId)); - assert.isTrue(collector1.subModels.indexOf(drawingModelId) < collector1.subModels.indexOf(documentListModelId), "in bottom-up search, a child model should be visited before its parent model"); + assert.isTrue( + collector1.subModels.indexOf(drawingModelId) < collector1.subModels.indexOf(documentListModelId), + "in bottom-up search, a child model should be visited before its parent model", + ); assert.isFalse(collector1.subModels.includes(definitionModelId)); assert.isTrue(collector1.definitionModels.includes(definitionModelId)); assert.isFalse(collector1.subModels.includes(definitionContainerId)); @@ -238,15 +286,42 @@ describe("ElementTreeWalker", () => { assert.isFalse(collector1.elements.includes(drawingCategoryId)); assert.isFalse(collector1.elements.includes(spatialCategoryId)); assert.isFalse(collector1.elements.includes(nestedSpatialCategoryId)); - assert.isTrue(collector1.elements.indexOf(physicalObjectId1) < collector1.elements.indexOf(physicalModelId), "in bottom-up search, an element in a model should be visited before its model's element"); - assert.isTrue(collector1.elements.indexOf(drawingGraphicId1) < collector1.elements.indexOf(drawingModelId), "in bottom-up search, an element in a model should be visited before its model's element"); - assert.isTrue(collector1.elements.indexOf(drawingModelId) < collector1.elements.indexOf(documentListModelId), "in bottom-up search, an element in a model should be visited before its model's element"); - assert.isTrue(collector1.elements.indexOf(documentListModelId) < collector1.elements.indexOf(jobSubjectId), "in bottom-up search, a child element should be visited before its parent element"); - assert.isTrue(collector1.elements.indexOf(definitionModelId) < collector1.elements.indexOf(jobSubjectId), "in bottom-up search, a child element should be visited before its parent element"); - assert.isTrue(collector1.elements.indexOf(definitionContainerId) < collector1.elements.indexOf(definitionModelId), "in bottom-up search, a child element should be visited before its parent element"); - assert.isTrue(collector1.elements.indexOf(drawingDefinitionModelId) < collector1.elements.indexOf(jobSubjectId), "in bottom-up search, a child element should be visited before its parent element"); - assert.isTrue(collector1.elements.indexOf(childSubject) < collector1.elements.indexOf(jobSubjectId), "in bottom-up search, a child element should be visited before its parent element"); - assert.isTrue(collector1.elements.indexOf(physicalModelId) < collector1.elements.indexOf(childSubject), "in bottom-up search, a child element should be visited before its parent element"); + assert.isTrue( + collector1.elements.indexOf(physicalObjectId1) < collector1.elements.indexOf(physicalModelId), + "in bottom-up search, an element in a model should be visited before its model's element", + ); + assert.isTrue( + collector1.elements.indexOf(drawingGraphicId1) < collector1.elements.indexOf(drawingModelId), + "in bottom-up search, an element in a model should be visited before its model's element", + ); + assert.isTrue( + collector1.elements.indexOf(drawingModelId) < collector1.elements.indexOf(documentListModelId), + "in bottom-up search, an element in a model should be visited before its model's element", + ); + assert.isTrue( + collector1.elements.indexOf(documentListModelId) < collector1.elements.indexOf(jobSubjectId), + "in bottom-up search, a child element should be visited before its parent element", + ); + assert.isTrue( + collector1.elements.indexOf(definitionModelId) < collector1.elements.indexOf(jobSubjectId), + "in bottom-up search, a child element should be visited before its parent element", + ); + assert.isTrue( + collector1.elements.indexOf(definitionContainerId) < collector1.elements.indexOf(definitionModelId), + "in bottom-up search, a child element should be visited before its parent element", + ); + assert.isTrue( + collector1.elements.indexOf(drawingDefinitionModelId) < collector1.elements.indexOf(jobSubjectId), + "in bottom-up search, a child element should be visited before its parent element", + ); + assert.isTrue( + collector1.elements.indexOf(childSubject) < collector1.elements.indexOf(jobSubjectId), + "in bottom-up search, a child element should be visited before its parent element", + ); + assert.isTrue( + collector1.elements.indexOf(physicalModelId) < collector1.elements.indexOf(childSubject), + "in bottom-up search, a child element should be visited before its parent element", + ); } // Exercise the search filters diff --git a/core/backend/src/test/imodel/GetTextureImage.test.ts b/core/backend/src/test/imodel/GetTextureImage.test.ts index 8cb553d03449..903e476551fc 100644 --- a/core/backend/src/test/imodel/GetTextureImage.test.ts +++ b/core/backend/src/test/imodel/GetTextureImage.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { TextureLoadProps } from "@itwin/core-common"; +import { expect } from "chai"; import { SnapshotDb } from "../../IModelDb"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -12,7 +12,10 @@ describe("IModelDb.queryTextureData", () => { let imodel: SnapshotDb; before(() => { - imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("ElementGraphics", "mirukuru.ibim"), IModelTestUtils.resolveAssetFile("mirukuru.ibim")); + imodel = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("ElementGraphics", "mirukuru.ibim"), + IModelTestUtils.resolveAssetFile("mirukuru.ibim"), + ); }); after(() => imodel.close()); @@ -29,9 +32,15 @@ describe("IModelDb.queryTextureData", () => { }); it("if max size is not a positive number", async () => { - await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: "25" } as unknown as TextureLoadProps)).to.be.rejectedWith("maxTextureSize property must be a positive number"); - await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: 0 })).to.be.rejectedWith("maxTextureSize property must be a positive number"); - await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: -1 })).to.be.rejectedWith("maxTextureSize property must be a positive number"); + await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: "25" } as unknown as TextureLoadProps)).to.be.rejectedWith( + "maxTextureSize property must be a positive number", + ); + await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: 0 })).to.be.rejectedWith( + "maxTextureSize property must be a positive number", + ); + await expect(imodel.queryTextureData({ name: "0x123", maxTextureSize: -1 })).to.be.rejectedWith( + "maxTextureSize property must be a positive number", + ); }); }); }); diff --git a/core/backend/src/test/imodel/IModel.test.ts b/core/backend/src/test/imodel/IModel.test.ts index 7304ae93487d..7b72beaac39f 100644 --- a/core/backend/src/test/imodel/IModel.test.ts +++ b/core/backend/src/test/imodel/IModel.test.ts @@ -2,39 +2,135 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import * as path from "path"; -import * as semver from "semver"; -import * as sinon from "sinon"; import { DbResult, Guid, GuidString, Id64, Id64String, Logger, OpenMode, ProcessDetector, using } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, BisCodeSpec, BriefcaseIdValue, ChangesetIdWithIndex, Code, CodeScopeSpec, CodeSpec, ColorByName, ColorDef, DefinitionElementProps, - DisplayStyleProps, DisplayStyleSettings, DisplayStyleSettingsProps, EcefLocation, ElementProps, EntityMetaData, EntityProps, FilePropertyProps, - FontMap, FontType, GeoCoordinatesRequestProps, GeoCoordStatus, GeographicCRS, GeographicCRSProps, GeometricElementProps, GeometryParams, GeometryStreamBuilder, - ImageSourceFormat, IModel, IModelCoordinatesRequestProps, IModelError, IModelStatus, LightLocationProps, MapImageryProps, PhysicalElementProps, - PointWithStatus, PrimitiveTypeCode, RelatedElement, RenderMode, SchemaState, SpatialViewDefinitionProps, SubCategoryAppearance, SubjectProps, TextureMapping, - TextureMapProps, TextureMapUnits, ViewDefinitionProps, ViewFlagProps, ViewFlags, + AxisAlignedBox3d, + BisCodeSpec, + BriefcaseIdValue, + ChangesetIdWithIndex, + Code, + CodeScopeSpec, + CodeSpec, + ColorByName, + ColorDef, + DefinitionElementProps, + DisplayStyleProps, + DisplayStyleSettings, + DisplayStyleSettingsProps, + EcefLocation, + ElementProps, + EntityMetaData, + EntityProps, + FilePropertyProps, + FontMap, + FontType, + GeoCoordinatesRequestProps, + GeoCoordStatus, + GeographicCRS, + GeographicCRSProps, + GeometricElementProps, + GeometryParams, + GeometryStreamBuilder, + ImageSourceFormat, + IModel, + IModelCoordinatesRequestProps, + IModelError, + IModelStatus, + LightLocationProps, + MapImageryProps, + PhysicalElementProps, + PointWithStatus, + PrimitiveTypeCode, + RelatedElement, + RenderMode, + SchemaState, + SpatialViewDefinitionProps, + SubCategoryAppearance, + SubjectProps, + TextureMapping, + TextureMapProps, + TextureMapUnits, + ViewDefinitionProps, + ViewFlagProps, + ViewFlags, } from "@itwin/core-common"; import { - Geometry, GeometryQuery, LineString3d, Loop, Matrix4d, Point3d, PolyfaceBuilder, Range3d, StrokeOptions, Transform, XYZProps, YawPitchRollAngles, + Geometry, + GeometryQuery, + LineString3d, + Loop, + Matrix4d, + Point3d, + PolyfaceBuilder, + Range3d, + StrokeOptions, + Transform, + XYZProps, + YawPitchRollAngles, } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import * as path from "path"; +import { performance } from "perf_hooks"; +import * as semver from "semver"; +import * as sinon from "sinon"; import { V2CheckpointAccessProps } from "../../BackendHubAccess"; import { V2CheckpointManager } from "../../CheckpointManager"; import { - _nativeDb, BisCoreSchema, Category, ClassRegistry, DefinitionContainer, DefinitionGroup, DefinitionGroupGroupsDefinitions, - DefinitionModel, DefinitionPartition, DictionaryModel, DisplayStyle3d, DisplayStyleCreationOptions, DocumentPartition, DrawingGraphic, ECSqlStatement, - Element, ElementDrivesElement, ElementGroupsMembers, ElementOwnsChildElements, Entity, GeometricElement2d, GeometricElement3d, - GeometricModel, GroupInformationPartition, IModelDb, IModelHost, IModelJsFs, InformationPartitionElement, InformationRecordElement, LightLocation, - LinkPartition, Model, PhysicalElement, PhysicalModel, PhysicalObject, PhysicalPartition, RenderMaterialElement, RenderMaterialElementParams, SnapshotDb, SpatialCategory, - SqliteStatement, SqliteValue, SqliteValueType, StandaloneDb, SubCategory, Subject, Texture, ViewDefinition, + _nativeDb, + BisCoreSchema, + Category, + ClassRegistry, + DefinitionContainer, + DefinitionGroup, + DefinitionGroupGroupsDefinitions, + DefinitionModel, + DefinitionPartition, + DictionaryModel, + DisplayStyle3d, + DisplayStyleCreationOptions, + DocumentPartition, + DrawingGraphic, + ECSqlStatement, + Element, + ElementDrivesElement, + ElementGroupsMembers, + ElementOwnsChildElements, + Entity, + GeometricElement2d, + GeometricElement3d, + GeometricModel, + GroupInformationPartition, + IModelDb, + IModelHost, + IModelJsFs, + InformationPartitionElement, + InformationRecordElement, + LightLocation, + LinkPartition, + Model, + PhysicalElement, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + RenderMaterialElement, + RenderMaterialElementParams, + SnapshotDb, + SpatialCategory, + SqliteStatement, + SqliteValue, + SqliteValueType, + StandaloneDb, + SubCategory, + Subject, + Texture, + ViewDefinition, } from "../../core-backend"; -import { BriefcaseDb, SnapshotDbOpenArgs } from "../../IModelDb"; import { HubMock } from "../../HubMock"; -import { KnownTestLocations } from "../KnownTestLocations"; +import { BriefcaseDb, SnapshotDbOpenArgs } from "../../IModelDb"; +import { samplePngTexture } from "../imageData"; import { IModelTestUtils } from "../IModelTestUtils"; +import { KnownTestLocations } from "../KnownTestLocations"; import { DisableNativeAssertions } from "../TestUtils"; -import { samplePngTexture } from "../imageData"; -import { performance } from "perf_hooks"; // spell-checker: disable async function getIModelError(promise: Promise): Promise { @@ -64,11 +160,23 @@ describe("iModel", () => { originalEnv = { ...process.env }; IModelTestUtils.registerTestBimSchema(); - imodel1 = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "test.bim"), IModelTestUtils.resolveAssetFile("test.bim")); - imodel2 = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "CompatibilityTestSeed.bim"), IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim")); + imodel1 = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "test.bim"), + IModelTestUtils.resolveAssetFile("test.bim"), + ); + imodel2 = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "CompatibilityTestSeed.bim"), + IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim"), + ); imodel3 = SnapshotDb.openFile(IModelTestUtils.resolveAssetFile("GetSetAutoHandledStructProperties.bim")); - imodel4 = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "GetSetAutoHandledArrayProperties.bim"), IModelTestUtils.resolveAssetFile("GetSetAutoHandledArrayProperties.bim")); - imodel5 = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "mirukuru.ibim"), IModelTestUtils.resolveAssetFile("mirukuru.ibim")); + imodel4 = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "GetSetAutoHandledArrayProperties.bim"), + IModelTestUtils.resolveAssetFile("GetSetAutoHandledArrayProperties.bim"), + ); + imodel5 = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "mirukuru.ibim"), + IModelTestUtils.resolveAssetFile("mirukuru.ibim"), + ); const schemaPathname = path.join(KnownTestLocations.assetsDir, "TestBim.ecschema.xml"); await imodel1.importSchemas([schemaPathname]); // will throw an exception if import fails @@ -104,7 +212,12 @@ describe("iModel", () => { // make sure we can construct a new element even if we haven't loaded its metadata (will be loaded in ctor) assert.isUndefined(imodel1.classMetaDataRegistry.find("biscore:lightlocation")); - const e1 = imodel1.constructEntity({ category: "0x11", classFullName: "BisCore:LightLocation", model: "0x01", code: Code.createEmpty() }); + const e1 = imodel1.constructEntity({ + category: "0x11", + classFullName: "BisCore:LightLocation", + model: "0x01", + code: Code.createEmpty(), + }); assert.isDefined(e1); assert.isDefined(imodel1.classMetaDataRegistry.find("biscore:lightlocation")); // should have been loaded in ctor }); @@ -408,19 +521,25 @@ describe("iModel", () => { const testTextureFormat = ImageSourceFormat.Png; const testTextureDescription = "empty description"; - const texId = Texture.insertTexture(imodel5, IModel.dictionaryId, testTextureName, testTextureFormat, samplePngTexture.base64, testTextureDescription); + const texId = Texture.insertTexture( + imodel5, + IModel.dictionaryId, + testTextureName, + testTextureFormat, + samplePngTexture.base64, + testTextureDescription, + ); /* eslint-disable @typescript-eslint/naming-convention */ - const matId = RenderMaterialElement.insert(imodel5, IModel.dictionaryId, "test material name", - { - paletteName: "TestPaletteName", - patternMap: { - TextureId: texId, - pattern_offset: [0, 0], - pattern_scale: [1, 1], - pattern_scalemode: TextureMapUnits.Relative, - }, - }); + const matId = RenderMaterialElement.insert(imodel5, IModel.dictionaryId, "test material name", { + paletteName: "TestPaletteName", + patternMap: { + TextureId: texId, + pattern_offset: [0, 0], + pattern_scale: [1, 1], + pattern_scalemode: TextureMapUnits.Relative, + }, + }); /* eslint-enable @typescript-eslint/naming-convention */ /** Create a simple flat mesh with 4 points (2x2) */ @@ -621,7 +740,10 @@ describe("iModel", () => { if (childLocalId === 16 && childBcId === 0) { assert.isTrue(childElement instanceof DefinitionPartition, "ChildId 0x00000010 should be a DefinitionPartition"); - assert.isTrue(childElement.code.value === "BisCore.DictionaryModel", "Definition Partition should have code value of BisCore.DictionaryModel"); + assert.isTrue( + childElement.code.value === "BisCore.DictionaryModel", + "Definition Partition should have code value of BisCore.DictionaryModel", + ); } else if (childLocalId === 14 && childBcId === 0) { assert.isTrue(childElement instanceof LinkPartition); assert.isTrue(childElement.code.value === "BisCore.RealityDataSources"); @@ -634,8 +756,14 @@ describe("iModel", () => { if (childLocalId === 19 && childBcId === 0) { assert.isTrue(childElement instanceof Subject); assert.isTrue(childElement.code.value === "DgnV8:mf3, A", "Subject should have code value of DgnV8:mf3, A"); - assert.isTrue(childElement.jsonProperties.Subject.Job.DgnV8.V8File === "mf3.dgn", "Subject should have jsonProperty Subject.Job.DgnV.V8File"); - assert.isTrue(childElement.jsonProperties.Subject.Job.DgnV8.V8RootModel === "A", "Subject should have jsonProperty Subject.Job.DgnV.V8RootModel"); + assert.isTrue( + childElement.jsonProperties.Subject.Job.DgnV8.V8File === "mf3.dgn", + "Subject should have jsonProperty Subject.Job.DgnV.V8File", + ); + assert.isTrue( + childElement.jsonProperties.Subject.Job.DgnV8.V8RootModel === "A", + "Subject should have jsonProperty Subject.Job.DgnV.V8RootModel", + ); } } } @@ -695,7 +823,7 @@ describe("iModel", () => { }); it("should throw on invalid tile requests", async () => { - await using(new DisableNativeAssertions(), async (_r) => { + using(new DisableNativeAssertions(), async (_r) => { let error = await getIModelError(imodel1.tiles.requestTileTreeProps("0x12345")); expectIModelError(IModelStatus.InvalidId, error); @@ -1242,7 +1370,14 @@ describe("iModel", () => { }); // make sure queryEnityIds works fine when all params are specified - const physicalObjectIds = imodel2.queryEntityIds({ from: "generic.PhysicalObject", where: "codevalue is null", limit: 1, offset: 1, only: true, orderBy: "ecinstanceid desc" }); + const physicalObjectIds = imodel2.queryEntityIds({ + from: "generic.PhysicalObject", + where: "codevalue is null", + limit: 1, + offset: 1, + only: true, + orderBy: "ecinstanceid desc", + }); assert.equal(physicalObjectIds.size, 1); }); @@ -1330,7 +1465,12 @@ describe("iModel", () => { it("snapping", async () => { const worldToView = Matrix4d.createIdentity(); - const response = await imodel2.requestSnap("0x222", { testPoint: { x: 1, y: 2, z: 3 }, closePoint: { x: 1, y: 2, z: 3 }, id: "0x111", worldToView: worldToView.toJSON() }); + const response = await imodel2.requestSnap("0x222", { + testPoint: { x: 1, y: 2, z: 3 }, + closePoint: { x: 1, y: 2, z: 3 }, + id: "0x111", + worldToView: worldToView.toJSON(), + }); assert.isDefined(response.status); }); @@ -1341,7 +1481,6 @@ describe("iModel", () => { }); it("should do CRUD on models", () => { - const testImodel = imodel2; const [modeledElementId, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(testImodel, Code.createEmpty(), true); @@ -1375,7 +1514,10 @@ describe("iModel", () => { it("should create model with custom relationship to modeled element", async () => { const testImodel = imodel1; - assert.isDefined(testImodel.getMetaData("TestBim:TestModelModelsElement"), "TestModelModelsElement is expected to be defined in TestBim.ecschema.xml"); + assert.isDefined( + testImodel.getMetaData("TestBim:TestModelModelsElement"), + "TestModelModelsElement is expected to be defined in TestBim.ecschema.xml", + ); let newModelId1: Id64String; let newModelId2: Id64String; @@ -1415,7 +1557,12 @@ describe("iModel", () => { const newModelId = PhysicalModel.insert(testImodel, IModel.rootSubjectId, "TestModel"); // create a SpatialCategory - const spatialCategoryId = SpatialCategory.insert(testImodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorByName.darkRed })); + const spatialCategoryId = SpatialCategory.insert( + testImodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorByName.darkRed }), + ); // Create a couple of physical elements. const elementProps: GeometricElementProps = { @@ -1448,7 +1595,7 @@ describe("iModel", () => { assert.equal(g1.memberPriority, 1, "g1.memberPriority"); assert.deepEqual(g2.id, r2.id); assert.equal(g2.classFullName, ElementGroupsMembers.classFullName); - assert.equal(g2.memberPriority, 0, "g2.memberPriority"); // The memberPriority parameter defaults to 0 in ElementGroupsMembers.create + assert.equal(g2.memberPriority, 0, "g2.memberPriority"); // The memberPriority parameter defaults to 0 in ElementGroupsMembers.create // Look up by source and target const g1byst = ElementGroupsMembers.getInstance(testImodel, { sourceId: r1.sourceId, targetId: r1.targetId }); @@ -1491,16 +1638,18 @@ describe("iModel", () => { DefinitionGroupGroupsDefinitions.insert(iModelDb, definitionGroupId, categoryId1); DefinitionGroupGroupsDefinitions.insert(iModelDb, definitionGroupId, categoryId2); DefinitionGroupGroupsDefinitions.insert(iModelDb, definitionGroupId, categoryId3); - const numMembers = iModelDb.withPreparedStatement(`SELECT COUNT(*) FROM ${DefinitionGroupGroupsDefinitions.classFullName}`, (statement: ECSqlStatement): number => { - return statement.step() === DbResult.BE_SQLITE_ROW ? statement.getValue(0).getInteger() : 0; - }); + const numMembers = iModelDb.withPreparedStatement( + `SELECT COUNT(*) FROM ${DefinitionGroupGroupsDefinitions.classFullName}`, + (statement: ECSqlStatement): number => { + return statement.step() === DbResult.BE_SQLITE_ROW ? statement.getValue(0).getInteger() : 0; + }, + ); assert.equal(numMembers, 3); iModelDb.saveChanges(); iModelDb.close(); }); it("should set EC properties of various types", async () => { - const testImodel = imodel1; testImodel.getMetaData("TestBim:TestPhysicalObject"); @@ -1534,7 +1683,7 @@ describe("iModel", () => { elementProps.id = Id64.invalid; (elementProps as any).relatedElement = { id: id1, relClassName: trelClassName }; elementProps.parent = { id: id1, relClassName: trelClassName }; - (elementProps as any).longProp = 4294967295; // make sure that we can save values in the range 0 ... UINT_MAX + (elementProps as any).longProp = 4294967295; // make sure that we can save values in the range 0 ... UINT_MAX id2 = testImodel.elements.insertElement(testImodel.elements.createElement(elementProps).toJSON()); assert.isTrue(Id64.isValidId64(id2)); @@ -1735,8 +1884,13 @@ describe("iModel", () => { if (!ProcessDetector.isIOSAppBackend) { it("should be able to reproject with iModel coordinates to or from any other GeographicCRS", async () => { - const convertTest = async (fileName: string, fileGCS: GeographicCRSProps, datum: string | GeographicCRSProps, inputCoord: XYZProps, outputCoord: PointWithStatus) => { - + const convertTest = async ( + fileName: string, + fileGCS: GeographicCRSProps, + datum: string | GeographicCRSProps, + inputCoord: XYZProps, + outputCoord: PointWithStatus, + ) => { const args = { rootSubject: { name: "TestSubject", description: "test project" }, client: "ABC Engineering", @@ -1767,7 +1921,6 @@ describe("iModel", () => { // If success or warning we compare result if (outputCoord.s === GeoCoordStatus.Success || outputCoord.s === GeoCoordStatus.OutOfUsefulRange) { - const expectedPt1 = Point3d.fromJSON(outputCoord.p); const outPt1 = Point3d.fromJSON(response1.geoCoords[0].p); @@ -1837,7 +1990,8 @@ describe("iModel", () => { }, scalePPM: -20.489, }, - }], + }, + ], }, unit: "Meter", projection: { @@ -1873,35 +2027,142 @@ describe("iModel", () => { }, }; - await convertTest("ExtonCampus1.bim", { horizontalCRS: { id: "EPSG:2272" }, verticalCRS: { id: "NAVD88" } }, "WGS84", { x: 775970.3155166894, y: 83323.24543981979, z: 130.74977547686285 }, { p: { x: -75.68712011112366, y: 40.06524845273591, z: 95.9769083 }, s: GeoCoordStatus.Success }); - - await convertTest("UTM83-10-NGVD29-10.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NAVD88" } }, { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "NGVD29" } }, { x: 548296.472, y: 4179414.470, z: 0.8457 }, { p: { x: 548392.9689991799, y: 4179217.683834238, z: -0.0006774162750405877 }, s: GeoCoordStatus.Success }); - - await convertTest("BritishNatGrid-EllipsoidHelmert1.bim", EWRGCS, "WGS84", { x: 199247.08883859176, y: 150141.68625139236, z: 0.0 }, { p: { x: -0.80184489371471, y: 51.978341907041205, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("BritishNatGrid-Ellipsoid1.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "", { x: 170370.718, y: 11572.405, z: 0.0 }, { p: { x: -5.2020119082059511, y: 49.959453295440234, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("BritishNatGrid-Ellipsoid2.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "ETRF89", { x: 170370.718, y: 11572.405, z: 0.0 }, { p: { x: -5.2030365061523707, y: 49.960007477936202, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("BritishNatGrid-Ellipsoid3.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "OSGB", { x: 170370.718, y: 11572.405, z: 0.0 }, { p: { x: -5.2020119082059511, y: 49.959453295440234, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("GermanyDHDN-3-Ellipsoid1.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "", { x: 4360857.005, y: 5606083.067, z: 0.0 }, { p: { x: 10.035413954488630, y: 50.575070810112159, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("GermanyDHDN-3-Ellipsoid2.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "DHDN/3", { x: 4360857.005, y: 5606083.067, z: 0.0 }, { p: { x: 10.035413954488630, y: 50.575070810112159, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("GermanyDHDN-3-Ellipsoid3.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "WGS84", { x: 4360857.005, y: 5606083.067, z: 0.0 }, { p: { x: 10.034215937440818, y: 50.573862480894853, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-1.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "", { x: 632748.112, y: 4263868.307, z: 0.0 }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-2.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "NAD83", { x: 632748.112, y: 4263868.307, z: 0.0 }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-3.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "WGS84", { x: 632748.112, y: 4263868.307, z: 0.0 }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }); - await convertTest("UTM27-10-Ellipsoid1.bim", { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "ELLIPSOID" } }, "", { x: 623075.328, y: 4265650.532, z: 0.0 }, { p: { x: -121.58798236995744, y: 38.532616292207997, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("UTM27-10-Ellipsoid2.bim", { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "ELLIPSOID" } }, "NAD83", { x: 623075.328, y: 4265650.532, z: 0.0 }, { p: { x: -121.58905088839697, y: 38.532522753851708, z: 0.0 }, s: GeoCoordStatus.Success }); - - await convertTest("UTM83-10-NGVD29-4.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "LL84" }, verticalCRS: { id: "ELLIPSOID" } }, { x: 632748.112, y: 4263868.307, z: 0.0 }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }); - - await convertTest("UTM83-10-NGVD29-5.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "LL84" }, verticalCRS: { id: "GEOID" } }, { x: 632748.112, y: 4263868.307, z: 0.0 }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: 0.7621583779125531 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-6.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "NAVD88" } }, { x: 569024.940, y: 4386341.752, z: 0.0 }, { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-7.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "GEOID" } }, { x: 569024.940, y: 4386341.752, z: 0.0 }, { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-8.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "NGVD29" } }, { x: 569024.940, y: 4386341.752, z: 0.0 }, { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.0 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-9.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { epsg: 26942 }, verticalCRS: { id: "NAVD88" } }, { x: 569024.940, y: 4386341.752, z: 0.0 }, { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }); - await convertTest("UTM83-10-NGVD29-10.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NAVD88" } }, { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "NGVD29" } }, { x: 548296.472, y: 4179414.470, z: 0.8457 }, { p: { x: 548392.9689991799, y: 4179217.683834238, z: -0.0006774162750405877 }, s: GeoCoordStatus.Success }); - - await convertTest("BritishNatGrid-Ellipsoid4.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "HS2_Snake_2015" }, verticalCRS: { id: "GEOID" } }, { x: 473327.251, y: 257049.636, z: 0.0 }, { p: { x: 237732.58101946692, y: 364048.01547843055, z: -47.874172425966336 }, s: GeoCoordStatus.Success }); - - await convertTest("BritishNatGrid-Ellipsoid5.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, + await convertTest("ExtonCampus1.bim", { horizontalCRS: { id: "EPSG:2272" }, verticalCRS: { id: "NAVD88" } }, "WGS84", { + x: 775970.3155166894, + y: 83323.24543981979, + z: 130.74977547686285, + }, { p: { x: -75.68712011112366, y: 40.06524845273591, z: 95.9769083 }, s: GeoCoordStatus.Success }); + + await convertTest( + "UTM83-10-NGVD29-10.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NAVD88" } }, + { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "NGVD29" } }, + { x: 548296.472, y: 4179414.470, z: 0.8457 }, + { p: { x: 548392.9689991799, y: 4179217.683834238, z: -0.0006774162750405877 }, s: GeoCoordStatus.Success }, + ); + + await convertTest("BritishNatGrid-EllipsoidHelmert1.bim", EWRGCS, "WGS84", { x: 199247.08883859176, y: 150141.68625139236, z: 0.0 }, { + p: { x: -0.80184489371471, y: 51.978341907041205, z: 0.0 }, + s: GeoCoordStatus.Success, + }); + await convertTest("BritishNatGrid-Ellipsoid1.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "", { + x: 170370.718, + y: 11572.405, + z: 0.0, + }, { p: { x: -5.2020119082059511, y: 49.959453295440234, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("BritishNatGrid-Ellipsoid2.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "ETRF89", { + x: 170370.718, + y: 11572.405, + z: 0.0, + }, { p: { x: -5.2030365061523707, y: 49.960007477936202, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("BritishNatGrid-Ellipsoid3.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, "OSGB", { + x: 170370.718, + y: 11572.405, + z: 0.0, + }, { p: { x: -5.2020119082059511, y: 49.959453295440234, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("GermanyDHDN-3-Ellipsoid1.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "", { + x: 4360857.005, + y: 5606083.067, + z: 0.0, + }, { p: { x: 10.035413954488630, y: 50.575070810112159, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("GermanyDHDN-3-Ellipsoid2.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "DHDN/3", { + x: 4360857.005, + y: 5606083.067, + z: 0.0, + }, { p: { x: 10.035413954488630, y: 50.575070810112159, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("GermanyDHDN-3-Ellipsoid3.bim", { horizontalCRS: { id: "DHDN/3.GK3d-4/EN" }, verticalCRS: { id: "ELLIPSOID" } }, "WGS84", { + x: 4360857.005, + y: 5606083.067, + z: 0.0, + }, { p: { x: 10.034215937440818, y: 50.573862480894853, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("UTM83-10-NGVD29-1.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "", { + x: 632748.112, + y: 4263868.307, + z: 0.0, + }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("UTM83-10-NGVD29-2.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "NAD83", { + x: 632748.112, + y: 4263868.307, + z: 0.0, + }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }); + await convertTest("UTM83-10-NGVD29-3.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, "WGS84", { + x: 632748.112, + y: 4263868.307, + z: 0.0, + }, { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }); + await convertTest("UTM27-10-Ellipsoid1.bim", { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "ELLIPSOID" } }, "", { + x: 623075.328, + y: 4265650.532, + z: 0.0, + }, { p: { x: -121.58798236995744, y: 38.532616292207997, z: 0.0 }, s: GeoCoordStatus.Success }); + await convertTest("UTM27-10-Ellipsoid2.bim", { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "ELLIPSOID" } }, "NAD83", { + x: 623075.328, + y: 4265650.532, + z: 0.0, + }, { p: { x: -121.58905088839697, y: 38.532522753851708, z: 0.0 }, s: GeoCoordStatus.Success }); + + await convertTest( + "UTM83-10-NGVD29-4.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { id: "LL84" }, verticalCRS: { id: "ELLIPSOID" } }, + { x: 632748.112, y: 4263868.307, z: 0.0 }, + { p: { x: -121.47738265889652, y: 38.513305313793019, z: -30.12668428839329 }, s: GeoCoordStatus.Success }, + ); + + await convertTest( + "UTM83-10-NGVD29-5.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { id: "LL84" }, verticalCRS: { id: "GEOID" } }, + { x: 632748.112, y: 4263868.307, z: 0.0 }, + { p: { x: -121.47738265889652, y: 38.513305313793019, z: 0.7621583779125531 }, s: GeoCoordStatus.Success }, + ); + await convertTest( + "UTM83-10-NGVD29-6.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "NAVD88" } }, + { x: 569024.940, y: 4386341.752, z: 0.0 }, + { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }, + ); + await convertTest( + "UTM83-10-NGVD29-7.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "GEOID" } }, + { x: 569024.940, y: 4386341.752, z: 0.0 }, + { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }, + ); + await convertTest( + "UTM83-10-NGVD29-8.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { id: "CA83-II" }, verticalCRS: { id: "NGVD29" } }, + { x: 569024.940, y: 4386341.752, z: 0.0 }, + { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.0 }, s: GeoCoordStatus.Success }, + ); + await convertTest( + "UTM83-10-NGVD29-9.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + { horizontalCRS: { epsg: 26942 }, verticalCRS: { id: "NAVD88" } }, + { x: 569024.940, y: 4386341.752, z: 0.0 }, + { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }, + ); + await convertTest( + "UTM83-10-NGVD29-10.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NAVD88" } }, + { horizontalCRS: { id: "UTM27-10" }, verticalCRS: { id: "NGVD29" } }, + { x: 548296.472, y: 4179414.470, z: 0.8457 }, + { p: { x: 548392.9689991799, y: 4179217.683834238, z: -0.0006774162750405877 }, s: GeoCoordStatus.Success }, + ); + + await convertTest( + "BritishNatGrid-Ellipsoid4.bim", + { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, + { horizontalCRS: { id: "HS2_Snake_2015" }, verticalCRS: { id: "GEOID" } }, + { x: 473327.251, y: 257049.636, z: 0.0 }, + { p: { x: 237732.58101946692, y: 364048.01547843055, z: -47.874172425966336 }, s: GeoCoordStatus.Success }, + ); + + await convertTest( + "BritishNatGrid-Ellipsoid5.bim", + { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "HS2-MOCK", @@ -1922,12 +2183,22 @@ describe("iModel", () => { verticalCRS: { id: "GEOID", }, - } - , { x: 473327.251, y: 257049.636, z: 0.0 }, { p: { x: 237732.58101952373, y: 364048.01548327296, z: -47.874172425966336 }, s: GeoCoordStatus.Success }); - - await convertTest("BritishNatGrid-Ellipsoid.bim", { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, { x: 473327.251, y: 257049.636, z: 0.0 }, { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.Success }); - - await convertTest("UTM83-10-NGVD29-12.bim", { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, + }, + { x: 473327.251, y: 257049.636, z: 0.0 }, + { p: { x: 237732.58101952373, y: 364048.01548327296, z: -47.874172425966336 }, s: GeoCoordStatus.Success }, + ); + + await convertTest( + "BritishNatGrid-Ellipsoid.bim", + { horizontalCRS: { id: "BritishNatGrid" }, verticalCRS: { id: "ELLIPSOID" } }, + { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, + { x: 473327.251, y: 257049.636, z: 0.0 }, + { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.Success }, + ); + + await convertTest( + "UTM83-10-NGVD29-12.bim", + { horizontalCRS: { id: "UTM83-10" }, verticalCRS: { id: "NGVD29" } }, { horizontalCRS: { id: "California2", @@ -1959,14 +2230,27 @@ describe("iModel", () => { verticalCRS: { id: "GEOID", }, - }, { x: 569024.940, y: 4386341.752, z: 0.0 }, { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }); + }, + { x: 569024.940, y: 4386341.752, z: 0.0 }, + { p: { x: 1983192.529823256, y: 717304.0311293667, z: 0.745910484422781 }, s: GeoCoordStatus.Success }, + ); // Do some test that return errors // First test uses one GCS in Eastern USA and the other in UK. This will produce a hard domain error - await convertTest("Error1.bim", { horizontalCRS: { id: "UTM84-17N" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, { x: 1473327.251, y: 1257049.636, z: 0.0 }, { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.OutOfMathematicalDomain }); + await convertTest( + "Error1.bim", + { horizontalCRS: { id: "UTM84-17N" }, verticalCRS: { id: "ELLIPSOID" } }, + { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, + { x: 1473327.251, y: 1257049.636, z: 0.0 }, + { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.OutOfMathematicalDomain }, + ); // This test performs conversion in a region outside normal use of GCS but still mathematically valid (soft domain error) - await convertTest("Error2.bim", { horizontalCRS: { id: "DanishS34-S99" }, verticalCRS: { id: "ELLIPSOID" } }, "", { x: -6618.5925260757449, y: 36058.097489683532, z: 0.0 }, { p: { x: 13.53250346041385, y: 54.71216475341563, z: 0.0 }, s: GeoCoordStatus.OutOfUsefulRange }); + await convertTest("Error2.bim", { horizontalCRS: { id: "DanishS34-S99" }, verticalCRS: { id: "ELLIPSOID" } }, "", { + x: -6618.5925260757449, + y: 36058.097489683532, + z: 0.0, + }, { p: { x: 13.53250346041385, y: 54.71216475341563, z: 0.0 }, s: GeoCoordStatus.OutOfUsefulRange }); // -6618.5925260757449, 36058.097489683532 // { x: -221748.034, y: -10012.784, z: 0.0 } { p: { x: 10.36481105, y: 54.38462506, z: 0.0 } // This test makes use of a GCS using a grid file that does not even exist and will return a datum conversion error. @@ -2011,17 +2295,32 @@ describe("iModel", () => { southWest: { latitude: 48, longitude: -120.5 }, northEast: { latitude: 84, longitude: -109.5 }, }, - }, verticalCRS: { id: "ELLIPSOID" }, + }, + verticalCRS: { id: "ELLIPSOID" }, }; - await convertTest("Error3.bim", userGCSWithinexistentGridFile, "WGS84", { x: 1473327.251, y: 1257049.636, z: 0.0 }, { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.NoDatumConverter }); + await convertTest("Error3.bim", userGCSWithinexistentGridFile, "WGS84", { x: 1473327.251, y: 1257049.636, z: 0.0 }, { + p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, + s: GeoCoordStatus.NoDatumConverter, + }); // The model GCS is not valid - await convertTest("Error4.bim", { horizontalCRS: { id: "badfood" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, { x: 1473327.251, y: 1257049.636, z: 0.0 }, { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.NoGCSDefined }); + await convertTest( + "Error4.bim", + { horizontalCRS: { id: "badfood" }, verticalCRS: { id: "ELLIPSOID" } }, + { horizontalCRS: { id: "OSGB-GPS-2015" }, verticalCRS: { id: "GEOID" } }, + { x: 1473327.251, y: 1257049.636, z: 0.0 }, + { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.NoGCSDefined }, + ); // The given GCS is not valid - await convertTest("Error5.bim", { horizontalCRS: { id: "UTM84-17N" }, verticalCRS: { id: "ELLIPSOID" } }, { horizontalCRS: { id: "badfood" }, verticalCRS: { id: "GEOID" } }, { x: 1473327.251, y: 1257049.636, z: 0.0 }, { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.NoGCSDefined }); - + await convertTest( + "Error5.bim", + { horizontalCRS: { id: "UTM84-17N" }, verticalCRS: { id: "ELLIPSOID" } }, + { horizontalCRS: { id: "badfood" }, verticalCRS: { id: "GEOID" } }, + { x: 1473327.251, y: 1257049.636, z: 0.0 }, + { p: { x: 473325.6830048648, y: 257049.77062273448, z: -47.87643904264457 }, s: GeoCoordStatus.NoGCSDefined }, + ); }); } @@ -2177,20 +2476,19 @@ describe("iModel", () => { const iTwinId = "fakeIModelId"; const iModelId = "fakeIModelId"; const cloudContainer = { accessToken: "sas" }; - const fakeSnapshotDb: any = - { + const fakeSnapshotDb: any = { cloudContainer, isReadonly: () => true, isOpen: () => true, getIModelId: () => iModelId, getITwinId: () => iTwinId, getCurrentChangeset: () => changeset, - setIModelDb: () => { }, - closeFile: () => { }, + setIModelDb: () => {}, + closeFile: () => {}, }; - const errorLogStub = sinon.stub(Logger, "logError").callsFake(() => { }); - const infoLogStub = sinon.stub(Logger, "logInfo").callsFake(() => { }); + const errorLogStub = sinon.stub(Logger, "logError").callsFake(() => {}); + const infoLogStub = sinon.stub(Logger, "logInfo").callsFake(() => {}); // Mock iModelHub const mockCheckpointV2: V2CheckpointAccessProps = { @@ -2249,7 +2547,14 @@ describe("iModel", () => { sinon.stub(IModelHost.hubAccess, "queryV2Checkpoint").callsFake(async () => undefined); const accessToken = "token"; - const error = await getIModelError(SnapshotDb.openCheckpointFromRpc({ accessToken, iTwinId: Guid.createValue(), iModelId: Guid.createValue(), changeset: IModelTestUtils.generateChangeSetId() })); + const error = await getIModelError( + SnapshotDb.openCheckpointFromRpc({ + accessToken, + iTwinId: Guid.createValue(), + iModelId: Guid.createValue(), + changeset: IModelTestUtils.generateChangeSetId(), + }), + ); expectIModelError(IModelStatus.NotFound, error); }); @@ -2488,14 +2793,19 @@ describe("iModel", () => { assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); }); - imodel1.withPreparedSqliteStatement("SELECT 1 FROM ec_CustomAttribute WHERE ContainerId=? AND Instance LIKE ' { - stmt.bindValue(1, "0x1f"); - assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); - }); + imodel1.withPreparedSqliteStatement( + "SELECT 1 FROM ec_CustomAttribute WHERE ContainerId=? AND Instance LIKE ' { + stmt.bindValue(1, "0x1f"); + assert.equal(stmt.step(), DbResult.BE_SQLITE_DONE); + }, + ); }); it("Run plain SQL against readonly connection", () => { - let iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "sqlitesqlreadonlyconnection.bim"), { rootSubject: { name: "test" } }); + let iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "sqlitesqlreadonlyconnection.bim"), { + rootSubject: { name: "test" }, + }); const iModelPath = iModel.pathName; iModel.close(); iModel = SnapshotDb.openFile(iModelPath); @@ -2799,7 +3109,6 @@ describe("iModel", () => { assert.equal(subject4.code.value, "Subject4"); // should not have changed assert.equal(subject4.description, "Description4"); // should not have changed assert.isUndefined(subject4.federationGuid); // should not have changed - }); it('should allow untrimmed codes when using "exact" codeValueBehavior', () => { diff --git a/core/backend/src/test/imodel/ProjectExtents.test.ts b/core/backend/src/test/imodel/ProjectExtents.test.ts index 1f3aad62fb4f..0ee7b34b458a 100644 --- a/core/backend/src/test/imodel/ProjectExtents.test.ts +++ b/core/backend/src/test/imodel/ProjectExtents.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { GeometricElement3dProps, Placement3d } from "@itwin/core-common"; +import { expect } from "chai"; import { GeometricElement3d, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../index"; @@ -13,7 +13,10 @@ describe("computeProjectExtents", () => { let imodel: SnapshotDb; before(() => { - imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "test.bim"), IModelTestUtils.resolveAssetFile("test.bim")); + imodel = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "test.bim"), + IModelTestUtils.resolveAssetFile("test.bim"), + ); }); after(() => { diff --git a/core/backend/src/test/imodel/SchemaXmlImport.test.ts b/core/backend/src/test/imodel/SchemaXmlImport.test.ts index 7dcd05db466f..d20a20694d83 100644 --- a/core/backend/src/test/imodel/SchemaXmlImport.test.ts +++ b/core/backend/src/test/imodel/SchemaXmlImport.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger, LogLevel } from "@itwin/core-bentley"; import { assert } from "chai"; import * as fs from "fs"; import * as path from "path"; import { PhysicalElement, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; -import { Logger, LogLevel } from "@itwin/core-bentley"; import { KnownTestLocations } from "../KnownTestLocations"; describe("Schema XML Import Tests", () => { @@ -40,5 +40,4 @@ describe("Schema XML Import Tests", () => { assert.equal(testDomainClass.baseClasses.length, 1); assert.equal(testDomainClass.baseClasses[0], PhysicalElement.classFullName); }); - }); diff --git a/core/backend/src/test/misc/DevTools.test.ts b/core/backend/src/test/misc/DevTools.test.ts index 36fcb85a6c58..0b825c28fcc3 100644 --- a/core/backend/src/test/misc/DevTools.test.ts +++ b/core/backend/src/test/misc/DevTools.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger, LogLevel } from "@itwin/core-bentley"; import { assert } from "chai"; import * as os from "os"; -import { Logger, LogLevel } from "@itwin/core-bentley"; import { DevTools, DevToolsStatsFormatter } from "../../core-backend"; interface StringIndexedObject { @@ -84,5 +84,4 @@ describe("DevTools", () => { assert.isDefined(versions.iTwinJs); assert.isDefined(versions.availableRpcs); }); -}, -); +}); diff --git a/core/backend/src/test/misc/GeoServices.test.ts b/core/backend/src/test/misc/GeoServices.test.ts index 29ca60089695..7defef3f1ec9 100644 --- a/core/backend/src/test/misc/GeoServices.test.ts +++ b/core/backend/src/test/misc/GeoServices.test.ts @@ -3,14 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { - GeographicCRSInterpretRequestProps, GeographicCRSProps, -} from "@itwin/core-common"; -import { IModelNative } from "../../internal/NativePlatform"; +import { GeographicCRSInterpretRequestProps, GeographicCRSProps } from "@itwin/core-common"; import { Geometry, Range2d, Range2dProps } from "@itwin/core-geometry"; +import { assert } from "chai"; import { GeoCoordConfig } from "../../GeoCoordConfig"; import { getAvailableCoordinateReferenceSystems } from "../../GeographicCRSServices"; +import { IModelNative } from "../../internal/NativePlatform"; // spell-checker: disable @@ -20,7 +18,6 @@ describe("GeoServices", () => { }); const completionTest = async (incompleteGCS: GeographicCRSProps, completeCRS: GeographicCRSProps) => { - const requestProps: GeographicCRSInterpretRequestProps = { format: "JSON", geographicCRSDef: JSON.stringify(incompleteGCS) }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); @@ -34,17 +31,25 @@ describe("GeoServices", () => { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.method === completeCRS.horizontalCRS!.projection!.method); if (completeCRS.horizontalCRS!.projection!.falseEasting !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.falseEasting !== undefined); - assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseEasting! - completeCRS.horizontalCRS!.projection!.falseEasting) < Geometry.smallMetricDistance); + assert.isTrue( + Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseEasting! - completeCRS.horizontalCRS!.projection!.falseEasting) < + Geometry.smallMetricDistance, + ); } if (completeCRS.horizontalCRS!.projection!.falseNorthing !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.falseNorthing !== undefined); - assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseNorthing! - completeCRS.horizontalCRS!.projection!.falseNorthing) < Geometry.smallMetricDistance); + assert.isTrue( + Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseNorthing! - completeCRS.horizontalCRS!.projection!.falseNorthing) < + Geometry.smallMetricDistance, + ); } assert.isTrue(response.geographicCRS.horizontalCRS!.datum !== undefined && completeCRS.horizontalCRS!.datum !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.id === completeCRS.horizontalCRS!.datum!.id); - assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.ellipsoid !== undefined && completeCRS.horizontalCRS!.datum!.ellipsoid !== undefined); + assert.isTrue( + response.geographicCRS.horizontalCRS!.datum!.ellipsoid !== undefined && completeCRS.horizontalCRS!.datum!.ellipsoid !== undefined, + ); assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.ellipsoid!.id === completeCRS.horizontalCRS!.datum!.ellipsoid!.id); if (response.geographicCRS.additionalTransform !== undefined) { @@ -52,11 +57,34 @@ describe("GeoServices", () => { assert.isTrue(response.geographicCRS.additionalTransform.helmert2DWithZOffset !== undefined); assert.isTrue(completeCRS.additionalTransform!.helmert2DWithZOffset !== undefined); - assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset!.rotDeg - completeCRS.additionalTransform!.helmert2DWithZOffset!.rotDeg) < Geometry.smallAngleDegrees); - assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationX - completeCRS.additionalTransform!.helmert2DWithZOffset!.translationX) < Geometry.smallMetricDistance); - assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationY - completeCRS.additionalTransform!.helmert2DWithZOffset!.translationY) < Geometry.smallMetricDistance); - assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationZ - completeCRS.additionalTransform!.helmert2DWithZOffset!.translationZ) < Geometry.smallMetricDistance); - assert.isTrue(Math.abs(response.geographicCRS.additionalTransform.helmert2DWithZOffset!.scale - completeCRS.additionalTransform!.helmert2DWithZOffset!.scale) < Geometry.smallFraction); + assert.isTrue( + Math.abs( + response.geographicCRS.additionalTransform.helmert2DWithZOffset!.rotDeg - completeCRS.additionalTransform!.helmert2DWithZOffset!.rotDeg, + ) < Geometry.smallAngleDegrees, + ); + assert.isTrue( + Math.abs( + response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationX - + completeCRS.additionalTransform!.helmert2DWithZOffset!.translationX, + ) < Geometry.smallMetricDistance, + ); + assert.isTrue( + Math.abs( + response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationY - + completeCRS.additionalTransform!.helmert2DWithZOffset!.translationY, + ) < Geometry.smallMetricDistance, + ); + assert.isTrue( + Math.abs( + response.geographicCRS.additionalTransform.helmert2DWithZOffset!.translationZ - + completeCRS.additionalTransform!.helmert2DWithZOffset!.translationZ, + ) < Geometry.smallMetricDistance, + ); + assert.isTrue( + Math.abs( + response.geographicCRS.additionalTransform.helmert2DWithZOffset!.scale - completeCRS.additionalTransform!.helmert2DWithZOffset!.scale, + ) < Geometry.smallFraction, + ); } assert.isTrue(response.geographicCRS.verticalCRS !== undefined && completeCRS.verticalCRS !== undefined); @@ -65,11 +93,8 @@ describe("GeoServices", () => { }; describe("Interpret to completion an incomplete GeographicCRS", async () => { - it("should be able to interpret to completion britishNationalGridOld", async () => { - - const britishNationalGridOld: GeographicCRSProps = - { + const britishNationalGridOld: GeographicCRSProps = { horizontalCRS: { datum: { deprecated: true, @@ -110,7 +135,8 @@ describe("GeoServices", () => { id: "WGS84", polarRadius: 6356752.3142, }, - }], + }, + ], }, datumId: "EPSG:6277", deprecated: true, @@ -146,7 +172,6 @@ describe("GeoServices", () => { }); it("should be able to interpret to completion EWRGCS", async () => { - const EWRGCS: GeographicCRSProps = { horizontalCRS: { id: "EPSG:27700", @@ -192,7 +217,8 @@ describe("GeoServices", () => { }, scalePPM: -20.489, }, - }], + }, + ], }, unit: "Meter", projection: { @@ -228,11 +254,22 @@ describe("GeoServices", () => { }, }; - await completionTest({ horizontalCRS: { id: "EPSG:27700" }, verticalCRS: { id: "ELLIPSOID" }, additionalTransform: { helmert2DWithZOffset: { translationX: 284597.3343, translationY: 79859.4651, translationZ: 0, rotDeg: 0.5263624458992088, scale: 0.9996703340508721 } } }, EWRGCS); + await completionTest({ + horizontalCRS: { id: "EPSG:27700" }, + verticalCRS: { id: "ELLIPSOID" }, + additionalTransform: { + helmert2DWithZOffset: { + translationX: 284597.3343, + translationY: 79859.4651, + translationZ: 0, + rotDeg: 0.5263624458992088, + scale: 0.9996703340508721, + }, + }, + }, EWRGCS); }); it("should be able to interpret to completion UTM27Z10", async () => { - const UTM27Z10: GeographicCRSProps = { horizontalCRS: { datum: { @@ -287,7 +324,8 @@ describe("GeoServices", () => { direction: "Direct", fileName: "./Usa/Nadcon/stpaul.l?s", format: "NADCON", - }], + }, + ], }, method: "GridFiles", sourceEllipsoid: { @@ -300,7 +338,8 @@ describe("GeoServices", () => { id: "GRS1980", polarRadius: 6356752.314140348, }, - }], + }, + ], }, datumId: "NAD27", description: "UTM with NAD27 datum, Zone 10, Meter; Central Meridian 123d W", @@ -333,9 +372,7 @@ describe("GeoServices", () => { }); it("should be able to interpret to completion UTM27Z10B", async () => { - - const UTM27Z10B: GeographicCRSProps = - { + const UTM27Z10B: GeographicCRSProps = { horizontalCRS: { datum: { description: "North American Datum of 1927 (US48, AK, HI, and Canada)", @@ -442,7 +479,6 @@ describe("GeoServices", () => { describe("Interpretation of WKT GeographicCRS", async () => { const interpretWKTTest = async (testWKT: string, completeCRS: GeographicCRSProps) => { - const requestProps: GeographicCRSInterpretRequestProps = { format: "WKT", geographicCRSDef: testWKT }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); @@ -456,17 +492,25 @@ describe("GeoServices", () => { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.method === completeCRS.horizontalCRS!.projection!.method); if (completeCRS.horizontalCRS!.projection!.falseEasting !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.falseEasting !== undefined); - assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseEasting! - completeCRS.horizontalCRS!.projection!.falseEasting) < Geometry.smallMetricDistance); + assert.isTrue( + Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseEasting! - completeCRS.horizontalCRS!.projection!.falseEasting) < + Geometry.smallMetricDistance, + ); } if (completeCRS.horizontalCRS!.projection!.falseNorthing !== undefined) { assert.isTrue(response.geographicCRS.horizontalCRS!.projection!.falseNorthing !== undefined); - assert.isTrue(Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseNorthing! - completeCRS.horizontalCRS!.projection!.falseNorthing) < Geometry.smallMetricDistance); + assert.isTrue( + Math.abs(response.geographicCRS.horizontalCRS!.projection!.falseNorthing! - completeCRS.horizontalCRS!.projection!.falseNorthing) < + Geometry.smallMetricDistance, + ); } assert.isTrue(response.geographicCRS.horizontalCRS!.datum !== undefined && completeCRS.horizontalCRS!.datum !== undefined); assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.id === completeCRS.horizontalCRS!.datum!.id); - assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.ellipsoid !== undefined && completeCRS.horizontalCRS!.datum!.ellipsoid !== undefined); + assert.isTrue( + response.geographicCRS.horizontalCRS!.datum!.ellipsoid !== undefined && completeCRS.horizontalCRS!.datum!.ellipsoid !== undefined, + ); assert.isTrue(response.geographicCRS.horizontalCRS!.datum!.ellipsoid!.id === completeCRS.horizontalCRS!.datum!.ellipsoid!.id); assert.isTrue(response.geographicCRS.verticalCRS !== undefined && completeCRS.verticalCRS !== undefined); @@ -478,8 +522,7 @@ describe("GeoServices", () => { }; it("should be able to interpret airportGrid2007 WKT", async () => { - const airportGrid2007: GeographicCRSProps = - { + const airportGrid2007: GeographicCRSProps = { horizontalCRS: { datum: { description: "Heathrow T5 Datum", @@ -542,13 +585,14 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",DATUM["Heathrow T5", SPHEROID["AIRY30",6377563.396,299.32496127],358.398,-213.7028,495.3183,-668.80613932004700,4.72664217602752,-719.67109718139600,-6.26386076385543],PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],PROJECTION["Transverse Mercator"],PARAMETER["latitude_of_origin",51.470110655555558],PARAMETER["central_meridian",-0.41832591666666669],PARAMETER["scale_factor",0.999995],PARAMETER["false_easting",7334.810],PARAMETER["false_northing",5637.423],UNIT["Meter",1.00000000000000]]', airportGrid2007); + await interpretWKTTest( + 'PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",DATUM["Heathrow T5", SPHEROID["AIRY30",6377563.396,299.32496127],358.398,-213.7028,495.3183,-668.80613932004700,4.72664217602752,-719.67109718139600,-6.26386076385543],PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],PROJECTION["Transverse Mercator"],PARAMETER["latitude_of_origin",51.470110655555558],PARAMETER["central_meridian",-0.41832591666666669],PARAMETER["scale_factor",0.999995],PARAMETER["false_easting",7334.810],PARAMETER["false_northing",5637.423],UNIT["Meter",1.00000000000000]]', + airportGrid2007, + ); }); it("should be able to interpret denmarkED50 WKT", async () => { - - const denmarkED50: GeographicCRSProps = - { + const denmarkED50: GeographicCRSProps = { horizontalCRS: { datum: { description: "European 1950, Denmark, for System 34", @@ -616,13 +660,14 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('GEOGCS[ "DummyName", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]', denmarkED50); + await interpretWKTTest( + 'GEOGCS[ "DummyName", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]', + denmarkED50, + ); }); it("should be able to interpret californiaStateZone2 WKT", async () => { - - const californiaStateZone2: GeographicCRSProps = - { + const californiaStateZone2: GeographicCRSProps = { horizontalCRS: { datum: { description: "North American Datum of 1983", @@ -664,13 +709,14 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('PROJCS["NAD_1983_StatePlane_California_II_FIPS_0402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.30480060960121924]]', californiaStateZone2); + await interpretWKTTest( + 'PROJCS["NAD_1983_StatePlane_California_II_FIPS_0402_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",6561666.666666666],PARAMETER["False_Northing",1640416.666666667],PARAMETER["Central_Meridian",-122],PARAMETER["Standard_Parallel_1",38.33333333333334],PARAMETER["Standard_Parallel_2",39.83333333333334],PARAMETER["Latitude_Of_Origin",37.66666666666666],UNIT["Foot_US",0.30480060960121924]]', + californiaStateZone2, + ); }); it("should be able to interpret utm84Zone34S WKT", async () => { - - const utm84Zone34S: GeographicCRSProps = - { + const utm84Zone34S: GeographicCRSProps = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", @@ -711,13 +757,14 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('PROJCS["WGS 84 / UTM zone 34S", GEOGCS [ "WGS 84", DATUM ["World Geodetic System 1984 (EPSG ID 6326)", SPHEROID ["WGS 84 (EPSG ID 7030)", 6378137, 298.257223563]], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994328]], PROJECTION ["UTM zone 34S (EPSG OP 16134)"], PARAMETER ["Latitude_Of_Origin", 0], PARAMETER ["Central_Meridian", 21], PARAMETER ["Scale_Factor", .9996], PARAMETER ["False_Easting", 500000], PARAMETER ["False_Northing", 10000000], UNIT ["Meter", 1]]', utm84Zone34S); + await interpretWKTTest( + 'PROJCS["WGS 84 / UTM zone 34S", GEOGCS [ "WGS 84", DATUM ["World Geodetic System 1984 (EPSG ID 6326)", SPHEROID ["WGS 84 (EPSG ID 7030)", 6378137, 298.257223563]], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994328]], PROJECTION ["UTM zone 34S (EPSG OP 16134)"], PARAMETER ["Latitude_Of_Origin", 0], PARAMETER ["Central_Meridian", 21], PARAMETER ["Scale_Factor", .9996], PARAMETER ["False_Easting", 500000], PARAMETER ["False_Northing", 10000000], UNIT ["Meter", 1]]', + utm84Zone34S, + ); }); it("should be able to interpret utm84Zone32NGeoid WKT", async () => { - - const utm84Zone32NGeoid: GeographicCRSProps = - { + const utm84Zone32NGeoid: GeographicCRSProps = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", @@ -758,12 +805,13 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('COMPD_CS["WGS 84 / UTM zone 32N + EGM96 geoid height",PROJCS["WGS 84 / UTM zone32N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",9],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32632"]],VERT_CS["EGM96 geoid height",VERT_DATUM["EGM96 geoid",2005,EXTENSION["PROJ4_GRIDS","egm96_15.gtx"],AUTHORITY["EPSG","5171"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Up",UP],AUTHORITY["EPSG","5773"]]]', utm84Zone32NGeoid); + await interpretWKTTest( + 'COMPD_CS["WGS 84 / UTM zone 32N + EGM96 geoid height",PROJCS["WGS 84 / UTM zone32N",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",9],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","32632"]],VERT_CS["EGM96 geoid height",VERT_DATUM["EGM96 geoid",2005,EXTENSION["PROJ4_GRIDS","egm96_15.gtx"],AUTHORITY["EPSG","5171"]],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Up",UP],AUTHORITY["EPSG","5773"]]]', + utm84Zone32NGeoid, + ); }); it("should be able to interpret utm84Zone18NGeoid WKT", async () => { - - const utm84Zone18NGeoid: GeographicCRSProps = - { + const utm84Zone18NGeoid: GeographicCRSProps = { horizontalCRS: { datum: { description: "World Geodetic System of 1984", @@ -801,7 +849,10 @@ describe("GeoServices", () => { }, }; - await interpretWKTTest('COMPD_CS["UTM84-18N",PROJCS["UTM84-18N",GEOGCS["LL84",DATUM["WGS84",SPHEROID["WGS84",6378137.000,298.25722293]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Universal Transverse Mercator System"],PARAMETER["UTM Zone Number (1 - 60)",18.0],PARAMETER["Hemisphere, North or South",1.0],UNIT["Meter",1.00000000000000]],VERT_CS["Geoid Height",VERT_DATUM["EGM96 geoid",2005],UNIT["METER",1.000000]]]', utm84Zone18NGeoid); + await interpretWKTTest( + 'COMPD_CS["UTM84-18N",PROJCS["UTM84-18N",GEOGCS["LL84",DATUM["WGS84",SPHEROID["WGS84",6378137.000,298.25722293]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Universal Transverse Mercator System"],PARAMETER["UTM Zone Number (1 - 60)",18.0],PARAMETER["Hemisphere, North or South",1.0],UNIT["Meter",1.00000000000000]],VERT_CS["Geoid Height",VERT_DATUM["EGM96 geoid",2005],UNIT["METER",1.000000]]]', + utm84Zone18NGeoid, + ); }); }); @@ -894,9 +945,7 @@ describe("GeoServices", () => { }); it("should not be able to interpret an invalid GeographicCRS", async () => { - const interpretInvalidTest = async (formatCRS: "WKT" | "JSON", testInvalid: string) => { - const requestProps: GeographicCRSInterpretRequestProps = { format: formatCRS, geographicCRSDef: testInvalid }; const response = IModelNative.platform.GeoServices.getGeographicCRSInterpretation(requestProps); @@ -906,13 +955,19 @@ describe("GeoServices", () => { }; // WKT Without datum or projection clause - await interpretInvalidTest("WKT", 'PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],UNIT["Meter",1.00000000000000]]'); + await interpretInvalidTest( + "WKT", + 'PROJCS["AirportGrid2007", GEOGCS["HeathrowT5.LL",PRIMEM["Greenwich",0],UNIT["Decimal Degree",0.017453292519943295]],UNIT["Meter",1.00000000000000]]', + ); // Plain garbage await interpretInvalidTest("WKT", "Some invalid content"); // Format is JSON but content is WKT - await interpretInvalidTest("JSON", 'GEOGCS[ "Longitude / Latitude (ED 50 Denmark)", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]'); + await interpretInvalidTest( + "JSON", + 'GEOGCS[ "Longitude / Latitude (ED 50 Denmark)", DATUM ["European 1950 (Denmark)", SPHEROID ["International 1924", 6378388, 297],-81.0703, -89.3603, -115.7526, .48488, .02436, .41321, -.540645], PRIMEM [ "Greenwich", 0.000000 ], UNIT ["Decimal Degree", 0.01745329251994330]]', + ); // Vertical datum invalid for horizontal definition await interpretInvalidTest("JSON", '{ horizontalCRS: { id: "EPSG:27700" }, verticalCRS: { id: "NAVD29" } }'); diff --git a/core/backend/src/test/misc/PromiseMemoizer.test.ts b/core/backend/src/test/misc/PromiseMemoizer.test.ts index 8023c5b1df9d..1352c545c6cb 100644 --- a/core/backend/src/test/misc/PromiseMemoizer.test.ts +++ b/core/backend/src/test/misc/PromiseMemoizer.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { BeDuration } from "@itwin/core-bentley"; -import { PromiseMemoizer, QueryablePromise } from "../../PromiseMemoizer"; +import { assert } from "chai"; import * as sinon from "sinon"; +import { PromiseMemoizer, QueryablePromise } from "../../PromiseMemoizer"; describe("PromiseMemoizer", () => { let clock: sinon.SinonFakeTimers | undefined; diff --git a/core/backend/src/test/native/DgnDbWorker.test.ts b/core/backend/src/test/native/DgnDbWorker.test.ts index 7ad2daca8994..c6b90dfdc00b 100644 --- a/core/backend/src/test/native/DgnDbWorker.test.ts +++ b/core/backend/src/test/native/DgnDbWorker.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; +import { IModelJsNative } from "@bentley/imodeljs-native"; import { BeDuration } from "@itwin/core-bentley"; import { Matrix4d } from "@itwin/core-geometry"; -import { IModelNative } from "../../internal/NativePlatform"; +import { assert, expect } from "chai"; import { StandaloneDb } from "../../IModelDb"; -import { IModelTestUtils } from "../IModelTestUtils"; -import { IModelJsNative } from "@bentley/imodeljs-native"; +import { IModelNative } from "../../internal/NativePlatform"; import { _nativeDb } from "../../internal/Symbols"; +import { IModelTestUtils } from "../IModelTestUtils"; describe("DgnDbWorker", () => { let imodel: StandaloneDb; @@ -36,22 +36,50 @@ describe("DgnDbWorker", () => { this._worker = new IModelNative.platform.TestWorker(imodel[_nativeDb]); } - public queue() { this.promise = this._worker.queue(); } - public cancel() { this._worker.cancel(); } - public setReady() { this._worker.setReady(); } - public setThrow() { this._worker.setThrow(); } - - public get isCanceled(): boolean { return this._worker.isCanceled(); } - public get wasExecuted(): boolean { return this._worker.wasExecuted(); } - public get state(): IModelJsNative.TestWorkerState { return this._worker.getState(); } - - public get wasQueued() { return IModelJsNative.TestWorkerState.NotQueued !== this.state; } - public get isQueued() { return IModelJsNative.TestWorkerState.Queued === this.state; } - public get isRunning() { return IModelJsNative.TestWorkerState.Running === this.state; } - public get isError() { return IModelJsNative.TestWorkerState.Error === this.state; } - public get isOk() { return IModelJsNative.TestWorkerState.Ok === this.state; } - public get isSkipped() { return IModelJsNative.TestWorkerState.Skipped === this.state; } - public get isAborted() { return IModelJsNative.TestWorkerState.Aborted === this.state; } + public queue() { + this.promise = this._worker.queue(); + } + public cancel() { + this._worker.cancel(); + } + public setReady() { + this._worker.setReady(); + } + public setThrow() { + this._worker.setThrow(); + } + + public get isCanceled(): boolean { + return this._worker.isCanceled(); + } + public get wasExecuted(): boolean { + return this._worker.wasExecuted(); + } + public get state(): IModelJsNative.TestWorkerState { + return this._worker.getState(); + } + + public get wasQueued() { + return IModelJsNative.TestWorkerState.NotQueued !== this.state; + } + public get isQueued() { + return IModelJsNative.TestWorkerState.Queued === this.state; + } + public get isRunning() { + return IModelJsNative.TestWorkerState.Running === this.state; + } + public get isError() { + return IModelJsNative.TestWorkerState.Error === this.state; + } + public get isOk() { + return IModelJsNative.TestWorkerState.Ok === this.state; + } + public get isSkipped() { + return IModelJsNative.TestWorkerState.Skipped === this.state; + } + public get isAborted() { + return IModelJsNative.TestWorkerState.Aborted === this.state; + } } async function waitUntil(condition: () => boolean): Promise { diff --git a/core/backend/src/test/rpc/response.test.ts b/core/backend/src/test/rpc/response.test.ts index e3aac95a7044..8c9798c7ede1 100644 --- a/core/backend/src/test/rpc/response.test.ts +++ b/core/backend/src/test/rpc/response.test.ts @@ -1,15 +1,24 @@ +import { + HttpServerRequest, + HttpServerResponse, + RpcRequestFulfillment, + RpcRequestStatus, + SerializedRpcRequest, + WebAppRpcProtocol, +} from "@itwin/core-common"; import { expect } from "chai"; +import { brotliDecompressSync, unzipSync } from "node:zlib"; import { SinonStub, stub } from "sinon"; import { Readable, Writable } from "stream"; -import { HttpServerRequest, HttpServerResponse, RpcRequestFulfillment, RpcRequestStatus, SerializedRpcRequest, WebAppRpcProtocol } from "@itwin/core-common"; import { sendResponse } from "../../rpc/web/response"; -import { brotliDecompressSync, unzipSync } from "node:zlib"; /* eslint-disable deprecation/deprecation */ class StubResponse extends Writable implements HttpServerResponse { public chunks: any[] = []; - public get buffer(): Buffer { return Buffer.concat(this.chunks); } + public get buffer(): Buffer { + return Buffer.concat(this.chunks); + } // eslint-disable-next-line @typescript-eslint/naming-convention public override _write(chunk: any, _encoding: BufferEncoding, callback: VoidFunction): void { diff --git a/core/backend/src/test/schema/ClassRegistry.test.ts b/core/backend/src/test/schema/ClassRegistry.test.ts index f9be8898d6d4..c93928af38f6 100644 --- a/core/backend/src/test/schema/ClassRegistry.test.ts +++ b/core/backend/src/test/schema/ClassRegistry.test.ts @@ -2,23 +2,46 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import * as sinon from "sinon"; -import * as path from "path"; +import { OpenMode } from "@itwin/core-bentley"; import { - BisCodeSpec, Code, ConcreteEntityTypes, DefinitionElementProps, ElementAspectProps, ElementProps, EntityMetaData, EntityReferenceSet, ModelProps, - RelatedElement, RelatedElementProps, RelationshipProps, SchemaState, + BisCodeSpec, + Code, + ConcreteEntityTypes, + DefinitionElementProps, + ElementAspectProps, + ElementProps, + EntityMetaData, + EntityReferenceSet, + ModelProps, + RelatedElement, + RelatedElementProps, + RelationshipProps, + SchemaState, } from "@itwin/core-common"; +import { assert, expect } from "chai"; +import * as path from "path"; +import * as sinon from "sinon"; +import { ClassRegistry } from "../../ClassRegistry"; import { - DefinitionElement, DefinitionModel, ElementRefersToElements, EntityReferences, IModelDb, IModelJsFs, Model, RepositoryLink, - Schema, SnapshotDb, SpatialViewDefinition, StandaloneDb, UrlLink, ViewDefinition3d, + DefinitionElement, + DefinitionModel, + ElementRefersToElements, + EntityReferences, + IModelDb, + IModelJsFs, + Model, + RepositoryLink, + Schema, + SnapshotDb, + SpatialViewDefinition, + StandaloneDb, + UrlLink, + ViewDefinition3d, } from "../../core-backend"; -import { IModelTestUtils } from "../IModelTestUtils"; -import { KnownTestLocations } from "../KnownTestLocations"; import { Element } from "../../Element"; import { Schemas } from "../../Schema"; -import { ClassRegistry } from "../../ClassRegistry"; -import { OpenMode } from "@itwin/core-bentley"; +import { IModelTestUtils } from "../IModelTestUtils"; +import { KnownTestLocations } from "../KnownTestLocations"; describe("Class Registry", () => { let imodel: SnapshotDb; @@ -172,14 +195,16 @@ describe("Class Registry - getRootMetaData", () => { }); it("should get the root metadata", async () => { - for (const [testClass, expectedRoot] of [ - ["TestSchema1.TestBase", "BisCore:Element"], - ["TestSchema1.TestDerived", "BisCore:Element"], - ["TestSchema1.ITestMixinForAspectsBase", "BisCore:ElementAspect"], - ["TestSchema1.ITestMixinForAspectsDerived", "BisCore:ElementAspect"], - ["TestSchema1.ITestMixinForElements", "BisCore:Element"], - ["TestSchema1.TestMixedInAndDerived", "BisCore:Element"], - ] as const) { + for ( + const [testClass, expectedRoot] of [ + ["TestSchema1.TestBase", "BisCore:Element"], + ["TestSchema1.TestDerived", "BisCore:Element"], + ["TestSchema1.ITestMixinForAspectsBase", "BisCore:ElementAspect"], + ["TestSchema1.ITestMixinForAspectsDerived", "BisCore:ElementAspect"], + ["TestSchema1.ITestMixinForElements", "BisCore:Element"], + ["TestSchema1.TestMixedInAndDerived", "BisCore:Element"], + ] as const + ) { const rootMetaData = ClassRegistry.getRootEntity(imodel, testClass); expect(rootMetaData.replace(".", ":")).to.equal(expectedRoot); } @@ -232,9 +257,21 @@ describe("Class Registry - generated classes", () => { } class TestGeneratedClasses extends Schema { - public static override get schemaName(): string { return "TestGeneratedClasses"; } + public static override get schemaName(): string { + return "TestGeneratedClasses"; + } public static get classes() { - return [TestModelWithNavProp, TestElementWithNavProp, LinkTableRelWithNavProp, DerivedWithNavProp, Derived2, Derived3, Derived4, Derived5, Derived6]; + return [ + TestModelWithNavProp, + TestElementWithNavProp, + LinkTableRelWithNavProp, + DerivedWithNavProp, + Derived2, + Derived3, + Derived4, + Derived5, + Derived6, + ]; } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { @@ -253,7 +290,9 @@ describe("Class Registry - generated classes", () => { } class TestElementWithNavProp extends DefinitionElement { - public static override get className() { return "TestElementWithNavProp"; } + public static override get className() { + return "TestElementWithNavProp"; + } public static override schema = TestGeneratedClasses; public navProp: RelatedElement; public constructor(props: TestElementWithNavPropProps, inIModel: IModelDb) { @@ -263,7 +302,9 @@ describe("Class Registry - generated classes", () => { } class TestModelWithNavProp extends DefinitionModel { - public static override get className() { return "TestModelWithNavProp"; } + public static override get className() { + return "TestModelWithNavProp"; + } public static override schema = TestGeneratedClasses; public elemNavProp: RelatedElement; public aspectNavProp: RelatedElement; @@ -277,7 +318,9 @@ describe("Class Registry - generated classes", () => { } class LinkTableRelWithNavProp extends ElementRefersToElements { - public static override get className() { return "LinkTableRelWithNavProp"; } + public static override get className() { + return "LinkTableRelWithNavProp"; + } public static override schema = TestGeneratedClasses; public elemNavProp: RelatedElement; public aspectNavProp: RelatedElement; @@ -291,7 +334,9 @@ describe("Class Registry - generated classes", () => { } class DerivedWithNavProp extends TestElementWithNavProp { - public static override get className() { return "DerivedWithNavProp"; } + public static override get className() { + return "DerivedWithNavProp"; + } public static override schema = TestGeneratedClasses; public derivedNavProp: RelatedElement; public constructor(props: DerivedWithNavPropProps, inIModel: IModelDb) { @@ -301,19 +346,29 @@ describe("Class Registry - generated classes", () => { } class Derived2 extends DerivedWithNavProp { - public static override get className() { return "Derived2"; } + public static override get className() { + return "Derived2"; + } } class Derived3 extends Derived2 { - public static override get className() { return "Derived3"; } + public static override get className() { + return "Derived3"; + } } class Derived4 extends Derived3 { - public static override get className() { return "Derived4"; } + public static override get className() { + return "Derived4"; + } } class Derived5 extends Derived4 { - public static override get className() { return "Derived5"; } + public static override get className() { + return "Derived5"; + } } class Derived6 extends Derived5 { - public static override get className() { return "Derived6"; } + public static override get className() { + return "Derived6"; + } } // if a single inherited class is not generated, the entire hierarchy is considered not-generated @@ -409,12 +464,14 @@ describe("Class Registry - generated classes", () => { EntityReferences.fromEntityType(testEntityId, ConcreteEntityTypes.Element), ].filter((x) => x !== undefined)); - const modelTestEntityIds = new Array(2).fill(undefined).map((_, index) => imodel.elements.insertElement({ - classFullName: "TestGeneratedClasses:TestEntity", - prop: `model-value-${index}`, - model: IModelDb.dictionaryId, - code: Code.createEmpty(), - } as TestEntityProps)); + const modelTestEntityIds = new Array(2).fill(undefined).map((_, index) => + imodel.elements.insertElement({ + classFullName: "TestGeneratedClasses:TestEntity", + prop: `model-value-${index}`, + model: IModelDb.dictionaryId, + code: Code.createEmpty(), + } as TestEntityProps) + ); // eslint-disable-next-line @typescript-eslint/naming-convention const GeneratedTestAspectWithNavProp = imodel.getJsClass("TestGeneratedClasses:TestAspectWithNavProp"); @@ -455,12 +512,14 @@ describe("Class Registry - generated classes", () => { // EntityReferences.fromEntityType(relWithNavPropId, ConcreteEntityTypes.Relationship), ].filter((x) => x !== undefined)); - const relTestEntityIds = new Array(3).fill(undefined).map((_, index) => imodel.elements.insertElement({ - classFullName: "TestGeneratedClasses:TestEntity", - prop: `rel-value-${index}`, - model: IModelDb.dictionaryId, - code: Code.createEmpty(), - } as TestEntityProps)); + const relTestEntityIds = new Array(3).fill(undefined).map((_, index) => + imodel.elements.insertElement({ + classFullName: "TestGeneratedClasses:TestEntity", + prop: `rel-value-${index}`, + model: IModelDb.dictionaryId, + code: Code.createEmpty(), + } as TestEntityProps) + ); // eslint-disable-next-line @typescript-eslint/naming-convention const GeneratedLinkTableRelWithNavProp = imodel.getJsClass("TestGeneratedClasses:LinkTableRelWithNavProp"); @@ -627,7 +686,7 @@ describe("Class Registry - generated classes", () => { expect(ActualDerived5.isGeneratedClass).to.be.true; expect(ActualDerived6.isGeneratedClass).to.be.true; - assert.isTrue(ActualTestElementWithNavProp.prototype.hasOwnProperty("collectReferenceIds" )); // should have automatic impl + assert.isTrue(ActualTestElementWithNavProp.prototype.hasOwnProperty("collectReferenceIds")); // should have automatic impl assert.isTrue(ActualDerivedWithNavProp.prototype.hasOwnProperty("collectReferenceIds")); assert.isTrue(ActualDerived2.prototype.hasOwnProperty("collectReferenceIds")); // non-generated; manually implements so has method assert.isFalse(ActualDerived3.prototype.hasOwnProperty("collectReferenceIds")); // base is non-generated so it shouldn't get the automatic impl @@ -744,7 +803,9 @@ describe("Class Registry - generated classes", () => { class Base { public static staticProperty: string = "base"; - public static get sqlName(): string { return `s.${this.staticProperty}`; } + public static get sqlName(): string { + return `s.${this.staticProperty}`; + } } class Derived extends Base { @@ -754,8 +815,8 @@ describe("Static Properties", () => { it("should be inherited, and the subclass should get its own copy", async () => { assert.equal(Base.staticProperty, "base"); assert.equal(Derived.staticProperty, "base"); // Derived inherits Base's staticProperty (via its prototype) - Derived.staticProperty = "derived"; // Derived now gets its own copy of staticProperty - assert.equal(Base.staticProperty, "base"); // Base's staticProperty remains as it was + Derived.staticProperty = "derived"; // Derived now gets its own copy of staticProperty + assert.equal(Base.staticProperty, "base"); // Base's staticProperty remains as it was assert.equal(Derived.staticProperty, "derived"); // Derived's staticProperty is now different assert.equal(Base.sqlName, "s.base"); const d = new Derived(); @@ -763,7 +824,6 @@ describe("Static Properties", () => { const b = new Base(); assert.equal((b.constructor as any).staticProperty, "base"); // Instances of Base see Base.staticProperty }); - }); // TODO: add tests on the new model/aspect prefixes diff --git a/core/backend/src/test/schema/FunctionalDomain.test.ts b/core/backend/src/test/schema/FunctionalDomain.test.ts index 450163718e7f..abf44e40fecb 100644 --- a/core/backend/src/test/schema/FunctionalDomain.test.ts +++ b/core/backend/src/test/schema/FunctionalDomain.test.ts @@ -3,18 +3,36 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Guid, Id64 } from "@itwin/core-bentley"; +import { CodeScopeSpec, CodeSpec, ElementProps, IModel } from "@itwin/core-common"; import { assert, expect } from "chai"; import { join } from "path"; import { restore as sinonRestore, spy as sinonSpy } from "sinon"; -import { Guid, Id64 } from "@itwin/core-bentley"; -import { CodeScopeSpec, CodeSpec, ElementProps, IModel } from "@itwin/core-common"; import { ClassRegistry } from "../../ClassRegistry"; -import { ElementUniqueAspect, OnAspectIdArg, OnAspectPropsArg } from "../../ElementAspect"; import { - _nativeDb, ChannelControl, ChannelKey, FunctionalBreakdownElement, FunctionalComponentElement, FunctionalModel, FunctionalPartition, - FunctionalSchema, InformationPartitionElement, OnChildElementIdArg, OnChildElementPropsArg, OnElementIdArg, OnElementInModelIdArg, - OnElementInModelPropsArg, OnElementPropsArg, OnModelIdArg, OnModelPropsArg, OnSubModelIdArg, OnSubModelPropsArg, Schemas, StandaloneDb, + _nativeDb, + ChannelControl, + ChannelKey, + FunctionalBreakdownElement, + FunctionalComponentElement, + FunctionalModel, + FunctionalPartition, + FunctionalSchema, + InformationPartitionElement, + OnChildElementIdArg, + OnChildElementPropsArg, + OnElementIdArg, + OnElementInModelIdArg, + OnElementInModelPropsArg, + OnElementPropsArg, + OnModelIdArg, + OnModelPropsArg, + OnSubModelIdArg, + OnSubModelPropsArg, + Schemas, + StandaloneDb, } from "../../core-backend"; +import { ElementUniqueAspect, OnAspectIdArg, OnAspectPropsArg } from "../../ElementAspect"; import { ElementOwnsChildElements, ElementOwnsUniqueAspect, SubjectOwnsPartitionElements } from "../../NavigationRelationship"; import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; @@ -26,12 +44,16 @@ const updatedLabel = "updated label"; /** test schema for supplying element/model/aspect classes */ class TestSchema extends FunctionalSchema { - public static override get schemaName() { return "TestFunctional"; } + public static override get schemaName() { + return "TestFunctional"; + } } /** partition element for testing `Element.onSubModelXxx` methods */ class TestFuncPartition extends InformationPartitionElement { - public static override get className() { return "TestFuncPartition"; } + public static override get className() { + return "TestFuncPartition"; + } public static override onSubModelInsert(arg: OnSubModelPropsArg): void { super.onSubModelInsert(arg); @@ -54,7 +76,9 @@ class TestFuncPartition extends InformationPartitionElement { /** for testing `Model.onXxx` methods */ class TestFuncModel extends FunctionalModel { - public static override get className() { return "TestFuncModel"; } + public static override get className() { + return "TestFuncModel"; + } public static dontDelete = ""; public static override onInsert(arg: OnModelPropsArg): void { @@ -114,7 +138,9 @@ class TestFuncModel extends FunctionalModel { /** for testing `Element.onXxx` methods */ class Breakdown extends FunctionalBreakdownElement { - public static override get className() { return "Breakdown"; } + public static override get className() { + return "Breakdown"; + } public static dontDeleteChild = ""; public static override onInsert(arg: OnElementPropsArg): void { @@ -191,7 +217,9 @@ class Breakdown extends FunctionalBreakdownElement { /** for testing `ElementAspect.onXxx` methods */ class TestFuncAspect extends ElementUniqueAspect { - public static override get className() { return "TestFuncAspect"; } + public static override get className() { + return "TestFuncAspect"; + } public static expectedVal = ""; public static override onInsert(arg: OnAspectPropsArg): void { @@ -225,11 +253,12 @@ class TestFuncAspect extends ElementUniqueAspect { } class Component extends FunctionalComponentElement { - public static override get className() { return "Component"; } + public static override get className() { + return "Component"; + } } describe("Functional Domain", () => { - afterEach(() => { sinonRestore(); }); @@ -346,14 +375,20 @@ describe("Functional Domain", () => { const partitionCode = FunctionalPartition.createCode(iModelDb, subject1Id, "Test Functional Model"); const partitionProps = { - classFullName: TestFuncPartition.classFullName, model: IModel.repositoryModelId, - parent: new SubjectOwnsPartitionElements(subject1Id), code: partitionCode, + classFullName: TestFuncPartition.classFullName, + model: IModel.repositoryModelId, + parent: new SubjectOwnsPartitionElements(subject1Id), + code: partitionCode, }; iModelDb.channels.addAllowedChannel(testChannelKey1); let partitionId = iModelDb.elements.insertElement(partitionProps); - const modelId = testChannel(testChannelKey1, () => iModelDb.models.insertModel({ classFullName: TestFuncModel.classFullName, modeledElement: { id: partitionId } }), [spy.model.onInsert]); + const modelId = testChannel( + testChannelKey1, + () => iModelDb.models.insertModel({ classFullName: TestFuncModel.classFullName, modeledElement: { id: partitionId } }), + [spy.model.onInsert], + ); assert.isTrue(Id64.isValidId64(modelId)); assert.isTrue(spy.model.onInsert.calledOnce); @@ -364,13 +399,20 @@ describe("Functional Domain", () => { assert.isTrue(spy.partition.onSubModelInsert.calledOnce); assert.isTrue(spy.partition.onSubModelInserted.calledOnce); - assert.equal(spy.partition.onSubModelInserted.getCall(0).args[0].subModelId, modelId, "Element.onSubModelInserted should have correct subModelId"); - - expect(() => iModelDb.channels.insertChannelSubject({ subjectName: "Test Functional Subject 2", channelKey: testChannelKey1 })).to.throw("a channel root for the specified key already exists"); + assert.equal( + spy.partition.onSubModelInserted.getCall(0).args[0].subModelId, + modelId, + "Element.onSubModelInserted should have correct subModelId", + ); + + expect(() => iModelDb.channels.insertChannelSubject({ subjectName: "Test Functional Subject 2", channelKey: testChannelKey1 })).to.throw( + "a channel root for the specified key already exists", + ); const subject2Id = iModelDb.channels.insertChannelSubject({ subjectName: "Test Functional Subject 2", channelKey: testChannelKey2 }); iModelDb.channels.addAllowedChannel(testChannelKey2); - expect(() => iModelDb.channels.insertChannelSubject({ subjectName: "Nested Subject", parentSubjectId: subject2Id, channelKey: "nested channel" })).to.throw("may not nest"); + expect(() => iModelDb.channels.insertChannelSubject({ subjectName: "Nested Subject", parentSubjectId: subject2Id, channelKey: "nested channel" })) + .to.throw("may not nest"); partitionProps.code.value = "Test Func 2"; partitionProps.parent = new SubjectOwnsPartitionElements(subject2Id); @@ -381,7 +423,11 @@ describe("Functional Domain", () => { assert.equal(spy.model.onInserted.getCall(1).args[0].id, modelId2, "second insert should set new id"); assert.equal(spy.model.onInsert.callCount, 2); assert.equal(spy.model.onInserted.callCount, 2); - assert.equal(spy.partition.onSubModelInserted.getCall(1).args[0].subModelId, modelId2, "Element.onSubModelInserted should have correct subModelId"); + assert.equal( + spy.partition.onSubModelInserted.getCall(1).args[0].subModelId, + modelId2, + "Element.onSubModelInserted should have correct subModelId", + ); const model2 = iModelDb.models.getModel(modelId2); testChannel(testChannelKey2, () => model2.update(), []); @@ -397,8 +443,15 @@ describe("Functional Domain", () => { assert.isTrue(spy.partition.onSubModelDeleted.calledOnce); assert.equal(spy.partition.onSubModelDeleted.getCall(0).args[0].subModelId, modelId2); - const breakdownProps = { classFullName: Breakdown.classFullName, model: modelId, code: { spec: codeSpec.id, scope: modelId, value: "Breakdown1" } }; - const breakdownId = testChannel(testChannelKey1, () => elements.insertElement(breakdownProps), [spy.model.onInsertElement, spy.breakdown.onInsert]); + const breakdownProps = { + classFullName: Breakdown.classFullName, + model: modelId, + code: { spec: codeSpec.id, scope: modelId, value: "Breakdown1" }, + }; + const breakdownId = testChannel(testChannelKey1, () => elements.insertElement(breakdownProps), [ + spy.model.onInsertElement, + spy.breakdown.onInsert, + ]); assert.isTrue(Id64.isValidId64(breakdownId)); assert.isTrue(spy.model.onInsertElement.calledOnce); assert.isTrue(spy.model.onInsertedElement.calledOnce); @@ -409,7 +462,11 @@ describe("Functional Domain", () => { assert.equal(spy.breakdown.onInserted.getCall(0).args[0].id, breakdownId); assert.equal(spy.breakdown.onInsert.getCall(0).args[0].props, breakdownProps); - const breakdown2Props: ElementProps = { classFullName: Breakdown.classFullName, model: modelId, code: { spec: codeSpec.id, scope: modelId, value: "badval" } }; + const breakdown2Props: ElementProps = { + classFullName: Breakdown.classFullName, + model: modelId, + code: { spec: codeSpec.id, scope: modelId, value: "badval" }, + }; // TestFuncModel.onInsertElement throws for this code.value expect(() => elements.insertElement(breakdown2Props)).to.throw("bad element"); diff --git a/core/backend/src/test/schema/GenericDomain.test.ts b/core/backend/src/test/schema/GenericDomain.test.ts index 8092085c5e1d..1646cd881da8 100644 --- a/core/backend/src/test/schema/GenericDomain.test.ts +++ b/core/backend/src/test/schema/GenericDomain.test.ts @@ -2,21 +2,45 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { DbResult, Guid, Id64, Id64String } from "@itwin/core-bentley"; import { - CategoryProps, Code, DefinitionElementProps, ElementProps, GeometricElement3dProps, IModel, PhysicalElementProps, PhysicalTypeProps, + CategoryProps, + Code, + DefinitionElementProps, + ElementProps, + GeometricElement3dProps, + IModel, + PhysicalElementProps, + PhysicalTypeProps, TypeDefinitionElementProps, } from "@itwin/core-common"; +import { assert } from "chai"; import { - DefinitionModel, DocumentListModel, ECSqlStatement, GenericDocument, GenericGraphicalModel3d, GenericGraphicalType2d, GenericPhysicalMaterial, - GenericPhysicalType, GenericSchema, Graphic3d, Group, GroupModel, IModelDb, IModelJsFs, PhysicalElementIsOfPhysicalMaterial, - PhysicalElementIsOfType, PhysicalModel, PhysicalObject, PhysicalTypeIsOfPhysicalMaterial, SnapshotDb, SpatialCategory, + DefinitionModel, + DocumentListModel, + ECSqlStatement, + GenericDocument, + GenericGraphicalModel3d, + GenericGraphicalType2d, + GenericPhysicalMaterial, + GenericPhysicalType, + GenericSchema, + Graphic3d, + Group, + GroupModel, + IModelDb, + IModelJsFs, + PhysicalElementIsOfPhysicalMaterial, + PhysicalElementIsOfType, + PhysicalModel, + PhysicalObject, + PhysicalTypeIsOfPhysicalMaterial, + SnapshotDb, + SpatialCategory, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; describe("Generic Domain", () => { - function count(iModelDb: IModelDb, classFullName: string): number { return iModelDb.withPreparedStatement(`SELECT COUNT(*) FROM ${classFullName}`, (statement: ECSqlStatement): number => { return DbResult.BE_SQLITE_ROW === statement.step() ? statement.getValue(0).getInteger() : 0; diff --git a/core/backend/src/test/sheetindex/SheetIndex.test.ts b/core/backend/src/test/sheetindex/SheetIndex.test.ts index 3f7874413cf8..f772b94e3e0b 100644 --- a/core/backend/src/test/sheetindex/SheetIndex.test.ts +++ b/core/backend/src/test/sheetindex/SheetIndex.test.ts @@ -6,20 +6,26 @@ import { Id64, Id64String } from "@itwin/core-bentley"; import { BisCodeSpec, CodeScopeSpec, CodeSpec, GeometricModel2dProps, RelatedElement, SheetProps } from "@itwin/core-common"; -import { IModelDb, SnapshotDb } from "../../IModelDb"; -import { ExtensiveTestScenario, IModelTestUtils } from "../IModelTestUtils"; -import { DocumentPartition, Sheet } from "../../Element"; import { expect } from "chai"; +import { DocumentPartition, Sheet } from "../../Element"; +import { IModelDb, SnapshotDb } from "../../IModelDb"; import { DocumentListModel, SheetIndexModel, SheetModel } from "../../Model"; -import { ElementOwnsChildElements, SheetIndexFolderOwnsEntries, SheetIndexOwnsEntries, SheetIndexReferenceRefersToSheetIndex, SheetReferenceRefersToSheet } from "../../NavigationRelationship"; +import { + ElementOwnsChildElements, + SheetIndexFolderOwnsEntries, + SheetIndexOwnsEntries, + SheetIndexReferenceRefersToSheetIndex, + SheetReferenceRefersToSheet, +} from "../../NavigationRelationship"; import { SheetIndex, SheetIndexFolder, SheetIndexReference, SheetReference } from "../../SheetIndex"; +import { ExtensiveTestScenario, IModelTestUtils } from "../IModelTestUtils"; export const getOrCreateDocumentList = async (iModel: IModelDb): Promise => { const documentListName = "SheetList"; let documentListModelId: string | undefined; // Attempt to find an existing document partition and document list model - const ids = iModel.queryEntityIds({ from: DocumentPartition.classFullName, where: `CodeValue = '${documentListName}'`}); + const ids = iModel.queryEntityIds({ from: DocumentPartition.classFullName, where: `CodeValue = '${documentListName}'` }); if (ids.size === 1) { documentListModelId = ids.values().next().value; } @@ -118,7 +124,13 @@ describe("SheetIndex", () => { const sheetIndex1Id = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex1Id)).to.be.true; - const folderId = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex1Id, name: "TestFolder", priority: 1 }); + const folderId = SheetIndexFolder.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex1Id, + name: "TestFolder", + priority: 1, + }); expect(Id64.isValidId64(folderId)).to.be.true; const folder = iModel.elements.tryGetElement(folderId); @@ -144,22 +156,37 @@ describe("SheetIndex", () => { const sheetIndex2Id = SheetIndex.insert(iModel, modelId, "TestSheetIndex-2"); expect(Id64.isValidId64(sheetIndex2Id)).to.be.true; - const folderId = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex1Id, name: "TestFolder", priority: 1 }); + const folderId = SheetIndexFolder.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex1Id, + name: "TestFolder", + priority: 1, + }); expect(Id64.isValidId64(folderId)).to.be.true; const folder = iModel.elements.tryGetElement(folderId); expect(folder).to.not.be.undefined; - const parentRel11 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { sourceId: sheetIndex1Id, targetId: folderId }); + const parentRel11 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { + sourceId: sheetIndex1Id, + targetId: folderId, + }); expect(parentRel11).to.not.be.undefined; folder!.parent = new SheetIndexOwnsEntries(sheetIndex2Id); folder!.update(); - const parentRel12 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { sourceId: sheetIndex1Id, targetId: folderId }); + const parentRel12 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { + sourceId: sheetIndex1Id, + targetId: folderId, + }); expect(parentRel12).to.be.undefined; - const parentRel22 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { sourceId: sheetIndex2Id, targetId: folderId }); + const parentRel22 = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { + sourceId: sheetIndex2Id, + targetId: folderId, + }); expect(parentRel22).to.not.be.undefined; }); @@ -175,7 +202,13 @@ describe("SheetIndex", () => { const sheet1Id = await insertSheet(iModel, "sheet-1"); const sheet2Id = await insertSheet(iModel, "sheet-2"); - const sheetRefId = SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndexId, name: "TestSheetReference", priority: 1 }); + const sheetRefId = SheetReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndexId, + name: "TestSheetReference", + priority: 1, + }); expect(Id64.isValidId64(sheetRefId)).to.be.true; const sheetRef = iModel.elements.tryGetElement(sheetRefId); @@ -185,19 +218,31 @@ describe("SheetIndex", () => { sheetRef!.sheet = new SheetReferenceRefersToSheet(sheet1Id); sheetRef!.update(); - const refersRel11 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { sourceId: sheetRefId, targetId: sheet1Id }); + const refersRel11 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { + sourceId: sheetRefId, + targetId: sheet1Id, + }); expect(refersRel11).to.not.be.undefined; - const parentRel12 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { sourceId: sheetRefId, targetId: sheet2Id }); + const parentRel12 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { + sourceId: sheetRefId, + targetId: sheet2Id, + }); expect(parentRel12).to.be.undefined; sheetRef!.sheet = new SheetReferenceRefersToSheet(sheet2Id); sheetRef!.update(); - const refersRel21 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { sourceId: sheetRefId, targetId: sheet1Id }); + const refersRel21 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { + sourceId: sheetRefId, + targetId: sheet1Id, + }); expect(refersRel21).to.be.undefined; - const parentRel22 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { sourceId: sheetRefId, targetId: sheet2Id }); + const parentRel22 = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { + sourceId: sheetRefId, + targetId: sheet2Id, + }); expect(parentRel22).to.not.be.undefined; }); @@ -215,7 +260,13 @@ describe("SheetIndex", () => { const sheetIndex3Id = SheetIndex.insert(iModel, modelId, "TestSheetIndex-3"); expect(Id64.isValidId64(sheetIndex3Id)).to.be.true; - const sheetIndexRefId = SheetIndexReference.insert({iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex1Id, name: "TestSheetReference", priority: 1}); + const sheetIndexRefId = SheetIndexReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex1Id, + name: "TestSheetReference", + priority: 1, + }); expect(Id64.isValidId64(sheetIndexRefId)).to.be.true; const sheetIndexRef = iModel.elements.tryGetElement(sheetIndexRefId); @@ -225,16 +276,25 @@ describe("SheetIndex", () => { sheetIndexRef!.sheetIndex = new SheetIndexReferenceRefersToSheetIndex(sheetIndex2Id); sheetIndexRef!.update(); - const parentRel11 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { sourceId: sheetIndexRefId, targetId: sheetIndex2Id }); + const parentRel11 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { + sourceId: sheetIndexRefId, + targetId: sheetIndex2Id, + }); expect(parentRel11).to.not.be.undefined; sheetIndexRef!.sheetIndex = new SheetIndexReferenceRefersToSheetIndex(sheetIndex3Id); sheetIndexRef!.update(); - const refersRel21 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { sourceId: sheetIndexRefId, targetId: sheetIndex2Id }); + const refersRel21 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { + sourceId: sheetIndexRefId, + targetId: sheetIndex2Id, + }); expect(refersRel21).to.be.undefined; - const parentRel22 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { sourceId: sheetIndexRefId, targetId: sheetIndex3Id }); + const parentRel22 = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { + sourceId: sheetIndexRefId, + targetId: sheetIndex3Id, + }); expect(parentRel22).to.not.be.undefined; }); }); @@ -248,13 +308,22 @@ describe("SheetIndex", () => { const sheetIndexId = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndexId)).to.be.true; - const folderId = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndexId, name: "TestFolder-1", priority: 1}); + const folderId = SheetIndexFolder.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndexId, + name: "TestFolder-1", + priority: 1, + }); expect(Id64.isValidId64(folderId)).to.be.true; const folder = iModel.elements.tryGetElement(folderId); expect(folder).to.not.be.undefined; - const relationship = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { sourceId: sheetIndexId, targetId: folderId }); + const relationship = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { + sourceId: sheetIndexId, + targetId: folderId, + }); expect(relationship).to.not.be.undefined; expect(relationship?.classFullName).equals(SheetIndexOwnsEntries.classFullName); @@ -272,7 +341,8 @@ describe("SheetIndex", () => { const folder = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestFolder", priority: 1 }); expect(Id64.isValidId64(folder)).to.be.true; - const failInsert = () => SheetIndexFolder.insert({iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestFolder", priority: 0 }); + const failInsert = () => + SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestFolder", priority: 0 }); expect(failInsert).throws(); }); @@ -285,15 +355,30 @@ describe("SheetIndex", () => { const sheetIndexId = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndexId)).to.be.true; - const folder1Id = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndexId, name: "TestFolder-1", priority: 1 }); + const folder1Id = SheetIndexFolder.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndexId, + name: "TestFolder-1", + priority: 1, + }); expect(Id64.isValidId64(folder1Id)).to.be.true; - const folder2Id = SheetIndexFolder.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: folder1Id, name: "TestFolder-2", priority: 1 }); + const folder2Id = SheetIndexFolder.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: folder1Id, + name: "TestFolder-2", + priority: 1, + }); expect(Id64.isValidId64(folder2Id)).to.be.true; const folder2 = iModel.elements.tryGetElement(folder2Id); expect(folder2).to.not.be.undefined; - const relationship = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { sourceId: folder1Id, targetId: folder2Id }); + const relationship = iModel.relationships.tryGetInstanceProps(ElementOwnsChildElements.classFullName, { + sourceId: folder1Id, + targetId: folder2Id, + }); expect(relationship).to.not.be.undefined; expect(relationship?.classFullName).equals(SheetIndexFolderOwnsEntries.classFullName); @@ -310,10 +395,17 @@ describe("SheetIndex", () => { const sheetIndex = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex)).to.be.true; - const sheetRef1 = SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef", priority: 1 }); + const sheetRef1 = SheetReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex, + name: "TestSheetRef", + priority: 1, + }); expect(Id64.isValidId64(sheetRef1)).to.be.true; - const failInsert = () => SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef", priority: 0 }); + const failInsert = () => + SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef", priority: 0 }); expect(failInsert).throws(); }); @@ -326,7 +418,13 @@ describe("SheetIndex", () => { const sheetIndex = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex)).to.be.true; - const sheetRef = SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef", priority: 1 }); + const sheetRef = SheetReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex, + name: "TestSheetRef", + priority: 1, + }); expect(Id64.isValidId64(sheetRef)).to.be.true; }); @@ -339,13 +437,23 @@ describe("SheetIndex", () => { const sheetIndex = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex)).to.be.true; - const sheetRefId = SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef", priority: 1, sheetId }); + const sheetRefId = SheetReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex, + name: "TestSheetRef", + priority: 1, + sheetId, + }); expect(Id64.isValidId64(sheetRefId)).to.be.true; const ref = iModel.elements.tryGetElement(sheetRefId); expect(ref).to.not.be.undefined; - const relationship = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { sourceId: sheetRefId, targetId: sheetId }); + const relationship = iModel.relationships.tryGetInstanceProps(SheetReferenceRefersToSheet.classFullName, { + sourceId: sheetRefId, + targetId: sheetId, + }); expect(relationship).to.not.be.undefined; expect(relationship?.classFullName).equals(SheetReferenceRefersToSheet.classFullName); @@ -362,7 +470,8 @@ describe("SheetIndex", () => { SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef-1", priority: 1, sheetId }); - const sameIndex = () => SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef-2", priority: 2, sheetId }); + const sameIndex = () => + SheetReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetRef-2", priority: 2, sheetId }); expect(sameIndex).throws(); }); @@ -377,10 +486,17 @@ describe("SheetIndex", () => { const sheetIndex = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex)).to.be.true; - const sheetIndexRef = SheetIndexReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetIndexRef", priority: 1 }); + const sheetIndexRef = SheetIndexReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex, + name: "TestSheetIndexRef", + priority: 1, + }); expect(Id64.isValidId64(sheetIndexRef)).to.be.true; - const failInsert = () => SheetIndexReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetIndexRef", priority: 0 }); + const failInsert = () => + SheetIndexReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex, name: "TestSheetIndexRef", priority: 0 }); expect(failInsert).throws(); }); @@ -393,7 +509,13 @@ describe("SheetIndex", () => { const sheetIndex1Id = SheetIndex.insert(iModel, modelId, "TestSheetIndex"); expect(Id64.isValidId64(sheetIndex1Id)).to.be.true; - const sheetRef = SheetIndexReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex1Id, name: "TestSheetIndexRef", priority: 1 }); + const sheetRef = SheetIndexReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex1Id, + name: "TestSheetIndexRef", + priority: 1, + }); expect(Id64.isValidId64(sheetRef)).to.be.true; }); @@ -407,13 +529,23 @@ describe("SheetIndex", () => { const sheetIndex2Id = SheetIndex.insert(iModel, modelId, "TestSheetIndex-2"); expect(Id64.isValidId64(sheetIndex1Id)).to.be.true; - const sheetIndexRefId = SheetIndexReference.insert({ iModelDb: iModel, sheetIndexModelId: modelId, parentId: sheetIndex1Id, name: "TestSheetRef", priority: 1, sheetIndexId: sheetIndex2Id }); + const sheetIndexRefId = SheetIndexReference.insert({ + iModelDb: iModel, + sheetIndexModelId: modelId, + parentId: sheetIndex1Id, + name: "TestSheetRef", + priority: 1, + sheetIndexId: sheetIndex2Id, + }); expect(Id64.isValidId64(sheetIndexRefId)).to.be.true; const ref = iModel.elements.tryGetElement(sheetIndexRefId); expect(ref).to.not.be.undefined; - const relationship = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { sourceId: sheetIndexRefId, targetId: sheetIndex2Id }); + const relationship = iModel.relationships.tryGetInstanceProps(SheetIndexReferenceRefersToSheetIndex.classFullName, { + sourceId: sheetIndexRefId, + targetId: sheetIndex2Id, + }); expect(relationship).to.not.be.undefined; expect(relationship?.classFullName).equals(SheetIndexReferenceRefersToSheetIndex.classFullName); diff --git a/core/backend/src/test/standalone/ChangeConflictHandler.test.ts b/core/backend/src/test/standalone/ChangeConflictHandler.test.ts index 816f85c09c19..f4fa3534baf2 100644 --- a/core/backend/src/test/standalone/ChangeConflictHandler.test.ts +++ b/core/backend/src/test/standalone/ChangeConflictHandler.test.ts @@ -3,27 +3,28 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { DbChangeStage, DbConflictCause, DbConflictResolution, DbOpcode, DbResult, DbValueType, Guid, GuidString, Id64String, Logger, LogLevel } from "@itwin/core-bentley"; import { - ElementAspectProps, - FilePropertyProps, - IModel, - SubCategoryAppearance, -} from "@itwin/core-common"; + DbChangeStage, + DbConflictCause, + DbConflictResolution, + DbOpcode, + DbResult, + DbValueType, + Guid, + GuidString, + Id64String, + Logger, + LogLevel, +} from "@itwin/core-bentley"; +import { ElementAspectProps, FilePropertyProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import * as chai from "chai"; import { assert, expect } from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { HubWrappers, KnownTestLocations } from "../"; +import { BriefcaseDb, ChannelControl, DictionaryModel, SpatialCategory, SqliteChangesetReader } from "../../core-backend"; import { HubMock } from "../../HubMock"; -import { - BriefcaseDb, - ChannelControl, - DictionaryModel, - SpatialCategory, - SqliteChangesetReader, -} from "../../core-backend"; -import { IModelTestUtils, TestUserType } from "../IModelTestUtils"; import { ChangesetConflictArgs } from "../../internal/ChangesetConflictArgs"; +import { HubWrappers, KnownTestLocations } from "../"; +import { IModelTestUtils, TestUserType } from "../IModelTestUtils"; chai.use(chaiAsPromised); import sinon = require("sinon"); @@ -40,7 +41,12 @@ async function assertThrowsAsync(test: () => Promise, msg?: string) { } export async function createNewModelAndCategory(rwIModel: BriefcaseDb, parent?: Id64String) { // Create a new physical model. - const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), true, parent); + const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync( + rwIModel, + IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), + true, + parent, + ); // Find or create a SpatialCategory. const dictionary: DictionaryModel = rwIModel.models.getModel(IModel.dictionaryId); @@ -110,7 +116,13 @@ describe("Changeset conflict handler", () => { accessToken1 = await HubWrappers.getAccessToken(TestUserType.SuperManager); accessToken2 = await HubWrappers.getAccessToken(TestUserType.Regular); accessToken3 = await HubWrappers.getAccessToken(TestUserType.Super); - const rwIModelId = await HubMock.createNewIModel({ accessToken: accessToken1, iTwinId, iModelName, description: "TestSubject", noLocks: undefined }); + const rwIModelId = await HubMock.createNewIModel({ + accessToken: accessToken1, + iTwinId, + iModelName, + description: "TestSubject", + noLocks: undefined, + }); assert.isNotEmpty(rwIModelId); b1 = await HubWrappers.downloadAndOpenBriefcase({ accessToken: accessToken1, iTwinId, iModelId: rwIModelId, noLock: true }); b1.channels.addAllowedChannel(ChannelControl.sharedChannelName); @@ -123,7 +135,8 @@ describe("Changeset conflict handler", () => { [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( b1, IModelTestUtils.getUniqueModelCode(b1, "newPhysicalModel"), - true); + true, + ); const dictionary: DictionaryModel = b1.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "ThisTestSpatialCategory"); spatialCategoryId = SpatialCategory.insert( @@ -157,7 +170,11 @@ describe("Changeset conflict handler", () => { } }); - async function spyChangesetConflictHandler(b: BriefcaseDb, cb: () => Promise, test: (s: sinon.SinonSpy) => void) { + async function spyChangesetConflictHandler( + b: BriefcaseDb, + cb: () => Promise, + test: (s: sinon.SinonSpy) => void, + ) { const s1 = sinon.spy(b, "onChangesetConflict" as any) as sinon.SinonSpy; try { await cb(); @@ -167,7 +184,11 @@ describe("Changeset conflict handler", () => { } } - async function stubChangesetConflictHandler(b: BriefcaseDb, cb: () => Promise, test: (s: sinon.SinonStub) => void) { + async function stubChangesetConflictHandler( + b: BriefcaseDb, + cb: () => Promise, + test: (s: sinon.SinonStub) => void, + ) { const s1 = sinon.stub(b as any, "onChangesetConflict" as any); try { test(s1 as sinon.SinonStub); @@ -176,7 +197,11 @@ describe("Changeset conflict handler", () => { s1.restore(); } } - async function fakeChangesetConflictHandler(b: BriefcaseDb, cb: () => Promise, interceptMethod: (arg: ChangesetConflictArgs) => DbConflictResolution | undefined) { + async function fakeChangesetConflictHandler( + b: BriefcaseDb, + cb: () => Promise, + interceptMethod: (arg: ChangesetConflictArgs) => DbConflictResolution | undefined, + ) { const s1 = sinon.stub(b as any, "onChangesetConflict" as any); s1.callsFake(interceptMethod); try { @@ -218,9 +243,11 @@ describe("Changeset conflict handler", () => { await spyChangesetConflictHandler( b1, - async () => assertThrowsAsync( - async () => b1.pushChanges({ accessToken: accessToken1, description: "" }), - "PRIMARY KEY INSERT CONFLICT - rejecting this changeset"), + async () => + assertThrowsAsync( + async () => b1.pushChanges({ accessToken: accessToken1, description: "" }), + "PRIMARY KEY INSERT CONFLICT - rejecting this changeset", + ), (spy) => { expect(spy.callCount).eq(1); expect(spy.alwaysReturned(DbConflictResolution.Abort)).true; @@ -286,9 +313,11 @@ describe("Changeset conflict handler", () => { await spyChangesetConflictHandler( b1, - async () => assertThrowsAsync( - async () => b1.pushChanges({ accessToken: accessToken1, description: "" }), - "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered."), + async () => + assertThrowsAsync( + async () => b1.pushChanges({ accessToken: accessToken1, description: "" }), + "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered.", + ), (spy) => { expect(spy.callCount).eq(1); expect(spy.alwaysReturned(DbConflictResolution.Abort)).true; @@ -368,9 +397,11 @@ describe("Changeset conflict handler", () => { await spyChangesetConflictHandler( b2, - async () => assertThrowsAsync( - async () => b2.pushChanges({ accessToken: accessToken1, description: "" }), - "Error in native callback"), + async () => + assertThrowsAsync( + async () => b2.pushChanges({ accessToken: accessToken1, description: "" }), + "Error in native callback", + ), (spy) => { expect(spy.callCount).eq(2); expect(spy.returnValues[0]).eq(DbConflictResolution.Skip); @@ -413,9 +444,11 @@ describe("Changeset conflict handler", () => { await spyChangesetConflictHandler( b2, - async () => assertThrowsAsync( - async () => b2.pullChanges({ accessToken: accessToken1 }), - "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered."), + async () => + assertThrowsAsync( + async () => b2.pullChanges({ accessToken: accessToken1 }), + "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered.", + ), (spy) => { expect(spy.callCount).eq(1); expect(spy.alwaysReturned(DbConflictResolution.Abort)).true; @@ -430,7 +463,6 @@ describe("Changeset conflict handler", () => { b2, async () => b2.pushChanges({ accessToken: accessToken1, description: "" }), (arg: ChangesetConflictArgs) => { - // *** SqliteChangeReader API test *** const reader = SqliteChangesetReader.openFile({ fileName: arg.changesetFile!, db: b2 }); expect(reader.step()).is.true; @@ -591,4 +623,3 @@ describe("Changeset conflict handler", () => { ); }); }); - diff --git a/core/backend/src/test/standalone/ChangesetReader.test.ts b/core/backend/src/test/standalone/ChangesetReader.test.ts index 9477a74b3473..2d7d234e11f1 100644 --- a/core/backend/src/test/standalone/ChangesetReader.test.ts +++ b/core/backend/src/test/standalone/ChangesetReader.test.ts @@ -9,12 +9,12 @@ import { assert, expect } from "chai"; import * as path from "node:path"; import { DrawingCategory } from "../../Category"; import { ChangesetECAdaptor as ECChangesetAdaptor, PartialECChangeUnifier } from "../../ChangesetECAdaptor"; +import { _nativeDb, ChannelControl } from "../../core-backend"; import { HubMock } from "../../HubMock"; import { BriefcaseDb, SnapshotDb } from "../../IModelDb"; import { SqliteChangeOp, SqliteChangesetReader } from "../../SqliteChangesetReader"; import { HubWrappers, IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; -import { _nativeDb, ChannelControl } from "../../core-backend"; describe("Changeset Reader API", async () => { let iTwinId: GuidString; @@ -60,7 +60,12 @@ describe("Changeset Reader API", async () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); // Insert element with 100 properties const geomArray: Arc3d[] = [ @@ -103,7 +108,8 @@ describe("Changeset Reader API", async () => { return { [`p${i}`]: `updated_${i}` }; }).reduce((acc, curr) => { return { ...acc, ...curr }; - }, {})); + }, {}), + ); await rwIModel.locks.acquireLocks({ exclusive: id }); rwIModel.elements.updateElement(updatedElementProps); @@ -124,7 +130,9 @@ describe("Changeset Reader API", async () => { const reader = SqliteChangesetReader.openFile({ fileName: changesets[1].pathname, db: rwIModel, disableSchemaCheck: true }); // Set ExclusiveRootClassId to NULL for overflow table to simulate the issue - expect(rwIModel[_nativeDb].executeSql("UPDATE ec_Table SET ExclusiveRootClassId=NULL WHERE Name='bis_GeometricElement2d_Overflow'")).to.be.eq(DbResult.BE_SQLITE_OK); + expect(rwIModel[_nativeDb].executeSql("UPDATE ec_Table SET ExclusiveRootClassId=NULL WHERE Name='bis_GeometricElement2d_Overflow'")).to.be.eq( + DbResult.BE_SQLITE_OK, + ); const adaptor = new ECChangesetAdaptor(reader); let assertOnOverflowTable = false; @@ -202,7 +210,12 @@ describe("Changeset Reader API", async () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); rwIModel.saveChanges("user 1: create drawing partition"); if ("push changes") { @@ -532,7 +545,12 @@ describe("Changeset Reader API", async () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); rwIModel.saveChanges(); await rwIModel.pushChanges({ description: "setup category", accessToken: adminToken }); @@ -559,7 +577,7 @@ describe("Changeset Reader API", async () => { geom: geometryStream, ...args, }; - return rwIModel.elements.insertElement(e1);; + return rwIModel.elements.insertElement(e1); }; const updateEl = async (id: Id64String, args: { [key: string]: any }) => { await rwIModel.locks.acquireLocks({ exclusive: id }); @@ -682,7 +700,12 @@ describe("Changeset Reader API", async () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); rwIModel.saveChanges(); await rwIModel.pushChanges({ description: "setup category", accessToken: adminToken }); @@ -736,9 +759,19 @@ describe("Changeset Reader API", async () => { const instances: ({ id: string, classId?: string, op: SqliteChangeOp, classFullName?: string })[] = []; while (adaptor.step()) { if (adaptor.inserted) { - instances.push({ id: adaptor.inserted?.ECInstanceId, classId: adaptor.inserted.ECClassId, op: adaptor.op, classFullName: adaptor.inserted.$meta?.classFullName }); + instances.push({ + id: adaptor.inserted?.ECInstanceId, + classId: adaptor.inserted.ECClassId, + op: adaptor.op, + classFullName: adaptor.inserted.$meta?.classFullName, + }); } else if (adaptor.deleted) { - instances.push({ id: adaptor.deleted?.ECInstanceId, classId: adaptor.deleted.ECClassId, op: adaptor.op, classFullName: adaptor.deleted.$meta?.classFullName }); + instances.push({ + id: adaptor.deleted?.ECInstanceId, + classId: adaptor.deleted.ECClassId, + op: adaptor.op, + classFullName: adaptor.deleted.$meta?.classFullName, + }); } } expect(instances.length).to.eq(1); @@ -749,14 +782,28 @@ describe("Changeset Reader API", async () => { } if ("Grouping changeset [3,4] should contain update+delete=delete TestDomain:Test2dElement") { - const reader = SqliteChangesetReader.openGroup({ changesetFiles: changesets.slice(1).map((c) => c.pathname), db: rwIModel, disableSchemaCheck: true }); + const reader = SqliteChangesetReader.openGroup({ + changesetFiles: changesets.slice(1).map((c) => c.pathname), + db: rwIModel, + disableSchemaCheck: true, + }); const adaptor = new ECChangesetAdaptor(reader); const instances: ({ id: string, classId?: string, op: SqliteChangeOp, classFullName?: string })[] = []; while (adaptor.step()) { if (adaptor.inserted) { - instances.push({ id: adaptor.inserted?.ECInstanceId, classId: adaptor.inserted.ECClassId, op: adaptor.op, classFullName: adaptor.inserted.$meta?.classFullName }); + instances.push({ + id: adaptor.inserted?.ECInstanceId, + classId: adaptor.inserted.ECClassId, + op: adaptor.op, + classFullName: adaptor.inserted.$meta?.classFullName, + }); } else if (adaptor.deleted) { - instances.push({ id: adaptor.deleted?.ECInstanceId, classId: adaptor.deleted.ECClassId, op: adaptor.op, classFullName: adaptor.deleted.$meta?.classFullName }); + instances.push({ + id: adaptor.deleted?.ECInstanceId, + classId: adaptor.deleted.ECClassId, + op: adaptor.op, + classFullName: adaptor.deleted.$meta?.classFullName, + }); } } expect(instances.length).to.eq(3); @@ -781,14 +828,28 @@ describe("Changeset Reader API", async () => { } const groupCsFile = path.join(KnownTestLocations.outputDir, "changeset_grouping.ec"); if ("Grouping changeset [2,3] should contain insert+update=insert TestDomain:Test2dElement") { - const reader = SqliteChangesetReader.openGroup({ changesetFiles: changesets.slice(0, 2).map((c) => c.pathname), db: rwIModel, disableSchemaCheck: true }); + const reader = SqliteChangesetReader.openGroup({ + changesetFiles: changesets.slice(0, 2).map((c) => c.pathname), + db: rwIModel, + disableSchemaCheck: true, + }); const adaptor = new ECChangesetAdaptor(reader); const instances: ({ id: string, classId?: string, op: SqliteChangeOp, classFullName?: string })[] = []; while (adaptor.step()) { if (adaptor.inserted) { - instances.push({ id: adaptor.inserted?.ECInstanceId, classId: adaptor.inserted.ECClassId, op: adaptor.op, classFullName: adaptor.inserted.$meta?.classFullName }); + instances.push({ + id: adaptor.inserted?.ECInstanceId, + classId: adaptor.inserted.ECClassId, + op: adaptor.op, + classFullName: adaptor.inserted.$meta?.classFullName, + }); } else if (adaptor.deleted) { - instances.push({ id: adaptor.deleted?.ECInstanceId, classId: adaptor.deleted.ECClassId, op: adaptor.op, classFullName: adaptor.deleted.$meta?.classFullName }); + instances.push({ + id: adaptor.deleted?.ECInstanceId, + classId: adaptor.deleted.ECClassId, + op: adaptor.op, + classFullName: adaptor.deleted.$meta?.classFullName, + }); } } expect(instances.length).to.eq(3); @@ -819,9 +880,19 @@ describe("Changeset Reader API", async () => { const instances: ({ id: string, classId?: string, op: SqliteChangeOp, classFullName?: string })[] = []; while (adaptor.step()) { if (adaptor.inserted) { - instances.push({ id: adaptor.inserted?.ECInstanceId, classId: adaptor.inserted.ECClassId, op: adaptor.op, classFullName: adaptor.inserted.$meta?.classFullName }); + instances.push({ + id: adaptor.inserted?.ECInstanceId, + classId: adaptor.inserted.ECClassId, + op: adaptor.op, + classFullName: adaptor.inserted.$meta?.classFullName, + }); } else if (adaptor.deleted) { - instances.push({ id: adaptor.deleted?.ECInstanceId, classId: adaptor.deleted.ECClassId, op: adaptor.op, classFullName: adaptor.deleted.$meta?.classFullName }); + instances.push({ + id: adaptor.deleted?.ECInstanceId, + classId: adaptor.deleted.ECClassId, + op: adaptor.op, + classFullName: adaptor.deleted.$meta?.classFullName, + }); } } expect(instances.length).to.eq(3); diff --git a/core/backend/src/test/standalone/CustomViewState3dCreator.test.ts b/core/backend/src/test/standalone/CustomViewState3dCreator.test.ts index a0e4810e7efb..0bf0f3ee5b77 100644 --- a/core/backend/src/test/standalone/CustomViewState3dCreator.test.ts +++ b/core/backend/src/test/standalone/CustomViewState3dCreator.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { CompressedId64Set, Id64String } from "@itwin/core-bentley"; import { CustomViewState3dProps } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; +import { assert } from "chai"; +import { CustomViewState3dCreator } from "../../CustomViewState3dCreator"; import { SnapshotDb } from "../../IModelDb"; -import { CompressedId64Set, Id64String} from "@itwin/core-bentley"; import { IModelTestUtils } from "../IModelTestUtils"; -import { CustomViewState3dCreator } from "../../CustomViewState3dCreator"; -import { Range3d } from "@itwin/core-geometry"; describe("CustomViewState3dCreator", () => { let imodel: SnapshotDb; @@ -28,7 +28,14 @@ describe("CustomViewState3dCreator", () => { it("should get correct data from customviewstate3dcreator", async () => { const expectedCatIds = new Set().add("0x17"); const expectedModelIds = new Set().add("0x1c").add("0x28"); - const expectedModelExtents: Range3d = new Range3d(288874.09375, 3803760.75, -0.0005000000237487257, 289160.84375, 3803959.5, 0.0005000000237487257); + const expectedModelExtents: Range3d = new Range3d( + 288874.09375, + 3803760.75, + -0.0005000000237487257, + 289160.84375, + 3803959.5, + 0.0005000000237487257, + ); const customViewStateCreator = new CustomViewState3dCreator(imodel); const result: CustomViewState3dProps = await customViewStateCreator.getCustomViewState3dData({}); @@ -44,7 +51,9 @@ describe("CustomViewState3dCreator", () => { const expectedModelExtents: Range3d = new Range3d(1e200, 1e200, 1e200, -1e200, -1e200, -1e200); const customViewStateCreator = new CustomViewState3dCreator(imodel); - const result: CustomViewState3dProps = await customViewStateCreator.getCustomViewState3dData({modelIds: CompressedId64Set.compressArray(["0x28"])}); + const result: CustomViewState3dProps = await customViewStateCreator.getCustomViewState3dData({ + modelIds: CompressedId64Set.compressArray(["0x28"]), + }); const catIds = CompressedId64Set.decompressSet(result.categoryIds); const modelIds = CompressedId64Set.decompressSet(result.modelIds); assert.isTrue(setsAreEqual(expectedCatIds, catIds)); diff --git a/core/backend/src/test/standalone/DisplayStyle.test.ts b/core/backend/src/test/standalone/DisplayStyle.test.ts index aaa5fc22256e..31d5d98767ef 100644 --- a/core/backend/src/test/standalone/DisplayStyle.test.ts +++ b/core/backend/src/test/standalone/DisplayStyle.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CompressedId64Set, Guid } from "@itwin/core-bentley"; import { DisplayStyle3dSettingsProps, DisplayStyleSettingsProps, IModel, SkyBoxImageType, SkyBoxProps } from "@itwin/core-common"; +import { expect } from "chai"; import { DisplayStyle3d, IModelElementCloneContext, StandaloneDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -76,8 +76,15 @@ describe("DisplayStyle", () => { roundTrip({ image: { type: SkyBoxImageType.Spherical, texture: "0x123" } }); roundTrip({ image: { type: SkyBoxImageType.Spherical, texture: "images/sky.jpg" } }); - roundTrip({ image: { type: SkyBoxImageType.Cube, textures: { front: "0x1", back: "0x2", left: "0x3", right: "0x4", top: "0x5", bottom: "0x6" } } }); - roundTrip({ image: { type: SkyBoxImageType.Cube, textures: { front: "front.jpg", back: "back.png", left: "left.jpeg", right: "right.jpg", top: "top.png", bottom: "bottom.png" } } }); + roundTrip({ + image: { type: SkyBoxImageType.Cube, textures: { front: "0x1", back: "0x2", left: "0x3", right: "0x4", top: "0x5", bottom: "0x6" } }, + }); + roundTrip({ + image: { + type: SkyBoxImageType.Cube, + textures: { front: "front.jpg", back: "back.png", left: "left.jpeg", right: "right.jpg", top: "top.png", bottom: "bottom.png" }, + }, + }); }); describe("onClone", () => { @@ -106,7 +113,7 @@ describe("DisplayStyle", () => { it("remaps excludedElements when cloning", () => { const cloneContext = new IModelElementCloneContext(db, db2); - const displayStyleJsonProps: DisplayStyleSettingsProps = {excludedElements: ["0x1", "0x2", "0x3", "0x4"]}; + const displayStyleJsonProps: DisplayStyleSettingsProps = { excludedElements: ["0x1", "0x2", "0x3", "0x4"] }; const displayStyleId = DisplayStyle3d.insert(db, IModel.dictionaryId, "TestStyle", displayStyleJsonProps); cloneContext.remapElement("0x1", "0xa"); @@ -114,19 +121,21 @@ describe("DisplayStyle", () => { const displayStyle = db.elements.getElement(displayStyleId); const displayStyleClone = cloneContext.cloneElement(displayStyle); - const excludedElementsClone = CompressedId64Set.decompressArray(displayStyleClone.jsonProperties.styles.excludedElements); + const excludedElementsClone = CompressedId64Set.decompressArray(displayStyleClone.jsonProperties.styles.excludedElements); expect(excludedElementsClone.length).to.equal(2); expect(excludedElementsClone).to.contain.members(["0xa", "0xc"]); }); it("remaps subCategory overrides when cloning", () => { const cloneContext = new IModelElementCloneContext(db, db2); - const displayStyleJsonProps: DisplayStyleSettingsProps = {subCategoryOvr: [ - {subCategory: "0x1", weight: 5}, - {subCategory: "0x2", weight: 3}, - {subCategory: "0x3", invisible: false}, - {subCategory: "0x4", invisible: true}, - ]}; + const displayStyleJsonProps: DisplayStyleSettingsProps = { + subCategoryOvr: [ + { subCategory: "0x1", weight: 5 }, + { subCategory: "0x2", weight: 3 }, + { subCategory: "0x3", invisible: false }, + { subCategory: "0x4", invisible: true }, + ], + }; const displayStyleId = DisplayStyle3d.insert(db, IModel.dictionaryId, "TestStyle", displayStyleJsonProps); cloneContext.remapElement("0x1", "0xa"); @@ -134,11 +143,11 @@ describe("DisplayStyle", () => { const displayStyle = db.elements.getElement(displayStyleId); const displayStyleClone = cloneContext.cloneElement(displayStyle); - const subCategoryOvrClone = displayStyleClone.jsonProperties.styles.subCategoryOvr; + const subCategoryOvrClone = displayStyleClone.jsonProperties.styles.subCategoryOvr; expect(subCategoryOvrClone.length).to.equal(2); expect(subCategoryOvrClone).to.deep.contain.members([ - {subCategory: "0xa", weight: 5}, - {subCategory: "0xd", invisible: true}, + { subCategory: "0xa", weight: 5 }, + { subCategory: "0xd", invisible: true }, ]); }); }); diff --git a/core/backend/src/test/standalone/ElementGraphics.test.ts b/core/backend/src/test/standalone/ElementGraphics.test.ts index 7af47897c0a1..e2dc0270205d 100644 --- a/core/backend/src/test/standalone/ElementGraphics.test.ts +++ b/core/backend/src/test/standalone/ElementGraphics.test.ts @@ -3,10 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { assert } from "@itwin/core-bentley"; -import { CurrentImdlVersion, DynamicGraphicsRequest3dProps, ElementGeometry, ElementGeometryDataEntry, ElementGraphicsRequestProps, GeometryStreamIterator } from "@itwin/core-common"; import { ElementGraphicsStatus } from "@bentley/imodeljs-native"; +import { assert } from "@itwin/core-bentley"; +import { + CurrentImdlVersion, + DynamicGraphicsRequest3dProps, + ElementGeometry, + ElementGeometryDataEntry, + ElementGraphicsRequestProps, + GeometryStreamIterator, +} from "@itwin/core-common"; +import { expect } from "chai"; import { _nativeDb, GeometricElement3d, SnapshotDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -14,7 +21,10 @@ describe("ElementGraphics", () => { let imodel: SnapshotDb; before(() => { - imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("ElementGraphics", "mirukuru.ibim"), IModelTestUtils.resolveAssetFile("mirukuru.ibim")); + imodel = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("ElementGraphics", "mirukuru.ibim"), + IModelTestUtils.resolveAssetFile("mirukuru.ibim"), + ); }); after(() => { diff --git a/core/backend/src/test/standalone/ElementMesh.test.ts b/core/backend/src/test/standalone/ElementMesh.test.ts index 2abd8a10fd51..dadfa4e00642 100644 --- a/core/backend/src/test/standalone/ElementMesh.test.ts +++ b/core/backend/src/test/standalone/ElementMesh.test.ts @@ -2,16 +2,30 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; import { - Loop, Path, Point3d, PolyfaceBuilder, Range3d, StrokeOptions, -} from "@itwin/core-geometry"; -import { - Code, ColorDef, GeometricElement3dProps, GeometryParams, GeometryPartProps, GeometryStreamBuilder, GeometryStreamEntryProps, IModel, readElementMeshes, + Code, + ColorDef, + GeometricElement3dProps, + GeometryParams, + GeometryPartProps, + GeometryStreamBuilder, + GeometryStreamEntryProps, + IModel, + readElementMeshes, } from "@itwin/core-common"; +import { Loop, Path, Point3d, PolyfaceBuilder, Range3d, StrokeOptions } from "@itwin/core-geometry"; +import { expect } from "chai"; import { - _nativeDb, GenericSchema, GeometryPart, PhysicalModel, PhysicalObject, PhysicalPartition, SnapshotDb, SpatialCategory, SubjectOwnsPartitionElements, + _nativeDb, + GenericSchema, + GeometryPart, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + SnapshotDb, + SpatialCategory, + SubjectOwnsPartitionElements, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -47,7 +61,7 @@ describe("generateElementMeshes", () => { }); it("throws if source is not a geometric element", async () => { - await expect(imodel[_nativeDb].generateElementMeshes({source: "NotAnId"})).rejectedWith("Geometric element required"); + await expect(imodel[_nativeDb].generateElementMeshes({ source: "NotAnId" })).rejectedWith("Geometric element required"); }); function insertTriangleElement(origin = [0, 0, 0]): string { @@ -66,7 +80,7 @@ describe("generateElementMeshes", () => { geom, placement: { origin, - angles: { }, + angles: {}, }, }; @@ -77,7 +91,7 @@ describe("generateElementMeshes", () => { it("produces a polyface", async () => { const source = insertTriangleElement(); - const bytes = await imodel[_nativeDb].generateElementMeshes({source}); + const bytes = await imodel[_nativeDb].generateElementMeshes({ source }); const meshes = readElementMeshes(bytes); expect(meshes.length).to.equal(1); expect(meshes[0].range().isAlmostEqual(new Range3d(0, 0, 0, 1, 1, 0))).to.be.true; @@ -85,7 +99,7 @@ describe("generateElementMeshes", () => { it("applies element placement transform", async () => { const source = insertTriangleElement([5, 0, -2]); - const bytes = await imodel[_nativeDb].generateElementMeshes({source}); + const bytes = await imodel[_nativeDb].generateElementMeshes({ source }); const meshes = readElementMeshes(bytes); expect(meshes.length).to.equal(1); expect(meshes[0].range().isAlmostEqual(new Range3d(5, 0, -2, 6, 1, -2))).to.be.true; @@ -110,7 +124,7 @@ describe("generateElementMeshes", () => { elBldr.appendGeometryPart3d(partId, new Point3d(0, 0, -1)); const source = insertElement(elBldr.geometryStream, [2, -4, 0]); - const bytes = await imodel[_nativeDb].generateElementMeshes({source}); + const bytes = await imodel[_nativeDb].generateElementMeshes({ source }); const meshes = readElementMeshes(bytes); expect(meshes.length).to.equal(2); expect(meshes[0].range().isAlmostEqual(new Range3d(2, -4, 1, 3, -3, 1))).to.be.true; @@ -124,7 +138,7 @@ describe("generateElementMeshes", () => { bldr.appendGeometry(Loop.createPolygon([new Point3d(0, 0, 5), new Point3d(1, 0, 5), new Point3d(0, 1, 5), new Point3d(0, 0, 5)])); const source = insertElement(bldr.geometryStream); - const meshes = readElementMeshes(await imodel[_nativeDb].generateElementMeshes({source})); + const meshes = readElementMeshes(await imodel[_nativeDb].generateElementMeshes({ source })); expect(meshes.length).to.equal(2); expect(meshes[0].range().isAlmostEqual(new Range3d(0, 0, 0, 1, 1, 0))).to.be.true; expect(meshes[1].range().isAlmostEqual(new Range3d(0, 0, 5, 1, 1, 5))).to.be.true; @@ -138,7 +152,7 @@ describe("generateElementMeshes", () => { bldr.appendGeometry(Loop.createPolygon([new Point3d(0, 0, 5), new Point3d(1, 0, 5), new Point3d(0, 1, 5), new Point3d(0, 0, 5)])); const source = insertElement(bldr.geometryStream); - const meshes = readElementMeshes(await imodel[_nativeDb].generateElementMeshes({source})); + const meshes = readElementMeshes(await imodel[_nativeDb].generateElementMeshes({ source })); expect(meshes.length).to.equal(2); expect(meshes[0].range().isAlmostEqual(new Range3d(0, 0, 0, 1, 1, 0))).to.be.true; expect(meshes[1].range().isAlmostEqual(new Range3d(0, 0, 5, 1, 1, 5))).to.be.true; @@ -159,7 +173,7 @@ describe("generateElementMeshes", () => { bldr.appendGeometry(pf); const source = insertElement(bldr.geometryStream, [10, 0, 0]); - const bytes = await imodel[_nativeDb].generateElementMeshes({source}); + const bytes = await imodel[_nativeDb].generateElementMeshes({ source }); const meshes = readElementMeshes(bytes); expect(meshes.length).to.equal(1); expect(meshes[0].pointCount).to.equal(3); diff --git a/core/backend/src/test/standalone/ExportGraphics.test.ts b/core/backend/src/test/standalone/ExportGraphics.test.ts index eb042c2ca07d..12f330d52fb3 100644 --- a/core/backend/src/test/standalone/ExportGraphics.test.ts +++ b/core/backend/src/test/standalone/ExportGraphics.test.ts @@ -3,19 +3,57 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as fs from "fs"; import { Id64, Id64Array, Id64String } from "@itwin/core-bentley"; import { - Code, ColorDef, DbResult, ElementGeometryInfo, ElementGeometryOpcode, FillDisplay, GeometryClass, GeometryParams, GeometryPartProps, GeometryStreamBuilder, GeometryStreamProps, - ImageSourceFormat, IModel, LineStyle, PhysicalElementProps, Point2dProps, TextureMapProps, TextureMapUnits, + Code, + ColorDef, + DbResult, + ElementGeometryInfo, + ElementGeometryOpcode, + FillDisplay, + GeometryClass, + GeometryParams, + GeometryPartProps, + GeometryStreamBuilder, + GeometryStreamProps, + ImageSourceFormat, + IModel, + LineStyle, + PhysicalElementProps, + Point2dProps, + TextureMapProps, + TextureMapUnits, } from "@itwin/core-common"; import { - Angle, Box, GeometryQuery, GrowableXYArray, GrowableXYZArray, LineSegment3d, LineString3d, Loop, Point3d, PolyfaceBuilder, Range3d, Sphere, StrokeOptions, Vector3d, + Angle, + Box, + GeometryQuery, + GrowableXYArray, + GrowableXYZArray, + LineSegment3d, + LineString3d, + Loop, + Point3d, + PolyfaceBuilder, + Range3d, + Sphere, + StrokeOptions, + Vector3d, } from "@itwin/core-geometry"; +import { assert } from "chai"; +import * as fs from "fs"; import { - ExportGraphics, ExportGraphicsInfo, ExportGraphicsMeshVisitor, ExportGraphicsOptions, GeometricElement, IModelJsFs, LineStyleDefinition, PhysicalObject, - RenderMaterialElement, SnapshotDb, Texture, + ExportGraphics, + ExportGraphicsInfo, + ExportGraphicsMeshVisitor, + ExportGraphicsOptions, + GeometricElement, + IModelJsFs, + LineStyleDefinition, + PhysicalObject, + RenderMaterialElement, + SnapshotDb, + Texture, } from "../../core-backend"; import { GeometryPart } from "../../Element"; import { ExportLinesInfo, ExportPartInfo, ExportPartInstanceInfo, ExportPartLinesInfo } from "../../ExportGraphics"; @@ -37,7 +75,12 @@ describe("exportGraphics", () => { return iModel.elements.insertElement(elementProps); } - function insertRenderMaterialWithTexture(name: string, textureId: Id64String, patternScale?: Point2dProps, patternScaleMode?: TextureMapUnits): Id64String { + function insertRenderMaterialWithTexture( + name: string, + textureId: Id64String, + patternScale?: Point2dProps, + patternScaleMode?: TextureMapUnits, + ): Id64String { // eslint-disable-next-line @typescript-eslint/naming-convention const props: TextureMapProps = { TextureId: textureId, pattern_offset: [0.0, 0.0] }; if (patternScale) @@ -213,11 +256,138 @@ describe("exportGraphics", () => { return textureIdString; // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. - const pngData = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, - 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, - 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, - 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, - 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, + const pngData = new Uint8Array([ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, ]); return textureIdString = Texture.insertTexture(iModel, IModel.dictionaryId, "test-texture", ImageSourceFormat.Png, pngData); } @@ -278,7 +448,7 @@ describe("exportGraphics", () => { /** return 2x2 array of uvParams: [vNegate][meters] given raw uv and the [1][1] entry */ const mutateUV = (uvRaw: Float32Array, uvVNegatedMeters: Float32Array): Float32Array[][] => { - const uvArray: Float32Array[][] = [[],[]]; + const uvArray: Float32Array[][] = [[], []]; uvArray[1].push(Float32Array.from(uvRaw, negateV)); uvArray[1].push(uvVNegatedMeters); for (let i = 0; i < 2; ++i) @@ -286,7 +456,7 @@ describe("exportGraphics", () => { return uvArray; }; - const materials: Id64String[][] = [["",""], ["",""]]; + const materials: Id64String[][] = [["", ""], ["", ""]]; const getMaterial = (vNegate: boolean, meters: boolean): Id64String => { const i = vNegate ? 1 : 0; const j = meters ? 1 : 0; @@ -312,11 +482,292 @@ describe("exportGraphics", () => { const cubeBuilder = PolyfaceBuilder.create(); cubeBuilder.options.needParams = cubeBuilder.options.needNormals = true; - const cubeIndices = new Int32Array([0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7, 8, 9, 10, 10, 9, 11, 12, 13, 14, 14, 13, 15, 16, 17, 18, 18, 17, 19, 20, 21, 22, 22, 21, 23]); - const cubeXYZ = new Float32Array([-1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1]); - const cubeNormals = new Float32Array([0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]); - const cubeUV = new Float32Array([0.875, 0.5, 0.875, 0.25, 0.625, 0.5, 0.625, 0.25, 0.625, 0.25, 0.625, 0, 0.375, 0.25, 0.375, 0, 0.625, 1, 0.625, 0.75, 0.375, 1, 0.375, 0.75, 0.375, 0.5, 0.375, 0.25, 0.125, 0.5, 0.125, 0.25, 0.625, 0.5, 0.625, 0.25, 0.375, 0.5, 0.375, 0.25, 0.625, 0.75, 0.625, 0.5, 0.375, 0.75, 0.375, 0.5]); - const cubeUVScaled = new Float32Array([5.25, -3, 5.25, -1, 3.75, -3, 3.75, -1, 3.75, -1, 3.75, 1, 2.25, -1, 2.25, 1, 3.75, -7, 3.75, -5, 2.25, -7, 2.25, -5, 2.25, -3, 2.25, -1, 0.75, -3, 0.75, -1, 3.75, -3, 3.75, -1, 2.25, -3, 2.25, -1, 3.75, -5, 3.75, -3, 2.25, -5, 2.25, -3]); + const cubeIndices = new Int32Array([ + 0, + 1, + 2, + 2, + 1, + 3, + 4, + 5, + 6, + 6, + 5, + 7, + 8, + 9, + 10, + 10, + 9, + 11, + 12, + 13, + 14, + 14, + 13, + 15, + 16, + 17, + 18, + 18, + 17, + 19, + 20, + 21, + 22, + 22, + 21, + 23, + ]); + const cubeXYZ = new Float32Array([ + -1, + 1, + -1, + -1, + 1, + 1, + 1, + 1, + -1, + 1, + 1, + 1, + 1, + 1, + 1, + -1, + 1, + 1, + 1, + -1, + 1, + -1, + -1, + 1, + -1, + 1, + 1, + -1, + 1, + -1, + -1, + -1, + 1, + -1, + -1, + -1, + 1, + -1, + -1, + 1, + -1, + 1, + -1, + -1, + -1, + -1, + -1, + 1, + 1, + 1, + -1, + 1, + 1, + 1, + 1, + -1, + -1, + 1, + -1, + 1, + -1, + 1, + -1, + 1, + 1, + -1, + -1, + -1, + -1, + 1, + -1, + -1, + ]); + const cubeNormals = new Float32Array([ + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + 0, + 0, + -1, + ]); + const cubeUV = new Float32Array([ + 0.875, + 0.5, + 0.875, + 0.25, + 0.625, + 0.5, + 0.625, + 0.25, + 0.625, + 0.25, + 0.625, + 0, + 0.375, + 0.25, + 0.375, + 0, + 0.625, + 1, + 0.625, + 0.75, + 0.375, + 1, + 0.375, + 0.75, + 0.375, + 0.5, + 0.375, + 0.25, + 0.125, + 0.5, + 0.125, + 0.25, + 0.625, + 0.5, + 0.625, + 0.25, + 0.375, + 0.5, + 0.375, + 0.25, + 0.625, + 0.75, + 0.625, + 0.5, + 0.375, + 0.75, + 0.375, + 0.5, + ]); + const cubeUVScaled = new Float32Array([ + 5.25, + -3, + 5.25, + -1, + 3.75, + -3, + 3.75, + -1, + 3.75, + -1, + 3.75, + 1, + 2.25, + -1, + 2.25, + 1, + 3.75, + -7, + 3.75, + -5, + 2.25, + -7, + 2.25, + -5, + 2.25, + -3, + 2.25, + -1, + 0.75, + -3, + 0.75, + -1, + 3.75, + -3, + 3.75, + -1, + 2.25, + -3, + 2.25, + -1, + 3.75, + -5, + 3.75, + -3, + 2.25, + -5, + 2.25, + -3, + ]); for (let i = 0; i < cubeIndices.length; i += 3) makeFacet(cubeBuilder, cubeXYZ, cubeNormals, cubeUV, cubeIndices[i], cubeIndices[i + 1], cubeIndices[i + 2]); const cube = cubeBuilder.claimPolyface(); @@ -358,9 +809,9 @@ describe("exportGraphics", () => { it("export elements from local bim file", () => { // edit these values to run const outBimFileName: string = "out.bim"; // will be written to core\backend\lib\cjs\test\output\ExportGraphics - const outFBFileName: string = ""; // e.g., "c:\\tmp\\foo.fb" - const inBimFilePathName: string = ""; // e.g., "c:\\tmp\\foo.bim" - const elementIds: Id64Array = []; // e.g., ["0x2000000000c", "0x2000000000a"] + const outFBFileName: string = ""; // e.g., "c:\\tmp\\foo.fb" + const inBimFilePathName: string = ""; // e.g., "c:\\tmp\\foo.bim" + const elementIds: Id64Array = []; // e.g., ["0x2000000000c", "0x2000000000a"] if (outBimFileName !== "" && inBimFilePathName !== "" && elementIds.length > 0) { const testFileName = IModelTestUtils.prepareOutputFile("ExportGraphics", outBimFileName); @@ -368,13 +819,16 @@ describe("exportGraphics", () => { if (outFBFileName !== "") { for (const elementId of elementIds) { - myIModel.elementGeometryRequest({elementId, onGeometry: (info: ElementGeometryInfo) => { - for (const entry of info.entryArray) { - // examine entry here, e.g.: - if (entry.opcode === ElementGeometryOpcode.BsplineSurface) - IModelJsFs.writeFileSync(outFBFileName, entry.data); - } - }}); + myIModel.elementGeometryRequest({ + elementId, + onGeometry: (info: ElementGeometryInfo) => { + for (const entry of info.entryArray) { + // examine entry here, e.g.: + if (entry.opcode === ElementGeometryOpcode.BsplineSurface) + IModelJsFs.writeFileSync(outFBFileName, entry.data); + } + }, + }); } } @@ -451,7 +905,9 @@ describe("exportGraphics", () => { const id0 = insertPhysicalElement(builder0.geometryStream); const builder1 = new GeometryStreamBuilder(); - builder1.appendGeometry(Loop.createPolygon([Point3d.createZero(), Point3d.create(-1, 0, 0), Point3d.create(-1, -1, 0), Point3d.create(0, -1, 0)])); + builder1.appendGeometry( + Loop.createPolygon([Point3d.createZero(), Point3d.create(-1, 0, 0), Point3d.create(-1, -1, 0), Point3d.create(0, -1, 0)]), + ); const id1 = insertPhysicalElement(builder1.geometryStream); const infos: ExportGraphicsInfo[] = []; @@ -669,7 +1125,9 @@ describe("exportGraphics", () => { // Create line style with small component - logic copied from line style tests in GeometryStream.test.ts partParams.fillDisplay = FillDisplay.Always; partBuilder.appendGeometryParamsChange(partParams); - partBuilder.appendGeometry(Loop.create(LineString3d.create(Point3d.create(0.1, 0, 0), Point3d.create(0, -0.05, 0), Point3d.create(0, 0.05, 0), Point3d.create(0.1, 0, 0)))); + partBuilder.appendGeometry( + Loop.create(LineString3d.create(Point3d.create(0.1, 0, 0), Point3d.create(0, -0.05, 0), Point3d.create(0, 0.05, 0), Point3d.create(0.1, 0, 0))), + ); const partProps: GeometryPartProps = { classFullName: GeometryPart.classFullName, model: IModel.dictionaryId, @@ -681,10 +1139,17 @@ describe("exportGraphics", () => { const pointSymbolData = LineStyleDefinition.Utils.createPointSymbolComponent(iModel, { geomPartId }); // base and size will be set automatically... assert.isTrue(undefined !== pointSymbolData); - const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(iModel, { descr: "TestArrowHead", lcId: 0, lcType: LineStyleDefinition.ComponentType.Internal, symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveEnd }] }); + const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(iModel, { + descr: "TestArrowHead", + lcId: 0, + lcType: LineStyleDefinition.ComponentType.Internal, + symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveEnd }], + }); assert.isTrue(undefined !== strokePointData); - const compoundData = LineStyleDefinition.Utils.createCompoundComponent(iModel, { comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }] }); + const compoundData = LineStyleDefinition.Utils.createCompoundComponent(iModel, { + comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }], + }); assert.isTrue(undefined !== compoundData); const styleId = LineStyleDefinition.Utils.createStyle(iModel, IModel.dictionaryId, "TestArrowStyle", compoundData); @@ -1187,5 +1652,4 @@ describe("exportGraphics", () => { assert.strictEqual(infos[0].elementId, newId); assert.strictEqual(infos[0].mesh.indices.length, 6); }); - }); diff --git a/core/backend/src/test/standalone/GeometryChangeEvents.test.ts b/core/backend/src/test/standalone/GeometryChangeEvents.test.ts index 06fa0b27fc36..aa9f1e12972a 100644 --- a/core/backend/src/test/standalone/GeometryChangeEvents.test.ts +++ b/core/backend/src/test/standalone/GeometryChangeEvents.test.ts @@ -2,16 +2,19 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CompressedId64Set, IModelStatus, OpenMode } from "@itwin/core-bentley"; -import { LineSegment3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; import { - Code, ColorByName, GeometricElement3dProps, GeometryStreamBuilder, IModel, ModelGeometryChangesProps, SubCategoryAppearance, + Code, + ColorByName, + GeometricElement3dProps, + GeometryStreamBuilder, + IModel, + ModelGeometryChangesProps, + SubCategoryAppearance, } from "@itwin/core-common"; -import { - _nativeDb, - ChannelControl, IModelJsFs, PhysicalModel, SpatialCategory, StandaloneDb, VolumeElement, -} from "../../core-backend"; +import { LineSegment3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { _nativeDb, ChannelControl, IModelJsFs, PhysicalModel, SpatialCategory, StandaloneDb, VolumeElement } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; describe("Model geometry changes", () => { diff --git a/core/backend/src/test/standalone/GeometryStream.test.ts b/core/backend/src/test/standalone/GeometryStream.test.ts index bef591118781..f2d44682fefa 100644 --- a/core/backend/src/test/standalone/GeometryStream.test.ts +++ b/core/backend/src/test/standalone/GeometryStream.test.ts @@ -3,24 +3,104 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { BentleyStatus, Id64, Id64String, IModelStatus } from "@itwin/core-bentley"; import { - Angle, AngleSweep, Arc3d, Box, ClipMaskXYZRangePlanes, ClipPlane, ClipPlaneContainment, ClipPrimitive, ClipShape, ClipVector, ConvexClipPlaneSet, - CurveCollection, CurvePrimitive, Geometry, GeometryQueryCategory, IndexedPolyface, InterpolationCurve3d, InterpolationCurve3dOptions, InterpolationCurve3dProps, - LineSegment3d, LineString3d, Loop, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point3dArray, PointString3d, PolyfaceBuilder, Range2d, Range3d, - SolidPrimitive, Sphere, StrokeOptions, Transform, Vector3d, YawPitchRollAngles, + AreaPattern, + BackgroundFill, + BRepGeometryCreate, + BRepGeometryFunction, + BRepGeometryInfo, + BRepGeometryOperation, + Code, + ColorByName, + ColorDef, + ElementGeometry, + ElementGeometryDataEntry, + ElementGeometryFunction, + ElementGeometryInfo, + ElementGeometryOpcode, + ElementGeometryRequest, + FillDisplay, + GeometricElement3dProps, + GeometricElementProps, + GeometryClass, + GeometryContainmentRequestProps, + GeometryParams, + GeometryPartProps, + GeometryPrimitive, + GeometryStreamBuilder, + GeometryStreamFlags, + GeometryStreamIterator, + GeometryStreamProps, + Gradient, + ImageGraphicCorners, + ImageGraphicProps, + IModel, + LinePixels, + LineStyle, + MassPropertiesOperation, + MassPropertiesRequestProps, + PhysicalElementProps, + Placement3d, + Placement3dProps, + TextString, + TextStringGlyphData, + TextStringProps, + ThematicGradientMode, + ThematicGradientSettings, + ViewFlags, +} from "@itwin/core-common"; +import { + Angle, + AngleSweep, + Arc3d, + Box, + ClipMaskXYZRangePlanes, + ClipPlane, + ClipPlaneContainment, + ClipPrimitive, + ClipShape, + ClipVector, + ConvexClipPlaneSet, + CurveCollection, + CurvePrimitive, + Geometry, + GeometryQueryCategory, + IndexedPolyface, + InterpolationCurve3d, + InterpolationCurve3dOptions, + InterpolationCurve3dProps, + LineSegment3d, + LineString3d, + Loop, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Point3dArray, + PointString3d, + PolyfaceBuilder, + Range2d, + Range3d, + SolidPrimitive, + Sphere, + StrokeOptions, + Transform, + Vector3d, + YawPitchRollAngles, } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { - AreaPattern, BackgroundFill, BRepGeometryCreate, BRepGeometryFunction, BRepGeometryInfo, BRepGeometryOperation, Code, ColorByName, - ColorDef, ElementGeometry, ElementGeometryDataEntry, ElementGeometryFunction, ElementGeometryInfo, ElementGeometryOpcode, ElementGeometryRequest, - FillDisplay, GeometricElement3dProps, GeometricElementProps, GeometryClass, - GeometryContainmentRequestProps, GeometryParams, GeometryPartProps, GeometryPrimitive, GeometryStreamBuilder, GeometryStreamFlags, GeometryStreamIterator, - GeometryStreamProps, Gradient, ImageGraphicCorners, ImageGraphicProps, IModel, LinePixels, LineStyle, MassPropertiesOperation, - MassPropertiesRequestProps, PhysicalElementProps, Placement3d, Placement3dProps, TextString, TextStringGlyphData, TextStringProps, ThematicGradientMode, - ThematicGradientSettings, ViewFlags, -} from "@itwin/core-common"; -import { _nativeDb, DefinitionModel, deleteElementTree, GeometricElement, GeometryPart, LineStyleDefinition, PhysicalObject, SnapshotDb, Subject } from "../../core-backend"; + _nativeDb, + DefinitionModel, + deleteElementTree, + GeometricElement, + GeometryPart, + LineStyleDefinition, + PhysicalObject, + SnapshotDb, + Subject, +} from "../../core-backend"; import { createBRepDataProps } from "../GeometryTestUtil"; import { IModelTestUtils } from "../IModelTestUtils"; import { Timer } from "../TestUtils"; @@ -39,7 +119,12 @@ function createGeometryPartProps(geom?: GeometryStreamProps, modelId?: Id64Strin return partProps; } -function createPhysicalElementProps(seedElement: GeometricElement, placement?: Placement3dProps, geom?: GeometryStreamProps, modelId?: Id64String): PhysicalElementProps { +function createPhysicalElementProps( + seedElement: GeometricElement, + placement?: Placement3dProps, + geom?: GeometryStreamProps, + modelId?: Id64String, +): PhysicalElementProps { const elementProps: PhysicalElementProps = { classFullName: PhysicalObject.classFullName, model: modelId ?? seedElement.model, @@ -62,10 +147,22 @@ function createGeometricElem(geom: GeometryStreamProps, placement: Placement3dPr return imodel.elements.insertElement(el.toJSON()); } -function createPartElem(partId: Id64String, origin: Point3d, angles: YawPitchRollAngles, imodel: SnapshotDb, seedElement: GeometricElement, isRelative = false): Id64String { +function createPartElem( + partId: Id64String, + origin: Point3d, + angles: YawPitchRollAngles, + imodel: SnapshotDb, + seedElement: GeometricElement, + isRelative = false, +): Id64String { const builder = new GeometryStreamBuilder(); builder.appendGeometryPart3d(partId, isRelative ? origin : undefined, isRelative ? angles : undefined); - return createGeometricElem(builder.geometryStream, isRelative ? { origin: Point3d.createZero(), angles: YawPitchRollAngles.createDegrees(0, 0, 0) } : { origin, angles }, imodel, seedElement); + return createGeometricElem( + builder.geometryStream, + isRelative ? { origin: Point3d.createZero(), angles: YawPitchRollAngles.createDegrees(0, 0, 0) } : { origin, angles }, + imodel, + seedElement, + ); } function createCirclePart(radius: number, imodel: SnapshotDb): Id64String { @@ -74,19 +171,37 @@ function createCirclePart(radius: number, imodel: SnapshotDb): Id64String { return createGeometryPart(builder.geometryStream, imodel); } -function createCircleElem(radius: number, origin: Point3d, angles: YawPitchRollAngles, imodel: SnapshotDb, seedElement: GeometricElement): Id64String { +function createCircleElem( + radius: number, + origin: Point3d, + angles: YawPitchRollAngles, + imodel: SnapshotDb, + seedElement: GeometricElement, +): Id64String { const builder = new GeometryStreamBuilder(); builder.appendGeometry(Arc3d.createXY(Point3d.createZero(), radius)); return createGeometricElem(builder.geometryStream, { origin, angles }, imodel, seedElement); } -function createSphereElem(radius: number, origin: Point3d, angles: YawPitchRollAngles, imodel: SnapshotDb, seedElement: GeometricElement): Id64String { +function createSphereElem( + radius: number, + origin: Point3d, + angles: YawPitchRollAngles, + imodel: SnapshotDb, + seedElement: GeometricElement, +): Id64String { const builder = new GeometryStreamBuilder(); builder.appendGeometry(Sphere.createCenterRadius(Point3d.createZero(), radius)); return createGeometricElem(builder.geometryStream, { origin, angles }, imodel, seedElement); } -function createDisjointCirclesElem(radius: number, origin: Point3d, angles: YawPitchRollAngles, imodel: SnapshotDb, seedElement: GeometricElement): Id64String { +function createDisjointCirclesElem( + radius: number, + origin: Point3d, + angles: YawPitchRollAngles, + imodel: SnapshotDb, + seedElement: GeometricElement, +): Id64String { const builder = new GeometryStreamBuilder(); const xOffset = radius * 1.5; builder.appendGeometry(Arc3d.createXY(Point3d.create(-xOffset), radius)); @@ -114,7 +229,15 @@ function createIndexedPolyface(radius: number, origin?: Point3d, angleTol?: Angl return polyBuilder.claimPolyface(); } -function createStyledLineElem(imodel: SnapshotDb, seedElement: GeometricElement, x: number, y: number, length: number, styleInfo?: LineStyle.Info, color?: ColorDef): Id64String { +function createStyledLineElem( + imodel: SnapshotDb, + seedElement: GeometricElement, + x: number, + y: number, + length: number, + styleInfo?: LineStyle.Info, + color?: ColorDef, +): Id64String { const builder = new GeometryStreamBuilder(); const params = new GeometryParams(seedElement.category); @@ -141,7 +264,7 @@ interface ExpectedElementGeometryEntry { function validateElementInfo(info: ElementGeometryInfo, expected: ExpectedElementGeometryEntry[], isWorld: boolean): void { assert.isTrue(undefined !== info.entryArray && expected.length === info.entryArray.length); - const geomParams = (undefined !== info.categoryId ? new GeometryParams(info.categoryId) : undefined); + const geomParams = undefined !== info.categoryId ? new GeometryParams(info.categoryId) : undefined; info.entryArray.forEach((entry, i) => { assert.isTrue(expected[i].opcode === entry.opcode); @@ -185,8 +308,8 @@ function validateElementInfo(info: ElementGeometryInfo, expected: ExpectedElemen const transform = Transform.fromJSON(brep?.transform); const otherTrans = Transform.fromJSON(other?.transform); assert.isTrue(transform.isAlmostEqual(otherTrans)); - const faceSymbLen = (undefined !== brep?.faceSymbology ? brep?.faceSymbology.length : 0); - const otherSymbLen = (undefined !== other?.faceSymbology ? other?.faceSymbology.length : 0); + const faceSymbLen = undefined !== brep?.faceSymbology ? brep?.faceSymbology.length : 0; + const otherSymbLen = undefined !== other?.faceSymbology ? other?.faceSymbology.length : 0; assert.isTrue(faceSymbLen === otherSymbLen); } break; @@ -267,7 +390,14 @@ function validateGeometricElementProps(info: ElementGeometryInfo, expected: Geom assert.isFalse(bbox?.isNull); } -function doElementGeometryValidate(imodel: SnapshotDb, elementId: Id64String, expected: ExpectedElementGeometryEntry[], isWorld: boolean, elementProps?: GeometricElement3dProps, brepOpt?: number): IModelStatus { +function doElementGeometryValidate( + imodel: SnapshotDb, + elementId: Id64String, + expected: ExpectedElementGeometryEntry[], + isWorld: boolean, + elementProps?: GeometricElement3dProps, + brepOpt?: number, +): IModelStatus { const onGeometry: ElementGeometryFunction = (info: ElementGeometryInfo): void => { if (undefined !== elementProps) validateGeometricElementProps(info, elementProps); @@ -291,7 +421,12 @@ function doElementGeometryValidate(imodel: SnapshotDb, elementId: Id64String, ex return imodel.elementGeometryRequest(requestProps); } -function createGeometricElemFromSeed(imodel: SnapshotDb, seedId: Id64String, entryArray: ElementGeometryDataEntry[], placement?: Placement3dProps): Id64String { +function createGeometricElemFromSeed( + imodel: SnapshotDb, + seedId: Id64String, + entryArray: ElementGeometryDataEntry[], + placement?: Placement3dProps, +): Id64String { const seedElement = imodel.elements.getElement(seedId); assert.exists(seedElement); @@ -325,18 +460,35 @@ describe("GeometryStream", () => { assert.isTrue(seedElement.federationGuid! === "18eb4650-b074-414f-b961-d9cfaa6c8746"); // init line code to line pixels array - const lsCodes: LinePixels[] = [LinePixels.Solid, LinePixels.Code1, LinePixels.Code2, LinePixels.Code3, LinePixels.Code4, LinePixels.Code5, LinePixels.Code6, LinePixels.Code7]; + const lsCodes: LinePixels[] = [ + LinePixels.Solid, + LinePixels.Code1, + LinePixels.Code2, + LinePixels.Code3, + LinePixels.Code4, + LinePixels.Code5, + LinePixels.Code6, + LinePixels.Code7, + ]; // create new line style definitions for line codes 1-7 const lsStyles: Id64String[] = []; lsCodes.forEach((linePixels) => { - lsStyles.push(LinePixels.Solid === linePixels ? Id64.invalid : LineStyleDefinition.Utils.getOrCreateLinePixelsStyle(imodel, IModel.dictionaryId, linePixels)); + lsStyles.push( + LinePixels.Solid === linePixels + ? Id64.invalid + : LineStyleDefinition.Utils.getOrCreateLinePixelsStyle(imodel, IModel.dictionaryId, linePixels), + ); }); // get existing line style definitions for line codes 1-7 const lsStylesExist: Id64String[] = []; lsCodes.forEach((linePixels) => { - lsStylesExist.push(LinePixels.Solid === linePixels ? Id64.invalid : LineStyleDefinition.Utils.getOrCreateLinePixelsStyle(imodel, IModel.dictionaryId, linePixels)); + lsStylesExist.push( + LinePixels.Solid === linePixels + ? Id64.invalid + : LineStyleDefinition.Utils.getOrCreateLinePixelsStyle(imodel, IModel.dictionaryId, linePixels), + ); }); // make sure we found existing styles and didn't create a second set @@ -406,7 +558,7 @@ describe("GeometryStream", () => { // make sure we found existing style and didn't create a new one const styleIdExists = LineStyleDefinition.Utils.getOrCreateContinuousStyle(imodel, IModel.dictionaryId); - assert.isTrue(Id64.isValidId64(styleIdExists) && styleIdExists === (styleId)); + assert.isTrue(Id64.isValidId64(styleIdExists) && styleIdExists === styleId); // create continuous style with pre-defined constant width const styleIdWidth = LineStyleDefinition.Utils.getOrCreateContinuousStyle(imodel, IModel.dictionaryId, 0.05); @@ -414,7 +566,7 @@ describe("GeometryStream", () => { // make sure we found existing style and didn't create a new one const styleIdWidthExists = LineStyleDefinition.Utils.getOrCreateContinuousStyle(imodel, IModel.dictionaryId, 0.05); - assert.isTrue(Id64.isValidId64(styleIdWidthExists) && styleIdWidthExists === (styleIdWidth)); + assert.isTrue(Id64.isValidId64(styleIdWidthExists) && styleIdWidthExists === styleIdWidth); const builder = new GeometryStreamBuilder(); const params = new GeometryParams(seedElement.category); @@ -486,7 +638,9 @@ describe("GeometryStream", () => { partParams.fillDisplay = FillDisplay.Always; partBuilder.appendGeometryParamsChange(partParams); - partBuilder.appendGeometry(Loop.create(LineString3d.create(Point3d.create(0.1, 0, 0), Point3d.create(0, -0.05, 0), Point3d.create(0, 0.05, 0), Point3d.create(0.1, 0, 0)))); + partBuilder.appendGeometry( + Loop.create(LineString3d.create(Point3d.create(0.1, 0, 0), Point3d.create(0, -0.05, 0), Point3d.create(0, 0.05, 0), Point3d.create(0.1, 0, 0))), + ); const partProps = createGeometryPartProps(partBuilder.geometryStream, definitionModelId); const partId = imodel.elements.insertElement(partProps); @@ -496,10 +650,17 @@ describe("GeometryStream", () => { assert.isTrue(undefined !== pointSymbolData); // Use internal default instead of creating a stroke component for a solid line - const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: "TestArrowHead", lcId: 0, lcType: LineStyleDefinition.ComponentType.Internal, symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveEnd }] }); + const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: "TestArrowHead", + lcId: 0, + lcType: LineStyleDefinition.ComponentType.Internal, + symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveEnd }], + }); assert.isTrue(undefined !== strokePointData); - const compoundData = LineStyleDefinition.Utils.createCompoundComponent(imodel, { comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }] }); + const compoundData = LineStyleDefinition.Utils.createCompoundComponent(imodel, { + comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }], + }); assert.isTrue(undefined !== compoundData); const styleId = LineStyleDefinition.Utils.createStyle(imodel, definitionModelId, "TestArrowStyle", compoundData); @@ -557,14 +718,35 @@ describe("GeometryStream", () => { assert.isTrue(seedElement.federationGuid! === "18eb4650-b074-414f-b961-d9cfaa6c8746"); const lsStrokes: LineStyleDefinition.Strokes = []; - lsStrokes.push({ length: 0.25, orgWidth: 0.0, endWidth: 0.025, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Left }); + lsStrokes.push({ + length: 0.25, + orgWidth: 0.0, + endWidth: 0.025, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Left, + }); lsStrokes.push({ length: 0.1 }); - lsStrokes.push({ length: 0.1, orgWidth: 0.025, endWidth: 0.025, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Full }); + lsStrokes.push({ + length: 0.1, + orgWidth: 0.025, + endWidth: 0.025, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Full, + }); lsStrokes.push({ length: 0.1 }); - lsStrokes.push({ length: 0.25, orgWidth: 0.025, endWidth: 0.0, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Right }); + lsStrokes.push({ + length: 0.25, + orgWidth: 0.025, + endWidth: 0.0, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Right, + }); lsStrokes.push({ length: 0.1 }); - const strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { descr: "TestDashDotDashLineCode", strokes: lsStrokes }); + const strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { + descr: "TestDashDotDashLineCode", + strokes: lsStrokes, + }); assert.isTrue(undefined !== strokePatternData); const partBuilder = new GeometryStreamBuilder(); @@ -581,7 +763,11 @@ describe("GeometryStream", () => { lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 1, mod1: LineStyleDefinition.SymbolOptions.Center }); lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 3, mod1: LineStyleDefinition.SymbolOptions.Center }); - const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: "TestGapSymbolsLinePoint", lcId: strokePatternData.compId, symbols: lsSymbols }); + const strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: "TestGapSymbolsLinePoint", + lcId: strokePatternData.compId, + symbols: lsSymbols, + }); assert.isTrue(undefined !== strokePointData); const lsComponents: LineStyleDefinition.Components = []; @@ -627,20 +813,42 @@ describe("GeometryStream", () => { let unitDef = 1.0; let widthDef = 0.0; let name = `Continuous-${unitDef}-${widthDef}`; - let styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { compId: 0, compType: LineStyleDefinition.ComponentType.Internal, flags: LineStyleDefinition.StyleFlags.Continuous | LineStyleDefinition.StyleFlags.NoSnap }); + let styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { + compId: 0, + compType: LineStyleDefinition.ComponentType.Internal, + flags: LineStyleDefinition.StyleFlags.Continuous | LineStyleDefinition.StyleFlags.NoSnap, + }); assert.isTrue(Id64.isValidId64(styleId)); // Expect no range padding... let newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.0)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.0, + ), + ); // Expect range padded by 0.25... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), ColorDef.red); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), + ColorDef.red, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // LineStyleDefinition: create continuous style with both width and unit scale specified in definition... x = 0.0; @@ -648,27 +856,70 @@ describe("GeometryStream", () => { unitDef = 2.0; widthDef = 0.5; name = `Continuous-${unitDef}-${widthDef}`; - let strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { descr: name, strokes: [{ length: 1e37, orgWidth: widthDef, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Full }] }); - styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { compId: strokePatternData.compId, compType: strokePatternData.compType, flags: LineStyleDefinition.StyleFlags.Continuous | LineStyleDefinition.StyleFlags.NoSnap, unitDef }); + let strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { + descr: name, + strokes: [{ + length: 1e37, + orgWidth: widthDef, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Full, + }], + }); + styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { + compId: strokePatternData.compId, + compType: strokePatternData.compType, + flags: LineStyleDefinition.StyleFlags.Continuous | LineStyleDefinition.StyleFlags.NoSnap, + unitDef, + }); assert.isTrue(Id64.isValidId64(styleId)); // Expect no range padding... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.0, physicalWidth: true }))); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.0, physicalWidth: true })), + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.0)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.0, + ), + ); // Expect range padded by 1.0... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId), ColorDef.red); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), widthDef * unitDef)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + widthDef * unitDef, + ), + ); // Expect range padded by 0.25... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // LineStyleDefinition: create stroke pattern with dash widths in definition... x = 0.0; @@ -677,27 +928,67 @@ describe("GeometryStream", () => { widthDef = 0.025; name = `StrokePattern-${unitDef}-${widthDef}`; const lsStrokes: LineStyleDefinition.Strokes = []; - lsStrokes.push({ length: 0.25, orgWidth: widthDef, endWidth: widthDef, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Left }); + lsStrokes.push({ + length: 0.25, + orgWidth: widthDef, + endWidth: widthDef, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Left, + }); lsStrokes.push({ length: 0.1 }); - lsStrokes.push({ length: 0.2, orgWidth: widthDef, endWidth: widthDef, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Full }); + lsStrokes.push({ + length: 0.2, + orgWidth: widthDef, + endWidth: widthDef, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Full, + }); lsStrokes.push({ length: 0.1 }); - lsStrokes.push({ length: 0.25, orgWidth: widthDef, endWidth: widthDef, strokeMode: LineStyleDefinition.StrokeMode.Dash, widthMode: LineStyleDefinition.StrokeWidth.Right }); + lsStrokes.push({ + length: 0.25, + orgWidth: widthDef, + endWidth: widthDef, + strokeMode: LineStyleDefinition.StrokeMode.Dash, + widthMode: LineStyleDefinition.StrokeWidth.Right, + }); lsStrokes.push({ length: 0.1 }); strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { descr: name, strokes: lsStrokes }); - styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { compId: strokePatternData.compId, compType: strokePatternData.compType, flags: LineStyleDefinition.StyleFlags.NoSnap }); + styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { + compId: strokePatternData.compId, + compType: strokePatternData.compType, + flags: LineStyleDefinition.StyleFlags.NoSnap, + }); assert.isTrue(Id64.isValidId64(styleId)); // Expect range padded by 0.025... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), widthDef * unitDef)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + widthDef * unitDef, + ), + ); // Expect range padded by 0.25... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), ColorDef.red); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), + ColorDef.red, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // LineStyleDefinition: create stroke pattern with dash widths and unit scale specified in definition... x = 0.0; @@ -705,32 +996,81 @@ describe("GeometryStream", () => { unitDef = 2.0; widthDef = 0.025; name = `StrokePattern-${unitDef}-${widthDef}`; - styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { compId: strokePatternData.compId, compType: strokePatternData.compType, flags: LineStyleDefinition.StyleFlags.NoSnap, unitDef }); + styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, { + compId: strokePatternData.compId, + compType: strokePatternData.compType, + flags: LineStyleDefinition.StyleFlags.NoSnap, + unitDef, + }); assert.isTrue(Id64.isValidId64(styleId)); // Expect range padded by 0.05... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), widthDef * unitDef)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + widthDef * unitDef, + ), + ); // Expect range padded by 0.25... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), ColorDef.red); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, physicalWidth: true })), + ColorDef.red, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // Expect range padded by 0.25... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, scale: 0.5, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.25, scale: 0.5, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // Expect range padded by 0.025... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), ColorDef.blue); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), + ColorDef.blue, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), widthDef * unitDef * 0.5)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + widthDef * unitDef * 0.5, + ), + ); // LineStyleDefinition: create point symbol with internal default instead of a stroke pattern... x = 0.0; @@ -740,8 +1080,15 @@ describe("GeometryStream", () => { name = `PointSymbol-${unitDef}-${widthDef}`; const partId = createCirclePart(0.25, imodel); let pointSymbolData = LineStyleDefinition.Utils.createPointSymbolComponent(imodel, { geomPartId: partId }); - let strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: name, lcId: 0, lcType: LineStyleDefinition.ComponentType.Internal, symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveOrigin }] }); - let compoundData = LineStyleDefinition.Utils.createCompoundComponent(imodel, { comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }] }); + let strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: name, + lcId: 0, + lcType: LineStyleDefinition.ComponentType.Internal, + symbols: [{ symId: pointSymbolData!.compId, strokeNum: -1, mod1: LineStyleDefinition.SymbolOptions.CurveOrigin }], + }); + let compoundData = LineStyleDefinition.Utils.createCompoundComponent(imodel, { + comps: [{ id: strokePointData.compId, type: strokePointData.compType }, { id: 0, type: LineStyleDefinition.ComponentType.Internal }], + }); styleId = LineStyleDefinition.Utils.createStyle(imodel, IModel.dictionaryId, name, compoundData); assert.isTrue(Id64.isValidId64(styleId)); @@ -749,19 +1096,42 @@ describe("GeometryStream", () => { newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.5)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.5, + ), + ); // Expect range padded by 0.25 (scaled circle radius)... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), ColorDef.red); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.25)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.25, + ), + ); // Expect range padded by 1.0 (width override > symbol size)... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 1.0, scale: 0.5, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 1.0, scale: 0.5, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 1.0)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 1.0, + ), + ); // LineStyleDefinition: create scaling point symbol with stroke pattern with width and unit scale specified in definition... x = 0.0; @@ -774,7 +1144,11 @@ describe("GeometryStream", () => { const lsSymbols: LineStyleDefinition.Symbols = []; lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 1, mod1: LineStyleDefinition.SymbolOptions.Center }); lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 3, mod1: LineStyleDefinition.SymbolOptions.Center }); - strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: name, lcId: strokePatternData.compId, symbols: lsSymbols }); + strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: name, + lcId: strokePatternData.compId, + symbols: lsSymbols, + }); const lsComponents: LineStyleDefinition.Components = []; lsComponents.push({ id: strokePointData.compId, type: strokePointData.compType }); lsComponents.push({ id: strokePatternData.compId, type: strokePatternData.compType }); @@ -787,19 +1161,42 @@ describe("GeometryStream", () => { newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.125)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.125, + ), + ); // Expect range padded by 0.0625 (symbol and modifier scaled circle radius)... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), ColorDef.red); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.0625)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.0625, + ), + ); // Expect range padded by 0.75 (width override > symbol and modifier scaled symbol size)... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.75)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.75, + ), + ); // LineStyleDefinition: create non-scaling point symbol with stroke pattern with width and unit scale specified in definition... x = 0.0; @@ -808,11 +1205,19 @@ describe("GeometryStream", () => { widthDef = 0.025; // value used for lsStrokes... name = `NonScalingPointSymbol-${unitDef}-${widthDef}}`; strokePatternData = LineStyleDefinition.Utils.createStrokePatternComponent(imodel, { descr: name, strokes: lsStrokes }); - pointSymbolData = LineStyleDefinition.Utils.createPointSymbolComponent(imodel, { geomPartId: partId, scale: 2.0, symFlags: LineStyleDefinition.PointSymbolFlags.NoScale }); + pointSymbolData = LineStyleDefinition.Utils.createPointSymbolComponent(imodel, { + geomPartId: partId, + scale: 2.0, + symFlags: LineStyleDefinition.PointSymbolFlags.NoScale, + }); lsSymbols.length = 0; lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 1, mod1: LineStyleDefinition.SymbolOptions.Center }); lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 3, mod1: LineStyleDefinition.SymbolOptions.Center }); - strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: name, lcId: strokePatternData.compId, symbols: lsSymbols }); + strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: name, + lcId: strokePatternData.compId, + symbols: lsSymbols, + }); lsComponents.length = 0; lsComponents.push({ id: strokePointData.compId, type: strokePointData.compType }); lsComponents.push({ id: strokePatternData.compId, type: strokePatternData.compType }); @@ -825,19 +1230,42 @@ describe("GeometryStream", () => { newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.5)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.5, + ), + ); // Expect range padded by 0.5 (unscaled circle radius)... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), ColorDef.red); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.5)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.5, + ), + ); // Expect range padded by 0.75 (width override > unscaled symbol size)... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.75)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.75, + ), + ); // LineStyleDefinition: create scaling point symbol with offsets with stroke pattern with width and unit scale specified in definition... x = 0.0; @@ -850,7 +1278,11 @@ describe("GeometryStream", () => { lsSymbols.length = 0; lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 1, mod1: LineStyleDefinition.SymbolOptions.Center, yOffset: -0.1 }); lsSymbols.push({ symId: pointSymbolData!.compId, strokeNum: 3, mod1: LineStyleDefinition.SymbolOptions.Center, yOffset: 0.1 }); - strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { descr: name, lcId: strokePatternData.compId, symbols: lsSymbols }); + strokePointData = LineStyleDefinition.Utils.createStrokePointComponent(imodel, { + descr: name, + lcId: strokePatternData.compId, + symbols: lsSymbols, + }); lsComponents.length = 0; lsComponents.push({ id: strokePointData.compId, type: strokePointData.compType }); lsComponents.push({ id: strokePatternData.compId, type: strokePatternData.compType }); @@ -863,19 +1295,42 @@ describe("GeometryStream", () => { newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId)); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.225)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.225, + ), + ); // Expect range padded by 0.1125 (offset symbol and modifier scaled circle radius)... newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ scale: 0.5 })), ColorDef.red); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.1125)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.1125, + ), + ); // Expect range padded by 0.75 (width override > symbol and modifier scaled symbol size)... - newId = createStyledLineElem(imodel, seedElement, x++, y, 1.0, new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), ColorDef.green); + newId = createStyledLineElem( + imodel, + seedElement, + x++, + y, + 1.0, + new LineStyle.Info(styleId, new LineStyle.Modifier({ startWidth: 0.75, scale: 0.5, physicalWidth: true })), + ColorDef.green, + ); assert.isTrue(Id64.isValidId64(newId)); imodel.saveChanges(); - assert.isTrue(Geometry.isSameCoordinate(Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), 0.75)); + assert.isTrue( + Geometry.isSameCoordinate( + Placement3d.fromJSON(imodel.elements.getElementProps({ id: newId, wantGeometry: true }).placement).bbox.yLength(), + 0.75, + ), + ); }); it("create GeometricElement3d using shapes with fill/gradient", async () => { @@ -890,7 +1345,15 @@ describe("GeometryStream", () => { builder.appendGeometryRanges(); // Test inclusion of local ranges... const xOffset = Transform.createTranslation(Point3d.create(1.5)); - const shape = Loop.create(LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 0))); + const shape = Loop.create( + LineString3d.create( + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 0), + ), + ); // No fill... params.lineColor = ColorDef.green; @@ -1012,7 +1475,15 @@ describe("GeometryStream", () => { builder.appendGeometryRanges(); // Test inclusion of local ranges... const xOffset = Transform.createTranslation(Point3d.create(1.5)); - const shape = Loop.create(LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 0))); + const shape = Loop.create( + LineString3d.create( + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 0), + ), + ); // Hatch w/o overrides params.lineColor = ColorDef.create(ColorByName.yellow); @@ -1093,10 +1564,16 @@ describe("GeometryStream", () => { assert.isDefined(entry.geomParams.pattern); switch (iShape++) { case 0: - assert.isTrue(undefined !== entry.geomParams.pattern!.space1 && undefined !== entry.geomParams.pattern!.angle1 && undefined === entry.geomParams.pattern!.space2 && undefined === entry.geomParams.pattern!.angle2); + assert.isTrue( + undefined !== entry.geomParams.pattern!.space1 && undefined !== entry.geomParams.pattern!.angle1 && + undefined === entry.geomParams.pattern!.space2 && undefined === entry.geomParams.pattern!.angle2, + ); break; case 1: - assert.isTrue(undefined !== entry.geomParams.pattern!.space1 && undefined !== entry.geomParams.pattern!.angle1 && undefined !== entry.geomParams.pattern!.space2 && undefined !== entry.geomParams.pattern!.angle2); + assert.isTrue( + undefined !== entry.geomParams.pattern!.space1 && undefined !== entry.geomParams.pattern!.angle1 && + undefined !== entry.geomParams.pattern!.space2 && undefined !== entry.geomParams.pattern!.angle2, + ); break; case 2: assert.isTrue(undefined !== entry.geomParams.pattern!.symbolId && undefined === entry.geomParams.pattern!.color); @@ -1338,7 +1815,15 @@ describe("GeometryStream", () => { const builder = new GeometryStreamBuilder(); const params = new GeometryParams(seedElement.category); - const shape = Loop.create(LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 0))); + const shape = Loop.create( + LineString3d.create( + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 0), + ), + ); params.fillDisplay = FillDisplay.ByView; builder.appendGeometryParamsChange(params); @@ -1370,7 +1855,10 @@ describe("GeometryStream", () => { const fromElProps = JSON.stringify(value.geom); const fromScratch = JSON.stringify(geometryStream); - assert.isTrue(undefined !== builder.geometryStream[0].appearance && builder.geometryStream[0].appearance.subCategory === IModel.getDefaultSubCategoryId(value.category)); // Ensure default sub-category is specified... + assert.isTrue( + undefined !== builder.geometryStream[0].appearance && + builder.geometryStream[0].appearance.subCategory === IModel.getDefaultSubCategoryId(value.category), + ); // Ensure default sub-category is specified... assert.isTrue(fromElProps !== fromBuilder); // Should not match, default sub-category should not be persisted... assert.isTrue(fromElProps === fromScratch); }); @@ -1471,7 +1959,7 @@ describe("GeometryStream", () => { const roundTrip = () => { const iter = new GeometryStreamIterator(builder.geometryStream); - expect((iter.flags === GeometryStreamFlags.ViewIndependent)).to.equal(builder.isViewIndependent); + expect(iter.flags === GeometryStreamFlags.ViewIndependent).to.equal(builder.isViewIndependent); const partProps = createGeometryPartProps(builder.geometryStream); const part = imodel.elements.createElement(partProps); @@ -1556,7 +2044,11 @@ describe("ElementGeometry", () => { assert.exists(seedElement); assert.isTrue(seedElement.federationGuid! === "18eb4650-b074-414f-b961-d9cfaa6c8746"); - const expected: ExpectedElementGeometryEntry[] = [{ opcode: ElementGeometryOpcode.SolidPrimitive, geometryCategory: "solid", geometrySubCategory: "sphere" }]; + const expected: ExpectedElementGeometryEntry[] = [{ + opcode: ElementGeometryOpcode.SolidPrimitive, + geometryCategory: "solid", + geometrySubCategory: "sphere", + }]; assert(IModelStatus.Success === doElementGeometryValidate(imodel, "0x1d", expected, false)); }); @@ -2092,10 +2584,16 @@ describe("ElementGeometry", () => { geomParams.lineColor = ColorDef.green; geomParams.weight = 2; const modifiers = new LineStyle.Modifier({ - scale: 2, dashScale: 0.5, gapScale: 0.2, - startWidth: 0.1, endWidth: 0.3, - distPhase: 0.25, fractPhase: 0.1, centerPhase: true, - segmentMode: false, physicalWidth: true, + scale: 2, + dashScale: 0.5, + gapScale: 0.2, + startWidth: 0.1, + endWidth: 0.3, + distPhase: 0.25, + fractPhase: 0.1, + centerPhase: true, + segmentMode: false, + physicalWidth: true, normal: Vector3d.unitZ().toJSON(), rotation: YawPitchRollAngles.createDegrees(45, 0, 0).toJSON(), }); @@ -2297,7 +2795,9 @@ describe("ElementGeometry", () => { elemProps.elementGeometryBuilderParams = { entryArray: [{ opcode: 9999 } as unknown as ElementGeometryDataEntry] }; expect(() => imodel.elements.insertElement(elemProps)).to.throw(); // TODO: check error message - elemProps.elementGeometryBuilderParams = { entryArray: [{ opcode: ElementGeometryOpcode.ArcPrimitive, data: undefined } as unknown as ElementGeometryDataEntry] }; + elemProps.elementGeometryBuilderParams = { + entryArray: [{ opcode: ElementGeometryOpcode.ArcPrimitive, data: undefined } as unknown as ElementGeometryDataEntry], + }; expect(() => imodel.elements.insertElement(elemProps)).to.throw(); // TODO: check error message // Update @@ -2412,9 +2912,27 @@ describe("BRepGeometry", () => { }; // Step 1: Create solid by subtracting the 2 small spheres from the large sphere - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createUniformScale(5)), AngleSweep.createFullLatitude(), true)!); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(0, 0, 5), Matrix3d.createUniformScale(3)), AngleSweep.createFullLatitude(), true)!); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(0, 0, -5), Matrix3d.createUniformScale(3)), AngleSweep.createFullLatitude(), true)!); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createUniformScale(5)), + AngleSweep.createFullLatitude(), + true, + )!, + ); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(0, 0, 5), Matrix3d.createUniformScale(3)), + AngleSweep.createFullLatitude(), + true, + )!, + ); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(0, 0, -5), Matrix3d.createUniformScale(3)), + AngleSweep.createFullLatitude(), + true, + )!, + ); const createProps: BRepGeometryCreate = { operation: BRepGeometryOperation.Subtract, @@ -2543,9 +3061,27 @@ describe("BRepGeometry", () => { }; // Step 1: Create two solids by intersecting the 2 small spheres with the large sphere - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(2, 2, 0), Matrix3d.createUniformScale(5)), AngleSweep.createFullLatitude(), true)!); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(2, 2, 5), Matrix3d.createUniformScale(3)), AngleSweep.createFullLatitude(), true)!); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(2, 2, -5), Matrix3d.createUniformScale(3)), AngleSweep.createFullLatitude(), true)!); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(2, 2, 0), Matrix3d.createUniformScale(5)), + AngleSweep.createFullLatitude(), + true, + )!, + ); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(2, 2, 5), Matrix3d.createUniformScale(3)), + AngleSweep.createFullLatitude(), + true, + )!, + ); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(2, 2, -5), Matrix3d.createUniformScale(3)), + AngleSweep.createFullLatitude(), + true, + )!, + ); const createProps: BRepGeometryCreate = { operation: BRepGeometryOperation.Intersect, @@ -2574,8 +3110,20 @@ describe("BRepGeometry", () => { it("unite/subtract/intersect solids test", async () => { const builder = new ElementGeometry.Builder(); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createUniformScale(5)), AngleSweep.createFullLatitude(), true)!); - builder.appendGeometryQuery(Sphere.createEllipsoid(Transform.createOriginAndMatrix(Point3d.create(5, 0, 0), Matrix3d.createUniformScale(3)), AngleSweep.createFullLatitude(), true)!); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createUniformScale(5)), + AngleSweep.createFullLatitude(), + true, + )!, + ); + builder.appendGeometryQuery( + Sphere.createEllipsoid( + Transform.createOriginAndMatrix(Point3d.create(5, 0, 0), Matrix3d.createUniformScale(3)), + AngleSweep.createFullLatitude(), + true, + )!, + ); const onResult: BRepGeometryFunction = (info: BRepGeometryInfo): void => { assert.isTrue(undefined !== info.entryArray && 1 === info.entryArray.length && ElementGeometryOpcode.BRep === info.entryArray[0].opcode); @@ -2631,12 +3179,60 @@ describe("BRepGeometry", () => { it("sew sheets test", async () => { const builder = new ElementGeometry.Builder(); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 0), Point3d.create(0, 2, 0), Point3d.create(1, 2, 0), Point3d.create(1, 0, 0), Point3d.create(0, 0, 0)])); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 3), Point3d.create(1, 0, 3), Point3d.create(1, 2, 3), Point3d.create(0, 2, 3), Point3d.create(0, 0, 3)])); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 0, 3), Point3d.create(0, 0, 3), Point3d.create(0, 0, 0)])); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(1, 2, 0), Point3d.create(0, 2, 0), Point3d.create(0, 2, 3), Point3d.create(1, 2, 3), Point3d.create(1, 2, 0)])); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 2, 0), Point3d.create(0, 0, 0), Point3d.create(0, 0, 3), Point3d.create(0, 2, 3), Point3d.create(0, 2, 0)])); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(1, 0, 0), Point3d.create(1, 2, 0), Point3d.create(1, 2, 3), Point3d.create(1, 0, 3), Point3d.create(1, 0, 0)])); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 0), + Point3d.create(0, 2, 0), + Point3d.create(1, 2, 0), + Point3d.create(1, 0, 0), + Point3d.create(0, 0, 0), + ]), + ); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 3), + Point3d.create(1, 0, 3), + Point3d.create(1, 2, 3), + Point3d.create(0, 2, 3), + Point3d.create(0, 0, 3), + ]), + ); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 0, 3), + Point3d.create(0, 0, 3), + Point3d.create(0, 0, 0), + ]), + ); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(1, 2, 0), + Point3d.create(0, 2, 0), + Point3d.create(0, 2, 3), + Point3d.create(1, 2, 3), + Point3d.create(1, 2, 0), + ]), + ); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 2, 0), + Point3d.create(0, 0, 0), + Point3d.create(0, 0, 3), + Point3d.create(0, 2, 3), + Point3d.create(0, 2, 0), + ]), + ); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(1, 0, 0), + Point3d.create(1, 2, 0), + Point3d.create(1, 2, 3), + Point3d.create(1, 0, 3), + Point3d.create(1, 0, 0), + ]), + ); const onResult: BRepGeometryFunction = (info: BRepGeometryInfo): void => { assert.isTrue(undefined !== info.entryArray && 1 === info.entryArray.length && ElementGeometryOpcode.BRep === info.entryArray[0].opcode); @@ -2739,7 +3335,15 @@ describe("BRepGeometry", () => { // Test embossing a surface builder.entries.length = 0; - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 0), Point3d.create(0, 5, 0), Point3d.create(5, 5, 0), Point3d.create(5, 0, 0), Point3d.create(0, 0, 0)])); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 0), + Point3d.create(0, 5, 0), + Point3d.create(5, 5, 0), + Point3d.create(5, 0, 0), + Point3d.create(0, 0, 0), + ]), + ); builder.appendGeometryQuery(Loop.create(Arc3d.createXY(Point3d.create(2.5, 2.5, -0.5), 2, AngleSweep.createStartSweepDegrees(0, -360)))); try { @@ -2751,7 +3355,15 @@ describe("BRepGeometry", () => { it("thicken surfaces test", async () => { const builder = new ElementGeometry.Builder(); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 0), Point3d.create(0, 5, 0), Point3d.create(5, 5, 0), Point3d.create(5, 0, 0), Point3d.create(0, 0, 0)])); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 0), + Point3d.create(0, 5, 0), + Point3d.create(5, 5, 0), + Point3d.create(5, 0, 0), + Point3d.create(0, 0, 0), + ]), + ); const onResult: BRepGeometryFunction = (info: BRepGeometryInfo): void => { assert.isTrue(undefined !== info.entryArray && 1 === info.entryArray.length && ElementGeometryOpcode.BRep === info.entryArray[0].opcode); @@ -2786,7 +3398,15 @@ describe("BRepGeometry", () => { it("offset surfaces test", async () => { const builder = new ElementGeometry.Builder(); - builder.appendGeometryQuery(Loop.createPolygon([Point3d.create(0, 0, 0), Point3d.create(0, 5, 0), Point3d.create(5, 5, 0), Point3d.create(5, 0, 0), Point3d.create(0, 0, 0)])); + builder.appendGeometryQuery( + Loop.createPolygon([ + Point3d.create(0, 0, 0), + Point3d.create(0, 5, 0), + Point3d.create(5, 5, 0), + Point3d.create(5, 0, 0), + Point3d.create(0, 0, 0), + ]), + ); const onResult: BRepGeometryFunction = (info: BRepGeometryInfo): void => { assert.isTrue(undefined !== info.entryArray && 1 === info.entryArray.length && ElementGeometryOpcode.BRep === info.entryArray[0].opcode); @@ -2850,7 +3470,9 @@ describe("BRepGeometry", () => { it("sweep profile along path test", async () => { const builder = new ElementGeometry.Builder(); builder.appendGeometryQuery(Loop.create(Arc3d.createXY(Point3d.create(0, 0, 0), 1))); - builder.appendGeometryQuery(LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(0, 0, 3), Point3d.create(5, 0, 3), Point3d.create(8, 10, 10))); + builder.appendGeometryQuery( + LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(0, 0, 3), Point3d.create(5, 0, 3), Point3d.create(8, 10, 10)), + ); const onResult: BRepGeometryFunction = (info: BRepGeometryInfo): void => { assert.isTrue(undefined !== info.entryArray && 1 === info.entryArray.length && ElementGeometryOpcode.BRep === info.entryArray[0].opcode); @@ -2932,7 +3554,10 @@ describe("BRepGeometry", () => { assert.exists(brep); gsBuilder.appendBRepData(brep!); - const elementProps = createPhysicalElementProps(seedElement, { origin: Point3d.create(5, 10, 0), angles: YawPitchRollAngles.createDegrees(45, 0, 0) }, gsBuilder.geometryStream); + const elementProps = createPhysicalElementProps(seedElement, { + origin: Point3d.create(5, 10, 0), + angles: YawPitchRollAngles.createDegrees(45, 0, 0), + }, gsBuilder.geometryStream); const testElem = imodel.elements.createElement(elementProps); const newId = imodel.elements.insertElement(testElem.toJSON()); imodel.saveChanges(); @@ -3009,7 +3634,15 @@ describe("Mass Properties", () => { assert.exists(seedElement); assert.isTrue(seedElement.federationGuid! === "18eb4650-b074-414f-b961-d9cfaa6c8746"); - const shape = Loop.create(LineString3d.create(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 0))); + const shape = Loop.create( + LineString3d.create( + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 0), + ), + ); const builder = new GeometryStreamBuilder(); builder.appendGeometry(shape); @@ -3063,7 +3696,14 @@ describe("Geometry Containment", () => { const block = ClipShape.createBlock(range, ClipMaskXYZRangePlanes.All, false, false); clip.appendReference(block); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyInside]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyInside, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideId, rangeOutsideId, edgeOverlapId, cornerOverlapId, rangeOvrGeomOutId, rangeOvrGeomInId], @@ -3109,7 +3749,14 @@ describe("Geometry Containment", () => { const block = ClipShape.createBlock(range, ClipMaskXYZRangePlanes.All, false, false); clip.appendReference(block); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyInside]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyInside, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideId, rangeOutsideId, edgeOverlapId, cornerOverlapId, rangeOvrGeomOutId, rangeOvrGeomInId], @@ -3159,7 +3806,14 @@ describe("Geometry Containment", () => { const rangeOutsideRId = createPartElem(partAId, Point3d.create(12, 5, 0), YawPitchRollAngles.createDegrees(0, 0, 0), imodel, seedElement, true); const edgeOverlapRId = createPartElem(partAId, Point3d.create(0, 5, 0), YawPitchRollAngles.createDegrees(0, 0, 0), imodel, seedElement, true); const cornerOverlapRId = createPartElem(partAId, Point3d.create(10, 10, 0), YawPitchRollAngles.createDegrees(0, 0, 0), imodel, seedElement, true); - const rangeOvrGeomOutRId = createPartElem(partBId, Point3d.create(11, -1, 0), YawPitchRollAngles.createDegrees(0, 0, 0), imodel, seedElement, true); + const rangeOvrGeomOutRId = createPartElem( + partBId, + Point3d.create(11, -1, 0), + YawPitchRollAngles.createDegrees(0, 0, 0), + imodel, + seedElement, + true, + ); const rangeOvrGeomInRId = createPartElem(partCId, Point3d.create(5, 9, 0), YawPitchRollAngles.createDegrees(45, 0, 0), imodel, seedElement, true); imodel.saveChanges(); @@ -3169,10 +3823,36 @@ describe("Geometry Containment", () => { const block = ClipShape.createBlock(range, ClipMaskXYZRangePlanes.All, false, false); clip.appendReference(block); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyInside]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyInside, + ]; const requestProps: GeometryContainmentRequestProps = { - candidates: [rangeInsideId, rangeOutsideId, edgeOverlapId, cornerOverlapId, rangeOvrGeomOutId, rangeOvrGeomInId, rangeInsideRId, rangeOutsideRId, edgeOverlapRId, cornerOverlapRId, rangeOvrGeomOutRId, rangeOvrGeomInRId], + candidates: [ + rangeInsideId, + rangeOutsideId, + edgeOverlapId, + cornerOverlapId, + rangeOvrGeomOutId, + rangeOvrGeomInId, + rangeInsideRId, + rangeOutsideRId, + edgeOverlapRId, + cornerOverlapRId, + rangeOvrGeomOutRId, + rangeOvrGeomInRId, + ], clip: clip.toJSON(), allowOverlaps: true, }; @@ -3213,7 +3893,12 @@ describe("Geometry Containment", () => { const block = ClipShape.createBlock(range, ClipMaskXYZRangePlanes.All, false, false); clip.appendReference(block); - const expectedContainmentDef: ClipPlaneContainment[] = [ClipPlaneContainment.Ambiguous, ClipPlaneContainment.Ambiguous, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.Ambiguous]; + const expectedContainmentDef: ClipPlaneContainment[] = [ + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.Ambiguous, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.Ambiguous, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [primInConsOutId, primOutConsInId, primInConsInId, primOvrConsOvrId], @@ -3230,7 +3915,12 @@ describe("Geometry Containment", () => { assert.isTrue(0 === result.numOutside); assert.isTrue(3 === result.numOverlap); - const expectedContainmentSubCat: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyOutside]; + const expectedContainmentSubCat: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyOutside, + ]; requestProps.offSubCategories = [IModel.getDefaultSubCategoryId(seedElement.category)]; result = await imodel.getGeometryContainment(requestProps); @@ -3242,7 +3932,12 @@ describe("Geometry Containment", () => { assert.isTrue(4 === result.numOutside); assert.isTrue(0 === result.numOverlap); - const expectedContainmentViewFlags: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.Ambiguous]; + const expectedContainmentViewFlags: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.Ambiguous, + ]; const flags = new ViewFlags(); // constructions are off by default... requestProps.viewFlags = flags; @@ -3281,7 +3976,13 @@ describe("Geometry Containment", () => { const clip = ClipVector.createEmpty(); clip.appendShape(clipShapePts, -5, 5); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideXYId, rangeInsideXId, rangeInsideYId, rangeOutsideId, rangeOvrGeomOvrId], @@ -3323,7 +4024,13 @@ describe("Geometry Containment", () => { const clip = ClipVector.createEmpty(); clip.appendShape(clipShapePts, -5, 5); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideXYId, rangeInsideXId, rangeInsideYId, rangeOutsideId, rangeOvrGeomOvrId], @@ -3359,7 +4066,11 @@ describe("Geometry Containment", () => { const clip = ClipVector.createEmpty(); clip.appendReference(prim); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideId, rangeOutsideId, rangeOverlapId], @@ -3395,7 +4106,11 @@ describe("Geometry Containment", () => { const clip = ClipVector.createEmpty(); clip.appendReference(prim); - const expectedContainment: ClipPlaneContainment[] = [ClipPlaneContainment.StronglyInside, ClipPlaneContainment.StronglyOutside, ClipPlaneContainment.Ambiguous]; + const expectedContainment: ClipPlaneContainment[] = [ + ClipPlaneContainment.StronglyInside, + ClipPlaneContainment.StronglyOutside, + ClipPlaneContainment.Ambiguous, + ]; const requestProps: GeometryContainmentRequestProps = { candidates: [rangeInsideId, rangeOutsideId, rangeOverlapId], @@ -3412,5 +4127,4 @@ describe("Geometry Containment", () => { assert.isTrue(1 === result.numOverlap); result.candidatesContainment!.forEach((val, index) => assert.isTrue(val === expectedContainment[index])); }); - }); diff --git a/core/backend/src/test/standalone/HubMock.test.ts b/core/backend/src/test/standalone/HubMock.test.ts index 37680dad5d85..db9b0b804de4 100644 --- a/core/backend/src/test/standalone/HubMock.test.ts +++ b/core/backend/src/test/standalone/HubMock.test.ts @@ -3,19 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { join } from "path"; import { AccessToken, Guid, Mutable } from "@itwin/core-bentley"; import { ChangesetFileProps, ChangesetType, LockState } from "@itwin/core-common"; +import { assert, expect } from "chai"; +import { join } from "path"; import { LockProps } from "../../BackendHubAccess"; import { BriefcaseManager } from "../../BriefcaseManager"; +import { ProgressFunction, ProgressStatus } from "../../CheckpointManager"; +import { HubMock } from "../../HubMock"; import { IModelHost } from "../../IModelHost"; import { IModelJsFs } from "../../IModelJsFs"; -import { HubMock } from "../../HubMock"; +import { LockStatusExclusive, LockStatusShared } from "../../LocalHub"; import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; -import { LockStatusExclusive, LockStatusShared } from "../../LocalHub"; -import { ProgressFunction, ProgressStatus } from "../../CheckpointManager"; describe("HubMock", () => { const tmpDir = join(KnownTestLocations.outputDir, "HubMockTest"); @@ -77,8 +77,16 @@ describe("HubMock", () => { // try pushing changesets const cs1: ChangesetFileProps = { - id: "changeset0", description: "first changeset", changesType: ChangesetType.Regular, parentId: "", briefcaseId: 5, pushDate: "", index: 0, - userCreated: "user1", pathname, size: fileSize, + id: "changeset0", + description: "first changeset", + changesType: ChangesetType.Regular, + parentId: "", + briefcaseId: 5, + pushDate: "", + index: 0, + userCreated: "user1", + pathname, + size: fileSize, }; cs1.index = localHub.addChangeset(cs1); // first changeset const changesets1 = localHub.queryChangesets(); @@ -97,8 +105,15 @@ describe("HubMock", () => { fileSize = IModelJsFs.lstatSync(pathname)!.size; const cs2: ChangesetFileProps = { - id: "changeset1", parentId: cs1.id, description: "second changeset", changesType: ChangesetType.Schema, briefcaseId: 5, pushDate: "", index: 0, - userCreated: "user2", pathname: IModelTestUtils.resolveAssetFile("CloneTest.01.00.01.ecschema.xml"), + id: "changeset1", + parentId: cs1.id, + description: "second changeset", + changesType: ChangesetType.Schema, + briefcaseId: 5, + pushDate: "", + index: 0, + userCreated: "user2", + pathname: IModelTestUtils.resolveAssetFile("CloneTest.01.00.01.ecschema.xml"), size: fileSize, }; cs2.index = localHub.addChangeset(cs2); // second changeset, parent = cs1 @@ -133,8 +148,15 @@ describe("HubMock", () => { // test for duplicate changeset id fails const cs3: ChangesetFileProps = { - id: "changeset0", parentId: "changeset1", - description: "third changeset", changesType: ChangesetType.Regular, pathname: cs1.pathname, briefcaseId: 500, userCreated: "", pushDate: "", index: 0, + id: "changeset0", + parentId: "changeset1", + description: "third changeset", + changesType: ChangesetType.Regular, + pathname: cs1.pathname, + briefcaseId: 500, + userCreated: "", + pushDate: "", + index: 0, size: fileSize, }; expect(() => localHub.addChangeset(cs3)).throws("no briefcase with that id"); @@ -213,7 +235,9 @@ describe("HubMock", () => { assert.isTrue((lockStat as LockStatusShared).sharedBy.has(3)); assert.isTrue((lockStat as LockStatusShared).sharedBy.has(5)); - expect(() => localHub.acquireLock({ ...lock1, state: LockState.Exclusive }, { briefcaseId: 6, changeset: { id: "cs1" } })).to.throw("shared lock is held").include({ briefcaseId: 3, briefcaseAlias: "user2 briefcase 1" }); + expect(() => localHub.acquireLock({ ...lock1, state: LockState.Exclusive }, { briefcaseId: 6, changeset: { id: "cs1" } })).to.throw( + "shared lock is held", + ).include({ briefcaseId: 3, briefcaseAlias: "user2 briefcase 1" }); expect(() => localHub.releaseLocks([lock1], { briefcaseId: 9, changesetIndex: cs1.index })).to.throw("shared lock not held"); localHub.releaseLocks([lock1], { briefcaseId: 3, changesetIndex: cs1.index }); @@ -236,8 +260,13 @@ describe("HubMock", () => { localHub.acquireLock(lock1, { briefcaseId: 6, changeset: cs1 }); assert.equal(localHub.countSharedLocks(), 0); assert.equal(localHub.countLocks(), 1); - expect(() => localHub.acquireLock(lock1, { briefcaseId: 5, changeset: cs1 })).to.throw("exclusive lock is already held").include({ briefcaseId: 6, briefcaseAlias: "alias for 5" }); - expect(() => localHub.acquireLock({ ...lock1, state: LockState.Shared }, { briefcaseId: 5, changeset: cs1 })).to.throw("exclusive lock is already held").include({ briefcaseId: 6, briefcaseAlias: "alias for 5" }); + expect(() => localHub.acquireLock(lock1, { briefcaseId: 5, changeset: cs1 })).to.throw("exclusive lock is already held").include({ + briefcaseId: 6, + briefcaseAlias: "alias for 5", + }); + expect(() => localHub.acquireLock({ ...lock1, state: LockState.Shared }, { briefcaseId: 5, changeset: cs1 })).to.throw( + "exclusive lock is already held", + ).include({ briefcaseId: 6, briefcaseAlias: "alias for 5" }); localHub.releaseLocks([lock1], { briefcaseId: 6, changesetIndex: cs2.index }); assert.equal(localHub.countLocks(), 1); lockStat = localHub.queryLockStatus(lock1.id); @@ -294,14 +323,28 @@ describe("HubMock", () => { const fileSize = IModelJsFs.lstatSync(pathname)!.size; const cs1: ChangesetFileProps = { - id: "changeset0", description: "first changeset", changesType: ChangesetType.Regular, parentId: "", briefcaseId, pushDate: "", index: 0, + id: "changeset0", + description: "first changeset", + changesType: ChangesetType.Regular, + parentId: "", + briefcaseId, + pushDate: "", + index: 0, size: fileSize, - userCreated: "user1", pathname, + userCreated: "user1", + pathname, }; const cs2: ChangesetFileProps = { - id: "changeset1", parentId: cs1.id, description: "second changeset", changesType: ChangesetType.Schema, briefcaseId, pushDate: "", index: 0, + id: "changeset1", + parentId: cs1.id, + description: "second changeset", + changesType: ChangesetType.Schema, + briefcaseId, + pushDate: "", + index: 0, size: fileSize, - userCreated: "user2", pathname: IModelTestUtils.resolveAssetFile("CloneTest.01.00.01.ecschema.xml"), + userCreated: "user2", + pathname: IModelTestUtils.resolveAssetFile("CloneTest.01.00.01.ecschema.xml"), }; cs1.index = localHub.addChangeset(cs1); cs2.index = localHub.addChangeset(cs2); diff --git a/core/backend/src/test/standalone/IModelWrite.test.ts b/core/backend/src/test/standalone/IModelWrite.test.ts index 8135991f58e5..fe4b61c360f0 100644 --- a/core/backend/src/test/standalone/IModelWrite.test.ts +++ b/core/backend/src/test/standalone/IModelWrite.test.ts @@ -5,8 +5,17 @@ import { AccessToken, DbResult, GuidString, Id64, Id64String } from "@itwin/core-bentley"; import { - ChangesetIdWithIndex, Code, ColorDef, - GeometricElement2dProps, GeometryStreamProps, IModel, LockState, QueryRowFormat, RequestNewBriefcaseProps, SchemaState, SubCategoryAppearance, + ChangesetIdWithIndex, + Code, + ColorDef, + GeometricElement2dProps, + GeometryStreamProps, + IModel, + LockState, + QueryRowFormat, + RequestNewBriefcaseProps, + SchemaState, + SubCategoryAppearance, } from "@itwin/core-common"; import { Arc3d, IModelJson, Point2d, Point3d } from "@itwin/core-geometry"; import * as chai from "chai"; @@ -15,25 +24,38 @@ import * as chaiAsPromised from "chai-as-promised"; import * as fs from "fs"; import * as semver from "semver"; import * as sinon from "sinon"; -import { HubWrappers, KnownTestLocations } from "../"; import { DrawingCategory } from "../../Category"; -import { ECSqlStatement } from "../../ECSqlStatement"; -import { HubMock } from "../../HubMock"; import { _nativeDb, BriefcaseDb, BriefcaseManager, ChannelControl, - CodeService, DefinitionModel, DictionaryModel, DocumentListModel, Drawing, DrawingGraphic, OpenBriefcaseArgs, SpatialCategory, Subject, + CodeService, + DefinitionModel, + DictionaryModel, + DocumentListModel, + Drawing, + DrawingGraphic, + OpenBriefcaseArgs, + SpatialCategory, + Subject, } from "../../core-backend"; -import { IModelTestUtils, TestUserType } from "../IModelTestUtils"; +import { ECSqlStatement } from "../../ECSqlStatement"; +import { HubMock } from "../../HubMock"; import { ServerBasedLocks } from "../../internal/ServerBasedLocks"; +import { HubWrappers, KnownTestLocations } from "../"; +import { IModelTestUtils, TestUserType } from "../IModelTestUtils"; chai.use(chaiAsPromised); export async function createNewModelAndCategory(rwIModel: BriefcaseDb, parent?: Id64String) { // Create a new physical model. - const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), true, parent); + const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync( + rwIModel, + IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), + true, + parent, + ); // Find or create a SpatialCategory. const dictionary: DictionaryModel = rwIModel.models.getModel(IModel.dictionaryId); @@ -71,7 +93,6 @@ describe("IModelWriteTest", () => { let didThrow = false; try { await BriefcaseDb.open(args); - } catch (e: any) { assert.strictEqual(e.errorNumber, DbResult.BE_SQLITE_BUSY, "Expect error 'Db is busy'"); didThrow = true; @@ -86,10 +107,26 @@ describe("IModelWriteTest", () => { // lock db so another connection cannot write to it. db.saveFileProperty({ name: "test", namespace: "test" }, ""); - assert.isAtMost(await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(0) }), seconds(1), "open should fail with busy error instantly"); - assert.isAtLeast(await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(1) }), seconds(1), "open should fail with atleast 1 sec delay due to retry"); - assert.isAtLeast(await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(2) }), seconds(2), "open should fail with atleast 2 sec delay due to retry"); - assert.isAtLeast(await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(3) }), seconds(3), "open should fail with atleast 3 sec delay due to retry"); + assert.isAtMost( + await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(0) }), + seconds(1), + "open should fail with busy error instantly", + ); + assert.isAtLeast( + await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(1) }), + seconds(1), + "open should fail with atleast 1 sec delay due to retry", + ); + assert.isAtLeast( + await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(2) }), + seconds(2), + "open should fail with atleast 2 sec delay due to retry", + ); + assert.isAtLeast( + await tryOpen({ fileName: briefcaseProps.fileName, busyTimeout: seconds(3) }), + seconds(3), + "open should fail with atleast 3 sec delay due to retry", + ); db.abandonChanges(); db.close(); @@ -106,7 +143,7 @@ describe("IModelWriteTest", () => { let nClosed = 0; const fsWatcher = { - callback: () => { }, + callback: () => {}, close: () => ++nClosed, }; const watchStub: any = (_filename: fs.PathLike, _opts: fs.WatchOptions, fn: () => void) => { @@ -157,7 +194,7 @@ describe("IModelWriteTest", () => { let nClosed = 0; const fsWatcher = { - callback: () => { }, + callback: () => {}, close: () => ++nClosed, }; const watchStub: any = (_filename: fs.PathLike, _opts: fs.WatchOptions, fn: () => void) => { @@ -241,7 +278,7 @@ describe("IModelWriteTest", () => { // Writer that pulls + watcher. let nClosed = 0; const fsWatcher = { - callback: () => { }, + callback: () => {}, close: () => ++nClosed, }; const watchStub: any = (_filename: fs.PathLike, _opts: fs.WatchOptions, fn: () => void) => { @@ -431,7 +468,12 @@ describe("IModelWriteTest", () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); const insertElements = (imodel: BriefcaseDb, className: string = "Test2dElement", noOfElements: number = 10, userProp: (n: number) => object) => { for (let m = 0; m < noOfElements; ++m) { @@ -483,9 +525,9 @@ describe("IModelWriteTest", () => { CodeService.createForIModel = async () => { throw new CodeService.Error("MissingCode", 0x10000 + 1, " "); }; - const briefcaseDb = await BriefcaseDb.open({ fileName: briefcaseProps.fileName}); + const briefcaseDb = await BriefcaseDb.open({ fileName: briefcaseProps.fileName }); briefcaseDb.channels.addAllowedChannel(ChannelControl.sharedChannelName); - let firstNonRootElement = {id:undefined, codeValue: "test"}; + let firstNonRootElement = { id: undefined, codeValue: "test" }; briefcaseDb.withPreparedStatement("SELECT * from Bis.Element LIMIT 1 OFFSET 1", (stmt: ECSqlStatement) => { if (stmt.step() === DbResult.BE_SQLITE_ROW) { firstNonRootElement = stmt.getRow(); @@ -493,11 +535,17 @@ describe("IModelWriteTest", () => { }); // make change to the briefcaseDb that does not affect code, e.g., save file property // expect no error from verifyCode - expect(() => briefcaseDb.saveFileProperty({ name: "codeServiceProp", namespace: "codeService", id: 1, subId: 1 }, "codeService test")).to.not.throw(); + expect(() => briefcaseDb.saveFileProperty({ name: "codeServiceProp", namespace: "codeService", id: 1, subId: 1 }, "codeService test")).to.not + .throw(); // make change to the briefcaseDb that affects code that will invoke verifyCode, e.g., update an element with a non-null code // expect error from verifyCode - let newProps = { id: firstNonRootElement.id, code: {...Code.createEmpty(), value:firstNonRootElement.codeValue}, classFullName: undefined, model: undefined }; - await briefcaseDb.locks.acquireLocks({exclusive: firstNonRootElement.id}); + let newProps = { + id: firstNonRootElement.id, + code: { ...Code.createEmpty(), value: firstNonRootElement.codeValue }, + classFullName: undefined, + model: undefined, + }; + await briefcaseDb.locks.acquireLocks({ exclusive: firstNonRootElement.id }); expect(() => briefcaseDb.elements.updateElement(newProps)).to.throw(CodeService.Error); // make change to the briefcaseDb that will invoke verifyCode with a null(empty) code, e.g., update an element with a null(empty) code // expect no error from verifyCode @@ -508,12 +556,17 @@ describe("IModelWriteTest", () => { CodeService.createForIModel = async () => { throw new CodeService.Error("NoCodeIndex", 0x10000 + 1, " "); }; - const briefcaseDb2 = await BriefcaseDb.open({ fileName: briefcaseProps.fileName}); + const briefcaseDb2 = await BriefcaseDb.open({ fileName: briefcaseProps.fileName }); briefcaseDb2.channels.addAllowedChannel(ChannelControl.sharedChannelName); - await briefcaseDb2.locks.acquireLocks({exclusive: firstNonRootElement.id}); + await briefcaseDb2.locks.acquireLocks({ exclusive: firstNonRootElement.id }); // expect no error from verifyCode for empty code expect(() => briefcaseDb2.elements.updateElement(newProps)).to.not.throw(); - newProps = { id: firstNonRootElement.id, code: {...Code.createEmpty(), value:firstNonRootElement.codeValue}, classFullName: undefined, model: undefined }; + newProps = { + id: firstNonRootElement.id, + code: { ...Code.createEmpty(), value: firstNonRootElement.codeValue }, + classFullName: undefined, + model: undefined, + }; // make change to the briefcaseDb that affects code that will invoke verifyCode, e.g., update an element with a non-null code // expect no error from verifyCode expect(() => briefcaseDb2.elements.updateElement(newProps)).to.not.throw(); @@ -569,7 +622,12 @@ describe("IModelWriteTest", () => { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(rwIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(rwIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(rwIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + rwIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); const insertElements = (imodel: BriefcaseDb, className: string = "Test2dElement", noOfElements: number = 10, userProp: (n: number) => object) => { for (let m = 0; m < noOfElements; ++m) { @@ -624,7 +682,11 @@ describe("IModelWriteTest", () => { assert.equal(rows.length, 10); assert.equal(rows.map((r) => r.s).filter((v) => v).length, 10); rows = []; - for await (const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 10); @@ -641,7 +703,11 @@ describe("IModelWriteTest", () => { assert.equal(rows.length, 10); assert.equal(rows.map((r) => r.s).filter((v) => v).length, 10); rows = []; - for await (const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 10); @@ -698,14 +764,16 @@ describe("IModelWriteTest", () => { await rwIModel.locks.acquireLocks({ shared: drawingModelId }); insertElements(rwIModel, "Test2dElement", 10, (n: number) => { return { - s: `s-${n}`, v: `v-${n}`, + s: `s-${n}`, + v: `v-${n}`, }; }); // create some element and push those changes insertElements(rwIModel, "Test2dElement2nd", 10, (n: number) => { return { - t: `t-${n}`, r: `r-${n}`, + t: `t-${n}`, + r: `r-${n}`, }; }); assert.equal(6279, rwIModel[_nativeDb].getChangesetSize()); @@ -731,7 +799,11 @@ describe("IModelWriteTest", () => { assert.equal(rows.map((r) => r.s).filter((v) => v).length, 30); assert.equal(rows.map((r) => r.v).filter((v) => v).length, 10); rows = []; - for await (const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 30); @@ -748,7 +820,11 @@ describe("IModelWriteTest", () => { assert.equal(rows.map((r) => r.t).filter((v) => v).length, 10); assert.equal(rows.map((r) => r.r).filter((v) => v).length, 10); rows = []; - for await (const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement2nd", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel.createQueryReader("SELECT * FROM TestDomain.Test2dElement2nd", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 10); @@ -770,7 +846,11 @@ describe("IModelWriteTest", () => { assert.equal(rows.map((r) => r.v).filter((v) => v).length, 10); rows = []; // Following fail without native side fix where we clear concurrent query cache on schema changeset apply - for await (const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 30); @@ -814,7 +894,11 @@ describe("IModelWriteTest", () => { } } rows = []; - for await (const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement2nd", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of rwIModel2.createQueryReader("SELECT * FROM TestDomain.Test2dElement2nd", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { rows.push(queryRow.toRow()); } assert.equal(rows.length, 10); @@ -973,7 +1057,5 @@ describe("IModelWriteTest", () => { expect(serverLocks.getLockCount(LockState.Shared)).equal(0); expect(serverLocks.getLockCount(LockState.Exclusive)).equal(0); iModel.close(); - }); - }); diff --git a/core/backend/src/test/standalone/InlineGeometryPartReferences.test.ts b/core/backend/src/test/standalone/InlineGeometryPartReferences.test.ts index eb3cee9a2ba4..00b67fdf74d6 100644 --- a/core/backend/src/test/standalone/InlineGeometryPartReferences.test.ts +++ b/core/backend/src/test/standalone/InlineGeometryPartReferences.test.ts @@ -2,20 +2,40 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; -import { LineString3d, Loop, Point3d } from "@itwin/core-geometry"; import { AreaPattern, - Code, ColorDef, GeometricElement3dProps, GeometryParams, GeometryPartProps, GeometryStreamBuilder, GeometryStreamIterator, IModel, + Code, + ColorDef, + GeometricElement3dProps, + GeometryParams, + GeometryPartProps, + GeometryStreamBuilder, + GeometryStreamIterator, + IModel, } from "@itwin/core-common"; +import { LineString3d, Loop, Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { - _nativeDb, GenericSchema, GeometricElement3d, GeometryPart, PhysicalModel, PhysicalObject, PhysicalPartition, RenderMaterialElement, SnapshotDb, SpatialCategory, SubCategory, SubjectOwnsPartitionElements, + _nativeDb, + GenericSchema, + GeometricElement3d, + GeometryPart, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + RenderMaterialElement, + SnapshotDb, + SpatialCategory, + SubCategory, + SubjectOwnsPartitionElements, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; // The only geometry in our geometry streams will be squares of 1 meter in x and y, with origin at (pos, 0, 0). -interface Primitive { pos: number } +interface Primitive { + pos: number; +} interface PartRef { partId: string; @@ -40,15 +60,17 @@ function makeGeomParams(symb: Symbology): GeometryParams { return params; } -interface AppendSubRanges { appendSubRanges: true } +interface AppendSubRanges { + appendSubRanges: true; +} type UnionMember = T & { [k in keyof U]?: never }; type GeomWriterEntry = - UnionMember | - UnionMember | - UnionMember | - UnionMember; + | UnionMember + | UnionMember + | UnionMember + | UnionMember; class GeomWriter { public readonly builder: GeometryStreamBuilder; @@ -65,25 +87,34 @@ class GeomWriter { else if (entry.subCategoryId || entry.categoryId || entry.color || entry.materialId || entry.patternOrigin) this.builder.appendGeometryParamsChange(makeGeomParams(entry)); else if (undefined !== entry.pos) - this.builder.appendGeometry(Loop.createPolygon([new Point3d(entry.pos, 0, 0), new Point3d(entry.pos + 1, 0, 0), new Point3d(entry.pos + 1, 1, 0), new Point3d(entry.pos, 1, 0)])); + this.builder.appendGeometry( + Loop.createPolygon([ + new Point3d(entry.pos, 0, 0), + new Point3d(entry.pos + 1, 0, 0), + new Point3d(entry.pos + 1, 1, 0), + new Point3d(entry.pos, 1, 0), + ]), + ); else if (undefined !== entry.appendSubRanges) this.builder.appendGeometryRanges(); } } // SubGraphicRange where x dimension is 1 meter and y and z are empty. -interface SubRange { low: number } +interface SubRange { + low: number; +} type GeomStreamEntry = - UnionMember | - UnionMember | - UnionMember | - UnionMember; + | UnionMember + | UnionMember + | UnionMember + | UnionMember; function readGeomStream(iter: GeometryStreamIterator): GeomStreamEntry[] & { viewIndependent: boolean } { const result: GeomStreamEntry[] = []; for (const entry of iter) { - const symb: Symbology = { categoryId: entry.geomParams.categoryId, subCategoryId: entry.geomParams.subCategoryId }; + const symb: Symbology = { categoryId: entry.geomParams.categoryId, subCategoryId: entry.geomParams.subCategoryId }; if (undefined !== entry.geomParams.lineColor) symb.color = entry.geomParams.lineColor; @@ -215,7 +246,7 @@ describe("DgnDb.inlineGeometryPartReferences", () => { geom: writer.builder.geometryStream, placement: { origin: [0, 0, 0], - angles: { }, + angles: {}, }, }; @@ -312,7 +343,7 @@ describe("DgnDb.inlineGeometryPartReferences", () => { const part1 = insertGeometryPart([ { pos: 1 }, { color: ColorDef.green }, - { pos: 1.5}, + { pos: 1.5 }, ]); const part2 = insertGeometryPart([ @@ -354,7 +385,7 @@ describe("DgnDb.inlineGeometryPartReferences", () => { { categoryId, subCategoryId: blueSubCategoryId }, { pos: -1 }, { categoryId, subCategoryId: redSubCategoryId }, - { low: 1}, + { low: 1 }, { pos: 1 }, { categoryId, subCategoryId: redSubCategoryId, color: ColorDef.green }, { low: 1.5 }, @@ -379,7 +410,7 @@ describe("DgnDb.inlineGeometryPartReferences", () => { { categoryId, subCategoryId: redSubCategoryId, materialId: "0" }, { low: 3.5 }, { pos: 3.5 }, - {categoryId, subCategoryId: redSubCategoryId, color: ColorDef.white, materialId }, + { categoryId, subCategoryId: redSubCategoryId, color: ColorDef.white, materialId }, { low: -4 }, { pos: -4 }, ]); diff --git a/core/backend/src/test/standalone/MergeConflict.test.ts b/core/backend/src/test/standalone/MergeConflict.test.ts index a0a8af1fc634..fba00fd985d7 100644 --- a/core/backend/src/test/standalone/MergeConflict.test.ts +++ b/core/backend/src/test/standalone/MergeConflict.test.ts @@ -4,28 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import { GuidString, Id64String } from "@itwin/core-bentley"; -import { - ElementAspectProps, - IModel, - SubCategoryAppearance, -} from "@itwin/core-common"; +import { ElementAspectProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import * as chai from "chai"; import { assert, expect } from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { HubWrappers, KnownTestLocations } from "../"; +import { BriefcaseDb, ChannelControl, DictionaryModel, SpatialCategory } from "../../core-backend"; import { HubMock } from "../../HubMock"; -import { - BriefcaseDb, - ChannelControl, - DictionaryModel, - SpatialCategory, -} from "../../core-backend"; +import { HubWrappers, KnownTestLocations } from "../"; import { IModelTestUtils, TestUserType } from "../IModelTestUtils"; chai.use(chaiAsPromised); import sinon = require("sinon"); export async function createNewModelAndCategory(rwIModel: BriefcaseDb, parent?: Id64String) { // Create a new physical model. - const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), true, parent); + const [, modelId] = await IModelTestUtils.createAndInsertPhysicalPartitionAndModelAsync( + rwIModel, + IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), + true, + parent, + ); // Find or create a SpatialCategory. const dictionary: DictionaryModel = rwIModel.models.getModel(IModel.dictionaryId); @@ -72,7 +68,13 @@ describe("Merge conflict & locking", () => { const iModelName = "TestIModel"; // Create a new empty iModel on the Hub & obtain a briefcase - const rwIModelId = await HubMock.createNewIModel({ accessToken: accessToken1, iTwinId, iModelName, description: "TestSubject", noLocks: undefined }); + const rwIModelId = await HubMock.createNewIModel({ + accessToken: accessToken1, + iTwinId, + iModelName, + description: "TestSubject", + noLocks: undefined, + }); assert.isNotEmpty(rwIModelId); // to reproduce the issue we will disable locks altogether. @@ -86,7 +88,8 @@ describe("Merge conflict & locking", () => { const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( b1, IModelTestUtils.getUniqueModelCode(b1, "newPhysicalModel"), - true); + true, + ); const dictionary: DictionaryModel = b1.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "ThisTestSpatialCategory"); @@ -146,7 +149,8 @@ describe("Merge conflict & locking", () => { const onChangesetConflictStub = sinon.stub(BriefcaseDb.prototype, "onChangesetConflict" as any); await assertThrowsAsync( async () => b2.pushChanges({ accessToken: accessToken1, description: `modify aspect ${aspectId1} with no lock` }), - "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered."); + "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered.", + ); expect(onChangesetConflictStub.callCount).greaterThanOrEqual(1, "native conflict handler must call BriefcaseDb.onChangesetConflict()"); onChangesetConflictStub.restore(); @@ -170,7 +174,13 @@ describe("Merge conflict & locking", () => { const iModelName = "TestIModel"; // Create a new empty iModel on the Hub & obtain a briefcase - const rwIModelId = await HubMock.createNewIModel({ accessToken: accessToken1, iTwinId, iModelName, description: "TestSubject", noLocks: undefined }); + const rwIModelId = await HubMock.createNewIModel({ + accessToken: accessToken1, + iTwinId, + iModelName, + description: "TestSubject", + noLocks: undefined, + }); assert.isNotEmpty(rwIModelId); // to reproduce the issue we will disable locks altogether. @@ -184,7 +194,8 @@ describe("Merge conflict & locking", () => { const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( b1, IModelTestUtils.getUniqueModelCode(b1, "newPhysicalModel"), - true); + true, + ); const dictionary: DictionaryModel = b1.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "ThisTestSpatialCategory"); @@ -219,7 +230,8 @@ describe("Merge conflict & locking", () => { const onChangesetConflictStub = sinon.stub(BriefcaseDb.prototype, "onChangesetConflict" as any); await assertThrowsAsync( async () => b2.pushChanges({ accessToken: accessToken2, description: `add aspect to element ${el1}` }), - "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered."); + "UPDATE/DELETE before value do not match with one in db or CASCADE action was triggered.", + ); expect(onChangesetConflictStub.callCount).greaterThanOrEqual(1, "native conflict handler must call BriefcaseDb.onChangesetConflict()"); onChangesetConflictStub.restore(); @@ -240,7 +252,13 @@ describe("Merge conflict & locking", () => { const iModelName = "TestIModel"; // Create a new empty iModel on the Hub & obtain a briefcase - const rwIModelId = await HubMock.createNewIModel({ accessToken: accessToken1, iTwinId, iModelName, description: "TestSubject", noLocks: undefined }); + const rwIModelId = await HubMock.createNewIModel({ + accessToken: accessToken1, + iTwinId, + iModelName, + description: "TestSubject", + noLocks: undefined, + }); assert.isNotEmpty(rwIModelId); const b1 = await HubWrappers.downloadAndOpenBriefcase({ accessToken: accessToken1, iTwinId, iModelId: rwIModelId }); @@ -256,7 +274,8 @@ describe("Merge conflict & locking", () => { const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( b1, IModelTestUtils.getUniqueModelCode(b1, "newPhysicalModel"), - true); + true, + ); const dictionary: DictionaryModel = b1.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "ThisTestSpatialCategory"); @@ -287,7 +306,10 @@ describe("Merge conflict & locking", () => { }; /* attempt to insert aspect without a lock */ - assert.throws(insertAspectIntoB2, "Error inserting ElementAspect [exclusive lock not held on element for insert aspect (id=0x20000000004)], class: BisCore:ExternalSourceAspect"); + assert.throws( + insertAspectIntoB2, + "Error inserting ElementAspect [exclusive lock not held on element for insert aspect (id=0x20000000004)], class: BisCore:ExternalSourceAspect", + ); /* acquire lock and try again */ await b2.locks.acquireLocks({ exclusive: el1 }); @@ -316,7 +338,10 @@ describe("Merge conflict & locking", () => { }; /* attempt to update aspect without a lock */ - assert.throws(updateAspectIntoB1, "Error updating ElementAspect [exclusive lock not held on element for update aspect (id=0x20000000004)], id: 0x30000000001"); + assert.throws( + updateAspectIntoB1, + "Error updating ElementAspect [exclusive lock not held on element for update aspect (id=0x20000000004)], id: 0x30000000001", + ); /* acquire lock and try again */ await b1.locks.acquireLocks({ exclusive: el1 }); diff --git a/core/backend/src/test/standalone/NativeAppStorage.test.ts b/core/backend/src/test/standalone/NativeAppStorage.test.ts index 295209c554f6..a166c8f3a72c 100644 --- a/core/backend/src/test/standalone/NativeAppStorage.test.ts +++ b/core/backend/src/test/standalone/NativeAppStorage.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; import { IModelJsFs } from "../../IModelJsFs"; -import { NativeHost } from "../../NativeHost"; import { NativeAppStorage } from "../../NativeAppStorage"; +import { NativeHost } from "../../NativeHost"; describe("NativeApp storage backend", () => { before(async () => { diff --git a/core/backend/src/test/standalone/RenderMaterialElement.test.ts b/core/backend/src/test/standalone/RenderMaterialElement.test.ts index 0c2da791b925..d61cdfea2e53 100644 --- a/core/backend/src/test/standalone/RenderMaterialElement.test.ts +++ b/core/backend/src/test/standalone/RenderMaterialElement.test.ts @@ -3,10 +3,26 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; -import { ImageSourceFormat, IModel, NormalMapFlags, NormalMapProps, RenderMaterialAssetMapsProps, RenderMaterialAssetProps, RenderMaterialProps, TextureMapProps } from "@itwin/core-common"; -import { ChannelControl, IModelElementCloneContext, RenderMaterialElement, RenderMaterialElementParams, SnapshotDb, Texture } from "../../core-backend"; +import { + ImageSourceFormat, + IModel, + NormalMapFlags, + NormalMapProps, + RenderMaterialAssetMapsProps, + RenderMaterialAssetProps, + RenderMaterialProps, + TextureMapProps, +} from "@itwin/core-common"; +import { assert, expect } from "chai"; +import { + ChannelControl, + IModelElementCloneContext, + RenderMaterialElement, + RenderMaterialElementParams, + SnapshotDb, + Texture, +} from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; function removeUndefined(assetProps: RenderMaterialAssetProps): RenderMaterialAssetProps { @@ -29,7 +45,16 @@ function removeUndefined(assetProps: RenderMaterialAssetProps): RenderMaterialAs } function defaultBooleans(assetProps: RenderMaterialAssetProps): RenderMaterialAssetProps { - const boolKeys = ["HasBaseColor", "HasDiffuse", "HasFinish", "HasReflect", "HasReflectColor", "HasSpecular", "HasSpecularColor", "HasTransmit"] as const; + const boolKeys = [ + "HasBaseColor", + "HasDiffuse", + "HasFinish", + "HasReflect", + "HasReflectColor", + "HasSpecular", + "HasSpecularColor", + "HasTransmit", + ] as const; for (const boolKey of boolKeys) if (undefined === assetProps[boolKey]) assetProps[boolKey] = false; @@ -73,11 +98,137 @@ describe("RenderMaterialElement", () => { // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. const pngData = new Uint8Array([ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, - 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, - 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, - 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, - 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, ]); const name = `texture${++textureNumber}`; @@ -126,10 +277,10 @@ describe("RenderMaterialElement", () => { GlowColor: { TextureId: 6 }, Reflect: { TextureId: 7 }, Specular: { TextureId: 8 }, - TranslucencyColor: { OtherProp2: "test"}, // Should be unchanged, still present. + TranslucencyColor: { OtherProp2: "test" }, // Should be unchanged, still present. TransparentColor: { TextureId: 10, OtherProp: 1 }, // OtherProp should be unchanged, still present. - Displacement: { TextureId: "0x1"}, - OtherProperty: { OtherProperty: "test"}, // Should be unchanged. + Displacement: { TextureId: "0x1" }, + OtherProperty: { OtherProperty: "test" }, // Should be unchanged. } as any; /* eslint-enable @typescript-eslint/naming-convention */ const material = test({}); @@ -162,7 +313,7 @@ describe("RenderMaterialElement", () => { expect(props.jsonProperties?.materialAssets?.renderMaterial?.Map!.TransparentColor?.TextureId).to.equal("0xa"); expect((props.jsonProperties?.materialAssets?.renderMaterial?.Map!.TransparentColor as any).OtherProp).to.equal(1); expect(props.jsonProperties?.materialAssets?.renderMaterial?.Map!.Displacement?.TextureId).to.equal("0x1"); - expect(((props.jsonProperties?.materialAssets?.renderMaterial?.Map as any).OtherProperty).OtherProperty).to.equal("test"); + expect((props.jsonProperties?.materialAssets?.renderMaterial?.Map as any).OtherProperty.OtherProperty).to.equal("test"); }); it("with custom values", () => { @@ -179,14 +330,22 @@ describe("RenderMaterialElement", () => { /* eslint-disable @typescript-eslint/naming-convention */ test(params, { - HasBaseColor: true, color: params.color, - HasSpecularColor: true, specular_color: params.specularColor, - HasFinish: true, finish: params.finish, - HasTransmit: true, transmit: params.transmit, - HasDiffuse: true, diffuse: params.diffuse, - HasSpecular: true, specular: params.specular, - HasReflect: true, reflect: params.reflect, - HasReflectColor: true, reflect_color: params.reflectColor, + HasBaseColor: true, + color: params.color, + HasSpecularColor: true, + specular_color: params.specularColor, + HasFinish: true, + finish: params.finish, + HasTransmit: true, + transmit: params.transmit, + HasDiffuse: true, + diffuse: params.diffuse, + HasSpecular: true, + specular: params.specular, + HasReflect: true, + reflect: params.reflect, + HasReflectColor: true, + reflect_color: params.reflectColor, }); }); @@ -433,12 +592,12 @@ describe("RenderMaterialElement", () => { NoTextureId: { OtherProp: 1 }, }); - jsonProps.materialAssets.renderMaterial.Map = {Pattern: undefined}; + jsonProps.materialAssets.renderMaterial.Map = { Pattern: undefined }; // eslint-disable-next-line @typescript-eslint/dot-notation RenderMaterialElement["onCloned"](context, sourceProps, targetProps); // keep the sourceMap the same in targetProps expect(targetProps.jsonProperties?.materialAssets?.renderMaterial?.Map).to.have.property("Pattern").that.is.undefined; - jsonProps.materialAssets.renderMaterial.Map = {Pattern: null as any}; + jsonProps.materialAssets.renderMaterial.Map = { Pattern: null as any }; // eslint-disable-next-line @typescript-eslint/dot-notation RenderMaterialElement["onCloned"](context, sourceProps, targetProps); // keep the sourceMap the same in targetProps diff --git a/core/backend/src/test/standalone/RenderTimeline.test.ts b/core/backend/src/test/standalone/RenderTimeline.test.ts index 745d9ffc898c..ac5d9cb642e6 100644 --- a/core/backend/src/test/standalone/RenderTimeline.test.ts +++ b/core/backend/src/test/standalone/RenderTimeline.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64, Id64String, OpenMode } from "@itwin/core-bentley"; import { Code, IModel, RenderSchedule, RenderTimelineProps } from "@itwin/core-common"; +import { expect } from "chai"; import { GenericSchema, IModelJsFs, RenderTimeline, StandaloneDb } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; diff --git a/core/backend/src/test/standalone/SQLiteDb.test.ts b/core/backend/src/test/standalone/SQLiteDb.test.ts index 9f4ba17645c3..45a7f010d353 100644 --- a/core/backend/src/test/standalone/SQLiteDb.test.ts +++ b/core/backend/src/test/standalone/SQLiteDb.test.ts @@ -3,13 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, DbResult, OpenMode } from "@itwin/core-bentley"; +import { expect } from "chai"; import { SQLiteDb } from "../../SQLiteDb"; import { IModelTestUtils } from "../IModelTestUtils"; describe("SQLiteDb", () => { - it("should create new SQLiteDb", async () => { const fileName = IModelTestUtils.prepareOutputFile("SQLiteDb", "db1.db"); const db = new SQLiteDb(); @@ -33,7 +32,13 @@ describe("SQLiteDb", () => { testDb(); // now test immutable flag - db.openDb(fileName, { openMode: OpenMode.Readonly, skipFileCheck: true, immutable: true, defaultTxn: SQLiteDb.DefaultTxnMode.None, rawSQLite: true }); + db.openDb(fileName, { + openMode: OpenMode.Readonly, + skipFileCheck: true, + immutable: true, + defaultTxn: SQLiteDb.DefaultTxnMode.None, + rawSQLite: true, + }); testDb(); expect(db.isOpen).false; @@ -68,5 +73,4 @@ describe("SQLiteDb", () => { }); }); }); - }); diff --git a/core/backend/src/test/standalone/SchemaUtils.test.ts b/core/backend/src/test/standalone/SchemaUtils.test.ts index 93b7718e6350..7a92e35dd54e 100644 --- a/core/backend/src/test/standalone/SchemaUtils.test.ts +++ b/core/backend/src/test/standalone/SchemaUtils.test.ts @@ -3,11 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert } from "chai"; -import { Schema } from "../../Schema"; import * as Semver from "semver"; +import { Schema } from "../../Schema"; describe("Schema Utilities Test", () => { - it("paddedVersionToSemver", async () => { assert.equal(Schema.toSemverString("1.00.00"), "1.0.0"); assert.isNotNull(Semver.valid(Schema.toSemverString("1.00.00"))); diff --git a/core/backend/src/test/standalone/SectionDrawing.test.ts b/core/backend/src/test/standalone/SectionDrawing.test.ts index f3e0b71e8bd9..b85758139757 100644 --- a/core/backend/src/test/standalone/SectionDrawing.test.ts +++ b/core/backend/src/test/standalone/SectionDrawing.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { RelatedElement, SectionDrawingProps, SectionType } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { Drawing, SectionDrawing } from "../../Element"; -import { DocumentListModel, DrawingModel, SectionDrawingModel } from "../../Model"; import { SnapshotDb } from "../../IModelDb"; +import { DocumentListModel, DrawingModel, SectionDrawingModel } from "../../Model"; import { IModelTestUtils } from "../IModelTestUtils"; describe("SectionDrawing", () => { diff --git a/core/backend/src/test/standalone/ServerBasedLocks.test.ts b/core/backend/src/test/standalone/ServerBasedLocks.test.ts index 2a65045d6581..11cdd0d31022 100644 --- a/core/backend/src/test/standalone/ServerBasedLocks.test.ts +++ b/core/backend/src/test/standalone/ServerBasedLocks.test.ts @@ -3,23 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { AccessToken, Guid, GuidString, Id64, Id64Arg } from "@itwin/core-bentley"; +import { Code, IModel, IModelError, LocalBriefcaseProps, LockState, PhysicalElementProps, RequestNewBriefcaseProps } from "@itwin/core-common"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; import { restore as sinonRestore, spy as sinonSpy } from "sinon"; -import { AccessToken, Guid, GuidString, Id64, Id64Arg } from "@itwin/core-bentley"; -import { Code, IModel, IModelError, LocalBriefcaseProps, LockState, PhysicalElementProps, RequestNewBriefcaseProps } from "@itwin/core-common"; import { BriefcaseManager } from "../../BriefcaseManager"; +import { ChannelControl } from "../../core-backend"; import { PhysicalObject } from "../../domains/GenericElements"; import { PhysicalElement } from "../../Element"; +import { HubMock } from "../../HubMock"; import { BriefcaseDb, SnapshotDb } from "../../IModelDb"; import { IModelHost } from "../../IModelHost"; -import { ElementOwnsChildElements } from "../../NavigationRelationship"; import { ServerBasedLocks } from "../../internal/ServerBasedLocks"; -import { HubMock } from "../../HubMock"; +import { _releaseAllLocks } from "../../internal/Symbols"; +import { ElementOwnsChildElements } from "../../NavigationRelationship"; import { ExtensiveTestScenario, IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; -import { ChannelControl } from "../../core-backend"; -import { _releaseAllLocks } from "../../internal/Symbols"; const expect = chai.expect; const assert = chai.assert; diff --git a/core/backend/src/test/standalone/Setting.test.ts b/core/backend/src/test/standalone/Setting.test.ts index e27e85fd324d..c88506133c7e 100644 --- a/core/backend/src/test/standalone/Setting.test.ts +++ b/core/backend/src/test/standalone/Setting.test.ts @@ -65,7 +65,7 @@ describe("Setting", () => { it("should return false for different types", () => { expect(Setting.areEqual("1", 1)).to.be.false; - expect(Setting.areEqual([], { })).to.be.false; + expect(Setting.areEqual([], {})).to.be.false; expect(Setting.areEqual(false, undefined)).to.be.false; expect(Setting.areEqual("", false)).to.be.false; expect(Setting.areEqual([8, 9], { 0: 8, 1: 9 })).to.be.false; diff --git a/core/backend/src/test/standalone/Settings.test.ts b/core/backend/src/test/standalone/Settings.test.ts index ef6e69779ab4..d9a17c760a2e 100644 --- a/core/backend/src/test/standalone/Settings.test.ts +++ b/core/backend/src/test/standalone/Settings.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert, Mutable, OpenMode } from "@itwin/core-bentley"; +import { expect } from "chai"; +import { GcsDbProps, GeoCoordConfig } from "../../GeoCoordConfig"; import { SnapshotDb, StandaloneDb } from "../../IModelDb"; import { IModelHost } from "../../IModelHost"; import { Setting, SettingsContainer, SettingsPriority } from "../../workspace/Settings"; import { SettingGroupSchema, SettingSchema } from "../../workspace/SettingsSchemas"; import { IModelTestUtils } from "../IModelTestUtils"; -import { GcsDbProps, GeoCoordConfig } from "../../GeoCoordConfig"; describe("Settings", () => { let iModel: SnapshotDb; @@ -81,7 +81,6 @@ describe("Settings", () => { }, }, }, - }, databases: { type: "array", @@ -181,7 +180,9 @@ describe("Settings", () => { settings.addDictionary({ name: "iTwin.setting.json", priority: SettingsPriority.iTwin }, iTwinSettings); expect(settingsChanged).eq(3); - expect(() => IModelHost.appWorkspace.settings.addDictionary({ name: "iModel", priority: SettingsPriority.iModel }, imodel1Settings)).to.throw("Use IModelSettings"); + expect(() => IModelHost.appWorkspace.settings.addDictionary({ name: "iModel", priority: SettingsPriority.iModel }, imodel1Settings)).to.throw( + "Use IModelSettings", + ); expect(settings.getString("app1/sub1")).equals(imodel2Settings["app1/sub1"]); expect(settings.getString("app2/setting6")).equals(iTwinSettings["app2/setting6"]); @@ -254,7 +255,9 @@ describe("Settings", () => { // test validation of values vs. setting schemas const workspace: any = { dbName: "abc", containerId: "123", baseUri: "aab.com" }; const fontListVal: any = [{ workspace, fontName: "arial" }, { workspace, fontName: "helvetica", fontType: 3 }]; - expect(() => IModelHost.settingsSchemas.validateSetting(fontListVal, "testApp/fontList")).throws("required value for \"workspaceLimit\" is missing"); + expect(() => IModelHost.settingsSchemas.validateSetting(fontListVal, "testApp/fontList")).throws( + 'required value for "workspaceLimit" is missing', + ); workspace.workspaceLimit = 4; // add missing value expect(() => IModelHost.settingsSchemas.validateSetting(fontListVal, "testApp/fontList")).throws("value for testApp/fontList[1].fontType"); fontListVal[1].fontType = "ttf"; // correct font type to string @@ -330,7 +333,7 @@ describe("Settings", () => { } function addArray(schemaPrefix: string, name: string, value: Setting[], priority: SettingsPriority | number): void { - const settings: SettingsContainer = { }; + const settings: SettingsContainer = {}; settings[`${schemaPrefix}/array`] = value; IModelHost.appWorkspace.settings.addDictionary({ @@ -355,7 +358,7 @@ describe("Settings", () => { const settingName = `${prefix}/array`; expect(IModelHost.appWorkspace.settings.getSetting(settingName)).to.deep.equal([1, 2]); - const expected = ("true" === prefix ? [1, 2, 3, 4] : [1, 2]); + const expected = "true" === prefix ? [1, 2, 3, 4] : [1, 2]; expect(IModelHost.appWorkspace.settings.getArray(settingName)).to.deep.equal(expected); } }); @@ -384,14 +387,20 @@ describe("Settings", () => { expect(IModelHost.appWorkspace.settings.getArray("numbers/array")).to.deep.equal([4, 8, 2, 6, 10, 12, 3, 9]); - interface Point { x: number, y: number }; + interface Point { + x: number; + y: number; + } addGroup("points", "object", true); addArray("points", "a", [{ x: 1, y: 1 }, { x: 1, y: 2 }], 101); addArray("points", "b", [{ x: 2, y: 1 }, { x: 1, y: 2 }], 100); addArray("points", "c", [{ y: 1, x: 1 }, { y: 2, x: 1 }, { x: 3, y: 3 }], 99); - expect(IModelHost.appWorkspace.settings.getArray("points/array")).to.deep.equal([{ x: 1, y: 1 }, { x: 1, y: 2 }, { x: 2, y: 1 }, { x: 3, y: 3 }]); + expect(IModelHost.appWorkspace.settings.getArray("points/array")).to.deep.equal([{ x: 1, y: 1 }, { x: 1, y: 2 }, { x: 2, y: 1 }, { + x: 3, + y: 3, + }]); }); }); }); diff --git a/core/backend/src/test/standalone/SettingsSchemas.test.ts b/core/backend/src/test/standalone/SettingsSchemas.test.ts index 9d1870d1fb6a..1061898a6813 100644 --- a/core/backend/src/test/standalone/SettingsSchemas.test.ts +++ b/core/backend/src/test/standalone/SettingsSchemas.test.ts @@ -4,11 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { IModelTestUtils } from "../IModelTestUtils"; import { IModelHost } from "../../IModelHost"; +import { IModelTestUtils } from "../IModelTestUtils"; describe("SettingsSchemas", () => { - // SettingsSchema tests change the state of the IModelHost object. They should always clear // the current state before and after they run so they're not affected by, nor influence, other tests running in the same process. const restartSession = async () => { @@ -32,5 +31,4 @@ describe("SettingsSchemas", () => { expect(schemas.settingDefs.get("testApp/list/openMode")!.default).equals("singleClick"); expect(schemas.settingDefs.get("testApp/tree/blah")!.default).equals(true); }); - }); diff --git a/core/backend/src/test/standalone/SnapshotDb.test.ts b/core/backend/src/test/standalone/SnapshotDb.test.ts index d6ce5fe256cf..247e2e8b9476 100644 --- a/core/backend/src/test/standalone/SnapshotDb.test.ts +++ b/core/backend/src/test/standalone/SnapshotDb.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger } from "@itwin/core-bentley"; +import { ChangesetIdWithIndex } from "@itwin/core-common"; import { expect } from "chai"; import * as sinon from "sinon"; -import { ChangesetIdWithIndex } from "@itwin/core-common"; import { CheckpointManager, V1CheckpointManager, V2CheckpointManager } from "../../CheckpointManager"; +import { HubMock } from "../../HubMock"; import { IModelDb, SnapshotDb } from "../../IModelDb"; -import { Logger } from "@itwin/core-bentley"; import { IModelHost } from "../../IModelHost"; -import { HubMock } from "../../HubMock"; import { _nativeDb } from "../../internal/Symbols"; describe("SnapshotDb.refreshContainerForRpc", () => { @@ -40,10 +40,10 @@ describe("SnapshotDb.refreshContainerForRpc", () => { getIModelId: () => iModelId, getITwinId: () => iTwinId, getCurrentChangeset: () => changeset, - setIModelDb: () => { }, - closeIModel: () => { }, - restartDefaultTxn: () => { }, - closeFile: () => { }, + setIModelDb: () => {}, + closeIModel: () => {}, + restartDefaultTxn: () => {}, + closeFile: () => {}, getFilePath: () => "fakeFilePath", }; @@ -63,7 +63,13 @@ describe("SnapshotDb.refreshContainerForRpc", () => { sinon.stub(CheckpointManager, "validateCheckpointGuids").returns(); const userAccessToken = "token"; - const checkpoint = await SnapshotDb.openCheckpointFromRpc({ accessToken: userAccessToken, iTwinId, iModelId, changeset, reattachSafetySeconds: 60 }); + const checkpoint = await SnapshotDb.openCheckpointFromRpc({ + accessToken: userAccessToken, + iTwinId, + iModelId, + changeset, + reattachSafetySeconds: 60, + }); expect(openDgnDbStub.calledOnce).to.be.true; expect(openDgnDbStub.firstCall.firstArg.path).to.equal("fakeDb"); @@ -111,13 +117,19 @@ describe("SnapshotDb.refreshContainerForRpc", () => { sinon.stub(CheckpointManager, "validateCheckpointGuids").returns(); const userAccessToken = "token"; - const checkpoint = await SnapshotDb.openCheckpointFromRpc({ accessToken: userAccessToken, iTwinId, iModelId, changeset, reattachSafetySeconds: 60 }); + const checkpoint = await SnapshotDb.openCheckpointFromRpc({ + accessToken: userAccessToken, + iTwinId, + iModelId, + changeset, + reattachSafetySeconds: 60, + }); expect(checkpoint[_nativeDb].cloudContainer?.accessToken).equal(mockCheckpointV2.sasToken); expect(openDgnDbStub.calledOnce).to.be.true; expect(openDgnDbStub.firstCall.firstArg.path).to.equal("fakeDb"); - const errorLogStub = sinon.stub(Logger, "logError").callsFake(() => { }); - const infoLogStub = sinon.stub(Logger, "logInfo").callsFake(() => { }); + const errorLogStub = sinon.stub(Logger, "logError").callsFake(() => {}); + const infoLogStub = sinon.stub(Logger, "logInfo").callsFake(() => {}); clock.setSystemTime(Date.parse("2021-01-01T00:58:10Z")); // within safety period void expect(checkpoint.refreshContainerForRpc("")).to.be.fulfilled; diff --git a/core/backend/src/test/standalone/Texture.test.ts b/core/backend/src/test/standalone/Texture.test.ts index 84f95f5c946c..7a6c3c4a0d6c 100644 --- a/core/backend/src/test/standalone/Texture.test.ts +++ b/core/backend/src/test/standalone/Texture.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64 } from "@itwin/core-bentley"; import { Base64EncodedString, ImageSourceFormat, IModel, TextureTransparency } from "@itwin/core-common"; +import { expect } from "chai"; import { SnapshotDb, Texture } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; @@ -12,7 +12,10 @@ describe("Texture", () => { let imodel: SnapshotDb; before(async () => { - imodel = IModelTestUtils.createSnapshotFromSeed(IModelTestUtils.prepareOutputFile("IModel", "CompatibilityTestSeed.bim"), IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim")); + imodel = IModelTestUtils.createSnapshotFromSeed( + IModelTestUtils.prepareOutputFile("IModel", "CompatibilityTestSeed.bim"), + IModelTestUtils.resolveAssetFile("CompatibilityTestSeed.bim"), + ); }); after(() => { @@ -23,11 +26,137 @@ describe("Texture", () => { // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. const pngData = [ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, - 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, - 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, - 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, - 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, ]; function test(name: string, base64Encode: boolean) { @@ -74,24 +203,611 @@ describe("Texture", () => { // opaque has alpha of 241 // translucent has alpha of 240 // transparent has alpha of 0 - type TestCase = [ TextureTransparency, number[] ]; + type TestCase = [TextureTransparency, number[]]; const testCases: TestCase[] = [ // Opaque - [ TextureTransparency.Opaque, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 240, 17, 0, 4, 242, 1, 241, 120, 128, 186, 37, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Opaque, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 31, + 21, + 196, + 137, + 0, + 0, + 0, + 13, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 240, + 17, + 0, + 4, + 242, + 1, + 241, + 120, + 128, + 186, + 37, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Translucent - [ TextureTransparency.Translucent, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 240, 1, 0, 4, 241, 1, 240, 14, 23, 54, 113, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Translucent, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 31, + 21, + 196, + 137, + 0, + 0, + 0, + 13, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 240, + 1, + 0, + 4, + 241, + 1, + 240, + 14, + 23, + 54, + 113, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Transparent - [ TextureTransparency.Translucent, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 13, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 192, 0, 0, 4, 1, 1, 0, 101, 81, 193, 74, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Translucent, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 31, + 21, + 196, + 137, + 0, + 0, + 0, + 13, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 192, + 0, + 0, + 4, + 1, + 1, + 0, + 101, + 81, + 193, + 74, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Opaque+translucent - [ TextureTransparency.Mixed, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 2, 0, 0, 0, 1, 8, 6, 0, 0, 0, 244, 34, 127, 138, 0, 0, 0, 17, 73, 68, 65, 84, 8, 153, 99, 252, 207, 192, 240, 145, 241, 63, 195, 127, 0, 16, 191, 3, 241, 136, 91, 64, 58, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Mixed, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 244, + 34, + 127, + 138, + 0, + 0, + 0, + 17, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 252, + 207, + 192, + 240, + 145, + 241, + 63, + 195, + 127, + 0, + 16, + 191, + 3, + 241, + 136, + 91, + 64, + 58, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Opaque+transparent - [ TextureTransparency.Mixed, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 2, 0, 0, 0, 1, 8, 6, 0, 0, 0, 244, 34, 127, 138, 0, 0, 0, 17, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 240, 145, 225, 63, 3, 3, 0, 15, 179, 2, 240, 226, 182, 96, 27, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Mixed, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 244, + 34, + 127, + 138, + 0, + 0, + 0, + 17, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 240, + 145, + 225, + 63, + 3, + 3, + 0, + 15, + 179, + 2, + 240, + 226, + 182, + 96, + 27, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Translucent+transparent - [ TextureTransparency.Translucent, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 2, 0, 0, 0, 1, 8, 6, 0, 0, 0, 244, 34, 127, 138, 0, 0, 0, 17, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 240, 129, 225, 63, 3, 3, 0, 15, 174, 2, 239, 92, 238, 220, 37, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Translucent, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 244, + 34, + 127, + 138, + 0, + 0, + 0, + 17, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 240, + 129, + 225, + 63, + 3, + 3, + 0, + 15, + 174, + 2, + 239, + 92, + 238, + 220, + 37, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // Opaque+translucent+transparent - [ TextureTransparency.Mixed, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 1, 8, 6, 0, 0, 0, 27, 224, 20, 180, 0, 0, 0, 21, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 240, 145, 225, 63, 195, 7, 6, 134, 255, 12, 0, 34, 33, 4, 223, 53, 29, 74, 186, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Mixed, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 1, + 8, + 6, + 0, + 0, + 0, + 27, + 224, + 20, + 180, + 0, + 0, + 0, + 21, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 240, + 145, + 225, + 63, + 195, + 7, + 6, + 134, + 255, + 12, + 0, + 34, + 33, + 4, + 223, + 53, + 29, + 74, + 186, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], // No alpha channel - [ TextureTransparency.Opaque, [ 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 2, 0, 0, 0, 144, 119, 83, 222, 0, 0, 0, 12, 73, 68, 65, 84, 8, 153, 99, 248, 207, 192, 0, 0, 3, 1, 1, 0, 156, 227, 191, 89, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130 ] ], + [TextureTransparency.Opaque, [ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 8, + 2, + 0, + 0, + 0, + 144, + 119, + 83, + 222, + 0, + 0, + 0, + 12, + 73, + 68, + 65, + 84, + 8, + 153, + 99, + 248, + 207, + 192, + 0, + 0, + 3, + 1, + 1, + 0, + 156, + 227, + 191, + 89, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]], ]; for (const test of testCases) { diff --git a/core/backend/src/test/standalone/TileCache.test.ts b/core/backend/src/test/standalone/TileCache.test.ts index 1ac3ccb7c8c1..8e4544158ab2 100644 --- a/core/backend/src/test/standalone/TileCache.test.ts +++ b/core/backend/src/test/standalone/TileCache.test.ts @@ -2,21 +2,28 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as path from "path"; -import * as sinon from "sinon"; import { Guid, Logger } from "@itwin/core-bentley"; import { - BatchType, ContentIdProvider, defaultTileOptions, IModelTileRpcInterface, iModelTileTreeIdToString, RpcActivity, RpcManager, RpcRegistry, + BatchType, + ContentIdProvider, + defaultTileOptions, + IModelTileRpcInterface, + iModelTileTreeIdToString, + RpcActivity, + RpcManager, + RpcRegistry, } from "@itwin/core-common"; +import { expect } from "chai"; +import * as path from "path"; +import * as sinon from "sinon"; import { IModelDb, SnapshotDb } from "../../IModelDb"; import { IModelHost } from "../../IModelHost"; import { IModelJsFs } from "../../IModelJsFs"; +import { _nativeDb } from "../../internal/Symbols"; import { GeometricModel3d } from "../../Model"; import { RpcTrace } from "../../rpc/tracing"; -import { TestUtils } from "../TestUtils"; import { IModelTestUtils } from "../IModelTestUtils"; -import { _nativeDb } from "../../internal/Symbols"; +import { TestUtils } from "../TestUtils"; const fakeRpc: RpcActivity = { // eslint-disable-line deprecation/deprecation accessToken: "dummy", @@ -82,7 +89,10 @@ describe("TileCache open v1", () => { // Generate tile const tileProps = await getTileProps(iModel); expect(tileProps); - await RpcTrace.run(fakeRpc, async () => tileRpcInterface.generateTileContent(iModel.getRpcProps(), tileProps!.treeId, tileProps!.contentId, tileProps!.guid)); // eslint-disable-line deprecation/deprecation + await RpcTrace.run( + fakeRpc, + async () => tileRpcInterface.generateTileContent(iModel.getRpcProps(), tileProps!.treeId, tileProps!.contentId, tileProps!.guid), + ); // eslint-disable-line deprecation/deprecation const tilesCache = `${iModel.pathName}.Tiles`; expect(IModelJsFs.existsSync(tilesCache)).true; @@ -98,7 +108,6 @@ describe("TileCache open v1", () => { const snapshot = IModelTestUtils.createSnapshotFromSeed(dbPath, IModelTestUtils.resolveAssetFile("mirukuru.ibim")); snapshot.close(); await verifyTileCache(dbPath); - }); it("should create .tiles file next to .bim with set cacheDir", async () => { // Shutdown IModelHost to allow this test to use it. @@ -154,4 +163,3 @@ describe("TileCache, open v2", async () => { checkpoint.close(); }); }); - diff --git a/core/backend/src/test/standalone/TileTree.test.ts b/core/backend/src/test/standalone/TileTree.test.ts index 186cd4a30fbd..b12b9847414b 100644 --- a/core/backend/src/test/standalone/TileTree.test.ts +++ b/core/backend/src/test/standalone/TileTree.test.ts @@ -3,15 +3,30 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, Id64, Id64String } from "@itwin/core-bentley"; -import { Box, Point3d, Range3d, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; import { - BatchType, Code, ColorDef, defaultTileOptions, GeometryStreamBuilder, IModel, iModelTileTreeIdToString, PhysicalElementProps, - PrimaryTileTreeId, RenderSchedule, + BatchType, + Code, + ColorDef, + defaultTileOptions, + GeometryStreamBuilder, + IModel, + iModelTileTreeIdToString, + PhysicalElementProps, + PrimaryTileTreeId, + RenderSchedule, } from "@itwin/core-common"; +import { Box, Point3d, Range3d, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { expect } from "chai"; import { - _nativeDb, GenericSchema, IModelDb, PhysicalModel, PhysicalObject, PhysicalPartition, RenderTimeline, SnapshotDb, + _nativeDb, + GenericSchema, + IModelDb, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + RenderTimeline, + SnapshotDb, SpatialCategory, SubjectOwnsPartitionElements, } from "../../core-backend"; diff --git a/core/backend/src/test/standalone/TxnManager.test.ts b/core/backend/src/test/standalone/TxnManager.test.ts index ccc26a719748..c26ac17e299a 100644 --- a/core/backend/src/test/standalone/TxnManager.test.ts +++ b/core/backend/src/test/standalone/TxnManager.test.ts @@ -3,20 +3,36 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { BeDuration, BeEvent, Guid, Id64, IModelStatus, OpenMode } from "@itwin/core-bentley"; -import { LineSegment3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; import { - Code, ColorByName, DomainOptions, EntityIdAndClassId, EntityIdAndClassIdIterable, GeometryStreamBuilder, IModel, IModelError, SubCategoryAppearance, TxnAction, UpgradeOptions, + Code, + ColorByName, + DomainOptions, + EntityIdAndClassId, + EntityIdAndClassIdIterable, + GeometryStreamBuilder, + IModel, + IModelError, + SubCategoryAppearance, + TxnAction, + UpgradeOptions, } from "@itwin/core-common"; +import { LineSegment3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { _nativeDb, ChangeInstanceKey, ChannelControl, - IModelJsFs, PhysicalModel, setMaxEntitiesPerEvent, SpatialCategory, StandaloneDb, TxnChangedEntities, TxnManager, + IModelJsFs, + PhysicalModel, + setMaxEntitiesPerEvent, + SpatialCategory, + StandaloneDb, + TxnChangedEntities, + TxnManager, } from "../../core-backend"; -import { IModelTestUtils, TestElementDrivesElement, TestPhysicalObject, TestPhysicalObjectProps } from "../IModelTestUtils"; import { IModelNative } from "../../internal/NativePlatform"; +import { IModelTestUtils, TestElementDrivesElement, TestPhysicalObject, TestPhysicalObjectProps } from "../IModelTestUtils"; /// cspell:ignore accum @@ -158,7 +174,7 @@ describe("TxnManager", () => { let element = elements.getElement(elementId); assert.equal(element.intProperty, 100, "int property should be 100"); - assert.isTrue(txns.isUndoPossible); // we have an undoable Txn, but nothing undone. + assert.isTrue(txns.isUndoPossible); // we have an undoable Txn, but nothing undone. assert.equal(change1Msg, txns.getUndoString()); assert.equal(IModelStatus.Success, txns.reverseSingleTxn()); diff --git a/core/backend/src/test/standalone/ViewDefinition.test.ts b/core/backend/src/test/standalone/ViewDefinition.test.ts index e2a3ac50f27e..1a0ee8e1069c 100644 --- a/core/backend/src/test/standalone/ViewDefinition.test.ts +++ b/core/backend/src/test/standalone/ViewDefinition.test.ts @@ -3,23 +3,42 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { join } from "path"; import { CompressedId64Set, Guid, GuidString, Id64, Id64String, OpenMode } from "@itwin/core-bentley"; import { - Camera, Code, ColorByName, ColorDef, DisplayStyle3dProps, ElementProps, IModel, IModelError, PlanProjectionSettings, SpatialViewDefinitionProps, + Camera, + Code, + ColorByName, + ColorDef, + DisplayStyle3dProps, + ElementProps, + IModel, + IModelError, + PlanProjectionSettings, + SpatialViewDefinitionProps, SubCategoryAppearance, } from "@itwin/core-common"; import { Matrix3d, Range3d, StandardViewIndex, Transform, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import { join } from "path"; import { - CategorySelector, DictionaryModel, DisplayStyle3d, IModelDb, ModelSelector, SpatialCategory, SpatialViewDefinition, StandaloneDb, ViewStore, + CategorySelector, + DictionaryModel, + DisplayStyle3d, + IModelDb, + ModelSelector, + SpatialCategory, + SpatialViewDefinition, + StandaloneDb, + ViewStore, } from "../../core-backend"; import { IModelTestUtils } from "../IModelTestUtils"; import { KnownTestLocations } from "../KnownTestLocations"; function createNewModelAndCategory(rwIModel: IModelDb) { - const modelId = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"))[1]; - const modelId2 = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "PhysicalModel2"), true)[1]; + const modelId = + IModelTestUtils.createAndInsertPhysicalPartitionAndModel(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"))[1]; + const modelId2 = + IModelTestUtils.createAndInsertPhysicalPartitionAndModel(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "PhysicalModel2"), true)[1]; const dictionary: DictionaryModel = rwIModel.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "TestSpatialCategory"); const category = SpatialCategory.create(rwIModel, IModel.dictionaryId, newCategoryCode.value); @@ -129,20 +148,115 @@ describe("ViewDefinition", () => { expect(cs1out.categories.length).equal(2); expect(cs1out.categories[1]).equal("0x1234"); - const longElementList = CompressedId64Set.sortAndCompress(["0x2a", "0x2b", "0x2d", "0x2e", "0x43", "0x1a", "0x1d", "0x12", "0x22", - "0x8", "0x21", "0x1b", "0x1c", "0x1e", "0x1f", "0x2c", "0x2f", "0x3a", "0x3b", "0x3d", "0x3e", "0x43", - "0x4a", "0x4b", "0x4d", "0x4e", "0x5a", "0x5b", "0x5d", "0x5e", "0x6a", "0x6b", "0x6d", "0x6e", "0x7a", - "0x7b", "0x7d", "0x7e", "0x8a", "0x8b", "0x8d", "0x8e", "0x9a", "0x9b", "0x9d", "0x9e", "0xaa", "0xab", "0xad", - "0xae", "0xba", "0xbb", "0xbd", "0xbe", "0xf5ca", "0xcb", "0xcd", "0xce", "0xda", "0xdb", "0xdd", "0xde", "0xea", - "0xeb", "0xed", "0xee", "0xfa", "0xfb", "0xfd", "0xfe", "0x10a", "0x10b", "0x10d", "0x10e", "0x11a", "0x11b", "0x11d", - "0x11e", "0x12a", "0x12b", "0x12d", "0x12e", "0x13a", "0x13b", "0x13d", "0x13e", "0x14a", "0x14b", "0x14d", "0x14e", - "0x15a", "0x15b", "0x15d", "0x15e", "0x16a", "0x16b", "0x16d"]); - - await expect(vs1.addCategorySelector({ selector: { query: { from: "BisCore:SubCategory" } } })).to.be.rejectedWith("must select from BisCore:Category"); - const cs2 = (await vs1.addCategorySelector({ selector: { query: { from: "BisCore:Category" } } })); + const longElementList = CompressedId64Set.sortAndCompress([ + "0x2a", + "0x2b", + "0x2d", + "0x2e", + "0x43", + "0x1a", + "0x1d", + "0x12", + "0x22", + "0x8", + "0x21", + "0x1b", + "0x1c", + "0x1e", + "0x1f", + "0x2c", + "0x2f", + "0x3a", + "0x3b", + "0x3d", + "0x3e", + "0x43", + "0x4a", + "0x4b", + "0x4d", + "0x4e", + "0x5a", + "0x5b", + "0x5d", + "0x5e", + "0x6a", + "0x6b", + "0x6d", + "0x6e", + "0x7a", + "0x7b", + "0x7d", + "0x7e", + "0x8a", + "0x8b", + "0x8d", + "0x8e", + "0x9a", + "0x9b", + "0x9d", + "0x9e", + "0xaa", + "0xab", + "0xad", + "0xae", + "0xba", + "0xbb", + "0xbd", + "0xbe", + "0xf5ca", + "0xcb", + "0xcd", + "0xce", + "0xda", + "0xdb", + "0xdd", + "0xde", + "0xea", + "0xeb", + "0xed", + "0xee", + "0xfa", + "0xfb", + "0xfd", + "0xfe", + "0x10a", + "0x10b", + "0x10d", + "0x10e", + "0x11a", + "0x11b", + "0x11d", + "0x11e", + "0x12a", + "0x12b", + "0x12d", + "0x12e", + "0x13a", + "0x13b", + "0x13d", + "0x13e", + "0x14a", + "0x14b", + "0x14d", + "0x14e", + "0x15a", + "0x15b", + "0x15d", + "0x15e", + "0x16a", + "0x16b", + "0x16d", + ]); + + await expect(vs1.addCategorySelector({ selector: { query: { from: "BisCore:SubCategory" } } })).to.be.rejectedWith( + "must select from BisCore:Category", + ); + const cs2 = await vs1.addCategorySelector({ selector: { query: { from: "BisCore:Category" } } }); expect(cs2).equal("@2"); - const cs3 = (await vs1.addCategorySelector({ selector: { query: { from: "BisCore:Category", adds: longElementList } } })); - const cs4 = (await vs1.addCategorySelector({ selector: { query: { from: "BisCore:Category", removes: ["0x233", "0x21"], adds: longElementList } } })); + const cs3 = await vs1.addCategorySelector({ selector: { query: { from: "BisCore:Category", adds: longElementList } } }); + const cs4 = await vs1.addCategorySelector({ + selector: { query: { from: "BisCore:Category", removes: ["0x233", "0x21"], adds: longElementList } }, + }); const onlyUsedProps = { name: "only used spatial categories", selector: { @@ -163,7 +277,7 @@ describe("ViewDefinition", () => { expect(selected.categories.length).equal(1); expect(selected.categories[0]).equal(spatialCategoryId); - const ms3 = (await vs1.addModelSelector({ name: "model selector 2", selector: { query: { from: "Bis.GeometricModel3d" } } })); + const ms3 = await vs1.addModelSelector({ name: "model selector 2", selector: { query: { from: "Bis.GeometricModel3d" } } }); let selectedModels = vs1.getModelSelectorSync({ id: ms3 }); expect(selectedModels.models.length).equal(2); const ms4Props = { @@ -186,16 +300,14 @@ describe("ViewDefinition", () => { ds1.settings.setPlanProjectionSettings("0x2", new PlanProjectionSettings({ elevation: 2 })); const styles = (ds1.toJSON() as DisplayStyle3dProps).jsonProperties!.styles!; - styles.subCategoryOvr = - [{ - subCategory: spatialCategoryId, - color: ColorByName.fuchsia, - invisible: true, - style: "0xaaa", - weight: 10, - transp: 0.5, - }, - ]; + styles.subCategoryOvr = [{ + subCategory: spatialCategoryId, + color: ColorByName.fuchsia, + invisible: true, + style: "0xaaa", + weight: 10, + transp: 0.5, + }]; styles.excludedElements = CompressedId64Set.sortAndCompress(["0x8", "0x12", "0x22"]); styles.scheduleScript = [{ @@ -215,7 +327,12 @@ describe("ViewDefinition", () => { const ds1out = vs1.getDisplayStyleSync({ id: ds1Row }); expect(ds1out.classFullName).equal("BisCore:DisplayStyle3d"); expect(ds1out.jsonProperties?.styles).deep.equal(JSON.parse(JSON.stringify(styles))); - ds1out.jsonProperties!.styles!.scheduleScript![0].elementTimelines[0].elementIds = CompressedId64Set.sortAndCompress(["0x11a", "0x11d", "0x11e", "0x12a"]); + ds1out.jsonProperties!.styles!.scheduleScript![0].elementTimelines[0].elementIds = CompressedId64Set.sortAndCompress([ + "0x11a", + "0x11d", + "0x11e", + "0x12a", + ]); await vs1.updateDisplayStyle({ id: ds1Row, className: ds1.classFullName, settings: ds1out.jsonProperties!.styles! }); const ds1out2 = vs1.getDisplayStyleSync({ id: ds1Row }); expect(ds1out2.jsonProperties?.styles).deep.equal(ds1out.jsonProperties!.styles!); @@ -295,14 +412,35 @@ describe("ViewDefinition", () => { expect(vs1.getModelSelectorRow(1)).not.undefined; // modelselector has a name so it should not be deleted // attempt to create a ViewDefinition element with invalid properties - assert.throws(() => iModel.elements.createElement({ ...basicProps, modelSelectorId, categorySelectorId } as ElementProps), IModelError, "displayStyleId is invalid"); - assert.throws(() => iModel.elements.createElement({ ...basicProps, categorySelectorId, displayStyleId } as ElementProps), IModelError, "modelSelectorId is invalid"); - assert.throws(() => iModel.elements.createElement({ ...basicProps, modelSelectorId, displayStyleId } as ElementProps), IModelError, "categorySelectorId is invalid"); + assert.throws( + () => iModel.elements.createElement({ ...basicProps, modelSelectorId, categorySelectorId } as ElementProps), + IModelError, + "displayStyleId is invalid", + ); + assert.throws( + () => iModel.elements.createElement({ ...basicProps, categorySelectorId, displayStyleId } as ElementProps), + IModelError, + "modelSelectorId is invalid", + ); + assert.throws( + () => iModel.elements.createElement({ ...basicProps, modelSelectorId, displayStyleId } as ElementProps), + IModelError, + "categorySelectorId is invalid", + ); // attempt to insert a ViewDefinition with invalid properties - assert.throws(() => iModel.elements.insertElement({ ...basicProps, modelSelectorId, categorySelectorId, displayStyleId: modelId } as ElementProps), "invalid displayStyle"); - assert.throws(() => iModel.elements.insertElement({ ...basicProps, modelSelectorId: modelId, displayStyleId, categorySelectorId } as ElementProps), "invalid modelSelector"); - assert.throws(() => iModel.elements.insertElement({ ...basicProps, modelSelectorId, categorySelectorId: modelId, displayStyleId } as ElementProps), "invalid categorySelector"); + assert.throws( + () => iModel.elements.insertElement({ ...basicProps, modelSelectorId, categorySelectorId, displayStyleId: modelId } as ElementProps), + "invalid displayStyle", + ); + assert.throws( + () => iModel.elements.insertElement({ ...basicProps, modelSelectorId: modelId, displayStyleId, categorySelectorId } as ElementProps), + "invalid modelSelector", + ); + assert.throws( + () => iModel.elements.insertElement({ ...basicProps, modelSelectorId, categorySelectorId: modelId, displayStyleId } as ElementProps), + "invalid categorySelector", + ); // Better way to create and insert const props: SpatialViewDefinitionProps = { ...basicProps, modelSelectorId, categorySelectorId, displayStyleId }; @@ -312,6 +450,14 @@ describe("ViewDefinition", () => { assert.isTrue(Id64.isValid(viewDefinitionId)); // Best way to create and insert - SpatialViewDefinition.insertWithCamera(iModel, IModel.dictionaryId, "default", modelSelectorId, categorySelectorId, displayStyleId, iModel.projectExtents); + SpatialViewDefinition.insertWithCamera( + iModel, + IModel.dictionaryId, + "default", + modelSelectorId, + categorySelectorId, + displayStyleId, + iModel.projectExtents, + ); }); }); diff --git a/core/backend/src/test/standalone/ViewStoreDb.test.ts b/core/backend/src/test/standalone/ViewStoreDb.test.ts index 182014ec8b9d..4c242c6fecc4 100644 --- a/core/backend/src/test/standalone/ViewStoreDb.test.ts +++ b/core/backend/src/test/standalone/ViewStoreDb.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Guid, GuidString, Logger, LogLevel, OpenMode } from "@itwin/core-bentley"; +import { ThumbnailFormatProps } from "@itwin/core-common"; import { expect } from "chai"; import { Suite } from "mocha"; import { join } from "path"; -import { Guid, GuidString, Logger, LogLevel, OpenMode } from "@itwin/core-bentley"; import { ViewStore } from "../../ViewStore"; -import { ThumbnailFormatProps } from "@itwin/core-common"; import { KnownTestLocations } from "../KnownTestLocations"; -describe("ViewStore", function (this: Suite) { +describe("ViewStore", function(this: Suite) { this.timeout(0); let vs1: ViewStore.ViewDb; @@ -34,7 +34,16 @@ describe("ViewStore", function (this: Suite) { const ds1 = vs1.addDisplayStyleRow({ name: "first style", json: "style1-json" }); expect(vs1.getViewByNameSync({ name: "view1" })).to.be.undefined; - const v1Id = vs1.addViewRow({ className: "spatial", name: "view1", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 }); + const v1Id = vs1.addViewRow({ + className: "spatial", + name: "view1", + json: "json1", + owner: "owner10", + isPrivate: true, + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); expect(v1Id).equals(1); const v1 = vs1.getViewByNameSync({ name: "view1" })!; @@ -49,7 +58,15 @@ describe("ViewStore", function (this: Suite) { const v1Updated = vs1.getViewByNameSync({ name: "view1" })!; expect(v1Updated.isPrivate).to.be.false; - const v1Id2 = vs1.addViewRow({ className: "spatial", name: "v2", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 }); + const v1Id2 = vs1.addViewRow({ + className: "spatial", + name: "v2", + json: "json-v2", + owner: "owner1", + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); expect(v1Id2).equals(2); const v2 = vs1.getViewRow(v1Id2)!; expect(v2.name).equals("v2"); @@ -62,8 +79,12 @@ describe("ViewStore", function (this: Suite) { expect(() => vs1.addViewGroupRow({ name: "bad/name", json: "" })).to.throw("illegal group"); expect(() => vs1.addViewGroupRow({ name: "^fd", json: "" })).to.throw("illegal group"); expect(() => vs1.addViewGroupRow({ name: "sd#fd", json: "" })).to.throw("illegal group"); - expect(() => vs1.addViewRow({ className: "spatial", name: "@bad", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 })).to.throw("illegal view"); - expect(() => vs1.addViewRow({ className: "spatial", name: "bad/name", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 })).to.throw("illegal view"); + expect(() => + vs1.addViewRow({ className: "spatial", name: "@bad", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 }) + ).to.throw("illegal view"); + expect(() => + vs1.addViewRow({ className: "spatial", name: "bad/name", json: "json-v2", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 }) + ).to.throw("illegal view"); const g1 = vs1.addViewGroupRow({ name: "group1", json: "group1-json" }); const g2 = vs1.addViewGroupRow({ name: "group2", json: "group2-json" }); @@ -73,13 +94,47 @@ describe("ViewStore", function (this: Suite) { expect(v2Id).equals(3); for (let i = 0; i < 100; i++) - vs1.addViewRow({ className: "spatial", name: `test view ${i}`, json: `json${i}`, owner: "owner1", groupId: g2, categorySel: c1, displayStyle: ds1 }); + vs1.addViewRow({ + className: "spatial", + name: `test view ${i}`, + json: `json${i}`, + owner: "owner1", + groupId: g2, + categorySel: c1, + displayStyle: ds1, + }); // duplicate name in a group should throw - expect(() => vs1.addViewRow({ className: "spatial3", name: "test view 0", json: "json-blah", owner: "owner1", groupId: g2, categorySel: c1, displayStyle: ds1 })).to.throw("UNIQUE"); + expect(() => + vs1.addViewRow({ + className: "spatial3", + name: "test view 0", + json: "json-blah", + owner: "owner1", + groupId: g2, + categorySel: c1, + displayStyle: ds1, + }) + ).to.throw("UNIQUE"); // allow the same name in different groups - const v103 = vs1.addViewRow({ className: "spatial3", name: "test view 0", json: "json-blah", owner: "owner1", groupId: 1, categorySel: c1, displayStyle: ds1 }); - const v104 = vs1.addViewRow({ className: "spatial3", name: "another view", json: "json-blah", owner: "owner10", groupId: 1, categorySel: c1, displayStyle: ds1 }); + const v103 = vs1.addViewRow({ + className: "spatial3", + name: "test view 0", + json: "json-blah", + owner: "owner1", + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); + const v104 = vs1.addViewRow({ + className: "spatial3", + name: "another view", + json: "json-blah", + owner: "owner10", + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); const g3Id = vs1.getViewGroupByName("group 3", g2); @@ -147,7 +202,7 @@ describe("ViewStore", function (this: Suite) { let cat1 = vs1.getCategorySelectorRow(cat1Id)!; expect(cat1.name).equals("cat1"); expect(cat1.json).equals("cat1-json"); - await vs1.updateCategorySelectorJson(cat1Id, "cat1-json-updated");// eslint-disable-line @typescript-eslint/await-thenable + await vs1.updateCategorySelectorJson(cat1Id, "cat1-json-updated"); // eslint-disable-line @typescript-eslint/await-thenable cat1 = vs1.getCategorySelectorRow(cat1Id)!; expect(cat1.json).equals("cat1-json-updated"); @@ -242,10 +297,46 @@ describe("ViewStore", function (this: Suite) { expect(tags[1]).equals("tag2"); expect(tags[2]).equals("test tag 0"); - vs1.addViewRow({ className: "BisCore:SpatialViewDefinition", name: "my private 2", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 }); - vs1.addViewRow({ className: "BisCore:OrthographicViewDefinition", name: "my private 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 }); - vs1.addViewRow({ className: "BisCore:SheetViewDefinition", name: "sheet 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 }); - vs1.addViewRow({ className: "BisCore:DrawingViewDefinition", name: "drawing 3", json: "json1", owner: "owner10", isPrivate: true, groupId: 1, categorySel: c1, displayStyle: ds1 }); + vs1.addViewRow({ + className: "BisCore:SpatialViewDefinition", + name: "my private 2", + json: "json1", + owner: "owner10", + isPrivate: true, + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); + vs1.addViewRow({ + className: "BisCore:OrthographicViewDefinition", + name: "my private 3", + json: "json1", + owner: "owner10", + isPrivate: true, + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); + vs1.addViewRow({ + className: "BisCore:SheetViewDefinition", + name: "sheet 3", + json: "json1", + owner: "owner10", + isPrivate: true, + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); + vs1.addViewRow({ + className: "BisCore:DrawingViewDefinition", + name: "drawing 3", + json: "json1", + owner: "owner10", + isPrivate: true, + groupId: 1, + categorySel: c1, + displayStyle: ds1, + }); let views = vs1.queryViewsSync({ group: "/" }); expect(views.length).equals(3); @@ -269,7 +360,8 @@ describe("ViewStore", function (this: Suite) { views = vs1.queryViewsSync({ owner: "owner10", nameSearch: "my%", nameCompare: "LIKE" }); expect(views.length).equal(2); expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:SpatialViewDefinition"] }).length).equal(1); - expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:SpatialViewDefinition", "BisCore:OrthographicViewDefinition"] }).length).equal(2); + expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:SpatialViewDefinition", "BisCore:OrthographicViewDefinition"] }).length) + .equal(2); expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:DrawingViewDefinition"] }).length).equal(1); expect(vs1.queryViewsSync({ owner: "owner10", classNames: ["BisCore:DrawingViewDefinition", "BisCore:SheetViewDefinition"] }).length).equal(2); diff --git a/core/backend/src/test/standalone/Workspace.test.ts b/core/backend/src/test/standalone/Workspace.test.ts index 2d3b52cf3d13..1637ddeaed55 100644 --- a/core/backend/src/test/standalone/Workspace.test.ts +++ b/core/backend/src/test/standalone/Workspace.test.ts @@ -3,21 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Guid } from "@itwin/core-bentley"; +import { Range3d } from "@itwin/core-geometry"; import { expect } from "chai"; import * as fs from "fs-extra"; import { extname } from "path"; import * as sinon from "sinon"; -import { Guid } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; +import { _nativeDb } from "../../internal/Symbols"; +import { validateWorkspaceContainerId, validateWorkspaceDbName } from "../../internal/workspace/WorkspaceImpl"; import { SettingsPriority } from "../../workspace/Settings"; import { Workspace, WorkspaceContainerProps, WorkspaceDbManifest, WorkspaceDbProps } from "../../workspace/Workspace"; import { EditableWorkspaceDb, WorkspaceEditor } from "../../workspace/WorkspaceEditor"; import { IModelTestUtils } from "../IModelTestUtils"; -import { validateWorkspaceContainerId, validateWorkspaceDbName } from "../../internal/workspace/WorkspaceImpl"; -import { _nativeDb } from "../../internal/Symbols"; describe("WorkspaceFile", () => { - let editor: WorkspaceEditor; let workspace: Workspace; @@ -65,7 +64,8 @@ describe("WorkspaceFile", () => { "newline\n", "a".repeat(64), // too long "-leading-dash", - "trailing-dash-"]); + "trailing-dash-", + ]); validateWorkspaceContainerId(Guid.createValue()); // guids should be valid }); @@ -167,21 +167,34 @@ describe("WorkspaceFile", () => { it("load workspace settings", async () => { const settingsFile = IModelTestUtils.resolveAssetFile("test.setting.json5"); - const defaultDb = await makeEditableDb({ containerId: "default", dbName: "db1", baseUri: "", storageType: "azure" }, { workspaceName: "default resources", contactName: "contact 123" }); + const defaultDb = await makeEditableDb({ containerId: "default", dbName: "db1", baseUri: "", storageType: "azure" }, { + workspaceName: "default resources", + contactName: "contact 123", + }); defaultDb.addString("default-settings", fs.readFileSync(settingsFile, "utf-8")); defaultDb.close(); const settings = workspace.settings; await workspace.loadSettingsDictionary( - { dbName: "db1", containerId: "default", baseUri: "", storageType: "azure", resourceName: "default-settings", priority: SettingsPriority.defaults }); + { + dbName: "db1", + containerId: "default", + baseUri: "", + storageType: "azure", + resourceName: "default-settings", + priority: SettingsPriority.defaults, + }, + ); expect(settings.getSetting("editor/renderWhitespace")).equals("selection"); const workspaceName = "all fonts workspace"; const schemaFile = IModelTestUtils.resolveAssetFile("TestSettings.schema.json"); - const fontsDb = await makeEditableDb({ containerId: "fonts", dbName: "fonts", baseUri: "", storageType: "azure" }, { workspaceName, contactName: "font guy" }); + const fontsDb = await makeEditableDb({ containerId: "fonts", dbName: "fonts", baseUri: "", storageType: "azure" }, { + workspaceName, + contactName: "font guy", + }); fontsDb.addFile("Helvetica.ttf", schemaFile, "ttf"); fontsDb.close(); }); - }); diff --git a/core/backend/src/workspace/Settings.ts b/core/backend/src/workspace/Settings.ts index 360217c46b2b..97a597543f64 100644 --- a/core/backend/src/workspace/Settings.ts +++ b/core/backend/src/workspace/Settings.ts @@ -8,8 +8,8 @@ import { BeEvent, JSONSchemaType } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; -import { WorkspaceDb } from "./Workspace"; import { _implementationProhibited } from "../internal/Symbols"; +import { WorkspaceDb } from "./Workspace"; /** The value of a single named parameter within a [[Workspace.settings]] that configures some aspect of the applications run-time behavior. * Settings are stored in a [[SettingsDictionary]]. A setting is described by its [[SettingSchema]]. @@ -261,7 +261,7 @@ export interface Settings { getSetting(settingName: SettingName, defaultValue?: T): T | undefined; /** Obtain an iterator over all of the values in the [[dictionaries]] for the [[Setting]] identified by `settingName`, ordered by [[SettingsPriority]]. */ - getSettingEntries(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary}>; + getSettingEntries(settingName: SettingName): Iterable<{ value: T, dictionary: SettingsDictionary }>; /** Obtain an iterator over all of the values in the [[dictionaries]] for the [[Setting]] identified by `settingName`, ordered by [[SettingsPriority]]. */ getSettingValues(settingName: SettingName): Iterable; diff --git a/core/backend/src/workspace/SettingsSchemas.ts b/core/backend/src/workspace/SettingsSchemas.ts index b85a65e71990..c100cae80127 100644 --- a/core/backend/src/workspace/SettingsSchemas.ts +++ b/core/backend/src/workspace/SettingsSchemas.ts @@ -12,14 +12,14 @@ import { _implementationProhibited } from "../internal/Symbols"; import { SettingName } from "./Settings"; /** Metadata describing a single [[Setting]] as part of a [[SettingGroupSchema]]. - * Every setting has a [[type]], which can be one of the following: - * - A primitive type like `string` or `number`; - * - An object containing any number of named properties, each with their own types; or - * - An array of elements, all of the same type. - * This metadata is used to validate setting values against the schema, and to enable user interfaces by which - * users can view and modify their settings. - * @beta - */ + * Every setting has a [[type]], which can be one of the following: + * - A primitive type like `string` or `number`; + * - An object containing any number of named properties, each with their own types; or + * - An array of elements, all of the same type. + * This metadata is used to validate setting values against the schema, and to enable user interfaces by which + * users can view and modify their settings. + * @beta + */ export interface SettingSchema extends Readonly { /** For arrays only, the metadata describing every element in the array. */ readonly items?: SettingSchema; @@ -42,26 +42,26 @@ export interface SettingSchema extends Readonly { } /** Metadata describing a group of related [[SettingSchema]]s. You can register setting schema groups via [[SettingsSchemas.addGroup]] and - * remove them via [[SettingsSchemas.removeGroup]]. - * - * All of the settings share the same [[schemaPrefix]], which must be unique amongst all other groups. - * The prefix is combined with the name of each [[SettingSchema]] in the group to form the fully-qualified name used to refer - * to the setting outside of the group, e.g., when accessing [[SettingsSchemas.settingDefs]] or in [[SettingSchema.extends]]. - * In the following example, the fully-qualified name of the setting named "metric" is "format/units/metric". - * - * ```json - * { - * "schemaPrefix": "format/units", - * "settingDefs": { - * "metric": { "type": "boolean" } - * } - * } - * ``` - * - * A group can also define [[SettingSchema]]s that, rather than describing actual [[Setting]]s, instead describe types that can be extended by [[Setting]]s via - * [[SettingSchema.extends]]. A [[SettingSchema]] can refer to type definitions defined in its own group or any other group. - * @beta - */ + * remove them via [[SettingsSchemas.removeGroup]]. + * + * All of the settings share the same [[schemaPrefix]], which must be unique amongst all other groups. + * The prefix is combined with the name of each [[SettingSchema]] in the group to form the fully-qualified name used to refer + * to the setting outside of the group, e.g., when accessing [[SettingsSchemas.settingDefs]] or in [[SettingSchema.extends]]. + * In the following example, the fully-qualified name of the setting named "metric" is "format/units/metric". + * + * ```json + * { + * "schemaPrefix": "format/units", + * "settingDefs": { + * "metric": { "type": "boolean" } + * } + * } + * ``` + * + * A group can also define [[SettingSchema]]s that, rather than describing actual [[Setting]]s, instead describe types that can be extended by [[Setting]]s via + * [[SettingSchema.extends]]. A [[SettingSchema]] can refer to type definitions defined in its own group or any other group. + * @beta + */ export interface SettingGroupSchema { /** Uniquely identifies this group amongst all other groups. * The prefix can use forward-slashes to define logical subgroups - for example, two related groups with the prefixes "units/metric" and "units/imperial". @@ -87,20 +87,20 @@ export interface SettingGroupSchema { */ /** The registry of metadata describing groups of [[SettingSchema]]s available to the current session. - * The schemas are used to look up the default values of [[Setting]]s, validate that their values are of the type dictated by the schema, and - * query metadata like [[SettingsSchema.combineArray]] that modify their behavior. - * They can also be used to drive a user interface that enables end users to edit [[Settings]]. - * - * When [[IModelHost.startup]] is invoked at the beginning of a session, schemas delivered with the application - like those describing - * [[Workspace]]s - are automatically loaded. - * The application can manually register additional schemas using methods like [[addGroup]], [[addFile]], [[addDirectory]], and [[addJson]]. - * When [[IModelHost.shutdown]] is invoked at the end of a session, all registered schemas are unregistered. - * - * See the [learning article]($docs/learning/backend/Workspace) for a detailed overiew and examples. - * - * @see [[IModelHost.settingsSchemas]] to access the registry for the current session. - * @beta - */ + * The schemas are used to look up the default values of [[Setting]]s, validate that their values are of the type dictated by the schema, and + * query metadata like [[SettingsSchema.combineArray]] that modify their behavior. + * They can also be used to drive a user interface that enables end users to edit [[Settings]]. + * + * When [[IModelHost.startup]] is invoked at the beginning of a session, schemas delivered with the application - like those describing + * [[Workspace]]s - are automatically loaded. + * The application can manually register additional schemas using methods like [[addGroup]], [[addFile]], [[addDirectory]], and [[addJson]]. + * When [[IModelHost.shutdown]] is invoked at the end of a session, all registered schemas are unregistered. + * + * See the [learning article]($docs/learning/backend/Workspace) for a detailed overiew and examples. + * + * @see [[IModelHost.settingsSchemas]] to access the registry for the current session. + * @beta + */ export interface SettingsSchemas { /** @internal */ readonly [_implementationProhibited]: unknown; diff --git a/core/backend/src/workspace/Workspace.ts b/core/backend/src/workspace/Workspace.ts index 9acfa19acaab..8178ae16333b 100644 --- a/core/backend/src/workspace/Workspace.ts +++ b/core/backend/src/workspace/Workspace.ts @@ -6,14 +6,14 @@ * @module Workspace */ +import type { IModelJsNative } from "@bentley/imodeljs-native"; import { AccessToken, BeEvent, Logger, Optional, UnexpectedErrors } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; +import { BackendLoggerCategory } from "../BackendLoggerCategory"; import { CloudSqlite } from "../CloudSqlite"; +import { _implementationProhibited } from "../internal/Symbols"; import { SQLiteDb } from "../SQLiteDb"; import { SettingName, Settings, SettingsDictionary, SettingsPriority } from "./Settings"; -import type { IModelJsNative } from "@bentley/imodeljs-native"; -import { BackendLoggerCategory } from "../BackendLoggerCategory"; -import { _implementationProhibited } from "../internal/Symbols"; /** The unique identifier of a [[WorkspaceContainer]]. This becomes the base name for a local file directory holding the container's [[WorkspaceDb]]s. * A valid `WorkspaceContainerId` must conform to the following constraints: @@ -120,11 +120,11 @@ export interface WorkspaceDbQueryResourcesArgs { } /** Metadata stored inside a [[WorkspaceDb]] describing the database's contents, to help users understand the purpose of the [[WorkspaceDb]], who to - * contact with questions about it, and so on. - * @note Only the [[workspaceName]] field is required, and users may add additional fields for their own purposes. - * @note Since the information is stored inside of the [[WorkspaceDb]], it is versioned along with the rest of the contents. - * @beta - */ + * contact with questions about it, and so on. + * @note Only the [[workspaceName]] field is required, and users may add additional fields for their own purposes. + * @note Since the information is stored inside of the [[WorkspaceDb]], it is versioned along with the rest of the contents. + * @beta + */ export interface WorkspaceDbManifest { /** The name of the [[WorkspaceDb]] to be shown in user interfaces. Organizations should attempt to make this name informative enough * so that uses may refer to this name in conversations. It should also be unique enough that there's no confusion when it appears in @@ -165,9 +165,9 @@ export interface WorkspaceDbLoadErrors extends Error { } /** Specifies a resource inside a [[WorkspaceDb]] that holds a [[SettingsDictionary]] to load into [[Workspace.settings]]. - * Settings of this type named [[WorkspaceSettingNames.settingsWorkspaces]] are automatically loaded by [[Workspace.loadSettingsDictionary]]. - * @beta - */ + * Settings of this type named [[WorkspaceSettingNames.settingsWorkspaces]] are automatically loaded by [[Workspace.loadSettingsDictionary]]. + * @beta + */ export interface WorkspaceDbSettingsProps extends WorkspaceDbCloudProps { /** The name of the resource holding the stringified JSON of the [[SettingsDictionary]]. */ resourceName: string; @@ -289,8 +289,8 @@ export interface WorkspaceDb { } /** Options supplied to [[IModelHost.startup]] via [[IModelHostOptions.workspace]] to customize the initialization of [[IModelHost.appWorkspace]]. - * @beta - */ + * @beta + */ export interface WorkspaceOpts { /** The local directory for non-cloud-based [[WorkspaceDb]] files. The [[Workspace]] API will look in this directory * for files named `${containerId}/${dbId}.itwin-workspace`. @@ -343,7 +343,7 @@ export interface Workspace { * @note This function allows a `WorkspaceContainer.Props` without its [AccessToken]($bentley). It will attempt to obtain one from the [[BlobContainer]] service, * hence this function is async. * @see [[getContainer]] to obtain a container synchronously. - */ + */ getContainerAsync(props: WorkspaceContainerProps): Promise; /** Get a WorkspaceContainer with a supplied access token. This function is synchronous and may be used if: @@ -363,7 +363,7 @@ export interface Workspace { /** The properties of the [[WorkspaceDb]], plus the resourceName and [[SettingsPriority]]. May be either a single value or an array of them */ props: WorkspaceDbSettingsProps | WorkspaceDbSettingsProps[], /** If present, an array that is populated with a list of problems while attempting to load the [[SettingsDictionary]](s). */ - problems?: WorkspaceDbLoadError[] + problems?: WorkspaceDbLoadError[], ): Promise; /** Get a single [[WorkspaceDb]]. */ @@ -382,7 +382,8 @@ export interface Workspace { /** the name of the setting. */ settingName: SettingName, /** optional filter to choose specific WorkspaceDbs from the settings values. If present, only those WorkspaceDbs for which the filter returns `true` will be included. */ - filter?: Workspace.DbListFilter): WorkspaceDbCloudProps[]; + filter?: Workspace.DbListFilter, + ): WorkspaceDbCloudProps[]; /** * Get a sorted array of [[WorkspaceDb]]s that can be used to query or load resources. If the arguments supply a `settingName`, this function will @@ -397,7 +398,8 @@ export interface Workspace { problems?: WorkspaceDbLoadError[]; /** only valid when called with a settingName, if so passed as `filter` argument to [[resolveWorkspaceDbSetting]] */ filter?: Workspace.DbListFilter; - }): Promise; + }, + ): Promise; } /** @@ -518,7 +520,7 @@ export namespace Workspace { * Applications can override this function to notify the user and/or attempt to diagnose the problem. * The default implementation simply logs each exception. */ - export let exceptionDiagnosticFn = (e: WorkspaceDbLoadErrors) => { // eslint-disable-line prefer-const + export let exceptionDiagnosticFn = (e: WorkspaceDbLoadErrors) => { // eslint-disable-line prefer-const if (e instanceof Error) Logger.logException(BackendLoggerCategory.Workspace, e); else @@ -537,14 +539,17 @@ export namespace Workspace { * Applications can override this function to notify the user and/or record diagnostics. * The default implementation simply records an information message in the [Logger]($bentley). */ - export let onSettingsDictionaryLoadedFn = (loaded: SettingsDictionaryLoaded) => { // eslint-disable-line prefer-const + export let onSettingsDictionaryLoadedFn = (loaded: SettingsDictionaryLoaded) => { // eslint-disable-line prefer-const Logger.logInfo(BackendLoggerCategory.Workspace, `loaded setting dictionary ${loaded.dict.props.name} from ${loaded.from.dbFileName}`); }; /** Either an array of [[WorkspaceDbCloudProps]] or the name of a [[Setting]] that resolves to an array of [[WorkspaceDbCloudProps]]. * Used by [[Workspace.getWorkspaceDbs]]. */ - export type DbListOrSettingName = { readonly dbs: WorkspaceDbCloudProps[], readonly settingName?: never } | { readonly settingName: SettingName, readonly dbs?: never }; + export type DbListOrSettingName = { readonly dbs: WorkspaceDbCloudProps[], readonly settingName?: never } | { + readonly settingName: SettingName; + readonly dbs?: never; + }; /** In arguments supplied to [[Workspace.getWorkspaceDbs]] and [[Workspace.resolveWorkspaceDbSetting]], an optional function used to exclude some * [[WorkspaceDb]]s. Only those [[WorkspaceDb]]s for which the function returns `true` will be included. @@ -555,7 +560,7 @@ export namespace Workspace { /** The SettingsDictionary holding the [[WorkspaceSettingNames.settingsWorkspace]] setting. May be used, for example, to determine the * [[SettingsPriority]] of the dictionary. */ - dict: SettingsDictionary + dict: SettingsDictionary, ) => boolean; /** Searches a list of [[WorkspaceDb]]s for a string resource of a given name. diff --git a/core/backend/src/workspace/WorkspaceEditor.ts b/core/backend/src/workspace/WorkspaceEditor.ts index 61c53781d2a5..61b4d9713b74 100644 --- a/core/backend/src/workspace/WorkspaceEditor.ts +++ b/core/backend/src/workspace/WorkspaceEditor.ts @@ -7,16 +7,26 @@ */ import { LocalFileName } from "@itwin/core-common"; +import { BlobContainer } from "../BlobContainerService"; +import { _implementationProhibited } from "../internal/Symbols"; +import { constructWorkspaceEditor } from "../internal/workspace/WorkspaceImpl"; +import { WorkspaceSqliteDb } from "../internal/workspace/WorkspaceSqliteDb"; import { SQLiteDb } from "../SQLiteDb"; import { SettingsContainer } from "./Settings"; -import { BlobContainer } from "../BlobContainerService"; import { - GetWorkspaceContainerArgs, Workspace, WorkspaceContainer, WorkspaceContainerProps, WorkspaceDb, WorkspaceDbCloudProps, WorkspaceDbManifest, WorkspaceDbName, WorkspaceDbNameAndVersion, - WorkspaceDbProps, WorkspaceDbVersion, WorkspaceResourceName, + GetWorkspaceContainerArgs, + Workspace, + WorkspaceContainer, + WorkspaceContainerProps, + WorkspaceDb, + WorkspaceDbCloudProps, + WorkspaceDbManifest, + WorkspaceDbName, + WorkspaceDbNameAndVersion, + WorkspaceDbProps, + WorkspaceDbVersion, + WorkspaceResourceName, } from "./Workspace"; -import { WorkspaceSqliteDb } from "../internal/workspace/WorkspaceSqliteDb"; -import { constructWorkspaceEditor } from "../internal/workspace/WorkspaceImpl"; -import { _implementationProhibited } from "../internal/Symbols"; /** @beta */ export namespace WorkspaceEditor { @@ -73,7 +83,9 @@ export interface EditableWorkspaceContainer extends WorkspaceContainer { * @param props - The properties that determine the source WorkspaceDb to serve as the basis for the new version. * @returns A promise that resolves to an object containing the old and new WorkspaceDb names and versions. */ - createNewWorkspaceDbVersion(props: CreateNewWorkspaceDbVersionArgs): Promise<{ oldDb: WorkspaceDbNameAndVersion, newDb: WorkspaceDbNameAndVersion }>; + createNewWorkspaceDbVersion( + props: CreateNewWorkspaceDbVersionArgs, + ): Promise<{ oldDb: WorkspaceDbNameAndVersion, newDb: WorkspaceDbNameAndVersion }>; /** * Create a new, empty [[WorkspaceDb]]. diff --git a/core/backend/tsconfig.json b/core/backend/tsconfig.json index f416c78a6163..ea61c0d4f558 100644 --- a/core/backend/tsconfig.json +++ b/core/backend/tsconfig.json @@ -3,4 +3,4 @@ "include": [ "./src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/core/bentley/eslint.config.js b/core/bentley/eslint.config.js index 628f1d4b27a0..849e7479dee5 100644 --- a/core/bentley/eslint.config.js +++ b/core/bentley/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/bentley/src/AccessToken.ts b/core/bentley/src/AccessToken.ts index 4ce28b43bb11..cdf994e994d0 100644 --- a/core/bentley/src/AccessToken.ts +++ b/core/bentley/src/AccessToken.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. diff --git a/core/bentley/src/BeEvent.ts b/core/bentley/src/BeEvent.ts index b6815744e60f..aab9efb52417 100644 --- a/core/bentley/src/BeEvent.ts +++ b/core/bentley/src/BeEvent.ts @@ -30,7 +30,9 @@ export class BeEvent { private _insideRaiseEvent: boolean = false; /** The number of listeners currently subscribed to the event. */ - public get numberOfListeners() { return this._listeners.length; } + public get numberOfListeners() { + return this._listeners.length; + } /** * Registers a Listener to be executed whenever this event is raised. @@ -130,7 +132,9 @@ export class BeEvent { } /** Clear all Listeners from this BeEvent. */ - public clear(): void { this._listeners.length = 0; } + public clear(): void { + this._listeners.length = 0; + } } /** Specialization of BeEvent for events that take a single strongly typed argument, primarily used for UI events. @@ -138,7 +142,9 @@ export class BeEvent { */ export class BeUiEvent extends BeEvent<(args: TEventArgs) => void> { /** Raises event with single strongly typed argument. */ - public emit(args: TEventArgs): void { this.raiseEvent(args); } + public emit(args: TEventArgs): void { + this.raiseEvent(args); + } } /** @@ -184,9 +190,11 @@ export class BeEventList { * * @public */ -export type ListenerType void; -}> = +export type ListenerType< TEvent extends { - addListener(listener: infer TListener): () => void; - } ? TListener : never; + addListener(listener: Listener): () => void; + }, +> = TEvent extends { + addListener(listener: infer TListener): () => void; +} ? TListener : + never; diff --git a/core/bentley/src/BentleyError.ts b/core/bentley/src/BentleyError.ts index 3c1b97df6343..7b0a24d005ff 100644 --- a/core/bentley/src/BentleyError.ts +++ b/core/bentley/src/BentleyError.ts @@ -341,7 +341,9 @@ export class BentleyError extends Error { } /** Returns true if this BentleyError includes (optional) metadata. */ - public get hasMetaData(): boolean { return undefined !== this._metaData; } + public get hasMetaData(): boolean { + return undefined !== this._metaData; + } /** get the meta data associated with this BentleyError, if any. */ public getMetaData(): object | undefined { @@ -356,275 +358,543 @@ export class BentleyError extends Error { /** This function returns the name of each error status. Override this method to handle more error status codes. */ protected _initName(): string { switch (this.errorNumber) { - case IModelStatus.AlreadyLoaded: return "Already Loaded"; - case IModelStatus.AlreadyOpen: return "Already Open"; - case IModelStatus.BadArg: return "Bad Arg"; - case IModelStatus.BadElement: return "Bad Element"; - case IModelStatus.BadModel: return "Bad Model"; - case IModelStatus.BadRequest: return "Bad Request"; - case IModelStatus.BadSchema: return "Bad Schema"; - case IModelStatus.CannotUndo: return "Can not Undo"; - case IModelStatus.CodeNotReserved: return "Code Not Reserved"; - case IModelStatus.DeletionProhibited: return "Deletion Prohibited"; - case IModelStatus.DuplicateCode: return "Duplicate Code"; - case IModelStatus.DuplicateName: return "Duplicate Name"; - case IModelStatus.ElementBlockedChange: return "Element Blocked Change"; - case IModelStatus.FileAlreadyExists: return "File Already Exists"; - case IModelStatus.FileNotFound: return "File Not Found"; - case IModelStatus.FileNotLoaded: return "File Not Loaded"; - case IModelStatus.ForeignKeyConstraint: return "ForeignKey Constraint"; - case IModelStatus.IdExists: return "Id Exists"; - case IModelStatus.InDynamicTransaction: return "InDynamicTransaction"; - case IModelStatus.InvalidCategory: return "Invalid Category"; - case IModelStatus.InvalidCode: return "Invalid Code"; - case IModelStatus.InvalidCodeSpec: return "Invalid CodeSpec"; - case IModelStatus.InvalidId: return "Invalid Id"; - case IModelStatus.InvalidName: return "Invalid Name"; - case IModelStatus.InvalidParent: return "Invalid Parent"; - case IModelStatus.InvalidProfileVersion: return "Invalid Profile Version"; - case IModelStatus.IsCreatingChangeSet: return "IsCreatingChangeSet"; - case IModelStatus.LockNotHeld: return "Lock Not Held"; - case IModelStatus.Mismatch2d3d: return "Mismatch 2d3d"; - case IModelStatus.MismatchGcs: return "Mismatch Gcs"; - case IModelStatus.MissingDomain: return "Missing Domain"; - case IModelStatus.MissingHandler: return "Missing Handler"; - case IModelStatus.MissingId: return "Missing Id"; - case IModelStatus.NoGeometry: return "No Geometry"; - case IModelStatus.NoMultiTxnOperation: return "NoMultiTxnOperation"; - case IModelStatus.NotEnabled: return "Not Enabled"; - case IModelStatus.NotFound: return "Not Found"; - case IModelStatus.NotOpen: return "Not Open"; - case IModelStatus.NotOpenForWrite: return "Not Open For Write"; - case IModelStatus.NotSameUnitBase: return "Not Same Unit Base"; - case IModelStatus.NothingToRedo: return "Nothing To Redo"; - case IModelStatus.NothingToUndo: return "Nothing To Undo"; - case IModelStatus.ParentBlockedChange: return "Parent Blocked Change"; - case IModelStatus.ReadError: return "Read Error"; - case IModelStatus.ReadOnly: return "ReadOnly"; - case IModelStatus.ReadOnlyDomain: return "ReadOnlyDomain"; - case IModelStatus.RepositoryManagerError: return "RepositoryManagerError"; - case IModelStatus.SQLiteError: return "SQLiteError"; - case IModelStatus.TransactionActive: return "Transaction Active"; - case IModelStatus.UnitsMissing: return "Units Missing"; - case IModelStatus.UnknownFormat: return "Unknown Format"; - case IModelStatus.UpgradeFailed: return "Upgrade Failed"; - case IModelStatus.ValidationFailed: return "Validation Failed"; - case IModelStatus.VersionTooNew: return "Version Too New"; - case IModelStatus.VersionTooOld: return "Version Too Old"; - case IModelStatus.ViewNotFound: return "View Not Found"; - case IModelStatus.WriteError: return "Write Error"; - case IModelStatus.WrongClass: return "Wrong Class"; - case IModelStatus.WrongIModel: return "Wrong IModel"; - case IModelStatus.WrongDomain: return "Wrong Domain"; - case IModelStatus.WrongElement: return "Wrong Element"; - case IModelStatus.WrongHandler: return "Wrong Handler"; - case IModelStatus.WrongModel: return "Wrong Model"; - case DbResult.BE_SQLITE_ERROR: return "BE_SQLITE_ERROR"; - case DbResult.BE_SQLITE_INTERNAL: return "BE_SQLITE_INTERNAL"; - case DbResult.BE_SQLITE_PERM: return "BE_SQLITE_PERM"; - case DbResult.BE_SQLITE_ABORT: return "BE_SQLITE_ABORT"; - case DbResult.BE_SQLITE_BUSY: return "Db is busy"; - case DbResult.BE_SQLITE_LOCKED: return "Db is Locked"; - case DbResult.BE_SQLITE_NOMEM: return "BE_SQLITE_NOMEM"; - case DbResult.BE_SQLITE_READONLY: return "Readonly"; - case DbResult.BE_SQLITE_INTERRUPT: return "BE_SQLITE_INTERRUPT"; - case DbResult.BE_SQLITE_IOERR: return "BE_SQLITE_IOERR"; - case DbResult.BE_SQLITE_CORRUPT: return "BE_SQLITE_CORRUPT"; - case DbResult.BE_SQLITE_NOTFOUND: return "Not Found"; - case DbResult.BE_SQLITE_FULL: return "BE_SQLITE_FULL"; - case DbResult.BE_SQLITE_CANTOPEN: return "Can't open"; - case DbResult.BE_SQLITE_PROTOCOL: return "BE_SQLITE_PROTOCOL"; - case DbResult.BE_SQLITE_EMPTY: return "BE_SQLITE_EMPTY"; - case DbResult.BE_SQLITE_SCHEMA: return "BE_SQLITE_SCHEMA"; - case DbResult.BE_SQLITE_TOOBIG: return "BE_SQLITE_TOOBIG"; - case DbResult.BE_SQLITE_MISMATCH: return "BE_SQLITE_MISMATCH"; - case DbResult.BE_SQLITE_MISUSE: return "BE_SQLITE_MISUSE"; - case DbResult.BE_SQLITE_NOLFS: return "BE_SQLITE_NOLFS"; - case DbResult.BE_SQLITE_AUTH: return "BE_SQLITE_AUTH"; - case DbResult.BE_SQLITE_FORMAT: return "BE_SQLITE_FORMAT"; - case DbResult.BE_SQLITE_RANGE: return "BE_SQLITE_RANGE"; - case DbResult.BE_SQLITE_NOTADB: return "Not a Database"; - case DbResult.BE_SQLITE_IOERR_READ: return "BE_SQLITE_IOERR_READ"; - case DbResult.BE_SQLITE_IOERR_SHORT_READ: return "BE_SQLITE_IOERR_SHORT_READ"; - case DbResult.BE_SQLITE_IOERR_WRITE: return "BE_SQLITE_IOERR_WRITE"; - case DbResult.BE_SQLITE_IOERR_FSYNC: return "BE_SQLITE_IOERR_FSYNC"; - case DbResult.BE_SQLITE_IOERR_DIR_FSYNC: return "BE_SQLITE_IOERR_DIR_FSYNC"; - case DbResult.BE_SQLITE_IOERR_TRUNCATE: return "BE_SQLITE_IOERR_TRUNCATE"; - case DbResult.BE_SQLITE_IOERR_FSTAT: return "BE_SQLITE_IOERR_FSTAT"; - case DbResult.BE_SQLITE_IOERR_UNLOCK: return "BE_SQLITE_IOERR_UNLOCK"; - case DbResult.BE_SQLITE_IOERR_RDLOCK: return "BE_SQLITE_IOERR_RDLOCK"; - case DbResult.BE_SQLITE_IOERR_DELETE: return "BE_SQLITE_IOERR_DELETE"; - case DbResult.BE_SQLITE_IOERR_BLOCKED: return "BE_SQLITE_IOERR_BLOCKED"; - case DbResult.BE_SQLITE_IOERR_NOMEM: return "BE_SQLITE_IOERR_NOMEM"; - case DbResult.BE_SQLITE_IOERR_ACCESS: return "BE_SQLITE_IOERR_ACCESS"; - case DbResult.BE_SQLITE_IOERR_CHECKRESERVEDLOCK: return "BE_SQLITE_IOERR_CHECKRESERVEDLOCK"; - case DbResult.BE_SQLITE_IOERR_LOCK: return "BE_SQLITE_IOERR_LOCK"; - case DbResult.BE_SQLITE_IOERR_CLOSE: return "BE_SQLITE_IOERR_CLOSE"; - case DbResult.BE_SQLITE_IOERR_DIR_CLOSE: return "BE_SQLITE_IOERR_DIR_CLOSE"; - case DbResult.BE_SQLITE_IOERR_SHMOPEN: return "BE_SQLITE_IOERR_SHMOPEN"; - case DbResult.BE_SQLITE_IOERR_SHMSIZE: return "BE_SQLITE_IOERR_SHMSIZE"; - case DbResult.BE_SQLITE_IOERR_SHMLOCK: return "BE_SQLITE_IOERR_SHMLOCK"; - case DbResult.BE_SQLITE_IOERR_SHMMAP: return "BE_SQLITE_IOERR_SHMMAP"; - case DbResult.BE_SQLITE_IOERR_SEEK: return "BE_SQLITE_IOERR_SEEK"; - case DbResult.BE_SQLITE_IOERR_DELETE_NOENT: return "BE_SQLITE_IOERR_DELETE_NOENT"; - - case DbResult.BE_SQLITE_ERROR_DataTransformRequired: return "Schema update require to transform data"; - case DbResult.BE_SQLITE_ERROR_FileExists: return "File Exists"; - case DbResult.BE_SQLITE_ERROR_AlreadyOpen: return "Already Open"; - case DbResult.BE_SQLITE_ERROR_NoPropertyTable: return "No Property Table"; - case DbResult.BE_SQLITE_ERROR_FileNotFound: return "File Not Found"; - case DbResult.BE_SQLITE_ERROR_NoTxnActive: return "No Txn Active"; - case DbResult.BE_SQLITE_ERROR_BadDbProfile: return "Bad Db Profile"; - case DbResult.BE_SQLITE_ERROR_InvalidProfileVersion: return "Invalid Profile Version"; - case DbResult.BE_SQLITE_ERROR_ProfileUpgradeFailed: return "Profile Upgrade Failed"; - case DbResult.BE_SQLITE_ERROR_ProfileTooOldForReadWrite: return "Profile Too Old For ReadWrite"; - case DbResult.BE_SQLITE_ERROR_ProfileTooOld: return "Profile Too Old"; - case DbResult.BE_SQLITE_ERROR_ProfileTooNewForReadWrite: return "Profile Too New For ReadWrite"; - case DbResult.BE_SQLITE_ERROR_ProfileTooNew: return "Profile Too New"; - case DbResult.BE_SQLITE_ERROR_ChangeTrackError: return "ChangeTrack Error"; - case DbResult.BE_SQLITE_ERROR_InvalidChangeSetVersion: return "Invalid ChangeSet Version"; - case DbResult.BE_SQLITE_ERROR_SchemaUpgradeRequired: return "Schema Upgrade Required"; - case DbResult.BE_SQLITE_ERROR_SchemaTooNew: return "Schema Too New"; - case DbResult.BE_SQLITE_ERROR_SchemaTooOld: return "Schema Too Old"; - case DbResult.BE_SQLITE_ERROR_SchemaLockFailed: return "Schema Lock Failed"; - case DbResult.BE_SQLITE_ERROR_SchemaUpgradeFailed: return "Schema Upgrade Failed"; - case DbResult.BE_SQLITE_ERROR_SchemaImportFailed: return "Schema Import Failed"; - case DbResult.BE_SQLITE_ERROR_CouldNotAcquireLocksOrCodes: return "Could Not Acquire Locks Or Codes"; - case DbResult.BE_SQLITE_ERROR_SchemaUpgradeRecommended: return "Recommended that the schemas found in the database be upgraded"; - case DbResult.BE_SQLITE_LOCKED_SHAREDCACHE: return "BE_SQLITE_LOCKED_SHAREDCACHE"; - case DbResult.BE_SQLITE_BUSY_RECOVERY: return "BE_SQLITE_BUSY_RECOVERY"; - case DbResult.BE_SQLITE_CANTOPEN_NOTEMPDIR: return "SQLite No Temp Dir"; - case DbResult.BE_SQLITE_CANTOPEN_ISDIR: return "BE_SQLITE_CANTOPEN_ISDIR"; - case DbResult.BE_SQLITE_CANTOPEN_FULLPATH: return "BE_SQLITE_CANTOPEN_FULLPATH"; - case DbResult.BE_SQLITE_CORRUPT_VTAB: return "BE_SQLITE_CORRUPT_VTAB"; - case DbResult.BE_SQLITE_READONLY_RECOVERY: return "BE_SQLITE_READONLY_RECOVERY"; - case DbResult.BE_SQLITE_READONLY_CANTLOCK: return "BE_SQLITE_READONLY_CANTLOCK"; - case DbResult.BE_SQLITE_READONLY_ROLLBACK: return "BE_SQLITE_READONLY_ROLLBACK"; - case DbResult.BE_SQLITE_ABORT_ROLLBACK: return "BE_SQLITE_ABORT_ROLLBACK"; - case DbResult.BE_SQLITE_CONSTRAINT_CHECK: return "BE_SQLITE_CONSTRAINT_CHECK"; - case DbResult.BE_SQLITE_CONSTRAINT_COMMITHOOK: return "CommitHook Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_FOREIGNKEY: return "Foreign Key Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_FUNCTION: return "Function Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_NOTNULL: return "NotNull Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_PRIMARYKEY: return "Primary Key Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_TRIGGER: return "Trigger Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_UNIQUE: return "Unique Constraint Error"; - case DbResult.BE_SQLITE_CONSTRAINT_VTAB: return "VTable Constraint Error"; - case BentleyStatus.ERROR: return "Error"; - case BriefcaseStatus.CannotAcquire: return "CannotAcquire"; - case BriefcaseStatus.CannotDownload: return "CannotDownload"; - case BriefcaseStatus.CannotCopy: return "CannotCopy"; - case BriefcaseStatus.CannotDelete: return "CannotDelete"; - case BriefcaseStatus.VersionNotFound: return "VersionNotFound"; - case BriefcaseStatus.DownloadCancelled: return "DownloadCancelled"; - case BriefcaseStatus.ContainsDeletedChangeSets: return "ContainsDeletedChangeSets"; - case RpcInterfaceStatus.IncompatibleVersion: return "RpcInterfaceStatus.IncompatibleVersion"; - case ChangeSetStatus.ApplyError: return "Error applying a change set"; - case ChangeSetStatus.ChangeTrackingNotEnabled: return "Change tracking has not been enabled. The ChangeSet API mandates this"; - case ChangeSetStatus.CorruptedChangeStream: return "Contents of the change stream are corrupted and does not match the ChangeSet"; - case ChangeSetStatus.FileNotFound: return "File containing the changes was not found"; - case ChangeSetStatus.FileWriteError: return "Error writing the contents of the change set to the backing change stream file"; - case ChangeSetStatus.HasLocalChanges: return "Cannot perform the operation since the Db has local changes"; - case ChangeSetStatus.HasUncommittedChanges: return "Cannot perform the operation since current transaction has uncommitted changes"; - case ChangeSetStatus.InvalidId: return "Invalid ChangeSet Id"; - case ChangeSetStatus.InvalidVersion: return "Invalid version of the change set"; - case ChangeSetStatus.InDynamicTransaction: return "Cannot perform the operation since system is in the middle of a dynamic transaction"; - case ChangeSetStatus.IsCreatingChangeSet: return "Cannot perform operation since system is in the middle of a creating a change set"; - case ChangeSetStatus.IsNotCreatingChangeSet: return "Cannot perform operation since the system is not creating a change set"; - case ChangeSetStatus.MergePropagationError: return "Error propagating the changes after the merge"; - case ChangeSetStatus.NothingToMerge: return "No change sets to merge"; - case ChangeSetStatus.NoTransactions: return "No transactions are available to create a change set"; - case ChangeSetStatus.ParentMismatch: return "Parent change set of the Db does not match the parent id of the change set"; - case ChangeSetStatus.SQLiteError: return "Error performing a SQLite operation on the Db"; - case ChangeSetStatus.WrongDgnDb: return "ChangeSet originated in a different Db"; - case ChangeSetStatus.CouldNotOpenDgnDb: return "Could not open the DgnDb to merge change set"; - case ChangeSetStatus.MergeSchemaChangesOnOpen: return "Cannot merge changes in in an open DgnDb. Close the DgnDb, and process the operation when it is opened"; - case ChangeSetStatus.ReverseOrReinstateSchemaChanges: return "Cannot reverse or reinstate schema changes."; - case ChangeSetStatus.ProcessSchemaChangesOnOpen: return "Cannot process changes schema changes in an open DgnDb. Close the DgnDb, and process the operation when it is opened"; - case ChangeSetStatus.CannotMergeIntoReadonly: return "Cannot merge changes into a Readonly DgnDb"; - case ChangeSetStatus.CannotMergeIntoMaster: return "Cannot merge changes into a Master DgnDb"; - case ChangeSetStatus.CannotMergeIntoReversed: return "Cannot merge changes into a DgnDb that has reversed change sets"; - case ChangeSetStatus.DownloadCancelled: return "ChangeSet(s) download was cancelled."; - case RepositoryStatus.ServerUnavailable: return "ServerUnavailable"; - case RepositoryStatus.LockAlreadyHeld: return "LockAlreadyHeld"; - case RepositoryStatus.SyncError: return "SyncError"; - case RepositoryStatus.InvalidResponse: return "InvalidResponse"; - case RepositoryStatus.PendingTransactions: return "PendingTransactions"; - case RepositoryStatus.LockUsed: return "LockUsed"; - case RepositoryStatus.CannotCreateChangeSet: return "CannotCreateChangeSet"; - case RepositoryStatus.InvalidRequest: return "InvalidRequest"; - case RepositoryStatus.ChangeSetRequired: return "ChangeSetRequired"; - case RepositoryStatus.CodeUnavailable: return "CodeUnavailable"; - case RepositoryStatus.CodeNotReserved: return "CodeNotReserved"; - case RepositoryStatus.CodeUsed: return "CodeUsed"; - case RepositoryStatus.LockNotHeld: return "LockNotHeld"; - case RepositoryStatus.RepositoryIsLocked: return "RepositoryIsLocked"; - case RepositoryStatus.ChannelConstraintViolation: return "ChannelConstraintViolation"; - case HttpStatus.Info: return "HTTP Info"; - case HttpStatus.Redirection: return "HTTP Redirection"; - case HttpStatus.ClientError: return "HTTP Client error"; - case HttpStatus.ServerError: return "HTTP Server error"; - case IModelHubStatus.Unknown: return "Unknown error"; - case IModelHubStatus.MissingRequiredProperties: return "Missing required properties"; - case IModelHubStatus.InvalidPropertiesValues: return "Invalid properties values"; - case IModelHubStatus.UserDoesNotHavePermission: return "User does not have permission"; - case IModelHubStatus.UserDoesNotHaveAccess: return "User does not have access"; - case IModelHubStatus.InvalidBriefcase: return "Invalid briefcase"; - case IModelHubStatus.BriefcaseDoesNotExist: return "Briefcase does not exist"; - case IModelHubStatus.BriefcaseDoesNotBelongToUser: return "Briefcase does not belong to user"; - case IModelHubStatus.AnotherUserPushing: return "Another user pushing"; - case IModelHubStatus.ChangeSetAlreadyExists: return "ChangeSet already exists"; - case IModelHubStatus.ChangeSetDoesNotExist: return "ChangeSet does not exist"; - case IModelHubStatus.FileIsNotUploaded: return "File is not uploaded"; - case IModelHubStatus.iModelIsNotInitialized: return "iModel is not initialized"; - case IModelHubStatus.ChangeSetPointsToBadSeed: return "ChangeSet points to a bad seed file"; - case IModelHubStatus.OperationFailed: return "iModelHub operation has failed"; - case IModelHubStatus.PullIsRequired: return "Pull is required"; - case IModelHubStatus.MaximumNumberOfBriefcasesPerUser: return "Limit of briefcases per user was reached"; - case IModelHubStatus.MaximumNumberOfBriefcasesPerUserPerMinute: return "Limit of briefcases per user per minute was reached"; - case IModelHubStatus.DatabaseTemporarilyLocked: return "Database is temporarily locked"; - case IModelHubStatus.iModelIsLocked: return "iModel is locked"; - case IModelHubStatus.CodesExist: return "Code already exists"; - case IModelHubStatus.LocksExist: return "Lock already exists"; - case IModelHubStatus.iModelAlreadyExists: return "iModel already exists"; - case IModelHubStatus.iModelDoesNotExist: return "iModel does not exist"; - case IModelHubStatus.LockDoesNotExist: return "Lock does not exist"; - case IModelHubStatus.LockChunkDoesNotExist: return "Lock chunk does not exist"; - case IModelHubStatus.LockOwnedByAnotherBriefcase: return "Lock is owned by another briefcase"; - case IModelHubStatus.CodeStateInvalid: return "Code state is invalid"; - case IModelHubStatus.CodeReservedByAnotherBriefcase: return "Code is reserved by another briefcase"; - case IModelHubStatus.CodeDoesNotExist: return "Code does not exist"; - case IModelHubStatus.FileDoesNotExist: return "File does not exist"; - case IModelHubStatus.FileAlreadyExists: return "File already exists"; - case IModelHubStatus.EventTypeDoesNotExist: return "Event type does not exist"; - case IModelHubStatus.EventSubscriptionDoesNotExist: return "Event subscription does not exist"; - case IModelHubStatus.EventSubscriptionAlreadyExists: return "Event subscription already exists"; - case IModelHubStatus.ITwinIdIsNotSpecified: return "ITwin Id is not specified"; - case IModelHubStatus.FailedToGetITwinPermissions: return "Failed to get iTwin permissions"; - case IModelHubStatus.FailedToGetITwinMembers: return "Failed to get iTwin members"; - case IModelHubStatus.FailedToGetAssetPermissions: return "Failed to get asset permissions"; - case IModelHubStatus.FailedToGetAssetMembers: return "Failed to get asset members"; - case IModelHubStatus.ChangeSetAlreadyHasVersion: return "ChangeSet already has version"; - case IModelHubStatus.VersionAlreadyExists: return "Version already exists"; - case IModelHubStatus.JobSchedulingFailed: return "Failed to schedule a background job"; - case IModelHubStatus.ConflictsAggregate: return "Codes or locks are owned by another briefcase"; - case IModelHubStatus.FailedToGetITwinById: return "Failed to query iTwin by its id"; - case IModelHubStatus.DatabaseOperationFailed: return "Database operation has failed"; - case IModelHubStatus.ITwinDoesNotExist: return "ITwin does not exist"; - case IModelHubStatus.UndefinedArgumentError: return "Undefined argument"; - case IModelHubStatus.InvalidArgumentError: return "Invalid argument"; - case IModelHubStatus.MissingDownloadUrlError: return "Missing download url"; - case IModelHubStatus.NotSupportedInBrowser: return "Not supported in browser"; - case IModelHubStatus.FileHandlerNotSet: return "File handler is not set"; - case IModelHubStatus.FileNotFound: return "File not found"; - case GeoServiceStatus.NoGeoLocation: return "No GeoLocation"; - case GeoServiceStatus.OutOfUsefulRange: return "Out of useful range"; - case GeoServiceStatus.OutOfMathematicalDomain: return "Out of mathematical domain"; - case GeoServiceStatus.NoDatumConverter: return "No datum converter"; - case GeoServiceStatus.VerticalDatumConvertError: return "Vertical datum convert error"; - case GeoServiceStatus.CSMapError: return "CSMap error"; - case GeoServiceStatus.Pending: return "Pending"; - case RealityDataStatus.InvalidData: return "Invalid or unknown data"; + case IModelStatus.AlreadyLoaded: + return "Already Loaded"; + case IModelStatus.AlreadyOpen: + return "Already Open"; + case IModelStatus.BadArg: + return "Bad Arg"; + case IModelStatus.BadElement: + return "Bad Element"; + case IModelStatus.BadModel: + return "Bad Model"; + case IModelStatus.BadRequest: + return "Bad Request"; + case IModelStatus.BadSchema: + return "Bad Schema"; + case IModelStatus.CannotUndo: + return "Can not Undo"; + case IModelStatus.CodeNotReserved: + return "Code Not Reserved"; + case IModelStatus.DeletionProhibited: + return "Deletion Prohibited"; + case IModelStatus.DuplicateCode: + return "Duplicate Code"; + case IModelStatus.DuplicateName: + return "Duplicate Name"; + case IModelStatus.ElementBlockedChange: + return "Element Blocked Change"; + case IModelStatus.FileAlreadyExists: + return "File Already Exists"; + case IModelStatus.FileNotFound: + return "File Not Found"; + case IModelStatus.FileNotLoaded: + return "File Not Loaded"; + case IModelStatus.ForeignKeyConstraint: + return "ForeignKey Constraint"; + case IModelStatus.IdExists: + return "Id Exists"; + case IModelStatus.InDynamicTransaction: + return "InDynamicTransaction"; + case IModelStatus.InvalidCategory: + return "Invalid Category"; + case IModelStatus.InvalidCode: + return "Invalid Code"; + case IModelStatus.InvalidCodeSpec: + return "Invalid CodeSpec"; + case IModelStatus.InvalidId: + return "Invalid Id"; + case IModelStatus.InvalidName: + return "Invalid Name"; + case IModelStatus.InvalidParent: + return "Invalid Parent"; + case IModelStatus.InvalidProfileVersion: + return "Invalid Profile Version"; + case IModelStatus.IsCreatingChangeSet: + return "IsCreatingChangeSet"; + case IModelStatus.LockNotHeld: + return "Lock Not Held"; + case IModelStatus.Mismatch2d3d: + return "Mismatch 2d3d"; + case IModelStatus.MismatchGcs: + return "Mismatch Gcs"; + case IModelStatus.MissingDomain: + return "Missing Domain"; + case IModelStatus.MissingHandler: + return "Missing Handler"; + case IModelStatus.MissingId: + return "Missing Id"; + case IModelStatus.NoGeometry: + return "No Geometry"; + case IModelStatus.NoMultiTxnOperation: + return "NoMultiTxnOperation"; + case IModelStatus.NotEnabled: + return "Not Enabled"; + case IModelStatus.NotFound: + return "Not Found"; + case IModelStatus.NotOpen: + return "Not Open"; + case IModelStatus.NotOpenForWrite: + return "Not Open For Write"; + case IModelStatus.NotSameUnitBase: + return "Not Same Unit Base"; + case IModelStatus.NothingToRedo: + return "Nothing To Redo"; + case IModelStatus.NothingToUndo: + return "Nothing To Undo"; + case IModelStatus.ParentBlockedChange: + return "Parent Blocked Change"; + case IModelStatus.ReadError: + return "Read Error"; + case IModelStatus.ReadOnly: + return "ReadOnly"; + case IModelStatus.ReadOnlyDomain: + return "ReadOnlyDomain"; + case IModelStatus.RepositoryManagerError: + return "RepositoryManagerError"; + case IModelStatus.SQLiteError: + return "SQLiteError"; + case IModelStatus.TransactionActive: + return "Transaction Active"; + case IModelStatus.UnitsMissing: + return "Units Missing"; + case IModelStatus.UnknownFormat: + return "Unknown Format"; + case IModelStatus.UpgradeFailed: + return "Upgrade Failed"; + case IModelStatus.ValidationFailed: + return "Validation Failed"; + case IModelStatus.VersionTooNew: + return "Version Too New"; + case IModelStatus.VersionTooOld: + return "Version Too Old"; + case IModelStatus.ViewNotFound: + return "View Not Found"; + case IModelStatus.WriteError: + return "Write Error"; + case IModelStatus.WrongClass: + return "Wrong Class"; + case IModelStatus.WrongIModel: + return "Wrong IModel"; + case IModelStatus.WrongDomain: + return "Wrong Domain"; + case IModelStatus.WrongElement: + return "Wrong Element"; + case IModelStatus.WrongHandler: + return "Wrong Handler"; + case IModelStatus.WrongModel: + return "Wrong Model"; + case DbResult.BE_SQLITE_ERROR: + return "BE_SQLITE_ERROR"; + case DbResult.BE_SQLITE_INTERNAL: + return "BE_SQLITE_INTERNAL"; + case DbResult.BE_SQLITE_PERM: + return "BE_SQLITE_PERM"; + case DbResult.BE_SQLITE_ABORT: + return "BE_SQLITE_ABORT"; + case DbResult.BE_SQLITE_BUSY: + return "Db is busy"; + case DbResult.BE_SQLITE_LOCKED: + return "Db is Locked"; + case DbResult.BE_SQLITE_NOMEM: + return "BE_SQLITE_NOMEM"; + case DbResult.BE_SQLITE_READONLY: + return "Readonly"; + case DbResult.BE_SQLITE_INTERRUPT: + return "BE_SQLITE_INTERRUPT"; + case DbResult.BE_SQLITE_IOERR: + return "BE_SQLITE_IOERR"; + case DbResult.BE_SQLITE_CORRUPT: + return "BE_SQLITE_CORRUPT"; + case DbResult.BE_SQLITE_NOTFOUND: + return "Not Found"; + case DbResult.BE_SQLITE_FULL: + return "BE_SQLITE_FULL"; + case DbResult.BE_SQLITE_CANTOPEN: + return "Can't open"; + case DbResult.BE_SQLITE_PROTOCOL: + return "BE_SQLITE_PROTOCOL"; + case DbResult.BE_SQLITE_EMPTY: + return "BE_SQLITE_EMPTY"; + case DbResult.BE_SQLITE_SCHEMA: + return "BE_SQLITE_SCHEMA"; + case DbResult.BE_SQLITE_TOOBIG: + return "BE_SQLITE_TOOBIG"; + case DbResult.BE_SQLITE_MISMATCH: + return "BE_SQLITE_MISMATCH"; + case DbResult.BE_SQLITE_MISUSE: + return "BE_SQLITE_MISUSE"; + case DbResult.BE_SQLITE_NOLFS: + return "BE_SQLITE_NOLFS"; + case DbResult.BE_SQLITE_AUTH: + return "BE_SQLITE_AUTH"; + case DbResult.BE_SQLITE_FORMAT: + return "BE_SQLITE_FORMAT"; + case DbResult.BE_SQLITE_RANGE: + return "BE_SQLITE_RANGE"; + case DbResult.BE_SQLITE_NOTADB: + return "Not a Database"; + case DbResult.BE_SQLITE_IOERR_READ: + return "BE_SQLITE_IOERR_READ"; + case DbResult.BE_SQLITE_IOERR_SHORT_READ: + return "BE_SQLITE_IOERR_SHORT_READ"; + case DbResult.BE_SQLITE_IOERR_WRITE: + return "BE_SQLITE_IOERR_WRITE"; + case DbResult.BE_SQLITE_IOERR_FSYNC: + return "BE_SQLITE_IOERR_FSYNC"; + case DbResult.BE_SQLITE_IOERR_DIR_FSYNC: + return "BE_SQLITE_IOERR_DIR_FSYNC"; + case DbResult.BE_SQLITE_IOERR_TRUNCATE: + return "BE_SQLITE_IOERR_TRUNCATE"; + case DbResult.BE_SQLITE_IOERR_FSTAT: + return "BE_SQLITE_IOERR_FSTAT"; + case DbResult.BE_SQLITE_IOERR_UNLOCK: + return "BE_SQLITE_IOERR_UNLOCK"; + case DbResult.BE_SQLITE_IOERR_RDLOCK: + return "BE_SQLITE_IOERR_RDLOCK"; + case DbResult.BE_SQLITE_IOERR_DELETE: + return "BE_SQLITE_IOERR_DELETE"; + case DbResult.BE_SQLITE_IOERR_BLOCKED: + return "BE_SQLITE_IOERR_BLOCKED"; + case DbResult.BE_SQLITE_IOERR_NOMEM: + return "BE_SQLITE_IOERR_NOMEM"; + case DbResult.BE_SQLITE_IOERR_ACCESS: + return "BE_SQLITE_IOERR_ACCESS"; + case DbResult.BE_SQLITE_IOERR_CHECKRESERVEDLOCK: + return "BE_SQLITE_IOERR_CHECKRESERVEDLOCK"; + case DbResult.BE_SQLITE_IOERR_LOCK: + return "BE_SQLITE_IOERR_LOCK"; + case DbResult.BE_SQLITE_IOERR_CLOSE: + return "BE_SQLITE_IOERR_CLOSE"; + case DbResult.BE_SQLITE_IOERR_DIR_CLOSE: + return "BE_SQLITE_IOERR_DIR_CLOSE"; + case DbResult.BE_SQLITE_IOERR_SHMOPEN: + return "BE_SQLITE_IOERR_SHMOPEN"; + case DbResult.BE_SQLITE_IOERR_SHMSIZE: + return "BE_SQLITE_IOERR_SHMSIZE"; + case DbResult.BE_SQLITE_IOERR_SHMLOCK: + return "BE_SQLITE_IOERR_SHMLOCK"; + case DbResult.BE_SQLITE_IOERR_SHMMAP: + return "BE_SQLITE_IOERR_SHMMAP"; + case DbResult.BE_SQLITE_IOERR_SEEK: + return "BE_SQLITE_IOERR_SEEK"; + case DbResult.BE_SQLITE_IOERR_DELETE_NOENT: + return "BE_SQLITE_IOERR_DELETE_NOENT"; + + case DbResult.BE_SQLITE_ERROR_DataTransformRequired: + return "Schema update require to transform data"; + case DbResult.BE_SQLITE_ERROR_FileExists: + return "File Exists"; + case DbResult.BE_SQLITE_ERROR_AlreadyOpen: + return "Already Open"; + case DbResult.BE_SQLITE_ERROR_NoPropertyTable: + return "No Property Table"; + case DbResult.BE_SQLITE_ERROR_FileNotFound: + return "File Not Found"; + case DbResult.BE_SQLITE_ERROR_NoTxnActive: + return "No Txn Active"; + case DbResult.BE_SQLITE_ERROR_BadDbProfile: + return "Bad Db Profile"; + case DbResult.BE_SQLITE_ERROR_InvalidProfileVersion: + return "Invalid Profile Version"; + case DbResult.BE_SQLITE_ERROR_ProfileUpgradeFailed: + return "Profile Upgrade Failed"; + case DbResult.BE_SQLITE_ERROR_ProfileTooOldForReadWrite: + return "Profile Too Old For ReadWrite"; + case DbResult.BE_SQLITE_ERROR_ProfileTooOld: + return "Profile Too Old"; + case DbResult.BE_SQLITE_ERROR_ProfileTooNewForReadWrite: + return "Profile Too New For ReadWrite"; + case DbResult.BE_SQLITE_ERROR_ProfileTooNew: + return "Profile Too New"; + case DbResult.BE_SQLITE_ERROR_ChangeTrackError: + return "ChangeTrack Error"; + case DbResult.BE_SQLITE_ERROR_InvalidChangeSetVersion: + return "Invalid ChangeSet Version"; + case DbResult.BE_SQLITE_ERROR_SchemaUpgradeRequired: + return "Schema Upgrade Required"; + case DbResult.BE_SQLITE_ERROR_SchemaTooNew: + return "Schema Too New"; + case DbResult.BE_SQLITE_ERROR_SchemaTooOld: + return "Schema Too Old"; + case DbResult.BE_SQLITE_ERROR_SchemaLockFailed: + return "Schema Lock Failed"; + case DbResult.BE_SQLITE_ERROR_SchemaUpgradeFailed: + return "Schema Upgrade Failed"; + case DbResult.BE_SQLITE_ERROR_SchemaImportFailed: + return "Schema Import Failed"; + case DbResult.BE_SQLITE_ERROR_CouldNotAcquireLocksOrCodes: + return "Could Not Acquire Locks Or Codes"; + case DbResult.BE_SQLITE_ERROR_SchemaUpgradeRecommended: + return "Recommended that the schemas found in the database be upgraded"; + case DbResult.BE_SQLITE_LOCKED_SHAREDCACHE: + return "BE_SQLITE_LOCKED_SHAREDCACHE"; + case DbResult.BE_SQLITE_BUSY_RECOVERY: + return "BE_SQLITE_BUSY_RECOVERY"; + case DbResult.BE_SQLITE_CANTOPEN_NOTEMPDIR: + return "SQLite No Temp Dir"; + case DbResult.BE_SQLITE_CANTOPEN_ISDIR: + return "BE_SQLITE_CANTOPEN_ISDIR"; + case DbResult.BE_SQLITE_CANTOPEN_FULLPATH: + return "BE_SQLITE_CANTOPEN_FULLPATH"; + case DbResult.BE_SQLITE_CORRUPT_VTAB: + return "BE_SQLITE_CORRUPT_VTAB"; + case DbResult.BE_SQLITE_READONLY_RECOVERY: + return "BE_SQLITE_READONLY_RECOVERY"; + case DbResult.BE_SQLITE_READONLY_CANTLOCK: + return "BE_SQLITE_READONLY_CANTLOCK"; + case DbResult.BE_SQLITE_READONLY_ROLLBACK: + return "BE_SQLITE_READONLY_ROLLBACK"; + case DbResult.BE_SQLITE_ABORT_ROLLBACK: + return "BE_SQLITE_ABORT_ROLLBACK"; + case DbResult.BE_SQLITE_CONSTRAINT_CHECK: + return "BE_SQLITE_CONSTRAINT_CHECK"; + case DbResult.BE_SQLITE_CONSTRAINT_COMMITHOOK: + return "CommitHook Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_FOREIGNKEY: + return "Foreign Key Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_FUNCTION: + return "Function Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_NOTNULL: + return "NotNull Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_PRIMARYKEY: + return "Primary Key Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_TRIGGER: + return "Trigger Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_UNIQUE: + return "Unique Constraint Error"; + case DbResult.BE_SQLITE_CONSTRAINT_VTAB: + return "VTable Constraint Error"; + case BentleyStatus.ERROR: + return "Error"; + case BriefcaseStatus.CannotAcquire: + return "CannotAcquire"; + case BriefcaseStatus.CannotDownload: + return "CannotDownload"; + case BriefcaseStatus.CannotCopy: + return "CannotCopy"; + case BriefcaseStatus.CannotDelete: + return "CannotDelete"; + case BriefcaseStatus.VersionNotFound: + return "VersionNotFound"; + case BriefcaseStatus.DownloadCancelled: + return "DownloadCancelled"; + case BriefcaseStatus.ContainsDeletedChangeSets: + return "ContainsDeletedChangeSets"; + case RpcInterfaceStatus.IncompatibleVersion: + return "RpcInterfaceStatus.IncompatibleVersion"; + case ChangeSetStatus.ApplyError: + return "Error applying a change set"; + case ChangeSetStatus.ChangeTrackingNotEnabled: + return "Change tracking has not been enabled. The ChangeSet API mandates this"; + case ChangeSetStatus.CorruptedChangeStream: + return "Contents of the change stream are corrupted and does not match the ChangeSet"; + case ChangeSetStatus.FileNotFound: + return "File containing the changes was not found"; + case ChangeSetStatus.FileWriteError: + return "Error writing the contents of the change set to the backing change stream file"; + case ChangeSetStatus.HasLocalChanges: + return "Cannot perform the operation since the Db has local changes"; + case ChangeSetStatus.HasUncommittedChanges: + return "Cannot perform the operation since current transaction has uncommitted changes"; + case ChangeSetStatus.InvalidId: + return "Invalid ChangeSet Id"; + case ChangeSetStatus.InvalidVersion: + return "Invalid version of the change set"; + case ChangeSetStatus.InDynamicTransaction: + return "Cannot perform the operation since system is in the middle of a dynamic transaction"; + case ChangeSetStatus.IsCreatingChangeSet: + return "Cannot perform operation since system is in the middle of a creating a change set"; + case ChangeSetStatus.IsNotCreatingChangeSet: + return "Cannot perform operation since the system is not creating a change set"; + case ChangeSetStatus.MergePropagationError: + return "Error propagating the changes after the merge"; + case ChangeSetStatus.NothingToMerge: + return "No change sets to merge"; + case ChangeSetStatus.NoTransactions: + return "No transactions are available to create a change set"; + case ChangeSetStatus.ParentMismatch: + return "Parent change set of the Db does not match the parent id of the change set"; + case ChangeSetStatus.SQLiteError: + return "Error performing a SQLite operation on the Db"; + case ChangeSetStatus.WrongDgnDb: + return "ChangeSet originated in a different Db"; + case ChangeSetStatus.CouldNotOpenDgnDb: + return "Could not open the DgnDb to merge change set"; + case ChangeSetStatus.MergeSchemaChangesOnOpen: + return "Cannot merge changes in in an open DgnDb. Close the DgnDb, and process the operation when it is opened"; + case ChangeSetStatus.ReverseOrReinstateSchemaChanges: + return "Cannot reverse or reinstate schema changes."; + case ChangeSetStatus.ProcessSchemaChangesOnOpen: + return "Cannot process changes schema changes in an open DgnDb. Close the DgnDb, and process the operation when it is opened"; + case ChangeSetStatus.CannotMergeIntoReadonly: + return "Cannot merge changes into a Readonly DgnDb"; + case ChangeSetStatus.CannotMergeIntoMaster: + return "Cannot merge changes into a Master DgnDb"; + case ChangeSetStatus.CannotMergeIntoReversed: + return "Cannot merge changes into a DgnDb that has reversed change sets"; + case ChangeSetStatus.DownloadCancelled: + return "ChangeSet(s) download was cancelled."; + case RepositoryStatus.ServerUnavailable: + return "ServerUnavailable"; + case RepositoryStatus.LockAlreadyHeld: + return "LockAlreadyHeld"; + case RepositoryStatus.SyncError: + return "SyncError"; + case RepositoryStatus.InvalidResponse: + return "InvalidResponse"; + case RepositoryStatus.PendingTransactions: + return "PendingTransactions"; + case RepositoryStatus.LockUsed: + return "LockUsed"; + case RepositoryStatus.CannotCreateChangeSet: + return "CannotCreateChangeSet"; + case RepositoryStatus.InvalidRequest: + return "InvalidRequest"; + case RepositoryStatus.ChangeSetRequired: + return "ChangeSetRequired"; + case RepositoryStatus.CodeUnavailable: + return "CodeUnavailable"; + case RepositoryStatus.CodeNotReserved: + return "CodeNotReserved"; + case RepositoryStatus.CodeUsed: + return "CodeUsed"; + case RepositoryStatus.LockNotHeld: + return "LockNotHeld"; + case RepositoryStatus.RepositoryIsLocked: + return "RepositoryIsLocked"; + case RepositoryStatus.ChannelConstraintViolation: + return "ChannelConstraintViolation"; + case HttpStatus.Info: + return "HTTP Info"; + case HttpStatus.Redirection: + return "HTTP Redirection"; + case HttpStatus.ClientError: + return "HTTP Client error"; + case HttpStatus.ServerError: + return "HTTP Server error"; + case IModelHubStatus.Unknown: + return "Unknown error"; + case IModelHubStatus.MissingRequiredProperties: + return "Missing required properties"; + case IModelHubStatus.InvalidPropertiesValues: + return "Invalid properties values"; + case IModelHubStatus.UserDoesNotHavePermission: + return "User does not have permission"; + case IModelHubStatus.UserDoesNotHaveAccess: + return "User does not have access"; + case IModelHubStatus.InvalidBriefcase: + return "Invalid briefcase"; + case IModelHubStatus.BriefcaseDoesNotExist: + return "Briefcase does not exist"; + case IModelHubStatus.BriefcaseDoesNotBelongToUser: + return "Briefcase does not belong to user"; + case IModelHubStatus.AnotherUserPushing: + return "Another user pushing"; + case IModelHubStatus.ChangeSetAlreadyExists: + return "ChangeSet already exists"; + case IModelHubStatus.ChangeSetDoesNotExist: + return "ChangeSet does not exist"; + case IModelHubStatus.FileIsNotUploaded: + return "File is not uploaded"; + case IModelHubStatus.iModelIsNotInitialized: + return "iModel is not initialized"; + case IModelHubStatus.ChangeSetPointsToBadSeed: + return "ChangeSet points to a bad seed file"; + case IModelHubStatus.OperationFailed: + return "iModelHub operation has failed"; + case IModelHubStatus.PullIsRequired: + return "Pull is required"; + case IModelHubStatus.MaximumNumberOfBriefcasesPerUser: + return "Limit of briefcases per user was reached"; + case IModelHubStatus.MaximumNumberOfBriefcasesPerUserPerMinute: + return "Limit of briefcases per user per minute was reached"; + case IModelHubStatus.DatabaseTemporarilyLocked: + return "Database is temporarily locked"; + case IModelHubStatus.iModelIsLocked: + return "iModel is locked"; + case IModelHubStatus.CodesExist: + return "Code already exists"; + case IModelHubStatus.LocksExist: + return "Lock already exists"; + case IModelHubStatus.iModelAlreadyExists: + return "iModel already exists"; + case IModelHubStatus.iModelDoesNotExist: + return "iModel does not exist"; + case IModelHubStatus.LockDoesNotExist: + return "Lock does not exist"; + case IModelHubStatus.LockChunkDoesNotExist: + return "Lock chunk does not exist"; + case IModelHubStatus.LockOwnedByAnotherBriefcase: + return "Lock is owned by another briefcase"; + case IModelHubStatus.CodeStateInvalid: + return "Code state is invalid"; + case IModelHubStatus.CodeReservedByAnotherBriefcase: + return "Code is reserved by another briefcase"; + case IModelHubStatus.CodeDoesNotExist: + return "Code does not exist"; + case IModelHubStatus.FileDoesNotExist: + return "File does not exist"; + case IModelHubStatus.FileAlreadyExists: + return "File already exists"; + case IModelHubStatus.EventTypeDoesNotExist: + return "Event type does not exist"; + case IModelHubStatus.EventSubscriptionDoesNotExist: + return "Event subscription does not exist"; + case IModelHubStatus.EventSubscriptionAlreadyExists: + return "Event subscription already exists"; + case IModelHubStatus.ITwinIdIsNotSpecified: + return "ITwin Id is not specified"; + case IModelHubStatus.FailedToGetITwinPermissions: + return "Failed to get iTwin permissions"; + case IModelHubStatus.FailedToGetITwinMembers: + return "Failed to get iTwin members"; + case IModelHubStatus.FailedToGetAssetPermissions: + return "Failed to get asset permissions"; + case IModelHubStatus.FailedToGetAssetMembers: + return "Failed to get asset members"; + case IModelHubStatus.ChangeSetAlreadyHasVersion: + return "ChangeSet already has version"; + case IModelHubStatus.VersionAlreadyExists: + return "Version already exists"; + case IModelHubStatus.JobSchedulingFailed: + return "Failed to schedule a background job"; + case IModelHubStatus.ConflictsAggregate: + return "Codes or locks are owned by another briefcase"; + case IModelHubStatus.FailedToGetITwinById: + return "Failed to query iTwin by its id"; + case IModelHubStatus.DatabaseOperationFailed: + return "Database operation has failed"; + case IModelHubStatus.ITwinDoesNotExist: + return "ITwin does not exist"; + case IModelHubStatus.UndefinedArgumentError: + return "Undefined argument"; + case IModelHubStatus.InvalidArgumentError: + return "Invalid argument"; + case IModelHubStatus.MissingDownloadUrlError: + return "Missing download url"; + case IModelHubStatus.NotSupportedInBrowser: + return "Not supported in browser"; + case IModelHubStatus.FileHandlerNotSet: + return "File handler is not set"; + case IModelHubStatus.FileNotFound: + return "File not found"; + case GeoServiceStatus.NoGeoLocation: + return "No GeoLocation"; + case GeoServiceStatus.OutOfUsefulRange: + return "Out of useful range"; + case GeoServiceStatus.OutOfMathematicalDomain: + return "Out of mathematical domain"; + case GeoServiceStatus.NoDatumConverter: + return "No datum converter"; + case GeoServiceStatus.VerticalDatumConvertError: + return "Vertical datum convert error"; + case GeoServiceStatus.CSMapError: + return "CSMap error"; + case GeoServiceStatus.Pending: + return "Pending"; + case RealityDataStatus.InvalidData: + return "Invalid or unknown data"; case DbResult.BE_SQLITE_OK: case DbResult.BE_SQLITE_ROW: case DbResult.BE_SQLITE_DONE: @@ -656,7 +926,7 @@ export class BentleyError extends Error { // eslint-disable-next-line @typescript-eslint/no-base-to-string if (error.toString() !== "[object Object]") - return error.toString(); // eslint-disable-line @typescript-eslint/no-base-to-string + return error.toString(); // eslint-disable-line @typescript-eslint/no-base-to-string } return ""; @@ -709,4 +979,3 @@ export class BentleyError extends Error { return serialized; } } - diff --git a/core/bentley/src/ByteStream.ts b/core/bentley/src/ByteStream.ts index 7dba310a299e..0c2f98890c95 100644 --- a/core/bentley/src/ByteStream.ts +++ b/core/bentley/src/ByteStream.ts @@ -86,7 +86,9 @@ export class ByteStream { } /** The current read position as an index into the stream of bytes. */ - public get curPos(): number { return this._curPos; } + public get curPos(): number { + return this._curPos; + } public set curPos(pos: number) { this._curPos = pos; assert(!this.isPastTheEnd); @@ -94,7 +96,7 @@ export class ByteStream { /** Adds the specified number of bytes to the current read position */ public advance(numBytes: number): boolean { - this.curPos = (this.curPos + numBytes); + this.curPos = this.curPos + numBytes; return !this.isPastTheEnd; } @@ -108,41 +110,75 @@ export class ByteStream { } /** Resets the current read position to the beginning of the stream */ - public reset(): void { this.curPos = 0; } + public reset(): void { + this.curPos = 0; + } /** Read a unsigned 8-bit integer from the current read position and advance by 1 byte. */ - public readUint8(): number { return this.read(1, (view) => view.getUint8(this.curPos)); } + public readUint8(): number { + return this.read(1, (view) => view.getUint8(this.curPos)); + } /** Read an unsigned 16-bit integer from the current read position and advance by 2 bytes. */ - public readUint16(): number { return this.read(2, (view) => view.getUint16(this.curPos, true)); } + public readUint16(): number { + return this.read(2, (view) => view.getUint16(this.curPos, true)); + } /** Read an unsigned 32-bit integer from the current read position and advance by 4 bytes. */ - public readUint32(): number { return this.read(4, (view) => view.getUint32(this.curPos, true)); } + public readUint32(): number { + return this.read(4, (view) => view.getUint32(this.curPos, true)); + } /** Read a signed 32-bit integer from the current read position and advance by 4 bytes. */ - public readInt32(): number { return this.read(4, (view) => view.getInt32(this.curPos, true)); } + public readInt32(): number { + return this.read(4, (view) => view.getInt32(this.curPos, true)); + } /** Read a 32-bit floating point number from the current read position and advance by 4 bytes. */ - public readFloat32(): number { return this.read(4, (view) => view.getFloat32(this.curPos, true)); } + public readFloat32(): number { + return this.read(4, (view) => view.getFloat32(this.curPos, true)); + } /** Read a 64-bit floating point number from the current read position and advance by 8 bytes. */ - public readFloat64(): number { return this.read(8, (view) => view.getFloat64(this.curPos, true)); } + public readFloat64(): number { + return this.read(8, (view) => view.getFloat64(this.curPos, true)); + } /** Read an unsigned 64-bit integer from the current read position, advance by 8 bytes, and return the 64-bit value as an Id64String. */ - public readId64(): Id64String { return Id64.fromUint32Pair(this.readUint32(), this.readUint32()); } + public readId64(): Id64String { + return Id64.fromUint32Pair(this.readUint32(), this.readUint32()); + } /** Read an unsigned 24-bit integer from the current read position and advance by 3 bytes. */ - public readUint24(): number { return this.readUint8() | (this.readUint8() << 8) | (this.readUint8() << 16); } + public readUint24(): number { + return this.readUint8() | (this.readUint8() << 8) | (this.readUint8() << 16); + } /** @deprecated in 3.x. use [[readUint8]]. */ - public get nextUint8(): number { return this.readUint8(); } + public get nextUint8(): number { + return this.readUint8(); + } /** @deprecated in 3.x. use [[readUint16]]. */ - public get nextUint16(): number { return this.readUint16(); } + public get nextUint16(): number { + return this.readUint16(); + } /** @deprecated in 3.x. use [[readUint32]]. */ - public get nextUint32(): number { return this.readUint32(); } + public get nextUint32(): number { + return this.readUint32(); + } /** @deprecated in 3.x. use [[readInt32]]. */ - public get nextInt32(): number { return this.readInt32(); } + public get nextInt32(): number { + return this.readInt32(); + } /** @deprecated in 3.x. use [[readFloat32]]. */ - public get nextFloat32(): number { return this.readFloat32(); } + public get nextFloat32(): number { + return this.readFloat32(); + } /** @deprecated in 3.x. use [[readFloat64]]. */ - public get nextFloat64(): number { return this.readFloat64(); } + public get nextFloat64(): number { + return this.readFloat64(); + } /** @deprecated in 3.x. use [[readId64]]. */ - public get nextId64(): Id64String { return this.readId64(); } + public get nextId64(): Id64String { + return this.readId64(); + } /** @deprecated in 3.x. use [[readUint32]]. */ - public get nextUint24(): number { return this.readUint24(); } + public get nextUint24(): number { + return this.readUint24(); + } /** Read the specified number of bytes beginning at the current read position into a Uint8Array and advance by the specified number of byte. * @param numBytes The number of bytes to read. @@ -167,7 +203,9 @@ export class ByteStream { } /** Returns the underlying array buffer */ - public get arrayBuffer(): ArrayBuffer | SharedArrayBuffer { return this._view.buffer; } + public get arrayBuffer(): ArrayBuffer | SharedArrayBuffer { + return this._view.buffer; + } private read(numBytes: number, read: (view: DataView) => number) { const result = read(this._view); diff --git a/core/bentley/src/ClassUtils.ts b/core/bentley/src/ClassUtils.ts index c6bbfde8cc56..a0f79a658683 100644 --- a/core/bentley/src/ClassUtils.ts +++ b/core/bentley/src/ClassUtils.ts @@ -14,9 +14,9 @@ * @public */ export function isProperSubclassOf< - SuperClass extends new (..._: any[]) => any, - NonSubClass extends new (..._: any[]) => any, - SubClass extends new (..._: any[]) => InstanceType, + SuperClass extends new(..._: any[]) => any, + NonSubClass extends new(..._: any[]) => any, + SubClass extends new(..._: any[]) => InstanceType, >(subclass: SubClass | NonSubClass, superclass: SuperClass): subclass is SubClass { return subclass.prototype instanceof superclass; } @@ -29,9 +29,9 @@ export function isProperSubclassOf< * @public */ export function isSubclassOf< - SuperClass extends new (..._: any[]) => any, - NonSubClass extends new (..._: any[]) => any, - SubClass extends new (..._: any[]) => InstanceType, + SuperClass extends new(..._: any[]) => any, + NonSubClass extends new(..._: any[]) => any, + SubClass extends new(..._: any[]) => InstanceType, >(subclass: SuperClass | SubClass | NonSubClass, superclass: SuperClass): subclass is SubClass | SuperClass { return subclass === superclass || isProperSubclassOf(subclass, superclass); } diff --git a/core/bentley/src/CompressedId64Set.ts b/core/bentley/src/CompressedId64Set.ts index 3cd86c302212..eba9a3229684 100644 --- a/core/bentley/src/CompressedId64Set.ts +++ b/core/bentley/src/CompressedId64Set.ts @@ -155,11 +155,19 @@ export namespace CompressedId64Set { // eslint-disable-line @typescript-eslint/n return 0 === diff ? this.lower - rhs.lower : diff; } - public equals(rhs: Uint64): boolean { return 0 === this.compare(rhs); } - public isLessThan(rhs: Uint64): boolean { return this.compare(rhs) < 0; } - public isGreaterThan(rhs: Uint64): boolean { return this.compare(rhs) > 0; } + public equals(rhs: Uint64): boolean { + return 0 === this.compare(rhs); + } + public isLessThan(rhs: Uint64): boolean { + return this.compare(rhs) < 0; + } + public isGreaterThan(rhs: Uint64): boolean { + return this.compare(rhs) > 0; + } - public get isZero(): boolean { return 0 === this.lower && 0 === this.upper; } + public get isZero(): boolean { + return 0 === this.lower && 0 === this.upper; + } public setFromDifference(lhs: Uint64, rhs: Uint64): void { assert(!rhs.isGreaterThan(lhs)); @@ -232,7 +240,7 @@ export namespace CompressedId64Set { // eslint-disable-line @typescript-eslint/n break; // not a hex digit in [0..9] or [A..F] value <<= 4; - value |= (ch >= 65 ? ch - 65 + 10 : ch - 48); // ch - 'A' + 10 or ch - '0' + value |= ch >= 65 ? ch - 65 + 10 : ch - 48; // ch - 'A' + 10 or ch - '0' value = value >>> 0; // restore unsignedness because silly javascript. ++curIndex; } @@ -360,10 +368,14 @@ export class OrderedId64Array extends SortedArray { } /** An iterable that iterates over the Ids in sorted order. */ - public get ids(): OrderedId64Iterable { return this._array; } + public get ids(): OrderedId64Iterable { + return this._array; + } /** The underlying array of Ids. */ - public get array(): ReadonlyArray { return this._array; } + public get array(): ReadonlyArray { + return this._array; + } } /** A mutable set of valid [[Id64String]]s sorted in ascending order by the 64-bit unsigned integer value of the Ids. diff --git a/core/bentley/src/Dictionary.ts b/core/bentley/src/Dictionary.ts index 1a5c8fe475c9..7f2ecc496fb0 100644 --- a/core/bentley/src/Dictionary.ts +++ b/core/bentley/src/Dictionary.ts @@ -80,7 +80,9 @@ export class Dictionary implements Iterable> { } /** The number of entries in the dictionary. */ - public get size(): number { return this._keys.length; } + public get size(): number { + return this._keys.length; + } /** Returns an iterator over the key-value pairs in the Dictionary suitable for use in `for-of` loops. Entries are returned in sorted order by key. */ public [Symbol.iterator](): Iterator> { @@ -89,7 +91,7 @@ export class Dictionary implements Iterable> { /** Provides iteration over the keys in this Dictionary, in sorted order. */ public keys(): Iterable { - function * iterator(dict: Dictionary) { + function* iterator(dict: Dictionary) { for (const entry of dict) yield entry.key; } @@ -101,7 +103,7 @@ export class Dictionary implements Iterable> { /** Provides iteration over the values in this Dictionary, in sorted order by the corresponding keys. */ public values(): Iterable { - function * iterator(dict: Dictionary) { + function* iterator(dict: Dictionary) { for (const entry of dict) yield entry.value; } @@ -234,5 +236,7 @@ export class Dictionary implements Iterable> { * @param key The key whose position is to be computed. * @returns an object with 'index' corresponding to the computed position and 'equal' set to true if an equivalent key already exists at that index. */ - protected lowerBound(key: K): { index: number, equal: boolean } { return lowerBound(key, this._keys, this._compareKeys); } + protected lowerBound(key: K): { index: number, equal: boolean } { + return lowerBound(key, this._keys, this._compareKeys); + } } diff --git a/core/bentley/src/Disposable.ts b/core/bentley/src/Disposable.ts index 12570bdc598a..eb35f8053a52 100644 --- a/core/bentley/src/Disposable.ts +++ b/core/bentley/src/Disposable.ts @@ -110,8 +110,12 @@ export type DisposeFunc = () => void; class FuncDisposable implements IDisposable { private _disposeFunc: () => void; - constructor(disposeFunc: () => void) { this._disposeFunc = disposeFunc; } - public dispose() { this._disposeFunc(); } + constructor(disposeFunc: () => void) { + this._disposeFunc = disposeFunc; + } + public dispose() { + this._disposeFunc(); + } } /** A disposable container of disposable objects. diff --git a/core/bentley/src/Id.ts b/core/bentley/src/Id.ts index f35c7139edee..147ac645cdcb 100644 --- a/core/bentley/src/Id.ts +++ b/core/bentley/src/Id.ts @@ -128,7 +128,7 @@ export namespace Id64 { let high = 0; let start = 2; if (len > 12) { - start = (len - 10); + start = len - 10; high = toHex(val.slice(2, start)); } @@ -548,7 +548,9 @@ export namespace Id64 { } /** Returns true if the set contains the specified Id. */ - public hasId(id: Id64String): boolean { return this.has(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); } + public hasId(id: Id64String): boolean { + return this.has(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); + } /** Add an Id to the set. */ public add(low: number, high: number): void { @@ -591,7 +593,9 @@ export namespace Id64 { } /** Returns true if the set contains no Ids. */ - public get isEmpty(): boolean { return 0 === this._map.size; } + public get isEmpty(): boolean { + return 0 === this._map.size; + } /** Returns the number of Ids contained in the set. */ public get size(): number { @@ -638,11 +642,17 @@ export namespace Id64 { protected readonly _map = new Map>(); /** Remove all entries from the map. */ - public clear(): void { this._map.clear(); } + public clear(): void { + this._map.clear(); + } /** Find an entry in the map by Id. */ - public getById(id: Id64String): T | undefined { return this.get(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); } + public getById(id: Id64String): T | undefined { + return this.get(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); + } /** Set an entry in the map by Id. */ - public setById(id: Id64String, value: T): void { this.set(Id64.getLowerUint32(id), Id64.getUpperUint32(id), value); } + public setById(id: Id64String, value: T): void { + this.set(Id64.getLowerUint32(id), Id64.getUpperUint32(id), value); + } /** Set an entry in the map by Id components. */ public set(low: number, high: number, value: T): void { @@ -662,7 +672,9 @@ export namespace Id64 { } /** Returns true if the map contains no entries. */ - public get isEmpty(): boolean { return 0 === this._map.size; } + public get isEmpty(): boolean { + return 0 === this._map.size; + } /** Returns the number of entries in the map. */ public get size(): number { let size = 0; @@ -704,8 +716,8 @@ function validateLocalId(num: number): void { /** A function returned by [[TransientIdSequence.merge]] that remaps the local Id portion of an [Id64String]($docs/learning/common/Id64.md) generated by * the source sequence to the corresponding local Id in the target sequence. * It returns `sourceLocalId` if the input did not originate from the source sequence. -* @public -*/ + * @public + */ export type RemapTransientLocalId = (sourceLocalId: number) => number; /** @@ -869,9 +881,10 @@ export namespace Guid { const noDashValue = lowerValue.replace(/-/g, ""); const noDashPattern = /^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})$/; if (noDashPattern.test(noDashValue)) { - return noDashValue.replace(noDashPattern, - (_match: string, p1: string, p2: string, p3: string, p4: string, p5: string) => - `${p1}-${p2}-${p3}-${p4}-${p5}`); + return noDashValue.replace( + noDashPattern, + (_match: string, p1: string, p2: string, p3: string, p4: string, p5: string) => `${p1}-${p2}-${p3}-${p4}-${p5}`, + ); } // Return unmodified string - (note: it is *not* a valid Guid) diff --git a/core/bentley/src/IndexMap.ts b/core/bentley/src/IndexMap.ts index 27007e145a49..c941bbab5e64 100644 --- a/core/bentley/src/IndexMap.ts +++ b/core/bentley/src/IndexMap.ts @@ -47,16 +47,24 @@ export class IndexMap { } /** The number of elements in the map. */ - public get length(): number { return this._array.length; } + public get length(): number { + return this._array.length; + } /** Returns true if the maximum number of elements have been inserted. */ - public get isFull(): boolean { return this.length >= this._maximumSize; } + public get isFull(): boolean { + return this.length >= this._maximumSize; + } /** Returns true if the map contains no elements. */ - public get isEmpty(): boolean { return 0 === this.length; } + public get isEmpty(): boolean { + return 0 === this.length; + } /** Removes all elements from the map. */ - public clear(): void { this._array = []; } + public clear(): void { + this._array = []; + } /** Attempt to insert a new value into the map. * If an equivalent element already exists in the map, the corresponding index is returned. @@ -96,7 +104,9 @@ export class IndexMap { return bound.equal ? this._array[bound.index].index : -1; } - protected lowerBound(value: T): { index: number, equal: boolean } { return lowerBound(value, this._array, (lhs: T, rhs: IndexedValue) => this._compareValues(lhs, rhs.value)); } + protected lowerBound(value: T): { index: number, equal: boolean } { + return lowerBound(value, this._array, (lhs: T, rhs: IndexedValue) => this._compareValues(lhs, rhs.value)); + } /** Return an array of the elements in this map in which the array index of each element corresponds to the index assigned to it by the map. */ public toArray(): T[] { diff --git a/core/bentley/src/JsonUtils.ts b/core/bentley/src/JsonUtils.ts index 9f6a0c6165ef..94855e9d0b95 100644 --- a/core/bentley/src/JsonUtils.ts +++ b/core/bentley/src/JsonUtils.ts @@ -147,5 +147,4 @@ export namespace JsonUtils { return out; } - } diff --git a/core/bentley/src/LRUMap.ts b/core/bentley/src/LRUMap.ts index fa4062824edf..7ee8898d203b 100644 --- a/core/bentley/src/LRUMap.ts +++ b/core/bentley/src/LRUMap.ts @@ -21,7 +21,7 @@ import { Dictionary } from "./Dictionary"; export class Entry { public newer?: Entry; public older?: Entry; - constructor(public key: K, public value: V) { } + constructor(public key: K, public value: V) {} } class EntryIterator implements Iterator<[K, V] | undefined> { @@ -39,7 +39,7 @@ class EntryIterator implements Iterator<[K, V] | undefined> { } } -class KeyIterator implements Iterator { +class KeyIterator implements Iterator { private _entry: Entry | undefined; constructor(oldestEntry: Entry) { this._entry = oldestEntry; @@ -200,7 +200,7 @@ export class LRUCache { } // new entry - this._container.set(key, (entry = new Entry(key, value))); + this._container.set(key, entry = new Entry(key, value)); if (this.newest) { // link previous tail to the new tail (entry) diff --git a/core/bentley/src/Logger.ts b/core/bentley/src/Logger.ts index 02bc5fb8598f..28d6ed7dfacd 100644 --- a/core/bentley/src/Logger.ts +++ b/core/bentley/src/Logger.ts @@ -71,13 +71,13 @@ export class Logger { return Logger._onLogLevelChanged; } - private static _categoryFilter: {[categoryName: string]: LogLevel | undefined} = {}; + private static _categoryFilter: { [categoryName: string]: LogLevel | undefined } = {}; /** Maps category names to the least severe level at which messages in that category should be displayed, * or `undefined` if a minimum has not been defined. * @see [[setLevel]] to change the minimum logging level for a category. */ - public static get categoryFilter(): Readonly<{[categoryName: string]: LogLevel | undefined}> { + public static get categoryFilter(): Readonly<{ [categoryName: string]: LogLevel | undefined }> { // NOTE: this property is accessed by native code. return this._categoryFilter; } @@ -149,13 +149,20 @@ export class Logger { /** Interpret a string as the name of a LogLevel */ public static parseLogLevel(str: string): LogLevel { switch (str.toUpperCase()) { - case "EXCEPTION": return LogLevel.Error; - case "FATAL": return LogLevel.Error; - case "ERROR": return LogLevel.Error; - case "WARNING": return LogLevel.Warning; - case "INFO": return LogLevel.Info; - case "TRACE": return LogLevel.Trace; - case "DEBUG": return LogLevel.Trace; + case "EXCEPTION": + return LogLevel.Error; + case "FATAL": + return LogLevel.Error; + case "ERROR": + return LogLevel.Error; + case "WARNING": + return LogLevel.Warning; + case "INFO": + return LogLevel.Info; + case "TRACE": + return LogLevel.Trace; + case "DEBUG": + return LogLevel.Trace; } return LogLevel.None; } @@ -185,16 +192,27 @@ export class Logger { throw new BentleyError(IModelStatus.BadArg, `LoggerLevelsConfig - unrecognized property: ${prop}`); if (prop === "defaultLevel") { if (!Logger.isLogLevel(config.defaultLevel)) - throw new BentleyError(IModelStatus.BadArg, `LoggerLevelsConfig.defaultLevel must be a LogLevel. Invalid value: ${JSON.stringify(config.defaultLevel)}`); + throw new BentleyError( + IModelStatus.BadArg, + `LoggerLevelsConfig.defaultLevel must be a LogLevel. Invalid value: ${JSON.stringify(config.defaultLevel)}`, + ); } else if (prop === "categoryLevels") { const value = config[prop]; if (!Array.isArray(value)) throw new BentleyError(IModelStatus.BadArg, `LoggerLevelsConfig.categoryLevels must be an array. Invalid value: ${JSON.stringify(value)}`); for (const item of config[prop]) { if (!item.hasOwnProperty("category") || !item.hasOwnProperty("logLevel")) - throw new BentleyError(IModelStatus.BadArg, `LoggerLevelsConfig.categoryLevels - each item must be a LoggerCategoryAndLevel {category: logLevel:}. Invalid value: ${JSON.stringify(item)}`); + throw new BentleyError( + IModelStatus.BadArg, + `LoggerLevelsConfig.categoryLevels - each item must be a LoggerCategoryAndLevel {category: logLevel:}. Invalid value: ${ + JSON.stringify(item) + }`, + ); if (!Logger.isLogLevel(item.logLevel)) - throw new BentleyError(IModelStatus.BadArg, `LoggerLevelsConfig.categoryLevels - each item's logLevel property must be a LogLevel. Invalid value: ${JSON.stringify(item.logLevel)}`); + throw new BentleyError( + IModelStatus.BadArg, + `LoggerLevelsConfig.categoryLevels - each item's logLevel property must be a LogLevel. Invalid value: ${JSON.stringify(item.logLevel)}`, + ); } } } @@ -261,9 +279,13 @@ export class Logger { * @param err The exception object. * @param log The logger output function to use - defaults to Logger.logError */ - public static logException(category: string, err: any, log: LogFunction = (_category, message, metaData) => Logger.logError(_category, message, metaData)): void { + public static logException( + category: string, + err: any, + log: LogFunction = (_category, message, metaData) => Logger.logError(_category, message, metaData), + ): void { log(category, Logger.getExceptionMessage(err), () => { - return { ...BentleyError.getErrorMetadata(err), exceptionType: err?.constructor?.name ?? ""}; + return { ...BentleyError.getErrorMetadata(err), exceptionType: err?.constructor?.name ?? "" }; }); } @@ -335,7 +357,8 @@ export class PerfLogger implements IDisposable { Logger.logInfo(BentleyLoggerCategory.Performance, `${this._operation},END`, () => { const mdata = this._metaData ? BentleyError.getMetaData(this._metaData) : {}; return { - ...mdata, TimeElapsed: endTimeStamp - this._startTimeStamp, // eslint-disable-line @typescript-eslint/naming-convention + ...mdata, + TimeElapsed: endTimeStamp - this._startTimeStamp, // eslint-disable-line @typescript-eslint/naming-convention }; }); } @@ -344,4 +367,3 @@ export class PerfLogger implements IDisposable { this.logMessage(); } } - diff --git a/core/bentley/src/OneAtATimeAction.ts b/core/bentley/src/OneAtATimeAction.ts index a8a771da134a..1122069bcb09 100644 --- a/core/bentley/src/OneAtATimeAction.ts +++ b/core/bentley/src/OneAtATimeAction.ts @@ -9,7 +9,7 @@ import { BentleyError } from "./BentleyError"; /** @beta */ -export class AbandonedError extends Error { } +export class AbandonedError extends Error {} /** * An object that returns a Promise when you call [[init]], but supplies a way to abandon the promise if it is no longer relevant. @@ -26,7 +26,7 @@ class PromiseWithAbandon { * @param _run The method that creates the underlying Promise. * @param _args An array of args to be passed to run when [[start]] is called. */ - constructor(private _run: (...args: any[]) => Promise, private _args: any[]) { } + constructor(private _run: (...args: any[]) => Promise, private _args: any[]) {} /** Create a Promise that is chained to the underlying Promise, but is connected to the abandon method. */ public async init(msg: string): Promise { diff --git a/core/bentley/src/PriorityQueue.ts b/core/bentley/src/PriorityQueue.ts index 84d3fed66686..ff2d07ab80aa 100644 --- a/core/bentley/src/PriorityQueue.ts +++ b/core/bentley/src/PriorityQueue.ts @@ -34,13 +34,19 @@ export class PriorityQueue implements Iterable { } /** The number of values in the queue. */ - public get length(): number { return this._array.length; } + public get length(): number { + return this._array.length; + } /** Returns true if the queue contains no values. */ - public get isEmpty(): boolean { return 0 === this.length; } + public get isEmpty(): boolean { + return 0 === this.length; + } /** Returns an iterator over the contents of the heap suitable for use in `for-of` loops. */ - public [Symbol.iterator](): Iterator { return this._array[Symbol.iterator](); } + public [Symbol.iterator](): Iterator { + return this._array[Symbol.iterator](); + } protected _swap(a: number, b: number) { const temp = this._array[a]; diff --git a/core/bentley/src/ProcessDetector.ts b/core/bentley/src/ProcessDetector.ts index 6802040bf460..4e5e4f149be7 100644 --- a/core/bentley/src/ProcessDetector.ts +++ b/core/bentley/src/ProcessDetector.ts @@ -10,76 +10,108 @@ * @public */ export class ProcessDetector { - /** Is this a browser process? * @note this method will also return `true` for the frontend of Electron or Mobile apps. They *are* browser processes. */ - public static get isBrowserProcess() { return typeof window === "object" && typeof window.navigator === "object"; } + public static get isBrowserProcess() { + return typeof window === "object" && typeof window.navigator === "object"; + } /** Is this a Node process? * @note this means "is this a backend process"? It will return `true` for all backend process, including Electron and mobile apps. - */ - public static get isNodeProcess() { return typeof process === "object" && undefined !== process.platform; } + */ + public static get isNodeProcess() { + return typeof process === "object" && undefined !== process.platform; + } /** Is this process the frontend of an Electron app? */ - public static get isElectronAppFrontend() { return typeof navigator === "object" && navigator.userAgent.toLowerCase().indexOf("electron") >= 0; } + public static get isElectronAppFrontend() { + return typeof navigator === "object" && navigator.userAgent.toLowerCase().indexOf("electron") >= 0; + } /** Is this process the backend of an Electron app? */ - public static get isElectronAppBackend() { return typeof process === "object" && process.versions.hasOwnProperty("electron"); } + public static get isElectronAppBackend() { + return typeof process === "object" && process.versions.hasOwnProperty("electron"); + } /** Is this process running in a browser on an iPad? * @note This method will return `true` for any frontend running on an iPad, whether it is a user-launched web browser (e.g. Safari) or the frontend of a mobile app. */ public static get isIPadBrowser() { - return this.isBrowserProcess && window.navigator.platform === "iPad" || (window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 0 && !("MSStream" in window)); /* eslint-disable-line deprecation/deprecation */ + return this.isBrowserProcess && window.navigator.platform === "iPad" || + (window.navigator.platform === "MacIntel" && window.navigator.maxTouchPoints > 0 && + !("MSStream" in window)); /* eslint-disable-line deprecation/deprecation */ } /** Is this process running in a browser on an iPhone? * @note This method will return `true` for any frontend running on an iPhone, whether it is a user-launched web browser (e.g. Safari) or the frontend of a mobile app. */ - public static get isIPhoneBrowser() { return this.isBrowserProcess && (/(iphone|ipod)/i.test(window.navigator.userAgent)); } + public static get isIPhoneBrowser() { + return this.isBrowserProcess && (/(iphone|ipod)/i.test(window.navigator.userAgent)); + } /** Is this process running in a browser on an iOS device? * @note This method will return `true` for any frontend running on an iOS device, whether it is a user-launched web browser (e.g. Safari) or the frontend of a mobile app. - */ - public static get isIOSBrowser() { return this.isIPadBrowser || this.isIPhoneBrowser; } + */ + public static get isIOSBrowser() { + return this.isIPadBrowser || this.isIPhoneBrowser; + } /** Is this process running in a browser on an Android device? * @note This method will return `true` for any frontend running on an Android device, whether it is a user-launched web browser (e.g. Chrome) or the frontend of a mobile app. - */ - public static get isAndroidBrowser() { return this.isBrowserProcess && /android/i.test(window.navigator.userAgent); } + */ + public static get isAndroidBrowser() { + return this.isBrowserProcess && /android/i.test(window.navigator.userAgent); + } /** Is this process running in a browser on a mobile device? * @note This method will return `true` for any frontend running on a mobile device, whether it is a user-launched web browser or the frontend of a mobile app. - */ - public static get isMobileBrowser() { return this.isIOSBrowser || this.isAndroidBrowser; } + */ + public static get isMobileBrowser() { + return this.isIOSBrowser || this.isAndroidBrowser; + } /** Is this process running in a Chromium based browser (Chrome / new Edge / Electron front end)? */ public static get isChromium() { - return (this.isBrowserProcess && window.navigator.userAgent.indexOf("Chrome") > -1 && window.navigator.userAgent.indexOf("OP") === -1) || this.isElectronAppFrontend; + return (this.isBrowserProcess && window.navigator.userAgent.indexOf("Chrome") > -1 && window.navigator.userAgent.indexOf("OP") === -1) || + this.isElectronAppFrontend; } /** Is this process the frontend of an iTwin mobile application? * @note this indicates that this is a browser process started by an iTwin mobile application. * It will return `false` when running user-launched web browsers on a mobile device. */ - public static get isMobileAppFrontend() { return this.isAndroidAppFrontend || this.isIOSAppFrontend; } + public static get isMobileAppFrontend() { + return this.isAndroidAppFrontend || this.isIOSAppFrontend; + } /** Is this process the frontend of an iOS mobile application? */ - public static get isIOSAppFrontend() { return this.isBrowserProcess && window.location.hash.indexOf("platform=ios") !== -1; } + public static get isIOSAppFrontend() { + return this.isBrowserProcess && window.location.hash.indexOf("platform=ios") !== -1; + } /** Is this process the frontend of an Android mobile application? */ - public static get isAndroidAppFrontend() { return this.isBrowserProcess && window.location.hash.indexOf("platform=android") !== -1; } + public static get isAndroidAppFrontend() { + return this.isBrowserProcess && window.location.hash.indexOf("platform=android") !== -1; + } /** Is this process the backend of an iOS mobile application? */ - public static get isIOSAppBackend() { return this.isNodeProcess && (process.platform as any) === "ios"; } + public static get isIOSAppBackend() { + return this.isNodeProcess && (process.platform as any) === "ios"; + } /** Is this process the backend of an Android mobile application? */ - public static get isAndroidAppBackend() { return this.isNodeProcess && (process.platform as any) === "android"; } + public static get isAndroidAppBackend() { + return this.isNodeProcess && (process.platform as any) === "android"; + } /** Is this process a mobile app backend? */ - public static get isMobileAppBackend() { return this.isIOSAppBackend || this.isAndroidAppBackend; } + public static get isMobileAppBackend() { + return this.isIOSAppBackend || this.isAndroidAppBackend; + } /** Is this process the frontend of a native (Electron or Mobile) app? */ - public static get isNativeAppFrontend() { return this.isElectronAppFrontend || this.isMobileAppFrontend; } + public static get isNativeAppFrontend() { + return this.isElectronAppFrontend || this.isMobileAppFrontend; + } } diff --git a/core/bentley/src/SortedArray.ts b/core/bentley/src/SortedArray.ts index 6f298d03cb56..c043944db18f 100644 --- a/core/bentley/src/SortedArray.ts +++ b/core/bentley/src/SortedArray.ts @@ -115,13 +115,19 @@ export class ReadonlySortedArray implements Iterable { } /** The number of elements in the array */ - public get length(): number { return this._array.length; } + public get length(): number { + return this._array.length; + } /** Returns true if the array contains no elements. */ - public get isEmpty(): boolean { return 0 === this.length; } + public get isEmpty(): boolean { + return 0 === this.length; + } /** Returns an iterator over the contents of the array in sorted order, suitable for use in `for-of` loops. */ - public [Symbol.iterator](): Iterator { return this._array[Symbol.iterator](); } + public [Symbol.iterator](): Iterator { + return this._array[Symbol.iterator](); + } /** * Looks up the index of an element comparing equal to the specified value using binary search. @@ -183,7 +189,9 @@ export class ReadonlySortedArray implements Iterable { * @param index The array index * @returns the element corresponding to that position in the array, or undefined if the supplied index exceeds the length of the array. */ - public get(index: number): T | undefined { return index < this.length ? this._array[index] : undefined; } + public get(index: number): T | undefined { + return index < this.length ? this._array[index] : undefined; + } /** Apply a function to each element in the array, in sorted order. * @param func The function to be applied. @@ -205,10 +213,14 @@ export class ReadonlySortedArray implements Iterable { * @param value The value whose position is to be computed. * @returns an object with 'index' corresponding to the computed position and 'equal' set to true if an equivalent element already exists at that index. */ - protected lowerBound(value: T): { index: number, equal: boolean } { return lowerBound(value, this._array, this._compare); } + protected lowerBound(value: T): { index: number, equal: boolean } { + return lowerBound(value, this._array, this._compare); + } /** Clears the contents of the sorted array. */ - protected _clear(): void { this._array.length = 0; } + protected _clear(): void { + this._array.length = 0; + } /** Extracts the sorted array as a T[] and empties the contents of this ReadonlySortedArray. * @returns the contents of this ReadonlySortedArray as a T[]. @@ -312,12 +324,16 @@ export class SortedArray extends ReadonlySortedArray { } /** Clears the contents of the sorted array. */ - public clear(): void { this._clear(); } + public clear(): void { + this._clear(); + } /** Extracts the sorted array as a T[] and empties the contents of this SortedArray. * @returns the contents of this SortedArray as a T[]. */ - public extractArray(): T[] { return this._extractArray(); } + public extractArray(): T[] { + return this._extractArray(); + } /** * Attempts to insert a new value into the array at a position determined by the ordering. @@ -334,14 +350,18 @@ export class SortedArray extends ReadonlySortedArray { * @param onInsert The optional callback method to call if insertion occurs with the inserted value * @returns the index in the array of the newly-inserted value, or, if duplicates are not permitted and an equivalent value already exists, the index of the equivalent value. */ - public insert(value: T, onInsert?: (value: T) => any): number { return this._insert(value, onInsert); } + public insert(value: T, onInsert?: (value: T) => any): number { + return this._insert(value, onInsert); + } /** * Removes the first occurrence of a value comparing equal to the specified value from the array. * @param value The value of the element to delete * @returns the index of the deleted value, or -1 if no such element exists. */ - public remove(value: T): number { return this._remove(value); } + public remove(value: T): number { + return this._remove(value); + } /** The equivalent of [Array.slice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice). */ public override slice(start?: number, end?: number): SortedArray { diff --git a/core/bentley/src/StatusCategory.ts b/core/bentley/src/StatusCategory.ts index e2ebb10f1e04..32fcce8c2122 100644 --- a/core/bentley/src/StatusCategory.ts +++ b/core/bentley/src/StatusCategory.ts @@ -68,285 +68,539 @@ export abstract class ErrorCategory extends StatusCategory { } namespace HTTP { - export class OK extends SuccessCategory { public name = "OK"; public code = 200; } - export class Accepted extends SuccessCategory { public name = "Accepted"; public code = 202; } - export class NoContent extends SuccessCategory { public name = "NoContent"; public code = 204; } - - export class BadRequest extends ErrorCategory { public name = "BadRequest"; public code = 400; } - export class Unauthorized extends ErrorCategory { public name = "Unauthorized"; public code = 401; } - export class Forbidden extends ErrorCategory { public name = "Forbidden"; public code = 403; } - export class NotFound extends ErrorCategory { public name = "NotFound"; public code = 404; } - export class RequestTimeout extends ErrorCategory { public name = "RequestTimeout"; public code = 408; } - export class Conflict extends ErrorCategory { public name = "Conflict"; public code = 409; } - export class Gone extends ErrorCategory { public name = "Gone"; public code = 410; } - export class PreconditionFailed extends ErrorCategory { public name = "PreconditionFailed"; public code = 412; } - export class ExpectationFailed extends ErrorCategory { public name = "ExpectationFailed"; public code = 417; } - export class MisdirectedRequest extends ErrorCategory { public name = "MisdirectedRequest"; public code = 421; } - export class UnprocessableEntity extends ErrorCategory { public name = "UnprocessableEntity"; public code = 422; } - export class UpgradeRequired extends ErrorCategory { public name = "UpgradeRequired"; public code = 426; } - export class PreconditionRequired extends ErrorCategory { public name = "PreconditionRequired"; public code = 428; } - export class TooManyRequests extends ErrorCategory { public name = "TooManyRequests"; public code = 429; } - - export class InternalServerError extends ErrorCategory { public name = "InternalServerError"; public code = 500; } - export class NotImplemented extends ErrorCategory { public name = "NotImplemented"; public code = 501; } + export class OK extends SuccessCategory { + public name = "OK"; + public code = 200; + } + export class Accepted extends SuccessCategory { + public name = "Accepted"; + public code = 202; + } + export class NoContent extends SuccessCategory { + public name = "NoContent"; + public code = 204; + } + + export class BadRequest extends ErrorCategory { + public name = "BadRequest"; + public code = 400; + } + export class Unauthorized extends ErrorCategory { + public name = "Unauthorized"; + public code = 401; + } + export class Forbidden extends ErrorCategory { + public name = "Forbidden"; + public code = 403; + } + export class NotFound extends ErrorCategory { + public name = "NotFound"; + public code = 404; + } + export class RequestTimeout extends ErrorCategory { + public name = "RequestTimeout"; + public code = 408; + } + export class Conflict extends ErrorCategory { + public name = "Conflict"; + public code = 409; + } + export class Gone extends ErrorCategory { + public name = "Gone"; + public code = 410; + } + export class PreconditionFailed extends ErrorCategory { + public name = "PreconditionFailed"; + public code = 412; + } + export class ExpectationFailed extends ErrorCategory { + public name = "ExpectationFailed"; + public code = 417; + } + export class MisdirectedRequest extends ErrorCategory { + public name = "MisdirectedRequest"; + public code = 421; + } + export class UnprocessableEntity extends ErrorCategory { + public name = "UnprocessableEntity"; + public code = 422; + } + export class UpgradeRequired extends ErrorCategory { + public name = "UpgradeRequired"; + public code = 426; + } + export class PreconditionRequired extends ErrorCategory { + public name = "PreconditionRequired"; + public code = 428; + } + export class TooManyRequests extends ErrorCategory { + public name = "TooManyRequests"; + public code = 429; + } + + export class InternalServerError extends ErrorCategory { + public name = "InternalServerError"; + public code = 500; + } + export class NotImplemented extends ErrorCategory { + public name = "NotImplemented"; + public code = 501; + } } -class Success extends HTTP.OK { } +class Success extends HTTP.OK {} -class Pending extends HTTP.Accepted { } +class Pending extends HTTP.Accepted {} -class NoContent extends HTTP.NoContent { } -class NothingToDo extends HTTP.NoContent { } +class NoContent extends HTTP.NoContent {} +class NothingToDo extends HTTP.NoContent {} -class BadRequest extends HTTP.BadRequest { } +class BadRequest extends HTTP.BadRequest {} -class Forbidden extends HTTP.Forbidden { } -class PermissionsViolation extends HTTP.Forbidden { } -class ReadOnly extends HTTP.Forbidden { } +class Forbidden extends HTTP.Forbidden {} +class PermissionsViolation extends HTTP.Forbidden {} +class ReadOnly extends HTTP.Forbidden {} -class NotFound extends HTTP.NotFound { } +class NotFound extends HTTP.NotFound {} -class NotEnabled extends HTTP.UnprocessableEntity { } -class NotSupported extends HTTP.UnprocessableEntity { } +class NotEnabled extends HTTP.UnprocessableEntity {} +class NotSupported extends HTTP.UnprocessableEntity {} -class ValidationError extends HTTP.BadRequest { } +class ValidationError extends HTTP.BadRequest {} -class Timeout extends HTTP.RequestTimeout { } +class Timeout extends HTTP.RequestTimeout {} -class Conflict extends HTTP.Conflict { } +class Conflict extends HTTP.Conflict {} -class Cancelled extends HTTP.Gone { } +class Cancelled extends HTTP.Gone {} -class ConstraintViolation extends HTTP.Forbidden { } -class VersioningViolation extends HTTP.Forbidden { } +class ConstraintViolation extends HTTP.Forbidden {} +class VersioningViolation extends HTTP.Forbidden {} -class Corruption extends HTTP.InternalServerError { } -class InvalidData extends HTTP.InternalServerError { } -class OperationFailed extends HTTP.InternalServerError { } -class StateViolation extends HTTP.InternalServerError { } +class Corruption extends HTTP.InternalServerError {} +class InvalidData extends HTTP.InternalServerError {} +class OperationFailed extends HTTP.InternalServerError {} +class StateViolation extends HTTP.InternalServerError {} -class Locked extends HTTP.Conflict { } +class Locked extends HTTP.Conflict {} -class NetworkError extends HTTP.InternalServerError { } +class NetworkError extends HTTP.InternalServerError {} -class Throttled extends HTTP.TooManyRequests { } +class Throttled extends HTTP.TooManyRequests {} -class FileSystemError extends HTTP.InternalServerError { } -class InternalError extends HTTP.InternalServerError { } -class UnknownError extends HTTP.InternalServerError { } +class FileSystemError extends HTTP.InternalServerError {} +class InternalError extends HTTP.InternalServerError {} +class UnknownError extends HTTP.InternalServerError {} -class NotImplemented extends HTTP.NotImplemented { } +class NotImplemented extends HTTP.NotImplemented {} -class Aborted extends HTTP.BadRequest { } +class Aborted extends HTTP.BadRequest {} function lookupHttpStatusCategory(statusCode: number): StatusCategory { switch (statusCode) { - case BentleyStatus.SUCCESS: return new Success(); - case BentleyStatus.ERROR: return new UnknownError(); - - case IModelStatus.Success: return new Success(); - case IModelStatus.AlreadyLoaded: return new StateViolation(); - case IModelStatus.AlreadyOpen: return new StateViolation(); - case IModelStatus.BadArg: return new ValidationError(); - case IModelStatus.BadElement: return new ValidationError(); - case IModelStatus.BadModel: return new ValidationError(); - case IModelStatus.BadRequest: return new BadRequest(); - case IModelStatus.BadSchema: return new ValidationError(); - case IModelStatus.CannotUndo: return new OperationFailed(); - case IModelStatus.CodeNotReserved: return new StateViolation(); - case IModelStatus.DeletionProhibited: return new Forbidden(); - case IModelStatus.DuplicateCode: return new Conflict(); - case IModelStatus.DuplicateName: return new Conflict(); - case IModelStatus.ElementBlockedChange: return new ConstraintViolation(); - case IModelStatus.FileAlreadyExists: return new Conflict(); - case IModelStatus.FileNotFound: return new NotFound(); - case IModelStatus.FileNotLoaded: return new FileSystemError(); - case IModelStatus.ForeignKeyConstraint: return new ConstraintViolation(); - case IModelStatus.IdExists: return new Conflict(); - case IModelStatus.InDynamicTransaction: return new StateViolation(); - case IModelStatus.InvalidCategory: return new ValidationError(); - case IModelStatus.InvalidCode: return new ValidationError(); - case IModelStatus.InvalidCodeSpec: return new ValidationError(); - case IModelStatus.InvalidId: return new ValidationError(); - case IModelStatus.InvalidName: return new ValidationError(); - case IModelStatus.InvalidParent: return new Conflict(); - case IModelStatus.InvalidProfileVersion: return new InvalidData(); - case IModelStatus.IsCreatingChangeSet: return new StateViolation(); - case IModelStatus.LockNotHeld: return new Forbidden(); - case IModelStatus.Mismatch2d3d: return new ValidationError(); - case IModelStatus.MismatchGcs: return new ValidationError(); - case IModelStatus.MissingDomain: return new ValidationError(); - case IModelStatus.MissingHandler: return new ValidationError(); - case IModelStatus.MissingId: return new ValidationError(); - case IModelStatus.NoGeometry: return new NoContent(); - case IModelStatus.NoMultiTxnOperation: return new StateViolation(); - case IModelStatus.NotEnabled: return new NotEnabled(); - case IModelStatus.NotFound: return new NotFound(); - case IModelStatus.NotOpen: return new StateViolation(); - case IModelStatus.NotOpenForWrite: return new Forbidden(); - case IModelStatus.NotSameUnitBase: return new ValidationError(); - case IModelStatus.NothingToRedo: return new NothingToDo(); - case IModelStatus.NothingToUndo: return new NothingToDo(); - case IModelStatus.ParentBlockedChange: return new Forbidden(); - case IModelStatus.ReadError: return new FileSystemError(); - case IModelStatus.ReadOnly: return new ReadOnly(); - case IModelStatus.ReadOnlyDomain: return new ReadOnly(); - case IModelStatus.RepositoryManagerError: return new NetworkError(); - case IModelStatus.SQLiteError: return new InternalError(); - case IModelStatus.TransactionActive: return new StateViolation(); - case IModelStatus.UnitsMissing: return new ValidationError(); - case IModelStatus.UnknownFormat: return new InvalidData(); - case IModelStatus.UpgradeFailed: return new OperationFailed(); - case IModelStatus.ValidationFailed: return new ValidationError(); - case IModelStatus.VersionTooNew: return new VersioningViolation(); - case IModelStatus.VersionTooOld: return new VersioningViolation(); - case IModelStatus.ViewNotFound: return new NotFound(); - case IModelStatus.WriteError: return new FileSystemError(); - case IModelStatus.WrongClass: return new ValidationError(); - case IModelStatus.WrongIModel: return new ValidationError(); - case IModelStatus.WrongDomain: return new ValidationError(); - case IModelStatus.WrongElement: return new ValidationError(); - case IModelStatus.WrongHandler: return new ValidationError(); - case IModelStatus.WrongModel: return new ValidationError(); - case IModelStatus.ConstraintNotUnique: return new ConstraintViolation(); - case IModelStatus.NoGeoLocation: return new ValidationError(); - case IModelStatus.ServerTimeout: return new Timeout(); - case IModelStatus.NoContent: return new NoContent(); - case IModelStatus.NotRegistered: return new NotImplemented(); - case IModelStatus.FunctionNotFound: return new NotImplemented(); - case IModelStatus.NoActiveCommand: return new StateViolation(); - case IModelStatus.Aborted: return new Aborted(); - - case BriefcaseStatus.CannotAcquire: return new OperationFailed(); - case BriefcaseStatus.CannotDownload: return new OperationFailed(); - case BriefcaseStatus.CannotUpload: return new OperationFailed(); - case BriefcaseStatus.CannotCopy: return new OperationFailed(); - case BriefcaseStatus.CannotDelete: return new OperationFailed(); - case BriefcaseStatus.VersionNotFound: return new NotFound(); - case BriefcaseStatus.CannotApplyChanges: return new OperationFailed(); - case BriefcaseStatus.DownloadCancelled: return new Cancelled(); - case BriefcaseStatus.ContainsDeletedChangeSets: return new ValidationError(); - - case RpcInterfaceStatus.Success: return new Success(); - case RpcInterfaceStatus.IncompatibleVersion: return new VersioningViolation(); - - case ChangeSetStatus.Success: return new Success(); - case ChangeSetStatus.ApplyError: return new OperationFailed(); - case ChangeSetStatus.ChangeTrackingNotEnabled: return new NotEnabled(); - case ChangeSetStatus.CorruptedChangeStream: return new Corruption(); - case ChangeSetStatus.FileNotFound: return new NotFound(); - case ChangeSetStatus.FileWriteError: return new FileSystemError(); - case ChangeSetStatus.HasLocalChanges: return new StateViolation(); - case ChangeSetStatus.HasUncommittedChanges: return new StateViolation(); - case ChangeSetStatus.InvalidId: return new Corruption(); - case ChangeSetStatus.InvalidVersion: return new Corruption(); - case ChangeSetStatus.InDynamicTransaction: return new StateViolation(); - case ChangeSetStatus.IsCreatingChangeSet: return new StateViolation(); - case ChangeSetStatus.IsNotCreatingChangeSet: return new StateViolation(); - case ChangeSetStatus.MergePropagationError: return new OperationFailed(); - case ChangeSetStatus.NothingToMerge: return new NothingToDo(); - case ChangeSetStatus.NoTransactions: return new OperationFailed(); - case ChangeSetStatus.ParentMismatch: return new ValidationError(); - case ChangeSetStatus.SQLiteError: return new InternalError(); - case ChangeSetStatus.WrongDgnDb: return new ValidationError(); - case ChangeSetStatus.CouldNotOpenDgnDb: return new OperationFailed(); - case ChangeSetStatus.MergeSchemaChangesOnOpen: return new BadRequest(); - case ChangeSetStatus.ReverseOrReinstateSchemaChanges: return new Conflict(); - case ChangeSetStatus.ProcessSchemaChangesOnOpen: return new BadRequest(); - case ChangeSetStatus.CannotMergeIntoReadonly: return new ValidationError(); - case ChangeSetStatus.CannotMergeIntoMaster: return new ValidationError(); - case ChangeSetStatus.CannotMergeIntoReversed: return new ValidationError(); - - case RepositoryStatus.Success: return new Success(); - case RepositoryStatus.ServerUnavailable: return new NetworkError(); - case RepositoryStatus.LockAlreadyHeld: return new Conflict(); - case RepositoryStatus.SyncError: return new NetworkError(); - case RepositoryStatus.InvalidResponse: return new NetworkError(); - case RepositoryStatus.PendingTransactions: return new StateViolation(); - case RepositoryStatus.LockUsed: return new StateViolation(); - case RepositoryStatus.CannotCreateChangeSet: return new InternalError(); - case RepositoryStatus.InvalidRequest: return new NetworkError(); - case RepositoryStatus.ChangeSetRequired: return new StateViolation(); - case RepositoryStatus.CodeUnavailable: return new Conflict(); - case RepositoryStatus.CodeNotReserved: return new StateViolation(); - case RepositoryStatus.CodeUsed: return new StateViolation(); - case RepositoryStatus.LockNotHeld: return new Forbidden(); - case RepositoryStatus.RepositoryIsLocked: return new Locked(); - case RepositoryStatus.ChannelConstraintViolation: return new ConstraintViolation(); - - case HttpStatus.Success: return new Success(); - - case IModelHubStatus.Success: return new Success(); - case IModelHubStatus.Unknown: return new UnknownError(); - case IModelHubStatus.MissingRequiredProperties: return new ValidationError(); - case IModelHubStatus.InvalidPropertiesValues: return new ValidationError(); - case IModelHubStatus.UserDoesNotHavePermission: return new PermissionsViolation(); - case IModelHubStatus.UserDoesNotHaveAccess: return new PermissionsViolation(); - case IModelHubStatus.InvalidBriefcase: return new ValidationError(); - case IModelHubStatus.BriefcaseDoesNotExist: return new NotFound(); - case IModelHubStatus.BriefcaseDoesNotBelongToUser: return new PermissionsViolation(); - case IModelHubStatus.AnotherUserPushing: return new StateViolation(); - case IModelHubStatus.ChangeSetAlreadyExists: return new Conflict(); - case IModelHubStatus.ChangeSetDoesNotExist: return new NotFound(); - case IModelHubStatus.FileIsNotUploaded: return new StateViolation(); - case IModelHubStatus.iModelIsNotInitialized: return new StateViolation(); - case IModelHubStatus.ChangeSetPointsToBadSeed: return new InvalidData(); - case IModelHubStatus.OperationFailed: return new OperationFailed(); - case IModelHubStatus.PullIsRequired: return new StateViolation(); - case IModelHubStatus.MaximumNumberOfBriefcasesPerUser: return new Throttled(); - case IModelHubStatus.MaximumNumberOfBriefcasesPerUserPerMinute: return new Throttled(); - case IModelHubStatus.DatabaseTemporarilyLocked: return new Locked(); - case IModelHubStatus.iModelIsLocked: return new Locked(); - case IModelHubStatus.CodesExist: return new Conflict(); - case IModelHubStatus.LocksExist: return new Conflict(); - case IModelHubStatus.iModelAlreadyExists: return new Conflict(); - case IModelHubStatus.iModelDoesNotExist: return new NotFound(); - case IModelHubStatus.FileDoesNotExist: return new NotFound(); - case IModelHubStatus.FileAlreadyExists: return new Conflict(); - case IModelHubStatus.LockDoesNotExist: return new NotFound(); - case IModelHubStatus.LockOwnedByAnotherBriefcase: return new Conflict(); - case IModelHubStatus.CodeStateInvalid: return new StateViolation(); - case IModelHubStatus.CodeReservedByAnotherBriefcase: return new Conflict(); - case IModelHubStatus.CodeDoesNotExist: return new NotFound(); - case IModelHubStatus.EventTypeDoesNotExist: return new NotFound(); - case IModelHubStatus.EventSubscriptionDoesNotExist: return new NotFound(); - case IModelHubStatus.EventSubscriptionAlreadyExists: return new StateViolation(); - case IModelHubStatus.ITwinIdIsNotSpecified: return new ValidationError(); - case IModelHubStatus.FailedToGetITwinPermissions: return new OperationFailed(); - case IModelHubStatus.FailedToGetITwinMembers: return new OperationFailed(); - case IModelHubStatus.ChangeSetAlreadyHasVersion: return new Conflict(); - case IModelHubStatus.VersionAlreadyExists: return new Conflict(); - case IModelHubStatus.JobSchedulingFailed: return new InternalError(); - case IModelHubStatus.ConflictsAggregate: return new Conflict(); - case IModelHubStatus.FailedToGetITwinById: return new OperationFailed(); - case IModelHubStatus.DatabaseOperationFailed: return new OperationFailed(); - case IModelHubStatus.SeedFileInitializationFailed: return new OperationFailed(); - case IModelHubStatus.FailedToGetAssetPermissions: return new OperationFailed(); - case IModelHubStatus.FailedToGetAssetMembers: return new OperationFailed(); - case IModelHubStatus.ITwinDoesNotExist: return new NotFound(); - case IModelHubStatus.LockChunkDoesNotExist: return new NotFound(); - case IModelHubStatus.CheckpointAlreadyExists: return new Conflict(); - case IModelHubStatus.CheckpointDoesNotExist: return new NotFound(); - case IModelHubStatus.UndefinedArgumentError: return new ValidationError(); - case IModelHubStatus.InvalidArgumentError: return new ValidationError(); - case IModelHubStatus.MissingDownloadUrlError: return new ValidationError(); - case IModelHubStatus.NotSupportedInBrowser: return new NotSupported(); - case IModelHubStatus.FileHandlerNotSet: return new NotImplemented(); - case IModelHubStatus.FileNotFound: return new NotFound(); - case IModelHubStatus.InitializationTimeout: return new Timeout(); - - case GeoServiceStatus.Success: return new Success(); - case GeoServiceStatus.NoGeoLocation: return new ValidationError(); - case GeoServiceStatus.OutOfUsefulRange: return new ValidationError(); - case GeoServiceStatus.OutOfMathematicalDomain: return new ValidationError(); - case GeoServiceStatus.NoDatumConverter: return new OperationFailed(); - case GeoServiceStatus.VerticalDatumConvertError: return new OperationFailed(); - case GeoServiceStatus.CSMapError: return new InternalError(); - case GeoServiceStatus.Pending: return new Pending(); - - case RealityDataStatus.Success: return new Success(); - case RealityDataStatus.InvalidData: return new InvalidData(); - - default: return new UnknownError(); + case BentleyStatus.SUCCESS: + return new Success(); + case BentleyStatus.ERROR: + return new UnknownError(); + + case IModelStatus.Success: + return new Success(); + case IModelStatus.AlreadyLoaded: + return new StateViolation(); + case IModelStatus.AlreadyOpen: + return new StateViolation(); + case IModelStatus.BadArg: + return new ValidationError(); + case IModelStatus.BadElement: + return new ValidationError(); + case IModelStatus.BadModel: + return new ValidationError(); + case IModelStatus.BadRequest: + return new BadRequest(); + case IModelStatus.BadSchema: + return new ValidationError(); + case IModelStatus.CannotUndo: + return new OperationFailed(); + case IModelStatus.CodeNotReserved: + return new StateViolation(); + case IModelStatus.DeletionProhibited: + return new Forbidden(); + case IModelStatus.DuplicateCode: + return new Conflict(); + case IModelStatus.DuplicateName: + return new Conflict(); + case IModelStatus.ElementBlockedChange: + return new ConstraintViolation(); + case IModelStatus.FileAlreadyExists: + return new Conflict(); + case IModelStatus.FileNotFound: + return new NotFound(); + case IModelStatus.FileNotLoaded: + return new FileSystemError(); + case IModelStatus.ForeignKeyConstraint: + return new ConstraintViolation(); + case IModelStatus.IdExists: + return new Conflict(); + case IModelStatus.InDynamicTransaction: + return new StateViolation(); + case IModelStatus.InvalidCategory: + return new ValidationError(); + case IModelStatus.InvalidCode: + return new ValidationError(); + case IModelStatus.InvalidCodeSpec: + return new ValidationError(); + case IModelStatus.InvalidId: + return new ValidationError(); + case IModelStatus.InvalidName: + return new ValidationError(); + case IModelStatus.InvalidParent: + return new Conflict(); + case IModelStatus.InvalidProfileVersion: + return new InvalidData(); + case IModelStatus.IsCreatingChangeSet: + return new StateViolation(); + case IModelStatus.LockNotHeld: + return new Forbidden(); + case IModelStatus.Mismatch2d3d: + return new ValidationError(); + case IModelStatus.MismatchGcs: + return new ValidationError(); + case IModelStatus.MissingDomain: + return new ValidationError(); + case IModelStatus.MissingHandler: + return new ValidationError(); + case IModelStatus.MissingId: + return new ValidationError(); + case IModelStatus.NoGeometry: + return new NoContent(); + case IModelStatus.NoMultiTxnOperation: + return new StateViolation(); + case IModelStatus.NotEnabled: + return new NotEnabled(); + case IModelStatus.NotFound: + return new NotFound(); + case IModelStatus.NotOpen: + return new StateViolation(); + case IModelStatus.NotOpenForWrite: + return new Forbidden(); + case IModelStatus.NotSameUnitBase: + return new ValidationError(); + case IModelStatus.NothingToRedo: + return new NothingToDo(); + case IModelStatus.NothingToUndo: + return new NothingToDo(); + case IModelStatus.ParentBlockedChange: + return new Forbidden(); + case IModelStatus.ReadError: + return new FileSystemError(); + case IModelStatus.ReadOnly: + return new ReadOnly(); + case IModelStatus.ReadOnlyDomain: + return new ReadOnly(); + case IModelStatus.RepositoryManagerError: + return new NetworkError(); + case IModelStatus.SQLiteError: + return new InternalError(); + case IModelStatus.TransactionActive: + return new StateViolation(); + case IModelStatus.UnitsMissing: + return new ValidationError(); + case IModelStatus.UnknownFormat: + return new InvalidData(); + case IModelStatus.UpgradeFailed: + return new OperationFailed(); + case IModelStatus.ValidationFailed: + return new ValidationError(); + case IModelStatus.VersionTooNew: + return new VersioningViolation(); + case IModelStatus.VersionTooOld: + return new VersioningViolation(); + case IModelStatus.ViewNotFound: + return new NotFound(); + case IModelStatus.WriteError: + return new FileSystemError(); + case IModelStatus.WrongClass: + return new ValidationError(); + case IModelStatus.WrongIModel: + return new ValidationError(); + case IModelStatus.WrongDomain: + return new ValidationError(); + case IModelStatus.WrongElement: + return new ValidationError(); + case IModelStatus.WrongHandler: + return new ValidationError(); + case IModelStatus.WrongModel: + return new ValidationError(); + case IModelStatus.ConstraintNotUnique: + return new ConstraintViolation(); + case IModelStatus.NoGeoLocation: + return new ValidationError(); + case IModelStatus.ServerTimeout: + return new Timeout(); + case IModelStatus.NoContent: + return new NoContent(); + case IModelStatus.NotRegistered: + return new NotImplemented(); + case IModelStatus.FunctionNotFound: + return new NotImplemented(); + case IModelStatus.NoActiveCommand: + return new StateViolation(); + case IModelStatus.Aborted: + return new Aborted(); + + case BriefcaseStatus.CannotAcquire: + return new OperationFailed(); + case BriefcaseStatus.CannotDownload: + return new OperationFailed(); + case BriefcaseStatus.CannotUpload: + return new OperationFailed(); + case BriefcaseStatus.CannotCopy: + return new OperationFailed(); + case BriefcaseStatus.CannotDelete: + return new OperationFailed(); + case BriefcaseStatus.VersionNotFound: + return new NotFound(); + case BriefcaseStatus.CannotApplyChanges: + return new OperationFailed(); + case BriefcaseStatus.DownloadCancelled: + return new Cancelled(); + case BriefcaseStatus.ContainsDeletedChangeSets: + return new ValidationError(); + + case RpcInterfaceStatus.Success: + return new Success(); + case RpcInterfaceStatus.IncompatibleVersion: + return new VersioningViolation(); + + case ChangeSetStatus.Success: + return new Success(); + case ChangeSetStatus.ApplyError: + return new OperationFailed(); + case ChangeSetStatus.ChangeTrackingNotEnabled: + return new NotEnabled(); + case ChangeSetStatus.CorruptedChangeStream: + return new Corruption(); + case ChangeSetStatus.FileNotFound: + return new NotFound(); + case ChangeSetStatus.FileWriteError: + return new FileSystemError(); + case ChangeSetStatus.HasLocalChanges: + return new StateViolation(); + case ChangeSetStatus.HasUncommittedChanges: + return new StateViolation(); + case ChangeSetStatus.InvalidId: + return new Corruption(); + case ChangeSetStatus.InvalidVersion: + return new Corruption(); + case ChangeSetStatus.InDynamicTransaction: + return new StateViolation(); + case ChangeSetStatus.IsCreatingChangeSet: + return new StateViolation(); + case ChangeSetStatus.IsNotCreatingChangeSet: + return new StateViolation(); + case ChangeSetStatus.MergePropagationError: + return new OperationFailed(); + case ChangeSetStatus.NothingToMerge: + return new NothingToDo(); + case ChangeSetStatus.NoTransactions: + return new OperationFailed(); + case ChangeSetStatus.ParentMismatch: + return new ValidationError(); + case ChangeSetStatus.SQLiteError: + return new InternalError(); + case ChangeSetStatus.WrongDgnDb: + return new ValidationError(); + case ChangeSetStatus.CouldNotOpenDgnDb: + return new OperationFailed(); + case ChangeSetStatus.MergeSchemaChangesOnOpen: + return new BadRequest(); + case ChangeSetStatus.ReverseOrReinstateSchemaChanges: + return new Conflict(); + case ChangeSetStatus.ProcessSchemaChangesOnOpen: + return new BadRequest(); + case ChangeSetStatus.CannotMergeIntoReadonly: + return new ValidationError(); + case ChangeSetStatus.CannotMergeIntoMaster: + return new ValidationError(); + case ChangeSetStatus.CannotMergeIntoReversed: + return new ValidationError(); + + case RepositoryStatus.Success: + return new Success(); + case RepositoryStatus.ServerUnavailable: + return new NetworkError(); + case RepositoryStatus.LockAlreadyHeld: + return new Conflict(); + case RepositoryStatus.SyncError: + return new NetworkError(); + case RepositoryStatus.InvalidResponse: + return new NetworkError(); + case RepositoryStatus.PendingTransactions: + return new StateViolation(); + case RepositoryStatus.LockUsed: + return new StateViolation(); + case RepositoryStatus.CannotCreateChangeSet: + return new InternalError(); + case RepositoryStatus.InvalidRequest: + return new NetworkError(); + case RepositoryStatus.ChangeSetRequired: + return new StateViolation(); + case RepositoryStatus.CodeUnavailable: + return new Conflict(); + case RepositoryStatus.CodeNotReserved: + return new StateViolation(); + case RepositoryStatus.CodeUsed: + return new StateViolation(); + case RepositoryStatus.LockNotHeld: + return new Forbidden(); + case RepositoryStatus.RepositoryIsLocked: + return new Locked(); + case RepositoryStatus.ChannelConstraintViolation: + return new ConstraintViolation(); + + case HttpStatus.Success: + return new Success(); + + case IModelHubStatus.Success: + return new Success(); + case IModelHubStatus.Unknown: + return new UnknownError(); + case IModelHubStatus.MissingRequiredProperties: + return new ValidationError(); + case IModelHubStatus.InvalidPropertiesValues: + return new ValidationError(); + case IModelHubStatus.UserDoesNotHavePermission: + return new PermissionsViolation(); + case IModelHubStatus.UserDoesNotHaveAccess: + return new PermissionsViolation(); + case IModelHubStatus.InvalidBriefcase: + return new ValidationError(); + case IModelHubStatus.BriefcaseDoesNotExist: + return new NotFound(); + case IModelHubStatus.BriefcaseDoesNotBelongToUser: + return new PermissionsViolation(); + case IModelHubStatus.AnotherUserPushing: + return new StateViolation(); + case IModelHubStatus.ChangeSetAlreadyExists: + return new Conflict(); + case IModelHubStatus.ChangeSetDoesNotExist: + return new NotFound(); + case IModelHubStatus.FileIsNotUploaded: + return new StateViolation(); + case IModelHubStatus.iModelIsNotInitialized: + return new StateViolation(); + case IModelHubStatus.ChangeSetPointsToBadSeed: + return new InvalidData(); + case IModelHubStatus.OperationFailed: + return new OperationFailed(); + case IModelHubStatus.PullIsRequired: + return new StateViolation(); + case IModelHubStatus.MaximumNumberOfBriefcasesPerUser: + return new Throttled(); + case IModelHubStatus.MaximumNumberOfBriefcasesPerUserPerMinute: + return new Throttled(); + case IModelHubStatus.DatabaseTemporarilyLocked: + return new Locked(); + case IModelHubStatus.iModelIsLocked: + return new Locked(); + case IModelHubStatus.CodesExist: + return new Conflict(); + case IModelHubStatus.LocksExist: + return new Conflict(); + case IModelHubStatus.iModelAlreadyExists: + return new Conflict(); + case IModelHubStatus.iModelDoesNotExist: + return new NotFound(); + case IModelHubStatus.FileDoesNotExist: + return new NotFound(); + case IModelHubStatus.FileAlreadyExists: + return new Conflict(); + case IModelHubStatus.LockDoesNotExist: + return new NotFound(); + case IModelHubStatus.LockOwnedByAnotherBriefcase: + return new Conflict(); + case IModelHubStatus.CodeStateInvalid: + return new StateViolation(); + case IModelHubStatus.CodeReservedByAnotherBriefcase: + return new Conflict(); + case IModelHubStatus.CodeDoesNotExist: + return new NotFound(); + case IModelHubStatus.EventTypeDoesNotExist: + return new NotFound(); + case IModelHubStatus.EventSubscriptionDoesNotExist: + return new NotFound(); + case IModelHubStatus.EventSubscriptionAlreadyExists: + return new StateViolation(); + case IModelHubStatus.ITwinIdIsNotSpecified: + return new ValidationError(); + case IModelHubStatus.FailedToGetITwinPermissions: + return new OperationFailed(); + case IModelHubStatus.FailedToGetITwinMembers: + return new OperationFailed(); + case IModelHubStatus.ChangeSetAlreadyHasVersion: + return new Conflict(); + case IModelHubStatus.VersionAlreadyExists: + return new Conflict(); + case IModelHubStatus.JobSchedulingFailed: + return new InternalError(); + case IModelHubStatus.ConflictsAggregate: + return new Conflict(); + case IModelHubStatus.FailedToGetITwinById: + return new OperationFailed(); + case IModelHubStatus.DatabaseOperationFailed: + return new OperationFailed(); + case IModelHubStatus.SeedFileInitializationFailed: + return new OperationFailed(); + case IModelHubStatus.FailedToGetAssetPermissions: + return new OperationFailed(); + case IModelHubStatus.FailedToGetAssetMembers: + return new OperationFailed(); + case IModelHubStatus.ITwinDoesNotExist: + return new NotFound(); + case IModelHubStatus.LockChunkDoesNotExist: + return new NotFound(); + case IModelHubStatus.CheckpointAlreadyExists: + return new Conflict(); + case IModelHubStatus.CheckpointDoesNotExist: + return new NotFound(); + case IModelHubStatus.UndefinedArgumentError: + return new ValidationError(); + case IModelHubStatus.InvalidArgumentError: + return new ValidationError(); + case IModelHubStatus.MissingDownloadUrlError: + return new ValidationError(); + case IModelHubStatus.NotSupportedInBrowser: + return new NotSupported(); + case IModelHubStatus.FileHandlerNotSet: + return new NotImplemented(); + case IModelHubStatus.FileNotFound: + return new NotFound(); + case IModelHubStatus.InitializationTimeout: + return new Timeout(); + + case GeoServiceStatus.Success: + return new Success(); + case GeoServiceStatus.NoGeoLocation: + return new ValidationError(); + case GeoServiceStatus.OutOfUsefulRange: + return new ValidationError(); + case GeoServiceStatus.OutOfMathematicalDomain: + return new ValidationError(); + case GeoServiceStatus.NoDatumConverter: + return new OperationFailed(); + case GeoServiceStatus.VerticalDatumConvertError: + return new OperationFailed(); + case GeoServiceStatus.CSMapError: + return new InternalError(); + case GeoServiceStatus.Pending: + return new Pending(); + + case RealityDataStatus.Success: + return new Success(); + case RealityDataStatus.InvalidData: + return new InvalidData(); + + default: + return new UnknownError(); } } diff --git a/core/bentley/src/Time.ts b/core/bentley/src/Time.ts index bf941686272c..fb1558340ea1 100644 --- a/core/bentley/src/Time.ts +++ b/core/bentley/src/Time.ts @@ -12,30 +12,50 @@ */ export class BeDuration { private readonly _milliseconds: number; - private constructor(milliseconds: number = 0) { this._milliseconds = milliseconds; } + private constructor(milliseconds: number = 0) { + this._milliseconds = milliseconds; + } /** The duration in milliseconds */ - public get milliseconds() { return this._milliseconds; } - public get seconds() { return this._milliseconds / 1000; } + public get milliseconds() { + return this._milliseconds; + } + public get seconds() { + return this._milliseconds / 1000; + } /** Create a BeDuration from seconds. * @param seconds the number of seconds for this BeDuration */ - public static fromSeconds(seconds: number) { return new BeDuration(seconds * 1000); } + public static fromSeconds(seconds: number) { + return new BeDuration(seconds * 1000); + } /** Create a BeDuration from milliseconds. * @param milliseconds the number of milliseconds for this BeDuration */ - public static fromMilliseconds(milliseconds: number) { return new BeDuration(milliseconds); } + public static fromMilliseconds(milliseconds: number) { + return new BeDuration(milliseconds); + } /** Determine whether this BeDuration is 0 seconds */ - public get isZero() { return this._milliseconds === 0; } + public get isZero() { + return this._milliseconds === 0; + } /** Determine whether this BeDuration is towards the future */ - public get isTowardsFuture(): boolean { return this._milliseconds > 0; } + public get isTowardsFuture(): boolean { + return this._milliseconds > 0; + } /** Determine whether this BeDuration is towards the past */ - public get isTowardsPast(): boolean { return this._milliseconds < 0; } + public get isTowardsPast(): boolean { + return this._milliseconds < 0; + } /** Subtract a BeDuration from this BeDuration, returning a new BeDuration. */ - public minus(other: BeDuration): BeDuration { return new BeDuration(this._milliseconds - other._milliseconds); } + public minus(other: BeDuration): BeDuration { + return new BeDuration(this._milliseconds - other._milliseconds); + } /** Add a BeDuration to this BeDuration, returning a new BeDuration */ - public plus(other: BeDuration): BeDuration { return new BeDuration(this._milliseconds + other._milliseconds); } + public plus(other: BeDuration): BeDuration { + return new BeDuration(this._milliseconds + other._milliseconds); + } /** Utility function to just wait for the specified time * @param ms Duration in milliseconds to wait @@ -87,47 +107,69 @@ export class BeDuration { export class BeTimePoint { private readonly _milliseconds: number; /** the time in milliseconds, of this BeTimePoint (relative to January 1, 1970 00:00:00 UTC.) */ - public get milliseconds() { return this._milliseconds; } - private constructor(milliseconds: number) { this._milliseconds = milliseconds; } + public get milliseconds() { + return this._milliseconds; + } + private constructor(milliseconds: number) { + this._milliseconds = milliseconds; + } /** Create a BeTimePoint from Date.now() */ - public static now() { return new BeTimePoint(Date.now()); } + public static now() { + return new BeTimePoint(Date.now()); + } /** Create a BeTimePoint at a specified duration in the future from now * @param val the duration from now */ - public static fromNow(val: BeDuration) { return new BeTimePoint(Date.now() + val.milliseconds); } + public static fromNow(val: BeDuration) { + return new BeTimePoint(Date.now() + val.milliseconds); + } /** Create a BeTimePoint at a specified duration in the past before now * @param val the duration before now */ - public static beforeNow(val: BeDuration) { return new BeTimePoint(Date.now() - val.milliseconds); } + public static beforeNow(val: BeDuration) { + return new BeTimePoint(Date.now() - val.milliseconds); + } /** Determine whether this BeTimePoint is a time in the future from the time this method is called (it calls now()!) */ - public get isInFuture(): boolean { return Date.now() < this._milliseconds; } + public get isInFuture(): boolean { + return Date.now() < this._milliseconds; + } /** Determine whether this BeTimePoint is a time that has already passed before the time this method is called (it calls now()!) */ - public get isInPast(): boolean { return Date.now() > this._milliseconds; } + public get isInPast(): boolean { + return Date.now() > this._milliseconds; + } /** Determine whether this BeTimePoint happens before another one. * @param other the other BeTimePoint. */ - public before(other: BeTimePoint): boolean { return this._milliseconds < other._milliseconds; } + public before(other: BeTimePoint): boolean { + return this._milliseconds < other._milliseconds; + } /** Determine whether this BeTimePoint happens after another one. * @param other the other BeTimePoint. */ - public after(other: BeTimePoint): boolean { return this._milliseconds > other._milliseconds; } + public after(other: BeTimePoint): boolean { + return this._milliseconds > other._milliseconds; + } /** Subtract a BeDuration from this BeTimePoint, returning a new BeTimePoint. This moves this BeTimePoint backwards in time if BeDuration.isTowardsFuture() === true * @param duration the duration to subtract. */ - public minus(duration: BeDuration): BeTimePoint { return new BeTimePoint(this._milliseconds - duration.milliseconds); } + public minus(duration: BeDuration): BeTimePoint { + return new BeTimePoint(this._milliseconds - duration.milliseconds); + } /** Subtract a BeDuration from this BeTimePoint, returning a new BeTimePoint. This moves this BeTimePoint backwards in time if BeDuration.isTowardsFuture() === true * @param duration the duration to subtract. */ - public plus(duration: BeDuration) { return new BeTimePoint(this._milliseconds + duration.milliseconds); } + public plus(duration: BeDuration) { + return new BeTimePoint(this._milliseconds + duration.milliseconds); + } } /** A StopWatch for timing operations. @@ -137,13 +179,23 @@ export class StopWatch { private _start?: BeTimePoint; private _stop?: BeTimePoint; /** Get the elapsed time since start() on a running timer. */ - public get current(): BeDuration { return BeDuration.fromMilliseconds(BeTimePoint.now().milliseconds - (!!this._start ? this._start.milliseconds : 0)); } + public get current(): BeDuration { + return BeDuration.fromMilliseconds(BeTimePoint.now().milliseconds - (!!this._start ? this._start.milliseconds : 0)); + } /** Get the elapsed time, in seconds, since start() on a running timer. */ - public get currentSeconds(): number { return this.current.seconds; } + public get currentSeconds(): number { + return this.current.seconds; + } /** Get the elapsed time between start() and stop() on this timer in milliseconds. */ - public get elapsed(): BeDuration { return BeDuration.fromMilliseconds((!!this._stop ? this._stop.milliseconds : BeTimePoint.now().milliseconds) - (!!this._start ? this._start.milliseconds : 0)); } + public get elapsed(): BeDuration { + return BeDuration.fromMilliseconds( + (!!this._stop ? this._stop.milliseconds : BeTimePoint.now().milliseconds) - (!!this._start ? this._start.milliseconds : 0), + ); + } /** Get the elapsed time, in seconds, between start() and stop() on this timer. */ - public get elapsedSeconds(): number { return this.elapsed.seconds; } + public get elapsedSeconds(): number { + return this.elapsed.seconds; + } /** ctor for StopWatch * @param description optional string stored with the StopWatch * @param startImmediately if true, StopWatch is started when created. Otherwise, call start() explicitly. @@ -166,5 +218,7 @@ export class StopWatch { } /** Clear the StopWatch */ - public reset(): void { this._start = this._stop = undefined; } + public reset(): void { + this._start = this._stop = undefined; + } } diff --git a/core/bentley/src/Tracing.ts b/core/bentley/src/Tracing.ts index b271e254f3d1..aa9a64734c49 100644 --- a/core/bentley/src/Tracing.ts +++ b/core/bentley/src/Tracing.ts @@ -20,7 +20,7 @@ export enum SpanKind { SERVER = 1, CLIENT = 2, PRODUCER = 3, - CONSUMER = 4 + CONSUMER = 4, } function isValidPrimitive(val: unknown): val is SpanAttributeValue { @@ -152,11 +152,11 @@ export class Tracing { private static withOpenTelemetry(level: LogLevel, base: LogFunction, isError: boolean = false): LogFunction { return (category, message, metaData) => { const oTelContext = Tracing._openTelemetry?.context.active(); - if(Tracing._openTelemetry === undefined || oTelContext === undefined) + if (Tracing._openTelemetry === undefined || oTelContext === undefined) return base(category, message, metaData); const serializedMetadata = Logger.getMetaData(metaData); - if(Logger.isEnabled(category, level)) { + if (Logger.isEnabled(category, level)) { try { Tracing._openTelemetry?.trace .getSpan(Tracing._openTelemetry.context.active()) @@ -165,7 +165,7 @@ export class Tracing { error: isError, loggerCategory: category, }); - } catch (_e) { } // avoid throwing random errors (with stack trace mangled by async hooks) when openTelemetry collector doesn't work + } catch (_e) {} // avoid throwing random errors (with stack trace mangled by async hooks) when openTelemetry collector doesn't work const spanContext = Tracing._openTelemetry.trace.getSpan(oTelContext)?.spanContext(); base(category, message, { diff --git a/core/bentley/src/TupleKeyedMap.ts b/core/bentley/src/TupleKeyedMap.ts index f74fe6431e31..49b17d5a7dc7 100644 --- a/core/bentley/src/TupleKeyedMap.ts +++ b/core/bentley/src/TupleKeyedMap.ts @@ -31,10 +31,11 @@ export class TupleKeyedMap { // argument types match those of Map public constructor(entries?: readonly (readonly [K, V])[] | null) { - if (entries) + if (entries) { for (const [k, v] of entries) { this.set(k, v); } + } } public clear(): void { @@ -85,7 +86,7 @@ export class TupleKeyedMap { } public *[Symbol.iterator](): IterableIterator<[K, V]> { - function *impl(map: Map, keyPrefix: readonly any[]): IterableIterator<[K, V]> { + function* impl(map: Map, keyPrefix: readonly any[]): IterableIterator<[K, V]> { for (const [k, v] of map) { const nextKey = [...keyPrefix, k]; if (v instanceof Map) { diff --git a/core/bentley/src/TypedArrayBuilder.ts b/core/bentley/src/TypedArrayBuilder.ts index 5fe8375fb12b..e20689cb00e3 100644 --- a/core/bentley/src/TypedArrayBuilder.ts +++ b/core/bentley/src/TypedArrayBuilder.ts @@ -6,8 +6,8 @@ * @module Collections */ -import { Constructor } from "./UtilityTypes"; import { assert } from "./Assert"; +import { Constructor } from "./UtilityTypes"; /** Options used to construct a [[TypedArrayBuilder]]. * @public diff --git a/core/bentley/src/UnexpectedErrors.ts b/core/bentley/src/UnexpectedErrors.ts index 560d064a2fe1..982b2b5cc276 100644 --- a/core/bentley/src/UnexpectedErrors.ts +++ b/core/bentley/src/UnexpectedErrors.ts @@ -22,9 +22,14 @@ export type OnUnexpectedError = (error: any) => void; */ export class UnexpectedErrors { /** handler for re-throwing exceptions directly */ - public static readonly reThrowImmediate = (e: any) => { throw e; }; + public static readonly reThrowImmediate = (e: any) => { + throw e; + }; /** handler for re-throwing exceptions from an asynchronous interval (so the current call stack is not aborted) */ - public static readonly reThrowDeferred = (e: any) => setTimeout(() => { throw e; }, 0); + public static readonly reThrowDeferred = (e: any) => + setTimeout(() => { + throw e; + }, 0); /** handler for logging exception to console */ public static readonly consoleLog = (e: any) => console.error(e); // eslint-disable-line no-console /** handler for logging exception with [[Logger]] */ @@ -32,7 +37,7 @@ export class UnexpectedErrors { private static _telemetry: OnUnexpectedError[] = []; private static _handler = this.errorLog; // default to error logging - private constructor() { } // this is a singleton + private constructor() {} // this is a singleton /** Add a "telemetry tracker" for unexpected errors. Useful for tracking/reporting errors without changing handler. * @returns a method to remove the tracker diff --git a/core/bentley/src/UtilityTypes.ts b/core/bentley/src/UtilityTypes.ts index 6f94f9bc769e..cddc6c4e1708 100644 --- a/core/bentley/src/UtilityTypes.ts +++ b/core/bentley/src/UtilityTypes.ts @@ -29,7 +29,7 @@ export type MarkRequired = Pick, K> & Omit = new (...args: any[]) => T; +export type Constructor = new(...args: any[]) => T; /** Returns true if `obj` is an object of class `T`. * @see [[asInstanceOf]] to cast `obj` to class `T`. @@ -91,7 +91,7 @@ export type AsyncFunction = (...args: any[]) => Promise; /** The members of `T` that are async functions (functions that return a promise), and no other properties * @public */ -export type PickAsyncMethods = { [P in keyof T]: T[P] extends AsyncFunction ? T[P] : never; }; +export type PickAsyncMethods = { [P in keyof T]: T[P] extends AsyncFunction ? T[P] : never }; /** Extracts the names of all function properties of `T` that return a Promise. * @public @@ -111,7 +111,7 @@ export type PromiseReturnType = T extends (...args: any /** The members of `T` that are functions and no other properties * @public */ -export type PickMethods = { [P in keyof T]: T[P] extends Function ? T[P] : never; }; +export type PickMethods = { [P in keyof T]: T[P] extends Function ? T[P] : never }; /** The members of `T` that are functions that do not return a Promise * @public diff --git a/core/bentley/src/internal/BeSQLiteInternal.ts b/core/bentley/src/internal/BeSQLiteInternal.ts index de9ebe8e3b75..d41cae9c6a55 100644 --- a/core/bentley/src/internal/BeSQLiteInternal.ts +++ b/core/bentley/src/internal/BeSQLiteInternal.ts @@ -9,7 +9,7 @@ /** @internal */ export enum DbChangeStage { Old = 0, - New = 1 + New = 1, } /** @internal */ @@ -18,7 +18,7 @@ export enum DbValueType { FloatVal = 2, TextVal = 3, BlobVal = 4, - NullVal = 5 + NullVal = 5, } /** Cause of conflict when applying a changeset. @@ -41,4 +41,3 @@ export enum DbConflictResolution { /** Abort apply changeset */ Abort = 2, } - diff --git a/core/bentley/src/internal/RepositoryStatus.ts b/core/bentley/src/internal/RepositoryStatus.ts index 1ee034151a8c..2e91846783d2 100644 --- a/core/bentley/src/internal/RepositoryStatus.ts +++ b/core/bentley/src/internal/RepositoryStatus.ts @@ -42,4 +42,3 @@ export enum RepositoryStatus { /** Channel write constraint violation, such as an attempt to write outside the designated channel. */ ChannelConstraintViolation = 0x1500F, } - diff --git a/core/bentley/src/test/BeEvent.test.ts b/core/bentley/src/test/BeEvent.test.ts index c86e14f6beb7..daa172b545eb 100644 --- a/core/bentley/src/test/BeEvent.test.ts +++ b/core/bentley/src/test/BeEvent.test.ts @@ -7,17 +7,14 @@ import { BeEvent, BeEventList, Listener, ListenerType } from "../core-bentley"; /* eslint-disable no-empty */ class Dummy { - constructor(_name: string) { } + constructor(_name: string) {} } type DummyListener = (d: Dummy, r: number) => void; describe("BeEvent tests", () => { - describe("BeEvent", () => { - it("Subscribing to the event dispatcher", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -94,7 +91,6 @@ describe("BeEvent tests", () => { }); it("Subscribing to the event dispatcher. Fire twice", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -114,7 +110,6 @@ describe("BeEvent tests", () => { }); it("Sub to the event dispatcher. Fire twice", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -134,7 +129,6 @@ describe("BeEvent tests", () => { }); it("One subscription to the event dispatcher. Fire twice.", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -154,7 +148,6 @@ describe("BeEvent tests", () => { }); it("Unsubscribing from the event dispatcher.", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -172,11 +165,9 @@ describe("BeEvent tests", () => { expect(resultDummy, "resultDummy should be empty.").to.equal(undefined); expect(resultNr, "resultNr should be 0.").to.equal(0); - }); it("Unsubscribe from the event dispatcher.", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -197,7 +188,6 @@ describe("BeEvent tests", () => { }); it("Unsubscribing to a one subscription.", () => { - const carolus = new Dummy("Carolus"); const dispatcher = new BeEvent(); @@ -218,14 +208,14 @@ describe("BeEvent tests", () => { }); it("Has no event.", () => { - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; const dispatcher = new BeEvent(); const result = dispatcher.has(fn); expect(result, "Handler should not be present.").to.equal(false); }); it("Has event through subscribe.", () => { - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; const dispatcher = new BeEvent(); dispatcher.addListener(fn); const result = dispatcher.has(fn); @@ -233,7 +223,7 @@ describe("BeEvent tests", () => { }); it("Has event through one.", () => { - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; const dispatcher = new BeEvent(); dispatcher.addOnce(fn); const result = dispatcher.has(fn); @@ -241,7 +231,7 @@ describe("BeEvent tests", () => { }); it("Test subscribe -> unsubscribe -> has", () => { - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; const dispatcher = new BeEvent(); dispatcher.addListener(fn); dispatcher.removeListener(fn); @@ -250,7 +240,6 @@ describe("BeEvent tests", () => { }); it("Clear subscriptions.", () => { - const carolus = new Dummy("Carolus"); const willem = new Dummy("Willem"); @@ -271,8 +260,8 @@ describe("BeEvent tests", () => { }); it("Drop removed listeners only.", () => { - const fnOnce = () => { }; - const fn = () => { }; + const fnOnce = () => {}; + const fn = () => {}; const dispatcher = new BeEvent(); dispatcher.addOnce(fnOnce); dispatcher.addListener(fn); @@ -282,15 +271,13 @@ describe("BeEvent tests", () => { expect(hasFn, "Handler should be present because it was not dropped.").to.equal(true); expect(hasOnceFn, "Handler should not be present because it was dropped.").to.equal(false); }); - }); describe("BeEventList", () => { - it("Subscribe to event name", () => { const event = "myEvent"; const list = new BeEventList(); - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; list.get(event).addListener(fn); const result = list.get(event).has(fn); @@ -300,7 +287,7 @@ describe("BeEvent tests", () => { it("Unsubscribe to event name", () => { const event = "myEvent"; const list = new BeEventList(); - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; list.get(event).addListener(fn); list.get(event).removeListener(fn); @@ -310,7 +297,6 @@ describe("BeEvent tests", () => { }); it("Test firing two events in one list", () => { - const list = new BeEventList(); let result: string | undefined; @@ -331,9 +317,8 @@ describe("BeEvent tests", () => { }); it("Test remove from list.", () => { - const list = new BeEventList(); - const fn = (_dummy: Dummy, _nr: number) => { }; + const fn = (_dummy: Dummy, _nr: number) => {}; const event1 = "ev1"; list.get(event1).addListener(fn); @@ -356,7 +341,7 @@ describe("BeEvent tests", () => { describe("ListenerType", () => { it("Retrieves listener type", () => { - const dispatcher = new BeEvent<(args: {x: number, y: string}) => void>(); + const dispatcher = new BeEvent<(args: { x: number, y: string }) => void>(); type DispatcherListener = ListenerType; const fn: DispatcherListener = (args) => { @@ -374,7 +359,7 @@ describe("BeEvent tests", () => { addListener(listener: TListener): () => void; } - const dispatcher: MyEvent<(args: {x: number, y: string}) => void> = new BeEvent(); + const dispatcher: MyEvent<(args: { x: number, y: string }) => void> = new BeEvent(); type DispatcherListener = ListenerType; const fn: DispatcherListener = (args) => { args.x === 0; diff --git a/core/bentley/src/test/BentleyError.test.ts b/core/bentley/src/test/BentleyError.test.ts index 7dca334cf7a5..cbb7e1dd7a50 100644 --- a/core/bentley/src/test/BentleyError.test.ts +++ b/core/bentley/src/test/BentleyError.test.ts @@ -13,7 +13,9 @@ describe("BentleyError.getErrorMessage", () => { it("prefers Error.toString() to message property", () => { class CustomError extends Error { - public override toString() { return "CustomToString"; } + public override toString() { + return "CustomToString"; + } } expect(BentleyError.getErrorMessage(new Error("foo"))).to.equal("Error: foo"); expect(BentleyError.getErrorMessage(new CustomError("foo"))).to.equal("CustomToString"); @@ -138,7 +140,7 @@ describe("BentleyError.getErrorProps", () => { const err = new BentleyError(BentleyStatus.SUCCESS, "message"); const serialized = BentleyError.getErrorProps(err); expect(serialized).to.be.an("object"); - expect(serialized).to.eql({ message: err.toString(), stack: err.stack }); // eslint-disable-line @typescript-eslint/no-base-to-string + expect(serialized).to.eql({ message: err.toString(), stack: err.stack }); // eslint-disable-line @typescript-eslint/no-base-to-string expect(serialized).to.not.have.property("metadata"); }); @@ -147,7 +149,7 @@ describe("BentleyError.getErrorProps", () => { const err = new BentleyError(BentleyStatus.ERROR, "fail", () => metadata); const serialized = BentleyError.getErrorProps(err); expect(serialized).to.be.an("object"); - expect(serialized).to.eql({ message: err.toString(), stack: err.stack, metadata }); // eslint-disable-line @typescript-eslint/no-base-to-string + expect(serialized).to.eql({ message: err.toString(), stack: err.stack, metadata }); // eslint-disable-line @typescript-eslint/no-base-to-string }); it("returns values that can safely be JSON round-tripped", () => { diff --git a/core/bentley/src/test/ClassUtils.test.ts b/core/bentley/src/test/ClassUtils.test.ts index 6e52774aa44e..8978eff4f7e8 100644 --- a/core/bentley/src/test/ClassUtils.test.ts +++ b/core/bentley/src/test/ClassUtils.test.ts @@ -10,10 +10,18 @@ type Extends = T extends Base ? true : false; describe("ClassUtils", () => { it("isProperSubclassOf", () => { - class A { public a = "a"; } - class B extends A { public b = "b"; } - class C extends B { public c = "c"; } - class M { public m = "m"; } + class A { + public a = "a"; + } + class B extends A { + public b = "b"; + } + class C extends B { + public c = "c"; + } + class M { + public m = "m"; + } expect(ClassUtils.isProperSubclassOf(A, A)).to.be.false; expect(ClassUtils.isProperSubclassOf(A, B)).to.be.false; @@ -48,10 +56,18 @@ describe("ClassUtils", () => { }); it("isSubclassOf", () => { - class A { public a = "a"; } - class B extends A { public b = "b"; } - class C extends B { public c = "c"; } - class M { public m = "m"; } + class A { + public a = "a"; + } + class B extends A { + public b = "b"; + } + class C extends B { + public c = "c"; + } + class M { + public m = "m"; + } expect(ClassUtils.isSubclassOf(A, A)).to.be.true; expect(ClassUtils.isSubclassOf(A, B)).to.be.false; diff --git a/core/bentley/src/test/Disposable.test.ts b/core/bentley/src/test/Disposable.test.ts index 3ca39dfb42e0..b804694d8302 100644 --- a/core/bentley/src/test/Disposable.test.ts +++ b/core/bentley/src/test/Disposable.test.ts @@ -17,11 +17,9 @@ class CallbackDisposable implements IDisposable { } describe("Disposable", () => { - describe("isIDisposable", () => { - it("returns true when given an object with `dispose` function", () => { - assert.isTrue(isIDisposable({ dispose: () => { } })); + assert.isTrue(isIDisposable({ dispose: () => {} })); }); it("returns false when given an object without `dispose` function", () => { @@ -39,11 +37,9 @@ describe("Disposable", () => { assert.isFalse(isIDisposable("123")); assert.isFalse(isIDisposable([])); }); - }); describe("using IDisposable", () => { - it("Calls dispose on success and returns result", () => { let disposed = false; const disposable = new CallbackDisposable(() => { @@ -76,7 +72,7 @@ describe("Disposable", () => { const disposable = new CallbackDisposable(() => { disposed = true; }); - await using(disposable, async (_r) => { + using(disposable, async (_r) => { return new Promise((resolve: () => void, _reject: () => void) => { setTimeout(() => { resolve(); @@ -102,7 +98,7 @@ describe("Disposable", () => { }); await result.then(() => { assert.fail(undefined, undefined, "Expected result to be rejected"); - }, () => { }); + }, () => {}); assert.isTrue(disposed); }); @@ -124,17 +120,17 @@ describe("Disposable", () => { assert.isTrue(disposed1); assert.isTrue(disposed2); }); - }); describe("DisposableList", () => { - it("Calls dispose on registered IDisposable", () => { let disposed = false; const disposableList = new DisposableList(); - disposableList.add(new CallbackDisposable(() => { - disposed = true; - })); + disposableList.add( + new CallbackDisposable(() => { + disposed = true; + }), + ); disposableList.dispose(); assert.isTrue(disposed); }); @@ -160,7 +156,5 @@ describe("Disposable", () => { disposableList.dispose(); assert.isTrue(disposed); }); - }); - }); diff --git a/core/bentley/src/test/Id.test.ts b/core/bentley/src/test/Id.test.ts index 88c28dd05183..5a5fa75bf139 100644 --- a/core/bentley/src/test/Id.test.ts +++ b/core/bentley/src/test/Id.test.ts @@ -5,15 +5,26 @@ import { assert, describe, expect, it } from "vitest"; import { - CompressedId64Set, Guid, GuidString, Id64, Id64Arg, Id64Array, Id64String, MutableCompressedId64Set, OrderedId64Iterable, TransientIdSequence, + CompressedId64Set, + Guid, + GuidString, + Id64, + Id64Arg, + Id64Array, + Id64String, + MutableCompressedId64Set, + OrderedId64Iterable, + TransientIdSequence, } from "../core-bentley"; class Uint64Id { - public constructor(public readonly high: number, + public constructor( + public readonly high: number, public readonly low: number, public readonly localId: number, public readonly briefcaseId: number, - public readonly str: string) { } + public readonly str: string, + ) {} } describe("Ids", () => { @@ -219,7 +230,9 @@ describe("Ids", () => { ]; class MySet extends Id64.Uint32Set { - public get map() { return this._map; } + public get map() { + return this._map; + } } const set = new MySet(); @@ -331,7 +344,9 @@ describe("Ids", () => { ]; class MyMap extends Id64.Uint32Map { - public get map() { return this._map; } + public get map() { + return this._map; + } } const strings = new MyMap(); @@ -482,7 +497,7 @@ describe("OrderedId64Iterable", () => { }); it("should produce the difference of two sets", () => { - const test = (a: string[], b: string[], expected: string[]) => { + const test = (a: string[], b: string[], expected: string[]) => { const actual: string[] = []; for (const id of OrderedId64Iterable.difference(a, b)) actual.push(id); @@ -599,24 +614,59 @@ describe("CompressedId64Set", () => { roundTrip([], ""); roundTrip(makeIds([2]), "+2"); - roundTrip(makeIds([1,5]), "+1+4"); - roundTrip(makeIds([3,7,8,10]), "+3+4+1+2"); + roundTrip(makeIds([1, 5]), "+1+4"); + roundTrip(makeIds([3, 7, 8, 10]), "+3+4+1+2"); roundTrip(makeIds([0xFF, 0x150]), "+FF+51"); - roundTrip(makeIds([1,2,3,4,5]), "+1*5"); - roundTrip(makeIds([2,4,6,8]), "+2*4"); - roundTrip(makeIds([1,2,3,4,8,12,16]), "+1*4+4*3"); - roundTrip(makeIds([1,2,3,4,8,12,16,17]), "+1*4+4*3+1"); - - roundTrip(makeIds([100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,2100,2200,2300]), "+64*17"); - roundTrip(makeIds([1,10001,20001,30001,40001,50001,60001,70001,80001,90001,100001,110001,120001,130001,140001,150001,160001,170001,180001,190001,200001,210001,220001,230001, 230002]), "+1+2710*17+1"); + roundTrip(makeIds([1, 2, 3, 4, 5]), "+1*5"); + roundTrip(makeIds([2, 4, 6, 8]), "+2*4"); + roundTrip(makeIds([1, 2, 3, 4, 8, 12, 16]), "+1*4+4*3"); + roundTrip(makeIds([1, 2, 3, 4, 8, 12, 16, 17]), "+1*4+4*3+1"); + + roundTrip( + makeIds([100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300]), + "+64*17", + ); + roundTrip( + makeIds([ + 1, + 10001, + 20001, + 30001, + 40001, + 50001, + 60001, + 70001, + 80001, + 90001, + 100001, + 110001, + 120001, + 130001, + 140001, + 150001, + 160001, + 170001, + 180001, + 190001, + 200001, + 210001, + 220001, + 230001, + 230002, + ]), + "+1+2710*17+1", + ); roundTrip(makeIds([0x21234567890, 0x31234567890, 0x41234567890, 0x61234567890]), "+21234567890+10000000000*2+20000000000"); roundTrip(["0xabcdef0123456789", "0xabcdef1123456789"], "+ABCDEF0123456789+1000000000"); roundTrip(["0xf0a0000000100", "0xf0a0000000120", "0xf0a0000000140", "0xf0a0000000202"], "+F0A0000000100+20*2+C2"); roundTrip(["0xffffffffffffffff"], "+FFFFFFFFFFFFFFFF"); roundTrip(["0x1", "0xffffffffffffffff"], "+1+FFFFFFFFFFFFFFFE"); - roundTrip(["0x1000000000000001", "0x4000000000000004", "0x7000000000000007", "0xa000007777777777"], "+1000000000000001+3000000000000003*2+3000007777777770"); + roundTrip( + ["0x1000000000000001", "0x4000000000000004", "0x7000000000000007", "0xa000007777777777"], + "+1000000000000001+3000000000000003*2+3000007777777770", + ); roundTrip(["0xfffffffffe", "0xffffffffff"], "+FFFFFFFFFE+1"); roundTrip(["0xfffffffffe", "0x10000000001"], "+FFFFFFFFFE+3"); diff --git a/core/bentley/src/test/IndexMap.test.ts b/core/bentley/src/test/IndexMap.test.ts index adcc029e3829..0e4bff3f7198 100644 --- a/core/bentley/src/test/IndexMap.test.ts +++ b/core/bentley/src/test/IndexMap.test.ts @@ -8,7 +8,7 @@ import { compareNumbers, IndexMap } from "../core-bentley"; describe("IndexMap", () => { it("should remember insertion order", () => { const map = new IndexMap(compareNumbers); - const list = [ 9, 8, 7, 1, 2, 3, 0, 5, 4 ]; + const list = [9, 8, 7, 1, 2, 3, 0, 5, 4]; for (let i = 0; i < list.length; i++) expect(map.insert(list[i])).to.equal(i); @@ -23,7 +23,7 @@ describe("IndexMap", () => { it("should produce array ordered by index", () => { const map = new IndexMap(compareNumbers); - const inputs = [ 9, 8, 7, 8, 1, 9, 1, 2, 3, 3, 3, 0, 2 ]; + const inputs = [9, 8, 7, 8, 1, 9, 1, 2, 3, 3, 3, 0, 2]; for (const input of inputs) map.insert(input); diff --git a/core/bentley/src/test/InstanceOf.test.ts b/core/bentley/src/test/InstanceOf.test.ts index 4d0496fae214..22bdc1231181 100644 --- a/core/bentley/src/test/InstanceOf.test.ts +++ b/core/bentley/src/test/InstanceOf.test.ts @@ -21,7 +21,9 @@ describe("InstanceOf", () => { this.stuff = "private"; } - public static create() { return new PrivateThing(); } + public static create() { + return new PrivateThing(); + } } const test = (value: any, expectInstanceOf = false) => { diff --git a/core/bentley/src/test/LRUMap.test.ts b/core/bentley/src/test/LRUMap.test.ts index 3732f62461f2..ff92cb4b04ea 100644 --- a/core/bentley/src/test/LRUMap.test.ts +++ b/core/bentley/src/test/LRUMap.test.ts @@ -6,7 +6,6 @@ import { assert, describe, it } from "vitest"; import { LRUMap } from "../core-bentley"; describe("LRUMap", () => { - it("get and set", () => { const c = new LRUMap(4); assert.equal(c.size, 0); @@ -314,5 +313,4 @@ describe("LRUMap", () => { { key: "bob", value: 48 }, ]); }); - }); diff --git a/core/bentley/src/test/Logger.test.ts b/core/bentley/src/test/Logger.test.ts index 93ec92efe614..8e07d31c78ed 100644 --- a/core/bentley/src/test/Logger.test.ts +++ b/core/bentley/src/test/Logger.test.ts @@ -5,8 +5,8 @@ import { assert, describe, expect, it } from "vitest"; import { BentleyError, LoggingMetaData } from "../BentleyError"; import { using } from "../Disposable"; -import { Logger, LogLevel, PerfLogger } from "../Logger"; import { staticLoggerMetadata } from "../internal/staticLoggerMetadata"; +import { Logger, LogLevel, PerfLogger } from "../Logger"; import { BeDuration } from "../Time"; let outerr: any[]; @@ -70,7 +70,6 @@ function clearOutlets() { type FunctionReturningAny = () => any; describe("Logger", () => { - it("log without initializing", () => { // logging messages in the components must not cause failures if the app hasn't initialized logging. Logger.logError("test", "An error occurred"); @@ -129,12 +128,12 @@ describe("Logger", () => { }); it("levels", () => { - Logger.initialize( (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); const c1msg: [string, string, FunctionReturningAny | undefined] = ["c1", "message1", () => "metaData1"]; const c2msg: [string, string, FunctionReturningAny | undefined] = ["c2", "message2", undefined]; @@ -213,7 +212,8 @@ describe("Logger", () => { undefined, (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); Logger.setLevel("c1", LogLevel.Warning); Logger.logError.apply(null, c1msg); @@ -229,7 +229,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); Logger.setLevelDefault(LogLevel.Info); Logger.setLevel("c1", LogLevel.Warning); @@ -239,9 +240,9 @@ describe("Logger", () => { Logger.logInfo.apply(null, c4msg); checkOutlets([], [], c4msg, []); // ... but it should come out at the default Info level, even though we never turned on c4, since Info is the default level that applies to all categories. Logger.logWarning.apply(null, c1msg); - checkOutlets([], c1msg, [], []); // c1 should still come out at the warning level + checkOutlets([], c1msg, [], []); // c1 should still come out at the warning level Logger.logInfo.apply(null, c1msg); - checkOutlets([], [], [], []); // ... but not at the Info level, even though that's the default level, because c1 has a specific level setting + checkOutlets([], [], [], []); // ... but not at the Info level, even though that's the default level, because c1 has a specific level setting // ... now turn c4 off. Logger.setLevel("c4", LogLevel.None); @@ -257,7 +258,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); Logger.setLevel("g1", LogLevel.Trace); Logger.setLevel("g2", LogLevel.Error); @@ -273,7 +275,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); Logger.setLevel("g1", LogLevel.Trace); Logger.setLevel("g1.p1", LogLevel.Error); Logger.logWarning("g1.p1.c1", "unexpected"); @@ -289,7 +292,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); const c1msg: [string, string, FunctionReturningAny | undefined] = ["c1", "message1", () => "metaData1"]; const c2msg: [string, string, FunctionReturningAny | undefined] = ["c2", "message2", undefined]; @@ -345,7 +349,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); callLoggerConfigLevels({ categoryLevels: { stuff: 0 } }, true); callLoggerConfigLevels({ xcategoryLevels: [{ category: "c1", logLevel: "Error" }] }, true); @@ -358,12 +363,12 @@ describe("Logger", () => { }); it("turn on logging for a few categories", () => { - Logger.initialize( (c, m, d) => outerr = [c, m, d], (c, m, d) => outwarn = [c, m, d], (c, m, d) => outinfo = [c, m, d], - (c, m, d) => outtrace = [c, m, d]); + (c, m, d) => outtrace = [c, m, d], + ); const c1msg: [string, string, FunctionReturningAny | undefined] = ["c1", "message1", () => "metaData1"]; const c2msg: [string, string, FunctionReturningAny | undefined] = ["c2", "message2", undefined]; @@ -404,24 +409,23 @@ describe("Logger", () => { it("Performance logger", async () => { const perfMessages = new Array(); const perfData = new Array(); - Logger.initialize(undefined, undefined, - (category, message, metadata?: LoggingMetaData) => { - if (category === "Performance") { - perfMessages.push(message); + Logger.initialize(undefined, undefined, (category, message, metadata?: LoggingMetaData) => { + if (category === "Performance") { + perfMessages.push(message); - const data = metadata ? BentleyError.getMetaData(metadata) : {}; - perfData.push(data); - } - }, undefined); + const data = metadata ? BentleyError.getMetaData(metadata) : {}; + perfData.push(data); + } + }, undefined); - await using(new PerfLogger("mytestroutine"), async (_r) => { + using(new PerfLogger("mytestroutine"), async (_r) => { await BeDuration.wait(10); }); assert.isEmpty(perfMessages); Logger.setLevel("Performance", LogLevel.Info); - await using(new PerfLogger("mytestroutine2"), async (_r) => { + using(new PerfLogger("mytestroutine2"), async (_r) => { await BeDuration.wait(10); }); @@ -457,7 +461,8 @@ describe("Logger", () => { (c, m, d) => outerr = [c, m, BentleyError.getMetaData(d)], (c, m, d) => outwarn = [c, m, BentleyError.getMetaData(d)], (c, m, d) => outinfo = [c, m, BentleyError.getMetaData(d)], - (c, m, d) => outtrace = [c, m, BentleyError.getMetaData(d)]); + (c, m, d) => outtrace = [c, m, BentleyError.getMetaData(d)], + ); Logger.setLevel("testcat", LogLevel.Error); clearOutlets(); @@ -475,7 +480,5 @@ describe("Logger", () => { clearOutlets(); expect(() => Logger.logException("testcat", null)).to.not.throw("null exception"); checkOutlets(["testcat", "Error: err is null.", { ExceptionType: "Error" }], [], [], []); - }); - }); diff --git a/core/bentley/src/test/ObservableSet.test.ts b/core/bentley/src/test/ObservableSet.test.ts index 14bca14aee9e..0dcc3c5a78b3 100644 --- a/core/bentley/src/test/ObservableSet.test.ts +++ b/core/bentley/src/test/ObservableSet.test.ts @@ -16,7 +16,9 @@ class Listener { set.onCleared.addListener(() => this._cleared = true); } - private clear() { this._added = this._deleted = this._cleared; } + private clear() { + this._added = this._deleted = this._cleared; + } public expect(added: boolean, deleted: boolean, cleared: boolean, func: () => void): void { this.clear(); @@ -27,10 +29,18 @@ class Listener { this.clear(); } - public expectNone(func: () => void) { this.expect(false, false, false, func); } - public expectAdd(func: () => void) { this.expect(true, false, false, func); } - public expectDelete(func: () => void) { this.expect(false, true, false, func); } - public expectClear(func: () => void) { this.expect(false, false, true, func); } + public expectNone(func: () => void) { + this.expect(false, false, false, func); + } + public expectAdd(func: () => void) { + this.expect(true, false, false, func); + } + public expectDelete(func: () => void) { + this.expect(false, true, false, func); + } + public expectClear(func: () => void) { + this.expect(false, false, true, func); + } } describe("ObservableSet", () => { diff --git a/core/bentley/src/test/OneAtATime.test.ts b/core/bentley/src/test/OneAtATime.test.ts index 55575611b77d..f0bf4e02b844 100644 --- a/core/bentley/src/test/OneAtATime.test.ts +++ b/core/bentley/src/test/OneAtATime.test.ts @@ -16,7 +16,6 @@ import { BeDuration } from "../Time"; // chai.use(chaiAsPromised); describe("OneAtATime test", () => { - it.skip("OneAtATime", async () => { let calls = 0; const operation = new OneAtATimeAction(async (a: number, b: string) => { diff --git a/core/bentley/src/test/SortedArray.test.ts b/core/bentley/src/test/SortedArray.test.ts index 59dadf7b0aad..4ac99f3e76e3 100644 --- a/core/bentley/src/test/SortedArray.test.ts +++ b/core/bentley/src/test/SortedArray.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { compareStrings, SortedArray } from "../core-bentley"; import { compareBooleans, compareNumbers, compareNumbersOrUndefined, compareStringsOrUndefined, compareWithTolerance } from "../Compare"; +import { compareStrings, SortedArray } from "../core-bentley"; class Thing { - public constructor(public readonly first: number, public readonly second: number) { } + public constructor(public readonly first: number, public readonly second: number) {} } function compareThings(lhs: Thing, rhs: Thing) { @@ -22,7 +22,7 @@ function compareThings(lhs: Thing, rhs: Thing) { } export class Id { - public constructor(public readonly value: string) { } + public constructor(public readonly value: string) {} public compare(rhs: Id) { if (this === rhs || this.value === rhs.value) @@ -113,7 +113,6 @@ describe("SortedArray", () => { list.insert(new Id(toInsert)); expect(list.length, "length of protected array").to.equal(ids.length + lengthA); expectSorted(list.extractArray(), ids.length + 2, true, (lhs: Id, rhs: Id) => lhs.compare(rhs)); - }); it("Number array", () => { @@ -130,7 +129,7 @@ describe("SortedArray", () => { sumAll += toInsert; } - expect(listA.findEqual(sumAll)).to.be.undefined; // sum of positives is larger + expect(listA.findEqual(sumAll)).to.be.undefined; // sum of positives is larger expect(sumBInsert).to.equal(sumAll); let sumA = 0; @@ -149,13 +148,12 @@ describe("SortedArray", () => { expect(listA.contains(a)).to.be.false; const removeB = listB.remove(a); expect(removeB, "listB should have all original entries with duplicates").is.gte(0); - if (removeA === -1) // this must be removal of a dup. + if (removeA === -1) // this must be removal of a dup. numDuplicatesDuringRemoval++; } expect(numDuplicates).to.be.equal(numDuplicatesDuringRemoval); listA.clear(); expect(listA.isEmpty).to.be.true; - }); it("Should support iteration", () => { diff --git a/core/bentley/src/test/Time.test.ts b/core/bentley/src/test/Time.test.ts index 85e92068d7f7..79d4d4450196 100644 --- a/core/bentley/src/test/Time.test.ts +++ b/core/bentley/src/test/Time.test.ts @@ -7,7 +7,6 @@ import { assert, describe, it } from "vitest"; import { BeDuration } from "../Time"; describe("BeDuration", () => { - class Test { private _a = 33; public doTest(arg1: number, arg2: string) { @@ -25,5 +24,4 @@ describe("BeDuration", () => { assert.equal(val, 33); assert.isAtLeast(Date.now(), start + 400); // use 400ms to avoid false failures if precision of timing is reduced }); - }); diff --git a/core/bentley/src/test/TupleKeyedMap.test.ts b/core/bentley/src/test/TupleKeyedMap.test.ts index 181cded08f43..5cd04fa7e42f 100644 --- a/core/bentley/src/test/TupleKeyedMap.test.ts +++ b/core/bentley/src/test/TupleKeyedMap.test.ts @@ -50,9 +50,9 @@ describe("TupleKeyedMap", () => { // subkey-level insertion order is expected because the underlying Map guarantees insertion order const iter = map[Symbol.iterator](); - expect(iter.next()).to.deep.equal({ value: [["three", 3, c], 10], done: false}); - expect(iter.next()).to.deep.equal({ value: [["three", 4, c], 11], done: false}); - expect(iter.next()).to.deep.equal({ value: [["four", 4, d], 4], done: false}); + expect(iter.next()).to.deep.equal({ value: [["three", 3, c], 10], done: false }); + expect(iter.next()).to.deep.equal({ value: [["three", 4, c], 11], done: false }); + expect(iter.next()).to.deep.equal({ value: [["four", 4, d], 4], done: false }); expect(iter.next()).to.deep.equal({ value: undefined, done: true }); }); }); diff --git a/core/bentley/src/test/UnexpectedErrors.test.ts b/core/bentley/src/test/UnexpectedErrors.test.ts index d5b93ca0078f..f6c0bf209f89 100644 --- a/core/bentley/src/test/UnexpectedErrors.test.ts +++ b/core/bentley/src/test/UnexpectedErrors.test.ts @@ -8,7 +8,6 @@ import { BeEvent } from "../BeEvent"; import { UnexpectedErrors } from "../UnexpectedErrors"; describe("Unexpected error handling", () => { - it("from BeEvent", () => { let unexpectedCalled = 0; let telemetry1 = 0; diff --git a/core/bentley/src/test/YieldManager.test.ts b/core/bentley/src/test/YieldManager.test.ts index 759cd595c50f..b76acb8b67c1 100644 --- a/core/bentley/src/test/YieldManager.test.ts +++ b/core/bentley/src/test/YieldManager.test.ts @@ -18,7 +18,6 @@ describe("YieldManager", () => { yieldManager.actualYieldCount++; }; for (let i = 0; i < expectedYieldTimes * yieldManager.options.iterationsBeforeYield; ++i) { - await yieldManager.allowYield(); } diff --git a/core/bentley/src/test/partitionArray.test.ts b/core/bentley/src/test/partitionArray.test.ts index bb3583ba1195..22dc2a218831 100644 --- a/core/bentley/src/test/partitionArray.test.ts +++ b/core/bentley/src/test/partitionArray.test.ts @@ -11,24 +11,24 @@ describe("partitionArray", () => { return 0 === n % 2; } - type Test = [ number[], number ]; + type Test = [number[], number]; const tests: Test[] = [ - [ [], 0 ], - [ [1], 0 ], - [ [2], 1 ], - [ [1, 1], 0 ], - [ [2, 2], 2 ], - [ [1, 1, 1], 0 ], - [ [2, 2, 2], 3 ], - [ [1, 2], 1 ], - [ [2, 1], 1 ], - [ [1, 2, 3, 4], 2 ], - [ [4, 3, 2, 1], 2 ], - [ [1, 2, 3], 1 ], - [ [4, 3, 2], 2 ], - [ [4, 1, 2, 3, 2, 4, 1, 3], 4 ], - [ [4, 1, 2, 3, 2, 4, 1], 4 ], - [ [4, 1, 2, 3, 3, 4, 1], 3 ], + [[], 0], + [[1], 0], + [[2], 1], + [[1, 1], 0], + [[2, 2], 2], + [[1, 1, 1], 0], + [[2, 2, 2], 3], + [[1, 2], 1], + [[2, 1], 1], + [[1, 2, 3, 4], 2], + [[4, 3, 2, 1], 2], + [[1, 2, 3], 1], + [[4, 3, 2], 2], + [[4, 1, 2, 3, 2, 4, 1, 3], 4], + [[4, 1, 2, 3, 2, 4, 1], 4], + [[4, 1, 2, 3, 3, 4, 1], 3], ]; for (const test of tests) { diff --git a/core/bentley/vitest.config.mts b/core/bentley/vitest.config.mts index 7ab32697945d..8bc406cb1d78 100644 --- a/core/bentley/vitest.config.mts +++ b/core/bentley/vitest.config.mts @@ -1,24 +1,24 @@ -import { coverageConfigDefaults, defineConfig } from 'vitest/config'; +import { coverageConfigDefaults, defineConfig } from "vitest/config"; export default defineConfig({ test: { dir: "src", coverage: { provider: "v8", include: [ - "src/**/*" + "src/**/*", ], exclude: [ ...coverageConfigDefaults.exclude, "src/test/**/*", "**/*.d.ts", - "**/*.d.tsx" + "**/*.d.tsx", ], reporter: [ "text-summary", "lcov", - "cobertura" + "cobertura", ], reportsDirectory: "./lib/cjs/test/coverage", - } - } -}) + }, + }, +}); diff --git a/core/common/eslint.config.js b/core/common/eslint.config.js index 1b0e5731e3c6..28429aefc25c 100644 --- a/core/common/eslint.config.js +++ b/core/common/eslint.config.js @@ -13,12 +13,12 @@ module.exports = [ "error", { "releaseTags": [ - "public" + "public", ], - "outputApiFile": false - } - ] - } + "outputApiFile": false, + }, + ], + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/common/extraction.eslint.config.js b/core/common/extraction.eslint.config.js index eafbeebb72e5..617611e8b28d 100644 --- a/core/common/extraction.eslint.config.js +++ b/core/common/extraction.eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.extensionExportsConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/common/src/AmbientOcclusion.ts b/core/common/src/AmbientOcclusion.ts index ea81d61ee1cf..a72e6799ba2f 100644 --- a/core/common/src/AmbientOcclusion.ts +++ b/core/common/src/AmbientOcclusion.ts @@ -68,7 +68,9 @@ export namespace AmbientOcclusion { public static defaults = new Settings({}); - public static fromJSON(json?: Props): Settings { return undefined !== json ? new Settings(json) : this.defaults; } + public static fromJSON(json?: Props): Settings { + return undefined !== json ? new Settings(json) : this.defaults; + } public toJSON(): Props { return { diff --git a/core/common/src/AnalysisStyle.ts b/core/common/src/AnalysisStyle.ts index fa0710d4c67a..9e237bd6deb1 100644 --- a/core/common/src/AnalysisStyle.ts +++ b/core/common/src/AnalysisStyle.ts @@ -7,8 +7,8 @@ */ import { Range1d, Range1dProps } from "@itwin/core-geometry"; -import { ThematicGradientSettings, ThematicGradientSettingsProps } from "./ThematicDisplay"; import { Gradient } from "./Gradient"; +import { ThematicGradientSettings, ThematicGradientSettingsProps } from "./ThematicDisplay"; /** JSON representation of an [[AnalysisStyleDisplacement]]. * @see [[AnalysisStyleProps.displacement]]. diff --git a/core/common/src/Atmosphere.ts b/core/common/src/Atmosphere.ts index 1d787236b29d..be6d1e5cfe9b 100644 --- a/core/common/src/Atmosphere.ts +++ b/core/common/src/Atmosphere.ts @@ -28,7 +28,6 @@ import { JsonUtils } from "@itwin/core-bentley"; * Both of which are inspired by this Nvidia article on atmospheric scattering: https://developer.nvidia.com/gpugems/gpugems2/part-ii-shading-lighting-and-shadows/chapter-16-accurate-atmospheric-scattering. */ export namespace Atmosphere { - /** @internal JSON representation of a [[Wavelengths]] object */ export interface WavelengthsProps { r: number; diff --git a/core/common/src/BackendTypes.ts b/core/common/src/BackendTypes.ts index 57af1b031c11..9a263fc29cff 100644 --- a/core/common/src/BackendTypes.ts +++ b/core/common/src/BackendTypes.ts @@ -6,8 +6,8 @@ * @module Utils */ -import type { Readable, Writable } from "stream"; // Must be "import type" to avoid webpack polyfill errors import type { Buffer } from "buffer"; // Must be "import type" to avoid webpack polyfill errors +import type { Readable, Writable } from "stream"; // Must be "import type" to avoid webpack polyfill errors /* IMPORTANT: diff --git a/core/common/src/BackgroundMapSettings.ts b/core/common/src/BackgroundMapSettings.ts index 941239e50c4c..d8cc1bc7d0fe 100644 --- a/core/common/src/BackgroundMapSettings.ts +++ b/core/common/src/BackgroundMapSettings.ts @@ -136,7 +136,9 @@ export class BackgroundMapSettings { } /** If transparency is overridden, the transparency to apply; otherwise, undefined. */ - public get transparencyOverride(): number | undefined { return false !== this.transparency ? this.transparency : undefined; } + public get transparencyOverride(): number | undefined { + return false !== this.transparency ? this.transparency : undefined; + } private constructor(props: BackgroundMapProps | PersistentBackgroundMapProps) { this.groundBias = props.groundBias ?? 0; @@ -244,7 +246,9 @@ export class BackgroundMapSettings { globeMode: changedProps.globeMode ?? this.globeMode, nonLocatable: changedProps.nonLocatable ?? !this._locatable, applyTerrain: changedProps.applyTerrain ?? this.applyTerrain, - terrainSettings: changedProps.terrainSettings ? this.terrainSettings.clone(changedProps.terrainSettings).toJSON() : this.terrainSettings.toJSON(), + terrainSettings: changedProps.terrainSettings + ? this.terrainSettings.clone(changedProps.terrainSettings).toJSON() + : this.terrainSettings.toJSON(), planarClipMask: changedProps.planarClipMask ? this.planarClipMask.clone(changedProps.planarClipMask).toJSON() : this.planarClipMask.toJSON(), providerName: this._provider.name, providerData: { mapType: this._provider.type }, diff --git a/core/common/src/BlobReader.ts b/core/common/src/BlobReader.ts index e7e3b505369b..98143f5dfb80 100644 --- a/core/common/src/BlobReader.ts +++ b/core/common/src/BlobReader.ts @@ -7,7 +7,14 @@ */ import { Id64String } from "@itwin/core-bentley"; import { - BlobOptions, BlobOptionsBuilder, BlobRange, DbBlobRequest, DbBlobResponse, DbQueryError, DbRequestExecutor, DbRequestKind, + BlobOptions, + BlobOptionsBuilder, + BlobRange, + DbBlobRequest, + DbBlobResponse, + DbQueryError, + DbRequestExecutor, + DbRequestKind, } from "./ConcurrentQuery"; /** @beta */ @@ -16,8 +23,12 @@ export class Uint8Chunks implements Iterable { public append(chunk: Uint8Array) { this._chunks.push(chunk); } - public at(idx: number) { return this._chunks[idx]; } - public get length() { return this._chunks.length; } + public at(idx: number) { + return this._chunks[idx]; + } + public get length() { + return this._chunks.length; + } public [Symbol.iterator](): Iterator { return (this._chunks as any)[Symbol.iterator]; } @@ -37,11 +48,13 @@ export class BlobReader { private _chunks = new Uint8Chunks(); private _lengthToRead: number = -1; private _options = new BlobOptionsBuilder().getOptions(); - public constructor(private _executor: DbRequestExecutor, + public constructor( + private _executor: DbRequestExecutor, public readonly className: string, public readonly accessString: string, public readonly instanceId: Id64String, - options?: BlobOptions) { + options?: BlobOptions, + ) { this.reset(options); } public reset(options?: BlobOptions) { @@ -51,7 +64,9 @@ export class BlobReader { this._chunks = new Uint8Chunks(); this._lengthToRead = this.range.count!; } - public get range(): BlobRange { return this._options.range!; } + public get range(): BlobRange { + return this._options.range!; + } public async step(): Promise { if (this._lengthToRead === this._chunks.length) { return false; @@ -63,7 +78,7 @@ export class BlobReader { instanceId: this.instanceId, ...this._options, }; - request.range = {offset: this._chunks.length, count: this.range ? this._lengthToRead - this._chunks.length : 0}; + request.range = { offset: this._chunks.length, count: this.range ? this._lengthToRead - this._chunks.length : 0 }; const resp = await this._executor.execute(request); DbQueryError.throwIfError(resp, request); @@ -76,7 +91,7 @@ export class BlobReader { return true; } public async readToEnd(): Promise { - while (await this.step()) { } + while (await this.step()) {} return this._chunks.combine(); } public get current(): Uint8Array { @@ -85,5 +100,7 @@ export class BlobReader { } return this._chunks.at(this._chunks.length); } - public get chunks(): Uint8Chunks { return this._chunks; } + public get chunks(): Uint8Chunks { + return this._chunks; + } } diff --git a/core/common/src/BriefcaseTypes.ts b/core/common/src/BriefcaseTypes.ts index 113508ae1876..e8c5ca2b3a6d 100644 --- a/core/common/src/BriefcaseTypes.ts +++ b/core/common/src/BriefcaseTypes.ts @@ -155,7 +155,6 @@ export interface RequestNewBriefcaseProps { * After downloading, you can merely delete unassigned briefcase files when they are no longer needed. Assigned BriefcaseIds should be released (via [BriefcaseManager.releaseBriefcase]($backend) ) * when you are done with them. * @note this member is both an input and an output. - * */ briefcaseId?: BriefcaseId; diff --git a/core/common/src/Camera.ts b/core/common/src/Camera.ts index efd28d726028..3ea09233b442 100644 --- a/core/common/src/Camera.ts +++ b/core/common/src/Camera.ts @@ -37,23 +37,47 @@ export class Camera implements CameraProps { val.setRadians(Math.PI / 2.0); } - public invalidateFocus() { this.focusDist = 0.0; } - public get isFocusValid() { return this.focusDist > 0.0 && this.focusDist < 1.0e14; } - public getFocusDistance() { return this.focusDist; } - public setFocusDistance(dist: number) { this.focusDist = dist; } - public get isLensValid() { return Camera.isValidLensAngle(this.lens); } - public validateLens() { Camera.validateLensAngle(this.lens); } - public getLensAngle() { return this.lens; } - public setLensAngle(angle: Angle) { this.lens.setFrom(angle); } - public getEyePoint() { return this.eye; } - public setEyePoint(pt: XYAndZ) { this.eye.setFrom(pt); } - public get isValid() { return this.isLensValid && this.isFocusValid; } + public invalidateFocus() { + this.focusDist = 0.0; + } + public get isFocusValid() { + return this.focusDist > 0.0 && this.focusDist < 1.0e14; + } + public getFocusDistance() { + return this.focusDist; + } + public setFocusDistance(dist: number) { + this.focusDist = dist; + } + public get isLensValid() { + return Camera.isValidLensAngle(this.lens); + } + public validateLens() { + Camera.validateLensAngle(this.lens); + } + public getLensAngle() { + return this.lens; + } + public setLensAngle(angle: Angle) { + this.lens.setFrom(angle); + } + public getEyePoint() { + return this.eye; + } + public setEyePoint(pt: XYAndZ) { + this.eye.setFrom(pt); + } + public get isValid() { + return this.isLensValid && this.isFocusValid; + } public equals(other: Camera) { return Math.abs(this.lens.radians - other.lens.radians) < .01 && Math.abs(this.focusDist - other.focusDist) < .1 && this.eye.isAlmostEqual(other.eye); } - public clone() { return new Camera(this); } + public clone() { + return new Camera(this); + } public setFrom(rhs: Camera) { this.lens.setFrom(rhs.lens); this.focusDist = rhs.focusDist; diff --git a/core/common/src/ChangedElements.ts b/core/common/src/ChangedElements.ts index d05e3d813e65..20ebd4d039d7 100644 --- a/core/common/src/ChangedElements.ts +++ b/core/common/src/ChangedElements.ts @@ -56,7 +56,7 @@ export interface ChangedElements { modelIds?: Id64String[]; /** Property accessor strings of properties that changed, if any, for each changed element * This may be undefined if the agent that did the processing job did not export properties - */ + */ properties?: string[][]; /** Before state checksums of the property value * Useful to determine if property values have changed diff --git a/core/common/src/ChangesetProps.ts b/core/common/src/ChangesetProps.ts index 9c903651c852..cb06c75bfff7 100644 --- a/core/common/src/ChangesetProps.ts +++ b/core/common/src/ChangesetProps.ts @@ -30,19 +30,28 @@ export type ChangesetIndex = number; * @public * @extensions */ -export interface ChangesetIndexAndId { readonly index: ChangesetIndex, readonly id: ChangesetId } +export interface ChangesetIndexAndId { + readonly index: ChangesetIndex; + readonly id: ChangesetId; +} /** The Id and optionally the index of a changeset * @public * @extensions */ -export interface ChangesetIdWithIndex { readonly index?: ChangesetIndex, readonly id: ChangesetId } +export interface ChangesetIdWithIndex { + readonly index?: ChangesetIndex; + readonly id: ChangesetId; +} /** either changeset index, id, or both -* @public + * @public * @extensions -*/ -export type ChangesetIndexOrId = ChangesetIndexAndId | { readonly index: ChangesetIndex, readonly id?: never } | { readonly id: ChangesetId, readonly index?: never }; + */ +export type ChangesetIndexOrId = ChangesetIndexAndId | { readonly index: ChangesetIndex, readonly id?: never } | { + readonly id: ChangesetId; + readonly index?: never; +}; /** Value to indicate whether a changeset contains schema changes or not * @public diff --git a/core/common/src/ClipStyle.ts b/core/common/src/ClipStyle.ts index caa5251ddb84..848a05ec86cd 100644 --- a/core/common/src/ClipStyle.ts +++ b/core/common/src/ClipStyle.ts @@ -7,11 +7,11 @@ */ import { assert, JsonUtils } from "@itwin/core-bentley"; -import { ViewFlagOverrides } from "./ViewFlags"; -import { RgbColor, RgbColorProps } from "./RgbColor"; -import { HiddenLine } from "./HiddenLine"; -import { FeatureAppearance, FeatureAppearanceProps } from "./FeatureSymbology"; import { ColorDef } from "./ColorDef"; +import { FeatureAppearance, FeatureAppearanceProps } from "./FeatureSymbology"; +import { HiddenLine } from "./HiddenLine"; +import { RgbColor, RgbColorProps } from "./RgbColor"; +import { ViewFlagOverrides } from "./ViewFlags"; /** Wire format describing a [[CutStyle]] applied to section-cut geometry produced at intersections with a view's [ClipVector]($core-geometry). * @see [[ClipStyleProps.cutStyle]]. @@ -53,7 +53,10 @@ export class CutStyle { /** Create a CutStyle from its components. */ public static create(viewflags?: Readonly, hiddenLine?: HiddenLine.Settings, appearance?: FeatureAppearance): CutStyle { - if ((viewflags && JsonUtils.isNonEmptyObject(viewflags)) || (hiddenLine && !hiddenLine.matchesDefaults) || (appearance && !appearance.matchesDefaults)) + if ( + (viewflags && JsonUtils.isNonEmptyObject(viewflags)) || (hiddenLine && !hiddenLine.matchesDefaults) || + (appearance && !appearance.matchesDefaults) + ) return new CutStyle(viewflags, hiddenLine, appearance); return this.defaults; @@ -94,7 +97,8 @@ export class CutStyle { if (this === CutStyle.defaults) return true; - return !JsonUtils.isNonEmptyObject(this.viewflags) && (!this.hiddenLine || this.hiddenLine.matchesDefaults) && (!this.appearance || this.appearance.matchesDefaults); + return !JsonUtils.isNonEmptyObject(this.viewflags) && (!this.hiddenLine || this.hiddenLine.matchesDefaults) && + (!this.appearance || this.appearance.matchesDefaults); } } @@ -242,7 +246,14 @@ export class ClipStyle { /** The default style, which overrides none of the view's settings. */ public static readonly defaults = new ClipStyle(false, false, CutStyle.defaults, undefined, undefined, undefined); - private constructor(produceCutGeometry: boolean, colorizeIntersection: boolean, cutStyle: CutStyle, inside: RgbColor | undefined, outside: RgbColor | undefined, intersectionStyle: ClipIntersectionStyle | undefined) { + private constructor( + produceCutGeometry: boolean, + colorizeIntersection: boolean, + cutStyle: CutStyle, + inside: RgbColor | undefined, + outside: RgbColor | undefined, + intersectionStyle: ClipIntersectionStyle | undefined, + ) { this.produceCutGeometry = produceCutGeometry; this.colorizeIntersection = colorizeIntersection; this.cutStyle = cutStyle; @@ -258,8 +269,12 @@ export class ClipStyle { public static create(style: ClipStyleCreateArgs): ClipStyle; /** @internal */ - public static create(styleOrProduceCutGeometry: ClipStyleCreateArgs | boolean, cutStyle?: CutStyle, insideColor?: RgbColor, outsideColor?: RgbColor): ClipStyle { - + public static create( + styleOrProduceCutGeometry: ClipStyleCreateArgs | boolean, + cutStyle?: CutStyle, + insideColor?: RgbColor, + outsideColor?: RgbColor, + ): ClipStyle { if (typeof styleOrProduceCutGeometry === "boolean") { cutStyle = cutStyle === undefined ? CutStyle.defaults : cutStyle; @@ -271,14 +286,17 @@ export class ClipStyle { } const style = styleOrProduceCutGeometry; - if (!style.produceCutGeometry && !style.colorizeIntersection && (!style.cutStyle || style.cutStyle.matchesDefaults) && !style.insideColor && !style.outsideColor && !style.intersectionStyle) + if ( + !style.produceCutGeometry && !style.colorizeIntersection && (!style.cutStyle || style.cutStyle.matchesDefaults) && !style.insideColor && + !style.outsideColor && !style.intersectionStyle + ) return this.defaults; const produceCutGeometry = style.produceCutGeometry ? true : false; const colorizeIntersection = style.colorizeIntersection ? true : false; cutStyle = style.cutStyle === undefined ? CutStyle.defaults : style.cutStyle; - return new ClipStyle(produceCutGeometry, colorizeIntersection, cutStyle, style.insideColor, style.outsideColor, style.intersectionStyle); + return new ClipStyle(produceCutGeometry, colorizeIntersection, cutStyle, style.insideColor, style.outsideColor, style.intersectionStyle); } public static fromJSON(props?: ClipStyleProps): ClipStyle { @@ -290,7 +308,7 @@ export class ClipStyle { const outsideColor = props.outsideColor ? RgbColor.fromJSON(props.outsideColor) : undefined; const intersectionStyle = props.intersectionStyle ? ClipIntersectionStyle.fromJSON(props.intersectionStyle) : undefined; - return this.create({produceCutGeometry, colorizeIntersection, cutStyle, insideColor, outsideColor, intersectionStyle}); + return this.create({ produceCutGeometry, colorizeIntersection, cutStyle, insideColor, outsideColor, intersectionStyle }); } return this.defaults; @@ -331,6 +349,7 @@ export class ClipStyle { if (this === ClipStyle.defaults) return true; - return !this.produceCutGeometry && !this.colorizeIntersection && !this.insideColor && !this.outsideColor && this.cutStyle.matchesDefaults && !this.intersectionStyle; + return !this.produceCutGeometry && !this.colorizeIntersection && !this.insideColor && !this.outsideColor && this.cutStyle.matchesDefaults && + !this.intersectionStyle; } } diff --git a/core/common/src/Code.ts b/core/common/src/Code.ts index 0a4755b7c15d..9985bb46afe8 100644 --- a/core/common/src/Code.ts +++ b/core/common/src/Code.ts @@ -42,8 +42,12 @@ export class Code implements CodeProps { /** The [CodeValue]($docs/bis/guide/fundamentals/codes.md#codevalue-property) of the Element * @note Leading and trailing whitespace is invalid so is automatically trimmed. */ - public get value() { return this._value ?? ""; } - public set value(val: string) { this._value = val?.trim(); } + public get value() { + return this._value ?? ""; + } + public set value(val: string) { + this._value = val?.trim(); + } private _value?: string; constructor(codeProps: CodeProps) { @@ -58,26 +62,38 @@ export class Code implements CodeProps { return new Code({ spec: id, scope: id }); } - public static fromJSON(json?: any): Code { return json ? new Code(json) : Code.createEmpty(); } - public toJSON(): CodeProps { return { spec: this.spec, scope: this.scope, value: this.value }; } - public equals(other: Code): boolean { return Code.equalCodes(this, other); } + public static fromJSON(json?: any): Code { + return json ? new Code(json) : Code.createEmpty(); + } + public toJSON(): CodeProps { + return { spec: this.spec, scope: this.scope, value: this.value }; + } + public equals(other: Code): boolean { + return Code.equalCodes(this, other); + } /** @internal */ public static equalCodes(c1: CodeProps, c2: CodeProps): boolean { return c1.spec === c2.spec && c1.scope === c2.scope && c1.value === c2.value; } /** Determine whether this Code is valid. */ - public static isValid(c: CodeProps): boolean { return Id64.isValidId64(c.spec); } + public static isValid(c: CodeProps): boolean { + return Id64.isValidId64(c.spec); + } /** Determine if this code is valid but not otherwise meaningful (and therefore not necessarily unique) */ - public static isEmpty(c: CodeProps): boolean { return this.isValid(c) && (c.value === undefined || c.value === ""); } + public static isEmpty(c: CodeProps): boolean { + return this.isValid(c) && (c.value === undefined || c.value === ""); + } - public toString(): string { return `[Code: ${this.spec}, ${this.scope}, ${this.value}]`; } + public toString(): string { + return `[Code: ${this.spec}, ${this.scope}, ${this.value}]`; + } } /** Names of the internal BIS CodeSpecs. These names match those specified by the native library. * For other domains, the best practice is to include the domain name or alias as part of the CodeSpec name to ensure global uniqueness. * @public -* @extensions -* @see [CodeSpec]($docs/bis/guide/fundamentals/codes.md#codespec) + * @extensions + * @see [CodeSpec]($docs/bis/guide/fundamentals/codes.md#codespec) */ export enum BisCodeSpec { /** The name of the standard [[CodeSpec]] used when creating *empty* codes. @@ -312,14 +328,20 @@ export class CodeSpec { } /** Will be true if the id of this CodeSpec is valid. */ - public get isValid(): boolean { return Id64.isValid(this.id); } + public get isValid(): boolean { + return Id64.isValid(this.id); + } public get isExternal(): boolean { return true === this.properties.scopeSpec.fGuidRequired; } /** The scope type of this CodeSpec. */ - public get scopeType(): CodeScopeSpec.Type { return this.properties.scopeSpec.type; } - public set scopeType(scopeType: CodeScopeSpec.Type) { this.properties.scopeSpec.type = scopeType; } + public get scopeType(): CodeScopeSpec.Type { + return this.properties.scopeSpec.type; + } + public set scopeType(scopeType: CodeScopeSpec.Type) { + this.properties.scopeSpec.type = scopeType; + } /** Will be `CodeScopeSpec.ScopeRequirement.FederationGuid` if the scoping element is required to have a FederationGuid or * CodeScopeSpec.ScopeRequirement.ElementId` otherwise (the default). diff --git a/core/common/src/ColorDef.ts b/core/common/src/ColorDef.ts index d670d2b0bd3a..b25a5ff95068 100644 --- a/core/common/src/ColorDef.ts +++ b/core/common/src/ColorDef.ts @@ -51,7 +51,7 @@ export class ColorDef { private readonly _tbgr: number; private constructor(tbgr: number) { - scratchUInt32[0] = tbgr; // Force to be a 32-bit unsigned integer + scratchUInt32[0] = tbgr; // Force to be a 32-bit unsigned integer this._tbgr = scratchUInt32[0]; } @@ -80,7 +80,9 @@ export class ColorDef { } /** Convert this ColorDef to a 32 bit number representing the 0xTTBBGGRR value */ - public toJSON(): ColorDefProps { return this._tbgr; } + public toJSON(): ColorDefProps { + return this._tbgr; + } /** Create a new ColorDef from a json object. If the json object is a number, it is assumed to be a 0xTTBBGGRR value. */ public static fromJSON(json?: ColorDefProps): ColorDef { @@ -193,7 +195,8 @@ export class ColorDef { intOrPercent(color[1]), intOrPercent(color[2]), intOrPercent(color[3]), - typeof color[5] === "string" ? 255 - floatOrPercent(color[5]) : 0); + typeof color[5] === "string" ? 255 - floatOrPercent(color[5]) : 0, + ); } break; @@ -211,7 +214,7 @@ export class ColorDef { break; } // eslint-disable-next-line no-cond-assign - } else if (m = /^\#([a-f0-9]+)$/.exec(val)) { // hex color + } else if (m = /^\#([a-f0-9]+)$/.exec(val)) { // hex color const hex = m[1]; const size = hex.length; @@ -219,17 +222,21 @@ export class ColorDef { return this.computeTbgrFromComponents( parseInt(hex.charAt(0) + hex.charAt(0), 16), parseInt(hex.charAt(1) + hex.charAt(1), 16), - parseInt(hex.charAt(2) + hex.charAt(2), 16), 0); + parseInt(hex.charAt(2) + hex.charAt(2), 16), + 0, + ); } - if (size === 6) { // #ff0000 + if (size === 6) { // #ff0000 return this.computeTbgrFromComponents( parseInt(hex.charAt(0) + hex.charAt(1), 16), parseInt(hex.charAt(2) + hex.charAt(3), 16), - parseInt(hex.charAt(4) + hex.charAt(5), 16), 0); + parseInt(hex.charAt(4) + hex.charAt(5), 16), + 0, + ); } } - if (val && val.length > 0) { // ColorRgb value + if (val && val.length > 0) { // ColorRgb value for (const [key, value] of Object.entries(ColorByName)) if (key.toLowerCase() === val) return value; @@ -255,7 +262,9 @@ export class ColorDef { } /** The color value of this ColorDef as an integer in the form 0xTTBBGGRR (red in the low byte) */ - public get tbgr(): ColorDefProps { return this._tbgr; } + public get tbgr(): ColorDefProps { + return this._tbgr; + } /** Get the value of the color as a number in 0xAABBGGRR format (i.e. red is in low byte). Transparency (0==fully opaque) converted to alpha (0==fully transparent). */ public getAbgr(): number { @@ -476,7 +485,8 @@ export class ColorDef { hue2rgb(q, p, h + 1 / 3), hue2rgb(q, p, h), hue2rgb(q, p, h - 1 / 3), - transparency); + transparency, + ); } /** Create an [[HSLColor]] from this ColorDef */ @@ -539,11 +549,14 @@ export class ColorDef { const blueDistance = (max - b) / deltaRgb; let intermediateHue: number; - if (r === max) /* color between yellow & magenta */ + if (r === max) + /* color between yellow & magenta */ intermediateHue = blueDistance - greenDistance; - else if (g === max) /* color between cyan & yellow */ + else if (g === max) + /* color between cyan & yellow */ intermediateHue = 2.0 + redDistance - blueDistance; - else /* color between magenta & cyan */ + /* color between magenta & cyan */ + else intermediateHue = 4.0 + greenDistance - redDistance; /* intermediate hue is [0..6] */ @@ -590,13 +603,33 @@ export class ColorDef { let r = 0, b = 0, g = 0; switch (hueIntpart) { /* eslint-disable max-statements-per-line */ - case 0: r = v; g = t; b = p; break; // reddish - case 1: r = q, g = v; b = p; break; // yellowish - case 2: r = p, g = v; b = t; break; // greenish - case 3: r = p, g = q; b = v; break; // cyanish - case 4: r = t, g = p; b = v; break; // bluish - case 5: r = v, g = p; b = q; break; // magenta-ish - /* eslint-enable max-statements-per-line */ + case 0: + r = v; + g = t; + b = p; + break; // reddish + case 1: + r = q, g = v; + b = p; + break; // yellowish + case 2: + r = p, g = v; + b = t; + break; // greenish + case 3: + r = p, g = q; + b = v; + break; // cyanish + case 4: + r = t, g = p; + b = v; + break; // bluish + case 5: + r = v, g = p; + b = q; + break; + /* eslint-enable max-statements-per-line */ + // magenta-ish } return ColorDef.from(r, g, b, transparency); diff --git a/core/common/src/ConcurrentQuery.ts b/core/common/src/ConcurrentQuery.ts index 1711fd52735e..1d3059ab142a 100644 --- a/core/common/src/ConcurrentQuery.ts +++ b/core/common/src/ConcurrentQuery.ts @@ -35,7 +35,7 @@ export enum QueryRowFormat { * Specify limit or range of rows to return * @public * @extensions - * */ + */ export interface QueryLimit { /** Number of rows to return */ count?: number; @@ -80,7 +80,7 @@ export interface DbRuntimeStats { * Quota hint for the query. * @public * @extensions - * */ + */ export interface QueryQuota { /** Max time allowed in seconds. This is hint and may not be honoured but help in prioritize request */ time?: number; @@ -99,8 +99,8 @@ export interface BaseReaderOptions { /** If specified cancel last query (if any) with same restart token and queue the new query */ restartToken?: string; /** For editing apps this can be set to true and all query will run on primary connection - * his may cause slow queries execution but the most recent data changes will be visitable via query - */ + * his may cause slow queries execution but the most recent data changes will be visitable via query + */ usePrimaryConn?: boolean; /** Restrict time or memory for query but use as hint and may be changed base on backend settings */ quota?: QueryQuota; @@ -116,12 +116,12 @@ export interface BaseReaderOptions { * ECSql query config * @public * @extensions - * */ + */ export interface QueryOptions extends BaseReaderOptions { /** * default to false. It abbreviate blobs to single bytes. This help cases where wildcard is * used in select clause. Use BlobReader api to read individual blob specially if its of large size. - * */ + */ abbreviateBlobs?: boolean; /** * default to false. It will suppress error and will not log it. Useful in cases where we expect query @@ -135,7 +135,7 @@ export interface QueryOptions extends BaseReaderOptions { /** * Convert ECClassId, SourceECClassId, TargetECClassId and RelClassId to respective name. * When true, XXXXClassId property will be returned as className. - * */ + */ convertClassIdsToClassNames?: boolean; /** * Determine row format. @@ -152,8 +152,10 @@ export interface BlobOptions extends BaseReaderOptions { /** @public */ export class QueryOptionsBuilder { - public constructor(private _options: QueryOptions = {}) { } - public getOptions(): QueryOptions { return this._options; } + public constructor(private _options: QueryOptions = {}) {} + public getOptions(): QueryOptions { + return this._options; + } /** * @internal * Allow to set priority of query. Query will be inserted int queue base on priority value. This value will be ignored if concurrent query is configured with ignored priority is true. @@ -250,8 +252,10 @@ export class QueryOptionsBuilder { } /** @beta */ export class BlobOptionsBuilder { - public constructor(private _options: BlobOptions = {}) { } - public getOptions(): BlobOptions { return this._options; } + public constructor(private _options: BlobOptions = {}) {} + public getOptions(): BlobOptions { + return this._options; + } /** * @internal * Allow to set priority of blob request. Blob request will be inserted int queue base on priority value. This value will be ignored if concurrent query is configured with ignored priority is true. @@ -399,7 +403,8 @@ export class QueryBinder { const name = String(indexOrName); const base64 = Base64.fromUint8Array(val); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Blob, value: base64, }, @@ -417,7 +422,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Double, value: val, }, @@ -435,7 +441,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Id, value: val, }, @@ -454,7 +461,8 @@ export class QueryBinder { const name = String(indexOrName); OrderedId64Iterable.uniqueIterator(val); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.IdSet, value: CompressedId64Set.sortAndCompress(OrderedId64Iterable.uniqueIterator(val)), }, @@ -472,7 +480,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Integer, value: val, }, @@ -490,7 +499,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Struct, value: val, }, @@ -508,7 +518,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Long, value: val, }, @@ -526,7 +537,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.String, value: val, }, @@ -543,7 +555,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Null, value: null, }, @@ -561,7 +574,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Point2d, value: val, }, @@ -579,7 +593,8 @@ export class QueryBinder { this.verify(indexOrName); const name = String(indexOrName); Object.defineProperty(this._args, name, { - enumerable: true, value: { + enumerable: true, + value: { type: QueryParamType.Point3d, value: val, }, @@ -642,19 +657,19 @@ export class QueryBinder { /** @internal */ export enum DbRequestKind { BlobIO = 0, - ECSql = 1 + ECSql = 1, } /** @internal */ export enum DbResponseKind { BlobIO = DbRequestKind.BlobIO, ECSql = DbRequestKind.ECSql, - NoResult = 2 + NoResult = 2, } /** @internal */ export enum DbResponseStatus { - Done = 1, /* query ran to completion. */ + Done = 1, /* query ran to completion. */ Cancel = 2, /* Requested by user.*/ Partial = 3, /* query was running but ran out of quota.*/ Timeout = 4, /* query time quota expired while it was in queue.*/ @@ -671,7 +686,7 @@ export enum DbResponseStatus { /** @internal */ export enum DbValueFormat { ECSqlNames = 0, - JsNames = 1 + JsNames = 1, } /** @internal */ diff --git a/core/common/src/ContextRealityModel.ts b/core/common/src/ContextRealityModel.ts index d44e009e01d1..6dd972fd5214 100644 --- a/core/common/src/ContextRealityModel.ts +++ b/core/common/src/ContextRealityModel.ts @@ -9,8 +9,8 @@ import { assert, BeEvent } from "@itwin/core-bentley"; import { FeatureAppearance, FeatureAppearanceProps } from "./FeatureSymbology"; import { PlanarClipMaskMode, PlanarClipMaskProps, PlanarClipMaskSettings } from "./PlanarClipMask"; -import { SpatialClassifierProps, SpatialClassifiers, SpatialClassifiersContainer } from "./SpatialClassification"; import { RealityModelDisplayProps, RealityModelDisplaySettings } from "./RealityModelDisplaySettings"; +import { SpatialClassifierProps, SpatialClassifiers, SpatialClassifiersContainer } from "./SpatialClassification"; /** JSON representation of the blob properties for an OrbitGt property cloud. * @alpha @@ -59,11 +59,11 @@ export enum RealityDataProvider { export enum RealityDataFormat { /** * 3dTile supported formats; RealityMesh3DTiles, Terrain3DTiles, Cesium3DTiles - * */ + */ ThreeDTile = "ThreeDTile", /** * Orbit Point Cloud (OPC) storage format (RealityDataType.OPC) - */ + */ OPC = "OPC", } @@ -93,12 +93,12 @@ export interface RealityDataSourceKey { /** * The provider that supplies the access to reality data source for displaying the reality model * @see [[RealityDataProvider]] for default supported value; - */ + */ provider: string; /** * The format used by the provider to store the reality data * @see [[RealityDataFormat]] for default supported value; - */ + */ format: string; /** The reality data id that identify a reality data for the provider */ id: string; @@ -127,7 +127,7 @@ export namespace RealityDataSourceKey { /** JSON representation of the reality data reference attachment properties. * @beta -*/ + */ export interface RealityDataSourceProps { /** The source key that identify a reality data for the provider. */ sourceKey: RealityDataSourceKey; @@ -209,7 +209,9 @@ export namespace ContextRealityModelProps { output.planarClipMask = { ...input.planarClipMask }; if (input.classifiers) - output.classifiers = input.classifiers.map((x) => { return { ...x, flags: { ...x.flags } }; }); + output.classifiers = input.classifiers.map((x) => { + return { ...x, flags: { ...x.flags } }; + }); if (input.invisible) output.invisible = input.invisible; @@ -267,7 +269,10 @@ export class ContextRealityModel { * @param props JSON representation of the reality model, which will be kept in sync with changes made via the ContextRealityModel's methods. * @param options Options to customize how the reality model is created. */ - public constructor(props: ContextRealityModelProps, options?: { createClassifiers: (container: SpatialClassifiersContainer) => SpatialClassifiers }) { + public constructor( + props: ContextRealityModelProps, + options?: { createClassifiers: (container: SpatialClassifiersContainer) => SpatialClassifiers }, + ) { this._props = props; this.rdSourceKey = props.rdSourceKey; this.name = props.name ?? ""; @@ -336,7 +341,7 @@ export class ContextRealityModel { /** If true, reality model is not drawn. * @beta - */ + */ public get invisible(): boolean { return this._invisible; } @@ -428,7 +433,10 @@ export class ContextRealityModels { public constructor(args: ContextRealityModelsArgs); /** @internal */ - public constructor(arg0: ContextRealityModelsContainer | ContextRealityModelsArgs, createContextRealityModel?: (props: ContextRealityModelProps) => ContextRealityModel) { + public constructor( + arg0: ContextRealityModelsContainer | ContextRealityModelsArgs, + createContextRealityModel?: (props: ContextRealityModelProps) => ContextRealityModel, + ) { let container: ContextRealityModelsContainer; let defer = false; if (arg0.container) { @@ -454,9 +462,10 @@ export class ContextRealityModels { public populate(): void { assert(this._models.length === 0, "do not call ContextRealityModels.populate more than once"); const models = this._container.contextRealityModels; - if (models) + if (models) { for (const model of models) this._models.push(this.createModel(model)); + } } /** The read-only list of reality models. */ diff --git a/core/common/src/ContourDisplay.ts b/core/common/src/ContourDisplay.ts index 7a6d544f3567..426c15169847 100644 --- a/core/common/src/ContourDisplay.ts +++ b/core/common/src/ContourDisplay.ts @@ -71,7 +71,7 @@ export class ContourStyle { } private constructor(props?: Partial) { - this.color = props?.color ?? RgbColor.fromJSON({r: 0, g: 0, b: 0}); + this.color = props?.color ?? RgbColor.fromJSON({ r: 0, g: 0, b: 0 }); this.pixelWidth = props?.pixelWidth ?? 1; this.pattern = props?.pattern ?? LinePixels.Solid; } @@ -90,7 +90,7 @@ export class ContourStyle { public toJSON(): ContourStyleProps { const props: ContourStyleProps = {}; - if (!this.color.equals(RgbColor.fromJSON({r: 0, g: 0, b: 0}))) + if (!this.color.equals(RgbColor.fromJSON({ r: 0, g: 0, b: 0 }))) props.color = this.color.toJSON(); if (1 !== this.pixelWidth) @@ -165,17 +165,20 @@ export class Contour { public static readonly defaults = new Contour({}); public equals(other: Contour): boolean { - if (!this.majorStyle.equals(other.majorStyle) || !this.minorStyle.equals(other.minorStyle) || this.minorInterval !== other.minorInterval || this.majorIntervalCount !== other.majorIntervalCount || this.showGeometry !== other.showGeometry) { + if ( + !this.majorStyle.equals(other.majorStyle) || !this.minorStyle.equals(other.minorStyle) || this.minorInterval !== other.minorInterval || + this.majorIntervalCount !== other.majorIntervalCount || this.showGeometry !== other.showGeometry + ) { return false; } return true; } /** Performs ordered comparison of two contours. - * @param lhs First contour to compare - * @param rhs Second contour to compare - * @returns 0 if lhs is equivalent to rhs, a negative number if lhs compares less than rhs, or a positive number if lhs compares greater than rhs. - */ + * @param lhs First contour to compare + * @param rhs Second contour to compare + * @returns 0 if lhs is equivalent to rhs, a negative number if lhs compares less than rhs, or a positive number if lhs compares greater than rhs. + */ public static compare(lhs: Contour, rhs: Contour): number { return ContourStyle.compare(lhs.majorStyle, rhs.majorStyle) || ContourStyle.compare(lhs.minorStyle, rhs.minorStyle) diff --git a/core/common/src/DisplayStyleSettings.ts b/core/common/src/DisplayStyleSettings.ts index 593c1323bb62..941f941ca580 100644 --- a/core/common/src/DisplayStyleSettings.ts +++ b/core/common/src/DisplayStyleSettings.ts @@ -9,7 +9,15 @@ // cspell:ignore greyscale ovrs import { - assert, BeEvent, CompressedId64Set, Id64, Id64Array, Id64String, JsonUtils, MutableCompressedId64Set, OrderedId64Iterable, + assert, + BeEvent, + CompressedId64Set, + Id64, + Id64Array, + Id64String, + JsonUtils, + MutableCompressedId64Set, + OrderedId64Iterable, } from "@itwin/core-bentley"; import { XYZProps } from "@itwin/core-geometry"; import { AmbientOcclusion } from "./AmbientOcclusion"; @@ -17,27 +25,27 @@ import { AnalysisStyle, AnalysisStyleProps } from "./AnalysisStyle"; import { BackgroundMapSettings, PersistentBackgroundMapProps } from "./BackgroundMapSettings"; import { ClipStyle, ClipStyleProps } from "./ClipStyle"; import { ColorDef, ColorDefProps } from "./ColorDef"; +import { ContextRealityModel, ContextRealityModelProps, ContextRealityModels } from "./ContextRealityModel"; +import { ContourDisplay, ContourDisplayProps } from "./ContourDisplay"; import { DefinitionElementProps } from "./ElementProps"; -import { HiddenLine } from "./HiddenLine"; +import { Environment, EnvironmentProps } from "./Environment"; import { FeatureAppearance, FeatureAppearanceProps } from "./FeatureSymbology"; -import { PlanarClipMaskProps, PlanarClipMaskSettings } from "./PlanarClipMask"; -import { SubCategoryOverride } from "./SubCategoryOverride"; +import { Cartographic } from "./geometry/Cartographic"; +import { HiddenLine } from "./HiddenLine"; +import { IModel } from "./IModel"; import { LightSettings, LightSettingsProps } from "./LightSettings"; import { MapImageryProps, MapImagerySettings } from "./MapImagerySettings"; +import { PlanarClipMaskProps, PlanarClipMaskSettings } from "./PlanarClipMask"; import { PlanProjectionSettings, PlanProjectionSettingsProps } from "./PlanProjectionSettings"; +import { RealityModelDisplayProps, RealityModelDisplaySettings } from "./RealityModelDisplaySettings"; import { RenderSchedule } from "./RenderSchedule"; -import { Environment, EnvironmentProps } from "./Environment"; +import { calculateSolarDirection } from "./SolarCalculate"; import { SolarShadowSettings, SolarShadowSettingsProps } from "./SolarShadows"; import { SubCategoryAppearance } from "./SubCategoryAppearance"; +import { SubCategoryOverride } from "./SubCategoryOverride"; import { ThematicDisplay, ThematicDisplayMode, ThematicDisplayProps } from "./ThematicDisplay"; import { ViewFlagProps, ViewFlags } from "./ViewFlags"; -import { Cartographic } from "./geometry/Cartographic"; -import { IModel } from "./IModel"; -import { calculateSolarDirection } from "./SolarCalculate"; -import { ContextRealityModel, ContextRealityModelProps, ContextRealityModels } from "./ContextRealityModel"; -import { RealityModelDisplayProps, RealityModelDisplaySettings } from "./RealityModelDisplaySettings"; import { WhiteOnWhiteReversalProps, WhiteOnWhiteReversalSettings } from "./WhiteOnWhiteReversalSettings"; -import { ContourDisplay, ContourDisplayProps } from "./ContourDisplay"; /** Describes the [[SubCategoryOverride]]s applied to a [[SubCategory]] by a [[DisplayStyle]]. * @see [[DisplayStyleSettingsProps]] @@ -315,7 +323,9 @@ type OverridesArrayKey = "subCategoryOvr" | "modelOvr" | "planarClipOvr" | "real */ class OverridesMap extends Map { // This is required for mock framework used by ui libraries, which otherwise try to clone this as a standard Map. - public override get [Symbol.toStringTag]() { return "OverridesMap"; } + public override get [Symbol.toStringTag]() { + return "OverridesMap"; + } public constructor( private readonly _json: DisplayStyleSettingsProps, @@ -323,7 +333,8 @@ class OverridesMap extends Map { private readonly _event: BeEvent<(id: Id64String, ovr: Override | undefined) => void>, private readonly _idFromProps: (props: OverrideProps) => Id64String | undefined, private readonly _overrideToProps: (ovr: Override, id: Id64String) => OverrideProps, - private readonly _overrideFromProps: (props: OverrideProps) => Override | undefined) { + private readonly _overrideFromProps: (props: OverrideProps) => Override | undefined, + ) { super(); this.populate(); } @@ -502,7 +513,9 @@ export class DisplayStyleSettings { /** Event raised just before [[setRealityModelDisplaySettings]] changes the display settings for a reality model. * @beta */ - public readonly onRealityModelDisplaySettingsChanged = new BeEvent<(modelId: Id64String, newSettings: RealityModelDisplaySettings | undefined) => void>(); + public readonly onRealityModelDisplaySettingsChanged = new BeEvent< + (modelId: Id64String, newSettings: RealityModelDisplaySettings | undefined) => void + >(); /** Event raised just prior to assignment to the [[DisplayStyle3dSettings.thematic]] property. */ public readonly onThematicChanged = new BeEvent<(newThematic: ThematicDisplay) => void>(); /** Event raised just prior to assignment to the [[DisplayStyle3dSettings.contours]] property. */ @@ -557,35 +570,58 @@ export class DisplayStyleSettings { this._whiteOnWhiteReversal = WhiteOnWhiteReversalSettings.fromJSON(this._json.whiteOnWhiteReversal); this._clipStyle = ClipStyle.fromJSON(this._json.clipStyle); - this._subCategoryOverrides = new OverridesMap(this._json, "subCategoryOvr", this.onSubCategoryOverridesChanged, + this._subCategoryOverrides = new OverridesMap( + this._json, + "subCategoryOvr", + this.onSubCategoryOverridesChanged, (props) => props.subCategory, - (ovr, subCategory) => { return { ...ovr.toJSON(), subCategory }; }, + (ovr, subCategory) => { + return { ...ovr.toJSON(), subCategory }; + }, (props) => { const ovr = SubCategoryOverride.fromJSON(props); return ovr.anyOverridden ? ovr : undefined; - }); + }, + ); - this._modelAppearanceOverrides = new OverridesMap(this._json, "modelOvr", this.onModelAppearanceOverrideChanged, + this._modelAppearanceOverrides = new OverridesMap( + this._json, + "modelOvr", + this.onModelAppearanceOverrideChanged, (props) => props.modelId, - (ovr, modelId) => { return { ...ovr.toJSON(), modelId }; }, + (ovr, modelId) => { + return { ...ovr.toJSON(), modelId }; + }, (props) => { const app = FeatureAppearance.fromJSON(props); return app.anyOverridden ? app : undefined; - }); + }, + ); - this._realityModelDisplaySettings = new OverridesMap(this._json, "realityModelDisplay", this.onRealityModelDisplaySettingsChanged, + this._realityModelDisplaySettings = new OverridesMap( + this._json, + "realityModelDisplay", + this.onRealityModelDisplaySettingsChanged, (props) => props.modelId, - (settings, modelId) => { return { ...settings.toJSON(), modelId }; }, + (settings, modelId) => { + return { ...settings.toJSON(), modelId }; + }, (props) => RealityModelDisplaySettings.fromJSON(props), ); - this._planarClipMasks = new OverridesMap(this._json, "planarClipOvr", this.onPlanarClipMaskChanged, + this._planarClipMasks = new OverridesMap( + this._json, + "planarClipOvr", + this.onPlanarClipMaskChanged, (props) => props.modelId, - (ovr, modelId) => { return { ...ovr.toJSON(), modelId }; }, + (ovr, modelId) => { + return { ...ovr.toJSON(), modelId }; + }, (props) => { const settings = PlanarClipMaskSettings.fromJSON(props); return settings.isValid ? settings : undefined; - }); + }, + ); this._contextRealityModels = new ContextRealityModels({ container: this._json, @@ -595,7 +631,9 @@ export class DisplayStyleSettings { } /** Flags controlling various aspects of the display style. */ - public get viewFlags(): ViewFlags { return this._viewFlags; } + public get viewFlags(): ViewFlags { + return this._viewFlags; + } public set viewFlags(flags: ViewFlags) { if (this.viewFlags.equals(flags)) return; @@ -606,7 +644,9 @@ export class DisplayStyleSettings { } /** The color displayed in the view background - by default, [[ColorDef.black]]. */ - public get backgroundColor(): ColorDef { return this._background; } + public get backgroundColor(): ColorDef { + return this._background; + } public set backgroundColor(color: ColorDef) { if (this.backgroundColor.equals(color)) return; @@ -620,7 +660,9 @@ export class DisplayStyleSettings { * The monochrome color is applied to all surfaces and linear geometry, but only applied to the **edges** of surfaces in [[RenderMode.Wireframe]]. * @see [[monochromeMode]] to control how the color is applied. */ - public get monochromeColor(): ColorDef { return this._monochrome; } + public get monochromeColor(): ColorDef { + return this._monochrome; + } public set monochromeColor(color: ColorDef) { if (this.monochromeColor.equals(color)) return; @@ -631,7 +673,9 @@ export class DisplayStyleSettings { } /** The style in which [[monochromeColor]] is applied when [[ViewFlags.monochrome]] is enabled - by default, [[MonochromeMode.Scaled]]. */ - public get monochromeMode(): MonochromeMode { return this._monochromeMode; } + public get monochromeMode(): MonochromeMode { + return this._monochromeMode; + } public set monochromeMode(mode: MonochromeMode) { if (this.monochromeMode === mode) return; @@ -642,7 +686,9 @@ export class DisplayStyleSettings { } /** Settings controlling display of the background map within views of geolocated models. */ - public get backgroundMap(): BackgroundMapSettings { return this._backgroundMap; } + public get backgroundMap(): BackgroundMapSettings { + return this._backgroundMap; + } public set backgroundMap(map: BackgroundMapSettings) { if (!this.backgroundMap.equals(map)) { @@ -655,7 +701,9 @@ export class DisplayStyleSettings { /** Settings defining the map imagery layers to be displayed within the view. * @beta */ - public get mapImagery(): MapImagerySettings { return this._mapImagery; } + public get mapImagery(): MapImagerySettings { + return this._mapImagery; + } public set mapImagery(mapImagery: MapImagerySettings) { this.onMapImageryChanged.raiseEvent(mapImagery); @@ -717,7 +765,9 @@ export class DisplayStyleSettings { /** Settings controlling the display of analytical models. * @see [[analysisFraction]] to control playback of the animation. */ - public get analysisStyle(): AnalysisStyle | undefined { return this._analysisStyle; } + public get analysisStyle(): AnalysisStyle | undefined { + return this._analysisStyle; + } public set analysisStyle(style: AnalysisStyle | undefined) { if (style === this.analysisStyle) return; @@ -746,7 +796,9 @@ export class DisplayStyleSettings { } /** Settings controlling how white-on-white reversal is applied when [[ViewFlags.whiteOnWhiteReversal]] is enabled. */ - public get whiteOnWhiteReversal(): WhiteOnWhiteReversalSettings { return this._whiteOnWhiteReversal; } + public get whiteOnWhiteReversal(): WhiteOnWhiteReversalSettings { + return this._whiteOnWhiteReversal; + } public set whiteOnWhiteReversal(settings: WhiteOnWhiteReversalSettings) { if (settings.equals(this.whiteOnWhiteReversal)) return; @@ -952,9 +1004,10 @@ export class DisplayStyleSettings { props.timePoint = this.timePoint; if (this._json.contextRealityModels) { props.contextRealityModels = this._json.contextRealityModels; - if (!options?.includeIModelSpecific) + if (!options?.includeIModelSpecific) { for (const model of this._json.contextRealityModels) delete model.classifiers; + } } } @@ -1083,7 +1136,9 @@ export class DisplayStyle3dSettings extends DisplayStyleSettings { private _environment: Environment; private _planProjections?: Map; - private get _json3d(): DisplayStyle3dSettingsProps { return this._json as DisplayStyle3dSettingsProps; } + private get _json3d(): DisplayStyle3dSettingsProps { + return this._json as DisplayStyle3dSettingsProps; + } public override is3d(): this is DisplayStyle3dSettings { return true; @@ -1209,7 +1264,9 @@ export class DisplayStyle3dSettings extends DisplayStyleSettings { } /** The settings that control thematic display. */ - public get thematic(): ThematicDisplay { return this._thematic; } + public get thematic(): ThematicDisplay { + return this._thematic; + } public set thematic(thematic: ThematicDisplay) { if (thematic.equals(this.thematic)) return; @@ -1220,7 +1277,9 @@ export class DisplayStyle3dSettings extends DisplayStyleSettings { } /** The settings that control contour display. */ - public get contours(): ContourDisplay { return this._contours; } + public get contours(): ContourDisplay { + return this._contours; + } public set contours(contours: ContourDisplay) { if (contours.equals(this.contours)) return; @@ -1231,7 +1290,9 @@ export class DisplayStyle3dSettings extends DisplayStyleSettings { } /** The settings that control how visible and hidden edges are displayed. */ - public get hiddenLineSettings(): HiddenLine.Settings { return this._hline; } + public get hiddenLineSettings(): HiddenLine.Settings { + return this._hline; + } public set hiddenLineSettings(hline: HiddenLine.Settings) { if (hline.equals(this.hiddenLineSettings)) return; @@ -1242,7 +1303,9 @@ export class DisplayStyle3dSettings extends DisplayStyleSettings { } /** The settings that control how ambient occlusion is displayed. */ - public get ambientOcclusionSettings(): AmbientOcclusion.Settings { return this._ao; } + public get ambientOcclusionSettings(): AmbientOcclusion.Settings { + return this._ao; + } public set ambientOcclusionSettings(ao: AmbientOcclusion.Settings) { this.onAmbientOcclusionSettingsChanged.raiseEvent(ao); this._ao = ao; diff --git a/core/common/src/ECSqlReader.ts b/core/common/src/ECSqlReader.ts index f248a898801f..a688d6830d54 100644 --- a/core/common/src/ECSqlReader.ts +++ b/core/common/src/ECSqlReader.ts @@ -7,8 +7,18 @@ */ import { Base64EncodedString } from "./Base64EncodedString"; import { - DbQueryError, DbQueryRequest, DbQueryResponse, DbRequestExecutor, DbRequestKind, DbResponseStatus, DbValueFormat, QueryBinder, QueryOptions, QueryOptionsBuilder, - QueryPropertyMetaData, QueryRowFormat, + DbQueryError, + DbQueryRequest, + DbQueryResponse, + DbRequestExecutor, + DbRequestKind, + DbResponseStatus, + DbValueFormat, + QueryBinder, + QueryOptions, + QueryOptionsBuilder, + QueryPropertyMetaData, + QueryRowFormat, } from "./ConcurrentQuery"; /** @public */ @@ -212,7 +222,12 @@ export class ECSqlReader implements AsyncIterableIterator { /** * @internal */ - public constructor(private _executor: DbRequestExecutor, public readonly query: string, param?: QueryBinder, options?: QueryOptions) { + public constructor( + private _executor: DbRequestExecutor, + public readonly query: string, + param?: QueryBinder, + options?: QueryOptions, + ) { if (query.trim().length === 0) { throw new Error("expecting non-empty ecsql statement"); } @@ -328,9 +343,7 @@ export class ECSqlReader implements AsyncIterableIterator { return this._stats; } - /** - * - */ + /** */ private async readRows(): Promise { if (this._globalDone) { return []; @@ -343,7 +356,7 @@ export class ECSqlReader implements AsyncIterableIterator { } const valueFormat = this._options.rowFormat === QueryRowFormat.UseJsPropertyNames ? DbValueFormat.JsNames : DbValueFormat.ECSqlNames; const request: DbQueryRequest = { - ... this._options, + ...this._options, kind: DbRequestKind.ECSql, valueFormat, query: this.query, @@ -366,7 +379,9 @@ export class ECSqlReader implements AsyncIterableIterator { * @internal */ protected async runWithRetry(request: DbQueryRequest) { - const needRetry = (rs: DbQueryResponse) => (rs.status === DbResponseStatus.Partial || rs.status === DbResponseStatus.QueueFull || rs.status === DbResponseStatus.Timeout) && (rs.data === undefined || rs.data.length === 0); + const needRetry = (rs: DbQueryResponse) => + (rs.status === DbResponseStatus.Partial || rs.status === DbResponseStatus.QueueFull || rs.status === DbResponseStatus.Timeout) && + (rs.data === undefined || rs.data.length === 0); const updateStats = (rs: DbQueryResponse) => { this._stats.backendCpuTime += rs.stats.cpuTime; this._stats.backendTotalTime += rs.stats.totalTime; @@ -376,7 +391,7 @@ export class ECSqlReader implements AsyncIterableIterator { const execQuery = async (req: DbQueryRequest) => { const startTime = Date.now(); const rs = await this._executor.execute(req); - this.stats.totalTime += (Date.now() - startTime); + this.stats.totalTime += Date.now() - startTime; return rs; }; let retry = ECSqlReader._maxRetryCount; @@ -429,9 +444,7 @@ export class ECSqlReader implements AsyncIterableIterator { return this._props.properties; } - /** - * - */ + /** */ private async fetchRows() { this._localOffset = -1; this._localRows = await this.readRows(); @@ -504,4 +517,3 @@ export class ECSqlReader implements AsyncIterableIterator { } } } - diff --git a/core/common/src/ECSqlTypes.ts b/core/common/src/ECSqlTypes.ts index 1e0781479381..465a2b7d5fd9 100644 --- a/core/common/src/ECSqlTypes.ts +++ b/core/common/src/ECSqlTypes.ts @@ -118,7 +118,6 @@ export enum ECSqlSystemProperty { * @public */ export class ECJsNames { - /** Formats the specified ECProperty name according to the iTwin.js formatting rules. * * See [ECSQL Row Format]($docs/learning/ECSQLRowFormat) which describes the formatting rules. @@ -229,5 +228,7 @@ export class ECJsNames { } } - private static lowerFirstChar(name: string): string { return name[0].toLowerCase() + name.substring(1); } + private static lowerFirstChar(name: string): string { + return name[0].toLowerCase() + name.substring(1); + } } diff --git a/core/common/src/ElementProps.ts b/core/common/src/ElementProps.ts index 65339aaf18a5..52a460565a3d 100644 --- a/core/common/src/ElementProps.ts +++ b/core/common/src/ElementProps.ts @@ -8,15 +8,22 @@ import { GuidString, Id64, Id64String } from "@itwin/core-bentley"; import { - AngleProps, ClipVectorProps, LowAndHighXYProps, LowAndHighXYZProps, TransformProps, XYProps, XYZProps, YawPitchRollProps, + AngleProps, + ClipVectorProps, + LowAndHighXYProps, + LowAndHighXYZProps, + TransformProps, + XYProps, + XYZProps, + YawPitchRollProps, } from "@itwin/core-geometry"; +import { TextAnnotationProps } from "./annotation/TextAnnotation"; import { CodeProps } from "./Code"; import { EntityProps } from "./EntityProps"; import { ElementGeometryBuilderParams, ElementGeometryBuilderParamsForPart } from "./geometry/ElementGeometry"; import { GeometryStreamProps } from "./geometry/GeometryStream"; import { IModelError, IModelStatus } from "./IModelError"; import { SubCategoryAppearance } from "./SubCategoryAppearance"; -import { TextAnnotationProps } from "./annotation/TextAnnotation"; /** Properties of a NavigationProperty. * @public @@ -453,7 +460,7 @@ export interface ExternalSourceAspectProps extends ElementAspectProps { * @note Warning: if defined, jsonProperties must be a *string*, specifically a valid JSON string. * @note Warning: in a future major release, the type of `jsonProperties` will be changed to object, and itwin.js will automatically stringify it when writing to the iModel. * This will be a breaking change, since application code will have to change from supplying a string to supplying an object. - */ + */ jsonProperties?: any; /** The source of the imported/synchronized object. Should point to an instance of [ExternalSource]($backend). */ source?: RelatedElementProps; @@ -590,7 +597,7 @@ export interface RenderTimelineProps extends ElementProps { /** Properties of a [SheetIndexEntry]($backend). * @beta -*/ + */ export interface SheetIndexEntryProps extends ElementProps { /** Can be used to prioritize or order members within a SheetIndex or SheetIndexFolder. */ entryPriority: number; diff --git a/core/common/src/EntityReference.ts b/core/common/src/EntityReference.ts index d3cb96f13efe..615d0e53ee5b 100644 --- a/core/common/src/EntityReference.ts +++ b/core/common/src/EntityReference.ts @@ -57,10 +57,18 @@ export type EntityReference = `${ConcreteEntityTypes}${Id64String}`; * @alpha */ export class EntityReferenceSet extends Set { - public addElement(id: Id64String) { this.add(`e${id}`); } - public addModel(id: Id64String) { this.add(`m${id}`); } - public addAspect(id: Id64String) { this.add(`a${id}`); } - public addRelationship(id: Id64String) { this.add(`r${id}`); } + public addElement(id: Id64String) { + this.add(`e${id}`); + } + public addModel(id: Id64String) { + this.add(`m${id}`); + } + public addAspect(id: Id64String) { + this.add(`a${id}`); + } + public addRelationship(id: Id64String) { + this.add(`r${id}`); + } } /** @internal entity reference type information of a relationship */ diff --git a/core/common/src/FeatureIndex.ts b/core/common/src/FeatureIndex.ts index db7c0e982f9d..982a2a28dfb2 100644 --- a/core/common/src/FeatureIndex.ts +++ b/core/common/src/FeatureIndex.ts @@ -44,17 +44,27 @@ export class ColorIndex { private _color: ColorDef | NonUniformColor; /** Whether the color(s) in this index have transparency. */ - public get hasAlpha() { return !this._color.isOpaque; } + public get hasAlpha() { + return !this._color.isOpaque; + } /** Whether this index specifies a single uniform color for the entire mesh or polyline. */ - public get isUniform() { return this._color instanceof ColorDef; } + public get isUniform() { + return this._color instanceof ColorDef; + } /** The number of colors in this index. */ - public get numColors(): number { return this.isUniform ? 1 : this.nonUniform!.colors.length; } + public get numColors(): number { + return this.isUniform ? 1 : this.nonUniform!.colors.length; + } /** Construct a default index specifying a uniform white color. */ - public constructor() { this._color = ColorDef.white; } + public constructor() { + this._color = ColorDef.white; + } /** Reset this index to specify a uniform white color. */ - public reset() { this._color = ColorDef.white; } + public reset() { + this._color = ColorDef.white; + } /** Returns the single color to be applied to all vertices, if [[isUniform]] is `true`; or `undefined` otherwise. */ public get uniform(): ColorDef | undefined { @@ -108,10 +118,14 @@ export class FeatureIndex { public featureIDs?: Uint32Array; /** True if [[type]] is [[FeatureIndexType.Uniform]]. */ - public get isUniform(): boolean { return FeatureIndexType.Uniform === this.type; } + public get isUniform(): boolean { + return FeatureIndexType.Uniform === this.type; + } /** True if [[type]] is [[FeatureIndexType.Empty]]. */ - public get isEmpty(): boolean { return FeatureIndexType.Empty === this.type; } + public get isEmpty(): boolean { + return FeatureIndexType.Empty === this.type; + } /** Reset to an empty index. */ public reset(): void { diff --git a/core/common/src/FeatureSymbology.ts b/core/common/src/FeatureSymbology.ts index 6c07b6f26d87..e0e110d0feb3 100644 --- a/core/common/src/FeatureSymbology.ts +++ b/core/common/src/FeatureSymbology.ts @@ -7,8 +7,8 @@ */ import { assert, Id64, Id64String } from "@itwin/core-bentley"; -import { BatchType, Feature } from "./FeatureTable"; import { ColorDef } from "./ColorDef"; +import { BatchType, Feature } from "./FeatureTable"; import { GeometryClass } from "./GeometryParams"; import { LinePixels } from "./LinePixels"; import { RgbColor, RgbColorProps } from "./RgbColor"; @@ -223,10 +223,18 @@ export class FeatureAppearance { return this.equals(FeatureAppearance.defaults); } - public get overridesRgb(): boolean { return undefined !== this.rgb; } - public get overridesTransparency(): boolean { return undefined !== this.transparency; } - public get overridesLinePixels(): boolean { return undefined !== this.linePixels; } - public get overridesWeight(): boolean { return undefined !== this.weight; } + public get overridesRgb(): boolean { + return undefined !== this.rgb; + } + public get overridesTransparency(): boolean { + return undefined !== this.transparency; + } + public get overridesLinePixels(): boolean { + return undefined !== this.linePixels; + } + public get overridesWeight(): boolean { + return undefined !== this.weight; + } /** Get the color that will be applied to linear geometry, or undefined if not overridden. * This is the same as [[rgb]] if [[lineRgb]] is `undefined`. @@ -248,7 +256,9 @@ export class FeatureAppearance { || undefined !== this.getLineRgb() || undefined !== this.getLineTransparency(); } - public get overridesNonLocatable(): boolean { return undefined !== this.nonLocatable; } + public get overridesNonLocatable(): boolean { + return undefined !== this.nonLocatable; + } public get isFullyTransparent(): boolean { const surf = this.transparency ?? 0; @@ -257,7 +267,9 @@ export class FeatureAppearance { } /** Returns true if any aspect of the appearance is overridden (i.e., if any member is not undefined). */ - public get anyOverridden(): boolean { return this.overridesSymbology || this.overridesNonLocatable; } + public get anyOverridden(): boolean { + return this.overridesSymbology || this.overridesNonLocatable; + } public equals(other: FeatureAppearance): boolean { if (this === other) @@ -376,7 +388,9 @@ export class FeatureAppearance { this.lineRgb = typeof props.lineRgb === "object" ? RgbColor.fromJSON(props.lineRgb) : (false === props.lineRgb ? false : undefined); this.transparency = transparencyFromJSON(props.transparency); - this.lineTransparency = typeof props.lineTransparency === "number" ? transparencyFromJSON(props.lineTransparency) : (false === props.lineTransparency ? false : undefined); + this.lineTransparency = typeof props.lineTransparency === "number" + ? transparencyFromJSON(props.lineTransparency) + : (false === props.lineTransparency ? false : undefined); this.weight = props.weight; this.linePixels = props.linePixels; @@ -416,7 +430,17 @@ export interface FeatureAppearanceSource { * @returns The desired appearance overrides, or `undefined` to indicate the feature should not be displayed. * @see [Id64.isValidUint32Pair]($core-bentley) to determine if the components of an [Id64String]($core-bentley) represent a valid Id. */ - getAppearance(elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number): FeatureAppearance | undefined; + getAppearance( + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ): FeatureAppearance | undefined; } /** Common options for [[FeatureOverrides.override]]. @@ -599,19 +623,27 @@ export class FeatureOverrides implements FeatureAppearanceSource { } /** Overrides applied to features for which no other overrides are defined */ - public get defaultOverrides(): FeatureAppearance { return this._defaultOverrides; } + public get defaultOverrides(): FeatureAppearance { + return this._defaultOverrides; + } /** Whether or not line weights are applied. If false, all lines are drawn with a weight of 1. */ - public get lineWeights(): boolean { return this._lineWeights; } + public get lineWeights(): boolean { + return this._lineWeights; + } /** A set of elements that are always invisible. * @note If an element is present in both `alwaysDrawn` and [[neverDrawn]], it will not be displayed - `neverDrawn` takes precedence. */ - public get neverDrawn() { return this._neverDrawn; } + public get neverDrawn() { + return this._neverDrawn; + } /** A set of elements that are unconditionally displayed. * @see [[isAlwaysDrawnExclusive]] to specify that *only* elements in this set will be displayed. * @note If an element is present in both `alwaysDrawn` and [[neverDrawn]], it will not be displayed - `neverDrawn` takes precedence. */ - public get alwaysDrawn() { return this._alwaysDrawn; } + public get alwaysDrawn() { + return this._alwaysDrawn; + } /** @internal */ protected isNeverDrawn(elemIdLo: number, elemIdHi: number, animationNodeId: number): boolean { @@ -621,9 +653,13 @@ export class FeatureOverrides implements FeatureAppearanceSource { return this.neverDrawnAnimationNodes.has(animationNodeId); } /** @internal */ - protected isAlwaysDrawn(idLo: number, idHi: number): boolean { return this._alwaysDrawn.has(idLo, idHi); } + protected isAlwaysDrawn(idLo: number, idHi: number): boolean { + return this._alwaysDrawn.has(idLo, idHi); + } /** Returns true if the [SubCategory]($backend) specified by Id is in the set of visible subcategories. @internal */ - public isSubCategoryVisible(idLo: number, idHi: number): boolean { return this._visibleSubCategories.has(idLo, idHi); } + public isSubCategoryVisible(idLo: number, idHi: number): boolean { + return this._visibleSubCategories.has(idLo, idHi); + } /** @internal */ public isSubCategoryVisibleInModel(subcatLo: number, subcatHi: number, modelLo: number, modelHi: number): boolean { if (this.ignoreSubCategory) @@ -670,18 +706,30 @@ export class FeatureOverrides implements FeatureAppearanceSource { } /** @internal */ - protected getSubCategoryOverrides(idLo: number, idHi: number): FeatureAppearance | undefined { return this._subCategoryOverrides.get(idLo, idHi); } + protected getSubCategoryOverrides(idLo: number, idHi: number): FeatureAppearance | undefined { + return this._subCategoryOverrides.get(idLo, idHi); + } /** Add a [SubCategory]($backend) to the set of visible subcategories. */ - public setVisibleSubCategory(id: Id64String): void { this._visibleSubCategories.addId(id); } + public setVisibleSubCategory(id: Id64String): void { + this._visibleSubCategories.addId(id); + } /** Specify the Id of an element that should never be drawn. */ - public setNeverDrawn(id: Id64String): void { this._neverDrawn.addId(id); } + public setNeverDrawn(id: Id64String): void { + this._neverDrawn.addId(id); + } /** Specify the Id of an element that should always be drawn. */ - public setAlwaysDrawn(id: Id64String): void { this._alwaysDrawn.addId(id); } + public setAlwaysDrawn(id: Id64String): void { + this._alwaysDrawn.addId(id); + } /** Specify the Id of a animation node that should never be drawn. */ - public setAnimationNodeNeverDrawn(id: number): void { this.neverDrawnAnimationNodes.add(id); } + public setAnimationNodeNeverDrawn(id: number): void { + this.neverDrawnAnimationNodes.add(id); + } /** Specify the Ids of elements that should never be drawn. */ - public setNeverDrawnSet(ids: Iterable) { copyIdSetToUint32Set(this._neverDrawn, ids); } + public setNeverDrawnSet(ids: Iterable) { + copyIdSetToUint32Set(this._neverDrawn, ids); + } /** Specify the Ids of elements that should always be drawn. */ public setAlwaysDrawnSet(ids: Iterable, exclusive: boolean, ignoreSubCategory = true) { copyIdSetToUint32Set(this._alwaysDrawn, ids); @@ -690,13 +738,23 @@ export class FeatureOverrides implements FeatureAppearanceSource { } /** Returns the feature's appearance overrides, or undefined if the feature is not visible. */ - public getFeatureAppearance(feature: Feature, modelId: Id64String, type: BatchType = BatchType.Primary, animationNodeId = 0): FeatureAppearance | undefined { + public getFeatureAppearance( + feature: Feature, + modelId: Id64String, + type: BatchType = BatchType.Primary, + animationNodeId = 0, + ): FeatureAppearance | undefined { return this.getAppearance( - Id64.getLowerUint32(feature.elementId), Id64.getUpperUint32(feature.elementId), - Id64.getLowerUint32(feature.subCategoryId), Id64.getUpperUint32(feature.subCategoryId), + Id64.getLowerUint32(feature.elementId), + Id64.getUpperUint32(feature.elementId), + Id64.getLowerUint32(feature.subCategoryId), + Id64.getUpperUint32(feature.subCategoryId), feature.geometryClass, - Id64.getLowerUint32(modelId), Id64.getUpperUint32(modelId), - type, animationNodeId); + Id64.getLowerUint32(modelId), + Id64.getUpperUint32(modelId), + type, + animationNodeId, + ); } private static readonly _weight1Appearance = FeatureAppearance.fromJSON({ weight: 1 }); @@ -705,7 +763,17 @@ export class FeatureOverrides implements FeatureAppearanceSource { * Takes Id64s as pairs of unsigned 32-bit integers for efficiency, because that is how they are stored by the PackedFeatureTable associated with each batch of graphics. * @see [[getFeatureAppearance]] for an equivalent function that accepts [Id64String]($core-bentley)s instead of integer pairs. */ - public getAppearance(elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number): FeatureAppearance | undefined { + public getAppearance( + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ): FeatureAppearance | undefined { if (BatchType.VolumeClassifier === type || BatchType.PlanarClassifier === type) return this.getClassifierAppearance(elemLo, elemHi, subcatLo, subcatHi, modelLo, modelHi, animationNodeId); @@ -755,7 +823,15 @@ export class FeatureOverrides implements FeatureAppearanceSource { /** Classifiers behave totally differently...in particular they are never invisible unless fully-transparent. * @internal */ - protected getClassifierAppearance(elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, modelLo: number, modelHi: number, animationNodeId: number): FeatureAppearance | undefined { + protected getClassifierAppearance( + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + modelLo: number, + modelHi: number, + animationNodeId: number, + ): FeatureAppearance | undefined { let app = FeatureAppearance.defaults; const modelApp = this.getModelOverrides(modelLo, modelHi); if (undefined !== modelApp) @@ -783,10 +859,14 @@ export class FeatureOverrides implements FeatureAppearanceSource { */ public isClassVisible(geomClass: GeometryClass): boolean { switch (geomClass) { - case GeometryClass.Construction: return this._constructions; - case GeometryClass.Dimension: return this._dimensions; - case GeometryClass.Pattern: return this._patterns; - default: return true; + case GeometryClass.Construction: + return this._constructions; + case GeometryClass.Dimension: + return this._dimensions; + case GeometryClass.Pattern: + return this._patterns; + default: + return true; } } @@ -911,13 +991,21 @@ export class FeatureOverrides implements FeatureAppearanceSource { } /** Returns true if geometry belonging to the specified subcategory will be drawn. */ - public isSubCategoryIdVisible(id: Id64String): boolean { return this.isSubCategoryVisible(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); } + public isSubCategoryIdVisible(id: Id64String): boolean { + return this.isSubCategoryVisible(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); + } /** Returns the overrides applied to geometry belonging to the specified model, if any such are defined. */ - public getModelOverridesById(id: Id64String): FeatureAppearance | undefined { return this.getModelOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); } + public getModelOverridesById(id: Id64String): FeatureAppearance | undefined { + return this.getModelOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); + } /** Returns the overrides applied to geometry belonging to the specified element, if any such are defined. */ - public getElementOverridesById(id: Id64String): FeatureAppearance | undefined { return this.getElementOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id), 0); } + public getElementOverridesById(id: Id64String): FeatureAppearance | undefined { + return this.getElementOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id), 0); + } /** Returns the overrides applied to geometry belonging to the specified subcategory, if any such are defined. */ - public getSubCategoryOverridesById(id: Id64String): FeatureAppearance | undefined { return this.getSubCategoryOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); } + public getSubCategoryOverridesById(id: Id64String): FeatureAppearance | undefined { + return this.getSubCategoryOverrides(Id64.getLowerUint32(id), Id64.getUpperUint32(id)); + } /** Returns true if the specified Feature will be drawn. */ public isFeatureVisible(feature: Feature): boolean { @@ -964,7 +1052,18 @@ export interface FeatureAppearanceProvider { * @see [[FeatureAppearanceSource.getAppearance]] to forward the request to the source. * @see [Id64.isValidUint32Pair]($core-bentley) to determine if the components of an [Id64String]($core-bentley) represent a valid Id. */ - getFeatureAppearance(source: FeatureAppearanceSource, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number): FeatureAppearance | undefined; + getFeatureAppearance( + source: FeatureAppearanceSource, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ): FeatureAppearance | undefined; } /** @public */ @@ -972,7 +1071,17 @@ export namespace FeatureAppearanceProvider { /** Produce a FeatureAppearanceSource for which `getAppearance()` returns the appearance specified in `source`, potentially modified by `provider`. */ function wrap(source: FeatureAppearanceSource, provider: FeatureAppearanceProvider): FeatureAppearanceSource { return { - getAppearance: (elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number) => { + getAppearance: ( + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ) => { return provider.getFeatureAppearance(source, elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); }, }; @@ -984,7 +1093,18 @@ export namespace FeatureAppearanceProvider { */ export function supplement(supplementAppearance: (appearance: FeatureAppearance) => FeatureAppearance): FeatureAppearanceProvider { return { - getFeatureAppearance: (source: FeatureAppearanceSource, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number) => { + getFeatureAppearance: ( + source: FeatureAppearanceSource, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ) => { const app = source.getAppearance(elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); return app ? supplementAppearance(app) : app; }, @@ -1000,8 +1120,30 @@ export namespace FeatureAppearanceProvider { return first; return { - getFeatureAppearance: (source: FeatureAppearanceSource, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number) => { - return second.getFeatureAppearance(wrap(source, first), elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); + getFeatureAppearance: ( + source: FeatureAppearanceSource, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ) => { + return second.getFeatureAppearance( + wrap(source, first), + elemLo, + elemHi, + subcatLo, + subcatHi, + geomClass, + modelLo, + modelHi, + type, + animationNodeId, + ); }, }; } diff --git a/core/common/src/FeatureTable.ts b/core/common/src/FeatureTable.ts index f6853b0d9363..b3e77fa5e960 100644 --- a/core/common/src/FeatureTable.ts +++ b/core/common/src/FeatureTable.ts @@ -6,9 +6,7 @@ * @module Rendering */ -import { - assert, compareNumbers, compareStrings, Id64, Id64String, IndexedValue, IndexMap, UintArray, -} from "@itwin/core-bentley"; +import { assert, compareNumbers, compareStrings, Id64, Id64String, IndexedValue, IndexMap, UintArray } from "@itwin/core-bentley"; import { GeometryClass } from "./GeometryParams"; /** Describes a discrete entity within a batched [RenderGraphic]($frontend) that can be @@ -25,17 +23,27 @@ export class Feature { public readonly subCategoryId: Id64String; public readonly geometryClass: GeometryClass; - public constructor(elementId: Id64String = Id64.invalid, subCategoryId: Id64String = Id64.invalid, geometryClass: GeometryClass = GeometryClass.Primary) { + public constructor( + elementId: Id64String = Id64.invalid, + subCategoryId: Id64String = Id64.invalid, + geometryClass: GeometryClass = GeometryClass.Primary, + ) { this.elementId = elementId; this.subCategoryId = subCategoryId; this.geometryClass = geometryClass; } - public get isDefined(): boolean { return !Id64.isInvalid(this.elementId) || !Id64.isInvalid(this.subCategoryId) || this.geometryClass !== GeometryClass.Primary; } - public get isUndefined(): boolean { return !this.isDefined; } + public get isDefined(): boolean { + return !Id64.isInvalid(this.elementId) || !Id64.isInvalid(this.subCategoryId) || this.geometryClass !== GeometryClass.Primary; + } + public get isUndefined(): boolean { + return !this.isDefined; + } /** Returns true if this feature is equivalent to the supplied feature. */ - public equals(other: Feature): boolean { return 0 === this.compare(other); } + public equals(other: Feature): boolean { + return 0 === this.compare(other); + } /** Performs ordinal comparison of this feature with another. * @param rhs The feature to compare with. @@ -83,7 +91,8 @@ export namespace ModelFeature { /** Returns `true` if any of `feature`'s properties differ from the defaults (invalid Ids and [[GeometryClass.Primary]]). */ export function isDefined(feature: ModelFeature): boolean { - return !Id64.isInvalid(feature.modelId) || !Id64.isInvalid(feature.elementId) || !Id64.isInvalid(feature.subCategoryId) || feature.geometryClass !== GeometryClass.Primary; + return !Id64.isInvalid(feature.modelId) || !Id64.isInvalid(feature.elementId) || !Id64.isInvalid(feature.subCategoryId) || + feature.geometryClass !== GeometryClass.Primary; } /** @alpha */ @@ -184,17 +193,29 @@ export class FeatureTable extends IndexMap { } /** Returns the maximum number of [[Feature]]s this FeatureTable can contain. */ - public get maxFeatures(): number { return this._maximumSize; } + public get maxFeatures(): number { + return this._maximumSize; + } /** @internal */ - public get anyDefined(): boolean { return this.length > 1 || (1 === this.length && this._array[0].value.isDefined); } + public get anyDefined(): boolean { + return this.length > 1 || (1 === this.length && this._array[0].value.isDefined); + } /** Returns true if this FeatureTable contains exactly one [[Feature]]. */ - public get isUniform(): boolean { return 1 === this.length; } + public get isUniform(): boolean { + return 1 === this.length; + } /** If this FeatureTable contains exactly one [[Feature]], returns that Feature; otherwise returns undefined. */ - public get uniform(): Feature | undefined { return 1 === this.length ? this._array[0].value : undefined; } + public get uniform(): Feature | undefined { + return 1 === this.length ? this._array[0].value : undefined; + } /** Returns true if this FeatureTable is associated with [[BatchType.VolumeClassifier]] geometry. */ - public get isVolumeClassifier(): boolean { return BatchType.VolumeClassifier === this.type; } + public get isVolumeClassifier(): boolean { + return BatchType.VolumeClassifier === this.type; + } /** Returns true if this FeatureTable is associated with [[BatchType.PlanarClassifier]] geometry. */ - public get isPlanarClassifier(): boolean { return BatchType.PlanarClassifier === this.type; } + public get isPlanarClassifier(): boolean { + return BatchType.PlanarClassifier === this.type; + } /** Returns the Feature corresponding to the specified index, or undefined if the index is not present. */ public findFeature(index: number): Feature | undefined { @@ -215,7 +236,9 @@ export class FeatureTable extends IndexMap { } /** @internal */ - public getArray(): Array> { return this._array; } + public getArray(): Array> { + return this._array; + } /** Convert this feature table to a representation that can be supplied to [RenderSystem.createBatch]($frontend). */ public pack(): RenderFeatureTable { @@ -319,7 +342,9 @@ export class PackedFeatureTable implements RenderFeatureTable { public readonly type: BatchType; public animationNodeIds?: UintArray; - public get byteLength(): number { return this.data.byteLength; } + public get byteLength(): number { + return this.data.byteLength; + } /** Construct a PackedFeatureTable from the packed binary data. * This is used internally when deserializing Tiles in iMdl format. @@ -373,7 +398,7 @@ export class PackedFeatureTable implements RenderFeatureTable { let subCategoryIndex = subcategories.get(feature.subCategoryId)!; assert(undefined !== subCategoryIndex); // we inserted it above... - subCategoryIndex |= (feature.geometryClass << 24); + subCategoryIndex |= feature.geometryClass << 24; uint32s[index + 0] = Id64.getLowerUint32(feature.elementId); uint32s[index + 1] = Id64.getUpperUint32(feature.elementId); @@ -462,16 +487,24 @@ export class PackedFeatureTable implements RenderFeatureTable { } /** Return true if this table contains exactly 1 feature. */ - public get isUniform(): boolean { return 1 === this.numFeatures; } + public get isUniform(): boolean { + return 1 === this.numFeatures; + } /** If this table contains exactly 1 feature, return it. */ public getUniform(result: ModelFeature): ModelFeature | undefined { return this.isUniform ? this.getFeature(0, result) : undefined; } - public get isVolumeClassifier(): boolean { return BatchType.VolumeClassifier === this.type; } - public get isPlanarClassifier(): boolean { return BatchType.VolumeClassifier === this.type; } - public get isClassifier(): boolean { return this.isVolumeClassifier || this.isPlanarClassifier; } + public get isVolumeClassifier(): boolean { + return BatchType.VolumeClassifier === this.type; + } + public get isPlanarClassifier(): boolean { + return BatchType.VolumeClassifier === this.type; + } + public get isClassifier(): boolean { + return this.isVolumeClassifier || this.isPlanarClassifier; + } /** Unpack the features into a [[FeatureTable]]. */ public unpack(): FeatureTable { @@ -490,7 +523,7 @@ export class PackedFeatureTable implements RenderFeatureTable { this.animationNodeIds = populateAnimationNodeIds(this, computeNodeId, maxNodeId); } - public * iterator(output: PackedFeatureWithIndex): Iterator { + public *iterator(output: PackedFeatureWithIndex): Iterator { for (let i = 0; i < this.numFeatures; i++) { this.getPackedFeature(i, output); output.index = i; @@ -504,7 +537,9 @@ export class PackedFeatureTable implements RenderFeatureTable { }; } - private get _subCategoriesOffset(): number { return this.numFeatures * 3; } + private get _subCategoriesOffset(): number { + return this.numFeatures * 3; + } private readId(offset32: number): Id64String { return Id64.fromUint32Pair(this.data[offset32], this.data[offset32 + 1]); @@ -550,7 +585,7 @@ export class PackedFeatureModelTable { return this._data[modelIndex * 3]; } - public getEntry(modelIndex: number, result: PackedFeatureModelEntry): PackedFeatureModelEntry { + public getEntry(modelIndex: number, result: PackedFeatureModelEntry): PackedFeatureModelEntry { if (modelIndex >= this.length) { result.idLower = result.idUpper = 0; result.lastFeatureIndex = Number.MAX_SAFE_INTEGER; @@ -607,7 +642,13 @@ export class MultiModelPackedFeatureTable implements RenderFeatureTable { this._models = models; } - public static create(data: Uint32Array, batchModelId: Id64String, numFeatures: number, type: BatchType, numSubCategories: number): MultiModelPackedFeatureTable { + public static create( + data: Uint32Array, + batchModelId: Id64String, + numFeatures: number, + type: BatchType, + numSubCategories: number, + ): MultiModelPackedFeatureTable { const modelTableOffset = 3 * numFeatures + 2 * numSubCategories; const featureData = data.subarray(0, modelTableOffset); const features = new PackedFeatureTable(featureData, batchModelId, numFeatures, type); @@ -618,12 +659,24 @@ export class MultiModelPackedFeatureTable implements RenderFeatureTable { return new MultiModelPackedFeatureTable(features, models); } - public get batchModelId() { return this._features.batchModelId; } - public get batchModelIdPair() { return this._features.batchModelIdPair; } - public get numFeatures() { return this._features.numFeatures; } - public get type() { return this._features.type; } - public get animationNodeIds(): UintArray | undefined { return this._features.animationNodeIds; } - public set animationNodeIds(ids: UintArray | undefined) { this._features.animationNodeIds = ids; } + public get batchModelId() { + return this._features.batchModelId; + } + public get batchModelIdPair() { + return this._features.batchModelIdPair; + } + public get numFeatures() { + return this._features.numFeatures; + } + public get type() { + return this._features.type; + } + public get animationNodeIds(): UintArray | undefined { + return this._features.animationNodeIds; + } + public set animationNodeIds(ids: UintArray | undefined) { + this._features.animationNodeIds = ids; + } public get byteLength() { return this._features.byteLength + this._models.byteLength; @@ -657,7 +710,7 @@ export class MultiModelPackedFeatureTable implements RenderFeatureTable { return this._features.findElementId(featureIndex); } - public * iterator(output: PackedFeatureWithIndex): Iterator { + public *iterator(output: PackedFeatureWithIndex): Iterator { // Rather than perform a binary search on the model table to find each feature's model Id, traverse the model table in parallel with the feature table. let modelIndex = 0; const modelEntry = this._models.getEntry(modelIndex, scratchPackedFeatureModelEntry); diff --git a/core/common/src/Fonts.ts b/core/common/src/Fonts.ts index e2571d0c5448..8bd6c6945536 100644 --- a/core/common/src/Fonts.ts +++ b/core/common/src/Fonts.ts @@ -10,7 +10,11 @@ * @public * @extensions */ -export enum FontType { TrueType = 1, Rsc = 2, Shx = 3 } +export enum FontType { + TrueType = 1, + Rsc = 2, + Shx = 3, +} /** An iModel-local identifier for a font. * @public @@ -34,7 +38,9 @@ export interface FontProps { * @public * @extensions */ -export interface FontMapProps { fonts: FontProps[] } +export interface FontMapProps { + fonts: FontProps[]; +} /** * A FontMap holds the set of font names available in an iModel. diff --git a/core/common/src/Frustum.ts b/core/common/src/Frustum.ts index 3da8c884deb7..f63f8f561d1a 100644 --- a/core/common/src/Frustum.ts +++ b/core/common/src/Frustum.ts @@ -7,7 +7,21 @@ */ import { - AxisOrder, ClipPlane, ConvexClipPlaneSet, Geometry, GrowableXYZArray, LowAndHighXY, LowAndHighXYZ, Map4d, Matrix3d, Plane3dByOriginAndUnitNormal, Point3d, Range3d, Transform, Vector3d, XYAndZ, + AxisOrder, + ClipPlane, + ConvexClipPlaneSet, + Geometry, + GrowableXYZArray, + LowAndHighXY, + LowAndHighXYZ, + Map4d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point3d, + Range3d, + Transform, + Vector3d, + XYAndZ, } from "@itwin/core-geometry"; /** The 8 corners of the [Normalized Plane Coordinate]($docs/learning/glossary.md#npc) cube. @@ -90,7 +104,9 @@ export class Frustum { } /** Get a corner Point from this Frustum. */ - public getCorner(i: number) { return this.points[i]; } + public getCorner(i: number) { + return this.points[i]; + } /** Get the point at the center of this Frustum (halfway between RightTopFront and LeftBottomRear. */ public getCenter(): Point3d { return this.getCorner(Npc.RightTopFront).interpolate(0.5, this.getCorner(Npc.LeftBottomRear)); @@ -139,7 +155,9 @@ export class Frustum { } /** Set the points of this Frustum to be copies of the points in another Frustum. */ - public setFrom(other: Frustum) { this.setFromCorners(other.points); } + public setFrom(other: Frustum) { + this.setFromCorners(other.points); + } /** Set the points of this frustum from array of corner points in NPC order. */ public setFromCorners(corners: Point3d[]) { for (let i = 0; i < 8; ++i) @@ -208,7 +226,7 @@ export class Frustum { const fraction = this.getFraction(); if (Math.abs(fraction - 1) < 1E-8) - return undefined; // Parallel. + return undefined; // Parallel. const org = this.getCorner(Npc.LeftBottomRear); const zVec = org.vectorTo(this.getCorner(Npc.LeftBottomFront)); @@ -246,12 +264,36 @@ export class Frustum { public initFromRange(range: LowAndHighXYZ | LowAndHighXY): void { const getZ = (arg: any): number => arg.z !== undefined ? arg.z : 0; const pts = this.points; - pts[0].x = pts[2].x = pts[4].x = pts[6].x = range.low.x; - pts[1].x = pts[3].x = pts[5].x = pts[7].x = range.high.x; - pts[0].y = pts[1].y = pts[4].y = pts[5].y = range.low.y; - pts[2].y = pts[3].y = pts[6].y = pts[7].y = range.high.y; - pts[0].z = pts[1].z = pts[2].z = pts[3].z = getZ(range.low); - pts[4].z = pts[5].z = pts[6].z = pts[7].z = getZ(range.high); + pts[0].x = + pts[2].x = + pts[4].x = + pts[6].x = + range.low.x; + pts[1].x = + pts[3].x = + pts[5].x = + pts[7].x = + range.high.x; + pts[0].y = + pts[1].y = + pts[4].y = + pts[5].y = + range.low.y; + pts[2].y = + pts[3].y = + pts[6].y = + pts[7].y = + range.high.y; + pts[0].z = + pts[1].z = + pts[2].z = + pts[3].z = + getZ(range.low); + pts[4].z = + pts[5].z = + pts[6].z = + pts[7].z = + getZ(range.high); } /** Create a new Frustum from a Range3d */ @@ -303,12 +345,16 @@ export class Frustum { if (clipBack) { Vector3d.createCrossProductToPoints(this.points[1], this.points[2], this.points[0], scratchNormal); if (scratchNormal.normalizeInPlace()) - convexSet.addPlaneToConvexSet(ClipPlane.createNormalAndDistance(scratchNormal, scratchNormal.dotProduct(this.points[0]) - expandPlaneDistance)); + convexSet.addPlaneToConvexSet( + ClipPlane.createNormalAndDistance(scratchNormal, scratchNormal.dotProduct(this.points[0]) - expandPlaneDistance), + ); } if (clipFront) { Vector3d.createCrossProductToPoints(this.points[6], this.points[5], this.points[4], scratchNormal); if (scratchNormal.normalizeInPlace()) - convexSet.addPlaneToConvexSet(ClipPlane.createNormalAndDistance(scratchNormal, scratchNormal.dotProduct(this.points[4]) - expandPlaneDistance)); + convexSet.addPlaneToConvexSet( + ClipPlane.createNormalAndDistance(scratchNormal, scratchNormal.dotProduct(this.points[4]) - expandPlaneDistance), + ); } return convexSet; } diff --git a/core/common/src/GenericInstanceFilter.ts b/core/common/src/GenericInstanceFilter.ts index 2b446cadcb06..ce933b35686f 100644 --- a/core/common/src/GenericInstanceFilter.ts +++ b/core/common/src/GenericInstanceFilter.ts @@ -106,7 +106,8 @@ export namespace GenericInstanceFilterRuleValue { } /** Checks if supplied value is [[GenericInstanceFilterRuleValue.InstanceKey]] like. */ export function isInstanceKey(value: GenericInstanceFilterRuleValue.Values): value is GenericInstanceFilterRuleValue.InstanceKey { - return (value as GenericInstanceFilterRuleValue.InstanceKey) !== undefined && (value as GenericInstanceFilterRuleValue.InstanceKey).className !== undefined; + return (value as GenericInstanceFilterRuleValue.InstanceKey) !== undefined && + (value as GenericInstanceFilterRuleValue.InstanceKey).className !== undefined; } export type Values = | string diff --git a/core/common/src/GeoCoordinateServices.ts b/core/common/src/GeoCoordinateServices.ts index 672ed50a959e..bc43daaac038 100644 --- a/core/common/src/GeoCoordinateServices.ts +++ b/core/common/src/GeoCoordinateServices.ts @@ -68,14 +68,22 @@ export enum GeoCoordStatus { */ export function mapToGeoServiceStatus(s: GeoCoordStatus): GeoServiceStatus { switch (s) { - case GeoCoordStatus.Success: return GeoServiceStatus.Success; - case GeoCoordStatus.NoGCSDefined: return GeoServiceStatus.NoGeoLocation; - case GeoCoordStatus.OutOfUsefulRange: return GeoServiceStatus.OutOfUsefulRange; - case GeoCoordStatus.OutOfMathematicalDomain: return GeoServiceStatus.OutOfMathematicalDomain; - case GeoCoordStatus.NoDatumConverter: return GeoServiceStatus.NoDatumConverter; - case GeoCoordStatus.VerticalDatumConvertError: return GeoServiceStatus.VerticalDatumConvertError; - case GeoCoordStatus.CSMapError: return GeoServiceStatus.CSMapError; - case GeoCoordStatus.Pending: return GeoServiceStatus.Pending; + case GeoCoordStatus.Success: + return GeoServiceStatus.Success; + case GeoCoordStatus.NoGCSDefined: + return GeoServiceStatus.NoGeoLocation; + case GeoCoordStatus.OutOfUsefulRange: + return GeoServiceStatus.OutOfUsefulRange; + case GeoCoordStatus.OutOfMathematicalDomain: + return GeoServiceStatus.OutOfMathematicalDomain; + case GeoCoordStatus.NoDatumConverter: + return GeoServiceStatus.NoDatumConverter; + case GeoCoordStatus.VerticalDatumConvertError: + return GeoServiceStatus.VerticalDatumConvertError; + case GeoCoordStatus.CSMapError: + return GeoServiceStatus.CSMapError; + case GeoCoordStatus.Pending: + return GeoServiceStatus.Pending; default: throw new Error("GeoCoordStatus -> GeoServiceStatus - Missing enum conversion"); } @@ -103,7 +111,7 @@ export interface PointWithStatus { /** @beta */ export interface IModelCoordinatesResponseProps { iModelCoords: PointWithStatus[]; - fromCache: number; // the number that were read from the cache rather than calculated. + fromCache: number; // the number that were read from the cache rather than calculated. } /** Information required to request conversion of an array of iModel coordinates to Geographic Coordinates (longitude and latitude) @@ -119,7 +127,7 @@ export interface GeoCoordinatesRequestProps { */ export interface GeoCoordinatesResponseProps { geoCoords: PointWithStatus[]; - fromCache: number; // the number that were read from the cache rather than calculated. + fromCache: number; // the number that were read from the cache rather than calculated. } /** Information required to interpret or complete a Geographic CRS in the specified format. @@ -134,7 +142,7 @@ export interface GeographicCRSInterpretRequestProps { * which should then contain both the horizontal CRS definition as well as the vertical CRS specification. * WKT fragments starting with PROJCS or GEOGCS are also supported but the vertical CRS will be assigned a * default value. - */ + */ geographicCRSDef: string; } @@ -145,7 +153,7 @@ export interface GeographicCRSInterpretResponseProps { /** The result status of the interpret operation. A value of zero indicates successful interpretation. * Any value other than zero is to be considered a hard error and no valid result will * be returned in the geographicCRS property. - */ + */ status: number; /** The property that receives the interpreted geographic CRS if the process was successful. */ geographicCRS?: GeographicCRSProps; diff --git a/core/common/src/GeometryContainment.ts b/core/common/src/GeometryContainment.ts index a93de6e2d779..33b6f604e41d 100644 --- a/core/common/src/GeometryContainment.ts +++ b/core/common/src/GeometryContainment.ts @@ -7,8 +7,8 @@ */ import { BentleyStatus, Id64Array } from "@itwin/core-bentley"; -import { ViewFlagProps } from "./ViewFlags"; import { ClipPlaneContainment, ClipVectorProps } from "@itwin/core-geometry"; +import { ViewFlagProps } from "./ViewFlags"; /** Information required to request clip containment status for elements from the front end to the back end. * @public diff --git a/core/common/src/Gradient.ts b/core/common/src/Gradient.ts index 5bc6004df5a0..386a80342d36 100644 --- a/core/common/src/Gradient.ts +++ b/core/common/src/Gradient.ts @@ -128,7 +128,7 @@ export namespace Gradient { private static _fixedSchemeKeys = [ // NB: these color values are ordered as rbg. Note how the components are applied below. - [[0.0, 0, 255, 0], [0.25, 0, 255, 255], [0.5, 0, 0, 255], [0.75, 255, 0, 255], [1.0, 255, 0, 0]], // Blue Red. + [[0.0, 0, 255, 0], [0.25, 0, 255, 255], [0.5, 0, 0, 255], [0.75, 255, 0, 255], [1.0, 255, 0, 0]], // Blue Red. [[0.0, 255, 0, 0], [0.25, 255, 0, 255], [0.5, 0, 0, 255], [0.75, 0, 255, 255], [1.0, 0, 255, 0]], // Red blue. [[0.0, 0, 0, 0], [1.0, 255, 255, 255]], // Monochrome. [[0.0, 152, 148, 188], [0.5, 204, 160, 204], [1.0, 152, 72, 128]], // Based off of the topographic gradients in Point Clouds. @@ -184,32 +184,36 @@ export namespace Gradient { return 0; // Same pointer if (lhs.mode !== rhs.mode) return lhs.mode - rhs.mode; - if (lhs.flags !== rhs.flags) + if (lhs.flags !== rhs.flags) { if (lhs.flags === undefined) return -1; else if (rhs.flags === undefined) return 1; else return lhs.flags - rhs.flags; - if (lhs.tint !== rhs.tint) + } + if (lhs.tint !== rhs.tint) { if (lhs.tint === undefined) return -1; else if (rhs.tint === undefined) return 1; else return lhs.tint - rhs.tint; - if (lhs.shift !== rhs.shift) + } + if (lhs.shift !== rhs.shift) { if (lhs.shift === undefined) return -1; else if (rhs.shift === undefined) return 1; else return lhs.shift - rhs.shift; - if ((lhs.angle === undefined) !== (rhs.angle === undefined)) + } + if ((lhs.angle === undefined) !== (rhs.angle === undefined)) { if (lhs.angle === undefined) return -1; else return 1; + } if (lhs.angle && !lhs.angle.isAlmostEqualNoPeriodShift(rhs.angle!)) return lhs.angle.radians - rhs.angle!.radians; if (lhs.keys.length !== rhs.keys.length) @@ -220,7 +224,7 @@ export namespace Gradient { if (!lhs.keys[i].color.equals(rhs.keys[i].color)) return lhs.keys[i].color.tbgr - rhs.keys[i].color.tbgr; } - if (lhs.thematicSettings !== rhs.thematicSettings) + if (lhs.thematicSettings !== rhs.thematicSettings) { if (undefined === lhs.thematicSettings) return -1; else if (undefined === rhs.thematicSettings) @@ -230,6 +234,7 @@ export namespace Gradient { if (0 !== thematicCompareResult) return thematicCompareResult; } + } return 0; } @@ -265,7 +270,7 @@ export namespace Gradient { if (this.keys.length <= 2) { w0 = 1.0 - value; w1 = value; - } else { // locate value in map, blend corresponding colors + } else { // locate value in map, blend corresponding colors while (idx < (this.keys.length - 2) && value > this.keys[idx + 1].value) idx++; @@ -296,7 +301,9 @@ export namespace Gradient { } /** Returns true if the [[Gradient.Flags.Outline]] flag is set. */ - public get isOutlined(): boolean { return 0 !== (this.flags & Flags.Outline); } + public get isOutlined(): boolean { + return 0 !== (this.flags & Flags.Outline); + } /** This function (for internal use only) provides the WebGL renderer with a thematic image that its shaders * can use properly with various thematic rendering techniques. @@ -326,7 +333,7 @@ export namespace Gradient { switch (settings.mode) { case ThematicGradientMode.Smooth: { for (let j = 0; j < dimension; j++) { - const f = (1 - j / (dimension)); + const f = 1 - j / dimension; addColor(this.mapColor(f)); } break; @@ -344,7 +351,7 @@ export namespace Gradient { // We really want these values: 0 .25 .5 .75 1 // This preserves an exact color mapping of a n-step gradient when stepCount also equals n. // stepCount must be at least two for this. The thematic API enforces stepCount of at least 2. - const f = (1 - j / (dimension - 1)); + const f = 1 - j / (dimension - 1); addColor(this.mapColor(f)); } break; diff --git a/core/common/src/GraphicParams.ts b/core/common/src/GraphicParams.ts index cf973a1dbf70..a268eb242ae1 100644 --- a/core/common/src/GraphicParams.ts +++ b/core/common/src/GraphicParams.ts @@ -53,10 +53,14 @@ export class GraphicParams { public gradient?: Gradient.Symb; /** Set the transparency of the line color, where 0=fully opaque and 255=full transparent. */ - public setLineTransparency(transparency: number) { this.lineColor = this.lineColor.withTransparency(transparency); } + public setLineTransparency(transparency: number) { + this.lineColor = this.lineColor.withTransparency(transparency); + } /** Set the transparency of the fill color, where 0=fully opaque and 255=full transparent. */ - public setFillTransparency(transparency: number) { this.fillColor = this.fillColor.withTransparency(transparency); } + public setFillTransparency(transparency: number) { + this.fillColor = this.fillColor.withTransparency(transparency); + } public clone(out?: GraphicParams): GraphicParams { out = out ?? new GraphicParams(); diff --git a/core/common/src/HiddenLine.ts b/core/common/src/HiddenLine.ts index ff5a561e34bf..74fedce72c8d 100644 --- a/core/common/src/HiddenLine.ts +++ b/core/common/src/HiddenLine.ts @@ -43,7 +43,9 @@ export namespace HiddenLine { /** Describes the symbology with which edges should be drawn. */ export class Style { /** @internal */ - public get ovrColor(): boolean { return undefined !== this.color; } + public get ovrColor(): boolean { + return undefined !== this.color; + } /** If defined, the color used to draw the edges. If undefined, edges are drawn using the element's line color. */ public readonly color?: ColorDef; /** If defined, the pixel pattern used to draw the edges. If undefined, edges are drawn using the element's line pattern. */ @@ -180,7 +182,9 @@ export namespace HiddenLine { public readonly transparencyThreshold: number; /** An alias for [[transparencyThreshold]]. */ - public get transThreshold(): number { return this.transparencyThreshold; } + public get transThreshold(): number { + return this.transparencyThreshold; + } /** The default display settings. */ public static defaults = new Settings({}); diff --git a/core/common/src/Hilite.ts b/core/common/src/Hilite.ts index b8caab745c8e..83cfc669f40e 100644 --- a/core/common/src/Hilite.ts +++ b/core/common/src/Hilite.ts @@ -48,7 +48,9 @@ export namespace Hilite { /** The type of outline to be drawn around the boundaries of the hilited region. */ public silhouette: Silhouette; - private static clamp(value: number) { return Math.min(1.0, Math.max(0.0, value)); } + private static clamp(value: number) { + return Math.min(1.0, Math.max(0.0, value)); + } public constructor(color = ColorDef.from(0x23, 0xbb, 0xfc), visibleRatio = 0.25, hiddenRatio = 0.0, silhouette = Silhouette.Thin) { this.color = color; diff --git a/core/common/src/IModel.ts b/core/common/src/IModel.ts index 4e9563e5e893..140a41f95abb 100644 --- a/core/common/src/IModel.ts +++ b/core/common/src/IModel.ts @@ -8,8 +8,22 @@ import { assert, BeEvent, GeoServiceStatus, GuidString, Id64, Id64String, IModelStatus, Mutable, OpenMode } from "@itwin/core-bentley"; import { - Angle, AxisIndex, AxisOrder, Constant, Geometry, Matrix3d, Point3d, Range3d, Range3dProps, Transform, TransformProps, Vector3d, XYAndZ, XYZProps, - YawPitchRollAngles, YawPitchRollProps, + Angle, + AxisIndex, + AxisOrder, + Constant, + Geometry, + Matrix3d, + Point3d, + Range3d, + Range3dProps, + Transform, + TransformProps, + Vector3d, + XYAndZ, + XYZProps, + YawPitchRollAngles, + YawPitchRollProps, } from "@itwin/core-geometry"; import { ChangesetIdWithIndex } from "./ChangesetProps"; import { Cartographic, CartographicProps } from "./geometry/Cartographic"; @@ -144,7 +158,7 @@ export interface OpenSqliteArgs { * Specify timeout after which SQLite stop retrying to acquire lock to database file and throw SQLITE_BUSY error. * Timeout is specified in milliseconds. * For more information https://www.sqlite.org/c3ref/busy_timeout.html. - * */ + */ readonly busyTimeout?: number; } @@ -248,14 +262,20 @@ export class EcefLocation implements EcefLocationProps { private readonly _transform: Transform = Transform.createIdentity(); /** Get the transform from iModel Spatial coordinates to ECEF from this EcefLocation */ - public getTransform(): Transform { return this._transform; } + public getTransform(): Transform { + return this._transform; + } /** Construct a new EcefLocation. Once constructed, it is frozen and cannot be modified. */ constructor(props: EcefLocationProps) { this.origin = Point3d.fromJSON(props.origin).freeze(); this.orientation = YawPitchRollAngles.fromJSON(props.orientation).freeze(); if (props.cartographicOrigin) - this.cartographicOrigin = Cartographic.fromRadians({ longitude: props.cartographicOrigin.longitude, latitude: props.cartographicOrigin.latitude, height: props.cartographicOrigin.height }).freeze(); + this.cartographicOrigin = Cartographic.fromRadians({ + longitude: props.cartographicOrigin.longitude, + latitude: props.cartographicOrigin.latitude, + height: props.cartographicOrigin.height, + }).freeze(); if (props.xVector && props.yVector) { this.xVector = Vector3d.fromJSON(props.xVector).freeze(); this.yVector = Vector3d.fromJSON(props.yVector).freeze(); @@ -486,7 +506,7 @@ export abstract class IModel implements IModelProps { * cartographic projection used and a linear transformation should then be calculated at the exact origin of the data * it must position. * @see [GeoLocation of iModels]($docs/learning/GeoLocation.md) - */ + */ public get ecefLocation(): EcefLocation | undefined { return this._ecefLocation; } @@ -535,7 +555,7 @@ export abstract class IModel implements IModelProps { globalOrigin: this.globalOrigin.toJSON(), ecefLocation: this.ecefLocation, geographicCoordinateSystem: this.geographicCoordinateSystem, - ... this._getRpcProps(), + ...this._getRpcProps(), }; } @@ -549,15 +569,21 @@ export abstract class IModel implements IModelProps { */ protected _fileKey: string; /** Get the key that was used to open this iModel. This is the value used for Rpc and Ipc communications. */ - public get key(): string { return this._fileKey; } + public get key(): string { + return this._fileKey; + } /** @internal */ protected _iTwinId?: GuidString; /** The Guid that identifies the iTwin that owns this iModel. */ - public get iTwinId(): GuidString | undefined { return this._iTwinId; } + public get iTwinId(): GuidString | undefined { + return this._iTwinId; + } /** The Guid that identifies this iModel. */ - public get iModelId(): GuidString | undefined { return this._iModelId; } + public get iModelId(): GuidString | undefined { + return this._iModelId; + } /** @public */ public get changeset(): ChangesetIdWithIndex { @@ -573,7 +599,9 @@ export abstract class IModel implements IModelProps { protected _openMode = OpenMode.Readonly; /** The [[OpenMode]] used for this IModel. */ - public get openMode(): OpenMode { return this._openMode; } + public get openMode(): OpenMode { + return this._openMode; + } /** Return a token for RPC operations. * @throws IModelError if the iModel is not open. @@ -628,7 +656,9 @@ export abstract class IModel implements IModelProps { } /** True if this iModel has an [EcefLocation]($docs/learning/glossary#ecefLocation). */ - public get isGeoLocated() { return undefined !== this._ecefLocation; } + public get isGeoLocated() { + return undefined !== this._ecefLocation; + } /** Get the Transform from this iModel's Spatial coordinates to ECEF coordinates using its [[IModel.ecefLocation]]. * @throws IModelError if [[isGeoLocated]] is false. @@ -645,7 +675,9 @@ export abstract class IModel implements IModelProps { * @returns A Point3d in ECEF coordinates * @throws IModelError if [[isGeoLocated]] is false. */ - public spatialToEcef(spatial: XYAndZ, result?: Point3d): Point3d { return this.getEcefTransform().multiplyPoint3d(spatial, result); } + public spatialToEcef(spatial: XYAndZ, result?: Point3d): Point3d { + return this.getEcefTransform().multiplyPoint3d(spatial, result); + } /** Convert a point in ECEF coordinates to a point in this iModel's Spatial coordinates using its [[ecefLocation]]. * @param ecef A point in ECEF coordinates @@ -654,7 +686,9 @@ export abstract class IModel implements IModelProps { * @throws IModelError if [[isGeoLocated]] is false. * @note The resultant point will only be meaningful if the ECEF coordinate is close on the earth to the iModel. */ - public ecefToSpatial(ecef: XYAndZ, result?: Point3d): Point3d { return this.getEcefTransform().multiplyInversePoint3d(ecef, result)!; } + public ecefToSpatial(ecef: XYAndZ, result?: Point3d): Point3d { + return this.getEcefTransform().multiplyInversePoint3d(ecef, result)!; + } /** Convert a point in this iModel's Spatial coordinates to a [[Cartographic]] using its [[IModel.ecefLocation]]. * @param spatial A point in the iModel's spatial coordinates @@ -662,7 +696,9 @@ export abstract class IModel implements IModelProps { * @returns A Cartographic location * @throws IModelError if [[isGeoLocated]] is false. */ - public spatialToCartographicFromEcef(spatial: XYAndZ, result?: Cartographic): Cartographic { return Cartographic.fromEcef(this.spatialToEcef(spatial), result)!; } + public spatialToCartographicFromEcef(spatial: XYAndZ, result?: Cartographic): Cartographic { + return Cartographic.fromEcef(this.spatialToEcef(spatial), result)!; + } /** Convert a [[Cartographic]] to a point in this iModel's Spatial coordinates using its [[IModel.ecefLocation]]. * @param cartographic A cartographic location @@ -671,5 +707,7 @@ export abstract class IModel implements IModelProps { * @throws IModelError if [[isGeoLocated]] is false. * @note The resultant point will only be meaningful if the ECEF coordinate is close on the earth to the iModel. */ - public cartographicToSpatialFromEcef(cartographic: Cartographic, result?: Point3d) { return this.ecefToSpatial(cartographic.toEcef(result), result); } + public cartographicToSpatialFromEcef(cartographic: Cartographic, result?: Point3d) { + return this.ecefToSpatial(cartographic.toEcef(result), result); + } } diff --git a/core/common/src/IModelError.ts b/core/common/src/IModelError.ts index 3c900f23f806..dd39efa43bba 100644 --- a/core/common/src/IModelError.ts +++ b/core/common/src/IModelError.ts @@ -7,14 +7,19 @@ */ import { - BentleyError, BentleyStatus, BriefcaseStatus, ChangeSetStatus, DbResult, IModelHubStatus, IModelStatus, LoggingMetaData, + BentleyError, + BentleyStatus, + BriefcaseStatus, + ChangeSetStatus, + DbResult, + IModelHubStatus, + IModelStatus, + LoggingMetaData, } from "@itwin/core-bentley"; -export { - BentleyStatus, BentleyError, IModelStatus, BriefcaseStatus, DbResult, ChangeSetStatus, -} from "@itwin/core-bentley"; +export { BentleyError, BentleyStatus, BriefcaseStatus, ChangeSetStatus, DbResult, IModelStatus } from "@itwin/core-bentley"; -export type {GetMetaDataFunction, LogFunction, LoggingMetaData} from "@itwin/core-bentley"; +export type { GetMetaDataFunction, LogFunction, LoggingMetaData } from "@itwin/core-bentley"; /** Numeric values for common errors produced by iTwin.js APIs, typically provided by [[IModelError]]. * The values within each of these `enum`s are guaranteed not to conflict with one another. @@ -49,14 +54,14 @@ export enum LockState { /** Detailed information about a particular object Lock that is causing the Lock update conflict. * An example of a lock update conflict would be attempting to use [LockControl.acquireLocks]($backend) on an object that is already locked by another Briefcase. * @public -*/ + */ export interface ConflictingLock { /** Id of the object that is causing conflict. */ objectId: string; /** - * The level of conflicting lock. Possible values are {@link LockState.Shared}, {@link LockState.Exclusive}. - * See {@link LockState}. - */ + * The level of conflicting lock. Possible values are {@link LockState.Shared}, {@link LockState.Exclusive}. + * See {@link LockState}. + */ state: LockState; /** An array of Briefcase ids that hold this lock. */ briefcaseIds: number[]; @@ -73,7 +78,6 @@ export class ConflictingLocksError extends IModelError { super(IModelHubStatus.LockOwnedByAnotherBriefcase, message, getMetaData); this.conflictingLocks = conflictingLocks; } - } /** @public */ diff --git a/core/common/src/IModelVersion.ts b/core/common/src/IModelVersion.ts index c217018ba9a3..0b6880fbc98d 100644 --- a/core/common/src/IModelVersion.ts +++ b/core/common/src/IModelVersion.ts @@ -12,10 +12,10 @@ import { ChangesetId } from "./ChangesetProps"; * @public */ export type IModelVersionProps = - { first: true, latest?: never, afterChangeSetId?: never, versionName?: never } | - { latest: true, first?: never, afterChangeSetId?: never, versionName?: never } | - { afterChangeSetId: string, first?: never, latest?: never, versionName?: never } | - { versionName: string, first?: never, latest?: never, afterChangeSetId?: never }; + | { first: true, latest?: never, afterChangeSetId?: never, versionName?: never } + | { latest: true, first?: never, afterChangeSetId?: never, versionName?: never } + | { afterChangeSetId: string, first?: never, latest?: never, versionName?: never } + | { versionName: string, first?: never, latest?: never, afterChangeSetId?: never }; /** Option to specify the version of the iModel to be acquired and used * @public @@ -26,7 +26,7 @@ export class IModelVersion { private _afterChangeSetId?: string; private _versionName?: string; - private constructor() { } + private constructor() {} /** Describes the first version of the iModel */ public static first(): IModelVersion { @@ -69,10 +69,13 @@ export class IModelVersion { } public toJSON(): IModelVersionProps { - return this._versionName ? { versionName: this._versionName } : - this._afterChangeSetId ? { afterChangeSetId: this._afterChangeSetId } : - this._first ? { first: this._first } : - { latest: true }; + return this._versionName ? + { versionName: this._versionName } : + this._afterChangeSetId ? + { afterChangeSetId: this._afterChangeSetId } : + this._first ? + { first: this._first } : + { latest: true }; } /** Creates a version from an IModelVersionProps */ @@ -86,10 +89,14 @@ export class IModelVersion { } /** Returns true if this describes the first version */ - public get isFirst(): boolean { return !!this._first; } + public get isFirst(): boolean { + return !!this._first; + } /** Returns true if this describes the latest version */ - public get isLatest(): boolean { return !!this._latest; } + public get isLatest(): boolean { + return !!this._latest; + } /** Returns the last change set id to be applied to the iModel * to get to this specified version. @see asOfChangeSet(). @@ -97,8 +104,12 @@ export class IModelVersion { * if this describes the first version, last version, named version, etc. * @see evaluateChangeSet() for those use cases. */ - public getAsOfChangeSet(): ChangesetId | undefined { return this._afterChangeSetId; } + public getAsOfChangeSet(): ChangesetId | undefined { + return this._afterChangeSetId; + } /** Returns the name of the version if this describes a named version. @see named() */ - public getName(): string | undefined { return this._versionName; } + public getName(): string | undefined { + return this._versionName; + } } diff --git a/core/common/src/Image.ts b/core/common/src/Image.ts index 21fad405da4e..f9d08c8d5826 100644 --- a/core/common/src/Image.ts +++ b/core/common/src/Image.ts @@ -33,19 +33,26 @@ export class ImageBuffer { public readonly width: number; /** Return the number of bytes allocated for each pixel. */ - public get numBytesPerPixel(): number { return ImageBuffer.getNumBytesPerPixel(this.format); } + public get numBytesPerPixel(): number { + return ImageBuffer.getNumBytesPerPixel(this.format); + } /** Determine the number of bytes allocated to a single pixel for the specified format. */ public static getNumBytesPerPixel(format: ImageBufferFormat): number { switch (format) { - case ImageBufferFormat.Alpha: return 1; - case ImageBufferFormat.Rgb: return 3; - default: return 4; + case ImageBufferFormat.Alpha: + return 1; + case ImageBufferFormat.Rgb: + return 3; + default: + return 4; } } /** Get the height of this image in pixels. */ - public get height(): number { return ImageBuffer.computeHeight(this.data, this.format, this.width); } + public get height(): number { + return ImageBuffer.computeHeight(this.data, this.format, this.width); + } /** Create a new ImageBuffer. * @note The ImageBuffer takes ownership of the input Uint8Array. diff --git a/core/common/src/IpcAppProps.ts b/core/common/src/IpcAppProps.ts index 463b03ddf980..4b97f4fc9af9 100644 --- a/core/common/src/IpcAppProps.ts +++ b/core/common/src/IpcAppProps.ts @@ -189,4 +189,3 @@ export interface IpcAppFunctions { /** Query the number of concurrent threads supported by the host's IO or CPU thread pool. */ queryConcurrency: (pool: "io" | "cpu") => Promise; } - diff --git a/core/common/src/LightSettings.ts b/core/common/src/LightSettings.ts index 946f65fe154f..b1b47a265459 100644 --- a/core/common/src/LightSettings.ts +++ b/core/common/src/LightSettings.ts @@ -131,7 +131,8 @@ export class SolarLight { } public equals(rhs: SolarLight): boolean { - return this.intensity === rhs.intensity && this.alwaysEnabled === rhs.alwaysEnabled && this.direction.isExactEqual(rhs.direction) && this.timePoint === rhs.timePoint; + return this.intensity === rhs.intensity && this.alwaysEnabled === rhs.alwaysEnabled && this.direction.isExactEqual(rhs.direction) && + this.timePoint === rhs.timePoint; } } @@ -363,8 +364,10 @@ export class FresnelSettings { /** Create a copy of these settings, modified to match any properties explicitly specified by `changedProps`. */ public clone(changedProps?: FresnelSettingsProps): FresnelSettings { - if ((undefined === changedProps?.intensity || changedProps.intensity === this.intensity) - && (undefined === changedProps?.invert || changedProps.invert === this.invert)) + if ( + (undefined === changedProps?.intensity || changedProps.intensity === this.intensity) + && (undefined === changedProps?.invert || changedProps.invert === this.invert) + ) return this; const intensity = changedProps?.intensity ?? this.intensity; @@ -434,8 +437,15 @@ export class LightSettings { public readonly numCels: number; public readonly fresnel: FresnelSettings; - private constructor(solar: SolarLight, ambient: AmbientLight, hemisphere: HemisphereLights, portraitIntensity: number, specularIntensity: number, numCels: number, - fresnel: FresnelSettings) { + private constructor( + solar: SolarLight, + ambient: AmbientLight, + hemisphere: HemisphereLights, + portraitIntensity: number, + specularIntensity: number, + numCels: number, + fresnel: FresnelSettings, + ) { this.solar = solar; this.ambient = ambient; this.hemisphere = hemisphere; @@ -519,6 +529,7 @@ export class LightSettings { return true; return this.portraitIntensity === rhs.portraitIntensity && this.specularIntensity === rhs.specularIntensity && this.numCels === rhs.numCels - && this.ambient.equals(rhs.ambient) && this.solar.equals(rhs.solar) && this.hemisphere.equals(rhs.hemisphere) && this.fresnel.equals(rhs.fresnel); + && this.ambient.equals(rhs.ambient) && this.solar.equals(rhs.solar) && this.hemisphere.equals(rhs.hemisphere) && + this.fresnel.equals(rhs.fresnel); } } diff --git a/core/common/src/Localization.ts b/core/common/src/Localization.ts index 1901a54e2737..880c0c7276c6 100644 --- a/core/common/src/Localization.ts +++ b/core/common/src/Localization.ts @@ -117,21 +117,31 @@ export interface Localization { * @public */ export class EmptyLocalization implements Localization { - public async initialize(): Promise { } + public async initialize(): Promise {} public getLocalizedString(key: string | string[]): string { - if (typeof (key) !== "string") { + if (typeof key !== "string") { key = key[0]; } // Simulate correct and simple usage of i18next's translation function // Namely, remove the leading namespace substring if there is one return key.split(":", 2).pop()!; } - public getLocalizedStringWithNamespace(_namespace: string, key: string | string[]): string { return this.getLocalizedString(key); } - public getEnglishString(_namespace: string, key: string | string[]): string { return this.getLocalizedString(key); } - public getLocalizedKeys(inputString: string): string { return inputString; } - public async registerNamespace(): Promise { } - public unregisterNamespace(): void { } - public getNamespacePromise(): Promise | undefined { return undefined; } - public getLanguageList(): readonly string[] { return []; } - public async changeLanguage() { } + public getLocalizedStringWithNamespace(_namespace: string, key: string | string[]): string { + return this.getLocalizedString(key); + } + public getEnglishString(_namespace: string, key: string | string[]): string { + return this.getLocalizedString(key); + } + public getLocalizedKeys(inputString: string): string { + return inputString; + } + public async registerNamespace(): Promise {} + public unregisterNamespace(): void {} + public getNamespacePromise(): Promise | undefined { + return undefined; + } + public getLanguageList(): readonly string[] { + return []; + } + public async changeLanguage() {} } diff --git a/core/common/src/MapImagerySettings.ts b/core/common/src/MapImagerySettings.ts index ede8dd71a600..a5a5e77e99a8 100644 --- a/core/common/src/MapImagerySettings.ts +++ b/core/common/src/MapImagerySettings.ts @@ -77,18 +77,25 @@ export class MapImagerySettings { /** The settings for the base layer. * @note If changing the base provider it is currently necessary to also update the background map settings. */ - public get backgroundBase(): BaseLayerSettings { return this._backgroundBase; } - public set backgroundBase(base: BaseLayerSettings) { this._backgroundBase = base; } + public get backgroundBase(): BaseLayerSettings { + return this._backgroundBase; + } + public set backgroundBase(base: BaseLayerSettings) { + this._backgroundBase = base; + } - public get backgroundLayers(): MapLayerSettings[] { return this._backgroundLayers; } - public get overlayLayers(): MapLayerSettings[] { return this._overlayLayers; } + public get backgroundLayers(): MapLayerSettings[] { + return this._backgroundLayers; + } + public get overlayLayers(): MapLayerSettings[] { + return this._overlayLayers; + } /** Return base transparency as a number between 0 and 1. * @internal */ public get baseTransparency(): number { return (this._backgroundBase instanceof ColorDef) ? (this._backgroundBase.getTransparency() / 255) : this._backgroundBase.transparency; - } /** Construct from JSON, performing validation and applying default values for undefined fields. */ @@ -98,7 +105,9 @@ export class MapImagerySettings { /** @internal */ public static createFromJSON(imageryJson?: MapImageryProps, mapProps?: DeprecatedBackgroundMapProps) { - const baseLayer = imageryJson?.backgroundBase ? BaseLayerSettings.fromJSON(imageryJson.backgroundBase) : BaseMapLayerSettings.fromBackgroundMapProps(mapProps ?? { }); + const baseLayer = imageryJson?.backgroundBase + ? BaseLayerSettings.fromJSON(imageryJson.backgroundBase) + : BaseMapLayerSettings.fromBackgroundMapProps(mapProps ?? {}); return new MapImagerySettings(baseLayer, imageryJson?.backgroundLayers, imageryJson?.overlayLayers); } diff --git a/core/common/src/MapLayerSettings.ts b/core/common/src/MapLayerSettings.ts index 9a5893d99be2..4b20413007ea 100644 --- a/core/common/src/MapLayerSettings.ts +++ b/core/common/src/MapLayerSettings.ts @@ -15,7 +15,7 @@ import { DeprecatedBackgroundMapProps } from "./BackgroundMapSettings"; * In order to be displayed, a corresponding format must have been registered in the [MapLayerFormatRegistry]($frontend) * @public */ -export type ImageryMapLayerFormatId = "ArcGIS" | "BingMaps" | "MapboxImagery" | "TileURL" | "WMS" | "WMTS"; +export type ImageryMapLayerFormatId = "ArcGIS" | "BingMaps" | "MapboxImagery" | "TileURL" | "WMS" | "WMTS"; /** @public */ export type SubLayerId = string | number; @@ -111,16 +111,24 @@ export class MapSubLayerSettings { } /** return true if this sublayer is named. */ - public get isNamed(): boolean { return this.name.length > 0; } + public get isNamed(): boolean { + return this.name.length > 0; + } /** return true if this sublayer is a leaf (has no children) */ - public get isLeaf(): boolean { return this.children === undefined || this.children.length === 0; } + public get isLeaf(): boolean { + return this.children === undefined || this.children.length === 0; + } /** return true if this sublayer is an unnamed group */ - public get isUnnamedGroup(): boolean { return !this.isLeaf && !this.isNamed; } + public get isUnnamedGroup(): boolean { + return !this.isLeaf && !this.isNamed; + } /** return a string representing this sublayer id (converting to string if underlying id is number) */ - public get idString(): string { return (typeof this.id === "number") ? this.id.toString(10) : this.id; } + public get idString(): string { + return (typeof this.id === "number") ? this.id.toString(10) : this.id; + } } /** JSON representation of properties common to both [[ImageMapLayerProps]] and [[ModelMapLayerProps]]. @@ -167,9 +175,8 @@ export interface ImageMapLayerProps extends CommonMapLayerProps { /** List of query parameters that will get appended to the source. * @beta - */ + */ queryParams?: { [key: string]: string }; - } /** JSON representation of a [[ModelMapLayerSettings]]. @@ -262,7 +269,8 @@ export abstract class MapLayerSettings { /** @internal */ public displayMatches(other: MapLayerSettings): boolean { - return this.name === other.name && this.visible === other.visible && this.transparency === other.transparency && this.transparentBackground === other.transparentBackground; + return this.name === other.name && this.visible === other.visible && this.transparency === other.transparency && + this.transparentBackground === other.transparentBackground; } /** Return a unique string identifying the layers source... The URL for image layer or modelID for model layer */ @@ -291,15 +299,17 @@ export class ImageMapLayerSettings extends MapLayerSettings { /** List of query parameters to append to the settings URL and persisted as part of the JSON representation. * @note Sensitive information like user credentials should be provided in [[unsavedQueryParams]] to ensure it is never persisted. * @beta - */ + */ public savedQueryParams?: { [key: string]: string }; /** List of query parameters that will get appended to the settings URL that should *not* be be persisted part of the JSON representation. * @beta - */ + */ public unsavedQueryParams?: { [key: string]: string }; public readonly subLayers: MapSubLayerSettings[]; - public override get source(): string { return this.url; } + public override get source(): string { + return this.url; + } /** @internal */ protected constructor(props: ImageMapLayerProps) { @@ -310,7 +320,7 @@ export class ImageMapLayerSettings extends MapLayerSettings { this.url = props.url; this.accessKey = props.accessKey; if (props.queryParams) { - this.savedQueryParams = {...props.queryParams}; + this.savedQueryParams = { ...props.queryParams }; } this.subLayers = []; if (!props.subLayers) @@ -337,7 +347,7 @@ export class ImageMapLayerSettings extends MapLayerSettings { props.subLayers = this.subLayers.map((x) => x.toJSON()); if (this.savedQueryParams) - props.queryParams = {...this.savedQueryParams}; + props.queryParams = { ...this.savedQueryParams }; return props; } @@ -354,9 +364,9 @@ export class ImageMapLayerSettings extends MapLayerSettings { clone.password = this.password; clone.accessKey = this.accessKey; if (this.unsavedQueryParams) - clone.unsavedQueryParams = {...this.unsavedQueryParams}; + clone.unsavedQueryParams = { ...this.unsavedQueryParams }; if (this.savedQueryParams) - clone.savedQueryParams = {...this.savedQueryParams}; + clone.savedQueryParams = { ...this.savedQueryParams }; return clone; } @@ -370,9 +380,9 @@ export class ImageMapLayerSettings extends MapLayerSettings { props.accessKey = changedProps.accessKey ?? this.accessKey; props.subLayers = changedProps.subLayers ?? this.subLayers; if (changedProps.queryParams) { - props.queryParams = {...changedProps.queryParams}; + props.queryParams = { ...changedProps.queryParams }; } else if (this.savedQueryParams) { - props.queryParams = {...this.savedQueryParams}; + props.queryParams = { ...this.savedQueryParams }; } return props; @@ -380,7 +390,7 @@ export class ImageMapLayerSettings extends MapLayerSettings { /** @internal */ public override displayMatches(other: MapLayerSettings): boolean { - if (! (other instanceof ImageMapLayerSettings) || !super.displayMatches(other)) + if (!(other instanceof ImageMapLayerSettings) || !super.displayMatches(other)) return false; if (this.userName !== other.userName || this.password !== other.password || this.subLayers.length !== other.subLayers.length) { @@ -444,7 +454,7 @@ export class ImageMapLayerSettings extends MapLayerSettings { } /** @internal */ - protected static mapTypeName(type: BackgroundMapType) { // TBD.. Localization. + protected static mapTypeName(type: BackgroundMapType) { // TBD.. Localization. switch (type) { case BackgroundMapType.Aerial: return "Aerial Imagery"; @@ -462,15 +472,15 @@ export class ImageMapLayerSettings extends MapLayerSettings { } /** Collect all query parameters - * @beta - */ + * @beta + */ public collectQueryParams() { - let queryParams: {[key: string]: string} = {}; + let queryParams: { [key: string]: string } = {}; if (this.savedQueryParams) - queryParams = {...this.savedQueryParams}; + queryParams = { ...this.savedQueryParams }; if (this.unsavedQueryParams) - queryParams = {...queryParams, ...this.unsavedQueryParams}; + queryParams = { ...queryParams, ...this.unsavedQueryParams }; return queryParams; } @@ -485,11 +495,12 @@ export class ImageMapLayerSettings extends MapLayerSettings { */ export class ModelMapLayerSettings extends MapLayerSettings { public readonly modelId: Id64String; - public override get source(): string { return this.modelId; } + public override get source(): string { + return this.modelId; + } /** @internal */ - protected constructor(modelId: Id64String, name: string, visible = true, - transparency: number = 0, transparentBackground = true) { + protected constructor(modelId: Id64String, name: string, visible = true, transparency: number = 0, transparentBackground = true) { super(name, visible, transparency, transparentBackground); this.modelId = modelId; } @@ -555,7 +566,9 @@ export class BaseMapLayerSettings extends ImageMapLayerSettings { private _provider?: BackgroundMapProvider; /** The provider from which this base layer was configured, if any. */ - public get provider(): BackgroundMapProvider | undefined { return this._provider; } + public get provider(): BackgroundMapProvider | undefined { + return this._provider; + } /** Create a base layer from its JSON representation. * TODO: This, MapLayerSettings.fromJSON, and MapSubLayerSettings.fromJSON should never return undefined. diff --git a/core/common/src/ModelGeometryChanges.ts b/core/common/src/ModelGeometryChanges.ts index f90444ae9dad..3b4b84fd802e 100644 --- a/core/common/src/ModelGeometryChanges.ts +++ b/core/common/src/ModelGeometryChanges.ts @@ -106,9 +106,10 @@ export namespace ElementGeometryChange { // eslint-disable-line @typescript-esli if (modelChanges.updated) yield* extantIterable(modelChanges.updated, DbOpcode.Update); - if (modelChanges.deleted) + if (modelChanges.deleted) { for (const id of CompressedId64Set.iterable(modelChanges.deleted)) yield { type: DbOpcode.Delete, id }; + } } /** Obtain an iterable over the geometry changes for a single [GeometricModel]($backend). A given element will appear at most once. */ diff --git a/core/common/src/NativeAppProps.ts b/core/common/src/NativeAppProps.ts index af9fbf4b2e99..0120a829612f 100644 --- a/core/common/src/NativeAppProps.ts +++ b/core/common/src/NativeAppProps.ts @@ -50,7 +50,6 @@ export interface NativeAppNotifications { * @internal */ export interface NativeAppFunctions { - /** If the user is signed in a valid access token will be returned. */ getAccessToken: () => Promise; @@ -67,7 +66,7 @@ export interface NativeAppFunctions { /** Get the filename in the briefcase cache for the supplied BriefcaseId and iModelId. * @note this merely returns the full path fileName. It does not test for the existence of the file. - */ + */ getBriefcaseFileName(_props: BriefcaseProps): Promise; /** Download a briefcase file for the supplied briefcase properties. */ diff --git a/core/common/src/OctEncodedNormal.ts b/core/common/src/OctEncodedNormal.ts index da980e839131..855a81907954 100644 --- a/core/common/src/OctEncodedNormal.ts +++ b/core/common/src/OctEncodedNormal.ts @@ -103,5 +103,5 @@ export class OctEncodedNormal { /** @internal */ export class OctEncodedNormalPair { - constructor(public first: OctEncodedNormal, public second: OctEncodedNormal) { } + constructor(public first: OctEncodedNormal, public second: OctEncodedNormal) {} } diff --git a/core/common/src/PlanProjectionSettings.ts b/core/common/src/PlanProjectionSettings.ts index a94ceb7f5fca..08d9accd5e5b 100644 --- a/core/common/src/PlanProjectionSettings.ts +++ b/core/common/src/PlanProjectionSettings.ts @@ -55,7 +55,9 @@ export class PlanProjectionSettings { if (undefined === props) return undefined; - if (undefined === props.elevation && undefined === props.transparency && undefined === props.overlay && undefined === props.enforceDisplayPriority) + if ( + undefined === props.elevation && undefined === props.transparency && undefined === props.overlay && undefined === props.enforceDisplayPriority + ) return undefined; return new PlanProjectionSettings(props); @@ -103,6 +105,7 @@ export class PlanProjectionSettings { if (this === other) return true; - return this.elevation === other.elevation && this.transparency === other.transparency && this.overlay === other.overlay && this.enforceDisplayPriority === other.enforceDisplayPriority; + return this.elevation === other.elevation && this.transparency === other.transparency && this.overlay === other.overlay && + this.enforceDisplayPriority === other.enforceDisplayPriority; } } diff --git a/core/common/src/PlanarClipMask.ts b/core/common/src/PlanarClipMask.ts index 2ed216520467..d57d64395077 100644 --- a/core/common/src/PlanarClipMask.ts +++ b/core/common/src/PlanarClipMask.ts @@ -194,14 +194,30 @@ export class PlanarClipMaskSettings { } /** Create a new PlanarClipMaskSettings. */ - public static create(args: ModelPlanarClipMaskArgs | ElementPlanarClipMaskArgs | SubCategoryPlanarClipMaskArgs | PriorityPlanarClipMaskArgs): PlanarClipMaskSettings { + public static create( + args: ModelPlanarClipMaskArgs | ElementPlanarClipMaskArgs | SubCategoryPlanarClipMaskArgs | PriorityPlanarClipMaskArgs, + ): PlanarClipMaskSettings { const modelIds = args.modelIds ? CompressedId64Set.sortAndCompress(args.modelIds) : undefined; if (undefined !== args.priority) return new PlanarClipMaskSettings(PlanarClipMaskMode.Priority, args.transparency, undefined, undefined, args.priority, args.invert); else if (undefined !== args.subCategoryIds) - return new PlanarClipMaskSettings(PlanarClipMaskMode.IncludeSubCategories, args.transparency, modelIds, CompressedId64Set.sortAndCompress(args.subCategoryIds), undefined, args.invert); + return new PlanarClipMaskSettings( + PlanarClipMaskMode.IncludeSubCategories, + args.transparency, + modelIds, + CompressedId64Set.sortAndCompress(args.subCategoryIds), + undefined, + args.invert, + ); else if (undefined !== args.elementIds) - return new PlanarClipMaskSettings(args.exclude ? PlanarClipMaskMode.ExcludeElements : PlanarClipMaskMode.IncludeElements, args.transparency, modelIds, CompressedId64Set.sortAndCompress(args.elementIds), undefined, args.invert); + return new PlanarClipMaskSettings( + args.exclude ? PlanarClipMaskMode.ExcludeElements : PlanarClipMaskMode.IncludeElements, + args.transparency, + modelIds, + CompressedId64Set.sortAndCompress(args.elementIds), + undefined, + args.invert, + ); else return new PlanarClipMaskSettings(PlanarClipMaskMode.Models, args.transparency, modelIds, undefined, undefined, args.invert); } @@ -255,7 +271,14 @@ export class PlanarClipMaskSettings { }); } - private constructor(mode: PlanarClipMaskMode, transparency?: number, modelIds?: CompressedId64Set, subCategoryOrElementIds?: CompressedId64Set, priority?: number, invert?: boolean) { + private constructor( + mode: PlanarClipMaskMode, + transparency?: number, + modelIds?: CompressedId64Set, + subCategoryOrElementIds?: CompressedId64Set, + priority?: number, + invert?: boolean, + ) { this.mode = mode; this._modelIds = modelIds; this._subCategoryOrElementIds = subCategoryOrElementIds; diff --git a/core/common/src/QPoint.ts b/core/common/src/QPoint.ts index d20293fb0d1c..fb6b25c6f761 100644 --- a/core/common/src/QPoint.ts +++ b/core/common/src/QPoint.ts @@ -7,9 +7,7 @@ */ import { assert, Uint16ArrayBuilder } from "@itwin/core-bentley"; -import { - Point2d, Point3d, Range2d, Range3d, Vector2d, Vector3d, XAndY, XYAndZ, -} from "@itwin/core-geometry"; +import { Point2d, Point3d, Range2d, Range3d, Vector2d, Vector3d, XAndY, XYAndZ } from "@itwin/core-geometry"; /** * Provides facilities for quantizing floating point values within a specified range into 16-bit unsigned integers. @@ -79,7 +77,9 @@ export class QParams2d { /** The scale applied to coordinates to quantize them. */ public readonly scale = new Point2d(); - private constructor(ox = 0, oy = 0, sx = 0, sy = 0) { this.setFrom(ox, oy, sx, sy); } + private constructor(ox = 0, oy = 0, sx = 0, sy = 0) { + this.setFrom(ox, oy, sx, sy); + } private setFrom(ox: number, oy: number, sx: number, sy: number) { this.origin.x = ox; @@ -105,9 +105,18 @@ export class QParams2d { /** Initialize these parameters to support quantization of values within the specified range. */ public setFromRange(range: Range2d, rangeScale = Quantization.rangeScale16) { if (!range.isNull) { - this.setFrom(range.low.x, range.low.y, Quantization.computeScale(range.high.x - range.low.x, rangeScale), Quantization.computeScale(range.high.y - range.low.y, rangeScale)); + this.setFrom( + range.low.x, + range.low.y, + Quantization.computeScale(range.high.x - range.low.x, rangeScale), + Quantization.computeScale(range.high.y - range.low.y, rangeScale), + ); } else { - this.origin.x = this.origin.y = this.scale.x = this.scale.y = 0; + this.origin.x = + this.origin.y = + this.scale.x = + this.scale.y = + 0; } } @@ -143,7 +152,10 @@ export class QParams2d { /** @internal */ public get rangeDiagonal(): Vector2d { - return Vector2d.createFrom({ x: 0 === this.scale.x ? 0 : Quantization.rangeScale16 / this.scale.x, y: 0 === this.scale.y ? 0 : Quantization.rangeScale16 / this.scale.y }); + return Vector2d.createFrom({ + x: 0 === this.scale.x ? 0 : Quantization.rangeScale16 / this.scale.x, + y: 0 === this.scale.y ? 0 : Quantization.rangeScale16 / this.scale.y, + }); } /** Return true if the point point is quantizable using these parameters. */ @@ -177,21 +189,25 @@ export class QPoint2d { private _y: number = 0; /** The quantized x component. */ - public get x() { return this._x; } + public get x() { + return this._x; + } public set x(x: number) { assert(Quantization.isQuantized(x)); this._x = x; } /** The quantized y component. */ - public get y() { return this._y; } + public get y() { + return this._y; + } public set y(y: number) { assert(Quantization.isQuantized(y)); this._y = y; } /** Construct with `x` and `y` initialized to zero. */ - public constructor() { } + public constructor() {} /** Initialize this point by quantizing the supplied { x, y } using the specified params */ public init(pos: XAndY, params: QParams2d) { @@ -466,8 +482,14 @@ export class QParams3d { /** Initialize these parameters to support quantization of values within the specified range. */ public setFromRange(range: Range3d, rangeScale = Quantization.rangeScale16) { if (!range.isNull) { - this.setFrom(range.low.x, range.low.y, range.low.z, - Quantization.computeScale(range.high.x - range.low.x, rangeScale), Quantization.computeScale(range.high.y - range.low.y, rangeScale), Quantization.computeScale(range.high.z - range.low.z, rangeScale)); + this.setFrom( + range.low.x, + range.low.y, + range.low.z, + Quantization.computeScale(range.high.x - range.low.x, rangeScale), + Quantization.computeScale(range.high.y - range.low.y, rangeScale), + Quantization.computeScale(range.high.z - range.low.z, rangeScale), + ); } else { this.origin.x = this.origin.y = this.origin.z = 0; this.scale.x = this.scale.y = this.scale.z = 0; @@ -524,7 +546,8 @@ export class QParams3d { /** Return true if the point point is quantizable using these parameters. */ public isQuantizable(point: Point3d) { - return Quantization.isQuantizable(point.x, this.origin.x, this.scale.x) && Quantization.isQuantizable(point.y, this.origin.y, this.scale.y) && Quantization.isQuantizable(point.z, this.origin.z, this.scale.z); + return Quantization.isQuantizable(point.x, this.origin.x, this.scale.x) && Quantization.isQuantizable(point.y, this.origin.y, this.scale.y) && + Quantization.isQuantizable(point.z, this.origin.z, this.scale.z); } /** Compute the range to which these parameters quantize. */ @@ -562,28 +585,34 @@ export class QPoint3d { private _z: number = 0; /** The quantized x component. */ - public get x() { return this._x; } + public get x() { + return this._x; + } public set x(x: number) { assert(Quantization.isQuantized(x)); this._x = x; } /** The quantized y component. */ - public get y() { return this._y; } + public get y() { + return this._y; + } public set y(y: number) { assert(Quantization.isQuantized(y)); this._y = y; } /** The quantized z component. */ - public get z() { return this._z; } + public get z() { + return this._z; + } public set z(z: number) { assert(Quantization.isQuantized(z)); this._z = z; } /** Construct with all components initialized to zero. */ - public constructor() { } + public constructor() {} /** Initialize this point by quantizing the supplied { x, y, z } using the specified params */ public init(pos: XYAndZ, params: QParams3d): void { diff --git a/core/common/src/RealityDataAccessProps.ts b/core/common/src/RealityDataAccessProps.ts index 5e44cf5eac32..591bf3187b35 100644 --- a/core/common/src/RealityDataAccessProps.ts +++ b/core/common/src/RealityDataAccessProps.ts @@ -17,7 +17,7 @@ export enum DefaultSupportedTypes { OPC = "OPC", // Web Ready Orbit Point Cloud Terrain3dTiles = "Terrain3DTiles", // Web Ready Terrain Scalable Mesh OMR = "OMR", // Orbit Mapping Resource - Cesium3dTiles = "Cesium3DTiles" // Cesium 3D Tiles + Cesium3dTiles = "Cesium3DTiles", // Cesium 3D Tiles } /** RealityData diff --git a/core/common/src/RealityModelDisplaySettings.ts b/core/common/src/RealityModelDisplaySettings.ts index 0a3386e5594e..137bac16cf9e 100644 --- a/core/common/src/RealityModelDisplaySettings.ts +++ b/core/common/src/RealityModelDisplaySettings.ts @@ -184,7 +184,7 @@ export class PointCloudDisplaySettings { if (this.equals(defs)) return undefined; - const props: PointCloudDisplayProps = { }; + const props: PointCloudDisplayProps = {}; if (this.shape !== defs.shape) props.shape = this.shape; @@ -241,11 +241,11 @@ export class PointCloudDisplaySettings { return true; return this.shape === other.shape && this.sizeMode === other.sizeMode && this.pixelSize === other.pixelSize - && this.voxelScale === other.voxelScale && this.minPixelsPerVoxel === other.minPixelsPerVoxel && this.maxPixelsPerVoxel === other.maxPixelsPerVoxel + && this.voxelScale === other.voxelScale && this.minPixelsPerVoxel === other.minPixelsPerVoxel && + this.maxPixelsPerVoxel === other.maxPixelsPerVoxel && this.edlMode === other.edlMode && this.edlStrength === other.edlStrength && this.edlRadius === other.edlRadius && this.edlFilter === other.edlFilter - && this.edlMixWts1 === other.edlMixWts1 && this.edlMixWts2 === other.edlMixWts2 && this.edlMixWts4 === other.edlMixWts4 - ; + && this.edlMixWts1 === other.edlMixWts1 && this.edlMixWts2 === other.edlMixWts2 && this.edlMixWts4 === other.edlMixWts4; } } @@ -286,12 +286,14 @@ export class RealityModelDisplaySettings { /** Convert these settings to their JSON representation, which is `undefined` if all of their properties match the default settings. */ public toJSON(): RealityModelDisplayProps | undefined { const pointCloud = this.pointCloud.toJSON(); - const overrideColorRatio = this.overrideColorRatio === RealityModelDisplaySettings.defaults.overrideColorRatio ? undefined : this.overrideColorRatio; + const overrideColorRatio = this.overrideColorRatio === RealityModelDisplaySettings.defaults.overrideColorRatio + ? undefined + : this.overrideColorRatio; if (undefined === pointCloud && undefined === overrideColorRatio) return undefined; - const props: RealityModelDisplayProps = { }; + const props: RealityModelDisplayProps = {}; if (undefined !== pointCloud) props.pointCloud = pointCloud; diff --git a/core/common/src/Render.ts b/core/common/src/Render.ts index 3b64f74d909d..8ca66ae631a5 100644 --- a/core/common/src/Render.ts +++ b/core/common/src/Render.ts @@ -59,7 +59,9 @@ export class MeshPolyline { indices.push(index); } - public clear() { this.indices.length = 0; } + public clear() { + this.indices.length = 0; + } } /** @internal */ @@ -100,7 +102,7 @@ export class MeshEdges { public silhouette: MeshEdge[] = []; public polylines: MeshPolylineList = new MeshPolylineList(); public silhouetteNormals: OctEncodedNormalPair[] = []; - public constructor() { } + public constructor() {} } /** @internal */ @@ -115,9 +117,15 @@ export class EdgeArgs { return this.isValid; } - public clear(): void { this.edges = undefined; } - public get isValid(): boolean { return 0 < this.numEdges; } - public get numEdges() { return undefined !== this.edges ? this.edges.length : 0; } + public clear(): void { + this.edges = undefined; + } + public get isValid(): boolean { + return 0 < this.numEdges; + } + public get numEdges() { + return undefined !== this.edges ? this.edges.length : 0; + } } /** @internal */ @@ -144,14 +152,22 @@ export class SilhouetteEdgeArgs extends EdgeArgs { export class PolylineEdgeArgs { public lines?: PolylineIndices[]; - public constructor(lines?: PolylineIndices[]) { this.init(lines); } + public constructor(lines?: PolylineIndices[]) { + this.init(lines); + } public init(lines?: PolylineIndices[]): boolean { this.lines = undefined !== lines && 0 < lines.length ? lines : undefined; return this.isValid; } - public get numLines() { return undefined !== this.lines ? this.lines.length : 0; } - public get isValid() { return this.numLines > 0; } - public clear() { this.lines = undefined; } + public get numLines() { + return undefined !== this.lines ? this.lines.length : 0; + } + public get isValid() { + return this.numLines > 0; + } + public clear() { + this.lines = undefined; + } } diff --git a/core/common/src/RenderMaterial.ts b/core/common/src/RenderMaterial.ts index 87807965a2af..b0e6006ef5af 100644 --- a/core/common/src/RenderMaterial.ts +++ b/core/common/src/RenderMaterial.ts @@ -72,7 +72,9 @@ export namespace RenderMaterial { // eslint-disable-line no-redeclare public shadows = true; private _alpha?: number; - public constructor(key?: string) { this.key = key; } + public constructor(key?: string) { + this.key = key; + } /** Obtain an immutable instance of a RenderMaterial with all default properties. */ // eslint-disable-next-line deprecation/deprecation @@ -81,14 +83,23 @@ export namespace RenderMaterial { // eslint-disable-line no-redeclare /** A value from 0.0 (fully-transparent) to 1.0 (fully-opaque) controlling the transparency of surfaces to which this material is applied; * or undefined if this material does not override surface transparency. */ - public get alpha(): number | undefined { return this._alpha; } + public get alpha(): number | undefined { + return this._alpha; + } public set alpha(alpha: number | undefined) { this._alpha = undefined !== alpha ? clampToNormalizedRange(alpha) : undefined; } /** Create a RenderMaterial params object using specified key and ColorDef values, as well as an optional texture mapping. */ // eslint-disable-next-line deprecation/deprecation - public static fromColors(key?: string, diffuseColor?: ColorDef, specularColor?: ColorDef, emissiveColor?: ColorDef, reflectColor?: ColorDef, textureMap?: TextureMapping): Params { + public static fromColors( + key?: string, + diffuseColor?: ColorDef, + specularColor?: ColorDef, + emissiveColor?: ColorDef, + reflectColor?: ColorDef, + textureMap?: TextureMapping, + ): Params { // eslint-disable-next-line deprecation/deprecation const materialParams = new Params(); materialParams.key = key; diff --git a/core/common/src/RenderSchedule.ts b/core/common/src/RenderSchedule.ts index 47aa17910e26..98067e7201f3 100644 --- a/core/common/src/RenderSchedule.ts +++ b/core/common/src/RenderSchedule.ts @@ -7,16 +7,37 @@ */ import { - assert, compareBooleans, compareNumbers, comparePossiblyUndefined, compareStrings, compareStringsOrUndefined, - CompressedId64Set, Constructor, Id64, Id64String, OrderedId64Iterable, + assert, + compareBooleans, + compareNumbers, + comparePossiblyUndefined, + compareStrings, + compareStringsOrUndefined, + CompressedId64Set, + Constructor, + Id64, + Id64String, + OrderedId64Iterable, } from "@itwin/core-bentley"; -import { EntityReferenceSet } from "./EntityReference"; import { - ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Matrix3d, Plane3dByOriginAndUnitNormal, Point3d, Point4d, Range1d, Transform, UnionOfConvexClipPlaneSets, Vector3d, XYAndZ, + ClipPlane, + ClipPrimitive, + ClipVector, + ConvexClipPlaneSet, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point3d, + Point4d, + Range1d, + Transform, + UnionOfConvexClipPlaneSets, + Vector3d, + XYAndZ, } from "@itwin/core-geometry"; -import { RgbColor } from "./RgbColor"; +import { EntityReferenceSet } from "./EntityReference"; import { FeatureAppearance, FeatureOverrides } from "./FeatureSymbology"; -import {PackedFeatureWithIndex} from "./FeatureTable"; +import { PackedFeatureWithIndex } from "./FeatureTable"; +import { RgbColor } from "./RgbColor"; function interpolate(start: number, end: number, fraction: number): number { return start + fraction * (end - start); @@ -305,7 +326,8 @@ export namespace RenderSchedule { } public equals(other: TransformComponents): boolean { - return this.pivot.isAlmostEqual(other.pivot) && this.position.isAlmostEqual(other.position) && this.orientation.isAlmostEqual(other.orientation); + return this.pivot.isAlmostEqual(other.pivot) && this.position.isAlmostEqual(other.position) && + this.orientation.isAlmostEqual(other.orientation); } } @@ -386,7 +408,8 @@ export namespace RenderSchedule { } public compareTo(other: CuttingPlane): number { - return compareXYZ(this.position, other.position) || compareXYZ(this.direction, other.direction) || compareBooleans(this.visible, other.visible) || compareBooleans(this.hidden, other.hidden); + return compareXYZ(this.position, other.position) || compareXYZ(this.direction, other.direction) || + compareBooleans(this.visible, other.visible) || compareBooleans(this.hidden, other.hidden); } public equals(other: CuttingPlane): boolean { @@ -617,8 +640,10 @@ export namespace RenderSchedule { else if (!!this.cuttingPlane !== !!other.cuttingPlane) return this.cuttingPlane ? 1 : -1; - return comparePossiblyUndefined((x, y) => x.compareTo(y), this.visibility, other.visibility) || comparePossiblyUndefined((x, y) => x.compareTo(y), this.color, other.color) - || comparePossiblyUndefined((x, y) => x.compareTo(y), this.transform, other.transform) || comparePossiblyUndefined((x, y) => x.compareTo(y), this.cuttingPlane, other.cuttingPlane); + return comparePossiblyUndefined((x, y) => x.compareTo(y), this.visibility, other.visibility) || + comparePossiblyUndefined((x, y) => x.compareTo(y), this.color, other.color) + || comparePossiblyUndefined((x, y) => x.compareTo(y), this.transform, other.transform) || + comparePossiblyUndefined((x, y) => x.compareTo(y), this.cuttingPlane, other.cuttingPlane); } public equals(other: Timeline): boolean { @@ -945,8 +970,10 @@ export namespace RenderSchedule { assert(other instanceof ModelTimeline); let cmp = compareStrings(this.modelId, other.modelId) || compareStringsOrUndefined(this.realityModelUrl, other.realityModelUrl) - || compareNumbers(this.elementTimelines.length, other.elementTimelines.length) || compareBooleans(this.containsFeatureOverrides, other.containsFeatureOverrides) - || compareBooleans(this.containsModelClipping, other.containsModelClipping) || compareBooleans(this.containsTransform, other.containsTransform) + || compareNumbers(this.elementTimelines.length, other.elementTimelines.length) || + compareBooleans(this.containsFeatureOverrides, other.containsFeatureOverrides) + || compareBooleans(this.containsModelClipping, other.containsModelClipping) || + compareBooleans(this.containsTransform, other.containsTransform) || super.compareTo(other); if (0 === cmp) { @@ -1071,7 +1098,8 @@ export namespace RenderSchedule { if (undefined !== cached) return cached; - let cmp = compareNumbers(this.modelTimelines.length, other.modelTimelines.length) || compareBooleans(this.containsModelClipping, other.containsModelClipping) + let cmp = compareNumbers(this.modelTimelines.length, other.modelTimelines.length) || + compareBooleans(this.containsModelClipping, other.containsModelClipping) || compareBooleans(this.requiresBatching, other.requiresBatching) || compareBooleans(this.containsTransform, other.containsTransform) || compareBooleans(this.containsFeatureOverrides, other.containsFeatureOverrides) || compareDurations(this.duration, other.duration); @@ -1274,7 +1302,11 @@ export namespace RenderSchedule { } /** Append a new [[RenderSchedule.ColorEntry]] to the timeline. `time` must be more recent than any previously-appended color entries. */ - public addColor(time: number, color: RgbColor | { red: number, green: number, blue: number } | undefined, interpolation = Interpolation.Linear): void { + public addColor( + time: number, + color: RgbColor | { red: number, green: number, blue: number } | undefined, + interpolation = Interpolation.Linear, + ): void { if (!this.color) this.color = []; @@ -1283,7 +1315,11 @@ export namespace RenderSchedule { } /** Append a new [[RenderSchedule.CuttingPlaneEntry]] to the timeline. `time` must be more recent than any previously-appended cutting plane entries. */ - public addCuttingPlane(time: number, plane: { position: XYAndZ, direction: XYAndZ, visible?: boolean, hidden?: boolean } | undefined, interpolation = Interpolation.Linear): void { + public addCuttingPlane( + time: number, + plane: { position: XYAndZ, direction: XYAndZ, visible?: boolean, hidden?: boolean } | undefined, + interpolation = Interpolation.Linear, + ): void { if (!this.cuttingPlane) this.cuttingPlane = []; @@ -1305,7 +1341,12 @@ export namespace RenderSchedule { } /** Append a new [[RenderSchedule.TransformEntry]] to the timeline. `time` must be more recent than any previously-appended transform entries. */ - public addTransform(time: number, transform: Readonly | undefined, components?: { pivot: XYAndZ, orientation: Point4d, position: XYAndZ }, interpolation = Interpolation.Linear): void { + public addTransform( + time: number, + transform: Readonly | undefined, + components?: { pivot: XYAndZ, orientation: Point4d, position: XYAndZ }, + interpolation = Interpolation.Linear, + ): void { if (!this.transform) this.transform = []; @@ -1393,7 +1434,6 @@ export namespace RenderSchedule { /** Add a new [[RenderSchedule.ElementTimeline]] to be applied to the specified elements. * This function will sort and compress the Ids if they are not already compressed. - * */ public addElementTimeline(elementIds: CompressedId64Set | Iterable): ElementTimelineBuilder { const batchId = this._obtainNextBatchId(); diff --git a/core/common/src/RenderTexture.ts b/core/common/src/RenderTexture.ts index 33bc2e19c29a..db67132e9480 100644 --- a/core/common/src/RenderTexture.ts +++ b/core/common/src/RenderTexture.ts @@ -28,9 +28,15 @@ export abstract class RenderTexture implements IDisposable { /** Used for ordered comparisons, e.g. in DisplayParams.compareForMerge */ private readonly _guid: GuidString; - public get isTileSection(): boolean { return RenderTexture.Type.TileSection === this.type; } - public get isGlyph(): boolean { return RenderTexture.Type.Glyph === this.type; } - public get isSkyBox(): boolean { return RenderTexture.Type.SkyBox === this.type; } + public get isTileSection(): boolean { + return RenderTexture.Type.TileSection === this.type; + } + public get isGlyph(): boolean { + return RenderTexture.Type.Glyph === this.type; + } + public get isSkyBox(): boolean { + return RenderTexture.Type.SkyBox === this.type; + } public abstract get bytesUsed(): number; protected constructor(type: RenderTexture.Type) { @@ -91,8 +97,14 @@ export namespace RenderTexture { // eslint-disable-line no-redeclare this.isOwned = isOwned; } - public get isTileSection(): boolean { return RenderTexture.Type.TileSection === this.type; } - public get isGlyph(): boolean { return RenderTexture.Type.Glyph === this.type; } - public get isSkyBox(): boolean { return RenderTexture.Type.SkyBox === this.type; } + public get isTileSection(): boolean { + return RenderTexture.Type.TileSection === this.type; + } + public get isGlyph(): boolean { + return RenderTexture.Type.Glyph === this.type; + } + public get isSkyBox(): boolean { + return RenderTexture.Type.SkyBox === this.type; + } } } diff --git a/core/common/src/RpcInterface.ts b/core/common/src/RpcInterface.ts index 1525dd903645..9a5987a745e6 100644 --- a/core/common/src/RpcInterface.ts +++ b/core/common/src/RpcInterface.ts @@ -5,17 +5,17 @@ /** @packageDocumentation * @module RpcInterface */ +import { BeDuration } from "@itwin/core-bentley"; +import { BentleyStatus, IModelError, NoContentError } from "./IModelError"; +import { InterceptedRpcRequest, IpcSession } from "./ipc/IpcSession"; import { RpcConfiguration, RpcConfigurationSupplier } from "./rpc/core/RpcConfiguration"; +import { RpcRequestEvent, RpcRequestStatus } from "./rpc/core/RpcConstants"; +import { RpcNotFoundResponse } from "./rpc/core/RpcControl"; +import { RpcSerializedValue } from "./rpc/core/RpcMarshaling"; +import { RpcManagedStatus } from "./rpc/core/RpcProtocol"; import { CURRENT_REQUEST } from "./rpc/core/RpcRegistry"; import { aggregateLoad, RpcRequest } from "./rpc/core/RpcRequest"; import { RpcRoutingToken } from "./rpc/core/RpcRoutingToken"; -import { InterceptedRpcRequest, IpcSession } from "./ipc/IpcSession"; -import { RpcSerializedValue } from "./rpc/core/RpcMarshaling"; -import { RpcManagedStatus } from "./rpc/core/RpcProtocol"; -import { BentleyStatus, IModelError, NoContentError } from "./IModelError"; -import { RpcRequestEvent, RpcRequestStatus } from "./rpc/core/RpcConstants"; -import { BeDuration } from "@itwin/core-bentley"; -import { RpcNotFoundResponse } from "./rpc/core/RpcControl"; /* eslint-disable deprecation/deprecation */ @@ -24,13 +24,17 @@ import { RpcNotFoundResponse } from "./rpc/core/RpcControl"; * These properties are used to identify RPC requests and responses. * @beta */ -export interface RpcInterfaceDefinition { prototype: T, interfaceName: string, interfaceVersion: string } +export interface RpcInterfaceDefinition { + prototype: T; + interfaceName: string; + interfaceVersion: string; +} /** * A class that implements the operations of an RPC interface. * @beta */ -export type RpcInterfaceImplementation = new () => T; +export type RpcInterfaceImplementation = new() => T; interface SemverType { major: number; @@ -44,13 +48,16 @@ interface SemverType { * @public */ export abstract class RpcInterface { - private static findDiff(backend: SemverType, frontend: SemverType) { - return backend.major !== frontend.major ? "major" : - backend.minor !== frontend.minor ? "minor" : - backend.patch !== frontend.patch ? "patch" : - backend.prerelease !== frontend.prerelease ? "prerelease" : - "same"; + return backend.major !== frontend.major ? + "major" : + backend.minor !== frontend.minor ? + "minor" : + backend.patch !== frontend.patch ? + "patch" : + backend.prerelease !== frontend.prerelease ? + "prerelease" : + "same"; } private static parseVer(version: string): SemverType { @@ -106,7 +113,7 @@ export abstract class RpcInterface { /** Obtains the implementation result for an RPC operation. */ public async forward(parameters: IArguments): Promise { - const parametersCompat = (arguments.length === 1 && typeof (parameters) === "object") ? parameters : arguments; + const parametersCompat = (arguments.length === 1 && typeof parameters === "object") ? parameters : arguments; const parametersArray = Array.isArray(parametersCompat) ? parametersCompat : Array.prototype.slice.call(parametersCompat); const operationName = parametersArray.pop(); @@ -128,9 +135,15 @@ export abstract class RpcInterface { RpcInterface.prototype.configurationSupplier = undefined; class InterceptedRequest extends RpcRequest { - protected override async load(): Promise { throw new Error(); } - protected override async send(): Promise { throw new Error(); } - protected override setHeader(_name: string, _value: string): void { throw new Error(); } + protected override async load(): Promise { + throw new Error(); + } + protected override async send(): Promise { + throw new Error(); + } + protected override setHeader(_name: string, _value: string): void { + throw new Error(); + } } async function intercept(session: IpcSession, client: RpcInterface, operation: string, parameters: any[]) { @@ -163,7 +176,7 @@ async function intercept(session: IpcSession, client: RpcInterface, operation: s aggregateLoad.lastResponse = new Date().getTime(); - if (typeof (response) === "object" && response.hasOwnProperty("iTwinRpcCoreResponse") && response.hasOwnProperty("managedStatus")) { + if (typeof response === "object" && response.hasOwnProperty("iTwinRpcCoreResponse") && response.hasOwnProperty("managedStatus")) { const status: RpcManagedStatus = response; if (status.managedStatus === "pending") { diff --git a/core/common/src/RpcManager.ts b/core/common/src/RpcManager.ts index 2e708c90de9c..f57cccb56c57 100644 --- a/core/common/src/RpcManager.ts +++ b/core/common/src/RpcManager.ts @@ -9,8 +9,8 @@ import { IModelRpcProps } from "./IModel"; import { RpcOperation } from "./rpc/core/RpcOperation"; import { RpcRegistry } from "./rpc/core/RpcRegistry"; -import { RpcInterface, RpcInterfaceDefinition, RpcInterfaceImplementation } from "./RpcInterface"; import { RpcRoutingToken } from "./rpc/core/RpcRoutingToken"; +import { RpcInterface, RpcInterfaceDefinition, RpcInterfaceImplementation } from "./RpcInterface"; /* eslint-disable deprecation/deprecation */ @@ -41,17 +41,26 @@ export class RpcManager { } /** Returns the RPC client instance for the frontend. */ - public static getClientForInterface(definition: RpcInterfaceDefinition, routing: RpcRoutingToken = RpcRoutingToken.default): T { + public static getClientForInterface( + definition: RpcInterfaceDefinition, + routing: RpcRoutingToken = RpcRoutingToken.default, + ): T { return RpcRegistry.instance.getClientForInterface(definition, routing); } /** Register the RPC implementation class for the backend. */ - public static registerImpl(definition: RpcInterfaceDefinition, implementation: RpcInterfaceImplementation): void { + public static registerImpl( + definition: RpcInterfaceDefinition, + implementation: RpcInterfaceImplementation, + ): void { RpcRegistry.instance.registerImpl(definition, implementation); } /** Supply the instance of the RPC interface implementation class for the backend (optional). */ - public static supplyImplInstance(definition: RpcInterfaceDefinition, instance: TImplementation): void { + public static supplyImplInstance( + definition: RpcInterfaceDefinition, + instance: TImplementation, + ): void { RpcRegistry.instance.supplyImplInstance(definition, instance); } diff --git a/core/common/src/SessionProps.ts b/core/common/src/SessionProps.ts index 3debb6628212..10aa9f8dcc1d 100644 --- a/core/common/src/SessionProps.ts +++ b/core/common/src/SessionProps.ts @@ -22,4 +22,3 @@ export interface SessionProps { /** Used for logging to identify a session */ readonly sessionId: GuidString; } - diff --git a/core/common/src/SkyBox.ts b/core/common/src/SkyBox.ts index eef7a56f122a..63854ce1fde2 100644 --- a/core/common/src/SkyBox.ts +++ b/core/common/src/SkyBox.ts @@ -270,7 +270,10 @@ export class SkyBox { break; case SkyBoxImageType.Cube: { const tx = props.image.textures; - if (tx && undefined !== tx.top && undefined !== tx.bottom && undefined !== tx.right && undefined !== tx.left && undefined !== tx.front && undefined !== tx.back) + if ( + tx && undefined !== tx.top && undefined !== tx.bottom && undefined !== tx.right && undefined !== tx.left && undefined !== tx.front && + undefined !== tx.back + ) return new SkyCube(tx, gradient); break; diff --git a/core/common/src/SolarCalculate.ts b/core/common/src/SolarCalculate.ts index 3ae7dfd5b920..bcc9143044e2 100644 --- a/core/common/src/SolarCalculate.ts +++ b/core/common/src/SolarCalculate.ts @@ -33,17 +33,17 @@ function calcGeomMeanLongSun(t: number) { while (L0 < 0.0) { L0 += 360.0; } - return L0; // in degrees + return L0; // in degrees } function calcGeomMeanAnomalySun(t: number) { const M = 357.52911 + t * (35999.05029 - 0.0001537 * t); - return M; // in degrees + return M; // in degrees } function calcEccentricityEarthOrbit(t: number) { const e = 0.016708634 - t * (0.000042037 + 0.0000001267 * t); - return e; // unitless + return e; // unitless } function calcSunEqOfCenter(t: number) { @@ -53,34 +53,34 @@ function calcSunEqOfCenter(t: number) { const sin2m = Math.sin(mrad + mrad); const sin3m = Math.sin(mrad + mrad + mrad); const C = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289; - return C; // in degrees + return C; // in degrees } function calcSunTrueLong(t: number) { const l0 = calcGeomMeanLongSun(t); const c = calcSunEqOfCenter(t); const O = l0 + c; - return O; // in degrees + return O; // in degrees } function calcSunApparentLong(t: number) { const o = calcSunTrueLong(t); const omega = 125.04 - 1934.136 * t; const lambda = o - 0.00569 - 0.00478 * Math.sin(degToRad(omega)); - return lambda; // in degrees + return lambda; // in degrees } function calcMeanObliquityOfEcliptic(t: number) { const seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * (0.001813))); const e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0; - return e0; // in degrees + return e0; // in degrees } function calcObliquityCorrection(t: number) { const e0 = calcMeanObliquityOfEcliptic(t); const omega = 125.04 - 1934.136 * t; const e = e0 + 0.00256 * Math.cos(degToRad(omega)); - return e; // in degrees + return e; // in degrees } function calcSunDeclination(t: number) { @@ -89,7 +89,7 @@ function calcSunDeclination(t: number) { const sint = Math.sin(degToRad(e)) * Math.sin(degToRad(lambda)); const theta = radToDeg(Math.asin(sint)); - return theta; // in degrees + return theta; // in degrees } function calcEquationOfTime(t: number) { @@ -108,7 +108,7 @@ function calcEquationOfTime(t: number) { const sin2m = Math.sin(2.0 * degToRad(m)); const eTime = y * sin2l0 - 2.0 * e * sinm + 4.0 * e * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * e * e * sin2m; - return radToDeg(eTime) * 4.0; // in minutes of time + return radToDeg(eTime) * 4.0; // in minutes of time } function calcAzEl(t: number, localTime: number, latitude: number, longitude: number, zone: number): { azimuth: number, elevation: number } { @@ -131,7 +131,7 @@ function calcAzEl(t: number, localTime: number, latitude: number, longitude: num csz = -1.0; } const zenith = radToDeg(Math.acos(csz)); - const azDenom = (Math.cos(degToRad(latitude)) * Math.sin(degToRad(zenith))); + const azDenom = Math.cos(degToRad(latitude)) * Math.sin(degToRad(zenith)); let azimuth; if (Math.abs(azDenom) > 0.001) { let azRad = ((Math.sin(degToRad(latitude)) * Math.cos(degToRad(zenith))) - Math.sin(degToRad(theta))) / azDenom; @@ -160,7 +160,7 @@ function calcAzEl(t: number, localTime: number, latitude: number, longitude: num } function calculateJulianDay(date: Date) { - return Math.floor(date.getTime() / 86400000) + 2440587.5; // https://stackoverflow.com/questions/11759992/calculating-jdayjulian-day-in-javascript + return Math.floor(date.getTime() / 86400000) + 2440587.5; // https://stackoverflow.com/questions/11759992/calculating-jdayjulian-day-in-javascript } /** @public @@ -211,10 +211,10 @@ function calcSunriseUtcMinutes(rise: boolean, lat: number, longitude: number, jD const solarDec = calcSunDeclination(t); const latRad = degToRad(lat); const sdRad = degToRad(solarDec); - const hAarg = (Math.cos(degToRad(90.833)) / (Math.cos(latRad) * Math.cos(sdRad)) - Math.tan(latRad) * Math.tan(sdRad)); + const hAarg = Math.cos(degToRad(90.833)) / (Math.cos(latRad) * Math.cos(sdRad)) - Math.tan(latRad) * Math.tan(sdRad); const hourAngle = Math.acos(hAarg); - const delta = longitude + radToDeg(rise ? hourAngle : - hourAngle); - return 720 - (4.0 * delta) - eqTime; // in UTC minutes + const delta = longitude + radToDeg(rise ? hourAngle : -hourAngle); + return 720 - (4.0 * delta) - eqTime; // in UTC minutes } /** @public @@ -225,5 +225,7 @@ export function calculateSunriseOrSunset(date: Date, location: Cartographic, sun const longitude = location.longitudeDegrees; const latitude = location.latitudeDegrees; const utcMinutes = calcSunriseUtcMinutes(sunrise, latitude, longitude, jDay); - return sunrise ? dateFromUtcMinutes(date, utcMinutes) : dateFromUtcMinutes(date, calcSunriseUtcMinutes(sunrise, latitude, longitude, jDay + utcMinutes / 1440)); + return sunrise + ? dateFromUtcMinutes(date, utcMinutes) + : dateFromUtcMinutes(date, calcSunriseUtcMinutes(sunrise, latitude, longitude, jDay + utcMinutes / 1440)); } diff --git a/core/common/src/SpatialClassification.ts b/core/common/src/SpatialClassification.ts index 209f575d9d6b..831e11d0f2db 100644 --- a/core/common/src/SpatialClassification.ts +++ b/core/common/src/SpatialClassification.ts @@ -66,7 +66,11 @@ export class SpatialClassifierFlags { public readonly isVolumeClassifier: boolean; /** Construct new flags. */ - public constructor(inside = SpatialClassifierInsideDisplay.ElementColor, outside = SpatialClassifierOutsideDisplay.Dimmed, isVolumeClassifier = false) { + public constructor( + inside = SpatialClassifierInsideDisplay.ElementColor, + outside = SpatialClassifierOutsideDisplay.Dimmed, + isVolumeClassifier = false, + ) { this.inside = insideDisplay(inside); this.outside = outsideDisplay(outside); this.isVolumeClassifier = isVolumeClassifier; @@ -191,7 +195,7 @@ export class SpatialClassifier { * @beta */ public static fromModelMapLayer(mapLayer: ModelMapLayerSettings): SpatialClassifier { - const flags = SpatialClassifierFlags.fromJSON({ inside: SpatialClassifierInsideDisplay.Off, outside: SpatialClassifierOutsideDisplay.Off }); + const flags = SpatialClassifierFlags.fromJSON({ inside: SpatialClassifierInsideDisplay.Off, outside: SpatialClassifierOutsideDisplay.Off }); return new SpatialClassifier(mapLayer.modelId, mapLayer.name, flags); } @@ -304,7 +308,7 @@ export class SpatialClassifiers implements Iterable { this._active = active; for (let i = 0; i < array.length; i++) - array[i].isActive = (i === propsIndex); + array[i].isActive = i === propsIndex; return this.active; } diff --git a/core/common/src/SubCategoryAppearance.ts b/core/common/src/SubCategoryAppearance.ts index a084623960e6..f8684251ce13 100644 --- a/core/common/src/SubCategoryAppearance.ts +++ b/core/common/src/SubCategoryAppearance.ts @@ -54,9 +54,13 @@ export class SubCategoryAppearance { * @note The transparency component of the fill color is ignored. * @see [[SubCategoryAppearance.fillTransparency]]. */ - public get fillColor(): ColorDef { return (undefined !== this._fillColor ? this._fillColor : this.color); } + public get fillColor(): ColorDef { + return (undefined !== this._fillColor ? this._fillColor : this.color); + } /** A value in the range [0, 1] indicating the fill transparency of the geometry where 0.0 means "fully opaque" and 1.0 means "fully transparent". */ - public get fillTransparency(): number { return (undefined !== this._fillTransparency ? this._fillTransparency : this.transparency); } + public get fillTransparency(): number { + return (undefined !== this._fillTransparency ? this._fillTransparency : this.transparency); + } constructor(props?: SubCategoryAppearance.Props) { if (!props) { @@ -64,7 +68,11 @@ export class SubCategoryAppearance { this.weight = 0; this.priority = 0; this.transparency = 0; - this.invisible = this.dontPlot = this.dontSnap = this.dontLocate = false; + this.invisible = + this.dontPlot = + this.dontSnap = + this.dontLocate = + false; this.styleId = Id64.invalid; this.materialId = Id64.invalid; return; @@ -140,7 +148,9 @@ export class SubCategoryAppearance { return val; } - public clone(): SubCategoryAppearance { return new SubCategoryAppearance(this.toJSON()); } + public clone(): SubCategoryAppearance { + return new SubCategoryAppearance(this.toJSON()); + } public static defaults = new SubCategoryAppearance(); } diff --git a/core/common/src/SubCategoryOverride.ts b/core/common/src/SubCategoryOverride.ts index 71c53e2c66b5..88f621da8d79 100644 --- a/core/common/src/SubCategoryOverride.ts +++ b/core/common/src/SubCategoryOverride.ts @@ -37,7 +37,8 @@ export class SubCategoryOverride { /** Returns true if any aspect of the appearance is overridden (i.e., if any member is not undefined). */ public get anyOverridden(): boolean { - return undefined !== this.invisible || undefined !== this.color || undefined !== this.weight || undefined !== this.style || undefined !== this.priority || undefined !== this.material || undefined !== this.transparency; + return undefined !== this.invisible || undefined !== this.color || undefined !== this.weight || undefined !== this.style || + undefined !== this.priority || undefined !== this.material || undefined !== this.transparency; } /** Returns a SubCategoryAppearance overridden to match the properties defined by this SubCategoryOverride. */ @@ -96,8 +97,10 @@ export class SubCategoryOverride { /** Perform equality comparison against another SubCategoryOverride. */ public equals(other: SubCategoryOverride): boolean { - if (this.invisible !== other.invisible || this.weight !== other.weight || this.style !== other.style - || this.priority !== other.priority || this.material !== other.material || this.transparency !== other.transparency) + if ( + this.invisible !== other.invisible || this.weight !== other.weight || this.style !== other.style + || this.priority !== other.priority || this.material !== other.material || this.transparency !== other.transparency + ) return false; if (undefined !== this.color && undefined !== other.color) diff --git a/core/common/src/TerrainSettings.ts b/core/common/src/TerrainSettings.ts index e63f307cc8bb..debd753bdd10 100644 --- a/core/common/src/TerrainSettings.ts +++ b/core/common/src/TerrainSettings.ts @@ -106,12 +106,24 @@ export class TerrainSettings { } /** @deprecated in 4.5.x. Use the overload that takes [[TerrainProps]]. */ - constructor(providerName?: string, exaggeration?: number, applyLighting?: boolean, heightOrigin?: number, heightOriginMode?: TerrainHeightOriginMode); + constructor( + providerName?: string, + exaggeration?: number, + applyLighting?: boolean, + heightOrigin?: number, + heightOriginMode?: TerrainHeightOriginMode, + ); constructor(props?: TerrainProps); /** @internal */ - constructor(providerNameOrProps: string | TerrainProps | undefined, exaggeration?: number, applyLighting?: boolean, heightOrigin?: number, heightOriginMode?: TerrainHeightOriginMode) { + constructor( + providerNameOrProps: string | TerrainProps | undefined, + exaggeration?: number, + applyLighting?: boolean, + heightOrigin?: number, + heightOriginMode?: TerrainHeightOriginMode, + ) { let providerName; let dataSource; let nonLocatable; @@ -149,7 +161,10 @@ export class TerrainSettings { * one of those defined by [[CesiumTerrainAssetId]]. * @note You must ensure your Cesium ION account has access to the specified asset. */ - public static fromCesiumIonAsset(assetId: string = CesiumTerrainAssetId.Default, options?: Omit): TerrainSettings { + public static fromCesiumIonAsset( + assetId: string = CesiumTerrainAssetId.Default, + options?: Omit, + ): TerrainSettings { return TerrainSettings.fromJSON({ ...options, dataSource: assetId, @@ -175,7 +190,8 @@ export class TerrainSettings { } public equals(other: TerrainSettings): boolean { - return this.providerName === other.providerName && this.dataSource === other.dataSource && this.exaggeration === other.exaggeration && this.applyLighting === other.applyLighting + return this.providerName === other.providerName && this.dataSource === other.dataSource && this.exaggeration === other.exaggeration && + this.applyLighting === other.applyLighting && this.heightOrigin === other.heightOrigin && this.heightOriginMode === other.heightOriginMode && this.nonLocatable === other.nonLocatable; } diff --git a/core/common/src/TextureMapping.ts b/core/common/src/TextureMapping.ts index 63a3d787bc96..ec4c43db23a2 100644 --- a/core/common/src/TextureMapping.ts +++ b/core/common/src/TextureMapping.ts @@ -6,9 +6,15 @@ * @module Rendering */ +import { + compareBooleans, + compareBooleansOrUndefined, + compareNumbers, + compareNumbersOrUndefined, + comparePossiblyUndefined, +} from "@itwin/core-bentley"; import { IndexedPolyfaceVisitor, Matrix3d, Point2d, Point3d, PolyfaceVisitor, Transform, Vector3d, XAndY } from "@itwin/core-geometry"; import { RenderTexture } from "./RenderTexture"; -import { compareBooleans, compareBooleansOrUndefined, compareNumbers, compareNumbersOrUndefined, comparePossiblyUndefined } from "@itwin/core-bentley"; /** Defines normal map parameters. * @beta @@ -120,7 +126,8 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare return 0; } - const originDiff = compareNumbers(this.transform.origin.x, other.transform.origin.x) || compareNumbers(this.transform.origin.y, other.transform.origin.y); + const originDiff = compareNumbers(this.transform.origin.x, other.transform.origin.x) || + compareNumbers(this.transform.origin.y, other.transform.origin.y); if (originDiff !== 0) { return originDiff; } @@ -162,7 +169,8 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare } function compareConstantLodParams(lhs: ConstantLodParams, rhs: ConstantLodParams): number { - return compareNumbers(lhs.repetitions, rhs.repetitions) || compareNumbers(lhs.offset.x, rhs.offset.x) || compareNumbers(lhs.offset.y, rhs.offset.y) + return compareNumbers(lhs.repetitions, rhs.repetitions) || compareNumbers(lhs.offset.x, rhs.offset.x) || + compareNumbers(lhs.offset.y, rhs.offset.y) || compareNumbers(lhs.minDistClamp, rhs.minDistClamp) || compareNumbers(lhs.maxDistClamp, rhs.maxDistClamp); } @@ -225,7 +233,8 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare return 0; } - return compareNumbers(this.weight, other.weight) || compareNumbers(this.mode, other.mode) || compareBooleans(this.worldMapping, other.worldMapping) + return compareNumbers(this.weight, other.weight) || compareNumbers(this.mode, other.mode) || + compareBooleans(this.worldMapping, other.worldMapping) || compareBooleans(this.useConstantLod, other.useConstantLod) || this.textureMatrix.compare(other.textureMatrix) || compareConstantLodParams(this.constantLodParams, other.constantLodParams); } @@ -236,7 +245,7 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare */ public computeUVParams(visitor: IndexedPolyfaceVisitor, transformToImodel: Transform): Point2d[] | undefined { switch (this.mode) { - default: // Fall through to parametric in default case + default: // Fall through to parametric in default case case TextureMapping.Mode.Parametric: { return this.computeParametricUVParams(visitor, this.textureMatrix.transform, !this.worldMapping); } @@ -246,7 +255,10 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare return undefined; // Ignore planar mode unless master or sub units for scaleMode and facet is planar - if (!this.worldMapping || (visitor.normalIndex !== undefined && (normalIndices[0] !== normalIndices[1] || normalIndices[0] !== normalIndices[2]))) { + if ( + !this.worldMapping || + (visitor.normalIndex !== undefined && (normalIndices[0] !== normalIndices[1] || normalIndices[0] !== normalIndices[2])) + ) { return this.computeParametricUVParams(visitor, this.textureMatrix.transform, !this.worldMapping); } else { return this.computePlanarUVParams(visitor, this.textureMatrix.transform); @@ -283,7 +295,10 @@ export namespace TextureMapping { // eslint-disable-line no-redeclare let normal: Vector3d; if (visitor.normal === undefined) - normal = points.getPoint3dAtUncheckedPointIndex(0).crossProductToPoints(points.getPoint3dAtUncheckedPointIndex(1), points.getPoint3dAtUncheckedPointIndex(2)); + normal = points.getPoint3dAtUncheckedPointIndex(0).crossProductToPoints( + points.getPoint3dAtUncheckedPointIndex(1), + points.getPoint3dAtUncheckedPointIndex(2), + ); else normal = visitor.normal.getVector3dAtCheckedVectorIndex(0)!; diff --git a/core/common/src/TextureProps.ts b/core/common/src/TextureProps.ts index 78cce8964f54..e35d61641be8 100644 --- a/core/common/src/TextureProps.ts +++ b/core/common/src/TextureProps.ts @@ -7,9 +7,9 @@ */ import { Id64String } from "@itwin/core-bentley"; +import { Base64EncodedString } from "./Base64EncodedString"; import { DefinitionElementProps } from "./ElementProps"; import { ImageSourceFormat } from "./Image"; -import { Base64EncodedString } from "./Base64EncodedString"; /** Properties that define a [Texture]($backend) element. * @public diff --git a/core/common/src/ThematicDisplay.ts b/core/common/src/ThematicDisplay.ts index a2ba7e67b78c..b9230585533f 100644 --- a/core/common/src/ThematicDisplay.ts +++ b/core/common/src/ThematicDisplay.ts @@ -72,7 +72,7 @@ export enum ThematicGradientColorScheme { /** JSON representation of a [[ThematicGradientSettings]]. * @public * @extensions - **/ + */ export interface ThematicGradientSettingsProps { /** See [[ThematicGradientSettings.mode]]. */ mode?: ThematicGradientMode; @@ -116,9 +116,15 @@ export class ThematicGradientSettings { */ public readonly transparencyMode: ThematicGradientTransparencyMode; - public static get margin(): number { return .001; } // A fixed portion of the gradient for out of range values. - public static get contentRange(): number { return 1.0 - 2.0 * ThematicGradientSettings.margin; } - public static get contentMax(): number { return 1.0 - ThematicGradientSettings.margin; } + public static get margin(): number { + return .001; + } // A fixed portion of the gradient for out of range values. + public static get contentRange(): number { + return 1.0 - 2.0 * ThematicGradientSettings.margin; + } + public static get contentMax(): number { + return 1.0 - ThematicGradientSettings.margin; + } public static readonly defaults = new ThematicGradientSettings({}); @@ -140,17 +146,20 @@ export class ThematicGradientSettings { transp = haveOpaque ? TextureTransparency.Mixed : TextureTransparency.Translucent; } - if (transp !== TextureTransparency.Mixed) + if (transp !== TextureTransparency.Mixed) { if (this.marginColor.isOpaque !== (transp === TextureTransparency.Opaque)) transp = TextureTransparency.Mixed; + } return transp; } public equals(other: ThematicGradientSettings): boolean { - if (this.mode !== other.mode || this.stepCount !== other.stepCount || !this.marginColor.equals(other.marginColor) + if ( + this.mode !== other.mode || this.stepCount !== other.stepCount || !this.marginColor.equals(other.marginColor) || this.colorScheme !== other.colorScheme || this.customKeys.length !== other.customKeys.length - || this.colorMix !== other.colorMix || this.transparencyMode !== other.transparencyMode) { + || this.colorMix !== other.colorMix || this.transparencyMode !== other.transparencyMode + ) { return false; } @@ -217,7 +226,9 @@ export class ThematicGradientSettings { if (this.colorScheme === ThematicGradientColorScheme.Custom && this.customKeys.length < 2) { this.customKeys = []; for (const keyValue of ThematicGradientSettings._defaultCustomKeys) - this.customKeys.push(new Gradient.KeyColor({ value: keyValue[0], color: ColorDef.computeTbgrFromComponents(keyValue[1], keyValue[3], keyValue[2]) })); + this.customKeys.push( + new Gradient.KeyColor({ value: keyValue[0], color: ColorDef.computeTbgrFromComponents(keyValue[1], keyValue[3], keyValue[2]) }), + ); } this.colorMix = json.colorMix ?? 0.0; @@ -251,7 +262,9 @@ export class ThematicGradientSettings { props.transparencyMode = this.transparencyMode; if (this.customKeys.length > 0) - props.customKeys = this.customKeys.map((key) => { return { value: key.value, color: key.color.toJSON() }; }); + props.customKeys = this.customKeys.map((key) => { + return { value: key.value, color: key.color.toJSON() }; + }); return props; } @@ -269,7 +282,9 @@ export class ThematicGradientSettings { stepCount: undefined !== changedProps.stepCount ? changedProps.stepCount : this.stepCount, marginColor: undefined !== changedProps.marginColor ? changedProps.marginColor : this.marginColor.tbgr, colorScheme: undefined !== changedProps.colorScheme ? changedProps.colorScheme : this.colorScheme, - customKeys: undefined !== changedProps.customKeys ? changedProps.customKeys : this.customKeys.map((key) => ({ value: key.value, color: key.color.tbgr })), + customKeys: undefined !== changedProps.customKeys + ? changedProps.customKeys + : this.customKeys.map((key) => ({ value: key.value, color: key.color.tbgr })), colorMix: undefined !== changedProps.colorMix ? changedProps.colorMix : this.colorMix, transparencyMode: changedProps.transparencyMode ?? this.transparencyMode, }; diff --git a/core/common/src/TileProps.ts b/core/common/src/TileProps.ts index 126ef39b1144..1712b74a703c 100644 --- a/core/common/src/TileProps.ts +++ b/core/common/src/TileProps.ts @@ -6,9 +6,9 @@ * @module Tile */ -import type { ObjectReference } from "@itwin/object-storage-core/lib/common"; import { GuidString } from "@itwin/core-bentley"; import { Range3dProps, TransformProps } from "@itwin/core-geometry"; +import type { ObjectReference } from "@itwin/object-storage-core/lib/common"; /** @beta */ export interface TileContentIdentifier { diff --git a/core/common/src/Tween.ts b/core/common/src/Tween.ts index 57eb28715a2e..ffb99eb3c290 100644 --- a/core/common/src/Tween.ts +++ b/core/common/src/Tween.ts @@ -33,7 +33,9 @@ export class Tweens { private _tweens: any = {}; private _tweensAddedDuringUpdate: any = {}; private _nextId = 0; - public nextId() { return this._nextId++; } + public nextId() { + return this._nextId++; + } public getAll() { return Object.keys(this._tweens).map((tweenId) => this._tweens[tweenId]); @@ -167,9 +169,15 @@ export class Tween { this._id = _group.nextId(); } - public getId() { return this._id; } - public get isPlaying() { return this._isPlaying; } - public get isPaused() { return this._isPaused; } + public getId() { + return this._id; + } + public get isPlaying() { + return this._isPlaying; + } + public get isPaused() { + return this._isPaused; + } public to(properties: any, duration?: number) { this._valuesEnd = Object.create(properties); @@ -367,8 +375,7 @@ export class Tween { this._object[property] = this._interpolationFunction(end, value); } else { // Parses relative end values with start as base (e.g.: +10, -3) - if (typeof (end) === "string") { - + if (typeof end === "string") { if (end.charAt(0) === "+" || end.charAt(0) === "-") end = start + parseFloat(end); else @@ -376,7 +383,7 @@ export class Tween { } // Protect against non numeric properties. - if (typeof (end) === "number") + if (typeof end === "number") this._object[property] = start + (end - start) * value; } } @@ -391,7 +398,6 @@ export class Tween { // Reassign starting values, restart by making startTime = now for (property in this._valuesStartRepeat) { - if (typeof (this._valuesEnd[property]) === "string") { this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property]); } @@ -418,9 +424,7 @@ export class Tween { this._onRepeatCallback(this._object); return true; - } else { - if (this._onCompleteCallback !== undefined) this._onCompleteCallback(this._object); @@ -431,7 +435,6 @@ export class Tween { } return false; } - } return true; } @@ -460,7 +463,7 @@ export const Easing = { if ((k *= 2) < 1) { return 0.5 * k * k; } - return - 0.5 * (--k * (k - 2) - 1); + return -0.5 * (--k * (k - 2) - 1); }, }, @@ -496,7 +499,7 @@ export const Easing = { return 0.5 * k * k * k * k; } - return - 0.5 * ((k -= 2) * k * k * k - 2); + return -0.5 * ((k -= 2) * k * k * k - 2); }, }, @@ -538,7 +541,7 @@ export const Easing = { }, Out: (k: number) => { - return k === 1 ? 1 : 1 - Math.pow(2, - 10 * k); + return k === 1 ? 1 : 1 - Math.pow(2, -10 * k); }, InOut: (k: number) => { @@ -551,7 +554,7 @@ export const Easing = { if ((k *= 2) < 1) return 0.5 * Math.pow(1024, k - 1); - return 0.5 * (- Math.pow(2, - 10 * (k - 1)) + 2); + return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2); }, }, @@ -566,7 +569,7 @@ export const Easing = { InOut: (k: number) => { if ((k *= 2) < 1) - return - 0.5 * (Math.sqrt(1 - k * k) - 1); + return -0.5 * (Math.sqrt(1 - k * k) - 1); return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1); }, @@ -638,10 +641,10 @@ export const Easing = { if (k < (1 / 2.75)) return 7.5625 * k * k; if (k < (2 / 2.75)) - return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75; + return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75; if (k < (2.5 / 2.75)) - return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375; - return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375; + return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375; + return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375; }, InOut: (k: number) => { @@ -657,7 +660,6 @@ export const Easing = { * @public */ export const Interpolation = { - Linear: (v: any, k: number) => { const m = v.length - 1; const f = m * k; @@ -731,7 +733,6 @@ export const Interpolation = { a[n] = s; return s; }; - })(), CatmullRom: (p0: number, p1: number, p2: number, p3: number, t: number) => { @@ -739,7 +740,7 @@ export const Interpolation = { const v1 = (p3 - p1) * 0.5; const t2 = t * t; const t3 = t * t2; - return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (- 3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; + return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; }, }, }; diff --git a/core/common/src/ViewDetails.ts b/core/common/src/ViewDetails.ts index 7b456df50163..46601e06bd79 100644 --- a/core/common/src/ViewDetails.ts +++ b/core/common/src/ViewDetails.ts @@ -137,7 +137,7 @@ export class ViewDetails { public get clipVector(): ClipVector | undefined { if (undefined === this._clipVector) { const clip = this._json.clip; - this._clipVector = (undefined !== clip ? ClipVector.fromJSON(clip) : ClipVector.createEmpty()); + this._clipVector = undefined !== clip ? ClipVector.fromJSON(clip) : ClipVector.createEmpty(); } return this._clipVector.isValid ? this._clipVector : undefined; diff --git a/core/common/src/ViewProps.ts b/core/common/src/ViewProps.ts index 91d5ad2df17d..213fdf0fb17d 100644 --- a/core/common/src/ViewProps.ts +++ b/core/common/src/ViewProps.ts @@ -13,10 +13,10 @@ import { DisplayStyleProps, DisplayStyleSettingsProps } from "./DisplayStyleSett import { DefinitionElementProps, DisplayStyleLoadProps, ElementProps, RenderTimelineProps, SheetProps, ViewAttachmentProps } from "./ElementProps"; import { EntityQueryParams } from "./EntityProps"; import { ModelProps } from "./ModelProps"; +import { RenderSchedule } from "./RenderSchedule"; import { SubCategoryAppearance } from "./SubCategoryAppearance"; -import { ViewDetails3dProps, ViewDetailsProps } from "./ViewDetails"; import { ThumbnailProps } from "./Thumbnail"; -import { RenderSchedule } from "./RenderSchedule"; +import { ViewDetails3dProps, ViewDetailsProps } from "./ViewDetails"; /** The id of either an element or an entry in a ViewStore. * @public @@ -249,7 +249,6 @@ export interface AuxCoordSystem3dProps extends AuxCoordSystemProps { * @beta */ export namespace ViewStoreRpc { - /** * Version of the Rpc interface. If any methods or interfaces of this API change, this number should * be incremented according to the rules of semantic versioning. See .\rpc\README-RpcInterfaceVersioning.md for more information. @@ -330,7 +329,7 @@ export namespace ViewStoreRpc { where?: string; /** List of Model or Category ids to add to the query results. * @note This is only valid if there is a `where` clause. Otherwise all instances of `from` will be returned so there is no value in adding ids. - */ + */ adds?: Id64Array | CompressedId64Set; /** List of Model or Category Ids to remove from the query results. */ removes?: Id64Array | CompressedId64Set; diff --git a/core/common/src/annotation/TextBlock.ts b/core/common/src/annotation/TextBlock.ts index 334d97d98088..1b5a2cda6308 100644 --- a/core/common/src/annotation/TextBlock.ts +++ b/core/common/src/annotation/TextBlock.ts @@ -92,7 +92,7 @@ export abstract class TextBlockComponent { /** Reset any [[styleOverrides]] applied to this component's [[TextStyle]]. */ public clearStyleOverrides(): void { - this.styleOverrides = { }; + this.styleOverrides = {}; } /** Apply the [[TextStyle]] specified by `styleName` to this component, optionally preserving [[styleOverrides]] and/or preventing propagation to sub-components. */ @@ -164,9 +164,12 @@ export namespace Run { // eslint-disable-line @typescript-eslint/no-redeclare */ export function fromJSON(props: RunProps): Run { switch (props.type) { - case "text": return TextRun.create(props); - case "fraction": return FractionRun.create(props); - case "linebreak": return LineBreakRun.create(props); + case "text": + return TextRun.create(props); + case "fraction": + return FractionRun.create(props); + case "linebreak": + return LineBreakRun.create(props); } } } diff --git a/core/common/src/annotation/TextBlockLayoutResult.ts b/core/common/src/annotation/TextBlockLayoutResult.ts index 3e1305a1c054..fcd3e8a7db08 100644 --- a/core/common/src/annotation/TextBlockLayoutResult.ts +++ b/core/common/src/annotation/TextBlockLayoutResult.ts @@ -23,7 +23,7 @@ export interface RunLayoutResult { /** * The number of characters from the source [[Run]] that have already appeared in the layout. * @note A single source [[TextRun]] can be split into multiple lines to respect the [[TextBlock.width]]. - */ + */ characterOffset: number; /** The number of characters in the RunLayoutResult. */ characterCount: number; diff --git a/core/common/src/annotation/TextStyle.ts b/core/common/src/annotation/TextStyle.ts index 47237c92cc5d..2aedd15f289a 100644 --- a/core/common/src/annotation/TextStyle.ts +++ b/core/common/src/annotation/TextStyle.ts @@ -161,7 +161,7 @@ export class TextStyleSettings { }; /** Settings initialized to all default values. */ - public static defaults: TextStyleSettings = new TextStyleSettings({ }); + public static defaults: TextStyleSettings = new TextStyleSettings({}); private constructor(props: TextStyleSettingsProps, defaults?: Required) { if (!defaults) { @@ -254,4 +254,3 @@ export class TextStyle { return this.name === other.name && this.settings.equals(other.settings); } } - diff --git a/core/common/src/geometry/AdditionalTransform.ts b/core/common/src/geometry/AdditionalTransform.ts index 629b32440a5d..b1eea3ede256 100644 --- a/core/common/src/geometry/AdditionalTransform.ts +++ b/core/common/src/geometry/AdditionalTransform.ts @@ -72,7 +72,13 @@ export class Helmert2DWithZOffset implements Helmert2DWithZOffsetProps { /** Creates a JSON from the Helmert Transform definition * @public */ public toJSON(): Helmert2DWithZOffsetProps { - return { translationX: this.translationX, translationY: this.translationY, translationZ: this.translationZ, rotDeg: this.rotDeg, scale: this.scale }; + return { + translationX: this.translationX, + translationY: this.translationY, + translationZ: this.translationZ, + rotDeg: this.rotDeg, + scale: this.scale, + }; } /** Compares two Helmert2DWithZOffset objects applying a minuscule tolerance. @@ -100,9 +106,8 @@ export interface AdditionalTransformProps { * geographic CRS. The transformation is applied after the latitude/longitude have been projected thus the process * is applied to the result Cartesian coordinates of the projection process. * @public -*/ + */ export class AdditionalTransform implements AdditionalTransformProps { - /** The properties of a 2D Helmert transform with Z offset if one is defined. */ public readonly helmert2DWithZOffset?: Helmert2DWithZOffset; @@ -135,4 +140,3 @@ export class AdditionalTransform implements AdditionalTransformProps { return true; } } - diff --git a/core/common/src/geometry/AreaPattern.ts b/core/common/src/geometry/AreaPattern.ts index 70487f017791..bb5b9c59ee67 100644 --- a/core/common/src/geometry/AreaPattern.ts +++ b/core/common/src/geometry/AreaPattern.ts @@ -8,7 +8,17 @@ import { Id64, Id64String } from "@itwin/core-bentley"; import { - Angle, AngleProps, Geometry, Matrix3d, Point2d, Point3d, Transform, XYProps, XYZProps, YawPitchRollAngles, YawPitchRollProps, + Angle, + AngleProps, + Geometry, + Matrix3d, + Point2d, + Point3d, + Transform, + XYProps, + XYZProps, + YawPitchRollAngles, + YawPitchRollProps, } from "@itwin/core-geometry"; import { ColorDef, ColorDefProps } from "../ColorDef"; @@ -130,14 +140,16 @@ export namespace AreaPattern { public equals(other: Params): boolean { if (this === other) - return true; // Same pointer + return true; // Same pointer - if (this.scale !== other.scale || + if ( + this.scale !== other.scale || this.space1 !== other.space1 || this.space2 !== other.space2 || this.weight !== other.weight || this.invisibleBoundary !== other.invisibleBoundary || - this.snappable !== other.snappable) + this.snappable !== other.snappable + ) return false; if ((this.color === undefined) !== (other.color === undefined)) diff --git a/core/common/src/geometry/BoundingSphere.ts b/core/common/src/geometry/BoundingSphere.ts index e5260722cee1..292fada55b9f 100644 --- a/core/common/src/geometry/BoundingSphere.ts +++ b/core/common/src/geometry/BoundingSphere.ts @@ -39,7 +39,8 @@ export class BoundingSphere { public transformBy(transform: Transform, result?: BoundingSphere): BoundingSphere { result = result ?? new BoundingSphere(); transform.multiplyPoint3d(this.center, result.center); - result.radius = this.radius * Math.max(transform.matrix.columnXMagnitude(), Math.max(transform.matrix.columnYMagnitude(), (transform.matrix.columnZMagnitude()))); + result.radius = this.radius * + Math.max(transform.matrix.columnXMagnitude(), Math.max(transform.matrix.columnYMagnitude(), transform.matrix.columnZMagnitude())); return result; } diff --git a/core/common/src/geometry/Cartographic.ts b/core/common/src/geometry/Cartographic.ts index 8473059b3fc7..b24c2a89f21b 100644 --- a/core/common/src/geometry/Cartographic.ts +++ b/core/common/src/geometry/Cartographic.ts @@ -6,15 +6,15 @@ * @module Geometry */ -import { Angle, Constant, Point3d, Range1d, Range2d, Range3d, Transform, Vector3d, XYAndZ, XYZ } from "@itwin/core-geometry"; import { assert } from "@itwin/core-bentley"; +import { Angle, Constant, Point3d, Range1d, Range2d, Range3d, Transform, Vector3d, XYAndZ, XYZ } from "@itwin/core-geometry"; // portions adapted from Cesium.js Copyright 2011 - 2017 Cesium Contributors /** The JSON representation of a Cartographic object. * @public * @extensions - **/ + */ export interface CartographicProps { /** The longitude, specified in radians. */ longitude: number; @@ -33,7 +33,7 @@ export class Cartographic implements CartographicProps { * @param latitude latitude, in radians. * @param height The height, in meters, above the ellipsoid. */ - private constructor(public longitude: number = 0, public latitude: number = 0, public height: number = 0) { } + private constructor(public longitude: number = 0, public latitude: number = 0, public height: number = 0) {} /** Create a Cartographic object with longitude, latitude, and height of zero. */ public static createZero() { @@ -99,7 +99,11 @@ export class Cartographic implements CartographicProps { * @param result The object onto which to store the result. */ public static fromDegrees(args: { longitude: number, latitude: number, height?: number }, result?: Cartographic) { - return Cartographic.fromRadians({ longitude: Angle.degreesToRadians(args.longitude), latitude: Angle.degreesToRadians(args.latitude), height: args.height }, result); + return Cartographic.fromRadians({ + longitude: Angle.degreesToRadians(args.longitude), + latitude: Angle.degreesToRadians(args.latitude), + height: args.height, + }, result); } /** Create a new Cartographic from longitude and latitude in [Angle]($geometry)s. The values in the resulting object will be in radians. @@ -114,7 +118,11 @@ export class Cartographic implements CartographicProps { private static _cartesianToCartographicP = new Point3d(); private static _cartesianToCartographicH = new Vector3d(); private static _wgs84OneOverRadii = new Point3d(1.0 / 6378137.0, 1.0 / 6378137.0, 1.0 / 6356752.3142451793); - private static _wgs84OneOverRadiiSquared = new Point3d(1.0 / (6378137.0 * 6378137.0), 1.0 / (6378137.0 * 6378137.0), 1.0 / (6356752.3142451793 * 6356752.3142451793)); + private static _wgs84OneOverRadiiSquared = new Point3d( + 1.0 / (6378137.0 * 6378137.0), + 1.0 / (6378137.0 * 6378137.0), + 1.0 / (6356752.3142451793 * 6356752.3142451793), + ); private static _wgs84RadiiSquared = new Point3d(6378137.0 * 6378137.0, 6378137.0 * 6378137.0, 6356752.3142451793 * 6356752.3142451793); private static _wgs84CenterToleranceSquared = 0.1; private static _scratchN = new Vector3d(); @@ -215,11 +223,19 @@ export class Cartographic implements CartographicProps { } /** Create a string representing this cartographic in the format '(longitude, latitude, height)'. */ - public toString(): string { return `(${this.longitude}, ${this.latitude}, ${this.height})`; } + public toString(): string { + return `(${this.longitude}, ${this.latitude}, ${this.height})`; + } private static _scaleToGeodeticSurfaceIntersection = new Point3d(); private static _scaleToGeodeticSurfaceGradient = new Point3d(); - private static _scaleToGeodeticSurface(cartesian: Point3d, oneOverRadii: XYAndZ, oneOverRadiiSquared: XYAndZ, centerToleranceSquared: number, result?: Point3d) { + private static _scaleToGeodeticSurface( + cartesian: Point3d, + oneOverRadii: XYAndZ, + oneOverRadiiSquared: XYAndZ, + centerToleranceSquared: number, + result?: Point3d, + ) { const positionX = cartesian.x; const positionY = cartesian.y; const positionZ = cartesian.z; diff --git a/core/common/src/geometry/CoordinateReferenceSystem.ts b/core/common/src/geometry/CoordinateReferenceSystem.ts index b112598066b1..f377baaaf6e2 100644 --- a/core/common/src/geometry/CoordinateReferenceSystem.ts +++ b/core/common/src/geometry/CoordinateReferenceSystem.ts @@ -7,20 +7,20 @@ */ // cspell:ignore NAVD, NGVD, NSRS, Helmert +import { AdditionalTransform, AdditionalTransformProps } from "./AdditionalTransform"; import { GeodeticDatum, GeodeticDatumProps } from "./GeodeticDatum"; import { GeodeticEllipsoid, GeodeticEllipsoidProps } from "./GeodeticEllipsoid"; import { Carto2DDegrees, Carto2DDegreesProps, Projection, ProjectionProps } from "./Projection"; -import { AdditionalTransform, AdditionalTransformProps } from "./AdditionalTransform"; /** This type indicates possible linear and angular units supported. * @public * @extensions -*/ + */ export type UnitType = "Meter" | "InternationalFoot" | "USSurveyFoot" | "Degree" | "Unsupported"; /** The extent in latitude, longitude bounds where a horizontal CRS is applicable * @public * @extensions -*/ + */ export interface HorizontalCRSExtentProps { /** The South West point in latitude and longitude in degrees for the user-defined extent of the CRS */ southWest: Carto2DDegreesProps; @@ -105,7 +105,7 @@ export interface HorizontalCRSProps { datum?: GeodeticDatumProps; /** The identifier of the geodetic ellipsoid as stored in the dictionary or the service database. This property is exclusive * of having datumId and datum properties undefined. - */ + */ ellipsoidId?: string; /** The complete definition of the geodetic datum referred to by datumId. It can also be used if the datum is not stored * in either service or dictionary @@ -171,12 +171,12 @@ export class HorizontalCRS implements HorizontalCRSProps { /** The identifier of the geodetic ellipsoid as stored in the dictionary or the service database. This property is exclusive * of having datumId and datum properties undefined. - */ + */ public readonly ellipsoidId?: string; /** The complete definition of the geodetic ellipsoid referred to by ellipsoidId. It can also be used if the ellipsoid is not stored * in either service or dictionary. This property is exclusive * of having datumId and datum properties undefined. - */ + */ public readonly ellipsoid?: GeodeticEllipsoid; /** The text indicating the unit used. */ public readonly unit?: UnitType; @@ -245,14 +245,16 @@ export class HorizontalCRS implements HorizontalCRSProps { * but number compares are applied a minuscule tolerance. * @public */ public equals(other: HorizontalCRS): boolean { - if (this.id !== other.id || + if ( + this.id !== other.id || this.description !== other.description || this.source !== other.source || this.deprecated !== other.deprecated || this.epsg !== other.epsg || this.datumId !== other.datumId || this.ellipsoidId !== other.ellipsoidId || - this.unit !== other.unit) + this.unit !== other.unit + ) return false; if ((this.datum === undefined) !== (other.datum === undefined)) @@ -300,7 +302,7 @@ export interface VerticalCRSProps { * we expect to support a broader set in the future including, eventually, user defined vertical CRS * which will require additional parameters to be added. * @public -*/ + */ export class VerticalCRS implements VerticalCRSProps { /** Vertical CRS Key name. The only supported values are currently "GEOID", "ELLIPSOID", "NAVD88", "NGVD29" and "LOCAL_ELLIPSOID". * GEOID indicates elevations are to be interpreted relative to the local Geoid of the dataset. It can also be considered to be Mean Sea Level. @@ -311,7 +313,7 @@ export class VerticalCRS implements VerticalCRSProps { * ELLIPSOID indicates that elevations are relative to the surface of the WGS84(or current coincident) ellipsoid. * LOCAL_ELLIPSOID indicates that elevations are relative to the surface of the local ellipsoid used by the horizontal CRS. It can only * be used for datums that are not considered coincident vertically with WGS84. Use of this vertical datum is strongly discouraged. - */ + */ public readonly id: "GEOID" | "ELLIPSOID" | "NGVD29" | "NAVD88" | "LOCAL_ELLIPSOID"; public constructor(data?: VerticalCRSProps) { @@ -380,7 +382,7 @@ export interface GeographicCRSProps { * expressed coordinates relative to the Earth Center. Since there is no horizontal portion independent from * the vertical portion this system cannot be represented by a GeographicCRS and remains a separate concept. * @public -*/ + */ export class GeographicCRS implements GeographicCRSProps { /** The horizontal portion of the geographic coordinate reference system. */ public readonly horizontalCRS?: HorizontalCRS; @@ -446,4 +448,3 @@ export class GeographicCRS implements GeographicCRSProps { return true; } } - diff --git a/core/common/src/geometry/ElementGeometry.ts b/core/common/src/geometry/ElementGeometry.ts index 122e7345c6cc..92a1e075c081 100644 --- a/core/common/src/geometry/ElementGeometry.ts +++ b/core/common/src/geometry/ElementGeometry.ts @@ -5,23 +5,48 @@ /** @packageDocumentation * @module Geometry */ -import { flatbuffers } from "flatbuffers"; import { BentleyStatus, Id64, Id64String } from "@itwin/core-bentley"; -import { Angle, AngleSweep, Arc3d, BentleyGeometryFlatBuffer, CurveCollection, FrameBuilder, GeometryQuery, LineSegment3d, LineString3d, Loop, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point3dArray, PointString3d, Polyface, PolyfaceQuery, Range2d, Range3d, SolidPrimitive, Transform, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; -import { EGFBAccessors } from "./ElementGeometryFB"; +import { + Angle, + AngleSweep, + Arc3d, + BentleyGeometryFlatBuffer, + CurveCollection, + FrameBuilder, + GeometryQuery, + LineSegment3d, + LineString3d, + Loop, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Point3dArray, + PointString3d, + Polyface, + PolyfaceQuery, + Range2d, + Range3d, + SolidPrimitive, + Transform, + Vector3d, + YawPitchRollAngles, +} from "@itwin/core-geometry"; +import { flatbuffers } from "flatbuffers"; +import { TextBlockGeometryProps } from "../annotation/TextBlockGeometryProps"; import { Base64EncodedString } from "../Base64EncodedString"; -import { TextString, TextStringGlyphData, TextStringProps } from "./TextString"; import { ColorDef } from "../ColorDef"; +import { isPlacement2dProps, PlacementProps } from "../ElementProps"; import { BackgroundFill, FillDisplay, GeometryClass, GeometryParams } from "../GeometryParams"; import { Gradient } from "../Gradient"; import { ThematicGradientSettings, ThematicGradientSettingsProps } from "../ThematicDisplay"; import { AreaPattern } from "./AreaPattern"; +import { EGFBAccessors } from "./ElementGeometryFB"; import { BRepEntity } from "./GeometryStream"; import { ImageGraphic, ImageGraphicCorners, ImageGraphicProps } from "./ImageGraphic"; import { LineStyle } from "./LineStyle"; import { ElementAlignedBox3d, Placement2d, Placement3d } from "./Placement"; -import { isPlacement2dProps, PlacementProps } from "../ElementProps"; -import { TextBlockGeometryProps } from "../annotation/TextBlockGeometryProps"; +import { TextString, TextStringGlyphData, TextStringProps } from "./TextString"; /** Specifies the type of an entry in a geometry stream. * @see [[ElementGeometryDataEntry.opcode]]. @@ -310,18 +335,22 @@ export namespace ElementGeometry { public readonly entries: ElementGeometryDataEntry[] = []; /** Current placement transform, converts local coordinate (placement relative) input to world */ - public get localToWorld() { return this._localToWorld; } + public get localToWorld() { + return this._localToWorld; + } /** Current inverse placement transform, converts world coordinate input to local (placement relative) */ - public get worldToLocal() { return this._worldToLocal; } + public get worldToLocal() { + return this._worldToLocal; + } /** Supply optional local to world transform. Used to transform world coordinate input relative to element placement. * For a [[GeometricElement]]'s placement to be meaningful, world coordinate geometry should never be appended to an element with an identity placement. * Can be called with undefined or identity transform to start appending geometry supplied in local coordinates again. */ public setLocalToWorld(localToWorld?: Transform) { - this._localToWorld = (undefined === localToWorld || localToWorld.isIdentity ? undefined : localToWorld.clone()); - this._worldToLocal = (undefined === this._localToWorld ? undefined : this._localToWorld.inverse()); + this._localToWorld = undefined === localToWorld || localToWorld.isIdentity ? undefined : localToWorld.clone(); + this._worldToLocal = undefined === this._localToWorld ? undefined : this._localToWorld.inverse(); } /** Supply local to world transform from a Point3d and optional YawPitchRollAngles. @@ -488,8 +517,16 @@ export namespace ElementGeometry { /** Append a [[GeometryPart]] instance with relative position, orientation, and scale to the [[ElementGeometryDataEntry]] array for creating a [[GeometricElement3d]]. * Not valid when defining a [[GeometryPart]] as nesting of parts is not supported. */ - public appendGeometryPart3d(partId: Id64String, instanceOrigin?: Point3d, instanceRotation?: YawPitchRollAngles, instanceScale?: number): boolean { - const partTransform = Transform.createOriginAndMatrix(instanceOrigin, instanceRotation ? instanceRotation.toMatrix3d() : Matrix3d.createIdentity()); + public appendGeometryPart3d( + partId: Id64String, + instanceOrigin?: Point3d, + instanceRotation?: YawPitchRollAngles, + instanceScale?: number, + ): boolean { + const partTransform = Transform.createOriginAndMatrix( + instanceOrigin, + instanceRotation ? instanceRotation.toMatrix3d() : Matrix3d.createIdentity(), + ); if (undefined !== instanceScale) partTransform.matrix.scaleColumnsInPlace(instanceScale, instanceScale, instanceScale); return this.appendGeometryPart(partId, partTransform); @@ -499,7 +536,12 @@ export namespace ElementGeometry { * Not valid when defining a [[GeometryPart]] as nesting of parts is not supported. */ public appendGeometryPart2d(partId: Id64String, instanceOrigin?: Point2d, instanceRotation?: Angle, instanceScale?: number): boolean { - return this.appendGeometryPart3d(partId, instanceOrigin ? Point3d.createFrom(instanceOrigin) : undefined, instanceRotation ? new YawPitchRollAngles(instanceRotation) : undefined, instanceScale); + return this.appendGeometryPart3d( + partId, + instanceOrigin ? Point3d.createFrom(instanceOrigin) : undefined, + instanceRotation ? new YawPitchRollAngles(instanceRotation) : undefined, + instanceScale, + ); } } @@ -528,8 +570,12 @@ export namespace ElementGeometry { this._applyLocalToWorld = applyLocalToWorld ? !localToWorld.isIdentity : false; } - public get value() { return this._value!; } - public set value(value: ElementGeometryDataEntry) { this._value = value; } + public get value() { + return this._value!; + } + public set value(value: ElementGeometryDataEntry) { + this._value = value; + } public get outputTransform(): Transform | undefined { return this._applyLocalToWorld ? this.localToWorld : undefined; @@ -597,7 +643,7 @@ export namespace ElementGeometry { /** Construct a new Iterator given a [[ElementGeometryInfo]] from either a [[GeometricElement3d]], [[GeometricElement2d]], or [[GeometryPart]]. * Supply the optional [[GeometryParams]] and localToWorld transform to iterate a [[GeometryPart]] in the context of a [[GeometricElement]] reference. - */ + */ public constructor(info: ElementGeometryInfo, categoryOrGeometryParams?: Id64String | GeometryParams, localToWorld?: Transform) { this.entryArray = info.entryArray; this.viewIndependent = info.viewIndependent; @@ -623,7 +669,7 @@ export namespace ElementGeometry { if (undefined === orgAng.angles) orgAng.angles = YawPitchRollAngles.createDegrees(0, 0, 0); - let bbox = (undefined !== info.bbox ? ElementGeometry.toElementAlignedBox3d(info.bbox) : undefined); + let bbox = undefined !== info.bbox ? ElementGeometry.toElementAlignedBox3d(info.bbox) : undefined; if (undefined === bbox) bbox = Range3d.createNull(); @@ -648,7 +694,7 @@ export namespace ElementGeometry { while (this._index < this.entryArray.length) { const value = this.entryArray[this._index++]; if (ElementGeometry.isAppearanceEntry(value)) { - const localToWorld = (this._applyLocalToWorld ? this._localToWorld : undefined); + const localToWorld = this._applyLocalToWorld ? this._localToWorld : undefined; ElementGeometry.updateGeometryParams(value, this.entry.geomParams, localToWorld); } else if (ElementGeometryOpcode.SubGraphicRange === value.opcode) { // NOTE: localRange remains valid until the next sub-range entry is encountered... @@ -811,7 +857,7 @@ export namespace ElementGeometry { return false; if ("polyface" !== geom.geometryCategory) return false; - const polyface = (geom as Polyface); + const polyface = geom as Polyface; switch (polyface.expectedClosure) { case 0: return !PolyfaceQuery.isPolyfaceClosedByEdgePairing(polyface); @@ -855,7 +901,7 @@ export namespace ElementGeometry { return false; if ("polyface" !== geom.geometryCategory) return false; - const polyface = (geom as Polyface); + const polyface = geom as Polyface; switch (polyface.expectedClosure) { case 0: return PolyfaceQuery.isPolyfaceClosedByEdgePairing(polyface); @@ -939,7 +985,7 @@ export namespace ElementGeometry { return undefined; if ("polyface" !== geom.geometryCategory) return undefined; - const polyface = (geom as Polyface); + const polyface = geom as Polyface; switch (polyface.expectedClosure) { case 0: return PolyfaceQuery.isPolyfaceClosedByEdgePairing(polyface) ? BRepEntity.Type.Solid : BRepEntity.Type.Sheet; @@ -1119,7 +1165,19 @@ export namespace ElementGeometry { const transform = ppfb.transform(); if (null !== transform) { props.origin = Point3d.create(transform.form3d03(), transform.form3d13(), transform.form3d23()); - props.rotation = YawPitchRollAngles.createFromMatrix3d(Matrix3d.createRowValues(transform.form3d00(), transform.form3d01(), transform.form3d02(), transform.form3d10(), transform.form3d11(), transform.form3d12(), transform.form3d20(), transform.form3d21(), transform.form3d22())); + props.rotation = YawPitchRollAngles.createFromMatrix3d( + Matrix3d.createRowValues( + transform.form3d00(), + transform.form3d01(), + transform.form3d02(), + transform.form3d10(), + transform.form3d11(), + transform.form3d12(), + transform.form3d20(), + transform.form3d21(), + transform.form3d22(), + ), + ); } if (undefined === localToWorld) @@ -1155,7 +1213,11 @@ export namespace ElementGeometry { } /** Create entry from a [[TextString]] */ - export function fromTextString(text: TextStringProps, worldToLocal?: Transform, glyphs?: TextStringGlyphData): ElementGeometryDataEntry | undefined { + export function fromTextString( + text: TextStringProps, + worldToLocal?: Transform, + glyphs?: TextStringGlyphData, + ): ElementGeometryDataEntry | undefined { if (undefined !== worldToLocal) { const localText = new TextString(text); if (!localText.transformInPlace(worldToLocal)) @@ -1167,7 +1229,17 @@ export namespace ElementGeometry { const builder = EGFBAccessors.TextString; const textOffset = fbb.createString(text.text); - const styleOffset = EGFBAccessors.TextStringStyle.createTextStringStyle(fbb, 1, 0, text.font, undefined === text.bold ? false : text.bold, undefined === text.italic ? false : text.italic, undefined === text.underline ? false : text.underline, text.height, undefined === text.widthFactor ? 1.0 : text.widthFactor); + const styleOffset = EGFBAccessors.TextStringStyle.createTextStringStyle( + fbb, + 1, + 0, + text.font, + undefined === text.bold ? false : text.bold, + undefined === text.italic ? false : text.italic, + undefined === text.underline ? false : text.underline, + text.height, + undefined === text.widthFactor ? 1.0 : text.widthFactor, + ); const fbbGlyphs = (() => { if (!glyphs || glyphs.range.isNull) return undefined; @@ -1193,12 +1265,35 @@ export namespace ElementGeometry { const angles = YawPitchRollAngles.fromJSON(text.rotation); const matrix = angles.toMatrix3d(); const coffs = matrix.coffs; - const transformOffset = EGFBAccessors.TextStringTransform.createTextStringTransform(fbb, coffs[0], coffs[1], coffs[2], origin.x, coffs[3], coffs[4], coffs[5], origin.y, coffs[6], coffs[7], coffs[8], origin.z); + const transformOffset = EGFBAccessors.TextStringTransform.createTextStringTransform( + fbb, + coffs[0], + coffs[1], + coffs[2], + origin.x, + coffs[3], + coffs[4], + coffs[5], + origin.y, + coffs[6], + coffs[7], + coffs[8], + origin.z, + ); builder.addTransform(fbb, transformOffset); } if (fbbGlyphs) { - builder.addRange(fbb, EGFBAccessors.TextStringRange.createTextStringRange(fbb, fbbGlyphs.range.low.x, fbbGlyphs.range.low.y, fbbGlyphs.range.high.x, fbbGlyphs.range.high.y)); + builder.addRange( + fbb, + EGFBAccessors.TextStringRange.createTextStringRange( + fbb, + fbbGlyphs.range.low.x, + fbbGlyphs.range.low.y, + fbbGlyphs.range.high.x, + fbbGlyphs.range.high.y, + ), + ); builder.addGlyphIds(fbb, fbbGlyphs.glyphIdsOffset); builder.addGlyphOrigins(fbb, fbbGlyphs.glyphOriginsOffset); } @@ -1220,7 +1315,7 @@ export namespace ElementGeometry { const textureLong = ppfb.textureId(); const textureId = Id64.fromUint32Pair(textureLong.low, textureLong.high); - const hasBorder = (1 === ppfb.drawBorder()); + const hasBorder = 1 === ppfb.drawBorder(); const corners = new ImageGraphicCorners(Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()); const corner0 = ppfb.tileCorner0(); @@ -1303,7 +1398,20 @@ export namespace ElementGeometry { let transform; const entityTransform = ppfb.entityTransform(); if (null !== entityTransform) - transform = Transform.createRowValues(entityTransform.x00(), entityTransform.x01(), entityTransform.x02(), entityTransform.tx(), entityTransform.x10(), entityTransform.x11(), entityTransform.x12(), entityTransform.ty(), entityTransform.x20(), entityTransform.x21(), entityTransform.x22(), entityTransform.tz()); + transform = Transform.createRowValues( + entityTransform.x00(), + entityTransform.x01(), + entityTransform.x02(), + entityTransform.tx(), + entityTransform.x10(), + entityTransform.x11(), + entityTransform.x12(), + entityTransform.ty(), + entityTransform.x20(), + entityTransform.x21(), + entityTransform.x22(), + entityTransform.tz(), + ); if (undefined !== localToWorld) { if (undefined !== transform) @@ -1371,7 +1479,16 @@ export namespace ElementGeometry { const symb = brep.faceSymbology[i]; const materialIdPair = Id64.getUint32Pair(symb.materialId ? symb.materialId : Id64.invalid); const matLong = flatbuffers.Long.create(materialIdPair.lower, materialIdPair.upper); - EGFBAccessors.FaceSymbology.createFaceSymbology(fbb, symb.color ? 1 : 0, symb.materialId ? 1 : 0, symb.color ? symb.color : 0, matLong, symb.transparency ? symb.transparency : 0, 0, 0); + EGFBAccessors.FaceSymbology.createFaceSymbology( + fbb, + symb.color ? 1 : 0, + symb.materialId ? 1 : 0, + symb.color ? symb.color : 0, + matLong, + symb.transparency ? symb.transparency : 0, + 0, + 0, + ); } faceSymbOffset = fbb.endVector(); } @@ -1394,7 +1511,21 @@ export namespace ElementGeometry { if (undefined !== brep.transform) { const transform = Transform.fromJSON(brep.transform); - const transformOffset = EGFBAccessors.Transform.createTransform(fbb, transform.matrix.coffs[0], transform.matrix.coffs[1], transform.matrix.coffs[2], transform.origin.x, transform.matrix.coffs[3], transform.matrix.coffs[4], transform.matrix.coffs[5], transform.origin.y, transform.matrix.coffs[6], transform.matrix.coffs[7], transform.matrix.coffs[8], transform.origin.z); + const transformOffset = EGFBAccessors.Transform.createTransform( + fbb, + transform.matrix.coffs[0], + transform.matrix.coffs[1], + transform.matrix.coffs[2], + transform.origin.x, + transform.matrix.coffs[3], + transform.matrix.coffs[4], + transform.matrix.coffs[5], + transform.origin.y, + transform.matrix.coffs[6], + transform.matrix.coffs[7], + transform.matrix.coffs[8], + transform.origin.z, + ); builder.addEntityTransform(fbb, transformOffset); } @@ -1423,7 +1554,7 @@ export namespace ElementGeometry { const builder = EGFBAccessors.BRepData; const entityData = ppfb.entityDataArray(); - const dataOffset = (null !== entityData ? builder.createEntityDataVector(fbb, entityData) : undefined); + const dataOffset = null !== entityData ? builder.createEntityDataVector(fbb, entityData) : undefined; let faceSymbOffset; const faceSymbLen = ppfb.symbologyLength(); @@ -1433,7 +1564,16 @@ export namespace ElementGeometry { const faceSymbFb = ppfb.symbology(i); if (null === faceSymbFb) continue; - EGFBAccessors.FaceSymbology.createFaceSymbology(fbb, faceSymbFb.useColor(), faceSymbFb.useMaterial(), faceSymbFb.color(), faceSymbFb.materialId(), faceSymbFb.transparency(), 0, 0); + EGFBAccessors.FaceSymbology.createFaceSymbology( + fbb, + faceSymbFb.useColor(), + faceSymbFb.useMaterial(), + faceSymbFb.color(), + faceSymbFb.materialId(), + faceSymbFb.transparency(), + 0, + 0, + ); } faceSymbOffset = fbb.endVector(); } @@ -1444,14 +1584,41 @@ export namespace ElementGeometry { let transform; const entityTransform = ppfb.entityTransform(); if (null !== entityTransform) - transform = Transform.createRowValues(entityTransform.x00(), entityTransform.x01(), entityTransform.x02(), entityTransform.tx(), entityTransform.x10(), entityTransform.x11(), entityTransform.x12(), entityTransform.ty(), entityTransform.x20(), entityTransform.x21(), entityTransform.x22(), entityTransform.tz()); + transform = Transform.createRowValues( + entityTransform.x00(), + entityTransform.x01(), + entityTransform.x02(), + entityTransform.tx(), + entityTransform.x10(), + entityTransform.x11(), + entityTransform.x12(), + entityTransform.ty(), + entityTransform.x20(), + entityTransform.x21(), + entityTransform.x22(), + entityTransform.tz(), + ); if (undefined !== transform) transform.multiplyTransformTransform(inputTransform, transform); else transform = inputTransform; - const transformOffset = EGFBAccessors.Transform.createTransform(fbb, transform.matrix.coffs[0], transform.matrix.coffs[1], transform.matrix.coffs[2], transform.origin.x, transform.matrix.coffs[3], transform.matrix.coffs[4], transform.matrix.coffs[5], transform.origin.y, transform.matrix.coffs[6], transform.matrix.coffs[7], transform.matrix.coffs[8], transform.origin.z); + const transformOffset = EGFBAccessors.Transform.createTransform( + fbb, + transform.matrix.coffs[0], + transform.matrix.coffs[1], + transform.matrix.coffs[2], + transform.origin.x, + transform.matrix.coffs[3], + transform.matrix.coffs[4], + transform.matrix.coffs[5], + transform.origin.y, + transform.matrix.coffs[6], + transform.matrix.coffs[7], + transform.matrix.coffs[8], + transform.origin.z, + ); builder.addEntityTransform(fbb, transformOffset); if (undefined !== dataOffset) @@ -1681,10 +1848,10 @@ export namespace ElementGeometry { const tint = ppfb.tint(); const shift = ppfb.shift(); - props.flags = (0 !== flags ? flags : undefined); - props.angle = (0 !== angle ? { radians: angle } : undefined); - props.tint = (0 !== tint ? tint : undefined); - props.shift = (0 !== shift ? shift : undefined); + props.flags = 0 !== flags ? flags : undefined; + props.angle = 0 !== angle ? { radians: angle } : undefined; + props.tint = 0 !== tint ? tint : undefined; + props.shift = 0 !== shift ? shift : undefined; if (Gradient.Mode.Thematic === props.mode) { const thematic = ppfb.thematicSettings(); @@ -1697,10 +1864,10 @@ export namespace ElementGeometry { const marginColor = thematic.marginColor(); const colorScheme = thematic.colorScheme(); - tprops.mode = (0 !== mode ? mode : undefined); - tprops.stepCount = (0 !== stepCount ? stepCount : undefined); - tprops.marginColor = (0 !== marginColor ? marginColor : undefined); - tprops.colorScheme = (0 !== colorScheme ? colorScheme : undefined); + tprops.mode = 0 !== mode ? mode : undefined; + tprops.stepCount = 0 !== stepCount ? stepCount : undefined; + tprops.marginColor = 0 !== marginColor ? marginColor : undefined; + tprops.colorScheme = 0 !== colorScheme ? colorScheme : undefined; props.thematicSettings = tprops; } @@ -1712,7 +1879,7 @@ export namespace ElementGeometry { changed = true; } } else if (0 !== ppfb.backgroundFill()) { - const backgroundFill = (2 === ppfb.backgroundFill() ? BackgroundFill.Outline : BackgroundFill.Solid); + const backgroundFill = 2 === ppfb.backgroundFill() ? BackgroundFill.Outline : BackgroundFill.Solid; if (backgroundFill !== geomParams.backgroundFill) { geomParams.backgroundFill = backgroundFill; changed = true; @@ -1743,10 +1910,16 @@ export namespace ElementGeometry { const rotation = ppfb.rotation(); if (null !== rotation) { const angles = YawPitchRollAngles.createFromMatrix3d(Matrix3d.createRowValues( - rotation.x00(), rotation.x01(), rotation.x02(), - rotation.x10(), rotation.x11(), rotation.x12(), - rotation.x20(), rotation.x21(), rotation.x22()), - ); + rotation.x00(), + rotation.x01(), + rotation.x02(), + rotation.x10(), + rotation.x11(), + rotation.x12(), + rotation.x20(), + rotation.x21(), + rotation.x22(), + )); if (undefined !== angles && !angles.isIdentity()) props.rotation = angles; } @@ -1757,11 +1930,11 @@ export namespace ElementGeometry { const angle2 = ppfb.angle2(); const scale = ppfb.scale(); - props.space1 = (0 !== space1 ? space1 : undefined); - props.space2 = (0 !== space2 ? space2 : undefined); - props.angle1 = (0 !== angle1 ? { radians: angle1 } : undefined); - props.angle2 = (0 !== angle2 ? { radians: angle2 } : undefined); - props.scale = (0 !== scale ? scale : undefined); + props.space1 = 0 !== space1 ? space1 : undefined; + props.space2 = 0 !== space2 ? space2 : undefined; + props.angle1 = 0 !== angle1 ? { radians: angle1 } : undefined; + props.angle2 = 0 !== angle2 ? { radians: angle2 } : undefined; + props.scale = 0 !== scale ? scale : undefined; if (ppfb.useColor()) props.color = ppfb.color(); @@ -1769,11 +1942,11 @@ export namespace ElementGeometry { if (ppfb.useWeight()) props.weight = ppfb.weight(); - props.invisibleBoundary = (1 === ppfb.invisibleBoundary() ? true : undefined); - props.snappable = (1 === ppfb.snappable() ? true : undefined); + props.invisibleBoundary = 1 === ppfb.invisibleBoundary() ? true : undefined; + props.snappable = 1 === ppfb.snappable() ? true : undefined; const symbolId = Id64.fromUint32Pair(ppfb.symbolId().low, ppfb.symbolId().high); - props.symbolId = (Id64.isValid(symbolId) ? symbolId : undefined); + props.symbolId = Id64.isValid(symbolId) ? symbolId : undefined; const nDefLines = ppfb.defLineLength(); if (0 !== nDefLines) { @@ -1787,7 +1960,7 @@ export namespace ElementGeometry { const line: AreaPattern.HatchDefLineProps = {}; const angle = defLine.angle(); - line.angle = (0 !== angle ? { radians: defLine.angle() } : undefined); + line.angle = 0 !== angle ? { radians: defLine.angle() } : undefined; const through = defLine.through(); if (through) { @@ -1948,7 +2121,7 @@ export namespace ElementGeometry { } if (undefined !== lsMods.segmentMode) { - modifiers |= (lsMods.segmentMode ? StyleMod.SegMode : StyleMod.NoSegMode); + modifiers |= lsMods.segmentMode ? StyleMod.SegMode : StyleMod.NoSegMode; } if (lsMods.physicalWidth) { @@ -2008,7 +2181,11 @@ export namespace ElementGeometry { builderThematic.addMarginColor(fbbFill, thematic.marginColor.tbgr); builderThematic.addColorScheme(fbbFill, thematic.colorScheme); - const rangeOffset = EGFBAccessors.DRange1d.createDRange1d(fbbFill, ThematicGradientSettings.contentRange, ThematicGradientSettings.contentMax); + const rangeOffset = EGFBAccessors.DRange1d.createDRange1d( + fbbFill, + ThematicGradientSettings.contentRange, + ThematicGradientSettings.contentMax, + ); builderThematic.addRange(fbbFill, rangeOffset); thematicOffset = builderThematic.endThematicSettings(fbbFill); @@ -2118,10 +2295,18 @@ export namespace ElementGeometry { builderDefLines.addAngle(fbbPat, line.angle.radians); // NOTE: Backend requires through and offset to be present... - const throughOffset = EGFBAccessors.DPoint2d.createDPoint2d(fbbPat, undefined !== line.through ? line.through.x : 0, undefined !== line.through ? line.through.y : 0); + const throughOffset = EGFBAccessors.DPoint2d.createDPoint2d( + fbbPat, + undefined !== line.through ? line.through.x : 0, + undefined !== line.through ? line.through.y : 0, + ); builderDefLines.addThrough(fbbPat, throughOffset); - const offsetOffset = EGFBAccessors.DPoint2d.createDPoint2d(fbbPat, undefined !== line.offset ? line.offset.x : 0, undefined !== line.offset ? line.offset.y : 0); + const offsetOffset = EGFBAccessors.DPoint2d.createDPoint2d( + fbbPat, + undefined !== line.offset ? line.offset.x : 0, + undefined !== line.offset ? line.offset.y : 0, + ); builderDefLines.addOffset(fbbPat, offsetOffset); if (undefined !== dashOffset) @@ -2144,7 +2329,18 @@ export namespace ElementGeometry { if (undefined !== pattern.rotation) { const matrix = pattern.rotation.toMatrix3d(); const coffs = matrix.coffs; - const rotationOffset = EGFBAccessors.RotMatrix.createRotMatrix(fbbPat, coffs[0], coffs[1], coffs[2], coffs[3], coffs[4], coffs[5], coffs[6], coffs[7], coffs[8]); + const rotationOffset = EGFBAccessors.RotMatrix.createRotMatrix( + fbbPat, + coffs[0], + coffs[1], + coffs[2], + coffs[3], + coffs[4], + coffs[5], + coffs[6], + coffs[7], + coffs[8], + ); builderPat.addRotation(fbbPat, rotationOffset); } @@ -2328,9 +2524,18 @@ export namespace ElementGeometry { if (12 !== sourceToWorld.length) return undefined; return Transform.createRowValues( - sourceToWorld[0], sourceToWorld[1], sourceToWorld[2], sourceToWorld[3], - sourceToWorld[4], sourceToWorld[5], sourceToWorld[6], sourceToWorld[7], - sourceToWorld[8], sourceToWorld[9], sourceToWorld[10], sourceToWorld[11], + sourceToWorld[0], + sourceToWorld[1], + sourceToWorld[2], + sourceToWorld[3], + sourceToWorld[4], + sourceToWorld[5], + sourceToWorld[6], + sourceToWorld[7], + sourceToWorld[8], + sourceToWorld[9], + sourceToWorld[10], + sourceToWorld[11], ); } @@ -2341,4 +2546,3 @@ export namespace ElementGeometry { return Range3d.fromFloat64Array(bbox); } } - diff --git a/core/common/src/geometry/ElementGeometryFB.ts b/core/common/src/geometry/ElementGeometryFB.ts index d1e64f27e578..315d4880a383 100644 --- a/core/common/src/geometry/ElementGeometryFB.ts +++ b/core/common/src/geometry/ElementGeometryFB.ts @@ -26,7 +26,7 @@ export namespace EGFBAccessors { Cylindrical = 3, Spherical = 4, Hemispherical = 5, - Thematic = 6 + Thematic = 6, } /** @@ -35,7 +35,7 @@ export namespace EGFBAccessors { export enum BoundaryType { None = 0, Open = 1, - Closed = 2 + Closed = 2, } /** @@ -45,7 +45,7 @@ export namespace EGFBAccessors { None = 0, ByView = 1, Always = 2, - Blanking = 3 + Blanking = 3, } /** @@ -55,7 +55,7 @@ export namespace EGFBAccessors { Primary = 0, Construction = 1, Dimension = 2, - Pattern = 3 + Pattern = 3, } /** @@ -64,7 +64,7 @@ export namespace EGFBAccessors { export enum BRepType { Solid = 0, Sheet = 1, - Wire = 2 + Wire = 2, } /** @@ -120,7 +120,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** @@ -167,7 +166,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** @@ -223,7 +221,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** @@ -320,7 +317,18 @@ export namespace EGFBAccessors { * @param number x22 * @returns flatbuffers.Offset */ - static createRotMatrix(builder: flatbuffers.Builder, x00: number, x01: number, x02: number, x10: number, x11: number, x12: number, x20: number, x21: number, x22: number): flatbuffers.Offset { + static createRotMatrix( + builder: flatbuffers.Builder, + x00: number, + x01: number, + x02: number, + x10: number, + x11: number, + x12: number, + x20: number, + x21: number, + x22: number, + ): flatbuffers.Offset { builder.prep(8, 72); builder.writeFloat64(x22); builder.writeFloat64(x21); @@ -333,7 +341,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x00); return builder.offset(); } - } /** @@ -455,7 +462,21 @@ export namespace EGFBAccessors { * @param number tz * @returns flatbuffers.Offset */ - static createTransform(builder: flatbuffers.Builder, x00: number, x01: number, x02: number, tx: number, x10: number, x11: number, x12: number, ty: number, x20: number, x21: number, x22: number, tz: number): flatbuffers.Offset { + static createTransform( + builder: flatbuffers.Builder, + x00: number, + x01: number, + x02: number, + tx: number, + x10: number, + x11: number, + x12: number, + ty: number, + x20: number, + x21: number, + x22: number, + tz: number, + ): flatbuffers.Offset { builder.prep(8, 96); builder.writeFloat64(tz); builder.writeFloat64(x22); @@ -471,7 +492,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x00); return builder.offset(); } - } /** @@ -544,7 +564,15 @@ export namespace EGFBAccessors { * @param number ty * @returns flatbuffers.Offset */ - static createTrans2x3(builder: flatbuffers.Builder, x00: number, x01: number, tx: number, y00: number, y01: number, ty: number): flatbuffers.Offset { + static createTrans2x3( + builder: flatbuffers.Builder, + x00: number, + x01: number, + tx: number, + y00: number, + y01: number, + ty: number, + ): flatbuffers.Offset { builder.prep(8, 48); builder.writeFloat64(ty); builder.writeFloat64(y01); @@ -554,7 +582,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x00); return builder.offset(); } - } /** @@ -629,7 +656,16 @@ export namespace EGFBAccessors { * @param number uv_y * @returns flatbuffers.Offset */ - static createFaceSymbology(builder: flatbuffers.Builder, useColor: number, useMaterial: number, color: number, materialId: flatbuffers.Long, transparency: number, uv_x: number, uv_y: number): flatbuffers.Offset { + static createFaceSymbology( + builder: flatbuffers.Builder, + useColor: number, + useMaterial: number, + color: number, + materialId: flatbuffers.Long, + transparency: number, + uv_x: number, + uv_y: number, + ): flatbuffers.Offset { builder.prep(8, 40); builder.prep(8, 16); builder.writeFloat64(uv_y); @@ -642,7 +678,6 @@ export namespace EGFBAccessors { builder.writeInt8(useColor); return builder.offset(); } - } /** @@ -689,7 +724,6 @@ export namespace EGFBAccessors { builder.writeInt32(faceIndex); return builder.offset(); } - } /** @@ -736,7 +770,6 @@ export namespace EGFBAccessors { builder.writeFloat64(low); return builder.offset(); } - } /** @@ -1113,7 +1146,15 @@ export namespace EGFBAccessors { return offset; } - static createArcPrimitive(builder: flatbuffers.Builder, centerOffset: flatbuffers.Offset, vector0Offset: flatbuffers.Offset, vector90Offset: flatbuffers.Offset, start: number, sweep: number, boundary: BoundaryType): flatbuffers.Offset { + static createArcPrimitive( + builder: flatbuffers.Builder, + centerOffset: flatbuffers.Offset, + vector0Offset: flatbuffers.Offset, + vector90Offset: flatbuffers.Offset, + start: number, + sweep: number, + boundary: BoundaryType, + ): flatbuffers.Offset { ArcPrimitive.startArcPrimitive(builder); ArcPrimitive.addCenter(builder, centerOffset); ArcPrimitive.addVector0(builder, vector0Offset); @@ -1201,7 +1242,13 @@ export namespace EGFBAccessors { */ entityDataArray(): Uint8Array | null { var offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint8Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1333,7 +1380,14 @@ export namespace EGFBAccessors { return offset; } - static createBRepData(builder: flatbuffers.Builder, entityTransformOffset: flatbuffers.Offset, brepType: BRepType, entityDataOffset: flatbuffers.Offset, symbologyOffset: flatbuffers.Offset, symbologyIndexOffset: flatbuffers.Offset): flatbuffers.Offset { + static createBRepData( + builder: flatbuffers.Builder, + entityTransformOffset: flatbuffers.Offset, + brepType: BRepType, + entityDataOffset: flatbuffers.Offset, + symbologyOffset: flatbuffers.Offset, + symbologyIndexOffset: flatbuffers.Offset, + ): flatbuffers.Offset { BRepData.startBRepData(builder); BRepData.addEntityTransform(builder, entityTransformOffset); BRepData.addBrepType(builder, brepType); @@ -1479,7 +1533,13 @@ export namespace EGFBAccessors { */ byteDataArray(): Uint8Array | null { var offset = this.bb!.__offset(this.bb_pos, 22); - return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint8Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1615,7 +1675,20 @@ export namespace EGFBAccessors { return offset; } - static createImage(builder: flatbuffers.Builder, drawBorder: number, useFillTint: number, tileCorner0Offset: flatbuffers.Offset, tileCorner1Offset: flatbuffers.Offset, tileCorner2Offset: flatbuffers.Offset, tileCorner3Offset: flatbuffers.Offset, width: number, height: number, format: number, byteDataOffset: flatbuffers.Offset, textureId: flatbuffers.Long): flatbuffers.Offset { + static createImage( + builder: flatbuffers.Builder, + drawBorder: number, + useFillTint: number, + tileCorner0Offset: flatbuffers.Offset, + tileCorner1Offset: flatbuffers.Offset, + tileCorner2Offset: flatbuffers.Offset, + tileCorner3Offset: flatbuffers.Offset, + width: number, + height: number, + format: number, + byteDataOffset: flatbuffers.Offset, + textureId: flatbuffers.Long, + ): flatbuffers.Offset { Image.startImage(builder); Image.addDrawBorder(builder, drawBorder); Image.addUseFillTint(builder, useFillTint); @@ -1782,7 +1855,15 @@ export namespace EGFBAccessors { return offset; } - static createGeometryPart(builder: flatbuffers.Builder, geomPartId: flatbuffers.Long, originOffset: flatbuffers.Offset, yaw: number, pitch: number, roll: number, scale: number): flatbuffers.Offset { + static createGeometryPart( + builder: flatbuffers.Builder, + geomPartId: flatbuffers.Long, + originOffset: flatbuffers.Offset, + yaw: number, + pitch: number, + roll: number, + scale: number, + ): flatbuffers.Offset { GeometryPart.startGeometryPart(builder); GeometryPart.addGeomPartId(builder, geomPartId); GeometryPart.addOrigin(builder, originOffset); @@ -2007,7 +2088,19 @@ export namespace EGFBAccessors { return offset; } - static createBasicSymbology(builder: flatbuffers.Builder, subCategoryId: flatbuffers.Long, color: number, weight: number, lineStyleId: flatbuffers.Long, transparency: number, displayPriority: number, geomClass: GeometryClass, useColor: number, useWeight: number, useStyle: number): flatbuffers.Offset { + static createBasicSymbology( + builder: flatbuffers.Builder, + subCategoryId: flatbuffers.Long, + color: number, + weight: number, + lineStyleId: flatbuffers.Long, + transparency: number, + displayPriority: number, + geomClass: GeometryClass, + useColor: number, + useWeight: number, + useStyle: number, + ): flatbuffers.Offset { BasicSymbology.startBasicSymbology(builder); BasicSymbology.addSubCategoryId(builder, subCategoryId); BasicSymbology.addColor(builder, color); @@ -2269,7 +2362,21 @@ export namespace EGFBAccessors { return offset; } - static createLineStyleModifiers(builder: flatbuffers.Builder, modifiers: number, scale: number, dashScale: number, gapScale: number, startWidth: number, endWidth: number, distPhase: number, fractPhase: number, normalOffset: flatbuffers.Offset, yaw: number, pitch: number, roll: number): flatbuffers.Offset { + static createLineStyleModifiers( + builder: flatbuffers.Builder, + modifiers: number, + scale: number, + dashScale: number, + gapScale: number, + startWidth: number, + endWidth: number, + distPhase: number, + fractPhase: number, + normalOffset: flatbuffers.Offset, + yaw: number, + pitch: number, + roll: number, + ): flatbuffers.Offset { LineStyleModifiers.startLineStyleModifiers(builder); LineStyleModifiers.addModifiers(builder, modifiers); LineStyleModifiers.addScale(builder, scale); @@ -2471,7 +2578,17 @@ export namespace EGFBAccessors { return offset; } - static createMaterial(builder: flatbuffers.Builder, useMaterial: number, materialId: flatbuffers.Long, originOffset: flatbuffers.Offset, sizeOffset: flatbuffers.Offset, yaw: number, pitch: number, roll: number, trans2x3Offset: flatbuffers.Offset): flatbuffers.Offset { + static createMaterial( + builder: flatbuffers.Builder, + useMaterial: number, + materialId: flatbuffers.Long, + originOffset: flatbuffers.Offset, + sizeOffset: flatbuffers.Offset, + yaw: number, + pitch: number, + roll: number, + trans2x3Offset: flatbuffers.Offset, + ): flatbuffers.Offset { Material.startMaterial(builder); Material.addUseMaterial(builder, useMaterial); Material.addMaterialId(builder, materialId); @@ -2635,7 +2752,15 @@ export namespace EGFBAccessors { return offset; } - static createThematicSettings(builder: flatbuffers.Builder, stepCount: number, margin: number, marginColor: number, mode: number, colorScheme: number, rangeOffset: flatbuffers.Offset): flatbuffers.Offset { + static createThematicSettings( + builder: flatbuffers.Builder, + stepCount: number, + margin: number, + marginColor: number, + mode: number, + colorScheme: number, + rangeOffset: flatbuffers.Offset, + ): flatbuffers.Offset { ThematicSettings.startThematicSettings(builder); ThematicSettings.addStepCount(builder, stepCount); ThematicSettings.addMargin(builder, margin); @@ -2786,7 +2911,13 @@ export namespace EGFBAccessors { */ colorsArray(): Uint32Array | null { var offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2811,7 +2942,13 @@ export namespace EGFBAccessors { */ valuesArray(): Float64Array | null { var offset = this.bb!.__offset(this.bb_pos, 26); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2985,7 +3122,22 @@ export namespace EGFBAccessors { return offset; } - static createAreaFill(builder: flatbuffers.Builder, fill: FillDisplay, color: number, useColor: number, backgroundFill: number, transparency: number, mode: GradientMode, flags: number, angle: number, tint: number, shift: number, colorsOffset: flatbuffers.Offset, valuesOffset: flatbuffers.Offset, thematicSettingsOffset: flatbuffers.Offset): flatbuffers.Offset { + static createAreaFill( + builder: flatbuffers.Builder, + fill: FillDisplay, + color: number, + useColor: number, + backgroundFill: number, + transparency: number, + mode: GradientMode, + flags: number, + angle: number, + tint: number, + shift: number, + colorsOffset: flatbuffers.Offset, + valuesOffset: flatbuffers.Offset, + thematicSettingsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { AreaFill.startAreaFill(builder); AreaFill.addFill(builder, fill); AreaFill.addColor(builder, color); @@ -3089,7 +3241,13 @@ export namespace EGFBAccessors { */ dashesArray(): Float64Array | null { var offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -3161,7 +3319,13 @@ export namespace EGFBAccessors { return offset; } - static createDwgHatchDefLine(builder: flatbuffers.Builder, angle: number, throughOffset: flatbuffers.Offset, offsetOffset: flatbuffers.Offset, dashesOffset: flatbuffers.Offset): flatbuffers.Offset { + static createDwgHatchDefLine( + builder: flatbuffers.Builder, + angle: number, + throughOffset: flatbuffers.Offset, + offsetOffset: flatbuffers.Offset, + dashesOffset: flatbuffers.Offset, + ): flatbuffers.Offset { DwgHatchDefLine.startDwgHatchDefLine(builder); DwgHatchDefLine.addAngle(builder, angle); DwgHatchDefLine.addThrough(builder, throughOffset); @@ -3329,7 +3493,9 @@ export namespace EGFBAccessors { */ defLine(index: number, obj?: DwgHatchDefLine): DwgHatchDefLine | null { var offset = this.bb!.__offset(this.bb_pos, 32); - return offset ? (obj || new DwgHatchDefLine()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; + return offset + ? (obj || new DwgHatchDefLine()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) + : null; } /** @@ -3497,7 +3663,24 @@ export namespace EGFBAccessors { return offset; } - static createAreaPattern(builder: flatbuffers.Builder, originOffset: flatbuffers.Offset, rotationOffset: flatbuffers.Offset, space1: number, space2: number, angle1: number, angle2: number, scale: number, color: number, weight: number, useColor: number, useWeight: number, invisibleBoundary: number, snappable: number, symbolId: flatbuffers.Long, defLineOffset: flatbuffers.Offset): flatbuffers.Offset { + static createAreaPattern( + builder: flatbuffers.Builder, + originOffset: flatbuffers.Offset, + rotationOffset: flatbuffers.Offset, + space1: number, + space2: number, + angle1: number, + angle2: number, + scale: number, + color: number, + weight: number, + useColor: number, + useWeight: number, + invisibleBoundary: number, + snappable: number, + symbolId: flatbuffers.Long, + defLineOffset: flatbuffers.Offset, + ): flatbuffers.Offset { AreaPattern.startAreaPattern(builder); AreaPattern.addOrigin(builder, originOffset); AreaPattern.addRotation(builder, rotationOffset); @@ -3636,7 +3819,21 @@ export namespace EGFBAccessors { * @param number form3d23 * @returns flatbuffers.Offset */ - static createTextStringTransform(builder: flatbuffers.Builder, form3d00: number, form3d01: number, form3d02: number, form3d03: number, form3d10: number, form3d11: number, form3d12: number, form3d13: number, form3d20: number, form3d21: number, form3d22: number, form3d23: number): flatbuffers.Offset { + static createTextStringTransform( + builder: flatbuffers.Builder, + form3d00: number, + form3d01: number, + form3d02: number, + form3d03: number, + form3d10: number, + form3d11: number, + form3d12: number, + form3d13: number, + form3d20: number, + form3d21: number, + form3d22: number, + form3d23: number, + ): flatbuffers.Offset { builder.prep(8, 96); builder.writeFloat64(form3d23); builder.writeFloat64(form3d22); @@ -3652,7 +3849,6 @@ export namespace EGFBAccessors { builder.writeFloat64(form3d00); return builder.offset(); } - } /** @@ -3717,7 +3913,6 @@ export namespace EGFBAccessors { builder.writeFloat64(lowx); return builder.offset(); } - } /** @@ -3764,7 +3959,6 @@ export namespace EGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** @@ -3948,7 +4142,17 @@ export namespace EGFBAccessors { return offset; } - static createTextStringStyle(builder: flatbuffers.Builder, majorVersion: number, minorVersion: number, fontId: number, isBold: boolean, isItalic: boolean, isUnderlined: boolean, height: number, widthFactor: number): flatbuffers.Offset { + static createTextStringStyle( + builder: flatbuffers.Builder, + majorVersion: number, + minorVersion: number, + fontId: number, + isBold: boolean, + isItalic: boolean, + isUnderlined: boolean, + height: number, + widthFactor: number, + ): flatbuffers.Offset { TextStringStyle.startTextStringStyle(builder); TextStringStyle.addMajorVersion(builder, majorVersion); TextStringStyle.addMinorVersion(builder, minorVersion); @@ -4075,7 +4279,13 @@ export namespace EGFBAccessors { */ glyphIdsArray(): Uint32Array | null { var offset = this.bb!.__offset(this.bb_pos, 16); - return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4205,7 +4415,17 @@ export namespace EGFBAccessors { return offset; } - static createTextString(builder: flatbuffers.Builder, majorVersion: number, minorVersion: number, textOffset: flatbuffers.Offset, styleOffset: flatbuffers.Offset, transformOffset: flatbuffers.Offset, rangeOffset: flatbuffers.Offset, glyphIdsOffset: flatbuffers.Offset, glyphOriginsOffset: flatbuffers.Offset): flatbuffers.Offset { + static createTextString( + builder: flatbuffers.Builder, + majorVersion: number, + minorVersion: number, + textOffset: flatbuffers.Offset, + styleOffset: flatbuffers.Offset, + transformOffset: flatbuffers.Offset, + rangeOffset: flatbuffers.Offset, + glyphIdsOffset: flatbuffers.Offset, + glyphOriginsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { TextString.startTextString(builder); TextString.addMajorVersion(builder, majorVersion); TextString.addMinorVersion(builder, minorVersion); @@ -4218,5 +4438,4 @@ export namespace EGFBAccessors { return TextString.endTextString(builder); } } - } diff --git a/core/common/src/geometry/GeodeticDatum.ts b/core/common/src/geometry/GeodeticDatum.ts index f27e52fc5ac4..8409ea8accb3 100644 --- a/core/common/src/geometry/GeodeticDatum.ts +++ b/core/common/src/geometry/GeodeticDatum.ts @@ -68,12 +68,12 @@ export class XyzRotation implements XyzRotationProps { * @extensions */ export type GeodeticTransformMethod = - "None" | - "Geocentric" | - "PositionalVector" | - "GridFiles" | - "MultipleRegression" | - "Undefined"; + | "None" + | "Geocentric" + | "PositionalVector" + | "GridFiles" + | "MultipleRegression" + | "Undefined"; /** This interface represents a geocentric (three parameters) geodetic transformation. * @public @@ -173,10 +173,12 @@ export class PositionalVectorTransform implements PositionalVectorTransformProps /** Compares two Positional Vector Transforms. It applies a minuscule tolerance to number compares. * @public */ public equals(other: PositionalVectorTransform): boolean { - if (Math.abs(this.delta.x - other.delta.x) > Geometry.smallMetricDistance || + if ( + Math.abs(this.delta.x - other.delta.x) > Geometry.smallMetricDistance || Math.abs(this.delta.y - other.delta.y) > Geometry.smallMetricDistance || Math.abs(this.delta.z - other.delta.z) > Geometry.smallMetricDistance || - Math.abs(this.scalePPM - other.scalePPM) > Geometry.smallFraction) + Math.abs(this.scalePPM - other.scalePPM) > Geometry.smallFraction + ) return false; return this.rotation.equals(other.rotation); @@ -188,16 +190,16 @@ export class PositionalVectorTransform implements PositionalVectorTransformProps * @extensions */ export type GridFileFormat = - "NONE" | - "NTv1" | - "NTv2" | - "NADCON" | - "FRENCH" | - "JAPAN" | - "ATS77" | - "GEOCN" | - "OSTN02" | - "OSTN15"; + | "NONE" + | "NTv1" + | "NTv2" + | "NADCON" + | "FRENCH" + | "JAPAN" + | "ATS77" + | "GEOCN" + | "OSTN02" + | "OSTN15"; /** type to indicate the grid file application direction. * @public @@ -353,17 +355,17 @@ export interface GeodeticTransformProps { /** The complete definition of the source geodetic ellipsoid referred to by ellipsoidId. * The source ellipsoid identifier enables obtaining the shape of the Earth mathematical model * for the purpose of performing the transformation. - */ + */ sourceEllipsoid?: GeodeticEllipsoidProps; /** The complete definition of the target geodetic ellipsoid referred to by ellipsoidId. * The target ellipsoid identifier enables obtaining the shape of the Earth mathematical model - * for the purpose of performing the transformation.*/ + * for the purpose of performing the transformation. */ targetEllipsoid?: GeodeticEllipsoidProps; /** The id of the source datum. */ sourceDatumId?: string; /** The id of the target datum. This id is useful to seach within a geodetic transform path for * a shortcut to another included datum. - */ + */ targetDatumId?: string; /** When method is Geocentric this property contains the geocentric parameters */ geocentric?: GeocentricTransformProps; @@ -386,13 +388,13 @@ export class GeodeticTransform implements GeodeticTransformProps { public readonly sourceEllipsoid?: GeodeticEllipsoid; /** The complete definition of the target geodetic ellipsoid referred to by ellipsoidId. * The target ellipsoid identifier enables obtaining the shape of the Earth mathematical model - * for the purpose of performing the transformation.*/ + * for the purpose of performing the transformation. */ public readonly targetEllipsoid?: GeodeticEllipsoid; /** The id of the source datum. */ public readonly sourceDatumId?: string; /** The id of the target datum. This id is useful to seach within a geodetic transform path for * a shortcut to another included datum. - */ + */ public readonly targetDatumId?: string; /** When method is Geocentric this property contains the geocentric parameters */ public readonly geocentric?: GeocentricTransform; @@ -687,7 +689,7 @@ export class GeodeticDatum implements GeodeticDatumProps { data.id = this.id; data.description = this.description; /* We prefer to use the default undef instead of false value for deprecated value in Json */ - data.deprecated = (this.deprecated === false ? undefined : true); + data.deprecated = this.deprecated === false ? undefined : true; data.source = this.source; data.epsg = this.epsg; data.ellipsoidId = this.ellipsoidId; @@ -709,12 +711,14 @@ export class GeodeticDatum implements GeodeticDatumProps { * It takes into account descriptive properties not only mathematical definition properties. * @public */ public equals(other: GeodeticDatum): boolean { - if (this.id !== other.id || + if ( + this.id !== other.id || this.description !== other.description || this.deprecated !== other.deprecated || this.source !== other.source || this.epsg !== other.epsg || - this.ellipsoidId !== other.ellipsoidId) + this.ellipsoidId !== other.ellipsoidId + ) return false; if ((this.ellipsoid === undefined) !== (other.ellipsoid === undefined)) @@ -749,4 +753,3 @@ export class GeodeticDatum implements GeodeticDatumProps { return true; } } - diff --git a/core/common/src/geometry/GeodeticEllipsoid.ts b/core/common/src/geometry/GeodeticEllipsoid.ts index e0b7a82fb4b1..6996b6cbfc91 100644 --- a/core/common/src/geometry/GeodeticEllipsoid.ts +++ b/core/common/src/geometry/GeodeticEllipsoid.ts @@ -92,7 +92,7 @@ export class GeodeticEllipsoid implements GeodeticEllipsoidProps { data.id = this.id; data.description = this.description; /* We prefer to use the default undef instead of false value for deprecated in Json */ - data.deprecated = (this.deprecated === false ? undefined : true); + data.deprecated = this.deprecated === false ? undefined : true; data.source = this.source; data.epsg = this.epsg; data.equatorialRadius = this.equatorialRadius; @@ -114,4 +114,3 @@ export class GeodeticEllipsoid implements GeodeticEllipsoidProps { Geometry.isAlmostEqualOptional(this.polarRadius, other.polarRadius, Geometry.smallMetricDistance); } } - diff --git a/core/common/src/geometry/GeometryStream.ts b/core/common/src/geometry/GeometryStream.ts index 23a46fb87bae..f230900eefd4 100644 --- a/core/common/src/geometry/GeometryStream.ts +++ b/core/common/src/geometry/GeometryStream.ts @@ -8,9 +8,25 @@ import { Id64, Id64String, IModelStatus } from "@itwin/core-bentley"; import { - Angle, AnyGeometryQuery, GeometryQuery, IModelJson as GeomJson, LineSegment3d, LowAndHighXYZ, Matrix3d, Point2d, Point3d, Range3d, Transform, TransformProps, - Vector3d, XYZProps, YawPitchRollAngles, YawPitchRollProps, + Angle, + AnyGeometryQuery, + GeometryQuery, + IModelJson as GeomJson, + LineSegment3d, + LowAndHighXYZ, + Matrix3d, + Point2d, + Point3d, + Range3d, + Transform, + TransformProps, + Vector3d, + XYZProps, + YawPitchRollAngles, + YawPitchRollProps, } from "@itwin/core-geometry"; +import { TextBlockGeometryProps } from "../annotation/TextBlockGeometryProps"; +import { Base64EncodedString } from "../Base64EncodedString"; import { ColorDef, ColorDefProps } from "../ColorDef"; import { GeometricElement2dProps, GeometricElement3dProps, GeometryPartProps, isPlacement2dProps, PlacementProps } from "../ElementProps"; import { BackgroundFill, FillDisplay, GeometryClass, GeometryParams } from "../GeometryParams"; @@ -19,10 +35,8 @@ import { IModelError } from "../IModelError"; import { AreaPattern } from "./AreaPattern"; import { ImageGraphic, ImageGraphicProps } from "./ImageGraphic"; import { LineStyle } from "./LineStyle"; -import { TextString, TextStringProps } from "./TextString"; -import { Base64EncodedString } from "../Base64EncodedString"; import { Placement2d, Placement3d } from "./Placement"; -import { TextBlockGeometryProps } from "../annotation/TextBlockGeometryProps"; +import { TextString, TextStringProps } from "./TextString"; /** Establish a non-default [[SubCategory]] or to override [[SubCategoryAppearance]] for the geometry that follows. * A GeometryAppearanceProps always signifies a reset to the [[SubCategoryAppearance]] for subsequent [[GeometryStreamProps]] entries for undefined values. @@ -200,7 +214,7 @@ export class GeometryStreamBuilder { * Can be called with undefined or identity transform to start appending geometry supplied in local coordinates again. */ public setLocalToWorld(localToWorld?: Transform) { - this._worldToLocal = (undefined === localToWorld || localToWorld.isIdentity ? undefined : localToWorld.inverse()); + this._worldToLocal = undefined === localToWorld || localToWorld.isIdentity ? undefined : localToWorld.inverse(); } /** Supply local to world transform from a Point3d and optional YawPitchRollAngles. @@ -318,7 +332,12 @@ export class GeometryStreamBuilder { * Not valid when defining a [[GeometryPart]] as nesting of parts is not supported. */ public appendGeometryPart2d(partId: Id64String, instanceOrigin?: Point2d, instanceRotation?: Angle, instanceScale?: number): boolean { - return this.appendGeometryPart3d(partId, instanceOrigin ? Point3d.createFrom(instanceOrigin) : undefined, instanceRotation ? new YawPitchRollAngles(instanceRotation) : undefined, instanceScale); + return this.appendGeometryPart3d( + partId, + instanceOrigin ? Point3d.createFrom(instanceOrigin) : undefined, + instanceRotation ? new YawPitchRollAngles(instanceRotation) : undefined, + instanceScale, + ); } /** Append a [[TextString]] supplied in either local or world coordinates to the [[GeometryStreamProps]] array */ @@ -527,13 +546,25 @@ class IteratorEntry implements GeometryStreamIteratorEntry { this.localToWorld = localToWorld; } - public get primitive() { return this._primitive!; } - public set primitive(primitive: GeometryStreamPrimitive) { this._primitive = primitive; } + public get primitive() { + return this._primitive!; + } + public set primitive(primitive: GeometryStreamPrimitive) { + this._primitive = primitive; + } - public setGeometryQuery(geometry: AnyGeometryQuery) { this._primitive = { type: "geometryQuery", geometry }; } - public setTextString(textString: TextString) { this._primitive = { type: "textString", textString }; } - public setBRep(brep: BRepEntity.DataProps) { this._primitive = { type: "brep", brep }; } - public setImage(image: ImageGraphic) { this._primitive = { type: "image", image }; } + public setGeometryQuery(geometry: AnyGeometryQuery) { + this._primitive = { type: "geometryQuery", geometry }; + } + public setTextString(textString: TextString) { + this._primitive = { type: "textString", textString }; + } + public setBRep(brep: BRepEntity.DataProps) { + this._primitive = { type: "brep", brep }; + } + public setImage(image: ImageGraphic) { + this._primitive = { type: "image", image }; + } public setPartReference(id: Id64String, toLocal?: Transform) { this._primitive = { type: "partReference", @@ -593,7 +624,10 @@ export class GeometryStreamIterator implements IterableIterator(props.bbox)); + return new Placement3d( + Point3d.fromJSON(props.origin), + YawPitchRollAngles.fromJSON(props.angles), + Range3d.fromJSON(props.bbox), + ); } /** Get the 8 corners, in world coordinates, of this placement. */ @@ -84,7 +104,9 @@ export class Placement3d implements Placement3dProps { } /** Determine whether this Placement3d is valid. */ - public get isValid(): boolean { return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; } + public get isValid(): boolean { + return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; + } /** Calculate the axis-aligned bounding box for this placement. */ public calculateRange(): AxisAlignedBox3d { @@ -117,18 +139,24 @@ export class Placement3d implements Placement3dProps { * @public */ export class Placement2d implements Placement2dProps { - public constructor(public origin: Point2d, public angle: Angle, public bbox: ElementAlignedBox2d) { } + public constructor(public origin: Point2d, public angle: Angle, public bbox: ElementAlignedBox2d) {} /** Get the rotation from local coordinates of this placement to world coordinates. */ - public get rotation(): Matrix3d { return Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle)!; } + public get rotation(): Matrix3d { + return Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle)!; + } /** Get the transform from local coordinates of this placement to world coordinates. */ - public get transform(): Transform { return Transform.createOriginAndMatrix(Point3d.createFrom(this.origin), this.rotation); } + public get transform(): Transform { + return Transform.createOriginAndMatrix(Point3d.createFrom(this.origin), this.rotation); + } /** Create a new Placement2d from a Placement2dProps. */ public static fromJSON(json?: Placement2dProps): Placement2d { const props: any = json ? json : {}; return new Placement2d(Point2d.fromJSON(props.origin), Angle.fromJSON(props.angle), Range2d.fromJSON(props.bbox)); } /** determine if this is 3d placement */ - public get is3d(): boolean { return false; } + public get is3d(): boolean { + return false; + } /** Get the 8 corners, in world coordinates, of this placement. */ public getWorldCorners(out?: Frustum): Frustum { @@ -138,7 +166,9 @@ export class Placement2d implements Placement2dProps { } /** Determine whether this Placement2d is valid. */ - public get isValid(): boolean { return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; } + public get isValid(): boolean { + return !this.bbox.isNull && Math.max(this.origin.maxAbs(), this.bbox.maxAbs()) < Constant.circumferenceOfEarth; + } /** Set the contents of this Placement2d from another Placement2d */ public setFrom(other: Placement2d) { @@ -157,7 +187,7 @@ export class Placement2d implements Placement2dProps { // low and high are not allowed to be equal range.ensureMinLengths(); - range.low.z = - 1.0; // is the 2dFrustumDepth, which === 1 meter + range.low.z = -1.0; // is the 2dFrustumDepth, which === 1 meter range.high.z = 1.0; return range; } diff --git a/core/common/src/geometry/Projection.ts b/core/common/src/geometry/Projection.ts index 50a8a8b3a69e..201545b6f8be 100644 --- a/core/common/src/geometry/Projection.ts +++ b/core/common/src/geometry/Projection.ts @@ -17,56 +17,56 @@ import { Geometry } from "@itwin/core-geometry"; * @extensions */ export type ProjectionMethod = - "None" | - "TransverseMercator" | - "SouthOrientedTransverseMercator" | - "TransverseMercatorWisconsin" | - "TransverseMercatorMinnesota" | - "TransverseMercatorAffine" | - "MercatorStandardParallel" | - "Mercator" | - "UniversalTransverseMercator" | - "LambertConformalConicTwoParallels" | - "LambertConformalConicBelgium" | - "LambertConformalConicAffine" | - "LambertConformalConicWisconsin" | - "LambertConformalConicMinnesota" | - "LambertConformalConicMichigan" | - "LambertConformalConicOneParallel" | - "AlbersEqualArea" | - "NewZealandNationalGrid" | - "ObliqueMercator1" | - "ObliqueMercator2" | - "TransverseMercatorOSTN97" | - "TransverseMercatorOSTN02" | - "TransverseMercatorOSTN15" | - "Krovak" | - "KrovakModified" | - "ObliqueCylindricalSwiss" | - "TransverseMercatorDenmarkSystem34" | - "TransverseMercatorDenmarkSystem3499" | - "TransverseMercatorDenmarkSystem3401" | - "Cassini" | - "Sinusoidal" | - "VanDerGrinten" | - "Bonne" | - "Mollweide" | - "EckertIV" | - "EckertVI" | - "GoodeHomolosine" | - "Robinson" | - "PlateCarree" | - "MillerCylindrical" | - "WinkelTripel" | - "AzimuthalEqualArea" | - "ObliqueStereographic" | - "RectifiedSkewOrthomorphicCentered" | - "RectifiedSkewOrthomorphicOrigin" | - "ObliqueCylindricalHungary" | - "Orthographic" | - "AmericanPolyconic" | - "LambertEquidistantAzimuthal" | - "ObliqueMercatorMinnesota"; + | "None" + | "TransverseMercator" + | "SouthOrientedTransverseMercator" + | "TransverseMercatorWisconsin" + | "TransverseMercatorMinnesota" + | "TransverseMercatorAffine" + | "MercatorStandardParallel" + | "Mercator" + | "UniversalTransverseMercator" + | "LambertConformalConicTwoParallels" + | "LambertConformalConicBelgium" + | "LambertConformalConicAffine" + | "LambertConformalConicWisconsin" + | "LambertConformalConicMinnesota" + | "LambertConformalConicMichigan" + | "LambertConformalConicOneParallel" + | "AlbersEqualArea" + | "NewZealandNationalGrid" + | "ObliqueMercator1" + | "ObliqueMercator2" + | "TransverseMercatorOSTN97" + | "TransverseMercatorOSTN02" + | "TransverseMercatorOSTN15" + | "Krovak" + | "KrovakModified" + | "ObliqueCylindricalSwiss" + | "TransverseMercatorDenmarkSystem34" + | "TransverseMercatorDenmarkSystem3499" + | "TransverseMercatorDenmarkSystem3401" + | "Cassini" + | "Sinusoidal" + | "VanDerGrinten" + | "Bonne" + | "Mollweide" + | "EckertIV" + | "EckertVI" + | "GoodeHomolosine" + | "Robinson" + | "PlateCarree" + | "MillerCylindrical" + | "WinkelTripel" + | "AzimuthalEqualArea" + | "ObliqueStereographic" + | "RectifiedSkewOrthomorphicCentered" + | "RectifiedSkewOrthomorphicOrigin" + | "ObliqueCylindricalHungary" + | "Orthographic" + | "AmericanPolyconic" + | "LambertEquidistantAzimuthal" + | "ObliqueMercatorMinnesota"; /** The equations are: * X1 = a1*X + a2*Y + TranslationX @@ -361,16 +361,19 @@ export class Projection implements ProjectionProps { * but a minuscule tolerance is applied to number compares. * @public */ public equals(other: Projection): boolean { - if (this.method !== other.method || + if ( + this.method !== other.method || this.zoneNumber !== other.zoneNumber || this.hemisphere !== other.hemisphere || - this.danishSystem34Region !== other.danishSystem34Region) + this.danishSystem34Region !== other.danishSystem34Region + ) return false; // Note that even though falseEasting, falseNorthing, elevationAboveGeoid and geoidSeparation are expressed // in the units of the projection which can be foot or US survey foot, they are still within the same order // of size that Geometry.smallMetricDistance can be used effectively. - if (!Geometry.isAlmostEqualOptional(this.falseEasting, other.falseEasting, Geometry.smallMetricDistance) || + if ( + !Geometry.isAlmostEqualOptional(this.falseEasting, other.falseEasting, Geometry.smallMetricDistance) || !Geometry.isAlmostEqualOptional(this.falseNorthing, other.falseNorthing, Geometry.smallMetricDistance) || !Geometry.isAlmostEqualOptional(this.centralMeridian, other.centralMeridian, Geometry.smallAngleDegrees) || !Geometry.isAlmostEqualOptional(this.latitudeOfOrigin, other.latitudeOfOrigin, Geometry.smallAngleDegrees) || @@ -387,7 +390,8 @@ export class Projection implements ProjectionProps { !Geometry.isAlmostEqualOptional(this.point1Latitude, other.point1Latitude, Geometry.smallAngleDegrees) || !Geometry.isAlmostEqualOptional(this.point2Longitude, other.point2Longitude, Geometry.smallAngleDegrees) || !Geometry.isAlmostEqualOptional(this.point2Latitude, other.point2Latitude, Geometry.smallAngleDegrees) || - !Geometry.isAlmostEqualOptional(this.azimuth, other.azimuth, Geometry.smallAngleDegrees)) + !Geometry.isAlmostEqualOptional(this.azimuth, other.azimuth, Geometry.smallAngleDegrees) + ) return false; if (this.affine && other.affine) { @@ -419,7 +423,9 @@ export class Carto2DDegrees implements Carto2DDegreesProps { /** Latitude value in degrees. Must be between -90 and +90 included */ private _latitude!: number; /** Returns or sets the latitude in degrees. When setting the provided number must be between or equal from -90 to 90. */ - public get latitude() { return this._latitude; } + public get latitude() { + return this._latitude; + } public set latitude(newLatitude: number) { if ((newLatitude <= 90.0) && (newLatitude >= -90.0)) this._latitude = newLatitude; @@ -454,4 +460,3 @@ export class Carto2DDegrees implements Carto2DDegreesProps { Math.abs(this.longitude - other.longitude) < Geometry.smallAngleDegrees); } } - diff --git a/core/common/src/geometry/TextString.ts b/core/common/src/geometry/TextString.ts index c7fa33e4c4e5..04622a0979a0 100644 --- a/core/common/src/geometry/TextString.ts +++ b/core/common/src/geometry/TextString.ts @@ -69,7 +69,9 @@ export class TextString { public readonly origin: Point3d; /** Rotation relative to element's placement */ public readonly rotation: YawPitchRollAngles; - public get width() { return this.height * (this.widthFactor ? this.widthFactor : 1.0); } + public get width() { + return this.height * (this.widthFactor ? this.widthFactor : 1.0); + } public constructor(props: TextStringProps) { this.text = props.text; @@ -121,7 +123,7 @@ export class TextString { this.origin.setFrom(newOrigin); this.rotation.setFrom(newRotation); this.height = newHeight; - this.widthFactor = (newHeight === newWidth ? undefined : (newWidth / newHeight)); + this.widthFactor = newHeight === newWidth ? undefined : (newWidth / newHeight); return true; } } diff --git a/core/common/src/internal/cross-package.ts b/core/common/src/internal/cross-package.ts index 9c0c68184d81..52803c6660b2 100644 --- a/core/common/src/internal/cross-package.ts +++ b/core/common/src/internal/cross-package.ts @@ -4,4 +4,3 @@ *--------------------------------------------------------------------------------------------*/ export type { DecorationGeometryProps, SnapRequestProps, SnapResponseProps } from "./Snapping"; - diff --git a/core/common/src/ipc/IpcSession.ts b/core/common/src/ipc/IpcSession.ts index 2cc77caf6626..5d1ef6c86c34 100644 --- a/core/common/src/ipc/IpcSession.ts +++ b/core/common/src/ipc/IpcSession.ts @@ -22,7 +22,9 @@ export interface InterceptedRpcRequest { /** @internal */ export abstract class IpcSession { private static _active?: IpcSession; - public static get active(): IpcSession | undefined { return this._active; } + public static get active(): IpcSession | undefined { + return this._active; + } public static start(session: IpcSession) { if (this._active) diff --git a/core/common/src/ipc/IpcSocket.ts b/core/common/src/ipc/IpcSocket.ts index fca79c9b7db2..5284b9e6936b 100644 --- a/core/common/src/ipc/IpcSocket.ts +++ b/core/common/src/ipc/IpcSocket.ts @@ -9,7 +9,7 @@ /** * The prefix for all IpcSocket channels to disambiguate from system channels. * @internal - * */ + */ export const iTwinChannel = (channel: string) => `itwin.${channel}`; /** @@ -30,14 +30,17 @@ export type RemoveFunction = () => void; * frontend will re-throw a [BackendError]$(frontend) with the `errorNumber` and `message` values. Otherwise the `result` * member holds the response. * @internal */ -export type IpcInvokeReturn = { result: any, error?: never } | { result?: never, error: { name: string, message: string, errorNumber: number, stack?: string } }; +export type IpcInvokeReturn = { result: any, error?: never } | { + result?: never; + error: { name: string, message: string, errorNumber: number, stack?: string }; +}; /** * An inter-process socket connection between a single [IModelHost]($backend) on the backend (the node process), and an [IModelApp]($frontend) on * the frontend (the browser process.) Each side will implement this interface to form a two way connection. The frontend and backend * processes connected through an IpcSocket don't necessarily have to be on the same computer, but often are. * @public -*/ + */ export interface IpcSocket { /** * Send a message over the socket. @@ -94,4 +97,3 @@ export interface IpcSocketBackend extends IpcSocket { */ handle: (channel: string, handler: (...args: any[]) => Promise) => RemoveFunction; } - diff --git a/core/common/src/ipc/IpcWebSocket.ts b/core/common/src/ipc/IpcWebSocket.ts index d7986e847b21..38d144344bf8 100644 --- a/core/common/src/ipc/IpcWebSocket.ts +++ b/core/common/src/ipc/IpcWebSocket.ts @@ -16,7 +16,7 @@ export enum IpcWebSocketMessageType { Invoke, Response, Internal, - Duplicate + Duplicate, } /** @internal */ @@ -84,7 +84,7 @@ export abstract class IpcWebSocket implements IpcSocket { return; let arg = message.data; - if (typeof (arg) === "undefined") + if (typeof arg === "undefined") arg = []; for (const handler of handlers) @@ -169,7 +169,7 @@ export class IpcWebSocketBackend extends IpcWebSocket implements IpcSocketBacken const handler = this._handlers.get(message.channel); if (handler) { let args = message.data; - if (typeof (args) === "undefined") + if (typeof args === "undefined") args = []; const response = await handler({} as any, message.method, ...args); diff --git a/core/common/src/ipc/IpcWebSocketTransport.ts b/core/common/src/ipc/IpcWebSocketTransport.ts index 8502d4d4ab73..10d273a8d509 100644 --- a/core/common/src/ipc/IpcWebSocketTransport.ts +++ b/core/common/src/ipc/IpcWebSocketTransport.ts @@ -23,7 +23,7 @@ export abstract class IpcWebSocketTransport { public abstract send(message: IpcWebSocketMessage): void; protected unwrap(data: any) { - return (typeof (Blob) !== "undefined" && data instanceof Blob) ? data.arrayBuffer() : data; + return (typeof Blob !== "undefined" && data instanceof Blob) ? data.arrayBuffer() : data; } protected async notifyIncoming(data: any, connection: any): Promise { @@ -73,7 +73,11 @@ export abstract class IpcWebSocketTransport { } } -interface Marker { ipc: "binary", type: number, index: number } +interface Marker { + ipc: "binary"; + type: number; + index: number; +} const types = [Uint8Array, Int8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array, DataView]; function identify(value: any) { return isBuffer(value) ? 0 : types.indexOf(value.constructor); @@ -93,7 +97,7 @@ function replacer(this: any, _key: string, value: any) { } function reviver(_key: string, value: any) { - if (typeof (value) === "object" && value !== null && value.hasOwnProperty("ipc") && value.ipc === "binary") { + if (typeof value === "object" && value !== null && value.hasOwnProperty("ipc") && value.ipc === "binary") { return reviveBinary(value); } @@ -117,8 +121,8 @@ function reviveBinary(value: Marker): ArrayBufferView { } function makePromise() { - let resolve: (value: T | PromiseLike) => void = () => { }; - let reject: (reason?: any) => void = () => { }; + let resolve: (value: T | PromiseLike) => void = () => {}; + let reject: (reason?: any) => void = () => {}; const promise = new Promise((res, rej) => { resolve = res; reject = rej; @@ -169,7 +173,7 @@ class InSentOrder { this._connections.delete(connection); } - public release = () => { }; + public release = () => {}; public sequence: number; public duplicate = false; public message: Promise; diff --git a/core/common/src/rpc/DevToolsRpcInterface.ts b/core/common/src/rpc/DevToolsRpcInterface.ts index 3376c10c9058..11d9ce73b728 100644 --- a/core/common/src/rpc/DevToolsRpcInterface.ts +++ b/core/common/src/rpc/DevToolsRpcInterface.ts @@ -27,7 +27,9 @@ export enum DevToolsStatsOptions { */ export abstract class DevToolsRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation /** Returns the IModelReadRpcInterface instance for the frontend. */ - public static getClient(): DevToolsRpcInterface { return RpcManager.getClientForInterface(DevToolsRpcInterface); } + public static getClient(): DevToolsRpcInterface { + return RpcManager.getClientForInterface(DevToolsRpcInterface); + } /** The immutable name of the interface. */ public static readonly interfaceName = "DevToolsRpcInterface"; @@ -42,10 +44,14 @@ export abstract class DevToolsRpcInterface extends RpcInterface { // eslint-disa NOTE: Please consult the README in this folder for the semantic versioning rules. ==========================================================================================*/ // Sends a ping and returns true if the backend received the ping - public async ping(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } + public async ping(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } // Returns JSON object with backend performance and memory statistics - public async stats(_iModelToken: IModelRpcProps, _options: DevToolsStatsOptions): Promise { return this.forward(arguments); } + public async stats(_iModelToken: IModelRpcProps, _options: DevToolsStatsOptions): Promise { + return this.forward(arguments); + } // Returns JSON object with backend versions (application and iModelJs) public async versions(_iModelToken: IModelRpcProps): Promise { @@ -55,5 +61,7 @@ export abstract class DevToolsRpcInterface extends RpcInterface { // eslint-disa } // Sets a new log level for the specified category and returns the old log level - public async setLogLevel(_iModelToken: IModelRpcProps, _loggerCategory: string, _logLevel: LogLevel): Promise { return this.forward(arguments); } + public async setLogLevel(_iModelToken: IModelRpcProps, _loggerCategory: string, _logLevel: LogLevel): Promise { + return this.forward(arguments); + } } diff --git a/core/common/src/rpc/IModelReadRpcInterface.ts b/core/common/src/rpc/IModelReadRpcInterface.ts index 223d9c0cdf4d..2711f1c89bf8 100644 --- a/core/common/src/rpc/IModelReadRpcInterface.ts +++ b/core/common/src/rpc/IModelReadRpcInterface.ts @@ -15,22 +15,33 @@ import { ElementLoadOptions, ElementProps } from "../ElementProps"; import { EntityQueryParams } from "../EntityProps"; import { FontMapProps } from "../Fonts"; import { - GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, + GeoCoordinatesRequestProps, + GeoCoordinatesResponseProps, + IModelCoordinatesRequestProps, + IModelCoordinatesResponseProps, } from "../GeoCoordinateServices"; import { GeometryContainmentRequestProps, GeometryContainmentResponseProps } from "../GeometryContainment"; import { GeometrySummaryRequestProps } from "../GeometrySummary"; import { IModelConnectionProps, IModelRpcOpenProps, IModelRpcProps } from "../IModel"; +import { SnapRequestProps, SnapResponseProps } from "../internal/Snapping"; import { - MassPropertiesPerCandidateRequestProps, MassPropertiesPerCandidateResponseProps, MassPropertiesRequestProps, MassPropertiesResponseProps, + MassPropertiesPerCandidateRequestProps, + MassPropertiesPerCandidateResponseProps, + MassPropertiesRequestProps, + MassPropertiesResponseProps, } from "../MassProperties"; import { ModelProps } from "../ModelProps"; import { RpcInterface } from "../RpcInterface"; import { RpcManager } from "../RpcManager"; -import { SnapRequestProps, SnapResponseProps } from "../internal/Snapping"; import { TextureData, TextureLoadProps } from "../TextureProps"; import { - CustomViewState3dCreatorOptions, CustomViewState3dProps, HydrateViewStateRequestProps, HydrateViewStateResponseProps, SubCategoryResultRow, - ViewStateLoadProps, ViewStateProps, + CustomViewState3dCreatorOptions, + CustomViewState3dProps, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + SubCategoryResultRow, + ViewStateLoadProps, + ViewStateProps, } from "../ViewProps"; import { RpcResponseCacheControl } from "./core/RpcConstants"; import { RpcNotFoundResponse } from "./core/RpcControl"; @@ -75,10 +86,14 @@ export interface ModelExtentsProps { */ export abstract class IModelReadRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation /** Returns the IModelReadRpcInterface instance for the frontend. */ - public static getClient(): IModelReadRpcInterface { return RpcManager.getClientForInterface(IModelReadRpcInterface); } + public static getClient(): IModelReadRpcInterface { + return RpcManager.getClientForInterface(IModelReadRpcInterface); + } /** Returns the IModelReadRpcInterface instance for a custom RPC routing configuration. */ - public static getClientForRouting(token: RpcRoutingToken): IModelReadRpcInterface { return RpcManager.getClientForInterface(IModelReadRpcInterface, token); } + public static getClientForRouting(token: RpcRoutingToken): IModelReadRpcInterface { + return RpcManager.getClientForInterface(IModelReadRpcInterface, token); + } /** The immutable name of the interface. */ public static readonly interfaceName = "IModelReadRpcInterface"; @@ -91,54 +106,132 @@ export abstract class IModelReadRpcInterface extends RpcInterface { // eslint-di NOTE: Please consult the README in this folder for the semantic versioning rules. ===========================================================================================*/ @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getConnectionProps(_iModelToken: IModelRpcOpenProps): Promise { return this.forward(arguments); } - public async queryRows(_iModelToken: IModelRpcProps, _request: DbQueryRequest): Promise { return this.forward(arguments); } + public async getConnectionProps(_iModelToken: IModelRpcOpenProps): Promise { + return this.forward(arguments); + } + public async queryRows(_iModelToken: IModelRpcProps, _request: DbQueryRequest): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async querySubCategories(_iModelToken: IModelRpcProps, _categoryIds: CompressedId64Set): Promise { return this.forward(arguments); } + public async querySubCategories(_iModelToken: IModelRpcProps, _categoryIds: CompressedId64Set): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async queryAllUsedSpatialSubCategories(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } - public async queryBlob(_iModelToken: IModelRpcProps, _request: DbBlobRequest): Promise { return this.forward(arguments); } + public async queryAllUsedSpatialSubCategories(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } + public async queryBlob(_iModelToken: IModelRpcProps, _request: DbBlobRequest): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getModelProps(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { return this.forward(arguments); } + public async getModelProps(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async queryModelRanges(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { return this.forward(arguments); } + public async queryModelRanges(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async queryModelExtents(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { return this.forward(arguments); } - public async queryModelProps(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { return this.forward(arguments); } - public async getElementProps(_iModelToken: IModelRpcProps, _elementIds: Id64String[]): Promise { return this.forward(arguments); } - public async queryElementProps(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { return this.forward(arguments); } - public async queryEntityIds(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { return this.forward(arguments); } + public async queryModelExtents(_iModelToken: IModelRpcProps, _modelIds: Id64String[]): Promise { + return this.forward(arguments); + } + public async queryModelProps(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { + return this.forward(arguments); + } + public async getElementProps(_iModelToken: IModelRpcProps, _elementIds: Id64String[]): Promise { + return this.forward(arguments); + } + public async queryElementProps(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { + return this.forward(arguments); + } + public async queryEntityIds(_iModelToken: IModelRpcProps, _params: EntityQueryParams): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getClassHierarchy(_iModelToken: IModelRpcProps, _startClassName: string): Promise { return this.forward(arguments); } - public async getAllCodeSpecs(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } + public async getClassHierarchy(_iModelToken: IModelRpcProps, _startClassName: string): Promise { + return this.forward(arguments); + } + public async getAllCodeSpecs(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getViewStateData(_iModelToken: IModelRpcProps, _viewDefinitionId: string, _options?: ViewStateLoadProps): Promise { return this.forward(arguments); } - public async readFontJson(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } - public async getToolTipMessage(_iModelToken: IModelRpcProps, _elementId: string): Promise { return this.forward(arguments); } + public async getViewStateData(_iModelToken: IModelRpcProps, _viewDefinitionId: string, _options?: ViewStateLoadProps): Promise { + return this.forward(arguments); + } + public async readFontJson(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } + public async getToolTipMessage(_iModelToken: IModelRpcProps, _elementId: string): Promise { + return this.forward(arguments); + } /** @deprecated in 3.x use ViewStore apis. */ - public async getViewThumbnail(_iModelToken: IModelRpcProps, _viewId: string): Promise { return this.forward(arguments); } + public async getViewThumbnail(_iModelToken: IModelRpcProps, _viewId: string): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getDefaultViewId(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } + public async getDefaultViewId(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getCustomViewState3dData(_iModelToken: IModelRpcProps, _options: CustomViewState3dCreatorOptions): Promise { return this.forward(arguments); } + public async getCustomViewState3dData(_iModelToken: IModelRpcProps, _options: CustomViewState3dCreatorOptions): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async hydrateViewState(_iModelToken: IModelRpcProps, _options: HydrateViewStateRequestProps): Promise { return this.forward(arguments); } - public async requestSnap(_iModelToken: IModelRpcProps, _sessionId: string, _props: SnapRequestProps): Promise { return this.forward(arguments); } - public async cancelSnap(_iModelToken: IModelRpcProps, _sessionId: string): Promise { return this.forward(arguments); } - public async getGeometryContainment(_iModelToken: IModelRpcProps, _props: GeometryContainmentRequestProps): Promise { return this.forward(arguments); } - public async getMassProperties(_iModelToken: IModelRpcProps, _props: MassPropertiesRequestProps): Promise { return this.forward(arguments); } - public async getMassPropertiesPerCandidate(_iModelToken: IModelRpcProps, _props: MassPropertiesPerCandidateRequestProps): Promise { return this.forward(arguments); } - public async getIModelCoordinatesFromGeoCoordinates(_iModelToken: IModelRpcProps, _props: IModelCoordinatesRequestProps): Promise { return this.forward(arguments); } + public async hydrateViewState(_iModelToken: IModelRpcProps, _options: HydrateViewStateRequestProps): Promise { + return this.forward(arguments); + } + public async requestSnap(_iModelToken: IModelRpcProps, _sessionId: string, _props: SnapRequestProps): Promise { + return this.forward(arguments); + } + public async cancelSnap(_iModelToken: IModelRpcProps, _sessionId: string): Promise { + return this.forward(arguments); + } + public async getGeometryContainment( + _iModelToken: IModelRpcProps, + _props: GeometryContainmentRequestProps, + ): Promise { + return this.forward(arguments); + } + public async getMassProperties(_iModelToken: IModelRpcProps, _props: MassPropertiesRequestProps): Promise { + return this.forward(arguments); + } + public async getMassPropertiesPerCandidate( + _iModelToken: IModelRpcProps, + _props: MassPropertiesPerCandidateRequestProps, + ): Promise { + return this.forward(arguments); + } + public async getIModelCoordinatesFromGeoCoordinates( + _iModelToken: IModelRpcProps, + _props: IModelCoordinatesRequestProps, + ): Promise { + return this.forward(arguments); + } @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async getGeoCoordinatesFromIModelCoordinates(_iModelToken: IModelRpcProps, _props: GeoCoordinatesRequestProps): Promise { return this.forward(arguments); } - public async getGeometrySummary(_iModelToken: IModelRpcProps, _props: GeometrySummaryRequestProps): Promise { return this.forward(arguments); } - public async queryTextureData(_iModelToken: IModelRpcProps, _textureLoadProps: TextureLoadProps): Promise { return this.forward(arguments); } - public async loadElementProps(_iModelToken: IModelRpcProps, _elementIdentifier: Id64String | GuidString | CodeProps, _options?: ElementLoadOptions): Promise { + public async getGeoCoordinatesFromIModelCoordinates( + _iModelToken: IModelRpcProps, + _props: GeoCoordinatesRequestProps, + ): Promise { + return this.forward(arguments); + } + public async getGeometrySummary(_iModelToken: IModelRpcProps, _props: GeometrySummaryRequestProps): Promise { + return this.forward(arguments); + } + public async queryTextureData(_iModelToken: IModelRpcProps, _textureLoadProps: TextureLoadProps): Promise { + return this.forward(arguments); + } + public async loadElementProps( + _iModelToken: IModelRpcProps, + _elementIdentifier: Id64String | GuidString | CodeProps, + _options?: ElementLoadOptions, + ): Promise { return this.forward(arguments); } public async generateElementMeshes(_iModelToken: IModelRpcProps, _props: ElementMeshRequestProps): Promise { return this.forward(arguments); } /** @internal */ - public async callViewStore(_iModelToken: IModelRpcProps, _version: string, _forWrite: boolean, _methodName: string, ..._args: any[]): Promise { return this.forward(arguments); } + public async callViewStore(_iModelToken: IModelRpcProps, _version: string, _forWrite: boolean, _methodName: string, ..._args: any[]): Promise { + return this.forward(arguments); + } } diff --git a/core/common/src/rpc/IModelTileRpcInterface.ts b/core/common/src/rpc/IModelTileRpcInterface.ts index 41a8eba9e55d..e4c29ff305c6 100644 --- a/core/common/src/rpc/IModelTileRpcInterface.ts +++ b/core/common/src/rpc/IModelTileRpcInterface.ts @@ -6,19 +6,21 @@ * @module RpcInterface */ -import type { TransferConfig } from "@itwin/object-storage-core/lib/common"; import { Id64Array } from "@itwin/core-bentley"; -import { RpcResponseCacheControl } from "./core/RpcConstants"; -import { RpcOperation } from "./core/RpcOperation"; +import type { TransferConfig } from "@itwin/object-storage-core/lib/common"; import { IModelRpcProps } from "../IModel"; import { RpcInterface } from "../RpcInterface"; import { RpcManager } from "../RpcManager"; import { ElementGraphicsRequestProps } from "../tile/ElementGraphics"; import { IModelTileTreeProps, TileContentIdentifier, TileContentSource, TileVersionInfo } from "../TileProps"; +import { RpcResponseCacheControl } from "./core/RpcConstants"; +import { RpcOperation } from "./core/RpcOperation"; /** @public */ export abstract class IModelTileRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation - public static getClient(): IModelTileRpcInterface { return RpcManager.getClientForInterface(IModelTileRpcInterface); } + public static getClient(): IModelTileRpcInterface { + return RpcManager.getClientForInterface(IModelTileRpcInterface); + } /** The immutable name of the interface. */ public static readonly interfaceName = "IModelTileRpcInterface"; @@ -42,14 +44,21 @@ export abstract class IModelTileRpcInterface extends RpcInterface { // eslint-di /** @internal */ @RpcOperation.allowResponseCaching(RpcResponseCacheControl.Immutable) // eslint-disable-line deprecation/deprecation - public async requestTileTreeProps(_tokenProps: IModelRpcProps, _id: string): Promise { return this.forward(arguments); } + public async requestTileTreeProps(_tokenProps: IModelRpcProps, _id: string): Promise { + return this.forward(arguments); + } /** Ask the backend to generate content for the specified tile. This function, unlike the deprecated `requestTileContent`, does not check the cloud storage tile cache - * Use `CloudStorageTileCache.retrieve` for that. * @returns TileContentSource - if Backend, use retrieveTileContent. If ExternalCache, use TileAdmin.requestCachedTileContent * @internal */ - public async generateTileContent(_rpcProps: IModelRpcProps, _treeId: string, _contentId: string, _guid: string | undefined): Promise { + public async generateTileContent( + _rpcProps: IModelRpcProps, + _treeId: string, + _contentId: string, + _guid: string | undefined, + ): Promise { return this.forward(arguments); } @@ -71,7 +80,9 @@ export abstract class IModelTileRpcInterface extends RpcInterface { // eslint-di * If no array of model Ids is supplied, it purges *all* tile trees, which can be quite inefficient. * @internal */ - public async purgeTileTrees(_tokenProps: IModelRpcProps, _modelIds: Id64Array | undefined): Promise { return this.forward(arguments); } + public async purgeTileTrees(_tokenProps: IModelRpcProps, _modelIds: Id64Array | undefined): Promise { + return this.forward(arguments); + } /** Requests graphics for a single element in "iMdl" format. * @returns graphics in iMdl format, or `undefined` if the element's geometry produced no graphics or the request was canceled before completion. diff --git a/core/common/src/rpc/SnapshotIModelRpcInterface.ts b/core/common/src/rpc/SnapshotIModelRpcInterface.ts index 7afc489ba018..e909af2e1128 100644 --- a/core/common/src/rpc/SnapshotIModelRpcInterface.ts +++ b/core/common/src/rpc/SnapshotIModelRpcInterface.ts @@ -21,10 +21,14 @@ const unknownIModelId: RpcRequestTokenSupplier_T = (req) => ({ iModelId: "undefi */ export abstract class SnapshotIModelRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation /** Returns the SnapshotIModelRpcInterface client instance for the frontend. */ - public static getClient(): SnapshotIModelRpcInterface { return RpcManager.getClientForInterface(SnapshotIModelRpcInterface); } + public static getClient(): SnapshotIModelRpcInterface { + return RpcManager.getClientForInterface(SnapshotIModelRpcInterface); + } /** Returns the SnapshotIModelRpcInterface client instance for a custom RPC routing configuration. */ - public static getClientForRouting(token: RpcRoutingToken): SnapshotIModelRpcInterface { return RpcManager.getClientForInterface(SnapshotIModelRpcInterface, token); } + public static getClientForRouting(token: RpcRoutingToken): SnapshotIModelRpcInterface { + return RpcManager.getClientForInterface(SnapshotIModelRpcInterface, token); + } /** The immutable name of the interface. */ public static readonly interfaceName = "SnapshotIModelRpcInterface"; @@ -38,13 +42,19 @@ export abstract class SnapshotIModelRpcInterface extends RpcInterface { // eslin ===========================================================================================*/ @RpcOperation.setRoutingProps(unknownIModelId) - public async openFile(_filePath: string, _opts?: SnapshotOpenOptions): Promise { return this.forward(arguments); } + public async openFile(_filePath: string, _opts?: SnapshotOpenOptions): Promise { + return this.forward(arguments); + } /** * @deprecated in 4.10. Use [[CheckpointConnection.openRemote]]. */ @RpcOperation.setRoutingProps(unknownIModelId) - public async openRemote(_key: string, _opts?: SnapshotOpenOptions): Promise { return this.forward(arguments); } + public async openRemote(_key: string, _opts?: SnapshotOpenOptions): Promise { + return this.forward(arguments); + } - public async close(_iModelRpcProps: IModelRpcProps): Promise { return this.forward(arguments); } + public async close(_iModelRpcProps: IModelRpcProps): Promise { + return this.forward(arguments); + } } diff --git a/core/common/src/rpc/WipRpcInterface.ts b/core/common/src/rpc/WipRpcInterface.ts index 7675d255d49d..ae847eada991 100644 --- a/core/common/src/rpc/WipRpcInterface.ts +++ b/core/common/src/rpc/WipRpcInterface.ts @@ -22,7 +22,9 @@ import { RpcManager } from "../RpcManager"; */ export abstract class WipRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation /** Returns the IModelReadRpcInterface instance for the frontend. */ - public static getClient(): WipRpcInterface { return RpcManager.getClientForInterface(WipRpcInterface); } // eslint-disable-line deprecation/deprecation + public static getClient(): WipRpcInterface { + return RpcManager.getClientForInterface(WipRpcInterface); + } // eslint-disable-line deprecation/deprecation /** The immutable name of the interface. */ public static readonly interfaceName = "WipRpcInterface"; @@ -36,9 +38,23 @@ export abstract class WipRpcInterface extends RpcInterface { // eslint-disable-l NOTE: Any add/remove/change to the methods below requires an update of the interface version. NOTE: Please consult the README in this folder for the semantic versioning rules. ==========================================================================================*/ - public async placeholder(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } // here to test that WipRpcInterface is configured properly - public async isChangeCacheAttached(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } - public async attachChangeCache(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } - public async getChangedElements(_iModelToken: IModelRpcProps, _startChangesetId: string, _endChangesetId: string): Promise { return this.forward(arguments); } - public async isChangesetProcessed(_iModelToken: IModelRpcProps, _changesetId: string): Promise { return this.forward(arguments); } + public async placeholder(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } // here to test that WipRpcInterface is configured properly + public async isChangeCacheAttached(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } + public async attachChangeCache(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } + public async getChangedElements( + _iModelToken: IModelRpcProps, + _startChangesetId: string, + _endChangesetId: string, + ): Promise { + return this.forward(arguments); + } + public async isChangesetProcessed(_iModelToken: IModelRpcProps, _changesetId: string): Promise { + return this.forward(arguments); + } } diff --git a/core/common/src/rpc/core/RpcConfiguration.ts b/core/common/src/rpc/core/RpcConfiguration.ts index 91d65f823b4b..f8e73a450efd 100644 --- a/core/common/src/rpc/core/RpcConfiguration.ts +++ b/core/common/src/rpc/core/RpcConfiguration.ts @@ -21,7 +21,9 @@ import { RpcRoutingToken } from "./RpcRoutingToken"; export type RpcConfigurationSupplier = (routing?: RpcRoutingToken) => { new(): RpcConfiguration }; // eslint-disable-line @typescript-eslint/prefer-function-type /** @internal */ -export interface RpcRoutingMap extends RpcConfigurationSupplier { configurations: Map } +export interface RpcRoutingMap extends RpcConfigurationSupplier { + configurations: Map; +} /** @internal */ export namespace RpcRoutingMap { @@ -68,7 +70,11 @@ export abstract class RpcConfiguration { } /** Sets the configuration supplier for an RPC interface class for a given routing. */ - public static assignWithRouting(definition: RpcInterfaceDefinition, routing: RpcRoutingToken, configuration: new () => RpcConfiguration): void { + public static assignWithRouting( + definition: RpcInterfaceDefinition, + routing: RpcRoutingToken, + configuration: new() => RpcConfiguration, + ): void { if (!definition.prototype.configurationSupplier) { RpcConfiguration.assign(definition, RpcRoutingMap.create()); } @@ -86,7 +92,7 @@ export abstract class RpcConfiguration { } /** Obtains the instance of an RPC configuration class. */ - public static obtain(configurationConstructor: new () => T): T { + public static obtain(configurationConstructor: new() => T): T { let instance = (configurationConstructor as any)[INSTANCE] as T; if (!instance) instance = (configurationConstructor as any)[INSTANCE] = new configurationConstructor(); @@ -121,7 +127,9 @@ export abstract class RpcConfiguration { public allowAttachedInterfaces: boolean = true; /** @internal */ - public get attachedInterfaces(): ReadonlyArray { return this.attached; } + public get attachedInterfaces(): ReadonlyArray { + return this.attached; + } /** The target interval (in milliseconds) between connection attempts for pending RPC operation requests. */ public pendingOperationRetryInterval = 10000; diff --git a/core/common/src/rpc/core/RpcConstants.ts b/core/common/src/rpc/core/RpcConstants.ts index d0263012c1b8..d1497179b664 100644 --- a/core/common/src/rpc/core/RpcConstants.ts +++ b/core/common/src/rpc/core/RpcConstants.ts @@ -55,7 +55,7 @@ export enum RpcRequestStatus { ServiceUnavailable, GatewayTimeout, RequestTimeout, - TooManyRequests + TooManyRequests, } /** @public @deprecated in 3.6. The RPC system will be significantly refactored (or replaced) in the future. */ @@ -73,7 +73,7 @@ export namespace RpcRequestStatus { // eslint-disable-line @typescript-eslint/no export enum RpcRequestEvent { StatusChanged, PendingUpdateReceived, - TransientErrorReceived + TransientErrorReceived, } /** RPC content types. diff --git a/core/common/src/rpc/core/RpcControl.ts b/core/common/src/rpc/core/RpcControl.ts index c3fa23a3a25b..bb6a616adfa6 100644 --- a/core/common/src/rpc/core/RpcControl.ts +++ b/core/common/src/rpc/core/RpcControl.ts @@ -92,7 +92,9 @@ export class RpcControlChannel { private _channelInterface = class extends RpcInterface { public static readonly interfaceVersion = "CONTROL"; public static readonly interfaceName = ""; - public async describeEndpoints(): Promise { return this.forward(arguments); } + public async describeEndpoints(): Promise { + return this.forward(arguments); + } }; private _channelImpl = class extends RpcInterface { @@ -103,7 +105,12 @@ export class RpcControlChannel { if (!RpcRegistry.instance.isRpcInterfaceInitialized(definition)) return; - const description: RpcInterfaceEndpoints = { interfaceName: definition.interfaceName, interfaceVersion: definition.interfaceVersion, operationNames: [], compatible: true }; + const description: RpcInterfaceEndpoints = { + interfaceName: definition.interfaceName, + interfaceVersion: definition.interfaceVersion, + operationNames: [], + compatible: true, + }; RpcOperation.forEach(definition, (operation) => description.operationNames.push(operation.operationName)); endpoints.push(description); }); diff --git a/core/common/src/rpc/core/RpcInvocation.ts b/core/common/src/rpc/core/RpcInvocation.ts index 1774ae8ccea9..094d4b9c73fd 100644 --- a/core/common/src/rpc/core/RpcInvocation.ts +++ b/core/common/src/rpc/core/RpcInvocation.ts @@ -6,7 +6,17 @@ * @module RpcInterface */ -import { AccessToken, BentleyError, BentleyStatus, GuidString, IModelStatus, Logger, RpcInterfaceStatus, StatusCategory, Tracing } from "@itwin/core-bentley"; +import { + AccessToken, + BentleyError, + BentleyStatus, + GuidString, + IModelStatus, + Logger, + RpcInterfaceStatus, + StatusCategory, + Tracing, +} from "@itwin/core-bentley"; import { CommonLoggerCategory } from "../../CommonLoggerCategory"; import { IModelRpcProps } from "../../IModel"; import { IModelError } from "../../IModelError"; @@ -84,11 +94,15 @@ export class RpcInvocation { /** The status for this request. */ public get status(): RpcRequestStatus { - return this._threw ? RpcRequestStatus.Rejected : - this._pending ? RpcRequestStatus.Pending : - this._notFound ? RpcRequestStatus.NotFound : - this._noContent ? RpcRequestStatus.NoContent : - RpcRequestStatus.Resolved; + return this._threw ? + RpcRequestStatus.Rejected : + this._pending ? + RpcRequestStatus.Pending : + this._notFound ? + RpcRequestStatus.NotFound : + this._noContent ? + RpcRequestStatus.NoContent : + RpcRequestStatus.Resolved; } /** The elapsed time for this invocation. */ @@ -117,7 +131,10 @@ export class RpcInvocation { const backend = this.operation.interfaceVersion; const frontend = this.request.operation.interfaceVersion; if (!RpcInterface.isVersionCompatible(backend, frontend)) { - throw new IModelError(RpcInterfaceStatus.IncompatibleVersion, `Backend version ${backend} does not match frontend version ${frontend} for RPC interface ${this.operation.operationName}.`); + throw new IModelError( + RpcInterfaceStatus.IncompatibleVersion, + `Backend version ${backend} does not match frontend version ${frontend} for RPC interface ${this.operation.operationName}.`, + ); } } catch (error) { if (this.handleUnknownOperation(error)) { @@ -132,7 +149,10 @@ export class RpcInvocation { this.result = this.reject(error); } - this.fulfillment = this.result.then(async (value) => this._threw ? this.fulfillRejected(value) : this.fulfillResolved(value), async (reason) => this.fulfillRejected(reason)); + this.fulfillment = this.result.then( + async (value) => this._threw ? this.fulfillRejected(value) : this.fulfillResolved(value), + async (reason) => this.fulfillRejected(reason), + ); } private handleUnknownOperation(error: any): boolean { @@ -142,9 +162,15 @@ export class RpcInvocation { public static sanitizeForLog(activity?: RpcActivity) { /* eslint-disable @typescript-eslint/naming-convention */ - return activity ? { - ActivityId: activity.activityId, SessionId: activity.sessionId, ApplicationId: activity.applicationId, ApplicationVersion: activity.applicationVersion, rpcMethod: activity.rpcMethod, - } : undefined; + return activity ? + { + ActivityId: activity.activityId, + SessionId: activity.sessionId, + ApplicationId: activity.applicationId, + ApplicationVersion: activity.applicationVersion, + rpcMethod: activity.rpcMethod, + } : + undefined; /* eslint-enable @typescript-eslint/naming-convention */ } @@ -169,15 +195,16 @@ export class RpcInvocation { (impl as any)[CURRENT_INVOCATION] = this; const op = this.lookupOperationFunction(impl); - return await RpcInvocation.runActivity(activity, async () => op.call(impl, ...parameters) - .catch(async (error) => { - // this catch block is intentionally placed inside `runActivity` to attach the right logging metadata and use the correct openTelemetry span. - if (!(error instanceof RpcPendingResponse)) { - Logger.logError(CommonLoggerCategory.RpcInterfaceBackend, "Error in RPC operation", { error: BentleyError.getErrorProps(error) }); - Tracing.recordException(error); - } - throw error; - })); + return await RpcInvocation.runActivity(activity, async () => + op.call(impl, ...parameters) + .catch(async (error) => { + // this catch block is intentionally placed inside `runActivity` to attach the right logging metadata and use the correct openTelemetry span. + if (!(error instanceof RpcPendingResponse)) { + Logger.logError(CommonLoggerCategory.RpcInterfaceBackend, "Error in RPC operation", { error: BentleyError.getErrorProps(error) }); + Tracing.recordException(error); + } + throw error; + })); } catch (error: unknown) { return this.reject(error); } @@ -189,7 +216,8 @@ export class RpcInvocation { for (let i = 0; i !== parameters.length; ++i) { const parameter = parameters[i]; - const isToken = typeof (parameter) === "object" && parameter !== null && parameter.hasOwnProperty("iModelId") && parameter.hasOwnProperty("iTwinId"); + const isToken = typeof parameter === "object" && parameter !== null && parameter.hasOwnProperty("iModelId") && + parameter.hasOwnProperty("iTwinId"); if (isToken && this.protocol.checkToken && !this.operation.policy.allowTokenMismatch) { const inflated = this.protocol.inflateToken(parameter, this.request); parameters[i] = inflated; @@ -257,7 +285,8 @@ export class RpcInvocation { return false; } - return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedNoContent && this.request.protocolVersion >= RpcProtocolVersion.IntroducedNoContent; + return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedNoContent && + this.request.protocolVersion >= RpcProtocolVersion.IntroducedNoContent; } private supportsStatusCategory() { @@ -269,7 +298,8 @@ export class RpcInvocation { return false; } - return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory && this.request.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory; + return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory && + this.request.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory; } private fulfill(result: RpcSerializedValue, rawResult: any): RpcRequestFulfillment { @@ -289,15 +319,18 @@ export class RpcInvocation { if (impl[CURRENT_INVOCATION] === this) { impl[CURRENT_INVOCATION] = undefined; } - } catch (_err) { } + } catch (_err) {} return fulfillment; } private lookupOperationFunction(implementation: RpcInterface): (...args: any[]) => Promise { const func = (implementation as any)[this.operation.operationName]; - if (!func || typeof (func) !== "function") - throw new IModelError(BentleyStatus.ERROR, `RPC interface class "${implementation.constructor.name}" does not implement operation "${this.operation.operationName}".`); + if (!func || typeof func !== "function") + throw new IModelError( + BentleyStatus.ERROR, + `RPC interface class "${implementation.constructor.name}" does not implement operation "${this.operation.operationName}".`, + ); return func; } diff --git a/core/common/src/rpc/core/RpcMarshaling.ts b/core/common/src/rpc/core/RpcMarshaling.ts index 41fb3d65ed0a..b4180519b896 100644 --- a/core/common/src/rpc/core/RpcMarshaling.ts +++ b/core/common/src/rpc/core/RpcMarshaling.ts @@ -6,8 +6,8 @@ * @module RpcInterface */ -import { BentleyStatus, IModelError } from "../../IModelError"; import { BackendReadable } from "../../BackendTypes"; +import { BentleyStatus, IModelError } from "../../IModelError"; import { RpcProtocol } from "./RpcProtocol"; // cspell:ignore unmarshal @@ -52,7 +52,7 @@ export namespace RpcSerializedValue { /** @internal */ export class RpcMarshaling { - private constructor() { } + private constructor() {} /** Serializes a value. */ public static serialize(protocol: RpcProtocol | undefined, value: any): RpcSerializedValue { @@ -111,7 +111,7 @@ class WireFormat { /** JSON.parse reviver callback. */ public static unmarshal(_key: string, value: any) { - if (typeof (value) === "object" && value !== null && value.hasOwnProperty("isBinary") && value.isBinary) { + if (typeof value === "object" && value !== null && value.hasOwnProperty("isBinary") && value.isBinary) { return WireFormat.unmarshalBinary(value); } @@ -130,7 +130,7 @@ class WireFormat { const end = cursor + value.byteLength; let chunk = chunkThreshold; - for (; ;) { + for (;;) { if (cursor >= end) { break; } diff --git a/core/common/src/rpc/core/RpcOperation.ts b/core/common/src/rpc/core/RpcOperation.ts index ef83b2771a12..c703802af7b1 100644 --- a/core/common/src/rpc/core/RpcOperation.ts +++ b/core/common/src/rpc/core/RpcOperation.ts @@ -13,7 +13,10 @@ import { RpcInterface, RpcInterfaceDefinition } from "../../RpcInterface"; import { RpcResponseCacheControl } from "./RpcConstants"; import { OPERATION, POLICY, RpcRegistry } from "./RpcRegistry"; import { - RpcRequestCallback_T, RpcRequestInitialRetryIntervalSupplier_T, RpcRequestTokenSupplier_T, RpcResponseCachingCallback_T, + RpcRequestCallback_T, + RpcRequestInitialRetryIntervalSupplier_T, + RpcRequestTokenSupplier_T, + RpcResponseCachingCallback_T, } from "./RpcRequest"; /* eslint-disable deprecation/deprecation */ @@ -29,10 +32,10 @@ export class RpcOperationPolicy { public retryInterval: RpcRequestInitialRetryIntervalSupplier_T = (configuration) => configuration.pendingOperationRetryInterval; /** Called before every operation request on the frontend is sent. */ - public requestCallback: RpcRequestCallback_T = (_request) => { }; + public requestCallback: RpcRequestCallback_T = (_request) => {}; /** Called after every operation request on the frontend is sent. */ - public sentCallback: RpcRequestCallback_T = (_request) => { }; + public sentCallback: RpcRequestCallback_T = (_request) => {}; /** * Determines if caching is permitted for an operation response. @@ -59,12 +62,15 @@ export class RpcOperation { /** Looks up an RPC operation by name. */ public static lookup(target: string | RpcInterfaceDefinition, operationName: string): RpcOperation { - const definition = typeof (target) === "string" ? RpcRegistry.instance.lookupInterfaceDefinition(target) : target; + const definition = typeof target === "string" ? RpcRegistry.instance.lookupInterfaceDefinition(target) : target; const propertyName: string | symbol = RpcOperation.computeOperationName(operationName); - const proto = (definition.prototype as any); + const proto = definition.prototype as any; if (!proto.hasOwnProperty(propertyName)) - throw new IModelError(BentleyStatus.ERROR, `RPC interface class "${definition.interfaceName}" does not does not declare operation "${operationName}"`); + throw new IModelError( + BentleyStatus.ERROR, + `RPC interface class "${definition.interfaceName}" does not does not declare operation "${operationName}"`, + ); return proto[propertyName][OPERATION]; } @@ -87,7 +93,9 @@ export class RpcOperation { public readonly operationName: string; /** The version of this operation. */ - public get interfaceVersion(): string { return this.interfaceDefinition.interfaceVersion; } + public get interfaceVersion(): string { + return this.interfaceDefinition.interfaceVersion; + } /** The policy for this operation. */ public policy: RpcOperationPolicy; @@ -134,18 +142,26 @@ export namespace RpcOperation { // eslint-disable-line no-redeclare /** Convenience decorator for setting an RPC operation policy that allows response caching. */ export function allowResponseCaching(control: RpcResponseCacheControl = RpcResponseCacheControl.Immutable) { return (target: T, propertyKey: string, descriptor: PropertyDescriptor) => { - descriptor.value[OPERATION] = new RpcOperation(target.constructor as any, propertyKey, new class extends RpcOperationPolicy { - public override allowResponseCaching = () => control; - }()); + descriptor.value[OPERATION] = new RpcOperation( + target.constructor as any, + propertyKey, + new class extends RpcOperationPolicy { + public override allowResponseCaching = () => control; + }(), + ); }; } /** Convenience decorator for setting an RPC operation policy that supplies the IModelRpcProps for an operation. */ export function setRoutingProps(handler: RpcRequestTokenSupplier_T) { return (target: T, propertyKey: string, descriptor: PropertyDescriptor) => { - descriptor.value[OPERATION] = new RpcOperation(target.constructor as any, propertyKey, new class extends RpcOperationPolicy { - public override token = handler; - }()); + descriptor.value[OPERATION] = new RpcOperation( + target.constructor as any, + propertyKey, + new class extends RpcOperationPolicy { + public override token = handler; + }(), + ); }; } diff --git a/core/common/src/rpc/core/RpcPendingQueue.ts b/core/common/src/rpc/core/RpcPendingQueue.ts index 52f64dd37f9f..91020c38248d 100644 --- a/core/common/src/rpc/core/RpcPendingQueue.ts +++ b/core/common/src/rpc/core/RpcPendingQueue.ts @@ -66,7 +66,7 @@ export class RpcPendingQueue { this.clearPendingInterval(); } - private _pendingIntervalHandler = function (this: RpcPendingQueue) { + private _pendingIntervalHandler = function(this: RpcPendingQueue) { const now = new Date().getTime(); ++this._pendingLock; diff --git a/core/common/src/rpc/core/RpcProtocol.ts b/core/common/src/rpc/core/RpcProtocol.ts index 13d839e2e594..08f7d781f5d5 100644 --- a/core/common/src/rpc/core/RpcProtocol.ts +++ b/core/common/src/rpc/core/RpcProtocol.ts @@ -95,7 +95,7 @@ export type RpcProtocolEventHandler = (type: RpcProtocolEvent, object: RpcReques export enum RpcProtocolVersion { None = 0, IntroducedNoContent = 1, - IntroducedStatusCategory = 2 + IntroducedStatusCategory = 2, } /** @@ -163,7 +163,9 @@ export abstract class RpcProtocol { public supportsStatusCategory: boolean = false; /** If checkToken is true, will be called on the backend to inflate the IModelRpcProps for each request. */ - public inflateToken(tokenFromBody: IModelRpcProps, _request: SerializedRpcRequest): IModelRpcProps { return tokenFromBody; } + public inflateToken(tokenFromBody: IModelRpcProps, _request: SerializedRpcRequest): IModelRpcProps { + return tokenFromBody; + } /** Override to supply the status corresponding to a protocol-specific code value. */ public getStatus(code: number): RpcRequestStatus { @@ -215,14 +217,14 @@ export abstract class RpcProtocol { } /** @internal */ - public onRpcClientInitialized(_definition: RpcInterfaceDefinition, _client: RpcInterface): void { } + public onRpcClientInitialized(_definition: RpcInterfaceDefinition, _client: RpcInterface): void {} /** @internal */ - public onRpcImplInitialized(_definition: RpcInterfaceDefinition, _impl: RpcInterface): void { } + public onRpcImplInitialized(_definition: RpcInterfaceDefinition, _impl: RpcInterface): void {} /** @internal */ - public onRpcClientTerminated(_definition: RpcInterfaceDefinition, _client: RpcInterface): void { } + public onRpcClientTerminated(_definition: RpcInterfaceDefinition, _client: RpcInterface): void {} /** @internal */ - public onRpcImplTerminated(_definition: RpcInterfaceDefinition, _impl: RpcInterface): void { } + public onRpcImplTerminated(_definition: RpcInterfaceDefinition, _impl: RpcInterface): void {} } diff --git a/core/common/src/rpc/core/RpcPush.ts b/core/common/src/rpc/core/RpcPush.ts index 7830b5ab75d9..693a89be6449 100644 --- a/core/common/src/rpc/core/RpcPush.ts +++ b/core/common/src/rpc/core/RpcPush.ts @@ -64,8 +64,12 @@ export class RpcPushChannel { private _subscribers: RpcPushSubscription[] = []; public readonly name: string; public readonly service: RpcPushService; - public get id() { return RpcPushChannel.formatId(this.name, this.service); } - public get enabled() { return RpcPushChannel.enabled; } + public get id() { + return RpcPushChannel.formatId(this.name, this.service); + } + public get enabled() { + return RpcPushChannel.enabled; + } public subscribe(): RpcPushSubscription { const subscription = new RpcPushSubscription(this); diff --git a/core/common/src/rpc/core/RpcRegistry.ts b/core/common/src/rpc/core/RpcRegistry.ts index fc858d96e1fa..e66e8eca66f8 100644 --- a/core/common/src/rpc/core/RpcRegistry.ts +++ b/core/common/src/rpc/core/RpcRegistry.ts @@ -8,14 +8,14 @@ import { BentleyStatus } from "@itwin/core-bentley"; import { IModelError } from "../../IModelError"; -import { RpcConfiguration } from "./RpcConfiguration"; -import { RpcPendingQueue } from "./RpcPendingQueue"; -import { initializeRpcRequest } from "./RpcRequest"; -import { RpcRoutingToken } from "./RpcRoutingToken"; import { RpcInterface, RpcInterfaceDefinition, RpcInterfaceImplementation } from "../../RpcInterface"; import { RpcInterfaceEndpoints } from "../../RpcManager"; +import { RpcConfiguration } from "./RpcConfiguration"; import { RpcControlChannel } from "./RpcControl"; import { RpcOperation, RpcOperationPolicy } from "./RpcOperation"; +import { RpcPendingQueue } from "./RpcPendingQueue"; +import { initializeRpcRequest } from "./RpcRequest"; +import { RpcRoutingToken } from "./RpcRoutingToken"; /* eslint-disable deprecation/deprecation */ @@ -46,7 +46,13 @@ export class RpcRegistry { public static get instance() { if (!RpcRegistry._instance) { - const globalObj: any = typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}; + const globalObj: any = typeof global !== "undefined" + ? global + : typeof self !== "undefined" + ? self + : typeof window !== "undefined" + ? window + : {}; if (!globalObj[REGISTRY]) globalObj[REGISTRY] = new RpcRegistry(); @@ -106,7 +112,10 @@ export class RpcRegistry { return this.getImplForInterface(definition) as T; } - public registerImpl(definition: RpcInterfaceDefinition, implementation: RpcInterfaceImplementation) { + public registerImpl( + definition: RpcInterfaceDefinition, + implementation: RpcInterfaceImplementation, + ) { this.unregisterImpl(definition); this.implementationClasses.set(definition.interfaceName, implementation); } @@ -121,7 +130,10 @@ export class RpcRegistry { } } - public supplyImplInstance(definition: RpcInterfaceDefinition, instance: TImplementation): void { + public supplyImplInstance( + definition: RpcInterfaceDefinition, + instance: TImplementation, + ): void { this.suppliedImplementations.set(definition.interfaceName, instance); } @@ -161,7 +173,9 @@ export class RpcRegistry { return () => ++i; })(); - private instantiateImpl(definition: RpcInterfaceDefinition): TImplementation { + private instantiateImpl( + definition: RpcInterfaceDefinition, + ): TImplementation { this.checkInitialized(definition); const registeredImplementation = this.implementationClasses.get(definition.interfaceName) as RpcInterfaceImplementation; @@ -210,7 +224,7 @@ export class RpcRegistry { private interceptOperation(proxy: RpcInterface, operation: string) { const clientFunction = (proxy as any)[operation]; // eslint-disable-next-line prefer-arrow/prefer-arrow-functions - (proxy as any)[operation] = function () { + (proxy as any)[operation] = function() { const args = Array.from(arguments); args.push(operation); return clientFunction.apply(proxy, args); @@ -223,7 +237,7 @@ export class RpcRegistry { } private configureOperations(definition: RpcInterfaceDefinition) { - const proto = (definition.prototype as any); + const proto = definition.prototype as any; Object.getOwnPropertyNames(proto).forEach((operationName) => { if (operationName === "constructor" || operationName === "configurationSupplier") diff --git a/core/common/src/rpc/core/RpcRequest.ts b/core/common/src/rpc/core/RpcRequest.ts index 582a27a82d7f..b27c2d975793 100644 --- a/core/common/src/rpc/core/RpcRequest.ts +++ b/core/common/src/rpc/core/RpcRequest.ts @@ -28,22 +28,54 @@ export const aggregateLoad = { lastRequest: 0, lastResponse: 0 }; /** @internal */ export class ResponseLike implements Response { private _data: Promise; - public get body() { return null; } - public async arrayBuffer(): Promise { return this._data; } - public async blob(): Promise { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); } - public async formData(): Promise { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); } - public async json(): Promise { return this._data; } - public async text(): Promise { return this._data; } - public get bodyUsed() { return false; } - public get headers(): Headers { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); } - public get ok(): boolean { return this.status >= 200 && this.status <= 299; } - public get redirected() { return false; } - public get status() { return 200; } - public get statusText() { return ""; } - public get trailer(): Promise { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); } - public get type(): ResponseType { return "basic"; } - public get url() { return ""; } - public clone() { return { ...this }; } + public get body() { + return null; + } + public async arrayBuffer(): Promise { + return this._data; + } + public async blob(): Promise { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + } + public async formData(): Promise { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + } + public async json(): Promise { + return this._data; + } + public async text(): Promise { + return this._data; + } + public get bodyUsed() { + return false; + } + public get headers(): Headers { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + } + public get ok(): boolean { + return this.status >= 200 && this.status <= 299; + } + public get redirected() { + return false; + } + public get status() { + return 200; + } + public get statusText() { + return ""; + } + public get trailer(): Promise { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + } + public get type(): ResponseType { + return "basic"; + } + public get url() { + return ""; + } + public clone() { + return { ...this }; + } public constructor(data: any) { this._data = Promise.resolve(data); @@ -86,11 +118,16 @@ export type RpcRequestEventHandler = (type: RpcRequestEvent, request: RpcRequest /** Resolves "not found" responses for RPC requests. * @internal */ -export type RpcRequestNotFoundHandler = (request: RpcRequest, response: RpcNotFoundResponse, resubmit: () => void, reject: (reason?: any) => void) => void; +export type RpcRequestNotFoundHandler = ( + request: RpcRequest, + response: RpcNotFoundResponse, + resubmit: () => void, + reject: (reason?: any) => void, +) => void; class Cancellable { public promise: Promise; - public cancel() { } + public cancel() {} public constructor(task: Promise) { this.promise = new Promise((resolve, reject) => { @@ -133,7 +170,9 @@ export abstract class RpcRequest { public responseProtocolVersion = RpcProtocolVersion.None; /** All RPC requests that are currently in flight. */ - public static get activeRequests(): ReadonlyMap { return this._activeRequests; } + public static get activeRequests(): ReadonlyMap { + return this._activeRequests; + } /** Events raised by RpcRequest. See [[RpcRequestEvent]] */ public static readonly events: BeEvent = new BeEvent(); @@ -142,7 +181,9 @@ export abstract class RpcRequest { public static readonly notFoundHandlers: BeEvent = new BeEvent(); /** The aggregate operations profile of all active RPC interfaces. */ - public static get aggregateLoad(): RpcOperationsProfile { return aggregateLoad; } + public static get aggregateLoad(): RpcOperationsProfile { + return aggregateLoad; + } /** * The request for the current RPC operation. @@ -171,22 +212,32 @@ export abstract class RpcRequest { public readonly response: Promise; /** The status of this request. */ - public get status() { return this._status; } + public get status() { + return this._status; + } /** Extended status information for this request (if available). */ - public get extendedStatus() { return this._extendedStatus; } + public get extendedStatus() { + return this._extendedStatus; + } /** The last submission for this request. */ - public get lastSubmitted() { return this._lastSubmitted; } + public get lastSubmitted() { + return this._lastSubmitted; + } /** The last status update received for this request. */ - public get lastUpdated() { return this._lastUpdated; } + public get lastUpdated() { + return this._lastUpdated; + } /** The target interval (in milliseconds) between submission attempts for this request. */ public retryInterval: number; /** Whether a connection is active for this request. */ - public get connecting() { return this._connecting; } + public get connecting() { + return this._connecting; + } /** Whether this request is pending. */ public get pending(): boolean { @@ -214,12 +265,14 @@ export abstract class RpcRequest { public method: string; /** An attempt-specific value for when to next retry this request. */ - public get retryAfter() { return this._retryAfter; } + public get retryAfter() { + return this._retryAfter; + } /** Finds the first parameter of a given structural type if present. */ public findParameterOfType(requiredProperties: { [index: string]: string }): T | undefined { for (const param of this.parameters) { - if (typeof (param) === "object" && param !== null) { + if (typeof param === "object" && param !== null) { for (const prop of Object.getOwnPropertyNames(requiredProperties)) { if (prop in param && typeof (param[prop]) === requiredProperties[prop]) { return param; @@ -234,7 +287,6 @@ export abstract class RpcRequest { /** Finds the first IModelRpcProps parameter if present. */ public findTokenPropsParameter(): IModelRpcProps | undefined { return this.findParameterOfType({ iModelId: "string" }); - } /** The raw implementation response for this request. */ @@ -299,7 +351,8 @@ export abstract class RpcRequest { return false; } - return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory && this.responseProtocolVersion >= RpcProtocolVersion.IntroducedStatusCategory; + return RpcProtocol.protocolVersion >= RpcProtocolVersion.IntroducedStatusCategory && + this.responseProtocolVersion >= RpcProtocolVersion.IntroducedStatusCategory; } /* @internal */ @@ -337,7 +390,7 @@ export abstract class RpcRequest { this.operation.policy.sentCallback(this); const response = await this._sending.promise; - if (typeof (response) === "undefined") { + if (typeof response === "undefined") { return; } this._sending = undefined; @@ -456,7 +509,7 @@ export abstract class RpcRequest { try { const error = RpcMarshaling.deserialize(this.protocol, value); - const hasInfo = error && typeof (error) === "object" && error.hasOwnProperty("name") && error.hasOwnProperty("message"); + const hasInfo = error && typeof error === "object" && error.hasOwnProperty("name") && error.hasOwnProperty("message"); const name = hasInfo ? error.name : ""; const message = hasInfo ? error.message : ""; const errorNumber = (hasInfo && error.hasOwnProperty("errorNumber")) ? error.errorNumber : BentleyStatus.ERROR; diff --git a/core/common/src/rpc/core/RpcSessionInvocation.ts b/core/common/src/rpc/core/RpcSessionInvocation.ts index 5b482d9702c9..da75d2814b14 100644 --- a/core/common/src/rpc/core/RpcSessionInvocation.ts +++ b/core/common/src/rpc/core/RpcSessionInvocation.ts @@ -18,14 +18,18 @@ import { RpcRequest } from "./RpcRequest"; class SessionConfiguration extends RpcConfiguration { public interfaces = () => []; - public get protocol() { return SessionProtocol.instance; } + public get protocol() { + return SessionProtocol.instance; + } } class SessionProtocol extends RpcProtocol { public static instance = new SessionProtocol(); public requestType = RpcRequest; public override supportsStatusCategory = true; - constructor() { super(new SessionConfiguration()); } + constructor() { + super(new SessionConfiguration()); + } } /** @internal */ diff --git a/core/common/src/rpc/web/BentleyCloudRpcManager.ts b/core/common/src/rpc/web/BentleyCloudRpcManager.ts index d653401e49ab..726073428060 100644 --- a/core/common/src/rpc/web/BentleyCloudRpcManager.ts +++ b/core/common/src/rpc/web/BentleyCloudRpcManager.ts @@ -11,9 +11,9 @@ import { RpcManager } from "../../RpcManager"; import { RpcConfiguration } from "../core/RpcConfiguration"; import { RpcRequestEvent } from "../core/RpcConstants"; import { RpcRequest, RpcRequestEventHandler } from "../core/RpcRequest"; +import { RpcRoutingToken } from "../core/RpcRoutingToken"; import { BentleyCloudRpcProtocol } from "./BentleyCloudRpcProtocol"; import { OpenAPIInfo } from "./OpenAPI"; -import { RpcRoutingToken } from "../core/RpcRoutingToken"; /* eslint-disable deprecation/deprecation */ @@ -41,7 +41,8 @@ export abstract class BentleyCloudRpcConfiguration extends RpcConfiguration { public static readonly accessControl = { allowOrigin: "*", allowMethods: "POST, GET, OPTIONS", - allowHeaders: "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-Correlation-Id, X-Session-Id, X-Application-Id, X-Application-Version, X-User-Id, X-Protocol-Version", + allowHeaders: + "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-Correlation-Id, X-Session-Id, X-Application-Id, X-Application-Version, X-User-Id, X-Protocol-Version", }; /** @internal The protocol of the configuration. */ @@ -53,7 +54,11 @@ export abstract class BentleyCloudRpcConfiguration extends RpcConfiguration { */ export class BentleyCloudRpcManager extends RpcManager { /** @beta Initializes BentleyCloudRpcManager for the frontend of an application. */ - public static initializeClient(params: BentleyCloudRpcParams, interfaces: RpcInterfaceDefinition[], routing: RpcRoutingToken = RpcRoutingToken.default): BentleyCloudRpcConfiguration { + public static initializeClient( + params: BentleyCloudRpcParams, + interfaces: RpcInterfaceDefinition[], + routing: RpcRoutingToken = RpcRoutingToken.default, + ): BentleyCloudRpcConfiguration { return BentleyCloudRpcManager.performInitialization(params, interfaces, routing); } @@ -62,7 +67,11 @@ export class BentleyCloudRpcManager extends RpcManager { return BentleyCloudRpcManager.performInitialization(params, interfaces); } - private static performInitialization(params: BentleyCloudRpcParams, interfaces: RpcInterfaceDefinition[], routing: RpcRoutingToken = RpcRoutingToken.default): BentleyCloudRpcConfiguration { + private static performInitialization( + params: BentleyCloudRpcParams, + interfaces: RpcInterfaceDefinition[], + routing: RpcRoutingToken = RpcRoutingToken.default, + ): BentleyCloudRpcConfiguration { const protocol = class extends (params.protocol || BentleyCloudRpcProtocol) { public override pathPrefix = params.uriPrefix || ""; public info = params.info; diff --git a/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts b/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts index 4d3ae868ccaf..57e5e84b2b75 100644 --- a/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts +++ b/core/common/src/rpc/web/BentleyCloudRpcProtocol.ts @@ -10,12 +10,12 @@ import { BentleyStatus } from "@itwin/core-bentley"; import { IModelRpcProps } from "../../IModel"; import { IModelError } from "../../IModelError"; import { RpcConfiguration } from "../core/RpcConfiguration"; +import { SerializedRpcActivity } from "../core/RpcInvocation"; import { RpcOperation } from "../core/RpcOperation"; import { SerializedRpcOperation, SerializedRpcRequest } from "../core/RpcProtocol"; import { RpcRequest } from "../core/RpcRequest"; import { OpenAPIParameter } from "./OpenAPI"; import { WebAppRpcProtocol } from "./WebAppRpcProtocol"; -import { SerializedRpcActivity } from "../core/RpcInvocation"; /* eslint-disable deprecation/deprecation */ @@ -111,7 +111,9 @@ export abstract class BentleyCloudRpcProtocol extends WebAppRpcProtocol { appMode = AppMode.MilestoneReview; } - return `${prefix}/${appTitle}/${appVersion}/mode/${appMode}/context/${iTwinId}/imodel/${iModelId}${!!routeChangesetId ? `/changeset/${routeChangesetId}` : ""}/${operationId}`; + return `${prefix}/${appTitle}/${appVersion}/mode/${appMode}/context/${iTwinId}/imodel/${iModelId}${ + !!routeChangesetId ? `/changeset/${routeChangesetId}` : "" + }/${operationId}`; } /** @@ -144,7 +146,12 @@ export abstract class BentleyCloudRpcProtocol extends WebAppRpcProtocol { // Overwrite the key if it includes a : because its most likely a guid. We know what it should be based off of the url. // Leave it alone if its a non guid key. - return { key: tokenFromBody.key === undefined || tokenFromBody.key.includes(":") ? `${iModelId}:${changeset.id}` : tokenFromBody.key, iTwinId, iModelId, changeset }; + return { + key: tokenFromBody.key === undefined || tokenFromBody.key.includes(":") ? `${iModelId}:${changeset.id}` : tokenFromBody.key, + iTwinId, + iModelId, + changeset, + }; } /** Returns the OpenAPI-compatible URI path parameters for an RPC operation. diff --git a/core/common/src/rpc/web/BentleyCloudRpcRouting.swagger.json b/core/common/src/rpc/web/BentleyCloudRpcRouting.swagger.json index 701afeb96c4a..f1eb83e21792 100644 --- a/core/common/src/rpc/web/BentleyCloudRpcRouting.swagger.json +++ b/core/common/src/rpc/web/BentleyCloudRpcRouting.swagger.json @@ -108,4 +108,4 @@ ] } } -} \ No newline at end of file +} diff --git a/core/common/src/rpc/web/RpcMultipart.ts b/core/common/src/rpc/web/RpcMultipart.ts index 3f1211fdd5e6..87000ef304c1 100644 --- a/core/common/src/rpc/web/RpcMultipart.ts +++ b/core/common/src/rpc/web/RpcMultipart.ts @@ -6,8 +6,8 @@ * @module RpcInterface */ -import { BentleyStatus, IModelError } from "../../IModelError"; import { BackendBuffer, BackendReadable } from "../../BackendTypes"; +import { BentleyStatus, IModelError } from "../../IModelError"; import { RpcSerializedValue } from "../core/RpcMarshaling"; import { HttpServerRequest } from "../web/WebAppRpcProtocol"; @@ -66,4 +66,3 @@ export class RpcMultipart { }, }; } - diff --git a/core/common/src/rpc/web/WebAppRpcLogging.ts b/core/common/src/rpc/web/WebAppRpcLogging.ts index 7fb37f16a997..dfd4f7f67474 100644 --- a/core/common/src/rpc/web/WebAppRpcLogging.ts +++ b/core/common/src/rpc/web/WebAppRpcLogging.ts @@ -35,7 +35,7 @@ export abstract class WebAppRpcLogging { private static get backend(): WebAppRpcLogging { const instance = (globalThis as any)[BACKEND]; - if (typeof (instance) === "undefined") { + if (typeof instance === "undefined") { throw new IModelError(BentleyStatus.ERROR, "Backend logging is not initialized."); } @@ -44,7 +44,7 @@ export abstract class WebAppRpcLogging { private static get frontend(): WebAppRpcLogging { const instance = (globalThis as any)[FRONTEND]; - if (typeof (instance) === "undefined") { + if (typeof instance === "undefined") { throw new IModelError(BentleyStatus.ERROR, "Frontend logging is not initialized."); } @@ -91,7 +91,9 @@ export abstract class WebAppRpcLogging { return "unknown.unknown"; } - const interfaceName = typeof (operation.interfaceDefinition) === "string" ? operation.interfaceDefinition : operation.interfaceDefinition.interfaceName; + const interfaceName = typeof (operation.interfaceDefinition) === "string" + ? operation.interfaceDefinition + : operation.interfaceDefinition.interfaceName; const operationName = operation.operationName; return `${interfaceName}.${operationName}`; } @@ -113,7 +115,13 @@ export abstract class WebAppRpcLogging { })); } - protected logResponse(loggerCategory: string, message: string, object: WebAppRpcRequest | SerializedRpcRequest, status: number, elapsed: number): void { + protected logResponse( + loggerCategory: string, + message: string, + object: WebAppRpcRequest | SerializedRpcRequest, + status: number, + elapsed: number, + ): void { const operationDescriptor = this.buildOperationDescriptor(object.operation); const pathIds = this.findPathIds(object.path); @@ -135,10 +143,20 @@ export abstract class WebAppRpcLogging { class WebAppRpcLoggingFrontend extends WebAppRpcLogging { protected override async logProtocolEvent(event: RpcProtocolEvent, object: WebAppRpcRequest): Promise { switch (event) { - case RpcProtocolEvent.RequestCreated: return this.logRequest(CommonLoggerCategory.RpcInterfaceFrontend, "RpcInterface.frontend.request", object); - case RpcProtocolEvent.ResponseLoaded: return this.logResponse(CommonLoggerCategory.RpcInterfaceFrontend, "RpcInterface.frontend.response", object, object.metadata.status, object.elapsed); - case RpcProtocolEvent.ConnectionErrorReceived: return this.logErrorFrontend("RpcInterface.frontend.connectionError", object); - case RpcProtocolEvent.ConnectionAborted: return this.logErrorFrontend("RpcInterface.frontend.connectionAborted", object); + case RpcProtocolEvent.RequestCreated: + return this.logRequest(CommonLoggerCategory.RpcInterfaceFrontend, "RpcInterface.frontend.request", object); + case RpcProtocolEvent.ResponseLoaded: + return this.logResponse( + CommonLoggerCategory.RpcInterfaceFrontend, + "RpcInterface.frontend.response", + object, + object.metadata.status, + object.elapsed, + ); + case RpcProtocolEvent.ConnectionErrorReceived: + return this.logErrorFrontend("RpcInterface.frontend.connectionError", object); + case RpcProtocolEvent.ConnectionAborted: + return this.logErrorFrontend("RpcInterface.frontend.connectionAborted", object); } } diff --git a/core/common/src/rpc/web/WebAppRpcProtocol.ts b/core/common/src/rpc/web/WebAppRpcProtocol.ts index 946cd371cf58..b86d9936cbd4 100644 --- a/core/common/src/rpc/web/WebAppRpcProtocol.ts +++ b/core/common/src/rpc/web/WebAppRpcProtocol.ts @@ -7,8 +7,8 @@ */ import { BentleyError, Logger } from "@itwin/core-bentley"; -import { CommonLoggerCategory } from "../../CommonLoggerCategory"; import { BackendReadable, BackendWritable } from "../../BackendTypes"; +import { CommonLoggerCategory } from "../../CommonLoggerCategory"; import { RpcConfiguration } from "../core/RpcConfiguration"; import { RpcContentType, RpcRequestStatus, WEB_RPC_CONSTANTS } from "../core/RpcConstants"; import { RpcOperation } from "../core/RpcOperation"; @@ -121,34 +121,56 @@ export abstract class WebAppRpcProtocol extends RpcProtocol { /** Supplies the status corresponding to a protocol-specific code value. */ public override getStatus(code: number): RpcRequestStatus { switch (code) { - case 404: return RpcRequestStatus.NotFound; - case 202: return RpcRequestStatus.Pending; - case 200: return RpcRequestStatus.Resolved; - case 500: return RpcRequestStatus.Rejected; - case 204: return RpcRequestStatus.NoContent; - case 502: return RpcRequestStatus.BadGateway; - case 503: return RpcRequestStatus.ServiceUnavailable; - case 504: return RpcRequestStatus.GatewayTimeout; - case 408: return RpcRequestStatus.RequestTimeout; - case 429: return RpcRequestStatus.TooManyRequests; - default: return RpcRequestStatus.Unknown; + case 404: + return RpcRequestStatus.NotFound; + case 202: + return RpcRequestStatus.Pending; + case 200: + return RpcRequestStatus.Resolved; + case 500: + return RpcRequestStatus.Rejected; + case 204: + return RpcRequestStatus.NoContent; + case 502: + return RpcRequestStatus.BadGateway; + case 503: + return RpcRequestStatus.ServiceUnavailable; + case 504: + return RpcRequestStatus.GatewayTimeout; + case 408: + return RpcRequestStatus.RequestTimeout; + case 429: + return RpcRequestStatus.TooManyRequests; + default: + return RpcRequestStatus.Unknown; } } /** Supplies the protocol-specific code corresponding to a status value. */ public override getCode(status: RpcRequestStatus): number { switch (status) { - case RpcRequestStatus.NotFound: return 404; - case RpcRequestStatus.Pending: return 202; - case RpcRequestStatus.Resolved: return 200; - case RpcRequestStatus.Rejected: return 500; - case RpcRequestStatus.NoContent: return 204; - case RpcRequestStatus.BadGateway: return 502; - case RpcRequestStatus.ServiceUnavailable: return 503; - case RpcRequestStatus.GatewayTimeout: return 504; - case RpcRequestStatus.RequestTimeout: return 408; - case RpcRequestStatus.TooManyRequests: return 429; - default: return 501; + case RpcRequestStatus.NotFound: + return 404; + case RpcRequestStatus.Pending: + return 202; + case RpcRequestStatus.Resolved: + return 200; + case RpcRequestStatus.Rejected: + return 500; + case RpcRequestStatus.NoContent: + return 204; + case RpcRequestStatus.BadGateway: + return 502; + case RpcRequestStatus.ServiceUnavailable: + return 503; + case RpcRequestStatus.GatewayTimeout: + return 504; + case RpcRequestStatus.RequestTimeout: + return 408; + case RpcRequestStatus.TooManyRequests: + return 429; + default: + return 501; } } @@ -162,7 +184,9 @@ export abstract class WebAppRpcProtocol extends RpcProtocol { /** An OpenAPI-compatible description of this protocol. * @internal */ - public get openAPIDescription() { return new RpcOpenAPIDescription(this); } + public get openAPIDescription() { + return new RpcOpenAPIDescription(this); + } /** Returns the OpenAPI-compatible URI path parameters for an RPC operation. * @internal diff --git a/core/common/src/rpc/web/WebAppRpcRequest.ts b/core/common/src/rpc/web/WebAppRpcRequest.ts index a412efa08361..95ab7931bfc2 100644 --- a/core/common/src/rpc/web/WebAppRpcRequest.ts +++ b/core/common/src/rpc/web/WebAppRpcRequest.ts @@ -29,7 +29,9 @@ export class WebAppRpcRequest extends RpcRequest { private _loading: boolean = false; private _request: RequestInit = {}; private _pathSuffix: string = ""; - private get _headers() { return this._request.headers as { [key: string]: string }; } + private get _headers() { + return this._request.headers as { [key: string]: string }; + } /** The maximum size permitted for an encoded component in a URL. * Note that some backends limit the total cumulative request size. Our current node backends accept requests with a max size of 16 kb. @@ -98,7 +100,7 @@ export class WebAppRpcRequest extends RpcRequest { try { resolve(await this.performFetch()); } catch (reason) { - reject(new ServerError(-1, typeof (reason) === "string" ? reason : "Server connection error.")); + reject(new ServerError(-1, typeof reason === "string" ? reason : "Server connection error.")); } }); } @@ -170,7 +172,7 @@ export class WebAppRpcRequest extends RpcRequest { return; this._loading = false; - reject(new ServerError(this.metadata.status, typeof (reason) === "string" ? reason : "Unknown server response error.")); + reject(new ServerError(this.metadata.status, typeof reason === "string" ? reason : "Unknown server response error.")); } }); } @@ -189,7 +191,7 @@ export class WebAppRpcRequest extends RpcRequest { const requestClass = this.supplyRequest(); const fetchFunction = this.supplyFetch(); - const path = new URL(this.path, typeof (location) !== "undefined" ? location.origin : undefined); + const path = new URL(this.path, typeof location !== "undefined" ? location.origin : undefined); if (this._pathSuffix) { const params = new URLSearchParams(); params.set("parameters", this._pathSuffix); @@ -267,7 +269,13 @@ export class WebAppRpcRequest extends RpcRequest { /** @internal */ public static backend = { - sendResponse: async (_protocol: WebAppRpcProtocol, _request: SerializedRpcRequest, _fulfillment: RpcRequestFulfillment, _req: HttpServerRequest, _res: HttpServerResponse): Promise => { + sendResponse: async ( + _protocol: WebAppRpcProtocol, + _request: SerializedRpcRequest, + _fulfillment: RpcRequestFulfillment, + _req: HttpServerRequest, + _res: HttpServerResponse, + ): Promise => { throw new IModelError(BentleyStatus.ERROR, "Not bound."); }, parseRequest: async (_protocol: WebAppRpcProtocol, _req: HttpServerRequest): Promise => { diff --git a/core/common/src/test/AnalysisStyle.test.ts b/core/common/src/test/AnalysisStyle.test.ts index 171a8094e733..9fa9416a0357 100644 --- a/core/common/src/test/AnalysisStyle.test.ts +++ b/core/common/src/test/AnalysisStyle.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { ThematicGradientSettings } from "../ThematicDisplay"; import { AnalysisStyle, AnalysisStyleProps, LegacyAnalysisStyleProps } from "../AnalysisStyle"; +import { ThematicGradientSettings } from "../ThematicDisplay"; describe("AnalysisStyle", () => { it("round-trips through JSON", () => { function roundTrip(props: AnalysisStyleProps | undefined, expected: AnalysisStyleProps | "input"): void { if ("input" === expected) - expected = props ?? { }; + expected = props ?? {}; const style = AnalysisStyle.fromJSON(props); const actual = style.toJSON(); @@ -22,8 +22,8 @@ describe("AnalysisStyle", () => { expect(expected).not.to.deep.equal({}); } - roundTrip({ }, "input"); - roundTrip(undefined, { }); + roundTrip({}, "input"); + roundTrip(undefined, {}); roundTrip({ normalChannelName: "normals" }, "input"); roundTrip({ normalChannelName: "" }, "input"); @@ -53,12 +53,20 @@ describe("AnalysisStyle", () => { expect(src.clone(changed).toJSON()).to.deep.equal(expected); } - expectClone({ }, props); + expectClone({}, props); expectClone({ normalChannelName: undefined }, { displacement: props.displacement, scalar: props.scalar }); - expectClone({ displacement: undefined, normalChannelName: undefined, scalar: undefined }, { }); + expectClone({ displacement: undefined, normalChannelName: undefined, scalar: undefined }, {}); expectClone({ normalChannelName: "abnormals" }, { normalChannelName: "abnormals", displacement: props.displacement, scalar: props.scalar }); - expectClone({ displacement: { channelName: "disp" } }, { displacement: { channelName: "disp" }, normalChannelName: "normals", scalar: props.scalar }); - expectClone({ displacement: { channelName: "disp", scale: -2 } }, { displacement: { channelName: "disp", scale: -2 }, normalChannelName: "normals", scalar: props.scalar }); + expectClone({ displacement: { channelName: "disp" } }, { + displacement: { channelName: "disp" }, + normalChannelName: "normals", + scalar: props.scalar, + }); + expectClone({ displacement: { channelName: "disp", scale: -2 } }, { + displacement: { channelName: "disp", scale: -2 }, + normalChannelName: "normals", + scalar: props.scalar, + }); expectClone( { scalar: { channelName: "s", range: [-5, 15] } }, { scalar: { channelName: "s", range: [-5, 15] }, displacement: props.displacement, normalChannelName: "normals" }, @@ -69,7 +77,11 @@ describe("AnalysisStyle", () => { ); expectClone( { scalar: { channelName: "s", range: [-5, 15], thematicSettings: { stepCount: 1234 } } }, - { scalar: { channelName: "s", range: [-5, 15], thematicSettings: { stepCount: 1234 } }, displacement: props.displacement, normalChannelName: "normals" }, + { + scalar: { channelName: "s", range: [-5, 15], thematicSettings: { stepCount: 1234 } }, + displacement: props.displacement, + normalChannelName: "normals", + }, ); }); @@ -80,13 +92,13 @@ describe("AnalysisStyle", () => { expect(actual).to.deep.equal(expected); } - roundTrip({ }, { }); + roundTrip({}, {}); roundTrip({ normalChannelName: "normals" }, { normalChannelName: "normals" }); roundTrip( { displacementChannelName: "disp" }, { displacement: { channelName: "disp" } }, ); - roundTrip({ displacementScale: 42 }, { }); + roundTrip({ displacementScale: 42 }, {}); roundTrip( { displacementChannelName: "disp", displacementScale: 42 }, { displacement: { channelName: "disp", scale: 42 } }, @@ -99,8 +111,8 @@ describe("AnalysisStyle", () => { { scalarChannelName: "scalar", scalarRange: [1, 2], scalarThematicSettings: { stepCount: 6 } }, { scalar: { channelName: "scalar", range: [1, 2], thematicSettings: { stepCount: 6 } } }, ); - roundTrip({ scalarChannelName: "scalar" }, { }); - roundTrip({ scalarRange: [0, 1] }, { }); - roundTrip({ scalarThematicSettings: { stepCount: 6 } }, { }); + roundTrip({ scalarChannelName: "scalar" }, {}); + roundTrip({ scalarRange: [0, 1] }, {}); + roundTrip({ scalarThematicSettings: { stepCount: 6 } }, {}); }); }); diff --git a/core/common/src/test/BackgroundMapSettings.test.ts b/core/common/src/test/BackgroundMapSettings.test.ts index ed30f647c1b8..586c7f285bed 100644 --- a/core/common/src/test/BackgroundMapSettings.test.ts +++ b/core/common/src/test/BackgroundMapSettings.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { BackgroundMapSettings, GlobeMode, PersistentBackgroundMapProps } from "../BackgroundMapSettings"; import { BackgroundMapType } from "../BackgroundMapProvider"; +import { BackgroundMapSettings, GlobeMode, PersistentBackgroundMapProps } from "../BackgroundMapSettings"; import { TerrainHeightOriginMode } from "../TerrainSettings"; describe("BackgroundMapSettings", () => { diff --git a/core/common/src/test/Cartographic.test.ts b/core/common/src/test/Cartographic.test.ts index dfa136e5125f..3684df944cd5 100644 --- a/core/common/src/test/Cartographic.test.ts +++ b/core/common/src/test/Cartographic.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, it } from "vitest"; import { Angle } from "@itwin/core-geometry"; +import { assert, describe, it } from "vitest"; import { Cartographic } from "../geometry/Cartographic"; describe("Cartographic", () => { diff --git a/core/common/src/test/ClipStyle.test.ts b/core/common/src/test/ClipStyle.test.ts index a307b3450002..c5456293d0e5 100644 --- a/core/common/src/test/ClipStyle.test.ts +++ b/core/common/src/test/ClipStyle.test.ts @@ -3,11 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { - ClipStyle, - ClipStyleProps, - CutStyle, -} from "../ClipStyle"; +import { ClipStyle, ClipStyleProps, CutStyle } from "../ClipStyle"; import { DisplayStyleSettings, DisplayStyleSettingsProps } from "../DisplayStyleSettings"; describe("ClipStyle", () => { @@ -27,7 +23,7 @@ describe("ClipStyle", () => { roundTrip({}, undefined); roundTrip({ produceCutGeometry: false }, undefined); roundTrip({ cutStyle: undefined, produceCutGeometry: false }, undefined); - roundTrip(ClipStyle.create({produceCutGeometry: false, colorizeIntersection: false, cutStyle: CutStyle.defaults}).toJSON(), undefined); + roundTrip(ClipStyle.create({ produceCutGeometry: false, colorizeIntersection: false, cutStyle: CutStyle.defaults }).toJSON(), undefined); roundTrip({ cutStyle: CutStyle.defaults.toJSON(), produceCutGeometry: false, @@ -43,7 +39,7 @@ describe("ClipStyle", () => { roundTrip({ insideColor: undefined, outsideColor: undefined }, undefined); roundTrip({ colorizeIntersection: undefined, intersectionStyle: undefined }, undefined); - roundTrip({ colorizeIntersection: true, intersectionStyle: { color:{ r: 255, g: 0, b: 0 }, width: 5 }}, "input"); + roundTrip({ colorizeIntersection: true, intersectionStyle: { color: { r: 255, g: 0, b: 0 }, width: 5 } }, "input"); }); it("should serialize to DisplayStyleSettings", () => { @@ -62,7 +58,7 @@ describe("ClipStyle", () => { outsideColor: { r: 100, g: 255, b: 1 }, cutStyle: { appearance: { transparency: 0.5 } }, colorizeIntersection: true, - intersectionStyle: { color:{ r: 0, g: 100, b: 200 }, width: 3 }, + intersectionStyle: { color: { r: 0, g: 100, b: 200 }, width: 3 }, }; details.clipStyle = ClipStyle.fromJSON(styleProps); expect(details.clipStyle.matchesDefaults).to.be.false; @@ -85,7 +81,7 @@ describe("ClipStyle", () => { outsideColor: { r: 100, g: 255, b: 1 }, cutStyle: { appearance: { transparency: 0.5 } }, colorizeIntersection: true, - intersectionStyle: { color:{ r: 0, g: 100, b: 200 }, width: 3 }, + intersectionStyle: { color: { r: 0, g: 100, b: 200 }, width: 3 }, }; details.clipStyle = ClipStyle.fromJSON(styleProps); diff --git a/core/common/src/test/ColorDef.test.ts b/core/common/src/test/ColorDef.test.ts index 5606dbc28489..dd148bdcb189 100644 --- a/core/common/src/test/ColorDef.test.ts +++ b/core/common/src/test/ColorDef.test.ts @@ -128,7 +128,6 @@ describe("ColorDef", () => { assert.equal(0, t2.r); assert.equal(0, t2.b); assert.equal(100, t2.t); - }); it("determines whether string and numeric values represent valid colors", () => { diff --git a/core/common/src/test/ConcurrentQuery.test.ts b/core/common/src/test/ConcurrentQuery.test.ts index 53b3221d2668..c1dd398688e6 100644 --- a/core/common/src/test/ConcurrentQuery.test.ts +++ b/core/common/src/test/ConcurrentQuery.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Point2d, Point3d } from "@itwin/core-geometry"; -import { assert, describe, it } from "vitest"; import { Base64 } from "js-base64"; +import { assert, describe, it } from "vitest"; import { QueryBinder, QueryParamType } from "../ConcurrentQuery"; describe("QueryBinder", () => { diff --git a/core/common/src/test/ContextRealityModel.test.ts b/core/common/src/test/ContextRealityModel.test.ts index a1615a84dd36..dd670a5d72cc 100644 --- a/core/common/src/test/ContextRealityModel.test.ts +++ b/core/common/src/test/ContextRealityModel.test.ts @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { beforeEach, describe, expect, it } from "vitest"; -import { - ContextRealityModel, ContextRealityModelProps, ContextRealityModels, ContextRealityModelsContainer, -} from "../ContextRealityModel"; -import { SpatialClassifier, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay } from "../SpatialClassification"; -import { PlanarClipMaskMode, PlanarClipMaskSettings } from "../PlanarClipMask"; +import { ContextRealityModel, ContextRealityModelProps, ContextRealityModels, ContextRealityModelsContainer } from "../ContextRealityModel"; import { FeatureAppearance } from "../FeatureSymbology"; +import { PlanarClipMaskMode, PlanarClipMaskSettings } from "../PlanarClipMask"; +import { SpatialClassifier, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay } from "../SpatialClassification"; describe("ContextRealityModel", () => { function makeModel(props: ContextRealityModelProps): ContextRealityModel { @@ -35,7 +33,9 @@ describe("ContextRealityModel", () => { m = makeModel({ rdSourceKey: { - provider: "ContextShare", format: "ThreeDTile", id: "dummy", + provider: "ContextShare", + format: "ThreeDTile", + id: "dummy", }, tilesetUrl: "b", name: "c", @@ -43,12 +43,20 @@ describe("ContextRealityModel", () => { realityDataId: "e", appearanceOverrides: { transparency: 0.5 }, classifiers: [{ - modelId: "0x1", expand: 2, name: "3", flags: { - inside: SpatialClassifierInsideDisplay.On, outside: SpatialClassifierOutsideDisplay.Off, + modelId: "0x1", + expand: 2, + name: "3", + flags: { + inside: SpatialClassifierInsideDisplay.On, + outside: SpatialClassifierOutsideDisplay.Off, }, }], orbitGtBlob: { - rdsUrl: "rdsUrl", containerName: "container", blobFileName: "blob", sasToken: "token", accountName: "account", + rdsUrl: "rdsUrl", + containerName: "container", + blobFileName: "blob", + sasToken: "token", + accountName: "account", }, planarClipMask: { mode: PlanarClipMaskMode.Priority }, invisible: false, @@ -71,8 +79,12 @@ describe("ContextRealityModel", () => { planarClipMask: { mode: PlanarClipMaskMode.Priority, priority: 321 }, appearanceOverrides: { transparency: 0.5 }, classifiers: [{ - modelId: "0x1", expand: 2, name: "3", flags: { - inside: SpatialClassifierInsideDisplay.On, outside: SpatialClassifierOutsideDisplay.Off, + modelId: "0x1", + expand: 2, + name: "3", + flags: { + inside: SpatialClassifierInsideDisplay.On, + outside: SpatialClassifierOutsideDisplay.Off, }, }], }; @@ -96,26 +108,42 @@ describe("ContextRealityModel", () => { planarClipMask: { mode: PlanarClipMaskMode.Priority, priority: 123 }, appearanceOverrides: { weight: 5 }, classifiers: [{ - modelId: "0x1", expand: 2, name: "3", flags: { - inside: SpatialClassifierInsideDisplay.On, outside: SpatialClassifierOutsideDisplay.Off, + modelId: "0x1", + expand: 2, + name: "3", + flags: { + inside: SpatialClassifierInsideDisplay.On, + outside: SpatialClassifierOutsideDisplay.Off, }, }, { - modelId: "0x123", name: "new", expand: 0, isActive: false, flags: { - inside: SpatialClassifierInsideDisplay.ElementColor, outside: SpatialClassifierOutsideDisplay.Dimmed, + modelId: "0x123", + name: "new", + expand: 0, + isActive: false, + flags: { + inside: SpatialClassifierInsideDisplay.ElementColor, + outside: SpatialClassifierOutsideDisplay.Dimmed, }, }], }); }); it("defaults tilesetUrl to empty string", () => { - const m = makeModel({ } as unknown as ContextRealityModelProps); + const m = makeModel({} as unknown as ContextRealityModelProps); expect(m.url).to.equal(""); }); it("normalizes JSON when cloning", () => { const props: ContextRealityModelProps = { - rdSourceKey: undefined, tilesetUrl: "a", name: "", description: undefined, realityDataId: "", appearanceOverrides: undefined, - classifiers: undefined, orbitGtBlob: undefined, planarClipMask: undefined, + rdSourceKey: undefined, + tilesetUrl: "a", + name: "", + description: undefined, + realityDataId: "", + appearanceOverrides: undefined, + classifiers: undefined, + orbitGtBlob: undefined, + planarClipMask: undefined, }; (props as any).tilesetUrl = undefined; @@ -126,7 +154,9 @@ describe("ContextRealityModel", () => { it("clones deeply", () => { const props = { rdSourceKey: { - provider: "ContextShare", format: "ThreeDTile", id: "dummy", + provider: "ContextShare", + format: "ThreeDTile", + id: "dummy", }, tilesetUrl: "b", name: "c", @@ -134,12 +164,20 @@ describe("ContextRealityModel", () => { realityDataId: "e", appearanceOverrides: { rgb: { r: 1, g: 2, b: 3 } }, classifiers: [{ - modelId: "0x1", expand: 2, name: "3", flags: { - inside: SpatialClassifierInsideDisplay.On, outside: SpatialClassifierOutsideDisplay.Off, + modelId: "0x1", + expand: 2, + name: "3", + flags: { + inside: SpatialClassifierInsideDisplay.On, + outside: SpatialClassifierOutsideDisplay.Off, }, }], orbitGtBlob: { - rdsUrl: "rdsUrl", containerName: "container", blobFileName: "blob", sasToken: "token", accountName: "account", + rdsUrl: "rdsUrl", + containerName: "container", + blobFileName: "blob", + sasToken: "token", + accountName: "account", }, planarClipMask: { mode: PlanarClipMaskMode.Priority }, }; @@ -200,11 +238,13 @@ describe("ContextRealityModels", () => { it("populates from JSON", () => { expect(new ContextRealityModels({}).models.length).to.equal(0); - const props = { contextRealityModels: [ - { tilesetUrl: "a" }, - { tilesetUrl: "b", name: "bb" }, - { tilesetUrl: "c", description: "ccc" }, - ]}; + const props = { + contextRealityModels: [ + { tilesetUrl: "a" }, + { tilesetUrl: "b", name: "bb" }, + { tilesetUrl: "c", description: "ccc" }, + ], + }; const models = new ContextRealityModels(props).models; expect(models.length).to.equal(3); @@ -212,7 +252,7 @@ describe("ContextRealityModels", () => { }); it("adds models", () => { - const container: ContextRealityModelsContainer = { }; + const container: ContextRealityModelsContainer = {}; const models = new ContextRealityModels(container); expect(models.models.length).to.equal(0); expect(container.contextRealityModels).to.be.undefined; @@ -230,14 +270,20 @@ describe("ContextRealityModels", () => { expectProps(container.contextRealityModels, [{ tilesetUrl: "a", }, { - tilesetUrl: "b", name: "bb", description: "bbb", + tilesetUrl: "b", + name: "bb", + description: "bbb", }]); }); it("deletes models", () => { - const container = { contextRealityModels: [ - { tilesetUrl: "a" }, { tilesetUrl: "b" }, { tilesetUrl: "c" }, - ]}; + const container = { + contextRealityModels: [ + { tilesetUrl: "a" }, + { tilesetUrl: "b" }, + { tilesetUrl: "c" }, + ], + }; const models = new ContextRealityModels(container); expect(models.models.length).to.equal(3); @@ -252,13 +298,13 @@ describe("ContextRealityModels", () => { expect(models.delete(b)).to.be.true; expect(models.models.length).to.equal(2); expect(models.models.indexOf(b)).to.equal(-1); - expectProps(container.contextRealityModels, [ {tilesetUrl: "a"}, {tilesetUrl: "c"} ]); + expectProps(container.contextRealityModels, [{ tilesetUrl: "a" }, { tilesetUrl: "c" }]); expect(models.delete(b)).to.be.false; expect(models.delete(c)).to.be.true; expect(models.models.length).to.equal(1); expect(models.models.indexOf(c)).to.equal(-1); - expectProps(container.contextRealityModels, [ {tilesetUrl: "a"} ]); + expectProps(container.contextRealityModels, [{ tilesetUrl: "a" }]); expect(models.delete(c)).to.be.false; expect(models.delete(a)).to.be.true; @@ -299,14 +345,14 @@ describe("ContextRealityModels", () => { }); it("updates models", () => { - const container = { contextRealityModels: [{tilesetUrl: "a"}, {tilesetUrl: "b"}] }; + const container = { contextRealityModels: [{ tilesetUrl: "a" }, { tilesetUrl: "b" }] }; const models = new ContextRealityModels(container); const a = models.models[0]; const a1 = models.update(a, { name: "aa", description: "aaa" }); expect(models.models.indexOf(a)).to.equal(-1); expect(models.models.indexOf(a1)).to.equal(0); - expectProps(container.contextRealityModels, [{tilesetUrl: "a", name: "aa", description: "aaa"}, {tilesetUrl: "b"}]); + expectProps(container.contextRealityModels, [{ tilesetUrl: "a", name: "aa", description: "aaa" }, { tilesetUrl: "b" }]); expect(() => models.update(a, { name: "aaaa" })).to.throw(Error); @@ -314,15 +360,15 @@ describe("ContextRealityModels", () => { expect(a2.url).to.equal("a2"); expect(a2.name).to.be.equal(""); expect(a2.description).to.equal("aaa"); - expectProps(container.contextRealityModels, [{tilesetUrl: "a2", description: "aaa"}, {tilesetUrl: "b"}]); + expectProps(container.contextRealityModels, [{ tilesetUrl: "a2", description: "aaa" }, { tilesetUrl: "b" }]); - const a3 = models.update(a2, {tilesetUrl: undefined}); + const a3 = models.update(a2, { tilesetUrl: undefined }); expect(a3.url).to.equal("a2"); - expectProps(container.contextRealityModels, [{tilesetUrl: "a2", description: "aaa"}, {tilesetUrl: "b"}]); + expectProps(container.contextRealityModels, [{ tilesetUrl: "a2", description: "aaa" }, { tilesetUrl: "b" }]); }); it("instantiates correct type", () => { - class MyRealityModel extends ContextRealityModel { } + class MyRealityModel extends ContextRealityModel {} const container = { contextRealityModels: [{ tilesetUrl: "a" }] }; let models = new ContextRealityModels(container); @@ -351,7 +397,7 @@ describe("ContextRealityModels", () => { type ModelEvent = [string, "add" | "delete" | "update"]; const events: ModelEvent[] = []; - const models = new ContextRealityModels({ contextRealityModels: [{tilesetUrl: "a"}] }); + const models = new ContextRealityModels({ contextRealityModels: [{ tilesetUrl: "a" }] }); models.onChanged.addListener((prev, cur) => { expect(undefined !== prev || undefined !== cur).to.be.true; if (prev) @@ -364,9 +410,9 @@ describe("ContextRealityModels", () => { events.push([model.url, prev ? (cur ? "update" : "delete") : "add"]); }); - models.add({tilesetUrl: "b"}); - models.update(models.models[0], {name: "aa"}); - models.replace(models.models[1], {tilesetUrl: "bb"}); + models.add({ tilesetUrl: "b" }); + models.update(models.models[0], { name: "aa" }); + models.replace(models.models[1], { tilesetUrl: "bb" }); models.delete(models.models[0]); models.clear(); @@ -387,7 +433,7 @@ describe("ContextRealityModels", () => { beforeEach(() => { events.length = 0; - models = new ContextRealityModels({ contextRealityModels: [{tilesetUrl: "a"}, {tilesetUrl: "b"}] }); + models = new ContextRealityModels({ contextRealityModels: [{ tilesetUrl: "a" }, { tilesetUrl: "b" }] }); models.onPlanarClipMaskChanged.addListener((model) => events.push([model.url, "mask"])); models.onAppearanceOverridesChanged.addListener((model) => events.push([model.url, "appearance"])); models.onInvisibleChanged.addListener((model) => events.push([model.url, "invisible"])); @@ -407,12 +453,12 @@ describe("ContextRealityModels", () => { models.models[0].invisible = true; expectEvents([ - [ "a", "mask" ], - [ "b", "appearance" ], - [ "b", "mask" ], - [ "b", "invisible" ], - [ "a", "appearance" ], - [ "a", "invisible" ], + ["a", "mask"], + ["b", "appearance"], + ["b", "mask"], + ["b", "invisible"], + ["a", "appearance"], + ["a", "invisible"], ]); }); @@ -429,8 +475,8 @@ describe("ContextRealityModels", () => { m1.appearanceOverrides = FeatureAppearance.fromJSON({ weight: 2 }); expectEvents([ - [ "a", "mask" ], - [ "b", "appearance" ], + ["a", "mask"], + ["b", "appearance"], ]); }); @@ -445,10 +491,10 @@ describe("ContextRealityModels", () => { m2.planarClipMaskSettings = undefined; m3.invisible = true; expectEvents([ - [ "aa", "appearance" ], - [ "b", "appearance" ], - [ "c", "mask" ], - [ "d", "invisible" ], + ["aa", "appearance"], + ["b", "appearance"], + ["c", "mask"], + ["d", "invisible"], ]); }); }); diff --git a/core/common/src/test/ContourDisplay.test.ts b/core/common/src/test/ContourDisplay.test.ts index 8f6ba8d493b7..4fe164ab8373 100644 --- a/core/common/src/test/ContourDisplay.test.ts +++ b/core/common/src/test/ContourDisplay.test.ts @@ -61,37 +61,37 @@ describe("ContourDisplay", () => { // modify a group const groupsA = contourDisplayA.groups; - let modifiedGroup = groupsA[0].clone({name: "test 2"}); + let modifiedGroup = groupsA[0].clone({ name: "test 2" }); expect(groupsA[0].equals(modifiedGroup)).to.be.false; // ensure old group and modified group do not match - contourDisplayB = contourDisplayA.clone({groups: [ modifiedGroup ]}); + contourDisplayB = contourDisplayA.clone({ groups: [modifiedGroup] }); expect(contourDisplayA.equals(contourDisplayB)).to.be.false; // ensure the main object itself no longer matches // modify a contour - let modifiedContour = groupsA[0].contourDef.clone({showGeometry: true}); + let modifiedContour = groupsA[0].contourDef.clone({ showGeometry: true }); expect(modifiedContour.equals(groupsA[0].contourDef)).to.be.false; // ensure the old contour and modified contour do not match - modifiedGroup = groupsA[0].clone({contourDef: modifiedContour}); + modifiedGroup = groupsA[0].clone({ contourDef: modifiedContour }); expect(groupsA[0].equals(modifiedGroup)).to.be.false; // ensure old group and modified group do not match - contourDisplayB = contourDisplayA.clone({groups: [ modifiedGroup ]}); + contourDisplayB = contourDisplayA.clone({ groups: [modifiedGroup] }); expect(contourDisplayA.equals(contourDisplayB)).to.be.false; // ensure the main object itself no longer matches // modify a contour style - let modifiedContourStyle = groupsA[0].contourDef.minorStyle.clone({pattern: LinePixels.Solid}); + let modifiedContourStyle = groupsA[0].contourDef.minorStyle.clone({ pattern: LinePixels.Solid }); expect(modifiedContourStyle.equals(groupsA[0].contourDef.minorStyle)).to.be.false; // ensure old contour style and modified contour style do not match - modifiedContour = groupsA[0].contourDef.clone({minorStyle: modifiedContourStyle}); + modifiedContour = groupsA[0].contourDef.clone({ minorStyle: modifiedContourStyle }); expect(modifiedContour.equals(groupsA[0].contourDef)).to.be.false; // ensure the old contour and modified contour do not match - modifiedGroup = groupsA[0].clone({contourDef: modifiedContour}); + modifiedGroup = groupsA[0].clone({ contourDef: modifiedContour }); expect(groupsA[0].equals(modifiedGroup)).to.be.false; // ensure old group and modified group do not match - contourDisplayB = contourDisplayA.clone({groups: [ modifiedGroup ]}); + contourDisplayB = contourDisplayA.clone({ groups: [modifiedGroup] }); expect(contourDisplayA.equals(contourDisplayB)).to.be.false; // ensure the main object itself no longer matches // unmodify the contour style - modifiedContourStyle = contourDisplayB.groups[0].contourDef.minorStyle.clone({pattern: LinePixels.Code1}); + modifiedContourStyle = contourDisplayB.groups[0].contourDef.minorStyle.clone({ pattern: LinePixels.Code1 }); expect(modifiedContourStyle.equals(groupsA[0].contourDef.minorStyle)).to.be.true; // ensure old contour style and modified contour style do match - modifiedContour = groupsA[0].contourDef.clone({minorStyle: modifiedContourStyle}); + modifiedContour = groupsA[0].contourDef.clone({ minorStyle: modifiedContourStyle }); expect(modifiedContour.equals(groupsA[0].contourDef)).to.be.true; // ensure the old contour and modified contour do match - modifiedGroup = groupsA[0].clone({contourDef: modifiedContour}); + modifiedGroup = groupsA[0].clone({ contourDef: modifiedContour }); expect(groupsA[0].equals(modifiedGroup)).to.be.true; // ensure old group and modified group do match - contourDisplayB = contourDisplayA.clone({groups: [ modifiedGroup ]}); + contourDisplayB = contourDisplayA.clone({ groups: [modifiedGroup] }); expect(contourDisplayA.equals(contourDisplayB)).to.be.true; // ensure the main object itself matches }); }); diff --git a/core/common/src/test/CoordinateReferenceSystem.test.ts b/core/common/src/test/CoordinateReferenceSystem.test.ts index e21873f3d4fa..a5c49cfd55a6 100644 --- a/core/common/src/test/CoordinateReferenceSystem.test.ts +++ b/core/common/src/test/CoordinateReferenceSystem.test.ts @@ -5,14 +5,27 @@ // cspell:ignore JSONXYZ, ETRF, OSGB, DHDN, CLRK, Benoit, NAVD, NADCON, Xfrm, prvi, stgeorge, stlrnc, stpaul, helmert, NSRS import { describe, expect, it } from "vitest"; -import { GeographicCRS, GeographicCRSProps, HorizontalCRS, HorizontalCRSExtent, HorizontalCRSExtentProps, HorizontalCRSProps } from "../geometry/CoordinateReferenceSystem"; -import { GeodeticDatum, GeodeticDatumProps, GeodeticTransform, GeodeticTransformPath, GeodeticTransformPathProps, GeodeticTransformProps } from "../geometry/GeodeticDatum"; +import { + GeographicCRS, + GeographicCRSProps, + HorizontalCRS, + HorizontalCRSExtent, + HorizontalCRSExtentProps, + HorizontalCRSProps, +} from "../geometry/CoordinateReferenceSystem"; +import { + GeodeticDatum, + GeodeticDatumProps, + GeodeticTransform, + GeodeticTransformPath, + GeodeticTransformPathProps, + GeodeticTransformProps, +} from "../geometry/GeodeticDatum"; import { GeodeticEllipsoid, GeodeticEllipsoidProps } from "../geometry/GeodeticEllipsoid"; import { Carto2DDegrees } from "../geometry/Projection"; // import { ProjectionMethod2 } from "../geometry/Projection"; describe("Geodetic Settings", () => { - /* Geodetic Transform unit tests */ it("round-trips GeodeticTransform through JSON", () => { const roundTrip = (input: GeodeticTransformProps | undefined, expected: GeodeticTransformProps | "input") => { @@ -217,8 +230,7 @@ describe("Geodetic Settings", () => { sourceDatumId: "NAD27", targetDatumId: "NAD83/HARN-A", }, "input"); - }, - ); + }); /* Geodetic Ellipsoid unit tests */ it("round-trips GeodeticEllipsoid through JSON", () => { @@ -251,7 +263,6 @@ describe("Geodetic Settings", () => { expect(ellipsoid.equals(expectedEllipsoid)).to.be.true; expect(ellipsoid.equals(outEllipsoid)).to.be.true; - }; /** For the moment no property is validated so we always use input as compare base */ @@ -313,7 +324,6 @@ describe("Geodetic Settings", () => { polarRadius: 6356774.719195306, }); expect(ellipsoid1.equals(ellipsoid2)).to.be.true; - }); /* HorizontalCRSExtent unit tests */ @@ -339,7 +349,6 @@ describe("Geodetic Settings", () => { expect(extent.equals(expectedExtent)).to.be.true; expect(extent.equals(outExtent)).to.be.true; - }; roundTrip({ southWest: { latitude: 12.1, longitude: 45.6 }, northEast: { latitude: 14.56, longitude: 58.7 } }, "input"); @@ -349,11 +358,20 @@ describe("Geodetic Settings", () => { roundTrip({ southWest: { latitude: 12.1, longitude: 178.1 }, northEast: { latitude: 14.56, longitude: -178.7 } }, "input"); // This one verifies that fuzzy number compare are applied - const cartoPointA = HorizontalCRSExtent.fromJSON({ southWest: { latitude: 12.1, longitude: 178.1 }, northEast: { latitude: 14.56, longitude: -178.7 } }); - const cartoPointB = HorizontalCRSExtent.fromJSON({ southWest: { latitude: 12.100000000001, longitude: 178.1000000000001 }, northEast: { latitude: 14.56000000001, longitude: -178.70000000001 } }); + const cartoPointA = HorizontalCRSExtent.fromJSON({ + southWest: { latitude: 12.1, longitude: 178.1 }, + northEast: { latitude: 14.56, longitude: -178.7 }, + }); + const cartoPointB = HorizontalCRSExtent.fromJSON({ + southWest: { latitude: 12.100000000001, longitude: 178.1000000000001 }, + northEast: { latitude: 14.56000000001, longitude: -178.70000000001 }, + }); expect(cartoPointA.equals(cartoPointB)).to.be.true; - const cartoPointC = HorizontalCRSExtent.fromJSON({ southWest: { latitude: 12.100000001, longitude: 178.1000000001 }, northEast: { latitude: 14.56000000001, longitude: -178.70000000001 } }); + const cartoPointC = HorizontalCRSExtent.fromJSON({ + southWest: { latitude: 12.100000001, longitude: 178.1000000001 }, + northEast: { latitude: 14.56000000001, longitude: -178.70000000001 }, + }); expect(cartoPointA.equals(cartoPointC)).to.be.false; /* Additional unit tests */ @@ -962,7 +980,11 @@ describe("Geodetic Settings", () => { roundTrip({ horizontalCRS: { id: "ETRF89" }, verticalCRS: { id: "ELLIPSOID" } }, "input"); roundTrip({ horizontalCRS: { id: "OSGB" }, verticalCRS: { id: "LOCAL_ELLIPSOID" } }, "input"); roundTrip({ horizontalCRS: { id: "GDA2020" }, verticalCRS: { id: "GEOID" } }, "input"); - roundTrip({ horizontalCRS: { id: "GDA2020" }, verticalCRS: { id: "GEOID" }, additionalTransform: { helmert2DWithZOffset: { translationX: 10.0, translationY: 15.0, translationZ: 0.02, rotDeg: 1.2, scale: 1.0001 } } }, "input"); + roundTrip({ + horizontalCRS: { id: "GDA2020" }, + verticalCRS: { id: "GEOID" }, + additionalTransform: { helmert2DWithZOffset: { translationX: 10.0, translationY: 15.0, translationZ: 0.02, rotDeg: 1.2, scale: 1.0001 } }, + }, "input"); roundTrip({ horizontalCRS: { @@ -1480,5 +1502,4 @@ describe("Geodetic Settings", () => { expect(CRS1.equals(CRS2)).to.be.true; }); - }); diff --git a/core/common/src/test/CutStyle.test.ts b/core/common/src/test/CutStyle.test.ts index 6bccb0caf344..2745dbb76b10 100644 --- a/core/common/src/test/CutStyle.test.ts +++ b/core/common/src/test/CutStyle.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; import { CutStyle, CutStyleProps } from "../ClipStyle"; -import { HiddenLine } from "../HiddenLine"; import { FeatureAppearance } from "../FeatureSymbology"; +import { HiddenLine } from "../HiddenLine"; describe("CutStyle", () => { it("should round-trip through JSON", () => { @@ -24,7 +24,7 @@ describe("CutStyle", () => { roundTrip({}, undefined); roundTrip({ viewflags: undefined, hiddenLine: undefined, appearance: undefined }, undefined); roundTrip(CutStyle.create().toJSON(), undefined); - roundTrip(CutStyle.create({ }, HiddenLine.Settings.defaults, FeatureAppearance.defaults).toJSON(), undefined); + roundTrip(CutStyle.create({}, HiddenLine.Settings.defaults, FeatureAppearance.defaults).toJSON(), undefined); const hiddenLine = { ...HiddenLine.Settings.defaults.toJSON(), diff --git a/core/common/src/test/DisplayStyle.test.ts b/core/common/src/test/DisplayStyle.test.ts index 5e052d5630ab..53ebb7261876 100644 --- a/core/common/src/test/DisplayStyle.test.ts +++ b/core/common/src/test/DisplayStyle.test.ts @@ -3,29 +3,38 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { CompressedId64Set, Id64String, OrderedId64Iterable } from "@itwin/core-bentley"; +import { describe, expect, it } from "vitest"; +import { Atmosphere } from "../Atmosphere"; import { BackgroundMapType } from "../BackgroundMapProvider"; import { GlobeMode } from "../BackgroundMapSettings"; import { ColorByName } from "../ColorByName"; import { - DisplayStyle3dSettings, DisplayStyle3dSettingsProps, DisplayStyleOverridesOptions, DisplayStylePlanarClipMaskProps, DisplayStyleSettings, MonochromeMode, + DisplayStyle3dSettings, + DisplayStyle3dSettingsProps, + DisplayStyleOverridesOptions, + DisplayStylePlanarClipMaskProps, + DisplayStyleSettings, + MonochromeMode, } from "../DisplayStyleSettings"; +import { GroundPlane } from "../GroundPlane"; import { LinePixels } from "../LinePixels"; +import { PlanarClipMaskMode, PlanarClipMaskSettings } from "../PlanarClipMask"; import { PlanProjectionSettings, PlanProjectionSettingsProps } from "../PlanProjectionSettings"; +import { SkyGradient } from "../SkyBox"; import { SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay } from "../SpatialClassification"; import { ThematicDisplayMode } from "../ThematicDisplay"; import { RenderMode, ViewFlags } from "../ViewFlags"; -import { PlanarClipMaskMode, PlanarClipMaskSettings } from "../PlanarClipMask"; import { WhiteOnWhiteReversalProps, WhiteOnWhiteReversalSettings } from "../WhiteOnWhiteReversalSettings"; -import { SkyGradient } from "../SkyBox"; -import { GroundPlane } from "../GroundPlane"; -import { Atmosphere } from "../Atmosphere"; describe("DisplayStyleSettings", () => { describe("whiteOnWhiteReversal", () => { it("round-trips through JSON", () => { - function test(props: WhiteOnWhiteReversalProps | undefined, newSettings: WhiteOnWhiteReversalSettings, expected?: WhiteOnWhiteReversalProps | "input"): void { + function test( + props: WhiteOnWhiteReversalProps | undefined, + newSettings: WhiteOnWhiteReversalSettings, + expected?: WhiteOnWhiteReversalProps | "input", + ): void { const styleProps = { styles: props ? { whiteOnWhiteReversal: props } : {} }; const style = new DisplayStyle3dSettings(styleProps); style.whiteOnWhiteReversal = newSettings; @@ -70,7 +79,9 @@ describe("DisplayStyleSettings", () => { }); describe("plan projection settings", () => { - interface SettingsMap { [modelId: string]: PlanProjectionSettingsProps } + interface SettingsMap { + [modelId: string]: PlanProjectionSettingsProps; + } it("round-trips plan projection settings", () => { const roundTrip = (planProjections: SettingsMap | undefined) => { @@ -95,9 +106,10 @@ describe("DisplayStyleSettings", () => { expected = planProjections; const input = new DisplayStyle3dSettings({}); - if (undefined !== planProjections) + if (undefined !== planProjections) { for (const modelId of Object.keys(planProjections)) input.setPlanProjectionSettings(modelId, PlanProjectionSettings.fromJSON(planProjections[modelId])); + } const output = new DisplayStyle3dSettings({ styles: input.toJSON() }); const json = output.toJSON(); @@ -121,9 +133,10 @@ describe("DisplayStyleSettings", () => { const countSettings = () => { let count = 0; const iter = settings.planProjectionSettings; - if (undefined !== iter) + if (undefined !== iter) { for (const _entry of iter) // eslint-disable-line @typescript-eslint/naming-convention ++count; + } return count; }; @@ -252,16 +265,21 @@ describe("DisplayStyleSettings", () => { expectMasks([{ modelId: "0x1", mode: PlanarClipMaskMode.None }], []); expectMasks([makeProps(123, "0x456")], [["0x456", makeSettings(123)]]); - expectMasks([makeProps(5, "0x1"), makeProps(1, "0x5"), makeProps(3, "0x3")], [["0x1", makeSettings(5)], ["0x5", makeSettings(1)], ["0x3", makeSettings(3)]]); + expectMasks([makeProps(5, "0x1"), makeProps(1, "0x5"), makeProps(3, "0x3")], [["0x1", makeSettings(5)], ["0x5", makeSettings(1)], [ + "0x3", + makeSettings(3), + ]]); expectMasks([makeProps(1, "0x1"), makeProps(2, "0x1")], [["0x1", makeSettings(2)]]); }); it("synchronizes JSON and in-memory representations", () => { - function expectMasks(initialProps: DisplayStylePlanarClipMaskProps[] | undefined, + function expectMasks( + initialProps: DisplayStylePlanarClipMaskProps[] | undefined, func: (masks: Map, style: DisplayStyleSettings) => void, expectedPairs: Array<[Id64String, PlanarClipMaskSettings]>, - expectedProps: DisplayStylePlanarClipMaskProps[] | undefined) { + expectedProps: DisplayStylePlanarClipMaskProps[] | undefined, + ) { const styleProps = initialProps ? { styles: { planarClipOvr: initialProps } } : {}; const style = new DisplayStyleSettings(styleProps); @@ -271,29 +289,41 @@ describe("DisplayStyleSettings", () => { expect(style.toJSON().planarClipOvr).to.deep.equal(expectedProps); } - expectMasks(undefined, (map) => { - map.set("0x2", makeSettings(2)); - map.set("0x1", makeSettings(1)); - map.set("0x3", makeSettings(3)); - }, [["0x2", makeSettings(2)], ["0x1", makeSettings(1)], ["0x3", makeSettings(3)]], - [makeProps(2, "0x2"), makeProps(1, "0x1"), makeProps(3, "0x3")]); + expectMasks( + undefined, + (map) => { + map.set("0x2", makeSettings(2)); + map.set("0x1", makeSettings(1)); + map.set("0x3", makeSettings(3)); + }, + [["0x2", makeSettings(2)], ["0x1", makeSettings(1)], ["0x3", makeSettings(3)]], + [makeProps(2, "0x2"), makeProps(1, "0x1"), makeProps(3, "0x3")], + ); - expectMasks([makeProps(1, "0x1")], (map) => map.set("0x1", makeSettings(2)), - [["0x1", makeSettings(2)]], [makeProps(2, "0x1")]); + expectMasks([makeProps(1, "0x1")], (map) => map.set("0x1", makeSettings(2)), [["0x1", makeSettings(2)]], [makeProps(2, "0x1")]); - expectMasks([makeProps(1, "0x1"), makeProps(3, "0x3"), makeProps(2, "0x2")], (map) => { - map.delete("0x2"); - map.delete("0x4"); - }, [["0x1", makeSettings(1)], ["0x3", makeSettings(3)]], - [makeProps(1, "0x1"), makeProps(3, "0x3")]); + expectMasks( + [makeProps(1, "0x1"), makeProps(3, "0x3"), makeProps(2, "0x2")], + (map) => { + map.delete("0x2"); + map.delete("0x4"); + }, + [["0x1", makeSettings(1)], ["0x3", makeSettings(3)]], + [makeProps(1, "0x1"), makeProps(3, "0x3")], + ); expectMasks([makeProps(1, "0x1"), makeProps(2, "0x2")], (map) => map.clear(), [], undefined); - expectMasks([makeProps(1, "0x1"), makeProps(2, "0x2")], (map, style) => { - style.toJSON().planarClipOvr = [makeProps(4, "0x4")]; - expect(typeof (map as any).populate).to.equal("function"); - (map as any).populate(); - }, [["0x4", makeSettings(4)]], [makeProps(4, "0x4")]); + expectMasks( + [makeProps(1, "0x1"), makeProps(2, "0x2")], + (map, style) => { + style.toJSON().planarClipOvr = [makeProps(4, "0x4")]; + expect(typeof (map as any).populate).to.equal("function"); + (map as any).populate(); + }, + [["0x4", makeSettings(4)]], + [makeProps(4, "0x4")], + ); }); it("dispatches events", () => { @@ -360,7 +390,7 @@ describe("DisplayStyleSettings overrides", () => { }, contours: { displayContours: false, - groups: [ ], + groups: [], }, hline: { transThreshold: 0x7f, @@ -547,7 +577,13 @@ describe("DisplayStyleSettings overrides", () => { roundTrip({ includeITwinSpecific: true }, { ...baseProps, ...iTwinProps, viewflags: vfNoMapNoDec }); roundTrip({ includeIModelSpecific: true }, { ...baseProps, ...iTwinProps, ...iModelProps, viewflags: vfNoMapNoDec }); - roundTrip({ includeIModelSpecific: true, includeDrawingAids: true, includeBackgroundMap: true }, { ...baseProps, ...mapProps, ...iTwinProps, ...iModelProps, viewflags }); + roundTrip({ includeIModelSpecific: true, includeDrawingAids: true, includeBackgroundMap: true }, { + ...baseProps, + ...mapProps, + ...iTwinProps, + ...iModelProps, + viewflags, + }); }); it("overrides selected settings", () => { diff --git a/core/common/src/test/ElementMesh.test.ts b/core/common/src/test/ElementMesh.test.ts index a8af59be25cd..e226ee046587 100644 --- a/core/common/src/test/ElementMesh.test.ts +++ b/core/common/src/test/ElementMesh.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { Uint8ArrayBuilder } from "@itwin/core-bentley"; import { BentleyGeometryFlatBuffer, IndexedPolyface, Point3d, PolyfaceBuilder } from "@itwin/core-geometry"; +import { describe, expect, it } from "vitest"; import { readElementMeshes } from "../ElementMesh"; class MeshesBuilder extends Uint8ArrayBuilder { @@ -94,4 +94,3 @@ describe("readElementMeshes", () => { expect(builder.getPolyfaces().length).to.equal(0); }); }); - diff --git a/core/common/src/test/FeatureIndex.test.ts b/core/common/src/test/FeatureIndex.test.ts index 57808d02f5cc..b4a542d14b1e 100644 --- a/core/common/src/test/FeatureIndex.test.ts +++ b/core/common/src/test/FeatureIndex.test.ts @@ -26,7 +26,10 @@ describe("ColorIndex", () => { ci.initUniform(ColorDef.from(255, 127, 63, 31)); assert.isTrue(ci.isUniform, "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should be Uniform"); assert.isTrue(1 === ci.numColors, "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should have numColors of 1"); - assert.isTrue(0x1f3f7fff === ci.uniform!.tbgr, "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should have uniform color of 0x1f3f7fff"); + assert.isTrue( + 0x1f3f7fff === ci.uniform!.tbgr, + "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should have uniform color of 0x1f3f7fff", + ); assert.isTrue(undefined === ci.nonUniform, "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should have undefined nonUniform"); assert.isTrue(ci.hasAlpha, "Uniform ColorIndex set to ColorDef.from(255, 127, 63, 31) should have alpha"); @@ -47,15 +50,22 @@ describe("ColorIndex", () => { } ci.initNonUniform(colors, indices, true); assert.isFalse(ci.isUniform, "NonUniform ColorIndex should not be Uniform"); - assert.isTrue(numColors === ci.numColors, `NonUniform ColorIndex with ${numColors} should have numColors of ${numColors} but has ${ci.numColors}`); + assert.isTrue( + numColors === ci.numColors, + `NonUniform ColorIndex with ${numColors} should have numColors of ${numColors} but has ${ci.numColors}`, + ); assert.isTrue(ci.hasAlpha, "NonUniform ColorIndex which has alpha in its colors should return true from hasAlpha"); assert.isTrue(undefined !== ci.nonUniform, "NonUniform ColorIndex should not have an undefined nonUniform"); if (undefined !== ci.nonUniform) { for (let i = 0; i < numColors; ++i) { - assert.isTrue(ci.nonUniform.colors[i] === colors[i], - `NonUniform ColorIndex has colors[${i}] of ${ci.nonUniform.colors[i].toString(16)} but should be ${colors[i].toString(16)}`); - assert.isTrue(ci.nonUniform.indices[i] === indices[i], - `NonUniform ColorIndex has indices[${i}] of ${ci.nonUniform.indices[i]} but should be ${indices[i]}`); + assert.isTrue( + ci.nonUniform.colors[i] === colors[i], + `NonUniform ColorIndex has colors[${i}] of ${ci.nonUniform.colors[i].toString(16)} but should be ${colors[i].toString(16)}`, + ); + assert.isTrue( + ci.nonUniform.indices[i] === indices[i], + `NonUniform ColorIndex has indices[${i}] of ${ci.nonUniform.indices[i]} but should be ${indices[i]}`, + ); } } diff --git a/core/common/src/test/FeatureSymbology.test.ts b/core/common/src/test/FeatureSymbology.test.ts index 1a0399236b4c..f6d49c22b04b 100644 --- a/core/common/src/test/FeatureSymbology.test.ts +++ b/core/common/src/test/FeatureSymbology.test.ts @@ -2,18 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, expect, it } from "vitest"; import { Id64, Id64String } from "@itwin/core-bentley"; +import { assert, describe, expect, it } from "vitest"; import { ColorDef } from "../ColorDef"; -import { RgbColor } from "../RgbColor"; +import { FeatureAppearance, FeatureAppearanceProps, FeatureAppearanceProvider, FeatureAppearanceSource, FeatureOverrides } from "../FeatureSymbology"; import { BatchType, Feature } from "../FeatureTable"; import { GeometryClass } from "../GeometryParams"; import { LinePixels } from "../LinePixels"; +import { RgbColor } from "../RgbColor"; import { SubCategoryAppearance } from "../SubCategoryAppearance"; import { SubCategoryOverride } from "../SubCategoryOverride"; -import { - FeatureAppearance, FeatureAppearanceProps, FeatureAppearanceProvider, FeatureAppearanceSource, FeatureOverrides, -} from "../FeatureSymbology"; describe("FeatureAppearance", () => { it("default constructor works as expected", () => { @@ -26,7 +24,13 @@ describe("FeatureAppearance", () => { }); it("AppearanceProps passed in constructor works as expected", () => { - const props1 = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 200 / 255, linePixels: LinePixels.Code2, ignoresMaterial: true } as FeatureAppearanceProps; + const props1 = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 200 / 255, + linePixels: LinePixels.Code2, + ignoresMaterial: true, + } as FeatureAppearanceProps; const props2 = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 200 / 255, linePixels: LinePixels.Code2 } as FeatureAppearanceProps; let app = FeatureAppearance.fromJSON(props1); assert.isTrue(app.overridesRgb); @@ -42,7 +46,13 @@ describe("FeatureAppearance", () => { it("extend works as expected", () => { const props1 = { rgb: new RgbColor(100, 100, 100), linePixels: LinePixels.Code2, ignoresMaterial: true } as FeatureAppearanceProps; const props2 = { rgb: new RgbColor(250, 180, 150), weight: 1, transparency: 200 / 255, linePixels: LinePixels.Code3 } as FeatureAppearanceProps; - const expectedProps = { rgb: new RgbColor(100, 100, 100), linePixels: LinePixels.Code2, ignoresMaterial: true, weight: 1, transparency: 200 / 255 } as FeatureAppearanceProps; + const expectedProps = { + rgb: new RgbColor(100, 100, 100), + linePixels: LinePixels.Code2, + ignoresMaterial: true, + weight: 1, + transparency: 200 / 255, + } as FeatureAppearanceProps; let app1 = FeatureAppearance.fromJSON(props1); const app2 = FeatureAppearance.fromJSON(props2); app1 = app2.extendAppearance(app1); @@ -92,10 +102,10 @@ describe("FeatureAppearance", () => { expect(app.toJSON().viewDependentTransparency).to.equal(expected); } - test({ }, false); + test({}, false); test({ transparency: undefined }, false); test({ transparency: 1 }, false); - test({ transparency: 0 }, false ); + test({ transparency: 0 }, false); test({ transparency: 1, viewDependentTransparency: true }, true); test({ transparency: 0, viewDependentTransparency: true }, true); @@ -115,21 +125,37 @@ describe("FeatureAppearance", () => { test({ transp: 0.5 }, true); test({ transp: 0 }, true); test({ transp: undefined }, false); - test({ }, false); + test({}, false); test({ color: ColorDef.blue.toJSON() }, false); }); }); describe("FeatureOverrides", () => { class Overrides extends FeatureOverrides { - public constructor() { super(); } - public override get neverDrawn() { return this._neverDrawn; } - public override get alwaysDrawn() { return this._alwaysDrawn; } - public get modelOverrides() { return this._modelOverrides; } - public get elementOverrides() { return this._elementOverrides; } - public get subCategoryOverrides() { return this._subCategoryOverrides; } - public get visibleSubCategories() { return this._visibleSubCategories; } - public get modelSubCategoryOverrides() { return this._modelSubCategoryOverrides; } + public constructor() { + super(); + } + public override get neverDrawn() { + return this._neverDrawn; + } + public override get alwaysDrawn() { + return this._alwaysDrawn; + } + public get modelOverrides() { + return this._modelOverrides; + } + public get elementOverrides() { + return this._elementOverrides; + } + public get subCategoryOverrides() { + return this._subCategoryOverrides; + } + public get visibleSubCategories() { + return this._visibleSubCategories; + } + public get modelSubCategoryOverrides() { + return this._modelSubCategoryOverrides; + } } it("default constructor works as expected", () => { @@ -159,7 +185,13 @@ describe("FeatureOverrides", () => { it("overrideModel works as expected", () => { const overrides = new Overrides(); const id = Id64.fromString("0x111"); - const props1 = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true } as FeatureAppearanceProps; + const props1 = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + } as FeatureAppearanceProps; const props2 = { ...props1, transparency: 200 / 255 } as FeatureAppearanceProps; const modelApp1 = FeatureAppearance.fromJSON(props1); const modelApp2 = FeatureAppearance.fromJSON(props2); @@ -167,19 +199,31 @@ describe("FeatureOverrides", () => { assert.exists(overrides.getModelOverridesById(id)); overrides.overrideModel(id, modelApp2); // eslint-disable-line deprecation/deprecation - assert.isTrue(overrides.getModelOverridesById(id)!.equals(modelApp2), "overrideModel will override prexisting model associated with given id if replaceExisting is not set to false explicitly"); + assert.isTrue( + overrides.getModelOverridesById(id)!.equals(modelApp2), + "overrideModel will override prexisting model associated with given id if replaceExisting is not set to false explicitly", + ); overrides.overrideModel(id, modelApp1, false); // eslint-disable-line deprecation/deprecation assert.isTrue(overrides.getModelOverridesById(id)!.equals(modelApp2), "overrides will not replace model if replace existing is set to false"); overrides.overrideModel(id, modelApp1); // eslint-disable-line deprecation/deprecation - assert.isTrue(overrides.getModelOverridesById(id)!.equals(modelApp1), "overrides will replace model if replace existing isn't set to false (test 2)"); + assert.isTrue( + overrides.getModelOverridesById(id)!.equals(modelApp1), + "overrides will replace model if replace existing isn't set to false (test 2)", + ); }); it("overrideSubCategory works as expected", () => { const overrides = new Overrides(); const id = Id64.fromString("0x111"); - const props1 = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true } as FeatureAppearanceProps; + const props1 = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + } as FeatureAppearanceProps; const props2 = { ...props1, transparency: 200 / 255 } as FeatureAppearanceProps; const subCatApp1 = FeatureAppearance.fromJSON(props1); const subCatApp2 = FeatureAppearance.fromJSON(props2); @@ -195,16 +239,28 @@ describe("FeatureOverrides", () => { assert.exists(overrides.getSubCategoryOverridesById(id), "if subCategoryId is in subCategoryVisible set, then subCategoryApp set"); overrides.overrideSubCategory(id, subCatApp1, false); // eslint-disable-line deprecation/deprecation - assert.isTrue(overrides.getSubCategoryOverridesById(id)!.equals(subCatApp2), "overrides will not replace subCatApp if replace existing is set to false"); + assert.isTrue( + overrides.getSubCategoryOverridesById(id)!.equals(subCatApp2), + "overrides will not replace subCatApp if replace existing is set to false", + ); overrides.overrideSubCategory(id, subCatApp1); // eslint-disable-line deprecation/deprecation - assert.isTrue(overrides.getSubCategoryOverridesById(id)!.equals(subCatApp1), "overrides will replace subCatApp if replace existing isn't set to false"); + assert.isTrue( + overrides.getSubCategoryOverridesById(id)!.equals(subCatApp1), + "overrides will replace subCatApp if replace existing isn't set to false", + ); }); it("overrideElement works as expected", () => { let overrides = new Overrides(); const id = Id64.fromString("0x111"); - const props1 = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true } as FeatureAppearanceProps; + const props1 = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + } as FeatureAppearanceProps; const props2 = { ...props1, transparency: 200 / 255 } as FeatureAppearanceProps; const elemApp1 = FeatureAppearance.fromJSON(props1); const elemApp2 = FeatureAppearance.fromJSON(props2); @@ -226,9 +282,18 @@ describe("FeatureOverrides", () => { it("setDefaultOverrides works as expected", () => { const overrides = new Overrides(); - assert.isTrue(overrides.defaultOverrides.equals(FeatureAppearance.fromJSON()), "initial default overrides are equivalent to default appearance instance"); - - const props = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true } as FeatureAppearanceProps; + assert.isTrue( + overrides.defaultOverrides.equals(FeatureAppearance.fromJSON()), + "initial default overrides are equivalent to default appearance instance", + ); + + const props = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + } as FeatureAppearanceProps; const app = FeatureAppearance.fromJSON(props); overrides.setDefaultOverrides(app); assert.isTrue(overrides.defaultOverrides.equals(app), "default overrides can be overriden"); @@ -423,7 +488,11 @@ describe("FeatureOverrides", () => { const elementId = "0x1"; const ovrs = new Overrides(); - const test = (appearance: FeatureAppearance, onConflict: "subsume" | "extend" | "replace" | "skip" = "extend", expected: FeatureAppearance | undefined) => { + const test = ( + appearance: FeatureAppearance, + onConflict: "subsume" | "extend" | "replace" | "skip" = "extend", + expected: FeatureAppearance | undefined, + ) => { ovrs.override({ elementId, appearance, onConflict }); const actual = ovrs.getElementOverridesById(elementId); if (!expected) { @@ -466,17 +535,38 @@ describe("FeatureOverrides", () => { describe("FeatureAppearanceProvider", () => { class Source implements FeatureAppearanceSource { - public constructor(public readonly appearance: FeatureAppearance | undefined) { } - - public getAppearance(_elemLo: number, _elemHi: number, _subcatLo: number, _subcatHi: number, _geomClass: GeometryClass, _modelLo: number, _modelHi: number, _type: BatchType, _animationNodeId: number) { + public constructor(public readonly appearance: FeatureAppearance | undefined) {} + + public getAppearance( + _elemLo: number, + _elemHi: number, + _subcatLo: number, + _subcatHi: number, + _geomClass: GeometryClass, + _modelLo: number, + _modelHi: number, + _type: BatchType, + _animationNodeId: number, + ) { return this.appearance; } } class Provider implements FeatureAppearanceProvider { - public constructor(public readonly modifyAppearance: (app: FeatureAppearance) => FeatureAppearance) { } - - public getFeatureAppearance(source: FeatureAppearanceSource, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number) { + public constructor(public readonly modifyAppearance: (app: FeatureAppearance) => FeatureAppearance) {} + + public getFeatureAppearance( + source: FeatureAppearanceSource, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ) { const app = source.getAppearance(elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); return app ? this.modifyAppearance(app) : undefined; } diff --git a/core/common/src/test/FeatureTable.test.ts b/core/common/src/test/FeatureTable.test.ts index 49a54d5c0f5a..1a9823890a99 100644 --- a/core/common/src/test/FeatureTable.test.ts +++ b/core/common/src/test/FeatureTable.test.ts @@ -2,10 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { Id64 } from "@itwin/core-bentley"; +import { describe, expect, it } from "vitest"; import { - Feature, FeatureTable, ModelFeature, MultiModelPackedFeatureTable, PackedFeature, PackedFeatureModelTable, PackedFeatureTable, + Feature, + FeatureTable, + ModelFeature, + MultiModelPackedFeatureTable, + PackedFeature, + PackedFeatureModelTable, + PackedFeatureTable, } from "../FeatureTable"; import { GeometryClass } from "../GeometryParams"; @@ -90,12 +96,20 @@ describe("PackedFeatureModelTable", () => { ]); const modelByFeatureIndex = [ - Id64.invalid, Id64.invalid, Id64.invalid, + Id64.invalid, + Id64.invalid, + Id64.invalid, "0x2", - "0x321", "0x321", "0x321", - "0x20000000123", "0x20000000123", + "0x321", + "0x321", + "0x321", + "0x20000000123", + "0x20000000123", "0x555555555555", - "0xffffffffffff", "0xffffffffffff", "0xffffffffffff", "0xffffffffffff", + "0xffffffffffff", + "0xffffffffffff", + "0xffffffffffff", + "0xffffffffffff", ]; for (let i = 0; i < modelByFeatureIndex.length; i++) { @@ -138,12 +152,12 @@ describe("MultiModelPackedFeatureTable", () => { ]); const expectedFeatures = [ - [ "0x1", "0xa" ], - [ "0x2", "0xb" ], - [ "0x3", "0xb" ], - [ "0x4", "0xb" ], - [ "0x5", "0xc" ], - [ "0x6", "0xc" ], + ["0x1", "0xa"], + ["0x2", "0xb"], + ["0x3", "0xb"], + ["0x4", "0xb"], + ["0x5", "0xc"], + ["0x6", "0xc"], ]; for (let i = 0; i < expectedFeatures.length; i++) { @@ -164,12 +178,12 @@ describe("MultiModelPackedFeatureTable", () => { ]); const expectedFeatures = [ - [ "0x1", "0xa" ], - [ "0x2", "0xb" ], - [ "0x3", "0xb" ], - [ "0x4", "0xb" ], - [ "0x5", "0xc" ], - [ "0x6", "0xc" ], + ["0x1", "0xa"], + ["0x2", "0xb"], + ["0x3", "0xb"], + ["0x4", "0xb"], + ["0x5", "0xc"], + ["0x6", "0xc"], ]; let i = 0; @@ -184,12 +198,12 @@ describe("MultiModelPackedFeatureTable", () => { }); it("produces invalid model Id during iteration if feature index is greater than maximum", () => { - const table = makeTable(4, [ ["0xa", 1] ]); + const table = makeTable(4, [["0xa", 1]]); const expectedFeatures = [ - [ "0x1", "0xa" ], - [ "0x2", "0xa" ], - [ "0x3", "0" ], - [ "0x4", "0" ], + ["0x1", "0xa"], + ["0x2", "0xa"], + ["0x3", "0"], + ["0x4", "0"], ]; let i = 0; diff --git a/core/common/src/test/FrustumPlanes.test.ts b/core/common/src/test/FrustumPlanes.test.ts index 1e97a38133fa..e0474a424687 100644 --- a/core/common/src/test/FrustumPlanes.test.ts +++ b/core/common/src/test/FrustumPlanes.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Point3d } from "@itwin/core-geometry"; import { describe, expect, it } from "vitest"; -import { FrustumPlanes } from "../geometry/FrustumPlanes"; import { Frustum } from "../Frustum"; -import { Point3d } from "@itwin/core-geometry"; +import { FrustumPlanes } from "../geometry/FrustumPlanes"; describe("FrustumPlanes", () => { it("should properly handle a default frustum", () => { @@ -16,13 +16,13 @@ describe("FrustumPlanes", () => { it("should properly handle a good frustum", () => { const frustum = new Frustum(); frustum.setFromCorners([ - Point3d.fromJSON({ x: 88.51459041033166, y: 0.7622479698565066, z: -21.27515944984108 }), // left bottom rear - Point3d.fromJSON({ x: 83.59175566227866, y: -54.5154018605118, z: -21.275159449841123 }), // right bottom rear - Point3d.fromJSON({ x: 91.54647813049287, y: 0.4922386212896158, z: 14.92723336305222 }), // left top rear - Point3d.fromJSON({ x: 86.62364338243987, y: -54.78541120907869, z: 14.927233363052178 }), // right top rear + Point3d.fromJSON({ x: 88.51459041033166, y: 0.7622479698565066, z: -21.27515944984108 }), // left bottom rear + Point3d.fromJSON({ x: 83.59175566227866, y: -54.5154018605118, z: -21.275159449841123 }), // right bottom rear + Point3d.fromJSON({ x: 91.54647813049287, y: 0.4922386212896158, z: 14.92723336305222 }), // left top rear + Point3d.fromJSON({ x: 86.62364338243987, y: -54.78541120907869, z: 14.927233363052178 }), // right top rear Point3d.fromJSON({ x: 22.838134428009578, y: -21.182090505813676, z: 2.248236463773556 }), // left bottom front - Point3d.fromJSON({ x: 22.826687847036766, y: -21.3106221602675, z: 2.248236463773556 }), // right bottom front - Point3d.fromJSON({ x: 22.845184176795684, y: -21.18271833185903, z: 2.332414308846702 }), // left top front + Point3d.fromJSON({ x: 22.826687847036766, y: -21.3106221602675, z: 2.248236463773556 }), // right bottom front + Point3d.fromJSON({ x: 22.845184176795684, y: -21.18271833185903, z: 2.332414308846702 }), // left top front Point3d.fromJSON({ x: 22.833737595822875, y: -21.311249986312852, z: 2.332414308846702 }), // right top front ]); @@ -33,13 +33,13 @@ describe("FrustumPlanes", () => { it("should properly handle a frustum with very small front rect", () => { const frustum = new Frustum(); frustum.setFromCorners([ - Point3d.fromJSON({ x: 86.91579452523399, y: -51.11890676358028, z: 14.520007347159119 }), // left bottom rear - Point3d.fromJSON({ x: 86.86504365154272, y: -51.68877944224387, z: 14.520007347159117 }), // right bottom rear - Point3d.fromJSON({ x: 86.91958012182498, y: -51.11924389561279, z: 14.565209434923249 }), // left top rear - Point3d.fromJSON({ x: 86.86882924813371, y: -51.68911657427638, z: 14.565209434923247 }), // right top rear + Point3d.fromJSON({ x: 86.91579452523399, y: -51.11890676358028, z: 14.520007347159119 }), // left bottom rear + Point3d.fromJSON({ x: 86.86504365154272, y: -51.68877944224387, z: 14.520007347159117 }), // right bottom rear + Point3d.fromJSON({ x: 86.91958012182498, y: -51.11924389561279, z: 14.565209434923249 }), // left top rear + Point3d.fromJSON({ x: 86.86882924813371, y: -51.68911657427638, z: 14.565209434923247 }), // right top rear Point3d.fromJSON({ x: 22.834416905993425, y: -21.302724625992933, z: 2.3314674264499287 }), // left bottom front Point3d.fromJSON({ x: 22.834298900004015, y: -21.304049694595548, z: 2.3314674264499287 }), // right bottom front - Point3d.fromJSON({ x: 22.834425708266938, y: -21.30272540989272, z: 2.3315725303959707 }), // left top front + Point3d.fromJSON({ x: 22.834425708266938, y: -21.30272540989272, z: 2.3315725303959707 }), // left top front Point3d.fromJSON({ x: 22.834307702277528, y: -21.304050478495334, z: 2.3315725303959707 }), // right top front ]); @@ -72,14 +72,14 @@ describe("FrustumPlanes", () => { it("should properly handle a bad (zero-size) frustum", () => { const frustum = new Frustum(); frustum.setFromCorners([ - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left bottom rear - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right bottom rear - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left top rear - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right top rear - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left bottom front - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right bottom front - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left top front - Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right top front + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left bottom rear + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right bottom rear + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left top rear + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right top rear + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left bottom front + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right bottom front + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // left top front + Point3d.fromJSON({ x: 0, y: 0, z: 0 }), // right top front ]); const frustumPlanes = FrustumPlanes.fromFrustum(frustum); diff --git a/core/common/src/test/GenericInstanceFilter.test.ts b/core/common/src/test/GenericInstanceFilter.test.ts index 65a60b8361cd..81473ad600a0 100644 --- a/core/common/src/test/GenericInstanceFilter.test.ts +++ b/core/common/src/test/GenericInstanceFilter.test.ts @@ -14,7 +14,7 @@ describe("GenericInstanceFilterRuleValue", () => { expect(GenericInstanceFilterRuleValue.isPoint2d(false)).to.be.false; expect(GenericInstanceFilterRuleValue.isPoint2d("text")).to.be.false; expect(GenericInstanceFilterRuleValue.isPoint2d(new Date())).to.be.false; - expect(GenericInstanceFilterRuleValue.isPoint2d({ id: "0x1", className: "TestClass"})).to.be.false; + expect(GenericInstanceFilterRuleValue.isPoint2d({ id: "0x1", className: "TestClass" })).to.be.false; }); it("'isPoint3d' returns correct result", () => { @@ -24,11 +24,11 @@ describe("GenericInstanceFilterRuleValue", () => { expect(GenericInstanceFilterRuleValue.isPoint3d(false)).to.be.false; expect(GenericInstanceFilterRuleValue.isPoint3d("text")).to.be.false; expect(GenericInstanceFilterRuleValue.isPoint3d(new Date())).to.be.false; - expect(GenericInstanceFilterRuleValue.isPoint3d({ id: "0x1", className: "TestClass"})).to.be.false; + expect(GenericInstanceFilterRuleValue.isPoint3d({ id: "0x1", className: "TestClass" })).to.be.false; }); it("'isInstanceKey' returns correct result", () => { - expect(GenericInstanceFilterRuleValue.isInstanceKey({ id: "0x1", className: "TestClass"})).to.be.true; + expect(GenericInstanceFilterRuleValue.isInstanceKey({ id: "0x1", className: "TestClass" })).to.be.true; expect(GenericInstanceFilterRuleValue.isInstanceKey({ x: 1, y: 2, z: 3 })).to.be.false; expect(GenericInstanceFilterRuleValue.isInstanceKey({ x: 1, y: 2 })).to.be.false; expect(GenericInstanceFilterRuleValue.isInstanceKey(1)).to.be.false; diff --git a/core/common/src/test/Gradient.test.ts b/core/common/src/test/Gradient.test.ts index 78e32e33e2f7..3c67e69e8756 100644 --- a/core/common/src/test/Gradient.test.ts +++ b/core/common/src/test/Gradient.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, expect, it } from "vitest"; import { Angle } from "@itwin/core-geometry"; +import { assert, describe, expect, it } from "vitest"; import { Gradient } from "../Gradient"; import { ImageBuffer, ImageBufferFormat } from "../Image"; diff --git a/core/common/src/test/IModel.test.ts b/core/common/src/test/IModel.test.ts index 144e033c4457..6eaeb21ba9e8 100644 --- a/core/common/src/test/IModel.test.ts +++ b/core/common/src/test/IModel.test.ts @@ -2,19 +2,25 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { Point3d, Range3d } from "@itwin/core-geometry"; -import { EcefLocation, EcefLocationProps, IModel, IModelProps, RootSubjectProps } from "../IModel"; +import { describe, expect, it } from "vitest"; import { GeographicCRS } from "../geometry/CoordinateReferenceSystem"; +import { EcefLocation, EcefLocationProps, IModel, IModelProps, RootSubjectProps } from "../IModel"; interface TestIModelProps extends IModelProps { key: string; } class TestIModel extends IModel { - public get isOpen() { return true; } - public get isSnapshot() { return true; } - public get isBriefcase() { return false; } + public get isOpen() { + return true; + } + public get isSnapshot() { + return true; + } + public get isBriefcase() { + return false; + } public constructor(props: TestIModelProps) { super(props); @@ -131,7 +137,9 @@ describe("IModel", () => { orientation: { yaw: 5, pitch: 90, roll: -45 }, }); expectChange(imodel, () => imodel.setEcefLocation(newEcef), { ecef: { prev: ecef, curr: newEcef } }); - expectChange(imodel, () => imodel.initFromProps({ ...imodel.getProps(), ecefLocation: undefined }), { ecef: { prev: newEcef, curr: undefined } }); + expectChange(imodel, () => imodel.initFromProps({ ...imodel.getProps(), ecefLocation: undefined }), { + ecef: { prev: newEcef, curr: undefined }, + }); const newProps: TestIModelProps = { key: "", @@ -186,13 +194,17 @@ describe("IModel", () => { }; expect(new TestIModel(props).isGeoLocated).to.be.false; - expect(new TestIModel({ - ...props, - ecefLocation: { origin: [0, 0, 0], orientation: { yaw: 0, pitch: 0, roll: 0 } }, - }).isGeoLocated).to.be.false; - expect(new TestIModel({ - ...props, - ecefLocation: { origin: [1, 0, 0], orientation: { yaw: 0, pitch: 0, roll: 0 } }, - }).isGeoLocated).to.be.true; + expect( + new TestIModel({ + ...props, + ecefLocation: { origin: [0, 0, 0], orientation: { yaw: 0, pitch: 0, roll: 0 } }, + }).isGeoLocated, + ).to.be.false; + expect( + new TestIModel({ + ...props, + ecefLocation: { origin: [1, 0, 0], orientation: { yaw: 0, pitch: 0, roll: 0 } }, + }).isGeoLocated, + ).to.be.true; }); }); diff --git a/core/common/src/test/IntersectionStyle.test.ts b/core/common/src/test/IntersectionStyle.test.ts index 98b5efb57f65..18f1b57207c6 100644 --- a/core/common/src/test/IntersectionStyle.test.ts +++ b/core/common/src/test/IntersectionStyle.test.ts @@ -22,7 +22,7 @@ describe("IntersectionStyle", () => { roundTrip(undefined, undefined); roundTrip(ClipIntersectionStyle.create().toJSON(), undefined); - roundTrip({ color:{ r: 0, g: 100, b: 200 }, width: 3 }, "input"); + roundTrip({ color: { r: 0, g: 100, b: 200 }, width: 3 }, "input"); }); it("should trigger changed events", () => { @@ -34,7 +34,7 @@ describe("IntersectionStyle", () => { eventHeard = true; }); - details.clipStyle = ClipStyle.fromJSON({ colorizeIntersection: true, intersectionStyle: { color:{ r: 0, g: 100, b: 200 }, width: 3 }}); + details.clipStyle = ClipStyle.fromJSON({ colorizeIntersection: true, intersectionStyle: { color: { r: 0, g: 100, b: 200 }, width: 3 } }); expect(eventHeard).to.be.true; }); }); diff --git a/core/common/src/test/LightSettings.test.ts b/core/common/src/test/LightSettings.test.ts index 4476b5c7e78c..01098fc34f03 100644 --- a/core/common/src/test/LightSettings.test.ts +++ b/core/common/src/test/LightSettings.test.ts @@ -63,7 +63,7 @@ describe("LightSettings", () => { roundTrip({ hemisphere: { intensity: -0.1 } }, undefined); roundTrip({ hemisphere: { intensity: 5.1 } }, { hemisphere: { intensity: 5.0 } }); - roundTrip({ fresnel: { } }, undefined); + roundTrip({ fresnel: {} }, undefined); roundTrip({ fresnel: { intensity: 0.8, invert: false } }, { fresnel: { intensity: 0.8 } }); roundTrip({ fresnel: { intensity: 0, invert: true } }, { fresnel: { invert: true } }); roundTrip({ fresnel: { intensity: -1, invert: true } }, { fresnel: { invert: true } }); @@ -93,7 +93,7 @@ describe("LightSettings", () => { const dir1 = { x: 1, y: 2, z: 3 }; const dir2 = { x: -1, y: -2, z: -3 }; - test({ }, { timePoint: 123 }, { timePoint: 123 }); + test({}, { timePoint: 123 }, { timePoint: 123 }); test({ direction: dir1 }, { timePoint: 123 }, { direction: dir1, timePoint: 123 }); test({ direction: dir1, timePoint: 123 }, { timePoint: 456 }, { direction: dir1, timePoint: 456 }); test({ direction: dir1, timePoint: 123 }, { direction: dir2 }, { direction: dir2 }); diff --git a/core/common/src/test/MapLayerSettings.test.ts b/core/common/src/test/MapLayerSettings.test.ts index 59fcf3fcbfab..c52b959c26ae 100644 --- a/core/common/src/test/MapLayerSettings.test.ts +++ b/core/common/src/test/MapLayerSettings.test.ts @@ -24,7 +24,6 @@ describe("MapSubLayerSettings", () => { for (let i = 0; i < expected.children.length; i++) expect(expected.children[i]).to.equal(output.children![i]); } - }; it("round-trips through JSON", () => { @@ -57,9 +56,19 @@ const testMapLayer0 = { name: "TestName", url: "www.bentley.com", formatId: "WMS const testMapLayer1 = { name: "TestName", url: "www.bentley.com", formatId: "WMTS", transparency: .5, transparentBackground: false, visible: true }; const testMapLayer2 = { name: "TestName", url: "www.bentley.com", formatId: "WMS", subLayers: [testMapSubLayer0, testMapSubLayer1], visible: true }; const testMapLayer3 = { name: "TestName", url: "www.bentley.com", formatId: "WMS", subLayers: [testMapSubLayer0, testMapSubLayer1], visible: true }; -const testMapLayer4 = { name: "TestName", url: "www.bentley.com", formatId: "WMS", subLayers: [testMapSubLayer0, testMapSubLayer1], isBase: true, visible: false }; +const testMapLayer4 = { + name: "TestName", + url: "www.bentley.com", + formatId: "WMS", + subLayers: [testMapSubLayer0, testMapSubLayer1], + isBase: true, + visible: false, +}; const testMapLayer6 = { name: "TestName", url: "www.bentley.com", formatId: "WMS", visible: false }; -const legacyMapLayer = BaseMapLayerSettings.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Hybrid } }); +const legacyMapLayer = BaseMapLayerSettings.fromBackgroundMapProps({ + providerName: "BingProvider", + providerData: { mapType: BackgroundMapType.Hybrid }, +}); describe("ImageMapLayerSettings", () => { const expectMatches = (output: ImageMapLayerProps, expected: ImageMapLayerProps) => { @@ -85,7 +94,6 @@ describe("ImageMapLayerSettings", () => { it("round-trips through JSON", () => { const roundTrip = (input: ImageMapLayerProps, expected: ImageMapLayerProps | "input") => { - if ("input" === expected) expected = JSON.parse(JSON.stringify(input)) as ImageMapLayerProps; @@ -117,14 +125,27 @@ describe("ImageMapLayerSettings", () => { // Turn off visibility clone(testMapLayer0, { visible: false }, { name: "TestName", url: "www.bentley.com", formatId: "WMS", visible: false }); - clone(testMapLayer3, { visible: false }, { name: "TestName", url: "www.bentley.com", formatId: "WMS", subLayers: [testMapSubLayer0, testMapSubLayer1], visible: false }); + clone(testMapLayer3, { visible: false }, { + name: "TestName", + url: "www.bentley.com", + formatId: "WMS", + subLayers: [testMapSubLayer0, testMapSubLayer1], + visible: false, + }); // turn on visibility clone(testMapLayer6, { visible: true }, { name: "TestName", url: "www.bentley.com", formatId: "WMS", visible: true }); // Set transparency clone(testMapLayer0, { transparency: .5 }, { name: "TestName", url: "www.bentley.com", formatId: "WMS", transparency: .5, visible: true }); - clone(testMapLayer3, { transparency: .5 }, { name: "TestName", url: "www.bentley.com", formatId: "WMS", subLayers: [testMapSubLayer0, testMapSubLayer1], transparency: .5, visible: true }); + clone(testMapLayer3, { transparency: .5 }, { + name: "TestName", + url: "www.bentley.com", + formatId: "WMS", + subLayers: [testMapSubLayer0, testMapSubLayer1], + transparency: .5, + visible: true, + }); // Test settings not part of ImageMapLayerProps const settings1 = ImageMapLayerSettings.fromJSON(testMapLayer0); diff --git a/core/common/src/test/ModelGeometryChanges.test.ts b/core/common/src/test/ModelGeometryChanges.test.ts index 70171bd1ed5b..fcd16c769277 100644 --- a/core/common/src/test/ModelGeometryChanges.test.ts +++ b/core/common/src/test/ModelGeometryChanges.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { CompressedId64Set, DbOpcode, Guid, Id64String, OrderedId64Iterable, TransientIdSequence } from "@itwin/core-bentley"; import { Range3d, Range3dProps } from "@itwin/core-geometry"; +import { describe, expect, it } from "vitest"; import { ElementGeometryChange, ModelGeometryChanges, ModelGeometryChangesProps } from "../ModelGeometryChanges"; // Each test is list of inserted, updated, and/or deleted element Ids; along with modelId. @@ -90,7 +90,9 @@ function elementChangesToJSON(changes: ElementChangeSets): ModelGeometryChangesP const inserted = insertedIds && insertedRanges ? { ids: insertedIds, ranges: insertedRanges } : undefined; const updated = updatedIds && updatedRanges ? { ids: updatedIds, ranges: updatedRanges } : undefined; return { - inserted, updated, deleted, + inserted, + updated, + deleted, id: ids.getNext(), guid: Guid.createValue(), range: nextRange().toJSON(), diff --git a/core/common/src/test/ModelMapLayerSettings.test.ts b/core/common/src/test/ModelMapLayerSettings.test.ts index 2f90cf3eeac4..b3d1a6868939 100644 --- a/core/common/src/test/ModelMapLayerSettings.test.ts +++ b/core/common/src/test/ModelMapLayerSettings.test.ts @@ -21,7 +21,6 @@ describe("ModelMapLayerSettings", () => { it("round-trips through JSON", () => { const roundTrip = (input: ModelMapLayerProps, expected: ModelMapLayerProps | "input") => { - if ("input" === expected) expected = JSON.parse(JSON.stringify(input)) as ModelMapLayerProps; diff --git a/core/common/src/test/OctEncodedNormal.test.ts b/core/common/src/test/OctEncodedNormal.test.ts index c78069c0208c..c7f70d7f91fe 100644 --- a/core/common/src/test/OctEncodedNormal.test.ts +++ b/core/common/src/test/OctEncodedNormal.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, it } from "vitest"; import { Vector3d, XYZ } from "@itwin/core-geometry"; +import { assert, describe, it } from "vitest"; import { OctEncodedNormal } from "../OctEncodedNormal"; function _expectSignsEqual(a: number, b: number) { diff --git a/core/common/src/test/Placement.test.ts b/core/common/src/test/Placement.test.ts index 1a38ead07610..89a2ba8f55ad 100644 --- a/core/common/src/test/Placement.test.ts +++ b/core/common/src/test/Placement.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, it } from "vitest"; import { Angle, Matrix3d, Point2d, Point3d, Range2d, Range3d, Transform, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, describe, it } from "vitest"; import { Placement2d, Placement3d } from "../core-common"; describe("Placement", () => { @@ -17,7 +17,12 @@ describe("Placement", () => { placement.multiplyTransform(translation); assert.deepEqual(placement.origin, new Point3d(1, 3, 0)); assert.deepEqual(placement.calculateRange(), new Range3d(-4, -2, -2, 6, 8, 2)); - const invalidTransform: Transform = Transform.createOriginAndMatrixColumns(Point3d.createZero(), Vector3d.unitX(2), Vector3d.unitY(1), Vector3d.unitZ(1)); + const invalidTransform: Transform = Transform.createOriginAndMatrixColumns( + Point3d.createZero(), + Vector3d.unitX(2), + Vector3d.unitY(1), + Vector3d.unitZ(1), + ); assert.exists(invalidTransform); assert.throws(() => placement.multiplyTransform(invalidTransform)); }); @@ -32,7 +37,12 @@ describe("Placement", () => { placement.multiplyTransform(translation); assert.deepEqual(placement.origin, new Point2d(1, 3)); assert.deepEqual(placement.calculateRange(), new Range3d(-4, -2, -1, 6, 8, 1)); - const invalidTransform: Transform = Transform.createOriginAndMatrixColumns(Point3d.createZero(), Vector3d.unitX(2), Vector3d.unitY(1), Vector3d.unitZ(1)); + const invalidTransform: Transform = Transform.createOriginAndMatrixColumns( + Point3d.createZero(), + Vector3d.unitX(2), + Vector3d.unitY(1), + Vector3d.unitZ(1), + ); assert.exists(invalidTransform); assert.throws(() => placement.multiplyTransform(invalidTransform)); const invalidRotation: Transform = Transform.createOriginAndMatrix(undefined, Matrix3d.create90DegreeRotationAroundAxis(1)); diff --git a/core/common/src/test/PlanProjectionSettings.test.ts b/core/common/src/test/PlanProjectionSettings.test.ts index 426fd74c5d4b..bb409246640f 100644 --- a/core/common/src/test/PlanProjectionSettings.test.ts +++ b/core/common/src/test/PlanProjectionSettings.test.ts @@ -67,7 +67,12 @@ describe("PlanProjectionSettings", () => { clone({}, { elevation: 1, transparency: 0.2 }, { elevation: 1, transparency: 0.2, overlay: false, enforceDisplayPriority: false }); clone({ elevation: 1, transparency: 0.2 }, {}, { elevation: 1, transparency: 0.2, overlay: false, enforceDisplayPriority: false }); clone({ elevation: 1, overlay: true }, { transparency: 0.2 }, { elevation: 1, transparency: 0.2, overlay: true, enforceDisplayPriority: false }); - clone({ elevation: 1 }, { elevation: -1, transparency: 0.75 }, { elevation: -1, transparency: 0.75, overlay: false, enforceDisplayPriority: false }); + clone({ elevation: 1 }, { elevation: -1, transparency: 0.75 }, { + elevation: -1, + transparency: 0.75, + overlay: false, + enforceDisplayPriority: false, + }); clone({}, undefined, { enforceDisplayPriority: false, overlay: false }); clone({ enforceDisplayPriority: true }, undefined, { enforceDisplayPriority: true, overlay: false }); diff --git a/core/common/src/test/PlanarClipMaskSettings.test.ts b/core/common/src/test/PlanarClipMaskSettings.test.ts index e17e79f4fd54..c646176199d6 100644 --- a/core/common/src/test/PlanarClipMaskSettings.test.ts +++ b/core/common/src/test/PlanarClipMaskSettings.test.ts @@ -28,26 +28,39 @@ describe("PlanarClipMaskSettings", () => { }); it("creates for models", () => { - expectProps(PlanarClipMaskSettings.create({ }), { mode: PlanarClipMaskMode.Models }); + expectProps(PlanarClipMaskSettings.create({}), { mode: PlanarClipMaskMode.Models }); expectProps(PlanarClipMaskSettings.create({ modelIds: undefined }), { mode: PlanarClipMaskMode.Models }); expectProps(PlanarClipMaskSettings.create({ modelIds: ["0x3", "0x1"] }), { mode: PlanarClipMaskMode.Models, modelIds: "+1+2" }); - expectProps(PlanarClipMaskSettings.create({ modelIds: "0xabc", transparency: 0.5 }), { mode: PlanarClipMaskMode.Models, modelIds: "+ABC", transparency: 0.5 }); + expectProps(PlanarClipMaskSettings.create({ modelIds: "0xabc", transparency: 0.5 }), { + mode: PlanarClipMaskMode.Models, + modelIds: "+ABC", + transparency: 0.5, + }); }); it("creates for elements or subcategories", () => { - expectProps(PlanarClipMaskSettings.create({ elementIds: "0x5" }), - { mode: PlanarClipMaskMode.IncludeElements, subCategoryOrElementIds: "+5"}); + expectProps(PlanarClipMaskSettings.create({ elementIds: "0x5" }), { mode: PlanarClipMaskMode.IncludeElements, subCategoryOrElementIds: "+5" }); - expectProps(PlanarClipMaskSettings.create({ elementIds: ["0x1", "0x5"], modelIds: "0x2", exclude: true }), - { mode: PlanarClipMaskMode.ExcludeElements, subCategoryOrElementIds: "+1+4", modelIds: "+2" }); + expectProps(PlanarClipMaskSettings.create({ elementIds: ["0x1", "0x5"], modelIds: "0x2", exclude: true }), { + mode: PlanarClipMaskMode.ExcludeElements, + subCategoryOrElementIds: "+1+4", + modelIds: "+2", + }); - expectProps(PlanarClipMaskSettings.create({ subCategoryIds: "0x2", transparency: 0.5 }), - { mode: PlanarClipMaskMode.IncludeSubCategories, subCategoryOrElementIds: "+2", transparency: 0.5 }); + expectProps(PlanarClipMaskSettings.create({ subCategoryIds: "0x2", transparency: 0.5 }), { + mode: PlanarClipMaskMode.IncludeSubCategories, + subCategoryOrElementIds: "+2", + transparency: 0.5, + }); }); it("creates by priority", () => { expectProps(PlanarClipMaskSettings.create({ priority: 1234 }), { mode: PlanarClipMaskMode.Priority, priority: 1234 }); - expectProps(PlanarClipMaskSettings.create({ priority: -321, transparency: 0.75 }), { mode: PlanarClipMaskMode.Priority, priority: -321, transparency: 0.75 }); + expectProps(PlanarClipMaskSettings.create({ priority: -321, transparency: 0.75 }), { + mode: PlanarClipMaskMode.Priority, + priority: -321, + transparency: 0.75, + }); }); it("clones", () => { @@ -65,9 +78,16 @@ describe("PlanarClipMaskSettings", () => { expect(src.clone(changed).toJSON()).to.deep.equal(expected); } - expectClone({ mode: PlanarClipMaskMode.Models, subCategoryOrElementIds: undefined }, - { mode: PlanarClipMaskMode.Models, priority: 12, modelIds: "+1+5", transparency: 0.5 }); - expectClone({ transparency: undefined, priority: undefined, mode: PlanarClipMaskMode.None }, - { mode: PlanarClipMaskMode.None, modelIds: "+1+5", subCategoryOrElementIds: "+2+4" }); + expectClone({ mode: PlanarClipMaskMode.Models, subCategoryOrElementIds: undefined }, { + mode: PlanarClipMaskMode.Models, + priority: 12, + modelIds: "+1+5", + transparency: 0.5, + }); + expectClone({ transparency: undefined, priority: undefined, mode: PlanarClipMaskMode.None }, { + mode: PlanarClipMaskMode.None, + modelIds: "+1+5", + subCategoryOrElementIds: "+2+4", + }); }); }); diff --git a/core/common/src/test/QPoint.test.ts b/core/common/src/test/QPoint.test.ts index 5733fcb479a3..692753f451ef 100644 --- a/core/common/src/test/QPoint.test.ts +++ b/core/common/src/test/QPoint.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { Point3d, Range3d } from "@itwin/core-geometry"; +import { describe, expect, it } from "vitest"; import { QParams3d, QPoint3d } from "../QPoint"; function expectPointsEqual(lhs: Point3d, rhs: Point3d, tolerance: number) { diff --git a/core/common/src/test/RealityModelDisplaySettings.test.ts b/core/common/src/test/RealityModelDisplaySettings.test.ts index 1a3c0cecd243..e2403ad4d36f 100644 --- a/core/common/src/test/RealityModelDisplaySettings.test.ts +++ b/core/common/src/test/RealityModelDisplaySettings.test.ts @@ -5,7 +5,10 @@ import { describe, expect, it } from "vitest"; import { - PointCloudDisplayProps, PointCloudDisplaySettings, RealityModelDisplayProps, RealityModelDisplaySettings, + PointCloudDisplayProps, + PointCloudDisplaySettings, + RealityModelDisplayProps, + RealityModelDisplaySettings, } from "../RealityModelDisplaySettings"; describe("PointCloudDisplaySettings", () => { @@ -27,8 +30,11 @@ describe("PointCloudDisplaySettings", () => { roundTrip(undefined, undefined); roundTrip({ sizeMode: "voxel", voxelScale: 1, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 20, pixelSize: 1, shape: "round" }, undefined); roundTrip({ sizeMode: "pixel", voxelScale: 2, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 10, pixelSize: 2, shape: "square" }, "input"); - roundTrip({ sizeMode: "voxel", voxelScale: 2, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 10, pixelSize: 2, shape: "round" }, - { voxelScale: 2, maxPixelsPerVoxel: 10, pixelSize: 2 }); + roundTrip({ sizeMode: "voxel", voxelScale: 2, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 10, pixelSize: 2, shape: "round" }, { + voxelScale: 2, + maxPixelsPerVoxel: 10, + pixelSize: 2, + }); roundTrip({ shape: "round" }, undefined); roundTrip({ shape: "square" }, "input"); @@ -40,7 +46,11 @@ describe("PointCloudDisplaySettings", () => { }); it("clones", () => { - const test = (baseProps: PointCloudDisplayProps | undefined, changedProps: PointCloudDisplayProps, expected: PointCloudDisplayProps | undefined | "input") => { + const test = ( + baseProps: PointCloudDisplayProps | undefined, + changedProps: PointCloudDisplayProps, + expected: PointCloudDisplayProps | undefined | "input", + ) => { if (expected === "input") expected = baseProps; @@ -51,12 +61,23 @@ describe("PointCloudDisplaySettings", () => { }; test(undefined, { sizeMode: "voxel", voxelScale: 1, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 20, pixelSize: 1, shape: "round" }, "input"); - test({ voxelScale: 2, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 10, pixelSize: 1 }, { voxelScale: 0.5, maxPixelsPerVoxel: 12 }, { voxelScale: 0.5, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 12 }); - test({ voxelScale: 2, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 4, pixelSize: 5, sizeMode: "voxel", shape: "square" }, - { voxelScale: undefined, minPixelsPerVoxel: undefined, maxPixelsPerVoxel: undefined, pixelSize: undefined, sizeMode: undefined, shape: undefined }, - undefined, - ); - test({ voxelScale: 2, pixelSize: 3, minPixelsPerVoxel: 4 }, { pixelSize: undefined, minPixelsPerVoxel: 5 }, { voxelScale: 2, minPixelsPerVoxel: 5 }); + test({ voxelScale: 2, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 10, pixelSize: 1 }, { voxelScale: 0.5, maxPixelsPerVoxel: 12 }, { + voxelScale: 0.5, + minPixelsPerVoxel: 3, + maxPixelsPerVoxel: 12, + }); + test({ voxelScale: 2, minPixelsPerVoxel: 3, maxPixelsPerVoxel: 4, pixelSize: 5, sizeMode: "voxel", shape: "square" }, { + voxelScale: undefined, + minPixelsPerVoxel: undefined, + maxPixelsPerVoxel: undefined, + pixelSize: undefined, + sizeMode: undefined, + shape: undefined, + }, undefined); + test({ voxelScale: 2, pixelSize: 3, minPixelsPerVoxel: 4 }, { pixelSize: undefined, minPixelsPerVoxel: 5 }, { + voxelScale: 2, + minPixelsPerVoxel: 5, + }); }); }); @@ -79,7 +100,10 @@ describe("RealityModelDisplaySettings", () => { roundTrip(undefined, undefined); roundTrip({ overrideColorRatio: 0.5 }, undefined); roundTrip({ overrideColorRatio: 0.5, pointCloud: undefined }, undefined); - roundTrip({ overrideColorRatio: 0.5, pointCloud: { sizeMode: "voxel", voxelScale: 1, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 20, pixelSize: 1, shape: "round" } }, undefined); + roundTrip({ + overrideColorRatio: 0.5, + pointCloud: { sizeMode: "voxel", voxelScale: 1, minPixelsPerVoxel: 2, maxPixelsPerVoxel: 20, pixelSize: 1, shape: "round" }, + }, undefined); roundTrip({ overrideColorRatio: 0.1 }, "input"); roundTrip({ overrideColorRatio: 0 }, "input"); @@ -91,7 +115,11 @@ describe("RealityModelDisplaySettings", () => { }); it("clones", () => { - const test = (baseProps: RealityModelDisplayProps | undefined, changedProps: RealityModelDisplayProps, expected: RealityModelDisplayProps | undefined | "input") => { + const test = ( + baseProps: RealityModelDisplayProps | undefined, + changedProps: RealityModelDisplayProps, + expected: RealityModelDisplayProps | undefined | "input", + ) => { if (expected === "input") expected = baseProps; @@ -106,7 +134,10 @@ describe("RealityModelDisplaySettings", () => { test({ overrideColorRatio: 2 }, { overrideColorRatio: 3 }, { overrideColorRatio: 3 }); test({ pointCloud: { sizeMode: "pixel" } }, { overrideColorRatio: 2 }, { pointCloud: { sizeMode: "pixel" }, overrideColorRatio: 2 }); test({ pointCloud: { sizeMode: "pixel" } }, { pointCloud: { pixelSize: 2 } }, { pointCloud: { sizeMode: "pixel", pixelSize: 2 } }); - test({ pointCloud: { sizeMode: "pixel" }, overrideColorRatio: 2 }, { pointCloud: { sizeMode: undefined} }, { overrideColorRatio: 2 }); - test({ pointCloud: { sizeMode: "pixel" }, overrideColorRatio: 2 }, { pointCloud: { } }, { overrideColorRatio: 2, pointCloud: { sizeMode: "pixel" } }); + test({ pointCloud: { sizeMode: "pixel" }, overrideColorRatio: 2 }, { pointCloud: { sizeMode: undefined } }, { overrideColorRatio: 2 }); + test({ pointCloud: { sizeMode: "pixel" }, overrideColorRatio: 2 }, { pointCloud: {} }, { + overrideColorRatio: 2, + pointCloud: { sizeMode: "pixel" }, + }); }); }); diff --git a/core/common/src/test/Render.test.ts b/core/common/src/test/Render.test.ts index 2d5cb6be695a..ad6620f55a9b 100644 --- a/core/common/src/test/Render.test.ts +++ b/core/common/src/test/Render.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, it } from "vitest"; import { Id64 } from "@itwin/core-bentley"; +import { assert, describe, it } from "vitest"; import { Feature } from "../FeatureTable"; import { GeometryClass } from "../GeometryParams"; diff --git a/core/common/src/test/RenderSchedule.test.ts b/core/common/src/test/RenderSchedule.test.ts index f5fb00afac46..dba9a6827589 100644 --- a/core/common/src/test/RenderSchedule.test.ts +++ b/core/common/src/test/RenderSchedule.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { CompressedId64Set } from "@itwin/core-bentley"; import { Matrix3d, Point3d, Point4d, Transform, TransformProps } from "@itwin/core-geometry"; +import { describe, expect, it } from "vitest"; import { RenderSchedule as RS } from "../RenderSchedule"; import { RgbColor } from "../RgbColor"; @@ -138,31 +138,39 @@ describe("RenderSchedule", () => { expect(actual.isAlmostEqual(Transform.fromJSON(expected))).to.be.true; } - expectTransform(script.duration.low, [[1,0,0,7860.699219],[0,1,0,8590.857422],[0,0,1,-39.539063]]); + expectTransform(script.duration.low, [[1, 0, 0, 7860.699219], [0, 1, 0, 8590.857422], [0, 0, 1, -39.539063]]); expectTransform(script.duration.high, [ - [0.966043,0.208746,-0.152273,117478.09375], - [-0.207021,0.977956,0.02728,-39223.738281], - [0.15461,0.00517,0.987962,18307.048828], + [0.966043, 0.208746, -0.152273, 117478.09375], + [-0.207021, 0.977956, 0.02728, -39223.738281], + [0.15461, 0.00517, 0.987962, 18307.048828], ]); expectTransform(script.duration.fractionToPoint(0.5), [ - [0.9542084100696944,-0.29673855635648877,-0.037848901222266286,71759.88767870933], - [0.29684190212797457,0.9549219611634173,-0.002988850758880856,21679.967974600604], - [0.03702965424240229,-0.008383153301704048,0.9992790038059481,2437.9638765390373], + [0.9542084100696944, -0.29673855635648877, -0.037848901222266286, 71759.88767870933], + [0.29684190212797457, 0.9549219611634173, -0.002988850758880856, 21679.967974600604], + [0.03702965424240229, -0.008383153301704048, 0.9992790038059481, 2437.9638765390373], ]); }); it("interpolates visibility", () => { const props: RS.TimelineProps = { visibilityTimeline: [{ - interpolation: 2, time: 1254330000, value: undefined, + interpolation: 2, + time: 1254330000, + value: undefined, }, { - interpolation: 2, time: 1369123200, value: 70, + interpolation: 2, + time: 1369123200, + value: 70, }, { - interpolation: 2, time: 1369123260, value: 69, + interpolation: 2, + time: 1369123260, + value: 69, }, { - interpolation: 1, time: 1370710740, value: 30, + interpolation: 1, + time: 1370710740, + value: 30, }], }; @@ -200,7 +208,7 @@ describe("RenderSchedule", () => { expectIds(["0x5", "0x1"], "+1+4"); }); - it ("assigns unique consecutive batch Ids", () => { + it("assigns unique consecutive batch Ids", () => { const script = new RS.ScriptBuilder(); const modelA = script.addModelTimeline("0xa"); const modelB = script.addModelTimeline("0xb"); @@ -239,7 +247,7 @@ describe("RenderSchedule", () => { }], }], }, { - modelId:"0x2", + modelId: "0x2", realityModelUrl: "https://google.com", elementTimelines: [{ elementIds: "+ABC", @@ -248,16 +256,16 @@ describe("RenderSchedule", () => { time: 400, interpolation: linear, value: { - transform: [ [ 1, 0, 0, 4 ], [ 0, 1, 0, 5 ], [ 0, 0, 1, 6] ], + transform: [[1, 0, 0, 4], [0, 1, 0, 5], [0, 0, 1, 6]], }, }, { time: 500, interpolation: linear, value: { - transform: [ [ 1, 0, 0, 4 ], [ 0, 1, 0, 5 ], [ 0, 0, 1, 6] ], - pivot: [ 1, 2, 3 ], - orientation: [ 4, 5, 6, 7 ], - position: [ 8, 9, 0 ], + transform: [[1, 0, 0, 4], [0, 1, 0, 5], [0, 0, 1, 6]], + pivot: [1, 2, 3], + orientation: [4, 5, 6, 7], + position: [8, 9, 0], }, }], }, { @@ -267,8 +275,8 @@ describe("RenderSchedule", () => { time: 600, interpolation: linear, value: { - position: [ 1, 2, 3 ], - direction: [ 0, 0, -1 ], + position: [1, 2, 3], + direction: [0, 0, -1], visible: true, }, }], @@ -288,7 +296,11 @@ describe("RenderSchedule", () => { const elem2 = model2.addElementTimeline(["0xabc"]); elem2.addTransform(400, Transform.createRefs(new Point3d(4, 5, 6), Matrix3d.createIdentity())); - elem2.addTransform(500, Transform.createRefs(new Point3d(4, 5, 6), Matrix3d.createIdentity()), { pivot: new Point3d(1, 2, 3), position: new Point3d(8, 9, 0), orientation: Point4d.create(4, 5, 6, 7) }); + elem2.addTransform(500, Transform.createRefs(new Point3d(4, 5, 6), Matrix3d.createIdentity()), { + pivot: new Point3d(1, 2, 3), + position: new Point3d(8, 9, 0), + orientation: Point4d.create(4, 5, 6, 7), + }); const elem3 = model2.addElementTimeline(["0xdef"]); elem3.addCuttingPlane(600, { position: new Point3d(1, 2, 3), direction: new Point3d(0, 0, -1), visible: true }); @@ -332,8 +344,14 @@ describe("RenderSchedule", () => { expectEqual(new RS.ColorEntry({ time: 1, interpolation: 1 }), new RS.ColorEntry({ time: 1, interpolation: 1 })); expectUnequal(new RS.ColorEntry({ time: 1, interpolation: 1 }), new RS.ColorEntry({ time: 1, interpolation: 2 })); - expectEqual(new RS.ColorEntry({ time: 1, value: { red: 1, green: 2, blue: 3 } }), new RS.ColorEntry({time: 1, value: { red: 1, green: 2, blue: 3 } })); - expectUnequal(new RS.ColorEntry({ time: 1, value: { red: 1, green: 2, blue: 3 } }), new RS.ColorEntry({time: 1, value: { red: 3, green: 2, blue: 1 } })); + expectEqual( + new RS.ColorEntry({ time: 1, value: { red: 1, green: 2, blue: 3 } }), + new RS.ColorEntry({ time: 1, value: { red: 1, green: 2, blue: 3 } }), + ); + expectUnequal( + new RS.ColorEntry({ time: 1, value: { red: 1, green: 2, blue: 3 } }), + new RS.ColorEntry({ time: 1, value: { red: 3, green: 2, blue: 1 } }), + ); }); }); @@ -371,7 +389,7 @@ describe("RenderSchedule", () => { expectEqual(new RS.TransformEntry({ time: 1, value: cmp(1, 2, 3) }), new RS.TransformEntry({ time: 1, value: cmp(1, 2, 3) })); expectUnequal(new RS.TransformEntry({ time: 1, value: cmp(1, 2, 3) }), new RS.TransformEntry({ time: 1, value: cmp(3, 2, 1) })); - expectUnequal(new RS.TransformEntry({time: 1, value: tf(1, 2, 3, 4) }), new RS.TransformEntry({ time: 1, value: cmp(1, 2, 3) })); + expectUnequal(new RS.TransformEntry({ time: 1, value: tf(1, 2, 3, 4) }), new RS.TransformEntry({ time: 1, value: cmp(1, 2, 3) })); }); }); @@ -408,14 +426,20 @@ describe("RenderSchedule", () => { const compressedIds = CompressedId64Set.compressArray(elementIds); expectEqual(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds })); - expectEqual(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: compressedIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: compressedIds })); + expectEqual( + RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: compressedIds }), + RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: compressedIds }), + ); expectEqual(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: compressedIds })); expectUnequal(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 5, elementIds })); expectUnequal(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: ["0xabc"] })); expectUnequal(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: ["0x1", "0x5"] })); - expectUnequal(RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: ["0x1", "0x5", "0xdef"] })); + expectUnequal( + RS.ElementTimeline.fromJSON({ batchId: 4, elementIds }), + RS.ElementTimeline.fromJSON({ batchId: 4, elementIds: ["0x1", "0x5", "0xdef"] }), + ); const v1 = { time: 3, interpolation: 1, value: 1 }; const v2 = { time: 4, interpolation: 2, value: 2 }; @@ -473,12 +497,24 @@ describe("RenderSchedule", () => { describe("ModelTimeline", () => { it("compares for equality", () => { const elementTimelines: RS.ElementTimelineProps[] = []; - expectEqual(RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines })); + expectEqual( + RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), + RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), + ); expectEqual(RS.ModelTimeline.fromJSON({ modelId: "0x2", elementTimelines }), RS.ModelTimeline.fromJSON({ modelId: "0x2", elementTimelines })); - expectUnequal(RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines })); - expectUnequal(RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), RS.ModelTimeline.fromJSON({ modelId: "0x2", realityModelUrl: "blah", elementTimelines })); - expectUnequal(RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines }), RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines: [{ batchId: 0, elementIds: ["0x2"] }] })); + expectUnequal( + RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), + RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines }), + ); + expectUnequal( + RS.ModelTimeline.fromJSON({ modelId: "0x1", realityModelUrl: "blah", elementTimelines }), + RS.ModelTimeline.fromJSON({ modelId: "0x2", realityModelUrl: "blah", elementTimelines }), + ); + expectUnequal( + RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines }), + RS.ModelTimeline.fromJSON({ modelId: "0x1", elementTimelines: [{ batchId: 0, elementIds: ["0x2"] }] }), + ); }); }); @@ -494,8 +530,8 @@ describe("RenderSchedule", () => { it("weakly caches previous comparisons", () => { const elementTimelines: RS.ElementTimelineProps[] = []; - const s1 = RS.Script.fromJSON([{modelId: "0x1", elementTimelines}])!; - const s2 = RS.Script.fromJSON([{modelId: "0x2", elementTimelines}])!; + const s1 = RS.Script.fromJSON([{ modelId: "0x1", elementTimelines }])!; + const s2 = RS.Script.fromJSON([{ modelId: "0x2", elementTimelines }])!; function spy(timeline: any): void { timeline.compared = false; diff --git a/core/common/src/test/SolarCalculate.test.ts b/core/common/src/test/SolarCalculate.test.ts index d17e565c8e92..956deaeb128a 100644 --- a/core/common/src/test/SolarCalculate.test.ts +++ b/core/common/src/test/SolarCalculate.test.ts @@ -6,7 +6,14 @@ import { assert, describe, it } from "vitest"; import { Cartographic } from "../geometry/Cartographic"; import { calculateSolarAngles, calculateSunriseOrSunset } from "../SolarCalculate"; -function testSolarAngleCalculation(location: Cartographic, dateString: string, expectedAzimuth: number, expectedElevation: number, expectedSunriseString?: string, expectedSunsetString?: string) { +function testSolarAngleCalculation( + location: Cartographic, + dateString: string, + expectedAzimuth: number, + expectedElevation: number, + expectedSunriseString?: string, + expectedSunsetString?: string, +) { const date = new Date(dateString); const azEl = calculateSolarAngles(date, location); assert(Math.abs(azEl.azimuth - expectedAzimuth) < .05 && Math.abs(azEl.elevation - expectedElevation) < .05); @@ -25,12 +32,32 @@ function testSolarAngleCalculation(location: Cartographic, dateString: string, e } describe("Solar Calculations", () => { - it("should compare as expected", () => { const philadelphia = Cartographic.fromDegrees({ longitude: -75.17035, latitude: 39.954927, height: 0.0 }); - testSolarAngleCalculation(philadelphia, "May 03 2019 12:00:00 GMT -0500", 181.42, 65.78, "May 03 2019 04:59 GMT -0500", "May 03 2019 18:57 GMT -0500"); - testSolarAngleCalculation(philadelphia, "Sep 03 2019 12:00:00 GMT -0500", 179.96, 57.53, "Sep 03 2019 05:30 GMT -0500", "Sep 03 2019 18:29 GMT -0500"); - testSolarAngleCalculation(philadelphia, "Feb 03 2019 12:00:00 GMT -0500", 175.84, 33.51, "Feb 03 2019 07:07 GMT -0500", "Feb 03 2019 17:22 GMT -0500"); + testSolarAngleCalculation( + philadelphia, + "May 03 2019 12:00:00 GMT -0500", + 181.42, + 65.78, + "May 03 2019 04:59 GMT -0500", + "May 03 2019 18:57 GMT -0500", + ); + testSolarAngleCalculation( + philadelphia, + "Sep 03 2019 12:00:00 GMT -0500", + 179.96, + 57.53, + "Sep 03 2019 05:30 GMT -0500", + "Sep 03 2019 18:29 GMT -0500", + ); + testSolarAngleCalculation( + philadelphia, + "Feb 03 2019 12:00:00 GMT -0500", + 175.84, + 33.51, + "Feb 03 2019 07:07 GMT -0500", + "Feb 03 2019 17:22 GMT -0500", + ); const algeria = Cartographic.fromDegrees({ longitude: 2.54882812, latitude: 27.761329, height: 0.0 }); testSolarAngleCalculation(algeria, "May 03 2019 12:00:00 GMT -0000", 194.96, 77.53); testSolarAngleCalculation(algeria, "Sep 03 2019 12:00:00 GMT -0000", 187.66, 69.64); diff --git a/core/common/src/test/SpatialClassification.test.ts b/core/common/src/test/SpatialClassification.test.ts index 0ffad2a92aef..03b83bae75f6 100644 --- a/core/common/src/test/SpatialClassification.test.ts +++ b/core/common/src/test/SpatialClassification.test.ts @@ -3,10 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { Id64String } from "@itwin/core-bentley"; +import { describe, expect, it } from "vitest"; import { - SpatialClassifier, SpatialClassifierFlags, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, SpatialClassifierProps, SpatialClassifiers, + SpatialClassifier, + SpatialClassifierFlags, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + SpatialClassifierProps, + SpatialClassifiers, SpatialClassifiersContainer, } from "../SpatialClassification"; @@ -82,7 +87,9 @@ describe("SpatialClassifiers", () => { it("sets active classifier", () => { const classifiers = [ - makeClassifier("0x1", "1"), makeClassifier("0x2", "2"), makeClassifier("0x3", "3"), + makeClassifier("0x1", "1"), + makeClassifier("0x2", "2"), + makeClassifier("0x3", "3"), ]; const json = { classifiers: classifiers.map((x) => x.toJSON()) }; @@ -142,7 +149,9 @@ describe("SpatialClassifiers", () => { expect(set.has(c)).to.be.true; expectJson(json.classifiers, [ - makeClassifier("0x1", "1").toJSON(), makeClassifier("0x2", "2").toJSON(), makeClassifier("0x1", "1", undefined, 12).toJSON(), + makeClassifier("0x1", "1").toJSON(), + makeClassifier("0x2", "2").toJSON(), + makeClassifier("0x1", "1", undefined, 12).toJSON(), ]); }); @@ -184,7 +193,9 @@ describe("SpatialClassifiers", () => { it("resets active classifier if deleted", () => { const set = new SpatialClassifiers({ classifiers: [ - makeClassifier("0x1", "1").toJSON(), makeClassifierProps(makeClassifier("0x2", "2"), true), makeClassifier("0x3", "3").toJSON(), + makeClassifier("0x1", "1").toJSON(), + makeClassifierProps(makeClassifier("0x2", "2"), true), + makeClassifier("0x3", "3").toJSON(), ], }); expect(set.active!.name).to.equal("2"); @@ -216,7 +227,8 @@ describe("SpatialClassifiers", () => { it("resets active classifier when cleared", () => { const set = new SpatialClassifiers({ classifiers: [ - makeClassifierProps(makeClassifier("0x1", "1"), true), makeClassifier("0x2", "2").toJSON(), + makeClassifierProps(makeClassifier("0x1", "1"), true), + makeClassifier("0x2", "2").toJSON(), ], }); expect(set.active).not.to.be.undefined; @@ -225,7 +237,9 @@ describe("SpatialClassifiers", () => { }); it("replaces classifiers", () => { - const json = { classifiers: [makeClassifier("0x1", "1").toJSON(), makeClassifier("0x2", "2").toJSON(), makeClassifierProps(makeClassifier("0x3", "3"), true)] }; + const json = { + classifiers: [makeClassifier("0x1", "1").toJSON(), makeClassifier("0x2", "2").toJSON(), makeClassifierProps(makeClassifier("0x3", "3"), true)], + }; const set = new SpatialClassifiers(json); const c2 = set.findEquivalent(makeClassifier("0x2", "2"))!; diff --git a/core/common/src/test/SubCategoryAppearance.test.ts b/core/common/src/test/SubCategoryAppearance.test.ts index 17c7844ce321..895eac76c56b 100644 --- a/core/common/src/test/SubCategoryAppearance.test.ts +++ b/core/common/src/test/SubCategoryAppearance.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, it } from "vitest"; import { Id64 } from "@itwin/core-bentley"; +import { assert, describe, it } from "vitest"; import { ColorByName, ColorDef, SubCategoryAppearance, SubCategoryOverride } from "../core-common"; // spell-checker: disable diff --git a/core/common/src/test/ThematicDisplay.test.ts b/core/common/src/test/ThematicDisplay.test.ts index 22f6ec606633..a4b291a32510 100644 --- a/core/common/src/test/ThematicDisplay.test.ts +++ b/core/common/src/test/ThematicDisplay.test.ts @@ -6,7 +6,14 @@ import { Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { describe, expect, it } from "vitest"; import { ColorDef } from "../ColorDef"; -import { ThematicDisplay, ThematicDisplayMode, ThematicDisplayProps, ThematicDisplaySensorSettings, ThematicGradientColorScheme, ThematicGradientMode } from "../ThematicDisplay"; +import { + ThematicDisplay, + ThematicDisplayMode, + ThematicDisplayProps, + ThematicDisplaySensorSettings, + ThematicGradientColorScheme, + ThematicGradientMode, +} from "../ThematicDisplay"; describe("ThematicDisplay", () => { it("Ensures ThematicDisplay derives values properly from JSON, including handling defaults and incorrect values", () => { diff --git a/core/common/src/test/ThematicGradientSettings.test.ts b/core/common/src/test/ThematicGradientSettings.test.ts index d7586e876768..b188a48c8b38 100644 --- a/core/common/src/test/ThematicGradientSettings.test.ts +++ b/core/common/src/test/ThematicGradientSettings.test.ts @@ -6,7 +6,11 @@ import { describe, expect, it } from "vitest"; import { ColorDef } from "../ColorDef"; import { TextureTransparency } from "../TextureProps"; import { - ThematicGradientColorScheme, ThematicGradientMode, ThematicGradientSettings, ThematicGradientSettingsProps, ThematicGradientTransparencyMode, + ThematicGradientColorScheme, + ThematicGradientMode, + ThematicGradientSettings, + ThematicGradientSettingsProps, + ThematicGradientTransparencyMode, } from "../ThematicDisplay"; describe("ThematicGradientSettings", () => { @@ -17,9 +21,9 @@ describe("ThematicGradientSettings", () => { marginColor: ColorDef.blue.toJSON(), colorScheme: ThematicGradientColorScheme.Topographic, customKeys: [ - {value: 0.0, color: ColorDef.green.toJSON()}, - {value: 0.5, color: ColorDef.red.toJSON()}, - {value: 1.0, color: ColorDef.white.toJSON()}, + { value: 0.0, color: ColorDef.green.toJSON() }, + { value: 0.5, color: ColorDef.red.toJSON() }, + { value: 1.0, color: ColorDef.white.toJSON() }, ], colorMix: 0.5, transparencyMode: ThematicGradientTransparencyMode.MultiplySurfaceAndGradient, @@ -82,11 +86,10 @@ describe("ThematicGradientSettings", () => { // Make sure A !== B when B changes the customKeys. propsB = settingsA.toJSON(); propsB.customKeys = [ - {value: 0.0, color: ColorDef.black.toJSON()}, - {value: 0.5, color: ColorDef.white.toJSON()}, - {value: 1.0, color: ColorDef.green.toJSON()}, - ], - expect(ThematicGradientSettings.compare(settingsA, ThematicGradientSettings.fromJSON(propsB))).to.not.equal(0); + { value: 0.0, color: ColorDef.black.toJSON() }, + { value: 0.5, color: ColorDef.white.toJSON() }, + { value: 1.0, color: ColorDef.green.toJSON() }, + ], expect(ThematicGradientSettings.compare(settingsA, ThematicGradientSettings.fromJSON(propsB))).to.not.equal(0); }); it("computes texture transparency", () => { @@ -97,7 +100,11 @@ describe("ThematicGradientSettings", () => { const props: ThematicGradientSettingsProps = { colorScheme: undefined !== custom ? ThematicGradientColorScheme.Custom : ThematicGradientColorScheme.BlueRed, marginColor: margin.toJSON(), - customKeys: custom ? custom.map((x) => { return { value: 0.5, color: x.toJSON() }; }) : undefined, + customKeys: custom + ? custom.map((x) => { + return { value: 0.5, color: x.toJSON() }; + }) + : undefined, }; const remap = { opaque: TextureTransparency.Opaque, transparent: TextureTransparency.Translucent, mixed: TextureTransparency.Mixed }; diff --git a/core/common/src/test/TileMetadata.test.ts b/core/common/src/test/TileMetadata.test.ts index 6e87932daa31..8b5b2b2bddbe 100644 --- a/core/common/src/test/TileMetadata.test.ts +++ b/core/common/src/test/TileMetadata.test.ts @@ -8,8 +8,18 @@ import { Point3d, Range3d } from "@itwin/core-geometry"; import { describe, expect, it } from "vitest"; import { BatchType } from "../FeatureTable"; import { - ClassifierTileTreeId, computeTileChordTolerance, ContentIdProvider, EdgeOptions, IModelTileTreeId, iModelTileTreeIdToString, - parseTileTreeIdAndContentId, PrimaryTileTreeId, defaultTileOptions as realDefaultTileOptions, TileMetadata, TileOptions, TreeFlags, + ClassifierTileTreeId, + computeTileChordTolerance, + ContentIdProvider, + defaultTileOptions as realDefaultTileOptions, + EdgeOptions, + IModelTileTreeId, + iModelTileTreeIdToString, + parseTileTreeIdAndContentId, + PrimaryTileTreeId, + TileMetadata, + TileOptions, + TreeFlags, } from "../tile/TileMetadata"; // NB: These tests were written when defaultTileOptions specified indexed edges as the default. Now, compact edges are the default. @@ -332,7 +342,12 @@ describe("TileMetadata", () => { }); it("parseTileTreeIdAndContentId round trips", () => { - function test(modelId: Id64String, treeId: IModelTileTreeId, contentId: ReturnType, tileOptions: TileOptions) { + function test( + modelId: Id64String, + treeId: IModelTileTreeId, + contentId: ReturnType, + tileOptions: TileOptions, + ) { const treeIdStr = iModelTileTreeIdToString(modelId, treeId, tileOptions); const contentIdStr = ContentIdProvider.create(true, tileOptions).idFromSpec(contentId); const parsed = parseTileTreeIdAndContentId(treeIdStr, contentIdStr); @@ -351,57 +366,266 @@ describe("TileMetadata", () => { const defaultNoEdges: TileOptions = { ...defaultNoIndexedEdges, edgeOptions: { type: "non-indexed", smooth: false } }; const defaultNoSmoothEdges: TileOptions = { ...defaultTileOptions, edgeOptions: { ...defaultEdgeOptions, smooth: false } }; - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, realDefaultTileOptions); - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, enableInstancing: false }); - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, enableImprovedElision: false }); - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, ignoreAreaPatterns: true }); - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, enableExternalTextures: false }); - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, useProjectExtents: false }); + test( + "0x1c", + { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, + { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, + realDefaultTileOptions, + ); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + enableInstancing: false, + }); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + enableImprovedElision: false, + }); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + ignoreAreaPatterns: true, + }); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + enableExternalTextures: false, + }); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + useProjectExtents: false, + }); // disableMagnification and alwaysSubdivideIncompleteTiles intentionally left out - they're not included in tileTreeId and contentId strings - test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { ...realDefaultTileOptions, enableInstancing: false, enableImprovedElision: false, ignoreAreaPatterns: true, enableExternalTextures: false, useProjectExtents: false }); - - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1000000d", { type: BatchType.Primary, edges: false, animationId: "0x105", animationTransformNodeId: 50 } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); - - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoSmoothEdges); - - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoIndexedEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoIndexedEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoIndexedEdges); - test("0x1000000d", { type: BatchType.Primary, edges: false, animationId: "0x105", animationTransformNodeId: 50 } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); - - test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoIndexedEdges); - - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultTileOptions); - - test("0x1d", { type: BatchType.VolumeClassifier, expansion: 50 } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1000000d", { type: BatchType.VolumeClassifier, expansion: 50, animationId: "0x50000001" } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1000000d", { type: BatchType.VolumeClassifier, expansion: 50, animationId: "0x50000001", animationTransformNodeId: 500 } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - - test("0x1d", { type: BatchType.PlanarClassifier, expansion: 50 } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1000000d", { type: BatchType.PlanarClassifier, expansion: 50, animationId: "0x50000001" } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - test("0x1000000d", { type: BatchType.PlanarClassifier, expansion: 50, animationId: "0x50000001", animationTransformNodeId: 500 } as ClassifierTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, defaultNoEdges); - - const realDefaultNoSmoothEdges: TileOptions = { ...realDefaultTileOptions, edgeOptions: { type: "compact", smooth: false } }; - - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultNoSmoothEdges); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true } } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); - test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, realDefaultTileOptions); + test("0x1c", { type: BatchType.Primary, edges: false } as PrimaryTileTreeId, { depth: 2, i: 5, j: 400, k: 16, multiplier: 8 }, { + ...realDefaultTileOptions, + enableInstancing: false, + enableImprovedElision: false, + ignoreAreaPatterns: true, + enableExternalTextures: false, + useProjectExtents: false, + }); + + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoEdges); + test("0x1000000d", { type: BatchType.Primary, edges: false, animationId: "0x105", animationTransformNodeId: 50 } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultTileOptions); + + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "non-indexed", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoEdges, + ); + + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoSmoothEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoSmoothEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoSmoothEdges); + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "indexed", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoSmoothEdges, + ); + + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoIndexedEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoIndexedEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoIndexedEdges); + test("0x1000000d", { type: BatchType.Primary, edges: false, animationId: "0x105", animationTransformNodeId: 50 } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultTileOptions); + + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "non-indexed", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoIndexedEdges, + ); + + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultTileOptions); + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultTileOptions); + test("0x1d", { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultTileOptions); + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "indexed", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultTileOptions, + ); + + test( + "0x1d", + { type: BatchType.VolumeClassifier, expansion: 50 } as ClassifierTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoEdges, + ); + test("0x1000000d", { type: BatchType.VolumeClassifier, expansion: 50, animationId: "0x50000001" } as ClassifierTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoEdges); + test( + "0x1000000d", + { type: BatchType.VolumeClassifier, expansion: 50, animationId: "0x50000001", animationTransformNodeId: 500 } as ClassifierTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoEdges, + ); + + test( + "0x1d", + { type: BatchType.PlanarClassifier, expansion: 50 } as ClassifierTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoEdges, + ); + test("0x1000000d", { type: BatchType.PlanarClassifier, expansion: 50, animationId: "0x50000001" } as ClassifierTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, defaultNoEdges); + test( + "0x1000000d", + { type: BatchType.PlanarClassifier, expansion: 50, animationId: "0x50000001", animationTransformNodeId: 500 } as ClassifierTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + defaultNoEdges, + ); + + const realDefaultNoSmoothEdges: TileOptions = { ...realDefaultTileOptions, edgeOptions: { type: "compact", smooth: false } }; + + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultNoSmoothEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultNoSmoothEdges); + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: false }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultNoSmoothEdges); + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "compact", smooth: false }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + realDefaultNoSmoothEdges, + ); + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true } } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultTileOptions); + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true }, enforceDisplayPriority: true } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultTileOptions); + test("0x1d", { type: BatchType.Primary, edges: { type: "compact", smooth: true }, animationId: "0x105" } as PrimaryTileTreeId, { + depth: 20, + i: 50, + j: 4, + k: 1, + multiplier: 1, + }, realDefaultTileOptions); + test( + "0x1d", + { type: BatchType.Primary, edges: { type: "compact", smooth: true }, sectionCut: "010_1_0_-5_30_0_-1_5e-11____" } as PrimaryTileTreeId, + { depth: 20, i: 50, j: 4, k: 1, multiplier: 1 }, + realDefaultTileOptions, + ); }); it("parses TileTreeId and ContentId strings", () => { diff --git a/core/common/src/test/Tween.test.ts b/core/common/src/test/Tween.test.ts index bff75e1f8c12..03fda3168705 100644 --- a/core/common/src/test/Tween.test.ts +++ b/core/common/src/test/Tween.test.ts @@ -16,8 +16,8 @@ import { Easing, Tween, Tweens } from "../Tween"; // cSpell:ignore tweens tweening yoyo progressess tween's -const tweenCallback = (_obj: any) => { }; -const updateCallback = (_obj: any, _t: number) => { }; +const tweenCallback = (_obj: any) => {}; +const updateCallback = (_obj: any, _t: number) => {}; const interpolationFunction = (_v: any, _k: number) => 1; describe("Tween", () => { @@ -34,7 +34,6 @@ describe("Tween", () => { }); it("removeAll()", () => { - tweens.getAll(); const t = tweens.create({}); @@ -82,7 +81,6 @@ describe("Tween", () => { }); it("update() returns true when there are active tweens", () => { - tweens.removeAll(); const t = tweens.create({}); @@ -92,7 +90,6 @@ describe("Tween", () => { }); it("update() removes tweens when they are finished", () => { - tweens.removeAll(); const t1 = tweens.create({}).to({}, 1000), @@ -118,7 +115,6 @@ describe("Tween", () => { }); it("update() does not remove tweens when they are finished with preserve flag", () => { - tweens.removeAll(); const t1 = tweens.create({}).to({}, 1000), @@ -147,7 +143,6 @@ describe("Tween", () => { }); it("Unremoved tweens which have been updated past their finish time may be reused", () => { - tweens.removeAll(); const target1 = { a: 0 }; @@ -169,7 +164,6 @@ describe("Tween", () => { }); it("constructor", () => { - const t = tweens.create({}); assert.ok(t instanceof Tween, "Pass"); @@ -214,11 +208,9 @@ describe("Tween", () => { assert.ok(t.group(tweens) instanceof Tween); assert.equal(t.group(tweens), t); - }); it("Tween existing property", () => { - const obj = { x: 1 }, t = tweens.create(obj); @@ -230,7 +222,6 @@ describe("Tween", () => { }); it("Tween non-existing property", () => { - const obj: any = { x: 1 }, t = tweens.create(obj); @@ -243,7 +234,6 @@ describe("Tween", () => { }); it("Tween non-null property", () => { - const obj = { x: 1 }, t = tweens.create(obj); @@ -256,8 +246,7 @@ describe("Tween", () => { }); it("Tween function property", () => { - - const myFunction = () => { }; + const myFunction = () => {}; const obj = { x: myFunction }, t = tweens.create(obj); @@ -270,11 +259,10 @@ describe("Tween", () => { }); it("Tween boolean property", () => { - const obj = { x: true }, t = tweens.create(obj); - t.to({ x: () => { } }); + t.to({ x: () => {} }); t.start(0); t.update(1000); @@ -283,7 +271,6 @@ describe("Tween", () => { }); it("Tween null property", () => { - const obj = { x: null }, t = tweens.create(obj); @@ -295,7 +282,6 @@ describe("Tween", () => { }); it("Tween undefined property", () => { - const obj: any = {}, t = tweens.create(obj); @@ -307,7 +293,6 @@ describe("Tween", () => { }); it("Tween relative positive value, with sign", () => { - const obj = { x: 0 }, t = tweens.create(obj); @@ -319,7 +304,6 @@ describe("Tween", () => { }); it("Tween relative negative value", () => { - const obj = { x: 0 }, t = tweens.create(obj); @@ -331,7 +315,6 @@ describe("Tween", () => { }); it("String values without a + or - sign should not be interpreted as relative", () => { - const obj = { x: 100 }, t = tweens.create(obj); @@ -343,7 +326,6 @@ describe("Tween", () => { }); it("Test Tween.start()", () => { - const obj = {}, t = tweens.create(obj); @@ -359,7 +341,6 @@ describe("Tween", () => { }); it("Test Tween.stop()", () => { - const obj = {}, t = tweens.create(obj); @@ -374,7 +355,6 @@ describe("Tween", () => { }); it("Test Tween.delay()", () => { - const obj = { x: 1 }, t = tweens.create(obj); @@ -397,7 +377,6 @@ describe("Tween", () => { // TODO: not really sure how to test this. Advice appreciated! it("Test Easing()", () => { - const obj = { x: 0 }, t = tweens.create(obj); @@ -412,7 +391,6 @@ describe("Tween", () => { // TODO test interpolation() it("Test Tween.chain --with one tween", () => { - const t2 = tweens.create({}), t = tweens.create({}); let tStarted = false, @@ -460,7 +438,6 @@ describe("Tween", () => { }); it("Test Tween.chain --with several tweens in an array", () => { - const t = tweens.create({}), chainedTweens = [], numChained = 3; @@ -500,7 +477,6 @@ describe("Tween", () => { }); it("Test Tween.chain allows endless loops", () => { - const obj = { x: 0 }, t1 = tweens.create(obj).to({ x: 100 }, 1000), t2 = tweens.create(obj).to({ x: 0 }, 1000); @@ -582,11 +558,9 @@ describe("Tween", () => { tweens.update(4500); assert.equal(obj2.x, 50); - }); it("Test Tween.onStart", () => { - const obj = {}, t = tweens.create(obj); let counter = 0; @@ -610,7 +584,6 @@ describe("Tween", () => { }); it("Test Tween.onStop", () => { - const obj = {}, t = tweens.create(obj); let counter = 0; @@ -641,7 +614,6 @@ describe("Tween", () => { }); it("Test Tween.onUpdate", () => { - const obj = {}, t = tweens.create(obj); let counter = 0; @@ -669,11 +641,9 @@ describe("Tween", () => { tweens.update(1500); assert.deepEqual(counter, 4, "onUpdate callback should not be called after the tween has finished"); - }); it("Test Tween.onComplete", () => { - const obj = {}, t = tweens.create(obj); let counter = 0; @@ -704,7 +674,6 @@ describe("Tween", () => { }); it("Tween does not repeat by default", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -726,7 +695,6 @@ describe("Tween", () => { }); it("Test single repeat happens only once", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -751,7 +719,6 @@ describe("Tween", () => { }); it("Test Infinity repeat happens forever", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -779,7 +746,6 @@ describe("Tween", () => { }); it("Test tweening relatively with repeat", () => { - tweens.removeAll(); const obj = { x: 0, y: 0 }, @@ -809,7 +775,6 @@ describe("Tween", () => { }); it("Test yoyo with repeat Infinity happens forever", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -837,7 +802,6 @@ describe("Tween", () => { }); it("Test yoyo with repeat 1 happens once", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -865,7 +829,6 @@ describe("Tween", () => { }); it("Test Tween.chain progressess into chained tweens", () => { - const obj = { t: 1000 }; // 1000 of nothing @@ -881,11 +844,9 @@ describe("Tween", () => { tweens.update(2000); assert.equal(obj.t, 2000); - }); it("Test that Tween.end sets the final values.", () => { - const object1 = { x: 0, y: -50, z: 1000 }; const target1 = { x: 50, y: 123, z: "+234" }; @@ -910,7 +871,6 @@ describe("Tween", () => { assert.equal(object2.x, 50); assert.equal(object2.y, 123); assert.equal(object2.z, 1234); - }); it("Test that Tween.end calls the onComplete callback of the tween.", () => { @@ -920,11 +880,9 @@ describe("Tween", () => { tween1.start(); tween1.end(); - }); it("Test delay adds delay before each repeat", () => { - // If repeatDelay isn't specified then delay is used since // that's the way it worked before repeatDelay was added. @@ -955,11 +913,9 @@ describe("Tween", () => { tweens.update(400); assert.equal(obj.x, 100); - }); it("Test repeatDelay adds delay before each repeat", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -987,11 +943,9 @@ describe("Tween", () => { tweens.update(400); assert.equal(obj.x, 100); - }); it("Test repeatDelay and delay can be used together", () => { - tweens.removeAll(); const obj = { x: 0 }, @@ -1019,11 +973,9 @@ describe("Tween", () => { tweens.update(500); assert.equal(obj.x, 100); - }); it("js compatible with Object.defineProperty getter / setters", () => { - const obj: any = { _x: 0 }; // eslint-disable-line @typescript-eslint/naming-convention Object.defineProperty(obj, "x", { @@ -1051,7 +1003,6 @@ describe("Tween", () => { tweens.update(115); assert.equal(obj.x, 100); - }); it("isPlaying is false before the tween starts", () => { @@ -1131,7 +1082,6 @@ describe("Tween", () => { }); it("group sets the tween's group.", () => { - const group = new Tweens(); const groupTweenA = tweens.create({}) @@ -1143,7 +1093,6 @@ describe("Tween", () => { }); it("Test Tween.pause() and Tween.resume()", () => { - const obj = { x: 0.0 }, t = tweens.create(obj); @@ -1191,11 +1140,9 @@ describe("Tween", () => { tweens.update(5000); assert.equal(obj.x, 1.0); - }); it("Arrays in the object passed to to() are not modified by start().", () => { - const start = { x: 10, y: 20 }; const end = { x: 100, y: 200, values: ["a", "b"] }; const valuesArray = end.values; diff --git a/core/common/src/test/VersionCompatible.test.ts b/core/common/src/test/VersionCompatible.test.ts index 38b77d75b528..2b0ccb3c160d 100644 --- a/core/common/src/test/VersionCompatible.test.ts +++ b/core/common/src/test/VersionCompatible.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { RpcInterface } from "../RpcInterface"; import { describe, expect, it } from "vitest"; +import { RpcInterface } from "../RpcInterface"; describe("isVersionCompatible", () => { it("pass when versions match exactly with prerelease tags", () => { diff --git a/core/common/src/test/ViewDetails.test.ts b/core/common/src/test/ViewDetails.test.ts index 12db9cd0bb21..1a42f2a1e5ca 100644 --- a/core/common/src/test/ViewDetails.test.ts +++ b/core/common/src/test/ViewDetails.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import { ClipVector, ClipVectorProps } from "@itwin/core-geometry"; +import { describe, expect, it } from "vitest"; import { ViewDetails } from "../ViewDetails"; describe("ViewDetails", () => { @@ -12,7 +12,7 @@ describe("ViewDetails", () => { private _clipChanged = false; public constructor(clip?: ClipVectorProps) { - super(clip ? { viewDetails: { clip } } : { }); + super(clip ? { viewDetails: { clip } } : {}); this.onClipVectorChanged.addListener(() => this._clipChanged = true); } @@ -34,7 +34,10 @@ describe("ViewDetails", () => { const clipProps: ClipVectorProps = [{ shape: { points: [ - [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 0, 0], + [0, 0, 0], + [1, 0, 0], + [1, 1, 0], + [0, 0, 0], ], }, }]; diff --git a/core/common/src/test/ViewFlags.test.ts b/core/common/src/test/ViewFlags.test.ts index 56ff2152024b..8390c6c4537a 100644 --- a/core/common/src/test/ViewFlags.test.ts +++ b/core/common/src/test/ViewFlags.test.ts @@ -3,9 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert, describe, expect, it } from "vitest"; -import { - RenderMode, ViewFlagOverrides, ViewFlagProps, ViewFlags, ViewFlagsProperties, -} from "../ViewFlags"; +import { RenderMode, ViewFlagOverrides, ViewFlagProps, ViewFlags, ViewFlagsProperties } from "../ViewFlags"; function invertDefaults(): ViewFlags { const invertedProperties: Partial = { renderMode: RenderMode.SolidFill }; @@ -31,7 +29,7 @@ describe("ViewFlags", () => { it("should round-trip through JSON", () => { const roundTrip = (input: ViewFlagProps | undefined, expected: ViewFlagProps | "input") => { if ("input" === expected) - expected = input ?? { }; + expected = input ?? {}; const vf = ViewFlags.fromJSON(input); const output = vf.toJSON(); @@ -42,7 +40,7 @@ describe("ViewFlags", () => { expect(fullOutput[key]).to.equal(output[key]); }; - roundTrip({ }, { renderMode: RenderMode.Wireframe }); + roundTrip({}, { renderMode: RenderMode.Wireframe }); roundTrip({ acs: true, monochrome: true, renderMode: RenderMode.Wireframe }, "input"); roundTrip({ acs: false, monochrome: false, renderMode: RenderMode.SmoothShade }, { renderMode: RenderMode.SmoothShade }); @@ -141,7 +139,11 @@ describe("ViewFlags", () => { expect(def.copy(inv)).to.deep.equal(inv); expect(inv.copy(def)).to.deep.equal(def); - expect(inv.copy({ ...inv, renderMode: undefined, transparency: undefined })).to.deep.equal({ ...inv, renderMode: RenderMode.Wireframe, transparency: true }); + expect(inv.copy({ ...inv, renderMode: undefined, transparency: undefined })).to.deep.equal({ + ...inv, + renderMode: RenderMode.Wireframe, + transparency: true, + }); }); it("overrides", () => { @@ -158,14 +160,14 @@ describe("ViewFlags", () => { it("returns defaults if no properties supplied", () => { expect(ViewFlags.fromJSON()).to.equal(ViewFlags.defaults); expect(ViewFlags.create()).to.equal(ViewFlags.defaults); - expect(ViewFlags.create({ })).to.equal(ViewFlags.defaults); + expect(ViewFlags.create({})).to.equal(ViewFlags.defaults); }); it("uses different defaults for undefined vs ViewFlagProps", () => { const def = ViewFlags.defaults; expect(ViewFlags.fromJSON(undefined)).to.deep.equal(def); - expect(ViewFlags.fromJSON({ })).to.deep.equal({ + expect(ViewFlags.fromJSON({})).to.deep.equal({ ...def, clipVolume: !def.clipVolume, lighting: !def.lighting, @@ -243,7 +245,7 @@ describe("ViewFlagOverrides", () => { const ovrsTestCases: Array<[ViewFlagOverrides, RenderMode | undefined, boolean | undefined]> = []; for (const renderMode of [undefined, RenderMode.Wireframe, RenderMode.HiddenLine, RenderMode.SolidFill, RenderMode.SmoothShade]) { for (let i = 0; i < 3; i++) { - const ovrs: ViewFlagOverrides = { }; + const ovrs: ViewFlagOverrides = {}; if (undefined !== renderMode) ovrs.renderMode = renderMode; diff --git a/core/common/src/test/annotations/TextAnnotation.test.ts b/core/common/src/test/annotations/TextAnnotation.test.ts index ab18f4b4016a..d0ff88ed2331 100644 --- a/core/common/src/test/annotations/TextAnnotation.test.ts +++ b/core/common/src/test/annotations/TextAnnotation.test.ts @@ -1,6 +1,6 @@ +import { Angle, Point3d, Range2d, Range3d, YawPitchRollAngles } from "@itwin/core-geometry"; import { describe, expect, it } from "vitest"; import { TextAnnotation, TextAnnotationAnchor } from "../../annotation/TextAnnotation"; -import { Angle, Point3d, Range2d, Range3d, YawPitchRollAngles } from "@itwin/core-geometry"; describe("TextAnnotation", () => { describe("computeAnchorPoint", () => { @@ -44,7 +44,10 @@ describe("TextAnnotation", () => { const anchor = annotation.computeAnchorPoint(extents); const transformed = transform.multiplyPoint3d(anchor); const expected = annotation.offset; - expect(transformed.isAlmostEqual(expected)).to.equal(true, `expected ${JSON.stringify(transformed.toJSON())} to equal ${JSON.stringify(expected.toJSON())}`); + expect(transformed.isAlmostEqual(expected)).to.equal( + true, + `expected ${JSON.stringify(transformed.toJSON())} to equal ${JSON.stringify(expected.toJSON())}`, + ); }; // No offset nor rotation @@ -55,7 +58,7 @@ describe("TextAnnotation", () => { expectAnchorAtOrigin(); // Offset only - annotation.orientation = new YawPitchRollAngles();; + annotation.orientation = new YawPitchRollAngles(); annotation.offset = new Point3d(4, -6, 0); expectAnchorAtOrigin(); @@ -131,7 +134,7 @@ describe("TextAnnotation", () => { rotation: 90, }); expectTransformedRange([10, -10, 20, 10], { - anchor: { horizontal: "center", vertical: "top"}, + anchor: { horizontal: "center", vertical: "top" }, rotation: 90, }); expectTransformedRange([0, -20, 10, 0], { diff --git a/core/common/src/test/annotations/TextBlock.test.ts b/core/common/src/test/annotations/TextBlock.test.ts index fcb819c134e2..015403bc1a72 100644 --- a/core/common/src/test/annotations/TextBlock.test.ts +++ b/core/common/src/test/annotations/TextBlock.test.ts @@ -3,7 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { beforeEach, describe, expect, it } from "vitest"; -import { FractionRunProps, Paragraph, ParagraphProps, RunProps, TextBlock, TextBlockProps, TextRun, TextRunProps, TextStyleSettingsProps } from "../../core-common"; +import { + FractionRunProps, + Paragraph, + ParagraphProps, + RunProps, + TextBlock, + TextBlockProps, + TextRun, + TextRunProps, + TextStyleSettingsProps, +} from "../../core-common"; function makeTextRun(content?: string, styleName = "", styleOverrides?: TextStyleSettingsProps): TextRunProps { return { @@ -39,8 +49,8 @@ describe("TextBlockComponent", () => { let run: TextRun; beforeEach(() => { - block = TextBlock.create({ styleName: "block", styleOverrides: { widthFactor: 1234 }}); - paragraph = Paragraph.create({ styleName: "paragraph", styleOverrides: { lineHeight: 42 }}); + block = TextBlock.create({ styleName: "block", styleOverrides: { widthFactor: 1234 } }); + paragraph = Paragraph.create({ styleName: "paragraph", styleOverrides: { lineHeight: 42 } }); run = TextRun.create({ styleName: "run", styleOverrides: { fontName: "Consolas" } }); paragraph.runs.push(run); block.paragraphs.push(paragraph); diff --git a/core/common/src/test/annotations/TextStyle.test.ts b/core/common/src/test/annotations/TextStyle.test.ts index 494c6df4ddc2..17b2249478cd 100644 --- a/core/common/src/test/annotations/TextStyle.test.ts +++ b/core/common/src/test/annotations/TextStyle.test.ts @@ -40,7 +40,7 @@ describe("TextStyleSettings", () => { for (const propName of Object.keys(customProps)) { const key = propName as keyof TextStyleSettingsProps; - const props: TextStyleSettingsProps = { }; + const props: TextStyleSettingsProps = {}; (props as any)[key] = customProps[key]; const settings = TextStyleSettings.fromJSON(props); diff --git a/core/common/src/tile/B3dmTileIO.ts b/core/common/src/tile/B3dmTileIO.ts index 54ad46a79f0e..08e6221c9e2f 100644 --- a/core/common/src/tile/B3dmTileIO.ts +++ b/core/common/src/tile/B3dmTileIO.ts @@ -20,7 +20,9 @@ export class B3dmHeader extends TileHeader { public readonly batchTableBinaryLength: number; public readonly featureTableJson: any; public readonly batchTableJson: any; - public get isValid(): boolean { return TileFormat.B3dm === this.format; } + public get isValid(): boolean { + return TileFormat.B3dm === this.format; + } public constructor(stream: ByteStream) { super(stream); diff --git a/core/common/src/tile/CompositeTileIO.ts b/core/common/src/tile/CompositeTileIO.ts index 42173e9589cd..7318ee245c0c 100644 --- a/core/common/src/tile/CompositeTileIO.ts +++ b/core/common/src/tile/CompositeTileIO.ts @@ -17,7 +17,9 @@ export class CompositeTileHeader extends TileHeader { public readonly tileCount: number; public readonly tilePosition: number; - public get isValid(): boolean { return TileFormat.Cmpt === this.format; } + public get isValid(): boolean { + return TileFormat.Cmpt === this.format; + } public constructor(stream: ByteStream) { super(stream); diff --git a/core/common/src/tile/I3dmTileIO.ts b/core/common/src/tile/I3dmTileIO.ts index 5a7f2d5b68ee..1d8ffd29459c 100644 --- a/core/common/src/tile/I3dmTileIO.ts +++ b/core/common/src/tile/I3dmTileIO.ts @@ -21,7 +21,9 @@ export class I3dmHeader extends TileHeader { public readonly batchTableBinaryLength: number; public readonly gltfVersion: number; public readonly batchTableJson: any; - public get isValid(): boolean { return TileFormat.I3dm === this.format; } + public get isValid(): boolean { + return TileFormat.I3dm === this.format; + } public constructor(stream: ByteStream) { super(stream); diff --git a/core/common/src/tile/IModelTileIO.ts b/core/common/src/tile/IModelTileIO.ts index f49df06beb76..95eee2d6cfc4 100644 --- a/core/common/src/tile/IModelTileIO.ts +++ b/core/common/src/tile/IModelTileIO.ts @@ -65,11 +65,19 @@ export class ImdlHeader extends TileHeader { /** A bitfield wherein each set bit indicates an empty sub-volume. */ public readonly emptySubRanges: number; - public get versionMajor(): number { return this.version >>> 0x10; } - public get versionMinor(): number { return (this.version & 0xffff) >>> 0; } + public get versionMajor(): number { + return this.version >>> 0x10; + } + public get versionMinor(): number { + return (this.version & 0xffff) >>> 0; + } - public get isValid(): boolean { return TileFormat.IModel === this.format; } - public get isReadableVersion(): boolean { return this.versionMajor <= CurrentImdlVersion.Major; } + public get isValid(): boolean { + return TileFormat.IModel === this.format; + } + public get isReadableVersion(): boolean { + return this.versionMajor <= CurrentImdlVersion.Major; + } /** Deserialize a header from the binary data at the stream's current position. * If the binary data does not contain a valid header, the Header will be marked 'invalid'. diff --git a/core/common/src/tile/PntsTileIO.ts b/core/common/src/tile/PntsTileIO.ts index 8d13e2619e55..61d72ad016d9 100644 --- a/core/common/src/tile/PntsTileIO.ts +++ b/core/common/src/tile/PntsTileIO.ts @@ -18,7 +18,9 @@ export class PntsHeader extends TileHeader { public readonly featureTableBinaryLength: number; public readonly batchTableJsonLength: number; public readonly batchTableBinaryLength: number; - public get isValid(): boolean { return TileFormat.Pnts === this.format; } + public get isValid(): boolean { + return TileFormat.Pnts === this.format; + } public constructor(stream: ByteStream) { super(stream); diff --git a/core/common/src/tile/TileIO.ts b/core/common/src/tile/TileIO.ts index fb4bb73ec180..4c6788c93c2b 100644 --- a/core/common/src/tile/TileIO.ts +++ b/core/common/src/tile/TileIO.ts @@ -16,10 +16,10 @@ export enum TileFormat { Unknown = 0, B3dm = 0x6d643362, // "b3dm" Gltf = 0x46546c67, // "glTF" - Pnts = 0x73746e70, // "pnts" + Pnts = 0x73746e70, // "pnts" IModel = 0x6c644d69, // "iMdl" - Cmpt = 0x74706d63, // cmpt - I3dm = 0x6d643369, // i3dm + Cmpt = 0x74706d63, // cmpt + I3dm = 0x6d643369, // i3dm A3x = 0x583341, // A3X0 (numeric 0 not char '0') } @@ -86,7 +86,9 @@ export class TileReadError extends BentleyError { super(status, message); } - public get wasCanceled(): boolean { return TileReadStatus.Canceled === this.errorNumber; } + public get wasCanceled(): boolean { + return TileReadStatus.Canceled === this.errorNumber; + } } /** The base header preceding tile data of most formats, identifying the tile format and version of that format. @@ -104,7 +106,9 @@ export abstract class TileHeader { this.version = stream.readUint32(); } - public get format(): TileFormat { return this._format; } + public get format(): TileFormat { + return this._format; + } /** Returns whether the header represents valid data */ public abstract get isValid(): boolean; diff --git a/core/common/src/tile/TileMetadata.ts b/core/common/src/tile/TileMetadata.ts index 4aa8b056cd29..dbceaa5c19c6 100644 --- a/core/common/src/tile/TileMetadata.ts +++ b/core/common/src/tile/TileMetadata.ts @@ -7,7 +7,15 @@ */ import { - assert, ByteStream, compareBooleans, compareBooleansOrUndefined, compareNumbers, compareStrings, compareStringsOrUndefined, Id64, Id64String, + assert, + ByteStream, + compareBooleans, + compareBooleansOrUndefined, + compareNumbers, + compareStrings, + compareStringsOrUndefined, + Id64, + Id64String, } from "@itwin/core-bentley"; import { Range3d, Vector3d } from "@itwin/core-geometry"; import { BatchType } from "../FeatureTable"; @@ -181,7 +189,12 @@ class Parser { this.reject("Invalid content Id"); } - if (Object.keys(parsedContentId).some((key) => parsedContentId.hasOwnProperty(key) && typeof parsedContentId[key as keyof ContentIdSpec] === "number" && !Number.isFinite(parsedContentId[key as keyof ContentIdSpec]))) + if ( + Object.keys(parsedContentId).some((key) => + parsedContentId.hasOwnProperty(key) && typeof parsedContentId[key as keyof ContentIdSpec] === "number" && + !Number.isFinite(parsedContentId[key as keyof ContentIdSpec]) + ) + ) throw new Error("Invalid content Id"); let treeId: IModelTileTreeId; @@ -397,10 +410,14 @@ function edgeOptionsToString(options: EdgeOptions | false) { return "E:0_"; switch (options.type) { - case "non-indexed": return options.smooth ? "E:3_" : ""; - case "indexed": return options.smooth ? "E:4_" : "E:2_"; - case "compact": return options.smooth ? "E:6_" : "E:5_"; - default: throw new Error("Invalid tree Id"); + case "non-indexed": + return options.smooth ? "E:3_" : ""; + case "indexed": + return options.smooth ? "E:4_" : "E:2_"; + case "compact": + return options.smooth ? "E:6_" : "E:5_"; + default: + throw new Error("Invalid tree Id"); } } @@ -411,7 +428,7 @@ export function getMaximumMajorTileFormatVersion(maxMajorVersion: number, format // to that optionally configured by the app. let majorVersion = maxMajorVersion; if (undefined !== formatVersion) - majorVersion = Math.min((formatVersion >>> 0x10), majorVersion); + majorVersion = Math.min(formatVersion >>> 0x10, majorVersion); // Version number less than 1 is invalid - ignore majorVersion = Math.max(majorVersion, 1); @@ -432,7 +449,7 @@ export enum TreeFlags { EnforceDisplayPriority = 1 << 1, // For 3d plan projection models, group graphics into layers based on subcategory. OptimizeBRepProcessing = 1 << 2, // Use an optimized pipeline for producing facets from BRep entities. UseLargerTiles = 1 << 3, // Produce tiles of larger size in screen pixels. - ExpandProjectExtents = 1 << 4 // If UseProjectExtents, round them up/down to nearest powers of ten. + ExpandProjectExtents = 1 << 4, // If UseProjectExtents, round them up/down to nearest powers of ten. } /** Describes a tile tree used to draw the contents of a model, possibly with embedded animation. @@ -657,7 +674,9 @@ class ContentIdV1Provider extends ContentIdProvider { super(majorVersion, ContentFlags.None); } - protected get _separator() { return "/"; } + protected get _separator() { + return "/"; + } protected computeId(depth: number, i: number, j: number, k: number, mult: number): string { return this.join(depth, i, j, k, mult); } @@ -676,7 +695,9 @@ class ContentIdV2Provider extends ContentIdProvider { this._prefix = this._separator + majorVersion.toString(16) + this._separator + flags.toString(16) + this._separator; } - protected get _separator() { return "_"; } + protected get _separator() { + return "_"; + } protected computeId(depth: number, i: number, j: number, k: number, mult: number): string { return this._prefix + this.join(depth, i, j, k, mult); } @@ -704,7 +725,9 @@ class ContentIdV4Provider extends ContentIdProvider { this._prefix = this._separator + flags.toString(16) + this._separator; } - protected get _separator() { return "-"; } + protected get _separator() { + return "-"; + } protected computeId(depth: number, i: number, j: number, k: number, mult: number): string { return this._prefix + this.join(depth, i, j, k, mult); } @@ -764,7 +787,11 @@ export function computeChildTileRanges(tile: TileMetadata, root: TileTreeMetadat /** Given a description of the parent tile, obtain the properties of its child tiles, and the number of empty children. * @internal */ -export function computeChildTileProps(parent: TileMetadata, idProvider: ContentIdProvider, root: TileTreeMetadata): { children: TileProps[], numEmpty: number } { +export function computeChildTileProps( + parent: TileMetadata, + idProvider: ContentIdProvider, + root: TileTreeMetadata, +): { children: TileProps[], numEmpty: number } { let numEmpty = 0; const children: TileProps[] = []; @@ -852,7 +879,13 @@ export interface TileContentDescription extends TileContentMetadata { * @internal * @deprecated in 4.0. Use decodeTileContentDescription. I think tile agents (or their tests) are using this function. */ -export function readTileContentDescription(stream: ByteStream, sizeMultiplier: number | undefined, is2d: boolean, options: TileOptions, isVolumeClassifier: boolean): TileContentDescription { +export function readTileContentDescription( + stream: ByteStream, + sizeMultiplier: number | undefined, + is2d: boolean, + options: TileOptions, + isVolumeClassifier: boolean, +): TileContentDescription { return decodeTileContentDescription({ stream, sizeMultiplier, is2d, options, isVolumeClassifier }); } @@ -893,7 +926,7 @@ export function decodeTileContentDescription(args: DecodeTileContentDescriptionA // Determine subdivision based on header data. const completeTile = 0 === (header.flags & ImdlFlags.Incomplete); const emptyTile = completeTile && 0 === header.numElementsIncluded && 0 === header.numElementsExcluded; - isLeaf = (emptyTile || isVolumeClassifier); // Current classifier algorithm supports only a single tile. + isLeaf = emptyTile || isVolumeClassifier; // Current classifier algorithm supports only a single tile. if (!isLeaf) { // Non-spatial (2d) models are of arbitrary scale and contain geometry like line work and especially text which // can be adversely affected by quantization issues when zooming in closely. diff --git a/core/common/src/tile/Tileset3dSchema.ts b/core/common/src/tile/Tileset3dSchema.ts index b13a1aaea577..63dff0d75ccc 100644 --- a/core/common/src/tile/Tileset3dSchema.ts +++ b/core/common/src/tile/Tileset3dSchema.ts @@ -24,18 +24,34 @@ export namespace Tileset3dSchema { } export type BoundingSphere = [ - centerX: number, centerY: number, centerZ: number, radius: number + centerX: number, + centerY: number, + centerZ: number, + radius: number, ]; export type BoundingRegion = [ - west: number, south: number, east: number, north: number, minHeight: number, maxHeight: number + west: number, + south: number, + east: number, + north: number, + minHeight: number, + maxHeight: number, ]; export type BoundingBox = [ - centerX: number, centerY: number, centerZ: number, - uX: number, uY: number, uZ: number, - vX: number, vY: number, vZ: number, - wX: number, wY: number, wZ: number, + centerX: number, + centerY: number, + centerZ: number, + uX: number, + uY: number, + uZ: number, + vX: number, + vY: number, + vZ: number, + wX: number, + wY: number, + wZ: number, ]; export type BoundingVolume = RequireAtLeastOne<{ @@ -50,10 +66,22 @@ export namespace Tileset3dSchema { export type Refinement = "ADD" | "REPLACE" | string; export type Transform = [ - number, number, number, number, - number, number, number, number, - number, number, number, number, - number, number, number, number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, + number, ]; export interface Content extends TilesetProperty { diff --git a/core/common/vitest.config.mts b/core/common/vitest.config.mts index 7ab32697945d..8bc406cb1d78 100644 --- a/core/common/vitest.config.mts +++ b/core/common/vitest.config.mts @@ -1,24 +1,24 @@ -import { coverageConfigDefaults, defineConfig } from 'vitest/config'; +import { coverageConfigDefaults, defineConfig } from "vitest/config"; export default defineConfig({ test: { dir: "src", coverage: { provider: "v8", include: [ - "src/**/*" + "src/**/*", ], exclude: [ ...coverageConfigDefaults.exclude, "src/test/**/*", "**/*.d.ts", - "**/*.d.tsx" + "**/*.d.tsx", ], reporter: [ "text-summary", "lcov", - "cobertura" + "cobertura", ], reportsDirectory: "./lib/cjs/test/coverage", - } - } -}) + }, + }, +}); diff --git a/core/ecschema-editing/eslint.config.js b/core/ecschema-editing/eslint.config.js index 647ba18fc06a..0eaf8c725c25 100644 --- a/core/ecschema-editing/eslint.config.js +++ b/core/ecschema-editing/eslint.config.js @@ -10,8 +10,8 @@ module.exports = [ files: ["**/*.ts"], rules: { "radix": "warn", - "@typescript-eslint/explicit-member-accessibility": "warn" - } + "@typescript-eslint/explicit-member-accessibility": "warn", + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/ecschema-editing/public/locales/en/ECSchemaEditing.json b/core/ecschema-editing/public/locales/en/ECSchemaEditing.json index 9108c7f00f09..5a544cdb6a03 100644 --- a/core/ecschema-editing/public/locales/en/ECSchemaEditing.json +++ b/core/ecschema-editing/public/locales/en/ECSchemaEditing.json @@ -24,4 +24,4 @@ "ECObjects-1600": "The {0}-Constraint of '{1}' does not contain any constraint classes.", "ECObjects-1601": "The {0}-Constraint of '{1}' has multiple constraint classes which requires an abstract constraint to be defined." } -} \ No newline at end of file +} diff --git a/core/ecschema-editing/scripts/createLocalization.js b/core/ecschema-editing/scripts/createLocalization.js index 5ec2ce8be155..a46cba4fa42b 100644 --- a/core/ecschema-editing/scripts/createLocalization.js +++ b/core/ecschema-editing/scripts/createLocalization.js @@ -27,11 +27,11 @@ function createLocalization() { const json = { Diagnostics: { - ...jsonEntries - } - } + ...jsonEntries, + }, + }; - fs.writeFile(path.resolve(localesDir, "ECSchemaEditing.json"), JSON.stringify(json, undefined, 2), "utf8", function (err) { + fs.writeFile(path.resolve(localesDir, "ECSchemaEditing.json"), JSON.stringify(json, undefined, 2), "utf8", function(err) { if (err) { printErrorAndFail(err); } @@ -40,4 +40,4 @@ function createLocalization() { console.log("ECSchemaEditing localization successful."); } -createLocalization(); \ No newline at end of file +createLocalization(); diff --git a/core/ecschema-editing/src/Differencing/SchemaConflicts.ts b/core/ecschema-editing/src/Differencing/SchemaConflicts.ts index f519add57e39..e4744caf70d3 100644 --- a/core/ecschema-editing/src/Differencing/SchemaConflicts.ts +++ b/core/ecschema-editing/src/Differencing/SchemaConflicts.ts @@ -39,7 +39,6 @@ import type { SchemaType } from "./SchemaDifference"; * @alpha */ export enum ConflictCode { - ConflictingItemName = "C-001", ConflictingReferenceAlias = "C-002", diff --git a/core/ecschema-editing/src/Differencing/SchemaDiagnosticVisitor.ts b/core/ecschema-editing/src/Differencing/SchemaDiagnosticVisitor.ts index 87a5384b1bb2..74b286f9e5dc 100644 --- a/core/ecschema-editing/src/Differencing/SchemaDiagnosticVisitor.ts +++ b/core/ecschema-editing/src/Differencing/SchemaDiagnosticVisitor.ts @@ -6,13 +6,23 @@ * @module Differencing */ -import type { AnyDiagnostic } from "../Validation/Diagnostic"; -import { SchemaCompareCodes } from "../Validation/SchemaCompareDiagnostics"; import { - AnyEnumerator, AnyPropertyProps, AnySchemaItem, CustomAttribute, ECClass, - Enumeration, Mixin, Property, PropertyProps, - RelationshipConstraint, RelationshipConstraintProps, Schema, SchemaItem, + AnyEnumerator, + AnyPropertyProps, + AnySchemaItem, + CustomAttribute, + ECClass, + Enumeration, + Mixin, + Property, + PropertyProps, + RelationshipConstraint, + RelationshipConstraintProps, + Schema, + SchemaItem, } from "@itwin/ecschema-metadata"; +import type { AnyDiagnostic } from "../Validation/Diagnostic"; +import { SchemaCompareCodes } from "../Validation/SchemaCompareDiagnostics"; import { type AnyClassItemDifference, type AnySchemaItemDifference, @@ -36,7 +46,6 @@ import { * @internal */ export class SchemaDiagnosticVisitor { - public readonly schemaDifferences: Array; public readonly schemaItemDifferences: Array; public readonly schemaItemPathDifferences: Array; @@ -231,7 +240,8 @@ export class SchemaDiagnosticVisitor { } let modifyEntry = this.schemaItemPathDifferences.find((entry): entry is EnumeratorDifference => { - return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.Enumerator && entry.itemName === enumeration.name && entry.path === enumerator.name; + return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.Enumerator && entry.itemName === enumeration.name && + entry.path === enumerator.name; }); if (modifyEntry === undefined) { @@ -270,7 +280,8 @@ export class SchemaDiagnosticVisitor { } let modifyEntry = this.schemaItemPathDifferences.find((entry): entry is ClassPropertyDifference => { - return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.Property && entry.itemName === property.class.name && entry.path === property.name; + return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.Property && entry.itemName === property.class.name && + entry.path === property.name; }); if (modifyEntry === undefined) { @@ -336,7 +347,8 @@ export class SchemaDiagnosticVisitor { const constraintPath = constraint.isSource ? "$source" : "$target"; let modifyEntry = this.schemaItemPathDifferences.find((entry): entry is RelationshipConstraintClassDifference => { - return entry.changeType === "add" && entry.schemaType === SchemaOtherTypes.RelationshipConstraintClass, entry.itemName === className && entry.path === constraintPath; + return entry.changeType === "add" && entry.schemaType === SchemaOtherTypes.RelationshipConstraintClass, + entry.itemName === className && entry.path === constraintPath; }); if (!modifyEntry) { @@ -363,7 +375,8 @@ export class SchemaDiagnosticVisitor { } let modifyEntry = this.schemaItemPathDifferences.find((entry): entry is RelationshipConstraintDifference => { - return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.RelationshipConstraint && entry.itemName === className && entry.path === constraintPath; + return entry.changeType === "modify" && entry.schemaType === SchemaOtherTypes.RelationshipConstraint && entry.itemName === className && + entry.path === constraintPath; }); if (modifyEntry === undefined) { diff --git a/core/ecschema-editing/src/Differencing/SchemaDifference.ts b/core/ecschema-editing/src/Differencing/SchemaDifference.ts index d2c98264df90..ac120bd5ad37 100644 --- a/core/ecschema-editing/src/Differencing/SchemaDifference.ts +++ b/core/ecschema-editing/src/Differencing/SchemaDifference.ts @@ -6,16 +6,34 @@ * @module Differencing */ -import { SchemaDifferenceConflict } from "./SchemaConflicts"; -import { SchemaDiagnosticVisitor } from "./SchemaDiagnosticVisitor"; -import { SchemaChanges } from "../Validation/SchemaChanges"; -import { SchemaComparer } from "../Validation/SchemaComparer"; import { - AnyEnumerator, AnyPropertyProps, ConstantProps, CustomAttribute, - CustomAttributeClassProps, EntityClassProps, EnumerationProps, InvertedUnitProps, KindOfQuantityProps, - MixinProps, PhenomenonProps, PropertyCategoryProps, RelationshipClassProps, RelationshipConstraintProps, - type Schema, SchemaItemFormatProps, SchemaItemProps, SchemaItemType, SchemaItemUnitProps, SchemaReferenceProps, StructClassProps, UnitSystemProps, + AnyEnumerator, + AnyPropertyProps, + ConstantProps, + CustomAttribute, + CustomAttributeClassProps, + EntityClassProps, + EnumerationProps, + InvertedUnitProps, + KindOfQuantityProps, + MixinProps, + PhenomenonProps, + PropertyCategoryProps, + RelationshipClassProps, + RelationshipConstraintProps, + type Schema, + SchemaItemFormatProps, + SchemaItemProps, + SchemaItemType, + SchemaItemUnitProps, + SchemaReferenceProps, + StructClassProps, + UnitSystemProps, } from "@itwin/ecschema-metadata"; +import { SchemaChanges } from "../Validation/SchemaChanges"; +import { SchemaComparer } from "../Validation/SchemaComparer"; +import { SchemaDifferenceConflict } from "./SchemaConflicts"; +import { SchemaDiagnosticVisitor } from "./SchemaDiagnosticVisitor"; import { validateDifferences } from "./SchemaDifferenceValidator"; /** Utility-Type to remove possible readonly flags on the given type. */ @@ -29,7 +47,7 @@ type PartialEditable = { * by removing the readonly flag if present. */ type SchemaItemProperties = { - [P in keyof PartialEditable>>]: T[P] + [P in keyof PartialEditable>>]: T[P]; }; /** @@ -81,11 +99,11 @@ export interface SchemaDifferenceResult { * @alpha */ export type AnySchemaDifference = - SchemaDifference | - SchemaReferenceDifference | - AnySchemaItemDifference | - AnySchemaItemPathDifference | - CustomAttributeDifference; + | SchemaDifference + | SchemaReferenceDifference + | AnySchemaItemDifference + | AnySchemaItemPathDifference + | CustomAttributeDifference; /** * Differencing entry for changes on a Schema. @@ -115,39 +133,39 @@ export interface SchemaReferenceDifference { * @alpha */ export type AnySchemaItemDifference = - AnyClassItemDifference | - ConstantDifference | - EnumerationDifference | - EntityClassMixinDifference | - FormatDifference | - KindOfQuantityDifference | - InvertedUnitDifference | - PhenomenonDifference | - PropertyCategoryDifference | - UnitDifference | - UnitSystemDifference; + | AnyClassItemDifference + | ConstantDifference + | EnumerationDifference + | EntityClassMixinDifference + | FormatDifference + | KindOfQuantityDifference + | InvertedUnitDifference + | PhenomenonDifference + | PropertyCategoryDifference + | UnitDifference + | UnitSystemDifference; /** * Union for supported class Schema Items. * @alpha */ export type AnyClassItemDifference = - EntityClassDifference | - MixinClassDifference | - StructClassDifference | - CustomAttributeClassDifference | - RelationshipClassDifference; + | EntityClassDifference + | MixinClassDifference + | StructClassDifference + | CustomAttributeClassDifference + | RelationshipClassDifference; /** * Union of all differences that have a path pointing inside a schema item. * @alpha */ export type AnySchemaItemPathDifference = - RelationshipConstraintDifference | - RelationshipConstraintClassDifference | - CustomAttributePropertyDifference | - EnumeratorDifference | - ClassPropertyDifference; + | RelationshipConstraintDifference + | RelationshipConstraintClassDifference + | CustomAttributePropertyDifference + | EnumeratorDifference + | ClassPropertyDifference; /** * Internal base class for all Schema Item differencing entries. @@ -287,10 +305,10 @@ export interface ClassPropertyDifference { * @alpha */ export type CustomAttributeDifference = - CustomAttributeSchemaDifference | - CustomAttributeSchemaItemDifference | - CustomAttributePropertyDifference | - CustomAttributeRelationshipConstraintDifference; + | CustomAttributeSchemaDifference + | CustomAttributeSchemaItemDifference + | CustomAttributePropertyDifference + | CustomAttributeRelationshipConstraintDifference; /** * Differencing entry for Custom Attributes on Schema. diff --git a/core/ecschema-editing/src/Differencing/SchemaDifferenceValidator.ts b/core/ecschema-editing/src/Differencing/SchemaDifferenceValidator.ts index 1ce7fac329bc..a99006ffddb0 100644 --- a/core/ecschema-editing/src/Differencing/SchemaDifferenceValidator.ts +++ b/core/ecschema-editing/src/Differencing/SchemaDifferenceValidator.ts @@ -6,9 +6,53 @@ * @module Differencing */ -import { classModifierToString, ECClass, ECClassModifier, EntityClass, Enumeration, KindOfQuantity, LazyLoadedSchemaItem, Mixin, parseClassModifier, primitiveTypeToString, Property, propertyTypeToString, Schema, SchemaItem, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; -import { AnyClassItemDifference, AnySchemaDifference, AnySchemaItemDifference, ClassPropertyDifference, ConstantDifference, CustomAttributeClassDifference, CustomAttributeDifference, EntityClassDifference, EntityClassMixinDifference, EnumerationDifference, EnumeratorDifference, FormatDifference, InvertedUnitDifference, KindOfQuantityDifference, MixinClassDifference, PhenomenonDifference, PropertyCategoryDifference, RelationshipClassDifference, RelationshipConstraintClassDifference, RelationshipConstraintDifference, SchemaDifference, SchemaOtherTypes, SchemaReferenceDifference, StructClassDifference, UnitDifference, UnitSystemDifference } from "./SchemaDifference"; +import { + classModifierToString, + ECClass, + ECClassModifier, + EntityClass, + Enumeration, + KindOfQuantity, + LazyLoadedSchemaItem, + Mixin, + parseClassModifier, + primitiveTypeToString, + Property, + propertyTypeToString, + Schema, + SchemaItem, + SchemaItemKey, + SchemaItemType, +} from "@itwin/ecschema-metadata"; import { ConflictCode, SchemaDifferenceConflict } from "./SchemaConflicts"; +import { + AnyClassItemDifference, + AnySchemaDifference, + AnySchemaItemDifference, + ClassPropertyDifference, + ConstantDifference, + CustomAttributeClassDifference, + CustomAttributeDifference, + EntityClassDifference, + EntityClassMixinDifference, + EnumerationDifference, + EnumeratorDifference, + FormatDifference, + InvertedUnitDifference, + KindOfQuantityDifference, + MixinClassDifference, + PhenomenonDifference, + PropertyCategoryDifference, + RelationshipClassDifference, + RelationshipConstraintClassDifference, + RelationshipConstraintDifference, + SchemaDifference, + SchemaOtherTypes, + SchemaReferenceDifference, + StructClassDifference, + UnitDifference, + UnitSystemDifference, +} from "./SchemaDifference"; import { SchemaDifferenceVisitor, SchemaDifferenceWalker } from "./SchemaDifferenceVisitor"; /** @@ -34,7 +78,6 @@ export async function validateDifferences(differences: AnySchemaDifference[], ta * validates the given SchemaDifferences if the violate against some EC Rules. */ class SchemaDifferenceValidationVisitor implements SchemaDifferenceVisitor { - public readonly conflicts: Array; private readonly _sourceSchema: Schema; private readonly _targetSchema: Schema; @@ -370,7 +413,7 @@ class SchemaDifferenceValidationVisitor implements SchemaDifferenceVisitor { if ("kindOfQuantity" in entry.difference) { const sourceKoQ = await sourceProperty.kindOfQuantity; const targetKoQ = await targetProperty.kindOfQuantity; - if(!targetKoQ) { + if (!targetKoQ) { return this.addConflict({ code: ConflictCode.ConflictingPropertyKindOfQuantity, schemaType: targetClass.schemaItemType, @@ -382,7 +425,7 @@ class SchemaDifferenceValidationVisitor implements SchemaDifferenceVisitor { }); } - if(!sourceKoQ) { + if (!sourceKoQ) { return this.addConflict({ code: ConflictCode.ConflictingPropertyKindOfQuantity, schemaType: targetClass.schemaItemType, @@ -475,11 +518,11 @@ class SchemaDifferenceValidationVisitor implements SchemaDifferenceVisitor { // First check for name which must be same in any case... if (ecClass.name === baseClassKey.name) { // ... then check if the class is in the same schema as the expected base class... - if(ecClass.schema.name === baseClassKey.schemaName) + if (ecClass.schema.name === baseClassKey.schemaName) return true; // ... if not, whether it's in the source schema, but then we expect the baseclass // to be in the target schema. - if(ecClass.schema.name === this._sourceSchema.name && baseClassKey.schemaName === this._targetSchema.name) + if (ecClass.schema.name === this._sourceSchema.name && baseClassKey.schemaName === this._targetSchema.name) return true; } return this.derivedFrom(await ecClass.baseClass, baseClassKey); diff --git a/core/ecschema-editing/src/Differencing/SchemaDifferenceVisitor.ts b/core/ecschema-editing/src/Differencing/SchemaDifferenceVisitor.ts index 434fee32cfcc..97433e2faa7f 100644 --- a/core/ecschema-editing/src/Differencing/SchemaDifferenceVisitor.ts +++ b/core/ecschema-editing/src/Differencing/SchemaDifferenceVisitor.ts @@ -15,7 +15,11 @@ import { type AnySchemaDifference, SchemaOtherTypes } from "./SchemaDifference"; * @internal */ export type SchemaDifferenceVisitor = { - [Difference in AnySchemaDifference as `visit${Difference["schemaType"]}Difference`]: (entry: Difference, index: number, array: AnySchemaDifference[]) => Promise; + [Difference in AnySchemaDifference as `visit${Difference["schemaType"]}Difference`]: ( + entry: Difference, + index: number, + array: AnySchemaDifference[], + ) => Promise; }; /** @@ -24,7 +28,6 @@ export type SchemaDifferenceVisitor = { * @internal */ export class SchemaDifferenceWalker { - private readonly _visitor: SchemaDifferenceVisitor; /** Initializes a new instance of SchemaDifferenceWalker class. */ diff --git a/core/ecschema-editing/src/Editing/Constants.ts b/core/ecschema-editing/src/Editing/Constants.ts index b3dcbfd688fe..4cbbcf1ba16e 100644 --- a/core/ecschema-editing/src/Editing/Constants.ts +++ b/core/ecschema-editing/src/Editing/Constants.ts @@ -8,8 +8,8 @@ import { Constant, ConstantProps, DelayedPromiseWithProps, Phenomenon, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableConstant } from "./Mutable/MutableConstant"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableConstant } from "./Mutable/MutableConstant"; import { SchemaItems } from "./SchemaItems"; /** @@ -21,11 +21,24 @@ export class Constants extends SchemaItems { super(SchemaItemType.Constant, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, phenomenon: SchemaItemKey, definition: string, displayLabel?: string, numerator?: number, denominator?: number): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + phenomenon: SchemaItemKey, + definition: string, + displayLabel?: string, + numerator?: number, + denominator?: number, + ): Promise { try { - const newConstant = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createConstant.bind(schema), name) as MutableConstant; + const newConstant = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createConstant.bind(schema), + name, + ) as MutableConstant; - const newPhenomenon = (await this.getSchemaItem(phenomenon, SchemaItemType.Phenomenon)); + const newPhenomenon = await this.getSchemaItem(phenomenon, SchemaItemType.Phenomenon); newConstant.setPhenomenon(new DelayedPromiseWithProps(newPhenomenon.key, async () => newPhenomenon)); newConstant.setDefinition(definition); @@ -52,10 +65,19 @@ export class Constants extends SchemaItems { */ public async createFromProps(schemaKey: SchemaKey, constantProps: ConstantProps): Promise { try { - const newConstant = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createConstant.bind(schema), constantProps); + const newConstant = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createConstant.bind(schema), + constantProps, + ); return newConstant.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, constantProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new SchemaItemId(this.schemaItemType, constantProps.name!, schemaKey), + e, + ); } } } diff --git a/core/ecschema-editing/src/Editing/CustomAttributes.ts b/core/ecschema-editing/src/Editing/CustomAttributes.ts index 16eb154fdae2..9feb9bcc70fe 100644 --- a/core/ecschema-editing/src/Editing/CustomAttributes.ts +++ b/core/ecschema-editing/src/Editing/CustomAttributes.ts @@ -8,13 +8,16 @@ import { CustomAttributeClass, - CustomAttributeClassProps, CustomAttributeContainerType, - SchemaItemKey, SchemaItemType, SchemaKey, + CustomAttributeClassProps, + CustomAttributeContainerType, + SchemaItemKey, + SchemaItemType, + SchemaKey, } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "./Editor"; import { ECClasses } from "./ECClasses"; -import { MutableCAClass } from "./Mutable/MutableCAClass"; +import { SchemaContextEditor } from "./Editor"; import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; +import { MutableCAClass } from "./Mutable/MutableCAClass"; /** * @alpha @@ -25,9 +28,21 @@ export class CustomAttributes extends ECClasses { super(SchemaItemType.CustomAttributeClass, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, appliesTo: CustomAttributeContainerType, displayLabel?: string, baseClassKey?: SchemaItemKey): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + appliesTo: CustomAttributeContainerType, + displayLabel?: string, + baseClassKey?: SchemaItemKey, + ): Promise { try { - const newClass = await this.createClass(schemaKey, this.schemaItemType, (schema) => schema.createCustomAttributeClass.bind(schema), name, baseClassKey) as MutableCAClass; + const newClass = await this.createClass( + schemaKey, + this.schemaItemType, + (schema) => schema.createCustomAttributeClass.bind(schema), + name, + baseClassKey, + ) as MutableCAClass; if (displayLabel) newClass.setDisplayLabel(displayLabel); @@ -46,7 +61,12 @@ export class CustomAttributes extends ECClasses { */ public async createFromProps(schemaKey: SchemaKey, caProps: CustomAttributeClassProps): Promise { try { - const newClass = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createCustomAttributeClass.bind(schema), caProps); + const newClass = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createCustomAttributeClass.bind(schema), + caProps, + ); return newClass.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new ClassId(this.schemaItemType, caProps.name!, schemaKey), e); diff --git a/core/ecschema-editing/src/Editing/ECClasses.ts b/core/ecschema-editing/src/Editing/ECClasses.ts index 2762a4715cb4..e1cbd35662ae 100644 --- a/core/ecschema-editing/src/Editing/ECClasses.ts +++ b/core/ecschema-editing/src/Editing/ECClasses.ts @@ -6,32 +6,45 @@ * @module Editing */ +import { assert } from "@itwin/core-bentley"; import { CustomAttribute, CustomAttributeContainerProps, DelayedPromiseWithProps, - ECClass, Enumeration, EnumerationPropertyProps, PrimitiveArrayPropertyProps, - PrimitivePropertyProps, PrimitiveType, SchemaItemKey, SchemaItemType, SchemaKey, StructArrayPropertyProps, - StructClass, StructPropertyProps, + ECClass, + Enumeration, + EnumerationPropertyProps, + PrimitiveArrayPropertyProps, + PrimitivePropertyProps, + PrimitiveType, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StructArrayPropertyProps, + StructClass, + StructPropertyProps, } from "@itwin/ecschema-metadata"; -import { assert } from "@itwin/core-bentley"; +import { AnyDiagnostic } from "../Validation/Diagnostic"; +import * as Rules from "../Validation/ECRules"; import { SchemaContextEditor } from "./Editor"; +import { ClassId, CustomAttributeId, ECEditingStatus, PropertyId, SchemaEditingError, SchemaItemId } from "./Exception"; import { MutableClass } from "./Mutable/MutableClass"; -import * as Rules from "../Validation/ECRules"; +import { MutableSchema } from "./Mutable/MutableSchema"; import { ArrayProperties, EnumerationProperties, PrimitiveProperties, Properties, StructProperties } from "./Properties"; -import { ClassId, CustomAttributeId, ECEditingStatus, PropertyId, SchemaEditingError, SchemaItemId } from "./Exception"; -import { AnyDiagnostic } from "../Validation/Diagnostic"; import { CreateSchemaItem, SchemaItems } from "./SchemaItems"; -import { MutableSchema } from "./Mutable/MutableSchema"; -export type ECClassSchemaItems = SchemaItemType.EntityClass | SchemaItemType.StructClass | SchemaItemType.RelationshipClass | SchemaItemType.Mixin | SchemaItemType.CustomAttributeClass; +export type ECClassSchemaItems = + | SchemaItemType.EntityClass + | SchemaItemType.StructClass + | SchemaItemType.RelationshipClass + | SchemaItemType.Mixin + | SchemaItemType.CustomAttributeClass; /** * @alpha * Acts as a base class for schema class creation. Enables property creation. */ -export class ECClasses extends SchemaItems{ - +export class ECClasses extends SchemaItems { protected constructor(schemaItemType: ECClassSchemaItems, schemaEditor: SchemaContextEditor) { super(schemaItemType, schemaEditor); this.schemaItemType = schemaItemType; @@ -60,11 +73,20 @@ export class ECClasses extends SchemaItems{ */ public readonly structProperties = new StructProperties(this.schemaItemType, this.schemaEditor); - public async createClass(schemaKey: SchemaKey, type: SchemaItemType, create: CreateSchemaItem, name: string, baseClassKey?: SchemaItemKey, ...args: any[]): Promise { + public async createClass( + schemaKey: SchemaKey, + type: SchemaItemType, + create: CreateSchemaItem, + name: string, + baseClassKey?: SchemaItemKey, + ...args: any[] + ): Promise { const newClass = await this.createSchemaItem(schemaKey, type, create, name, ...args); if (baseClassKey !== undefined) { - const baseClassSchema = !baseClassKey.schemaKey.matches(newClass.schema.schemaKey) ? await this.getSchema(baseClassKey.schemaKey) : newClass.schema as MutableSchema; + const baseClassSchema = !baseClassKey.schemaKey.matches(newClass.schema.schemaKey) + ? await this.getSchema(baseClassKey.schemaKey) + : newClass.schema as MutableSchema; const baseClassItem = await this.lookupSchemaItem(baseClassSchema, baseClassKey); newClass.baseClass = new DelayedPromiseWithProps(baseClassKey, async () => baseClassItem as T); } @@ -80,9 +102,11 @@ export class ECClasses extends SchemaItems{ * @param type The PrimitiveType assigned to the new property. */ public async createProperty(classKey: SchemaItemKey, name: string, type: PrimitiveType, prefix: string): Promise { - if (type !== PrimitiveType.Double && type !== PrimitiveType.String && type !== PrimitiveType.DateTime - && type !== PrimitiveType.Integer) - throw new Error ("Property creation is restricted to type Double, String, DateTime, and Integer."); + if ( + type !== PrimitiveType.Double && type !== PrimitiveType.String && type !== PrimitiveType.DateTime + && type !== PrimitiveType.Integer + ) + throw new Error("Property creation is restricted to type Double, String, DateTime, and Integer."); if ("" === prefix) throw new Error("The specified property name prefix is invalid"); @@ -104,17 +128,22 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.createPrimitiveProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreatePrimitiveProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createPrimitivePropertyFromProps(classKey: SchemaItemKey, name: string, type: PrimitiveType, primitiveProps: PrimitivePropertyProps): Promise { + public async createPrimitivePropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: PrimitiveType, + primitiveProps: PrimitivePropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createPrimitiveProperty(name, type); + const newProperty = await mutableClass.createPrimitiveProperty(name, type); await newProperty.fromJSON(primitiveProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreatePrimitivePropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -124,20 +153,28 @@ export class ECClasses extends SchemaItems{ const mutableClass = await this.getClass(classKey); const enumSchemaItemKey = mutableClass.schema.getSchemaItemKey(type.fullName); if (enumSchemaItemKey === undefined) - throw new SchemaEditingError(ECEditingStatus.SchemaItemNotFound, new SchemaItemId(SchemaItemType.Enumeration, type.name, mutableClass.schema.schemaKey)); + throw new SchemaEditingError( + ECEditingStatus.SchemaItemNotFound, + new SchemaItemId(SchemaItemType.Enumeration, type.name, mutableClass.schema.schemaKey), + ); await mutableClass.createPrimitiveProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateEnumerationProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createEnumerationPropertyFromProps(classKey: SchemaItemKey, name: string, type: Enumeration, enumProps: EnumerationPropertyProps): Promise { + public async createEnumerationPropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: Enumeration, + enumProps: EnumerationPropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createPrimitiveProperty(name, type); + const newProperty = await mutableClass.createPrimitiveProperty(name, type); await newProperty.fromJSON(enumProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateEnumerationArrayPropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -146,17 +183,22 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.createPrimitiveArrayProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreatePrimitiveArrayProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createPrimitiveArrayPropertyFromProps(classKey: SchemaItemKey, name: string, type: PrimitiveType, primitiveProps: PrimitiveArrayPropertyProps): Promise { + public async createPrimitiveArrayPropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: PrimitiveType, + primitiveProps: PrimitiveArrayPropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createPrimitiveArrayProperty(name, type); + const newProperty = await mutableClass.createPrimitiveArrayProperty(name, type); await newProperty.fromJSON(primitiveProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreatePrimitiveArrayPropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -165,17 +207,22 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.createPrimitiveArrayProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateEnumerationArrayProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createEnumerationArrayPropertyFromProps(classKey: SchemaItemKey, name: string, type: Enumeration, props: PrimitiveArrayPropertyProps): Promise { + public async createEnumerationArrayPropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: Enumeration, + props: PrimitiveArrayPropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createPrimitiveArrayProperty(name, type); + const newProperty = await mutableClass.createPrimitiveArrayProperty(name, type); await newProperty.fromJSON(props); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateEnumerationArrayPropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -184,17 +231,22 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.createStructProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateStructProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createStructPropertyFromProps(classKey: SchemaItemKey, name: string, type: StructClass, structProps: StructPropertyProps): Promise { + public async createStructPropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: StructClass, + structProps: StructPropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createStructProperty(name, type); + const newProperty = await mutableClass.createStructProperty(name, type); await newProperty.fromJSON(structProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateStructPropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -203,17 +255,22 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.createStructArrayProperty(name, type); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateStructArrayProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } - public async createStructArrayPropertyFromProps(classKey: SchemaItemKey, name: string, type: StructClass, structProps: StructArrayPropertyProps): Promise { + public async createStructArrayPropertyFromProps( + classKey: SchemaItemKey, + name: string, + type: StructClass, + structProps: StructArrayPropertyProps, + ): Promise { try { const mutableClass = await this.getClass(classKey); - const newProperty = await mutableClass.createStructArrayProperty(name, type); + const newProperty = await mutableClass.createStructArrayProperty(name, type); await newProperty.fromJSON(structProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateStructArrayPropertyFromProps, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -222,7 +279,7 @@ export class ECClasses extends SchemaItems{ try { const mutableClass = await this.getClass(classKey); await mutableClass.deleteProperty(name); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.DeleteProperty, new PropertyId(this.schemaItemType, classKey, name), e); } } @@ -235,7 +292,7 @@ export class ECClasses extends SchemaItems{ return; await schema.deleteClass(ecClass.name); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.DeleteClass, new ClassId(this.schemaItemType, classKey), e); } } @@ -259,9 +316,14 @@ export class ECClasses extends SchemaItems{ if (diagnostics.length > 0) { this.removeCustomAttribute(mutableClass, customAttribute); - throw new SchemaEditingError(ECEditingStatus.RuleViolation, new CustomAttributeId(customAttribute.className, mutableClass), undefined, diagnostics); + throw new SchemaEditingError( + ECEditingStatus.RuleViolation, + new CustomAttributeId(customAttribute.className, mutableClass), + undefined, + diagnostics, + ); } - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddCustomAttributeToClass, new ClassId(this.schemaItemType, classKey), e); } } @@ -279,13 +341,21 @@ export class ECClasses extends SchemaItems{ return; } - const baseClassSchema = !baseClassKey.schemaKey.matches(itemKey.schemaKey) ? await this.getSchema(baseClassKey.schemaKey) : classItem.schema as MutableSchema; + const baseClassSchema = !baseClassKey.schemaKey.matches(itemKey.schemaKey) + ? await this.getSchema(baseClassKey.schemaKey) + : classItem.schema as MutableSchema; const baseClassItem = await this.lookupSchemaItem(baseClassSchema, baseClassKey); if (classItem.baseClass !== undefined && !await baseClassItem.is(await classItem.baseClass)) - throw new SchemaEditingError(ECEditingStatus.InvalidBaseClass, new ClassId(this.schemaItemType, baseClassKey), undefined, undefined, `Base class ${baseClassKey.fullName} must derive from ${(await classItem.baseClass).fullName}.`); + throw new SchemaEditingError( + ECEditingStatus.InvalidBaseClass, + new ClassId(this.schemaItemType, baseClassKey), + undefined, + undefined, + `Base class ${baseClassKey.fullName} must derive from ${(await classItem.baseClass).fullName}.`, + ); classItem.baseClass = new DelayedPromiseWithProps(baseClassKey, async () => baseClassItem); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetBaseClass, new ClassId(this.schemaItemType, itemKey), e); } } @@ -317,7 +387,7 @@ export class ECClasses extends SchemaItems{ map.delete(customAttribute.className); } - private async findDerivedClasses(mutableClass: MutableClass): Promise>{ + private async findDerivedClasses(mutableClass: MutableClass): Promise> { const derivedClasses: Array = []; const schemaItems = this.schemaEditor.schemaContext.getSchemaItems(); let { value, done } = schemaItems.next(); diff --git a/core/ecschema-editing/src/Editing/Editor.ts b/core/ecschema-editing/src/Editing/Editor.ts index 8a6319ef25f3..240758712edf 100644 --- a/core/ecschema-editing/src/Editing/Editor.ts +++ b/core/ecschema-editing/src/Editing/Editor.ts @@ -6,26 +6,37 @@ * @module Editing */ -import * as Rules from "../Validation/ECRules"; -import { CustomAttribute, ECObjectsError, ECObjectsStatus, Schema, SchemaContext, SchemaItem, SchemaItemKey, SchemaItemType, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; -import { MutableSchema } from "./Mutable/MutableSchema"; import { assert } from "@itwin/core-bentley"; +import { + CustomAttribute, + ECObjectsError, + ECObjectsStatus, + Schema, + SchemaContext, + SchemaItem, + SchemaItemKey, + SchemaItemType, + SchemaKey, + SchemaMatchType, +} from "@itwin/ecschema-metadata"; +import { AnyDiagnostic } from "../Validation/Diagnostic"; +import * as Rules from "../Validation/ECRules"; import { Constants } from "./Constants"; import { CustomAttributes } from "./CustomAttributes"; import { Entities } from "./Entities"; import { Enumerations } from "./Enumerations"; +import { CustomAttributeId, ECEditingStatus, SchemaEditingError, SchemaId, SchemaItemId } from "./Exception"; import { Formats } from "./Formats"; import { InvertedUnits } from "./InvertedUnits"; import { KindOfQuantities } from "./KindOfQuantities"; import { Mixins } from "./Mixins"; +import { MutableSchema } from "./Mutable/MutableSchema"; import { Phenomena } from "./Phenomena"; import { PropertyCategories } from "./PropertyCategories"; import { RelationshipClasses } from "./RelationshipClasses"; import { Structs } from "./Structs"; import { Units } from "./Units"; import { UnitSystems } from "./UnitSystems"; -import { CustomAttributeId, ECEditingStatus, SchemaEditingError, SchemaId, SchemaItemId } from "./Exception"; -import { AnyDiagnostic } from "../Validation/Diagnostic"; /** * A class that allows you to edit and create schemas, classes, and items from the SchemaContext level. @@ -58,7 +69,9 @@ export class SchemaContextEditor { } /** Allows you to get schema classes and items through regular SchemaContext methods. */ - public get schemaContext(): SchemaContext { return this._schemaContext; } + public get schemaContext(): SchemaContext { + return this._schemaContext; + } public async finish(): Promise { return this._schemaContext; @@ -68,7 +81,7 @@ export class SchemaContextEditor { * Helper method for retrieving a schema, previously added, from the SchemaContext. * @param schemaKey The SchemaKey identifying the schema. * @internal - */ + */ public async getSchema(schemaKey: SchemaKey): Promise { const schema = await this.schemaContext.getCachedSchema(schemaKey, SchemaMatchType.Latest); if (schema === undefined) @@ -180,7 +193,11 @@ export class SchemaContextEditor { } /** @internal */ - public async lookupSchemaItem(schemaOrKey: Schema | SchemaKey, schemaItemKey: SchemaItemKey, schemaItemType: SchemaItemType): Promise { + public async lookupSchemaItem( + schemaOrKey: Schema | SchemaKey, + schemaItemKey: SchemaItemKey, + schemaItemType: SchemaItemType, + ): Promise { const schema = Schema.isSchema(schemaOrKey) ? schemaOrKey : await this.getSchema(schemaOrKey); @@ -272,17 +289,25 @@ export class SchemaContextEditor { continue; if (currentSchema.alias.toLowerCase() === alias.toLowerCase()) - throw new SchemaEditingError(ECEditingStatus.SchemaAliasAlreadyExists, new SchemaId(schemaKey), undefined, undefined, `Schema ${currentSchema.name} already uses the alias '${alias}'.`); + throw new SchemaEditingError( + ECEditingStatus.SchemaAliasAlreadyExists, + new SchemaId(schemaKey), + undefined, + undefined, + `Schema ${currentSchema.name} already uses the alias '${alias}'.`, + ); } schema.setAlias(alias); - } catch(e: any) { + } catch (e: any) { if (e instanceof ECObjectsError && e.errorNumber === ECObjectsStatus.InvalidECName) { - throw new SchemaEditingError(ECEditingStatus.SetSchemaAlias, new SchemaId(schemaKey), - new SchemaEditingError(ECEditingStatus.InvalidSchemaAlias, new SchemaId(schemaKey))); + throw new SchemaEditingError( + ECEditingStatus.SetSchemaAlias, + new SchemaId(schemaKey), + new SchemaEditingError(ECEditingStatus.InvalidSchemaAlias, new SchemaId(schemaKey)), + ); } - throw new SchemaEditingError(ECEditingStatus.SetSchemaAlias, new SchemaId(schemaKey), e); + throw new SchemaEditingError(ECEditingStatus.SetSchemaAlias, new SchemaId(schemaKey), e); } } } - diff --git a/core/ecschema-editing/src/Editing/Entities.ts b/core/ecschema-editing/src/Editing/Entities.ts index f0792b466f9c..f80fdbd09d88 100644 --- a/core/ecschema-editing/src/Editing/Entities.ts +++ b/core/ecschema-editing/src/Editing/Entities.ts @@ -7,14 +7,22 @@ */ import { - ECClassModifier, EntityClass, EntityClassProps, - Mixin, NavigationPropertyProps, RelationshipClass, SchemaItemKey, SchemaItemType, SchemaKey, StrengthDirection, + ECClassModifier, + EntityClass, + EntityClassProps, + Mixin, + NavigationPropertyProps, + RelationshipClass, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StrengthDirection, } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "./Editor"; import { ECClasses } from "./ECClasses"; +import { SchemaContextEditor } from "./Editor"; +import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; import { MutableEntityClass } from "./Mutable/MutableEntityClass"; import { NavigationProperties } from "./Properties"; -import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; /** * @alpha @@ -30,48 +38,83 @@ export class Entities extends ECClasses { */ public readonly navigationProperties = new NavigationProperties(SchemaItemType.EntityClass, this.schemaEditor); - public async createElement(schemaKey: SchemaKey, name: string, modifier: ECClassModifier, baseClassKey: SchemaItemKey, displayLabel?: string, mixins?: Mixin[]): Promise { + public async createElement( + schemaKey: SchemaKey, + name: string, + modifier: ECClassModifier, + baseClassKey: SchemaItemKey, + displayLabel?: string, + mixins?: Mixin[], + ): Promise { try { const baseClass = await this.getSchemaItem(baseClassKey); if (!(await (baseClass as EntityClass).is("Element", "BisCore"))) { throw new SchemaEditingError(ECEditingStatus.BaseClassIsNotElement, new ClassId(this.schemaItemType, baseClassKey)); } - } catch(e: any){ + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateElement, new ClassId(this.schemaItemType, name, schemaKey), e); } return this.create(schemaKey, name, modifier, displayLabel, baseClassKey, mixins); } - public async createElementUniqueAspect(schemaKey: SchemaKey, name: string, modifier: ECClassModifier, baseClassKey: SchemaItemKey, displayLabel?: string, mixins?: Mixin[]): Promise { + public async createElementUniqueAspect( + schemaKey: SchemaKey, + name: string, + modifier: ECClassModifier, + baseClassKey: SchemaItemKey, + displayLabel?: string, + mixins?: Mixin[], + ): Promise { try { const baseClass = await this.getSchemaItem(baseClassKey); if (!(await (baseClass as EntityClass).is("ElementUniqueAspect", "BisCore"))) { throw new SchemaEditingError(ECEditingStatus.BaseClassIsNotElementUniqueAspect, new ClassId(this.schemaItemType, baseClassKey)); } - } catch(e: any){ + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateElement, new ClassId(this.schemaItemType, name, schemaKey), e); } return this.create(schemaKey, name, modifier, displayLabel, baseClassKey, mixins); } - public async createElementMultiAspect(schemaKey: SchemaKey, name: string, modifier: ECClassModifier, baseClassKey: SchemaItemKey, displayLabel?: string, mixins?: Mixin[]): Promise { + public async createElementMultiAspect( + schemaKey: SchemaKey, + name: string, + modifier: ECClassModifier, + baseClassKey: SchemaItemKey, + displayLabel?: string, + mixins?: Mixin[], + ): Promise { try { const baseClass = await this.getSchemaItem(baseClassKey); if (!(await (baseClass as EntityClass).is("ElementMultiAspect", "BisCore"))) { throw new SchemaEditingError(ECEditingStatus.BaseClassIsNotElementMultiAspect, new ClassId(this.schemaItemType, baseClassKey)); } - } catch(e: any){ + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateElement, new ClassId(this.schemaItemType, name, schemaKey), e); } return this.create(schemaKey, name, modifier, displayLabel, baseClassKey, mixins); } - public async create(schemaKey: SchemaKey, name: string, modifier: ECClassModifier, displayLabel?: string, baseClassKey?: SchemaItemKey, mixins?: Mixin[]): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + modifier: ECClassModifier, + displayLabel?: string, + baseClassKey?: SchemaItemKey, + mixins?: Mixin[], + ): Promise { try { - const newClass = await this.createClass(schemaKey, this.schemaItemType, (schema) => schema.createEntityClass.bind(schema), name, baseClassKey, modifier) as MutableEntityClass; + const newClass = await this.createClass( + schemaKey, + this.schemaItemType, + (schema) => schema.createEntityClass.bind(schema), + name, + baseClassKey, + modifier, + ) as MutableEntityClass; if (mixins !== undefined) mixins.forEach((m) => newClass.addMixin(m)); @@ -92,7 +135,12 @@ export class Entities extends ECClasses { */ public async createFromProps(schemaKey: SchemaKey, entityProps: EntityClassProps): Promise { try { - const newClass = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createEntityClass.bind(schema), entityProps); + const newClass = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createEntityClass.bind(schema), + entityProps, + ); return newClass.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new ClassId(this.schemaItemType, entityProps.name!, schemaKey), e); @@ -104,16 +152,21 @@ export class Entities extends ECClasses { const entity = await this.getSchemaItem(entityKey); const mixin = await this.getSchemaItem(mixinKey, SchemaItemType.Mixin); entity.addMixin(mixin); - } catch(e: any){ + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddMixin, new ClassId(SchemaItemType.EntityClass, entityKey), e); } } - public async createNavigationProperty(entityKey: SchemaItemKey, name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise { + public async createNavigationProperty( + entityKey: SchemaItemKey, + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise { try { const entity = await this.getSchemaItem(entityKey); await entity.createNavigationProperty(name, relationship, direction); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateNavigationProperty, new ClassId(SchemaItemType.RelationshipClass, entityKey), e); } } @@ -128,7 +181,7 @@ export class Entities extends ECClasses { const entity = await this.getSchemaItem(classKey); const property = await entity.createNavigationProperty(navigationProps.name, navigationProps.relationshipName, navigationProps.direction); await property.fromJSON(navigationProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateNavigationPropertyFromProps, new ClassId(SchemaItemType.EntityClass, classKey), e); } } diff --git a/core/ecschema-editing/src/Editing/Enumerations.ts b/core/ecschema-editing/src/Editing/Enumerations.ts index ef8fa59184f4..0bc101f45d75 100644 --- a/core/ecschema-editing/src/Editing/Enumerations.ts +++ b/core/ecschema-editing/src/Editing/Enumerations.ts @@ -8,12 +8,12 @@ import { AnyEnumerator, Enumeration, EnumerationProps, PrimitiveType, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableEnumeration } from "./Mutable/MutableEnumeration"; import { ECEditingStatus, EnumeratorId, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableEnumeration } from "./Mutable/MutableEnumeration"; import { SchemaItems } from "./SchemaItems"; type MutableEnumerator = { - -readonly [P in keyof AnyEnumerator]: AnyEnumerator[P] + -readonly [P in keyof AnyEnumerator]: AnyEnumerator[P]; }; /** @@ -25,16 +25,30 @@ export class Enumerations extends SchemaItems { super(SchemaItemType.Enumeration, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, type: PrimitiveType.Integer | PrimitiveType.String, displayLabel?: string, isStrict?: boolean, enumerators?: AnyEnumerator[]): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + type: PrimitiveType.Integer | PrimitiveType.String, + displayLabel?: string, + isStrict?: boolean, + enumerators?: AnyEnumerator[], + ): Promise { try { - const newEnum = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createEnumeration.bind(schema), name, type) as MutableEnumeration; + const newEnum = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createEnumeration.bind(schema), + name, + type, + ) as MutableEnumeration; if (undefined !== isStrict) newEnum.setIsStrict(isStrict); - if (undefined !== enumerators) + if (undefined !== enumerators) { for (const enumerator of enumerators) await this.addEnumerator(newEnum.key, enumerator); + } if (displayLabel) newEnum.setDisplayLabel(displayLabel); @@ -52,7 +66,12 @@ export class Enumerations extends SchemaItems { */ public async createFromProps(schemaKey: SchemaKey, enumProps: EnumerationProps): Promise { try { - const newEnum = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createEnumeration.bind(schema), enumProps); + const newEnum = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createEnumeration.bind(schema), + enumProps, + ); return newEnum.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, enumProps.name!, schemaKey), e); @@ -70,7 +89,7 @@ export class Enumerations extends SchemaItems { throw new SchemaEditingError(ECEditingStatus.InvalidEnumeratorType, new EnumeratorId(enumerator, enumeration)); (enumeration as MutableEnumeration).addEnumerator(enumerator); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddEnumerator, new SchemaItemId(this.schemaItemType, enumerationKey), e); } } @@ -84,7 +103,7 @@ export class Enumerations extends SchemaItems { throw new SchemaEditingError(ECEditingStatus.EnumeratorDoesNotExist, new EnumeratorId(enumeratorName, enumeration)); (enumerator as MutableEnumerator).label = label; - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetEnumeratorLabel, new SchemaItemId(this.schemaItemType, enumerationKey), e); } } @@ -98,7 +117,7 @@ export class Enumerations extends SchemaItems { throw new SchemaEditingError(ECEditingStatus.EnumeratorDoesNotExist, new EnumeratorId(enumeratorName, enumeration)); (enumerator as MutableEnumerator).description = description; - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetEnumeratorLabel, new SchemaItemId(this.schemaItemType, enumerationKey), e); } } diff --git a/core/ecschema-editing/src/Editing/Exception.ts b/core/ecschema-editing/src/Editing/Exception.ts index b8d3988d6f92..9086958de315 100644 --- a/core/ecschema-editing/src/Editing/Exception.ts +++ b/core/ecschema-editing/src/Editing/Exception.ts @@ -6,8 +6,19 @@ * @module Editing */ +import { + AnyEnumerator, + CustomAttributeContainerProps, + Enumeration, + PrimitiveType, + primitiveTypeToString, + Property, + RelationshipConstraint, + SchemaItemKey, + SchemaItemType, + SchemaKey, +} from "@itwin/ecschema-metadata"; import { AnyDiagnostic } from "../Validation/Diagnostic"; -import { AnyEnumerator, CustomAttributeContainerProps, Enumeration, PrimitiveType, primitiveTypeToString, Property, RelationshipConstraint, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; /** @alpha */ export enum ECEditingStatus { @@ -92,7 +103,7 @@ export enum ECEditingStatus { AddSchemaReference, SetSchemaVersion, IncrementSchemaMinorVersion, - SetSchemaAlias + SetSchemaAlias, } /** @@ -110,7 +121,7 @@ export enum PropertyTypeName { PrimitiveProperty = "PrimitiveProperty", EnumerationProperty = "EnumerationProperty", NavigationProperty = "NavigationProperty", - StructProperty = "StructProperty" + StructProperty = "StructProperty", } /** @@ -124,14 +135,19 @@ export enum SchemaTypeIdentifiers { PropertyIdentifier = "Property", EnumeratorIdentifier = "Enumerator", CustomAttributeIdentifier = "CustomAttribute", - RelationshipConstraintIdentifier = "RelationshipConstraint" + RelationshipConstraintIdentifier = "RelationshipConstraint", } /** * Type that constrains SchemaItemType enum to those used by EC Class types. * @alpha */ -export type ECClassSchemaItems = SchemaItemType.EntityClass | SchemaItemType.StructClass | SchemaItemType.RelationshipClass | SchemaItemType.Mixin | SchemaItemType.CustomAttributeClass; +export type ECClassSchemaItems = + | SchemaItemType.EntityClass + | SchemaItemType.StructClass + | SchemaItemType.RelationshipClass + | SchemaItemType.Mixin + | SchemaItemType.CustomAttributeClass; /** * Type that defines the possible SchemaTypeIdentifiers for SchemaItemId classes. @@ -143,7 +159,14 @@ export type AnySchemaItemTypeIdentifier = SchemaTypeIdentifiers.SchemaItemIdenti * Type that encompasses all ISchemaTypeIdentifier interfaces * @alpha */ -export type AnyIdentifier = ISchemaIdentifier | ISchemaItemIdentifier | IClassIdentifier | IPropertyIdentifier | ICustomAttributeIdentifier | IRelationshipConstraintIdentifier | IEnumeratorIdentifier; +export type AnyIdentifier = + | ISchemaIdentifier + | ISchemaItemIdentifier + | IClassIdentifier + | IPropertyIdentifier + | ICustomAttributeIdentifier + | IRelationshipConstraintIdentifier + | IEnumeratorIdentifier; /** * A base interface that defines what is needed to identity any schema type. @@ -249,7 +272,7 @@ export class SchemaItemId implements ISchemaItemIdentifier { public readonly schemaItemKey: SchemaItemKey; constructor(schemaItemType: SchemaItemType, schemaItemKeyOrName: SchemaItemKey | string, schemaKey?: SchemaKey) { - if (typeof(schemaItemKeyOrName) === "string") { + if (typeof schemaItemKeyOrName === "string") { if (!schemaKey) throw new Error("schemaKey if required if the specified schemaItem the name of the schema item."); @@ -304,7 +327,7 @@ export class PropertyId implements IPropertyIdentifier { * An IEnumeratorIdentifier implementation to identify Enumerator instances. * @alpha */ -export class EnumeratorId implements IEnumeratorIdentifier{ +export class EnumeratorId implements IEnumeratorIdentifier { public readonly typeIdentifier = SchemaTypeIdentifiers.EnumeratorIdentifier; public readonly enumeration: SchemaItemKey; public readonly enumerationType: string; @@ -314,9 +337,9 @@ export class EnumeratorId implements IEnumeratorIdentifier{ constructor(enumerator: AnyEnumerator | string, enumeration: Enumeration) { this.enumeration = enumeration.key; - this.enumerationType = enumeration.type ? primitiveTypeToString(enumeration.type): "string"; + this.enumerationType = enumeration.type ? primitiveTypeToString(enumeration.type) : "string"; this.enumeratorType = getEnumeratorType(enumeration ?? PrimitiveType.String, enumerator); - this.name = typeof(enumerator) === "string" ? enumerator : enumerator.name; + this.name = typeof enumerator === "string" ? enumerator : enumerator.name; this.schemaKey = enumeration.schema.schemaKey; } } @@ -373,11 +396,16 @@ export class SchemaEditingError extends Error { * @param ruleViolations Will contain EC rule violations of type [[AnyDiagnostic]] for exceptions with the error code ECEditingStatus.RuleViolation. * @param message Optional error message. Most messages on automatically generated by this class based on the ECEditingStatus code. */ - public constructor(public readonly errorNumber: ECEditingStatus, public readonly identifier: AnyIdentifier, public readonly innerError?: AnyEditingError, ruleViolations?: AnyDiagnostic[], message?: string) { + public constructor( + public readonly errorNumber: ECEditingStatus, + public readonly identifier: AnyIdentifier, + public readonly innerError?: AnyEditingError, + ruleViolations?: AnyDiagnostic[], + message?: string, + ) { super(message); this._ruleViolations = ruleViolations; - this._schemaKey = identifier.schemaKey, - this.generateMessage(); + this._schemaKey = identifier.schemaKey, this.generateMessage(); } /** @@ -477,7 +505,7 @@ export class SchemaEditingError extends Error { if (this.message) return; - switch(this.errorNumber) { + switch (this.errorNumber) { case ECEditingStatus.SchemaNotFound: this.message = `Schema Key ${this._schemaKey.toString(true)} could not be found in the context.`; return; @@ -491,7 +519,8 @@ export class SchemaEditingError extends Error { this.message = `Expected ${this._schemaItemId.name} to be of type ${this._schemaItemId.schemaItemType}.`; return; case ECEditingStatus.SchemaItemNameNotSpecified: - this.message = `Could not create a new ${this._schemaItemId.schemaItemType} in schema ${this._schemaKey.name}. No name was supplied within props.`; + this.message = + `Could not create a new ${this._schemaItemId.schemaItemType} in schema ${this._schemaKey.name}. No name was supplied within props.`; return; case ECEditingStatus.SchemaItemNameAlreadyExists: this.message = `${this._schemaItemId.schemaItemType} ${this._schemaItemId.name} already exists in the schema ${this._schemaKey.name}.`; @@ -521,7 +550,8 @@ export class SchemaEditingError extends Error { this.message = `The specified Format unit ${this._schemaItemId.name} is not of type Unit or InvertedUnit`; return; case ECEditingStatus.InvalidEnumeratorType: - this.message = `The Enumeration ${this._enumeratorId.enumeration.fullName} has type ${this._enumeratorId.enumerationType}, while Enumerator ${this._enumeratorId.name} has type ${this._enumeratorId.enumeratorType}.`; + this.message = + `The Enumeration ${this._enumeratorId.enumeration.fullName} has type ${this._enumeratorId.enumerationType}, while Enumerator ${this._enumeratorId.name} has type ${this._enumeratorId.enumeratorType}.`; return; case ECEditingStatus.EnumeratorDoesNotExist: this.message = `Enumerator ${this._enumeratorId.name} does not exists in Enumeration ${this._enumeratorId.enumeration.name}.`; @@ -562,7 +592,7 @@ export class SchemaEditingError extends Error { case SchemaTypeIdentifiers.RelationshipConstraintIdentifier: return `Rule violations occurred from ${this._relationshipConstraintId.name} constraint of RelationshipClass ${this._relationshipConstraintId.relationshipKey.fullName}: ${violations}`; default: - throw new Error ("Invalid identifier."); + throw new Error("Invalid identifier."); } } @@ -576,17 +606,23 @@ export class SchemaEditingError extends Error { case SchemaTypeIdentifiers.SchemaItemIdentifier: case SchemaTypeIdentifiers.ClassIdentifier: case SchemaTypeIdentifiers.RelationshipConstraintIdentifier: - return `While performing task '${ECEditingStatus[this.errorNumber]}' an error occurred editing ${this.identifier.typeIdentifier} ${this.identifier.name}.`; + return `While performing task '${ + ECEditingStatus[this.errorNumber] + }' an error occurred editing ${this.identifier.typeIdentifier} ${this.identifier.name}.`; case SchemaTypeIdentifiers.PropertyIdentifier: - return `While performing task '${ECEditingStatus[this.errorNumber]}' an error occurred editing ${this.identifier.typeIdentifier} ${this.identifier.fullName}.`; + return `While performing task '${ + ECEditingStatus[this.errorNumber] + }' an error occurred editing ${this.identifier.typeIdentifier} ${this.identifier.fullName}.`; default: - throw new Error ("Invalid identifier."); + throw new Error("Invalid identifier."); } } private isSchemaItemIdentifier(identifier: AnyIdentifier) { - if (identifier.typeIdentifier !== SchemaTypeIdentifiers.SchemaItemIdentifier && - identifier.typeIdentifier !== SchemaTypeIdentifiers.ClassIdentifier) + if ( + identifier.typeIdentifier !== SchemaTypeIdentifiers.SchemaItemIdentifier && + identifier.typeIdentifier !== SchemaTypeIdentifiers.ClassIdentifier + ) return true; return false; @@ -594,9 +630,9 @@ export class SchemaEditingError extends Error { } function getEnumeratorType(enumeration: Enumeration, enumerator: AnyEnumerator | string) { - if (typeof(enumerator) === "string") { + if (typeof enumerator === "string") { return enumeration.type ? primitiveTypeToString(enumeration.type) : "string"; } - return typeof(enumerator.value) === "string" ? "string" : "int"; + return typeof (enumerator.value) === "string" ? "string" : "int"; } diff --git a/core/ecschema-editing/src/Editing/Formats.ts b/core/ecschema-editing/src/Editing/Formats.ts index 2e61124ac9f2..2d7b21ebc919 100644 --- a/core/ecschema-editing/src/Editing/Formats.ts +++ b/core/ecschema-editing/src/Editing/Formats.ts @@ -6,11 +6,11 @@ * @module Editing */ -import { Format, InvertedUnit, SchemaItem, SchemaItemFormatProps, SchemaItemKey, SchemaItemType, SchemaKey, Unit } from "@itwin/ecschema-metadata"; import { FormatType } from "@itwin/core-quantity"; +import { Format, InvertedUnit, SchemaItem, SchemaItemFormatProps, SchemaItemKey, SchemaItemType, SchemaKey, Unit } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableFormat } from "./Mutable/MutableFormat"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableFormat } from "./Mutable/MutableFormat"; import { SchemaItems } from "./SchemaItems"; /** @@ -22,19 +22,33 @@ export class Formats extends SchemaItems { super(SchemaItemType.Format, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, formatType: FormatType, displayLabel?: string, units?: SchemaItemKey[]): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + formatType: FormatType, + displayLabel?: string, + units?: SchemaItemKey[], + ): Promise { try { - const newFormat = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createFormat.bind(schema), name) as MutableFormat; + const newFormat = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createFormat.bind(schema), + name, + ) as MutableFormat; if (units !== undefined) { for (const unit of units) { - const unitItem = await this.schemaEditor.schemaContext.getSchemaItem(unit); + const unitItem = await this.schemaEditor.schemaContext.getSchemaItem(unit); if (!unitItem) { throw new SchemaEditingError(ECEditingStatus.SchemaItemNotFoundInContext, new SchemaItemId(SchemaItemType.Unit, unit)); } if (unitItem.schemaItemType !== SchemaItemType.Unit && unitItem.schemaItemType !== SchemaItemType.InvertedUnit) - throw new SchemaEditingError(ECEditingStatus.InvalidFormatUnitsSpecified, new SchemaItemId((unitItem as SchemaItem).schemaItemType, (unitItem as SchemaItem).key)); + throw new SchemaEditingError( + ECEditingStatus.InvalidFormatUnitsSpecified, + new SchemaItemId((unitItem as SchemaItem).schemaItemType, (unitItem as SchemaItem).key), + ); newFormat.addUnit(unitItem); } @@ -58,7 +72,12 @@ export class Formats extends SchemaItems { */ public async createFromProps(schemaKey: SchemaKey, formatProps: SchemaItemFormatProps): Promise { try { - const newFormat = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createFormat.bind(schema), formatProps); + const newFormat = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createFormat.bind(schema), + formatProps, + ); return newFormat.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, formatProps.name!, schemaKey), e); diff --git a/core/ecschema-editing/src/Editing/InvertedUnits.ts b/core/ecschema-editing/src/Editing/InvertedUnits.ts index 6564243d7c55..f00fc2cd9e7a 100644 --- a/core/ecschema-editing/src/Editing/InvertedUnits.ts +++ b/core/ecschema-editing/src/Editing/InvertedUnits.ts @@ -7,12 +7,18 @@ */ import { - DelayedPromiseWithProps, InvertedUnit, InvertedUnitProps, SchemaItemKey, - SchemaItemType, SchemaKey, Unit, UnitSystem, + DelayedPromiseWithProps, + InvertedUnit, + InvertedUnitProps, + SchemaItemKey, + SchemaItemType, + SchemaKey, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableInvertedUnit } from "./Mutable/MutableInvertedUnit"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableInvertedUnit } from "./Mutable/MutableInvertedUnit"; import { SchemaItems } from "./SchemaItems"; /** @@ -23,9 +29,20 @@ export class InvertedUnits extends SchemaItems { public constructor(schemaEditor: SchemaContextEditor) { super(SchemaItemType.InvertedUnit, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, invertsUnitKey: SchemaItemKey, unitSystemKey: SchemaItemKey, displayLabel?: string): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + invertsUnitKey: SchemaItemKey, + unitSystemKey: SchemaItemKey, + displayLabel?: string, + ): Promise { try { - const newUnit = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createInvertedUnit.bind(schema), name) as MutableInvertedUnit; + const newUnit = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createInvertedUnit.bind(schema), + name, + ) as MutableInvertedUnit; const invertsUnit = await this.lookupSchemaItem(schemaKey, invertsUnitKey, SchemaItemType.Unit); newUnit.setInvertsUnit(new DelayedPromiseWithProps(invertsUnitKey, async () => invertsUnit)); @@ -44,10 +61,19 @@ export class InvertedUnits extends SchemaItems { public async createFromProps(schemaKey: SchemaKey, invertedUnitProps: InvertedUnitProps): Promise { try { - const newUnit = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createInvertedUnit.bind(schema), invertedUnitProps); + const newUnit = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createInvertedUnit.bind(schema), + invertedUnitProps, + ); return newUnit.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, invertedUnitProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new SchemaItemId(this.schemaItemType, invertedUnitProps.name!, schemaKey), + e, + ); } } @@ -56,7 +82,7 @@ export class InvertedUnits extends SchemaItems { const invertedUnit = await this.getSchemaItem(invertedUnitKey); const invertsUnit = await this.getSchemaItem(invertedUnitKey, SchemaItemType.Unit); invertedUnit.setInvertsUnit(new DelayedPromiseWithProps(invertsUnitKey, async () => invertsUnit)); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetInvertsUnit, new SchemaItemId(this.schemaItemType, invertedUnitKey), e); } } @@ -66,7 +92,7 @@ export class InvertedUnits extends SchemaItems { const invertedUnit = await this.getSchemaItem(invertedUnitKey); const unitSystem = await this.getSchemaItem(unitSystemKey, SchemaItemType.UnitSystem); invertedUnit.setUnitSystem(new DelayedPromiseWithProps(unitSystemKey, async () => unitSystem)); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetUnitSystem, new SchemaItemId(this.schemaItemType, invertedUnitKey), e); } } diff --git a/core/ecschema-editing/src/Editing/KindOfQuantities.ts b/core/ecschema-editing/src/Editing/KindOfQuantities.ts index b3e8d4dc5080..aff180044b9c 100644 --- a/core/ecschema-editing/src/Editing/KindOfQuantities.ts +++ b/core/ecschema-editing/src/Editing/KindOfQuantities.ts @@ -8,12 +8,19 @@ import { DelayedPromiseWithProps, - Format, InvertedUnit, KindOfQuantity, KindOfQuantityProps, OverrideFormat, - SchemaItemKey, SchemaItemType, SchemaKey, Unit, + Format, + InvertedUnit, + KindOfQuantity, + KindOfQuantityProps, + OverrideFormat, + SchemaItemKey, + SchemaItemType, + SchemaKey, + Unit, } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableKindOfQuantity } from "./Mutable/MutableKindOfQuantity"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableKindOfQuantity } from "./Mutable/MutableKindOfQuantity"; import { SchemaItems } from "./SchemaItems"; /** @@ -27,7 +34,12 @@ export class KindOfQuantities extends SchemaItems { public async create(schemaKey: SchemaKey, name: string, persistenceUnitKey: SchemaItemKey, displayLabel?: string): Promise { try { - const koqItem = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createKindOfQuantity.bind(schema), name) as MutableKindOfQuantity; + const koqItem = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createKindOfQuantity.bind(schema), + name, + ) as MutableKindOfQuantity; const persistenceUnit = await koqItem.schema.lookupItem(persistenceUnitKey); if (persistenceUnit === undefined) throw new SchemaEditingError(ECEditingStatus.SchemaItemNotFound, new SchemaItemId(SchemaItemType.Unit, persistenceUnitKey)); @@ -52,7 +64,12 @@ export class KindOfQuantities extends SchemaItems { public async createFromProps(schemaKey: SchemaKey, koqProps: KindOfQuantityProps): Promise { try { - const koqItem = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createKindOfQuantity.bind(schema), koqProps); + const koqItem = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createKindOfQuantity.bind(schema), + koqProps, + ); return koqItem.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, koqProps.name!, schemaKey), e); @@ -60,7 +77,6 @@ export class KindOfQuantities extends SchemaItems { } /** - * * @param koqKey A schemaItemKey of the editing KindOfQuantity. * @param format A schemaItemKey of a Format. * @param isDefault .is set to false when not explicitly passed. @@ -70,7 +86,7 @@ export class KindOfQuantities extends SchemaItems { const kindOfQuantity = await this.getSchemaItem(koqKey); const presentationFormat = await this.getSchemaItem(format, SchemaItemType.Format); kindOfQuantity.addPresentationFormat(presentationFormat, isDefault); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddPresentationUnit, new SchemaItemId(this.schemaItemType, koqKey), e); } } @@ -79,7 +95,7 @@ export class KindOfQuantities extends SchemaItems { try { const kindOfQuantity = await this.getSchemaItem(koqKey); kindOfQuantity.addPresentationFormat(overrideFormat, isDefault); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddPresentationOverride, new SchemaItemId(this.schemaItemType, koqKey), e); } } @@ -89,13 +105,18 @@ export class KindOfQuantities extends SchemaItems { * @param parent A SchemaItemKey of the parent Format. * @param unitLabelOverrides The list of Unit (or InvertedUnit) and label overrides. The length of list should be equal to the number of units in the parent Format. */ - public async createFormatOverride(koqKey: SchemaItemKey, parent: SchemaItemKey, precision?: number, unitLabelOverrides?: Array<[Unit | InvertedUnit, string | undefined]>): Promise { + public async createFormatOverride( + koqKey: SchemaItemKey, + parent: SchemaItemKey, + precision?: number, + unitLabelOverrides?: Array<[Unit | InvertedUnit, string | undefined]>, + ): Promise { try { await this.getSchemaItem(koqKey); const parentFormat = await this.getSchemaItem(parent, SchemaItemType.Format); return new OverrideFormat(parentFormat, precision, unitLabelOverrides); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddPresentationOverride, new SchemaItemId(this.schemaItemType, koqKey), e); } } diff --git a/core/ecschema-editing/src/Editing/Mixins.ts b/core/ecschema-editing/src/Editing/Mixins.ts index ad770b60b8fd..7989b8517f18 100644 --- a/core/ecschema-editing/src/Editing/Mixins.ts +++ b/core/ecschema-editing/src/Editing/Mixins.ts @@ -7,15 +7,23 @@ */ import { - DelayedPromiseWithProps, EntityClass, Mixin, MixinProps, NavigationPropertyProps, RelationshipClass, - SchemaItemKey, SchemaItemType, SchemaKey, StrengthDirection, + DelayedPromiseWithProps, + EntityClass, + Mixin, + MixinProps, + NavigationPropertyProps, + RelationshipClass, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StrengthDirection, } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "./Editor"; import { ECClasses } from "./ECClasses"; -import { MutableMixin } from "./Mutable/MutableMixin"; +import { SchemaContextEditor } from "./Editor"; +import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; import { MutableEntityClass } from "./Mutable/MutableEntityClass"; +import { MutableMixin } from "./Mutable/MutableMixin"; import { NavigationProperties } from "./Properties"; -import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; /** * @alpha @@ -31,9 +39,21 @@ export class Mixins extends ECClasses { */ public readonly navigationProperties = new NavigationProperties(SchemaItemType.Mixin, this.schemaEditor); - public async create(schemaKey: SchemaKey, name: string, appliesTo: SchemaItemKey, displayLabel?: string, baseClassKey?: SchemaItemKey): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + appliesTo: SchemaItemKey, + displayLabel?: string, + baseClassKey?: SchemaItemKey, + ): Promise { try { - const newClass = await this.createClass(schemaKey, this.schemaItemType, (schema) => schema.createMixinClass.bind(schema), name, baseClassKey) as MutableMixin; + const newClass = await this.createClass( + schemaKey, + this.schemaItemType, + (schema) => schema.createMixinClass.bind(schema), + name, + baseClassKey, + ) as MutableMixin; const newAppliesTo = await this.getSchemaItem(appliesTo, SchemaItemType.EntityClass); newClass.setAppliesTo(new DelayedPromiseWithProps(newAppliesTo.key, async () => newAppliesTo)); @@ -53,7 +73,12 @@ export class Mixins extends ECClasses { */ public async createFromProps(schemaKey: SchemaKey, mixinProps: MixinProps): Promise { try { - const newClass = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createMixinClass.bind(schema), mixinProps); + const newClass = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createMixinClass.bind(schema), + mixinProps, + ); return newClass.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new ClassId(this.schemaItemType, mixinProps.name!, schemaKey), e); @@ -65,16 +90,21 @@ export class Mixins extends ECClasses { const entity = await this.getSchemaItem(entityKey, SchemaItemType.EntityClass); const mixin = await this.getSchemaItem(mixinKey); entity.addMixin(mixin); - } catch(e: any){ + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.AddMixin, new ClassId(SchemaItemType.EntityClass, entityKey), e); } } - public async createNavigationProperty(mixinKey: SchemaItemKey, name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise { + public async createNavigationProperty( + mixinKey: SchemaItemKey, + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise { try { const mixin = await this.getSchemaItem(mixinKey); await mixin.createNavigationProperty(name, relationship, direction); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateNavigationProperty, new ClassId(SchemaItemType.Mixin, mixinKey), e); } } @@ -89,7 +119,7 @@ export class Mixins extends ECClasses { const mixin = await this.getSchemaItem(classKey); const property = await mixin.createNavigationProperty(navigationProps.name, navigationProps.relationshipName, navigationProps.direction); await property.fromJSON(navigationProps); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateNavigationPropertyFromProps, new ClassId(SchemaItemType.RelationshipClass, classKey), e); } } diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableClass.ts b/core/ecschema-editing/src/Editing/Mutable/MutableClass.ts index 6743a26fe449..85f9087dcb49 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableClass.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableClass.ts @@ -3,8 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { - CustomAttribute, ECClass, ECClassModifier, Enumeration, EnumerationArrayProperty, EnumerationProperty, PrimitiveArrayProperty, - PrimitiveProperty, PrimitiveType, Property, StructArrayProperty, StructClass, StructProperty, + CustomAttribute, + ECClass, + ECClassModifier, + Enumeration, + EnumerationArrayProperty, + EnumerationProperty, + PrimitiveArrayProperty, + PrimitiveProperty, + PrimitiveType, + Property, + StructArrayProperty, + StructClass, + StructProperty, } from "@itwin/ecschema-metadata"; /** diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableEntityClass.ts b/core/ecschema-editing/src/Editing/Mutable/MutableEntityClass.ts index 47b28c5c3828..e46e692d2cd6 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableEntityClass.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableEntityClass.ts @@ -2,10 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - EntityClass, Mixin, NavigationProperty, - RelationshipClass, StrengthDirection, -} from "@itwin/ecschema-metadata"; +import { EntityClass, Mixin, NavigationProperty, RelationshipClass, StrengthDirection } from "@itwin/ecschema-metadata"; /** * Hackish approach that works like a "friend class" so we can access protected members without making them public. @@ -13,7 +10,15 @@ import { */ export abstract class MutableEntityClass extends EntityClass { public abstract override addMixin(mixin: Mixin): any; - public abstract override createNavigationProperty(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise; - public abstract override createNavigationPropertySync(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): NavigationProperty; + public abstract override createNavigationProperty( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise; + public abstract override createNavigationPropertySync( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): NavigationProperty; public abstract override setDisplayLabel(displayLabel: string): void; } diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableFormat.ts b/core/ecschema-editing/src/Editing/Mutable/MutableFormat.ts index 4ac4b4edabf9..96832dad1e72 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableFormat.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableFormat.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Format, InvertedUnit, Unit } from "@itwin/ecschema-metadata"; import { FormatType, ShowSignOption } from "@itwin/core-quantity"; +import { Format, InvertedUnit, Unit } from "@itwin/ecschema-metadata"; /** * @internal diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableKindOfQuantity.ts b/core/ecschema-editing/src/Editing/Mutable/MutableKindOfQuantity.ts index 368c2ebc2c31..96d8de1b108c 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableKindOfQuantity.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableKindOfQuantity.ts @@ -10,7 +10,11 @@ import { Format, InvertedUnit, KindOfQuantity, LazyLoadedInvertedUnit, LazyLoade */ export abstract class MutableKindOfQuantity extends KindOfQuantity { public abstract override addPresentationFormat(format: Format | OverrideFormat, isDefault: boolean): void; - public abstract override createFormatOverride(parent: Format, precision?: number, unitLabelOverrides?: Array<[Unit | InvertedUnit, string | undefined]>): OverrideFormat; + public abstract override createFormatOverride( + parent: Format, + precision?: number, + unitLabelOverrides?: Array<[Unit | InvertedUnit, string | undefined]>, + ): OverrideFormat; public abstract override setDisplayLabel(displayLabel: string): void; public abstract override setDescription(description: string): void; public abstract override setRelativeError(relativeError: number): void; diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableMixin.ts b/core/ecschema-editing/src/Editing/Mutable/MutableMixin.ts index 3295829c698f..738baa8a15f6 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableMixin.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableMixin.ts @@ -10,7 +10,15 @@ import { LazyLoadedEntityClass, Mixin, NavigationProperty, RelationshipClass, St */ export abstract class MutableMixin extends Mixin { public abstract override setAppliesTo(entityClass: LazyLoadedEntityClass): void; - public abstract override createNavigationProperty(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise; - public abstract override createNavigationPropertySync(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): NavigationProperty; + public abstract override createNavigationProperty( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise; + public abstract override createNavigationPropertySync( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): NavigationProperty; public abstract override setDisplayLabel(displayLabel: string): void; } diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableRelationshipClass.ts b/core/ecschema-editing/src/Editing/Mutable/MutableRelationshipClass.ts index 395bb9e150e6..6907336230fd 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableRelationshipClass.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableRelationshipClass.ts @@ -2,7 +2,19 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CustomAttribute, EntityClass, LazyLoadedRelationshipConstraintClass, Mixin, NavigationProperty, RelationshipClass, RelationshipConstraint, RelationshipEnd, RelationshipMultiplicity, StrengthDirection, StrengthType } from "@itwin/ecschema-metadata"; +import { + CustomAttribute, + EntityClass, + LazyLoadedRelationshipConstraintClass, + Mixin, + NavigationProperty, + RelationshipClass, + RelationshipConstraint, + RelationshipEnd, + RelationshipMultiplicity, + StrengthDirection, + StrengthType, +} from "@itwin/ecschema-metadata"; /** * Hackish approach that works like a "friend class" so we can access protected members without making them public. @@ -13,7 +25,7 @@ export abstract class MutableRelationshipConstraint extends RelationshipConstrai public abstract override set multiplicity(multiplicity: RelationshipMultiplicity); public abstract override set polymorphic(polymorphic: boolean); public abstract override set roleLabel(roleLabel: string | undefined); - public abstract override set relationshipEnd(relationshipEnd: RelationshipEnd) ; + public abstract override set relationshipEnd(relationshipEnd: RelationshipEnd); public abstract override set abstractConstraint(abstractConstraint: LazyLoadedRelationshipConstraintClass | undefined); public abstract override removeClass(constraint: EntityClass | Mixin | RelationshipClass): void; } @@ -23,13 +35,25 @@ export abstract class MutableRelationshipConstraint extends RelationshipConstrai * An abstract class used for schema editing. */ export abstract class MutableRelationshipClass extends RelationshipClass { - public override get source() { return this._source as MutableRelationshipConstraint; } - public override get target() { return this._target as MutableRelationshipConstraint; } + public override get source() { + return this._source as MutableRelationshipConstraint; + } + public override get target() { + return this._target as MutableRelationshipConstraint; + } public abstract override setStrength(strength: StrengthType): void; public abstract override setStrengthDirection(direction: StrengthDirection): void; public abstract override setSourceConstraint(source: RelationshipConstraint): void; public abstract override setTargetConstraint(target: RelationshipConstraint): void; - public abstract override createNavigationProperty(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise; - public abstract override createNavigationPropertySync(name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): NavigationProperty; + public abstract override createNavigationProperty( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise; + public abstract override createNavigationPropertySync( + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): NavigationProperty; public abstract override setDisplayLabel(displayLabel: string): void; } diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableSchema.ts b/core/ecschema-editing/src/Editing/Mutable/MutableSchema.ts index a416b2ee47b3..9e8a35740dd7 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableSchema.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableSchema.ts @@ -3,9 +3,26 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { - Constant, CustomAttribute, CustomAttributeClass, ECClassModifier, EntityClass, Enumeration, - Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, PrimitiveType, PropertyCategory, - RelationshipClass, Schema, SchemaContext, SchemaItem, StructClass, Unit, UnitSystem, + Constant, + CustomAttribute, + CustomAttributeClass, + ECClassModifier, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PrimitiveType, + PropertyCategory, + RelationshipClass, + Schema, + SchemaContext, + SchemaItem, + StructClass, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; /** diff --git a/core/ecschema-editing/src/Editing/Mutable/MutableSchemaItem.ts b/core/ecschema-editing/src/Editing/Mutable/MutableSchemaItem.ts index fb320121df42..e271d2401e56 100644 --- a/core/ecschema-editing/src/Editing/Mutable/MutableSchemaItem.ts +++ b/core/ecschema-editing/src/Editing/Mutable/MutableSchemaItem.ts @@ -2,7 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import {SchemaItem} from "@itwin/ecschema-metadata"; +import { SchemaItem } from "@itwin/ecschema-metadata"; /** * Hackish approach that works like a "friend class" so we can access protected members without making them public. diff --git a/core/ecschema-editing/src/Editing/Phenomena.ts b/core/ecschema-editing/src/Editing/Phenomena.ts index 89854dcdc087..7f4aff29ebbb 100644 --- a/core/ecschema-editing/src/Editing/Phenomena.ts +++ b/core/ecschema-editing/src/Editing/Phenomena.ts @@ -8,8 +8,8 @@ import { Phenomenon, PhenomenonProps, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutablePhenomenon } from "./Mutable/MutablePhenomenon"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutablePhenomenon } from "./Mutable/MutablePhenomenon"; import { SchemaItems } from "./SchemaItems"; /** @@ -23,7 +23,12 @@ export class Phenomena extends SchemaItems { public async create(schemaKey: SchemaKey, name: string, definition: string, displayLabel?: string): Promise { try { - const newPhenomenon = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createPhenomenon.bind(schema), name) as MutablePhenomenon; + const newPhenomenon = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createPhenomenon.bind(schema), + name, + ) as MutablePhenomenon; if (displayLabel) newPhenomenon.setDisplayLabel(displayLabel); @@ -38,10 +43,19 @@ export class Phenomena extends SchemaItems { public async createFromProps(schemaKey: SchemaKey, phenomenonProps: PhenomenonProps): Promise { try { - const newPhenomenon = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createPhenomenon.bind(schema), phenomenonProps); + const newPhenomenon = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createPhenomenon.bind(schema), + phenomenonProps, + ); return newPhenomenon.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, phenomenonProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new SchemaItemId(this.schemaItemType, phenomenonProps.name!, schemaKey), + e, + ); } } } diff --git a/core/ecschema-editing/src/Editing/Properties.ts b/core/ecschema-editing/src/Editing/Properties.ts index 5e8072991519..490a9b62ff74 100644 --- a/core/ecschema-editing/src/Editing/Properties.ts +++ b/core/ecschema-editing/src/Editing/Properties.ts @@ -1,20 +1,37 @@ -import { CustomAttribute, CustomAttributeContainerProps, DelayedPromiseWithProps, ECClass, ECName, - EnumerationProperty, KindOfQuantity, NavigationProperty, PrimitiveProperty, - PropertyCategory, SchemaItemKey, SchemaItemType, StructProperty } from "@itwin/ecschema-metadata"; import { assert } from "@itwin/core-bentley"; -import { SchemaContextEditor } from "./Editor"; +import { + CustomAttribute, + CustomAttributeContainerProps, + DelayedPromiseWithProps, + ECClass, + ECName, + EnumerationProperty, + KindOfQuantity, + NavigationProperty, + PrimitiveProperty, + PropertyCategory, + SchemaItemKey, + SchemaItemType, + StructProperty, +} from "@itwin/ecschema-metadata"; +import { AnyDiagnostic } from "../Validation/Diagnostic"; import * as Rules from "../Validation/ECRules"; +import { ECClassSchemaItems } from "./ECClasses"; +import { SchemaContextEditor } from "./Editor"; +import { ClassId, CustomAttributeId, ECEditingStatus, PropertyId, PropertyTypeName, SchemaEditingError, SchemaId } from "./Exception"; import { MutableArrayProperty } from "./Mutable/MutableArrayProperty"; -import { MutableProperty } from "./Mutable/MutableProperty"; -import { MutablePrimitiveOrEnumPropertyBase } from "./Mutable/MutablePrimitiveOrEnumProperty"; import { MutableClass } from "./Mutable/MutableClass"; -import { MutableStructProperty } from "./Mutable/MutableStructProperty"; import { MutableNavigationProperty } from "./Mutable/MutableNavigationProperty"; -import { ECClassSchemaItems } from "./ECClasses"; -import { ClassId, CustomAttributeId, ECEditingStatus, PropertyId, PropertyTypeName, SchemaEditingError, SchemaId } from "./Exception"; -import { AnyDiagnostic } from "../Validation/Diagnostic"; +import { MutablePrimitiveOrEnumPropertyBase } from "./Mutable/MutablePrimitiveOrEnumProperty"; +import { MutableProperty } from "./Mutable/MutableProperty"; +import { MutableStructProperty } from "./Mutable/MutableStructProperty"; -type MutablePropertyType = MutableProperty | MutableArrayProperty | MutablePrimitiveOrEnumPropertyBase | MutableNavigationProperty | MutableStructProperty; +type MutablePropertyType = + | MutableProperty + | MutableArrayProperty + | MutablePrimitiveOrEnumPropertyBase + | MutableNavigationProperty + | MutableStructProperty; /** * @alpha @@ -28,9 +45,12 @@ export class Properties { let newName: ECName; try { newName = new ECName(newPropertyName); - } catch(e: any) { - throw new SchemaEditingError(ECEditingStatus.SetPropertyName, new PropertyId(this.ecClassType, classKey, propertyName), - new SchemaEditingError(ECEditingStatus.InvalidECName, new PropertyId(this.ecClassType, classKey, newPropertyName))); + } catch (e: any) { + throw new SchemaEditingError( + ECEditingStatus.SetPropertyName, + new PropertyId(this.ecClassType, classKey, propertyName), + new SchemaEditingError(ECEditingStatus.InvalidECName, new PropertyId(this.ecClassType, classKey, newPropertyName)), + ); } const existingProperty = await this.getProperty(classKey, propertyName) @@ -40,8 +60,11 @@ export class Properties { const baseProperty = await existingProperty.class.getProperty(newPropertyName, true) as MutableProperty; if (baseProperty) { - throw new SchemaEditingError(ECEditingStatus.SetPropertyName, new PropertyId(this.ecClassType, classKey, propertyName), - new SchemaEditingError(ECEditingStatus.PropertyAlreadyExists, new PropertyId(this.ecClassType, baseProperty.class.key, newPropertyName))); + throw new SchemaEditingError( + ECEditingStatus.SetPropertyName, + new PropertyId(this.ecClassType, classKey, propertyName), + new SchemaEditingError(ECEditingStatus.PropertyAlreadyExists, new PropertyId(this.ecClassType, baseProperty.class.key, newPropertyName)), + ); } // Handle derived classes @@ -49,8 +72,11 @@ export class Properties { const derivedClasses = await this.findDerivedClasses(existingProperty.class as MutableClass); for (const derivedClass of derivedClasses) { if (await derivedClass.getProperty(newPropertyName)) { - throw new SchemaEditingError(ECEditingStatus.SetPropertyName, new PropertyId(this.ecClassType, classKey, propertyName), - new SchemaEditingError(ECEditingStatus.PropertyAlreadyExists, new PropertyId(this.ecClassType, derivedClass.key, newPropertyName))); + throw new SchemaEditingError( + ECEditingStatus.SetPropertyName, + new PropertyId(this.ecClassType, classKey, propertyName), + new SchemaEditingError(ECEditingStatus.PropertyAlreadyExists, new PropertyId(this.ecClassType, derivedClass.key, newPropertyName)), + ); } const propertyOverride = await derivedClass.getProperty(propertyName) as MutableProperty; @@ -161,8 +187,16 @@ export class Properties { }); const currentKoq = await property.kindOfQuantity; - if(currentKoq && currentKoq.persistenceUnit && koq.persistenceUnit && !currentKoq.persistenceUnit.matchesFullName(koq.persistenceUnit.fullName)) { - throw new SchemaEditingError(ECEditingStatus.SetKindOfQuantity, new PropertyId(this.ecClassType, classKey, propertyName), undefined, undefined, "KindOfQuantity can only be changed if it has the same persistence unit as the property."); + if ( + currentKoq && currentKoq.persistenceUnit && koq.persistenceUnit && !currentKoq.persistenceUnit.matchesFullName(koq.persistenceUnit.fullName) + ) { + throw new SchemaEditingError( + ECEditingStatus.SetKindOfQuantity, + new PropertyId(this.ecClassType, classKey, propertyName), + undefined, + undefined, + "KindOfQuantity can only be changed if it has the same persistence unit as the property.", + ); } property.setKindOfQuantity(new DelayedPromiseWithProps(kindOfQuantityKey, async () => koq)); @@ -191,8 +225,11 @@ export class Properties { if (diagnostics.length > 0) { this.removeCustomAttribute(property, customAttribute); - throw new SchemaEditingError(ECEditingStatus.AddCustomAttributeToProperty, new PropertyId(this.ecClassType, classKey, propertyName), - new SchemaEditingError(ECEditingStatus.RuleViolation, new CustomAttributeId(customAttribute.className, property))); + throw new SchemaEditingError( + ECEditingStatus.AddCustomAttributeToProperty, + new PropertyId(this.ecClassType, classKey, propertyName), + new SchemaEditingError(ECEditingStatus.RuleViolation, new CustomAttributeId(customAttribute.className, property)), + ); } } @@ -217,17 +254,20 @@ export class Properties { const property = await mutableClass.getProperty(propertyName) as T; if (property === undefined) { - throw new SchemaEditingError(ECEditingStatus.PropertyNotFound, new PropertyId(mutableClass.schemaItemType as ECClassSchemaItems, classKey, propertyName)); + throw new SchemaEditingError( + ECEditingStatus.PropertyNotFound, + new PropertyId(mutableClass.schemaItemType as ECClassSchemaItems, classKey, propertyName), + ); } return property; } - private async findDerivedClasses(mutableClass: MutableClass): Promise>{ + private async findDerivedClasses(mutableClass: MutableClass): Promise> { const derivedClasses: Array = []; for await (const schemaItem of this._schemaEditor.schemaContext.getSchemaItems()) { - if(ECClass.isECClass(schemaItem) && await schemaItem.is(mutableClass)) { + if (ECClass.isECClass(schemaItem) && await schemaItem.is(mutableClass)) { if (!mutableClass.key.matches(schemaItem.key)) { derivedClasses.push(schemaItem as MutableClass); } @@ -246,7 +286,7 @@ export class Properties { if (ecClass === undefined) throw new SchemaEditingError(ECEditingStatus.SchemaItemNotFound, new ClassId(this.ecClassType, classKey)); - if (ecClass.schemaItemType !== this.ecClassType){ + if (ecClass.schemaItemType !== this.ecClassType) { throw new SchemaEditingError(ECEditingStatus.InvalidSchemaItemType, new ClassId(this.ecClassType, classKey)); } @@ -299,8 +339,11 @@ export class ArrayProperties extends Properties { */ protected override async getProperty(classKey: SchemaItemKey, propertyName: string): Promise { const property = await super.getProperty(classKey, propertyName) as T; - if (!property.isArray()){ - throw new SchemaEditingError(ECEditingStatus.InvalidPropertyType, new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.ArrayProperty)); + if (!property.isArray()) { + throw new SchemaEditingError( + ECEditingStatus.InvalidPropertyType, + new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.ArrayProperty), + ); } return property; } @@ -402,8 +445,11 @@ export class PrimitiveProperties extends PrimitiveOrEnumProperties { */ protected override async getProperty(classKey: SchemaItemKey, propertyName: string): Promise { const property = await super.getProperty(classKey, propertyName) as T; - if (!(property instanceof PrimitiveProperty)){ - throw new SchemaEditingError(ECEditingStatus.InvalidPropertyType, new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.PrimitiveProperty)); + if (!(property instanceof PrimitiveProperty)) { + throw new SchemaEditingError( + ECEditingStatus.InvalidPropertyType, + new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.PrimitiveProperty), + ); } return property; } @@ -425,8 +471,11 @@ export class EnumerationProperties extends PrimitiveOrEnumProperties { */ protected override async getProperty(classKey: SchemaItemKey, propertyName: string): Promise { const property = await super.getProperty(classKey, propertyName) as T; - if (!(property instanceof EnumerationProperty)){ - throw new SchemaEditingError(ECEditingStatus.InvalidPropertyType, new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.EnumerationProperty)); + if (!(property instanceof EnumerationProperty)) { + throw new SchemaEditingError( + ECEditingStatus.InvalidPropertyType, + new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.EnumerationProperty), + ); } return property; } @@ -448,8 +497,11 @@ export class NavigationProperties extends Properties { */ protected override async getProperty(classKey: SchemaItemKey, propertyName: string): Promise { const property = await super.getProperty(classKey, propertyName) as T; - if (!(property instanceof NavigationProperty)){ - throw new SchemaEditingError(ECEditingStatus.InvalidPropertyType, new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.NavigationProperty)); + if (!(property instanceof NavigationProperty)) { + throw new SchemaEditingError( + ECEditingStatus.InvalidPropertyType, + new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.NavigationProperty), + ); } return property; } @@ -471,10 +523,12 @@ export class StructProperties extends Properties { */ protected override async getProperty(classKey: SchemaItemKey, propertyName: string): Promise { const property = await super.getProperty(classKey, propertyName) as T; - if (!(property instanceof StructProperty)){ - throw new SchemaEditingError(ECEditingStatus.InvalidPropertyType, new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.StructProperty)); + if (!(property instanceof StructProperty)) { + throw new SchemaEditingError( + ECEditingStatus.InvalidPropertyType, + new PropertyId(this.ecClassType, classKey, propertyName, PropertyTypeName.StructProperty), + ); } return property; } } - diff --git a/core/ecschema-editing/src/Editing/PropertyCategories.ts b/core/ecschema-editing/src/Editing/PropertyCategories.ts index c37faa48796f..a80f7b728642 100644 --- a/core/ecschema-editing/src/Editing/PropertyCategories.ts +++ b/core/ecschema-editing/src/Editing/PropertyCategories.ts @@ -8,8 +8,8 @@ import { PropertyCategory, PropertyCategoryProps, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutablePropertyCategory } from "./Mutable/MutablePropertyCategory"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutablePropertyCategory } from "./Mutable/MutablePropertyCategory"; import { SchemaItems } from "./SchemaItems"; /** @@ -23,7 +23,12 @@ export class PropertyCategories extends SchemaItems { public async create(schemaKey: SchemaKey, name: string, priority: number, displayLabel?: string): Promise { try { - const newPropCategory = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createPropertyCategory.bind(schema), name) as MutablePropertyCategory; + const newPropCategory = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createPropertyCategory.bind(schema), + name, + ) as MutablePropertyCategory; newPropCategory.setPriority(priority); if (displayLabel) newPropCategory.setDisplayLabel(displayLabel); @@ -36,10 +41,19 @@ export class PropertyCategories extends SchemaItems { public async createFromProps(schemaKey: SchemaKey, propertyCategoryProps: PropertyCategoryProps): Promise { try { - const newPropCategory = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createPropertyCategory.bind(schema), propertyCategoryProps); + const newPropCategory = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createPropertyCategory.bind(schema), + propertyCategoryProps, + ); return newPropCategory.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, propertyCategoryProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new SchemaItemId(this.schemaItemType, propertyCategoryProps.name!, schemaKey), + e, + ); } } @@ -47,7 +61,7 @@ export class PropertyCategories extends SchemaItems { try { const propertyCategory = await this.getSchemaItem(propCategoryKey); propertyCategory.setPriority(priority); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.SetPropertyCategoryPriority, new SchemaItemId(this.schemaItemType, propCategoryKey), e); } } diff --git a/core/ecschema-editing/src/Editing/RelationshipClasses.ts b/core/ecschema-editing/src/Editing/RelationshipClasses.ts index 14581961aa46..c1c1ae8d02f0 100644 --- a/core/ecschema-editing/src/Editing/RelationshipClasses.ts +++ b/core/ecschema-editing/src/Editing/RelationshipClasses.ts @@ -7,17 +7,31 @@ */ import { - CustomAttribute, DelayedPromiseWithProps, ECClassModifier, EntityClass, LazyLoadedRelationshipConstraintClass, Mixin, NavigationPropertyProps, - RelationshipClass, RelationshipClassProps, RelationshipConstraint, RelationshipEnd, RelationshipMultiplicity, SchemaItemKey, SchemaItemType, - SchemaKey, StrengthDirection, StrengthType, + CustomAttribute, + DelayedPromiseWithProps, + ECClassModifier, + EntityClass, + LazyLoadedRelationshipConstraintClass, + Mixin, + NavigationPropertyProps, + RelationshipClass, + RelationshipClassProps, + RelationshipConstraint, + RelationshipEnd, + RelationshipMultiplicity, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StrengthDirection, + StrengthType, } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "./Editor"; +import { AnyDiagnostic, RelationshipConstraintDiagnostic, SchemaItemDiagnostic } from "../Validation/Diagnostic"; +import * as Rules from "../Validation/ECRules"; import { ECClasses } from "./ECClasses"; +import { SchemaContextEditor } from "./Editor"; +import { ClassId, CustomAttributeId, ECEditingStatus, RelationshipConstraintId, SchemaEditingError } from "./Exception"; import { MutableRelationshipClass, MutableRelationshipConstraint } from "./Mutable/MutableRelationshipClass"; -import * as Rules from "../Validation/ECRules"; -import { AnyDiagnostic, RelationshipConstraintDiagnostic, SchemaItemDiagnostic } from "../Validation/Diagnostic"; import { NavigationProperties } from "./Properties"; -import { ClassId, CustomAttributeId, ECEditingStatus, RelationshipConstraintId, SchemaEditingError } from "./Exception"; /** * @alpha @@ -42,9 +56,23 @@ export class RelationshipClasses extends ECClasses { * @param StrengthDirection The relationship StrengthDirection of the class. * @param baseClassKey An optional SchemaItemKey that specifies the base relationship class. */ - public async create(schemaKey: SchemaKey, name: string, modifier: ECClassModifier, strength: StrengthType, direction: StrengthDirection, baseClassKey?: SchemaItemKey): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + modifier: ECClassModifier, + strength: StrengthType, + direction: StrengthDirection, + baseClassKey?: SchemaItemKey, + ): Promise { try { - const newClass = await this.createClass(schemaKey, this.schemaItemType, (schema) => schema.createRelationshipClass.bind(schema), name, baseClassKey, modifier) as MutableRelationshipClass; + const newClass = await this.createClass( + schemaKey, + this.schemaItemType, + (schema) => schema.createRelationshipClass.bind(schema), + name, + baseClassKey, + modifier, + ) as MutableRelationshipClass; newClass.setStrength(strength); newClass.setStrengthDirection(direction); @@ -90,14 +118,23 @@ export class RelationshipClasses extends ECClasses { */ public async createFromProps(schemaKey: SchemaKey, relationshipProps: RelationshipClassProps): Promise { try { - const newClass = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createRelationshipClass.bind(schema), relationshipProps); + const newClass = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createRelationshipClass.bind(schema), + relationshipProps, + ); await newClass.source.fromJSON(relationshipProps.source); await newClass.target.fromJSON(relationshipProps.target); return newClass.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new ClassId(this.schemaItemType, relationshipProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new ClassId(this.schemaItemType, relationshipProps.name!, schemaKey), + e, + ); } } @@ -114,17 +151,22 @@ export class RelationshipClasses extends ECClasses { try { await this.validate(relClass!); - } catch(e: any) { + } catch (e: any) { relClass!.baseClass = baseClass; throw new SchemaEditingError(ECEditingStatus.SetBaseClass, new ClassId(SchemaItemType.RelationshipClass, itemKey), e); } } - public async createNavigationProperty(relationshipKey: SchemaItemKey, name: string, relationship: string | RelationshipClass, direction: string | StrengthDirection): Promise { + public async createNavigationProperty( + relationshipKey: SchemaItemKey, + name: string, + relationship: string | RelationshipClass, + direction: string | StrengthDirection, + ): Promise { try { const relationshipClass = await this.getSchemaItem(relationshipKey); await relationshipClass.createNavigationProperty(name, relationship, direction); - } catch(e: any) { + } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateNavigationProperty, new ClassId(SchemaItemType.RelationshipClass, relationshipKey), e); } } @@ -137,10 +179,18 @@ export class RelationshipClasses extends ECClasses { public async createNavigationPropertyFromProps(relationshipKey: SchemaItemKey, navigationProps: NavigationPropertyProps): Promise { try { const relationshipClass = await this.getSchemaItem(relationshipKey); - const property = await relationshipClass.createNavigationProperty(navigationProps.name, navigationProps.relationshipName, navigationProps.direction); + const property = await relationshipClass.createNavigationProperty( + navigationProps.name, + navigationProps.relationshipName, + navigationProps.direction, + ); await property.fromJSON(navigationProps); - } catch(e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateNavigationPropertyFromProps, new ClassId(SchemaItemType.RelationshipClass, relationshipKey), e); + } catch (e: any) { + throw new SchemaEditingError( + ECEditingStatus.CreateNavigationPropertyFromProps, + new ClassId(SchemaItemType.RelationshipClass, relationshipKey), + e, + ); } } @@ -159,8 +209,11 @@ export class RelationshipClasses extends ECClasses { mutableConstraint.relationshipEnd = relationshipEnd; } - public async setAbstractConstraint(constraint: RelationshipConstraint, abstractConstraint?: EntityClass | Mixin | RelationshipClass): Promise { - const existing: LazyLoadedRelationshipConstraintClass | undefined = constraint.abstractConstraint; + public async setAbstractConstraint( + constraint: RelationshipConstraint, + abstractConstraint?: EntityClass | Mixin | RelationshipClass, + ): Promise { + const existing: LazyLoadedRelationshipConstraintClass | undefined = constraint.abstractConstraint; const mutableConstraint = constraint as MutableRelationshipConstraint; if (undefined === abstractConstraint) { @@ -171,14 +224,14 @@ export class RelationshipClasses extends ECClasses { try { await this.validate(constraint.relationshipClass); - } catch(e: any){ + } catch (e: any) { mutableConstraint.abstractConstraint = existing; throw new SchemaEditingError(ECEditingStatus.SetAbstractConstraint, new RelationshipConstraintId(constraint), e); } try { await this.validate(constraint); - } catch(e: any){ + } catch (e: any) { mutableConstraint.abstractConstraint = existing; throw new SchemaEditingError(ECEditingStatus.SetAbstractConstraint, new RelationshipConstraintId(constraint), e); } @@ -190,14 +243,14 @@ export class RelationshipClasses extends ECClasses { try { await this.validate(constraint.relationshipClass); - } catch(e: any){ + } catch (e: any) { mutableConstraint.removeClass(ecClass); throw new SchemaEditingError(ECEditingStatus.AddConstraintClass, new RelationshipConstraintId(constraint), e); } try { await this.validate(constraint); - } catch(e: any){ + } catch (e: any) { mutableConstraint.removeClass(ecClass); throw new SchemaEditingError(ECEditingStatus.AddConstraintClass, new RelationshipConstraintId(constraint), e); } @@ -207,9 +260,9 @@ export class RelationshipClasses extends ECClasses { const mutableConstraint = constraint as MutableRelationshipConstraint; mutableConstraint.removeClass(ecClass); - try{ + try { await this.validate(constraint); - } catch(e: any) { + } catch (e: any) { mutableConstraint.addClass(ecClass); throw new SchemaEditingError(ECEditingStatus.RemoveConstraintClass, new RelationshipConstraintId(constraint), e); } @@ -228,8 +281,11 @@ export class RelationshipClasses extends ECClasses { if (diagnostics.length > 0) { this.removeCustomAttribute(constraint, customAttribute); - throw new SchemaEditingError(ECEditingStatus.AddCustomAttributeToConstraint, new RelationshipConstraintId(constraint), - new SchemaEditingError(ECEditingStatus.RuleViolation, new CustomAttributeId(customAttribute.className, constraint), undefined, diagnostics)); + throw new SchemaEditingError( + ECEditingStatus.AddCustomAttributeToConstraint, + new RelationshipConstraintId(constraint), + new SchemaEditingError(ECEditingStatus.RuleViolation, new CustomAttributeId(customAttribute.className, constraint), undefined, diagnostics), + ); } } @@ -252,7 +308,12 @@ export class RelationshipClasses extends ECClasses { if (diagnostics.length > 0) { if (relationshipOrConstraint instanceof RelationshipClass) { - throw new SchemaEditingError(ECEditingStatus.RuleViolation, new ClassId(SchemaItemType.RelationshipClass, relationshipKey), undefined, diagnostics); + throw new SchemaEditingError( + ECEditingStatus.RuleViolation, + new ClassId(SchemaItemType.RelationshipClass, relationshipKey), + undefined, + diagnostics, + ); } else { throw new SchemaEditingError(ECEditingStatus.RuleViolation, new RelationshipConstraintId(relationshipOrConstraint), undefined, diagnostics); } diff --git a/core/ecschema-editing/src/Editing/SchemaItems.ts b/core/ecschema-editing/src/Editing/SchemaItems.ts index 52b0e70a2d4b..89610a824db7 100644 --- a/core/ecschema-editing/src/Editing/SchemaItems.ts +++ b/core/ecschema-editing/src/Editing/SchemaItems.ts @@ -50,10 +50,13 @@ export abstract class SchemaItems { await schema.deleteSchemaItem(existingName); schema.addItem(mutableItem); return mutableItem.key; - } catch(e: any) { + } catch (e: any) { if (e instanceof ECObjectsError && e.errorNumber === ECObjectsStatus.InvalidECName) { - throw new SchemaEditingError(ECEditingStatus.SetClassName, new SchemaItemId(this.schemaItemType, itemKey), - new SchemaEditingError(ECEditingStatus.InvalidECName, new SchemaItemId(this.schemaItemType, itemKey))); + throw new SchemaEditingError( + ECEditingStatus.SetClassName, + new SchemaItemId(this.schemaItemType, itemKey), + new SchemaEditingError(ECEditingStatus.InvalidECName, new SchemaItemId(this.schemaItemType, itemKey)), + ); } throw new SchemaEditingError(ECEditingStatus.SetClassName, new SchemaItemId(this.schemaItemType, itemKey), e); @@ -94,17 +97,27 @@ export abstract class SchemaItems { return schema; } - protected async getSchemaItem(schemaItemKey: SchemaItemKey, schemaItemType?: SchemaItemType): Promise{ + protected async getSchemaItem(schemaItemKey: SchemaItemKey, schemaItemType?: SchemaItemType): Promise { schemaItemType = schemaItemType ?? this.schemaItemType; return this.schemaEditor.getSchemaItem(schemaItemKey, schemaItemType); } - protected async lookupSchemaItem(schemaOrKey: MutableSchema | SchemaKey, schemaItemKey: SchemaItemKey, schemaItemType?: SchemaItemType): Promise{ + protected async lookupSchemaItem( + schemaOrKey: MutableSchema | SchemaKey, + schemaItemKey: SchemaItemKey, + schemaItemType?: SchemaItemType, + ): Promise { schemaItemType = schemaItemType ?? this.schemaItemType; return this.schemaEditor.lookupSchemaItem(schemaOrKey, schemaItemKey, schemaItemType); } - protected async createSchemaItem(schemaKey: SchemaKey, type: SchemaItemType, create: CreateSchemaItem, name: string, ...args: any[]): Promise { + protected async createSchemaItem( + schemaKey: SchemaKey, + type: SchemaItemType, + create: CreateSchemaItem, + name: string, + ...args: any[] + ): Promise { const schema = await this.getSchema(schemaKey); try { const boundCreate = create(schema); @@ -118,7 +131,12 @@ export abstract class SchemaItems { } } - protected async createSchemaItemFromProps(schemaKey: SchemaKey, type: SchemaItemType, create: CreateSchemaItem, props: SchemaItemProps): Promise { + protected async createSchemaItemFromProps( + schemaKey: SchemaKey, + type: SchemaItemType, + create: CreateSchemaItem, + props: SchemaItemProps, + ): Promise { if (props.name === undefined) throw new SchemaEditingError(ECEditingStatus.SchemaItemNameNotSpecified, new SchemaItemId(type, "", schemaKey)); diff --git a/core/ecschema-editing/src/Editing/Structs.ts b/core/ecschema-editing/src/Editing/Structs.ts index 8bbd79e62c38..15e57db61949 100644 --- a/core/ecschema-editing/src/Editing/Structs.ts +++ b/core/ecschema-editing/src/Editing/Structs.ts @@ -7,10 +7,10 @@ */ import { SchemaItemKey, SchemaItemType, SchemaKey, StructClass, StructClassProps } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "./Editor"; import { ECClasses } from "./ECClasses"; -import { MutableStructClass } from "./Mutable/MutableClass"; +import { SchemaContextEditor } from "./Editor"; import { ClassId, ECEditingStatus, SchemaEditingError } from "./Exception"; +import { MutableStructClass } from "./Mutable/MutableClass"; /** * @alpha A class extending ECClasses allowing you to create schema items of type StructClass. @@ -22,7 +22,13 @@ export class Structs extends ECClasses { public async create(schemaKey: SchemaKey, name: string, displayLabel?: string, baseClassKey?: SchemaItemKey): Promise { try { - const newClass = await this.createClass(schemaKey, this.schemaItemType, (schema) => schema.createStructClass.bind(schema), name, baseClassKey) as MutableStructClass; + const newClass = await this.createClass( + schemaKey, + this.schemaItemType, + (schema) => schema.createStructClass.bind(schema), + name, + baseClassKey, + ) as MutableStructClass; if (displayLabel) newClass.setDisplayLabel(displayLabel); @@ -40,7 +46,12 @@ export class Structs extends ECClasses { */ public async createFromProps(schemaKey: SchemaKey, structProps: StructClassProps): Promise { try { - const newClass = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createStructClass.bind(schema), structProps); + const newClass = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createStructClass.bind(schema), + structProps, + ); return newClass.key; } catch (e: any) { throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new ClassId(this.schemaItemType, structProps.name!, schemaKey), e); diff --git a/core/ecschema-editing/src/Editing/UnitSystems.ts b/core/ecschema-editing/src/Editing/UnitSystems.ts index 03630e1f76ef..3561b78a9b59 100644 --- a/core/ecschema-editing/src/Editing/UnitSystems.ts +++ b/core/ecschema-editing/src/Editing/UnitSystems.ts @@ -8,8 +8,8 @@ import { SchemaItemKey, SchemaItemType, SchemaKey, UnitSystem, UnitSystemProps } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableUnitSystem } from "./Mutable/MutableUnitSystem"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableUnitSystem } from "./Mutable/MutableUnitSystem"; import { SchemaItems } from "./SchemaItems"; /** @@ -22,9 +22,13 @@ export class UnitSystems extends SchemaItems { } public async create(schemaKey: SchemaKey, name: string, displayLabel?: string): Promise { - try { - const newUnitSystem = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createUnitSystem.bind(schema), name) as MutableUnitSystem; + const newUnitSystem = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createUnitSystem.bind(schema), + name, + ) as MutableUnitSystem; if (displayLabel) newUnitSystem.setDisplayLabel(displayLabel); @@ -37,10 +41,19 @@ export class UnitSystems extends SchemaItems { public async createFromProps(schemaKey: SchemaKey, unitSystemProps: UnitSystemProps): Promise { try { - const newUnitSystem = await this.createSchemaItemFromProps(schemaKey, this.schemaItemType, (schema) => schema.createUnitSystem.bind(schema), unitSystemProps); + const newUnitSystem = await this.createSchemaItemFromProps( + schemaKey, + this.schemaItemType, + (schema) => schema.createUnitSystem.bind(schema), + unitSystemProps, + ); return newUnitSystem.key; } catch (e: any) { - throw new SchemaEditingError(ECEditingStatus.CreateSchemaItemFromProps, new SchemaItemId(this.schemaItemType, unitSystemProps.name!, schemaKey), e); + throw new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFromProps, + new SchemaItemId(this.schemaItemType, unitSystemProps.name!, schemaKey), + e, + ); } } } diff --git a/core/ecschema-editing/src/Editing/Units.ts b/core/ecschema-editing/src/Editing/Units.ts index f55fd4c348ef..6a1026e4bead 100644 --- a/core/ecschema-editing/src/Editing/Units.ts +++ b/core/ecschema-editing/src/Editing/Units.ts @@ -6,10 +6,19 @@ * @module Editing */ -import { DelayedPromiseWithProps, Phenomenon, SchemaItemKey, SchemaItemType, SchemaItemUnitProps, SchemaKey, Unit, UnitSystem } from "@itwin/ecschema-metadata"; +import { + DelayedPromiseWithProps, + Phenomenon, + SchemaItemKey, + SchemaItemType, + SchemaItemUnitProps, + SchemaKey, + Unit, + UnitSystem, +} from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "./Editor"; -import { MutableUnit } from "./Mutable/MutableUnit"; import { ECEditingStatus, SchemaEditingError, SchemaItemId } from "./Exception"; +import { MutableUnit } from "./Mutable/MutableUnit"; import { SchemaItems } from "./SchemaItems"; /** @@ -22,9 +31,21 @@ export class Units extends SchemaItems { super(SchemaItemType.Unit, schemaEditor); } - public async create(schemaKey: SchemaKey, name: string, definition: string, phenomenon: SchemaItemKey, unitSystem: SchemaItemKey, displayLabel?: string): Promise { + public async create( + schemaKey: SchemaKey, + name: string, + definition: string, + phenomenon: SchemaItemKey, + unitSystem: SchemaItemKey, + displayLabel?: string, + ): Promise { try { - const newUnit = await this.createSchemaItem(schemaKey, this.schemaItemType, (schema) => schema.createUnit.bind(schema), name) as MutableUnit; + const newUnit = await this.createSchemaItem( + schemaKey, + this.schemaItemType, + (schema) => schema.createUnit.bind(schema), + name, + ) as MutableUnit; const phenomenonItem = await this.lookupSchemaItem(newUnit.schema.schemaKey, phenomenon, SchemaItemType.Phenomenon); await newUnit.setPhenomenon(new DelayedPromiseWithProps(phenomenon, async () => phenomenonItem)); diff --git a/core/ecschema-editing/src/Merging/ClassMerger.ts b/core/ecschema-editing/src/Merging/ClassMerger.ts index d3a23a280d74..e3d777e0f8e3 100644 --- a/core/ecschema-editing/src/Merging/ClassMerger.ts +++ b/core/ecschema-editing/src/Merging/ClassMerger.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { type SchemaMergeContext } from "./SchemaMerger"; +import { CustomAttribute, ECClass, ECClassModifier, parseClassModifier, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; import { AnyClassItemDifference } from "../Differencing/SchemaDifference"; -import { updateSchemaItemKey } from "./Utils"; import { type MutableClass } from "../Editing/Mutable/MutableClass"; -import { CustomAttribute, ECClass, ECClassModifier, parseClassModifier, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; -import { mergeClassProperties } from "./PropertyMerger"; import { applyCustomAttributes } from "./CustomAttributeMerger"; +import { mergeClassProperties } from "./PropertyMerger"; +import { type SchemaMergeContext } from "./SchemaMerger"; +import { updateSchemaItemKey } from "./Utils"; /** * Shared modify merger of all ECClass based items. @@ -28,7 +28,7 @@ export async function modifyClass(context: SchemaMergeContext, change: AnyClassI // If the entry difference have a property baseClass and it is explicitly set to undefined, // it is expected to remove the base class, which is not allowed in this case. // TODO: We should consider using null for this case. - if(change.difference.baseClass === undefined) { + if (change.difference.baseClass === undefined) { throw new Error(`Changing the class '${item.key.name}' baseClass is not supported.`); } await setBaseClass(context, item, change.difference.baseClass, change.changeType === "add"); @@ -72,11 +72,16 @@ async function setClassModifier(item: MutableClass, modifierValue: string): Prom function getBaseClassSetter(context: SchemaMergeContext, item: ECClass) { return async (itemKey: SchemaItemKey, baseClassKey: SchemaItemKey) => { switch (item.schemaItemType) { - case SchemaItemType.CustomAttributeClass: return context.editor.customAttributes.setBaseClass(itemKey, baseClassKey); - case SchemaItemType.EntityClass: return context.editor.entities.setBaseClass(itemKey, baseClassKey); - case SchemaItemType.Mixin: return context.editor.mixins.setBaseClass(itemKey, baseClassKey); - case SchemaItemType.RelationshipClass: return context.editor.relationships.setBaseClass(itemKey, baseClassKey); - case SchemaItemType.StructClass: return context.editor.structs.setBaseClass(itemKey, baseClassKey); + case SchemaItemType.CustomAttributeClass: + return context.editor.customAttributes.setBaseClass(itemKey, baseClassKey); + case SchemaItemType.EntityClass: + return context.editor.entities.setBaseClass(itemKey, baseClassKey); + case SchemaItemType.Mixin: + return context.editor.mixins.setBaseClass(itemKey, baseClassKey); + case SchemaItemType.RelationshipClass: + return context.editor.relationships.setBaseClass(itemKey, baseClassKey); + case SchemaItemType.StructClass: + return context.editor.structs.setBaseClass(itemKey, baseClassKey); } throw new Error(`Changing the base class '${item.name}' is not supported.`); }; diff --git a/core/ecschema-editing/src/Merging/ConstantMerger.ts b/core/ecschema-editing/src/Merging/ConstantMerger.ts index 1b4a54542caf..610748bfee42 100644 --- a/core/ecschema-editing/src/Merging/ConstantMerger.ts +++ b/core/ecschema-editing/src/Merging/ConstantMerger.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { DelayedPromiseWithProps, ECObjectsError, ECObjectsStatus, Phenomenon, SchemaItemKey } from "@itwin/ecschema-metadata"; import type { ConstantDifference } from "../Differencing/SchemaDifference"; -import type{ MutableConstant } from "../Editing/Mutable/MutableConstant"; +import type { MutableConstant } from "../Editing/Mutable/MutableConstant"; import type { SchemaMergeContext } from "./SchemaMerger"; -import { DelayedPromiseWithProps, ECObjectsError, ECObjectsStatus, Phenomenon, SchemaItemKey } from "@itwin/ecschema-metadata"; import { updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; /** diff --git a/core/ecschema-editing/src/Merging/CustomAttributeClassMerger.ts b/core/ecschema-editing/src/Merging/CustomAttributeClassMerger.ts index c6a3e493e4ed..49f1a2a499fc 100644 --- a/core/ecschema-editing/src/Merging/CustomAttributeClassMerger.ts +++ b/core/ecschema-editing/src/Merging/CustomAttributeClassMerger.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { containerTypeToString, parseCustomAttributeContainerType, SchemaItemKey } from "@itwin/ecschema-metadata"; import type { CustomAttributeClassDifference } from "../Differencing/SchemaDifference"; import type { MutableCAClass } from "../Editing/Mutable/MutableCAClass"; -import type { SchemaMergeContext } from "./SchemaMerger"; -import { containerTypeToString, parseCustomAttributeContainerType, SchemaItemKey } from "@itwin/ecschema-metadata"; import { modifyClass } from "./ClassMerger"; +import type { SchemaMergeContext } from "./SchemaMerger"; /** * Merges a new CustomAttribute into the target schema. diff --git a/core/ecschema-editing/src/Merging/CustomAttributeMerger.ts b/core/ecschema-editing/src/Merging/CustomAttributeMerger.ts index df0143f9721d..f67486572154 100644 --- a/core/ecschema-editing/src/Merging/CustomAttributeMerger.ts +++ b/core/ecschema-editing/src/Merging/CustomAttributeMerger.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { CustomAttribute, CustomAttributeClass, RelationshipClass, SchemaItemKey } from "@itwin/ecschema-metadata"; -import { type SchemaMergeContext } from "./SchemaMerger"; import { type CustomAttributeDifference } from "../Differencing/SchemaDifference"; +import { type SchemaMergeContext } from "./SchemaMerger"; import { getClassEditor, updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; type CustomAttributeSetter = (customAttribute: CustomAttribute) => Promise; @@ -60,7 +60,11 @@ export async function addCustomAttribute(context: SchemaMergeContext, change: Cu /** * @internal */ -export async function applyCustomAttributes(context: SchemaMergeContext, customAttributes: CustomAttribute[], handler: CustomAttributeSetter): Promise { +export async function applyCustomAttributes( + context: SchemaMergeContext, + customAttributes: CustomAttribute[], + handler: CustomAttributeSetter, +): Promise { for (const customAttribute of customAttributes) { await applyCustomAttribute(context, customAttribute, handler); } @@ -69,7 +73,11 @@ export async function applyCustomAttributes(context: SchemaMergeContext, customA /** * @internal */ -export async function applyCustomAttribute(context: SchemaMergeContext, customAttribute: CustomAttribute, handler: CustomAttributeSetter): Promise { +export async function applyCustomAttribute( + context: SchemaMergeContext, + customAttribute: CustomAttribute, + handler: CustomAttributeSetter, +): Promise { customAttribute.className = await updateSchemaItemFullName(context, customAttribute.className); return handler(customAttribute); } diff --git a/core/ecschema-editing/src/Merging/Edits/RenameEditHandler.ts b/core/ecschema-editing/src/Merging/Edits/RenameEditHandler.ts index fc87f82e0830..95d6e024909f 100644 --- a/core/ecschema-editing/src/Merging/Edits/RenameEditHandler.ts +++ b/core/ecschema-editing/src/Merging/Edits/RenameEditHandler.ts @@ -6,10 +6,30 @@ * @module Merging */ -import type { RenamePropertyEdit, RenameSchemaItemEdit } from "./SchemaEdits"; -import { AnyClassItemDifference, AnySchemaItemDifference, ClassPropertyDifference, RelationshipClassDifference, RelationshipConstraintClassDifference, SchemaDifferenceResult, SchemaOtherTypes, SchemaType } from "../../Differencing/SchemaDifference"; -import { NavigationPropertyProps, PrimitiveArrayPropertyProps, PrimitivePropertyProps, RelationshipConstraintProps, SchemaItem, SchemaItemKey, SchemaItemType, SchemaKey, StructArrayPropertyProps, StructPropertyProps } from "@itwin/ecschema-metadata"; +import { + NavigationPropertyProps, + PrimitiveArrayPropertyProps, + PrimitivePropertyProps, + RelationshipConstraintProps, + SchemaItem, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StructArrayPropertyProps, + StructPropertyProps, +} from "@itwin/ecschema-metadata"; +import { + AnyClassItemDifference, + AnySchemaItemDifference, + ClassPropertyDifference, + RelationshipClassDifference, + RelationshipConstraintClassDifference, + SchemaDifferenceResult, + SchemaOtherTypes, + SchemaType, +} from "../../Differencing/SchemaDifference"; import * as Utils from "../../Differencing/Utils"; +import type { RenamePropertyEdit, RenameSchemaItemEdit } from "./SchemaEdits"; type Editable = { -readonly [P in keyof T]: T[P]; @@ -133,7 +153,11 @@ function renameName(change: AnySchemaItemDifference, oldName: string, newName: s } } -function renameRelationshipConstraint(change: RelationshipClassDifference | RelationshipConstraintClassDifference, oldKey: SchemaItemKey, newKey: SchemaItemKey) { +function renameRelationshipConstraint( + change: RelationshipClassDifference | RelationshipConstraintClassDifference, + oldKey: SchemaItemKey, + newKey: SchemaItemKey, +) { if (change.schemaType === SchemaItemType.RelationshipClass) { const constraintProps = [change.difference.source, change.difference.target] as Editable[]; for (const props of constraintProps) { @@ -211,9 +235,11 @@ function renameEnumerationName({ differences }: SchemaDifferenceResult, oldKey: } } - if (change.schemaType === SchemaOtherTypes.Property && ( - change.difference.type === "PrimitiveProperty" || change.difference.type === "PrimitiveArrayProperty" - )) { + if ( + change.schemaType === SchemaOtherTypes.Property && ( + change.difference.type === "PrimitiveProperty" || change.difference.type === "PrimitiveArrayProperty" + ) + ) { const props = change.difference as Editable; if (props.typeName && oldKey.matchesFullName(props.typeName)) props.typeName = newKey.fullName; @@ -239,16 +265,18 @@ function renameStructClassName({ differences }: SchemaDifferenceResult, oldKey: if (Utils.isClassDifference(change) && change.difference.properties) { for (const property of change.difference.properties) { if (property.type === "StructProperty" || property.type === "StructArrayProperty") { - const props = property as Editable;; + const props = property as Editable; if (props.typeName && oldKey.matchesFullName(props.typeName)) props.typeName = newKey.fullName; } } } - if (change.schemaType === SchemaOtherTypes.Property && ( - change.difference.type === "StructProperty" || change.difference.type === "StructArrayProperty" - )) { + if ( + change.schemaType === SchemaOtherTypes.Property && ( + change.difference.type === "StructProperty" || change.difference.type === "StructArrayProperty" + ) + ) { const props = change.difference as Editable; if (props.typeName && oldKey.matchesFullName(props.typeName)) props.typeName = newKey.fullName; diff --git a/core/ecschema-editing/src/Merging/Edits/SchemaEdits.ts b/core/ecschema-editing/src/Merging/Edits/SchemaEdits.ts index 890f057c0b0c..9eff1ba290b6 100644 --- a/core/ecschema-editing/src/Merging/Edits/SchemaEdits.ts +++ b/core/ecschema-editing/src/Merging/Edits/SchemaEdits.ts @@ -54,9 +54,9 @@ export interface SkipEdit { * @alpha */ export type AnySchemaEdits = - SkipEdit | - RenameSchemaItemEdit | - RenamePropertyEdit; + | SkipEdit + | RenameSchemaItemEdit + | RenamePropertyEdit; abstract class Editor { private readonly _edits: Array; @@ -79,7 +79,6 @@ abstract class Editor { } class PropertyEditor extends Editor { - public rename(schemaName: string, className: string, propertyName: string, newName: string) { this.add({ type: SchemaEditType.RenameProperty, diff --git a/core/ecschema-editing/src/Merging/Edits/SkipEditHandler.ts b/core/ecschema-editing/src/Merging/Edits/SkipEditHandler.ts index 8fb2fde11553..2ddbd95d881a 100644 --- a/core/ecschema-editing/src/Merging/Edits/SkipEditHandler.ts +++ b/core/ecschema-editing/src/Merging/Edits/SkipEditHandler.ts @@ -68,4 +68,3 @@ function findRelatedItemEntries({ differences }: SchemaDifferenceResult, itemNam }); return found; } - diff --git a/core/ecschema-editing/src/Merging/EntityClassMerger.ts b/core/ecschema-editing/src/Merging/EntityClassMerger.ts index ada6ddcea8e9..932d0fe42654 100644 --- a/core/ecschema-editing/src/Merging/EntityClassMerger.ts +++ b/core/ecschema-editing/src/Merging/EntityClassMerger.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { EntityClassDifference, EntityClassMixinDifference } from "../Differencing/SchemaDifference"; import type { MutableEntityClass } from "../Editing/Mutable/MutableEntityClass"; -import type { SchemaMergeContext } from "./SchemaMerger"; -import { SchemaItemKey } from "@itwin/ecschema-metadata"; import { modifyClass } from "./ClassMerger"; +import type { SchemaMergeContext } from "./SchemaMerger"; import { updateSchemaItemKey } from "./Utils"; /** @@ -28,8 +28,8 @@ export async function addEntityClass(context: SchemaMergeContext, change: Entity */ export async function modifyEntityClass(context: SchemaMergeContext, change: EntityClassDifference, itemKey: SchemaItemKey) { const item = await context.targetSchema.lookupItem(itemKey) as MutableEntityClass; - if(change.difference.mixins !== undefined) { - for(const mixin of change.difference.mixins) { + if (change.difference.mixins !== undefined) { + for (const mixin of change.difference.mixins) { const mixinKey = await updateSchemaItemKey(context, mixin); await context.editor.entities.addMixin(itemKey, mixinKey); } @@ -43,7 +43,7 @@ export async function modifyEntityClass(context: SchemaMergeContext, change: Ent * @internal */ export async function addClassMixins(context: SchemaMergeContext, change: EntityClassMixinDifference): Promise { - for(const mixinFullName of change.difference) { + for (const mixinFullName of change.difference) { const mixinKey = await updateSchemaItemKey(context, mixinFullName); const entityKey = new SchemaItemKey(change.itemName, context.targetSchemaKey); await context.editor.entities.addMixin(entityKey, mixinKey); diff --git a/core/ecschema-editing/src/Merging/EnumerationMerger.ts b/core/ecschema-editing/src/Merging/EnumerationMerger.ts index a6921354a8af..9911b311023e 100644 --- a/core/ecschema-editing/src/Merging/EnumerationMerger.ts +++ b/core/ecschema-editing/src/Merging/EnumerationMerger.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { primitiveTypeToString, type SchemaItemKey } from "@itwin/ecschema-metadata"; import type { EnumerationDifference } from "../Differencing/SchemaDifference"; -import type { SchemaMergeContext } from "./SchemaMerger"; import type { MutableEnumeration } from "../Editing/Mutable/MutableEnumeration"; +import type { SchemaMergeContext } from "./SchemaMerger"; /** * Merges a new Enumeration into the target schema. @@ -38,16 +38,20 @@ export async function addEnumeration(context: SchemaMergeContext, change: Enumer */ export async function modifyEnumeration(context: SchemaMergeContext, change: EnumerationDifference, itemKey: SchemaItemKey) { const enumeration = await context.targetSchema.lookupItem(itemKey) as MutableEnumeration; - if(change.difference.type !== undefined) { - throw new Error(`The Enumeration ${itemKey.name} has an incompatible type. It must be "${primitiveTypeToString(enumeration.type!)}", not "${change.difference.type}".`); + if (change.difference.type !== undefined) { + throw new Error( + `The Enumeration ${itemKey.name} has an incompatible type. It must be "${ + primitiveTypeToString(enumeration.type!) + }", not "${change.difference.type}".`, + ); } - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.enumerations.setDisplayLabel(itemKey, change.difference.label); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.enumerations.setDescription(itemKey, change.difference.description); } - if(change.difference.isStrict !== undefined) { + if (change.difference.isStrict !== undefined) { enumeration.setIsStrict(change.difference.isStrict); } } diff --git a/core/ecschema-editing/src/Merging/EnumeratorMerger.ts b/core/ecschema-editing/src/Merging/EnumeratorMerger.ts index e8df30dbc35a..c9bab63f7d10 100644 --- a/core/ecschema-editing/src/Merging/EnumeratorMerger.ts +++ b/core/ecschema-editing/src/Merging/EnumeratorMerger.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { EnumeratorDifference } from "../Differencing/SchemaDifference"; import type { SchemaMergeContext } from "./SchemaMerger"; -import { SchemaItemKey } from "@itwin/ecschema-metadata"; /** * Merges a new Enumerator into the target schema. @@ -32,13 +32,13 @@ export async function addEnumerator(context: SchemaMergeContext, change: Enumera * @internal */ export async function modifyEnumerator(context: SchemaMergeContext, change: EnumeratorDifference, itemKey: SchemaItemKey) { - if(change.difference.value !== undefined) { + if (change.difference.value !== undefined) { throw new Error(`Failed to merge enumerator attribute, Enumerator "${change.path}" has different values.`); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.enumerations.setEnumeratorDescription(itemKey, change.path, change.difference.description); } - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.enumerations.setEnumeratorLabel(itemKey, change.path, change.difference.label); } } diff --git a/core/ecschema-editing/src/Merging/KindOfQuantityMerger.ts b/core/ecschema-editing/src/Merging/KindOfQuantityMerger.ts index c2b6e45f3550..63ceb02a0a77 100644 --- a/core/ecschema-editing/src/Merging/KindOfQuantityMerger.ts +++ b/core/ecschema-editing/src/Merging/KindOfQuantityMerger.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { KindOfQuantityDifference } from "../Differencing/SchemaDifference"; import type { MutableKindOfQuantity } from "../Editing/Mutable/MutableKindOfQuantity"; import type { SchemaMergeContext } from "./SchemaMerger"; -import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import { updateSchemaItemFullName } from "./Utils"; /** @@ -20,9 +20,9 @@ export async function addKindOfQuantity(context: SchemaMergeContext, change: Kin throw new Error("KindOfQuantity must define relativeError"); } change.difference.persistenceUnit = await updateSchemaItemFullName(context, change.difference.persistenceUnit); - if(change.difference.presentationUnits) { - if(Array.isArray(change.difference.presentationUnits)) { - for(let index = 0; index < change.difference.presentationUnits.length; index++) { + if (change.difference.presentationUnits) { + if (Array.isArray(change.difference.presentationUnits)) { + for (let index = 0; index < change.difference.presentationUnits.length; index++) { change.difference.presentationUnits[index] = await updateOverrideFormat(context, change.difference.presentationUnits[index]); } } else { @@ -46,16 +46,16 @@ export async function addKindOfQuantity(context: SchemaMergeContext, change: Kin */ export async function modifyKindOfQuantity(context: SchemaMergeContext, change: KindOfQuantityDifference, itemKey: SchemaItemKey) { const kindOfQuantity = await context.targetSchema.lookupItem(itemKey) as MutableKindOfQuantity; - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.kindOfQuantities.setDisplayLabel(itemKey, change.difference.label); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.kindOfQuantities.setDescription(itemKey, change.difference.description); } - if(change.difference.relativeError !== undefined) { + if (change.difference.relativeError !== undefined) { kindOfQuantity.setRelativeError(change.difference.relativeError); } - if(change.difference.persistenceUnit !== undefined) { + if (change.difference.persistenceUnit !== undefined) { // TODO: It should be checked if the unit is the same, but referring to the source schema. throw new Error(`Changing the kind of quantity '${itemKey.name}' persistenceUnit is not supported.`); } @@ -64,15 +64,15 @@ export async function modifyKindOfQuantity(context: SchemaMergeContext, change: async function updateOverrideFormat(context: SchemaMergeContext, formatString: string) { // https://www.itwinjs.org/v1/bis/ec/kindofquantity/#format-string const match = formatString.match(/^([^(]+)\((\d+)\)\[(.*)\]$/); - if(match === null) { + if (match === null) { return formatString; } const originalFormat = match[1]; const updatedFormat = await updateSchemaItemFullName(context, originalFormat); - const unitOverrides = match[3].split("]["); - for(let index=0; index< unitOverrides.length; index++) { + const unitOverrides = match[3].split("]["); + for (let index = 0; index < unitOverrides.length; index++) { const [unit, label] = unitOverrides[index].split("|"); const updatedUnit = await updateSchemaItemFullName(context, unit); unitOverrides[index] = `${updatedUnit}${label ? `|${label}` : ""}`; diff --git a/core/ecschema-editing/src/Merging/MixinMerger.ts b/core/ecschema-editing/src/Merging/MixinMerger.ts index 5695d9c0f431..5f0b238cec95 100644 --- a/core/ecschema-editing/src/Merging/MixinMerger.ts +++ b/core/ecschema-editing/src/Merging/MixinMerger.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { MixinClassDifference } from "../Differencing/SchemaDifference"; import type { MutableMixin } from "../Editing/Mutable/MutableMixin"; +import { modifyClass } from "./ClassMerger"; import type { SchemaMergeContext } from "./SchemaMerger"; -import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import { updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; -import { modifyClass } from "./ClassMerger"; /** * Merges a new Mixin into the target schema. @@ -31,7 +31,7 @@ export async function addMixinClass(context: SchemaMergeContext, change: MixinCl */ export async function modifyMixinClass(context: SchemaMergeContext, change: MixinClassDifference, itemKey: SchemaItemKey) { const mixin = await context.targetSchema.lookupItem(itemKey) as MutableMixin; - if(change.difference.appliesTo !== undefined) { + if (change.difference.appliesTo !== undefined) { const appliesTo = await updateSchemaItemKey(context, change.difference.appliesTo); const currentValue = await mixin.appliesTo; if (currentValue !== undefined && !appliesTo.matches(currentValue.key)) { diff --git a/core/ecschema-editing/src/Merging/PhenomenonMerger.ts b/core/ecschema-editing/src/Merging/PhenomenonMerger.ts index e7e19ef7d3c6..eb8b16f8c479 100644 --- a/core/ecschema-editing/src/Merging/PhenomenonMerger.ts +++ b/core/ecschema-editing/src/Merging/PhenomenonMerger.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECObjectsError, ECObjectsStatus, type SchemaItemKey } from "@itwin/ecschema-metadata"; import type { PhenomenonDifference } from "../Differencing/SchemaDifference"; import type { MutablePhenomenon } from "../Editing/Mutable/MutablePhenomenon"; import type { SchemaMergeContext } from "./SchemaMerger"; -import { ECObjectsError, ECObjectsStatus, type SchemaItemKey } from "@itwin/ecschema-metadata"; /** * Merges a new Phenomenon into the target schema. @@ -30,14 +30,14 @@ export async function addPhenomenon(context: SchemaMergeContext, change: Phenome */ export async function modifyPhenomenon(context: SchemaMergeContext, change: PhenomenonDifference, itemKey: SchemaItemKey) { const phenomenon = await context.targetSchema.lookupItem(itemKey) as MutablePhenomenon; - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.phenomenons.setDisplayLabel(itemKey, change.difference.label); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.phenomenons.setDescription(itemKey, change.difference.description); } - if(change.difference.definition !== undefined) { + if (change.difference.definition !== undefined) { // It would be better if the validation would be part of phenomenon.setDefinition. if (phenomenon.definition !== "" && change.difference.definition.toLowerCase() !== phenomenon.definition.toLowerCase()) throw new ECObjectsError(ECObjectsStatus.InvalidECJson, `The Phenomenon ${itemKey.name} has an invalid 'definition' attribute.`); diff --git a/core/ecschema-editing/src/Merging/PropertyCategoryMerger.ts b/core/ecschema-editing/src/Merging/PropertyCategoryMerger.ts index 66a1dfbc0239..f08849b1692c 100644 --- a/core/ecschema-editing/src/Merging/PropertyCategoryMerger.ts +++ b/core/ecschema-editing/src/Merging/PropertyCategoryMerger.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { PropertyCategoryDifference } from "../Differencing/SchemaDifference"; import type { SchemaMergeContext } from "./SchemaMerger"; -import type { SchemaItemKey } from "@itwin/ecschema-metadata"; /** * Merges a new PropertyCategory into the target schema. @@ -28,13 +28,13 @@ export async function addPropertyCategory(context: SchemaMergeContext, change: P * @internal */ export async function modifyPropertyCategory(context: SchemaMergeContext, change: PropertyCategoryDifference, itemKey: SchemaItemKey) { - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.propertyCategories.setDisplayLabel(itemKey, change.difference.label); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.propertyCategories.setDescription(itemKey, change.difference.description); } - if(change.difference.priority !== undefined) { + if (change.difference.priority !== undefined) { await context.editor.propertyCategories.setPriority(itemKey, change.difference.priority); } } diff --git a/core/ecschema-editing/src/Merging/PropertyMerger.ts b/core/ecschema-editing/src/Merging/PropertyMerger.ts index 3572737fb22e..61a1b2e56632 100644 --- a/core/ecschema-editing/src/Merging/PropertyMerger.ts +++ b/core/ecschema-editing/src/Merging/PropertyMerger.ts @@ -2,12 +2,28 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { SchemaMergeContext } from "./SchemaMerger"; +import { + AnyProperty, + AnyPropertyProps, + ArrayPropertyProps, + CustomAttribute, + ECClass, + Enumeration, + EnumerationPropertyProps, + NavigationPropertyProps, + parsePrimitiveType, + PrimitivePropertyProps, + RelationshipClass, + SchemaItemKey, + SchemaItemType, + StructClass, + StructPropertyProps, +} from "@itwin/ecschema-metadata"; import type { AnyClassItemDifference, ClassPropertyDifference, DifferenceType } from "../Differencing/SchemaDifference"; -import { AnyProperty, AnyPropertyProps, ArrayPropertyProps, CustomAttribute, ECClass, Enumeration, EnumerationPropertyProps, NavigationPropertyProps, parsePrimitiveType, PrimitivePropertyProps, RelationshipClass, SchemaItemKey, SchemaItemType, StructClass, StructPropertyProps } from "@itwin/ecschema-metadata"; -import { getClassEditor, updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; import { MutableProperty } from "../Editing/Mutable/MutableProperty"; import { applyCustomAttributes } from "./CustomAttributeMerger"; +import type { SchemaMergeContext } from "./SchemaMerger"; +import { getClassEditor, updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; type PartialEditable = { -readonly [P in keyof T]: T[P]; @@ -39,7 +55,12 @@ export async function mergeClassProperties(context: SchemaMergeContext, change: } } -async function mergeClassProperty(context: SchemaMergeContext, change: { changeType: DifferenceType }, itemKey: SchemaItemKey, property: AnyPropertyProps) { +async function mergeClassProperty( + context: SchemaMergeContext, + change: { changeType: DifferenceType }, + itemKey: SchemaItemKey, + property: AnyPropertyProps, +) { return change.changeType === "add" ? addClassProperty(context, itemKey, property) : modifyClassProperty(context, itemKey, property); diff --git a/core/ecschema-editing/src/Merging/RelationshipClassMerger.ts b/core/ecschema-editing/src/Merging/RelationshipClassMerger.ts index 7ad27c8b6b60..39172887ae1a 100644 --- a/core/ecschema-editing/src/Merging/RelationshipClassMerger.ts +++ b/core/ecschema-editing/src/Merging/RelationshipClassMerger.ts @@ -2,12 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { RelationshipClassDifference, RelationshipConstraintClassDifference, RelationshipConstraintDifference } from "../Differencing/SchemaDifference"; +import { + EntityClass, + Mixin, + parseStrength, + parseStrengthDirection, + RelationshipClass, + RelationshipConstraintProps, + RelationshipMultiplicity, + SchemaItemKey, + SchemaItemType, +} from "@itwin/ecschema-metadata"; +import type { + RelationshipClassDifference, + RelationshipConstraintClassDifference, + RelationshipConstraintDifference, +} from "../Differencing/SchemaDifference"; import type { MutableRelationshipClass } from "../Editing/Mutable/MutableRelationshipClass"; -import { locateSchemaItem, updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; import { modifyClass } from "./ClassMerger"; import { SchemaMergeContext } from "./SchemaMerger"; -import { EntityClass, Mixin, parseStrength, parseStrengthDirection, RelationshipClass, RelationshipConstraintProps, RelationshipMultiplicity, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; +import { locateSchemaItem, updateSchemaItemFullName, updateSchemaItemKey } from "./Utils"; type ConstraintClassTypes = EntityClass | Mixin | RelationshipClass; @@ -46,8 +60,8 @@ export async function addRelationshipClass(context: SchemaMergeContext, change: */ export async function modifyRelationshipClass(context: SchemaMergeContext, change: RelationshipClassDifference, itemKey: SchemaItemKey) { const item = await context.targetSchema.lookupItem(itemKey) as MutableRelationshipClass; - if(change.changeType === "modify") { - if(change.difference.strength !== undefined) { + if (change.changeType === "modify") { + if (change.difference.strength !== undefined) { if (item.strength === undefined) { const strength = parseStrength(change.difference.strength); if (strength === undefined) { @@ -57,7 +71,7 @@ export async function modifyRelationshipClass(context: SchemaMergeContext, chang } throw new Error(`Changing the relationship '${itemKey.name}' strength is not supported.`); } - if(change.difference.strengthDirection !== undefined) { + if (change.difference.strengthDirection !== undefined) { if (item.strengthDirection === undefined) { const strengthDirection = parseStrengthDirection(change.difference.strengthDirection); if (strengthDirection === undefined) { @@ -77,19 +91,19 @@ export async function modifyRelationshipClass(context: SchemaMergeContext, chang * @internal */ export async function mergeRelationshipConstraint(context: SchemaMergeContext, change: RelationshipConstraintDifference) { - if(change.changeType !== "modify") { + if (change.changeType !== "modify") { throw new Error("RelationshipConstraints can only be modified."); } const item = await locateSchemaItem(context, change.itemName, SchemaItemType.RelationshipClass) as MutableRelationshipClass; const constraint = item[parseConstraint(change.path)]; - if(change.difference.roleLabel !== undefined) { + if (change.difference.roleLabel !== undefined) { constraint.roleLabel = change.difference.roleLabel; } - if(change.difference.polymorphic !== undefined) { + if (change.difference.polymorphic !== undefined) { await context.editor.relationships.setConstraintPolymorphic(constraint, change.difference.polymorphic); } - if(change.difference.multiplicity !== undefined) { + if (change.difference.multiplicity !== undefined) { if (constraint.multiplicity === undefined) { const multiplicity = RelationshipMultiplicity.fromString(change.difference.multiplicity); if (multiplicity === undefined) { @@ -99,7 +113,7 @@ export async function mergeRelationshipConstraint(context: SchemaMergeContext, c } throw new Error(`Changing the relationship constraint '${constraint.fullName}' multiplicity is not supported.`); } - if(change.difference.abstractConstraint !== undefined) { + if (change.difference.abstractConstraint !== undefined) { const itemKey = await updateSchemaItemKey(context, change.difference.abstractConstraint); const abstractConstraint = await context.editor.schemaContext.getSchemaItem(itemKey); if (abstractConstraint === undefined) { @@ -115,16 +129,16 @@ export async function mergeRelationshipConstraint(context: SchemaMergeContext, c * @internal */ export async function mergeRelationshipClassConstraint(context: SchemaMergeContext, change: RelationshipConstraintClassDifference): Promise { - if(change.changeType !== "add") { + if (change.changeType !== "add") { throw new Error(`Change type ${change.changeType} is not supported for Relationship constraint classes.`); } const item = await locateSchemaItem(context, change.itemName, SchemaItemType.RelationshipClass) as MutableRelationshipClass; const constraint = item[parseConstraint(change.path)]; - for(const constraintName of change.difference) { + for (const constraintName of change.difference) { const constraintClassKey = await updateSchemaItemKey(context, constraintName); const constraintClass = await context.editor.schemaContext.getSchemaItem(constraintClassKey); - if(constraintClass === undefined) { + if (constraintClass === undefined) { throw new Error(`Could not locate relationship constraint class ${constraintClassKey.name}`); } @@ -138,7 +152,10 @@ function parseConstraint(path: string): "source" | "target" { : "target"; } -async function updateRelationshipConstraintKey(context: SchemaMergeContext, props: RelationshipConstraintProps): Promise { +async function updateRelationshipConstraintKey( + context: SchemaMergeContext, + props: RelationshipConstraintProps, +): Promise { let abstractConstraint = props.abstractConstraint; if (abstractConstraint !== undefined) abstractConstraint = await updateSchemaItemFullName(context, abstractConstraint); diff --git a/core/ecschema-editing/src/Merging/SchemaMerger.ts b/core/ecschema-editing/src/Merging/SchemaMerger.ts index cdc6c5b712a1..bd053a8570b6 100644 --- a/core/ecschema-editing/src/Merging/SchemaMerger.ts +++ b/core/ecschema-editing/src/Merging/SchemaMerger.ts @@ -7,13 +7,13 @@ */ import { Schema, type SchemaContext, SchemaKey } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "../Editing/Editor"; import { SchemaConflictsError } from "../Differencing/Errors"; import { getSchemaDifferences, type SchemaDifferenceResult } from "../Differencing/SchemaDifference"; +import { SchemaContextEditor } from "../Editing/Editor"; +import { ECEditingStatus, SchemaEditingError } from "../Editing/Exception"; +import type { SchemaEdits } from "./Edits/SchemaEdits"; import { SchemaMergingVisitor } from "./SchemaMergingVisitor"; import { SchemaMergingWalker } from "./SchemaMergingWalker"; -import type { SchemaEdits } from "./Edits/SchemaEdits"; -import { ECEditingStatus, SchemaEditingError } from "../Editing/Exception"; /** * Defines the context of a Schema merging run. @@ -32,7 +32,6 @@ export interface SchemaMergeContext { * @beta */ export class SchemaMerger { - private readonly _editor: SchemaContextEditor; /** diff --git a/core/ecschema-editing/src/Merging/SchemaMergingVisitor.ts b/core/ecschema-editing/src/Merging/SchemaMergingVisitor.ts index 82a172d8bb68..22ffdfa58f94 100644 --- a/core/ecschema-editing/src/Merging/SchemaMergingVisitor.ts +++ b/core/ecschema-editing/src/Merging/SchemaMergingVisitor.ts @@ -2,10 +2,39 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { AnyClassItemDifference, AnySchemaDifference, AnySchemaItemDifference, ClassPropertyDifference, ConstantDifference, CustomAttributeClassDifference, CustomAttributeDifference, EntityClassDifference, EntityClassMixinDifference, EnumerationDifference, EnumeratorDifference, FormatDifference, InvertedUnitDifference, KindOfQuantityDifference, MixinClassDifference, PhenomenonDifference, PropertyCategoryDifference, RelationshipClassDifference, RelationshipConstraintClassDifference, RelationshipConstraintDifference, SchemaDifference, SchemaReferenceDifference, StructClassDifference, UnitDifference, UnitSystemDifference } from "../Differencing/SchemaDifference"; +import { SchemaItemKey } from "@itwin/ecschema-metadata"; +import { + AnyClassItemDifference, + AnySchemaDifference, + AnySchemaItemDifference, + ClassPropertyDifference, + ConstantDifference, + CustomAttributeClassDifference, + CustomAttributeDifference, + EntityClassDifference, + EntityClassMixinDifference, + EnumerationDifference, + EnumeratorDifference, + FormatDifference, + InvertedUnitDifference, + KindOfQuantityDifference, + MixinClassDifference, + PhenomenonDifference, + PropertyCategoryDifference, + RelationshipClassDifference, + RelationshipConstraintClassDifference, + RelationshipConstraintDifference, + SchemaDifference, + SchemaReferenceDifference, + StructClassDifference, + UnitDifference, + UnitSystemDifference, +} from "../Differencing/SchemaDifference"; +import { SchemaDifferenceVisitor } from "../Differencing/SchemaDifferenceVisitor"; +import { isClassDifference } from "../Differencing/Utils"; import { addConstant, modifyConstant } from "./ConstantMerger"; -import { addCustomAttribute } from "./CustomAttributeMerger"; import { addCustomAttributeClass, modifyCustomAttributeClass } from "./CustomAttributeClassMerger"; +import { addCustomAttribute } from "./CustomAttributeMerger"; import { addClassMixins, addEntityClass, modifyEntityClass } from "./EntityClassMerger"; import { addEnumeration, modifyEnumeration } from "./EnumerationMerger"; import { addEnumerator, modifyEnumerator } from "./EnumeratorMerger"; @@ -13,15 +42,17 @@ import { addKindOfQuantity, modifyKindOfQuantity } from "./KindOfQuantityMerger" import { addMixinClass, modifyMixinClass } from "./MixinMerger"; import { addPhenomenon, modifyPhenomenon } from "./PhenomenonMerger"; import { addPropertyCategory, modifyPropertyCategory } from "./PropertyCategoryMerger"; -import { addRelationshipClass, mergeRelationshipClassConstraint, mergeRelationshipConstraint, modifyRelationshipClass } from "./RelationshipClassMerger"; +import { mergePropertyDifference } from "./PropertyMerger"; +import { + addRelationshipClass, + mergeRelationshipClassConstraint, + mergeRelationshipConstraint, + modifyRelationshipClass, +} from "./RelationshipClassMerger"; +import { SchemaMergeContext } from "./SchemaMerger"; import { addSchemaReferences, modifySchemaReferences } from "./SchemaReferenceMerger"; import { addStructClass, modifyStructClass } from "./StructClassMerger"; import { addUnitSystem, modifyUnitSystem } from "./UnitSystemMerger"; -import { mergePropertyDifference } from "./PropertyMerger"; -import { isClassDifference } from "../Differencing/Utils"; -import { SchemaDifferenceVisitor } from "../Differencing/SchemaDifferenceVisitor"; -import { SchemaItemKey } from "@itwin/ecschema-metadata"; -import { SchemaMergeContext } from "./SchemaMerger"; /** Definition of schema items change type handler array. */ interface ItemChangeTypeHandler { @@ -35,7 +66,6 @@ interface ItemChangeTypeHandler { * @internal */ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { - private readonly _context: SchemaMergeContext; /** @@ -55,13 +85,18 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { /** * Shared merging logic for all types of ClassItemDifference union. */ - private async visitClassDifference(entry: T, index: number, array: AnySchemaDifference[], handler: ItemChangeTypeHandler) { + private async visitClassDifference( + entry: T, + index: number, + array: AnySchemaDifference[], + handler: ItemChangeTypeHandler, + ) { return this.visitSchemaItemDifference(entry, { add: async (context) => { // To add classes a slightly different approach is done. In fact the class entries gets processed // two times. The first time, a stub with the bare minimum is added to the schema. The second time, // the class gets completed with all properties, mixins, etc... - if(entry.changeType === "add" && !await context.targetSchema.getItem(entry.itemName)) { + if (entry.changeType === "add" && !await context.targetSchema.getItem(entry.itemName)) { await handler.add(this._context, { ...entry, difference: { @@ -105,7 +140,11 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * Visitor implementation for handling CustomAttributeClassDifference. * @internal */ - public async visitCustomAttributeClassDifference(entry: CustomAttributeClassDifference, index: number, array: AnySchemaDifference[]): Promise { + public async visitCustomAttributeClassDifference( + entry: CustomAttributeClassDifference, + index: number, + array: AnySchemaDifference[], + ): Promise { return this.visitClassDifference(entry, index, array, { add: addCustomAttributeClass, modify: modifyCustomAttributeClass, @@ -117,8 +156,9 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * @internal */ public async visitCustomAttributeInstanceDifference(entry: CustomAttributeDifference): Promise { - switch(entry.changeType) { - case "add": return addCustomAttribute(this._context, entry); + switch (entry.changeType) { + case "add": + return addCustomAttribute(this._context, entry); } } @@ -138,8 +178,9 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * @internal */ public async visitEntityClassMixinDifference(entry: EntityClassMixinDifference): Promise { - switch(entry.changeType) { - case "add": return addClassMixins(this._context, entry); + switch (entry.changeType) { + case "add": + return addClassMixins(this._context, entry); } } @@ -159,9 +200,11 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * @internal */ public async visitEnumeratorDifference(entry: EnumeratorDifference): Promise { - switch(entry.changeType) { - case "add": return addEnumerator(this._context, entry); - case "modify": return modifyEnumerator(this._context, entry, this.toItemKey(entry.itemName)); + switch (entry.changeType) { + case "add": + return addEnumerator(this._context, entry); + case "modify": + return modifyEnumerator(this._context, entry, this.toItemKey(entry.itemName)); } } @@ -277,17 +320,17 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * Shared merging logic for all types of AnySchemaItemDifference union. */ private async visitSchemaItemDifference(entry: T, handler: ItemChangeTypeHandler) { - switch(entry.changeType) { + switch (entry.changeType) { case "add": { return handler.add(this._context, entry); } case "modify": { - if("schemaItemType" in entry.difference && entry.difference.schemaItemType !== entry.schemaType) { + if ("schemaItemType" in entry.difference && entry.difference.schemaItemType !== entry.schemaType) { throw new Error(`Changing the type of item '${entry.itemName}' not supported.`); } return handler.modify(this._context, entry, this.toItemKey(entry.itemName)); - }; + } } } @@ -296,9 +339,11 @@ export class SchemaMergingVisitor implements SchemaDifferenceVisitor { * @internal */ public async visitSchemaReferenceDifference(entry: SchemaReferenceDifference): Promise { - switch(entry.changeType) { - case "add": return addSchemaReferences(this._context, entry); - case "modify": return modifySchemaReferences(this._context, entry); + switch (entry.changeType) { + case "add": + return addSchemaReferences(this._context, entry); + case "modify": + return modifySchemaReferences(this._context, entry); } } diff --git a/core/ecschema-editing/src/Merging/SchemaMergingWalker.ts b/core/ecschema-editing/src/Merging/SchemaMergingWalker.ts index aabd4e511728..3ab9a186578f 100644 --- a/core/ecschema-editing/src/Merging/SchemaMergingWalker.ts +++ b/core/ecschema-editing/src/Merging/SchemaMergingWalker.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaDifferenceWalker } from "../Differencing/SchemaDifferenceVisitor"; import { AnySchemaDifference, DifferenceType, SchemaOtherTypes, SchemaType } from "../Differencing/SchemaDifference"; +import { SchemaDifferenceWalker } from "../Differencing/SchemaDifferenceVisitor"; /** * A walker that traverses the schema differences in a certain oder and invokes the appropriate @@ -12,7 +12,6 @@ import { AnySchemaDifference, DifferenceType, SchemaOtherTypes, SchemaType } fro * @internal */ export class SchemaMergingWalker extends SchemaDifferenceWalker { - /** * Traverses the schema differences and calls the appropriate method on the visitor. * This method overrides the derived class method to apply some ordering how the @@ -22,7 +21,6 @@ export class SchemaMergingWalker extends SchemaDifferenceWalker { * @param changeType Optional type of change to filter by. */ public override async traverse(differences: Array, changeType?: DifferenceType): Promise { - const filterByType = (schemaType: SchemaType) => { return (entry: AnySchemaDifference) => { return entry.schemaType === schemaType && (!changeType || entry.changeType === changeType); diff --git a/core/ecschema-editing/src/Merging/SchemaReferenceMerger.ts b/core/ecschema-editing/src/Merging/SchemaReferenceMerger.ts index a95d29bd1f30..aac0f7324411 100644 --- a/core/ecschema-editing/src/Merging/SchemaReferenceMerger.ts +++ b/core/ecschema-editing/src/Merging/SchemaReferenceMerger.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { SchemaMergeContext } from "./SchemaMerger"; +import { ECVersion, Schema, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; import type { SchemaReferenceDifference } from "../Differencing/SchemaDifference"; import type { SchemaContextEditor } from "../Editing/Editor"; -import { ECVersion, Schema, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; +import type { SchemaMergeContext } from "./SchemaMerger"; /** * Merges a new reference to an external schema into the target schema. @@ -21,13 +21,16 @@ export async function addSchemaReferences(context: SchemaMergeContext, change: S * @internal */ export async function modifySchemaReferences(context: SchemaMergeContext, change: SchemaReferenceDifference) { - const existingSchema = await context.targetSchema.getReference(change.difference.name) as Schema; - const [older, latest] = sortSchemas(existingSchema.schemaKey, new SchemaKey(change.difference.name, ECVersion.fromString(change.difference.version))); - if(latest === existingSchema.schemaKey) { + const existingSchema = await context.targetSchema.getReference(change.difference.name) as Schema; + const [older, latest] = sortSchemas( + existingSchema.schemaKey, + new SchemaKey(change.difference.name, ECVersion.fromString(change.difference.version)), + ); + if (latest === existingSchema.schemaKey) { return; } - if(!latest.matches(older, SchemaMatchType.LatestWriteCompatible)) { + if (!latest.matches(older, SchemaMatchType.LatestWriteCompatible)) { throw new Error(`Schemas references of ${change.difference.name} have incompatible versions: ${older.version} and ${latest.version}`); } @@ -46,13 +49,13 @@ export async function modifySchemaReferences(context: SchemaMergeContext, change * @returns The schema found in the context. */ async function locateSchema(editor: SchemaContextEditor, schemaName?: string, version?: string): Promise { - if(schemaName === undefined || version === undefined) { + if (schemaName === undefined || version === undefined) { throw new Error("Schema name and version must not be undefined."); } const schemaKey = new SchemaKey(schemaName, ECVersion.fromString(version)); const schema = await editor.schemaContext.getSchema(schemaKey, SchemaMatchType.LatestWriteCompatible); - if(schema === undefined) { + if (schema === undefined) { throw new Error(`Referenced schema ${schemaKey.toString()} could not be found in target context`); } return schema; diff --git a/core/ecschema-editing/src/Merging/StructClassMerger.ts b/core/ecschema-editing/src/Merging/StructClassMerger.ts index 1dffbb10b148..2cc030cdcfff 100644 --- a/core/ecschema-editing/src/Merging/StructClassMerger.ts +++ b/core/ecschema-editing/src/Merging/StructClassMerger.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { StructClassDifference } from "../Differencing/SchemaDifference"; import type { MutableClass } from "../Editing/Mutable/MutableClass"; -import type { SchemaMergeContext } from "./SchemaMerger"; -import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import { modifyClass } from "./ClassMerger"; +import type { SchemaMergeContext } from "./SchemaMerger"; /** * Merges a new StructClass into the target schema. diff --git a/core/ecschema-editing/src/Merging/UnitSystemMerger.ts b/core/ecschema-editing/src/Merging/UnitSystemMerger.ts index 698091db6a4e..88bdf4cb7e46 100644 --- a/core/ecschema-editing/src/Merging/UnitSystemMerger.ts +++ b/core/ecschema-editing/src/Merging/UnitSystemMerger.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import type { SchemaItemKey } from "@itwin/ecschema-metadata"; import type { UnitSystemDifference } from "../Differencing/SchemaDifference"; import type { SchemaMergeContext } from "./SchemaMerger"; -import type { SchemaItemKey } from "@itwin/ecschema-metadata"; /** * Merges a new UnitSystem into the target schema. @@ -23,10 +23,10 @@ export async function addUnitSystem(context: SchemaMergeContext, change: UnitSys * @internal */ export async function modifyUnitSystem(context: SchemaMergeContext, change: UnitSystemDifference, itemKey: SchemaItemKey) { - if(change.difference.label !== undefined) { + if (change.difference.label !== undefined) { await context.editor.unitSystems.setDisplayLabel(itemKey, change.difference.label); } - if(change.difference.description !== undefined) { + if (change.difference.description !== undefined) { await context.editor.unitSystems.setDescription(itemKey, change.difference.description); } } diff --git a/core/ecschema-editing/src/Merging/Utils.ts b/core/ecschema-editing/src/Merging/Utils.ts index 7c0c14fb8547..212c3f563676 100644 --- a/core/ecschema-editing/src/Merging/Utils.ts +++ b/core/ecschema-editing/src/Merging/Utils.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECClass, ECObjectsError, ECObjectsStatus, SchemaContext, SchemaItem, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; import { ECClasses } from "../Editing/ECClasses"; import type { SchemaMergeContext } from "./SchemaMerger"; -import { ECClass, ECObjectsError, ECObjectsStatus, SchemaContext, SchemaItem, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; /** * Convenience-method around updateSchemaItemKey that returns the full name instead of a SchemaItemKey. @@ -69,7 +69,7 @@ export async function getClassEditor(context: SchemaMergeContext, ecClass: ECCla ? ecClass.schemaItemType : (await context.editor.schemaContext.getSchemaItem(ecClass))?.schemaItemType; - switch(schemaItemType) { + switch (schemaItemType) { case SchemaItemType.EntityClass: return context.editor.entities; case SchemaItemType.Mixin: diff --git a/core/ecschema-editing/src/Validation/Diagnostic.ts b/core/ecschema-editing/src/Validation/Diagnostic.ts index c75a0c8f7ef0..709bc6efb0ea 100644 --- a/core/ecschema-editing/src/Validation/Diagnostic.ts +++ b/core/ecschema-editing/src/Validation/Diagnostic.ts @@ -6,7 +6,15 @@ * @module Diagnostic */ -import { AnyClass, AnyECType, AnyProperty, CustomAttributeContainerProps, RelationshipConstraint, Schema, SchemaItem } from "@itwin/ecschema-metadata"; +import { + AnyClass, + AnyECType, + AnyProperty, + CustomAttributeContainerProps, + RelationshipConstraint, + Schema, + SchemaItem, +} from "@itwin/ecschema-metadata"; /* eslint-disable @typescript-eslint/no-shadow */ @@ -121,10 +129,14 @@ export abstract class SchemaDiagnostic extends BaseDiagnosti } /** Gets the schema where the diagnostic originated. */ - public get schema(): Schema { return this.ecDefinition; } + public get schema(): Schema { + return this.ecDefinition; + } /** Gets the DiagnosticType. */ - public get diagnosticType(): DiagnosticType { return DiagnosticType.Schema; } + public get diagnosticType(): DiagnosticType { + return DiagnosticType.Schema; + } } /** @@ -144,10 +156,14 @@ export abstract class SchemaItemDiagnostic extends SchemaItemDiag } /** Gets the schema where the diagnostic originated. */ - public override get schema(): Schema { return this.ecDefinition.schema; } + public override get schema(): Schema { + return this.ecDefinition.schema; + } } /** @@ -185,10 +203,14 @@ export abstract class PropertyDiagnostic extends BaseDiagnos } /** Gets the schema where the diagnostic originated. */ - public get schema(): Schema { return this.ecDefinition.schema; } + public get schema(): Schema { + return this.ecDefinition.schema; + } /** Gets the DiagnosticType. */ - public get diagnosticType(): DiagnosticType { return DiagnosticType.Property; } + public get diagnosticType(): DiagnosticType { + return DiagnosticType.Property; + } } /** @@ -207,10 +229,14 @@ export abstract class RelationshipConstraintDiagnostic exten } /** Gets the schema where the diagnostic originated. */ - public get schema(): Schema { return this.ecDefinition.schema; } + public get schema(): Schema { + return this.ecDefinition.schema; + } /** Gets the DiagnosticType. */ - public get diagnosticType(): DiagnosticType { return DiagnosticType.RelationshipConstraint; } + public get diagnosticType(): DiagnosticType { + return DiagnosticType.RelationshipConstraint; + } } /** @@ -229,10 +255,14 @@ export abstract class CustomAttributeContainerDiagnostic ext } /** Gets the schema where the diagnostic originated. */ - public get schema(): Schema { return this.ecDefinition.schema; } + public get schema(): Schema { + return this.ecDefinition.schema; + } /** Gets the DiagnosticType. */ - public get diagnosticType(): DiagnosticType { return DiagnosticType.CustomAttributeContainer; } + public get diagnosticType(): DiagnosticType { + return DiagnosticType.CustomAttributeContainer; + } } /** @@ -245,8 +275,12 @@ export function createSchemaDiagnosticClass(code: string, me validateCode(code); return class extends SchemaDiagnostic { public static code = code; - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } @@ -259,8 +293,12 @@ export function createSchemaDiagnosticClass(code: string, me export function createSchemaItemDiagnosticClass(code: string, messageText: string) { validateCode(code); return class extends SchemaItemDiagnostic { - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } @@ -273,8 +311,12 @@ export function createSchemaItemDiagnosticClass(code: string, messageText: string) { validateCode(code); return class extends ClassDiagnostic { - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } @@ -288,8 +330,12 @@ export function createPropertyDiagnosticClass(code: string, validateCode(code); return class extends PropertyDiagnostic { public static code = code; - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } @@ -302,8 +348,12 @@ export function createPropertyDiagnosticClass(code: string, export function createRelationshipConstraintDiagnosticClass(code: string, messageText: string) { validateCode(code); return class extends RelationshipConstraintDiagnostic { - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } @@ -316,8 +366,12 @@ export function createRelationshipConstraintDiagnosticClass( export function createCustomAttributeContainerDiagnosticClass(code: string, messageText: string) { validateCode(code); return class extends CustomAttributeContainerDiagnostic { - public get code(): string { return code; } - public get messageText(): string { return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); } + public get code(): string { + return code; + } + public get messageText(): string { + return undefined === this.messageArgs ? messageText : formatString(messageText, ...this.messageArgs); + } }; } diff --git a/core/ecschema-editing/src/Validation/ECRules.ts b/core/ecschema-editing/src/Validation/ECRules.ts index 41161c79323b..b9caac13a9e8 100644 --- a/core/ecschema-editing/src/Validation/ECRules.ts +++ b/core/ecschema-editing/src/Validation/ECRules.ts @@ -7,16 +7,43 @@ */ import { - AnyClass, AnyProperty, CustomAttribute, CustomAttributeContainerProps, ECClass, ECClassModifier, - ECStringConstants, EntityClass, Enumeration, PrimitiveProperty, PrimitiveType, primitiveTypeToString, - Property, RelationshipClass, RelationshipConstraint, RelationshipMultiplicity, Schema, SchemaGraph, SchemaItemType, - StrengthDirection, strengthDirectionToString, + AnyClass, + AnyProperty, + CustomAttribute, + CustomAttributeContainerProps, + ECClass, + ECClassModifier, + ECStringConstants, + EntityClass, + Enumeration, + PrimitiveProperty, + PrimitiveType, + primitiveTypeToString, + Property, + RelationshipClass, + RelationshipConstraint, + RelationshipMultiplicity, + Schema, + SchemaGraph, + SchemaItemType, + StrengthDirection, + strengthDirectionToString, } from "@itwin/ecschema-metadata"; import { - ClassDiagnostic, createClassDiagnosticClass, createCustomAttributeContainerDiagnosticClass, createPropertyDiagnosticClass, - createRelationshipConstraintDiagnosticClass, createSchemaDiagnosticClass, createSchemaItemDiagnosticClass, CustomAttributeContainerDiagnostic, + ClassDiagnostic, + createClassDiagnosticClass, + createCustomAttributeContainerDiagnosticClass, + createPropertyDiagnosticClass, + createRelationshipConstraintDiagnosticClass, + createSchemaDiagnosticClass, + createSchemaItemDiagnosticClass, + CustomAttributeContainerDiagnostic, // eslint-disable-next-line @typescript-eslint/no-unused-vars - DiagnosticType, PropertyDiagnostic, RelationshipConstraintDiagnostic, SchemaDiagnostic, SchemaItemDiagnostic, + DiagnosticType, + PropertyDiagnostic, + RelationshipConstraintDiagnostic, + SchemaDiagnostic, + SchemaItemDiagnostic, } from "./Diagnostic"; import { IRuleSet } from "./Rules"; @@ -95,96 +122,139 @@ export const DiagnosticCodes = { */ export const Diagnostics = { /** EC-001: Required message parameters: schema name, referenced schema name */ - SupplementalSchemasCannotBeReferenced: createSchemaDiagnosticClass<[string, string]>(getCode(1), - "Referenced schema '{1}' of schema '{0}' is a supplemental schema. Supplemental schemas are not allowed to be referenced."), + SupplementalSchemasCannotBeReferenced: createSchemaDiagnosticClass<[string, string]>( + getCode(1), + "Referenced schema '{1}' of schema '{0}' is a supplemental schema. Supplemental schemas are not allowed to be referenced.", + ), /** EC-002: Required message parameters: schema name, reference schema alias, first schema reference name, second schema reference name. */ - SchemaRefAliasMustBeUnique: createSchemaDiagnosticClass<[string, string, string, string]>(getCode(2), - "Schema '{0}' has multiple schema references ({2}, {3}) with the same alias '{1}', which is not allowed."), + SchemaRefAliasMustBeUnique: createSchemaDiagnosticClass<[string, string, string, string]>( + getCode(2), + "Schema '{0}' has multiple schema references ({2}, {3}) with the same alias '{1}', which is not allowed.", + ), /** EC-003: Required message parameters: schema name, cycle text */ - ReferenceCyclesNotAllowed: createSchemaDiagnosticClass<[string, string]>(getCode(3), - "Schema '{0}' has reference cycles: {1}"), + ReferenceCyclesNotAllowed: createSchemaDiagnosticClass<[string, string]>(getCode(3), "Schema '{0}' has reference cycles: {1}"), /** EC-100: Required message parameters: childClass.FullName, baseClass.FullName */ - BaseClassIsSealed: createClassDiagnosticClass<[string, string]>(DiagnosticCodes.BaseClassIsSealed, - "Class '{0}' cannot derive from sealed base class '{1}'."), + BaseClassIsSealed: createClassDiagnosticClass<[string, string]>( + DiagnosticCodes.BaseClassIsSealed, + "Class '{0}' cannot derive from sealed base class '{1}'.", + ), /** EC-101: Required message parameters: childClass.FullName, baseClass.FullName, baseClass.schemaItemType */ - BaseClassIsOfDifferentType: createClassDiagnosticClass<[string, string, string]>(DiagnosticCodes.BaseClassOfDifferentType, - "Class '{0}' cannot derive from base class '{1}' of type '{2}'."), + BaseClassIsOfDifferentType: createClassDiagnosticClass<[string, string, string]>( + DiagnosticCodes.BaseClassOfDifferentType, + "Class '{0}' cannot derive from base class '{1}' of type '{2}'.", + ), /** **DEPRECATED** EC-102: Required message parameters: childClass.FullName, baseClass.FullName */ - AbstractClassWithNonAbstractBase: createClassDiagnosticClass<[string, string]>(DiagnosticCodes.AbstractClassWithNonAbstractBase, - "Abstract Class '{0}' cannot derive from base class '{1}' because it is not an abstract class."), + AbstractClassWithNonAbstractBase: createClassDiagnosticClass<[string, string]>( + DiagnosticCodes.AbstractClassWithNonAbstractBase, + "Abstract Class '{0}' cannot derive from base class '{1}' because it is not an abstract class.", + ), /** EC-500: Required message parameters: CustomAttribute container name and CustomAttributeClass name. */ - CustomAttributeNotOfConcreteClass: createCustomAttributeContainerDiagnosticClass<[string, string]>(DiagnosticCodes.CustomAttributeNotOfConcreteClass, - "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' which is not a concrete class."), + CustomAttributeNotOfConcreteClass: createCustomAttributeContainerDiagnosticClass<[string, string]>( + DiagnosticCodes.CustomAttributeNotOfConcreteClass, + "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' which is not a concrete class.", + ), /** EC-501: Required message parameters: CustomAttribute container name, CustomAttributeClass name, CustomAttributeClass Schema name. */ - CustomAttributeSchemaMustBeReferenced: createCustomAttributeContainerDiagnosticClass<[string, string]>(DiagnosticCodes.CustomAttributeSchemaMustBeReferenced, - "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' whose schema is not referenced by the container's Schema."), + CustomAttributeSchemaMustBeReferenced: createCustomAttributeContainerDiagnosticClass<[string, string]>( + DiagnosticCodes.CustomAttributeSchemaMustBeReferenced, + "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' whose schema is not referenced by the container's Schema.", + ), /** EC-502: Required message parameters: CustomAttribute container name and CustomAttributeClass name. */ - CustomAttributeClassNotFound: createCustomAttributeContainerDiagnosticClass<[string, string]>(DiagnosticCodes.CustomAttributeClassNotFound, - "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' which cannot be found."), + CustomAttributeClassNotFound: createCustomAttributeContainerDiagnosticClass<[string, string]>( + DiagnosticCodes.CustomAttributeClassNotFound, + "The CustomAttribute container '{0}' has a CustomAttribute with the class '{1}' which cannot be found.", + ), /** EC-700: Required message parameters: Enumeration name */ - EnumerationTypeUnsupported: createSchemaItemDiagnosticClass(DiagnosticCodes.EnumerationTypeUnsupported, - "Enumeration '{0}' has invalid primitive type."), + EnumerationTypeUnsupported: createSchemaItemDiagnosticClass( + DiagnosticCodes.EnumerationTypeUnsupported, + "Enumeration '{0}' has invalid primitive type.", + ), /** EC-1100: Required message parameters: mixin class fullName, class fullName, applies to constraint class fullName */ - MixinAppliedToClassMustDeriveFromConstraint: createSchemaItemDiagnosticClass(DiagnosticCodes.MixinAppliedToClassMustDeriveFromConstraint, - "Mixin '{0}' cannot be applied to the class '{1}' because it does not satisfy the applies to constraint '{2}'."), + MixinAppliedToClassMustDeriveFromConstraint: createSchemaItemDiagnosticClass( + DiagnosticCodes.MixinAppliedToClassMustDeriveFromConstraint, + "Mixin '{0}' cannot be applied to the class '{1}' because it does not satisfy the applies to constraint '{2}'.", + ), /** EC-1300: Required message parameters: childClass.FullName, property name, baseClass.FullName, base value type, child value type */ - IncompatibleValueTypePropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string]>(DiagnosticCodes.IncompatibleValueTypePropertyOverride, - "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with a value type of {3} which is incompatible with the value type of {4}."), + IncompatibleValueTypePropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string]>( + DiagnosticCodes.IncompatibleValueTypePropertyOverride, + "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with a value type of {3} which is incompatible with the value type of {4}.", + ), /** EC-1301: Required message parameters: childClass.FullName, property name, baseClass.FullName, base property type, child property type */ - IncompatibleTypePropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string]>(DiagnosticCodes.IncompatibleTypePropertyOverride, - "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with a type of {3} which is incompatible with the type of {4}."), + IncompatibleTypePropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string]>( + DiagnosticCodes.IncompatibleTypePropertyOverride, + "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with a type of {3} which is incompatible with the type of {4}.", + ), /** EC-1302: Required message parameters: childClass.Name, property name, baseClass.Name, baseClass Koq name, baseClass Koq persistence unit name, child class Koq persistence unit name, child class Koq name */ - IncompatibleUnitPropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string, string, string]>(DiagnosticCodes.IncompatibleUnitPropertyOverride, - "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with KindOfQuantity '{3}' with persistence unit '{4}' which is not the same as the persistence unit '{5}' of the provided KindOfQuantity '{6}'."), + IncompatibleUnitPropertyOverride: createPropertyDiagnosticClass<[string, string, string, string, string, string, string]>( + DiagnosticCodes.IncompatibleUnitPropertyOverride, + "The ECProperty '{0}.{1}' has a base property '{2}.{1}' with KindOfQuantity '{3}' with persistence unit '{4}' which is not the same as the persistence unit '{5}' of the provided KindOfQuantity '{6}'.", + ), /** EC-1303: Required message parameters: property.fullName, navigation relationship.fullName */ - NavigationRelationshipMustBeRoot: createPropertyDiagnosticClass<[string, string]>(getCode(1303), - "The referenced relationship '{1}', used in NavigationProperty '{0}' is not the root relationship."), + NavigationRelationshipMustBeRoot: createPropertyDiagnosticClass<[string, string]>( + getCode(1303), + "The referenced relationship '{1}', used in NavigationProperty '{0}' is not the root relationship.", + ), /** EC-1304: Required message parameters: property.fullName, navigation relationship.fullName */ - NavigationTargetMustHaveSingularMultiplicity: createPropertyDiagnosticClass<[string, string, string]>(getCode(1304), - "NavigationProperty '{0}' uses the relationship '{1}' that cannot be traversed in the '{2}' direction due to a max multiplicity greater than 1."), + NavigationTargetMustHaveSingularMultiplicity: createPropertyDiagnosticClass<[string, string, string]>( + getCode(1304), + "NavigationProperty '{0}' uses the relationship '{1}' that cannot be traversed in the '{2}' direction due to a max multiplicity greater than 1.", + ), /** EC-1305: Required message parameters: property.fullName, navigation relationship.fullName */ - NavigationRelationshipAbstractConstraintEntityOrMixin: createPropertyDiagnosticClass<[string, string]>(getCode(1305), - "The NavigationProperty '{0}', using the relationship '{1}', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin."), + NavigationRelationshipAbstractConstraintEntityOrMixin: createPropertyDiagnosticClass<[string, string]>( + getCode(1305), + "The NavigationProperty '{0}', using the relationship '{1}', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin.", + ), /** EC-1306: Required message parameters: class name, property name, navigation relationship.fullName */ - NavigationClassMustBeAConstraintClassOfRelationship: createPropertyDiagnosticClass<[string, string, string, string]>(getCode(1306), - "The class '{0}' of NavigationProperty '{1}' is not supported by the {3} constraint of the referenced relationship '{2}'."), + NavigationClassMustBeAConstraintClassOfRelationship: createPropertyDiagnosticClass<[string, string, string, string]>( + getCode(1306), + "The class '{0}' of NavigationProperty '{1}' is not supported by the {3} constraint of the referenced relationship '{2}'.", + ), /** EC-1500: Required message parameters: abstract constraint class name, relationship end (source/target), relationship name, base relationship name */ - AbstractConstraintMustNarrowBaseConstraints: createSchemaItemDiagnosticClass(DiagnosticCodes.AbstractConstraintMustNarrowBaseConstraints, - "The abstract constraint class '{0}' on the {1}-Constraint of '{2}' is not supported by the base class constraint in '{3}'."), + AbstractConstraintMustNarrowBaseConstraints: createSchemaItemDiagnosticClass( + DiagnosticCodes.AbstractConstraintMustNarrowBaseConstraints, + "The abstract constraint class '{0}' on the {1}-Constraint of '{2}' is not supported by the base class constraint in '{3}'.", + ), /** EC-1501: Required message parameters: constraint class name, relationship end (source/target), relationship name, base relationship name */ - DerivedConstraintsMustNarrowBaseConstraints: createSchemaItemDiagnosticClass(DiagnosticCodes.DerivedConstraintsMustNarrowBaseConstraints, - "The constraint class '{0}' on the {1}-Constraint of '{2}' is not supported by the base class constraint in '{3}'."), + DerivedConstraintsMustNarrowBaseConstraints: createSchemaItemDiagnosticClass( + DiagnosticCodes.DerivedConstraintsMustNarrowBaseConstraints, + "The constraint class '{0}' on the {1}-Constraint of '{2}' is not supported by the base class constraint in '{3}'.", + ), /** EC-1502: Required message parameters: constraint class name, relationship end (source/target), relationship name, abstract constraint class name */ - ConstraintClassesDeriveFromAbstractConstraint: createSchemaItemDiagnosticClass(DiagnosticCodes.ConstraintClassesDeriveFromAbstractConstraint, - "The constraint class '{0}' on the {1}-Constraint of '{2}' is not derived from the abstract constraint class '{3}'."), + ConstraintClassesDeriveFromAbstractConstraint: createSchemaItemDiagnosticClass( + DiagnosticCodes.ConstraintClassesDeriveFromAbstractConstraint, + "The constraint class '{0}' on the {1}-Constraint of '{2}' is not derived from the abstract constraint class '{3}'.", + ), /** EC-1600: Required message parameters: relationship end (source/target), relationship name */ - AtLeastOneConstraintClassDefined: createRelationshipConstraintDiagnosticClass<[string, string]>(DiagnosticCodes.AtLeastOneConstraintClassDefined, - "The {0}-Constraint of '{1}' does not contain any constraint classes."), + AtLeastOneConstraintClassDefined: createRelationshipConstraintDiagnosticClass<[string, string]>( + DiagnosticCodes.AtLeastOneConstraintClassDefined, + "The {0}-Constraint of '{1}' does not contain any constraint classes.", + ), /** EC-1601: Required message parameters: relationship end (source/target), relationship name */ - AbstractConstraintMustExistWithMultipleConstraints: createRelationshipConstraintDiagnosticClass<[string, string]>(DiagnosticCodes.AbstractConstraintMustExistWithMultipleConstraints, - "The {0}-Constraint of '{1}' has multiple constraint classes which requires an abstract constraint to be defined."), + AbstractConstraintMustExistWithMultipleConstraints: createRelationshipConstraintDiagnosticClass<[string, string]>( + DiagnosticCodes.AbstractConstraintMustExistWithMultipleConstraints, + "The {0}-Constraint of '{1}' has multiple constraint classes which requires an abstract constraint to be defined.", + ), }; /** @@ -303,7 +373,7 @@ export async function* baseClassIsOfDifferentType(ecClass: AnyClass): AsyncItera /** * EC Rule: When overriding a class primitive property, the child and base property must be of the same type (string, number, etc...). * @internal -*/ + */ export async function* incompatibleValueTypePropertyOverride(property: AnyProperty): AsyncIterable> { if (!property.class.baseClass) return; @@ -328,7 +398,13 @@ export async function* incompatibleValueTypePropertyOverride(property: AnyProper if (!baseType || primitiveType === baseType) return; - return new Diagnostics.IncompatibleValueTypePropertyOverride(property, [property.class.fullName, property.name, baseClass.fullName, primitiveTypeToString(baseType), primitiveTypeToString(primitiveType!)]); + return new Diagnostics.IncompatibleValueTypePropertyOverride(property, [ + property.class.fullName, + property.name, + baseClass.fullName, + primitiveTypeToString(baseType), + primitiveTypeToString(primitiveType!), + ]); } for await (const baseClass of property.class.getAllBaseClasses()) { @@ -355,7 +431,13 @@ export async function* incompatibleTypePropertyOverride(property: AnyProperty): if (propertyTypesMatch(property, baseProperty)) return; - return new Diagnostics.IncompatibleTypePropertyOverride(property, [property.class.fullName, property.name, baseClass.fullName, baseProperty.constructor.name, property.constructor.name]); + return new Diagnostics.IncompatibleTypePropertyOverride(property, [ + property.class.fullName, + property.name, + baseClass.fullName, + baseProperty.constructor.name, + property.constructor.name, + ]); } for await (const baseClass of property.class.getAllBaseClasses()) { @@ -473,7 +555,12 @@ export async function* validateNavigationProperty(property: AnyProperty): AsyncI } if (!classSupported) - yield new Diagnostics.NavigationClassMustBeAConstraintClassOfRelationship(property, [property.class.name, property.name, relationship.fullName, navigationClassSide]); + yield new Diagnostics.NavigationClassMustBeAConstraintClassOfRelationship(property, [ + property.class.name, + property.name, + relationship.fullName, + navigationClassSide, + ]); if (thatConstraint.multiplicity === RelationshipMultiplicity.oneMany || thatConstraint.multiplicity === RelationshipMultiplicity.zeroMany) { const direction = strengthDirectionToString(navProp.direction); @@ -497,7 +584,9 @@ export async function* validateRelationship(ecClass: RelationshipClass): AsyncIt * EC Rule: When overriding a RelationshipClass, the derived abstract constraint must narrow the base constraint classes. * @internal */ -export async function* abstractConstraintMustNarrowBaseConstraints(ecClass: RelationshipClass): AsyncIterable> { +export async function* abstractConstraintMustNarrowBaseConstraints( + ecClass: RelationshipClass, +): AsyncIterable> { if (!ecClass.baseClass) return; @@ -515,7 +604,9 @@ export async function* abstractConstraintMustNarrowBaseConstraints(ecClass: Rela * EC Rule: When overriding a RelationshipClass, derived constraint classes must narrow base constraint classes. * @internal */ -export async function* derivedConstraintsMustNarrowBaseConstraints(ecClass: RelationshipClass): AsyncIterable> { +export async function* derivedConstraintsMustNarrowBaseConstraints( + ecClass: RelationshipClass, +): AsyncIterable> { if (!ecClass.baseClass) return; @@ -533,7 +624,9 @@ export async function* derivedConstraintsMustNarrowBaseConstraints(ecClass: Rela * EC Rule: All constraint classes must have a common base class specified in the abstract constraint. * @internal */ -export async function* constraintClassesDeriveFromAbstractConstraint(ecClass: RelationshipClass): AsyncIterable> { +export async function* constraintClassesDeriveFromAbstractConstraint( + ecClass: RelationshipClass, +): AsyncIterable> { const sourceResult = await applyConstraintClassesDeriveFromAbstractConstraint(ecClass, ecClass.source); if (sourceResult) yield sourceResult; @@ -566,7 +659,9 @@ export async function* atLeastOneConstraintClassDefined(constraint: Relationship * EC Rule: If multiple constraints exist, an abstract constraint must be defined. * @internal */ -export async function* abstractConstraintMustExistWithMultipleConstraints(constraint: RelationshipConstraint): AsyncIterable> { +export async function* abstractConstraintMustExistWithMultipleConstraints( + constraint: RelationshipConstraint, +): AsyncIterable> { if (!constraint.constraintClasses || constraint.constraintClasses.length <= 1) { return; } @@ -606,14 +701,20 @@ export async function* enumerationTypeUnsupported(enumeration: Enumeration): Asy * EC Rule: Mixin applied to class must derived from the Mixin appliesTo constraint. * @internal */ -export async function* mixinAppliedToClassMustDeriveFromConstraint(entityClass: EntityClass): AsyncIterable> { +export async function* mixinAppliedToClassMustDeriveFromConstraint( + entityClass: EntityClass, +): AsyncIterable> { for (const lazyMixin of entityClass.mixins) { const mixin = await lazyMixin; if (!mixin.appliesTo) continue; if (!await entityClass.is(await mixin.appliesTo)) - yield new Diagnostics.MixinAppliedToClassMustDeriveFromConstraint(entityClass, [mixin.fullName, entityClass.fullName, mixin.appliesTo.fullName]); + yield new Diagnostics.MixinAppliedToClassMustDeriveFromConstraint(entityClass, [ + mixin.fullName, + entityClass.fullName, + mixin.appliesTo.fullName, + ]); } return; @@ -623,14 +724,20 @@ export async function* mixinAppliedToClassMustDeriveFromConstraint(entityClass: * Validates a custom attribute instance and yields EC-500, EC-501, and EC-502 rule violations. * @internal */ -export async function* validateCustomAttributeInstance(container: CustomAttributeContainerProps, customAttribute: CustomAttribute): AsyncIterable> { +export async function* validateCustomAttributeInstance( + container: CustomAttributeContainerProps, + customAttribute: CustomAttribute, +): AsyncIterable> { yield* customAttributeNotOfConcreteClass(container, customAttribute); yield* customAttributeSchemaMustBeReferenced(container, customAttribute); yield* customAttributeClassMustExist(container, customAttribute); } /** EC Rule: CustomAttribute instance must be of a concrete CustomAttributeClass. */ -async function* customAttributeNotOfConcreteClass(container: CustomAttributeContainerProps, customAttribute: CustomAttribute): AsyncIterable> { +async function* customAttributeNotOfConcreteClass( + container: CustomAttributeContainerProps, + customAttribute: CustomAttribute, +): AsyncIterable> { const schema = container.schema; const caClass = await schema.lookupItem(customAttribute.className) as ECClass; if (!caClass) @@ -643,7 +750,10 @@ async function* customAttributeNotOfConcreteClass(container: CustomAttributeCont } /** EC Rule: CustomAttribute Schema must be referenced by the container's Schema. */ -async function* customAttributeSchemaMustBeReferenced(container: CustomAttributeContainerProps, customAttribute: CustomAttribute): AsyncIterable> { +async function* customAttributeSchemaMustBeReferenced( + container: CustomAttributeContainerProps, + customAttribute: CustomAttribute, +): AsyncIterable> { const schema = container.schema; const nameParts = customAttribute.className.split("."); if (nameParts.length === 1 || nameParts[0] === schema.name) @@ -656,14 +766,21 @@ async function* customAttributeSchemaMustBeReferenced(container: CustomAttribute } /** EC Rule: CustomAttribute instance class must exist. */ -async function* customAttributeClassMustExist(container: CustomAttributeContainerProps, customAttribute: CustomAttribute): AsyncIterable> { +async function* customAttributeClassMustExist( + container: CustomAttributeContainerProps, + customAttribute: CustomAttribute, +): AsyncIterable> { const schema = container.schema; const caClass = await schema.lookupItem(customAttribute.className) as ECClass; if (!caClass) yield new Diagnostics.CustomAttributeClassNotFound(container, [container.fullName, customAttribute.className]); } -async function applyAbstractConstraintMustNarrowBaseConstraints(ecClass: RelationshipClass, constraint: RelationshipConstraint, baseRelationship: RelationshipClass): Promise | undefined> { +async function applyAbstractConstraintMustNarrowBaseConstraints( + ecClass: RelationshipClass, + constraint: RelationshipConstraint, + baseRelationship: RelationshipClass, +): Promise | undefined> { const baseConstraint = constraint.isSource ? baseRelationship.source : baseRelationship.target; const abstractConstraint = await constraint.abstractConstraint; if (!abstractConstraint) @@ -673,10 +790,19 @@ async function applyAbstractConstraintMustNarrowBaseConstraints(ecClass: Relatio return; const constraintType = constraint.isSource ? ECStringConstants.RELATIONSHIP_END_SOURCE : ECStringConstants.RELATIONSHIP_END_TARGET; - return new Diagnostics.AbstractConstraintMustNarrowBaseConstraints(ecClass, [abstractConstraint.fullName, constraintType, constraint.relationshipClass.fullName, baseRelationship.fullName]); + return new Diagnostics.AbstractConstraintMustNarrowBaseConstraints(ecClass, [ + abstractConstraint.fullName, + constraintType, + constraint.relationshipClass.fullName, + baseRelationship.fullName, + ]); } -async function applyDerivedConstraintsMustNarrowBaseConstraints(ecClass: RelationshipClass, constraint: RelationshipConstraint, baseRelationship: RelationshipClass): Promise | undefined> { +async function applyDerivedConstraintsMustNarrowBaseConstraints( + ecClass: RelationshipClass, + constraint: RelationshipConstraint, + baseRelationship: RelationshipClass, +): Promise | undefined> { const baseConstraint = constraint.isSource ? baseRelationship.source : baseRelationship.target; if (!constraint.constraintClasses) @@ -689,13 +815,21 @@ async function applyDerivedConstraintsMustNarrowBaseConstraints(ecClass: Relatio continue; const constraintType = constraint.isSource ? ECStringConstants.RELATIONSHIP_END_SOURCE : ECStringConstants.RELATIONSHIP_END_TARGET; - return new Diagnostics.DerivedConstraintsMustNarrowBaseConstraints(ecClass, [constraintClass.fullName, constraintType, constraint.relationshipClass.fullName, baseRelationship.fullName]); + return new Diagnostics.DerivedConstraintsMustNarrowBaseConstraints(ecClass, [ + constraintClass.fullName, + constraintType, + constraint.relationshipClass.fullName, + baseRelationship.fullName, + ]); } return; } -async function applyConstraintClassesDeriveFromAbstractConstraint(ecClass: RelationshipClass, constraint: RelationshipConstraint): Promise | undefined> { +async function applyConstraintClassesDeriveFromAbstractConstraint( + ecClass: RelationshipClass, + constraint: RelationshipConstraint, +): Promise | undefined> { const abstractConstraint = await getAbstractConstraint(constraint); if (!abstractConstraint) return; @@ -707,16 +841,26 @@ async function applyConstraintClassesDeriveFromAbstractConstraint(ecClass: Relat const constraintClass = await classPromise; if (constraintClass.schemaItemType === SchemaItemType.Mixin && abstractConstraint.schemaItemType === SchemaItemType.EntityClass) { - if (!await (constraintClass).applicableTo(abstractConstraint as EntityClass)) { + if (!await constraintClass.applicableTo(abstractConstraint as EntityClass)) { const constraintType = constraint.isSource ? ECStringConstants.RELATIONSHIP_END_SOURCE : ECStringConstants.RELATIONSHIP_END_TARGET; - return new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(ecClass, [constraintClass.fullName, constraintType, constraint.relationshipClass.fullName, abstractConstraint.fullName]); + return new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(ecClass, [ + constraintClass.fullName, + constraintType, + constraint.relationshipClass.fullName, + abstractConstraint.fullName, + ]); } continue; } if (!await constraintClass.is(abstractConstraint)) { const constraintType = constraint.isSource ? ECStringConstants.RELATIONSHIP_END_SOURCE : ECStringConstants.RELATIONSHIP_END_TARGET; - return new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(ecClass, [constraintClass.fullName, constraintType, constraint.relationshipClass.fullName, abstractConstraint.fullName]); + return new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(ecClass, [ + constraintClass.fullName, + constraintType, + constraint.relationshipClass.fullName, + abstractConstraint.fullName, + ]); } } diff --git a/core/ecschema-editing/src/Validation/LoggingDiagnosticReporter.ts b/core/ecschema-editing/src/Validation/LoggingDiagnosticReporter.ts index e21f35c93741..e76b000091a9 100644 --- a/core/ecschema-editing/src/Validation/LoggingDiagnosticReporter.ts +++ b/core/ecschema-editing/src/Validation/LoggingDiagnosticReporter.ts @@ -35,6 +35,15 @@ export class LoggingDiagnosticReporter extends FormatDiagnosticReporter { } private getLogMetaData(diagnostic: AnyDiagnostic) { - return { ...diagnostic, ...{ code: diagnostic.code, category: diagnostic.category, diagnosticType: diagnostic.diagnosticType, messageText: undefined, messageArgs: undefined } }; + return { + ...diagnostic, + ...{ + code: diagnostic.code, + category: diagnostic.category, + diagnosticType: diagnostic.diagnosticType, + messageText: undefined, + messageArgs: undefined, + }, + }; } } diff --git a/core/ecschema-editing/src/Validation/RuleSuppressionSet.ts b/core/ecschema-editing/src/Validation/RuleSuppressionSet.ts index 4e565fdfc36f..f0a028370c57 100644 --- a/core/ecschema-editing/src/Validation/RuleSuppressionSet.ts +++ b/core/ecschema-editing/src/Validation/RuleSuppressionSet.ts @@ -6,10 +6,30 @@ * @module Validation */ -import { AnyClass, AnyECType, AnyProperty, Constant, CustomAttribute, CustomAttributeClass, - CustomAttributeContainerProps, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, - PropertyCategory, RelationshipClass, RelationshipConstraint, Schema, SchemaItem, StructClass, Unit, - UnitSystem } from "@itwin/ecschema-metadata"; +import { + AnyClass, + AnyECType, + AnyProperty, + Constant, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + StructClass, + Unit, + UnitSystem, +} from "@itwin/ecschema-metadata"; import { AnyDiagnostic } from "./Diagnostic"; /** diff --git a/core/ecschema-editing/src/Validation/Rules.ts b/core/ecschema-editing/src/Validation/Rules.ts index 4732d71e227a..b727756d4e05 100644 --- a/core/ecschema-editing/src/Validation/Rules.ts +++ b/core/ecschema-editing/src/Validation/Rules.ts @@ -6,10 +6,30 @@ * @module Validation */ -import { AnyClass, AnyECType, AnyProperty, Constant, CustomAttribute, CustomAttributeClass, - CustomAttributeContainerProps, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, - PropertyCategory, RelationshipClass, RelationshipConstraint, Schema, SchemaItem, StructClass, Unit, - UnitSystem } from "@itwin/ecschema-metadata"; +import { + AnyClass, + AnyECType, + AnyProperty, + Constant, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + StructClass, + Unit, + UnitSystem, +} from "@itwin/ecschema-metadata"; import { BaseDiagnostic } from "./Diagnostic"; /** diff --git a/core/ecschema-editing/src/Validation/SchemaChanges.ts b/core/ecschema-editing/src/Validation/SchemaChanges.ts index 0eca7837ae58..dfce776c0908 100644 --- a/core/ecschema-editing/src/Validation/SchemaChanges.ts +++ b/core/ecschema-editing/src/Validation/SchemaChanges.ts @@ -6,9 +6,24 @@ * @module Comparison */ -import { AnyClass, AnyEnumerator, CustomAttribute, ECClass, ECObjectsError, ECObjectsStatus, - EntityClass, Enumeration, Format, KindOfQuantity, OverrideFormat, Property, RelationshipClass, RelationshipConstraint, - Schema, SchemaItem, SchemaItemType, +import { + AnyClass, + AnyEnumerator, + CustomAttribute, + ECClass, + ECObjectsError, + ECObjectsStatus, + EntityClass, + Enumeration, + Format, + KindOfQuantity, + OverrideFormat, + Property, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + SchemaItemType, } from "@itwin/ecschema-metadata"; import { AnyDiagnostic } from "./Diagnostic"; import { SchemaCompareCodes } from "./SchemaCompareDiagnostics"; @@ -52,7 +67,9 @@ export interface ISchemaChanges { /** * Allows an ISchemaChanges implementation to be dynamically constructed in addChangeToMap. */ -interface SchemaChangesConstructor { new(schema: Schema, ecTypeName: string): ISchemaChanges } // eslint-disable-line @typescript-eslint/prefer-function-type +interface SchemaChangesConstructor { + new(schema: Schema, ecTypeName: string): ISchemaChanges; +} // eslint-disable-line @typescript-eslint/prefer-function-type /** * An ISchemaChange implementation meant to be used as the base class @@ -72,7 +89,9 @@ export abstract class BaseSchemaChange implements ISchemaChange { } /** Gets the diagnostic holding the information about the schema change. */ - public get diagnostic(): AnyDiagnostic { return this._diagnostic; } + public get diagnostic(): AnyDiagnostic { + return this._diagnostic; + } /** * Returns the SchemaItem that this change ultimately belongs to. For example, @@ -90,7 +109,9 @@ export abstract class BaseSchemaChange implements ISchemaChange { this._changeType = this.defaultChangeType; return this._changeType; } - public set changeType(changeType: ChangeType) { this._changeType = changeType; } + public set changeType(changeType: ChangeType) { + this._changeType = changeType; + } /** The default ChangeType (Delta or Missing). */ public abstract get defaultChangeType(): ChangeType; @@ -108,14 +129,20 @@ export abstract class BaseSchemaChange implements ISchemaChange { */ protected getNameFromArgument(index: number, allowUndefined: boolean = false, fullName: boolean = false): string { if (!this.diagnostic.messageArgs || this.diagnostic.messageArgs.length <= index) - throw new ECObjectsError(ECObjectsStatus.InvalidSchemaComparisonArgument, `Schema comparison diagnostic '${this.diagnostic.code}' for SchemaItem '${this.topLevelSchemaItem.fullName}' has invalid arguments`); + throw new ECObjectsError( + ECObjectsStatus.InvalidSchemaComparisonArgument, + `Schema comparison diagnostic '${this.diagnostic.code}' for SchemaItem '${this.topLevelSchemaItem.fullName}' has invalid arguments`, + ); const schemaItem = this.getValueFromArgument(index); if (Schema.isSchema(schemaItem) || SchemaItem.isSchemaItem(schemaItem) || OverrideFormat.isOverrideFormat(schemaItem)) return fullName ? schemaItem.fullName : schemaItem.name; if (!allowUndefined) - throw new ECObjectsError(ECObjectsStatus.InvalidSchemaComparisonArgument, `Schema comparison diagnostic '${this.diagnostic.code}' for SchemaItem '${this.topLevelSchemaItem.fullName}' has invalid arguments`); + throw new ECObjectsError( + ECObjectsStatus.InvalidSchemaComparisonArgument, + `Schema comparison diagnostic '${this.diagnostic.code}' for SchemaItem '${this.topLevelSchemaItem.fullName}' has invalid arguments`, + ); return "undefined"; } @@ -202,7 +229,12 @@ export abstract class BaseSchemaChanges implements ISchemaChanges { * @param change The ISchemaChange to add. * @param changeKey The key used to identify the ISchemaChanges in the Map (typically the name of the EC type, ie. SchemaItem.name). */ - protected addChangeToMap(changes: Map, changesType: SchemaChangesConstructor, change: ISchemaChange, changeKey: string) { + protected addChangeToMap( + changes: Map, + changesType: SchemaChangesConstructor, + change: ISchemaChange, + changeKey: string, + ) { if (changes.has(changeKey)) { const existingChanges = changes.get(changeKey); existingChanges!.addChange(change); @@ -284,34 +316,54 @@ export class SchemaChanges extends BaseSchemaChanges { } /** Gets the MissingSchemaReferences collection. */ - public get missingSchemaReferences(): SchemaReferenceMissing[] { return this._missingSchemaReferences; } + public get missingSchemaReferences(): SchemaReferenceMissing[] { + return this._missingSchemaReferences; + } /** Gets the SchemaReferenceChange collection. */ - public get schemaReferenceDeltas(): SchemaReferenceDelta[] { return this._schemaReferenceDeltas; } + public get schemaReferenceDeltas(): SchemaReferenceDelta[] { + return this._schemaReferenceDeltas; + } /** Gets the CustomAttributeContainerChanges Map. */ - public get customAttributeChanges(): Map { return this._customAttributeChanges; } + public get customAttributeChanges(): Map { + return this._customAttributeChanges; + } /** Gets the ClassChanges Map. */ - public get classChanges(): Map { return this._classChanges; } + public get classChanges(): Map { + return this._classChanges; + } /** Gets the EntityClassChanges Map. */ - public get entityClassChanges(): Map { return this._entityClassChanges; } + public get entityClassChanges(): Map { + return this._entityClassChanges; + } /** Gets the RelationshipClassChanges Map. */ - public get relationshipClassChanges(): Map { return this._relationshipClassChanges; } + public get relationshipClassChanges(): Map { + return this._relationshipClassChanges; + } /** Gets the SchemaItemChanges Map. */ - public get schemaItemChanges(): Map { return this._schemaItemChanges; } + public get schemaItemChanges(): Map { + return this._schemaItemChanges; + } /** Gets the EnumerationChanges Map. */ - public get enumerationChanges(): Map { return this._enumerationChanges; } + public get enumerationChanges(): Map { + return this._enumerationChanges; + } /** Gets the KindOfQuantityChanges Map. */ - public get kindOfQuantityChanges(): Map { return this._kindOfQuantityChanges; } + public get kindOfQuantityChanges(): Map { + return this._kindOfQuantityChanges; + } /** Gets the FormatChanges Map. */ - public get formatChanges(): Map { return this._formatChanges; } + public get formatChanges(): Map { + return this._formatChanges; + } /** Gets all the change diagnostics that have been added to instance. */ public get allDiagnostics(): AnyDiagnostic[] { @@ -352,7 +404,12 @@ export class SchemaChanges extends BaseSchemaChanges { } if (this.isCAContainerChangeForThis(change.diagnostic, schemaName)) { - this.addChangeToMap(this.customAttributeChanges, CustomAttributeContainerChanges, change, (change as CustomAttributeContainerChange).changeKey); + this.addChangeToMap( + this.customAttributeChanges, + CustomAttributeContainerChanges, + change, + (change as CustomAttributeContainerChange).changeKey, + ); return; } @@ -1023,7 +1080,9 @@ export class FormatUnitChanges extends BaseSchemaChanges { * @alpha */ export abstract class SchemaItemChange extends BaseSchemaChange { - public get topLevelSchemaItem(): Schema | SchemaItem { return this.diagnostic.ecDefinition as SchemaItem; } + public get topLevelSchemaItem(): Schema | SchemaItem { + return this.diagnostic.ecDefinition as SchemaItem; + } } /** @@ -1032,10 +1091,14 @@ export abstract class SchemaItemChange extends BaseSchemaChange { */ export class SchemaReferenceMissing extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem or Schema (if a schema change) that this change ultimately belongs to. */ - public get topLevelSchemaItem(): Schema | SchemaItem { return this.diagnostic.ecDefinition as Schema; } + public get topLevelSchemaItem(): Schema | SchemaItem { + return this.diagnostic.ecDefinition as Schema; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1050,10 +1113,14 @@ export class SchemaReferenceMissing extends BaseSchemaChange { */ export class SchemaReferenceDelta extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Delta; } + public get defaultChangeType(): ChangeType { + return ChangeType.Delta; + } /** Gets the SchemaItem or Schema (if a schema change) that this change ultimately belongs to. */ - public get topLevelSchemaItem(): Schema | SchemaItem { return this.diagnostic.ecDefinition as Schema; } + public get topLevelSchemaItem(): Schema | SchemaItem { + return this.diagnostic.ecDefinition as Schema; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1070,7 +1137,9 @@ export class SchemaReferenceDelta extends BaseSchemaChange { */ export class SchemaItemMissing extends SchemaItemChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1085,7 +1154,6 @@ export class SchemaItemMissing extends SchemaItemChange { * @alpha */ export class PropertyValueChange extends BaseSchemaChange { - /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { if (SchemaItem.isSchemaItem(this.diagnostic.ecDefinition)) @@ -1104,7 +1172,9 @@ export class PropertyValueChange extends BaseSchemaChange { } /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Delta; } + public get defaultChangeType(): ChangeType { + return ChangeType.Delta; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1124,7 +1194,9 @@ export class PropertyValueChange extends BaseSchemaChange { */ export class CustomAttributeContainerChange extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1160,7 +1232,9 @@ export class CustomAttributeContainerChange extends BaseSchemaChange { */ export class BaseClassDelta extends SchemaItemChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Delta; } + public get defaultChangeType(): ChangeType { + return ChangeType.Delta; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1181,7 +1255,9 @@ export class PropertyMissing extends BaseSchemaChange { } /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets a string representation of the change. */ public toString(): string { @@ -1195,7 +1271,9 @@ export class PropertyMissing extends BaseSchemaChange { */ export class RelationshipConstraintClassChange extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1215,7 +1293,9 @@ export class RelationshipConstraintClassChange extends BaseSchemaChange { */ export class EnumeratorDelta extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Delta; } + public get defaultChangeType(): ChangeType { + return ChangeType.Delta; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1245,7 +1325,9 @@ export class EnumeratorDelta extends BaseSchemaChange { */ export class EnumeratorMissing extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1269,7 +1351,9 @@ export class EnumeratorMissing extends BaseSchemaChange { */ export class EntityMixinChange extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1293,7 +1377,9 @@ export class EntityMixinChange extends BaseSchemaChange { */ export class PresentationUnitChange extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1324,7 +1410,9 @@ export class PresentationUnitChange extends BaseSchemaChange { */ export class FormatUnitChange extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Missing; } + public get defaultChangeType(): ChangeType { + return ChangeType.Missing; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { @@ -1355,7 +1443,9 @@ export class FormatUnitChange extends BaseSchemaChange { */ export class UnitLabelOverrideDelta extends BaseSchemaChange { /** Gets the default ChangeType (Delta or Missing) for this change */ - public get defaultChangeType(): ChangeType { return ChangeType.Delta; } + public get defaultChangeType(): ChangeType { + return ChangeType.Delta; + } /** Gets the SchemaItem that this change ultimately belongs to. */ public get topLevelSchemaItem(): Schema | SchemaItem { diff --git a/core/ecschema-editing/src/Validation/SchemaCompareDiagnostics.ts b/core/ecschema-editing/src/Validation/SchemaCompareDiagnostics.ts index 61f24cd18db0..45e56e73775e 100644 --- a/core/ecschema-editing/src/Validation/SchemaCompareDiagnostics.ts +++ b/core/ecschema-editing/src/Validation/SchemaCompareDiagnostics.ts @@ -6,13 +6,32 @@ * @module Comparison */ -import { AnyClass, AnyEnumerator, Constant, CustomAttribute, CustomAttributeClass, EntityClass, - Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, OverrideFormat, PropertyCategory, - RelationshipClass, Schema, SchemaItem, Unit, +import { + AnyClass, + AnyEnumerator, + Constant, + CustomAttribute, + CustomAttributeClass, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + OverrideFormat, + PropertyCategory, + RelationshipClass, + Schema, + SchemaItem, + Unit, } from "@itwin/ecschema-metadata"; import { - createClassDiagnosticClass, createCustomAttributeContainerDiagnosticClass, createPropertyDiagnosticClass, - createRelationshipConstraintDiagnosticClass, createSchemaDiagnosticClass, createSchemaItemDiagnosticClass, + createClassDiagnosticClass, + createCustomAttributeContainerDiagnosticClass, + createPropertyDiagnosticClass, + createRelationshipConstraintDiagnosticClass, + createSchemaDiagnosticClass, + createSchemaItemDiagnosticClass, } from "./Diagnostic"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -98,13 +117,22 @@ export const SchemaCompareDiagnostics = { RelationshipConstraintDelta: createRelationshipConstraintDiagnosticClass<[string, any, any]>(SchemaCompareCodes.RelationshipConstraintDelta, ""), /** Required message parameters: constraint class */ - RelationshipConstraintClassMissing: createRelationshipConstraintDiagnosticClass<[AnyClass]>(SchemaCompareCodes.RelationshipConstraintClassMissing, ""), + RelationshipConstraintClassMissing: createRelationshipConstraintDiagnosticClass<[AnyClass]>( + SchemaCompareCodes.RelationshipConstraintClassMissing, + "", + ), /** Required message parameters: property name, property A value, property B value */ - CustomAttributeClassDelta: createSchemaItemDiagnosticClass(SchemaCompareCodes.CustomAttributeClassDelta, ""), + CustomAttributeClassDelta: createSchemaItemDiagnosticClass( + SchemaCompareCodes.CustomAttributeClassDelta, + "", + ), /** Required message parameters: CustomAttributeClass name */ - CustomAttributeInstanceClassMissing: createCustomAttributeContainerDiagnosticClass<[CustomAttribute]>(SchemaCompareCodes.CustomAttributeInstanceClassMissing, ""), + CustomAttributeInstanceClassMissing: createCustomAttributeContainerDiagnosticClass<[CustomAttribute]>( + SchemaCompareCodes.CustomAttributeInstanceClassMissing, + "", + ), /** Required message parameters: property name, property A value, property B value */ EnumerationDelta: createSchemaItemDiagnosticClass(SchemaCompareCodes.EnumerationDelta, ""), @@ -131,7 +159,10 @@ export const SchemaCompareDiagnostics = { FormatUnitMissing: createSchemaItemDiagnosticClass(SchemaCompareCodes.FormatUnitMissing, ""), /** Required message parameters: Unit or InvertedUnit, label A, label B */ - UnitLabelOverrideDelta: createSchemaItemDiagnosticClass(SchemaCompareCodes.UnitLabelOverrideDelta, ""), + UnitLabelOverrideDelta: createSchemaItemDiagnosticClass( + SchemaCompareCodes.UnitLabelOverrideDelta, + "", + ), /** Required message parameters: property name, property A value, property B value */ UnitDelta: createSchemaItemDiagnosticClass(SchemaCompareCodes.UnitDelta, ""), diff --git a/core/ecschema-editing/src/Validation/SchemaCompareResultDelegate.ts b/core/ecschema-editing/src/Validation/SchemaCompareResultDelegate.ts index 82bf62a235d7..fbf029710725 100644 --- a/core/ecschema-editing/src/Validation/SchemaCompareResultDelegate.ts +++ b/core/ecschema-editing/src/Validation/SchemaCompareResultDelegate.ts @@ -6,10 +6,28 @@ * @module Comparison */ -import { AnyClass, AnyEnumerator, AnyProperty, Constant, CustomAttribute, - CustomAttributeClass, CustomAttributeContainerProps, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, - Mixin, OverrideFormat, Phenomenon, PropertyCategory, RelationshipClass, RelationshipConstraint, - Schema, SchemaItem, Unit, +import { + AnyClass, + AnyEnumerator, + AnyProperty, + Constant, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + OverrideFormat, + Phenomenon, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + Unit, } from "@itwin/ecschema-metadata"; import { AnyDiagnostic } from "./Diagnostic"; import { SchemaChanges } from "./SchemaChanges"; @@ -56,7 +74,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Schema. * @param valueB The value from the second Schema. */ - public async reportSchemaDelta(schemaA: Schema, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportSchemaDelta( + schemaA: Schema, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.SchemaDelta(schemaA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -76,7 +100,13 @@ export class SchemaCompareResultDelegate { * @param schemaA The first Schema supplied for comparison. * @param referenceSchema The missing schema reference. */ - public async reportSchemaReferenceDelta(schemaA: Schema, referenceSchema: Schema, versionA: string, versionB: string, _compareDirection: SchemaCompareDirection): Promise { + public async reportSchemaReferenceDelta( + schemaA: Schema, + referenceSchema: Schema, + versionA: string, + versionB: string, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.SchemaReferenceDelta(schemaA, [referenceSchema, versionA, versionB]); await this.reportDiagnostic(diag); } @@ -97,7 +127,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first SchemaItem. * @param valueB The value from the second SchemaItem. */ - public async reportSchemaItemDelta(schemaItemA: SchemaItem, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportSchemaItemDelta( + schemaItemA: SchemaItem, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.SchemaItemDelta(schemaItemA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -109,7 +145,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first ECClass. * @param valueB The value from the second ECClass. */ - public async reportClassDelta(classA: AnyClass, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportClassDelta( + classA: AnyClass, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.ClassDelta(classA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -120,7 +162,12 @@ export class SchemaCompareResultDelegate { * @param baseClassA The base class of the first ECClass. * @param baseClassB The base class of the second ECClass. */ - public async reportBaseClassDelta(classA: AnyClass, baseClassA: AnyClass | undefined, baseClassB: AnyClass | undefined, _compareDirection: SchemaCompareDirection): Promise { + public async reportBaseClassDelta( + classA: AnyClass, + baseClassA: AnyClass | undefined, + baseClassB: AnyClass | undefined, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.BaseClassDelta(classA, [baseClassA, baseClassB]); await this.reportDiagnostic(diag); } @@ -132,7 +179,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first ECProperty. * @param valueB The value from the second ECProperty. */ - public async reportPropertyDelta(propertyA: AnyProperty, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportPropertyDelta( + propertyA: AnyProperty, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.PropertyDelta(propertyA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -163,7 +216,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Mixin. * @param valueB The value from the second Mixin. */ - public async reportMixinDelta(mixinA: Mixin, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportMixinDelta( + mixinA: Mixin, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.MixinDelta(mixinA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -175,7 +234,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first RelationshipClass. * @param valueB The value from the second RelationshipClass. */ - public async reportRelationshipClassDelta(relationshipClassA: RelationshipClass, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportRelationshipClassDelta( + relationshipClassA: RelationshipClass, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.RelationshipDelta(relationshipClassA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -187,7 +252,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first RelationshipConstraint. * @param valueB The value from the second RelationshipConstraint. */ - public async reportRelationshipConstraintDelta(constraintA: RelationshipConstraint, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportRelationshipConstraintDelta( + constraintA: RelationshipConstraint, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.RelationshipConstraintDelta(constraintA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -197,7 +268,11 @@ export class SchemaCompareResultDelegate { * @param constraintA The first RelationshipConstraint that is missing the class constraint. * @param constraintClass The constraint ECClass from the first RelationshipConstraint. */ - public async reportRelationshipConstraintClassMissing(constraintA: RelationshipConstraint, constraintClass: EntityClass | Mixin | RelationshipClass, _compareDirection: SchemaCompareDirection): Promise { + public async reportRelationshipConstraintClassMissing( + constraintA: RelationshipConstraint, + constraintClass: EntityClass | Mixin | RelationshipClass, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.RelationshipConstraintClassMissing(constraintA, [constraintClass]); await this.reportDiagnostic(diag); } @@ -209,7 +284,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first CustomAttributeClass. * @param valueB The value from the second CustomAttributeClass. */ - public async reportCustomAttributeClassDelta(customAttributeA: CustomAttributeClass, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportCustomAttributeClassDelta( + customAttributeA: CustomAttributeClass, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.CustomAttributeClassDelta(customAttributeA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -219,7 +300,11 @@ export class SchemaCompareResultDelegate { * @param customAttributeContainerA The first CustomAttribute container that is missing the CustomAttribute instance. * @param customAttribute The CustomAttribute missing. */ - public async reportCustomAttributeInstanceClassMissing(customAttributeContainerA: CustomAttributeContainerProps, customAttribute: CustomAttribute, _compareDirection: SchemaCompareDirection): Promise { + public async reportCustomAttributeInstanceClassMissing( + customAttributeContainerA: CustomAttributeContainerProps, + customAttribute: CustomAttribute, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.CustomAttributeInstanceClassMissing(customAttributeContainerA, [customAttribute]); await this.reportDiagnostic(diag); } @@ -231,7 +316,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Enumeration. * @param valueB The value from the second Enumeration. */ - public async reportEnumerationDelta(enumerationA: Enumeration, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportEnumerationDelta( + enumerationA: Enumeration, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.EnumerationDelta(enumerationA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -241,7 +332,11 @@ export class SchemaCompareResultDelegate { * @param enumerationA The first Enumeration that is missing the enumerator. * @param enumerator The enumerator missing from the second schema. */ - public async reportEnumeratorMissing(enumerationA: Enumeration, enumerator: AnyEnumerator, _compareDirection: SchemaCompareDirection): Promise { + public async reportEnumeratorMissing( + enumerationA: Enumeration, + enumerator: AnyEnumerator, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.EnumeratorMissing(enumerationA, [enumerator]); await this.reportDiagnostic(diag); } @@ -254,7 +349,14 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first enumerator. * @param valueB The value from the second enumerator. */ - public async reportEnumeratorDelta(enumerationA: Enumeration, enumerator: AnyEnumerator, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportEnumeratorDelta( + enumerationA: Enumeration, + enumerator: AnyEnumerator, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.EnumeratorDelta(enumerationA, [enumerator, propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -266,7 +368,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first KindOfQuantity. * @param valueB The value from the second KindOfQuantity. */ - public async reportKoqDelta(koqA: KindOfQuantity, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportKoqDelta( + koqA: KindOfQuantity, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.KoqDelta(koqA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -276,7 +384,11 @@ export class SchemaCompareResultDelegate { * @param koqA The first KindOfQuantity that is missing the presentation unit. * @param unit The Format or OverrideFormat presentation unit missing from the second schema. */ - public async reportPresentationUnitMissing(koqA: KindOfQuantity, unit: Format | OverrideFormat, _compareDirection: SchemaCompareDirection): Promise { + public async reportPresentationUnitMissing( + koqA: KindOfQuantity, + unit: Format | OverrideFormat, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.PresentationUnitMissing(koqA, [unit]); await this.reportDiagnostic(diag); } @@ -288,7 +400,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first PropertyCategory. * @param valueB The value from the second PropertyCategory. */ - public async reportPropertyCategoryDelta(categoryA: PropertyCategory, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportPropertyCategoryDelta( + categoryA: PropertyCategory, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.PropertyCategoryDelta(categoryA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -300,7 +418,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Format. * @param valueB The value from the second Format. */ - public async reportFormatDelta(formatA: Format, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportFormatDelta( + formatA: Format, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.FormatDelta(formatA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -322,7 +446,13 @@ export class SchemaCompareResultDelegate { * @param labelA The value from the first label. * @param labelB The value from the second label. */ - public async reportUnitLabelOverrideDelta(formatA: Format, unit: Unit | InvertedUnit, labelA: string | undefined, labelB: string | undefined, _compareDirection: SchemaCompareDirection): Promise { + public async reportUnitLabelOverrideDelta( + formatA: Format, + unit: Unit | InvertedUnit, + labelA: string | undefined, + labelB: string | undefined, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.UnitLabelOverrideDelta(formatA, [unit, labelA, labelB]); await this.reportDiagnostic(diag); } @@ -334,7 +464,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Unit. * @param valueB The value from the second Unit. */ - public async reportUnitDelta(unitA: Unit, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportUnitDelta( + unitA: Unit, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.UnitDelta(unitA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -346,7 +482,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first InvertedUnit. * @param valueB The value from the second InvertedUnit. */ - public async reportInvertedUnitDelta(invertedUnitA: InvertedUnit, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportInvertedUnitDelta( + invertedUnitA: InvertedUnit, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.InvertedUnitDelta(invertedUnitA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -358,7 +500,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Phenomenon. * @param valueB The value from the second Phenomenon. */ - public async reportPhenomenonDelta(phenomenonA: Phenomenon, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportPhenomenonDelta( + phenomenonA: Phenomenon, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.PhenomenonDelta(phenomenonA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } @@ -370,7 +518,13 @@ export class SchemaCompareResultDelegate { * @param valueA The value from the first Constant. * @param valueB The value from the second Constant. */ - public async reportConstantDelta(constantA: Constant, propertyName: string, valueA: any, valueB: any, _compareDirection: SchemaCompareDirection): Promise { + public async reportConstantDelta( + constantA: Constant, + propertyName: string, + valueA: any, + valueB: any, + _compareDirection: SchemaCompareDirection, + ): Promise { const diag = new SchemaCompareDiagnostics.ConstantDelta(constantA, [propertyName, valueA, valueB]); await this.reportDiagnostic(diag); } diff --git a/core/ecschema-editing/src/Validation/SchemaCompareVisitor.ts b/core/ecschema-editing/src/Validation/SchemaCompareVisitor.ts index f558a816a8a6..7f4666a848f2 100644 --- a/core/ecschema-editing/src/Validation/SchemaCompareVisitor.ts +++ b/core/ecschema-editing/src/Validation/SchemaCompareVisitor.ts @@ -6,10 +6,31 @@ * @module Comparison */ -import { AnyClass, AnyProperty, Constant, CustomAttributeClass, CustomAttributeContainerProps, - ECClass, EntityClass, Enumeration, Format, InvertedUnit, ISchemaPartVisitor, KindOfQuantity, Mixin, - Phenomenon, Property, PropertyCategory, RelationshipClass, RelationshipConstraint, Schema, SchemaItem, - SchemaItemType, StructClass, Unit, UnitSystem, +import { + AnyClass, + AnyProperty, + Constant, + CustomAttributeClass, + CustomAttributeContainerProps, + ECClass, + EntityClass, + Enumeration, + Format, + InvertedUnit, + ISchemaPartVisitor, + KindOfQuantity, + Mixin, + Phenomenon, + Property, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + SchemaItemType, + StructClass, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; import { ISchemaComparer } from "./SchemaComparer"; @@ -66,7 +87,7 @@ export class SchemaCompareVisitor implements ISchemaPartVisitor { let propertyB: AnyProperty | undefined; const classB = await this._schemaB.lookupItem(propertyA.class.name); - if (classB && propertyA.class.schemaItemType === classB.schemaItemType){ + if (classB && propertyA.class.schemaItemType === classB.schemaItemType) { propertyB = await classB.getProperty(propertyA.name) as AnyProperty; this._schemaComparer.compareProperties(propertyA, propertyB); } diff --git a/core/ecschema-editing/src/Validation/SchemaComparer.ts b/core/ecschema-editing/src/Validation/SchemaComparer.ts index 2e41e89fc18b..d0d6e8ea2f01 100644 --- a/core/ecschema-editing/src/Validation/SchemaComparer.ts +++ b/core/ecschema-editing/src/Validation/SchemaComparer.ts @@ -6,13 +6,37 @@ * @module Comparison */ +import { formatTraitsToArray, formatTypeToString, scientificTypeToString, showSignOptionToString } from "@itwin/core-quantity"; import { - AnyClass, AnyEnumerator, AnyProperty, classModifierToString, Constant, containerTypeToString, CustomAttribute, CustomAttributeClass, - CustomAttributeContainerProps, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, OverrideFormat, Phenomenon, - primitiveTypeToString, PropertyCategory, propertyTypeToString, RelationshipClass, RelationshipConstraint, Schema, - SchemaItem, SchemaItemKey, strengthDirectionToString, strengthToString, Unit, + AnyClass, + AnyEnumerator, + AnyProperty, + classModifierToString, + Constant, + containerTypeToString, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + OverrideFormat, + Phenomenon, + primitiveTypeToString, + PropertyCategory, + propertyTypeToString, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + SchemaItemKey, + strengthDirectionToString, + strengthToString, + Unit, } from "@itwin/ecschema-metadata"; -import { formatTraitsToArray, formatTypeToString, scientificTypeToString, showSignOptionToString } from "@itwin/core-quantity"; import { ISchemaCompareReporter } from "./SchemaCompareReporter"; import { SchemaCompareResultDelegate } from "./SchemaCompareResultDelegate"; import { SchemaCompareVisitor } from "./SchemaCompareVisitor"; @@ -111,14 +135,24 @@ export class SchemaComparer { if (!refB) promises.push(this._reporter.reportSchemaReferenceMissing(schemaA, ref, this._compareDirection)); else if (!refB.schemaKey.matches(ref.schemaKey)) - promises.push(this._reporter.reportSchemaReferenceDelta(schemaA, ref, ref.schemaKey.version.toString(), refB.schemaKey.version.toString(), this._compareDirection)); + promises.push( + this._reporter.reportSchemaReferenceDelta( + schemaA, + ref, + ref.schemaKey.version.toString(), + refB.schemaKey.version.toString(), + this._compareDirection, + ), + ); } if (this._compareDirection === SchemaCompareDirection.Backward) return; if (schemaA.schemaKey.toString() !== schemaB.schemaKey.toString()) - promises.push(this._reporter.reportSchemaDelta(schemaA, "schemaKey", schemaA.schemaKey.toString(), schemaB.schemaKey.toString(), this._compareDirection)); + promises.push( + this._reporter.reportSchemaDelta(schemaA, "schemaKey", schemaA.schemaKey.toString(), schemaB.schemaKey.toString(), this._compareDirection), + ); if (schemaA.alias !== schemaB.alias) promises.push(this._reporter.reportSchemaDelta(schemaA, "alias", schemaA.alias, schemaB.alias, this._compareDirection)); @@ -157,7 +191,9 @@ export class SchemaComparer { } if (schemaItemA.description !== schemaItemB.description) - promises.push(this._reporter.reportSchemaItemDelta(schemaItemA, "description", schemaItemA.description, schemaItemB.description, this._compareDirection)); + promises.push( + this._reporter.reportSchemaItemDelta(schemaItemA, "description", schemaItemA.description, schemaItemB.description, this._compareDirection), + ); if (!labelsMatch(schemaItemA.label, schemaItemB.label)) promises.push(this._reporter.reportSchemaItemDelta(schemaItemA, "label", schemaItemA.label, schemaItemB.label, this._compareDirection)); @@ -228,7 +264,9 @@ export class SchemaComparer { promises.push(this._reporter.reportPropertyDelta(propertyA, "label", propertyA.label, propertyB.label, this._compareDirection)); if (propertyA.description !== propertyB.description) - promises.push(this._reporter.reportPropertyDelta(propertyA, "description", propertyA.description, propertyB.description, this._compareDirection)); + promises.push( + this._reporter.reportPropertyDelta(propertyA, "description", propertyA.description, propertyB.description, this._compareDirection), + ); if (propertyA.isReadOnly !== propertyB.isReadOnly) promises.push(this._reporter.reportPropertyDelta(propertyA, "isReadOnly", propertyA.isReadOnly, propertyB.isReadOnly, this._compareDirection)); @@ -250,7 +288,12 @@ export class SchemaComparer { const koqKeyA = propertyA.kindOfQuantity?.fullName; const koqKeyB = propertyB.kindOfQuantity?.fullName; if (koqKeyA !== koqKeyB) { - const areSameByName = this.areItemsSameByName(propertyA.kindOfQuantity, propertyB.kindOfQuantity, propertyA.schema.name, propertyB.schema.name); + const areSameByName = this.areItemsSameByName( + propertyA.kindOfQuantity, + propertyB.kindOfQuantity, + propertyA.schema.name, + propertyB.schema.name, + ); if (!areSameByName) promises.push(this._reporter.reportPropertyDelta(propertyA, "kindOfQuantity", koqKeyA, koqKeyB, this._compareDirection)); } @@ -315,7 +358,9 @@ export class SchemaComparer { if (relationshipA.strengthDirection !== relationshipB.strengthDirection) { const directionAString = strengthDirectionToString(relationshipA.strengthDirection); const directionBString = strengthDirectionToString(relationshipB.strengthDirection); - promises.push(this._reporter.reportRelationshipClassDelta(relationshipA, "strengthDirection", directionAString, directionBString, this._compareDirection)); + promises.push( + this._reporter.reportRelationshipClassDelta(relationshipA, "strengthDirection", directionAString, directionBString, this._compareDirection), + ); } await Promise.all(promises); @@ -331,8 +376,13 @@ export class SchemaComparer { if (constraintA.constraintClasses) { for (const classA of constraintA.constraintClasses) { - if (!constraintB.constraintClasses || -1 === constraintB.constraintClasses.findIndex((classB) => - this.areItemsSameByName(classA, classB, constraintA.schema.name, constraintB.schema.name))) + if ( + !constraintB.constraintClasses || + -1 === + constraintB.constraintClasses.findIndex((classB) => + this.areItemsSameByName(classA, classB, constraintA.schema.name, constraintB.schema.name) + ) + ) promises.push(this._reporter.reportRelationshipConstraintClassMissing(constraintA, await classA, this._compareDirection)); } } @@ -346,22 +396,47 @@ export class SchemaComparer { const multiplicityA = constraintA.multiplicity.toString(); const multiplicityB = constraintB.multiplicity.toString(); if (multiplicityA !== multiplicityB) - promises.push(this._reporter.reportRelationshipConstraintDelta(constraintA, "multiplicity", multiplicityA, multiplicityB, this._compareDirection)); + promises.push( + this._reporter.reportRelationshipConstraintDelta(constraintA, "multiplicity", multiplicityA, multiplicityB, this._compareDirection), + ); } if (constraintA.roleLabel !== constraintB.roleLabel) - promises.push(this._reporter.reportRelationshipConstraintDelta(constraintA, "roleLabel", constraintA.roleLabel, constraintB.roleLabel, this._compareDirection)); + promises.push( + this._reporter.reportRelationshipConstraintDelta( + constraintA, + "roleLabel", + constraintA.roleLabel, + constraintB.roleLabel, + this._compareDirection, + ), + ); if (constraintA.polymorphic !== constraintB.polymorphic) - promises.push(this._reporter.reportRelationshipConstraintDelta(constraintA, "polymorphic", constraintA.polymorphic, constraintB.polymorphic, this._compareDirection)); + promises.push( + this._reporter.reportRelationshipConstraintDelta( + constraintA, + "polymorphic", + constraintA.polymorphic, + constraintB.polymorphic, + this._compareDirection, + ), + ); if (constraintA.abstractConstraint || constraintB.abstractConstraint) { const abstractA = constraintA.abstractConstraint?.fullName; const abstractB = constraintB.abstractConstraint?.fullName; if (abstractA !== abstractB) { - const areSameByName = this.areItemsSameByName(constraintA.abstractConstraint, constraintB.abstractConstraint, constraintA.schema.name, constraintB.schema.name); + const areSameByName = this.areItemsSameByName( + constraintA.abstractConstraint, + constraintB.abstractConstraint, + constraintA.schema.name, + constraintB.schema.name, + ); if (!areSameByName) { - promises.push(this._reporter.reportRelationshipConstraintDelta(constraintA, "abstractConstraint", abstractA, abstractB, this._compareDirection)); + promises.push( + this._reporter.reportRelationshipConstraintDelta(constraintA, "abstractConstraint", abstractA, abstractB, this._compareDirection), + ); } } } @@ -374,7 +449,10 @@ export class SchemaComparer { * @param customAttributeClassA * @param customAttributeClassB */ - public async compareCustomAttributeClasses(customAttributeClassA: CustomAttributeClass, customAttributeClassB: CustomAttributeClass): Promise { + public async compareCustomAttributeClasses( + customAttributeClassA: CustomAttributeClass, + customAttributeClassB: CustomAttributeClass, + ): Promise { if (this._compareDirection === SchemaCompareDirection.Backward) return; @@ -529,19 +607,27 @@ export class SchemaComparer { } if (formatA.decimalSeparator !== formatB.decimalSeparator) - promises.push(this._reporter.reportFormatDelta(formatA, "decimalSeparator", formatA.decimalSeparator, formatB.decimalSeparator, this._compareDirection)); + promises.push( + this._reporter.reportFormatDelta(formatA, "decimalSeparator", formatA.decimalSeparator, formatB.decimalSeparator, this._compareDirection), + ); if (formatA.thousandSeparator !== formatB.thousandSeparator) - promises.push(this._reporter.reportFormatDelta(formatA, "thousandSeparator", formatA.thousandSeparator, formatB.thousandSeparator, this._compareDirection)); + promises.push( + this._reporter.reportFormatDelta(formatA, "thousandSeparator", formatA.thousandSeparator, formatB.thousandSeparator, this._compareDirection), + ); if (formatA.uomSeparator !== formatB.uomSeparator) promises.push(this._reporter.reportFormatDelta(formatA, "uomSeparator", formatA.uomSeparator, formatB.uomSeparator, this._compareDirection)); if (formatA.stationSeparator !== formatB.stationSeparator) - promises.push(this._reporter.reportFormatDelta(formatA, "stationSeparator", formatA.stationSeparator, formatB.stationSeparator, this._compareDirection)); + promises.push( + this._reporter.reportFormatDelta(formatA, "stationSeparator", formatA.stationSeparator, formatB.stationSeparator, this._compareDirection), + ); if (formatA.stationOffsetSize !== formatB.stationOffsetSize) - promises.push(this._reporter.reportFormatDelta(formatA, "stationOffsetSize", formatA.stationOffsetSize, formatB.stationOffsetSize, this._compareDirection)); + promises.push( + this._reporter.reportFormatDelta(formatA, "stationOffsetSize", formatA.stationOffsetSize, formatB.stationOffsetSize, this._compareDirection), + ); if (formatA.formatTraits !== formatB.formatTraits) { const traitsA = formatTraitsToArray(formatA.formatTraits); @@ -619,7 +705,12 @@ export class SchemaComparer { const fullNameA = invertedUnitA.invertsUnit?.fullName; const fullNameB = invertedUnitB.invertsUnit?.fullName; if (fullNameA !== fullNameB) { - const eqByName = this.areItemsSameByName(invertedUnitA.invertsUnit, invertedUnitB.invertsUnit, invertedUnitA.schema.name, invertedUnitB.schema.name); + const eqByName = this.areItemsSameByName( + invertedUnitA.invertsUnit, + invertedUnitB.invertsUnit, + invertedUnitA.schema.name, + invertedUnitB.schema.name, + ); if (!eqByName) promises.push(this._reporter.reportInvertedUnitDelta(invertedUnitA, "invertsUnit", fullNameA, fullNameB, this._compareDirection)); } @@ -629,7 +720,12 @@ export class SchemaComparer { const fullNameA = invertedUnitA.unitSystem?.fullName; const fullNameB = invertedUnitB.unitSystem?.fullName; if (fullNameA !== fullNameB) { - const eqByName = this.areItemsSameByName(invertedUnitA.unitSystem, invertedUnitB.unitSystem, invertedUnitA.schema.name, invertedUnitB.schema.name); + const eqByName = this.areItemsSameByName( + invertedUnitA.unitSystem, + invertedUnitB.unitSystem, + invertedUnitA.schema.name, + invertedUnitB.schema.name, + ); if (!eqByName) promises.push(this._reporter.reportInvertedUnitDelta(invertedUnitA, "unitSystem", fullNameA, fullNameB, this._compareDirection)); } @@ -679,7 +775,9 @@ export class SchemaComparer { promises.push(this._reporter.reportConstantDelta(constantA, "numerator", constantA.numerator, constantB.numerator, this._compareDirection)); if (constantA.denominator !== constantB.denominator) - promises.push(this._reporter.reportConstantDelta(constantA, "denominator", constantA.denominator, constantB.denominator, this._compareDirection)); + promises.push( + this._reporter.reportConstantDelta(constantA, "denominator", constantA.denominator, constantB.denominator, this._compareDirection), + ); await Promise.all(promises); } @@ -725,9 +823,14 @@ export class SchemaComparer { const relationshipClassB = propertyB.isNavigation() ? propertyB.relationshipClass : undefined; const relA = propertyA.relationshipClass.fullName; const relB = relationshipClassB ? relationshipClassB.fullName : undefined; - if (relA !== relB){ - const areSameByName = this.areItemsSameByName(propertyA.relationshipClass, relationshipClassB, propertyA.schema.name, propertyB.schema.name); - if(!areSameByName) + if (relA !== relB) { + const areSameByName = this.areItemsSameByName( + propertyA.relationshipClass, + relationshipClassB, + propertyA.schema.name, + propertyB.schema.name, + ); + if (!areSameByName) promises.push(this._reporter.reportPropertyDelta(propertyA, "relationshipClass", relA, relB, this._compareDirection)); } } @@ -764,7 +867,9 @@ export class SchemaComparer { const extendedTypeNameB = propertyB.isPrimitive() ? propertyB.extendedTypeName : undefined; if (propertyA.extendedTypeName !== extendedTypeNameB) { - promises.push(this._reporter.reportPropertyDelta(propertyA, "extendedTypeName", propertyA.extendedTypeName, extendedTypeNameB, this._compareDirection)); + promises.push( + this._reporter.reportPropertyDelta(propertyA, "extendedTypeName", propertyA.extendedTypeName, extendedTypeNameB, this._compareDirection), + ); } } @@ -790,7 +895,16 @@ export class SchemaComparer { const promises: Array> = []; if (enumeratorA.description !== enumeratorB.description) - promises.push(this._reporter.reportEnumeratorDelta(enumA, enumeratorA, "description", enumeratorA.description, enumeratorB.description, this._compareDirection)); + promises.push( + this._reporter.reportEnumeratorDelta( + enumA, + enumeratorA, + "description", + enumeratorA.description, + enumeratorB.description, + this._compareDirection, + ), + ); if (!labelsMatch(enumeratorA.label, enumeratorB.label)) promises.push(this._reporter.reportEnumeratorDelta(enumA, enumeratorA, "label", enumeratorA.label, enumeratorB.label, this._compareDirection)); @@ -809,7 +923,9 @@ export class SchemaComparer { const promises: Array> = []; for (const unitA of formatA.units) { - const unitB = formatB.units ? formatB.units.find((u) => this.areItemsSameByName(unitA[0], u[0], formatA.schema.name, formatB.schema.name)) : undefined; + const unitB = formatB.units + ? formatB.units.find((u) => this.areItemsSameByName(unitA[0], u[0], formatA.schema.name, formatB.schema.name)) + : undefined; if (!unitB) { promises.push(this._reporter.reportFormatUnitMissing(formatA, unitA[0], this._compareDirection)); continue; @@ -832,13 +948,17 @@ export class SchemaComparer { itemKeyA: Format | OverrideFormat, itemKeyB: Format | OverrideFormat, topLevelSchemaNameA: string, - topLevelSchemaNameB: string | undefined ): boolean { - + topLevelSchemaNameB: string | undefined, + ): boolean { if (itemKeyA.units) { for (const unitA of itemKeyA.units) { - if (!itemKeyB.units - || -1 === itemKeyB.units.findIndex((unitB) => this.areItemsSameByName(unitA[0], unitB[0], topLevelSchemaNameA, topLevelSchemaNameB) - && unitA[1] === unitB[1])) + if ( + !itemKeyB.units + || -1 === itemKeyB.units.findIndex((unitB) => + this.areItemsSameByName(unitA[0], unitB[0], topLevelSchemaNameA, topLevelSchemaNameB) + && unitA[1] === unitB[1] + ) + ) return false; } } @@ -861,8 +981,8 @@ export class SchemaComparer { itemKeyA: Readonly | SchemaItem | undefined, itemKeyB: Readonly | SchemaItem | undefined, topLevelSchemaNameA: string, - topLevelSchemaNameB: string | undefined ): boolean { - + topLevelSchemaNameB: string | undefined, + ): boolean { const nameA = itemKeyA ? itemKeyA.name.toUpperCase() : undefined; const nameB = itemKeyB ? itemKeyB.name.toUpperCase() : undefined; @@ -878,7 +998,8 @@ export class SchemaComparer { : itemKeyB.schemaName : undefined; - return (nameA === nameB && schemaNameA === topLevelSchemaNameA && schemaNameB === topLevelSchemaNameB) || (nameA === nameB && schemaNameA === schemaNameB); + return (nameA === nameB && schemaNameA === topLevelSchemaNameA && schemaNameB === topLevelSchemaNameB) || + (nameA === nameB && schemaNameA === schemaNameB); } /** @@ -888,7 +1009,11 @@ export class SchemaComparer { * @param containerB container in which to look for classNameA. * @returns true if a same classA is in containerB, otherwise false. */ - private containerHasClass(attributeA: CustomAttribute, containerA: CustomAttributeContainerProps, containerB: CustomAttributeContainerProps): boolean { + private containerHasClass( + attributeA: CustomAttribute, + containerA: CustomAttributeContainerProps, + containerB: CustomAttributeContainerProps, + ): boolean { if (containerB && containerB.customAttributes) { for (const [_className, attributeB] of containerB.customAttributes) { const classItemKeyA = containerA.schema.getSchemaItemKey(attributeA.className); @@ -901,7 +1026,7 @@ export class SchemaComparer { // If propertyName is class name, they don't need to be compared as this has been done // in the areItemsSameByName function. - if(propertyName === "className") + if (propertyName === "className") return true; return deepEquals(valueA, valueB); @@ -920,12 +1045,12 @@ export class SchemaComparer { * @returns true if they are deeply equal, otherwise false. */ function deepEquals(a: unknown, b: unknown): boolean { - if(Array.isArray(a) && Array.isArray(b)) { + if (Array.isArray(a) && Array.isArray(b)) { return a.length === b.length && a.every((value, index) => { return deepEquals(value, b[index]); }); } - if(isObject(a) && isObject(b)) { + if (isObject(a) && isObject(b)) { const propertiesA = Object.keys(a); const propertiesB = Object.keys(b); return propertiesA.length === propertiesB.length && propertiesA.every((propertyName) => { diff --git a/core/ecschema-editing/src/Validation/SchemaValidater.ts b/core/ecschema-editing/src/Validation/SchemaValidater.ts index 2ec3583b942d..f0466a03f08a 100644 --- a/core/ecschema-editing/src/Validation/SchemaValidater.ts +++ b/core/ecschema-editing/src/Validation/SchemaValidater.ts @@ -7,12 +7,12 @@ */ import { ISchemaPartVisitor, Schema } from "@itwin/ecschema-metadata"; +import { AnyDiagnostic } from "./Diagnostic"; +import { IDiagnosticReporter, SuppressionDiagnosticReporter } from "./DiagnosticReporter"; +import { ECRuleSet } from "./ECRules"; import { IRuleSet } from "./Rules"; import { SchemaValidationVisitor } from "./SchemaValidationVisitor"; -import { IDiagnosticReporter, SuppressionDiagnosticReporter } from "./DiagnosticReporter"; -import { AnyDiagnostic } from "./Diagnostic"; import { SchemaWalker } from "./SchemaWalker"; -import { ECRuleSet } from "./ECRules"; class CollectionReporter extends SuppressionDiagnosticReporter { private _diagnostics: AnyDiagnostic[] = []; diff --git a/core/ecschema-editing/src/Validation/SchemaValidationVisitor.ts b/core/ecschema-editing/src/Validation/SchemaValidationVisitor.ts index 023a079a7ede..2db52d430bdd 100644 --- a/core/ecschema-editing/src/Validation/SchemaValidationVisitor.ts +++ b/core/ecschema-editing/src/Validation/SchemaValidationVisitor.ts @@ -6,10 +6,30 @@ * @module Validation */ -import { AnyClass, AnyECType, AnyProperty, Constant, CustomAttribute, CustomAttributeClass, CustomAttributeContainerProps, - EntityClass, Enumeration, Format, InvertedUnit, ISchemaPartVisitor, KindOfQuantity, Mixin, - Phenomenon, PropertyCategory, RelationshipClass, RelationshipConstraint, Schema, SchemaItem, - StructClass, Unit, UnitSystem, +import { + AnyClass, + AnyECType, + AnyProperty, + Constant, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + ISchemaPartVisitor, + KindOfQuantity, + Mixin, + Phenomenon, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + StructClass, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; import { AnyDiagnostic, DiagnosticCategory } from "./Diagnostic"; @@ -540,7 +560,10 @@ export class SchemaValidationVisitor implements ISchemaPartVisitor { } } - private findSuppressionRule(suppressionSet: Array>, code: string): ISuppressionRule | undefined { + private findSuppressionRule( + suppressionSet: Array>, + code: string, + ): ISuppressionRule | undefined { if (!suppressionSet) return; @@ -560,7 +583,11 @@ export class SchemaValidationVisitor implements ISchemaPartVisitor { return ruleSet.schemaExclusionSet.includes(schema.name); } - private async reportDiagnostics(diagnostic: AnyDiagnostic, ecType: T, suppressionMap: Array> | undefined) { + private async reportDiagnostics( + diagnostic: AnyDiagnostic, + ecType: T, + suppressionMap: Array> | undefined, + ) { if (!diagnostic) return; diff --git a/core/ecschema-editing/src/Validation/SchemaWalker.ts b/core/ecschema-editing/src/Validation/SchemaWalker.ts index 835b94459763..468d8e44a5d0 100644 --- a/core/ecschema-editing/src/Validation/SchemaWalker.ts +++ b/core/ecschema-editing/src/Validation/SchemaWalker.ts @@ -3,8 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ECClass, ISchemaPartVisitor, RelationshipClass, Schema, SchemaItem, - SchemaItemType, SchemaPartVisitorDelegate, +import { + ECClass, + ISchemaPartVisitor, + RelationshipClass, + Schema, + SchemaItem, + SchemaItemType, + SchemaPartVisitorDelegate, } from "@itwin/ecschema-metadata"; /** diff --git a/core/ecschema-editing/src/ecschema-editing.ts b/core/ecschema-editing/src/ecschema-editing.ts index 99c5f4d96905..2c9b07d92879 100644 --- a/core/ecschema-editing/src/ecschema-editing.ts +++ b/core/ecschema-editing/src/ecschema-editing.ts @@ -17,7 +17,7 @@ export * from "./Validation/SchemaComparer"; export * from "./Validation/SchemaCompareReporter"; export * from "./Editing/Editor"; export * from "./Editing/Exception"; -export { ISuppressionRule, IRuleSuppressionSet, IRuleSuppressionMap } from "./Validation/RuleSuppressionSet"; +export { IRuleSuppressionMap, IRuleSuppressionSet, ISuppressionRule } from "./Validation/RuleSuppressionSet"; export { SchemaValidater } from "./Validation/SchemaValidater"; export * from "./Differencing/SchemaDifference"; export * from "./Differencing/SchemaConflicts"; diff --git a/core/ecschema-editing/src/test/Differencing/Conflicts.test.ts b/core/ecschema-editing/src/test/Differencing/Conflicts.test.ts index d886c3928e2b..72eb9f5fffe4 100644 --- a/core/ecschema-editing/src/test/Differencing/Conflicts.test.ts +++ b/core/ecschema-editing/src/test/Differencing/Conflicts.test.ts @@ -2,14 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ConflictCode, SchemaDifferenceConflict } from "../../Differencing/SchemaConflicts"; import { Schema, SchemaContext, SchemaProps } from "@itwin/ecschema-metadata"; -import { getSchemaDifferences, SchemaDifferenceResult } from "../../Differencing/SchemaDifference"; import { expect } from "chai"; +import { ConflictCode, SchemaDifferenceConflict } from "../../Differencing/SchemaConflicts"; +import { getSchemaDifferences, SchemaDifferenceResult } from "../../Differencing/SchemaDifference"; /* eslint-disable @typescript-eslint/naming-convention */ describe("Schema Difference Conflicts", () => { - async function findConflictItem({ conflicts }: SchemaDifferenceResult, name: string, path?: string) { return conflicts && conflicts.find((entry) => { return entry.itemName === name && (entry.path === path || entry.path); @@ -879,7 +878,10 @@ describe("Schema Difference Conflicts", () => { expect(conflict).to.have.a.property("path", "TestProperty"); expect(conflict).to.have.a.property("source", "ConflictSchema.KoQ_1"); expect(conflict).to.have.a.property("target", null); - expect(conflict).to.have.a.property("description", "The kind of quantity cannot be assiged if the property did not have a kind of quantities before."); + expect(conflict).to.have.a.property( + "description", + "The kind of quantity cannot be assiged if the property did not have a kind of quantities before.", + ); }); }); @@ -976,7 +978,10 @@ describe("Schema Difference Conflicts", () => { expect(conflict).to.have.a.property("path", "TestProperty"); expect(conflict).to.have.a.property("source", null); expect(conflict).to.have.a.property("target", "ConflictSchema.KoQ_1"); - expect(conflict).to.have.a.property("description", "The kind of quantity cannot be undefined if the property had a kind of quantities before."); + expect(conflict).to.have.a.property( + "description", + "The kind of quantity cannot be undefined if the property had a kind of quantities before.", + ); }); }); diff --git a/core/ecschema-editing/src/test/Differencing/Difference.test.ts b/core/ecschema-editing/src/test/Differencing/Difference.test.ts index 694446eb8cba..00060928d19c 100644 --- a/core/ecschema-editing/src/test/Differencing/Difference.test.ts +++ b/core/ecschema-editing/src/test/Differencing/Difference.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import { DifferenceType, getSchemaDifferences, SchemaDifferenceResult, SchemaOtherTypes } from "../../Differencing/SchemaDifference"; import { expect } from "chai"; +import { DifferenceType, getSchemaDifferences, SchemaDifferenceResult, SchemaOtherTypes } from "../../Differencing/SchemaDifference"; import sourceJson from "./sourceSchema.json"; import targetJson from "./targetSchema.json"; @@ -34,7 +34,6 @@ function expectPartiallyEquals(actual: any, expected: any, message?: string) { /* eslint-disable @typescript-eslint/naming-convention */ describe("Schema Differences", () => { - const customAttributeSchemaJson = { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", name: "CustomAttributeSchema", @@ -94,7 +93,8 @@ describe("Schema Differences", () => { const targetSchema = await Schema.fromJson(targetJson, targetContext); differenceResult = await getSchemaDifferences(targetSchema, sourceSchema); - expect(differenceResult.conflicts, `This test suite should not have conflicts.\n${JSON.stringify(differenceResult.conflicts, null, 2)}`).to.be.undefined; + expect(differenceResult.conflicts, `This test suite should not have conflicts.\n${JSON.stringify(differenceResult.conflicts, null, 2)}`).to.be + .undefined; expect(differenceResult.differences).has.a.lengthOf(27, "Unexpected count of differences."); }); @@ -152,7 +152,8 @@ describe("Schema Differences", () => { name: "EmptySchema", version: "01.00.01", }, - }, { + }, + { changeType: "add", schemaType: SchemaOtherTypes.SchemaReference, difference: { @@ -280,8 +281,7 @@ describe("Schema Differences", () => { customAttributes: [{ className: "CustomAttributeSchema.MissingCA", }], - }, - { + }, { name: "IntegerProperty", type: "PrimitiveArrayProperty", typeName: "int", @@ -330,26 +330,32 @@ describe("Schema Differences", () => { }); it("should return changed source relationship constraint properties", () => { - expectPartiallyEquals(findEntry({ changeType: "modify", schemaType: "RelationshipConstraint", itemName: "RelationshipEntity", path: "$source" }), { - changeType: "modify", - schemaType: "RelationshipConstraint", - itemName: "RelationshipEntity", - path: "$source", - difference: { - roleLabel: "New Source RoleLabel", - abstractConstraint: "SourceSchema.RelationshipSourceEntity", + expectPartiallyEquals( + findEntry({ changeType: "modify", schemaType: "RelationshipConstraint", itemName: "RelationshipEntity", path: "$source" }), + { + changeType: "modify", + schemaType: "RelationshipConstraint", + itemName: "RelationshipEntity", + path: "$source", + difference: { + roleLabel: "New Source RoleLabel", + abstractConstraint: "SourceSchema.RelationshipSourceEntity", + }, }, - }); + ); }); it("should return changed source relationship constraint with added constraint classes", () => { - expectPartiallyEquals(findEntry({ changeType: "add", schemaType: "RelationshipConstraintClass", itemName: "RelationshipEntity", path: "$source" }), { - changeType: "add", - schemaType: "RelationshipConstraintClass", - itemName: "RelationshipEntity", - difference: [ - "SourceSchema.RelationshipSourceEntity", - ], - }); + expectPartiallyEquals( + findEntry({ changeType: "add", schemaType: "RelationshipConstraintClass", itemName: "RelationshipEntity", path: "$source" }), + { + changeType: "add", + schemaType: "RelationshipConstraintClass", + itemName: "RelationshipEntity", + difference: [ + "SourceSchema.RelationshipSourceEntity", + ], + }, + ); }); }); diff --git a/core/ecschema-editing/src/test/Differencing/sourceSchema.json.ts b/core/ecschema-editing/src/test/Differencing/sourceSchema.json.ts index 3c2f38e70ea5..a64a94f7900c 100644 --- a/core/ecschema-editing/src/test/Differencing/sourceSchema.json.ts +++ b/core/ecschema-editing/src/test/Differencing/sourceSchema.json.ts @@ -91,8 +91,7 @@ export default { type: "PrimitiveProperty", typeName: "boolean", customAttributes: [{ className: "CustomAttributeSchema.MissingCA" }], - }, - { + }, { name: "IntegerProperty", type: "PrimitiveArrayProperty", typeName: "int", @@ -115,8 +114,7 @@ export default { type: "PrimitiveProperty", typeName: "boolean", customAttributes: [{ className: "CustomAttributeSchema.InternalId" }], - }, - { + }, { name: "StructProperty", type: "StructArrayProperty", typeName: "SourceSchema.MissingStruct", diff --git a/core/ecschema-editing/src/test/Differencing/targetSchema.json.ts b/core/ecschema-editing/src/test/Differencing/targetSchema.json.ts index 8f88aff39f2d..da03ffb6e9b3 100644 --- a/core/ecschema-editing/src/test/Differencing/targetSchema.json.ts +++ b/core/ecschema-editing/src/test/Differencing/targetSchema.json.ts @@ -31,8 +31,8 @@ export default { definition: "Units.LENGTH(4)", }, TargetPropertyCategory: { - schemaItemType:"PropertyCategory", - label:"Target Schema Category", + schemaItemType: "PropertyCategory", + label: "Target Schema Category", priority: 100000, }, ChangedEnumeration: { @@ -73,16 +73,14 @@ export default { multiplicity: "(0..*)", roleLabel: "Source RoleLabel", abstractConstraint: "TargetSchema.ChangedEntity", - constraintClasses: [ - ], + constraintClasses: [], }, target: { polymorphic: true, multiplicity: "(0..*)", roleLabel: "Target RoleLabel", abstractConstraint: "TargetSchema.ChangedEntity", - constraintClasses: [ - ], + constraintClasses: [], }, }, }, diff --git a/core/ecschema-editing/src/test/Editing/Constants.test.ts b/core/ecschema-editing/src/test/Editing/Constants.test.ts index 1cb61901fd48..4a2af5cb7cc0 100644 --- a/core/ecschema-editing/src/test/Editing/Constants.test.ts +++ b/core/ecschema-editing/src/test/Editing/Constants.test.ts @@ -1,6 +1,6 @@ +import { Constant, ConstantProps, ECVersion, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; -import { Constant, ConstantProps, ECVersion, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; import { ECEditingStatus } from "../../Editing/Exception"; describe("Constant tests", () => { @@ -40,20 +40,24 @@ describe("Constant tests", () => { }); it("try creating Constant to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.constants.create(badKey, "testConstant", phenomenonKey, "testDefinition")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.constants.create(badKey, "testConstant", phenomenonKey, "testDefinition")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }, + ); }); it("try creating Constant with existing name, throws error", async () => { await testEditor.constants.create(testKey, "testConstant", phenomenonKey, "testDefinition"); - await expect(testEditor.constants.create(testKey, "testConstant", phenomenonKey, "testDefinition")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Constant testSchema.testConstant already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.constants.create(testKey, "testConstant", phenomenonKey, "testDefinition")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Constant testSchema.testConstant already exists in the schema ${testKey.name}.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }, + ); }); }); diff --git a/core/ecschema-editing/src/test/Editing/CustomAttributes.test.ts b/core/ecschema-editing/src/test/Editing/CustomAttributes.test.ts index 367789ee9100..e49b05012697 100644 --- a/core/ecschema-editing/src/test/Editing/CustomAttributes.test.ts +++ b/core/ecschema-editing/src/test/Editing/CustomAttributes.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CustomAttributeClass, CustomAttributeContainerType, ECVersion, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -38,7 +38,7 @@ describe("CustomAttribute tests", () => { const baseClassRes = await testEditor.customAttributes.create(testKey, "testBaseClass", CustomAttributeContainerType.AnyClass); const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.AnyClass); - await testEditor.customAttributes.setBaseClass(caRes,baseClassRes); + await testEditor.customAttributes.setBaseClass(caRes, baseClassRes); const testCA = await testEditor.schemaContext.getSchemaItem(caRes); expect(await testCA?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); @@ -46,8 +46,20 @@ describe("CustomAttribute tests", () => { it("should change custom attribute base class with class derived from", async () => { const baseClassRes = await testEditor.customAttributes.create(testKey, "testBaseClass", CustomAttributeContainerType.AnyProperty); - const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.AnyProperty, "testLabel",baseClassRes); - const newBaseClassRes = await testEditor.customAttributes.create(testKey, "newBaseClass", CustomAttributeContainerType.AnyProperty, "newLabel",baseClassRes); + const caRes = await testEditor.customAttributes.create( + testKey, + "testCustomAttribute", + CustomAttributeContainerType.AnyProperty, + "testLabel", + baseClassRes, + ); + const newBaseClassRes = await testEditor.customAttributes.create( + testKey, + "newBaseClass", + CustomAttributeContainerType.AnyProperty, + "newLabel", + baseClassRes, + ); const testCA = await testEditor.schemaContext.getSchemaItem(caRes); expect(await testCA?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); @@ -58,7 +70,13 @@ describe("CustomAttribute tests", () => { it("should remove a base class from custom attribute class", async () => { const baseClassRes = await testEditor.customAttributes.create(testKey, "testBaseClass", CustomAttributeContainerType.AnyRelationshipConstraint); - const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.AnyRelationshipConstraint, "testLabel",baseClassRes); + const caRes = await testEditor.customAttributes.create( + testKey, + "testCustomAttribute", + CustomAttributeContainerType.AnyRelationshipConstraint, + "testLabel", + baseClassRes, + ); const testCA = await testEditor.schemaContext.getSchemaItem(caRes); expect(await testCA?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); @@ -82,7 +100,7 @@ describe("CustomAttribute tests", () => { it("try adding base class to custom attribute class with different SchemaItemType, returns error", async () => { const baseClassRes = await testEditor.structs.create(testKey, "testBaseClass"); const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.NavigationProperty); - await expect(testEditor.customAttributes.setBaseClass(caRes,baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.customAttributes.setBaseClass(caRes, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Expected ${baseClassRes.fullName} to be of type CustomAttributeClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -92,18 +110,21 @@ describe("CustomAttribute tests", () => { it("try adding base class to a custom attribute class where the base class cannot be located, returns error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.PrimitiveProperty); - await expect(testEditor.customAttributes.setBaseClass(caRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.customAttributes.setBaseClass(caRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `CustomAttributeClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `CustomAttributeClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); it("try adding base class to non-existing custom attribute class, returns error", async () => { const baseClassRes = await testEditor.customAttributes.create(testKey, "testBaseClass", CustomAttributeContainerType.RelationshipClass); - const caKey = new SchemaItemKey("testCustomAttribute", testKey); + const caKey = new SchemaItemKey("testCustomAttribute", testKey); - await expect(testEditor.customAttributes.setBaseClass(caKey,baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.customAttributes.setBaseClass(caKey, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `CustomAttributeClass ${caKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -111,11 +132,11 @@ describe("CustomAttribute tests", () => { }); it("try adding base class with unknown schema to existing custom attribute class, returns error", async () => { - const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); + const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", schemaKey); const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty); - await expect(testEditor.customAttributes.setBaseClass(caRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.customAttributes.setBaseClass(caRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${schemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -123,44 +144,71 @@ describe("CustomAttribute tests", () => { }); it("try changing the custom attribute base class to one that doesn't derive from, returns error", async () => { - const baseClassRes = await testEditor.customAttributes.create(testKey, "testBaseClass", CustomAttributeContainerType.TargetRelationshipConstraint); - const caRes = await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.TargetRelationshipConstraint, "testLabel",baseClassRes); + const baseClassRes = await testEditor.customAttributes.create( + testKey, + "testBaseClass", + CustomAttributeContainerType.TargetRelationshipConstraint, + ); + const caRes = await testEditor.customAttributes.create( + testKey, + "testCustomAttribute", + CustomAttributeContainerType.TargetRelationshipConstraint, + "testLabel", + baseClassRes, + ); const testCA = await testEditor.schemaContext.getSchemaItem(caRes); expect(await testCA?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); - const newBaseClassRes = await testEditor.customAttributes.create(testKey, "newBaseClass", CustomAttributeContainerType.TargetRelationshipConstraint); - await expect(testEditor.customAttributes.setBaseClass(caRes, newBaseClassRes)).to.be.eventually.rejected.then(function (error) { + const newBaseClassRes = await testEditor.customAttributes.create( + testKey, + "newBaseClass", + CustomAttributeContainerType.TargetRelationshipConstraint, + ); + await expect(testEditor.customAttributes.setBaseClass(caRes, newBaseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); it("try creating custom attribute class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.customAttributes.create(badKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.customAttributes.create(badKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty)).to.be.eventually + .rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }); }); it("try creating custom attribute class with unknown base class, throws error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty, undefined, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect( + testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty, undefined, baseClassKey), + ).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `CustomAttributeClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `CustomAttributeClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); it("try creating custom attribute class with existing name, throws error", async () => { await testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty); - await expect(testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `CustomAttributeClass testSchema.testCustomAttribute already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.customAttributes.create(testKey, "testCustomAttribute", CustomAttributeContainerType.StructProperty)).to.be.eventually + .rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `CustomAttributeClass testSchema.testCustomAttribute already exists in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }); }); }); diff --git a/core/ecschema-editing/src/test/Editing/ECClasses.test.ts b/core/ecschema-editing/src/test/Editing/ECClasses.test.ts index c16a623d6295..e74c2094f23e 100644 --- a/core/ecschema-editing/src/test/Editing/ECClasses.test.ts +++ b/core/ecschema-editing/src/test/Editing/ECClasses.test.ts @@ -2,13 +2,30 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - ECClassModifier, EntityClass, Enumeration, EnumerationArrayProperty, EnumerationProperty, NavigationProperty, - PrimitiveArrayProperty, PrimitiveProperty, PrimitiveType, RelationshipClass, RelationshipClassProps, - RelationshipConstraintProps, Schema, SchemaContext, SchemaItemKey, SchemaKey, StrengthDirection, - StructArrayProperty, StructClass, StructProperty, UnitSystem, + ECClassModifier, + EntityClass, + Enumeration, + EnumerationArrayProperty, + EnumerationProperty, + NavigationProperty, + PrimitiveArrayProperty, + PrimitiveProperty, + PrimitiveType, + RelationshipClass, + RelationshipClassProps, + RelationshipConstraintProps, + Schema, + SchemaContext, + SchemaItemKey, + SchemaKey, + StrengthDirection, + StructArrayProperty, + StructClass, + StructProperty, + UnitSystem, } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -41,9 +58,12 @@ describe("ECClass tests", () => { it("try changing class name to invalid name, throws error", async () => { const result1 = await testEditor.entities.create(testKey, "testEntity1", ECClassModifier.None); - await expect(testEditor.entities.setName(result1, "123")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setName(result1, "123")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetClassName); - expect(error).to.have.nested.property("innerError.message", `Could not rename class ${result1.fullName} because the specified name is not a valid ECName.`); + expect(error).to.have.nested.property( + "innerError.message", + `Could not rename class ${result1.fullName} because the specified name is not a valid ECName.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidECName); }); @@ -54,7 +74,7 @@ describe("ECClass tests", () => { it("try changing class name to existing name in the schema, returns error", async () => { const result1 = await testEditor.entities.create(testKey, "testEntity1", ECClassModifier.None); await testEditor.entities.create(testKey, "testEntity2", ECClassModifier.None); - await expect(testEditor.entities.setName(result1, "testEntity2")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setName(result1, "testEntity2")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetClassName); expect(error).to.have.nested.property("innerError.message", `EntityClass TestSchema.testEntity2 already exists in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); @@ -120,7 +140,7 @@ describe("ECClass tests", () => { }; const enumResult = await testEditor.enumerations.createFromProps(testKey, enumJson); const enumeration = await testEditor.schemaContext.getSchemaItem(enumResult) as Enumeration; - await testEditor.entities.createEnumerationPropertyFromProps(entityKey, "TestProperty", enumeration,propertyJson); + await testEditor.entities.createEnumerationPropertyFromProps(entityKey, "TestProperty", enumeration, propertyJson); const property = await entity?.getProperty("TestProperty") as EnumerationProperty; expect(await property.enumeration).to.eql(enumeration); }); @@ -234,7 +254,7 @@ describe("ECClass tests", () => { testKey = testSchema.schemaKey; const relationshipResult = await testEditor.relationships.createFromProps(testKey, relClassProps); const relationship = await testEditor.schemaContext.getSchemaItem(relationshipResult) as RelationshipClass; - await testEditor.relationships.createNavigationProperty(relationship.key, "TestProperty", relationship,"Forward"); + await testEditor.relationships.createNavigationProperty(relationship.key, "TestProperty", relationship, "Forward"); const navProperty = await relationship.getProperty("TestProperty") as NavigationProperty; expect(navProperty.direction).to.eql(StrengthDirection.Forward); expect(await navProperty.relationshipClass).to.eql(relationship); @@ -262,7 +282,7 @@ describe("ECClass tests", () => { maxOccurs: 55, }; - await testEditor.entities.createPrimitiveArrayPropertyFromProps(entityKey, "TestProperty", PrimitiveType.Integer,propertyJson); + await testEditor.entities.createPrimitiveArrayPropertyFromProps(entityKey, "TestProperty", PrimitiveType.Integer, propertyJson); const property = await entity?.getProperty("TestProperty") as PrimitiveArrayProperty; expect(property.minOccurs).to.eql(42); expect(property.maxOccurs).to.eql(55); @@ -504,11 +524,16 @@ describe("ECClass tests", () => { testEditor = new SchemaContextEditor(context); const badKey = new SchemaItemKey("BadClass", testSchema.schemaKey); - await expect(testEditor.entities.addCustomAttribute(badKey, { className: "testCustomAttribute" })).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); - expect(error).to.have.nested.property("innerError.message", `EntityClass ValidSchema.BadClass could not be found in the schema ValidSchema.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.entities.addCustomAttribute(badKey, { className: "testCustomAttribute" })).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ValidSchema.BadClass could not be found in the schema ValidSchema.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); it("Adding a CustomAttribute to a class with an unsupported SchemaItemType fails as expected.", async () => { @@ -533,11 +558,12 @@ describe("ECClass tests", () => { testEditor = new SchemaContextEditor(context); const testClass = await testSchema.getItem("testUnitSystem"); - await expect(testEditor.entities.addCustomAttribute(testClass?.key as SchemaItemKey, { className: "testCustomAttribute" })).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); - expect(error).to.have.nested.property("innerError.message", `Expected ${testClass?.fullName} to be of type EntityClass.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); - }); + await expect(testEditor.entities.addCustomAttribute(testClass?.key as SchemaItemKey, { className: "testCustomAttribute" })).to.be.eventually + .rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); + expect(error).to.have.nested.property("innerError.message", `Expected ${testClass?.fullName} to be of type EntityClass.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); + }); }); }); }); diff --git a/core/ecschema-editing/src/test/Editing/Editor.test.ts b/core/ecschema-editing/src/test/Editing/Editor.test.ts index 915b83412882..6b43e00ac1cb 100644 --- a/core/ecschema-editing/src/test/Editing/Editor.test.ts +++ b/core/ecschema-editing/src/test/Editing/Editor.test.ts @@ -2,15 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECVersion, EntityClass, PrimitiveType, Schema, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; import { expect } from "chai"; -import { - ECVersion, EntityClass, PrimitiveType, Schema, - SchemaContext, SchemaItemKey, SchemaKey, -} from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "../../Editing/Editor"; +import { ECEditingStatus } from "../../Editing/Exception"; import { AnyDiagnostic } from "../../Validation/Diagnostic"; import { Diagnostics } from "../../Validation/ECRules"; -import { ECEditingStatus } from "../../Editing/Exception"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -24,7 +21,6 @@ function getRuleViolationMessage(ruleViolations: AnyDiagnostic[]) { // TODO: Add tests for cases where invalid names are passed into props objects. (to test the error message) describe("Editor tests", () => { - describe("SchemaEditor tests", () => { let testEditor: SchemaContextEditor; let testSchema: Schema; @@ -114,8 +110,7 @@ describe("Editor tests", () => { name: "SchemaA", version: "1.2.3", alias: "vs", - customAttributes: [ - ], + customAttributes: [], references: [ { name: "SchemaB", @@ -136,15 +131,21 @@ describe("Editor tests", () => { testEditor = new SchemaContextEditor(context); testKey = schemaA.schemaKey; - await expect(testEditor.addCustomAttribute(testKey, { className: "SchemaB.TestCustomAttribute" })).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(error).to.have.nested.property("innerError.message", `Rule violations occurred from CustomAttribute SchemaB.TestCustomAttribute, container ${testKey.name}: ${getRuleViolationMessage(error.innerError.ruleViolations)}`); - const violations = error.innerError.ruleViolations as AnyDiagnostic[]; - expect(violations[0]).to.deep.equal(new Diagnostics.CustomAttributeClassNotFound(schemaA, ["SchemaA", "SchemaB.TestCustomAttribute"])); - expect(schemaA.customAttributes && schemaA.customAttributes.has("SchemaB.TestCustomAttribute")).to.be.false; - }); - + await expect(testEditor.addCustomAttribute(testKey, { className: "SchemaB.TestCustomAttribute" })).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToClass); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); + expect(error).to.have.nested.property( + "innerError.message", + `Rule violations occurred from CustomAttribute SchemaB.TestCustomAttribute, container ${testKey.name}: ${ + getRuleViolationMessage(error.innerError.ruleViolations) + }`, + ); + const violations = error.innerError.ruleViolations as AnyDiagnostic[]; + expect(violations[0]).to.deep.equal(new Diagnostics.CustomAttributeClassNotFound(schemaA, ["SchemaA", "SchemaB.TestCustomAttribute"])); + expect(schemaA.customAttributes && schemaA.customAttributes.has("SchemaB.TestCustomAttribute")).to.be.false; + }, + ); }); }); @@ -220,10 +221,15 @@ describe("Editor tests", () => { } catch (e: any) { expect(e).to.have.property("errorNumber", ECEditingStatus.AddSchemaReference); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from Schema ${schemaA.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from Schema ${schemaA.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; expect(violations[0]).to.deep.equal(new Diagnostics.SchemaRefAliasMustBeUnique(schemaA, [schemaA.name, "b", "SchemaB", "SchemaC"])); - expect(violations[1]).to.deep.equal(new Diagnostics.ReferenceCyclesNotAllowed(schemaA, [schemaA.name, `SchemaC --> SchemaA, SchemaA --> SchemaC`])); + expect(violations[1]).to.deep.equal( + new Diagnostics.ReferenceCyclesNotAllowed(schemaA, [schemaA.name, `SchemaC --> SchemaA, SchemaA --> SchemaC`]), + ); expect(schemaA.getReferenceSync("SchemaC")).to.be.undefined; } }); @@ -469,9 +475,12 @@ describe("Editor tests", () => { testSchema = await Schema.fromJson(schemaJson, context); testEditor = new SchemaContextEditor(context); - await expect(testEditor.setAlias(testSchema.schemaKey, "123")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.setAlias(testSchema.schemaKey, "123")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetSchemaAlias); - expect(error).to.have.nested.property("innerError.message", `Could not set the alias for schema ${testSchema.name} because the specified alias is not a valid ECName.`); + expect(error).to.have.nested.property( + "innerError.message", + `Could not set the alias for schema ${testSchema.name} because the specified alias is not a valid ECName.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaAlias); }); @@ -499,7 +508,7 @@ describe("Editor tests", () => { testEditor = new SchemaContextEditor(context); // tests case-insensitive search (ts2 === TS2) - await expect(testEditor.setAlias(testSchema1.schemaKey, "ts2")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.setAlias(testSchema1.schemaKey, "ts2")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetSchemaAlias); expect(error).to.have.nested.property("innerError.message", `Schema ${testSchema2.name} already uses the alias 'ts2'.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaAliasAlreadyExists); diff --git a/core/ecschema-editing/src/test/Editing/Entities.test.ts b/core/ecschema-editing/src/test/Editing/Entities.test.ts index 4553dfbe662e..1d1ec36f7f38 100644 --- a/core/ecschema-editing/src/test/Editing/Entities.test.ts +++ b/core/ecschema-editing/src/test/Editing/Entities.test.ts @@ -2,11 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; import { - ECClassModifier, ECVersion, EntityClass, EntityClassProps, NavigationProperty, NavigationPropertyProps, RelationshipClass, Schema, SchemaContext, SchemaItemKey, SchemaItemType, SchemaKey, StrengthDirection, StrengthType, + ECClassModifier, + ECVersion, + EntityClass, + EntityClassProps, + NavigationProperty, + NavigationPropertyProps, + RelationshipClass, + Schema, + SchemaContext, + SchemaItemKey, + SchemaItemType, + SchemaKey, + StrengthDirection, + StrengthType, } from "@itwin/ecschema-metadata"; +import * as chai from "chai"; +import * as chaiAsPromised from "chai-as-promised"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -90,22 +103,29 @@ describe("Entities tests", () => { }); it("try creating a new entity class with base class from unknown schema, returns error", async () => { - const badSchemaKey = new SchemaKey("badSchema", new ECVersion(1,0,0)); + const badSchemaKey = new SchemaKey("badSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", badSchemaKey); - await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badSchemaKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badSchemaKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }, + ); }); it("try creating a new entity class with a base class that cannot be located, returns error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); it("should create a new entity class using EntityClassProps", async () => { @@ -134,7 +154,13 @@ describe("Entities tests", () => { it("should create a new navigation property from NavigationPropertyProps", async () => { const testEntityRes = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None); - const testRelRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); + const testRelRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); const navProps: NavigationPropertyProps = { name: "testProperty", type: "NavigationProperty", @@ -231,11 +257,11 @@ describe("Entities tests", () => { }); it("try adding base class with unknown schema to existing entity class, returns error", async () => { - const badSchemaKey = new SchemaKey("badSchema", new ECVersion(1,0,0)); + const badSchemaKey = new SchemaKey("badSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", badSchemaKey); const entityResult = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.setBaseClass(entityResult, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(entityResult, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badSchemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -245,9 +271,12 @@ describe("Entities tests", () => { it("try adding base class to an existing entity class where the base class cannot be located, returns error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); const createResult = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.setBaseClass(createResult, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(createResult, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); @@ -260,7 +289,7 @@ describe("Entities tests", () => { }; const unitResult = await testEditor.unitSystems.createFromProps(testKey, unitSystemProps); const entityResult = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.setBaseClass(entityResult, unitResult)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(entityResult, unitResult)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Expected ${unitResult.fullName} to be of type EntityClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -269,9 +298,9 @@ describe("Entities tests", () => { it("try adding base class to non-existing custom attribute class, returns error", async () => { const baseClassRes = await testEditor.entities.create(testKey, "testBaseClass", ECClassModifier.None, "testLabel"); - const entityKey = new SchemaItemKey("testEntityClass", testKey); + const entityKey = new SchemaItemKey("testEntityClass", testKey); - await expect(testEditor.entities.setBaseClass(entityKey, baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(entityKey, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `EntityClass ${entityKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -279,11 +308,11 @@ describe("Entities tests", () => { }); it("try adding base class with unknown schema to existing entity class, returns error", async () => { - const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); + const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", schemaKey); const entityRes = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.setBaseClass(entityRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(entityRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${schemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -292,22 +321,25 @@ describe("Entities tests", () => { it("try changing the entity base class to one that doesn't derive from, returns error", async () => { const baseClassRes = await testEditor.entities.create(testKey, "testBaseClass", ECClassModifier.None, "testLabel"); - const entityRes = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel",baseClassRes); + const entityRes = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassRes); const testEntity = await testEditor.schemaContext.getSchemaItem(entityRes); expect(await testEntity?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); const newBaseClassRes = await testEditor.entities.create(testKey, "newBaseClass", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.setBaseClass(entityRes, newBaseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.setBaseClass(entityRes, newBaseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); it("try creating entity class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.entities.create(badKey, "testEntity", ECClassModifier.None, "testLabel")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.entities.create(badKey, "testEntity", ECClassModifier.None, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -316,19 +348,29 @@ describe("Entities tests", () => { it("try creating entity class with unknown base class, throws error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel", baseClassKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); it("try creating entity with existing name, throws error", async () => { await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel"); - await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `EntityClass testSchema.testEntity already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.entities.create(testKey, "testEntity", ECClassModifier.None, "testLabel")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass testSchema.testEntity already exists in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }, + ); }); }); diff --git a/core/ecschema-editing/src/test/Editing/Enumerations.test.ts b/core/ecschema-editing/src/test/Editing/Enumerations.test.ts index 921eccf8fc00..d07255ac3a70 100644 --- a/core/ecschema-editing/src/test/Editing/Enumerations.test.ts +++ b/core/ecschema-editing/src/test/Editing/Enumerations.test.ts @@ -2,9 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + ECClassModifier, + Enumeration, + EnumerationProps, + PrimitiveType, + SchemaContext, + SchemaItemKey, + SchemaItemType, + SchemaKey, +} from "@itwin/ecschema-metadata"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { ECClassModifier, Enumeration, EnumerationProps, PrimitiveType, SchemaContext, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -62,7 +71,7 @@ describe("Enumerations tests", () => { it("should add Enumerator to existing Enumeration.", async () => { const enumerator = { name: "testEnum", value: 1 }; - const enumResult = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.Integer); + const enumResult = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.Integer); await testEditor.enumerations.addEnumerator(enumResult, enumerator); const schema = await testEditor.schemaContext.getCachedSchema(testKey); const testEnumeration = await schema?.getItem("testEnumeration") as Enumeration; @@ -73,8 +82,8 @@ describe("Enumerations tests", () => { it("add Enumerator to a type that is not an enumeration, throws.", async () => { const enumerator = { name: "testEnum", value: 1 }; - const result = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None); - await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function (error) { + const result = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None); + await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddEnumerator); expect(error).to.have.nested.property("innerError.message", `Expected ${result.fullName} to be of type Enumeration.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -83,20 +92,26 @@ describe("Enumerations tests", () => { it("add string Enumerator to an enumeration of type number, throws.", async () => { const enumerator = { name: "testEnum", value: "one" }; - const result = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.Integer); - await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function (error) { + const result = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.Integer); + await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddEnumerator); - expect(error).to.have.nested.property("innerError.message", `The Enumeration ${result.fullName} has type int, while Enumerator testEnum has type string.`); + expect(error).to.have.nested.property( + "innerError.message", + `The Enumeration ${result.fullName} has type int, while Enumerator testEnum has type string.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidEnumeratorType); }); }); it("add number Enumerator to an enumeration of type string, throws.", async () => { const enumerator = { name: "testEnum", value: 1 }; - const result = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.String); - await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function (error) { + const result = await testEditor.enumerations.create(testKey, "testEnumeration", PrimitiveType.String); + await expect(testEditor.enumerations.addEnumerator(result, enumerator)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddEnumerator); - expect(error).to.have.nested.property("innerError.message", `The Enumeration ${result.fullName} has type string, while Enumerator testEnum has type int.`); + expect(error).to.have.nested.property( + "innerError.message", + `The Enumeration ${result.fullName} has type string, while Enumerator testEnum has type int.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidEnumeratorType); }); }); @@ -104,7 +119,7 @@ describe("Enumerations tests", () => { it("add string Enumerator to an enumeration that can't be found, throws.", async () => { const enumerator = { name: "testEnum", value: 1 }; const badKey = new SchemaItemKey("badKey", testKey); - await expect(testEditor.enumerations.addEnumerator(badKey, enumerator)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.enumerations.addEnumerator(badKey, enumerator)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddEnumerator); expect(error).to.have.nested.property("innerError.message", `Enumeration ${badKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); diff --git a/core/ecschema-editing/src/test/Editing/Exception.test.ts b/core/ecschema-editing/src/test/Editing/Exception.test.ts index a1f0f9bb9c58..1b9e2aecccd8 100644 --- a/core/ecschema-editing/src/test/Editing/Exception.test.ts +++ b/core/ecschema-editing/src/test/Editing/Exception.test.ts @@ -1,12 +1,21 @@ +import { + RelationshipClass, + RelationshipConstraint, + RelationshipEnd, + Schema, + SchemaContext, + SchemaItemKey, + SchemaItemType, + SchemaKey, +} from "@itwin/ecschema-metadata"; import { expect } from "chai"; +import { AnyDiagnostic, Diagnostics } from "../../ecschema-editing"; import { SchemaContextEditor } from "../../Editing/Editor"; -import { RelationshipClass, RelationshipConstraint, RelationshipEnd, Schema, SchemaContext, SchemaItemKey, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; import { ClassId, ECEditingStatus, PropertyId, RelationshipConstraintId, SchemaEditingError, SchemaId, SchemaItemId } from "../../Editing/Exception"; -import { AnyDiagnostic, Diagnostics } from "../../ecschema-editing"; function getRuleViolationMessage(ruleViolations: AnyDiagnostic[]) { let violations = ""; - for (const diagnostic of ruleViolations){ + for (const diagnostic of ruleViolations) { violations += `${diagnostic.code}: ${diagnostic.messageText}\r\n`; } return violations; @@ -34,38 +43,60 @@ describe("SchemaEditingError tests", () => { ]; const innerError = new SchemaEditingError(ECEditingStatus.RuleViolation, new SchemaId(testKey), undefined, diagnostics); const error = new SchemaEditingError(ECEditingStatus.AddSchemaReference, new SchemaId(testKey), innerError); - expect(error.toDebugString()).to.equal(`ECEditingStatus.AddSchemaReference: While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Schema ${testKey.name}. Inner error: ECEditingStatus.RuleViolation: Rule violations occurred from Schema TestSchema: ${getRuleViolationMessage(diagnostics)}`); + expect(error.toDebugString()).to.equal( + `ECEditingStatus.AddSchemaReference: While performing task '${ + ECEditingStatus[error.errorNumber] + }' an error occurred editing Schema ${testKey.name}. Inner error: ECEditingStatus.RuleViolation: Rule violations occurred from Schema TestSchema: ${ + getRuleViolationMessage(diagnostics) + }`, + ); }); it("Should create proper debug string with inner exception of type Error", async () => { const innerError = new Error("Could not create EntityClass testEntityClass for some unknown reason."); - const error = new SchemaEditingError(ECEditingStatus.CreateSchemaItemFailed, new ClassId(SchemaItemType.EntityClass, "TestEntity", testKey), innerError); - expect(error.toDebugString()).to.equal(`ECEditingStatus.CreateSchemaItemFailed: While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Class TestSchema.TestEntity. Inner error: Could not create EntityClass testEntityClass for some unknown reason.`); + const error = new SchemaEditingError( + ECEditingStatus.CreateSchemaItemFailed, + new ClassId(SchemaItemType.EntityClass, "TestEntity", testKey), + innerError, + ); + expect(error.toDebugString()).to.equal( + `ECEditingStatus.CreateSchemaItemFailed: While performing task '${ + ECEditingStatus[error.errorNumber] + }' an error occurred editing Class TestSchema.TestEntity. Inner error: Could not create EntityClass testEntityClass for some unknown reason.`, + ); }); it("Should create correct error message for Schema task error", async () => { const identifier = new SchemaId(testKey); const error = new SchemaEditingError(ECEditingStatus.CreateElement, identifier, new Error("inner error")); - expect(error.message).to.equal(`While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Schema ${identifier.name}.`); + expect(error.message).to.equal( + `While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Schema ${identifier.name}.`, + ); }); it("Should create correct error message for SchemaItem task error", async () => { const identifier = new SchemaItemId(SchemaItemType.Unit, "TestUnit", testKey); const error = new SchemaEditingError(ECEditingStatus.CreateSchemaItemFailed, identifier, new Error("inner error")); - expect(error.message).to.equal(`While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing SchemaItem ${identifier.name}.`); + expect(error.message).to.equal( + `While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing SchemaItem ${identifier.name}.`, + ); }); it("Should create correct error message for Class task error", async () => { const identifier = new ClassId(SchemaItemType.EntityClass, "TestEntity", testKey); const error = new SchemaEditingError(ECEditingStatus.CreateElement, identifier, new Error("inner error")); - expect(error.message).to.equal(`While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Class ${identifier.name}.`); + expect(error.message).to.equal( + `While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Class ${identifier.name}.`, + ); }); it("Should create correct error message for Property task error", async () => { const itemKey = new SchemaItemKey("TestEntity", testKey); const identifier = new PropertyId(SchemaItemType.EntityClass, itemKey, "TestProperty"); const error = new SchemaEditingError(ECEditingStatus.SetPropertyName, identifier, new Error("inner error")); - expect(error.message).to.equal(`While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Property ${identifier.fullName}.`); + expect(error.message).to.equal( + `While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing Property ${identifier.fullName}.`, + ); }); it("Should create correct error message for RelationshipConstraint task error", async () => { @@ -73,7 +104,8 @@ describe("SchemaEditingError tests", () => { const testConstraint = new RelationshipConstraint(relClass, RelationshipEnd.Source); const identifier = new RelationshipConstraintId(testConstraint); const error = new SchemaEditingError(ECEditingStatus.AddCustomAttributeToConstraint, identifier, new Error("inner error")); - expect(error.message).to.equal(`While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing RelationshipConstraint ${identifier.name}.`); + expect(error.message).to.equal( + `While performing task '${ECEditingStatus[error.errorNumber]}' an error occurred editing RelationshipConstraint ${identifier.name}.`, + ); }); - }); diff --git a/core/ecschema-editing/src/test/Editing/Formats.test.ts b/core/ecschema-editing/src/test/Editing/Formats.test.ts index e643c029e536..83b8f7b6c322 100644 --- a/core/ecschema-editing/src/test/Editing/Formats.test.ts +++ b/core/ecschema-editing/src/test/Editing/Formats.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { ECClassModifier, ECVersion, Format, SchemaContext, SchemaKey } from "@itwin/ecschema-metadata"; import { FormatTraits, FormatType } from "@itwin/core-quantity"; +import { ECClassModifier, ECVersion, Format, SchemaContext, SchemaKey } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -28,11 +28,16 @@ describe("Formats tests", () => { it("create Format with invalid type for units, throws", async () => { const entityResult = await testEditor.entities.create(testKey, "testEntity", ECClassModifier.None); - await expect(testEditor.formats.create(testKey, "testFormat", FormatType.Decimal, "testLabel", [entityResult])).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `The specified Format unit ${entityResult.fullName} is not of type Unit or InvertedUnit`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidFormatUnitsSpecified); - }); + await expect(testEditor.formats.create(testKey, "testFormat", FormatType.Decimal, "testLabel", [entityResult])).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `The specified Format unit ${entityResult.fullName} is not of type Unit or InvertedUnit`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidFormatUnitsSpecified); + }, + ); }); it("should create a valid Format from FormatProps", async () => { @@ -61,8 +66,8 @@ describe("Formats tests", () => { }); it("try creating format in unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.formats.create(badKey, "testFormat", FormatType.Decimal, "testLabel")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.formats.create(badKey, "testFormat", FormatType.Decimal, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -71,7 +76,7 @@ describe("Formats tests", () => { it("try creating format with existing name, throws error", async () => { await testEditor.formats.create(testKey, "testFormat", FormatType.Decimal, "testLabel"); - await expect(testEditor.formats.create(testKey, "testFormat", FormatType.Decimal, "testLabel")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.formats.create(testKey, "testFormat", FormatType.Decimal, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Format testSchema.testFormat already exists in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); diff --git a/core/ecschema-editing/src/test/Editing/InvertedUnits.test.ts b/core/ecschema-editing/src/test/Editing/InvertedUnits.test.ts index a6e3972dc49b..9dce3b757c1e 100644 --- a/core/ecschema-editing/src/test/Editing/InvertedUnits.test.ts +++ b/core/ecschema-editing/src/test/Editing/InvertedUnits.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECVersion, InvertedUnit, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -18,9 +18,9 @@ describe("Inverted Units tests", () => { context = new SchemaContext(); testEditor = new SchemaContextEditor(context); testKey = await testEditor.createSchema("testSchema", "test", 1, 0, 0); - unitSystemKey = (await testEditor.unitSystems.create(testKey, "testUnitSystem")); - const phenomenonKey = (await testEditor.phenomenons.create(testKey, "testPhenomenon", "testDefinition")); - invertsUnitKey = (await testEditor.units.create(testKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey)); + unitSystemKey = await testEditor.unitSystems.create(testKey, "testUnitSystem"); + const phenomenonKey = await testEditor.phenomenons.create(testKey, "testPhenomenon", "testDefinition"); + invertsUnitKey = await testEditor.units.create(testKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey); }); it("should create a valid Inverted Unit", async () => { @@ -47,26 +47,33 @@ describe("Inverted Units tests", () => { }); it("try creating InvertedUnit in unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.invertedUnits.create(badKey, "testInvertedUnit", invertsUnitKey, unitSystemKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.invertedUnits.create(badKey, "testInvertedUnit", invertsUnitKey, unitSystemKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }, + ); }); it("try creating InvertedUnit with existing name, throws error", async () => { await testEditor.invertedUnits.create(testKey, "testInvertedUnit", invertsUnitKey, unitSystemKey); - await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", invertsUnitKey, unitSystemKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `InvertedUnit testSchema.testInvertedUnit already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", invertsUnitKey, unitSystemKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `InvertedUnit testSchema.testInvertedUnit already exists in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }, + ); }); it("try creating InvertedUnit with unknown invertsUnit, throws error", async () => { const badKey = new SchemaItemKey("unknownInvertsUnit", testKey); - await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", badKey, unitSystemKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", badKey, unitSystemKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Unit ${badKey.fullName} could not be found in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); @@ -75,10 +82,15 @@ describe("Inverted Units tests", () => { it("try creating InvertedUnit with unknown unitSystem, throws error", async () => { const badKey = new SchemaItemKey("unknownUnitSystem", testKey); - await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", invertsUnitKey, badKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `UnitSystem ${badKey.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.invertedUnits.create(testKey, "testInvertedUnit", invertsUnitKey, badKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `UnitSystem ${badKey.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); }); diff --git a/core/ecschema-editing/src/test/Editing/KindOfQuantities.test.ts b/core/ecschema-editing/src/test/Editing/KindOfQuantities.test.ts index 3688e97c8b14..fab8c4771fc8 100644 --- a/core/ecschema-editing/src/test/Editing/KindOfQuantities.test.ts +++ b/core/ecschema-editing/src/test/Editing/KindOfQuantities.test.ts @@ -2,11 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECVersion, KindOfQuantity, KindOfQuantityProps, SchemaContext, SchemaItemKey, SchemaKey } from "@itwin/ecschema-metadata"; import { expect } from "chai"; -import { - ECVersion, - KindOfQuantity, KindOfQuantityProps, SchemaContext, SchemaItemKey, SchemaKey, -} from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -51,8 +48,8 @@ describe("KindOfQuantities tests", () => { }); it("try creating KindOfQuantity in unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.kindOfQuantities.create(badKey, "testInvertedUnit", unitKey)).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.kindOfQuantities.create(badKey, "testInvertedUnit", unitKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -61,7 +58,7 @@ describe("KindOfQuantities tests", () => { it("try creating KindOfQuantity with existing name, throws error", async () => { await testEditor.kindOfQuantities.create(testKey, "testKoq", unitKey); - await expect(testEditor.kindOfQuantities.create(testKey, "testKoq", unitKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.kindOfQuantities.create(testKey, "testKoq", unitKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `KindOfQuantity testSchema.testKoq already exists in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); diff --git a/core/ecschema-editing/src/test/Editing/Mixins.test.ts b/core/ecschema-editing/src/test/Editing/Mixins.test.ts index 571255f7205e..5e4b1bd692fc 100644 --- a/core/ecschema-editing/src/test/Editing/Mixins.test.ts +++ b/core/ecschema-editing/src/test/Editing/Mixins.test.ts @@ -2,8 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + ECClassModifier, + ECVersion, + Mixin, + NavigationProperty, + NavigationPropertyProps, + RelationshipClass, + SchemaContext, + SchemaItemKey, + SchemaKey, + StrengthDirection, + StrengthType, +} from "@itwin/ecschema-metadata"; import { expect } from "chai"; -import { ECClassModifier, ECVersion, Mixin, NavigationProperty, NavigationPropertyProps, RelationshipClass, SchemaContext, SchemaItemKey, SchemaKey, StrengthDirection, StrengthType } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -29,7 +41,13 @@ describe("Mixins tests", () => { it("should create a new navigation property from NavigationPropertyProps", async () => { const testMixinRes = await testEditor.mixins.create(testKey, "testMixin", entityKey); - const testRelRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); + const testRelRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); const navProps: NavigationPropertyProps = { name: "testProperty", type: "NavigationProperty", @@ -75,7 +93,7 @@ describe("Mixins tests", () => { const anotherEntityResult = await testEditor.entities.create(testKey, "anotherTestEntity", ECClassModifier.None); - const mixinBaseClass = await testEditor.mixins.create(testKey, "testMixinBaseClass", anotherEntityResult); + const mixinBaseClass = await testEditor.mixins.create(testKey, "testMixinBaseClass", anotherEntityResult); await testEditor.mixins.setBaseClass(mixinResult, mixinBaseClass); const mixin = testEditor.schemaContext.getSchemaItemSync(mixinResult) as Mixin; @@ -90,7 +108,7 @@ describe("Mixins tests", () => { const testMixin = await testEditor.schemaContext.getSchemaItem(mixinResult); expect(await testMixin?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); - const newBaseClassRes = await testEditor.mixins.create(testKey, "newBaseClass", entityKey, "newLabel",baseClassRes); + const newBaseClassRes = await testEditor.mixins.create(testKey, "newBaseClass", entityKey, "newLabel", baseClassRes); await testEditor.mixins.setBaseClass(mixinResult, newBaseClassRes); expect(await testMixin?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(newBaseClassRes)); }); @@ -108,7 +126,7 @@ describe("Mixins tests", () => { it("should return error message because it tries to set base class that is not of mixin type", async () => { const mixinResult = await testEditor.mixins.create(testKey, "testMixin", entityKey); - await expect(testEditor.mixins.setBaseClass(mixinResult, entityKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.setBaseClass(mixinResult, entityKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Expected ${entityKey.fullName} to be of type Mixin.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -118,7 +136,7 @@ describe("Mixins tests", () => { it("should return an error message when a base class cannot be found in the context", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); const mixinRes = await testEditor.mixins.create(testKey, "testMixin", entityKey); - await expect(testEditor.mixins.setBaseClass(mixinRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.setBaseClass(mixinRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Mixin ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); @@ -127,9 +145,9 @@ describe("Mixins tests", () => { it("adding a base class to a non-existing mixin should result in an error message", async () => { await testEditor.mixins.create(testKey, "testBaseClass", entityKey); - const mixinKey = new SchemaItemKey("testMixin", testKey); + const mixinKey = new SchemaItemKey("testMixin", testKey); - await expect(testEditor.mixins.setBaseClass(mixinKey, entityKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.setBaseClass(mixinKey, entityKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Mixin ${mixinKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -137,11 +155,11 @@ describe("Mixins tests", () => { }); it("adding a base class with an unknown schema to mixin, should result in an error message", async () => { - const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); + const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", schemaKey); const mixinRes = await testEditor.mixins.create(testKey, "testMixin", entityKey); - await expect(testEditor.mixins.setBaseClass(mixinRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.setBaseClass(mixinRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${schemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -150,23 +168,26 @@ describe("Mixins tests", () => { it("changing the mixin base class to one that doesn't derive from, should result in an error message", async () => { const baseClassRes = await testEditor.mixins.create(testKey, "testBaseClass", entityKey); - const mixinRes = await testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel",baseClassRes); + const mixinRes = await testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel", baseClassRes); const testMixin = await testEditor.schemaContext.getSchemaItem(mixinRes); expect(await testMixin?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); const newBaseClassRes = await testEditor.mixins.create(testKey, "newBaseClass", entityKey); - await expect(testEditor.mixins.setBaseClass(mixinRes, newBaseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.setBaseClass(mixinRes, newBaseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); it("try creating mixin class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.mixins.create(badKey, "testMixin", entityKey, "testLabel")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.mixins.create(badKey, "testMixin", entityKey, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -175,16 +196,21 @@ describe("Mixins tests", () => { it("try creating mixin class with unknown base class, throws error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel", baseClassKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Mixin ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel", baseClassKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `Mixin ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); it("try creating mixin with existing name, throws error", async () => { await testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel"); - await expect(testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.create(testKey, "testMixin", entityKey, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Mixin testSchema.testMixin already exists in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); @@ -198,7 +224,7 @@ describe("Mixins tests", () => { label: "testDec", }; const unitResult = await testEditor.unitSystems.createFromProps(testKey, unitSystemProps); - await expect(testEditor.mixins.create(testKey, "testMixin", unitResult, "testLabel")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.create(testKey, "testMixin", unitResult, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Expected ${unitResult.fullName} to be of type EntityClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -207,7 +233,7 @@ describe("Mixins tests", () => { it("try creating mixin with unknown appliesTo key, throws error", async () => { const badKey = new SchemaItemKey("unknownEntityKey", testKey); - await expect(testEditor.mixins.create(testKey, "testMixin", badKey, "testLabel")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.mixins.create(testKey, "testMixin", badKey, "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `EntityClass ${badKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); diff --git a/core/ecschema-editing/src/test/Editing/Phenomena.test.ts b/core/ecschema-editing/src/test/Editing/Phenomena.test.ts index 48ad6bd825b6..a884b0a61232 100644 --- a/core/ecschema-editing/src/test/Editing/Phenomena.test.ts +++ b/core/ecschema-editing/src/test/Editing/Phenomena.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECVersion, Phenomenon, SchemaContext, SchemaKey } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -39,8 +39,8 @@ describe("Phenomenons tests", () => { }); it("try creating Phenomenon class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.phenomenons.create(badKey, "testPhenomenon", "Units.LENGTH(2)")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.phenomenons.create(badKey, "testPhenomenon", "Units.LENGTH(2)")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -49,9 +49,12 @@ describe("Phenomenons tests", () => { it("try creating Phenomenon with existing name, throws error", async () => { await testEditor.phenomenons.create(testKey, "testPhenomenon", "Units.LENGTH(2)"); - await expect(testEditor.phenomenons.create(testKey, "testPhenomenon", "Units.LENGTH(2)")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.phenomenons.create(testKey, "testPhenomenon", "Units.LENGTH(2)")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Phenomenon testSchema.testPhenomenon already exists in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Phenomenon testSchema.testPhenomenon already exists in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); }); }); diff --git a/core/ecschema-editing/src/test/Editing/Properties.test.ts b/core/ecschema-editing/src/test/Editing/Properties.test.ts index eebc6cde3cbd..96725cc336c8 100644 --- a/core/ecschema-editing/src/test/Editing/Properties.test.ts +++ b/core/ecschema-editing/src/test/Editing/Properties.test.ts @@ -1,4 +1,20 @@ -import { ECClassModifier, EntityClass, Enumeration, EnumerationProperty, KindOfQuantity, PrimitiveArrayProperty, PrimitiveProperty, PrimitiveType, PropertyCategory, Schema, SchemaContext, SchemaItemKey, SchemaKey, StructClass, UnitSystem } from "@itwin/ecschema-metadata"; +import { + ECClassModifier, + EntityClass, + Enumeration, + EnumerationProperty, + KindOfQuantity, + PrimitiveArrayProperty, + PrimitiveProperty, + PrimitiveType, + PropertyCategory, + Schema, + SchemaContext, + SchemaItemKey, + SchemaKey, + StructClass, + UnitSystem, +} from "@itwin/ecschema-metadata"; import { expect } from "chai"; import { SchemaContextEditor } from "../../ecschema-editing"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -73,9 +89,12 @@ describe("Properties editing tests", () => { it("try editing a property of where schema cannot be located, rejected with error.", async () => { const badKey = new SchemaItemKey("className", new SchemaKey("badSchema", testKey.version)); - await expect(testEditor.entities.properties.setName(badKey, "TestProperty", "TestProperty1")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.properties.setName(badKey, "TestProperty", "TestProperty1")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.schemaKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property( + "innerError.message", + `Schema Key ${badKey.schemaKey.toString(true)} could not be found in the context.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); }); }); @@ -83,9 +102,12 @@ describe("Properties editing tests", () => { it("try editing a property of a non-existent class, rejected with error.", async () => { const badKey = new SchemaItemKey("badName", testKey); - await expect(testEditor.entities.properties.setName(badKey, "TestProperty", "TestProperty1")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.properties.setName(badKey, "TestProperty", "TestProperty1")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `EntityClass ${badKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ${badKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); @@ -93,22 +115,32 @@ describe("Properties editing tests", () => { it("try editing a non-existent property in the class, rejected with error.", async () => { await testEditor.entities.createPrimitiveProperty(entityKey, "TestProperty", PrimitiveType.Double); - await expect(testEditor.entities.properties.setName(entityKey, "TestProperty2", "TestProperty3")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `An ECProperty with the name TestProperty2 could not be found in the class ${entityKey.fullName}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyNotFound); - }); + await expect(testEditor.entities.properties.setName(entityKey, "TestProperty2", "TestProperty3")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property( + "innerError.message", + `An ECProperty with the name TestProperty2 could not be found in the class ${entityKey.fullName}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyNotFound); + }, + ); }); it("try renaming property to existing name in class, returns error.", async () => { await testEditor.entities.createPrimitiveProperty(entityKey, "TestProperty", PrimitiveType.Double); await testEditor.entities.createPrimitiveProperty(entityKey, "TestProperty2", PrimitiveType.Double); - await expect(testEditor.entities.properties.setName(entityKey, "TestProperty", "TestProperty2")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `An ECProperty with the name TestProperty2 already exists in the class ${entityKey.fullName}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); - }); + await expect(testEditor.entities.properties.setName(entityKey, "TestProperty", "TestProperty2")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property( + "innerError.message", + `An ECProperty with the name TestProperty2 already exists in the class ${entityKey.fullName}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); + }, + ); }); it("try renaming property to existing name in base class, rejected with error.", async () => { @@ -134,11 +166,16 @@ describe("Properties editing tests", () => { await testEditor.entities.createPrimitiveProperty(baseClassKey, "BasePropertyName", PrimitiveType.Double); await testEditor.entities.createPrimitiveProperty(result, "ChildPropertyName", PrimitiveType.Double); - await expect(testEditor.entities.properties.setName(result, "ChildPropertyName", "BasePropertyName")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `An ECProperty with the name BasePropertyName already exists in the class ${baseClassKey.fullName}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); - }); + await expect(testEditor.entities.properties.setName(result, "ChildPropertyName", "BasePropertyName")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property( + "innerError.message", + `An ECProperty with the name BasePropertyName already exists in the class ${baseClassKey.fullName}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); + }, + ); }); it("try renaming property to existing name in child class, rejected with error.", async () => { @@ -164,11 +201,16 @@ describe("Properties editing tests", () => { await testEditor.entities.createPrimitiveProperty(baseClassKey, "BasePropertyName", PrimitiveType.Double); await testEditor.entities.createPrimitiveProperty(result, "ChildPropertyName", PrimitiveType.Double); - await expect(testEditor.entities.properties.setName(baseClassKey, "BasePropertyName", "ChildPropertyName")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `An ECProperty with the name ChildPropertyName already exists in the class ${result.fullName}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); - }); + await expect(testEditor.entities.properties.setName(baseClassKey, "BasePropertyName", "ChildPropertyName")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property( + "innerError.message", + `An ECProperty with the name ChildPropertyName already exists in the class ${result.fullName}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyAlreadyExists); + }, + ); }); it("should successfully rename class property", async () => { @@ -235,23 +277,30 @@ describe("Properties editing tests", () => { const notACategory = await testEditor.entities.create(testKey, "notACategory", ECClassModifier.None); await testEditor.entities.createPrimitiveProperty(entityKey, "testProperty", PrimitiveType.String); - await expect(testEditor.entities.properties.setCategory(entityKey, "testProperty", notACategory)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetCategory); - expect(error).to.have.nested.property("innerError.message", `Expected ${notACategory.fullName} to be of type PropertyCategory.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); - }); + await expect(testEditor.entities.properties.setCategory(entityKey, "testProperty", notACategory)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetCategory); + expect(error).to.have.nested.property("innerError.message", `Expected ${notACategory.fullName} to be of type PropertyCategory.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); + }, + ); }); it("try setting property category to an unknown category, throws error", async () => { const unknownCategory = new SchemaItemKey("unknownCategory", testKey); await testEditor.entities.createPrimitiveProperty(entityKey, "testProperty", PrimitiveType.String); - await expect(testEditor.entities.properties.setCategory(entityKey, "testProperty", unknownCategory)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetCategory); + await expect(testEditor.entities.properties.setCategory(entityKey, "testProperty", unknownCategory)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetCategory); - expect(error).to.have.nested.property("innerError.message", `PropertyCategory ${unknownCategory.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + expect(error).to.have.nested.property( + "innerError.message", + `PropertyCategory ${unknownCategory.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); it("CustomAttribute defined in same schema, instance added to property successfully.", async () => { @@ -335,7 +384,9 @@ describe("Properties editing tests", () => { const testClass = await schemaA.getItem("testEntity"); const property = await testClass?.getProperty("testProperty"); - await testEditor.entities.properties.addCustomAttribute(testClass?.key as SchemaItemKey, "testProperty", { className: "SchemaB.testCustomAttribute" }); + await testEditor.entities.properties.addCustomAttribute(testClass?.key as SchemaItemKey, "testProperty", { + className: "SchemaB.testCustomAttribute", + }); expect(property!.customAttributes && property!.customAttributes.has("SchemaB.testCustomAttribute")).to.be.true; }); @@ -369,11 +420,15 @@ describe("Properties editing tests", () => { testEditor = new SchemaContextEditor(context); const badKey = new SchemaItemKey("BadClass", testSchema.schemaKey); - await expect(testEditor.entities.properties.addCustomAttribute(badKey, "testProperty", { className: "testCustomAttribute" })).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToProperty); - expect(error).to.have.nested.property("innerError.message", `EntityClass ${badKey.fullName} could not be found in the schema ${testSchema.schemaKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + await expect(testEditor.entities.properties.addCustomAttribute(badKey, "testProperty", { className: "testCustomAttribute" })).to.be.eventually + .rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToProperty); + expect(error).to.have.nested.property( + "innerError.message", + `EntityClass ${badKey.fullName} could not be found in the schema ${testSchema.schemaKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }); }); it("Adding a CustomAttribute to a non-existent property fails as expected.", async () => { @@ -405,15 +460,20 @@ describe("Properties editing tests", () => { testEditor = new SchemaContextEditor(context); const testClass = await testSchema.getItem("testEntity"); - await expect(testEditor.entities.properties.addCustomAttribute(testClass?.key as SchemaItemKey, "badPropertyName", { className: "testCustomAttribute" })).to.be.eventually.rejected.then(function (error) { + await expect( + testEditor.entities.properties.addCustomAttribute(testClass?.key as SchemaItemKey, "badPropertyName", { className: "testCustomAttribute" }), + ).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddCustomAttributeToProperty); - expect(error).to.have.nested.property("innerError.message", `An ECProperty with the name badPropertyName could not be found in the class ${testClass?.key.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `An ECProperty with the name badPropertyName could not be found in the class ${testClass?.key.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.PropertyNotFound); }); }); - it("editing an entities property where the specified SchemaItemKey does return an EntityClass, rejected with error", async () => { - await expect(testEditor.entities.arrayProperties.setMaxOccurs(structKey, "TestProperty", 1)).to.be.eventually.rejected.then(function (error) { + it("editing an entities property where the specified SchemaItemKey does return an EntityClass, rejected with error", async () => { + await expect(testEditor.entities.arrayProperties.setMaxOccurs(structKey, "TestProperty", 1)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetMaxOccurs); expect(error).to.have.nested.property("innerError.message", `Expected ${structKey.fullName} to be of type EntityClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -431,7 +491,7 @@ describe("Properties editing tests", () => { maxOccurs: 55, }; - await testEditor.entities.createPrimitiveArrayPropertyFromProps(entityKey, "TestProperty", PrimitiveType.Integer,propertyJson); + await testEditor.entities.createPrimitiveArrayPropertyFromProps(entityKey, "TestProperty", PrimitiveType.Integer, propertyJson); const property = await entity?.getProperty("TestProperty") as PrimitiveArrayProperty; expect(property.minOccurs).to.eql(42); expect(property.maxOccurs).to.eql(55); @@ -443,9 +503,9 @@ describe("Properties editing tests", () => { expect(property.maxOccurs).to.eql(56); }); - it("editing a array property attribute not belonging to the proper property type, rejected with error", async () => { + it("editing a array property attribute not belonging to the proper property type, rejected with error", async () => { await testEditor.entities.createPrimitiveProperty(entityKey, "TestProperty", PrimitiveType.Double); - await expect(testEditor.entities.arrayProperties.setMaxOccurs(entityKey, "TestProperty", 1)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.arrayProperties.setMaxOccurs(entityKey, "TestProperty", 1)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetMaxOccurs); expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type ArrayProperty.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); @@ -504,10 +564,10 @@ describe("Properties editing tests", () => { expect(property.maxValue).to.eql(1000); }); - it("editing a primitive property attribute not belonging to the proper property type, rejected with error", async () => { + it("editing a primitive property attribute not belonging to the proper property type, rejected with error", async () => { const structClass = await testEditor.schemaContext.getSchemaItem(structKey); await testEditor.entities.createStructProperty(entityKey, "TestProperty", structClass!); - await expect(testEditor.entities.primitiveProperties.setMinValue(entityKey, "TestProperty", 1)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.entities.primitiveProperties.setMinValue(entityKey, "TestProperty", 1)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetMinValue); expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type PrimitiveProperty.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); @@ -581,39 +641,45 @@ describe("Properties editing tests", () => { expect(property.maxValue).to.eql(1000); }); - it("editing a enumeration property attribute not belonging to the proper property type, rejected with error", async () => { + it("editing a enumeration property attribute not belonging to the proper property type, rejected with error", async () => { const structClass = await testEditor.schemaContext.getSchemaItem(structKey); await testEditor.entities.createStructProperty(entityKey, "TestProperty", structClass!); - await expect(testEditor.entities.enumerationProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type EnumerationProperty.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); - }); + await expect(testEditor.entities.enumerationProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type EnumerationProperty.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); + }, + ); }); }); describe("Navigation property editing tests", () => { - it("editing a property through navigationProperties that is not a NavigationProperty, rejected with error", async () => { + it("editing a property through navigationProperties that is not a NavigationProperty, rejected with error", async () => { const structClass = await testEditor.schemaContext.getSchemaItem(structKey); await testEditor.entities.createStructProperty(entityKey, "TestProperty", structClass!); - await expect(testEditor.entities.navigationProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type NavigationProperty.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); - }); + await expect(testEditor.entities.navigationProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type NavigationProperty.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); + }, + ); }); }); describe("Struct property editing tests", () => { - it("editing a property through structProperties that is not a StructProperty, rejected with error", async () => { + it("editing a property through structProperties that is not a StructProperty, rejected with error", async () => { const schema = await testEditor.getSchema(testKey); const testEnum = new Enumeration(schema, "TestEnumeration"); await testEditor.entities.createEnumerationProperty(entityKey, "TestProperty", testEnum); - await expect(testEditor.entities.structProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); - expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type StructProperty.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); - }); + await expect(testEditor.entities.structProperties.setName(entityKey, "TestProperty", "testName")).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetPropertyName); + expect(error).to.have.nested.property("innerError.message", `Expected property TestProperty to be of type StructProperty.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidPropertyType); + }, + ); }); }); @@ -640,23 +706,30 @@ describe("Properties editing tests", () => { const notAKindOfQuantity = await testEditor.entities.create(testKey, "notAKindOfQuantity", ECClassModifier.None); await testEditor.entities.createPrimitiveProperty(entityKey, "testProperty", PrimitiveType.String); - await expect(testEditor.entities.properties.setKindOfQuantity(entityKey, "testProperty", notAKindOfQuantity)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetKindOfQuantity); - expect(error).to.have.nested.property("innerError.message", `Expected ${notAKindOfQuantity.fullName} to be of type KindOfQuantity.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); - }); + await expect(testEditor.entities.properties.setKindOfQuantity(entityKey, "testProperty", notAKindOfQuantity)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetKindOfQuantity); + expect(error).to.have.nested.property("innerError.message", `Expected ${notAKindOfQuantity.fullName} to be of type KindOfQuantity.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); + }, + ); }); it("try setting property KindOfQuantity to an unknown KindOfQuantity, throws error", async () => { const unknownKOQ = new SchemaItemKey("unknownKindOfQuantity", testKey); await testEditor.entities.createPrimitiveProperty(entityKey, "testProperty", PrimitiveType.String); - await expect(testEditor.entities.properties.setKindOfQuantity(entityKey, "testProperty", unknownKOQ)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.SetKindOfQuantity); + await expect(testEditor.entities.properties.setKindOfQuantity(entityKey, "testProperty", unknownKOQ)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.SetKindOfQuantity); - expect(error).to.have.nested.property("innerError.message", `KindOfQuantity ${unknownKOQ.fullName} could not be found in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); - }); + expect(error).to.have.nested.property( + "innerError.message", + `KindOfQuantity ${unknownKOQ.fullName} could not be found in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); + }, + ); }); }); }); diff --git a/core/ecschema-editing/src/test/Editing/PropertyCategories.test.ts b/core/ecschema-editing/src/test/Editing/PropertyCategories.test.ts index bbc23b6e899e..11d4ffa28d88 100644 --- a/core/ecschema-editing/src/test/Editing/PropertyCategories.test.ts +++ b/core/ecschema-editing/src/test/Editing/PropertyCategories.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECVersion, PropertyCategory, SchemaContext, SchemaItemType, SchemaKey } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -39,8 +39,8 @@ describe("Property Category tests", () => { }); it("try creating PropertyCategory to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.propertyCategories.create(badKey, "testPropCategory", 5)).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.propertyCategories.create(badKey, "testPropCategory", 5)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -49,9 +49,12 @@ describe("Property Category tests", () => { it("try creating PropertyCategory with existing name, throws error", async () => { await testEditor.propertyCategories.create(testKey, "testPropCategory", 5); - await expect(testEditor.propertyCategories.create(testKey, "testPropCategory", 5)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.propertyCategories.create(testKey, "testPropCategory", 5)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `PropertyCategory testSchema.testPropCategory already exists in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `PropertyCategory testSchema.testPropCategory already exists in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); }); }); diff --git a/core/ecschema-editing/src/test/Editing/RelationshipClasses.test.ts b/core/ecschema-editing/src/test/Editing/RelationshipClasses.test.ts index e5a6f7d846e9..c4b762b6a8f3 100644 --- a/core/ecschema-editing/src/test/Editing/RelationshipClasses.test.ts +++ b/core/ecschema-editing/src/test/Editing/RelationshipClasses.test.ts @@ -2,18 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - ECClassModifier, ECVersion, EntityClass, NavigationProperty, NavigationPropertyProps, RelationshipClass, RelationshipClassProps, RelationshipConstraint, - RelationshipConstraintProps, RelationshipEnd, Schema, SchemaContext, SchemaItemKey, SchemaKey, StrengthDirection, StrengthType, + ECClassModifier, + ECVersion, + EntityClass, + NavigationProperty, + NavigationPropertyProps, + RelationshipClass, + RelationshipClassProps, + RelationshipConstraint, + RelationshipConstraintProps, + RelationshipEnd, + Schema, + SchemaContext, + SchemaItemKey, + SchemaKey, + StrengthDirection, + StrengthType, } from "@itwin/ecschema-metadata"; -import { SchemaContextEditor } from "../../Editing/Editor"; +import { expect } from "chai"; import { AnyDiagnostic, Diagnostics } from "../../ecschema-editing"; +import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; function getRuleViolationMessage(ruleViolations: AnyDiagnostic[]) { let violations = ""; - for (const diagnostic of ruleViolations){ + for (const diagnostic of ruleViolations) { violations += `${diagnostic.code}: ${diagnostic.messageText}\r\n`; } return violations; @@ -116,7 +130,13 @@ describe("Relationship tests from an existing schema", () => { }); it("should create a relationship class via the create method", async () => { - const result = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward); + const result = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + ); const relClass = await testEditor.schemaContext.getSchemaItem(result) as RelationshipClass; expect(relClass.name).to.equal("TestRelationship"); expect(relClass.modifier).to.equal(ECClassModifier.None); @@ -154,7 +174,14 @@ describe("Relationship tests from an existing schema", () => { const baseResult = await testEditor.relationships.createFromProps(testKey, relClassProps); const baseRelClass = await testEditor.schemaContext.getSchemaItem(baseResult) as RelationshipClass; - const result = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward, baseRelClass.key); + const result = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + baseRelClass.key, + ); const testRelationship = await testEditor.schemaContext.getSchemaItem(result); expect(await testRelationship?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseRelClass.key)); @@ -190,15 +217,35 @@ describe("Relationship tests from an existing schema", () => { const baseResult = await testEditor.relationships.createFromProps(refKey, relClassProps); const baseRelClass = await testEditor.schemaContext.getSchemaItem(baseResult) as RelationshipClass; - const result = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward, baseRelClass.key); + const result = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + baseRelClass.key, + ); const testRelationship = await testEditor.schemaContext.getSchemaItem(result); expect(await testRelationship?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseRelClass.key)); }); it("should remove a base class from relationship class", async () => { - const baseClassRes = await testEditor.relationships.create(testKey, "testBaseClass", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); - const relRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward,baseClassRes); + const baseClassRes = await testEditor.relationships.create( + testKey, + "testBaseClass", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); + const relRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + baseClassRes, + ); const testRel = await testEditor.schemaContext.getSchemaItem(relRes); expect(await testRel?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); @@ -350,7 +397,13 @@ describe("Relationship tests from an existing schema", () => { }); it("should set source and target constraints to the relationship", async () => { - const relClassResult = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); + const relClassResult = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); const relClass = await testEditor.schemaContext.getSchemaItem(relClassResult) as RelationshipClass; const sourceConstraint = new RelationshipConstraint(relClass, RelationshipEnd.Source, "source label", true); await testEditor.relationships.setSourceConstraint(relClass.key, sourceConstraint); @@ -361,7 +414,13 @@ describe("Relationship tests from an existing schema", () => { }); it("should create a navigation property", async () => { - const relClassResult = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); + const relClassResult = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); const relClass = await testEditor.schemaContext.getSchemaItem(relClassResult) as RelationshipClass; await testEditor.relationships.createNavigationProperty(relClass.key, "TestProperty", "TestSchema.TestRelationship", "Forward"); const navProperty = await relClass.getProperty("TestProperty") as NavigationProperty; @@ -408,7 +467,13 @@ describe("Relationship tests from an existing schema", () => { }); it("should add a constraint class", async () => { - const relResult = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward); + const relResult = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + ); const relClass = await testEditor.schemaContext.getSchemaItem(relResult) as RelationshipClass; const constraint = new RelationshipConstraint(relClass, RelationshipEnd.Source, "source label", true); await testEditor.relationships.setSourceConstraint(relClass.key, constraint); @@ -545,17 +610,33 @@ describe("Relationship tests from an existing schema", () => { const relClassResult = await testEditor.relationships.createFromProps(testKey, relClassProps); const relClass = await testEditor.schemaContext.getSchemaItem(relClassResult) as RelationshipClass; - const constraintClassResult = await testEditor.relationships.create(testKey, "MyRelationship", ECClassModifier.Sealed, StrengthType.Holding, StrengthDirection.Forward); + const constraintClassResult = await testEditor.relationships.create( + testKey, + "MyRelationship", + ECClassModifier.Sealed, + StrengthType.Holding, + StrengthDirection.Forward, + ); const constraintClass = await testEditor.schemaContext.getSchemaItem(constraintClassResult) as RelationshipClass; try { await testEditor.relationships.addConstraintClass(relClass.source, constraintClass); - } catch(e: any) { + } catch (e: any) { expect(e).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; - expect(violations[0]).to.deep.equal(new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(relClass, [constraintClass.fullName, "Source", relClass.fullName, (await relClass.source.abstractConstraint)!.fullName])); + expect(violations[0]).to.deep.equal( + new Diagnostics.ConstraintClassesDeriveFromAbstractConstraint(relClass, [ + constraintClass.fullName, + "Source", + relClass.fullName, + (await relClass.source.abstractConstraint)!.fullName, + ]), + ); expect(relClass.source.constraintClasses?.length).to.eq(1); expect((await relClass.source.constraintClasses![0]).fullName).to.eq("TestSchema.TestSourceEntity"); } @@ -586,7 +667,14 @@ describe("Relationship tests from an existing schema", () => { const baseRelClassResult = await testEditor.relationships.createFromProps(testKey, relClassProps); const baseRelClass = await testEditor.schemaContext.getSchemaItem(baseRelClassResult) as RelationshipClass; - const relClassResult = await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.Sealed, StrengthType.Embedding, StrengthDirection.Forward, baseRelClass.key); + const relClassResult = await testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.Sealed, + StrengthType.Embedding, + StrengthDirection.Forward, + baseRelClass.key, + ); const relClass = await testEditor.schemaContext.getSchemaItem(relClassResult) as RelationshipClass; const constraint = new RelationshipConstraint(relClass, RelationshipEnd.Source, "source label", true); await testEditor.relationships.setSourceConstraint(relClass.key, constraint); @@ -596,13 +684,30 @@ describe("Relationship tests from an existing schema", () => { try { await testEditor.relationships.addConstraintClass(relClass.source, entityClass); - } catch(e: any) { + } catch (e: any) { expect(e).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; - expect(violations[0]).to.deep.equal(new Diagnostics.AbstractConstraintMustNarrowBaseConstraints(relClass, [entityClass.fullName, "Source", relClass.fullName, baseRelClass.fullName])); - expect(violations[1]).to.deep.equal(new Diagnostics.DerivedConstraintsMustNarrowBaseConstraints(relClass, [entityClass.fullName, "Source", relClass.fullName, baseRelClass.fullName])); + expect(violations[0]).to.deep.equal( + new Diagnostics.AbstractConstraintMustNarrowBaseConstraints(relClass, [ + entityClass.fullName, + "Source", + relClass.fullName, + baseRelClass.fullName, + ]), + ); + expect(violations[1]).to.deep.equal( + new Diagnostics.DerivedConstraintsMustNarrowBaseConstraints(relClass, [ + entityClass.fullName, + "Source", + relClass.fullName, + baseRelClass.fullName, + ]), + ); } }); @@ -635,12 +740,19 @@ describe("Relationship tests from an existing schema", () => { try { await testEditor.relationships.addConstraintClass(relClass.source, constraintClass); - } catch(e: any) { + } catch (e: any) { expect(e).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from Source constraint of RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from Source constraint of RelationshipClass ${relClassResult.fullName}: ${ + getRuleViolationMessage(e.innerError.ruleViolations) + }`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; - expect(violations[0]).to.deep.equal(new Diagnostics.AbstractConstraintMustExistWithMultipleConstraints(relClass.source, ["Source", relClass.fullName])); + expect(violations[0]).to.deep.equal( + new Diagnostics.AbstractConstraintMustExistWithMultipleConstraints(relClass.source, ["Source", relClass.fullName]), + ); expect(relClass.source.constraintClasses?.length).to.eq(1); expect((await relClass.source.constraintClasses![0]).fullName).to.eq("TestSchema.TestSourceEntity"); } @@ -675,10 +787,15 @@ describe("Relationship tests from an existing schema", () => { try { await testEditor.relationships.removeConstraintClass(relClass.target, constraintClass); - } catch(e: any) { + } catch (e: any) { expect(e).to.have.property("errorNumber", ECEditingStatus.RemoveConstraintClass); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from Target constraint of RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from Target constraint of RelationshipClass ${relClassResult.fullName}: ${ + getRuleViolationMessage(e.innerError.ruleViolations) + }`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; expect(violations[0]).to.deep.equal(new Diagnostics.AtLeastOneConstraintClassDefined(relClass.target, ["Target", relClass.fullName])); expect(relClass.target.constraintClasses?.length).to.eq(1); @@ -716,13 +833,20 @@ describe("Relationship tests from an existing schema", () => { try { await testEditor.relationships.setAbstractConstraint(relClass.source, undefined); - } catch(e: any) { + } catch (e: any) { expect((await relClass.source.constraintClasses![0]).fullName).eq("TestSchema.TestSourceEntity"); expect(e).to.have.property("errorNumber", ECEditingStatus.SetAbstractConstraint); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from Source constraint of RelationshipClass ${relClassResult.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from Source constraint of RelationshipClass ${relClassResult.fullName}: ${ + getRuleViolationMessage(e.innerError.ruleViolations) + }`, + ); const violations = e.innerError.ruleViolations as AnyDiagnostic[]; - expect(violations[0]).to.deep.equal(new Diagnostics.AbstractConstraintMustExistWithMultipleConstraints(relClass.source, ["Source", relClass.fullName])); + expect(violations[0]).to.deep.equal( + new Diagnostics.AbstractConstraintMustExistWithMultipleConstraints(relClass.source, ["Source", relClass.fullName]), + ); expect((await relClass.source.constraintClasses![0]).fullName).eq("TestSchema.TestSourceEntity"); } }); @@ -782,8 +906,14 @@ describe("Relationship tests from an existing schema", () => { it("try adding base class to relationship class with different SchemaItemType, returns error", async () => { const baseClassRes = await testEditor.entities.create(testKey, "testBaseClass", ECClassModifier.None); - const relRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward); - await expect(testEditor.relationships.setBaseClass(relRes, baseClassRes)).to.be.eventually.rejected.then(function (error) { + const relRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + ); + await expect(testEditor.relationships.setBaseClass(relRes, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Expected ${baseClassRes.fullName} to be of type RelationshipClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -792,32 +922,56 @@ describe("Relationship tests from an existing schema", () => { it("try adding base class to a relationship class where the base class cannot be located, returns error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - const relRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Referencing, StrengthDirection.Forward); - - await expect(testEditor.relationships.setBaseClass(relRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + const relRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Referencing, + StrengthDirection.Forward, + ); + + await expect(testEditor.relationships.setBaseClass(relRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `RelationshipClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `RelationshipClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); it("try adding base class to non-existing relationship class, returns error", async () => { - const baseClassRes = await testEditor.relationships.create(testKey, "testBaseClass", ECClassModifier.None, StrengthType.Referencing, StrengthDirection.Forward); + const baseClassRes = await testEditor.relationships.create( + testKey, + "testBaseClass", + ECClassModifier.None, + StrengthType.Referencing, + StrengthDirection.Forward, + ); const relationshipKey = new SchemaItemKey("testRelationship", testKey); - await expect(testEditor.relationships.setBaseClass(relationshipKey, baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.relationships.setBaseClass(relationshipKey, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `RelationshipClass ${relationshipKey.fullName} could not be found in the schema context.`); + expect(error).to.have.nested.property( + "innerError.message", + `RelationshipClass ${relationshipKey.fullName} could not be found in the schema context.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); }); }); it("try adding base class with unknown schema to relationship class, returns error", async () => { - const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); + const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", schemaKey); - const relRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Referencing, StrengthDirection.Forward); - - await expect(testEditor.relationships.setBaseClass(relRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + const relRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Referencing, + StrengthDirection.Forward, + ); + + await expect(testEditor.relationships.setBaseClass(relRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${schemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -825,17 +979,39 @@ describe("Relationship tests from an existing schema", () => { }); it("try changing the relationship base class to one that doesn't derive from, returns error", async () => { - const baseClassRes = await testEditor.relationships.create(testKey, "testBaseClass", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); - const relRes = await testEditor.relationships.create(testKey, "testRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward, baseClassRes); - const newBaseClassRes = await testEditor.relationships.create(testKey, "newBaseClass", ECClassModifier.None, StrengthType.Embedding, StrengthDirection.Forward); + const baseClassRes = await testEditor.relationships.create( + testKey, + "testBaseClass", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); + const relRes = await testEditor.relationships.create( + testKey, + "testRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + baseClassRes, + ); + const newBaseClassRes = await testEditor.relationships.create( + testKey, + "newBaseClass", + ECClassModifier.None, + StrengthType.Embedding, + StrengthDirection.Forward, + ); const relClass = await testEditor.schemaContext.getSchemaItem(relRes); const baseClass = await testEditor.schemaContext.getSchemaItem(baseClassRes); expect(await relClass?.baseClass).to.eql(baseClass); - await expect(testEditor.relationships.setBaseClass(relRes, newBaseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.relationships.setBaseClass(relRes, newBaseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); @@ -901,24 +1077,40 @@ describe("Relationship tests from an existing schema", () => { expect(relClass.baseClass).to.be.undefined; expect(e).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(e).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(e).to.have.nested.property("innerError.message", `Rule violations occurred from RelationshipClass ${relRes.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`); + expect(e).to.have.nested.property( + "innerError.message", + `Rule violations occurred from RelationshipClass ${relRes.fullName}: ${getRuleViolationMessage(e.innerError.ruleViolations)}`, + ); } }); it("try creating Relationship class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.relationships.create(badKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.relationships.create(badKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward)) + .to.be.eventually.rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }); }); it("try creating Relationship class with unknown base class, throws error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect( + testEditor.relationships.create( + testKey, + "TestRelationship", + ECClassModifier.None, + StrengthType.Holding, + StrengthDirection.Forward, + baseClassKey, + ), + ).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `RelationshipClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `RelationshipClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); @@ -926,10 +1118,14 @@ describe("Relationship tests from an existing schema", () => { it("try creating Relationship with existing name, throws error", async () => { await testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward); - await expect(testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `RelationshipClass TestSchema.TestRelationship already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.relationships.create(testKey, "TestRelationship", ECClassModifier.None, StrengthType.Holding, StrengthDirection.Forward)) + .to.be.eventually.rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property( + "innerError.message", + `RelationshipClass TestSchema.TestRelationship already exists in the schema ${testKey.name}.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }); }); }); diff --git a/core/ecschema-editing/src/test/Editing/SchemaItems.test.ts b/core/ecschema-editing/src/test/Editing/SchemaItems.test.ts index 9a9d5b801bbe..c917b87d392f 100644 --- a/core/ecschema-editing/src/test/Editing/SchemaItems.test.ts +++ b/core/ecschema-editing/src/test/Editing/SchemaItems.test.ts @@ -34,7 +34,7 @@ describe("Properties editing tests", () => { it("try setting description to unknown SchemaItem, returns error", async () => { const unknownKey = new SchemaItemKey("testUnitSystem", testKey); - await expect(testEditor.unitSystems.setDescription(unknownKey, "test description")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.unitSystems.setDescription(unknownKey, "test description")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetDescription); expect(error).to.have.nested.property("innerError.message", `UnitSystem ${unknownKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -44,7 +44,7 @@ describe("Properties editing tests", () => { it("try setting label to unknown SchemaItem, returns error", async () => { const unknownKey = new SchemaItemKey("testUnitSystem", testKey); - await expect(testEditor.unitSystems.setDisplayLabel(unknownKey, "label")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.unitSystems.setDisplayLabel(unknownKey, "label")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetLabel); expect(error).to.have.nested.property("innerError.message", `UnitSystem ${unknownKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); diff --git a/core/ecschema-editing/src/test/Editing/Structs.test.ts b/core/ecschema-editing/src/test/Editing/Structs.test.ts index a6eea5c7b679..ef5d68d7b37a 100644 --- a/core/ecschema-editing/src/test/Editing/Structs.test.ts +++ b/core/ecschema-editing/src/test/Editing/Structs.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECClassModifier, ECVersion, Schema, SchemaContext, SchemaItemKey, SchemaKey, StructClass } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -117,7 +117,7 @@ describe("Structs tests", () => { const baseClassRes = await testEditor.entities.create(testKey, "testBaseClass", ECClassModifier.None); const structRes = await testEditor.structs.create(testKey, "testStruct", "testLabel"); - await expect(testEditor.structs.setBaseClass(structRes, baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.setBaseClass(structRes, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Expected ${baseClassRes.fullName} to be of type StructClass.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidSchemaItemType); @@ -128,18 +128,21 @@ describe("Structs tests", () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); const structRes = await testEditor.structs.create(testKey, "testStruct", "testLabel"); - await expect(testEditor.structs.setBaseClass(structRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.setBaseClass(structRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `StructClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `StructClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); it("try adding base class to non-existing struct class, returns error", async () => { const baseClassRes = await testEditor.structs.create(testKey, "testBaseClass"); - const structKey = new SchemaItemKey("testStruct", testKey); + const structKey = new SchemaItemKey("testStruct", testKey); - await expect(testEditor.structs.setBaseClass(structKey, baseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.setBaseClass(structKey, baseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `StructClass ${structKey.fullName} could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -147,11 +150,11 @@ describe("Structs tests", () => { }); it("try adding base class with unknown schema to existing struct class, returns error", async () => { - const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); + const schemaKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); const baseClassKey = new SchemaItemKey("testBaseClass", schemaKey); const structRes = await testEditor.structs.create(testKey, "testStruct", "testLabel"); - await expect(testEditor.structs.setBaseClass(structRes, baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.setBaseClass(structRes, baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Schema Key ${schemaKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -166,16 +169,19 @@ describe("Structs tests", () => { expect(await testStruct?.baseClass).to.eql(await testEditor.schemaContext.getSchemaItem(baseClassRes)); const newBaseClassRes = await testEditor.structs.create(testKey, "newBaseClass"); - await expect(testEditor.structs.setBaseClass(structRes, newBaseClassRes)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.setBaseClass(structRes, newBaseClassRes)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class ${newBaseClassRes.fullName} must derive from ${baseClassRes.fullName}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); it("try creating Struct class to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.structs.create(badKey, "testStruct", "testLabel")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.structs.create(badKey, "testStruct", "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -184,16 +190,19 @@ describe("Structs tests", () => { it("try creating Struct class with unknown base class, throws error", async () => { const baseClassKey = new SchemaItemKey("testBaseClass", testKey); - await expect(testEditor.structs.create(testKey, "testStruct", "testLabel", baseClassKey)).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.create(testKey, "testStruct", "testLabel", baseClassKey)).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `StructClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `StructClass ${baseClassKey.fullName} could not be found in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFound); }); }); it("try creating Struct with existing name, throws error", async () => { await testEditor.structs.create(testKey, "testStruct", "testLabel"); - await expect(testEditor.structs.create(testKey, "testStruct", "testLabel")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.structs.create(testKey, "testStruct", "testLabel")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `StructClass testSchema.testStruct already exists in the schema ${testKey.name}.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); diff --git a/core/ecschema-editing/src/test/Editing/UnitSystems.test.ts b/core/ecschema-editing/src/test/Editing/UnitSystems.test.ts index 7e2e5464fff2..3236afb13969 100644 --- a/core/ecschema-editing/src/test/Editing/UnitSystems.test.ts +++ b/core/ecschema-editing/src/test/Editing/UnitSystems.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECVersion, SchemaContext, SchemaItemType, SchemaKey, UnitSystem } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -32,8 +32,8 @@ describe("UnitSystems tests", () => { }); it("try creating Unit to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.unitSystems.create(badKey, "testUnitSystem", "testDefinition")).to.be.eventually.rejected.then(function (error) { + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.unitSystems.create(badKey, "testUnitSystem", "testDefinition")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); @@ -42,9 +42,12 @@ describe("UnitSystems tests", () => { it("try creating Unit with existing name, throws error", async () => { await testEditor.unitSystems.create(testKey, "testUnitSystem", "testDefinition"); - await expect(testEditor.unitSystems.create(testKey, "testUnitSystem", "testDefinition")).to.be.eventually.rejected.then(function (error) { + await expect(testEditor.unitSystems.create(testKey, "testUnitSystem", "testDefinition")).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `UnitSystem testSchema.testUnitSystem already exists in the schema ${testKey.name}.`); + expect(error).to.have.nested.property( + "innerError.message", + `UnitSystem testSchema.testUnitSystem already exists in the schema ${testKey.name}.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); }); }); diff --git a/core/ecschema-editing/src/test/Editing/Units.test.ts b/core/ecschema-editing/src/test/Editing/Units.test.ts index 6c84d9945253..770dd585014a 100644 --- a/core/ecschema-editing/src/test/Editing/Units.test.ts +++ b/core/ecschema-editing/src/test/Editing/Units.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ECVersion, SchemaContext, SchemaItemKey, SchemaKey, Unit } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaContextEditor } from "../../Editing/Editor"; import { ECEditingStatus } from "../../Editing/Exception"; @@ -48,20 +48,24 @@ describe("Units tests", () => { }); it("try creating Unit to unknown schema, throws error", async () => { - const badKey = new SchemaKey("unknownSchema", new ECVersion(1,0,0)); - await expect(testEditor.units.create(badKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); - }); + const badKey = new SchemaKey("unknownSchema", new ECVersion(1, 0, 0)); + await expect(testEditor.units.create(badKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Schema Key ${badKey.toString(true)} could not be found in the context.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaNotFound); + }, + ); }); it("try creating Unit with existing name, throws error", async () => { await testEditor.units.create(testKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey); - await expect(testEditor.units.create(testKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey)).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); - expect(error).to.have.nested.property("innerError.message", `Unit testSchema.testUnit already exists in the schema ${testKey.name}.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); - }); + await expect(testEditor.units.create(testKey, "testUnit", "testDefinition", phenomenonKey, unitSystemKey)).to.be.eventually.rejected.then( + function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateSchemaItemFailed); + expect(error).to.have.nested.property("innerError.message", `Unit testSchema.testUnit already exists in the schema ${testKey.name}.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNameAlreadyExists); + }, + ); }); }); diff --git a/core/ecschema-editing/src/test/Editing/mvp.test.ts b/core/ecschema-editing/src/test/Editing/mvp.test.ts index 66f038573a55..23d3b6f17c9c 100644 --- a/core/ecschema-editing/src/test/Editing/mvp.test.ts +++ b/core/ecschema-editing/src/test/Editing/mvp.test.ts @@ -2,14 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + ECClass, + ECClassModifier, + ECVersion, + EntityClass, + PrimitiveProperty, + PrimitiveType, + Schema, + SchemaContext, + SchemaItemKey, + SchemaKey, + SchemaMatchType, +} from "@itwin/ecschema-metadata"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { ECClass, ECClassModifier, ECVersion, EntityClass, PrimitiveProperty, PrimitiveType, Schema, SchemaContext, - SchemaItemKey, SchemaKey, SchemaMatchType, -} from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "../../Editing/Editor"; -import { BisTestHelper } from "../TestUtils/BisTestHelper"; import { ECEditingStatus } from "../../Editing/Exception"; +import { BisTestHelper } from "../TestUtils/BisTestHelper"; const expect = chai.expect; chai.use(chaiAsPromised); @@ -36,14 +46,14 @@ describe("SchemaEditor tests", () => { it("should create a new schema and return a SchemaEditResults", async () => { const schemaKey = await testEditor.createSchema("testSchema", "test", 1, 0, 0); expect(schemaKey).to.not.be.undefined; - expect(schemaKey).to.deep.equal(new SchemaKey("testSchema", new ECVersion(1,0,0))); + expect(schemaKey).to.deep.equal(new SchemaKey("testSchema", new ECVersion(1, 0, 0))); }); }); describe("Class tests", () => { beforeEach(async () => { testSchemaKey = await testEditor.createSchema("testSchema", "test", 1, 0, 0); - const result2 = await testEditor.schemaContext.getCachedSchema(testSchemaKey); + const result2 = await testEditor.schemaContext.getCachedSchema(testSchemaKey); if (!result2) throw new Error("Could not retrieve cached schema!"); testSchema = result2; @@ -84,7 +94,13 @@ describe("SchemaEditor tests", () => { it("should create BisCore.ElementUniqueAspect subclass successfully", async () => { const uniqueAspectKey = new SchemaItemKey("ElementUniqueAspect", bisSchemaKey); - const result = await testEditor.entities.createElementUniqueAspect(testSchemaKey, "testElement", ECClassModifier.None, uniqueAspectKey, "test element"); + const result = await testEditor.entities.createElementUniqueAspect( + testSchemaKey, + "testElement", + ECClassModifier.None, + uniqueAspectKey, + "test element", + ); expect(result).to.not.be.undefined; expect(result).to.deep.equal(new SchemaItemKey("testElement", testSchemaKey)); const element = await testSchema!.getItem("testElement") as ECClass; @@ -96,7 +112,13 @@ describe("SchemaEditor tests", () => { it("should create BisCore.ElementUniqueAspect grandchild successfully", async () => { const elementKey = new SchemaItemKey("ElementUniqueAspect", bisSchemaKey); - const result = await testEditor.entities.createElementUniqueAspect(testSchemaKey, "testElement", ECClassModifier.None, elementKey, "test element"); + const result = await testEditor.entities.createElementUniqueAspect( + testSchemaKey, + "testElement", + ECClassModifier.None, + elementKey, + "test element", + ); expect(result).to.not.be.undefined; expect(result).to.deep.equal(new SchemaItemKey("testElement", testSchemaKey)); const element = await testSchema!.getItem("testElement") as EntityClass; @@ -105,7 +127,13 @@ describe("SchemaEditor tests", () => { expect(baseClass).to.not.be.undefined; expect(baseClass?.key).to.deep.equal(new SchemaItemKey("ElementUniqueAspect", bisSchemaKey)); - const result2 = await testEditor.entities.createElementUniqueAspect(testSchemaKey, "testElement2", ECClassModifier.None, result, "test element2"); + const result2 = await testEditor.entities.createElementUniqueAspect( + testSchemaKey, + "testElement2", + ECClassModifier.None, + result, + "test element2", + ); expect(result2).to.not.be.undefined; expect(result2).to.deep.equal(new SchemaItemKey("testElement2", testSchemaKey)); const element2 = await testSchema!.getItem("testElement2") as EntityClass; @@ -117,7 +145,13 @@ describe("SchemaEditor tests", () => { it("should create BisCore.ElementMultiAspect subclass successfully", async () => { const multiAspectKey = new SchemaItemKey("ElementMultiAspect", bisSchemaKey); - const result = await testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement", ECClassModifier.None, multiAspectKey, "test element"); + const result = await testEditor.entities.createElementMultiAspect( + testSchemaKey, + "testElement", + ECClassModifier.None, + multiAspectKey, + "test element", + ); expect(result).to.not.be.undefined; expect(result).to.deep.equal(new SchemaItemKey("testElement", testSchemaKey)); const element = await testSchema!.getItem("testElement") as ECClass; @@ -129,7 +163,13 @@ describe("SchemaEditor tests", () => { it("should create BisCore.ElementMultiAspect grandchild successfully", async () => { const elementKey = new SchemaItemKey("ElementMultiAspect", bisSchemaKey); - const result = await testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement", ECClassModifier.None, elementKey, "test element"); + const result = await testEditor.entities.createElementMultiAspect( + testSchemaKey, + "testElement", + ECClassModifier.None, + elementKey, + "test element", + ); expect(result).to.not.be.undefined; expect(result).to.deep.equal(new SchemaItemKey("testElement", testSchemaKey)); const element = await testSchema!.getItem("testElement") as EntityClass; @@ -138,7 +178,13 @@ describe("SchemaEditor tests", () => { expect(baseClass).to.not.be.undefined; expect(baseClass?.key).to.deep.equal(new SchemaItemKey("ElementMultiAspect", bisSchemaKey)); - const result2 = await testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement2", ECClassModifier.None, result, "test element2"); + const result2 = await testEditor.entities.createElementMultiAspect( + testSchemaKey, + "testElement2", + ECClassModifier.None, + result, + "test element2", + ); expect(result2).to.not.be.undefined; expect(result2).to.deep.equal(new SchemaItemKey("testElement2", testSchemaKey)); const element2 = await testSchema!.getItem("testElement2") as EntityClass; @@ -150,34 +196,49 @@ describe("SchemaEditor tests", () => { it("Creating Element, try subclassing unsupported base class, throws", async () => { const elementKey = new SchemaItemKey("PhysicalModel", bisSchemaKey); - await expect(testEditor.entities.createElement(testSchemaKey, "testElement", ECClassModifier.None, elementKey, "test element")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); - expect(error).to.have.nested.property("innerError.message", `Expected base class ${elementKey.fullName} to derive from BisCore.Element.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElement); - }); + await expect(testEditor.entities.createElement(testSchemaKey, "testElement", ECClassModifier.None, elementKey, "test element")).to.be.eventually + .rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); + expect(error).to.have.nested.property("innerError.message", `Expected base class ${elementKey.fullName} to derive from BisCore.Element.`); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElement); + }); }); it("Creating ElementUniqueAspect, try subclassing unsupported base class, throws", async () => { const uniqueAspectKey = new SchemaItemKey("PhysicalModel", bisSchemaKey); - await expect(testEditor.entities.createElementUniqueAspect(testSchemaKey, "testElement", ECClassModifier.None, uniqueAspectKey, "test element")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); - expect(error).to.have.nested.property("innerError.message", `Expected base class ${uniqueAspectKey.fullName} to derive from BisCore.ElementUniqueAspect.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElementUniqueAspect); - }); + await expect(testEditor.entities.createElementUniqueAspect(testSchemaKey, "testElement", ECClassModifier.None, uniqueAspectKey, "test element")) + .to.be.eventually.rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); + expect(error).to.have.nested.property( + "innerError.message", + `Expected base class ${uniqueAspectKey.fullName} to derive from BisCore.ElementUniqueAspect.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElementUniqueAspect); + }); }); it("Creating ElementMultiAspect, try subclassing unsupported base class, throws", async () => { const multiAspectKey = new SchemaItemKey("PhysicalModel", bisSchemaKey); - await expect(testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement", ECClassModifier.None, multiAspectKey, "test element")).to.be.eventually.rejected.then(function (error) { - expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); - expect(error).to.have.nested.property("innerError.message", `Expected base class ${multiAspectKey.fullName} to derive from BisCore.ElementMultiAspect.`); - expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElementMultiAspect); - }); + await expect(testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement", ECClassModifier.None, multiAspectKey, "test element")) + .to.be.eventually.rejected.then(function(error) { + expect(error).to.have.property("errorNumber", ECEditingStatus.CreateElement); + expect(error).to.have.nested.property( + "innerError.message", + `Expected base class ${multiAspectKey.fullName} to derive from BisCore.ElementMultiAspect.`, + ); + expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.BaseClassIsNotElementMultiAspect); + }); }); it("should delete class successfully", async () => { const multiAspectKey = new SchemaItemKey("ElementMultiAspect", bisSchemaKey); - const result = await testEditor.entities.createElementMultiAspect(testSchemaKey, "testElement", ECClassModifier.None, multiAspectKey, "test element"); + const result = await testEditor.entities.createElementMultiAspect( + testSchemaKey, + "testElement", + ECClassModifier.None, + multiAspectKey, + "test element", + ); expect(result).to.not.be.undefined; expect(result).to.deep.equal(new SchemaItemKey("testElement", testSchemaKey)); let element = await testSchema!.getItem("testElement"); @@ -225,7 +286,10 @@ describe("SchemaEditor tests", () => { }); it("try to create a property of unsupported type, throws", async () => { - await expect(testEditor.entities.createProperty(entityKey as SchemaItemKey, "TestProperty", PrimitiveType.Boolean, "p")).to.be.rejectedWith(Error, "Property creation is restricted to type Double, String, DateTime, and Integer."); + await expect(testEditor.entities.createProperty(entityKey as SchemaItemKey, "TestProperty", PrimitiveType.Boolean, "p")).to.be.rejectedWith( + Error, + "Property creation is restricted to type Double, String, DateTime, and Integer.", + ); }); it("should successfully delete PrimitiveProperty.", async () => { diff --git a/core/ecschema-editing/src/test/Merging/ClassMergerOrder.test.ts b/core/ecschema-editing/src/test/Merging/ClassMergerOrder.test.ts index f18446bfa86f..9edec68bcadd 100644 --- a/core/ecschema-editing/src/test/Merging/ClassMergerOrder.test.ts +++ b/core/ecschema-editing/src/test/Merging/ClassMergerOrder.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { EntityClass, Mixin, Schema, SchemaContext, SchemaItemType, StructClass } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; describe("Class items merging order tests", () => { let context: SchemaContext; @@ -111,8 +111,8 @@ describe("Class items merging order tests", () => { const mergedItem = await mergedSchema.getItem("testClass"); const classMixins = mergedItem?.mixins; if (classMixins) { - expect((classMixins[0]).fullName).to.deep.equal("TargetSchema.mixinA"); - expect((classMixins[1]).fullName).to.deep.equal("TargetSchema.mixinB"); + expect(classMixins[0].fullName).to.deep.equal("TargetSchema.mixinA"); + expect(classMixins[1].fullName).to.deep.equal("TargetSchema.mixinB"); } expect(classMixins?.length).be.equal(2); }); @@ -284,7 +284,6 @@ describe("Class items merging order tests", () => { typeName: "int", }, ], - }, bracketSlot: { schemaItemType: "StructClass", diff --git a/core/ecschema-editing/src/test/Merging/ConstantMerger.test.ts b/core/ecschema-editing/src/test/Merging/ConstantMerger.test.ts index 91920cafa2e8..a94789804fe2 100644 --- a/core/ecschema-editing/src/test/Merging/ConstantMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/ConstantMerger.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Constant, Schema, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; describe("Constant merger tests", () => { const targetJson = { @@ -171,7 +171,6 @@ describe("Constant merger tests", () => { ], }); await expect(merge).to.be.rejectedWith("The Constant testConstant has an invalid 'definition' attribute."); - }); it("it should throw error if numerator conflict exist", async () => { diff --git a/core/ecschema-editing/src/test/Merging/CustomAttributeClassMerger.test.ts b/core/ecschema-editing/src/test/Merging/CustomAttributeClassMerger.test.ts index 8da96b459349..031a9f8bb78e 100644 --- a/core/ecschema-editing/src/test/Merging/CustomAttributeClassMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/CustomAttributeClassMerger.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { CustomAttributeClass, CustomAttributeContainerType, Schema, SchemaContext, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; import { expect } from "chai"; import { ECEditingStatus } from "../../Editing/Exception"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -224,7 +224,7 @@ describe("CustomAttributeClass merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Base class TargetSchema.TestBase must derive from TargetSchema.TargetBase.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); diff --git a/core/ecschema-editing/src/test/Merging/CustomAttributeMerger.test.ts b/core/ecschema-editing/src/test/Merging/CustomAttributeMerger.test.ts index 6e775332d2c4..da9c73f82005 100644 --- a/core/ecschema-editing/src/test/Merging/CustomAttributeMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/CustomAttributeMerger.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { CustomAttributeClass, EntityClass, RelationshipClass, Schema, SchemaContext, SchemaItemType, StructClass } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/Edits/RenameEdit.test.ts b/core/ecschema-editing/src/test/Merging/Edits/RenameEdit.test.ts index c9713029a156..6e0d925adba3 100644 --- a/core/ecschema-editing/src/test/Merging/Edits/RenameEdit.test.ts +++ b/core/ecschema-editing/src/test/Merging/Edits/RenameEdit.test.ts @@ -2,10 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CustomAttributeClass, EntityClass, Enumeration, EnumerationArrayProperty, EnumerationProperty, KindOfQuantity, Mixin, NavigationProperty, PropertyCategory, RelationshipClass, Schema, SchemaContext, StructArrayProperty, StructClass, StructProperty } from "@itwin/ecschema-metadata"; +import { + CustomAttributeClass, + EntityClass, + Enumeration, + EnumerationArrayProperty, + EnumerationProperty, + KindOfQuantity, + Mixin, + NavigationProperty, + PropertyCategory, + RelationshipClass, + Schema, + SchemaContext, + StructArrayProperty, + StructClass, + StructProperty, +} from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { ConflictCode, getSchemaDifferences, SchemaEdits, SchemaMerger } from "../../../ecschema-editing"; import { BisTestHelper } from "../../TestUtils/BisTestHelper"; -import { expect } from "chai"; import "chai-as-promised"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/Edits/SchemaEdit.test.ts b/core/ecschema-editing/src/test/Merging/Edits/SchemaEdit.test.ts index b5e8733a3909..7828f43bda1b 100644 --- a/core/ecschema-editing/src/test/Merging/Edits/SchemaEdit.test.ts +++ b/core/ecschema-editing/src/test/Merging/Edits/SchemaEdit.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { EntityClass, PrimitiveProperty, PrimitiveType, Schema, SchemaContext, StructClass } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { ConflictCode, getSchemaDifferences, SchemaEdits, SchemaMerger } from "../../../ecschema-editing"; import { BisTestHelper } from "../../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/EntityClassMerger.test.ts b/core/ecschema-editing/src/test/Merging/EntityClassMerger.test.ts index 2281062fdfc3..c51fed5b92ed 100644 --- a/core/ecschema-editing/src/test/Merging/EntityClassMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/EntityClassMerger.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { ECClassModifier, EntityClass, Schema, SchemaContext, SchemaItemKey, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; import { ECEditingStatus } from "../../Editing/Exception"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -367,8 +367,7 @@ describe("EntityClass merger tests", () => { changeType: "add", schemaType: SchemaItemType.EntityClass, itemName: "BaseEntity", - difference: { - }, + difference: {}, }, { changeType: "modify", @@ -407,8 +406,7 @@ describe("EntityClass merger tests", () => { changeType: "add", schemaType: SchemaItemType.EntityClass, itemName: "SourceBase", - difference: { - }, + difference: {}, }, { changeType: "add", @@ -429,7 +427,7 @@ describe("EntityClass merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Base class TargetSchema.TestBase must derive from TargetSchema.TargetBase.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); @@ -462,7 +460,7 @@ describe("EntityClass merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddMixin); expect(error).to.have.nested.property("innerError.message", `Mixin TargetSchema.NotExistingMixin could not be found in the schema context.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.SchemaItemNotFoundInContext); @@ -512,7 +510,7 @@ describe("EntityClass merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); expect(error).to.have.nested.property("innerError.message", `Base class TargetSchema.TestBase must derive from TargetSchema.BaseMixin.`); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); diff --git a/core/ecschema-editing/src/test/Merging/EnumerationMerger.test.ts b/core/ecschema-editing/src/test/Merging/EnumerationMerger.test.ts index 6ee2a2925905..fbf055761c4f 100644 --- a/core/ecschema-editing/src/test/Merging/EnumerationMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/EnumerationMerger.test.ts @@ -3,15 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Enumeration, Schema, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ describe("Enumeration merge tests", () => { - const targetJson = { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", name: "TargetSchema", @@ -150,8 +149,7 @@ describe("Enumeration merge tests", () => { name: "FirstValue", label: "first value", value: 0, - }, - { + }, { name: "SecondValue", label: "second value", value: 1, @@ -290,7 +288,7 @@ describe("Enumeration merge tests", () => { ], }); - await expect(merge).to.be.rejectedWith(Error, "The Enumeration TestEnumeration has an incompatible type. It must be \"string\", not \"int\"."); + await expect(merge).to.be.rejectedWith(Error, 'The Enumeration TestEnumeration has an incompatible type. It must be "string", not "int".'); }); it("should throw an error if enumerator value attribute conflict exist", async () => { @@ -329,6 +327,6 @@ describe("Enumeration merge tests", () => { ], }); - await expect(merge).to.be.rejectedWith("Failed to merge enumerator attribute, Enumerator \"EnumeratorOne\" has different values."); + await expect(merge).to.be.rejectedWith('Failed to merge enumerator attribute, Enumerator "EnumeratorOne" has different values.'); }); }); diff --git a/core/ecschema-editing/src/test/Merging/KindOfQuantityMerger.test.ts b/core/ecschema-editing/src/test/Merging/KindOfQuantityMerger.test.ts index 3612662ba669..7127442740ff 100644 --- a/core/ecschema-editing/src/test/Merging/KindOfQuantityMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/KindOfQuantityMerger.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { KindOfQuantity, Schema, SchemaContext, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/MixinMerger.test.ts b/core/ecschema-editing/src/test/Merging/MixinMerger.test.ts index b34a7cd53f0e..36bd78852b24 100644 --- a/core/ecschema-editing/src/test/Merging/MixinMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/MixinMerger.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Mixin, Schema, SchemaContext, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; import { expect } from "chai"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -144,8 +144,7 @@ describe("Mixin merger tests", () => { changeType: "add", schemaType: SchemaItemType.EntityClass, itemName: "SourceEntity", - difference: { - }, + difference: {}, }, { changeType: "modify", diff --git a/core/ecschema-editing/src/test/Merging/PhenomenonMerger.test.ts b/core/ecschema-editing/src/test/Merging/PhenomenonMerger.test.ts index 4c691e40fff7..80a878e90306 100644 --- a/core/ecschema-editing/src/test/Merging/PhenomenonMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/PhenomenonMerger.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Phenomenon, Schema, SchemaItemType } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; describe("Phenomenon merger tests", () => { const targetJson = { diff --git a/core/ecschema-editing/src/test/Merging/PropertyCategoryMerger.test.ts b/core/ecschema-editing/src/test/Merging/PropertyCategoryMerger.test.ts index edbbce11c955..eb27fc050f71 100644 --- a/core/ecschema-editing/src/test/Merging/PropertyCategoryMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/PropertyCategoryMerger.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { PropertyCategory, Schema, SchemaItemType } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/PropertyMerger.test.ts b/core/ecschema-editing/src/test/Merging/PropertyMerger.test.ts index e615925c408d..e3105ab55a11 100644 --- a/core/ecschema-editing/src/test/Merging/PropertyMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/PropertyMerger.test.ts @@ -2,11 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CustomAttributeClass, ECClass, EntityClass, Mixin, Property, Schema, SchemaContext, SchemaItemType, StructClass } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { + CustomAttributeClass, + ECClass, + EntityClass, + Mixin, + Property, + Schema, + SchemaContext, + SchemaItemType, + StructClass, +} from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/RelationshipClassMerger.test.ts b/core/ecschema-editing/src/test/Merging/RelationshipClassMerger.test.ts index 43e0237293fd..058ed64d71a5 100644 --- a/core/ecschema-editing/src/test/Merging/RelationshipClassMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/RelationshipClassMerger.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { RelationshipClass, Schema, SchemaContext, SchemaItemType } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; -import { ECEditingStatus } from "../../Editing/Exception"; import { AnyDiagnostic } from "../../ecschema-editing"; +import { ECEditingStatus } from "../../Editing/Exception"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -651,17 +651,21 @@ describe("Relationship Class merger tests", () => { schemaType: SchemaOtherTypes.RelationshipConstraint, itemName: "BaseRelationship", path: "$source", - difference: { - }, + difference: {}, }, ], }); // await expect(merge).to.be.rejectedWith(Error, "ECObjects-1601: The Source-Constraint of 'TargetSchema.BaseRelationship' has multiple constraint classes which requires an abstract constraint to be defined."); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(error).to.have.nested.property("innerError.message", `Rule violations occurred from Source constraint of RelationshipClass TargetSchema.BaseRelationship: ${getRuleViolationMessage(error.innerError.ruleViolations)}`); + expect(error).to.have.nested.property( + "innerError.message", + `Rule violations occurred from Source constraint of RelationshipClass TargetSchema.BaseRelationship: ${ + getRuleViolationMessage(error.innerError.ruleViolations) + }`, + ); }); }); @@ -711,10 +715,13 @@ describe("Relationship Class merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(error).to.have.nested.property("innerError.message", `Rule violations occurred from RelationshipClass TargetSchema.BaseRelationship: ${getRuleViolationMessage(error.innerError.ruleViolations)}`); + expect(error).to.have.nested.property( + "innerError.message", + `Rule violations occurred from RelationshipClass TargetSchema.BaseRelationship: ${getRuleViolationMessage(error.innerError.ruleViolations)}`, + ); }); }); @@ -763,10 +770,13 @@ describe("Relationship Class merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.AddConstraintClass); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.RuleViolation); - expect(error).to.have.nested.property("innerError.message", `Rule violations occurred from RelationshipClass TargetSchema.ChildRelationship: ${getRuleViolationMessage(error.innerError.ruleViolations)}`); + expect(error).to.have.nested.property( + "innerError.message", + `Rule violations occurred from RelationshipClass TargetSchema.ChildRelationship: ${getRuleViolationMessage(error.innerError.ruleViolations)}`, + ); }); }); @@ -1011,9 +1021,12 @@ describe("Relationship Class merger tests", () => { ], }); - await expect(merge).to.be.eventually.rejected.then(function (error) { + await expect(merge).to.be.eventually.rejected.then(function(error) { expect(error).to.have.property("errorNumber", ECEditingStatus.SetBaseClass); - expect(error).to.have.nested.property("innerError.message", `Base class TargetSchema.TestRelationship must derive from TestSchema.BaseRelationship.`); + expect(error).to.have.nested.property( + "innerError.message", + `Base class TargetSchema.TestRelationship must derive from TestSchema.BaseRelationship.`, + ); expect(error).to.have.nested.property("innerError.errorNumber", ECEditingStatus.InvalidBaseClass); }); }); diff --git a/core/ecschema-editing/src/test/Merging/SchemaMerger.test.ts b/core/ecschema-editing/src/test/Merging/SchemaMerger.test.ts index f4bc741cf544..4bed2b3c5a62 100644 --- a/core/ecschema-editing/src/test/Merging/SchemaMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/SchemaMerger.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext, SchemaItemType } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaConflictsError } from "../../Differencing/Errors"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; -import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; import { ConflictCode, SchemaDifferenceConflict } from "../../Differencing/SchemaConflicts"; +import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; import "chai-as-promised"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-editing/src/test/Merging/SchemaReferenceMerger.test.ts b/core/ecschema-editing/src/test/Merging/SchemaReferenceMerger.test.ts index b6aac5d56317..adbecb6cb085 100644 --- a/core/ecschema-editing/src/test/Merging/SchemaReferenceMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/SchemaReferenceMerger.test.ts @@ -3,13 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; +import { expect } from "chai"; import { SchemaOtherTypes } from "../../Differencing/SchemaDifference"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; describe("Schema reference merging tests", () => { - const targetJson = { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", name: "TargetSchema", diff --git a/core/ecschema-editing/src/test/Merging/StructClassMerger.test.ts b/core/ecschema-editing/src/test/Merging/StructClassMerger.test.ts index c92b27a38328..473eec3006fb 100644 --- a/core/ecschema-editing/src/test/Merging/StructClassMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/StructClassMerger.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext, SchemaItemType, StructClass } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; -import { expect } from "chai"; /* eslint-disable @typescript-eslint/naming-convention */ @@ -155,8 +155,7 @@ describe("StructClass merger tests", () => { changeType: "add", schemaType: SchemaItemType.StructClass, itemName: "BaseStruct", - difference: { - }, + difference: {}, }, { changeType: "modify", diff --git a/core/ecschema-editing/src/test/Merging/UnitSystemMerger.test.ts b/core/ecschema-editing/src/test/Merging/UnitSystemMerger.test.ts index 7d2af89f28a4..ea0b609339c3 100644 --- a/core/ecschema-editing/src/test/Merging/UnitSystemMerger.test.ts +++ b/core/ecschema-editing/src/test/Merging/UnitSystemMerger.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaItemType, UnitSystem } from "@itwin/ecschema-metadata"; -import { SchemaMerger } from "../../Merging/SchemaMerger"; import { expect } from "chai"; +import { SchemaMerger } from "../../Merging/SchemaMerger"; import { BisTestHelper } from "../TestUtils/BisTestHelper"; describe("Unit system merger tests", () => { diff --git a/core/ecschema-editing/src/test/TestUtils/BisTestHelper.ts b/core/ecschema-editing/src/test/TestUtils/BisTestHelper.ts index acd744926fc5..4aa36a40b543 100644 --- a/core/ecschema-editing/src/test/TestUtils/BisTestHelper.ts +++ b/core/ecschema-editing/src/test/TestUtils/BisTestHelper.ts @@ -33,7 +33,8 @@ const coreCustomAttributesSchema = { DynamicSchema: { schemaItemType: "CustomAttributeClass", label: "Dynamic Schema", - description: "Identifies a schema as dynamically generated by an application. Like versions of a schema may differ and are not guaranteed to merge without conflicts.", + description: + "Identifies a schema as dynamically generated by an application. Like versions of a schema may differ and are not guaranteed to merge without conflicts.", modifier: "Sealed", appliesTo: "Schema", }, @@ -63,13 +64,15 @@ const bisCoreSchema = { }, IParentElement: { appliesTo: "BisCore.Element", - description: "An interface that indicates that this Element is capable of being a parent (owning child Elements). This interface is mutually exclusive with ISubModeledElement.", + description: + "An interface that indicates that this Element is capable of being a parent (owning child Elements). This interface is mutually exclusive with ISubModeledElement.", label: "Parent Element", schemaItemType: "Mixin", }, ISubModeledElement: { appliesTo: "BisCore.Element", - description: "An interface which indicates that an Element can be broken down or described by a (sub) Model. This interface is mutually exclusive with IParentElement.", + description: + "An interface which indicates that an Element can be broken down or described by a (sub) Model. This interface is mutually exclusive with IParentElement.", label: "Modellable Element", schemaItemType: "Mixin", }, @@ -188,7 +191,8 @@ const bisCoreSchema = { }, ClassHasHandler: { appliesTo: "Any", - description: "Applied to an ECClass to indicate that a C++ subclass of DgnDomain::Handler will supply behavior for it at run-time. This custom attribute may only be used by BisCore or other core schemas.", + description: + "Applied to an ECClass to indicate that a C++ subclass of DgnDomain::Handler will supply behavior for it at run-time. This custom attribute may only be used by BisCore or other core schemas.", modifier: "sealed", schemaItemType: "CustomAttributeClass", }, diff --git a/core/ecschema-editing/src/test/TestUtils/DeserializationHelpers.ts b/core/ecschema-editing/src/test/TestUtils/DeserializationHelpers.ts index 6f913398a356..ffd7965b1735 100644 --- a/core/ecschema-editing/src/test/TestUtils/DeserializationHelpers.ts +++ b/core/ecschema-editing/src/test/TestUtils/DeserializationHelpers.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { DOMParser } from "@xmldom/xmldom"; import { ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, SchemaReadHelper, XmlParser } from "@itwin/ecschema-metadata"; +import { DOMParser } from "@xmldom/xmldom"; export function createSchemaJsonWithItems(itemsJson: any, referenceJson?: any): any { return { @@ -22,7 +22,10 @@ export class ReferenceSchemaLocater implements ISchemaLocater { private readonly _parser: (schemaContent: any, context: SchemaContext) => Schema; private readonly _asyncParser: (SchemaContent: any, context: SchemaContext) => Promise; - constructor(parser: (schemaContent: any, context: SchemaContext) => Schema, asyncParser: (SchemaContent: any, context: SchemaContext) => Promise) { + constructor( + parser: (schemaContent: any, context: SchemaContext) => Schema, + asyncParser: (SchemaContent: any, context: SchemaContext) => Promise, + ) { this._schemaList = new Map(); this._parser = parser; this._asyncParser = asyncParser; @@ -50,7 +53,6 @@ export class ReferenceSchemaLocater implements ISchemaLocater { } public getSchemaSync(schemaKey: SchemaKey, _matchType: SchemaMatchType, context: SchemaContext): T | undefined { - if (this._schemaList.has(schemaKey.name)) { const schemaBody = this._schemaList.get(schemaKey.name); const schema = this._parser(schemaBody, context); diff --git a/core/ecschema-editing/src/test/TestUtils/DiagnosticHelpers.ts b/core/ecschema-editing/src/test/TestUtils/DiagnosticHelpers.ts index fe6a3647f9a1..1aedc03213ee 100644 --- a/core/ecschema-editing/src/test/TestUtils/DiagnosticHelpers.ts +++ b/core/ecschema-editing/src/test/TestUtils/DiagnosticHelpers.ts @@ -3,11 +3,30 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import { AnyClass, AnyProperty, Constant, CustomAttribute, CustomAttributeClass, CustomAttributeContainerProps, EntityClass, - Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, PropertyCategory, - RelationshipClass, RelationshipConstraint, Schema, SchemaItem, StructClass, Unit, UnitSystem, +import { + AnyClass, + AnyProperty, + Constant, + CustomAttribute, + CustomAttributeClass, + CustomAttributeContainerProps, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + Schema, + SchemaItem, + StructClass, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; +import * as sinon from "sinon"; import * as Diagnostics from "../../Validation/Diagnostic"; import { IDiagnosticReporter } from "../../Validation/DiagnosticReporter"; import { IRuleSet } from "../../Validation/Rules"; @@ -51,46 +70,86 @@ export const TestDiagnosticCodes = { // eslint-disable-next-line @typescript-eslint/naming-convention export const TestDiagnostics = { - FailingSchemaDiagnostic: Diagnostics.createSchemaDiagnosticClass<[string, string]>(TestDiagnosticCodes.FailingSchemaDiagnostic, - "Failed with param {0} {1}"), - FailingSchemaItemDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingSchemaItemDiagnostic, - "Failed with param {0} {1}"), - FailingClassDiagnostic: Diagnostics.createClassDiagnosticClass<[string, string]>(TestDiagnosticCodes.FailingClassDiagnostic, - "Failed with params {0} {1}"), - FailingPropertyDiagnostic: Diagnostics.createPropertyDiagnosticClass<[string, string]>(TestDiagnosticCodes.FailingPropertyDiagnostic, - "Failed with param {0} {1}"), - FailingEntityClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingEntityClassDiagnostic, - "Failed with params {0} {1}"), - FailingStructClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingStructClassDiagnostic, - "Failed with params {0} {1}"), - FailingMixinDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingMixinDiagnostic, - "Failed with params {0} {1}"), - FailingRelationshipDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingRelationshipDiagnostic, - "Failed with param {0} {1}"), - FailingRelationshipConstraintDiagnostic: Diagnostics.createRelationshipConstraintDiagnosticClass<[string, string]>(TestDiagnosticCodes.FailingRelationshipConstraintDiagnostic, - "Failed with param {0} {1}"), - FailingCustomAttributeClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingCustomAttributeClassDiagnostic, - "Failed with param {0} {1}"), - FailingCustomAttributeContainerDiagnostic: Diagnostics.createCustomAttributeContainerDiagnosticClass<[string, string]>(TestDiagnosticCodes.FailingCustomAttributeContainerDiagnostic, - "Failed with param {0} {1}"), - FailingEnumerationDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingEnumerationDiagnostic, - "Failed with param {0} {1}"), - FailingKindOfQuantityDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingKindOfQuantityDiagnostic, - "Failed with param {0} {1}"), - FailingPropertyCategoryDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingPropertyCategoryDiagnostic, - "Failed with param {0} {1}"), - FailingFormatDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingFormatDiagnostic, - "Failed with param {0} {1}"), - FailingUnitDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingUnitDiagnostic, - "Failed with param {0} {1}"), - FailingInvertedUnitFormatDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingInvertedUnitFormatDiagnostic, - "Failed with param {0} {1}"), - FailingUnitSystemDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingUnitSystemDiagnostic, - "Failed with param {0} {1}"), - FailingPhenomenonDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingPhenomenonDiagnostic, - "Failed with param {0} {1}"), - FailingConstantDiagnostic: Diagnostics.createSchemaItemDiagnosticClass(TestDiagnosticCodes.FailingConstantDiagnostic, - "Failed with param {0} {1}"), + FailingSchemaDiagnostic: Diagnostics.createSchemaDiagnosticClass<[string, string]>( + TestDiagnosticCodes.FailingSchemaDiagnostic, + "Failed with param {0} {1}", + ), + FailingSchemaItemDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingSchemaItemDiagnostic, + "Failed with param {0} {1}", + ), + FailingClassDiagnostic: Diagnostics.createClassDiagnosticClass<[string, string]>( + TestDiagnosticCodes.FailingClassDiagnostic, + "Failed with params {0} {1}", + ), + FailingPropertyDiagnostic: Diagnostics.createPropertyDiagnosticClass<[string, string]>( + TestDiagnosticCodes.FailingPropertyDiagnostic, + "Failed with param {0} {1}", + ), + FailingEntityClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingEntityClassDiagnostic, + "Failed with params {0} {1}", + ), + FailingStructClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingStructClassDiagnostic, + "Failed with params {0} {1}", + ), + FailingMixinDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingMixinDiagnostic, + "Failed with params {0} {1}", + ), + FailingRelationshipDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingRelationshipDiagnostic, + "Failed with param {0} {1}", + ), + FailingRelationshipConstraintDiagnostic: Diagnostics.createRelationshipConstraintDiagnosticClass<[string, string]>( + TestDiagnosticCodes.FailingRelationshipConstraintDiagnostic, + "Failed with param {0} {1}", + ), + FailingCustomAttributeClassDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingCustomAttributeClassDiagnostic, + "Failed with param {0} {1}", + ), + FailingCustomAttributeContainerDiagnostic: Diagnostics.createCustomAttributeContainerDiagnosticClass<[string, string]>( + TestDiagnosticCodes.FailingCustomAttributeContainerDiagnostic, + "Failed with param {0} {1}", + ), + FailingEnumerationDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingEnumerationDiagnostic, + "Failed with param {0} {1}", + ), + FailingKindOfQuantityDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingKindOfQuantityDiagnostic, + "Failed with param {0} {1}", + ), + FailingPropertyCategoryDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingPropertyCategoryDiagnostic, + "Failed with param {0} {1}", + ), + FailingFormatDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingFormatDiagnostic, + "Failed with param {0} {1}", + ), + FailingUnitDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingUnitDiagnostic, + "Failed with param {0} {1}", + ), + FailingInvertedUnitFormatDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingInvertedUnitFormatDiagnostic, + "Failed with param {0} {1}", + ), + FailingUnitSystemDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingUnitSystemDiagnostic, + "Failed with param {0} {1}", + ), + FailingPhenomenonDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingPhenomenonDiagnostic, + "Failed with param {0} {1}", + ), + FailingConstantDiagnostic: Diagnostics.createSchemaItemDiagnosticClass( + TestDiagnosticCodes.FailingConstantDiagnostic, + "Failed with param {0} {1}", + ), }; export async function* failingSchemaRule(schema: Schema): AsyncIterable> { @@ -125,7 +184,9 @@ export async function* passingPropertyRule(_property: AnyProperty): AsyncIterabl return undefined; } -export async function* failingEntityClassRule(entityClass: EntityClass): AsyncIterable> { +export async function* failingEntityClassRule( + entityClass: EntityClass, +): AsyncIterable> { yield new TestDiagnostics.FailingEntityClassDiagnostic(entityClass, ["Param1", "Param2"]); } @@ -133,7 +194,9 @@ export async function* passingEntityClassRule(_entityClass: EntityClass): AsyncI return undefined; } -export async function* failingStructClassRule(structClass: StructClass): AsyncIterable> { +export async function* failingStructClassRule( + structClass: StructClass, +): AsyncIterable> { yield new TestDiagnostics.FailingStructClassDiagnostic(structClass, ["Param1", "Param2"]); } @@ -149,47 +212,71 @@ export async function* passingMixinRule(_mixin: Mixin): AsyncIterable> { +export async function* failingRelationshipRule( + relationship: RelationshipClass, +): AsyncIterable> { yield new TestDiagnostics.FailingRelationshipDiagnostic(relationship, ["Param1", "Param2"]); } -export async function* passingRelationshipRule(_relationship: RelationshipClass): AsyncIterable> { +export async function* passingRelationshipRule( + _relationship: RelationshipClass, +): AsyncIterable> { return undefined; } -export async function* failingRelationshipConstraintRule(constraint: RelationshipConstraint): AsyncIterable> { +export async function* failingRelationshipConstraintRule( + constraint: RelationshipConstraint, +): AsyncIterable> { yield new TestDiagnostics.FailingRelationshipConstraintDiagnostic(constraint, ["Param1", "Param2"]); } -export async function* passingRelationshipConstraintRule(_constraint: RelationshipConstraint): AsyncIterable> { +export async function* passingRelationshipConstraintRule( + _constraint: RelationshipConstraint, +): AsyncIterable> { return undefined; } -export async function* failingCustomAttributeClassRule(customAttributeClass: CustomAttributeClass): AsyncIterable> { +export async function* failingCustomAttributeClassRule( + customAttributeClass: CustomAttributeClass, +): AsyncIterable> { yield new TestDiagnostics.FailingCustomAttributeClassDiagnostic(customAttributeClass, ["Param1", "Param2"]); } -export async function* passingCustomAttributeClassRule(_customAttributeClass: CustomAttributeClass): AsyncIterable> { +export async function* passingCustomAttributeClassRule( + _customAttributeClass: CustomAttributeClass, +): AsyncIterable> { return undefined; } -export async function* failingCustomAttributeContainerRule(container: CustomAttributeContainerProps): AsyncIterable> { +export async function* failingCustomAttributeContainerRule( + container: CustomAttributeContainerProps, +): AsyncIterable> { yield new TestDiagnostics.FailingCustomAttributeContainerDiagnostic(container, ["Param1", "Param2"]); } -export async function* passingCustomAttributeContainerRule(_container: CustomAttributeContainerProps): AsyncIterable> { +export async function* passingCustomAttributeContainerRule( + _container: CustomAttributeContainerProps, +): AsyncIterable> { return undefined; } -export async function* failingCustomAttributeRule(container: CustomAttributeContainerProps, _customAttribute: CustomAttribute): AsyncIterable> { +export async function* failingCustomAttributeRule( + container: CustomAttributeContainerProps, + _customAttribute: CustomAttribute, +): AsyncIterable> { yield new TestDiagnostics.FailingCustomAttributeContainerDiagnostic(container, ["Param1", "Param2"]); } -export async function* passingCustomAttributeRule(_container: CustomAttributeContainerProps, _customAttribute: CustomAttribute): AsyncIterable> { +export async function* passingCustomAttributeRule( + _container: CustomAttributeContainerProps, + _customAttribute: CustomAttribute, +): AsyncIterable> { return undefined; } -export async function* failingEnumerationRule(enumeration: Enumeration): AsyncIterable> { +export async function* failingEnumerationRule( + enumeration: Enumeration, +): AsyncIterable> { yield new TestDiagnostics.FailingEnumerationDiagnostic(enumeration, ["Param1", "Param2"]); } @@ -197,19 +284,27 @@ export async function* passingEnumerationRule(_enumeration: Enumeration): AsyncI return undefined; } -export async function* failingKindOfQuantityRule(kindOfQuantity: KindOfQuantity): AsyncIterable> { +export async function* failingKindOfQuantityRule( + kindOfQuantity: KindOfQuantity, +): AsyncIterable> { yield new TestDiagnostics.FailingKindOfQuantityDiagnostic(kindOfQuantity, ["Param1", "Param2"]); } -export async function* passingKindOfQuantityRule(_kindOfQuantity: KindOfQuantity): AsyncIterable> { +export async function* passingKindOfQuantityRule( + _kindOfQuantity: KindOfQuantity, +): AsyncIterable> { return undefined; } -export async function* failingPropertyCategoryRule(propertyCategory: PropertyCategory): AsyncIterable> { +export async function* failingPropertyCategoryRule( + propertyCategory: PropertyCategory, +): AsyncIterable> { yield new TestDiagnostics.FailingPropertyCategoryDiagnostic(propertyCategory, ["Param1", "Param2"]); } -export async function* passingPropertyCategoryRule(_propertyCategory: PropertyCategory): AsyncIterable> { +export async function* passingPropertyCategoryRule( + _propertyCategory: PropertyCategory, +): AsyncIterable> { return undefined; } @@ -229,7 +324,9 @@ export async function* passingUnitRule(_unit: Unit): AsyncIterable> { +export async function* failingInvertedUnitRule( + invertedUnit: InvertedUnit, +): AsyncIterable> { yield new TestDiagnostics.FailingInvertedUnitFormatDiagnostic(invertedUnit, ["Param1", "Param2"]); } @@ -326,35 +423,61 @@ export async function applyRelationshipClassSuppression(_diagnostic: Diagnostics return true; } -export async function ignoreRelationshipConstraintSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _constraint: RelationshipConstraint): Promise { +export async function ignoreRelationshipConstraintSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _constraint: RelationshipConstraint, +): Promise { return false; } -export async function applyRelationshipConstraintSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _constraint: RelationshipConstraint): Promise { +export async function applyRelationshipConstraintSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _constraint: RelationshipConstraint, +): Promise { return true; } -export async function ignoreCustomAttributeClassSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _customAttributeClass: CustomAttributeClass): Promise { +export async function ignoreCustomAttributeClassSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _customAttributeClass: CustomAttributeClass, +): Promise { return false; } -export async function applyCustomAttributeClassSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _customAttributeClass: CustomAttributeClass): Promise { +export async function applyCustomAttributeClassSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _customAttributeClass: CustomAttributeClass, +): Promise { return true; } -export async function ignoreCustomAttributeContainerSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _container: CustomAttributeContainerProps): Promise { +export async function ignoreCustomAttributeContainerSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _container: CustomAttributeContainerProps, +): Promise { return false; } -export async function applyCustomAttributeContainerSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _container: CustomAttributeContainerProps): Promise { +export async function applyCustomAttributeContainerSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _container: CustomAttributeContainerProps, +): Promise { return true; } -export async function ignoreCustomAttributeInstanceSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _container: CustomAttributeContainerProps, _customAttribute: CustomAttribute): Promise { +export async function ignoreCustomAttributeInstanceSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _container: CustomAttributeContainerProps, + _customAttribute: CustomAttribute, +): Promise { return false; } -export async function applyCustomAttributeInstanceSuppression(_diagnostic: Diagnostics.AnyDiagnostic, _container: CustomAttributeContainerProps, _customAttribute: CustomAttribute): Promise { +export async function applyCustomAttributeInstanceSuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _container: CustomAttributeContainerProps, + _customAttribute: CustomAttribute, +): Promise { return true; } @@ -374,11 +497,17 @@ export async function applyKindOfQuantitySuppression(_diagnostic: Diagnostics.An return true; } -export async function ignorePropertyCategorySuppression(_diagnostic: Diagnostics.AnyDiagnostic, _propertyCategory: PropertyCategory): Promise { +export async function ignorePropertyCategorySuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _propertyCategory: PropertyCategory, +): Promise { return false; } -export async function applyPropertyCategorySuppression(_diagnostic: Diagnostics.AnyDiagnostic, _propertyCategory: PropertyCategory): Promise { +export async function applyPropertyCategorySuppression( + _diagnostic: Diagnostics.AnyDiagnostic, + _propertyCategory: PropertyCategory, +): Promise { return true; } diff --git a/core/ecschema-editing/src/test/Validation/DiagnosticReporters.test.ts b/core/ecschema-editing/src/test/Validation/DiagnosticReporters.test.ts index 2b85f2e14ddb..8c78ea8bca0e 100644 --- a/core/ecschema-editing/src/test/Validation/DiagnosticReporters.test.ts +++ b/core/ecschema-editing/src/test/Validation/DiagnosticReporters.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { BentleyError, Logger } from "@itwin/core-bentley"; import { EmptyLocalization } from "@itwin/core-common"; import { EntityClass, PrimitiveProperty, PrimitiveType, Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { assert, expect } from "chai"; import { FormatDiagnosticReporter } from "../../ecschema-editing"; import { MutableClass } from "../../Editing/Mutable/MutableClass"; import { AnyDiagnostic, createPropertyDiagnosticClass, DiagnosticCategory } from "../../Validation/Diagnostic"; @@ -23,7 +23,6 @@ class TestDiagnosticReporter extends FormatDiagnosticReporter { } describe("DiagnosticReporters tests", () => { - let testSchema: Schema; let testSchemaItem: EntityClass; let testProperty: PrimitiveProperty; @@ -93,7 +92,6 @@ describe("DiagnosticReporters tests", () => { expect(reportDiagnostic.notCalled).to.be.true; }); - }); describe("LoggingDiagnosticReporter tests", () => { @@ -202,4 +200,3 @@ describe("DiagnosticReporters tests", () => { }); }); }); - diff --git a/core/ecschema-editing/src/test/Validation/Diagnostics.test.ts b/core/ecschema-editing/src/test/Validation/Diagnostics.test.ts index 7c3794d5e9d4..b522713ebf21 100644 --- a/core/ecschema-editing/src/test/Validation/Diagnostics.test.ts +++ b/core/ecschema-editing/src/test/Validation/Diagnostics.test.ts @@ -3,10 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { EntityClass, PrimitiveProperty, RelationshipClass, RelationshipConstraint, RelationshipEnd, - Schema, SchemaContext, +import { + EntityClass, + PrimitiveProperty, + RelationshipClass, + RelationshipConstraint, + RelationshipEnd, + Schema, + SchemaContext, } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import * as Diagnostics from "../../Validation/Diagnostic"; describe("Diagnostics tests", () => { diff --git a/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts index 8fdeacc5ad9b..38d0e932be61 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/ClassRules.test.ts @@ -3,12 +3,18 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { DelayedPromiseWithProps, ECClassModifier, EntityClass, - RelationshipClass, Schema, SchemaContext, schemaItemTypeToString, +import { + DelayedPromiseWithProps, + ECClassModifier, + EntityClass, + RelationshipClass, + Schema, + SchemaContext, + schemaItemTypeToString, } from "@itwin/ecschema-metadata"; -import * as Rules from "../../../Validation/ECRules"; +import { expect } from "chai"; import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; +import * as Rules from "../../../Validation/ECRules"; /* eslint-disable deprecation/deprecation */ diff --git a/core/ecschema-editing/src/test/Validation/ECRules/CustomAttributeRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/CustomAttributeRules.test.ts index d916ce9e7a50..d65a3581e215 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/CustomAttributeRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/CustomAttributeRules.test.ts @@ -3,15 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { CustomAttributeClass, ECClassModifier, EntityClass, Schema, SchemaContext } from "@itwin/ecschema-metadata"; import { expect } from "chai"; -import { CustomAttributeClass, ECClassModifier, EntityClass, - Schema, SchemaContext, -} from "@itwin/ecschema-metadata"; import { MutableClass } from "../../../Editing/Mutable/MutableClass"; import { MutableSchema } from "../../../Editing/Mutable/MutableSchema"; +import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; import * as Rules from "../../../Validation/ECRules"; import { toArray } from "../../TestUtils/DiagnosticHelpers"; -import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; /* eslint-disable deprecation/deprecation */ diff --git a/core/ecschema-editing/src/test/Validation/ECRules/EnumerationRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/EnumerationRules.test.ts index af929641c7ad..919e9b4127dd 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/EnumerationRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/EnumerationRules.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Enumeration, PrimitiveType, Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import * as Rules from "../../../Validation/ECRules"; +import { expect } from "chai"; import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; +import * as Rules from "../../../Validation/ECRules"; /* eslint-disable deprecation/deprecation */ diff --git a/core/ecschema-editing/src/test/Validation/ECRules/MixinRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/MixinRules.test.ts index 8754e0af44db..44bdcbf47de3 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/MixinRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/MixinRules.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { DelayedPromiseWithProps, EntityClass, Mixin, Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { MutableEntityClass } from "../../../Editing/Mutable/MutableEntityClass"; import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; import * as Rules from "../../../Validation/ECRules"; diff --git a/core/ecschema-editing/src/test/Validation/ECRules/PropertyRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/PropertyRules.test.ts index 0f7275111f00..d3582407aba1 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/PropertyRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/PropertyRules.test.ts @@ -3,9 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + AnyProperty, + DelayedPromiseWithProps, + ECClass, + EntityClass, + KindOfQuantity, + PrimitiveProperty, + PrimitiveType, + PropertyProps, + RelationshipClass, + Schema, + SchemaContext, + StructClass, +} from "@itwin/ecschema-metadata"; import { expect } from "chai"; -import { AnyProperty, DelayedPromiseWithProps, ECClass, EntityClass, KindOfQuantity, PrimitiveProperty, PrimitiveType, - PropertyProps, RelationshipClass, Schema, SchemaContext, StructClass } from "@itwin/ecschema-metadata"; import { MutableClass } from "../../../Editing/Mutable/MutableClass"; import { MutableSchema } from "../../../Editing/Mutable/MutableSchema"; import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; @@ -47,7 +59,9 @@ describe("PropertyRule tests", () => { expect(diagnostic.ecDefinition).eq(properties[0]); expect(diagnostic.messageArgs).deep.eq([testClass.fullName, "TestProperty", testBaseClass.fullName, "string", "int"]); expect(diagnostic.messageText) - .eq("The ECProperty 'TestSchema.TestClass.TestProperty' has a base property 'TestSchema.TestBaseClass.TestProperty' with a value type of string which is incompatible with the value type of int."); + .eq( + "The ECProperty 'TestSchema.TestClass.TestProperty' has a base property 'TestSchema.TestBaseClass.TestProperty' with a value type of string which is incompatible with the value type of int.", + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleValueTypePropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -70,7 +84,9 @@ describe("PropertyRule tests", () => { expect(diagnostic.ecDefinition).eq(properties[0]); expect(diagnostic.messageArgs).deep.eq([testClass.fullName, "TestProperty", rootBaseClass.fullName, "string", "int"]); expect(diagnostic.messageText) - .eq("The ECProperty 'TestSchema.TestClass.TestProperty' has a base property 'TestSchema.RootBaseClass.TestProperty' with a value type of string which is incompatible with the value type of int."); + .eq( + "The ECProperty 'TestSchema.TestClass.TestProperty' has a base property 'TestSchema.RootBaseClass.TestProperty' with a value type of string which is incompatible with the value type of int.", + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleValueTypePropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -141,9 +157,17 @@ describe("PropertyRule tests", () => { for await (const diagnostic of results) { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(properties[0]); - expect(diagnostic.messageArgs).deep.eq([testClass.fullName, "TestProperty", testBaseClass.fullName, "PrimitiveArrayProperty", "PrimitiveProperty"]); + expect(diagnostic.messageArgs).deep.eq([ + testClass.fullName, + "TestProperty", + testBaseClass.fullName, + "PrimitiveArrayProperty", + "PrimitiveProperty", + ]); expect(diagnostic.messageText) - .eq(`The ECProperty '${testClass.fullName}.TestProperty' has a base property '${testBaseClass.fullName}.TestProperty' with a type of PrimitiveArrayProperty which is incompatible with the type of PrimitiveProperty.`); + .eq( + `The ECProperty '${testClass.fullName}.TestProperty' has a base property '${testBaseClass.fullName}.TestProperty' with a type of PrimitiveArrayProperty which is incompatible with the type of PrimitiveProperty.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleTypePropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -164,9 +188,17 @@ describe("PropertyRule tests", () => { for await (const diagnostic of results) { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(properties[0]); - expect(diagnostic.messageArgs).deep.eq([testClass.fullName, "TestProperty", rootBaseClass.fullName, "PrimitiveArrayProperty", "PrimitiveProperty"]); + expect(diagnostic.messageArgs).deep.eq([ + testClass.fullName, + "TestProperty", + rootBaseClass.fullName, + "PrimitiveArrayProperty", + "PrimitiveProperty", + ]); expect(diagnostic.messageText) - .eq(`The ECProperty '${testClass.fullName}.TestProperty' has a base property '${rootBaseClass.fullName}.TestProperty' with a type of PrimitiveArrayProperty which is incompatible with the type of PrimitiveProperty.`); + .eq( + `The ECProperty '${testClass.fullName}.TestProperty' has a base property '${rootBaseClass.fullName}.TestProperty' with a type of PrimitiveArrayProperty which is incompatible with the type of PrimitiveProperty.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleTypePropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -241,11 +273,18 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(childProperties[0]); expect(diagnostic.messageArgs).deep.eq([ - testClass.fullName, "TestProperty", testBaseClass.fullName, - testBaseKindOfQuantity.fullName, baseUnit.fullName, childUnit.fullName, testKindOfQuantity.fullName, + testClass.fullName, + "TestProperty", + testBaseClass.fullName, + testBaseKindOfQuantity.fullName, + baseUnit.fullName, + childUnit.fullName, + testKindOfQuantity.fullName, ]); expect(diagnostic.messageText) - .eq(`The ECProperty '${testClass.fullName}.TestProperty' has a base property '${testBaseClass.fullName}.TestProperty' with KindOfQuantity '${testBaseKindOfQuantity.fullName}' with persistence unit '${baseUnit.fullName}' which is not the same as the persistence unit '${childUnit.fullName}' of the provided KindOfQuantity '${testKindOfQuantity.fullName}'.`); + .eq( + `The ECProperty '${testClass.fullName}.TestProperty' has a base property '${testBaseClass.fullName}.TestProperty' with KindOfQuantity '${testBaseKindOfQuantity.fullName}' with persistence unit '${baseUnit.fullName}' which is not the same as the persistence unit '${childUnit.fullName}' of the provided KindOfQuantity '${testKindOfQuantity.fullName}'.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleUnitPropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -299,10 +338,17 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(childProperty); expect(diagnostic.messageArgs).deep.eq([ - testClass.fullName, "TestProperty", rootBaseClass.fullName, - testBaseKindOfQuantity.fullName, baseUnit.fullName, childUnit.fullName, testKindOfQuantity.fullName, + testClass.fullName, + "TestProperty", + rootBaseClass.fullName, + testBaseKindOfQuantity.fullName, + baseUnit.fullName, + childUnit.fullName, + testKindOfQuantity.fullName, ]); - expect(diagnostic.messageText).eq(`The ECProperty '${testClass.fullName}.TestProperty' has a base property '${rootBaseClass.fullName}.TestProperty' with KindOfQuantity '${testBaseKindOfQuantity.fullName}' with persistence unit '${baseUnit.fullName}' which is not the same as the persistence unit '${childUnit.fullName}' of the provided KindOfQuantity '${testKindOfQuantity.fullName}'.`); + expect(diagnostic.messageText).eq( + `The ECProperty '${testClass.fullName}.TestProperty' has a base property '${rootBaseClass.fullName}.TestProperty' with KindOfQuantity '${testBaseKindOfQuantity.fullName}' with persistence unit '${baseUnit.fullName}' which is not the same as the persistence unit '${childUnit.fullName}' of the provided KindOfQuantity '${testKindOfQuantity.fullName}'.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.DiagnosticCodes.IncompatibleUnitPropertyOverride); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -459,7 +505,15 @@ describe("PropertyRule tests", () => { }); describe("Validate NavigationProperty Tests", () => { - function createSchemaJson(baseRelationship: any, sourceConst: any, targetConst: any, sourceProperties: any, targetProperties: any, inheritanceLevel: any, relationshipProperties?: any) { + function createSchemaJson( + baseRelationship: any, + sourceConst: any, + targetConst: any, + sourceProperties: any, + targetProperties: any, + inheritanceLevel: any, + relationshipProperties?: any, + ) { let sourcePropsInherited1: any; let targetPropsInherited1: any; let sourcePropsInherited2: any; @@ -593,7 +647,10 @@ describe("PropertyRule tests", () => { baseClass: "TestSchema.TestRelationship2", }; - const testSchema = await Schema.fromJson(createSchemaJson(baseRelationshipJson, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(baseRelationshipJson, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -603,7 +660,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestSourceEntity.TestProperty", "TestSchema.TestRelationship"]); - expect(diagnostic.messageText).eq(`The referenced relationship 'TestSchema.TestRelationship', used in NavigationProperty 'TestSourceEntity.TestProperty' is not the root relationship.`); + expect(diagnostic.messageText).eq( + `The referenced relationship 'TestSchema.TestRelationship', used in NavigationProperty 'TestSourceEntity.TestProperty' is not the root relationship.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationRelationshipMustBeRoot.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -641,7 +700,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -682,7 +744,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -692,7 +757,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestSourceEntity.TestProperty", "TestSchema.TestRelationship", "Forward"]); - expect(diagnostic.messageText).eq(`NavigationProperty 'TestSourceEntity.TestProperty' uses the relationship 'TestSchema.TestRelationship' that cannot be traversed in the 'Forward' direction due to a max multiplicity greater than 1.`); + expect(diagnostic.messageText).eq( + `NavigationProperty 'TestSourceEntity.TestProperty' uses the relationship 'TestSchema.TestRelationship' that cannot be traversed in the 'Forward' direction due to a max multiplicity greater than 1.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationTargetMustHaveSingularMultiplicity.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -730,7 +797,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -769,7 +839,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -779,7 +852,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestTargetEntity.TestProperty", "TestSchema.TestRelationship", "Backward"]); - expect(diagnostic.messageText).eq(`NavigationProperty 'TestTargetEntity.TestProperty' uses the relationship 'TestSchema.TestRelationship' that cannot be traversed in the 'Backward' direction due to a max multiplicity greater than 1.`); + expect(diagnostic.messageText).eq( + `NavigationProperty 'TestTargetEntity.TestProperty' uses the relationship 'TestSchema.TestRelationship' that cannot be traversed in the 'Backward' direction due to a max multiplicity greater than 1.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationTargetMustHaveSingularMultiplicity.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -817,7 +892,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -858,7 +936,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -868,7 +949,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestSourceEntity.TestProperty", "TestSchema.TestRelationship"]); - expect(diagnostic.messageText).eq(`The NavigationProperty 'TestSourceEntity.TestProperty', using the relationship 'TestSchema.TestRelationship', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin.`); + expect(diagnostic.messageText).eq( + `The NavigationProperty 'TestSourceEntity.TestProperty', using the relationship 'TestSchema.TestRelationship', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationRelationshipAbstractConstraintEntityOrMixin.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -906,7 +989,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, undefined, 0, propertyJson), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, undefined, 0, propertyJson), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestRelationship2"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -945,7 +1031,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -955,7 +1044,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestTargetEntity.TestProperty", "TestSchema.TestRelationship"]); - expect(diagnostic.messageText).eq(`The NavigationProperty 'TestTargetEntity.TestProperty', using the relationship 'TestSchema.TestRelationship', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin.`); + expect(diagnostic.messageText).eq( + `The NavigationProperty 'TestTargetEntity.TestProperty', using the relationship 'TestSchema.TestRelationship', points to a RelationshipClass, which is not allowed. NavigationProperties must point to an EntityClass or Mixin.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationRelationshipAbstractConstraintEntityOrMixin.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -993,7 +1084,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, undefined, 0, propertyJson), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, undefined, 0, propertyJson), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestRelationship2"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1034,7 +1128,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1044,7 +1141,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestSourceEntity", "TestProperty", "TestSchema.TestRelationship", "source"]); - expect(diagnostic.messageText).eq(`The class 'TestSourceEntity' of NavigationProperty 'TestProperty' is not supported by the source constraint of the referenced relationship 'TestSchema.TestRelationship'.`); + expect(diagnostic.messageText).eq( + `The class 'TestSourceEntity' of NavigationProperty 'TestProperty' is not supported by the source constraint of the referenced relationship 'TestSchema.TestRelationship'.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationClassMustBeAConstraintClassOfRelationship.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -1082,7 +1181,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1121,7 +1223,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1131,7 +1236,9 @@ describe("PropertyRule tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).eq(testProperty); expect(diagnostic.messageArgs).deep.eq(["TestTargetEntity", "TestProperty", "TestSchema.TestRelationship", "target"]); - expect(diagnostic.messageText).eq(`The class 'TestTargetEntity' of NavigationProperty 'TestProperty' is not supported by the target constraint of the referenced relationship 'TestSchema.TestRelationship'.`); + expect(diagnostic.messageText).eq( + `The class 'TestTargetEntity' of NavigationProperty 'TestProperty' is not supported by the target constraint of the referenced relationship 'TestSchema.TestRelationship'.`, + ); expect(diagnostic.category).eq(DiagnosticCategory.Error); expect(diagnostic.code).eq(Rules.Diagnostics.NavigationClassMustBeAConstraintClassOfRelationship.code); expect(diagnostic.diagnosticType).eq(DiagnosticType.Property); @@ -1169,7 +1276,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 0), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1208,7 +1318,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 1), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 1), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1247,7 +1360,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 2), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 2), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1286,7 +1402,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 3), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, propertyJson, undefined, 3), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestSourceEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1325,7 +1444,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 1), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 1), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1364,7 +1486,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 2), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 2), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); @@ -1403,7 +1528,10 @@ describe("PropertyRule tests", () => { ], }; - const testSchema = await Schema.fromJson(createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 3), new SchemaContext()); + const testSchema = await Schema.fromJson( + createSchemaJson(undefined, sourceJson, targetJson, undefined, propertyJson, 3), + new SchemaContext(), + ); const testProperty = (await testSchema.getItem("TestTargetEntity"))?.getPropertySync("TestProperty") as AnyProperty; const results = Rules.validateNavigationProperty(testProperty); diff --git a/core/ecschema-editing/src/test/Validation/ECRules/RelationshipConstraintRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/RelationshipConstraintRules.test.ts index fc0e72175fd4..59ad972fea64 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/RelationshipConstraintRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/RelationshipConstraintRules.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { RelationshipClass, Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; +import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; import * as Rules from "../../../Validation/ECRules"; import { createSchemaJsonWithItems } from "../../TestUtils/DeserializationHelpers"; -import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable deprecation/deprecation */ diff --git a/core/ecschema-editing/src/test/Validation/ECRules/RelationshipRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/RelationshipRules.test.ts index a84b49253e16..20305954709c 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/RelationshipRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/RelationshipRules.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { RelationshipClass, Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; +import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; import * as Rules from "../../../Validation/ECRules"; import { createSchemaJsonWithItems } from "../../TestUtils/DeserializationHelpers"; -import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; /* eslint-disable @typescript-eslint/naming-convention */ /* eslint-disable deprecation/deprecation */ @@ -80,9 +80,15 @@ describe("RelationshipRule tests", () => { TM1: { schemaItemType: "Mixin", appliesTo: "TestSchema.TDE1" }, SBR1: { ...createNavPropRelationship({ constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.SBE1"] }) }, - SDR1: { baseClass: "TestSchema.SBR1", ...createNavPropRelationship({ constraintClasses: ["TestSchema.SDE1"] }, { constraintClasses: ["TestSchema.SDE1"] }) }, + SDR1: { + baseClass: "TestSchema.SBR1", + ...createNavPropRelationship({ constraintClasses: ["TestSchema.SDE1"] }, { constraintClasses: ["TestSchema.SDE1"] }), + }, TBR1: { ...createNavPropRelationship({ constraintClasses: ["TestSchema.TBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }) }, - TDR1: { baseClass: "TestSchema.TBR1", ...createNavPropRelationship({ constraintClasses: ["TestSchema.TDE1"] }, { constraintClasses: ["TestSchema.TDE1"] }) }, + TDR1: { + baseClass: "TestSchema.TBR1", + ...createNavPropRelationship({ constraintClasses: ["TestSchema.TDE1"] }, { constraintClasses: ["TestSchema.TDE1"] }), + }, E1: { schemaItemType: "EntityClass" }, E2: { schemaItemType: "EntityClass" }, @@ -115,7 +121,9 @@ describe("RelationshipRule tests", () => { describe("AbstractConstraintMustNarrowBaseConstraints rule tests", () => { it("supported source and target constraint classes, rule passes", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"] }); + const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { + constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"], + }); schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -127,7 +135,9 @@ describe("RelationshipRule tests", () => { it("no base class, rule passes", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson: any = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"] }); + const childJson: any = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { + constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"], + }); delete childJson.ChildRelationship.baseClass; schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -170,7 +180,8 @@ describe("RelationshipRule tests", () => { let count = 0; for await (const diagnostic of result) { count++; - const expectedArgs = count === 1 ? ["TestSchema.E1", "Source", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"] : + const expectedArgs = count === 1 ? + ["TestSchema.E1", "Source", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"] : ["TestSchema.E2", "Target", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"]; expect(diagnostic.ecDefinition).to.equal(relationship); @@ -186,7 +197,9 @@ describe("RelationshipRule tests", () => { describe("DerivedConstraintsMustNarrowBaseConstraints rule tests", () => { it("supported source and target constraint classes, rule passes", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"] }); + const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { + constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"], + }); schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -198,7 +211,9 @@ describe("RelationshipRule tests", () => { it("no base class, rule passes", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson: any = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"] }); + const childJson: any = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.SDE2"] }, { + constraintClasses: ["TestSchema.TDE1", "TestSchema.TDE2"], + }); delete childJson.ChildRelationship.baseClass; schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -211,7 +226,9 @@ describe("RelationshipRule tests", () => { it("unsupported source constraint class, rule violated", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.E1"] }, { constraintClasses: ["TestSchema.TDE1"] }); + const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.E1"] }, { + constraintClasses: ["TestSchema.TDE1"], + }); schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -232,7 +249,9 @@ describe("RelationshipRule tests", () => { it("unsupported source and target constraint classes, rule violated twice", async () => { const baseJson = createBaseRelationship(true, { constraintClasses: ["TestSchema.SBE1"] }, { constraintClasses: ["TestSchema.TBE1"] }); - const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.E1"] }, { constraintClasses: ["TestSchema.E2"] }); + const childJson = createChildRelationship(true, { constraintClasses: ["TestSchema.SDE1", "TestSchema.E1"] }, { + constraintClasses: ["TestSchema.E2"], + }); schema = await Schema.fromJson(createSchemaJson(baseJson, childJson), new SchemaContext()); const relationship = schema.getItemSync("ChildRelationship") as RelationshipClass; @@ -241,7 +260,8 @@ describe("RelationshipRule tests", () => { let count = 0; for await (const diagnostic of result) { count++; - const expectedArgs = count === 1 ? ["TestSchema.E1", "Source", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"] : + const expectedArgs = count === 1 ? + ["TestSchema.E1", "Source", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"] : ["TestSchema.E2", "Target", "TestSchema.ChildRelationship", "TestSchema.BaseRelationship"]; expect(diagnostic.ecDefinition).to.equal(relationship); @@ -255,7 +275,6 @@ describe("RelationshipRule tests", () => { }); describe("ConstraintClassesDeriveFromAbstractConstraint rule tests", () => { - it("supported source and target constraint Entity classes, rule passes", async () => { const sourceConstraints = { abstractConstraint: "TestSchema.SBE1", @@ -514,7 +533,8 @@ describe("RelationshipRule tests", () => { let count = 0; for await (const diagnostic of result) { count++; - const expectedArgs = count === 1 ? ["TestSchema.E1", "Source", "TestSchema.BaseRelationship", "TestSchema.SBE1"] : + const expectedArgs = count === 1 ? + ["TestSchema.E1", "Source", "TestSchema.BaseRelationship", "TestSchema.SBE1"] : ["TestSchema.E2", "Target", "TestSchema.BaseRelationship", "TestSchema.TBE1"]; expect(diagnostic.ecDefinition).to.equal(relationship); diff --git a/core/ecschema-editing/src/test/Validation/ECRules/SchemaRules.test.ts b/core/ecschema-editing/src/test/Validation/ECRules/SchemaRules.test.ts index b7c9dd26688a..972ae5196730 100644 --- a/core/ecschema-editing/src/test/Validation/ECRules/SchemaRules.test.ts +++ b/core/ecschema-editing/src/test/Validation/ECRules/SchemaRules.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { MutableSchema } from "../../../Editing/Mutable/MutableSchema"; -import * as Rules from "../../../Validation/ECRules"; import { DiagnosticCategory, DiagnosticType } from "../../../Validation/Diagnostic"; +import * as Rules from "../../../Validation/ECRules"; describe("Schema rules tests", () => { let context: SchemaContext; @@ -63,7 +63,7 @@ describe("Schema rules tests", () => { version: "1.0.0", alias: "ca", items: { - SupplementalSchema: { // eslint-disable-line @typescript-eslint/naming-convention + SupplementalSchema: { // eslint-disable-line @typescript-eslint/naming-convention schemaItemType: "CustomAttributeClass", label: "Supplemental Schema", description: "Mock Supplemental Schema CustomAttributeClass", @@ -88,7 +88,9 @@ describe("Schema rules tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).to.equal(schemaA); expect(diagnostic.messageArgs).to.eql([schemaA.name, "SchemaB"]); - expect(diagnostic.messageText).to.eql("Referenced schema 'SchemaB' of schema 'SchemaA' is a supplemental schema. Supplemental schemas are not allowed to be referenced."); + expect(diagnostic.messageText).to.eql( + "Referenced schema 'SchemaB' of schema 'SchemaA' is a supplemental schema. Supplemental schemas are not allowed to be referenced.", + ); expect(diagnostic.category).to.equal(DiagnosticCategory.Error); expect(diagnostic.code).to.equal(Rules.Diagnostics.SupplementalSchemasCannotBeReferenced.code); expect(diagnostic.diagnosticType).to.equal(DiagnosticType.Schema); @@ -134,7 +136,9 @@ describe("Schema rules tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).to.equal(schemaA); expect(diagnostic.messageArgs).to.eql([schemaA.name, "b", "SchemaB", "SchemaC"]); - expect(diagnostic.messageText).to.eql("Schema 'SchemaA' has multiple schema references (SchemaB, SchemaC) with the same alias 'b', which is not allowed."); + expect(diagnostic.messageText).to.eql( + "Schema 'SchemaA' has multiple schema references (SchemaB, SchemaC) with the same alias 'b', which is not allowed.", + ); expect(diagnostic.category).to.equal(DiagnosticCategory.Error); expect(diagnostic.code).to.equal(Rules.Diagnostics.SchemaRefAliasMustBeUnique.code); expect(diagnostic.diagnosticType).to.equal(DiagnosticType.Schema); @@ -229,7 +233,9 @@ describe("Schema rules tests", () => { resultHasEntries = true; expect(diagnostic.ecDefinition).to.equal(schemaA); expect(diagnostic.messageArgs).to.eql([schemaA.name, "SchemaC --> SchemaA, SchemaA --> SchemaC, SchemaD --> SchemaA, SchemaA --> SchemaD"]); - expect(diagnostic.messageText).to.eql("Schema 'SchemaA' has reference cycles: SchemaC --> SchemaA, SchemaA --> SchemaC, SchemaD --> SchemaA, SchemaA --> SchemaD"); + expect(diagnostic.messageText).to.eql( + "Schema 'SchemaA' has reference cycles: SchemaC --> SchemaA, SchemaA --> SchemaC, SchemaD --> SchemaA, SchemaA --> SchemaD", + ); expect(diagnostic.category).to.equal(DiagnosticCategory.Error); expect(diagnostic.code).to.equal(Rules.Diagnostics.ReferenceCyclesNotAllowed.code); expect(diagnostic.diagnosticType).to.equal(DiagnosticType.Schema); diff --git a/core/ecschema-editing/src/test/Validation/SchemaChanges.test.ts b/core/ecschema-editing/src/test/Validation/SchemaChanges.test.ts index b5012d9fec50..ee0719f6ef49 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaChanges.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaChanges.test.ts @@ -3,11 +3,28 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - AnyEnumerator, Constant, CustomAttributeClass, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, PrimitiveProperty, - PropertyCategory, RelationshipClass, RelationshipConstraint, RelationshipEnd, Schema, SchemaContext, SchemaItemType, Unit, + AnyEnumerator, + Constant, + CustomAttributeClass, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PrimitiveProperty, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + RelationshipEnd, + Schema, + SchemaContext, + SchemaItemType, + Unit, } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { ChangeType, SchemaChanges } from "../../Validation/SchemaChanges"; import { SchemaCompareDiagnostics } from "../../Validation/SchemaCompareDiagnostics"; diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparer.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparer.test.ts index 48949cc23f32..140fb4cf972f 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparer.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparer.test.ts @@ -3,10 +3,27 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { AnyECType, AnyProperty, Constant, CustomAttributeClass, ECClass, EntityClass, Enumeration, Format, InvertedUnit, KindOfQuantity, Mixin, Phenomenon, PropertyCategory, - RelationshipClass, Schema, SchemaContext, StructClass, Unit, +import { + AnyECType, + AnyProperty, + Constant, + CustomAttributeClass, + ECClass, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PropertyCategory, + RelationshipClass, + Schema, + SchemaContext, + StructClass, + Unit, } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { AnyDiagnostic, DiagnosticCategory, DiagnosticType } from "../../Validation/Diagnostic"; import { ISchemaChanges, SchemaChanges } from "../../Validation/SchemaChanges"; import { SchemaCompareCodes } from "../../Validation/SchemaCompareDiagnostics"; @@ -100,7 +117,14 @@ describe("Schema comparison tests", () => { }); } - function validateDiagnostic(diagnostic: AnyDiagnostic, expectedCode: string, expectedType: DiagnosticType, expectedObject: AnyECType | undefined, expectedArgs: any[], expectedSchema: Schema | undefined) { + function validateDiagnostic( + diagnostic: AnyDiagnostic, + expectedCode: string, + expectedType: DiagnosticType, + expectedObject: AnyECType | undefined, + expectedArgs: any[], + expectedSchema: Schema | undefined, + ) { expect(diagnostic.category).to.equal(DiagnosticCategory.Error); expect(diagnostic.code).to.equal(expectedCode); expect(diagnostic.diagnosticType).to.equal(expectedType); @@ -125,7 +149,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, ["schemaKey", schemaA.schemaKey.toString(), schemaB.schemaKey.toString()], schemaA); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, [ + "schemaKey", + schemaA.schemaKey.toString(), + schemaB.schemaKey.toString(), + ], schemaA); }); it("Different version, diagnostic reported", async () => { @@ -137,7 +165,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, ["schemaKey", schemaA.schemaKey.toString(), schemaB.schemaKey.toString()], schemaA); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, [ + "schemaKey", + schemaA.schemaKey.toString(), + schemaB.schemaKey.toString(), + ], schemaA); }); it("Different alias, diagnostic reported", async () => { @@ -161,7 +193,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, ["label", "labelA", "labelB"], schemaA); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.SchemaDelta, + DiagnosticType.Schema, + schemaA, + ["label", "labelA", "labelB"], + schemaA, + ); }); it("Different description, diagnostic reported", async () => { @@ -173,7 +212,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, ["description", "descriptionA", "descriptionB"], schemaA); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaDelta, DiagnosticType.Schema, schemaA, [ + "description", + "descriptionA", + "descriptionB", + ], schemaA); }); it("Different references, diagnostic reported for each schema", async () => { @@ -228,8 +271,16 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaA, [refSchemaA, "01.00.00", "02.00.00"], schemaA); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaB, [refSchemaA2, "02.00.00", "01.00.00"], schemaB); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaA, [ + refSchemaA, + "01.00.00", + "02.00.00", + ], schemaA); + validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaB, [ + refSchemaA2, + "02.00.00", + "01.00.00", + ], schemaB); }); it("Reference missing from Schema B, diagnostic reported", async () => { @@ -356,7 +407,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, ["label", "labelA", "labelB"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.SchemaItemDelta, + DiagnosticType.SchemaItem, + itemA, + ["label", "labelA", "labelB"], + itemA.schema, + ); }); it("Undefined and empty label are considered equivalent, diagnostic not reported", async () => { @@ -406,7 +464,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, ["description", "descriptionA", "descriptionB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, [ + "description", + "descriptionA", + "descriptionB", + ], itemA.schema); }); it("Different SchemaItemType, diagnostic reported", async () => { @@ -443,7 +505,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, ["schemaItemType", "EntityClass", "Mixin"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, [ + "schemaItemType", + "EntityClass", + "Mixin", + ], itemA.schema); }); it("Same SchemaItemType, diagnostic not reported", async () => { @@ -474,8 +540,7 @@ describe("Schema comparison tests", () => { schemaItemType: "EntityClass", }, }; - const bItems = { - }; + const bItems = {}; const aJson = getSchemaJsonWithItems(schemaAJson, aItems); const bJson = getSchemaJsonWithItems(schemaAJson, bItems); const schemaA = await Schema.fromJson(aJson, contextA); @@ -513,7 +578,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ClassDelta, DiagnosticType.SchemaItem, itemA, ["modifier", "Sealed", "None"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.ClassDelta, + DiagnosticType.SchemaItem, + itemA, + ["modifier", "Sealed", "None"], + itemA.schema, + ); }); it("Same modifier, diagnostic reported", async () => { @@ -564,7 +636,10 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.BaseClassDelta, DiagnosticType.SchemaItem, itemA, [await itemA.baseClass, undefined], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.BaseClassDelta, DiagnosticType.SchemaItem, itemA, [ + await itemA.baseClass, + undefined, + ], itemA.schema); }); it("Different baseClass, Schema A has undefined base class, diagnostic reported", async () => { @@ -596,7 +671,10 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.BaseClassDelta, DiagnosticType.SchemaItem, itemA, [undefined, await itemB.baseClass], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.BaseClassDelta, DiagnosticType.SchemaItem, itemA, [ + undefined, + await itemB.baseClass, + ], itemA.schema); }); it("Different baseClass, diagnostic reported", async () => { @@ -636,7 +714,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.BaseClassDelta, DiagnosticType.SchemaItem, itemA, [baseClassA, baseClassB], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.BaseClassDelta, + DiagnosticType.SchemaItem, + itemA, + [baseClassA, baseClassB], + itemA.schema, + ); }); it("Same baseClass, diagnostic not reported", async () => { @@ -768,7 +853,6 @@ describe("Schema comparison tests", () => { typeName: "int", }, ], - }, }; const aJson = getSchemaJsonWithItems(schemaAJson, aItems); @@ -781,7 +865,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, ["schemaItemType", "StructClass", "EntityClass"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaItemDelta, DiagnosticType.SchemaItem, itemA, [ + "schemaItemType", + "StructClass", + "EntityClass", + ], itemA.schema); }); }); @@ -1151,7 +1239,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["label", "labelA", "labelB"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["label", "labelA", "labelB"], + itemA.schema, + ); }); it("Undefined and empty label are considered equivalent, diagnostic not reported", async () => { @@ -1229,7 +1324,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["description", "descriptionA", "descriptionB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "description", + "descriptionA", + "descriptionB", + ], itemA.schema); }); it("Different isReadOnly, diagnostic reported", async () => { @@ -1270,7 +1369,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["isReadOnly", true, false], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["isReadOnly", true, false], + itemA.schema, + ); }); it("Different priority, diagnostic reported", async () => { @@ -1311,7 +1417,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["priority", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["priority", 1, 2], + itemA.schema, + ); }); it("Different category, diagnostic reported", async () => { @@ -1376,7 +1489,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["category", "SchemaA.CategoryA", "SchemaA.CategoryB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "category", + "SchemaA.CategoryA", + "SchemaA.CategoryB", + ], itemA.schema); }); it("Schema A category undefined, diagnostic reported", async () => { @@ -1428,7 +1545,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["category", undefined, "SchemaA.CategoryA"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "category", + undefined, + "SchemaA.CategoryA", + ], itemA.schema); }); it("Schema B category undefined, diagnostic reported", async () => { @@ -1480,7 +1601,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["category", "SchemaA.CategoryA", undefined], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "category", + "SchemaA.CategoryA", + undefined, + ], itemA.schema); }); it("Different kindOfQuantity, diagnostic reported", async () => { @@ -1595,7 +1720,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["kindOfQuantity", "SchemaA.KindOfQuantityA", "SchemaA.KindOfQuantityB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "kindOfQuantity", + "SchemaA.KindOfQuantityA", + "SchemaA.KindOfQuantityB", + ], itemA.schema); }); it("Schema A kindOfQuantity undefined, diagnostic reported", async () => { @@ -1691,7 +1820,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["kindOfQuantity", undefined, "SchemaA.KindOfQuantityA"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "kindOfQuantity", + undefined, + "SchemaA.KindOfQuantityA", + ], itemA.schema); }); it("Schema B kindOfQuantity undefined, diagnostic reported", async () => { @@ -1787,7 +1920,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["kindOfQuantity", "SchemaA.KindOfQuantityA", undefined], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "kindOfQuantity", + "SchemaA.KindOfQuantityA", + undefined, + ], itemA.schema); }); it("Different propertyType, diagnostic reported", async () => { @@ -1834,7 +1971,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["type", "PrimitiveProperty", "PrimitiveArrayProperty"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "type", + "PrimitiveProperty", + "PrimitiveArrayProperty", + ], itemA.schema); }); it("Different property minLength, maxLength, extendedTypeName, diagnostic reported", async () => { @@ -1879,9 +2020,27 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(3, "Expected 3 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["minLength", 10, 50], itemA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["maxLength", 150, 450], itemA.schema); - validateDiagnostic(reporter.diagnostics[2], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["extendedTypeName", "Json", "XML"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["minLength", 10, 50], + itemA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["maxLength", 150, 450], + itemA.schema, + ); + validateDiagnostic(reporter.diagnostics[2], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "extendedTypeName", + "Json", + "XML", + ], itemA.schema); }); it("Different property minValue, maxValue, diagnostic reported", async () => { @@ -1924,8 +2083,22 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["minValue", 1, 5], itemA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["maxValue", 100, 95], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["minValue", 1, 5], + itemA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["maxValue", 100, 95], + itemA.schema, + ); }); it("Different array minOccurs, diagnostic reported", async () => { @@ -1966,7 +2139,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["minOccurs", 0, 1], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["minOccurs", 0, 1], + itemA.schema, + ); }); it("Different array maxOccurs, diagnostic reported", async () => { @@ -2007,7 +2187,14 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["maxOccurs", 0, 1], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyDelta, + DiagnosticType.Property, + itemAProp, + ["maxOccurs", 0, 1], + itemA.schema, + ); }); it("Different enumeration, diagnostic reported", async () => { @@ -2086,7 +2273,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["enumeration", "SchemaA.EnumA", "SchemaA.EnumB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "enumeration", + "SchemaA.EnumA", + "SchemaA.EnumB", + ], itemA.schema); }); it("Same enumeration, diagnostic not reported", async () => { @@ -2272,7 +2463,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["relationshipClass", "SchemaA.RelationshipA", "SchemaA.RelationshipB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "relationshipClass", + "SchemaA.RelationshipA", + "SchemaA.RelationshipB", + ], itemA.schema); }); it("Different navigation property direction, diagnostic reported", async () => { @@ -2357,7 +2552,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["direction", "Forward", "Backward"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "direction", + "Forward", + "Backward", + ], itemA.schema); }); it("Same navigation property relationship, diagnostic not reported", async () => { @@ -2479,7 +2678,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["primitiveType", "string", "int"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "primitiveType", + "string", + "int", + ], itemA.schema); }); it("Different struct class, diagnostic reported", async () => { @@ -2558,7 +2761,11 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, ["structClass", "SchemaA.StructA", "SchemaA.StructB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyDelta, DiagnosticType.Property, itemAProp, [ + "structClass", + "SchemaA.StructA", + "SchemaA.StructB", + ], itemA.schema); }); it("Same struct class, diagnostic not reported", async () => { @@ -2832,7 +3039,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("MixinA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.MixinDelta, DiagnosticType.SchemaItem, itemA, ["appliesTo", "SchemaA.TestClassA", "SchemaA.TestClassB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.MixinDelta, DiagnosticType.SchemaItem, itemA, [ + "appliesTo", + "SchemaA.TestClassA", + "SchemaA.TestClassB", + ], itemA.schema); }); it("Same appliesTo, diagnostic not reported", async () => { @@ -3030,7 +3241,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestRelationship") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipDelta, DiagnosticType.SchemaItem, itemA, ["strength", "Referencing", "Embedding"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipDelta, DiagnosticType.SchemaItem, itemA, [ + "strength", + "Referencing", + "Embedding", + ], itemA.schema); }); it("Same strength, diagnostic reported", async () => { @@ -3161,7 +3376,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestRelationship") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipDelta, DiagnosticType.SchemaItem, itemA, ["strengthDirection", "Forward", "Backward"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipDelta, DiagnosticType.SchemaItem, itemA, [ + "strengthDirection", + "Forward", + "Backward", + ], itemA.schema); }); it("Same strengthDirection, diagnostic not reported", async () => { @@ -3292,7 +3511,8 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - expect(reporter.diagnostics.find((d) => d.code === SchemaCompareCodes.SchemaItemMissing && d.ecDefinition === relationship)).to.not.be.undefined; + expect(reporter.diagnostics.find((d) => d.code === SchemaCompareCodes.SchemaItemMissing && d.ecDefinition === relationship)).to.not.be + .undefined; }); it("Different multiplicities, diagnostic reported for each constraint", async () => { @@ -3343,8 +3563,22 @@ describe("Schema comparison tests", () => { const relA = await schemaA.getItem("TestRelationship") as RelationshipClass; expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["multiplicity", "(0..*)", "(0..1)"], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["multiplicity", "(0..1)", "(0..*)"], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["multiplicity", "(0..*)", "(0..1)"], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["multiplicity", "(0..1)", "(0..*)"], + relA.schema, + ); }); it("Different roleLabel, diagnostic reported for each constraint", async () => { @@ -3395,8 +3629,22 @@ describe("Schema comparison tests", () => { const relA = await schemaA.getItem("TestRelationship") as RelationshipClass; expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["roleLabel", "LabelA", "LabelB"], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["roleLabel", "LabelB", "LabelA"], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["roleLabel", "LabelA", "LabelB"], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["roleLabel", "LabelB", "LabelA"], + relA.schema, + ); }); it("Different polymorphic, diagnostic reported for each constraint", async () => { @@ -3447,8 +3695,22 @@ describe("Schema comparison tests", () => { const relA = await schemaA.getItem("TestRelationship") as RelationshipClass; expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["polymorphic", true, false], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["polymorphic", false, true], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["polymorphic", true, false], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["polymorphic", false, true], + relA.schema, + ); }); it("Different abstractConstraint, diagnostic reported for each constraint", async () => { @@ -3503,8 +3765,22 @@ describe("Schema comparison tests", () => { const relA = await schemaA.getItem("TestRelationship") as RelationshipClass; expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["abstractConstraint", "SchemaA.TestClassA", "SchemaA.TestClassB"], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["abstractConstraint", "SchemaA.TestClassB", "SchemaA.TestClassA"], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["abstractConstraint", "SchemaA.TestClassA", "SchemaA.TestClassB"], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["abstractConstraint", "SchemaA.TestClassB", "SchemaA.TestClassA"], + relA.schema, + ); }); it("Schema A abstractConstraints undefined, diagnostic reported for each constraint", async () => { @@ -3563,8 +3839,22 @@ describe("Schema comparison tests", () => { const relA = await schemaA.getItem("TestRelationship") as RelationshipClass; expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["abstractConstraint", undefined, "SchemaA.TestClassA"], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["abstractConstraint", undefined, "SchemaA.TestClassA"], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["abstractConstraint", undefined, "SchemaA.TestClassA"], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["abstractConstraint", undefined, "SchemaA.TestClassA"], + relA.schema, + ); }); it("Schema B abstractConstraints undefined, diagnostic reported for each constraint", async () => { @@ -3620,8 +3910,22 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.source, ["abstractConstraint", "SchemaA.TestClassA", undefined], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintDelta, DiagnosticType.RelationshipConstraint, relA.target, ["abstractConstraint", "SchemaA.TestClassA", undefined], relA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.source, + ["abstractConstraint", "SchemaA.TestClassA", undefined], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintDelta, + DiagnosticType.RelationshipConstraint, + relA.target, + ["abstractConstraint", "SchemaA.TestClassA", undefined], + relA.schema, + ); }); it("Different constraints, diagnostic reported for each constraint", async () => { @@ -3678,10 +3982,38 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(4, "Expected 4 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.RelationshipConstraintClassMissing, DiagnosticType.RelationshipConstraint, relA.source, [classB], relA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.RelationshipConstraintClassMissing, DiagnosticType.RelationshipConstraint, relA.target, [classB], relA.schema); - validateDiagnostic(reporter.diagnostics[2], SchemaCompareCodes.RelationshipConstraintClassMissing, DiagnosticType.RelationshipConstraint, relB.source, [classC], relB.schema); - validateDiagnostic(reporter.diagnostics[3], SchemaCompareCodes.RelationshipConstraintClassMissing, DiagnosticType.RelationshipConstraint, relB.target, [classC], relB.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.RelationshipConstraintClassMissing, + DiagnosticType.RelationshipConstraint, + relA.source, + [classB], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.RelationshipConstraintClassMissing, + DiagnosticType.RelationshipConstraint, + relA.target, + [classB], + relA.schema, + ); + validateDiagnostic( + reporter.diagnostics[2], + SchemaCompareCodes.RelationshipConstraintClassMissing, + DiagnosticType.RelationshipConstraint, + relB.source, + [classC], + relB.schema, + ); + validateDiagnostic( + reporter.diagnostics[3], + SchemaCompareCodes.RelationshipConstraintClassMissing, + DiagnosticType.RelationshipConstraint, + relB.target, + [classC], + relB.schema, + ); }); }); @@ -3737,7 +4069,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestCustomAttribute") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.CustomAttributeClassDelta, DiagnosticType.SchemaItem, itemA, ["appliesTo", "Schema, AnyProperty", "AnyClass"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.CustomAttributeClassDelta, DiagnosticType.SchemaItem, itemA, [ + "appliesTo", + "Schema, AnyProperty", + "AnyClass", + ], itemA.schema); }); }); @@ -3996,8 +4332,22 @@ describe("Schema comparison tests", () => { const caB = itemB.customAttributes!.get("SchemaA.CustomAttributeB"); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.CustomAttributeInstanceClassMissing, DiagnosticType.CustomAttributeContainer, itemA, [caA], itemA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.CustomAttributeInstanceClassMissing, DiagnosticType.CustomAttributeContainer, itemB, [caB], itemB.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.CustomAttributeInstanceClassMissing, + DiagnosticType.CustomAttributeContainer, + itemA, + [caA], + itemA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.CustomAttributeInstanceClassMissing, + DiagnosticType.CustomAttributeContainer, + itemB, + [caB], + itemB.schema, + ); }); it("Different CA properties, diagnostic reported", async () => { @@ -4075,8 +4425,22 @@ describe("Schema comparison tests", () => { const caB = propertyB!.customAttributes!.get("SchemaA.CustomAttribute"); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.CustomAttributeInstanceClassMissing, DiagnosticType.CustomAttributeContainer, propertyA, [caA], itemA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.CustomAttributeInstanceClassMissing, DiagnosticType.CustomAttributeContainer, propertyB, [caB], itemB.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.CustomAttributeInstanceClassMissing, + DiagnosticType.CustomAttributeContainer, + propertyA, + [caA], + itemA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.CustomAttributeInstanceClassMissing, + DiagnosticType.CustomAttributeContainer, + propertyB, + [caB], + itemB.schema, + ); }); it("Same custom attribute from updated schema reference, no ca diagnostic reported", async () => { @@ -4147,8 +4511,16 @@ describe("Schema comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(reporter.diagnostics.length).to.equal(2, "Expected 2 differences."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaA, [refSchemaA, "01.00.00", "01.00.01"], schemaA); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaB, [refSchemaB, "01.00.01", "01.00.00"], schemaB); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaA, [ + refSchemaA, + "01.00.00", + "01.00.01", + ], schemaA); + validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.SchemaReferenceDelta, DiagnosticType.Schema, schemaB, [ + refSchemaB, + "01.00.01", + "01.00.00", + ], schemaB); }); it("Same custom attribute different property order, no diagnostic reported", async () => { @@ -4164,8 +4536,7 @@ describe("Schema comparison tests", () => { name: "from", type: "PrimitiveProperty", typeName: "string", - }, - { + }, { name: "to", type: "PrimitiveProperty", typeName: "string", @@ -4310,7 +4681,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestEnumeration") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumerationDelta, DiagnosticType.SchemaItem, itemA, ["type", "string", "int"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.EnumerationDelta, + DiagnosticType.SchemaItem, + itemA, + ["type", "string", "int"], + itemA.schema, + ); }); it("Different isStrict, diagnostic reported", async () => { @@ -4351,7 +4729,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestEnumeration") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumerationDelta, DiagnosticType.SchemaItem, itemA, ["isStrict", true, false], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.EnumerationDelta, + DiagnosticType.SchemaItem, + itemA, + ["isStrict", true, false], + itemA.schema, + ); }); it("Different enumerators missing, diagnostic reported for each schema", async () => { @@ -4437,7 +4822,12 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestEnumeration") as Enumeration; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [itemA.enumerators[0], "description", "A", "B"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [ + itemA.enumerators[0], + "description", + "A", + "B", + ], itemA.schema); }); it("Different enumerator label, diagnostic reported", async () => { @@ -4478,7 +4868,12 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestEnumeration") as Enumeration; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [itemA.enumerators[0], "label", "A", "B"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [ + itemA.enumerators[0], + "label", + "A", + "B", + ], itemA.schema); }); it("Undefined and empty label are considered equivalent, diagnostic not reported", async () => { @@ -4554,7 +4949,12 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("TestEnumeration") as Enumeration; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [itemA.enumerators[0], "value", "A", "B"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.EnumeratorDelta, DiagnosticType.SchemaItem, itemA, [ + itemA.enumerators[0], + "value", + "A", + "B", + ], itemA.schema); }); }); @@ -4621,7 +5021,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("KoqA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.KoqDelta, DiagnosticType.SchemaItem, itemA, ["relativeError", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.KoqDelta, + DiagnosticType.SchemaItem, + itemA, + ["relativeError", 1, 2], + itemA.schema, + ); }); it("Different persistenceUnit, diagnostic reported", async () => { @@ -4652,7 +5059,11 @@ describe("Schema comparison tests", () => { const unitB = await schemaB.getItem("UnitB") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.KoqDelta, DiagnosticType.SchemaItem, itemA, ["persistenceUnit", unitA.fullName, unitB.fullName], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.KoqDelta, DiagnosticType.SchemaItem, itemA, [ + "persistenceUnit", + unitA.fullName, + unitB.fullName, + ], itemA.schema); }); it("Different presentation units, diagnostic reported for each schema", async () => { @@ -4771,7 +5182,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("CategoryA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PropertyCategoryDelta, DiagnosticType.SchemaItem, itemA, ["priority", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PropertyCategoryDelta, + DiagnosticType.SchemaItem, + itemA, + ["priority", 1, 2], + itemA.schema, + ); }); }); @@ -4829,7 +5247,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["roundFactor", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["roundFactor", 1, 2], + itemA.schema, + ); }); it("Different type, diagnostic reported", async () => { @@ -4856,7 +5281,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["type", "Decimal", "Fractional"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["type", "Decimal", "Fractional"], + itemA.schema, + ); }); it("Different precision, diagnostic reported", async () => { @@ -4885,7 +5317,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["precision", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["precision", 1, 2], + itemA.schema, + ); }); it("Different minWidth, diagnostic reported", async () => { @@ -4943,7 +5382,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["scientificType", "Normalized", "ZeroNormalized"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, [ + "scientificType", + "Normalized", + "ZeroNormalized", + ], itemA.schema); }); it("Different showSignOption, diagnostic reported", async () => { @@ -4972,7 +5415,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["showSignOption", "NoSign", "SignAlways"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, [ + "showSignOption", + "NoSign", + "SignAlways", + ], itemA.schema); }); it("Different decimalSeparator, diagnostic reported", async () => { @@ -5001,7 +5448,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["decimalSeparator", "-", "."], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["decimalSeparator", "-", "."], + itemA.schema, + ); }); it("Different thousandSeparator, diagnostic reported", async () => { @@ -5030,7 +5484,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["thousandSeparator", "-", "."], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["thousandSeparator", "-", "."], + itemA.schema, + ); }); it("Different uomSeparator, diagnostic reported", async () => { @@ -5059,7 +5520,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["uomSeparator", "-", "."], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["uomSeparator", "-", "."], + itemA.schema, + ); }); it("Different stationSeparator, diagnostic reported", async () => { @@ -5088,7 +5556,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["stationSeparator", "-", "."], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["stationSeparator", "-", "."], + itemA.schema, + ); }); it("Different stationOffsetSize, diagnostic reported", async () => { @@ -5117,7 +5592,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["stationOffsetSize", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["stationOffsetSize", 1, 2], + itemA.schema, + ); }); it("Different formatTraits, diagnostic reported", async () => { @@ -5146,7 +5628,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["formatTraits", "TrailZeroes,KeepSingleZero", "KeepSingleZero"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, [ + "formatTraits", + "TrailZeroes,KeepSingleZero", + "KeepSingleZero", + ], itemA.schema); }); it("Different spacer, diagnostic reported", async () => { @@ -5187,7 +5673,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["spacer", "A", "B"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["spacer", "A", "B"], + itemA.schema, + ); }); it("Different includeZero, diagnostic reported", async () => { @@ -5228,7 +5721,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("FormatA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.FormatDelta, DiagnosticType.SchemaItem, itemA, ["includeZero", true, false], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.FormatDelta, + DiagnosticType.SchemaItem, + itemA, + ["includeZero", true, false], + itemA.schema, + ); }); it("Different units, diagnostic reported for each schema", async () => { @@ -5315,7 +5815,14 @@ describe("Schema comparison tests", () => { const unit = await schemaB.getItem("UnitA"); expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [unit, "A", "B"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.UnitLabelOverrideDelta, + DiagnosticType.SchemaItem, + itemA, + [unit, "A", "B"], + itemA.schema, + ); }); it("Null and Empty unit labels, diagnostic reported", async () => { @@ -5327,7 +5834,10 @@ describe("Schema comparison tests", () => { includeZero: true, spacer: "A", units: [ - { name: "SchemaA.UnitA" }, { name: "SchemaA.UnitB", label: "" }, { name: "SchemaA.UnitC" }, { name: "SchemaA.UnitD", label: "tango" }, + { name: "SchemaA.UnitA" }, + { name: "SchemaA.UnitB", label: "" }, + { name: "SchemaA.UnitC" }, + { name: "SchemaA.UnitD", label: "tango" }, ], }, }, @@ -5340,7 +5850,10 @@ describe("Schema comparison tests", () => { includeZero: true, spacer: "A", units: [ - { name: "SchemaA.UnitA", label: "" }, { name: "SchemaA.UnitB" }, { name: "SchemaA.UnitC", label: "bravo" }, { name: "SchemaA.UnitD" }, + { name: "SchemaA.UnitA", label: "" }, + { name: "SchemaA.UnitB" }, + { name: "SchemaA.UnitC", label: "bravo" }, + { name: "SchemaA.UnitD" }, ], }, }, @@ -5360,10 +5873,32 @@ describe("Schema comparison tests", () => { const unitD = await schemaB.getItem("UnitD") as Unit; expect(reporter.diagnostics.length).to.equal(4, "Expected total of 4 differences, one for each unit label."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [unitA, undefined, ""], itemA.schema); - validateDiagnostic(reporter.diagnostics[1], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [unitB, "", undefined], itemA.schema); - validateDiagnostic(reporter.diagnostics[2], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [unitC, undefined, "bravo"], itemA.schema); - validateDiagnostic(reporter.diagnostics[3], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [unitD, "tango", undefined], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.UnitLabelOverrideDelta, + DiagnosticType.SchemaItem, + itemA, + [unitA, undefined, ""], + itemA.schema, + ); + validateDiagnostic( + reporter.diagnostics[1], + SchemaCompareCodes.UnitLabelOverrideDelta, + DiagnosticType.SchemaItem, + itemA, + [unitB, "", undefined], + itemA.schema, + ); + validateDiagnostic(reporter.diagnostics[2], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [ + unitC, + undefined, + "bravo", + ], itemA.schema); + validateDiagnostic(reporter.diagnostics[3], SchemaCompareCodes.UnitLabelOverrideDelta, DiagnosticType.SchemaItem, itemA, [ + unitD, + "tango", + undefined, + ], itemA.schema); }); }); @@ -5423,7 +5958,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("UnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, ["phenomenon", "SchemaA.PhenomenonA", "SchemaA.PhenomenonB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, [ + "phenomenon", + "SchemaA.PhenomenonA", + "SchemaA.PhenomenonB", + ], itemA.schema); }); it("Different unitSystem, diagnostic reported", async () => { @@ -5440,7 +5979,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("UnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, ["unitSystem", "SchemaA.UnitSystemA", "SchemaA.UnitSystemB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, [ + "unitSystem", + "SchemaA.UnitSystemA", + "SchemaA.UnitSystemB", + ], itemA.schema); }); it("Different definition, diagnostic reported", async () => { @@ -5457,7 +6000,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("UnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, ["definition", "A", "B"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.UnitDelta, + DiagnosticType.SchemaItem, + itemA, + ["definition", "A", "B"], + itemA.schema, + ); }); it("Different numerator, diagnostic reported", async () => { @@ -5508,7 +6058,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("UnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.UnitDelta, DiagnosticType.SchemaItem, itemA, ["denominator", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.UnitDelta, + DiagnosticType.SchemaItem, + itemA, + ["denominator", 1, 2], + itemA.schema, + ); }); }); @@ -5560,7 +6117,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("InvertedUnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.InvertedUnitDelta, DiagnosticType.SchemaItem, itemA, ["invertsUnit", "SchemaA.UnitA", "SchemaA.UnitB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.InvertedUnitDelta, DiagnosticType.SchemaItem, itemA, [ + "invertsUnit", + "SchemaA.UnitA", + "SchemaA.UnitB", + ], itemA.schema); }); it("Different unitSystem, diagnostic reported", async () => { @@ -5589,7 +6150,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("InvertedUnitA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.InvertedUnitDelta, DiagnosticType.SchemaItem, itemA, ["unitSystem", "SchemaA.UnitSystemA", "SchemaA.UnitSystemB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.InvertedUnitDelta, DiagnosticType.SchemaItem, itemA, [ + "unitSystem", + "SchemaA.UnitSystemA", + "SchemaA.UnitSystemB", + ], itemA.schema); }); }); @@ -5638,7 +6203,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("PhenomenonA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.PhenomenonDelta, DiagnosticType.SchemaItem, itemA, ["definition", "A", "B"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.PhenomenonDelta, + DiagnosticType.SchemaItem, + itemA, + ["definition", "A", "B"], + itemA.schema, + ); }); }); @@ -5716,7 +6288,11 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("ConstantA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ConstantDelta, DiagnosticType.SchemaItem, itemA, ["phenomenon", "SchemaA.PhenomenonA", "SchemaA.PhenomenonB"], itemA.schema); + validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ConstantDelta, DiagnosticType.SchemaItem, itemA, [ + "phenomenon", + "SchemaA.PhenomenonA", + "SchemaA.PhenomenonB", + ], itemA.schema); }); it("Different definition, diagnostic reported", async () => { @@ -5753,7 +6329,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("ConstantA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ConstantDelta, DiagnosticType.SchemaItem, itemA, ["definition", "A", "B"], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.ConstantDelta, + DiagnosticType.SchemaItem, + itemA, + ["definition", "A", "B"], + itemA.schema, + ); }); it("Different numerator, diagnostic reported", async () => { @@ -5792,7 +6375,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("ConstantA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ConstantDelta, DiagnosticType.SchemaItem, itemA, ["numerator", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.ConstantDelta, + DiagnosticType.SchemaItem, + itemA, + ["numerator", 1, 2], + itemA.schema, + ); }); it("Different denominator, diagnostic reported", async () => { @@ -5831,7 +6421,14 @@ describe("Schema comparison tests", () => { const itemA = await schemaA.getItem("ConstantA") as ECClass; expect(reporter.diagnostics.length).to.equal(1, "Expected 1 difference."); - validateDiagnostic(reporter.diagnostics[0], SchemaCompareCodes.ConstantDelta, DiagnosticType.SchemaItem, itemA, ["denominator", 1, 2], itemA.schema); + validateDiagnostic( + reporter.diagnostics[0], + SchemaCompareCodes.ConstantDelta, + DiagnosticType.SchemaItem, + itemA, + ["denominator", 1, 2], + itemA.schema, + ); }); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparison.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparison.test.ts index d954628288c6..d476f5903528 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparison.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparison.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; import { expect } from "chai"; +import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; class TestSchemaCompareReporter implements ISchemaCompareReporter { public changes: SchemaChanges[] = []; @@ -110,7 +110,15 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.ConstantDelta, "SchemaA.testPhenomenon", "SchemaB.testPhenomenon", "phenomenon")).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.ConstantDelta, + "SchemaA.testPhenomenon", + "SchemaB.testPhenomenon", + "phenomenon", + ), + ).to.be.undefined; }); it("should report constant delta for phenomenon with the same name but defined in a referenced schema", async () => { @@ -152,7 +160,15 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.ConstantDelta, "SchemaA.testPhenomenon", "DummyReferenceTwo.testPhenomenon", "phenomenon")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.ConstantDelta, + "SchemaA.testPhenomenon", + "DummyReferenceTwo.testPhenomenon", + "phenomenon", + ), + ).to.be.not.undefined; }); }); @@ -196,8 +212,24 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.UnitDelta, "SchemaA.testPhenomenon", "SchemaB.testPhenomenon", "phenomenon")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.UnitDelta, "SchemaA.testUnitSystem", "SchemaB.testUnitSystem", "unitSystem")).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.UnitDelta, + "SchemaA.testPhenomenon", + "SchemaB.testPhenomenon", + "phenomenon", + ), + ).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.UnitDelta, + "SchemaA.testUnitSystem", + "SchemaB.testUnitSystem", + "unitSystem", + ), + ).to.be.undefined; }); it("should report unit delta for phenomenon and unitSystem with the same names but defined in a referenced schema", async () => { @@ -241,8 +273,24 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.UnitDelta, "SchemaA.testPhenomenon", "DummyReferenceTwo.testPhenomenon", "phenomenon")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.UnitDelta, "SchemaA.testUnitSystem", "DummyReferenceTwo.testUnitSystem", "unitSystem")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.UnitDelta, + "SchemaA.testPhenomenon", + "DummyReferenceTwo.testPhenomenon", + "phenomenon", + ), + ).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.UnitDelta, + "SchemaA.testUnitSystem", + "DummyReferenceTwo.testUnitSystem", + "unitSystem", + ), + ).to.be.not.undefined; }); }); @@ -296,8 +344,24 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.InvertedUnitDelta, "SchemaA.testUnit", "SchemaB.testUnit", "invertsUnit")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.InvertedUnitDelta, "SchemaA.testUnitSystem", "SchemaB.testUnitSystem", "unitSystem")).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.InvertedUnitDelta, + "SchemaA.testUnit", + "SchemaB.testUnit", + "invertsUnit", + ), + ).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.InvertedUnitDelta, + "SchemaA.testUnitSystem", + "SchemaB.testUnitSystem", + "unitSystem", + ), + ).to.be.undefined; }); it("should report invertedUnit delta for unitSystem and invertsUnit with the same names but defined in a referenced schema", async () => { @@ -351,8 +415,24 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.InvertedUnitDelta, "SchemaA.testUnit", "DummyReferenceTwo.testUnit", "invertsUnit")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.InvertedUnitDelta, "SchemaA.testUnitSystem", "DummyReferenceTwo.testUnitSystem", "unitSystem")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.InvertedUnitDelta, + "SchemaA.testUnit", + "DummyReferenceTwo.testUnit", + "invertsUnit", + ), + ).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.InvertedUnitDelta, + "SchemaA.testUnitSystem", + "DummyReferenceTwo.testUnitSystem", + "unitSystem", + ), + ).to.be.not.undefined; }); }); @@ -424,8 +504,16 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.KoqDelta, "SchemaA.testUnit", "SchemaB.testUnit", "persistenceUnit")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PresentationUnitMissing, "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]")).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.KoqDelta, "SchemaA.testUnit", "SchemaB.testUnit", "persistenceUnit"), + ).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PresentationUnitMissing, + "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]", + ), + ).to.be.undefined; }); it("should report presentation unit missing when the presentationFormats have the same names but different precision", async () => { @@ -473,7 +561,13 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PresentationUnitMissing, "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PresentationUnitMissing, + "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]", + ), + ).to.be.not.undefined; }); it("should report presentation unit missing when the presentationFormats have the same names but different labels", async () => { @@ -521,7 +615,13 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PresentationUnitMissing, "SchemaA.testFormat(4)[SchemaA.testUnit|test]")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PresentationUnitMissing, + "SchemaA.testFormat(4)[SchemaA.testUnit|test]", + ), + ).to.be.not.undefined; }); it("should report kindOfQuantity delta for presentationFormats and persistenceUnit with the same names but defined in a referenced schema", async () => { @@ -581,8 +681,22 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.KoqDelta, "SchemaA.testUnit", "DummyReferenceTwo.testUnit", "persistenceUnit")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PresentationUnitMissing, "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.KoqDelta, + "SchemaA.testUnit", + "DummyReferenceTwo.testUnit", + "persistenceUnit", + ), + ).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PresentationUnitMissing, + "SchemaA.testFormat(4)[SchemaA.testUnit|undefined]", + ), + ).to.be.not.undefined; }); }); @@ -637,7 +751,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }, { name: "SchemaA.in", - label: "\"", + label: '"', }, ], }, @@ -670,7 +784,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }, { name: "SchemaB.in", - label: "\"", + label: '"', }, ], }, @@ -718,7 +832,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }, { name: "SchemaA.in", - label: "\"", + label: '"', }, ], }, @@ -756,7 +870,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }, { name: "DummyReferenceTwo.in", - label: "\"", + label: '"', }, ], }, @@ -803,7 +917,9 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaB.testBaseClass")).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaB.testBaseClass"), + ).to.be.undefined; }); it("should not report baseClass delta when the base class has the same name with different case and is defined in comparable schemas", async () => { @@ -835,7 +951,9 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaB.testbaseclass")).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaB.testbaseclass"), + ).to.be.undefined; }); it("should report baseClass delta when base class has different full name", async () => { @@ -867,7 +985,9 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClassA", "SchemaB.testBaseClassB")).to.be.not.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClassA", "SchemaB.testBaseClassB"), + ).to.be.not.undefined; }); it("should report baseClass delta for baseClass with the same name but defined in a referenced schema", async () => { @@ -911,7 +1031,14 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "DummyReferenceTwo.testBaseClass")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.BaseClassDelta, + "SchemaA.testBaseClass", + "DummyReferenceTwo.testBaseClass", + ), + ).to.be.not.undefined; }); it("should not report baseClass delta if the full names are the same, even though the schema containing the definition classA has a different name ", async () => { @@ -942,11 +1069,12 @@ describe("Schema comparison tests for comparing schemas with different names", ( baseClass: "SchemaA.testBaseClass", }, }, - }, contextA); const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaA.testBaseClass")).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.BaseClassDelta, "SchemaA.testBaseClass", "SchemaA.testBaseClass"), + ).to.be.undefined; }); }); @@ -991,8 +1119,12 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.MixinDelta, "SchemaA.testEntity", "SchemaB.testEntity", "appliesTo")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.MixinDelta, "SchemaA.testEntity", "SchemaB.testEntity2", "appliesTo")).to.be.not.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.MixinDelta, "SchemaA.testEntity", "SchemaB.testEntity", "appliesTo"), + ).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.MixinDelta, "SchemaA.testEntity", "SchemaB.testEntity2", "appliesTo"), + ).to.be.not.undefined; }); it("should report Mixin delta for appliesTo with the same name but defined in a referenced schema", async () => { @@ -1036,7 +1168,15 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.MixinDelta, "SchemaA.testEntity", "DummyReferenceTwo.testEntity", "appliesTo")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.MixinDelta, + "SchemaA.testEntity", + "DummyReferenceTwo.testEntity", + "appliesTo", + ), + ).to.be.not.undefined; }); }); @@ -1114,10 +1254,28 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintDelta, "SchemaA.sourceEntity", "SchemaB.sourceEntity", "abstractConstraint")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintDelta, "SchemaA.targetEntity", "SchemaB.targetEntity", "abstractConstraint")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.sourceEntity")).to.be.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.targetEntity")).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.RelationshipConstraintDelta, + "SchemaA.sourceEntity", + "SchemaB.sourceEntity", + "abstractConstraint", + ), + ).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.RelationshipConstraintDelta, + "SchemaA.targetEntity", + "SchemaB.targetEntity", + "abstractConstraint", + ), + ).to.be.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.sourceEntity")).to + .be.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.targetEntity")).to + .be.undefined; }); it("should report Relationship Constraint delta for abstract constraint with the same name but defined in a referenced schema", async () => { @@ -1205,15 +1363,33 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintDelta, "SchemaA.sourceEntity", "DummyReferenceTwo.sourceEntity", "abstractConstraint")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintDelta, "SchemaA.targetEntity", "DummyReferenceTwo.targetEntity", "abstractConstraint")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.sourceEntity")).to.be.not.undefined; - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.targetEntity")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.RelationshipConstraintDelta, + "SchemaA.sourceEntity", + "DummyReferenceTwo.sourceEntity", + "abstractConstraint", + ), + ).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.RelationshipConstraintDelta, + "SchemaA.targetEntity", + "DummyReferenceTwo.targetEntity", + "abstractConstraint", + ), + ).to.be.not.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.sourceEntity")).to + .be.not.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.RelationshipConstraintClassMissing, "SchemaA.targetEntity")).to + .be.not.undefined; }); }); }); - describe("Property comparison cases", ()=> { + describe("Property comparison cases", () => { function items(schemaName: string) { return { testUnitSystem: { @@ -1237,7 +1413,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }; } - it("should not report property delta when the category class has the same name and is defined in comparable schemas", async ()=> { + it("should not report property delta when the category class has the same name and is defined in comparable schemas", async () => { const schemaA = await Schema.fromJson({ ...schemaAJson, items: { @@ -1284,10 +1460,18 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PropertyDelta, "SchemaA.testCategory", "SchemaB.testCategory", "category")).to.be.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PropertyDelta, + "SchemaA.testCategory", + "SchemaB.testCategory", + "category", + ), + ).to.be.undefined; }); - it("should not report property delta when the kind of quantity class has the same name and is defined in comparable schemas", async ()=> { + it("should not report property delta when the kind of quantity class has the same name and is defined in comparable schemas", async () => { const schemaA = await Schema.fromJson({ ...schemaAJson, items: { @@ -1326,10 +1510,12 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PropertyDelta, "SchemaA.testKoq", "SchemaB.testKoq", "kindOfQuantity")).to.be.undefined; + expect( + findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PropertyDelta, "SchemaA.testKoq", "SchemaB.testKoq", "kindOfQuantity"), + ).to.be.undefined; }); - it("should report property delta for category with the same name but defined in a referenced schema", async ()=> { + it("should report property delta for category with the same name but defined in a referenced schema", async () => { await Schema.fromJson({ ...dummyRefOneJson, items: { @@ -1388,10 +1574,18 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PropertyDelta, "DummyReferenceOne.testCategory", "SchemaB.testCategory", "category")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PropertyDelta, + "DummyReferenceOne.testCategory", + "SchemaB.testCategory", + "category", + ), + ).to.be.not.undefined; }); - it("should report property delta for kind of quantity with the same name but defined in a referenced schema", async ()=> { + it("should report property delta for kind of quantity with the same name but defined in a referenced schema", async () => { await Schema.fromJson({ ...dummyRefOneJson, items: { @@ -1442,11 +1636,19 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, SchemaCompareCodes.PropertyDelta, "DummyReferenceOne.testKoq", "SchemaB.testKoq", "kindOfQuantity")).to.be.not.undefined; + expect( + findDiagnostic( + reporter.changes[0].allDiagnostics, + SchemaCompareCodes.PropertyDelta, + "DummyReferenceOne.testKoq", + "SchemaB.testKoq", + "kindOfQuantity", + ), + ).to.be.not.undefined; }); }); - describe("Custom Attribute comparison cases", ()=> { + describe("Custom Attribute comparison cases", () => { const items = { testCA: { schemaItemType: "CustomAttributeClass", @@ -1461,7 +1663,7 @@ describe("Schema comparison tests for comparing schemas with different names", ( }, }; - it("should not report custom attribute missing when CA class has the same name and is defined in comparable schemas", async ()=> { + it("should not report custom attribute missing when CA class has the same name and is defined in comparable schemas", async () => { const schemaA = await Schema.fromJson({ ...schemaAJson, items: { @@ -1496,10 +1698,14 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(reporter.changes[0].allDiagnostics.find((d) => d.code === SchemaCompareCodes.CustomAttributeInstanceClassMissing && d.messageArgs!.at(0).className === "SchemaA.testCA")).to.be.undefined; + expect( + reporter.changes[0].allDiagnostics.find((d) => + d.code === SchemaCompareCodes.CustomAttributeInstanceClassMissing && d.messageArgs!.at(0).className === "SchemaA.testCA" + ), + ).to.be.undefined; }); - it("should report custom attribute missing for CA with the same name but defined in a referenced schema", async ()=> { + it("should report custom attribute missing for CA with the same name but defined in a referenced schema", async () => { await Schema.fromJson({ ...dummyRefOneJson, items: { @@ -1560,13 +1766,17 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(reporter.changes[0].allDiagnostics.find((d) => d.code === SchemaCompareCodes.CustomAttributeInstanceClassMissing && d.messageArgs!.at(0).className === "DummyReferenceOne.testCA")).to.be.not.undefined; + expect( + reporter.changes[0].allDiagnostics.find((d) => + d.code === SchemaCompareCodes.CustomAttributeInstanceClassMissing && d.messageArgs!.at(0).className === "DummyReferenceOne.testCA" + ), + ).to.be.not.undefined; }); }); /** - * Linear draft schema examples - */ + * Linear draft schema examples + */ describe("Struct Class comparisons", () => { it("should not report property delta for typeName of the property with same name and is defined in schemas being compared", async () => { const schemaA = await Schema.fromJson({ @@ -1613,7 +1823,8 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "SchemaA.inSpanAddress", "SchemaB.inSpanAddress", "structClass")).to.be.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "SchemaA.inSpanAddress", "SchemaB.inSpanAddress", "structClass")).to.be + .undefined; }); it("should report property delta for typeName of the property with different name", async () => { @@ -1661,7 +1872,8 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "SchemaA.inSpanAddressA", "SchemaB.inSpanAddressB", "structClass")).to.be.not.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "SchemaA.inSpanAddressA", "SchemaB.inSpanAddressB", "structClass")).to.be + .not.undefined; }); it("should report property delta for typeName of the property with the same name but defined in a referenced schema", async () => { @@ -1722,7 +1934,8 @@ describe("Schema comparison tests for comparing schemas with different names", ( const comparer = new SchemaComparer(reporter); await comparer.compareSchemas(schemaA, schemaB); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "DummyReferenceOne.inSpanAddress", "SchemaB.inSpanAddress", "structClass")).to.be.not.undefined; + expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-106", "DummyReferenceOne.inSpanAddress", "SchemaB.inSpanAddress", "structClass")) + .to.be.not.undefined; }); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparisonCustomAttributes.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparisonCustomAttributes.test.ts index e79f5989a037..3a2cf20c8bf4 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparisonCustomAttributes.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparisonCustomAttributes.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; import { expect } from "chai"; +import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; class TestSchemaCompareReporter implements ISchemaCompareReporter { public changes: SchemaChanges[] = []; @@ -18,8 +18,10 @@ function findDiagnostic(diagnostics: AnyDiagnostic[], code: string, fullNameA?: diagnostics.find((anyDiagnostic) => { switch (code) { case SchemaCompareCodes.CustomAttributeInstanceClassMissing: { - if (anyDiagnostic.code === code && - anyDiagnostic.messageArgs?.at(0).className === fullNameA) { + if ( + anyDiagnostic.code === code && + anyDiagnostic.messageArgs?.at(0).className === fullNameA + ) { found = true; } break; @@ -185,7 +187,7 @@ describe("Custom attributes class comparison tests", () => { expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-114", "DummyReference.customAttributeOne")).to.equal(true); }); - it("should not report custom attribute instance class missing for top level referenced custom attribute if same full name", async ()=> { + it("should not report custom attribute instance class missing for top level referenced custom attribute if same full name", async () => { const context = new SchemaContext(); const _dummyRefOne = await Schema.fromJson({ ...dummyRefJson, @@ -304,6 +306,5 @@ describe("Custom attributes class comparison tests", () => { expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-114", "DummyReference.customAttributeOne")).to.equal(false); }); - }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparisonMixin.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparisonMixin.test.ts index 23cfd226a715..a6fd0038fb80 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparisonMixin.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparisonMixin.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; import { expect } from "chai"; +import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; class TestSchemaCompareReporter implements ISchemaCompareReporter { public changes: SchemaChanges[] = []; @@ -18,17 +18,21 @@ function findDiagnostic(diagnostics: AnyDiagnostic[], code: string, fullNameA?: diagnostics.find((anyDiagnostic) => { switch (code) { case SchemaCompareCodes.MixinDelta: { - if (anyDiagnostic.code === code && + if ( + anyDiagnostic.code === code && anyDiagnostic.messageArgs?.at(0) === propertyType && anyDiagnostic.messageArgs?.at(1) === fullNameA && - anyDiagnostic.messageArgs?.at(2) === fullNameB) { + anyDiagnostic.messageArgs?.at(2) === fullNameB + ) { found = true; } break; } case SchemaCompareCodes.EntityMixinMissing: { - if (anyDiagnostic.code === code && - anyDiagnostic.messageArgs?.at(0).fullName === fullNameA) { + if ( + anyDiagnostic.code === code && + anyDiagnostic.messageArgs?.at(0).fullName === fullNameA + ) { found = true; } break; @@ -238,7 +242,6 @@ describe("Mixin comparison tests", () => { expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-108", "SchemaA.mixinA")).to.equal(false); expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-108", "SchemaA.mixinB")).to.equal(false); - }); it("should report missing mixin", async () => { @@ -293,7 +296,6 @@ describe("Mixin comparison tests", () => { expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-108", "SchemaA.mixinC")).to.equal(true); expect(findDiagnostic(reporter.changes[1].allDiagnostics, "SC-108", "SchemaB.mixinD")).to.equal(true); - }); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparisonRelationshipClass.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparisonRelationshipClass.test.ts index a034e175f96c..ecbf2a6cd3a5 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparisonRelationshipClass.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparisonRelationshipClass.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Schema, SchemaContext } from "@itwin/ecschema-metadata"; -import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; import { expect } from "chai"; +import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; class TestSchemaCompareReporter implements ISchemaCompareReporter { public changes: SchemaChanges[] = []; @@ -18,17 +18,21 @@ function findDiagnostic(diagnostics: AnyDiagnostic[], code: string, fullNameA?: diagnostics.find((anyDiagnostic) => { switch (code) { case SchemaCompareCodes.RelationshipConstraintClassMissing: { - if (anyDiagnostic.code === code && - anyDiagnostic.messageArgs?.at(0).fullName === fullNameA) { + if ( + anyDiagnostic.code === code && + anyDiagnostic.messageArgs?.at(0).fullName === fullNameA + ) { found = true; } break; } case SchemaCompareCodes.RelationshipConstraintDelta: { - if (anyDiagnostic.code === code && - anyDiagnostic.messageArgs?.at(0) === propertyType && - anyDiagnostic.messageArgs?.at(1) === fullNameA && - anyDiagnostic.messageArgs?.at(2) === fullNameB) { + if ( + anyDiagnostic.code === code && + anyDiagnostic.messageArgs?.at(0) === propertyType && + anyDiagnostic.messageArgs?.at(1) === fullNameA && + anyDiagnostic.messageArgs?.at(2) === fullNameB + ) { found = true; } break; @@ -157,8 +161,8 @@ describe("Custom attributes class comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-112", "SchemaA.testClassOne")).to.equal(false); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-111", "SchemaA.testClassOne", "SchemaB.testClassOne", "abstractConstraint")).to.equal(false); - + expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-111", "SchemaA.testClassOne", "SchemaB.testClassOne", "abstractConstraint")).to + .equal(false); }); it("should not report relationship constraint missing or abstractConstraint delta", async () => { @@ -258,8 +262,8 @@ describe("Custom attributes class comparison tests", () => { await comparer.compareSchemas(schemaA, schemaB); expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-112", "SchemaA.testClassOne")).to.equal(false); - expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-111", "SchemaA.testClassOne", "SchemaB.testClassOne", "abstractConstraint")).to.equal(false); - + expect(findDiagnostic(reporter.changes[0].allDiagnostics, "SC-111", "SchemaA.testClassOne", "SchemaB.testClassOne", "abstractConstraint")).to + .equal(false); }); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaComparisonSameNameVersion.test.ts b/core/ecschema-editing/src/test/Validation/SchemaComparisonSameNameVersion.test.ts index a254602b2b94..dbfdde9e467c 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaComparisonSameNameVersion.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaComparisonSameNameVersion.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Property, Schema, SchemaContext, SchemaItem } from "@itwin/ecschema-metadata"; -import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; import { expect } from "chai"; +import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaCompareCodes, SchemaComparer } from "../../ecschema-editing"; class SchemaCompareReporter implements ISchemaCompareReporter { public changes: SchemaChanges[] = []; @@ -16,26 +16,34 @@ class SchemaCompareReporter implements ISchemaCompareReporter { function findDiagnostic(diagnostics: AnyDiagnostic[], code: string, fullNameA: string) { let found = false; for (const diagnostic of diagnostics) { - if (SchemaCompareCodes.SchemaItemMissing === code && - (diagnostic.ecDefinition as SchemaItem).fullName === fullNameA) { + if ( + SchemaCompareCodes.SchemaItemMissing === code && + (diagnostic.ecDefinition as SchemaItem).fullName === fullNameA + ) { found = true; break; } - if (SchemaCompareCodes.CustomAttributeInstanceClassMissing === code && - diagnostic.messageArgs?.at(0).className === fullNameA) { + if ( + SchemaCompareCodes.CustomAttributeInstanceClassMissing === code && + diagnostic.messageArgs?.at(0).className === fullNameA + ) { found = true; break; } - if (SchemaCompareCodes.SchemaReferenceMissing === code && - diagnostic.messageArgs?.at(0).fullName === fullNameA) { + if ( + SchemaCompareCodes.SchemaReferenceMissing === code && + diagnostic.messageArgs?.at(0).fullName === fullNameA + ) { found = true; break; } - if (SchemaCompareCodes.PropertyMissing === code && - (diagnostic.ecDefinition as Property).fullName === fullNameA) { + if ( + SchemaCompareCodes.PropertyMissing === code && + (diagnostic.ecDefinition as Property).fullName === fullNameA + ) { found = true; break; } @@ -150,7 +158,6 @@ describe("Comparison tests for schemas with same name and version", () => { expect(findTestClassTwoMissing).to.be.false; expect(findTestClassThreeMissing).to.be.false; - }); it("should return true to finding schemaItemMissing diagnostic from schemaB in schemaBChanges", async () => { @@ -195,7 +202,6 @@ describe("Comparison tests for schemas with same name and version", () => { label: "test class one ref one", }, }, - }, contextA); await Schema.fromJson({ @@ -319,7 +325,6 @@ describe("Comparison tests for schemas with same name and version", () => { expect(findDiagnostic(schemaAChanges, SchemaCompareCodes.PropertyMissing, "testClassOne.PropertyTwo")).to.be.false; expect(findDiagnostic(schemaBChanges, SchemaCompareCodes.PropertyMissing, "testClassOne.PropertyTwo")).to.be.true; - }); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaValidater.test.ts b/core/ecschema-editing/src/test/Validation/SchemaValidater.test.ts index 9ca839ab7281..551041ca0ab2 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaValidater.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaValidater.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { DelayedPromiseWithProps, ECClassModifier, EntityClass, Schema, SchemaContext } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { MutableSchema } from "../../Editing/Mutable/MutableSchema"; import { SchemaValidater } from "../../Validation/SchemaValidater"; import { TestRuleSet } from "../TestUtils/DiagnosticHelpers"; @@ -24,7 +24,7 @@ describe("SchemaValidater tests", () => { const result = await SchemaValidater.validateSchema(schema); - expect((result).length).to.equal(1); + expect(result.length).to.equal(1); expect(result[0].code).to.equal("ECObjects-100"); }); @@ -37,7 +37,7 @@ describe("SchemaValidater tests", () => { const result = await SchemaValidater.validateSchema(schema, ruleSet); - expect((result).length).to.equal(7); + expect(result.length).to.equal(7); expect(result[3].code).to.equal("ECObjects-100"); }); }); diff --git a/core/ecschema-editing/src/test/Validation/SchemaValidationVisitor.test.ts b/core/ecschema-editing/src/test/Validation/SchemaValidationVisitor.test.ts index 3ef7c9de924e..9825c4133d99 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaValidationVisitor.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaValidationVisitor.test.ts @@ -3,16 +3,43 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { AnyProperty, Constant, CustomAttributeClass, ECClass, EntityClass, Enumeration, Format, - InvertedUnit, KindOfQuantity, Mixin, Phenomenon, PrimitiveType, PropertyCategory, RelationshipClass, - RelationshipConstraint, RelationshipEnd, Schema, SchemaContext, StructClass, Unit, UnitSystem, +import { + AnyProperty, + Constant, + CustomAttributeClass, + ECClass, + EntityClass, + Enumeration, + Format, + InvertedUnit, + KindOfQuantity, + Mixin, + Phenomenon, + PrimitiveType, + PropertyCategory, + RelationshipClass, + RelationshipConstraint, + RelationshipEnd, + Schema, + SchemaContext, + StructClass, + Unit, + UnitSystem, } from "@itwin/ecschema-metadata"; -import { MutableClass } from "../../Editing/Mutable/MutableClass"; import { MutableProperty } from "@itwin/ecschema-metadata/src/Metadata/Property"; +import { expect } from "chai"; +import { MutableClass } from "../../Editing/Mutable/MutableClass"; import { DiagnosticCategory } from "../../Validation/Diagnostic"; import { SchemaValidationVisitor } from "../../Validation/SchemaValidationVisitor"; -import { ApplySuppressionSet, EmptyRuleSet, IgnoreSuppressionSet, TestDiagnostics, TestReporter, TestRuleSet, TestRuleSetB } from "../TestUtils/DiagnosticHelpers"; +import { + ApplySuppressionSet, + EmptyRuleSet, + IgnoreSuppressionSet, + TestDiagnostics, + TestReporter, + TestRuleSet, + TestRuleSetB, +} from "../TestUtils/DiagnosticHelpers"; import sinon = require("sinon"); @@ -916,7 +943,9 @@ describe("SchemaValidationVisitor tests", () => { await visitor.visitCustomAttributeContainer(entityClass); ruleSet.customAttributeContainerRules.forEach((spy) => expect(spy.calledOnceWithExactly(entityClass)).to.be.true); - ruleSet.customAttributeInstanceRules.forEach((spy) => expect(spy.calledOnceWithExactly(entityClass, entityClass.customAttributes!.get("TestSchema.TestCA")!)).to.be.true); + ruleSet.customAttributeInstanceRules.forEach((spy) => + expect(spy.calledOnceWithExactly(entityClass, entityClass.customAttributes!.get("TestSchema.TestCA")!)).to.be.true + ); }); it("No rules, visit does not fail", async () => { @@ -938,7 +967,9 @@ describe("SchemaValidationVisitor tests", () => { await visitor.visitCustomAttributeContainer(properties[0] as AnyProperty); ruleSet.customAttributeContainerRules.forEach((spy) => expect(spy.calledOnceWithExactly(properties[0])).to.be.true); - ruleSet.customAttributeInstanceRules.forEach((spy) => expect(spy.calledOnceWithExactly(properties[0], property.customAttributes!.get("TestSchema.TestCA")!)).to.be.true); + ruleSet.customAttributeInstanceRules.forEach((spy) => + expect(spy.calledOnceWithExactly(properties[0], property.customAttributes!.get("TestSchema.TestCA")!)).to.be.true + ); }); it("Property, exclude TestSchema, does not call CustomAttributeContainer rules", async () => { @@ -964,7 +995,9 @@ describe("SchemaValidationVisitor tests", () => { await visitor.visitCustomAttributeContainer(relationshipClass); ruleSet.customAttributeContainerRules.forEach((spy) => expect(spy.calledOnceWithExactly(relationshipClass)).to.be.true); - ruleSet.customAttributeInstanceRules.forEach((spy) => expect(spy.calledOnceWithExactly(relationshipClass, relationshipClass.customAttributes!.get("TestSchema.TestCA")!)).to.be.true); + ruleSet.customAttributeInstanceRules.forEach((spy) => + expect(spy.calledOnceWithExactly(relationshipClass, relationshipClass.customAttributes!.get("TestSchema.TestCA")!)).to.be.true + ); }); it("RelationshipClass, exclude TestSchema, does not call CustomAttributeContainer rules", async () => { @@ -989,7 +1022,9 @@ describe("SchemaValidationVisitor tests", () => { await visitor.visitCustomAttributeContainer(constraint); ruleSet.customAttributeContainerRules.forEach((spy) => expect(spy.calledOnceWithExactly(constraint)).to.be.true); - ruleSet.customAttributeInstanceRules.forEach((spy) => expect(spy.calledOnceWithExactly(constraint, constraint.customAttributes!.get("TestSchema.TestCA")!)).to.be.true); + ruleSet.customAttributeInstanceRules.forEach((spy) => + expect(spy.calledOnceWithExactly(constraint, constraint.customAttributes!.get("TestSchema.TestCA")!)).to.be.true + ); }); it("RelationshipConstraint, exclude TestSchema, does not call CustomAttributeContainer rules", async () => { diff --git a/core/ecschema-editing/src/test/Validation/SchemaWalker.test.ts b/core/ecschema-editing/src/test/Validation/SchemaWalker.test.ts index 03ee49287580..b5825c46e24b 100644 --- a/core/ecschema-editing/src/test/Validation/SchemaWalker.test.ts +++ b/core/ecschema-editing/src/test/Validation/SchemaWalker.test.ts @@ -5,9 +5,9 @@ /* eslint-disable @typescript-eslint/naming-convention */ +import { ECClass, ISchemaPartVisitor, RelationshipClass, Schema, SchemaContext, SchemaWalker } from "@itwin/ecschema-metadata"; import { expect } from "chai"; import * as sinon from "sinon"; -import { ECClass, ISchemaPartVisitor, RelationshipClass, Schema, SchemaContext, SchemaWalker } from "@itwin/ecschema-metadata"; describe("SchemaWalker tests", () => { let testSchema: Schema; @@ -128,7 +128,7 @@ describe("SchemaWalker tests", () => { }, }; - type Mock = { readonly [P in keyof T]: sinon.SinonSpy; }; + type Mock = { readonly [P in keyof T]: sinon.SinonSpy }; let mockVisitor: Mock; beforeEach(async () => { diff --git a/core/ecschema-editing/tsconfig.json b/core/ecschema-editing/tsconfig.json index f4993dee2ed7..7555dcce6b22 100644 --- a/core/ecschema-editing/tsconfig.json +++ b/core/ecschema-editing/tsconfig.json @@ -3,4 +3,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/core/ecschema-locaters/eslint.config.js b/core/ecschema-locaters/eslint.config.js index 5af49c6a06fe..b41eeafae82e 100644 --- a/core/ecschema-locaters/eslint.config.js +++ b/core/ecschema-locaters/eslint.config.js @@ -8,7 +8,7 @@ module.exports = [ { files: ["**/*.ts"], rules: { - "radix": "warn" - } - } -]; \ No newline at end of file + "radix": "warn", + }, + }, +]; diff --git a/core/ecschema-locaters/src/SchemaFileLocater.ts b/core/ecschema-locaters/src/SchemaFileLocater.ts index b468da0aa0b3..65ddb66f9706 100644 --- a/core/ecschema-locaters/src/SchemaFileLocater.ts +++ b/core/ecschema-locaters/src/SchemaFileLocater.ts @@ -6,10 +6,10 @@ * @module Locaters */ +import { Schema, SchemaContext, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; import * as fs from "fs"; import { globSync } from "glob"; import * as path from "path"; -import { Schema, SchemaContext, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; const formatString = (format: string, ...args: string[]) => { return format.replace(/{(\d+)}/g, (match, theNumber) => { @@ -21,7 +21,7 @@ const formatString = (format: string, ...args: string[]) => { const padStartEx = (str: string, targetLength: number, padString: string) => { targetLength = targetLength >> 0; // truncate if number or convert non-number to 0; - padString = String((typeof padString !== "undefined" ? padString : " ")); + padString = String(typeof padString !== "undefined" ? padString : " "); if (str.length > targetLength) { return String(str); } else { @@ -132,7 +132,14 @@ export abstract class SchemaFileLocater { * @param matchType The SchemaMatchType to use when comparing the desiredKey and the keys found during the search. * @param format The type of file that the schema key refers to. json or xml */ - private addCandidateNoExtSchemaKey(foundFiles: FileSchemaKey[], schemaPath: string, schemaName: string, desiredKey: Readonly, matchType: SchemaMatchType, format: string) { + private addCandidateNoExtSchemaKey( + foundFiles: FileSchemaKey[], + schemaPath: string, + schemaName: string, + desiredKey: Readonly, + matchType: SchemaMatchType, + format: string, + ) { const fullPath = path.join(schemaPath, `${schemaName}.ecschema.${format}`); // If the file does not exist, end @@ -161,12 +168,19 @@ export abstract class SchemaFileLocater { * @param matchType The SchemaMatchType to use when comparing the desired Key and the keys found during the search. * @param format The type of file that the schema key refers to. json or xml */ - private addCandidateSchemaKeys(foundFiles: FileSchemaKey[], schemaPath: string, fileFilter: string, desiredKey: Readonly, matchType: SchemaMatchType, format: string) { + private addCandidateSchemaKeys( + foundFiles: FileSchemaKey[], + schemaPath: string, + fileFilter: string, + desiredKey: Readonly, + matchType: SchemaMatchType, + format: string, + ) { const fullPath = path.join(schemaPath, fileFilter); const result = globSync(fullPath, { windowsPathsNoEscape: true }); for (const match of result) { - let fileName = path.basename(match, (`.ecschema.${format}`)); + let fileName = path.basename(match, `.ecschema.${format}`); // TODO: should this be moved or handled elsewhere? // Handles two version file names - SchemaKey.parseString supports only 3 version names. if (/[^\d]\.\d?\d\.\d?\d$/.test(fileName)) { @@ -202,8 +216,8 @@ export abstract class SchemaFileLocater { const minorVersion = desiredKey.minorVersion.toString(); if (matchType === SchemaMatchType.Latest) { - twoVersionSuffix = (`.*.*.ecschema.${format}`); - threeVersionSuffix = (`.*.*.*.ecschema.${format}`); + twoVersionSuffix = `.*.*.ecschema.${format}`; + threeVersionSuffix = `.*.*.*.ecschema.${format}`; } else if (matchType === SchemaMatchType.LatestWriteCompatible) { twoVersionSuffix = formatString(`.{0}.*.ecschema.${format}`, padStartEx(readVersion, 2, "0")); threeVersionSuffix = formatString(`.{0}.{1}.*.ecschema.${format}`, padStartEx(readVersion, 2, "0"), padStartEx(writeVersion, 2, "0")); @@ -212,7 +226,12 @@ export abstract class SchemaFileLocater { threeVersionSuffix = formatString(`.{0}.*.*.ecschema.${format}`, padStartEx(readVersion, 2, "0")); } else { twoVersionSuffix = formatString(`.{0}.{1}.ecschema.${format}`, padStartEx(readVersion, 2, "0"), padStartEx(writeVersion, 2, "0")); - threeVersionSuffix = formatString(`.{0}.{1}.{2}.ecschema.${format}`, padStartEx(readVersion, 2, "0"), padStartEx(writeVersion, 2, "0"), padStartEx(minorVersion, 2, "0")); + threeVersionSuffix = formatString( + `.{0}.{1}.{2}.ecschema.${format}`, + padStartEx(readVersion, 2, "0"), + padStartEx(writeVersion, 2, "0"), + padStartEx(minorVersion, 2, "0"), + ); } const twoVersionExpression = desiredKey.name + twoVersionSuffix; diff --git a/core/ecschema-locaters/src/SchemaJsonFileLocater.ts b/core/ecschema-locaters/src/SchemaJsonFileLocater.ts index 5a695dc0a070..b5108528c9fc 100644 --- a/core/ecschema-locaters/src/SchemaJsonFileLocater.ts +++ b/core/ecschema-locaters/src/SchemaJsonFileLocater.ts @@ -6,11 +6,19 @@ * @module Locaters */ -import * as fs from "fs"; -import * as path from "path"; import { - ECObjectsError, ECObjectsStatus, ECVersion, ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, + ECObjectsError, + ECObjectsStatus, + ECVersion, + ISchemaLocater, + Schema, + SchemaContext, + SchemaInfo, + SchemaKey, + SchemaMatchType, } from "@itwin/ecschema-metadata"; +import * as fs from "fs"; +import * as path from "path"; import { FileSchemaKey, SchemaFileLocater } from "./SchemaFileLocater"; /** @@ -19,7 +27,6 @@ import { FileSchemaKey, SchemaFileLocater } from "./SchemaFileLocater"; * @beta */ export class SchemaJsonFileLocater extends SchemaFileLocater implements ISchemaLocater { - /** * Constructs a SchemaKey based on the information in the Schema JSON * @param data The Schema JSON as a string @@ -58,12 +65,12 @@ export class SchemaJsonFileLocater extends SchemaFileLocater implements ISchemaL } /** - * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. - * The fully loaded schema can be gotten later from the context using the getCachedSchema method. - * @param schemaKey The SchemaKey describing the schema to get from the cache. - * @param matchType The match type to use when locating the schema - * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ + * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. + * The fully loaded schema can be gotten later from the context using the getCachedSchema method. + * @param schemaKey The SchemaKey describing the schema to get from the cache. + * @param matchType The match type to use when locating the schema + * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. + */ public async getSchemaInfo(schemaKey: SchemaKey, matchType: SchemaMatchType, context: SchemaContext): Promise { // Grab all schema files that match the schema key const candidates: FileSchemaKey[] = this.findEligibleSchemaKeys(schemaKey, matchType, "json"); diff --git a/core/ecschema-locaters/src/SchemaXml.ts b/core/ecschema-locaters/src/SchemaXml.ts index ec338c66ee91..5648895fec59 100644 --- a/core/ecschema-locaters/src/SchemaXml.ts +++ b/core/ecschema-locaters/src/SchemaXml.ts @@ -6,17 +6,16 @@ * @module Utils */ +import { Schema } from "@itwin/ecschema-metadata"; +import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; import * as fs from "fs-extra"; import * as path from "path"; -import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; -import { Schema } from "@itwin/ecschema-metadata"; /** * Utility class to assist in creating serialized EC Schemas on the file system. * @beta */ export namespace SchemaXml { - /** * Writes a Schema to an xml file to the specified output path. * @param schema The Schema to serialize. diff --git a/core/ecschema-locaters/src/SchemaXmlFileLocater.ts b/core/ecschema-locaters/src/SchemaXmlFileLocater.ts index 1827a09a74c3..e45d9f4ea00b 100644 --- a/core/ecschema-locaters/src/SchemaXmlFileLocater.ts +++ b/core/ecschema-locaters/src/SchemaXmlFileLocater.ts @@ -6,11 +6,21 @@ * @module Locaters */ -import * as path from "path"; -import { DOMParser } from "@xmldom/xmldom"; import { - ECObjectsError, ECObjectsStatus, ECVersion, ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, SchemaReadHelper, XmlParser, + ECObjectsError, + ECObjectsStatus, + ECVersion, + ISchemaLocater, + Schema, + SchemaContext, + SchemaInfo, + SchemaKey, + SchemaMatchType, + SchemaReadHelper, + XmlParser, } from "@itwin/ecschema-metadata"; +import { DOMParser } from "@xmldom/xmldom"; +import * as path from "path"; import { FileSchemaKey, SchemaFileLocater } from "./SchemaFileLocater"; /** @@ -34,12 +44,12 @@ export class SchemaXmlFileLocater extends SchemaFileLocater implements ISchemaLo } /** - * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. - * The fully loaded schema can be gotten later from the context using the getCachedSchema method. - * @param schemaKey The SchemaKey describing the schema to get from the cache. - * @param matchType The match type to use when locating the schema - * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ + * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. + * The fully loaded schema can be gotten later from the context using the getCachedSchema method. + * @param schemaKey The SchemaKey describing the schema to get from the cache. + * @param matchType The match type to use when locating the schema + * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. + */ public async getSchemaInfo(schemaKey: SchemaKey, matchType: SchemaMatchType, context: SchemaContext): Promise { const candidates: FileSchemaKey[] = this.findEligibleSchemaKeys(schemaKey, matchType, "xml"); diff --git a/core/ecschema-locaters/src/SchemaXmlStringLocater.ts b/core/ecschema-locaters/src/SchemaXmlStringLocater.ts index e19d26c24990..7ea17d216a57 100644 --- a/core/ecschema-locaters/src/SchemaXmlStringLocater.ts +++ b/core/ecschema-locaters/src/SchemaXmlStringLocater.ts @@ -6,10 +6,20 @@ * @module Locaters */ -import { DOMParser } from "@xmldom/xmldom"; import { - ECObjectsError, ECObjectsStatus, ECVersion, ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, SchemaReadHelper, XmlParser, + ECObjectsError, + ECObjectsStatus, + ECVersion, + ISchemaLocater, + Schema, + SchemaContext, + SchemaInfo, + SchemaKey, + SchemaMatchType, + SchemaReadHelper, + XmlParser, } from "@itwin/ecschema-metadata"; +import { DOMParser } from "@xmldom/xmldom"; import { SchemaStringLocater, StringSchemaKey } from "./SchemaStringLocater"; /** @@ -18,7 +28,6 @@ import { SchemaStringLocater, StringSchemaKey } from "./SchemaStringLocater"; * @beta */ export class SchemaXmlStringLocater extends SchemaStringLocater implements ISchemaLocater { - /** * Constructs a SchemaKey based on the information in the Schema XML. * @param schemaXml The Schema XML as a string. @@ -53,12 +62,12 @@ export class SchemaXmlStringLocater extends SchemaStringLocater implements ISche } /** - * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. - * The fully loaded schema can be gotten later from the context using the getCachedSchema method. - * @param schemaKey The SchemaKey describing the schema to get from the cache. - * @param matchType The match type to use when locating the schema - * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ + * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. + * The fully loaded schema can be gotten later from the context using the getCachedSchema method. + * @param schemaKey The SchemaKey describing the schema to get from the cache. + * @param matchType The match type to use when locating the schema + * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. + */ public async getSchemaInfo(schemaKey: SchemaKey, matchType: SchemaMatchType, context: SchemaContext): Promise { // Grab all schema strings that match the schema key const candidates: StringSchemaKey[] = this.findEligibleSchemaKeys(schemaKey, matchType); @@ -121,5 +130,4 @@ export class SchemaXmlStringLocater extends SchemaStringLocater implements ISche return new ECVersion(+read, 0, +minor); } - } diff --git a/core/ecschema-locaters/src/StubSchemaXmlFileLocater.ts b/core/ecschema-locaters/src/StubSchemaXmlFileLocater.ts index a58a67c8cfca..9f82d569bd0d 100644 --- a/core/ecschema-locaters/src/StubSchemaXmlFileLocater.ts +++ b/core/ecschema-locaters/src/StubSchemaXmlFileLocater.ts @@ -6,10 +6,18 @@ * @module Locaters */ -import * as path from "path"; import { - ECObjectsError, ECObjectsStatus, ECVersion, ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, + ECObjectsError, + ECObjectsStatus, + ECVersion, + ISchemaLocater, + Schema, + SchemaContext, + SchemaInfo, + SchemaKey, + SchemaMatchType, } from "@itwin/ecschema-metadata"; +import * as path from "path"; import { FileSchemaKey, SchemaFileLocater } from "./SchemaFileLocater"; function isECv2Schema(schemaText: string): boolean { @@ -59,12 +67,12 @@ export class StubSchemaXmlFileLocater extends SchemaFileLocater implements ISche } /** - * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. - * The fully loaded schema can be gotten later from the context using the getCachedSchema method. - * @param schemaKey The SchemaKey describing the schema to get from the cache. - * @param matchType The match type to use when locating the schema - * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ + * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. + * The fully loaded schema can be gotten later from the context using the getCachedSchema method. + * @param schemaKey The SchemaKey describing the schema to get from the cache. + * @param matchType The match type to use when locating the schema + * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. + */ public async getSchemaInfo(key: SchemaKey, matchType: SchemaMatchType, context: SchemaContext): Promise { return this.getSchemaSync(key, matchType, context) as SchemaInfo; } @@ -137,7 +145,10 @@ export class StubSchemaXmlFileLocater extends SchemaFileLocater implements ISche for (const key of refKeys) { const refSchema = context ? context.getSchemaSync(key, refMatchType) : undefined; if (!refSchema) - throw new ECObjectsError(ECObjectsStatus.UnableToLocateSchema, `Unable to locate referenced schema: ${key.name}.${key.readVersion}.${key.writeVersion}.${key.minorVersion}`); + throw new ECObjectsError( + ECObjectsStatus.UnableToLocateSchema, + `Unable to locate referenced schema: ${key.name}.${key.readVersion}.${key.writeVersion}.${key.minorVersion}`, + ); schema.references.push(refSchema); } @@ -151,7 +162,10 @@ export class StubSchemaXmlFileLocater extends SchemaFileLocater implements ISche const file = xmlSchemaKey.schemaText; if (!file) - throw new ECObjectsError(ECObjectsStatus.UnableToLocateSchema, `Could not locate the schema file, ${xmlSchemaKey.fileName}, for the schema ${xmlSchemaKey.name}`); + throw new ECObjectsError( + ECObjectsStatus.UnableToLocateSchema, + `Could not locate the schema file, ${xmlSchemaKey.fileName}, for the schema ${xmlSchemaKey.name}`, + ); const data = file.toString().replace(/(\s*) RefSchemaB, RefSchemaB --> TestSchema`); + await expect(Schema.fromJson(json, context)).to.be.rejectedWith( + ECObjectsError, + `Schema 'RefSchemaB' has reference cycles: TestSchema --> RefSchemaB, RefSchemaB --> TestSchema`, + ); const context2 = new SchemaContext(); const schemaCJson = { @@ -273,7 +299,10 @@ describe("Full Schema Deserialization", () => { ], }; - const locater2 = new ReferenceSchemaLocater((jsonObj, _context) => Schema.fromJsonSync(jsonObj, _context), async (jsonObj, _context) => Schema.fromJson(jsonObj, _context)); + const locater2 = new ReferenceSchemaLocater( + (jsonObj, _context) => Schema.fromJsonSync(jsonObj, _context), + async (jsonObj, _context) => Schema.fromJson(jsonObj, _context), + ); locater2.addSchema("RefSchemaC", schemaCJson); locater2.addSchema("RefSchemaD", schemaDJson); locater2.addSchema("RefSchemaE", schemaEJson); @@ -287,7 +316,10 @@ describe("Full Schema Deserialization", () => { { name: "RefSchemaC", version: "1.0.0" }, ], }; - await expect(Schema.fromJson(json, context2)).to.be.rejectedWith(ECObjectsError, `Schema 'RefSchemaF' has reference cycles: RefSchemaE --> RefSchemaF, RefSchemaC --> RefSchemaE, RefSchemaF --> RefSchemaC`); + await expect(Schema.fromJson(json, context2)).to.be.rejectedWith( + ECObjectsError, + `Schema 'RefSchemaF' has reference cycles: RefSchemaE --> RefSchemaF, RefSchemaC --> RefSchemaE, RefSchemaF --> RefSchemaC`, + ); }); it("should not throw cyclic references", async () => { @@ -341,7 +373,10 @@ describe("Full Schema Deserialization", () => { alias: "d", }; - const locater = new ReferenceSchemaLocater((jsonObj, _context) => Schema.fromJsonSync(jsonObj, _context), async (jsonObj, _context) => Schema.fromJson(jsonObj, _context)); + const locater = new ReferenceSchemaLocater( + (jsonObj, _context) => Schema.fromJsonSync(jsonObj, _context), + async (jsonObj, _context) => Schema.fromJson(jsonObj, _context), + ); locater.addSchema("RefSchemaA", schemaAJson); locater.addSchema("RefSchemaB", schemaBJson); locater.addSchema("RefSchemaC", schemaCJson); @@ -386,7 +421,10 @@ describe("Full Schema Deserialization", () => { `; - await expect(deserializeXml(testSchemaXML, context)).to.be.rejectedWith(ECObjectsError, `Schema 'TestSchema' has reference cycles: RefSchemaB --> TestSchema, TestSchema --> RefSchemaB`); + await expect(deserializeXml(testSchemaXML, context)).to.be.rejectedWith( + ECObjectsError, + `Schema 'TestSchema' has reference cycles: RefSchemaB --> TestSchema, TestSchema --> RefSchemaB`, + ); const context2 = new SchemaContext(); @@ -427,7 +465,10 @@ describe("Full Schema Deserialization", () => { `; - await expect(deserializeXml(testSchemaXML, context2)).to.be.rejectedWith(ECObjectsError, `Schema 'TestSchema' has reference cycles: RefSchemaF --> RefSchemaC, RefSchemaE --> RefSchemaF, RefSchemaC --> RefSchemaE, TestSchema --> RefSchemaC`); + await expect(deserializeXml(testSchemaXML, context2)).to.be.rejectedWith( + ECObjectsError, + `Schema 'TestSchema' has reference cycles: RefSchemaF --> RefSchemaC, RefSchemaE --> RefSchemaF, RefSchemaC --> RefSchemaE, TestSchema --> RefSchemaC`, + ); }); it("should not throw cyclic references in XML", async () => { @@ -484,15 +525,24 @@ describe("Full Schema Deserialization", () => { it("should throw for invalid items attribute", async () => { let json: any = { ...baseJson, items: 0 }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The schema TestSchema has an invalid 'items' attribute. It should be of type 'object'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The schema TestSchema has an invalid 'items' attribute. It should be of type 'object'.`, + ); json = { ...baseJson, items: [{}] }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The schema TestSchema has an invalid 'items' attribute. It should be of type 'object'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The schema TestSchema has an invalid 'items' attribute. It should be of type 'object'.`, + ); }); it("should throw for item with invalid name", async () => { const json = { ...baseJson, items: { "": {} } }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `A SchemaItem in TestSchema has an invalid 'name' attribute. '' is not a valid ECName.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `A SchemaItem in TestSchema has an invalid 'name' attribute. '' is not a valid ECName.`, + ); }); it("should throw for item with missing schemaItemType", async () => { @@ -500,7 +550,10 @@ describe("Full Schema Deserialization", () => { ...baseJson, items: { BadItem: {} }, }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The SchemaItem TestSchema.BadItem is missing the required 'schemaItemType' attribute.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The SchemaItem TestSchema.BadItem is missing the required 'schemaItemType' attribute.`, + ); }); it("should throw for item with invalid schemaItemType", async () => { @@ -508,7 +561,10 @@ describe("Full Schema Deserialization", () => { ...baseJson, items: { BadItem: { schemaItemType: 0 } }, }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The SchemaItem TestSchema.BadItem has an invalid 'schemaItemType' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The SchemaItem TestSchema.BadItem has an invalid 'schemaItemType' attribute. It should be of type 'string'.`, + ); }); it("invalid property type in child class json, reports error correctly", async () => { @@ -534,7 +590,10 @@ describe("Full Schema Deserialization", () => { const context = new SchemaContext(); const reader = new SchemaReadHelper(JsonParser, context); - await expect(reader.readSchema(new Schema(context), schemaJson)).to.be.rejectedWith(ECObjectsError, "The ECProperty TestSchema.TestEntity.TestProp has an invalid 'type' attribute. 'BadProperty' is not a valid type."); + await expect(reader.readSchema(new Schema(context), schemaJson)).to.be.rejectedWith( + ECObjectsError, + "The ECProperty TestSchema.TestEntity.TestProp has an invalid 'type' attribute. 'BadProperty' is not a valid type.", + ); }); it("invalid property type in class json with mixin, reports error correctly", async () => { @@ -561,9 +620,11 @@ describe("Full Schema Deserialization", () => { const context = new SchemaContext(); const reader = new SchemaReadHelper(JsonParser, context); - await expect(reader.readSchema(new Schema(context), schemaJson)).to.be.rejectedWith(ECObjectsError, "The ECProperty TestSchema.TestEntityClass.TestProp has an invalid 'type' attribute. 'BadProperty' is not a valid type."); + await expect(reader.readSchema(new Schema(context), schemaJson)).to.be.rejectedWith( + ECObjectsError, + "The ECProperty TestSchema.TestEntityClass.TestProp has an invalid 'type' attribute. 'BadProperty' is not a valid type.", + ); }); - }); describe("with visitor", () => { @@ -572,7 +633,7 @@ describe("Full Schema Deserialization", () => { name: "TestSchema", version: "1.2.3", }; - type Mock = { readonly [P in keyof T]: sinon.SinonSpy; }; + type Mock = { readonly [P in keyof T]: sinon.SinonSpy }; let mockVisitor: Mock; beforeEach(() => { @@ -708,12 +769,16 @@ describe("Full Schema Deserialization", () => { expect(testEntity).to.exist; expect(mockVisitor!.visitClass!.firstCall.calledWithExactly(testEntity)).to.be.true; - expect(descriptions[0]).to.equal("Description for AMixin", - `ISchemaPartVisitor.visitClass was called for "BEntityClass" before its base class, "AMixin" was fully deserialized.`); + expect(descriptions[0]).to.equal( + "Description for AMixin", + `ISchemaPartVisitor.visitClass was called for "BEntityClass" before its base class, "AMixin" was fully deserialized.`, + ); expect(mockVisitor!.visitClass!.secondCall.calledWithExactly(testMixin)).to.be.true; - expect(descriptions[1]).to.equal("Description for BEntityClass", - `ISchemaPartVisitor.visitClass was called for "AMixin" before its appliesTo class, "BEntityClass" was fully deserialized.`); + expect(descriptions[1]).to.equal( + "Description for BEntityClass", + `ISchemaPartVisitor.visitClass was called for "AMixin" before its appliesTo class, "BEntityClass" was fully deserialized.`, + ); }); it("should safely handle EntityClass-extends-Mixin-appliesTo-EntityClass cycle", async () => { @@ -759,12 +824,16 @@ describe("Full Schema Deserialization", () => { expect(testMixin).to.exist; expect(mockVisitor!.visitClass!.firstCall.calledWithExactly(testMixin)).to.be.true; - expect(descriptions[0]).to.equal("Description for AEntityClass", - `ISchemaPartVisitor.visitClass was called for "BMixin" before its appliesTo class, "AEntityClass" was fully deserialized.`); + expect(descriptions[0]).to.equal( + "Description for AEntityClass", + `ISchemaPartVisitor.visitClass was called for "BMixin" before its appliesTo class, "AEntityClass" was fully deserialized.`, + ); expect(mockVisitor!.visitClass!.secondCall.calledWithExactly(testEntity)).to.be.true; - expect(descriptions[1]).to.equal("Description for BMixin", - `ISchemaPartVisitor.visitClass was called for "AEntityClass" before its base class, "BMixin" was fully deserialized.`); + expect(descriptions[1]).to.equal( + "Description for BMixin", + `ISchemaPartVisitor.visitClass was called for "AEntityClass" before its base class, "BMixin" was fully deserialized.`, + ); }); it("should safely handle EntityClass-navProp-RelationshipClass-constraint-EntityClass cycle", async () => { @@ -832,12 +901,16 @@ describe("Full Schema Deserialization", () => { expect(testRelationship).to.exist; expect(mockVisitor!.visitClass!.firstCall.calledWithExactly(testRelationship)).to.be.true; - expect(descriptions[0]).to.equal("Description for AEntityClass", - `ISchemaPartVisitor.visitClass was called for "BRelationshipClass" before the entity class its constraints use, "AEntityClass" was fully deserialized.`); + expect(descriptions[0]).to.equal( + "Description for AEntityClass", + `ISchemaPartVisitor.visitClass was called for "BRelationshipClass" before the entity class its constraints use, "AEntityClass" was fully deserialized.`, + ); expect(mockVisitor!.visitClass!.secondCall.calledWithExactly(testEntity)).to.be.true; - expect(descriptions[1]).to.equal("Description for BRelationshipClass", - `ISchemaPartVisitor.visitClass was called for "AEntityClass" before the relationship its NavigationProperty uses, "BRelationshipClass" was fully deserialized.`); + expect(descriptions[1]).to.equal( + "Description for BRelationshipClass", + `ISchemaPartVisitor.visitClass was called for "AEntityClass" before the relationship its NavigationProperty uses, "BRelationshipClass" was fully deserialized.`, + ); }); it("should safely handle RelationshipClass-constraint-EntityClass-navProp-RelationshipClass cycle", async () => { @@ -905,13 +978,16 @@ describe("Full Schema Deserialization", () => { expect(testEntity).to.exist; expect(mockVisitor!.visitClass!.firstCall.calledWithExactly(testEntity)).to.be.true; - expect(descriptions[0]).to.equal("Description for ARelationshipClass", - `ISchemaPartVisitor.visitClass was called for "BEntityClass" before the relationship its NavigationProperty uses, "ARelationshipClass" was fully deserialized.`); + expect(descriptions[0]).to.equal( + "Description for ARelationshipClass", + `ISchemaPartVisitor.visitClass was called for "BEntityClass" before the relationship its NavigationProperty uses, "ARelationshipClass" was fully deserialized.`, + ); expect(mockVisitor!.visitClass!.secondCall.calledWithExactly(testRelationship)).to.be.true; - expect(descriptions[1]).to.equal("Description for BEntityClass", - `ISchemaPartVisitor.visitClass was called for "ARelationshipClass" before the entity class its constraints use, "BEntityClass" was fully deserialized.`); - + expect(descriptions[1]).to.equal( + "Description for BEntityClass", + `ISchemaPartVisitor.visitClass was called for "ARelationshipClass" before the entity class its constraints use, "BEntityClass" was fully deserialized.`, + ); }); }); @@ -1061,7 +1137,10 @@ describe("Full Schema Deserialization", () => { const schema: Schema = new Schema(context); const reader = new SchemaReadHelper(XmlParser, context); - expect(() => reader.readSchemaSync(schema, document)).not.to.throw(ECObjectsError, "Custom attribute namespaces must contain a valid 3.2 full schema name in the form .RR.ww.mm."); + expect(() => reader.readSchemaSync(schema, document)).not.to.throw( + ECObjectsError, + "Custom attribute namespaces must contain a valid 3.2 full schema name in the form .RR.ww.mm.", + ); }); it("with invalid custom attribute namespace", () => { @@ -1081,7 +1160,10 @@ describe("Full Schema Deserialization", () => { const schema: Schema = new Schema(context); const reader = new SchemaReadHelper(XmlParser, context); - expect(() => reader.readSchemaSync(schema, document)).to.throw(ECObjectsError, "Custom attribute namespaces must contain a valid 3.2 full schema name in the form .RR.ww.mm."); + expect(() => reader.readSchemaSync(schema, document)).to.throw( + ECObjectsError, + "Custom attribute namespaces must contain a valid 3.2 full schema name in the form .RR.ww.mm.", + ); }); describe("with property custom attributes", () => { diff --git a/core/ecschema-metadata/src/test/Metadata/ECName.test.ts b/core/ecschema-metadata/src/test/Metadata/ECName.test.ts index 7d15ec4bc706..bd5475034298 100644 --- a/core/ecschema-metadata/src/test/Metadata/ECName.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/ECName.test.ts @@ -30,17 +30,17 @@ describe("ECName", () => { }); const testcases = [ - [ "NothingSpecial", "NothingSpecial" ], - [ "Nothing1Special2", "Nothing1Special2" ], - [ "1_LeadingDigitsDisallowed", "__x0031___LeadingDigitsDisallowed" ], - [ "Special!", "Special__x0021__" ], - [ "thing@mail.com", "thing__x0040__mail__x002E__com" ], - [ "*", "__x002A__" ], - [ "9&:", "__x0039____x0026____x003A__" ], - [ "__xNotAChar__", "__xNotAChar__" ], - [ "__xTTTT__", "__xTTTT__" ], - [ "__x####__", "__x__x0023____x0023____x0023____x0023____" ], - [ "\u822C\u6A21\u578B", "__x822C____x6A21____x578B__" ], + ["NothingSpecial", "NothingSpecial"], + ["Nothing1Special2", "Nothing1Special2"], + ["1_LeadingDigitsDisallowed", "__x0031___LeadingDigitsDisallowed"], + ["Special!", "Special__x0021__"], + ["thing@mail.com", "thing__x0040__mail__x002E__com"], + ["*", "__x002A__"], + ["9&:", "__x0039____x0026____x003A__"], + ["__xNotAChar__", "__xNotAChar__"], + ["__xTTTT__", "__xTTTT__"], + ["__x####__", "__x__x0023____x0023____x0023____x0023____"], + ["\u822C\u6A21\u578B", "__x822C____x6A21____x578B__"], ]; it("encodes", () => { diff --git a/core/ecschema-metadata/src/test/Metadata/EntityClass.test.ts b/core/ecschema-metadata/src/test/Metadata/EntityClass.test.ts index d382fb90f87c..fc54bceef129 100644 --- a/core/ecschema-metadata/src/test/Metadata/EntityClass.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/EntityClass.test.ts @@ -265,7 +265,7 @@ describe("EntityClass", () => { const baseClass = testEntity!.getBaseClassSync(); assert.isDefined(baseClass); - assert.isTrue(typeof (baseClass) === "object"); + assert.isTrue(typeof baseClass === "object"); assert.isTrue(baseClass === testBaseEntity); }); @@ -292,7 +292,7 @@ describe("EntityClass", () => { assert.isDefined(navProp); if (navProp && navProp.isNavigation()) { const relClass = await schema.getItem("NavPropRelationship"); - assert.isTrue(await navProp.relationshipClass === relClass); // << For some reason type guard was failing..? + assert.isTrue(await navProp.relationshipClass === relClass); // << For some reason type guard was failing..? } else { assert.fail(); } @@ -328,67 +328,100 @@ describe("EntityClass", () => { it("should throw for invalid baseClass", async () => { const json = createSchemaJson({ baseClass: 0 }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECClass TestSchema.TestEntityClass has an invalid 'baseClass' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECClass TestSchema.TestEntityClass has an invalid 'baseClass' attribute. It should be of type 'string'.`, + ); }); it("should throw for invalid mixins", async () => { let json: any = createSchemaJson({ mixins: 0, schema: "TestSchema" }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECEntityClass TestSchema.TestEntityClass has an invalid 'mixins' attribute. It should be of type 'string[]'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECEntityClass TestSchema.TestEntityClass has an invalid 'mixins' attribute. It should be of type 'string[]'.`, + ); json = createSchemaJson({ mixins: [0], schema: "TestSchema" }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECEntityClass TestSchema.TestEntityClass has an invalid 'mixins' attribute. It should be of type 'string[]'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECEntityClass TestSchema.TestEntityClass has an invalid 'mixins' attribute. It should be of type 'string[]'.`, + ); }); it("should throw for invalid properties", async () => { let json: any = createSchemaJson({ properties: 0 }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECClass TestSchema.TestEntityClass has an invalid 'properties' attribute. It should be of type 'object[]'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECClass TestSchema.TestEntityClass has an invalid 'properties' attribute. It should be of type 'object[]'.`, + ); json = createSchemaJson({ properties: [0], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `An ECProperty in TestSchema.TestEntityClass is an invalid JSON object.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `An ECProperty in TestSchema.TestEntityClass is an invalid JSON object.`, + ); }); it("should throw for property with missing name", async () => { const json = createSchemaJson({ properties: [{ type: "PrimitiveProperty" }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `An ECProperty in TestSchema.TestEntityClass is missing the required 'name' attribute.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `An ECProperty in TestSchema.TestEntityClass is missing the required 'name' attribute.`, + ); }); it("should throw for property with invalid name", async () => { const json = createSchemaJson({ properties: [{ type: "PrimitiveProperty", name: 0 }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `An ECProperty in TestSchema.TestEntityClass has an invalid 'name' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `An ECProperty in TestSchema.TestEntityClass has an invalid 'name' attribute. It should be of type 'string'.`, + ); }); it("should throw for property with missing type", async () => { const json = createSchemaJson({ properties: [{ name: "badProp" }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.badProp does not have the required 'type' attribute.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.badProp does not have the required 'type' attribute.`, + ); }); it("should throw for property with invalid type", async () => { const json = createSchemaJson({ properties: [{ name: "badProp", type: 0 }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.badProp has an invalid 'type' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.badProp has an invalid 'type' attribute. It should be of type 'string'.`, + ); }); it("should throw for property with missing typeName", async () => { const json = createSchemaJson({ properties: [{ name: "badProp", type: "PrimitiveProperty" }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.badProp is missing the required 'typeName' attribute.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.badProp is missing the required 'typeName' attribute.`, + ); }); it("should throw for property with invalid typeName", async () => { const json = createSchemaJson({ properties: [{ name: "badProp", type: "PrimitiveProperty", typeName: 0 }], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.badProp has an invalid 'typeName' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.badProp has an invalid 'typeName' attribute. It should be of type 'string'.`, + ); }); it("should throw for property with invalid category", async () => { @@ -402,7 +435,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.testProp has an invalid 'category' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.testProp has an invalid 'category' attribute. It should be of type 'string'.`, + ); }); it("should throw for property with invalid kindOfQuantity", async () => { @@ -416,7 +452,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The ECProperty TestSchema.TestEntityClass.testProp has an invalid 'kindOfQuantity' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The ECProperty TestSchema.TestEntityClass.testProp has an invalid 'kindOfQuantity' attribute. It should be of type 'string'.`, + ); }); it("should throw for navigation property with missing relationshipName", async () => { @@ -429,7 +468,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Navigation Property TestSchema.TestEntityClass.testNavProp is missing the required 'relationshipName' property.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Navigation Property TestSchema.TestEntityClass.testNavProp is missing the required 'relationshipName' property.`, + ); }); it("should throw for navigation property with invalid relationshipName", async () => { @@ -443,7 +485,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Navigation Property TestSchema.TestEntityClass.testNavProp has an invalid 'relationshipName' property. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Navigation Property TestSchema.TestEntityClass.testNavProp has an invalid 'relationshipName' property. It should be of type 'string'.`, + ); }); it("should throw for navigation property with nonexistent relationship", async () => { @@ -457,7 +502,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `Unable to locate SchemaItem BadSchema.ThisDoesNotExist.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `Unable to locate SchemaItem BadSchema.ThisDoesNotExist.`, + ); }); it("should throw for navigation property with missing direction", async () => { @@ -470,7 +518,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Navigation Property TestSchema.TestEntityClass.testNavProp is missing the required 'direction' property.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Navigation Property TestSchema.TestEntityClass.testNavProp is missing the required 'direction' property.`, + ); }); it("should throw for navigation property with invalid direction", async () => { @@ -484,7 +535,10 @@ describe("EntityClass", () => { }, ], }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Navigation Property TestSchema.TestEntityClass.testNavProp has an invalid 'direction' property. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Navigation Property TestSchema.TestEntityClass.testNavProp has an invalid 'direction' property. It should be of type 'string'.`, + ); }); }); diff --git a/core/ecschema-metadata/src/test/Metadata/Enumeration.test.ts b/core/ecschema-metadata/src/test/Metadata/Enumeration.test.ts index 72664dd767d9..e51cc5277085 100644 --- a/core/ecschema-metadata/src/test/Metadata/Enumeration.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Enumeration.test.ts @@ -9,8 +9,8 @@ import { PrimitiveType } from "../../ECObjects"; import { ECObjectsError } from "../../Exception"; import { Enumeration, MutableEnumeration } from "../../Metadata/Enumeration"; import { Schema } from "../../Metadata/Schema"; -import { createEmptyXmlDocument, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; +import { createEmptyXmlDocument, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; describe("Enumeration", () => { it("should get fullName", async () => { @@ -63,13 +63,25 @@ describe("Enumeration", () => { it("Add duplicate enumerator", async () => { const newEnum = testStringEnum.createEnumerator("Enum1", "Val1"); (testStringEnum as MutableEnumeration).addEnumerator(newEnum); - assert.throws(() => testStringEnum.createEnumerator("Enum1", "Val1"), ECObjectsError, `The Enumeration TestEnumeration has a duplicate Enumerator with name 'Enum1'.`); + assert.throws( + () => testStringEnum.createEnumerator("Enum1", "Val1"), + ECObjectsError, + `The Enumeration TestEnumeration has a duplicate Enumerator with name 'Enum1'.`, + ); }); it("Add int enumerator to string enumeration", async () => { - assert.throws(() => testStringEnum.createEnumerator("Enum1", 1), ECObjectsError, `The Enumeration TestEnumeration has a backing type 'string' and an enumerator with value of type 'integer'.`); + assert.throws( + () => testStringEnum.createEnumerator("Enum1", 1), + ECObjectsError, + `The Enumeration TestEnumeration has a backing type 'string' and an enumerator with value of type 'integer'.`, + ); }); it("Add string enumerator to int enumeration", async () => { - assert.throws(() => testEnum.createEnumerator("Enum1", "Value1"), ECObjectsError, `The Enumeration TestEnumeration has a backing type 'integer' and an enumerator with value of type 'string'.`); + assert.throws( + () => testEnum.createEnumerator("Enum1", "Value1"), + ECObjectsError, + `The Enumeration TestEnumeration has a backing type 'integer' and an enumerator with value of type 'string'.`, + ); }); }); @@ -146,19 +158,19 @@ describe("Enumeration", () => { expect(enumeration.enumerators.length).to.eql(2); } function assertValidEnumerator(enumeration: Enumeration, enumVal: number | string, label?: string, description?: string) { - if (typeof (enumVal) === "number") { + if (typeof enumVal === "number") { expect(enumeration.isInt).to.be.true; expect(enumeration.isString).to.be.false; - if (typeof (label) !== undefined) + if (typeof label !== undefined) expect(enumeration.getEnumerator(enumVal)!.label).to.eql(label); - if (typeof (description) !== undefined) + if (typeof description !== undefined) expect(enumeration.getEnumerator(enumVal)!.description).to.eql(description); } else { expect(enumeration.isInt).to.be.false; expect(enumeration.isString).to.be.true; - if (typeof (label) !== undefined) + if (typeof label !== undefined) expect(enumeration.getEnumerator(enumVal)!.label).to.eql(label); - if (typeof (description) !== undefined) + if (typeof description !== undefined) expect(enumeration.getEnumerator(enumVal)!.description).to.eql(description); } } @@ -224,7 +236,10 @@ describe("Enumeration", () => { { name: "SixValue", value: 8, label: "An enumerator label" }, ], }; - await expect(testEnum.fromJSON(json)).to.be.rejectedWith(ECObjectsError, `The Enumeration TestEnumeration has a duplicate Enumerator with name 'SixValue'.`); + await expect(testEnum.fromJSON(json)).to.be.rejectedWith( + ECObjectsError, + `The Enumeration TestEnumeration has a duplicate Enumerator with name 'SixValue'.`, + ); }); it("Duplicate value", async () => { @@ -239,7 +254,10 @@ describe("Enumeration", () => { { name: "EightValue", value: 6 }, ], }; - await expect(testEnum.fromJSON(json)).to.be.rejectedWith(ECObjectsError, `The Enumeration TestEnumeration has a duplicate Enumerator with value '6'.`); + await expect(testEnum.fromJSON(json)).to.be.rejectedWith( + ECObjectsError, + `The Enumeration TestEnumeration has a duplicate Enumerator with value '6'.`, + ); }); it("Basic test with number values", async () => { @@ -300,7 +318,10 @@ describe("Enumeration", () => { { name: "onevalue", value: "two", label: "Label for the second value", description: "description for the second value" }, ], }; - await expect(testStringEnum.fromJSON(json)).to.be.rejectedWith(ECObjectsError, `The Enumeration TestEnumeration has a duplicate Enumerator with name 'onevalue'.`); + await expect(testStringEnum.fromJSON(json)).to.be.rejectedWith( + ECObjectsError, + `The Enumeration TestEnumeration has a duplicate Enumerator with name 'onevalue'.`, + ); }); it("Get enumerator by name", async () => { diff --git a/core/ecschema-metadata/src/test/Metadata/Format.test.ts b/core/ecschema-metadata/src/test/Metadata/Format.test.ts index f906664f463e..7743c10eda2a 100644 --- a/core/ecschema-metadata/src/test/Metadata/Format.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Format.test.ts @@ -3,6 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { DecimalPrecision, FormatTraits, FormatType, QuantityError, ShowSignOption } from "@itwin/core-quantity"; import { assert, expect } from "chai"; import { SchemaContext } from "../../Context"; import { JsonParser } from "../../Deserialization/JsonParser"; @@ -10,7 +11,6 @@ import { SchemaItemFormatProps } from "../../Deserialization/JsonProps"; import { ECObjectsError } from "../../Exception"; import { Format } from "../../Metadata/Format"; import { MutableSchema, Schema } from "../../Metadata/Schema"; -import { DecimalPrecision, FormatTraits, FormatType, QuantityError, ShowSignOption } from "@itwin/core-quantity"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; import { TestSchemaLocater } from "../TestUtils/FormatTestHelper"; import { createEmptyXmlDocument, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; @@ -113,72 +113,128 @@ describe("Format", () => { it("missing type attribute", () => { const missingType = { schemaItemType: "Format" }; - assert.throws(() => jsonParser.parseFormat(missingType), ECObjectsError, `The Format TestSchema.TestFormat does not have the required 'type' attribute.`); + assert.throws( + () => jsonParser.parseFormat(missingType), + ECObjectsError, + `The Format TestSchema.TestFormat does not have the required 'type' attribute.`, + ); }); it("invalid type attribute", () => { const invalidType = { schemaItemType: "Format", type: true }; - assert.throws(() => jsonParser.parseFormat(invalidType), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'type' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(invalidType), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'type' attribute. It should be of type 'string'.`, + ); }); it("invalid precision attribute", () => { const invalidPrecision = { precision: "" }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidPrecision)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'precision' attribute. It should be of type 'number'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidPrecision)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'precision' attribute. It should be of type 'number'.`, + ); }); it("invalid roundFactor attribute", () => { const invalidRoundFactor = { roundFactor: "" }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidRoundFactor)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'roundFactor' attribute. It should be of type 'number'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidRoundFactor)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'roundFactor' attribute. It should be of type 'number'.`, + ); }); it("invalid minWidth attribute", () => { const invalidMinWidth = { minWidth: "" }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidMinWidth)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'minWidth' attribute. It should be of type 'number'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidMinWidth)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'minWidth' attribute. It should be of type 'number'.`, + ); }); it("invalid showSignOption attribute", () => { const invalidShowSignOption = { showSignOption: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidShowSignOption)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'showSignOption' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidShowSignOption)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'showSignOption' attribute. It should be of type 'string'.`, + ); }); it("invalid formatTraits attribute", () => { const invalidFormatTraits = { formatTraits: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidFormatTraits)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'formatTraits' attribute. It should be of type 'string' or 'string[]'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidFormatTraits)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'formatTraits' attribute. It should be of type 'string' or 'string[]'.`, + ); }); it("invalid decimalSeparator attribute", () => { const invalidDecimalSeparator = { decimalSeparator: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidDecimalSeparator)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'decimalSeparator' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidDecimalSeparator)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'decimalSeparator' attribute. It should be of type 'string'.`, + ); }); it("invalid thousandSeparator attribute", () => { const invalidThousandSeparator = { thousandSeparator: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidThousandSeparator)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'thousandSeparator' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidThousandSeparator)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'thousandSeparator' attribute. It should be of type 'string'.`, + ); }); it("invalid uomSeparator attribute", () => { const invalidUOMSeparator = { uomSeparator: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidUOMSeparator)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'uomSeparator' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidUOMSeparator)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'uomSeparator' attribute. It should be of type 'string'.`, + ); }); it("invalid scientificType attribute", () => { const invalidScientificType = { scientificType: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidScientificType)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'scientificType' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidScientificType)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'scientificType' attribute. It should be of type 'string'.`, + ); }); it("invalid stationOffsetSize attribute", () => { const invalidStationOffsetSize = { stationOffsetSize: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidStationOffsetSize)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'stationOffsetSize' attribute. It should be of type 'number'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidStationOffsetSize)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'stationOffsetSize' attribute. It should be of type 'number'.`, + ); }); it("invalid stationSeparator attribute", () => { const invalidStationSeparator = { stationSeparator: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidStationSeparator)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'stationSeparator' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidStationSeparator)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'stationSeparator' attribute. It should be of type 'string'.`, + ); }); it("invalid composite attribute", () => { const invalidComposite = { composite: true }; - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidComposite)), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'composite' object.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidComposite)), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'composite' object.`, + ); }); const invalidCompositeSpacer = { @@ -187,7 +243,11 @@ describe("Format", () => { }, }; it("invalid composite spacer attribute", () => { - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidCompositeSpacer)), ECObjectsError, `The Format TestSchema.TestFormat has a Composite with an invalid 'spacer' attribute. It should be of type 'string'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidCompositeSpacer)), + ECObjectsError, + `The Format TestSchema.TestFormat has a Composite with an invalid 'spacer' attribute. It should be of type 'string'.`, + ); }); const invalidCompositeIncludeZero = { @@ -196,7 +256,11 @@ describe("Format", () => { }, }; it("invalid composite include zero attribute", () => { - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidCompositeIncludeZero)), ECObjectsError, `The Format TestSchema.TestFormat has a Composite with an invalid 'includeZero' attribute. It should be of type 'boolean'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidCompositeIncludeZero)), + ECObjectsError, + `The Format TestSchema.TestFormat has a Composite with an invalid 'includeZero' attribute. It should be of type 'boolean'.`, + ); }); const invalidCompositeUnits = { @@ -205,7 +269,11 @@ describe("Format", () => { }, }; it("invalid composite units attribute", () => { - assert.throws(() => jsonParser.parseFormat(createFormatJson(invalidCompositeUnits)), ECObjectsError, `The Format TestSchema.TestFormat has a Composite with an invalid 'units' attribute. It should be of type 'object[]'.`); + assert.throws( + () => jsonParser.parseFormat(createFormatJson(invalidCompositeUnits)), + ECObjectsError, + `The Format TestSchema.TestFormat has a Composite with an invalid 'units' attribute. It should be of type 'object[]'.`, + ); }); }); // type checking json @@ -264,10 +332,17 @@ describe("Format", () => { type: "BadType", }; it("sync - invalid type attribute value", () => { - assert.throws(() => testFormat.fromJSONSync(invalidTypeAttributeValue), QuantityError, `The Format TestFormat has an invalid 'type' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidTypeAttributeValue), + QuantityError, + `The Format TestFormat has an invalid 'type' attribute.`, + ); }); it("async - invalid type attribute value", async () => { - await expect(testFormat.fromJSON(invalidTypeAttributeValue)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'type' attribute.`); + await expect(testFormat.fromJSON(invalidTypeAttributeValue)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'type' attribute.`, + ); }); const invalidPrecisionDecimal: SchemaItemFormatProps = { @@ -288,14 +363,35 @@ describe("Format", () => { precision: -1, }; it("sync - precision value is invalid with different format types", () => { - assert.throws(() => testFormat.fromJSONSync(invalidPrecisionDecimal), QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); - assert.throws(() => testFormat.fromJSONSync(invalidPrecisionScientific), QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); - assert.throws(() => testFormat.fromJSONSync(invalidPrecisionStation), QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidPrecisionDecimal), + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); + assert.throws( + () => testFormat.fromJSONSync(invalidPrecisionScientific), + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); + assert.throws( + () => testFormat.fromJSONSync(invalidPrecisionStation), + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); }); it("async - precision value is invalid with different format types", async () => { - await expect(testFormat.fromJSON(invalidPrecisionDecimal)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); - await expect(testFormat.fromJSON(invalidPrecisionScientific)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); - await expect(testFormat.fromJSON(invalidPrecisionStation)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'precision' attribute.`); + await expect(testFormat.fromJSON(invalidPrecisionDecimal)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); + await expect(testFormat.fromJSON(invalidPrecisionScientific)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); + await expect(testFormat.fromJSON(invalidPrecisionStation)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'precision' attribute.`, + ); }); const validPrecisionDecimal: SchemaItemFormatProps = { @@ -347,17 +443,31 @@ describe("Format", () => { minWidth: 5.5, }; it("sync - minWidth value is invalid", () => { - assert.throws(() => testFormat.fromJSONSync(invalidMinWidth), QuantityError, `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`); + assert.throws( + () => testFormat.fromJSONSync(invalidMinWidth), + QuantityError, + `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); invalidMinWidth.minWidth = -1; - assert.throws(() => testFormat.fromJSONSync(invalidMinWidth), QuantityError, `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`); + assert.throws( + () => testFormat.fromJSONSync(invalidMinWidth), + QuantityError, + `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); }); it("async - minWidth value is invalid", async () => { invalidMinWidth.minWidth = 5.5; // TODO fix this - await expect(testFormat.fromJSON(invalidMinWidth)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`); + await expect(testFormat.fromJSON(invalidMinWidth)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); invalidMinWidth.minWidth = -1; - await expect(testFormat.fromJSON(invalidMinWidth)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`); + await expect(testFormat.fromJSON(invalidMinWidth)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); }); const missingScientificType: SchemaItemFormatProps = { @@ -365,10 +475,17 @@ describe("Format", () => { type: "Scientific", }; it("sync - scientific type is required when type is scientific", () => { - assert.throws(() => testFormat.fromJSONSync(missingScientificType), QuantityError, `The Format TestFormat is 'Scientific' type therefore the attribute 'scientificType' is required.`); + assert.throws( + () => testFormat.fromJSONSync(missingScientificType), + QuantityError, + `The Format TestFormat is 'Scientific' type therefore the attribute 'scientificType' is required.`, + ); }); it("async - scientific type is required when type is scientific", async () => { - await expect(testFormat.fromJSON(missingScientificType)).to.be.rejectedWith(QuantityError, `The Format TestFormat is 'Scientific' type therefore the attribute 'scientificType' is required.`); + await expect(testFormat.fromJSON(missingScientificType)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat is 'Scientific' type therefore the attribute 'scientificType' is required.`, + ); }); const invalidScientificType: SchemaItemFormatProps = { @@ -377,10 +494,17 @@ describe("Format", () => { scientificType: "badType", }; it("sync - scientific type is not supported", () => { - assert.throws(() => testFormat.fromJSONSync(invalidScientificType), QuantityError, `The Format TestFormat has an invalid 'scientificType' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidScientificType), + QuantityError, + `The Format TestFormat has an invalid 'scientificType' attribute.`, + ); }); it("async - scientific type is not supported", async () => { - await expect(testFormat.fromJSON(invalidScientificType)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'scientificType' attribute.`); + await expect(testFormat.fromJSON(invalidScientificType)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'scientificType' attribute.`, + ); }); const missingStationOffsetSize: SchemaItemFormatProps = { @@ -388,10 +512,17 @@ describe("Format", () => { type: "station", }; it("sync - stationOffsetSize is required when type is station", () => { - assert.throws(() => testFormat.fromJSONSync(missingStationOffsetSize), QuantityError, `The Format TestFormat is 'Station' type therefore the attribute 'stationOffsetSize' is required.`); + assert.throws( + () => testFormat.fromJSONSync(missingStationOffsetSize), + QuantityError, + `The Format TestFormat is 'Station' type therefore the attribute 'stationOffsetSize' is required.`, + ); }); it("async - stationOffsetSize is required when type is station", async () => { - await expect(testFormat.fromJSON(missingStationOffsetSize)).to.be.rejectedWith(QuantityError, `The Format TestFormat is 'Station' type therefore the attribute 'stationOffsetSize' is required.`); + await expect(testFormat.fromJSON(missingStationOffsetSize)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat is 'Station' type therefore the attribute 'stationOffsetSize' is required.`, + ); }); const invalidStationOffsetSize: SchemaItemFormatProps = { @@ -400,10 +531,17 @@ describe("Format", () => { stationOffsetSize: -1, }; it("sync - stationOffsetSize is invalid value", () => { - assert.throws(() => testFormat.fromJSONSync(invalidStationOffsetSize), QuantityError, `The Format TestFormat has an invalid 'stationOffsetSize' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidStationOffsetSize), + QuantityError, + `The Format TestFormat has an invalid 'stationOffsetSize' attribute.`, + ); }); it("async - stationOffsetSize is invalid value", async () => { - await expect(testFormat.fromJSON(invalidStationOffsetSize)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'stationOffsetSize' attribute.`); + await expect(testFormat.fromJSON(invalidStationOffsetSize)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'stationOffsetSize' attribute.`, + ); }); const invalidShowSignOption: SchemaItemFormatProps = { @@ -412,10 +550,17 @@ describe("Format", () => { showSignOption: "noSigned", }; it("sync - scientific type is not supported", () => { - assert.throws(() => testFormat.fromJSONSync(invalidShowSignOption), QuantityError, `The Format TestFormat has an invalid 'showSignOption' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidShowSignOption), + QuantityError, + `The Format TestFormat has an invalid 'showSignOption' attribute.`, + ); }); it("async - scientific type is not supported", async () => { - await expect(testFormat.fromJSON(invalidShowSignOption)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'showSignOption' attribute.`); + await expect(testFormat.fromJSON(invalidShowSignOption)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'showSignOption' attribute.`, + ); }); const invalidDecimalSeparator: SchemaItemFormatProps = { @@ -424,10 +569,17 @@ describe("Format", () => { decimalSeparator: "badSeparator", }; it("sync - decimal separator cannot be larger than 1 character", () => { - assert.throws(() => testFormat.fromJSONSync(invalidDecimalSeparator), QuantityError, `The Format TestFormat has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`); + assert.throws( + () => testFormat.fromJSONSync(invalidDecimalSeparator), + QuantityError, + `The Format TestFormat has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`, + ); }); it("async - decimal separator cannot be larger than 1 character", async () => { - await expect(testFormat.fromJSON(invalidDecimalSeparator)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`); + await expect(testFormat.fromJSON(invalidDecimalSeparator)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`, + ); }); const invalidThousandSeparator: SchemaItemFormatProps = { @@ -436,10 +588,17 @@ describe("Format", () => { thousandSeparator: "badSeparator", }; it("sync - thousand separator cannot be larger than 1 character", () => { - assert.throws(() => testFormat.fromJSONSync(invalidThousandSeparator), QuantityError, `The Format TestFormat has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`); + assert.throws( + () => testFormat.fromJSONSync(invalidThousandSeparator), + QuantityError, + `The Format TestFormat has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`, + ); }); it("async - thousand separator cannot be larger than 1 character", async () => { - await expect(testFormat.fromJSON(invalidThousandSeparator)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`); + await expect(testFormat.fromJSON(invalidThousandSeparator)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`, + ); }); const invalidUOMSeparator: SchemaItemFormatProps = { @@ -448,10 +607,17 @@ describe("Format", () => { uomSeparator: "badSeparator", }; it("sync - UOM separator cannot be larger than 1 character", () => { - assert.throws(() => testFormat.fromJSONSync(invalidUOMSeparator), QuantityError, `The Format TestFormat has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`); + assert.throws( + () => testFormat.fromJSONSync(invalidUOMSeparator), + QuantityError, + `The Format TestFormat has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`, + ); }); it("async - UOM separator cannot be larger than 1 character", async () => { - await expect(testFormat.fromJSON(invalidUOMSeparator)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`); + await expect(testFormat.fromJSON(invalidUOMSeparator)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`, + ); }); const invalidStationSeparator: SchemaItemFormatProps = { @@ -460,10 +626,17 @@ describe("Format", () => { stationSeparator: "badSeparator", }; it("sync - station separator cannot be larger than 1 character", () => { - assert.throws(() => testFormat.fromJSONSync(invalidStationSeparator), QuantityError, `The Format TestFormat has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`); + assert.throws( + () => testFormat.fromJSONSync(invalidStationSeparator), + QuantityError, + `The Format TestFormat has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`, + ); }); it("async - station separator cannot be larger than 1 character", async () => { - await expect(testFormat.fromJSON(invalidStationSeparator)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`); + await expect(testFormat.fromJSON(invalidStationSeparator)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`, + ); }); describe("format traits", () => { @@ -484,7 +657,8 @@ describe("Format", () => { const validFormatTraitString: SchemaItemFormatProps = { schemaItemType: "Format", type: "decimal", - formatTraits: "trailZeroes|keepSingleZero|zeroEmpty|keepDecimalPoint|applyRounding|fractionDash|showUnitLabel|prependUnitLabel|use1000Separator|exponentOnlyNegative", + formatTraits: + "trailZeroes|keepSingleZero|zeroEmpty|keepDecimalPoint|applyRounding|fractionDash|showUnitLabel|prependUnitLabel|use1000Separator|exponentOnlyNegative", }; it("sync - all valid options defined in a string", () => { testFormat.fromJSONSync(validFormatTraitString); @@ -583,10 +757,17 @@ describe("Format", () => { formatTraits: "applyRounding\fractionDash;showUnitLabel", }; it("sync - invalid format trait separator", () => { - assert.throws(() => testFormat.fromJSONSync(invalidSeparator), QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidSeparator), + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); it("async - invalid format trait separator", async () => { - await expect(testFormat.fromJSON(invalidSeparator)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + await expect(testFormat.fromJSON(invalidSeparator)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); const invalidFormatTraitInString: SchemaItemFormatProps = { @@ -595,10 +776,17 @@ describe("Format", () => { formatTraits: "badTraits", }; it("sync - invalid format trait within a string", () => { - assert.throws(() => testFormat.fromJSONSync(invalidFormatTraitInString), QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidFormatTraitInString), + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); it("async - invalid format trait within a string", async () => { - await expect(testFormat.fromJSON(invalidFormatTraitInString)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + await expect(testFormat.fromJSON(invalidFormatTraitInString)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); const invalidFormatTraitInArray: SchemaItemFormatProps = { @@ -609,10 +797,17 @@ describe("Format", () => { ], }; it("sync - invalid format trait within a array", () => { - assert.throws(() => testFormat.fromJSONSync(invalidFormatTraitInArray), QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + assert.throws( + () => testFormat.fromJSONSync(invalidFormatTraitInArray), + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); it("async - invalid format trait within a array", async () => { - await expect(testFormat.fromJSON(invalidFormatTraitInArray)).to.be.rejectedWith(QuantityError, `The Format TestFormat has an invalid 'formatTraits' attribute.`); + await expect(testFormat.fromJSON(invalidFormatTraitInArray)).to.be.rejectedWith( + QuantityError, + `The Format TestFormat has an invalid 'formatTraits' attribute.`, + ); }); }); // formatTraits @@ -634,10 +829,18 @@ describe("Format", () => { }, }; it("sync - spacer must be a one character string", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidSpacer), context), ECObjectsError, `The Format TestSchema.TestFormat has a composite with an invalid 'spacer' attribute. It should be an empty or one character string.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidSpacer), context), + ECObjectsError, + `The Format TestSchema.TestFormat has a composite with an invalid 'spacer' attribute. It should be an empty or one character string.`, + ); }); it("async - spacer must be a one character string", async () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidSpacer), context), ECObjectsError, `The Format TestSchema.TestFormat has a composite with an invalid 'spacer' attribute. It should be an empty or one character string.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidSpacer), context), + ECObjectsError, + `The Format TestSchema.TestFormat has a composite with an invalid 'spacer' attribute. It should be an empty or one character string.`, + ); }); const invalidCompositeWithoutUnits = { @@ -645,10 +848,17 @@ describe("Format", () => { composite: {}, }; it("sync - invalid composite without units", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidCompositeWithoutUnits), context), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidCompositeWithoutUnits), context), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); it("async - invalid composite without units", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidCompositeWithoutUnits), context)).to.be.rejectedWith(ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + await expect(Schema.fromJson(createSchemaJson(invalidCompositeWithoutUnits), context)).to.be.rejectedWith( + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); const invalidCompositeEmptyUnits = { @@ -658,10 +868,17 @@ describe("Format", () => { }, }; it("sync - invalid composite without units", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidCompositeEmptyUnits), context), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidCompositeEmptyUnits), context), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); it("async - invalid composite without units", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidCompositeEmptyUnits), context)).to.be.rejectedWith(ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + await expect(Schema.fromJson(createSchemaJson(invalidCompositeEmptyUnits), context)).to.be.rejectedWith( + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); const invalidCompositeTooManyUnits = { @@ -677,10 +894,17 @@ describe("Format", () => { }, }; it("sync - invalid composite with too many units", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidCompositeTooManyUnits), context), ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidCompositeTooManyUnits), context), + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); it("async - invalid composite with too many units", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidCompositeTooManyUnits), context)).to.be.rejectedWith(ECObjectsError, `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`); + await expect(Schema.fromJson(createSchemaJson(invalidCompositeTooManyUnits), context)).to.be.rejectedWith( + ECObjectsError, + `The Format TestSchema.TestFormat has an invalid 'Composite' attribute. It should have 1-4 units.`, + ); }); const invalidCompositeDuplicateUnits = { @@ -693,10 +917,17 @@ describe("Format", () => { }, }; it("sync - invalid composite with duplicate units", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidCompositeDuplicateUnits), context), ECObjectsError, `The Format TestSchema.TestFormat has duplicate units, 'Formats.MILE'.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidCompositeDuplicateUnits), context), + ECObjectsError, + `The Format TestSchema.TestFormat has duplicate units, 'Formats.MILE'.`, + ); }); it("async - invalid composite with duplicate units", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidCompositeDuplicateUnits), context)).to.be.rejectedWith(ECObjectsError, `The Format TestSchema.TestFormat has duplicate units, 'Formats.MILE'.`); + await expect(Schema.fromJson(createSchemaJson(invalidCompositeDuplicateUnits), context)).to.be.rejectedWith( + ECObjectsError, + `The Format TestSchema.TestFormat has duplicate units, 'Formats.MILE'.`, + ); }); const validComposite = { @@ -719,7 +950,7 @@ describe("Format", () => { }, { name: "Formats.IN", - label: "\"", + label: '"', }, ], }, @@ -745,7 +976,7 @@ describe("Format", () => { expect(format!.units![2][1]).eq("'"); expect(format!.units![3][0].fullName).eq("Formats.IN"); - expect(format!.units![3][1]).eq("\""); + expect(format!.units![3][1]).eq('"'); } it("sync - ", () => { const testSchema = Schema.fromJsonSync(createSchemaJson(validComposite), context); @@ -760,7 +991,6 @@ describe("Format", () => { validateTestFormat(format); }); }); // composite - }); // deserialize properly formatted ECJSON describe("toJSON", () => { diff --git a/core/ecschema-metadata/src/test/Metadata/InvertedUnit.test.ts b/core/ecschema-metadata/src/test/Metadata/InvertedUnit.test.ts index 0bf151d090ac..9142352e794c 100644 --- a/core/ecschema-metadata/src/test/Metadata/InvertedUnit.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/InvertedUnit.test.ts @@ -138,7 +138,10 @@ describe("Inverted Unit tests", () => { }, }, }; - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The InvertedUnit TestSchema.HORIZONTAL_PER_VERTICAL does not have the required 'unitSystem' attribute.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The InvertedUnit TestSchema.HORIZONTAL_PER_VERTICAL does not have the required 'unitSystem' attribute.`, + ); }); it("Resolve all dependencies for inverts unit and unit system", async () => { const json = { diff --git a/core/ecschema-metadata/src/test/Metadata/KindOfQuantity.test.ts b/core/ecschema-metadata/src/test/Metadata/KindOfQuantity.test.ts index f37af9938733..f27b8d52c476 100644 --- a/core/ecschema-metadata/src/test/Metadata/KindOfQuantity.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/KindOfQuantity.test.ts @@ -3,6 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { DecimalPrecision } from "@itwin/core-quantity"; import { assert, expect } from "chai"; import { SchemaContext } from "../../Context"; import { ECObjectsError } from "../../Exception"; @@ -11,7 +12,6 @@ import { KindOfQuantity } from "../../Metadata/KindOfQuantity"; import { OverrideFormat } from "../../Metadata/OverrideFormat"; import { Schema } from "../../Metadata/Schema"; import { Unit } from "../../Metadata/Unit"; -import { DecimalPrecision } from "@itwin/core-quantity"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; import { TestSchemaLocater } from "../TestUtils/FormatTestHelper"; import { createEmptyXmlDocument } from "../TestUtils/SerializationHelper"; @@ -98,7 +98,6 @@ describe("KindOfQuantity", () => { expect(testKoq!.persistenceUnit!.fullName).eq(testUnit!.key.fullName); // Formats.IN === Formats.IN }); it("sync - should successfully deserialize without presentationUnits", () => { - }); // should throw for presentationUnit with non-existent format @@ -111,10 +110,17 @@ describe("KindOfQuantity", () => { ], }; it("async - should throw for presentationUnit having a non-existent format", async () => { - await expect(Schema.fromJson(createSchemaJson(presentationUnitsNonExistentFormat), context)).to.be.rejectedWith(ECObjectsError, `Unable to locate SchemaItem TestSchema.NonexistentFormat.`); + await expect(Schema.fromJson(createSchemaJson(presentationUnitsNonExistentFormat), context)).to.be.rejectedWith( + ECObjectsError, + `Unable to locate SchemaItem TestSchema.NonexistentFormat.`, + ); }); it("sync - should throw for presentationUnit having a non-existent format", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(presentationUnitsNonExistentFormat), context), ECObjectsError, `Unable to locate SchemaItem TestSchema.NonexistentFormat.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(presentationUnitsNonExistentFormat), context), + ECObjectsError, + `Unable to locate SchemaItem TestSchema.NonexistentFormat.`, + ); }); // should throw for persistenceUnit with non-existent format @@ -127,10 +133,17 @@ describe("KindOfQuantity", () => { ], }; it("async - should throw for persistenceUnit having a non-existent format", async () => { - await expect(Schema.fromJson(createSchemaJson(persistenceUnitNonExistentFormat), context)).to.be.rejectedWith(ECObjectsError, `Unable to locate SchemaItem TestSchema.NonexistentFormat.`); + await expect(Schema.fromJson(createSchemaJson(persistenceUnitNonExistentFormat), context)).to.be.rejectedWith( + ECObjectsError, + `Unable to locate SchemaItem TestSchema.NonexistentFormat.`, + ); }); it("sync - should throw for persistenceUnit having a non-existent format", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(persistenceUnitNonExistentFormat), context), ECObjectsError, `Unable to locate SchemaItem TestSchema.NonexistentFormat.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(persistenceUnitNonExistentFormat), context), + ECObjectsError, + `Unable to locate SchemaItem TestSchema.NonexistentFormat.`, + ); }); // should deserialize for persistenceUnit with InvertedUnit @@ -188,7 +201,11 @@ describe("KindOfQuantity", () => { assert.isDefined(defaultFormat); assert.isTrue(OverrideFormat.isOverrideFormat(defaultFormat)); - assert.notEqual(defaultFormat, await schema.lookupItem((defaultFormat as OverrideFormat).parent.key.fullName), "The format in the KOQ should be different than the one in the schema"); + assert.notEqual( + defaultFormat, + await schema.lookupItem((defaultFormat as OverrideFormat).parent.key.fullName), + "The format in the KOQ should be different than the one in the schema", + ); expect(defaultFormat!.precision).eq(DecimalPrecision.Two); @@ -198,18 +215,30 @@ describe("KindOfQuantity", () => { type: "Decimal", precision: 2, }; - expect(JSON.parse(JSON.stringify((defaultFormat as OverrideFormat)?.getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(2)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((defaultFormat as OverrideFormat)?.getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(2)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[0].precision).eq(DecimalPrecision.Two); - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[0] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(2)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[0] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(2)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[1].precision).eq(DecimalPrecision.Three); expectedJson.precision = 3; - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[1] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(3)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[1] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(3)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[2].precision).eq(DecimalPrecision.Four); expectedJson.precision = 4; - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[2] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(4)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[2] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(4)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[0].name).eq("Formats.DefaultReal(2)"); expect(testKoq!.presentationFormats[0].fullName).eq("Formats.DefaultReal(2)"); @@ -228,7 +257,11 @@ describe("KindOfQuantity", () => { assert.isDefined(defaultFormat); assert.isTrue(OverrideFormat.isOverrideFormat(defaultFormat)); - assert.notEqual(defaultFormat, schema.lookupItemSync((defaultFormat as OverrideFormat).parent.fullName), "The format in the KOQ should be different than the one in the schema"); + assert.notEqual( + defaultFormat, + schema.lookupItemSync((defaultFormat as OverrideFormat).parent.fullName), + "The format in the KOQ should be different than the one in the schema", + ); expect(defaultFormat!.precision).eq(DecimalPrecision.Two); @@ -238,18 +271,30 @@ describe("KindOfQuantity", () => { type: "Decimal", precision: 2, }; - expect(JSON.parse(JSON.stringify((defaultFormat as OverrideFormat)?.getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(2)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((defaultFormat as OverrideFormat)?.getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(2)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[0].precision).eq(DecimalPrecision.Two); - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[0] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(2)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[0] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(2)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[1].precision).eq(DecimalPrecision.Three); expectedJson.precision = 3; - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[1] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(3)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[1] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(3)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[2].precision).eq(DecimalPrecision.Four); expectedJson.precision = 4; - expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[2] as OverrideFormat).getFormatProps()))).to.be.deep.equal({name: "Formats.DefaultReal(4)", ...expectedJson}); + expect(JSON.parse(JSON.stringify((testKoq!.presentationFormats[2] as OverrideFormat).getFormatProps()))).to.be.deep.equal({ + name: "Formats.DefaultReal(4)", + ...expectedJson, + }); expect(testKoq!.presentationFormats[0].name).eq("Formats.DefaultReal(2)"); expect(testKoq!.presentationFormats[0].fullName).eq("Formats.DefaultReal(2)"); @@ -310,7 +355,11 @@ describe("KindOfQuantity", () => { const defaultFormat = testKoq!.defaultPresentationFormat; assert.isDefined(defaultFormat); - assert.notEqual(defaultFormat, schema.lookupItemSync((defaultFormat as OverrideFormat).parent.key.fullName), "The format in the KOQ should be different than the one in the schema"); + assert.notEqual( + defaultFormat, + schema.lookupItemSync((defaultFormat as OverrideFormat).parent.key.fullName), + "The format in the KOQ should be different than the one in the schema", + ); assert.isDefined(defaultFormat!.units); expect(defaultFormat!.units!.length).to.eq(1); @@ -395,7 +444,6 @@ describe("KindOfQuantity", () => { }, }; expect(JSON.parse(JSON.stringify((defaultFormat as OverrideFormat)?.getFormatProps()))).to.be.deep.equal(expectedJson); - }); const nullOrEmptyUnitLabelOverride = { ...baseJson, @@ -405,15 +453,18 @@ describe("KindOfQuantity", () => { }; const expectedOutputJson = { - schemaItemType:"Format", - name:"Formats.QuadUnitFormat[Formats.MILE][Formats.YRD|][Formats.FT|'][Formats.IN|in]", - parent:"Formats.QuadUnitFormat", - type:"Decimal", - precision:6, + schemaItemType: "Format", + name: "Formats.QuadUnitFormat[Formats.MILE][Formats.YRD|][Formats.FT|'][Formats.IN|in]", + parent: "Formats.QuadUnitFormat", + type: "Decimal", + precision: 6, composite: { spacer: "-", includeZero: false, - units: [{ name: "Formats.MILE"},{ name: "Formats.YRD", label: "" },{ name: "Formats.FT", label: "'" },{ name: "Formats.IN", label: "in" }], + units: [{ name: "Formats.MILE" }, { name: "Formats.YRD", label: "" }, { name: "Formats.FT", label: "'" }, { + name: "Formats.IN", + label: "in", + }], }, }; it("async - null or empty unit label override", async () => { @@ -491,8 +542,16 @@ describe("KindOfQuantity", () => { // testInvalidFormatStrings("should throw for invalid override string with an empty string for unit", "Formats.DefaultReal[|label]", "Unable to locate SchemaItem ."); testInvalidFormatStrings("should throw for invalid override string with an invalid precision", "Formats.DefaultReal(banana)", ""); testInvalidFormatStrings("should throw for invalid override string without any overrides but still has commas", "Formats.DefaultReal(,,,,,)", ""); - testInvalidFormatStrings("should throw for invalid override string with 5 unit overrides", "Formats.DefaultReal[Formats.MILE|m][Formats.YRD|yard][Formats.FT|feet][Formats.IN|in][Formats.MILLIINCH|milli]", ""); - testInvalidFormatStrings("should throw for presentationUnit having a non-existent unit as an override", "Formats.DefaultReal[Formats.NonexistentUnit]", "Unable to locate SchemaItem Formats.NonexistentUnit."); + testInvalidFormatStrings( + "should throw for invalid override string with 5 unit overrides", + "Formats.DefaultReal[Formats.MILE|m][Formats.YRD|yard][Formats.FT|feet][Formats.IN|in][Formats.MILLIINCH|milli]", + "", + ); + testInvalidFormatStrings( + "should throw for presentationUnit having a non-existent unit as an override", + "Formats.DefaultReal[Formats.NonexistentUnit]", + "Unable to locate SchemaItem Formats.NonexistentUnit.", + ); }); describe("toJSON", () => { diff --git a/core/ecschema-metadata/src/test/Metadata/Mixin.test.ts b/core/ecschema-metadata/src/test/Metadata/Mixin.test.ts index 779c829aac85..e0ec991475ed 100644 --- a/core/ecschema-metadata/src/test/Metadata/Mixin.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Mixin.test.ts @@ -19,7 +19,6 @@ import { createEmptyXmlDocument, getElementChildrenByTagName } from "../TestUtil /* eslint-disable @typescript-eslint/naming-convention */ describe("Mixin", () => { - function createSchemaJson(mixinJson: any): any { return createSchemaJsonWithItems({ TestMixin: { @@ -160,7 +159,10 @@ describe("Mixin", () => { const json = createSchemaJson({ appliesTo: 0, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Mixin TestSchema.TestMixin has an invalid 'appliesTo' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Mixin TestSchema.TestMixin has an invalid 'appliesTo' attribute. It should be of type 'string'.`, + ); }); it("applicableTo, wrong entity, fails", async () => { diff --git a/core/ecschema-metadata/src/test/Metadata/OverrideFormat.test.ts b/core/ecschema-metadata/src/test/Metadata/OverrideFormat.test.ts index ef152080962d..745cb42cd589 100644 --- a/core/ecschema-metadata/src/test/Metadata/OverrideFormat.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/OverrideFormat.test.ts @@ -3,6 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { FormatTraits, FractionalPrecision, ShowSignOption } from "@itwin/core-quantity"; import { assert, expect } from "chai"; import { SchemaContext } from "../../Context"; import { Format } from "../../Metadata/Format"; @@ -10,7 +11,6 @@ import { InvertedUnit } from "../../Metadata/InvertedUnit"; import { OverrideFormat } from "../../Metadata/OverrideFormat"; import { Schema } from "../../Metadata/Schema"; import { Unit } from "../../Metadata/Unit"; -import { FormatTraits, FractionalPrecision, ShowSignOption } from "@itwin/core-quantity"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; import { TestSchemaLocater } from "../TestUtils/FormatTestHelper"; diff --git a/core/ecschema-metadata/src/test/Metadata/Property.test.ts b/core/ecschema-metadata/src/test/Metadata/Property.test.ts index f278620c0818..1f6c81938780 100644 --- a/core/ecschema-metadata/src/test/Metadata/Property.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Property.test.ts @@ -15,8 +15,15 @@ import { EntityClass } from "../../Metadata/EntityClass"; import { Enumeration } from "../../Metadata/Enumeration"; import { KindOfQuantity } from "../../Metadata/KindOfQuantity"; import { - EnumerationArrayProperty, EnumerationProperty, MutableProperty, NavigationProperty, PrimitiveArrayProperty, PrimitiveProperty, Property, - StructArrayProperty, StructProperty, + EnumerationArrayProperty, + EnumerationProperty, + MutableProperty, + NavigationProperty, + PrimitiveArrayProperty, + PrimitiveProperty, + Property, + StructArrayProperty, + StructProperty, } from "../../Metadata/Property"; import { PropertyCategory } from "../../Metadata/PropertyCategory"; import { RelationshipClass } from "../../Metadata/RelationshipClass"; @@ -161,8 +168,10 @@ describe("Property", () => { category: "TestSchema.NonExistentPropertyCategory", }; await testProp.fromJSON(propertyJson); - await expect(testProp.category).to.be.rejectedWith(ECObjectsError, `The Property BadProp has a 'category' ("TestSchema.NonExistentPropertyCategory") that cannot be found.`); - + await expect(testProp.category).to.be.rejectedWith( + ECObjectsError, + `The Property BadProp has a 'category' ("TestSchema.NonExistentPropertyCategory") that cannot be found.`, + ); }); it("should throw for non-existent kindOfQuantity", async () => { @@ -173,7 +182,10 @@ describe("Property", () => { kindOfQuantity: "TestSchema.NonExistentKindOfQuantity", }; await testProp.fromJSON(propertyJson); - await expect(testProp.kindOfQuantity).to.be.rejectedWith(ECObjectsError, `The Property BadProp has a 'kindOfQuantity' ("TestSchema.NonExistentKindOfQuantity") that cannot be found.`); + await expect(testProp.kindOfQuantity).to.be.rejectedWith( + ECObjectsError, + `The Property BadProp has a 'kindOfQuantity' ("TestSchema.NonExistentKindOfQuantity") that cannot be found.`, + ); }); }); @@ -531,7 +543,7 @@ describe("Property", () => { property.addCustomAttribute(ca); const serialized = await property.toXml(newDom); - const expectedTimeFromString = new Date("2021-08-19T16:37:42.278").getTime(); + const expectedTimeFromString = new Date("2021-08-19T16:37:42.278").getTime(); let element = getCAPropertyValueElement(serialized, "TestCustomAttribute", "TrueBoolean"); expect(element.textContent).to.equal("True"); @@ -1408,4 +1420,3 @@ describe("NavigationProperty (Deserialization not fully implemented)", () => { }); }); }); - diff --git a/core/ecschema-metadata/src/test/Metadata/PropertyCategory.test.ts b/core/ecschema-metadata/src/test/Metadata/PropertyCategory.test.ts index 9ec05323aa07..05d613d2fcb4 100644 --- a/core/ecschema-metadata/src/test/Metadata/PropertyCategory.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/PropertyCategory.test.ts @@ -8,8 +8,8 @@ import { SchemaContext } from "../../Context"; import { SchemaItemType } from "../../ECObjects"; import { PropertyCategory } from "../../Metadata/PropertyCategory"; import { Schema } from "../../Metadata/Schema"; -import { createEmptyXmlDocument } from "../TestUtils/SerializationHelper"; import { createSchemaJsonWithItems } from "../TestUtils/DeserializationHelpers"; +import { createEmptyXmlDocument } from "../TestUtils/SerializationHelper"; /* eslint-disable @typescript-eslint/naming-convention */ diff --git a/core/ecschema-metadata/src/test/Metadata/PropertyInheritance.test.ts b/core/ecschema-metadata/src/test/Metadata/PropertyInheritance.test.ts index f7c28ca33e31..561c8f299a4b 100644 --- a/core/ecschema-metadata/src/test/Metadata/PropertyInheritance.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/PropertyInheritance.test.ts @@ -34,7 +34,8 @@ describe("Property Inheritance", () => { ], }, MiddleClass: { - schemaItemType: "StructClass", baseClass: "TestSchema.RootClass", + schemaItemType: "StructClass", + baseClass: "TestSchema.RootClass", properties: [ { name: "P2", type: "PrimitiveProperty", typeName: "string" }, { name: "P1", type: "PrimitiveProperty", typeName: "string" }, @@ -42,10 +43,12 @@ describe("Property Inheritance", () => { ], }, TestClass: { - schemaItemType: "StructClass", baseClass: "TestSchema.MiddleClass", + schemaItemType: "StructClass", + baseClass: "TestSchema.MiddleClass", properties: [ { name: "P4", type: "PrimitiveProperty", typeName: "string" }, - { name: "P3", type: "PrimitiveProperty", typeName: "string" }], + { name: "P3", type: "PrimitiveProperty", typeName: "string" }, + ], }, }, }; @@ -89,7 +92,8 @@ describe("Property Inheritance", () => { ], }, MiddleClass: { - schemaItemType: "EntityClass", baseClass: "TestSchema.RootClass", + schemaItemType: "EntityClass", + baseClass: "TestSchema.RootClass", properties: [ { name: "P2", type: "PrimitiveProperty", typeName: "string" }, { name: "P1", type: "PrimitiveProperty", typeName: "string" }, @@ -97,7 +101,8 @@ describe("Property Inheritance", () => { ], }, TestClass: { - schemaItemType: "EntityClass", baseClass: "TestSchema.MiddleClass", + schemaItemType: "EntityClass", + baseClass: "TestSchema.MiddleClass", properties: [ { name: "P4", type: "PrimitiveProperty", typeName: "string" }, { name: "P3", type: "PrimitiveProperty", typeName: "string" }, @@ -142,7 +147,8 @@ describe("Property Inheritance", () => { properties: [{ name: "P1", type: "PrimitiveProperty", typeName: "string" }], }, Mixin: { - schemaItemType: "Mixin", appliesTo: "TestSchema.RootClass", + schemaItemType: "Mixin", + appliesTo: "TestSchema.RootClass", properties: [{ name: "P5", type: "PrimitiveProperty", typeName: "string" }], }, TestClass: { schemaItemType: "EntityClass", baseClass: "TestSchema.RootClass", mixins: ["TestSchema.Mixin"] }, @@ -328,13 +334,15 @@ describe("Property Inheritance", () => { }, B: { schemaItemType: "Mixin", appliesTo: "TestSchema.A" }, C: { - schemaItemType: "Mixin", appliesTo: "TestSchema.A", + schemaItemType: "Mixin", + appliesTo: "TestSchema.A", properties: [ { name: "P3", type: "PrimitiveProperty", typeName: "string" }, ], }, D: { - schemaItemType: "Mixin", appliesTo: "TestSchema.A", + schemaItemType: "Mixin", + appliesTo: "TestSchema.A", properties: [ { name: "P4", type: "PrimitiveProperty", typeName: "string" }, ], @@ -342,11 +350,15 @@ describe("Property Inheritance", () => { E: { schemaItemType: "Mixin", appliesTo: "TestSchema.A", baseClass: "TestSchema.C" }, F: { schemaItemType: "Mixin", appliesTo: "TestSchema.A", baseClass: "TestSchema.D" }, G: { - schemaItemType: "EntityClass", baseClass: "TestSchema.A", mixins: ["TestSchema.B"], + schemaItemType: "EntityClass", + baseClass: "TestSchema.A", + mixins: ["TestSchema.B"], properties: [{ name: "P1", type: "PrimitiveProperty", typeName: "string" }], }, H: { - schemaItemType: "EntityClass", baseClass: "TestSchema.G", mixins: ["TestSchema.E", "TestSchema.F"], + schemaItemType: "EntityClass", + baseClass: "TestSchema.G", + mixins: ["TestSchema.E", "TestSchema.F"], properties: [{ name: "P2", type: "PrimitiveProperty", typeName: "string" }], }, }, diff --git a/core/ecschema-metadata/src/test/Metadata/Quantity.test.ts b/core/ecschema-metadata/src/test/Metadata/Quantity.test.ts index 609f08476d10..26aba5efbf9b 100644 --- a/core/ecschema-metadata/src/test/Metadata/Quantity.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Quantity.test.ts @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Format as QFormat, Formatter, FormatterSpec, Parser, ParserSpec, UnitProps } from "@itwin/core-quantity"; import { assert } from "chai"; +import * as fs from "fs"; +import * as path from "path"; import { SchemaContext } from "../../Context"; import { SchemaItemFormatProps } from "../../Deserialization/JsonProps"; +import { SchemaKey, SchemaMatchType, SchemaUnitProvider } from "../../ecschema-metadata"; import { Format } from "../../Metadata/Format"; import { MutableSchema, Schema } from "../../Metadata/Schema"; -import { Formatter, FormatterSpec, Parser, ParserSpec, Format as QFormat, UnitProps } from "@itwin/core-quantity"; import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; -import { SchemaKey, SchemaMatchType, SchemaUnitProvider } from "../../ecschema-metadata"; -import * as fs from "fs"; -import * as path from "path"; describe("Quantity", () => { let schema: Schema; @@ -35,7 +35,7 @@ describe("Quantity", () => { units: [ { name: "Units.ARC_DEG", label: "°" }, { name: "Units.ARC_MINUTE", label: "'" }, - { name: "Units.ARC_SECOND", label: "\"" }, + { name: "Units.ARC_SECOND", label: '"' }, ], }, }; @@ -76,8 +76,6 @@ describe("Quantity", () => { const formatterResult = Formatter.formatQuantity(value, bearingDMSFormatter); assert.equal(formatterResult, inputString); - }); - }); }); diff --git a/core/ecschema-metadata/src/test/Metadata/Relationship.test.ts b/core/ecschema-metadata/src/test/Metadata/Relationship.test.ts index cc19bcb63b90..fe03bfa58d2c 100644 --- a/core/ecschema-metadata/src/test/Metadata/Relationship.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Relationship.test.ts @@ -108,7 +108,6 @@ describe("RelationshipClass", () => { }); describe("deserialization", () => { - function createSchemaJson(relClassJson: any): any { return { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", @@ -307,7 +306,10 @@ describe("RelationshipClass", () => { strengthDirection: "backward", target: validConstraint, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The RelationshipClass TestSchema.TestRelationship is missing the required source constraint.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The RelationshipClass TestSchema.TestRelationship is missing the required source constraint.`, + ); }); it("should throw for missing target constraint", async () => { @@ -316,7 +318,10 @@ describe("RelationshipClass", () => { strengthDirection: "forward", source: validConstraint, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The RelationshipClass TestSchema.TestRelationship is missing the required target constraint.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The RelationshipClass TestSchema.TestRelationship is missing the required target constraint.`, + ); }); it("should throw for invalid source constraint", async () => { @@ -326,7 +331,10 @@ describe("RelationshipClass", () => { source: 0, target: validConstraint, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The RelationshipClass TestSchema.TestRelationship has an invalid source constraint. It should be of type 'object'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The RelationshipClass TestSchema.TestRelationship has an invalid source constraint. It should be of type 'object'.`, + ); }); it("should throw for invalid target constraint", async () => { @@ -336,7 +344,10 @@ describe("RelationshipClass", () => { source: validConstraint, target: 0, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The RelationshipClass TestSchema.TestRelationship has an invalid target constraint. It should be of type 'object'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The RelationshipClass TestSchema.TestRelationship has an invalid target constraint. It should be of type 'object'.`, + ); }); it("should throw for invalid abstractConstraint", async () => { @@ -354,7 +365,10 @@ describe("RelationshipClass", () => { }, target: {}, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Source Constraint of TestSchema.TestRelationship has an invalid 'abstractConstraint' attribute. It should be of type 'string'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Source Constraint of TestSchema.TestRelationship has an invalid 'abstractConstraint' attribute. It should be of type 'string'.`, + ); }); it("should throw for invalid constraintClasses", async () => { @@ -369,7 +383,10 @@ describe("RelationshipClass", () => { }, target: {}, }); - await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Source Constraint of TestSchema.TestRelationship has an invalid 'constraintClasses' attribute. It should be of type 'string[]'.`); + await expect(Schema.fromJson(json, new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Source Constraint of TestSchema.TestRelationship has an invalid 'constraintClasses' attribute. It should be of type 'string[]'.`, + ); }); }); diff --git a/core/ecschema-metadata/src/test/Metadata/Schema.test.ts b/core/ecschema-metadata/src/test/Metadata/Schema.test.ts index 54665449a03d..cb3b589079bc 100644 --- a/core/ecschema-metadata/src/test/Metadata/Schema.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Schema.test.ts @@ -5,6 +5,8 @@ import { assert, expect } from "chai"; import { SchemaContext } from "../../Context"; +import { SchemaReadHelper } from "../../Deserialization/Helper"; +import { XmlParser } from "../../Deserialization/XmlParser"; import { SchemaItemType } from "../../ECObjects"; import { ECObjectsError } from "../../Exception"; import { AnySchemaItem } from "../../Interfaces"; @@ -12,13 +14,22 @@ import { ECClass, StructClass } from "../../Metadata/Class"; import { EntityClass } from "../../Metadata/EntityClass"; import { Mixin } from "../../Metadata/Mixin"; import { MutableSchema, Schema } from "../../Metadata/Schema"; -import { createEmptyXmlDocument, getElementChildren, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; -import { SchemaReadHelper } from "../../Deserialization/Helper"; -import { XmlParser } from "../../Deserialization/XmlParser"; import { SchemaKey } from "../../SchemaKey"; +import { createEmptyXmlDocument, getElementChildren, getElementChildrenByTagName } from "../TestUtils/SerializationHelper"; -import { Constant, CustomAttributeClass, Enumeration, Format, KindOfQuantity, Phenomenon, PropertyCategory, SchemaItem, Unit, UnitSystem } from "../../ecschema-metadata"; import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; +import { + Constant, + CustomAttributeClass, + Enumeration, + Format, + KindOfQuantity, + Phenomenon, + PropertyCategory, + SchemaItem, + Unit, + UnitSystem, +} from "../../ecschema-metadata"; /* eslint-disable @typescript-eslint/naming-convention */ describe("Schema", () => { @@ -676,7 +687,10 @@ describe("Schema", () => { }; const testSchema = new Schema(new SchemaContext()); expect(testSchema).to.exist; - await expect(testSchema.fromJSON(propertyJson)).to.be.rejectedWith(ECObjectsError, "The Schema ValidSchema does not have the required 'alias' attribute."); + await expect(testSchema.fromJSON(propertyJson)).to.be.rejectedWith( + ECObjectsError, + "The Schema ValidSchema does not have the required 'alias' attribute.", + ); }); it("should throw for invalid $schema", async () => { @@ -688,8 +702,14 @@ describe("Schema", () => { const context = new SchemaContext(); const testSchema = new Schema(context, "InvalidSchema", "is", 1, 2, 3); expect(testSchema).to.exist; - await expect(testSchema.fromJSON(schemaJson as any)).to.be.rejectedWith(ECObjectsError, "The Schema InvalidSchema has an unsupported namespace 'https://badmetaschema.com'."); - await expect(Schema.fromJson(schemaJson as any, context)).to.be.rejectedWith(ECObjectsError, "The Schema InvalidSchema has an unsupported namespace 'https://badmetaschema.com'."); + await expect(testSchema.fromJSON(schemaJson as any)).to.be.rejectedWith( + ECObjectsError, + "The Schema InvalidSchema has an unsupported namespace 'https://badmetaschema.com'.", + ); + await expect(Schema.fromJson(schemaJson as any, context)).to.be.rejectedWith( + ECObjectsError, + "The Schema InvalidSchema has an unsupported namespace 'https://badmetaschema.com'.", + ); }); it("should throw for mismatched name", async () => { @@ -1040,7 +1060,10 @@ describe("Schema", () => { const context = new SchemaContext(); await context.addSchema(refSchema); - await expect(Schema.fromJson(schemaJson, context)).to.be.rejectedWith(ECObjectsError, "Could not locate the referenced schema, RefSchema.01.00.00, of ValidSchema"); + await expect(Schema.fromJson(schemaJson, context)).to.be.rejectedWith( + ECObjectsError, + "Could not locate the referenced schema, RefSchema.01.00.00, of ValidSchema", + ); }); describe("toXML", () => { @@ -1089,7 +1112,6 @@ describe("Schema", () => { }); it("Deserialize after Serialization", async () => { - const referenceJson = { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", name: "RefSchema", @@ -1107,8 +1129,7 @@ describe("Schema", () => { }, }; - const coreCASchema = - { + const coreCASchema = { $schema: "https://dev.bentley.com/json_schemas/ec/32/ecschema", alias: "CoreCA", description: "Custom attributes to indicate core EC concepts, may include struct classes intended for use in core custom attributes.", @@ -1119,7 +1140,8 @@ describe("Schema", () => { label: "Is Mixin", modifier: "Sealed", CoreCustomAttributes: [{ - description: "This mixin may only be applied to entity classes which derive from this class. Class Name should be fully specified as 'alias:ClassName'", + description: + "This mixin may only be applied to entity classes which derive from this class. Class Name should be fully specified as 'alias:ClassName'", name: "AppliesToEntityClass", type: "PrimitiveProperty", typeName: "string", @@ -1807,8 +1829,20 @@ describe("Schema", () => { MM: { schemaItemType: "Unit", label: "mm", phenomenon: "TestSchema.LENGTH", unitSystem: "TestSchema.SI", definition: "MM" }, FT: { schemaItemType: "Unit", label: "ft", phenomenon: "TestSchema.LENGTH", unitSystem: "TestSchema.SI", definition: "IN" }, - TestFormat: { schemaItemType:"Format", label:"testFormat", type:"Decimal", precision:6, formatTraits:["KeepSingleZero", "KeepDecimalPoint", "ShowUnitLabel"]}, - TestKoq: { schemaItemType:"KindOfQuantity", label:"testKoq", relativeError:0.00001, persistenceUnit:"TestSchema.M", ...presentationUnit}, + TestFormat: { + schemaItemType: "Format", + label: "testFormat", + type: "Decimal", + precision: 6, + formatTraits: ["KeepSingleZero", "KeepDecimalPoint", "ShowUnitLabel"], + }, + TestKoq: { + schemaItemType: "KindOfQuantity", + label: "testKoq", + relativeError: 0.00001, + persistenceUnit: "TestSchema.M", + ...presentationUnit, + }, }, }; @@ -1819,12 +1853,32 @@ describe("Schema", () => { } it("KoQ serialization with overriden formats", async () => { - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M][TestSchema.MM][TestSchema.FT]"]}), `presentationUnits="TestFormat(4)[M][MM][FT]"`); - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M][TestSchema.MM][TestSchema.FT|]"]}), `presentationUnits="TestFormat(4)[M][MM][FT|]"`); - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM][TestSchema.FT|]"]}), `presentationUnits="TestFormat(4)[M|alpha][MM][FT|]"`); - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT]"]}), `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT]"`); - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT|]"]}), `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT|]"`); - assert.deepEqual(await testKoQSerialization({presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT|charlie]"]}), `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT|charlie]"`); + assert.deepEqual( + await testKoQSerialization({ presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M][TestSchema.MM][TestSchema.FT]"] }), + `presentationUnits="TestFormat(4)[M][MM][FT]"`, + ); + assert.deepEqual( + await testKoQSerialization({ presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M][TestSchema.MM][TestSchema.FT|]"] }), + `presentationUnits="TestFormat(4)[M][MM][FT|]"`, + ); + assert.deepEqual( + await testKoQSerialization({ presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM][TestSchema.FT|]"] }), + `presentationUnits="TestFormat(4)[M|alpha][MM][FT|]"`, + ); + assert.deepEqual( + await testKoQSerialization({ presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT]"] }), + `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT]"`, + ); + assert.deepEqual( + await testKoQSerialization({ presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT|]"] }), + `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT|]"`, + ); + assert.deepEqual( + await testKoQSerialization({ + presentationUnits: ["TestSchema.TestFormat(4)[TestSchema.M|alpha][TestSchema.MM|bravo][TestSchema.FT|charlie]"], + }), + `presentationUnits="TestFormat(4)[M|alpha][MM|bravo][FT|charlie]"`, + ); }); async function testCompositeFormatSerialization(compositeFormat: any): Promise { @@ -1841,7 +1895,14 @@ describe("Schema", () => { MM: { schemaItemType: "Unit", label: "mm", phenomenon: "TestSchema.LENGTH", unitSystem: "TestSchema.SI", definition: "MM" }, FT: { schemaItemType: "Unit", label: "ft", phenomenon: "TestSchema.LENGTH", unitSystem: "TestSchema.SI", definition: "IN" }, - TestFormat: { schemaItemType:"Format", label:"testFormat", type:"Decimal", precision:6, formatTraits:["KeepSingleZero", "KeepDecimalPoint", "ShowUnitLabel"], composite:{...compositeFormat}}, + TestFormat: { + schemaItemType: "Format", + label: "testFormat", + type: "Decimal", + precision: 6, + formatTraits: ["KeepSingleZero", "KeepDecimalPoint", "ShowUnitLabel"], + composite: { ...compositeFormat }, + }, }, }; @@ -1853,17 +1914,31 @@ describe("Schema", () => { } it("Composite format serialization with overriden formats", async () => { - assert.deepEqual(await testCompositeFormatSerialization({units:[{name:"TestSchema.M"},{name:"TestSchema.MM"},{name:"TestSchema.FT"}]}), - `MMMFT`); - - assert.deepEqual(await testCompositeFormatSerialization({units:[{name:"TestSchema.M",label:"metre"},{name:"TestSchema.MM"},{name:"TestSchema.FT"}]}), - `MMMFT`); - - assert.deepEqual(await testCompositeFormatSerialization({units:[{name:"TestSchema.M",label:"metre"},{name:"TestSchema.MM", label:""},{name:"TestSchema.FT"}]}), - `MMMFT`); - - assert.deepEqual(await testCompositeFormatSerialization({units:[{name:"TestSchema.M",label:"metre"},{name:"TestSchema.MM", label:""},{name:"TestSchema.FT", label: "\""}]}), - `MMMFT`); + assert.deepEqual( + await testCompositeFormatSerialization({ units: [{ name: "TestSchema.M" }, { name: "TestSchema.MM" }, { name: "TestSchema.FT" }] }), + `MMMFT`, + ); + + assert.deepEqual( + await testCompositeFormatSerialization({ + units: [{ name: "TestSchema.M", label: "metre" }, { name: "TestSchema.MM" }, { name: "TestSchema.FT" }], + }), + `MMMFT`, + ); + + assert.deepEqual( + await testCompositeFormatSerialization({ + units: [{ name: "TestSchema.M", label: "metre" }, { name: "TestSchema.MM", label: "" }, { name: "TestSchema.FT" }], + }), + `MMMFT`, + ); + + assert.deepEqual( + await testCompositeFormatSerialization({ + units: [{ name: "TestSchema.M", label: "metre" }, { name: "TestSchema.MM", label: "" }, { name: "TestSchema.FT", label: '"' }], + }), + `MMMFT`, + ); }); }); }); // Schema tests diff --git a/core/ecschema-metadata/src/test/Metadata/SchemaFromJson.test.ts b/core/ecschema-metadata/src/test/Metadata/SchemaFromJson.test.ts index 2bda4d569f8f..154a350cdfd3 100644 --- a/core/ecschema-metadata/src/test/Metadata/SchemaFromJson.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/SchemaFromJson.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { SchemaContext } from "../../Context"; -import { Schema } from "../../Metadata/Schema"; import { ECObjectsError } from "../../Exception"; +import { Schema } from "../../Metadata/Schema"; describe("Schema from json creation with different containers tests", () => { let context: SchemaContext; @@ -91,7 +91,10 @@ describe("Schema from json creation with different containers tests", () => { }, }; - await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith(ECObjectsError, "Unable to load custom attribute DummyReference.customAttributeOne from container SchemaA.testClassOne, DummyReference reference not defined"); + await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith( + ECObjectsError, + "Unable to load custom attribute DummyReference.customAttributeOne from container SchemaA.testClassOne, DummyReference reference not defined", + ); }); it("should throw an error not allow the creation of a schema with relationship class and custom attribute and no reference defined", async () => { @@ -151,7 +154,10 @@ describe("Schema from json creation with different containers tests", () => { }, }; - await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith(ECObjectsError, "Unable to load custom attribute DummyReference.customAttributeOne from container SchemaA.relationshipOne, DummyReference reference not defined"); + await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith( + ECObjectsError, + "Unable to load custom attribute DummyReference.customAttributeOne from container SchemaA.relationshipOne, DummyReference reference not defined", + ); }); }); @@ -192,7 +198,10 @@ describe("Schema from json creation with different containers tests", () => { }, }; - await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith(ECObjectsError, "Unable to load custom attribute DummyReference.customAttributeOne from container testClassOne.Offset, DummyReference reference not defined"); + await expect(Schema.fromJson(schemaA, context)).to.be.rejectedWith( + ECObjectsError, + "Unable to load custom attribute DummyReference.customAttributeOne from container testClassOne.Offset, DummyReference reference not defined", + ); }); }); }); diff --git a/core/ecschema-metadata/src/test/Metadata/SchemaItem.test.ts b/core/ecschema-metadata/src/test/Metadata/SchemaItem.test.ts index a42479844426..0b7638f90839 100644 --- a/core/ecschema-metadata/src/test/Metadata/SchemaItem.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/SchemaItem.test.ts @@ -5,9 +5,9 @@ import { assert, expect } from "chai"; import { SchemaContext } from "../../Context"; -import { SchemaItem } from "../../Metadata/SchemaItem"; import { EntityClass } from "../../Metadata/EntityClass"; import { Schema } from "../../Metadata/Schema"; +import { SchemaItem } from "../../Metadata/SchemaItem"; import { SchemaItemKey, SchemaKey } from "../../SchemaKey"; import { createEmptyXmlDocument } from "../TestUtils/SerializationHelper"; diff --git a/core/ecschema-metadata/src/test/Metadata/Unit.test.ts b/core/ecschema-metadata/src/test/Metadata/Unit.test.ts index d2ac5eeb873c..e957c6177674 100644 --- a/core/ecschema-metadata/src/test/Metadata/Unit.test.ts +++ b/core/ecschema-metadata/src/test/Metadata/Unit.test.ts @@ -16,7 +16,6 @@ import { createEmptyXmlDocument } from "../TestUtils/SerializationHelper"; /* eslint-disable @typescript-eslint/naming-convention */ describe("Unit", () => { - function createSchemaJson(unitJson: any): any { return createSchemaJsonWithItems({ TestUnit: { @@ -142,10 +141,17 @@ describe("Unit", () => { definition: "[MILLI]*Units.M", }; it("async - should throw for missing phenomenon", async () => { - await expect(Schema.fromJson(createSchemaJson(missingPhenomenonJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'phenomenon' attribute.`); + await expect(Schema.fromJson(createSchemaJson(missingPhenomenonJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'phenomenon' attribute.`, + ); }); it("sync - should throw for missing phenomenon", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(missingPhenomenonJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'phenomenon' attribute.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(missingPhenomenonJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'phenomenon' attribute.`, + ); }); // Invalid phenomenon @@ -155,10 +161,17 @@ describe("Unit", () => { definition: "[MILLI]*Units.M", }; it("async - should throw for invalid phenomenon", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidPhenomenonJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'phenomenon' attribute. It should be of type 'string'`); + await expect(Schema.fromJson(createSchemaJson(invalidPhenomenonJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'phenomenon' attribute. It should be of type 'string'`, + ); }); it("sync - should throw for invalid phenomenon", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidPhenomenonJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'phenomenon' attribute. It should be of type 'string'`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidPhenomenonJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'phenomenon' attribute. It should be of type 'string'`, + ); }); // Missing UnitSystem @@ -167,10 +180,17 @@ describe("Unit", () => { definition: "[MILLI]*Units.M", }; it("async - should throw for missing unit system", async () => { - await expect(Schema.fromJson(createSchemaJson(missingUnitSystemJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'unitSystem' attribute.`); + await expect(Schema.fromJson(createSchemaJson(missingUnitSystemJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'unitSystem' attribute.`, + ); }); it("sync - should throw for missing unit system", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(missingUnitSystemJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'unitSystem' attribute.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(missingUnitSystemJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'unitSystem' attribute.`, + ); }); // Invalid UnitSystem @@ -180,10 +200,17 @@ describe("Unit", () => { definition: "[MILLI]*Units.M", }; it("async - should throw for invalid unit system", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidUnitSystemJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'unitSystem' attribute. It should be of type 'string'`); + await expect(Schema.fromJson(createSchemaJson(invalidUnitSystemJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'unitSystem' attribute. It should be of type 'string'`, + ); }); it("sync - should throw for invalid unit system", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidUnitSystemJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'unitSystem' attribute. It should be of type 'string'`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidUnitSystemJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'unitSystem' attribute. It should be of type 'string'`, + ); }); // Missing Definition @@ -192,10 +219,17 @@ describe("Unit", () => { unitSystem: "TestSchema.TestUnitSystem", }; it("async - should throw for missing definition", async () => { - await expect(Schema.fromJson(createSchemaJson(missingDefinitionJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'definition' attribute.`); + await expect(Schema.fromJson(createSchemaJson(missingDefinitionJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'definition' attribute.`, + ); }); it("sync - should throw for missing definition", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(missingDefinitionJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit does not have the required 'definition' attribute.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(missingDefinitionJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit does not have the required 'definition' attribute.`, + ); }); // Missing Definition @@ -205,10 +239,17 @@ describe("Unit", () => { unitSystem: "TestSchema.TestUnitSystem", }; it("async - should throw for invalid definition", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidDefinitionJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'definition' attribute. It should be of type 'string'`); + await expect(Schema.fromJson(createSchemaJson(invalidDefinitionJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'definition' attribute. It should be of type 'string'`, + ); }); it("sync - should throw for invalid definition", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidDefinitionJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'definition' attribute. It should be of type 'string'`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidDefinitionJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'definition' attribute. It should be of type 'string'`, + ); }); // Invalid numerator @@ -219,10 +260,17 @@ describe("Unit", () => { numerator: "5", }; it("async - should throw for invalid numerator", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidNumeratorJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'numerator' attribute. It should be of type 'number'.`); + await expect(Schema.fromJson(createSchemaJson(invalidNumeratorJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'numerator' attribute. It should be of type 'number'.`, + ); }); it("sync - should throw for invalid numerator", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidNumeratorJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'numerator' attribute. It should be of type 'number'.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidNumeratorJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'numerator' attribute. It should be of type 'number'.`, + ); }); // Invalid denominator @@ -233,10 +281,17 @@ describe("Unit", () => { denominator: "5", }; it("async - should throw for invalid denominator", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidDenominatorJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'denominator' attribute. It should be of type 'number'.`); + await expect(Schema.fromJson(createSchemaJson(invalidDenominatorJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'denominator' attribute. It should be of type 'number'.`, + ); }); it("sync - should throw for invalid denominator", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidDenominatorJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'denominator' attribute. It should be of type 'number'.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidDenominatorJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'denominator' attribute. It should be of type 'number'.`, + ); }); // Invalid offset @@ -247,10 +302,17 @@ describe("Unit", () => { offset: "5", }; it("async - should throw for invalid offset", async () => { - await expect(Schema.fromJson(createSchemaJson(invalidOffsetJson), new SchemaContext())).to.be.rejectedWith(ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'offset' attribute. It should be of type 'number'.`); + await expect(Schema.fromJson(createSchemaJson(invalidOffsetJson), new SchemaContext())).to.be.rejectedWith( + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'offset' attribute. It should be of type 'number'.`, + ); }); it("sync - should throw for invalid offset", () => { - assert.throws(() => Schema.fromJsonSync(createSchemaJson(invalidOffsetJson), new SchemaContext()), ECObjectsError, `The Unit TestSchema.TestUnit has an invalid 'offset' attribute. It should be of type 'number'.`); + assert.throws( + () => Schema.fromJsonSync(createSchemaJson(invalidOffsetJson), new SchemaContext()), + ECObjectsError, + `The Unit TestSchema.TestUnit has an invalid 'offset' attribute. It should be of type 'number'.`, + ); }); }); diff --git a/core/ecschema-metadata/src/test/ParseUtils.test.ts b/core/ecschema-metadata/src/test/ParseUtils.test.ts index 438cabfcfa30..97634cb69917 100644 --- a/core/ecschema-metadata/src/test/ParseUtils.test.ts +++ b/core/ecschema-metadata/src/test/ParseUtils.test.ts @@ -5,9 +5,25 @@ import { expect } from "chai"; import { - classModifierToString, containerTypeToString, CustomAttributeContainerType, ECClassModifier, parseClassModifier, parseCustomAttributeContainerType, - parsePrimitiveType, parseRelationshipEnd, parseSchemaItemType, parseStrength, parseStrengthDirection, PrimitiveType, primitiveTypeToString, - RelationshipEnd, relationshipEndToString, SchemaItemType, StrengthDirection, strengthDirectionToString, strengthToString, + classModifierToString, + containerTypeToString, + CustomAttributeContainerType, + ECClassModifier, + parseClassModifier, + parseCustomAttributeContainerType, + parsePrimitiveType, + parseRelationshipEnd, + parseSchemaItemType, + parseStrength, + parseStrengthDirection, + PrimitiveType, + primitiveTypeToString, + RelationshipEnd, + relationshipEndToString, + SchemaItemType, + StrengthDirection, + strengthDirectionToString, + strengthToString, StrengthType, } from "../ECObjects"; import { ECObjectsError, ECObjectsStatus } from "../Exception"; @@ -77,7 +93,10 @@ describe("Parsing/ToString Functions", () => { expect(parseCustomAttributeContainerType("TarGETreLATIoNShIPCOnSTrAInT")).to.equal(CustomAttributeContainerType.TargetRelationshipConstraint); expect(parseCustomAttributeContainerType("AnyRELaTioNShiPCoNSTrAInt")).to.equal(CustomAttributeContainerType.AnyRelationshipConstraint); expect(parseCustomAttributeContainerType("aNy")).to.equal(CustomAttributeContainerType.Any); - expect(() => parseCustomAttributeContainerType("invalid type")).to.throw(ECObjectsError, "invalid type is not a valid CustomAttributeContainerType value."); + expect(() => parseCustomAttributeContainerType("invalid type")).to.throw( + ECObjectsError, + "invalid type is not a valid CustomAttributeContainerType value.", + ); const combo = CustomAttributeContainerType.Schema | CustomAttributeContainerType.AnyClass @@ -189,7 +208,9 @@ describe("ECObjectsError ", () => { expect(new ECObjectsError(ECObjectsStatus.InvalidPrimitiveType, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidPrimitiveType: msg"); expect(new ECObjectsError(ECObjectsStatus.InvalidSchemaItemType, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidSchemaItemType: msg"); expect(new ECObjectsError(ECObjectsStatus.InvalidStrength, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidStrength: msg"); - expect(new ECObjectsError(ECObjectsStatus.InvalidStrengthDirection, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidStrengthDirection: msg"); + expect(new ECObjectsError(ECObjectsStatus.InvalidStrengthDirection, "msg").toDebugString()).to.equal( + "ECObjectsStatus.InvalidStrengthDirection: msg", + ); expect(new ECObjectsError(ECObjectsStatus.InvalidRelationshipEnd, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidRelationshipEnd: msg"); expect(new ECObjectsError(ECObjectsStatus.InvalidType, "msg").toDebugString()).to.equal("ECObjectsStatus.InvalidType: msg"); expect(new ECObjectsError(ECObjectsStatus.MissingSchemaUrl, "msg").toDebugString()).to.equal("ECObjectsStatus.MissingSchemaUrl: msg"); diff --git a/core/ecschema-metadata/src/test/SchemaKey.test.ts b/core/ecschema-metadata/src/test/SchemaKey.test.ts index f6badcd8798f..ae61daa6e418 100644 --- a/core/ecschema-metadata/src/test/SchemaKey.test.ts +++ b/core/ecschema-metadata/src/test/SchemaKey.test.ts @@ -42,7 +42,6 @@ describe("SchemaKey", () => { }); describe("compareByName", () => { - it("should compare against a string", () => { const key = new SchemaKey("SchemaName", 1, 2, 3); expect(key.compareByName("SchemaName")).to.be.true; @@ -136,20 +135,18 @@ describe("SchemaKey", () => { expect(new SchemaKey("SchemaTest", 1, 0, 0).matches(new SchemaKey("SchemaTest", 1, 0, 0), -1 as SchemaMatchType)).false; }); }); - }); describe("fromJSON", () => { let testKey2: SchemaKey; it("should return a SchemaKey given a SchemaKeyProp using fromJson", async () => { - testKey2 = SchemaKey.fromJSON({name: "testKey2", read: 1, write: 0, minor: 12}); + testKey2 = SchemaKey.fromJSON({ name: "testKey2", read: 1, write: 0, minor: 12 }); expect(testKey2).to.not.eql(undefined); expect(testKey2.name).to.eql("testKey2"); expect(testKey2.readVersion).to.eql(1); expect(testKey2.writeVersion).to.eql(0); expect(testKey2.minorVersion).to.eql(12); - }); }); @@ -164,7 +161,7 @@ describe("SchemaKey", () => { }); it("should return a schemaKeyProps given a different test key", () => { - const testKey2 = new SchemaKey("testKey2", new ECVersion(4,16,25)); + const testKey2 = new SchemaKey("testKey2", new ECVersion(4, 16, 25)); schemaKeyProps = testKey2.toJSON(); expect(schemaKeyProps.name).to.eql("testKey2"); expect(schemaKeyProps.read).to.eql(4); diff --git a/core/ecschema-metadata/src/test/SchemaPartVisitorDelegate.test.ts b/core/ecschema-metadata/src/test/SchemaPartVisitorDelegate.test.ts index 03c2dca644ed..56b64614a55d 100644 --- a/core/ecschema-metadata/src/test/SchemaPartVisitorDelegate.test.ts +++ b/core/ecschema-metadata/src/test/SchemaPartVisitorDelegate.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; +import * as sinon from "sinon"; import { SchemaContext } from "../Context"; import { PrimitiveType, RelationshipEnd } from "../ECObjects"; import { ECClass, MutableClass, StructClass } from "../Metadata/Class"; @@ -22,7 +23,6 @@ import { Schema } from "../Metadata/Schema"; import { Unit } from "../Metadata/Unit"; import { UnitSystem } from "../Metadata/UnitSystem"; import { SchemaPartVisitorDelegate } from "../SchemaPartVisitorDelegate"; -import * as sinon from "sinon"; describe("SchemaPartVisitorDelegate Tests", () => { let schema: Schema; diff --git a/core/ecschema-metadata/src/test/TestUtils/BisTestHelper.ts b/core/ecschema-metadata/src/test/TestUtils/BisTestHelper.ts index f9c5ebca528b..111de0a1d2bf 100644 --- a/core/ecschema-metadata/src/test/TestUtils/BisTestHelper.ts +++ b/core/ecschema-metadata/src/test/TestUtils/BisTestHelper.ts @@ -57,13 +57,15 @@ const bisCoreSchema = { }, IParentElement: { appliesTo: "BisCore.Element", - description: "An interface that indicates that this Element is capable of being a parent (owning child Elements). This interface is mutually exclusive with ISubModeledElement.", + description: + "An interface that indicates that this Element is capable of being a parent (owning child Elements). This interface is mutually exclusive with ISubModeledElement.", label: "Parent Element", schemaItemType: "Mixin", }, ISubModeledElement: { appliesTo: "BisCore.Element", - description: "An interface which indicates that an Element can be broken down or described by a (sub) Model. This interface is mutually exclusive with IParentElement.", + description: + "An interface which indicates that an Element can be broken down or described by a (sub) Model. This interface is mutually exclusive with IParentElement.", label: "Modellable Element", schemaItemType: "Mixin", }, diff --git a/core/ecschema-metadata/src/test/TestUtils/DeserializationHelpers.ts b/core/ecschema-metadata/src/test/TestUtils/DeserializationHelpers.ts index 437c23402092..d38705e48066 100644 --- a/core/ecschema-metadata/src/test/TestUtils/DeserializationHelpers.ts +++ b/core/ecschema-metadata/src/test/TestUtils/DeserializationHelpers.ts @@ -8,9 +8,9 @@ import { ISchemaLocater, SchemaContext } from "../../Context"; import { SchemaReadHelper } from "../../Deserialization/Helper"; import { XmlParser } from "../../Deserialization/XmlParser"; import { SchemaMatchType } from "../../ECObjects"; +import { SchemaInfo } from "../../Interfaces"; import { Schema } from "../../Metadata/Schema"; import { SchemaKey } from "../../SchemaKey"; -import { SchemaInfo } from "../../Interfaces"; export function createSchemaJsonWithItems(itemsJson: any, referenceJson?: any): any { return { @@ -28,7 +28,10 @@ export class ReferenceSchemaLocater implements ISchemaLocater { private readonly _parser: (schemaContent: any, context: SchemaContext) => Schema; private readonly _asyncParser: (SchemaContent: any, context: SchemaContext) => Promise; - constructor(parser: (schemaContent: any, context: SchemaContext) => Schema, asyncParser: (SchemaContent: any, context: SchemaContext) => Promise) { + constructor( + parser: (schemaContent: any, context: SchemaContext) => Schema, + asyncParser: (SchemaContent: any, context: SchemaContext) => Promise, + ) { this._schemaList = new Map(); this._parser = parser; this._asyncParser = asyncParser; @@ -56,7 +59,6 @@ export class ReferenceSchemaLocater implements ISchemaLocater { } public getSchemaSync(schemaKey: SchemaKey, _matchType: SchemaMatchType, context: SchemaContext): T | undefined { - if (this._schemaList.has(schemaKey.name)) { const schemaBody = this._schemaList.get(schemaKey.name); const schema = this._parser(schemaBody, context); diff --git a/core/ecschema-metadata/src/test/TestUtils/PerfTestHelper.ts b/core/ecschema-metadata/src/test/TestUtils/PerfTestHelper.ts index f77724e5232f..04dcb3d12f43 100644 --- a/core/ecschema-metadata/src/test/TestUtils/PerfTestHelper.ts +++ b/core/ecschema-metadata/src/test/TestUtils/PerfTestHelper.ts @@ -9,7 +9,6 @@ import * as Benchmark from "benchmark"; export async function comparePerformance(...funcs: Array<() => Promise>): Promise { const suite = new Benchmark.Suite(); return new Promise((resolve) => { - funcs.forEach((testFunc, i) => { suite.add(testFunc.name || String.fromCharCode(65 + i), { defer: true, @@ -22,7 +21,7 @@ export async function comparePerformance(...funcs: Array<() => Promise>): P suite.on("cycle", (event: any) => { console.log(String(event.target)); }); - suite.on("complete", function (this: any) { + suite.on("complete", function(this: any) { console.log(`Fastest is ${this.filter("fastest").map("name")}`); resolve(); }); @@ -39,7 +38,7 @@ export function comparePerformanceSync(...funcs: Array<() => any>): void { suite.on("cycle", (event: any) => { console.log(String(event.target)); }); - suite.on("complete", function (this: any) { + suite.on("complete", function(this: any) { console.log(`Fastest is ${this.filter("fastest").map("name")}`); }); suite.run({ async: false }); diff --git a/core/ecschema-metadata/src/test/UnitConversion/Convert.test.ts b/core/ecschema-metadata/src/test/UnitConversion/Convert.test.ts index ebf64929cfb6..5cd040adcfd2 100644 --- a/core/ecschema-metadata/src/test/UnitConversion/Convert.test.ts +++ b/core/ecschema-metadata/src/test/UnitConversion/Convert.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { almostEqual } from "@itwin/core-quantity"; +import { expect } from "chai"; import * as fs from "fs"; import * as path from "path"; -import { expect } from "chai"; import { SchemaContext } from "../../Context"; -import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; import { UnitConverter } from "../../UnitConversion/UnitConverter"; -import { almostEqual } from "@itwin/core-quantity"; +import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; interface TestData { from: string; diff --git a/core/ecschema-metadata/src/test/UnitConversion/CrossSchema.test.ts b/core/ecschema-metadata/src/test/UnitConversion/CrossSchema.test.ts index e5f94cb93517..5836759d92a2 100644 --- a/core/ecschema-metadata/src/test/UnitConversion/CrossSchema.test.ts +++ b/core/ecschema-metadata/src/test/UnitConversion/CrossSchema.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { almostEqual } from "@itwin/core-quantity"; +import { expect } from "chai"; import * as fs from "fs"; import * as path from "path"; -import { expect } from "chai"; import { SchemaContext } from "../../Context"; -import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; import { UnitConverter } from "../../UnitConversion/UnitConverter"; -import { almostEqual } from "@itwin/core-quantity"; +import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; interface TestData { fromSchema: string; diff --git a/core/ecschema-metadata/src/test/UnitConversion/Parser.test.ts b/core/ecschema-metadata/src/test/UnitConversion/Parser.test.ts index 76631f8ebb60..769453576e37 100644 --- a/core/ecschema-metadata/src/test/UnitConversion/Parser.test.ts +++ b/core/ecschema-metadata/src/test/UnitConversion/Parser.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { expect } from "chai"; import * as fs from "fs"; import * as path from "path"; -import { expect } from "chai"; import { DefinitionFragment, parseDefinition } from "../../UnitConversion/Parser"; describe("DefinitionParser tests", () => { diff --git a/core/ecschema-metadata/src/test/UnitConversion/Validation.test.ts b/core/ecschema-metadata/src/test/UnitConversion/Validation.test.ts index db291a4d593e..066ac70ffa3f 100644 --- a/core/ecschema-metadata/src/test/UnitConversion/Validation.test.ts +++ b/core/ecschema-metadata/src/test/UnitConversion/Validation.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { SchemaContext } from "../../Context"; import { expect } from "chai"; import * as fs from "fs"; import * as path from "path"; -import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; +import { SchemaContext } from "../../Context"; import { UnitConverter } from "../../UnitConversion/UnitConverter"; +import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; describe("Testing when unit conversion should throw", () => { const context = new SchemaContext(); diff --git a/core/ecschema-metadata/src/test/UnitProvider/UnitData.ts b/core/ecschema-metadata/src/test/UnitProvider/UnitData.ts index 5117b9edc352..fdaa239a599e 100644 --- a/core/ecschema-metadata/src/test/UnitProvider/UnitData.ts +++ b/core/ecschema-metadata/src/test/UnitProvider/UnitData.ts @@ -29,7 +29,7 @@ export const UNIT_EXTRA_DATA = [ { name: "Units.MILLIINCH", altDisplayLabels: [] }, { name: "Units.MICROINCH", altDisplayLabels: [] }, { name: "Units.MILLIFOOT", altDisplayLabels: [] }, - { name: "Units.IN", altDisplayLabels: ["IN", "\""] }, + { name: "Units.IN", altDisplayLabels: ["IN", '"'] }, { name: "Units.FT", altDisplayLabels: ["F", "FT", "'"] }, { name: "Units.CHAIN", altDisplayLabels: ["CHAIN"] }, { name: "Units.YRD", altDisplayLabels: ["YRD", "yrd"] }, diff --git a/core/ecschema-metadata/src/test/UnitProvider/UnitProvider.test.ts b/core/ecschema-metadata/src/test/UnitProvider/UnitProvider.test.ts index 48f84e34f218..8e57797540a1 100644 --- a/core/ecschema-metadata/src/test/UnitProvider/UnitProvider.test.ts +++ b/core/ecschema-metadata/src/test/UnitProvider/UnitProvider.test.ts @@ -2,24 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { UnitProps } from "@itwin/core-quantity"; +import { expect } from "chai"; import * as fs from "fs"; import * as path from "path"; -import { expect } from "chai"; -import { Schema, SchemaContext, SchemaInfo } from "../../ecschema-metadata"; -import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; -import { SchemaUnitProvider } from "../../UnitProvider/SchemaUnitProvider"; -import { UNIT_EXTRA_DATA } from "./UnitData"; -import { UnitProps } from "@itwin/core-quantity"; import { ISchemaLocater } from "../../Context"; import { SchemaMatchType } from "../../ECObjects"; +import { Schema, SchemaContext, SchemaInfo } from "../../ecschema-metadata"; import { SchemaKey } from "../../SchemaKey"; +import { SchemaUnitProvider } from "../../UnitProvider/SchemaUnitProvider"; +import { deserializeXmlSync } from "../TestUtils/DeserializationHelpers"; +import { UNIT_EXTRA_DATA } from "./UnitData"; class TestSchemaLocater implements ISchemaLocater { - public async getSchema(schemaKey: Readonly, matchType: SchemaMatchType, context?: SchemaContext): Promise { + public async getSchema( + schemaKey: Readonly, + matchType: SchemaMatchType, + context?: SchemaContext, + ): Promise { return this.getSchemaSync(schemaKey, matchType, context) as T; } - public async getSchemaInfo(schemaKey: Readonly, matchType: SchemaMatchType, context?: SchemaContext | undefined): Promise { + public async getSchemaInfo( + schemaKey: Readonly, + matchType: SchemaMatchType, + context?: SchemaContext | undefined, + ): Promise { return this.getSchema(schemaKey, matchType, context); } public getSchemaSync(schemaKey: Readonly, _matchType: SchemaMatchType, context?: SchemaContext): T | undefined { @@ -41,7 +49,6 @@ describe("Unit Provider tests", () => { let provider: SchemaUnitProvider; describe("Initialized with SchemaContext", () => { - before(() => { context = new SchemaContext(); diff --git a/core/ecschema-metadata/src/test/Validation/SchemaWalker.test.ts b/core/ecschema-metadata/src/test/Validation/SchemaWalker.test.ts index 5af437d026a5..28274427f269 100644 --- a/core/ecschema-metadata/src/test/Validation/SchemaWalker.test.ts +++ b/core/ecschema-metadata/src/test/Validation/SchemaWalker.test.ts @@ -135,7 +135,7 @@ describe("SchemaWalker tests", () => { }, }; - type Mock = { readonly [P in keyof T]: sinon.SinonSpy; }; + type Mock = { readonly [P in keyof T]: sinon.SinonSpy }; let mockVisitor: Mock; beforeEach(async () => { diff --git a/core/ecschema-metadata/src/test/assets/CrossSchemaTests.json b/core/ecschema-metadata/src/test/assets/CrossSchemaTests.json index 91dc119a3184..9fc0be7f93d1 100644 --- a/core/ecschema-metadata/src/test/assets/CrossSchemaTests.json +++ b/core/ecschema-metadata/src/test/assets/CrossSchemaTests.json @@ -319,4 +319,4 @@ "input": 42.42, "expect": 84.84 } -] \ No newline at end of file +] diff --git a/core/ecschema-metadata/src/test/assets/ParserTests.json b/core/ecschema-metadata/src/test/assets/ParserTests.json index 4787501b1f7b..4916b9a2535b 100644 --- a/core/ecschema-metadata/src/test/assets/ParserTests.json +++ b/core/ecschema-metadata/src/test/assets/ParserTests.json @@ -431,4 +431,4 @@ } ] ] -} \ No newline at end of file +} diff --git a/core/ecschema-metadata/src/test/assets/UnitTests.json b/core/ecschema-metadata/src/test/assets/UnitTests.json index 8cf5c3eb5bde..1f198ccc55b3 100644 --- a/core/ecschema-metadata/src/test/assets/UnitTests.json +++ b/core/ecschema-metadata/src/test/assets/UnitTests.json @@ -9047,4 +9047,4 @@ "to": "N", "expect": 424.2 } -] \ No newline at end of file +] diff --git a/core/ecschema-metadata/src/utils/SchemaGraph.ts b/core/ecschema-metadata/src/utils/SchemaGraph.ts index e93845cd10a3..dd2d3b34fcb3 100644 --- a/core/ecschema-metadata/src/utils/SchemaGraph.ts +++ b/core/ecschema-metadata/src/utils/SchemaGraph.ts @@ -26,7 +26,7 @@ export interface ReferenceCycle { export class SchemaGraph { private _schemas: SchemaInfo[] = []; - private constructor() { } + private constructor() {} private find(schemaKey: Readonly) { return this._schemas.find((info: SchemaInfo) => info.schemaKey.matches(schemaKey, SchemaMatchType.Latest)); @@ -71,7 +71,10 @@ export class SchemaGraph { for (const refKey of schema.references) { const refSchema = this.find(refKey.schemaKey); if (undefined === refSchema) - throw new ECObjectsError(ECObjectsStatus.UnableToLoadSchema, `Could not find the schema info for ref schema ${refKey.schemaKey.toString()} for schema ${schema.schemaKey.toString()}`); + throw new ECObjectsError( + ECObjectsStatus.UnableToLoadSchema, + `Could not find the schema info for ref schema ${refKey.schemaKey.toString()} for schema ${schema.schemaKey.toString()}`, + ); if (!visited[refKey.schemaKey.name] && this.detectCycleUtil(refSchema, visited, recStack, cycles)) { cycles.push({ schema, refSchema }); cycleFound = true; @@ -106,8 +109,10 @@ export class SchemaGraph { if (!graph.find(refSchema.schemaKey)) { const refInfo = await context.getSchemaInfo(refSchema.schemaKey, SchemaMatchType.LatestWriteCompatible); if (undefined === refInfo) { - throw new ECObjectsError(ECObjectsStatus.UnableToLocateSchema, - `Could not locate the referenced schema, ${refSchema.schemaKey.name}.${refSchema.schemaKey.version.toString()}, of ${s.schemaKey.name} when populating the graph for ${schema.schemaKey.name}`); + throw new ECObjectsError( + ECObjectsStatus.UnableToLocateSchema, + `Could not locate the referenced schema, ${refSchema.schemaKey.name}.${refSchema.schemaKey.version.toString()}, of ${s.schemaKey.name} when populating the graph for ${schema.schemaKey.name}`, + ); } await genGraph(refInfo); } @@ -141,6 +146,4 @@ export class SchemaGraph { genGraph(schema); return graph; } - } - diff --git a/core/ecschema-metadata/tsconfig.json b/core/ecschema-metadata/tsconfig.json index fa9e0c9b95db..fb9e4848b8e8 100644 --- a/core/ecschema-metadata/tsconfig.json +++ b/core/ecschema-metadata/tsconfig.json @@ -6,4 +6,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/core/ecschema-rpc/common/eslint.config.js b/core/ecschema-rpc/common/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/ecschema-rpc/common/eslint.config.js +++ b/core/ecschema-rpc/common/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/ecschema-rpc/common/src/ECSchemaRpcInterface.ts b/core/ecschema-rpc/common/src/ECSchemaRpcInterface.ts index 6545eb5ebd63..bff471808ec5 100644 --- a/core/ecschema-rpc/common/src/ECSchemaRpcInterface.ts +++ b/core/ecschema-rpc/common/src/ECSchemaRpcInterface.ts @@ -48,5 +48,4 @@ export abstract class ECSchemaRpcInterface extends RpcInterface { // eslint-disa public async getSchemaJSON(_tokenProps: IModelRpcProps, _schemaName: string): Promise { return this.forward.apply(this, [arguments]) as Promise; } - } diff --git a/core/ecschema-rpc/common/src/ECSchemaRpcLocater.ts b/core/ecschema-rpc/common/src/ECSchemaRpcLocater.ts index 54cba8a7ba15..a31d195aaca9 100644 --- a/core/ecschema-rpc/common/src/ECSchemaRpcLocater.ts +++ b/core/ecschema-rpc/common/src/ECSchemaRpcLocater.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, SchemaProps } from "@itwin/ecschema-metadata"; import { IModelRpcProps } from "@itwin/core-common"; +import { ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType, SchemaProps } from "@itwin/ecschema-metadata"; import { ECSchemaRpcInterface } from "./ECSchemaRpcInterface"; /** @@ -13,15 +13,21 @@ import { ECSchemaRpcInterface } from "./ECSchemaRpcInterface"; export class ECSchemaRpcLocater implements ISchemaLocater { public readonly token: IModelRpcProps; - constructor(token: IModelRpcProps) { this.token = token; } + constructor(token: IModelRpcProps) { + this.token = token; + } /** * Attempts to get a schema from the schema rpc locater. Yields undefined if no matching schema is found. * @param schemaKey Key to look up * @param matchType How to match key against candidate schemas * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ - public async getSchema(schemaKey: Readonly, matchType: SchemaMatchType, context: SchemaContext): Promise { + */ + public async getSchema( + schemaKey: Readonly, + matchType: SchemaMatchType, + context: SchemaContext, + ): Promise { await this.getSchemaInfo(schemaKey, matchType, context); const schema = await context.getCachedSchema(schemaKey, matchType); @@ -29,11 +35,11 @@ export class ECSchemaRpcLocater implements ISchemaLocater { } /** - * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. - * The fully loaded schema can be accessed via the schema context using the getCachedSchema method. - * @param schemaKey The SchemaKey describing the schema to get from the cache. - * @param matchType The match type to use when locating the schema - */ + * Gets the schema info which matches the provided SchemaKey. The schema info may be returned before the schema is fully loaded. + * The fully loaded schema can be accessed via the schema context using the getCachedSchema method. + * @param schemaKey The SchemaKey describing the schema to get from the cache. + * @param matchType The match type to use when locating the schema + */ public async getSchemaInfo(schemaKey: Readonly, matchType: SchemaMatchType, context: SchemaContext): Promise { const schemaJson = await ECSchemaRpcInterface.getClient().getSchemaJSON(this.token, schemaKey.name); const schemaInfo = await Schema.startLoadingFromJson(schemaJson, context || new SchemaContext()); @@ -48,7 +54,7 @@ export class ECSchemaRpcLocater implements ISchemaLocater { * @param schemaKey Key to look up * @param matchType How to match key against candidate schemas * @param context The SchemaContext that will control the lifetime of the schema and holds the schema's references, if they exist. - */ + */ public getSchemaSync(schemaKey: Readonly, matchType: SchemaMatchType, context: SchemaContext): T | undefined { const schemaJson = ECSchemaRpcInterface.getClient().getSchemaJSON(this.token, schemaKey.name).then((props: SchemaProps) => { return props; diff --git a/core/ecschema-rpc/impl/eslint.config.js b/core/ecschema-rpc/impl/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/ecschema-rpc/impl/eslint.config.js +++ b/core/ecschema-rpc/impl/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/ecschema-rpc/impl/src/ECSchemaRpcImpl.ts b/core/ecschema-rpc/impl/src/ECSchemaRpcImpl.ts index d0d6f18b8279..dfa5a524d3a4 100644 --- a/core/ecschema-rpc/impl/src/ECSchemaRpcImpl.ts +++ b/core/ecschema-rpc/impl/src/ECSchemaRpcImpl.ts @@ -49,11 +49,11 @@ export class ECSchemaRpcImpl extends RpcInterface implements ECSchemaRpcInterfac * @returns An array of SchemaKeyProps. */ public async getSchemaKeys(tokenProps: IModelRpcProps): Promise { - const schemaKeyProps: SchemaKeyProps[] = []; const iModelDb = await this.getIModelDatabase(tokenProps); - const schemaNameQuery = `SELECT Name as schemaName, VersionMajor as read, VersionWrite as write, VersionMinor as minor FROM main.meta.ECSchemaDef`; + const schemaNameQuery = + `SELECT Name as schemaName, VersionMajor as read, VersionWrite as write, VersionMinor as minor FROM main.meta.ECSchemaDef`; for await (const row of iModelDb.createQueryReader(schemaNameQuery, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { const schemaDefinitionRow = row.toRow() as SchemaNameRow; const schemaFullName = schemaDefinitionRow.schemaName; diff --git a/core/ecschema-rpc/impl/tsconfig.json b/core/ecschema-rpc/impl/tsconfig.json index da99e2c8b30a..b71a2b1db387 100644 --- a/core/ecschema-rpc/impl/tsconfig.json +++ b/core/ecschema-rpc/impl/tsconfig.json @@ -7,4 +7,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/core/ecsql/common/eslint.config.js b/core/ecsql/common/eslint.config.js index 26fcf8009893..259628a4f04a 100644 --- a/core/ecsql/common/eslint.config.js +++ b/core/ecsql/common/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/ecsql/common/src/ECSqlAst.ts b/core/ecsql/common/src/ECSqlAst.ts index 44f660561df7..d0767676bdde 100644 --- a/core/ecsql/common/src/ECSqlAst.ts +++ b/core/ecsql/common/src/ECSqlAst.ts @@ -55,7 +55,7 @@ export enum LiteralValueType { Date = "DATE", Time = "TIME", Timestamp = "TIMESTAMP", - Raw = "RAW" + Raw = "RAW", } /** * Sort direction specified by ORDER BY spec @see [[OrderBySpecExpr]] @@ -224,7 +224,7 @@ export enum ExprType { LimitClause = "LimitClause", Assignment = "Assignment", - NavValueCreationFunc = "NavValueCreationFunc" + NavValueCreationFunc = "NavValueCreationFunc", } /** @@ -232,7 +232,7 @@ export enum ExprType { * @alpha */ export class ExprFactory { - public constructor(public readonly provider: NativeECSqlParseNodeProvider) { } + public constructor(public readonly provider: NativeECSqlParseNodeProvider) {} public async parseStatement(ecsql: string): Promise { return StatementExpr.deserialize(this.provider.parseECSql(ecsql)); } @@ -243,7 +243,7 @@ export class ExprFactory { * @alpha */ export abstract class Expr { - public constructor(public readonly expType: ExprType) { } + public constructor(public readonly expType: ExprType) {} /** * Write expression tree to a ECSQL string * @param writer A instance of writer to which expression tree will output tokens. @@ -289,8 +289,12 @@ export abstract class Expr { * @param type A class that extends from Expr * @returns true if instances matches the type else return false. */ - public isInstanceOf(type: Constructor) { return isInstanceOf(this, type); } - public asInstanceOf(type: Constructor) { return asInstanceOf(this, type); } + public isInstanceOf(type: Constructor) { + return isInstanceOf(this, type); + } + public asInstanceOf(type: Constructor) { + return asInstanceOf(this, type); + } /** * Convert expression tree to ECSQL. * @param args args to ecsql writer. @@ -358,10 +362,18 @@ export abstract class ComputedExpr extends Expr { * @alpha */ export abstract class BooleanExpr extends ComputedExpr { - public static readonly deserializableIds = [NativeExpIds.BinaryBoolean, NativeExpIds.BooleanFactor, NativeExpIds.SubqueryTest, NativeExpIds.AllOrAny, NativeExpIds.BooleanFactor]; - public static override deserialize(node: NativeECSqlParseNode): BooleanExpr | SubqueryTestExpr | BetweenExpr | LikeExpr | InExpr | IsNullExpr | IsOfTypeExpr | NotExpr | BinaryBooleanExpr { + public static readonly deserializableIds = [ + NativeExpIds.BinaryBoolean, + NativeExpIds.BooleanFactor, + NativeExpIds.SubqueryTest, + NativeExpIds.AllOrAny, + NativeExpIds.BooleanFactor, + ]; + public static override deserialize( + node: NativeECSqlParseNode, + ): BooleanExpr | SubqueryTestExpr | BetweenExpr | LikeExpr | InExpr | IsNullExpr | IsOfTypeExpr | NotExpr | BinaryBooleanExpr { if (node.id === NativeExpIds.BinaryBoolean) { - const op = (node.op as string); + const op = node.op as string; // if (MatchExpr.parseOp(op)[0]) { // return MatchExpr.deserialize(node); // } @@ -425,7 +437,20 @@ export abstract class ValueExpr extends ComputedExpr { NativeExpIds.NavValueCreationFunc, ]; - public static override deserialize(node: NativeECSqlParseNode): SubqueryExpr | ValueExpr | UnaryValueExpr | FuncCallExpr | CastExpr | BinaryValueExpr | SearchCaseExpr | IIFExpr | LiteralExpr | PropertyNameExpr | NavValueCreationFuncExpr { + public static override deserialize( + node: NativeECSqlParseNode, + ): + | SubqueryExpr + | ValueExpr + | UnaryValueExpr + | FuncCallExpr + | CastExpr + | BinaryValueExpr + | SearchCaseExpr + | IIFExpr + | LiteralExpr + | PropertyNameExpr + | NavValueCreationFuncExpr { if (node.id === NativeExpIds.UnaryValue) { return UnaryValueExpr.deserialize(node); } @@ -491,7 +516,9 @@ export abstract class ClassRefExpr extends Expr { NativeExpIds.CommonTableBlockName, ]; - public static deserialize(node: NativeECSqlParseNode): ClassNameExpr | SubqueryRefExpr | UsingRelationshipJoinExpr | QualifiedJoinExpr | CteBlockRefExpr | TableValuedFuncExpr { + public static deserialize( + node: NativeECSqlParseNode, + ): ClassNameExpr | SubqueryRefExpr | UsingRelationshipJoinExpr | QualifiedJoinExpr | CteBlockRefExpr | TableValuedFuncExpr { if (node.id === NativeExpIds.ClassName) { return ClassNameExpr.deserialize(node); } @@ -535,7 +562,69 @@ export interface ECSqlWriterArgs { * Keywords output by @see [[ECSqlWriter.appendKeyword]] * @alpha */ -export type Keywords = "ALL" | "AND" | "AS" | "ASC" | "BACKWARD" | "BETWEEN" | "BY" | "CASE" | "CAST" | "CROSS" | "DATE" | "DELETE" | "DESC" | "DISTINCT" | "ECSQLOPTIONS" | "ELSE" | "END" | "ESCAPE" | "EXCEPT" | "EXISTS" | "FIRST" | "FORWARD" | "FROM" | "FULL" | "GROUP" | "HAVING" | "IIF" | "IN" | "INNER" | "INSERT" | "INTERSECT" | "INTO" | "IS" | "JOIN" | "LAST" | "LEFT" | "LIKE" | "LIMIT" | "NATURAL" | "NOT" | "NULL" | "NULLS" | "OFFSET" | "ON" | "ONLY" | "OR" | "ORDER" | "OUTER" | "RECURSIVE" | "RIGHT" | "SELECT" | "SET" | "THEN" | "TIME" | "TIMESTAMP" | "UNION" | "UPDATE" | "USING" | "VALUES" | "WHEN" | "WHERE" | "WITH"; +export type Keywords = + | "ALL" + | "AND" + | "AS" + | "ASC" + | "BACKWARD" + | "BETWEEN" + | "BY" + | "CASE" + | "CAST" + | "CROSS" + | "DATE" + | "DELETE" + | "DESC" + | "DISTINCT" + | "ECSQLOPTIONS" + | "ELSE" + | "END" + | "ESCAPE" + | "EXCEPT" + | "EXISTS" + | "FIRST" + | "FORWARD" + | "FROM" + | "FULL" + | "GROUP" + | "HAVING" + | "IIF" + | "IN" + | "INNER" + | "INSERT" + | "INTERSECT" + | "INTO" + | "IS" + | "JOIN" + | "LAST" + | "LEFT" + | "LIKE" + | "LIMIT" + | "NATURAL" + | "NOT" + | "NULL" + | "NULLS" + | "OFFSET" + | "ON" + | "ONLY" + | "OR" + | "ORDER" + | "OUTER" + | "RECURSIVE" + | "RIGHT" + | "SELECT" + | "SET" + | "THEN" + | "TIME" + | "TIMESTAMP" + | "UNION" + | "UPDATE" + | "USING" + | "VALUES" + | "WHEN" + | "WHERE" + | "WITH"; /** * Write expression tree to string @@ -545,14 +634,16 @@ export class ECSqlWriter { private _tokens: string[] = []; private _currentIndent = 0; private _isNewLine = false; - public constructor(public readonly options: ECSqlWriterArgs = { - multiline: false, - spaceAfterComma: true, - spaceAroundBinOp: true, - eol: "\r\n", - keywordCasing: "UPPER", - indent: { size: 3, char: " " }, - }) { } + public constructor( + public readonly options: ECSqlWriterArgs = { + multiline: false, + spaceAfterComma: true, + spaceAroundBinOp: true, + eol: "\r\n", + keywordCasing: "UPPER", + indent: { size: 3, char: " " }, + }, + ) {} public indent() { this._currentIndent++; } @@ -626,10 +717,10 @@ export class ECSqlWriter { exp.writeTo(this); return this; } - public appendParenLeft(){ + public appendParenLeft() { return this.append("("); } - public appendParenRight(){ + public appendParenRight() { return this.append(")"); } } @@ -670,7 +761,8 @@ export class DeleteStatementExpr extends StatementExpr { public constructor( public readonly className: ClassNameExpr, public readonly where?: WhereClauseExp, - public readonly options?: ECSqlOptionsClauseExpr) { + public readonly options?: ECSqlOptionsClauseExpr, + ) { super(DeleteStatementExpr.type); } public override get children(): Expr[] { @@ -717,7 +809,8 @@ export class InsertStatementExpr extends StatementExpr { public constructor( public readonly className: ClassNameExpr, public readonly values: ValueExpr[], - public readonly propertyNames?: PropertyNameExpr[]) { + public readonly propertyNames?: PropertyNameExpr[], + ) { super(InsertStatementExpr.type); } public override get children(): Expr[] { @@ -740,7 +833,9 @@ export class InsertStatementExpr extends StatementExpr { } } const values = Array.from((node.values as NativeECSqlParseNode[]).map((v) => ValueExpr.deserialize(v))); - const properties = node.properties ? Array.from((node.properties as NativeECSqlParseNode[]).map((v) => PropertyNameExpr.deserialize(v))) : undefined; + const properties = node.properties + ? Array.from((node.properties as NativeECSqlParseNode[]).map((v) => PropertyNameExpr.deserialize(v))) + : undefined; return new InsertStatementExpr(className, values, properties); } public override writeTo(writer: ECSqlWriter): void { @@ -783,7 +878,8 @@ export class QualifiedJoinExpr extends ClassRefExpr { public readonly joinType: JoinType, public readonly from: ClassRefExpr, public readonly to: ClassRefExpr, - public readonly spec: JoinSpec) { + public readonly spec: JoinSpec, + ) { super(QualifiedJoinExpr.type); } public override get children(): Expr[] { @@ -859,7 +955,8 @@ export class UsingRelationshipJoinExpr extends ClassRefExpr { public readonly fromClassName: ClassRefExpr, public readonly toClassName: ClassNameExpr, public readonly toRelClassName: ClassNameExpr, - public readonly direction?: JoinDirection) { + public readonly direction?: JoinDirection, + ) { super(UsingRelationshipJoinExpr.type); } public override get children(): Expr[] { @@ -1263,7 +1360,8 @@ export class SelectExpr extends Expr { public readonly having?: HavingClauseExpr, public readonly orderBy?: OrderByClauseExpr, public readonly limit?: LimitClauseExpr, - public readonly options?: ECSqlOptionsClauseExpr) { + public readonly options?: ECSqlOptionsClauseExpr, + ) { super(SelectExpr.type); } public override get children(): Expr[] { @@ -1359,11 +1457,15 @@ export class SubqueryExpr extends ValueExpr { if (node.id !== NativeExpIds.Subquery) { throw new Error(`Parse node is 'node.id !== NativeExpIds.Subquery'. ${JSON.stringify(node)}`); } - if(node.query.id === NativeExpIds.SelectStatement) + if (node.query.id === NativeExpIds.SelectStatement) return new SubqueryExpr(SelectStatementExpr.deserialize(node.query as NativeECSqlParseNode)); - if(node.query.id === NativeExpIds.CommonTable) + if (node.query.id === NativeExpIds.CommonTable) return new SubqueryExpr(CteExpr.deserialize(node.query as NativeECSqlParseNode)); - throw new Error(`Parse query node is 'node.query.id !== NativeExpIds.SelectStatement' and 'node.query.id !== NativeExpIds.CommonTable'. ${JSON.stringify(node.query)}`); + throw new Error( + `Parse query node is 'node.query.id !== NativeExpIds.SelectStatement' and 'node.query.id !== NativeExpIds.CommonTable'. ${ + JSON.stringify(node.query) + }`, + ); } public writeTo(writer: ECSqlWriter): void { writer.append("("); @@ -1378,7 +1480,12 @@ export class SubqueryExpr extends ValueExpr { */ export class BinaryBooleanExpr extends BooleanExpr { public static readonly type = ExprType.BinaryBoolean; - public constructor(public readonly op: BinaryBooleanOp, public readonly lhsExpr: ComputedExpr, public readonly rhsExpr: ComputedExpr, public readonly not?: UnaryBooleanOp) { + public constructor( + public readonly op: BinaryBooleanOp, + public readonly lhsExpr: ComputedExpr, + public readonly rhsExpr: ComputedExpr, + public readonly not?: UnaryBooleanOp, + ) { super(BinaryBooleanExpr.type); } public override get children(): Expr[] { @@ -1389,7 +1496,11 @@ export class BinaryBooleanExpr extends BooleanExpr { throw new Error(`Parse node is 'node.id !== NativeExpIds.BinaryBoolean'. ${JSON.stringify(node)}`); } const op = node.op as BinaryBooleanOp; - return new BinaryBooleanExpr(op, ComputedExpr.deserialize(node.lhs as NativeECSqlParseNode), ComputedExpr.deserialize(node.rhs as NativeECSqlParseNode)); + return new BinaryBooleanExpr( + op, + ComputedExpr.deserialize(node.lhs as NativeECSqlParseNode), + ComputedExpr.deserialize(node.rhs as NativeECSqlParseNode), + ); } public writeTo(writer: ECSqlWriter): void { writer.append("("); @@ -1591,7 +1702,12 @@ export class InExpr extends BooleanExpr { */ export class LikeExpr extends BooleanExpr { public static readonly type = ExprType.Like; - public constructor(public readonly lhsExpr: ValueExpr, public readonly patternExpr: ValueExpr, public readonly escapeExpr?: ValueExpr, public readonly not?: UnaryBooleanOp) { + public constructor( + public readonly lhsExpr: ValueExpr, + public readonly patternExpr: ValueExpr, + public readonly escapeExpr?: ValueExpr, + public readonly not?: UnaryBooleanOp, + ) { super(LikeExpr.type); } public override get children(): Expr[] { @@ -1641,7 +1757,12 @@ export class LikeExpr extends BooleanExpr { */ export class BetweenExpr extends BooleanExpr { public static readonly type = ExprType.Between; - public constructor(public readonly lhsExpr: ValueExpr, public readonly lowerBoundExpr: ValueExpr, public readonly upperBoundExpr: ValueExpr, public readonly not?: UnaryBooleanOp) { + public constructor( + public readonly lhsExpr: ValueExpr, + public readonly lowerBoundExpr: ValueExpr, + public readonly upperBoundExpr: ValueExpr, + public readonly not?: UnaryBooleanOp, + ) { super(BetweenExpr.type); } public override get children(): Expr[] { @@ -1689,7 +1810,11 @@ export class BetweenExpr extends BooleanExpr { */ export class CteExpr extends StatementExpr { public static readonly type = ExprType.Cte; - public constructor(public readonly cteBlocks: CteBlockExpr[], public readonly query: SelectStatementExpr, public readonly recursive?: RecursiveCte) { + public constructor( + public readonly cteBlocks: CteBlockExpr[], + public readonly query: SelectStatementExpr, + public readonly recursive?: RecursiveCte, + ) { super(CteExpr.type); } public override get children(): Expr[] { @@ -1700,7 +1825,11 @@ export class CteExpr extends StatementExpr { throw new Error(`Parse node is 'node.id !== NativeExpIds.CommonTable'. ${JSON.stringify(node)}`); } const blocks = Array.from((node.blocks as NativeECSqlParseNode[]).map((v) => CteBlockExpr.deserialize(v))); - return new CteExpr(blocks, SelectStatementExpr.deserialize(node.select as NativeECSqlParseNode), node.recursive === true ? "RECURSIVE" : undefined); + return new CteExpr( + blocks, + SelectStatementExpr.deserialize(node.select as NativeECSqlParseNode), + node.recursive === true ? "RECURSIVE" : undefined, + ); } public writeTo(writer: ECSqlWriter): void { writer.appendKeyword("WITH"); @@ -1736,11 +1865,15 @@ export class CteBlockExpr extends Expr { if (node.id !== NativeExpIds.CommonTableBlock) { throw new Error(`Parse node is 'node.id !== NativeExpIds.CommonTableBlock'. ${JSON.stringify(node)}`); } - return new CteBlockExpr(node.name as string, SelectStatementExpr.deserialize(node.asQuery as NativeECSqlParseNode), node.args ? node.args as string[] : []); + return new CteBlockExpr( + node.name as string, + SelectStatementExpr.deserialize(node.asQuery as NativeECSqlParseNode), + node.args ? node.args as string[] : [], + ); } public writeTo(writer: ECSqlWriter): void { writer.appendQuoted(this.name); - if(this.props.length > 0){ + if (this.props.length > 0) { writer.append("("); this.props.forEach((v, i) => { if (i > 0) { @@ -1824,7 +1957,14 @@ export class TableValuedFuncExpr extends ClassRefExpr { */ export class ClassNameExpr extends ClassRefExpr { public static readonly type = ExprType.ClassName; - public constructor(public readonly schemaNameOrAlias: string, public readonly className: string, public readonly tablespace?: string, public readonly alias?: string, public polymorphicInfo?: PolymorphicInfo, public readonly memberFunc?: MemberFuncCallExpr) { + public constructor( + public readonly schemaNameOrAlias: string, + public readonly className: string, + public readonly tablespace?: string, + public readonly alias?: string, + public polymorphicInfo?: PolymorphicInfo, + public readonly memberFunc?: MemberFuncCallExpr, + ) { super(ClassNameExpr.type); } public override get children(): Expr[] { @@ -1839,7 +1979,9 @@ export class ClassNameExpr extends ClassRefExpr { const schemaName = node.schemaName as string; const alias = node.alias ? node.alias as string : undefined; - const polymorphicInfo = node.polymorphicInfo ? { disqualify: node.polymorphicInfo.disqualify, allOrAny: node.polymorphicInfo.scope } as PolymorphicInfo : undefined; + const polymorphicInfo = node.polymorphicInfo + ? { disqualify: node.polymorphicInfo.disqualify, allOrAny: node.polymorphicInfo.scope } as PolymorphicInfo + : undefined; const memberFunc = node.func ? MemberFuncCallExpr.deserialize(node.func as NativeECSqlParseNode) : undefined; return new ClassNameExpr(schemaName, className, tablespace, alias, polymorphicInfo, memberFunc); } @@ -1897,7 +2039,12 @@ export class ClassNameExpr extends ClassRefExpr { */ export class UpdateStatementExpr extends StatementExpr { public static readonly type = ExprType.UpdateStatement; - public constructor(public readonly className: ClassNameExpr, public readonly assignement: SetClauseExpr, public readonly where?: WhereClauseExp, public readonly options?: ECSqlOptionsClauseExpr) { + public constructor( + public readonly className: ClassNameExpr, + public readonly assignement: SetClauseExpr, + public readonly where?: WhereClauseExp, + public readonly options?: ECSqlOptionsClauseExpr, + ) { super(UpdateStatementExpr.type); } public override get children(): Expr[] { @@ -2059,7 +2206,11 @@ export class IIFExpr extends ValueExpr { if (node.id !== NativeExpIds.IIF) { throw new Error(`Parse node is 'node.id !== NativeExpIds.IIF'. ${JSON.stringify(node)}`); } - return new IIFExpr(BooleanExpr.deserialize(node.when as NativeECSqlParseNode), ValueExpr.deserialize(node.then as NativeECSqlParseNode), ValueExpr.deserialize(node.else as NativeECSqlParseNode)); + return new IIFExpr( + BooleanExpr.deserialize(node.when as NativeECSqlParseNode), + ValueExpr.deserialize(node.then as NativeECSqlParseNode), + ValueExpr.deserialize(node.else as NativeECSqlParseNode), + ); } public writeTo(writer: ECSqlWriter): void { writer.appendKeyword("IIF"); @@ -2151,7 +2302,11 @@ export class BinaryValueExpr extends ValueExpr { if (node.id !== NativeExpIds.BinaryValue && node.id !== NativeExpIds.BinaryBoolean) { throw new Error(`Parse node is 'node.id !== NativeExpIds.BinaryValue' . ${JSON.stringify(node)}`); } - return new BinaryValueExpr(node.op as BinaryValueOp, ValueExpr.deserialize(node.lhs as NativeECSqlParseNode), ValueExpr.deserialize(node.rhs as NativeECSqlParseNode)); + return new BinaryValueExpr( + node.op as BinaryValueOp, + ValueExpr.deserialize(node.lhs as NativeECSqlParseNode), + ValueExpr.deserialize(node.rhs as NativeECSqlParseNode), + ); } public writeTo(writer: ECSqlWriter): void { writer.append("("); @@ -2449,13 +2604,27 @@ export class LiteralExpr extends ValueExpr { else writer.append(this.rawValue); } - public static makeRaw(val: string) { return new LiteralExpr(LiteralValueType.Raw, val); } - public static makeString(val: string) { return new LiteralExpr(LiteralValueType.String, val); } - public static makeNumber(val: number) { return new LiteralExpr(LiteralValueType.Raw, val.toString()); } - public static makeDate(val: Date) { return new LiteralExpr(LiteralValueType.Date, val.toDateString()); } - public static makeTime(val: Date) { return new LiteralExpr(LiteralValueType.String, val.toTimeString()); } - public static makeTimestamp(val: Date) { return new LiteralExpr(LiteralValueType.String, val.toTimeString()); } - public static makeNull() { return new LiteralExpr(LiteralValueType.Null, ""); } + public static makeRaw(val: string) { + return new LiteralExpr(LiteralValueType.Raw, val); + } + public static makeString(val: string) { + return new LiteralExpr(LiteralValueType.String, val); + } + public static makeNumber(val: number) { + return new LiteralExpr(LiteralValueType.Raw, val.toString()); + } + public static makeDate(val: Date) { + return new LiteralExpr(LiteralValueType.Date, val.toDateString()); + } + public static makeTime(val: Date) { + return new LiteralExpr(LiteralValueType.String, val.toTimeString()); + } + public static makeTimestamp(val: Date) { + return new LiteralExpr(LiteralValueType.String, val.toTimeString()); + } + public static makeNull() { + return new LiteralExpr(LiteralValueType.Null, ""); + } } /** diff --git a/core/ecsql/common/src/test/ECSqlAst.test.ts b/core/ecsql/common/src/test/ECSqlAst.test.ts index fd3a7c29b1cc..cc22daa9fb37 100644 --- a/core/ecsql/common/src/test/ECSqlAst.test.ts +++ b/core/ecsql/common/src/test/ECSqlAst.test.ts @@ -64,9 +64,12 @@ describe("ECSql AST", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), "ALL", new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -75,7 +78,10 @@ describe("ECSql AST", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new LiteralExpr(LiteralValueType.Raw, "1")))), + new LiteralExpr(LiteralValueType.Raw, "1"), + ), + ), + ), ); const expected = "SELECT ALL [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = 1)"; assert.equal(stmt.toECSql(), expected); @@ -94,9 +100,12 @@ describe("ECSql AST", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), undefined, new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -105,7 +114,10 @@ describe("ECSql AST", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new ParameterExpr()))), + new ParameterExpr(), + ), + ), + ), ); const expected = "SELECT [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = ?)"; assert.equal(stmt.toECSql(), expected); diff --git a/core/electron/eslint.config.js b/core/electron/eslint.config.js index 628f1d4b27a0..849e7479dee5 100644 --- a/core/electron/eslint.config.js +++ b/core/electron/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/electron/src/__DOC_ONLY__.ts b/core/electron/src/__DOC_ONLY__.ts index 947df2dc8a1e..964c4c0d3ee1 100644 --- a/core/electron/src/__DOC_ONLY__.ts +++ b/core/electron/src/__DOC_ONLY__.ts @@ -28,5 +28,5 @@ export * from "./frontend/ElectronApp"; /** * @docs-group-description RpcInterface - * Functionality facilitate electron RPC + * Functionality facilitate electron RPC */ diff --git a/core/electron/src/backend/ElectronHost.ts b/core/electron/src/backend/ElectronHost.ts index 85d7e123a69b..724638c3d37a 100644 --- a/core/electron/src/backend/ElectronHost.ts +++ b/core/electron/src/backend/ElectronHost.ts @@ -11,13 +11,13 @@ import type { BrowserWindow, BrowserWindowConstructorOptions, WebPreferences } from "electron"; import type * as ElectronModule from "electron"; -import * as fs from "fs"; -import * as path from "path"; -import { BeDuration, IModelStatus, ProcessDetector } from "@itwin/core-bentley"; import { IpcHandler, IpcHost, NativeHost, NativeHostOpts } from "@itwin/core-backend"; +import { BeDuration, IModelStatus, ProcessDetector } from "@itwin/core-bentley"; import { IModelError, IpcListener, IpcSocketBackend, RemoveFunction, RpcConfiguration, RpcInterfaceDefinition } from "@itwin/core-common"; -import { ElectronRpcConfiguration, ElectronRpcManager } from "../common/ElectronRpcManager"; +import * as fs from "fs"; +import * as path from "path"; import { DialogModuleMethod, electronIpcStrings } from "../common/ElectronIpcInterface"; +import { ElectronRpcConfiguration, ElectronRpcManager } from "../common/ElectronRpcManager"; // cSpell:ignore signin devserver webcontents copyfile unmaximize eopt @@ -70,7 +70,7 @@ export interface ElectronHostOpts extends NativeHostOpts { export interface ElectronHostWindowOptions extends BrowserWindowConstructorOptions { storeWindowName?: string; /** The style of window title bar. Default is `default`. */ - titleBarStyle?: ("default" | "hidden" | "hiddenInset" | "customButtonsOnHover"); + titleBarStyle?: "default" | "hidden" | "hiddenInset" | "customButtonsOnHover"; } /** the size and position of a window as stored in the settings file. @@ -100,11 +100,17 @@ export class ElectronHost { public static appIconPath: string; public static frontendURL: string; public static rpcConfig: RpcConfiguration; - public static get ipcMain() { return this._electron?.ipcMain; } - public static get app() { return this._electron?.app; } - public static get electron() { return this._electron; } + public static get ipcMain() { + return this._electron?.ipcMain; + } + public static get app() { + return this._electron?.app; + } + public static get electron() { + return this._electron; + } - private constructor() { } + private constructor() {} /** * Converts an "electron://frontend/" URL to an absolute file path. @@ -137,7 +143,7 @@ export class ElectronHost { ...options?.webPreferences, // These web preference variables should not be overriden by the ElectronHostWindowOptions - preload: require.resolve(/* webpack: copyfile */"./ElectronPreload.js"), + preload: require.resolve(/* webpack: copyfile */ "./ElectronPreload.js"), experimentalFeatures: false, nodeIntegration: false, contextIsolation: true, @@ -187,7 +193,9 @@ export class ElectronHost { } /** The "main" BrowserWindow for this application. */ - public static get mainWindow() { return this._mainWindow; } + public static get mainWindow() { + return this._mainWindow; + } /** * Gets window size and position for a window, by name, from settings file, if present. @@ -257,7 +265,9 @@ export class ElectronHost { this._openWindow(windowOptions); } - public static get isValid() { return this._ipc !== undefined; } + public static get isValid() { + return this._ipc !== undefined; + } /** * Initialize the backend of an Electron app. @@ -304,7 +314,9 @@ export class ElectronHost { } class ElectronDialogHandler extends IpcHandler { - public get channelName() { return electronIpcStrings.dialogChannel; } + public get channelName() { + return electronIpcStrings.dialogChannel; + } public async callDialog(method: DialogModuleMethod, ...args: any) { const dialog = ElectronHost.electron.dialog; const dialogMethod = dialog[method] as Function; @@ -317,7 +329,7 @@ class ElectronDialogHandler extends IpcHandler { function debounce(func: Function, ms: number = 200) { let timeout: NodeJS.Timeout; - return function (this: any, ...args: any[]) { + return function(this: any, ...args: any[]) { clearTimeout(timeout); timeout = setTimeout(() => { func.apply(this, args); diff --git a/core/electron/src/common/ElectronIpcTransport.ts b/core/electron/src/common/ElectronIpcTransport.ts index 59345cf4304c..1f711999f6c3 100644 --- a/core/electron/src/common/ElectronIpcTransport.ts +++ b/core/electron/src/common/ElectronIpcTransport.ts @@ -5,7 +5,13 @@ import { BentleyError, BentleyStatus, ProcessDetector } from "@itwin/core-bentley"; import { - IModelError, iTwinChannel, RpcPushChannel, RpcPushConnection, RpcRequestFulfillment, RpcSerializedValue, SerializedRpcRequest, + IModelError, + iTwinChannel, + RpcPushChannel, + RpcPushConnection, + RpcRequestFulfillment, + RpcSerializedValue, + SerializedRpcRequest, } from "@itwin/core-common"; import { ElectronPushConnection, ElectronPushTransport } from "./ElectronPush"; import { ElectronRpcConfiguration } from "./ElectronRpcManager"; @@ -15,18 +21,31 @@ import { ElectronRpcRequest } from "./ElectronRpcRequest"; const OBJECTS_CHANNEL = iTwinChannel("rpc.objects"); const DATA_CHANNEL = iTwinChannel("rpc.data"); -interface PartialPayload { id: string, index: number, data: Uint8Array } +interface PartialPayload { + id: string; + index: number; + data: Uint8Array; +} /** @internal */ -export interface IpcTransportMessage { id: string, parameters?: RpcSerializedValue, result?: RpcSerializedValue } +export interface IpcTransportMessage { + id: string; + parameters?: RpcSerializedValue; + result?: RpcSerializedValue; +} /** @internal */ -export abstract class ElectronIpcTransport { +export abstract class ElectronIpcTransport< + TIn extends IpcTransportMessage = IpcTransportMessage, + TOut extends IpcTransportMessage = IpcTransportMessage, +> { private _partials: Map; private _removeListeners: VoidFunction[] = []; protected _protocol: ElectronRpcProtocol; - public get protocol() { return this._protocol; } + public get protocol() { + return this._protocol; + } public sendRequest(request: SerializedRpcRequest) { const value = this._extractValue(request); @@ -41,7 +60,7 @@ export abstract class ElectronIpcTransport { diff --git a/core/electron/src/common/ElectronPush.ts b/core/electron/src/common/ElectronPush.ts index 77727ef418b4..35e8fc4e2273 100644 --- a/core/electron/src/common/ElectronPush.ts +++ b/core/electron/src/common/ElectronPush.ts @@ -13,7 +13,9 @@ export class ElectronPushTransport extends RpcPushTransport { private _ipc: FrontendIpcTransport; private _last: number = -1; - public get last() { return this._last; } + public get last() { + return this._last; + } public constructor(ipc: FrontendIpcTransport) { super(); diff --git a/core/electron/src/common/ElectronRpcManager.ts b/core/electron/src/common/ElectronRpcManager.ts index be63f861262d..dbd9c20c419a 100644 --- a/core/electron/src/common/ElectronRpcManager.ts +++ b/core/electron/src/common/ElectronRpcManager.ts @@ -3,14 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { IpcSocket, IpcSocketBackend, IpcSocketFrontend, RpcConfiguration, RpcInterfaceDefinition, RpcManager, RpcRegistry } from "@itwin/core-common"; +import { + IpcSocket, + IpcSocketBackend, + IpcSocketFrontend, + RpcConfiguration, + RpcInterfaceDefinition, + RpcManager, + RpcRegistry, +} from "@itwin/core-common"; import { ElectronRpcProtocol } from "./ElectronRpcProtocol"; /** RPC interface configuration for an Electron-based application. * @internal */ export abstract class ElectronRpcConfiguration extends RpcConfiguration { - public static targetWindowId?: number; /** The protocol of the configuration. */ diff --git a/core/electron/src/frontend/ElectronApp.ts b/core/electron/src/frontend/ElectronApp.ts index 36b660073935..f944726666b4 100644 --- a/core/electron/src/frontend/ElectronApp.ts +++ b/core/electron/src/frontend/ElectronApp.ts @@ -56,7 +56,9 @@ export type ElectronAppOpts = NativeAppOpts; */ export class ElectronApp { private static _ipc?: ElectronIpc; - public static get isValid(): boolean { return undefined !== this._ipc; } + public static get isValid(): boolean { + return undefined !== this._ipc; + } /** * Start the frontend of an Electron application. diff --git a/core/electron/src/test/backend/ElectronHost.test.ts b/core/electron/src/test/backend/ElectronHost.test.ts index e894f68b1ae0..ea03932f9207 100644 --- a/core/electron/src/test/backend/ElectronHost.test.ts +++ b/core/electron/src/test/backend/ElectronHost.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; -import { assert } from "chai"; -import { exec } from "child_process"; import { IModelHost, IpcHandler, NativeHost } from "@itwin/core-backend"; import { BeDuration } from "@itwin/core-bentley"; import { RpcInterface, RpcRegistry } from "@itwin/core-common"; +import { assert } from "chai"; +import { exec } from "child_process"; +import * as path from "path"; import { ElectronHost, ElectronHostOptions } from "../../ElectronBackend"; import { TestSuite } from "./ElectronBackendTests"; @@ -72,7 +72,9 @@ async function testStartWithOptions() { async function testRegisterIpcHandler() { class IpcHandlerMock extends IpcHandler { - public override get channelName() { return "electron-test/mock-channel"; } + public override get channelName() { + return "electron-test/mock-channel"; + } public static wasRegisterCalled = false; public static override register() { diff --git a/core/electron/src/test/frontend/ElectronApp.test.ts b/core/electron/src/test/frontend/ElectronApp.test.ts index 24da68a7e289..bb5838ed6c7b 100644 --- a/core/electron/src/test/frontend/ElectronApp.test.ts +++ b/core/electron/src/test/frontend/ElectronApp.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { EmptyLocalization, RpcInterface, RpcRegistry } from "@itwin/core-common"; import { IModelApp, NativeApp } from "@itwin/core-frontend"; +import { assert } from "chai"; import { ElectronApp } from "../../ElectronFrontend"; describe("ElectronApp tests.", () => { diff --git a/core/electron/src/test/frontend/utils/webpack.config.js b/core/electron/src/test/frontend/utils/webpack.config.js index c1935b8cad29..40439fcc14b9 100644 --- a/core/electron/src/test/frontend/utils/webpack.config.js +++ b/core/electron/src/test/frontend/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig() { output: { path: path.resolve(frontendLib, "test/frontend/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,19 +27,19 @@ function createConfig() { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -53,13 +53,13 @@ function createConfig() { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; return config; } module.exports = [ - createConfig() -] + createConfig(), +]; diff --git a/core/express-server/eslint.config.js b/core/express-server/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/express-server/eslint.config.js +++ b/core/express-server/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/express-server/src/ExpressServer.ts b/core/express-server/src/ExpressServer.ts index b14a062a4ac2..b9f872b8cfda 100644 --- a/core/express-server/src/ExpressServer.ts +++ b/core/express-server/src/ExpressServer.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { LocalhostIpcHost } from "@itwin/core-backend"; +import { BentleyCloudRpcConfiguration, RpcConfiguration, WebAppRpcProtocol } from "@itwin/core-common"; import * as express from "express"; import * as enableWs from "express-ws"; import { Server as HttpServer } from "http"; -import { BentleyCloudRpcConfiguration, RpcConfiguration, WebAppRpcProtocol } from "@itwin/core-common"; -import { LocalhostIpcHost } from "@itwin/core-backend"; /** * Options for configuring IModelJsExpressServer. @@ -34,7 +34,9 @@ export class IModelJsExpressServer { protected _app: import("express").Application = express(); /** @alpha */ - public get rpcConfiguration(): RpcConfiguration { return this._protocol.configuration; } + public get rpcConfiguration(): RpcConfiguration { + return this._protocol.configuration; + } constructor(protocol: WebAppRpcProtocol, config = IModelJsExpressServer.defaults) { this._protocol = protocol; diff --git a/core/express-server/src/test/ExpressServer.test.ts b/core/express-server/src/test/ExpressServer.test.ts index cab377bacd53..5e2ad00e5fc4 100644 --- a/core/express-server/src/test/ExpressServer.test.ts +++ b/core/express-server/src/test/ExpressServer.test.ts @@ -13,7 +13,8 @@ function mockRequestHandler(mock: sinon.SinonMock, method: string, status: numbe return mock.expects(method).callsFake( (_req: HttpServerRequest, res: HttpServerResponse) => { // eslint-disable-line deprecation/deprecation res.status(status).send(result); - }); + }, + ); } describe("IModelJsExpressServer", () => { diff --git a/core/express-server/src/test/Mocks.ts b/core/express-server/src/test/Mocks.ts index e3ed5d05318b..44486977f28f 100644 --- a/core/express-server/src/test/Mocks.ts +++ b/core/express-server/src/test/Mocks.ts @@ -8,7 +8,6 @@ import * as sinon from "sinon"; import { IModelJsExpressServer } from "../ExpressServer"; export class FakeBentleyCloudRpcConfiguration extends BentleyCloudRpcConfiguration { - // eslint-disable-next-line @typescript-eslint/naming-convention private static info: OpenAPIInfo = { title: "randomTitle", version: "randomVersion" }; // eslint-disable-line deprecation/deprecation @@ -33,7 +32,9 @@ const fakeHttpServer = { } as any; export class TestIModelJsExpressServer extends IModelJsExpressServer { - public get expressApp() { return this._app; } + public get expressApp() { + return this._app; + } // Wrap base initialize so we configure express app, but don't actually listen on any ports public override async initialize(port: number) { diff --git a/core/extension/codeGen/generate-exports.js b/core/extension/codeGen/generate-exports.js index 56dc54f0821b..a1b7b8c5ea54 100644 --- a/core/extension/codeGen/generate-exports.js +++ b/core/extension/codeGen/generate-exports.js @@ -17,7 +17,7 @@ const codeGenOpeningComment = "// BEGIN GENERATED CODE"; const codeGenClosingComment = "// END GENERATED CODE"; // select all of generated block, including comments const codeGenBlock = RegExp( - `${codeGenOpeningComment}(\\s|\\S)*${codeGenClosingComment}` + `${codeGenOpeningComment}(\\s|\\S)*${codeGenClosingComment}`, ); // Convert extension linter's output file to a set of lists separated by export type @@ -40,7 +40,7 @@ function interpretCsv(csvString) { } const [exportName, exportType, releaseTag] = line.split(","); apiByType[`${releaseTag.toLocaleLowerCase()}Api`][exportType].add( - exportName + exportName, ); }); } catch (error) { @@ -76,8 +76,7 @@ function generateDeclarationCode(exportList) { reals = reals ? `\n\t${reals}` : ""; types = types ? `\n\t${types}` : ""; - exportCode += - realExports + reals + exportTrailer + typeExports + types + exportTrailer; + exportCode += realExports + reals + exportTrailer + typeExports + types + exportTrailer; } return exportCode; @@ -110,8 +109,7 @@ function generateRuntimeCode(exportList) { let exportsApi = `const extensionExports = {\n${tab}`; const _exports = []; const exportTrailer = `\n};\n\n`; - const addComment = (packageName, release, kind) => - ` // @${release} ${kind}(s) from ${packageName}\n`; + const addComment = (packageName, release, kind) => ` // @${release} ${kind}(s) from ${packageName}\n`; for (const packageName in exportList) { let imports = "import {\n"; @@ -120,19 +118,17 @@ function generateRuntimeCode(exportList) { if (packageName === "@itwin/core-frontend") importTrailer = `} from "../core-frontend";\n\n`; - imports += - exportList[packageName].enum.size > 0 - ? addComment(packageName, "public", "enum") - : ""; + imports += exportList[packageName].enum.size > 0 + ? addComment(packageName, "public", "enum") + : ""; [...exportList[packageName].enum].sort().forEach((enumExport) => { imports += `${tab}${enumExport},\n`; _exports.push(enumExport); }); - imports += - exportList[packageName].real.size > 0 - ? addComment(packageName, "public", "real") - : ""; + imports += exportList[packageName].real.size > 0 + ? addComment(packageName, "public", "real") + : ""; [...exportList[packageName].real].sort().forEach((realExport) => { imports += `${tab}${realExport},\n`; _exports.push(realExport); @@ -160,7 +156,7 @@ function collectExports(packagePath) { } catch (error) { throw Error( "Failed to read extension api csv, it may not exist or has no content.\n" + - error + error, ); } @@ -176,7 +172,7 @@ function addToFile(filePath, generatedCode) { if (!codeGenBlock.test(fileContents)) throw Error( - `No block for generated code found in '${filePath}. A block with the code gen opening and closing comments is required.` + `No block for generated code found in '${filePath}. A block with the code gen opening and closing comments is required.`, ); // Embed generated code in codeGen block diff --git a/core/extension/eslint.config.js b/core/extension/eslint.config.js index 081ca508152a..68f824b1f59e 100644 --- a/core/extension/eslint.config.js +++ b/core/extension/eslint.config.js @@ -5,4 +5,4 @@ export default [ files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, -]; \ No newline at end of file +]; diff --git a/core/extension/index.d.ts b/core/extension/index.d.ts index 6224052c16a3..6dc78aee4069 100644 --- a/core/extension/index.d.ts +++ b/core/extension/index.d.ts @@ -6,17 +6,10 @@ // manually curated section // these types are needed for ExtensionHost -import type { - ToolAdmin, - NotificationManager, - ViewManager, - ElementLocateManager, - AccuSnap, - RenderSystem -} from "@itwin/core-frontend"; +import type { AccuSnap, ElementLocateManager, NotificationManager, RenderSystem, ToolAdmin, ViewManager } from "@itwin/core-frontend"; // ExtensionHost must always be in the API export declare class ExtensionHost { - public static get toolAdmin(): ToolAdmin; + public static get toolAdmin(): ToolAdmin; public static get notifications(): NotificationManager; public static get viewManager(): ViewManager; public static get locateManager(): ElementLocateManager; @@ -26,611 +19,611 @@ export declare class ExtensionHost { // BEGIN GENERATED CODE export { - ACSDisplayOptions, - ACSType, - AccuDrawHintBuilder, - AccuSnap, - ActivityMessageDetails, - ActivityMessageEndReason, - AuxCoordSystem2dState, - AuxCoordSystem3dState, - AuxCoordSystemSpatialState, - AuxCoordSystemState, - BeButton, - BeButtonEvent, - BeButtonState, - BeModifierKeys, - BeTouchEvent, - BeWheelEvent, - BingElevationProvider, - BingLocationProvider, - CategorySelectorState, - ChangeFlags, - ClipEventType, - Cluster, - ContextRealityModelState, - ContextRotationId, - CoordSource, - CoordSystem, - CoordinateLockOverrides, - DecorateContext, - Decorations, - DisclosedTileTreeSet, - DisplayStyle2dState, - DisplayStyle3dState, - DisplayStyleState, - DrawingModelState, - DrawingViewState, - EditManipulator, - ElementLocateManager, - ElementPicker, - ElementState, - EmphasizeElements, - EntityState, - EventController, - EventHandled, - FeatureSymbology, - FlashMode, - FlashSettings, - FrontendLoggerCategory, - FrustumAnimator, - GeometricModel2dState, - GeometricModel3dState, - GeometricModelState, - GlobeAnimator, - GraphicAssembler, - GraphicBranch, - GraphicBuilder, - GraphicType, - HiliteSet, - HitDetail, - HitDetailType, - HitGeomType, - HitList, - HitParentGeomType, - HitPriority, - HitSource, - IModelConnection, - IconSprites, - InputCollector, - InputSource, - InteractiveTool, - IntersectDetail, - KeyinParseError, - LocateAction, - LocateFilterStatus, - LocateOptions, - LocateResponse, - ManipulatorToolEvent, - MarginPercent, - Marker, - MarkerSet, - MessageBoxIconType, - MessageBoxType, - MessageBoxValue, - ModelSelectorState, - ModelState, - NotificationHandler, - NotificationManager, - NotifyMessageDetails, - OffScreenViewport, - OrthographicViewState, - OutputMessageAlert, - OutputMessagePriority, - OutputMessageType, - ParseAndRunResult, - ParticleCollectionBuilder, - PerModelCategoryVisibility, - PhysicalModelState, - Pixel, - PrimitiveTool, - RenderClipVolume, - RenderContext, - RenderGraphic, - RenderGraphicOwner, - RenderSystem, - Scene, - ScreenViewport, - SectionDrawingModelState, - SelectionMethod, - SelectionMode, - SelectionProcessing, - SelectionSet, - SelectionSetEventType, - SheetModelState, - SheetViewState, - SnapDetail, - SnapHeat, - SnapMode, - SnapStatus, - SpatialLocationModelState, - SpatialModelState, - SpatialViewState, - Sprite, - SpriteLocation, - StandardViewId, - StartOrResume, - TentativePoint, - Tile, - TileAdmin, - TileBoundingBoxes, - TileDrawArgs, - TileGraphicType, - TileLoadPriority, - TileLoadStatus, - TileRequest, - TileRequestChannel, - TileRequestChannelStatistics, - TileRequestChannels, - TileTree, - TileTreeLoadStatus, - TileTreeReference, - TileUsageMarker, - TileVisibility, - Tiles, - Tool, - ToolAdmin, - ToolAssistance, - ToolAssistanceImage, - ToolAssistanceInputMethod, - ToolSettings, - TwoWayViewportFrustumSync, - TwoWayViewportSync, - UniformType, - VaryingType, - ViewClipClearTool, - ViewClipDecoration, - ViewClipDecorationProvider, - ViewClipTool, - ViewCreator2d, - ViewCreator3d, - ViewManager, - ViewManip, - ViewPose, - ViewPose2d, - ViewPose3d, - ViewRect, - ViewState, - ViewState2d, - ViewState3d, - ViewStatus, - ViewTool, - ViewingSpace, - Viewport, - canvasToImageBuffer, - canvasToResizedCanvasWithBars, - connectViewportFrusta, - connectViewportViews, - connectViewports, - extractImageSourceDimensions, - getCompressedJpegFromCanvas, - getImageSourceFormatForMimeType, - getImageSourceMimeType, - imageBufferToBase64EncodedPng, - imageBufferToCanvas, - imageBufferToPngDataUrl, - imageElementFromImageSource, - imageElementFromUrl, - queryTerrainElevationOffset, - readElementGraphics, - readGltfGraphics, - synchronizeViewportFrusta, - synchronizeViewportViews + AccuDrawHintBuilder, + AccuSnap, + ACSDisplayOptions, + ACSType, + ActivityMessageDetails, + ActivityMessageEndReason, + AuxCoordSystem2dState, + AuxCoordSystem3dState, + AuxCoordSystemSpatialState, + AuxCoordSystemState, + BeButton, + BeButtonEvent, + BeButtonState, + BeModifierKeys, + BeTouchEvent, + BeWheelEvent, + BingElevationProvider, + BingLocationProvider, + canvasToImageBuffer, + canvasToResizedCanvasWithBars, + CategorySelectorState, + ChangeFlags, + ClipEventType, + Cluster, + connectViewportFrusta, + connectViewports, + connectViewportViews, + ContextRealityModelState, + ContextRotationId, + CoordinateLockOverrides, + CoordSource, + CoordSystem, + DecorateContext, + Decorations, + DisclosedTileTreeSet, + DisplayStyle2dState, + DisplayStyle3dState, + DisplayStyleState, + DrawingModelState, + DrawingViewState, + EditManipulator, + ElementLocateManager, + ElementPicker, + ElementState, + EmphasizeElements, + EntityState, + EventController, + EventHandled, + extractImageSourceDimensions, + FeatureSymbology, + FlashMode, + FlashSettings, + FrontendLoggerCategory, + FrustumAnimator, + GeometricModel2dState, + GeometricModel3dState, + GeometricModelState, + getCompressedJpegFromCanvas, + getImageSourceFormatForMimeType, + getImageSourceMimeType, + GlobeAnimator, + GraphicAssembler, + GraphicBranch, + GraphicBuilder, + GraphicType, + HiliteSet, + HitDetail, + HitDetailType, + HitGeomType, + HitList, + HitParentGeomType, + HitPriority, + HitSource, + IconSprites, + imageBufferToBase64EncodedPng, + imageBufferToCanvas, + imageBufferToPngDataUrl, + imageElementFromImageSource, + imageElementFromUrl, + IModelConnection, + InputCollector, + InputSource, + InteractiveTool, + IntersectDetail, + KeyinParseError, + LocateAction, + LocateFilterStatus, + LocateOptions, + LocateResponse, + ManipulatorToolEvent, + MarginPercent, + Marker, + MarkerSet, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + ModelSelectorState, + ModelState, + NotificationHandler, + NotificationManager, + NotifyMessageDetails, + OffScreenViewport, + OrthographicViewState, + OutputMessageAlert, + OutputMessagePriority, + OutputMessageType, + ParseAndRunResult, + ParticleCollectionBuilder, + PerModelCategoryVisibility, + PhysicalModelState, + Pixel, + PrimitiveTool, + queryTerrainElevationOffset, + readElementGraphics, + readGltfGraphics, + RenderClipVolume, + RenderContext, + RenderGraphic, + RenderGraphicOwner, + RenderSystem, + Scene, + ScreenViewport, + SectionDrawingModelState, + SelectionMethod, + SelectionMode, + SelectionProcessing, + SelectionSet, + SelectionSetEventType, + SheetModelState, + SheetViewState, + SnapDetail, + SnapHeat, + SnapMode, + SnapStatus, + SpatialLocationModelState, + SpatialModelState, + SpatialViewState, + Sprite, + SpriteLocation, + StandardViewId, + StartOrResume, + synchronizeViewportFrusta, + synchronizeViewportViews, + TentativePoint, + Tile, + TileAdmin, + TileBoundingBoxes, + TileDrawArgs, + TileGraphicType, + TileLoadPriority, + TileLoadStatus, + TileRequest, + TileRequestChannel, + TileRequestChannels, + TileRequestChannelStatistics, + Tiles, + TileTree, + TileTreeLoadStatus, + TileTreeReference, + TileUsageMarker, + TileVisibility, + Tool, + ToolAdmin, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolSettings, + TwoWayViewportFrustumSync, + TwoWayViewportSync, + UniformType, + VaryingType, + ViewClipClearTool, + ViewClipDecoration, + ViewClipDecorationProvider, + ViewClipTool, + ViewCreator2d, + ViewCreator3d, + ViewingSpace, + ViewManager, + ViewManip, + Viewport, + ViewPose, + ViewPose2d, + ViewPose3d, + ViewRect, + ViewState, + ViewState2d, + ViewState3d, + ViewStatus, + ViewTool, } from "@itwin/core-frontend"; export type { - Animator, - BatchOptions, - BeButtonEventProps, - BeTouchEventProps, - BeWheelEventProps, - CanvasDecoration, - CanvasDecorationList, - ComputeChordToleranceArgs, - CreateTextureArgs, - CreateTextureFromSourceArgs, - CustomGraphicBuilderOptions, - Decorator, - ExtentLimits, - FeatureOverrideProvider, - FlashSettingsOptions, - FrontendSecurityOptions, - FuzzySearchResult, - GlobalAlignmentOptions, - GlobalLocation, - GlobalLocationArea, - GpuMemoryLimit, - GpuMemoryLimits, - GraphicArc, - GraphicArc2d, - GraphicBranchOptions, - GraphicBuilderOptions, - GraphicLineString, - GraphicLineString2d, - GraphicList, - GraphicLoop, - GraphicPath, - GraphicPointString, - GraphicPointString2d, - GraphicPolyface, - GraphicPrimitive, - GraphicPrimitive2d, - GraphicShape, - GraphicShape2d, - GraphicSolidPrimitive, - HitListHolder, - IModelIdArg, - MarginOptions, - MarkerFillStyle, - MarkerImage, - MarkerTextAlign, - MarkerTextBaseline, - OnViewExtentsError, - OsmBuildingDisplayOptions, - PaddingPercent, - ParseKeyinError, - ParseKeyinResult, - ParsedKeyin, - ParticleCollectionBuilder, - ParticleCollectionBuilderParams, - ParticleProps, - PickableGraphicOptions, - ReadGltfGraphicsArgs, - ReadPixelsArgs, - ScreenSpaceEffectBuilder, - ScreenSpaceEffectBuilderParams, - ScreenSpaceEffectContext, - ScreenSpaceEffectSource, - SelectAddEvent, - SelectRemoveEvent, - SelectReplaceEvent, - SelectedViewportChangedArgs, - SelectionSetEvent, - SynchronizeViewports, - TextureCacheKey, - TextureCacheOwnership, - TextureImage, - TextureImageSource, - TextureOwnership, - TileContent, - TileDrawArgParams, - TileParams, - TileTreeDiscloser, - TileTreeOwner, - TileTreeParams, - TileTreeSupplier, - TiledGraphicsProvider, - ToolAssistanceInputKey, - ToolAssistanceInstruction, - ToolAssistanceInstructions, - ToolAssistanceKeyboardInfo, - ToolAssistancePromptKey, - ToolAssistanceSection, - ToolList, - ToolTipOptions, - ToolType, - TxnEntityChange, - TxnEntityChangeIterable, - TxnEntityChangeType, - TxnEntityChanges, - TxnEntityChangesFilterOptions, - TxnEntityMetadata, - TxnEntityMetadataCriterion, - Uniform, - UniformArrayParams, - UniformContext, - UniformParams, - ViewAnimationOptions, - ViewChangeOptions, - ViewClipEventHandler, - ViewCreator2dOptions, - ViewCreator3dOptions, - ViewportGraphicBuilderOptions + Animator, + BatchOptions, + BeButtonEventProps, + BeTouchEventProps, + BeWheelEventProps, + CanvasDecoration, + CanvasDecorationList, + ComputeChordToleranceArgs, + CreateTextureArgs, + CreateTextureFromSourceArgs, + CustomGraphicBuilderOptions, + Decorator, + ExtentLimits, + FeatureOverrideProvider, + FlashSettingsOptions, + FrontendSecurityOptions, + FuzzySearchResult, + GlobalAlignmentOptions, + GlobalLocation, + GlobalLocationArea, + GpuMemoryLimit, + GpuMemoryLimits, + GraphicArc, + GraphicArc2d, + GraphicBranchOptions, + GraphicBuilderOptions, + GraphicLineString, + GraphicLineString2d, + GraphicList, + GraphicLoop, + GraphicPath, + GraphicPointString, + GraphicPointString2d, + GraphicPolyface, + GraphicPrimitive, + GraphicPrimitive2d, + GraphicShape, + GraphicShape2d, + GraphicSolidPrimitive, + HitListHolder, + IModelIdArg, + MarginOptions, + MarkerFillStyle, + MarkerImage, + MarkerTextAlign, + MarkerTextBaseline, + OnViewExtentsError, + OsmBuildingDisplayOptions, + PaddingPercent, + ParsedKeyin, + ParseKeyinError, + ParseKeyinResult, + ParticleCollectionBuilder, + ParticleCollectionBuilderParams, + ParticleProps, + PickableGraphicOptions, + ReadGltfGraphicsArgs, + ReadPixelsArgs, + ScreenSpaceEffectBuilder, + ScreenSpaceEffectBuilderParams, + ScreenSpaceEffectContext, + ScreenSpaceEffectSource, + SelectAddEvent, + SelectedViewportChangedArgs, + SelectionSetEvent, + SelectRemoveEvent, + SelectReplaceEvent, + SynchronizeViewports, + TextureCacheKey, + TextureCacheOwnership, + TextureImage, + TextureImageSource, + TextureOwnership, + TileContent, + TiledGraphicsProvider, + TileDrawArgParams, + TileParams, + TileTreeDiscloser, + TileTreeOwner, + TileTreeParams, + TileTreeSupplier, + ToolAssistanceInputKey, + ToolAssistanceInstruction, + ToolAssistanceInstructions, + ToolAssistanceKeyboardInfo, + ToolAssistancePromptKey, + ToolAssistanceSection, + ToolList, + ToolTipOptions, + ToolType, + TxnEntityChange, + TxnEntityChangeIterable, + TxnEntityChanges, + TxnEntityChangesFilterOptions, + TxnEntityChangeType, + TxnEntityMetadata, + TxnEntityMetadataCriterion, + Uniform, + UniformArrayParams, + UniformContext, + UniformParams, + ViewAnimationOptions, + ViewChangeOptions, + ViewClipEventHandler, + ViewCreator2dOptions, + ViewCreator3dOptions, + ViewportGraphicBuilderOptions, } from "@itwin/core-frontend"; export { - BackgroundFill, - BackgroundMapType, - BatchType, - BisCodeSpec, - BriefcaseIdValue, - ChangeOpCode, - ChangedValueState, - ChangesetType, - ClipIntersectionStyle, - ColorByName, - ColorDef, - CommonLoggerCategory, - ECSqlSystemProperty, - ECSqlValueType, - ElementGeometryOpcode, - FeatureOverrideType, - FillDisplay, - FillFlags, - FontType, - FrustumPlanes, - GeoCoordStatus, - GeometryClass, - GeometryStreamFlags, - GeometrySummaryVerbosity, - GlobeMode, - GridOrientationType, - HSVConstants, - ImageBufferFormat, - ImageSourceFormat, - LinePixels, - MassPropertiesOperation, - MonochromeMode, - Npc, - PlanarClipMaskMode, - PlanarClipMaskPriority, - QParams2d, - QParams3d, - QPoint2d, - QPoint2dBuffer, - QPoint2dBufferBuilder, - QPoint2dList, - QPoint3d, - QPoint3dBuffer, - QPoint3dBufferBuilder, - QPoint3dList, - Quantization, - QueryRowFormat, - Rank, - RenderMode, - SectionType, - SkyBoxImageType, - SpatialClassifierInsideDisplay, - SpatialClassifierOutsideDisplay, - SyncMode, - TerrainHeightOriginMode, - TextureMapUnits, - ThematicDisplayMode, - ThematicGradientColorScheme, - ThematicGradientMode, - ThematicGradientTransparencyMode, - TxnAction, - TypeOfChange + BackgroundFill, + BackgroundMapType, + BatchType, + BisCodeSpec, + BriefcaseIdValue, + ChangedValueState, + ChangeOpCode, + ChangesetType, + ClipIntersectionStyle, + ColorByName, + ColorDef, + CommonLoggerCategory, + ECSqlSystemProperty, + ECSqlValueType, + ElementGeometryOpcode, + FeatureOverrideType, + FillDisplay, + FillFlags, + FontType, + FrustumPlanes, + GeoCoordStatus, + GeometryClass, + GeometryStreamFlags, + GeometrySummaryVerbosity, + GlobeMode, + GridOrientationType, + HSVConstants, + ImageBufferFormat, + ImageSourceFormat, + LinePixels, + MassPropertiesOperation, + MonochromeMode, + Npc, + PlanarClipMaskMode, + PlanarClipMaskPriority, + QParams2d, + QParams3d, + QPoint2d, + QPoint2dBuffer, + QPoint2dBufferBuilder, + QPoint2dList, + QPoint3d, + QPoint3dBuffer, + QPoint3dBufferBuilder, + QPoint3dList, + Quantization, + QueryRowFormat, + Rank, + RenderMode, + SectionType, + SkyBoxImageType, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + SyncMode, + TerrainHeightOriginMode, + TextureMapUnits, + ThematicDisplayMode, + ThematicGradientColorScheme, + ThematicGradientMode, + ThematicGradientTransparencyMode, + TxnAction, + TypeOfChange, } from "@itwin/core-common"; export type { - AdditionalTransformProps, - AffineTransformProps, - AmbientLightProps, - AnalysisStyleDisplacementProps, - AnalysisStyleProps, - AnalysisStyleThematicProps, - AppearanceOverrideProps, - AreaFillProps, - AuxCoordSystem2dProps, - AuxCoordSystem3dProps, - AuxCoordSystemProps, - AxisAlignedBox3d, - AxisAlignedBox3dProps, - BRepPrimitive, - BackgroundMapProps, - BackgroundMapProviderName, - Base64EncodedString, - BaseReaderOptions, - BriefcaseId, - CalloutProps, - CameraProps, - Carto2DDegreesProps, - CartographicProps, - CategoryProps, - CategorySelectorProps, - ChangedElements, - ChangedEntities, - ChangesetId, - ChangesetIdWithIndex, - ChangesetIndex, - ChangesetIndexAndId, - ChangesetIndexOrId, - ChangesetRange, - ChannelRootAspectProps, - ClipIntersectionStyleProps, - ClipStyleCreateArgs, - ClipStyleProps, - CodeProps, - CodeScopeProps, - ColorDefProps, - ContextRealityModelProps, - ContextRealityModelsContainer, - CutStyleProps, - DanishSystem34Region, - DefinitionElementProps, - DeletedElementGeometryChange, - DeprecatedBackgroundMapProps, - DisplayStyle3dProps, - DisplayStyle3dSettingsProps, - DisplayStyleLoadProps, - DisplayStyleModelAppearanceProps, - DisplayStyleOverridesOptions, - DisplayStylePlanarClipMaskProps, - DisplayStyleProps, - DisplayStyleSettingsOptions, - DisplayStyleSettingsProps, - DisplayStyleSubCategoryProps, - DynamicGraphicsRequest2dProps, - DynamicGraphicsRequest3dProps, - DynamicGraphicsRequestProps, - EasingFunction, - EcefLocationProps, - ElementAlignedBox2d, - ElementAlignedBox3d, - ElementAspectProps, - ElementGeometryChange, - ElementGeometryDataEntry, - ElementGraphicsRequestProps, - ElementIdsAndRangesProps, - ElementLoadOptions, - ElementLoadProps, - ElementProps, - EmphasizeElementsProps, - EntityIdAndClassId, - EntityIdAndClassIdIterable, - EntityProps, - EntityQueryParams, - EnvironmentProps, - ExtantElementGeometryChange, - ExternalSourceAspectProps, - FeatureAppearanceProps, - FeatureAppearanceProvider, - FeatureAppearanceSource, - FilePropertyProps, - FlatBufferGeometryStream, - FontId, - FontMapProps, - FresnelSettingsProps, - FunctionalElementProps, - GeocentricTransformProps, - GeodeticDatumProps, - GeodeticEllipsoidProps, - GeodeticTransformMethod, - GeodeticTransformProps, - GeographicCRSProps, - GeometricElement2dProps, - GeometricElement3dProps, - GeometricElementProps, - GeometricModel2dProps, - GeometricModel3dProps, - GeometricModelProps, - GeometryAppearanceProps, - GeometryContainmentRequestProps, - GeometryContainmentResponseProps, - GeometryPartInstanceProps, - GeometryPartProps, - GeometryPrimitive, - GeometryStreamEntryProps, - GeometryStreamHeaderProps, - GeometryStreamIteratorEntry, - GeometryStreamPrimitive, - GeometryStreamProps, - GeometrySummaryOptions, - GeometrySummaryRequestProps, - GraphicsRequestProps, - GridFileDefinitionProps, - GridFileDirection, - GridFileFormat, - GridFileTransformProps, - GroundPlaneProps, - Helmert2DWithZOffsetProps, - HemisphereEnum, - HemisphereLightsProps, - HorizontalCRSExtentProps, - HorizontalCRSProps, - ImageGraphicCornersProps, - ImageGraphicProps, - ImagePrimitive, - InformationPartitionElementProps, - InterpolationFunction, - JsonGeometryStream, - LightSettingsProps, - LineStyleProps, - LocalAlignedBox3d, - LocalBriefcaseProps, - Localization, - MassPropertiesRequestProps, - MassPropertiesResponseProps, - MaterialProps, - ModelClipGroupProps, - ModelGeometryChanges, - ModelGeometryChangesProps, - ModelIdAndGeometryGuid, - ModelLoadProps, - ModelProps, - ModelQueryParams, - ModelSelectorProps, - NavigationBindingValue, - NavigationValue, - PartReference, - PersistentBackgroundMapProps, - PersistentGraphicsRequestProps, - PhysicalElementProps, - PhysicalTypeProps, - Placement, - Placement2dProps, - Placement3dProps, - PlacementProps, - PlanProjectionSettingsProps, - PlanarClipMaskProps, - Point2dProps, - PositionalVectorTransformProps, - ProjectionMethod, - ProjectionProps, - QPoint2dBuffer, - QPoint3dBuffer, - QueryLimit, - QueryOptions, - QueryQuota, - RelatedElementProps, - RelationshipProps, - RemoveFunction, - RenderMaterialAssetProps, - RenderMaterialProps, - RenderTimelineLoadProps, - RenderTimelineProps, - RepositoryLinkProps, - RequestNewBriefcaseProps, - RgbColorProps, - RgbFactorProps, - RootSubjectProps, - RpcActivity, - SectionDrawingLocationProps, - SectionDrawingProps, - SectionDrawingViewProps, - SessionProps, - SheetProps, - SkyBoxImageProps, - SkyBoxProps, - SkyCubeProps, - SolarLightProps, - SolarShadowSettingsProps, - SourceAndTarget, - SpatialClassifierFlagsProps, - SpatialClassifierProps, - SpatialClassifiersContainer, - SpatialViewDefinitionProps, - SubCategoryProps, - SubjectProps, - TerrainProps, - TerrainProviderName, - TextAnnotation2dProps, - TextAnnotation3dProps, - TextStringPrimitive, - TextStringProps, - TextureData, - TextureLoadProps, - TextureMapProps, - TextureProps, - ThematicDisplayProps, - ThematicDisplaySensorProps, - ThematicDisplaySensorSettingsProps, - ThematicGradientSettingsProps, - ThumbnailFormatProps, - ThumbnailProps, - TileVersionInfo, - TweenCallback, - TypeDefinitionElementProps, - UnitType, - UpdateCallback, - UrlLinkProps, - VerticalCRSProps, - ViewAttachmentLabelProps, - ViewAttachmentProps, - ViewDefinition2dProps, - ViewDefinition3dProps, - ViewDefinitionProps, - ViewDetails3dProps, - ViewDetailsProps, - ViewFlagOverrides, - ViewFlagProps, - ViewFlagsProperties, - ViewQueryParams, - ViewStateLoadProps, - ViewStateProps, - WhiteOnWhiteReversalProps, - XyzRotationProps + AdditionalTransformProps, + AffineTransformProps, + AmbientLightProps, + AnalysisStyleDisplacementProps, + AnalysisStyleProps, + AnalysisStyleThematicProps, + AppearanceOverrideProps, + AreaFillProps, + AuxCoordSystem2dProps, + AuxCoordSystem3dProps, + AuxCoordSystemProps, + AxisAlignedBox3d, + AxisAlignedBox3dProps, + BackgroundMapProps, + BackgroundMapProviderName, + Base64EncodedString, + BaseReaderOptions, + BRepPrimitive, + BriefcaseId, + CalloutProps, + CameraProps, + Carto2DDegreesProps, + CartographicProps, + CategoryProps, + CategorySelectorProps, + ChangedElements, + ChangedEntities, + ChangesetId, + ChangesetIdWithIndex, + ChangesetIndex, + ChangesetIndexAndId, + ChangesetIndexOrId, + ChangesetRange, + ChannelRootAspectProps, + ClipIntersectionStyleProps, + ClipStyleCreateArgs, + ClipStyleProps, + CodeProps, + CodeScopeProps, + ColorDefProps, + ContextRealityModelProps, + ContextRealityModelsContainer, + CutStyleProps, + DanishSystem34Region, + DefinitionElementProps, + DeletedElementGeometryChange, + DeprecatedBackgroundMapProps, + DisplayStyle3dProps, + DisplayStyle3dSettingsProps, + DisplayStyleLoadProps, + DisplayStyleModelAppearanceProps, + DisplayStyleOverridesOptions, + DisplayStylePlanarClipMaskProps, + DisplayStyleProps, + DisplayStyleSettingsOptions, + DisplayStyleSettingsProps, + DisplayStyleSubCategoryProps, + DynamicGraphicsRequest2dProps, + DynamicGraphicsRequest3dProps, + DynamicGraphicsRequestProps, + EasingFunction, + EcefLocationProps, + ElementAlignedBox2d, + ElementAlignedBox3d, + ElementAspectProps, + ElementGeometryChange, + ElementGeometryDataEntry, + ElementGraphicsRequestProps, + ElementIdsAndRangesProps, + ElementLoadOptions, + ElementLoadProps, + ElementProps, + EmphasizeElementsProps, + EntityIdAndClassId, + EntityIdAndClassIdIterable, + EntityProps, + EntityQueryParams, + EnvironmentProps, + ExtantElementGeometryChange, + ExternalSourceAspectProps, + FeatureAppearanceProps, + FeatureAppearanceProvider, + FeatureAppearanceSource, + FilePropertyProps, + FlatBufferGeometryStream, + FontId, + FontMapProps, + FresnelSettingsProps, + FunctionalElementProps, + GeocentricTransformProps, + GeodeticDatumProps, + GeodeticEllipsoidProps, + GeodeticTransformMethod, + GeodeticTransformProps, + GeographicCRSProps, + GeometricElement2dProps, + GeometricElement3dProps, + GeometricElementProps, + GeometricModel2dProps, + GeometricModel3dProps, + GeometricModelProps, + GeometryAppearanceProps, + GeometryContainmentRequestProps, + GeometryContainmentResponseProps, + GeometryPartInstanceProps, + GeometryPartProps, + GeometryPrimitive, + GeometryStreamEntryProps, + GeometryStreamHeaderProps, + GeometryStreamIteratorEntry, + GeometryStreamPrimitive, + GeometryStreamProps, + GeometrySummaryOptions, + GeometrySummaryRequestProps, + GraphicsRequestProps, + GridFileDefinitionProps, + GridFileDirection, + GridFileFormat, + GridFileTransformProps, + GroundPlaneProps, + Helmert2DWithZOffsetProps, + HemisphereEnum, + HemisphereLightsProps, + HorizontalCRSExtentProps, + HorizontalCRSProps, + ImageGraphicCornersProps, + ImageGraphicProps, + ImagePrimitive, + InformationPartitionElementProps, + InterpolationFunction, + JsonGeometryStream, + LightSettingsProps, + LineStyleProps, + LocalAlignedBox3d, + LocalBriefcaseProps, + Localization, + MassPropertiesRequestProps, + MassPropertiesResponseProps, + MaterialProps, + ModelClipGroupProps, + ModelGeometryChanges, + ModelGeometryChangesProps, + ModelIdAndGeometryGuid, + ModelLoadProps, + ModelProps, + ModelQueryParams, + ModelSelectorProps, + NavigationBindingValue, + NavigationValue, + PartReference, + PersistentBackgroundMapProps, + PersistentGraphicsRequestProps, + PhysicalElementProps, + PhysicalTypeProps, + Placement, + Placement2dProps, + Placement3dProps, + PlacementProps, + PlanarClipMaskProps, + PlanProjectionSettingsProps, + Point2dProps, + PositionalVectorTransformProps, + ProjectionMethod, + ProjectionProps, + QPoint2dBuffer, + QPoint3dBuffer, + QueryLimit, + QueryOptions, + QueryQuota, + RelatedElementProps, + RelationshipProps, + RemoveFunction, + RenderMaterialAssetProps, + RenderMaterialProps, + RenderTimelineLoadProps, + RenderTimelineProps, + RepositoryLinkProps, + RequestNewBriefcaseProps, + RgbColorProps, + RgbFactorProps, + RootSubjectProps, + RpcActivity, + SectionDrawingLocationProps, + SectionDrawingProps, + SectionDrawingViewProps, + SessionProps, + SheetProps, + SkyBoxImageProps, + SkyBoxProps, + SkyCubeProps, + SolarLightProps, + SolarShadowSettingsProps, + SourceAndTarget, + SpatialClassifierFlagsProps, + SpatialClassifierProps, + SpatialClassifiersContainer, + SpatialViewDefinitionProps, + SubCategoryProps, + SubjectProps, + TerrainProps, + TerrainProviderName, + TextAnnotation2dProps, + TextAnnotation3dProps, + TextStringPrimitive, + TextStringProps, + TextureData, + TextureLoadProps, + TextureMapProps, + TextureProps, + ThematicDisplayProps, + ThematicDisplaySensorProps, + ThematicDisplaySensorSettingsProps, + ThematicGradientSettingsProps, + ThumbnailFormatProps, + ThumbnailProps, + TileVersionInfo, + TweenCallback, + TypeDefinitionElementProps, + UnitType, + UpdateCallback, + UrlLinkProps, + VerticalCRSProps, + ViewAttachmentLabelProps, + ViewAttachmentProps, + ViewDefinition2dProps, + ViewDefinition3dProps, + ViewDefinitionProps, + ViewDetails3dProps, + ViewDetailsProps, + ViewFlagOverrides, + ViewFlagProps, + ViewFlagsProperties, + ViewQueryParams, + ViewStateLoadProps, + ViewStateProps, + WhiteOnWhiteReversalProps, + XyzRotationProps, } from "@itwin/core-common"; // END GENERATED CODE diff --git a/core/extension/index.js b/core/extension/index.js index f976181f1dfb..01c8002896b6 100644 --- a/core/extension/index.js +++ b/core/extension/index.js @@ -12,259 +12,259 @@ export const { ExtensionHost } = ext.exports; // BEGIN GENERATED CODE export const { -// @itwin/core-frontend: - ACSDisplayOptions, - ACSType, - AccuDrawHintBuilder, - AccuSnap, - ActivityMessageDetails, - ActivityMessageEndReason, - AuxCoordSystem2dState, - AuxCoordSystem3dState, - AuxCoordSystemSpatialState, - AuxCoordSystemState, - BeButton, - BeButtonEvent, - BeButtonState, - BeModifierKeys, - BeTouchEvent, - BeWheelEvent, - BingElevationProvider, - BingLocationProvider, - CategorySelectorState, - ChangeFlags, - ClipEventType, - Cluster, - ContextRealityModelState, - ContextRotationId, - CoordSource, - CoordSystem, - CoordinateLockOverrides, - DecorateContext, - Decorations, - DisclosedTileTreeSet, - DisplayStyle2dState, - DisplayStyle3dState, - DisplayStyleState, - DrawingModelState, - DrawingViewState, - EditManipulator, - ElementLocateManager, - ElementPicker, - ElementState, - EmphasizeElements, - EntityState, - EventController, - EventHandled, - FeatureSymbology, - FlashMode, - FlashSettings, - FrontendLoggerCategory, - FrustumAnimator, - GeometricModel2dState, - GeometricModel3dState, - GeometricModelState, - GlobeAnimator, - GraphicAssembler, - GraphicBranch, - GraphicBuilder, - GraphicType, - HiliteSet, - HitDetail, - HitDetailType, - HitGeomType, - HitList, - HitParentGeomType, - HitPriority, - HitSource, - IModelConnection, - IconSprites, - InputCollector, - InputSource, - InteractiveTool, - IntersectDetail, - KeyinParseError, - LocateAction, - LocateFilterStatus, - LocateOptions, - LocateResponse, - ManipulatorToolEvent, - MarginPercent, - Marker, - MarkerSet, - MessageBoxIconType, - MessageBoxType, - MessageBoxValue, - ModelSelectorState, - ModelState, - NotificationHandler, - NotificationManager, - NotifyMessageDetails, - OffScreenViewport, - OrthographicViewState, - OutputMessageAlert, - OutputMessagePriority, - OutputMessageType, - ParseAndRunResult, - ParticleCollectionBuilder, - PerModelCategoryVisibility, - PhysicalModelState, - Pixel, - PrimitiveTool, - RenderClipVolume, - RenderContext, - RenderGraphic, - RenderGraphicOwner, - RenderSystem, - Scene, - ScreenViewport, - SectionDrawingModelState, - SelectionMethod, - SelectionMode, - SelectionProcessing, - SelectionSet, - SelectionSetEventType, - SheetModelState, - SheetViewState, - SnapDetail, - SnapHeat, - SnapMode, - SnapStatus, - SpatialLocationModelState, - SpatialModelState, - SpatialViewState, - Sprite, - SpriteLocation, - StandardViewId, - StartOrResume, - TentativePoint, - Tile, - TileAdmin, - TileBoundingBoxes, - TileDrawArgs, - TileGraphicType, - TileLoadPriority, - TileLoadStatus, - TileRequest, - TileRequestChannel, - TileRequestChannelStatistics, - TileRequestChannels, - TileTree, - TileTreeLoadStatus, - TileTreeReference, - TileUsageMarker, - TileVisibility, - Tiles, - Tool, - ToolAdmin, - ToolAssistance, - ToolAssistanceImage, - ToolAssistanceInputMethod, - ToolSettings, - TwoWayViewportFrustumSync, - TwoWayViewportSync, - UniformType, - VaryingType, - ViewClipClearTool, - ViewClipDecoration, - ViewClipDecorationProvider, - ViewClipTool, - ViewCreator2d, - ViewCreator3d, - ViewManager, - ViewManip, - ViewPose, - ViewPose2d, - ViewPose3d, - ViewRect, - ViewState, - ViewState2d, - ViewState3d, - ViewStatus, - ViewTool, - ViewingSpace, - Viewport, - canvasToImageBuffer, - canvasToResizedCanvasWithBars, - connectViewportFrusta, - connectViewportViews, - connectViewports, - extractImageSourceDimensions, - getCompressedJpegFromCanvas, - getImageSourceFormatForMimeType, - getImageSourceMimeType, - imageBufferToBase64EncodedPng, - imageBufferToCanvas, - imageBufferToPngDataUrl, - imageElementFromImageSource, - imageElementFromUrl, - queryTerrainElevationOffset, - readElementGraphics, - readGltfGraphics, - synchronizeViewportFrusta, - synchronizeViewportViews, -// @itwin/core-common: - BackgroundFill, - BackgroundMapType, - BatchType, - BisCodeSpec, - BriefcaseIdValue, - ChangeOpCode, - ChangedValueState, - ChangesetType, - ClipIntersectionStyle, - ColorByName, - ColorDef, - CommonLoggerCategory, - ECSqlSystemProperty, - ECSqlValueType, - ElementGeometryOpcode, - FeatureOverrideType, - FillDisplay, - FillFlags, - FontType, - FrustumPlanes, - GeoCoordStatus, - GeometryClass, - GeometryStreamFlags, - GeometrySummaryVerbosity, - GlobeMode, - GridOrientationType, - HSVConstants, - ImageBufferFormat, - ImageSourceFormat, - LinePixels, - MassPropertiesOperation, - MonochromeMode, - Npc, - PlanarClipMaskMode, - PlanarClipMaskPriority, - QParams2d, - QParams3d, - QPoint2d, - QPoint2dBuffer, - QPoint2dBufferBuilder, - QPoint2dList, - QPoint3d, - QPoint3dBuffer, - QPoint3dBufferBuilder, - QPoint3dList, - Quantization, - QueryRowFormat, - Rank, - RenderMode, - SectionType, - SkyBoxImageType, - SpatialClassifierInsideDisplay, - SpatialClassifierOutsideDisplay, - SyncMode, - TerrainHeightOriginMode, - TextureMapUnits, - ThematicDisplayMode, - ThematicGradientColorScheme, - ThematicGradientMode, - ThematicGradientTransparencyMode, - TxnAction, - TypeOfChange, + // @itwin/core-frontend: + ACSDisplayOptions, + ACSType, + AccuDrawHintBuilder, + AccuSnap, + ActivityMessageDetails, + ActivityMessageEndReason, + AuxCoordSystem2dState, + AuxCoordSystem3dState, + AuxCoordSystemSpatialState, + AuxCoordSystemState, + BeButton, + BeButtonEvent, + BeButtonState, + BeModifierKeys, + BeTouchEvent, + BeWheelEvent, + BingElevationProvider, + BingLocationProvider, + CategorySelectorState, + ChangeFlags, + ClipEventType, + Cluster, + ContextRealityModelState, + ContextRotationId, + CoordSource, + CoordSystem, + CoordinateLockOverrides, + DecorateContext, + Decorations, + DisclosedTileTreeSet, + DisplayStyle2dState, + DisplayStyle3dState, + DisplayStyleState, + DrawingModelState, + DrawingViewState, + EditManipulator, + ElementLocateManager, + ElementPicker, + ElementState, + EmphasizeElements, + EntityState, + EventController, + EventHandled, + FeatureSymbology, + FlashMode, + FlashSettings, + FrontendLoggerCategory, + FrustumAnimator, + GeometricModel2dState, + GeometricModel3dState, + GeometricModelState, + GlobeAnimator, + GraphicAssembler, + GraphicBranch, + GraphicBuilder, + GraphicType, + HiliteSet, + HitDetail, + HitDetailType, + HitGeomType, + HitList, + HitParentGeomType, + HitPriority, + HitSource, + IModelConnection, + IconSprites, + InputCollector, + InputSource, + InteractiveTool, + IntersectDetail, + KeyinParseError, + LocateAction, + LocateFilterStatus, + LocateOptions, + LocateResponse, + ManipulatorToolEvent, + MarginPercent, + Marker, + MarkerSet, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + ModelSelectorState, + ModelState, + NotificationHandler, + NotificationManager, + NotifyMessageDetails, + OffScreenViewport, + OrthographicViewState, + OutputMessageAlert, + OutputMessagePriority, + OutputMessageType, + ParseAndRunResult, + ParticleCollectionBuilder, + PerModelCategoryVisibility, + PhysicalModelState, + Pixel, + PrimitiveTool, + RenderClipVolume, + RenderContext, + RenderGraphic, + RenderGraphicOwner, + RenderSystem, + Scene, + ScreenViewport, + SectionDrawingModelState, + SelectionMethod, + SelectionMode, + SelectionProcessing, + SelectionSet, + SelectionSetEventType, + SheetModelState, + SheetViewState, + SnapDetail, + SnapHeat, + SnapMode, + SnapStatus, + SpatialLocationModelState, + SpatialModelState, + SpatialViewState, + Sprite, + SpriteLocation, + StandardViewId, + StartOrResume, + TentativePoint, + Tile, + TileAdmin, + TileBoundingBoxes, + TileDrawArgs, + TileGraphicType, + TileLoadPriority, + TileLoadStatus, + TileRequest, + TileRequestChannel, + TileRequestChannelStatistics, + TileRequestChannels, + TileTree, + TileTreeLoadStatus, + TileTreeReference, + TileUsageMarker, + TileVisibility, + Tiles, + Tool, + ToolAdmin, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolSettings, + TwoWayViewportFrustumSync, + TwoWayViewportSync, + UniformType, + VaryingType, + ViewClipClearTool, + ViewClipDecoration, + ViewClipDecorationProvider, + ViewClipTool, + ViewCreator2d, + ViewCreator3d, + ViewManager, + ViewManip, + ViewPose, + ViewPose2d, + ViewPose3d, + ViewRect, + ViewState, + ViewState2d, + ViewState3d, + ViewStatus, + ViewTool, + ViewingSpace, + Viewport, + canvasToImageBuffer, + canvasToResizedCanvasWithBars, + connectViewportFrusta, + connectViewportViews, + connectViewports, + extractImageSourceDimensions, + getCompressedJpegFromCanvas, + getImageSourceFormatForMimeType, + getImageSourceMimeType, + imageBufferToBase64EncodedPng, + imageBufferToCanvas, + imageBufferToPngDataUrl, + imageElementFromImageSource, + imageElementFromUrl, + queryTerrainElevationOffset, + readElementGraphics, + readGltfGraphics, + synchronizeViewportFrusta, + synchronizeViewportViews, + // @itwin/core-common: + BackgroundFill, + BackgroundMapType, + BatchType, + BisCodeSpec, + BriefcaseIdValue, + ChangeOpCode, + ChangedValueState, + ChangesetType, + ClipIntersectionStyle, + ColorByName, + ColorDef, + CommonLoggerCategory, + ECSqlSystemProperty, + ECSqlValueType, + ElementGeometryOpcode, + FeatureOverrideType, + FillDisplay, + FillFlags, + FontType, + FrustumPlanes, + GeoCoordStatus, + GeometryClass, + GeometryStreamFlags, + GeometrySummaryVerbosity, + GlobeMode, + GridOrientationType, + HSVConstants, + ImageBufferFormat, + ImageSourceFormat, + LinePixels, + MassPropertiesOperation, + MonochromeMode, + Npc, + PlanarClipMaskMode, + PlanarClipMaskPriority, + QParams2d, + QParams3d, + QPoint2d, + QPoint2dBuffer, + QPoint2dBufferBuilder, + QPoint2dList, + QPoint3d, + QPoint3dBuffer, + QPoint3dBufferBuilder, + QPoint3dList, + Quantization, + QueryRowFormat, + Rank, + RenderMode, + SectionType, + SkyBoxImageType, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + SyncMode, + TerrainHeightOriginMode, + TextureMapUnits, + ThematicDisplayMode, + ThematicGradientColorScheme, + ThematicGradientMode, + ThematicGradientTransparencyMode, + TxnAction, + TypeOfChange, } = ext.exports; // END GENERATED CODE diff --git a/core/frontend-devtools/eslint.config.js b/core/frontend-devtools/eslint.config.js index e626e3b08ba4..849e7479dee5 100644 --- a/core/frontend-devtools/eslint.config.js +++ b/core/frontend-devtools/eslint.config.js @@ -6,5 +6,5 @@ module.exports = [ files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, - ...eslintBaseConfig -]; \ No newline at end of file + ...eslintBaseConfig, +]; diff --git a/core/frontend-devtools/public/locales/en/FrontendDevTools.json b/core/frontend-devtools/public/locales/en/FrontendDevTools.json index e297165a40c1..487e0802039f 100644 --- a/core/frontend-devtools/public/locales/en/FrontendDevTools.json +++ b/core/frontend-devtools/public/locales/en/FrontendDevTools.json @@ -492,4 +492,4 @@ "keyin": "fdt bgcolor" } } -} \ No newline at end of file +} diff --git a/core/frontend-devtools/src/FrontEndDevTools.ts b/core/frontend-devtools/src/FrontEndDevTools.ts index de1fa8390764..42eb1bdeb49c 100644 --- a/core/frontend-devtools/src/FrontEndDevTools.ts +++ b/core/frontend-devtools/src/FrontEndDevTools.ts @@ -15,60 +15,136 @@ import { LensDistortionConfig, LensDistortionEffect } from "./effects/LensDistor import { SaturationConfig, SaturationEffect } from "./effects/Saturation"; import { SnowEffect } from "./effects/Snow"; import { VignetteConfig, VignetteEffect } from "./effects/Vignette"; -import { - MaskBackgroundMapByElementTool, MaskBackgroundMapByExcludedElementTool, MaskBackgroundMapByModelTool, MaskBackgroundMapBySubCategoryTool, MaskRealityModelByElementTool, MaskRealityModelByExcludedElementTool, - MaskRealityModelByModelTool, MaskRealityModelBySubCategoryTool, SetHigherPriorityRealityModelMasking, SetMapHigherPriorityMasking, UnmaskMapTool, UnmaskRealityModelTool, -} from "./tools/PlanarMaskTools"; -import { - ChangeCameraTool, ChangeEmphasisSettingsTool, ChangeFlashSettingsTool, ChangeHiliteModeTool, ChangeHiliteSettingsTool, DefaultTileSizeModifierTool, FadeOutTool, - FreezeSceneTool, SetAspectRatioSkewTool, ShowTileVolumesTool, Toggle3dManipulationsTool, ToggleDrawingGraphicsTool, ToggleSectionDrawingSpatialViewTool, - ToggleTileTreeReferencesTool, ToggleViewAttachmentBoundariesTool, ToggleViewAttachmentClipShapesTool, ToggleViewAttachmentsTool, ViewportAddRealityModel, - ViewportTileSizeModifierTool, -} from "./tools/ViewportTools"; import { AnimationIntervalTool } from "./tools/AnimationIntervalTool"; import { ChangeUnitsTool } from "./tools/ChangeUnitsTool"; import { ClipColorTool, ClipIntersectionTool, TestClipStyleTool, ToggleSectionCutTool } from "./tools/ClipTools"; import { - ApplyRenderingStyleTool, ChangeBackgroundColorTool, ChangeViewFlagsTool, OverrideSubCategoryTool, SaveRenderingStyleTool, SkyCubeTool, - SkySphereTool, ToggleSkyboxTool, ToggleWiremeshTool, WoWIgnoreBackgroundTool, + ApplyRenderingStyleTool, + ChangeBackgroundColorTool, + ChangeViewFlagsTool, + OverrideSubCategoryTool, + SaveRenderingStyleTool, + SkyCubeTool, + SkySphereTool, + ToggleSkyboxTool, + ToggleWiremeshTool, + WoWIgnoreBackgroundTool, } from "./tools/DisplayStyleTools"; -import { QueryScheduleScriptTool, ReverseScheduleScriptTool, SetScheduleScriptTool } from "./tools/ScheduleScriptTools"; import { - ClearEmphasizedElementsTool, ClearIsolatedElementsTool, EmphasizeSelectedElementsTool, EmphasizeVisibleElementsTool, IsolateSelectedElementsTool, + ClearEmphasizedElementsTool, + ClearIsolatedElementsTool, + EmphasizeSelectedElementsTool, + EmphasizeVisibleElementsTool, + IsolateSelectedElementsTool, } from "./tools/EmphasizeElementsTool"; import { ToggleFrustumSnapshotTool, ToggleSelectedViewFrustumTool, ToggleShadowFrustumTool } from "./tools/FrustumDecoration"; import { InspectElementTool } from "./tools/InspectElementTool"; import { AttachArcGISFeatureMapLayerByUrlTool, - AttachArcGISMapLayerByUrlTool, AttachMapLayerTool, AttachMapOverlayTool, AttachModelMapLayerTool, AttachOgcApiFeaturesMapLayerTool, AttachTileURLMapLayerByUrlTool, AttachWmsMapLayerByUrlTool, - AttachWmtsMapLayerByUrlTool, DetachMapLayersTool, MapBaseColorTool, MapBaseTransparencyTool, MapBaseVisibilityTool, MapLayerSubLayerVisibilityTool, - MapLayerTransparencyTool, MapLayerVisibilityTool, MapLayerZoomTool, ReorderMapLayers, SetMapBaseTool, ToggleTerrainTool, + AttachArcGISMapLayerByUrlTool, + AttachMapLayerTool, + AttachMapOverlayTool, + AttachModelMapLayerTool, + AttachOgcApiFeaturesMapLayerTool, + AttachTileURLMapLayerByUrlTool, + AttachWmsMapLayerByUrlTool, + AttachWmtsMapLayerByUrlTool, + DetachMapLayersTool, + MapBaseColorTool, + MapBaseTransparencyTool, + MapBaseVisibilityTool, + MapLayerSubLayerVisibilityTool, + MapLayerTransparencyTool, + MapLayerVisibilityTool, + MapLayerZoomTool, + ReorderMapLayers, + SetMapBaseTool, + ToggleTerrainTool, } from "./tools/MapLayerTool"; import { MeasureTileLoadTimeTool } from "./tools/MeasureTileLoadTime"; import { - ClearModelAppearanceOverrides, SetModelColorTool, SetModelEmphasizedTool, SetModelIgnoresMaterialsTool, SetModelLineCodeTool, - SetModelLineWeightTool, SetModelLocateTool, SetModelTransparencyTool, + ClearModelAppearanceOverrides, + SetModelColorTool, + SetModelEmphasizedTool, + SetModelIgnoresMaterialsTool, + SetModelLineCodeTool, + SetModelLineWeightTool, + SetModelLocateTool, + SetModelTransparencyTool, } from "./tools/ModelAppearanceTools"; +import { + MaskBackgroundMapByElementTool, + MaskBackgroundMapByExcludedElementTool, + MaskBackgroundMapByModelTool, + MaskBackgroundMapBySubCategoryTool, + MaskRealityModelByElementTool, + MaskRealityModelByExcludedElementTool, + MaskRealityModelByModelTool, + MaskRealityModelBySubCategoryTool, + SetHigherPriorityRealityModelMasking, + SetMapHigherPriorityMasking, + UnmaskMapTool, + UnmaskRealityModelTool, +} from "./tools/PlanarMaskTools"; import { ChangePlanProjectionSettingsTool, DumpPlanProjectionSettingsTool, OverrideSubCategoryPriorityTool } from "./tools/PlanProjectionTools"; import { ToggleProjectExtentsTool } from "./tools/ProjectExtents"; import { - AttachCesiumAssetTool, AttachRealityModelTool, ClearRealityModelAppearanceOverrides, DetachRealityModelTool, SaveRealityModelTool, - SetRealityModelColorTool, SetRealityModelEmphasizedTool, SetRealityModelLocateTool, SetRealityModelTransparencyTool, ToggleOSMBuildingDisplay, + AttachCesiumAssetTool, + AttachRealityModelTool, + ClearRealityModelAppearanceOverrides, + DetachRealityModelTool, + SaveRealityModelTool, + SetRealityModelColorTool, + SetRealityModelEmphasizedTool, + SetRealityModelLocateTool, + SetRealityModelTransparencyTool, + ToggleOSMBuildingDisplay, } from "./tools/RealityModelTools"; import { RealityTransitionTool } from "./tools/RealityTransitionTool"; import { CompileShadersTool, LoseWebGLContextTool, ToggleDPIForLODTool } from "./tools/RenderSystemTools"; import { - SetAASamplesTool, ToggleDrapeFrustumTool, ToggleMaskFrustumTool, ToggleNormalMaps, TogglePrimitiveVisibilityTool, ToggleReadPixelsTool, ToggleRealityTileBounds, ToggleRealityTileFreeze, - ToggleRealityTileLogging, ToggleRealityTilePreload, ToggleVolClassIntersect, + SetAASamplesTool, + ToggleDrapeFrustumTool, + ToggleMaskFrustumTool, + ToggleNormalMaps, + TogglePrimitiveVisibilityTool, + ToggleReadPixelsTool, + ToggleRealityTileBounds, + ToggleRealityTileFreeze, + ToggleRealityTileLogging, + ToggleRealityTilePreload, + ToggleVolClassIntersect, } from "./tools/RenderTargetTools"; import { ReportWebGLCompatibilityTool } from "./tools/ReportWebGLCompatibilityTool"; import { ApplyViewByIdTool, ApplyViewTool, SaveViewTool } from "./tools/SavedViews"; +import { QueryScheduleScriptTool, ReverseScheduleScriptTool, SetScheduleScriptTool } from "./tools/ScheduleScriptTools"; import { DumpSelectionSetTool, SelectElementsByIdTool } from "./tools/SelectionTools"; import { SetGpuMemoryLimitTool } from "./tools/SetGpuMemoryLimitTool"; import { ElementIdFromSourceAspectIdTool, SourceAspectIdFromElementIdTool } from "./tools/SourceAspectIdTools"; import { ToggleTileRequestDecorationTool } from "./tools/TileRequestDecoration"; import { ToggleTileTreeBoundsDecorationTool } from "./tools/TileTreeBoundsDecoration"; import { ToggleToolTipsTool } from "./tools/ToolTipProvider"; +import { + ChangeCameraTool, + ChangeEmphasisSettingsTool, + ChangeFlashSettingsTool, + ChangeHiliteModeTool, + ChangeHiliteSettingsTool, + DefaultTileSizeModifierTool, + FadeOutTool, + FreezeSceneTool, + SetAspectRatioSkewTool, + ShowTileVolumesTool, + Toggle3dManipulationsTool, + ToggleDrawingGraphicsTool, + ToggleSectionDrawingSpatialViewTool, + ToggleTileTreeReferencesTool, + ToggleViewAttachmentBoundariesTool, + ToggleViewAttachmentClipShapesTool, + ToggleViewAttachmentsTool, + ViewportAddRealityModel, + ViewportTileSizeModifierTool, +} from "./tools/ViewportTools"; /** Entry-point for the package. Before using the package you *must* call [[FrontendDevTools.initialize]]. * @beta diff --git a/core/frontend-devtools/src/effects/Convolution.ts b/core/frontend-devtools/src/effects/Convolution.ts index f44ead5a9c99..3731ce518a7f 100644 --- a/core/frontend-devtools/src/effects/Convolution.ts +++ b/core/frontend-devtools/src/effects/Convolution.ts @@ -14,12 +14,18 @@ import { AddEffectTool } from "./EffectTools"; * @beta */ export abstract class ConvolutionEffect extends AddEffectTool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } protected abstract get matrix(): number[]; - protected get textureCoordFromPosition() { return true; } + protected get textureCoordFromPosition() { + return true; + } protected get source() { return { @@ -85,12 +91,20 @@ export abstract class ConvolutionEffect extends AddEffectTool { */ export class GaussianBlurEffect extends ConvolutionEffect { public static override toolId = "GaussianBlurEffect"; - protected get effectName() { return "blur"; } + protected get effectName() { + return "blur"; + } protected get matrix() { return [ - 0.045, 0.122, 0.045, - 0.122, 0.332, 0.122, - 0.045, 0.122, 0.045, + 0.045, + 0.122, + 0.045, + 0.122, + 0.332, + 0.122, + 0.045, + 0.122, + 0.045, ]; } } @@ -100,12 +114,20 @@ export class GaussianBlurEffect extends ConvolutionEffect { */ export class UnsharpenEffect extends ConvolutionEffect { public static override toolId = "UnsharpenEffect"; - protected get effectName() { return "unsharpen"; } + protected get effectName() { + return "unsharpen"; + } protected get matrix() { return [ - -1, -1, -1, - -1, 9, -1, - -1, -1, -1, + -1, + -1, + -1, + -1, + 9, + -1, + -1, + -1, + -1, ]; } } @@ -115,12 +137,20 @@ export class UnsharpenEffect extends ConvolutionEffect { */ export class EmbossEffect extends ConvolutionEffect { public static override toolId = "EmbossEffect"; - protected get effectName() { return "emboss"; } + protected get effectName() { + return "emboss"; + } protected get matrix() { return [ - -2, -1, 0, - -1, 1, 1, - 0, 1, 2, + -2, + -1, + 0, + -1, + 1, + 1, + 0, + 1, + 2, ]; } } @@ -130,12 +160,20 @@ export class EmbossEffect extends ConvolutionEffect { */ export class SharpenEffect extends ConvolutionEffect { public static override toolId = "SharpenEffect"; - protected get effectName() { return "sharpen"; } + protected get effectName() { + return "sharpen"; + } protected get matrix() { return [ - 0, -1, 0, - -1, 5, -1, - 0, -1, 0, + 0, + -1, + 0, + -1, + 5, + -1, + 0, + -1, + 0, ]; } } @@ -145,12 +183,20 @@ export class SharpenEffect extends ConvolutionEffect { */ export class SharpnessEffect extends ConvolutionEffect { public static override toolId = "SharpnessEffect"; - protected get effectName() { return "sharpness"; } + protected get effectName() { + return "sharpness"; + } protected get matrix() { return [ - 0, -1, 0, - -1, 5, -1, - 0, -1, 0, + 0, + -1, + 0, + -1, + 5, + -1, + 0, + -1, + 0, ]; } } @@ -160,12 +206,20 @@ export class SharpnessEffect extends ConvolutionEffect { */ export class EdgeDetectionEffect extends ConvolutionEffect { public static override toolId = "EdgeDetectionEffect"; - protected get effectName() { return "edgedetect"; } + protected get effectName() { + return "edgedetect"; + } protected get matrix() { return [ - -5, 0, 0, - 0, 0, 0, - 0, 0, 5, + -5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 5, ]; } } diff --git a/core/frontend-devtools/src/effects/EffectTools.ts b/core/frontend-devtools/src/effects/EffectTools.ts index 55fc69266c78..705d5fa00a4e 100644 --- a/core/frontend-devtools/src/effects/EffectTools.ts +++ b/core/frontend-devtools/src/effects/EffectTools.ts @@ -7,9 +7,7 @@ */ import { assert } from "@itwin/core-bentley"; -import { - IModelApp, ScreenSpaceEffectBuilder, ScreenSpaceEffectSource, Tool, -} from "@itwin/core-frontend"; +import { IModelApp, ScreenSpaceEffectBuilder, ScreenSpaceEffectSource, Tool } from "@itwin/core-frontend"; /** Adds a screen-space effect to the selected viewport. * @beta @@ -57,8 +55,12 @@ export abstract class AddEffectTool extends Tool { */ export class ClearEffectsTool extends Tool { public static override toolId = "ClearEffects"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } public override async run(): Promise { IModelApp.viewManager.selectedView?.removeScreenSpaceEffects(); diff --git a/core/frontend-devtools/src/effects/Explosion.ts b/core/frontend-devtools/src/effects/Explosion.ts index 575afd1b01af..881e746d0038 100644 --- a/core/frontend-devtools/src/effects/Explosion.ts +++ b/core/frontend-devtools/src/effects/Explosion.ts @@ -7,11 +7,19 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { RenderTexture, TextureTransparency } from "@itwin/core-common"; import { - DecorateContext, GraphicType, HitDetail, imageElementFromUrl, IModelApp, IModelConnection, ParticleCollectionBuilder, ParticleProps, Tool, + DecorateContext, + GraphicType, + HitDetail, + imageElementFromUrl, + IModelApp, + IModelConnection, + ParticleCollectionBuilder, + ParticleProps, + Tool, } from "@itwin/core-frontend"; +import { Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { randomFloat, randomFloatInRange, randomIntegerInRange, randomPositionInRange } from "./Random"; /** Represents one particle in the system. */ @@ -29,9 +37,15 @@ class Particle implements ParticleProps { /** Particle transparency in [0..255]. */ public transparency = 0; - public get x() { return this.position.x; } - public get y() { return this.position.y; } - public get z() { return this.position.z; } + public get x() { + return this.position.x; + } + public get y() { + return this.position.y; + } + public get z() { + return this.position.z; + } public constructor(position: Point3d, velocity: Vector3d, lifetime: number, size: number) { this.position = position; @@ -40,7 +54,9 @@ class Particle implements ParticleProps { this.size = size; } - public get isExpired() { return this.age >= this.lifetime; } + public get isExpired() { + return this.age >= this.lifetime; + } } /** Emits particles in a sphere with its center at the origin. diff --git a/core/frontend-devtools/src/effects/FlipImage.ts b/core/frontend-devtools/src/effects/FlipImage.ts index 20fa9f45d818..7f9ff1ca5e66 100644 --- a/core/frontend-devtools/src/effects/FlipImage.ts +++ b/core/frontend-devtools/src/effects/FlipImage.ts @@ -21,8 +21,12 @@ let flipColor = false; export class FlipImageEffect extends AddEffectTool { public static override toolId = "FlipImageEffect"; - protected get effectName() { return "flip"; } - protected get textureCoordFromPosition() { return true; } + protected get effectName() { + return "flip"; + } + protected get textureCoordFromPosition() { + return true; + } protected get source() { return { @@ -87,8 +91,12 @@ export class FlipImageEffect extends AddEffectTool { */ export class FlipImageConfig extends Tool { public static override toolId = "FlipImageConfig"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } public override async run(horizontal?: boolean, vertical?: boolean, color?: boolean): Promise { flipHorizontal = !!horizontal; diff --git a/core/frontend-devtools/src/effects/LensDistortion.ts b/core/frontend-devtools/src/effects/LensDistortion.ts index b59858833bc7..9d8da30e5461 100644 --- a/core/frontend-devtools/src/effects/LensDistortion.ts +++ b/core/frontend-devtools/src/effects/LensDistortion.ts @@ -8,8 +8,8 @@ import { assert } from "@itwin/core-bentley"; import { ScreenSpaceEffectBuilder, Tool, UniformType, VaryingType } from "@itwin/core-frontend"; -import { AddEffectTool, refreshViewportsForEffect } from "./EffectTools"; import { parseArgs } from "../tools/parseArgs"; +import { AddEffectTool, refreshViewportsForEffect } from "./EffectTools"; /** Adds a screen-space effect to the selected [[Viewport]] to simulate the lens distortion produced by real-world cameras with very wide fields of view. * Based on https://www.decarpentier.nl/lens-distortion @@ -20,8 +20,12 @@ import { parseArgs } from "../tools/parseArgs"; export class LensDistortionEffect extends AddEffectTool { public static override toolId = "LensDistortionEffect"; - protected get effectName() { return "lensdistortion"; } - protected get textureCoordFromPosition() { return true; } + protected get effectName() { + return "lensdistortion"; + } + protected get textureCoordFromPosition() { + return true; + } protected get source() { return { @@ -95,8 +99,12 @@ export class LensDistortionEffect extends AddEffectTool { */ export class LensDistortionConfig extends Tool { public static override toolId = "LensDistortionConfig"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } public static strength = 0.5; public static cylindricalRatio = 0.5; diff --git a/core/frontend-devtools/src/effects/Saturation.ts b/core/frontend-devtools/src/effects/Saturation.ts index 37b4940278a1..1b1eb15fad17 100644 --- a/core/frontend-devtools/src/effects/Saturation.ts +++ b/core/frontend-devtools/src/effects/Saturation.ts @@ -16,8 +16,12 @@ import { AddEffectTool, refreshViewportsForEffect } from "./EffectTools"; export class SaturationEffect extends AddEffectTool { public static override toolId = "SaturationEffect"; - protected get effectName() { return "Saturation"; } - protected get textureCoordFromPosition() { return true; } + protected get effectName() { + return "Saturation"; + } + protected get textureCoordFromPosition() { + return true; + } protected get source() { // rgb <-> hsl conversion routines from https://gamedev.stackexchange.com/questions/59797/glsl-shader-change-hue-saturation-brightness @@ -70,8 +74,12 @@ export class SaturationEffect extends AddEffectTool { */ export class SaturationConfig extends Tool { public static override toolId = "SaturationConfig"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** Multiplier applied to the saturation of each color in the source image. */ public static multiplier = 2.0; @@ -87,4 +95,3 @@ export class SaturationConfig extends Tool { return this.run(args.getFloat("s")); } } - diff --git a/core/frontend-devtools/src/effects/Snow.ts b/core/frontend-devtools/src/effects/Snow.ts index f99c89aada2e..612d0ad9defe 100644 --- a/core/frontend-devtools/src/effects/Snow.ts +++ b/core/frontend-devtools/src/effects/Snow.ts @@ -7,11 +7,19 @@ */ import { dispose } from "@itwin/core-bentley"; -import { Point2d, Range1d, Range2d, Vector2d } from "@itwin/core-geometry"; import { RenderTexture, TextureTransparency } from "@itwin/core-common"; import { - DecorateContext, Decorator, GraphicType, imageElementFromUrl, IModelApp, ParticleCollectionBuilder, ParticleProps, Tool, Viewport, + DecorateContext, + Decorator, + GraphicType, + imageElementFromUrl, + IModelApp, + ParticleCollectionBuilder, + ParticleProps, + Tool, + Viewport, } from "@itwin/core-frontend"; +import { Point2d, Range1d, Range2d, Vector2d } from "@itwin/core-geometry"; import { parseToggle } from "../tools/parseToggle"; import { randomFloat, randomInteger } from "./Random"; @@ -159,8 +167,10 @@ export class SnowDecorator implements Decorator { z: 0, size: randomInteger(this._params.sizeRange.low, this._params.sizeRange.high), transparency: randomInteger(this._params.transparencyRange.low, this._params.transparencyRange.high), - velocity: new Vector2d(randomFloat(this._params.velocityRange.low.x, this._params.velocityRange.high.x), - randomFloat(this._params.velocityRange.low.y, this._params.velocityRange.high.y)), + velocity: new Vector2d( + randomFloat(this._params.velocityRange.low.x, this._params.velocityRange.high.x), + randomFloat(this._params.velocityRange.low.y, this._params.velocityRange.high.y), + ), }; } @@ -182,8 +192,10 @@ export class SnowDecorator implements Decorator { for (let i = 0; i < this._particles.length; i++) { // Apply some acceleration to produce random drift. const particle = this._particles[i]; - acceleration.set(randomFloat(this._params.accelerationRange.low.x, this._params.accelerationRange.high.x), - randomFloat(this._params.accelerationRange.low.y, this._params.accelerationRange.high.y)); + acceleration.set( + randomFloat(this._params.accelerationRange.low.x, this._params.accelerationRange.high.x), + randomFloat(this._params.accelerationRange.low.y, this._params.accelerationRange.high.y), + ); acceleration.scale(elapsedSeconds, acceleration); particle.velocity.plus(acceleration, particle.velocity); diff --git a/core/frontend-devtools/src/effects/Vignette.ts b/core/frontend-devtools/src/effects/Vignette.ts index 38b8652c462e..7cfd2b86ef10 100644 --- a/core/frontend-devtools/src/effects/Vignette.ts +++ b/core/frontend-devtools/src/effects/Vignette.ts @@ -17,8 +17,12 @@ import { AddEffectTool, refreshViewportsForEffect } from "./EffectTools"; export class VignetteEffect extends AddEffectTool { public static override toolId = "VignetteEffect"; - protected get effectName() { return "Vignette"; } - protected get textureCoordFromPosition() { return true; } + protected get effectName() { + return "Vignette"; + } + protected get textureCoordFromPosition() { + return true; + } protected get source() { return { @@ -81,8 +85,12 @@ export class VignetteEffect extends AddEffectTool { */ export class VignetteConfig extends Tool { public static override toolId = "VignetteConfig"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } /** Size of the vignette in the form (width/2, height/2). e.g., to make the vignette start fading in halfway between the center and edges of * UV space, use (0.25, 0.25). diff --git a/core/frontend-devtools/src/tools/AnimationIntervalTool.ts b/core/frontend-devtools/src/tools/AnimationIntervalTool.ts index f2396c475523..d040fbe9fcca 100644 --- a/core/frontend-devtools/src/tools/AnimationIntervalTool.ts +++ b/core/frontend-devtools/src/tools/AnimationIntervalTool.ts @@ -15,8 +15,12 @@ import { IModelApp, Tool } from "@itwin/core-frontend"; */ export class AnimationIntervalTool extends Tool { public static override toolId = "AnimationInterval"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async run(interval?: BeDuration): Promise { IModelApp.animationInterval = interval; diff --git a/core/frontend-devtools/src/tools/ChangeUnitsTool.ts b/core/frontend-devtools/src/tools/ChangeUnitsTool.ts index 6fa26b0a778d..20679a64d635 100644 --- a/core/frontend-devtools/src/tools/ChangeUnitsTool.ts +++ b/core/frontend-devtools/src/tools/ChangeUnitsTool.ts @@ -18,8 +18,12 @@ import { parseToggle } from "./parseToggle"; */ export class ChangeUnitsTool extends Tool { public static override toolId = "ChangeUnits"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } // support boolean for backwards compatibility public override async run(useMetric?: boolean): Promise { diff --git a/core/frontend-devtools/src/tools/ClipTools.ts b/core/frontend-devtools/src/tools/ClipTools.ts index bdf8eb1a4b42..1745fe263362 100644 --- a/core/frontend-devtools/src/tools/ClipTools.ts +++ b/core/frontend-devtools/src/tools/ClipTools.ts @@ -8,12 +8,20 @@ */ import { - ClipIntersectionStyle, ClipStyle, ClipStyleProps, ColorByName, ColorDef, CutStyleProps, LinePixels, RenderMode, RgbColor, + ClipIntersectionStyle, + ClipStyle, + ClipStyleProps, + ColorByName, + ColorDef, + CutStyleProps, + LinePixels, + RenderMode, + RgbColor, } from "@itwin/core-common"; import { IModelApp, Tool, Viewport } from "@itwin/core-frontend"; -import { parseToggle } from "./parseToggle"; -import { parseBoolean } from "./parseBoolean"; import { DisplayStyleTool } from "./DisplayStyleTools"; +import { parseBoolean } from "./parseBoolean"; +import { parseToggle } from "./parseToggle"; /** This tool specifies or un-specifies a clip color to use for pixels inside or outside the clip region. * Arguments can be: @@ -32,8 +40,12 @@ import { DisplayStyleTool } from "./DisplayStyleTools"; */ export class ClipColorTool extends Tool { public static override toolId = "ClipColorTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } private _clearClipColors() { const vp = IModelApp.viewManager.selectedView; @@ -101,8 +113,12 @@ export class ClipColorTool extends Tool { */ export class ClipIntersectionTool extends Tool { public static override toolId = "ClipIntersectionTool"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } private _toggleIntersectionStyle(toggle: boolean) { const vp = IModelApp.viewManager.selectedView; @@ -183,8 +199,12 @@ export class ClipIntersectionTool extends Tool { */ export class ToggleSectionCutTool extends Tool { public static override toolId = "ToggleSectionCut"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, controlling a view state's view details' flag for producing cut geometry for a clip style. * @param produceCutGeometry whether to produce cut geometry @@ -225,13 +245,19 @@ export class ToggleSectionCutTool extends Tool { */ export class TestClipStyleTool extends DisplayStyleTool { public static override toolId = "TestClipStyle"; - public static override get maxArgs() { return 2; } - public static override get minArgs() { return 1; } + public static override get maxArgs() { + return 2; + } + public static override get minArgs() { + return 1; + } private _useStyle = false; private _style?: CutStyleProps; - protected override get require3d() { return true; } + protected override get require3d() { + return true; + } protected async parse(args: string[]): Promise { this._useStyle = parseBoolean(args[0]) ?? false; diff --git a/core/frontend-devtools/src/tools/DisplayStyleTools.ts b/core/frontend-devtools/src/tools/DisplayStyleTools.ts index bd65fe2f608c..644610adef84 100644 --- a/core/frontend-devtools/src/tools/DisplayStyleTools.ts +++ b/core/frontend-devtools/src/tools/DisplayStyleTools.ts @@ -8,25 +8,68 @@ */ import { - ColorDef, DisplayStyle3dSettingsProps, DisplayStyleOverridesOptions, RenderMode, SkyCube, SkySphere, - SubCategoryAppearance, SubCategoryOverride, ViewFlags, ViewFlagsProperties, WhiteOnWhiteReversalSettings, + ColorDef, + DisplayStyle3dSettingsProps, + DisplayStyleOverridesOptions, + RenderMode, + SkyCube, + SkySphere, + SubCategoryAppearance, + SubCategoryOverride, + ViewFlags, + ViewFlagsProperties, + WhiteOnWhiteReversalSettings, } from "@itwin/core-common"; -import { - DisplayStyle3dState, IModelApp, NotifyMessageDetails, OutputMessagePriority, Tool, Viewport, -} from "@itwin/core-frontend"; +import { DisplayStyle3dState, IModelApp, NotifyMessageDetails, OutputMessagePriority, Tool, Viewport } from "@itwin/core-frontend"; import { copyStringToClipboard } from "../ClipboardUtilities"; import { parseArgs } from "./parseArgs"; import { parseToggle } from "./parseToggle"; type BooleanFlagName = - "dimensions" | "patterns" | "weights" | "styles" | "transparency" | "fill" | "textures" | "materials" | "acsTriad" | "grid" | "visibleEdges" | - "hiddenEdges" | "lighting" | "shadows" | "clipVolume" | "constructions" | "monochrome" | "backgroundMap" | "ambientOcclusion" | "forceSurfaceDiscard" + | "dimensions" + | "patterns" + | "weights" + | "styles" + | "transparency" + | "fill" + | "textures" + | "materials" + | "acsTriad" + | "grid" + | "visibleEdges" + | "hiddenEdges" + | "lighting" + | "shadows" + | "clipVolume" + | "constructions" + | "monochrome" + | "backgroundMap" + | "ambientOcclusion" + | "forceSurfaceDiscard" | "wiremesh"; // Compiler has the info to construct this array for us, but we have no access to it... const booleanFlagNames: BooleanFlagName[] = [ - "dimensions", "patterns", "weights", "styles", "transparency", "fill", "textures", "materials", "acsTriad", "grid", "visibleEdges", - "hiddenEdges", "lighting", "shadows", "clipVolume", "constructions", "monochrome", "backgroundMap", "ambientOcclusion", "forceSurfaceDiscard", + "dimensions", + "patterns", + "weights", + "styles", + "transparency", + "fill", + "textures", + "materials", + "acsTriad", + "grid", + "visibleEdges", + "hiddenEdges", + "lighting", + "shadows", + "clipVolume", + "constructions", + "monochrome", + "backgroundMap", + "ambientOcclusion", + "forceSurfaceDiscard", "wiremesh", ]; @@ -36,7 +79,9 @@ const lowercaseBooleanFlagNames = booleanFlagNames.map((name) => name.toLowerCas * @beta */ export abstract class DisplayStyleTool extends Tool { - protected get require3d() { return false; } + protected get require3d() { + return false; + } // Return true if the display style was modified - we will invalidate the viewport's render plan. protected abstract execute(vp: Viewport): Promise; // Return false if failed to parse. @@ -69,8 +114,12 @@ export abstract class DisplayStyleTool extends Tool { */ export class ChangeViewFlagsTool extends Tool { public static override toolId = "ChangeViewFlags"; - public static override get maxArgs() { return undefined; } - public static override get minArgs() { return 1; } + public static override get maxArgs() { + return undefined; + } + public static override get minArgs() { + return 1; + } public override async run(vf: ViewFlags, vp?: Viewport): Promise { if (undefined !== vf && undefined !== vp) @@ -130,9 +179,13 @@ export class ChangeViewFlagsTool extends Tool { export class ToggleSkyboxTool extends DisplayStyleTool { public static override toolId = "ToggleSkybox"; - public override get require3d() { return true; } + public override get require3d() { + return true; + } - public async parse(_args: string[]): Promise { return true; } // no arguments + public async parse(_args: string[]): Promise { + return true; + } // no arguments public async execute(vp: Viewport) { const style = vp.view.displayStyle as DisplayStyle3dState; @@ -148,10 +201,16 @@ export class SkySphereTool extends DisplayStyleTool { private _image?: string; public static override toolId = "SetSkySphere"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } - public override get require3d() { return true; } + public override get require3d() { + return true; + } public async parse(args: string[]) { this._image = args[0]; @@ -177,10 +236,16 @@ export class SkyCubeTool extends DisplayStyleTool { private _images: string[] = []; public static override toolId = "SetSkyCube"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 6; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 6; + } - public override get require3d() { return true; } + public override get require3d() { + return true; + } public async parse(args: string[]) { this._images = [...args]; @@ -195,11 +260,21 @@ export class SkyCubeTool extends DisplayStyleTool { let top, bottom, left, right, front, back; switch (imgs.length) { case 1: - top = bottom = left = right = front = back = imgs[0]; + top = + bottom = + left = + right = + front = + back = + imgs[0]; break; case 2: top = bottom = imgs[0]; - left = right = front = back = imgs[1]; + left = + right = + front = + back = + imgs[1]; break; case 3: top = bottom = imgs[0]; @@ -259,8 +334,12 @@ export class SaveRenderingStyleTool extends DisplayStyleTool { public static override toolId = "SaveRenderingStyle"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 7; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 7; + } public async parse(inputArgs: string[]) { const args = parseArgs(inputArgs); @@ -301,8 +380,12 @@ export class ApplyRenderingStyleTool extends DisplayStyleTool { public static override toolId = "ApplyRenderingStyle"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public async parse(args: string[]) { try { @@ -330,8 +413,12 @@ export class OverrideSubCategoryTool extends DisplayStyleTool { private _subcategoryIds: string[] = []; public static override toolId = "OverrideSubCategory"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 7; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 7; + } public async parse(inArgs: string[]) { const args = parseArgs(inArgs); @@ -367,8 +454,12 @@ export class WoWIgnoreBackgroundTool extends DisplayStyleTool { private _ignore?: boolean; public static override toolId = "WoWIgnoreBackground"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public async parse(args: string[]) { const ignore = parseToggle(args[0]); @@ -394,8 +485,12 @@ export class ToggleWiremeshTool extends DisplayStyleTool { private _enable?: boolean; public static override toolId = "ToggleWiremesh"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public async parse(args: string[]) { const enable = parseToggle(args[0]); @@ -419,8 +514,12 @@ export class ChangeBackgroundColorTool extends DisplayStyleTool { private _color?: ColorDef; public static override toolId = "ChangeBackgroundColor"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public async parse(args: string[]) { this._color = ColorDef.fromString(args[0]); diff --git a/core/frontend-devtools/src/tools/EmphasizeElementsTool.ts b/core/frontend-devtools/src/tools/EmphasizeElementsTool.ts index 33480b32df8e..8758e6e97670 100644 --- a/core/frontend-devtools/src/tools/EmphasizeElementsTool.ts +++ b/core/frontend-devtools/src/tools/EmphasizeElementsTool.ts @@ -15,8 +15,12 @@ import { parseArgs } from "./parseArgs"; * @beta */ export abstract class EmphasizeElementsTool extends Tool { - protected get _wantCreate(): boolean { return true; } - protected get _wantClear(): boolean { return false; } + protected get _wantCreate(): boolean { + return true; + } + protected get _wantClear(): boolean { + return false; + } protected abstract execute(emph: EmphasizeElements, vp: ScreenViewport): void; public override async run(_args: any[]): Promise { @@ -47,8 +51,12 @@ const enum OverrideType { // eslint-disable-line no-restricted-syntax */ export class EmphasizeSelectedElementsTool extends EmphasizeElementsTool { public static override toolId = "EmphasizeSelectedElements"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _type = OverrideType.None; public execute(emph: EmphasizeElements, vp: ScreenViewport): void { @@ -102,7 +110,9 @@ export class IsolateSelectedElementsTool extends EmphasizeElementsTool { */ export class ClearIsolatedElementsTool extends EmphasizeElementsTool { public static override toolId = "ClearIsolatedElements"; - protected override get _wantCreate() { return false; } + protected override get _wantCreate() { + return false; + } public execute(emph: EmphasizeElements, vp: ScreenViewport): void { emph.clearIsolatedElements(vp); } @@ -113,8 +123,12 @@ export class ClearIsolatedElementsTool extends EmphasizeElementsTool { */ export class ClearEmphasizedElementsTool extends EmphasizeElementsTool { public static override toolId = "ClearEmphasizedElements"; - protected override get _wantCreate() { return false; } - protected override get _wantClear() { return true; } + protected override get _wantCreate() { + return false; + } + protected override get _wantClear() { + return true; + } public execute(emph: EmphasizeElements, vp: ScreenViewport): void { emph.clearEmphasizedElements(vp); @@ -127,10 +141,16 @@ export class ClearEmphasizedElementsTool extends EmphasizeElementsTool { */ export class EmphasizeVisibleElementsTool extends EmphasizeElementsTool { public static override toolId = "EmphasizeVisibleElements"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } private _options: QueryVisibleFeaturesOptions = { source: "screen" }; - protected override get _wantClear() { return true; } + protected override get _wantClear() { + return true; + } public override async parseAndRun(...input: string[]): Promise { const args = parseArgs(input); diff --git a/core/frontend-devtools/src/tools/FrustumDecoration.ts b/core/frontend-devtools/src/tools/FrustumDecoration.ts index ee109cf209cd..c3ad9fc60e5b 100644 --- a/core/frontend-devtools/src/tools/FrustumDecoration.ts +++ b/core/frontend-devtools/src/tools/FrustumDecoration.ts @@ -7,11 +7,20 @@ * @module Tools */ -import { Map4d, Point3d } from "@itwin/core-geometry"; import { ColorByName, ColorDef, Frustum, LinePixels, Npc } from "@itwin/core-common"; import { - CoordSystem, DecorateContext, Decorator, GraphicBuilder, GraphicType, IModelApp, Tool, Viewport, ViewState, ViewState3d, + CoordSystem, + DecorateContext, + Decorator, + GraphicBuilder, + GraphicType, + IModelApp, + Tool, + Viewport, + ViewState, + ViewState3d, } from "@itwin/core-frontend"; +import { Map4d, Point3d } from "@itwin/core-geometry"; import { parseToggle } from "./parseToggle"; interface FrustumDecorationOptions { @@ -56,7 +65,14 @@ class FrustumDecoration { const builder = context.createGraphicBuilder(GraphicType.WorldDecoration); if (this._isCameraOn) - FrustumDecoration.drawEyePositionAndFocalPlane(builder, this._npcFrustum, this._worldToNpcMap, this._eyePoint, this._focalPlane, context.viewport); + FrustumDecoration.drawEyePositionAndFocalPlane( + builder, + this._npcFrustum, + this._worldToNpcMap, + this._eyePoint, + this._focalPlane, + context.viewport, + ); FrustumDecoration.drawFrustumBox(builder, this._worldFrustum, false, context.viewport); // show original frustum... FrustumDecoration.drawFrustumBox(builder, this._adjustedWorldFrustum, true, context.viewport); // show adjusted frustum... @@ -131,7 +147,14 @@ class FrustumDecoration { return planePts; } - public static drawEyePositionAndFocalPlane(builder: GraphicBuilder, npcFrustum: Frustum, worldToNpcMap: Map4d, eyePoint: Point3d, focusPlaneNpc: number, vp: Viewport): void { + public static drawEyePositionAndFocalPlane( + builder: GraphicBuilder, + npcFrustum: Frustum, + worldToNpcMap: Map4d, + eyePoint: Point3d, + focusPlaneNpc: number, + vp: Viewport, + ): void { // Eye position... const contrastColor = vp.getContrastToBackgroundColor(); builder.setSymbology(contrastColor, ColorDef.black, 8); @@ -194,7 +217,9 @@ export class FrustumDecorator implements Decorator { } } - public static get isEnabled() { return undefined !== FrustumDecorator._instance; } + public static get isEnabled() { + return undefined !== FrustumDecorator._instance; + } } /** Enable ("ON"), disable ("OFF"), or toggle ("TOGGLE" or omitted) the [[FrustumDecorator]]. @@ -202,8 +227,12 @@ export class FrustumDecorator implements Decorator { */ export class ToggleFrustumSnapshotTool extends Tool { public static override toolId = "ToggleFrustumSnapshot"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } public override async run(enable?: boolean, showPreloadFrustum?: boolean, showBackgroundIntersections?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; @@ -298,7 +327,14 @@ class SelectedViewFrustumDecoration { if (this._targetVp.isCameraOn) { const npcFrustum = this._targetVp.getFrustum(CoordSystem.Npc, true); const focalPlane = this._targetVp.worldToNpc(this._targetVp.view.getTargetPoint()).z; - FrustumDecoration.drawEyePositionAndFocalPlane(builder, npcFrustum, this._targetVp.viewingSpace.worldToNpcMap, this._targetVp.view.camera.getEyePoint(), focalPlane, context.viewport); + FrustumDecoration.drawEyePositionAndFocalPlane( + builder, + npcFrustum, + this._targetVp.viewingSpace.worldToNpcMap, + this._targetVp.view.camera.getEyePoint(), + focalPlane, + context.viewport, + ); } const worldFrustum = this._targetVp.getFrustum(CoordSystem.World, false); @@ -336,8 +372,12 @@ class SelectedViewFrustumDecoration { */ export class ToggleSelectedViewFrustumTool extends Tool { public static override toolId = "ToggleSelectedViewFrustum"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; @@ -439,8 +479,12 @@ class ShadowFrustumDecoration { */ export class ToggleShadowFrustumTool extends Tool { public static override toolId = "ToggleShadowFrustum"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/core/frontend-devtools/src/tools/InspectElementTool.ts b/core/frontend-devtools/src/tools/InspectElementTool.ts index 80cfb29c31dc..c232c5f797ad 100644 --- a/core/frontend-devtools/src/tools/InspectElementTool.ts +++ b/core/frontend-devtools/src/tools/InspectElementTool.ts @@ -10,8 +10,18 @@ import { BentleyError, Id64, Id64Array, Id64String } from "@itwin/core-bentley"; import { GeometrySummaryOptions, GeometrySummaryVerbosity, IModelReadRpcInterface } from "@itwin/core-common"; import { - BeButtonEvent, CoreTools, EventHandled, HitDetail, IModelApp, LocateFilterStatus, LocateResponse, MessageBoxIconType, MessageBoxType, - NotifyMessageDetails, OutputMessagePriority, PrimitiveTool, + BeButtonEvent, + CoreTools, + EventHandled, + HitDetail, + IModelApp, + LocateFilterStatus, + LocateResponse, + MessageBoxIconType, + MessageBoxType, + NotifyMessageDetails, + OutputMessagePriority, + PrimitiveTool, } from "@itwin/core-frontend"; import { copyStringToClipboard } from "../ClipboardUtilities"; import { parseArgs } from "./parseArgs"; @@ -29,8 +39,12 @@ import { parseArgs } from "./parseArgs"; */ export class InspectElementTool extends PrimitiveTool { public static override toolId = "InspectElement"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 6; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 6; + } private _options: GeometrySummaryOptions = {}; private _elementIds?: Id64String[]; @@ -48,7 +62,7 @@ export class InspectElementTool extends PrimitiveTool { } private setupAndPromptForNextAction(): void { - this._useSelection = (undefined !== this.targetView && this.targetView.iModel.selectionSet.isActive); + this._useSelection = undefined !== this.targetView && this.targetView.iModel.selectionSet.isActive; if (!this._useSelection) IModelApp.accuSnap.enableLocate(true); @@ -59,9 +73,11 @@ export class InspectElementTool extends PrimitiveTool { CoreTools.outputPromptByKey(this._useSelection ? "ElementSet.Prompts.ConfirmSelection" : "ElementSet.Prompts.IdentifyElement"); } - public override autoLockTarget(): void { } + public override autoLockTarget(): void {} - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } public override async onUnsuspend() { this.showPrompt(); @@ -91,7 +107,9 @@ export class InspectElementTool extends PrimitiveTool { }); if (0 === ids.length) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.NotSupportedElmType"))); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.NotSupportedElmType")), + ); else await this.process(ids); @@ -139,7 +157,10 @@ export class InspectElementTool extends PrimitiveTool { }; let messageDetails: NotifyMessageDetails; try { - let str = await IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).getGeometrySummary(this.iModel.getRpcProps(), request); + let str = await IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).getGeometrySummary( + this.iModel.getRpcProps(), + request, + ); if (this._explodeParts) { const regex = /^part id: (0x[a-f0-9]+)/gm; const partIds = new Set(); @@ -150,7 +171,10 @@ export class InspectElementTool extends PrimitiveTool { if (partIds.size > 0) { request.elementIds = Array.from(partIds); str += `\npart ids: ${JSON.stringify(request.elementIds)}\n`; - str += await IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).getGeometrySummary(this.iModel.getRpcProps(), request); + str += await IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).getGeometrySummary( + this.iModel.getRpcProps(), + request, + ); } } @@ -182,7 +206,11 @@ export class InspectElementTool extends PrimitiveTool { await IModelApp.notifications.openMessageBox(MessageBoxType.Ok, div, MessageBoxIconType.Information); } } catch (err) { - messageDetails = new NotifyMessageDetails(OutputMessagePriority.Error, "Error occurred while generating summary", BentleyError.getErrorMessage(err)); + messageDetails = new NotifyMessageDetails( + OutputMessagePriority.Error, + "Error occurred while generating summary", + BentleyError.getErrorMessage(err), + ); } IModelApp.notifications.outputMessage(messageDetails); diff --git a/core/frontend-devtools/src/tools/MapLayerTool.ts b/core/frontend-devtools/src/tools/MapLayerTool.ts index 9117685fb720..cffe9a42ebeb 100644 --- a/core/frontend-devtools/src/tools/MapLayerTool.ts +++ b/core/frontend-devtools/src/tools/MapLayerTool.ts @@ -9,7 +9,16 @@ import { Id64String } from "@itwin/core-bentley"; import { BaseMapLayerSettings, ColorDef, ModelMapLayerSettings } from "@itwin/core-common"; -import { IModelApp, MapLayerSource, MapLayerSources, MapLayerSourceStatus, NotifyMessageDetails, OutputMessagePriority, Tool, WmsUtilities } from "@itwin/core-frontend"; +import { + IModelApp, + MapLayerSource, + MapLayerSources, + MapLayerSourceStatus, + NotifyMessageDetails, + OutputMessagePriority, + Tool, + WmsUtilities, +} from "@itwin/core-frontend"; import { parseBoolean } from "./parseBoolean"; import { parseToggle } from "./parseToggle"; @@ -40,22 +49,32 @@ class AttachMapLayerBaseTool extends Tool { if (validation.status === MapLayerSourceStatus.Valid) { vp.invalidateRenderPlan(); - const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttached", { sourceName: source.name }); + const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttached", { + sourceName: source.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, msg)); } else if (validation.status === MapLayerSourceStatus.RequireAuth) { - const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttachedRequiresAuth", { sourceName: source.name }); + const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttachedRequiresAuth", { + sourceName: source.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Warning, msg)); } - } else if (validation.status === MapLayerSourceStatus.IncompatibleFormat) { - const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayersIncompatibleFormat", { sourceName: source.name }); + const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayersIncompatibleFormat", { + sourceName: source.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg)); } else { - const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerValidationFailed", { sourceName: source.name }); + const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerValidationFailed", { + sourceName: source.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg)); } }).catch((error) => { - const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttachError", { error, sourceName: source.name }); + const msg = IModelApp.localization.getLocalizedString("FrontendDevTools:tools.AttachMapLayerTool.Messages.MapLayerAttachError", { + error, + sourceName: source.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, msg)); }); } @@ -65,10 +84,16 @@ class AttachMapLayerBaseTool extends Tool { * @beta */ export class AttachModelMapLayerTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public static override toolId = "AttachModelMapLayerTool"; - constructor(protected _formatId: string) { super(); } + constructor(protected _formatId: string) { + super(); + } public override async run(nameIn?: string): Promise { const vp = IModelApp.viewManager.selectedView; @@ -100,9 +125,15 @@ export class AttachModelMapLayerTool extends Tool { } /** Attach a map layer from URL base class. */ class AttachMapLayerByURLBaseTool extends AttachMapLayerBaseTool { - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 4; } - constructor(protected _formatId: string) { super(); } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 4; + } + constructor(protected _formatId: string) { + super(); + } public override async run(url: string, name?: string, userName?: string, password?: string): Promise { const source = MapLayerSource.fromJSON({ url, name: (name ? name : url), formatId: this._formatId }); @@ -125,7 +156,9 @@ class AttachMapLayerByURLBaseTool extends AttachMapLayerBaseTool { */ export class AttachWmsMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachWmsMapLayerTool"; - constructor() { super("WMS"); } + constructor() { + super("WMS"); + } /** This method runs the tool, attaching a WMS map layer from a given URL. * @param args contains url, name, userName, password in array order */ @@ -139,7 +172,9 @@ export class AttachWmsMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { */ export class AttachWmtsMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachWmtsMapLayerTool"; - constructor() { super("WMTS"); } + constructor() { + super("WMTS"); + } /** This method runs the tool, attaching a WMTS map layer from a given URL. * @param args contains url, name, userName, password in array order */ @@ -153,7 +188,9 @@ export class AttachWmtsMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { */ export class AttachArcGISMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachArcGISMapLayerTool"; - constructor() { super("ArcGIS"); } + constructor() { + super("ArcGIS"); + } } /** This tool attaches an ArcGIS map layer from a given URL. @@ -161,7 +198,9 @@ export class AttachArcGISMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { */ export class AttachArcGISFeatureMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachArcGISFeatureMapLayerTool"; - constructor() { super("ArcGISFeature"); } + constructor() { + super("ArcGISFeature"); + } } /** This tool attaches an ArcGIS map layer from a given URL. @@ -169,7 +208,9 @@ export class AttachArcGISFeatureMapLayerByUrlTool extends AttachMapLayerByURLBas */ export class AttachOgcApiFeaturesMapLayerTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachOgcApiFeaturesMapLayerTool"; - constructor() { super("OgcApiFeatures"); } + constructor() { + super("OgcApiFeatures"); + } } /** This tool attaches a map layer from a given tile URL. @@ -177,7 +218,9 @@ export class AttachOgcApiFeaturesMapLayerTool extends AttachMapLayerByURLBaseToo */ export class AttachTileURLMapLayerByUrlTool extends AttachMapLayerByURLBaseTool { public static override toolId = "AttachTileURLMapLayerTool"; - constructor() { super("TileURL"); } + constructor() { + super("TileURL"); + } } /** This tool add a Map Layer from a specified name (look up in MapLayerSources.json). @@ -185,8 +228,12 @@ export class AttachTileURLMapLayerByUrlTool extends AttachMapLayerByURLBaseTool */ export class AttachMapLayerTool extends AttachMapLayerBaseTool { public static override toolId = "AttachMapLayerTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, adding a map layer from a specified name in MayLayerSources.json. * @param name the name of the map layer to add @@ -202,7 +249,7 @@ export class AttachMapLayerTool extends AttachMapLayerBaseTool { if (source !== undefined) this.doAttach(source); } - }).catch((_err) => { }); + }).catch((_err) => {}); return true; } @@ -241,8 +288,12 @@ export class SetMapBaseTool extends AttachMapLayerTool { */ export class DetachMapLayersTool extends Tool { public static override toolId = "DetachMapLayersTool"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } public override async parseAndRun(..._args: string[]): Promise { return this.run(); } @@ -268,8 +319,12 @@ function parseLayerIndex(args: string[]) { */ export class MapLayerVisibilityTool extends Tool { public static override toolId = "SetMapLayerVisibility"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } /** This method runs the tool, setting the visibility of a map layer. * @param layerIndex the index of the layer to change @@ -309,8 +364,12 @@ export class MapLayerVisibilityTool extends Tool { */ export class ReorderMapLayers extends Tool { public static override toolId = "ReorderMapLayers"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } /** This method runs the tool, reordering the map layers. * @param from a numeric value specifying the layer index that is being moved * @param from a numeric value specifying the layer index to move that layer to @@ -333,7 +392,6 @@ export class ReorderMapLayers extends Tool { await this.run(from, to); return true; } - } /** This tool sets the transparency of a map layer. @@ -341,8 +399,12 @@ export class ReorderMapLayers extends Tool { */ export class MapLayerTransparencyTool extends Tool { public static override toolId = "SetMapLayerTransparency"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } /** This method runs the tool, setting the transparency of a map layer. * @param layerIndex the index of the layer to change * @param transparency a numeric value in the range 0.0 (fully opaque) to 1.0 (fully transparent) @@ -374,8 +436,12 @@ export class MapLayerTransparencyTool extends Tool { */ export class MapLayerSubLayerVisibilityTool extends Tool { public static override toolId = "SetMapSubLayerVisibility"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } /** This method runs the tool, setting the visibility of a map sublayer. * @param layerIndex the index of the layer to change @@ -409,8 +475,12 @@ export class MapLayerSubLayerVisibilityTool extends Tool { */ export class MapLayerZoomTool extends Tool { public static override toolId = "MapLayerZoom"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, changing the viewport so it is zoomed to the range of a map layer. * @param layerIndex the index of the layer whose range to zoom to @@ -420,7 +490,7 @@ export class MapLayerZoomTool extends Tool { if (undefined === vp || !vp.view.isSpatialView()) return false; - vp.viewMapLayerRange({ index: layerIndex, isOverlay: false }, vp).then(() => { }).catch(() => { }); + vp.viewMapLayerRange({ index: layerIndex, isOverlay: false }, vp).then(() => {}).catch(() => {}); return true; } @@ -441,8 +511,12 @@ export class MapLayerZoomTool extends Tool { */ export class ToggleTerrainTool extends Tool { public static override toolId = "ToggleTerrain"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, changing whether to apply terrain heights to the map. * @param enable whether or not to enable terrain heights on the map @@ -476,8 +550,12 @@ export class ToggleTerrainTool extends Tool { */ export class MapBaseColorTool extends Tool { public static override toolId = "SetMapBaseColorTool"; - public static override get minArgs() { return 3; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 3; + } + public static override get maxArgs() { + return 3; + } /** This method runs the tool, changing the color of the base map. * @param color the color for the base map @@ -501,7 +579,9 @@ export class MapBaseColorTool extends Tool { public override async parseAndRun(...args: string[]): Promise { const red = parseFloat(args[0]), green = parseFloat(args[1]), blue = parseFloat(args[2]); - return (isNaN(red) || red < 0 || red > 255 || isNaN(green) || green < 0 || green > 255 || isNaN(blue) || blue < 0 || blue > 255) ? false : this.run(ColorDef.from(red, green, blue)); + return (isNaN(red) || red < 0 || red > 255 || isNaN(green) || green < 0 || green > 255 || isNaN(blue) || blue < 0 || blue > 255) + ? false + : this.run(ColorDef.from(red, green, blue)); } } /** This tool changes the transparency of the base map. @@ -509,8 +589,12 @@ export class MapBaseColorTool extends Tool { */ export class MapBaseTransparencyTool extends Tool { public static override toolId = "SetMapBaseTransparencyTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, changing the transparency of the base map. * @param transparency a numeric value in range 0.0 to 1.0 whether 0.0 means fully opaque and 1.0 means fully transparent @@ -541,8 +625,12 @@ export class MapBaseTransparencyTool extends Tool { */ export class MapBaseVisibilityTool extends Tool { public static override toolId = "SetMapBaseVisibilityTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, changing the visibility of the base map. * @param visible a boolean which specifies whether or not to make the base map visible diff --git a/core/frontend-devtools/src/tools/MeasureTileLoadTime.ts b/core/frontend-devtools/src/tools/MeasureTileLoadTime.ts index 4105c3c294d2..f47adb32a192 100644 --- a/core/frontend-devtools/src/tools/MeasureTileLoadTime.ts +++ b/core/frontend-devtools/src/tools/MeasureTileLoadTime.ts @@ -51,7 +51,9 @@ class TileLoadTimer { return; this._stopwatch.stop(); - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `Tiles loaded in ${this._stopwatch.elapsedSeconds.toFixed(4)} seconds.`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `Tiles loaded in ${this._stopwatch.elapsedSeconds.toFixed(4)} seconds.`), + ); this.stop(); } diff --git a/core/frontend-devtools/src/tools/ModelAppearanceTools.ts b/core/frontend-devtools/src/tools/ModelAppearanceTools.ts index 1349099db43e..7fe9228f2db4 100644 --- a/core/frontend-devtools/src/tools/ModelAppearanceTools.ts +++ b/core/frontend-devtools/src/tools/ModelAppearanceTools.ts @@ -34,14 +34,20 @@ function modelChangedString(name: string) { */ export class SetModelTransparencyTool extends Tool { public static override toolId = "SetModelTransparencyTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(transparency: number, name: string): Promise { const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { transparency }, name); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to transparency: ${transparency}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to transparency: ${transparency}`), + ); return changed; } @@ -56,14 +62,20 @@ export class SetModelTransparencyTool extends Tool { */ export class SetModelLineWeightTool extends Tool { public static override toolId = "SetModelLineWeightTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(weight: number, name: string): Promise { const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { weight }, name); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to line weight: ${weight}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to line weight: ${weight}`), + ); return changed; } @@ -78,18 +90,37 @@ export class SetModelLineWeightTool extends Tool { */ export class SetModelLineCodeTool extends Tool { public static override toolId = "SetModelLineCodeTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } - public static linePixels = [LinePixels.Code0, LinePixels.Code1, LinePixels.Code2, LinePixels.Code3, LinePixels.Code4, LinePixels.Code5, LinePixels.Code6, LinePixels.Code7]; + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } + public static linePixels = [ + LinePixels.Code0, + LinePixels.Code1, + LinePixels.Code2, + LinePixels.Code3, + LinePixels.Code4, + LinePixels.Code5, + LinePixels.Code6, + LinePixels.Code7, + ]; public override async run(lineCode: number, name: string): Promise { if (lineCode < 0 || lineCode >= SetModelLineCodeTool.linePixels.length) return false; - const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { linePixels: SetModelLineCodeTool.linePixels[lineCode] }, name); + const changed = changeModelAppearanceOverrides( + IModelApp.viewManager.selectedView, + { linePixels: SetModelLineCodeTool.linePixels[lineCode] }, + name, + ); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to line code: ${lineCode}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to line code: ${lineCode}`), + ); return changed; } @@ -104,15 +135,21 @@ export class SetModelLineCodeTool extends Tool { */ export class SetModelLocateTool extends Tool { public static override toolId = "SetModelLocateTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(locate: boolean, name: string): Promise { const nonLocatable = locate ? undefined : true; const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { nonLocatable }, name); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to locate: ${locate}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to locate: ${locate}`), + ); return changed; } @@ -128,8 +165,12 @@ export class SetModelLocateTool extends Tool { */ export class SetModelEmphasizedTool extends Tool { public static override toolId = "SetModelEmphasizedTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(emphasized: true | undefined, name: string): Promise { const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { emphasized }, name); @@ -151,14 +192,20 @@ export class SetModelEmphasizedTool extends Tool { */ export class SetModelIgnoresMaterialsTool extends Tool { public static override toolId = "SetModelIgnoresMaterialsTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(ignoresMaterial: true | undefined, name: string): Promise { const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { ignoresMaterial }, name); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `Mode: ${name} set to ignore Materials: ${ignoresMaterial}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `Mode: ${name} set to ignore Materials: ${ignoresMaterial}`), + ); return changed; } @@ -174,14 +221,20 @@ export class SetModelIgnoresMaterialsTool extends Tool { */ export class SetModelColorTool extends Tool { public static override toolId = "SetModelColorTool"; - public static override get minArgs() { return 3; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 3; + } + public static override get maxArgs() { + return 4; + } public override async run(rgb: RgbColorProps, name: string): Promise { const changed = changeModelAppearanceOverrides(IModelApp.viewManager.selectedView, { rgb }, name); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to RGB color: (${rgb.r}, ${rgb.g}, ${rgb.b})`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${modelChangedString(name)} set to RGB color: (${rgb.r}, ${rgb.g}, ${rgb.b})`), + ); return true; } @@ -196,8 +249,12 @@ export class SetModelColorTool extends Tool { */ export class ClearModelAppearanceOverrides extends Tool { public static override toolId = "ClearModelAppearanceOverrides"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(name?: string): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/core/frontend-devtools/src/tools/PlanProjectionTools.ts b/core/frontend-devtools/src/tools/PlanProjectionTools.ts index cb3ead444496..3c9349910755 100644 --- a/core/frontend-devtools/src/tools/PlanProjectionTools.ts +++ b/core/frontend-devtools/src/tools/PlanProjectionTools.ts @@ -18,12 +18,18 @@ import { parseArgs } from "./parseArgs"; */ export class DumpPlanProjectionSettingsTool extends DisplayStyleTool { public static override toolId = "DumpLayerSettings"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _copyToClipboard = false; - protected override get require3d() { return true; } + protected override get require3d() { + return true; + } protected async parse(args: string[]) { if (1 === args.length) @@ -59,8 +65,12 @@ export class DumpPlanProjectionSettingsTool extends DisplayStyleTool { */ export abstract class OverrideSubCategoryPriorityTool extends DisplayStyleTool { public static override toolId = "OverrideSubCategoryPriority"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } private readonly _subcatIds = new Set(); private _priority?: number; @@ -99,13 +109,19 @@ export abstract class OverrideSubCategoryPriorityTool extends DisplayStyleTool { */ export abstract class ChangePlanProjectionSettingsTool extends DisplayStyleTool { public static override toolId = "ChangeLayerSettings"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 5; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 5; + } private readonly _modelIds = new Set(); private _settings?: PlanProjectionSettings; - protected override get require3d() { return true; } + protected override get require3d() { + return true; + } protected async execute(vp: Viewport) { const settings = (vp.displayStyle as DisplayStyle3dState).settings; diff --git a/core/frontend-devtools/src/tools/PlanarMaskTools.ts b/core/frontend-devtools/src/tools/PlanarMaskTools.ts index 472deb998035..a16b86e236e4 100644 --- a/core/frontend-devtools/src/tools/PlanarMaskTools.ts +++ b/core/frontend-devtools/src/tools/PlanarMaskTools.ts @@ -10,7 +10,16 @@ import { Id64String } from "@itwin/core-bentley"; import { PlanarClipMaskMode, PlanarClipMaskPriority, PlanarClipMaskSettings } from "@itwin/core-common"; import { - BeButtonEvent, ContextRealityModelState, EventHandled, HitDetail, IModelApp, LocateFilterStatus, LocateResponse, PrimitiveTool, ScreenViewport, Tool, + BeButtonEvent, + ContextRealityModelState, + EventHandled, + HitDetail, + IModelApp, + LocateFilterStatus, + LocateResponse, + PrimitiveTool, + ScreenViewport, + Tool, } from "@itwin/core-frontend"; import { parseBoolean } from "./parseBoolean"; @@ -19,15 +28,21 @@ import { parseBoolean } from "./parseBoolean"; */ export class SetMapHigherPriorityMasking extends Tool { public static override toolId = "SetMapHigherPriorityMask"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } public override async run(transparency: number, invert: boolean): Promise { const vp = IModelApp.viewManager.selectedView; if (undefined === vp) return false; - vp.changeBackgroundMapProps({ planarClipMask: { mode: PlanarClipMaskMode.Priority, priority: PlanarClipMaskPriority.BackgroundMap, transparency, invert } }); + vp.changeBackgroundMapProps({ + planarClipMask: { mode: PlanarClipMaskMode.Priority, priority: PlanarClipMaskPriority.BackgroundMap, transparency, invert }, + }); vp.invalidateRenderPlan(); return true; } @@ -46,8 +61,12 @@ export class SetMapHigherPriorityMasking extends Tool { */ export class UnmaskMapTool extends Tool { public static override toolId = "UnmaskMap"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } public override async run(): Promise { const vp = IModelApp.viewManager.selectedView; @@ -72,22 +91,32 @@ export abstract class PlanarMaskBaseTool extends PrimitiveTool { protected _invert: boolean = false; protected _targetMaskModel?: Id64String | ContextRealityModelState; - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); } - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } private setupAndPromptForNextAction(): void { - this._useSelection = (undefined !== this.targetView && this.iModel.selectionSet.isActive); + this._useSelection = undefined !== this.targetView && this.iModel.selectionSet.isActive; this.initLocateElements(!this._useSelection || (this.targetModelRequired() && !this._targetMaskModel)); - IModelApp.locateManager.options.allowDecorations = true; // So we can select "contextual" reality models. + IModelApp.locateManager.options.allowDecorations = true; // So we can select "contextual" reality models. this.showPrompt(); } - protected targetModelRequired(): boolean { return true; } - protected elementRequired(): boolean { return true; } - protected allowSelection(): boolean { return true; } + protected targetModelRequired(): boolean { + return true; + } + protected elementRequired(): boolean { + return true; + } + protected allowSelection(): boolean { + return true; + } protected abstract showPrompt(): void; protected abstract createToolInstance(): PlanarMaskBaseTool; protected abstract applyMask(vp: ScreenViewport): void; @@ -134,7 +163,9 @@ export abstract class PlanarMaskBaseTool extends PrimitiveTool { const model = this.iModel.models.getLoaded(hit.modelId)?.asSpatialModel; return model?.isRealityModel ? LocateFilterStatus.Accept : LocateFilterStatus.Reject; } else - return (hit.isElementHit && !hit.isModelHit && !this._acceptedElementIds.has(hit.sourceId)) ? LocateFilterStatus.Accept : LocateFilterStatus.Reject; + return (hit.isElementHit && !hit.isModelHit && !this._acceptedElementIds.has(hit.sourceId)) + ? LocateFilterStatus.Accept + : LocateFilterStatus.Reject; } public override async onDataButtonDown(ev: BeButtonEvent): Promise { @@ -211,13 +242,23 @@ export abstract class PlanarMaskBaseTool extends PrimitiveTool { */ export class MaskBackgroundMapByElementTool extends PlanarMaskBaseTool { public static override toolId = "MaskBackgroundMapByElement"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return false; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return false; + } protected showPrompt(): void { - IModelApp.notifications.outputPromptByKey(`FrontendDevTools:tools.MaskBackgroundMapByElement.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskElement"}`); + IModelApp.notifications.outputPromptByKey( + `FrontendDevTools:tools.MaskBackgroundMapByElement.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskElement"}`, + ); + } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskBackgroundMapByElementTool(); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskBackgroundMapByElementTool(); } protected applyMask(vp: ScreenViewport): void { vp.changeBackgroundMapProps({ planarClipMask: this.createElementMask("include").toJSON() }); } @@ -227,13 +268,23 @@ export class MaskBackgroundMapByElementTool extends PlanarMaskBaseTool { */ export class MaskBackgroundMapByExcludedElementTool extends PlanarMaskBaseTool { public static override toolId = "MaskBackgroundMapByExcludedElement"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return false; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return false; + } protected showPrompt(): void { - IModelApp.notifications.outputPromptByKey(`FrontendDevTools:tools.MaskBackgroundMapByExcludedElement.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskElement"}`); + IModelApp.notifications.outputPromptByKey( + `FrontendDevTools:tools.MaskBackgroundMapByExcludedElement.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskElement"}`, + ); + } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskBackgroundMapByExcludedElementTool(); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskBackgroundMapByExcludedElementTool(); } protected applyMask(vp: ScreenViewport): void { vp.changeBackgroundMapProps({ planarClipMask: this.createElementMask("exclude").toJSON() }); } @@ -244,14 +295,24 @@ export class MaskBackgroundMapByExcludedElementTool extends PlanarMaskBaseTool { */ export class MaskBackgroundMapBySubCategoryTool extends PlanarMaskBaseTool { public static override toolId = "MaskBackgroundMapBySubCategory"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return false; } - protected override allowSelection(): boolean { return false; } // Need picking to get subcategory. + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return false; + } + protected override allowSelection(): boolean { + return false; + } // Need picking to get subcategory. protected showPrompt(): void { IModelApp.notifications.outputPromptByKey("FrontendDevTools:tools.MaskBackgroundMapBySubCategory.Prompts.IdentifyMaskSubCategory"); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskBackgroundMapBySubCategoryTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskBackgroundMapBySubCategoryTool(); + } protected applyMask(vp: ScreenViewport): void { vp.changeBackgroundMapProps({ planarClipMask: this.createSubCategoryMask().toJSON() }); } @@ -262,13 +323,23 @@ export class MaskBackgroundMapBySubCategoryTool extends PlanarMaskBaseTool { */ export class MaskBackgroundMapByModelTool extends PlanarMaskBaseTool { public static override toolId = "MaskBackgroundMapByModel"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return false; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return false; + } protected showPrompt(): void { - IModelApp.notifications.outputPromptByKey(`FrontendDevTools:tools.MaskBackgroundMapByModel.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskModel"}`); + IModelApp.notifications.outputPromptByKey( + `FrontendDevTools:tools.MaskBackgroundMapByModel.Prompts.${this._useSelection ? "AcceptSelection" : "IdentifyMaskModel"}`, + ); + } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskBackgroundMapByModelTool(); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskBackgroundMapByModelTool(); } protected applyMask(vp: ScreenViewport): void { vp.changeBackgroundMapProps({ planarClipMask: this.createModelMask().toJSON() }); } @@ -279,15 +350,25 @@ export class MaskBackgroundMapByModelTool extends PlanarMaskBaseTool { */ export class MaskRealityModelByElementTool extends PlanarMaskBaseTool { public static override toolId = "MaskRealityModelByElement"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return true; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return true; + } protected showPrompt(): void { - const key = `FrontendDevTools:tools.MaskRealityModelByElement.Prompts.${this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskElement")}`; + const key = `FrontendDevTools:tools.MaskRealityModelByElement.Prompts.${ + this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskElement") + }`; IModelApp.notifications.outputPromptByKey(key); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskRealityModelByElementTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskRealityModelByElementTool(); + } protected applyMask(vp: ScreenViewport): void { this.setRealityModelMask(vp, this.createElementMask("include")); } @@ -298,15 +379,25 @@ export class MaskRealityModelByElementTool extends PlanarMaskBaseTool { */ export class MaskRealityModelByExcludedElementTool extends PlanarMaskBaseTool { public static override toolId = "MaskRealityModelByExcludedElement"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return true; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return true; + } protected showPrompt(): void { - const key = `FrontendDevTools:tools.MaskRealityModelByExcludedElement.Prompts.${this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskElement")}`; + const key = `FrontendDevTools:tools.MaskRealityModelByExcludedElement.Prompts.${ + this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskElement") + }`; IModelApp.notifications.outputPromptByKey(key); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskRealityModelByExcludedElementTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskRealityModelByExcludedElementTool(); + } protected applyMask(vp: ScreenViewport): void { this.setRealityModelMask(vp, this.createElementMask("exclude")); } @@ -318,16 +409,26 @@ export class MaskRealityModelByExcludedElementTool extends PlanarMaskBaseTool { export class MaskRealityModelByModelTool extends PlanarMaskBaseTool { public static override toolId = "MaskRealityModelByModel"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } - protected override targetModelRequired() { return true; } + protected override targetModelRequired() { + return true; + } protected showPrompt(): void { - const key = `FrontendDevTools:tools.MaskRealityModelByModel.Prompts.${this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskModel")}`; + const key = `FrontendDevTools:tools.MaskRealityModelByModel.Prompts.${ + this._targetMaskModel === undefined ? "IdentifyRealityModel" : (this._useSelection ? "AcceptSelection" : "IdentifyMaskModel") + }`; IModelApp.notifications.outputPromptByKey(key); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskRealityModelByModelTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskRealityModelByModelTool(); + } protected applyMask(vp: ScreenViewport): void { this.setRealityModelMask(vp, this.createModelMask()); } @@ -338,16 +439,28 @@ export class MaskRealityModelByModelTool extends PlanarMaskBaseTool { */ export class MaskRealityModelBySubCategoryTool extends PlanarMaskBaseTool { public static override toolId = "MaskRealityModelBySubCategory"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } - protected override targetModelRequired() { return true; } - protected override allowSelection(): boolean { return false; } // Need picking to get subcategory. + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } + protected override targetModelRequired() { + return true; + } + protected override allowSelection(): boolean { + return false; + } // Need picking to get subcategory. protected showPrompt(): void { - const key = `FrontendDevTools:tools.MaskRealityModelByModel.Prompts.${this._targetMaskModel === undefined ? "IdentifyRealityModel" : "IdentifyMaskSubCategory"}`; + const key = `FrontendDevTools:tools.MaskRealityModelByModel.Prompts.${ + this._targetMaskModel === undefined ? "IdentifyRealityModel" : "IdentifyMaskSubCategory" + }`; IModelApp.notifications.outputPromptByKey(key); } - protected createToolInstance(): PlanarMaskBaseTool { return new MaskRealityModelBySubCategoryTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new MaskRealityModelBySubCategoryTool(); + } protected applyMask(vp: ScreenViewport): void { this.setRealityModelMask(vp, this.createSubCategoryMask()); } @@ -358,19 +471,34 @@ export class MaskRealityModelBySubCategoryTool extends PlanarMaskBaseTool { */ export class SetHigherPriorityRealityModelMasking extends PlanarMaskBaseTool { public static override toolId = "SetHigherPriorityRealityModelMasking"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } - protected override targetModelRequired() { return true; } - protected override elementRequired() { return false; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } + protected override targetModelRequired() { + return true; + } + protected override elementRequired() { + return false; + } private _priority = 0; protected showPrompt(): void { IModelApp.notifications.outputPromptByKey("FrontendDevTools:tools.SetHigherPriorityRealityModelMasking.Prompts.IdentifyRealityModel"); } - protected createToolInstance(): PlanarMaskBaseTool { return new SetHigherPriorityRealityModelMasking(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new SetHigherPriorityRealityModelMasking(); + } protected applyMask(vp: ScreenViewport): void { - const basePriority = this._targetMaskModel === vp.displayStyle.getOSMBuildingRealityModel() ? PlanarClipMaskPriority.GlobalRealityModel : PlanarClipMaskPriority.RealityModel; - this.setRealityModelMask(vp, PlanarClipMaskSettings.create({ priority: basePriority + this._priority, transparency: this._transparency, invert: this._invert })); + const basePriority = this._targetMaskModel === vp.displayStyle.getOSMBuildingRealityModel() + ? PlanarClipMaskPriority.GlobalRealityModel + : PlanarClipMaskPriority.RealityModel; + this.setRealityModelMask( + vp, + PlanarClipMaskSettings.create({ priority: basePriority + this._priority, transparency: this._transparency, invert: this._invert }), + ); } public override async parseAndRun(...args: string[]): Promise { @@ -394,12 +522,16 @@ export class SetHigherPriorityRealityModelMasking extends PlanarMaskBaseTool { */ export class UnmaskRealityModelTool extends PlanarMaskBaseTool { public static override toolId = "UnmaskRealityModel"; - protected override targetModelRequired() { return true; } + protected override targetModelRequired() { + return true; + } protected showPrompt(): void { IModelApp.notifications.outputPromptByKey("FrontendDevTools:tools.UnmaskRealityModel.Prompts.IdentifyRealityModel"); } - protected createToolInstance(): PlanarMaskBaseTool { return new UnmaskRealityModelTool(); } + protected createToolInstance(): PlanarMaskBaseTool { + return new UnmaskRealityModelTool(); + } protected applyMask(vp: ScreenViewport): void { const settings = PlanarClipMaskSettings.create({ subCategoryIds: this._acceptedSubCategoryIds, modelIds: this._acceptedModelIds }); this.setRealityModelMask(vp, settings); diff --git a/core/frontend-devtools/src/tools/ProjectExtents.ts b/core/frontend-devtools/src/tools/ProjectExtents.ts index 420dc63465e2..449bd74c2c3e 100644 --- a/core/frontend-devtools/src/tools/ProjectExtents.ts +++ b/core/frontend-devtools/src/tools/ProjectExtents.ts @@ -22,7 +22,9 @@ export class ProjectExtentsDecoration { this.updateDecorationListener(true); } - protected stop(): void { this.updateDecorationListener(false); } + protected stop(): void { + this.updateDecorationListener(false); + } protected updateDecorationListener(add: boolean): void { if (this._removeDecorationListener) { @@ -102,8 +104,12 @@ export function toggleProjectExtents(imodel: IModelConnection, enabled?: boolean */ export class ToggleProjectExtentsTool extends Tool { public static override toolId = "ToggleProjectExtents"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/core/frontend-devtools/src/tools/RealityModelTools.ts b/core/frontend-devtools/src/tools/RealityModelTools.ts index 6aafa8b528cc..35e3b96d0796 100644 --- a/core/frontend-devtools/src/tools/RealityModelTools.ts +++ b/core/frontend-devtools/src/tools/RealityModelTools.ts @@ -18,8 +18,12 @@ import { parseToggle } from "./parseToggle"; */ export class AttachRealityModelTool extends Tool { public static override toolId = "AttachRealityModelTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, attaching a specified reality model. * @param data a [[ContextRealityModelProps]] JSON representation @@ -52,8 +56,12 @@ export class AttachRealityModelTool extends Tool { * @beta */ export class SaveRealityModelTool extends Tool { public static override toolId = "SaveRealityModelTool"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, saving a reality model's JSON representation to the system clipboard. * @param name the name of the reality model to copy; if undefined, copy the last found reality model @@ -65,7 +73,9 @@ export class SaveRealityModelTool extends Tool { vp.displayStyle.forEachRealityModel((realityModel) => { if (name === undefined || realityModel.name === name) { copyStringToClipboard(JSON.stringify(realityModel.toJSON())); - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `Reality Model ${realityModel.name} copied to clipboard`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `Reality Model ${realityModel.name} copied to clipboard`), + ); } }); @@ -105,8 +115,12 @@ function appearanceChangedString(index: number) { */ export class SetRealityModelTransparencyTool extends Tool { public static override toolId = "SetRealityModelTransparencyTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(transparency: number, index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -116,7 +130,9 @@ export class SetRealityModelTransparencyTool extends Tool { const changed = changeRealityModelAppearanceOverrides(vp, { transparency }, index); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to transparency: ${transparency}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to transparency: ${transparency}`), + ); return true; } @@ -130,8 +146,12 @@ export class SetRealityModelTransparencyTool extends Tool { */ export class SetRealityModelLocateTool extends Tool { public static override toolId = "SetRealityModelLocateTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(locate: boolean, index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -142,7 +162,9 @@ export class SetRealityModelLocateTool extends Tool { const changed = changeRealityModelAppearanceOverrides(vp, { nonLocatable }, index); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to locate: ${locate}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to locate: ${locate}`), + ); return true; } @@ -158,8 +180,12 @@ export class SetRealityModelLocateTool extends Tool { */ export class SetRealityModelEmphasizedTool extends Tool { public static override toolId = "SetRealityModelEmphasizedTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(emphasized: true | undefined, index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -169,7 +195,9 @@ export class SetRealityModelEmphasizedTool extends Tool { const changed = changeRealityModelAppearanceOverrides(vp, { emphasized }, index); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to emphasized: ${emphasized}`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to emphasized: ${emphasized}`), + ); return true; } @@ -185,8 +213,12 @@ export class SetRealityModelEmphasizedTool extends Tool { */ export class DetachRealityModelTool extends Tool { public static override toolId = "ViewportDetachRealityModel"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -216,8 +248,12 @@ export class DetachRealityModelTool extends Tool { */ export class SetRealityModelColorTool extends Tool { public static override toolId = "SetRealityModelColorTool"; - public static override get minArgs() { return 3; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 3; + } + public static override get maxArgs() { + return 4; + } public override async run(rgb: RgbColorProps, index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -227,7 +263,9 @@ export class SetRealityModelColorTool extends Tool { const changed = changeRealityModelAppearanceOverrides(vp, { rgb }, index); if (changed) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to RGB color: (${rgb.r}, ${rgb.g}, ${rgb.b})`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, `${appearanceChangedString(index)} set to RGB color: (${rgb.r}, ${rgb.g}, ${rgb.b})`), + ); return true; } @@ -242,8 +280,12 @@ export class SetRealityModelColorTool extends Tool { */ export class ClearRealityModelAppearanceOverrides extends Tool { public static override toolId = "ClearRealityModelAppearanceOverrides"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(index: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -268,8 +310,12 @@ export class ClearRealityModelAppearanceOverrides extends Tool { */ export class AttachCesiumAssetTool extends Tool { public static override toolId = "AttachCesiumAssetTool"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(assetId: number, requestKey: string): Promise { const vp = IModelApp.viewManager.selectedView; @@ -304,8 +350,12 @@ export class AttachCesiumAssetTool extends Tool { */ export class ToggleOSMBuildingDisplay extends Tool { public static override toolId = "SetBuildingDisplay"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } public override async run(onOff?: boolean, transparency?: number): Promise { const vp = IModelApp.viewManager.selectedView; @@ -315,7 +365,9 @@ export class ToggleOSMBuildingDisplay extends Tool { if (onOff === undefined) onOff = undefined === vp.displayStyle.getOSMBuildingRealityModel(); // Toggle current state. - const appearanceOverrides = (transparency !== undefined && transparency > 0 && transparency < 1) ? FeatureAppearance.fromJSON({ transparency }) : undefined; + const appearanceOverrides = (transparency !== undefined && transparency > 0 && transparency < 1) + ? FeatureAppearance.fromJSON({ transparency }) + : undefined; vp.displayStyle.setOSMBuildingDisplay({ onOff, appearanceOverrides }); return true; diff --git a/core/frontend-devtools/src/tools/RealityTransitionTool.ts b/core/frontend-devtools/src/tools/RealityTransitionTool.ts index fb3221d83ae3..70c6aa48b16b 100644 --- a/core/frontend-devtools/src/tools/RealityTransitionTool.ts +++ b/core/frontend-devtools/src/tools/RealityTransitionTool.ts @@ -7,18 +7,27 @@ * @module Tools */ -import { Vector3d } from "@itwin/core-geometry"; import { RenderSchedule } from "@itwin/core-common"; import { IModelApp, Tool } from "@itwin/core-frontend"; +import { Vector3d } from "@itwin/core-geometry"; -enum FadeMode { X, Y, Z, Transparent } +enum FadeMode { + X, + Y, + Z, + Transparent, +} /** This tool applies a transition in X, Y, Z, or transparency. * @beta */ export class RealityTransitionTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public static override toolId = "RealityTransition"; /** This method runs the tool, applying a transition in X, Y, Z, or transparency. * @param fadeMode whether to apply the transition in X, Y, Z, or transparency @@ -52,11 +61,27 @@ export class RealityTransitionTool extends Tool { default: { const direction = directions[fadeMode - FadeMode.X]; const clipInTimeline = new Array(); - clipInTimeline.push({ time: timeNow, interpolation: 2, value: { position: [range.low.x, range.low.y, range.low.z], direction: [direction.x, direction.y, direction.z] } }); - clipInTimeline.push({ time: timeEnd, interpolation: 2, value: { position: [range.high.x, range.high.y, range.high.z], direction: [direction.x, direction.y, direction.z] } }); + clipInTimeline.push({ + time: timeNow, + interpolation: 2, + value: { position: [range.low.x, range.low.y, range.low.z], direction: [direction.x, direction.y, direction.z] }, + }); + clipInTimeline.push({ + time: timeEnd, + interpolation: 2, + value: { position: [range.high.x, range.high.y, range.high.z], direction: [direction.x, direction.y, direction.z] }, + }); const clipOutTimeline = new Array(); - clipOutTimeline.push({ time: timeNow, interpolation: 2, value: { position: [range.low.x, range.low.y, range.low.z], direction: [-direction.x, -direction.y, -direction.z] } }); - clipOutTimeline.push({ time: timeEnd, interpolation: 2, value: { position: [range.high.x, range.high.y, range.high.z], direction: [-direction.x, -direction.y, -direction.z] } }); + clipOutTimeline.push({ + time: timeNow, + interpolation: 2, + value: { position: [range.low.x, range.low.y, range.low.z], direction: [-direction.x, -direction.y, -direction.z] }, + }); + clipOutTimeline.push({ + time: timeEnd, + interpolation: 2, + value: { position: [range.high.x, range.high.y, range.high.z], direction: [-direction.x, -direction.y, -direction.z] }, + }); modelInTimeline.cuttingPlaneTimeline = clipInTimeline; modelOutTimeline.cuttingPlaneTimeline = clipOutTimeline; break; diff --git a/core/frontend-devtools/src/tools/RenderSystemTools.ts b/core/frontend-devtools/src/tools/RenderSystemTools.ts index e4ce22e450bb..97200172063d 100644 --- a/core/frontend-devtools/src/tools/RenderSystemTools.ts +++ b/core/frontend-devtools/src/tools/RenderSystemTools.ts @@ -43,7 +43,12 @@ export class CompileShadersTool extends RenderSystemDebugControlTool { public static override toolId = "CompileShaders"; public execute(control: RenderSystemDebugControl): void { const compiled = control.compileAllShaders(); - IModelApp.notifications.outputMessage(new NotifyMessageDetails(compiled ? OutputMessagePriority.Info : OutputMessagePriority.Error, `${compiled ? "No" : "Some"} compilation errors occurred.`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails( + compiled ? OutputMessagePriority.Info : OutputMessagePriority.Error, + `${compiled ? "No" : "Some"} compilation errors occurred.`, + ), + ); } } @@ -53,8 +58,12 @@ export class CompileShadersTool extends RenderSystemDebugControlTool { */ export class ToggleDPIForLODTool extends RenderSystemDebugControlTool { public static override toolId = "ToggleDPIForLOD"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _enable?: boolean; diff --git a/core/frontend-devtools/src/tools/RenderTargetTools.ts b/core/frontend-devtools/src/tools/RenderTargetTools.ts index a6776c6f8fd8..1cbcab9c3d89 100644 --- a/core/frontend-devtools/src/tools/RenderTargetTools.ts +++ b/core/frontend-devtools/src/tools/RenderTargetTools.ts @@ -27,15 +27,27 @@ export abstract class RenderTargetDebugControlTool extends Tool { } type DebugControlBoolean = - "displayDrapeFrustum" | "displayMaskFrustum" | "drawForReadPixels" | "displayRealityTileRanges" | "displayRealityTileRanges" | - "displayRealityTilePreload" | "freezeRealityTiles" | "logRealityTiles" | "vcSupportIntersectingVolumes" | "displayNormalMaps"; + | "displayDrapeFrustum" + | "displayMaskFrustum" + | "drawForReadPixels" + | "displayRealityTileRanges" + | "displayRealityTileRanges" + | "displayRealityTilePreload" + | "freezeRealityTiles" + | "logRealityTiles" + | "vcSupportIntersectingVolumes" + | "displayNormalMaps"; /** Toggles some aspect of a RenderTargetDebugControl for the selected viewport. * @beta */ export abstract class RenderTargetDebugControlToggleTool extends RenderTargetDebugControlTool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _enable?: boolean; @@ -63,7 +75,9 @@ export abstract class RenderTargetDebugControlToggleTool extends RenderTargetDeb */ export class ToggleReadPixelsTool extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleReadPixels"; - public get aspect(): DebugControlBoolean { return "drawForReadPixels"; } + public get aspect(): DebugControlBoolean { + return "drawForReadPixels"; + } } /** Turn on the display of the draping frustum. @@ -71,7 +85,9 @@ export class ToggleReadPixelsTool extends RenderTargetDebugControlToggleTool { */ export class ToggleDrapeFrustumTool extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleDrapeFrustum"; - public get aspect(): DebugControlBoolean { return "displayDrapeFrustum"; } + public get aspect(): DebugControlBoolean { + return "displayDrapeFrustum"; + } } /** Turn on the display of the planar mask frustum. @@ -79,7 +95,9 @@ export class ToggleDrapeFrustumTool extends RenderTargetDebugControlToggleTool { */ export class ToggleMaskFrustumTool extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleMaskFrustum"; - public get aspect(): DebugControlBoolean { return "displayMaskFrustum"; } + public get aspect(): DebugControlBoolean { + return "displayMaskFrustum"; + } } /** Control whether all geometry renders, or only instanced or batched geometry. @@ -88,8 +106,12 @@ export class ToggleMaskFrustumTool extends RenderTargetDebugControlToggleTool { */ export class TogglePrimitiveVisibilityTool extends RenderTargetDebugControlTool { public static override toolId = "TogglePrimitiveVisibility"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _visibility = PrimitiveVisibility.All; @@ -123,7 +145,9 @@ export class TogglePrimitiveVisibilityTool extends RenderTargetDebugControlTool */ export class ToggleRealityTileBounds extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleRealityTileBounds"; - public get aspect(): DebugControlBoolean { return "displayRealityTileRanges"; } + public get aspect(): DebugControlBoolean { + return "displayRealityTileRanges"; + } } /** Turn on display of reality tile preload debugging. @@ -131,14 +155,18 @@ export class ToggleRealityTileBounds extends RenderTargetDebugControlToggleTool */ export class ToggleRealityTilePreload extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleRealityTilePreload"; - public get aspect(): DebugControlBoolean { return "displayRealityTilePreload"; } + public get aspect(): DebugControlBoolean { + return "displayRealityTilePreload"; + } } /** Freeze loading of reality tiles. * @beta */ export class ToggleRealityTileFreeze extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleRealityTileFreeze"; - public get aspect(): DebugControlBoolean { return "freezeRealityTiles"; } + public get aspect(): DebugControlBoolean { + return "freezeRealityTiles"; + } } /** Turn on logging of console tile selection and loading (to console). @@ -146,7 +174,9 @@ export class ToggleRealityTileFreeze extends RenderTargetDebugControlToggleTool */ export class ToggleRealityTileLogging extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleRealityTileLogging"; - public get aspect(): DebugControlBoolean { return "logRealityTiles"; } + public get aspect(): DebugControlBoolean { + return "logRealityTiles"; + } } /** Toggles support for intersecting volume classifiers. @@ -154,7 +184,9 @@ export class ToggleRealityTileLogging extends RenderTargetDebugControlToggleTool */ export class ToggleVolClassIntersect extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleVCIntersect"; - public get aspect(): DebugControlBoolean { return "vcSupportIntersectingVolumes"; } + public get aspect(): DebugControlBoolean { + return "vcSupportIntersectingVolumes"; + } } /** Set the number of antialiasing samples to use (<=1 for no antialiasing). @@ -162,8 +194,12 @@ export class ToggleVolClassIntersect extends RenderTargetDebugControlToggleTool */ export class SetAASamplesTool extends RenderTargetDebugControlTool { public static override toolId = "SetAASamples"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } private _aaSamples = 1; private _changeAll = false; @@ -181,7 +217,7 @@ export class SetAASamplesTool extends RenderTargetDebugControlTool { public override async parseAndRun(...args: string[]): Promise { if (0 < args.length) this._aaSamples = parseInt(args[0], 10); - this._changeAll = (1 < args.length && args[1].toLowerCase() === "all"); + this._changeAll = 1 < args.length && args[1].toLowerCase() === "all"; return this.run(args); } @@ -192,5 +228,7 @@ export class SetAASamplesTool extends RenderTargetDebugControlTool { */ export class ToggleNormalMaps extends RenderTargetDebugControlToggleTool { public static override toolId = "ToggleNormalMaps"; - public get aspect(): DebugControlBoolean { return "displayNormalMaps"; } + public get aspect(): DebugControlBoolean { + return "displayNormalMaps"; + } } diff --git a/core/frontend-devtools/src/tools/SavedViews.ts b/core/frontend-devtools/src/tools/SavedViews.ts index 0a149d4b66f3..ddc9b0e9c21a 100644 --- a/core/frontend-devtools/src/tools/SavedViews.ts +++ b/core/frontend-devtools/src/tools/SavedViews.ts @@ -9,9 +9,7 @@ import { BentleyError } from "@itwin/core-bentley"; import { ViewStateProps } from "@itwin/core-common"; -import { - EntityState, IModelApp, IModelConnection, NotifyMessageDetails, OutputMessagePriority, Tool, ViewState, -} from "@itwin/core-frontend"; +import { EntityState, IModelApp, IModelConnection, NotifyMessageDetails, OutputMessagePriority, Tool, ViewState } from "@itwin/core-frontend"; import { copyStringToClipboard } from "../ClipboardUtilities"; import { parseArgs } from "./parseArgs"; @@ -45,8 +43,12 @@ export async function deserializeViewState(props: ViewStateProps, iModel: IModel */ export class SaveViewTool extends Tool { private _quote = false; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public static override toolId = "SaveView"; public parse(inputArgs: string[]) { @@ -81,7 +83,9 @@ export class SaveViewTool extends Tool { copyStringToClipboard(json); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, "JSON copied to clipboard")); } catch (err) { - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred.")); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."), + ); } return true; @@ -95,8 +99,12 @@ export class SaveViewTool extends Tool { */ export class ApplyViewTool extends Tool { public static override toolId = "ApplyView"; - public static override get maxArgs() { return 1; } - public static override get minArgs() { return 1; } + public static override get maxArgs() { + return 1; + } + public static override get minArgs() { + return 1; + } public override async run(view?: ViewState): Promise { const vp = IModelApp.viewManager.selectedView; @@ -117,7 +125,9 @@ export class ApplyViewTool extends Tool { const view = await deserializeViewState(json, vp.iModel); await this.run(view); } catch (err) { - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Info, BentleyError.getErrorMessage(err) || "An unknown error occurred.")); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Info, BentleyError.getErrorMessage(err) || "An unknown error occurred."), + ); } return true; @@ -129,8 +139,12 @@ export class ApplyViewTool extends Tool { */ export class ApplyViewByIdTool extends Tool { public static override toolId = "ApplyViewById"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async parseAndRun(...args: string[]): Promise { return this.run(args[0]); @@ -146,7 +160,7 @@ export class ApplyViewByIdTool extends Tool { vp.iModel.views.load(viewId).then((view) => { vp.changeView(view); - }).catch(() => { }); + }).catch(() => {}); return true; } diff --git a/core/frontend-devtools/src/tools/ScheduleScriptTools.ts b/core/frontend-devtools/src/tools/ScheduleScriptTools.ts index 8a1dec797335..966d57539794 100644 --- a/core/frontend-devtools/src/tools/ScheduleScriptTools.ts +++ b/core/frontend-devtools/src/tools/ScheduleScriptTools.ts @@ -8,13 +8,11 @@ */ import { assert, CompressedId64Set } from "@itwin/core-bentley"; -import { - ElementLoadOptions, RenderSchedule, RenderTimelineProps, -} from "@itwin/core-common"; +import { ElementLoadOptions, RenderSchedule, RenderTimelineProps } from "@itwin/core-common"; import { Viewport } from "@itwin/core-frontend"; import { copyStringToClipboard } from "../ClipboardUtilities"; -import { parseArgs } from "./parseArgs"; import { DisplayStyleTool } from "./DisplayStyleTools"; +import { parseArgs } from "./parseArgs"; /** Query the schedule script JSON from an element. * @beta @@ -27,8 +25,12 @@ export class QueryScheduleScriptTool extends DisplayStyleTool { private _expandElementIds = false; public static override toolId = "QueryScheduleScript"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } public async parse(input: string[], vp: Viewport) { const args = parseArgs(input); @@ -105,7 +107,10 @@ interface Timeline { getEntry(index: number): Entry | undefined; } -function reverseTimeline(timeline: Timeline | undefined, accept: (time: number, entry: Entry) => void): void { +function reverseTimeline( + timeline: Timeline | undefined, + accept: (time: number, entry: Entry) => void, +): void { if (!timeline) return; @@ -161,8 +166,12 @@ export class ReverseScheduleScriptTool extends DisplayStyleTool { */ export class SetScheduleScriptTool extends DisplayStyleTool { public static override toolId = "SetScheduleScript"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _script?: RenderSchedule.Script; diff --git a/core/frontend-devtools/src/tools/SelectionTools.ts b/core/frontend-devtools/src/tools/SelectionTools.ts index 7aa2f25cf3fe..66b7f276be3c 100644 --- a/core/frontend-devtools/src/tools/SelectionTools.ts +++ b/core/frontend-devtools/src/tools/SelectionTools.ts @@ -18,8 +18,12 @@ import { parseArgs } from "./parseArgs"; */ export class SelectElementsByIdTool extends Tool { public static override toolId = "SelectElementsById"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return undefined; + } public override async run(ids?: Id64Arg): Promise { const vp = IModelApp.viewManager.selectedView; @@ -39,8 +43,12 @@ export class SelectElementsByIdTool extends Tool { */ export class DumpSelectionSetTool extends Tool { public static override toolId = "DumpSelectionSet"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } private _format: "json" | "compressed" | "list" = "list"; private _copy?: boolean; diff --git a/core/frontend-devtools/src/tools/SetGpuMemoryLimitTool.ts b/core/frontend-devtools/src/tools/SetGpuMemoryLimitTool.ts index dddc84c8cc09..c1adc953443c 100644 --- a/core/frontend-devtools/src/tools/SetGpuMemoryLimitTool.ts +++ b/core/frontend-devtools/src/tools/SetGpuMemoryLimitTool.ts @@ -14,8 +14,12 @@ import { GpuMemoryLimit, IModelApp, Tool } from "@itwin/core-frontend"; */ export class SetGpuMemoryLimitTool extends Tool { public static override toolId = "SetGpuMemoryLimit"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async run(limit?: GpuMemoryLimit): Promise { if (undefined !== limit) { diff --git a/core/frontend-devtools/src/tools/SourceAspectIdTools.ts b/core/frontend-devtools/src/tools/SourceAspectIdTools.ts index 20be449c0d6c..044c4388f35f 100644 --- a/core/frontend-devtools/src/tools/SourceAspectIdTools.ts +++ b/core/frontend-devtools/src/tools/SourceAspectIdTools.ts @@ -19,8 +19,12 @@ import { parseArgs } from "./parseArgs"; * @beta */ export abstract class SourceAspectIdTool extends Tool { - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } protected abstract getECSql(queryId: string): string; @@ -43,7 +47,12 @@ export abstract class SourceAspectIdTool extends Tool { let resultId; try { - for await (const row of imodel.createQueryReader(this.getECSql(queryId), undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames, limit: { count: 1 } })) + for await ( + const row of imodel.createQueryReader(this.getECSql(queryId), undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + limit: { count: 1 }, + }) + ) resultId = row.resultId; } catch (ex) { resultId = BentleyError.getErrorMessage(ex); diff --git a/core/frontend-devtools/src/tools/TileRequestDecoration.ts b/core/frontend-devtools/src/tools/TileRequestDecoration.ts index ebc4c05150b5..29d4343f015c 100644 --- a/core/frontend-devtools/src/tools/TileRequestDecoration.ts +++ b/core/frontend-devtools/src/tools/TileRequestDecoration.ts @@ -78,8 +78,12 @@ class TileRequestDecoration { */ export class ToggleTileRequestDecorationTool extends Tool { public static override toolId = "ToggleTileRequestDecoration"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/core/frontend-devtools/src/tools/TileTreeBoundsDecoration.ts b/core/frontend-devtools/src/tools/TileTreeBoundsDecoration.ts index caa2b8a49e6d..fbb1157ce877 100644 --- a/core/frontend-devtools/src/tools/TileTreeBoundsDecoration.ts +++ b/core/frontend-devtools/src/tools/TileTreeBoundsDecoration.ts @@ -70,8 +70,12 @@ class TreeDecoration { */ export class ToggleTileTreeBoundsDecorationTool extends Tool { public static override toolId = "ToggleTileTreeBoundsDecoration"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { TreeDecoration.toggle(enable); diff --git a/core/frontend-devtools/src/tools/ToolTipProvider.ts b/core/frontend-devtools/src/tools/ToolTipProvider.ts index aacc33324cc5..28432e3de803 100644 --- a/core/frontend-devtools/src/tools/ToolTipProvider.ts +++ b/core/frontend-devtools/src/tools/ToolTipProvider.ts @@ -57,8 +57,12 @@ class DebugToolTipProvider implements ToolTipProvider { */ export class ToggleToolTipsTool extends Tool { public static override toolId = "ToggleToolTips"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { DebugToolTipProvider.setEnabled(enable); diff --git a/core/frontend-devtools/src/tools/ViewportTools.ts b/core/frontend-devtools/src/tools/ViewportTools.ts index 611b821aba3d..5a3d5022946d 100644 --- a/core/frontend-devtools/src/tools/ViewportTools.ts +++ b/core/frontend-devtools/src/tools/ViewportTools.ts @@ -9,9 +9,7 @@ import { BeDuration } from "@itwin/core-bentley"; import { Camera, ColorDef, Hilite } from "@itwin/core-common"; -import { - DrawingViewState, FlashMode, FlashSettings, FlashSettingsOptions, IModelApp, TileBoundingBoxes, Tool, Viewport, -} from "@itwin/core-frontend"; +import { DrawingViewState, FlashMode, FlashSettings, FlashSettingsOptions, IModelApp, TileBoundingBoxes, Tool, Viewport } from "@itwin/core-frontend"; import { parseArgs } from "./parseArgs"; import { parseToggle } from "./parseToggle"; @@ -19,8 +17,12 @@ import { parseToggle } from "./parseToggle"; * @beta */ export abstract class ViewportToggleTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } protected abstract toggle(vp: Viewport, enable?: boolean): Promise; @@ -72,8 +74,12 @@ const boundingVolumeNames = [ */ export class ShowTileVolumesTool extends Tool { public static override toolId = "ShowTileVolumes"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(boxes?: TileBoundingBoxes): Promise { const vp = IModelApp.viewManager.selectedView; @@ -113,8 +119,12 @@ export class ShowTileVolumesTool extends Tool { */ export class ToggleTileTreeReferencesTool extends Tool { public static override toolId = "ToggleTileTreeReferences"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 3; + } private _modelIds?: string | string[]; private _which?: "all" | "animated" | "primary" | "section" | number[]; @@ -166,8 +176,12 @@ export class ToggleTileTreeReferencesTool extends Tool { */ export class SetAspectRatioSkewTool extends Tool { public static override toolId = "SetAspectRatioSkew"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, setting the aspect ratio skew for the selected viewport. * @param skew the aspect ratio (x/y) skew value; 1.0 or undefined removes any skew @@ -199,8 +213,12 @@ export class SetAspectRatioSkewTool extends Tool { * @beta */ export class ChangeHiliteModeTool extends Tool { - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public static override toolId = "ChangeHiliteMode"; public override async run(mode?: string) { @@ -223,8 +241,12 @@ export class ChangeHiliteModeTool extends Tool { * @beta */ export abstract class ChangeHiliteTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 6; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 6; + } public override async run(settings?: Hilite.Settings): Promise { const vp = IModelApp.viewManager.selectedView; @@ -300,7 +322,9 @@ export abstract class ChangeHiliteTool extends Tool { export class ChangeHiliteSettingsTool extends ChangeHiliteTool { public static override toolId = "ChangeHiliteSettings"; - protected getCurrentSettings(vp: Viewport) { return vp.hilite; } + protected getCurrentSettings(vp: Viewport) { + return vp.hilite; + } protected apply(vp: Viewport, settings?: Hilite.Settings): void { vp.hilite = undefined !== settings ? settings : new Hilite.Settings(); } @@ -312,7 +336,9 @@ export class ChangeHiliteSettingsTool extends ChangeHiliteTool { export class ChangeEmphasisSettingsTool extends ChangeHiliteTool { public static override toolId = "ChangeEmphasisSettings"; - protected getCurrentSettings(vp: Viewport) { return vp.emphasisSettings; } + protected getCurrentSettings(vp: Viewport) { + return vp.emphasisSettings; + } protected apply(vp: Viewport, settings?: Hilite.Settings): void { if (undefined !== settings) vp.emphasisSettings = settings; @@ -324,8 +350,12 @@ export class ChangeEmphasisSettingsTool extends ChangeHiliteTool { */ export class ChangeFlashSettingsTool extends Tool { public static override toolId = "ChangeFlashSettings"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } public override async run(settings?: FlashSettings): Promise { const vp = IModelApp.viewManager.selectedView; @@ -391,8 +421,12 @@ export class FadeOutTool extends ViewportToggleTool { */ export class DefaultTileSizeModifierTool extends Tool { public static override toolId = "DefaultTileSizeMod"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, setting the default tile size modifier used for all viewports that don't explicitly override it. * @param modifier the tile size modifier to use; if undefined, do not set modifier @@ -417,8 +451,12 @@ export class DefaultTileSizeModifierTool extends Tool { */ export class ViewportTileSizeModifierTool extends Tool { public static override toolId = "ViewportTileSizeMod"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, setting the tile size modifier used for the selected viewport. * @param modifier the tile size modifier to use; if undefined, reset the modifier @@ -446,8 +484,12 @@ export class ViewportTileSizeModifierTool extends Tool { */ export class ViewportAddRealityModel extends Tool { public static override toolId = "ViewportAddRealityModel"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } /** This method runs the tool, adding a reality model to the viewport * @param url the URL which points to the reality model tileset @@ -574,8 +616,12 @@ export class ToggleSectionDrawingSpatialViewTool extends ViewportToggleTool { * @beta */ export class ChangeCameraTool extends Tool { - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public static override toolId = "ChangeCamera"; public override async run(camera?: Camera): Promise { diff --git a/core/frontend-devtools/src/tools/parseBoolean.ts b/core/frontend-devtools/src/tools/parseBoolean.ts index 7bf2da6fb86e..afa269f07e82 100644 --- a/core/frontend-devtools/src/tools/parseBoolean.ts +++ b/core/frontend-devtools/src/tools/parseBoolean.ts @@ -16,10 +16,15 @@ export function parseBoolean(arg: string | undefined): boolean | undefined { return undefined; switch (arg.toLowerCase()) { - case "on": return true; - case "true": return true; - case "off": return false; - case "false": return false; - default: return undefined; + case "on": + return true; + case "true": + return true; + case "off": + return false; + case "false": + return false; + default: + return undefined; } } diff --git a/core/frontend-devtools/src/tools/parseToggle.ts b/core/frontend-devtools/src/tools/parseToggle.ts index 024bbe1ffb41..b3f00382ba8e 100644 --- a/core/frontend-devtools/src/tools/parseToggle.ts +++ b/core/frontend-devtools/src/tools/parseToggle.ts @@ -16,9 +16,13 @@ export function parseToggle(arg: string | undefined): string | boolean | undefin return undefined; switch (arg.toLowerCase()) { - case "on": return true; - case "off": return false; - case "toggle": return undefined; - default: return arg; + case "on": + return true; + case "off": + return false; + case "toggle": + return undefined; + default: + return arg; } } diff --git a/core/frontend-devtools/src/ui/ColorInput.ts b/core/frontend-devtools/src/ui/ColorInput.ts index 579a16e138ab..7ec2624ba0b1 100644 --- a/core/frontend-devtools/src/ui/ColorInput.ts +++ b/core/frontend-devtools/src/ui/ColorInput.ts @@ -34,16 +34,17 @@ export interface ColorInput { export function convertHexToRgb(hex: string): RgbColor | undefined { // Parse a hex color string formatted as "#FFFFFF" const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? new RgbColor( - parseInt(result[1], 16), - parseInt(result[2], 16), - parseInt(result[3], 16), - ) : undefined; + return result ? + new RgbColor( + parseInt(result[1], 16), + parseInt(result[2], 16), + parseInt(result[3], 16), + ) : + undefined; } /** @alpha */ export function createColorInput(props: ColorInputProps): ColorInput { - const inputDiv = document.createElement("div"); const colorInput = document.createElement("input"); diff --git a/core/frontend-devtools/src/widgets/DiagnosticsPanel.ts b/core/frontend-devtools/src/widgets/DiagnosticsPanel.ts index cbcf2bc2f8af..9a22321aba34 100644 --- a/core/frontend-devtools/src/widgets/DiagnosticsPanel.ts +++ b/core/frontend-devtools/src/widgets/DiagnosticsPanel.ts @@ -102,7 +102,9 @@ export class DiagnosticsPanel { this._toolSettingsTracker = new ToolSettingsTracker(this._element, vp); } - public get element(): HTMLElement { return this._element; } + public get element(): HTMLElement { + return this._element; + } public dispose(): void { dispose(this._fpsTracker); diff --git a/core/frontend-devtools/src/widgets/GpuProfiler.ts b/core/frontend-devtools/src/widgets/GpuProfiler.ts index e25e6f6ff89d..3bee9b9d4fe3 100644 --- a/core/frontend-devtools/src/widgets/GpuProfiler.ts +++ b/core/frontend-devtools/src/widgets/GpuProfiler.ts @@ -7,8 +7,8 @@ * @module Widgets */ -import { saveAs } from "file-saver"; import { GLTimerResult, IModelApp, RenderSystemDebugControl } from "@itwin/core-frontend"; +import { saveAs } from "file-saver"; import { createCheckBox } from "../ui/CheckBox"; /** Trace Event Format, viewable with chrome://tracing @@ -33,7 +33,9 @@ interface ChromeTraceEvent { args: ChromeTraceEventArgs; } -interface ChromeTraceEventArgs { 0: 0 } +interface ChromeTraceEventArgs { + 0: 0; +} const dummyArgs: ChromeTraceEventArgs = { 0: 0 }; // Reuse instead of allocating for each entry /** diff --git a/core/frontend-devtools/src/widgets/KeyinField.ts b/core/frontend-devtools/src/widgets/KeyinField.ts index 3ae109599c8c..537e9e976bcc 100644 --- a/core/frontend-devtools/src/widgets/KeyinField.ts +++ b/core/frontend-devtools/src/widgets/KeyinField.ts @@ -87,8 +87,12 @@ export class KeyinField { id: `${props.baseId}_textBox`, parent: props.parent, handler: () => this.selectAll(), - keypresshandler: async (_tb, ev) => { await this.handleKeyPress(ev); }, - focushandler: (_tb) => { this.respondToKeyinFocus(); }, + keypresshandler: async (_tb, ev) => { + await this.handleKeyPress(ev); + }, + focushandler: (_tb) => { + this.respondToKeyinFocus(); + }, tooltip: "Type the key-in text here", inline: true, list: autoCompleteListId, @@ -96,7 +100,9 @@ export class KeyinField { if (props.wantButton) { createButton({ - handler: async (_bt) => { await this.submitKeyin(); }, + handler: async (_bt) => { + await this.submitKeyin(); + }, parent: props.parent, value: "Enter", inline: true, @@ -111,8 +117,12 @@ export class KeyinField { } } - public focus() { this.textBox.textbox.focus(); } - public loseFocus() { this.textBox.textbox.blur(); } + public focus() { + this.textBox.textbox.focus(); + } + public loseFocus() { + this.textBox.textbox.blur(); + } public selectAll(): void { this.textBox.textbox.setSelectionRange(0, this.textBox.textbox.value.length); diff --git a/core/frontend-devtools/src/widgets/MemoryTracker.ts b/core/frontend-devtools/src/widgets/MemoryTracker.ts index 9cdc858a8675..746352bbdca2 100644 --- a/core/frontend-devtools/src/widgets/MemoryTracker.ts +++ b/core/frontend-devtools/src/widgets/MemoryTracker.ts @@ -8,9 +8,7 @@ */ import { assert, BeTimePoint } from "@itwin/core-bentley"; -import { - DisclosedTileTreeSet, IModelApp, RenderMemory, TileTree, TileTreeOwner, Viewport, -} from "@itwin/core-frontend"; +import { DisclosedTileTreeSet, IModelApp, RenderMemory, TileTree, TileTreeOwner, Viewport } from "@itwin/core-frontend"; import { ComboBoxEntry, createComboBox } from "../ui/ComboBox"; function collectTileTreeMemory(stats: RenderMemory.Statistics, owner: TileTreeOwner): void { @@ -216,8 +214,31 @@ export class MemoryTracker { row1.appendChild(cell11); table.appendChild(row1); - this._textures = new MemoryPanel(cell00, "Textures", ["Surface Textures", "Vertex Tables", "Edge Tables", "Feature Tables", "Feature Overrides", "Clip Volumes", "Planar Classifiers", "Shadow Maps", "Texture Attachments", "Thematic Textures"]); - this._buffers = new MemoryPanel(cell01, "Buffers", ["Surfaces", "Visible Edges", "Silhouettes", "Polyline Edges", "Indexed Edges", "Polylines", "Point Strings", "Point Clouds", "Instances", "Terrain", "Reality Mesh"]); + this._textures = new MemoryPanel(cell00, "Textures", [ + "Surface Textures", + "Vertex Tables", + "Edge Tables", + "Feature Tables", + "Feature Overrides", + "Clip Volumes", + "Planar Classifiers", + "Shadow Maps", + "Texture Attachments", + "Thematic Textures", + ]); + this._buffers = new MemoryPanel(cell01, "Buffers", [ + "Surfaces", + "Visible Edges", + "Silhouettes", + "Polyline Edges", + "Indexed Edges", + "Polylines", + "Point Strings", + "Point Clouds", + "Instances", + "Terrain", + "Reality Mesh", + ]); this._totalElem = this.addStatistics(cell10); this._totalTreesElem = this.addStatistics(cell11); diff --git a/core/frontend-devtools/src/widgets/TileMemoryBreakdown.ts b/core/frontend-devtools/src/widgets/TileMemoryBreakdown.ts index 0b7fb9363374..da0d76571128 100644 --- a/core/frontend-devtools/src/widgets/TileMemoryBreakdown.ts +++ b/core/frontend-devtools/src/widgets/TileMemoryBreakdown.ts @@ -43,9 +43,10 @@ class TileMemoryTracer { for (const vp of IModelApp.viewManager) { imodels.add(vp.iModel); const tiles = IModelApp.tileAdmin.getTilesForUser(vp)?.selected; - if (tiles) + if (tiles) { for (const tile of tiles) selectedTiles.add(tile); + } } for (const selected of selectedTiles) @@ -112,9 +113,10 @@ class TileMemoryTracer { this.add(tile, TileMemorySelector.Orphaned); const children = tile.children; - if (children) + if (children) { for (const child of children) this.processOrphan(child); + } } } diff --git a/core/frontend-devtools/src/widgets/ToolSettingsTracker.ts b/core/frontend-devtools/src/widgets/ToolSettingsTracker.ts index 03f099feab33..d2e0321e2ac4 100644 --- a/core/frontend-devtools/src/widgets/ToolSettingsTracker.ts +++ b/core/frontend-devtools/src/widgets/ToolSettingsTracker.ts @@ -219,5 +219,5 @@ export class ToolSettingsTracker { }); } - public dispose(): void { } + public dispose(): void {} } diff --git a/core/frontend-devtools/tsconfig.json b/core/frontend-devtools/tsconfig.json index 67be9deac4ee..baa950b82605 100644 --- a/core/frontend-devtools/tsconfig.json +++ b/core/frontend-devtools/tsconfig.json @@ -3,4 +3,4 @@ "compilerOptions": { "outDir": "./lib" } -} \ No newline at end of file +} diff --git a/core/frontend/eslint.config.js b/core/frontend/eslint.config.js index f4404c87fc85..3e417b6144ca 100644 --- a/core/frontend/eslint.config.js +++ b/core/frontend/eslint.config.js @@ -13,20 +13,20 @@ module.exports = [ "error", { "required-barrel-modules": [ - "./src/tile/internal.ts" - ] - } + "./src/tile/internal.ts", + ], + }, ], "@itwin/public-extension-exports": [ "error", { "releaseTags": [ - "public" + "public", ], - "outputApiFile": false - } - ] - } + "outputApiFile": false, + }, + ], + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/frontend/extraction.eslint.config.js b/core/frontend/extraction.eslint.config.js index eafbeebb72e5..617611e8b28d 100644 --- a/core/frontend/extraction.eslint.config.js +++ b/core/frontend/extraction.eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.extensionExportsConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/frontend/src/AccuDraw.ts b/core/frontend/src/AccuDraw.ts index 438934b46210..d25f8696a7be 100644 --- a/core/frontend/src/AccuDraw.ts +++ b/core/frontend/src/AccuDraw.ts @@ -7,26 +7,40 @@ * @module AccuDraw */ import { BentleyStatus } from "@itwin/core-bentley"; +import { ColorByName, ColorDef, GeometryStreamProps, LinePixels } from "@itwin/core-common"; import { - Arc3d, AxisOrder, CurveCurve, CurvePrimitive, Geometry, IModelJson as GeomJson, LineSegment3d, LineString3d, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, - PointString3d, Ray3d, Transform, Vector3d, + Arc3d, + AxisOrder, + CurveCurve, + CurvePrimitive, + Geometry, + IModelJson as GeomJson, + LineSegment3d, + LineString3d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + PointString3d, + Ray3d, + Transform, + Vector3d, } from "@itwin/core-geometry"; -import { ColorByName, ColorDef, GeometryStreamProps, LinePixels } from "@itwin/core-common"; +import { ParseError, Parser, ParserSpec, QuantityParseResult } from "@itwin/core-quantity"; import { TentativeOrAccuSnap } from "./AccuSnap"; import { ACSDisplayOptions, AuxCoordSystemState } from "./AuxCoordSys"; +import { GraphicType } from "./common/render/GraphicType"; import { HitDetail, SnapDetail, SnapHeat, SnapMode } from "./HitDetail"; import { IModelApp } from "./IModelApp"; +import { linePlaneIntersect } from "./LinePlaneIntersect"; +import { QuantityType } from "./quantity-formatting/QuantityFormatter"; import { GraphicBuilder } from "./render/GraphicBuilder"; import { StandardViewId } from "./StandardView"; import { BeButton, BeButtonEvent, CoordinateLockOverrides, InputCollector, InputSource } from "./tools/Tool"; import { ViewTool } from "./tools/ViewTool"; import { DecorateContext } from "./ViewContext"; -import { linePlaneIntersect } from "./LinePlaneIntersect"; import { ScreenViewport, Viewport } from "./Viewport"; import { ViewState } from "./ViewState"; -import { QuantityType } from "./quantity-formatting/QuantityFormatter"; -import { ParseError, Parser, ParserSpec, QuantityParseResult } from "@itwin/core-quantity"; -import { GraphicType } from "./common/render/GraphicType"; // cspell:ignore dont primitivetools @@ -235,14 +249,18 @@ export class ThreeAxes { result.fromMatrix3d(rMatrix); return result; } - public toMatrix3d(out?: Matrix3d) { return Matrix3d.createRows(this.x, this.y, this.z, out); } + public toMatrix3d(out?: Matrix3d) { + return Matrix3d.createRows(this.x, this.y, this.z, out); + } public clone(): ThreeAxes { const out = new ThreeAxes(); out.setFrom(this); return out; } - public equals(other: ThreeAxes): boolean { return this.x.isExactEqual(other.x) && this.y.isExactEqual(other.y) && this.z.isExactEqual(other.z); } + public equals(other: ThreeAxes): boolean { + return this.x.isExactEqual(other.x) && this.y.isExactEqual(other.y) && this.z.isExactEqual(other.z); + } } /** Accudraw is an aide for entering coordinate data. @@ -256,7 +274,9 @@ export class AccuDraw { private _currentState = CurrentState.NotEnabled; /** Current AccuDraw state */ - public get currentState(): CurrentState { return this._currentState; } + public get currentState(): CurrentState { + return this._currentState; + } public set currentState(state: CurrentState) { if (state === this._currentState) return; @@ -361,7 +381,9 @@ export class AccuDraw { private static _tempRot = new Matrix3d(); /** @internal */ - public onInitialized() { this.enableForSession(); } + public onInitialized() { + this.enableForSession(); + } /** @internal */ public getRotation(rMatrix?: Matrix3d): Matrix3d { if (!rMatrix) @@ -371,18 +393,30 @@ export class AccuDraw { return rMatrix; } - public get isActive(): boolean { return CurrentState.Active === this.currentState; } - public get isEnabled(): boolean { return (this.currentState > CurrentState.NotEnabled); } - public get isInactive(): boolean { return (CurrentState.Inactive === this.currentState); } - public get isDeactivated(): boolean { return (CurrentState.Deactivated === this.currentState); } + public get isActive(): boolean { + return CurrentState.Active === this.currentState; + } + public get isEnabled(): boolean { + return (this.currentState > CurrentState.NotEnabled); + } + public get isInactive(): boolean { + return (CurrentState.Inactive === this.currentState); + } + public get isDeactivated(): boolean { + return (CurrentState.Deactivated === this.currentState); + } /** Get the current lock state for the supplied input field */ - public getFieldLock(index: ItemField): boolean { return this._fieldLocked[index]; } + public getFieldLock(index: ItemField): boolean { + return this._fieldLocked[index]; + } /** @internal */ - public getKeyinStatus(index: ItemField): KeyinStatus { return this._keyinStatus[index]; } + public getKeyinStatus(index: ItemField): KeyinStatus { + return this._keyinStatus[index]; + } /** Implement this method to set focus to the AccuDraw UI. */ - public grabInputFocus() { } + public grabInputFocus() {} /** @internal */ public activate(): void { @@ -451,8 +485,8 @@ export class AccuDraw { distance = ptP.distance(snapPt); } - const isRectMode = (CompassMode.Rectangular === this.compassMode); - const offsetSnap = ((TentativeOrAccuSnap.isHot || IModelApp.tentativePoint.isActive) && ((this.locked) || (distance > 0.0))); + const isRectMode = CompassMode.Rectangular === this.compassMode; + const offsetSnap = (TentativeOrAccuSnap.isHot || IModelApp.tentativePoint.isActive) && ((this.locked) || (distance > 0.0)); // XY Offset: if (offsetSnap) { @@ -463,15 +497,15 @@ export class AccuDraw { const xOffset = vec.dotProduct(this.axes.x); const yOffset = vec.dotProduct(this.axes.y); - xIsOffset = (Math.abs(xOffset) > 1.0); - yIsOffset = (Math.abs(yOffset) > 1.0); + xIsOffset = Math.abs(xOffset) > 1.0; + yIsOffset = Math.abs(yOffset) > 1.0; if (xIsOffset || yIsOffset) return true; } } - const isOnCompassPlane = (!vp.view.is3d() || this.flags.pointIsOnPlane || this.isZLocked(vp)); + const isOnCompassPlane = !vp.view.is3d() || this.flags.pointIsOnPlane || this.isZLocked(vp); // Z Offset: if (offsetSnap) { @@ -493,7 +527,10 @@ export class AccuDraw { if ((this.indexed & LockedStates.XY_BM) && (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item])) axisIsIndexed = true; } else { - if ((this.indexed & LockedStates.ANGLE_BM || this.locked & LockedStates.ANGLE_BM) && (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item])) + if ( + (this.indexed & LockedStates.ANGLE_BM || this.locked & LockedStates.ANGLE_BM) && + (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item]) + ) axisIsIndexed = true; } @@ -526,7 +563,7 @@ export class AccuDraw { if (!this.isEnabled) return false; - const lastWasIndexed = (0 !== this.indexed); + const lastWasIndexed = 0 !== this.indexed; let pointChanged = false, handled = false; if (0.0 !== pointActive.z && !vp.isPointAdjustmentRequired) @@ -645,27 +682,45 @@ export class AccuDraw { switch (this.flags.baseRotation) { case RotationMode.Top: switch (whichVec) { - case 0: vecP.x = 1.0; break; - case 1: vecP.y = 1.0; break; - case 2: vecP.z = 1.0; break; + case 0: + vecP.x = 1.0; + break; + case 1: + vecP.y = 1.0; + break; + case 2: + vecP.z = 1.0; + break; } this.accountForACSContextLock(vecP); break; case RotationMode.Front: switch (whichVec) { - case 0: vecP.x = 1.0; break; - case 1: vecP.z = 1.0; break; - case 2: vecP.y = -1.0; break; + case 0: + vecP.x = 1.0; + break; + case 1: + vecP.z = 1.0; + break; + case 2: + vecP.y = -1.0; + break; } this.accountForACSContextLock(vecP); break; case RotationMode.Side: switch (whichVec) { - case 0: vecP.y = 1.0; break; - case 1: vecP.z = 1.0; break; - case 2: vecP.x = 1.0; break; + case 0: + vecP.y = 1.0; + break; + case 1: + vecP.z = 1.0; + break; + case 2: + vecP.x = 1.0; + break; } this.accountForACSContextLock(vecP); break; @@ -675,9 +730,15 @@ export class AccuDraw { myAxes = ThreeAxes.createFromMatrix3d(rMatrix); this.accountForAuxRotationPlane(myAxes, this.flags.auxRotationPlane); switch (whichVec) { - case 0: vecP.setFrom(myAxes.x); break; - case 1: vecP.setFrom(myAxes.y); break; - case 2: vecP.setFrom(myAxes.z); break; + case 0: + vecP.setFrom(myAxes.x); + break; + case 1: + vecP.setFrom(myAxes.y); + break; + case 2: + vecP.setFrom(myAxes.z); + break; } break; @@ -690,9 +751,15 @@ export class AccuDraw { myAxes = this.baseAxes.clone(); this.accountForAuxRotationPlane(myAxes, this.flags.auxRotationPlane); switch (whichVec) { - case 0: vecP.setFrom(myAxes.x); break; - case 1: vecP.setFrom(myAxes.y); break; - case 2: vecP.setFrom(myAxes.z); break; + case 0: + vecP.setFrom(myAxes.x); + break; + case 1: + vecP.setFrom(myAxes.y); + break; + case 2: + vecP.setFrom(myAxes.z); + break; } break; } @@ -709,12 +776,12 @@ export class AccuDraw { const rot1 = vec1.crossProduct(rotation.x); const rot2 = vec2.crossProduct(rotation.x); const rot3 = vec3.crossProduct(rotation.x); - const useRot1 = (rot1.normalizeWithLength(rot1).mag > 0.00001); - const useRot2 = (rot2.normalizeWithLength(rot2).mag > 0.00001); - const useRot3 = (rot3.normalizeWithLength(rot3).mag > 0.00001); - const dot1 = (useRot1 ? Math.abs(rotation.x.crossProduct(rot1).dotProduct(viewZ)) : -1.0); - const dot2 = (useRot2 ? Math.abs(rotation.x.crossProduct(rot2).dotProduct(viewZ)) : -1.0); - const dot3 = (useRot3 ? Math.abs(rotation.x.crossProduct(rot3).dotProduct(viewZ)) : -1.0); + const useRot1 = rot1.normalizeWithLength(rot1).mag > 0.00001; + const useRot2 = rot2.normalizeWithLength(rot2).mag > 0.00001; + const useRot3 = rot3.normalizeWithLength(rot3).mag > 0.00001; + const dot1 = useRot1 ? Math.abs(rotation.x.crossProduct(rot1).dotProduct(viewZ)) : -1.0; + const dot2 = useRot2 ? Math.abs(rotation.x.crossProduct(rot2).dotProduct(viewZ)) : -1.0; + const dot3 = useRot3 ? Math.abs(rotation.x.crossProduct(rot3).dotProduct(viewZ)) : -1.0; const max = Math.max(dot1, dot2, dot3); if (Geometry.isDistanceWithinTol(dot1 - dot2, 0.1) && (max !== dot3)) @@ -825,7 +892,7 @@ export class AccuDraw { switch (this.flags.contextRotMode) { case ContextMode.XAxis: this.getRotationFromVector(newRotation, 0); - clearLocks = (LockedStates.Y_BM !== this.locked || !oldRotation.x.isExactEqual(newRotation.x)); // Try to keep locked axis when tool being unsuspended... + clearLocks = LockedStates.Y_BM !== this.locked || !oldRotation.x.isExactEqual(newRotation.x); // Try to keep locked axis when tool being unsuspended... break; case ContextMode.XAxis2: @@ -833,12 +900,12 @@ export class AccuDraw { this.getBestViewedRotationFromXVector(newRotation, vp); // Use base rotation axis that results in compass being most closely aligned to view direction.... else this.getRotationFromVector(newRotation, 0); - clearLocks = (LockedStates.Y_BM !== this.locked || !oldRotation.x.isExactEqual(newRotation.x)); // Try to keep locked axis when tool being unsuspended... + clearLocks = LockedStates.Y_BM !== this.locked || !oldRotation.x.isExactEqual(newRotation.x); // Try to keep locked axis when tool being unsuspended... break; case ContextMode.YAxis: this.getRotationFromVector(newRotation, 1); - clearLocks = (LockedStates.X_BM !== this.locked || !oldRotation.y.isExactEqual(newRotation.y)); // Try to keep locked axis when tool being unsuspended... + clearLocks = LockedStates.X_BM !== this.locked || !oldRotation.y.isExactEqual(newRotation.y); // Try to keep locked axis when tool being unsuspended... break; case ContextMode.ZAxis: @@ -896,7 +963,14 @@ export class AccuDraw { /** Emulate a mouse click at the specified location in the supplied view by sending button down/up events. */ public async sendDataPoint(pt: Point3d, viewport: ScreenViewport): Promise { - const ev = new BeButtonEvent({ point: pt, rawPoint: pt, viewPoint: viewport.worldToView(pt), viewport, inputSource: InputSource.Mouse, isDown: true }); + const ev = new BeButtonEvent({ + point: pt, + rawPoint: pt, + viewPoint: viewport.worldToView(pt), + viewport, + inputSource: InputSource.Mouse, + isDown: true, + }); // Send both down and up events... await IModelApp.toolAdmin.sendButtonEvent(ev); @@ -924,7 +998,10 @@ export class AccuDraw { if (!this.autoPointPlacement) return; - if (this._fieldLocked[ItemField.DIST_Item] && (this._fieldLocked[ItemField.ANGLE_Item] || this.indexed & LockedStates.ANGLE_BM) && KeyinStatus.Dynamic === this._keyinStatus[index]) { + if ( + this._fieldLocked[ItemField.DIST_Item] && (this._fieldLocked[ItemField.ANGLE_Item] || this.indexed & LockedStates.ANGLE_BM) && + KeyinStatus.Dynamic === this._keyinStatus[index] + ) { this.fixPointPolar(vp); return this.sendDataPoint(this.point, vp); } @@ -956,7 +1033,10 @@ export class AccuDraw { if (!this.autoPointPlacement || KeyinStatus.Dynamic !== this._keyinStatus[index]) return; - if ((ItemField.X_Item === index && this._fieldLocked[ItemField.X_Item] && (this.indexed & LockedStates.Y_BM)) || (ItemField.Y_Item === index && this._fieldLocked[ItemField.Y_Item] && (this.indexed & LockedStates.X_BM))) { + if ( + (ItemField.X_Item === index && this._fieldLocked[ItemField.X_Item] && (this.indexed & LockedStates.Y_BM)) || + (ItemField.Y_Item === index && this._fieldLocked[ItemField.Y_Item] && (this.indexed & LockedStates.X_BM)) + ) { this.origin.plus3Scaled(this.axes.x, this.delta.x, this.axes.y, this.delta.y, this.axes.z, this.delta.z, this.point); return this.sendDataPoint(this.point, vp); } @@ -965,11 +1045,16 @@ export class AccuDraw { /** Get the current value for the supplied input field */ public getValueByIndex(index: ItemField): number { switch (index) { - case ItemField.X_Item: return this.delta.x; - case ItemField.Y_Item: return this.delta.y; - case ItemField.Z_Item: return this.delta.z; - case ItemField.DIST_Item: return this._distance; - case ItemField.ANGLE_Item: return this._angle; + case ItemField.X_Item: + return this.delta.x; + case ItemField.Y_Item: + return this.delta.y; + case ItemField.Z_Item: + return this.delta.z; + case ItemField.DIST_Item: + return this._distance; + case ItemField.ANGLE_Item: + return this._angle; default: return 0.0; } @@ -1015,7 +1100,9 @@ export class AccuDraw { } /** Allow the AccuDraw user interface to specify bearing */ - public get isBearingMode(): boolean { return false; } + public get isBearingMode(): boolean { + return false; + } /** Allow the AccuDraw user interface to supply the angle/direction parser */ public getAngleParser(): ParserSpec | undefined { @@ -1034,7 +1121,7 @@ export class AccuDraw { if (input.length === 0) return BentleyStatus.ERROR; - if (input.length === 1) + if (input.length === 1) { switch (input) { case ":": case "-": @@ -1042,6 +1129,7 @@ export class AccuDraw { case ".": return BentleyStatus.ERROR; } + } let parseResult; @@ -1067,7 +1155,7 @@ export class AccuDraw { if (Parser.isParsedQuantity(parseResult)) { this.delta.x = parseResult.value; - this._xIsExplicit = (input[0] === "+" || input[0] === "-"); + this._xIsExplicit = input[0] === "+" || input[0] === "-"; if (!this._xIsExplicit) { if (this.smartKeyin && this.isActive && this._xIsNegative === (this.delta.x >= 0.0)) this.delta.x = -this.delta.x; @@ -1081,7 +1169,7 @@ export class AccuDraw { if (Parser.isParsedQuantity(parseResult)) { this.delta.y = parseResult.value; - this._yIsExplicit = (input[0] === "+" || input[0] === "-"); + this._yIsExplicit = input[0] === "+" || input[0] === "-"; if (!this._yIsExplicit) { if (this.smartKeyin && this.isActive && this._yIsNegative === (this.delta.y >= 0.0)) this.delta.y = -this.delta.y; @@ -1305,13 +1393,13 @@ export class AccuDraw { const vp = (undefined !== currentVp) ? currentVp : snap.viewport; const rotation = out ? out : new Matrix3d(); const viewZ = vp.rotation.rowZ(); - const snapLoc = (undefined !== snap.primitive ? snap.primitive.closestPoint(snap.snapPoint, false) : undefined); + const snapLoc = undefined !== snap.primitive ? snap.primitive.closestPoint(snap.snapPoint, false) : undefined; if (undefined !== snapLoc) { const frame = snap.primitive!.fractionToFrenetFrame(snapLoc.fraction); - const frameZ = (undefined !== frame ? frame.matrix.columnZ() : Vector3d.unitZ()); - let xVec = (undefined !== frame ? frame.matrix.columnX() : Vector3d.unitX()); - const zVec = (vp.view.allow3dManipulations() ? (undefined !== snap.normal ? snap.normal.clone() : frameZ.clone()) : Vector3d.unitZ()); + const frameZ = undefined !== frame ? frame.matrix.columnZ() : Vector3d.unitZ(); + let xVec = undefined !== frame ? frame.matrix.columnX() : Vector3d.unitX(); + const zVec = vp.view.allow3dManipulations() ? (undefined !== snap.normal ? snap.normal.clone() : frameZ.clone()) : Vector3d.unitZ(); if (!vp.isCameraOn && viewZ.isPerpendicularTo(zVec)) zVec.setFrom(viewZ); @@ -1350,7 +1438,7 @@ export class AccuDraw { } if (undefined !== snap.normal) { - const zVec = (vp.view.allow3dManipulations() ? snap.normal.clone() : Vector3d.unitZ()); + const zVec = vp.view.allow3dManipulations() ? snap.normal.clone() : Vector3d.unitZ(); if (!vp.isCameraOn && viewZ.isPerpendicularTo(zVec)) zVec.setFrom(viewZ); @@ -1483,13 +1571,16 @@ export class AccuDraw { /** @internal */ public saveCoordinate(index: ItemField, value: number): void { - const isAngle = (ItemField.ANGLE_Item === index); + const isAngle = ItemField.ANGLE_Item === index; let currIndex = this._savedCoords.nSaveValues + 1; if (currIndex >= Constants.MAX_SAVED_VALUES) currIndex = 0; - if (this._savedCoords.savedValues[this._savedCoords.nSaveValues] === value && this._savedCoords.savedValIsAngle[this._savedCoords.nSaveValues] === isAngle) + if ( + this._savedCoords.savedValues[this._savedCoords.nSaveValues] === value && + this._savedCoords.savedValIsAngle[this._savedCoords.nSaveValues] === isAngle + ) return; if (isAngle) { @@ -1619,7 +1710,15 @@ export class AccuDraw { } /** @internal */ - public setContext(flags: AccuDrawFlags, originP?: Point3d, orientationP?: Matrix3d | Vector3d, deltaP?: Vector3d, distanceP?: number, angleP?: number, transP?: Transform): BentleyStatus { + public setContext( + flags: AccuDrawFlags, + originP?: Point3d, + orientationP?: Matrix3d | Vector3d, + deltaP?: Vector3d, + distanceP?: number, + angleP?: number, + transP?: Transform, + ): BentleyStatus { this.published.flags |= flags; if (flags & AccuDrawFlags.SetOrigin && originP) { @@ -1791,7 +1890,7 @@ export class AccuDraw { this.updateRotation(); if (stateBuffer.ignoreDataButton) - this.flags.ignoreDataButton = (this.flags.inDataPoint ? true : false); + this.flags.ignoreDataButton = this.flags.inDataPoint ? true : false; } private getCompassPlanePoint(point: Point3d, vp: Viewport): boolean { @@ -1847,8 +1946,8 @@ export class AccuDraw { distance = this.point.distance(snapPt); } - const isRectMode = (CompassMode.Rectangular === this.compassMode); - const offsetSnap = ((TentativeOrAccuSnap.isHot || IModelApp.tentativePoint.isActive) && ((this.locked) || (distance > 0.0))); + const isRectMode = CompassMode.Rectangular === this.compassMode; + const offsetSnap = (TentativeOrAccuSnap.isHot || IModelApp.tentativePoint.isActive) && ((this.locked) || (distance > 0.0)); // XY Offset: if (offsetSnap) { @@ -1856,31 +1955,35 @@ export class AccuDraw { const vec = this.point.vectorTo(this._rawPointOnPlane); const xOffset = vec.dotProduct(this.axes.x); const yOffset = vec.dotProduct(this.axes.y); - const xIsOffset = (Math.abs(xOffset) > 1.0); - const yIsOffset = (Math.abs(yOffset) > 1.0); + const xIsOffset = Math.abs(xOffset) > 1.0; + const yIsOffset = Math.abs(yOffset) > 1.0; if (xIsOffset) { - if (yIsOffset) { /* both */ + if (yIsOffset) { + /* both */ const pts: Point3d[] = [ this.point, this.point.plusScaled(this.axes.y, yOffset), this._rawPointOnPlane, - this.point.plusScaled(this.axes.x, xOffset)]; + this.point.plusScaled(this.axes.x, xOffset), + ]; pts[4] = pts[0]; graphic.setSymbology(colorIndex, colorIndex, 2, LinePixels.Code5); graphic.addLineString(pts); - } else { /* just X */ + } else { + /* just X */ graphic.setSymbology(colorIndex, colorIndex, 2, LinePixels.Code5); graphic.addLineString([this.point, this._rawPointOnPlane]); } - } else if (yIsOffset) { /* just Y */ + } else if (yIsOffset) { + /* just Y */ graphic.setSymbology(colorIndex, colorIndex, 2, LinePixels.Code5); graphic.addLineString([this.point, this._rawPointOnPlane]); } } } - const isOnCompassPlane = (!vp.view.is3d() || this.flags.pointIsOnPlane || this.isZLocked(vp)); + const isOnCompassPlane = !vp.view.is3d() || this.flags.pointIsOnPlane || this.isZLocked(vp); // Z Offset: if (offsetSnap) { @@ -1911,7 +2014,10 @@ export class AccuDraw { if ((this.indexed & LockedStates.XY_BM) && (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item])) axisIsIndexed = true; } else { - if ((this.indexed & LockedStates.ANGLE_BM || this.locked & LockedStates.ANGLE_BM) && (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item])) + if ( + (this.indexed & LockedStates.ANGLE_BM || this.locked & LockedStates.ANGLE_BM) && + (this.flags.pointIsOnPlane || this._fieldLocked[ItemField.Z_Item]) + ) axisIsIndexed = true; } @@ -1976,7 +2082,9 @@ export class AccuDraw { } /** @internal */ - public testDecorationHit(id: string): boolean { return id === this._acsPickId; } + public testDecorationHit(id: string): boolean { + return id === this._acsPickId; + } /** @internal */ public getDecorationGeometry(hit: HitDetail): GeometryStreamProps | undefined { if (!hit.viewport.viewFlags.acsTriad) @@ -1991,7 +2099,7 @@ export class AccuDraw { /** @internal */ public decorate(context: DecorateContext) { if (context.viewport.viewFlags.acsTriad) { - context.viewport.view.auxiliaryCoordinateSystem.display(context, (ACSDisplayOptions.CheckVisible | ACSDisplayOptions.Active)); + context.viewport.view.auxiliaryCoordinateSystem.display(context, ACSDisplayOptions.CheckVisible | ACSDisplayOptions.Active); if (undefined === this._acsPickId) this._acsPickId = context.viewport.iModel.transientIds.getNext(); const acsPickBuilder = context.createGraphicBuilder(GraphicType.WorldDecoration, undefined, this._acsPickId); @@ -2044,7 +2152,8 @@ export class AccuDraw { new Point3d(-1.0, 1.0, 0.0), new Point3d(1.0, 1.0, 0.0), new Point3d(1.0, -1.0, 0.0), - new Point3d(-1.0, -1.0, 0.0)]; + new Point3d(-1.0, -1.0, 0.0), + ]; pts[4] = pts[0].clone(); builder.addShape(pts); builder.addLineString(pts); @@ -2086,7 +2195,8 @@ export class AccuDraw { new Point3d(-0.5, 0.5, 0.0), new Point3d(0.5, 0.5, 0.0), new Point3d(0.5, -0.5, 0.0), - new Point3d(-0.5, -0.5, 0.0)]; + new Point3d(-0.5, -0.5, 0.0), + ]; pts[4] = pts[0].clone(); builder.addLineString(pts); } @@ -2129,7 +2239,7 @@ export class AccuDraw { if (!this.axes.z.isPerpendicularTo(viewZRoot)) return; - const preferY = (Math.abs(this.axes.x.dotProduct(viewZRoot)) < Math.abs(this.axes.y.dotProduct(viewZRoot))); + const preferY = Math.abs(this.axes.x.dotProduct(viewZRoot)) < Math.abs(this.axes.y.dotProduct(viewZRoot)); // NOTE: Cycle rotation to get one that isn't edge-on... switch (this.rotationMode) { @@ -2186,26 +2296,35 @@ export class AccuDraw { } /** Called after compass state is changed between the active state and one of the disabled states */ - public onCompassDisplayChange(_state: "show" | "hide"): void { } + public onCompassDisplayChange(_state: "show" | "hide"): void {} /** Called after compass mode is changed between polar and rectangular */ - public onCompassModeChange(): void { } + public onCompassModeChange(): void {} /** Called after compass rotation is changed */ - public onRotationModeChange(): void { } + public onRotationModeChange(): void {} /** Called after input field locked state is changed */ - public onFieldLockChange(_index: ItemField) { } + public onFieldLockChange(_index: ItemField) {} /** Called after input field value changes */ - public onFieldValueChange(_index: ItemField) { } + public onFieldValueChange(_index: ItemField) {} /** Whether AccuDraw currently has input focus */ - public get hasInputFocus() { return true; } + public get hasInputFocus() { + return true; + } /** Set focus to the specified input field */ - public setFocusItem(_index: ItemField) { } + public setFocusItem(_index: ItemField) {} private static getMinPolarMag(origin: Point3d): number { return (1.0e-12 * (1.0 + origin.magnitude())); } /** projects cursor onto plane in view, or returns an error */ - private constructionPlane(outPtP: Point3d, inPtP: Point3d, pointOnPlaneP: Point3d, normalVectorP: Vector3d, vp: Viewport, perpendicular: boolean): BentleyStatus { + private constructionPlane( + outPtP: Point3d, + inPtP: Point3d, + pointOnPlaneP: Point3d, + normalVectorP: Vector3d, + vp: Viewport, + perpendicular: boolean, + ): BentleyStatus { let fromPtP: Point3d; let dotProduct: number; let distance: number; @@ -2251,7 +2370,14 @@ export class AccuDraw { } /** @internal */ - public softConstructionPlane(outPtP: Point3d, inPtP: Point3d, pointOnPlaneP: Point3d, normalVectorP: Vector3d, vp: Viewport, isSnap: boolean): boolean { + public softConstructionPlane( + outPtP: Point3d, + inPtP: Point3d, + pointOnPlaneP: Point3d, + normalVectorP: Vector3d, + vp: Viewport, + isSnap: boolean, + ): boolean { if (!vp.isPointAdjustmentRequired) { outPtP.setFrom(inPtP); return true; @@ -2272,7 +2398,14 @@ export class AccuDraw { } /** @internal */ - public hardConstructionPlane(outPtP: Point3d, inPtP: Point3d, pointOnPlaneP: Point3d, normalVectorP: Vector3d, vp: Viewport, isSnap: boolean): boolean { + public hardConstructionPlane( + outPtP: Point3d, + inPtP: Point3d, + pointOnPlaneP: Point3d, + normalVectorP: Vector3d, + vp: Viewport, + isSnap: boolean, + ): boolean { if (!vp.isPointAdjustmentRequired) { outPtP.setFrom(inPtP); return true; @@ -2395,7 +2528,9 @@ export class AccuDraw { this.hardConstructionPlane(this._rawPointOnPlane, this._rawPoint, this.planePt, this.axes.z, vp, TentativeOrAccuSnap.isHot); this.flags.pointIsOnPlane = true; } else { - this.flags.pointIsOnPlane = (this.softConstructionPlane(this._rawPointOnPlane, this._rawPoint, this.planePt, this.axes.z, vp, TentativeOrAccuSnap.isHot) || !!(this.locked & LockedStates.XY_BM)); + this.flags.pointIsOnPlane = + this.softConstructionPlane(this._rawPointOnPlane, this._rawPoint, this.planePt, this.axes.z, vp, TentativeOrAccuSnap.isHot) || + !!(this.locked & LockedStates.XY_BM); } } @@ -2421,7 +2556,7 @@ export class AccuDraw { return; } - this.flags.pointIsOnPlane = (Math.abs(this.axes.z.dotProduct(delta)) < Constants.SMALL_DELTA); + this.flags.pointIsOnPlane = Math.abs(this.axes.z.dotProduct(delta)) < Constants.SMALL_DELTA; } else { mag = delta.magnitude(); if (mag < minPolarMag) { @@ -2455,7 +2590,11 @@ export class AccuDraw { } } - if (this.locked & LockedStates.X_BM || (AccuDraw.allowAxisIndexing(this.flags.pointIsOnPlane) && (rotVec.x < this._tolerance && rotVec.x > - this._tolerance) && !this.flags.indexLocked && this.axisIndexing)) { + if ( + this.locked & LockedStates.X_BM || + (AccuDraw.allowAxisIndexing(this.flags.pointIsOnPlane) && (rotVec.x < this._tolerance && rotVec.x > -this._tolerance) && + !this.flags.indexLocked && this.axisIndexing) + ) { this.indexed |= LockedStates.X_BM; // indexed in X xyCorrection.x -= rotVec.x; @@ -2468,7 +2607,11 @@ export class AccuDraw { angleChanged = true; } - if (this.locked & LockedStates.Y_BM || (AccuDraw.allowAxisIndexing(this.flags.pointIsOnPlane) && (rotVec.y < this._tolerance && rotVec.y > -this._tolerance) && !this.flags.indexLocked && this.axisIndexing)) { + if ( + this.locked & LockedStates.Y_BM || + (AccuDraw.allowAxisIndexing(this.flags.pointIsOnPlane) && (rotVec.y < this._tolerance && rotVec.y > -this._tolerance) && + !this.flags.indexLocked && this.axisIndexing) + ) { if (this.indexed & LockedStates.X_BM) { // both indexed this.handleDegeneratePolarCase(); return; @@ -2564,20 +2707,27 @@ export class AccuDraw { this.indexed = 0; if (zLocked) { - this.flags.pointIsOnPlane = (this.delta.z < Constants.SMALL_ANGLE && this.delta.z > -Constants.SMALL_ANGLE); + this.flags.pointIsOnPlane = this.delta.z < Constants.SMALL_ANGLE && this.delta.z > -Constants.SMALL_ANGLE; if (!this.flags.pointIsOnPlane) this.planePt.addScaledInPlace(this.axes.z, this.delta.z); this.hardConstructionPlane(this._rawPointOnPlane, this._rawPoint, this.planePt, this.axes.z, vp, TentativeOrAccuSnap.isHot); } else { - this.flags.pointIsOnPlane = this.softConstructionPlane(this._rawPointOnPlane, this._rawPoint, this.origin, this.axes.z, vp, TentativeOrAccuSnap.isHot); + this.flags.pointIsOnPlane = this.softConstructionPlane( + this._rawPointOnPlane, + this._rawPoint, + this.origin, + this.axes.z, + vp, + TentativeOrAccuSnap.isHot, + ); } const trueDelta = this.origin.vectorTo(this._rawPointOnPlane); this._rawDelta.x = trueDelta.dotProduct(this.axes.x); - this._xIsNegative = (this._rawDelta.x < -Constants.SMALL_ANGLE); + this._xIsNegative = this._rawDelta.x < -Constants.SMALL_ANGLE; this._rawDelta.y = trueDelta.dotProduct(this.axes.y); - this._yIsNegative = (this._rawDelta.y < -Constants.SMALL_ANGLE); + this._yIsNegative = this._rawDelta.y < -Constants.SMALL_ANGLE; if (!zLocked) this.delta.z = (this.flags.pointIsOnPlane) ? 0.0 : trueDelta.dotProduct(this.axes.z); @@ -2590,8 +2740,10 @@ export class AccuDraw { this._rawDelta.x = roundedDeltaX; } - if (this._rawDelta.x < this._tolerance && this._rawDelta.x > -this._tolerance && - !this.flags.indexLocked && this.axisIndexing) { // index x + if ( + this._rawDelta.x < this._tolerance && this._rawDelta.x > -this._tolerance && + !this.flags.indexLocked && this.axisIndexing + ) { // index x this.indexed |= LockedStates.X_BM; // indexed in X xyCorrection.x -= this._rawDelta.x; this._rawDelta.x = 0.0; @@ -2604,8 +2756,10 @@ export class AccuDraw { this._rawDelta.y = roundedDeltaY; } - if (this._rawDelta.y < this._tolerance && this._rawDelta.y > -this._tolerance && - !this.flags.indexLocked && this.axisIndexing) { // index y + if ( + this._rawDelta.y < this._tolerance && this._rawDelta.y > -this._tolerance && + !this.flags.indexLocked && this.axisIndexing + ) { // index y this.indexed |= LockedStates.Y_BM; // indexed in Y xyCorrection.y -= this._rawDelta.y; this._rawDelta.y = 0.0; @@ -2616,9 +2770,11 @@ export class AccuDraw { if (this.locked & LockedStates.X_BM) { if (this.rawDeltaIsValid(this._rawDelta.x)) { // cursor changed sides, reverse value - if ((this.delta.x < -Constants.SMALL_ANGLE) !== this._xIsNegative && + if ( + (this.delta.x < -Constants.SMALL_ANGLE) !== this._xIsNegative && this.smartKeyin && this._keyinStatus[ItemField.X_Item] === KeyinStatus.Partial && - !this._xIsExplicit) + !this._xIsExplicit + ) this.delta.x = -this.delta.x; } @@ -2626,9 +2782,12 @@ export class AccuDraw { } else { const lastDist = (this._rawDelta.x < 0.0) ? (-this._lastDistance) : this._lastDistance; - if (!TentativeOrAccuSnap.isHot && ((this.locked & LockedStates.Y_BM) || (this.indexed & LockedStates.Y_BM)) && !(this.indexed & LockedStates.X_BM) && + if ( + !TentativeOrAccuSnap.isHot && ((this.locked & LockedStates.Y_BM) || (this.indexed & LockedStates.Y_BM)) && + !(this.indexed & LockedStates.X_BM) && Geometry.isDistanceWithinTol(this._rawDelta.x - lastDist, this._tolerance) && - !this.flags.indexLocked && this.distanceIndexing) { + !this.flags.indexLocked && this.distanceIndexing + ) { xyCorrection.x += lastDist - this._rawDelta.x; this.delta.x = lastDist; this.indexed |= LockedStates.DIST_BM; @@ -2640,19 +2799,24 @@ export class AccuDraw { if (this.locked & LockedStates.Y_BM) { if (this.rawDeltaIsValid(this._rawDelta.y)) { // cursor changed sides, reverse value - if ((this.delta.y < -Constants.SMALL_ANGLE) !== this._yIsNegative && + if ( + (this.delta.y < -Constants.SMALL_ANGLE) !== this._yIsNegative && this.smartKeyin && this._keyinStatus[ItemField.Y_Item] === KeyinStatus.Partial && - !this._yIsExplicit) + !this._yIsExplicit + ) this.delta.y = -this.delta.y; } xyCorrection.y = this.delta.y - this._rawDelta.y; } else { - const lastDist = (this._rawDelta.y < Constants.SMALL_ANGLE) ? - this._lastDistance : this._lastDistance; + const lastDist = (this._rawDelta.y < Constants.SMALL_ANGLE) ? -this._lastDistance : this._lastDistance; - if (!TentativeOrAccuSnap.isHot && ((this.locked & LockedStates.X_BM) || (this.indexed & LockedStates.X_BM)) && !(this.indexed & LockedStates.Y_BM) && + if ( + !TentativeOrAccuSnap.isHot && ((this.locked & LockedStates.X_BM) || (this.indexed & LockedStates.X_BM)) && + !(this.indexed & LockedStates.Y_BM) && Geometry.isDistanceWithinTol(this._rawDelta.y - lastDist, this._tolerance) && - !this.flags.indexLocked && this.distanceIndexing) { + !this.flags.indexLocked && this.distanceIndexing + ) { xyCorrection.y += lastDist - this._rawDelta.y; this.delta.y = lastDist; this.indexed |= LockedStates.DIST_BM; @@ -2695,7 +2859,7 @@ export class AccuDraw { this.newFocus = ItemField.Y_Item; this.dontMoveFocus = false; } else { - this.newFocus = ((Math.abs(this._rawDelta.x) > Math.abs(this._rawDelta.y)) ? ItemField.X_Item : ItemField.Y_Item); + this.newFocus = (Math.abs(this._rawDelta.x) > Math.abs(this._rawDelta.y)) ? ItemField.X_Item : ItemField.Y_Item; } } @@ -2824,15 +2988,19 @@ export class AccuDraw { } /** @internal */ - public onBeginDynamics(): boolean { return this.upgradeToActiveState(); } + public onBeginDynamics(): boolean { + return this.upgradeToActiveState(); + } /** @internal */ - public onEndDynamics(): boolean { return this.downgradeInactiveState(); } + public onEndDynamics(): boolean { + return this.downgradeInactiveState(); + } /** Implemented by sub-classes to update ui fields to show current deltas or coordinates when inactive. * Should also choose active x or y input field in rectangular mode based on cursor position when * axis isn't locked to support "smart lock". */ - public onMotion(_ev: BeButtonEvent): void { } + public onMotion(_ev: BeButtonEvent): void {} /** @internal */ public onPreButtonEvent(ev: BeButtonEvent): boolean { @@ -2873,9 +3041,11 @@ export class AccuDraw { this.flags.ignoreDataButton = false; } else if (!this.flags.fixedOrg && this.currentState >= CurrentState.Inactive) { /* set origin to last point placed unless its being set elsewhere */ - if (((!this.contextSensitive && - !(this.published.flags & (AccuDrawFlags.AlwaysSetOrigin ^ AccuDrawFlags.SetOrigin))) || - !(this.published.flags & AccuDrawFlags.SetOrigin))) { + if ( + ((!this.contextSensitive && + !(this.published.flags & (AccuDrawFlags.AlwaysSetOrigin ^ AccuDrawFlags.SetOrigin))) || + !(this.published.flags & AccuDrawFlags.SetOrigin)) + ) { this.published.flags |= AccuDrawFlags.SetOrigin; if (this.currentState >= CurrentState.Inactive) @@ -2913,7 +3083,13 @@ export class AccuDraw { return; const worldToView = this.currentView.worldToViewMap.transform0; - const detail = CurveCurve.intersectionProjectedXYPairs(worldToView, usePointOnSnap ? curveSegment : curve, true, usePointOnSnap ? curve : curveSegment, true); + const detail = CurveCurve.intersectionProjectedXYPairs( + worldToView, + usePointOnSnap ? curveSegment : curve, + true, + usePointOnSnap ? curve : curveSegment, + true, + ); if (0 === detail.length) return; @@ -2999,9 +3175,11 @@ export class AccuDraw { this.currentView = current; // Reset AccuDraw when iModel or view type changes... - if (undefined !== current && undefined !== previous && + if ( + undefined !== current && undefined !== previous && (current.view.classFullName === previous.view.classFullName) && - (current.view.iModel === previous.view.iModel)) + (current.view.iModel === previous.view.iModel) + ) return; this._acsPickId = undefined; @@ -3162,7 +3340,16 @@ export class AccuDraw { * @public * @extensions */ -export enum ContextRotationId { Top, Front, Left, Bottom, Back, Right, View, Face } +export enum ContextRotationId { + Top, + Front, + Left, + Bottom, + Back, + Right, + View, + Face, +} /** [[AccuDrawHintBuilder]] is an [[InteractiveTool]] helper class that facilitates AccuDraw interaction. * Accudraw is an aide for entering coordinate data. @@ -3276,16 +3463,24 @@ export class AccuDrawHintBuilder { } /** Enable AccuDraw for the current tool without sending any hints */ - public static activate(): void { IModelApp.accuDraw.activate(); } + public static activate(): void { + IModelApp.accuDraw.activate(); + } /** Disable AccuDraw for the current tool */ - public static deactivate(): void { IModelApp.accuDraw.deactivate(); } + public static deactivate(): void { + IModelApp.accuDraw.deactivate(); + } /** Whether AccuDraw is enabled by the host application this session and can be used */ - public static get isEnabled(): boolean { return IModelApp.accuDraw.isEnabled; } + public static get isEnabled(): boolean { + return IModelApp.accuDraw.isEnabled; + } /** Whether AccuDraw compass is currently displayed and points are being adjusted */ - public static get isActive(): boolean { return IModelApp.accuDraw.isActive; } + public static get isActive(): boolean { + return IModelApp.accuDraw.isActive; + } /** * Provide hints to AccuDraw using the current builder state. @@ -3325,7 +3520,17 @@ export class AccuDrawHintBuilder { flags |= AccuDrawFlags.SmartRotation; const accuDraw = IModelApp.accuDraw; - if (BentleyStatus.SUCCESS !== accuDraw.setContext(flags, this._origin, this._flagRotation ? this._rMatrix : this._axis, undefined, this._flagDistance ? this._distance : undefined, this._flagAngle ? this._angle : undefined)) + if ( + BentleyStatus.SUCCESS !== + accuDraw.setContext( + flags, + this._origin, + this._flagRotation ? this._rMatrix : this._axis, + undefined, + this._flagDistance ? this._distance : undefined, + this._flagAngle ? this._angle : undefined, + ) + ) return false; // Not enabled for this session... if (activate) @@ -3361,7 +3566,14 @@ export class AccuDrawHintBuilder { /** Return ray intersection with a plane defined by a point and normal * @see [[getBoresite]] */ - public static projectPointToPlaneInView(spacePt: Point3d, planePt: Point3d, planeNormal: Vector3d, vp: Viewport, checkAccuDraw: boolean = false, checkACS: boolean = false): Point3d | undefined { + public static projectPointToPlaneInView( + spacePt: Point3d, + planePt: Point3d, + planeNormal: Vector3d, + vp: Viewport, + checkAccuDraw: boolean = false, + checkACS: boolean = false, + ): Point3d | undefined { const plane = Plane3dByOriginAndUnitNormal.create(planePt, planeNormal); if (undefined === plane) return undefined; @@ -3375,7 +3587,14 @@ export class AccuDrawHintBuilder { /** Return ray intersection with a line defined by a point and direction * @see [[getBoresite]] */ - public static projectPointToLineInView(spacePt: Point3d, linePt: Point3d, lineDirection: Vector3d, vp: Viewport, checkAccuDraw: boolean = false, checkACS: boolean = false): Point3d | undefined { + public static projectPointToLineInView( + spacePt: Point3d, + linePt: Point3d, + lineDirection: Vector3d, + vp: Viewport, + checkAccuDraw: boolean = false, + checkACS: boolean = false, + ): Point3d | undefined { const lineRay = Ray3d.create(linePt, lineDirection); const rayToEye = AccuDrawHintBuilder.getBoresite(spacePt, vp, checkAccuDraw, checkACS); if (rayToEye.direction.isParallelTo(lineRay.direction, true)) diff --git a/core/frontend/src/AccuSnap.ts b/core/frontend/src/AccuSnap.ts index ccab0c626fcb..a828257856d4 100644 --- a/core/frontend/src/AccuSnap.ts +++ b/core/frontend/src/AccuSnap.ts @@ -7,8 +7,9 @@ */ import { BeDuration, Id64, Id64Arg, Id64Set } from "@itwin/core-bentley"; -import { CurveCurve, CurvePrimitive, GeometryQuery, IModelJson as GeomJson, Point2d, Point3d, Vector3d, XAndY } from "@itwin/core-geometry"; import { SnapRequestProps } from "@itwin/core-common"; +import { CurveCurve, CurvePrimitive, GeometryQuery, IModelJson as GeomJson, Point2d, Point3d, Vector3d, XAndY } from "@itwin/core-geometry"; +import { _requestSnap } from "./common/internal/Symbols"; import { ElementLocateManager, HitListHolder, LocateAction, LocateFilterStatus, LocateResponse, SnapStatus } from "./ElementLocateManager"; import { HitDetail, HitDetailType, HitGeomType, HitList, HitPriority, HitSource, IntersectDetail, SnapDetail, SnapHeat, SnapMode } from "./HitDetail"; import { IModelApp } from "./IModelApp"; @@ -19,7 +20,6 @@ import { ToolSettings } from "./tools/ToolSettings"; import { DecorateContext } from "./ViewContext"; import { Decorator } from "./ViewManager"; import { ScreenViewport, Viewport } from "./Viewport"; -import { _requestSnap } from "./common/internal/Symbols"; // cspell:ignore dont primitivetools @@ -111,8 +111,12 @@ export class TouchCursor implements CanvasDecoration { this.drawHandle(ctx, false); } - protected isSelected(pt: XAndY): boolean { return this.position.distance(Point3d.create(pt.x, pt.y)) < this._size; } - public isButtonHandled(ev: BeButtonEvent): boolean { return (BeButton.Data === ev.button && InputSource.Touch === ev.inputSource && !this._inTouchTap); } + protected isSelected(pt: XAndY): boolean { + return this.position.distance(Point3d.create(pt.x, pt.y)) < this._size; + } + public isButtonHandled(ev: BeButtonEvent): boolean { + return (BeButton.Data === ev.button && InputSource.Touch === ev.inputSource && !this._inTouchTap); + } public doTouchMove(ev: BeTouchEvent): boolean { if (undefined === ev.viewport || !ev.isSingleTouch) @@ -211,31 +215,55 @@ export class AccuSnap implements Decorator { private _toolTipPromise?: Promise>; /** @internal */ - public onInitialized() { } - private get _searchDistance(): number { return this.isLocateEnabled ? 1.0 : this._settings.searchDistance; } - private get _hotDistanceInches(): number { return IModelApp.locateManager.apertureInches * this._settings.hotDistanceFactor; } + public onInitialized() {} + private get _searchDistance(): number { + return this.isLocateEnabled ? 1.0 : this._settings.searchDistance; + } + private get _hotDistanceInches(): number { + return IModelApp.locateManager.apertureInches * this._settings.hotDistanceFactor; + } /** Whether locate of elements under the cursor is enabled by the current InteractiveTool. */ - public get isLocateEnabled(): boolean { return this.toolState.locate; } + public get isLocateEnabled(): boolean { + return this.toolState.locate; + } /** Whether snapping to elements under the cursor is enabled by the current InteractiveTool. */ - public get isSnapEnabled(): boolean { return this.toolState.enabled; } + public get isSnapEnabled(): boolean { + return this.toolState.enabled; + } /** Whether the user setting for snapping is enabled. Snapping is done only when both the user and current InteractiveTool have enabled it. */ - public get isSnapEnabledByUser(): boolean { return this._settings.enableFlag; } + public get isSnapEnabledByUser(): boolean { + return this._settings.enableFlag; + } /** AccuSnap user settings */ - public get userSettings() { return this._settings; } + public get userSettings() { + return this._settings; + } - private isFlashed(view: Viewport): boolean { return (this.areFlashed.has(view)); } - private needsFlash(view: Viewport): boolean { return (this.needFlash.has(view)); } + private isFlashed(view: Viewport): boolean { + return (this.areFlashed.has(view)); + } + private needsFlash(view: Viewport): boolean { + return (this.needFlash.has(view)); + } private setNeedsFlash(view: Viewport) { this.needFlash.add(view); this.clearIsFlashed(view); view.invalidateDecorations(); } - private setIsFlashed(view: Viewport) { this.areFlashed.add(view); } - private clearIsFlashed(view: Viewport) { this.areFlashed.delete(view); } - private static toSnapDetail(hit?: HitDetail): SnapDetail | undefined { return (hit && hit instanceof SnapDetail) ? hit : undefined; } + private setIsFlashed(view: Viewport) { + this.areFlashed.add(view); + } + private clearIsFlashed(view: Viewport) { + this.areFlashed.delete(view); + } + private static toSnapDetail(hit?: HitDetail): SnapDetail | undefined { + return (hit && hit instanceof SnapDetail) ? hit : undefined; + } /** Currently active snap */ - public getCurrSnapDetail(): SnapDetail | undefined { return AccuSnap.toSnapDetail(this.currHit); } + public getCurrSnapDetail(): SnapDetail | undefined { + return AccuSnap.toSnapDetail(this.currHit); + } /** Determine whether there is a current hit that is *hot*. */ public get isHot(): boolean { const currSnap = this.getCurrSnapDetail(); @@ -256,7 +284,7 @@ export class AccuSnap implements Decorator { for (const id of Id64.iterable(ids)) newIds.add(id); - this.toolState.neverFlash = (0 !== newIds.size ? newIds : undefined); + this.toolState.neverFlash = 0 !== newIds.size ? newIds : undefined; } /** @internal */ @@ -265,13 +293,19 @@ export class AccuSnap implements Decorator { this.aSnapHits = undefined; } - private get _doSnapping(): boolean { return this.isSnapEnabled && this.isSnapEnabledByUser && !this._isSnapSuspended; } - private get _isSnapSuspended(): boolean { return (0 !== this._suppressed || 0 !== this.toolState.suspended); } + private get _doSnapping(): boolean { + return this.isSnapEnabled && this.isSnapEnabledByUser && !this._isSnapSuspended; + } + private get _isSnapSuspended(): boolean { + return (0 !== this._suppressed || 0 !== this.toolState.suspended); + } /** Get the current snap divisor to use to use for SnapMode.NearestKeypoint. * @public */ - public get keypointDivisor() { return this._settings.keypointDivisor; } + public get keypointDivisor() { + return this._settings.keypointDivisor; + } /** Get the current active SnapModes. SnapMode position determines priority, with the first entry being the highest. The SnapDetail will be returned for the first SnapMode that produces a hot snap. * @public @@ -286,7 +320,7 @@ export class AccuSnap implements Decorator { * This method will be called whenever a new tool is installed and on button events. * @internal */ - public synchSnapMode(): void { } + public synchSnapMode(): void {} /** Check whether current tentative snap has valid curve geometry for finding extended intersections. */ private get _searchForExtendedIntersections(): boolean { @@ -321,18 +355,20 @@ export class AccuSnap implements Decorator { } /** Clear the current AccuSnap info. */ - public clear(): void { this.setCurrHit(undefined); } + public clear(): void { + this.setCurrHit(undefined); + } /** @internal */ public setCurrHit(newHit?: HitDetail): void { const newSnap = AccuSnap.toSnapDetail(newHit); const currSnap = this.getCurrSnapDetail(); - const sameElem = (undefined !== newHit && newHit.isSameHit(this.currHit)); - const sameHit = (sameElem && !newSnap); - const sameSnap = (sameElem && undefined !== newSnap && undefined !== currSnap); - const samePt = (sameHit || (sameSnap && newSnap.snapPoint.isAlmostEqual(currSnap.snapPoint))); - const sameHot = (sameHit || (sameSnap && (this.isHot === newSnap.isHot))); - const sameBaseSnapMode = (!newSnap || !currSnap || newSnap.snapMode === currSnap.snapMode); - const sameType = (sameHot && (!currSnap || (currSnap.getHitType() === newHit.getHitType()))); + const sameElem = undefined !== newHit && newHit.isSameHit(this.currHit); + const sameHit = sameElem && !newSnap; + const sameSnap = sameElem && undefined !== newSnap && undefined !== currSnap; + const samePt = sameHit || (sameSnap && newSnap.snapPoint.isAlmostEqual(currSnap.snapPoint)); + const sameHot = sameHit || (sameSnap && (this.isHot === newSnap.isHot)); + const sameBaseSnapMode = !newSnap || !currSnap || newSnap.snapMode === currSnap.snapMode; + const sameType = sameHot && (!currSnap || (currSnap.getHitType() === newHit.getHitType())); // see if it is the same point on the same element, the hot flags are the same multiple snaps, and the snap modes are the same if (samePt && sameType && sameBaseSnapMode) { @@ -399,7 +435,7 @@ export class AccuSnap implements Decorator { const msg = await IModelApp.toolAdmin.getToolTip(hit); if (this._toolTipPromise === promise) // have we abandoned this request while awaiting getToolTip? this.showLocateMessage(viewPt, vp, msg); - } catch (error) { } // happens if getToolTip was canceled + } catch (error) {} // happens if getToolTip was canceled }); } @@ -491,8 +527,8 @@ export class AccuSnap implements Decorator { private static adjustIconLocation(vp: Viewport, input: Point3d, iconSize: XAndY): Point3d { const out = vp.worldToView(input); - out.x += (iconSize.x / 3.0); - out.y -= (iconSize.y * 1.3); + out.x += iconSize.x / 3.0; + out.y -= iconSize.y * 1.3; return vp.viewToWorld(out, out); } @@ -570,7 +606,7 @@ export class AccuSnap implements Decorator { /** Implemented by sub-classes to update ui to show current enabled state. * @internal */ - public onEnabledStateChange(_isEnabled: boolean, _wasEnabled: boolean) { } + public onEnabledStateChange(_isEnabled: boolean, _wasEnabled: boolean) {} /** @internal */ public getHitAndList(holder: HitListHolder): HitDetail | undefined { @@ -641,7 +677,10 @@ export class AccuSnap implements Decorator { let closeIndex = 0; if (detail.length > 1) { - const snapPt = worldToView.multiplyPoint3d(HitGeomType.Point === tpSnap.geomType && HitGeomType.Point !== second.geomType ? second.getPoint() : tpSnap.getPoint(), 1); // Don't check distance from arc centers... + const snapPt = worldToView.multiplyPoint3d( + HitGeomType.Point === tpSnap.geomType && HitGeomType.Point !== second.geomType ? second.getPoint() : tpSnap.getPoint(), + 1, + ); // Don't check distance from arc centers... let lastDist: number | undefined; for (let i = 0; i < detail.length; i++) { @@ -662,7 +701,14 @@ export class AccuSnap implements Decorator { } /** @internal */ - public static async requestSnap(thisHit: HitDetail, snapModes: SnapMode[], hotDistanceInches: number, keypointDivisor: number, hitList?: HitList, out?: LocateResponse): Promise { + public static async requestSnap( + thisHit: HitDetail, + snapModes: SnapMode[], + hotDistanceInches: number, + keypointDivisor: number, + hitList?: HitList, + out?: LocateResponse, + ): Promise { if (thisHit.isModelHit || thisHit.isMapHit || thisHit.isClassifier) { if (snapModes.includes(SnapMode.Nearest)) { if (out) @@ -690,7 +736,9 @@ export class AccuSnap implements Decorator { if (appearance.dontSnap) { if (out) { out.snapStatus = SnapStatus.NotSnappable; - out.explanation = IModelApp.localization.getLocalizedString(`iModelJs:${ElementLocateManager.getFailureMessageKey("NotSnappableSubCategory")}`); + out.explanation = IModelApp.localization.getLocalizedString( + `iModelJs:${ElementLocateManager.getFailureMessageKey("NotSnappableSubCategory")}`, + ); } return undefined; } @@ -710,7 +758,9 @@ export class AccuSnap implements Decorator { modelToWorld: thisHit.transformFromSourceIModel?.toJSON(), }; - const thisGeom = (thisHit.isElementHit ? IModelApp.viewManager.overrideElementGeometry(thisHit) : IModelApp.viewManager.getDecorationGeometry(thisHit)); + const thisGeom = thisHit.isElementHit + ? IModelApp.viewManager.overrideElementGeometry(thisHit) + : IModelApp.viewManager.getDecorationGeometry(thisHit); if (undefined !== thisGeom) { requestProps.decorationGeometry = [{ id: thisHit.sourceId, geometryStream: thisGeom }]; @@ -726,7 +776,7 @@ export class AccuSnap implements Decorator { if (thisHit.sourceId === hit.sourceId || thisHit.iModel !== hit.iModel) continue; - const geom = (hit.isElementHit ? IModelApp.viewManager.overrideElementGeometry(hit) : IModelApp.viewManager.getDecorationGeometry(hit)); + const geom = hit.isElementHit ? IModelApp.viewManager.overrideElementGeometry(hit) : IModelApp.viewManager.getDecorationGeometry(hit); if (undefined !== geom) { if (undefined === requestProps.decorationGeometry) @@ -825,7 +875,9 @@ export class AccuSnap implements Decorator { if (undefined === thisHit) return undefined; - const filterStatus: LocateFilterStatus = (this.isLocateEnabled ? await IModelApp.locateManager.filterHit(thisHit, LocateAction.AutoLocate, out) : LocateFilterStatus.Accept); + const filterStatus: LocateFilterStatus = this.isLocateEnabled + ? await IModelApp.locateManager.filterHit(thisHit, LocateAction.AutoLocate, out) + : LocateFilterStatus.Accept; if (LocateFilterStatus.Accept !== filterStatus) { out.snapStatus = SnapStatus.FilteredByApp; return undefined; @@ -901,7 +953,8 @@ export class AccuSnap implements Decorator { this.aSnapHits = picker.getHitList(true); // take ownership of the pickElem hit list. // see if we should keep the current hit - const canBeSticky = !force && this.aSnapHits.length > 1 && this.currHit && (HitDetailType.Intersection !== this.currHit.getHitType() && this.currHit.priority < HitPriority.PlanarSurface); + const canBeSticky = !force && this.aSnapHits.length > 1 && this.currHit && + (HitDetailType.Intersection !== this.currHit.getHitType() && this.currHit.priority < HitPriority.PlanarSurface); if (canBeSticky) { for (let iHit = 1; iHit < this.aSnapHits.length; ++iHit) { const thisHit = this.aSnapHits.hits[iHit]; @@ -1032,7 +1085,9 @@ export class AccuSnap implements Decorator { } /** @internal */ - public onPreButtonEvent(ev: BeButtonEvent): boolean { return (undefined !== this.touchCursor) ? this.touchCursor.isButtonHandled(ev) : false; } + public onPreButtonEvent(ev: BeButtonEvent): boolean { + return (undefined !== this.touchCursor) ? this.touchCursor.isButtonHandled(ev) : false; + } /** @internal */ public onTouchStart(ev: BeTouchEvent): void { if (undefined !== this.touchCursor) @@ -1173,7 +1228,9 @@ export class AccuSnap implements Decorator { */ export class TentativeOrAccuSnap { /** @return true if AccuSnap is *hot* or TentativePoint is active and snapped to pickable geometry. */ - public static get isHot(): boolean { return IModelApp.accuSnap.isHot || IModelApp.tentativePoint.isSnapped; } + public static get isHot(): boolean { + return IModelApp.accuSnap.isHot || IModelApp.tentativePoint.isSnapped; + } /** Get the current snap from either AccuSnap or TentativePoint. * @param checkIsHot true to only return the snap from AccuSnap when it is *hot*. diff --git a/core/frontend/src/ApproximateTerrainHeights.ts b/core/frontend/src/ApproximateTerrainHeights.ts index 1a1a83b6f092..b10d1a4a4b70 100644 --- a/core/frontend/src/ApproximateTerrainHeights.ts +++ b/core/frontend/src/ApproximateTerrainHeights.ts @@ -7,10 +7,10 @@ */ import { assert } from "@itwin/core-bentley"; -import { Point2d, Range1d, Range2d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; -import { GeographicTilingScheme, QuadId } from "./tile/internal"; +import { Point2d, Range1d, Range2d } from "@itwin/core-geometry"; import type { ApproximateTerrainHeightsProps } from "./ApproximateTerrainHeightsProps"; +import { GeographicTilingScheme, QuadId } from "./tile/internal"; let instance: ApproximateTerrainHeights | undefined; @@ -47,12 +47,12 @@ export class ApproximateTerrainHeights { public getTileHeightRange(quadId: QuadId, result?: Range1d): Range1d { result = Range1d.createFrom(this.globalHeightRange, result); if (undefined === this._terrainHeights) - return result; // Not initialized. + return result; // Not initialized. let level = quadId.level, column = quadId.column, row = quadId.row; if (level > 6) { column = column >> (level - 6); - row = row >> quadId.row >> ((level - 6)); + row = row >> quadId.row >> (level - 6); level = 6; } @@ -69,7 +69,7 @@ export class ApproximateTerrainHeights { public getMinimumMaximumHeights(rectangle: Range2d, result?: Range1d): Range1d { result = Range1d.createFrom(this.globalHeightRange, result); if (undefined === this._terrainHeights) - return result; // Not initialized. + return result; // Not initialized. const xyLevel = this._getTileXYLevel(rectangle); if (undefined !== xyLevel) { diff --git a/core/frontend/src/AuxCoordSys.ts b/core/frontend/src/AuxCoordSys.ts index cce41f8d0d84..0ad8dd37555e 100644 --- a/core/frontend/src/AuxCoordSys.ts +++ b/core/frontend/src/AuxCoordSys.ts @@ -7,18 +7,26 @@ */ import { JsonUtils } from "@itwin/core-bentley"; -import { Angle, AngleSweep, Arc3d, Matrix3d, Point2d, Point3d, Transform, Vector3d, XAndY, XYAndZ, YawPitchRollAngles } from "@itwin/core-geometry"; import { - AuxCoordSystem2dProps, AuxCoordSystem3dProps, AuxCoordSystemProps, BisCodeSpec, Code, ColorDef, IModel, LinePixels, Npc, + AuxCoordSystem2dProps, + AuxCoordSystem3dProps, + AuxCoordSystemProps, + BisCodeSpec, + Code, + ColorDef, + IModel, + LinePixels, + Npc, } from "@itwin/core-common"; +import { Angle, AngleSweep, Arc3d, Matrix3d, Point2d, Point3d, Transform, Vector3d, XAndY, XYAndZ, YawPitchRollAngles } from "@itwin/core-geometry"; +import { GraphicType } from "./common/render/GraphicType"; +import { CoordSystem } from "./CoordSystem"; import { ElementState } from "./EntityState"; import { IModelConnection } from "./IModelConnection"; import { GraphicBuilder } from "./render/GraphicBuilder"; import { DecorateContext } from "./ViewContext"; -import { CoordSystem } from "./CoordSystem"; import { Viewport } from "./Viewport"; import { ViewState } from "./ViewState"; -import { GraphicType } from "./common/render/GraphicType"; /** * @public @@ -63,7 +71,9 @@ const enum ACSDisplaySizes { // eslint-disable-line no-restricted-syntax * @extensions */ export abstract class AuxCoordSystemState extends ElementState implements AuxCoordSystemProps { - public static override get className() { return "AuxCoordSystem"; } + public static override get className() { + return "AuxCoordSystem"; + } public type: number; public description?: string; @@ -111,7 +121,9 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo /** get a *copy of* the rotation matrix for this ACS. */ public abstract getRotation(result?: Matrix3d): Matrix3d; public abstract setRotation(val: Matrix3d): void; - public get is3d(): boolean { return this instanceof AuxCoordSystem3dState; } + public get is3d(): boolean { + return this instanceof AuxCoordSystem3dState; + } public drawGrid(context: DecorateContext): void { // Called for active ACS when grid orientation is GridOrientationType::ACS. @@ -121,7 +133,9 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo } /** Returns the value, clamped to the supplied range. */ - private static limitRange(min: number, max: number, val: number): number { return Math.max(min, Math.min(max, val)); } + private static limitRange(min: number, max: number, val: number): number { + return Math.max(min, Math.min(max, val)); + } /** * Given an origin point, returns whether the point falls within the view or not. If adjustOrigin is set to true, a point outside @@ -136,7 +150,7 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo screenRange.z = frustum.points[Npc._000].distance(frustum.points[Npc._001]); // Check if current acs origin is outside view... - const inView = (!((testPtView.x < 0 || testPtView.x > screenRange.x) || (testPtView.y < 0 || testPtView.y > screenRange.y))); + const inView = !((testPtView.x < 0 || testPtView.x > screenRange.x) || (testPtView.y < 0 || testPtView.y > screenRange.y)); if (!adjustOrigin) return inView; @@ -171,7 +185,9 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo color = color.adjustedForContrast(viewport.view.backgroundColor); if (isFill) - color = color.withTransparency((options & (ACSDisplayOptions.Deemphasized | ACSDisplayOptions.Dynamics)) !== ACSDisplayOptions.None ? 225 : 200); + color = color.withTransparency( + (options & (ACSDisplayOptions.Deemphasized | ACSDisplayOptions.Dynamics)) !== ACSDisplayOptions.None ? 225 : 200, + ); else color = color.withTransparency((options & ACSDisplayOptions.Deemphasized) !== ACSDisplayOptions.None ? 150 : 75); @@ -206,7 +222,7 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo } private addAxis(builder: GraphicBuilder, axis: number, options: ACSDisplayOptions, vp: Viewport) { - const color = (0 === axis ? ColorDef.red : (1 === axis ? ColorDef.green : ColorDef.blue)); + const color = 0 === axis ? ColorDef.red : (1 === axis ? ColorDef.green : ColorDef.blue); const lineColor = this.getAdjustedColor(color, false, vp, options); const fillColor = this.getAdjustedColor(color, true, vp, options); @@ -216,7 +232,12 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo const linePts2: Point3d[] = [Point3d.create(), Point3d.create()]; // NOTE: Don't use same point array, addPointString/addLineString don't deep copy... linePts2[1].z = ACSDisplaySizes.ZAxisLength; - builder.setSymbology(lineColor, lineColor, 1, (options & ACSDisplayOptions.Dynamics) === ACSDisplayOptions.None ? LinePixels.Solid : LinePixels.Code2); + builder.setSymbology( + lineColor, + lineColor, + 1, + (options & ACSDisplayOptions.Dynamics) === ACSDisplayOptions.None ? LinePixels.Solid : LinePixels.Code2, + ); builder.addLineString(linePts2); const scale = ACSDisplaySizes.ArrowTipWidth / 2; @@ -232,7 +253,13 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo xVec.normalize(xVec); yVec.normalize(yVec); - const ellipse = Arc3d.createScaledXYColumns(center, Matrix3d.createColumns(xVec, yVec, Vector3d.create()), scale, scale, AngleSweep.createStartEnd(Angle.createRadians(0), Angle.createRadians(Math.PI * 2))); + const ellipse = Arc3d.createScaledXYColumns( + center, + Matrix3d.createColumns(xVec, yVec, Vector3d.create()), + scale, + scale, + AngleSweep.createStartEnd(Angle.createRadians(0), Angle.createRadians(Math.PI * 2)), + ); builder.addArc(ellipse, false, false); builder.setBlankingFill(fillColor); @@ -252,7 +279,12 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo if (1 === axis) shapePts.forEach((tmpPt) => tmpPt.set(tmpPt.y, tmpPt.x)); - builder.setSymbology(lineColor, lineColor, 1, (options & ACSDisplayOptions.Dynamics) === ACSDisplayOptions.None ? LinePixels.Solid : LinePixels.Code2); + builder.setSymbology( + lineColor, + lineColor, + 1, + (options & ACSDisplayOptions.Dynamics) === ACSDisplayOptions.None ? LinePixels.Solid : LinePixels.Code2, + ); builder.addLineString(shapePts); this.addAxisLabel(builder, axis, options, vp); @@ -304,7 +336,9 @@ export abstract class AuxCoordSystemState extends ElementState implements AuxCoo * @extensions */ export class AuxCoordSystem2dState extends AuxCoordSystemState implements AuxCoordSystem2dProps { - public static override get className() { return "AuxCoordSystem2d"; } + public static override get className() { + return "AuxCoordSystem2d"; + } public readonly origin: Point2d; public angle: number; // in degrees private readonly _rMatrix: Matrix3d; @@ -323,13 +357,19 @@ export class AuxCoordSystem2dState extends AuxCoordSystemState implements AuxCoo return val; } - public getOrigin(result?: Point3d): Point3d { return Point3d.createFrom(this.origin, result); } - public setOrigin(val: XYAndZ | XAndY): void { this.origin.setFrom(val); } - public getRotation(result?: Matrix3d): Matrix3d { return this._rMatrix.clone(result); } + public getOrigin(result?: Point3d): Point3d { + return Point3d.createFrom(this.origin, result); + } + public setOrigin(val: XYAndZ | XAndY): void { + this.origin.setFrom(val); + } + public getRotation(result?: Matrix3d): Matrix3d { + return this._rMatrix.clone(result); + } public setRotation(val: Matrix3d): void { this._rMatrix.setFrom(val); const angle = YawPitchRollAngles.createFromMatrix3d(val); - this.angle = (undefined !== angle ? angle.yaw.degrees : 0.0); + this.angle = undefined !== angle ? angle.yaw.degrees : 0.0; } } @@ -338,7 +378,9 @@ export class AuxCoordSystem2dState extends AuxCoordSystemState implements AuxCoo * @extensions */ export class AuxCoordSystem3dState extends AuxCoordSystemState implements AuxCoordSystem3dProps { - public static override get className() { return "AuxCoordSystem3d"; } + public static override get className() { + return "AuxCoordSystem3d"; + } public readonly origin: Point3d; public yaw: number; // in degrees public pitch: number; // in degrees @@ -364,15 +406,21 @@ export class AuxCoordSystem3dState extends AuxCoordSystemState implements AuxCoo return val; } - public getOrigin(result?: Point3d): Point3d { return Point3d.createFrom(this.origin, result); } - public setOrigin(val: XYAndZ | XAndY): void { this.origin.setFrom(val); } - public getRotation(result?: Matrix3d): Matrix3d { return this._rMatrix.clone(result); } + public getOrigin(result?: Point3d): Point3d { + return Point3d.createFrom(this.origin, result); + } + public setOrigin(val: XYAndZ | XAndY): void { + this.origin.setFrom(val); + } + public getRotation(result?: Matrix3d): Matrix3d { + return this._rMatrix.clone(result); + } public setRotation(rMatrix: Matrix3d): void { this._rMatrix.setFrom(rMatrix); const angles = YawPitchRollAngles.createFromMatrix3d(rMatrix); - this.yaw = (undefined !== angles ? angles.yaw.degrees : 0.0); - this.pitch = (undefined !== angles ? angles.pitch.degrees : 0.0); - this.roll = (undefined !== angles ? angles.roll.degrees : 0.0); + this.yaw = undefined !== angles ? angles.yaw.degrees : 0.0; + this.pitch = undefined !== angles ? angles.pitch.degrees : 0.0; + this.roll = undefined !== angles ? angles.roll.degrees : 0.0; } } @@ -381,5 +429,7 @@ export class AuxCoordSystem3dState extends AuxCoordSystemState implements AuxCoo * @extensions */ export class AuxCoordSystemSpatialState extends AuxCoordSystem3dState { - public static override get className() { return "AuxCoordSystemSpatial"; } + public static override get className() { + return "AuxCoordSystemSpatial"; + } } diff --git a/core/frontend/src/BackgroundMapGeometry.ts b/core/frontend/src/BackgroundMapGeometry.ts index 74ce991d3510..b7ac60ef8fb0 100644 --- a/core/frontend/src/BackgroundMapGeometry.ts +++ b/core/frontend/src/BackgroundMapGeometry.ts @@ -7,8 +7,30 @@ */ import { assert } from "@itwin/core-bentley"; -import { Angle, Arc3d, ClipPlane, ClipPlaneContainment, Constant, CurvePrimitive, Ellipsoid, GrowableXYZArray, LongitudeLatitudeNumber, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point4d, Range1d, Range3d, Ray3d, Transform, Vector3d, WritableXYAndZ, XYAndZ } from "@itwin/core-geometry"; import { Cartographic, ColorByName, ColorDef, Frustum, GeoCoordStatus, GlobeMode, LinePixels } from "@itwin/core-common"; +import { + Angle, + Arc3d, + ClipPlane, + ClipPlaneContainment, + Constant, + CurvePrimitive, + Ellipsoid, + GrowableXYZArray, + LongitudeLatitudeNumber, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Point4d, + Range1d, + Range3d, + Ray3d, + Transform, + Vector3d, + WritableXYAndZ, + XYAndZ, +} from "@itwin/core-geometry"; import { IModelConnection } from "./IModelConnection"; import { GraphicBuilder } from "./render/GraphicBuilder"; import { WebMercatorTilingScheme } from "./tile/internal"; @@ -30,7 +52,13 @@ function accumulateDepthRange(point: Point3d, viewRotation: Matrix3d, range: Ran range.extend(scratchPoint); } -function accumulateFrustumPlaneDepthRange(frustum: Frustum, plane: Plane3dByOriginAndUnitNormal, viewRotation: Matrix3d, range: Range3d, eyePoint?: Point3d) { +function accumulateFrustumPlaneDepthRange( + frustum: Frustum, + plane: Plane3dByOriginAndUnitNormal, + viewRotation: Matrix3d, + range: Range3d, + eyePoint?: Point3d, +) { let includeHorizon = false; for (let i = 0; i < 4; i++) { const frustumRay = Ray3d.createStartEnd(eyePoint ? eyePoint : frustum.points[i + 4], frustum.points[i]); @@ -81,8 +109,8 @@ export class BackgroundMapGeometry { private _mercatorFractionToDb: Transform; private _mercatorTilingScheme: WebMercatorTilingScheme; private _ecefToDb: Transform; - public static maxCartesianDistance = 1E4; // If globe is 3D we still consider the map geometry flat within this distance of the project extents. - private static _transitionDistanceMultiplier = .25; // In the transition range which extends beyond the cartesian range we interpolate between cartesian and ellipsoid. + public static maxCartesianDistance = 1E4; // If globe is 3D we still consider the map geometry flat within this distance of the project extents. + private static _transitionDistanceMultiplier = .25; // In the transition range which extends beyond the cartesian range we interpolate between cartesian and ellipsoid. private static _scratchRayFractions = new Array(); private static _scratchRayAngles = new Array(); @@ -112,7 +140,8 @@ export class BackgroundMapGeometry { return cartesianRange; } public static getCartesianTransitionDistance(iModel: IModelConnection): number { - return BackgroundMapGeometry.getCartesianRange(iModel, scratchRange).diagonal().magnitudeXY() * BackgroundMapGeometry._transitionDistanceMultiplier; + return BackgroundMapGeometry.getCartesianRange(iModel, scratchRange).diagonal().magnitudeXY() * + BackgroundMapGeometry._transitionDistanceMultiplier; } public async dbToCartographicFromGcs(db: XYAndZ[]): Promise { @@ -134,7 +163,7 @@ export class BackgroundMapGeometry { const scratch = new Point3d(); for (let i = 0; i < db.length; i++) { Point3d.createFrom(db[i], scratch); - if (this.cartesianRange.containsPoint(scratch) ) { + if (this.cartesianRange.containsPoint(scratch)) { reprojectIdx.push(i); reproject.push(db[i]); } else { @@ -146,8 +175,8 @@ export class BackgroundMapGeometry { return result; const reprojectPromise = this._iModel.wgs84CartographicFromSpatial(reproject); - return reprojectPromise.then((reprojected) => { - if (reprojected.length === reprojectIdx.length) { // reprojected array size must match our index array, otherwise something is OFF + return reprojectPromise.then((reprojected) => { + if (reprojected.length === reprojectIdx.length) { // reprojected array size must match our index array, otherwise something is OFF for (let i = 0; i < reprojected.length; i++) { result[reprojectIdx[i]] = reprojected[i]; // Insert the reprojected values at their original index } @@ -210,7 +239,7 @@ export class BackgroundMapGeometry { const toReprojectIdx: number[] = []; db.forEach(async (p, i) => { if (this.cartesianRange.containsPoint(p)) { - toReprojectCoords.push({x:cartographic[i].longitudeDegrees, y:cartographic[i].latitudeDegrees, z:cartographic[i].height}); + toReprojectCoords.push({ x: cartographic[i].longitudeDegrees, y: cartographic[i].latitudeDegrees, z: cartographic[i].height }); toReprojectIdx.push(i); } }); @@ -254,9 +283,13 @@ export class BackgroundMapGeometry { if ((!positiveOnly || thisFraction > 0) && (undefined === intersectDistance || thisFraction < intersectDistance)) { intersectDistance = thisFraction; intersect = scratchIntersectRay; - ellipsoid.radiansToUnitNormalRay(BackgroundMapGeometry._scratchRayAngles[i].longitudeRadians, BackgroundMapGeometry._scratchRayAngles[i].latitudeRadians, intersect); + ellipsoid.radiansToUnitNormalRay( + BackgroundMapGeometry._scratchRayAngles[i].longitudeRadians, + BackgroundMapGeometry._scratchRayAngles[i].latitudeRadians, + intersect, + ); if (intersect.direction.dotProduct(ray.direction) < 0) { - if (this.cartesianRange.containsPoint(intersect.origin)) { // If we're in the cartesian range, correct to planar intersection. + if (this.cartesianRange.containsPoint(intersect.origin)) { // If we're in the cartesian range, correct to planar intersection. const planeFraction = ray.intersectionWithPlane(this.cartesianPlane, scratchIntersectRay.origin); if (undefined !== planeFraction && (!positiveOnly || planeFraction > 0)) { intersect.direction.setFromVector3d(this.cartesianPlane.getNormalRef()); @@ -292,16 +325,22 @@ export class BackgroundMapGeometry { } /** @internal */ - public getFrustumIntersectionDepthRange(frustum: Frustum, bimRange: Range3d, heightRange?: Range1d, gridPlane?: Plane3dByOriginAndUnitNormal, doGlobalScope?: boolean): Range1d { + public getFrustumIntersectionDepthRange( + frustum: Frustum, + bimRange: Range3d, + heightRange?: Range1d, + gridPlane?: Plane3dByOriginAndUnitNormal, + doGlobalScope?: boolean, + ): Range1d { const clipPlanes = frustum.getRangePlanes(false, false, 0); const eyePoint = frustum.getEyePoint(scratchEyePoint); const viewRotation = frustum.getRotation(scratchViewRotation); if (undefined === viewRotation) - return Range1d.createNull(); // Degenerate frustum... + return Range1d.createNull(); // Degenerate frustum... const viewZ = viewRotation.getRow(2); const cartoRange = this.cartesianTransitionRange; const intersectRange = Range3d.createNull(); - const doAccumulate = ((point: Point3d) => accumulateDepthRange(point, viewRotation, intersectRange)); + const doAccumulate = (point: Point3d) => accumulateDepthRange(point, viewRotation, intersectRange); if (gridPlane) accumulateFrustumPlaneDepthRange(frustum, gridPlane, viewRotation, intersectRange, eyePoint); @@ -331,10 +370,12 @@ export class BackgroundMapGeometry { // Extrema... let angles, extremaPoint; - if (undefined !== (angles = ellipsoid.surfaceNormalToAngles(viewZ)) && + if ( + undefined !== (angles = ellipsoid.surfaceNormalToAngles(viewZ)) && undefined !== (extremaPoint = ellipsoid.radiansToPoint(angles.longitudeRadians, angles.latitudeRadians)) && (eyePoint === undefined || viewZ.dotProductStartEnd(extremaPoint, eyePoint) > 0) && - clipPlanes.classifyPointContainment([extremaPoint], false) !== ClipPlaneContainment.StronglyOutside) + clipPlanes.classifyPointContainment([extremaPoint], false) !== ClipPlaneContainment.StronglyOutside + ) doAccumulate(extremaPoint); if (isInside) { @@ -355,7 +396,9 @@ export class BackgroundMapGeometry { if (Vector3d.createStartEnd(silhouette.center, bimRange.center).dotProduct(scratchSilhouetteNormal) < 0) scratchSilhouetteNormal.negate(scratchSilhouetteNormal); } - clipPlanes.planes.push(ClipPlane.createNormalAndDistance(scratchSilhouetteNormal, scratchSilhouetteNormal.dotProduct(silhouette.center))!); + clipPlanes.planes.push( + ClipPlane.createNormalAndDistance(scratchSilhouetteNormal, scratchSilhouetteNormal.dotProduct(silhouette.center))!, + ); } else { clipPlanes.planes.push(ClipPlane.createNormalAndPoint(viewZ, center)!); } @@ -370,12 +413,11 @@ export class BackgroundMapGeometry { if (undefined !== arc) { arc.announceClipIntervals(clipPlanes, (a0: number, a1: number, cp: CurvePrimitive) => { if (Math.abs(a1 - a0) < 1.0E-8) { - doAccumulate(cp.fractionToPoint(a0)); // Tiny sweep - avoid problem with rangeMethod (not worth doing anyway). + doAccumulate(cp.fractionToPoint(a0)); // Tiny sweep - avoid problem with rangeMethod (not worth doing anyway). } else { const segment = cp.clonePartialCurve(a0, a1); if (segment !== undefined) segment.extendRange(intersectRange, toView); - } }); } @@ -392,7 +434,7 @@ export class BackgroundMapGeometry { clipPlanes.clipConvexPolygonInPlace(scratchCartoRectangle, scratchWorkArray); for (let i = 0; i < scratchCartoRectangle.length; i++) doAccumulate(scratchCartoRectangle.getPoint3dAtUncheckedPointIndex(i)); - while (clipPlanes.planes.length > clipPlaneCount) // Remove pushed silhouette plane. + while (clipPlanes.planes.length > clipPlaneCount) // Remove pushed silhouette plane. clipPlanes.planes.pop(); } } @@ -475,12 +517,15 @@ export async function calculateEcefToDbTransformAtLocation(originIn: Point3d, iM if (geoConverter === undefined) return undefined; - const origin = Point3d.create(originIn.x, originIn.y, 0); // Always Test at zero. + const origin = Point3d.create(originIn.x, originIn.y, 0); // Always Test at zero. const eastPoint = origin.plusXYZ(1, 0, 0); const northPoint = origin.plusXYZ(0, 1, 0); const response = await geoConverter.getGeoCoordinatesFromIModelCoordinates([origin, northPoint, eastPoint]); - if (response.geoCoords[0].s !== GeoCoordStatus.Success || response.geoCoords[1].s !== GeoCoordStatus.Success || response.geoCoords[2].s !== GeoCoordStatus.Success) + if ( + response.geoCoords[0].s !== GeoCoordStatus.Success || response.geoCoords[1].s !== GeoCoordStatus.Success || + response.geoCoords[2].s !== GeoCoordStatus.Success + ) return undefined; const geoOrigin = Point3d.fromJSON(response.geoCoords[0].p); @@ -494,7 +539,7 @@ export async function calculateEcefToDbTransformAtLocation(originIn: Point3d, iM const yVector = Vector3d.createStartEnd(ecefOrigin, ecefNorth); const zVector = xVector.unitCrossProduct(yVector); if (undefined === zVector) { - assert(false); // Should never occur. + assert(false); // Should never occur. return undefined; } const matrix = Matrix3d.createColumns(xVector, yVector, zVector); @@ -503,10 +548,9 @@ export async function calculateEcefToDbTransformAtLocation(originIn: Point3d, iM const inverse = matrix.inverse(); if (inverse === undefined) { - assert(false); // Should never occur. + assert(false); // Should never occur. return undefined; } return Transform.createMatrixPickupPutdown(matrix, origin, ecefOrigin).inverse()!; } - diff --git a/core/frontend/src/BingLocation.ts b/core/frontend/src/BingLocation.ts index 45099912bac1..59d897d85040 100644 --- a/core/frontend/src/BingLocation.ts +++ b/core/frontend/src/BingLocation.ts @@ -7,8 +7,8 @@ */ import { Cartographic } from "@itwin/core-common"; -import { request } from "./request/Request"; import { IModelApp } from "./IModelApp"; +import { request } from "./request/Request"; import { GlobalLocation } from "./ViewGlobalLocation"; /** Provides an interface to the [Bing Maps location services](https://docs.microsoft.com/en-us/bingmaps/rest-services/locations/). diff --git a/core/frontend/src/BriefcaseConnection.ts b/core/frontend/src/BriefcaseConnection.ts index 130546a591e3..15f4b1497212 100644 --- a/core/frontend/src/BriefcaseConnection.ts +++ b/core/frontend/src/BriefcaseConnection.ts @@ -8,8 +8,14 @@ import { assert, BeEvent, CompressedId64Set, Guid, GuidString, Id64String, IModelStatus, OpenMode } from "@itwin/core-bentley"; import { - ChangesetIndex, ChangesetIndexAndId, getPullChangesIpcChannel, IModelConnectionProps, IModelError, - PullChangesOptions as IpcAppPullChangesOptions, OpenBriefcaseProps, StandaloneOpenOptions, + ChangesetIndex, + ChangesetIndexAndId, + getPullChangesIpcChannel, + IModelConnectionProps, + IModelError, + OpenBriefcaseProps, + PullChangesOptions as IpcAppPullChangesOptions, + StandaloneOpenOptions, } from "@itwin/core-common"; import { BriefcaseTxns } from "./BriefcaseTxns"; import { GraphicalEditingScope } from "./GraphicalEditingScope"; @@ -264,13 +270,19 @@ export class BriefcaseConnection extends IModelConnection { public readonly txns: BriefcaseTxns; /** @internal */ - public override isBriefcaseConnection(): this is BriefcaseConnection { return true; } + public override isBriefcaseConnection(): this is BriefcaseConnection { + return true; + } /** The Guid that identifies the iTwin that owns this iModel. */ - public override get iTwinId(): GuidString { return super.iTwinId!; } // GuidString | undefined for IModelConnection, but required for BriefcaseConnection + public override get iTwinId(): GuidString { + return super.iTwinId!; + } // GuidString | undefined for IModelConnection, but required for BriefcaseConnection /** The Guid that identifies this iModel. */ - public override get iModelId(): GuidString { return super.iModelId!; } // GuidString | undefined for IModelConnection, but required for BriefcaseConnection + public override get iModelId(): GuidString { + return super.iModelId!; + } // GuidString | undefined for IModelConnection, but required for BriefcaseConnection protected constructor(props: IModelConnectionProps, openMode: OpenMode) { super(props); @@ -278,7 +290,9 @@ export class BriefcaseConnection extends IModelConnection { this.txns = new BriefcaseTxns(this); this._modelsMonitor = new ModelChangeMonitor(this); if (OpenMode.ReadWrite === this._openMode) - this.txns.onAfterUndoRedo.addListener(async () => { await IModelApp.toolAdmin.restartPrimitiveTool(); }); + this.txns.onAfterUndoRedo.addListener(async () => { + await IModelApp.toolAdmin.restartPrimitiveTool(); + }); } /** Open a BriefcaseConnection to a [BriefcaseDb]($backend). */ @@ -292,7 +306,11 @@ export class BriefcaseConnection extends IModelConnection { /** Open a BriefcaseConnection to a [StandaloneDb]($backend) * @note StandaloneDbs, by definition, may not push or pull changes. Attempting to do so will throw exceptions. */ - public static async openStandalone(filePath: string, openMode: OpenMode = OpenMode.ReadWrite, opts?: StandaloneOpenOptions): Promise { + public static async openStandalone( + filePath: string, + openMode: OpenMode = OpenMode.ReadWrite, + opts?: StandaloneOpenOptions, + ): Promise { const openResponse = await IpcApp.appFunctionIpc.openStandalone(filePath, openMode, opts); const connection = new this(openResponse, openMode); IModelConnection.onOpen.raiseEvent(connection); @@ -300,7 +318,9 @@ export class BriefcaseConnection extends IModelConnection { } /** Returns `true` if [[close]] has already been called. */ - public get isClosed(): boolean { return this._isClosed === true; } + public get isClosed(): boolean { + return this._isClosed === true; + } /** * Close this BriefcaseConnection. diff --git a/core/frontend/src/BriefcaseTxns.ts b/core/frontend/src/BriefcaseTxns.ts index 6c4abbda5c46..1d99da2caf82 100644 --- a/core/frontend/src/BriefcaseTxns.ts +++ b/core/frontend/src/BriefcaseTxns.ts @@ -8,8 +8,18 @@ import { BeEvent } from "@itwin/core-bentley"; import { - ChangesetIndexAndId, EcefLocation, EcefLocationProps, GeographicCRS, GeographicCRSProps, IModelStatus, ipcAppChannels, - ModelIdAndGeometryGuid, NotifyEntitiesChangedArgs, RemoveFunction, RootSubjectProps, TxnNotifications, + ChangesetIndexAndId, + EcefLocation, + EcefLocationProps, + GeographicCRS, + GeographicCRSProps, + IModelStatus, + ipcAppChannels, + ModelIdAndGeometryGuid, + NotifyEntitiesChangedArgs, + RemoveFunction, + RootSubjectProps, + TxnNotifications, } from "@itwin/core-common"; import { Point3d, Range3d, Range3dProps, XYZProps } from "@itwin/core-geometry"; import { BriefcaseConnection } from "./BriefcaseConnection"; @@ -22,9 +32,13 @@ import { EntityChanges, TxnEntityChanges } from "./TxnEntityChanges"; * @public */ export abstract class BriefcaseNotificationHandler extends NotificationHandler { - constructor(private _key: string) { super(); } + constructor(private _key: string) { + super(); + } public abstract get briefcaseChannelName(): string; - public get channelName() { return `${this.briefcaseChannelName}/${this._key}`; } + public get channelName() { + return `${this.briefcaseChannelName}/${this._key}`; + } } /** Manages local changes to a [[BriefcaseConnection]] via [Txns]($docs/learning/InteractiveEditing.md). diff --git a/core/frontend/src/CategorySelectorState.ts b/core/frontend/src/CategorySelectorState.ts index 63725eb13694..2b7bdfb1a40e 100644 --- a/core/frontend/src/CategorySelectorState.ts +++ b/core/frontend/src/CategorySelectorState.ts @@ -21,7 +21,9 @@ import { IModelConnection } from "./IModelConnection"; * @extensions */ export class CategorySelectorState extends ElementState { - public static override get className() { return "CategorySelector"; } + public static override get className() { + return "CategorySelector"; + } private readonly _categories = new ObservableSet(); @@ -68,13 +70,19 @@ export class CategorySelectorState extends ElementState { } /** The name of this CategorySelector */ - public get name(): string { return this.code.value; } + public get name(): string { + return this.code.value; + } /** Determine whether this CategorySelector includes the specified categoryId string */ - public has(id: Id64String): boolean { return this.categories.has(id); } + public has(id: Id64String): boolean { + return this.categories.has(id); + } /** Determine whether this CategorySelector includes the specified category */ - public isCategoryViewed(categoryId: Id64String): boolean { return this.has(categoryId); } + public isCategoryViewed(categoryId: Id64String): boolean { + return this.has(categoryId); + } /** Add one or more categories to this CategorySelector */ public addCategories(arg: Id64Arg): void { diff --git a/core/frontend/src/ChangeFlags.ts b/core/frontend/src/ChangeFlags.ts index 8e008afee989..5a7f397125bd 100644 --- a/core/frontend/src/ChangeFlags.ts +++ b/core/frontend/src/ChangeFlags.ts @@ -56,49 +56,75 @@ export class ChangeFlags { /** The set of always-drawn elements has changed. * @see [[Viewport.setAlwaysDrawn]] and [[Viewport.clearAlwaysDrawn]]. */ - public get alwaysDrawn() { return this.isSet(ChangeFlag.AlwaysDrawn); } + public get alwaysDrawn() { + return this.isSet(ChangeFlag.AlwaysDrawn); + } /** The set of never-drawn elements has changed. * @see [[Viewport.setNeverDrawn]] and [[Viewport.clearNeverDrawn]]. */ - public get neverDrawn() { return this.isSet(ChangeFlag.NeverDrawn); } + public get neverDrawn() { + return this.isSet(ChangeFlag.NeverDrawn); + } /** The set of displayed categories defined by the viewport's [[CategorySelectorState]] has changed. */ - public get viewedCategories() { return this.isSet(ChangeFlag.ViewedCategories); } + public get viewedCategories() { + return this.isSet(ChangeFlag.ViewedCategories); + } /** The set of models to be displayed in the viewport has changed. */ - public get viewedModels() { return this.isSet(ChangeFlag.ViewedModels); } + public get viewedModels() { + return this.isSet(ChangeFlag.ViewedModels); + } /** The [[DisplayStyleState]] or its settings such as [ViewFlags]($common) have changed. */ - public get displayStyle() { return this.isSet(ChangeFlag.DisplayStyle); } + public get displayStyle() { + return this.isSet(ChangeFlag.DisplayStyle); + } /** The [[FeatureOverrideProvider]] has changed, or its internal state has changed such that its overrides must be recomputed. * @see [[Viewport.addFeatureOverrideProvider]] and [[Viewport.setFeatureOverrideProviderChanged]]. */ - public get featureOverrideProvider() { return this.isSet(ChangeFlag.FeatureOverrideProvider); } + public get featureOverrideProvider() { + return this.isSet(ChangeFlag.FeatureOverrideProvider); + } /** [[Vewport.changeView]] was used to replace the previous [[ViewState]] with a new one. */ - public get viewState() { return this.isSet(ChangeFlag.ViewState); } + public get viewState() { + return this.isSet(ChangeFlag.ViewState); + } /** The [[PerModelCategoryVisibility.Overrides]] associated with the viewport have changed. * @beta */ - public get viewedCategoriesPerModel() { return this.isSet(ChangeFlag.ViewedCategoriesPerModel); } + public get viewedCategoriesPerModel() { + return this.isSet(ChangeFlag.ViewedCategoriesPerModel); + } /** Returns true if any of the specified flags are set. */ - public isSet(flags: ChangeFlag): boolean { return 0 !== (this._flags & flags); } + public isSet(flags: ChangeFlag): boolean { + return 0 !== (this._flags & flags); + } /** Returns true if all of the specified flags are set. */ - public areAllSet(flags: ChangeFlag): boolean { return flags === (this._flags & flags); } + public areAllSet(flags: ChangeFlag): boolean { + return flags === (this._flags & flags); + } /** Returns true if any aspects affecting [[FeatureSymbology.Overrides]] have changed. */ - public get areFeatureOverridesDirty() { return this.isSet(ChangeFlag.Overrides); } + public get areFeatureOverridesDirty() { + return this.isSet(ChangeFlag.Overrides); + } /** Returns true if any aspect at all has changed. */ - public get hasChanges() { return this.isSet(ChangeFlag.All); } + public get hasChanges() { + return this.isSet(ChangeFlag.All); + } /** The underlying bitmask indicating the state of each individual flag. */ - public get value(): ChangeFlag { return this._flags; } + public get value(): ChangeFlag { + return this._flags; + } } /** A [[ChangeFlags]] that permits modifying the states of individual [[ChangeFlag]]s. @@ -113,17 +139,37 @@ export class MutableChangeFlags extends ChangeFlags { } /** Set all of the specified flags. */ - private set(flags: ChangeFlag): void { this._flags |= flags; } + private set(flags: ChangeFlag): void { + this._flags |= flags; + } - public setAlwaysDrawn() { this.set(ChangeFlag.AlwaysDrawn); } - public setNeverDrawn() { this.set(ChangeFlag.NeverDrawn); } - public setViewedCategories() { this.set(ChangeFlag.ViewedCategories); } - public setViewedModels() { this.set(ChangeFlag.ViewedModels); } - public setDisplayStyle() { this.set(ChangeFlag.DisplayStyle); } - public setFeatureOverrideProvider() { this.set(ChangeFlag.FeatureOverrideProvider); } - public setViewState() { this.set(ChangeFlag.ViewState); } - public setViewedCategoriesPerModel() { this.set(ChangeFlag.ViewedCategoriesPerModel); } + public setAlwaysDrawn() { + this.set(ChangeFlag.AlwaysDrawn); + } + public setNeverDrawn() { + this.set(ChangeFlag.NeverDrawn); + } + public setViewedCategories() { + this.set(ChangeFlag.ViewedCategories); + } + public setViewedModels() { + this.set(ChangeFlag.ViewedModels); + } + public setDisplayStyle() { + this.set(ChangeFlag.DisplayStyle); + } + public setFeatureOverrideProvider() { + this.set(ChangeFlag.FeatureOverrideProvider); + } + public setViewState() { + this.set(ChangeFlag.ViewState); + } + public setViewedCategoriesPerModel() { + this.set(ChangeFlag.ViewedCategoriesPerModel); + } /** Clear all of the specified flags. By default, clears all flags. */ - public clear(flags: ChangeFlag = ChangeFlag.All): void { this._flags &= ~flags; } + public clear(flags: ChangeFlag = ChangeFlag.All): void { + this._flags &= ~flags; + } } diff --git a/core/frontend/src/CheckpointConnection.ts b/core/frontend/src/CheckpointConnection.ts index 1d431a59b7bf..6fcb6b42ea8e 100644 --- a/core/frontend/src/CheckpointConnection.ts +++ b/core/frontend/src/CheckpointConnection.ts @@ -8,8 +8,16 @@ import { BentleyError, BentleyStatus, GuidString, Logger } from "@itwin/core-bentley"; import { - IModelConnectionProps, IModelError, IModelReadRpcInterface, IModelRpcOpenProps, IModelVersion, RpcManager, RpcNotFoundResponse, RpcOperation, - RpcRequest, RpcRequestEvent, + IModelConnectionProps, + IModelError, + IModelReadRpcInterface, + IModelRpcOpenProps, + IModelVersion, + RpcManager, + RpcNotFoundResponse, + RpcOperation, + RpcRequest, + RpcRequestEvent, } from "@itwin/core-common"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import { IModelApp } from "./IModelApp"; @@ -28,12 +36,18 @@ export class CheckpointConnection extends IModelConnection { private readonly _fromIpc: boolean; /** The Guid that identifies the iTwin that owns this iModel. */ - public override get iTwinId(): GuidString { return super.iTwinId!; } + public override get iTwinId(): GuidString { + return super.iTwinId!; + } /** The Guid that identifies this iModel. */ - public override get iModelId(): GuidString { return super.iModelId!; } + public override get iModelId(): GuidString { + return super.iModelId!; + } /** Returns `true` if [[close]] has already been called. */ - public get isClosed(): boolean { return this._isClosed ? true : false; } + public get isClosed(): boolean { + return this._isClosed ? true : false; + } protected _isClosed?: boolean; protected constructor(props: IModelConnectionProps, fromIpc: boolean) { @@ -42,7 +56,9 @@ export class CheckpointConnection extends IModelConnection { } /** Type guard for instanceof [[CheckpointConnection]] */ - public override isCheckpointConnection(): this is CheckpointConnection { return true; } + public override isCheckpointConnection(): this is CheckpointConnection { + return true; + } /** * Open a readonly IModelConnection to a Checkpoint of an iModel. @@ -94,14 +110,26 @@ export class CheckpointConnection extends IModelConnection { const connectionTimeElapsed = Date.now() - startTime; if (connectionTimeElapsed > IModelConnection.connectionTimeout) { - Logger.logError(loggerCategory, `Timed out opening connection in IModelConnection.open (took longer than ${IModelConnection.connectionTimeout} milliseconds)`, iModelToken); + Logger.logError( + loggerCategory, + `Timed out opening connection in IModelConnection.open (took longer than ${IModelConnection.connectionTimeout} milliseconds)`, + iModelToken, + ); throw new IModelError(BentleyStatus.ERROR, "Opening a connection was timed out"); // NEEDS_WORK: More specific error status } - connectionRetryInterval = Math.min(connectionRetryIntervalRange.max, connectionRetryInterval * 2, IModelConnection.connectionTimeout - connectionTimeElapsed); + connectionRetryInterval = Math.min( + connectionRetryIntervalRange.max, + connectionRetryInterval * 2, + IModelConnection.connectionTimeout - connectionTimeElapsed, + ); if (request.retryInterval !== connectionRetryInterval) { request.retryInterval = connectionRetryInterval; - Logger.logTrace(loggerCategory, `Adjusted open connection retry interval to ${request.retryInterval} milliseconds in IModelConnection.open`, iModelToken); + Logger.logTrace( + loggerCategory, + `Adjusted open connection retry interval to ${request.retryInterval} milliseconds in IModelConnection.open`, + iModelToken, + ); } }); @@ -117,7 +145,12 @@ export class CheckpointConnection extends IModelConnection { return openResponse; } - private _reopenConnectionHandler = async (request: RpcRequest, response: any, resubmit: () => void, reject: (reason?: any) => void) => { + private _reopenConnectionHandler = async ( + request: RpcRequest, + response: any, + resubmit: () => void, + reject: (reason?: any) => void, + ) => { if (!response.hasOwnProperty("isIModelNotFoundResponse")) reject(); @@ -132,7 +165,6 @@ export class CheckpointConnection extends IModelConnection { // The new/reopened connection may have a new rpcKey and/or changesetId, but the other IModelRpcTokenProps should be the same this._fileKey = openResponse.key; this.changeset = openResponse.changeset!; - } catch (error) { reject(BentleyError.getErrorMessage(error)); } finally { diff --git a/core/frontend/src/ContextRealityModelState.ts b/core/frontend/src/ContextRealityModelState.ts index 5cc2b43cad1b..139ca74f9712 100644 --- a/core/frontend/src/ContextRealityModelState.ts +++ b/core/frontend/src/ContextRealityModelState.ts @@ -68,7 +68,9 @@ export class ContextRealityModelState extends ContextRealityModel { } /** The tile tree reference responsible for drawing the reality model into a [[Viewport]]. */ - public get treeRef(): TileTreeReference { return this._treeRef; } + public get treeRef(): TileTreeReference { + return this._treeRef; + } /** The set of available [[ActiveSpatialClassifier]]s that can be used to classify the reality model. */ public override get classifiers(): SpatialClassifiersState { diff --git a/core/frontend/src/DecorationsCache.ts b/core/frontend/src/DecorationsCache.ts index beb23f5802ac..a5ea37d52389 100644 --- a/core/frontend/src/DecorationsCache.ts +++ b/core/frontend/src/DecorationsCache.ts @@ -7,16 +7,16 @@ */ import { assert } from "@itwin/core-bentley"; +import { GraphicType } from "./common/render/GraphicType"; +import { CanvasDecoration } from "./render/CanvasDecoration"; import { RenderGraphicOwner } from "./render/RenderGraphic"; import { ViewportDecorator } from "./Viewport"; -import { CanvasDecoration } from "./render/CanvasDecoration"; -import { GraphicType } from "./common/render/GraphicType"; /** @internal */ export type CachedDecoration = - { type: "graphic", graphicType: GraphicType, graphicOwner: RenderGraphicOwner } | - { type: "canvas", canvasDecoration: CanvasDecoration, atFront: boolean } | - { type: "html", htmlElement: HTMLElement }; + | { type: "graphic", graphicType: GraphicType, graphicOwner: RenderGraphicOwner } + | { type: "canvas", canvasDecoration: CanvasDecoration, atFront: boolean } + | { type: "html", htmlElement: HTMLElement }; function disposeCachedDecorations(decorations: CachedDecoration[]): void { for (const dec of decorations) diff --git a/core/frontend/src/DevTools.ts b/core/frontend/src/DevTools.ts index ce5704a7ec56..d3e5f0e55a4f 100644 --- a/core/frontend/src/DevTools.ts +++ b/core/frontend/src/DevTools.ts @@ -23,7 +23,6 @@ export interface PingTestResult { * @internal */ export class DevTools { - /** Create a new connection with a specific backend instance. * @param tokenProps The iModelToken that identifies that backend instance. * Supply a dummy token if contacting the backend without the Orchestrator. @@ -34,7 +33,8 @@ export class DevTools { /** Constructor */ private constructor( - private readonly _tokenProps: IModelRpcProps) { + private readonly _tokenProps: IModelRpcProps, + ) { } /** Measures the round trip times for one or more pings to the backend diff --git a/core/frontend/src/DisplayStyleState.ts b/core/frontend/src/DisplayStyleState.ts index 1c250ce8f615..dfe8279e45d8 100644 --- a/core/frontend/src/DisplayStyleState.ts +++ b/core/frontend/src/DisplayStyleState.ts @@ -6,14 +6,39 @@ * @module Views */ import { assert, BeEvent, Id64, Id64Arg, Id64String } from "@itwin/core-bentley"; -import { Range1d, Vector3d } from "@itwin/core-geometry"; import { - BackgroundMapProps, BackgroundMapProvider, BackgroundMapProviderProps, BackgroundMapSettings, - BaseLayerSettings, BaseMapLayerSettings, ColorDef, ContextRealityModelProps, DisplayStyle3dSettings, DisplayStyle3dSettingsProps, - DisplayStyleProps, DisplayStyleSettings, Environment, FeatureAppearance, GlobeMode, ImageMapLayerSettings, LightSettings, MapLayerProps, - MapLayerSettings, MapSubLayerProps, RenderSchedule, RenderTimelineProps, - SolarShadowSettings, SubCategoryOverride, SubLayerId, TerrainHeightOriginMode, ThematicDisplay, ThematicDisplayMode, ThematicGradientMode, ViewFlags, + BackgroundMapProps, + BackgroundMapProvider, + BackgroundMapProviderProps, + BackgroundMapSettings, + BaseLayerSettings, + BaseMapLayerSettings, + ColorDef, + ContextRealityModelProps, + DisplayStyle3dSettings, + DisplayStyle3dSettingsProps, + DisplayStyleProps, + DisplayStyleSettings, + Environment, + FeatureAppearance, + GlobeMode, + ImageMapLayerSettings, + LightSettings, + MapLayerProps, + MapLayerSettings, + MapSubLayerProps, + RenderSchedule, + RenderTimelineProps, + SolarShadowSettings, + SubCategoryOverride, + SubLayerId, + TerrainHeightOriginMode, + ThematicDisplay, + ThematicDisplayMode, + ThematicGradientMode, + ViewFlags, } from "@itwin/core-common"; +import { Range1d, Vector3d } from "@itwin/core-geometry"; import { ApproximateTerrainHeights } from "./ApproximateTerrainHeights"; import { BackgroundMapGeometry } from "./BackgroundMapGeometry"; import { ContextRealityModelState } from "./ContextRealityModelState"; @@ -47,7 +72,9 @@ export interface OsmBuildingDisplayOptions { * @extensions */ export abstract class DisplayStyleState extends ElementState implements DisplayStyleProps { - public static override get className() { return "DisplayStyle"; } + public static override get className() { + return "DisplayStyle"; + } private _scriptReference?: RenderSchedule.ScriptReference; private _ellipsoidMapGeometry: BackgroundMapGeometry | undefined; private _attachedRealityModelPlanarClipMasks = new Map(); @@ -84,10 +111,11 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS if (styles) { // ###TODO Use DisplayStyleSettings.planarClipMasks - if (styles.planarClipOvr) + if (styles.planarClipOvr) { for (const planarClipOvr of styles.planarClipOvr) if (Id64.isValid(planarClipOvr.modelId)) this._attachedRealityModelPlanarClipMasks.set(planarClipOvr.modelId, PlanarClipMaskState.fromJSON(planarClipOvr)); + } } } @@ -179,7 +207,9 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } /** @internal */ - public get globeMode(): GlobeMode { return this.settings.backgroundMap.globeMode; } + public get globeMode(): GlobeMode { + return this.settings.backgroundMap.globeMode; + } /** Settings controlling how the base map is displayed within a view. * The base map can be provided by any map imagery source or set to be a single color. @@ -195,7 +225,9 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS /** The settings controlling how a background map is displayed within a view. * @see [[ViewFlags.backgroundMap]] for toggling display of the map on or off. */ - public get backgroundMapSettings(): BackgroundMapSettings { return this.settings.backgroundMap; } + public get backgroundMapSettings(): BackgroundMapSettings { + return this.settings.backgroundMap; + } public set backgroundMapSettings(settings: BackgroundMapSettings) { this.settings.backgroundMap = settings; } @@ -242,7 +274,7 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } } - private * getRealityModels(): Iterable { + private *getRealityModels(): Iterable { for (const model of this.settings.contextRealityModels.models) { assert(model instanceof ContextRealityModelState); yield model; @@ -280,7 +312,9 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } /** The name of this DisplayStyle */ - public get name(): string { return this.code.value; } + public get name(): string { + return this.code.value; + } /** Change the Id of the [RenderTimeline]($backend) element that hosts the [RenderSchedule.Script]($common) to be applied by this display style for * animating the contents of the view, and update [[scheduleScript]] using the script associated with the [RenderTimeline]($backend) element. @@ -354,7 +388,7 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS * @see [[setOSMBuildingDisplay]] */ public getOSMBuildingRealityModel(): ContextRealityModelState | undefined { - if (!this.iModel.isGeoLocated || this.globeMode !== GlobeMode.Ellipsoid) // The OSM tile tree is ellipsoidal. + if (!this.iModel.isGeoLocated || this.globeMode !== GlobeMode.Ellipsoid) // The OSM tile tree is ellipsoidal. return undefined; const url = getCesiumOSMBuildingsUrl(); @@ -369,7 +403,7 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS * The options [[OsmBuildingDisplayOptions]] control the display and appearance overrides. */ public setOSMBuildingDisplay(options: OsmBuildingDisplayOptions): boolean { - if (!this.iModel.isGeoLocated || this.globeMode !== GlobeMode.Ellipsoid) // The OSM tile tree is ellipsoidal. + if (!this.iModel.isGeoLocated || this.globeMode !== GlobeMode.Ellipsoid) // The OSM tile tree is ellipsoidal. return false; const url = getCesiumOSMBuildingsUrl(); @@ -405,7 +439,9 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } /** @internal */ - public getMapLayers(isOverlay: boolean) { return isOverlay ? this.settings.mapImagery.overlayLayers : this.settings.mapImagery.backgroundLayers; } + public getMapLayers(isOverlay: boolean) { + return isOverlay ? this.settings.mapImagery.overlayLayers : this.settings.mapImagery.backgroundLayers; + } /** Attach a map layer to display style. * @param Settings representing the map layer. @@ -450,7 +486,7 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS /** @internal */ public detachMapLayerByNameAndSource(name: string, source: string, isOverlay: boolean): void { const index = this.findMapLayerIndexByNameAndSource(name, source, isOverlay); - if (- 1 !== index) + if (-1 !== index) this.detachMapLayerByIndex({ index, isOverlay }); } @@ -475,7 +511,6 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS * @param source Unique string identifying the layer. * @param isOverlay true if layer is overlay, otherwise layer is background. Defaults to false. * @public - * */ public findMapLayerIndexByNameAndSource(name: string, source: string, isOverlay: boolean) { return this.getMapLayers(isOverlay).findIndex((layer) => layer.matchesNameAndSource(name, source)); @@ -578,7 +613,6 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS /** Move map layer to top. * @param mapLayerIndex the [[MapLayerIndex]] of the map layer to move. * @public - * */ public moveMapLayerToTop(mapLayerIndex: MapLayerIndex) { const layers = this.getMapLayers(mapLayerIndex.isOverlay); @@ -626,18 +660,30 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS /** Flags controlling various aspects of the display style. * @see [DisplayStyleSettings.viewFlags]($common) */ - public get viewFlags(): ViewFlags { return this.settings.viewFlags; } - public set viewFlags(flags: ViewFlags) { this.settings.viewFlags = flags; } + public get viewFlags(): ViewFlags { + return this.settings.viewFlags; + } + public set viewFlags(flags: ViewFlags) { + this.settings.viewFlags = flags; + } /** The background color for this DisplayStyle */ - public get backgroundColor(): ColorDef { return this.settings.backgroundColor; } - public set backgroundColor(val: ColorDef) { this.settings.backgroundColor = val; } + public get backgroundColor(): ColorDef { + return this.settings.backgroundColor; + } + public set backgroundColor(val: ColorDef) { + this.settings.backgroundColor = val; + } /** The color used to draw geometry in monochrome mode. * @see [ViewFlags.monochrome]($common) for enabling monochrome mode. */ - public get monochromeColor(): ColorDef { return this.settings.monochromeColor; } - public set monochromeColor(val: ColorDef) { this.settings.monochromeColor = val; } + public get monochromeColor(): ColorDef { + return this.settings.monochromeColor; + } + public set monochromeColor(val: ColorDef) { + this.settings.monochromeColor = val; + } private _backgroundMapGeometry?: { bimElevationBias: number; @@ -666,7 +712,9 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS const terrainSettings = this.backgroundMapSettings.terrainSettings; switch (terrainSettings.heightOriginMode) { case TerrainHeightOriginMode.Ground: - return (undefined === this.iModel.projectCenterAltitude) ? undefined : terrainSettings.heightOrigin + terrainSettings.exaggeration * this.iModel.projectCenterAltitude; + return (undefined === this.iModel.projectCenterAltitude) + ? undefined + : terrainSettings.heightOrigin + terrainSettings.exaggeration * this.iModel.projectCenterAltitude; case TerrainHeightOriginMode.Geodetic: return terrainSettings.heightOrigin; @@ -677,7 +725,6 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } else { return this.backgroundMapSettings.groundBias; } - } /** @internal */ @@ -691,7 +738,10 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS return undefined; const globeMode = this.globeMode; - if (undefined === this._backgroundMapGeometry || this._backgroundMapGeometry.globeMode !== globeMode || this._backgroundMapGeometry.bimElevationBias !== bimElevationBias) { + if ( + undefined === this._backgroundMapGeometry || this._backgroundMapGeometry.globeMode !== globeMode || + this._backgroundMapGeometry.bimElevationBias !== bimElevationBias + ) { const geometry = new BackgroundMapGeometry(bimElevationBias, globeMode, this.iModel); this._backgroundMapGeometry = { bimElevationBias, geometry, globeMode }; } @@ -725,30 +775,40 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS } /** Returns true if this is a 3d display style. */ - public is3d(): this is DisplayStyle3dState { return this instanceof DisplayStyle3dState; } + public is3d(): this is DisplayStyle3dState { + return this instanceof DisplayStyle3dState; + } /** Customize the way geometry belonging to a [[SubCategory]] is drawn by this display style. * @param id The ID of the SubCategory whose appearance is to be overridden. * @param ovr The overrides to apply to the [[SubCategoryAppearance]]. * @see [[dropSubCategoryOverride]] */ - public overrideSubCategory(id: Id64String, ovr: SubCategoryOverride) { this.settings.overrideSubCategory(id, ovr); } + public overrideSubCategory(id: Id64String, ovr: SubCategoryOverride) { + this.settings.overrideSubCategory(id, ovr); + } /** Remove any [[SubCategoryOverride]] applied to a [[SubCategoryAppearance]] by this style. * @param id The ID of the [[SubCategory]]. * @see [[overrideSubCategory]] */ - public dropSubCategoryOverride(id: Id64String) { this.settings.dropSubCategoryOverride(id); } + public dropSubCategoryOverride(id: Id64String) { + this.settings.dropSubCategoryOverride(id); + } /** Returns true if an [[SubCategoryOverride]]s are defined by this style. */ - public get hasSubCategoryOverride() { return this.settings.hasSubCategoryOverride; } + public get hasSubCategoryOverride() { + return this.settings.hasSubCategoryOverride; + } /** Obtain the overrides applied to a [[SubCategoryAppearance]] by this style. * @param id The ID of the [[SubCategory]]. * @returns The corresponding SubCategoryOverride, or undefined if the SubCategory's appearance is not overridden. * @see [[overrideSubCategory]] */ - public getSubCategoryOverride(id: Id64String): SubCategoryOverride | undefined { return this.settings.getSubCategoryOverride(id); } + public getSubCategoryOverride(id: Id64String): SubCategoryOverride | undefined { + return this.settings.getSubCategoryOverride(id); + } /** For each subcategory belonging to any of the specified categories, make it visible by turning off the "invisible" flag in its subcategory appearance. * This requires that the categories and subcategories have been previously loaded by, e.g., a call to IModelConnection.querySubCategories. @@ -761,10 +821,11 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS let anyChanged = false; for (const categoryId of Id64.iterable(categoryIds)) { const subCategoryIds = this.iModel.subcategories.getSubCategories(categoryId); - if (undefined !== subCategoryIds) + if (undefined !== subCategoryIds) { for (const subCategoryId of subCategoryIds) if (this.setSubCategoryVisible(subCategoryId, true)) anyChanged = true; + } } return anyChanged; @@ -848,13 +909,19 @@ export abstract class DisplayStyleState extends ElementState implements DisplayS * @extensions */ export class DisplayStyle2dState extends DisplayStyleState { - public static override get className() { return "DisplayStyle2d"; } + public static override get className() { + return "DisplayStyle2d"; + } private readonly _settings: DisplayStyleSettings; - public get settings(): DisplayStyleSettings { return this._settings; } + public get settings(): DisplayStyleSettings { + return this._settings; + } /** @internal */ - public overrideTerrainDisplay(): TerrainDisplayOverrides | undefined { return undefined; } + public overrideTerrainDisplay(): TerrainDisplayOverrides | undefined { + return undefined; + } constructor(props: DisplayStyleProps, iModel: IModelConnection) { super(props, iModel); @@ -873,10 +940,14 @@ export class DisplayStyle2dState extends DisplayStyleState { * @extensions */ export class DisplayStyle3dState extends DisplayStyleState { - public static override get className() { return "DisplayStyle3d"; } + public static override get className() { + return "DisplayStyle3d"; + } private _settings: DisplayStyle3dSettings; - public get settings(): DisplayStyle3dSettings { return this._settings; } + public get settings(): DisplayStyle3dSettings { + return this._settings; + } public constructor(props: DisplayStyleProps, iModel: IModelConnection, source?: DisplayStyle3dState) { super(props, iModel, source); @@ -896,8 +967,12 @@ export class DisplayStyle3dState extends DisplayStyleState { this.settings.environment = env; } - public get lights(): LightSettings { return this.settings.lights; } - public set lights(lights: LightSettings) { this.settings.lights = lights; } + public get lights(): LightSettings { + return this.settings.lights; + } + public set lights(lights: LightSettings) { + this.settings.lights = lights; + } /** The direction of the solar light. */ public get sunDirection(): Readonly { @@ -943,7 +1018,10 @@ export class DisplayStyle3dState extends DisplayStyleState { const ovr = new TerrainDisplayOverrides(); if (this.viewFlags.thematicDisplay && ThematicGradientMode.IsoLines === this.settings.thematic.gradientSettings.mode) ovr.wantSkirts = false; - if (this.viewFlags.thematicDisplay && (ThematicDisplayMode.Slope === this.settings.thematic.displayMode || ThematicDisplayMode.HillShade === this.settings.thematic.displayMode)) + if ( + this.viewFlags.thematicDisplay && + (ThematicDisplayMode.Slope === this.settings.thematic.displayMode || ThematicDisplayMode.HillShade === this.settings.thematic.displayMode) + ) ovr.wantNormals = true; return ovr; } diff --git a/core/frontend/src/DrawingViewState.ts b/core/frontend/src/DrawingViewState.ts index baf03ebfa8f1..8ef6ff1efe2a 100644 --- a/core/frontend/src/DrawingViewState.ts +++ b/core/frontend/src/DrawingViewState.ts @@ -8,10 +8,19 @@ import { assert, dispose, Id64, Id64String } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, Frustum, HydrateViewStateRequestProps, HydrateViewStateResponseProps, QueryRowFormat, SectionDrawingViewProps, ViewDefinition2dProps, ViewFlagOverrides, ViewStateProps, + AxisAlignedBox3d, + Frustum, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + QueryRowFormat, + SectionDrawingViewProps, + ViewDefinition2dProps, + ViewFlagOverrides, + ViewStateProps, } from "@itwin/core-common"; import { Constant, Range3d, Transform, TransformProps, Vector3d } from "@itwin/core-geometry"; import { CategorySelectorState } from "./CategorySelectorState"; +import { ViewRect } from "./common/ViewRect"; import { CoordSystem } from "./CoordSystem"; import { DisplayStyle2dState } from "./DisplayStyleState"; import { Frustum2d } from "./Frustum2d"; @@ -25,7 +34,6 @@ import { Scene } from "./render/Scene"; import { DisclosedTileTreeSet, TileGraphicType } from "./tile/internal"; import { SceneContext } from "./ViewContext"; import { OffScreenViewport } from "./Viewport"; -import { ViewRect } from "./common/ViewRect"; import { AttachToViewportArgs, ExtentLimits, ViewState2d, ViewState3d } from "./ViewState"; /** Strictly for testing. @@ -45,7 +53,9 @@ class SectionAttachmentInfo { private readonly _drawingToSpatialTransform: Transform; private readonly _displaySpatialView: boolean; - public get spatialView(): Id64String | ViewState3d { return this._spatialView; } + public get spatialView(): Id64String | ViewState3d { + return this._spatialView; + } public get wantDisplayed(): boolean { return this._displaySpatialView || DrawingViewState.alwaysDisplaySpatialView; } @@ -308,7 +318,9 @@ class SectionAttachment { * @extensions */ export class DrawingViewState extends ViewState2d { - public static override get className() { return "DrawingViewDefinition"; } + public static override get className() { + return "DrawingViewDefinition"; + } /** Exposed strictly for testing and debugging. Indicates that when loading the view, the spatial view should be displayed even * if `SectionDrawing.displaySpatialView` is not `true`. @@ -345,7 +357,14 @@ export class DrawingViewState extends ViewState2d { return this._attachmentInfo; } - public constructor(props: ViewDefinition2dProps, iModel: IModelConnection, categories: CategorySelectorState, displayStyle: DisplayStyle2dState, extents: AxisAlignedBox3d, sectionDrawing?: SectionDrawingViewProps) { + public constructor( + props: ViewDefinition2dProps, + iModel: IModelConnection, + categories: CategorySelectorState, + displayStyle: DisplayStyle2dState, + extents: AxisAlignedBox3d, + sectionDrawing?: SectionDrawingViewProps, + ) { super(props, iModel, categories, displayStyle); if (categories instanceof DrawingViewState) { this._viewedExtents = categories._viewedExtents.clone(); @@ -457,7 +476,9 @@ export class DrawingViewState extends ViewState2d { } /** @internal */ - public override isDrawingView(): this is DrawingViewState { return true; } + public override isDrawingView(): this is DrawingViewState { + return true; + } /** See [[ViewState.getOrigin]]. */ public override getOrigin() { diff --git a/core/frontend/src/ElementLocateManager.ts b/core/frontend/src/ElementLocateManager.ts index 82c4591fa918..a2e9d30b45c2 100644 --- a/core/frontend/src/ElementLocateManager.ts +++ b/core/frontend/src/ElementLocateManager.ts @@ -8,12 +8,12 @@ import { Id64, Id64String } from "@itwin/core-bentley"; import { Point2d, Point3d } from "@itwin/core-geometry"; +import { ViewRect } from "./common/ViewRect"; import { HitDetail, HitList, HitSource } from "./HitDetail"; import { IModelApp } from "./IModelApp"; import { Pixel } from "./render/Pixel"; import { InputSource, InteractiveTool } from "./tools/Tool"; import { ScreenViewport, Viewport } from "./Viewport"; -import { ViewRect } from "./common/ViewRect"; /** The possible actions for which a locate filter can be called. * @public @@ -158,10 +158,14 @@ export class ElementPicker { return list; } - public getNextHit(): HitDetail | undefined { return this.hitList ? this.hitList.getNextHit() : undefined; } + public getNextHit(): HitDetail | undefined { + return this.hitList ? this.hitList.getNextHit() : undefined; + } /** Return a hit from the list of hits created the last time pickElements was called. */ - public getHit(i: number): HitDetail | undefined { return this.hitList ? this.hitList.getHit(i) : undefined; } + public getHit(i: number): HitDetail | undefined { + return this.hitList ? this.hitList.getHit(i) : undefined; + } public resetCurrentHit(): void { if (this.hitList) @@ -195,7 +199,13 @@ export class ElementPicker { * @param excludedElements Optional ids to not draw during pick. Allows hits for geometry obscured by these ids to be returned. * @returns The number of hits in the hitList of this object. */ - public doPick(vp: ScreenViewport, pickPointWorld: Point3d, pickRadiusView: number, options: LocateOptions, excludedElements?: Iterable): number { + public doPick( + vp: ScreenViewport, + pickPointWorld: Point3d, + pickRadiusView: number, + options: LocateOptions, + excludedElements?: Iterable, + ): number { if (this.hitList && this.hitList.length > 0 && vp === this.viewport && pickPointWorld.isAlmostEqual(this.pickPointWorld)) { this.hitList.resetCurrentHit(); return this.hitList.length; @@ -208,7 +218,12 @@ export class ElementPicker { const pickPointView = vp.worldToView(pickPointWorld); const testPointView = new Point2d(Math.floor(pickPointView.x + 0.5), Math.floor(pickPointView.y + 0.5)); let pixelRadius = Math.floor(pickRadiusView + 0.5); - const rect = new ViewRect(testPointView.x - pixelRadius, testPointView.y - pixelRadius, testPointView.x + pixelRadius, testPointView.y + pixelRadius); + const rect = new ViewRect( + testPointView.x - pixelRadius, + testPointView.y - pixelRadius, + testPointView.x + pixelRadius, + testPointView.y + pixelRadius, + ); if (rect.isNull) return 0; const receiver = (pixels: Pixel.Buffer | undefined) => { @@ -307,15 +322,29 @@ export class ElementLocateManager { public readonly picker = new ElementPicker(); /** get the full message key for a locate failure */ - public static getFailureMessageKey(key: string) { return `LocateFailure.${key}`; } - public onInitialized() { } - public get apertureInches() { return 0.11; } - public get touchApertureInches() { return 0.22; } + public static getFailureMessageKey(key: string) { + return `LocateFailure.${key}`; + } + public onInitialized() {} + public get apertureInches() { + return 0.11; + } + public get touchApertureInches() { + return 0.22; + } - public clear(): void { this.setCurrHit(undefined); } - public setHitList(list?: HitList) { this.hitList = list; } - public setCurrHit(hit?: HitDetail): void { this.currHit = hit; } - public getNextHit(): HitDetail | undefined { return this.hitList ? this.hitList.getNextHit() : undefined; } + public clear(): void { + this.setCurrHit(undefined); + } + public setHitList(list?: HitList) { + this.hitList = list; + } + public setCurrHit(hit?: HitDetail): void { + this.currHit = hit; + } + public getNextHit(): HitDetail | undefined { + return this.hitList ? this.hitList.getNextHit() : undefined; + } /** return the current path from either the snapping logic or the pre-locating systems. */ public getPreLocatedHit(): HitDetail | undefined { @@ -324,11 +353,11 @@ export class ElementLocateManager { const preLocated = fromAccuSnap ?? IModelApp.tentativePoint.getHitAndList(this); if (preLocated) { - const excludedElements = (preLocated.isElementHit ? new Set([preLocated.sourceId]) : undefined); + const excludedElements = preLocated.isElementHit ? new Set([preLocated.sourceId]) : undefined; if (excludedElements || !fromAccuSnap) { // NOTE: For tentative snap, get new hit list at snap point; want reset to cycle hits using adjusted point location... - const point = (fromAccuSnap ? preLocated.hitPoint : preLocated.getPoint()); + const point = fromAccuSnap ? preLocated.hitPoint : preLocated.getPoint(); const vp = preLocated.viewport; this.picker.empty(); @@ -386,7 +415,9 @@ export class ElementLocateManager { return status; } - public initLocateOptions() { this.options.init(); } + public initLocateOptions() { + this.options.init(); + } public initToolLocate() { this.initLocateOptions(); this.clear(); @@ -394,7 +425,14 @@ export class ElementLocateManager { IModelApp.tentativePoint.clear(true); } - private async _doLocate(response: LocateResponse, newSearch: boolean, testPoint: Point3d, vp: ScreenViewport | undefined, source: InputSource, filterHits: boolean): Promise { + private async _doLocate( + response: LocateResponse, + newSearch: boolean, + testPoint: Point3d, + vp: ScreenViewport | undefined, + source: InputSource, + filterHits: boolean, + ): Promise { if (!vp) return; @@ -411,7 +449,12 @@ export class ElementLocateManager { } this.picker.empty(); - this.picker.doPick(vp, testPoint, (vp.pixelsFromInches(InputSource.Touch === source ? this.touchApertureInches : this.apertureInches) / 2.0) + 1.5, this.options); + this.picker.doPick( + vp, + testPoint, + (vp.pixelsFromInches(InputSource.Touch === source ? this.touchApertureInches : this.apertureInches) / 2.0) + 1.5, + this.options, + ); const hitList = this.picker.getHitList(true); this.setHitList(hitList); @@ -427,7 +470,14 @@ export class ElementLocateManager { return undefined; } - public async doLocate(response: LocateResponse, newSearch: boolean, testPoint: Point3d, view: ScreenViewport | undefined, source: InputSource, filterHits = true): Promise { + public async doLocate( + response: LocateResponse, + newSearch: boolean, + testPoint: Point3d, + view: ScreenViewport | undefined, + source: InputSource, + filterHits = true, + ): Promise { response.reason = ElementLocateManager.getFailureMessageKey("NoElements"); response.explanation = ""; diff --git a/core/frontend/src/EmphasizeElements.ts b/core/frontend/src/EmphasizeElements.ts index f9d65d86aab6..79b533dcb581 100644 --- a/core/frontend/src/EmphasizeElements.ts +++ b/core/frontend/src/EmphasizeElements.ts @@ -8,8 +8,8 @@ import { Id64, Id64Arg, Id64Set } from "@itwin/core-bentley"; import { AppearanceOverrideProps, ColorDef, EmphasizeElementsProps, FeatureAppearance, FeatureOverrideType, RgbColor } from "@itwin/core-common"; -import { FeatureSymbology } from "./render/FeatureSymbology"; import { FeatureOverrideProvider } from "./FeatureOverrideProvider"; +import { FeatureSymbology } from "./render/FeatureSymbology"; import { Viewport } from "./Viewport"; /** An implementation of [[FeatureOverrideProvider]] for emphasizing selected elements through simple color/transparency appearance overrides. @@ -129,8 +129,12 @@ export class EmphasizeElements implements FeatureOverrideProvider { * without also calling overrideElements, an explicit refresh must be requested for the change to take effect. * @see [[Viewport.setFeatureOverrideProviderChanged]] */ - public get defaultAppearance(): FeatureAppearance | undefined { return this._defaultAppearance; } - public set defaultAppearance(appearance: FeatureAppearance | undefined) { this._defaultAppearance = appearance; } + public get defaultAppearance(): FeatureAppearance | undefined { + return this._defaultAppearance; + } + public set defaultAppearance(appearance: FeatureAppearance | undefined) { + this._defaultAppearance = appearance; + } /** Establish a default appearance to apply to elements that are not animated by the view's [RenderSchedule.Script]($common). * @note If this is the only change made to EmphasizeElements, you must call [[Viewport.setFeatureOverrideProviderChanged]] for @@ -175,12 +179,16 @@ export class EmphasizeElements implements FeatureOverrideProvider { /** Get the IDs of the currently emphasized isolated elements. */ public getEmphasizedIsolatedElements(): Id64Set | undefined { - return (undefined !== this._defaultAppearance && undefined !== this._emphasizeIsolated && 0 !== this._emphasizeIsolated.size ? this._emphasizeIsolated : undefined); + return (undefined !== this._defaultAppearance && undefined !== this._emphasizeIsolated && 0 !== this._emphasizeIsolated.size + ? this._emphasizeIsolated + : undefined); } /** Get the IDs of the currently emphasized elements. */ public getEmphasizedElements(vp: Viewport): Id64Set | undefined { - return (undefined !== this.getEmphasizedIsolatedElements() ? this._emphasizeIsolated : (undefined !== this._defaultAppearance && !vp.isAlwaysDrawnExclusive ? this.getAlwaysDrawnElements(vp) : undefined)); + return (undefined !== this.getEmphasizedIsolatedElements() + ? this._emphasizeIsolated + : (undefined !== this._defaultAppearance && !vp.isAlwaysDrawnExclusive ? this.getAlwaysDrawnElements(vp) : undefined)); } /** Get the map of current elements with color/transparency overrides. */ @@ -313,10 +321,11 @@ export class EmphasizeElements implements FeatureOverrideProvider { if (0 === newIds.size) return undefined; - const oldSize = (!replace && undefined !== existingIds ? existingIds.size : 0); - if (0 !== oldSize && undefined !== existingIds) + const oldSize = !replace && undefined !== existingIds ? existingIds.size : 0; + if (0 !== oldSize && undefined !== existingIds) { for (const id of existingIds) newIds.add(id); + } if (oldSize === newIds.size) return undefined; @@ -394,7 +403,7 @@ export class EmphasizeElements implements FeatureOverrideProvider { * @see [[Viewport.isAlwaysDrawnExclusive]] */ public isolateElements(ids: Id64Arg, vp: Viewport, replace: boolean = true): boolean { - const wasEmphasized = (undefined !== this.getEmphasizedElements(vp)); + const wasEmphasized = undefined !== this.getEmphasizedElements(vp); if (!this.setAlwaysDrawnElements(ids, vp, true, replace)) return false; @@ -445,7 +454,7 @@ export class EmphasizeElements implements FeatureOverrideProvider { this._emphasizeIsolated = undefined; } - this._defaultAppearance = (undefined === defaultAppearance ? this.createDefaultAppearance() : defaultAppearance); + this._defaultAppearance = undefined === defaultAppearance ? this.createDefaultAppearance() : defaultAppearance; return true; } @@ -458,7 +467,12 @@ export class EmphasizeElements implements FeatureOverrideProvider { * @see [[Viewport.alwaysDrawn]] * @see [[Viewport.isAlwaysDrawnExclusive]] */ - public emphasizeSelectedElements(vp: Viewport, defaultAppearance?: FeatureAppearance, replace: boolean = true, clearSelection: boolean = true): boolean { + public emphasizeSelectedElements( + vp: Viewport, + defaultAppearance?: FeatureAppearance, + replace: boolean = true, + clearSelection: boolean = true, + ): boolean { const selection = vp.view.iModel.selectionSet; if (!selection.isActive || !this.emphasizeElements(selection.elements, vp, defaultAppearance, replace)) return false; @@ -478,7 +492,13 @@ export class EmphasizeElements implements FeatureOverrideProvider { * @return true if overrides were changed. * @see [[Viewport.addFeatureOverrideProvider]] */ - public overrideElements(ids: Id64Arg, vp: Viewport, color: ColorDef, override: FeatureOverrideType = FeatureOverrideType.ColorOnly, replace: boolean = false): boolean { + public overrideElements( + ids: Id64Arg, + vp: Viewport, + color: ColorDef, + override: FeatureOverrideType = FeatureOverrideType.ColorOnly, + replace: boolean = false, + ): boolean { const ovrKey = this.createOverrideKey(color, override); if (undefined === ovrKey) return false; @@ -490,11 +510,12 @@ export class EmphasizeElements implements FeatureOverrideProvider { if (0 === overrideIds.size) return false; - const existingIds = (!replace ? this.getOverriddenElementsByKey(ovrKey) : undefined); - const oldSize = (undefined !== existingIds ? existingIds.size : 0); - if (0 !== oldSize && undefined !== existingIds) + const existingIds = !replace ? this.getOverriddenElementsByKey(ovrKey) : undefined; + const oldSize = undefined !== existingIds ? existingIds.size : 0; + if (0 !== oldSize && undefined !== existingIds) { for (const id of existingIds) overrideIds.add(id); + } if (oldSize === overrideIds.size) return false; @@ -531,7 +552,13 @@ export class EmphasizeElements implements FeatureOverrideProvider { * @return true if overrides were changed. * @see [[Viewport.addFeatureOverrideProvider]] */ - public overrideSelectedElements(vp: Viewport, color: ColorDef, override: FeatureOverrideType = FeatureOverrideType.ColorOnly, replace: boolean = false, clearSelection: boolean = true): boolean { + public overrideSelectedElements( + vp: Viewport, + color: ColorDef, + override: FeatureOverrideType = FeatureOverrideType.ColorOnly, + replace: boolean = false, + clearSelection: boolean = true, + ): boolean { const selection = vp.view.iModel.selectionSet; if (!selection.isActive || !this.overrideElements(selection.elements, vp, color, override, replace)) return false; @@ -541,7 +568,10 @@ export class EmphasizeElements implements FeatureOverrideProvider { } /** @return true if provider is currently overriding the display of any elements. */ - public isActive(vp: Viewport): boolean { return (undefined !== this.getNeverDrawnElements(vp) || undefined !== this.getAlwaysDrawnElements(vp) || undefined !== this.getOverriddenElements()); } + public isActive(vp: Viewport): boolean { + return (undefined !== this.getNeverDrawnElements(vp) || undefined !== this.getAlwaysDrawnElements(vp) || + undefined !== this.getOverriddenElements()); + } /** Serialize to JSON representation. * @see [[EmphasizeElements.fromJSON]] @@ -595,7 +625,10 @@ export class EmphasizeElements implements FeatureOverrideProvider { if (undefined !== props.neverDrawn && this.setNeverDrawnElements(new Set(props.neverDrawn), vp, true)) changed = true; - if (undefined !== props.alwaysDrawn && this.setAlwaysDrawnElements(new Set(props.alwaysDrawn), vp, undefined !== props.isAlwaysDrawnExclusive && props.isAlwaysDrawnExclusive)) + if ( + undefined !== props.alwaysDrawn && + this.setAlwaysDrawnElements(new Set(props.alwaysDrawn), vp, undefined !== props.isAlwaysDrawnExclusive && props.isAlwaysDrawnExclusive) + ) changed = true; if (undefined !== props.alwaysDrawnExclusiveEmphasized) diff --git a/core/frontend/src/EntityState.ts b/core/frontend/src/EntityState.ts index eee2fe8b7036..c606707ddcd0 100644 --- a/core/frontend/src/EntityState.ts +++ b/core/frontend/src/EntityState.ts @@ -18,19 +18,27 @@ export class EntityState implements EntityProps { /** The name of the BIS schema for this class. * @note Subclasses from other than the BisCore domain must override the static member "schemaName" with their schema name. */ - public static get schemaName() { return "BisCore"; } + public static get schemaName() { + return "BisCore"; + } - private get _ctor(): typeof EntityState { return this.constructor as typeof EntityState; } + private get _ctor(): typeof EntityState { + return this.constructor as typeof EntityState; + } /** The name of the BIS class associated with this class. * @note Every subclass of EntityState **MUST** override this method to identify its BIS class. * Failure to do so will ordinarily result in an error when the class is registered, since there may only * be one JavaScript class for a given BIS class (usually the errant class will collide with its superclass.) */ - public static get className() { return "Entity"; } + public static get className() { + return "Entity"; + } /** The name of the BIS class associated with this class. */ - public get className(): string { return this._ctor.className; } + public get className(): string { + return this._ctor.className; + } /** The Id of this Entity. May be invalid if the Entity has not yet been saved in the database. */ public readonly id: Id64String; @@ -65,13 +73,19 @@ export class EntityState implements EntityProps { } /** Return true if this EntityState is equal to another one. */ - public equals(other: this): boolean { return JSON.stringify(this.toJSON()) === JSON.stringify(other.toJSON()); } + public equals(other: this): boolean { + return JSON.stringify(this.toJSON()) === JSON.stringify(other.toJSON()); + } /** Make an independent copy of this EntityState */ - public clone(iModel?: IModelConnection): this { return new this._ctor(this.toJSON(), iModel ? iModel : this.iModel, this) as this; } + public clone(iModel?: IModelConnection): this { + return new this._ctor(this.toJSON(), iModel ? iModel : this.iModel, this) as this; + } /** Get full BIS class name of this Entity in the form "SchemaName:ClassName". */ - public static get classFullName(): string { return `${this.schemaName}:${this.className}`; } + public static get classFullName(): string { + return `${this.schemaName}:${this.className}`; + } } /** The "state" of an Element as represented in a web browser. @@ -79,7 +93,9 @@ export class EntityState implements EntityProps { * @extensions */ export class ElementState extends EntityState implements ElementProps { - public static override get className() { return "Element"; } + public static override get className() { + return "Element"; + } /** The ModelId of the [Model]($docs/bis/guide/fundamentals/model-fundamentals.md) containing this element */ public readonly model: Id64String; diff --git a/core/frontend/src/EnvironmentDecorations.ts b/core/frontend/src/EnvironmentDecorations.ts index 86bda98685d5..ee0262d421e5 100644 --- a/core/frontend/src/EnvironmentDecorations.ts +++ b/core/frontend/src/EnvironmentDecorations.ts @@ -8,16 +8,24 @@ import { assert, Id64 } from "@itwin/core-bentley"; import { - ColorDef, Environment, Gradient, GraphicParams, RenderTexture, SkyCube, SkySphere, TextureImageSpec, TextureMapping, + ColorDef, + Environment, + Gradient, + GraphicParams, + RenderTexture, + SkyCube, + SkySphere, + TextureImageSpec, + TextureMapping, } from "@itwin/core-common"; import { Point2d, Point3d, PolyfaceBuilder, StrokeOptions } from "@itwin/core-geometry"; import { tryImageElementFromUrl } from "./common/ImageUtil"; +import { GraphicType } from "./common/render/GraphicType"; import { IModelApp } from "./IModelApp"; import { RenderGraphic } from "./render/RenderGraphic"; import { RenderSkyBoxParams } from "./render/RenderSystem"; import { DecorateContext } from "./ViewContext"; import { ViewState3d } from "./ViewState"; -import { GraphicType } from "./common/render/GraphicType"; /** @internal */ export interface GroundPlaneDecorations { @@ -143,7 +151,10 @@ export class EnvironmentDecorations { const gradient = new Gradient.Symb(); gradient.mode = Gradient.Mode.Spherical; - gradient.keys = [{ color: groundColors[0], value: values[0] }, { color: groundColors[1], value: values[1] }, { color: groundColors[2], value: values[2] }]; + gradient.keys = [{ color: groundColors[0], value: values[0] }, { color: groundColors[1], value: values[1] }, { + color: groundColors[2], + value: values[2], + }]; const texture = IModelApp.renderSystem.getGradientTexture(gradient, this._view.iModel); if (!texture) return undefined; @@ -163,7 +174,7 @@ export class EnvironmentDecorations { // Create GraphicParams using the material. const params = new GraphicParams(); params.lineColor = gradient.keys[0].color; - params.fillColor = ColorDef.white; // Fill should be set to opaque white for gradient texture... + params.fillColor = ColorDef.white; // Fill should be set to opaque white for gradient texture... params.material = material; return params; @@ -194,7 +205,7 @@ export class EnvironmentDecorations { } private loadSkyBoxParams(): SkyBoxParamsLoader { - let load: (() => RenderSkyBoxParams | undefined); + let load: () => RenderSkyBoxParams | undefined; let preload: Promise | undefined; const sky = this._environment.sky; @@ -226,22 +237,38 @@ export class EnvironmentDecorations { // eslint-disable-next-line deprecation/deprecation const params = new RenderTexture.Params(key, RenderTexture.Type.SkyBox); const txImgs = [ - idToImage.get(sky.images.front)!, idToImage.get(sky.images.back)!, idToImage.get(sky.images.top)!, - idToImage.get(sky.images.bottom)!, idToImage.get(sky.images.right)!, idToImage.get(sky.images.left)!, + idToImage.get(sky.images.front)!, + idToImage.get(sky.images.back)!, + idToImage.get(sky.images.top)!, + idToImage.get(sky.images.bottom)!, + idToImage.get(sky.images.right)!, + idToImage.get(sky.images.left)!, ]; - return undefined !== IModelApp.renderSystem.createTextureFromCubeImages(txImgs[0], txImgs[1], txImgs[2], txImgs[3], txImgs[4], txImgs[5], this._view.iModel, params); + return undefined !== + IModelApp.renderSystem.createTextureFromCubeImages( + txImgs[0], + txImgs[1], + txImgs[2], + txImgs[3], + txImgs[4], + txImgs[5], + this._view.iModel, + params, + ); }); } } else if (sky instanceof SkySphere) { load = () => { const texture = IModelApp.renderSystem.findTexture(sky.image, this._view.iModel); - return texture ? { - type: "sphere", - texture, - rotation: 0, - zOffset: this._view.iModel.globalOrigin.z, - } : undefined; + return texture ? + { + type: "sphere", + texture, + rotation: 0, + zOffset: this._view.iModel.globalOrigin.z, + } : + undefined; }; if (!IModelApp.renderSystem.findTexture(sky.image, this._view.iModel)) { diff --git a/core/frontend/src/FeatureOverrideProvider.ts b/core/frontend/src/FeatureOverrideProvider.ts index 022fd0059664..e6834cffcff0 100644 --- a/core/frontend/src/FeatureOverrideProvider.ts +++ b/core/frontend/src/FeatureOverrideProvider.ts @@ -6,8 +6,8 @@ * @module Views */ -import { Viewport } from "./Viewport"; import { FeatureSymbology } from "./render/FeatureSymbology"; +import { Viewport } from "./Viewport"; /** An object that customizes the appearance of [Feature]($common)s within a [[Viewport]] using [[FeatureSymbology.Overrides]]. * When the viewport needs to recreate the symbology overrides, it invokes the provider's [[addFeatureOverrides]] method. diff --git a/core/frontend/src/FrustumAnimator.ts b/core/frontend/src/FrustumAnimator.ts index 16c8d378dead..f0195da65871 100644 --- a/core/frontend/src/FrustumAnimator.ts +++ b/core/frontend/src/FrustumAnimator.ts @@ -6,8 +6,8 @@ * @module Views */ -import { Angle, Geometry, Matrix3d, Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { Tweens } from "@itwin/core-common"; +import { Angle, Geometry, Matrix3d, Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { Animator, ViewAnimationOptions } from "./ViewAnimation"; import { ScreenViewport } from "./Viewport"; import { ViewPose, ViewPose3d } from "./ViewPose"; @@ -105,22 +105,33 @@ export class FrustumAnimator implements Animator { start: true, easing: options.easingFunction ? options.easingFunction : settings.easing, interpolation: zoomSettings.interpolation, - onComplete: () => - viewport.setupFromView(end), // when we're done, set up from final state + onComplete: () => viewport.setupFromView(end), // when we're done, set up from final state onUpdate: () => { const fraction = extentBias ? timing.position : timing.fraction; // if we're zooming, fraction comes from position interpolation - const rot = Matrix3d.createRotationAroundVector(axis.axis, Angle.createDegrees(fraction * axis.angle.degrees))!.multiplyMatrixMatrix(begin.rotation); + const rot = Matrix3d.createRotationAroundVector(axis.axis, Angle.createDegrees(fraction * axis.angle.degrees))!.multiplyMatrixMatrix( + begin.rotation, + ); if (begin.cameraOn) { const newExtents = begin.extents.interpolate(fraction, end.extents); if (undefined !== eyeBias) { const eyePoint = begin3.camera.eye.interpolate(fraction, end3.camera.eye); eyePoint.plusScaled(eyeBias, timing.height, eyePoint); - const targetPoint = eyePoint.plusScaled(rot.getRow(2), -1.0 * (Geometry.interpolate(begin3.camera.focusDist, fraction, end3.camera.focusDist))); + const targetPoint = eyePoint.plusScaled( + rot.getRow(2), + -1.0 * (Geometry.interpolate(begin3.camera.focusDist, fraction, end3.camera.focusDist)), + ); view3.lookAt({ eyePoint, targetPoint, upVector: rot.getRow(1), newExtents }); } else { const data = interpolateSwingingEye( - begin3.rotation, begin3.camera.eye, begin3.camera.focusDist, - end3.rotation, end3.camera.eye, end3.camera.focusDist, fraction, rot); + begin3.rotation, + begin3.camera.eye, + begin3.camera.focusDist, + end3.rotation, + end3.camera.eye, + end3.camera.focusDist, + fraction, + rot, + ); view3.lookAt({ eyePoint: data.eye, targetPoint: data.target, upVector: rot.getRow(1), newExtents }); } } else { diff --git a/core/frontend/src/FuzzySearch.ts b/core/frontend/src/FuzzySearch.ts index 303da75e2e0b..b07e789bb760 100644 --- a/core/frontend/src/FuzzySearch.ts +++ b/core/frontend/src/FuzzySearch.ts @@ -10,7 +10,6 @@ import Fuse from "fuse.js"; /** @public */ export class FuzzySearch { - /** Override to provide non-standard FuseOptions for searches where the a single word pattern is used */ public onGetSingleWordSearchOptions(): Fuse.FuseOptions { return { @@ -183,9 +182,13 @@ export class FuzzySearchResults implements Iterable { this.results = results; } - public [Symbol.iterator](): any { return new FuzzySearchResultsIterator(this); } + public [Symbol.iterator](): any { + return new FuzzySearchResultsIterator(this); + } - public get length(): number { return this.results.length; } + public get length(): number { + return this.results.length; + } public getResult(resultIndex: number): FuzzySearchResult | undefined { if ((resultIndex < 0) || (resultIndex > this.results.length)) diff --git a/core/frontend/src/GeoServices.ts b/core/frontend/src/GeoServices.ts index 3d7892b3db7d..cf054ca71676 100644 --- a/core/frontend/src/GeoServices.ts +++ b/core/frontend/src/GeoServices.ts @@ -7,16 +7,20 @@ */ // cspell:ignore GCRS +import { assert, BeEvent, Dictionary, Logger, SortedArray } from "@itwin/core-bentley"; import { - assert, BeEvent, Dictionary, Logger, SortedArray, -} from "@itwin/core-bentley"; -import { WritableXYAndZ, XYAndZ, XYZProps } from "@itwin/core-geometry"; -import { - GeoCoordinatesRequestProps, GeoCoordinatesResponseProps, GeoCoordStatus, GeographicCRSProps, IModelCoordinatesRequestProps, IModelCoordinatesResponseProps, - IModelReadRpcInterface, PointWithStatus, + GeoCoordinatesRequestProps, + GeoCoordinatesResponseProps, + GeoCoordStatus, + GeographicCRSProps, + IModelCoordinatesRequestProps, + IModelCoordinatesResponseProps, + IModelReadRpcInterface, + PointWithStatus, } from "@itwin/core-common"; -import { IModelConnection } from "./IModelConnection"; +import { WritableXYAndZ, XYAndZ, XYZProps } from "@itwin/core-geometry"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; +import { IModelConnection } from "./IModelConnection"; /** Options used to create a [[CoordinateConverter]]. * @internal exported strictly for tests. @@ -39,10 +43,10 @@ function cloneXYAndZ(xyz: XYAndZ): XYAndZ { type CoordinateConverterState = // No pending requests. - "idle" | - // We have scheduled a requestAnimationFrame to dispatch all pending requests. - "scheduled" | - // We have dispatched all requests that were pending at the most recent requestAnimationFrame callback. + | "idle" + | // We have scheduled a requestAnimationFrame to dispatch all pending requests. + "scheduled" + | // We have dispatched all requests that were pending at the most recent requestAnimationFrame callback. "in-flight"; /** Performs conversion of coordinates from one coordinate system to another. @@ -134,7 +138,10 @@ export class CoordinateConverter { return; if (results.length !== requests.length) - Logger.logError(`${FrontendLoggerCategory.Package}.geoservices`, `requested conversion of ${requests.length} points, but received ${results.length} points`); + Logger.logError( + `${FrontendLoggerCategory.Package}.geoservices`, + `requested conversion of ${requests.length} points, but received ${results.length} points`, + ); for (let j = 0; j < results.length; j++) { if (j < requests.length) diff --git a/core/frontend/src/GlobeAnimator.ts b/core/frontend/src/GlobeAnimator.ts index 14af78c81eeb..66b508ee5a05 100644 --- a/core/frontend/src/GlobeAnimator.ts +++ b/core/frontend/src/GlobeAnimator.ts @@ -6,13 +6,18 @@ * @module Views */ -import { Arc3d, Geometry, Point3d, SmoothTransformBetweenFrusta } from "@itwin/core-geometry"; import { Cartographic, Easing, Frustum, GlobeMode, Interpolation, Tweens } from "@itwin/core-common"; +import { Arc3d, Geometry, Point3d, SmoothTransformBetweenFrusta } from "@itwin/core-geometry"; +import { Animator } from "./ViewAnimation"; import { - areaToEyeHeight, areaToEyeHeightFromGcs, eyeToCartographicOnGlobe, GlobalLocation, metersToRange, ViewGlobalLocationConstants, + areaToEyeHeight, + areaToEyeHeightFromGcs, + eyeToCartographicOnGlobe, + GlobalLocation, + metersToRange, + ViewGlobalLocationConstants, } from "./ViewGlobalLocation"; import { ScreenViewport } from "./Viewport"; -import { Animator } from "./ViewAnimation"; /** Animates the transition of a [[Viewport]] to view a location on the Earth. The animation traces a flight path from the viewport's current [Frustum]($common) to the destination. * The duration of the animation varies based on the distance traversed. @@ -48,7 +53,7 @@ export class GlobeAnimator implements Animator { // If we're done, set the final state directly if (fraction >= 1.0) { - if (vp.view.is3d()) // Need to reset focus as well -- setupViewFromFustum does not set this and it will remain at flight distance. + if (vp.view.is3d()) // Need to reset focus as well -- setupViewFromFustum does not set this and it will remain at flight distance. vp.view.camera.setFocusDistance(this._afterFocusDistance); vp.setupViewFromFrustum(this._afterLanding); vp.synchWithView(); @@ -109,7 +114,9 @@ export class GlobeAnimator implements Animator { if (!(view.is3d()) || !viewport.iModel.isGeoLocated) // This animation only works for 3d views and geolocated models return undefined; - const endHeight = destination.area !== undefined ? await areaToEyeHeightFromGcs(view, destination.area, destination.center.height) : ViewGlobalLocationConstants.birdHeightAboveEarthInMeters; + const endHeight = destination.area !== undefined + ? await areaToEyeHeightFromGcs(view, destination.area, destination.center.height) + : ViewGlobalLocationConstants.birdHeightAboveEarthInMeters; const beforeFrustum = viewport.getWorldFrustum(); await view.lookAtGlobalLocationFromGcs(endHeight, ViewGlobalLocationConstants.birdPitchAngleRadians, destination); @@ -138,7 +145,9 @@ export class GlobeAnimator implements Animator { return; this._startHeight = eyeToCartographicOnGlobe(this._viewport, true)!.height; - this._endHeight = destination.area !== undefined ? areaToEyeHeight(view, destination.area, destination.center.height) : ViewGlobalLocationConstants.birdHeightAboveEarthInMeters; + this._endHeight = destination.area !== undefined + ? areaToEyeHeight(view, destination.area, destination.center.height) + : ViewGlobalLocationConstants.birdHeightAboveEarthInMeters; // Starting cartographic position is the eye projected onto the globe. let startCartographic = eyeToCartographicOnGlobe(viewport); @@ -159,7 +168,12 @@ export class GlobeAnimator implements Animator { } else { // Calculate a flight arc from the ellipsoid of the Earth and the starting and ending cartographic coordinates. const earthEllipsoid = backgroundMapGeometry.getEarthEllipsoid(); - this._ellipsoidArc = earthEllipsoid.radiansPairToGreatArc(this._startCartographic.longitude, this._startCartographic.latitude, this._endLocation.center.longitude, this._endLocation.center.latitude)!; + this._ellipsoidArc = earthEllipsoid.radiansPairToGreatArc( + this._startCartographic.longitude, + this._startCartographic.latitude, + this._endLocation.center.longitude, + this._endLocation.center.latitude, + )!; if (this._ellipsoidArc !== undefined) this._flightLength = this._ellipsoidArc.curveLength(); // Set a longer flight duration in 3D mode @@ -170,10 +184,12 @@ export class GlobeAnimator implements Animator { return; // The peak of the flight varies based on total distance to travel. The larger the distance, the higher the peak of the flight will be. - this._midHeight = metersToRange(this._flightLength, + this._midHeight = metersToRange( + this._flightLength, ViewGlobalLocationConstants.birdHeightAboveEarthInMeters, ViewGlobalLocationConstants.satelliteHeightAboveEarthInMeters * 4, - ViewGlobalLocationConstants.largestEarthArc); + ViewGlobalLocationConstants.largestEarthArc, + ); // We will "fix" the initial frustum so it smoothly transitions to some point along the travel arc depending on the starting height. // Alternatively, if the distance to travel is small enough, we will _only_ do a frustum transition to the destination location - ignoring the flight arc. @@ -184,7 +200,9 @@ export class GlobeAnimator implements Animator { // However, if within driving distance, still use SmoothTransformBetweenFrusta to navigate there without flight. this._fixTakeoffFraction = this._flightLength <= ViewGlobalLocationConstants.maximumDistanceToDrive ? 1.0 : 0.0; } else { - this._fixTakeoffFraction = this._flightLength <= ViewGlobalLocationConstants.maximumDistanceToDrive ? 1.0 : metersToRange(this._startHeight, 0.1, 0.4, ViewGlobalLocationConstants.birdHeightAboveEarthInMeters); + this._fixTakeoffFraction = this._flightLength <= ViewGlobalLocationConstants.maximumDistanceToDrive + ? 1.0 + : metersToRange(this._startHeight, 0.1, 0.4, ViewGlobalLocationConstants.birdHeightAboveEarthInMeters); } if (this._fixTakeoffFraction > 0.0) { diff --git a/core/frontend/src/GraphicalEditingScope.ts b/core/frontend/src/GraphicalEditingScope.ts index bb735924b5f0..fe1ed982e62b 100644 --- a/core/frontend/src/GraphicalEditingScope.ts +++ b/core/frontend/src/GraphicalEditingScope.ts @@ -7,12 +7,17 @@ */ import { assert, BeEvent, compareStrings, DbOpcode, DuplicatePolicy, GuidString, Id64Set, Id64String, SortedArray } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { - EditingScopeNotifications, ElementGeometryChange, ipcAppChannels, ModelGeometryChanges, ModelGeometryChangesProps, RemoveFunction, + EditingScopeNotifications, + ElementGeometryChange, + ipcAppChannels, + ModelGeometryChanges, + ModelGeometryChangesProps, + RemoveFunction, } from "@itwin/core-common"; -import { BriefcaseNotificationHandler } from "./BriefcaseTxns"; +import { Range3d } from "@itwin/core-geometry"; import { BriefcaseConnection } from "./BriefcaseConnection"; +import { BriefcaseNotificationHandler } from "./BriefcaseTxns"; import { IpcApp } from "./IpcApp"; class ModelChanges extends SortedArray { @@ -53,7 +58,9 @@ class ModelChanges extends SortedArray { * @public */ export class GraphicalEditingScope extends BriefcaseNotificationHandler implements EditingScopeNotifications { - public get briefcaseChannelName() { return ipcAppChannels.editingScope; } + public get briefcaseChannelName() { + return ipcAppChannels.editingScope; + } /** Maps model Id to accumulated changes to geometric elements within the associated model. */ private readonly _geometryChanges = new Map(); @@ -142,7 +149,7 @@ export class GraphicalEditingScope extends BriefcaseNotificationHandler implemen return this._disposed; } - private * geometryChangeIterator(): Iterator { + private *geometryChangeIterator(): Iterator { for (const [key, value] of this._geometryChanges) { yield { id: key, diff --git a/core/frontend/src/HitDetail.ts b/core/frontend/src/HitDetail.ts index c7e3f3bf9339..2e4a51ebdb4d 100644 --- a/core/frontend/src/HitDetail.ts +++ b/core/frontend/src/HitDetail.ts @@ -6,14 +6,14 @@ * @module LocatingElements */ import { assert, Id64, Id64String } from "@itwin/core-bentley"; -import { Arc3d, CurvePrimitive, LineSegment3d, LineString3d, Path, Point3d, Transform, Vector3d, XYZProps } from "@itwin/core-geometry"; import { GeometryClass, LinePixels } from "@itwin/core-common"; +import { Arc3d, CurvePrimitive, LineSegment3d, LineString3d, Path, Point3d, Transform, Vector3d, XYZProps } from "@itwin/core-geometry"; +import { GraphicType } from "./common/render/GraphicType"; import { IModelApp } from "./IModelApp"; import { IModelConnection } from "./IModelConnection"; import { IconSprites, Sprite } from "./Sprites"; import { DecorateContext } from "./ViewContext"; import { ScreenViewport, Viewport } from "./Viewport"; -import { GraphicType } from "./common/render/GraphicType"; /** * @public @@ -35,7 +35,7 @@ export enum SnapMode { */ export enum SnapHeat { None = 0, - NotInRange = 1, // "of interest", but out of range + NotInRange = 1, // "of interest", but out of range InRange = 2, } @@ -175,55 +175,117 @@ export class HitDetail { private readonly _props: HitDetailProps; /** The point in world coordinates that was used as the initial locate point. */ - public get testPoint(): Point3d { return this._props.testPoint; } + public get testPoint(): Point3d { + return this._props.testPoint; + } /** The viewport in which the locate operation was performed. */ - public get viewport(): ScreenViewport { return this._props.viewport; } + public get viewport(): ScreenViewport { + return this._props.viewport; + } /** The procedure that requested the locate operation. */ - public get hitSource(): HitSource { return this._props.hitSource; } + public get hitSource(): HitSource { + return this._props.hitSource; + } /** The approximate location in world coordinates on the geometry identified by this HitDetail. */ - public get hitPoint(): Point3d { return this._props.hitPoint; } + public get hitPoint(): Point3d { + return this._props.hitPoint; + } /** The source of the geometry. This may be a persistent element Id, or a transient Id used for, e.g., pickable decorations. */ - public get sourceId(): Id64String { return this._props.sourceId; } + public get sourceId(): Id64String { + return this._props.sourceId; + } /** The hit geometry priority/classification. */ - public get priority(): HitPriority { return this._props.priority; } + public get priority(): HitPriority { + return this._props.priority; + } /** The xy distance to the hit in view coordinates. */ - public get distXY(): number { return this._props.distXY; } + public get distXY(): number { + return this._props.distXY; + } /** The distance in view coordinates between the hit and the near plane. */ - public get distFraction(): number { return this._props.distFraction; } + public get distFraction(): number { + return this._props.distFraction; + } /** The [SubCategory]($backend) to which the hit geometry belongs. */ - public get subCategoryId(): Id64String | undefined { return this._props.subCategoryId; } + public get subCategoryId(): Id64String | undefined { + return this._props.subCategoryId; + } /** The class of the hit geometry. */ - public get geometryClass(): GeometryClass | undefined { return this._props.geometryClass; } + public get geometryClass(): GeometryClass | undefined { + return this._props.geometryClass; + } /** The Id of the [[ModelState]] from which the hit originated. */ - public get modelId(): string | undefined { return this._props.modelId; } + public get modelId(): string | undefined { + return this._props.modelId; + } /** The IModelConnection from which the hit originated. * This should almost always be left undefined, unless the hit is known to have originated from an iModel * other than the one associated with the viewport. * @internal */ - public get sourceIModel(): IModelConnection | undefined { return this._props.sourceIModel; } + public get sourceIModel(): IModelConnection | undefined { + return this._props.sourceIModel; + } /** @internal */ - public get transformFromSourceIModel(): Transform | undefined { return this._props.transformFromSourceIModel; } + public get transformFromSourceIModel(): Transform | undefined { + return this._props.transformFromSourceIModel; + } /** @internal chiefly for debugging */ - public get tileId(): string | undefined { return this._props.tileId; } + public get tileId(): string | undefined { + return this._props.tileId; + } /** True if the hit originated from a reality model classifier. * @alpha */ - public get isClassifier(): boolean | undefined { return this._props.isClassifier; } + public get isClassifier(): boolean | undefined { + return this._props.isClassifier; + } /** Information about the [ViewAttachment]($backend) within which the hit geometry resides, if any. * @note Only [[SheetViewState]]s can have view attachments. * @beta */ - public get viewAttachment(): ViewAttachmentHitInfo | undefined { return this._props.viewAttachment; } + public get viewAttachment(): ViewAttachmentHitInfo | undefined { + return this._props.viewAttachment; + } /** Create a new HitDetail from the inputs to and results of a locate operation. */ public constructor(props: HitDetailProps); /** @deprecated in 4.1. Use the overload that takes a [[HitDetailProps]]. */ - public constructor(testPoint: Point3d, viewport: ScreenViewport, hitSource: HitSource, hitPoint: Point3d, sourceId: string, priority: HitPriority, distXY: number, distFraction: number, subCategoryId?: string, geometryClass?: GeometryClass, modelId?: string, sourceIModel?: IModelConnection, tileId?: string, isClassifier?: boolean); + public constructor( + testPoint: Point3d, + viewport: ScreenViewport, + hitSource: HitSource, + hitPoint: Point3d, + sourceId: string, + priority: HitPriority, + distXY: number, + distFraction: number, + subCategoryId?: string, + geometryClass?: GeometryClass, + modelId?: string, + sourceIModel?: IModelConnection, + tileId?: string, + isClassifier?: boolean, + ); /** @internal */ - public constructor(arg0: Point3d | HitDetailProps, viewport?: ScreenViewport, hitSource?: HitSource, hitPoint?: Point3d, sourceId?: string, priority?: HitPriority, distXY?: number, distFraction?: number, subCategoryId?: string, geometryClass?: GeometryClass, modelId?: string, sourceIModel?: IModelConnection, tileId?: string, isClassifier?: boolean) { + public constructor( + arg0: Point3d | HitDetailProps, + viewport?: ScreenViewport, + hitSource?: HitSource, + hitPoint?: Point3d, + sourceId?: string, + priority?: HitPriority, + distXY?: number, + distFraction?: number, + subCategoryId?: string, + geometryClass?: GeometryClass, + modelId?: string, + sourceIModel?: IModelConnection, + tileId?: string, + isClassifier?: boolean, + ) { if (arg0 instanceof Point3d) { assert(undefined !== viewport && undefined !== hitSource && undefined !== hitPoint && undefined !== sourceId); assert(undefined !== priority && undefined !== distXY && undefined !== distFraction); @@ -270,23 +332,33 @@ export class HitDetail { /** Get the type of HitDetail. * @returns HitDetailType.Hit if this is a HitDetail, HitDetailType.Snap if it is a SnapDetail */ - public getHitType(): HitDetailType { return HitDetailType.Hit; } + public getHitType(): HitDetailType { + return HitDetailType.Hit; + } /** Get the *hit point* for this HitDetail. Returns the approximate point on the element that caused the hit when not a SnapDetail or IntersectDetail. * For a snap that is *hot*, the *exact* point on the Element for the snap mode is returned, otherwise the close point on the hit geometry is returned. */ - public getPoint(): Point3d { return this.hitPoint; } + public getPoint(): Point3d { + return this.hitPoint; + } /** Determine if this HitPoint is from the same source as another HitDetail. */ - public isSameHit(otherHit?: HitDetail): boolean { return (undefined !== otherHit && this.sourceId === otherHit.sourceId && this.iModel === otherHit.iModel); } + public isSameHit(otherHit?: HitDetail): boolean { + return (undefined !== otherHit && this.sourceId === otherHit.sourceId && this.iModel === otherHit.iModel); + } /** Return whether sourceId is for a persistent element and not a pickable decoration. */ - public get isElementHit(): boolean { return !Id64.isInvalid(this.sourceId) && !Id64.isTransient(this.sourceId); } + public get isElementHit(): boolean { + return !Id64.isInvalid(this.sourceId) && !Id64.isTransient(this.sourceId); + } // return whether the sourceId is for a model (reality models etc.) public get isModelHit(): boolean { return this.modelId === this.sourceId; } // return whether the hit point is from map. - public get isMapHit(): boolean { return 0 !== this.viewport.mapLayerFromHit(this).length; } + public get isMapHit(): boolean { + return 0 !== this.viewport.mapLayerFromHit(this).length; + } /** Create a deep copy of this HitDetail */ public clone(): HitDetail { @@ -357,13 +429,21 @@ export class SnapDetail extends HitDetail { } /** Returns `HitDetailType.Snap` */ - public override getHitType(): HitDetailType { return HitDetailType.Snap; } + public override getHitType(): HitDetailType { + return HitDetailType.Snap; + } /** Get the snap point if this SnapDetail is *hot*, the pick point otherwise. */ - public override getPoint(): Point3d { return this.isHot ? this.snapPoint : super.getPoint(); } + public override getPoint(): Point3d { + return this.isHot ? this.snapPoint : super.getPoint(); + } /** Return true if the pick point was closer than the snap aperture from the generated snap point. */ - public get isHot(): boolean { return this.heat !== SnapHeat.None; } + public get isHot(): boolean { + return this.heat !== SnapHeat.None; + } /** Determine whether the [[adjustedPoint]] is different than the [[snapPoint]]. This happens, for example, when points are adjusted for grids, acs plane snap, and AccuDraw. */ - public get isPointAdjusted(): boolean { return !this.adjustedPoint.isExactEqual(this.snapPoint); } + public get isPointAdjusted(): boolean { + return !this.adjustedPoint.isExactEqual(this.snapPoint); + } /** Change the snap point. */ public setSnapPoint(point: Point3d, heat: SnapHeat) { this.snapPoint.setFrom(point); @@ -425,7 +505,7 @@ export class SnapDetail extends HitDetail { if (ls.points.length > 2) { const loc = ls.closestPoint(this.snapPoint, false); const nSegments = ls.points.length - 1; - const uSegRange = (1.0 / nSegments); + const uSegRange = 1.0 / nSegments; let segmentNo = Math.floor(loc.fraction / uSegRange); if (segmentNo >= nSegments) segmentNo = nSegments - 1; @@ -470,13 +550,20 @@ export class SnapDetail extends HitDetail { private static getSnapSpriteUrl(snapType: SnapMode): string { switch (snapType) { - case SnapMode.Nearest: return `${IModelApp.publicPath}sprites/SnapPointOn.png`; - case SnapMode.NearestKeypoint: return `${IModelApp.publicPath}sprites/SnapKeypoint.png`; - case SnapMode.MidPoint: return `${IModelApp.publicPath}sprites/SnapMidpoint.png`; - case SnapMode.Center: return `${IModelApp.publicPath}sprites/SnapCenter.png`; - case SnapMode.Origin: return `${IModelApp.publicPath}sprites/SnapOrigin.png`; - case SnapMode.Bisector: return `${IModelApp.publicPath}sprites/SnapBisector.png`; - case SnapMode.Intersection: return `${IModelApp.publicPath}sprites/SnapIntersection.png`; + case SnapMode.Nearest: + return `${IModelApp.publicPath}sprites/SnapPointOn.png`; + case SnapMode.NearestKeypoint: + return `${IModelApp.publicPath}sprites/SnapKeypoint.png`; + case SnapMode.MidPoint: + return `${IModelApp.publicPath}sprites/SnapMidpoint.png`; + case SnapMode.Center: + return `${IModelApp.publicPath}sprites/SnapCenter.png`; + case SnapMode.Origin: + return `${IModelApp.publicPath}sprites/SnapOrigin.png`; + case SnapMode.Bisector: + return `${IModelApp.publicPath}sprites/SnapBisector.png`; + case SnapMode.Intersection: + return `${IModelApp.publicPath}sprites/SnapIntersection.png`; } return ""; } @@ -487,7 +574,13 @@ export class SnapDetail extends HitDetail { * @extensions */ export class IntersectDetail extends SnapDetail { - public constructor(from: SnapDetail, heat: SnapHeat = SnapHeat.None, snapPoint: XYZProps, public readonly otherPrimitive: CurvePrimitive, public readonly otherId: string) { + public constructor( + from: SnapDetail, + heat: SnapHeat = SnapHeat.None, + snapPoint: XYZProps, + public readonly otherPrimitive: CurvePrimitive, + public readonly otherId: string, + ) { super(from, SnapMode.Intersection, heat, snapPoint); this.primitive = from.primitive; this.normal = from.normal; // Preserve normal from primary snap location for AccuDraw smart rotation... @@ -525,13 +618,17 @@ export class IntersectDetail extends SnapDetail { export class HitList { public hits: T[] = []; public currHit = -1; - public get length(): number { return this.hits.length; } + public get length(): number { + return this.hits.length; + } public empty(): void { this.hits.length = 0; this.currHit = -1; } - public resetCurrentHit(): void { this.currHit = -1; } + public resetCurrentHit(): void { + this.currHit = -1; + } /** Get a hit from a particular index into a HitList * return the requested hit from the HitList or undefined @@ -562,7 +659,9 @@ export class HitList { return this.getCurrentHit(); } - public getCurrentHit(): T | undefined { return -1 === this.currHit ? undefined : this.getHit(this.currHit); } + public getCurrentHit(): T | undefined { + return -1 === this.currHit ? undefined : this.getHit(this.currHit); + } public setCurrentHit(hit: T): void { this.resetCurrentHit(); @@ -573,18 +672,20 @@ export class HitList { } /** remove the current hit from the list. */ - public removeCurrentHit() { this.removeHit(this.currHit); } + public removeCurrentHit() { + this.removeHit(this.currHit); + } /** remove a hit in the list. */ public removeHit(hitNum: number) { - if (hitNum < 0) // Support -1 == END + if (hitNum < 0) // Support -1 == END hitNum = this.length - 1; if (hitNum <= this.currHit) this.currHit = -1; - if (hitNum >= this.length) // Locate calls GetNextHit, which increments currHit, until it goes beyond the end of size of the array. - return; // Then Reset call RemoteCurrentHit, which passes in currHit. When it is out of range, we do nothing. + if (hitNum >= this.length) // Locate calls GetNextHit, which increments currHit, until it goes beyond the end of size of the array. + return; // Then Reset call RemoteCurrentHit, which passes in currHit. When it is out of range, we do nothing. this.hits.splice(hitNum, 1); } diff --git a/core/frontend/src/IModelApp.ts b/core/frontend/src/IModelApp.ts index c61638eee9c8..b60a640bb3d7 100644 --- a/core/frontend/src/IModelApp.ts +++ b/core/frontend/src/IModelApp.ts @@ -12,12 +12,20 @@ import packageJson from "../../package.json"; /** @public */ // eslint-disable-next-line @typescript-eslint/no-var-requires export const ITWINJS_CORE_VERSION = packageJson.version as string; -const COPYRIGHT_NOTICE = 'Copyright © 2017-2024 Bentley Systems, Inc.'; +const COPYRIGHT_NOTICE = + 'Copyright © 2017-2024 Bentley Systems, Inc.'; import { UiAdmin } from "@itwin/appui-abstract"; import { AccessToken, BeDuration, BeEvent, BentleyStatus, DbResult, dispose, Guid, GuidString, Logger, ProcessDetector } from "@itwin/core-bentley"; import { - AuthorizationClient, IModelStatus, Localization, RealityDataAccess, RpcConfiguration, RpcInterfaceDefinition, RpcRequest, SerializedRpcActivity, + AuthorizationClient, + IModelStatus, + Localization, + RealityDataAccess, + RpcConfiguration, + RpcInterfaceDefinition, + RpcRequest, + SerializedRpcActivity, } from "@itwin/core-common"; import { ITwinLocalization } from "@itwin/core-i18n"; import { TelemetryManager } from "@itwin/core-telemetry"; @@ -26,23 +34,23 @@ import { AccuDraw } from "./AccuDraw"; import { AccuSnap } from "./AccuSnap"; import * as auxCoordState from "./AuxCoordSys"; import * as categorySelectorState from "./CategorySelectorState"; -import { ExtensionAdmin } from "./extension/ExtensionAdmin"; +import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import * as displayStyleState from "./DisplayStyleState"; import * as drawingViewState from "./DrawingViewState"; import { ElementLocateManager } from "./ElementLocateManager"; import { EntityState } from "./EntityState"; +import { ExtensionAdmin } from "./extension/ExtensionAdmin"; import { FrontendHubAccess } from "./FrontendHubAccess"; -import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import * as modelselector from "./ModelSelectorState"; import * as modelState from "./ModelState"; import { NotificationManager } from "./NotificationManager"; import { QuantityFormatter } from "./quantity-formatting/QuantityFormatter"; +import { RealityDataSourceProviderRegistry } from "./RealityDataSource"; import { RenderSystem } from "./render/RenderSystem"; import { System } from "./render/webgl/System"; import * as sheetState from "./SheetViewState"; import * as spatialViewState from "./SpatialViewState"; import { TentativePoint } from "./TentativePoint"; -import { RealityDataSourceProviderRegistry } from "./RealityDataSource"; import { MapLayerFormatRegistry, MapLayerOptions, TerrainProviderRegistry, TileAdmin } from "./tile/internal"; import * as accudrawTool from "./tools/AccuDrawTool"; import * as clipViewTool from "./tools/ClipViewTool"; @@ -213,7 +221,7 @@ export class IModelApp { private static _publicPath: string; // No instances of IModelApp may be created. All members are static and must be on the singleton object IModelApp. - protected constructor() { } + protected constructor() {} /** Event raised just before the frontend IModelApp is to be [[shutdown]]. */ public static readonly onBeforeShutdown = new BeEvent<() => void>(); @@ -228,52 +236,92 @@ export class IModelApp { /** A uniqueId for this session */ public static sessionId: GuidString; /** The [[MapLayerFormatRegistry]] for this session. */ - public static get mapLayerFormatRegistry(): MapLayerFormatRegistry { return this._mapLayerFormatRegistry; } + public static get mapLayerFormatRegistry(): MapLayerFormatRegistry { + return this._mapLayerFormatRegistry; + } /** The [[TerrainProviderRegistry]] for this session. */ - public static get terrainProviderRegistry(): TerrainProviderRegistry { return this._terrainProviderRegistry; } + public static get terrainProviderRegistry(): TerrainProviderRegistry { + return this._terrainProviderRegistry; + } /** The [[RealityDataSourceProviderRegistry]] for this session. * @alpha */ - public static get realityDataSourceProviders(): RealityDataSourceProviderRegistry { return this._realityDataSourceProviders; } + public static get realityDataSourceProviders(): RealityDataSourceProviderRegistry { + return this._realityDataSourceProviders; + } /** The [[RenderSystem]] for this session. */ - public static get renderSystem(): RenderSystem { return this._renderSystem!; } + public static get renderSystem(): RenderSystem { + return this._renderSystem!; + } /** The [[ViewManager]] for this session. */ - public static get viewManager(): ViewManager { return this._viewManager; } + public static get viewManager(): ViewManager { + return this._viewManager; + } /** The [[NotificationManager]] for this session. */ - public static get notifications(): NotificationManager { return this._notifications; } + public static get notifications(): NotificationManager { + return this._notifications; + } /** The [[TileAdmin]] for this session. */ - public static get tileAdmin(): TileAdmin { return this._tileAdmin; } + public static get tileAdmin(): TileAdmin { + return this._tileAdmin; + } /** The [[QuantityFormatter]] for this session. */ - public static get quantityFormatter(): QuantityFormatter { return this._quantityFormatter; } + public static get quantityFormatter(): QuantityFormatter { + return this._quantityFormatter; + } /** The [[ToolAdmin]] for this session. */ - public static get toolAdmin(): ToolAdmin { return this._toolAdmin; } + public static get toolAdmin(): ToolAdmin { + return this._toolAdmin; + } /** The [[AccuDraw]] for this session. */ - public static get accuDraw(): AccuDraw { return this._accuDraw; } + public static get accuDraw(): AccuDraw { + return this._accuDraw; + } /** The [[AccuSnap]] for this session. */ - public static get accuSnap(): AccuSnap { return this._accuSnap; } - public static get locateManager(): ElementLocateManager { return this._locateManager; } + public static get accuSnap(): AccuSnap { + return this._accuSnap; + } + public static get locateManager(): ElementLocateManager { + return this._locateManager; + } /** The [[TentativePoint]] for this session]]. */ - public static get tentativePoint(): TentativePoint { return this._tentativePoint; } + public static get tentativePoint(): TentativePoint { + return this._tentativePoint; + } /** The [[Localization]] for this session. */ - public static get localization(): Localization { return this._localization; } + public static get localization(): Localization { + return this._localization; + } /** The [[UserPreferencesAccess]] for this session. * @beta */ - public static get userPreferences(): UserPreferencesAccess | undefined { return this._userPreferences; } + public static get userPreferences(): UserPreferencesAccess | undefined { + return this._userPreferences; + } /** The Id of this application. Applications must set this to the Global Product Registry ID (GPRID) for usage logging. */ - public static get applicationId(): string { return this._applicationId; } + public static get applicationId(): string { + return this._applicationId; + } /** The version of this application. Must be set for usage logging. */ - public static get applicationVersion(): string { return this._applicationVersion; } + public static get applicationVersion(): string { + return this._applicationVersion; + } /** True after [[startup]] has been called, until [[shutdown]] is called. */ - public static get initialized() { return this._initialized; } + public static get initialized() { + return this._initialized; + } /** Provides access to IModelHub services. */ - public static get hubAccess(): FrontendHubAccess | undefined { return this._hubAccess; } + public static get hubAccess(): FrontendHubAccess | undefined { + return this._hubAccess; + } /** Provides access to the RealityData service implementation for this IModelApp * @beta */ - public static get realityDataAccess(): RealityDataAccess | undefined { return this._realityDataAccess; } + public static get realityDataAccess(): RealityDataAccess | undefined { + return this._realityDataAccess; + } /** Whether the [renderSystem[]] has been successfully initialized. * This will always be `false` before calling [[startup]] and after calling [[shutdown]]. @@ -286,14 +334,20 @@ export class IModelApp { } /** The [[UiAdmin]] for this session. */ - public static get uiAdmin() { return this._uiAdmin; } + public static get uiAdmin() { + return this._uiAdmin; + } /** The requested security options for the frontend. */ - public static get securityOptions() { return this._securityOptions; } + public static get securityOptions() { + return this._securityOptions; + } /** If present, overrides where public assets are fetched. The default is to fetch assets relative to the current URL. * The path should always end with a trailing `/`. */ - public static get publicPath() { return this._publicPath; } + public static get publicPath() { + return this._publicPath; + } /** The [[TelemetryManager]] for this session * @internal @@ -324,7 +378,8 @@ export class IModelApp { public static registerEntityState(classFullName: string, classType: typeof EntityState) { const lowerName = classFullName.toLowerCase(); if (this._entityClasses.has(lowerName)) { - const errMsg = `Class ${classFullName} is already registered. Make sure static schemaName and className members are correct on class ${classType.name}`; + const errMsg = + `Class ${classFullName} is already registered. Make sure static schemaName and className members are correct on class ${classType.name}`; Logger.logError(FrontendLoggerCategory.IModelConnection, errMsg); throw new Error(errMsg); } @@ -333,7 +388,9 @@ export class IModelApp { } /** @internal */ - public static lookupEntityClass(classFullName: string) { return this._entityClasses.get(classFullName.toLowerCase()); } + public static lookupEntityClass(classFullName: string) { + return this._entityClasses.get(classFullName.toLowerCase()); + } /** * Obtain WebGL rendering compatibility information for the client system. This information describes whether the client meets the @@ -342,7 +399,10 @@ export class IModelApp { * @note As of 4.x, iTwin.js requires WebGL 2. If the client does not support WebGL 2, the `status` field of the returned compatibility info will be [WebGLRenderCompatibilityStatus.CannotCreateContext]($webgl-compatibility). */ public static queryRenderCompatibility(): WebGLRenderCompatibilityInfo { - return queryRenderCompatibility(true, (canvas, useWebGL2, inputContextAttributes) => System.createContext(canvas, useWebGL2, inputContextAttributes)); + return queryRenderCompatibility( + true, + (canvas, useWebGL2, inputContextAttributes) => System.createContext(canvas, useWebGL2, inputContextAttributes), + ); } /** @@ -367,7 +427,7 @@ export class IModelApp { } this.sessionId = opts.sessionId ?? Guid.createValue(); - this._applicationId = opts.applicationId ?? "2686"; // Default to product id of iTwin.js + this._applicationId = opts.applicationId ?? "2686"; // Default to product id of iTwin.js this._applicationVersion = opts.applicationVersion ?? "1.0.0"; this.authorizationClient = opts.authorizationClient; this._hubAccess = opts.hubAccess; @@ -467,7 +527,9 @@ export class IModelApp { * @param interval The interval at which to poll for changes. If undefined (or negative), the application will never poll. If zero, the application will poll as frequently as possible. * @beta */ - public static get animationInterval(): BeDuration | undefined { return IModelApp._animationInterval; } + public static get animationInterval(): BeDuration | undefined { + return IModelApp._animationInterval; + } public static set animationInterval(interval: BeDuration | undefined) { if (undefined !== interval && interval.isTowardsPast) interval = undefined; @@ -558,7 +620,9 @@ export class IModelApp { } /** @internal */ - public static createRenderSys(opts?: RenderSystem.Options): RenderSystem { return System.create(opts); } + public static createRenderSys(opts?: RenderSystem.Options): RenderSystem { + return System.create(opts); + } private static _setupRpcRequestContext() { RpcConfiguration.requestContext.getId = (_request: RpcRequest): string => { @@ -684,7 +748,8 @@ export class IModelApp { iconWidth?: number; /** A *notice* string to be shown on the logo card. May include HTML. */ notice?: string | HTMLElement; - }): HTMLTableRowElement { + }, + ): HTMLTableRowElement { const card = IModelApp.makeHTMLElement("tr"); const iconCell = IModelApp.makeHTMLElement("td", { parent: card, className: "logo-card-logo" }); if (undefined !== opts.iconSrc) { diff --git a/core/frontend/src/IModelConnection.ts b/core/frontend/src/IModelConnection.ts index f9c0495fb422..6f07e0775415 100644 --- a/core/frontend/src/IModelConnection.ts +++ b/core/frontend/src/IModelConnection.ts @@ -7,23 +7,84 @@ */ import { - assert, BeEvent, CompressedId64Set, GeoServiceStatus, GuidString, Id64, Id64Arg, Id64Set, Id64String, Logger, OneAtATimeAction, OpenMode, - PickAsyncMethods, TransientIdSequence, + assert, + BeEvent, + CompressedId64Set, + GeoServiceStatus, + GuidString, + Id64, + Id64Arg, + Id64Set, + Id64String, + Logger, + OneAtATimeAction, + OpenMode, + PickAsyncMethods, + TransientIdSequence, } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, Cartographic, CodeProps, CodeSpec, DbQueryRequest, DbResult, EcefLocation, EcefLocationProps, ECSqlReader, ElementLoadOptions, + AxisAlignedBox3d, + Cartographic, + CodeProps, + CodeSpec, + DbQueryRequest, + DbResult, + EcefLocation, + EcefLocationProps, + ECSqlReader, + ElementLoadOptions, ElementMeshRequestProps, - ElementProps, EntityQueryParams, FontMap, GeoCoordStatus, GeographicCRSProps, GeometryContainmentRequestProps, GeometryContainmentResponseProps, GeometrySummaryRequestProps, ImageSourceFormat, IModel, IModelConnectionProps, IModelError, - IModelReadRpcInterface, IModelStatus, mapToGeoServiceStatus, MassPropertiesPerCandidateRequestProps, MassPropertiesPerCandidateResponseProps, - MassPropertiesRequestProps, MassPropertiesResponseProps, ModelExtentsProps, ModelProps, ModelQueryParams, NoContentError, Placement, Placement2d, - Placement3d, QueryBinder, QueryOptions, QueryOptionsBuilder, QueryRowFormat, RpcManager, SnapRequestProps, SnapResponseProps, - SnapshotIModelRpcInterface, SubCategoryAppearance, SubCategoryResultRow, TextureData, TextureLoadProps, ThumbnailProps, ViewDefinitionProps, - ViewIdString, ViewQueryParams, ViewStateLoadProps, ViewStateProps, ViewStoreRpc, + ElementProps, + EntityQueryParams, + FontMap, + GeoCoordStatus, + GeographicCRSProps, + GeometryContainmentRequestProps, + GeometryContainmentResponseProps, + GeometrySummaryRequestProps, + ImageSourceFormat, + IModel, + IModelConnectionProps, + IModelError, + IModelReadRpcInterface, + IModelStatus, + mapToGeoServiceStatus, + MassPropertiesPerCandidateRequestProps, + MassPropertiesPerCandidateResponseProps, + MassPropertiesRequestProps, + MassPropertiesResponseProps, + ModelExtentsProps, + ModelProps, + ModelQueryParams, + NoContentError, + Placement, + Placement2d, + Placement3d, + QueryBinder, + QueryOptions, + QueryOptionsBuilder, + QueryRowFormat, + RpcManager, + SnapRequestProps, + SnapResponseProps, + SnapshotIModelRpcInterface, + SubCategoryAppearance, + SubCategoryResultRow, + TextureData, + TextureLoadProps, + ThumbnailProps, + ViewDefinitionProps, + ViewIdString, + ViewQueryParams, + ViewStateLoadProps, + ViewStateProps, + ViewStoreRpc, } from "@itwin/core-common"; import { Point3d, Range3d, Range3dProps, Transform, XYAndZ, XYZProps } from "@itwin/core-geometry"; import { BriefcaseConnection } from "./BriefcaseConnection"; import { CheckpointConnection } from "./CheckpointConnection"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; +import { _requestSnap } from "./common/internal/Symbols"; import { EntityState } from "./EntityState"; import { GeoServices } from "./GeoServices"; import { IModelApp } from "./IModelApp"; @@ -34,7 +95,6 @@ import { SubCategoriesCache } from "./SubCategoriesCache"; import { BingElevationProvider } from "./tile/internal"; import { Tiles } from "./Tiles"; import { ViewState } from "./ViewState"; -import { _requestSnap } from "./common/internal/Symbols"; const loggerCategory: string = FrontendLoggerCategory.IModelConnection; @@ -78,7 +138,9 @@ export abstract class IModelConnection extends IModel { /** A cache of information about SubCategories chiefly used for rendering. * @internal */ - public get subcategories(): SubCategoriesCache { return this.categories.cache; } + public get subcategories(): SubCategoriesCache { + return this.categories.cache; + } /** Generator for unique Ids of transient graphics for this IModelConnection. */ public readonly transientIds = new TransientIdSequence(); /** The Geographic location services available for this iModelConnection. */ @@ -86,9 +148,13 @@ export abstract class IModelConnection extends IModel { /** @internal Whether GCS has been disabled for this iModelConnection. */ protected _gcsDisabled = false; /** @internal Return true if a GCS is not defined for this iModelConnection; also returns true if GCS is defined but disabled. */ - public get noGcsDefined(): boolean { return this._gcsDisabled || undefined === this.geographicCoordinateSystem; } + public get noGcsDefined(): boolean { + return this._gcsDisabled || undefined === this.geographicCoordinateSystem; + } /** @internal */ - public disableGCS(disable: boolean): void { this._gcsDisabled = disable; } + public disableGCS(disable: boolean): void { + this._gcsDisabled = disable; + } /** The displayed extents of this iModel, initialized to [IModel.projectExtents]($common). The displayed extents can be made larger via * [[expandDisplayedExtents]], but never smaller, to accommodate data sources like reality models that may exceed the project extents. * @note Do not modify these extents directly - use [[expandDisplayedExtents]] only. @@ -104,38 +170,56 @@ export abstract class IModelConnection extends IModel { public routingContext: IModelRoutingContext = IModelRoutingContext.default; /** Type guard for instanceof [[BriefcaseConnection]] */ - public isBriefcaseConnection(): this is BriefcaseConnection { return false; } + public isBriefcaseConnection(): this is BriefcaseConnection { + return false; + } /** Type guard for instanceof [[CheckpointConnection]] * @beta - */ - public isCheckpointConnection(): this is CheckpointConnection { return false; } + */ + public isCheckpointConnection(): this is CheckpointConnection { + return false; + } /** Type guard for instanceof [[SnapshotConnection]] */ - public isSnapshotConnection(): this is SnapshotConnection { return false; } + public isSnapshotConnection(): this is SnapshotConnection { + return false; + } /** Type guard for instanceof [[BlankConnection]] */ - public isBlankConnection(): this is BlankConnection { return false; } + public isBlankConnection(): this is BlankConnection { + return false; + } /** Returns `true` if this is a briefcase copy of an iModel that is synchronized with iModelHub. */ - public get isBriefcase(): boolean { return this.isBriefcaseConnection(); } + public get isBriefcase(): boolean { + return this.isBriefcaseConnection(); + } /** Returns `true` if this is a *snapshot* iModel. * @see [[SnapshotConnection.openSnapshot]] */ - public get isSnapshot(): boolean { return this.isSnapshotConnection(); } + public get isSnapshot(): boolean { + return this.isSnapshotConnection(); + } /** True if this is a [Blank Connection]($docs/learning/frontend/BlankConnection). */ - public get isBlank(): boolean { return this.isBlankConnection(); } + public get isBlank(): boolean { + return this.isBlankConnection(); + } /** Check the [[openMode]] of this IModelConnection to see if it was opened read-only. */ - public get isReadonly(): boolean { return this.openMode === OpenMode.Readonly; } + public get isReadonly(): boolean { + return this.openMode === OpenMode.Readonly; + } /** Check if the IModelConnection is open (i.e. it has a *connection* to a backend server). * Returns false for [[BlankConnection]] instances and after [[IModelConnection.close]] has been called. * @note no RPC operations are valid on this IModelConnection if this method returns false. */ - public get isOpen(): boolean { return !this.isClosed; } + public get isOpen(): boolean { + return !this.isClosed; + } /** Check if the IModelConnection is closed (i.e. it has no *connection* to a backend server). * Returns true for [[BlankConnection]] instances and after [[IModelConnection.close]] has been called. @@ -191,7 +275,10 @@ export abstract class IModelConnection extends IModel { // wait until we get the full list of base classes from backend if (this.isOpen) { - const baseClasses = await IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getClassHierarchy(this.getRpcProps(), className); + const baseClasses = await IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getClassHierarchy( + this.getRpcProps(), + className, + ); // Make sure some other async code didn't register this class while we were await-ing above ctor = IModelApp.lookupEntityClass(className) as T | undefined; @@ -265,7 +352,7 @@ export abstract class IModelConnection extends IModel { * @param config Allow to specify certain flags which control how query is executed. * @returns Returns an [ECSqlReader]($common) which helps iterate over the result set and also give access to metadata. * @public - * */ + */ public createQueryReader(ecsql: string, params?: QueryBinder, config?: QueryOptions): ECSqlReader { const executor = { execute: async (request: DbQueryRequest) => { @@ -310,7 +397,7 @@ export abstract class IModelConnection extends IModel { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead; it accepts the same parameters. */ - public async * query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *query(ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { const builder = new QueryOptionsBuilder(options); const reader = this.createQueryReader(ecsql, params, builder.getOptions()); while (await reader.step()) @@ -355,7 +442,7 @@ export abstract class IModelConnection extends IModel { * @throws [IModelError]($common) If there was any error while submitting, preparing or stepping into query * @deprecated in 3.7. Use [[createQueryReader]] instead. Pass in the restart token as part of the `config` argument; e.g., `{ restartToken: myToken }` or `new QueryOptionsBuilder().setRestartToken(myToken).getOptions()`. */ - public async * restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { + public async *restartQuery(token: string, ecsql: string, params?: QueryBinder, options?: QueryOptions): AsyncIterableIterator { for await (const row of this.createQueryReader(ecsql, params, new QueryOptionsBuilder(options).setRestartToken(token).getOptions())) { yield row; } @@ -365,7 +452,11 @@ export abstract class IModelConnection extends IModel { * @throws [IModelError]($common) If the generated statement is invalid or would return too many rows. */ public async queryEntityIds(params: EntityQueryParams): Promise { - return new Set(this.isOpen ? await IModelReadRpcInterface.getClientForRouting(this.routingContext.token).queryEntityIds(this.getRpcProps(), params) : undefined); + return new Set( + this.isOpen + ? await IModelReadRpcInterface.getClientForRouting(this.routingContext.token).queryEntityIds(this.getRpcProps(), params) + : undefined, + ); } private _snapRpc = new OneAtATimeAction( @@ -388,7 +479,9 @@ export abstract class IModelConnection extends IModel { return this[_requestSnap](props); } - private _toolTipRpc = new OneAtATimeAction(async (id: string) => IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getToolTipMessage(this.getRpcProps(), id)); + private _toolTipRpc = new OneAtATimeAction(async (id: string) => + IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getToolTipMessage(this.getRpcProps(), id) + ); /** Request a tooltip from the backend. * @note If another call to this method occurs before preceding call(s) return, all preceding calls will be abandoned - only the most recent will resolve. Therefore callers must gracefully handle Promise rejected with AbandonedError. */ @@ -397,7 +490,9 @@ export abstract class IModelConnection extends IModel { } /** Request element clip containment status from the backend. */ - public async getGeometryContainment(requestProps: GeometryContainmentRequestProps): Promise { return IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getGeometryContainment(this.getRpcProps(), requestProps); } + public async getGeometryContainment(requestProps: GeometryContainmentRequestProps): Promise { + return IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getGeometryContainment(this.getRpcProps(), requestProps); + } /** Obtain a summary of the geometry belonging to one or more [GeometricElement]($backend)s suitable for debugging and diagnostics. * @param requestProps Specifies the elements to query and options for how to format the output. @@ -431,7 +526,9 @@ export abstract class IModelConnection extends IModel { } /** Request mass properties for multiple elements from the backend. */ - public async getMassPropertiesPerCandidate(requestProps: MassPropertiesPerCandidateRequestProps): Promise { + public async getMassPropertiesPerCandidate( + requestProps: MassPropertiesPerCandidateRequestProps, + ): Promise { return IModelReadRpcInterface.getClientForRouting(this.routingContext.token).getMassPropertiesPerCandidate(this.getRpcProps(), requestProps); } @@ -606,7 +703,6 @@ export abstract class IModelConnection extends IModel { * @beta */ public async toSpatialFromGcs(geoCoords: XYAndZ[], datumOrGCRS?: string | GeographicCRSProps): Promise { - if (!this.isGeoLocated) throw new IModelError(GeoServiceStatus.NoGeoLocation, "iModel is not GeoLocated"); @@ -710,21 +806,31 @@ export abstract class IModelConnection extends IModel { * @public */ export class BlankConnection extends IModelConnection { - public override isBlankConnection(): this is BlankConnection { return true; } + public override isBlankConnection(): this is BlankConnection { + return true; + } /** The Guid that identifies the iTwin for this BlankConnection. * @note This can also be set via the [[create]] method using [[BlankConnectionProps.iTwinId]]. */ - public override get iTwinId(): GuidString | undefined { return this._iTwinId; } - public override set iTwinId(iTwinId: GuidString | undefined) { this._iTwinId = iTwinId; } + public override get iTwinId(): GuidString | undefined { + return this._iTwinId; + } + public override set iTwinId(iTwinId: GuidString | undefined) { + this._iTwinId = iTwinId; + } /** A BlankConnection does not have an associated iModel, so its `iModelId` is alway `undefined`. */ - public override get iModelId(): undefined { return undefined; } // GuidString | undefined for the superclass, but always undefined for BlankConnection + public override get iModelId(): undefined { + return undefined; + } // GuidString | undefined for the superclass, but always undefined for BlankConnection /** A BlankConnection is always considered closed because it does not have a specific backend nor associated iModel. * @returns `true` is always returned since RPC operations and iModel queries are not valid. * @note Even though true is always returned, it is still valid to call [[close]] to dispose frontend resources. */ - public get isClosed(): boolean { return true; } + public get isClosed(): boolean { + return true; + } /** Create a new [Blank IModelConnection]($docs/learning/frontend/BlankConnection). * @param props The properties to use for the new BlankConnection. @@ -760,19 +866,27 @@ export class BlankConnection extends IModelConnection { */ export class SnapshotConnection extends IModelConnection { /** Type guard for instanceof [[SnapshotConnection]] */ - public override isSnapshotConnection(): this is SnapshotConnection { return true; } + public override isSnapshotConnection(): this is SnapshotConnection { + return true; + } /** The Guid that identifies this iModel. */ - public override get iModelId(): GuidString { return super.iModelId!; } // GuidString | undefined for the superclass, but required for SnapshotConnection + public override get iModelId(): GuidString { + return super.iModelId!; + } // GuidString | undefined for the superclass, but required for SnapshotConnection /** Returns `true` if [[close]] has already been called. */ - public get isClosed(): boolean { return this._isClosed ? true : false; } + public get isClosed(): boolean { + return this._isClosed ? true : false; + } private _isClosed?: boolean; /** Returns `true` if this is a connection to a remote snapshot iModel resolved by the backend. * @see [[openRemote]] */ - public get isRemote(): boolean { return this._isRemote ? true : false; } + public get isRemote(): boolean { + return this._isRemote ? true : false; + } private _isRemote?: boolean; /** Open an IModelConnection to a read-only snapshot iModel from a file name. @@ -829,7 +943,6 @@ export class SnapshotConnection extends IModelConnection { /** @public */ export namespace IModelConnection { // eslint-disable-line no-redeclare - /** The id/name/class of a ViewDefinition. Returned by [[IModelConnection.Views.getViewList]] */ export interface ViewSpec { /** The element id of the ViewDefinition. This string may be passed to [[IModelConnection.Views.load]]. */ @@ -845,7 +958,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare private _loaded = new Map(); /** @internal */ - public get loaded(): Map { return this._loaded; } + public get loaded(): Map { + return this._loaded; + } /** An iterator over all currently-loaded models. */ public [Symbol.iterator](): Iterator { @@ -853,10 +968,12 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare } /** @internal */ - constructor(private _iModel: IModelConnection) { } + constructor(private _iModel: IModelConnection) {} /** The Id of the [RepositoryModel]($backend). */ - public get repositoryModelId(): string { return "0x1"; } + public get repositoryModelId(): string { + return "0x1"; + } /** @internal */ public async getDictionaryModel(): Promise { @@ -869,7 +986,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare /** Get a batch of [[ModelProps]] given a list of Model ids. */ public async getProps(modelIds: Id64Arg): Promise { const iModel = this._iModel; - return iModel.isOpen ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getModelProps(iModel.getRpcProps(), [...Id64.toIdSet(modelIds)]) : []; + return iModel.isOpen + ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getModelProps(iModel.getRpcProps(), [...Id64.toIdSet(modelIds)]) + : []; } /** Find a ModelState in the set of loaded Models by ModelId. */ @@ -940,7 +1059,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async queryModelRanges(modelIds: Id64Arg): Promise { const iModel = this._iModel; - return iModel.isOpen ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).queryModelRanges(iModel.getRpcProps(), [...Id64.toIdSet(modelIds)]) : []; + return iModel.isOpen + ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).queryModelRanges(iModel.getRpcProps(), [...Id64.toIdSet(modelIds)]) + : []; } /** For each [GeometricModel]($backend) specified by Id, attempts to obtain the union of the volumes of all geometric elements within that model. @@ -987,7 +1108,7 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare } /** Asynchronously stream ModelProps using the specified ModelQueryParams. */ - public async * query(queryParams: ModelQueryParams): AsyncIterableIterator { + public async *query(queryParams: ModelQueryParams): AsyncIterableIterator { // NOTE: this implementation has the desired API signature, but its implementation must be improved to actually page results const modelPropsArray: ModelProps[] = await this.queryProps(queryParams); for (const modelProps of modelPropsArray) { @@ -1011,13 +1132,17 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare /** The collection of Elements for an [[IModelConnection]]. */ export class Elements { /** @internal */ - public constructor(private _iModel: IModelConnection) { } + public constructor(private _iModel: IModelConnection) {} /** The Id of the [root subject element]($docs/bis/guide/references/glossary.md#subject-root) for this iModel. */ - public get rootSubjectId(): Id64String { return "0x1"; } + public get rootSubjectId(): Id64String { + return "0x1"; + } /** Get a set of element ids that satisfy a query */ - public async queryIds(params: EntityQueryParams): Promise { return this._iModel.queryEntityIds(params); } + public async queryIds(params: EntityQueryParams): Promise { + return this._iModel.queryEntityIds(params); + } /** Get an array of [[ElementProps]] given one or more element ids. * @note This method returns **all** of the properties of the element (excluding GeometryStream), which may be a very large amount of data - consider using @@ -1025,7 +1150,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async getProps(arg: Id64Arg): Promise { const iModel = this._iModel; - return iModel.isOpen ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getElementProps(this._iModel.getRpcProps(), [...Id64.toIdSet(arg)]) : []; + return iModel.isOpen + ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getElementProps(this._iModel.getRpcProps(), [...Id64.toIdSet(arg)]) + : []; } /** Obtain the properties of a single element, optionally specifying specific properties to include or exclude. @@ -1041,7 +1168,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async loadProps(identifier: Id64String | GuidString | CodeProps, options?: ElementLoadOptions): Promise { const imodel = this._iModel; - return imodel.isOpen ? IModelReadRpcInterface.getClientForRouting(imodel.routingContext.token).loadElementProps(imodel.getRpcProps(), identifier, options) : undefined; + return imodel.isOpen + ? IModelReadRpcInterface.getClientForRouting(imodel.routingContext.token).loadElementProps(imodel.getRpcProps(), identifier, options) + : undefined; } /** Get an array of [[ElementProps]] that satisfy a query @@ -1050,7 +1179,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async queryProps(params: EntityQueryParams): Promise { const iModel = this._iModel; - return iModel.isOpen ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).queryElementProps(iModel.getRpcProps(), params) : []; + return iModel.isOpen + ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).queryElementProps(iModel.getRpcProps(), params) + : []; } /** Obtain the [Placement]($common)s of a set of [GeometricElement]($backend)s. @@ -1059,7 +1190,10 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare * @returns an array of placements, each having an additional `elementId` property identifying the element from which the placement was obtained. * @note Any Id that does not identify a geometric element with a valid bounding box and origin is omitted from the returned array. */ - public async getPlacements(elementIds: Iterable, options?: Readonly): Promise> { + public async getPlacements( + elementIds: Iterable, + options?: Readonly, + ): Promise> { let ids: Id64String[]; if (typeof elementIds === "string") ids = [elementIds]; @@ -1130,7 +1264,7 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare else placement = Placement3d.fromJSON({ bbox, origin, angles: { yaw: row.yaw, pitch: row.pitch, roll: row.roll } }); - const placementWithId = (placement as Placement & { elementId: Id64String }); + const placementWithId = placement as Placement & { elementId: Id64String }; placementWithId.elementId = row.id; placements.push(placementWithId); } @@ -1144,7 +1278,7 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare private _loaded?: CodeSpec[]; /** @internal */ - constructor(private _iModel: IModelConnection) { } + constructor(private _iModel: IModelConnection) {} /** Loads all CodeSpec from the remote IModelDb. */ private async _loadAllCodeSpecs(): Promise { @@ -1152,7 +1286,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare return; this._loaded = []; - const codeSpecArray: any[] = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getAllCodeSpecs(this._iModel.getRpcProps()); + const codeSpecArray: any[] = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getAllCodeSpecs( + this._iModel.getRpcProps(), + ); for (const codeSpec of codeSpecArray) { this._loaded.push(CodeSpec.createFromJson(this._iModel, Id64.fromString(codeSpec.id), codeSpec.name, codeSpec.jsonProperties)); } @@ -1193,7 +1329,7 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare /** The collection of views for an [[IModelConnection]]. */ export class Views { /** @internal */ - constructor(private _iModel: IModelConnection) { } + constructor(private _iModel: IModelConnection) {} private _writeViewStoreProxy?: PickAsyncMethods; private _readViewStoreProxy?: PickAsyncMethods; @@ -1201,7 +1337,14 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare return this._writeViewStoreProxy ??= new Proxy(this, { get(views, methodName: string) { const iModel = views._iModel; - return async (...args: any[]) => IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).callViewStore(iModel.getRpcProps(), ViewStoreRpc.version, true, methodName, ...args); + return async (...args: any[]) => + IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).callViewStore( + iModel.getRpcProps(), + ViewStoreRpc.version, + true, + methodName, + ...args, + ); }, }) as unknown as PickAsyncMethods; } @@ -1209,7 +1352,14 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare return this._readViewStoreProxy ??= new Proxy(this, { get(views, methodName: string) { const iModel = views._iModel; - return async (...args: any[]) => IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).callViewStore(iModel.getRpcProps(), ViewStoreRpc.version, false, methodName, ...args); + return async (...args: any[]) => + IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).callViewStore( + iModel.getRpcProps(), + ViewStoreRpc.version, + false, + methodName, + ...args, + ); }, }) as unknown as PickAsyncMethods; } @@ -1233,7 +1383,7 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare params.where += "IsPrivate=FALSE "; } const viewProps = await IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).queryElementProps(iModel.getRpcProps(), params); - assert((viewProps.length === 0) || ("categorySelectorId" in viewProps[0]), "invalid view definition"); // spot check that the first returned element is-a ViewDefinitionProps + assert((viewProps.length === 0) || ("categorySelectorId" in viewProps[0]), "invalid view definition"); // spot check that the first returned element is-a ViewDefinitionProps return viewProps as ViewDefinitionProps[]; } @@ -1267,7 +1417,9 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async queryDefaultViewId(): Promise { const iModel = this._iModel; - return iModel.isOpen ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getDefaultViewId(iModel.getRpcProps()) : Id64.invalid; + return iModel.isOpen + ? IModelReadRpcInterface.getClientForRouting(iModel.routingContext.token).getDefaultViewId(iModel.getRpcProps()) + : Id64.invalid; } /** Load a [[ViewState]] object from the specified [[ViewDefinition]] id. */ @@ -1278,7 +1430,11 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare compressExcludedElementIds: true, }, }; - const viewProps = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getViewStateData(this._iModel.getRpcProps(), viewDefinitionId, options); + const viewProps = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getViewStateData( + this._iModel.getRpcProps(), + viewDefinitionId, + options, + ); const viewState = await this.convertViewStatePropsToViewState(viewProps); return viewState; } @@ -1305,13 +1461,21 @@ export namespace IModelConnection { // eslint-disable-line no-redeclare */ public async getThumbnail(_viewId: Id64String): Promise { // eslint-disable-next-line deprecation/deprecation - const val = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getViewThumbnail(this._iModel.getRpcProps(), _viewId.toString()); + const val = await IModelReadRpcInterface.getClientForRouting(this._iModel.routingContext.token).getViewThumbnail( + this._iModel.getRpcProps(), + _viewId.toString(), + ); const intValues = new Uint32Array(val.buffer, 0, 4); if (intValues[1] !== ImageSourceFormat.Jpeg && intValues[1] !== ImageSourceFormat.Png) throw new NoContentError(); - return { format: intValues[1] === ImageSourceFormat.Jpeg ? "jpeg" : "png", width: intValues[2], height: intValues[3], image: new Uint8Array(val.buffer, 16, intValues[0]) }; + return { + format: intValues[1] === ImageSourceFormat.Jpeg ? "jpeg" : "png", + width: intValues[2], + height: intValues[3], + image: new Uint8Array(val.buffer, 16, intValues[0]), + }; } } diff --git a/core/frontend/src/IModelRoutingContext.ts b/core/frontend/src/IModelRoutingContext.ts index 29ca61b85383..f6a5d69a6acc 100644 --- a/core/frontend/src/IModelRoutingContext.ts +++ b/core/frontend/src/IModelRoutingContext.ts @@ -27,7 +27,9 @@ export class IModelRoutingContext { public readonly token: RpcRoutingToken; - public get active(): boolean { return IModelRoutingContext.current === this; } + public get active(): boolean { + return IModelRoutingContext.current === this; + } private constructor(token: RpcRoutingToken) { this.token = token; diff --git a/core/frontend/src/IpcApp.ts b/core/frontend/src/IpcApp.ts index 805f4d439c7a..6e73242847c8 100644 --- a/core/frontend/src/IpcApp.ts +++ b/core/frontend/src/IpcApp.ts @@ -8,11 +8,20 @@ import { AsyncMethodsOf, PickAsyncMethods, PromiseReturnType } from "@itwin/core-bentley"; import { - BackendError, IModelError, IModelStatus, ipcAppChannels, IpcAppFunctions, IpcAppNotifications, IpcInvokeReturn, IpcListener, IpcSocketFrontend, - iTwinChannel, RemoveFunction, + BackendError, + IModelError, + IModelStatus, + ipcAppChannels, + IpcAppFunctions, + IpcAppNotifications, + IpcInvokeReturn, + IpcListener, + IpcSocketFrontend, + iTwinChannel, + RemoveFunction, } from "@itwin/core-common"; -import { IModelApp, IModelAppOptions } from "./IModelApp"; import { _callIpcChannel } from "./common/internal/Symbols"; +import { IModelApp, IModelAppOptions } from "./IModelApp"; /** * Options for [[IpcApp.startup]] @@ -30,10 +39,14 @@ export class IpcApp { private static _ipc: IpcSocketFrontend | undefined; /** Get the implementation of the [[IpcSocketFrontend]] interface. */ - private static get ipc(): IpcSocketFrontend { return this._ipc!; } + private static get ipc(): IpcSocketFrontend { + return this._ipc!; + } /** Determine whether Ipc is available for this frontend. This will only be true if [[startup]] has been called on this class. */ - public static get isValid(): boolean { return undefined !== this._ipc; } + public static get isValid(): boolean { + return undefined !== this._ipc; + } /** * Establish a message handler function for the supplied channel over Ipc. The handler will be called when messages are sent for @@ -115,8 +128,7 @@ export class IpcApp { public static makeIpcProxy(channelName: string): PickAsyncMethods { return new Proxy({} as PickAsyncMethods, { get(_target, methodName: string) { - return async (...args: any[]) => - IpcApp[_callIpcChannel](channelName, methodName, ...args); + return async (...args: any[]) => IpcApp[_callIpcChannel](channelName, methodName, ...args); }, }); } @@ -128,8 +140,7 @@ export class IpcApp { public static makeIpcFunctionProxy(channelName: string, functionName: string): PickAsyncMethods { return new Proxy({} as PickAsyncMethods, { get(_target, methodName: string) { - return async (...args: any[]) => - IpcApp[_callIpcChannel](channelName, functionName, methodName, ...args); + return async (...args: any[]) => IpcApp[_callIpcChannel](channelName, functionName, methodName, ...args); }, }); } @@ -179,7 +190,10 @@ export abstract class NotificationHandler { return IpcApp.addListener(this.channelName, (_evt: Event, funcName: string, ...args: any[]) => { const func = (this as any)[funcName]; if (typeof func !== "function") - throw new IModelError(IModelStatus.FunctionNotFound, `Method "${this.constructor.name}.${funcName}" not found on NotificationHandler registered for channel: ${this.channelName}`); + throw new IModelError( + IModelStatus.FunctionNotFound, + `Method "${this.constructor.name}.${funcName}" not found on NotificationHandler registered for channel: ${this.channelName}`, + ); func.call(this, ...args); }); @@ -198,6 +212,8 @@ export abstract class NotificationHandler { /** IpcApp notifications from backend */ class IpcAppNotifyHandler extends NotificationHandler implements IpcAppNotifications { - public get channelName() { return ipcAppChannels.appNotify; } - public notifyApp() { } + public get channelName() { + return ipcAppChannels.appNotify; + } + public notifyApp() {} } diff --git a/core/frontend/src/LinePlaneIntersect.ts b/core/frontend/src/LinePlaneIntersect.ts index 61ce25ecc83d..f101c174f440 100644 --- a/core/frontend/src/LinePlaneIntersect.ts +++ b/core/frontend/src/LinePlaneIntersect.ts @@ -9,7 +9,14 @@ import { Point3d, Vector3d } from "@itwin/core-geometry"; /** @internal */ -export function linePlaneIntersect(outP: Point3d, linePt: Point3d, lineNormal: Vector3d | undefined, planePt: Point3d, planeNormal: Vector3d, perpendicular: boolean): void { +export function linePlaneIntersect( + outP: Point3d, + linePt: Point3d, + lineNormal: Vector3d | undefined, + planePt: Point3d, + planeNormal: Vector3d, + perpendicular: boolean, +): void { let dot = 0; if (lineNormal) dot = lineNormal.dotProduct(planeNormal); diff --git a/core/frontend/src/LocalhostIpcApp.ts b/core/frontend/src/LocalhostIpcApp.ts index d340762aa319..d2cc8a54e7a8 100644 --- a/core/frontend/src/LocalhostIpcApp.ts +++ b/core/frontend/src/LocalhostIpcApp.ts @@ -6,10 +6,18 @@ * @module IModelApp */ -import { InterceptedRpcRequest, IpcSession, IpcWebSocket, IpcWebSocketFrontend, IpcWebSocketMessage, IpcWebSocketTransport, rpcOverIpcStrings } from "@itwin/core-common"; -import { IpcApp } from "./IpcApp"; -import { IModelApp, IModelAppOptions } from "./IModelApp"; +import { + InterceptedRpcRequest, + IpcSession, + IpcWebSocket, + IpcWebSocketFrontend, + IpcWebSocketMessage, + IpcWebSocketTransport, + rpcOverIpcStrings, +} from "@itwin/core-common"; import { _callIpcChannel } from "./common/internal/Symbols"; +import { IModelApp, IModelAppOptions } from "./IModelApp"; +import { IpcApp } from "./IpcApp"; /** @internal */ export interface LocalHostIpcAppOpts { diff --git a/core/frontend/src/Marker.ts b/core/frontend/src/Marker.ts index 7ad4bd875ff4..12d804829ba9 100644 --- a/core/frontend/src/Marker.ts +++ b/core/frontend/src/Marker.ts @@ -7,8 +7,8 @@ */ import { assert, Logger, ObservableSet } from "@itwin/core-bentley"; -import { Geometry, Matrix4d, Point2d, Point3d, Range1d, Range1dProps, Vector3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { ColorDef } from "@itwin/core-common"; +import { Geometry, Matrix4d, Point2d, Point3d, Range1d, Range1dProps, Vector3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import { imageElementFromUrl } from "./common/ImageUtil"; import { ViewRect } from "./common/ViewRect"; @@ -121,7 +121,9 @@ export class Marker implements CanvasDecoration { public htmlElement?: HTMLElement; /** Return true to display [[image]], if present. */ - public get wantImage() { return true; } + public get wantImage() { + return true; + } /** Implement this function to draw onto the CanvasRenderingContext2D when this Marker is displayed. The [0,0] point will be the center of the Marker. */ public drawFunc?(ctx: CanvasRenderingContext2D): void; @@ -134,7 +136,9 @@ export class Marker implements CanvasDecoration { } /** Called when the mouse pointer leaves this Marker. */ - public onMouseLeave() { this._isHilited = false; } + public onMouseLeave() { + this._isHilited = false; + } /** Called when the mouse pointer moves over this Marker */ public onMouseMove(ev: BeButtonEvent): void { @@ -145,7 +149,9 @@ export class Marker implements CanvasDecoration { public onMouseButton?(_ev: BeButtonEvent): boolean; /** Determine whether the point is within this Marker. */ - public pick(pt: XAndY): boolean { return this.rect.containsPoint(pt); } + public pick(pt: XAndY): boolean { + return this.rect.containsPoint(pt); + } /** Establish a range of scale factors to increases and decrease the size of this Marker based on its distance from the camera. * @param range The minimum and maximum scale factors to be applied to the size of this Marker based on its distance from the camera. `range.Low` is the scale factor @@ -228,9 +234,7 @@ export class Marker implements CanvasDecoration { */ public setImage(image: MarkerImage | Promise) { if (image instanceof Promise) { - image.then((resolvedImage) => - this.image = resolvedImage, - ).catch((err: Event) => { + image.then((resolvedImage) => this.image = resolvedImage).catch((err: Event) => { const target = err.target as any; const msg = `Could not load image ${target && target.src ? target.src : "unknown"}`; Logger.logError(`${FrontendLoggerCategory.Package}.markers`, msg); @@ -241,7 +245,9 @@ export class Marker implements CanvasDecoration { } /** Set the image for this Marker from a URL. */ - public setImageUrl(url: string) { this.setImage(imageElementFromUrl(url)); } + public setImageUrl(url: string) { + this.setImage(imageElementFromUrl(url)); + } /** Set the position (in pixels) for this Marker in the supplied Viewport, based on its worldLocation. * @param markerSet The MarkerSet if this Marker is included in a set. @@ -269,7 +275,7 @@ export class Marker implements CanvasDecoration { let scale = 1.0; if (vp.isCameraOn) { const range = this._scaleFactorRange; - const minScaleViewW = (undefined !== markerSet ? markerSet.getMinScaleViewW(vp) : getMinScaleViewW(vp)); + const minScaleViewW = undefined !== markerSet ? markerSet.getMinScaleViewW(vp) : getMinScaleViewW(vp); if (minScaleViewW > 0.0) scale = Geometry.clamp(range.high - (pt4.w / minScaleViewW) * range.length(), .4, 2.0); else @@ -368,7 +374,9 @@ export abstract class MarkerSet { /** The minimum number of Markers that must overlap before they are clustered. Otherwise they are each drawn individually. Default is 1 (always create a cluster.) */ public minimumClusterSize = 1; /** The set of Markers in this MarkerSet. Add your [[Marker]]s into this. */ - public get markers(): Set { return this._markers; } + public get markers(): Set { + return this._markers; + } /** The radius (in pixels) representing the distance between the screen X,Y positions of two Markers to be clustered. When less than or equal to 0 (the default), the radius is calculated based on the first visible marker imageSize/size. */ protected clusterRadius = 0; @@ -384,7 +392,9 @@ export abstract class MarkerSet { } /** The ScreenViewport of this MarkerSet. */ - public get viewport(): ScreenViewport | undefined { return this._viewport; } + public get viewport(): ScreenViewport | undefined { + return this._viewport; + } /** Change the ScreenViewport for this MarkerSet. * After this call, the markers from this MarkerSet will only appear in the supplied ScreenViewport. diff --git a/core/frontend/src/ModelSelectorState.ts b/core/frontend/src/ModelSelectorState.ts index 2b4a4c020be3..321bfacbdd25 100644 --- a/core/frontend/src/ModelSelectorState.ts +++ b/core/frontend/src/ModelSelectorState.ts @@ -17,7 +17,9 @@ import { IModelConnection } from "./IModelConnection"; * @extensions */ export class ModelSelectorState extends ElementState { - public static override get className() { return "ModelSelector"; } + public static override get className() { + return "ModelSelector"; + } private readonly _models = new ObservableSet(); @@ -44,7 +46,9 @@ export class ModelSelectorState extends ElementState { } /** The name of this ModelSelector */ - public get name(): string { return this.code.value; } + public get name(): string { + return this.code.value; + } public override toJSON(): ModelSelectorProps { const val: any = super.toJSON(); @@ -83,10 +87,14 @@ export class ModelSelectorState extends ElementState { } /** Determine whether this ModelSelectorState includes the specified modelId value */ - public has(id: string): boolean { return this.models.has(id); } + public has(id: string): boolean { + return this.models.has(id); + } /** Determine whether this ModelSelectorState includes the specified modelId */ - public containsModel(modelId: Id64String): boolean { return this.has(modelId.toString()); } + public containsModel(modelId: Id64String): boolean { + return this.has(modelId.toString()); + } /** Make sure all models referenced by this ModelSelectorState are loaded. */ public async load(): Promise { diff --git a/core/frontend/src/ModelState.ts b/core/frontend/src/ModelState.ts index 3c0a92867961..389e321d7a2a 100644 --- a/core/frontend/src/ModelState.ts +++ b/core/frontend/src/ModelState.ts @@ -8,23 +8,32 @@ import { Id64, Id64String, JsonUtils } from "@itwin/core-bentley"; import { - GeometricModel2dProps, GeometricModel3dProps, GeometricModelProps, ModelProps, RealityDataFormat, RealityDataSourceKey, RealityModelDisplaySettings, RelatedElement, + GeometricModel2dProps, + GeometricModel3dProps, + GeometricModelProps, + ModelProps, + RealityDataFormat, + RealityDataSourceKey, + RealityModelDisplaySettings, + RelatedElement, } from "@itwin/core-common"; import { Point2d, Range3d } from "@itwin/core-geometry"; import { EntityState } from "./EntityState"; import { HitDetail } from "./HitDetail"; import { IModelConnection } from "./IModelConnection"; import { RealityDataSource } from "./RealityDataSource"; +import { SpatialClassifiersState } from "./SpatialClassifiersState"; import { createOrbitGtTileTreeReference, createPrimaryTileTreeReference, createRealityTileTreeReference, TileTreeReference } from "./tile/internal"; import { ViewState } from "./ViewState"; -import { SpatialClassifiersState } from "./SpatialClassifiersState"; /** Represents the front-end state of a [Model]($backend). * @public * @extensions */ export class ModelState extends EntityState implements ModelProps { - public static override get className() { return "Model"; } + public static override get className() { + return "Model"; + } public readonly modeledElement: RelatedElement; public readonly name: string; public parentModel: Id64String; @@ -54,22 +63,34 @@ export class ModelState extends EntityState implements ModelProps { } /** Determine whether this is a GeometricModel */ - public get isGeometricModel(): boolean { return false; } + public get isGeometricModel(): boolean { + return false; + } /** Attempts to cast this model to a geometric model. */ - public get asGeometricModel(): GeometricModelState | undefined { return undefined; } + public get asGeometricModel(): GeometricModelState | undefined { + return undefined; + } /** Attempts to cast this model to a 3d geometric model. */ - public get asGeometricModel3d(): GeometricModel3dState | undefined { return undefined; } + public get asGeometricModel3d(): GeometricModel3dState | undefined { + return undefined; + } /** Attempts to cast this model to a 2d geometric model. */ - public get asGeometricModel2d(): GeometricModel2dState | undefined { return undefined; } + public get asGeometricModel2d(): GeometricModel2dState | undefined { + return undefined; + } /** Attempts to cast this model to a spatial model. */ - public get asSpatialModel(): SpatialModelState | undefined { return undefined; } + public get asSpatialModel(): SpatialModelState | undefined { + return undefined; + } /** * Return the tool tip for this model. This is called only if the hit does not return a tooltip. * @internal */ - public getToolTip(_hit: HitDetail): HTMLElement | string | undefined { return undefined; } + public getToolTip(_hit: HitDetail): HTMLElement | string | undefined { + return undefined; + } } /** Represents the front-end state of a [GeometricModel]($backend). @@ -78,7 +99,9 @@ export class ModelState extends EntityState implements ModelProps { * @extensions */ export abstract class GeometricModelState extends ModelState implements GeometricModelProps { - public static override get className() { return "GeometricModel"; } + public static override get className() { + return "GeometricModel"; + } /** @internal */ public geometryGuid?: string; @@ -92,14 +115,22 @@ export abstract class GeometricModelState extends ModelState implements Geometri /** Returns true if this is a 3d model (a [[GeometricModel3dState]]). */ public abstract get is3d(): boolean; /** @internal */ - public override get asGeometricModel(): GeometricModelState { return this; } + public override get asGeometricModel(): GeometricModelState { + return this; + } /** Returns true if this is a 2d model (a [[GeometricModel2dState]]). */ - public get is2d(): boolean { return !this.is3d; } + public get is2d(): boolean { + return !this.is3d; + } /** @internal */ - public override get isGeometricModel(): boolean { return true; } + public override get isGeometricModel(): boolean { + return true; + } /** @internal */ - public get treeModelId(): Id64String { return this.id; } + public get treeModelId(): Id64String { + return this.id; + } /** Query for the union of the ranges of all the elements in this GeometricModel. * @note This value is cached after the first time it is called. @@ -149,7 +180,7 @@ export abstract class GeometricModelState extends ModelState implements Geometri const orbitGtBlob = this.jsonProperties.orbitGtBlob; // If this is an OrbitGt reality model, create it's reference - if(orbitGtBlob) { + if (orbitGtBlob) { let orbitGtName = ""; if (orbitGtBlob.blobFileName !== "") { if (orbitGtBlob.blobFileName[0] === "/") @@ -175,11 +206,11 @@ export abstract class GeometricModelState extends ModelState implements Geometri // If this is a TileTree reality model, create it's reference const tilesetUrl = this.jsonProperties.tilesetUrl; - if(tilesetUrl) { + if (tilesetUrl) { const rdSourceKeyCS = RealityDataSource.createKeyFromUrl(tilesetUrl); return createRealityTileTreeReference({ rdSourceKey: rdSourceKeyCS, - url : tilesetUrl, + url: tilesetUrl, iModel: this.iModel, source: view, modelId: this.id, @@ -197,7 +228,9 @@ export abstract class GeometricModelState extends ModelState implements Geometri * @extensions */ export class GeometricModel2dState extends GeometricModelState implements GeometricModel2dProps { - public static override get className() { return "GeometricModel2d"; } + public static override get className() { + return "GeometricModel2d"; + } /** @internal */ public readonly globalOrigin: Point2d; @@ -207,9 +240,13 @@ export class GeometricModel2dState extends GeometricModelState implements Geomet } /** @internal */ - public get is3d(): boolean { return false; } + public get is3d(): boolean { + return false; + } /** @internal */ - public override get asGeometricModel2d(): GeometricModel2dState { return this; } + public override get asGeometricModel2d(): GeometricModel2dState { + return this; + } public override toJSON(): GeometricModel2dProps { const val = super.toJSON() as GeometricModel2dProps; @@ -223,7 +260,9 @@ export class GeometricModel2dState extends GeometricModelState implements Geomet * @extensions */ export class GeometricModel3dState extends GeometricModelState { - public static override get className() { return "GeometricModel3d"; } + public static override get className() { + return "GeometricModel3d"; + } constructor(props: GeometricModel3dProps, iModel: IModelConnection, state?: GeometricModel3dState) { super(props, iModel, state); @@ -244,9 +283,13 @@ export class GeometricModel3dState extends GeometricModelState { } /** @internal */ - public get is3d(): boolean { return true; } + public get is3d(): boolean { + return true; + } /** @internal */ - public override get asGeometricModel3d(): GeometricModel3dState { return this; } + public override get asGeometricModel3d(): GeometricModel3dState { + return this; + } /** If true, then the elements in this GeometricModel3dState are expected to be in an XY plane. * @note The associated ECProperty was added to the BisCore schema in version 1.0.8 @@ -259,7 +302,9 @@ export class GeometricModel3dState extends GeometricModelState { public readonly isNotSpatiallyLocated: boolean; /** If true, then the elements in this GeometricModel3dState are in real-world coordinates and will be in the spatial index. */ - public get isSpatiallyLocated(): boolean { return !this.isNotSpatiallyLocated; } + public get isSpatiallyLocated(): boolean { + return !this.isNotSpatiallyLocated; + } } /** Represents the front-end state of a [SheetModel]($backend). @@ -267,7 +312,9 @@ export class GeometricModel3dState extends GeometricModelState { * @extensions */ export class SheetModelState extends GeometricModel2dState { - public static override get className() { return "SheetModel"; } + public static override get className() { + return "SheetModel"; + } } /** Represents the front-end state of a [SpatialModel]($backend). @@ -278,10 +325,14 @@ export class SpatialModelState extends GeometricModel3dState { /** If this is a reality model, provides access to a list of available spatial classifiers that can be applied to it. */ public readonly classifiers?: SpatialClassifiersState; - public static override get className() { return "SpatialModel"; } + public static override get className() { + return "SpatialModel"; + } /** @internal */ - public override get asSpatialModel(): SpatialModelState { return this; } + public override get asSpatialModel(): SpatialModelState { + return this; + } public constructor(props: ModelProps, iModel: IModelConnection, state?: SpatialModelState) { super(props, iModel, state); @@ -300,7 +351,9 @@ export class SpatialModelState extends GeometricModel3dState { * @extensions */ export class PhysicalModelState extends SpatialModelState { - public static override get className() { return "PhysicalModel"; } + public static override get className() { + return "PhysicalModel"; + } } /** Represents the front-end state of a [SpatialLocationModel]($backend). @@ -308,7 +361,9 @@ export class PhysicalModelState extends SpatialModelState { * @extensions */ export class SpatialLocationModelState extends SpatialModelState { - public static override get className() { return "SpatialLocationModel"; } + public static override get className() { + return "SpatialLocationModel"; + } } /** Represents the front-end state of a [DrawingModel]($backend). @@ -316,7 +371,9 @@ export class SpatialLocationModelState extends SpatialModelState { * @extensions */ export class DrawingModelState extends GeometricModel2dState { - public static override get className() { return "DrawingModel"; } + public static override get className() { + return "DrawingModel"; + } } /** Represents the front-end state of a [SectionDrawingModel]($backend). @@ -324,5 +381,7 @@ export class DrawingModelState extends GeometricModel2dState { * @extensions */ export class SectionDrawingModelState extends DrawingModelState { - public static override get className() { return "SectionDrawingModel"; } + public static override get className() { + return "SectionDrawingModel"; + } } diff --git a/core/frontend/src/NativeApp.ts b/core/frontend/src/NativeApp.ts index f8be7ebf4e0b..d7133b469145 100644 --- a/core/frontend/src/NativeApp.ts +++ b/core/frontend/src/NativeApp.ts @@ -8,29 +8,40 @@ import { AsyncMethodsOf, BeEvent, GuidString, Logger, PromiseReturnType } from "@itwin/core-bentley"; import { - BriefcaseDownloader, BriefcaseProps, IModelVersion, InternetConnectivityStatus, IpcSocketFrontend, LocalBriefcaseProps, - NativeAppFunctions, nativeAppIpcStrings, NativeAppNotifications, OverriddenBy, - RemoveFunction, RequestNewBriefcaseProps, StorageValue, SyncMode, + BriefcaseDownloader, + BriefcaseProps, + IModelVersion, + InternetConnectivityStatus, + IpcSocketFrontend, + LocalBriefcaseProps, + NativeAppFunctions, + nativeAppIpcStrings, + NativeAppNotifications, + OverriddenBy, + RemoveFunction, + RequestNewBriefcaseProps, + StorageValue, + SyncMode, } from "@itwin/core-common"; -import { ProgressCallback } from "./request/Request"; +import { OnDownloadProgress } from "./BriefcaseConnection"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; +import { _callIpcChannel } from "./common/internal/Symbols"; import { IpcApp, IpcAppOptions, NotificationHandler } from "./IpcApp"; import { NativeAppLogger } from "./NativeAppLogger"; -import { OnDownloadProgress } from "./BriefcaseConnection"; -import { _callIpcChannel } from "./common/internal/Symbols"; +import { ProgressCallback } from "./request/Request"; /** Properties for specifying the BriefcaseId for downloading. May either specify a BriefcaseId directly (preferable) or, for * backwards compatibility, a [SyncMode]($common). If [SyncMode.PullAndPush]($common) is supplied, a new briefcaseId will be acquired. * @public */ export type DownloadBriefcaseId = - { syncMode?: SyncMode, briefcaseId?: never } | - { briefcaseId: number, syncMode?: never }; + | { syncMode?: SyncMode, briefcaseId?: never } + | { briefcaseId: number, syncMode?: never }; /** -* Options to download a briefcase -* @public -*/ + * Options to download a briefcase + * @public + */ export type DownloadBriefcaseOptions = DownloadBriefcaseId & { /** the full path for the briefcase file */ fileName?: string; @@ -42,7 +53,9 @@ export type DownloadBriefcaseOptions = DownloadBriefcaseId & { /** NativeApp notifications from backend */ class NativeAppNotifyHandler extends NotificationHandler implements NativeAppNotifications { - public get channelName() { return nativeAppIpcStrings.notifyChannel; } + public get channelName() { + return nativeAppIpcStrings.notifyChannel; + } public notifyInternetConnectivityChanged(status: InternetConnectivityStatus) { Logger.logInfo(FrontendLoggerCategory.NativeApp, "Internet connectivity changed"); NativeApp.onInternetConnectivityChanged.raiseEvent(status); @@ -106,7 +119,9 @@ export class NativeApp { return this.nativeAppIpc.overrideInternetConnectivity(OverriddenBy.User, status); } private static _isValid = false; - public static get isValid(): boolean { return this._isValid; } + public static get isValid(): boolean { + return this._isValid; + } /** * This is called by either ElectronApp.startup or MobileApp.startup - it should not be called directly @@ -123,7 +138,10 @@ export class NativeApp { // initialize current online state. if (window.navigator.onLine) { - await this.setConnectivity(OverriddenBy.Browser, window.navigator.onLine ? InternetConnectivityStatus.Online : InternetConnectivityStatus.Offline); + await this.setConnectivity( + OverriddenBy.Browser, + window.navigator.onLine ? InternetConnectivityStatus.Online : InternetConnectivityStatus.Offline, + ); } } @@ -136,15 +154,24 @@ export class NativeApp { this._isValid = false; } - public static async requestDownloadBriefcase(iTwinId: string, iModelId: string, downloadOptions: DownloadBriefcaseOptions, - asOf?: IModelVersion): Promise; + public static async requestDownloadBriefcase( + iTwinId: string, + iModelId: string, + downloadOptions: DownloadBriefcaseOptions, + asOf?: IModelVersion, + ): Promise; /** * @deprecated in 3.6. `progress` argument is now deprecated, use [[DownloadBriefcaseOptions.progressCallback]] instead. */ - public static async requestDownloadBriefcase(iTwinId: string, iModelId: string, downloadOptions: DownloadBriefcaseOptions, + public static async requestDownloadBriefcase( + iTwinId: string, + iModelId: string, + downloadOptions: DownloadBriefcaseOptions, // eslint-disable-next-line @typescript-eslint/unified-signatures, deprecation/deprecation - asOf?: IModelVersion, progress?: ProgressCallback): Promise; + asOf?: IModelVersion, + progress?: ProgressCallback, + ): Promise; public static async requestDownloadBriefcase( iTwinId: string, @@ -155,7 +182,7 @@ export class NativeApp { ): Promise { const shouldReportProgress = !!progress || !!downloadOptions.progressCallback; - let stopProgressEvents = () => { }; + let stopProgressEvents = () => {}; if (shouldReportProgress) { const handleProgress = (_evt: Event, data: { loaded: number, total: number }) => { progress?.(data); @@ -165,7 +192,8 @@ export class NativeApp { stopProgressEvents = IpcApp.addListener(`nativeApp.progress-${iModelId}`, handleProgress); } - const briefcaseId = (undefined !== downloadOptions.briefcaseId) ? downloadOptions.briefcaseId : + const briefcaseId = (undefined !== downloadOptions.briefcaseId) ? + downloadOptions.briefcaseId : (downloadOptions.syncMode === SyncMode.PullOnly ? 0 : await this.nativeAppIpc.acquireNewBriefcaseId(iModelId)); const fileName = downloadOptions.fileName ?? await this.getBriefcaseFileName({ briefcaseId, iModelId }); @@ -245,7 +273,7 @@ export class NativeApp { * @public */ export class Storage { - constructor(public readonly id: string) { } + constructor(public readonly id: string) {} /** get the type of a value for a key, or undefined if not present. */ public async getValueType(key: string): Promise<"number" | "string" | "boolean" | "Uint8Array" | "null" | undefined> { diff --git a/core/frontend/src/NoRenderApp.ts b/core/frontend/src/NoRenderApp.ts index af497be68431..55ac4d21e5d4 100644 --- a/core/frontend/src/NoRenderApp.ts +++ b/core/frontend/src/NoRenderApp.ts @@ -7,12 +7,12 @@ */ import { EmptyLocalization } from "@itwin/core-common"; +import { _implementationProhibited } from "./common/internal/Symbols"; +import { ViewRect } from "./common/ViewRect"; import { IModelApp, IModelAppOptions } from "./IModelApp"; import { AnimationBranchStates } from "./render/GraphicBranch"; import { RenderSystem } from "./render/RenderSystem"; import { RenderTarget } from "./render/RenderTarget"; -import { ViewRect } from "./common/ViewRect"; -import { _implementationProhibited } from "./common/internal/Symbols"; /** * A RenderTarget for applications that must run in environments where WebGL is not present. @@ -21,30 +21,44 @@ import { _implementationProhibited } from "./common/internal/Symbols"; */ export class NullTarget extends RenderTarget { protected override readonly [_implementationProhibited] = undefined; - public get analysisFraction(): number { return 0; } - public set analysisFraction(_fraction: number) { } - public get renderSystem() { return undefined as any; } - public get viewRect(): ViewRect { return new ViewRect(); } - public get wantInvertBlackBackground(): boolean { return false; } - public override get animationBranches(): AnimationBranchStates | undefined { return undefined; } - public override set animationBranches(_branches: AnimationBranchStates | undefined) { } - public onDestroy(): void { } - public override reset(): void { } - public changeScene(): void { } - public changeDynamics(): void { } - public changeDecorations(): void { } - public changeRenderPlan(): void { } - public drawFrame(_sceneMilSecElapsed?: number): void { } - public override overrideFeatureSymbology(): void { } - public override setHiliteSet(): void { } - public override setFlashed(): void { } - public setViewRect(): void { } - public override onResized(): void { } - public override dispose(): void { } - public updateViewRect(): boolean { return false; } - public readPixels(): void { } - public get screenSpaceEffects(): Iterable { return []; } - public set screenSpaceEffects(_effects: Iterable) { } + public get analysisFraction(): number { + return 0; + } + public set analysisFraction(_fraction: number) {} + public get renderSystem() { + return undefined as any; + } + public get viewRect(): ViewRect { + return new ViewRect(); + } + public get wantInvertBlackBackground(): boolean { + return false; + } + public override get animationBranches(): AnimationBranchStates | undefined { + return undefined; + } + public override set animationBranches(_branches: AnimationBranchStates | undefined) {} + public onDestroy(): void {} + public override reset(): void {} + public changeScene(): void {} + public changeDynamics(): void {} + public changeDecorations(): void {} + public changeRenderPlan(): void {} + public drawFrame(_sceneMilSecElapsed?: number): void {} + public override overrideFeatureSymbology(): void {} + public override setHiliteSet(): void {} + public override setFlashed(): void {} + public setViewRect(): void {} + public override onResized(): void {} + public override dispose(): void {} + public updateViewRect(): boolean { + return false; + } + public readPixels(): void {} + public get screenSpaceEffects(): Iterable { + return []; + } + public set screenSpaceEffects(_effects: Iterable) {} } /** @@ -53,18 +67,40 @@ export class NullTarget extends RenderTarget { * @internal */ export class NullRenderSystem extends RenderSystem { - public get isValid(): boolean { return false; } - public doIdleWork(): boolean { return false; } - public createTarget() { return new NullTarget(); } - public createOffscreenTarget() { return new NullTarget(); } - public createGraphic() { return undefined as any; } - public createGraphicList() { return undefined as any; } - public createGraphicBranch() { return undefined as any; } - public createBatch() { return undefined as any; } - public dispose() { } - public constructor() { super(); } - public override createRenderGraphic() { return undefined; } - public override createGraphicFromTemplate() { return undefined as any; } + public get isValid(): boolean { + return false; + } + public doIdleWork(): boolean { + return false; + } + public createTarget() { + return new NullTarget(); + } + public createOffscreenTarget() { + return new NullTarget(); + } + public createGraphic() { + return undefined as any; + } + public createGraphicList() { + return undefined as any; + } + public createGraphicBranch() { + return undefined as any; + } + public createBatch() { + return undefined as any; + } + public dispose() {} + public constructor() { + super(); + } + public override createRenderGraphic() { + return undefined; + } + public override createGraphicFromTemplate() { + return undefined as any; + } } /** A utility class intended for applications (primarily test-runners) that run in environments that lack support for WebGL. diff --git a/core/frontend/src/NotificationManager.ts b/core/frontend/src/NotificationManager.ts index 58ff90bae069..57031bd5fd8f 100644 --- a/core/frontend/src/NotificationManager.ts +++ b/core/frontend/src/NotificationManager.ts @@ -5,9 +5,9 @@ /** @packageDocumentation * @module Notifications */ +import { DisplayMessageType, MessagePresenter, MessageSeverity, RelativePosition } from "@itwin/appui-abstract"; import { BeDuration } from "@itwin/core-bentley"; import { Point2d, XAndY } from "@itwin/core-geometry"; -import { DisplayMessageType, MessagePresenter, MessageSeverity, RelativePosition } from "@itwin/appui-abstract"; import { IModelApp } from "./IModelApp"; import { ToolAssistanceInstructions } from "./tools/ToolAssistance"; @@ -81,11 +81,11 @@ export enum MessageBoxType { * @extensions */ export enum MessageBoxIconType { - NoSymbol = 0, // Means Don't draw Symbol - Information = 1, // Lower Case i - Question = 2, // Question Mark - Warning = 3, // Exclamation Point - Critical = 4, // Stop Sign + NoSymbol = 0, // Means Don't draw Symbol + Information = 1, // Lower Case i + Question = 2, // Question Mark + Warning = 3, // Exclamation Point + Critical = 4, // Stop Sign Success = 5, // check mark } @@ -135,8 +135,13 @@ export class NotifyMessageDetails { * @param msgType The type of message. Defaults to Toast. * @param openAlert Whether an alert box should be displayed or not, and if so what kind. */ - public constructor(public priority: OutputMessagePriority, public briefMessage: HTMLElement | string, - public detailedMessage?: HTMLElement | string, public msgType = OutputMessageType.Toast, public openAlert = OutputMessageAlert.None) { } + public constructor( + public priority: OutputMessagePriority, + public briefMessage: HTMLElement | string, + public detailedMessage?: HTMLElement | string, + public msgType = OutputMessageType.Toast, + public openAlert = OutputMessageAlert.None, + ) {} /** Set OutputMessageType.Pointer message details. * @param viewport Viewport over which to display the Pointer type message. @@ -172,13 +177,22 @@ export class ActivityMessageDetails { * @param supportsCancellation Indicates whether to show the Cancel button, giving the user the ability to cancel the operation. * @param showDialogInitially Indicates whether to show the activity message dialog initially. User can click status bar to open it. */ - public constructor(public showProgressBar: boolean, public showPercentInMessage: boolean, public supportsCancellation: boolean, public showDialogInitially: boolean = true) { } + public constructor( + public showProgressBar: boolean, + public showPercentInMessage: boolean, + public supportsCancellation: boolean, + public showDialogInitially: boolean = true, + ) {} /** Called from NotificationAdmin when the user cancels the activity. */ - public onActivityCancelled() { this.wasCancelled = true; } + public onActivityCancelled() { + this.wasCancelled = true; + } /** Called from NotificationAdmin when the activity completes successfully. */ - public onActivityCompleted() { this.wasCancelled = false; } + public onActivityCompleted() { + this.wasCancelled = false; + } } /** The NotificationManager controls the interaction with the user for prompts, error messages, and alert dialogs. @@ -193,15 +207,17 @@ export class NotificationManager implements MessagePresenter { /** Output a prompt, given a localization key. * @param key The key of the localized string with the prompt message. */ - public outputPromptByKey(key: string) { this.outputPrompt(IModelApp.localization.getLocalizedString(key)); } + public outputPromptByKey(key: string) { + this.outputPrompt(IModelApp.localization.getLocalizedString(key)); + } /** Output a localized prompt to the user. A 'prompt' indicates an action the user should take to proceed. * @param _prompt The localized string with the prompt message. */ - public outputPrompt(_prompt: string) { } + public outputPrompt(_prompt: string) {} /** Output a message and/or alert to the user. */ - public outputMessage(_message: NotifyMessageDetails) { } + public outputMessage(_message: NotifyMessageDetails) {} /** Output a MessageBox and wait for response from the user. * @param _mbType The MessageBox type. @@ -209,14 +225,18 @@ export class NotificationManager implements MessagePresenter { * @param _icon The MessageBox icon type. * @return the response from the user. */ - public async openMessageBox(_mbType: MessageBoxType, _message: HTMLElement | string, _icon: MessageBoxIconType): Promise { return MessageBoxValue.Ok; } + public async openMessageBox(_mbType: MessageBoxType, _message: HTMLElement | string, _icon: MessageBoxIconType): Promise { + return MessageBoxValue.Ok; + } /** * Set up for activity messages. * @param _details The activity message details. * @return true if the message was displayed, false if an invalid priority is specified. */ - public setupActivityMessage(_details: ActivityMessageDetails) { return true; } + public setupActivityMessage(_details: ActivityMessageDetails) { + return true; + } /** * Output an activity message to the user. @@ -224,23 +244,31 @@ export class NotificationManager implements MessagePresenter { * @param _percentComplete The percentage of completion. * @return true if the message was displayed, false if the message could not be displayed. */ - public outputActivityMessage(_messageText: HTMLElement | string, _percentComplete: number) { return true; } + public outputActivityMessage(_messageText: HTMLElement | string, _percentComplete: number) { + return true; + } /** * End an activity message. * @param _reason The reason for the end of the Activity Message. * @return true if the message was ended successfully, false if the activityMessage could not be ended. */ - public endActivityMessage(_reason: ActivityMessageEndReason) { return true; } + public endActivityMessage(_reason: ActivityMessageEndReason) { + return true; + } /** Return true if _showTooltip has an implementation and will display a tooltip. */ - public get isToolTipSupported(): boolean { return false; } + public get isToolTipSupported(): boolean { + return false; + } /** Return true if the tooltip is currently open. */ - public get isToolTipOpen(): boolean { return false; } + public get isToolTipOpen(): boolean { + return false; + } /** Implement to display a tooltip message at the specified location. */ - protected _showToolTip(_htmlElement: HTMLElement, _message: HTMLElement | string, _location?: XAndY, _options?: ToolTipOptions): void { } + protected _showToolTip(_htmlElement: HTMLElement, _message: HTMLElement | string, _location?: XAndY, _options?: ToolTipOptions): void {} /** Show a tooltip window. Saves tooltip location for AccuSnap to test if cursor has moved far enough away to close tooltip. * @param htmlElement The HTMLElement that anchors the toolTip. @@ -257,19 +285,19 @@ export class NotificationManager implements MessagePresenter { } /** Clear the tooltip if it is currently open. */ - public clearToolTip(): void { } + public clearToolTip(): void {} /** Update message position created with [[OutputMessageType.Pointer]]. * @param displayPoint Point at which to display the Pointer type message. * @param relativePosition Position relative to displayPoint at which to display the Pointer type message. */ - public updatePointerMessage(_displayPoint: XAndY, _relativePosition = RelativePosition.TopRight): void { } + public updatePointerMessage(_displayPoint: XAndY, _relativePosition = RelativePosition.TopRight): void {} /** Close message created with [[OutputMessageType.Pointer]]. */ - public closePointerMessage(): void { } + public closePointerMessage(): void {} /** Close message created with [[OutputMessageType.InputField]]. */ - public closeInputFieldMessage(): void { } + public closeInputFieldMessage(): void {} /** Setup tool assistance instructions for a tool. The instructions include the main instruction, which includes the current prompt. * @param instructions The tool assistance instructions. @@ -285,8 +313,18 @@ export class NotificationManager implements MessagePresenter { * @param detailedMessage An optional comprehensive message that explains the issue in detail and potentially offers a solution. * @param messageType The type of message. Defaults to Toast. */ - public displayMessage(severity: MessageSeverity, briefMessage: HTMLElement | string, detailedMessage?: HTMLElement | string, messageType?: DisplayMessageType): void { - const details = new NotifyMessageDetails(this.convertSeverityToPriority(severity), briefMessage, detailedMessage, this.convertMessageType(messageType)); + public displayMessage( + severity: MessageSeverity, + briefMessage: HTMLElement | string, + detailedMessage?: HTMLElement | string, + messageType?: DisplayMessageType, + ): void { + const details = new NotifyMessageDetails( + this.convertSeverityToPriority(severity), + briefMessage, + detailedMessage, + this.convertMessageType(messageType), + ); this.outputMessage(details); } @@ -297,7 +335,12 @@ export class NotificationManager implements MessagePresenter { * @param briefMessage A short message that conveys the simplest explanation of the issue. * @param detailedMessage An optional comprehensive message that explains the issue in detail and potentially offers a solution. */ - public displayInputFieldMessage(inputField: HTMLElement, severity: MessageSeverity, briefMessage: HTMLElement | string, detailedMessage?: HTMLElement | string): void { + public displayInputFieldMessage( + inputField: HTMLElement, + severity: MessageSeverity, + briefMessage: HTMLElement | string, + detailedMessage?: HTMLElement | string, + ): void { const details = new NotifyMessageDetails(this.convertSeverityToPriority(severity), briefMessage, detailedMessage); details.setInputFieldTypeDetails(inputField); this.outputMessage(details); @@ -333,5 +376,4 @@ export class NotificationManager implements MessagePresenter { return undefined; } } - } diff --git a/core/frontend/src/PerModelCategoryVisibility.ts b/core/frontend/src/PerModelCategoryVisibility.ts index 535807c02603..544a0a68ed55 100644 --- a/core/frontend/src/PerModelCategoryVisibility.ts +++ b/core/frontend/src/PerModelCategoryVisibility.ts @@ -64,7 +64,7 @@ export namespace PerModelCategoryVisibility { /** Describes a set of [[PerModelCategoryVisibility.Overrides]]. * @see [[PerModelCategoryVisibility.Overrides.setOverrides]]. * @beta - */ + */ export interface Props { /** The id of the model to which the overrides apply. */ modelId: string; @@ -175,7 +175,7 @@ class PerModelCategoryVisibilityOverrides extends SortedArray treeRef.treeOwner.load() !== undefined); maskRange.clone(this._maskRange); - } else // If already loaded, just set the maskRange to the saved maskRange. + } + // If already loaded, just set the maskRange to the saved maskRange. + else this._maskRange.clone(maskRange); return this._allLoaded ? this._tileTreeRefs : undefined; } // Returns any potential FeatureSymbology overrides for drawing the planar clip mask. - public getPlanarClipMaskSymbologyOverrides(context: SceneContext, featureSymbologySource: FeatureSymbology.Source): FeatureSymbology.Overrides | undefined { + public getPlanarClipMaskSymbologyOverrides( + context: SceneContext, + featureSymbologySource: FeatureSymbology.Source, + ): FeatureSymbology.Overrides | undefined { this._usingViewportOverrides = false; // First obtain a list of models that will need to be turned off for drawing the planar clip mask (only used for batched tile trees). - const overrideModels = context.viewport.view.isSpatialView() ? context.viewport.view.getModelsNotInMask(this.settings.modelIds, PlanarClipMaskMode.Priority === this.settings.mode) : undefined; + const overrideModels = context.viewport.view.isSpatialView() + ? context.viewport.view.getModelsNotInMask(this.settings.modelIds, PlanarClipMaskMode.Priority === this.settings.mode) + : undefined; const noSubCategoryOrElementIds = !this.settings.subCategoryOrElementIds; if (noSubCategoryOrElementIds && !overrideModels) return undefined; - const ovrBasedOnContext = PlanarClipMaskMode.Priority === this.settings.mode || PlanarClipMaskMode.Models === this.settings.mode || noSubCategoryOrElementIds; + const ovrBasedOnContext = PlanarClipMaskMode.Priority === this.settings.mode || PlanarClipMaskMode.Models === this.settings.mode || + noSubCategoryOrElementIds; const viewport = overrideModels && ovrBasedOnContext ? context.viewport : undefined; const overrides = FeatureSymbology.Overrides.withSource(featureSymbologySource, viewport); @@ -96,7 +106,7 @@ export class PlanarClipMaskState { // For Priority or Models mode, we need to start with the current overrides and modify them if (ovrBasedOnContext) { this._usingViewportOverrides = true; // Set flag to use listener since context.viewport might change afterwards. - overrides.addInvisibleElementOverridesToNeverDrawn(); // need this for fully trans element overrides to not participate in mask + overrides.addInvisibleElementOverridesToNeverDrawn(); // need this for fully trans element overrides to not participate in mask overrideModels.forEach((modelId: string) => { overrides.override({ modelId, appearance: appOff, onConflict: "replace" }); }); diff --git a/core/frontend/src/RealityDataSource.ts b/core/frontend/src/RealityDataSource.ts index a0e4893d84ce..bb837bb04a4e 100644 --- a/core/frontend/src/RealityDataSource.ts +++ b/core/frontend/src/RealityDataSource.ts @@ -6,14 +6,22 @@ * @module Tiles */ import { BentleyError, GuidString, Logger, LoggingMetaData, RealityDataStatus } from "@itwin/core-bentley"; -import { Cartographic, EcefLocation, OrbitGtBlobProps, RealityData, RealityDataFormat, RealityDataProvider, RealityDataSourceKey } from "@itwin/core-common"; +import { + Cartographic, + EcefLocation, + OrbitGtBlobProps, + RealityData, + RealityDataFormat, + RealityDataProvider, + RealityDataSourceKey, +} from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; -import { CesiumIonAssetProvider, ContextShareProvider, getCesiumAssetUrl } from "./tile/internal"; -import { RealityDataSourceTilesetUrlImpl } from "./RealityDataSourceTilesetUrlImpl"; -import { RealityDataSourceContextShareImpl } from "./RealityDataSourceContextShareImpl"; -import { RealityDataSourceCesiumIonAssetImpl } from "./RealityDataSourceCesiumIonAssetImpl"; import { IModelApp } from "./IModelApp"; -import { Range3d } from "@itwin/core-geometry"; +import { RealityDataSourceCesiumIonAssetImpl } from "./RealityDataSourceCesiumIonAssetImpl"; +import { RealityDataSourceContextShareImpl } from "./RealityDataSourceContextShareImpl"; +import { RealityDataSourceTilesetUrlImpl } from "./RealityDataSourceTilesetUrlImpl"; +import { CesiumIonAssetProvider, ContextShareProvider, getCesiumAssetUrl } from "./tile/internal"; const loggerCategory: string = FrontendLoggerCategory.RealityData; @@ -132,7 +140,7 @@ export namespace RealityDataSource { let format = inputFormat ? inputFormat : RealityDataFormat.fromUrl(tilesetUrl); if (CesiumIonAssetProvider.isProviderUrl(tilesetUrl)) { const provider = RealityDataProvider.CesiumIonAsset; - let cesiumIonAssetKey: RealityDataSourceKey = { provider, format, id: CesiumIonAssetProvider.osmBuildingId }; // default OSM building + let cesiumIonAssetKey: RealityDataSourceKey = { provider, format, id: CesiumIonAssetProvider.osmBuildingId }; // default OSM building // Parse URL to extract possible asset id and key if provided const cesiumAsset = CesiumIonAssetProvider.parseCesiumUrl(tilesetUrl); if (cesiumAsset) { @@ -164,7 +172,11 @@ export namespace RealityDataSource { return contextShareKey; } /** @alpha - OrbitGtBlobProps is alpha */ - export function createKeyFromOrbitGtBlobProps(orbitGtBlob: OrbitGtBlobProps, inputProvider?: RealityDataProvider, inputFormat?: RealityDataFormat): RealityDataSourceKey { + export function createKeyFromOrbitGtBlobProps( + orbitGtBlob: OrbitGtBlobProps, + inputProvider?: RealityDataProvider, + inputFormat?: RealityDataFormat, + ): RealityDataSourceKey { const format = inputFormat ? inputFormat : RealityDataFormat.OPC; if (orbitGtBlob.blobFileName && orbitGtBlob.blobFileName.toLowerCase().startsWith("http")) { return RealityDataSource.createKeyFromBlobUrl(orbitGtBlob.blobFileName, inputProvider, format); @@ -192,8 +204,8 @@ export namespace RealityDataSource { } /** @internal - Is used by "fdt attach cesium asset" keyin*/ export function createCesiumIonAssetKey(osmAssetId: number, requestKey: string): RealityDataSourceKey { - const id = getCesiumAssetUrl(osmAssetId,requestKey); - return {provider: RealityDataProvider.CesiumIonAsset, format: RealityDataFormat.ThreeDTile, id}; + const id = getCesiumAssetUrl(osmAssetId, requestKey); + return { provider: RealityDataProvider.CesiumIonAsset, format: RealityDataFormat.ThreeDTile, id }; } /** Return an instance of a RealityDataSource from a source key. * There will aways be only one reality data RealityDataSource for a corresponding reality data source key. diff --git a/core/frontend/src/RealityDataSourceCesiumIonAssetImpl.ts b/core/frontend/src/RealityDataSourceCesiumIonAssetImpl.ts index 302775b272d4..b55c5f8035ac 100644 --- a/core/frontend/src/RealityDataSourceCesiumIonAssetImpl.ts +++ b/core/frontend/src/RealityDataSourceCesiumIonAssetImpl.ts @@ -5,19 +5,19 @@ /** @packageDocumentation * @module Tiles */ -import { request } from "./request/Request"; import { assert, BentleyStatus, GuidString } from "@itwin/core-bentley"; import { IModelError, RealityData, RealityDataProvider, RealityDataSourceKey, RealityDataSourceProps } from "@itwin/core-common"; -import { CesiumIonAssetProvider, getCesiumAccessTokenAndEndpointUrl, getCesiumAssetUrl, getCesiumOSMBuildingsUrl } from "./tile/internal"; import { PublisherProductInfo, RealityDataSource, SpatialLocationAndExtents } from "./RealityDataSource"; +import { request } from "./request/Request"; +import { CesiumIonAssetProvider, getCesiumAccessTokenAndEndpointUrl, getCesiumAssetUrl, getCesiumOSMBuildingsUrl } from "./tile/internal"; /** This class provides access to the reality data provider services. * It encapsulates access to a reality data weiter it be from local access, http or ProjectWise Context Share. * The key provided at the creation determines if this is ProjectWise Context Share reference. * If not then it is considered local (ex: C:\temp\TileRoot.json) or plain http access (http://someserver.com/data/TileRoot.json) * There is a one to one relationship between a reality data and the instances of present class. -* @internal -*/ + * @internal + */ export class RealityDataSourceCesiumIonAssetImpl implements RealityDataSource { public readonly key: RealityDataSourceKey; /** The URL that supplies the 3d tiles for displaying the reality model. */ @@ -57,7 +57,7 @@ export class RealityDataSourceCesiumIonAssetImpl implements RealityDataSource { /** * Returns Reality Data if available - */ + */ public get realityData(): RealityData | undefined { return undefined; } @@ -171,4 +171,3 @@ export class RealityDataSourceCesiumIonAssetImpl implements RealityDataSource { return publisherInfo; } } - diff --git a/core/frontend/src/RealityDataSourceContextShareImpl.ts b/core/frontend/src/RealityDataSourceContextShareImpl.ts index c421d449fc5b..a9fa1cbfe9c8 100644 --- a/core/frontend/src/RealityDataSourceContextShareImpl.ts +++ b/core/frontend/src/RealityDataSourceContextShareImpl.ts @@ -5,11 +5,11 @@ /** @packageDocumentation * @module Tiles */ -import { request } from "./request/Request"; import { AccessToken, assert, GuidString, Logger } from "@itwin/core-bentley"; import { RealityData, RealityDataFormat, RealityDataProvider, RealityDataSourceKey, RealityDataSourceProps } from "@itwin/core-common"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; import { IModelApp } from "./IModelApp"; +import { request } from "./request/Request"; import { PublisherProductInfo, RealityDataSource, SpatialLocationAndExtents } from "./RealityDataSource"; import { OPCFormatInterpreter, ThreeDTileFormatInterpreter } from "./tile/internal"; @@ -19,8 +19,8 @@ import { OPCFormatInterpreter, ThreeDTileFormatInterpreter } from "./tile/intern * The key provided at the creation determines if this is ProjectWise Context Share reference. * If not then it is considered local (ex: C:\temp\TileRoot.json) or plain http access (http://someserver.com/data/TileRoot.json) * There is a one to one relationship between a reality data and the instances of present class. -* @internal -*/ + * @internal + */ export class RealityDataSourceContextShareImpl implements RealityDataSource { public readonly key: RealityDataSourceKey; /** The URL that supplies the 3d tiles for displaying the reality model. */ @@ -62,7 +62,7 @@ export class RealityDataSourceContextShareImpl implements RealityDataSource { } /** * Returns Reality Data if available - */ + */ public get realityData(): RealityData | undefined { return this._rd; } @@ -85,7 +85,9 @@ export class RealityDataSourceContextShareImpl implements RealityDataSource { const token = await IModelApp.getAccessToken(); if (token && this.realityDataId) { if (undefined === IModelApp.realityDataAccess) - throw new Error("Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess."); + throw new Error( + "Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess.", + ); this._rd = await IModelApp.realityDataAccess.getRealityData(token, iTwinId, this.realityDataId); // A reality data that has not root document set should not be considered. const rootDocument: string = this._rd.rootDocument ?? ""; @@ -129,7 +131,9 @@ export class RealityDataSourceContextShareImpl implements RealityDataSource { const rdSourceKey = this.key; // we need to resolve tilesetURl from realityDataId and iTwinId if (undefined === IModelApp.realityDataAccess) - throw new Error("Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess."); + throw new Error( + "Missing an implementation of RealityDataAccess on IModelApp, it is required to access reality data. Please provide an implementation to the IModelApp.startup using IModelAppOptions.realityDataAccess.", + ); try { const resolvedITwinId = iTwinId ? iTwinId : rdSourceKey.iTwinId; @@ -246,4 +250,3 @@ export class RealityDataSourceContextShareImpl implements RealityDataSource { return publisherInfo; } } - diff --git a/core/frontend/src/RealityDataSourceTilesetUrlImpl.ts b/core/frontend/src/RealityDataSourceTilesetUrlImpl.ts index 513cdec06c68..36574e11090c 100644 --- a/core/frontend/src/RealityDataSourceTilesetUrlImpl.ts +++ b/core/frontend/src/RealityDataSourceTilesetUrlImpl.ts @@ -8,8 +8,8 @@ import { assert, BentleyStatus, GuidString } from "@itwin/core-bentley"; import { IModelError, RealityData, RealityDataFormat, RealityDataProvider, RealityDataSourceKey, RealityDataSourceProps } from "@itwin/core-common"; -import { request } from "./request/Request"; import { PublisherProductInfo, RealityDataSource, SpatialLocationAndExtents } from "./RealityDataSource"; +import { request } from "./request/Request"; import { ThreeDTileFormatInterpreter } from "./tile/internal"; /** This class provides access to the reality data provider services. @@ -17,8 +17,8 @@ import { ThreeDTileFormatInterpreter } from "./tile/internal"; * The key provided at the creation determines if this is ProjectWise Context Share reference. * If not then it is considered local (ex: C:\temp\TileRoot.json) or plain http access (http://someserver.com/data/TileRoot.json) * There is a one to one relationship between a reality data and the instances of present class. -* @internal -*/ + * @internal + */ export class RealityDataSourceTilesetUrlImpl implements RealityDataSource { public readonly key: RealityDataSourceKey; /** The URL that supplies the 3d tiles for displaying the reality model. */ @@ -50,7 +50,7 @@ export class RealityDataSourceTilesetUrlImpl implements RealityDataSource { } /** * Returns Reality Data if available - */ + */ public get realityData(): RealityData | undefined { return undefined; } @@ -96,7 +96,7 @@ export class RealityDataSourceTilesetUrlImpl implements RealityDataSource { return request(url, "json"); } - private isValidURL(url: string){ + private isValidURL(url: string) { try { new URL(url); } catch (_) { @@ -106,7 +106,7 @@ export class RealityDataSourceTilesetUrlImpl implements RealityDataSource { } /** Returns the tile URL. If the tile path is a full URL, it is returned as is. Otherwise, the base URL is prepended to the tile path. */ - private getTileUrl(tilePath: string){ + private getTileUrl(tilePath: string) { return this.isValidURL(tilePath) ? tilePath : this._baseUrl + tilePath; } @@ -152,4 +152,3 @@ export class RealityDataSourceTilesetUrlImpl implements RealityDataSource { return publisherInfo; } } - diff --git a/core/frontend/src/SelectionSet.ts b/core/frontend/src/SelectionSet.ts index 1d5af30bb4cb..0be9dc7e1b11 100644 --- a/core/frontend/src/SelectionSet.ts +++ b/core/frontend/src/SelectionSet.ts @@ -139,7 +139,9 @@ class HilitedElementIds extends HilitedIds { this.wantSyncWithSelectionSet = syncWithSelectionSet; } - public get wantSyncWithSelectionSet(): boolean { return undefined !== this._removeListener; } + public get wantSyncWithSelectionSet(): boolean { + return undefined !== this._removeListener; + } public set wantSyncWithSelectionSet(want: boolean) { if (want === this.wantSyncWithSelectionSet) return; @@ -210,7 +212,9 @@ export class HiliteSet { public readonly models: Id64.Uint32Set; /** The set of hilited elements. */ - public get elements(): Id64.Uint32Set { return this._elements; } + public get elements(): Id64.Uint32Set { + return this._elements; + } /** Controls how the sets of hilited [[models]] and [[subcategories]] interact with one another. * By default they are treated as a union: a [Feature]($common) is hilited if either its model **or** its subcategory is hilited. @@ -247,8 +251,12 @@ export class HiliteSet { * When turning synchronization off, the contents of the HiliteSet will remain unchanged. * When turning synchronization on, the current contents of the HiliteSet will be preserved, and the contents of the selection set will be added to them. */ - public get wantSyncWithSelectionSet(): boolean { return this._elements.wantSyncWithSelectionSet; } - public set wantSyncWithSelectionSet(want: boolean) { this._elements.wantSyncWithSelectionSet = want; } + public get wantSyncWithSelectionSet(): boolean { + return this._elements.wantSyncWithSelectionSet; + } + public set wantSyncWithSelectionSet(want: boolean) { + this._elements.wantSyncWithSelectionSet = want; + } /** Remove all elements from the hilited set. */ public clear() { @@ -258,7 +266,9 @@ export class HiliteSet { } /** Returns true if nothing is hilited. */ - public get isEmpty(): boolean { return this.elements.isEmpty && this.subcategories.isEmpty && this.models.isEmpty; } + public get isEmpty(): boolean { + return this.elements.isEmpty && this.subcategories.isEmpty && this.models.isEmpty; + } /** Toggle the hilited state of one or more elements. * @param arg the ID(s) of the elements whose state is to be toggled. @@ -291,12 +301,14 @@ export class SelectionSet { /** The IDs of the selected elements. * @note Do not modify this set directly. Instead, use methods like [[SelectionSet.add]]. */ - public get elements(): Set { return this._elements; } + public get elements(): Set { + return this._elements; + } /** Called whenever elements are added or removed from this SelectionSet */ public readonly onChanged = new BeEvent<(ev: SelectionSetEvent) => void>(); - public constructor(public iModel: IModelConnection) { } + public constructor(public iModel: IModelConnection) {} private sendChangedEvent(ev: SelectionSetEvent) { IModelApp.viewManager.onSelectionSetChanged(this.iModel); @@ -304,20 +316,28 @@ export class SelectionSet { } /** Get the number of entries in this selection set. */ - public get size() { return this.elements.size; } + public get size() { + return this.elements.size; + } /** Check whether there are any selected elements. */ - public get isActive() { return this.size !== 0; } + public get isActive() { + return this.size !== 0; + } /** Return true if elemId is in this SelectionSet. * @see [[isSelected]] */ - public has(elemId?: string) { return !!elemId && this.elements.has(elemId); } + public has(elemId?: string) { + return !!elemId && this.elements.has(elemId); + } /** Query whether an Id is in the selection set. * @see [[has]] */ - public isSelected(elemId?: Id64String): boolean { return !!elemId && this.elements.has(elemId); } + public isSelected(elemId?: Id64String): boolean { + return !!elemId && this.elements.has(elemId); + } /** Clear current selection set. * @note raises the [[onChanged]] event with [[SelectionSetEventType.Clear]]. diff --git a/core/frontend/src/SheetViewState.ts b/core/frontend/src/SheetViewState.ts index 06908515e8f8..28c3d70ba48c 100644 --- a/core/frontend/src/SheetViewState.ts +++ b/core/frontend/src/SheetViewState.ts @@ -7,34 +7,63 @@ */ import { assert, CompressedId64Set, dispose, Id64Array, Id64String } from "@itwin/core-bentley"; -import { Angle, ClipShape, ClipVector, Constant, Matrix3d, Point2d, Point3d, PolyfaceBuilder, Range2d, Range3d, StrokeOptions, Transform } from "@itwin/core-geometry"; import { - AxisAlignedBox3d, ColorDef, Feature, FeatureTable, Frustum, Gradient, GraphicParams, HiddenLine, HydrateViewStateRequestProps, HydrateViewStateResponseProps, PackedFeatureTable, Placement2d, SheetProps, - TextureTransparency, ViewAttachmentProps, ViewDefinition2dProps, ViewFlagOverrides, ViewStateProps, + AxisAlignedBox3d, + ColorDef, + Feature, + FeatureTable, + Frustum, + Gradient, + GraphicParams, + HiddenLine, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + PackedFeatureTable, + Placement2d, + SheetProps, + TextureTransparency, + ViewAttachmentProps, + ViewDefinition2dProps, + ViewFlagOverrides, + ViewStateProps, } from "@itwin/core-common"; +import { + Angle, + ClipShape, + ClipVector, + Constant, + Matrix3d, + Point2d, + Point3d, + PolyfaceBuilder, + Range2d, + Range3d, + StrokeOptions, + Transform, +} from "@itwin/core-geometry"; import { CategorySelectorState } from "./CategorySelectorState"; +import { imageBufferToPngDataUrl, openImageDataUrlInNewWindow } from "./common/ImageUtil"; +import { GraphicType } from "./common/render/GraphicType"; +import { ViewRect } from "./common/ViewRect"; +import { CoordSystem } from "./CoordSystem"; import { DisplayStyle2dState } from "./DisplayStyleState"; -import { IModelConnection } from "./IModelConnection"; -import { GraphicBuilder } from "./render/GraphicBuilder"; -import { RenderGraphic } from "./render/RenderGraphic"; -import { GraphicBranch } from "./render/GraphicBranch"; +import { DrawingViewState } from "./DrawingViewState"; import { Frustum2d } from "./Frustum2d"; -import { Scene } from "./render/Scene"; +import { IModelApp } from "./IModelApp"; +import { IModelConnection } from "./IModelConnection"; import { Decorations } from "./render/Decorations"; +import { FeatureSymbology } from "./render/FeatureSymbology"; +import { GraphicBranch } from "./render/GraphicBranch"; +import { GraphicBuilder } from "./render/GraphicBuilder"; import { MockRender } from "./render/MockRender"; import { RenderClipVolume } from "./render/RenderClipVolume"; +import { RenderGraphic } from "./render/RenderGraphic"; import { RenderMemory } from "./render/RenderMemory"; -import { FeatureSymbology } from "./render/FeatureSymbology"; +import { Scene } from "./render/Scene"; +import { createDefaultViewFlagOverrides, DisclosedTileTreeSet, TileGraphicType } from "./tile/internal"; import { DecorateContext, SceneContext } from "./ViewContext"; -import { IModelApp } from "./IModelApp"; -import { CoordSystem } from "./CoordSystem"; import { OffScreenViewport, Viewport } from "./Viewport"; import { AttachToViewportArgs, ComputeDisplayTransformArgs, ViewState, ViewState2d } from "./ViewState"; -import { DrawingViewState } from "./DrawingViewState"; -import { createDefaultViewFlagOverrides, DisclosedTileTreeSet, TileGraphicType } from "./tile/internal"; -import { imageBufferToPngDataUrl, openImageDataUrlInNewWindow } from "./common/ImageUtil"; -import { ViewRect } from "./common/ViewRect"; -import { GraphicType } from "./common/render/GraphicType"; // cSpell:ignore ovrs @@ -60,7 +89,8 @@ class SheetBorder { Point3d.create(0, 0), Point3d.create(width, 0), Point3d.create(width, height), - Point3d.create(0, height)]; + Point3d.create(0, height), + ]; if (context) { context.viewport.worldToViewArray(rect); } @@ -133,7 +163,9 @@ interface ViewAttachmentInfo extends ViewAttachmentProps { class ViewAttachmentsInfo { private _attachments: Id64Array | ViewAttachmentInfo[]; - public get attachments() { return this._attachments; } + public get attachments() { + return this._attachments; + } private constructor(attachments: Id64Array | ViewAttachmentInfo[]) { this._attachments = attachments; @@ -347,14 +379,23 @@ export class SheetViewState extends ViewState2d { return this._attachmentsInfo.toJSON(); } - public static override get className() { return "SheetViewDefinition"; } + public static override get className() { + return "SheetViewDefinition"; + } public static override createFromProps(viewStateData: ViewStateProps, iModel: IModelConnection): SheetViewState { const cat = new CategorySelectorState(viewStateData.categorySelectorProps, iModel); const displayStyleState = new DisplayStyle2dState(viewStateData.displayStyleProps, iModel); // use "new this" so subclasses are correct - return new this(viewStateData.viewDefinitionProps as ViewDefinition2dProps, iModel, cat, displayStyleState, viewStateData.sheetProps!, viewStateData.sheetAttachments!); + return new this( + viewStateData.viewDefinitionProps as ViewDefinition2dProps, + iModel, + cat, + displayStyleState, + viewStateData.sheetProps!, + viewStateData.sheetAttachments!, + ); } public override toProps(): ViewStateProps { @@ -397,11 +438,22 @@ export class SheetViewState extends ViewState2d { } /** @internal */ - public override isDrawingView(): this is DrawingViewState { return false; } + public override isDrawingView(): this is DrawingViewState { + return false; + } /** @internal */ - public override isSheetView(): this is SheetViewState { return true; } - - public constructor(props: ViewDefinition2dProps, iModel: IModelConnection, categories: CategorySelectorState, displayStyle: DisplayStyle2dState, sheetProps: SheetProps, attachments: Id64Array) { + public override isSheetView(): this is SheetViewState { + return true; + } + + public constructor( + props: ViewDefinition2dProps, + iModel: IModelConnection, + categories: CategorySelectorState, + displayStyle: DisplayStyle2dState, + sheetProps: SheetProps, + attachments: Id64Array, + ) { super(props, iModel, categories, displayStyle); if (categories instanceof SheetViewState) { // we are coming from clone... diff --git a/core/frontend/src/SpatialClassifiersState.ts b/core/frontend/src/SpatialClassifiersState.ts index b191621ef635..511386e6c309 100644 --- a/core/frontend/src/SpatialClassifiersState.ts +++ b/core/frontend/src/SpatialClassifiersState.ts @@ -80,4 +80,3 @@ export class SpatialClassifiersState extends SpatialClassifiers { return new SpatialClassifiersState(container); } } - diff --git a/core/frontend/src/SpatialViewState.ts b/core/frontend/src/SpatialViewState.ts index aa2c3b9017a8..8b8e8142306b 100644 --- a/core/frontend/src/SpatialViewState.ts +++ b/core/frontend/src/SpatialViewState.ts @@ -7,17 +7,23 @@ */ import { BeEvent, CompressedId64Set, Id64String, OrderedId64Iterable } from "@itwin/core-bentley"; +import { + AxisAlignedBox3d, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + SpatialViewDefinitionProps, + ViewStateProps, +} from "@itwin/core-common"; import { Constant, Matrix3d, Range3d, XYAndZ } from "@itwin/core-geometry"; -import { AxisAlignedBox3d, HydrateViewStateRequestProps, HydrateViewStateResponseProps, SpatialViewDefinitionProps, ViewStateProps } from "@itwin/core-common"; import { AuxCoordSystemSpatialState, AuxCoordSystemState } from "./AuxCoordSys"; -import { ModelSelectorState } from "./ModelSelectorState"; import { CategorySelectorState } from "./CategorySelectorState"; import { DisplayStyle3dState } from "./DisplayStyleState"; +import { IModelConnection } from "./IModelConnection"; +import { ModelSelectorState } from "./ModelSelectorState"; import { GeometricModel3dState, GeometricModelState } from "./ModelState"; +import { SpatialTileTreeReferences, TileTreeReference } from "./tile/internal"; import { SceneContext } from "./ViewContext"; -import { IModelConnection } from "./IModelConnection"; import { AttachToViewportArgs, ViewState3d } from "./ViewState"; -import { SpatialTileTreeReferences, TileTreeReference } from "./tile/internal"; /** Options supplied to [[SpatialViewState.computeFitRange]]. * @public @@ -33,7 +39,9 @@ export interface ComputeSpatialViewFitRangeOptions { * @extensions */ export class SpatialViewState extends ViewState3d { - public static override get className() { return "SpatialViewDefinition"; } + public static override get className() { + return "SpatialViewDefinition"; + } private readonly _treeRefs: SpatialTileTreeReferences; private _modelSelector: ModelSelectorState; @@ -100,7 +108,13 @@ export class SpatialViewState extends ViewState3d { return props; } - constructor(props: SpatialViewDefinitionProps, iModel: IModelConnection, arg3: CategorySelectorState, displayStyle: DisplayStyle3dState, modelSelector: ModelSelectorState) { + constructor( + props: SpatialViewDefinitionProps, + iModel: IModelConnection, + arg3: CategorySelectorState, + displayStyle: DisplayStyle3dState, + modelSelector: ModelSelectorState, + ) { super(props, iModel, arg3, displayStyle); this._modelSelector = modelSelector; if (arg3 instanceof SpatialViewState) // from clone @@ -110,12 +124,20 @@ export class SpatialViewState extends ViewState3d { } /** @internal */ - public override isSpatialView(): this is SpatialViewState { return true; } + public override isSpatialView(): this is SpatialViewState { + return true; + } - public override equals(other: this): boolean { return super.equals(other) && this.modelSelector.equals(other.modelSelector); } + public override equals(other: this): boolean { + return super.equals(other) && this.modelSelector.equals(other.modelSelector); + } - public override createAuxCoordSystem(acsName: string): AuxCoordSystemState { return AuxCoordSystemSpatialState.createNew(acsName, this.iModel); } - public get defaultExtentLimits() { return { min: Constant.oneMillimeter, max: 3 * Constant.diameterOfEarth }; } // Increased max by 3X to support globe mode. + public override createAuxCoordSystem(acsName: string): AuxCoordSystemState { + return AuxCoordSystemSpatialState.createNew(acsName, this.iModel); + } + public get defaultExtentLimits() { + return { min: Constant.oneMillimeter, max: 3 * Constant.diameterOfEarth }; + } // Increased max by 3X to support globe mode. /** @internal */ public markModelSelectorChanged(): void { @@ -205,10 +227,18 @@ export class SpatialViewState extends ViewState3d { await Promise.all(promises); } - public viewsModel(modelId: Id64String): boolean { return this.modelSelector.containsModel(modelId); } - public clearViewedModels() { this.modelSelector.models.clear(); } - public addViewedModel(id: Id64String) { this.modelSelector.addModels(id); } - public removeViewedModel(id: Id64String) { this.modelSelector.dropModels(id); } + public viewsModel(modelId: Id64String): boolean { + return this.modelSelector.containsModel(modelId); + } + public clearViewedModels() { + this.modelSelector.models.clear(); + } + public addViewedModel(id: Id64String) { + this.modelSelector.addModels(id); + } + public removeViewedModel(id: Id64String) { + this.modelSelector.dropModels(id); + } public forEachModel(func: (model: GeometricModelState) => void) { for (const modelId of this.modelSelector.models) { @@ -252,7 +282,11 @@ export class SpatialViewState extends ViewState3d { * @param which The references to be affected as either a broad category or one or more indices of animated references. * @internal */ - public setTileTreeReferencesDeactivated(modelIds: Id64String | Id64String[] | undefined, deactivated: boolean | undefined, which: "all" | "animated" | "primary" | "section" | number[]): void { + public setTileTreeReferencesDeactivated( + modelIds: Id64String | Id64String[] | undefined, + deactivated: boolean | undefined, + which: "all" | "animated" | "primary" | "section" | number[], + ): void { this._treeRefs.setDeactivated(modelIds, deactivated, which); } @@ -297,9 +331,21 @@ export class SpatialViewState extends ViewState3d { * @extensions */ export class OrthographicViewState extends SpatialViewState { - public static override get className() { return "OrthographicViewDefinition"; } + public static override get className() { + return "OrthographicViewDefinition"; + } - constructor(props: SpatialViewDefinitionProps, iModel: IModelConnection, categories: CategorySelectorState, displayStyle: DisplayStyle3dState, modelSelector: ModelSelectorState) { super(props, iModel, categories, displayStyle, modelSelector); } + constructor( + props: SpatialViewDefinitionProps, + iModel: IModelConnection, + categories: CategorySelectorState, + displayStyle: DisplayStyle3dState, + modelSelector: ModelSelectorState, + ) { + super(props, iModel, categories, displayStyle, modelSelector); + } - public override supportsCamera(): boolean { return false; } + public override supportsCamera(): boolean { + return false; + } } diff --git a/core/frontend/src/Sprites.ts b/core/frontend/src/Sprites.ts index 5f8f19cd3eb8..b053b60013ce 100644 --- a/core/frontend/src/Sprites.ts +++ b/core/frontend/src/Sprites.ts @@ -7,10 +7,10 @@ */ import { Logger } from "@itwin/core-bentley"; -import { Point2d, Point3d, XYAndZ } from "@itwin/core-geometry"; import { ImageSource } from "@itwin/core-common"; +import { Point2d, Point3d, XYAndZ } from "@itwin/core-geometry"; import { FrontendLoggerCategory } from "./common/FrontendLoggerCategory"; -import { imageElementFromImageSource, imageElementFromUrl } from "./common/ImageUtil"; +import { imageElementFromImageSource, imageElementFromUrl } from "./common/ImageUtil"; import { CanvasDecoration } from "./render/CanvasDecoration"; import { DecorateContext } from "./ViewContext"; import { ScreenViewport } from "./Viewport"; @@ -38,9 +38,13 @@ export class Sprite { /** Promise fulfilled when this sprite is loaded. */ public loadPromise: Promise; /** The offset to the middle of this Sprite. If not loaded, value is not meaningful. */ - public get offset(): Point2d { return new Point2d(Math.round(this.size.x) / 2, Math.round(this.size.y / 2)); } + public get offset(): Point2d { + return new Point2d(Math.round(this.size.x) / 2, Math.round(this.size.y / 2)); + } /** Whether this sprite has be successfully loaded. */ - public get isLoaded(): boolean { return undefined !== this.image; } + public get isLoaded(): boolean { + return undefined !== this.image; + } /** construct a Sprite from an ImageSource or a Url * @param src The ImageSource holding an image to create the texture for this Sprite, or the url of the image @@ -79,7 +83,9 @@ export class IconSprites { } /** Empty the cache, disposing all existing Sprites. */ - public static emptyAll() { this._sprites.clear(); } + public static emptyAll() { + this._sprites.clear(); + } } /** A Sprite location. Sprites generally move around on the screen and this object holds the current location @@ -97,7 +103,9 @@ export class SpriteLocation implements CanvasDecoration { * @see [[CanvasDecoration.position]] */ public readonly position = new Point3d(); - public get isActive(): boolean { return this._viewport !== undefined; } + public get isActive(): boolean { + return this._viewport !== undefined; + } /** Activate this SpriteLocation to show a Sprite at a location in a single ScreenViewport. * This call does not display the Sprite. Rather, subsequent calls to [[decorate]] from will show the Sprite. diff --git a/core/frontend/src/StandardView.ts b/core/frontend/src/StandardView.ts index 661d3e58959e..0ded5cc8bc04 100644 --- a/core/frontend/src/StandardView.ts +++ b/core/frontend/src/StandardView.ts @@ -41,13 +41,27 @@ function getMatrices(): Matrix3d[] { standardViewMatrices[StandardViewId.Front] = Matrix3d.createRowValues(1, 0, 0, 0, 0, 1, 0, -1, 0); standardViewMatrices[StandardViewId.Back] = Matrix3d.createRowValues(-1, 0, 0, 0, 0, 1, 0, 1, 0); standardViewMatrices[StandardViewId.Iso] = Matrix3d.createRowValues( - 0.707106781186548, -0.70710678118654757, 0.00000000000000000, - 0.408248290463863, 0.40824829046386302, 0.81649658092772603, - -0.577350269189626, -0.57735026918962573, 0.57735026918962573); + 0.707106781186548, + -0.70710678118654757, + 0.00000000000000000, + 0.408248290463863, + 0.40824829046386302, + 0.81649658092772603, + -0.577350269189626, + -0.57735026918962573, + 0.57735026918962573, + ); standardViewMatrices[StandardViewId.RightIso] = Matrix3d.createRowValues( - 0.707106781186548, 0.70710678118654757, 0.00000000000000000, - -0.408248290463863, 0.40824829046386302, 0.81649658092772603, - 0.577350269189626, -0.57735026918962573, 0.57735026918962573); + 0.707106781186548, + 0.70710678118654757, + 0.00000000000000000, + -0.408248290463863, + 0.40824829046386302, + 0.81649658092772603, + 0.577350269189626, + -0.57735026918962573, + 0.57735026918962573, + ); standardViewMatrices.forEach((mat) => Object.freeze(mat)); return standardViewMatrices; @@ -57,14 +71,30 @@ function getMatrices(): Matrix3d[] { * @public */ export class StandardView { - public static get top(): Matrix3d { return this.getStandardRotation(StandardViewId.Top); } - public static get bottom(): Matrix3d { return this.getStandardRotation(StandardViewId.Bottom); } - public static get left(): Matrix3d { return this.getStandardRotation(StandardViewId.Left); } - public static get right(): Matrix3d { return this.getStandardRotation(StandardViewId.Right); } - public static get front(): Matrix3d { return this.getStandardRotation(StandardViewId.Front); } - public static get back(): Matrix3d { return this.getStandardRotation(StandardViewId.Back); } - public static get iso(): Matrix3d { return this.getStandardRotation(StandardViewId.Iso); } - public static get rightIso(): Matrix3d { return this.getStandardRotation(StandardViewId.RightIso); } + public static get top(): Matrix3d { + return this.getStandardRotation(StandardViewId.Top); + } + public static get bottom(): Matrix3d { + return this.getStandardRotation(StandardViewId.Bottom); + } + public static get left(): Matrix3d { + return this.getStandardRotation(StandardViewId.Left); + } + public static get right(): Matrix3d { + return this.getStandardRotation(StandardViewId.Right); + } + public static get front(): Matrix3d { + return this.getStandardRotation(StandardViewId.Front); + } + public static get back(): Matrix3d { + return this.getStandardRotation(StandardViewId.Back); + } + public static get iso(): Matrix3d { + return this.getStandardRotation(StandardViewId.Iso); + } + public static get rightIso(): Matrix3d { + return this.getStandardRotation(StandardViewId.RightIso); + } /** Obtain a [[Matrix3d]] corresponding to the specified [[StandardViewId]]. * @param id The ID of the desired rotation. diff --git a/core/frontend/src/SubCategoriesCache.ts b/core/frontend/src/SubCategoriesCache.ts index 721735ac89df..84cb556702b1 100644 --- a/core/frontend/src/SubCategoriesCache.ts +++ b/core/frontend/src/SubCategoriesCache.ts @@ -33,13 +33,19 @@ export class SubCategoriesCache { private readonly _imodel: IModelConnection; private _missingAtTimeOfPreload: Id64Set | undefined; - public constructor(imodel: IModelConnection) { this._imodel = imodel; } + public constructor(imodel: IModelConnection) { + this._imodel = imodel; + } /** Get the Ids of all subcategories belonging to the category with the specified Id, or undefined if no such information is present. */ - public getSubCategories(categoryId: string): Id64Set | undefined { return this._byCategoryId.get(categoryId); } + public getSubCategories(categoryId: string): Id64Set | undefined { + return this._byCategoryId.get(categoryId); + } /** Get the base appearance of the subcategory with the specified Id, or undefined if no such information is present. */ - public getSubCategoryAppearance(subCategoryId: Id64String): SubCategoryAppearance | undefined { return this._appearances.get(subCategoryId.toString()); } + public getSubCategoryAppearance(subCategoryId: Id64String): SubCategoryAppearance | undefined { + return this._appearances.get(subCategoryId.toString()); + } /** Request that the subcategory information for all of the specified categories is loaded. * If all such information has already been loaded, returns undefined. @@ -69,13 +75,12 @@ export class SubCategoriesCache { public async loadAllUsedSpatialSubCategories(): Promise { try { const results = await this._imodel.queryAllUsedSpatialSubCategories(); - if (undefined !== results){ + if (undefined !== results) { this.processResults(results, new Set(), false); } } catch (e) { // In case of a truncated response, gracefully handle the error and exit. } - } /** Given categoryIds, return which of these are not cached. */ private getMissing(categoryIds: Id64Arg): Id64Set | undefined { @@ -110,7 +115,7 @@ export class SubCategoriesCache { } private processResults(result: SubCategoriesCache.Result, missing: Id64Set, override: boolean = true): void { - for (const row of result){ + for (const row of result) { this.add(row.parentId, row.id, SubCategoriesCache.createSubCategoryAppearance(row.appearance), override); } @@ -133,7 +138,9 @@ export class SubCategoriesCache { this._appearances.set(subCategoryId, appearance); } - public async getCategoryInfo(inputCategoryIds: Id64String | Iterable): Promise> { + public async getCategoryInfo( + inputCategoryIds: Id64String | Iterable, + ): Promise> { // Eliminate duplicates... const categoryIds = new Set(typeof inputCategoryIds === "string" ? [inputCategoryIds] : inputCategoryIds); const req = this.load(categoryIds); @@ -153,7 +160,10 @@ export class SubCategoriesCache { return map; } - public async getSubCategoryInfo(categoryId: Id64String, inputSubCategoryIds: Id64String | Iterable): Promise> { + public async getSubCategoryInfo( + categoryId: Id64String, + inputSubCategoryIds: Id64String | Iterable, + ): Promise> { // Eliminate duplicates... const subCategoryIds = new Set(typeof inputSubCategoryIds === "string" ? [inputSubCategoryIds] : inputSubCategoryIds); const req = this.load(categoryId); @@ -188,7 +198,9 @@ export namespace SubCategoriesCache { // eslint-disable-line no-redeclare private _canceled = false; private _curCategoryIdsIndex = 0; - public get wasCanceled() { return this._canceled || this._imodel.isClosed; } + public get wasCanceled() { + return this._canceled || this._imodel.isClosed; + } public constructor(categoryIds: Set, imodel: IModelConnection, maxCategoriesPerQuery = 2500) { this._imodel = imodel; @@ -202,7 +214,9 @@ export namespace SubCategoriesCache { // eslint-disable-line no-redeclare } } - public cancel() { this._canceled = true; } + public cancel() { + this._canceled = true; + } public async dispatch(): Promise { if (this.wasCanceled || this._curCategoryIdsIndex >= this._categoryIds.length) // handle case of empty category Id set... @@ -314,9 +328,10 @@ export namespace SubCategoriesCache { // eslint-disable-line no-redeclare // Invoke all the functions which were awaiting this set of IModelConnection.Categories. assert(undefined !== this._current); - if (completed) + if (completed) { for (const func of this._current.funcs) func(); + } this._request = undefined; this._current = undefined; diff --git a/core/frontend/src/TentativePoint.ts b/core/frontend/src/TentativePoint.ts index 55ccaf3dc894..e8686639d2d1 100644 --- a/core/frontend/src/TentativePoint.ts +++ b/core/frontend/src/TentativePoint.ts @@ -24,21 +24,29 @@ export class TentativePoint { public isActive = false; public currSnap?: SnapDetail; public tpHits?: HitList; - private get _hotDistanceInches(): number { return 0.21; } + private get _hotDistanceInches(): number { + return 0.21; + } private readonly _point: Point3d = new Point3d(); private readonly _rawPoint: Point3d = new Point3d(); private readonly _viewPoint: Point3d = new Point3d(); private _tentativePromise?: Promise; public viewport?: ScreenViewport; - public onInitialized() { } - public setHitList(list?: HitList) { this.tpHits = list; } + public onInitialized() {} + public setHitList(list?: HitList) { + this.tpHits = list; + } /** @return true if the tentative point is currently active and snapped to an element. */ - public get isSnapped(): boolean { return undefined !== this.currSnap; } + public get isSnapped(): boolean { + return undefined !== this.currSnap; + } /** @return The current snap path when TentativePoint.isSnapped or undefined. */ - public getCurrSnap(): SnapDetail | undefined { return this.currSnap; } + public getCurrSnap(): SnapDetail | undefined { + return this.currSnap; + } public getPoint(): Point3d { const snap = this.currSnap; @@ -158,7 +166,7 @@ export class TentativePoint { private async getSnap(newSearch: boolean): Promise { // Use next hit from previous search when using tentative to cycle through hits... - let thisHit = (!newSearch && undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined); + let thisHit = !newSearch && undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined; // Use existing AccuSnap hit list if one exists... if (undefined === thisHit) { @@ -177,7 +185,7 @@ export class TentativePoint { return undefined; this.tpHits = picker.getHitList(true); - thisHit = (undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined); + thisHit = undefined !== this.tpHits ? this.tpHits.getNextHit() : undefined; } else if (thisHit instanceof SnapDetail) { // Make the current AccuSnap the TentativePoint snap... return thisHit; @@ -198,7 +206,9 @@ export class TentativePoint { return thisSnap; } - private static arePointsCloseEnough(pt1: Point3d, pt2: Point3d, pixelDistance: number): boolean { return pt1.distance(pt2) < (pixelDistance + 1.5); } + private static arePointsCloseEnough(pt1: Point3d, pt2: Point3d, pixelDistance: number): boolean { + return pt1.distance(pt2) < (pixelDistance + 1.5); + } public process(ev: BeButtonEvent): void { if (undefined !== this._tentativePromise) @@ -217,7 +227,8 @@ export class TentativePoint { this._rawPoint.setFrom(ev.rawPoint); this._viewPoint.setFrom(ev.viewPoint); - const newSearch = (!this.isSnapped || !TentativePoint.arePointsCloseEnough(lastPtView, this._viewPoint, this.viewport.pixelsFromInches(IModelApp.locateManager.apertureInches))); + const newSearch = !this.isSnapped || + !TentativePoint.arePointsCloseEnough(lastPtView, this._viewPoint, this.viewport.pixelsFromInches(IModelApp.locateManager.apertureInches)); const promise = this.getSnap(newSearch); this._tentativePromise = promise; diff --git a/core/frontend/src/Tiles.ts b/core/frontend/src/Tiles.ts index 08ba6600a9e1..7bbc6ed9c0ac 100644 --- a/core/frontend/src/Tiles.ts +++ b/core/frontend/src/Tiles.ts @@ -19,9 +19,15 @@ class TreeOwner implements TileTreeOwner { public readonly id: any; - public get tileTree(): TileTree | undefined { return this._tileTree; } - public get loadStatus(): TileTreeLoadStatus { return this._loadStatus; } - public get iModel(): IModelConnection { return this._iModel; } + public get tileTree(): TileTree | undefined { + return this._tileTree; + } + public get loadStatus(): TileTreeLoadStatus { + return this._loadStatus; + } + public get iModel(): IModelConnection { + return this._iModel; + } public constructor(id: any, supplier: TileTreeSupplier, iModel: IModelConnection) { this.id = id; @@ -80,7 +86,9 @@ export class Tiles implements Iterable<{ supplier: TileTreeSupplier, id: any, ow private _disposed = false; /** @internal */ - public get isDisposed() { return this._disposed; } + public get isDisposed() { + return this._disposed; + } /** @internal */ constructor(iModel: IModelConnection) { @@ -208,7 +216,7 @@ export class Tiles implements Iterable<{ supplier: TileTreeSupplier, id: any, ow } /** Iterate over all of the TileTreeOwners. */ - public * [Symbol.iterator](): Iterator<{ supplier: TileTreeSupplier, id: any, owner: TileTreeOwner }> { + public *[Symbol.iterator](): Iterator<{ supplier: TileTreeSupplier, id: any, owner: TileTreeOwner }> { for (const [supplier, dict] of this._treesBySupplier) { for (const entry of dict) yield { supplier, id: entry.key, owner: entry.value }; @@ -218,9 +226,10 @@ export class Tiles implements Iterable<{ supplier: TileTreeSupplier, id: any, ow /** Obtain the TileTreeOwners supplied by the specified supplier. */ public getTreeOwnersForSupplier(supplier: TileTreeSupplier): Iterable<{ id: any, owner: TileTreeOwner }> { function* iterator(trees: Dictionary | undefined) { - if (trees) + if (trees) { for (const entry of trees) yield { id: entry.key, owner: entry.value }; + } } return { @@ -237,9 +246,10 @@ export class Tiles implements Iterable<{ supplier: TileTreeSupplier, id: any, ow const dict = entry[1]; dict.forEach((_treeId, owner) => { const tree = owner.tileTree; - if (undefined !== tree && tree.lastSelectedTime.milliseconds < olderThan.milliseconds) + if (undefined !== tree && tree.lastSelectedTime.milliseconds < olderThan.milliseconds) { if (undefined === exclude || !exclude.has(tree)) owner.dispose(); + } }); } } diff --git a/core/frontend/src/TxnEntityChanges.ts b/core/frontend/src/TxnEntityChanges.ts index 6d8bf68a2d78..e6bf2e59f3c2 100644 --- a/core/frontend/src/TxnEntityChanges.ts +++ b/core/frontend/src/TxnEntityChanges.ts @@ -106,7 +106,7 @@ export class Metadata implements TxnEntityMetadata { } } -function * entityChangesIterator(changes: EntityChanges, options?: TxnEntityChangesFilterOptions): Iterator { +function* entityChangesIterator(changes: EntityChanges, options?: TxnEntityChangesFilterOptions): Iterator { let excludedMetaIndices: Set | undefined; if (options?.includeMetadata) { for (let i = 0; i < changes.metadata.length; i++) { @@ -117,7 +117,7 @@ function * entityChangesIterator(changes: EntityChanges, options?: TxnEntityChan } } - function * process(type: TxnEntityChangeType) { + function* process(type: TxnEntityChangeType) { if (options?.includeTypes && !options.includeTypes.includes(type)) { return; } @@ -161,9 +161,15 @@ export class EntityChanges implements TxnEntityChanges { } } - public get inserted(): CompressedId64Set | undefined { return this.args.inserted; } - public get deleted(): CompressedId64Set | undefined { return this.args.deleted; } - public get updated(): CompressedId64Set | undefined { return this.args.updated; } + public get inserted(): CompressedId64Set | undefined { + return this.args.inserted; + } + public get deleted(): CompressedId64Set | undefined { + return this.args.deleted; + } + public get updated(): CompressedId64Set | undefined { + return this.args.updated; + } public [Symbol.iterator](): Iterator { return entityChangesIterator(this); diff --git a/core/frontend/src/ViewAnimation.ts b/core/frontend/src/ViewAnimation.ts index f7abb44bffa2..4e793a5f3d17 100644 --- a/core/frontend/src/ViewAnimation.ts +++ b/core/frontend/src/ViewAnimation.ts @@ -7,9 +7,9 @@ */ import { EasingFunction } from "@itwin/core-common"; -import { ViewStatus } from "./ViewStatus"; -import { MarginPercent, PaddingPercent } from "./MarginPercent"; import { Point3d } from "@itwin/core-geometry"; +import { MarginPercent, PaddingPercent } from "./MarginPercent"; +import { ViewStatus } from "./ViewStatus"; /** An object to animate a transition of a [[Viewport]]. * Only one animator may be associated with a viewport at a time. Registering a new diff --git a/core/frontend/src/ViewContext.ts b/core/frontend/src/ViewContext.ts index 7e8e61494ee1..87bee0752bd9 100644 --- a/core/frontend/src/ViewContext.ts +++ b/core/frontend/src/ViewContext.ts @@ -7,11 +7,9 @@ */ import { assert, Id64String } from "@itwin/core-bentley"; -import { - Matrix3d, Point2d, - Point3d, Range1d, Transform, XAndY, -} from "@itwin/core-geometry"; import { Frustum, FrustumPlanes, ViewFlags } from "@itwin/core-common"; +import { Matrix3d, Point2d, Point3d, Range1d, Transform, XAndY } from "@itwin/core-geometry"; +import { GraphicType } from "./common/render/GraphicType"; import { CachedDecoration, DecorationsCache } from "./DecorationsCache"; import { IModelApp } from "./IModelApp"; import { PlanarClipMaskState } from "./PlanarClipMaskState"; @@ -24,11 +22,10 @@ import { RenderPlanarClassifier } from "./render/RenderPlanarClassifier"; import { RenderSystem, RenderTextureDrape } from "./render/RenderSystem"; import { RenderTarget } from "./render/RenderTarget"; import { Scene } from "./render/Scene"; +import { ActiveSpatialClassifier } from "./SpatialClassifiersState"; import { SpatialClassifierTileTreeReference, Tile, TileGraphicType, TileLoadStatus, TileTreeReference } from "./tile/internal"; import { ViewingSpace } from "./ViewingSpace"; import { ELEMENT_MARKED_FOR_REMOVAL, ScreenViewport, Viewport, ViewportDecorator } from "./Viewport"; -import { ActiveSpatialClassifier } from "./SpatialClassifiersState"; -import { GraphicType } from "./common/render/GraphicType"; /** Provides context for producing [[RenderGraphic]]s for drawing within a [[Viewport]]. * @public @@ -66,7 +63,9 @@ export class RenderContext { } /** @internal */ - public get target(): RenderTarget { return this.viewport.target; } + public get target(): RenderTarget { + return this.viewport.target; + } /** @internal */ protected _createGraphicBuilder(options: Omit): GraphicBuilder { @@ -92,7 +91,9 @@ export class RenderContext { * @returns A RenderGraphic suitable for drawing the scene graph node within this context's [[Viewport]]. * @see [[RenderSystem.createBranch]] */ - public createBranch(branch: GraphicBranch, location: Transform): RenderGraphic { return this.createGraphicBranch(branch, location); } + public createBranch(branch: GraphicBranch, location: Transform): RenderGraphic { + return this.createGraphicBranch(branch, location); + } /** Given the size of a logical pixel in meters, convert it to the size of a physical pixel in meters, if [[RenderSystem.dpiAwareLOD]] is `true`. * Used when computing LOD for graphics. @@ -319,14 +320,27 @@ export class DecorateContext extends RenderContext { } /** @internal */ - public drawStandardGrid(gridOrigin: Point3d, rMatrix: Matrix3d, spacing: XAndY, gridsPerRef: number, _isoGrid: boolean = false, _fixedRepetitions?: Point2d): void { + public drawStandardGrid( + gridOrigin: Point3d, + rMatrix: Matrix3d, + spacing: XAndY, + gridsPerRef: number, + _isoGrid: boolean = false, + _fixedRepetitions?: Point2d, + ): void { const vp = this.viewport; if (vp.viewingGlobe) return; const color = vp.getContrastToBackgroundColor(); - const planarGrid = this.viewport.target.renderSystem.createPlanarGrid(vp.getFrustum(), { origin: gridOrigin, rMatrix, spacing, gridsPerRef, color }); + const planarGrid = this.viewport.target.renderSystem.createPlanarGrid(vp.getFrustum(), { + origin: gridOrigin, + rMatrix, + spacing, + gridsPerRef, + color, + }); if (planarGrid) { this.addDecoration(GraphicType.WorldDecoration, planarGrid); } @@ -381,7 +395,9 @@ export class SceneContext extends RenderContext { } /** @internal */ - public get graphicType() { return this._graphicType; } + public get graphicType() { + return this._graphicType; + } /** Add the specified graphic to the scene. */ public outputGraphic(graphic: RenderGraphic): void { @@ -415,7 +431,11 @@ export class SceneContext extends RenderContext { } /** @internal */ - public addPlanarClassifier(classifiedModelId: Id64String, classifierTree?: SpatialClassifierTileTreeReference, planarClipMask?: PlanarClipMaskState): RenderPlanarClassifier | undefined { + public addPlanarClassifier( + classifiedModelId: Id64String, + classifierTree?: SpatialClassifierTileTreeReference, + planarClipMask?: PlanarClipMaskState, + ): RenderPlanarClassifier | undefined { // Target may have the classifier from a previous frame; if not we must create one. let classifier = this.viewport.target.getPlanarClassifier(classifiedModelId); if (undefined === classifier) @@ -472,15 +492,25 @@ export class SceneContext extends RenderContext { } /** The graphics in the scene that will be drawn with depth. */ - public get graphics() { return this.scene.foreground; } + public get graphics() { + return this.scene.foreground; + } /** The graphics that will be drawn behind everything else in the scene. */ - public get backgroundGraphics() { return this.scene.background; } + public get backgroundGraphics() { + return this.scene.background; + } /** The graphics that will be drawn in front of everything else in the scene. */ - public get overlayGraphics() { return this.scene.overlay; } + public get overlayGraphics() { + return this.scene.overlay; + } /** @internal */ - public get planarClassifiers() { return this.scene.planarClassifiers; } + public get planarClassifiers() { + return this.scene.planarClassifiers; + } /** @internal */ - public get textureDrapes() { return this.scene.textureDrapes; } + public get textureDrapes() { + return this.scene.textureDrapes; + } /** @internal */ public setVolumeClassifier(classifier: ActiveSpatialClassifier, modelId: Id64String): void { diff --git a/core/frontend/src/ViewCreator2d.ts b/core/frontend/src/ViewCreator2d.ts index a94f62f02781..4cd4ba82aca0 100644 --- a/core/frontend/src/ViewCreator2d.ts +++ b/core/frontend/src/ViewCreator2d.ts @@ -14,8 +14,18 @@ Additional options (such as background color) can be passed during view creation import { Id64Array, Id64String, IModelStatus } from "@itwin/core-bentley"; import { - CategorySelectorProps, Code, ColorDef, DisplayStyleProps, IModel, IModelError, ModelSelectorProps, QueryBinder, QueryRowFormat, SheetProps, - ViewDefinition2dProps, ViewStateProps, + CategorySelectorProps, + Code, + ColorDef, + DisplayStyleProps, + IModel, + IModelError, + ModelSelectorProps, + QueryBinder, + QueryRowFormat, + SheetProps, + ViewDefinition2dProps, + ViewStateProps, } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; import { DrawingViewState } from "./DrawingViewState"; @@ -28,7 +38,7 @@ import { ViewState, ViewState2d } from "./ViewState"; /** Options for creating a [[ViewState2d]] via [[ViewCreator2d]]. * @public * @extensions -*/ + */ export interface ViewCreator2dOptions { /** Aspect ratio of [[Viewport]]. Required to fit contents of the model in the initial state of the view. */ vpAspect?: number; @@ -51,7 +61,6 @@ export interface ViewCreator2dOptions { * @extensions */ export class ViewCreator2d { - // Types of 2D models the API supports private static _drawingModelClasses = [DrawingModelState.classFullName, SectionDrawingModelState.classFullName]; private static _sheetModelClasses = [SheetModelState.classFullName]; @@ -60,7 +69,7 @@ export class ViewCreator2d { * Constructs a ViewCreator2d using an [[IModelConnection]]. * @param _imodel [[IModelConnection]] to query for categories and/or models. */ - constructor(private _imodel: IModelConnection) { } + constructor(private _imodel: IModelConnection) {} /** * Creates and returns view for the 2D model id passed in. @@ -69,13 +78,12 @@ export class ViewCreator2d { * @throws [IModelError]($common) If modelType is not supported. */ public async createViewForModel(modelId: Id64String, options?: ViewCreator2dOptions): Promise { - const baseClassName = await this._getModelBaseClassName(modelId); const viewState = await this._createViewState2d(modelId, baseClassName.classFullName, options); try { await viewState.load(); - } catch { } + } catch {} return viewState; } @@ -86,7 +94,6 @@ export class ViewCreator2d { * @throws [IModelError]($common) if modelId is invalid. */ private async _getModelBaseClassName(modelId: Id64String): Promise { - let baseClassName; const modelProps = await this._imodel.models.getProps(modelId); @@ -239,7 +246,11 @@ export class ViewCreator2d { private async _addSheetViewProps(modelId: Id64String, props: ViewStateProps) { let width = 0; let height = 0; - for await (const row of this._imodel.createQueryReader(`SELECT Width, Height FROM bis.Sheet WHERE ECInstanceId = ?`, QueryBinder.from([modelId]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of this._imodel.createQueryReader(`SELECT Width, Height FROM bis.Sheet WHERE ECInstanceId = ?`, QueryBinder.from([modelId]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { width = row.width as number; height = row.height as number; break; @@ -259,17 +270,17 @@ export class ViewCreator2d { } /** - * Merges a seed view in the iModel with the passed view state props. It will be a no-op if there are no 2D views for target model. - * @param modelId of target model. - * @param props Input view props to be merged - */ + * Merges a seed view in the iModel with the passed view state props. It will be a no-op if there are no 2D views for target model. + * @param modelId of target model. + * @param props Input view props to be merged + */ private async _mergeSeedView(modelId: Id64String, props: ViewStateProps): Promise { const viewDefinitionId = await this._getViewDefinitionsIdForModel(modelId); // Return incase no viewDefinition found. if (viewDefinitionId === undefined) return props; - const seedViewState = (await this._imodel.views.load(viewDefinitionId)); + const seedViewState = await this._imodel.views.load(viewDefinitionId); const seedViewStateProps: ViewStateProps = { categorySelectorProps: seedViewState.categorySelector.toJSON(), viewDefinitionProps: seedViewState.toJSON(), @@ -291,7 +302,6 @@ export class ViewCreator2d { * @param modelId of target model. */ private async _getViewDefinitionsIdForModel(modelId: Id64String): Promise { - const query = `SELECT ECInstanceId from Bis.ViewDefinition2D WHERE BaseModel.Id = ${modelId} AND isPrivate = false LIMIT 1`; const viewDefinitionsId = await this._executeQuery(query); @@ -302,7 +312,6 @@ export class ViewCreator2d { * Get all drawing categories */ private async _getAllCategories(): Promise { - const query = "SELECT ECInstanceId from BisCore.DrawingCategory"; const categories = await this._executeQuery(query); @@ -314,7 +323,6 @@ export class ViewCreator2d { * @param modelId of target model. */ private async _getSheetAttachments(modelId: string): Promise { - const query = `SELECT ECInstanceId FROM Bis.ViewAttachment WHERE Model.Id = ${modelId}`; const attachments = await this._executeQuery(query); diff --git a/core/frontend/src/ViewCreator3d.ts b/core/frontend/src/ViewCreator3d.ts index fbcd44eeaa31..e378493d02e4 100644 --- a/core/frontend/src/ViewCreator3d.ts +++ b/core/frontend/src/ViewCreator3d.ts @@ -9,8 +9,18 @@ import { CompressedId64Set, Id64, Id64Array, Id64String } from "@itwin/core-bentley"; import { - Camera, CategorySelectorProps, Code, CustomViewState3dCreatorOptions, DisplayStyle3dProps, Environment, IModel, IModelReadRpcInterface, - ModelSelectorProps, RenderMode, ViewDefinition3dProps, ViewStateProps, + Camera, + CategorySelectorProps, + Code, + CustomViewState3dCreatorOptions, + DisplayStyle3dProps, + Environment, + IModel, + IModelReadRpcInterface, + ModelSelectorProps, + RenderMode, + ViewDefinition3dProps, + ViewStateProps, } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; import { IModelConnection } from "./IModelConnection"; @@ -23,7 +33,7 @@ import { ViewState } from "./ViewState"; /** Options for creating a [[ViewState3d]] via [[ViewCreator3d]]. * @public * @extensions -*/ + */ export interface ViewCreator3dOptions { /** Turn the [[Camera]] on to produce a perspective view. * Default: true @@ -67,7 +77,7 @@ export class ViewCreator3d { * Constructs a ViewCreator3d using an [[IModelConnection]]. * @param _imodel [[IModelConnection]] to query for categories and/or models. */ - constructor(private _imodel: IModelConnection) { } + constructor(private _imodel: IModelConnection) {} /** * Creates a default [[ViewState3d]] based on the model ids passed in. If no model ids are passed in, all 3D models in the iModel are used. @@ -112,7 +122,12 @@ export class ViewCreator3d { * @param models Models to put in view props * @param options view creation options like camera On and skybox On */ - private async _createViewStateProps(models: Id64Array, categories: Id64Array, modelExtents: Range3d, options?: ViewCreator3dOptions): Promise { + private async _createViewStateProps( + models: Id64Array, + categories: Id64Array, + modelExtents: Range3d, + options?: ViewCreator3dOptions, + ): Promise { // Use dictionary model in all props const dictionaryId = IModel.dictionaryId; @@ -189,12 +204,11 @@ export class ViewCreator3d { visEdges: false, backgroundMap: this._imodel.isGeoLocated, }, - environment: - options !== undefined && + environment: options !== undefined && options.skyboxOn !== undefined && options.skyboxOn - ? Environment.defaults.withDisplay({ sky: true }).toJSON() - : undefined, + ? Environment.defaults.withDisplay({ sky: true }).toJSON() + : undefined, }, }, }; @@ -220,7 +234,7 @@ export class ViewCreator3d { if (viewId === undefined) return viewStateProps; - const seedViewState = (await this._imodel.views.load(viewId) as SpatialViewState); + const seedViewState = await this._imodel.views.load(viewId) as SpatialViewState; const seedViewStateProps = { categorySelectorProps: seedViewState.categorySelector.toJSON(), modelSelectorProps: seedViewState.modelSelector.toJSON(), diff --git a/core/frontend/src/ViewGlobalLocation.ts b/core/frontend/src/ViewGlobalLocation.ts index 7200a78c969e..737e3c90b7d9 100644 --- a/core/frontend/src/ViewGlobalLocation.ts +++ b/core/frontend/src/ViewGlobalLocation.ts @@ -6,8 +6,8 @@ * @module Views */ -import { Point3d, Range3d } from "@itwin/core-geometry"; import { Cartographic, GlobeMode } from "@itwin/core-common"; +import { Point3d, Range3d } from "@itwin/core-geometry"; import { BingElevationProvider } from "./tile/internal"; import { ScreenViewport } from "./Viewport"; import { ViewState3d } from "./ViewState"; @@ -16,7 +16,10 @@ import { ViewState3d } from "./ViewState"; * @public * @extensions */ -export interface GlobalLocationArea { southwest: Cartographic, northeast: Cartographic } +export interface GlobalLocationArea { + southwest: Cartographic; + northeast: Cartographic; +} /** Describes a location on the earth using cartographic data structures. * The viewed area of the location can be optionally specified. @@ -24,7 +27,10 @@ export interface GlobalLocationArea { southwest: Cartographic, northeast: Cartog * @public * @extensions */ -export interface GlobalLocation { center: Cartographic, area?: GlobalLocationArea } +export interface GlobalLocation { + center: Cartographic; + area?: GlobalLocationArea; +} /** @internal */ export class ViewGlobalLocationConstants { @@ -41,7 +47,12 @@ export class ViewGlobalLocationConstants { * A good use of this is to convert meters to some transition duration. * @internal */ -export function metersToRange(inputMeters: number, minimumOutput: number = 500, maximumOutput: number = 3000, maximumInputMeters = ViewGlobalLocationConstants.satelliteHeightAboveEarthInMeters): number { +export function metersToRange( + inputMeters: number, + minimumOutput: number = 500, + maximumOutput: number = 3000, + maximumInputMeters = ViewGlobalLocationConstants.satelliteHeightAboveEarthInMeters, +): number { let output: number; if (inputMeters <= 0) output = minimumOutput; @@ -158,7 +169,13 @@ export async function eyeToCartographicOnGlobeFromGcs(viewport: ScreenViewport, } /** @internal */ -export function viewGlobalLocation(viewport: ScreenViewport, doAnimate: boolean, eyeHeight = ViewGlobalLocationConstants.birdHeightAboveEarthInMeters, pitchAngleRadians = 0, location?: GlobalLocation): number { +export function viewGlobalLocation( + viewport: ScreenViewport, + doAnimate: boolean, + eyeHeight = ViewGlobalLocationConstants.birdHeightAboveEarthInMeters, + pitchAngleRadians = 0, + location?: GlobalLocation, +): number { if (!(viewport.view instanceof ViewState3d)) return 0; diff --git a/core/frontend/src/ViewManager.ts b/core/frontend/src/ViewManager.ts index 40ba01f3360b..0d60b2163044 100644 --- a/core/frontend/src/ViewManager.ts +++ b/core/frontend/src/ViewManager.ts @@ -10,10 +10,10 @@ import { GeometryStreamProps } from "@itwin/core-common"; import { HitDetail } from "./HitDetail"; import { IModelApp } from "./IModelApp"; import { IModelConnection } from "./IModelConnection"; +import { System } from "./render/webgl/System"; import { DisclosedTileTreeSet, TileTree } from "./tile/internal"; import { BeButtonEvent, EventHandled } from "./tools/Tool"; import { ScreenViewport, ViewportDecorator } from "./Viewport"; -import { System } from "./render/webgl/System"; /** Interface for drawing [decoration graphics]($docs/learning/frontend/ViewDecorations.md) into, or on top of, the active [[ScreenViewport]]s managed by [[ViewManager]]. * Decorators generate [[Decorations]]. @@ -212,10 +212,14 @@ export class ViewManager implements Iterable { } /** @internal */ - public beginDynamicsMode() { this.inDynamicsMode = true; } + public beginDynamicsMode() { + this.inDynamicsMode = true; + } /** @internal */ - public get doesHostHaveFocus(): boolean { return document.hasFocus(); } + public get doesHostHaveFocus(): boolean { + return document.hasFocus(); + } /** Set the selected [[Viewport]] to undefined. */ public clearSelectedView(): void { @@ -250,15 +254,19 @@ export class ViewManager implements Iterable { /** @internal */ public notifySelectedViewportChanged(previous: ScreenViewport | undefined, current: ScreenViewport | undefined) { - IModelApp.toolAdmin.onSelectedViewportChanged(previous, current);// eslint-disable-line @typescript-eslint/no-floating-promises + IModelApp.toolAdmin.onSelectedViewportChanged(previous, current); // eslint-disable-line @typescript-eslint/no-floating-promises this.onSelectedViewportChanged.emit({ previous, current }); } /** The "selected view" is the default for certain operations. */ - public get selectedView(): ScreenViewport | undefined { return this._selectedView; } + public get selectedView(): ScreenViewport | undefined { + return this._selectedView; + } /** Get the first opened view. */ - public getFirstOpenView(): ScreenViewport | undefined { return this._viewports.length > 0 ? this._viewports[0] : undefined; } + public getFirstOpenView(): ScreenViewport | undefined { + return this._viewports.length > 0 ? this._viewports[0] : undefined; + } /** Check if only a single viewport is being used. If so, render directly on-screen using its WebGL canvas. Otherwise, render each view offscreen. */ private updateRenderToScreen() { @@ -280,7 +288,7 @@ export class ViewManager implements Iterable { this._viewports.push(newVp); this.updateRenderToScreen(); - this.setSelectedView(newVp);// eslint-disable-line @typescript-eslint/no-floating-promises + this.setSelectedView(newVp); // eslint-disable-line @typescript-eslint/no-floating-promises // Start up the render loop if necessary. if (1 === this._viewports.length) @@ -318,7 +326,7 @@ export class ViewManager implements Iterable { this._viewports.splice(index, 1); if (this.selectedView === vp) // if removed viewport was selectedView, set it to undefined. - this.setSelectedView(undefined);// eslint-disable-line @typescript-eslint/no-floating-promises + this.setSelectedView(undefined); // eslint-disable-line @typescript-eslint/no-floating-promises vp.rendersToScreen = false; this.updateRenderToScreen(); @@ -341,9 +349,10 @@ export class ViewManager implements Iterable { * @see [[Viewport.invalidateCachedDecorations]] to invalidate the cached decorations for a single viewport. */ public invalidateCachedDecorationsAllViews(decorator: ViewportDecorator): void { - if (decorator.useCachedDecorations) + if (decorator.useCachedDecorations) { for (const vp of this) vp.invalidateCachedDecorations(decorator); + } } /** Force each registered [[Viewport]] to regenerate its [[Decorations]] on the next frame. */ @@ -389,7 +398,9 @@ export class ViewManager implements Iterable { } /** @internal */ - public get sceneInvalidated(): boolean { return this._invalidateScenes; } + public get sceneInvalidated(): boolean { + return this._invalidateScenes; + } /** Invoked by ToolAdmin event loop. * @internal @@ -571,14 +582,30 @@ export class ViewManager implements Iterable { return undefined; } - public get crossHairCursor(): string { return `url(${IModelApp.publicPath}cursors/crosshair.cur), crosshair`; } - public get dynamicsCursor(): string { return `url(${IModelApp.publicPath}cursors/dynamics.cur), move`; } - public get grabCursor(): string { return `url(${IModelApp.publicPath}cursors/openHand.cur), auto`; } - public get grabbingCursor(): string { return `url(${IModelApp.publicPath}cursors/closedHand.cur), auto`; } - public get walkCursor(): string { return `url(${IModelApp.publicPath}cursors/walk.cur), auto`; } - public get rotateCursor(): string { return `url(${IModelApp.publicPath}cursors/rotate.cur), auto`; } - public get lookCursor(): string { return `url(${IModelApp.publicPath}cursors/look.cur), auto`; } - public get zoomCursor(): string { return `url(${IModelApp.publicPath}cursors/zoom.cur), auto`; } + public get crossHairCursor(): string { + return `url(${IModelApp.publicPath}cursors/crosshair.cur), crosshair`; + } + public get dynamicsCursor(): string { + return `url(${IModelApp.publicPath}cursors/dynamics.cur), move`; + } + public get grabCursor(): string { + return `url(${IModelApp.publicPath}cursors/openHand.cur), auto`; + } + public get grabbingCursor(): string { + return `url(${IModelApp.publicPath}cursors/closedHand.cur), auto`; + } + public get walkCursor(): string { + return `url(${IModelApp.publicPath}cursors/walk.cur), auto`; + } + public get rotateCursor(): string { + return `url(${IModelApp.publicPath}cursors/rotate.cur), auto`; + } + public get lookCursor(): string { + return `url(${IModelApp.publicPath}cursors/look.cur), auto`; + } + public get zoomCursor(): string { + return `url(${IModelApp.publicPath}cursors/zoom.cur), auto`; + } /** Change the cursor shown in all Viewports. * @param cursor The new cursor to display. If undefined, the default cursor is used. diff --git a/core/frontend/src/ViewPose.ts b/core/frontend/src/ViewPose.ts index 1da0bf6e7b5d..753a27b70302 100644 --- a/core/frontend/src/ViewPose.ts +++ b/core/frontend/src/ViewPose.ts @@ -7,8 +7,8 @@ */ import { BeTimePoint } from "@itwin/core-bentley"; -import { Angle, Matrix3d, Point2d, Point3d, Vector3d } from "@itwin/core-geometry"; import { Camera } from "@itwin/core-common"; +import { Angle, Matrix3d, Point2d, Point3d, Vector3d } from "@itwin/core-geometry"; import { ViewState, ViewState2d, ViewState3d } from "./ViewState"; /** The "pose" for a [View]($docs/learning/frontend/views#viewstate-parameters) describing the viewed area or volume, depending upon whether @@ -51,10 +51,14 @@ export abstract class ViewPose { } /** Returns the target point of the view. This is the same as [[center]] unless [[cameraOn]] is `true`. */ - public get target() { return this.center; } + public get target() { + return this.center; + } /** Computes the Z vector of the [[rotation]] matrix. */ - public get zVec() { return this.rotation.getRow(2); } + public get zVec() { + return this.rotation.getRow(2); + } public constructor(cameraOn: boolean) { this.cameraOn = cameraOn; diff --git a/core/frontend/src/ViewState.ts b/core/frontend/src/ViewState.ts index 4c13881315d6..6506bccb98ce 100644 --- a/core/frontend/src/ViewState.ts +++ b/core/frontend/src/ViewState.ts @@ -8,21 +8,61 @@ import { assert, BeEvent, dispose, Id64, Id64Arg, Id64String, JsonUtils } from "@itwin/core-bentley"; import { - Angle, AxisOrder, ClipVector, Constant, Geometry, LongitudeLatitudeNumber, LowAndHighXY, LowAndHighXYZ, Map4d, Matrix3d, - Plane3dByOriginAndUnitNormal, Point2d, Point3d, Range2d, Range3d, Ray3d, Transform, Vector2d, Vector3d, XAndY, - XYAndZ, XYZ, YawPitchRollAngles, -} from "@itwin/core-geometry"; -import { - AnalysisStyle, AxisAlignedBox3d, Camera, Cartographic, ColorDef, FeatureAppearance, Frustum, GlobeMode, GridOrientationType, - HydrateViewStateRequestProps, HydrateViewStateResponseProps, IModelReadRpcInterface, - ModelClipGroups, Npc, RenderSchedule, SubCategoryOverride, - ViewDefinition2dProps, ViewDefinition3dProps, ViewDefinitionProps, ViewDetails, ViewDetails3d, ViewFlags, ViewStateProps, + AnalysisStyle, + AxisAlignedBox3d, + Camera, + Cartographic, + ColorDef, + FeatureAppearance, + Frustum, + GlobeMode, + GridOrientationType, + HydrateViewStateRequestProps, + HydrateViewStateResponseProps, + IModelReadRpcInterface, + ModelClipGroups, + Npc, + RenderSchedule, + SubCategoryOverride, + ViewDefinition2dProps, + ViewDefinition3dProps, + ViewDefinitionProps, + ViewDetails, + ViewDetails3d, + ViewFlags, + ViewStateProps, } from "@itwin/core-common"; +import { + Angle, + AxisOrder, + ClipVector, + Constant, + Geometry, + LongitudeLatitudeNumber, + LowAndHighXY, + LowAndHighXYZ, + Map4d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Range2d, + Range3d, + Ray3d, + Transform, + Vector2d, + Vector3d, + XAndY, + XYAndZ, + XYZ, + YawPitchRollAngles, +} from "@itwin/core-geometry"; import { AuxCoordSystem2dState, AuxCoordSystem3dState, AuxCoordSystemState } from "./AuxCoordSys"; import { CategorySelectorState } from "./CategorySelectorState"; import { DisplayStyle2dState, DisplayStyle3dState, DisplayStyleState } from "./DisplayStyleState"; import { DrawingViewState } from "./DrawingViewState"; import { ElementState } from "./EntityState"; +import { EnvironmentDecorations } from "./EnvironmentDecorations"; import { Frustum2d } from "./Frustum2d"; import { IModelApp } from "./IModelApp"; import { IModelConnection } from "./IModelConnection"; @@ -41,7 +81,6 @@ import { ViewingSpace } from "./ViewingSpace"; import { Viewport } from "./Viewport"; import { ViewPose, ViewPose2d, ViewPose3d } from "./ViewPose"; import { ViewStatus } from "./ViewStatus"; -import { EnvironmentDecorations } from "./EnvironmentDecorations"; /** Describes the largest and smallest values allowed for the extents of a [[ViewState]]. * Attempts to exceed these limits in any dimension will fail, preserving the previous extents. @@ -153,7 +192,7 @@ export interface LookAtUsingLensAngle extends LookAtArgs { /** Decorates the viewport with the view's grid. Graphics are cached as long as scene remains valid. */ class GridDecorator { - public constructor(private readonly _view: ViewState) { } + public constructor(private readonly _view: ViewState) {} public readonly useCachedDecorations = true; @@ -206,7 +245,9 @@ export type AttachToViewportArgs = Viewport; * @extensions */ export abstract class ViewState extends ElementState { - public static override get className() { return "ViewDefinition"; } + public static override get className() { + return "ViewDefinition"; + } private _auxCoordSystem?: AuxCoordSystemState; private _extentLimits?: ExtentLimits; @@ -267,14 +308,19 @@ export abstract class ViewState extends ElementState { } /** @internal */ - protected constructor(props: ViewDefinitionProps, iModel: IModelConnection, categoryOrClone: CategorySelectorState, displayStyle: DisplayStyleState) { + protected constructor( + props: ViewDefinitionProps, + iModel: IModelConnection, + categoryOrClone: CategorySelectorState, + displayStyle: DisplayStyleState, + ) { super(props, iModel); this.description = props.description; this.isPrivate = props.isPrivate; this._displayStyle = displayStyle; this._categorySelector = categoryOrClone; this._gridDecorator = new GridDecorator(this); - if (!(categoryOrClone instanceof ViewState)) // is this from the clone method? + if (!(categoryOrClone instanceof ViewState)) // is this from the clone method? return; // not from clone // from clone, 3rd argument is source ViewState @@ -289,7 +335,9 @@ export abstract class ViewState extends ElementState { /** Create a new ViewState object from a set of properties. Generally this is called internally by [[IModelConnection.Views.load]] after the properties * have been read from an iModel. But, it can also be used to create a ViewState in memory, from scratch or from properties stored elsewhere. */ - public static createFromProps(_props: ViewStateProps, _iModel: IModelConnection): ViewState | undefined { return undefined; } + public static createFromProps(_props: ViewStateProps, _iModel: IModelConnection): ViewState | undefined { + return undefined; + } /** Serialize this ViewState as a set of properties that can be used to recreate it via [[ViewState.createFromProps]]. */ public toProps(): ViewStateProps { @@ -330,10 +378,14 @@ export abstract class ViewState extends ElementState { /** Get the globe projection mode. * @internal */ - public get globeMode(): GlobeMode { return this.displayStyle.globeMode; } + public get globeMode(): GlobeMode { + return this.displayStyle.globeMode; + } /** Determine whether this ViewState exactly matches another. */ - public override equals(other: this): boolean { return super.equals(other) && this.categorySelector.equals(other.categorySelector) && this.displayStyle.equals(other.displayStyle); } + public override equals(other: this): boolean { + return super.equals(other) && this.categorySelector.equals(other.categorySelector) && this.displayStyle.equals(other.displayStyle); + } /** Convert to JSON representation. */ public override toJSON(): ViewDefinitionProps { @@ -370,14 +422,14 @@ export abstract class ViewState extends ElementState { const hydrateRequest: HydrateViewStateRequestProps = {}; this.preload(hydrateRequest); const promises: Promise[] = [ - IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).hydrateViewState(this.iModel.getRpcProps(), hydrateRequest). - then(async (hydrateResponse) => this.postload(hydrateResponse)), + IModelReadRpcInterface.getClientForRouting(this.iModel.routingContext.token).hydrateViewState(this.iModel.getRpcProps(), hydrateRequest) + .then(async (hydrateResponse) => this.postload(hydrateResponse)), this.displayStyle.load(), ]; const subcategories = this.iModel.subcategories.load(this.categorySelector.categories); if (undefined !== subcategories) - promises.push(subcategories.promise.then((_) => { })); + promises.push(subcategories.promise.then((_) => {})); await Promise.all(promises); } @@ -445,13 +497,17 @@ export abstract class ViewState extends ElementState { /** Returns true if this ViewState is-a [[ViewState3d]] */ public abstract is3d(): this is ViewState3d; /** Returns true if this ViewState is-a [[ViewState2d]] */ - public is2d(): this is ViewState2d { return !this.is3d(); } + public is2d(): this is ViewState2d { + return !this.is3d(); + } /** Returns true if this ViewState is-a [[SpatialViewState]] */ public abstract isSpatialView(): this is SpatialViewState; /** Returns true if this ViewState is-a [[DrawingViewState]] */ public abstract isDrawingView(): this is DrawingViewState; /** Returns true if this ViewState is-a [[SheetViewState]] */ - public isSheetView(): this is SheetViewState { return false; } + public isSheetView(): this is SheetViewState { + return false; + } /** Returns true if [[ViewTool]]s are allowed to operate in three dimensions on this view. */ public abstract allow3dManipulations(): boolean; /** @internal */ @@ -567,7 +623,9 @@ export abstract class ViewState extends ElementState { } /** Orient this view to one of the [[StandardView]] rotations. */ - public setStandardRotation(id: StandardViewId) { this.setRotation(ViewState.getStandardViewMatrix(id)); } + public setStandardRotation(id: StandardViewId) { + this.setRotation(ViewState.getStandardViewMatrix(id)); + } /** Orient this view to one of the [[StandardView]] rotations, if the the view is not viewing the project then the * standard rotation is relative to the global position rather than the project. @@ -582,7 +640,9 @@ export abstract class ViewState extends ElementState { } /** Get the target point of the view. If there is no camera, center is returned. */ - public getTargetPoint(result?: Point3d): Point3d { return this.getCenter(result); } + public getTargetPoint(result?: Point3d): Point3d { + return this.getCenter(result); + } /** Get the point at the geometric center of the view. */ public getCenter(result?: Point3d): Point3d { @@ -596,7 +656,12 @@ export abstract class ViewState extends ElementState { } /** @internal */ - public computeWorldToNpc(viewRot?: Matrix3d, inOrigin?: Point3d, delta?: Vector3d, enforceFrontToBackRatio = true): { map: Map4d | undefined, frustFraction: number } { + public computeWorldToNpc( + viewRot?: Matrix3d, + inOrigin?: Point3d, + delta?: Vector3d, + enforceFrontToBackRatio = true, + ): { map: Map4d | undefined, frustFraction: number } { if (viewRot === undefined) viewRot = this.getRotation(); @@ -619,12 +684,12 @@ export abstract class ViewState extends ElementState { if (this.is3d() && this.isCameraOn) { const camera = this.camera; const eyeToOrigin = Vector3d.createStartEnd(camera.eye, inOrigin); // vector from origin on backplane to eye - viewRot.multiplyVectorInPlace(eyeToOrigin); // align with view coordinates. + viewRot.multiplyVectorInPlace(eyeToOrigin); // align with view coordinates. const focusDistance = camera.focusDist; let zDelta = delta.z; - let zBack = eyeToOrigin.z; // Distance from eye to backplane. - let zFront = zBack + zDelta; // Distance from eye to frontplane. + let zBack = eyeToOrigin.z; // Distance from eye to backplane. + let zFront = zBack + zDelta; // Distance from eye to frontplane. const nearScale = IModelApp.renderSystem.supportsLogZBuffer ? ViewingSpace.nearScaleLog24 : ViewingSpace.nearScaleNonLog24; if (enforceFrontToBackRatio && zFront / zBack < nearScale) { @@ -643,24 +708,25 @@ export abstract class ViewState extends ElementState { } // z out back of eye ===> origin z coordinates are negative. (Back plane more negative than front plane) - const backFraction = -zBack / focusDistance; // Perspective fraction at back clip plane. - const frontFraction = -zFront / focusDistance; // Perspective fraction at front clip plane. + const backFraction = -zBack / focusDistance; // Perspective fraction at back clip plane. + const frontFraction = -zFront / focusDistance; // Perspective fraction at front clip plane. frustFraction = frontFraction / backFraction; // delta.x,delta.y are view rectangle sizes at focus distance. Scale to back plane: - xExtent = xVector.scale(delta.x * backFraction); // xExtent at back == delta.x * backFraction. - yExtent = yVector.scale(delta.y * backFraction); // yExtent at back == delta.y * backFraction. + xExtent = xVector.scale(delta.x * backFraction); // xExtent at back == delta.x * backFraction. + yExtent = yVector.scale(delta.y * backFraction); // yExtent at back == delta.y * backFraction. // Calculate the zExtent in the View coordinate system. zExtent = new Vector3d(eyeToOrigin.x * (frontFraction - backFraction), eyeToOrigin.y * (frontFraction - backFraction), zDelta); - viewRot.multiplyTransposeVectorInPlace(zExtent); // rotate back to root coordinates. + viewRot.multiplyTransposeVectorInPlace(zExtent); // rotate back to root coordinates. origin = new Point3d( - eyeToOrigin.x * backFraction, // Calculate origin in eye coordinates + eyeToOrigin.x * backFraction, // Calculate origin in eye coordinates eyeToOrigin.y * backFraction, - eyeToOrigin.z); + eyeToOrigin.z, + ); - viewRot.multiplyTransposeVectorInPlace(origin); // Rotate back to root coordinates + viewRot.multiplyTransposeVectorInPlace(origin); // Rotate back to root coordinates origin.plus(camera.eye, origin); // Add the eye point. } else { origin = inOrigin; @@ -690,7 +756,12 @@ export abstract class ViewState extends ElementState { public calculateFocusCorners() { const map = this.computeWorldToNpc().map!; const focusNpcZ = Geometry.clamp(map.transform0.multiplyPoint3dQuietNormalize(this.getTargetPoint()).z, 0, 1.0); - const pts = [new Point3d(0.0, 0.0, focusNpcZ), new Point3d(1.0, 0.0, focusNpcZ), new Point3d(0.0, 1.0, focusNpcZ), new Point3d(1.0, 1.0, focusNpcZ)]; + const pts = [ + new Point3d(0.0, 0.0, focusNpcZ), + new Point3d(1.0, 0.0, focusNpcZ), + new Point3d(0.0, 1.0, focusNpcZ), + new Point3d(1.0, 1.0, focusNpcZ), + ]; map.transform1.multiplyPoint3dArrayQuietNormalize(pts); return pts; } @@ -738,8 +809,8 @@ export abstract class ViewState extends ElementState { return ViewStatus.InvalidWindow; const viewDiagRoot = new Vector3d(); - viewDiagRoot.plus2Scaled(xDir, xDir.dotProduct(frustumX), yDir, yDir.dotProduct(frustumY), viewDiagRoot); // vectors on the back plane - viewDiagRoot.plusScaled(zDir, zSize, viewDiagRoot); // add in z vector perpendicular to x,y + viewDiagRoot.plus2Scaled(xDir, xDir.dotProduct(frustumX), yDir, yDir.dotProduct(frustumY), viewDiagRoot); // vectors on the back plane + viewDiagRoot.plusScaled(zDir, zSize, viewDiagRoot); // add in z vector perpendicular to x,y // use center of frustum and view diagonal for origin. Original frustum may not have been orthogonal frustum.getCenter().plusScaled(viewDiagRoot, -0.5, viewOrg); @@ -764,19 +835,27 @@ export abstract class ViewState extends ElementState { * Explicitly setting the extent limits overrides the default limits. * @see [[resetExtentLimits]] to restore the default limits. */ - public get extentLimits(): ExtentLimits { return undefined !== this._extentLimits ? this._extentLimits : this.defaultExtentLimits; } - public set extentLimits(limits: ExtentLimits) { this._extentLimits = limits; } + public get extentLimits(): ExtentLimits { + return undefined !== this._extentLimits ? this._extentLimits : this.defaultExtentLimits; + } + public set extentLimits(limits: ExtentLimits) { + this._extentLimits = limits; + } /** Resets the largest and smallest values allowed for the extents of this ViewState to their default values. * @see [[extentLimits]]. */ - public resetExtentLimits(): void { this._extentLimits = undefined; } + public resetExtentLimits(): void { + this._extentLimits = undefined; + } /** Returns the default extent limits for this ViewState. These limits are used if the [[extentLimits]] have not been explicitly overridden. */ public abstract get defaultExtentLimits(): ExtentLimits; - public setDisplayStyle(style: DisplayStyleState) { this.displayStyle = style; } + public setDisplayStyle(style: DisplayStyleState) { + this.displayStyle = style; + } /** Adjust the y dimension of this ViewState so that its aspect ratio matches the supplied value. * @internal @@ -797,7 +876,9 @@ export abstract class ViewState extends ElementState { /** @internal */ public outputStatusMessage(status: ViewStatus): ViewStatus { - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, IModelApp.localization.getLocalizedString(`iModelJs:Viewing.${ViewStatus[status]}`))); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, IModelApp.localization.getLocalizedString(`iModelJs:Viewing.${ViewStatus[status]}`)), + ); return status; } @@ -850,7 +931,9 @@ export abstract class ViewState extends ElementState { } /** Set the CategorySelector for this view. */ - public setCategorySelector(categories: CategorySelectorState) { this.categorySelector = categories; } + public setCategorySelector(categories: CategorySelectorState) { + this.categorySelector = categories; + } /** get the auxiliary coordinate system state object for this ViewState. */ public get auxiliaryCoordinateSystem(): AuxCoordSystemState { @@ -896,17 +979,23 @@ export abstract class ViewState extends ElementState { /** Get the unit vector that points in the view X (left-to-right) direction. * @param result optional Vector3d to be used for output. If undefined, a new object is created. */ - public getXVector(result?: Vector3d): Vector3d { return this.getRotation().getRow(0, result); } + public getXVector(result?: Vector3d): Vector3d { + return this.getRotation().getRow(0, result); + } /** Get the unit vector that points in the view Y (bottom-to-top) direction. * @param result optional Vector3d to be used for output. If undefined, a new object is created. */ - public getYVector(result?: Vector3d): Vector3d { return this.getRotation().getRow(1, result); } + public getYVector(result?: Vector3d): Vector3d { + return this.getRotation().getRow(1, result); + } /** Get the unit vector that points in the view Z (front-to-back) direction. * @param result optional Vector3d to be used for output. If undefined, a new object is created. */ - public getZVector(result?: Vector3d): Vector3d { return this.getRotation().getRow(2, result); } + public getZVector(result?: Vector3d): Vector3d { + return this.getRotation().getRow(2, result); + } /** Set or clear the clipping volume for this view. * @param clip the new clipping volume. If undefined, clipping is removed from view. @@ -1033,7 +1122,11 @@ export abstract class ViewState extends ElementState { let left, right, top, bottom; const padding = options.paddingPercent; if (typeof padding === "number") { - left = right = top = bottom = padding; + left = + right = + top = + bottom = + padding; } else { left = padding.left ?? 0; right = padding.right ?? 0; @@ -1226,7 +1319,6 @@ export abstract class ViewState extends ElementState { const angles = intersectAngles[minIndex]; const pointAndDeriv = earthEllipsoid.radiansToPointAndDerivatives(angles.longitudeRadians, angles.latitudeRadians, false); return Matrix3d.createRigidFromColumns(pointAndDeriv.vectorU, pointAndDeriv.vectorV, AxisOrder.XYZ)?.transpose(); - } /** A value that represents the global scope of the view -- a value greater than one indicates that the scope of this view is global (viewing most of Earth). */ @@ -1241,14 +1333,20 @@ export abstract class ViewState extends ElementState { * A value greater than one indicates that the viewport has been used to view globally at least once. * @internal */ - public get maxGlobalScopeFactor() { return this._maxGlobalScopeFactor; } + public get maxGlobalScopeFactor() { + return this._maxGlobalScopeFactor; + } - protected _updateMaxGlobalScopeFactor() { this._maxGlobalScopeFactor = Math.max(this._maxGlobalScopeFactor, this.globalScopeFactor); } + protected _updateMaxGlobalScopeFactor() { + this._maxGlobalScopeFactor = Math.max(this._maxGlobalScopeFactor, this.globalScopeFactor); + } /** Return elevation applied to model when displayed. This is strictly relevant to plan projection models. * @internal */ - public getModelElevation(_modelId: Id64String): number { return 0; } + public getModelElevation(_modelId: Id64String): number { + return 0; + } /** An object that can provide per-model transforms to be applied at display time. * @note The transform is used for display purposes only. Operations upon geometry within the model may not take the display transform into account. @@ -1381,7 +1479,9 @@ export abstract class ViewState3d extends ViewState { private readonly _details: ViewDetails3d; private readonly _modelClips: Array = []; private _environmentDecorations?: EnvironmentDecorations; - public static override get className() { return "ViewDefinition3d"; } + public static override get className() { + return "ViewDefinition3d"; + } /** True if the camera is valid. */ protected _cameraOn: boolean; /** The lower left back corner of the view frustum. */ @@ -1444,7 +1544,9 @@ export abstract class ViewState3d extends ViewState { } /** Capture a copy of the viewed volume and camera parameters. */ - public savePose(): ViewPose3d { return new ViewPose3d(this); } + public savePose(): ViewPose3d { + return new ViewPose3d(this); + } /** See [[ViewState.applyPose]]. */ public applyPose(val: ViewPose): this { @@ -1471,14 +1573,20 @@ export abstract class ViewState3d extends ViewState { } /** See [[ViewState.is3d]]. */ - public is3d(): this is ViewState3d { return true; } + public is3d(): this is ViewState3d { + return true; + } /** @internal */ - public isDrawingView(): this is DrawingViewState { return false; } + public isDrawingView(): this is DrawingViewState { + return false; + } - public get isCameraOn(): boolean { return this._cameraOn; } + public get isCameraOn(): boolean { + return this._cameraOn; + } - private static _minGlobeEyeHeight = Constant.earthRadiusWGS84.equator / 4; // View as globe if more than a quarter of earth radius from surface. + private static _minGlobeEyeHeight = Constant.earthRadiusWGS84.equator / 4; // View as globe if more than a quarter of earth radius from surface. private static _scratchGlobeCarto = Cartographic.createZero(); public get isGlobalView() { @@ -1493,7 +1601,9 @@ export abstract class ViewState3d extends ViewState { */ public override get globalScopeFactor(): number { const eyeHeight = this.getEyeCartographicHeight(); - return (undefined === eyeHeight) ? (this.extents.magnitudeXY() / Constant.earthRadiusWGS84.equator) : (eyeHeight / ViewState3d._minGlobeEyeHeight); + return (undefined === eyeHeight) + ? (this.extents.magnitudeXY() / Constant.earthRadiusWGS84.equator) + : (eyeHeight / ViewState3d._minGlobeEyeHeight); } /** A value representing the degree to which a view is viewing the globe as opposed to a specific location @@ -1510,7 +1620,7 @@ export abstract class ViewState3d extends ViewState { let h = 0.0; if (this.isCameraOn) { const carto = this.rootToCartographic(this.getEyePoint(), ViewState3d._scratchGlobeCarto); - h = (undefined === carto ? 0.0 : carto.height); + h = undefined === carto ? 0.0 : carto.height; } else h = this.extents.magnitudeXY(); @@ -1594,7 +1704,13 @@ export abstract class ViewState3d extends ViewState { return this.finishLookAtGlobalLocation(targetPointCartographic, origEyePoint, lEyePoint, targetPoint, pitchAngleRadians); } - private finishLookAtGlobalLocation(targetPointCartographic: Cartographic, origEyePoint: Point3d, eyePoint: Point3d, targetPoint: Point3d, pitchAngleRadians: number): number { + private finishLookAtGlobalLocation( + targetPointCartographic: Cartographic, + origEyePoint: Point3d, + eyePoint: Point3d, + targetPoint: Point3d, + pitchAngleRadians: number, + ): number { targetPointCartographic.latitude += .001; const northOfEyePoint = this.cartographicToRoot(targetPointCartographic)!; let upVector = targetPoint.unitVectorTo(northOfEyePoint)!; @@ -1706,12 +1822,12 @@ export abstract class ViewState3d extends ViewState { const frustOrgToEye = frustumZ.scale(1.0 / (1.0 - compression)); const eyePoint = viewOrg.plus(frustOrgToEye); - const backDistance = frustOrgToEye.dotProduct(zDir); // distance from eye to back plane of frustum + const backDistance = frustOrgToEye.dotProduct(zDir); // distance from eye to back plane of frustum const focusDistance = this.camera.isFocusValid ? this.camera.focusDist : (backDistance - (viewDelta.z / 2.0)); - const focalFraction = focusDistance / backDistance; // ratio of focus plane distance to back plane distance + const focalFraction = focusDistance / backDistance; // ratio of focus plane distance to back plane distance - viewOrg = eyePoint.plus2Scaled(frustOrgToEye, -focalFraction, zDir, focusDistance - backDistance); // now project that point onto back plane - viewDelta.x *= focalFraction; // adjust view delta for x and y so they are also at focus plane + viewOrg = eyePoint.plus2Scaled(frustOrgToEye, -focalFraction, zDir, focusDistance - backDistance); // now project that point onto back plane + viewDelta.x *= focalFraction; // adjust view delta for x and y so they are also at focus plane viewDelta.y *= focalFraction; this.setEyePoint(eyePoint); @@ -1725,19 +1841,31 @@ export abstract class ViewState3d extends ViewState { } protected static calculateMaxDepth(delta: Vector3d, zVec: Vector3d): number { - const depthRatioLimit = 1.0E8; // Limit for depth Ratio. + const depthRatioLimit = 1.0E8; // Limit for depth Ratio. const maxTransformRowRatio = 1.0E5; const minXYComponent = Math.min(Math.abs(zVec.x), Math.abs(zVec.y)); - const maxDepthRatio = (0.0 === minXYComponent) ? depthRatioLimit : Math.min((maxTransformRowRatio / minXYComponent), depthRatioLimit); + const maxDepthRatio = (0.0 === minXYComponent) ? depthRatioLimit : Math.min(maxTransformRowRatio / minXYComponent, depthRatioLimit); return Math.max(delta.x, delta.y) * maxDepthRatio; } - public getOrigin(): Point3d { return this.origin; } - public getExtents(): Vector3d { return this.extents; } - public getRotation(): Matrix3d { return this.rotation; } - public setOrigin(origin: XYAndZ) { this.origin.setFrom(origin); } - public setExtents(extents: XYAndZ) { this.extents.setFrom(extents); } - public setRotation(rot: Matrix3d) { this.rotation.setFrom(rot); } + public getOrigin(): Point3d { + return this.origin; + } + public getExtents(): Vector3d { + return this.extents; + } + public getRotation(): Matrix3d { + return this.rotation; + } + public setOrigin(origin: XYAndZ) { + this.origin.setFrom(origin); + } + public setExtents(extents: XYAndZ) { + this.extents.setFrom(extents); + } + public setRotation(rot: Matrix3d) { + this.rotation.setFrom(rot); + } /** @internal */ protected enableCamera(): void { if (this.supportsCamera()) @@ -1777,10 +1905,14 @@ export abstract class ViewState3d extends ViewState { * display with an orthographic (infinite focal length) projection of the view volume from the view direction. * @note To turn the camera back on, call #lookAt */ - public turnCameraOff() { this._cameraOn = false; } + public turnCameraOff() { + this._cameraOn = false; + } /** Determine whether the camera is valid for this view */ - public get isCameraValid() { return this.camera.isValid; } + public get isCameraValid() { + return this.camera.isValid; + } /** Calculate the lens angle formed by the current delta and focus distance */ public calcLensAngle(): Angle { @@ -1806,9 +1938,9 @@ export abstract class ViewState3d extends ViewState { if (args.lensAngle) { const lensAngle = args.lensAngle; const eyePoint = Vector3d.createFrom(args.eyePoint); - const focus = eyePoint.vectorTo(args.targetPoint).magnitude(); // Set focus at target point + const focus = eyePoint.vectorTo(args.targetPoint).magnitude(); // Set focus at target point - if (focus <= Constant.oneMillimeter) // eye and target are too close together + if (focus <= Constant.oneMillimeter) // eye and target are too close together return ViewStatus.InvalidTargetPoint; if (lensAngle.radians < .0001 || lensAngle.radians > Math.PI) @@ -1848,7 +1980,7 @@ export abstract class ViewState3d extends ViewState { const xVec = new Vector3d(); if (yVec.crossProduct(zVec).normalizeWithLength(xVec).mag < Geometry.smallMetricDistance) - return ViewStatus.InvalidUpVector; // up is parallel to z + return ViewStatus.InvalidUpVector; // up is parallel to z if (zVec.crossProduct(xVec).normalizeWithLength(yVec).mag < Geometry.smallMetricDistance) return ViewStatus.InvalidUpVector; @@ -1863,7 +1995,7 @@ export abstract class ViewState3d extends ViewState { // The front/back distance are relatively arbitrary -- the frustum will be adjusted to include geometry. // Set them here to reasonable in front of eye and just beyond target. - frontDist = Math.min(frontDist, (.5 * Constant.oneMeter)); + frontDist = Math.min(frontDist, .5 * Constant.oneMeter); backDist = Math.min(backDist, focusDist + (.5 * Constant.oneMeter)); if (backDist < focusDist) // make sure focus distance is in front of back distance. @@ -1875,7 +2007,7 @@ export abstract class ViewState3d extends ViewState { if (frontDist < minFrontDist) frontDist = minFrontDist; - delta.z = (backDist - frontDist); + delta.z = backDist - frontDist; const stat = this.adjustViewDelta(delta, eye, rotation, undefined, args.opts); if (ViewStatus.Success !== stat) @@ -1973,7 +2105,7 @@ export abstract class ViewState3d extends ViewState { const about = aboutPt ? aboutPt : this.getEyePoint(); const rotation = Matrix3d.createRotationAroundVector(axis, angle); if (!rotation) - return ViewStatus.InvalidUpVector; // Invalid axis given + return ViewStatus.InvalidUpVector; // Invalid axis given const trans = Transform.createFixedPointAndMatrix(about, rotation); const targetPoint = trans.multiplyPoint3d(this.getTargetPoint()); const upVector = rotation.multiplyVector(this.getYVector()); @@ -1993,7 +2125,10 @@ export abstract class ViewState3d extends ViewState { return ViewStatus.NotEllipsoidGlobeMode; const earthCenter = this.iModel.ecefLocation?.earthCenter; - const rMatrix = Matrix3d.createRotationVectorToVector(Vector3d.createStartEnd(earthCenter, toPoint), Vector3d.createStartEnd(earthCenter, fromPoint)); + const rMatrix = Matrix3d.createRotationVectorToVector( + Vector3d.createStartEnd(earthCenter, toPoint), + Vector3d.createStartEnd(earthCenter, fromPoint), + ); if (!rMatrix) return ViewStatus.DegenerateGeometry; @@ -2007,7 +2142,9 @@ export abstract class ViewState3d extends ViewState { } /** Get the distance from the eyePoint to the front plane for this view. */ - public getFrontDistance(): number { return this.getBackDistance() - this.extents.z; } + public getFrontDistance(): number { + return this.getBackDistance() - this.extents.z; + } /** Get the distance from the eyePoint to the back plane for this view. */ public getBackDistance(): number { @@ -2076,10 +2213,14 @@ export abstract class ViewState3d extends ViewState { } /** Get the current location of the eyePoint for camera in this view. */ - public getEyePoint(): Point3d { return this.camera.eye; } + public getEyePoint(): Point3d { + return this.camera.eye; + } /** Get the lens angle for this view. */ - public getLensAngle(): Angle { return this.camera.lens; } + public getLensAngle(): Angle { + return this.camera.lens; + } /** Set the lens angle for this view. * @param angle The new lens angle in radians. Must be greater than 0 and less than pi. @@ -2087,23 +2228,31 @@ export abstract class ViewState3d extends ViewState { * is subsequently modified and the lens angle is used to position the eyepoint. * @note To change the field-of-view (i.e. "zoom") of a view, pass a new viewDelta to #lookAt */ - public setLensAngle(angle: Angle): void { this.camera.setLensAngle(angle); } + public setLensAngle(angle: Angle): void { + this.camera.setLensAngle(angle); + } /** Change the location of the eyePoint for the camera in this view. * @param pt The new eyepoint. * @note This method is generally for internal use only. Moving the eyePoint arbitrarily can result in skewed or illegal perspectives. * The most common method for user-level camera positioning is #lookAt. */ - public setEyePoint(pt: XYAndZ): void { this.camera.setEyePoint(pt); } + public setEyePoint(pt: XYAndZ): void { + this.camera.setEyePoint(pt); + } /** Set the focus distance for this view. * @note Changing the focus distance changes the plane on which the delta.x and delta.y values lie. So, changing focus distance * without making corresponding changes to delta.x and delta.y essentially changes the lens angle, causing a "zoom" effect */ - public setFocusDistance(dist: number): void { this.camera.setFocusDistance(dist); } + public setFocusDistance(dist: number): void { + this.camera.setFocusDistance(dist); + } /** Get the distance from the eyePoint to the focus plane for this view. */ - public getFocusDistance(): number { return this.camera.focusDist; } + public getFocusDistance(): number { + return this.camera.focusDist; + } /** Obtain an "eye" point for this view. If the camera is on, this simply returns [[Camera.getEyePoint]]. * Otherwise, a pseudo-eye-point is computed from the view direction and a lens angle of PI/2. @@ -2118,9 +2267,11 @@ export abstract class ViewState3d extends ViewState { const eyeDistance = tanHalfAngle ? (halfDelta / tanHalfAngle) : 0; const zVector = this.getRotation().getRow(2); - return this.getCenter().plusScaled(zVector, - eyeDistance); + return this.getCenter().plusScaled(zVector, -eyeDistance); + } + public createAuxCoordSystem(acsName: string): AuxCoordSystemState { + return AuxCoordSystem3dState.createNew(acsName, this.iModel); } - public createAuxCoordSystem(acsName: string): AuxCoordSystemState { return AuxCoordSystem3dState.createNew(acsName, this.iModel); } public override decorate(context: DecorateContext): void { super.decorate(context); @@ -2150,11 +2301,11 @@ export abstract class ViewState3d extends ViewState { // first determine whether the ground plane is displayed in the view const worldFrust = vp.getFrustum(); for (const point of worldFrust.points) { - viewRay.origin = point; // We never modify the reference + viewRay.origin = point; // We never modify the reference const xyzPoint = Point3d.create(); const param = viewRay.intersectionWithPlane(xyPlane!, xyzPoint); if (param === undefined) - return extents; // View does not show ground plane + return extents; // View does not show ground plane } } @@ -2165,7 +2316,7 @@ export abstract class ViewState3d extends ViewState { const radius = extents.low.distance(extents.high); extents.setNull(); - extents.extendPoint(center); // Extents now contains single point + extents.extendPoint(center); // Extents now contains single point extents.low.addScaledInPlace(Vector3d.create(-1, -1, -1), radius); extents.high.addScaledInPlace(Vector3d.create(1, 1, 1), radius); extents.low.z = extents.high.z = elevation; @@ -2287,12 +2438,16 @@ export abstract class ViewState3d extends ViewState { */ export abstract class ViewState2d extends ViewState { private readonly _details: ViewDetails; - public static override get className() { return "ViewDefinition2d"; } + public static override get className() { + return "ViewDefinition2d"; + } public readonly origin: Point2d; public readonly delta: Point2d; public readonly angle: Angle; protected _baseModelId: Id64String; - public get baseModelId(): Id64String { return this._baseModelId; } + public get baseModelId(): Id64String { + return this._baseModelId; + } /** @internal */ protected _treeRef?: TileTreeReference; @@ -2326,13 +2481,19 @@ export abstract class ViewState2d extends ViewState { } /** See [[ViewState.is3d]]. */ - public is3d(): this is ViewState3d { return false; } + public is3d(): this is ViewState3d { + return false; + } /** @internal */ - public isSpatialView(): this is SpatialViewState { return false; } + public isSpatialView(): this is SpatialViewState { + return false; + } /** Capture a copy of the viewed area. */ - public savePose(): ViewPose2d { return new ViewPose2d(this); } + public savePose(): ViewPose2d { + return new ViewPose2d(this); + } /** See [[ViewState.applyPose]]. */ public applyPose(val: ViewPose) { @@ -2394,18 +2555,32 @@ export abstract class ViewState2d extends ViewState { return this._details; } - public allow3dManipulations(): boolean { return false; } - public getOrigin() { return new Point3d(this.origin.x, this.origin.y, Frustum2d.minimumZExtents.low); } - public getExtents() { return new Vector3d(this.delta.x, this.delta.y, Frustum2d.minimumZExtents.length()); } - public getRotation() { return Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle)!; } - public setExtents(delta: XAndY) { this.delta.set(delta.x, delta.y); } - public setOrigin(origin: XAndY) { this.origin.set(origin.x, origin.y); } + public allow3dManipulations(): boolean { + return false; + } + public getOrigin() { + return new Point3d(this.origin.x, this.origin.y, Frustum2d.minimumZExtents.low); + } + public getExtents() { + return new Vector3d(this.delta.x, this.delta.y, Frustum2d.minimumZExtents.length()); + } + public getRotation() { + return Matrix3d.createRotationAroundVector(Vector3d.unitZ(), this.angle)!; + } + public setExtents(delta: XAndY) { + this.delta.set(delta.x, delta.y); + } + public setOrigin(origin: XAndY) { + this.origin.set(origin.x, origin.y); + } public setRotation(rot: Matrix3d) { const xColumn = rot.getColumn(0); this.angle.setRadians(Math.atan2(xColumn.y, xColumn.x)); } - public viewsModel(modelId: Id64String) { return this.baseModelId === modelId; } + public viewsModel(modelId: Id64String) { + return this.baseModelId === modelId; + } public forEachModel(func: (model: GeometricModelState) => void) { const model = this.iModel.models.getLoaded(this.baseModelId); if (undefined !== model && undefined !== model.asGeometricModel2d) @@ -2419,5 +2594,7 @@ export abstract class ViewState2d extends ViewState { func(ref); } - public createAuxCoordSystem(acsName: string): AuxCoordSystemState { return AuxCoordSystem2dState.createNew(acsName, this.iModel); } + public createAuxCoordSystem(acsName: string): AuxCoordSystemState { + return AuxCoordSystem2dState.createNew(acsName, this.iModel); + } } diff --git a/core/frontend/src/ViewingSpace.ts b/core/frontend/src/ViewingSpace.ts index ccd63f41ac77..1a4c06ff89aa 100644 --- a/core/frontend/src/ViewingSpace.ts +++ b/core/frontend/src/ViewingSpace.ts @@ -6,17 +6,31 @@ * @module Views */ +import { AxisAlignedBox3d, Frustum, GridOrientationType, Npc, NpcCorners } from "@itwin/core-common"; import { - AxisOrder, ClipPlaneContainment, Constant, Map4d, Matrix3d, Plane3dByOriginAndUnitNormal, Point3d, Point4d, Range1d, Range2d, Range3d, Transform, Vector3d, XYAndZ, XYZ, + AxisOrder, + ClipPlaneContainment, + Constant, + Map4d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point3d, + Point4d, + Range1d, + Range2d, + Range3d, + Transform, + Vector3d, + XYAndZ, + XYZ, } from "@itwin/core-geometry"; -import { AxisAlignedBox3d, Frustum, GridOrientationType, Npc, NpcCorners } from "@itwin/core-common"; import { ApproximateTerrainHeights } from "./ApproximateTerrainHeights"; +import { getFrustumPlaneIntersectionDepthRange } from "./BackgroundMapGeometry"; +import { ViewRect } from "./common/ViewRect"; import { CoordSystem } from "./CoordSystem"; +import { Frustum2d } from "./Frustum2d"; import { Viewport } from "./Viewport"; -import { ViewRect } from "./common/ViewRect"; import { ViewState } from "./ViewState"; -import { Frustum2d } from "./Frustum2d"; -import { getFrustumPlaneIntersectionDepthRange } from "./BackgroundMapGeometry"; /** Describes a [[Viewport]]'s viewing volume, plus its size on the screen. A new * instance of ViewingSpace is created every time the Viewport's frustum changes. @@ -53,15 +67,19 @@ export class ViewingSpace { /** Providers conversions between world and Npc (non-dimensional perspective) coordinates. */ public readonly worldToNpcMap = Map4d.createIdentity(); /** @internal */ - public readonly zClipAdjusted: boolean = false; // were the view z clip planes adjusted due to front/back clipping off? + public readonly zClipAdjusted: boolean = false; // were the view z clip planes adjusted due to front/back clipping off? /** Eye point - undefined if not a perspective projection. */ public readonly eyePoint: Point3d | undefined; private _view: ViewState; /** The ViewState for this Viewport */ - public get view(): ViewState { return this._view; } - public set view(view: ViewState) { this._view = view; } + public get view(): ViewState { + return this._view; + } + public set view(view: ViewState) { + this._view = view; + } private readonly _clientWidth: number; private readonly _clientHeight: number; @@ -83,9 +101,13 @@ export class ViewingSpace { } /** @internal */ - public toViewOrientation(from: XYZ, to?: XYZ) { this.rotation.multiplyVectorInPlace(ViewingSpace._copyOutput(from, to)); } + public toViewOrientation(from: XYZ, to?: XYZ) { + this.rotation.multiplyVectorInPlace(ViewingSpace._copyOutput(from, to)); + } /** @internal */ - public fromViewOrientation(from: XYZ, to?: XYZ) { this.rotation.multiplyTransposeVectorInPlace(ViewingSpace._copyOutput(from, to)); } + public fromViewOrientation(from: XYZ, to?: XYZ) { + this.rotation.multiplyTransposeVectorInPlace(ViewingSpace._copyOutput(from, to)); + } /** Ensure the rotation matrix for this view is aligns the root z with the view out (i.e. a "2d view"). */ private alignWithRootZ() { @@ -169,7 +191,7 @@ export class ViewingSpace { let gridPlane; if (this.view.viewFlags.grid) { const gridOrigin = this.view.isSpatialView() ? this.view.iModel.globalOrigin : Point3d.create(); - switch(this.view.getGridOrientation()) { + switch (this.view.getGridOrientation()) { case GridOrientationType.WorldXY: gridPlane = Plane3dByOriginAndUnitNormal.create(gridOrigin, Vector3d.create(0, 0, 1)); break; @@ -192,7 +214,13 @@ export class ViewingSpace { const viewZ = this.rotation.getRow(2); const eyeDepth = this.eyePoint ? viewZ.dotProduct(this.eyePoint) : undefined; - depthRange = globalGeometry.geometry.getFrustumIntersectionDepthRange(frustum, extents, globalGeometry.heightRange, gridPlane, this.view.maxGlobalScopeFactor > 1); + depthRange = globalGeometry.geometry.getFrustumIntersectionDepthRange( + frustum, + extents, + globalGeometry.heightRange, + gridPlane, + this.view.maxGlobalScopeFactor > 1, + ); if (eyeDepth !== undefined) { const maxBackgroundFrontBackRatio = 1.0E6; @@ -202,7 +230,7 @@ export class ViewingSpace { depthRange.high = eyeDepth - backDist / maxBackgroundFrontBackRatio; } } else - depthRange = gridPlane ? getFrustumPlaneIntersectionDepthRange(frustum, gridPlane) : Range1d.createNull(); + depthRange = gridPlane ? getFrustumPlaneIntersectionDepthRange(frustum, gridPlane) : Range1d.createNull(); if (!extents.isNull) { const viewZ = this.rotation.getRow(2); @@ -214,8 +242,8 @@ export class ViewingSpace { if (depthRange.isNull) return; - this.rotation.multiplyVectorInPlace(origin); // put origin in view coordinates - origin.z = depthRange.low; // set origin to back of viewed extents + this.rotation.multiplyVectorInPlace(origin); // put origin in view coordinates + origin.z = depthRange.low; // set origin to back of viewed extents delta.z = Math.max(depthRange.high - depthRange.low, ViewingSpace._minDepth); // and delta to front of viewed extents this.rotation.multiplyTransposeVectorInPlace(origin); @@ -230,7 +258,7 @@ export class ViewingSpace { // that the camera is outside the viewed extents and pointed away from it. There's nothing to see anyway. if (eyeOrg.z < 1.0) { this.rotation.multiplyVectorInPlace(origin); - origin.z -= (2.0 - eyeOrg.z); + origin.z -= 2.0 - eyeOrg.z; this.rotation.multiplyTransposeVectorInPlace(origin); delta.z = 1.0; return; @@ -257,7 +285,7 @@ export class ViewingSpace { const corners = this._viewCorners; const viewRect = this._viewRect; corners.high.x = viewRect.right; - corners.low.y = viewRect.bottom; // y's are swapped on the screen! + corners.low.y = viewRect.bottom; // y's are swapped on the screen! corners.low.x = 0; corners.high.y = 0; corners.low.z = -32767; @@ -333,7 +361,7 @@ export class ViewingSpace { if (frontDist < minFrontDist) { // camera is too close to front plane, move origin away from eye to maintain a minimum front distance. this.toViewOrientation(origin); - origin.z -= (minFrontDist - frontDist); + origin.z -= minFrontDist - frontDist; this.fromViewOrientation(origin); } } @@ -349,7 +377,12 @@ export class ViewingSpace { this.viewOrigin.setFrom(origin); this.viewDelta.setFrom(delta); - const newRootToNpc = this.view.computeWorldToNpc(this.rotation, origin, delta, !this.view.displayStyle.getIsBackgroundMapVisible() /* if displaying background map, don't enforce front/back ratio as no Z-Buffer */); + const newRootToNpc = this.view.computeWorldToNpc( + this.rotation, + origin, + delta, + !this.view.displayStyle.getIsBackgroundMapVisible(), /* if displaying background map, don't enforce front/back ratio as no Z-Buffer */ + ); if (newRootToNpc.map === undefined) { this.frustFraction = 0; // invalid frustum return; @@ -401,54 +434,78 @@ export class ViewingSpace { } /** Convert an array of points from CoordSystem.World to CoordSystem.Npc */ - public worldToNpcArray(pts: Point3d[]): void { this.worldToNpcMap.transform0.multiplyPoint3dArrayQuietNormalize(pts); } + public worldToNpcArray(pts: Point3d[]): void { + this.worldToNpcMap.transform0.multiplyPoint3dArrayQuietNormalize(pts); + } /** Convert an array of points from CoordSystem.Npc to CoordSystem.World */ - public npcToWorldArray(pts: Point3d[]): void { this.worldToNpcMap.transform1.multiplyPoint3dArrayQuietNormalize(pts); } + public npcToWorldArray(pts: Point3d[]): void { + this.worldToNpcMap.transform1.multiplyPoint3dArrayQuietNormalize(pts); + } /** Convert an array of points from CoordSystem.World to CoordSystem.View */ - public worldToViewArray(pts: Point3d[]): void { this.worldToViewMap.transform0.multiplyPoint3dArrayQuietNormalize(pts); } + public worldToViewArray(pts: Point3d[]): void { + this.worldToViewMap.transform0.multiplyPoint3dArrayQuietNormalize(pts); + } /** Convert an array of points from CoordSystem.World to CoordSystem.View, as Point4ds */ - public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { this.worldToViewMap.transform0.multiplyPoint3dArray(worldPts, viewPts); } + public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { + this.worldToViewMap.transform0.multiplyPoint3dArray(worldPts, viewPts); + } /** Convert an array of points from CoordSystem.View to CoordSystem.World */ - public viewToWorldArray(pts: Point3d[]) { this.worldToViewMap.transform1.multiplyPoint3dArrayQuietNormalize(pts); } + public viewToWorldArray(pts: Point3d[]) { + this.worldToViewMap.transform1.multiplyPoint3dArrayQuietNormalize(pts); + } /** Convert an array of points from CoordSystem.View as Point4ds to CoordSystem.World */ - public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { this.worldToViewMap.transform1.multiplyPoint4dArrayQuietRenormalize(viewPts, worldPts); } + public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { + this.worldToViewMap.transform1.multiplyPoint4dArrayQuietRenormalize(viewPts, worldPts); + } /** * Convert a point from CoordSystem.World to CoordSystem.Npc * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { return this.worldToNpcMap.transform0.multiplyPoint3dQuietNormalize(pt, out); } + public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { + return this.worldToNpcMap.transform0.multiplyPoint3dQuietNormalize(pt, out); + } /** * Convert a point from CoordSystem.Npc to CoordSystem.World * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { return this.worldToNpcMap.transform1.multiplyPoint3dQuietNormalize(pt, out); } + public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { + return this.worldToNpcMap.transform1.multiplyPoint3dQuietNormalize(pt, out); + } /** * Convert a point from CoordSystem.World to CoordSystem.View * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public worldToView(input: XYAndZ, out?: Point3d): Point3d { return this.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(input, out); } + public worldToView(input: XYAndZ, out?: Point3d): Point3d { + return this.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(input, out); + } /** * Convert a point from CoordSystem.World to CoordSystem.View as Point4d * @param input the point to convert * @param out optional location for result. If undefined, a new Point4d is created. */ - public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { return this.worldToViewMap.transform0.multiplyPoint3d(input, 1.0, out); } + public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { + return this.worldToViewMap.transform0.multiplyPoint3d(input, 1.0, out); + } /** * Convert a point from CoordSystem.View to CoordSystem.World * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { return this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(input, out); } + public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { + return this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(input, out); + } /** * Convert a point from CoordSystem.View as a Point4d to CoordSystem.View * @param input the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public view4dToWorld(input: Point4d, out?: Point3d): Point3d { return this.worldToViewMap.transform1.multiplyXYZWQuietRenormalize(input.x, input.y, input.z, input.w, out); } + public view4dToWorld(input: Point4d, out?: Point3d): Point3d { + return this.worldToViewMap.transform1.multiplyXYZWQuietRenormalize(input.x, input.y, input.z, input.w, out); + } /** Get an 8-point Frustum corresponding to the 8 corners of the Viewport in the specified coordinate system. * diff --git a/core/frontend/src/Viewport.ts b/core/frontend/src/Viewport.ts index c48ce27a1301..84f4af934944 100644 --- a/core/frontend/src/Viewport.ts +++ b/core/frontend/src/Viewport.ts @@ -7,33 +7,94 @@ */ import { - asInstanceOf, assert, BeDuration, BeEvent, BeTimePoint, Constructor, dispose, Id64, Id64Arg, Id64Set, Id64String, IDisposable, isInstanceOf, + asInstanceOf, + assert, + BeDuration, + BeEvent, + BeTimePoint, + Constructor, + dispose, + Id64, + Id64Arg, + Id64Set, + Id64String, + IDisposable, + isInstanceOf, StopWatch, } from "@itwin/core-bentley"; import { - Angle, AngleSweep, Arc3d, Geometry, LowAndHighXY, LowAndHighXYZ, Map4d, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, Point4d, Range1d, - Range3d, Ray3d, Transform, Vector3d, XAndY, XYAndZ, XYZ, -} from "@itwin/core-geometry"; -import { - AnalysisStyle, BackgroundMapProps, BackgroundMapProviderProps, BackgroundMapSettings, Camera, CartographicRange, ClipStyle, ColorDef, DisplayStyleSettingsProps, - Easing, ElementProps, FeatureAppearance, Frustum, GlobeMode, GridOrientationType, Hilite, ImageBuffer, - Interpolation, isPlacement2dProps, LightSettings, ModelMapLayerSettings, Npc, NpcCenter, Placement, - Placement2d, Placement3d, PlacementProps, SolarShadowSettings, SubCategoryAppearance, SubCategoryOverride, ViewFlags, + AnalysisStyle, + BackgroundMapProps, + BackgroundMapProviderProps, + BackgroundMapSettings, + Camera, + CartographicRange, + ClipStyle, + ColorDef, + DisplayStyleSettingsProps, + Easing, + ElementProps, + FeatureAppearance, + Frustum, + GlobeMode, + GridOrientationType, + Hilite, + ImageBuffer, + Interpolation, + isPlacement2dProps, + LightSettings, + ModelMapLayerSettings, + Npc, + NpcCenter, + Placement, + Placement2d, + Placement3d, + PlacementProps, + SolarShadowSettings, + SubCategoryAppearance, + SubCategoryOverride, + ViewFlags, } from "@itwin/core-common"; +import { + Angle, + AngleSweep, + Arc3d, + Geometry, + LowAndHighXY, + LowAndHighXYZ, + Map4d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Point4d, + Range1d, + Range3d, + Ray3d, + Transform, + Vector3d, + XAndY, + XYAndZ, + XYZ, +} from "@itwin/core-geometry"; import { AuxCoordSystemState } from "./AuxCoordSys"; import { BackgroundMapGeometry } from "./BackgroundMapGeometry"; import { ChangeFlag, ChangeFlags, MutableChangeFlags } from "./ChangeFlags"; +import { GraphicType } from "./common/render/GraphicType"; +import { ViewRect } from "./common/ViewRect"; import { CoordSystem } from "./CoordSystem"; import { DecorationsCache } from "./DecorationsCache"; import { DisplayStyleState } from "./DisplayStyleState"; import { ElementPicker, LocateOptions } from "./ElementLocateManager"; import { FeatureOverrideProvider } from "./FeatureOverrideProvider"; +import { FlashSettings } from "./FlashSettings"; import { FrustumAnimator } from "./FrustumAnimator"; import { GlobeAnimator } from "./GlobeAnimator"; import { HitDetail, SnapDetail } from "./HitDetail"; import { IModelApp } from "./IModelApp"; import { IModelConnection } from "./IModelConnection"; import { linePlaneIntersect } from "./LinePlaneIntersect"; +import { GeometricModelState } from "./ModelState"; import { ToolTipOptions } from "./NotificationManager"; import { PerModelCategoryVisibility } from "./PerModelCategoryVisibility"; import { Decorations } from "./render/Decorations"; @@ -45,11 +106,26 @@ import { GraphicList } from "./render/RenderGraphic"; import { RenderMemory } from "./render/RenderMemory"; import { createRenderPlanFromViewport } from "./render/RenderPlan"; import { RenderTarget } from "./render/RenderTarget"; +import { queryVisibleFeatures, QueryVisibleFeaturesCallback, QueryVisibleFeaturesOptions } from "./render/VisibleFeature"; import { StandardView, StandardViewId } from "./StandardView"; import { SubCategoriesCache } from "./SubCategoriesCache"; import { - DisclosedTileTreeSet, MapCartoRectangle, MapFeatureInfo, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProvider, MapLayerIndex, MapLayerInfoFromTileTree, MapTiledGraphicsProvider, - MapTileTreeReference, MapTileTreeScaleRangeVisibility, TileBoundingBoxes, TiledGraphicsProvider, TileTreeLoadStatus, TileTreeReference, TileUser, + DisclosedTileTreeSet, + MapCartoRectangle, + MapFeatureInfo, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapLayerImageryProvider, + MapLayerIndex, + MapLayerInfoFromTileTree, + MapTiledGraphicsProvider, + MapTileTreeReference, + MapTileTreeScaleRangeVisibility, + TileBoundingBoxes, + TiledGraphicsProvider, + TileTreeLoadStatus, + TileTreeReference, + TileUser, } from "./tile/internal"; import { EventController } from "./tools/EventController"; import { ToolSettings } from "./tools/ToolSettings"; @@ -58,13 +134,8 @@ import { DecorateContext, SceneContext } from "./ViewContext"; import { GlobalLocation, viewGlobalLocation, ViewGlobalLocationConstants } from "./ViewGlobalLocation"; import { ViewingSpace } from "./ViewingSpace"; import { ViewPose } from "./ViewPose"; -import { ViewRect } from "./common/ViewRect"; import { ModelDisplayTransformProvider, ViewState } from "./ViewState"; import { ViewStatus } from "./ViewStatus"; -import { queryVisibleFeatures, QueryVisibleFeaturesCallback, QueryVisibleFeaturesOptions } from "./render/VisibleFeature"; -import { FlashSettings } from "./FlashSettings"; -import { GeometricModelState } from "./ModelState"; -import { GraphicType } from "./common/render/GraphicType"; // cSpell:Ignore rect's ovrs subcat subcats unmounting UI's @@ -161,7 +232,10 @@ export interface ChangeViewedModel2dOptions { * @see [[Viewport.onViewUndoRedo]]. * @public */ -export enum ViewUndoEvent { Undo = 0, Redo = 1 } +export enum ViewUndoEvent { + Undo = 0, + Redo = 1, +} /** @internal */ export const ELEMENT_MARKED_FOR_REMOVAL = Symbol.for("@bentley/imodeljs/Viewport/__element_marked_for_removal__"); @@ -229,13 +303,13 @@ export interface ReadImageBufferArgs { */ export interface MapLayerScaleRangeVisibility { /** True if map-layer is part of [[DisplayStyleState]]'s overlay map, otherwise map-layer is part of [[DisplayStyleState]]'s background map - * @see [[DisplayStyleState.mapLayerAtIndex]]. - */ + * @see [[DisplayStyleState.mapLayerAtIndex]]. + */ isOverlay: boolean; /** Index of the map-layer in [[DisplayStyleState]]'s background/overlay map * @see [[DisplayStyleState.mapLayerAtIndex]]. - */ + */ index: number; /** Scale range visibility value of the map-layer */ @@ -337,8 +411,8 @@ export abstract class Viewport implements IDisposable, TileUser { public readonly onFlashedIdChanged = new BeEvent<(vp: Viewport, args: OnFlashedIdChangedEventArgs) => void>(); /** Event indicating when a map-layer scale range visibility change for the current viewport scale. - * @beta - */ + * @beta + */ public readonly onMapLayerScaleRangeVisibilityChanged = new BeEvent<(layerIndexes: MapLayerScaleRangeVisibility[]) => void>(); /** Event invoked every time [[invalidateScene]] is called. * @note This event will be raised **very** frequently. Avoid doing significant work inside of your event listener. @@ -367,29 +441,47 @@ export abstract class Viewport implements IDisposable, TileUser { /** @internal */ protected _sceneValid = false; /** @internal */ - public get sceneValid() { return this._sceneValid; } + public get sceneValid() { + return this._sceneValid; + } /** @internal */ protected _renderPlanValid = false; /** @internal */ - public get renderPlanValid() { return this._renderPlanValid; } + public get renderPlanValid() { + return this._renderPlanValid; + } /** @internal */ - public setRenderPlanValid() { this._renderPlanValid = true; } + public setRenderPlanValid() { + this._renderPlanValid = true; + } /** @internal */ protected _controllerValid = false; /** @internal */ - public get controllerValid() { return this._controllerValid; } + public get controllerValid() { + return this._controllerValid; + } private _redrawPending = false; private _analysisFractionValid = false; /** @internal */ - public get analysisFractionValid() { return this._analysisFractionValid; } + public get analysisFractionValid() { + return this._analysisFractionValid; + } private _timePointValid = false; /** @internal */ - public get timePointValid() { return this._timePointValid; } + public get timePointValid() { + return this._timePointValid; + } /** Strictly for tests. @internal */ public setAllValid(): void { - this._sceneValid = this._decorationsValid = this._renderPlanValid = this._controllerValid = this._redrawPending - = this._analysisFractionValid = this._timePointValid = true; + this._sceneValid = + this._decorationsValid = + this._renderPlanValid = + this._controllerValid = + this._redrawPending = + this._analysisFractionValid = + this._timePointValid = + true; } /** Mark the current set of decorations invalid, so that they will be recreated on the next render frame. @@ -472,7 +564,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** For debug purposes, controls whether or not view attachments are displayed in sheet views. * @internal */ - public get wantViewAttachments() { return this._wantViewAttachments; } + public get wantViewAttachments() { + return this._wantViewAttachments; + } public set wantViewAttachments(want: boolean) { if (want !== this._wantViewAttachments) { this._wantViewAttachments = want; @@ -484,7 +578,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** For debug purposes, controls whether or not the boundary of each view attachment is displayed in a sheet view. * @internal */ - public get wantViewAttachmentBoundaries() { return this._wantViewAttachmentBoundaries; } + public get wantViewAttachmentBoundaries() { + return this._wantViewAttachmentBoundaries; + } public set wantViewAttachmentBoundaries(want: boolean) { if (want !== this._wantViewAttachmentBoundaries) { this._wantViewAttachmentBoundaries = want; @@ -496,7 +592,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** For debug purposes, controls whether or not graphics representing the clipping shapes of each view attachment are displayed in a sheet view. * @internal */ - public get wantViewAttachmentClipShapes() { return this._wantViewAttachmentClipShapes; } + public get wantViewAttachmentClipShapes() { + return this._wantViewAttachmentClipShapes; + } public set wantViewAttachmentClipShapes(want: boolean) { if (want !== this._wantViewAttachmentClipShapes) { this._wantViewAttachmentClipShapes = want; @@ -541,18 +639,30 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @public */ - public get viewingSpace(): ViewingSpace { return this._viewingSpace; } + public get viewingSpace(): ViewingSpace { + return this._viewingSpace; + } /** This viewport's rotation matrix. */ - public get rotation(): Matrix3d { return this._viewingSpace.rotation; } + public get rotation(): Matrix3d { + return this._viewingSpace.rotation; + } /** The vector between the opposite corners of this viewport's extents. */ - public get viewDelta(): Vector3d { return this._viewingSpace.viewDelta; } + public get viewDelta(): Vector3d { + return this._viewingSpace.viewDelta; + } /** Provides conversions between world and view coordinates. */ - public get worldToViewMap(): Map4d { return this._viewingSpace.worldToViewMap; } + public get worldToViewMap(): Map4d { + return this._viewingSpace.worldToViewMap; + } /** Provides conversions between world and Npc (non-dimensional perspective) coordinates. */ - public get worldToNpcMap(): Map4d { return this._viewingSpace.worldToNpcMap; } + public get worldToNpcMap(): Map4d { + return this._viewingSpace.worldToNpcMap; + } /** @internal */ - public get frustFraction(): number { return this._viewingSpace.frustFraction; } + public get frustFraction(): number { + return this._viewingSpace.frustFraction; + } /** See [DisplayStyleSettings.analysisFraction]($common). */ public get analysisFraction(): number { @@ -578,7 +688,9 @@ export abstract class Viewport implements IDisposable, TileUser { */ public abstract get viewRect(): ViewRect; /** @internal */ - public get isAspectRatioLocked(): boolean { return false; } + public get isAspectRatioLocked(): boolean { + return false; + } /** @internal */ public get target(): RenderTarget { @@ -595,7 +707,9 @@ export abstract class Viewport implements IDisposable, TileUser { } /** The settings that control how elements are hilited in this Viewport. */ - public get hilite(): Hilite.Settings { return this._hilite; } + public get hilite(): Hilite.Settings { + return this._hilite; + } public set hilite(hilite: Hilite.Settings) { this._hilite = hilite; this.invalidateRenderPlan(); @@ -604,7 +718,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** The settings that control how emphasized elements are displayed in this Viewport. The default settings apply a thick black silhouette to the emphasized elements. * @see [FeatureAppearance.emphasized]($common). */ - public get emphasisSettings(): Hilite.Settings { return this._emphasis; } + public get emphasisSettings(): Hilite.Settings { + return this._emphasis; + } public set emphasisSettings(settings: Hilite.Settings) { this._emphasis = settings; this.invalidateRenderPlan(); @@ -622,18 +738,24 @@ export abstract class Viewport implements IDisposable, TileUser { /** Determine whether the Grid display is currently enabled in this Viewport. * @return true if the grid display is on. */ - public get isGridOn(): boolean { return this.viewFlags.grid; } + public get isGridOn(): boolean { + return this.viewFlags.grid; + } /** Flags controlling aspects of how the contents of this viewport are rendered. * @see [DisplayStyleSettings.viewFlags]($common). */ - public get viewFlags(): ViewFlags { return this.view.viewFlags; } + public get viewFlags(): ViewFlags { + return this.view.viewFlags; + } public set viewFlags(viewFlags: ViewFlags) { this.view.displayStyle.viewFlags = viewFlags; } /** See [[ViewState.displayStyle]] */ - public get displayStyle(): DisplayStyleState { return this.view.displayStyle; } + public get displayStyle(): DisplayStyleState { + return this.view.displayStyle; + } public set displayStyle(style: DisplayStyleState) { this.view.displayStyle = style; } @@ -646,7 +768,9 @@ export abstract class Viewport implements IDisposable, TileUser { } /** See [DisplayStyleSettings.clipStyle]($common) */ - public get clipStyle(): ClipStyle { return this.displayStyle.settings.clipStyle; } + public get clipStyle(): ClipStyle { + return this.displayStyle.settings.clipStyle; + } public set clipStyle(style: ClipStyle) { this.displayStyle.settings.clipStyle = style; } @@ -725,7 +849,9 @@ export abstract class Viewport implements IDisposable, TileUser { * @returns true if the subcategory is visible in this viewport. * @note Because this function does not know the Id of the containing Category, it does not check if the Category is enabled for display. The caller should check that separately if he knows the Id of the Category. */ - public isSubCategoryVisible(id: Id64String): boolean { return this.view.isSubCategoryVisible(id); } + public isSubCategoryVisible(id: Id64String): boolean { + return this.view.isSubCategoryVisible(id); + } /** Override the appearance of a model when rendered within this viewport. * @param id The Id of the model. @@ -794,7 +920,9 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal */ - public getSubCategories(categoryId: Id64String): Id64Set | undefined { return this.iModel.subcategories.getSubCategories(categoryId); } + public getSubCategories(categoryId: Id64String): Id64Set | undefined { + return this.iModel.subcategories.getSubCategories(categoryId); + } /** Change the visibility of geometry belonging to the specified subcategory when displayed in this viewport. * @param subCategoryId The Id of the subcategory @@ -809,7 +937,9 @@ export abstract class Viewport implements IDisposable, TileUser { * @see [[ViewFlags.backgroundMap]] for toggling display of the map on or off. * @see [DisplayStyleSettings.backgroundMap]($common) */ - public get backgroundMapSettings(): BackgroundMapSettings { return this.displayStyle.backgroundMapSettings; } + public get backgroundMapSettings(): BackgroundMapSettings { + return this.displayStyle.backgroundMapSettings; + } public set backgroundMapSettings(settings: BackgroundMapSettings) { this.displayStyle.backgroundMapSettings = settings; } @@ -825,19 +955,27 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal */ - public get backgroundMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundMap; } + public get backgroundMap(): MapTileTreeReference | undefined { + return this._mapTiledGraphicsProvider?.backgroundMap; + } /** @internal */ - public get overlayMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.overlayMap; } + public get overlayMap(): MapTileTreeReference | undefined { + return this._mapTiledGraphicsProvider?.overlayMap; + } /** @internal */ - public get backgroundDrapeMap(): MapTileTreeReference | undefined { return this._mapTiledGraphicsProvider?.backgroundDrapeMap; } + public get backgroundDrapeMap(): MapTileTreeReference | undefined { + return this._mapTiledGraphicsProvider?.backgroundDrapeMap; + } /** Return the imagery provider for the provided map-layer index. * @param mapLayerIndex the [[MapLayerIndex]] of the map layer. * @beta */ - public getMapLayerImageryProvider(mapLayerIndex: MapLayerIndex): MapLayerImageryProvider | undefined { return this._mapTiledGraphicsProvider?.getMapLayerImageryProvider(mapLayerIndex); } + public getMapLayerImageryProvider(mapLayerIndex: MapLayerIndex): MapLayerImageryProvider | undefined { + return this._mapTiledGraphicsProvider?.getMapLayerImageryProvider(mapLayerIndex); + } /** Return the map-layer scale range visibility for the provided map-layer index. * @param mapLayerIndex the [[MapLayerIndex]] of the map layer. @@ -845,10 +983,9 @@ export abstract class Viewport implements IDisposable, TileUser { * @beta */ public getMapLayerScaleRangeVisibility(mapLayerIndex: MapLayerIndex): MapTileTreeScaleRangeVisibility { - const treeRef = (mapLayerIndex.isOverlay ? this._mapTiledGraphicsProvider?.overlayMap : this._mapTiledGraphicsProvider?.backgroundMap); + const treeRef = mapLayerIndex.isOverlay ? this._mapTiledGraphicsProvider?.overlayMap : this._mapTiledGraphicsProvider?.backgroundMap; if (treeRef) { return treeRef.getMapLayerScaleRangeVisibility(mapLayerIndex.index); - } return MapTileTreeScaleRangeVisibility.Unknown; } @@ -920,10 +1057,14 @@ export abstract class Viewport implements IDisposable, TileUser { /** Fully reset a map-layer tile tree; by calling this, the map-layer will to go through initialize process again, and all previously fetched tile will be lost. * @beta */ - public resetMapLayer(mapLayerIndex: MapLayerIndex) { this._mapTiledGraphicsProvider?.resetMapLayer(mapLayerIndex); } + public resetMapLayer(mapLayerIndex: MapLayerIndex) { + this._mapTiledGraphicsProvider?.resetMapLayer(mapLayerIndex); + } /** Returns true if this Viewport is currently displaying the model with the specified Id. */ - public viewsModel(modelId: Id64String): boolean { return this.view.viewsModel(modelId); } + public viewsModel(modelId: Id64String): boolean { + return this.view.viewsModel(modelId); + } /** Attempt to change the 2d Model this Viewport is displaying, if its ViewState is a ViewState2d. * @param baseModelId The Id of the new 2d Model to be displayed. @@ -1022,7 +1163,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** Determines what type (if any) of debug graphics will be displayed to visualize [[Tile]] volumes. Chiefly for debugging. * @see [[TileBoundingBoxes]] */ - public get debugBoundingBoxes(): TileBoundingBoxes { return this._debugBoundingBoxes; } + public get debugBoundingBoxes(): TileBoundingBoxes { + return this._debugBoundingBoxes; + } public set debugBoundingBoxes(boxes: TileBoundingBoxes) { if (boxes !== this.debugBoundingBoxes) { this._debugBoundingBoxes = boxes; @@ -1032,7 +1175,9 @@ export abstract class Viewport implements IDisposable, TileUser { /** When true, the scene will never be recreated. Chiefly for debugging purposes. * @internal */ - public get freezeScene(): boolean { return this._freezeScene; } + public get freezeScene(): boolean { + return this._freezeScene; + } public set freezeScene(freeze: boolean) { if (freeze !== this._freezeScene) { this._freezeScene = freeze; @@ -1042,19 +1187,29 @@ export abstract class Viewport implements IDisposable, TileUser { } /** The iModel of this Viewport */ - public get iModel(): IModelConnection { return this.view.iModel; } + public get iModel(): IModelConnection { + return this.view.iModel; + } /** @internal */ - public get isPointAdjustmentRequired(): boolean { return this.view.is3d(); } + public get isPointAdjustmentRequired(): boolean { + return this.view.is3d(); + } /** @internal */ - public get isSnapAdjustmentRequired(): boolean { return IModelApp.toolAdmin.acsPlaneSnapLock && this.view.is3d(); } + public get isSnapAdjustmentRequired(): boolean { + return IModelApp.toolAdmin.acsPlaneSnapLock && this.view.is3d(); + } /** @internal */ - public get isContextRotationRequired(): boolean { return IModelApp.toolAdmin.acsContextLock; } + public get isContextRotationRequired(): boolean { + return IModelApp.toolAdmin.acsContextLock; + } /** Enables or disables "fade-out" mode. When this mode is enabled, transparent graphics are rendered with a flat alpha weight, * causing them to appear de-emphasized. This is typically used in contexts in which a handful of elements are to be emphasized in the view, * while the rest of the graphics are drawn transparently. */ - public get isFadeOutActive(): boolean { return this._fadeOutActive; } + public get isFadeOutActive(): boolean { + return this._fadeOutActive; + } public set isFadeOutActive(active: boolean) { if (active !== this._fadeOutActive) { this._fadeOutActive = active; @@ -1063,8 +1218,8 @@ export abstract class Viewport implements IDisposable, TileUser { } /** Obtain a tooltip from the map layer or reality model, if any, identified by the specified [[HitDetail]]. - * @see [[ElementLocateManager]] - */ + * @see [[ElementLocateManager]] + */ public async getToolTip(hit: HitDetail): Promise { const promises = new Array>(); this.view.forEachTileTreeRef((ref) => { @@ -1113,7 +1268,6 @@ export abstract class Viewport implements IDisposable, TileUser { const results = await Promise.all(promises); for (const result of results) if (result !== undefined) { - if (featureInfo.layerInfos === undefined) { featureInfo.layerInfos = []; } @@ -1342,7 +1496,6 @@ export abstract class Viewport implements IDisposable, TileUser { if (this._view) this._view.detachFromViewport(); - } private detachFromDisplayStyle(): void { @@ -1365,7 +1518,9 @@ export abstract class Viewport implements IDisposable, TileUser { * * @note An application which enables continuous rendering should disable it as soon as it is no longer needed. */ - public get continuousRendering(): boolean { return this._doContinuousRendering; } + public get continuousRendering(): boolean { + return this._doContinuousRendering; + } public set continuousRendering(contRend: boolean) { if (contRend !== this._doContinuousRendering) { this._doContinuousRendering = contRend; @@ -1393,20 +1548,26 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal */ - public get backgroundMapGeometry(): BackgroundMapGeometry | undefined { return this.view.displayStyle.getBackgroundMapGeometry(); } + public get backgroundMapGeometry(): BackgroundMapGeometry | undefined { + return this.view.displayStyle.getBackgroundMapGeometry(); + } /** Ids of a set of elements which should not be rendered within this view. * @note Do not modify this set directly - use [[setNeverDrawn]] or [[clearNeverDrawn]] instead. * @note This set takes precedence over the [[alwaysDrawn]] set - if an element is present in both sets, it is never drawn. */ - public get neverDrawn(): Id64Set | undefined { return this._neverDrawn; } + public get neverDrawn(): Id64Set | undefined { + return this._neverDrawn; + } /** Ids of a set of elements which should always be rendered within this view, regardless of category and subcategory visibility. * If the [[isAlwaysDrawnExclusive]] flag is also set, *only* those elements in this set will be drawn. * @note Do not modify this set directly - use [[setAlwaysDrawn]] or [[clearAlwaysDrawn]] instead. * @note The [[neverDrawn]] set takes precedence - if an element is present in both sets, it is never drawn. */ - public get alwaysDrawn(): Id64Set | undefined { return this._alwaysDrawn; } + public get alwaysDrawn(): Id64Set | undefined { + return this._alwaysDrawn; + } /** Clear the set of always-drawn elements. * @see [[alwaysDrawn]] @@ -1456,10 +1617,14 @@ export abstract class Viewport implements IDisposable, TileUser { } /** Returns true if the set of elements in the [[alwaysDrawn]] set are the *only* elements rendered within this view. */ - public get isAlwaysDrawnExclusive(): boolean { return this._alwaysDrawnExclusive; } + public get isAlwaysDrawnExclusive(): boolean { + return this._alwaysDrawnExclusive; + } /** Allows visibility of categories within this viewport to be overridden on a per-model basis. */ - public get perModelCategoryVisibility(): PerModelCategoryVisibility.Overrides { return this._perModelCategoryVisibility; } + public get perModelCategoryVisibility(): PerModelCategoryVisibility.Overrides { + return this._perModelCategoryVisibility; + } /** Adds visibility overrides for any subcategories whose visibility differs from that defined by the view's * category selector in the context of specific models. @@ -1661,7 +1826,9 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal */ - public markSelectionSetDirty() { this._selectionSetDirty = true; } + public markSelectionSetDirty() { + this._selectionSetDirty = true; + } /** True if this is a 3d view with the camera turned on. */ public get isCameraOn(): boolean { @@ -1713,14 +1880,22 @@ export abstract class Viewport implements IDisposable, TileUser { } } - public get auxCoordSystem(): AuxCoordSystemState { return this.view.auxiliaryCoordinateSystem; } - public getAuxCoordRotation(result?: Matrix3d) { return this.auxCoordSystem.getRotation(result); } - public getAuxCoordOrigin(result?: Point3d) { return this.auxCoordSystem.getOrigin(result); } + public get auxCoordSystem(): AuxCoordSystemState { + return this.view.auxiliaryCoordinateSystem; + } + public getAuxCoordRotation(result?: Matrix3d) { + return this.auxCoordSystem.getRotation(result); + } + public getAuxCoordOrigin(result?: Point3d) { + return this.auxCoordSystem.getOrigin(result); + } /** The number of outstanding requests for tiles to be displayed in this viewport. * @see Viewport.numSelectedTiles */ - public get numRequestedTiles(): number { return IModelApp.tileAdmin.getNumRequestsForUser(this); } + public get numRequestedTiles(): number { + return IModelApp.tileAdmin.getNumRequestsForUser(this); + } /** The number of tiles selected for display in the view as of the most recently-drawn frame. * The tiles selected may not meet the desired level-of-detail for the view, instead being temporarily drawn while @@ -1746,9 +1921,13 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal */ - public toViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.toViewOrientation(from, to); } + public toViewOrientation(from: XYZ, to?: XYZ) { + this._viewingSpace.toViewOrientation(from, to); + } /** @internal */ - public fromViewOrientation(from: XYZ, to?: XYZ) { this._viewingSpace.fromViewOrientation(from, to); } + public fromViewOrientation(from: XYZ, to?: XYZ) { + this._viewingSpace.fromViewOrientation(from, to); + } /** Change the ViewState of this Viewport * @param view a fully loaded (see discussion at [[ViewState.load]] ) ViewState @@ -1790,7 +1969,8 @@ export abstract class Viewport implements IDisposable, TileUser { const xBorder = screenRangeX * borderPaddingFactor; const yBorder = screenRangeY * borderPaddingFactor; - return (!(testPtView.x < xBorder || testPtView.x > (screenRangeX - xBorder) || testPtView.y < yBorder || testPtView.y > (screenRangeY - yBorder))); + return (!(testPtView.x < xBorder || testPtView.x > (screenRangeX - xBorder) || testPtView.y < yBorder || + testPtView.y > (screenRangeY - yBorder))); } /** Computes the range of npc depth values for a region of the screen @@ -1953,71 +2133,107 @@ export abstract class Viewport implements IDisposable, TileUser { /** Call [[setupFromView]] on this Viewport and then apply optional behavior. * @param options _options for behavior of view change. If undefined, all options have their default values (see [[ViewChangeOptions]] for details.) */ - public synchWithView(_options?: ViewChangeOptions): void { this.setupFromView(); } + public synchWithView(_options?: ViewChangeOptions): void { + this.setupFromView(); + } /** Convert an array of points from CoordSystem.View to CoordSystem.Npc */ - public viewToNpcArray(pts: Point3d[]): void { this._viewingSpace.viewToNpcArray(pts); } + public viewToNpcArray(pts: Point3d[]): void { + this._viewingSpace.viewToNpcArray(pts); + } /** Convert an array of points from CoordSystem.Npc to CoordSystem.View */ - public npcToViewArray(pts: Point3d[]): void { this._viewingSpace.npcToViewArray(pts); } + public npcToViewArray(pts: Point3d[]): void { + this._viewingSpace.npcToViewArray(pts); + } /** Convert a point from CoordSystem.View to CoordSystem.Npc * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public viewToNpc(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.viewToNpc(pt, out); } + public viewToNpc(pt: Point3d, out?: Point3d): Point3d { + return this._viewingSpace.viewToNpc(pt, out); + } /** Convert a point from CoordSystem.Npc to CoordSystem.View * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public npcToView(pt: Point3d, out?: Point3d): Point3d { return this._viewingSpace.npcToView(pt, out); } + public npcToView(pt: Point3d, out?: Point3d): Point3d { + return this._viewingSpace.npcToView(pt, out); + } /** Convert an array of points from CoordSystem.World to CoordSystem.Npc */ - public worldToNpcArray(pts: Point3d[]): void { this._viewingSpace.worldToNpcArray(pts); } + public worldToNpcArray(pts: Point3d[]): void { + this._viewingSpace.worldToNpcArray(pts); + } /** Convert an array of points from CoordSystem.Npc to CoordSystem.World */ - public npcToWorldArray(pts: Point3d[]): void { this._viewingSpace.npcToWorldArray(pts); } + public npcToWorldArray(pts: Point3d[]): void { + this._viewingSpace.npcToWorldArray(pts); + } /** Convert an array of points from CoordSystem.World to CoordSystem.View */ - public worldToViewArray(pts: Point3d[]): void { this._viewingSpace.worldToViewArray(pts); } + public worldToViewArray(pts: Point3d[]): void { + this._viewingSpace.worldToViewArray(pts); + } /** Convert an array of points from CoordSystem.World to CoordSystem.View, as Point4ds */ - public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { this._viewingSpace.worldToView4dArray(worldPts, viewPts); } + public worldToView4dArray(worldPts: Point3d[], viewPts: Point4d[]): void { + this._viewingSpace.worldToView4dArray(worldPts, viewPts); + } /** Convert an array of points from CoordSystem.View to CoordSystem.World */ - public viewToWorldArray(pts: Point3d[]) { this._viewingSpace.viewToWorldArray(pts); } + public viewToWorldArray(pts: Point3d[]) { + this._viewingSpace.viewToWorldArray(pts); + } /** Convert an array of points from CoordSystem.View as Point4ds to CoordSystem.World */ - public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { this._viewingSpace.view4dToWorldArray(viewPts, worldPts); } + public view4dToWorldArray(viewPts: Point4d[], worldPts: Point3d[]): void { + this._viewingSpace.view4dToWorldArray(viewPts, worldPts); + } /** Convert a point from CoordSystem.World to CoordSystem.Npc * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToNpc(pt, out); } + public worldToNpc(pt: XYAndZ, out?: Point3d): Point3d { + return this._viewingSpace.worldToNpc(pt, out); + } /** Convert a point from CoordSystem.Npc to CoordSystem.World * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.npcToWorld(pt, out); } + public npcToWorld(pt: XYAndZ, out?: Point3d): Point3d { + return this._viewingSpace.npcToWorld(pt, out); + } /** Convert a point from CoordSystem.World to CoordSystem.View * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public worldToView(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.worldToView(input, out); } + public worldToView(input: XYAndZ, out?: Point3d): Point3d { + return this._viewingSpace.worldToView(input, out); + } /** Convert a point from CoordSystem.World to CoordSystem.View as Point4d * @param input the point to convert * @param out optional location for result. If undefined, a new Point4d is created. */ - public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { return this._viewingSpace.worldToView4d(input, out); } + public worldToView4d(input: XYAndZ, out?: Point4d): Point4d { + return this._viewingSpace.worldToView4d(input, out); + } /** Convert a point from CoordSystem.View to CoordSystem.World * @param pt the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { return this._viewingSpace.viewToWorld(input, out); } + public viewToWorld(input: XYAndZ, out?: Point3d): Point3d { + return this._viewingSpace.viewToWorld(input, out); + } /** Convert a point from CoordSystem.View as a Point4d to CoordSystem.View * @param input the point to convert * @param out optional location for result. If undefined, a new Point3d is created. */ - public view4dToWorld(input: Point4d, out?: Point3d): Point3d { return this._viewingSpace.view4dToWorld(input, out); } + public view4dToWorld(input: Point4d, out?: Point3d): Point3d { + return this._viewingSpace.view4dToWorld(input, out); + } /** Converts inches to pixels based on screen DPI. * @Note this information may not be accurate in some browsers. * @param inches the number of inches to convert * @returns the corresponding number of pixels */ - public pixelsFromInches(inches: number): number { return inches * this.pixelsPerInch; } + public pixelsFromInches(inches: number): number { + return inches * this.pixelsPerInch; + } /** Get an 8-point Frustum corresponding to the 8 corners of the Viewport in the specified coordinate system. * @@ -2031,10 +2247,14 @@ export abstract class Viewport implements IDisposable, TileUser { * @return the view frustum * @note The "adjusted" box may be either larger or smaller than the "unadjusted" box. */ - public getFrustum(sys: CoordSystem = CoordSystem.World, adjustedBox: boolean = true, box?: Frustum): Frustum { return this._viewingSpace.getFrustum(sys, adjustedBox, box); } + public getFrustum(sys: CoordSystem = CoordSystem.World, adjustedBox: boolean = true, box?: Frustum): Frustum { + return this._viewingSpace.getFrustum(sys, adjustedBox, box); + } /** Get a copy of the current (unadjusted) frustum of this viewport, in world coordinates. */ - public getWorldFrustum(box?: Frustum): Frustum { return this.getFrustum(CoordSystem.World, false, box); } + public getWorldFrustum(box?: Frustum): Frustum { + return this.getFrustum(CoordSystem.World, false, box); + } /** Scroll the view by a given number of pixels. * @param screenDist distance to scroll, in pixels @@ -2624,7 +2844,7 @@ export abstract class Viewport implements IDisposable, TileUser { /** Populate a set of decoration graphics to be displayed in this viewport. * This base implementation produces no graphics. */ - protected addDecorations(_decorations: Decorations): void { } + protected addDecorations(_decorations: Decorations): void {} /** Capture selected data about each pixel within a rectangular region of this Viewport. * @param rect The area of the viewport's contents to read. The origin specifies the upper-left corner. Must lie entirely within the viewport's dimensions. This input viewport is specified using CSS pixels not device pixels. @@ -2658,7 +2878,13 @@ export abstract class Viewport implements IDisposable, TileUser { ); } - private _readPixels(rect: ViewRect, selector: Pixel.Selector, receiver: Pixel.Receiver, excludeNonLocatable?: boolean, excludedElements?: Iterable): void { + private _readPixels( + rect: ViewRect, + selector: Pixel.Selector, + receiver: Pixel.Receiver, + excludeNonLocatable?: boolean, + excludedElements?: Iterable, + ): void { if (this.isDisposed || rect.isNull || !rect.isContained(this.viewRect)) { receiver(undefined); return; @@ -2673,9 +2899,9 @@ export abstract class Viewport implements IDisposable, TileUser { return false; if (pixel.modelId === pixel.elementId) - return false; // Reality Models not selectable + return false; // Reality Models not selectable - return (0 === this.mapLayerFromIds(pixel.modelId, pixel.elementId).length); // Maps no selectable. + return (0 === this.mapLayerFromIds(pixel.modelId, pixel.elementId).length); // Maps no selectable. } /** Read the current image from this viewport from the rendering system. If a "null" rectangle is supplied (@see [[ViewRect.isNull]]), the entire view is captured. @@ -2686,7 +2912,11 @@ export abstract class Viewport implements IDisposable, TileUser { * @note By default the image is returned with the coordinate (0,0) referring to the bottom-most pixel. Pass `true` for `flipVertically` to flip it along the x-axis. * @deprecated in 3.x. Use readImageBuffer. */ - public readImage(rect: ViewRect = new ViewRect(1, 1, 0, 0), targetSize: Point2d = Point2d.createZero(), flipVertically: boolean = false): ImageBuffer | undefined { + public readImage( + rect: ViewRect = new ViewRect(1, 1, 0, 0), + targetSize: Point2d = Point2d.createZero(), + flipVertically: boolean = false, + ): ImageBuffer | undefined { // eslint-disable-next-line deprecation/deprecation return this.target.readImage(rect, targetSize, flipVertically); } @@ -2931,11 +3161,12 @@ export abstract class Viewport implements IDisposable, TileUser { const addSettingsListener = (style: DisplayStyleState) => style.settings.onAnalysisStyleChanged.addListener(listener); let removeSettingsListener = addSettingsListener(this.displayStyle); - const addStyleListener = (view: ViewState) => view.onDisplayStyleChanged.addListener((style) => { - listener(style.settings.analysisStyle); - removeSettingsListener(); - removeSettingsListener = addSettingsListener(view.displayStyle); - }); + const addStyleListener = (view: ViewState) => + view.onDisplayStyleChanged.addListener((style) => { + listener(style.settings.analysisStyle); + removeSettingsListener(); + removeSettingsListener = addSettingsListener(view.displayStyle); + }); const removeStyleListener = addStyleListener(this.view); @@ -2963,8 +3194,12 @@ export abstract class Viewport implements IDisposable, TileUser { } /** @internal See [[OffScreenViewport.drawingToSheetTransform */ - public get drawingToSheetTransform(): Transform | undefined { return undefined; } - public set drawingToSheetTransform(_: Transform | undefined) { assert(false, "drawingToSheetTransform is only relevant for OffScreenViewport"); } + public get drawingToSheetTransform(): Transform | undefined { + return undefined; + } + public set drawingToSheetTransform(_: Transform | undefined) { + assert(false, "drawingToSheetTransform is only relevant for OffScreenViewport"); + } } /** An interactive Viewport that exists within an HTMLDivElement. ScreenViewports can receive HTML events. @@ -3163,7 +3398,9 @@ export class ScreenViewport extends Viewport { } /** The HTMLImageElement of the iTwin.js logo displayed in this ScreenViewport. */ - public get logo() { return this._logo; } + public get logo() { + return this._logo; + } /** @internal */ protected addLogo() { @@ -3303,7 +3540,11 @@ export class ScreenViewport extends Viewport { * @returns A plane with origin from closest geometry point or reference plane projection and the source of the depth point. * @note The result plane normal is valid when the source is not geometry or a reality model. */ - public pickDepthPoint(pickPoint: Point3d, radius?: number, options?: DepthPointOptions): { plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource, sourceId?: string } { + public pickDepthPoint( + pickPoint: Point3d, + radius?: number, + options?: DepthPointOptions, + ): { plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource, sourceId?: string } { if (!this.view.is3d()) return { plane: Plane3dByOriginAndUnitNormal.createXYPlane(pickPoint), source: DepthPointSource.ACS }; @@ -3312,19 +3553,31 @@ export class ScreenViewport extends Viewport { this.picker.empty(); const locateOpts = new LocateOptions(); - locateOpts.allowNonLocatable = (undefined === options || !options.excludeNonLocatable); - locateOpts.allowDecorations = (undefined === options || !options.excludeDecorations); - locateOpts.allowExternalIModels = (undefined === options || !options.excludeExternalIModels); + locateOpts.allowNonLocatable = undefined === options || !options.excludeNonLocatable; + locateOpts.allowDecorations = undefined === options || !options.excludeDecorations; + locateOpts.allowExternalIModels = undefined === options || !options.excludeExternalIModels; locateOpts.preserveModelDisplayTransforms = true; if (0 !== this.picker.doPick(this, pickPoint, radius, locateOpts)) { const hitDetail = this.picker.getHit(0)!; const hitPoint = hitDetail.getPoint(); if (hitDetail.isModelHit) - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Model, sourceId: hitDetail.sourceId }; + return { + plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, + source: DepthPointSource.Model, + sourceId: hitDetail.sourceId, + }; else if (hitDetail.isMapHit) - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, source: DepthPointSource.Map, sourceId: hitDetail.sourceId }; - return { plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getZVector())!, source: DepthPointSource.Geometry, sourceId: hitDetail.sourceId }; + return { + plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getUpVector(hitPoint))!, + source: DepthPointSource.Map, + sourceId: hitDetail.sourceId, + }; + return { + plane: Plane3dByOriginAndUnitNormal.create(hitPoint, this.view.getZVector())!, + source: DepthPointSource.Geometry, + sourceId: hitDetail.sourceId, + }; } const eyePoint = this.worldToViewMap.transform1.columnZ(); @@ -3345,7 +3598,7 @@ export class ScreenViewport extends Viewport { if (undefined !== intersect) { const npcPt = this.worldToNpc(intersect.origin); - if (npcPt.z < 1) // Only if in front of eye. + if (npcPt.z < 1) // Only if in front of eye. return { plane: Plane3dByOriginAndUnitNormal.create(intersect.origin, intersect.direction)!, source: DepthPointSource.BackgroundMap }; } } @@ -3366,7 +3619,10 @@ export class ScreenViewport extends Viewport { const acsPlane = Plane3dByOriginAndUnitNormal.create(this.getAuxCoordOrigin(), this.getAuxCoordRotation().getRow(2)); if (undefined !== acsPlane && boresiteIntersect(acsPlane)) - return { plane: Plane3dByOriginAndUnitNormal.create(projectedPt, acsPlane.getNormalRef())!, source: (this.isGridOn && GridOrientationType.AuxCoord === this.view.getGridOrientation() ? DepthPointSource.Grid : DepthPointSource.ACS) }; + return { + plane: Plane3dByOriginAndUnitNormal.create(projectedPt, acsPlane.getNormalRef())!, + source: (this.isGridOn && GridOrientationType.AuxCoord === this.view.getGridOrientation() ? DepthPointSource.Grid : DepthPointSource.ACS), + }; const targetPointNpc = this.worldToNpc(this.view.getTargetPoint()); if (targetPointNpc.z < 0.0 || targetPointNpc.z > 1.0) @@ -3406,10 +3662,14 @@ export class ScreenViewport extends Viewport { } /** @internal */ - public pickCanvasDecoration(pt: XAndY) { return this.target.pickOverlayDecoration(pt); } + public pickCanvasDecoration(pt: XAndY) { + return this.target.pickOverlayDecoration(pt); + } /** Get the DOMRect of the canvas for this Viewport. */ - public getClientRect(): DOMRect { return this.canvas.getBoundingClientRect(); } + public getClientRect(): DOMRect { + return this.canvas.getBoundingClientRect(); + } /** The ViewRect for this ScreenViewport. Left and top will be 0, right will be the width, and bottom will be the height. * @note Do not modify the ViewRect's properties. @@ -3496,13 +3756,21 @@ export class ScreenViewport extends Viewport { /** A point in world coordinates describing an appropriate default point for a [[ViewTool]] when no more specific point is provided by the user. * This point is generally managed and used by [[ViewManip]]. */ - public get viewCmdTargetCenter(): Point3d | undefined { return this._viewCmdTargetCenter; } - public set viewCmdTargetCenter(center: Point3d | undefined) { this._viewCmdTargetCenter = center ? center.clone() : undefined; } + public get viewCmdTargetCenter(): Point3d | undefined { + return this._viewCmdTargetCenter; + } + public set viewCmdTargetCenter(center: Point3d | undefined) { + this._viewCmdTargetCenter = center ? center.clone() : undefined; + } /** True if an undoable viewing operation exists on the stack */ - public get isUndoPossible(): boolean { return 0 < this._backStack.length; } + public get isUndoPossible(): boolean { + return 0 < this._backStack.length; + } /** True if a redoable viewing operation exists on the stack */ - public get isRedoPossible(): boolean { return 0 < this._forwardStack.length; } + public get isRedoPossible(): boolean { + return 0 < this._forwardStack.length; + } /** Clear the undo buffers of this Viewport. This resets the undo stack. */ public clearViewUndo(): void { @@ -3577,7 +3845,7 @@ export class ScreenViewport extends Viewport { /** Clear the view undo buffer and establish the current ViewState as the new baseline. */ public resetUndo() { this.clearViewUndo(); - this.saveViewUndo(); // Set up new baseline state + this.saveViewUndo(); // Set up new baseline state } /** Show the surface normal for geometry under the cursor when snapping. */ @@ -3602,7 +3870,7 @@ export class ScreenViewport extends Viewport { builder.addArc(ellipse, true, true); builder.addArc(ellipse, false, false); - const lengthX = (0.6 * radius); + const lengthX = 0.6 * radius; const lengthY = lengthX / skew; const normal = Vector3d.create(); @@ -3653,7 +3921,9 @@ export class ScreenViewport extends Viewport { * ViewManager takes care of toggling this behavior. * @internal */ - public get rendersToScreen(): boolean { return undefined !== this._webglCanvas; } + public get rendersToScreen(): boolean { + return undefined !== this._webglCanvas; + } public set rendersToScreen(toScreen: boolean) { if (toScreen === this.rendersToScreen) return; diff --git a/core/frontend/src/common/ImageUtil.ts b/core/frontend/src/common/ImageUtil.ts index 1be54ee46711..f8b5cc173ca5 100644 --- a/core/frontend/src/common/ImageUtil.ts +++ b/core/frontend/src/common/ImageUtil.ts @@ -6,8 +6,8 @@ * @module Rendering */ -import { Point2d } from "@itwin/core-geometry"; import { ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat } from "@itwin/core-common"; +import { Point2d } from "@itwin/core-geometry"; import { ViewRect } from "./ViewRect"; interface Rgba { @@ -20,7 +20,11 @@ interface Rgba { const scratchRgba = { r: 0, g: 0, b: 0, a: 0 }; function rgbaFromAlpha(rgba: Rgba, src: Uint8Array, idx: number): number { - rgba.r = rgba.g = rgba.b = rgba.a = src[idx]; + rgba.r = + rgba.g = + rgba.b = + rgba.a = + src[idx]; return idx + 1; } @@ -47,7 +51,12 @@ function rgbaFromRgba(rgba: Rgba, src: Uint8Array, idx: number): number { * @public * @extensions */ -export function canvasToResizedCanvasWithBars(canvasIn: HTMLCanvasElement, targetSize: Point2d, barSize = new Point2d(0, 0), barStyle = "#C0C0C0"): HTMLCanvasElement { +export function canvasToResizedCanvasWithBars( + canvasIn: HTMLCanvasElement, + targetSize: Point2d, + barSize = new Point2d(0, 0), + barStyle = "#C0C0C0", +): HTMLCanvasElement { const canvasOut = document.createElement("canvas"); canvasOut.width = targetSize.x + barSize.x; canvasOut.height = targetSize.y + barSize.y; @@ -89,7 +98,9 @@ export function imageBufferToCanvas(buffer: ImageBuffer, preserveAlpha: boolean return undefined; const imageData = context.createImageData(buffer.width, buffer.height); - const extractRgba = ImageBufferFormat.Alpha === buffer.format ? rgbaFromAlpha : (ImageBufferFormat.Rgb === buffer.format ? rgbaFromRgb : rgbaFromRgba); + const extractRgba = ImageBufferFormat.Alpha === buffer.format + ? rgbaFromAlpha + : (ImageBufferFormat.Rgb === buffer.format ? rgbaFromRgb : rgbaFromRgba); const bufferData = buffer.data; let i = 0; @@ -164,7 +175,6 @@ export function canvasToImageBuffer(canvas: HTMLCanvasElement, format = ImageBuf * @extensions */ export function getImageSourceMimeType(format: ImageSourceFormat): string { - switch (format) { case ImageSourceFormat.Jpeg: return "image/jpeg"; @@ -182,12 +192,17 @@ export function getImageSourceMimeType(format: ImageSourceFormat): string { */ export function getImageSourceFormatForMimeType(mimeType: string): ImageSourceFormat | undefined { switch (mimeType) { - case "image/jpeg": return ImageSourceFormat.Jpeg; + case "image/jpeg": + return ImageSourceFormat.Jpeg; // not standard, but people accidentally use it anyway. - case "image/jpg": return ImageSourceFormat.Jpeg; - case "image/png": return ImageSourceFormat.Png; - case "image/svg+xml;charset=utf-8": return ImageSourceFormat.Svg; - default: return undefined; + case "image/jpg": + return ImageSourceFormat.Jpeg; + case "image/png": + return ImageSourceFormat.Png; + case "image/svg+xml;charset=utf-8": + return ImageSourceFormat.Svg; + default: + return undefined; } } diff --git a/core/frontend/src/common/ViewRect.ts b/core/frontend/src/common/ViewRect.ts index e4743d862198..d63e4920ddae 100644 --- a/core/frontend/src/common/ViewRect.ts +++ b/core/frontend/src/common/ViewRect.ts @@ -26,33 +26,67 @@ export class ViewRect { } /** Construct a new ViewRect. */ - public constructor(left = 0, top = 0, right = 0, bottom = 0) { this.init(left, top, right, bottom); } + public constructor(left = 0, top = 0, right = 0, bottom = 0) { + this.init(left, top, right, bottom); + } /** The leftmost side of this ViewRect. */ - public get left(): number { return this._left; } - public set left(val: number) { this._set("_left", val); } + public get left(): number { + return this._left; + } + public set left(val: number) { + this._set("_left", val); + } /** The topmost side of this ViewRect. */ - public get top(): number { return this._top; } - public set top(val: number) { this._set("_top", val); } + public get top(): number { + return this._top; + } + public set top(val: number) { + this._set("_top", val); + } /** The rightmost side of this ViewRect. */ - public get right(): number { return this._right; } - public set right(val: number) { this._set("_right", val); } + public get right(): number { + return this._right; + } + public set right(val: number) { + this._set("_right", val); + } /** The bottommost side of this ViewRect. */ - public get bottom(): number { return this._bottom; } - public set bottom(val: number) { this._set("_bottom", val); } + public get bottom(): number { + return this._bottom; + } + public set bottom(val: number) { + this._set("_bottom", val); + } /** True if this ViewRect has an area <= 0. */ - public get isNull(): boolean { return this.right <= this.left || this.bottom <= this.top; } + public get isNull(): boolean { + return this.right <= this.left || this.bottom <= this.top; + } /** True if `!isNull` */ - public get isValid(): boolean { return !this.isNull; } + public get isValid(): boolean { + return !this.isNull; + } /** The width (right-left) of this ViewRect. */ - public get width() { return this.right - this.left; } - public set width(width: number) { this.right = this.left + width; } + public get width() { + return this.right - this.left; + } + public set width(width: number) { + this.right = this.left + width; + } /** The height (bottom-top) of this ViewRect. */ - public get height() { return this.bottom - this.top; } - public set height(height: number) { this.bottom = this.top + height; } + public get height() { + return this.bottom - this.top; + } + public set height(height: number) { + this.bottom = this.top + height; + } /** The aspect ratio (width/height) of this ViewRect. */ - public get aspect() { return this.isNull ? 1.0 : this.width / this.height; } + public get aspect() { + return this.isNull ? 1.0 : this.width / this.height; + } /** The area (width*height) of this ViewRect. */ - public get area() { return this.isNull ? 0 : this.width * this.height; } + public get area() { + return this.isNull ? 0 : this.width * this.height; + } /** Initialize this ViewRect from its left/top/right/bottom parameters. */ public init(left: number, top: number, right: number, bottom: number) { this.left = left; @@ -64,17 +98,25 @@ export class ViewRect { * @param topLeft The top-left corner. * @param bottomRight The bottom-right corner. */ - public initFromPoints(topLeft: XAndY, bottomRight: XAndY): void { this.init(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); } + public initFromPoints(topLeft: XAndY, bottomRight: XAndY): void { + this.init(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); + } /** Initialize this ViewRect from a range. * @param input The Range to use. `input.low` defines the top-left and `input.high` defines the bottom-right. */ - public initFromRange(input: LowAndHighXY): void { this.initFromPoints(input.low, input.high); } + public initFromRange(input: LowAndHighXY): void { + this.initFromPoints(input.low, input.high); + } /** Return true is this ViewRect is exactly equal to another ViewRect. * @param other The other ViewRect to compare */ - public equals(other: ViewRect): boolean { return this.left === other.left && this.right === other.right && this.bottom === other.bottom && this.top === other.top; } + public equals(other: ViewRect): boolean { + return this.left === other.left && this.right === other.right && this.bottom === other.bottom && this.top === other.top; + } /** Initialize this ViewRect from another ViewRect. */ - public setFrom(other: ViewRect): void { this.init(other.left, other.top, other.right, other.bottom); } + public setFrom(other: ViewRect): void { + this.init(other.left, other.top, other.right, other.bottom); + } /** Duplicate this ViewRect. * @param result Optional ViewRect for result. If undefined, a new ViewRect is created. */ @@ -117,7 +159,9 @@ export class ViewRect { * @param offset The distance to inset this ViewRect. Positive values will make this ViewRect smaller and negative values will make it larger. * @note The inset operation can cause a previously valid ViewRect to become invalid. */ - public insetUniform(offset: number): void { this.inset(offset, offset); } + public insetUniform(offset: number): void { + this.inset(offset, offset); + } /** Scale this ViewRect about its center by the supplied scale factors. */ public scaleAboutCenter(xScale: number, yScale: number): void { @@ -133,19 +177,27 @@ export class ViewRect { * @note The ViewRect will become smaller (or larger, if percent is negative) by `percent * width * 2` in each direction, since each side is moved by that distance. * @see [[inset]] */ - public insetByPercent(percent: number): void { this.insetUniform(this.width * percent); } + public insetByPercent(percent: number): void { + this.insetUniform(this.width * percent); + } /** Determine if this ViewRect is entirely contained within the bounds of another ViewRect. */ - public isContained(other: ViewRect): boolean { return this.left >= other.left && this.right <= other.right && this.bottom <= other.bottom && this.top >= other.top; } + public isContained(other: ViewRect): boolean { + return this.left >= other.left && this.right <= other.right && this.bottom <= other.bottom && this.top >= other.top; + } /** Return true if the supplied point is contained in this ViewRect. * @param point The point to test. * @note if the point is exactly on the left or top edges, this method returns true. If the point is exactly on the right or bottom edge, it returns false. */ - public containsPoint(point: XAndY): boolean { return point.x >= this.left && point.x < this.right && point.y >= this.top && point.y < this.bottom; } + public containsPoint(point: XAndY): boolean { + return point.x >= this.left && point.x < this.right && point.y >= this.top && point.y < this.bottom; + } /** Determine whether this ViewRect overlaps another. */ - public overlaps(other: ViewRect): boolean { return this.left <= other.right && this.top <= other.bottom && this.right >= other.left && this.bottom >= other.top; } + public overlaps(other: ViewRect): boolean { + return this.left <= other.right && this.top <= other.bottom && this.right >= other.left && this.bottom >= other.top; + } /** Return a ViewRect that is the overlap (intersection) of this ViewRect and another ViewRect. * If the two ViewRects are equal, their value is the result. Otherwise, the result will always be smaller than either of them. diff --git a/core/frontend/src/common/WorkerProxy.ts b/core/frontend/src/common/WorkerProxy.ts index 6ab5cc83c390..03e995556461 100644 --- a/core/frontend/src/common/WorkerProxy.ts +++ b/core/frontend/src/common/WorkerProxy.ts @@ -43,8 +43,7 @@ type WorkerResponse = WorkerResult | WorkerError; export type WorkerInterface = { [P in keyof T]: T[P] extends () => any ? () => Promise> : (T[P] extends (arg: any) => any ? (arg: Parameters[0], transfer?: Transferable[]) => Promise> : - (T[P] extends (...args: any) => any ? (args: Parameters, transfer?: Transferable[]) => Promise> : never) - ) + (T[P] extends (...args: any) => any ? (args: Parameters, transfer?: Transferable[]) => Promise> : never)); }; /** Augments each method of `T` with the ability to specify values to be transferred from the worker thread to the main thread. @@ -52,7 +51,9 @@ export type WorkerInterface = { * @see [[WorkerImplementation]]. * @beta */ -export type WorkerReturnType any> = MaybePromise | { result: Awaited>, transfer: Transferable[] }>; +export type WorkerReturnType any> = MaybePromise< + ReturnType | { result: Awaited>, transfer: Transferable[] } +>; /** Given an interface T that defines the operations provided by a worker, produce an interface to which the implementation of those operations must conform. * The return type of each function is enhanced to permit supplying a list of values to be transferred from the worker to the main thread. @@ -68,8 +69,7 @@ export type WorkerReturnType any> = MaybePromise = { [P in keyof T]: T[P] extends () => any ? () => WorkerReturnType : (T[P] extends (arg: any) => any ? (arg: Parameters[0]) => WorkerReturnType : - (T[P] extends (...args: any) => any ? (args: Parameters) => WorkerReturnType : never) - ) + (T[P] extends (...args: any) => any ? (args: Parameters) => WorkerReturnType : never)); }; /** A proxy for a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker) that provides the operations specified by @@ -129,11 +129,12 @@ export function createWorkerProxy(workerJsPath: string): WorkerProxy { } else if (operation === "isTerminated") { return terminated; } else { - return async (...args: any[]) => new Promise((resolve, reject) => { - const msgId = ++curMsgId; - tasks.set(msgId, { resolve, reject }); - worker.postMessage({ operation, payload: args[0], msgId }, args[1] ?? []); - }); + return async (...args: any[]) => + new Promise((resolve, reject) => { + const msgId = ++curMsgId; + tasks.set(msgId, { resolve, reject }); + worker.postMessage({ operation, payload: args[0], msgId }, args[1] ?? []); + }); } }, }); diff --git a/core/frontend/src/common/gltf/GltfParser.ts b/core/frontend/src/common/gltf/GltfParser.ts index 2f8191b3665e..5f6d33fb8cc5 100644 --- a/core/frontend/src/common/gltf/GltfParser.ts +++ b/core/frontend/src/common/gltf/GltfParser.ts @@ -7,18 +7,30 @@ */ import { ByteStream, JsonUtils, Logger, utf8ToString } from "@itwin/core-bentley"; -import { Matrix3d, Point3d, Point4d, Transform } from "@itwin/core-geometry"; import { GlbHeader, ImageSource, TileFormat } from "@itwin/core-common"; +import { Matrix3d, Point3d, Point4d, Transform } from "@itwin/core-geometry"; import type { DracoLoader, DracoMesh } from "@loaders.gl/draco"; import { FrontendLoggerCategory } from "../FrontendLoggerCategory"; +import { getImageSourceFormatForMimeType, imageBitmapFromImageSource, imageElementFromImageSource, tryImageElementFromUrl } from "../ImageUtil"; import { TextureImageSource } from "../render/TextureParams"; +import { Gltf } from "./GltfModel"; import { - getImageSourceFormatForMimeType, imageBitmapFromImageSource, imageElementFromImageSource, tryImageElementFromUrl, -} from "../ImageUtil"; -import { - DracoMeshCompression, getGltfNodeMeshIds, GltfAccessor, GltfBuffer, GltfBufferViewProps, GltfDictionary, gltfDictionaryIterator, GltfDocument, GltfId, GltfImage, GltfMesh, GltfMeshMode, GltfMeshPrimitive, GltfNode, traverseGltfNodes, + DracoMeshCompression, + getGltfNodeMeshIds, + GltfAccessor, + GltfBuffer, + GltfBufferViewProps, + GltfDictionary, + gltfDictionaryIterator, + GltfDocument, + GltfId, + GltfImage, + GltfMesh, + GltfMeshMode, + GltfMeshPrimitive, + GltfNode, + traverseGltfNodes, } from "./GltfSchema"; -import { Gltf } from "./GltfModel"; /** @internal */ export interface ParseGltfLogger { @@ -176,7 +188,7 @@ class GltfParser { this._isCanceled = options.isCanceled; this._imageFromImageSource = options.imageFromImageSource; - const emptyDict = { }; + const emptyDict = {}; const doc = options.document; this._buffers = doc.buffers ?? emptyDict; this._images = doc.images ?? emptyDict; @@ -239,19 +251,35 @@ class GltfParser { if (node.matrix) { const origin = Point3d.create(node.matrix[12], node.matrix[13], node.matrix[14]); const matrix = Matrix3d.createRowValues( - node.matrix[0], node.matrix[4], node.matrix[8], - node.matrix[1], node.matrix[5], node.matrix[9], - node.matrix[2], node.matrix[6], node.matrix[10], + node.matrix[0], + node.matrix[4], + node.matrix[8], + node.matrix[1], + node.matrix[5], + node.matrix[9], + node.matrix[2], + node.matrix[6], + node.matrix[10], ); toParent = Transform.createOriginAndMatrix(origin, matrix); } else if (node.rotation || node.scale || node.translation) { // SPEC: To compose the local transformation matrix, TRS properties MUST be converted to matrices and postmultiplied in the T * R * S order; // first the scale is applied to the vertices, then the rotation, and then the translation. - const scale = Transform.createRefs(undefined, node.scale ? Matrix3d.createScale(node.scale[0], node.scale[1], node.scale[2]) : Matrix3d.identity); - const rot = Transform.createRefs(undefined, node.rotation ? Matrix3d.createFromQuaternion(Point4d.create(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3])) : Matrix3d.identity); + const scale = Transform.createRefs( + undefined, + node.scale ? Matrix3d.createScale(node.scale[0], node.scale[1], node.scale[2]) : Matrix3d.identity, + ); + const rot = Transform.createRefs( + undefined, + node.rotation + ? Matrix3d.createFromQuaternion(Point4d.create(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3])) + : Matrix3d.identity, + ); rot.matrix.transposeInPlace(); // See comment on Matrix3d.createFromQuaternion - const trans = Transform.createTranslation(node.translation ? new Point3d(node.translation[0], node.translation[1], node.translation[2]) : Point3d.createZero()); + const trans = Transform.createTranslation( + node.translation ? new Point3d(node.translation[0], node.translation[1], node.translation[2]) : Point3d.createZero(), + ); toParent = scale.multiplyTransformTransform(rot); trans.multiplyTransformTransform(toParent, toParent); @@ -311,10 +339,11 @@ class GltfParser { for (const node of this.traverseNodes(this._sceneNodes)) { for (const meshId of getGltfNodeMeshIds(node)) { const mesh = this._meshes[meshId]; - if (mesh?.primitives) + if (mesh?.primitives) { for (const primitive of mesh.primitives) if (primitive.extensions?.KHR_draco_mesh_compression) dracoMeshes.push(primitive.extensions.KHR_draco_mesh_compression); + } } } @@ -387,7 +416,10 @@ class GltfParser { if (image.resolvedImage) return; - interface BufferViewSource { bufferView?: GltfId, mimeType?: string } + interface BufferViewSource { + bufferView?: GltfId; + mimeType?: string; + } const bvSrc: BufferViewSource | undefined = undefined !== image.bufferView ? image : image.extensions?.KHR_binary_glTF; if (undefined !== bvSrc?.bufferView) { const format = undefined !== bvSrc.mimeType ? getImageSourceFormatForMimeType(bvSrc.mimeType) : undefined; @@ -427,7 +459,7 @@ class GltfParser { const offset = bv.byteOffset ?? 0; buf = buf.subarray(offset, offset + bv.byteLength); - const mesh = await loader.parse(buf, { }); // NB: `options` argument declared optional but will produce exception if not supplied. + const mesh = await loader.parse(buf, {}); // NB: `options` argument declared optional but will produce exception if not supplied. if (mesh) this._dracoMeshes.set(ext, mesh); } diff --git a/core/frontend/src/common/gltf/GltfSchema.ts b/core/frontend/src/common/gltf/GltfSchema.ts index 94fecee695bf..ef44af33754a 100644 --- a/core/frontend/src/common/gltf/GltfSchema.ts +++ b/core/frontend/src/common/gltf/GltfSchema.ts @@ -99,7 +99,7 @@ export interface GltfStringMap { /** Iterate the contents of a [[GltfDictionary]]. * @internal */ -export function * gltfDictionaryIterator(dict: GltfDictionary): Iterable { +export function* gltfDictionaryIterator(dict: GltfDictionary): Iterable { if (Array.isArray(dict)) { for (const elem of dict) yield elem; @@ -300,7 +300,7 @@ export function getGltfNodeMeshIds(node: GltfNode): GltfId[] { } /** @internal */ -export function * traverseGltfNodes(ids: Iterable, nodes: GltfDictionary, traversed: Set): Iterable { +export function* traverseGltfNodes(ids: Iterable, nodes: GltfDictionary, traversed: Set): Iterable { for (const id of ids) { if (traversed.has(id)) throw new Error("Cycle detected while traversing glTF nodes"); @@ -311,9 +311,10 @@ export function * traverseGltfNodes(ids: Iterable, nodes: GltfDictionary traversed.add(id); yield node; - if (node.children) + if (node.children) { for (const child of traverseGltfNodes(node.children, nodes, traversed)) yield child; + } } } @@ -399,7 +400,7 @@ export interface GltfTexture extends GltfChildOfRootProperty { * effectively, unless `wrapS` or `wrapT` is set to ClampToEdge, the sampler will use GltfWrapMode.Repeat. * @internal */ -export interface GltfSampler extends GltfChildOfRootProperty { +export interface GltfSampler extends GltfChildOfRootProperty { /** Magnification filter. */ magFilter?: GltfMagFilter; /** Minification filter. */ @@ -478,7 +479,7 @@ export interface Gltf2Material extends GltfChildOfRootProperty { * indicates that the material should be displayed without lighting. The extension adds no additional properties; it is effectively a boolean flag. */ // eslint-disable-next-line @typescript-eslint/naming-convention - KHR_materials_unlit?: { }; + KHR_materials_unlit?: {}; /** The [KHR_techniques_webgl extension](https://github.com/KhronosGroup/glTF/blob/c1c12bd100e88ff468ccef1cb88cfbec56a69af2/extensions/2.0/Khronos/KHR_techniques_webgl/README.md) * allows "techniques" to be associated with [[GltfMaterial]]s. Techniques can supply custom shader programs to render geometry; this was a core feature of glTF 1.0 (see [[GltfTechnique]]). * Here, it is only used to extract uniform values. @@ -531,7 +532,7 @@ export type ExtMeshoptCompressionFilter = "NONE" | "OCTAHEDRAL" | "QUATERNION"; /** https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_meshopt_compression/README.md * @internal -*/ + */ export interface GltfBufferViewMeshoptCompressionExtension { buffer: number; byteOffset?: number; @@ -558,7 +559,13 @@ export interface GltfBufferViewProps extends GltfChildOfRootProperty { export interface GltfAccessor extends GltfChildOfRootProperty { bufferView?: GltfId; byteOffset?: number; - componentType?: GltfDataType.SignedByte | GltfDataType.UnsignedByte | GltfDataType.SignedShort | GltfDataType.UnsignedShort | GltfDataType.UInt32 | GltfDataType.Float; + componentType?: + | GltfDataType.SignedByte + | GltfDataType.UnsignedByte + | GltfDataType.SignedShort + | GltfDataType.UnsignedShort + | GltfDataType.UInt32 + | GltfDataType.Float; normalized?: boolean; count: number; type: "SCALAR" | "VEC2" | "VEC3" | "VEC4" | "MAT2" | "MAT3" | "MAT4"; @@ -582,7 +589,18 @@ export namespace GltfStructuralMetadata { // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents export type ClassPropertyType = "SCALAR" | "STRING" | "BOOLEAN" | "ENUM" | "VEC2" | "VEC3" | "VEC4" | "MAT2" | "MAT3" | "MAT4" | string; // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents - export type ClassPropertyComponentType = "INT8" | "UINT8" | "INT16" | "UINT16" | "INT32" | "UINT32" | "INT64" | "UINT64" | "FLOAT32" | "FLOAT64" | string; + export type ClassPropertyComponentType = + | "INT8" + | "UINT8" + | "INT16" + | "UINT16" + | "INT32" + | "UINT32" + | "INT64" + | "UINT64" + | "FLOAT32" + | "FLOAT64" + | string; // Ignoring VECN and MATN types because they complicate offset, scale, min, and max, all of which are otherwise only relevant to SCALAR in which case they're all just numbers. export interface ClassProperty extends GltfProperty { @@ -613,7 +631,7 @@ export namespace GltfStructuralMetadata { export interface Enum extends GltfProperty { values: EnumValue[]; // Default: UINT16 - valueType?: "INT8" | "UINT8" | "INT16" | "UINT16" | "INT32" | "UINT32" | "INT64" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents + valueType?: "INT8" | "UINT8" | "INT16" | "UINT16" | "INT32" | "UINT32" | "INT64" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents name?: string; description?: string; } @@ -642,8 +660,8 @@ export namespace GltfStructuralMetadata { values: GltfId; arrayOffsets?: GltfId; stringOffsets?: GltfId; - arrayOffsetType?: "UINT8" | "UINT16" | "UINT32" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents - stringOffsetType?: "UINT8" | "UINT16" | "UINT32" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents + arrayOffsetType?: "UINT8" | "UINT16" | "UINT32" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents + stringOffsetType?: "UINT8" | "UINT16" | "UINT32" | "UINT64" | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents offset?: number; scale?: number; min?: number; diff --git a/core/frontend/src/common/imdl/CompactEdges.ts b/core/frontend/src/common/imdl/CompactEdges.ts index 190a8b1b927a..6fe44938f43b 100644 --- a/core/frontend/src/common/imdl/CompactEdges.ts +++ b/core/frontend/src/common/imdl/CompactEdges.ts @@ -7,10 +7,10 @@ */ import { assert } from "@itwin/core-bentley"; -import { ImdlEdgeVisibility } from "./ImdlSchema"; -import { ImdlModel } from "./ImdlModel"; import { calculateEdgeTableParams } from "../internal/render/EdgeParams"; import { VertexIndices } from "../internal/render/VertexIndices"; +import { ImdlModel } from "./ImdlModel"; +import { ImdlEdgeVisibility } from "./ImdlSchema"; /** Parameters supplied to [[indexedEdgeParamsFromCompactEdges]]. * @internal @@ -39,7 +39,11 @@ interface CompactEdge { /** Iterate over the compact edges. * @note The same object is returned on each iteration, mutated in place. */ -function * compactEdgeIterator(visibilityFlags: Uint8Array, vertexIndices: VertexIndices, normalPairs: Uint32Array | undefined): IterableIterator { +function* compactEdgeIterator( + visibilityFlags: Uint8Array, + vertexIndices: VertexIndices, + normalPairs: Uint32Array | undefined, +): IterableIterator { let bitIndex = 0; let flagsIndex = 0; let normalIndex = 0; @@ -78,7 +82,7 @@ function setUint24(edgeTable: Uint8Array, byteIndex: number, value: number): voi /** Convert an [[ImdlCompactEdges]] to an [[IndexedEdgeParams]]. * @internal */ -export function indexedEdgeParamsFromCompactEdges(compact: CompactEdgeParams): ImdlModel.IndexedEdgeParams | undefined { +export function indexedEdgeParamsFromCompactEdges(compact: CompactEdgeParams): ImdlModel.IndexedEdgeParams | undefined { const numSilhouettes = compact.normalPairs?.length ?? 0; const numTotalEdges = compact.numVisibleEdges + numSilhouettes; if (numTotalEdges <= 0) @@ -90,7 +94,11 @@ export function indexedEdgeParamsFromCompactEdges(compact: CompactEdgeParams): I for (let j = 0; j < 6; j++) indices.setNthIndex(i * 6 + j, i); - const {width, height, silhouettePadding, silhouetteStartByteIndex} = calculateEdgeTableParams(compact.numVisibleEdges, numSilhouettes, compact.maxEdgeTableDimension); + const { width, height, silhouettePadding, silhouetteStartByteIndex } = calculateEdgeTableParams( + compact.numVisibleEdges, + numSilhouettes, + compact.maxEdgeTableDimension, + ); const edgeTable = new Uint8Array(width * height * 4); let curVisibleIndex = 0; diff --git a/core/frontend/src/common/imdl/ImdlModel.ts b/core/frontend/src/common/imdl/ImdlModel.ts index cdab3c95686a..2471ebc8abef 100644 --- a/core/frontend/src/common/imdl/ImdlModel.ts +++ b/core/frontend/src/common/imdl/ImdlModel.ts @@ -7,15 +7,22 @@ */ import { UintArray } from "@itwin/core-bentley"; -import { XYAndZ } from "@itwin/core-geometry"; import { - ColorDefProps, FeatureIndexType, FillFlags, Gradient, LinePixels, PolylineTypeFlags, QParams2dProps, QParams3dProps, + ColorDefProps, + FeatureIndexType, + FillFlags, + Gradient, + LinePixels, + PolylineTypeFlags, + QParams2dProps, + QParams3dProps, } from "@itwin/core-common"; +import { XYAndZ } from "@itwin/core-geometry"; +import { AuxChannelTableProps } from "../internal/render/AuxChannelTable"; import { EdgeTable } from "../internal/render/EdgeParams"; import { SurfaceMaterialAtlas, SurfaceType } from "../internal/render/SurfaceParams"; -import { AuxChannelTableProps } from "../internal/render/AuxChannelTable"; -import { ImdlAreaPattern, ImdlDocument } from "./ImdlSchema"; import { InstancedGraphicProps } from "../render/InstancedGraphicParams"; +import { ImdlAreaPattern, ImdlDocument } from "./ImdlSchema"; /** Types comprising the parsed representation of an ImdlDocument, produced by [[parseImdlDocument]] and consumed by [[decodeImdlGraphics]]. * All of the types are required to support [structured cloning](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) so that they diff --git a/core/frontend/src/common/imdl/ImdlSchema.ts b/core/frontend/src/common/imdl/ImdlSchema.ts index 556ed6cf0fb3..e29bb85bc057 100644 --- a/core/frontend/src/common/imdl/ImdlSchema.ts +++ b/core/frontend/src/common/imdl/ImdlSchema.ts @@ -6,10 +6,17 @@ * @module Tiles */ -import { ClipVectorProps, Range3dProps, TransformProps, XYProps, XYZProps } from "@itwin/core-geometry"; import { - ColorDefProps, FeatureIndexType, FillFlags, Gradient, ImageSourceFormat, LinePixels, TextureMapping, TextureTransparency, + ColorDefProps, + FeatureIndexType, + FillFlags, + Gradient, + ImageSourceFormat, + LinePixels, + TextureMapping, + TextureTransparency, } from "@itwin/core-common"; +import { ClipVectorProps, Range3dProps, TransformProps, XYProps, XYZProps } from "@itwin/core-geometry"; import { AuxChannelTableProps } from "../internal/render/AuxChannelTable"; import { DisplayParams } from "../internal/render/DisplayParams"; import { MeshPrimitiveType } from "../internal/render/MeshPrimitive"; diff --git a/core/frontend/src/common/imdl/ParseImdlDocument.ts b/core/frontend/src/common/imdl/ParseImdlDocument.ts index 1f16ee21c78b..42160ad41d38 100644 --- a/core/frontend/src/common/imdl/ParseImdlDocument.ts +++ b/core/frontend/src/common/imdl/ParseImdlDocument.ts @@ -7,29 +7,63 @@ */ import { assert, ByteStream, Id64, Id64Set, Id64String, JsonUtils, utf8ToString } from "@itwin/core-bentley"; -import { Point3d, Range2d, Range3d } from "@itwin/core-geometry"; import { - BatchType, ColorDef, FeatureTableHeader, FillFlags, GltfV2ChunkTypes, GltfVersions, Gradient, ImdlFlags, ImdlHeader, LinePixels, MultiModelPackedFeatureTable, - PackedFeatureTable, PolylineTypeFlags, QParams2d, QParams3d, RenderFeatureTable, RenderMaterial, RenderSchedule, RenderTexture, RgbColor, TextureMapping, TileFormat, - TileHeader, TileReadStatus, + BatchType, + ColorDef, + FeatureTableHeader, + FillFlags, + GltfV2ChunkTypes, + GltfVersions, + Gradient, + ImdlFlags, + ImdlHeader, + LinePixels, + MultiModelPackedFeatureTable, + PackedFeatureTable, + PolylineTypeFlags, + QParams2d, + QParams3d, + RenderFeatureTable, + RenderMaterial, + RenderSchedule, + RenderTexture, + RgbColor, + TextureMapping, + TileFormat, + TileHeader, + TileReadStatus, } from "@itwin/core-common"; -import { ImdlModel as Imdl } from "./ImdlModel"; -import { - AnyImdlPrimitive, ImdlAreaPattern, ImdlColorDef, ImdlCompactEdges, ImdlDisplayParams, ImdlDocument, ImdlIndexedEdges, ImdlMesh, ImdlMeshEdges, - ImdlMeshPrimitive, ImdlNamedTexture, ImdlPolyline, ImdlSegmentEdges, ImdlSilhouetteEdges, ImdlTextureMapping, -} from "./ImdlSchema"; -import { MeshPrimitiveType } from "../internal/render/MeshPrimitive"; -import { isValidSurfaceType, SurfaceMaterial } from "../internal/render/SurfaceParams"; -import { DisplayParams } from "../internal/render/DisplayParams"; -import { AuxChannelTable, AuxChannelTableProps } from "../internal/render/AuxChannelTable"; -import { ComputeAnimationNodeId, splitMeshParams, splitPointStringParams, splitPolylineParams } from "../internal/render/VertexTableSplitter"; +import { Point3d, Range2d, Range3d } from "@itwin/core-geometry"; import { AnimationNodeId } from "../internal/render/AnimationNodeId"; +import { AuxChannelTable, AuxChannelTableProps } from "../internal/render/AuxChannelTable"; +import { DisplayParams } from "../internal/render/DisplayParams"; import { EdgeParams } from "../internal/render/EdgeParams"; import { MeshParams } from "../internal/render/MeshParams"; +import { MeshPrimitiveType } from "../internal/render/MeshPrimitive"; +import { isValidSurfaceType, SurfaceMaterial } from "../internal/render/SurfaceParams"; +import { VertexIndices } from "../internal/render/VertexIndices"; import { VertexTable } from "../internal/render/VertexTable"; +import { ComputeAnimationNodeId, splitMeshParams, splitPointStringParams, splitPolylineParams } from "../internal/render/VertexTableSplitter"; import { MaterialParams } from "../render/MaterialParams"; -import { VertexIndices } from "../internal/render/VertexIndices"; import { indexedEdgeParamsFromCompactEdges } from "./CompactEdges"; +import { ImdlModel as Imdl } from "./ImdlModel"; +import { + AnyImdlPrimitive, + ImdlAreaPattern, + ImdlColorDef, + ImdlCompactEdges, + ImdlDisplayParams, + ImdlDocument, + ImdlIndexedEdges, + ImdlMesh, + ImdlMeshEdges, + ImdlMeshPrimitive, + ImdlNamedTexture, + ImdlPolyline, + ImdlSegmentEdges, + ImdlSilhouetteEdges, + ImdlTextureMapping, +} from "./ImdlSchema"; /** Timeline used to reassemble iMdl content into animatable nodes. * @internal @@ -64,7 +98,9 @@ class GltfHeader extends TileHeader { public readonly scenePosition: number = 0; public readonly sceneStrLength: number = 0; public readonly binaryPosition: number = 0; - public get isValid(): boolean { return TileFormat.Gltf === this.format; } + public get isValid(): boolean { + return TileFormat.Gltf === this.format; + } public constructor(stream: ByteStream) { super(stream); @@ -137,8 +173,10 @@ abstract class Texture extends RenderTexture { public abstract toImdl(): string | Gradient.SymbProps; - public override dispose() { } - public override get bytesUsed() { return 0; } + public override dispose() {} + public override get bytesUsed() { + return 0; + } } class NamedTexture extends Texture { @@ -237,23 +275,31 @@ function fromVertexTable(table: VertexTable): Imdl.VertexTable { export function edgeParamsFromImdl(imdl: Imdl.EdgeParams): EdgeParams { return { ...imdl, - segments: imdl.segments ? { - ...imdl.segments, - indices: new VertexIndices(imdl.segments.indices), - } : undefined, - silhouettes: imdl.silhouettes ? { - ...imdl.silhouettes, - indices: new VertexIndices(imdl.silhouettes.indices), - } : undefined, - polylines: imdl.polylines ? { - ...imdl.polylines, - indices: new VertexIndices(imdl.polylines.indices), - prevIndices: new VertexIndices(imdl.polylines.prevIndices), - } : undefined, - indexed: imdl.indexed ? { - indices: new VertexIndices(imdl.indexed.indices), - edges: imdl.indexed.edges, - } : undefined, + segments: imdl.segments ? + { + ...imdl.segments, + indices: new VertexIndices(imdl.segments.indices), + } : + undefined, + silhouettes: imdl.silhouettes ? + { + ...imdl.silhouettes, + indices: new VertexIndices(imdl.silhouettes.indices), + } : + undefined, + polylines: imdl.polylines ? + { + ...imdl.polylines, + indices: new VertexIndices(imdl.polylines.indices), + prevIndices: new VertexIndices(imdl.polylines.prevIndices), + } : + undefined, + indexed: imdl.indexed ? + { + indices: new VertexIndices(imdl.indexed.indices), + edges: imdl.indexed.edges, + } : + undefined, }; } @@ -261,23 +307,31 @@ export function edgeParamsFromImdl(imdl: Imdl.EdgeParams): EdgeParams { export function edgeParamsToImdl(params: EdgeParams): Imdl.EdgeParams { return { ...params, - segments: params.segments ? { - ...params.segments, - indices: params.segments.indices.data, - } : undefined, - silhouettes: params.silhouettes ? { - ...params.silhouettes, - indices: params.silhouettes.indices.data, - } : undefined, - polylines: params.polylines ? { - ...params.polylines, - indices: params.polylines.indices.data, - prevIndices: params.polylines.prevIndices.data, - } : undefined, - indexed: params.indexed ? { - indices: params.indexed.indices.data, - edges: params.indexed.edges, - } : undefined, + segments: params.segments ? + { + ...params.segments, + indices: params.segments.indices.data, + } : + undefined, + silhouettes: params.silhouettes ? + { + ...params.silhouettes, + indices: params.silhouettes.indices.data, + } : + undefined, + polylines: params.polylines ? + { + ...params.polylines, + indices: params.polylines.indices.data, + prevIndices: params.polylines.prevIndices.data, + } : + undefined, + indexed: params.indexed ? + { + indices: params.indexed.indices.data, + edges: params.indexed.edges, + } : + undefined, }; } @@ -304,11 +358,13 @@ class Parser { if (!featureTable) return TileReadStatus.InvalidFeatureTable; - const rtcCenter = this._document.rtcCenter ? { - x: this._document.rtcCenter[0] ?? 0, - y: this._document.rtcCenter[1] ?? 0, - z: this._document.rtcCenter[2] ?? 0, - } : undefined; + const rtcCenter = this._document.rtcCenter ? + { + x: this._document.rtcCenter[0] ?? 0, + y: this._document.rtcCenter[1] ?? 0, + z: this._document.rtcCenter[2] ?? 0, + } : + undefined; const primitiveNodes = this.parseNodes(featureTable); const nodes = this.groupPrimitiveNodes(primitiveNodes, featureTable); @@ -437,7 +493,9 @@ class Parser { if (!docPrimitives) return; - const primitives = docPrimitives.map((x) => this.parseNodePrimitive(x)).filter((x): x is Imdl.NodePrimitive => x !== undefined); + const primitives = docPrimitives.map((x) => this.parseNodePrimitive(x)).filter((x): x is Imdl.NodePrimitive => + x !== undefined + ); if (primitives.length === 0) return; @@ -446,7 +504,7 @@ class Parser { nodeId = nodeId ?? AnimationNodeId.Untransformed; let node = nodesById.get(nodeId); if (!node) { - node = { + node = { animationNodeId: nodeId, animationId: `${this._options.batchModelId}_Node_${nodeId}`, primitives: [], @@ -474,7 +532,12 @@ class Parser { this.splitPrimitives(primitives, featureTable, computeNodeId, getNode); } - private splitPrimitives(primitives: Imdl.NodePrimitive[], featureTable: RenderFeatureTable, computeNodeId: ComputeAnimationNodeId, getPrimitivesNode: (nodeId: number | undefined) => Imdl.PrimitivesNode): void { + private splitPrimitives( + primitives: Imdl.NodePrimitive[], + featureTable: RenderFeatureTable, + computeNodeId: ComputeAnimationNodeId, + getPrimitivesNode: (nodeId: number | undefined) => Imdl.PrimitivesNode, + ): void { const splitArgs = { maxDimension: this._options.maxVertexTableSize, computeNodeId, @@ -507,11 +570,15 @@ class Parser { ...primitive.params.surface, indices: new VertexIndices(primitive.params.surface.indices), material: convertMaterial(mesh.surface.material), - textureMapping: texMap ? { - alwaysDisplayed: texMap.alwaysDisplayed, - // The texture type doesn't actually matter here. - texture: typeof texMap.texture === "string" ? new NamedTexture(texMap.texture, RenderTexture.Type.Normal) : new GradientTexture(texMap.texture), - } : undefined, + textureMapping: texMap ? + { + alwaysDisplayed: texMap.alwaysDisplayed, + // The texture type doesn't actually matter here. + texture: typeof texMap.texture === "string" + ? new NamedTexture(texMap.texture, RenderTexture.Type.Normal) + : new GradientTexture(texMap.texture), + } : + undefined, }, edges: primitive.params.edges ? edgeParamsFromImdl(primitive.params.edges) : undefined, isPlanar: primitive.params.isPlanar, @@ -544,10 +611,12 @@ class Parser { ...p.surface, indices: p.surface.indices.data, material, - textureMapping: p.surface.textureMapping?.texture instanceof Texture ? { - texture: p.surface.textureMapping.texture.toImdl(), - alwaysDisplayed: p.surface.textureMapping.alwaysDisplayed, - } : undefined, + textureMapping: p.surface.textureMapping?.texture instanceof Texture ? + { + texture: p.surface.textureMapping.texture.toImdl(), + alwaysDisplayed: p.surface.textureMapping.alwaysDisplayed, + } : + undefined, }, edges: p.edges ? edgeParamsToImdl(p.edges) : undefined, isPlanar: p.isPlanar, @@ -735,7 +804,7 @@ class Parser { if (!indexed && imdl.compact) indexed = this.parseCompactEdges(imdl.compact, new VertexIndices(indices)); - if (!segments && !silhouettes && !indexed &&!polylines) + if (!segments && !silhouettes && !indexed && !polylines) return undefined; return { @@ -971,7 +1040,9 @@ class Parser { if (undefined === rangeMin || undefined === rangeMax) return undefined; - const qparams = QParams3d.fromRange(Range3d.create(Point3d.create(rangeMin[0], rangeMin[1], rangeMin[2]), Point3d.create(rangeMax[0], rangeMax[1], rangeMax[2]))); + const qparams = QParams3d.fromRange( + Range3d.create(Point3d.create(rangeMin[0], rangeMin[1], rangeMin[2]), Point3d.create(rangeMax[0], rangeMax[1], rangeMax[2])), + ); const uniformColor = undefined !== json.uniformColor ? ColorDef.fromJSON(json.uniformColor) : undefined; let uvParams: QParams2d | undefined; @@ -1099,19 +1170,25 @@ class Parser { } private parseNamedTexture(namedTex: ImdlNamedTexture, name: string): RenderTexture | undefined { - const textureType = JsonUtils.asBool(namedTex.isGlyph) ? RenderTexture.Type.Glyph : + const textureType = JsonUtils.asBool(namedTex.isGlyph) ? + RenderTexture.Type.Glyph : (JsonUtils.asBool(namedTex.isTileSection) ? RenderTexture.Type.TileSection : RenderTexture.Type.Normal); return new NamedTexture(name, textureType); } - private parseConstantLodProps(propsJson: { repetitions?: number, offset?: number[], minDistClamp?: number, maxDistClamp?: number } | undefined): TextureMapping.ConstantLodParamProps | undefined { + private parseConstantLodProps( + propsJson: { repetitions?: number, offset?: number[], minDistClamp?: number, maxDistClamp?: number } | undefined, + ): TextureMapping.ConstantLodParamProps | undefined { if (undefined === propsJson) return undefined; return { repetitions: JsonUtils.asDouble(propsJson.repetitions, 1.0), - offset: { x: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[0]) : 0.0, y: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[1]) : 0.0 }, + offset: { + x: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[0]) : 0.0, + y: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[1]) : 0.0, + }, minDistClamp: JsonUtils.asDouble(propsJson.minDistClamp, 1.0), maxDistClamp: JsonUtils.asDouble(propsJson.maxDistClamp, 4096.0 * 1024.0 * 1024.0), }; @@ -1217,7 +1294,13 @@ export function toMaterialParams(mat: Imdl.SurfaceMaterialParams): MaterialParam /** @internal */ export function convertFeatureTable(imdlFeatureTable: Imdl.FeatureTable, batchModelId: Id64String): RenderFeatureTable { const table = imdlFeatureTable.multiModel - ? MultiModelPackedFeatureTable.create(imdlFeatureTable.data, batchModelId, imdlFeatureTable.numFeatures, BatchType.Primary, imdlFeatureTable.numSubCategories) + ? MultiModelPackedFeatureTable.create( + imdlFeatureTable.data, + batchModelId, + imdlFeatureTable.numFeatures, + BatchType.Primary, + imdlFeatureTable.numSubCategories, + ) : new PackedFeatureTable(imdlFeatureTable.data, batchModelId, imdlFeatureTable.numFeatures, BatchType.Primary); table.animationNodeIds = imdlFeatureTable.animationNodeIds; @@ -1258,13 +1341,13 @@ export function parseImdlDocument(options: ParseImdlDocumentArgs): Imdl.Document scene: JsonUtils.asString(sceneValue.scene), scenes: JsonUtils.asArray(sceneValue.scenes), animationNodes: JsonUtils.asObject(sceneValue.animationNodes), - bufferViews: JsonUtils.asObject(sceneValue.bufferViews) ?? { }, + bufferViews: JsonUtils.asObject(sceneValue.bufferViews) ?? {}, meshes: JsonUtils.asObject(sceneValue.meshes), - nodes: JsonUtils.asObject(sceneValue.nodes) ?? { }, - materials: JsonUtils.asObject(sceneValue.materials) ?? { }, - renderMaterials: JsonUtils.asObject(sceneValue.renderMaterials) ?? { }, - namedTextures: JsonUtils.asObject(sceneValue.namedTextures) ?? { }, - patternSymbols: JsonUtils.asObject(sceneValue.patternSymbols) ?? { }, + nodes: JsonUtils.asObject(sceneValue.nodes) ?? {}, + materials: JsonUtils.asObject(sceneValue.materials) ?? {}, + renderMaterials: JsonUtils.asObject(sceneValue.renderMaterials) ?? {}, + namedTextures: JsonUtils.asObject(sceneValue.namedTextures) ?? {}, + patternSymbols: JsonUtils.asObject(sceneValue.patternSymbols) ?? {}, rtcCenter: JsonUtils.asArray(sceneValue.rtcCenter), }; diff --git a/core/frontend/src/common/internal/render/AuxChannelTable.ts b/core/frontend/src/common/internal/render/AuxChannelTable.ts index 2182d5f67616..d3b75036ddf4 100644 --- a/core/frontend/src/common/internal/render/AuxChannelTable.ts +++ b/core/frontend/src/common/internal/render/AuxChannelTable.ts @@ -7,10 +7,8 @@ */ import { assert, Mutable } from "@itwin/core-bentley"; -import { - AuxChannelDataType, Point3d, AuxChannel as PolyfaceAuxChannel, Range1d, Range3d, Vector3d, -} from "@itwin/core-geometry"; import { OctEncodedNormal, QParams3d, QPoint3d, Quantization } from "@itwin/core-common"; +import { AuxChannel as PolyfaceAuxChannel, AuxChannelDataType, Point3d, Range1d, Range3d, Vector3d } from "@itwin/core-geometry"; import { computeDimensions } from "./VertexTable"; /** @alpha */ @@ -167,7 +165,9 @@ export class AuxChannelTable { params.push(new AuxParamChannel(param)); } - return undefined !== displacements || undefined !== normals || undefined !== params ? new AuxChannelTable(props, displacements, normals, params) : undefined; + return undefined !== displacements || undefined !== normals || undefined !== params + ? new AuxChannelTable(props, displacements, normals, params) + : undefined; } public toJSON(): AuxChannelTableProps { @@ -206,7 +206,11 @@ class AuxChannelTableBuilder { this._view = new DataView(props.data.buffer); } - public static buildAuxChannelTable(channels: ReadonlyArray, numVertices: number, maxDimension: number): AuxChannelTable | undefined { + public static buildAuxChannelTable( + channels: ReadonlyArray, + numVertices: number, + maxDimension: number, + ): AuxChannelTable | undefined { const numBytesPerVertex = channels.reduce((accum, channel) => accum + computeNumBytesPerVertex(channel), 0); if (!numBytesPerVertex) return undefined; diff --git a/core/frontend/src/common/internal/render/ColorMap.ts b/core/frontend/src/common/internal/render/ColorMap.ts index dd7aee63881e..cb69d368d3c3 100644 --- a/core/frontend/src/common/internal/render/ColorMap.ts +++ b/core/frontend/src/common/internal/render/ColorMap.ts @@ -13,9 +13,13 @@ import { ColorDef, ColorIndex } from "@itwin/core-common"; export class ColorMap extends IndexMap { private _hasTransparency: boolean = false; - public constructor() { super(compareNumbers, 0xffff); } + public constructor() { + super(compareNumbers, 0xffff); + } - public hasColor(color: number): boolean { return -1 !== this.indexOf(color); } + public hasColor(color: number): boolean { + return -1 !== this.indexOf(color); + } public override insert(color: number): number { // The table should never contain a mix of opaque and translucent colors. @@ -27,8 +31,12 @@ export class ColorMap extends IndexMap { return super.insert(color); } - public get hasTransparency(): boolean { return this._hasTransparency; } - public get isUniform(): boolean { return 1 === this.length; } + public get hasTransparency(): boolean { + return this._hasTransparency; + } + public get isUniform(): boolean { + return 1 === this.length; + } public toColorIndex(index: ColorIndex, indices: number[]): void { index.reset(); diff --git a/core/frontend/src/common/internal/render/DisplayParams.ts b/core/frontend/src/common/internal/render/DisplayParams.ts index eed3452eb5b1..1bd324adbf52 100644 --- a/core/frontend/src/common/internal/render/DisplayParams.ts +++ b/core/frontend/src/common/internal/render/DisplayParams.ts @@ -21,7 +21,7 @@ function compareTextureMappings(lhs?: TextureMapping, rhs?: TextureMapping): num * @internal */ export class DisplayParams { - public static readonly minTransparency: number = 15; // Threshold below which we consider a color fully opaque + public static readonly minTransparency: number = 15; // Threshold below which we consider a color fully opaque public readonly type: DisplayParams.Type = DisplayParams.Type.Mesh; public readonly material?: RenderMaterial; // meshes only public readonly gradient?: Gradient.Symb; @@ -33,8 +33,18 @@ export class DisplayParams { public readonly fillFlags: FillFlags; // meshes only public readonly ignoreLighting: boolean; // always true for text and linear geometry; true for meshes only if normals not desired - public constructor(type: DisplayParams.Type, lineColor: ColorDef, fillColor: ColorDef, width: number = 0, linePixels: LinePixels = LinePixels.Solid, - fillFlags: FillFlags = FillFlags.None, material?: RenderMaterial, gradient?: Gradient.Symb, ignoreLighting: boolean = false, textureMapping?: TextureMapping) { + public constructor( + type: DisplayParams.Type, + lineColor: ColorDef, + fillColor: ColorDef, + width: number = 0, + linePixels: LinePixels = LinePixels.Solid, + fillFlags: FillFlags = FillFlags.None, + material?: RenderMaterial, + gradient?: Gradient.Symb, + ignoreLighting: boolean = false, + textureMapping?: TextureMapping, + ) { this.type = type; this.material = material; this.gradient = gradient; @@ -50,7 +60,12 @@ export class DisplayParams { } /** Creates a DisplayParams object for a particular type (mesh, linear, text) based on the specified GraphicParams. */ - public static createForType(type: DisplayParams.Type, gf: GraphicParams, resolveGradient?: (grad: Gradient.Symb) => RenderTexture | undefined, ignoreLighting = false): DisplayParams { + public static createForType( + type: DisplayParams.Type, + gf: GraphicParams, + resolveGradient?: (grad: Gradient.Symb) => RenderTexture | undefined, + ignoreLighting = false, + ): DisplayParams { const lineColor = DisplayParams.adjustTransparency(gf.lineColor); switch (type) { case DisplayParams.Type.Mesh: { @@ -60,7 +75,18 @@ export class DisplayParams { if (undefined !== gradientTexture) gradientMapping = new TextureMapping(gradientTexture, new TextureMapping.Params()); } - return new DisplayParams(type, lineColor, DisplayParams.adjustTransparency(gf.fillColor), gf.rasterWidth, gf.linePixels, gf.fillFlags, gf.material, gf.gradient, ignoreLighting, gradientMapping); + return new DisplayParams( + type, + lineColor, + DisplayParams.adjustTransparency(gf.fillColor), + gf.rasterWidth, + gf.linePixels, + gf.fillFlags, + gf.material, + gf.gradient, + ignoreLighting, + gradientMapping, + ); } case DisplayParams.Type.Linear: return new DisplayParams(type, lineColor, lineColor, gf.rasterWidth, gf.linePixels); @@ -70,7 +96,11 @@ export class DisplayParams { } /** Creates a DisplayParams object that describes mesh geometry based on the specified GraphicParams. */ - public static createForMesh(gf: GraphicParams, ignoreLighting: boolean, resolveGradient?: (grad: Gradient.Symb) => RenderTexture | undefined): DisplayParams { + public static createForMesh( + gf: GraphicParams, + ignoreLighting: boolean, + resolveGradient?: (grad: Gradient.Symb) => RenderTexture | undefined, + ): DisplayParams { return DisplayParams.createForType(DisplayParams.Type.Mesh, gf, resolveGradient, ignoreLighting); } @@ -102,11 +132,21 @@ export class DisplayParams { return DisplayParams.RegionEdgeType.Outline === this.regionEdgeType; } - public get hasBlankingFill(): boolean { return FillFlags.Blanking === (this.fillFlags & FillFlags.Blanking); } - public get hasFillTransparency(): boolean { return 255 !== this.fillColor.getAlpha(); } - public get hasLineTransparency(): boolean { return 255 !== this.lineColor.getAlpha(); } - public get textureMapping(): TextureMapping | undefined { return undefined !== this.material ? this.material.textureMapping : this._textureMapping; } - public get isTextured(): boolean { return undefined !== this.textureMapping; } + public get hasBlankingFill(): boolean { + return FillFlags.Blanking === (this.fillFlags & FillFlags.Blanking); + } + public get hasFillTransparency(): boolean { + return 255 !== this.fillColor.getAlpha(); + } + public get hasLineTransparency(): boolean { + return 255 !== this.lineColor.getAlpha(); + } + public get textureMapping(): TextureMapping | undefined { + return undefined !== this.material ? this.material.textureMapping : this._textureMapping; + } + public get isTextured(): boolean { + return undefined !== this.textureMapping; + } /** Determines if the properties of this DisplayParams object are equal to those of another DisplayParams object. */ public equals(rhs: DisplayParams, purpose: DisplayParams.ComparePurpose = DisplayParams.ComparePurpose.Strict): boolean { @@ -200,7 +240,7 @@ export namespace DisplayParams { // eslint-disable-line no-redeclare } export enum ComparePurpose { - Merge, // considers colors equivalent if both have or both lack transparency + Merge, // considers colors equivalent if both have or both lack transparency Strict, // compares all members } } diff --git a/core/frontend/src/common/internal/render/EdgeParams.ts b/core/frontend/src/common/internal/render/EdgeParams.ts index 26fbdba0819d..387cf5466f44 100644 --- a/core/frontend/src/common/internal/render/EdgeParams.ts +++ b/core/frontend/src/common/internal/render/EdgeParams.ts @@ -6,12 +6,12 @@ * @module Rendering */ -import { LinePixels, MeshEdge, OctEncodedNormalPair, PolylineIndices } from "@itwin/core-common"; -import { VertexIndices } from "./VertexIndices"; -import { TesselatedPolyline, tesselatePolylineFromMesh, wantJointTriangles } from "./PolylineParams"; -import { MeshArgsEdges } from "./MeshPrimitives"; import { assert } from "@itwin/core-bentley"; +import { LinePixels, MeshEdge, OctEncodedNormalPair, PolylineIndices } from "@itwin/core-common"; import { MeshArgs } from "../../../render/MeshArgs"; +import { MeshArgsEdges } from "./MeshPrimitives"; +import { TesselatedPolyline, tesselatePolylineFromMesh, wantJointTriangles } from "./PolylineParams"; +import { VertexIndices } from "./VertexIndices"; /** * Describes a set of line segments representing edges of a mesh. @@ -144,9 +144,10 @@ export function calculateEdgeTableParams(numSegmentEdges: number, numSilhouettes function convertPolylinesAndEdges(polylines?: PolylineIndices[], edges?: MeshEdge[]): SegmentEdgeParams | undefined { let numIndices = undefined !== edges ? edges.length : 0; - if (undefined !== polylines) + if (undefined !== polylines) { for (const pd of polylines) - numIndices += (pd.length - 1); + numIndices += pd.length - 1; + } if (0 === numIndices) return undefined; @@ -247,7 +248,7 @@ function buildIndexedEdges(args: MeshArgsEdges, doPolylines: boolean, maxSize: n for (let j = 0; j < 6; j++) indices.setNthIndex(i * 6 + j, i); - const {width, height, silhouettePadding, silhouetteStartByteIndex } = calculateEdgeTableParams (numSegmentEdges, numSilhouettes, maxSize); + const { width, height, silhouettePadding, silhouetteStartByteIndex } = calculateEdgeTableParams(numSegmentEdges, numSilhouettes, maxSize); const data = new Uint8Array(width * height * 4); function setUint24(byteIndex: number, value: number): void { @@ -263,9 +264,10 @@ function buildIndexedEdges(args: MeshArgsEdges, doPolylines: boolean, maxSize: n } let curIndex = 0; - if (hardEdges) + if (hardEdges) { for (const edge of hardEdges) setEdge(curIndex++, edge.indices[0], edge.indices[1]); + } if (polylines) { for (const pd of polylines) { @@ -334,7 +336,9 @@ export function createEdgeParams(args: { indexed = buildIndexedEdges(edgeArgs, !doJoints, maxWidth); } else { segments = convertPolylinesAndEdges(undefined, edgeArgs.edges.edges); - silhouettes = edgeArgs.silhouettes.edges && edgeArgs.silhouettes.normals ? convertSilhouettes(edgeArgs.silhouettes.edges, edgeArgs.silhouettes.normals) : undefined; + silhouettes = edgeArgs.silhouettes.edges && edgeArgs.silhouettes.normals + ? convertSilhouettes(edgeArgs.silhouettes.edges, edgeArgs.silhouettes.normals) + : undefined; } if (!segments && !silhouettes && !polylines && !indexed) diff --git a/core/frontend/src/common/internal/render/GeometryAccumulator.ts b/core/frontend/src/common/internal/render/GeometryAccumulator.ts index dbae9af98820..1f256fed7325 100644 --- a/core/frontend/src/common/internal/render/GeometryAccumulator.ts +++ b/core/frontend/src/common/internal/render/GeometryAccumulator.ts @@ -6,14 +6,14 @@ * @module Rendering */ -import { IndexedPolyface, Loop, Path, Point3d, Range3d, SolidPrimitive, Transform } from "@itwin/core-geometry"; import { AnalysisStyleDisplacement, Feature } from "@itwin/core-common"; +import { IndexedPolyface, Loop, Path, Point3d, Range3d, SolidPrimitive, Transform } from "@itwin/core-geometry"; import { DisplayParams } from "./DisplayParams"; +import { GeometryList } from "./GeometryList"; +import { Geometry, PrimitiveGeometryType } from "./GeometryPrimitives"; import { MeshBuilderMap } from "./MeshBuilderMap"; import { MeshList } from "./MeshPrimitives"; import { GeometryOptions } from "./Primitives"; -import { GeometryList } from "./GeometryList"; -import { Geometry, PrimitiveGeometryType } from "./GeometryPrimitives"; /** @internal */ export class GeometryAccumulator { @@ -25,10 +25,18 @@ export class GeometryAccumulator { public readonly geometries: GeometryList = new GeometryList(); public currentFeature?: Feature; - public get surfacesOnly(): boolean { return this._surfacesOnly; } - public get transform(): Transform { return this._transform; } - public get isEmpty(): boolean { return this.geometries.isEmpty; } - public get haveTransform(): boolean { return !this._transform.isIdentity; } + public get surfacesOnly(): boolean { + return this._surfacesOnly; + } + public get transform(): Transform { + return this._transform; + } + public get isEmpty(): boolean { + return this.geometries.isEmpty; + } + public get haveTransform(): boolean { + return !this._transform.isIdentity; + } public constructor(options?: { surfacesOnly?: boolean; @@ -136,7 +144,9 @@ export class GeometryAccumulator { return true; } - public clear(): void { this.geometries.clear(); } + public clear(): void { + this.geometries.clear(); + } /** * Generates a MeshBuilderMap @@ -144,7 +154,11 @@ export class GeometryAccumulator { * note : removed featureTable, ViewContext * @param tolerance should derive from Viewport.getPixelSizeAtPoint */ - public toMeshBuilderMap(options: GeometryOptions, tolerance: number, pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined): MeshBuilderMap { + public toMeshBuilderMap( + options: GeometryOptions, + tolerance: number, + pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined, + ): MeshBuilderMap { const { geometries } = this; // declare internal dependencies const range = geometries.computeRange(); diff --git a/core/frontend/src/common/internal/render/GeometryList.ts b/core/frontend/src/common/internal/render/GeometryList.ts index 7dbff3240649..1f3d8828c742 100644 --- a/core/frontend/src/common/internal/render/GeometryList.ts +++ b/core/frontend/src/common/internal/render/GeometryList.ts @@ -6,17 +6,23 @@ * @module Rendering */ -import { Range3d } from "@itwin/core-geometry"; import { QParams3d } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { Geometry } from "./GeometryPrimitives"; /** @internal */ export class GeometryList { private _list: Geometry[] = []; - public get first(): Geometry | undefined { return this._list[0]; } - public get isEmpty(): boolean { return this._list.length === 0; } - public get length(): number { return this._list.length; } + public get first(): Geometry | undefined { + return this._list[0]; + } + public get isEmpty(): boolean { + return this._list.length === 0; + } + public get length(): number { + return this._list.length; + } public push(geom: Geometry): number { return this._list.push(geom); @@ -27,7 +33,9 @@ export class GeometryList { return this; } - public clear(): void { this._list.length = 0; } + public clear(): void { + this._list.length = 0; + } public computeRange(): Range3d { const range: Range3d = Range3d.createNull(); @@ -36,7 +44,9 @@ export class GeometryList { return range; } - public computeQuantizationParams(): QParams3d { return QParams3d.fromRange(this.computeRange()); } + public computeQuantizationParams(): QParams3d { + return QParams3d.fromRange(this.computeRange()); + } public [Symbol.iterator]() { return this._list[Symbol.iterator](); diff --git a/core/frontend/src/common/internal/render/GeometryPrimitives.ts b/core/frontend/src/common/internal/render/GeometryPrimitives.ts index d65daab545ae..d4c8eda21ac6 100644 --- a/core/frontend/src/common/internal/render/GeometryPrimitives.ts +++ b/core/frontend/src/common/internal/render/GeometryPrimitives.ts @@ -7,10 +7,21 @@ */ import { assert } from "@itwin/core-bentley"; +import { Feature } from "@itwin/core-common"; import { - CurveChain, IndexedPolyface, Loop, Path, Point3d, PolyfaceBuilder, PolyfaceQuery, Range3d, SolidPrimitive, StrokeOptions, SweepContour, Transform, + CurveChain, + IndexedPolyface, + Loop, + Path, + Point3d, + PolyfaceBuilder, + PolyfaceQuery, + Range3d, + SolidPrimitive, + StrokeOptions, + SweepContour, + Transform, } from "@itwin/core-geometry"; -import { Feature } from "@itwin/core-common"; import { DisplayParams } from "./DisplayParams"; import { PolyfacePrimitive, PolyfacePrimitiveList } from "./Polyface"; import { StrokesPrimitive, StrokesPrimitiveList, StrokesPrimitivePointList, StrokesPrimitivePointLists } from "./Strokes"; @@ -32,27 +43,65 @@ export abstract class Geometry { this.feature = feature; } - public static createFromPointString(pts: Point3d[], tf: Transform, tileRange: Range3d, params: DisplayParams, feature: Feature | undefined): Geometry { + public static createFromPointString( + pts: Point3d[], + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + feature: Feature | undefined, + ): Geometry { return new PrimitivePointStringGeometry(pts, tf, tileRange, params, feature); } - public static createFromLineString(pts: Point3d[], tf: Transform, tileRange: Range3d, params: DisplayParams, feature: Feature | undefined): Geometry { + public static createFromLineString( + pts: Point3d[], + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + feature: Feature | undefined, + ): Geometry { return new PrimitiveLineStringGeometry(pts, tf, tileRange, params, feature); } - public static createFromLoop(loop: Loop, tf: Transform, tileRange: Range3d, params: DisplayParams, disjoint: boolean, feature: Feature | undefined): Geometry { + public static createFromLoop( + loop: Loop, + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + disjoint: boolean, + feature: Feature | undefined, + ): Geometry { return new PrimitiveLoopGeometry(loop, tf, tileRange, params, disjoint, feature); } - public static createFromSolidPrimitive(primitive: SolidPrimitive, tf: Transform, tileRange: Range3d, params: DisplayParams, feature: Feature | undefined): Geometry { + public static createFromSolidPrimitive( + primitive: SolidPrimitive, + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + feature: Feature | undefined, + ): Geometry { return new SolidPrimitiveGeometry(primitive, tf, tileRange, params, feature); } - public static createFromPath(path: Path, tf: Transform, tileRange: Range3d, params: DisplayParams, disjoint: boolean, feature: Feature | undefined): Geometry { + public static createFromPath( + path: Path, + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + disjoint: boolean, + feature: Feature | undefined, + ): Geometry { return new PrimitivePathGeometry(path, tf, tileRange, params, disjoint, feature); } - public static createFromPolyface(ipf: IndexedPolyface, tf: Transform, tileRange: Range3d, params: DisplayParams, feature: Feature | undefined): Geometry { + public static createFromPolyface( + ipf: IndexedPolyface, + tf: Transform, + tileRange: Range3d, + params: DisplayParams, + feature: Feature | undefined, + ): Geometry { return new PrimitivePolyfaceGeometry(ipf, tf, tileRange, params, feature); } @@ -77,10 +126,18 @@ export abstract class Geometry { return this._getStrokes(strokeOptions); } - public get hasTexture() { return this.displayParams.isTextured; } - public doDecimate() { return false; } - public doVertexCluster() { return true; } - public part() { return undefined; } + public get hasTexture() { + return this.displayParams.isTextured; + } + public doDecimate() { + return false; + } + public doVertexCluster() { + return true; + } + public part() { + return undefined; + } } /** @internal */ @@ -94,13 +151,21 @@ export class PrimitivePathGeometry extends Geometry { this.isDisjoint = isDisjoint; } - protected _getPolyfaces(_facetOptions: StrokeOptions): PolyfacePrimitiveList | undefined { return undefined; } + protected _getPolyfaces(_facetOptions: StrokeOptions): PolyfacePrimitiveList | undefined { + return undefined; + } protected _getStrokes(facetOptions: StrokeOptions): StrokesPrimitiveList | undefined { return PrimitivePathGeometry.getStrokesForLoopOrPath(this.path, facetOptions, this.displayParams, this.isDisjoint, this.transform); } - public static getStrokesForLoopOrPath(loopOrPath: Loop | Path, facetOptions: StrokeOptions, params: DisplayParams, isDisjoint: boolean, transform: Transform): StrokesPrimitiveList | undefined { + public static getStrokesForLoopOrPath( + loopOrPath: Loop | Path, + facetOptions: StrokeOptions, + params: DisplayParams, + isDisjoint: boolean, + transform: Transform, + ): StrokesPrimitiveList | undefined { const strksList = new StrokesPrimitiveList(); if (!loopOrPath.isAnyRegionType || params.wantRegionOutline) { @@ -247,7 +312,9 @@ export class PrimitivePolyfaceGeometry extends Geometry { return new PolyfacePrimitiveList(PolyfacePrimitive.create(this.displayParams, this.polyface)); } - protected _getStrokes(_facetOptions: StrokeOptions): StrokesPrimitiveList | undefined { return undefined; } + protected _getStrokes(_facetOptions: StrokeOptions): StrokesPrimitiveList | undefined { + return undefined; + } } class SolidPrimitiveGeometry extends Geometry { @@ -259,7 +326,9 @@ class SolidPrimitiveGeometry extends Geometry { this._primitive = xformPrim !== undefined ? xformPrim as SolidPrimitive : primitive; } - protected _getStrokes() { return undefined; } + protected _getStrokes() { + return undefined; + } protected _getPolyfaces(opts: StrokeOptions): PolyfacePrimitiveList { const builder = PolyfaceBuilder.create(opts); diff --git a/core/frontend/src/common/internal/render/GraphicDescriptionBuilderImpl.ts b/core/frontend/src/common/internal/render/GraphicDescriptionBuilderImpl.ts index 84b4ba4f5a84..7cc7de4e5500 100644 --- a/core/frontend/src/common/internal/render/GraphicDescriptionBuilderImpl.ts +++ b/core/frontend/src/common/internal/render/GraphicDescriptionBuilderImpl.ts @@ -6,27 +6,30 @@ * @module Rendering */ +import { assert, Id64String, TransientIdSequence } from "@itwin/core-bentley"; +import { Gradient, PackedFeatureTable, QPoint3dList } from "@itwin/core-common"; import { Point3d, Range3d, Range3dProps, Transform, XYAndZ } from "@itwin/core-geometry"; +import { MeshArgs } from "../../../render/MeshArgs"; +import { PolylineArgs } from "../../../render/PolylineArgs"; import { addPrimitiveTransferables, ImdlModel } from "../../imdl/ImdlModel"; +import { edgeParamsToImdl } from "../../imdl/ParseImdlDocument"; +import { BatchOptions } from "../../render/BatchOptions"; +import { GraphicAssembler } from "../../render/GraphicAssembler"; import { - ComputeGraphicDescriptionChordToleranceArgs, GraphicDescription, GraphicDescriptionBuilder, GraphicDescriptionBuilderOptions, + ComputeGraphicDescriptionChordToleranceArgs, + GraphicDescription, + GraphicDescriptionBuilder, + GraphicDescriptionBuilderOptions, } from "../../render/GraphicDescriptionBuilder"; +import { GraphicDescriptionContext } from "../../render/GraphicDescriptionContext"; import { GraphicType } from "../../render/GraphicType"; -import { GraphicAssembler } from "../../render/GraphicAssembler"; -import { Gradient, PackedFeatureTable, QPoint3dList } from "@itwin/core-common"; -import { BatchOptions } from "../../render/BatchOptions"; -import { assert, Id64String, TransientIdSequence } from "@itwin/core-bentley"; +import { _accumulator, _implementationProhibited } from "../Symbols"; +import { WorkerGraphicDescriptionContextImpl, WorkerMaterial, WorkerTexture } from "./GraphicDescriptionContextImpl"; import { Mesh } from "./MeshPrimitives"; import { createPointStringParams } from "./PointStringParams"; -import { VertexTable } from "./VertexTable"; import { createPolylineParams } from "./PolylineParams"; +import { VertexTable } from "./VertexTable"; import { createMeshParams } from "./VertexTableBuilder"; -import { edgeParamsToImdl } from "../../imdl/ParseImdlDocument"; -import { _accumulator, _implementationProhibited } from "../Symbols"; -import { WorkerGraphicDescriptionContextImpl, WorkerMaterial, WorkerTexture } from "./GraphicDescriptionContextImpl"; -import { GraphicDescriptionContext } from "../../render/GraphicDescriptionContext"; -import { MeshArgs } from "../../../render/MeshArgs"; -import { PolylineArgs } from "../../../render/PolylineArgs"; export type BatchDescription = Omit & { featureTable: ImdlModel.FeatureTable; @@ -284,4 +287,3 @@ export function collectGraphicDescriptionTransferables(xfers: Set, addPrimitiveTransferables(xfers, primitive); } } - diff --git a/core/frontend/src/common/internal/render/GraphicDescriptionContextImpl.ts b/core/frontend/src/common/internal/render/GraphicDescriptionContextImpl.ts index ed8ad36cd4a5..f0cd3edc15a3 100644 --- a/core/frontend/src/common/internal/render/GraphicDescriptionContextImpl.ts +++ b/core/frontend/src/common/internal/render/GraphicDescriptionContextImpl.ts @@ -7,11 +7,29 @@ */ import { TransientIdSequence, TransientIdSequenceProps } from "@itwin/core-bentley"; -import { _implementationProhibited } from "../Symbols"; -import { GraphicDescriptionContextProps, WorkerGraphicDescriptionContext, WorkerGraphicDescriptionContextProps, WorkerTextureParams } from "../../render/GraphicDescriptionContext"; -import { MaterialParams } from "../../render/MaterialParams"; -import { ColorDef, ColorDefProps, Gradient, ImageBufferFormat, ImageSource, ImageSourceFormat, RenderMaterial, RenderTexture, RgbColor, RgbColorProps, TextureMapping, TextureTransparency } from "@itwin/core-common"; +import { + ColorDef, + ColorDefProps, + Gradient, + ImageBufferFormat, + ImageSource, + ImageSourceFormat, + RenderMaterial, + RenderTexture, + RgbColor, + RgbColorProps, + TextureMapping, + TextureTransparency, +} from "@itwin/core-common"; import { ImdlModel } from "../../imdl/ImdlModel"; +import { + GraphicDescriptionContextProps, + WorkerGraphicDescriptionContext, + WorkerGraphicDescriptionContextProps, + WorkerTextureParams, +} from "../../render/GraphicDescriptionContext"; +import { MaterialParams } from "../../render/MaterialParams"; +import { _implementationProhibited } from "../Symbols"; /** As part of a [[WorkerGraphicDescriptionContext]], describes constraints imposed by the [[RenderSystem]] that a [[GraphicDescriptionBuilder]] needs to know about * when creating a [[GraphicDescription]]. @@ -116,8 +134,10 @@ export class WorkerTexture extends RenderTexture { } } - public override dispose() { } - public override get bytesUsed() { return 0; } // doesn't matter, nobody's calling this. + public override dispose() {} + public override get bytesUsed() { + return 0; + } // doesn't matter, nobody's calling this. public toProps(xfer: Set): WorkerTextureProps { const source = this.source.gradient ? { ...this.source, gradient: this.source.gradient.toJSON() } : this.source; @@ -147,14 +167,17 @@ export class WorkerMaterial extends RenderMaterial { public constructor(params: MaterialParams) { let textureMapping; if (params.textureMapping) { - textureMapping = new TextureMapping(params.textureMapping.texture, new TextureMapping.Params({ - textureMat2x3: params.textureMapping.transform, - mapMode: params.textureMapping.mode, - textureWeight: params.textureMapping.weight, - worldMapping: params.textureMapping.worldMapping, - useConstantLod: params.textureMapping.useConstantLod, - constantLodProps: params.textureMapping.constantLodProps, - })); + textureMapping = new TextureMapping( + params.textureMapping.texture, + new TextureMapping.Params({ + textureMat2x3: params.textureMapping.transform, + mapMode: params.textureMapping.mode, + textureWeight: params.textureMapping.weight, + worldMapping: params.textureMapping.worldMapping, + useConstantLod: params.textureMapping.useConstantLod, + constantLodProps: params.textureMapping.constantLodProps, + }), + ); textureMapping.normalMapParams = params.textureMapping.normalMapParams; } @@ -241,4 +264,3 @@ export class WorkerGraphicDescriptionContextImpl implements WorkerGraphicDescrip }; } } - diff --git a/core/frontend/src/common/internal/render/InstancedGraphicPropsBuilder.ts b/core/frontend/src/common/internal/render/InstancedGraphicPropsBuilder.ts index b3920e92c784..4783a3bc447a 100644 --- a/core/frontend/src/common/internal/render/InstancedGraphicPropsBuilder.ts +++ b/core/frontend/src/common/internal/render/InstancedGraphicPropsBuilder.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Range3d } from "@itwin/core-geometry"; -import { Instance } from "../../render/RenderInstancesParams"; import { Feature, FeatureTable } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { InstancedGraphicProps } from "../../render/InstancedGraphicParams"; -import { OvrFlags } from "./OvrFlags"; +import { Instance } from "../../render/RenderInstancesParams"; import { lineCodeFromLinePixels } from "./LineCode"; +import { OvrFlags } from "./OvrFlags"; const invalidFeature = new Feature(); @@ -28,7 +28,9 @@ export class InstancedGraphicPropsBuilder { } } - public get length() { return this._instances.length; } + public get length() { + return this._instances.length; + } public finish(featureTable: FeatureTable | undefined): InstancedGraphicProps { const count = this.length; @@ -108,4 +110,3 @@ export class InstancedGraphicPropsBuilder { }; } } - diff --git a/core/frontend/src/common/internal/render/LineCode.ts b/core/frontend/src/common/internal/render/LineCode.ts index c8756cc038c7..ffcf8bea4367 100644 --- a/core/frontend/src/common/internal/render/LineCode.ts +++ b/core/frontend/src/common/internal/render/LineCode.ts @@ -13,16 +13,27 @@ import { LinePixels } from "@itwin/core-common"; */ export function lineCodeFromLinePixels(pixels: LinePixels): number { switch (pixels) { - case LinePixels.Code0: return 0; - case LinePixels.Code1: return 1; - case LinePixels.Code2: return 2; - case LinePixels.Code3: return 3; - case LinePixels.Code4: return 4; - case LinePixels.Code5: return 5; - case LinePixels.Code6: return 6; - case LinePixels.Code7: return 7; - case LinePixels.HiddenLine: return 8; - case LinePixels.Invisible: return 9; - default: return 0; + case LinePixels.Code0: + return 0; + case LinePixels.Code1: + return 1; + case LinePixels.Code2: + return 2; + case LinePixels.Code3: + return 3; + case LinePixels.Code4: + return 4; + case LinePixels.Code5: + return 5; + case LinePixels.Code6: + return 6; + case LinePixels.Code7: + return 7; + case LinePixels.HiddenLine: + return 8; + case LinePixels.Invisible: + return 9; + default: + return 0; } } diff --git a/core/frontend/src/common/internal/render/MeshBuilder.ts b/core/frontend/src/common/internal/render/MeshBuilder.ts index 18ae5291d14c..601e0d6fd6ce 100644 --- a/core/frontend/src/common/internal/render/MeshBuilder.ts +++ b/core/frontend/src/common/internal/render/MeshBuilder.ts @@ -7,13 +7,13 @@ */ import { assert, Dictionary } from "@itwin/core-bentley"; -import { Angle, IndexedPolyface, Point2d, Point3d, Polyface, PolyfaceVisitor, Range3d, Vector3d } from "@itwin/core-geometry"; import { Feature, MeshEdge, MeshEdges, MeshPolyline, OctEncodedNormal, OctEncodedNormalPair, QPoint3dList, TextureMapping } from "@itwin/core-common"; +import { Angle, IndexedPolyface, Point2d, Point3d, Polyface, PolyfaceVisitor, Range3d, Vector3d } from "@itwin/core-geometry"; import { DisplayParams } from "./DisplayParams"; +import { Mesh } from "./MeshPrimitives"; import { Triangle, TriangleKey, TriangleSet } from "./Primitives"; import { StrokesPrimitivePointLists } from "./Strokes"; import { VertexKey, VertexKeyProps, VertexMap } from "./VertexKey"; -import { Mesh } from "./MeshPrimitives"; // Describes a vertex along with the index of the source vertex in the source PolyfaceVisitor. type VertexKeyPropsWithIndex = VertexKeyProps & { sourceIndex: number }; @@ -27,9 +27,15 @@ export class MeshBuilder { public readonly tolerance: number; public readonly areaTolerance: number; public readonly tileRange: Range3d; - public get currentPolyface(): MeshBuilderPolyface | undefined { return this._currentPolyface; } - public get displayParams(): DisplayParams { return this.mesh.displayParams; } - public set displayParams(params: DisplayParams) { this.mesh.displayParams = params; } + public get currentPolyface(): MeshBuilderPolyface | undefined { + return this._currentPolyface; + } + public get displayParams(): DisplayParams { + return this.mesh.displayParams; + } + public set displayParams(params: DisplayParams) { + this.mesh.displayParams = params; + } /** create reference for triangleSet on demand */ public get triangleSet(): TriangleSet { @@ -124,7 +130,12 @@ export class MeshBuilder { } } - public createTriangleVertices(triangleIndex: number, visitor: PolyfaceVisitor, options: MeshBuilder.PolyfaceVisitorOptions, feature: Feature | undefined): VertexKeyPropsWithIndex[] | undefined { + public createTriangleVertices( + triangleIndex: number, + visitor: PolyfaceVisitor, + options: MeshBuilder.PolyfaceVisitorOptions, + feature: Feature | undefined, + ): VertexKeyPropsWithIndex[] | undefined { const { point, requireNormals } = visitor; const { fillColor, haveParam } = options; @@ -151,15 +162,22 @@ export class MeshBuilder { // Previously we would add all 3 vertices to our map, then detect degenerate triangles in AddTriangle(). // This led to unused vertex data, and caused mismatch in # of vertices when recreating the MeshBuilder from the data in the tile cache. // Detect beforehand instead. - if (this.vertexMap.arePositionsAlmostEqual(vertices[0], vertices[1]) + if ( + this.vertexMap.arePositionsAlmostEqual(vertices[0], vertices[1]) || this.vertexMap.arePositionsAlmostEqual(vertices[0], vertices[2]) - || this.vertexMap.arePositionsAlmostEqual(vertices[1], vertices[2])) + || this.vertexMap.arePositionsAlmostEqual(vertices[1], vertices[2]) + ) return undefined; return vertices; } - public createTriangle(triangleIndex: number, visitor: PolyfaceVisitor, options: MeshBuilder.PolyfaceVisitorOptions, feature: Feature | undefined): Triangle | undefined { + public createTriangle( + triangleIndex: number, + visitor: PolyfaceVisitor, + options: MeshBuilder.PolyfaceVisitorOptions, + feature: Feature | undefined, + ): Triangle | undefined { // generate vertex key properties for each of the three sides of the triangle const vertices = this.createTriangleVertices(triangleIndex, visitor, options, feature); @@ -276,12 +294,22 @@ export namespace MeshBuilder { // eslint-disable-line no-redeclare export class MeshEdgeCreationOptions { public readonly type: MeshEdgeCreationOptions.Type; public readonly minCreaseAngle = 20.0 * Angle.radiansPerDegree; - public get generateAllEdges(): boolean { return this.type === MeshEdgeCreationOptions.Type.AllEdges; } - public get generateNoEdges(): boolean { return this.type === MeshEdgeCreationOptions.Type.NoEdges; } - public get generateCreaseEdges(): boolean { return 0 !== (this.type & MeshEdgeCreationOptions.Type.CreaseEdges); } + public get generateAllEdges(): boolean { + return this.type === MeshEdgeCreationOptions.Type.AllEdges; + } + public get generateNoEdges(): boolean { + return this.type === MeshEdgeCreationOptions.Type.NoEdges; + } + public get generateCreaseEdges(): boolean { + return 0 !== (this.type & MeshEdgeCreationOptions.Type.CreaseEdges); + } /** Create edge chains for polyfaces that do not already have them. */ - public get createEdgeChains(): boolean { return 0 !== (this.type & MeshEdgeCreationOptions.Type.CreateChains); } - constructor(type = MeshEdgeCreationOptions.Type.NoEdges) { this.type = type; } + public get createEdgeChains(): boolean { + return 0 !== (this.type & MeshEdgeCreationOptions.Type.CreateChains); + } + constructor(type = MeshEdgeCreationOptions.Type.NoEdges) { + this.type = type; + } } /** @internal */ @@ -317,7 +345,8 @@ class EdgeInfo { public faceIndex0: number, public edge: MeshEdge, public point0: Point3d, - public point1: Point3d) { + public point1: Point3d, + ) { } public addFace(visible: boolean, faceIndex: number) { diff --git a/core/frontend/src/common/internal/render/MeshBuilderMap.ts b/core/frontend/src/common/internal/render/MeshBuilderMap.ts index cd80f28effe3..7d1a326ca8d2 100644 --- a/core/frontend/src/common/internal/render/MeshBuilderMap.ts +++ b/core/frontend/src/common/internal/render/MeshBuilderMap.ts @@ -7,17 +7,17 @@ */ import { compareBooleans, compareNumbers, Dictionary, Id64String } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { Feature, FeatureTable } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { DisplayParams } from "./DisplayParams"; -import { MeshPrimitiveType } from "./MeshPrimitive"; import { GeometryList } from "./GeometryList"; import { Geometry } from "./GeometryPrimitives"; +import { MeshBuilder, MeshEdgeCreationOptions } from "./MeshBuilder"; +import { MeshPrimitiveType } from "./MeshPrimitive"; +import { Mesh, MeshList } from "./MeshPrimitives"; import { PolyfacePrimitive } from "./Polyface"; import { GeometryOptions, ToleranceRatio } from "./Primitives"; import { StrokesPrimitive } from "./Strokes"; -import { MeshBuilder, MeshEdgeCreationOptions } from "./MeshBuilder"; -import { Mesh, MeshList } from "./MeshPrimitives"; /** @internal */ export class MeshBuilderMap extends Dictionary { @@ -31,7 +31,13 @@ export class MeshBuilderMap extends Dictionary private readonly _isVolumeClassifier: boolean; private _keyOrder = 0; - constructor(tolerance: number, range: Range3d, is2d: boolean, options: GeometryOptions, pickable: { isVolumeClassifier?: boolean, modelId?: Id64String } | undefined) { + constructor( + tolerance: number, + range: Range3d, + is2d: boolean, + options: GeometryOptions, + pickable: { isVolumeClassifier?: boolean, modelId?: Id64String } | undefined, + ) { super((lhs: MeshBuilderMap.Key, rhs: MeshBuilderMap.Key) => lhs.compare(rhs)); this.tolerance = tolerance; this.vertexTolerance = tolerance * ToleranceRatio.vertex; @@ -45,7 +51,14 @@ export class MeshBuilderMap extends Dictionary this.features = new FeatureTable(2048 * 1024, pickable.modelId); } - public static createFromGeometries(geometries: GeometryList, tolerance: number, range: Range3d, is2d: boolean, options: GeometryOptions, pickable: { isVolumeClassifier?: boolean, modelId?: Id64String } | undefined): MeshBuilderMap { + public static createFromGeometries( + geometries: GeometryList, + tolerance: number, + range: Range3d, + is2d: boolean, + options: GeometryOptions, + pickable: { isVolumeClassifier?: boolean, modelId?: Id64String } | undefined, + ): MeshBuilderMap { const map = new MeshBuilderMap(tolerance, range, is2d, options, pickable); for (const geom of geometries) @@ -79,9 +92,10 @@ export class MeshBuilderMap extends Dictionary public loadPolyfacePrimitiveList(geom: Geometry): void { const polyfaces = geom.getPolyfaces(this.tolerance); - if (polyfaces !== undefined) + if (polyfaces !== undefined) { for (const polyface of polyfaces) this.loadIndexedPolyface(polyface, geom.feature); + } } /** @@ -98,8 +112,14 @@ export class MeshBuilderMap extends Dictionary return; const builder = this.getBuilder(displayParams, MeshPrimitiveType.Mesh, normalCount > 0, isPlanar); - const edgeOptions = new MeshEdgeCreationOptions(polyface.displayEdges && this.options.wantEdges ? MeshEdgeCreationOptions.Type.DefaultEdges : MeshEdgeCreationOptions.Type.NoEdges); - builder.addFromPolyface(indexedPolyface, { edgeOptions, includeParams: isTextured, fillColor: fillColor.tbgr, mappedTexture: textureMapping }, feature); + const edgeOptions = new MeshEdgeCreationOptions( + polyface.displayEdges && this.options.wantEdges ? MeshEdgeCreationOptions.Type.DefaultEdges : MeshEdgeCreationOptions.Type.NoEdges, + ); + builder.addFromPolyface( + indexedPolyface, + { edgeOptions, includeParams: isTextured, fillColor: fillColor.tbgr, mappedTexture: textureMapping }, + feature, + ); } /** @@ -109,9 +129,10 @@ export class MeshBuilderMap extends Dictionary public loadStrokePrimitiveList(geom: Geometry): void { const strokes = geom.getStrokes(this.tolerance); - if (undefined !== strokes) + if (undefined !== strokes) { for (const stroke of strokes) this.loadStrokesPrimitive(stroke, geom.feature); + } } /** @@ -208,6 +229,8 @@ export namespace MeshBuilderMap { // eslint-disable-line no-redeclare return diff; } - public equals(rhs: Key): boolean { return 0 === this.compare(rhs); } + public equals(rhs: Key): boolean { + return 0 === this.compare(rhs); + } } } diff --git a/core/frontend/src/common/internal/render/MeshParams.ts b/core/frontend/src/common/internal/render/MeshParams.ts index 61ddc3f9d012..2b47b8efb1f2 100644 --- a/core/frontend/src/common/internal/render/MeshParams.ts +++ b/core/frontend/src/common/internal/render/MeshParams.ts @@ -7,9 +7,9 @@ */ import { AuxChannelTable } from "./AuxChannelTable"; -import { VertexTable } from "./VertexTable"; -import { SurfaceParams } from "./SurfaceParams"; import { EdgeParams } from "./EdgeParams"; +import { SurfaceParams } from "./SurfaceParams"; +import { VertexTable } from "./VertexTable"; /** Describes mesh geometry to be submitted to the rendering system. * A mesh consists of a surface and its edges, which may include any combination of silhouettes, polylines, and single segments. diff --git a/core/frontend/src/common/internal/render/MeshPrimitive.ts b/core/frontend/src/common/internal/render/MeshPrimitive.ts index 39f8c62de47d..d294823f79c1 100644 --- a/core/frontend/src/common/internal/render/MeshPrimitive.ts +++ b/core/frontend/src/common/internal/render/MeshPrimitive.ts @@ -6,8 +6,8 @@ * @module Rendering */ -import { Point3d, Range3d } from "@itwin/core-geometry"; import { QPoint3dList } from "@itwin/core-common"; +import { Point3d, Range3d } from "@itwin/core-geometry"; /** @internal */ export enum MeshPrimitiveType { diff --git a/core/frontend/src/common/internal/render/MeshPrimitives.ts b/core/frontend/src/common/internal/render/MeshPrimitives.ts index f1b5b86523a5..9682883be569 100644 --- a/core/frontend/src/common/internal/render/MeshPrimitives.ts +++ b/core/frontend/src/common/internal/render/MeshPrimitives.ts @@ -7,19 +7,33 @@ */ import { assert } from "@itwin/core-bentley"; -import { AuxChannel, AuxChannelData, Point2d, Point3d, Range3d } from "@itwin/core-geometry"; import { - ColorIndex, EdgeArgs, Feature, FeatureIndex, FeatureIndexType, FeatureTable, LinePixels, MeshEdges, MeshPolyline, MeshPolylineList, - OctEncodedNormal, PolylineEdgeArgs, PolylineFlags, PolylineTypeFlags, QParams3d, QPoint3dList, + ColorIndex, + EdgeArgs, + Feature, + FeatureIndex, + FeatureIndexType, + FeatureTable, + LinePixels, + MeshEdges, + MeshPolyline, + MeshPolylineList, + OctEncodedNormal, + PolylineEdgeArgs, + PolylineFlags, + PolylineTypeFlags, + QParams3d, + QPoint3dList, SilhouetteEdgeArgs, } from "@itwin/core-common"; +import { AuxChannel, AuxChannelData, Point2d, Point3d, Range3d } from "@itwin/core-geometry"; +import { MeshArgs } from "../../../render/MeshArgs"; +import { PolylineArgs } from "../../../render/PolylineArgs"; import { ColorMap } from "./ColorMap"; import { DisplayParams } from "./DisplayParams"; import { MeshPointList, MeshPrimitiveType, Point3dList } from "./MeshPrimitive"; import { Triangle, TriangleList } from "./Primitives"; import { VertexKeyProps } from "./VertexKey"; -import { MeshArgs } from "../../../render/MeshArgs"; -import { PolylineArgs } from "../../../render/PolylineArgs"; export function createPolylineArgs(mesh: Mesh): PolylineArgs | undefined { if (!mesh.polylines || mesh.polylines.length === 0) @@ -79,7 +93,9 @@ export class MeshArgsEdges { this.width = 0; this.linePixels = LinePixels.Solid; } - public get isValid(): boolean { return this.edges.isValid || this.silhouettes.isValid || this.polylines.isValid; } + public get isValid(): boolean { + return this.edges.isValid || this.silhouettes.isValid || this.polylines.isValid; + } } export function createMeshArgs(mesh: Mesh): MeshArgs | undefined { @@ -154,8 +170,8 @@ export class Mesh { this.type = type; this.is2d = is2d; this.isPlanar = isPlanar; - this.hasBakedLighting = (true === props.hasBakedLighting); - this.isVolumeClassifier = (true === props.isVolumeClassifier); + this.hasBakedLighting = true === props.hasBakedLighting; + this.isVolumeClassifier = true === props.isVolumeClassifier; if (props.quantizePositions) { this.points = new QPoint3dList(QParams3d.fromRange(range)); } else { @@ -170,7 +186,9 @@ export class Mesh { } } - public static create(props: Mesh.Props): Mesh { return new Mesh(props); } + public static create(props: Mesh.Props): Mesh { + return new Mesh(props); + } public get triangles(): TriangleList | undefined { return MeshPrimitiveType.Mesh === this.type ? this._data as TriangleList : undefined; @@ -294,7 +312,9 @@ export namespace Mesh { // eslint-disable-line no-redeclare public uniform = 0; public initialized = false; - public constructor(table: FeatureTable) { this.table = table; } + public constructor(table: FeatureTable) { + this.table = table; + } public add(feat: Feature, numVerts: number): void { const index = this.table.insert(feat); @@ -327,7 +347,7 @@ export namespace Mesh { // eslint-disable-line no-redeclare } public toFeatureIndex(output?: FeatureIndex): FeatureIndex { - const index = output ?? new FeatureIndex(); + const index = output ?? new FeatureIndex(); if (!this.initialized) { index.type = FeatureIndexType.Empty; } else if (this.indices.length === 0) { diff --git a/core/frontend/src/common/internal/render/OvrFlags.ts b/core/frontend/src/common/internal/render/OvrFlags.ts index 05031c8e8076..0dc45428af97 100644 --- a/core/frontend/src/common/internal/render/OvrFlags.ts +++ b/core/frontend/src/common/internal/render/OvrFlags.ts @@ -38,4 +38,3 @@ export const enum OvrFlags { // eslint-disable-line no-restricted-syntax Rgba = Rgb | Alpha, } - diff --git a/core/frontend/src/common/internal/render/PointStringParams.ts b/core/frontend/src/common/internal/render/PointStringParams.ts index 659e64ef0e15..10ef6117890b 100644 --- a/core/frontend/src/common/internal/render/PointStringParams.ts +++ b/core/frontend/src/common/internal/render/PointStringParams.ts @@ -7,10 +7,10 @@ */ import { assert } from "@itwin/core-bentley"; -import { VertexTableBuilder } from "./VertexTableBuilder"; +import { PolylineArgs } from "../../../render/PolylineArgs"; import { VertexIndices } from "./VertexIndices"; import { VertexTable } from "./VertexTable"; -import { PolylineArgs } from "../../../render/PolylineArgs"; +import { VertexTableBuilder } from "./VertexTableBuilder"; /** Describes point string geometry to be submitted to the rendering system. * @internal diff --git a/core/frontend/src/common/internal/render/Polyface.ts b/core/frontend/src/common/internal/render/Polyface.ts index 3ed83ff4f2e2..82b50ac5de6c 100644 --- a/core/frontend/src/common/internal/render/Polyface.ts +++ b/core/frontend/src/common/internal/render/Polyface.ts @@ -16,7 +16,9 @@ export class PolyfacePrimitive { public readonly displayEdges: boolean; public readonly isPlanar: boolean; - public get indexedPolyface() { return this._polyface; } + public get indexedPolyface() { + return this._polyface; + } public static create(params: DisplayParams, pf: IndexedPolyface, displayEdges: boolean = true, isPlanar: boolean = false) { return new PolyfacePrimitive(params, pf, displayEdges, isPlanar); @@ -29,8 +31,12 @@ export class PolyfacePrimitive { this.isPlanar = isPlanar; } - public clone(): PolyfacePrimitive { return new PolyfacePrimitive(this.displayParams, this._polyface.clone(), this.displayEdges, this.isPlanar); } - public transform(trans: Transform): boolean { return this._polyface.tryTransformInPlace(trans); } + public clone(): PolyfacePrimitive { + return new PolyfacePrimitive(this.displayParams, this._polyface.clone(), this.displayEdges, this.isPlanar); + } + public transform(trans: Transform): boolean { + return this._polyface.tryTransformInPlace(trans); + } } /** @internal */ diff --git a/core/frontend/src/common/internal/render/PolylineParams.ts b/core/frontend/src/common/internal/render/PolylineParams.ts index f663b1952190..f51a9b6f2e3d 100644 --- a/core/frontend/src/common/internal/render/PolylineParams.ts +++ b/core/frontend/src/common/internal/render/PolylineParams.ts @@ -6,14 +6,14 @@ * @module Rendering */ +import { assert } from "@itwin/core-bentley"; import { LinePixels, PolylineIndices, PolylineTypeFlags, QPoint3dList } from "@itwin/core-common"; -import { VertexIndices } from "./VertexIndices"; -import { VertexTable } from "./VertexTable"; import { Point3d, Vector3d } from "@itwin/core-geometry"; -import { assert } from "@itwin/core-bentley"; -import { VertexTableBuilder } from "./VertexTableBuilder"; import { MeshArgs } from "../../../render/MeshArgs"; import { PolylineArgs } from "../../../render/PolylineArgs"; +import { VertexIndices } from "./VertexIndices"; +import { VertexTable } from "./VertexTable"; +import { VertexTableBuilder } from "./VertexTableBuilder"; /** Represents a tesselated polyline. * Given a polyline as a line string, each segment of the line string is triangulated into a quad. @@ -64,7 +64,7 @@ class PolylineVertex { public prevIndex: number = 0; public nextIndex: number = 0; - public constructor() { } + public constructor() {} public init(isSegmentStart: boolean, isPolylineStartOrEnd: boolean, vertexIndex: number, prevIndex: number, nextIndex: number) { this.isSegmentStart = isSegmentStart; @@ -164,8 +164,8 @@ class PolylineTesselator { for (let i = 0; i < last; ++i) { const idx0 = line[i]; const idx1 = line[i + 1]; - const isStart: boolean = (0 === i); - const isEnd: boolean = (last - 1 === i); + const isStart: boolean = 0 === i; + const isEnd: boolean = last - 1 === i; const prevIdx0 = isStart ? (isClosed ? line[last - 1] : idx0) : line[i - 1]; const nextIdx1 = isEnd ? (isClosed ? line[1] : idx1) : line[i + 2]; diff --git a/core/frontend/src/common/internal/render/Primitives.ts b/core/frontend/src/common/internal/render/Primitives.ts index 4f5a130c5052..7d5e80357806 100644 --- a/core/frontend/src/common/internal/render/Primitives.ts +++ b/core/frontend/src/common/internal/render/Primitives.ts @@ -25,7 +25,9 @@ export class Triangle { public readonly visible = [true, true, true]; public singleSided: boolean; - public constructor(singleSided: boolean = true) { this.singleSided = singleSided; } + public constructor(singleSided: boolean = true) { + this.singleSided = singleSided; + } public setIndices(a: number, b: number, c: number) { this.indices[0] = a; @@ -44,7 +46,9 @@ export class Triangle { return this.visible[index]; } - public get isDegenerate() { return this.indices[0] === this.indices[1] || this.indices[0] === this.indices[2] || this.indices[1] === this.indices[2]; } + public get isDegenerate() { + return this.indices[0] === this.indices[1] || this.indices[0] === this.indices[2] || this.indices[1] === this.indices[2]; + } } /** @internal */ @@ -52,14 +56,18 @@ export class TriangleList { private readonly _flags: number[] = []; public readonly indices: number[] = []; - public get length(): number { return this._flags.length; } - public get isEmpty(): boolean { return 0 === this.length; } + public get length(): number { + return this._flags.length; + } + public get isEmpty(): boolean { + return 0 === this.length; + } public addTriangle(triangle: Triangle): void { let flags = triangle.singleSided ? 1 : 0; for (let i = 0; i < 3; i++) { if (triangle.isEdgeVisible(i)) - flags |= (0x0002 << i); + flags |= 0x0002 << i; this.indices.push(triangle.indices[i]); } diff --git a/core/frontend/src/common/internal/render/Strokes.ts b/core/frontend/src/common/internal/render/Strokes.ts index 23f1d233d5a1..43db0de473aa 100644 --- a/core/frontend/src/common/internal/render/Strokes.ts +++ b/core/frontend/src/common/internal/render/Strokes.ts @@ -12,7 +12,9 @@ import { DisplayParams } from "./DisplayParams"; /** @internal */ export class StrokesPrimitivePointList { public points: Point3d[]; - constructor(points: Point3d[] = []) { this.points = [...points]; } + constructor(points: Point3d[] = []) { + this.points = [...points]; + } } /** @internal */ diff --git a/core/frontend/src/common/internal/render/VertexIndices.ts b/core/frontend/src/common/internal/render/VertexIndices.ts index 3523fc5138af..1cea0de1e6ca 100644 --- a/core/frontend/src/common/internal/render/VertexIndices.ts +++ b/core/frontend/src/common/internal/render/VertexIndices.ts @@ -26,7 +26,9 @@ export class VertexIndices implements Iterable { } /** Get the number of 24-bit indices. */ - public get length(): number { return this.data.length / 3; } + public get length(): number { + return this.data.length / 3; + } /** Convert an array of 24-bit unsigned integer values into a VertexIndices object. */ public static fromArray(indices: number[]): VertexIndices { @@ -63,7 +65,7 @@ export class VertexIndices implements Iterable { } public [Symbol.iterator]() { - function * iterator(indices: VertexIndices) { + function* iterator(indices: VertexIndices) { for (let i = 0; i < indices.length; i++) yield indices.decodeIndex(i); } diff --git a/core/frontend/src/common/internal/render/VertexKey.ts b/core/frontend/src/common/internal/render/VertexKey.ts index 126527f658a6..1b273ea001af 100644 --- a/core/frontend/src/common/internal/render/VertexKey.ts +++ b/core/frontend/src/common/internal/render/VertexKey.ts @@ -7,8 +7,8 @@ */ import { assert, comparePossiblyUndefined, compareWithTolerance, IndexMap } from "@itwin/core-bentley"; -import { Point2d, Point3d, XYAndZ } from "@itwin/core-geometry"; import { Feature, OctEncodedNormal } from "@itwin/core-common"; +import { Point2d, Point3d, XYAndZ } from "@itwin/core-geometry"; /** @internal */ export interface VertexKeyProps { diff --git a/core/frontend/src/common/internal/render/VertexTableBuilder.ts b/core/frontend/src/common/internal/render/VertexTableBuilder.ts index 6f9965ed168f..8e0032ec0123 100644 --- a/core/frontend/src/common/internal/render/VertexTableBuilder.ts +++ b/core/frontend/src/common/internal/render/VertexTableBuilder.ts @@ -7,19 +7,17 @@ */ import { assert } from "@itwin/core-bentley"; +import { ColorDef, ColorIndex, FeatureIndex, FeatureIndexType, FillFlags, QParams2d, QParams3d, QPoint2d, QPoint3dList } from "@itwin/core-common"; import { Point2d, Point3d, Range2d } from "@itwin/core-geometry"; -import { - ColorDef, ColorIndex, FeatureIndex, FeatureIndexType, FillFlags, QParams2d, QParams3d, QPoint2d, QPoint3dList, -} from "@itwin/core-common"; +import { MeshArgs } from "../../../render/MeshArgs"; +import { PolylineArgs } from "../../../render/PolylineArgs"; import { AuxChannelTable } from "./AuxChannelTable"; -import { computeDimensions, VertexTable } from "./VertexTable"; -import { createSurfaceMaterial, SurfaceParams, SurfaceType } from "./SurfaceParams"; +import { createEdgeParams } from "./EdgeParams"; import { MeshParams } from "./MeshParams"; import { Point3dList } from "./MeshPrimitive"; +import { createSurfaceMaterial, SurfaceParams, SurfaceType } from "./SurfaceParams"; import { VertexIndices } from "./VertexIndices"; -import { createEdgeParams } from "./EdgeParams"; -import { MeshArgs } from "../../../render/MeshArgs"; -import { PolylineArgs } from "../../../render/PolylineArgs"; +import { computeDimensions, VertexTable } from "./VertexTable"; /** @internal */ export function createMeshParams(args: MeshArgs, maxDimension: number, enableIndexedEdges: boolean): MeshParams { @@ -59,7 +57,9 @@ export abstract class VertexTableBuilder { public abstract get numRgbaPerVertex(): number; public abstract get qparams(): QParams3d; public abstract get usesUnquantizedPositions(): boolean; - public get uvParams(): QParams2d | undefined { return undefined; } + public get uvParams(): QParams2d | undefined { + return undefined; + } public abstract appendVertex(vertIndex: number): void; public appendColorTable(colorIndex: ColorIndex) { @@ -188,9 +188,15 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== this.args.points); } - public get numVertices() { return this.args.points.length; } - public get numRgbaPerVertex() { return 3; } - public get usesUnquantizedPositions() { return false; } + public get numVertices() { + return this.args.points.length; + } + public get numRgbaPerVertex() { + return 3; + } + public get usesUnquantizedPositions() { + return false; + } public get qparams() { return this._qpoints.params; } @@ -246,9 +252,10 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare const uvRange = Range2d.createNull(); const fpts = args.textureMapping.uvParams; const pt2d = new Point2d(); - if (undefined !== fpts && fpts.length > 0) + if (undefined !== fpts && fpts.length > 0) { for (let i = 0; i < args.points.length; i++) uvRange.extendPoint(Point2d.create(fpts[i].x, fpts[i].y, pt2d)); + } uvParams = QParams2d.fromRange(uvRange); } @@ -274,8 +281,12 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== args.textureMapping); } - public override get numRgbaPerVertex() { return 4; } - public override get uvParams() { return this._qparams; } + public override get numRgbaPerVertex() { + return 4; + } + public override get uvParams() { + return this._qparams; + } public override appendVertex(vertIndex: number) { this.appendPosition(vertIndex); @@ -284,7 +295,9 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare this.appendUVParams(vertIndex); } - protected appendNormal(_vertIndex: number): void { this.advance(2); } // no normal for unlit meshes + protected appendNormal(_vertIndex: number): void { + this.advance(2); + } // no normal for unlit meshes protected appendUVParams(vertIndex: number) { this._qpoint.init(this.args.textureMapping!.uvParams[vertIndex], this._qparams); @@ -300,7 +313,9 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== args.normals); } - protected override appendNormal(vertIndex: number) { this.append16(this.args.normals![vertIndex].value); } + protected override appendNormal(vertIndex: number) { + this.append16(this.args.normals![vertIndex].value); + } } /** 16 bytes. The last 2 bytes are unused; the 2 immediately preceding it hold the oct-encoded normal value. */ @@ -310,7 +325,9 @@ namespace Quantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== args.normals); } - public override get numRgbaPerVertex() { return 4; } + public override get numRgbaPerVertex() { + return 4; + } public override appendVertex(vertIndex: number) { super.appendVertex(vertIndex); @@ -353,10 +370,18 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare this._points = args.points; } - public get numVertices() { return this._points.length; } - public get numRgbaPerVertex() { return 5; } - public get usesUnquantizedPositions() { return true; } - public get qparams() { return this._qparams3d; } + public get numVertices() { + return this._points.length; + } + public get numRgbaPerVertex() { + return 5; + } + public get usesUnquantizedPositions() { + return true; + } + public get qparams() { + return this._qparams3d; + } public appendVertex(vertIndex: number): void { this.appendTransposePosAndFeatureNdx(vertIndex); @@ -377,9 +402,9 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare // transpose position xyz vals into [0].xyz - [3].xyz, and add feature index at .w // this is to order things to let shader code access much more efficiently const pt = this._points[vertIndex]; - const x = this.convertFloat32 (pt.x); - const y = this.convertFloat32 (pt.y); - const z = this.convertFloat32 (pt.z); + const x = this.convertFloat32(pt.x); + const y = this.convertFloat32(pt.y); + const z = this.convertFloat32(pt.z); const featID = (this.args.features.featureIDs) ? this.args.features.featureIDs[vertIndex] : 0; this.append8(x & 0x000000ff); this.append8(y & 0x000000ff); @@ -447,9 +472,10 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare const uvRange = Range2d.createNull(); const fpts = args.textureMapping.uvParams; const pt2d = new Point2d(); - if (undefined !== fpts && fpts.length > 0) + if (undefined !== fpts && fpts.length > 0) { for (let i = 0; i < args.points.length; i++) uvRange.extendPoint(Point2d.create(fpts[i].x, fpts[i].y, pt2d)); + } uvParams = QParams2d.fromRange(uvRange); } @@ -473,7 +499,9 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== args.textureMapping); } - public override get uvParams() { return this._qparams; } + public override get uvParams() { + return this._qparams; + } public override appendVertex(vertIndex: number) { super.appendVertex(vertIndex); @@ -483,7 +511,7 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare this.append16(this._qpoint.y); } - protected override appendColorIndex() { } + protected override appendColorIndex() {} } // u: 10 @@ -496,7 +524,9 @@ namespace Unquantized { // eslint-disable-line @typescript-eslint/no-redeclare assert(undefined !== args.normals); } - public override get numRgbaPerVertex() { return 6; } + public override get numRgbaPerVertex() { + return 6; + } public override appendVertex(vertIndex: number) { super.appendVertex(vertIndex); diff --git a/core/frontend/src/common/internal/render/VertexTableSplitter.ts b/core/frontend/src/common/internal/render/VertexTableSplitter.ts index d5dd732cd4ba..ad9afd7bf901 100644 --- a/core/frontend/src/common/internal/render/VertexTableSplitter.ts +++ b/core/frontend/src/common/internal/render/VertexTableSplitter.ts @@ -8,14 +8,14 @@ import { assert, Uint32ArrayBuilder, Uint8ArrayBuilder } from "@itwin/core-bentley"; import { ColorDef, RenderFeatureTable, RenderMaterial } from "@itwin/core-common"; -import { calculateEdgeTableParams, EdgeParams, EdgeTable, IndexedEdgeParams } from "./EdgeParams"; -import { computeDimensions, VertexTable } from "./VertexTable"; -import { VertexIndices } from "./VertexIndices"; -import { createSurfaceMaterial, SurfaceMaterial } from "./SurfaceParams"; import { MaterialParams } from "../../render/MaterialParams"; +import { calculateEdgeTableParams, EdgeParams, EdgeTable, IndexedEdgeParams } from "./EdgeParams"; import { MeshParams } from "./MeshParams"; import { PointStringParams } from "./PointStringParams"; import { PolylineParams, TesselatedPolyline } from "./PolylineParams"; +import { createSurfaceMaterial, SurfaceMaterial } from "./SurfaceParams"; +import { VertexIndices } from "./VertexIndices"; +import { computeDimensions, VertexTable } from "./VertexTable"; /** @internal */ export interface VertexTableWithIndices { @@ -253,11 +253,16 @@ class Node { public constructor(vertexTable: VertexTable, atlas?: AtlasInfo) { this.vertices = new VertexBuffer(vertexTable); if (undefined === vertexTable.uniformColor) - this.colors = new ColorTableRemapper(new Uint32Array(vertexTable.data.buffer, vertexTable.data.byteOffset + 4 * vertexTable.numVertices * vertexTable.numRgbaPerVertex)); + this.colors = new ColorTableRemapper( + new Uint32Array(vertexTable.data.buffer, vertexTable.data.byteOffset + 4 * vertexTable.numVertices * vertexTable.numRgbaPerVertex), + ); if (atlas) { const atlasOffset = (vertexTable.numVertices * vertexTable.numRgbaPerVertex + atlas.offset) * 4; - this.atlas = new MaterialAtlasRemapper(new Uint32Array(vertexTable.data.buffer, vertexTable.data.byteOffset + atlasOffset), atlas.createMaterial); + this.atlas = new MaterialAtlasRemapper( + new Uint32Array(vertexTable.data.buffer, vertexTable.data.byteOffset + atlasOffset), + atlas.createMaterial, + ); } this.usesUnquantizedPositions = vertexTable.usesUnquantizedPositions; @@ -342,7 +347,11 @@ class VertexTableSplitter { const vertSize = this._input.vertices.numRgbaPerVertex; const vertex = new Uint32Array(vertSize); - const vertexTable = new Uint32Array(this._input.vertices.data.buffer, this._input.vertices.data.byteOffset, this._input.vertices.numVertices * vertSize); + const vertexTable = new Uint32Array( + this._input.vertices.data.buffer, + this._input.vertices.data.byteOffset, + this._input.vertices.numVertices * vertSize, + ); let extractFeatureIndex: () => number; if (this._input.vertices.usesUnquantizedPositions) { @@ -469,11 +478,15 @@ function remapSegmentEdges(type: "segments" | "silhouettes", source: EdgeParams, let srcNormalPairs; if (type === "silhouettes") { assert(undefined !== source.silhouettes); - srcNormalPairs = new Uint32Array(source.silhouettes.normalPairs.buffer, source.silhouettes.normalPairs.byteOffset, source.silhouettes.normalPairs.length / 4); + srcNormalPairs = new Uint32Array( + source.silhouettes.normalPairs.buffer, + source.silhouettes.normalPairs.byteOffset, + source.silhouettes.normalPairs.length / 4, + ); } let curIndexIndex = 0; - const remappedIndex = { } as unknown as RemappedIndex; + const remappedIndex = {} as unknown as RemappedIndex; for (const srcIndex of src.indices) { if (remapIndex(remappedIndex, srcIndex, nodes)) { let endPointAndQuad = srcEndPts[curIndexIndex]; @@ -484,7 +497,7 @@ function remapSegmentEdges(type: "segments" | "silhouettes", source: EdgeParams, let entry = edges.get(remappedIndex.id); if (!entry) - edges.set(remappedIndex.id, entry = { }); + edges.set(remappedIndex.id, entry = {}); if (srcNormalPairs) { if (!entry.silhouettes) @@ -510,7 +523,7 @@ function remapPolylineEdges(src: TesselatedPolyline, nodes: Map, e const srcNextAndParam = new Uint32Array(src.nextIndicesAndParams.buffer, src.nextIndicesAndParams.byteOffset, src.nextIndicesAndParams.length / 4); const prevIter = src.prevIndices[Symbol.iterator](); let curIndexIndex = 0; - const remappedIndex = { } as unknown as RemappedIndex; + const remappedIndex = {} as unknown as RemappedIndex; for (const srcIndex of src.indices) { if (remapIndex(remappedIndex, srcIndex, nodes)) { const prevIndex = prevIter.next().value; @@ -526,7 +539,7 @@ function remapPolylineEdges(src: TesselatedPolyline, nodes: Map, e let entry = edges.get(remappedIndex.id); if (!entry) - edges.set(remappedIndex.id, entry = { }); + edges.set(remappedIndex.id, entry = {}); if (!entry.polylines) entry.polylines = new RemappedPolylineEdges(); @@ -546,8 +559,10 @@ function remapIndexedEdges(src: IndexedEdgeParams, nodes: Map, edg const silhouetteStartByteIndex = numSegments * 6 + src.edges.silhouettePadding; function getUint24EdgePair(byteIndex: number): [number, number] { - return [srcEdgeData[byteIndex + 0] | (srcEdgeData[byteIndex + 1] << 8) | srcEdgeData[byteIndex + 2] << 16, - srcEdgeData[byteIndex + 3] | (srcEdgeData[byteIndex + 4] << 8) | srcEdgeData[byteIndex + 5] << 16]; + return [ + srcEdgeData[byteIndex + 0] | (srcEdgeData[byteIndex + 1] << 8) | srcEdgeData[byteIndex + 2] << 16, + srcEdgeData[byteIndex + 3] | (srcEdgeData[byteIndex + 4] << 8) | srcEdgeData[byteIndex + 5] << 16, + ]; } function setUint24EdgePair(indEdges: RemappedIndexEdges, value1: number, value2: number): void { @@ -560,9 +575,12 @@ function remapIndexedEdges(src: IndexedEdgeParams, nodes: Map, edg } function getUint24SilPair(byteIndex: number): [number, number, number, number] { - return [srcEdgeData[byteIndex + 0] | (srcEdgeData[byteIndex + 1] << 8) | srcEdgeData[byteIndex + 2] << 16, + return [ + srcEdgeData[byteIndex + 0] | (srcEdgeData[byteIndex + 1] << 8) | srcEdgeData[byteIndex + 2] << 16, srcEdgeData[byteIndex + 3] | (srcEdgeData[byteIndex + 4] << 8) | srcEdgeData[byteIndex + 5] << 16, - srcEdgeData[byteIndex + 6] | (srcEdgeData[byteIndex + 7] << 8), srcEdgeData[byteIndex + 8] | (srcEdgeData[byteIndex + 9] << 8)]; + srcEdgeData[byteIndex + 6] | (srcEdgeData[byteIndex + 7] << 8), + srcEdgeData[byteIndex + 8] | (srcEdgeData[byteIndex + 9] << 8), + ]; } function setUint24SilPair(indSil: RemappedIndexEdges, value1: number, value2: number, norm1: number, norm2: number): void { @@ -580,15 +598,15 @@ function remapIndexedEdges(src: IndexedEdgeParams, nodes: Map, edg let maxIndex = 0; for (const srcIndex of src.indices) - maxIndex = Math.max (srcIndex, maxIndex); + maxIndex = Math.max(srcIndex, maxIndex); - const remappedIndex = { } as unknown as RemappedIndex; + const remappedIndex = {} as unknown as RemappedIndex; let es1Index = 0, es2Index = 0, n1 = 0, n2 = 0; for (let curSegment = 0, byteIndex = 0; curSegment <= maxIndex; ++curSegment) { - if (curSegment < numSegments) { // edges + if (curSegment < numSegments) { // edges [es1Index, es2Index] = getUint24EdgePair(byteIndex); byteIndex += 6; - } else { // silhouettes + } else { // silhouettes byteIndex = silhouetteStartByteIndex + (curSegment - numSegments) * 10; [es1Index, es2Index, n1, n2] = getUint24SilPair(byteIndex); } @@ -596,18 +614,18 @@ function remapIndexedEdges(src: IndexedEdgeParams, nodes: Map, edg if (remapIndex(remappedIndex, es1Index, nodes)) { let entry = edges.get(remappedIndex.id); if (!entry) - edges.set(remappedIndex.id, entry = { }); + edges.set(remappedIndex.id, entry = {}); if (!entry.indexed) entry.indexed = { edges: new Uint8ArrayBuilder(), silhouettes: new Uint8ArrayBuilder() }; - if (curSegment < numSegments) { // edges + if (curSegment < numSegments) { // edges const newE1Index = remappedIndex.node.remappedIndices.get(es1Index); assert(undefined !== newE1Index); const newE2Index = remappedIndex.node.remappedIndices.get(es2Index); assert(undefined !== newE2Index); setUint24EdgePair(entry.indexed, newE1Index, newE2Index); - } else { // silhouettes + } else { // silhouettes const newS1Index = remappedIndex.node.remappedIndices.get(es1Index); assert(undefined !== newS1Index); const newS2Index = remappedIndex.node.remappedIndices.get(es2Index); @@ -634,8 +652,8 @@ function splitEdges(source: EdgeParams, nodes: Map, maxDimension: if (!remappedEdges.segments && !remappedEdges.silhouettes && !remappedEdges.indexed) continue; - let edgeTable = { } as unknown as EdgeTable; - let edgeIndices = { } as unknown as VertexIndices; + let edgeTable = {} as unknown as EdgeTable; + let edgeIndices = {} as unknown as VertexIndices; if (remappedEdges.indexed) { const numSegmentEdges = remappedEdges.indexed.edges.length / 6; const numSilhouettes = remappedEdges.indexed.silhouettes.length / 10; @@ -663,24 +681,32 @@ function splitEdges(source: EdgeParams, nodes: Map, maxDimension: result.set(id, { weight: source.weight, linePixels: source.linePixels, - segments: remappedEdges.segments ? { - indices: remappedEdges.segments.indices.toVertexIndices(), - endPointAndQuadIndices: remappedEdges.segments.endPointAndQuadIndices.toUint8Array(), - } : undefined, - silhouettes: remappedEdges.silhouettes ? { - indices: remappedEdges.silhouettes.indices.toVertexIndices(), - endPointAndQuadIndices: remappedEdges.silhouettes.endPointAndQuadIndices.toUint8Array(), - normalPairs: remappedEdges.silhouettes.normalPairs.toUint8Array(), - } : undefined, - polylines: remappedEdges.polylines ? { - indices: remappedEdges.polylines.indices.toVertexIndices(), - prevIndices: remappedEdges.polylines.prevIndices.toVertexIndices(), - nextIndicesAndParams: remappedEdges.polylines.nextIndicesAndParams.toUint8Array(), - } : undefined, - indexed: remappedEdges.indexed ? { - indices: edgeIndices, - edges: edgeTable, - } : undefined, + segments: remappedEdges.segments ? + { + indices: remappedEdges.segments.indices.toVertexIndices(), + endPointAndQuadIndices: remappedEdges.segments.endPointAndQuadIndices.toUint8Array(), + } : + undefined, + silhouettes: remappedEdges.silhouettes ? + { + indices: remappedEdges.silhouettes.indices.toVertexIndices(), + endPointAndQuadIndices: remappedEdges.silhouettes.endPointAndQuadIndices.toUint8Array(), + normalPairs: remappedEdges.silhouettes.normalPairs.toUint8Array(), + } : + undefined, + polylines: remappedEdges.polylines ? + { + indices: remappedEdges.polylines.indices.toVertexIndices(), + prevIndices: remappedEdges.polylines.prevIndices.toVertexIndices(), + nextIndicesAndParams: remappedEdges.polylines.nextIndicesAndParams.toUint8Array(), + } : + undefined, + indexed: remappedEdges.indexed ? + { + indices: edgeIndices, + edges: edgeTable, + } : + undefined, }); } @@ -755,7 +781,7 @@ export function splitPolylineParams(args: SplitPolylineArgs): Map this.resolveGradient(grad)); } - private getLinearDisplayParams(): DisplayParams { return DisplayParams.createForLinear(this._graphicParams); } + private getMeshDisplayParams(): DisplayParams { + return DisplayParams.createForMesh(this._graphicParams, !this.wantNormals, (grad) => this.resolveGradient(grad)); + } + private getLinearDisplayParams(): DisplayParams { + return DisplayParams.createForLinear(this._graphicParams); + } /** @internal */ protected abstract resolveGradient(gradient: Gradient.Symb): RenderTexture | undefined; - public add(geom: Geometry): void { this[_accumulator].addGeometry(geom); } + public add(geom: Geometry): void { + this[_accumulator].addGeometry(geom); + } } function copy2dTo3d(pts2d: Point2d[], depth: number): Point3d[] { diff --git a/core/frontend/src/common/render/GraphicDescriptionBuilder.ts b/core/frontend/src/common/render/GraphicDescriptionBuilder.ts index 72bcf6aad6c5..5fad5f5eaf12 100644 --- a/core/frontend/src/common/render/GraphicDescriptionBuilder.ts +++ b/core/frontend/src/common/render/GraphicDescriptionBuilder.ts @@ -6,13 +6,13 @@ * @module Rendering */ -import { GraphicAssembler } from "./GraphicAssembler"; -import { collectGraphicDescriptionTransferables, GraphicDescriptionBuilderImpl } from "../internal/render/GraphicDescriptionBuilderImpl"; import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; -import { GraphicType } from "./GraphicType"; -import { PickableGraphicOptions } from "./BatchOptions"; +import { collectGraphicDescriptionTransferables, GraphicDescriptionBuilderImpl } from "../internal/render/GraphicDescriptionBuilderImpl"; import { _implementationProhibited } from "../internal/Symbols"; +import { PickableGraphicOptions } from "./BatchOptions"; +import { GraphicAssembler } from "./GraphicAssembler"; import { WorkerGraphicDescriptionContext } from "./GraphicDescriptionContext"; +import { GraphicType } from "./GraphicType"; /** An opaque representation of a [[RenderGraphic]] created by a [[GraphicDescriptionBuilder]]. * Unlike `RenderGraphic`, a `GraphicDescription` does not allocate any WebGL resources like textures, vertex buffers, etc, so @@ -49,38 +49,42 @@ export interface ComputeGraphicDescriptionChordToleranceArgs { /** Options supplied to [[GraphicDescriptionBuilder.create]]. * @beta */ -export type GraphicDescriptionBuilderOptions = { - /** The type of graphic to create. This influences the default values of some other options like [[generateEdges]] and - * properties like [[GraphicDescriptionBuilder.wantNormals]]. - */ - type: GraphicType; - /** The local-to-world transform in which the builder's geoemtry is to be defined. - * Default: an identity transform. - */ - placement?: Transform; - /** If the graphic is to contain one or more [Feature]($common)s, specifies the initial pickable Id and other options. */ - pickable?: PickableGraphicOptions; - /** Specifies whether edges are generated for surfaces. - * By default, edges are only produced if [[type]] is [[GraphicType.Scene]]. - */ - generateEdges?: boolean; - /** Computes the level of detail in meters for the graphics produced by the builder. */ - computeChordTolerance: (args: ComputeGraphicDescriptionChordToleranceArgs) => number; - /** Context in which the graphic description will be created, obtained from the [[RenderSystem]] on the main thread. */ - context: WorkerGraphicDescriptionContext; -} & ({ - /** If defined, specifies a point about which the graphic will rotate such that it always faces the viewer. - * This can be particular useful for planar regions to create a billboarding effect - e.g., to implement [[Marker]]-like WebGL decorations. - * The graphic's [[placement]] transform is not applied to the point. - * @note This has no effect for graphics displayed in a 2d view. - */ - viewIndependentOrigin?: Point3d; - /** @internal */ - instances?: never; -}/* ) | { +export type GraphicDescriptionBuilderOptions = + & { + /** The type of graphic to create. This influences the default values of some other options like [[generateEdges]] and + * properties like [[GraphicDescriptionBuilder.wantNormals]]. + */ + type: GraphicType; + /** The local-to-world transform in which the builder's geoemtry is to be defined. + * Default: an identity transform. + */ + placement?: Transform; + /** If the graphic is to contain one or more [Feature]($common)s, specifies the initial pickable Id and other options. */ + pickable?: PickableGraphicOptions; + /** Specifies whether edges are generated for surfaces. + * By default, edges are only produced if [[type]] is [[GraphicType.Scene]]. + */ + generateEdges?: boolean; + /** Computes the level of detail in meters for the graphics produced by the builder. */ + computeChordTolerance: (args: ComputeGraphicDescriptionChordToleranceArgs) => number; + /** Context in which the graphic description will be created, obtained from the [[RenderSystem]] on the main thread. */ + context: WorkerGraphicDescriptionContext; + } + & ( + { + /** If defined, specifies a point about which the graphic will rotate such that it always faces the viewer. + * This can be particular useful for planar regions to create a billboarding effect - e.g., to implement [[Marker]]-like WebGL decorations. + * The graphic's [[placement]] transform is not applied to the point. + * @note This has no effect for graphics displayed in a 2d view. + */ + viewIndependentOrigin?: Point3d; + /** @internal */ + instances?: never; + } /* ) | { instances?: InstancedGraphicParams; viewIndependentOrigin?: never; -}*/); +}*/ + ); /** An equivalent of a [[GraphicBuilder]] that is designed for use on a [Worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker). * Unlike [[GraphicBuilder.finish]], which produces a [[RenderGraphic]], [[GraphicDescriptionBuilder.finish]] produces a [[GraphicDescription]]. diff --git a/core/frontend/src/common/render/GraphicDescriptionContext.ts b/core/frontend/src/common/render/GraphicDescriptionContext.ts index c49091472a63..6887813cf55e 100644 --- a/core/frontend/src/common/render/GraphicDescriptionContext.ts +++ b/core/frontend/src/common/render/GraphicDescriptionContext.ts @@ -7,9 +7,9 @@ */ import { TransientIdSequence } from "@itwin/core-bentley"; -import { _implementationProhibited, _textures } from "../internal/Symbols"; -import { WorkerGraphicDescriptionContextImpl } from "../internal/render/GraphicDescriptionContextImpl"; import { Gradient, ImageBuffer, ImageSource, RenderMaterial, RenderTexture, TextureTransparency } from "@itwin/core-common"; +import { WorkerGraphicDescriptionContextImpl } from "../internal/render/GraphicDescriptionContextImpl"; +import { _implementationProhibited, _textures } from "../internal/Symbols"; import { MaterialParams } from "./MaterialParams"; /** Parameters describing a [[RenderTexture]] to be created on a Worker by [[WorkerGraphicDescriptionContext.createTexture]]. @@ -97,4 +97,3 @@ export interface GraphicDescriptionContext { /** @internal */ [_textures]: Map; } - diff --git a/core/frontend/src/common/render/GraphicPrimitive.ts b/core/frontend/src/common/render/GraphicPrimitive.ts index bba372f8c44f..40441224f45a 100644 --- a/core/frontend/src/common/render/GraphicPrimitive.ts +++ b/core/frontend/src/common/render/GraphicPrimitive.ts @@ -165,4 +165,16 @@ export interface GraphicSolidPrimitive { * @public * @extensions */ -export type GraphicPrimitive = GraphicLineString | GraphicLineString2d | GraphicPointString | GraphicPointString2d | GraphicShape | GraphicShape2d | GraphicArc | GraphicArc2d | GraphicPath | GraphicLoop | GraphicPolyface | GraphicSolidPrimitive; +export type GraphicPrimitive = + | GraphicLineString + | GraphicLineString2d + | GraphicPointString + | GraphicPointString2d + | GraphicShape + | GraphicShape2d + | GraphicArc + | GraphicArc2d + | GraphicPath + | GraphicLoop + | GraphicPolyface + | GraphicSolidPrimitive; diff --git a/core/frontend/src/common/render/MaterialParams.ts b/core/frontend/src/common/render/MaterialParams.ts index c2756f405518..2cc6a22e9b04 100644 --- a/core/frontend/src/common/render/MaterialParams.ts +++ b/core/frontend/src/common/render/MaterialParams.ts @@ -104,4 +104,3 @@ export interface MaterialParams { /** Maps [RenderTexture]($common) images to the surfaces to which the material is applied to customize their appearance. */ textureMapping?: MaterialTextureMappingProps; } - diff --git a/core/frontend/src/common/render/RenderInstancesParams.ts b/core/frontend/src/common/render/RenderInstancesParams.ts index 5508f57694cb..414e61c186ba 100644 --- a/core/frontend/src/common/render/RenderInstancesParams.ts +++ b/core/frontend/src/common/render/RenderInstancesParams.ts @@ -7,10 +7,10 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { Feature, LinePixels, RgbColorProps } from "@itwin/core-common"; -import { _implementationProhibited } from "../internal/Symbols"; +import { Transform } from "@itwin/core-geometry"; import { collectRenderInstancesParamsTransferables, createRenderInstancesParamsBuilder } from "../../internal/render/RenderInstancesParamsImpl"; +import { _implementationProhibited } from "../internal/Symbols"; /** Represents a [[RenderInstances]] in a form that supports [structured cloning](https://developer.mozilla.org/en-US/docs/Web/API/structuredClone), * e.g., for transferring between Workers and the main JavaScript thread. diff --git a/core/frontend/src/core-frontend.ts b/core/frontend/src/core-frontend.ts index 1409c7628ef9..70e8abe09486 100644 --- a/core/frontend/src/core-frontend.ts +++ b/core/frontend/src/core-frontend.ts @@ -110,9 +110,9 @@ export * from "./render/webgl/Target"; export type { TxnEntityChange, TxnEntityChangeIterable, - TxnEntityChangeType, TxnEntityChanges, TxnEntityChangesFilterOptions, + TxnEntityChangeType, TxnEntityMetadata, TxnEntityMetadataCriterion, } from "./TxnEntityChanges"; @@ -247,4 +247,4 @@ import "./extension/ExtensionRuntime"; /** * @docs-group-description TileStorage * Class for working with cloud storage using iTwin/object-storage cloud providers -*/ + */ diff --git a/core/frontend/src/extension/ExtensionHost.ts b/core/frontend/src/extension/ExtensionHost.ts index 0d9442449ffb..fde3995c0855 100644 --- a/core/frontend/src/extension/ExtensionHost.ts +++ b/core/frontend/src/extension/ExtensionHost.ts @@ -6,25 +6,37 @@ * @module Extensions */ -import { IModelApp } from "../IModelApp"; -import type { ToolAdmin } from "../tools/ToolAdmin"; import type { AccuSnap } from "../AccuSnap"; -import type { NotificationManager } from "../NotificationManager"; -import type { ViewManager } from "../ViewManager"; import type { ElementLocateManager } from "../ElementLocateManager"; +import { IModelApp } from "../IModelApp"; +import type { NotificationManager } from "../NotificationManager"; import type { RenderSystem } from "../render/RenderSystem"; +import type { ToolAdmin } from "../tools/ToolAdmin"; +import type { ViewManager } from "../ViewManager"; /** * Subset of IModelApp exposed to Extensions * @alpha */ export class ExtensionHost { - protected constructor() { } + protected constructor() {} - public static get toolAdmin(): ToolAdmin { return IModelApp.toolAdmin; } - public static get notifications(): NotificationManager { return IModelApp.notifications; } - public static get viewManager(): ViewManager { return IModelApp.viewManager; } - public static get locateManager(): ElementLocateManager { return IModelApp.locateManager; } // internal ? - public static get accuSnap(): AccuSnap { return IModelApp.accuSnap; } - public static get renderSystem(): RenderSystem { return IModelApp.renderSystem; } // re think this, should be smaller interface + public static get toolAdmin(): ToolAdmin { + return IModelApp.toolAdmin; + } + public static get notifications(): NotificationManager { + return IModelApp.notifications; + } + public static get viewManager(): ViewManager { + return IModelApp.viewManager; + } + public static get locateManager(): ElementLocateManager { + return IModelApp.locateManager; + } // internal ? + public static get accuSnap(): AccuSnap { + return IModelApp.accuSnap; + } + public static get renderSystem(): RenderSystem { + return IModelApp.renderSystem; + } // re think this, should be smaller interface } diff --git a/core/frontend/src/extension/ExtensionRuntime.ts b/core/frontend/src/extension/ExtensionRuntime.ts index 87d7630fc1b6..f258e7378e36 100644 --- a/core/frontend/src/extension/ExtensionRuntime.ts +++ b/core/frontend/src/extension/ExtensionRuntime.ts @@ -18,76 +18,40 @@ if ((globalThis as any)[globalSymbol]) // BEGIN GENERATED CODE import { - // @public enum(s) from @itwin/core-frontend - ACSDisplayOptions, - ACSType, - ActivityMessageEndReason, - BeButton, - BeModifierKeys, - ClipEventType, - ContextRotationId, - CoordSource, - CoordSystem, - CoordinateLockOverrides, - EventHandled, - FlashMode, - FrontendLoggerCategory, - GraphicType, - HitDetailType, - HitGeomType, - HitParentGeomType, - HitPriority, - HitSource, - InputSource, - KeyinParseError, - LocateAction, - LocateFilterStatus, - ManipulatorToolEvent, - MessageBoxIconType, - MessageBoxType, - MessageBoxValue, - OutputMessageAlert, - OutputMessagePriority, - OutputMessageType, - ParseAndRunResult, - SelectionMethod, - SelectionMode, - SelectionProcessing, - SelectionSetEventType, - SnapHeat, - SnapMode, - SnapStatus, - StandardViewId, - StartOrResume, - TileBoundingBoxes, - TileGraphicType, - TileLoadPriority, - TileLoadStatus, - TileTreeLoadStatus, - TileVisibility, - ToolAssistanceImage, - ToolAssistanceInputMethod, - UniformType, - VaryingType, - ViewStatus, // @public real(s) from @itwin/core-frontend AccuDrawHintBuilder, AccuSnap, + // @public enum(s) from @itwin/core-frontend + ACSDisplayOptions, + ACSType, ActivityMessageDetails, + ActivityMessageEndReason, AuxCoordSystem2dState, AuxCoordSystem3dState, AuxCoordSystemSpatialState, AuxCoordSystemState, + BeButton, BeButtonEvent, BeButtonState, + BeModifierKeys, BeTouchEvent, BeWheelEvent, BingElevationProvider, BingLocationProvider, + canvasToImageBuffer, + canvasToResizedCanvasWithBars, CategorySelectorState, ChangeFlags, + ClipEventType, Cluster, + connectViewportFrusta, + connectViewports, + connectViewportViews, ContextRealityModelState, + ContextRotationId, + CoordinateLockOverrides, + CoordSource, + CoordSystem, DecorateContext, Decorations, DisclosedTileTreeSet, @@ -103,29 +67,55 @@ import { EmphasizeElements, EntityState, EventController, + EventHandled, + extractImageSourceDimensions, FeatureSymbology, + FlashMode, FlashSettings, + FrontendLoggerCategory, FrustumAnimator, GeometricModel2dState, GeometricModel3dState, GeometricModelState, + getCompressedJpegFromCanvas, + getImageSourceFormatForMimeType, + getImageSourceMimeType, GlobeAnimator, GraphicAssembler, GraphicBranch, GraphicBuilder, + GraphicType, HiliteSet, HitDetail, + HitDetailType, + HitGeomType, HitList, - IModelConnection, + HitParentGeomType, + HitPriority, + HitSource, IconSprites, + imageBufferToBase64EncodedPng, + imageBufferToCanvas, + imageBufferToPngDataUrl, + imageElementFromImageSource, + imageElementFromUrl, + IModelConnection, InputCollector, + InputSource, InteractiveTool, IntersectDetail, + KeyinParseError, + LocateAction, + LocateFilterStatus, LocateOptions, LocateResponse, + ManipulatorToolEvent, MarginPercent, Marker, MarkerSet, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, ModelSelectorState, ModelState, NotificationHandler, @@ -133,11 +123,18 @@ import { NotifyMessageDetails, OffScreenViewport, OrthographicViewState, + OutputMessageAlert, + OutputMessagePriority, + OutputMessageType, + ParseAndRunResult, ParticleCollectionBuilder, PerModelCategoryVisibility, PhysicalModelState, Pixel, PrimitiveTool, + queryTerrainElevationOffset, + readElementGraphics, + readGltfGraphics, RenderClipVolume, RenderContext, RenderGraphic, @@ -146,41 +143,64 @@ import { Scene, ScreenViewport, SectionDrawingModelState, + SelectionMethod, + SelectionMode, + SelectionProcessing, SelectionSet, + SelectionSetEventType, SheetModelState, SheetViewState, SnapDetail, + SnapHeat, + SnapMode, + SnapStatus, SpatialLocationModelState, SpatialModelState, SpatialViewState, Sprite, SpriteLocation, + StandardViewId, + StartOrResume, + synchronizeViewportFrusta, + synchronizeViewportViews, TentativePoint, Tile, TileAdmin, + TileBoundingBoxes, TileDrawArgs, + TileGraphicType, + TileLoadPriority, + TileLoadStatus, TileRequest, TileRequestChannel, - TileRequestChannelStatistics, TileRequestChannels, + TileRequestChannelStatistics, + Tiles, TileTree, + TileTreeLoadStatus, TileTreeReference, TileUsageMarker, - Tiles, + TileVisibility, Tool, ToolAdmin, ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, ToolSettings, TwoWayViewportFrustumSync, TwoWayViewportSync, + UniformType, + VaryingType, ViewClipClearTool, ViewClipDecoration, ViewClipDecorationProvider, ViewClipTool, ViewCreator2d, ViewCreator3d, + ViewingSpace, ViewManager, ViewManip, + Viewport, ViewPose, ViewPose2d, ViewPose3d, @@ -188,28 +208,8 @@ import { ViewState, ViewState2d, ViewState3d, + ViewStatus, ViewTool, - ViewingSpace, - Viewport, - canvasToImageBuffer, - canvasToResizedCanvasWithBars, - connectViewportFrusta, - connectViewportViews, - connectViewports, - extractImageSourceDimensions, - getCompressedJpegFromCanvas, - getImageSourceFormatForMimeType, - getImageSourceMimeType, - imageBufferToBase64EncodedPng, - imageBufferToCanvas, - imageBufferToPngDataUrl, - imageElementFromImageSource, - imageElementFromUrl, - queryTerrainElevationOffset, - readElementGraphics, - readGltfGraphics, - synchronizeViewportFrusta, - synchronizeViewportViews, } from "../core-frontend"; import { @@ -219,9 +219,13 @@ import { BatchType, BisCodeSpec, BriefcaseIdValue, - ChangeOpCode, ChangedValueState, + ChangeOpCode, ChangesetType, + // @public real(s) from @itwin/core-common + ClipIntersectionStyle, + ColorByName, + ColorDef, CommonLoggerCategory, ECSqlSystemProperty, ECSqlValueType, @@ -230,6 +234,7 @@ import { FillDisplay, FillFlags, FontType, + FrustumPlanes, GeoCoordStatus, GeometryClass, GeometryStreamFlags, @@ -245,6 +250,17 @@ import { Npc, PlanarClipMaskMode, PlanarClipMaskPriority, + QParams2d, + QParams3d, + QPoint2d, + QPoint2dBuffer, + QPoint2dBufferBuilder, + QPoint2dList, + QPoint3d, + QPoint3dBuffer, + QPoint3dBufferBuilder, + QPoint3dList, + Quantization, QueryRowFormat, Rank, RenderMode, @@ -261,22 +277,6 @@ import { ThematicGradientTransparencyMode, TxnAction, TypeOfChange, - // @public real(s) from @itwin/core-common - ClipIntersectionStyle, - ColorByName, - ColorDef, - FrustumPlanes, - QParams2d, - QParams3d, - QPoint2d, - QPoint2dBuffer, - QPoint2dBufferBuilder, - QPoint2dList, - QPoint3d, - QPoint3dBuffer, - QPoint3dBufferBuilder, - QPoint3dList, - Quantization, } from "@itwin/core-common"; const extensionExports = { diff --git a/core/frontend/src/extension/providers/ExtensionLoadScript.ts b/core/frontend/src/extension/providers/ExtensionLoadScript.ts index 515a16372d59..3547a01fd92e 100644 --- a/core/frontend/src/extension/providers/ExtensionLoadScript.ts +++ b/core/frontend/src/extension/providers/ExtensionLoadScript.ts @@ -19,7 +19,7 @@ export async function loadScript(jsUrl: string): Promise { // "Critical dependency: the request of a dependency is an expression" // Because tsc transpiles "await import" to "require" (when compiled to is CommonJS). // So use FunctionConstructor to avoid tsc. - const module = await Function("x","return import(x)")(jsUrl); + const module = await Function("x", "return import(x)")(jsUrl); return execute(module); } diff --git a/core/frontend/src/extension/providers/LocalExtensionProvider.ts b/core/frontend/src/extension/providers/LocalExtensionProvider.ts index afe176265d7f..630fd3a7fcd0 100644 --- a/core/frontend/src/extension/providers/LocalExtensionProvider.ts +++ b/core/frontend/src/extension/providers/LocalExtensionProvider.ts @@ -2,11 +2,7 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { - ExtensionManifest, - ExtensionProvider, - ResolveFunc, -} from "../Extension"; +import type { ExtensionManifest, ExtensionProvider, ResolveFunc } from "../Extension"; /** * Required props for a local extension provider @@ -26,7 +22,7 @@ export interface LocalExtensionProviderProps { * @alpha */ export class LocalExtensionProvider implements ExtensionProvider { - constructor(private readonly _props: LocalExtensionProviderProps) { } + constructor(private readonly _props: LocalExtensionProviderProps) {} /** returns the manifest (package.json) of a local extension */ public async getManifest(): Promise { diff --git a/core/frontend/src/extension/providers/RemoteExtensionProvider.ts b/core/frontend/src/extension/providers/RemoteExtensionProvider.ts index 7226d136043f..7825c5601806 100644 --- a/core/frontend/src/extension/providers/RemoteExtensionProvider.ts +++ b/core/frontend/src/extension/providers/RemoteExtensionProvider.ts @@ -2,11 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { - ExtensionManifest, - ExtensionProvider, -} from "../Extension"; import { request } from "../../request/Request"; +import type { ExtensionManifest, ExtensionProvider } from "../Extension"; import { loadScript } from "./ExtensionLoadScript"; /** @@ -49,5 +46,4 @@ export class RemoteExtensionProvider implements ExtensionProvider { public async getManifest(): Promise { return request(this._props.manifestUrl, "json"); } - } diff --git a/core/frontend/src/internal/render/PrimitiveBuilder.ts b/core/frontend/src/internal/render/PrimitiveBuilder.ts index 1a4d76a45a70..500a7c609b85 100644 --- a/core/frontend/src/internal/render/PrimitiveBuilder.ts +++ b/core/frontend/src/internal/render/PrimitiveBuilder.ts @@ -6,18 +6,18 @@ * @module Rendering */ -import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { assert } from "@itwin/core-bentley"; import { Gradient, PackedFeatureTable, QPoint3dList, RenderTexture } from "@itwin/core-common"; -import { CustomGraphicBuilderOptions, GraphicBuilder, ViewportGraphicBuilderOptions } from "../../render/GraphicBuilder"; -import { RenderGraphic } from "../../render/RenderGraphic"; -import { RenderSystem } from "../../render/RenderSystem"; -import { GeometryOptions } from "../../common/internal/render/Primitives"; +import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { GeometryAccumulator } from "../../common/internal/render/GeometryAccumulator"; import { MeshList } from "../../common/internal/render/MeshPrimitives"; -import { GraphicBranch } from "../../render/GraphicBranch"; -import { assert } from "@itwin/core-bentley"; +import { GeometryOptions } from "../../common/internal/render/Primitives"; import { _accumulator, _implementationProhibited } from "../../common/internal/Symbols"; +import { GraphicBranch } from "../../render/GraphicBranch"; +import { CustomGraphicBuilderOptions, GraphicBuilder, ViewportGraphicBuilderOptions } from "../../render/GraphicBuilder"; import { createGraphicTemplate, GraphicTemplate, GraphicTemplateBatch } from "../../render/GraphicTemplate"; +import { RenderGraphic } from "../../render/RenderGraphic"; +import { RenderSystem } from "../../render/RenderSystem"; import { RenderGeometry } from "./RenderGeometry"; /** @internal */ @@ -69,7 +69,12 @@ export class PrimitiveBuilder extends GraphicBuilder { * Populate a list of Graphic objects from the accumulated Geometry objects. * removed ViewContext */ - public saveToGraphicList(graphics: RenderGraphic[], options: GeometryOptions, tolerance: number, pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined): MeshList | undefined { + public saveToGraphicList( + graphics: RenderGraphic[], + options: GeometryOptions, + tolerance: number, + pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined, + ): MeshList | undefined { const meshes = this[_accumulator].toMeshes(options, tolerance, pickable); if (0 === meshes.length) return undefined; @@ -130,7 +135,12 @@ export class PrimitiveBuilder extends GraphicBuilder { return meshes; } - private saveToTemplate(options: GeometryOptions, tolerance: number, pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined, noDispose: boolean): GraphicTemplate | undefined { + private saveToTemplate( + options: GeometryOptions, + tolerance: number, + pickable: { isVolumeClassifier?: boolean, modelId?: string } | undefined, + noDispose: boolean, + ): GraphicTemplate | undefined { const meshes = this[_accumulator].toMeshes(options, tolerance, pickable); if (0 === meshes.length) return undefined; @@ -147,7 +157,7 @@ export class PrimitiveBuilder extends GraphicBuilder { for (const mesh of meshes) { const verts = mesh.points; - if (!transformOrigin){ + if (!transformOrigin) { if (verts instanceof QPoint3dList) { transformOrigin = verts.params.origin.clone(); verts.params.origin.setZero(); diff --git a/core/frontend/src/internal/render/RenderGeometry.ts b/core/frontend/src/internal/render/RenderGeometry.ts index b33dce30d6e0..5b2875829470 100644 --- a/core/frontend/src/internal/render/RenderGeometry.ts +++ b/core/frontend/src/internal/render/RenderGeometry.ts @@ -7,8 +7,8 @@ */ import { IDisposable } from "@itwin/core-bentley"; -import { RenderMemory } from "../../render/RenderMemory"; import { Range3d } from "@itwin/core-geometry"; +import { RenderMemory } from "../../render/RenderMemory"; /** An opaque representation of geometry allocated by a [[RenderSystem]] to be supplied to [[RenderSystem.createRenderGraphic]]. */ export interface RenderGeometry extends IDisposable, RenderMemory.Consumer { @@ -23,4 +23,3 @@ export interface RenderGeometry extends IDisposable, RenderMemory.Consumer { /** @internal */ computeRange(out?: Range3d): Range3d; } - diff --git a/core/frontend/src/internal/render/RenderInstancesParamsImpl.ts b/core/frontend/src/internal/render/RenderInstancesParamsImpl.ts index 7bff4bd4a8c5..44ffe7b94658 100644 --- a/core/frontend/src/internal/render/RenderInstancesParamsImpl.ts +++ b/core/frontend/src/internal/render/RenderInstancesParamsImpl.ts @@ -7,11 +7,16 @@ */ import { Id64String } from "@itwin/core-bentley"; +import { FeatureTable, PackedFeatureTable } from "@itwin/core-common"; +import { InstancedGraphicPropsBuilder } from "../../common/internal/render/InstancedGraphicPropsBuilder"; import { _implementationProhibited } from "../../common/internal/Symbols"; import { InstancedGraphicProps } from "../../common/render/InstancedGraphicParams"; -import { CreateRenderInstancesParamsBuilderArgs, Instance, RenderInstancesParams, RenderInstancesParamsBuilder } from "../../common/render/RenderInstancesParams"; -import { InstancedGraphicPropsBuilder } from "../../common/internal/render/InstancedGraphicPropsBuilder"; -import { FeatureTable, PackedFeatureTable } from "@itwin/core-common"; +import { + CreateRenderInstancesParamsBuilderArgs, + Instance, + RenderInstancesParams, + RenderInstancesParamsBuilder, +} from "../../common/render/RenderInstancesParams"; /** Intermediate representation of `RenderInstances[_batch]`. */ export interface InstancedFeaturesParams { diff --git a/core/frontend/src/properties/AngleDescription.ts b/core/frontend/src/properties/AngleDescription.ts index f10badc7f876..c24c0407587f 100644 --- a/core/frontend/src/properties/AngleDescription.ts +++ b/core/frontend/src/properties/AngleDescription.ts @@ -24,8 +24,14 @@ export class AngleDescription extends FormattedQuantityDescription { ); } - public get formatterQuantityType(): QuantityType { return QuantityType.Angle; } - public get quantityType(): string { return "Angle"; } + public get formatterQuantityType(): QuantityType { + return QuantityType.Angle; + } + public get quantityType(): string { + return "Angle"; + } - public get parseError(): string { return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseAngle"); } + public get parseError(): string { + return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseAngle"); + } } diff --git a/core/frontend/src/properties/FormattedQuantityDescription.ts b/core/frontend/src/properties/FormattedQuantityDescription.ts index f6824b22dfce..d05ef350f524 100644 --- a/core/frontend/src/properties/FormattedQuantityDescription.ts +++ b/core/frontend/src/properties/FormattedQuantityDescription.ts @@ -6,8 +6,8 @@ * @module Properties */ -import { FormatterSpec, Parser, ParserSpec } from "@itwin/core-quantity"; import { BaseQuantityDescription, ParseResults } from "@itwin/appui-abstract"; +import { FormatterSpec, Parser, ParserSpec } from "@itwin/core-quantity"; import { IModelApp } from "../IModelApp"; import { QuantityType } from "../quantity-formatting/QuantityFormatter"; diff --git a/core/frontend/src/properties/LengthDescription.ts b/core/frontend/src/properties/LengthDescription.ts index 0f1622b3e929..f22a81f09353 100644 --- a/core/frontend/src/properties/LengthDescription.ts +++ b/core/frontend/src/properties/LengthDescription.ts @@ -24,10 +24,16 @@ export class LengthDescription extends FormattedQuantityDescription { ); } - public get formatterQuantityType(): QuantityType { return QuantityType.Length; } - public get quantityType(): string { return "Length"; } + public get formatterQuantityType(): QuantityType { + return QuantityType.Length; + } + public get quantityType(): string { + return "Length"; + } - public get parseError(): string { return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); } + public get parseError(): string { + return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); + } } /** @@ -44,10 +50,16 @@ export class SurveyLengthDescription extends FormattedQuantityDescription { ); } - public get formatterQuantityType(): QuantityType { return QuantityType.LengthSurvey; } - public get quantityType(): string { return "LengthSurvey"; } + public get formatterQuantityType(): QuantityType { + return QuantityType.LengthSurvey; + } + public get quantityType(): string { + return "LengthSurvey"; + } - public get parseError(): string { return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); } + public get parseError(): string { + return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); + } } /** @@ -55,7 +67,6 @@ export class SurveyLengthDescription extends FormattedQuantityDescription { * @beta */ export class EngineeringLengthDescription extends FormattedQuantityDescription { - constructor(name?: string, displayLabel?: string, iconSpec?: string) { const defaultName = "engineeringLength"; super( @@ -65,8 +76,14 @@ export class EngineeringLengthDescription extends FormattedQuantityDescription { ); } - public get formatterQuantityType(): QuantityType { return QuantityType.LengthEngineering; } - public get quantityType(): string { return "LengthEngineering"; } + public get formatterQuantityType(): QuantityType { + return QuantityType.LengthEngineering; + } + public get quantityType(): string { + return "LengthEngineering"; + } - public get parseError(): string { return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); } + public get parseError(): string { + return IModelApp.localization.getLocalizedString("iModelJs:Properties.UnableToParseLength"); + } } diff --git a/core/frontend/src/public/assets/MapLayerSources.json b/core/frontend/src/public/assets/MapLayerSources.json index aea6b80a9dac..8ed2604cca1f 100644 --- a/core/frontend/src/public/assets/MapLayerSources.json +++ b/core/frontend/src/public/assets/MapLayerSources.json @@ -23,4 +23,4 @@ "formatId": "TileURL", "transparentBackground": true } -] \ No newline at end of file +] diff --git a/core/frontend/src/public/locales/en/CoreTools.json b/core/frontend/src/public/locales/en/CoreTools.json index e5f909cc4973..c1ef2daf3b2b 100644 --- a/core/frontend/src/public/locales/en/CoreTools.json +++ b/core/frontend/src/public/locales/en/CoreTools.json @@ -495,4 +495,4 @@ "shiftKey": "Shift", "inputs": "Inputs" } -} \ No newline at end of file +} diff --git a/core/frontend/src/public/locales/en/iModelJs.json b/core/frontend/src/public/locales/en/iModelJs.json index 1ec761547977..171fda66a789 100644 --- a/core/frontend/src/public/locales/en/iModelJs.json +++ b/core/frontend/src/public/locales/en/iModelJs.json @@ -174,4 +174,4 @@ "TooltipInfo": { "Name": "Name:" } -} \ No newline at end of file +} diff --git a/core/frontend/src/quantity-formatting/BaseUnitFormattingSettingsProvider.ts b/core/frontend/src/quantity-formatting/BaseUnitFormattingSettingsProvider.ts index 1f10c099caf7..80210f84f072 100644 --- a/core/frontend/src/quantity-formatting/BaseUnitFormattingSettingsProvider.ts +++ b/core/frontend/src/quantity-formatting/BaseUnitFormattingSettingsProvider.ts @@ -11,8 +11,12 @@ import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { SelectedViewportChangedArgs } from "../ViewManager"; import { - FormattingUnitSystemChangedArgs, OverrideFormatEntry, QuantityFormatOverridesChangedArgs, QuantityFormatter, - QuantityTypeKey, UnitFormattingSettingsProvider, + FormattingUnitSystemChangedArgs, + OverrideFormatEntry, + QuantityFormatOverridesChangedArgs, + QuantityFormatter, + QuantityTypeKey, + UnitFormattingSettingsProvider, } from "./QuantityFormatter"; /** This abstract class reacts to changes in the "active" iModel and updates the [[QuantityFormatter]] overrides and active @@ -42,34 +46,34 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti return !!this._maintainOverridesPerIModel; } - public storeFormatOverrides = async ({typeKey, overrideEntry, unitSystem}: QuantityFormatOverridesChangedArgs) => { + public storeFormatOverrides = async ({ typeKey, overrideEntry, unitSystem }: QuantityFormatOverridesChangedArgs) => { if (undefined === overrideEntry) { // remove all overrides for quantity type if (undefined === unitSystem) { - await this.remove (typeKey); + await this.remove(typeKey); return; - }else { + } else { // remove only system specific overrides for quantity type - const storedJson = await this.retrieve (typeKey); + const storedJson = await this.retrieve(typeKey); if (storedJson) { delete storedJson[unitSystem]; if (Object.keys(storedJson).length) { - await this.store (typeKey, storedJson); + await this.store(typeKey, storedJson); } else { - await this.remove (typeKey); + await this.remove(typeKey); } } } } else { // setting a new override or set of overrides - const storedJson = await this.retrieve (typeKey); - const updatedFormat = {...storedJson, ...overrideEntry}; - await this.store (typeKey, updatedFormat); + const storedJson = await this.retrieve(typeKey); + const updatedFormat = { ...storedJson, ...overrideEntry }; + await this.store(typeKey, updatedFormat); } }; /** save UnitSystem for active iModel */ - public storeUnitSystemSetting = async ({system}: FormattingUnitSystemChangedArgs) => { + public storeUnitSystemSetting = async ({ system }: FormattingUnitSystemChangedArgs) => { await this.storeUnitSystemKey(system); }; @@ -81,17 +85,17 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti if (this._maintainOverridesPerIModel) this._imodelConnection = imodel; const overrideFormatProps = await this.buildQuantityFormatOverridesMap(); - const unitSystemKey = await this.retrieveUnitSystem (this._quantityFormatter.activeUnitSystem); + const unitSystemKey = await this.retrieveUnitSystem(this._quantityFormatter.activeUnitSystem); await this._quantityFormatter.reinitializeFormatAndParsingsMaps(overrideFormatProps, unitSystemKey, true, true); }; private handleIModelOpen = async (imodel: IModelConnection) => { - await this.applyQuantityFormattingSettingsForIModel (imodel); + await this.applyQuantityFormattingSettingsForIModel(imodel); }; private handleViewportChanged = async (args: SelectedViewportChangedArgs) => { - if(args.current?.iModel && (args.current?.iModel?.iModelId !== this.imodelConnection?.iModelId)) { - await this.applyQuantityFormattingSettingsForIModel (args.current?.iModel); + if (args.current?.iModel && (args.current?.iModel?.iModelId !== this.imodelConnection?.iModelId)) { + await this.applyQuantityFormattingSettingsForIModel(args.current?.iModel); } }; @@ -100,7 +104,7 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti }; protected get imodelConnection() { - return this._imodelConnection; + return this._imodelConnection; } /** function to convert from serialized JSON format for Quantity Type overrides to build a map compatible with QuantityManager */ @@ -112,10 +116,10 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti const quantityTypeDef = this._quantityFormatter.quantityTypesRegistry.get(quantityTypeKey); if (quantityTypeDef) { const typeKey = quantityTypeDef.key; - const overrideEntry = await this.retrieve (typeKey); + const overrideEntry = await this.retrieve(typeKey); if (overrideEntry) { // extract overrides and insert into appropriate override map entry - Object.keys(overrideEntry).forEach ((systemKey) => { + Object.keys(overrideEntry).forEach((systemKey) => { const unitSystemKey = systemKey as UnitSystemKey; const props = overrideEntry[unitSystemKey]; if (props) { @@ -138,7 +142,7 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti public abstract store(quantityTypeKey: QuantityTypeKey, overrideProps: OverrideFormatEntry): Promise; /** Retrieves serialized JSON object containing format overrides for a specific quantity type. */ - public abstract retrieve(quantityTypeKey: QuantityTypeKey): Promise; + public abstract retrieve(quantityTypeKey: QuantityTypeKey): Promise; /** Removes the override formats for a specific quantity type. */ public abstract remove(quantityTypeKey: QuantityTypeKey): Promise; @@ -149,4 +153,3 @@ export abstract class BaseUnitFormattingSettingsProvider implements UnitFormatti /** Store the active unit system typically for the "active" iModelConnection. */ public abstract storeUnitSystemKey(unitSystemKey: UnitSystemKey): Promise; } - diff --git a/core/frontend/src/quantity-formatting/BasicUnitsProvider.ts b/core/frontend/src/quantity-formatting/BasicUnitsProvider.ts index a1299f7c617d..05cd317dfaec 100644 --- a/core/frontend/src/quantity-formatting/BasicUnitsProvider.ts +++ b/core/frontend/src/quantity-formatting/BasicUnitsProvider.ts @@ -6,9 +6,7 @@ * @module QuantityFormatting */ -import { - BadUnit, BasicUnit, UnitConversionProps, UnitProps, UnitsProvider, -} from "@itwin/core-quantity"; +import { BadUnit, BasicUnit, UnitConversionProps, UnitProps, UnitsProvider } from "@itwin/core-quantity"; import { UnitNameKey } from "./QuantityFormatter"; import { UNIT_EXTRA_DATA } from "./UnitsData"; @@ -18,7 +16,6 @@ import { UNIT_EXTRA_DATA } from "./UnitsData"; * @internal */ export class BasicUnitsProvider implements UnitsProvider { - /** Find a unit given the unitLabel. */ public async findUnit(unitLabel: string, schemaName?: string, phenomenon?: string, unitSystem?: string): Promise { const labelToFind = unitLabel.toLowerCase(); @@ -148,48 +145,270 @@ export function getDefaultAlternateUnitLabels() { // Set of supported units - this information will come from Schema-based units once the EC package is ready to provide this information. const UNIT_DATA: UnitDefinition[] = [ // Angles ( base unit radian ) - { name: "Units.RAD", phenomenon: "Units.ANGLE", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "rad" }, + { + name: "Units.RAD", + phenomenon: "Units.ANGLE", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "rad", + }, // 1 rad = 180.0/PI ° - { name: "Units.ARC_DEG", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 180.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "°" }, - { name: "Units.ARC_MINUTE", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 10800.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "'" }, - { name: "Units.ARC_SECOND", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 648000.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: '"' }, - { name: "Units.GRAD", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 200, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "grad" }, + { + name: "Units.ARC_DEG", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 180.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "°", + }, + { + name: "Units.ARC_MINUTE", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 10800.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "'", + }, + { + name: "Units.ARC_SECOND", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 648000.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: '"', + }, + { + name: "Units.GRAD", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 200, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "grad", + }, // Time ( base unit second ) { name: "Units.S", phenomenon: "Units.TIME", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "s" }, - { name: "Units.MIN", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 60.0, offset: 0.0 }, displayLabel: "min" }, - { name: "Units.HR", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 3600.0, offset: 0.0 }, displayLabel: "h"}, - { name: "Units.DAY", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 86400.0, offset: 0.0 }, displayLabel: "days" }, - { name: "Units.WEEK", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 604800.0, offset: 0.0 }, displayLabel: "weeks" }, + { + name: "Units.MIN", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 60.0, offset: 0.0 }, + displayLabel: "min", + }, + { + name: "Units.HR", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 3600.0, offset: 0.0 }, + displayLabel: "h", + }, + { + name: "Units.DAY", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 86400.0, offset: 0.0 }, + displayLabel: "days", + }, + { + name: "Units.WEEK", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 604800.0, offset: 0.0 }, + displayLabel: "weeks", + }, // 1 sec = 1/31536000.0 yr - { name: "Units.YR", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 31536000.0, offset: 0.0 }, displayLabel: "years" }, + { + name: "Units.YR", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 31536000.0, offset: 0.0 }, + displayLabel: "years", + }, // conversion => specified unit to base unit of m - { name: "Units.M", phenomenon: "Units.LENGTH", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m" }, - { name: "Units.MM", phenomenon: "Units.LENGTH", system: "Units.METRIC", conversion: { numerator: 1000.0, denominator: 1.0, offset: 0.0 }, displayLabel: "mm" }, - { name: "Units.CM", phenomenon: "Units.LENGTH", system: "Units.METRIC", conversion: { numerator: 100.0, denominator: 1.0, offset: 0.0 }, displayLabel: "cm" }, - { name: "Units.DM", phenomenon: "Units.LENGTH", system: "Units.METRIC", conversion: { numerator: 10.0, denominator: 1.0, offset: 0.0 }, displayLabel: "dm" }, - { name: "Units.KM", phenomenon: "Units.LENGTH", system: "Units.METRIC", conversion: { numerator: 1.0, denominator: 1000.0, offset: 0.0 }, displayLabel: "km" }, - { name: "Units.UM", phenomenon: "Units.LENGTH", system: "Units.METRIC", conversion: { numerator: 1000000.0, denominator: 1.0, offset: 0.0 }, displayLabel: "µm" }, - { name: "Units.MILLIINCH", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "mil" }, - { name: "Units.MICROINCH", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000000.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "µin" }, - { name: "Units.MILLIFOOT", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000.0, denominator: 0.3048, offset: 0.0 }, displayLabel: "mft" }, - { name: "Units.IN", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "in" }, - { name: "Units.FT", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.3048, offset: 0.0 }, displayLabel: "ft" }, - { name: "Units.CHAIN", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 66.0 * 0.3048, offset: 0.0 }, displayLabel: "chain" }, - { name: "Units.YRD", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.9144, offset: 0.0 }, displayLabel: "yd" }, - { name: "Units.MILE", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 1609.344, offset: 0.0 }, displayLabel: "mi" }, - { name: "Units.US_SURVEY_FT", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 1200.0, offset: 0.0 }, displayLabel: "ft (US Survey)" }, - { name: "Units.US_SURVEY_YRD", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 3.0 * 1200.0, offset: 0.0 }, displayLabel: "yrd (US Survey)" }, - { name: "Units.US_SURVEY_IN", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 100.0, offset: 0.0 }, displayLabel: "in (US Survey)" }, - { name: "Units.US_SURVEY_MILE", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 5280.0 * 1200.0, offset: 0.0 }, displayLabel: "mi (US Survey)" }, - { name: "Units.US_SURVEY_CHAIN", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 1.0, denominator: 20.11684, offset: 0.0 }, displayLabel: "chain (US Survey)" }, + { + name: "Units.M", + phenomenon: "Units.LENGTH", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m", + }, + { + name: "Units.MM", + phenomenon: "Units.LENGTH", + system: "Units.METRIC", + conversion: { numerator: 1000.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "mm", + }, + { + name: "Units.CM", + phenomenon: "Units.LENGTH", + system: "Units.METRIC", + conversion: { numerator: 100.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "cm", + }, + { + name: "Units.DM", + phenomenon: "Units.LENGTH", + system: "Units.METRIC", + conversion: { numerator: 10.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "dm", + }, + { + name: "Units.KM", + phenomenon: "Units.LENGTH", + system: "Units.METRIC", + conversion: { numerator: 1.0, denominator: 1000.0, offset: 0.0 }, + displayLabel: "km", + }, + { + name: "Units.UM", + phenomenon: "Units.LENGTH", + system: "Units.METRIC", + conversion: { numerator: 1000000.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "µm", + }, + { + name: "Units.MILLIINCH", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "mil", + }, + { + name: "Units.MICROINCH", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000000.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "µin", + }, + { + name: "Units.MILLIFOOT", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000.0, denominator: 0.3048, offset: 0.0 }, + displayLabel: "mft", + }, + { + name: "Units.IN", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "in", + }, + { + name: "Units.FT", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.3048, offset: 0.0 }, + displayLabel: "ft", + }, + { + name: "Units.CHAIN", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 66.0 * 0.3048, offset: 0.0 }, + displayLabel: "chain", + }, + { + name: "Units.YRD", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.9144, offset: 0.0 }, + displayLabel: "yd", + }, + { + name: "Units.MILE", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 1609.344, offset: 0.0 }, + displayLabel: "mi", + }, + { + name: "Units.US_SURVEY_FT", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 1200.0, offset: 0.0 }, + displayLabel: "ft (US Survey)", + }, + { + name: "Units.US_SURVEY_YRD", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 3.0 * 1200.0, offset: 0.0 }, + displayLabel: "yrd (US Survey)", + }, + { + name: "Units.US_SURVEY_IN", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 100.0, offset: 0.0 }, + displayLabel: "in (US Survey)", + }, + { + name: "Units.US_SURVEY_MILE", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 5280.0 * 1200.0, offset: 0.0 }, + displayLabel: "mi (US Survey)", + }, + { + name: "Units.US_SURVEY_CHAIN", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 1.0, denominator: 20.11684, offset: 0.0 }, + displayLabel: "chain (US Survey)", + }, // conversion => specified unit to base unit of m² - { name: "Units.SQ_FT", phenomenon: "Units.AREA", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: .09290304, offset: 0.0 }, displayLabel: "ft²" }, - { name: "Units.SQ_US_SURVEY_FT", phenomenon: "Units.AREA", system: "Units.USCUSTOM", conversion: { numerator: 15499969.0, denominator: 1440000, offset: 0.0 }, displayLabel: "ft² (US Survey)" }, - { name: "Units.SQ_M", phenomenon: "Units.AREA", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m²" }, - { name: "Units.SQ_KM", phenomenon: "Units.AREA", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1000000.0, offset: 0.0 }, displayLabel: "km²" }, + { + name: "Units.SQ_FT", + phenomenon: "Units.AREA", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: .09290304, offset: 0.0 }, + displayLabel: "ft²", + }, + { + name: "Units.SQ_US_SURVEY_FT", + phenomenon: "Units.AREA", + system: "Units.USCUSTOM", + conversion: { numerator: 15499969.0, denominator: 1440000, offset: 0.0 }, + displayLabel: "ft² (US Survey)", + }, + { + name: "Units.SQ_M", + phenomenon: "Units.AREA", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m²", + }, + { + name: "Units.SQ_KM", + phenomenon: "Units.AREA", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1000000.0, offset: 0.0 }, + displayLabel: "km²", + }, // conversion => specified unit to base unit m³ - { name: "Units.CUB_FT", phenomenon: "Units.VOLUME", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.028316847, offset: 0.0 }, displayLabel: "ft³" }, - { name: "Units.CUB_US_SURVEY_FT", phenomenon: "Units.VOLUME", system: "Units.USSURVEY", conversion: { numerator: 1, denominator: 0.0283170164937591, offset: 0.0 }, displayLabel: "ft³" }, - { name: "Units.CUB_YRD", phenomenon: "Units.VOLUME", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.76455486, offset: 0.0 }, displayLabel: "yd³" }, - { name: "Units.CUB_M", phenomenon: "Units.VOLUME", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m³" }, + { + name: "Units.CUB_FT", + phenomenon: "Units.VOLUME", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.028316847, offset: 0.0 }, + displayLabel: "ft³", + }, + { + name: "Units.CUB_US_SURVEY_FT", + phenomenon: "Units.VOLUME", + system: "Units.USSURVEY", + conversion: { numerator: 1, denominator: 0.0283170164937591, offset: 0.0 }, + displayLabel: "ft³", + }, + { + name: "Units.CUB_YRD", + phenomenon: "Units.VOLUME", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.76455486, offset: 0.0 }, + displayLabel: "yd³", + }, + { + name: "Units.CUB_M", + phenomenon: "Units.VOLUME", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m³", + }, ]; diff --git a/core/frontend/src/quantity-formatting/LocalUnitFormatProvider.ts b/core/frontend/src/quantity-formatting/LocalUnitFormatProvider.ts index a5f0377b9dfe..f2b29e129cf4 100644 --- a/core/frontend/src/quantity-formatting/LocalUnitFormatProvider.ts +++ b/core/frontend/src/quantity-formatting/LocalUnitFormatProvider.ts @@ -7,8 +7,8 @@ */ import { UnitSystemKey } from "@itwin/core-quantity"; -import { OverrideFormatEntry, QuantityFormatter, QuantityTypeKey } from "./QuantityFormatter"; import { BaseUnitFormattingSettingsProvider } from "./BaseUnitFormattingSettingsProvider"; +import { OverrideFormatEntry, QuantityFormatter, QuantityTypeKey } from "./QuantityFormatter"; /** Implementation of BaseUnitFormattingSettingsProvider that stores and retrieves data in local storage. * @beta @@ -17,7 +17,7 @@ export class LocalUnitFormatProvider extends BaseUnitFormattingSettingsProvider /** If `maintainOverridesPerIModel` is true, the base class will set up listeners to monitor active iModel * changes so the overrides for the QuantityFormatter properly match the overrides set up by the user. */ constructor(quantityFormatter: QuantityFormatter, maintainOverridesPerIModel?: boolean) { - super (quantityFormatter, maintainOverridesPerIModel); + super(quantityFormatter, maintainOverridesPerIModel); } private buildUnitSystemKey() { @@ -27,7 +27,7 @@ export class LocalUnitFormatProvider extends BaseUnitFormattingSettingsProvider } public async retrieveUnitSystem(defaultKey: UnitSystemKey): Promise { - const readUnitSystem = localStorage.getItem (this.buildUnitSystemKey()); + const readUnitSystem = localStorage.getItem(this.buildUnitSystemKey()); if (readUnitSystem && readUnitSystem.length) { return readUnitSystem as UnitSystemKey; } @@ -37,7 +37,7 @@ export class LocalUnitFormatProvider extends BaseUnitFormattingSettingsProvider public async storeUnitSystemKey(unitSystemKey: UnitSystemKey): Promise { try { - localStorage.setItem (this.buildUnitSystemKey(), unitSystemKey); + localStorage.setItem(this.buildUnitSystemKey(), unitSystemKey); return true; } catch (_e) { return false; @@ -52,15 +52,15 @@ export class LocalUnitFormatProvider extends BaseUnitFormattingSettingsProvider public async store(quantityTypeKey: QuantityTypeKey, overrideProps: OverrideFormatEntry): Promise { try { - localStorage.setItem (this.buildOverridesKey(quantityTypeKey), JSON.stringify(overrideProps)); + localStorage.setItem(this.buildOverridesKey(quantityTypeKey), JSON.stringify(overrideProps)); return true; } catch (_e) { return false; } } - public async retrieve(quantityTypeKey: QuantityTypeKey): Promise { - const storedFormat = localStorage.getItem (this.buildOverridesKey(quantityTypeKey)); + public async retrieve(quantityTypeKey: QuantityTypeKey): Promise { + const storedFormat = localStorage.getItem(this.buildOverridesKey(quantityTypeKey)); if (storedFormat) { return JSON.parse(storedFormat); } @@ -71,7 +71,7 @@ export class LocalUnitFormatProvider extends BaseUnitFormattingSettingsProvider public async remove(quantityTypeKey: QuantityTypeKey): Promise { const key = this.buildOverridesKey(quantityTypeKey); if (localStorage.getItem(key)) { - localStorage.removeItem (key); + localStorage.removeItem(key); return true; } diff --git a/core/frontend/src/quantity-formatting/QuantityFormatter.ts b/core/frontend/src/quantity-formatting/QuantityFormatter.ts index 5bf73d050d5a..e5e7efd94675 100644 --- a/core/frontend/src/quantity-formatting/QuantityFormatter.ts +++ b/core/frontend/src/quantity-formatting/QuantityFormatter.ts @@ -8,8 +8,17 @@ import { BentleyError, BeUiEvent, Logger } from "@itwin/core-bentley"; import { - AlternateUnitLabelsProvider, Format, FormatProps, FormatterSpec, ParseError, ParserSpec, QuantityParseResult, - UnitConversionProps, UnitProps, UnitsProvider, UnitSystemKey, + AlternateUnitLabelsProvider, + Format, + FormatProps, + FormatterSpec, + ParseError, + ParserSpec, + QuantityParseResult, + UnitConversionProps, + UnitProps, + UnitsProvider, + UnitSystemKey, } from "@itwin/core-quantity"; import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; import { IModelApp } from "../IModelApp"; @@ -41,7 +50,7 @@ export enum QuantityType { /** LengthSurvey is a distance value stored in meters. Typically formatted to display in meters or US Survey Feet based on active unit system.. */ LengthSurvey = 8, /** LengthEngineering is a distance value stored in meters. Typically formatted to display either meters or feet based on active unit system. */ - LengthEngineering = 9 + LengthEngineering = 9, } /** @@ -123,7 +132,11 @@ export interface QuantityTypeDefinition { /** Async function to generate a [FormatterSpec]$(core-quantity) that will be called to format values.*/ generateFormatterSpec: (formatProps: FormatProps, unitsProvider: UnitsProvider) => Promise; /** Async function to generate a [ParserSpec]$(core-quantity) that will be called to parse a string into a quantity value.*/ - generateParserSpec: (formatProps: FormatProps, unitsProvider: UnitsProvider, alternateUnitLabelsProvider?: AlternateUnitLabelsProvider) => Promise; + generateParserSpec: ( + formatProps: FormatProps, + unitsProvider: UnitsProvider, + alternateUnitLabelsProvider?: AlternateUnitLabelsProvider, + ) => Promise; } /** CustomQuantityTypeDefinition interface is used to define a Custom quantity type that can be registered with the [[QuantityFormatter]]. @@ -145,7 +158,7 @@ export interface CustomQuantityTypeDefinition extends QuantityTypeDefinition { /** CustomQuantityTypeDefinition type guard. * @public -*/ + */ export function isCustomQuantityTypeDefinition(item: QuantityTypeDefinition): item is CustomQuantityTypeDefinition { return !!(item as CustomQuantityTypeDefinition).isCompatibleFormatProps; } @@ -160,7 +173,9 @@ class StandardQuantityTypeDefinition implements QuantityTypeDefinition { this._key = getQuantityTypeKey(type); } - public get key(): string { return this._key; } + public get key(): string { + return this._key; + } public get label(): string { if (!this._label) { @@ -330,8 +345,8 @@ export class QuantityFormatter implements UnitsProvider { } /** Called after the active unit system is changed. - * The system will report the UnitSystemKey/name of the the system that was activated. - */ + * The system will report the UnitSystemKey/name of the the system that was activated. + */ public readonly onActiveFormattingUnitSystemChanged = new BeUiEvent(); /** Called when the format of a QuantityType is overriden or the override is cleared. The string returned will @@ -369,51 +384,87 @@ export class QuantityFormatter implements UnitsProvider { protected async initializeQuantityTypesRegistry() { // QuantityType.Length const lengthUnit = await this.findUnitByName("Units.M"); - const lengthDefinition = new StandardQuantityTypeDefinition(QuantityType.Length, lengthUnit, - "iModelJs:QuantityType.Length.label", "iModelJs:QuantityType.Length.description"); + const lengthDefinition = new StandardQuantityTypeDefinition( + QuantityType.Length, + lengthUnit, + "iModelJs:QuantityType.Length.label", + "iModelJs:QuantityType.Length.description", + ); this._quantityTypeRegistry.set(lengthDefinition.key, lengthDefinition); // QuantityType.LengthEngineering - const lengthEngineeringDefinition = new StandardQuantityTypeDefinition(QuantityType.LengthEngineering, lengthUnit, - "iModelJs:QuantityType.LengthEngineering.label", "iModelJs:QuantityType.LengthEngineering.description"); + const lengthEngineeringDefinition = new StandardQuantityTypeDefinition( + QuantityType.LengthEngineering, + lengthUnit, + "iModelJs:QuantityType.LengthEngineering.label", + "iModelJs:QuantityType.LengthEngineering.description", + ); this._quantityTypeRegistry.set(lengthEngineeringDefinition.key, lengthEngineeringDefinition); // QuantityType.Coordinate - const coordinateDefinition = new StandardQuantityTypeDefinition(QuantityType.Coordinate, lengthUnit, - "iModelJs:QuantityType.Coordinate.label", "iModelJs:QuantityType.Coordinate.description"); + const coordinateDefinition = new StandardQuantityTypeDefinition( + QuantityType.Coordinate, + lengthUnit, + "iModelJs:QuantityType.Coordinate.label", + "iModelJs:QuantityType.Coordinate.description", + ); this._quantityTypeRegistry.set(coordinateDefinition.key, coordinateDefinition); // QuantityType.Stationing - const stationingDefinition = new StandardQuantityTypeDefinition(QuantityType.Stationing, lengthUnit, - "iModelJs:QuantityType.Stationing.label", "iModelJs:QuantityType.Stationing.description"); + const stationingDefinition = new StandardQuantityTypeDefinition( + QuantityType.Stationing, + lengthUnit, + "iModelJs:QuantityType.Stationing.label", + "iModelJs:QuantityType.Stationing.description", + ); this._quantityTypeRegistry.set(stationingDefinition.key, stationingDefinition); // QuantityType.LengthSurvey - const lengthSurveyDefinition = new StandardQuantityTypeDefinition(QuantityType.LengthSurvey, lengthUnit, - "iModelJs:QuantityType.LengthSurvey.label", "iModelJs:QuantityType.LengthSurvey.description"); + const lengthSurveyDefinition = new StandardQuantityTypeDefinition( + QuantityType.LengthSurvey, + lengthUnit, + "iModelJs:QuantityType.LengthSurvey.label", + "iModelJs:QuantityType.LengthSurvey.description", + ); this._quantityTypeRegistry.set(lengthSurveyDefinition.key, lengthSurveyDefinition); // QuantityType.Angle const radUnit = await this.findUnitByName("Units.RAD"); - const angleDefinition = new StandardQuantityTypeDefinition(QuantityType.Angle, radUnit, - "iModelJs:QuantityType.Angle.label", "iModelJs:QuantityType.Angle.description"); + const angleDefinition = new StandardQuantityTypeDefinition( + QuantityType.Angle, + radUnit, + "iModelJs:QuantityType.Angle.label", + "iModelJs:QuantityType.Angle.description", + ); this._quantityTypeRegistry.set(angleDefinition.key, angleDefinition); // QuantityType.LatLong - const latLongDefinition = new StandardQuantityTypeDefinition(QuantityType.LatLong, radUnit, - "iModelJs:QuantityType.LatLong.label", "iModelJs:QuantityType.LatLong.description"); + const latLongDefinition = new StandardQuantityTypeDefinition( + QuantityType.LatLong, + radUnit, + "iModelJs:QuantityType.LatLong.label", + "iModelJs:QuantityType.LatLong.description", + ); this._quantityTypeRegistry.set(latLongDefinition.key, latLongDefinition); // QuantityType.Area const sqMetersUnit = await this.findUnitByName("Units.SQ_M"); - const areaDefinition = new StandardQuantityTypeDefinition(QuantityType.Area, sqMetersUnit, - "iModelJs:QuantityType.Area.label", "iModelJs:QuantityType.Area.description"); + const areaDefinition = new StandardQuantityTypeDefinition( + QuantityType.Area, + sqMetersUnit, + "iModelJs:QuantityType.Area.label", + "iModelJs:QuantityType.Area.description", + ); this._quantityTypeRegistry.set(areaDefinition.key, areaDefinition); // QuantityType.Volume const cubicMetersUnit = await this.findUnitByName("Units.CUB_M"); - const volumeDefinition = new StandardQuantityTypeDefinition(QuantityType.Volume, cubicMetersUnit, - "iModelJs:QuantityType.Volume.label", "iModelJs:QuantityType.Volume.description"); + const volumeDefinition = new StandardQuantityTypeDefinition( + QuantityType.Volume, + cubicMetersUnit, + "iModelJs:QuantityType.Volume.label", + "iModelJs:QuantityType.Volume.description", + ); this._quantityTypeRegistry.set(volumeDefinition.key, volumeDefinition); } @@ -436,7 +487,11 @@ export class QuantityFormatter implements UnitsProvider { } } - private getFormatPropsByQuantityTypeEntryAndSystem(quantityEntry: QuantityTypeDefinition, requestedSystem: UnitSystemKey, ignoreOverrides?: boolean): FormatProps { + private getFormatPropsByQuantityTypeEntryAndSystem( + quantityEntry: QuantityTypeDefinition, + requestedSystem: UnitSystemKey, + ignoreOverrides?: boolean, + ): FormatProps { if (!ignoreOverrides) { const overrideProps = this.getOverrideFormatPropsByQuantityType(quantityEntry.key, requestedSystem); if (overrideProps) @@ -554,9 +609,12 @@ export class QuantityFormatter implements UnitsProvider { try { // force all cached data to be reinitialized await IModelApp.quantityFormatter.onInitialized(); - } catch(err) { + } catch (err) { Logger.logWarning(`${FrontendLoggerCategory.Package}.quantityFormatter`, BentleyError.getErrorMessage(err), BentleyError.getErrorMetadata(err)); - Logger.logWarning(`${FrontendLoggerCategory.Package}.quantityFormatter`, "An exception occurred initializing the iModelApp.quantityFormatter with the given UnitsProvider. Defaulting back to the internal units provider."); + Logger.logWarning( + `${FrontendLoggerCategory.Package}.quantityFormatter`, + "An exception occurred initializing the iModelApp.quantityFormatter with the given UnitsProvider. Defaulting back to the internal units provider.", + ); // If there is a problem initializing with the given provider, default back to the internal provider await IModelApp.quantityFormatter.resetToUseInternalUnitsProvider(); return; @@ -598,8 +656,12 @@ export class QuantityFormatter implements UnitsProvider { * startDefaultTool - set to true to start the Default to instead of leaving any active tool pointing to cached unit data that is no longer valid * @public */ - public async reinitializeFormatAndParsingsMaps(overrideFormatPropsByUnitSystem: Map>, - unitSystemKey?: UnitSystemKey, fireUnitSystemChanged?: boolean, startDefaultTool?: boolean): Promise { + public async reinitializeFormatAndParsingsMaps( + overrideFormatPropsByUnitSystem: Map>, + unitSystemKey?: UnitSystemKey, + fireUnitSystemChanged?: boolean, + startDefaultTool?: boolean, + ): Promise { this._overrideFormatPropsByUnitSystem.clear(); if (overrideFormatPropsByUnitSystem.size) { this._overrideFormatPropsByUnitSystem = overrideFormatPropsByUnitSystem; @@ -633,7 +695,9 @@ export class QuantityFormatter implements UnitsProvider { } /** Retrieve the active [[UnitSystemKey]] which is used to determine what formats are to be used to display quantities */ - public get activeUnitSystem(): UnitSystemKey { return this._activeUnitSystem; } + public get activeUnitSystem(): UnitSystemKey { + return this._activeUnitSystem; + } /** Clear any formatting override for specified quantity type, but only for the "active" Unit System. */ public async clearOverrideFormats(type: QuantityTypeArg) { @@ -890,7 +954,7 @@ export class QuantityFormatter implements UnitsProvider { // ======================================================================================================================================== const DEFAULT_FORMATKEY_BY_UNIT_SYSTEM = [ { - system: "metric", // PresentationUnitSystem.Metric, + system: "metric", // PresentationUnitSystem.Metric, entries: [ { type: getQuantityTypeKey(QuantityType.Length), formatKey: "[units:length]meter4" }, { type: getQuantityTypeKey(QuantityType.Angle), formatKey: "[units:angle]degree2" }, @@ -918,7 +982,7 @@ const DEFAULT_FORMATKEY_BY_UNIT_SYSTEM = [ ], }, { - system: "usCustomary", // PresentationUnitSystem.UsCustomary + system: "usCustomary", // PresentationUnitSystem.UsCustomary entries: [ { type: getQuantityTypeKey(QuantityType.Length), formatKey: "[units:length]fi8" }, { type: getQuantityTypeKey(QuantityType.Angle), formatKey: "[units:angle]dms2" }, @@ -932,7 +996,7 @@ const DEFAULT_FORMATKEY_BY_UNIT_SYSTEM = [ ], }, { - system: "usSurvey", // PresentationUnitSystem.UsSurvey + system: "usSurvey", // PresentationUnitSystem.UsSurvey entries: [ { type: getQuantityTypeKey(QuantityType.Length), formatKey: "[units:length]f-survey-4" }, { type: getQuantityTypeKey(QuantityType.Angle), formatKey: "[units:angle]dms2" }, @@ -1020,7 +1084,7 @@ const DEFAULT_FORMATPROPS: UniqueFormatsProps[] = [ composite: { includeZero: true, spacer: "-", - units: [{ label: "'", name: "Units.FT" }, { label: "\"", name: "Units.IN" }], + units: [{ label: "'", name: "Units.FT" }, { label: '"', name: "Units.IN" }], }, formatTraits: ["keepSingleZero", "showUnitLabel"], precision: 8, @@ -1139,7 +1203,7 @@ const DEFAULT_FORMATPROPS: UniqueFormatsProps[] = [ composite: { includeZero: true, spacer: "", - units: [{ label: "°", name: "Units.ARC_DEG" }, { label: "'", name: "Units.ARC_MINUTE" }, { label: "\"", name: "Units.ARC_SECOND" }], + units: [{ label: "°", name: "Units.ARC_DEG" }, { label: "'", name: "Units.ARC_MINUTE" }, { label: '"', name: "Units.ARC_SECOND" }], }, formatTraits: ["keepSingleZero", "showUnitLabel"], precision: 4, @@ -1154,7 +1218,7 @@ const DEFAULT_FORMATPROPS: UniqueFormatsProps[] = [ composite: { includeZero: true, spacer: "", - units: [{ label: "°", name: "Units.ARC_DEG" }, { label: "'", name: "Units.ARC_MINUTE" }, { label: "\"", name: "Units.ARC_SECOND" }], + units: [{ label: "°", name: "Units.ARC_DEG" }, { label: "'", name: "Units.ARC_MINUTE" }, { label: '"', name: "Units.ARC_SECOND" }], }, formatTraits: ["keepSingleZero", "showUnitLabel"], precision: 2, diff --git a/core/frontend/src/quantity-formatting/QuantityTypesEditorSpecs.ts b/core/frontend/src/quantity-formatting/QuantityTypesEditorSpecs.ts index 4b4e37186b04..2d34964d0026 100644 --- a/core/frontend/src/quantity-formatting/QuantityTypesEditorSpecs.ts +++ b/core/frontend/src/quantity-formatting/QuantityTypesEditorSpecs.ts @@ -6,9 +6,7 @@ * @module QuantityFormatting */ -import { - FormatProps, -} from "@itwin/core-quantity"; +import { FormatProps } from "@itwin/core-quantity"; /** Properties that define an EditorSpec for editing a custom formatting property that is stored in the "custom" property in the FormatProps. * The editor controls will be automatically generated in the UI and are limited to a checkbox to set a boolean value, a text dropdown/select diff --git a/core/frontend/src/quantity-formatting/UnitsData.ts b/core/frontend/src/quantity-formatting/UnitsData.ts index 40194d56fda9..99df48beea40 100644 --- a/core/frontend/src/quantity-formatting/UnitsData.ts +++ b/core/frontend/src/quantity-formatting/UnitsData.ts @@ -34,7 +34,7 @@ export const UNIT_EXTRA_DATA = [ { name: "Units.MILLIINCH", altDisplayLabels: [] }, { name: "Units.MICROINCH", altDisplayLabels: [] }, { name: "Units.MILLIFOOT", altDisplayLabels: [] }, - { name: "Units.IN", altDisplayLabels: ["IN", "\""] }, + { name: "Units.IN", altDisplayLabels: ["IN", '"'] }, { name: "Units.FT", altDisplayLabels: ["F", "FT", "'"] }, { name: "Units.CHAIN", altDisplayLabels: ["CHAIN"] }, { name: "Units.YRD", altDisplayLabels: ["YRD", "yrd"] }, diff --git a/core/frontend/src/render/CreateRenderMaterialArgs.ts b/core/frontend/src/render/CreateRenderMaterialArgs.ts index 06d6614fabe6..40089a126f87 100644 --- a/core/frontend/src/render/CreateRenderMaterialArgs.ts +++ b/core/frontend/src/render/CreateRenderMaterialArgs.ts @@ -7,8 +7,8 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { IModelConnection } from "../IModelConnection"; import { MaterialParams } from "../common/render/MaterialParams"; +import { IModelConnection } from "../IModelConnection"; /** Specifies the provenance of a [RenderMaterial]($common) created for a persistent material element. * @see [[CreateRenderMaterialArgs.source]]. diff --git a/core/frontend/src/render/CreateTextureArgs.ts b/core/frontend/src/render/CreateTextureArgs.ts index 12abb510becb..f48ded0c6a30 100644 --- a/core/frontend/src/render/CreateTextureArgs.ts +++ b/core/frontend/src/render/CreateTextureArgs.ts @@ -7,8 +7,8 @@ */ import { ImageSource, RenderTexture, TextureTransparency } from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; import { TextureCacheKey, TextureImage } from "../common/render/TextureParams"; +import { IModelConnection } from "../IModelConnection"; /** Specifies that a [RenderTexture]($common) should be kept in memory until the corresponding [[IModelConnection]] is closed, at * which point it will be disposed. diff --git a/core/frontend/src/render/Decorations.ts b/core/frontend/src/render/Decorations.ts index 172ed5de1fb3..ebae78b9f7de 100644 --- a/core/frontend/src/render/Decorations.ts +++ b/core/frontend/src/render/Decorations.ts @@ -17,50 +17,62 @@ import { GraphicList, RenderGraphic } from "./RenderGraphic"; export class Decorations implements IDisposable { private _skyBox?: RenderGraphic; private _viewBackground?: RenderGraphic; // drawn first, view units, with no zbuffer, smooth shading, default lighting. e.g., a skybox - private _normal?: GraphicList; // drawn with zbuffer, with scene lighting - private _world?: GraphicList; // drawn with zbuffer, with default lighting, smooth shading + private _normal?: GraphicList; // drawn with zbuffer, with scene lighting + private _world?: GraphicList; // drawn with zbuffer, with default lighting, smooth shading private _worldOverlay?: GraphicList; // drawn in overlay mode, world units - private _viewOverlay?: GraphicList; // drawn in overlay mode, view units + private _viewOverlay?: GraphicList; // drawn in overlay mode, view units public canvasDecorations?: CanvasDecorationList; /** A view decoration created from a [[SkyBox]] rendered behind all other geometry to provide environmental context. */ - public get skyBox(): RenderGraphic | undefined { return this._skyBox; } + public get skyBox(): RenderGraphic | undefined { + return this._skyBox; + } public set skyBox(skyBox: RenderGraphic | undefined) { dispose(this._skyBox); this._skyBox = skyBox; } /** A view decoration drawn as the background of the view. @see [[GraphicType.ViewBackground]]. */ - public get viewBackground(): RenderGraphic | undefined { return this._viewBackground; } + public get viewBackground(): RenderGraphic | undefined { + return this._viewBackground; + } public set viewBackground(viewBackground: RenderGraphic | undefined) { dispose(this._viewBackground); this._viewBackground = viewBackground; } /** Decorations drawn as if they were part of the scene. @see [[GraphicType.Scene]]. */ - public get normal(): GraphicList | undefined { return this._normal; } + public get normal(): GraphicList | undefined { + return this._normal; + } public set normal(normal: GraphicList | undefined) { disposeArray(this._normal); this._normal = normal; } /** Decorations drawn as if they were part of the world, but ignoring the view's [[ViewFlags]]. @see [[GraphicType.WorldDecoration]]. */ - public get world(): GraphicList | undefined { return this._world; } + public get world(): GraphicList | undefined { + return this._world; + } public set world(world: GraphicList | undefined) { disposeArray(this._world); this._world = world; } /** Overlay decorations drawn in world coordinates. @see [[GraphicType.WorldOverlay]]. */ - public get worldOverlay(): GraphicList | undefined { return this._worldOverlay; } + public get worldOverlay(): GraphicList | undefined { + return this._worldOverlay; + } public set worldOverlay(worldOverlay: GraphicList | undefined) { disposeArray(this._worldOverlay); this._worldOverlay = worldOverlay; } /** Overlay decorations drawn in view coordinates. @see [[GraphicType.ViewOverlay]]. */ - public get viewOverlay(): GraphicList | undefined { return this._viewOverlay; } + public get viewOverlay(): GraphicList | undefined { + return this._viewOverlay; + } public set viewOverlay(viewOverlay: GraphicList | undefined) { disposeArray(this._viewOverlay); this._viewOverlay = viewOverlay; diff --git a/core/frontend/src/render/FrameStats.ts b/core/frontend/src/render/FrameStats.ts index a93f5a86cd0d..fd765b0ff7bb 100644 --- a/core/frontend/src/render/FrameStats.ts +++ b/core/frontend/src/render/FrameStats.ts @@ -102,7 +102,9 @@ export class FrameStatsCollector { this._frameStats.backgroundTime = 0; } - public constructor(onFrameStatsReady?: OnFrameStatsReadyEvent) { this._onFrameStatsReady = onFrameStatsReady; } + public constructor(onFrameStatsReady?: OnFrameStatsReadyEvent) { + this._onFrameStatsReady = onFrameStatsReady; + } private _begin(entry: keyof FrameStats) { const prevSpan = this._frameStats[entry]; diff --git a/core/frontend/src/render/GraphicBranch.ts b/core/frontend/src/render/GraphicBranch.ts index c0d22230b0ea..94ccf1f51407 100644 --- a/core/frontend/src/render/GraphicBranch.ts +++ b/core/frontend/src/render/GraphicBranch.ts @@ -7,19 +7,17 @@ */ import { disposeArray, Id64String, IDisposable } from "@itwin/core-bentley"; -import { - FeatureAppearanceProvider, HiddenLine, RealityModelDisplaySettings, RenderSchedule, ViewFlagOverrides, ViewFlags, -} from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; +import { FeatureAppearanceProvider, HiddenLine, RealityModelDisplaySettings, RenderSchedule, ViewFlagOverrides, ViewFlags } from "@itwin/core-common"; +import { Range3d, Transform } from "@itwin/core-geometry"; +import { AnimationNodeId } from "../common/internal/render/AnimationNodeId"; import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; import { FeatureSymbology } from "./FeatureSymbology"; import { RenderClipVolume } from "./RenderClipVolume"; import { RenderGraphic } from "./RenderGraphic"; import { RenderMemory } from "./RenderMemory"; import { RenderPlanarClassifier } from "./RenderPlanarClassifier"; import { RenderTextureDrape } from "./RenderSystem"; -import { Range3d, Transform } from "@itwin/core-geometry"; -import { AnimationNodeId } from "../common/internal/render/AnimationNodeId"; /** Carries information in a GraphicBranchOptions about a GraphicBranch produced by drawing one view into the context of another. * @internal @@ -182,7 +180,13 @@ export function formatAnimationBranchId(modelId: Id64String, branchId: number): return `${modelId}_Node_${branchId.toString()}`; } -function addAnimationBranch(modelId: Id64String, timeline: RenderSchedule.Timeline, branchId: number, branches: Map, time: number): void { +function addAnimationBranch( + modelId: Id64String, + timeline: RenderSchedule.Timeline, + branchId: number, + branches: Map, + time: number, +): void { const clipVector = timeline.getClipVector(time); const clip = clipVector ? IModelApp.renderSystem.createClipVolume(clipVector) : undefined; if (clip) diff --git a/core/frontend/src/render/GraphicBuilder.ts b/core/frontend/src/render/GraphicBuilder.ts index 8dcdc6dd89b6..4b44cb0c45da 100644 --- a/core/frontend/src/render/GraphicBuilder.ts +++ b/core/frontend/src/render/GraphicBuilder.ts @@ -8,14 +8,14 @@ import { Id64String } from "@itwin/core-bentley"; import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { _implementationProhibited } from "../common/internal/Symbols"; +import type { PickableGraphicOptions } from "../common/render/BatchOptions"; +import { GraphicAssembler } from "../common/render/GraphicAssembler"; +import { GraphicType } from "../common/render/GraphicType"; import { IModelConnection } from "../IModelConnection"; import { Viewport } from "../Viewport"; -import { RenderGraphic } from "./RenderGraphic"; -import { GraphicType } from "../common/render/GraphicType"; -import type { PickableGraphicOptions} from "../common/render/BatchOptions"; -import { GraphicAssembler } from "../common/render/GraphicAssembler"; -import { _implementationProhibited } from "../common/internal/Symbols"; import { GraphicTemplate } from "./GraphicTemplate"; +import { RenderGraphic } from "./RenderGraphic"; /** Options for creating a [[GraphicBuilder]] used by functions like [[DecorateContext.createGraphic]] and [[RenderSystem.createGraphic]]. * @see [[ViewportGraphicBuilderOptions]] to create a graphic builder for a [[Viewport]]. @@ -150,7 +150,8 @@ export abstract class GraphicBuilder extends GraphicAssembler { const placement = options.placement ?? Transform.createIdentity(); const wantEdges = options.generateEdges ?? (options.type === GraphicType.Scene && (!vp || vp.viewFlags.edgesRequired())); const wantNormals = options.wantNormals ?? (wantEdges || options.type === GraphicType.Scene); - const preserveOrder = options.preserveOrder ?? (options.type === GraphicType.ViewOverlay || options.type === GraphicType.WorldOverlay || options.type === GraphicType.ViewBackground); + const preserveOrder = options.preserveOrder ?? + (options.type === GraphicType.ViewOverlay || options.type === GraphicType.WorldOverlay || options.type === GraphicType.ViewBackground); super({ ...options, diff --git a/core/frontend/src/render/GraphicTemplate.ts b/core/frontend/src/render/GraphicTemplate.ts index 25e3286899fd..308023bd4885 100644 --- a/core/frontend/src/render/GraphicTemplate.ts +++ b/core/frontend/src/render/GraphicTemplate.ts @@ -6,12 +6,12 @@ * @module Rendering */ +import { RenderFeatureTable, ViewFlagOverrides } from "@itwin/core-common"; import { Range3d, Transform } from "@itwin/core-geometry"; import { _batch, _branch, _implementationProhibited, _nodes } from "../common/internal/Symbols"; -import { RenderGeometry } from "../internal/render/RenderGeometry"; -import { RenderFeatureTable, ViewFlagOverrides } from "@itwin/core-common"; -import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; import { BatchOptions } from "../common/render/BatchOptions"; +import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; +import { RenderGeometry } from "../internal/render/RenderGeometry"; /** @internal */ export interface GraphicTemplateNode { diff --git a/core/frontend/src/render/MeshArgs.ts b/core/frontend/src/render/MeshArgs.ts index d198ba064c4a..7407c80ec973 100644 --- a/core/frontend/src/render/MeshArgs.ts +++ b/core/frontend/src/render/MeshArgs.ts @@ -7,8 +7,8 @@ */ import { ColorIndex, FeatureIndex, FillFlags, OctEncodedNormal, QPoint3dList, RenderMaterial, RenderTexture } from "@itwin/core-common"; -import { MeshArgsEdges } from "../common/internal/render/MeshPrimitives"; import { AuxChannel, Point2d, Point3d, Range3d } from "@itwin/core-geometry"; +import { MeshArgsEdges } from "../common/internal/render/MeshPrimitives"; /** Arguments supplied to [[RenderSystem.createTriMesh]] describing a triangle mesh. * @public @@ -57,4 +57,3 @@ export interface MeshArgs { uvParams: Point2d[]; }; } - diff --git a/core/frontend/src/render/MockRender.ts b/core/frontend/src/render/MockRender.ts index 0c34ef16f531..a6b4146abd95 100644 --- a/core/frontend/src/render/MockRender.ts +++ b/core/frontend/src/render/MockRender.ts @@ -8,28 +8,28 @@ */ import { dispose } from "@itwin/core-bentley"; -import { Range3d, Transform } from "@itwin/core-geometry"; import { ElementAlignedBox3d, EmptyLocalization, RenderFeatureTable } from "@itwin/core-common"; -import { IModelApp, IModelAppOptions } from "../IModelApp"; -import { IModelConnection } from "../IModelConnection"; +import { Range3d, Transform } from "@itwin/core-geometry"; import { MeshParams } from "../common/internal/render/MeshParams"; +import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; import { PointStringParams } from "../common/internal/render/PointStringParams"; import { PolylineParams } from "../common/internal/render/PolylineParams"; +import { _implementationProhibited } from "../common/internal/Symbols"; import { ViewRect } from "../common/ViewRect"; +import { IModelApp, IModelAppOptions } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; +import { PrimitiveBuilder } from "../internal/render/PrimitiveBuilder"; +import { RenderGeometry } from "../internal/render/RenderGeometry"; import { Decorations } from "./Decorations"; import { GraphicBranch, GraphicBranchOptions } from "./GraphicBranch"; import { CustomGraphicBuilderOptions, GraphicBuilder, ViewportGraphicBuilderOptions } from "./GraphicBuilder"; import { Pixel } from "./Pixel"; -import { PrimitiveBuilder } from "../internal/render/PrimitiveBuilder"; -import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; import { GraphicList, RenderGraphic } from "./RenderGraphic"; import { RenderMemory } from "./RenderMemory"; import { RenderPlan } from "./RenderPlan"; import { RenderAreaPattern, RenderSystem } from "./RenderSystem"; import { RenderTarget } from "./RenderTarget"; import { Scene } from "./Scene"; -import { _implementationProhibited } from "../common/internal/Symbols"; -import { RenderGeometry } from "../internal/render/RenderGeometry"; /** Contains extensible mock implementations of the various components of a RenderSystem, intended for use in tests. * Use these for tests instead of the default RenderSystem wherever possible because: @@ -48,37 +48,61 @@ export namespace MockRender { export abstract class Target extends RenderTarget { protected override readonly [_implementationProhibited] = undefined; - protected constructor(private readonly _system: RenderSystem) { super(); } - - public get renderSystem(): RenderSystem { return this._system; } - public get wantInvertBlackBackground() { return false; } - public get analysisFraction() { return 0; } - public set analysisFraction(_fraction: number) { } - public changeScene(_scene: Scene) { } - public changeDynamics(_dynamics?: GraphicList) { } - public changeDecorations(_decs: Decorations) { } - public changeRenderPlan(_plan: RenderPlan) { } - public drawFrame(_sceneTime?: number) { } - public updateViewRect() { return false; } - public readPixels(_rect: ViewRect, _selector: Pixel.Selector, receiver: Pixel.Receiver, _excludeNonLocatable: boolean) { receiver(undefined); } - public get screenSpaceEffects(): Iterable { return []; } - public set screenSpaceEffects(_effects: Iterable) { } + protected constructor(private readonly _system: RenderSystem) { + super(); + } + + public get renderSystem(): RenderSystem { + return this._system; + } + public get wantInvertBlackBackground() { + return false; + } + public get analysisFraction() { + return 0; + } + public set analysisFraction(_fraction: number) {} + public changeScene(_scene: Scene) {} + public changeDynamics(_dynamics?: GraphicList) {} + public changeDecorations(_decs: Decorations) {} + public changeRenderPlan(_plan: RenderPlan) {} + public drawFrame(_sceneTime?: number) {} + public updateViewRect() { + return false; + } + public readPixels(_rect: ViewRect, _selector: Pixel.Selector, receiver: Pixel.Receiver, _excludeNonLocatable: boolean) { + receiver(undefined); + } + public get screenSpaceEffects(): Iterable { + return []; + } + public set screenSpaceEffects(_effects: Iterable) {} } /** @internal */ export class OnScreenTarget extends Target { - public constructor(system: RenderSystem, private readonly _canvas: HTMLCanvasElement) { super(system); } + public constructor(system: RenderSystem, private readonly _canvas: HTMLCanvasElement) { + super(system); + } - public get viewRect() { return new ViewRect(0, 0, this._canvas.clientWidth, this._canvas.clientHeight); } - public setViewRect(_rect: ViewRect, _temp: boolean) { } + public get viewRect() { + return new ViewRect(0, 0, this._canvas.clientWidth, this._canvas.clientHeight); + } + public setViewRect(_rect: ViewRect, _temp: boolean) {} } /** @internal */ export class OffScreenTarget extends Target { - public constructor(system: RenderSystem, private readonly _viewRect: ViewRect) { super(system); } + public constructor(system: RenderSystem, private readonly _viewRect: ViewRect) { + super(system); + } - public get viewRect() { return this._viewRect; } - public setViewRect(rect: ViewRect, _temp: boolean) { this._viewRect.setFrom(rect); } + public get viewRect() { + return this._viewRect; + } + public setViewRect(rect: ViewRect, _temp: boolean) { + this._viewRect.setFrom(rect); + } } /** @internal */ @@ -89,15 +113,19 @@ export namespace MockRender { } export class Graphic extends RenderGraphic { - public constructor() { super(); } + public constructor() { + super(); + } - public dispose() { } - public collectStatistics(_stats: RenderMemory.Statistics): void { } - public unionRange() { } + public dispose() {} + public collectStatistics(_stats: RenderMemory.Statistics): void {} + public unionRange() {} } export class List extends Graphic { - public constructor(public readonly graphics: RenderGraphic[]) { super(); } + public constructor(public readonly graphics: RenderGraphic[]) { + super(); + } public override dispose() { for (const graphic of this.graphics) @@ -108,13 +136,23 @@ export namespace MockRender { } export class Branch extends Graphic { - public constructor(public readonly branch: GraphicBranch, public readonly transform: Transform, public readonly options?: GraphicBranchOptions) { super(); } + public constructor(public readonly branch: GraphicBranch, public readonly transform: Transform, public readonly options?: GraphicBranchOptions) { + super(); + } - public override dispose() { this.branch.dispose(); } + public override dispose() { + this.branch.dispose(); + } } export class Batch extends Graphic { - public constructor(public readonly graphic: RenderGraphic, public readonly featureTable: RenderFeatureTable, public readonly range: ElementAlignedBox3d) { super(); } + public constructor( + public readonly graphic: RenderGraphic, + public readonly featureTable: RenderFeatureTable, + public readonly range: ElementAlignedBox3d, + ) { + super(); + } public override dispose() { dispose(this.graphic); @@ -127,63 +165,104 @@ export namespace MockRender { public readonly isInstanceable = true; public isDisposed = false; public constructor(public readonly renderGeometryType: "mesh" | "polyline" | "point-string") { - } - public dispose(): void { this.isDisposed = true; } - public collectStatistics(): void { } - public computeRange() { return new Range3d(); } + public dispose(): void { + this.isDisposed = true; + } + public collectStatistics(): void {} + public computeRange() { + return new Range3d(); + } } /** @internal */ export class AreaPattern implements RenderAreaPattern { public readonly [_implementationProhibited] = "renderAreaPattern"; - public dispose(): void { } - public collectStatistics(): void { } + public dispose(): void {} + public collectStatistics(): void {} } export class System extends RenderSystem { - public get isValid() { return true; } - public dispose(): void { } - public override get maxTextureSize() { return 4096; } + public get isValid() { + return true; + } + public dispose(): void {} + public override get maxTextureSize() { + return 4096; + } - public constructor() { super(); } + public constructor() { + super(); + } /** @internal */ - public override doIdleWork(): boolean { return false; } + public override doIdleWork(): boolean { + return false; + } /** @internal */ - public override createTarget(canvas: HTMLCanvasElement): OnScreenTarget { return new OnScreenTarget(this, canvas); } + public override createTarget(canvas: HTMLCanvasElement): OnScreenTarget { + return new OnScreenTarget(this, canvas); + } /** @internal */ - public override createOffscreenTarget(rect: ViewRect): RenderTarget { return new OffScreenTarget(this, rect); } + public override createOffscreenTarget(rect: ViewRect): RenderTarget { + return new OffScreenTarget(this, rect); + } public override createGraphic(options: CustomGraphicBuilderOptions | ViewportGraphicBuilderOptions): GraphicBuilder { return new Builder(this, options); } - public override createGraphicList(primitives: RenderGraphic[]) { return new List(primitives); } - public override createGraphicBranch(branch: GraphicBranch, transform: Transform, options?: GraphicBranchOptions) { return new Branch(branch, transform, options); } - public override createBatch(graphic: RenderGraphic, features: RenderFeatureTable, range: ElementAlignedBox3d) { return new Batch(graphic, features, range); } + public override createGraphicList(primitives: RenderGraphic[]) { + return new List(primitives); + } + public override createGraphicBranch(branch: GraphicBranch, transform: Transform, options?: GraphicBranchOptions) { + return new Branch(branch, transform, options); + } + public override createBatch(graphic: RenderGraphic, features: RenderFeatureTable, range: ElementAlignedBox3d) { + return new Batch(graphic, features, range); + } /** @internal */ - public override createMesh(_params: MeshParams) { return new Graphic(); } + public override createMesh(_params: MeshParams) { + return new Graphic(); + } /** @internal */ - public override createPolyline(_params: PolylineParams) { return new Graphic(); } + public override createPolyline(_params: PolylineParams) { + return new Graphic(); + } /** @internal */ - public override createPointString(_params: PointStringParams) { return new Graphic(); } + public override createPointString(_params: PointStringParams) { + return new Graphic(); + } /** @internal */ - public override createPointCloud(_args: PointCloudArgs, _imodel: IModelConnection) { return new Graphic(); } - public override createRenderGraphic() { return new Graphic(); } + public override createPointCloud(_args: PointCloudArgs, _imodel: IModelConnection) { + return new Graphic(); + } + public override createRenderGraphic() { + return new Graphic(); + } /** @internal */ - public override createMeshGeometry() { return new Geometry("mesh"); } + public override createMeshGeometry() { + return new Geometry("mesh"); + } /** @internal */ - public override createPolylineGeometry() { return new Geometry("polyline"); } + public override createPolylineGeometry() { + return new Geometry("polyline"); + } /** @internal */ - public override createPointStringGeometry() { return new Geometry("point-string"); } + public override createPointStringGeometry() { + return new Geometry("point-string"); + } /** @internal */ - public override createAreaPattern() { return new AreaPattern(); } + public override createAreaPattern() { + return new AreaPattern(); + } /** @internal */ - public override createGraphicFromTemplate() { return new Graphic(); } + public override createGraphicFromTemplate() { + return new Graphic(); + } } export type SystemFactory = () => RenderSystem; @@ -204,6 +283,8 @@ export namespace MockRender { await IModelApp.shutdown(); } - protected static createDefaultRenderSystem() { return new System(); } + protected static createDefaultRenderSystem() { + return new System(); + } } } diff --git a/core/frontend/src/render/ParticleCollectionBuilder.ts b/core/frontend/src/render/ParticleCollectionBuilder.ts index dc6cd1079f6f..758d5f149ffc 100644 --- a/core/frontend/src/render/ParticleCollectionBuilder.ts +++ b/core/frontend/src/render/ParticleCollectionBuilder.ts @@ -7,18 +7,27 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { Matrix3d, Point2d, Point3d, Range3d, Transform, Vector2d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { - ColorDef, ColorIndex, Feature, FeatureIndex, FeatureTable, FillFlags, PackedFeatureTable, QParams3d, QPoint3dList, RenderTexture, + ColorDef, + ColorIndex, + Feature, + FeatureIndex, + FeatureTable, + FillFlags, + PackedFeatureTable, + QParams3d, + QPoint3dList, + RenderTexture, } from "@itwin/core-common"; -import { Viewport } from "../Viewport"; -import { RenderGraphic } from "./RenderGraphic"; -import { GraphicBranch } from "./GraphicBranch"; +import { Matrix3d, Point2d, Point3d, Range3d, Transform, Vector2d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { DisplayParams } from "../common/internal/render/DisplayParams"; import { MeshParams } from "../common/internal/render/MeshParams"; import { createMeshParams } from "../common/internal/render/VertexTableBuilder"; import { IModelApp } from "../IModelApp"; +import { Viewport } from "../Viewport"; +import { GraphicBranch } from "./GraphicBranch"; import { MeshArgs } from "./MeshArgs"; +import { RenderGraphic } from "./RenderGraphic"; /** Parameters used to construct a [[ParticleCollectionBuilder]]. * @public @@ -83,7 +92,7 @@ export interface ParticleProps extends XYAndZ { * * Creating a particle collection using a ParticleCollectionBuilder is far more efficient (in both CPU and GPU usage) than doing so using a [[GraphicBuilder]]. * @see interactive demonstrations of [Snow and Rain](https://www.itwinjs.org/sample-showcase/?group=Viewer+Features&sample=snow-rain-sample&imodel=Villa) and - * [Fire and Smoke](https://www.itwinjs.org/sample-showcase/?group=Viewer+Features&sample=fire-sample&imodel=Villa) particle effects. + * [Fire and Smoke](https://www.itwinjs.org/sample-showcase/?group=Viewer+Features&sample=fire-sample&imodel=Villa) particle effects. * @see [SnowEffect]($frontend-devtools) for an example of a particle effect. * @public * @extensions @@ -159,7 +168,9 @@ class Builder implements ParticleCollectionBuilder { this._pickableId = params.pickableId; this._texture = params.texture; this._transparency = undefined !== params.transparency ? clampTransparency(params.transparency) : 0; - this._localToWorldTransform = params.origin ? Transform.createTranslationXYZ(params.origin.x, params.origin.y, params.origin.z) : Transform.createIdentity(); + this._localToWorldTransform = params.origin + ? Transform.createTranslationXYZ(params.origin.x, params.origin.y, params.origin.z) + : Transform.createIdentity(); if ("number" === typeof params.size) this._size = new Vector2d(params.size, params.size); @@ -347,8 +358,10 @@ function createQuad(size: XAndY, texture: RenderTexture, transparency: number, v const halfWidth = size.x / 2; const halfHeight = size.y / 2; const corners = [ - new Point3d(-halfWidth, -halfHeight, 0), new Point3d(halfWidth, -halfHeight, 0), - new Point3d(-halfWidth, halfHeight, 0), new Point3d(halfWidth, halfHeight, 0), + new Point3d(-halfWidth, -halfHeight, 0), + new Point3d(halfWidth, -halfHeight, 0), + new Point3d(-halfWidth, halfHeight, 0), + new Point3d(halfWidth, halfHeight, 0), ]; const range = new Range3d(); diff --git a/core/frontend/src/render/Pixel.ts b/core/frontend/src/render/Pixel.ts index 0824530d6efd..4a21c92af138 100644 --- a/core/frontend/src/render/Pixel.ts +++ b/core/frontend/src/render/Pixel.ts @@ -8,10 +8,10 @@ import { Id64, Id64String } from "@itwin/core-bentley"; import { BatchType, Feature, GeometryClass, ModelFeature } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; import { HitPriority, ViewAttachmentHitInfo } from "../HitDetail"; import { IModelConnection } from "../IModelConnection"; import type { Viewport } from "../Viewport"; -import { Transform } from "@itwin/core-geometry"; /** Describes aspects of a pixel as read from a [[Viewport]]. * @see [[Viewport.readPixels]]. diff --git a/core/frontend/src/render/PolylineArgs.ts b/core/frontend/src/render/PolylineArgs.ts index 2d6b8e111f08..4554e5696057 100644 --- a/core/frontend/src/render/PolylineArgs.ts +++ b/core/frontend/src/render/PolylineArgs.ts @@ -32,4 +32,3 @@ export interface PolylineArgs { /** The set of polylines. Each entry in the array describes a separate line string or point string as a series of indices into [[points]]. */ polylines: PolylineIndices[]; } - diff --git a/core/frontend/src/render/RealityMeshGraphicParams.ts b/core/frontend/src/render/RealityMeshGraphicParams.ts index 7152c60f5e86..af1c5d7bf2f7 100644 --- a/core/frontend/src/render/RealityMeshGraphicParams.ts +++ b/core/frontend/src/render/RealityMeshGraphicParams.ts @@ -8,7 +8,7 @@ import { ColorDef, PackedFeatureTable } from "@itwin/core-common"; import { MapCartoRectangle, MapTileProjection } from "../tile/internal"; -import { MapLayerClassifiers, RenderTerrainGeometry, TerrainTexture } from "./RenderSystem"; +import { MapLayerClassifiers, RenderTerrainGeometry, TerrainTexture } from "./RenderSystem"; /** @internal */ export interface RealityMeshGraphicParams { diff --git a/core/frontend/src/render/RealityMeshParams.ts b/core/frontend/src/render/RealityMeshParams.ts index 7f35f3ffa89e..052865c7a3a0 100644 --- a/core/frontend/src/render/RealityMeshParams.ts +++ b/core/frontend/src/render/RealityMeshParams.ts @@ -8,13 +8,18 @@ import { assert, Uint16ArrayBuilder, UintArray, UintArrayBuilder } from "@itwin/core-bentley"; import { - IndexedPolyface, Point2d, Point3d, Range2d, Range3d, Transform, Vector3d, XAndY, XYAndZ, -} from "@itwin/core-geometry"; -import { - OctEncodedNormal, QPoint2d, QPoint2dBuffer, QPoint2dBufferBuilder, QPoint3d, QPoint3dBuffer, QPoint3dBufferBuilder, RenderTexture, + OctEncodedNormal, + QPoint2d, + QPoint2dBuffer, + QPoint2dBufferBuilder, + QPoint3d, + QPoint3dBuffer, + QPoint3dBufferBuilder, + RenderTexture, } from "@itwin/core-common"; -import { GltfMeshData } from "../tile/internal"; +import { IndexedPolyface, Point2d, Point3d, Range2d, Range3d, Transform, Vector3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { MeshPrimitiveType } from "../common/internal/render/MeshPrimitive"; +import { GltfMeshData } from "../tile/internal"; function precondition(condition: boolean, message: string | (() => string)): asserts condition { if (condition) @@ -53,7 +58,10 @@ export namespace RealityMeshParams { /** @internal */ export function fromGltfMesh(mesh: GltfMeshData): RealityMeshParams | undefined { // The specialized reality mesh shaders expect a mesh with uvs and no edges. - if (mesh.primitive.type !== MeshPrimitiveType.Mesh || mesh.primitive.edges || !mesh.pointQParams || !mesh.uvQParams || !mesh.points || !mesh.uvs || !mesh.indices) + if ( + mesh.primitive.type !== MeshPrimitiveType.Mesh || mesh.primitive.edges || !mesh.pointQParams || !mesh.uvQParams || !mesh.points || !mesh.uvs || + !mesh.indices + ) return undefined; return { @@ -73,7 +81,10 @@ export namespace RealityMeshParams { } /** @alpha */ - export function toPolyface(params: RealityMeshParams, options?: { transform?: Transform, wantNormals?: boolean, wantParams?: boolean }): IndexedPolyface | undefined { + export function toPolyface( + params: RealityMeshParams, + options?: { transform?: Transform, wantNormals?: boolean, wantParams?: boolean }, + ): IndexedPolyface | undefined { const { positions, normals, uvs, indices } = params; const includeNormals = options?.wantNormals && undefined !== normals; const includeParams = options?.wantParams; diff --git a/core/frontend/src/render/RenderGraphic.ts b/core/frontend/src/render/RenderGraphic.ts index a5f60f100b00..5033fa1ea419 100644 --- a/core/frontend/src/render/RenderGraphic.ts +++ b/core/frontend/src/render/RenderGraphic.ts @@ -7,8 +7,8 @@ */ import { IDisposable } from "@itwin/core-bentley"; -import { RenderMemory } from "./RenderMemory"; import { Range3d } from "@itwin/core-geometry"; +import { RenderMemory } from "./RenderMemory"; /** Abstract representation of an object which can be rendered by a [[RenderSystem]]. * Two broad classes of graphics exist: @@ -25,8 +25,8 @@ export abstract class RenderGraphic implements IDisposable /* , RenderMemory.Con public abstract collectStatistics(stats: RenderMemory.Statistics): void; /** Extend `range` to include the bounding box of this graphic, including any child graphics. - * @internal - */ + * @internal + */ public abstract unionRange(range: Range3d): void; } @@ -41,13 +41,19 @@ export abstract class RenderGraphicOwner extends RenderGraphic { /** The owned graphic. */ public abstract get graphic(): RenderGraphic; /** Does nothing. To dispose of the owned graphic, use [[disposeGraphic]]. */ - public dispose(): void { } + public dispose(): void {} /** Disposes of the owned graphic. */ - public disposeGraphic(): void { this.graphic.dispose(); } + public disposeGraphic(): void { + this.graphic.dispose(); + } /** @internal */ - public collectStatistics(stats: RenderMemory.Statistics): void { this.graphic.collectStatistics(stats); } + public collectStatistics(stats: RenderMemory.Statistics): void { + this.graphic.collectStatistics(stats); + } /** @internal */ - public override unionRange(range: Range3d): void { this.graphic.unionRange(range); } + public override unionRange(range: Range3d): void { + this.graphic.unionRange(range); + } } /** An array of [[RenderGraphic]]s. diff --git a/core/frontend/src/render/RenderMemory.ts b/core/frontend/src/render/RenderMemory.ts index 10f256feabe3..5f146b37244e 100644 --- a/core/frontend/src/render/RenderMemory.ts +++ b/core/frontend/src/render/RenderMemory.ts @@ -60,17 +60,39 @@ export namespace RenderMemory { this.consumers[i] = new Consumers(); } - public get surfaces() { return this.consumers[BufferType.Surfaces]; } - public get visibleEdges() { return this.consumers[BufferType.VisibleEdges]; } - public get indexedEdges() { return this.consumers[BufferType.IndexedEdges]; } - public get silhouetteEdges() { return this.consumers[BufferType.SilhouetteEdges]; } - public get polylineEdges() { return this.consumers[BufferType.PolylineEdges]; } - public get polylines() { return this.consumers[BufferType.Polylines]; } - public get pointStrings() { return this.consumers[BufferType.PointStrings]; } - public get pointClouds() { return this.consumers[BufferType.PointClouds]; } - public get instances() { return this.consumers[BufferType.Instances]; } - public get terrain() { return this.consumers[BufferType.Terrain]; } - public get reality() { return this.consumers[BufferType.RealityMesh]; } + public get surfaces() { + return this.consumers[BufferType.Surfaces]; + } + public get visibleEdges() { + return this.consumers[BufferType.VisibleEdges]; + } + public get indexedEdges() { + return this.consumers[BufferType.IndexedEdges]; + } + public get silhouetteEdges() { + return this.consumers[BufferType.SilhouetteEdges]; + } + public get polylineEdges() { + return this.consumers[BufferType.PolylineEdges]; + } + public get polylines() { + return this.consumers[BufferType.Polylines]; + } + public get pointStrings() { + return this.consumers[BufferType.PointStrings]; + } + public get pointClouds() { + return this.consumers[BufferType.PointClouds]; + } + public get instances() { + return this.consumers[BufferType.Instances]; + } + public get terrain() { + return this.consumers[BufferType.Terrain]; + } + public get reality() { + return this.consumers[BufferType.RealityMesh]; + } public override clear(): void { for (const consumer of this.consumers) @@ -130,27 +152,49 @@ export namespace RenderMemory { * is an estimate based on the number of bytes of data requested via WebGL APIs. It is always an *under-estimate* as each WebGL implementation imposes * its own additional overhead. */ - public get totalBytes(): number { return this._totalBytes; } + public get totalBytes(): number { + return this._totalBytes; + } /** @internal */ - public get textures() { return this.consumers[ConsumerType.Textures]; } + public get textures() { + return this.consumers[ConsumerType.Textures]; + } /** @internal */ - public get vertexTables() { return this.consumers[ConsumerType.VertexTables]; } + public get vertexTables() { + return this.consumers[ConsumerType.VertexTables]; + } /** @internal */ - public get edgeTables() { return this.consumers[ConsumerType.EdgeTables]; } + public get edgeTables() { + return this.consumers[ConsumerType.EdgeTables]; + } /** @internal */ - public get featureTables() { return this.consumers[ConsumerType.FeatureTables]; } + public get featureTables() { + return this.consumers[ConsumerType.FeatureTables]; + } /** @internal */ - public get thematicTextures() { return this.consumers[ConsumerType.ThematicTextures]; } + public get thematicTextures() { + return this.consumers[ConsumerType.ThematicTextures]; + } /** @internal */ - public get featureOverrides() { return this.consumers[ConsumerType.FeatureOverrides]; } + public get featureOverrides() { + return this.consumers[ConsumerType.FeatureOverrides]; + } /** @internal */ - public get clipVolumes() { return this.consumers[ConsumerType.ClipVolumes]; } + public get clipVolumes() { + return this.consumers[ConsumerType.ClipVolumes]; + } /** @internal */ - public get planarClassifiers() { return this.consumers[ConsumerType.PlanarClassifiers]; } + public get planarClassifiers() { + return this.consumers[ConsumerType.PlanarClassifiers]; + } /** @internal */ - public get shadowMaps() { return this.consumers[ConsumerType.ShadowMaps]; } + public get shadowMaps() { + return this.consumers[ConsumerType.ShadowMaps]; + } /** @internal */ - public get textureAttachments() { return this.consumers[ConsumerType.TextureAttachments]; } + public get textureAttachments() { + return this.consumers[ConsumerType.TextureAttachments]; + } /** @internal */ public addBuffer(type: BufferType, numBytes: number): void { @@ -173,44 +217,82 @@ export namespace RenderMemory { } /** @internal */ - public addTexture(numBytes: number) { this.addConsumer(ConsumerType.Textures, numBytes); } + public addTexture(numBytes: number) { + this.addConsumer(ConsumerType.Textures, numBytes); + } /** @internal */ - public addVertexTable(numBytes: number) { this.addConsumer(ConsumerType.VertexTables, numBytes); } + public addVertexTable(numBytes: number) { + this.addConsumer(ConsumerType.VertexTables, numBytes); + } /** @internal */ - public addEdgeTable(numBytes: number) { this.addConsumer(ConsumerType.EdgeTables, numBytes); } + public addEdgeTable(numBytes: number) { + this.addConsumer(ConsumerType.EdgeTables, numBytes); + } /** @internal */ - public addFeatureTable(numBytes: number) { this.addConsumer(ConsumerType.FeatureTables, numBytes); } + public addFeatureTable(numBytes: number) { + this.addConsumer(ConsumerType.FeatureTables, numBytes); + } /** @internal */ - public addThematicTexture(numBytes: number) { this.addConsumer(ConsumerType.ThematicTextures, numBytes); } + public addThematicTexture(numBytes: number) { + this.addConsumer(ConsumerType.ThematicTextures, numBytes); + } /** @internal */ - public addFeatureOverrides(numBytes: number) { this.addConsumer(ConsumerType.FeatureOverrides, numBytes); } + public addFeatureOverrides(numBytes: number) { + this.addConsumer(ConsumerType.FeatureOverrides, numBytes); + } /** @internal */ - public addContours(numBytes: number) { this.addConsumer(ConsumerType.FeatureOverrides, numBytes); } + public addContours(numBytes: number) { + this.addConsumer(ConsumerType.FeatureOverrides, numBytes); + } /** @internal */ - public addClipVolume(numBytes: number) { this.addConsumer(ConsumerType.ClipVolumes, numBytes); } + public addClipVolume(numBytes: number) { + this.addConsumer(ConsumerType.ClipVolumes, numBytes); + } /** @internal */ - public addPlanarClassifier(numBytes: number) { this.addConsumer(ConsumerType.PlanarClassifiers, numBytes); } + public addPlanarClassifier(numBytes: number) { + this.addConsumer(ConsumerType.PlanarClassifiers, numBytes); + } /** @internal */ - public addShadowMap(numBytes: number) { this.addConsumer(ConsumerType.ShadowMaps, numBytes); } + public addShadowMap(numBytes: number) { + this.addConsumer(ConsumerType.ShadowMaps, numBytes); + } /** @internal */ - public addTextureAttachment(numBytes: number) { this.addConsumer(ConsumerType.TextureAttachments, numBytes); } + public addTextureAttachment(numBytes: number) { + this.addConsumer(ConsumerType.TextureAttachments, numBytes); + } /** @internal */ - public addSurface(numBytes: number) { this.addBuffer(BufferType.Surfaces, numBytes); } + public addSurface(numBytes: number) { + this.addBuffer(BufferType.Surfaces, numBytes); + } /** @internal */ - public addVisibleEdges(numBytes: number) { this.addBuffer(BufferType.VisibleEdges, numBytes); } + public addVisibleEdges(numBytes: number) { + this.addBuffer(BufferType.VisibleEdges, numBytes); + } /** @internal */ - public addIndexedEdges(numBytes: number) { this.addBuffer(BufferType.IndexedEdges, numBytes); } + public addIndexedEdges(numBytes: number) { + this.addBuffer(BufferType.IndexedEdges, numBytes); + } /** @internal */ - public addSilhouetteEdges(numBytes: number) { this.addBuffer(BufferType.SilhouetteEdges, numBytes); } + public addSilhouetteEdges(numBytes: number) { + this.addBuffer(BufferType.SilhouetteEdges, numBytes); + } /** @internal */ - public addPolylineEdges(numBytes: number) { this.addBuffer(BufferType.PolylineEdges, numBytes); } + public addPolylineEdges(numBytes: number) { + this.addBuffer(BufferType.PolylineEdges, numBytes); + } /** @internal */ - public addPolyline(numBytes: number) { this.addBuffer(BufferType.Polylines, numBytes); } + public addPolyline(numBytes: number) { + this.addBuffer(BufferType.Polylines, numBytes); + } /** @internal */ - public addPointString(numBytes: number) { this.addBuffer(BufferType.PointStrings, numBytes); } + public addPointString(numBytes: number) { + this.addBuffer(BufferType.PointStrings, numBytes); + } /** @internal */ - public addPointCloud(numBytes: number) { this.addBuffer(BufferType.PointClouds, numBytes); } + public addPointCloud(numBytes: number) { + this.addBuffer(BufferType.PointClouds, numBytes); + } /** @internal */ public addTerrain(numBytes: number) { this.addBuffer(BufferType.Terrain, numBytes); @@ -220,7 +302,9 @@ export namespace RenderMemory { this.addBuffer(BufferType.RealityMesh, numBytes); } /** @internal */ - public addInstances(numBytes: number) { this.addBuffer(BufferType.Instances, numBytes); } + public addInstances(numBytes: number) { + this.addBuffer(BufferType.Instances, numBytes); + } } /** @internal */ diff --git a/core/frontend/src/render/RenderPlan.ts b/core/frontend/src/render/RenderPlan.ts index 1df75e5b6471..421586f290ff 100644 --- a/core/frontend/src/render/RenderPlan.ts +++ b/core/frontend/src/render/RenderPlan.ts @@ -7,8 +7,23 @@ */ import { - AmbientOcclusion, AnalysisStyle, Atmosphere, ClipStyle, ColorDef, ContourDisplay, Frustum, GlobeMode, HiddenLine, Hilite, LightSettings, MonochromeMode, Npc, - RenderTexture, ThematicDisplay, ViewFlags, WhiteOnWhiteReversalSettings, + AmbientOcclusion, + AnalysisStyle, + Atmosphere, + ClipStyle, + ColorDef, + ContourDisplay, + Frustum, + GlobeMode, + HiddenLine, + Hilite, + LightSettings, + MonochromeMode, + Npc, + RenderTexture, + ThematicDisplay, + ViewFlags, + WhiteOnWhiteReversalSettings, } from "@itwin/core-common"; import { ClipVector, Constant, Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry"; import { FlashSettings } from "../FlashSettings"; @@ -131,7 +146,9 @@ export function createRenderPlanFromViewport(vp: Viewport): RenderPlan { const analysisStyle = style.settings.analysisStyle; const thematic = (style.is3d() && view.displayStyle.viewFlags.thematicDisplay) ? style.settings.thematic : undefined; const contours = (style.is3d() && style.settings.contours.groups.length > 0) ? style.settings.contours : undefined; - const shouldDisplayAtmosphere = (style.is3d() && GlobeMode.Ellipsoid === view.globeMode && vp.iModel.isGeoLocated && style.viewFlags.backgroundMap) ? (vp.view as ViewState3d).getDisplayStyle3d().environment.displayAtmosphere : false; + const shouldDisplayAtmosphere = (style.is3d() && GlobeMode.Ellipsoid === view.globeMode && vp.iModel.isGeoLocated && style.viewFlags.backgroundMap) + ? (vp.view as ViewState3d).getDisplayStyle3d().environment.displayAtmosphere + : false; const atmosphere = shouldDisplayAtmosphere ? (vp.view as ViewState3d).getDisplayStyle3d().environment.atmosphere : undefined; let upVector; diff --git a/core/frontend/src/render/RenderPlanarClassifier.ts b/core/frontend/src/render/RenderPlanarClassifier.ts index 8fa420f403af..e3fc707a7c40 100644 --- a/core/frontend/src/render/RenderPlanarClassifier.ts +++ b/core/frontend/src/render/RenderPlanarClassifier.ts @@ -13,7 +13,12 @@ import { SpatialClassifierTileTreeReference, Tile } from "../tile/internal"; import { SceneContext } from "../ViewContext"; /** @internal */ -export interface PlanarClassifierTarget { modelId: Id64String, tiles: Tile[], location: Transform, isPointCloud: boolean } +export interface PlanarClassifierTarget { + modelId: Id64String; + tiles: Tile[]; + location: Transform; + isPointCloud: boolean; +} /** An opaque representation of a planar classifier applied to geometry within a [[Viewport]]. * @internal */ diff --git a/core/frontend/src/render/RenderSystem.ts b/core/frontend/src/render/RenderSystem.ts index 799873883be6..12a2fa691fa6 100644 --- a/core/frontend/src/render/RenderSystem.ts +++ b/core/frontend/src/render/RenderSystem.ts @@ -8,50 +8,77 @@ import { base64StringToUint8Array, Id64String, IDisposable } from "@itwin/core-bentley"; import { - ColorDef, ColorIndex, ElementAlignedBox3d, FeatureIndex, FeatureIndexType, FillFlags, Frustum, Gradient, ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, - isValidImageSourceFormat, PackedFeatureTable, QParams3d, QPoint3dList, RenderFeatureTable, RenderMaterial, RenderTexture, SkyGradient, TextureProps, TextureTransparency, + ColorDef, + ColorIndex, + ElementAlignedBox3d, + FeatureIndex, + FeatureIndexType, + FillFlags, + Frustum, + Gradient, + ImageBuffer, + ImageBufferFormat, + ImageSource, + ImageSourceFormat, + isValidImageSourceFormat, + PackedFeatureTable, + QParams3d, + QPoint3dList, + RenderFeatureTable, + RenderMaterial, + RenderTexture, + SkyGradient, + TextureProps, + TextureTransparency, } from "@itwin/core-common"; import { ClipVector, Matrix3d, Point2d, Point3d, Range2d, Range3d, Transform, Vector2d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { WebGLExtensionName } from "@itwin/webgl-compatibility"; -import { IModelApp } from "../IModelApp"; -import { IModelConnection } from "../IModelConnection"; -import { createGraphicFromDescription, createGraphicTemplateFromDescription, MapTileTreeReference, TileTreeReference } from "../tile/internal"; -import { ToolAdmin } from "../tools/ToolAdmin"; -import { SceneContext } from "../ViewContext"; -import { Viewport } from "../Viewport"; import { imageElementFromImageSource, tryImageElementFromUrl } from "../common/ImageUtil"; +import { + GraphicDescriptionContextPropsImpl, + WorkerGraphicDescriptionContextPropsImpl, +} from "../common/internal/render/GraphicDescriptionContextImpl"; import { MeshParams } from "../common/internal/render/MeshParams"; +import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; import { createPointStringParams, PointStringParams } from "../common/internal/render/PointStringParams"; import { createPolylineParams, PolylineParams } from "../common/internal/render/PolylineParams"; +import { createMeshParams } from "../common/internal/render/VertexTableBuilder"; +import { _featureTable, _implementationProhibited, _renderSystem, _textures, _transformCenter, _transforms } from "../common/internal/Symbols"; +import { BatchOptions } from "../common/render/BatchOptions"; +import { GraphicDescription } from "../common/render/GraphicDescriptionBuilder"; +import { + GraphicDescriptionContext, + GraphicDescriptionContextProps, + WorkerGraphicDescriptionContextProps, +} from "../common/render/GraphicDescriptionContext"; +import { GraphicType } from "../common/render/GraphicType"; +import { InstancedGraphicParams, PatternGraphicParams } from "../common/render/InstancedGraphicParams"; +import { RenderInstancesParams } from "../common/render/RenderInstancesParams"; import { TextureCacheKey } from "../common/render/TextureParams"; import { ViewRect } from "../common/ViewRect"; +import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; +import { RenderGeometry } from "../internal/render/RenderGeometry"; +import { createGraphicFromDescription, createGraphicTemplateFromDescription, MapTileTreeReference, TileTreeReference } from "../tile/internal"; +import { ToolAdmin } from "../tools/ToolAdmin"; +import { SceneContext } from "../ViewContext"; +import { Viewport } from "../Viewport"; +import { CreateRenderMaterialArgs } from "./CreateRenderMaterialArgs"; +import { CreateTextureArgs, CreateTextureFromSourceArgs } from "./CreateTextureArgs"; import { GraphicBranch, GraphicBranchOptions } from "./GraphicBranch"; import { CustomGraphicBuilderOptions, GraphicBuilder, ViewportGraphicBuilderOptions } from "./GraphicBuilder"; -import { InstancedGraphicParams, PatternGraphicParams } from "../common/render/InstancedGraphicParams"; -import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { GraphicTemplate } from "./GraphicTemplate"; +import { MeshArgs } from "./MeshArgs"; +import { PolylineArgs } from "./PolylineArgs"; import { RealityMeshGraphicParams } from "./RealityMeshGraphicParams"; import { RealityMeshParams } from "./RealityMeshParams"; -import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; import { RenderClipVolume } from "./RenderClipVolume"; import { RenderGraphic, RenderGraphicOwner } from "./RenderGraphic"; -import { CreateRenderMaterialArgs } from "./CreateRenderMaterialArgs"; import { RenderMemory } from "./RenderMemory"; import { RenderPlanarClassifier } from "./RenderPlanarClassifier"; import { RenderTarget } from "./RenderTarget"; -import { CreateTextureArgs, CreateTextureFromSourceArgs } from "./CreateTextureArgs"; import { ScreenSpaceEffectBuilder, ScreenSpaceEffectBuilderParams } from "./ScreenSpaceEffectBuilder"; -import { createMeshParams } from "../common/internal/render/VertexTableBuilder"; -import { GraphicType } from "../common/render/GraphicType"; -import { BatchOptions } from "../common/render/BatchOptions"; -import { GraphicDescription } from "../common/render/GraphicDescriptionBuilder"; -import { GraphicDescriptionContextPropsImpl, WorkerGraphicDescriptionContextPropsImpl } from "../common/internal/render/GraphicDescriptionContextImpl"; -import { _featureTable, _implementationProhibited, _renderSystem, _textures, _transformCenter, _transforms } from "../common/internal/Symbols"; -import { GraphicDescriptionContext, GraphicDescriptionContextProps, WorkerGraphicDescriptionContextProps } from "../common/render/GraphicDescriptionContext"; -import { MeshArgs } from "./MeshArgs"; -import { PolylineArgs } from "./PolylineArgs"; -import { RenderGeometry } from "../internal/render/RenderGeometry"; -import { RenderInstancesParams } from "../common/render/RenderInstancesParams"; -import { GraphicTemplate } from "./GraphicTemplate"; /* eslint-disable no-restricted-syntax */ // cSpell:ignore deserializing subcat uninstanced wiremesh qorigin trimesh @@ -113,8 +140,12 @@ export type GLTimerResultCallback = (result: GLTimerResult) => void; /** Default implementation of RenderGraphicOwner. */ class GraphicOwner extends RenderGraphicOwner { - public constructor(private readonly _graphic: RenderGraphic) { super(); } - public get graphic(): RenderGraphic { return this._graphic; } + public constructor(private readonly _graphic: RenderGraphic) { + super(); + } + public get graphic(): RenderGraphic { + return this._graphic; + } } /** An interface optionally exposed by a RenderSystem that allows control of various debugging features. @@ -171,10 +202,19 @@ export class TerrainTexture { public readonly layerIndex: number, public transparency: number, public readonly clipRectangle?: Range2d, - ) { } + ) {} public cloneWithClip(clipRectangle: Range2d) { - return new TerrainTexture (this.texture, this.featureId, this.scale, this.translate, this.targetRectangle, this.layerIndex, this.transparency, clipRectangle); + return new TerrainTexture( + this.texture, + this.featureId, + this.scale, + this.translate, + this.targetRectangle, + this.layerIndex, + this.transparency, + clipRectangle, + ); } } /** @internal */ @@ -185,7 +225,7 @@ export class DebugShaderFile { public isVS: boolean, public isGL: boolean, public isUsed: boolean, - ) { } + ) {} } /** Transparency settings for planar grid display. * @alpha @@ -327,16 +367,24 @@ export abstract class RenderSystem implements IDisposable { public abstract dispose(): void; /** The maximum permitted width or height of a texture supported by this render system. */ - public get maxTextureSize(): number { return 0; } + public get maxTextureSize(): number { + return 0; + } /** @internal */ - public get supportsCreateImageBitmap(): boolean { return false; } + public get supportsCreateImageBitmap(): boolean { + return false; + } /** @internal */ - public get dpiAwareLOD(): boolean { return true === this.options.dpiAwareLOD; } + public get dpiAwareLOD(): boolean { + return true === this.options.dpiAwareLOD; + } /** @internal */ - public get isMobile(): boolean { return false; } + public get isMobile(): boolean { + return false; + } /** @internal */ public abstract createTarget(canvas: HTMLCanvasElement): RenderTarget; @@ -353,7 +401,9 @@ export abstract class RenderSystem implements IDisposable { * @param _imodel The IModelConnection with which the material is associated. * @returns A previously-created material matching the specified ID, or undefined if no such material exists. */ - public findMaterial(_key: string, _imodel: IModelConnection): RenderMaterial | undefined { return undefined; } + public findMaterial(_key: string, _imodel: IModelConnection): RenderMaterial | undefined { + return undefined; + } /** Create a [RenderMaterial]($common) from parameters * If the parameters include a non-empty key, and no previously-created material already exists with that key, the newly-created material will be cached on the IModelConnection such @@ -364,7 +414,9 @@ export abstract class RenderSystem implements IDisposable { * @deprecated in 3.x. Use [[createRenderMaterial]]. */ // eslint-disable-next-line deprecation/deprecation - public createMaterial(_params: RenderMaterial.Params, _imodel: IModelConnection): RenderMaterial | undefined { return undefined; } + public createMaterial(_params: RenderMaterial.Params, _imodel: IModelConnection): RenderMaterial | undefined { + return undefined; + } /** Create a [RenderMaterial]($common). * @see [[CreateRenderMaterialArgs]] for a description of the material parameters. @@ -467,23 +519,37 @@ export abstract class RenderSystem implements IDisposable { } /** @internal */ - public createMeshGeometry(_params: MeshParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { return undefined; } + public createMeshGeometry(_params: MeshParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { + return undefined; + } /** @internal */ - public createPolylineGeometry(_params: PolylineParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { return undefined; } + public createPolylineGeometry(_params: PolylineParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { + return undefined; + } /** @internal */ - public createPointStringGeometry(_params: PointStringParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { return undefined; } + public createPointStringGeometry(_params: PointStringParams, _viewIndependentOrigin?: Point3d): RenderGeometry | undefined { + return undefined; + } /** @internal */ - public createPointCloudGeometry(_args: PointCloudArgs): RenderGeometry | undefined { return undefined; } + public createPointCloudGeometry(_args: PointCloudArgs): RenderGeometry | undefined { + return undefined; + } /** @internal */ - public createRealityMeshGeometry(_params: RealityMeshParams, _disableTextureDisposal = false): RenderGeometry | undefined { return undefined; } + public createRealityMeshGeometry(_params: RealityMeshParams, _disableTextureDisposal = false): RenderGeometry | undefined { + return undefined; + } /** @internal */ - public createAreaPattern(_params: PatternGraphicParams): RenderAreaPattern | undefined { return undefined; } + public createAreaPattern(_params: PatternGraphicParams): RenderAreaPattern | undefined { + return undefined; + } /** Create a [[RenderInstances]] from a [[RenderInstancesParams]], to be supplied to [[createGraphicFromTemplate]] via [[CreateGraphicFromTempalateArgs.instances]]. * @beta */ - public createRenderInstances(_params: RenderInstancesParams): RenderInstances | undefined { return undefined; } + public createRenderInstances(_params: RenderInstancesParams): RenderInstances | undefined { + return undefined; + } /** Creates a graphic that draws any number of repetitions of a [[GraphicTemplate]]. * @beta @@ -497,7 +563,8 @@ export abstract class RenderSystem implements IDisposable { private createGraphicFromGeometry( createGeometry: (viewIndependentOrigin?: Point3d) => RenderGeometry | undefined, - instancesOrOrigin?: InstancedGraphicParams | RenderAreaPattern | Point3d): RenderGraphic | undefined { + instancesOrOrigin?: InstancedGraphicParams | RenderAreaPattern | Point3d, + ): RenderGraphic | undefined { let viOrigin; let instances; if (instancesOrOrigin instanceof Point3d) @@ -530,7 +597,9 @@ export abstract class RenderSystem implements IDisposable { } /** @internal */ - public createRealityMeshGraphic(_params: RealityMeshGraphicParams, _disableTextureDisposal = false): RenderGraphic | undefined { return undefined; } + public createRealityMeshGraphic(_params: RealityMeshGraphicParams, _disableTextureDisposal = false): RenderGraphic | undefined { + return undefined; + } /** @internal */ public createRealityMesh(realityMesh: RealityMeshParams, disableTextureDisposal = false): RenderGraphic | undefined { const geom = this.createRealityMeshGeometry(realityMesh, disableTextureDisposal); @@ -538,7 +607,9 @@ export abstract class RenderSystem implements IDisposable { } /** @internal */ - public get maxRealityImageryLayers() { return 0; } + public get maxRealityImageryLayers() { + return 0; + } /** @internal */ public createPointCloud(args: PointCloudArgs, _imodel: IModelConnection): RenderGraphic | undefined { const geom = this.createPointCloudGeometry(args); @@ -550,12 +621,18 @@ export abstract class RenderSystem implements IDisposable { * @param _clipVector Defines how the volume clips geometry. * @returns A clip volume, or undefined if, e.g., the clip vector does not clip anything. */ - public createClipVolume(_clipVector: ClipVector): RenderClipVolume | undefined { return undefined; } + public createClipVolume(_clipVector: ClipVector): RenderClipVolume | undefined { + return undefined; + } /** @internal */ - public createPlanarGrid(_frustum: Frustum, _grid: PlanarGridProps): RenderGraphic | undefined { return undefined; } + public createPlanarGrid(_frustum: Frustum, _grid: PlanarGridProps): RenderGraphic | undefined { + return undefined; + } /** @internal */ - public createBackgroundMapDrape(_drapedTree: TileTreeReference, _mapTree: MapTileTreeReference): RenderTextureDrape | undefined { return undefined; } + public createBackgroundMapDrape(_drapedTree: TileTreeReference, _mapTree: MapTileTreeReference): RenderTextureDrape | undefined { + return undefined; + } /** @internal */ public createTile(tileTexture: RenderTexture, corners: Point3d[], featureIndex?: number): RenderGraphic | undefined { // corners @@ -604,7 +681,9 @@ export abstract class RenderSystem implements IDisposable { /** Create a Graphic for a [[SkyBox]] which encompasses the entire scene, rotating with the camera. * @internal */ - public createSkyBox(_params: RenderSkyBoxParams): RenderGraphic | undefined { return undefined; } + public createSkyBox(_params: RenderSkyBoxParams): RenderGraphic | undefined { + return undefined; + } /** Create a RenderGraphic consisting of a list of Graphics to be drawn together. */ public abstract createGraphicList(primitives: RenderGraphic[]): RenderGraphic; @@ -633,12 +712,21 @@ export abstract class RenderSystem implements IDisposable { * @param range A volume fully encompassing the batch's geometry. * @param options Options customizing the behavior of the batch. */ - public abstract createBatch(graphic: RenderGraphic, features: RenderFeatureTable, range: ElementAlignedBox3d, options?: BatchOptions): RenderGraphic; + public abstract createBatch( + graphic: RenderGraphic, + features: RenderFeatureTable, + range: ElementAlignedBox3d, + options?: BatchOptions, + ): RenderGraphic; /** Return a Promise which when resolved indicates that all pending external textures have finished loading from the backend. */ - public async waitForAllExternalTextures(): Promise { return Promise.resolve(); } + public async waitForAllExternalTextures(): Promise { + return Promise.resolve(); + } /** @internal */ - public get hasExternalTextureRequests(): boolean { return false; } + public get hasExternalTextureRequests(): boolean { + return false; + } /** Create a graphic that assumes ownership of another graphic. * @param ownedGraphic The RenderGraphic to be owned. @@ -646,7 +734,9 @@ export abstract class RenderSystem implements IDisposable { * @see [[RenderGraphicOwner]] for details regarding ownership semantics. * @public */ - public createGraphicOwner(ownedGraphic: RenderGraphic): RenderGraphicOwner { return new GraphicOwner(ownedGraphic); } + public createGraphicOwner(ownedGraphic: RenderGraphic): RenderGraphicOwner { + return new GraphicOwner(ownedGraphic); + } /** Create a "layer" containing the graphics belonging to it. A layer has a unique identifier and all of its geometry lies in an XY plane. * Different layers can be drawn coincident with one another; their draw order can be controlled by a per-layer priority value so that one layer draws @@ -655,12 +745,16 @@ export abstract class RenderSystem implements IDisposable { * @see [[createGraphicLayerContainer]] * @internal */ - public createGraphicLayer(graphic: RenderGraphic, _layerId: string): RenderGraphic { return graphic; } + public createGraphicLayer(graphic: RenderGraphic, _layerId: string): RenderGraphic { + return graphic; + } /** Create a graphic that can contain [[GraphicLayer]]s. * @internal */ - public createGraphicLayerContainer(graphic: RenderGraphic, _drawAsOverlay: boolean, _transparency: number, _elevation: number): RenderGraphic { return graphic; } + public createGraphicLayerContainer(graphic: RenderGraphic, _drawAsOverlay: boolean, _transparency: number, _elevation: number): RenderGraphic { + return graphic; + } /** Find a previously-created [[RenderTexture]] by its key. * @param _key The unique key of the texture within the context of the IModelConnection. Typically an element Id. @@ -712,7 +806,10 @@ export abstract class RenderSystem implements IDisposable { return undefined; const textureProps = elemProps[0] as TextureProps; - if (undefined === textureProps.data || "string" !== typeof (textureProps.data) || undefined === textureProps.format || "number" !== typeof (textureProps.format)) + if ( + undefined === textureProps.data || "string" !== typeof (textureProps.data) || undefined === textureProps.format || + "number" !== typeof (textureProps.format) + ) return undefined; const format = textureProps.format; @@ -756,7 +853,12 @@ export abstract class RenderSystem implements IDisposable { * @deprecated in 3.x. Use [[createTexture]]. */ // eslint-disable-next-line deprecation/deprecation - public createTextureFromImage(image: HTMLImageElement, hasAlpha: boolean, iModel: IModelConnection | undefined, params: RenderTexture.Params): RenderTexture | undefined { + public createTextureFromImage( + image: HTMLImageElement, + hasAlpha: boolean, + iModel: IModelConnection | undefined, + params: RenderTexture.Params, + ): RenderTexture | undefined { const ownership = params.key && iModel ? { key: params.key, iModel } : (params.isOwned ? "external" : undefined); return this.createTexture({ type: params.type, @@ -772,7 +874,11 @@ export abstract class RenderSystem implements IDisposable { * @deprecated in 3.x. Use RenderSystem.createTextureFromSource. */ // eslint-disable-next-line deprecation/deprecation - public async createTextureFromImageSource(source: ImageSource, iModel: IModelConnection | undefined, params: RenderTexture.Params): Promise { + public async createTextureFromImageSource( + source: ImageSource, + iModel: IModelConnection | undefined, + params: RenderTexture.Params, + ): Promise { const ownership = iModel && params.key ? { iModel, key: params.key } : (params.isOwned ? "external" : undefined); return this.createTextureFromSource({ type: params.type, @@ -786,7 +892,9 @@ export abstract class RenderSystem implements IDisposable { public async createTextureFromSource(args: CreateTextureFromSourceArgs): Promise { try { // JPEGs don't support transparency. - const transparency = ImageSourceFormat.Jpeg === args.source.format ? TextureTransparency.Opaque : (args.transparency ?? TextureTransparency.Mixed); + const transparency = ImageSourceFormat.Jpeg === args.source.format + ? TextureTransparency.Opaque + : (args.transparency ?? TextureTransparency.Mixed); const image = await imageElementFromImageSource(args.source); if (!IModelApp.hasRenderSystem) return undefined; @@ -806,7 +914,12 @@ export abstract class RenderSystem implements IDisposable { /** Create a new texture by its element ID. This texture will be retrieved asynchronously from the backend. A placeholder image will be associated with the texture until the requested image data loads. */ // eslint-disable-next-line deprecation/deprecation - public createTextureFromElement(_id: Id64String, _imodel: IModelConnection, _params: RenderTexture.Params, _format: ImageSourceFormat): RenderTexture | undefined { + public createTextureFromElement( + _id: Id64String, + _imodel: IModelConnection, + _params: RenderTexture.Params, + _format: ImageSourceFormat, + ): RenderTexture | undefined { return undefined; } @@ -818,26 +931,39 @@ export abstract class RenderSystem implements IDisposable { * @internal */ // eslint-disable-next-line deprecation/deprecation - public createTextureFromCubeImages(_posX: HTMLImageElement, _negX: HTMLImageElement, _posY: HTMLImageElement, _negY: HTMLImageElement, _posZ: HTMLImageElement, _negZ: HTMLImageElement, _imodel: IModelConnection, _params: RenderTexture.Params): RenderTexture | undefined { + public createTextureFromCubeImages( + _posX: HTMLImageElement, + _negX: HTMLImageElement, + _posY: HTMLImageElement, + _negY: HTMLImageElement, + _posZ: HTMLImageElement, + _negZ: HTMLImageElement, + _imodel: IModelConnection, + _params: RenderTexture.Params, + ): RenderTexture | undefined { return undefined; } /** @internal */ - public onInitialized(): void { } + public onInitialized(): void {} /** @internal */ - public enableDiagnostics(_enable: RenderDiagnostics): void { } + public enableDiagnostics(_enable: RenderDiagnostics): void {} /** @internal */ - public get supportsLogZBuffer(): boolean { return false !== this.options.logarithmicDepthBuffer; } + public get supportsLogZBuffer(): boolean { + return false !== this.options.logarithmicDepthBuffer; + } /** Obtain an object that can be used to control various debugging features. Returns `undefined` if debugging features are unavailable for this `RenderSystem`. * @beta */ - public get debugControl(): RenderSystemDebugControl | undefined { return undefined; } + public get debugControl(): RenderSystemDebugControl | undefined { + return undefined; + } /** @internal */ - public collectStatistics(_stats: RenderMemory.Statistics): void { } + public collectStatistics(_stats: RenderMemory.Statistics): void {} /** A function that is invoked after the WebGL context is lost. Context loss is almost always caused by excessive consumption of GPU memory. * After context loss occurs, the RenderSystem will be unable to interact with WebGL by rendering viewports, creating graphics and textures, etc. diff --git a/core/frontend/src/render/RenderTarget.ts b/core/frontend/src/render/RenderTarget.ts index 63e8c552973a..538184575893 100644 --- a/core/frontend/src/render/RenderTarget.ts +++ b/core/frontend/src/render/RenderTarget.ts @@ -9,11 +9,13 @@ import { Id64String, IDisposable } from "@itwin/core-bentley"; import { Frustum, ImageBuffer } from "@itwin/core-common"; import { Point2d, XAndY } from "@itwin/core-geometry"; +import { _implementationProhibited } from "../common/internal/Symbols"; +import { ViewRect } from "../common/ViewRect"; import { IModelConnection } from "../IModelConnection"; import { HiliteSet } from "../SelectionSet"; +import { ActiveSpatialClassifier } from "../SpatialClassifiersState"; import { SceneContext } from "../ViewContext"; import { ReadImageBufferArgs, Viewport } from "../Viewport"; -import { ViewRect } from "../common/ViewRect"; import { CanvasDecoration } from "./CanvasDecoration"; import { Decorations } from "./Decorations"; import { FeatureSymbology } from "./FeatureSymbology"; @@ -28,8 +30,6 @@ import { RenderPlanarClassifier } from "./RenderPlanarClassifier"; import { RenderSystem, RenderTextureDrape } from "./RenderSystem"; import { Scene } from "./Scene"; import { QueryTileFeaturesOptions, QueryVisibleFeaturesCallback } from "./VisibleFeature"; -import { ActiveSpatialClassifier } from "../SpatialClassifiersState"; -import { _implementationProhibited } from "../common/internal/Symbols"; /** Used for debugging purposes, to toggle display of instanced or batched primitives. * @see [[RenderTargetDebugControl]]. @@ -80,7 +80,9 @@ export abstract class RenderTarget implements IDisposable, RenderMemory.Consumer protected abstract readonly [_implementationProhibited]: unknown; /** @internal */ - public pickOverlayDecoration(_pt: XAndY): CanvasDecoration | undefined { return undefined; } + public pickOverlayDecoration(_pt: XAndY): CanvasDecoration | undefined { + return undefined; + } /** @internal */ public abstract get renderSystem(): RenderSystem; @@ -90,7 +92,9 @@ export abstract class RenderTarget implements IDisposable, RenderMemory.Consumer public abstract get viewRect(): ViewRect; /** @internal */ - public get devicePixelRatio(): number { return 1; } + public get devicePixelRatio(): number { + return 1; + } /** @internal */ public cssPixelsToDevicePixels(cssPixels: number, floor = true): number { const pix = cssPixels * this.devicePixelRatio; @@ -113,25 +117,35 @@ export abstract class RenderTarget implements IDisposable, RenderMemory.Consumer public abstract set analysisFraction(fraction: number); /** @internal */ - public get animationBranches(): AnimationBranchStates | undefined { return undefined; } - public set animationBranches(_transforms: AnimationBranchStates | undefined) { } + public get animationBranches(): AnimationBranchStates | undefined { + return undefined; + } + public set animationBranches(_transforms: AnimationBranchStates | undefined) {} /** @internal */ - public get antialiasSamples(): number { return 1; } - public set antialiasSamples(_numSamples: number) { } + public get antialiasSamples(): number { + return 1; + } + public set antialiasSamples(_numSamples: number) {} /** @internal */ - public assignFrameStatsCollector(_collector: FrameStatsCollector) { } + public assignFrameStatsCollector(_collector: FrameStatsCollector) {} /** Update the solar shadow map. If a SceneContext is supplied, shadows are enabled; otherwise, shadows are disabled. */ /** @internal */ - public updateSolarShadows(_context: SceneContext | undefined): void { } + public updateSolarShadows(_context: SceneContext | undefined): void {} /** @internal */ - public getPlanarClassifier(_id: string): RenderPlanarClassifier | undefined { return undefined; } + public getPlanarClassifier(_id: string): RenderPlanarClassifier | undefined { + return undefined; + } /** @internal */ - public createPlanarClassifier(_properties?: ActiveSpatialClassifier): RenderPlanarClassifier | undefined { return undefined; } + public createPlanarClassifier(_properties?: ActiveSpatialClassifier): RenderPlanarClassifier | undefined { + return undefined; + } /** @internal */ - public getTextureDrape(_id: Id64String): RenderTextureDrape | undefined { return undefined; } + public getTextureDrape(_id: Id64String): RenderTextureDrape | undefined { + return undefined; + } /** @internal */ public createGraphicBuilder(options: CustomGraphicBuilderOptions | ViewportGraphicBuilderOptions) { @@ -139,9 +153,9 @@ export abstract class RenderTarget implements IDisposable, RenderMemory.Consumer } /** @internal */ - public dispose(): void { } + public dispose(): void {} /** @internal */ - public reset(): void { } + public reset(): void {} /** @internal */ public abstract changeScene(scene: Scene): void; /** @internal */ @@ -153,42 +167,58 @@ export abstract class RenderTarget implements IDisposable, RenderMemory.Consumer /** @internal */ public abstract drawFrame(sceneMilSecElapsed?: number): void; /** @internal */ - public overrideFeatureSymbology(_ovr: FeatureSymbology.Overrides): void { } + public overrideFeatureSymbology(_ovr: FeatureSymbology.Overrides): void {} /** @internal */ - public setHiliteSet(_hilited: HiliteSet): void { } + public setHiliteSet(_hilited: HiliteSet): void {} /** @internal */ - public setFlashed(_elementId: Id64String, _intensity: number): void { } + public setFlashed(_elementId: Id64String, _intensity: number): void {} /** @internal */ - public onBeforeRender(_viewport: Viewport, _setSceneNeedRedraw: (redraw: boolean) => void): void { } + public onBeforeRender(_viewport: Viewport, _setSceneNeedRedraw: (redraw: boolean) => void): void {} /** @internal */ public abstract setViewRect(_rect: ViewRect, _temporary: boolean): void; /** @internal */ - public onResized(): void { } + public onResized(): void {} /** @internal */ public abstract updateViewRect(): boolean; // force a RenderTarget viewRect to resize if necessary since last draw /** `rect` is specified in *CSS* pixels. */ /** @internal */ - public abstract readPixels(rect: ViewRect, selector: Pixel.Selector, receiver: Pixel.Receiver, excludeNonLocatable: boolean, excludedElements?: Iterable): void; + public abstract readPixels( + rect: ViewRect, + selector: Pixel.Selector, + receiver: Pixel.Receiver, + excludeNonLocatable: boolean, + excludedElements?: Iterable, + ): void; /** @deprecated in 3.x. use readImageBuffer * @internal */ - public readImage(_rect: ViewRect, _targetSize: Point2d, _flipVertically: boolean): ImageBuffer | undefined { return undefined; } + public readImage(_rect: ViewRect, _targetSize: Point2d, _flipVertically: boolean): ImageBuffer | undefined { + return undefined; + } /** @internal */ - public readImageBuffer(_args?: ReadImageBufferArgs): ImageBuffer | undefined { return undefined; } + public readImageBuffer(_args?: ReadImageBufferArgs): ImageBuffer | undefined { + return undefined; + } /** @internal */ - public readImageToCanvas(): HTMLCanvasElement { return document.createElement("canvas"); } + public readImageToCanvas(): HTMLCanvasElement { + return document.createElement("canvas"); + } /** @internal */ - public collectStatistics(_stats: RenderMemory.Statistics): void { } + public collectStatistics(_stats: RenderMemory.Statistics): void {} /** Specify whether webgl content should be rendered directly to the screen. * If rendering to screen becomes enabled, returns the canvas to which to render the webgl content. * Returns undefined if rendering to screen becomes disabled, or is not supported by this RenderTarget. */ /** @internal */ - public setRenderToScreen(_toScreen: boolean): HTMLCanvasElement | undefined { return undefined; } + public setRenderToScreen(_toScreen: boolean): HTMLCanvasElement | undefined { + return undefined; + } /** @internal */ - public get debugControl(): RenderTargetDebugControl | undefined { return undefined; } + public get debugControl(): RenderTargetDebugControl | undefined { + return undefined; + } /** An ordered list of names of screen-space post-processing effects to be applied to the image produced by this target. * The effects are applied in the order in which they appear in the list. Any names not corresponding to a registered effect are ignored. diff --git a/core/frontend/src/render/Scene.ts b/core/frontend/src/render/Scene.ts index fb758aa3f357..20eba030dba0 100644 --- a/core/frontend/src/render/Scene.ts +++ b/core/frontend/src/render/Scene.ts @@ -7,10 +7,10 @@ */ import { Id64String } from "@itwin/core-bentley"; +import { ActiveSpatialClassifier } from "../SpatialClassifiersState"; import { RenderGraphic } from "./RenderGraphic"; import { RenderPlanarClassifier } from "./RenderPlanarClassifier"; import { RenderTextureDrape } from "./RenderSystem"; -import { ActiveSpatialClassifier } from "../SpatialClassifiersState"; /** Describes the spatial classification applied to a [[Scene]]. * @internal diff --git a/core/frontend/src/render/UpsampleRealityMeshParams.ts b/core/frontend/src/render/UpsampleRealityMeshParams.ts index ec7611395b14..c15be034bbcf 100644 --- a/core/frontend/src/render/UpsampleRealityMeshParams.ts +++ b/core/frontend/src/render/UpsampleRealityMeshParams.ts @@ -6,12 +6,8 @@ * @module Rendering */ -import { - Range1d, Range2d, Vector3d, -} from "@itwin/core-geometry"; -import { - OctEncodedNormal, QParams2d, QPoint2d, QPoint3d, Quantization, -} from "@itwin/core-common"; +import { OctEncodedNormal, QParams2d, QPoint2d, QPoint3d, Quantization } from "@itwin/core-common"; +import { Range1d, Range2d, Vector3d } from "@itwin/core-geometry"; import { RealityMeshParams, RealityMeshParamsBuilder } from "./RealityMeshParams"; class UpsampleIndexMap extends Map { @@ -35,7 +31,7 @@ export interface UpsampledRealityMeshParams { } class ClipAxis { - constructor(public vertical: boolean, public lessThan: boolean, public value: number) { } + constructor(public vertical: boolean, public lessThan: boolean, public value: number) {} } export function upsampleRealityMeshParams(params: RealityMeshParams, uvSampleRange: Range2d): UpsampledRealityMeshParams { @@ -134,7 +130,11 @@ function interpolateInt(value0: number, value1: number, fraction: number) { } function interpolateQPoint3d(qPoint: QPoint3d, qNext: QPoint3d, fraction: number): QPoint3d { - return QPoint3d.fromScalars(interpolateInt(qPoint.x, qNext.x, fraction), interpolateInt(qPoint.y, qNext.y, fraction), interpolateInt(qPoint.z, qNext.z, fraction)); + return QPoint3d.fromScalars( + interpolateInt(qPoint.x, qNext.x, fraction), + interpolateInt(qPoint.y, qNext.y, fraction), + interpolateInt(qPoint.z, qNext.z, fraction), + ); } function interpolateQPoint2d(qPoint: QPoint2d, qNext: QPoint2d, fraction: number): QPoint2d { @@ -153,7 +153,16 @@ function interpolateOctEncodedNormal(normal0: number, normal1: number, fraction: } } -function addClipped(params: RealityMeshParams, triangleIndices: number[], indexMap: UpsampleIndexMap, clipAxes: ClipAxis[], clipIndex: number, addedPoints: QPoint3d[], addedParams: QPoint2d[], addedNormals: number[]) { +function addClipped( + params: RealityMeshParams, + triangleIndices: number[], + indexMap: UpsampleIndexMap, + clipAxes: ClipAxis[], + clipIndex: number, + addedPoints: QPoint3d[], + addedParams: QPoint2d[], + addedNormals: number[], +) { if (clipIndex === clipAxes.length) { indexMap.addTriangle(triangleIndices); return; @@ -224,7 +233,6 @@ function addClipped(params: RealityMeshParams, triangleIndices: number[], indexM addedParams.push(interpolateQPoint2d(getParam(index, scratchQPoint2d), getParam(nextIndex, scratchQPoint2d1), fraction)); if (parentNormals) addedNormals.push(interpolateOctEncodedNormal(getNormal(index)!, getNormal(nextIndex)!, fraction)); - } } @@ -234,4 +242,3 @@ function addClipped(params: RealityMeshParams, triangleIndices: number[], indexM addClipped(params, [clipOutput[0], clipOutput[2], clipOutput[3]], indexMap, clipAxes, clipIndex, addedPoints, addedParams, addedNormals); } } - diff --git a/core/frontend/src/render/VisibleFeature.ts b/core/frontend/src/render/VisibleFeature.ts index 87eb09f90351..ee3d77a1da33 100644 --- a/core/frontend/src/render/VisibleFeature.ts +++ b/core/frontend/src/render/VisibleFeature.ts @@ -9,8 +9,8 @@ import { assert, Id64String } from "@itwin/core-bentley"; import { GeometryClass } from "@itwin/core-common"; import { ViewRect } from "../common/ViewRect"; -import { Viewport } from "../Viewport"; import { IModelConnection } from "../IModelConnection"; +import { Viewport } from "../Viewport"; import { Pixel } from "./Pixel"; /** Represents a [Feature]($common) determined to be visible within a [[Viewport]]. @@ -149,7 +149,12 @@ export function queryVisibleFeatures(viewport: Viewport, options: QueryVisibleFe switch (options.source) { case "screen": const rect = options.rect ?? viewport.viewRect; - viewport.readPixels(rect, Pixel.Selector.Feature, (pixels) => invokeCallback(pixels ? new ScreenFeatures(pixels, rect, viewport) : [], callback), true !== options.includeNonLocatable); + viewport.readPixels( + rect, + Pixel.Selector.Feature, + (pixels) => invokeCallback(pixels ? new ScreenFeatures(pixels, rect, viewport) : [], callback), + true !== options.includeNonLocatable, + ); break; case "tiles": viewport.target.queryVisibleTileFeatures(options, viewport.iModel, (features) => invokeCallback(features, callback)); diff --git a/core/frontend/src/render/webgl/AtmosphereUniforms.ts b/core/frontend/src/render/webgl/AtmosphereUniforms.ts index 6dae852e3711..aa147e5255fb 100644 --- a/core/frontend/src/render/webgl/AtmosphereUniforms.ts +++ b/core/frontend/src/render/webgl/AtmosphereUniforms.ts @@ -29,7 +29,9 @@ export class AtmosphereUniforms implements WebGLDisposable, SyncTarget { * { earthCenter.x, earthCenter.y, earthCenter.z, 0 }, * { scatteringCoefficients.x, scatteringCoefficients.y, scatteringCoefficients.z, 0 } } */ - public get atmosphereData() { return this._atmosphereData; } + public get atmosphereData() { + return this._atmosphereData; + } // Fragment shader uniforms private _exposure = 0.0; @@ -179,5 +181,5 @@ export class AtmosphereUniforms implements WebGLDisposable, SyncTarget { return true; } - public dispose() { } + public dispose() {} } diff --git a/core/frontend/src/render/webgl/AttributeBuffers.ts b/core/frontend/src/render/webgl/AttributeBuffers.ts index 54b68d24905e..d331dd59700e 100644 --- a/core/frontend/src/render/webgl/AttributeBuffers.ts +++ b/core/frontend/src/render/webgl/AttributeBuffers.ts @@ -7,21 +7,21 @@ */ import { assert } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { QParams2d, QParams3d } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { WebGLDisposable } from "./Disposable"; import { GL } from "./GL"; import { System } from "./System"; /** Describes a connection between a BufferHandle and an arbitrary number of attributes associated with that BufferHandle. */ -interface BufferHandleLinkage { // eslint-disable-line @typescript-eslint/no-unsafe-declaration-merging +interface BufferHandleLinkage { // eslint-disable-line @typescript-eslint/no-unsafe-declaration-merging buffer: BufferHandle; params: BufferParameters[]; // If empty, means no vertex attrib details are necessary (index buffer probably) } /** Provides convenience methods for creating a BufferHandleLinkage interface. */ -class BufferHandleLinkage { // eslint-disable-line @typescript-eslint/no-unsafe-declaration-merging - private constructor() { } +class BufferHandleLinkage { // eslint-disable-line @typescript-eslint/no-unsafe-declaration-merging + private constructor() {} public static create(buffer: BufferHandle, params: BufferParameters[]): BufferHandleLinkage { return { buffer, params }; } @@ -60,12 +60,28 @@ export interface BufferParameters { * @internal */ export namespace BufferParameters { - export function create(glAttribLoc: number, glSize: number, glType: number, glNormalized: boolean, glStride: number, glOffset: number, glInstanced: boolean): BufferParameters { + export function create( + glAttribLoc: number, + glSize: number, + glType: number, + glNormalized: boolean, + glStride: number, + glOffset: number, + glInstanced: boolean, + ): BufferParameters { return { glAttribLoc, glSize, glType, glNormalized, glStride, glOffset, glInstanced }; } export function clone(params: BufferParameters): BufferParameters { - return BufferParameters.create(params.glAttribLoc, params.glSize, params.glType, params.glNormalized, params.glStride, params.glOffset, params.glInstanced); + return BufferParameters.create( + params.glAttribLoc, + params.glSize, + params.glType, + params.glNormalized, + params.glStride, + params.glOffset, + params.glInstanced, + ); } } @@ -154,7 +170,9 @@ export class VAOHandle implements WebGLDisposable { assert(!this.isDisposed); } - public get isDisposed(): boolean { return this._arrayObject === undefined; } + public get isDisposed(): boolean { + return this._arrayObject === undefined; + } /** Frees the WebGL vertex array object */ public dispose(): void { @@ -202,8 +220,12 @@ export class BufferHandle implements WebGLDisposable { assert(!this.isDisposed); } - public get isDisposed(): boolean { return this._glBuffer === undefined; } - public get bytesUsed(): number { return this._bytesUsed; } + public get isDisposed(): boolean { + return this._glBuffer === undefined; + } + public get bytesUsed(): number { + return this._bytesUsed; + } /** Frees the WebGL buffer */ public dispose(): void { @@ -222,7 +244,9 @@ export class BufferHandle implements WebGLDisposable { } /** Sets the specified target to be bound to no buffer */ - public unbind(): void { System.instance.context.bindBuffer(this._target, null); } + public unbind(): void { + System.instance.context.bindBuffer(this._target, null); + } /** Binds this buffer to the target specified at construction and sets the buffer's data store. */ public bindData(data: BufferSource, usage: GL.Buffer.Usage = GL.Buffer.Usage.StaticDraw): void { @@ -233,7 +257,11 @@ export class BufferHandle implements WebGLDisposable { } /** Creates a BufferHandle and binds its data */ - public static createBuffer(target: GL.Buffer.Target, data: BufferSource, usage: GL.Buffer.Usage = GL.Buffer.Usage.StaticDraw): BufferHandle | undefined { + public static createBuffer( + target: GL.Buffer.Target, + data: BufferSource, + usage: GL.Buffer.Usage = GL.Buffer.Usage.StaticDraw, + ): BufferHandle | undefined { const handle = new BufferHandle(target); if (handle.isDisposed) { return undefined; @@ -247,7 +275,9 @@ export class BufferHandle implements WebGLDisposable { return BufferHandle.createBuffer(GL.Buffer.Target.ArrayBuffer, data, usage); } - public isBound(binding: GL.Buffer.Binding) { return System.instance.context.getParameter(binding) === this._glBuffer; } + public isBound(binding: GL.Buffer.Binding) { + return System.instance.context.getParameter(binding) === this._glBuffer; + } } function setScale(index: number, value: number, array: Float32Array) { diff --git a/core/frontend/src/render/webgl/BackgroundMapDrape.ts b/core/frontend/src/render/webgl/BackgroundMapDrape.ts index 28cdf6cad26b..847bd9414549 100644 --- a/core/frontend/src/render/webgl/BackgroundMapDrape.ts +++ b/core/frontend/src/render/webgl/BackgroundMapDrape.ts @@ -8,8 +8,8 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { Matrix4d, Plane3dByOriginAndUnitNormal, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { ColorDef, Frustum, FrustumPlanes, RenderTexture, TextureTransparency } from "@itwin/core-common"; +import { Matrix4d, Plane3dByOriginAndUnitNormal, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { GraphicsCollectorDrawArgs, MapTileTreeReference, TileTreeReference } from "../../tile/internal"; import { SceneContext } from "../../ViewContext"; import { ViewState3d } from "../../ViewState"; @@ -37,10 +37,23 @@ export class BackgroundMapDrape extends TextureDrape { private _mapTree: MapTileTreeReference; private _drapedTree: TileTreeReference; private static _postProjectionMatrix = Matrix4d.createRowValues( - 0, 1, 0, 0, - 0, 0, -1, 0, - 1, 0, 0, 0, - 0, 0, 0, 1); + 0, + 1, + 0, + 0, + 0, + 0, + -1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ); private _debugFrustum?: Frustum; private _debugFrustumGraphic?: RenderGraphic = undefined; private readonly _symbologyOverrides = new FeatureSymbology.Overrides(); @@ -53,7 +66,9 @@ export class BackgroundMapDrape extends TextureDrape { this._mapTree = mapTree; } - public override get isDisposed(): boolean { return super.isDisposed && undefined === this._fbo; } + public override get isDisposed(): boolean { + return super.isDisposed && undefined === this._fbo; + } public override dispose() { super.dispose(); @@ -81,7 +96,7 @@ export class BackgroundMapDrape extends TextureDrape { if (undefined === tileTree || !this._mapTree.initializeLayers(context)) return; - const requiredWidth = 2 * Math.max(context.target.viewRect.width, context.target.viewRect.height); // TBD - Size to textured area. + const requiredWidth = 2 * Math.max(context.target.viewRect.width, context.target.viewRect.height); // TBD - Size to textured area. const requiredHeight = requiredWidth; if (requiredWidth !== this._width || requiredHeight !== this._height) @@ -97,7 +112,16 @@ export class BackgroundMapDrape extends TextureDrape { const targetTiles = targetTree.selectTiles(args); - const projection = PlanarTextureProjection.computePlanarTextureProjection(this._plane, context, { tiles: targetTiles, location: args.location }, [this._mapTree], viewState, this._width, this._height, Range3d.createNull()); + const projection = PlanarTextureProjection.computePlanarTextureProjection( + this._plane, + context, + { tiles: targetTiles, location: args.location }, + [this._mapTree], + viewState, + this._width, + this._height, + Range3d.createNull(), + ); if (!projection.textureFrustum || !projection.projectionMatrix || !projection.worldToViewMap) return; @@ -105,7 +129,13 @@ export class BackgroundMapDrape extends TextureDrape { this._debugFrustum = projection.debugFrustum; this._projectionMatrix = projection.projectionMatrix; - const drawArgs = GraphicsCollectorDrawArgs.create(context, this, this._mapTree, FrustumPlanes.fromFrustum(this._frustum), projection.worldToViewMap); + const drawArgs = GraphicsCollectorDrawArgs.create( + context, + this, + this._mapTree, + FrustumPlanes.fromFrustum(this._frustum), + projection.worldToViewMap, + ); if (undefined !== drawArgs) tileTree.draw(drawArgs); @@ -130,13 +160,23 @@ export class BackgroundMapDrape extends TextureDrape { return; if (undefined === this._fbo) { - const colorTextureHandle = TextureHandle.createForAttachment(this._width, this._height, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte); + const colorTextureHandle = TextureHandle.createForAttachment( + this._width, + this._height, + GL.Texture.Format.Rgba, + GL.Texture.DataType.UnsignedByte, + ); if (undefined === colorTextureHandle) { assert(false, "Failed to create planar texture"); return; } - this._texture = new Texture({ ownership: "external", type: RenderTexture.Type.TileSection, handle: colorTextureHandle, transparency: TextureTransparency.Opaque }); + this._texture = new Texture({ + ownership: "external", + type: RenderTexture.Type.TileSection, + handle: colorTextureHandle, + transparency: TextureTransparency.Opaque, + }); this._fbo = FrameBuffer.create([colorTextureHandle]); } if (undefined === this._fbo) { @@ -175,12 +215,12 @@ export class BackgroundMapDrape extends TextureDrape { system.frameBufferStack.execute(this._fbo, true, false, () => { gl.clearColor(0, 0, 0, 0); gl.clear(GL.BufferBit.Color); - target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaqueGeneral), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. + target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaqueGeneral), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. }); target.uniforms.branch.pop(); - batchState.reset(); // Reset the batch Ids... + batchState.reset(); // Reset the batch Ids... target.changeRenderPlan(prevPlan); system.applyRenderState(prevState); diff --git a/core/frontend/src/render/webgl/BatchState.ts b/core/frontend/src/render/webgl/BatchState.ts index e5e2a7be442b..724c66c71c12 100644 --- a/core/frontend/src/render/webgl/BatchState.ts +++ b/core/frontend/src/render/webgl/BatchState.ts @@ -36,10 +36,18 @@ export class BatchState { this._stack = stack; } - public get currentBatch(): Batch | undefined { return this._curBatch; } - public get currentBatchId(): number { return undefined !== this._curBatch ? this._curBatch.batchId : 0; } - public get currentBatchIModel(): IModelConnection | undefined { return undefined !== this._curBatch ? this._curBatch.batchIModel : undefined; } - public get isEmpty(): boolean { return 0 === this._batches.length; } + public get currentBatch(): Batch | undefined { + return this._curBatch; + } + public get currentBatchId(): number { + return undefined !== this._curBatch ? this._curBatch.batchId : 0; + } + public get currentBatchIModel(): IModelConnection | undefined { + return undefined !== this._curBatch ? this._curBatch.batchIModel : undefined; + } + public get isEmpty(): boolean { + return 0 === this._batches.length; + } public push(batch: Batch, allowAdd: boolean): void { assert(undefined === this.currentBatch, "batches cannot nest"); @@ -85,8 +93,12 @@ export class BatchState { return batch.featureTable.findFeature(featureIndex, result); } - public get numFeatureIds() { return this.nextBatchId; } - public get numBatches() { return this._batches.length; } + public get numFeatureIds() { + return this.nextBatchId; + } + public get numBatches() { + return this._batches.length; + } public findBatchId(featureId: number) { const batch = this.find(featureId); diff --git a/core/frontend/src/render/webgl/BatchUniforms.ts b/core/frontend/src/render/webgl/BatchUniforms.ts index 599f4cbe5fe9..d9206763afcb 100644 --- a/core/frontend/src/render/webgl/BatchUniforms.ts +++ b/core/frontend/src/render/webgl/BatchUniforms.ts @@ -6,16 +6,16 @@ * @module WebGL */ +import { OvrFlags } from "../../common/internal/render/OvrFlags"; import { BatchState } from "./BatchState"; +import { Contours } from "./Contours"; import { FeatureOverrides } from "./FeatureOverrides"; import { Batch } from "./Graphic"; -import { UniformHandle } from "./UniformHandle"; import { desync, sync } from "./Sync"; import { Target } from "./Target"; import { FeatureMode } from "./TechniqueFlags"; import { ThematicSensors } from "./ThematicSensors"; -import { Contours } from "./Contours"; -import { OvrFlags } from "../../common/internal/render/OvrFlags"; +import { UniformHandle } from "./UniformHandle"; const scratchRgb = new Float32Array(3); const noOverrideRgb = new Float32Array([-1.0, -1.0, -1.0]); @@ -82,7 +82,9 @@ export class BatchUniforms { this.state.reset(); } - public get featureMode(): FeatureMode { return this._featureMode; } + public get featureMode(): FeatureMode { + return this._featureMode; + } public bindNumThematicSensors(uniform: UniformHandle): void { if (undefined !== this._sensors) @@ -166,7 +168,7 @@ export class BatchUniforms { if (undefined !== this._overrides) { const uo = this._overrides.getUniformOverrides(); if (uo[0] & OvrFlags.Alpha) { - uniform.setUniform1f(uo[7]/255.0); + uniform.setUniform1f(uo[7] / 255.0); } else { uniform.setUniform1f(-1.0); } diff --git a/core/frontend/src/render/webgl/BranchStack.ts b/core/frontend/src/render/webgl/BranchStack.ts index 4c7f6907005c..12efb0afa25b 100644 --- a/core/frontend/src/render/webgl/BranchStack.ts +++ b/core/frontend/src/render/webgl/BranchStack.ts @@ -7,12 +7,12 @@ */ import { assert } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { HiddenLine, ViewFlags } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; import { FeatureSymbology } from "../FeatureSymbology"; import { BranchState } from "./BranchState"; -import { Branch } from "./Graphic"; import { EdgeSettings } from "./EdgeSettings"; +import { Branch } from "./Graphic"; /** * Represents the current state of the scene graph. As the scene graph is traversed, @@ -47,8 +47,12 @@ export class BranchStack { return this._stack[0]; } - public get length() { return this._stack.length; } - public get empty() { return 0 === this.length; } + public get length() { + return this._stack.length; + } + public get empty() { + return 0 === this.length; + } public pushBranch(branch: Branch): void { assert(this.length > 0); diff --git a/core/frontend/src/render/webgl/BranchState.ts b/core/frontend/src/render/webgl/BranchState.ts index 08159b738c32..7554f7de067f 100644 --- a/core/frontend/src/render/webgl/BranchState.ts +++ b/core/frontend/src/render/webgl/BranchState.ts @@ -7,17 +7,24 @@ */ import { Id64String } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { - BatchType, FeatureAppearance, FeatureAppearanceProvider, GeometryClass, HiddenLine, RealityModelDisplaySettings, RenderMode, ViewFlags, + BatchType, + FeatureAppearance, + FeatureAppearanceProvider, + GeometryClass, + HiddenLine, + RealityModelDisplaySettings, + RenderMode, + ViewFlags, } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; import { IModelConnection } from "../../IModelConnection"; import { FeatureSymbology } from "../FeatureSymbology"; import { ClipVolume } from "./ClipVolume"; +import { EdgeSettings } from "./EdgeSettings"; import { Branch } from "./Graphic"; import { PlanarClassifier } from "./PlanarClassifier"; import { TextureDrape } from "./TextureDrape"; -import { EdgeSettings } from "./EdgeSettings"; /** Options used to construct a BranchState. * @internal @@ -60,24 +67,60 @@ export interface BranchStateOptions { export class BranchState { private readonly _opts: BranchStateOptions; - public get transform() { return this._opts.transform; } - public get viewFlags() { return this._opts.viewFlags; } - public set viewFlags(vf: ViewFlags) { this._opts.viewFlags = vf.normalize(); } - public get clipVolume() { return this._opts.clipVolume; } - public get forceViewCoords(): boolean { return true === this._opts.forceViewCoords; } - public get planarClassifier() { return this._opts.planarClassifier; } - public get textureDrape() { return this._opts.textureDrape; } - public get edgeSettings() { return this._opts.edgeSettings; } - public get iModel() { return this._opts.iModel; } - public get transformFromIModel() { return this._opts.transformFromIModel; } - public get is3d() { return this._opts.is3d; } - public get frustumScale() { return this._opts.frustumScale!; } - public get appearanceProvider() { return this._opts.appearanceProvider; } - public get secondaryClassifiers() { return this._opts.secondaryClassifiers; } - public get realityModelDisplaySettings() { return this._opts.realityModelDisplaySettings; } - public get viewAttachmentId() { return this._opts.viewAttachmentId; } - public get groupNodeId() { return this._opts.groupNodeId; } - public get disableClipStyle() { return this._opts.disableClipStyle;} + public get transform() { + return this._opts.transform; + } + public get viewFlags() { + return this._opts.viewFlags; + } + public set viewFlags(vf: ViewFlags) { + this._opts.viewFlags = vf.normalize(); + } + public get clipVolume() { + return this._opts.clipVolume; + } + public get forceViewCoords(): boolean { + return true === this._opts.forceViewCoords; + } + public get planarClassifier() { + return this._opts.planarClassifier; + } + public get textureDrape() { + return this._opts.textureDrape; + } + public get edgeSettings() { + return this._opts.edgeSettings; + } + public get iModel() { + return this._opts.iModel; + } + public get transformFromIModel() { + return this._opts.transformFromIModel; + } + public get is3d() { + return this._opts.is3d; + } + public get frustumScale() { + return this._opts.frustumScale!; + } + public get appearanceProvider() { + return this._opts.appearanceProvider; + } + public get secondaryClassifiers() { + return this._opts.secondaryClassifiers; + } + public get realityModelDisplaySettings() { + return this._opts.realityModelDisplaySettings; + } + public get viewAttachmentId() { + return this._opts.viewAttachmentId; + } + public get groupNodeId() { + return this._opts.groupNodeId; + } + public get disableClipStyle() { + return this._opts.disableClipStyle; + } public get symbologyOverrides() { return this._opts.symbologyOverrides; @@ -100,14 +143,16 @@ export class BranchState { symbologyOverrides: branch.branch.symbologyOverrides ?? prev.symbologyOverrides, iModel: branch.iModel ?? prev.iModel, transformFromIModel: branch.transformFromExternalIModel ?? prev.transformFromIModel, - planarClassifier: (undefined !== branch.planarClassifier && undefined !== branch.planarClassifier.texture) ? branch.planarClassifier : prev.planarClassifier, + planarClassifier: (undefined !== branch.planarClassifier && undefined !== branch.planarClassifier.texture) + ? branch.planarClassifier + : prev.planarClassifier, textureDrape: branch.textureDrape ?? prev.textureDrape, clipVolume: branch.clips, forceViewCoords: prev.forceViewCoords, edgeSettings: branch.edgeSettings ?? prev.edgeSettings, is3d: branch.frustum?.is3d ?? prev.is3d, frustumScale: branch.frustum?.scale ?? prev.frustumScale, - secondaryClassifiers: branch.secondaryClassifiers?? prev.secondaryClassifiers, + secondaryClassifiers: branch.secondaryClassifiers ?? prev.secondaryClassifiers, // The branch can augment the symbology overrides. If it doesn't want to, allow its parent to do so, unless this branch supplies its own symbology overrides. appearanceProvider: branch.appearanceProvider ?? (branch.branch.symbologyOverrides ? undefined : prev.appearanceProvider), realityModelDisplaySettings: branch.branch.realityModelDisplaySettings ?? prev.realityModelDisplaySettings, @@ -117,9 +162,31 @@ export class BranchState { }); } - public getFeatureAppearance(overrides: FeatureSymbology.Overrides, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number): FeatureAppearance | undefined { + public getFeatureAppearance( + overrides: FeatureSymbology.Overrides, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ): FeatureAppearance | undefined { if (this._opts.appearanceProvider) - return this._opts.appearanceProvider.getFeatureAppearance(overrides, elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); + return this._opts.appearanceProvider.getFeatureAppearance( + overrides, + elemLo, + elemHi, + subcatLo, + subcatHi, + geomClass, + modelLo, + modelHi, + type, + animationNodeId, + ); return overrides.getAppearance(elemLo, elemHi, subcatLo, subcatHi, geomClass, modelLo, modelHi, type, animationNodeId); } diff --git a/core/frontend/src/render/webgl/BranchUniforms.ts b/core/frontend/src/render/webgl/BranchUniforms.ts index f7f571c543c1..28ba97a9d49b 100644 --- a/core/frontend/src/render/webgl/BranchUniforms.ts +++ b/core/frontend/src/render/webgl/BranchUniforms.ts @@ -7,21 +7,21 @@ */ import { assert } from "@itwin/core-bentley"; -import { ClipVector, Matrix3d, Matrix4d, Point3d, Transform, XYZ } from "@itwin/core-geometry"; import { ClipStyle, HiddenLine, ViewFlags } from "@itwin/core-common"; +import { ClipVector, Matrix3d, Matrix4d, Point3d, Transform, XYZ } from "@itwin/core-geometry"; +import { IModelApp } from "../../IModelApp"; import { FeatureSymbology } from "../FeatureSymbology"; -import { BranchState } from "./BranchState"; -import { BranchStack } from "./BranchStack"; import { BatchState } from "./BatchState"; +import { BranchStack } from "./BranchStack"; +import { BranchState } from "./BranchState"; import { CachedGeometry } from "./CachedGeometry"; +import { ClipStack } from "./ClipStack"; import { Branch } from "./Graphic"; -import { UniformHandle } from "./UniformHandle"; import { Matrix3, Matrix4 } from "./Matrix"; import { RenderCommands } from "./RenderCommands"; import { desync, sync, SyncToken } from "./Sync"; import { Target } from "./Target"; -import { ClipStack } from "./ClipStack"; -import { IModelApp } from "../../IModelApp"; +import { UniformHandle } from "./UniformHandle"; function equalXYZs(a: XYZ | undefined, b: XYZ | undefined): boolean { if (a === b) @@ -71,7 +71,9 @@ export class BranchUniforms { private readonly _scratchVIModelMatrix = Transform.createIdentity(); private readonly _zeroPoint = new Point3d(0, 0, 0); - public get stack(): BranchStack { return this._stack; } + public get stack(): BranchStack { + return this._stack; + } public constructor(target: Target) { this._target = target; @@ -221,7 +223,10 @@ export class BranchUniforms { if (vio) { const viewToWorldRot = viewMatrix.matrix.inverse(this._scratchViewToWorld)!; const rotateAboutOrigin = Transform.createFixedPointAndMatrix(vio, viewToWorldRot, this._scratchTransform2); - const viModelMatrix = rotateAboutOrigin.multiplyTransformTransform(instancedGeom.getRtcModelTransform(modelMatrix), this._scratchVIModelMatrix); + const viModelMatrix = rotateAboutOrigin.multiplyTransformTransform( + instancedGeom.getRtcModelTransform(modelMatrix), + this._scratchVIModelMatrix, + ); mv = viewMatrix.multiplyTransformTransform(viModelMatrix, this._scratchTransform); } else { mv = viewMatrix.multiplyTransformTransform(instancedGeom.getRtcModelTransform(modelMatrix), this._scratchTransform); diff --git a/core/frontend/src/render/webgl/CachedGeometry.ts b/core/frontend/src/render/webgl/CachedGeometry.ts index 2271ff16a1cd..36a2e0bd4d5d 100644 --- a/core/frontend/src/render/webgl/CachedGeometry.ts +++ b/core/frontend/src/render/webgl/CachedGeometry.ts @@ -7,35 +7,35 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { Angle, Point2d, Point3d, Range3d, Vector2d, Vector3d } from "@itwin/core-geometry"; import { Npc, QParams2d, QParams3d, QPoint2dList, QPoint3dList, RenderMode, RenderTexture } from "@itwin/core-common"; -import { RenderSkyGradientParams, RenderSkySphereParams } from "../RenderSystem"; -import { FlashMode } from "../../FlashSettings"; +import { Angle, Point2d, Point3d, Range3d, Vector2d, Vector3d } from "@itwin/core-geometry"; import { TesselatedPolyline } from "../../common/internal/render/PolylineParams"; +import { FlashMode } from "../../FlashSettings"; import { RenderMemory } from "../RenderMemory"; +import { RenderSkyGradientParams, RenderSkySphereParams } from "../RenderSystem"; +import { BufferHandle, BufferParameters, BuffersContainer, QBufferHandle2d, QBufferHandle3d } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { ColorInfo } from "./ColorInfo"; import { WebGLDisposable } from "./Disposable"; import { DrawParams, ShaderProgramParams } from "./DrawCommand"; -import { LineCode } from "./LineCode"; +import { EdgeGeometry, SilhouetteEdgeGeometry } from "./EdgeGeometry"; import { fromSumOf, FrustumUniformType } from "./FrustumUniforms"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer, QBufferHandle2d, QBufferHandle3d } from "./AttributeBuffers"; +import { IndexedEdgeGeometry } from "./IndexedEdgeGeometry"; import { InstancedGeometry } from "./InstancedGeometry"; +import { LineCode } from "./LineCode"; import { MaterialInfo } from "./Material"; import { MeshGeometry } from "./MeshGeometry"; -import { EdgeGeometry, SilhouetteEdgeGeometry } from "./EdgeGeometry"; -import { IndexedEdgeGeometry } from "./IndexedEdgeGeometry"; -import { SurfaceGeometry } from "./SurfaceGeometry"; +import { PlanarGridGeometry } from "./PlanarGrid"; import { PointCloudGeometry } from "./PointCloud"; +import { RealityMeshGeometry } from "./RealityMesh"; import { CompositeFlags, Pass, RenderOrder } from "./RenderFlags"; +import { SurfaceGeometry } from "./SurfaceGeometry"; import { System } from "./System"; import { Target } from "./Target"; import { computeCompositeTechniqueId, TechniqueId } from "./TechniqueId"; -import { RealityMeshGeometry } from "./RealityMesh"; import { TextureHandle } from "./Texture"; import { VertexLUT } from "./VertexLUT"; -import { PlanarGridGeometry } from "./PlanarGrid"; const scratchVec3a = new Vector3d(); const scratchVec3b = new Vector3d(); @@ -56,26 +56,56 @@ export abstract class CachedGeometry implements WebGLDisposable, RenderMemory.Co * Instanced geometry holds a reference to the shared geometry rendered for each instance - such casts will fail, * while the casting `functions` will forward to the shared geometry. */ - public get asLUT(): LUTGeometry | undefined { return undefined; } - public get asSurface(): SurfaceGeometry | undefined { return undefined; } - public get asMesh(): MeshGeometry | undefined { return undefined; } - public get asEdge(): EdgeGeometry | undefined { return undefined; } - public get asIndexedEdge(): IndexedEdgeGeometry | undefined { return undefined; } - public get asRealityMesh(): RealityMeshGeometry | undefined { return undefined; } - public get asSilhouette(): SilhouetteEdgeGeometry | undefined { return undefined; } - public get asInstanced(): InstancedGeometry | undefined { return undefined; } - public get isInstanced() { return undefined !== this.asInstanced; } - public get asPointCloud(): PointCloudGeometry | undefined { return undefined; } - public get asPlanarGrid(): PlanarGridGeometry | undefined { return undefined; } - public get alwaysRenderTranslucent(): boolean { return false; } - public get allowColorOverride(): boolean { return true; } + public get asLUT(): LUTGeometry | undefined { + return undefined; + } + public get asSurface(): SurfaceGeometry | undefined { + return undefined; + } + public get asMesh(): MeshGeometry | undefined { + return undefined; + } + public get asEdge(): EdgeGeometry | undefined { + return undefined; + } + public get asIndexedEdge(): IndexedEdgeGeometry | undefined { + return undefined; + } + public get asRealityMesh(): RealityMeshGeometry | undefined { + return undefined; + } + public get asSilhouette(): SilhouetteEdgeGeometry | undefined { + return undefined; + } + public get asInstanced(): InstancedGeometry | undefined { + return undefined; + } + public get isInstanced() { + return undefined !== this.asInstanced; + } + public get asPointCloud(): PointCloudGeometry | undefined { + return undefined; + } + public get asPlanarGrid(): PlanarGridGeometry | undefined { + return undefined; + } + public get alwaysRenderTranslucent(): boolean { + return false; + } + public get allowColorOverride(): boolean { + return true; + } // Returns true if white portions of this geometry should render as black on white background protected abstract _wantWoWReversal(_target: Target): boolean; // Returns the edge/line weight used to render this geometry - protected _getLineWeight(_params: ShaderProgramParams): number { return 0; } + protected _getLineWeight(_params: ShaderProgramParams): number { + return 0; + } // Returns the edge/line pattern used to render this geometry - protected _getLineCode(_params: ShaderProgramParams): number { return LineCode.solid; } + protected _getLineCode(_params: ShaderProgramParams): number { + return LineCode.solid; + } public abstract get isDisposed(): boolean; // Returns the Id of the Technique used to render this geometry @@ -85,17 +115,25 @@ export abstract class CachedGeometry implements WebGLDisposable, RenderMemory.Co // Returns the 'order' of this geometry, which determines how z-fighting is resolved. public abstract get renderOrder(): RenderOrder; // Returns true if this is a lit surface - public get isLitSurface(): boolean { return false; } + public get isLitSurface(): boolean { + return false; + } // Returns true if this is an unlit surface with baked-in lighting (e.g. 3mx, scalable mesh reality models) - public get hasBakedLighting(): boolean { return false; } + public get hasBakedLighting(): boolean { + return false; + } // Returns true if this primitive contains auxillary animation data. - public get hasAnimation(): boolean { return false; } + public get hasAnimation(): boolean { + return false; + } /** If false, the geometry's positions are not quantized. * qOrigin and qScale can still be used to derive the geometry's range, but will not be passed to the shader. * see VertexLUT.usesQuantizedPositions. */ - public get usesQuantizedPositions(): boolean { return true; } + public get usesQuantizedPositions(): boolean { + return true; + } /** Returns the origin of this geometry's quantization parameters. */ public abstract get qOrigin(): Float32Array; /** Returns the scale of this geometry's quantization parameters. */ @@ -106,18 +144,30 @@ export abstract class CachedGeometry implements WebGLDisposable, RenderMemory.Co public abstract dispose(): void; // Intended to be overridden by specific subclasses - public get materialInfo(): MaterialInfo | undefined { return undefined; } + public get materialInfo(): MaterialInfo | undefined { + return undefined; + } public get hasMaterialAtlas(): boolean { const mat = this.materialInfo; return undefined !== mat && mat.isAtlas; } - public get polylineBuffers(): PolylineBuffers | undefined { return undefined; } - public get hasFeatures(): boolean { return false; } - public get viewIndependentOrigin(): Point3d | undefined { return undefined; } - public get isViewIndependent(): boolean { return undefined !== this.viewIndependentOrigin; } + public get polylineBuffers(): PolylineBuffers | undefined { + return undefined; + } + public get hasFeatures(): boolean { + return false; + } + public get viewIndependentOrigin(): Point3d | undefined { + return undefined; + } + public get isViewIndependent(): boolean { + return undefined !== this.viewIndependentOrigin; + } - public get supportsThematicDisplay() { return false; } + public get supportsThematicDisplay() { + return false; + } public get isEdge(): boolean { switch (this.renderOrder) { @@ -161,8 +211,12 @@ export abstract class CachedGeometry implements WebGLDisposable, RenderMemory.Co return vf.lighting ? params.target.plan.flashSettings.litMode : FlashMode.Hilite; } - public wantMixMonochromeColor(_target: Target): boolean { return false; } - public wantMonochrome(_target: Target): boolean { return true; } + public wantMixMonochromeColor(_target: Target): boolean { + return false; + } + public wantMonochrome(_target: Target): boolean { + return true; + } public abstract collectStatistics(stats: RenderMemory.Statistics): void; @@ -193,20 +247,38 @@ export abstract class LUTGeometry extends CachedGeometry { // The texture containing the vertex data. public abstract get lut(): VertexLUT; - public override get asLUT() { return this; } - public override get viewIndependentOrigin() { return this._viewIndependentOrigin; } + public override get asLUT() { + return this; + } + public override get viewIndependentOrigin() { + return this._viewIndependentOrigin; + } protected abstract _draw(_numInstances: number, _instanceBuffersContainer?: BuffersContainer): void; - public draw(): void { this._draw(0); } - public drawInstanced(numInstances: number, instanceBuffersContainer: BuffersContainer): void { this._draw(numInstances, instanceBuffersContainer); } + public draw(): void { + this._draw(0); + } + public drawInstanced(numInstances: number, instanceBuffersContainer: BuffersContainer): void { + this._draw(numInstances, instanceBuffersContainer); + } // Override this if your color varies based on the target - public getColor(_target: Target): ColorInfo { return this.lut.colorInfo; } + public getColor(_target: Target): ColorInfo { + return this.lut.colorInfo; + } - public override get usesQuantizedPositions() { return this.lut.usesQuantizedPositions; } - public get qOrigin(): Float32Array { return this.lut.qOrigin; } - public get qScale(): Float32Array { return this.lut.qScale; } - public override get hasAnimation() { return this.lut.hasAnimation; } + public override get usesQuantizedPositions() { + return this.lut.usesQuantizedPositions; + } + public get qOrigin(): Float32Array { + return this.lut.qOrigin; + } + public get qScale(): Float32Array { + return this.lut.qScale; + } + public override get hasAnimation() { + return this.lut.hasAnimation; + } protected constructor(viewIndependentOrigin?: Point3d) { super(); @@ -264,13 +336,17 @@ export class IndexedGeometryParams implements WebGLDisposable { */ export abstract class IndexedGeometry extends CachedGeometry { protected readonly _params: IndexedGeometryParams; - protected _wantWoWReversal(_target: Target): boolean { return false; } + protected _wantWoWReversal(_target: Target): boolean { + return false; + } protected constructor(params: IndexedGeometryParams) { super(); this._params = params; } - public get isDisposed(): boolean { return this._params.isDisposed; } + public get isDisposed(): boolean { + return this._params.isDisposed; + } public dispose() { dispose(this._params); @@ -282,8 +358,12 @@ export abstract class IndexedGeometry extends CachedGeometry { this._params.buffers.unbind(); } - public get qOrigin() { return this._params.positions.origin; } - public get qScale() { return this._params.positions.scale; } + public get qOrigin() { + return this._params.positions.origin; + } + public get qScale() { + return this._params.positions.scale; + } } /** a cube of quads in normalized device coordinates for skybox rendering techniques @@ -304,52 +384,52 @@ class SkyBoxQuads { // ###TODO: Make this indexed. Currently not indexed because of previous six-sided texture system. // Back (Bottom after rotation) - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 - qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 - qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 + qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 + qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 // Front (Top after rotation) - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6 // Top (Front after rotation) - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 // Bottom (Back after rotation) - qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 + qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6 // Left (Right after rotation) - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 - qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 - qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, skyBoxSz)); // back upper left - 0 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 + qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 + qVerts.add(new Point3d(-skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper left - 4 qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower left - 6 - qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 + qVerts.add(new Point3d(-skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower left - 2 // Right (Left after rotation) - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 - qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 - qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, skyBoxSz)); // back upper right - 1 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 + qVerts.add(new Point3d(skyBoxSz, skyBoxSz, -skyBoxSz)); // front upper right - 5 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, -skyBoxSz)); // front lower right - 7 + qVerts.add(new Point3d(skyBoxSz, -skyBoxSz, skyBoxSz)); // back lower right - 3 this.vertices = qVerts.toTypedArray(); this.vertexParams = qVerts.params; @@ -383,7 +463,9 @@ export class SkyBoxGeometryParams implements WebGLDisposable { return new SkyBoxGeometryParams(posBuf); } - public get isDisposed(): boolean { return this.buffers.isDisposed && this.positions.isDisposed; } + public get isDisposed(): boolean { + return this.buffers.isDisposed && this.positions.isDisposed; + } public dispose() { dispose(this.buffers); @@ -427,9 +509,15 @@ export class SkyBoxQuadsGeometry extends CachedGeometry { // Not interested in tracking this. } - public get techniqueId(): TechniqueId { return this._techniqueId; } - public override getPass(): Pass { return "skybox"; } - public get renderOrder() { return RenderOrder.UnlitSurface; } + public get techniqueId(): TechniqueId { + return this._techniqueId; + } + public override getPass(): Pass { + return "skybox"; + } + public get renderOrder() { + return RenderOrder.UnlitSurface; + } public draw(): void { this._params.buffers.bind(); @@ -437,16 +525,24 @@ export class SkyBoxQuadsGeometry extends CachedGeometry { this._params.buffers.unbind(); } - public get qOrigin() { return this._params.positions.origin; } - public get qScale() { return this._params.positions.scale; } + public get qOrigin() { + return this._params.positions.origin; + } + public get qScale() { + return this._params.positions.scale; + } - public get isDisposed(): boolean { return this._params.isDisposed; } + public get isDisposed(): boolean { + return this._params.isDisposed; + } public dispose() { dispose(this._params); } - protected _wantWoWReversal(_target: Target): boolean { return false; } + protected _wantWoWReversal(_target: Target): boolean { + return false; + } } /** A quad with its corners mapped to the dimensions as the viewport, used for special rendering techniques. @@ -511,9 +607,15 @@ export class ViewportQuadGeometry extends IndexedGeometry { return undefined !== params ? new this(params, techniqueId) : undefined; } - public get techniqueId(): TechniqueId { return this._techniqueId; } - public override getPass(): Pass { return "opaque"; } - public get renderOrder() { return RenderOrder.UnlitSurface; } + public get techniqueId(): TechniqueId { + return this._techniqueId; + } + public override getPass(): Pass { + return "opaque"; + } + public get renderOrder() { + return RenderOrder.UnlitSurface; + } public collectStatistics(_stats: RenderMemory.Statistics): void { // NB: These don't really count... @@ -622,7 +724,15 @@ export class SkySphereViewportQuadGeometry extends ViewportQuadGeometry { let zScale = focalLength / delta.magnitude(); if (zScale < 1.000001) zScale = 1.000001; // prevent worldEye front being on or inside the frustum front plane - camPos = Point3d.createAdd3Scaled(frustum.getCorner(Npc.LeftBottomRear), .5, frustum.getCorner(Npc.RightTopRear), .5, delta, zScale, scratchPoint3a); + camPos = Point3d.createAdd3Scaled( + frustum.getCorner(Npc.LeftBottomRear), + .5, + frustum.getCorner(Npc.RightTopRear), + .5, + delta, + zScale, + scratchPoint3a, + ); } // Compute the distance from the camera to the frustum center. const camDist = camPos.distance(fCenter); @@ -725,7 +835,9 @@ export class SkySphereViewportQuadGeometry extends ViewportQuadGeometry { return new SkySphereViewportQuadGeometry(params, skybox, technique); } - public override get isDisposed(): boolean { return super.isDisposed && this._worldPosBuff.isDisposed; } + public override get isDisposed(): boolean { + return super.isDisposed && this._worldPosBuff.isDisposed; + } public override dispose() { super.dispose(); @@ -747,9 +859,15 @@ export class AmbientOcclusionGeometry extends TexturedViewportQuadGeometry { return new AmbientOcclusionGeometry(params, [depth, depthAndOrder]); } - public get depthAndOrder() { return this._textures[1]; } - public get depth() { return this._textures[0]; } - public get noise() { return System.instance.noiseTexture!.getHandle()!; } + public get depthAndOrder() { + return this._textures[1]; + } + public get depth() { + return this._textures[0]; + } + public get noise() { + return System.instance.noiseTexture!.getHandle()!; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[]) { super(params, TechniqueId.AmbientOcclusion, textures); @@ -766,7 +884,13 @@ export enum BlurType { export class BlurGeometry extends TexturedViewportQuadGeometry { public readonly blurDir: Vector2d; - public static createGeometry(texToBlur: WebGLTexture, depthAndOrder: WebGLTexture, depthAndOrderHidden: WebGLTexture | undefined, blurDir: Vector2d, blurType: BlurType) { + public static createGeometry( + texToBlur: WebGLTexture, + depthAndOrder: WebGLTexture, + depthAndOrderHidden: WebGLTexture | undefined, + blurDir: Vector2d, + blurType: BlurType, + ) { const params = ViewportQuad.getInstance().createParams(); if (undefined === params) { return undefined; @@ -777,9 +901,15 @@ export class BlurGeometry extends TexturedViewportQuadGeometry { return new BlurGeometry(params, [texToBlur, depthAndOrder, depthAndOrderHidden], blurDir, blurType); } - public get textureToBlur() { return this._textures[0]; } - public get depthAndOrder() { return this._textures[1]; } - public get depthAndOrderHidden() { return this._textures[2]; } + public get textureToBlur() { + return this._textures[0]; + } + public get depthAndOrder() { + return this._textures[1]; + } + public get depthAndOrderHidden() { + return this._textures[2]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[], blurDir: Vector2d, blurType: BlurType) { super(params, BlurType.NoTest === blurType ? TechniqueId.Blur : TechniqueId.BlurTestOrder, textures); @@ -799,8 +929,12 @@ export class EDLCalcBasicGeometry extends TexturedViewportQuadGeometry { return new EDLCalcBasicGeometry(params, [colorBuffer, depthBuffer], width, height); } - public get colorTexture() { return this._textures[0]; } - public get depthTexture() { return this._textures[1]; } + public get colorTexture() { + return this._textures[0]; + } + public get depthTexture() { + return this._textures[1]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[], width: number, height: number) { super(params, TechniqueId.EDLCalcBasic, textures); @@ -822,8 +956,12 @@ export class EDLCalcFullGeometry extends TexturedViewportQuadGeometry { return new EDLCalcFullGeometry(params, [colorBuffer, depthBuffer], scale, width, height); } - public get colorTexture() { return this._textures[0]; } - public get depthTexture() { return this._textures[1]; } + public get colorTexture() { + return this._textures[0]; + } + public get depthTexture() { + return this._textures[1]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[], scale: number, width: number, height: number) { super(params, TechniqueId.EDLCalcFull, textures); @@ -845,8 +983,12 @@ export class EDLFilterGeometry extends TexturedViewportQuadGeometry { return new EDLFilterGeometry(params, [colorBuffer, depthBuffer], scale, width, height); } - public get colorTexture() { return this._textures[0]; } - public get depthTexture() { return this._textures[1]; } + public get colorTexture() { + return this._textures[0]; + } + public get depthTexture() { + return this._textures[1]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[], scale: number, width: number, height: number) { super(params, TechniqueId.EDLFilter, textures); @@ -858,7 +1000,6 @@ export class EDLFilterGeometry extends TexturedViewportQuadGeometry { /** @internal */ export class EDLMixGeometry extends TexturedViewportQuadGeometry { - public static createGeometry(colorTexture1: WebGLTexture, colorTexture2: WebGLTexture, colorTexture4: WebGLTexture) { const params = ViewportQuad.getInstance().createParams(); if (undefined === params) @@ -867,9 +1008,15 @@ export class EDLMixGeometry extends TexturedViewportQuadGeometry { return new EDLMixGeometry(params, [colorTexture1, colorTexture2, colorTexture4]); } - public get colorTexture1() { return this._textures[0]; } - public get colorTexture2() { return this._textures[1]; } - public get colorTexture4() { return this._textures[2]; } + public get colorTexture1() { + return this._textures[0]; + } + public get colorTexture2() { + return this._textures[1]; + } + public get colorTexture4() { + return this._textures[2]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[]) { super(params, TechniqueId.EDLMix, textures); @@ -888,7 +1035,9 @@ export class EVSMGeometry extends TexturedViewportQuadGeometry { return new EVSMGeometry(params, [depthBuffer], width, height); } - public get depthTexture() { return this._textures[0]; } + public get depthTexture() { + return this._textures[0]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[], width: number, height: number) { super(params, TechniqueId.EVSMFromDepth, textures); @@ -910,10 +1059,18 @@ export class CompositeGeometry extends TexturedViewportQuadGeometry { return new CompositeGeometry(params, textures); } - public get opaque() { return this._textures[0]; } - public get accum() { return this._textures[1]; } - public get reveal() { return this._textures[2]; } - public get hilite() { return this._textures[3]; } + public get opaque() { + return this._textures[0]; + } + public get accum() { + return this._textures[1]; + } + public get reveal() { + return this._textures[2]; + } + public get hilite() { + return this._textures[3]; + } public get occlusion(): WebGLTexture | undefined { return this._textures.length > 4 ? this._textures[4] : undefined; } @@ -926,7 +1083,9 @@ export class CompositeGeometry extends TexturedViewportQuadGeometry { } // Invoked each frame to determine the appropriate Technique to use. - public update(flags: CompositeFlags): void { this._techniqueId = this.determineTechnique(flags); } + public update(flags: CompositeFlags): void { + this._techniqueId = this.determineTechnique(flags); + } private determineTechnique(flags: CompositeFlags): TechniqueId { return computeCompositeTechniqueId(flags); @@ -951,8 +1110,12 @@ export class CopyPickBufferGeometry extends TexturedViewportQuadGeometry { } } - public get featureId() { return this._textures[0]; } - public get depthAndOrder() { return this._textures[1]; } + public get featureId() { + return this._textures[0]; + } + public get depthAndOrder() { + return this._textures[1]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[]) { super(params, TechniqueId.CopyPickBuffers, textures); @@ -968,8 +1131,12 @@ export class CombineTexturesGeometry extends TexturedViewportQuadGeometry { } } - public get texture0() { return this._textures[0]; } - public get texture1() { return this._textures[1]; } + public get texture0() { + return this._textures[0]; + } + public get texture1() { + return this._textures[1]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[]) { super(params, TechniqueId.CombineTextures, textures); @@ -986,9 +1153,15 @@ export class Combine3TexturesGeometry extends TexturedViewportQuadGeometry { } } - public get texture0() { return this._textures[0]; } - public get texture1() { return this._textures[1]; } - public get texture2() { return this._textures[2]; } + public get texture0() { + return this._textures[0]; + } + public get texture1() { + return this._textures[1]; + } + public get texture2() { + return this._textures[2]; + } private constructor(params: IndexedGeometryParams, textures: WebGLTexture[]) { super(params, TechniqueId.Combine3Textures, textures); @@ -1006,8 +1179,12 @@ export class SingleTexturedViewportQuadGeometry extends TexturedViewportQuadGeom return new SingleTexturedViewportQuadGeometry(params, texture, techId); } - public get texture(): WebGLTexture { return this._textures[0]; } - public set texture(texture: WebGLTexture) { this._textures[0] = texture; } + public get texture(): WebGLTexture { + return this._textures[0]; + } + public set texture(texture: WebGLTexture) { + this._textures[0] = texture; + } protected constructor(params: IndexedGeometryParams, texture: WebGLTexture, techId: TechniqueId) { super(params, techId, [texture]); @@ -1099,7 +1276,9 @@ export class ScreenPointsGeometry extends CachedGeometry { this.buffers.unbind(); } - public get isDisposed(): boolean { return this.buffers.isDisposed && this._positions.isDisposed; } + public get isDisposed(): boolean { + return this.buffers.isDisposed && this._positions.isDisposed; + } public dispose() { dispose(this.buffers); @@ -1110,12 +1289,24 @@ export class ScreenPointsGeometry extends CachedGeometry { stats.addBuffer(RenderMemory.BufferType.PointStrings, this._positions.bytesUsed); } - protected _wantWoWReversal(_target: Target): boolean { return false; } - public get techniqueId(): TechniqueId { return TechniqueId.VolClassCopyZ; } - public override getPass(): Pass { return "classification"; } - public get renderOrder() { return RenderOrder.None; } - public get qOrigin() { return this._origin; } - public get qScale() { return this._scale; } + protected _wantWoWReversal(_target: Target): boolean { + return false; + } + public get techniqueId(): TechniqueId { + return TechniqueId.VolClassCopyZ; + } + public override getPass(): Pass { + return "classification"; + } + public get renderOrder() { + return RenderOrder.None; + } + public get qOrigin() { + return this._origin; + } + public get qScale() { + return this._scale; + } } /** @internal */ diff --git a/core/frontend/src/render/webgl/ClipStack.ts b/core/frontend/src/render/webgl/ClipStack.ts index fe7f03950ce4..ecfb88ab305d 100644 --- a/core/frontend/src/render/webgl/ClipStack.ts +++ b/core/frontend/src/render/webgl/ClipStack.ts @@ -7,14 +7,14 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { ClipPlaneContainment, ClipVector, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ClipIntersectionStyle, RgbColor } from "@itwin/core-common"; +import { ClipPlaneContainment, ClipVector, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { IModelApp } from "../../IModelApp"; import { RenderClipVolume } from "../RenderClipVolume"; -import { FloatRgba } from "./FloatRGBA"; -import { Texture2DData, Texture2DHandle, TextureHandle } from "./Texture"; import { ClipVolume } from "./ClipVolume"; +import { FloatRgba } from "./FloatRGBA"; import { GL } from "./GL"; +import { Texture2DData, Texture2DHandle, TextureHandle } from "./Texture"; interface Clip { readonly numRows: number; @@ -28,8 +28,14 @@ const emptyClip = { }; const scratchRangeCorners = [ - new Point3d(), new Point3d(), new Point3d(), new Point3d(), - new Point3d(), new Point3d(), new Point3d(), new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), + new Point3d(), ]; function getRangeCorners(r: Range3d): Point3d[] { @@ -106,7 +112,10 @@ export class ClipStack { return this._texture ? this._texture.bytesUsed : 0; } - public setViewClip(clip: ClipVector | undefined, style: { insideColor?: RgbColor, outsideColor?: RgbColor, colorizeIntersection?: boolean, intersectionStyle?: ClipIntersectionStyle }): void { + public setViewClip( + clip: ClipVector | undefined, + style: { insideColor?: RgbColor, outsideColor?: RgbColor, colorizeIntersection?: boolean, intersectionStyle?: ClipIntersectionStyle }, + ): void { assert(this._stack.length === 1); this.updateColor(style.insideColor, this._insideColor); @@ -160,7 +169,7 @@ export class ClipStack { public pop(): void { assert(this._stack.length > 0); const clip = this._stack.pop(); - this._numRowsInUse -= (clip ? clip.numRows : 0); + this._numRowsInUse -= clip ? clip.numRows : 0; } public get hasClip(): boolean { @@ -256,7 +265,14 @@ export class ClipStack { if (this._texture) this._texture.replaceTextureData(this._gpuBuffer); else - this._texture = Texture2DHandle.createForData(1, this._numTotalRows, this._gpuBuffer, false, GL.Texture.WrapMode.ClampToEdge, GL.Texture.Format.Rgba); + this._texture = Texture2DHandle.createForData( + 1, + this._numTotalRows, + this._gpuBuffer, + false, + GL.Texture.WrapMode.ClampToEdge, + GL.Texture.Format.Rgba, + ); assert(this._texture!.height === this._numTotalRows); } @@ -271,7 +287,11 @@ export class ClipStack { rgba.setRgbColor(rgb); } - protected updateIntersectionStyle(colorizeIntersection: boolean | undefined, style: ClipIntersectionStyle | undefined, _thisStyle: FloatRgba): void { + protected updateIntersectionStyle( + colorizeIntersection: boolean | undefined, + style: ClipIntersectionStyle | undefined, + _thisStyle: FloatRgba, + ): void { this._colorizeIntersection = colorizeIntersection === true ? true : false; if (style !== undefined) { diff --git a/core/frontend/src/render/webgl/ClipVolume.ts b/core/frontend/src/render/webgl/ClipVolume.ts index 64a40ced4e58..74df823268d1 100644 --- a/core/frontend/src/render/webgl/ClipVolume.ts +++ b/core/frontend/src/render/webgl/ClipVolume.ts @@ -7,9 +7,7 @@ */ import { assert } from "@itwin/core-bentley"; -import { - ClipVector, Point3d, Transform, UnionOfConvexClipPlaneSets, Vector3d, -} from "@itwin/core-geometry"; +import { ClipVector, Point3d, Transform, UnionOfConvexClipPlaneSets, Vector3d } from "@itwin/core-geometry"; import { RenderClipVolume } from "../RenderClipVolume"; const scratch = { diff --git a/core/frontend/src/render/webgl/ClippingProgram.ts b/core/frontend/src/render/webgl/ClippingProgram.ts index e43846427d37..3baeaf161c16 100644 --- a/core/frontend/src/render/webgl/ClippingProgram.ts +++ b/core/frontend/src/render/webgl/ClippingProgram.ts @@ -7,10 +7,10 @@ */ import { dispose } from "@itwin/core-bentley"; +import { addClipping } from "./glsl/Clipping"; import { ProgramBuilder } from "./ShaderBuilder"; import { CompileStatus, ShaderProgram } from "./ShaderProgram"; import { System } from "./System"; -import { addClipping } from "./glsl/Clipping"; function createClippingBuilder(src: ProgramBuilder): ProgramBuilder { const builder = src.clone(); diff --git a/core/frontend/src/render/webgl/ColorInfo.ts b/core/frontend/src/render/webgl/ColorInfo.ts index 1cbe4ed3115e..c35b51d90c25 100644 --- a/core/frontend/src/render/webgl/ColorInfo.ts +++ b/core/frontend/src/render/webgl/ColorInfo.ts @@ -8,8 +8,8 @@ import { assert } from "@itwin/core-bentley"; import { ColorDef, ColorIndex } from "@itwin/core-common"; -import { FloatRgba } from "./FloatRGBA"; import { VertexTable } from "../../common/internal/render/VertexTable"; +import { FloatRgba } from "./FloatRGBA"; /* Describes a primitive's basic color properties * @internal @@ -23,9 +23,15 @@ export class ColorInfo { this._uniform = uniform; } - public static createUniform(color: FloatRgba) { return new ColorInfo(color.hasTranslucency, color); } - public static createNonUniform(hasTranslucency: boolean) { return hasTranslucency ? this._nonUniformTranslucent : this._nonUniformOpaque; } - public static createFromColorDef(color: ColorDef) { return this.createUniform(FloatRgba.fromColorDef(color)); } + public static createUniform(color: FloatRgba) { + return new ColorInfo(color.hasTranslucency, color); + } + public static createNonUniform(hasTranslucency: boolean) { + return hasTranslucency ? this._nonUniformTranslucent : this._nonUniformOpaque; + } + public static createFromColorDef(color: ColorDef) { + return this.createUniform(FloatRgba.fromColorDef(color)); + } public static createFromColorIndex(colorIndex: ColorIndex) { return undefined !== colorIndex.uniform ? this.createFromColorDef(colorIndex.uniform) : this.createNonUniform(colorIndex.hasAlpha); @@ -35,8 +41,12 @@ export class ColorInfo { return undefined !== vt.uniformColor ? this.createFromColorDef(vt.uniformColor) : this.createNonUniform(vt.hasTranslucency); } - public get isUniform() { return undefined !== this._uniform; } - public get isNonUniform() { return !this.isUniform; } + public get isUniform() { + return undefined !== this._uniform; + } + public get isNonUniform() { + return !this.isUniform; + } public get uniform(): FloatRgba { assert(this.isUniform); return this._uniform!; diff --git a/core/frontend/src/render/webgl/ContourUniforms.ts b/core/frontend/src/render/webgl/ContourUniforms.ts index 61d047afee3d..780ff5ceaaf2 100644 --- a/core/frontend/src/render/webgl/ContourUniforms.ts +++ b/core/frontend/src/render/webgl/ContourUniforms.ts @@ -7,10 +7,10 @@ */ import { ContourDisplay, RgbColor } from "@itwin/core-common"; -import { UniformHandle } from "./UniformHandle"; +import { LineCode } from "./LineCode"; import { desync, sync } from "./Sync"; import { Target } from "./Target"; -import { LineCode } from "./LineCode"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state for uniforms related to contour display. * @internal @@ -30,8 +30,8 @@ export class ContourUniforms { private packColor(startNdx: number, majorColor: RgbColor, minorColor: RgbColor) { // pack 2 bytes major (upper) minor (lower) into each float this._contourDefs[startNdx] = majorColor.r * 256 + minorColor.r; - this._contourDefs[startNdx+1] = majorColor.g * 256 + minorColor.g; - this._contourDefs[startNdx+2] = majorColor.b * 256 + minorColor.b; + this._contourDefs[startNdx + 1] = majorColor.g * 256 + minorColor.g; + this._contourDefs[startNdx + 2] = majorColor.b * 256 + minorColor.b; } private packPatWidth(startNdx: number, majorPattern: number, minorPattern: number, majorWidth: number, minorWidth: number, showGeometry: boolean) { @@ -43,16 +43,16 @@ export class ContourUniforms { // NB: showGeometry flag is packed into bit 16 (above major pattern) const majWt = Math.floor((Math.min(8.5, Math.max(1.0, majorWidth)) - 1.0) * 2 + 0.5); const minWt = Math.floor((Math.min(8.5, Math.max(1.0, minorWidth)) - 1.0) * 2 + 0.5); - this._contourDefs[startNdx+3] = (showGeometry ? 65536 : 0) + majorPattern * 4096 + majWt * 256 + minorPattern * 16 + minWt; + this._contourDefs[startNdx + 3] = (showGeometry ? 65536 : 0) + majorPattern * 4096 + majWt * 256 + minorPattern * 16 + minWt; } private packIntervals(startNdx: number, even: boolean, minorInterval: number, majorIntervalCount: number) { // minorInterval is a float of interval in meters, majorIntervalCount is an int > 0 count of minor inteverals per major interval // minorInterval is stored in r or b (0 or 2) and majorIntervalCount is stored in g or a (1 or 3) depending on even or odd index const offset = (even ? 0 : 1) * 2; - this._contourDefs[startNdx+offset] = minorInterval <= 0.0 ? 1.0 : minorInterval; + this._contourDefs[startNdx + offset] = minorInterval <= 0.0 ? 1.0 : minorInterval; majorIntervalCount = Math.floor(majorIntervalCount + 0.5); - this._contourDefs[startNdx+offset+1] = majorIntervalCount < 1.0 ? 1.0 : majorIntervalCount; + this._contourDefs[startNdx + offset + 1] = majorIntervalCount < 1.0 ? 1.0 : majorIntervalCount; } public update(target: Target): void { @@ -94,10 +94,17 @@ export class ContourUniforms { const contourDef = this.contourDisplay.groups[index].contourDef; const even = (index & 1) === 0; const colorDefsNdx = (even ? index * 1.5 : (index - 1) * 1.5 + 2) * 4; - this.packColor (colorDefsNdx, contourDef.majorStyle.color, contourDef.minorStyle.color); - this.packPatWidth (colorDefsNdx, LineCode.valueFromLinePixels(contourDef.majorStyle.pattern), LineCode.valueFromLinePixels(contourDef.minorStyle.pattern), contourDef.majorStyle.pixelWidth, contourDef.minorStyle.pixelWidth, contourDef.showGeometry); + this.packColor(colorDefsNdx, contourDef.majorStyle.color, contourDef.minorStyle.color); + this.packPatWidth( + colorDefsNdx, + LineCode.valueFromLinePixels(contourDef.majorStyle.pattern), + LineCode.valueFromLinePixels(contourDef.minorStyle.pattern), + contourDef.majorStyle.pixelWidth, + contourDef.minorStyle.pixelWidth, + contourDef.showGeometry, + ); const intervalsPairNdx = (Math.floor(index * 0.5) * 3 + 1) * 4; - this.packIntervals (intervalsPairNdx, even, contourDef.minorInterval, contourDef.majorIntervalCount); + this.packIntervals(intervalsPairNdx, even, contourDef.minorInterval, contourDef.majorIntervalCount); } } diff --git a/core/frontend/src/render/webgl/Contours.ts b/core/frontend/src/render/webgl/Contours.ts index ed02b11c3762..c4862e984402 100644 --- a/core/frontend/src/render/webgl/Contours.ts +++ b/core/frontend/src/render/webgl/Contours.ts @@ -8,15 +8,15 @@ import { assert, dispose, Id64, OrderedId64Iterable } from "@itwin/core-bentley"; import { ContourDisplay, PackedFeature, RenderFeatureTable } from "@itwin/core-common"; +import { computeDimensions } from "../../common/internal/render/VertexTable"; +import { BatchOptions } from "../../common/render/BatchOptions"; import { WebGLDisposable } from "./Disposable"; import { GL } from "./GL"; -import { UniformHandle } from "./UniformHandle"; import { TextureUnit } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { Texture2DDataUpdater, Texture2DHandle, TextureHandle } from "./Texture"; -import { BatchOptions } from "../../common/render/BatchOptions"; -import { computeDimensions } from "../../common/internal/render/VertexTable"; +import { UniformHandle } from "./UniformHandle"; /** @internal */ export type ContoursCleanup = () => void; @@ -32,7 +32,9 @@ export class Contours implements WebGLDisposable { private _lutWidth = 0; private _numFeatures = 0; - public get byteLength(): number { return undefined !== this._lut ? this._lut.bytesUsed : 0; } + public get byteLength(): number { + return undefined !== this._lut ? this._lut.bytesUsed : 0; + } public matchesTargetAndFeatureCount(target: Target, map: RenderFeatureTable): boolean { // checking for target change or texture size requirement change @@ -56,7 +58,7 @@ export class Contours implements WebGLDisposable { private _initialize(map: RenderFeatureTable) { assert(0 < map.numFeatures); this._numFeatures = map.numFeatures; - const dims = computeDimensions(this._numFeatures, 1/8, 0, System.instance.maxTextureSize); + const dims = computeDimensions(this._numFeatures, 1 / 8, 0, System.instance.maxTextureSize); const width = dims.width; const height = dims.height; assert(width * height * 8 >= this._numFeatures); @@ -78,7 +80,7 @@ export class Contours implements WebGLDisposable { private buildLookupTable(data: Texture2DDataUpdater, map: RenderFeatureTable, contours: ContourDisplay) { // setup an efficient way to compare feature subcategories with lists in terrains const subCatMap = new Id64.Uint32Map(); - let defaultNdx = 0xf; // default for unmatched subcategories is to not show contours + let defaultNdx = 0xf; // default for unmatched subcategories is to not show contours // NB: index also has to be a max of 14 - has to fit in 4 bits with value 15 reserved for no terrain def for (let index = 0, len = contours.groups.length; index < len && index < ContourDisplay.maxContourGroups; ++index) { const subCats = contours.groups[index].subCategories; @@ -96,7 +98,7 @@ export class Contours implements WebGLDisposable { let byteOut = 0; let dataIndex = 0; for (const feature of map.iterable(scratchPackedFeature)) { - dataIndex = Math.floor (feature.index * 0.5); + dataIndex = Math.floor(feature.index * 0.5); even = (feature.index & 1) === 0; const terrainNdx = subCatMap.get(feature.subCategoryId.lower, feature.subCategoryId.upper) ?? defaultNdx; if (even) @@ -118,7 +120,9 @@ export class Contours implements WebGLDisposable { return new Contours(target, options); } - public get isDisposed(): boolean { return undefined === this._lut; } + public get isDisposed(): boolean { + return undefined === this._lut; + } public dispose() { this._lut = dispose(this._lut); diff --git a/core/frontend/src/render/webgl/Diagnostics.ts b/core/frontend/src/render/webgl/Diagnostics.ts index 67e42a8ce1a8..a5c0141e318c 100644 --- a/core/frontend/src/render/webgl/Diagnostics.ts +++ b/core/frontend/src/render/webgl/Diagnostics.ts @@ -36,7 +36,9 @@ export class Debug { } /** If [[Debug.evaluateEnabled]] is true, returns whether the currently-bound framebuffer is complete. */ - public static get isValidFrameBuffer(): boolean { return GL.FrameBuffer.Status.Complete === this.checkFrameBufferStatus(); } + public static get isValidFrameBuffer(): boolean { + return GL.FrameBuffer.Status.Complete === this.checkFrameBufferStatus(); + } /** If [[Debug.evaluateEnabled]] is true, returns the status of the currently-bound framebuffer. */ public static checkFrameBufferStatus(): GL.FrameBuffer.Status { diff --git a/core/frontend/src/render/webgl/DrawCommand.ts b/core/frontend/src/render/webgl/DrawCommand.ts index e8010d035477..840ee5bf047d 100644 --- a/core/frontend/src/render/webgl/DrawCommand.ts +++ b/core/frontend/src/render/webgl/DrawCommand.ts @@ -13,7 +13,6 @@ import { CachedGeometry } from "./CachedGeometry"; import { ClipVolume } from "./ClipVolume"; import { isFeatureHilited } from "./FeatureOverrides"; import { Batch, Branch } from "./Graphic"; -import { UniformHandle } from "./UniformHandle"; import { Primitive } from "./Primitive"; import { Pass, RenderOrder, RenderPass } from "./RenderFlags"; import { ShaderProgramExecutor } from "./ShaderProgram"; @@ -21,6 +20,7 @@ import { System } from "./System"; import { Hilites, Target } from "./Target"; import { EnableAtmosphere, IsAnimated, IsClassified, IsInstanced, IsShadowable, IsThematic, IsWiremesh, TechniqueFlags } from "./TechniqueFlags"; import { TechniqueId } from "./TechniqueId"; +import { UniformHandle } from "./UniformHandle"; /* eslint-disable no-restricted-syntax */ @@ -34,14 +34,26 @@ export class ShaderProgramParams { return this._target; } - public get renderPass() { return this._renderPass; } + public get renderPass() { + return this._renderPass; + } - public get projectionMatrix() { return this.target.uniforms.getProjectionMatrix32(this.isViewCoords); } - public bindProjectionMatrix(uniform: UniformHandle) { this.target.uniforms.bindProjectionMatrix(uniform, this.isViewCoords); } + public get projectionMatrix() { + return this.target.uniforms.getProjectionMatrix32(this.isViewCoords); + } + public bindProjectionMatrix(uniform: UniformHandle) { + this.target.uniforms.bindProjectionMatrix(uniform, this.isViewCoords); + } - public get isViewCoords() { return RenderPass.ViewOverlay === this.renderPass || RenderPass.Background === this.renderPass; } - public get isOverlayPass() { return RenderPass.WorldOverlay === this.renderPass || RenderPass.ViewOverlay === this.renderPass; } - public get context() { return System.instance.context; } + public get isViewCoords() { + return RenderPass.ViewOverlay === this.renderPass || RenderPass.Background === this.renderPass; + } + public get isOverlayPass() { + return RenderPass.WorldOverlay === this.renderPass || RenderPass.ViewOverlay === this.renderPass; + } + public get context() { + return System.instance.context; + } public init(target: Target, pass: RenderPass = RenderPass.OpaqueGeneral) { this._renderPass = pass; @@ -64,14 +76,24 @@ export class DrawParams { return this._programParams; } - public get target() { return this.programParams.target; } - public get renderPass() { return this.programParams.renderPass; } - public get projectionMatrix() { return this.programParams.projectionMatrix; } + public get target() { + return this.programParams.target; + } + public get renderPass() { + return this.programParams.renderPass; + } + public get projectionMatrix() { + return this.programParams.projectionMatrix; + } public get isViewCoords() { return this.programParams.isViewCoords || this.target.currentBranch.forceViewCoords; } - public get isOverlayPass() { return this.programParams.isOverlayPass; } - public get context() { return this.programParams.context; } + public get isOverlayPass() { + return this.programParams.isOverlayPass; + } + public get context() { + return this.programParams.context; + } public init(programParams: ShaderProgramParams, geometry: CachedGeometry) { this._programParams = programParams; @@ -107,7 +129,7 @@ export enum DrawOpCode { export class PopBatchCommand { public readonly opcode = "popBatch"; - private constructor() { } + private constructor() {} public static instance = new PopBatchCommand(); @@ -120,7 +142,7 @@ export class PopBatchCommand { export class PushBatchCommand { public readonly opcode = "pushBatch"; - public constructor(public readonly batch: Batch) { } + public constructor(public readonly batch: Batch) {} public execute(exec: ShaderProgramExecutor): void { exec.target.pushBatch(this.batch); @@ -131,7 +153,7 @@ export class PushBatchCommand { export class PushStateCommand { public readonly opcode = "pushState"; - public constructor(public readonly state: BranchState) { } + public constructor(public readonly state: BranchState) {} public execute(exec: ShaderProgramExecutor): void { exec.target.pushState(this.state); @@ -142,7 +164,7 @@ export class PushStateCommand { export class PushBranchCommand { public readonly opcode = "pushBranch"; - public constructor(public readonly branch: Branch) { } + public constructor(public readonly branch: Branch) {} public execute(exec: ShaderProgramExecutor): void { exec.pushBranch(this.branch); @@ -153,7 +175,7 @@ export class PushBranchCommand { export class PopBranchCommand { public readonly opcode = "popBranch"; - private constructor() { } + private constructor() {} public static instance = new PopBranchCommand(); @@ -166,7 +188,7 @@ export class PopBranchCommand { export class PushClipCommand { public readonly opcode = "pushClip"; - public constructor(public readonly clip: ClipVolume) { } + public constructor(public readonly clip: ClipVolume) {} public execute(exec: ShaderProgramExecutor): void { exec.target.uniforms.branch.clipStack.push(this.clip); @@ -177,7 +199,7 @@ export class PushClipCommand { export class PopClipCommand { public readonly opcode = "popClip"; - private constructor() { } + private constructor() {} public static instance = new PopClipCommand(); @@ -190,7 +212,7 @@ export class PopClipCommand { export class PrimitiveCommand { public readonly opcode = "drawPrimitive"; - public constructor(public readonly primitive: Primitive) { } + public constructor(public readonly primitive: Primitive) {} private static readonly _scratchTechniqueFlags = new TechniqueFlags(); @@ -204,15 +226,21 @@ export class PrimitiveCommand { const target = exec.target; const thematic = this.primitive.cachedGeometry.supportsThematicDisplay && target.wantThematicDisplay; - const shadowable = (techniqueId === TechniqueId.Surface || techniqueId === TechniqueId.RealityMesh) && target.solarShadowMap.isReady && target.currentViewFlags.shadows && !thematic; + const shadowable = (techniqueId === TechniqueId.Surface || techniqueId === TechniqueId.RealityMesh) && target.solarShadowMap.isReady && + target.currentViewFlags.shadows && !thematic; const isShadowable = shadowable ? IsShadowable.Yes : IsShadowable.No; let isThematic = thematic ? IsThematic.Yes : IsThematic.No; - const isClassified = (undefined !== target.currentPlanarClassifierOrDrape || undefined !== target.activeVolumeClassifierTexture) ? IsClassified.Yes : IsClassified.No; + const isClassified = (undefined !== target.currentPlanarClassifierOrDrape || undefined !== target.activeVolumeClassifierTexture) + ? IsClassified.Yes + : IsClassified.No; const isInstanced = this.primitive.isInstanced ? IsInstanced.Yes : IsInstanced.No; const isAnimated = this.primitive.hasAnimation ? IsAnimated.Yes : IsAnimated.No; // Point clouds do not support hillshade or slope mode for thematic display. - if (isThematic && (undefined !== this.primitive.cachedGeometry.asPointCloud) && (target.uniforms.thematic.wantSlopeMode || target.uniforms.thematic.wantHillShadeMode)) + if ( + isThematic && (undefined !== this.primitive.cachedGeometry.asPointCloud) && + (target.uniforms.thematic.wantSlopeMode || target.uniforms.thematic.wantHillShadeMode) + ) isThematic = IsThematic.No; const wiremesh = target.currentViewFlags.wiremesh && (techniqueId === TechniqueId.Surface || techniqueId === TechniqueId.RealityMesh); @@ -229,8 +257,12 @@ export class PrimitiveCommand { exec.target.compositor.drawPrimitive(this.primitive, exec, program.outputsToPick); } - public get hasFeatures(): boolean { return this.primitive.hasFeatures; } - public get renderOrder(): RenderOrder { return this.primitive.renderOrder; } + public get hasFeatures(): boolean { + return this.primitive.hasFeatures; + } + public get renderOrder(): RenderOrder { + return this.primitive.renderOrder; + } public getPass(target: Target): Pass { return this.primitive.getPass(target); @@ -254,7 +286,11 @@ export type DrawCommands = DrawCommand[]; * The primitive should be right in the middle of a set. We need to find the set which matches the flashID. * @internal */ -export function extractFlashedVolumeClassifierCommands(flashedId: Id64String, cmds: DrawCommands, numCmdsPerClassifier: number): DrawCommands | undefined { +export function extractFlashedVolumeClassifierCommands( + flashedId: Id64String, + cmds: DrawCommands, + numCmdsPerClassifier: number, +): DrawCommands | undefined { if (!Id64.isValid(flashedId) || 0 === numCmdsPerClassifier) return undefined; diff --git a/core/frontend/src/render/webgl/EDL.ts b/core/frontend/src/render/webgl/EDL.ts index e2a3a6d3dd52..cea8f4835672 100644 --- a/core/frontend/src/render/webgl/EDL.ts +++ b/core/frontend/src/render/webgl/EDL.ts @@ -28,17 +28,16 @@ class Bundle implements WebGLDisposable { public edlCalcTex4?: TextureHandle, public edlFiltTex2?: TextureHandle, public edlFiltTex4?: TextureHandle, - public edlCalcFbo1?: FrameBuffer, public edlCalcFbo2?: FrameBuffer, public edlCalcFbo4?: FrameBuffer, public edlFiltFbo2?: FrameBuffer, public edlFiltFbo4?: FrameBuffer, - public edlCalcBasicGeom?: EDLCalcBasicGeometry, public edlCalcFullGeom?: [EDLCalcFullGeometry | undefined, EDLCalcFullGeometry | undefined, EDLCalcFullGeometry | undefined], public edlFiltGeom?: [EDLFilterGeometry | undefined, EDLFilterGeometry | undefined], - public edlMixGeom?: EDLMixGeometry) { + public edlMixGeom?: EDLMixGeometry, + ) { } public static create(width: number, height: number): Bundle | undefined { @@ -47,12 +46,14 @@ class Bundle implements WebGLDisposable { const edlCalcTex4 = TextureHandle.createForAttachment(width >> 2, height >> 2, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte); const edlFiltTex2 = TextureHandle.createForAttachment(width >> 1, height >> 1, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte); const edlFiltTex4 = TextureHandle.createForAttachment(width >> 2, height >> 2, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte); - if (undefined === edlCalcTex1 || undefined === edlCalcTex2 || undefined === edlCalcTex4 || undefined === edlFiltTex2 || undefined === edlFiltTex4) { - dispose (edlCalcTex1); - dispose (edlCalcTex2); - dispose (edlCalcTex4); - dispose (edlFiltTex2); - dispose (edlFiltTex4); + if ( + undefined === edlCalcTex1 || undefined === edlCalcTex2 || undefined === edlCalcTex4 || undefined === edlFiltTex2 || undefined === edlFiltTex4 + ) { + dispose(edlCalcTex1); + dispose(edlCalcTex2); + dispose(edlCalcTex4); + dispose(edlFiltTex2); + dispose(edlFiltTex4); return undefined; } const edlCalcFbo1 = FrameBuffer.create([edlCalcTex1]); @@ -60,15 +61,28 @@ class Bundle implements WebGLDisposable { const edlCalcFbo4 = FrameBuffer.create([edlCalcTex4]); const edlFiltFbo2 = FrameBuffer.create([edlFiltTex2]); const edlFiltFbo4 = FrameBuffer.create([edlFiltTex4]); - if (undefined === edlCalcFbo1 || undefined === edlCalcFbo2 || undefined === edlCalcFbo4 || undefined === edlFiltFbo2 || undefined === edlFiltFbo4) { - dispose (edlCalcFbo1); - dispose (edlCalcFbo2); - dispose (edlCalcFbo4); - dispose (edlFiltFbo2); - dispose (edlFiltFbo4); + if ( + undefined === edlCalcFbo1 || undefined === edlCalcFbo2 || undefined === edlCalcFbo4 || undefined === edlFiltFbo2 || undefined === edlFiltFbo4 + ) { + dispose(edlCalcFbo1); + dispose(edlCalcFbo2); + dispose(edlCalcFbo4); + dispose(edlFiltFbo2); + dispose(edlFiltFbo4); return undefined; } - return new Bundle(edlCalcTex1, edlCalcTex2, edlCalcTex4, edlFiltTex2, edlFiltTex4, edlCalcFbo1, edlCalcFbo2, edlCalcFbo4, edlFiltFbo2, edlFiltFbo4); + return new Bundle( + edlCalcTex1, + edlCalcTex2, + edlCalcTex4, + edlFiltTex2, + edlFiltTex4, + edlCalcFbo1, + edlCalcFbo2, + edlCalcFbo4, + edlFiltFbo2, + edlFiltFbo4, + ); } public get isDisposed(): boolean { @@ -121,14 +135,18 @@ class Bundle implements WebGLDisposable { } /** @internal */ -export enum EDLMode { Off, On, Full } +export enum EDLMode { + Off, + On, + Full, +} /** @internal */ export interface EDLDrawParams { - inputTex: TextureHandle; // input to calc EDL from - curFbo: FrameBuffer; // output fbo to get color texture from for EDL to put result in + inputTex: TextureHandle; // input to calc EDL from + curFbo: FrameBuffer; // output fbo to get color texture from for EDL to put result in edlMode: EDLMode; - edlFilter: boolean; // applies to Full mode only + edlFilter: boolean; // applies to Full mode only useMsBuffers: boolean; } @@ -136,7 +154,7 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { private _bundle?: Bundle; private _width: number; private _height: number; - private _depth?: DepthBuffer; // depth buffer to read from, has to be non-MS and be up to date in draw if MS is used + private _depth?: DepthBuffer; // depth buffer to read from, has to be non-MS and be up to date in draw if MS is used private _edlFinalFbo?: FrameBuffer; private _edlFinalBufs?: { tex: TextureHandle, msBuf: RenderBufferMultiSample | undefined }; private readonly _target: Target; @@ -182,11 +200,13 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { } } - public get isDisposed(): boolean { return undefined === this._bundle && undefined === this._edlFinalFbo; } + public get isDisposed(): boolean { + return undefined === this._bundle && undefined === this._edlFinalFbo; + } public dispose() { this._bundle = dispose(this._bundle); - this._edlFinalFbo = dispose (this._edlFinalFbo); + this._edlFinalFbo = dispose(this._edlFinalFbo); } public reset() { @@ -206,13 +226,20 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { // NB: have to test and create MS buffer as well if useMsBuffers, not outputting to depth const finalBufs = edlParams.curFbo.getColorTargets(edlParams.useMsBuffers, 0); - if (undefined === this._edlFinalFbo || this._edlFinalBufs?.tex !== finalBufs.tex || - (edlParams.useMsBuffers && this._edlFinalBufs?.msBuf !== finalBufs.msBuf)) { - this._edlFinalFbo = dispose (this._edlFinalFbo); + if ( + undefined === this._edlFinalFbo || this._edlFinalBufs?.tex !== finalBufs.tex || + (edlParams.useMsBuffers && this._edlFinalBufs?.msBuf !== finalBufs.msBuf) + ) { + this._edlFinalFbo = dispose(this._edlFinalFbo); this._edlFinalBufs = finalBufs; const filters = [GL.MultiSampling.Filter.Linear]; - this._edlFinalFbo = FrameBuffer.create([this._edlFinalBufs.tex], undefined, - edlParams.useMsBuffers && this._edlFinalBufs.msBuf ? [this._edlFinalBufs.msBuf] : undefined, filters, undefined); + this._edlFinalFbo = FrameBuffer.create( + [this._edlFinalBufs.tex], + undefined, + edlParams.useMsBuffers && this._edlFinalBufs.msBuf ? [this._edlFinalBufs.msBuf] : undefined, + filters, + undefined, + ); if (undefined === this._edlFinalFbo) return false; } @@ -241,9 +268,11 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { const ct2 = bundle.edlCalcTex2; const ct4 = bundle.edlCalcTex4; const ctd = this._depth.getHandle()!; - bundle.edlCalcFullGeom = [EDLCalcFullGeometry.createGeometry(ct1.getHandle()!, ctd, 1, ct1.width, ct1.height), + bundle.edlCalcFullGeom = [ + EDLCalcFullGeometry.createGeometry(ct1.getHandle()!, ctd, 1, ct1.width, ct1.height), EDLCalcFullGeometry.createGeometry(ct1.getHandle()!, ctd, 2, ct2!.width, ct2!.height), - EDLCalcFullGeometry.createGeometry(ct1.getHandle()!, ctd, 4, ct4!.width, ct4!.height)]; + EDLCalcFullGeometry.createGeometry(ct1.getHandle()!, ctd, 4, ct4!.width, ct4!.height), + ]; } const edlFiltFbos: FrameBuffer[] = [bundle.edlFiltFbo2!, bundle.edlFiltFbo4!]; @@ -251,8 +280,10 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { const ft2 = bundle.edlCalcTex2; const ft4 = bundle.edlCalcTex4; const ftd = this._depth.getHandle()!; - bundle.edlFiltGeom = [EDLFilterGeometry.createGeometry(ft2!.getHandle()!, ftd, 2, ft2!.width, ft2!.height), - EDLFilterGeometry.createGeometry(ft4!.getHandle()!, ftd, 4, ft4!.width, ft4!.height)]; + bundle.edlFiltGeom = [ + EDLFilterGeometry.createGeometry(ft2!.getHandle()!, ftd, 2, ft2!.width, ft2!.height), + EDLFilterGeometry.createGeometry(ft4!.getHandle()!, ftd, 4, ft4!.width, ft4!.height), + ]; } const gl = System.instance.context; @@ -266,8 +297,8 @@ export class EyeDomeLighting implements RenderMemory.Consumer, WebGLDisposable { }); if (edlParams.edlFilter && i > 0) { - fbStack.execute(edlFiltFbos[i-1], true, false, () => { - const params = getDrawParams(this._target, bundle.edlFiltGeom![i-1]!); + fbStack.execute(edlFiltFbos[i - 1], true, false, () => { + const params = getDrawParams(this._target, bundle.edlFiltGeom![i - 1]!); this._target.techniques.draw(params); }); } diff --git a/core/frontend/src/render/webgl/EdgeGeometry.ts b/core/frontend/src/render/webgl/EdgeGeometry.ts index e56838441b54..66850d978d5f 100644 --- a/core/frontend/src/render/webgl/EdgeGeometry.ts +++ b/core/frontend/src/render/webgl/EdgeGeometry.ts @@ -8,21 +8,21 @@ import { assert, dispose } from "@itwin/core-bentley"; import { RenderMode } from "@itwin/core-common"; +import { SegmentEdgeParams, SilhouetteParams } from "../../common/internal/render/EdgeParams"; import { TesselatedPolyline } from "../../common/internal/render/PolylineParams"; import { RenderMemory } from "../RenderMemory"; +import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { PolylineBuffers } from "./CachedGeometry"; import { ColorInfo } from "./ColorInfo"; import { ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; +import { MeshData } from "./MeshData"; +import { MeshGeometry } from "./MeshGeometry"; import { RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { MeshData } from "./MeshData"; -import { MeshGeometry } from "./MeshGeometry"; -import { SegmentEdgeParams, SilhouetteParams } from "../../common/internal/render/EdgeParams"; /** @internal */ export class EdgeGeometry extends MeshGeometry { @@ -30,15 +30,25 @@ export class EdgeGeometry extends MeshGeometry { protected readonly _indices: BufferHandle; protected readonly _endPointAndQuadIndices: BufferHandle; - public get lutBuffers() { return this.buffers; } - public override get asSurface() { return undefined; } - public override get asEdge() { return this; } - public override get asSilhouette(): SilhouetteEdgeGeometry | undefined { return undefined; } + public get lutBuffers() { + return this.buffers; + } + public override get asSurface() { + return undefined; + } + public override get asEdge() { + return this; + } + public override get asSilhouette(): SilhouetteEdgeGeometry | undefined { + return undefined; + } public static create(mesh: MeshData, edges: SegmentEdgeParams): EdgeGeometry | undefined { const indexBuffer = BufferHandle.createArrayBuffer(edges.indices.data); const endPointBuffer = BufferHandle.createArrayBuffer(edges.endPointAndQuadIndices); - return undefined !== indexBuffer && undefined !== endPointBuffer ? new EdgeGeometry(indexBuffer, endPointBuffer, edges.indices.length, mesh) : undefined; + return undefined !== indexBuffer && undefined !== endPointBuffer + ? new EdgeGeometry(indexBuffer, endPointBuffer, edges.indices.length, mesh) + : undefined; } public get isDisposed(): boolean { @@ -65,13 +75,27 @@ export class EdgeGeometry extends MeshGeometry { bufs.unbind(); } - protected _wantWoWReversal(_target: Target): boolean { return true; } - protected override _getLineCode(params: ShaderProgramParams): number { return this.computeEdgeLineCode(params); } - public get techniqueId(): TechniqueId { return TechniqueId.Edge; } - public override getPass(target: Target) { return this.computeEdgePass(target); } - public get renderOrder(): RenderOrder { return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; } - public override getColor(target: Target): ColorInfo { return this.computeEdgeColor(target); } - public get endPointAndQuadIndices(): BufferHandle { return this._endPointAndQuadIndices; } + protected _wantWoWReversal(_target: Target): boolean { + return true; + } + protected override _getLineCode(params: ShaderProgramParams): number { + return this.computeEdgeLineCode(params); + } + public get techniqueId(): TechniqueId { + return TechniqueId.Edge; + } + public override getPass(target: Target) { + return this.computeEdgePass(target); + } + public get renderOrder(): RenderOrder { + return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; + } + public override getColor(target: Target): ColorInfo { + return this.computeEdgeColor(target); + } + public get endPointAndQuadIndices(): BufferHandle { + return this._endPointAndQuadIndices; + } public override wantMonochrome(target: Target): boolean { return target.currentViewFlags.renderMode === RenderMode.Wireframe; } @@ -84,7 +108,9 @@ export class EdgeGeometry extends MeshGeometry { assert(attrPos !== undefined); assert(attrEndPointAndQuadIndices !== undefined); this.buffers.addBuffer(indices, [BufferParameters.create(attrPos.location, 3, GL.DataType.UnsignedByte, false, 0, 0, false)]); - this.buffers.addBuffer(endPointAndQuadsIndices, [BufferParameters.create(attrEndPointAndQuadIndices.location, 4, GL.DataType.UnsignedByte, false, 0, 0, false)]); + this.buffers.addBuffer(endPointAndQuadsIndices, [ + BufferParameters.create(attrEndPointAndQuadIndices.location, 4, GL.DataType.UnsignedByte, false, 0, 0, false), + ]); this._indices = indices; this._endPointAndQuadIndices = endPointAndQuadsIndices; } @@ -94,16 +120,22 @@ export class EdgeGeometry extends MeshGeometry { export class SilhouetteEdgeGeometry extends EdgeGeometry { private readonly _normalPairs: BufferHandle; - public override get asSilhouette() { return this; } + public override get asSilhouette() { + return this; + } public static createSilhouettes(mesh: MeshData, params: SilhouetteParams): SilhouetteEdgeGeometry | undefined { const indexBuffer = BufferHandle.createArrayBuffer(params.indices.data); const endPointBuffer = BufferHandle.createArrayBuffer(params.endPointAndQuadIndices); const normalsBuffer = BufferHandle.createArrayBuffer(params.normalPairs); - return undefined !== indexBuffer && undefined !== endPointBuffer && undefined !== normalsBuffer ? new SilhouetteEdgeGeometry(indexBuffer, endPointBuffer, normalsBuffer, params.indices.length, mesh) : undefined; + return undefined !== indexBuffer && undefined !== endPointBuffer && undefined !== normalsBuffer + ? new SilhouetteEdgeGeometry(indexBuffer, endPointBuffer, normalsBuffer, params.indices.length, mesh) + : undefined; } - public override get isDisposed(): boolean { return super.isDisposed && this._normalPairs.isDisposed; } + public override get isDisposed(): boolean { + return super.isDisposed && this._normalPairs.isDisposed; + } public override dispose() { super.dispose(); @@ -114,9 +146,15 @@ export class SilhouetteEdgeGeometry extends EdgeGeometry { stats.addSilhouetteEdges(this._indices.bytesUsed + this._endPointAndQuadIndices.bytesUsed + this._normalPairs.bytesUsed); } - public override get techniqueId(): TechniqueId { return TechniqueId.SilhouetteEdge; } - public override get renderOrder(): RenderOrder { return this.isPlanar ? RenderOrder.PlanarSilhouette : RenderOrder.Silhouette; } - public get normalPairs(): BufferHandle { return this._normalPairs; } + public override get techniqueId(): TechniqueId { + return TechniqueId.SilhouetteEdge; + } + public override get renderOrder(): RenderOrder { + return this.isPlanar ? RenderOrder.PlanarSilhouette : RenderOrder.Silhouette; + } + public get normalPairs(): BufferHandle { + return this._normalPairs; + } private constructor(indices: BufferHandle, endPointAndQuadsIndices: BufferHandle, normalPairs: BufferHandle, numIndices: number, mesh: MeshData) { super(indices, endPointAndQuadsIndices, numIndices, mesh); @@ -131,14 +169,18 @@ export class SilhouetteEdgeGeometry extends EdgeGeometry { export class PolylineEdgeGeometry extends MeshGeometry { private _buffers: PolylineBuffers; - public get lutBuffers() { return this._buffers.buffers; } + public get lutBuffers() { + return this._buffers.buffers; + } public static create(mesh: MeshData, polyline: TesselatedPolyline): PolylineEdgeGeometry | undefined { const buffers = PolylineBuffers.create(polyline); return undefined !== buffers ? new PolylineEdgeGeometry(polyline.indices.length, buffers, mesh) : undefined; } - public get isDisposed(): boolean { return this._buffers.isDisposed; } + public get isDisposed(): boolean { + return this._buffers.isDisposed; + } public dispose() { dispose(this._buffers); @@ -148,14 +190,30 @@ export class PolylineEdgeGeometry extends MeshGeometry { this._buffers.collectStatistics(stats, RenderMemory.BufferType.PolylineEdges); } - protected _wantWoWReversal(_target: Target): boolean { return true; } - protected override _getLineWeight(params: ShaderProgramParams): number { return this.computeEdgeWeight(params); } - protected override _getLineCode(params: ShaderProgramParams): number { return this.computeEdgeLineCode(params); } - public override getColor(target: Target): ColorInfo { return this.computeEdgeColor(target); } - public get techniqueId(): TechniqueId { return TechniqueId.Polyline; } - public override getPass(target: Target) { return this.computeEdgePass(target); } - public get renderOrder(): RenderOrder { return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; } - public override get polylineBuffers(): PolylineBuffers { return this._buffers; } + protected _wantWoWReversal(_target: Target): boolean { + return true; + } + protected override _getLineWeight(params: ShaderProgramParams): number { + return this.computeEdgeWeight(params); + } + protected override _getLineCode(params: ShaderProgramParams): number { + return this.computeEdgeLineCode(params); + } + public override getColor(target: Target): ColorInfo { + return this.computeEdgeColor(target); + } + public get techniqueId(): TechniqueId { + return TechniqueId.Polyline; + } + public override getPass(target: Target) { + return this.computeEdgePass(target); + } + public get renderOrder(): RenderOrder { + return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; + } + public override get polylineBuffers(): PolylineBuffers { + return this._buffers; + } public override wantMonochrome(target: Target): boolean { return target.currentViewFlags.renderMode === RenderMode.Wireframe; diff --git a/core/frontend/src/render/webgl/EdgeSettings.ts b/core/frontend/src/render/webgl/EdgeSettings.ts index c205ad04b9f2..0c8fd980f3bf 100644 --- a/core/frontend/src/render/webgl/EdgeSettings.ts +++ b/core/frontend/src/render/webgl/EdgeSettings.ts @@ -7,10 +7,10 @@ */ import { ColorDef, HiddenLine, RenderMode, ViewFlags } from "@itwin/core-common"; +import { OvrFlags } from "../../common/internal/render/OvrFlags"; import { FloatRgba } from "./FloatRGBA"; -import { RenderPass } from "./RenderFlags"; import { LineCode } from "./LineCode"; -import { OvrFlags } from "../../common/internal/render/OvrFlags"; +import { RenderPass } from "./RenderFlags"; /** Controls symbology of edges based on ViewFlags and HiddenLine.Settings. Typically these come from the Target's * RenderPlan, but a GraphicBranch may override those settings. @@ -51,7 +51,7 @@ export class EdgeSettings { this._color.setColorDef(vis.color); } - this._visibleLineCode = (undefined !== vis.pattern ? LineCode.valueFromLinePixels(vis.pattern) : undefined); + this._visibleLineCode = undefined !== vis.pattern ? LineCode.valueFromLinePixels(vis.pattern) : undefined; this._visibleWeight = vis.width; // Hidden edge settings default to matching visible edge settings. diff --git a/core/frontend/src/render/webgl/FeatureOverrides.ts b/core/frontend/src/render/webgl/FeatureOverrides.ts index f2d6495083d3..2c4de88d3984 100644 --- a/core/frontend/src/render/webgl/FeatureOverrides.ts +++ b/core/frontend/src/render/webgl/FeatureOverrides.ts @@ -8,20 +8,20 @@ import { assert, dispose, Id64 } from "@itwin/core-bentley"; import { PackedFeature, RenderFeatureTable } from "@itwin/core-common"; +import { DisplayParams } from "../../common/internal/render/DisplayParams"; +import { OvrFlags } from "../../common/internal/render/OvrFlags"; +import { computeDimensions } from "../../common/internal/render/VertexTable"; +import { BatchOptions } from "../../common/render/BatchOptions"; import { FeatureSymbology } from "../FeatureSymbology"; import { WebGLDisposable } from "./Disposable"; -import { LineCode } from "./LineCode"; import { GL } from "./GL"; -import { UniformHandle } from "./UniformHandle"; +import { LineCode } from "./LineCode"; import { EmphasisFlags, TextureUnit } from "./RenderFlags"; import { sync, SyncObserver } from "./Sync"; import { System } from "./System"; import { Hilites, Target } from "./Target"; import { Texture2DDataUpdater, Texture2DHandle, TextureHandle } from "./Texture"; -import { BatchOptions } from "../../common/render/BatchOptions"; -import { DisplayParams } from "../../common/internal/render/DisplayParams"; -import { OvrFlags } from "../../common/internal/render/OvrFlags"; -import { computeDimensions } from "../../common/internal/render/VertexTable"; +import { UniformHandle } from "./UniformHandle"; export function isFeatureHilited(feature: PackedFeature, hilites: Hilites, isModelHilited: boolean): boolean { if (hilites.isEmpty) @@ -57,17 +57,35 @@ export class FeatureOverrides implements WebGLDisposable { private _uniformSymbologyFlags: EmphasisFlags = EmphasisFlags.None; private _cleanup?: FeatureOverridesCleanup; - public get anyOverridden() { return this._anyOverridden; } - public get allHidden() { return this._allHidden; } - public get anyTranslucent() { return this._anyTranslucent; } - public get anyViewIndependentTranslucent() { return this._anyViewIndependentTranslucent; } - public get anyOpaque() { return this._anyOpaque; } - public get anyHilited() { return this._anyHilited; } + public get anyOverridden() { + return this._anyOverridden; + } + public get allHidden() { + return this._allHidden; + } + public get anyTranslucent() { + return this._anyTranslucent; + } + public get anyViewIndependentTranslucent() { + return this._anyViewIndependentTranslucent; + } + public get anyOpaque() { + return this._anyOpaque; + } + public get anyHilited() { + return this._anyHilited; + } /** For tests. */ - public get lutData(): Uint8Array | undefined { return this._lut?.dataBytes; } - public get byteLength(): number { return undefined !== this._lut ? this._lut.bytesUsed : 0; } - public get isUniform() { return 3 === this._lutParams[0] && 1 === this._lutParams[1]; } + public get lutData(): Uint8Array | undefined { + return this._lut?.dataBytes; + } + public get byteLength(): number { + return undefined !== this._lut ? this._lut.bytesUsed : 0; + } + public get isUniform() { + return 3 === this._lutParams[0] && 1 === this._lutParams[1]; + } private updateUniformSymbologyFlags(): void { this._uniformSymbologyFlags = EmphasisFlags.None; @@ -99,7 +117,13 @@ export class FeatureOverrides implements WebGLDisposable { return this._lut.dataBytes; } - private _initialize(map: RenderFeatureTable, ovrs: FeatureSymbology.Overrides, pickExcludes: Id64.Uint32Set, hilite: Hilites, flashed?: Id64.Uint32Pair): Texture2DHandle | undefined { + private _initialize( + map: RenderFeatureTable, + ovrs: FeatureSymbology.Overrides, + pickExcludes: Id64.Uint32Set, + hilite: Hilites, + flashed?: Id64.Uint32Pair, + ): Texture2DHandle | undefined { const nFeatures = map.numFeatures; const dims = computeDimensions(nFeatures, 3, 0, System.instance.maxTextureSize); const width = dims.width; @@ -116,7 +140,14 @@ export class FeatureOverrides implements WebGLDisposable { return TextureHandle.createForData(width, height, data, true, GL.Texture.WrapMode.ClampToEdge); } - private _update(map: RenderFeatureTable, lut: Texture2DHandle, pickExcludes: Id64.Uint32Set | undefined, flashed?: Id64.Uint32Pair, hilites?: Hilites, ovrs?: FeatureSymbology.Overrides) { + private _update( + map: RenderFeatureTable, + lut: Texture2DHandle, + pickExcludes: Id64.Uint32Set | undefined, + flashed?: Id64.Uint32Pair, + hilites?: Hilites, + ovrs?: FeatureSymbology.Overrides, + ) { const updater = new Texture2DDataUpdater(lut.dataBytes!); if (undefined === ovrs) { @@ -129,7 +160,13 @@ export class FeatureOverrides implements WebGLDisposable { lut.update(updater); } - private setTransparency(transparency: number, viewDependentTransparency: true | undefined, data: Texture2DDataUpdater, transparencyByteIndex: number, curFlags: OvrFlags): OvrFlags { + private setTransparency( + transparency: number, + viewDependentTransparency: true | undefined, + data: Texture2DDataUpdater, + transparencyByteIndex: number, + curFlags: OvrFlags, + ): OvrFlags { // transparency in range [0, 1]...convert to byte and invert so 0=transparent... let alpha = 1.0 - transparency; alpha = Math.floor(0xff * alpha + 0.5); @@ -150,7 +187,14 @@ export class FeatureOverrides implements WebGLDisposable { return curFlags; } - private buildLookupTable(data: Texture2DDataUpdater, map: RenderFeatureTable, ovr: FeatureSymbology.Overrides, pickExclude: Id64.Uint32Set | undefined, flashedIdParts: Id64.Uint32Pair | undefined, hilites: Hilites) { + private buildLookupTable( + data: Texture2DDataUpdater, + map: RenderFeatureTable, + ovr: FeatureSymbology.Overrides, + pickExclude: Id64.Uint32Set | undefined, + flashedIdParts: Id64.Uint32Pair | undefined, + hilites: Hilites, + ) { const allowHilite = true !== this._options.noHilite; const allowFlash = true !== this._options.noFlash; const allowEmphasis = true !== this._options.noEmphasis; @@ -158,7 +202,11 @@ export class FeatureOverrides implements WebGLDisposable { let isModelHilited = false; const prevModelId = { lower: -1, upper: -1 }; - this._anyOpaque = this._anyTranslucent = this._anyViewIndependentTranslucent = this._anyHilited = false; + this._anyOpaque = + this._anyTranslucent = + this._anyViewIndependentTranslucent = + this._anyHilited = + false; let nHidden = 0; let nOverridden = 0; @@ -186,11 +234,16 @@ export class FeatureOverrides implements WebGLDisposable { const app = this.target.currentBranch.getFeatureAppearance( ovr, - feature.elementId.lower, feature.elementId.upper, - feature.subCategoryId.lower, feature.subCategoryId.upper, + feature.elementId.lower, + feature.elementId.upper, + feature.subCategoryId.lower, + feature.subCategoryId.upper, feature.geometryClass, - feature.modelId.lower, feature.modelId.upper, - map.type, feature.animationNodeId); + feature.modelId.lower, + feature.modelId.upper, + map.type, + feature.animationNodeId, + ); // NB: If the appearance is fully transparent, then: // - For normal ("primary") models, getAppearance() returns undefined. @@ -259,7 +312,10 @@ export class FeatureOverrides implements WebGLDisposable { if (app.ignoresMaterial) flags |= OvrFlags.IgnoreMaterial; - if (allowFlash && undefined !== flashedIdParts && feature.elementId.lower === flashedIdParts.lower && feature.elementId.upper === flashedIdParts.upper) + if ( + allowFlash && undefined !== flashedIdParts && feature.elementId.lower === flashedIdParts.lower && + feature.elementId.upper === flashedIdParts.upper + ) flags |= OvrFlags.Flashed; if (pickExclude?.hasPair(feature.elementId)) { @@ -272,14 +328,20 @@ export class FeatureOverrides implements WebGLDisposable { nOverridden++; } - this._allHidden = (nHidden === map.numFeatures); - this._anyOverridden = (nOverridden > 0); + this._allHidden = nHidden === map.numFeatures; + this._anyOverridden = nOverridden > 0; this.updateUniformSymbologyFlags(); } // NB: If hilites is undefined, it means that the hilited set has not changed. - private updateFlashedAndHilited(data: Texture2DDataUpdater, map: RenderFeatureTable, pickExcludes: Id64.Uint32Set | undefined, flashed?: Id64.Uint32Pair, hilites?: Hilites) { + private updateFlashedAndHilited( + data: Texture2DDataUpdater, + map: RenderFeatureTable, + pickExcludes: Id64.Uint32Set | undefined, + flashed?: Id64.Uint32Pair, + hilites?: Hilites, + ) { if (!hilites || true === this._options.noHilite) { this.updateFlashed(data, map, pickExcludes, flashed); return; @@ -303,9 +365,10 @@ export class FeatureOverrides implements WebGLDisposable { if (!isHilited) isHilited = hilites.elements.hasPair(feature.elementId); - if (!isHilited) + if (!isHilited) { if (isModelHilited || !intersect) isHilited = hilites.subcategories.hasPair(feature.subCategoryId); + } let isFlashed = false; if (flashed && allowFlash) @@ -327,7 +390,12 @@ export class FeatureOverrides implements WebGLDisposable { this.updateUniformSymbologyFlags(); } - private updateFlashed(data: Texture2DDataUpdater, map: RenderFeatureTable, pickExcludes: Id64.Uint32Set | undefined, flashed?: Id64.Uint32Pair): void { + private updateFlashed( + data: Texture2DDataUpdater, + map: RenderFeatureTable, + pickExcludes: Id64.Uint32Set | undefined, + flashed?: Id64.Uint32Pair, + ): void { if (true === this._options.noFlash && !pickExcludes) return; @@ -376,7 +444,9 @@ export class FeatureOverrides implements WebGLDisposable { return new FeatureOverrides(target, options, cleanup); } - public get isDisposed(): boolean { return undefined === this._lut; } + public get isDisposed(): boolean { + return undefined === this._lut; + } public dispose() { this._lut = dispose(this._lut); @@ -423,7 +493,8 @@ export class FeatureOverrides implements WebGLDisposable { this._lut, undefined !== ovrs || pickExcludesUpdated ? this.target.pickExclusions : undefined, this.target.flashed, - undefined !== ovrs || hiliteUpdated ? hilite : undefined, ovrs, + undefined !== ovrs || hiliteUpdated ? hilite : undefined, + ovrs, ); } diff --git a/core/frontend/src/render/webgl/FloatRGBA.ts b/core/frontend/src/render/webgl/FloatRGBA.ts index ee806994f0d8..5b5a7725d91f 100644 --- a/core/frontend/src/render/webgl/FloatRGBA.ts +++ b/core/frontend/src/render/webgl/FloatRGBA.ts @@ -29,11 +29,21 @@ export abstract class FloatColor { protected abstract maskTbgr(tbgr: number): number; protected abstract setComponents(r: number, g: number, b: number, a: number): void; - public get red() { return this._components[0]; } - public get green() { return this._components[1]; } - public get blue() { return this._components[2]; } - public get tbgr() { return this._tbgr; } - public get isWhite() { return 1.0 === this.red && 1.0 === this.green && 1.0 === this.blue; } + public get red() { + return this._components[0]; + } + public get green() { + return this._components[1]; + } + public get blue() { + return this._components[2]; + } + public get tbgr() { + return this._tbgr; + } + public get isWhite() { + return 1.0 === this.red && 1.0 === this.green && 1.0 === this.blue; + } public setColorDef(def: ColorDef) { this.setTbgr(def.tbgr); @@ -132,9 +142,15 @@ export class FloatRgba extends FloatColor { this.setRgbaComponents(r, g, b, a); } - public get alpha(): number { return this._components[3]; } - public set alpha(alpha: number) { this._components[3] = alpha; } - public get hasTranslucency(): boolean { return 1.0 !== this.alpha; } + public get alpha(): number { + return this._components[3]; + } + public set alpha(alpha: number) { + this._components[3] = alpha; + } + public get hasTranslucency(): boolean { + return 1.0 !== this.alpha; + } public bind(uniform: UniformHandle): void { uniform.setUniform4fv(this._components); diff --git a/core/frontend/src/render/webgl/FrameBuffer.ts b/core/frontend/src/render/webgl/FrameBuffer.ts index 855f32b72f38..bc33030ad484 100644 --- a/core/frontend/src/render/webgl/FrameBuffer.ts +++ b/core/frontend/src/render/webgl/FrameBuffer.ts @@ -39,15 +39,25 @@ export class FrameBuffer implements WebGLDisposable { public readonly depthBuffer?: DepthBuffer; public readonly depthBufferMs?: DepthBuffer; - public get isDisposed(): boolean { return this._fbo === undefined; } + public get isDisposed(): boolean { + return this._fbo === undefined; + } - public get isBound(): boolean { return FrameBufferBindState.Bound <= this._bindState && FrameBufferBindState.BoundWithAttachmentsMultisampled >= this._bindState; } + public get isBound(): boolean { + return FrameBufferBindState.Bound <= this._bindState && FrameBufferBindState.BoundWithAttachmentsMultisampled >= this._bindState; + } - public get isBoundMultisampled(): boolean { return FrameBufferBindState.BoundMultisampled === this._bindState || FrameBufferBindState.BoundWithAttachmentsMultisampled === this._bindState; } + public get isBoundMultisampled(): boolean { + return FrameBufferBindState.BoundMultisampled === this._bindState || FrameBufferBindState.BoundWithAttachmentsMultisampled === this._bindState; + } - public get isSuspended(): boolean { return FrameBufferBindState.Suspended === this._bindState; } + public get isSuspended(): boolean { + return FrameBufferBindState.Suspended === this._bindState; + } - public get isMultisampled(): boolean { return this._colorMsBuffers.length > 0 || undefined !== this.depthBufferMs; } + public get isMultisampled(): boolean { + return this._colorMsBuffers.length > 0 || undefined !== this.depthBufferMs; + } public getColor(ndx: number): TextureHandle { assert(ndx < this._colorTextures.length); @@ -60,15 +70,21 @@ export class FrameBuffer implements WebGLDisposable { public getColorTargets(useMSBuffers: boolean, ndx: number): { tex: TextureHandle, msBuf: RenderBufferMultiSample | undefined } { let msBuf; if (useMSBuffers) { - assert (ndx < this._colorMsBuffers.length); - msBuf = this._colorMsBuffers[ndx]; + assert(ndx < this._colorMsBuffers.length); + msBuf = this._colorMsBuffers[ndx]; } assert(ndx < this._colorTextures.length); return { tex: this._colorTextures[ndx], msBuf }; } - private constructor(fbo: WebGLFramebuffer, colorTextures: TextureHandle[], depthBuffer?: DepthBuffer, - colorMsBuffers?: RenderBufferMultiSample[], msFilters?: GL.MultiSampling.Filter[], depthBufferMs?: DepthBuffer) { + private constructor( + fbo: WebGLFramebuffer, + colorTextures: TextureHandle[], + depthBuffer?: DepthBuffer, + colorMsBuffers?: RenderBufferMultiSample[], + msFilters?: GL.MultiSampling.Filter[], + depthBufferMs?: DepthBuffer, + ) { this._fbo = fbo; const gl = System.instance.context; @@ -103,7 +119,10 @@ export class FrameBuffer implements WebGLDisposable { this.unbind(); - if (undefined !== colorMsBuffers && colorMsBuffers.length === colorTextures.length && undefined !== msFilters && msFilters.length === colorMsBuffers.length) { + if ( + undefined !== colorMsBuffers && colorMsBuffers.length === colorTextures.length && undefined !== msFilters && + msFilters.length === colorMsBuffers.length + ) { // Create a matching FBO with multisampling render buffers. const fbo2 = System.instance.context.createFramebuffer(); if (null !== fbo2) { @@ -132,7 +151,13 @@ export class FrameBuffer implements WebGLDisposable { } } - public static create(colorTextures: TextureHandle[], depthBuffer?: DepthBuffer, colorMsBuffers?: RenderBufferMultiSample[], msFilters?: GL.MultiSampling.Filter[], depthBufferMs?: DepthBuffer): FrameBuffer | undefined { + public static create( + colorTextures: TextureHandle[], + depthBuffer?: DepthBuffer, + colorMsBuffers?: RenderBufferMultiSample[], + msFilters?: GL.MultiSampling.Filter[], + depthBufferMs?: DepthBuffer, + ): FrameBuffer | undefined { const fbo: WebGLFramebuffer | null = System.instance.context.createFramebuffer(); if (null === fbo) { return undefined; @@ -204,7 +229,7 @@ export class FrameBuffer implements WebGLDisposable { System.instance.frameBufferStack.suspend(); const gl2 = System.instance.context; const attachments = []; - const max = (undefined === ndx ? this._colorMsBuffers.length : ndx + 1); + const max = undefined === ndx ? this._colorMsBuffers.length : ndx + 1; for (let i = 0; i < max; ++i) { if (undefined !== ndx && i < ndx) { attachments.push(gl2.NONE); // skip this one, but first add a NONE for it in the attachment list @@ -218,9 +243,18 @@ export class FrameBuffer implements WebGLDisposable { gl2.drawBuffers(attachments); attachments.pop(); attachments.push(gl2.NONE); - gl2.blitFramebuffer(0, 0, this._colorTextures[i].width, this._colorTextures[i].height, - 0, 0, this._colorTextures[i].width, this._colorTextures[i].height, - GL.BufferBit.Color, this._colorMsFilters[i]); + gl2.blitFramebuffer( + 0, + 0, + this._colorTextures[i].width, + this._colorTextures[i].height, + 0, + 0, + this._colorTextures[i].width, + this._colorTextures[i].height, + GL.BufferBit.Color, + this._colorMsFilters[i], + ); this._colorMsBuffers[i].markBufferDirty(false); if (undefined !== ndx && i === ndx) break; @@ -230,9 +264,18 @@ export class FrameBuffer implements WebGLDisposable { const mask = GL.BufferBit.Depth; // (this.depthBuffer instanceof RenderBuffer ? GL.BufferBit.Depth : GL.BufferBit.Depth | GL.BufferBit.Stencil); gl2.bindFramebuffer(gl2.READ_FRAMEBUFFER, this._fboMs); gl2.bindFramebuffer(gl2.DRAW_FRAMEBUFFER, this._fbo!); - gl2.blitFramebuffer(0, 0, this.depthBuffer.width, this.depthBuffer.height, - 0, 0, this.depthBuffer.width, this.depthBuffer.height, - mask, GL.MultiSampling.Filter.Nearest); + gl2.blitFramebuffer( + 0, + 0, + this.depthBuffer.width, + this.depthBuffer.height, + 0, + 0, + this.depthBuffer.width, + this.depthBuffer.height, + mask, + GL.MultiSampling.Filter.Nearest, + ); (this.depthBufferMs as RenderBufferMultiSample).markBufferDirty(false); } gl2.bindFramebuffer(gl2.READ_FRAMEBUFFER, null); @@ -246,7 +289,9 @@ export class FrameBuffer implements WebGLDisposable { */ public invalidate(invDepth: boolean, invStencil: boolean, withMultiSampling: boolean, indices?: number[]): void { const gl = System.instance.context; - const attachments: number[] = invDepth ? (invStencil ? [gl.DEPTH_STENCIL_ATTACHMENT] : [System.instance.context.DEPTH_ATTACHMENT]) : (invDepth ? [gl.STENCIL_ATTACHMENT] : []); + const attachments: number[] = invDepth + ? (invStencil ? [gl.DEPTH_STENCIL_ATTACHMENT] : [System.instance.context.DEPTH_ATTACHMENT]) + : (invDepth ? [gl.STENCIL_ATTACHMENT] : []); if (undefined !== indices) { if (indices.length > 0) { for (const i of indices) @@ -293,7 +338,9 @@ export class FrameBufferStack { // FrameBuffers within this array are not owned, as this is only a storage device holding references private readonly _stack: Binding[] = []; - private get _top() { return !this.isEmpty ? this._stack[this._stack.length - 1] : undefined; } + private get _top() { + return !this.isEmpty ? this._stack[this._stack.length - 1] : undefined; + } public push(fbo: FrameBuffer, withAttachments: boolean, withMultSampling: boolean): void { if (undefined !== this._top) { @@ -339,7 +386,9 @@ export class FrameBufferStack { return undefined !== this._top ? this._top.fbo.isBoundMultisampled : false; } - public get isEmpty(): boolean { return 0 === this._stack.length; } + public get isEmpty(): boolean { + return 0 === this._stack.length; + } public execute(fbo: FrameBuffer, withAttachments: boolean, withMultSampling: boolean, func: () => void) { this.push(fbo, withAttachments, withMultSampling); diff --git a/core/frontend/src/render/webgl/FrustumUniforms.ts b/core/frontend/src/render/webgl/FrustumUniforms.ts index 07db1e44d63d..b6670a309cec 100644 --- a/core/frontend/src/render/webgl/FrustumUniforms.ts +++ b/core/frontend/src/render/webgl/FrustumUniforms.ts @@ -6,12 +6,12 @@ * @module WebGL */ -import { InverseMatrixState, Matrix4d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { Frustum, Npc } from "@itwin/core-common"; -import { UniformHandle } from "./UniformHandle"; +import { InverseMatrixState, Matrix4d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { IModelFrameLifecycle } from "./IModelFrameLifecycle"; import { Matrix4 } from "./Matrix"; import { desync, sync } from "./Sync"; +import { UniformHandle } from "./UniformHandle"; /** @internal */ export const enum FrustumUniformType { // eslint-disable-line no-restricted-syntax @@ -81,19 +81,35 @@ export class FrustumUniforms { } // uniform vec4 u_frustumPlanes; // { top, bottom, left, right } - public get planes(): Float32Array { return this._planeData; } + public get planes(): Float32Array { + return this._planeData; + } // uniform vec3 u_frustum; // { near, far, type } - public get frustum(): Float32Array { return this._frustumData; } + public get frustum(): Float32Array { + return this._frustumData; + } - public get nearPlane(): number { return this._frustumData[FrustumData.kNear]; } - public get farPlane(): number { return this._frustumData[FrustumData.kFar]; } - public get type(): FrustumUniformType { return this.frustum[FrustumData.kType] as FrustumUniformType; } - public get is2d(): boolean { return FrustumUniformType.TwoDee === this.type; } - public get planFraction(): number { return this._planFraction; } + public get nearPlane(): number { + return this._frustumData[FrustumData.kNear]; + } + public get farPlane(): number { + return this._frustumData[FrustumData.kFar]; + } + public get type(): FrustumUniformType { + return this.frustum[FrustumData.kType] as FrustumUniformType; + } + public get is2d(): boolean { + return FrustumUniformType.TwoDee === this.type; + } + public get planFraction(): number { + return this._planFraction; + } // uniform vec2 u_logZ where x = 1/near and y = log(far/near) - public get logZ(): Float32Array { return this._logZData; } + public get logZ(): Float32Array { + return this._logZData; + } public changeFrustum(newFrustum: Frustum, newFraction: number, is3d: boolean): void { if (newFraction === this._planFraction && is3d !== this.is2d && newFrustum.equals(this.planFrustum)) @@ -247,18 +263,44 @@ function lookIn(eye: Point3d, viewX: Vector3d, viewY: Vector3d, viewZ: Vector3d, function ortho(left: number, right: number, bottom: number, top: number, near: number, far: number, result: Matrix4d) { Matrix4d.createRowValues( - 2.0 / (right - left), 0.0, 0.0, -(right + left) / (right - left), - 0.0, 2.0 / (top - bottom), 0.0, -(top + bottom) / (top - bottom), - 0.0, 0.0, -2.0 / (far - near), -(far + near) / (far - near), - 0.0, 0.0, 0.0, 1.0, - result); + 2.0 / (right - left), + 0.0, + 0.0, + -(right + left) / (right - left), + 0.0, + 2.0 / (top - bottom), + 0.0, + -(top + bottom) / (top - bottom), + 0.0, + 0.0, + -2.0 / (far - near), + -(far + near) / (far - near), + 0.0, + 0.0, + 0.0, + 1.0, + result, + ); } function frustum(left: number, right: number, bottom: number, top: number, near: number, far: number, result: Matrix4d) { Matrix4d.createRowValues( - (2.0 * near) / (right - left), 0.0, (right + left) / (right - left), 0.0, - 0.0, (2.0 * near) / (top - bottom), (top + bottom) / (top - bottom), 0.0, - 0.0, 0.0, -(far + near) / (far - near), -(2.0 * far * near) / (far - near), - 0.0, 0.0, -1.0, 0.0, - result); + (2.0 * near) / (right - left), + 0.0, + (right + left) / (right - left), + 0.0, + 0.0, + (2.0 * near) / (top - bottom), + (top + bottom) / (top - bottom), + 0.0, + 0.0, + 0.0, + -(far + near) / (far - near), + -(2.0 * far * near) / (far - near), + 0.0, + 0.0, + -1.0, + 0.0, + result, + ); } diff --git a/core/frontend/src/render/webgl/GL.ts b/core/frontend/src/render/webgl/GL.ts index 2b326ed708b9..f26696d0967c 100644 --- a/core/frontend/src/render/webgl/GL.ts +++ b/core/frontend/src/render/webgl/GL.ts @@ -6,7 +6,7 @@ * @module WebGL */ -if (typeof (WebGLRenderingContext) === "undefined") { +if (typeof WebGLRenderingContext === "undefined") { (global as any).WebGLRenderingContext = new Proxy({}, { get: () => 0 }); } diff --git a/core/frontend/src/render/webgl/GLTimer.ts b/core/frontend/src/render/webgl/GLTimer.ts index f9070304d06c..e36902eb2a0f 100644 --- a/core/frontend/src/render/webgl/GLTimer.ts +++ b/core/frontend/src/render/webgl/GLTimer.ts @@ -17,17 +17,27 @@ class DisjointTimerExtension { this._context = system.context; } - public get isSupported(): boolean { return this._e !== undefined; } + public get isSupported(): boolean { + return this._e !== undefined; + } public didDisjointEventHappen(): boolean { return this._context.getParameter(this._e.GPU_DISJOINT_EXT); } - public createQuery(): WebGLQuery { return this._context.createQuery() as WebGLQuery; } - public deleteQuery(q: WebGLQuery) { this._context.deleteQuery(q); } + public createQuery(): WebGLQuery { + return this._context.createQuery() as WebGLQuery; + } + public deleteQuery(q: WebGLQuery) { + this._context.deleteQuery(q); + } - public beginQuery(q: WebGLQuery) { this._context.beginQuery(this._e.TIME_ELAPSED_EXT, q); } - public endQuery() { this._context.endQuery(this._e.TIME_ELAPSED_EXT); } + public beginQuery(q: WebGLQuery) { + this._context.beginQuery(this._e.TIME_ELAPSED_EXT, q); + } + public endQuery() { + this._context.endQuery(this._e.TIME_ELAPSED_EXT); + } public isResultAvailable(q: WebGLQuery): boolean { return this._context.getQueryParameter(q, this._context.QUERY_RESULT_AVAILABLE); @@ -75,7 +85,9 @@ export class GLTimer { return new GLTimer(system); } - public get isSupported(): boolean { return this._extension.isSupported; } + public get isSupported(): boolean { + return this._extension.isSupported; + } public set resultsCallback(callback: GLTimerResultCallback | undefined) { if (this._queryStack.length !== 0) @@ -131,7 +143,7 @@ export class GLTimer { // It takes one or more frames for results to become available. // Only checking time for root since it will always be the last query completed. // If there are any sibling queries then we will just check the last one. - const finalQuery = (undefined === root.siblingQueries ? root.query : root.siblingQueries[root.siblingQueries.length-1]); + const finalQuery = undefined === root.siblingQueries ? root.query : root.siblingQueries[root.siblingQueries.length - 1]; if (!this._extension.isResultAvailable(finalQuery)) { setTimeout(queryCallback, 0); return; diff --git a/core/frontend/src/render/webgl/Graphic.ts b/core/frontend/src/render/webgl/Graphic.ts index 16878c571e48..9a79b09886de 100644 --- a/core/frontend/src/render/webgl/Graphic.ts +++ b/core/frontend/src/render/webgl/Graphic.ts @@ -9,12 +9,15 @@ import { assert, dispose, Id64String } from "@itwin/core-bentley"; import { ElementAlignedBox3d, FeatureAppearanceProvider, RenderFeatureTable, ThematicDisplayMode, ViewFlags } from "@itwin/core-common"; import { Range3d, Transform } from "@itwin/core-geometry"; +import { BatchOptions } from "../../common/render/BatchOptions"; import { IModelConnection } from "../../IModelConnection"; import { FeatureSymbology } from "../FeatureSymbology"; import { GraphicBranch, GraphicBranchFrustum, GraphicBranchOptions } from "../GraphicBranch"; import { GraphicList, RenderGraphic } from "../RenderGraphic"; import { RenderMemory } from "../RenderMemory"; +import { BranchState } from "./BranchState"; import { ClipVolume } from "./ClipVolume"; +import { Contours } from "./Contours"; import { WebGLDisposable } from "./Disposable"; import { EdgeSettings } from "./EdgeSettings"; import { FeatureOverrides } from "./FeatureOverrides"; @@ -25,17 +28,18 @@ import { RenderPass } from "./RenderFlags"; import { Target } from "./Target"; import { TextureDrape } from "./TextureDrape"; import { ThematicSensors } from "./ThematicSensors"; -import { BranchState } from "./BranchState"; -import { BatchOptions } from "../../common/render/BatchOptions"; -import { Contours } from "./Contours"; /** @internal */ export abstract class Graphic extends RenderGraphic implements WebGLDisposable { public abstract addCommands(_commands: RenderCommands): void; public abstract get isDisposed(): boolean; public abstract get isPickable(): boolean; - public addHiliteCommands(_commands: RenderCommands, _pass: RenderPass): void { assert(false); } - public toPrimitive(): Primitive | undefined { return undefined; } + public addHiliteCommands(_commands: RenderCommands, _pass: RenderPass): void { + assert(false); + } + public toPrimitive(): Primitive | undefined { + return undefined; + } } export class GraphicOwner extends Graphic { @@ -46,11 +50,17 @@ export class GraphicOwner extends Graphic { this._graphic = graphic; } - public get graphic(): RenderGraphic { return this._graphic; } + public get graphic(): RenderGraphic { + return this._graphic; + } private _isDisposed = false; - public get isDisposed(): boolean { return this._isDisposed; } - public dispose(): void { this._isDisposed = true; } + public get isDisposed(): boolean { + return this._isDisposed; + } + public dispose(): void { + this._isDisposed = true; + } public disposeGraphic(): void { this.graphic.dispose(); } @@ -155,7 +165,9 @@ export class PerTargetBatchData { } /** Exposed strictly for tests. */ - public get featureOverrides() { return this._featureOverrides; } + public get featureOverrides() { + return this._featureOverrides; + } private onSourceDisposed(source: FeatureSymbology.Source): void { const ovrs = this._featureOverrides.get(source); @@ -189,7 +201,9 @@ export class PerTargetData { } /** Exposed strictly for tests. */ - public get data(): PerTargetBatchData[] { return this._data; } + public get data(): PerTargetBatchData[] { + return this._data; + } public onTargetDisposed(target: Target): void { const index = this._data.findIndex((x) => x.target === target); @@ -249,10 +263,18 @@ export class Batch extends Graphic { } /** The following are valid only during a draw and reset afterward. */ - public get batchId() { return this._context.batchId; } - public get batchIModel() { return this._context.iModel; } - public get transformFromBatchIModel() { return this._context.transformFromIModel; } - public get viewAttachmentId() { return this._context.viewAttachmentId; } + public get batchId() { + return this._context.batchId; + } + public get batchIModel() { + return this._context.iModel; + } + public get transformFromBatchIModel() { + return this._context.transformFromIModel; + } + public get viewAttachmentId() { + return this._context.viewAttachmentId; + } public setContext(batchId: number, branch: BranchState) { this._context.batchId = batchId; @@ -492,9 +514,13 @@ export class WorldDecorations extends Branch { /** @internal */ export class GraphicsArray extends Graphic { // Note: We assume the graphics array we get contains undisposed graphics to start - constructor(public graphics: RenderGraphic[]) { super(); } + constructor(public graphics: RenderGraphic[]) { + super(); + } - public get isDisposed(): boolean { return 0 === this.graphics.length; } + public get isDisposed(): boolean { + return 0 === this.graphics.length; + } public override get isPickable(): boolean { return this.graphics.some((x) => (x as Graphic).isPickable); diff --git a/core/frontend/src/render/webgl/HiliteUniforms.ts b/core/frontend/src/render/webgl/HiliteUniforms.ts index ad67f63708df..58261778a4b6 100644 --- a/core/frontend/src/render/webgl/HiliteUniforms.ts +++ b/core/frontend/src/render/webgl/HiliteUniforms.ts @@ -8,9 +8,9 @@ import { Hilite } from "@itwin/core-common"; import { FloatRgb } from "./FloatRGBA"; -import { UniformHandle } from "./UniformHandle"; import { Matrix3 } from "./Matrix"; import { desync, sync } from "./Sync"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state for uniforms related to hilite and emphasis. * @internal @@ -26,9 +26,15 @@ export class HiliteUniforms { public syncKey = 0; - public get hiliteSettings() { return this._hiliteSettings; } - public get emphasisSettings() { return this._emphasisSettings; } - public get hiliteColor() { return this._hiliteRgb; } + public get hiliteSettings() { + return this._hiliteSettings; + } + public get emphasisSettings() { + return this._emphasisSettings; + } + public get hiliteColor() { + return this._hiliteRgb; + } public update(hilite: Hilite.Settings, emphasis: Hilite.Settings): void { if (Hilite.equalSettings(hilite, this._hiliteSettings) && Hilite.equalSettings(emphasis, this._emphasisSettings)) diff --git a/core/frontend/src/render/webgl/IndexedEdgeGeometry.ts b/core/frontend/src/render/webgl/IndexedEdgeGeometry.ts index deaeb2dd6687..e7f708211bce 100644 --- a/core/frontend/src/render/webgl/IndexedEdgeGeometry.ts +++ b/core/frontend/src/render/webgl/IndexedEdgeGeometry.ts @@ -8,20 +8,20 @@ import { assert, dispose } from "@itwin/core-bentley"; import { RenderMode } from "@itwin/core-common"; +import { EdgeTable, IndexedEdgeParams } from "../../common/internal/render/EdgeParams"; import { RenderMemory } from "../RenderMemory"; -import { TextureHandle } from "./Texture"; import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; +import { AttributeMap } from "./AttributeMap"; import { WebGLDisposable } from "./Disposable"; +import { ShaderProgramParams } from "./DrawCommand"; +import { GL } from "./GL"; import { MeshData } from "./MeshData"; import { MeshGeometry } from "./MeshGeometry"; -import { AttributeMap } from "./AttributeMap"; -import { TechniqueId } from "./TechniqueId"; -import { GL } from "./GL"; +import { RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; -import { ShaderProgramParams } from "./DrawCommand"; -import { RenderOrder } from "./RenderFlags"; -import { EdgeTable, IndexedEdgeParams } from "../../common/internal/render/EdgeParams"; +import { TechniqueId } from "./TechniqueId"; +import { TextureHandle } from "./Texture"; /** @see [[EdgeTable]] * @internal @@ -63,8 +63,12 @@ export class IndexedEdgeGeometry extends MeshGeometry { private readonly _indices: BufferHandle; public readonly edgeLut: EdgeLUT; - public get lutBuffers() { return this._buffers; } - public override get asIndexedEdge() { return this; } + public get lutBuffers() { + return this._buffers; + } + public override get asIndexedEdge() { + return this; + } private constructor(mesh: MeshData, indices: BufferHandle, numIndices: number, lut: EdgeLUT) { super(mesh, numIndices); @@ -104,12 +108,26 @@ export class IndexedEdgeGeometry extends MeshGeometry { bufs.unbind(); } - protected _wantWoWReversal(): boolean { return true; } - protected override _getLineCode(params: ShaderProgramParams): number { return this.computeEdgeLineCode(params); } + protected _wantWoWReversal(): boolean { + return true; + } + protected override _getLineCode(params: ShaderProgramParams): number { + return this.computeEdgeLineCode(params); + } - public get techniqueId() { return TechniqueId.IndexedEdge; } - public override getPass(target: Target) { return this.computeEdgePass(target); } - public get renderOrder() { return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; } - public override getColor(target: Target) { return this.computeEdgeColor(target); } - public override wantMonochrome(target: Target) { return target.currentViewFlags.renderMode === RenderMode.Wireframe; } + public get techniqueId() { + return TechniqueId.IndexedEdge; + } + public override getPass(target: Target) { + return this.computeEdgePass(target); + } + public get renderOrder() { + return this.isPlanar ? RenderOrder.PlanarEdge : RenderOrder.Edge; + } + public override getColor(target: Target) { + return this.computeEdgeColor(target); + } + public override wantMonochrome(target: Target) { + return target.currentViewFlags.renderMode === RenderMode.Wireframe; + } } diff --git a/core/frontend/src/render/webgl/InstancedGeometry.ts b/core/frontend/src/render/webgl/InstancedGeometry.ts index 8c8b8b54f690..0df8e87e85e8 100644 --- a/core/frontend/src/render/webgl/InstancedGeometry.ts +++ b/core/frontend/src/render/webgl/InstancedGeometry.ts @@ -7,25 +7,26 @@ */ import { assert, dispose } from "@itwin/core-bentley"; +import { BatchType, PackedFeatureTable } from "@itwin/core-common"; import { Point3d, Range3d, Transform, XYAndZ } from "@itwin/core-geometry"; +import { _featureTable, _implementationProhibited, _renderSystem, _transformCenter, _transforms } from "../../common/internal/Symbols"; import { InstancedGraphicParams, InstancedGraphicProps, PatternGraphicParams } from "../../common/render/InstancedGraphicParams"; +import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; import { RenderMemory } from "../RenderMemory"; +import { RenderInstances } from "../RenderSystem"; +import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { CachedGeometry, LUTGeometry } from "./CachedGeometry"; import { ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; +import { Matrix4 } from "./Matrix"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { Matrix4 } from "./Matrix"; -import { RenderInstances } from "../RenderSystem"; -import { _featureTable, _implementationProhibited, _renderSystem, _transformCenter, _transforms } from "../../common/internal/Symbols"; -import { BatchType, PackedFeatureTable } from "@itwin/core-common"; -import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; /** @internal */ export function isInstancedGraphicParams(params: any): params is InstancedGraphicParams { - return typeof params === "object" && typeof params.count === "number" && params.transforms instanceof Float32Array && params.transformCenter instanceof Point3d; + return typeof params === "object" && typeof params.count === "number" && params.transforms instanceof Float32Array && + params.transformCenter instanceof Point3d; } class InstanceData { @@ -77,7 +78,14 @@ export class InstanceBuffersData extends InstanceData { public readonly symbology?: BufferHandle; private _noDispose = false; - private constructor(count: number, transforms: BufferHandle, rtcCenter: Point3d, symbology?: BufferHandle, featureIds?: BufferHandle, disableDisposal = false) { + private constructor( + count: number, + transforms: BufferHandle, + rtcCenter: Point3d, + symbology?: BufferHandle, + featureIds?: BufferHandle, + disableDisposal = false, + ) { super(count, rtcCenter); this.transforms = transforms; this.featureIds = featureIds; @@ -161,15 +169,31 @@ export class InstanceBuffers { public readonly viewIndependentOrigin = undefined; public readonly range: Range3d; - public get numInstances() { return this._data.numInstances; } - public get transforms() { return this._data.transforms; } - public get featureIds() { return this._data.featureIds; } - public get symbology() { return this._data.symbology; } - public get hasFeatures() { return undefined !== this.featureIds; } - public get patternFeatureId() { return this._data.patternFeatureId; } + public get numInstances() { + return this._data.numInstances; + } + public get transforms() { + return this._data.transforms; + } + public get featureIds() { + return this._data.featureIds; + } + public get symbology() { + return this._data.symbology; + } + public get hasFeatures() { + return undefined !== this.featureIds; + } + public get patternFeatureId() { + return this._data.patternFeatureId; + } - public getRtcModelTransform(modelMatrix: Transform) { return this._data.getRtcModelTransform(modelMatrix); } - public getRtcOnlyTransform() { return this._data.getRtcOnlyTransform(); } + public getRtcModelTransform(modelMatrix: Transform) { + return this._data.getRtcModelTransform(modelMatrix); + } + public getRtcOnlyTransform() { + return this._data.getRtcOnlyTransform(); + } private constructor(data: InstanceBuffersData, range: Range3d) { this._data = data; @@ -237,9 +261,11 @@ export class InstanceBuffers { } private static extendTransformedRange(tfs: Float32Array, i: number, range: Range3d, x: number, y: number, z: number) { - range.extendXYZ(tfs[i + 3] + tfs[i + 0] * x + tfs[i + 1] * y + tfs[i + 2] * z, + range.extendXYZ( + tfs[i + 3] + tfs[i + 0] * x + tfs[i + 1] * y + tfs[i + 2] * z, tfs[i + 7] + tfs[i + 4] * x + tfs[i + 5] * y + tfs[i + 6] * z, - tfs[i + 11] + tfs[i + 8] * x + tfs[i + 9] * y + tfs[i + 10] * z); + tfs[i + 11] + tfs[i + 8] * x + tfs[i + 9] * y + tfs[i + 10] * z, + ); } public static computeRange(reprRange: Range3d, tfs: Float32Array, rtcCenter: XYAndZ, out?: Range3d): Range3d { @@ -348,39 +374,97 @@ export class InstancedGeometry extends CachedGeometry { private readonly _repr: LUTGeometry; private readonly _ownsBuffers: boolean; - public getRtcModelTransform(modelMatrix: Transform) { return this._buffers.getRtcModelTransform(modelMatrix); } - public getRtcOnlyTransform() { return this._buffers.getRtcOnlyTransform(); } - - public override get viewIndependentOrigin(): Point3d | undefined { return this._buffers.viewIndependentOrigin; } - - public override get asInstanced() { return this; } - public override get asLUT() { return this._repr.asLUT; } - public override get asMesh() { return this._repr.asMesh; } - public override get asSurface() { return this._repr.asSurface; } - public override get asEdge() { return this._repr.asEdge; } - public override get asSilhouette() { return this._repr.asSilhouette; } - public override get asIndexedEdge() { return this._repr.asIndexedEdge; } - - public get renderOrder() { return this._repr.renderOrder; } - public override get isLitSurface() { return this._repr.isLitSurface; } - public override get hasBakedLighting() { return this._repr.hasBakedLighting; } - public override get hasAnimation() { return this._repr.hasAnimation; } - public override get usesQuantizedPositions() { return this._repr.usesQuantizedPositions; } - public get qOrigin() { return this._repr.qOrigin; } - public get qScale() { return this._repr.qScale; } - public override get materialInfo() { return this._repr.materialInfo; } - public override get polylineBuffers() { return this._repr.polylineBuffers; } - public override get isEdge() { return this._repr.isEdge; } - public override get hasFeatures() { return this._buffers.hasFeatures; } - public get techniqueId(): TechniqueId { return this._repr.techniqueId; } - public override get supportsThematicDisplay() { return this._repr.supportsThematicDisplay; } - - public override getPass(target: Target) { return this._repr.getPass(target); } - public override wantWoWReversal(params: ShaderProgramParams) { return this._repr.wantWoWReversal(params); } - public override getLineCode(params: ShaderProgramParams) { return this._repr.getLineCode(params); } - public override getLineWeight(params: ShaderProgramParams) { return this._repr.getLineWeight(params); } - public override wantMonochrome(target: Target) { return this._repr.wantMonochrome(target); } - public override wantMixMonochromeColor(target: Target): boolean { return this._repr.wantMixMonochromeColor(target); } + public getRtcModelTransform(modelMatrix: Transform) { + return this._buffers.getRtcModelTransform(modelMatrix); + } + public getRtcOnlyTransform() { + return this._buffers.getRtcOnlyTransform(); + } + + public override get viewIndependentOrigin(): Point3d | undefined { + return this._buffers.viewIndependentOrigin; + } + + public override get asInstanced() { + return this; + } + public override get asLUT() { + return this._repr.asLUT; + } + public override get asMesh() { + return this._repr.asMesh; + } + public override get asSurface() { + return this._repr.asSurface; + } + public override get asEdge() { + return this._repr.asEdge; + } + public override get asSilhouette() { + return this._repr.asSilhouette; + } + public override get asIndexedEdge() { + return this._repr.asIndexedEdge; + } + + public get renderOrder() { + return this._repr.renderOrder; + } + public override get isLitSurface() { + return this._repr.isLitSurface; + } + public override get hasBakedLighting() { + return this._repr.hasBakedLighting; + } + public override get hasAnimation() { + return this._repr.hasAnimation; + } + public override get usesQuantizedPositions() { + return this._repr.usesQuantizedPositions; + } + public get qOrigin() { + return this._repr.qOrigin; + } + public get qScale() { + return this._repr.qScale; + } + public override get materialInfo() { + return this._repr.materialInfo; + } + public override get polylineBuffers() { + return this._repr.polylineBuffers; + } + public override get isEdge() { + return this._repr.isEdge; + } + public override get hasFeatures() { + return this._buffers.hasFeatures; + } + public get techniqueId(): TechniqueId { + return this._repr.techniqueId; + } + public override get supportsThematicDisplay() { + return this._repr.supportsThematicDisplay; + } + + public override getPass(target: Target) { + return this._repr.getPass(target); + } + public override wantWoWReversal(params: ShaderProgramParams) { + return this._repr.wantWoWReversal(params); + } + public override getLineCode(params: ShaderProgramParams) { + return this._repr.getLineCode(params); + } + public override getLineWeight(params: ShaderProgramParams) { + return this._repr.getLineWeight(params); + } + public override wantMonochrome(target: Target) { + return this._repr.wantMonochrome(target); + } + public override wantMixMonochromeColor(target: Target): boolean { + return this._repr.wantMixMonochromeColor(target); + } public static create(repr: LUTGeometry, ownsBuffers: boolean, buffers: InstanceBuffers): InstancedGeometry { const techId = repr.techniqueId; @@ -464,7 +548,13 @@ export class InstancedGeometry extends CachedGeometry { this._buffers.collectStatistics(stats); } - public get patternParams(): Float32Array { return this._buffers.patternParams; } - public get patternTransforms(): PatternTransforms | undefined { return this._buffers.patternTransforms; } - public get patternFeatureId(): Float32Array { return this._buffers.patternFeatureId; } + public get patternParams(): Float32Array { + return this._buffers.patternParams; + } + public get patternTransforms(): PatternTransforms | undefined { + return this._buffers.patternTransforms; + } + public get patternFeatureId(): Float32Array { + return this._buffers.patternFeatureId; + } } diff --git a/core/frontend/src/render/webgl/Layer.ts b/core/frontend/src/render/webgl/Layer.ts index 11151ae5d581..c5b576e670a5 100644 --- a/core/frontend/src/render/webgl/Layer.ts +++ b/core/frontend/src/render/webgl/Layer.ts @@ -7,12 +7,12 @@ */ import { Id64 } from "@itwin/core-bentley"; +import { Range3d } from "@itwin/core-geometry"; import { RenderMemory } from "../RenderMemory"; import { Graphic } from "./Graphic"; import { RenderCommands } from "./RenderCommands"; import { RenderPass } from "./RenderFlags"; import { Target } from "./Target"; -import { Range3d } from "@itwin/core-geometry"; abstract class GraphicWrapper extends Graphic { public readonly graphic: Graphic; diff --git a/core/frontend/src/render/webgl/LayerCommands.ts b/core/frontend/src/render/webgl/LayerCommands.ts index 7de4286125d0..1c085d140844 100644 --- a/core/frontend/src/render/webgl/LayerCommands.ts +++ b/core/frontend/src/render/webgl/LayerCommands.ts @@ -8,7 +8,14 @@ import { assert, compareNumbers, compareStrings, SortedArray } from "@itwin/core-bentley"; import { - DrawCommand, DrawCommands, PopBatchCommand, PopBranchCommand, PopCommand, PushBatchCommand, PushBranchCommand, PushCommand, + DrawCommand, + DrawCommands, + PopBatchCommand, + PopBranchCommand, + PopCommand, + PushBatchCommand, + PushBranchCommand, + PushCommand, } from "./DrawCommand"; import { Layer, LayerContainer } from "./Layer"; import { RenderCommands } from "./RenderCommands"; @@ -32,7 +39,7 @@ abstract class State { this.map.state = this; } - protected exit(): void { } + protected exit(): void {} protected throwStateError(operation: string): void { // Using assert because these are intended for developers. @@ -70,7 +77,9 @@ abstract class State { } class IdleState extends State { - protected get opcode(): OpCode { return "Idle"; } + protected get opcode(): OpCode { + return "Idle"; + } public constructor(map: LayerCommandMap) { super(map); @@ -83,7 +92,9 @@ class IdleState extends State { class ContainerState extends State { public readonly elevation: number; - protected get opcode(): OpCode { return "Container"; } + protected get opcode(): OpCode { + return "Container"; + } public constructor(idle: IdleState, container: LayerContainer) { super(idle.map); @@ -100,7 +111,9 @@ class BranchState extends State { public readonly containerState: ContainerState; private readonly _layerCommands = new Set(); - protected get opcode(): OpCode { return "Branch"; } + protected get opcode(): OpCode { + return "Branch"; + } public constructor(containerState: ContainerState, pushCommand: PushBranchCommand) { super(containerState.map); @@ -129,7 +142,9 @@ class BatchState extends State { public readonly branchState: BranchState; public readonly pushCommand: PushBatchCommand; - protected get opcode(): OpCode { return "Batch"; } + protected get opcode(): OpCode { + return "Batch"; + } public constructor(branchState: BranchState, pushCommand: PushBatchCommand) { super(branchState.map); @@ -149,7 +164,9 @@ class LayerState extends State { private readonly _batchState: BatchState; public readonly commands: LayerCommands; - protected get opcode(): OpCode { return "Layer"; } + protected get opcode(): OpCode { + return "Layer"; + } public constructor(batchState: BatchState, layer: Layer) { super(batchState.map); diff --git a/core/frontend/src/render/webgl/LightingUniforms.ts b/core/frontend/src/render/webgl/LightingUniforms.ts index 781a1571078c..f37e7ccc2b54 100644 --- a/core/frontend/src/render/webgl/LightingUniforms.ts +++ b/core/frontend/src/render/webgl/LightingUniforms.ts @@ -8,8 +8,8 @@ import { ColorDef, LightSettings, RgbColor } from "@itwin/core-common"; import { FloatRgb } from "./FloatRGBA"; -import { UniformHandle } from "./UniformHandle"; import { desync, sync } from "./Sync"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state of uniforms associated with a DisplayStyle3dState's LightSettings. * A single float array stored as: diff --git a/core/frontend/src/render/webgl/LineCode.ts b/core/frontend/src/render/webgl/LineCode.ts index 526ebb83ccb6..717ec5f939f3 100644 --- a/core/frontend/src/render/webgl/LineCode.ts +++ b/core/frontend/src/render/webgl/LineCode.ts @@ -24,20 +24,517 @@ export namespace LineCode { // NB: Non-power-of-two textures in WebGL only support clamp-to-edge. // Make this a power of two so we can use repeat. export const lineCodeData: number[] = [ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ]; } diff --git a/core/frontend/src/render/webgl/Material.ts b/core/frontend/src/render/webgl/Material.ts index a29f7a2c1ebf..db26aa725ac1 100644 --- a/core/frontend/src/render/webgl/Material.ts +++ b/core/frontend/src/render/webgl/Material.ts @@ -7,8 +7,8 @@ */ import { ColorDef, RenderMaterial } from "@itwin/core-common"; -import { FloatRgb } from "./FloatRGBA"; import { SurfaceMaterial, SurfaceMaterialAtlas } from "../../common/internal/render/SurfaceParams"; +import { FloatRgb } from "./FloatRGBA"; /** Parameters describing a single material. The parameters used are: * - diffuse color rgb (vec3). @@ -47,9 +47,15 @@ export class Material extends RenderMaterial { public readonly fragUniforms = new Float32Array(4); public readonly rgba = new Float32Array(4); - public get overridesRgb() { return this.rgba[0] >= 0; } - public get overridesAlpha() { return this.rgba[3] >= 0; } - public get hasTranslucency() { return this.overridesAlpha && this.rgba[3] < 1; } + public get overridesRgb() { + return this.rgba[0] >= 0; + } + public get overridesAlpha() { + return this.rgba[3] >= 0; + } + public get hasTranslucency() { + return this.overridesAlpha && this.rgba[3] < 1; + } /** Strictly for testing. */ public static preserveParams = false; @@ -90,7 +96,7 @@ export class Material extends RenderMaterial { } private setInteger(loByte: number, hiByte: number, index: number): void { - const clamp = (x: number) => Math.floor(Math.min(255, (Math.max(x, 0)))); + const clamp = (x: number) => Math.floor(Math.min(255, Math.max(x, 0))); loByte = clamp(loByte); hiByte = clamp(hiByte); diff --git a/core/frontend/src/render/webgl/Matrix.ts b/core/frontend/src/render/webgl/Matrix.ts index 818d6f2b552b..af460cfb4b50 100644 --- a/core/frontend/src/render/webgl/Matrix.ts +++ b/core/frontend/src/render/webgl/Matrix.ts @@ -13,7 +13,7 @@ import { Matrix3d, Matrix4d, Point3d, Transform, Vector3d } from "@itwin/core-ge export class Matrix3 { public readonly data: Float32Array = new Float32Array(3 * 3); - public constructor() { } + public constructor() {} public initIdentity(): void { this.setValues(1, 0, 0, 0, 1, 0, 0, 0, 1); @@ -46,7 +46,18 @@ export class Matrix3 { this.m21 = m21; this.m22 = m22; } - public static fromValues(m00: number, m01: number, m02: number, m10: number, m11: number, m12: number, m20: number, m21: number, m22: number, out?: Matrix3) { + public static fromValues( + m00: number, + m01: number, + m02: number, + m10: number, + m11: number, + m12: number, + m20: number, + m21: number, + m22: number, + out?: Matrix3, + ) { const mat = undefined !== out ? out : new Matrix3(); mat.setValues(m00, m01, m02, m10, m11, m12, m20, m21, m22); return mat; @@ -54,9 +65,16 @@ export class Matrix3 { public initFromMatrix3d(rot: Matrix3d): void { this.setValues( - rot.at(0, 0), rot.at(0, 1), rot.at(0, 2), - rot.at(1, 0), rot.at(1, 1), rot.at(1, 2), - rot.at(2, 0), rot.at(2, 1), rot.at(2, 2)); + rot.at(0, 0), + rot.at(0, 1), + rot.at(0, 2), + rot.at(1, 0), + rot.at(1, 1), + rot.at(1, 2), + rot.at(2, 0), + rot.at(2, 1), + rot.at(2, 2), + ); } public static fromMatrix3d(rot: Matrix3d, out?: Matrix3): Matrix3 { const mat = undefined !== out ? out : new Matrix3(); @@ -98,34 +116,74 @@ export class Matrix3 { this.data[index] = value; } - public at(row: number, col: number) { return this.get(col * 3 + row); } - public setAt(row: number, col: number, value: number) { this.set(col * 3 + row, value); } - - public get m00() { return this.at(0, 0); } - public set m00(value: number) { this.setAt(0, 0, value); } - public get m01() { return this.at(0, 1); } - public set m01(value: number) { this.setAt(0, 1, value); } - public get m02() { return this.at(0, 2); } - public set m02(value: number) { this.setAt(0, 2, value); } - public get m10() { return this.at(1, 0); } - public set m10(value: number) { this.setAt(1, 0, value); } - public get m11() { return this.at(1, 1); } - public set m11(value: number) { this.setAt(1, 1, value); } - public get m12() { return this.at(1, 2); } - public set m12(value: number) { this.setAt(1, 2, value); } - public get m20() { return this.at(2, 0); } - public set m20(value: number) { this.setAt(2, 0, value); } - public get m21() { return this.at(2, 1); } - public set m21(value: number) { this.setAt(2, 1, value); } - public get m22() { return this.at(2, 2); } - public set m22(value: number) { this.setAt(2, 2, value); } + public at(row: number, col: number) { + return this.get(col * 3 + row); + } + public setAt(row: number, col: number, value: number) { + this.set(col * 3 + row, value); + } + + public get m00() { + return this.at(0, 0); + } + public set m00(value: number) { + this.setAt(0, 0, value); + } + public get m01() { + return this.at(0, 1); + } + public set m01(value: number) { + this.setAt(0, 1, value); + } + public get m02() { + return this.at(0, 2); + } + public set m02(value: number) { + this.setAt(0, 2, value); + } + public get m10() { + return this.at(1, 0); + } + public set m10(value: number) { + this.setAt(1, 0, value); + } + public get m11() { + return this.at(1, 1); + } + public set m11(value: number) { + this.setAt(1, 1, value); + } + public get m12() { + return this.at(1, 2); + } + public set m12(value: number) { + this.setAt(1, 2, value); + } + public get m20() { + return this.at(2, 0); + } + public set m20(value: number) { + this.setAt(2, 0, value); + } + public get m21() { + return this.at(2, 1); + } + public set m21(value: number) { + this.setAt(2, 1, value); + } + public get m22() { + return this.at(2, 2); + } + public set m22(value: number) { + this.setAt(2, 2, value); + } } /** @internal */ export class Matrix4 { public readonly data: Float32Array = new Float32Array(4 * 4); - public constructor() { } + public constructor() {} public copyFrom(src: Matrix4): void { for (let i = 0; i < this.data.length; i++) { @@ -140,10 +198,23 @@ export class Matrix4 { public initIdentity(): void { this.setValues( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + ); } public static fromIdentity(out?: Matrix4): Matrix4 { const mat = undefined !== out ? out : new Matrix4(); @@ -151,7 +222,24 @@ export class Matrix4 { return mat; } - public setValues(m00: number, m01: number, m02: number, m03: number, m10: number, m11: number, m12: number, m13: number, m20: number, m21: number, m22: number, m23: number, m30: number, m31: number, m32: number, m33: number) { + public setValues( + m00: number, + m01: number, + m02: number, + m03: number, + m10: number, + m11: number, + m12: number, + m13: number, + m20: number, + m21: number, + m22: number, + m23: number, + m30: number, + m31: number, + m32: number, + m33: number, + ) { this.m00 = m00; this.m01 = m01; this.m02 = m02; @@ -170,7 +258,25 @@ export class Matrix4 { this.m33 = m33; } - public static fromValues(m00: number, m01: number, m02: number, m03: number, m10: number, m11: number, m12: number, m13: number, m20: number, m21: number, m22: number, m23: number, m30: number, m31: number, m32: number, m33: number, out?: Matrix4): Matrix4 { + public static fromValues( + m00: number, + m01: number, + m02: number, + m03: number, + m10: number, + m11: number, + m12: number, + m13: number, + m20: number, + m21: number, + m22: number, + m23: number, + m30: number, + m31: number, + m32: number, + m33: number, + out?: Matrix4, + ): Matrix4 { const mat = undefined !== out ? out : new Matrix4(); mat.setValues(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33); return mat; @@ -186,10 +292,23 @@ export class Matrix4 { const mat = transform.matrix; const org = transform.origin; this.setValues( - mat.at(0, 0), mat.at(0, 1), mat.at(0, 2), org.x, - mat.at(1, 0), mat.at(1, 1), mat.at(1, 2), org.y, - mat.at(2, 0), mat.at(2, 1), mat.at(2, 2), org.z, - 0, 0, 0, 1); + mat.at(0, 0), + mat.at(0, 1), + mat.at(0, 2), + org.x, + mat.at(1, 0), + mat.at(1, 1), + mat.at(1, 2), + org.y, + mat.at(2, 0), + mat.at(2, 1), + mat.at(2, 2), + org.z, + 0, + 0, + 0, + 1, + ); } public static fromTransform(transform: Transform, out?: Matrix4): Matrix4 { const mat = undefined !== out ? out : new Matrix4(); @@ -210,10 +329,23 @@ export class Matrix4 { public initFromMatrix4d(mat: Matrix4d): void { this.setValues( - mat.atIJ(0, 0), mat.atIJ(0, 1), mat.atIJ(0, 2), mat.atIJ(0, 3), - mat.atIJ(1, 0), mat.atIJ(1, 1), mat.atIJ(1, 2), mat.atIJ(1, 3), - mat.atIJ(2, 0), mat.atIJ(2, 1), mat.atIJ(2, 2), mat.atIJ(2, 3), - mat.atIJ(3, 0), mat.atIJ(3, 1), mat.atIJ(3, 2), mat.atIJ(3, 3)); + mat.atIJ(0, 0), + mat.atIJ(0, 1), + mat.atIJ(0, 2), + mat.atIJ(0, 3), + mat.atIJ(1, 0), + mat.atIJ(1, 1), + mat.atIJ(1, 2), + mat.atIJ(1, 3), + mat.atIJ(2, 0), + mat.atIJ(2, 1), + mat.atIJ(2, 2), + mat.atIJ(2, 3), + mat.atIJ(3, 0), + mat.atIJ(3, 1), + mat.atIJ(3, 2), + mat.atIJ(3, 3), + ); } public static fromMatrix4d(mat: Matrix4d, out?: Matrix4): Matrix4 { const result = undefined !== out ? out : new Matrix4(); @@ -222,11 +354,25 @@ export class Matrix4 { } public toMatrix4d(result?: Matrix4d): Matrix4d { const data = this.data; - return Matrix4d.createRowValues(data[0], data[4], data[8], data[12], - data[1], data[5], data[9], data[13], - data[2], data[6], data[10], data[14], - data[3], data[7], data[11], data[15], - result); + return Matrix4d.createRowValues( + data[0], + data[4], + data[8], + data[12], + data[1], + data[5], + data[9], + data[13], + data[2], + data[6], + data[10], + data[14], + data[3], + data[7], + data[11], + data[15], + result, + ); } public lookAt(eye: Point3d, center: Point3d, up: Vector3d): boolean { @@ -242,10 +388,23 @@ export class Matrix4 { const u = Vector3d.createCrossProduct(s.x, s.y, s.z, f.x, f.y, f.z); this.setValues( - s.x, s.y, s.z, -s.dotProduct(eye), - u.x, u.y, u.z, -u.dotProduct(eye), - -f.x, -f.y, -f.z, f.dotProduct(eye), - 0, 0, 0, 1); + s.x, + s.y, + s.z, + -s.dotProduct(eye), + u.x, + u.y, + u.z, + -u.dotProduct(eye), + -f.x, + -f.y, + -f.z, + f.dotProduct(eye), + 0, + 0, + 0, + 1, + ); return true; } public static fromLookAt(eye: Point3d, center: Point3d, up: Vector3d, out?: Matrix4): Matrix4 | undefined { @@ -255,9 +414,24 @@ export class Matrix4 { // left, right, bottom, top, near, far public frustum(l: number, r: number, b: number, t: number, n: number, f: number): void { - this.setValues((2 * n) / (r - l), 0, (r + l) / (r - l), 0, 0, (2 * n) / (t - b), - (t + b) / (t - b), 0, 0, 0, -(f + n) / (f - n), - -(2 * f * n) / (f - n), 0, 0, -1, 0); + this.setValues( + (2 * n) / (r - l), + 0, + (r + l) / (r - l), + 0, + 0, + (2 * n) / (t - b), + (t + b) / (t - b), + 0, + 0, + 0, + -(f + n) / (f - n), + -(2 * f * n) / (f - n), + 0, + 0, + -1, + 0, + ); } public static fromFrustum(l: number, r: number, b: number, t: number, n: number, f: number, out?: Matrix4): Matrix4 { const mat = undefined !== out ? out : new Matrix4(); @@ -278,10 +452,23 @@ export class Matrix4 { public ortho(l: number, r: number, b: number, t: number, n: number, f: number): void { this.setValues( - 2 / (r - l), 0, 0, -(r + l) / (r - l), - 0, 2 / (t - b), 0, -(t + b) / (t - b), - 0, 0, -2 / (f - n), -(f + n) / (f - n), - 0, 0, 0, 1); + 2 / (r - l), + 0, + 0, + -(r + l) / (r - l), + 0, + 2 / (t - b), + 0, + -(t + b) / (t - b), + 0, + 0, + -2 / (f - n), + -(f + n) / (f - n), + 0, + 0, + 0, + 1, + ); } public static fromOrtho(l: number, r: number, b: number, t: number, n: number, f: number, out?: Matrix4): Matrix4 { const mat = undefined !== out ? out : new Matrix4(); @@ -312,7 +499,8 @@ export class Matrix4 { -d[1] * d[6] * d[11] + d[1] * d[7] * d[10] + d[5] * d[2] * d[11] - d[5] * d[3] * d[10] - d[9] * d[2] * d[7] + d[9] * d[3] * d[6], d[0] * d[6] * d[11] - d[0] * d[7] * d[10] - d[4] * d[2] * d[11] + d[4] * d[3] * d[10] + d[8] * d[2] * d[7] - d[8] * d[3] * d[6], -d[0] * d[5] * d[11] + d[0] * d[7] * d[9] + d[4] * d[1] * d[11] - d[4] * d[3] * d[9] - d[8] * d[1] * d[7] + d[8] * d[3] * d[5], - d[0] * d[5] * d[10] - d[0] * d[6] * d[9] - d[4] * d[1] * d[10] + d[4] * d[2] * d[9] + d[8] * d[1] * d[6] - d[8] * d[2] * d[5]); + d[0] * d[5] * d[10] - d[0] * d[6] * d[9] - d[4] * d[1] * d[10] + d[4] * d[2] * d[9] + d[8] * d[1] * d[6] - d[8] * d[2] * d[5], + ); const determinant = d0 * d[0] + d1 * d[4] + d2 * d[8] + d3 * d[12]; if (0 === determinant) { @@ -370,7 +558,8 @@ export class Matrix4 { a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + a[15] * b[3], a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + a[15] * b[7], a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + a[15] * b[11], - a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15]); + a[3] * b[12] + a[7] * b[13] + a[11] * b[14] + a[15] * b[15], + ); } public static fromProduct(a: Matrix4, b: Matrix4, out?: Matrix4): Matrix4 { const mat = a.clone(out); @@ -394,42 +583,110 @@ export class Matrix4 { this.data[index] = value; } - public at(row: number, col: number) { return this.get(col * 4 + row); } - public setAt(row: number, col: number, value: number) { this.set(col * 4 + row, value); } - - public get m00() { return this.at(0, 0); } - public set m00(value: number) { this.setAt(0, 0, value); } - public get m01() { return this.at(0, 1); } - public set m01(value: number) { this.setAt(0, 1, value); } - public get m02() { return this.at(0, 2); } - public set m02(value: number) { this.setAt(0, 2, value); } - public get m03() { return this.at(0, 3); } - public set m03(value: number) { this.setAt(0, 3, value); } - public get m10() { return this.at(1, 0); } - public set m10(value: number) { this.setAt(1, 0, value); } - public get m11() { return this.at(1, 1); } - public set m11(value: number) { this.setAt(1, 1, value); } - public get m12() { return this.at(1, 2); } - public set m12(value: number) { this.setAt(1, 2, value); } - public get m13() { return this.at(1, 3); } - public set m13(value: number) { this.setAt(1, 3, value); } - public get m20() { return this.at(2, 0); } - public set m20(value: number) { this.setAt(2, 0, value); } - public get m21() { return this.at(2, 1); } - public set m21(value: number) { this.setAt(2, 1, value); } - public get m22() { return this.at(2, 2); } - public set m22(value: number) { this.setAt(2, 2, value); } - public get m23() { return this.at(2, 3); } - public set m23(value: number) { this.setAt(2, 3, value); } - - public get m30() { return this.at(3, 0); } - public set m30(value: number) { this.setAt(3, 0, value); } - public get m31() { return this.at(3, 1); } - public set m31(value: number) { this.setAt(3, 1, value); } - public get m32() { return this.at(3, 2); } - public set m32(value: number) { this.setAt(3, 2, value); } - public get m33() { return this.at(3, 3); } - public set m33(value: number) { this.setAt(3, 3, value); } + public at(row: number, col: number) { + return this.get(col * 4 + row); + } + public setAt(row: number, col: number, value: number) { + this.set(col * 4 + row, value); + } + + public get m00() { + return this.at(0, 0); + } + public set m00(value: number) { + this.setAt(0, 0, value); + } + public get m01() { + return this.at(0, 1); + } + public set m01(value: number) { + this.setAt(0, 1, value); + } + public get m02() { + return this.at(0, 2); + } + public set m02(value: number) { + this.setAt(0, 2, value); + } + public get m03() { + return this.at(0, 3); + } + public set m03(value: number) { + this.setAt(0, 3, value); + } + public get m10() { + return this.at(1, 0); + } + public set m10(value: number) { + this.setAt(1, 0, value); + } + public get m11() { + return this.at(1, 1); + } + public set m11(value: number) { + this.setAt(1, 1, value); + } + public get m12() { + return this.at(1, 2); + } + public set m12(value: number) { + this.setAt(1, 2, value); + } + public get m13() { + return this.at(1, 3); + } + public set m13(value: number) { + this.setAt(1, 3, value); + } + public get m20() { + return this.at(2, 0); + } + public set m20(value: number) { + this.setAt(2, 0, value); + } + public get m21() { + return this.at(2, 1); + } + public set m21(value: number) { + this.setAt(2, 1, value); + } + public get m22() { + return this.at(2, 2); + } + public set m22(value: number) { + this.setAt(2, 2, value); + } + public get m23() { + return this.at(2, 3); + } + public set m23(value: number) { + this.setAt(2, 3, value); + } + + public get m30() { + return this.at(3, 0); + } + public set m30(value: number) { + this.setAt(3, 0, value); + } + public get m31() { + return this.at(3, 1); + } + public set m31(value: number) { + this.setAt(3, 1, value); + } + public get m32() { + return this.at(3, 2); + } + public set m32(value: number) { + this.setAt(3, 2, value); + } + public get m33() { + return this.at(3, 3); + } + public set m33(value: number) { + this.setAt(3, 3, value); + } } // missing Vector3d functions diff --git a/core/frontend/src/render/webgl/Mesh.ts b/core/frontend/src/render/webgl/Mesh.ts index 9a8f2ac1e4d3..e82af8b81a03 100644 --- a/core/frontend/src/render/webgl/Mesh.ts +++ b/core/frontend/src/render/webgl/Mesh.ts @@ -10,18 +10,18 @@ import { dispose } from "@itwin/core-bentley"; import { Point3d, Range3d } from "@itwin/core-geometry"; import { MeshParams } from "../../common/internal/render/MeshParams"; import { SurfaceType } from "../../common/internal/render/SurfaceParams"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; import { RenderMemory } from "../RenderMemory"; import { CachedGeometry } from "./CachedGeometry"; +import { EdgeGeometry, PolylineEdgeGeometry, SilhouetteEdgeGeometry } from "./EdgeGeometry"; import { Graphic } from "./Graphic"; +import { IndexedEdgeGeometry } from "./IndexedEdgeGeometry"; import { InstanceBuffers, PatternBuffers } from "./InstancedGeometry"; +import { MeshData } from "./MeshData"; import { Primitive } from "./Primitive"; import { RenderCommands } from "./RenderCommands"; import { RenderPass } from "./RenderFlags"; -import { EdgeGeometry, PolylineEdgeGeometry, SilhouetteEdgeGeometry } from "./EdgeGeometry"; -import { IndexedEdgeGeometry } from "./IndexedEdgeGeometry"; import { SurfaceGeometry } from "./SurfaceGeometry"; -import { MeshData } from "./MeshData"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; /** @internal */ export class MeshRenderGeometry implements RenderGeometry { @@ -106,8 +106,12 @@ export class MeshGraphic extends Graphic { private readonly _instances?: InstanceBuffers | PatternBuffers; private readonly _meshRange: Range3d; - public get primitives(): readonly Primitive[] { return this._primitives; } - public get meshRange(): Readonly { return this._meshRange; } + public get primitives(): readonly Primitive[] { + return this._primitives; + } + public get meshRange(): Readonly { + return this._meshRange; + } public static create(geometry: MeshRenderGeometry, instances?: InstanceBuffers | PatternBuffers): MeshGraphic | undefined { return new MeshGraphic(geometry, instances); @@ -135,8 +139,12 @@ export class MeshGraphic extends Graphic { this.addPrimitive(geometry.indexedEdges); } - public get isDisposed(): boolean { return this.meshData.isDisposed && 0 === this._primitives.length; } - public get isPickable() { return false; } + public get isDisposed(): boolean { + return this.meshData.isDisposed && 0 === this._primitives.length; + } + public get isPickable() { + return false; + } public dispose() { for (const primitive of this._primitives) @@ -160,8 +168,14 @@ export class MeshGraphic extends Graphic { range.extendRange(this._meshRange); } - public addCommands(cmds: RenderCommands): void { this._primitives.forEach((prim) => prim.addCommands(cmds)); } - public override addHiliteCommands(cmds: RenderCommands, pass: RenderPass): void { this._primitives.forEach((prim) => prim.addHiliteCommands(cmds, pass)); } + public addCommands(cmds: RenderCommands): void { + this._primitives.forEach((prim) => prim.addCommands(cmds)); + } + public override addHiliteCommands(cmds: RenderCommands, pass: RenderPass): void { + this._primitives.forEach((prim) => prim.addHiliteCommands(cmds, pass)); + } - public get surfaceType(): SurfaceType { return this.meshData.type; } + public get surfaceType(): SurfaceType { + return this.meshData.type; + } } diff --git a/core/frontend/src/render/webgl/MeshData.ts b/core/frontend/src/render/webgl/MeshData.ts index bd72698aba18..ea248f978dcb 100644 --- a/core/frontend/src/render/webgl/MeshData.ts +++ b/core/frontend/src/render/webgl/MeshData.ts @@ -7,8 +7,8 @@ */ import { dispose } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { FeatureIndexType, FillFlags, LinePixels } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { MeshParams } from "../../common/internal/render/MeshParams"; import { SurfaceType } from "../../common/internal/render/SurfaceParams"; import { RenderMemory } from "../RenderMemory"; @@ -70,11 +70,11 @@ export class MeshData implements WebGLDisposable { this.constantLodVParams = new Float32Array(3); this.constantLodVParams[0] = matTM.params.constantLodParams.offset.x; // x offset this.constantLodVParams[1] = matTM.params.constantLodParams.offset.y; // y offset - this.constantLodVParams[3] = 0.0; // placeholder for orto view distance + this.constantLodVParams[3] = 0.0; // placeholder for orto view distance this.constantLodFParams = new Float32Array(3); this.constantLodFParams[0] = matTM.params.constantLodParams.minDistClamp; // Minimum texture size this.constantLodFParams[1] = matTM.params.constantLodParams.maxDistClamp; // Maximum texture size - this.constantLodFParams[2] = matTM.params.constantLodParams.repetitions; // # repetitions of pattern (to scale it) + this.constantLodFParams[2] = matTM.params.constantLodParams.repetitions; // # repetitions of pattern (to scale it) } } } @@ -99,7 +99,9 @@ export class MeshData implements WebGLDisposable { return undefined !== lut ? new MeshData(lut, params, viOrigin) : undefined; } - public get isDisposed(): boolean { return undefined === this.texture && this.lut.isDisposed; } + public get isDisposed(): boolean { + return undefined === this.texture && this.lut.isDisposed; + } public dispose() { dispose(this.lut); @@ -107,8 +109,12 @@ export class MeshData implements WebGLDisposable { this.texture!.dispose(); } - public get isGlyph() { return undefined !== this.texture && this.texture.isGlyph; } - public get isTextureAlwaysDisplayed() { return this.isGlyph || this._textureAlwaysDisplayed; } + public get isGlyph() { + return undefined !== this.texture && this.texture.isGlyph; + } + public get isTextureAlwaysDisplayed() { + return this.isGlyph || this._textureAlwaysDisplayed; + } // Returns true if no one else owns this texture. Implies that the texture should be disposed when this object is disposed, and the texture's memory should be tracked as belonging to this object. private get _ownsTexture(): boolean { diff --git a/core/frontend/src/render/webgl/MeshGeometry.ts b/core/frontend/src/render/webgl/MeshGeometry.ts index 2d03a393cfbe..6140d98b6c5c 100644 --- a/core/frontend/src/render/webgl/MeshGeometry.ts +++ b/core/frontend/src/render/webgl/MeshGeometry.ts @@ -11,9 +11,9 @@ import { LUTGeometry } from "./CachedGeometry"; import { ColorInfo } from "./ColorInfo"; import { ShaderProgramParams } from "./DrawCommand"; import { FloatRgba } from "./FloatRGBA"; +import { MeshData } from "./MeshData"; import { Pass } from "./RenderFlags"; import { Target } from "./Target"; -import { MeshData } from "./MeshData"; /** Defines one aspect of the geometry of a mesh (surface or edges) * @internal @@ -22,23 +22,53 @@ export abstract class MeshGeometry extends LUTGeometry { public readonly mesh: MeshData; protected readonly _numIndices: number; - public override get asMesh() { return this; } - protected override _getLineWeight(params: ShaderProgramParams): number { return this.computeEdgeWeight(params); } + public override get asMesh() { + return this; + } + protected override _getLineWeight(params: ShaderProgramParams): number { + return this.computeEdgeWeight(params); + } // Convenience accessors... - public get edgeWidth() { return this.mesh.edgeWidth; } - public get edgeLineCode() { return this.mesh.edgeLineCode; } - public override get hasFeatures() { return this.mesh.hasFeatures; } - public get surfaceType() { return this.mesh.type; } - public get fillFlags() { return this.mesh.fillFlags; } - public get isPlanar() { return this.mesh.isPlanar; } - public get colorInfo(): ColorInfo { return this.mesh.lut.colorInfo; } - public get uniformColor(): FloatRgba | undefined { return this.colorInfo.isUniform ? this.colorInfo.uniform : undefined; } - public get texture() { return this.mesh.texture; } - public get normalMap() { return this.mesh.normalMap; } - public override get hasBakedLighting() { return this.mesh.hasBakedLighting; } - public get lut() { return this.mesh.lut; } - public get hasScalarAnimation() { return this.mesh.lut.hasScalarAnimation; } + public get edgeWidth() { + return this.mesh.edgeWidth; + } + public get edgeLineCode() { + return this.mesh.edgeLineCode; + } + public override get hasFeatures() { + return this.mesh.hasFeatures; + } + public get surfaceType() { + return this.mesh.type; + } + public get fillFlags() { + return this.mesh.fillFlags; + } + public get isPlanar() { + return this.mesh.isPlanar; + } + public get colorInfo(): ColorInfo { + return this.mesh.lut.colorInfo; + } + public get uniformColor(): FloatRgba | undefined { + return this.colorInfo.isUniform ? this.colorInfo.uniform : undefined; + } + public get texture() { + return this.mesh.texture; + } + public get normalMap() { + return this.mesh.normalMap; + } + public override get hasBakedLighting() { + return this.mesh.hasBakedLighting; + } + public get lut() { + return this.mesh.lut; + } + public get hasScalarAnimation() { + return this.mesh.lut.hasScalarAnimation; + } protected constructor(mesh: MeshData, numIndices: number) { super(mesh.viewIndependentOrigin); diff --git a/core/frontend/src/render/webgl/PerformanceMetrics.ts b/core/frontend/src/render/webgl/PerformanceMetrics.ts index d1a3ff3375df..d1a684f11289 100644 --- a/core/frontend/src/render/webgl/PerformanceMetrics.ts +++ b/core/frontend/src/render/webgl/PerformanceMetrics.ts @@ -75,10 +75,14 @@ export class PerformanceMetrics { // Use double buffering here to ensure that we grab a COMPLETE set of timings from a SINGLE run when grabbing timing data while continuously rendering this._updateallTimePoints1 = !this._updateallTimePoints1; // Switch to other allTimePoints buffer if (this._updateallTimePoints1) { // Get data from the old buffer that was just completed - this._allTimePoints2.forEach((record: AllTimePoints) => this.frameTimings.set(record.name, record.end.milliseconds - record.begin.milliseconds)); + this._allTimePoints2.forEach((record: AllTimePoints) => + this.frameTimings.set(record.name, record.end.milliseconds - record.begin.milliseconds) + ); this._allTimePoints2 = []; // Reset to empty } else { - this._allTimePoints1.forEach((record: AllTimePoints) => this.frameTimings.set(record.name, record.end.milliseconds - record.begin.milliseconds)); + this._allTimePoints1.forEach((record: AllTimePoints) => + this.frameTimings.set(record.name, record.end.milliseconds - record.begin.milliseconds) + ); this._allTimePoints1 = []; // Reset to empty } this._beginTimePoints = []; // This should be back to [] at this point diff --git a/core/frontend/src/render/webgl/PlanarClassifier.ts b/core/frontend/src/render/webgl/PlanarClassifier.ts index c2d0484635f3..7dab45485963 100644 --- a/core/frontend/src/render/webgl/PlanarClassifier.ts +++ b/core/frontend/src/render/webgl/PlanarClassifier.ts @@ -9,10 +9,18 @@ import { BeEvent, dispose } from "@itwin/core-bentley"; import { - ColorDef, Frustum, FrustumPlanes, RenderMode, RenderTexture, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, TextureTransparency, + ColorDef, + Frustum, + FrustumPlanes, + RenderMode, + RenderTexture, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + TextureTransparency, } from "@itwin/core-common"; import { Matrix4d, Plane3dByOriginAndUnitNormal, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { PlanarClipMaskState } from "../../PlanarClipMaskState"; +import { ActiveSpatialClassifier } from "../../SpatialClassifiersState"; import { GraphicsCollectorDrawArgs, SpatialClassifierTileTreeReference, TileTreeReference } from "../../tile/internal"; import { SceneContext } from "../../ViewContext"; import { FeatureSymbology } from "../FeatureSymbology"; @@ -36,9 +44,13 @@ import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; import { Texture, TextureHandle } from "./Texture"; -import { ActiveSpatialClassifier } from "../../SpatialClassifiersState"; -export enum PlanarClassifierContent { None = 0, MaskOnly = 1, ClassifierOnly = 2, ClassifierAndMask = 3 } +export enum PlanarClassifierContent { + None = 0, + MaskOnly = 1, + ClassifierOnly = 2, + ClassifierAndMask = 3, +} function createTexture(handle: TextureHandle): Texture { return new Texture({ @@ -54,9 +66,7 @@ function createTextureHandle(width: number, height: number, heightMult = 1.0) { } class ClassifierTextures implements WebGLDisposable { - private constructor(public readonly color: Texture, - public readonly feature: Texture, - public readonly hilite: Texture) { } + private constructor(public readonly color: Texture, public readonly feature: Texture, public readonly hilite: Texture) {} public get isDisposed(): boolean { return this.color.isDisposed @@ -98,7 +108,8 @@ class ClassifierFrameBuffers implements WebGLDisposable { public readonly textures: ClassifierTextures, private readonly _hilite: FrameBuffer, private readonly _fbo: FrameBuffer, - private readonly _clearGeom: ViewportQuadGeometry) { + private readonly _clearGeom: ViewportQuadGeometry, + ) { } public get isDisposed(): boolean { @@ -155,8 +166,12 @@ interface TextureAndFbo { abstract class SingleTextureFrameBuffer implements WebGLDisposable { public texture: Texture; protected fbo: FrameBuffer; - public get isDisposed(): boolean { return this.texture.isDisposed && this.fbo.isDisposed; } - public collectStatistics(stats: RenderMemory.Statistics): void { stats.addPlanarClassifier(this.texture.bytesUsed); } + public get isDisposed(): boolean { + return this.texture.isDisposed && this.fbo.isDisposed; + } + public collectStatistics(stats: RenderMemory.Statistics): void { + stats.addPlanarClassifier(this.texture.bytesUsed); + } protected constructor(textureAndFbo: TextureAndFbo) { this.texture = textureAndFbo.texture; this.fbo = textureAndFbo.fbo; @@ -170,7 +185,12 @@ abstract class SingleTextureFrameBuffer implements WebGLDisposable { if (!hTexture) return undefined; - const texture = new Texture({ type: RenderTexture.Type.TileSection, ownership: "external", handle: hTexture, transparency: TextureTransparency.Opaque }); + const texture = new Texture({ + type: RenderTexture.Type.TileSection, + ownership: "external", + handle: hTexture, + transparency: TextureTransparency.Opaque, + }); if (!texture) return undefined; @@ -198,7 +218,15 @@ class MaskFrameBuffer extends SingleTextureFrameBuffer { } } abstract class CombineTexturesFrameBuffer extends SingleTextureFrameBuffer { - constructor(textureAndFbo: TextureAndFbo, private _combineGeom: CachedGeometry, private _width: number, private _height: number, private _heightMult: number) { super(textureAndFbo); } + constructor( + textureAndFbo: TextureAndFbo, + private _combineGeom: CachedGeometry, + private _width: number, + private _height: number, + private _heightMult: number, + ) { + super(textureAndFbo); + } public compose(target: Target): void { const system = System.instance; const gl = system.context; @@ -212,7 +240,12 @@ abstract class CombineTexturesFrameBuffer extends SingleTextureFrameBuffer { } class ClassifierCombinationBuffer extends CombineTexturesFrameBuffer { - public static create(width: number, height: number, classifierColor: Texture, classifierFeature: Texture): ClassifierAndMaskCombinationBuffer | undefined { + public static create( + width: number, + height: number, + classifierColor: Texture, + classifierFeature: Texture, + ): ClassifierAndMaskCombinationBuffer | undefined { const combineGeom = CombineTexturesGeometry.createGeometry(classifierColor.texture.getHandle()!, classifierFeature.texture.getHandle()!); if (undefined === combineGeom) return undefined; @@ -222,8 +255,18 @@ class ClassifierCombinationBuffer extends CombineTexturesFrameBuffer { } } class ClassifierAndMaskCombinationBuffer extends CombineTexturesFrameBuffer { - public static create(width: number, height: number, classifierColor: Texture, classifierFeature: Texture, mask: Texture): ClassifierAndMaskCombinationBuffer | undefined { - const combineGeom = Combine3TexturesGeometry.createGeometry(classifierColor.texture.getHandle()!, classifierFeature.texture.getHandle()!, mask.texture.getHandle()!); + public static create( + width: number, + height: number, + classifierColor: Texture, + classifierFeature: Texture, + mask: Texture, + ): ClassifierAndMaskCombinationBuffer | undefined { + const combineGeom = Combine3TexturesGeometry.createGeometry( + classifierColor.texture.getHandle()!, + classifierFeature.texture.getHandle()!, + mask.texture.getHandle()!, + ); if (undefined === combineGeom) return undefined; @@ -252,7 +295,7 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe private _anyOpaque = false; private _anyTranslucent = false; private _classifier?: ActiveSpatialClassifier; - private readonly _plane = Plane3dByOriginAndUnitNormal.create(new Point3d(0, 0, 0), new Vector3d(0, 0, 1))!; // TBD -- Support other planes - default to X-Y for now. + private readonly _plane = Plane3dByOriginAndUnitNormal.create(new Point3d(0, 0, 0), new Vector3d(0, 0, 1))!; // TBD -- Support other planes - default to X-Y for now. private readonly _renderState = new RenderState(); private readonly _renderCommands: RenderCommands; private readonly _branchStack = new BranchStack(); @@ -264,13 +307,26 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe private _removeMe?: () => void; private _featureSymbologySource: FeatureSymbology.Source = { onSourceDisposed: new BeEvent<() => void>(), - };; + }; private static _postProjectionMatrix = Matrix4d.createRowValues( - 0, 1, 0, 0, - 0, 0, -1, 0, - 1, 0, 0, 0, - 0, 0, 0, 1); + 0, + 1, + 0, + 0, + 0, + 0, + -1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ); private _debugFrustum?: Frustum; private _doDebugFrustum = false; private _debugFrustumGraphic?: RenderGraphic = undefined; @@ -287,29 +343,48 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe this._batchState = new BatchState(this._branchStack); this._renderCommands = new RenderCommands(target, this._branchStack, this._batchState); } - public get textureImageCount(): number { return this._contentMode; } + public get textureImageCount(): number { + return this._contentMode; + } public getParams(params: Float32Array): void { params[0] = this.insideDisplay; params[1] = this.outsideDisplay; params[2] = this._contentMode; - if (this._planarClipMask?.settings.invert) // If the mask sense is inverted, negate the contentMode to indicate this to the shader. - params[2] = - params[2]; + if (this._planarClipMask?.settings.invert) // If the mask sense is inverted, negate the contentMode to indicate this to the shader. + params[2] = -params[2]; params[3] = (this._planarClipMask?.settings.transparency === undefined) ? -1 : this._planarClipMask.settings.transparency; - } - public get hiliteTexture(): Texture | undefined { return undefined !== this._classifierBuffers ? this._classifierBuffers.textures.hilite : undefined; } - public get projectionMatrix(): Matrix4d { return this._projectionMatrix; } + public get hiliteTexture(): Texture | undefined { + return undefined !== this._classifierBuffers ? this._classifierBuffers.textures.hilite : undefined; + } + public get projectionMatrix(): Matrix4d { + return this._projectionMatrix; + } // public get properties(): SpatialClassifier { return this._classifier; } - public get baseBatchId(): number { return this._baseBatchId; } - public get anyHilited(): boolean { return this._anyHilited; } - public get anyOpaque(): boolean { return this._anyOpaque; } - public get anyTranslucent(): boolean { return this._anyTranslucent; } - public get insideDisplay(): SpatialClassifierInsideDisplay { return this._classifier ? this._classifier.flags.inside : SpatialClassifierInsideDisplay.Off; } - public get outsideDisplay(): SpatialClassifierOutsideDisplay { return this._classifier ? this._classifier.flags.outside : SpatialClassifierOutsideDisplay.On; } - public get isClassifyingPointCloud(): boolean { return true === this._isClassifyingPointCloud; } + public get baseBatchId(): number { + return this._baseBatchId; + } + public get anyHilited(): boolean { + return this._anyHilited; + } + public get anyOpaque(): boolean { + return this._anyOpaque; + } + public get anyTranslucent(): boolean { + return this._anyTranslucent; + } + public get insideDisplay(): SpatialClassifierInsideDisplay { + return this._classifier ? this._classifier.flags.inside : SpatialClassifierInsideDisplay.Off; + } + public get outsideDisplay(): SpatialClassifierOutsideDisplay { + return this._classifier ? this._classifier.flags.outside : SpatialClassifierOutsideDisplay.On; + } + public get isClassifyingPointCloud(): boolean { + return true === this._isClassifyingPointCloud; + } public addGraphic(graphic: RenderGraphic) { this._graphics!.push(graphic); @@ -333,7 +408,9 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe this._classifierAndMaskCombinedBuffer.collectStatistics(stats); } - public get isDisposed(): boolean { return undefined === this._classifierBuffers; } + public get isDisposed(): boolean { + return undefined === this._classifierBuffers; + } public dispose() { this._classifierBuffers = dispose(this._classifierBuffers); @@ -363,7 +440,12 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe if (undefined === this._classifierBuffers) this._classifierBuffers = ClassifierFrameBuffers.create(this._width, this._height); if (undefined !== this._classifierBuffers && undefined === this._classifierCombinedBuffer) - this._classifierCombinedBuffer = ClassifierCombinationBuffer.create(this._width, this._height, this._classifierBuffers.textures.color, this._classifierBuffers.textures.feature); + this._classifierCombinedBuffer = ClassifierCombinationBuffer.create( + this._width, + this._height, + this._classifierBuffers.textures.color, + this._classifierBuffers.textures.feature, + ); return this._classifierCombinedBuffer?.texture; } @@ -423,7 +505,16 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe if (this._classifierTreeRef) allTrees.push(this._classifierTreeRef); - const projection = PlanarTextureProjection.computePlanarTextureProjection(this._plane, context, target, allTrees, viewState, this._width, this._height, maskRange); + const projection = PlanarTextureProjection.computePlanarTextureProjection( + this._plane, + context, + target, + allTrees, + viewState, + this._width, + this._height, + maskRange, + ); if (!projection.textureFrustum || !projection.projectionMatrix || !projection.worldToViewMap) return; @@ -470,11 +561,11 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe builder.setSymbology(ColorDef.blue, ColorDef.blue, 2); builder.addFrustum(this._frustum); - builder.setSymbology(ColorDef.from(0,200,0,222), ColorDef.from(0,200,0,222), 2); + builder.setSymbology(ColorDef.from(0, 200, 0, 222), ColorDef.from(0, 200, 0, 222), 2); builder.addFrustumSides(context.viewingSpace.getFrustum()); - builder.setSymbology(ColorDef.from(200,0,0,222), ColorDef.from(200,0,0,222), 2); + builder.setSymbology(ColorDef.from(200, 0, 0, 222), ColorDef.from(200, 0, 0, 222), 2); builder.addFrustumSides(this._debugFrustum!); - builder.setSymbology(ColorDef.from(0,0,200,222), ColorDef.from(0,0,200,222), 2); + builder.setSymbology(ColorDef.from(0, 0, 200, 222), ColorDef.from(0, 0, 200, 222), 2); builder.addFrustumSides(this._frustum); this._debugFrustumGraphic = builder.finish(); context.outputGraphic(this._debugFrustumGraphic); @@ -506,7 +597,12 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe } if (this._maskGraphics.length === 0) { if (undefined === this._classifierCombinedBuffer) { - combinationBuffer = this._classifierCombinedBuffer = ClassifierCombinationBuffer.create(this._width, this._height, this._classifierBuffers.textures.color, this._classifierBuffers.textures.feature); + combinationBuffer = this._classifierCombinedBuffer = ClassifierCombinationBuffer.create( + this._width, + this._height, + this._classifierBuffers.textures.color, + this._classifierBuffers.textures.feature, + ); if (undefined === this._classifierCombinedBuffer) return; } @@ -519,7 +615,13 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe return; } if (undefined === this._classifierAndMaskCombinedBuffer) { - combinationBuffer = this._classifierAndMaskCombinedBuffer = ClassifierAndMaskCombinationBuffer.create(this._width, this._height, this._classifierBuffers.textures.color, this._classifierBuffers.textures.feature, this._maskBuffer.texture); + combinationBuffer = this._classifierAndMaskCombinedBuffer = ClassifierAndMaskCombinationBuffer.create( + this._width, + this._height, + this._classifierBuffers.textures.color, + this._classifierBuffers.textures.feature, + this._maskBuffer.texture, + ); if (undefined === this._classifierAndMaskCombinedBuffer) return; } @@ -599,7 +701,6 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe this._anyTranslucent = true; this._maskBuffer.draw(getDrawCommands(this._maskGraphics), target); - } if (combinationBuffer) combinationBuffer.compose(target); @@ -612,4 +713,3 @@ export class PlanarClassifier extends RenderPlanarClassifier implements RenderMe system.context.viewport(0, 0, target.viewRect.width, target.viewRect.height); } } - diff --git a/core/frontend/src/render/webgl/PlanarGrid.ts b/core/frontend/src/render/webgl/PlanarGrid.ts index 1e1df44d0c0a..1ad49583c574 100644 --- a/core/frontend/src/render/webgl/PlanarGrid.ts +++ b/core/frontend/src/render/webgl/PlanarGrid.ts @@ -7,8 +7,8 @@ */ import { assert } from "@itwin/core-bentley"; -import { Plane3dByOriginAndUnitNormal, Point2d, Transform } from "@itwin/core-geometry"; import { Frustum, QPoint2dList, QPoint3dList } from "@itwin/core-common"; +import { Plane3dByOriginAndUnitNormal, Point2d, Transform } from "@itwin/core-geometry"; import { GraphicBranch } from "../GraphicBranch"; import { RenderGraphic } from "../RenderGraphic"; import { RenderMemory } from "../RenderMemory"; @@ -22,10 +22,15 @@ import { Pass, RenderOrder } from "./RenderFlags"; import { TechniqueId } from "./TechniqueId"; class PlanarGridGeometryParams extends IndexedGeometryParams { - public readonly uvParams: QBufferHandle2d; - public constructor(positions: QBufferHandle3d, uvParams: QBufferHandle2d, indices: BufferHandle, numIndices: number, public readonly props: PlanarGridProps) { + public constructor( + positions: QBufferHandle3d, + uvParams: QBufferHandle2d, + indices: BufferHandle, + numIndices: number, + public readonly props: PlanarGridProps, + ) { super(positions, indices, numIndices); const attrParams = AttributeMap.findAttribute("a_uvParam", TechniqueId.PlanarGrid, false); assert(attrParams !== undefined); @@ -35,13 +40,21 @@ class PlanarGridGeometryParams extends IndexedGeometryParams { } export class PlanarGridGeometry extends IndexedGeometry { - public get techniqueId(): TechniqueId { return TechniqueId.PlanarGrid; } - public override getPass(): Pass { return "translucent"; } - public collectStatistics(_stats: RenderMemory.Statistics): void { } - public get renderOrder(): RenderOrder { return RenderOrder.UnlitSurface; } + public get techniqueId(): TechniqueId { + return TechniqueId.PlanarGrid; + } + public override getPass(): Pass { + return "translucent"; + } + public collectStatistics(_stats: RenderMemory.Statistics): void {} + public get renderOrder(): RenderOrder { + return RenderOrder.UnlitSurface; + } public readonly uvParams: QBufferHandle2d; public readonly props: PlanarGridProps; - public override get asPlanarGrid(): PlanarGridGeometry | undefined { return this; } + public override get asPlanarGrid(): PlanarGridGeometry | undefined { + return this; + } private constructor(params: PlanarGridGeometryParams) { super(params); @@ -110,4 +123,3 @@ export class PlanarGridGeometry extends IndexedGeometry { return graphic; } } - diff --git a/core/frontend/src/render/webgl/PlanarTextureProjection.ts b/core/frontend/src/render/webgl/PlanarTextureProjection.ts index d27ad4b08b68..79fa26793905 100644 --- a/core/frontend/src/render/webgl/PlanarTextureProjection.ts +++ b/core/frontend/src/render/webgl/PlanarTextureProjection.ts @@ -9,8 +9,19 @@ import { Frustum, FrustumPlanes, Npc, RenderMode } from "@itwin/core-common"; import { - ClipUtilities, ConvexClipPlaneSet, GrowableXYZArray, Map4d, Matrix3d, Matrix4d, Plane3dByOriginAndUnitNormal, Point3d, Range1d, Range2d, Range3d, - Ray3d, Transform, + ClipUtilities, + ConvexClipPlaneSet, + GrowableXYZArray, + Map4d, + Matrix3d, + Matrix4d, + Plane3dByOriginAndUnitNormal, + Point3d, + Range1d, + Range2d, + Range3d, + Ray3d, + Transform, } from "@itwin/core-geometry"; import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; import { Tile, TileTreeReference } from "../../tile/internal"; @@ -23,7 +34,24 @@ const scratchRange = Range3d.createNull(); const scratchMap4d = Map4d.createIdentity(); const scratchMatrix4d = Matrix4d.createIdentity(); export class PlanarTextureProjection { - private static _postProjectionMatrixNpc = Matrix4d.createRowValues(/* Row 1 */ 0, 1, 0, 0, /* Row 2 */ 0, 0, 1, 0, /* Row 3 */ 1, 0, 0, 0, /* Row 4 */ 0, 0, 0, 1); + private static _postProjectionMatrixNpc = Matrix4d.createRowValues( + /* Row 1 */ 0, + 1, + 0, + 0, + /* Row 2 */ 0, + 0, + 1, + 0, + /* Row 3 */ 1, + 0, + 0, + 0, + /* Row 4 */ 0, + 0, + 0, + 1, + ); private static isTileRangeInBounds(tileRange: Range3d, drapeRange: Range3d): boolean { // return false if tile is outside of drapeRange, ignoring height (x) for this @@ -43,7 +71,8 @@ export class PlanarTextureProjection { textureWidth: number, textureHeight: number, maskRange: Range3d, - _heightRange?: Range1d): { textureFrustum?: Frustum, worldToViewMap?: Map4d, projectionMatrix?: Matrix4d, debugFrustum?: Frustum } { + _heightRange?: Range1d, + ): { textureFrustum?: Frustum, worldToViewMap?: Map4d, projectionMatrix?: Matrix4d, debugFrustum?: Frustum } { const textureZ = texturePlane.getNormalRef(); const viewingSpace = sceneContext.viewingSpace; const viewX = viewingSpace.rotation.rowX(); @@ -51,7 +80,7 @@ export class PlanarTextureProjection { const minCrossMagnitude = 1.0E-4; if (viewZ === undefined) - return {}; // View without depth?.... + return {}; // View without depth?.... let textureX = viewZ.crossProduct(textureZ); let textureY; @@ -135,9 +164,10 @@ export class PlanarTextureProjection { const textureFrustum = Frustum.fromRange(textureRange); let debugFrustum; - if (true) // debugFrustum as textureRange. + if (true) // debugFrustum as textureRange. debugFrustum = textureFrustum.clone(); - else // debugFrustum as drapeRange. + // debugFrustum as drapeRange. + else debugFrustum = Frustum.fromRange(drapeRange); textureTransform.multiplyInversePoint3dArray(debugFrustum.points, debugFrustum.points); @@ -149,10 +179,10 @@ export class PlanarTextureProjection { // viewZVecZ is negative when looking up, positive when looking down. if (viewState.isCameraOn && viewState.getEyePoint().z > textureRange.low.x && viewZVecZ > 0.09) { // NB moved the eyePlane from the center to the bottom of the textureRange to solve problems when the eye was below the eyePlane. - const eyePlane = Plane3dByOriginAndUnitNormal.create(Point3d.createScale(textureZ, textureRange.low.x), textureZ); // at bottom of range - parallel to texture. + const eyePlane = Plane3dByOriginAndUnitNormal.create(Point3d.createScale(textureZ, textureRange.low.x), textureZ); // at bottom of range - parallel to texture. const projectionRay = Ray3d.create(viewState.getEyePoint(), viewZ.crossProduct(textureX).normalize()!); let projectionDistance = projectionRay.intersectionWithPlane(eyePlane!); - const minNearToFarRatio = .01; // Smaller value allows texture projection to conform tightly to view frustum. + const minNearToFarRatio = .01; // Smaller value allows texture projection to conform tightly to view frustum. if (undefined !== projectionDistance) { projectionDistance = Math.max(.1, projectionDistance); const eyePoint = textureTransform.multiplyPoint3d(projectionRay.fractionToPoint(projectionDistance)); @@ -202,7 +232,13 @@ export class PlanarTextureProjection { return {}; } const worldToNpc = PlanarTextureProjection._postProjectionMatrixNpc.multiplyMatrixMatrix(frustumMap.transform0); - const npcToView = Map4d.createBoxMap(Point3d.create(0, 0, 0), Point3d.create(1, 1, 1), Point3d.create(0, 0, 0), Point3d.create(textureWidth, textureHeight, 1), scratchMap4d)!; + const npcToView = Map4d.createBoxMap( + Point3d.create(0, 0, 0), + Point3d.create(1, 1, 1), + Point3d.create(0, 0, 0), + Point3d.create(textureWidth, textureHeight, 1), + scratchMap4d, + )!; const npcToWorld = worldToNpc.createInverse(scratchMatrix4d); if (undefined === npcToWorld) { return {}; diff --git a/core/frontend/src/render/webgl/PointCloud.ts b/core/frontend/src/render/webgl/PointCloud.ts index b7bc831af47b..d35b7b5ede40 100644 --- a/core/frontend/src/render/webgl/PointCloud.ts +++ b/core/frontend/src/render/webgl/PointCloud.ts @@ -10,17 +10,17 @@ import { assert, dispose } from "@itwin/core-bentley"; import { FeatureIndexType } from "@itwin/core-common"; import { PointCloudArgs } from "../../common/internal/render/PointCloudPrimitive"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; import { RenderMemory } from "../RenderMemory"; +import { BufferHandle, BufferParameters, BuffersContainer, QBufferHandle3d } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { CachedGeometry } from "./CachedGeometry"; import { ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer, QBufferHandle3d } from "./AttributeBuffers"; import { Pass, RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; /** @internal */ export class PointCloudGeometry extends CachedGeometry implements RenderGeometry { @@ -36,10 +36,18 @@ export class PointCloudGeometry extends CachedGeometry implements RenderGeometry public readonly voxelSize: number; public readonly colorIsBgr: boolean; - public get isDisposed(): boolean { return this.buffers.isDisposed && this._vertices.isDisposed; } - public override get asPointCloud(): PointCloudGeometry | undefined { return this; } - public override get supportsThematicDisplay() { return true; } - public get overrideColorMix() { return .5; } // This could be a setting from either the mesh or the override if required. + public get isDisposed(): boolean { + return this.buffers.isDisposed && this._vertices.isDisposed; + } + public override get asPointCloud(): PointCloudGeometry | undefined { + return this; + } + public override get supportsThematicDisplay() { + return true; + } + public get overrideColorMix() { + return .5; + } // This could be a setting from either the mesh or the override if required. public dispose() { if (!this.noDispose) { @@ -54,7 +62,9 @@ export class PointCloudGeometry extends CachedGeometry implements RenderGeometry this._vertices = QBufferHandle3d.create(pointCloud.qparams, pointCloud.positions) as QBufferHandle3d; const attrPos = AttributeMap.findAttribute("a_pos", TechniqueId.PointCloud, false); assert(undefined !== attrPos); - const vertexDataType = (pointCloud.positions instanceof Float32Array) ? GL.DataType.Float : ((pointCloud.positions instanceof Uint8Array) ? GL.DataType.UnsignedByte : GL.DataType.UnsignedShort); + const vertexDataType = (pointCloud.positions instanceof Float32Array) + ? GL.DataType.Float + : ((pointCloud.positions instanceof Uint8Array) ? GL.DataType.UnsignedByte : GL.DataType.UnsignedShort); this.buffers.addBuffer(this._vertices, [BufferParameters.create(attrPos.location, 3, vertexDataType, false, 0, 0, false)]); this._vertexCount = pointCloud.positions.length / 3; this._hasFeatures = FeatureIndexType.Empty !== pointCloud.features.type; @@ -74,19 +84,35 @@ export class PointCloudGeometry extends CachedGeometry implements RenderGeometry stats.addPointCloud(bytesUsed); } - protected _wantWoWReversal(_target: Target): boolean { return false; } + protected _wantWoWReversal(_target: Target): boolean { + return false; + } - public get techniqueId(): TechniqueId { return TechniqueId.PointCloud; } + public get techniqueId(): TechniqueId { + return TechniqueId.PointCloud; + } public override getPass(target: Target): Pass { // Point clouds don't cast shadows. return target.isDrawingShadowMap ? "none" : "point-clouds"; } - public get renderOrder(): RenderOrder { return RenderOrder.Linear; } - public get qOrigin(): Float32Array { return this._vertices.origin; } - public get qScale(): Float32Array { return this._vertices.scale; } - public get colors(): BufferHandle | undefined { return this._colorHandle; } - public override get hasFeatures() { return this._hasFeatures; } - public override get hasBakedLighting() { return true; } + public get renderOrder(): RenderOrder { + return RenderOrder.Linear; + } + public get qOrigin(): Float32Array { + return this._vertices.origin; + } + public get qScale(): Float32Array { + return this._vertices.scale; + } + public get colors(): BufferHandle | undefined { + return this._colorHandle; + } + public override get hasFeatures() { + return this._hasFeatures; + } + public override get hasBakedLighting() { + return true; + } public draw(): void { this.buffers.bind(); @@ -97,6 +123,6 @@ export class PointCloudGeometry extends CachedGeometry implements RenderGeometry // ###TODO delete this. public override getLineWeight(_params: ShaderProgramParams): number { // If line weight < 0 it is real size in meters (voxel size). - return (this.voxelSize > 0) ? - this.voxelSize : 1; + return (this.voxelSize > 0) ? -this.voxelSize : 1; } } diff --git a/core/frontend/src/render/webgl/PointString.ts b/core/frontend/src/render/webgl/PointString.ts index fdefe2844805..107e2eb3839e 100644 --- a/core/frontend/src/render/webgl/PointString.ts +++ b/core/frontend/src/render/webgl/PointString.ts @@ -7,21 +7,21 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { FeatureIndexType, QParams3d } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { PointStringParams } from "../../common/internal/render/PointStringParams"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; import { RenderMemory } from "../RenderMemory"; +import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { LUTGeometry } from "./CachedGeometry"; import { ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { Pass, RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; import { VertexLUT } from "./VertexLUT"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; /** @internal */ export class PointStringGeometry extends LUTGeometry implements RenderGeometry { @@ -36,9 +36,19 @@ export class PointStringGeometry extends LUTGeometry implements RenderGeometry { public readonly indices: BufferHandle; public readonly numIndices: number; - public get lutBuffers() { return this.buffers; } + public get lutBuffers() { + return this.buffers; + } - private constructor(indices: BufferHandle, numIndices: number, lut: VertexLUT, qparams: QParams3d, weight: number, hasFeatures: boolean, viOrigin: Point3d | undefined) { + private constructor( + indices: BufferHandle, + numIndices: number, + lut: VertexLUT, + qparams: QParams3d, + weight: number, + hasFeatures: boolean, + viOrigin: Point3d | undefined, + ) { super(viOrigin); this.isInstanceable = undefined === viOrigin; this.buffers = BuffersContainer.create(); @@ -53,13 +63,25 @@ export class PointStringGeometry extends LUTGeometry implements RenderGeometry { this._hasFeatures = hasFeatures; } - protected _wantWoWReversal(_target: Target): boolean { return true; } + protected _wantWoWReversal(_target: Target): boolean { + return true; + } - public get techniqueId(): TechniqueId { return TechniqueId.PointString; } - public override getPass(): Pass { return "opaque-linear"; } - public override get hasFeatures() { return this._hasFeatures; } - public get renderOrder(): RenderOrder { return RenderOrder.PlanarLinear; } - protected override _getLineWeight(_params: ShaderProgramParams): number { return this.weight; } + public get techniqueId(): TechniqueId { + return TechniqueId.PointString; + } + public override getPass(): Pass { + return "opaque-linear"; + } + public override get hasFeatures() { + return this._hasFeatures; + } + public get renderOrder(): RenderOrder { + return RenderOrder.PlanarLinear; + } + protected override _getLineWeight(_params: ShaderProgramParams): number { + return this.weight; + } protected _draw(numInstances: number, instanceBuffersContainer?: BuffersContainer): void { const gl = System.instance; diff --git a/core/frontend/src/render/webgl/Polyline.ts b/core/frontend/src/render/webgl/Polyline.ts index eeea0c96bfcc..77eb117e1e3d 100644 --- a/core/frontend/src/render/webgl/Polyline.ts +++ b/core/frontend/src/render/webgl/Polyline.ts @@ -7,22 +7,22 @@ */ import { dispose } from "@itwin/core-bentley"; -import { Point3d } from "@itwin/core-geometry"; import { FeatureIndexType, PolylineTypeFlags, QParams3d, RenderMode } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { PolylineParams } from "../../common/internal/render/PolylineParams"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; import { RenderMemory } from "../RenderMemory"; +import { BuffersContainer } from "./AttributeBuffers"; import { LUTGeometry, PolylineBuffers } from "./CachedGeometry"; import { ColorInfo } from "./ColorInfo"; import { ShaderProgramParams } from "./DrawCommand"; -import { LineCode } from "./LineCode"; import { GL } from "./GL"; -import { BuffersContainer } from "./AttributeBuffers"; +import { LineCode } from "./LineCode"; import { Pass, RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; import { VertexLUT } from "./VertexLUT"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; /** @internal */ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { @@ -39,7 +39,9 @@ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { public numIndices: number; private _buffers: PolylineBuffers; - public get lutBuffers() { return this._buffers.buffers; } + public get lutBuffers() { + return this._buffers.buffers; + } private constructor(lut: VertexLUT, buffers: PolylineBuffers, params: PolylineParams, viOrigin: Point3d | undefined) { super(viOrigin); @@ -55,7 +57,9 @@ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { this._buffers = buffers; } - public get isDisposed(): boolean { return this._buffers.isDisposed && this.lut.isDisposed; } + public get isDisposed(): boolean { + return this._buffers.isDisposed && this.lut.isDisposed; + } public dispose() { if (!this.noDispose) { @@ -69,9 +73,15 @@ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { stats.addVertexTable(this.lut.bytesUsed); } - public get isAnyEdge(): boolean { return PolylineTypeFlags.Normal !== this.type; } - public get isNormalEdge(): boolean { return PolylineTypeFlags.Edge === this.type; } - public get isOutlineEdge(): boolean { return PolylineTypeFlags.Outline === this.type; } + public get isAnyEdge(): boolean { + return PolylineTypeFlags.Normal !== this.type; + } + public get isNormalEdge(): boolean { + return PolylineTypeFlags.Edge === this.type; + } + public get isOutlineEdge(): boolean { + return PolylineTypeFlags.Outline === this.type; + } public get renderOrder(): RenderOrder { if (this.isAnyEdge) @@ -80,9 +90,13 @@ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { return this.isPlanar ? RenderOrder.PlanarLinear : RenderOrder.Linear; } - protected _wantWoWReversal(_target: Target): boolean { return true; } + protected _wantWoWReversal(_target: Target): boolean { + return true; + } - public override get polylineBuffers(): PolylineBuffers | undefined { return this._buffers; } + public override get polylineBuffers(): PolylineBuffers | undefined { + return this._buffers; + } private _computeEdgePass(target: Target, colorInfo: ColorInfo): Pass { const vf = target.currentViewFlags; @@ -109,13 +123,27 @@ export class PolylineGeometry extends LUTGeometry implements RenderGeometry { return isTranslucent ? "translucent" : "opaque-linear"; } - public get techniqueId(): TechniqueId { return TechniqueId.Polyline; } - public get isPlanar(): boolean { return this._isPlanar; } - public override get isEdge(): boolean { return this.isAnyEdge; } - public override get qOrigin(): Float32Array { return this.lut.qOrigin; } - public override get qScale(): Float32Array { return this.lut.qScale; } - public get numRgbaPerVertex(): number { return this.lut.numRgbaPerVertex; } - public override get hasFeatures() { return this._hasFeatures; } + public get techniqueId(): TechniqueId { + return TechniqueId.Polyline; + } + public get isPlanar(): boolean { + return this._isPlanar; + } + public override get isEdge(): boolean { + return this.isAnyEdge; + } + public override get qOrigin(): Float32Array { + return this.lut.qOrigin; + } + public override get qScale(): Float32Array { + return this.lut.qScale; + } + public get numRgbaPerVertex(): number { + return this.lut.numRgbaPerVertex; + } + public override get hasFeatures() { + return this._hasFeatures; + } protected override _getLineWeight(params: ShaderProgramParams): number { return this.isEdge ? params.target.computeEdgeWeight(params.renderPass, this.lineWeight) : this.lineWeight; diff --git a/core/frontend/src/render/webgl/Primitive.ts b/core/frontend/src/render/webgl/Primitive.ts index 3124aa5a2631..4f102a03abb5 100644 --- a/core/frontend/src/render/webgl/Primitive.ts +++ b/core/frontend/src/render/webgl/Primitive.ts @@ -7,6 +7,7 @@ */ import { assert, dispose } from "@itwin/core-bentley"; +import { Range3d } from "@itwin/core-geometry"; import { RenderMemory } from "../RenderMemory"; import { PrimitiveVisibility } from "../RenderTarget"; import { CachedGeometry, LUTGeometry, SkySphereViewportQuadGeometry } from "./CachedGeometry"; @@ -19,7 +20,6 @@ import { ShaderProgramExecutor } from "./ShaderProgram"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { Range3d } from "@itwin/core-geometry"; /** @internal */ export class Primitive extends Graphic { @@ -62,8 +62,12 @@ export class Primitive extends Graphic { return new this(geom); } - public get isDisposed(): boolean { return this.cachedGeometry.isDisposed; } - public get isPickable() { return false; } + public get isDisposed(): boolean { + return this.cachedGeometry.isDisposed; + } + public get isPickable() { + return false; + } public dispose() { dispose(this.cachedGeometry); @@ -95,9 +99,13 @@ export class Primitive extends Graphic { return this.cachedGeometry.getPass(target); } - public get hasFeatures(): boolean { return this.cachedGeometry.hasFeatures; } + public get hasFeatures(): boolean { + return this.cachedGeometry.hasFeatures; + } - public addCommands(commands: RenderCommands): void { commands.addPrimitive(this); } + public addCommands(commands: RenderCommands): void { + commands.addPrimitive(this); + } public override addHiliteCommands(commands: RenderCommands, pass: RenderPass): void { // Edges do not contribute to hilite pass. @@ -106,18 +114,34 @@ export class Primitive extends Graphic { commands.getCommands(pass).push(new PrimitiveCommand(this)); } - public get hasAnimation(): boolean { return this.cachedGeometry.hasAnimation; } - public get isInstanced(): boolean { return this.cachedGeometry.isInstanced; } - public get isLit(): boolean { return this.cachedGeometry.isLitSurface; } - public get isEdge(): boolean { return this.cachedGeometry.isEdge; } - public get renderOrder(): RenderOrder { return this.cachedGeometry.renderOrder; } - public get hasMaterialAtlas(): boolean { return this.cachedGeometry.hasMaterialAtlas; } + public get hasAnimation(): boolean { + return this.cachedGeometry.hasAnimation; + } + public get isInstanced(): boolean { + return this.cachedGeometry.isInstanced; + } + public get isLit(): boolean { + return this.cachedGeometry.isLitSurface; + } + public get isEdge(): boolean { + return this.cachedGeometry.isEdge; + } + public get renderOrder(): RenderOrder { + return this.cachedGeometry.renderOrder; + } + public get hasMaterialAtlas(): boolean { + return this.cachedGeometry.hasMaterialAtlas; + } - public override toPrimitive(): Primitive { return this; } + public override toPrimitive(): Primitive { + return this; + } private static _drawParams?: DrawParams; - public static freeParams(): void { Primitive._drawParams = undefined; } + public static freeParams(): void { + Primitive._drawParams = undefined; + } public draw(shader: ShaderProgramExecutor): void { // ###TODO: local to world should be pushed before we're invoked...we shouldn't need to pass (or copy) it @@ -129,12 +153,16 @@ export class Primitive extends Graphic { shader.draw(drawParams); } - public get techniqueId(): TechniqueId { return this.cachedGeometry.techniqueId; } + public get techniqueId(): TechniqueId { + return this.cachedGeometry.techniqueId; + } } /** @internal */ export class SkyCubePrimitive extends Primitive { - public constructor(cachedGeom: CachedGeometry) { super(cachedGeom); } + public constructor(cachedGeom: CachedGeometry) { + super(cachedGeom); + } public override draw(shader: ShaderProgramExecutor): void { // Alter viewport to maintain square aspect ratio of skybox images even as viewRect resizes diff --git a/core/frontend/src/render/webgl/RealityMesh.ts b/core/frontend/src/render/webgl/RealityMesh.ts index 2e51a0b961a7..06f6625e1d79 100644 --- a/core/frontend/src/render/webgl/RealityMesh.ts +++ b/core/frontend/src/render/webgl/RealityMesh.ts @@ -10,6 +10,7 @@ import { assert, dispose, disposeArray, IDisposable, UintArray } from "@itwin/core-bentley"; import { ColorDef, Quantization, RenderTexture } from "@itwin/core-common"; import { Matrix4d, Range2d, Range3d, Transform, Vector2d } from "@itwin/core-geometry"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; import { GraphicBranch } from "../GraphicBranch"; import { RealityMeshGraphicParams } from "../RealityMeshGraphicParams"; import { RealityMeshParams } from "../RealityMeshParams"; @@ -28,7 +29,6 @@ import { RenderOrder } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; const scratchOverlapRange = Range2d.createNull(); const scratchBytes = new Uint8Array(4); @@ -46,8 +46,10 @@ class ProjectedTexture { type TerrainOrProjectedTexture = TerrainTexture | ProjectedTexture; class RealityTextureParam implements IDisposable { - constructor(public texture: RenderTexture | undefined, private _projectedTextureOrMatrix: ProjectedTexture | Matrix4) { } - public get isProjected() { return this._projectedTextureOrMatrix instanceof ProjectedTexture; } + constructor(public texture: RenderTexture | undefined, private _projectedTextureOrMatrix: ProjectedTexture | Matrix4) {} + public get isProjected() { + return this._projectedTextureOrMatrix instanceof ProjectedTexture; + } public dispose(): void { this.texture = dispose(this.texture); @@ -63,7 +65,7 @@ class RealityTextureParam implements IDisposable { are instead generated by a projection of the model position onto the X-Y plane. We only have eye position, not model position so the matrix in this case is a real transform matrix that contains a mapping from eye to model position followed by the model to texture projection. -*/ + */ public getProjectionMatrix(): Matrix4d | undefined { return this._projectedTextureOrMatrix instanceof ProjectedTexture ? this._projectedTextureOrMatrix.classifier.projectionMatrix : undefined; } @@ -102,11 +104,11 @@ class RealityTextureParam implements IDisposable { const x0 = result.data[10] - result.data[8], y0 = result.data[11] - result.data[9]; const x1 = result.data[12] - result.data[8], y1 = result.data[13] - result.data[9]; if (x0 * y1 - x1 * y0 < 0) { - const swap = ((i: number, j: number) => { + const swap = (i: number, j: number) => { const temp = result.data[i]; result.data[i] = result.data[j]; result.data[j] = temp; - }); + }; for (let i = 8, j = 14; i <= 10; i += 2, j -= 2) { swap(i, j); swap(i + 1, j + 1); @@ -121,7 +123,7 @@ class RealityTextureParam implements IDisposable { /** @internal */ export class RealityTextureParams implements IDisposable { - constructor(public params: RealityTextureParam[]) { } + constructor(public params: RealityTextureParam[]) {} public static create(textures: TerrainOrProjectedTexture[]) { const maxTexturesPerMesh = System.instance.maxRealityImageryLayers; assert(textures.length <= maxTexturesPerMesh); @@ -130,7 +132,7 @@ export class RealityTextureParams implements IDisposable { for (const texture of textures) { if (texture instanceof TerrainTexture) { const terrainTexture = texture; - const matrix = new Matrix4(); // Published as Mat4. + const matrix = new Matrix4(); // Published as Mat4. assert(terrainTexture.texture !== undefined, "Texture not defined in TerrainTextureParams constructor"); matrix.data[0] = terrainTexture.translate.x; matrix.data[1] = terrainTexture.translate.y; @@ -146,7 +148,7 @@ export class RealityTextureParams implements IDisposable { matrix.data[4] = matrix.data[5] = 0; matrix.data[6] = matrix.data[7] = 1; } - matrix.data[8] = (1.0 - terrainTexture.transparency); + matrix.data[8] = 1.0 - terrainTexture.transparency; matrix.data[9] = terrainTexture.featureId; textureParams.push(new RealityTextureParam(terrainTexture.texture, matrix)); } else { @@ -161,7 +163,7 @@ export class RealityTextureParams implements IDisposable { matrix.data[2] = matrix.data[3] = 1.0; matrix.data[4] = matrix.data[5] = 1; matrix.data[6] = matrix.data[7] = -1; - matrix.data[15] = 0; // Denotes a terrain texture. + matrix.data[15] = 0; // Denotes a terrain texture. textureParams.push(new RealityTextureParam(undefined, matrix)); } return new RealityTextureParams(textureParams); @@ -179,7 +181,15 @@ export class RealityMeshGeometryParams extends IndexedGeometryParams { public readonly normals?: BufferHandle; public readonly numBytesPerIndex: 1 | 2 | 4; - protected constructor(positions: QBufferHandle3d, normals: BufferHandle | undefined, uvParams: QBufferHandle2d, indices: BufferHandle, numIndices: number, numBytesPerIndex: 1 | 2 | 4, featureID?: number) { + protected constructor( + positions: QBufferHandle3d, + normals: BufferHandle | undefined, + uvParams: QBufferHandle2d, + indices: BufferHandle, + numIndices: number, + numBytesPerIndex: 1 | 2 | 4, + featureID?: number, + ) { super(positions, indices, numIndices); this.numBytesPerIndex = numBytesPerIndex; let attrParams = AttributeMap.findAttribute("a_uvParam", TechniqueId.RealityMesh, false); @@ -197,7 +207,13 @@ export class RealityMeshGeometryParams extends IndexedGeometryParams { this.featureID = featureID; } - private static createFromBuffers(posBuf: QBufferHandle3d, uvParamBuf: QBufferHandle2d, indices: UintArray, normBuf: BufferHandle | undefined, featureID: number) { + private static createFromBuffers( + posBuf: QBufferHandle3d, + uvParamBuf: QBufferHandle2d, + indices: UintArray, + normBuf: BufferHandle | undefined, + featureID: number, + ) { const indBuf = BufferHandle.createBuffer(GL.Buffer.Target.ElementArrayBuffer, indices); if (undefined === indBuf) @@ -206,20 +222,23 @@ export class RealityMeshGeometryParams extends IndexedGeometryParams { const bytesPerIndex = indices.BYTES_PER_ELEMENT; assert(1 === bytesPerIndex || 2 === bytesPerIndex || 4 === bytesPerIndex); return new RealityMeshGeometryParams(posBuf, normBuf, uvParamBuf, indBuf, indices.length, bytesPerIndex, featureID); - } public static fromRealityMesh(params: RealityMeshParams) { const posBuf = QBufferHandle3d.create(params.positions.params, params.positions.points); const uvParamBuf = QBufferHandle2d.create(params.uvs.params, params.uvs.points); const normalBuf = params.normals ? BufferHandle.createArrayBuffer(params.normals) : undefined; - return (undefined === posBuf || undefined === uvParamBuf) ? undefined : this.createFromBuffers(posBuf, uvParamBuf, params.indices, normalBuf, params.featureID ?? 0); + return (undefined === posBuf || undefined === uvParamBuf) + ? undefined + : this.createFromBuffers(posBuf, uvParamBuf, params.indices, normalBuf, params.featureID ?? 0); } public override get isDisposed(): boolean { return super.isDisposed && this.uvParams.isDisposed; } - public get bytesUsed(): number { return this.positions.bytesUsed + (undefined === this.normals ? 0 : this.normals.bytesUsed) + this.uvParams.bytesUsed + this.indices.bytesUsed; } + public get bytesUsed(): number { + return this.positions.bytesUsed + (undefined === this.normals ? 0 : this.normals.bytesUsed) + this.uvParams.bytesUsed + this.indices.bytesUsed; + } public override dispose() { super.dispose(); @@ -233,13 +252,27 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet public readonly isInstanceable = false; public noDispose = false; public readonly hasTextures: boolean; - public override get asRealityMesh(): RealityMeshGeometry | undefined { return this; } - public override get isDisposed(): boolean { return this._realityMeshParams.isDisposed; } - public get uvQParams() { return this._realityMeshParams.uvParams.params; } - public override get hasFeatures(): boolean { return this._realityMeshParams.featureID !== undefined; } - public override get supportsThematicDisplay() { return true; } - public get overrideColorMix() { return .5; } // This could be a setting from either the mesh or the override if required. - public get transform(): Transform | undefined { return this._transform; } + public override get asRealityMesh(): RealityMeshGeometry | undefined { + return this; + } + public override get isDisposed(): boolean { + return this._realityMeshParams.isDisposed; + } + public get uvQParams() { + return this._realityMeshParams.uvParams.params; + } + public override get hasFeatures(): boolean { + return this._realityMeshParams.featureID !== undefined; + } + public override get supportsThematicDisplay() { + return true; + } + public get overrideColorMix() { + return .5; + } // This could be a setting from either the mesh or the override if required. + public get transform(): Transform | undefined { + return this._transform; + } private _realityMeshParams: RealityMeshGeometryParams; private readonly _indexType: GL.DataType; @@ -302,13 +335,36 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet const params = RealityMeshGeometryParams.fromRealityMesh(realityMesh); if (!params) return undefined; - const texture = realityMesh.texture ? new TerrainTexture(realityMesh.texture, realityMesh.featureID ?? 0, Vector2d.create(1.0, -1.0), Vector2d.create(0.0, 1.0), Range2d.createXYXY(0, 0, 1, 1), 0, 0) : undefined; + const texture = realityMesh.texture + ? new TerrainTexture( + realityMesh.texture, + realityMesh.featureID ?? 0, + Vector2d.create(1.0, -1.0), + Vector2d.create(0.0, 1.0), + Range2d.createXYXY(0, 0, 1, 1), + 0, + 0, + ) + : undefined; - return new RealityMeshGeometry({ realityMeshParams: params, textureParams: texture ? RealityTextureParams.create([texture]) : undefined, baseIsTransparent: false, isTerrain: false, disableTextureDisposal }); + return new RealityMeshGeometry({ + realityMeshParams: params, + textureParams: texture ? RealityTextureParams.create([texture]) : undefined, + baseIsTransparent: false, + isTerrain: false, + disableTextureDisposal, + }); } public getRange(): Range3d { - return Range3d.createXYZXYZ(this.qOrigin[0], this.qOrigin[1], this.qOrigin[2], this.qOrigin[0] + Quantization.rangeScale16 * this.qScale[0], this.qOrigin[1] + Quantization.rangeScale16 * this.qScale[1], this.qOrigin[2] + Quantization.rangeScale16 * this.qScale[2]); + return Range3d.createXYZXYZ( + this.qOrigin[0], + this.qOrigin[1], + this.qOrigin[2], + this.qOrigin[0] + Quantization.rangeScale16 * this.qScale[0], + this.qOrigin[1] + Quantization.rangeScale16 * this.qScale[1], + this.qOrigin[2] + Quantization.rangeScale16 * this.qScale[2], + ); } public static createGraphic(system: RenderSystem, params: RealityMeshGraphicParams, disableTextureDisposal = false): RenderGraphic | undefined { @@ -328,11 +384,23 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet layers[texture.layerIndex] = [texture]; } } - params.layerClassifiers?.forEach((layerClassifier, layerIndex) => layers[layerIndex] = [new ProjectedTexture(layerClassifier, params, params.tileRectangle)]); + params.layerClassifiers?.forEach((layerClassifier, layerIndex) => + layers[layerIndex] = [new ProjectedTexture(layerClassifier, params, params.tileRectangle)] + ); if (layers.length < 2 && !layerClassifiers?.size && textures.length < texturesPerMesh) { // If only there is not more than one layer then we can group all of the textures into a single draw call. - meshes.push(new RealityMeshGeometry({ realityMeshParams: realityMesh._realityMeshParams, textureParams: RealityTextureParams.create(textures), transform: realityMesh._transform, baseColor, baseIsTransparent: baseTransparent, isTerrain: realityMesh._isTerrain, disableTextureDisposal })); + meshes.push( + new RealityMeshGeometry({ + realityMeshParams: realityMesh._realityMeshParams, + textureParams: RealityTextureParams.create(textures), + transform: realityMesh._transform, + baseColor, + baseIsTransparent: baseTransparent, + isTerrain: realityMesh._isTerrain, + disableTextureDisposal, + }), + ); } else { let primaryLayer; while (primaryLayer === undefined) @@ -368,10 +436,30 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet } } while (layerTextures.length > texturesPerMesh) { - meshes.push(new RealityMeshGeometry({ realityMeshParams: realityMesh._realityMeshParams, textureParams: RealityTextureParams.create(layerTextures.slice(0, texturesPerMesh)), transform: realityMesh._transform, baseColor, baseIsTransparent: baseTransparent, isTerrain: realityMesh._isTerrain, disableTextureDisposal })); + meshes.push( + new RealityMeshGeometry({ + realityMeshParams: realityMesh._realityMeshParams, + textureParams: RealityTextureParams.create(layerTextures.slice(0, texturesPerMesh)), + transform: realityMesh._transform, + baseColor, + baseIsTransparent: baseTransparent, + isTerrain: realityMesh._isTerrain, + disableTextureDisposal, + }), + ); layerTextures = layerTextures.slice(texturesPerMesh); } - meshes.push(new RealityMeshGeometry({ realityMeshParams: realityMesh._realityMeshParams, textureParams: RealityTextureParams.create(layerTextures), transform: realityMesh._transform, baseColor, baseIsTransparent: baseTransparent, isTerrain: realityMesh._isTerrain, disableTextureDisposal })); + meshes.push( + new RealityMeshGeometry({ + realityMeshParams: realityMesh._realityMeshParams, + textureParams: RealityTextureParams.create(layerTextures), + transform: realityMesh._transform, + baseColor, + baseIsTransparent: baseTransparent, + isTerrain: realityMesh._isTerrain, + disableTextureDisposal, + }), + ); } } @@ -384,7 +472,9 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet branch.add(system.createBatch(primitive!, featureTable, mesh.getRange(), { tileId })); } - return system.createBranch(branch, realityMesh._transform ? realityMesh._transform : Transform.createIdentity(), {disableClipStyle: params.disableClipStyle}); + return system.createBranch(branch, realityMesh._transform ? realityMesh._transform : Transform.createIdentity(), { + disableClipStyle: params.disableClipStyle, + }); } public collectStatistics(stats: RenderMemory.Statistics): void { @@ -397,7 +487,9 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet } } - public get techniqueId(): TechniqueId { return TechniqueId.RealityMesh; } + public get techniqueId(): TechniqueId { + return TechniqueId.RealityMesh; + } public override getPass(target: Target) { if (this._baseIsTransparent || (target.wantThematicDisplay && target.uniforms.thematic.wantIsoLines)) @@ -405,7 +497,9 @@ export class RealityMeshGeometry extends IndexedGeometry implements RenderGeomet return "opaque"; } - public get renderOrder(): RenderOrder { return RenderOrder.UnlitSurface; } + public get renderOrder(): RenderOrder { + return RenderOrder.UnlitSurface; + } public override draw(): void { this._params.buffers.bind(); diff --git a/core/frontend/src/render/webgl/RealityModelUniforms.ts b/core/frontend/src/render/webgl/RealityModelUniforms.ts index 44db8a188894..a38f45798437 100644 --- a/core/frontend/src/render/webgl/RealityModelUniforms.ts +++ b/core/frontend/src/render/webgl/RealityModelUniforms.ts @@ -8,10 +8,10 @@ */ import { PointCloudDisplaySettings, RealityModelDisplaySettings } from "@itwin/core-common"; -import { UniformHandle } from "./UniformHandle"; -import { desync, sync } from "./Sync"; import { Range3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { desync, sync } from "./Sync"; import { Target } from "./Target"; +import { UniformHandle } from "./UniformHandle"; /** A Target keeps track of the current settings for drawing point clouds. * Pushing a Branch may *replace* the current settings. Popping the Branch does not reset them. It is expected that every Branch containing @@ -54,7 +54,7 @@ export class PointCloudUniforms { } public updateRange(range: Range3d | undefined, target: Target, xform: Transform, is3d: boolean): void { - let rangeFactor = 8.0; // default to min scale factor of 8 + let rangeFactor = 8.0; // default to min scale factor of 8 const near = target.uniforms.frustum.nearPlane; const far = target.uniforms.frustum.farPlane; const viewDepth = far - near; @@ -63,12 +63,13 @@ export class PointCloudUniforms { // calculate a "normalized" strength factor based on the size of the point cloud versus the current viewing depth // from the matrix, only care about scaling factor here (entries 0,4,8) to scale the range lengths // then use the largest length component as the reference for the size of the point cloud - const rangeScale = Vector3d.create(scale.coffs[0] * range.xLength(), scale.coffs[4] * range.xLength(), scale.coffs[8] * range.xLength()).maxAbs(); + const rangeScale = Vector3d.create(scale.coffs[0] * range.xLength(), scale.coffs[4] * range.xLength(), scale.coffs[8] * range.xLength()) + .maxAbs(); // limit the viewDepth/rangeScale ratio to min of 10 to still get reasonable factors when close to and inside the model - rangeFactor = Math.log (Math.max (10, viewDepth / rangeScale)); + rangeFactor = Math.log(Math.max(10, viewDepth / rangeScale)); } - const zoomFactor = Math.log (far / near); // compensate for zoom level - const winSizeFactor = Math.pow (1.8440033, Math.log2 (2226 / target.uniforms.viewRect.width)); // compensate for window size + const zoomFactor = Math.log(far / near); // compensate for zoom level + const winSizeFactor = Math.pow(1.8440033, Math.log2(2226 / target.uniforms.viewRect.width)); // compensate for window size const scaleFactor = (rangeFactor + zoomFactor) / winSizeFactor; if (this._scaleFactor === scaleFactor && this._is3d === is3d) diff --git a/core/frontend/src/render/webgl/RenderBuffer.ts b/core/frontend/src/render/webgl/RenderBuffer.ts index 28587a16c548..58674478cde4 100644 --- a/core/frontend/src/render/webgl/RenderBuffer.ts +++ b/core/frontend/src/render/webgl/RenderBuffer.ts @@ -12,7 +12,7 @@ import { GL } from "./GL"; import { System } from "./System"; function computeBytesUsed(width: number, height: number, format: GL.RenderBuffer.Format, numSamples: number): number { - const bytesPerPixel = (GL.RenderBuffer.Format.DepthComponent16 === format ? 2 : 4); + const bytesPerPixel = GL.RenderBuffer.Format.DepthComponent16 === format ? 2 : 4; return width * height * bytesPerPixel * numSamples; } @@ -23,11 +23,19 @@ export class RenderBuffer implements WebGLDisposable { private _width: number; private _height: number; - public get bytesUsed(): number { return this._bytesUsed; } - public get width(): number { return this._width; } - public get height(): number { return this._height; } + public get bytesUsed(): number { + return this._bytesUsed; + } + public get width(): number { + return this._width; + } + public get height(): number { + return this._height; + } - public getHandle() { return this._glBuffer; } + public getHandle() { + return this._glBuffer; + } public static create(width: number, height: number, format = GL.RenderBuffer.Format.DepthComponent16) { const gl = System.instance.context; @@ -45,7 +53,9 @@ export class RenderBuffer implements WebGLDisposable { return new RenderBuffer(glBuffer, width, height, computeBytesUsed(width, height, format, 1)); } - public get isDisposed(): boolean { return this._glBuffer === undefined || this._glBuffer === null; } + public get isDisposed(): boolean { + return this._glBuffer === undefined || this._glBuffer === null; + } public dispose(): void { if (!this.isDisposed) { @@ -69,8 +79,12 @@ export class RenderBuffer implements WebGLDisposable { this._height = height; } - private static bindBuffer(glBuffer: WebGLRenderbuffer | null) { System.instance.context.bindRenderbuffer(GL.RenderBuffer.TARGET, glBuffer); } - private static unbind() { this.bindBuffer(null); } + private static bindBuffer(glBuffer: WebGLRenderbuffer | null) { + System.instance.context.bindRenderbuffer(GL.RenderBuffer.TARGET, glBuffer); + } + private static unbind() { + this.bindBuffer(null); + } } /** @@ -84,15 +98,25 @@ export class RenderBufferMultiSample implements WebGLDisposable { private _height: number; private _isDirty: boolean = false; - public get bytesUsed(): number { return this._bytesUsed; } - public get width(): number { return this._width; } - public get height(): number { return this._height; } - public get isDirty(): boolean { return this._isDirty; } + public get bytesUsed(): number { + return this._bytesUsed; + } + public get width(): number { + return this._width; + } + public get height(): number { + return this._height; + } + public get isDirty(): boolean { + return this._isDirty; + } public markBufferDirty(dirty: boolean) { this._isDirty = dirty; } - public getHandle() { return this._glBuffer; } + public getHandle() { + return this._glBuffer; + } public static create(width: number, height: number, format: number, numSamples: number) { const gl = System.instance.context; @@ -108,7 +132,9 @@ export class RenderBufferMultiSample implements WebGLDisposable { return new RenderBufferMultiSample(glBuffer, width, height, computeBytesUsed(width, height, format, numSamples)); } - public get isDisposed(): boolean { return this._glBuffer === undefined || this._glBuffer === null; } + public get isDisposed(): boolean { + return this._glBuffer === undefined || this._glBuffer === null; + } public dispose(): void { if (!this.isDisposed) { @@ -131,6 +157,10 @@ export class RenderBufferMultiSample implements WebGLDisposable { this._height = height; } - private static bindBuffer(glBuffer: WebGLRenderbuffer | null) { System.instance.context.bindRenderbuffer(GL.RenderBuffer.TARGET, glBuffer); } - private static unbind() { this.bindBuffer(null); } + private static bindBuffer(glBuffer: WebGLRenderbuffer | null) { + System.instance.context.bindRenderbuffer(GL.RenderBuffer.TARGET, glBuffer); + } + private static unbind() { + this.bindBuffer(null); + } } diff --git a/core/frontend/src/render/webgl/RenderCommands.ts b/core/frontend/src/render/webgl/RenderCommands.ts index 3fddf628eed2..3dd9ccf639ae 100644 --- a/core/frontend/src/render/webgl/RenderCommands.ts +++ b/core/frontend/src/render/webgl/RenderCommands.ts @@ -7,18 +7,28 @@ */ import { assert } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { Frustum, FrustumPlanes, RenderMode, ViewFlags } from "@itwin/core-common"; -import { Decorations } from "../Decorations"; +import { Range3d } from "@itwin/core-geometry"; import { SurfaceType } from "../../common/internal/render/SurfaceParams"; -import { GraphicList, RenderGraphic } from "../RenderGraphic"; +import { Decorations } from "../Decorations"; import { AnimationBranchState } from "../GraphicBranch"; -import { BranchStack } from "./BranchStack"; +import { GraphicList, RenderGraphic } from "../RenderGraphic"; import { BatchState } from "./BatchState"; +import { BranchStack } from "./BranchStack"; import { BranchState } from "./BranchState"; +import { ClipVolume } from "./ClipVolume"; import { - DrawCommands, PopBatchCommand, PopBranchCommand, PopClipCommand, PopCommand, PrimitiveCommand, PushBatchCommand, - PushBranchCommand, PushClipCommand, PushCommand, PushStateCommand, + DrawCommands, + PopBatchCommand, + PopBranchCommand, + PopClipCommand, + PopCommand, + PrimitiveCommand, + PushBatchCommand, + PushBranchCommand, + PushClipCommand, + PushCommand, + PushStateCommand, } from "./DrawCommand"; import { Batch, Branch, Graphic, GraphicsArray } from "./Graphic"; import { Layer, LayerContainer } from "./Layer"; @@ -26,9 +36,8 @@ import { LayerCommandLists } from "./LayerCommands"; import { MeshGraphic } from "./Mesh"; import { Primitive } from "./Primitive"; import { CompositeFlags, Pass, RenderOrder, RenderPass } from "./RenderFlags"; -import { TargetGraphics } from "./TargetGraphics"; import { Target } from "./Target"; -import { ClipVolume } from "./ClipVolume"; +import { TargetGraphics } from "./TargetGraphics"; /** A list of DrawCommands to be rendered, ordered by render pass. * @internal @@ -48,7 +57,9 @@ export class RenderCommands implements Iterable { private _addTranslucentAsOpaque = false; // true when rendering for _ReadPixels to force translucent items to be drawn in opaque pass. private readonly _layers: LayerCommandLists; - public get target(): Target { return this._target; } + public get target(): Target { + return this._target; + } public [Symbol.iterator](): Iterator { return this._commands[Symbol.iterator](); @@ -73,13 +84,18 @@ export class RenderCommands implements Iterable { } } - public get currentViewFlags(): ViewFlags { return this._stack.top.viewFlags; } + public get currentViewFlags(): ViewFlags { + return this._stack.top.viewFlags; + } public get compositeFlags(): CompositeFlags { let flags = CompositeFlags.None; if (this.hasCommands(RenderPass.Translucent)) flags |= CompositeFlags.Translucent; - if (this.hasCommands(RenderPass.Hilite) || this.hasCommands(RenderPass.HiliteClassification) || this.hasCommands(RenderPass.HilitePlanarClassification)) + if ( + this.hasCommands(RenderPass.Hilite) || this.hasCommands(RenderPass.HiliteClassification) || + this.hasCommands(RenderPass.HilitePlanarClassification) + ) flags |= CompositeFlags.Hilite; if (this.target.wantAmbientOcclusion) @@ -88,10 +104,16 @@ export class RenderCommands implements Iterable { return flags; } - private get _curBatch(): Batch | undefined { return this._batchState.currentBatch; } + private get _curBatch(): Batch | undefined { + return this._batchState.currentBatch; + } - public hasCommands(pass: RenderPass): boolean { return 0 !== this.getCommands(pass).length; } - public isOpaquePass(pass: RenderPass): boolean { return pass >= RenderPass.OpaqueLinear && pass <= RenderPass.OpaqueGeneral; } + public hasCommands(pass: RenderPass): boolean { + return 0 !== this.getCommands(pass).length; + } + public isOpaquePass(pass: RenderPass): boolean { + return pass >= RenderPass.OpaqueLinear && pass <= RenderPass.OpaqueGeneral; + } constructor(target: Target, stack: BranchStack, batchState: BatchState) { this._target = target; @@ -492,7 +514,11 @@ export class RenderCommands implements Iterable { } } - public initForPickOverlays(sceneOverlays: GraphicList, worldOverlayDecorations: GraphicList | undefined, viewOverlayDecorations: GraphicList | undefined): void { + public initForPickOverlays( + sceneOverlays: GraphicList, + worldOverlayDecorations: GraphicList | undefined, + viewOverlayDecorations: GraphicList | undefined, + ): void { this._clearCommands(); this._addTranslucentAsOpaque = true; @@ -691,8 +717,10 @@ export class RenderCommands implements Iterable { const anyHilited = overrides.anyHilited; const planarClassifierHilited = undefined !== classifier && classifier.anyHilited; if (anyHilited || planarClassifierHilited) - (batch.graphic as Graphic).addHiliteCommands(this, planarClassifierHilited ? RenderPass.HilitePlanarClassification : this.computeBatchHiliteRenderPass(batch)); - + (batch.graphic as Graphic).addHiliteCommands( + this, + planarClassifierHilited ? RenderPass.HilitePlanarClassification : this.computeBatchHiliteRenderPass(batch), + ); }); this._opaqueOverrides = this._translucentOverrides = false; @@ -700,9 +728,13 @@ export class RenderCommands implements Iterable { } // Define a culling frustum. Commands associated with Graphics whose ranges do not intersect the frustum will be skipped. - public setCheckRange(frustum: Frustum) { this._frustumPlanes = FrustumPlanes.fromFrustum(frustum); } + public setCheckRange(frustum: Frustum) { + this._frustumPlanes = FrustumPlanes.fromFrustum(frustum); + } // Clear the culling frustum. - public clearCheckRange(): void { this._frustumPlanes = undefined; } + public clearCheckRange(): void { + this._frustumPlanes = undefined; + } private setupClassificationByVolume(): void { // To make it easier to process the classifiers individually, set up a secondary command list for them where they @@ -726,7 +758,8 @@ export class RenderCommands implements Iterable { for (let i = pushCommands.length - 1; i >= 0; --i) { if ("pushBatch" === pushCommands[i].opcode) byIndexCmds.push(PopBatchCommand.instance); - else // should be eith pushBranch or pushState opcode + // should be eith pushBranch or pushState opcode + else byIndexCmds.push(PopBranchCommand.instance); } break; diff --git a/core/frontend/src/render/webgl/RenderFlags.ts b/core/frontend/src/render/webgl/RenderFlags.ts index b56118340e9e..1f5cb309f17f 100644 --- a/core/frontend/src/render/webgl/RenderFlags.ts +++ b/core/frontend/src/render/webgl/RenderFlags.ts @@ -15,22 +15,22 @@ export const enum RenderPass { None = 0xff, Background = 0, - OpaqueLayers, // XY planar models render without depth-testing in order based on priority - OpaqueLinear, // Linear geometry that is opaque and needs to be written to the pick data buffers - OpaquePlanar, // Planar surface geometry that is opaque and needs to be written to the pick data buffers + OpaqueLayers, // XY planar models render without depth-testing in order based on priority + OpaqueLinear, // Linear geometry that is opaque and needs to be written to the pick data buffers + OpaquePlanar, // Planar surface geometry that is opaque and needs to be written to the pick data buffers PointClouds, - OpaqueGeneral, // All other opaque geometry (including point clouds and reality meshes) which are not written to the pick data buffers - Classification, // Stencil volumes for normal processing of reality data classification. - TranslucentLayers, // like Layers but drawn without depth write, blending with opaque + OpaqueGeneral, // All other opaque geometry (including point clouds and reality meshes) which are not written to the pick data buffers + Classification, // Stencil volumes for normal processing of reality data classification. + TranslucentLayers, // like Layers but drawn without depth write, blending with opaque Translucent, HiddenEdge, Hilite, - OverlayLayers, // Like Layers, but drawn atop all other geometry - WorldOverlay, // Decorations - ViewOverlay, // Decorations + OverlayLayers, // Like Layers, but drawn atop all other geometry + WorldOverlay, // Decorations + ViewOverlay, // Decorations SkyBox, BackgroundMap, - HiliteClassification, // Secondary hilite pass for stencil volumes to process hilited classifiers for reality data + HiliteClassification, // Secondary hilite pass for stencil volumes to process hilited classifiers for reality data ClassificationByIndex, // Stencil volumes for processing classification one classifier at a time (used for generating pick data Ids and flashing a single classifier). HilitePlanarClassification, PlanarClassification, @@ -47,19 +47,29 @@ export const enum RenderPass { * @internal */ export type Pass = - "skybox" | // SkyBox - "opaque" | // OpaqueGeneral - "opaque-linear" | // OpaqueLinear - "opaque-planar" | // OpaquePlanar - "translucent" | // Translucent - "point-clouds" | // PointClouds - "view-overlay" | // ViewOverlay - "classification" | // Classification - "none" | // None + | "skybox" + | // SkyBox + "opaque" + | // OpaqueGeneral + "opaque-linear" + | // OpaqueLinear + "opaque-planar" + | // OpaquePlanar + "translucent" + | // Translucent + "point-clouds" + | // PointClouds + "view-overlay" + | // ViewOverlay + "classification" + | // Classification + "none" + | // None // The following apply to textured meshes when the texture image contains a mix of opaque and transparent pixels. // The mesh requests to be rendered in both opaque and transparent passes, with each pass discarding pixels that don't match that pass. // (i.e., discard transparent pixels during opaque pass and vice-versa). - "opaque-translucent" | // OpaqueGeneral and Translucent + "opaque-translucent" + | // OpaqueGeneral and Translucent "opaque-planar-translucent"; // OpaquePlanar and Translucent /** [[Pass]]es that map to two [[RenderPass]]es. @@ -85,15 +95,24 @@ export namespace Pass { // eslint-disable-line @typescript-eslint/no-redeclare /** Return the RenderPass corresponding to the specified Pass. */ export function toRenderPass(pass: SinglePass): RenderPass { switch (pass) { - case "skybox": return RenderPass.SkyBox; - case "opaque": return RenderPass.OpaqueGeneral; - case "opaque-linear": return RenderPass.OpaqueLinear; - case "opaque-planar": return RenderPass.OpaquePlanar; - case "translucent": return RenderPass.Translucent; - case "point-clouds": return RenderPass.PointClouds; - case "view-overlay": return RenderPass.ViewOverlay; - case "classification": return RenderPass.Classification; - case "none": return RenderPass.None; + case "skybox": + return RenderPass.SkyBox; + case "opaque": + return RenderPass.OpaqueGeneral; + case "opaque-linear": + return RenderPass.OpaqueLinear; + case "opaque-planar": + return RenderPass.OpaquePlanar; + case "translucent": + return RenderPass.Translucent; + case "point-clouds": + return RenderPass.PointClouds; + case "view-overlay": + return RenderPass.ViewOverlay; + case "classification": + return RenderPass.Classification; + case "none": + return RenderPass.None; } } @@ -297,4 +316,8 @@ export const enum EmphasisFlags { } /** @internal */ -export const enum IsTranslucent { No, Yes, Maybe } +export const enum IsTranslucent { + No, + Yes, + Maybe, +} diff --git a/core/frontend/src/render/webgl/RenderState.ts b/core/frontend/src/render/webgl/RenderState.ts index d0c0c9413fa3..bbec3b9ffc3b 100644 --- a/core/frontend/src/render/webgl/RenderState.ts +++ b/core/frontend/src/render/webgl/RenderState.ts @@ -103,8 +103,11 @@ export class RenderStateBlend { if (previousBlend === undefined || previousBlend.equationRgb !== this.equationRgb || previousBlend.equationAlpha !== this.equationAlpha) { gl.blendEquationSeparate(this.equationRgb, this.equationAlpha); } - if (previousBlend === undefined || previousBlend.functionSourceRgb !== this.functionSourceRgb || previousBlend.functionSourceAlpha !== this.functionSourceAlpha - || previousBlend.functionDestRgb !== this.functionDestRgb || previousBlend.functionDestAlpha !== this.functionDestAlpha) { + if ( + previousBlend === undefined || previousBlend.functionSourceRgb !== this.functionSourceRgb || + previousBlend.functionSourceAlpha !== this.functionSourceAlpha + || previousBlend.functionDestRgb !== this.functionDestRgb || previousBlend.functionDestAlpha !== this.functionDestAlpha + ) { gl.blendFuncSeparate(this.functionSourceRgb, this.functionDestRgb, this.functionSourceAlpha, this.functionDestAlpha); } } diff --git a/core/frontend/src/render/webgl/SceneCompositor.ts b/core/frontend/src/render/webgl/SceneCompositor.ts index 79baf98a3981..4f2130fbd75c 100644 --- a/core/frontend/src/render/webgl/SceneCompositor.ts +++ b/core/frontend/src/render/webgl/SceneCompositor.ts @@ -7,44 +7,57 @@ */ import { assert, dispose, Id64String } from "@itwin/core-bentley"; -import { Transform, Vector2d, Vector3d } from "@itwin/core-geometry"; import { - ModelFeature, PointCloudDisplaySettings, RenderFeatureTable, RenderMode, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, + ModelFeature, + PointCloudDisplaySettings, + RenderFeatureTable, + RenderMode, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, } from "@itwin/core-common"; +import { Transform, Vector2d, Vector3d } from "@itwin/core-geometry"; import { RenderType } from "@itwin/webgl-compatibility"; +import { ViewRect } from "../../common/ViewRect"; import { IModelConnection } from "../../IModelConnection"; import { SceneContext } from "../../ViewContext"; -import { ViewRect } from "../../common/ViewRect"; import { Pixel } from "../Pixel"; import { GraphicList } from "../RenderGraphic"; import { RenderMemory } from "../RenderMemory"; -import { BranchState } from "./BranchState"; import { BatchState } from "./BatchState"; +import { BranchState } from "./BranchState"; import { - AmbientOcclusionGeometry, BlurGeometry, BlurType, BoundaryType, CachedGeometry, CompositeGeometry, CopyPickBufferGeometry, - SingleTexturedViewportQuadGeometry, ViewportQuadGeometry, VolumeClassifierGeometry, + AmbientOcclusionGeometry, + BlurGeometry, + BlurType, + BoundaryType, + CachedGeometry, + CompositeGeometry, + CopyPickBufferGeometry, + SingleTexturedViewportQuadGeometry, + ViewportQuadGeometry, + VolumeClassifierGeometry, } from "./CachedGeometry"; import { Debug } from "./Diagnostics"; import { WebGLDisposable } from "./Disposable"; import { DrawCommands, extractFlashedVolumeClassifierCommands, extractHilitedVolumeClassifierCommands } from "./DrawCommand"; +import { EDLMode, EyeDomeLighting } from "./EDL"; import { DepthBuffer, FrameBuffer } from "./FrameBuffer"; +import { FrustumUniformType } from "./FrustumUniforms"; import { GL } from "./GL"; import { IModelFrameLifecycle } from "./IModelFrameLifecycle"; import { Matrix4 } from "./Matrix"; +import { Primitive } from "./Primitive"; +import { RenderBufferMultiSample } from "./RenderBuffer"; import { RenderCommands } from "./RenderCommands"; import { CompositeFlags, RenderOrder, RenderPass, TextureUnit } from "./RenderFlags"; import { RenderState } from "./RenderState"; import { getDrawParams } from "./ScratchDrawParams"; +import { ShaderProgramExecutor } from "./ShaderProgram"; import { SolarShadowMap } from "./SolarShadowMap"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; import { TextureHandle } from "./Texture"; -import { RenderBufferMultiSample } from "./RenderBuffer"; -import { Primitive } from "./Primitive"; -import { ShaderProgramExecutor } from "./ShaderProgram"; -import { EDLMode, EyeDomeLighting } from "./EDL"; -import { FrustumUniformType } from "./FrustumUniforms"; export function collectTextureStatistics(texture: TextureHandle | undefined, stats: RenderMemory.Statistics): void { if (undefined !== texture) @@ -320,7 +333,10 @@ class FrameBuffers implements WebGLDisposable { private initPotentialMSMRTFbos(textures: Textures, depth: DepthBuffer, depthMs: DepthBuffer | undefined): boolean { const boundColor = System.instance.frameBufferStack.currentColorBuffer; - assert(undefined !== boundColor && undefined !== textures.color && undefined !== textures.featureId && undefined !== textures.depthAndOrder && undefined !== textures.accumulation && undefined !== textures.revealage); + assert( + undefined !== boundColor && undefined !== textures.color && undefined !== textures.featureId && undefined !== textures.depthAndOrder && + undefined !== textures.accumulation && undefined !== textures.revealage, + ); const colorAndPick = [boundColor, textures.featureId, textures.depthAndOrder]; if (undefined === depthMs) { @@ -328,7 +344,10 @@ class FrameBuffers implements WebGLDisposable { colorAndPick[0] = textures.color; this.opaqueAndCompositeAll = FrameBuffer.create(colorAndPick, depth); } else { - assert(undefined !== textures.colorMsBuff && undefined !== textures.featureIdMsBuff && undefined !== textures.featureIdMsBuffHidden && undefined !== textures.depthAndOrderMsBuff && undefined !== textures.depthAndOrderMsBuffHidden); + assert( + undefined !== textures.colorMsBuff && undefined !== textures.featureIdMsBuff && undefined !== textures.featureIdMsBuffHidden && + undefined !== textures.depthAndOrderMsBuff && undefined !== textures.depthAndOrderMsBuffHidden, + ); const colorAndPickMsBuffs = [textures.colorMsBuff, textures.featureIdMsBuff, textures.depthAndOrderMsBuff]; const colorAndPickFilters = [GL.MultiSampling.Filter.Linear, GL.MultiSampling.Filter.Nearest, GL.MultiSampling.Filter.Nearest]; this.opaqueAll = FrameBuffer.create(colorAndPick, depth, colorAndPickMsBuffs, colorAndPickFilters, depthMs); @@ -383,7 +402,13 @@ class FrameBuffers implements WebGLDisposable { this.pingPongMS = dispose(this.pingPongMS); } - public enableVolumeClassifier(textures: Textures, depth: DepthBuffer, volClassDepth: DepthBuffer | undefined, depthMS?: DepthBuffer, volClassDepthMS?: DepthBuffer): void { + public enableVolumeClassifier( + textures: Textures, + depth: DepthBuffer, + volClassDepth: DepthBuffer | undefined, + depthMS?: DepthBuffer, + volClassDepthMS?: DepthBuffer, + ): void { const boundColor = System.instance.frameBufferStack.currentColorBuffer; if (undefined === boundColor) return; @@ -392,8 +417,12 @@ class FrameBuffers implements WebGLDisposable { if (undefined !== depthMS) { // if multisampling use the multisampled depth everywhere this.stencilSet = FrameBuffer.create([], depth, [], [], depthMS); this.altZOnly = FrameBuffer.create([], volClassDepth, [], [], volClassDepthMS); - this.volClassCreateBlend = FrameBuffer.create([textures.volClassBlend!], depth, [textures.volClassBlendMsBuff!], [GL.MultiSampling.Filter.Nearest], depthMS); - this.volClassCreateBlendAltZ = FrameBuffer.create([textures.volClassBlend!], volClassDepth, [textures.volClassBlendMsBuff!], [GL.MultiSampling.Filter.Nearest], volClassDepthMS); + this.volClassCreateBlend = FrameBuffer.create([textures.volClassBlend!], depth, [textures.volClassBlendMsBuff!], [ + GL.MultiSampling.Filter.Nearest, + ], depthMS); + this.volClassCreateBlendAltZ = FrameBuffer.create([textures.volClassBlend!], volClassDepth, [textures.volClassBlendMsBuff!], [ + GL.MultiSampling.Filter.Nearest, + ], volClassDepthMS); } else if (undefined !== volClassDepth) { this.stencilSet = FrameBuffer.create([], depth); this.altZOnly = FrameBuffer.create([], volClassDepth); @@ -529,7 +558,9 @@ class Geometry implements WebGLDisposable, RenderMemory.Consumer { this.composite = CompositeGeometry.createGeometry( textures.color!.getHandle()!, textures.accumulation!.getHandle()!, - textures.revealage!.getHandle()!, textures.hilite!.getHandle()!); + textures.revealage!.getHandle()!, + textures.hilite!.getHandle()!, + ); if (undefined === this.composite) return false; @@ -544,12 +575,29 @@ class Geometry implements WebGLDisposable, RenderMemory.Consumer { } public enableOcclusion(textures: Textures, depth: DepthBuffer): void { - assert(undefined !== textures.occlusion && undefined !== textures.occlusionBlur && undefined !== textures.depthAndOrder && undefined !== textures.occlusionBlur); + assert( + undefined !== textures.occlusion && undefined !== textures.occlusionBlur && undefined !== textures.depthAndOrder && + undefined !== textures.occlusionBlur, + ); this.composite!.occlusion = textures.occlusion.getHandle(); this.occlusion = AmbientOcclusionGeometry.createGeometry(textures.depthAndOrder.getHandle()!, depth.getHandle()!); - this.occlusionXBlur = BlurGeometry.createGeometry(textures.occlusion.getHandle()!, textures.depthAndOrder.getHandle()!, undefined, new Vector2d(1.0, 0.0), BlurType.NoTest); - const depthAndOrderHidden = (undefined === textures.depthAndOrderHidden ? textures.revealage?.getHandle() : textures.depthAndOrderHidden.getHandle()); - this.occlusionYBlur = BlurGeometry.createGeometry(textures.occlusionBlur.getHandle()!, textures.depthAndOrder.getHandle()!, depthAndOrderHidden, new Vector2d(0.0, 1.0), BlurType.TestOrder); + this.occlusionXBlur = BlurGeometry.createGeometry( + textures.occlusion.getHandle()!, + textures.depthAndOrder.getHandle()!, + undefined, + new Vector2d(1.0, 0.0), + BlurType.NoTest, + ); + const depthAndOrderHidden = undefined === textures.depthAndOrderHidden + ? textures.revealage?.getHandle() + : textures.depthAndOrderHidden.getHandle(); + this.occlusionYBlur = BlurGeometry.createGeometry( + textures.occlusionBlur.getHandle()!, + textures.depthAndOrder.getHandle()!, + depthAndOrderHidden, + new Vector2d(0.0, 1.0), + BlurType.TestOrder, + ); } public disableOcclusion(): void { @@ -560,12 +608,16 @@ class Geometry implements WebGLDisposable, RenderMemory.Consumer { } public enableVolumeClassifier(textures: Textures, depth: DepthBuffer): boolean { - assert(undefined === this.volClassColorStencil && undefined === this.volClassCopyZ && undefined === this.volClassSetBlend && undefined === this.volClassBlend); + assert( + undefined === this.volClassColorStencil && undefined === this.volClassCopyZ && undefined === this.volClassSetBlend && + undefined === this.volClassBlend, + ); this.volClassColorStencil = ViewportQuadGeometry.create(TechniqueId.VolClassColorUsingStencil); this.volClassCopyZ = SingleTexturedViewportQuadGeometry.createGeometry(depth.getHandle()!, TechniqueId.VolClassCopyZ); this.volClassSetBlend = VolumeClassifierGeometry.createVCGeometry(depth.getHandle()!); this.volClassBlend = SingleTexturedViewportQuadGeometry.createGeometry(textures.volClassBlend!.getHandle()!, TechniqueId.VolClassBlend); - return undefined !== this.volClassColorStencil && undefined !== this.volClassCopyZ && undefined !== this.volClassSetBlend && undefined !== this.volClassBlend; + return undefined !== this.volClassColorStencil && undefined !== this.volClassCopyZ && undefined !== this.volClassSetBlend && + undefined !== this.volClassBlend; } public disableVolumeClassifier(): void { @@ -613,7 +665,9 @@ class PixelBuffer implements Pixel.Buffer { private readonly _batchState: BatchState; private readonly _scratchModelFeature = ModelFeature.create(); - private get _numPixels(): number { return this._rect.width * this._rect.height; } + private get _numPixels(): number { + return this._rect.width * this._rect.height; + } private getPixelIndex(x: number, y: number): number { if (x < this._rect.left || y < this._rect.top) @@ -784,7 +838,9 @@ class PixelBuffer implements Pixel.Buffer { } } - public get isEmpty(): boolean { return Pixel.Selector.None === this._selector; } + public get isEmpty(): boolean { + return Pixel.Selector.None === this._selector; + } public static create(rect: ViewRect, selector: Pixel.Selector, compositor: SceneCompositor): Pixel.Buffer | undefined { const pdb = new PixelBuffer(rect, selector, compositor); @@ -807,7 +863,12 @@ export abstract class SceneCompositor implements WebGLDisposable, RenderMemory.C public abstract dispose(): void; public abstract preDraw(): void; public abstract draw(_commands: RenderCommands): void; - public abstract drawForReadPixels(_commands: RenderCommands, sceneOverlays: GraphicList, worldOverlayDecorations: GraphicList | undefined, viewOverlayDecorations: GraphicList | undefined): void; + public abstract drawForReadPixels( + _commands: RenderCommands, + sceneOverlays: GraphicList, + worldOverlayDecorations: GraphicList | undefined, + viewOverlayDecorations: GraphicList | undefined, + ): void; public abstract readPixels(rect: ViewRect, selector: Pixel.Selector): Pixel.Buffer | undefined; public abstract readDepthAndOrder(rect: ViewRect): Uint8Array | undefined; public abstract readFeatureIds(rect: ViewRect): Uint8Array | undefined; @@ -822,7 +883,9 @@ export abstract class SceneCompositor implements WebGLDisposable, RenderMemory.C public abstract get depthAndOrder(): TextureHandle; public abstract get antialiasSamples(): number; - public get needHiddenEdges(): boolean { return this._needHiddenEdges; } + public get needHiddenEdges(): boolean { + return this._needHiddenEdges; + } protected constructor(target: Target) { this.target = target; @@ -878,15 +941,27 @@ class Compositor extends SceneCompositor { protected readonly _viewProjectionMatrix = new Matrix4(); protected _primitiveDrawState = PrimitiveDrawState.Both; // used by drawPrimitive to decide whether a primitive needs to be drawn. - public forceBufferChange(): void { this._width = this._height = -1; } - public get featureIds(): TextureHandle { return this.getSamplerTexture(this._readPickDataFromPingPong ? 0 : 1); } - public get depthAndOrder(): TextureHandle { return this.getSamplerTexture(this._readPickDataFromPingPong ? 1 : 2); } - private get _samplerFbo(): FrameBuffer { return this._readPickDataFromPingPong ? this._fbos.pingPong! : this._fbos.opaqueAll!; } - private getSamplerTexture(index: number) { return this._samplerFbo.getColor(index); } + public forceBufferChange(): void { + this._width = this._height = -1; + } + public get featureIds(): TextureHandle { + return this.getSamplerTexture(this._readPickDataFromPingPong ? 0 : 1); + } + public get depthAndOrder(): TextureHandle { + return this.getSamplerTexture(this._readPickDataFromPingPong ? 1 : 2); + } + private get _samplerFbo(): FrameBuffer { + return this._readPickDataFromPingPong ? this._fbos.pingPong! : this._fbos.opaqueAll!; + } + private getSamplerTexture(index: number) { + return this._samplerFbo.getColor(index); + } public drawPrimitive(primitive: Primitive, exec: ShaderProgramExecutor, outputsToPick: boolean) { - if ((outputsToPick && this._primitiveDrawState !== PrimitiveDrawState.NonPickable) || - (!outputsToPick && this._primitiveDrawState !== PrimitiveDrawState.Pickable)) + if ( + (outputsToPick && this._primitiveDrawState !== PrimitiveDrawState.NonPickable) || + (!outputsToPick && this._primitiveDrawState !== PrimitiveDrawState.Pickable) + ) primitive.draw(exec); } @@ -909,7 +984,7 @@ class Compositor extends SceneCompositor { } protected renderLayers(commands: RenderCommands, needComposite: boolean, pass: RenderPass): void { - const fbo = (needComposite ? this._fbos.opaqueAndCompositeAll! : this._fbos.opaqueAll!); + const fbo = needComposite ? this._fbos.opaqueAndCompositeAll! : this._fbos.opaqueAll!; const useMsBuffers = RenderPass.OpaqueLayers === pass && fbo.isMultisampled && this.useMsBuffers; this._readPickDataFromPingPong = !useMsBuffers; System.instance.frameBufferStack.execute(fbo, true, useMsBuffers, () => { @@ -928,7 +1003,7 @@ class Compositor extends SceneCompositor { const fbStack = System.instance.frameBufferStack; // Output the first 2 passes to color and pick data buffers. (All 3 in the case of rendering for readPixels() or ambient occlusion). - let fbo = (needComposite ? this._fbos.opaqueAndCompositeAll! : this._fbos.opaqueAll!); + let fbo = needComposite ? this._fbos.opaqueAndCompositeAll! : this._fbos.opaqueAll!; const useMsBuffers = fbo.isMultisampled && this.useMsBuffers; this._readPickDataFromPingPong = !useMsBuffers; // if multisampling then can read pick textures directly. fbStack.execute(fbo, true, useMsBuffers, () => { @@ -945,7 +1020,7 @@ class Compositor extends SceneCompositor { // The general pass (and following) will not bother to write to pick buffers and so can read from the actual pick buffers. if (!renderForReadPixels) { - fbo = (needComposite ? this._fbos.opaqueAndCompositeColor! : this._fbos.opaqueColor!); + fbo = needComposite ? this._fbos.opaqueAndCompositeColor! : this._fbos.opaqueColor!; fbStack.execute(fbo, true, useMsBuffers, () => { this.drawPass(commands, RenderPass.OpaqueGeneral, false); this.drawPass(commands, RenderPass.HiddenEdge, false); @@ -994,7 +1069,7 @@ class Compositor extends SceneCompositor { // If multisampling then we will use the accumulation texture for featureIDs and a special texture for depthAndOrder since the revealage texture is not the right type for multisampling. // First we will need to copy what's in the pick buffers so far into the hidden pick buffers. System.instance.applyRenderState(this._noDepthMaskRenderState); - fbo = (useMsBuffers ? this._fbos.pingPongMS! : this._fbos.pingPong!); + fbo = useMsBuffers ? this._fbos.pingPongMS! : this._fbos.pingPong!; fbStack.execute(fbo, true, useMsBuffers, () => { const params = getDrawParams(this.target, this._geom.copyPickBuffers!); this.target.techniques.draw(params); @@ -1035,8 +1110,12 @@ class Compositor extends SceneCompositor { ++pushDepth; if (pushDepth === 1) { pcs = cmd.branch.branch.realityModelDisplaySettings?.pointCloud; - this.target.uniforms.realityModel.pointCloud.updateRange(cmd.branch.branch.realityModelRange, - this.target, cmd.branch.localToWorldTransform, is3d); + this.target.uniforms.realityModel.pointCloud.updateRange( + cmd.branch.branch.realityModelRange, + this.target, + cmd.branch.localToWorldTransform, + is3d, + ); pointClouds.push(curPC = { pcs, cmds: [cmd] }); } else { assert(undefined !== curPC); @@ -1051,7 +1130,7 @@ class Compositor extends SceneCompositor { } const needComposite = CompositeFlags.None !== compositeFlags; - const fbo = (needComposite ? this._fbos.opaqueAndCompositeColor! : this._fbos.opaqueColor!); + const fbo = needComposite ? this._fbos.opaqueAndCompositeColor! : this._fbos.opaqueColor!; const useMsBuffers = fbo.isMultisampled && this.useMsBuffers; const system = System.instance; const fbStack = system.frameBufferStack; @@ -1073,12 +1152,19 @@ class Compositor extends SceneCompositor { let drawColBufs; if (undefined !== this._fbos.edlDrawCol) drawColBufs = this._fbos.edlDrawCol.getColorTargets(useMsBuffers, 0); - if (undefined === this._fbos.edlDrawCol || this._textures.hilite !== drawColBufs?.tex || this._textures.hiliteMsBuff !== drawColBufs.msBuf) { + if ( + undefined === this._fbos.edlDrawCol || this._textures.hilite !== drawColBufs?.tex || this._textures.hiliteMsBuff !== drawColBufs.msBuf + ) { this._fbos.edlDrawCol = dispose(this._fbos.edlDrawCol); const filters = [GL.MultiSampling.Filter.Linear]; if (useMsBuffers) - this._fbos.edlDrawCol = FrameBuffer.create([this._textures.hilite], this._depth, - useMsBuffers && this._textures.hiliteMsBuff ? [this._textures.hiliteMsBuff] : undefined, filters, this._depthMS); + this._fbos.edlDrawCol = FrameBuffer.create( + [this._textures.hilite], + this._depth, + useMsBuffers && this._textures.hiliteMsBuff ? [this._textures.hiliteMsBuff] : undefined, + filters, + this._depthMS, + ); else this._fbos.edlDrawCol = FrameBuffer.create([this._textures.hilite], this._depth); } @@ -1096,7 +1182,7 @@ class Compositor extends SceneCompositor { this._fbos.edlDrawCol.blitMsBuffersToTextures(true, 0); // need to read the non-MS depth and hilite buffers // next process buffers to generate EDL (depth buffer is passed during init) - this.target.beginPerfMetricRecord("Calc EDL"); // ### todo keep? (probably) + this.target.beginPerfMetricRecord("Calc EDL"); // ### todo keep? (probably) const sts = this.eyeDomeLighting.draw({ edlMode: pc.pcs?.edlMode === "full" ? EDLMode.Full : EDLMode.On, edlFilter: !!pcs?.edlFilter, @@ -1139,10 +1225,16 @@ class Compositor extends SceneCompositor { } } - protected renderIndexedClassifierForReadPixels(cmds: DrawCommands, state: RenderState, renderForIntersectingVolumes: boolean, needComposite: boolean) { + protected renderIndexedClassifierForReadPixels( + cmds: DrawCommands, + state: RenderState, + renderForIntersectingVolumes: boolean, + needComposite: boolean, + ) { this._readPickDataFromPingPong = true; - const fbo = (renderForIntersectingVolumes ? (needComposite ? this._fbos.idsAndZComposite! : this._fbos.idsAndZ!) - : (needComposite ? this._fbos.idsAndAltZComposite! : this._fbos.idsAndAltZ!)); + const fbo = renderForIntersectingVolumes ? + (needComposite ? this._fbos.idsAndZComposite! : this._fbos.idsAndZ!) + : (needComposite ? this._fbos.idsAndAltZComposite! : this._fbos.idsAndAltZ!); System.instance.frameBufferStack.execute(fbo, true, false, () => { System.instance.applyRenderState(state); this.target.techniques.execute(this.target, cmds, RenderPass.OpaqueGeneral); @@ -1182,11 +1274,21 @@ class Compositor extends SceneCompositor { } } - public get antialiasSamples(): number { return this._antialiasSamples; } + public get antialiasSamples(): number { + return this._antialiasSamples; + } - protected get useMsBuffers(): boolean { return this._antialiasSamples > 1 && !this.target.isReadPixelsInProgress; } + protected get useMsBuffers(): boolean { + return this._antialiasSamples > 1 && !this.target.isReadPixelsInProgress; + } - protected enableVolumeClassifierFbos(textures: Textures, depth: DepthBuffer, volClassDepth: DepthBuffer | undefined, depthMS?: DepthBuffer, volClassDepthMS?: DepthBuffer): void { + protected enableVolumeClassifierFbos( + textures: Textures, + depth: DepthBuffer, + volClassDepth: DepthBuffer | undefined, + depthMS?: DepthBuffer, + volClassDepthMS?: DepthBuffer, + ): void { this._fbos.enableVolumeClassifier(textures, depth, volClassDepth, depthMS, volClassDepthMS); } @@ -1240,7 +1342,12 @@ class Compositor extends SceneCompositor { this._translucentRenderState.flags.depthMask = false; this._translucentRenderState.flags.blend = this._translucentRenderState.flags.depthTest = true; - this._translucentRenderState.blend.setBlendFuncSeparate(GL.BlendFactor.One, GL.BlendFactor.Zero, GL.BlendFactor.One, GL.BlendFactor.OneMinusSrcAlpha); + this._translucentRenderState.blend.setBlendFuncSeparate( + GL.BlendFactor.One, + GL.BlendFactor.Zero, + GL.BlendFactor.One, + GL.BlendFactor.OneMinusSrcAlpha, + ); this._hiliteRenderState.flags.depthMask = false; this._hiliteRenderState.flags.blend = true; @@ -1274,12 +1381,12 @@ class Compositor extends SceneCompositor { const width = rect.width; const height = rect.height; const includeOcclusion = this.target.wantAmbientOcclusion; - const wantVolumeClassifier = (undefined !== this.target.activeVolumeClassifierProps); + const wantVolumeClassifier = undefined !== this.target.activeVolumeClassifierProps; let wantAntialiasSamples = this.target.antialiasSamples <= 1 ? 1 : this.target.antialiasSamples; if (wantAntialiasSamples > System.instance.maxAntialiasSamples) wantAntialiasSamples = System.instance.maxAntialiasSamples; - const changeAntialiasSamples = (this._antialiasSamples > 1 && wantAntialiasSamples > 1 && this._antialiasSamples !== wantAntialiasSamples); + const changeAntialiasSamples = this._antialiasSamples > 1 && wantAntialiasSamples > 1 && this._antialiasSamples !== wantAntialiasSamples; // If not yet initialized, or dimensions changed, or antialiasing changed the number of samples, initialize. if (undefined === this._textures.accumulation || width !== this._width || height !== this._height || changeAntialiasSamples) { @@ -1493,9 +1600,16 @@ class Compositor extends SceneCompositor { this.target.popViewClip(); } - public get fullHeight(): number { return this.target.viewRect.height; } + public get fullHeight(): number { + return this.target.viewRect.height; + } - public drawForReadPixels(commands: RenderCommands, sceneOverlays: GraphicList, worldOverlayDecorations: GraphicList | undefined, viewOverlayDecorations: GraphicList | undefined): void { + public drawForReadPixels( + commands: RenderCommands, + sceneOverlays: GraphicList, + worldOverlayDecorations: GraphicList | undefined, + viewOverlayDecorations: GraphicList | undefined, + ): void { this.target.beginPerfMetricRecord("Render Background", true); if (!this.preDraw()) { this.target.endPerfMetricRecord(true); // End Render Background record if returning @@ -1583,7 +1697,9 @@ class Compositor extends SceneCompositor { return PixelBuffer.create(rect, selector, this); } - public readDepthAndOrder(rect: ViewRect): Uint8Array | undefined { return this.readFrameBuffer(rect, this._fbos.depthAndOrder); } + public readDepthAndOrder(rect: ViewRect): Uint8Array | undefined { + return this.readFrameBuffer(rect, this._fbos.depthAndOrder); + } public readFeatureIds(rect: ViewRect): Uint8Array | undefined { const tex = this._textures.featureId; @@ -1835,7 +1951,12 @@ class Compositor extends SceneCompositor { this._vcBlendRenderState.flags.colorWrite = true; this._vcBlendRenderState.flags.stencilTest = false; this._vcBlendRenderState.flags.blend = true; - this._vcBlendRenderState.blend.setBlendFuncSeparate(GL.BlendFactor.SrcAlpha, GL.BlendFactor.Zero, GL.BlendFactor.OneMinusSrcAlpha, GL.BlendFactor.One); + this._vcBlendRenderState.blend.setBlendFuncSeparate( + GL.BlendFactor.SrcAlpha, + GL.BlendFactor.Zero, + GL.BlendFactor.OneMinusSrcAlpha, + GL.BlendFactor.One, + ); if (this._debugStencil > 0) { this._vcDebugRenderState = new RenderState(); @@ -1968,7 +2089,7 @@ class Compositor extends SceneCompositor { this.target.pushState(this.target.decorationsState); System.instance.applyRenderState(this._vcCopyZRenderState!); - this.target.techniques.draw(getDrawParams(this.target, this._geom.volClassCopyZ!)); // This method uses the EXT_frag_depth extension + this.target.techniques.draw(getDrawParams(this.target, this._geom.volClassCopyZ!)); // This method uses the EXT_frag_depth extension System.instance.bindTexture2d(TextureUnit.Zero, undefined); this.target.popBranch(); @@ -2082,7 +2203,12 @@ class Compositor extends SceneCompositor { fbStack.execute(volClassBlendFbo, true, this.useMsBuffers, () => { this.target.pushState(this._vcBranchState!); this._vcColorRenderState!.blend.color = [1.0, 1.0, 1.0, 0.35]; - this._vcColorRenderState!.blend.setBlendFuncSeparate(GL.BlendFactor.One, GL.BlendFactor.ConstAlpha, GL.BlendFactor.Zero, GL.BlendFactor.Zero); + this._vcColorRenderState!.blend.setBlendFuncSeparate( + GL.BlendFactor.One, + GL.BlendFactor.ConstAlpha, + GL.BlendFactor.Zero, + GL.BlendFactor.Zero, + ); this._vcColorRenderState!.flags.cull = true; System.instance.applyRenderState(this._vcColorRenderState!); this.target.activeVolumeClassifierTexture = undefined; // make sure this texture is undefined so we do not use the planar classification shader @@ -2102,7 +2228,12 @@ class Compositor extends SceneCompositor { // Since we need the blend texture to have alpha in it, we will use blending just to modify the alpha that gets written. this.target.pushState(this._vcBranchState!); this._vcColorRenderState!.blend.color = [1.0, 1.0, 1.0, 0.35]; - this._vcColorRenderState!.blend.setBlendFuncSeparate(GL.BlendFactor.One, GL.BlendFactor.ConstAlpha, GL.BlendFactor.Zero, GL.BlendFactor.Zero); + this._vcColorRenderState!.blend.setBlendFuncSeparate( + GL.BlendFactor.One, + GL.BlendFactor.ConstAlpha, + GL.BlendFactor.Zero, + GL.BlendFactor.Zero, + ); this._vcColorRenderState!.flags.depthTest = true; this._vcColorRenderState!.flags.depthMask = true; this._vcColorRenderState!.flags.cull = true; @@ -2170,7 +2301,12 @@ class Compositor extends SceneCompositor { fbStack.execute(fboColorAndZ, false, this.useMsBuffers, () => { this.target.pushState(this.target.decorationsState); - this._vcBlendRenderState!.blend.setBlendFuncSeparate(GL.BlendFactor.SrcAlpha, GL.BlendFactor.Zero, GL.BlendFactor.OneMinusSrcAlpha, GL.BlendFactor.One); + this._vcBlendRenderState!.blend.setBlendFuncSeparate( + GL.BlendFactor.SrcAlpha, + GL.BlendFactor.Zero, + GL.BlendFactor.OneMinusSrcAlpha, + GL.BlendFactor.One, + ); System.instance.applyRenderState(this._vcBlendRenderState!); const params = getDrawParams(this.target, this._geom.volClassBlend!); this.target.techniques.draw(params); diff --git a/core/frontend/src/render/webgl/ScreenSpaceEffect.ts b/core/frontend/src/render/webgl/ScreenSpaceEffect.ts index adeee3a6be54..ece9e058aece 100644 --- a/core/frontend/src/render/webgl/ScreenSpaceEffect.ts +++ b/core/frontend/src/render/webgl/ScreenSpaceEffect.ts @@ -8,39 +8,55 @@ import { assert, dispose } from "@itwin/core-bentley"; import { - ScreenSpaceEffectBuilder, ScreenSpaceEffectBuilderParams, ScreenSpaceEffectContext, UniformArrayParams, UniformParams, UniformType, VaryingType, + ScreenSpaceEffectBuilder, + ScreenSpaceEffectBuilderParams, + ScreenSpaceEffectContext, + UniformArrayParams, + UniformParams, + UniformType, + VaryingType, } from "../ScreenSpaceEffectBuilder"; -import { TechniqueId } from "./TechniqueId"; -import { ProgramBuilder, VariableType } from "./ShaderBuilder"; -import { CompileStatus, ShaderProgram } from "./ShaderProgram"; -import { RenderState } from "./RenderState"; import { SingleTexturedViewportQuadGeometry, ViewportQuadGeometry } from "./CachedGeometry"; import { FrameBuffer } from "./FrameBuffer"; +import { createScreenSpaceEffectProgramBuilder } from "./glsl/ScreenSpaceEffect"; +import { RenderState } from "./RenderState"; import { getDrawParams } from "./ScratchDrawParams"; -import { SingularTechnique } from "./Technique"; -import { Target } from "./Target"; +import { ProgramBuilder, VariableType } from "./ShaderBuilder"; +import { CompileStatus, ShaderProgram } from "./ShaderProgram"; import { System } from "./System"; -import { createScreenSpaceEffectProgramBuilder } from "./glsl/ScreenSpaceEffect"; +import { Target } from "./Target"; +import { SingularTechnique } from "./Technique"; +import { TechniqueId } from "./TechniqueId"; type ShouldApply = (context: ScreenSpaceEffectContext) => boolean; function getUniformVariableType(type: UniformType): VariableType { switch (type) { - case UniformType.Bool: return VariableType.Boolean; - case UniformType.Int: return VariableType.Int; - case UniformType.Float: return VariableType.Float; - case UniformType.Vec2: return VariableType.Vec2; - case UniformType.Vec3: return VariableType.Vec3; - case UniformType.Vec4: return VariableType.Vec4; + case UniformType.Bool: + return VariableType.Boolean; + case UniformType.Int: + return VariableType.Int; + case UniformType.Float: + return VariableType.Float; + case UniformType.Vec2: + return VariableType.Vec2; + case UniformType.Vec3: + return VariableType.Vec3; + case UniformType.Vec4: + return VariableType.Vec4; } } function getVaryingVariableType(type: VaryingType): VariableType { switch (type) { - case VaryingType.Float: return VariableType.Float; - case VaryingType.Vec2: return VariableType.Vec2; - case VaryingType.Vec3: return VariableType.Vec3; - case VaryingType.Vec4: return VariableType.Vec4; + case VaryingType.Float: + return VariableType.Float; + case VaryingType.Vec2: + return VariableType.Vec2; + case VaryingType.Vec3: + return VariableType.Vec3; + case VaryingType.Vec4: + return VariableType.Vec4; } } diff --git a/core/frontend/src/render/webgl/ShaderBuilder.ts b/core/frontend/src/render/webgl/ShaderBuilder.ts index 14ad4e7be9b6..3203482c8587 100644 --- a/core/frontend/src/render/webgl/ShaderBuilder.ts +++ b/core/frontend/src/render/webgl/ShaderBuilder.ts @@ -63,18 +63,30 @@ export const enum VariablePrecision { namespace Convert { export function typeToString(type: VariableType): string { switch (type) { - case VariableType.Boolean: return "bool"; - case VariableType.Int: return "int"; - case VariableType.Float: return "float"; - case VariableType.Vec2: return "vec2"; - case VariableType.Vec3: return "vec3"; - case VariableType.Vec4: return "vec4"; - case VariableType.Mat3: return "mat3"; - case VariableType.Mat4: return "mat4"; - case VariableType.Sampler2D: return "sampler2D"; - case VariableType.SamplerCube: return "samplerCube"; - case VariableType.Uint: return "uint"; - case VariableType.BVec2: return "bvec2"; + case VariableType.Boolean: + return "bool"; + case VariableType.Int: + return "int"; + case VariableType.Float: + return "float"; + case VariableType.Vec2: + return "vec2"; + case VariableType.Vec3: + return "vec3"; + case VariableType.Vec4: + return "vec4"; + case VariableType.Mat3: + return "mat3"; + case VariableType.Mat4: + return "mat4"; + case VariableType.Sampler2D: + return "sampler2D"; + case VariableType.SamplerCube: + return "samplerCube"; + case VariableType.Uint: + return "uint"; + case VariableType.BVec2: + return "bvec2"; default: assert(false); return "undefined"; @@ -83,9 +95,12 @@ namespace Convert { export function scopeToString(scope: VariableScope, isVertexShader: boolean): string { switch (scope) { - case VariableScope.Global: return ""; - case VariableScope.Varying: return (isVertexShader ? "out" : "in"); - case VariableScope.Uniform: return "uniform"; + case VariableScope.Global: + return ""; + case VariableScope.Varying: + return (isVertexShader ? "out" : "in"); + case VariableScope.Uniform: + return "uniform"; default: assert(false); return "undefined"; @@ -94,10 +109,14 @@ namespace Convert { export function precisionToString(precision: VariablePrecision): string { switch (precision) { - case VariablePrecision.Default: return ""; - case VariablePrecision.Low: return "lowp"; - case VariablePrecision.Medium: return "mediump"; - case VariablePrecision.High: return "highp"; + case VariablePrecision.Default: + return ""; + case VariablePrecision.Low: + return "lowp"; + case VariablePrecision.Medium: + return "mediump"; + case VariablePrecision.High: + return "highp"; default: assert(false); return "undefined"; @@ -126,7 +145,16 @@ export class ShaderVariable { public readonly isConst: boolean = false; // for global variables only public readonly length: number; // for uniform arrays only - private constructor(name: string, type: VariableType, scope: VariableScope, precision: VariablePrecision, isConst: boolean, addBinding?: AddVariableBinding, value?: string, length: number = 0) { + private constructor( + name: string, + type: VariableType, + scope: VariableScope, + precision: VariablePrecision, + isConst: boolean, + addBinding?: AddVariableBinding, + value?: string, + length: number = 0, + ) { this._addBinding = addBinding; this.name = name; this.value = value; @@ -137,11 +165,24 @@ export class ShaderVariable { this.length = length; } - public static create(name: string, type: VariableType, scope: VariableScope, addBinding?: AddVariableBinding, precision: VariablePrecision = VariablePrecision.Default): ShaderVariable { + public static create( + name: string, + type: VariableType, + scope: VariableScope, + addBinding?: AddVariableBinding, + precision: VariablePrecision = VariablePrecision.Default, + ): ShaderVariable { return new ShaderVariable(name, type, scope, precision, false, addBinding, undefined); } - public static createArray(name: string, type: VariableType, length: number, scope: VariableScope, addBinding?: AddVariableBinding, precision: VariablePrecision = VariablePrecision.Default): ShaderVariable { + public static createArray( + name: string, + type: VariableType, + length: number, + scope: VariableScope, + addBinding?: AddVariableBinding, + precision: VariablePrecision = VariablePrecision.Default, + ): ShaderVariable { return new ShaderVariable(name, type, scope, precision, false, addBinding, undefined, length); } @@ -149,15 +190,23 @@ export class ShaderVariable { return new ShaderVariable(name, type, VariableScope.Global, VariablePrecision.Default, isConst, undefined, value); } - public get hasBinding(): boolean { return undefined !== this._addBinding; } + public get hasBinding(): boolean { + return undefined !== this._addBinding; + } public addBinding(prog: ShaderProgram) { if (undefined !== this._addBinding) this._addBinding(prog); } - public get typeName(): string { return Convert.typeToString(this.type); } - public getScopeName(isVertexShader: boolean): string { return Convert.scopeToString(this.scope, isVertexShader); } - public get precisionName(): string { return Convert.precisionToString(this.precision); } + public get typeName(): string { + return Convert.typeToString(this.type); + } + public getScopeName(isVertexShader: boolean): string { + return Convert.scopeToString(this.scope, isVertexShader); + } + public get precisionName(): string { + return Convert.precisionToString(this.precision); + } /** Constructs the single-line declaration of this variable */ public buildDeclaration(isVertexShader: boolean): string { @@ -198,7 +247,9 @@ export class ShaderVariables { protected _list: ShaderVariable[] = new Array(); /** Find an existing variable with the specified name */ - public find(name: string): ShaderVariable | undefined { return this._list.find((v: ShaderVariable) => v.name === name); } + public find(name: string): ShaderVariable | undefined { + return this._list.find((v: ShaderVariable) => v.name === name); + } /** Add a new variable, if a variable with the same name does not already exist. return true if added */ public addVariable(v: ShaderVariable): boolean { @@ -278,7 +329,9 @@ export class ShaderVariables { } } - public get length(): number { return this._list.length; } + public get length(): number { + return this._list.length; + } private findSlot(variableSize: number, loopSize: number, registers: number[]): number { // Find the first available slot into which to insert this variable @@ -351,7 +404,7 @@ export class ShaderVariables { outStr += `// Slots used: ${slotsUsed} [${registers.toString()}]\n`; // debug output modes - const outputAll = true; // false just outputs varyings that use more than 8 + const outputAll = true; // false just outputs varyings that use more than 8 if (outputAll) { return outStr; } else { @@ -430,10 +483,14 @@ export class SourceBuilder { public source: string = ""; /* Append the specified string to the glsl source */ - public add(what: string): void { this.source += what; } + public add(what: string): void { + this.source += what; + } /* Append a new-line to the glsl source */ - public newline(): void { this.add("\n"); } + public newline(): void { + this.add("\n"); + } /* Append the specified string to the glsl source, followed by a new-line */ public addline(what: string): void { @@ -462,10 +519,14 @@ export class SourceBuilder { } /** Constructs a function definition as described by buildFunctionDefinition() and appends it to the glsl source. */ - public addFunction(declaration: string, implementation: string): void { this.add(SourceBuilder.buildFunctionDefinition(declaration, implementation)); } + public addFunction(declaration: string, implementation: string): void { + this.add(SourceBuilder.buildFunctionDefinition(declaration, implementation)); + } /** Constructs the definition of the main() function using the supplied function body and appends it to the glsl source. */ - public addMain(implementation: string): void { this.addFunction("void main()", implementation); } + public addMain(implementation: string): void { + this.addFunction("void main()", implementation); + } } /** @internal */ @@ -707,7 +768,9 @@ export const enum VertexShaderComponent { export class VertexShaderBuilder extends ShaderBuilder { private _computedVarying: string[] = new Array(); - private buildPrelude(attrMap?: Map): SourceBuilder { return this.buildPreludeCommon(attrMap, true); } + private buildPrelude(attrMap?: Map): SourceBuilder { + return this.buildPreludeCommon(attrMap, true); + } public constructor(flags: ShaderBuilderFlags = {}) { super(VertexShaderComponent.COUNT, flags); @@ -734,9 +797,15 @@ export class VertexShaderBuilder extends ShaderBuilder { return this._flags.positionType; } - public get(id: VertexShaderComponent): string | undefined { return this.getComponent(id); } - public set(id: VertexShaderComponent, component: string) { this.addComponent(id, component); } - public unset(id: VertexShaderComponent) { this.removeComponent(id); } + public get(id: VertexShaderComponent): string | undefined { + return this.getComponent(id); + } + public set(id: VertexShaderComponent, component: string) { + this.addComponent(id, component); + } + public unset(id: VertexShaderComponent) { + this.removeComponent(id); + } public addComputedVarying(name: string, type: VariableType, computation: string): void { this.addVarying(name, type); @@ -949,9 +1018,15 @@ export class FragmentShaderBuilder extends ShaderBuilder { this.addFragOutput("FragColor", -1); } - public get(id: FragmentShaderComponent): string | undefined { return this.getComponent(id); } - public set(id: FragmentShaderComponent, component: string) { this.addComponent(id, component); } - public unset(id: FragmentShaderComponent) { this.removeComponent(id); } + public get(id: FragmentShaderComponent): string | undefined { + return this.getComponent(id); + } + public set(id: FragmentShaderComponent, component: string) { + this.addComponent(id, component); + } + public unset(id: FragmentShaderComponent) { + this.removeComponent(id); + } public addDrawBuffersExtension(n: number): void { this.clearFragOutput(); @@ -1243,8 +1318,8 @@ export class ProgramBuilder { } public setDebugDescription(description: string): void { - this.vert.headerComment = (`//!V! ${description}`); - this.frag.headerComment = (`//!F! ${description}`); + this.vert.headerComment = `//!V! ${description}`; + this.frag.headerComment = `//!F! ${description}`; } /** Returns a deep copy of this program builder. */ diff --git a/core/frontend/src/render/webgl/ShaderProgram.ts b/core/frontend/src/render/webgl/ShaderProgram.ts index 42b199b6fef7..7d4f54d60f79 100644 --- a/core/frontend/src/render/webgl/ShaderProgram.ts +++ b/core/frontend/src/render/webgl/ShaderProgram.ts @@ -13,11 +13,11 @@ import { WebGLDisposable } from "./Disposable"; import { DrawParams, ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; import { Batch, Branch } from "./Graphic"; -import { UniformHandle } from "./UniformHandle"; import { RenderPass } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueFlags } from "./TechniqueFlags"; +import { UniformHandle } from "./UniformHandle"; /* eslint-disable no-restricted-syntax */ @@ -40,7 +40,9 @@ export class Uniform { private readonly _name: string; protected _handle?: UniformHandle; - protected constructor(name: string) { this._name = name; } + protected constructor(name: string) { + this._name = name; + } public compile(prog: ShaderProgram): boolean { assert(!this.isValid); @@ -51,7 +53,9 @@ export class Uniform { return this.isValid; } - public get isValid(): boolean { return undefined !== this._handle; } + public get isValid(): boolean { + return undefined !== this._handle; + } } /** @@ -113,8 +117,8 @@ export class GraphicUniform extends Uniform { * @internal */ export const enum CompileStatus { - Success, // The program was successfully compiled. - Failure, // The program failed to compile. + Success, // The program was successfully compiled. + Failure, // The program failed to compile. Uncompiled, // No attempt has yet been made to compile the program. } @@ -137,7 +141,14 @@ export class ShaderProgram implements WebGLDisposable { private _fragHNdx: number = -1; public readonly outputsToPick; - public constructor(gl: WebGL2RenderingContext, vertSource: string, fragSource: string, attrMap: Map | undefined, description: string, fragDescription: string) { + public constructor( + gl: WebGL2RenderingContext, + vertSource: string, + fragSource: string, + attrMap: Map | undefined, + description: string, + fragDescription: string, + ) { this.description = description; this.outputsToPick = description.includes("Overrides") || description.includes("Pick"); this._fragDescription = fragDescription; @@ -149,7 +160,9 @@ export class ShaderProgram implements WebGLDisposable { this._glProgram = (null === glProgram) ? undefined : glProgram; } - public get isDisposed(): boolean { return this._glProgram === undefined; } + public get isDisposed(): boolean { + return this._glProgram === undefined; + } public dispose(): void { if (!this.isDisposed) { @@ -160,9 +173,15 @@ export class ShaderProgram implements WebGLDisposable { } } - public get glProgram(): WebGLProgram | undefined { return this._glProgram; } - public get isUncompiled() { return CompileStatus.Uncompiled === this._status; } - public get isCompiled() { return CompileStatus.Success === this._status; } + public get glProgram(): WebGLProgram | undefined { + return this._glProgram; + } + public get isUncompiled() { + return CompileStatus.Uncompiled === this._status; + } + public get isCompiled() { + return CompileStatus.Success === this._status; + } private compileShader(type: GL.ShaderType): WebGLShader | undefined { const gl = System.instance.context; @@ -176,7 +195,9 @@ export class ShaderProgram implements WebGLDisposable { gl.compileShader(shader); const succeeded = gl.getShaderParameter(shader, GL.ShaderParameter.CompileStatus) as boolean; if (!succeeded) { - const compileLog = `${GL.ShaderType.Vertex === type ? "Vertex" : "Fragment"} shader failed to compile. Errors: ${gl.getShaderInfoLog(shader)} Program description: ${this.description}`; + const compileLog = `${GL.ShaderType.Vertex === type ? "Vertex" : "Fragment"} shader failed to compile. Errors: ${ + gl.getShaderInfoLog(shader) + } Program description: ${this.description}`; throw new Error(compileLog); } @@ -251,8 +272,10 @@ export class ShaderProgram implements WebGLDisposable { this.setDebugShaderUsage(); switch (this._status) { - case CompileStatus.Failure: return CompileStatus.Failure; - case CompileStatus.Success: return CompileStatus.Success; + case CompileStatus.Failure: + return CompileStatus.Failure; + case CompileStatus.Success: + return CompileStatus.Success; default: { if (this.isDisposed) { this._status = CompileStatus.Failure; @@ -266,9 +289,10 @@ export class ShaderProgram implements WebGLDisposable { const vert = this.compileShader(GL.ShaderType.Vertex); const frag = this.compileShader(GL.ShaderType.Fragment); - if (undefined !== vert && undefined !== frag) + if (undefined !== vert && undefined !== frag) { if (this.linkProgram(vert, frag) && this.compileUniforms(this._programUniforms) && this.compileUniforms(this._graphicUniforms)) this._status = CompileStatus.Success; + } if (System.instance.options.debugShaders && forUse && this._status === CompileStatus.Success) this.setDebugShaderUsage(); @@ -670,7 +694,9 @@ export class ShaderProgramExecutor { } private _isDisposed = false; - public get isDisposed(): boolean { return this._isDisposed; } + public get isDisposed(): boolean { + return this._isDisposed; + } /** Clears the current program to be executed. This does not free WebGL resources, since those are owned by Techniques. */ public dispose() { @@ -679,10 +705,18 @@ export class ShaderProgramExecutor { this._isDisposed = true; } - public setProgram(program: ShaderProgram): boolean { return this.changeProgram(program); } - public get isValid() { return undefined !== this._program; } - public get target() { return this.params.target; } - public get renderPass() { return this.params.renderPass; } + public setProgram(program: ShaderProgram): boolean { + return this.changeProgram(program); + } + public get isValid() { + return undefined !== this._program; + } + public get target() { + return this.params.target; + } + public get renderPass() { + return this.params.renderPass; + } public get params() { if (undefined === ShaderProgramExecutor._params) ShaderProgramExecutor._params = new ShaderProgramParams(); @@ -706,10 +740,18 @@ export class ShaderProgramExecutor { } } - public pushBranch(branch: Branch): void { this.target.pushBranch(branch); } - public popBranch(): void { this.target.popBranch(); } - public pushBatch(batch: Batch): void { this.target.pushBatch(batch); } - public popBatch(): void { this.target.popBatch(); } + public pushBranch(branch: Branch): void { + this.target.pushBranch(branch); + } + public popBranch(): void { + this.target.popBranch(); + } + public pushBatch(batch: Batch): void { + this.target.pushBatch(batch); + } + public popBatch(): void { + this.target.popBatch(); + } private changeProgram(program?: ShaderProgram): boolean { if (this._program === program) { diff --git a/core/frontend/src/render/webgl/ShadowUniforms.ts b/core/frontend/src/render/webgl/ShadowUniforms.ts index 19df7e19f88d..10d4888a19f6 100644 --- a/core/frontend/src/render/webgl/ShadowUniforms.ts +++ b/core/frontend/src/render/webgl/ShadowUniforms.ts @@ -6,13 +6,13 @@ * @module WebGL */ -import { Matrix4d } from "@itwin/core-geometry"; import { ColorDef, RgbColor } from "@itwin/core-common"; +import { Matrix4d } from "@itwin/core-geometry"; import { FloatRgba } from "./FloatRGBA"; -import { UniformHandle } from "./UniformHandle"; import { Matrix4 } from "./Matrix"; import { desync, sync, SyncToken } from "./Sync"; import { Target } from "./Target"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state of uniforms used for applying shadows. * @internal diff --git a/core/frontend/src/render/webgl/SolarShadowMap.ts b/core/frontend/src/render/webgl/SolarShadowMap.ts index 6ff9b612cf04..f9de9293b6ff 100644 --- a/core/frontend/src/render/webgl/SolarShadowMap.ts +++ b/core/frontend/src/render/webgl/SolarShadowMap.ts @@ -8,17 +8,27 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { ClipUtilities, ConvexClipPlaneSet, Geometry, GrowableXYZArray, Map4d, Matrix3d, Matrix4d, Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { Frustum, FrustumPlanes, RenderMode, RenderTexture, SolarShadowSettings, TextureTransparency, ViewFlags } from "@itwin/core-common"; import { - Frustum, FrustumPlanes, RenderMode, RenderTexture, SolarShadowSettings, TextureTransparency, ViewFlags, -} from "@itwin/core-common"; + ClipUtilities, + ConvexClipPlaneSet, + Geometry, + GrowableXYZArray, + Map4d, + Matrix3d, + Matrix4d, + Point3d, + Range3d, + Transform, + Vector3d, +} from "@itwin/core-geometry"; import { RenderType } from "@itwin/webgl-compatibility"; import { Tile, TileDrawArgs, TileTreeReference, TileVisibility } from "../../tile/internal"; import { SceneContext } from "../../ViewContext"; import { RenderGraphic } from "../RenderGraphic"; import { RenderMemory } from "../RenderMemory"; -import { BranchStack } from "./BranchStack"; import { BatchState } from "./BatchState"; +import { BranchStack } from "./BranchStack"; import { EVSMGeometry } from "./CachedGeometry"; import { WebGLDisposable } from "./Disposable"; import { FrameBuffer } from "./FrameBuffer"; @@ -33,7 +43,13 @@ import { Texture, TextureHandle } from "./Texture"; type ProcessTiles = (tiles: Tile[]) => void; -function createDrawArgs(sceneContext: SceneContext, solarShadowMap: SolarShadowMap, tree: TileTreeReference, frustumPlanes: FrustumPlanes, processTiles: ProcessTiles): TileDrawArgs | undefined { +function createDrawArgs( + sceneContext: SceneContext, + solarShadowMap: SolarShadowMap, + tree: TileTreeReference, + frustumPlanes: FrustumPlanes, + processTiles: ProcessTiles, +): TileDrawArgs | undefined { class SolarShadowMapDrawArgs extends TileDrawArgs { private _useViewportMap?: boolean; private readonly _processTiles: ProcessTiles; @@ -45,7 +61,9 @@ function createDrawArgs(sceneContext: SceneContext, solarShadowMap: SolarShadowM // The solar shadow projection is parallel - which can cause excessive tile selection if it is along an axis of an unbounded tile // tree such as the OSM buildings. Rev limit the selection here. - public override get maxRealityTreeSelectionCount(): undefined | number { return 500; } + public override get maxRealityTreeSelectionCount(): undefined | number { + return 500; + } public override processSelectedTiles(tiles: Tile[]): void { this._processTiles(tiles); @@ -87,7 +105,13 @@ function createDrawArgs(sceneContext: SceneContext, solarShadowMap: SolarShadowM return size; } - public static create(context: SceneContext, shadowMap: SolarShadowMap, tileTree: TileTreeReference, planes: FrustumPlanes, process: ProcessTiles) { + public static create( + context: SceneContext, + shadowMap: SolarShadowMap, + tileTree: TileTreeReference, + planes: FrustumPlanes, + process: ProcessTiles, + ) { const args = tileTree.createDrawArgs(context); return undefined !== args ? new SolarShadowMapDrawArgs(planes, shadowMap, args, process) : undefined; } @@ -96,11 +120,28 @@ function createDrawArgs(sceneContext: SceneContext, solarShadowMap: SolarShadowM return SolarShadowMapDrawArgs.create(sceneContext, solarShadowMap, tree, frustumPlanes, processTiles); } -const shadowMapWidth = 4096; // size of original depth buffer map +const shadowMapWidth = 4096; // size of original depth buffer map const shadowMapHeight = shadowMapWidth; // TBD - Adjust for aspect ratio. -const evsmWidth = shadowMapWidth / 2; // EVSM buffer is 1/2 size each direction +const evsmWidth = shadowMapWidth / 2; // EVSM buffer is 1/2 size each direction const evsmHeight = shadowMapHeight / 2; -const postProjectionMatrixNpc = Matrix4d.createRowValues(/* Row 1 */ 0, 1, 0, 0, /* Row 2 */ 0, 0, 1, 0, /* Row 3 */ 1, 0, 0, 0, /* Row 4 */ 0, 0, 0, 1); +const postProjectionMatrixNpc = Matrix4d.createRowValues( + /* Row 1 */ 0, + 1, + 0, + 0, + /* Row 2 */ 0, + 0, + 1, + 0, + /* Row 3 */ 1, + 0, + 0, + 0, + /* Row 4 */ 0, + 0, + 0, + 1, +); // Bundles up the disposable, create-once-and-reuse members of a SolarShadowMap. class Bundle implements WebGLDisposable { @@ -110,7 +151,8 @@ class Bundle implements WebGLDisposable { public readonly fbo: FrameBuffer, public readonly fboSM: FrameBuffer, public readonly evsmGeom: EVSMGeometry, - public readonly renderCommands: RenderCommands) { + public readonly renderCommands: RenderCommands, + ) { } public static create(target: Target, stack: BranchStack, batch: BatchState): Bundle | undefined { @@ -145,12 +187,22 @@ class Bundle implements WebGLDisposable { if (undefined === fboSM) return undefined; - const depthTexture = new Texture({ ownership: "external", type: RenderTexture.Type.TileSection, handle: depthTextureHandle, transparency: TextureTransparency.Opaque }); + const depthTexture = new Texture({ + ownership: "external", + type: RenderTexture.Type.TileSection, + handle: depthTextureHandle, + transparency: TextureTransparency.Opaque, + }); const evsmGeom = EVSMGeometry.createGeometry(depthTexture.texture.getHandle()!, shadowMapWidth, shadowMapHeight); if (undefined === evsmGeom) return undefined; - const shadowMapTexture = new Texture({ type: RenderTexture.Type.Normal, ownership: "external", handle: shadowMapTextureHandle, transparency: TextureTransparency.Opaque }); + const shadowMapTexture = new Texture({ + type: RenderTexture.Type.Normal, + ownership: "external", + handle: shadowMapTextureHandle, + transparency: TextureTransparency.Opaque, + }); const renderCommands = new RenderCommands(target, stack, batch); return new Bundle(depthTexture, shadowMapTexture, fbo, fboSM, evsmGeom, renderCommands); } @@ -226,17 +278,39 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { return this._bundle; } - public get isReady() { return this._isReady; } - public get isDrawing() { return this._isDrawing; } - public get isEnabled() { return this._enabled; } - public get projectionMatrix(): Matrix4d { return this._projectionMatrix; } - public get depthTexture(): Texture | undefined { return undefined !== this._bundle ? this._bundle.depthTexture : undefined; } - public get shadowMapTexture(): Texture | undefined { return undefined !== this._bundle ? this._bundle.shadowMapTexture : undefined; } - public get settings(): SolarShadowSettings | undefined { return undefined !== this._params ? this._params.settings : undefined; } - public get direction(): Vector3d | undefined { return undefined !== this._params ? this._params.direction : undefined; } - public get frustum(): Frustum { return this._shadowFrustum; } - public get worldToViewMap(): Map4d { return this._worldToViewMap; } - public addGraphic(graphic: RenderGraphic) { this._graphics.push(graphic); } + public get isReady() { + return this._isReady; + } + public get isDrawing() { + return this._isDrawing; + } + public get isEnabled() { + return this._enabled; + } + public get projectionMatrix(): Matrix4d { + return this._projectionMatrix; + } + public get depthTexture(): Texture | undefined { + return undefined !== this._bundle ? this._bundle.depthTexture : undefined; + } + public get shadowMapTexture(): Texture | undefined { + return undefined !== this._bundle ? this._bundle.shadowMapTexture : undefined; + } + public get settings(): SolarShadowSettings | undefined { + return undefined !== this._params ? this._params.settings : undefined; + } + public get direction(): Vector3d | undefined { + return undefined !== this._params ? this._params.direction : undefined; + } + public get frustum(): Frustum { + return this._shadowFrustum; + } + public get worldToViewMap(): Map4d { + return this._worldToViewMap; + } + public addGraphic(graphic: RenderGraphic) { + this._graphics.push(graphic); + } public constructor(target: Target) { this._target = target; @@ -264,7 +338,9 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { stats.addShadowMap(bundle.depthTexture.bytesUsed + bundle.shadowMapTexture.bytesUsed); } - public get isDisposed(): boolean { return undefined === this._bundle && 0 === this._graphics.length; } + public get isDisposed(): boolean { + return undefined === this._bundle && 0 === this._graphics.length; + } public dispose() { this._bundle = dispose(this._bundle); @@ -346,7 +422,7 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { // Expand shadow range to include both the shadowers and shadowed portion of background map. scratchFrustum.initFromRange(shadowRange); - mapToWorld.multiplyPoint3dArrayQuietNormalize(scratchFrustum.points); // This frustum represents the shadowing geometry. Intersect it with background geometry and expand the range depth to include that intersection. + mapToWorld.multiplyPoint3dArrayQuietNormalize(scratchFrustum.points); // This frustum represents the shadowing geometry. Intersect it with background geometry and expand the range depth to include that intersection. const backgroundMapGeometry = context.viewport.view.displayStyle.getBackgroundMapGeometry(); if (undefined !== backgroundMapGeometry) { const backgroundDepthRange = backgroundMapGeometry.getFrustumIntersectionDepthRange(this._shadowFrustum, iModel.projectExtents); @@ -367,14 +443,14 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { this.notifyGraphicsChanged(); return; } - viewIntersectShadowRange.high.z = shadowRange.high.z; // We need to include shadowing geometry that may be outside view (along the solar axis). + viewIntersectShadowRange.high.z = shadowRange.high.z; // We need to include shadowing geometry that may be outside view (along the solar axis). this._shadowFrustum.initFromRange(viewIntersectShadowRange); mapToWorld.multiplyPoint3dArrayQuietNormalize(this._shadowFrustum.points); const tileRange = Range3d.createNull(); scratchFrustumPlanes.init(this._shadowFrustum); - view.forEachTileTreeRef(((ref) => { + view.forEachTileTreeRef((ref) => { if (!ref.castsShadows) return; @@ -388,15 +464,17 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { const tileToMapTransform = worldToMapTransform.multiplyTransformTransform(drawArgs.location, this._scratchTransform); drawArgs.tree.draw(drawArgs); - })); + }); if (tileRange.isNull) { this.clearGraphics(true); } else if (this._graphics.length > 0) { // Avoid an uninvertible matrix on empty range... - if (Geometry.isAlmostEqualNumber(shadowRange.low.x, shadowRange.high.x) || + if ( + Geometry.isAlmostEqualNumber(shadowRange.low.x, shadowRange.high.x) || Geometry.isAlmostEqualNumber(shadowRange.low.y, shadowRange.high.y) || - Geometry.isAlmostEqualNumber(shadowRange.low.z, shadowRange.high.z)) { + Geometry.isAlmostEqualNumber(shadowRange.low.z, shadowRange.high.z) + ) { this.clearGraphics(true); return; } @@ -411,7 +489,12 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { this._projectionMatrix = frustumMap.transform0.clone(); const worldToNpc = postProjectionMatrixNpc.multiplyMatrixMatrix(this._projectionMatrix); - const npcToView = Map4d.createBoxMap(Point3d.create(0, 0, 0), Point3d.create(1, 1, 1), Point3d.create(0, 0, 0), Point3d.create(shadowMapWidth, shadowMapHeight, 1))!; + const npcToView = Map4d.createBoxMap( + Point3d.create(0, 0, 0), + Point3d.create(1, 1, 1), + Point3d.create(0, 0, 0), + Point3d.create(shadowMapWidth, shadowMapHeight, 1), + )!; const npcToWorld = worldToNpc.createInverse(); if (undefined === npcToWorld) { this.clearGraphics(true); @@ -468,8 +551,8 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { System.instance.frameBufferStack.execute(bundle.fbo, true, false, () => { System.instance.context.clearDepth(1.0); System.instance.context.clear(GL.BufferBit.Depth); - target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaquePlanar), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. - target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaqueGeneral), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. + target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaquePlanar), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. + target.techniques.execute(target, renderCommands.getCommands(RenderPass.OpaqueGeneral), RenderPass.PlanarClassification); // Draw these with RenderPass.PlanarClassification (rather than Opaque...) so that the pick ordering is avoided. }); // copy depth buffer to EVSM shadow buffer and average down for AA effect @@ -489,7 +572,7 @@ export class SolarShadowMap implements RenderMemory.Consumer, WebGLDisposable { System.instance.setMaxAnisotropy(undefined); // target.recordPerformanceMetric("Compute EVSM"); - this._batchState.reset(); // Reset the batch Ids... + this._batchState.reset(); // Reset the batch Ids... target.changeRenderPlan(prevPlan); System.instance.applyRenderState(prevState); diff --git a/core/frontend/src/render/webgl/StyleUniforms.ts b/core/frontend/src/render/webgl/StyleUniforms.ts index c14859fae0e8..ff3bebbd7c75 100644 --- a/core/frontend/src/render/webgl/StyleUniforms.ts +++ b/core/frontend/src/render/webgl/StyleUniforms.ts @@ -10,8 +10,8 @@ import { ColorDef, WhiteOnWhiteReversalSettings } from "@itwin/core-common"; import { RenderPlan } from "../RenderPlan"; import { ColorInfo } from "./ColorInfo"; import { FloatRgb, FloatRgba } from "./FloatRGBA"; -import { UniformHandle } from "./UniformHandle"; import { desync, sync } from "./Sync"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state of uniforms associated with the DisplayStyleState. * @internal diff --git a/core/frontend/src/render/webgl/SurfaceGeometry.ts b/core/frontend/src/render/webgl/SurfaceGeometry.ts index 7c1558d9c9c7..4ef791c18c08 100644 --- a/core/frontend/src/render/webgl/SurfaceGeometry.ts +++ b/core/frontend/src/render/webgl/SurfaceGeometry.ts @@ -11,17 +11,17 @@ import { FillFlags, RenderMode, TextureTransparency, ThematicGradientTransparenc import { SurfaceType } from "../../common/internal/render/SurfaceParams"; import { VertexIndices } from "../../common/internal/render/VertexIndices"; import { RenderMemory } from "../RenderMemory"; +import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { AttributeMap } from "./AttributeMap"; import { ShaderProgramParams } from "./DrawCommand"; import { GL } from "./GL"; -import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers"; import { MaterialInfo } from "./Material"; +import { MeshData } from "./MeshData"; +import { MeshGeometry } from "./MeshGeometry"; import { Pass, RenderOrder, RenderPass, SurfaceBitIndex } from "./RenderFlags"; import { System } from "./System"; import { Target } from "./Target"; import { TechniqueId } from "./TechniqueId"; -import { MeshData } from "./MeshData"; -import { MeshGeometry } from "./MeshGeometry"; /** @internal */ export function wantMaterials(vf: ViewFlags): boolean { @@ -37,7 +37,9 @@ export class SurfaceGeometry extends MeshGeometry { private readonly _buffers: BuffersContainer; private readonly _indices: BufferHandle; - public get lutBuffers() { return this._buffers; } + public get lutBuffers() { + return this._buffers; + } public static create(mesh: MeshData, indices: VertexIndices): SurfaceGeometry | undefined { const indexBuffer = BufferHandle.createArrayBuffer(indices.data); @@ -58,14 +60,30 @@ export class SurfaceGeometry extends MeshGeometry { stats.addSurface(this._indices.bytesUsed); } - public get isLit() { return SurfaceType.Lit === this.surfaceType || SurfaceType.TexturedLit === this.surfaceType; } - public get isTexturedType() { return SurfaceType.Textured === this.surfaceType || SurfaceType.TexturedLit === this.surfaceType; } - public get hasTexture() { return this.isTexturedType && undefined !== this.texture; } - public get hasNormalMap() { return this.isLit && this.isTexturedType && undefined !== this.normalMap; } - public get isGlyph() { return this.mesh.isGlyph; } - public override get alwaysRenderTranslucent() { return this.isGlyph; } - public get isTileSection() { return undefined !== this.texture && this.texture.isTileSection; } - public get isClassifier() { return SurfaceType.VolumeClassifier === this.surfaceType; } + public get isLit() { + return SurfaceType.Lit === this.surfaceType || SurfaceType.TexturedLit === this.surfaceType; + } + public get isTexturedType() { + return SurfaceType.Textured === this.surfaceType || SurfaceType.TexturedLit === this.surfaceType; + } + public get hasTexture() { + return this.isTexturedType && undefined !== this.texture; + } + public get hasNormalMap() { + return this.isLit && this.isTexturedType && undefined !== this.normalMap; + } + public get isGlyph() { + return this.mesh.isGlyph; + } + public override get alwaysRenderTranslucent() { + return this.isGlyph; + } + public get isTileSection() { + return undefined !== this.texture && this.texture.isTileSection; + } + public get isClassifier() { + return SurfaceType.VolumeClassifier === this.surfaceType; + } public override get supportsThematicDisplay() { return !this.isGlyph; } @@ -77,9 +95,15 @@ export class SurfaceGeometry extends MeshGeometry { return FillFlags.Blanking !== (this.fillFlags & FillFlags.Blanking); } - public override get asSurface() { return this; } - public override get asEdge() { return undefined; } - public override get asSilhouette() { return undefined; } + public override get asSurface() { + return this; + } + public override get asEdge() { + return undefined; + } + public override get asSilhouette() { + return undefined; + } protected _draw(numInstances: number, instanceBuffersContainer?: BuffersContainer): void { const system = System.instance; @@ -105,9 +129,15 @@ export class SurfaceGeometry extends MeshGeometry { return !this.isGlyph && (this.isLitSurface || this.wantTextures(target, this.hasTexture)); } - public get techniqueId(): TechniqueId { return TechniqueId.Surface; } - public override get isLitSurface() { return this.isLit; } - public override get hasBakedLighting() { return this.mesh.hasBakedLighting; } + public get techniqueId(): TechniqueId { + return TechniqueId.Surface; + } + public override get isLitSurface() { + return this.isLit; + } + public override get hasBakedLighting() { + return this.mesh.hasBakedLighting; + } public get renderOrder(): RenderOrder { if (FillFlags.Behind === (this.fillFlags & FillFlags.Behind)) return RenderOrder.BlankingRegion; @@ -229,7 +259,9 @@ export class SurfaceGeometry extends MeshGeometry { return !this.wantTextures(target, this.hasTexture); } - public override get materialInfo(): MaterialInfo | undefined { return this.mesh.materialInfo; } + public override get materialInfo(): MaterialInfo | undefined { + return this.mesh.materialInfo; + } public useTexture(params: ShaderProgramParams): boolean { return this.wantTextures(params.target, this.hasTexture); diff --git a/core/frontend/src/render/webgl/System.ts b/core/frontend/src/render/webgl/System.ts index 63fa94dc0c98..24eeb1fbc80b 100644 --- a/core/frontend/src/render/webgl/System.ts +++ b/core/frontend/src/render/webgl/System.ts @@ -7,35 +7,63 @@ */ import { assert, BentleyStatus, Dictionary, dispose, Id64, Id64String } from "@itwin/core-bentley"; -import { ColorDef, ElementAlignedBox3d, Frustum, Gradient, ImageBuffer, ImageBufferFormat, ImageSourceFormat, IModelError, RenderFeatureTable, RenderMaterial, RenderTexture, RgbColorProps, TextureMapping, TextureTransparency } from "@itwin/core-common"; +import { + ColorDef, + ElementAlignedBox3d, + Frustum, + Gradient, + ImageBuffer, + ImageBufferFormat, + ImageSourceFormat, + IModelError, + RenderFeatureTable, + RenderMaterial, + RenderTexture, + RgbColorProps, + TextureMapping, + TextureTransparency, +} from "@itwin/core-common"; import { ClipVector, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { Capabilities, WebGLContext } from "@itwin/webgl-compatibility"; -import { IModelApp } from "../../IModelApp"; -import { IModelConnection } from "../../IModelConnection"; -import { MapTileTreeReference, TileTreeReference } from "../../tile/internal"; import { imageElementFromImageSource } from "../../common/ImageUtil"; import { MeshParams } from "../../common/internal/render/MeshParams"; +import { PointCloudArgs } from "../../common/internal/render/PointCloudPrimitive"; import { PointStringParams } from "../../common/internal/render/PointStringParams"; import { PolylineParams } from "../../common/internal/render/PolylineParams"; +import { _batch, _branch, _featureTable, _nodes } from "../../common/internal/Symbols"; +import { BatchOptions } from "../../common/render/BatchOptions"; +import { InstancedGraphicParams, PatternGraphicParams } from "../../common/render/InstancedGraphicParams"; +import { RenderInstancesParams } from "../../common/render/RenderInstancesParams"; import { TextureCacheKey } from "../../common/render/TextureParams"; import { ViewRect } from "../../common/ViewRect"; +import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; +import { PrimitiveBuilder } from "../../internal/render/PrimitiveBuilder"; +import { RenderGeometry } from "../../internal/render/RenderGeometry"; +import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; +import { MapTileTreeReference, TileTreeReference } from "../../tile/internal"; +import { CreateRenderMaterialArgs } from "../CreateRenderMaterialArgs"; +import { CreateTextureArgs, CreateTextureFromSourceArgs } from "../CreateTextureArgs"; import { GraphicBranch, GraphicBranchOptions } from "../GraphicBranch"; import { CustomGraphicBuilderOptions, GraphicBuilder, ViewportGraphicBuilderOptions } from "../GraphicBuilder"; -import { InstancedGraphicParams, PatternGraphicParams } from "../../common/render/InstancedGraphicParams"; -import { PrimitiveBuilder } from "../../internal/render/PrimitiveBuilder"; import { RealityMeshGraphicParams } from "../RealityMeshGraphicParams"; -import { PointCloudArgs } from "../../common/internal/render/PointCloudPrimitive"; +import { RealityMeshParams } from "../RealityMeshParams"; import { RenderClipVolume } from "../RenderClipVolume"; import { RenderGraphic, RenderGraphicOwner } from "../RenderGraphic"; -import { CreateRenderMaterialArgs } from "../CreateRenderMaterialArgs"; import { RenderMemory } from "../RenderMemory"; -import { RealityMeshParams } from "../RealityMeshParams"; import { CreateGraphicFromTemplateArgs, - DebugShaderFile, GLTimerResultCallback, PlanarGridProps, RenderAreaPattern, RenderDiagnostics, RenderInstances, RenderSkyBoxParams, RenderSystem, RenderSystemDebugControl, + DebugShaderFile, + GLTimerResultCallback, + PlanarGridProps, + RenderAreaPattern, + RenderDiagnostics, + RenderInstances, + RenderSkyBoxParams, + RenderSystem, + RenderSystemDebugControl, } from "../RenderSystem"; import { RenderTarget } from "../RenderTarget"; -import { CreateTextureArgs, CreateTextureFromSourceArgs } from "../CreateTextureArgs"; import { ScreenSpaceEffectBuilder, ScreenSpaceEffectBuilderParams } from "../ScreenSpaceEffectBuilder"; import { BackgroundMapDrape } from "./BackgroundMapDrape"; import { SkyBoxQuadsGeometry, SkySphereViewportQuadGeometry } from "./CachedGeometry"; @@ -65,11 +93,6 @@ import { OffScreenTarget, OnScreenTarget } from "./Target"; import { Techniques } from "./Technique"; import { ExternalTextureLoader, Texture, TextureHandle } from "./Texture"; import { UniformHandle } from "./UniformHandle"; -import { BatchOptions } from "../../common/render/BatchOptions"; -import { RenderGeometry } from "../../internal/render/RenderGeometry"; -import { RenderInstancesParams } from "../../common/render/RenderInstancesParams"; -import { _batch, _branch, _featureTable, _nodes } from "../../common/internal/Symbols"; -import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; /* eslint-disable no-restricted-syntax */ @@ -155,7 +178,7 @@ export class IdMap implements WebGLDisposable { /** Find or create a new material given material parameters. This will cache the material if its key is valid. */ // eslint-disable-next-line deprecation/deprecation public getMaterial(params: RenderMaterial.Params): RenderMaterial { - if (!params.key || !Id64.isValidId64(params.key)) // Only cache persistent materials. + if (!params.key || !Id64.isValidId64(params.key)) // Only cache persistent materials. return new Material(params); let material = this.materials.get(params.key); @@ -176,7 +199,12 @@ export class IdMap implements WebGLDisposable { } // eslint-disable-next-line deprecation/deprecation - public getTextureFromElement(key: Id64String, iModel: IModelConnection, params: RenderTexture.Params, format: ImageSourceFormat): RenderTexture | undefined { + public getTextureFromElement( + key: Id64String, + iModel: IModelConnection, + params: RenderTexture.Params, + format: ImageSourceFormat, + ): RenderTexture | undefined { let tex = this.findTexture(params.key); if (tex) return tex; @@ -213,7 +241,9 @@ export class IdMap implements WebGLDisposable { public async createTextureFromImageSource(args: CreateTextureFromSourceArgs, key: string): Promise { // JPEGs don't support transparency. - const transparency = ImageSourceFormat.Jpeg === args.source.format ? TextureTransparency.Opaque : (args.transparency ?? TextureTransparency.Mixed); + const transparency = ImageSourceFormat.Jpeg === args.source.format + ? TextureTransparency.Opaque + : (args.transparency ?? TextureTransparency.Mixed); try { const image = await imageElementFromImageSource(args.source); if (!IModelApp.hasRenderSystem) @@ -235,7 +265,15 @@ export class IdMap implements WebGLDisposable { } // eslint-disable-next-line deprecation/deprecation - public getTextureFromCubeImages(posX: HTMLImageElement, negX: HTMLImageElement, posY: HTMLImageElement, negY: HTMLImageElement, posZ: HTMLImageElement, negZ: HTMLImageElement, params: RenderTexture.Params): RenderTexture | undefined { + public getTextureFromCubeImages( + posX: HTMLImageElement, + negX: HTMLImageElement, + posY: HTMLImageElement, + negY: HTMLImageElement, + posZ: HTMLImageElement, + negZ: HTMLImageElement, + params: RenderTexture.Params, + ): RenderTexture | undefined { let tex = this.findTexture(params.key); if (tex) return tex; @@ -287,7 +325,7 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re public readonly canvas: HTMLCanvasElement; public readonly currentRenderState = new RenderState(); public readonly context: WebGL2RenderingContext; - public readonly frameBufferStack = new FrameBufferStack(); // frame buffers are not owned by the system + public readonly frameBufferStack = new FrameBufferStack(); // frame buffers are not owned by the system private readonly _capabilities: Capabilities; public readonly resourceCache: Map; public readonly glTimer: GLTimer; @@ -296,14 +334,32 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re // NB: Increase the size of these arrays when the maximum number of attributes used by any one shader increases. private readonly _curVertexAttribStates: VertexAttribState[] = [ - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, ]; private readonly _nextVertexAttribStates: VertexAttribState[] = [ - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, - VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, + VertexAttribState.Disabled, ]; // The following are initialized immediately after the System is constructed. @@ -313,11 +369,19 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re private _screenSpaceEffects?: ScreenSpaceEffects; public readonly debugShaderFiles: DebugShaderFile[] = []; - public static get instance() { return IModelApp.renderSystem as System; } + public static get instance() { + return IModelApp.renderSystem as System; + } - public get isValid(): boolean { return this.canvas !== undefined; } - public get lineCodeTexture() { return this._lineCodeTexture; } - public get noiseTexture() { return this._noiseTexture; } + public get isValid(): boolean { + return this.canvas !== undefined; + } + public get lineCodeTexture() { + return this._lineCodeTexture; + } + public get noiseTexture() { + return this._noiseTexture; + } public get techniques() { assert(undefined !== this._techniques); @@ -329,19 +393,35 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re return this._screenSpaceEffects; } - public override get maxTextureSize(): number { return this._capabilities.maxTextureSize; } - public override get supportsCreateImageBitmap(): boolean { return this._capabilities.supportsCreateImageBitmap; } - public get maxRenderType() { return this._capabilities.maxRenderType; } - public get fragDepthDoesNotDisableEarlyZ() { return this._capabilities.driverBugs.fragDepthDoesNotDisableEarlyZ; } - public get maxAntialiasSamples() { return this._capabilities.maxAntialiasSamples; } - public get supportsNonPowerOf2Textures() { return this._capabilities.supportsNonPowerOf2Textures; } - public get maxTexSizeAllow() { return this._capabilities.maxTexSizeAllow; } + public override get maxTextureSize(): number { + return this._capabilities.maxTextureSize; + } + public override get supportsCreateImageBitmap(): boolean { + return this._capabilities.supportsCreateImageBitmap; + } + public get maxRenderType() { + return this._capabilities.maxRenderType; + } + public get fragDepthDoesNotDisableEarlyZ() { + return this._capabilities.driverBugs.fragDepthDoesNotDisableEarlyZ; + } + public get maxAntialiasSamples() { + return this._capabilities.maxAntialiasSamples; + } + public get supportsNonPowerOf2Textures() { + return this._capabilities.supportsNonPowerOf2Textures; + } + public get maxTexSizeAllow() { + return this._capabilities.maxTexSizeAllow; + } public get disjointTimerQuery() { const ext = this._capabilities.queryExtensionObject("EXT_disjoint_timer_query_webgl2"); return ext ?? this._capabilities.queryExtensionObject("EXT_disjoint_timer_query"); } - public override get isMobile(): boolean { return this._capabilities.isMobile; } + public override get isMobile(): boolean { + return this._capabilities.isMobile; + } public setDrawBuffers(attachments: GLenum[]): void { this.context.drawBuffers(attachments); @@ -370,7 +450,11 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re } /** Attempt to create a WebGLRenderingContext, returning undefined if unsuccessful. */ - public static createContext(canvas: HTMLCanvasElement, useWebGL2: boolean, inputContextAttributes?: WebGLContextAttributes): WebGLContext | undefined { + public static createContext( + canvas: HTMLCanvasElement, + useWebGL2: boolean, + inputContextAttributes?: WebGLContextAttributes, + ): WebGLContext | undefined { if (!useWebGL2) return undefined; // WebGL 2 is required. @@ -402,7 +486,7 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re throw new IModelError(BentleyStatus.ERROR, "Failed to initialize rendering capabilities"); // set actual gl state to match desired state defaults - context.depthFunc(GL.DepthFunc.Default); // LessOrEqual + context.depthFunc(GL.DepthFunc.Default); // LessOrEqual return new this(canvas, context, capabilities, options); } @@ -441,7 +525,14 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re this._noiseTexture = TextureHandle.createForData(noiseDim, noiseDim, noiseArr, false, GL.Texture.WrapMode.Repeat, GL.Texture.Format.Luminance); assert(undefined !== this._noiseTexture, "System.noiseTexture not created."); - this._lineCodeTexture = TextureHandle.createForData(LineCode.size, LineCode.count, new Uint8Array(LineCode.lineCodeData), false, GL.Texture.WrapMode.Repeat, GL.Texture.Format.Luminance); + this._lineCodeTexture = TextureHandle.createForData( + LineCode.size, + LineCode.count, + new Uint8Array(LineCode.lineCodeData), + false, + GL.Texture.WrapMode.Repeat, + GL.Texture.Format.Luminance, + ); assert(undefined !== this._lineCodeTexture, "System.lineCodeTexture not created."); this._screenSpaceEffects = new ScreenSpaceEffects(); @@ -463,7 +554,11 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re return PlanarGridGeometry.create(frustum, grid, this); } - public override createTerrainMesh(params: RealityMeshParams, transform?: Transform, disableTextureDisposal = false): RealityMeshGeometry | undefined { + public override createTerrainMesh( + params: RealityMeshParams, + transform?: Transform, + disableTextureDisposal = false, + ): RealityMeshGeometry | undefined { return RealityMeshGeometry.createForTerrain(params, transform, disableTextureDisposal); } @@ -555,7 +650,10 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re return graphic; } - public override createRenderGraphic(geometry: RenderGeometry, instances?: InstancedGraphicParams | RenderAreaPattern | InstanceBuffers): RenderGraphic | undefined { + public override createRenderGraphic( + geometry: RenderGeometry, + instances?: InstancedGraphicParams | RenderAreaPattern | InstanceBuffers, + ): RenderGraphic | undefined { const geom = geometry as RenderGeometryImpl; let buffers: InstanceBuffers | PatternBuffers | undefined; @@ -686,14 +784,17 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re } if (args.textureMapping) { - params.textureMapping = new TextureMapping(args.textureMapping.texture, new TextureMapping.Params({ - textureMat2x3: args.textureMapping.transform, - mapMode: args.textureMapping.mode, - textureWeight: args.textureMapping.weight, - worldMapping: args.textureMapping.worldMapping, - useConstantLod: args.textureMapping.useConstantLod, - constantLodProps: args.textureMapping.constantLodProps, - })); + params.textureMapping = new TextureMapping( + args.textureMapping.texture, + new TextureMapping.Params({ + textureMat2x3: args.textureMapping.transform, + mapMode: args.textureMapping.mode, + textureWeight: args.textureMapping.weight, + worldMapping: args.textureMapping.worldMapping, + useConstantLod: args.textureMapping.useConstantLod, + constantLodProps: args.textureMapping.constantLodProps, + }), + ); params.textureMapping.normalMapParams = args.textureMapping.normalMapParams; } @@ -755,12 +856,26 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re } // eslint-disable-next-line deprecation/deprecation - public override createTextureFromElement(id: Id64String, imodel: IModelConnection, params: RenderTexture.Params, format: ImageSourceFormat): RenderTexture | undefined { + public override createTextureFromElement( + id: Id64String, + imodel: IModelConnection, + params: RenderTexture.Params, + format: ImageSourceFormat, + ): RenderTexture | undefined { return this.getIdMap(imodel).getTextureFromElement(id, imodel, params, format); } // eslint-disable-next-line deprecation/deprecation - public override createTextureFromCubeImages(posX: HTMLImageElement, negX: HTMLImageElement, posY: HTMLImageElement, negY: HTMLImageElement, posZ: HTMLImageElement, negZ: HTMLImageElement, imodel: IModelConnection, params: RenderTexture.Params): RenderTexture | undefined { + public override createTextureFromCubeImages( + posX: HTMLImageElement, + negX: HTMLImageElement, + posY: HTMLImageElement, + negY: HTMLImageElement, + posZ: HTMLImageElement, + negZ: HTMLImageElement, + imodel: IModelConnection, + params: RenderTexture.Params, + ): RenderTexture | undefined { return this.getIdMap(imodel).getTextureFromCubeImages(posX, negX, posY, negY, posZ, negZ, params); } @@ -837,13 +952,21 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re } /** Bind the specified texture to the specified unit. This may *or may not* make the texture *active* */ - public bindTexture2d(unit: TextureUnit, texture: TextureBinding) { this.bindTexture(unit, GL.Texture.Target.TwoDee, texture, false); } + public bindTexture2d(unit: TextureUnit, texture: TextureBinding) { + this.bindTexture(unit, GL.Texture.Target.TwoDee, texture, false); + } /** Bind the specified texture to the specified unit. This may *or may not* make the texture *active* */ - public bindTextureCubeMap(unit: TextureUnit, texture: TextureBinding) { this.bindTexture(unit, GL.Texture.Target.CubeMap, texture, false); } + public bindTextureCubeMap(unit: TextureUnit, texture: TextureBinding) { + this.bindTexture(unit, GL.Texture.Target.CubeMap, texture, false); + } /** Bind the specified texture to the specified unit. This *always* makes the texture *active* */ - public activateTexture2d(unit: TextureUnit, texture: TextureBinding) { this.bindTexture(unit, GL.Texture.Target.TwoDee, texture, true); } + public activateTexture2d(unit: TextureUnit, texture: TextureBinding) { + this.bindTexture(unit, GL.Texture.Target.TwoDee, texture, true); + } /** Bind the specified texture to the specified unit. This *always* makes the texture *active* */ - public activateTextureCubeMap(unit: TextureUnit, texture: TextureBinding) { this.bindTexture(unit, GL.Texture.Target.CubeMap, texture, true); } + public activateTextureCubeMap(unit: TextureUnit, texture: TextureBinding) { + this.bindTexture(unit, GL.Texture.Target.CubeMap, texture, true); + } // Ensure *something* is bound to suppress 'no texture assigned to unit x' warnings. public ensureSamplerBound(uniform: UniformHandle, unit: TextureUnit): void { @@ -933,11 +1056,17 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re } // RenderSystemDebugControl - public override get debugControl(): RenderSystemDebugControl { return this; } + public override get debugControl(): RenderSystemDebugControl { + return this; + } private _dpiAwareLOD?: boolean; - public override get dpiAwareLOD(): boolean { return this._dpiAwareLOD ?? super.dpiAwareLOD; } - public override set dpiAwareLOD(dpiAware: boolean) { this._dpiAwareLOD = dpiAware; } + public override get dpiAwareLOD(): boolean { + return this._dpiAwareLOD ?? super.dpiAwareLOD; + } + public override set dpiAwareLOD(dpiAware: boolean) { + this._dpiAwareLOD = dpiAware; + } public loseContext(): boolean { const ext = this._capabilities.queryExtensionObject("WEBGL_lose_context"); @@ -952,7 +1081,9 @@ export class System extends RenderSystem implements RenderSystemDebugControl, Re return this.techniques.compileShaders(); } - public get isGLTimerSupported(): boolean { return this.glTimer.isSupported; } + public get isGLTimerSupported(): boolean { + return this.glTimer.isSupported; + } public set resultsCallback(callback: GLTimerResultCallback | undefined) { this.glTimer.resultsCallback = callback; } diff --git a/core/frontend/src/render/webgl/Target.ts b/core/frontend/src/render/webgl/Target.ts index f21bf62c6434..96ce19f35496 100644 --- a/core/frontend/src/render/webgl/Target.ts +++ b/core/frontend/src/render/webgl/Target.ts @@ -7,19 +7,32 @@ */ import { assert, dispose, Id64, Id64String, IDisposable } from "@itwin/core-bentley"; -import { Point2d, Point3d, Range3d, Transform, XAndY, XYZ } from "@itwin/core-geometry"; import { - AmbientOcclusion, AnalysisStyle, Frustum, ImageBuffer, ImageBufferFormat, Npc, RenderMode, RenderTexture, ThematicDisplayMode, ViewFlags, + AmbientOcclusion, + AnalysisStyle, + Frustum, + ImageBuffer, + ImageBufferFormat, + Npc, + RenderMode, + RenderTexture, + ThematicDisplayMode, + ViewFlags, } from "@itwin/core-common"; -import { ViewRect } from "../../common/ViewRect"; +import { Point2d, Point3d, Range3d, Transform, XAndY, XYZ } from "@itwin/core-geometry"; import { canvasToImageBuffer, canvasToResizedCanvasWithBars, imageBufferToCanvas } from "../../common/ImageUtil"; +import { AnimationNodeId } from "../../common/internal/render/AnimationNodeId"; +import { _implementationProhibited } from "../../common/internal/Symbols"; +import { ViewRect } from "../../common/ViewRect"; +import { IModelConnection } from "../../IModelConnection"; import { HiliteSet, ModelSubCategoryHiliteMode } from "../../SelectionSet"; +import { ActiveSpatialClassifier } from "../../SpatialClassifiersState"; import { SceneContext } from "../../ViewContext"; import { ReadImageBufferArgs, Viewport } from "../../Viewport"; -import { IModelConnection } from "../../IModelConnection"; import { CanvasDecoration } from "../CanvasDecoration"; import { Decorations } from "../Decorations"; import { FeatureSymbology } from "../FeatureSymbology"; +import { FrameStatsCollector } from "../FrameStats"; import { AnimationBranchStates } from "../GraphicBranch"; import { Pixel } from "../Pixel"; import { GraphicList } from "../RenderGraphic"; @@ -28,14 +41,15 @@ import { createEmptyRenderPlan, RenderPlan } from "../RenderPlan"; import { PlanarClassifierMap, RenderPlanarClassifier } from "../RenderPlanarClassifier"; import { RenderTextureDrape, TextureDrapeMap } from "../RenderSystem"; import { PrimitiveVisibility, RenderTarget, RenderTargetDebugControl } from "../RenderTarget"; -import { ScreenSpaceEffectContext } from "../ScreenSpaceEffectBuilder"; import { Scene } from "../Scene"; +import { ScreenSpaceEffectContext } from "../ScreenSpaceEffectBuilder"; import { QueryTileFeaturesOptions, QueryVisibleFeaturesCallback } from "../VisibleFeature"; import { BranchState } from "./BranchState"; import { CachedGeometry, SingleTexturedViewportQuadGeometry } from "./CachedGeometry"; import { ColorInfo } from "./ColorInfo"; import { WebGLDisposable } from "./Disposable"; import { DrawParams, ShaderProgramParams } from "./DrawCommand"; +import { EdgeSettings } from "./EdgeSettings"; import { FrameBuffer } from "./FrameBuffer"; import { GL } from "./GL"; import { Batch, Branch, WorldDecorations } from "./Graphic"; @@ -52,18 +66,13 @@ import { ShaderProgramExecutor } from "./ShaderProgram"; import { SolarShadowMap } from "./SolarShadowMap"; import { desync, SyncTarget } from "./Sync"; import { System } from "./System"; +import { TargetGraphics } from "./TargetGraphics"; import { TargetUniforms } from "./TargetUniforms"; import { Techniques } from "./Technique"; import { TechniqueId } from "./TechniqueId"; import { Texture2DHandle, TextureHandle } from "./Texture"; import { TextureDrape } from "./TextureDrape"; -import { EdgeSettings } from "./EdgeSettings"; -import { TargetGraphics } from "./TargetGraphics"; import { VisibleTileFeatures } from "./VisibleTileFeatures"; -import { FrameStatsCollector } from "../FrameStats"; -import { ActiveSpatialClassifier } from "../../SpatialClassifiersState"; -import { AnimationNodeId } from "../../common/internal/render/AnimationNodeId"; -import { _implementationProhibited } from "../../common/internal/Symbols"; function swapImageByte(image: ImageBuffer, i0: number, i1: number) { const tmp = image.data[i0]; @@ -162,7 +171,9 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return map.isEnabled && map.isReady ? map.frustum : undefined; } - public override get debugControl(): RenderTargetDebugControl { return this; } + public override get debugControl(): RenderTargetDebugControl { + return this; + } public get viewRect(): ViewRect { return this.renderRect; @@ -175,32 +186,58 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo this._overlayRenderState.flags.depthMask = false; this._overlayRenderState.flags.blend = true; this._overlayRenderState.blend.setBlendFunc(GL.BlendFactor.One, GL.BlendFactor.OneMinusSrcAlpha); - this._compositor = SceneCompositor.create(this); // compositor is created but not yet initialized... we are still undisposed - this.renderRect = rect ? rect : new ViewRect(); // if the rect is undefined, expect that it will be updated dynamically in an OnScreenTarget + this._compositor = SceneCompositor.create(this); // compositor is created but not yet initialized... we are still undisposed + this.renderRect = rect ? rect : new ViewRect(); // if the rect is undefined, expect that it will be updated dynamically in an OnScreenTarget if (undefined !== System.instance.antialiasSamples) this._antialiasSamples = System.instance.antialiasSamples; else - this._antialiasSamples = (undefined !== System.instance.options.antialiasSamples ? System.instance.options.antialiasSamples : 1); + this._antialiasSamples = undefined !== System.instance.options.antialiasSamples ? System.instance.options.antialiasSamples : 1; } - public get compositor() { return this._compositor; } - public get isReadPixelsInProgress(): boolean { return this._isReadPixelsInProgress; } - public get readPixelsSelector(): Pixel.Selector { return this._readPixelsSelector; } - public get drawNonLocatable(): boolean { return this._drawNonLocatable; } + public get compositor() { + return this._compositor; + } + public get isReadPixelsInProgress(): boolean { + return this._isReadPixelsInProgress; + } + public get readPixelsSelector(): Pixel.Selector { + return this._readPixelsSelector; + } + public get drawNonLocatable(): boolean { + return this._drawNonLocatable; + } - public get techniques(): Techniques { return this.renderSystem.techniques; } + public get techniques(): Techniques { + return this.renderSystem.techniques; + } - public get hilites(): Hilites { return this._hilites; } - public get hiliteSyncTarget(): SyncTarget { return this._hiliteSyncTarget; } + public get hilites(): Hilites { + return this._hilites; + } + public get hiliteSyncTarget(): SyncTarget { + return this._hiliteSyncTarget; + } - public get pickExclusions(): Id64.Uint32Set { return this._currPickExclusions; } + public get pickExclusions(): Id64.Uint32Set { + return this._currPickExclusions; + } - public get flashed(): Id64.Uint32Pair | undefined { return Id64.isValid(this._flashedId) ? this._flashed : undefined; } - public get flashedId(): Id64String { return this._flashedId; } - public get flashIntensity(): number { return this._flashIntensity; } + public get flashed(): Id64.Uint32Pair | undefined { + return Id64.isValid(this._flashedId) ? this._flashed : undefined; + } + public get flashedId(): Id64String { + return this._flashedId; + } + public get flashIntensity(): number { + return this._flashIntensity; + } - public get analysisFraction(): number { return this._analysisFraction; } - public set analysisFraction(fraction: number) { this._analysisFraction = fraction; } + public get analysisFraction(): number { + return this._analysisFraction; + } + public set analysisFraction(fraction: number) { + this._analysisFraction = fraction; + } public override get animationBranches(): AnimationBranchStates | undefined { return this._animationBranches; @@ -214,11 +251,19 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo this._animationBranches = undefined; } - public override get antialiasSamples(): number { return this._antialiasSamples; } - public override set antialiasSamples(numSamples: number) { this._antialiasSamples = numSamples; } + public override get antialiasSamples(): number { + return this._antialiasSamples; + } + public override set antialiasSamples(numSamples: number) { + this._antialiasSamples = numSamples; + } - public get solarShadowMap(): SolarShadowMap { return this.compositor.solarShadowMap; } - public get isDrawingShadowMap(): boolean { return this.solarShadowMap.isEnabled && this.solarShadowMap.isDrawing; } + public get solarShadowMap(): SolarShadowMap { + return this.compositor.solarShadowMap; + } + public get isDrawingShadowMap(): boolean { + return this.solarShadowMap.isEnabled && this.solarShadowMap.isDrawing; + } public override getPlanarClassifier(id: Id64String): RenderPlanarClassifier | undefined { return undefined !== this._planarClassifiers ? this._planarClassifiers.get(id) : undefined; } @@ -247,14 +292,30 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return this._worldDecorations; } - public get currentBranch(): BranchState { return this.uniforms.branch.top; } - public get currentViewFlags(): ViewFlags { return this.currentBranch.viewFlags; } - public get currentTransform(): Transform { return this.currentBranch.transform; } - public get currentTransparencyThreshold(): number { return this.currentEdgeSettings.transparencyThreshold; } - public get currentEdgeSettings(): EdgeSettings { return this.currentBranch.edgeSettings; } - public get currentFeatureSymbologyOverrides(): FeatureSymbology.Overrides { return this.currentBranch.symbologyOverrides; } - public get currentPlanarClassifier(): PlanarClassifier | undefined { return this.currentBranch.planarClassifier; } - public get currentlyDrawingClassifier(): PlanarClassifier | undefined { return this._currentlyDrawingClassifier; } + public get currentBranch(): BranchState { + return this.uniforms.branch.top; + } + public get currentViewFlags(): ViewFlags { + return this.currentBranch.viewFlags; + } + public get currentTransform(): Transform { + return this.currentBranch.transform; + } + public get currentTransparencyThreshold(): number { + return this.currentEdgeSettings.transparencyThreshold; + } + public get currentEdgeSettings(): EdgeSettings { + return this.currentBranch.edgeSettings; + } + public get currentFeatureSymbologyOverrides(): FeatureSymbology.Overrides { + return this.currentBranch.symbologyOverrides; + } + public get currentPlanarClassifier(): PlanarClassifier | undefined { + return this.currentBranch.planarClassifier; + } + public get currentlyDrawingClassifier(): PlanarClassifier | undefined { + return this._currentlyDrawingClassifier; + } public get currentTextureDrape(): TextureDrape | undefined { const drape = this.currentBranch.textureDrape; return undefined !== drape && drape.isReady ? drape : undefined; @@ -268,8 +329,12 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return this.uniforms.branch.modelViewMatrix.multiplyPoint3dQuietNormalize(modelPt, result); } - public get is2d(): boolean { return this.uniforms.frustum.is2d; } - public get is3d(): boolean { return !this.is2d; } + public get is2d(): boolean { + return this.uniforms.frustum.is2d; + } + public get is3d(): boolean { + return !this.is2d; + } private _isDisposed = false; public get isDisposed(): boolean { @@ -401,7 +466,8 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo public get wantThematicSensors(): boolean { const thematic = this.plan.thematic; - return this.wantThematicDisplay && undefined !== thematic && ThematicDisplayMode.InverseDistanceWeightedSensors === thematic.displayMode && thematic.sensorSettings.sensors.length > 0; + return this.wantThematicDisplay && undefined !== thematic && ThematicDisplayMode.InverseDistanceWeightedSensors === thematic.displayMode && + thematic.sensorSettings.sensors.length > 0; } public override updateSolarShadows(context: SceneContext | undefined): void { @@ -410,10 +476,16 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo // ---- Implementation of RenderTarget interface ---- // - public get renderSystem(): System { return System.instance; } + public get renderSystem(): System { + return System.instance; + } - public get planFraction() { return this.uniforms.frustum.planFraction; } - public get planFrustum() { return this.uniforms.frustum.planFrustum; } + public get planFraction() { + return this.uniforms.frustum.planFraction; + } + public get planFrustum() { + return this.uniforms.frustum.planFrustum; + } public changeDecorations(decs: Decorations): void { this.graphics.decorations = decs; @@ -443,9 +515,10 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo private changeDrapesOrClassifiers(oldMap: Map | undefined, newMap: Map | undefined): void { if (undefined === newMap) { - if (undefined !== oldMap) + if (undefined !== oldMap) { for (const value of oldMap.values()) value.dispose(); + } return; } @@ -549,7 +622,7 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo assert(this.renderSystem.frameBufferStack.isEmpty); } - protected drawOverlayDecorations(): void { } + protected drawOverlayDecorations(): void {} /** * Invoked via Viewport.changeView() when the owning Viewport is changed to look at a different view. @@ -580,7 +653,9 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo Primitive.freeParams(); } - public get wantInvertBlackBackground(): boolean { return false; } + public get wantInvertBlackBackground(): boolean { + return false; + } public computeEdgeWeight(pass: RenderPass, baseWeight: number): number { return this.currentEdgeSettings.getWeight(pass, this.currentViewFlags) ?? baseWeight; @@ -635,9 +710,13 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo private _frameStatsCollector = new FrameStatsCollector(); - public get frameStatsCollector(): FrameStatsCollector { return this._frameStatsCollector; } + public get frameStatsCollector(): FrameStatsCollector { + return this._frameStatsCollector; + } - public override assignFrameStatsCollector(collector: FrameStatsCollector) { this._frameStatsCollector = collector; } + public override assignFrameStatsCollector(collector: FrameStatsCollector) { + this._frameStatsCollector = collector; + } private paintScene(sceneMilSecElapsed?: number): void { if (!this._dcAssigned) @@ -657,7 +736,12 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo // Set this to true to visualize the output of readPixels()...useful for debugging pick. if (this.drawForReadPixels) { this.beginReadPixels(Pixel.Selector.Feature); - this.compositor.drawForReadPixels(this._renderCommands, this.graphics.overlays, this.graphics.decorations?.worldOverlay, this.graphics.decorations?.viewOverlay); + this.compositor.drawForReadPixels( + this._renderCommands, + this.graphics.overlays, + this.graphics.decorations?.worldOverlay, + this.graphics.decorations?.viewOverlay, + ); this.endReadPixels(); } else { // After the Target is first created or any time its dimensions change, SceneCompositor.preDraw() must update @@ -750,7 +834,13 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return true; } - public readPixels(rect: ViewRect, selector: Pixel.Selector, receiver: Pixel.Receiver, excludeNonLocatable: boolean, excludedElements?: Iterable): void { + public readPixels( + rect: ViewRect, + selector: Pixel.Selector, + receiver: Pixel.Receiver, + excludeNonLocatable: boolean, + excludedElements?: Iterable, + ): void { if (!this.assignDC()) return; @@ -811,7 +901,6 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo private createOrReuseReadPixelResources(rect: ViewRect): ReadPixelResources | undefined { if (this._readPixelReusableResources !== undefined) { - // To reuse a texture, we need it to be the same size or bigger than what we need if (this._readPixelReusableResources.texture.width >= rect.width && this._readPixelReusableResources.texture.height >= rect.height) { const resources = this._readPixelReusableResources; @@ -842,7 +931,6 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo let reuseResources = !isTooBigToReuse; if (reuseResources && this._readPixelReusableResources !== undefined) { - // Keep the biggest texture if (this._readPixelReusableResources.texture.width > texture.width && this._readPixelReusableResources.texture.height > texture.height) { reuseResources = false; // The current resources being reused are better @@ -948,7 +1036,12 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo this.beginReadPixels(selector, rectFrust); // Draw the scene - this.compositor.drawForReadPixels(this._renderCommands, this.graphics.overlays, this.graphics.decorations?.worldOverlay, this.graphics.decorations?.viewOverlay); + this.compositor.drawForReadPixels( + this._renderCommands, + this.graphics.overlays, + this.graphics.decorations?.worldOverlay, + this.graphics.decorations?.viewOverlay, + ); if (this.performanceMetrics && !this.performanceMetrics.gatherCurPerformanceMetrics) { // Only collect readPixels data if in disp-perf-test-app this.performanceMetrics.endOperation(); // End the 'CPU Total Time' operation @@ -985,7 +1078,11 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return result; } - public override queryVisibleTileFeatures(options: QueryTileFeaturesOptions, iModel: IModelConnection, callback: QueryVisibleFeaturesCallback): void { + public override queryVisibleTileFeatures( + options: QueryTileFeaturesOptions, + iModel: IModelConnection, + callback: QueryVisibleFeaturesCallback, + ): void { this.beginReadPixels(Pixel.Selector.Feature); callback(new VisibleTileFeatures(this._renderCommands, options, this, iModel)); this.endReadPixels(); @@ -1076,7 +1173,12 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return undefined; const adjustedTargetSize = Target._applyAspectRatioCorrection(new Point2d(wantRect.width, wantRect.height), targetSize); - const resizedCanvas = canvasToResizedCanvasWithBars(canvas, adjustedTargetSize, new Point2d(targetSize.x - adjustedTargetSize.x, targetSize.y - adjustedTargetSize.y), this.uniforms.style.backgroundHexString); + const resizedCanvas = canvasToResizedCanvasWithBars( + canvas, + adjustedTargetSize, + new Point2d(targetSize.x - adjustedTargetSize.x, targetSize.y - adjustedTargetSize.y), + this.uniforms.style.backgroundHexString, + ); const resizedImage = canvasToImageBuffer(resizedCanvas); if (undefined !== resizedImage) @@ -1150,7 +1252,12 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo return undefined; const adjustedSize = Target._applyAspectRatioCorrection({ x: captureRect.width, y: captureRect.height }, args.size); - canvas = canvasToResizedCanvasWithBars(canvas, adjustedSize, new Point2d(args.size.x - adjustedSize.x, args.size.y - adjustedSize.y), this.uniforms.style.backgroundHexString); + canvas = canvasToResizedCanvasWithBars( + canvas, + adjustedSize, + new Point2d(args.size.x - adjustedSize.x, args.size.y - adjustedSize.y), + this.uniforms.style.backgroundHexString, + ); image = canvasToImageBuffer(canvas); if (!image) return undefined; @@ -1257,7 +1364,8 @@ export abstract class Target extends RenderTarget implements RenderTargetDebugCo Math.floor(rect.left * ratio), Math.floor(rect.top * ratio), Math.floor(rect.right * ratio), - Math.floor(rect.bottom * ratio)); + Math.floor(rect.bottom * ratio), + ); } public getRenderCommands(): Array<{ name: string, count: number }> { @@ -1300,8 +1408,12 @@ class CanvasState { return true; } - public get width() { return this.canvas.width; } - public get height() { return this.canvas.height; } + public get width() { + return this.canvas.width; + } + public get height() { + return this.canvas.height; + } } /** A Target that renders to a canvas on the screen @@ -1316,7 +1428,9 @@ export class OnScreenTarget extends Target { private _scratchDrawParams?: DrawParams; private _devicePixelRatioOverride?: number; - private get _curCanvas() { return this._usingWebGLCanvas ? this._webglCanvas : this._2dCanvas; } + private get _curCanvas() { + return this._usingWebGLCanvas ? this._webglCanvas : this._2dCanvas; + } public constructor(canvas: HTMLCanvasElement) { super(); @@ -1344,8 +1458,12 @@ export class OnScreenTarget extends Target { this._blitGeom.collectStatistics(stats); } - public get devicePixelRatioOverride(): number | undefined { return this._devicePixelRatioOverride; } - public set devicePixelRatioOverride(ovr: number | undefined) { this._devicePixelRatioOverride = ovr; } + public get devicePixelRatioOverride(): number | undefined { + return this._devicePixelRatioOverride; + } + public set devicePixelRatioOverride(ovr: number | undefined) { + this._devicePixelRatioOverride = ovr; + } public override get devicePixelRatio(): number { if (undefined !== this.devicePixelRatioOverride) return this.devicePixelRatioOverride; @@ -1527,7 +1645,9 @@ export class OffScreenTarget extends Target { assert(false); // offscreen viewport's dimensions are set once, in constructor. } - public updateViewRect(): boolean { return false; } // offscreen target does not dynamically resize the view rect + public updateViewRect(): boolean { + return false; + } // offscreen target does not dynamically resize the view rect public setViewRect(rect: ViewRect, temporary: boolean): void { if (this.renderRect.equals(rect)) diff --git a/core/frontend/src/render/webgl/TargetGraphics.ts b/core/frontend/src/render/webgl/TargetGraphics.ts index 7c56d2882626..3fd4ec36b4ff 100644 --- a/core/frontend/src/render/webgl/TargetGraphics.ts +++ b/core/frontend/src/render/webgl/TargetGraphics.ts @@ -7,9 +7,9 @@ */ import { dispose, disposeArray } from "@itwin/core-bentley"; -import { GraphicList } from "../RenderGraphic"; -import { Decorations } from "../Decorations"; import { CanvasDecorationList } from "../CanvasDecoration"; +import { Decorations } from "../Decorations"; +import { GraphicList } from "../RenderGraphic"; import { Scene } from "../Scene"; /** The various graphics associated with a [[Target]]. @@ -39,13 +39,17 @@ export class TargetGraphics { this.overlays = scene.overlay; } - public get dynamics(): GraphicList | undefined { return this._dynamics; } + public get dynamics(): GraphicList | undefined { + return this._dynamics; + } public set dynamics(dynamics: GraphicList | undefined) { disposeArray(this._dynamics); this._dynamics = dynamics; } - public get decorations(): Decorations | undefined { return this._decorations; } + public get decorations(): Decorations | undefined { + return this._decorations; + } public set decorations(decorations: Decorations | undefined) { dispose(this._decorations); this._decorations = decorations; diff --git a/core/frontend/src/render/webgl/TargetUniforms.ts b/core/frontend/src/render/webgl/TargetUniforms.ts index bce9631600b3..3a56f5b30551 100644 --- a/core/frontend/src/render/webgl/TargetUniforms.ts +++ b/core/frontend/src/render/webgl/TargetUniforms.ts @@ -8,22 +8,22 @@ import { Matrix4d, Vector3d } from "@itwin/core-geometry"; import { RenderPlan } from "../RenderPlan"; +import { AtmosphereUniforms } from "./AtmosphereUniforms"; import { BatchUniforms } from "./BatchUniforms"; import { BranchUniforms } from "./BranchUniforms"; +import { ContourUniforms } from "./ContourUniforms"; import { FrustumUniforms, FrustumUniformType } from "./FrustumUniforms"; -import { UniformHandle } from "./UniformHandle"; import { HiliteUniforms } from "./HiliteUniforms"; import { LightingUniforms } from "./LightingUniforms"; import { Matrix4 } from "./Matrix"; +import { RealityModelUniforms } from "./RealityModelUniforms"; import { ShadowUniforms } from "./ShadowUniforms"; import { StyleUniforms } from "./StyleUniforms"; import { desync, sync, SyncObserver, SyncToken } from "./Sync"; import { Target } from "./Target"; import { ThematicUniforms } from "./ThematicUniforms"; +import { UniformHandle } from "./UniformHandle"; import { ViewRectUniforms } from "./ViewRectUniforms"; -import { RealityModelUniforms } from "./RealityModelUniforms"; -import { AtmosphereUniforms } from "./AtmosphereUniforms"; -import { ContourUniforms } from "./ContourUniforms"; class PixelWidthFactor { /** The pixel width factor depends on both the frustum and the view rect. It also depends on the frustum scale associated with the current Branch. */ diff --git a/core/frontend/src/render/webgl/Technique.ts b/core/frontend/src/render/webgl/Technique.ts index 030798b93b74..770eb8a65205 100644 --- a/core/frontend/src/render/webgl/Technique.ts +++ b/core/frontend/src/render/webgl/Technique.ts @@ -13,7 +13,6 @@ import { WebGLDisposable } from "./Disposable"; import { DrawCommands, DrawParams } from "./DrawCommand"; import { createAmbientOcclusionProgram } from "./glsl/AmbientOcclusion"; import { createBlurProgram } from "./glsl/Blur"; -import { createEDLCalcBasicProgram, createEDLCalcFullProgram, createEDLFilterProgram, createEDLMixProgram } from "./glsl/EDL"; import { createClearPickAndColorProgram } from "./glsl/ClearPickAndColor"; import { createClearTranslucentProgram } from "./glsl/ClearTranslucent"; import { createCombine3TexturesProgram } from "./glsl/Combine3Textures"; @@ -23,11 +22,22 @@ import { createCompositeProgram } from "./glsl/Composite"; import { createCopyColorProgram } from "./glsl/CopyColor"; import { createCopyPickBuffersProgram } from "./glsl/CopyPickBuffers"; import { - createVolClassBlendProgram, createVolClassColorUsingStencilProgram, createVolClassCopyZProgram, createVolClassSetBlendProgram, + createVolClassBlendProgram, + createVolClassColorUsingStencilProgram, + createVolClassCopyZProgram, + createVolClassSetBlendProgram, } from "./glsl/CopyStencil"; import { createEdgeBuilder, EdgeBuilderType } from "./glsl/Edge"; +import { createEDLCalcBasicProgram, createEDLCalcFullProgram, createEDLFilterProgram, createEDLMixProgram } from "./glsl/EDL"; import { createEVSMProgram } from "./glsl/EVSMFromDepth"; -import { addFeatureId, addFeatureSymbology, addRenderOrder, addUniformFeatureSymbology, FeatureSymbologyOptions, mixFeatureColor } from "./glsl/FeatureSymbology"; +import { + addFeatureId, + addFeatureSymbology, + addRenderOrder, + addUniformFeatureSymbology, + FeatureSymbologyOptions, + mixFeatureColor, +} from "./glsl/FeatureSymbology"; import { addFragColorWithPreMultipliedAlpha, addPickBufferOutputs } from "./glsl/Fragment"; import { addLogDepth } from "./glsl/LogarithmicDepthBuffer"; import { addUnlitMonochrome } from "./glsl/Monochrome"; @@ -35,9 +45,7 @@ import createPlanarGridProgram from "./glsl/PlanarGrid"; import { createPointCloudBuilder, createPointCloudHiliter } from "./glsl/PointCloud"; import { createPointStringBuilder, createPointStringHiliter } from "./glsl/PointString"; import { createPolylineBuilder, createPolylineHiliter } from "./glsl/Polyline"; -import { - addColorOverrideMix, createClassifierRealityMeshHiliter, createRealityMeshBuilder, createRealityMeshHiliter, -} from "./glsl/RealityMesh"; +import { addColorOverrideMix, createClassifierRealityMeshHiliter, createRealityMeshBuilder, createRealityMeshHiliter } from "./glsl/RealityMesh"; import { createSkyBoxProgram } from "./glsl/SkyBox"; import { createSkySphereBuilder } from "./glsl/SkySphere"; import { createSurfaceBuilder, createSurfaceHiliter } from "./glsl/Surface"; @@ -50,7 +58,16 @@ import { System } from "./System"; import { Target } from "./Target"; import { EnableAtmosphere, - FeatureMode, IsAnimated, IsClassified, IsEdgeTestNeeded, IsInstanced, IsShadowable, IsThematic, IsWiremesh, PositionType, TechniqueFlags, + FeatureMode, + IsAnimated, + IsClassified, + IsEdgeTestNeeded, + IsInstanced, + IsShadowable, + IsThematic, + IsWiremesh, + PositionType, + TechniqueFlags, } from "./TechniqueFlags"; import { computeCompositeTechniqueId, TechniqueId } from "./TechniqueId"; @@ -73,14 +90,26 @@ export class SingularTechnique implements Technique { public readonly program: ShaderProgram; // Note: Technique assumes ownership of a program - public constructor(program: ShaderProgram) { this.program = program; } + public constructor(program: ShaderProgram) { + this.program = program; + } - public getShader(_flags: TechniqueFlags) { return this.program; } - public getShaderByIndex(_index: number) { return this.program; } - public getShaderCount() { return 1; } - public compileShaders(): boolean { return this.program.compile() === CompileStatus.Success; } + public getShader(_flags: TechniqueFlags) { + return this.program; + } + public getShaderByIndex(_index: number) { + return this.program; + } + public getShaderCount() { + return 1; + } + public compileShaders(): boolean { + return this.program.compile() === CompileStatus.Success; + } - public get isDisposed(): boolean { return this.program.isDisposed; } + public get isDisposed(): boolean { + return this.program.isDisposed; + } public dispose(): void { dispose(this.program); @@ -130,11 +159,16 @@ export abstract class VariedTechnique implements Technique { // Confirm no empty entries in our array. let emptyShaderIndex = -1; - assert(-1 === (emptyShaderIndex = this._basicPrograms.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`); + assert( + -1 === (emptyShaderIndex = this._basicPrograms.findIndex((prog) => undefined === prog)), + `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`, + ); } private _isDisposed = false; - public get isDisposed(): boolean { return this._isDisposed; } + public get isDisposed(): boolean { + return this._isDisposed; + } public dispose(): void { if (this._isDisposed) @@ -193,7 +227,13 @@ export abstract class VariedTechnique implements Technique { assert(this._clippingPrograms[index] !== undefined); } - protected addHiliteShader(gl: WebGL2RenderingContext, instanced: IsInstanced, classified: IsClassified, posType: PositionType, create: CreateHiliter): void { + protected addHiliteShader( + gl: WebGL2RenderingContext, + instanced: IsInstanced, + classified: IsClassified, + posType: PositionType, + create: CreateHiliter, + ): void { const builder = create(instanced, classified, posType); scratchHiliteFlags.initForHilite(0, instanced, classified, posType); this.addShader(builder, scratchHiliteFlags, gl); @@ -350,7 +390,7 @@ class SurfaceTechnique extends VariedTechnique { flags.reset(featureMode, IsInstanced.No, shadowable, thematic, posType); flags.isClassified = IsClassified.Yes; - flags.isTranslucent = (0 !== translucent); + flags.isTranslucent = 0 !== translucent; const builder = createSurfaceBuilder(flags); if (flags.isTranslucent) @@ -366,7 +406,9 @@ class SurfaceTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return "Surface"; } + protected get _debugDescription() { + return "Surface"; + } public computeShaderIndex(flags: TechniqueFlags): number { assert(!(flags.isThematic && flags.isShadowable)); @@ -464,7 +506,9 @@ class PolylineTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return "Polyline"; } + protected get _debugDescription() { + return "Polyline"; + } public computeShaderIndex(flags: TechniqueFlags): number { const idxOffset = flags.positionType === "unquantized" ? PolylineTechnique._kUnquantized : 0; @@ -527,7 +571,9 @@ class EdgeTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return this._type; } + protected get _debugDescription() { + return this._type; + } public computeShaderIndex(flags: TechniqueFlags): number { let index = flags.isTranslucent ? EdgeTechnique._kTranslucent : EdgeTechnique._kOpaque; @@ -587,7 +633,9 @@ class PointStringTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return "PointString"; } + protected get _debugDescription() { + return "PointString"; + } public computeShaderIndex(flags: TechniqueFlags): number { const idxOffset = "quantized" === flags.positionType ? 0 : PointStringTechnique._kUnquantized; @@ -633,7 +681,9 @@ class PointCloudTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return "PointCloud"; } + protected get _debugDescription() { + return "PointCloud"; + } public computeShaderIndex(flags: TechniqueFlags): number { assert(flags.positionType === "quantized", "Unquantized point cloud positions not currently supported"); @@ -697,7 +747,9 @@ class RealityMeshTechnique extends VariedTechnique { this.finishConstruction(); } - protected get _debugDescription() { return "RealityMesh"; } + protected get _debugDescription() { + return "RealityMesh"; + } public computeShaderIndex(flags: TechniqueFlags): number { assert("quantized" === flags.positionType, "Unquantized reality mesh positions not currently supported."); @@ -730,7 +782,9 @@ abstract class MultipleTechnique implements Technique { private readonly _programs: ShaderProgram[] = []; private _isDisposed = false; - public get isDisposed(): boolean { return this._isDisposed; } + public get isDisposed(): boolean { + return this._isDisposed; + } public constructor(numPrograms: number) { this._programs.length = numPrograms; @@ -806,7 +860,10 @@ abstract class MultipleTechnique implements Technique { protected finishConstruction(): void { // Confirm no empty entries in our array. let emptyShaderIndex = -1; - assert(-1 === (emptyShaderIndex = this._programs.findIndex((prog) => undefined === prog)), `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`); + assert( + -1 === (emptyShaderIndex = this._programs.findIndex((prog) => undefined === prog)), + `Shader index ${emptyShaderIndex} is undefined in ${this.constructor.name}`, + ); } } @@ -831,7 +888,9 @@ class SkySphereTechnique extends MultipleTechnique { this.finishConstruction(); } - protected get _debugDescription() { return `SkySphere-${this._isGradient ? "Gradient" : "Texture"}`; } + protected get _debugDescription() { + return `SkySphere-${this._isGradient ? "Gradient" : "Texture"}`; + } public computeShaderIndex(flags: TechniqueFlags): number { let index = 0; @@ -857,16 +916,106 @@ interface PrioritizedTechniqueOrShader { const techniquesByPriority: PrioritizedTechniqueOrShader[] = [ // Compile these specific shader variations first because they seem most likely to be used immediately upon opening a file. - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.None, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: false } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Pick, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: false } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Pick, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, isTranslucent: false } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Overrides, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: false } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Overrides, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, isTranslucent: false } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.None, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: true } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Pick, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: true } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Pick, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, isTranslucent: true } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Overrides, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.No, isTranslucent: true } }, - { techniqueId: TechniqueId.Surface, specificShader: { featureMode: FeatureMode.Overrides, isInstanced: IsInstanced.No, isShadowable: IsShadowable.No, isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, isTranslucent: true } }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.None, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: false, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Pick, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: false, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Pick, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, + isTranslucent: false, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Overrides, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: false, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Overrides, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, + isTranslucent: false, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.None, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: true, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Pick, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: true, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Pick, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, + isTranslucent: true, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Overrides, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.No, + isTranslucent: true, + }, + }, + { + techniqueId: TechniqueId.Surface, + specificShader: { + featureMode: FeatureMode.Overrides, + isInstanced: IsInstanced.No, + isShadowable: IsShadowable.No, + isEdgeTestedNeeded: IsEdgeTestNeeded.Yes, + isTranslucent: true, + }, + }, // Next, compile all shaders in specific techniques. // Do surfaces first because (1) they are the most commonly used and (2) they take longer to compile. @@ -981,7 +1130,9 @@ export class Techniques implements WebGLDisposable { System.instance.frameBufferStack.markTargetsDirty(); } - public get isDisposed(): boolean { return 0 === this._list.length; } + public get isDisposed(): boolean { + return 0 === this._list.length; + } public dispose(): void { for (const tech of this._list) @@ -1018,7 +1169,13 @@ export class Techniques implements WebGLDisposable { if (pTech.specificShader !== undefined) { // if this entry consists of a specific shader, just compile that const flags = scratchTechniqueFlags; - flags.reset(pTech.specificShader.featureMode, pTech.specificShader.isInstanced, pTech.specificShader.isShadowable, IsThematic.No, "quantized"); + flags.reset( + pTech.specificShader.featureMode, + pTech.specificShader.isInstanced, + pTech.specificShader.isShadowable, + IsThematic.No, + "quantized", + ); flags.isEdgeTestNeeded = pTech.specificShader.isEdgeTestedNeeded; flags.isTranslucent = pTech.specificShader.isTranslucent; shader = tech.getShader(flags); @@ -1051,7 +1208,7 @@ export class Techniques implements WebGLDisposable { technique.forEachProgram(func); } - private constructor() { } + private constructor() {} private initializeBuiltIns(gl: WebGL2RenderingContext): void { this._list[TechniqueId.OITClearTranslucent] = new SingularTechnique(createClearTranslucentProgram(gl)); diff --git a/core/frontend/src/render/webgl/TechniqueFlags.ts b/core/frontend/src/render/webgl/TechniqueFlags.ts index fdf37c52462f..520da67db3d0 100644 --- a/core/frontend/src/render/webgl/TechniqueFlags.ts +++ b/core/frontend/src/render/webgl/TechniqueFlags.ts @@ -16,37 +16,61 @@ import { Target } from "./Target"; * @internal */ export const enum FeatureMode { - None, // no features - Pick, // feature table only - Overrides, // feature table with symbology overrides + None, // no features + Pick, // feature table only + Overrides, // feature table with symbology overrides } /** @internal */ -export const enum IsInstanced { No, Yes } +export const enum IsInstanced { + No, + Yes, +} /** @internal */ -export const enum IsAnimated { No, Yes } +export const enum IsAnimated { + No, + Yes, +} /** @internal */ -export const enum IsClassified { No, Yes } +export const enum IsClassified { + No, + Yes, +} /** @internal */ -export const enum IsEdgeTestNeeded { No, Yes } +export const enum IsEdgeTestNeeded { + No, + Yes, +} /** @internal */ -export const enum IsShadowable { No, Yes } +export const enum IsShadowable { + No, + Yes, +} /** @internal */ -export const enum IsThematic { No, Yes } +export const enum IsThematic { + No, + Yes, +} /** @internal */ -export const enum IsWiremesh { No, Yes } +export const enum IsWiremesh { + No, + Yes, +} /** @internal */ export type PositionType = "quantized" | "unquantized"; /** @internal */ -export const enum EnableAtmosphere { No, Yes } +export const enum EnableAtmosphere { + No, + Yes, +} /** Flags used to control which shader program is used by a rendering Technique. * @internal @@ -78,7 +102,18 @@ export class TechniqueFlags { return "quantized" === this.positionType; } - public init(target: Target, pass: RenderPass, instanced: IsInstanced, animated: IsAnimated = IsAnimated.No, classified = IsClassified.No, shadowable = IsShadowable.No, thematic = IsThematic.No, wiremesh = IsWiremesh.No, posType: PositionType = "quantized", enableAtmosphere = EnableAtmosphere.No): void { + public init( + target: Target, + pass: RenderPass, + instanced: IsInstanced, + animated: IsAnimated = IsAnimated.No, + classified = IsClassified.No, + shadowable = IsShadowable.No, + thematic = IsThematic.No, + wiremesh = IsWiremesh.No, + posType: PositionType = "quantized", + enableAtmosphere = EnableAtmosphere.No, + ): void { const clipStack = target.uniforms.branch.clipStack; const numClipPlanes = clipStack.hasClip ? clipStack.textureHeight : 0; this.positionType = posType; @@ -140,15 +175,23 @@ export class TechniqueFlags { this.numClipPlanes = 0; } - public get hasFeatures() { return FeatureMode.None !== this.featureMode; } + public get hasFeatures() { + return FeatureMode.None !== this.featureMode; + } - public setAnimated(animated: boolean) { this.isAnimated = animated ? IsAnimated.Yes : IsAnimated.No; } - public setInstanced(instanced: boolean) { this.isInstanced = instanced ? IsInstanced.Yes : IsInstanced.No; } + public setAnimated(animated: boolean) { + this.isAnimated = animated ? IsAnimated.Yes : IsAnimated.No; + } + public setInstanced(instanced: boolean) { + this.isInstanced = instanced ? IsInstanced.Yes : IsInstanced.No; + } public setClassified(classified: boolean) { this.isClassified = classified ? IsClassified.Yes : IsClassified.No; } - public get isHilite() { return this._isHilite; } + public get isHilite() { + return this._isHilite; + } public initForHilite(numClipPlanes: number, instanced: IsInstanced, classified: IsClassified, posType: PositionType) { this.featureMode = classified ? FeatureMode.None : FeatureMode.Overrides; this._isHilite = true; diff --git a/core/frontend/src/render/webgl/Texture.ts b/core/frontend/src/render/webgl/Texture.ts index efc5a45c3f8e..bb8b63191813 100644 --- a/core/frontend/src/render/webgl/Texture.ts +++ b/core/frontend/src/render/webgl/Texture.ts @@ -8,18 +8,26 @@ import { assert, BeEvent, dispose, Id64String } from "@itwin/core-bentley"; import { - ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, isPowerOfTwo, nextHighestPowerOfTwo, RenderTexture, TextureData, TextureTransparency, + ImageBuffer, + ImageBufferFormat, + ImageSource, + ImageSourceFormat, + isPowerOfTwo, + nextHighestPowerOfTwo, + RenderTexture, + TextureData, + TextureTransparency, } from "@itwin/core-common"; import { getImageSourceMimeType, imageBufferToPngDataUrl, imageElementFromImageSource, openImageDataUrlInNewWindow } from "../../common/ImageUtil"; -import { IModelConnection } from "../../IModelConnection"; +import { OvrFlags } from "../../common/internal/render/OvrFlags"; import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; +import { TextureOwnership } from "../CreateTextureArgs"; import { WebGLDisposable } from "./Disposable"; import { GL } from "./GL"; -import { UniformHandle } from "./UniformHandle"; import { TextureUnit } from "./RenderFlags"; import { System } from "./System"; -import { TextureOwnership } from "../CreateTextureArgs"; -import { OvrFlags } from "../../common/internal/render/OvrFlags"; +import { UniformHandle } from "./UniformHandle"; /** @internal */ export type Texture2DData = Uint8Array | Float32Array; @@ -107,7 +115,14 @@ function loadTextureCubeImageData(handle: TextureHandle, params: TextureCubeCrea // Bind the texture object; make sure we do not interfere with other active textures System.instance.activateTextureCubeMap(TextureUnit.Zero, tex); - const cubeTargets: number[] = [GL.Texture.Target.CubeMapPositiveX, GL.Texture.Target.CubeMapNegativeX, GL.Texture.Target.CubeMapPositiveY, GL.Texture.Target.CubeMapNegativeY, GL.Texture.Target.CubeMapPositiveZ, GL.Texture.Target.CubeMapNegativeZ]; + const cubeTargets: number[] = [ + GL.Texture.Target.CubeMapPositiveX, + GL.Texture.Target.CubeMapNegativeX, + GL.Texture.Target.CubeMapPositiveY, + GL.Texture.Target.CubeMapNegativeY, + GL.Texture.Target.CubeMapPositiveZ, + GL.Texture.Target.CubeMapNegativeZ, + ]; for (let i = 0; i < 6; i++) { gl.texImage2D(cubeTargets[i], 0, params.format, params.format, params.dataType, images[i]); @@ -151,8 +166,12 @@ export class Texture extends RenderTexture implements WebGLDisposable { public readonly ownership?: TextureOwnership; public transparency: TextureTransparency; - public get bytesUsed(): number { return this.texture.bytesUsed; } - public get hasOwner(): boolean { return undefined !== this.ownership; } + public get bytesUsed(): number { + return this.texture.bytesUsed; + } + public get hasOwner(): boolean { + return undefined !== this.ownership; + } public get key(): string | undefined { return typeof this.ownership !== "string" && typeof this.ownership?.key === "string" ? this.ownership.key : undefined; } @@ -164,7 +183,9 @@ export class Texture extends RenderTexture implements WebGLDisposable { this.transparency = params.handle.format === GL.Texture.Format.Rgba ? params.transparency : TextureTransparency.Opaque; } - public get isDisposed(): boolean { return this.texture.isDisposed; } + public get isDisposed(): boolean { + return this.texture.isDisposed; + } /** Free this object in the WebGL wrapper. */ public dispose() { @@ -188,12 +209,30 @@ class Texture2DCreateParams { public useMipMaps?: TextureFlag, public interpolate?: TextureFlag, public anisotropicFilter?: TextureAnisotropicFilter, - public dataBytes?: Uint8Array) { } - - public static createForData(width: number, height: number, data: Texture2DData, preserveData = false, wrapMode = GL.Texture.WrapMode.ClampToEdge, format = GL.Texture.Format.Rgba) { + public dataBytes?: Uint8Array, + ) {} + + public static createForData( + width: number, + height: number, + data: Texture2DData, + preserveData = false, + wrapMode = GL.Texture.WrapMode.ClampToEdge, + format = GL.Texture.Format.Rgba, + ) { const bytes = (preserveData && data instanceof Uint8Array) ? data : undefined; - return new Texture2DCreateParams(width, height, format, getDataType(data), wrapMode, - (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params, data), undefined, undefined, undefined, bytes); + return new Texture2DCreateParams( + width, + height, + format, + getDataType(data), + wrapMode, + (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params, data), + undefined, + undefined, + undefined, + bytes, + ); } public static createForImageBuffer(image: ImageBuffer, type: RenderTexture.Type) { @@ -201,13 +240,29 @@ class Texture2DCreateParams { if (ImageBufferFormat.Rgb === image.format) props.format = GL.Texture.Format.Rgb; - return new Texture2DCreateParams(image.width, image.height, props.format, GL.Texture.DataType.UnsignedByte, props.wrapMode, - (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params, image.data), props.useMipMaps, props.interpolate); + return new Texture2DCreateParams( + image.width, + image.height, + props.format, + GL.Texture.DataType.UnsignedByte, + props.wrapMode, + (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params, image.data), + props.useMipMaps, + props.interpolate, + ); } public static createForAttachment(width: number, height: number, format: GL.Texture.Format, dataType: GL.Texture.DataType) { - return new Texture2DCreateParams(width, height, format, dataType, GL.Texture.WrapMode.ClampToEdge, - (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params), undefined, undefined); + return new Texture2DCreateParams( + width, + height, + format, + dataType, + GL.Texture.WrapMode.ClampToEdge, + (tex: TextureHandle, params: Texture2DCreateParams) => loadTextureFromBytes(tex, params), + undefined, + undefined, + ); } public static createForImage(image: HTMLImageElement, type: RenderTexture.Type) { @@ -249,8 +304,17 @@ class Texture2DCreateParams { element = canvas; } - return new Texture2DCreateParams(targetWidth, targetHeight, props.format, GL.Texture.DataType.UnsignedByte, props.wrapMode, - (tex: TextureHandle, params: Texture2DCreateParams) => loadTexture2DImageData(tex, params, undefined, element), props.useMipMaps, props.interpolate, props.anisotropicFilter); + return new Texture2DCreateParams( + targetWidth, + targetHeight, + props.format, + GL.Texture.DataType.UnsignedByte, + props.wrapMode, + (tex: TextureHandle, params: Texture2DCreateParams) => loadTexture2DImageData(tex, params, undefined, element), + props.useMipMaps, + props.interpolate, + props.anisotropicFilter, + ); } public static createForImageBitmap(image: ImageBitmap, type: RenderTexture.Type) { @@ -286,8 +350,17 @@ class Texture2DCreateParams { source = canvas; } - return new Texture2DCreateParams(targetWidth, targetHeight, props.format, GL.Texture.DataType.UnsignedByte, props.wrapMode, - (tex: TextureHandle, params: Texture2DCreateParams) => loadTexture2DImageData(tex, params, undefined, source), props.useMipMaps, props.interpolate, props.anisotropicFilter); + return new Texture2DCreateParams( + targetWidth, + targetHeight, + props.format, + GL.Texture.DataType.UnsignedByte, + props.wrapMode, + (tex: TextureHandle, params: Texture2DCreateParams) => loadTexture2DImageData(tex, params, undefined, source), + props.useMipMaps, + props.interpolate, + props.anisotropicFilter, + ); } private static getImageProperties(type: RenderTexture.Type): TextureImageProperties { @@ -308,8 +381,14 @@ class Texture2DCreateParams { return { format, wrapMode, useMipMaps, interpolate, anisotropicFilter }; } - public static readonly placeholderParams = new Texture2DCreateParams(1, 1, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte, GL.Texture.WrapMode.ClampToEdge, - (_tex: TextureHandle, _params: Texture2DCreateParams) => undefined); + public static readonly placeholderParams = new Texture2DCreateParams( + 1, + 1, + GL.Texture.Format.Rgba, + GL.Texture.DataType.UnsignedByte, + GL.Texture.WrapMode.ClampToEdge, + (_tex: TextureHandle, _params: Texture2DCreateParams) => undefined, + ); } class TextureCubeCreateParams { @@ -318,9 +397,17 @@ class TextureCubeCreateParams { public format: GL.Texture.Format, public dataType: GL.Texture.DataType, public wrapMode: GL.Texture.WrapMode, - public loadImageData: LoadCubeImageData) { } - - public static createForCubeImages(posX: HTMLImageElement, negX: HTMLImageElement, posY: HTMLImageElement, negY: HTMLImageElement, posZ: HTMLImageElement, negZ: HTMLImageElement): TextureCubeCreateParams | undefined { + public loadImageData: LoadCubeImageData, + ) {} + + public static createForCubeImages( + posX: HTMLImageElement, + negX: HTMLImageElement, + posY: HTMLImageElement, + negY: HTMLImageElement, + posZ: HTMLImageElement, + negZ: HTMLImageElement, + ): TextureCubeCreateParams | undefined { const targetDim = posX.naturalWidth; if (posX.naturalHeight !== targetDim) // Cube texture dimensions must match (width must equal height) @@ -333,8 +420,13 @@ class TextureCubeCreateParams { return undefined; } - return new TextureCubeCreateParams(targetDim, GL.Texture.Format.Rgba, GL.Texture.DataType.UnsignedByte, GL.Texture.WrapMode.ClampToEdge, - (tex: TextureHandle, params: TextureCubeCreateParams) => loadTextureCubeImageData(tex, params, images)); + return new TextureCubeCreateParams( + targetDim, + GL.Texture.Format.Rgba, + GL.Texture.DataType.UnsignedByte, + GL.Texture.WrapMode.ClampToEdge, + (tex: TextureHandle, params: TextureCubeCreateParams) => loadTextureCubeImageData(tex, params, images), + ); } } @@ -350,14 +442,18 @@ export abstract class TextureHandle implements WebGLDisposable { public abstract get format(): GL.Texture.Format; public abstract get dataType(): GL.Texture.DataType; public abstract get dataBytes(): Uint8Array | undefined; - public get bytesUsed(): number { return this._bytesUsed; } + public get bytesUsed(): number { + return this._bytesUsed; + } public set bytesUsed(bytesUsed: number) { // assert(0 === this.bytesUsed); this._bytesUsed = bytesUsed; } /** Get the WebGLTexture for this TextureHandle. */ - public getHandle(): WebGLTexture | undefined { return this._glTexture; } + public getHandle(): WebGLTexture | undefined { + return this._glTexture; + } /** Bind texture handle (if available) associated with an instantiation of this class to specified texture unit. */ public abstract bind(_texUnit: TextureUnit): boolean; @@ -365,7 +461,9 @@ export abstract class TextureHandle implements WebGLDisposable { /** Bind this texture to a uniform sampler. */ public abstract bindSampler(_uniform: UniformHandle, _unit: TextureUnit): void; - public get isDisposed(): boolean { return this._glTexture === undefined; } + public get isDisposed(): boolean { + return this._glTexture === undefined; + } public dispose() { if (!this.isDisposed) { @@ -381,7 +479,14 @@ export abstract class TextureHandle implements WebGLDisposable { } /** Create a 2D texture to hold non-image data */ - public static createForData(width: number, height: number, data: Texture2DData, wantPreserveData = false, wrapMode = GL.Texture.WrapMode.ClampToEdge, format = GL.Texture.Format.Rgba) { + public static createForData( + width: number, + height: number, + data: Texture2DData, + wantPreserveData = false, + wrapMode = GL.Texture.WrapMode.ClampToEdge, + format = GL.Texture.Format.Rgba, + ) { return Texture2DHandle.createForData(width, height, data, wantPreserveData, wrapMode, format); } @@ -401,11 +506,24 @@ export abstract class TextureHandle implements WebGLDisposable { } /** Create a cube map texture from six HTMLImageElement objects. */ - public static createForCubeImages(posX: HTMLImageElement, negX: HTMLImageElement, posY: HTMLImageElement, negY: HTMLImageElement, posZ: HTMLImageElement, negZ: HTMLImageElement) { + public static createForCubeImages( + posX: HTMLImageElement, + negX: HTMLImageElement, + posY: HTMLImageElement, + negY: HTMLImageElement, + posZ: HTMLImageElement, + negZ: HTMLImageElement, + ) { return TextureCubeHandle.createForCubeImages(posX, negX, posY, negY, posZ, negZ); } - public static createForElement(id: Id64String, imodel: IModelConnection, type: RenderTexture.Type, format: ImageSourceFormat, onLoaded: ExternalTextureLoadCallback) { + public static createForElement( + id: Id64String, + imodel: IModelConnection, + type: RenderTexture.Type, + format: ImageSourceFormat, + onLoaded: ExternalTextureLoadCallback, + ) { return Texture2DHandle.createForElement(id, imodel, type, format, onLoaded); } @@ -443,11 +561,21 @@ export class Texture2DHandle extends TextureHandle { private _dataType: GL.Texture.DataType; private _dataBytes?: Uint8Array; - public get width(): number { return this._width; } - public get height(): number { return this._height; } - public get format(): GL.Texture.Format { return this._format; } - public get dataType(): GL.Texture.DataType { return this._dataType; } - public get dataBytes(): Uint8Array | undefined { return this._dataBytes; } + public get width(): number { + return this._width; + } + public get height(): number { + return this._height; + } + public get format(): GL.Texture.Format { + return this._format; + } + public get dataType(): GL.Texture.DataType { + return this._dataType; + } + public get dataBytes(): Uint8Array | undefined { + return this._dataBytes; + } /** Bind specified texture handle to specified texture unit. */ public static bindTexture(texUnit: TextureUnit, glTex: WebGLTexture | undefined) { @@ -519,7 +647,14 @@ export class Texture2DHandle extends TextureHandle { } /** Create a texture to hold non-image data */ - public static override createForData(width: number, height: number, data: Texture2DData, wantPreserveData = false, wrapMode = GL.Texture.WrapMode.ClampToEdge, format = GL.Texture.Format.Rgba) { + public static override createForData( + width: number, + height: number, + data: Texture2DData, + wantPreserveData = false, + wrapMode = GL.Texture.WrapMode.ClampToEdge, + format = GL.Texture.Format.Rgba, + ) { return this.create(Texture2DCreateParams.createForData(width, height, data, wantPreserveData, wrapMode, format)); } @@ -543,7 +678,13 @@ export class Texture2DHandle extends TextureHandle { private static _placeHolderTextureData = new Uint8Array([128, 128, 128, 255]); - public static override createForElement(id: Id64String, imodel: IModelConnection, type: RenderTexture.Type, format: ImageSourceFormat, onLoaded: ExternalTextureLoadCallback) { + public static override createForElement( + id: Id64String, + imodel: IModelConnection, + type: RenderTexture.Type, + format: ImageSourceFormat, + onLoaded: ExternalTextureLoadCallback, + ) { // set a placeholder texture while we wait for the external texture to load const handle = this.createForData(1, 1, this._placeHolderTextureData, undefined, undefined, GL.Texture.Format.Rgba); @@ -598,7 +739,8 @@ interface TextureConvertRequest { } /** @internal */ -export class ExternalTextureLoader { /* currently exported for tests only */ +export class ExternalTextureLoader { + /* currently exported for tests only */ public static readonly instance = new ExternalTextureLoader(2); public readonly onTexturesLoaded = new BeEvent<() => void>(); private readonly _maxActiveRequests: number; @@ -607,9 +749,15 @@ export class ExternalTextureLoader { /* currently exported for tests only */ private _convertRequests: Array = []; private _convertPending = false; - public get numActiveRequests() { return this._activeRequests.length; } - public get numPendingRequests() { return this._pendingRequests.length; } - public get maxActiveRequests() { return this._maxActiveRequests; } + public get numActiveRequests() { + return this._activeRequests.length; + } + public get numPendingRequests() { + return this._pendingRequests.length; + } + public get maxActiveRequests() { + return this._maxActiveRequests; + } private constructor(maxActiveRequests: number) { this._maxActiveRequests = maxActiveRequests; @@ -651,7 +799,7 @@ export class ExternalTextureLoader { /* currently exported for tests only */ } } } - } catch (_e) { } + } catch (_e) {} return this._nextRequest(req); } @@ -675,7 +823,7 @@ export class ExternalTextureLoader { /* currently exported for tests only */ } } } - } catch (_e) { } + } catch (_e) {} this._convertPending = false; } @@ -691,7 +839,14 @@ export class ExternalTextureLoader { /* currently exported for tests only */ return false; } - public loadTexture(handle: Texture2DHandle, name: Id64String, imodel: IModelConnection, type: RenderTexture.Type, format: ImageSourceFormat, onLoaded?: ExternalTextureLoadCallback) { + public loadTexture( + handle: Texture2DHandle, + name: Id64String, + imodel: IModelConnection, + type: RenderTexture.Type, + format: ImageSourceFormat, + onLoaded?: ExternalTextureLoadCallback, + ) { const req = { handle, name, imodel, type, format, onLoaded }; if (this._requestExists(req)) return; @@ -709,11 +864,21 @@ export class TextureCubeHandle extends TextureHandle { private _format: GL.Texture.Format; // Format must be the same for each of the six faces. private _dataType: GL.Texture.DataType; // Type must be the same for each of the six faces. - public get width(): number { return this._dim; } - public get height(): number { return this._dim; } - public get format(): GL.Texture.Format { return this._format; } - public get dataType(): GL.Texture.DataType { return this._dataType; } - public get dataBytes(): Uint8Array | undefined { return undefined; } + public get width(): number { + return this._dim; + } + public get height(): number { + return this._dim; + } + public get format(): GL.Texture.Format { + return this._format; + } + public get dataType(): GL.Texture.DataType { + return this._dataType; + } + public get dataBytes(): Uint8Array | undefined { + return undefined; + } /** Bind specified cubemap texture handle to specified texture unit. */ public static bindTexture(texUnit: TextureUnit, glTex: WebGLTexture | undefined) { @@ -748,7 +913,14 @@ export class TextureCubeHandle extends TextureHandle { } /** Create a cube map texture from six HTMLImageElement objects. */ - public static override createForCubeImages(posX: HTMLImageElement, negX: HTMLImageElement, posY: HTMLImageElement, negY: HTMLImageElement, posZ: HTMLImageElement, negZ: HTMLImageElement) { + public static override createForCubeImages( + posX: HTMLImageElement, + negX: HTMLImageElement, + posY: HTMLImageElement, + negY: HTMLImageElement, + posZ: HTMLImageElement, + negZ: HTMLImageElement, + ) { const params = TextureCubeCreateParams.createForCubeImages(posX, negX, posY, negY, posZ, negZ); return params !== undefined ? this.create(params) : undefined; } @@ -768,7 +940,9 @@ export class Texture2DDataUpdater { public data: Uint8Array; public modified: boolean = false; - public constructor(data: Uint8Array) { this.data = data; } + public constructor(data: Uint8Array) { + this.data = data; + } public setByteAtIndex(index: number, byte: number) { assert(index < this.data.length); diff --git a/core/frontend/src/render/webgl/TextureDrape.ts b/core/frontend/src/render/webgl/TextureDrape.ts index 48f6f6192ac0..6c6a1499d4a4 100644 --- a/core/frontend/src/render/webgl/TextureDrape.ts +++ b/core/frontend/src/render/webgl/TextureDrape.ts @@ -17,18 +17,26 @@ import { Texture } from "./Texture"; export abstract class TextureDrape implements RenderTextureDrape, RenderMemory.Consumer, WebGLDisposable { protected _texture?: Texture; protected _projectionMatrix = Matrix4d.createIdentity(); - public get texture(): Texture | undefined { return this._texture; } - public get projectionMatrix(): Matrix4d { return this._projectionMatrix; } + public get texture(): Texture | undefined { + return this._texture; + } + public get projectionMatrix(): Matrix4d { + return this._projectionMatrix; + } public abstract collectGraphics(context: SceneContext): void; public abstract draw(target: Target): void; - public get isReady(): boolean { return this._texture !== undefined; } + public get isReady(): boolean { + return this._texture !== undefined; + } public collectStatistics(stats: RenderMemory.Statistics): void { if (undefined !== this._texture) stats.addPlanarClassifier(this._texture.bytesUsed); } - public get isDisposed(): boolean { return undefined === this.texture; } + public get isDisposed(): boolean { + return undefined === this.texture; + } public dispose() { this._texture = dispose(this._texture); diff --git a/core/frontend/src/render/webgl/ThematicSensors.ts b/core/frontend/src/render/webgl/ThematicSensors.ts index 6cd09e628b77..7504ae8d640c 100644 --- a/core/frontend/src/render/webgl/ThematicSensors.ts +++ b/core/frontend/src/render/webgl/ThematicSensors.ts @@ -7,14 +7,14 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ThematicDisplaySensor, ThematicDisplaySensorSettings } from "@itwin/core-common"; +import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { WebGLDisposable } from "./Disposable"; import { GL } from "./GL"; -import { Texture2DData, Texture2DHandle } from "./Texture"; -import { UniformHandle } from "./UniformHandle"; import { TextureUnit } from "./RenderFlags"; import { Target } from "./Target"; +import { Texture2DData, Texture2DHandle } from "./Texture"; +import { UniformHandle } from "./UniformHandle"; /** @internal */ interface ThematicSensorsTexture { @@ -36,7 +36,9 @@ export class ThematicSensors implements WebGLDisposable { public readonly range: Range3d; public readonly sensorSettings?: ThematicDisplaySensorSettings; - public get numSensors(): number { return this._sensors.length; } + public get numSensors(): number { + return this._sensors.length; + } private _sensors: ThematicDisplaySensor[]; private readonly _viewMatrix = Transform.createIdentity(); @@ -53,7 +55,8 @@ export class ThematicSensors implements WebGLDisposable { target.plan.thematic.sensorSettings.sensors, range, target.currentTransform, - target.plan.thematic.sensorSettings.distanceCutoff); + target.plan.thematic.sensorSettings.distanceCutoff, + ); } const obj = this.createFloat(target, range, sensors); @@ -61,7 +64,9 @@ export class ThematicSensors implements WebGLDisposable { return obj; } - public get isDisposed(): boolean { return this._texture.handle.isDisposed; } + public get isDisposed(): boolean { + return this._texture.handle.isDisposed; + } public dispose(): void { dispose(this._texture.handle); @@ -75,9 +80,13 @@ export class ThematicSensors implements WebGLDisposable { this._texture.handle.bindSampler(uniform, TextureUnit.ThematicSensors); } - public get bytesUsed(): number { return this._texture.handle.bytesUsed; } + public get bytesUsed(): number { + return this._texture.handle.bytesUsed; + } - public get texture(): Texture2DHandle { return this._texture.handle; } + public get texture(): Texture2DHandle { + return this._texture.handle; + } private _update(viewMatrix: Transform) { this._viewMatrix.setFrom(viewMatrix); @@ -114,7 +123,9 @@ export class ThematicSensors implements WebGLDisposable { return new this({ handle, data }, target, range, sensors); } - protected append(value: number) { this.appendFloat(value); } + protected append(value: number) { + this.appendFloat(value); + } protected appendFloat(value: number): void { this._view.setFloat32(this._curPos, value, true); @@ -126,8 +137,12 @@ export class ThematicSensors implements WebGLDisposable { this.advance(1); } - private advance(numBytes: number): void { this._curPos += numBytes; } - private reset(): void { this._curPos = 0; } + private advance(numBytes: number): void { + this._curPos += numBytes; + } + private reset(): void { + this._curPos = 0; + } private appendValues(a: number, b: number, c: number, d: number) { this.append(a); @@ -136,7 +151,9 @@ export class ThematicSensors implements WebGLDisposable { this.append(d); } - private appendSensor(position: Point3d, value: number): void { this.appendValues(position.x, position.y, position.z, value); } + private appendSensor(position: Point3d, value: number): void { + this.appendValues(position.x, position.y, position.z, value); + } } function _sensorRadiusAffectsRange(sensor: ThematicDisplaySensor, sensorRadius: number, range: Range3d) { @@ -146,7 +163,12 @@ function _sensorRadiusAffectsRange(sensor: ThematicDisplaySensor, sensorRadius: const scratchRange = Range3d.createNull(); -function _accumulateSensorsInRange(sensors: ThematicDisplaySensor[], range: Range3d, transform: Transform, distanceCutoff: number): ThematicDisplaySensor[] { +function _accumulateSensorsInRange( + sensors: ThematicDisplaySensor[], + range: Range3d, + transform: Transform, + distanceCutoff: number, +): ThematicDisplaySensor[] { const retSensors: ThematicDisplaySensor[] = []; transform.multiplyRange(range, scratchRange); diff --git a/core/frontend/src/render/webgl/ThematicUniforms.ts b/core/frontend/src/render/webgl/ThematicUniforms.ts index ebf40611addf..14b1ce69d769 100644 --- a/core/frontend/src/render/webgl/ThematicUniforms.ts +++ b/core/frontend/src/render/webgl/ThematicUniforms.ts @@ -8,18 +8,23 @@ import { assert, dispose } from "@itwin/core-bentley"; import { - Gradient, RenderTexture, ThematicDisplay, ThematicDisplayMode, ThematicGradientMode, ThematicGradientTransparencyMode, + Gradient, + RenderTexture, + ThematicDisplay, + ThematicDisplayMode, + ThematicGradientMode, + ThematicGradientTransparencyMode, } from "@itwin/core-common"; +import { Angle, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { WebGLDisposable } from "./Disposable"; -import { UniformHandle } from "./UniformHandle"; +import { FloatRgba } from "./FloatRGBA"; import { TextureUnit } from "./RenderFlags"; import { desync, sync } from "./Sync"; +import { System } from "./System"; +import { Target } from "./Target"; import { TextureHandle } from "./Texture"; import { ThematicSensors } from "./ThematicSensors"; -import { Angle, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; -import { Target } from "./Target"; -import { System } from "./System"; -import { FloatRgba } from "./FloatRGBA"; +import { UniformHandle } from "./UniformHandle"; /** Maintains state for uniforms related to thematic display. * @internal @@ -40,7 +45,9 @@ export class ThematicUniforms implements WebGLDisposable { public syncKey = 0; - private get _distanceCutoff(): number { return this._fragSettings[1]; } + private get _distanceCutoff(): number { + return this._fragSettings[1]; + } public get thematicDisplay(): ThematicDisplay | undefined { return this._thematicDisplay; @@ -122,7 +129,10 @@ export class ThematicUniforms implements WebGLDisposable { this._colorMix = this.thematicDisplay.gradientSettings.colorMix; - this._updateAxis(this.thematicDisplay.axis, (ThematicDisplayMode.Slope === this.thematicDisplay.displayMode) ? target.uniforms.frustum.viewMatrix : undefined); + this._updateAxis( + this.thematicDisplay.axis, + (ThematicDisplayMode.Slope === this.thematicDisplay.displayMode) ? target.uniforms.frustum.viewMatrix : undefined, + ); if (ThematicDisplayMode.HillShade === this.thematicDisplay.displayMode) this._updateSunDirection(this.thematicDisplay.sunDirection, target.uniforms.frustum.viewMatrix); diff --git a/core/frontend/src/render/webgl/UniformHandle.ts b/core/frontend/src/render/webgl/UniformHandle.ts index 39f7aa41fce2..768c76d4a788 100644 --- a/core/frontend/src/render/webgl/UniformHandle.ts +++ b/core/frontend/src/render/webgl/UniformHandle.ts @@ -13,7 +13,7 @@ import { ShaderProgram } from "./ShaderProgram"; import { SyncToken } from "./Sync"; import { System } from "./System"; -const enum DataType {// eslint-disable-line no-restricted-syntax +const enum DataType { // eslint-disable-line no-restricted-syntax Undefined, // eslint-disable-line id-blacklist Mat3, Mat4, @@ -36,7 +36,9 @@ export class UniformHandle { private readonly _data: number[] = []; public syncToken?: SyncToken; - private constructor(location: WebGLUniformLocation | null) { this._location = location; } + private constructor(location: WebGLUniformLocation | null) { + this._location = location; + } public static create(program: ShaderProgram, name: string): UniformHandle { let location = null; diff --git a/core/frontend/src/render/webgl/VertexLUT.ts b/core/frontend/src/render/webgl/VertexLUT.ts index e61fb10922db..54b974fc71b7 100644 --- a/core/frontend/src/render/webgl/VertexLUT.ts +++ b/core/frontend/src/render/webgl/VertexLUT.ts @@ -8,12 +8,12 @@ import { dispose } from "@itwin/core-bentley"; import { QParams2d, QParams3d } from "@itwin/core-common"; +import { AuxChannel, AuxChannelTable, AuxDisplacementChannel, AuxParamChannel } from "../../common/internal/render/AuxChannelTable"; import { VertexTable } from "../../common/internal/render/VertexTable"; +import { qorigin3dToArray, qparams2dToArray, qscale3dToArray } from "./AttributeBuffers"; import { ColorInfo } from "./ColorInfo"; import { WebGLDisposable } from "./Disposable"; -import { qorigin3dToArray, qparams2dToArray, qscale3dToArray } from "./AttributeBuffers"; import { TextureHandle } from "./Texture"; -import { AuxChannel, AuxChannelTable, AuxDisplacementChannel, AuxParamChannel } from "../../common/internal/render/AuxChannelTable"; type ChannelPropName = "normals" | "displacements" | "params"; @@ -50,10 +50,16 @@ export class AuxChannelLUT implements WebGLDisposable { map.set(channel.name, channel as T); } - public get bytesUsed(): number { return this.texture.bytesUsed; } - public get hasScalarAnimation() { return undefined !== this.params; } + public get bytesUsed(): number { + return this.texture.bytesUsed; + } + public get hasScalarAnimation() { + return undefined !== this.params; + } - public get isDisposed(): boolean { return this.texture.isDisposed; } + public get isDisposed(): boolean { + return this.texture.isDisposed; + } public dispose() { dispose(this.texture); @@ -74,13 +80,17 @@ export class VertexLUT implements WebGLDisposable { public readonly numRgbaPerVertex: number; public readonly colorInfo: ColorInfo; public readonly usesQuantizedPositions: boolean; // If true, positions are 16-bit integers quantized to qOrigin and qScale; otherwise they are unquantized 32-bit floats. - public readonly qOrigin: Float32Array; // Origin of quantized range - public readonly qScale: Float32Array; // Scale of quantized range + public readonly qOrigin: Float32Array; // Origin of quantized range + public readonly qScale: Float32Array; // Scale of quantized range public readonly uvQParams?: Float32Array; // If vertices contain texture UV params, quantization parameters as [origin.x, origin.y, scale.x, scale.y ] public readonly auxChannels?: AuxChannelLUT; - public get hasAnimation() { return undefined !== this.auxChannels; } - public get hasScalarAnimation() { return undefined !== this.auxChannels && this.auxChannels.hasScalarAnimation; } + public get hasAnimation() { + return undefined !== this.auxChannels; + } + public get hasScalarAnimation() { + return undefined !== this.auxChannels && this.auxChannels.hasScalarAnimation; + } public get bytesUsed(): number { let bytesUsed = this.texture.bytesUsed; @@ -99,7 +109,15 @@ export class VertexLUT implements WebGLDisposable { return new VertexLUT(texture, vt, ColorInfo.createFromVertexTable(vt), vt.qparams, !vt.usesUnquantizedPositions, vt.uvParams, auxLUT); } - private constructor(texture: TextureHandle, table: VertexTable, colorInfo: ColorInfo, qparams: QParams3d, positionsAreQuantized: boolean, uvParams?: QParams2d, auxChannels?: AuxChannelLUT) { + private constructor( + texture: TextureHandle, + table: VertexTable, + colorInfo: ColorInfo, + qparams: QParams3d, + positionsAreQuantized: boolean, + uvParams?: QParams2d, + auxChannels?: AuxChannelLUT, + ) { this.texture = texture; this.numVertices = table.numVertices; this.numRgbaPerVertex = table.numRgbaPerVertex; @@ -113,7 +131,9 @@ export class VertexLUT implements WebGLDisposable { this.uvQParams = qparams2dToArray(uvParams); } - public get isDisposed(): boolean { return this.texture.isDisposed; } + public get isDisposed(): boolean { + return this.texture.isDisposed; + } public dispose() { dispose(this.texture); diff --git a/core/frontend/src/render/webgl/ViewRectUniforms.ts b/core/frontend/src/render/webgl/ViewRectUniforms.ts index 0fe522fd5e2a..bc2b1d67a707 100644 --- a/core/frontend/src/render/webgl/ViewRectUniforms.ts +++ b/core/frontend/src/render/webgl/ViewRectUniforms.ts @@ -7,9 +7,9 @@ */ import { Matrix4d } from "@itwin/core-geometry"; -import { UniformHandle } from "./UniformHandle"; import { Matrix4 } from "./Matrix"; import { desync, sync } from "./Sync"; +import { UniformHandle } from "./UniformHandle"; /** Maintains uniform variable state associated with a Target's ViewRect. * @internal @@ -19,8 +19,8 @@ export class ViewRectUniforms { public readonly projectionMatrix = Matrix4d.createIdentity(); public readonly projectionMatrix32 = new Matrix4(); - private readonly _dimensions = [ 0, 0 ]; - private readonly _inverseDimensions = [ 0, 0 ]; + private readonly _dimensions = [0, 0]; + private readonly _inverseDimensions = [0, 0]; private readonly _viewportMatrix = new Matrix4(); public update(width: number, height: number): void { @@ -55,15 +55,32 @@ export class ViewRectUniforms { const column3Row3 = 1.0; Matrix4.fromValues( - column0Row0, 0.0, 0.0, column3Row0, - 0.0, column1Row1, 0.0, column3Row1, - 0.0, 0.0, column2Row2, column3Row2, - 0.0, 0.0, 0.0, column3Row3, - this._viewportMatrix); + column0Row0, + 0.0, + 0.0, + column3Row0, + 0.0, + column1Row1, + 0.0, + column3Row1, + 0.0, + 0.0, + column2Row2, + column3Row2, + 0.0, + 0.0, + 0.0, + column3Row3, + this._viewportMatrix, + ); } - public get width() { return this._dimensions[0]; } - public get height() { return this._dimensions[1]; } + public get width() { + return this._dimensions[0]; + } + public get height() { + return this._dimensions[1]; + } public bindProjectionMatrix(uniform: UniformHandle): void { if (!sync(this, uniform)) diff --git a/core/frontend/src/render/webgl/VisibleTileFeatures.ts b/core/frontend/src/render/webgl/VisibleTileFeatures.ts index 05a44ebac083..2a8c542ccfa1 100644 --- a/core/frontend/src/render/webgl/VisibleTileFeatures.ts +++ b/core/frontend/src/render/webgl/VisibleTileFeatures.ts @@ -10,8 +10,8 @@ import { Id64 } from "@itwin/core-bentley"; import { BatchType, PackedFeature } from "@itwin/core-common"; import { IModelConnection } from "../../IModelConnection"; import { QueryTileFeaturesOptions, VisibleFeature } from "../VisibleFeature"; -import { RenderPass } from "./RenderFlags"; import { RenderCommands } from "./RenderCommands"; +import { RenderPass } from "./RenderFlags"; import { ShaderProgramExecutor } from "./ShaderProgram"; import { Target } from "./Target"; @@ -56,11 +56,16 @@ function isFeatureVisible(feature: PackedFeature, target: Target, includeNonLoca const app = target.currentBranch.getFeatureAppearance( ovrs, - feature.elementId.lower, feature.elementId.upper, - feature.subCategoryId.lower, feature.subCategoryId.upper, + feature.elementId.lower, + feature.elementId.upper, + feature.subCategoryId.lower, + feature.subCategoryId.upper, feature.geometryClass, - feature.modelId.lower, feature.modelId.upper, - BatchType.Primary, feature.animationNodeId); + feature.modelId.lower, + feature.modelId.upper, + BatchType.Primary, + feature.animationNodeId, + ); return undefined !== app && (includeNonLocatable || !app.nonLocatable); } diff --git a/core/frontend/src/render/webgl/glsl/AmbientOcclusion.ts b/core/frontend/src/render/webgl/glsl/AmbientOcclusion.ts index aa660f91f745..ee95e452a327 100644 --- a/core/frontend/src/render/webgl/glsl/AmbientOcclusion.ts +++ b/core/frontend/src/render/webgl/glsl/AmbientOcclusion.ts @@ -233,9 +233,12 @@ export function createAmbientOcclusionProgram(context: WebGL2RenderingContext): }); }); - frag.set(FragmentShaderComponent.ComputeBaseColor, shouldUseDB ? - computeAmbientOcclusionPrefixDB + computeAmbientOcclusion : - computeAmbientOcclusionPrefixPB + computeAmbientOcclusion); + frag.set( + FragmentShaderComponent.ComputeBaseColor, + shouldUseDB ? + computeAmbientOcclusionPrefixDB + computeAmbientOcclusion : + computeAmbientOcclusionPrefixPB + computeAmbientOcclusion, + ); frag.set(FragmentShaderComponent.AssignFragData, assignFragColor); frag.addUniform("u_pickDepthAndOrder", VariableType.Sampler2D, (prog) => { @@ -283,7 +286,8 @@ export function createAmbientOcclusionProgram(context: WebGL2RenderingContext): params.target.ambientOcclusionSettings.bias, params.target.ambientOcclusionSettings.zLengthCap, params.target.ambientOcclusionSettings.intensity, - params.target.ambientOcclusionSettings.texelStepSize]); + params.target.ambientOcclusionSettings.texelStepSize, + ]); uniform.setUniform4fv(hbaoSettings); }); }, VariablePrecision.High); diff --git a/core/frontend/src/render/webgl/glsl/Animation.ts b/core/frontend/src/render/webgl/glsl/Animation.ts index 539419eb5777..27adebf5b4de 100644 --- a/core/frontend/src/render/webgl/glsl/Animation.ts +++ b/core/frontend/src/render/webgl/glsl/Animation.ts @@ -8,12 +8,12 @@ import { assert } from "@itwin/core-bentley"; import { AnalysisStyleDisplacement, AnalysisStyleThematic, ThematicGradientSettings } from "@itwin/core-common"; +import { AuxChannel, AuxDisplacementChannel, AuxParamChannel } from "../../../common/internal/render/AuxChannelTable"; import { DrawParams } from "../DrawCommand"; import { TextureUnit } from "../RenderFlags"; import { VariableType, VertexShaderBuilder, VertexShaderComponent } from "../ShaderBuilder"; import { octDecodeNormal } from "./Surface"; import { unquantizePosition } from "./Vertex"; -import { AuxChannel, AuxDisplacementChannel, AuxParamChannel } from "../../../common/internal/render/AuxChannelTable"; const initialize = ` g_anim_step = vec2(1.0) / u_animLUTParams.xy; @@ -133,9 +133,10 @@ const scratchAnimParams = [ function getAnimParams(size: 2 | 3, initialValue?: number): Float32Array { const array = scratchAnimParams[size]!; - if (undefined !== initialValue) + if (undefined !== initialValue) { for (let i = 0; i < array.length; i++) array[i] = initialValue; + } return array; } @@ -232,9 +233,10 @@ export function addAnimation(vert: VertexShaderBuilder, isSurface: boolean): voi prog.addGraphicUniform("u_qAnimDispScale", (uniform, params) => { const animParams = getAnimParams(3, 0.0); const disp = getDisplacementChannel(params); - if (undefined !== disp) + if (undefined !== disp) { for (let i = 0; i < 3; i++) animParams[i] = disp.channel.qScale[i] * disp.displacement.scale; + } uniform.setUniform3fv(animParams); }); @@ -243,9 +245,10 @@ export function addAnimation(vert: VertexShaderBuilder, isSurface: boolean): voi prog.addGraphicUniform("u_qAnimDispOrigin", (uniform, params) => { const animParams = getAnimParams(3, 0.0); const disp = getDisplacementChannel(params); - if (undefined !== disp) + if (undefined !== disp) { for (let i = 0; i < 3; i++) animParams[i] = disp.channel.qOrigin[i] * disp.displacement.scale; + } uniform.setUniform3fv(animParams); }); diff --git a/core/frontend/src/render/webgl/glsl/Blur.ts b/core/frontend/src/render/webgl/glsl/Blur.ts index c0e654ffc6c1..b33e4171988a 100644 --- a/core/frontend/src/render/webgl/glsl/Blur.ts +++ b/core/frontend/src/render/webgl/glsl/Blur.ts @@ -97,7 +97,8 @@ export function createBlurProgram(context: WebGL2RenderingContext, type: BlurTyp // ###TODO: If we want to apply this blur shader to situations other than AO, we should move these settings away from the ambient occlusion params. params.target.ambientOcclusionSettings.blurDelta, params.target.ambientOcclusionSettings.blurSigma, - params.target.ambientOcclusionSettings.blurTexelStepSize]); + params.target.ambientOcclusionSettings.blurTexelStepSize, + ]); uniform.setUniform3fv(hbaoSettings); }); }, VariablePrecision.High); diff --git a/core/frontend/src/render/webgl/glsl/Common.ts b/core/frontend/src/render/webgl/glsl/Common.ts index f8d714734d51..77c2f6b7f511 100644 --- a/core/frontend/src/render/webgl/glsl/Common.ts +++ b/core/frontend/src/render/webgl/glsl/Common.ts @@ -8,9 +8,9 @@ import { RenderType } from "@itwin/webgl-compatibility"; import { DrawParams } from "../DrawCommand"; -import { UniformHandle } from "../UniformHandle"; import { ProgramBuilder, ShaderBuilder, ShaderType, VariableType } from "../ShaderBuilder"; import { System } from "../System"; +import { UniformHandle } from "../UniformHandle"; import { addModelViewMatrix } from "./Vertex"; // These are not used anywhere currently, but will leave them here commented out in case we want them later. diff --git a/core/frontend/src/render/webgl/glsl/Contours.ts b/core/frontend/src/render/webgl/glsl/Contours.ts index 3a272c7b1479..bdef58e0fcc4 100644 --- a/core/frontend/src/render/webgl/glsl/Contours.ts +++ b/core/frontend/src/render/webgl/glsl/Contours.ts @@ -7,9 +7,7 @@ */ import { ContourDisplay } from "@itwin/core-common"; import { TextureUnit } from "../RenderFlags"; -import { - FragmentShaderComponent, ProgramBuilder, VariableType, -} from "../ShaderBuilder"; +import { FragmentShaderComponent, ProgramBuilder, VariableType } from "../ShaderBuilder"; import { addFeatureIndex } from "./FeatureSymbology"; import { addInstancedRtcMatrix } from "./Vertex"; diff --git a/core/frontend/src/render/webgl/glsl/CopyColor.ts b/core/frontend/src/render/webgl/glsl/CopyColor.ts index 209ba824b787..701b14abf5c1 100644 --- a/core/frontend/src/render/webgl/glsl/CopyColor.ts +++ b/core/frontend/src/render/webgl/glsl/CopyColor.ts @@ -48,7 +48,7 @@ export function createCopyColorProgram(context: WebGL2RenderingContext, copyAlph }); } - const flagString = (copyAlpha ? "-CopyAlpha" : "-NoAlpha"); + const flagString = copyAlpha ? "-CopyAlpha" : "-NoAlpha"; builder.vert.headerComment = `//!V! CopyColor${flagString}`; builder.frag.headerComment = `//!F! CopyColor${flagString}`; diff --git a/core/frontend/src/render/webgl/glsl/Edge.ts b/core/frontend/src/render/webgl/glsl/Edge.ts index e2621a1a4dfc..10ef30bb5de9 100644 --- a/core/frontend/src/render/webgl/glsl/Edge.ts +++ b/core/frontend/src/render/webgl/glsl/Edge.ts @@ -8,20 +8,20 @@ import { assert } from "@itwin/core-bentley"; import { AttributeMap } from "../AttributeMap"; +import { TextureUnit } from "../RenderFlags"; import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderBuilder, VertexShaderComponent } from "../ShaderBuilder"; import { IsAnimated, IsInstanced, PositionType } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; -import { TextureUnit } from "../RenderFlags"; import { addAnimation } from "./Animation"; import { addColor } from "./Color"; import { addFrustum, addShaderFlags } from "./Common"; +import { addRenderOrder, addRenderOrderConstants } from "./FeatureSymbology"; import { addWhiteOnWhiteReversal } from "./Fragment"; +import { addLookupTable } from "./LookupTable"; import { addAdjustWidth, addLineCode } from "./Polyline"; import { octDecodeNormal } from "./Surface"; import { addLineWeight, addModelViewMatrix, addNormalMatrix, addProjectionMatrix, addSamplePosition } from "./Vertex"; import { addModelToWindowCoordinates, addViewport } from "./Viewport"; -import { addLookupTable } from "./LookupTable"; -import { addRenderOrder, addRenderOrderConstants } from "./FeatureSymbology"; export type EdgeBuilderType = "SegmentEdge" | "Silhouette" | "IndexedEdge"; @@ -35,7 +35,8 @@ ${computeOtherPos} g_quadIndex = a_endPointAndQuadIndices.w; `; -const animateEndPoint = `g_otherPos.xyz += computeAnimationDisplacement(g_otherIndex, u_animDispParams.x, u_animDispParams.y, u_animDispParams.z, u_qAnimDispOrigin, u_qAnimDispScale);`; +const animateEndPoint = + `g_otherPos.xyz += computeAnimationDisplacement(g_otherIndex, u_animDispParams.x, u_animDispParams.y, u_animDispParams.z, u_qAnimDispOrigin, u_qAnimDispScale);`; // a_pos is a 24-bit index into edge lookup table. // First six bytes of lookup table entry are the pair of 24-bit indices identifying the endpoints of the edge in the vertex table. diff --git a/core/frontend/src/render/webgl/glsl/FeatureSymbology.ts b/core/frontend/src/render/webgl/glsl/FeatureSymbology.ts index d618f9985b0c..1581243b7834 100644 --- a/core/frontend/src/render/webgl/glsl/FeatureSymbology.ts +++ b/core/frontend/src/render/webgl/glsl/FeatureSymbology.ts @@ -7,9 +7,16 @@ */ import { assert } from "@itwin/core-bentley"; +import { OvrFlags } from "../../../common/internal/render/OvrFlags"; import { Pass, RenderOrder, TextureUnit } from "../RenderFlags"; import { - FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariablePrecision, VariableType, VertexShaderBuilder, + FragmentShaderBuilder, + FragmentShaderComponent, + ProgramBuilder, + ShaderBuilder, + VariablePrecision, + VariableType, + VertexShaderBuilder, VertexShaderComponent, } from "../ShaderBuilder"; import { FeatureMode, TechniqueFlags } from "../TechniqueFlags"; @@ -19,7 +26,6 @@ import { addWindowToTexCoords, assignFragColor, computeLinearDepth } from "./Fra import { addLookupTable } from "./LookupTable"; import { addRenderPass } from "./RenderPass"; import { addAlpha, addLineWeight, replaceLineCode, replaceLineWeight } from "./Vertex"; -import { OvrFlags } from "../../../common/internal/render/OvrFlags"; /* eslint-disable no-restricted-syntax */ @@ -745,7 +751,10 @@ export function addFeatureSymbology(builder: ProgramBuilder, feat: FeatureMode, if (!addCommon(builder, feat, opts) || FeatureSymbologyOptions.None === opts) return; - assert((FeatureSymbologyOptions.HasOverrides | FeatureSymbologyOptions.Color) === (opts & (FeatureSymbologyOptions.HasOverrides | FeatureSymbologyOptions.Color))); + assert( + (FeatureSymbologyOptions.HasOverrides | FeatureSymbologyOptions.Color) === + (opts & (FeatureSymbologyOptions.HasOverrides | FeatureSymbologyOptions.Color)), + ); builder.addGlobal("feature_rgb", VariableType.Vec3); builder.addGlobal("feature_alpha", VariableType.Float); diff --git a/core/frontend/src/render/webgl/glsl/Instancing.ts b/core/frontend/src/render/webgl/glsl/Instancing.ts index c04ea1c1bc09..73ddadbff85d 100644 --- a/core/frontend/src/render/webgl/glsl/Instancing.ts +++ b/core/frontend/src/render/webgl/glsl/Instancing.ts @@ -7,9 +7,9 @@ */ import { assert } from "@itwin/core-bentley"; +import { Matrix4 } from "../Matrix"; import { VariableType, VertexShaderBuilder } from "../ShaderBuilder"; import { UniformHandle } from "../UniformHandle"; -import { Matrix4 } from "../Matrix"; import { addExtractNthBit } from "./Common"; import { addOvrFlagConstants } from "./FeatureSymbology"; @@ -43,17 +43,32 @@ function setMatrix(uniform: UniformHandle, matrix: Matrix4 | undefined): void { } function addPatternTransforms(vert: VertexShaderBuilder): void { - vert.addUniform("u_patOrg", VariableType.Mat4, (prog) => - prog.addGraphicUniform("u_patOrg", (uniform, params) => - setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.orgTransform))); - - vert.addUniform("u_patLocalToModel", VariableType.Mat4, (prog) => - prog.addGraphicUniform("u_patLocalToModel", (uniform, params) => - setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.localToModel))); - - vert.addUniform("u_patSymbolToLocal", VariableType.Mat4, (prog) => - prog.addGraphicUniform("u_patSymbolToLocal", (uniform, params) => - setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.symbolToLocal))); + vert.addUniform( + "u_patOrg", + VariableType.Mat4, + (prog) => + prog.addGraphicUniform("u_patOrg", (uniform, params) => setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.orgTransform)), + ); + + vert.addUniform( + "u_patLocalToModel", + VariableType.Mat4, + (prog) => + prog.addGraphicUniform( + "u_patLocalToModel", + (uniform, params) => setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.localToModel), + ), + ); + + vert.addUniform( + "u_patSymbolToLocal", + VariableType.Mat4, + (prog) => + prog.addGraphicUniform( + "u_patSymbolToLocal", + (uniform, params) => setMatrix(uniform, params.geometry.asInstanced?.patternTransforms?.symbolToLocal), + ), + ); vert.addUniform("u_patternOrigin", VariableType.Vec2, (prog) => { prog.addGraphicUniform("u_patternOrigin", (uniform, params) => { diff --git a/core/frontend/src/render/webgl/glsl/Monochrome.ts b/core/frontend/src/render/webgl/glsl/Monochrome.ts index 70546b183d89..478034d023eb 100644 --- a/core/frontend/src/render/webgl/glsl/Monochrome.ts +++ b/core/frontend/src/render/webgl/glsl/Monochrome.ts @@ -45,7 +45,9 @@ export function addSurfaceMonochrome(frag: FragmentShaderBuilder): void { addMonoRgb(frag); frag.addUniform("u_mixMonoColor", VariableType.Float, (prog) => { prog.addGraphicUniform("u_mixMonoColor", (uniform, params) => { - uniform.setUniform1f(MonochromeMode.Scaled === params.target.plan.monochromeMode && params.geometry.wantMixMonochromeColor(params.target) ? 1.0 : 0.0); + uniform.setUniform1f( + MonochromeMode.Scaled === params.target.plan.monochromeMode && params.geometry.wantMixMonochromeColor(params.target) ? 1.0 : 0.0, + ); }); }); diff --git a/core/frontend/src/render/webgl/glsl/PlanarClassification.ts b/core/frontend/src/render/webgl/glsl/PlanarClassification.ts index 3e27919ac290..32ac147d6676 100644 --- a/core/frontend/src/render/webgl/glsl/PlanarClassification.ts +++ b/core/frontend/src/render/webgl/glsl/PlanarClassification.ts @@ -8,8 +8,8 @@ */ import { assert } from "@itwin/core-bentley"; -import { Matrix4d } from "@itwin/core-geometry"; import { SpatialClassifierInsideDisplay } from "@itwin/core-common"; +import { Matrix4d } from "@itwin/core-geometry"; import { Matrix4 } from "../Matrix"; import { PlanarClassifierContent } from "../PlanarClassifier"; import { TextureUnit } from "../RenderFlags"; @@ -106,8 +106,7 @@ if (doMask) { discard; return vec4(0); } -` - ; +`; // Currently we discard if classifier is pure black (acts as clipping mask). // These could be more efficiently handled with masks. @@ -196,7 +195,7 @@ const computeClassifierPosW = "v_pClassPosW = classProj.w;"; const scratchBytes = new Uint8Array(4); const scratchBatchBaseId = new Uint32Array(scratchBytes.buffer); const scratchBatchBaseComponents = [0, 0, 0, 0]; -const scratchColorParams = new Float32Array(4); // Unclassified scale, classified base scale, classified classifier scale, content/image count... MaskOnly = 1, ClassifierOnly = 2, ClassifierAndMask = 3 +const scratchColorParams = new Float32Array(4); // Unclassified scale, classified base scale, classified classifier scale, content/image count... MaskOnly = 1, ClassifierOnly = 2, ClassifierAndMask = 3 const scratchModel = Matrix4d.createIdentity(); const scratchModelProjection = Matrix4d.createIdentity(); const scratchMatrix = new Matrix4(); @@ -219,7 +218,11 @@ function addPlanarClassifierCommon(builder: ProgramBuilder) { if (vert.usesInstancedGeometry) addInstancedRtcMatrix(vert); - builder.addInlineComputedVarying("v_pClassPos", VariableType.Vec2, vert.usesInstancedGeometry ? computeInstancedClassifierPos : computeClassifierPos); + builder.addInlineComputedVarying( + "v_pClassPos", + VariableType.Vec2, + vert.usesInstancedGeometry ? computeInstancedClassifierPos : computeClassifierPos, + ); builder.addInlineComputedVarying("v_pClassPosW", VariableType.Float, computeClassifierPosW); addPlanarClassifierConstants(builder.frag); @@ -263,10 +266,10 @@ export function addColorPlanarClassifier(builder: ProgramBuilder, translucent: b if (undefined !== source) { source.getParams(scratchColorParams); } else { - scratchColorParams[0] = 6.0; // Volume classifier, by element color. - scratchColorParams[1] = 0.5; // used for alpha value - scratchColorParams[2] = 0.0; // Not used for volume. - scratchColorParams[3] = 0.0; // Not used for volume. + scratchColorParams[0] = 6.0; // Volume classifier, by element color. + scratchColorParams[1] = 0.5; // used for alpha value + scratchColorParams[2] = 0.0; // Not used for volume. + scratchColorParams[3] = 0.0; // Not used for volume. } uniform.setUniform4fv(scratchColorParams); }); @@ -295,13 +298,16 @@ export function addColorPlanarClassifier(builder: ProgramBuilder, translucent: b addShaderFlags(builder); - frag.set(FragmentShaderComponent.ApplyPlanarClassifier, (isThematic === IsThematic.No) ? applyPlanarClassificationColor : applyPlanarClassificationColorForThematic); + frag.set( + FragmentShaderComponent.ApplyPlanarClassifier, + (isThematic === IsThematic.No) ? applyPlanarClassificationColor : applyPlanarClassificationColorForThematic, + ); } /** @internal */ export function addFeaturePlanarClassifier(builder: ProgramBuilder) { const frag = builder.frag; - frag.addUniform("u_batchBase", VariableType.Vec4, (prog) => { // TBD. Instancing. + frag.addUniform("u_batchBase", VariableType.Vec4, (prog) => { // TBD. Instancing. prog.addGraphicUniform("u_batchBase", (uniform, params) => { const classifier = params.target.currentPlanarClassifier; if (classifier !== undefined) { @@ -394,7 +400,8 @@ const overrideClassifierColorPostludeClipForThematic = ` return encodeNonLocatable(isElem ? vec4(0.0, 0.0, 1.0, 1.0) : currentColor); `; -const overrideClassifierWithFeaturesForThematic = overrideClassifierColorPreludeForThematic + overrideClassifierEmphasisForThematic + overrideClassifierColorPostlude; +const overrideClassifierWithFeaturesForThematic = overrideClassifierColorPreludeForThematic + overrideClassifierEmphasisForThematic + + overrideClassifierColorPostlude; const overrideClassifierForClipForThematic = overrideClassifierColorPreludeForThematic + overrideClassifierColorPostludeClipForThematic; /** The classified geometry needs some information about the classifier geometry. The classified fragment shader outputs special values that do not represent valid RGB+A combinations when using @@ -419,5 +426,8 @@ export function addOverrideClassifierColor(builder: ProgramBuilder, isThematic: if (isThematic === IsThematic.No) builder.frag.set(FragmentShaderComponent.OverrideColor, haveOverrides ? overrideClassifierWithFeatures : overrideClassifierForClip); else - builder.frag.set(FragmentShaderComponent.OverrideColor, haveOverrides ? overrideClassifierWithFeaturesForThematic : overrideClassifierForClipForThematic); + builder.frag.set( + FragmentShaderComponent.OverrideColor, + haveOverrides ? overrideClassifierWithFeaturesForThematic : overrideClassifierForClipForThematic, + ); } diff --git a/core/frontend/src/render/webgl/glsl/PlanarGrid.ts b/core/frontend/src/render/webgl/glsl/PlanarGrid.ts index 02768eeda0de..a760fe387610 100644 --- a/core/frontend/src/render/webgl/glsl/PlanarGrid.ts +++ b/core/frontend/src/render/webgl/glsl/PlanarGrid.ts @@ -47,7 +47,7 @@ const drawGridLine = ` } `; -const fwidth2d = `\nvec2 screenSpaceDeriv(vec2 screenXY) { return fwidth(screenXY); }\n`; +const fwidth2d = `\nvec2 screenSpaceDeriv(vec2 screenXY) { return fwidth(screenXY); }\n`; const defaultTransparency = new PlanarGridTransparency(); /** @internal */ @@ -91,10 +91,14 @@ export default function createPlanarGridProgram(context: WebGL2RenderingContext) prog.addGraphicUniform("u_gridProps", (uniform, params) => { const planarGridProps = params.geometry.asPlanarGrid!.props; const transparency = planarGridProps.transparency ? planarGridProps.transparency : defaultTransparency; - uniform.setUniform4fv([planarGridProps.gridsPerRef, 1.0 - transparency.planeTransparency, 1.0 - transparency.lineTransparency, 1.0 - transparency.refTransparency]); + uniform.setUniform4fv([ + planarGridProps.gridsPerRef, + 1.0 - transparency.planeTransparency, + 1.0 - transparency.lineTransparency, + 1.0 - transparency.refTransparency, + ]); }); }); return builder.buildProgram(context); } - diff --git a/core/frontend/src/render/webgl/glsl/PointCloud.ts b/core/frontend/src/render/webgl/glsl/PointCloud.ts index bef3fe741735..860a3a74abb6 100644 --- a/core/frontend/src/render/webgl/glsl/PointCloud.ts +++ b/core/frontend/src/render/webgl/glsl/PointCloud.ts @@ -12,12 +12,12 @@ import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderComp import { FeatureMode, IsAnimated, IsClassified, IsThematic } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { addUniformHiliter } from "./FeatureSymbology"; +import { assignFragColor } from "./Fragment"; import { addColorPlanarClassifier, addFeaturePlanarClassifier, addHilitePlanarClassifier } from "./PlanarClassification"; +import { addTexture } from "./Surface"; +import { addThematicDisplay } from "./Thematic"; import { addModelViewProjectionMatrix } from "./Vertex"; import { addViewportTransformation } from "./Viewport"; -import { addThematicDisplay } from "./Thematic"; -import { addTexture } from "./Surface"; -import { assignFragColor } from "./Fragment"; // Revert components if color format is BGR instead of RGB. const computeColor = ` diff --git a/core/frontend/src/render/webgl/glsl/Polyline.ts b/core/frontend/src/render/webgl/glsl/Polyline.ts index d7d1259e13b0..775384168754 100644 --- a/core/frontend/src/render/webgl/glsl/Polyline.ts +++ b/core/frontend/src/render/webgl/glsl/Polyline.ts @@ -10,20 +10,23 @@ import { assert } from "@itwin/core-bentley"; import { AttributeMap } from "../AttributeMap"; import { TextureUnit } from "../RenderFlags"; import { - FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderBuilder, VertexShaderComponent, + FragmentShaderBuilder, + FragmentShaderComponent, + ProgramBuilder, + VariableType, + VertexShaderBuilder, + VertexShaderComponent, } from "../ShaderBuilder"; import { System } from "../System"; import { IsInstanced, PositionType } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { addColor } from "./Color"; -import { addEdgeContrast } from "./Edge"; import { addFrustum, addShaderFlags } from "./Common"; import { unquantize2d } from "./Decode"; +import { addEdgeContrast } from "./Edge"; import { addHiliter } from "./FeatureSymbology"; import { addWhiteOnWhiteReversal } from "./Fragment"; -import { - addLineCode as addLineCodeUniform, addLineWeight, addModelViewMatrix, addProjectionMatrix, addSamplePosition, -} from "./Vertex"; +import { addLineCode as addLineCodeUniform, addLineWeight, addModelViewMatrix, addProjectionMatrix, addSamplePosition } from "./Vertex"; import { addModelToWindowCoordinates, addViewport } from "./Viewport"; const checkForDiscard = "return discardByLineCode;"; diff --git a/core/frontend/src/render/webgl/glsl/RealityMesh.ts b/core/frontend/src/render/webgl/glsl/RealityMesh.ts index c8fb953d1d29..6e94dfd6103d 100644 --- a/core/frontend/src/render/webgl/glsl/RealityMesh.ts +++ b/core/frontend/src/render/webgl/glsl/RealityMesh.ts @@ -132,7 +132,8 @@ const scratchMatrix4d1 = Matrix4d.createIdentity(); const scratchMatrix4d2 = Matrix4d.createIdentity(); const scratchMatrix = new Matrix4(); -const overrideFeatureId = `return (classifierId == vec4(0)) ? (addUInt32s(feature_id * 255.0, vec4(featureIncrement, 0.0, 0.0, 0.0)) / 255.0) : classifierId;`; +const overrideFeatureId = + `return (classifierId == vec4(0)) ? (addUInt32s(feature_id * 255.0, vec4(featureIncrement, 0.0, 0.0, 0.0)) / 255.0) : classifierId;`; function addTextures(builder: ProgramBuilder, maxTexturesPerMesh: number) { builder.vert.addFunction(unquantize2d); @@ -156,7 +157,14 @@ function addTextures(builder: ProgramBuilder, maxTexturesPerMesh: number) { const textureLabel = `s_texture${i}`; builder.frag.addUniform(textureLabel, VariableType.Sampler2D, (prog) => { prog.addGraphicUniform(textureLabel, (uniform, params) => { - const textureUnits = [TextureUnit.RealityMesh0, TextureUnit.RealityMesh1, params.target.drawForReadPixels ? TextureUnit.ShadowMap : TextureUnit.PickDepthAndOrder, TextureUnit.RealityMesh3, TextureUnit.RealityMesh4, TextureUnit.RealityMesh5]; + const textureUnits = [ + TextureUnit.RealityMesh0, + TextureUnit.RealityMesh1, + params.target.drawForReadPixels ? TextureUnit.ShadowMap : TextureUnit.PickDepthAndOrder, + TextureUnit.RealityMesh3, + TextureUnit.RealityMesh4, + TextureUnit.RealityMesh5, + ]; const realityMesh = params.geometry.asRealityMesh!; const realityTexture = realityMesh.textureParams ? realityMesh.textureParams.params[i].texture : undefined; if (realityTexture !== undefined) { @@ -245,7 +253,10 @@ function addThematicToRealityMesh(builder: ProgramBuilder, gradientTextureUnit: }); builder.frag.addUniform("s_texture", VariableType.Sampler2D, (prog) => { prog.addGraphicUniform("s_texture", (uniform, params) => { - params.target.uniforms.thematic.bindTexture(uniform, gradientTextureUnit >= 0 ? gradientTextureUnit : (params.target.drawForReadPixels ? TextureUnit.ShadowMap : TextureUnit.PickDepthAndOrder)); + params.target.uniforms.thematic.bindTexture( + uniform, + gradientTextureUnit >= 0 ? gradientTextureUnit : (params.target.drawForReadPixels ? TextureUnit.ShadowMap : TextureUnit.PickDepthAndOrder), + ); }); }); } @@ -266,7 +277,6 @@ function createRealityMeshHiliterBuilder(): ProgramBuilder { addModelViewProjectionMatrix(vert); builder.frag.set(FragmentShaderComponent.AssignFragData, assignFragColor); return builder; - } /** @internal */ diff --git a/core/frontend/src/render/webgl/glsl/ScreenSpaceEffect.ts b/core/frontend/src/render/webgl/glsl/ScreenSpaceEffect.ts index d74aa95f22c9..97358870edf3 100644 --- a/core/frontend/src/render/webgl/glsl/ScreenSpaceEffect.ts +++ b/core/frontend/src/render/webgl/glsl/ScreenSpaceEffect.ts @@ -7,8 +7,8 @@ */ import { ScreenSpaceEffectBuilderParams } from "../../ScreenSpaceEffectBuilder"; -import { TextureUnit } from "../RenderFlags"; import { AttributeMap } from "../AttributeMap"; +import { TextureUnit } from "../RenderFlags"; import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderComponent } from "../ShaderBuilder"; import { assignFragColor } from "./Fragment"; diff --git a/core/frontend/src/render/webgl/glsl/SkySphere.ts b/core/frontend/src/render/webgl/glsl/SkySphere.ts index 77e14923d381..fe442352b7aa 100644 --- a/core/frontend/src/render/webgl/glsl/SkySphere.ts +++ b/core/frontend/src/render/webgl/glsl/SkySphere.ts @@ -6,20 +6,20 @@ * @module WebGL */ -import { Angle, Point3d, Vector3d } from "@itwin/core-geometry"; import { Npc } from "@itwin/core-common"; +import { Angle, Point3d, Vector3d } from "@itwin/core-geometry"; import { AttributeMap } from "../AttributeMap"; import { SkySphereViewportQuadGeometry } from "../CachedGeometry"; import { fromSumOf, FrustumUniformType } from "../FrustumUniforms"; import { TextureUnit } from "../RenderFlags"; import { FragmentShaderComponent, ProgramBuilder, ShaderType, VariableType } from "../ShaderBuilder"; import { System } from "../System"; +import { TechniqueFlags } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { Texture } from "../Texture"; +import { addAtmosphericScatteringEffect } from "./Atmosphere"; import { assignFragColor } from "./Fragment"; import { createViewportQuadBuilder } from "./ViewportQuad"; -import { addAtmosphericScatteringEffect } from "./Atmosphere"; -import { TechniqueFlags } from "../TechniqueFlags"; const computeGradientValue = ` // For the gradient sky it's good enough to calculate these in the vertex shader. @@ -256,7 +256,15 @@ export function createSkySphereBuilder(isGradient: boolean, flags: TechniqueFlag let zScale = focalLength / delta.magnitude(); if (zScale < 1.000001) zScale = 1.000001; // prevent worldEye front being on or inside the frustum front plane - const worldEye = Point3d.createAdd3Scaled(frustum.getCorner(Npc.LeftBottomRear), .5, frustum.getCorner(Npc.RightTopRear), .5, delta, zScale, scratchPoint3); + const worldEye = Point3d.createAdd3Scaled( + frustum.getCorner(Npc.LeftBottomRear), + .5, + frustum.getCorner(Npc.RightTopRear), + .5, + delta, + zScale, + scratchPoint3, + ); scratch3Floats[0] = worldEye.x; scratch3Floats[1] = worldEye.y; scratch3Floats[2] = worldEye.z; diff --git a/core/frontend/src/render/webgl/glsl/Surface.ts b/core/frontend/src/render/webgl/glsl/Surface.ts index a8e37ab85e1f..552f02782099 100644 --- a/core/frontend/src/render/webgl/glsl/Surface.ts +++ b/core/frontend/src/render/webgl/glsl/Surface.ts @@ -7,28 +7,37 @@ */ import { assert } from "@itwin/core-bentley"; +import { Npc } from "@itwin/core-common"; import { AttributeMap } from "../AttributeMap"; import { Material } from "../Material"; import { Pass, SurfaceBitIndex, SurfaceFlags, TextureUnit } from "../RenderFlags"; -import { - FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariableType, VertexShaderComponent, -} from "../ShaderBuilder"; +import { FragmentShaderBuilder, FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariableType, VertexShaderComponent } from "../ShaderBuilder"; +import { wantMaterials } from "../SurfaceGeometry"; import { System } from "../System"; -import { - FeatureMode, IsAnimated, IsClassified, IsInstanced, IsShadowable, IsThematic, PositionType, TechniqueFlags, -} from "../TechniqueFlags"; +import { FeatureMode, IsAnimated, IsClassified, IsInstanced, IsShadowable, IsThematic, PositionType, TechniqueFlags } from "../TechniqueFlags"; import { TechniqueId } from "../TechniqueId"; import { Texture } from "../Texture"; import { addAnimation } from "./Animation"; import { unpackFloat } from "./Clipping"; import { addColor } from "./Color"; import { addChooseVec2WithBitFlagsFunction, addChooseVec3WithBitFlagFunction, addExtractNthBit, addFrustum, addShaderFlags } from "./Common"; +import { addApplyContours } from "./Contours"; import { addUnpackAndNormalize2Bytes, decodeDepthRgb, unquantize2d } from "./Decode"; import { - addFeatureSymbology, addMaxAlpha, addRenderOrder, addRenderOrderConstants, addSurfaceDiscard, addSurfaceHiliter, FeatureSymbologyOptions, + addFeatureSymbology, + addMaxAlpha, + addRenderOrder, + addRenderOrderConstants, + addSurfaceDiscard, + addSurfaceHiliter, + FeatureSymbologyOptions, } from "./FeatureSymbology"; import { - addAltPickBufferOutputs, addFragColorWithPreMultipliedAlpha, addPickBufferOutputs, addWhiteOnWhiteReversal, assignFragColor, + addAltPickBufferOutputs, + addFragColorWithPreMultipliedAlpha, + addPickBufferOutputs, + addWhiteOnWhiteReversal, + assignFragColor, } from "./Fragment"; import { addLighting } from "./Lighting"; import { addSurfaceMonochrome } from "./Monochrome"; @@ -38,10 +47,7 @@ import { addSolarShadowMap } from "./SolarShadowMapping"; import { addThematicDisplay, getComputeThematicIndex } from "./Thematic"; import { addTranslucency } from "./Translucency"; import { addModelViewMatrix, addNormalMatrix, addProjectionMatrix } from "./Vertex"; -import { wantMaterials } from "../SurfaceGeometry"; import { addWiremesh } from "./Wiremesh"; -import { Npc } from "@itwin/core-common"; -import { addApplyContours } from "./Contours"; const constantLodTextureLookup = ` vec4 constantLodTextureLookup(sampler2D textureSampler) { @@ -259,7 +265,13 @@ const computePositionPostlude = ` return u_proj * pos; `; -function createCommon(isInstanced: IsInstanced, animated: IsAnimated, shadowable: IsShadowable, isHiliter: boolean, positionType: PositionType): ProgramBuilder { +function createCommon( + isInstanced: IsInstanced, + animated: IsAnimated, + shadowable: IsShadowable, + isHiliter: boolean, + positionType: PositionType, +): ProgramBuilder { const instanced = IsInstanced.Yes === isInstanced; const attrMap = AttributeMap.findAttributeMap(TechniqueId.Surface, instanced); const builder = new ProgramBuilder(attrMap, { positionType, instanced }); @@ -529,7 +541,12 @@ function addNormal(builder: ProgramBuilder, animated: IsAnimated) { const quantized = "quantized" === builder.vert.positionType; builder.vert.addFunction(octDecodeNormal); builder.vert.addFunction("vec3 computeSurfaceNormal()", getComputeNormal(quantized)); - builder.addFunctionComputedVarying("v_n", VariableType.Vec3, "computeLightingNormal", animated ? getComputeAnimatedNormal(quantized) : "return computeSurfaceNormal();"); + builder.addFunctionComputedVarying( + "v_n", + VariableType.Vec3, + "computeLightingNormal", + animated ? getComputeAnimatedNormal(quantized) : "return computeSurfaceNormal();", + ); builder.frag.addGlobal("g_normal", VariableType.Vec3); let finalizeNormal = finalizeNormalPrelude; @@ -565,7 +582,11 @@ function addNormal(builder: ProgramBuilder, animated: IsAnimated) { /** @internal */ export function addTexture(builder: ProgramBuilder, animated: IsAnimated, isThematic: IsThematic, isPointCloud: boolean, isHilite: boolean) { if (isThematic) { - builder.addInlineComputedVarying("v_thematicIndex", VariableType.Float, getComputeThematicIndex(builder.vert.usesInstancedGeometry, isPointCloud, true)); + builder.addInlineComputedVarying( + "v_thematicIndex", + VariableType.Float, + getComputeThematicIndex(builder.vert.usesInstancedGeometry, isPointCloud, true), + ); } // Point clouds do not need to compute texture coordinates since the only texture they use is the thematic gradient. @@ -574,7 +595,12 @@ export function addTexture(builder: ProgramBuilder, animated: IsAnimated, isThem builder.vert.addFunction(unquantize2d); addChooseVec2WithBitFlagsFunction(builder.vert); const quantized = "quantized" === builder.vert.positionType; - builder.addFunctionComputedVarying("v_texCoord", VariableType.Vec2, "computeTexCoord", animated ? getComputeAnimatedTexCoord(quantized) : getComputeTexCoord(quantized)); + builder.addFunctionComputedVarying( + "v_texCoord", + VariableType.Vec2, + "computeTexCoord", + animated ? getComputeAnimatedTexCoord(quantized) : getComputeTexCoord(quantized), + ); builder.vert.addUniform("u_qTexCoordParams", VariableType.Vec4, (prog) => { prog.addGraphicUniform("u_qTexCoordParams", (uniform, params) => { const surfGeom = params.geometry.asSurface!; @@ -594,7 +620,9 @@ export function addTexture(builder: ProgramBuilder, animated: IsAnimated, isThem if (params.geometry.supportsThematicDisplay && params.target.wantThematicDisplay) { // NB: if thematic display is enabled, bind the thematic texture and ignore any applied surface textures params.target.uniforms.thematic.bindTexture(uniform, TextureUnit.SurfaceTexture); } else if (surfGeom.useTexture(params.programParams)) { - const texture = (params.geometry.hasAnimation && params.target.analysisTexture) ? (params.target.analysisTexture as Texture) : surfGeom.texture; + const texture = (params.geometry.hasAnimation && params.target.analysisTexture) + ? (params.target.analysisTexture as Texture) + : surfGeom.texture; assert(undefined !== texture); texture.texture.bindSampler(uniform, TextureUnit.SurfaceTexture); } else { @@ -646,7 +674,9 @@ function addTransparencyDiscard(frag: FragmentShaderBuilder): void { // Otherwise, if the geometry draws in both opaque and translucent passes, use DisplayParams.minTransparency to filter pixels into appropriate pass to produce appropriate blending. // Negative cutoff applies only during opaque pass; positive cutoff applies during opaque and translucent passes. const pass = params.geometry.getPass(params.target); - const cutoff = (!Pass.rendersOpaqueAndTranslucent(pass) || params.target.isReadPixelsInProgress || !params.target.currentViewFlags.transparency) ? -1 / 255 : 241 / 255; + const cutoff = (!Pass.rendersOpaqueAndTranslucent(pass) || params.target.isReadPixelsInProgress || !params.target.currentViewFlags.transparency) + ? -1 / 255 + : 241 / 255; uniform.setUniform1f(cutoff); }); }); diff --git a/core/frontend/src/render/webgl/glsl/Thematic.ts b/core/frontend/src/render/webgl/glsl/Thematic.ts index 90fb0c1f02b9..9c98941fb698 100644 --- a/core/frontend/src/render/webgl/glsl/Thematic.ts +++ b/core/frontend/src/render/webgl/glsl/Thematic.ts @@ -7,12 +7,12 @@ */ import { ThematicDisplayMode, ThematicGradientMode } from "@itwin/core-common"; +import { TextureUnit } from "../RenderFlags"; import { FragmentShaderComponent, ProgramBuilder, ShaderBuilder, VariableType } from "../ShaderBuilder"; import { System } from "../System"; +import { addEyeSpace } from "./Common"; import { addRenderPass } from "./RenderPass"; import { addInstancedRtcMatrix, addProjectionMatrix } from "./Vertex"; -import { TextureUnit } from "../RenderFlags"; -import { addEyeSpace } from "./Common"; const getSensorFloat = ` vec4 getSensor(int index) { @@ -296,7 +296,8 @@ export function addThematicDisplay(builder: ProgramBuilder, isForPointClouds = f if (params.target.wantThematicSensors) { if (params.target.uniforms.thematic.wantGlobalSensorTexture) params.target.uniforms.thematic.bindNumSensors(uniform); - else // we are batching separate sensor textures per-tile; use the number of sensors from the batch + // we are batching separate sensor textures per-tile; use the number of sensors from the batch + else params.target.uniforms.batch.bindNumThematicSensors(uniform); } else { uniform.setUniform1i(0); diff --git a/core/frontend/src/render/webgl/glsl/Vertex.ts b/core/frontend/src/render/webgl/glsl/Vertex.ts index e671b232ccba..e44fd9d94c02 100644 --- a/core/frontend/src/render/webgl/glsl/Vertex.ts +++ b/core/frontend/src/render/webgl/glsl/Vertex.ts @@ -8,11 +8,11 @@ import { assert } from "@itwin/core-bentley"; import { DrawParams } from "../DrawCommand"; -import { UniformHandle } from "../UniformHandle"; import { Matrix4 } from "../Matrix"; import { Pass, TextureUnit } from "../RenderFlags"; -import { PositionType } from "../TechniqueFlags"; import { VariableType, VertexShaderBuilder } from "../ShaderBuilder"; +import { PositionType } from "../TechniqueFlags"; +import { UniformHandle } from "../UniformHandle"; import { decodeUint16, decodeUint24 } from "./Decode"; import { addInstanceOverrides } from "./Instancing"; import { addLookupTable } from "./LookupTable"; diff --git a/core/frontend/src/request/Request.ts b/core/frontend/src/request/Request.ts index e14749d120fd..ee8f8d8a130e 100644 --- a/core/frontend/src/request/Request.ts +++ b/core/frontend/src/request/Request.ts @@ -13,7 +13,6 @@ export interface RequestBasicCredentials { // axios: AxiosBasicCredentials * @internal */ export class HttpResponseError extends Error { - public constructor( public status: number, public responseText?: string, diff --git a/core/frontend/src/request/utils.ts b/core/frontend/src/request/utils.ts index 95161948d2b2..f535343587fa 100644 --- a/core/frontend/src/request/utils.ts +++ b/core/frontend/src/request/utils.ts @@ -15,9 +15,9 @@ import { RequestBasicCredentials } from "./Request"; */ export function headersIncludeAuthMethod(headers: Headers, query: string[]): boolean { const wwwAuthenticate = headers.get("WWW-authenticate"); - const lowerCaseQuery = query.map(((value)=>value.toLowerCase())); // not case-sensitive + const lowerCaseQuery = query.map((value) => value.toLowerCase()); // not case-sensitive if (wwwAuthenticate !== null) { - const authMethods = wwwAuthenticate.split(",").map(((value)=>value.toLowerCase().trim())); + const authMethods = wwwAuthenticate.split(",").map((value) => value.toLowerCase().trim()); for (const queryValue of lowerCaseQuery) { if (authMethods.includes(queryValue)) return true; @@ -35,15 +35,15 @@ export function setBasicAuthorization(headers: Headers, credentials: RequestBasi /** @internal */ export function setBasicAuthorization(headers: Headers, user: string, password: string): void; /** @internal */ -export function setBasicAuthorization(headers: Headers, userOrCreds: string|RequestBasicCredentials, password?: string): void { - let username: string|undefined; - let pwd: string|undefined; +export function setBasicAuthorization(headers: Headers, userOrCreds: string | RequestBasicCredentials, password?: string): void { + let username: string | undefined; + let pwd: string | undefined; if (typeof userOrCreds === "string") { username = userOrCreds; - pwd = password; + pwd = password; } else { username = userOrCreds.user; - pwd = userOrCreds.password; + pwd = userOrCreds.password; } if (username !== undefined && pwd !== undefined) @@ -54,9 +54,8 @@ export function setBasicAuthorization(headers: Headers, userOrCreds: string|Requ * Set number of milliseconds a request can take before automatically being terminated * @internal */ -export function setRequestTimeout(opts: RequestInit, ms: number, abortController?: AbortController ): void { +export function setRequestTimeout(opts: RequestInit, ms: number, abortController?: AbortController): void { const controller = abortController ?? new AbortController(); setTimeout(() => controller.abort(), ms); opts.signal = controller.signal; } - diff --git a/core/frontend/src/test/AccuSnap.test.ts b/core/frontend/src/test/AccuSnap.test.ts index a75d3beca70a..92ec4fb4d1ca 100644 --- a/core/frontend/src/test/AccuSnap.test.ts +++ b/core/frontend/src/test/AccuSnap.test.ts @@ -2,18 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64String } from "@itwin/core-bentley"; -import { Angle, AxisIndex, LineSegment3d, Matrix3d, Point3d, Transform, XYZ, XYZProps } from "@itwin/core-geometry"; import { EmptyLocalization, GeometryClass, RenderSchedule, SnapRequestProps, SnapResponseProps } from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; -import { HitDetail, HitPriority, HitSource, SnapDetail, SnapMode } from "../HitDetail"; -import { LocateResponse, SnapStatus } from "../ElementLocateManager"; -import { ScreenViewport } from "../Viewport"; +import { Angle, AxisIndex, LineSegment3d, Matrix3d, Point3d, Transform, XYZ, XYZProps } from "@itwin/core-geometry"; +import { expect } from "chai"; import { AccuSnap } from "../AccuSnap"; +import { _requestSnap } from "../common/internal/Symbols"; +import { LocateResponse, SnapStatus } from "../ElementLocateManager"; +import { HitDetail, HitPriority, HitSource, SnapDetail, SnapMode } from "../HitDetail"; import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; +import { ScreenViewport } from "../Viewport"; import { testBlankViewportAsync } from "./openBlankViewport"; -import { _requestSnap } from "../common/internal/Symbols"; interface HitDetailProps { hitPoint?: XYZProps; // defaults to [0, 0, 0] @@ -27,7 +27,7 @@ interface HitDetailProps { } function makeHitDetail(vp: ScreenViewport, props?: HitDetailProps): HitDetail { - const hitPoint = props?.hitPoint ?? [ 0, 0, 0 ]; + const hitPoint = props?.hitPoint ?? [0, 0, 0]; return new HitDetail({ testPoint: Point3d.fromJSON(props?.testPoint ?? hitPoint), viewport: vp, @@ -51,13 +51,16 @@ describe("AccuSnap", () => { describe("requestSnap", () => { function overrideRequestSnap(iModel: IModelConnection, impl?: (props: SnapRequestProps) => SnapResponseProps): void { - iModel[_requestSnap] = async (props) => Promise.resolve(impl ? impl(props) : { - status: SnapStatus.Success, - hitPoint: props.testPoint, - snapPoint: props.testPoint, - normal: [0, 1, 0], - curve: { lineSegment: [[0, 0, 0], [1, 0, 0]] }, - }); + iModel[_requestSnap] = async (props) => + Promise.resolve( + impl ? impl(props) : { + status: SnapStatus.Success, + hitPoint: props.testPoint, + snapPoint: props.testPoint, + normal: [0, 1, 0], + curve: { lineSegment: [[0, 0, 0], [1, 0, 0]] }, + }, + ); } type SnapResponse = SnapStatus | SnapDetail; @@ -106,7 +109,12 @@ describe("AccuSnap", () => { } } - async function testSnap(hit: HitDetailProps, verify: (response: SnapResponse) => void, snapModes: SnapMode[] = [], configureViewport?: (vp: ScreenViewport) => void): Promise { + async function testSnap( + hit: HitDetailProps, + verify: (response: SnapResponse) => void, + snapModes: SnapMode[] = [], + configureViewport?: (vp: ScreenViewport) => void, + ): Promise { await testBlankViewportAsync(async (vp) => { overrideRequestSnap(vp.iModel); if (configureViewport) @@ -125,7 +133,10 @@ describe("AccuSnap", () => { { sourceId: "0x123", modelId: "0x123" }, (response) => expect(response).to.equal(SnapStatus.NoSnapPossible), modes, - (vp) => vp.mapLayerFromHit = () => { return [] as any; }, + (vp) => + vp.mapLayerFromHit = () => { + return [] as any; + }, ); }); @@ -146,7 +157,7 @@ describe("AccuSnap", () => { }); class Transformer { - public constructor(public readonly transform: Transform, public readonly premultiply = false) { } + public constructor(public readonly transform: Transform, public readonly premultiply = false) {} public getModelDisplayTransform() { return { transform: this.transform, premultiply: this.premultiply }; @@ -172,7 +183,10 @@ describe("AccuSnap", () => { { sourceId: "0x123", modelId: "0x456", hitPoint: [1, 2, 3] }, (response) => expectSnapDetail(response, { point: [2, -1, 3], normal: [1, 0, 0], curve: [[0, 0, 0], [0, -1, 0]] }), [], - (vp) => vp.view.modelDisplayTransformProvider = new Transformer(Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90)))), + (vp) => + vp.view.modelDisplayTransformProvider = new Transformer( + Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90))), + ), ); }); @@ -206,7 +220,10 @@ describe("AccuSnap", () => { { sourceId: "0x123", modelId: "0x456", hitPoint: [1, 2, 3] }, (response) => expectSnapDetail(response, { point: [2, -1, 3], normal: [1, 0, 0], curve: [[0, 0, 0], [0, -1, 0]] }), [], - (vp) => vp.view.displayStyle.scheduleScript = makeElementTransformScript(Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90)))), + (vp) => + vp.view.displayStyle.scheduleScript = makeElementTransformScript( + Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90))), + ), ); }); @@ -217,7 +234,9 @@ describe("AccuSnap", () => { [], (vp) => { vp.view.getModelElevation = () => 10; - vp.view.modelDisplayTransformProvider = new Transformer(Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90)))); + vp.view.modelDisplayTransformProvider = new Transformer( + Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(-90))), + ); vp.view.displayStyle.scheduleScript = makeElementTransformScript(Transform.createTranslationXYZ(0, 0, -4)); }, ); @@ -242,7 +261,9 @@ describe("AccuSnap", () => { [], (vp) => { vp.view.getModelElevation = () => 10; - vp.view.modelDisplayTransformProvider = new Transformer(Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.X, Angle.createDegrees(-90)))); + vp.view.modelDisplayTransformProvider = new Transformer( + Transform.createRefs(undefined, Matrix3d.createRotationAroundAxisIndex(AxisIndex.X, Angle.createDegrees(-90))), + ); }, ); }); diff --git a/core/frontend/src/test/BackgroundMapGeometry.test.ts b/core/frontend/src/test/BackgroundMapGeometry.test.ts index f647ca8443db..604ea6ae89c5 100644 --- a/core/frontend/src/test/BackgroundMapGeometry.test.ts +++ b/core/frontend/src/test/BackgroundMapGeometry.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Cartographic, EmptyLocalization, GlobeMode } from "@itwin/core-common"; +import { Range3d, XYAndZ } from "@itwin/core-geometry"; import { expect } from "chai"; import sinon from "sinon"; +import { BackgroundMapGeometry } from "../BackgroundMapGeometry"; import { IModelApp } from "../IModelApp"; -import { Cartographic, EmptyLocalization, GlobeMode } from "@itwin/core-common"; import { IModelConnection } from "../IModelConnection"; -import { Range3d, XYAndZ } from "@itwin/core-geometry"; -import { BackgroundMapGeometry } from "../BackgroundMapGeometry"; import { createBlankConnection } from "./createBlankConnection"; describe("BackgroundMapGeometry", () => { @@ -26,28 +26,31 @@ describe("BackgroundMapGeometry", () => { }); it("provide cartographics from iModel coordinates", async () => { - - const wgs84CartographicFromSpatialFake = sandbox.stub(IModelConnection.prototype, "wgs84CartographicFromSpatial").callsFake(async function _(spatial: XYAndZ[]): Promise { - return Promise.resolve(spatial.map((value) => Cartographic.fromRadians({ longitude: value.x, latitude: value.y, height: value.z}))); - }); - - const dbToCartographicFake = sandbox.stub(BackgroundMapGeometry.prototype, "dbToCartographic").callsFake(function _(db: XYAndZ, _result?: Cartographic): any { - return Cartographic.fromRadians({longitude: db.x, latitude: db.y, height: db.z}); - }); + const wgs84CartographicFromSpatialFake = sandbox.stub(IModelConnection.prototype, "wgs84CartographicFromSpatial").callsFake( + async function _(spatial: XYAndZ[]): Promise { + return Promise.resolve(spatial.map((value) => Cartographic.fromRadians({ longitude: value.x, latitude: value.y, height: value.z }))); + }, + ); + + const dbToCartographicFake = sandbox.stub(BackgroundMapGeometry.prototype, "dbToCartographic").callsFake( + function _(db: XYAndZ, _result?: Cartographic): any { + return Cartographic.fromRadians({ longitude: db.x, latitude: db.y, height: db.z }); + }, + ); const imodel = createBlankConnection(); const bgGeom = new BackgroundMapGeometry(0, GlobeMode.Ellipsoid, imodel); // Any value in the 'negative' range should get reprojected using 'wgs84CartographicFromSpatial' - (bgGeom as any).cartesianRange = Range3d.createXYZXYZ(-100, -100, -100, 0, 0 , 0); - const dataset = [{x: -1, y: -1, z: -1}, {x: 1, y: 1, z: 1}, {x: -2, y: -2, z: -2}]; + (bgGeom as any).cartesianRange = Range3d.createXYZXYZ(-100, -100, -100, 0, 0, 0); + const dataset = [{ x: -1, y: -1, z: -1 }, { x: 1, y: 1, z: 1 }, { x: -2, y: -2, z: -2 }]; const result = await bgGeom.dbToWGS84CartographicFromGcs(dataset); expect(result.length).to.equals(dataset.length); expect(wgs84CartographicFromSpatialFake.getCalls().length).to.equals(1); expect(wgs84CartographicFromSpatialFake.getCalls()[0].args[0].length).to.equals(2); expect(dbToCartographicFake.getCalls().length).to.equals(1); - for (let i = 0; i { + public static override async create( + name: string, + format: Format, + unitsProvider: UnitsProvider, + persistenceUnit: UnitProps, + ): Promise { const conversions: UnitConversionSpec[] = await FormatterSpec.getUnitConversions(format, unitsProvider, persistenceUnit); return new BearingFormatterSpec(name, format, conversions, persistenceUnit); } @@ -154,7 +171,7 @@ class BearingParserSpec extends ParserSpec { } export class BearingQuantityType implements CustomQuantityTypeDefinition { - private _key = "Bearing"; // key and type should be the same unless a QuantityType enum is specified in _type + private _key = "Bearing"; // key and type should be the same unless a QuantityType enum is specified in _type private _type = "Bearing"; private _persistenceUnitName = "Units.RAD"; private _labelKey = "SampleApp:BearingQuantityType.label"; @@ -163,16 +180,22 @@ export class BearingQuantityType implements CustomQuantityTypeDefinition { private _description: string | undefined; private _formatProps = defaultBearingFormat; - constructor(private _persistenceUnit: UnitProps) { } + constructor(private _persistenceUnit: UnitProps) {} - public get key(): string { return this._key; } - public get type(): string { return this._type; } + public get key(): string { + return this._key; + } + public get type(): string { + return this._type; + } public isCompatibleFormatProps(formatProps: FormatProps) { return isBearingFormatProps(formatProps); } - public get formatProps(): FormatProps { return this._formatProps; } + public get formatProps(): FormatProps { + return this._formatProps; + } public set formatProps(value: FormatProps) { if (isBearingFormatProps(value)) { this._formatProps = value; diff --git a/core/frontend/src/test/BlankConnection.test.ts b/core/frontend/src/test/BlankConnection.test.ts index 6bf26177fd89..f263b141b375 100644 --- a/core/frontend/src/test/BlankConnection.test.ts +++ b/core/frontend/src/test/BlankConnection.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { EmptyLocalization } from "@itwin/core-common"; +import { expect } from "chai"; import { IModelApp } from "../IModelApp"; import { createBlankConnection } from "./createBlankConnection"; diff --git a/core/frontend/src/test/ContextRealityModelState.test.ts b/core/frontend/src/test/ContextRealityModelState.test.ts index 261300d39d61..4bca69e9ff67 100644 --- a/core/frontend/src/test/ContextRealityModelState.test.ts +++ b/core/frontend/src/test/ContextRealityModelState.test.ts @@ -2,18 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64, Id64String } from "@itwin/core-bentley"; import { - Code, EmptyLocalization, PlanarClipMaskMode, PlanarClipMaskProps, PlanarClipMaskSettings, RealityModelDisplaySettings, + Code, + EmptyLocalization, + PlanarClipMaskMode, + PlanarClipMaskProps, + PlanarClipMaskSettings, + RealityModelDisplaySettings, } from "@itwin/core-common"; -import { DisplayStyle3dState } from "../DisplayStyleState"; +import { expect } from "chai"; import { ContextRealityModelState } from "../ContextRealityModelState"; -import { IModelConnection } from "../IModelConnection"; +import { DisplayStyle3dState } from "../DisplayStyleState"; import { IModelApp } from "../IModelApp"; -import { - createOrbitGtTileTreeReference, createRealityTileTreeReference, OrbitGtTreeReference, TileTreeOwner, -} from "../tile/internal"; +import { IModelConnection } from "../IModelConnection"; +import { createOrbitGtTileTreeReference, createRealityTileTreeReference, OrbitGtTreeReference, TileTreeOwner } from "../tile/internal"; import { createBlankConnection } from "./createBlankConnection"; describe("ContextRealityModelState", () => { diff --git a/core/frontend/src/test/CoordinateConverter.test.ts b/core/frontend/src/test/CoordinateConverter.test.ts index e8f1bf68b147..1aacb152ee46 100644 --- a/core/frontend/src/test/CoordinateConverter.test.ts +++ b/core/frontend/src/test/CoordinateConverter.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point3d, Range3d, XYAndZ, XYZProps } from "@itwin/core-geometry"; import { Cartographic, EcefLocation, EmptyLocalization, GeoCoordStatus, PointWithStatus } from "@itwin/core-common"; -import { BlankConnection } from "../IModelConnection"; -import { IModelApp } from "../IModelApp"; +import { Point3d, Range3d, XYAndZ, XYZProps } from "@itwin/core-geometry"; +import { expect } from "chai"; import { CoordinateConverter, CoordinateConverterOptions } from "../GeoServices"; +import { IModelApp } from "../IModelApp"; +import { BlankConnection } from "../IModelConnection"; class Connection extends BlankConnection { private _isClosed = false; @@ -39,11 +39,21 @@ class Converter extends CoordinateConverter { }); } - public get cache() { return this._cache; } - public get pending() { return this._pending; } - public get inflight() { return this._inflight; } - public get maxPointsPerRequest() { return this._maxPointsPerRequest; } - public get state() { return this._state; } + public get cache() { + return this._cache; + } + public get pending() { + return this._pending; + } + public get inflight() { + return this._inflight; + } + public get maxPointsPerRequest() { + return this._maxPointsPerRequest; + } + public get state() { + return this._state; + } } describe("CoordinateConverter", () => { @@ -122,8 +132,8 @@ describe("CoordinateConverter", () => { it("converts points", async () => { const input: XYZProps[] = [ { x: 0, y: 1, z: 2 }, - [ 6, 7, 8 ], - [ 9, 10, 11 ], + [6, 7, 8], + [9, 10, 11], { x: 3, y: 4, z: 5 }, ]; @@ -135,7 +145,7 @@ describe("CoordinateConverter", () => { it("defaults omitted components to zero", async () => { const input: XYZProps[] = [ { y: 1 }, - [ 6 ], + [6], { x: 3, z: 5 }, ]; @@ -146,8 +156,8 @@ describe("CoordinateConverter", () => { it("caches responses", async () => { const input = [ - [ 0, 1, 2 ], - [ 3, 4, 5 ], + [0, 1, 2], + [3, 4, 5], ]; const c = new Converter({ iModel, requestPoints }); @@ -163,7 +173,7 @@ describe("CoordinateConverter", () => { }; const c = new Converter({ iModel, requestPoints: reqPts }); - const input = [ [ 0, 1, 2 ] ]; + const input = [[0, 1, 2]]; expect(nRequests).to.equal(0); await c.convert(input); expect(nRequests).to.equal(1); @@ -184,10 +194,10 @@ describe("CoordinateConverter", () => { }); await c.convert([[0, 0, 0], [1, 1, 1]]); - expect(ptsRequested).to.deep.equal([{x: 0, y: 0, z: 0}, {x: 1, y: 1, z: 1}]); + expect(ptsRequested).to.deep.equal([{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }]); await c.convert([[1, 1, 1], [2, 2, 2]]); - expect(ptsRequested).to.deep.equal([{x: 2, y: 2, z: 2}]); + expect(ptsRequested).to.deep.equal([{ x: 2, y: 2, z: 2 }]); }); async function waitOneFrame(): Promise { @@ -251,8 +261,8 @@ describe("CoordinateConverter", () => { const results = await Promise.all([p0, p1]); expect(ptsRequested).to.deep.equal([ - [{x: 0, y: 0, z: 0}, {x: 1, y: 1, z: 1}], - [{x: 2, y: 2, z: 2}], + [{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }], + [{ x: 2, y: 2, z: 2 }], ]); expectConverted(ptsRequested[0], results[0].points); @@ -270,21 +280,21 @@ describe("CoordinateConverter", () => { }); await c.convert([ - {x: 3, y: 3, z: 3}, + { x: 3, y: 3, z: 3 }, [1, 1, 1], [0, 0, 0], - {x: 2, y: 2, z: 2}, - {x: 0, y: 0, z: 0}, + { x: 2, y: 2, z: 2 }, + { x: 0, y: 0, z: 0 }, [2, 2, 2], - {x: 3, y: 3, z: 3}, + { x: 3, y: 3, z: 3 }, [0, 0, 0], ]); expect(ptsRequested).to.deep.equal([ - {x: 0, y: 0, z: 0}, - {x: 1, y: 1, z: 1}, - {x: 2, y: 2, z: 2}, - {x: 3, y: 3, z: 3}, + { x: 0, y: 0, z: 0 }, + { x: 1, y: 1, z: 1 }, + { x: 2, y: 2, z: 2 }, + { x: 3, y: 3, z: 3 }, ]); }); @@ -330,7 +340,7 @@ describe("CoordinateConverter", () => { const c = new Converter({ iModel, requestPoints: async (pts: XYAndZ[]) => { - expect(pts).to.deep.equal([{x: 0, y: 0, z: 0}, {x: 1, y: 1, z: 1}]); + expect(pts).to.deep.equal([{ x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }]); return requestPoints(pts); }, }); @@ -372,13 +382,13 @@ describe("CoordinateConverter", () => { const results = await c.convert([[2, 2, 2], [1, 1, 1], [3, 3, 3]]); expect(results.points).to.deep.equal([{ s: GeoCoordStatus.CSMapError, - p: {x: 2, y: 2, z: 2}, + p: { x: 2, y: 2, z: 2 }, }, { s: GeoCoordStatus.Success, p: [1, 2, 3], }, { s: GeoCoordStatus.CSMapError, - p: {x: 3, y: 3, z: 3}, + p: { x: 3, y: 3, z: 3 }, }]); }); }); diff --git a/core/frontend/src/test/DeferredMarkerHtmlRemoval.test.ts b/core/frontend/src/test/DeferredMarkerHtmlRemoval.test.ts index c93045030452..b8e5f7e4ab5e 100644 --- a/core/frontend/src/test/DeferredMarkerHtmlRemoval.test.ts +++ b/core/frontend/src/test/DeferredMarkerHtmlRemoval.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { expect } from "chai"; -import { ScreenViewport } from "../Viewport"; -import { Decorator } from "../ViewManager"; -import { DecorateContext } from "../ViewContext"; import { IModelApp } from "../IModelApp"; -import { openBlankViewport } from "./openBlankViewport"; import { Marker } from "../Marker"; -import { EmptyLocalization } from "@itwin/core-common"; +import { DecorateContext } from "../ViewContext"; +import { Decorator } from "../ViewManager"; +import { ScreenViewport } from "../Viewport"; +import { openBlankViewport } from "./openBlankViewport"; describe("ScreenViewport", () => { beforeEach(async () => { diff --git a/core/frontend/src/test/DisplayStyleState.test.ts b/core/frontend/src/test/DisplayStyleState.test.ts index 78e870877c8c..35e05cbdbf0d 100644 --- a/core/frontend/src/test/DisplayStyleState.test.ts +++ b/core/frontend/src/test/DisplayStyleState.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Code, DisplayStyle3dProps, EmptyLocalization, RenderSchedule, RenderTimelineProps } from "@itwin/core-common"; +import { expect } from "chai"; import { DisplayStyle3dState } from "../DisplayStyleState"; -import { IModelConnection } from "../IModelConnection"; import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; import { createBlankConnection } from "./createBlankConnection"; describe("DisplayStyleState", () => { @@ -59,7 +59,9 @@ describe("DisplayStyleState", () => { expect(this.scheduleScript!.modelTimelines[0].modelId).to.equal(props[0].modelId); } - public get isLoading() { return undefined !== this._queryRenderTimelinePropsPromise; } + public get isLoading() { + return undefined !== this._queryRenderTimelinePropsPromise; + } public async finishLoading() { while (this._queryRenderTimelinePropsPromise) await this._queryRenderTimelinePropsPromise; diff --git a/core/frontend/src/test/ExpectColors.ts b/core/frontend/src/test/ExpectColors.ts index 08e61256ae49..c1f3e9016d45 100644 --- a/core/frontend/src/test/ExpectColors.ts +++ b/core/frontend/src/test/ExpectColors.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef } from "@itwin/core-common"; -import { ScreenViewport } from "../Viewport"; +import { expect } from "chai"; import { ViewRect } from "../common/ViewRect"; +import { ScreenViewport } from "../Viewport"; /** A viewport-color-checking function for tests. Tests for the presence of a list of expected colors in the entire viewport or specified ViewRect. * @internal diff --git a/core/frontend/src/test/ExtensionAdmin.test.ts b/core/frontend/src/test/ExtensionAdmin.test.ts index 6c74fd0d6db0..b567fc6d9f6f 100644 --- a/core/frontend/src/test/ExtensionAdmin.test.ts +++ b/core/frontend/src/test/ExtensionAdmin.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import chai, { expect } from "chai"; -import { ExtensionManifest, RemoteExtensionProvider } from "../core-frontend"; -import { ExtensionAdmin } from "../extension/ExtensionAdmin"; import chaiAsPromised from "chai-as-promised"; import sinon from "sinon"; +import { ExtensionManifest, RemoteExtensionProvider } from "../core-frontend"; +import { ExtensionAdmin } from "../extension/ExtensionAdmin"; describe("ExtensionAdmin", () => { const extensions = [ @@ -23,12 +23,14 @@ describe("ExtensionAdmin", () => { manifestUrl: "https://anotherdomain.com/package.json", }), ]; - const stubManifest: Promise = new Promise((res) => res({ - name: "mock-extension", - version: "1.0.0", - main: "index.js", - activationEvents: [], - })); + const stubManifest: Promise = new Promise((res) => + res({ + name: "mock-extension", + version: "1.0.0", + main: "index.js", + activationEvents: [], + }) + ); before(async () => { chai.use(chaiAsPromised); diff --git a/core/frontend/src/test/FeatureSymbologyOverrides.test.ts b/core/frontend/src/test/FeatureSymbologyOverrides.test.ts index f6ad7f8e2fda..219bea5a3c09 100644 --- a/core/frontend/src/test/FeatureSymbologyOverrides.test.ts +++ b/core/frontend/src/test/FeatureSymbologyOverrides.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { expect } from "chai"; -import { testBlankViewport } from "./openBlankViewport"; import { FeatureSymbology, IModelApp, Viewport, ViewState } from "../core-frontend"; -import { EmptyLocalization } from "@itwin/core-common"; +import { testBlankViewport } from "./openBlankViewport"; describe("FeatureSymbology.Overrides", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/FlashSettings.test.ts b/core/frontend/src/test/FlashSettings.test.ts index ce5d8789bdd4..867c0ad0641a 100644 --- a/core/frontend/src/test/FlashSettings.test.ts +++ b/core/frontend/src/test/FlashSettings.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration } from "@itwin/core-bentley"; +import { expect } from "chai"; import { FlashMode, FlashSettings, FlashSettingsOptions } from "../FlashSettings"; type FlashProps = Pick; @@ -22,15 +22,21 @@ describe("FlashSettings", () => { }); it("normalizes inputs", () => { - expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(-100), litMode: -5 as FlashMode, maxIntensity: -1 }), - { duration: BeDuration.fromSeconds(0), litMode: FlashMode.Brighten, maxIntensity: 0 }, - ); - expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(0), litMode: FlashMode.Brighten, maxIntensity: 0 }), - { duration: BeDuration.fromSeconds(0), litMode: FlashMode.Brighten, maxIntensity: 0 }, - ); - expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(11), litMode: 42 as FlashMode, maxIntensity: 1.1 }), - { duration: BeDuration.fromSeconds(10), litMode: FlashMode.Brighten, maxIntensity: 1 }, - ); + expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(-100), litMode: -5 as FlashMode, maxIntensity: -1 }), { + duration: BeDuration.fromSeconds(0), + litMode: FlashMode.Brighten, + maxIntensity: 0, + }); + expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(0), litMode: FlashMode.Brighten, maxIntensity: 0 }), { + duration: BeDuration.fromSeconds(0), + litMode: FlashMode.Brighten, + maxIntensity: 0, + }); + expectFlash(new FlashSettings({ duration: BeDuration.fromSeconds(11), litMode: 42 as FlashMode, maxIntensity: 1.1 }), { + duration: BeDuration.fromSeconds(10), + litMode: FlashMode.Brighten, + maxIntensity: 1, + }); }); it("clones", () => { @@ -46,12 +52,16 @@ describe("FlashSettings", () => { let settings = clone(defaults, {}, defaults); expect(settings).not.to.equal(defaults); - settings = clone(settings, - { duration: BeDuration.fromSeconds(1), litMode: FlashMode.Hilite }, - { duration: BeDuration.fromSeconds(1), litMode: FlashMode.Hilite, maxIntensity: 1 }); + settings = clone(settings, { duration: BeDuration.fromSeconds(1), litMode: FlashMode.Hilite }, { + duration: BeDuration.fromSeconds(1), + litMode: FlashMode.Hilite, + maxIntensity: 1, + }); - clone(settings, - { duration: BeDuration.fromSeconds(2), maxIntensity: 0.2 }, - { duration: BeDuration.fromSeconds(2), maxIntensity: 0.2, litMode: FlashMode.Hilite }); + clone(settings, { duration: BeDuration.fromSeconds(2), maxIntensity: 0.2 }, { + duration: BeDuration.fromSeconds(2), + maxIntensity: 0.2, + litMode: FlashMode.Hilite, + }); }); }); diff --git a/core/frontend/src/test/GeoServices.test.ts b/core/frontend/src/test/GeoServices.test.ts index 25023f93efda..5bdc6c9e194c 100644 --- a/core/frontend/src/test/GeoServices.test.ts +++ b/core/frontend/src/test/GeoServices.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, BeEvent } from "@itwin/core-bentley"; import { GeographicCRSProps, PointWithStatus } from "@itwin/core-common"; +import { expect } from "chai"; import { GeoServices, GeoServicesOptions } from "../GeoServices"; describe("GeoServices", () => { - function makeGeoServices(opts: Partial = { }): GeoServices { + function makeGeoServices(opts: Partial = {}): GeoServices { return new GeoServices({ isIModelClosed: opts.isIModelClosed ?? (() => false), toIModelCoords: opts.toIModelCoords ?? (async () => Promise.resolve([])), @@ -143,7 +143,9 @@ describe("GeoServices", () => { it("removes converter from cache even if requests produce an exception", async () => { const gs = makeGeoServices({ - toIModelCoords: async () => { throw new Error("oh no!"); }, + toIModelCoords: async () => { + throw new Error("oh no!"); + }, }); const cv = gs.getConverter()!; expect(gs.getConverter()).to.equal(cv); diff --git a/core/frontend/src/test/IModelApp.test.ts b/core/frontend/src/test/IModelApp.test.ts index 7e2ab83b539b..c0995da8f182 100644 --- a/core/frontend/src/test/IModelApp.test.ts +++ b/core/frontend/src/test/IModelApp.test.ts @@ -2,8 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; +import { BentleyStatus, DbResult, IModelStatus } from "@itwin/core-bentley"; import { ITwinLocalization } from "@itwin/core-i18n"; +import { assert, expect } from "chai"; import { AccuDraw } from "../AccuDraw"; import { IModelApp, IModelAppOptions } from "../IModelApp"; import { MockRender } from "../render/MockRender"; @@ -11,13 +12,12 @@ import { IdleTool } from "../tools/IdleTool"; import { SelectionTool } from "../tools/SelectTool"; import { Tool } from "../tools/Tool"; import { PanViewTool, RotateViewTool } from "../tools/ViewTool"; -import { BentleyStatus, DbResult, IModelStatus } from "@itwin/core-bentley"; /** class to simulate overriding the default AccuDraw */ -class TestAccuDraw extends AccuDraw { } +class TestAccuDraw extends AccuDraw {} /** class to simulate overriding the Idle tool */ -class TestIdleTool extends IdleTool { } +class TestIdleTool extends IdleTool {} let testVal1: string; let testVal2: string; @@ -44,8 +44,8 @@ class FourthImmediate extends Tool { public static override toolId = "Test.FourthImmediate"; } -class TestRotateTool extends RotateViewTool { } -class TestSelectTool extends SelectionTool { } +class TestRotateTool extends RotateViewTool {} +class TestSelectTool extends SelectionTool {} class TestApp extends MockRender.App { public static override async startup(opts?: IModelAppOptions): Promise { @@ -66,7 +66,8 @@ class TestApp extends MockRender.App { // register an anonymous class with the toolId "Null.Tool" const testNull = class extends Tool { - public static override toolId = "Null.Tool"; public override async run() { + public static override toolId = "Null.Tool"; + public override async run() { testVal1 = "fromNullTool"; return true; } @@ -74,13 +75,15 @@ class TestApp extends MockRender.App { testNull.register(namespace); } - protected static supplyI18NOptions() { return { urlTemplate: `${window.location.origin}/locales/{{lng}}/{{ns}}.json` }; } + protected static supplyI18NOptions() { + return { urlTemplate: `${window.location.origin}/locales/{{lng}}/{{ns}}.json` }; + } } describe("IModelApp", () => { before(async () => { await TestApp.startup(); - await IModelApp.localization.registerNamespace("TestApp"); // we must wait for the localization read to finish. + await IModelApp.localization.registerNamespace("TestApp"); // we must wait for the localization read to finish. }); after(async () => TestApp.shutdown()); @@ -125,14 +128,24 @@ describe("IModelApp", () => { // we have "TrivialTest.Test1" as the key in TestApp.json assert.equal(IModelApp.localization.getLocalizedString("TestApp:TrivialTests.Test1"), "Localized Trivial Test 1"); assert.equal(IModelApp.localization.getLocalizedString("TestApp:TrivialTests.Test2"), "Localized Trivial Test 2"); - assert.equal(IModelApp.localization.getLocalizedString("LocateFailure.NoElements"), "No Elements Found", "message from default (iModelJs) namespace"); + assert.equal( + IModelApp.localization.getLocalizedString("LocateFailure.NoElements"), + "No Elements Found", + "message from default (iModelJs) namespace", + ); // there is no key for TrivialTest.Test3 assert.equal(IModelApp.localization.getLocalizedString("TestApp:TrivialTests.Test3"), "TrivialTests.Test3"); // Should properly substitute the values in localized strings with interpolations - assert.equal(IModelApp.localization.getLocalizedString("TestApp:SubstitutionTests.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2"); - assert.equal(IModelApp.localization.getLocalizedString("TestApp:SubstitutionTests.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1"); + assert.equal( + IModelApp.localization.getLocalizedString("TestApp:SubstitutionTests.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2", + ); + assert.equal( + IModelApp.localization.getLocalizedString("TestApp:SubstitutionTests.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1", + ); assert.equal(IModelApp.translateStatus(IModelStatus.AlreadyOpen), "Already open"); assert.equal(IModelApp.translateStatus(IModelStatus.DuplicateCode), "Duplicate code"); @@ -142,7 +155,6 @@ describe("IModelApp", () => { assert.equal(IModelApp.translateStatus(101), "DbResult.BE_SQLITE_DONE"); assert.equal(IModelApp.translateStatus(11111), "Status: 11111"); assert.equal(IModelApp.translateStatus(undefined as any), "Illegal value"); - }); it("Should support WebGL", () => { diff --git a/core/frontend/src/test/IModelConnection.test.ts b/core/frontend/src/test/IModelConnection.test.ts index 2d3b5140c29a..8193ff62cb11 100644 --- a/core/frontend/src/test/IModelConnection.test.ts +++ b/core/frontend/src/test/IModelConnection.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { createBlankConnection } from "./createBlankConnection"; -import { EmptyLocalization } from "@itwin/core-common"; describe("IModelConnection", () => { describe("displayed extents", () => { diff --git a/core/frontend/src/test/LookAt.test.ts b/core/frontend/src/test/LookAt.test.ts index d8bff295b7c6..0aab03d07c69 100644 --- a/core/frontend/src/test/LookAt.test.ts +++ b/core/frontend/src/test/LookAt.test.ts @@ -2,17 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Cartographic, EcefLocation, EmptyLocalization } from "@itwin/core-common"; +import { Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { expect } from "chai"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; -import { createBlankConnection } from "./createBlankConnection"; -import { Cartographic, EcefLocation, EmptyLocalization } from "@itwin/core-common"; +import { MarginPercent, PaddingPercent } from "../MarginPercent"; import { SpatialViewState } from "../SpatialViewState"; -import { Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { StandardViewId } from "../StandardView"; import { MarginOptions } from "../ViewAnimation"; -import { MarginPercent, PaddingPercent } from "../MarginPercent"; import { ViewStatus } from "../ViewStatus"; +import { createBlankConnection } from "./createBlankConnection"; describe("Look At", () => { let imodel: IModelConnection; @@ -82,7 +82,10 @@ describe("Look At", () => { return { marginPercent: { - left: percent.left ?? 0, right: percent.right ?? 0, top: percent.top ?? 0, bottom: percent.bottom ?? 0, + left: percent.left ?? 0, + right: percent.right ?? 0, + top: percent.top ?? 0, + bottom: percent.bottom ?? 0, }, }; } @@ -113,8 +116,14 @@ describe("Look At", () => { }); it("prioritizes PaddingPercent over MarginPercent", () => { - expectExtents([0, 0, 100, 100], [-50, -50, 200, 200], { paddingPercent: 0.5, marginPercent: { left: 0, right: 0.25, top: 0.125, bottom: 0.2 } }); - expectExtents([0, 0, 100, 100], [-50, -50, 200, 200], { paddingPercent: undefined, marginPercent: { left: 0.25, right: 0.25, top: 0.25, bottom: 0.25 } }); + expectExtents([0, 0, 100, 100], [-50, -50, 200, 200], { + paddingPercent: 0.5, + marginPercent: { left: 0, right: 0.25, top: 0.125, bottom: 0.2 }, + }); + expectExtents([0, 0, 100, 100], [-50, -50, 200, 200], { + paddingPercent: undefined, + marginPercent: { left: 0.25, right: 0.25, top: 0.25, bottom: 0.25 }, + }); }); }); }); diff --git a/core/frontend/src/test/QuantityFormatter.test.ts b/core/frontend/src/test/QuantityFormatter.test.ts index 6576c9f19668..fdaa96d6a145 100644 --- a/core/frontend/src/test/QuantityFormatter.test.ts +++ b/core/frontend/src/test/QuantityFormatter.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { assert as bAssert } from "@itwin/core-bentley"; import { EmptyLocalization } from "@itwin/core-common"; import { Parser, UnitProps } from "@itwin/core-quantity"; +import { assert } from "chai"; import { IModelApp } from "../IModelApp"; import { LocalUnitFormatProvider } from "../quantity-formatting/LocalUnitFormatProvider"; import { OverrideFormatEntry, QuantityFormatter, QuantityType, QuantityTypeArg } from "../quantity-formatting/QuantityFormatter"; @@ -21,7 +21,8 @@ function withinTolerance(x: number, y: number, tolerance?: number): boolean { /** setup a local storage mock that contains a unit system and QuantityType.Length override format */ const storageMock = () => { const storage: { [key: string]: any } = { - "quantityTypeFormat#user#q:QuantityTypeEnumValue-1": `{"metric":{"type":"Decimal","precision":2,"roundFactor":0,"showSignOption":"OnlyNegative","formatTraits":["keepSingleZero","showUnitLabel"],"decimalSeparator":".","thousandSeparator":",","uomSeparator":" ","stationSeparator":"+","composite":{"spacer":"","includeZero":true,"units":[{"name":"Units.CM","label":"cm"}]}}}`, + "quantityTypeFormat#user#q:QuantityTypeEnumValue-1": + `{"metric":{"type":"Decimal","precision":2,"roundFactor":0,"showSignOption":"OnlyNegative","formatTraits":["keepSingleZero","showUnitLabel"],"decimalSeparator":".","thousandSeparator":",","uomSeparator":" ","stationSeparator":"+","composite":{"spacer":"","includeZero":true,"units":[{"name":"Units.CM","label":"cm"}]}}}`, "unitsystem#user": "metric", }; @@ -91,7 +92,6 @@ describe("Quantity formatter", async () => { precision: 4, type: "Decimal", }, - }; // set the units settings provider that will set the QuantityFormatter to "metric" and provide overrides to display "cm" @@ -195,9 +195,11 @@ describe("Quantity formatter", async () => { assert(Parser.isParsedQuantity(overrideValueInMeters3)); assert(Parser.isParsedQuantity(overrideValueInMeters4)); assert(Parser.isParsedQuantity(overrideValueInMeters5)); - if (Parser.isParsedQuantity(overrideValueInMeters1) && Parser.isParsedQuantity(overrideValueInMeters2) && + if ( + Parser.isParsedQuantity(overrideValueInMeters1) && Parser.isParsedQuantity(overrideValueInMeters2) && Parser.isParsedQuantity(overrideValueInMeters3) && Parser.isParsedQuantity(overrideValueInMeters4) - && Parser.isParsedQuantity(overrideValueInMeters5)) { + && Parser.isParsedQuantity(overrideValueInMeters5) + ) { assert(withinTolerance(overrideValueInMeters1.value, 1.2192)); assert(withinTolerance(overrideValueInMeters1.value, overrideValueInMeters2.value)); assert(withinTolerance(overrideValueInMeters3.value, overrideValueInMeters2.value)); @@ -444,7 +446,10 @@ describe("Quantity formatter", async () => { const toUnit = await quantityFormatter.findUnitByName(toUnitName); const unitConversion = await quantityFormatter.getConversion(fromUnit, toUnit); const convertedValue = (magnitude * unitConversion.factor) + unitConversion.offset; - assert(withinTolerance(convertedValue, expectedValue, tolerance), `Expected ${expectedValue} ${toUnitName}, got ${convertedValue} ${toUnitName}`); + assert( + withinTolerance(convertedValue, expectedValue, tolerance), + `Expected ${expectedValue} ${toUnitName}, got ${convertedValue} ${toUnitName}`, + ); } it("UnitConversionTests, USCustomaryLengths", async () => { diff --git a/core/frontend/src/test/RealityDataSource.test.ts b/core/frontend/src/test/RealityDataSource.test.ts index 21cfb10a40f6..d9e2a6de55fe 100644 --- a/core/frontend/src/test/RealityDataSource.test.ts +++ b/core/frontend/src/test/RealityDataSource.test.ts @@ -31,10 +31,10 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("CesiumIonAsset:ThreeDTile:OSMBuildings:undefined"); }); it("should handle creation from any CesiumIonAsset url (not OSM Building)", () => { - const rdSourceKey = RealityDataSource.createCesiumIonAssetKey(75343,"ThisIsADummyCesiumIonKey"); + const rdSourceKey = RealityDataSource.createCesiumIonAssetKey(75343, "ThisIsADummyCesiumIonKey"); expect(rdSourceKey.provider).to.equal(RealityDataProvider.CesiumIonAsset); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); - const tilesetUrl = getCesiumAssetUrl(75343,"ThisIsADummyCesiumIonKey"); + const tilesetUrl = getCesiumAssetUrl(75343, "ThisIsADummyCesiumIonKey"); expect(rdSourceKey.id).to.be.equal(tilesetUrl); expect(rdSourceKey.iTwinId).to.be.undefined; const rdSourceKeyStr = RealityDataSourceKey.convertToString(rdSourceKey); @@ -49,7 +49,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyFromURLStr).to.be.equal(`CesiumIonAsset:ThreeDTile:${tilesetUrl}:undefined`); }); it("should handle creation from Context Share url", () => { - const tilesetUrl = "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; + const tilesetUrl = + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); @@ -59,7 +60,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:ThreeDTile:994fc408-401f-4ee1-91f0-3d7bfba50136:5b4ebd22-d94b-456b-8bd8-d59563de9acd"); }); it("should handle creation from Context Share url with server context", () => { - const tilesetUrl = "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--server/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; + const tilesetUrl = + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--server/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); @@ -69,7 +71,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:ThreeDTile:994fc408-401f-4ee1-91f0-3d7bfba50136:server"); }); it("should handle creation from Context Share url with empty guid context", () => { - const tilesetUrl = "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--00000000-0000-0000-0000-000000000000/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; + const tilesetUrl = + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--00000000-0000-0000-0000-000000000000/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); @@ -99,7 +102,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:ThreeDTile:c9fddf2c-e519-468b-b6fa-6d0e39f198a7:a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"); }); it("should handle creation from Context Share url using Reality Management apim in QA (qa-api.bentley.com)", () => { - const tilesetUrl = "https://qa-api.bentley.com/reality-management/reality-data/c9fddf2c-e519-468b-b6fa-6d0e39f198a7?iTwinId=a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"; + const tilesetUrl = + "https://qa-api.bentley.com/reality-management/reality-data/c9fddf2c-e519-468b-b6fa-6d0e39f198a7?iTwinId=a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); @@ -109,7 +113,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:ThreeDTile:c9fddf2c-e519-468b-b6fa-6d0e39f198a7:a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"); }); it("should handle creation from Context Share url using Reality Management apim in PROD (api.bentley.com)", () => { - const tilesetUrl = "https://api.bentley.com/reality-management/reality-data/c9fddf2c-e519-468b-b6fa-6d0e39f198a7?iTwinId=a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"; + const tilesetUrl = + "https://api.bentley.com/reality-management/reality-data/c9fddf2c-e519-468b-b6fa-6d0e39f198a7?iTwinId=a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.ThreeDTile); @@ -119,7 +124,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:ThreeDTile:c9fddf2c-e519-468b-b6fa-6d0e39f198a7:a57f6b1c-747d-4253-b0ce-9900c4dd7c1c"); }); it("should handle creation from url to an .opc file on an azure blob", () => { - const tilesetUrl = "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; + const tilesetUrl = + "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; const rdSourceKey = RealityDataSource.createKeyFromBlobUrl(tilesetUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.OPC); @@ -170,7 +176,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("TilesetUrl:ThreeDTile:Anything that is not a valid url:undefined"); }); it("should handle creation from Context Share url with provider override", () => { - const tilesetUrl = "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; + const tilesetUrl = + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; const forceProvider = RealityDataProvider.TilesetUrl; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl, forceProvider); expect(rdSourceKey.provider).to.equal(forceProvider); @@ -181,7 +188,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("TilesetUrl:ThreeDTile:994fc408-401f-4ee1-91f0-3d7bfba50136:5b4ebd22-d94b-456b-8bd8-d59563de9acd"); }); it("should handle creation from Context Share url with format override", () => { - const tilesetUrl = "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; + const tilesetUrl = + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136"; const forceFormat = RealityDataFormat.OPC; const rdSourceKey = RealityDataSource.createKeyFromUrl(tilesetUrl, undefined, forceFormat); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); @@ -193,7 +201,8 @@ describe("RealityDataSource", () => { }); it("should handle creation from a blob url to an .opc file on an azure blob", () => { - const blobUrl = "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; + const blobUrl = + "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; const rdSourceKey = RealityDataSource.createKeyFromBlobUrl(blobUrl); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); expect(rdSourceKey.format).to.equal(RealityDataFormat.OPC); @@ -203,7 +212,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("ContextShare:OPC:fe8d32a5-f6ab-4157-b3ec-a9b53db923e3:undefined"); }); it("should handle creation from blob url with provider override", () => { - const blobUrl = "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; + const blobUrl = + "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; const forceProvider = RealityDataProvider.TilesetUrl; const rdSourceKey = RealityDataSource.createKeyFromBlobUrl(blobUrl, forceProvider); expect(rdSourceKey.provider).to.equal(forceProvider); @@ -214,7 +224,8 @@ describe("RealityDataSource", () => { expect(rdSourceKeyStr).to.be.equal("TilesetUrl:OPC:fe8d32a5-f6ab-4157-b3ec-a9b53db923e3:undefined"); }); it("should handle creation from blob url with format override", () => { - const blobUrl = "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; + const blobUrl = + "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D"; const forceFormat = RealityDataFormat.ThreeDTile; const rdSourceKey = RealityDataSource.createKeyFromBlobUrl(blobUrl, undefined, forceFormat); expect(rdSourceKey.provider).to.equal(RealityDataProvider.ContextShare); @@ -234,10 +245,14 @@ describe("RealityDataSource", () => { const rdSourceKey = RealityDataSource.createKeyFromOrbitGtBlobProps(orbitGtBlob); expect(rdSourceKey.provider).to.equal(RealityDataProvider.OrbitGtBlob); expect(rdSourceKey.format).to.equal(RealityDataFormat.OPC); - expect(rdSourceKey.id).to.be.equal("ocpalphaeudata001:a5932aa8-2fde-470d-b5ab-637412ec4e49:/datasources/0b2ad731-ec01-4b8b-8f0f-c99a593f1ff3/Seinajoki_Trees_utm.opc:?sig=EaHCCCSX6bWw%2FOHgad%2Fn3VCgUs2gPbDn%2BE2p5osMYIg%3D&se=2022-01-11T12%3A01%3A20Z&sv=2019-02-02&sp=r&sr=b"); + expect(rdSourceKey.id).to.be.equal( + "ocpalphaeudata001:a5932aa8-2fde-470d-b5ab-637412ec4e49:/datasources/0b2ad731-ec01-4b8b-8f0f-c99a593f1ff3/Seinajoki_Trees_utm.opc:?sig=EaHCCCSX6bWw%2FOHgad%2Fn3VCgUs2gPbDn%2BE2p5osMYIg%3D&se=2022-01-11T12%3A01%3A20Z&sv=2019-02-02&sp=r&sr=b", + ); expect(rdSourceKey.iTwinId).to.be.undefined; const rdSourceKeyStr = RealityDataSourceKey.convertToString(rdSourceKey); - expect(rdSourceKeyStr).to.be.equal("OrbitGtBlob:OPC:ocpalphaeudata001:a5932aa8-2fde-470d-b5ab-637412ec4e49:/datasources/0b2ad731-ec01-4b8b-8f0f-c99a593f1ff3/Seinajoki_Trees_utm.opc:?sig=EaHCCCSX6bWw%2FOHgad%2Fn3VCgUs2gPbDn%2BE2p5osMYIg%3D&se=2022-01-11T12%3A01%3A20Z&sv=2019-02-02&sp=r&sr=b:undefined"); + expect(rdSourceKeyStr).to.be.equal( + "OrbitGtBlob:OPC:ocpalphaeudata001:a5932aa8-2fde-470d-b5ab-637412ec4e49:/datasources/0b2ad731-ec01-4b8b-8f0f-c99a593f1ff3/Seinajoki_Trees_utm.opc:?sig=EaHCCCSX6bWw%2FOHgad%2Fn3VCgUs2gPbDn%2BE2p5osMYIg%3D&se=2022-01-11T12%3A01%3A20Z&sv=2019-02-02&sp=r&sr=b:undefined", + ); const orbitGtBlobFromKey = RealityDataSource.createOrbitGtBlobPropsFromKey(rdSourceKey); expect(orbitGtBlobFromKey).to.not.be.undefined; if (orbitGtBlobFromKey !== undefined) { @@ -251,7 +266,8 @@ describe("RealityDataSource", () => { const orbitGtBlob: OrbitGtBlobProps = { accountName: "", containerName: "fe8d32a5-f6ab-4157-b3ec-a9b53db923e3", - blobFileName: "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D", + blobFileName: + "https://realityblobqaeussa01.blob.core.windows.net/fe8d32a5-f6ab-4157-b3ec-a9b53db923e3/Tuxford.opc?sv=2020-08-04&se=2021-08-26T05%3A11%3A31Z&sr=c&sp=rl&sig=J9wGT1f3nyKePPj%2FI%2BJdx086GylEfM0P4ZXBQL%2FaRD4%3D", sasToken: "", }; const rdSourceKey = RealityDataSource.createKeyFromOrbitGtBlobProps(orbitGtBlob); @@ -266,7 +282,8 @@ describe("RealityDataSource", () => { }); it("should handle creation from orbitGtBlobProps when rdsUrl is defined", () => { const orbitGtBlob: OrbitGtBlobProps = { - rdsUrl: "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136", + rdsUrl: + "https://connect-realitydataservices.bentley.com/v2.9/Repositories/S3MXECPlugin--5b4ebd22-d94b-456b-8bd8-d59563de9acd/S3MX/RealityData/994fc408-401f-4ee1-91f0-3d7bfba50136", accountName: "", containerName: "", blobFileName: "", diff --git a/core/frontend/src/test/RealityDataSourceTilesetUrl.test.ts b/core/frontend/src/test/RealityDataSourceTilesetUrl.test.ts index 870f486a141b..a2e27e99a174 100644 --- a/core/frontend/src/test/RealityDataSourceTilesetUrl.test.ts +++ b/core/frontend/src/test/RealityDataSourceTilesetUrl.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { RealityDataProvider } from "@itwin/core-common"; +import { expect } from "chai"; import { RealityDataSourceTilesetUrlImpl } from "../RealityDataSourceTilesetUrlImpl"; describe("RealityDataSourceTilesetUrl", () => { it("handle content type of relative urls", async () => { - const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider : RealityDataProvider.TilesetUrl }, undefined); + const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider: RealityDataProvider.TilesetUrl }, undefined); expect(rdSource).to.not.be.undefined; expect(rdSource?.getTileContentType("tileset.json")).to.equal("tileset"); expect(rdSource?.getTileContentType("tile.glb")).to.equal("tile"); @@ -48,7 +48,7 @@ describe("RealityDataSourceTilesetUrl", () => { expect(rdSource?.getTileContentType("models/tile.glb#fragment")).to.equal("tile"); }); it("handle content type of absolute urls", async () => { - const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider : RealityDataProvider.TilesetUrl }, undefined); + const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider: RealityDataProvider.TilesetUrl }, undefined); expect(rdSource).to.not.be.undefined; expect(rdSource?.getTileContentType("https://localhost/tilesets/tileset.json")).to.equal("tileset"); expect(rdSource?.getTileContentType("https://localhost/models/tile.glb")).to.equal("tile"); @@ -60,7 +60,7 @@ describe("RealityDataSourceTilesetUrl", () => { expect(rdSource?.getTileContentType("https://localhost/models/tile.glb#fragment")).to.equal("tile"); }); it("handle content type of other cases", async () => { - const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider : RealityDataProvider.TilesetUrl }, undefined); + const rdSource = await RealityDataSourceTilesetUrlImpl.createFromKey({ format: "", id: "", provider: RealityDataProvider.TilesetUrl }, undefined); expect(rdSource).to.not.be.undefined; expect(rdSource?.getTileContentType("")).to.not.equal("tileset"); expect(rdSource?.getTileContentType("tileset.json/")).to.not.equal("tileset"); diff --git a/core/frontend/src/test/Request.test.ts b/core/frontend/src/test/Request.test.ts index 0e126644c4b5..1f033406e56b 100644 --- a/core/frontend/src/test/Request.test.ts +++ b/core/frontend/src/test/Request.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import sinon from "sinon"; -import { HttpResponseError, request, RequestBasicCredentials } from "../request/Request"; import { assert, expect, use } from "chai"; import chaiAsPromised from "chai-as-promised"; +import sinon from "sinon"; +import { HttpResponseError, request, RequestBasicCredentials } from "../request/Request"; use(chaiAsPromised); diff --git a/core/frontend/src/test/SpatialViewState.test.ts b/core/frontend/src/test/SpatialViewState.test.ts index e1a16e8be513..2393ac4d484d 100644 --- a/core/frontend/src/test/SpatialViewState.test.ts +++ b/core/frontend/src/test/SpatialViewState.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Range3d } from "@itwin/core-geometry"; import { EmptyLocalization } from "@itwin/core-common"; -import { SpatialViewState } from "../SpatialViewState"; -import type { IModelConnection } from "../IModelConnection"; +import { Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { restore as sinonRestore, spy as sinonSpy } from "sinon"; import { IModelApp } from "../IModelApp"; +import type { IModelConnection } from "../IModelConnection"; +import { SpatialViewState } from "../SpatialViewState"; import { RealityModelTileTree, TileTreeLoadStatus, TileTreeReference } from "../tile/internal"; import { createBlankConnection } from "./createBlankConnection"; -import { restore as sinonRestore, spy as sinonSpy } from "sinon"; describe("SpatialViewState", () => { afterEach(() => { @@ -73,10 +73,13 @@ describe("SpatialViewState", () => { describe("computeFitRange", () => { it("unions ranges of all tile trees", () => { expectFitRange(createView([new Range3d(0, 1, 2, 3, 4, 5)]), new Range3d(0, 1, 2, 3, 4, 5)); - expectFitRange(createView([ - new Range3d(0, 1, 2, 3, 4, 5), - new Range3d(-1, 2, 2, 2, 5, 7), - ]), new Range3d(-1, 1, 2, 3, 5, 7)); + expectFitRange( + createView([ + new Range3d(0, 1, 2, 3, 4, 5), + new Range3d(-1, 2, 2, 2, 5, 7), + ]), + new Range3d(-1, 1, 2, 3, 5, 7), + ); }); it("falls back to slightly-expanded project extents upon null range", () => { @@ -105,7 +108,7 @@ describe("SpatialViewState", () => { it("does not include invisible context reality models when computing range", () => { const view = createView([new Range3d(-1, 2, 2, 2, 5, 7)]); - const state = view.displayStyle.attachRealityModel({tilesetUrl: "https://fake.com"}); + const state = view.displayStyle.attachRealityModel({ tilesetUrl: "https://fake.com" }); state.invisible = true; const unionFitRangeSpy = sinonSpy(RealityModelTileTree.Reference.prototype, "unionFitRange"); diff --git a/core/frontend/src/test/TestDecorators.ts b/core/frontend/src/test/TestDecorators.ts index 7ae304cff883..c0e67c503760 100644 --- a/core/frontend/src/test/TestDecorators.ts +++ b/core/frontend/src/test/TestDecorators.ts @@ -5,10 +5,10 @@ import { ColorDef } from "@itwin/core-common"; import { Point3d, Sphere, Transform } from "@itwin/core-geometry"; +import { GraphicBranch, GraphicType, PickableGraphicOptions } from "../core-frontend"; import { IModelApp } from "../IModelApp"; import { DecorateContext } from "../ViewContext"; import { ScreenViewport } from "../Viewport"; -import { GraphicBranch, GraphicType, PickableGraphicOptions } from "../core-frontend"; /** A base class used strictly for `instanceof` checks in tests. * @internal @@ -101,7 +101,14 @@ export class BoxDecorator extends TestDecorator { * @internal */ export class SphereDecorator extends TestDecorator { - public constructor(public readonly vp: ScreenViewport, public readonly color: ColorDef, public readonly pickable?: PickableGraphicOptions, public readonly placement?: Transform, private _center: Point3d = new Point3d(), private _radius: number = 1) { + public constructor( + public readonly vp: ScreenViewport, + public readonly color: ColorDef, + public readonly pickable?: PickableGraphicOptions, + public readonly placement?: Transform, + private _center: Point3d = new Point3d(), + private _radius: number = 1, + ) { super(); IModelApp.viewManager.addDecorator(this); } diff --git a/core/frontend/src/test/ToolRegistry.test.ts b/core/frontend/src/test/ToolRegistry.test.ts index f443a3941bbe..9614e3919ba4 100644 --- a/core/frontend/src/test/ToolRegistry.test.ts +++ b/core/frontend/src/test/ToolRegistry.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { ITwinLocalization } from "@itwin/core-i18n"; +import { assert, expect } from "chai"; import { FuzzySearchResult, FuzzySearchResults } from "../FuzzySearch"; import { IModelApp } from "../IModelApp"; import { MockRender } from "../render/MockRender"; @@ -22,8 +22,12 @@ class TestImmediate extends Tool { testVal2 = v2; return true; } - public static override get minArgs() { return 2; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 2; + } + public static override get maxArgs() { + return 2; + } public override async parseAndRun(v1: string, v2: string): Promise { if (arguments.length !== 2) return false; @@ -42,7 +46,9 @@ class TestCommandApp extends MockRender.App { TestImmediate.register(this.testNamespace); } - protected static supplyI18NOptions() { return { urlTemplate: `${window.location.origin}/locales/{{lng}}/{{ns}}.json` }; } + protected static supplyI18NOptions() { + return { urlTemplate: `${window.location.origin}/locales/{{lng}}/{{ns}}.json` }; + } } async function setupToolRegistryTests() { @@ -233,8 +239,9 @@ function registerTestClass(id: string, keyin: string, ns: string) { return true; } - public static override get keyin(): string { return keyin; } - + public static override get keyin(): string { + return keyin; + } }).register(ns); } diff --git a/core/frontend/src/test/TxnEntityChanges.test.ts b/core/frontend/src/test/TxnEntityChanges.test.ts index f2db90b44d4b..d5843874d210 100644 --- a/core/frontend/src/test/TxnEntityChanges.test.ts +++ b/core/frontend/src/test/TxnEntityChanges.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { NotifyEntitiesChangedArgs, NotifyEntitiesChangedMetadata } from "@itwin/core-common"; import { expect } from "chai"; import { EntityChanges, Metadata, TxnEntityChangeIterable, TxnEntityChangeType } from "../TxnEntityChanges"; -import { NotifyEntitiesChangedArgs, NotifyEntitiesChangedMetadata } from "@itwin/core-common"; describe("TxnEntityMetadata", () => { describe("is", () => { @@ -43,7 +43,9 @@ describe("TxnEntityChanges", () => { it("populates metadata from args", () => { function populate(met: NotifyEntitiesChangedMetadata[]): Metadata[] { const args: NotifyEntitiesChangedArgs = { - insertedMeta: [], updatedMeta: [], deletedMeta: [], + insertedMeta: [], + updatedMeta: [], + deletedMeta: [], meta: met, }; @@ -128,7 +130,10 @@ describe("TxnEntityChanges", () => { it("iterates", () => { let changes = new EntityChanges({ - insertedMeta: [], updatedMeta: [], deletedMeta: [], meta: [], + insertedMeta: [], + updatedMeta: [], + deletedMeta: [], + meta: [], }); expectEntities(changes, []); @@ -189,7 +194,7 @@ describe("TxnEntityChanges", () => { ], }); - expectEntities(changes.filter({ }), [ + expectEntities(changes.filter({}), [ [1, "a", "inserted"], [2, "b", "inserted"], [3, "c", "inserted"], @@ -233,7 +238,7 @@ describe("TxnEntityChanges", () => { [9, "b", "updated"], ]); - expectEntities(changes.filter({ includeMetadata: (meta) => meta.is("a"), includeTypes: ["inserted", "deleted" ]}), [ + expectEntities(changes.filter({ includeMetadata: (meta) => meta.is("a"), includeTypes: ["inserted", "deleted"] }), [ [1, "a", "inserted"], [2, "b", "inserted"], [3, "c", "inserted"], diff --git a/core/frontend/src/test/ViewManager.test.ts b/core/frontend/src/test/ViewManager.test.ts index def40ff17ece..3cc799919104 100644 --- a/core/frontend/src/test/ViewManager.test.ts +++ b/core/frontend/src/test/ViewManager.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ColorDef, EmptyLocalization } from "@itwin/core-common"; import { assert, expect } from "chai"; import { OnScreenTarget } from "../core-frontend"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { createBlankConnection } from "./createBlankConnection"; -import { openBlankViewport } from "./openBlankViewport"; import { expectColors } from "./ExpectColors"; -import { ColorDef, EmptyLocalization } from "@itwin/core-common"; +import { openBlankViewport } from "./openBlankViewport"; describe("ViewManager", () => { let imodel: IModelConnection; diff --git a/core/frontend/src/test/ViewRect.test.ts b/core/frontend/src/test/ViewRect.test.ts index 8991f6ff0a77..512de08141e7 100644 --- a/core/frontend/src/test/ViewRect.test.ts +++ b/core/frontend/src/test/ViewRect.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { ViewRect } from "../common/ViewRect"; import { getCenteredViewRect } from "../common/ImageUtil"; +import { ViewRect } from "../common/ViewRect"; function expectRect(rect: ViewRect, l: number, t: number, r: number, b: number): void { expect(rect.left).to.equal(l); @@ -16,7 +16,7 @@ function expectRect(rect: ViewRect, l: number, t: number, r: number, b: number): describe("ViewRect", () => { it("rounds negative inputs up to zero", () => { - expectRect(new ViewRect(-0.001, -50, 1, 2), 0, 0, 1, 2); + expectRect(new ViewRect(-0.001, -50, 1, 2), 0, 0, 1, 2); }); it("truncates inputs", () => { diff --git a/core/frontend/src/test/Viewport.test.ts b/core/frontend/src/test/Viewport.test.ts index ab398f852671..f3f5f9e4fcad 100644 --- a/core/frontend/src/test/Viewport.test.ts +++ b/core/frontend/src/test/Viewport.test.ts @@ -3,25 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64String, UnexpectedErrors } from "@itwin/core-bentley"; +import { AnalysisStyle, ColorDef, EmptyLocalization, Feature, ImageBuffer, ImageBufferFormat, ImageMapLayerSettings } from "@itwin/core-common"; import { Point2d, Point3d } from "@itwin/core-geometry"; -import { - AnalysisStyle, ColorDef, EmptyLocalization, Feature, ImageBuffer, ImageBufferFormat, ImageMapLayerSettings, -} from "@itwin/core-common"; +import { expect } from "chai"; +import * as sinon from "sinon"; +import { GraphicType } from "../common/render/GraphicType"; import { ViewRect } from "../common/ViewRect"; -import { OffScreenViewport, ScreenViewport, Viewport } from "../Viewport"; import { DisplayStyle3dState } from "../DisplayStyleState"; -import { SpatialViewState } from "../SpatialViewState"; import { IModelApp } from "../IModelApp"; -import { openBlankViewport, readUniqueFeatures, testBlankViewport, testBlankViewportAsync } from "./openBlankViewport"; -import { createBlankConnection } from "./createBlankConnection"; -import { DecorateContext } from "../ViewContext"; import { Pixel } from "../render/Pixel"; -import * as sinon from "sinon"; -import { GraphicType } from "../common/render/GraphicType"; import { RenderGraphic } from "../render/RenderGraphic"; +import { SpatialViewState } from "../SpatialViewState"; +import { DecorateContext } from "../ViewContext"; import { Decorator } from "../ViewManager"; +import { OffScreenViewport, ScreenViewport, Viewport } from "../Viewport"; +import { createBlankConnection } from "./createBlankConnection"; +import { openBlankViewport, readUniqueFeatures, testBlankViewport, testBlankViewportAsync } from "./openBlankViewport"; describe("Viewport", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); @@ -31,7 +29,9 @@ describe("Viewport", () => { it("invokes initialize method", () => { class ScreenVp extends ScreenViewport { public initialized = false; - protected override initialize() { this.initialized = true; } + protected override initialize() { + this.initialized = true; + } public static createVp(view: SpatialViewState): ScreenVp { const parentDiv = document.createElement("div"); @@ -45,14 +45,16 @@ describe("Viewport", () => { class OffScreenVp extends OffScreenViewport { public initialized = false; - protected override initialize() { this.initialized = true; } + protected override initialize() { + this.initialized = true; + } public static createVp(view: SpatialViewState): OffScreenVp { return this.create({ view, viewRect: new ViewRect(0, 0, 100, 100) }) as OffScreenVp; } } - function test(ctor: (typeof ScreenVp | typeof OffScreenVp)): void { + function test(ctor: typeof ScreenVp | typeof OffScreenVp): void { const iModel = createBlankConnection(); const view = SpatialViewState.createBlank(iModel, { x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }); const vp = ctor.createVp(view); @@ -68,7 +70,12 @@ describe("Viewport", () => { describe("flashedId", () => { type ChangedEvent = [string | undefined, string | undefined]; - function expectFlashedId(viewport: ScreenViewport, expectedId: string | undefined, expectedEvent: ChangedEvent | undefined, func: () => void): void { + function expectFlashedId( + viewport: ScreenViewport, + expectedId: string | undefined, + expectedEvent: ChangedEvent | undefined, + func: () => void, + ): void { let event: ChangedEvent | undefined; const removeListener = viewport.onFlashedIdChanged.addListener((vp, arg) => { expect(vp).to.equal(viewport); @@ -114,7 +121,10 @@ describe("Viewport", () => { testBlankViewport((viewport) => { const oldHandler = UnexpectedErrors.setHandler(UnexpectedErrors.reThrowImmediate); viewport.onFlashedIdChanged.addOnce(() => viewport.flashedId = "0x12345"); - expect(() => viewport.flashedId = "0x12345").to.throw(Error, "Cannot assign to Viewport.flashedId from within an onFlashedIdChanged event callback"); + expect(() => viewport.flashedId = "0x12345").to.throw( + Error, + "Cannot assign to Viewport.flashedId from within an onFlashedIdChanged event callback", + ); UnexpectedErrors.setHandler(oldHandler); }); }); @@ -310,7 +320,9 @@ describe("Viewport", () => { const actual: string[] = []; for (let i = 0; i < expected.length; i++) { const offset = i * 4; - actual.push(ColorDef.from(image.data[offset], image.data[offset + 1], image.data[offset + 2], 0xff - image.data[offset + 3]).tbgr.toString(16)); + actual.push( + ColorDef.from(image.data[offset], image.data[offset + 1], image.data[offset + 2], 0xff - image.data[offset + 3]).tbgr.toString(16), + ); } expect(actual).to.deep.equal(expected); @@ -319,8 +331,10 @@ describe("Viewport", () => { const rgbw2: TestCase = { width: 2, image: [ - ColorDef.red, ColorDef.green, - ColorDef.blue, ColorDef.white, + ColorDef.red, + ColorDef.green, + ColorDef.blue, + ColorDef.white, ], }; @@ -351,9 +365,15 @@ describe("Viewport", () => { const square3: TestCase = { width: 3, image: [ - ColorDef.red, ColorDef.green, ColorDef.blue, - ColorDef.white, ColorDef.black, grey, - cyan, purple, yellow, + ColorDef.red, + ColorDef.green, + ColorDef.blue, + ColorDef.white, + ColorDef.black, + grey, + cyan, + purple, + yellow, ], }; @@ -445,7 +465,12 @@ describe("Viewport", () => { it("resizes", () => { test({ ...rgbw2, bgColor: grey }, (viewport) => { - const resize = (w: number, h: number, expectedBarPixels?: { top?: number, bottom?: number, left?: number, right?: number }, expectedColors?: ColorDef[]) => { + const resize = ( + w: number, + h: number, + expectedBarPixels?: { top?: number, bottom?: number, left?: number, right?: number }, + expectedColors?: ColorDef[], + ) => { const image = viewport.readImageBuffer({ size: { x: w, y: h } })!; expect(image).not.to.be.undefined; expect(image.width).to.equal(w); @@ -471,24 +496,39 @@ describe("Viewport", () => { resize(4, 4); resize(1, 1); resize(4, 2, { left: 1, right: 1 }, [ - grey, ColorDef.red, ColorDef.green, grey, - grey, ColorDef.blue, ColorDef.white, grey, + grey, + ColorDef.red, + ColorDef.green, + grey, + grey, + ColorDef.blue, + ColorDef.white, + grey, ]); resize(2, 4, { top: 1, bottom: 1 }, [ - grey, grey, - ColorDef.red, ColorDef.green, - ColorDef.blue, ColorDef.white, - grey, grey, + grey, + grey, + ColorDef.red, + ColorDef.green, + ColorDef.blue, + ColorDef.white, + grey, + grey, ]); resize(8, 4, { left: 2, right: 2 }); resize(4, 8, { top: 2, bottom: 2 }); resize(3, 2, { left: 1 }); resize(2, 5, { top: 1, bottom: 2 }, [ - grey, grey, - ColorDef.red, ColorDef.green, - ColorDef.blue, ColorDef.white, - grey, grey, - grey, grey, + grey, + grey, + ColorDef.red, + ColorDef.green, + ColorDef.blue, + ColorDef.white, + grey, + grey, + grey, + grey, ]); }); }); @@ -590,7 +630,11 @@ describe("Viewport", () => { public constructor(z: number, id: string, vp: Viewport) { const pts = [ - new Point3d(-10, -10, z), new Point3d(10, -10, z), new Point3d(10, 10, z), new Point3d(-10, 10, z), new Point3d(-10, -10, z), + new Point3d(-10, -10, z), + new Point3d(10, -10, z), + new Point3d(10, 10, z), + new Point3d(-10, 10, z), + new Point3d(-10, -10, z), ]; vp.viewToWorldArray(pts); @@ -639,7 +683,11 @@ describe("Viewport", () => { it("can filter out specified elements within a single batch", () => { testBlankViewport((vp) => { const frontPts = [ - new Point3d(-10, -10, 0), new Point3d(10, -10, 0), new Point3d(10, 10, 0), new Point3d(-10, 10, 0), new Point3d(-10, -10, 0), + new Point3d(-10, -10, 0), + new Point3d(10, -10, 0), + new Point3d(10, 10, 0), + new Point3d(-10, 10, 0), + new Point3d(-10, -10, 0), ]; const backPts = frontPts.map((pt) => new Point3d(pt.x, pt.y, -10)); @@ -712,7 +760,7 @@ describe("Viewport", () => { const stub = sinon.stub(Viewport.prototype, "mapLayerFromIds").callsFake(function _(_mapTreeId: Id64String, _layerTreeId: Id64String) { return []; }); - const fakePixelData = {modelId: "123", elementId: "456"}; + const fakePixelData = { modelId: "123", elementId: "456" }; expect(vp.isPixelSelectable(fakePixelData as any)).to.be.true; stub.restore(); }); diff --git a/core/frontend/src/test/ViewportSync.test.ts b/core/frontend/src/test/ViewportSync.test.ts index 442720e99cd7..004cbf1e0617 100644 --- a/core/frontend/src/test/ViewportSync.test.ts +++ b/core/frontend/src/test/ViewportSync.test.ts @@ -3,13 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { EmptyLocalization, ViewFlags } from "@itwin/core-common"; +import { expect } from "chai"; import { IModelApp } from "../IModelApp"; import { StandardViewId } from "../StandardView"; import { Viewport } from "../Viewport"; import { - connectViewports, synchronizeViewportFrusta, synchronizeViewportViews, TwoWayViewportFrustumSync, TwoWayViewportSync, + connectViewports, + synchronizeViewportFrusta, + synchronizeViewportViews, + TwoWayViewportFrustumSync, + TwoWayViewportSync, } from "../ViewportSync"; import { openBlankViewport } from "./openBlankViewport"; @@ -112,7 +116,6 @@ describe("TwoWayViewportSync", () => { test(TwoWayViewportSync, true); test(TwoWayViewportFrustumSync, false); - }); it("synchronizes selectors", () => { diff --git a/core/frontend/src/test/createBlankConnection.ts b/core/frontend/src/test/createBlankConnection.ts index a6a88b77c3f7..7633b76102c3 100644 --- a/core/frontend/src/test/createBlankConnection.ts +++ b/core/frontend/src/test/createBlankConnection.ts @@ -3,14 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Guid } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { BlankConnection } from "../IModelConnection"; /** Open a blank connection for tests. */ -export function createBlankConnection(name = "test-blank-connection", +export function createBlankConnection( + name = "test-blank-connection", location = Cartographic.fromDegrees({ longitude: -75.686694, latitude: 40.065757, height: 0 }), extents = new Range3d(-1000, -1000, -100, 1000, 1000, 100), - iTwinId = Guid.createValue()): BlankConnection { + iTwinId = Guid.createValue(), +): BlankConnection { return BlankConnection.create({ name, location, extents, iTwinId }); } diff --git a/core/frontend/src/test/openBlankViewport.ts b/core/frontend/src/test/openBlankViewport.ts index 83ab3ca0c9fa..b6a8fbd8bdf9 100644 --- a/core/frontend/src/test/openBlankViewport.ts +++ b/core/frontend/src/test/openBlankViewport.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Dictionary, Id64String, SortedArray } from "@itwin/core-bentley"; import { ColorDef, Feature, GeometryClass } from "@itwin/core-common"; -import { BlankConnection } from "../IModelConnection"; -import { ScreenViewport, Viewport } from "../Viewport"; +import { expect } from "chai"; import { ViewRect } from "../common/ViewRect"; -import { SpatialViewState } from "../SpatialViewState"; +import { BlankConnection } from "../IModelConnection"; import { Pixel } from "../render/Pixel"; +import { SpatialViewState } from "../SpatialViewState"; +import { ScreenViewport, Viewport } from "../Viewport"; import { createBlankConnection } from "./createBlankConnection"; /** Options for openBlankViewport. @@ -88,7 +88,7 @@ export function testBlankViewport(args: TestBlankViewportOptions | ((vp: ScreenV /** Open a viewport for a blank spatial view, invoke a test function, then dispose of the viewport and remove it from the DOM. * @internal */ -export async function testBlankViewportAsync(args: ((vp: ScreenViewport) => Promise)): Promise { +export async function testBlankViewportAsync(args: (vp: ScreenViewport) => Promise): Promise { const vp = openBlankViewport(typeof args === "function" ? undefined : args); try { await args(vp); @@ -131,19 +131,30 @@ export class PixelDataSet extends SortedArray { super((lhs: Pixel.Data, rhs: Pixel.Data) => comparePixelData(lhs, rhs)); } - public get array(): Pixel.Data[] { return this._array; } + public get array(): Pixel.Data[] { + return this._array; + } public containsFeature(elemId?: Id64String, subcatId?: Id64String, geomClass?: GeometryClass, modelId?: Id64String) { return this.containsWhere((pxl) => (undefined === elemId || pxl.elementId === elemId) && (undefined === subcatId || pxl.subCategoryId === subcatId) && (undefined === geomClass || pxl.geometryClass === geomClass) && - (undefined === modelId || pxl.modelId === modelId)); + (undefined === modelId || pxl.modelId === modelId) + ); + } + public containsElement(id: Id64String) { + return this.containsWhere((pxl) => pxl.elementId === id); + } + public containsPlanarity(planarity: Pixel.Planarity) { + return this.containsWhere((pxl) => pxl.planarity === planarity); + } + public containsGeometryType(type: Pixel.GeometryType) { + return this.containsWhere((pxl) => pxl.type === type); + } + public containsGeometry(type: Pixel.GeometryType, planarity: Pixel.Planarity) { + return this.containsWhere((pxl) => pxl.type === type && pxl.planarity === planarity); } - public containsElement(id: Id64String) { return this.containsWhere((pxl) => pxl.elementId === id); } - public containsPlanarity(planarity: Pixel.Planarity) { return this.containsWhere((pxl) => pxl.planarity === planarity); } - public containsGeometryType(type: Pixel.GeometryType) { return this.containsWhere((pxl) => pxl.type === type); } - public containsGeometry(type: Pixel.GeometryType, planarity: Pixel.Planarity) { return this.containsWhere((pxl) => pxl.type === type && pxl.planarity === planarity); } public containsWhere(criterion: (pxl: Pixel.Data) => boolean) { for (const pixel of this.array) if (criterion(pixel)) @@ -174,7 +185,9 @@ export class Color { this.a = ((val & 0xff000000) >>> 0x18) >>> 0; } - public static from(val: number) { return new Color(val); } + public static from(val: number) { + return new Color(val); + } public static fromRgba(r: number, g: number, b: number, a: number) { const v = (r | (g << 0x08) | (b << 0x10) | (a << 0x18)) >>> 0; return Color.from(v); @@ -204,12 +217,24 @@ export class Color { * @internal */ export class ColorSet extends SortedArray { - public constructor() { super((lhs: Color, rhs: Color) => lhs.compare(rhs)); } - public get array(): Color[] { return this._array; } - public containsColorDef(color: ColorDef): boolean { return this.contains(Color.fromColorDef(color)); } + public constructor() { + super((lhs: Color, rhs: Color) => lhs.compare(rhs)); + } + public get array(): Color[] { + return this._array; + } + public containsColorDef(color: ColorDef): boolean { + return this.contains(Color.fromColorDef(color)); + } } -export function processPixels(vp: Viewport, processor: (pixel: Pixel.Data) => void, readRect?: ViewRect, excludeNonLocatable?: boolean, excludedElements?: Iterable): void { +export function processPixels( + vp: Viewport, + processor: (pixel: Pixel.Data) => void, + readRect?: ViewRect, + excludeNonLocatable?: boolean, + excludedElements?: Iterable, +): void { const rect = undefined !== readRect ? readRect : vp.viewRect; vp.readPixels({ @@ -237,20 +262,35 @@ export function processPixels(vp: Viewport, processor: (pixel: Pixel.Data) => vo * Omit `readRect` to read the contents of the entire viewport. * @internal */ -export function readUniquePixelData(vp: Viewport, readRect?: ViewRect, excludeNonLocatable = false, excludedElements?: Iterable): PixelDataSet { +export function readUniquePixelData( + vp: Viewport, + readRect?: ViewRect, + excludeNonLocatable = false, + excludedElements?: Iterable, +): PixelDataSet { const set = new PixelDataSet(); processPixels(vp, (pixel) => set.insert(pixel), readRect, excludeNonLocatable, excludedElements); return set; } -export function readUniqueFeatures(vp: Viewport, readRect?: ViewRect, excludeNonLocatable = false, excludedElements?: Iterable): SortedArray { +export function readUniqueFeatures( + vp: Viewport, + readRect?: ViewRect, + excludeNonLocatable = false, + excludedElements?: Iterable, +): SortedArray { const features = new SortedArray((lhs, rhs) => lhs.compare(rhs)); - processPixels(vp, (pixel) => { - if (pixel.feature) { - features.insert(pixel.feature); - } - }, - readRect, excludeNonLocatable, excludedElements); + processPixels( + vp, + (pixel) => { + if (pixel.feature) { + features.insert(pixel.feature); + } + }, + readRect, + excludeNonLocatable, + excludedElements, + ); return features; } diff --git a/core/frontend/src/test/public/locales/en/TestApp.json b/core/frontend/src/test/public/locales/en/TestApp.json index 6b01fc4e2265..f756e252e85e 100644 --- a/core/frontend/src/test/public/locales/en/TestApp.json +++ b/core/frontend/src/test/public/locales/en/TestApp.json @@ -27,4 +27,4 @@ "Test1": "Substitute {{varA}} and {{varB}}", "Test2": "Reverse substitute {{varB}} and {{varA}}" } -} \ No newline at end of file +} diff --git a/core/frontend/src/test/render/EnvironmentDecorations.test.ts b/core/frontend/src/test/render/EnvironmentDecorations.test.ts index 03c18667388c..24fd4765801b 100644 --- a/core/frontend/src/test/render/EnvironmentDecorations.test.ts +++ b/core/frontend/src/test/render/EnvironmentDecorations.test.ts @@ -3,14 +3,25 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration } from "@itwin/core-bentley"; -import { ColorDef, EmptyLocalization, Environment, EnvironmentProps, Gradient, ImageSource, ImageSourceFormat, RenderTexture, SkyBox, SkyBoxImageType } from "@itwin/core-common"; -import { EnvironmentDecorations } from "../../EnvironmentDecorations"; +import { + ColorDef, + EmptyLocalization, + Environment, + EnvironmentProps, + Gradient, + ImageSource, + ImageSourceFormat, + RenderTexture, + SkyBox, + SkyBoxImageType, +} from "@itwin/core-common"; +import { expect } from "chai"; import { imageElementFromImageSource } from "../../common/ImageUtil"; -import { SpatialViewState } from "../../SpatialViewState"; -import { IModelConnection } from "../../IModelConnection"; +import { EnvironmentDecorations } from "../../EnvironmentDecorations"; import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; +import { SpatialViewState } from "../../SpatialViewState"; import { createBlankConnection } from "../createBlankConnection"; describe("EnvironmentDecorations", () => { @@ -25,9 +36,15 @@ describe("EnvironmentDecorations", () => { } class Decorations extends EnvironmentDecorations { - public get sky() { return this._sky; } - public get ground() { return this._ground; } - public get environment() { return this._environment; } + public get sky() { + return this._sky; + } + public get ground() { + return this._ground; + } + public get environment() { + return this._environment; + } public constructor(view?: SpatialViewState, onLoad?: () => void, onDispose?: () => void) { super(view ?? createView(), onLoad ?? (() => undefined), onDispose ?? (() => undefined)); @@ -55,9 +72,137 @@ describe("EnvironmentDecorations", () => { await IModelApp.startup({ localization: new EmptyLocalization() }); const pngData = new Uint8Array([ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, - 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, - 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, ]); const textureImage = { @@ -282,9 +427,12 @@ describe("EnvironmentDecorations", () => { image: { type: SkyBoxImageType.Cube, textures: { - front: "0x1", back: "0x2", - left: "0x3", right: "0x4", - top: "0x5", bottom: "0x6", + front: "0x1", + back: "0x2", + left: "0x3", + right: "0x4", + top: "0x5", + bottom: "0x6", }, }, }, diff --git a/core/frontend/src/test/render/FrameStats.test.ts b/core/frontend/src/test/render/FrameStats.test.ts index f851b00f54c7..1823b99a7edb 100644 --- a/core/frontend/src/test/render/FrameStats.test.ts +++ b/core/frontend/src/test/render/FrameStats.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { expect } from "chai"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; -import { createBlankConnection } from "../createBlankConnection"; -import { ScreenViewport } from "../../Viewport"; import { FrameStats } from "../../render/FrameStats"; +import { ScreenViewport } from "../../Viewport"; +import { createBlankConnection } from "../createBlankConnection"; import { openBlankViewport } from "../openBlankViewport"; -import { EmptyLocalization } from "@itwin/core-common"; describe("FrameStats", () => { let imodel: IModelConnection; diff --git a/core/frontend/src/test/render/GraphicBuilder.test.ts b/core/frontend/src/test/render/GraphicBuilder.test.ts index 159e30c11313..8b870820f683 100644 --- a/core/frontend/src/test/render/GraphicBuilder.test.ts +++ b/core/frontend/src/test/render/GraphicBuilder.test.ts @@ -2,23 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { - Cone, Point3d, PolyfaceBuilder, Range3d, Sphere, StrokeOptions, Transform, -} from "@itwin/core-geometry"; import { ColorByName, ColorIndex, EmptyLocalization, FeatureIndex, FillFlags, QParams3d, QPoint3dList, RenderMode } from "@itwin/core-common"; -import { GraphicBuilder, ViewportGraphicBuilderOptions } from "../../render/GraphicBuilder"; +import { Cone, Point3d, PolyfaceBuilder, Range3d, Sphere, StrokeOptions, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { MeshParams } from "../../common/internal/render/MeshParams"; +import { SurfaceType } from "../../common/internal/render/SurfaceParams"; +import { GraphicType } from "../../common/render/GraphicType"; import { IModelApp, IModelAppOptions } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; -import { createBlankConnection } from "../createBlankConnection"; +import { GraphicBuilder, ViewportGraphicBuilderOptions } from "../../render/GraphicBuilder"; +import { MeshArgs } from "../../render/MeshArgs"; import { RenderSystem } from "../../render/RenderSystem"; -import { ScreenViewport } from "../../Viewport"; -import { MeshParams } from "../../common/internal/render/MeshParams"; -import { SurfaceType } from "../../common/internal/render/SurfaceParams"; import { MeshRenderGeometry } from "../../render/webgl/Mesh"; +import { ScreenViewport } from "../../Viewport"; +import { createBlankConnection } from "../createBlankConnection"; import { openBlankViewport } from "../openBlankViewport"; -import { GraphicType } from "../../common/render/GraphicType"; -import { MeshArgs } from "../../render/MeshArgs"; describe("GraphicBuilder", () => { let imodel: IModelConnection; @@ -51,7 +49,13 @@ describe("GraphicBuilder", () => { return IModelApp.renderSystem.createGraphic({ type, viewport, ...options }); } - const graphicTypes = [GraphicType.ViewBackground, GraphicType.Scene, GraphicType.WorldDecoration, GraphicType.WorldOverlay, GraphicType.ViewOverlay]; + const graphicTypes = [ + GraphicType.ViewBackground, + GraphicType.Scene, + GraphicType.WorldDecoration, + GraphicType.WorldOverlay, + GraphicType.ViewOverlay, + ]; describe("generates normals", () => { function expectNormals(type: GraphicType, options: BuilderOpts, expected: boolean): void { @@ -181,7 +185,7 @@ describe("GraphicBuilder", () => { } function createTriangle(): Point3d[] { - return [ new Point3d(0, 0, 0), new Point3d(100, 0, 0), new Point3d(0, 100, 0) ]; + return [new Point3d(0, 0, 0), new Point3d(100, 0, 0), new Point3d(0, 100, 0)]; } it("should preserve polyface normals", () => { @@ -197,7 +201,12 @@ describe("GraphicBuilder", () => { const pfBuilder = PolyfaceBuilder.create(options); pfBuilder.addTriangleFacet(createTriangle()); - const gfBuilder = IModelApp.renderSystem.createGraphic({ placement: Transform.createIdentity(), type: GraphicType.WorldDecoration, viewport, wantNormals: requestNormals }); + const gfBuilder = IModelApp.renderSystem.createGraphic({ + placement: Transform.createIdentity(), + type: GraphicType.WorldDecoration, + viewport, + wantNormals: requestNormals, + }); gfBuilder.addPolyface(pfBuilder.claimPolyface(), false); const gf = gfBuilder.finish(); gf.dispose(); @@ -215,7 +224,12 @@ describe("GraphicBuilder", () => { injectNormalsCheck(wantNormals); expect(createMeshInvoked).to.be.false; - const builder = IModelApp.renderSystem.createGraphic({ placement: Transform.createIdentity(), type: GraphicType.WorldDecoration, viewport, wantNormals }); + const builder = IModelApp.renderSystem.createGraphic({ + placement: Transform.createIdentity(), + type: GraphicType.WorldDecoration, + viewport, + wantNormals, + }); builder.addShape(createTriangle()); const gf = builder.finish(); gf.dispose(); @@ -227,7 +241,11 @@ describe("GraphicBuilder", () => { }); it("should produce edges", () => { - function expectEdges(expected: "silhouette" | "segment" | "both" | "none", addToGraphic: (builder: GraphicBuilder) => void, generateEdges?: boolean): void { + function expectEdges( + expected: "silhouette" | "segment" | "both" | "none", + addToGraphic: (builder: GraphicBuilder) => void, + generateEdges?: boolean, + ): void { let expectSilhouettes = false; let expectSegments = false; switch (expected) { @@ -256,7 +274,12 @@ describe("GraphicBuilder", () => { overrideCreateMesh(verifyParams); expect(createMeshInvoked).to.be.false; - const builder = IModelApp.renderSystem.createGraphic({ placement: Transform.createIdentity(), type: GraphicType.Scene, viewport, generateEdges }); + const builder = IModelApp.renderSystem.createGraphic({ + placement: Transform.createIdentity(), + type: GraphicType.Scene, + viewport, + generateEdges, + }); expect(builder.wantEdges).to.equal(generateEdges ?? true); addToGraphic(builder); diff --git a/core/frontend/src/test/render/GraphicDescription.test.ts b/core/frontend/src/test/render/GraphicDescription.test.ts index 90b9f0a6b1a4..c5f0bd3a9505 100644 --- a/core/frontend/src/test/render/GraphicDescription.test.ts +++ b/core/frontend/src/test/render/GraphicDescription.test.ts @@ -2,26 +2,53 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { Id64, Id64String, TransientIdSequence } from "@itwin/core-bentley"; +import { + ColorDef, + EmptyLocalization, + Feature, + FillFlags, + GeometryClass, + Gradient, + GraphicParams, + ImageBuffer, + ImageBufferFormat, + ImageSource, + ImageSourceFormat, + LinePixels, + ModelFeature, + RenderFeatureTable, + RenderMaterial, + RenderTexture, + TextureTransparency, +} from "@itwin/core-common"; import { Angle, Point2d, Point3d, Range3d, Transform, XYAndZ } from "@itwin/core-geometry"; -import { ColorDef, EmptyLocalization, Feature, FillFlags, GeometryClass, Gradient, GraphicParams, ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, LinePixels, ModelFeature, RenderFeatureTable, RenderMaterial, RenderTexture, TextureTransparency } from "@itwin/core-common"; -import { createWorkerProxy } from "../../common/WorkerProxy"; -import { TestWorker } from "../worker/test-worker"; -import { IModelApp } from "../../IModelApp"; -import { MeshGraphic } from "../../render/webgl/Mesh"; +import { expect } from "chai"; import { GraphicDescriptionBuilder, GraphicDescriptionBuilderOptions, imageBufferToPngDataUrl } from "../../common"; -import { GraphicType } from "../../common/render/GraphicType"; -import { GraphicDescriptionImpl, isGraphicDescription } from "../../common/internal/render/GraphicDescriptionBuilderImpl"; -import { Batch, Branch, GraphicsArray } from "../../webgl"; import { ImdlModel } from "../../common/imdl/ImdlModel"; -import { Id64, Id64String, TransientIdSequence } from "@itwin/core-bentley"; -import { GraphicDescriptionContext, WorkerGraphicDescriptionContext } from "../../common/render/GraphicDescriptionContext"; +import { GraphicDescriptionImpl, isGraphicDescription } from "../../common/internal/render/GraphicDescriptionBuilderImpl"; import { WorkerTexture } from "../../common/internal/render/GraphicDescriptionContextImpl"; import { _textures } from "../../common/internal/Symbols"; -import { Material } from "../../render/webgl/Material"; +import { GraphicDescriptionContext, WorkerGraphicDescriptionContext } from "../../common/render/GraphicDescriptionContext"; +import { GraphicType } from "../../common/render/GraphicType"; +import { createWorkerProxy } from "../../common/WorkerProxy"; +import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; +import { Material } from "../../render/webgl/Material"; +import { MeshGraphic } from "../../render/webgl/Mesh"; +import { Batch, Branch, GraphicsArray } from "../../webgl"; +import { TestWorker } from "../worker/test-worker"; -function expectRange(range: Readonly, translation: XYAndZ | undefined, lx: number, ly: number, lz: number, hx: number, hy: number, hz: number): void { +function expectRange( + range: Readonly, + translation: XYAndZ | undefined, + lx: number, + ly: number, + lz: number, + hx: number, + hy: number, + hz: number, +): void { if (!translation) { translation = { x: 0, y: 0, z: 0 }; } @@ -55,18 +82,31 @@ describe("GraphicDescriptionBuilder", () => { await IModelApp.shutdown(); }); - async function createContexts(): Promise<{ iModel: IModelConnection, workerContext: WorkerGraphicDescriptionContext, mainContext: GraphicDescriptionContext }> { + async function createContexts(): Promise< + { iModel: IModelConnection, workerContext: WorkerGraphicDescriptionContext, mainContext: GraphicDescriptionContext } + > { const iModel = createIModel(); - const contextProps = IModelApp.renderSystem.createWorkerGraphicDescriptionContextProps(iModel); + const contextProps = IModelApp.renderSystem.createWorkerGraphicDescriptionContextProps(iModel); const workerContext = WorkerGraphicDescriptionContext.fromProps(contextProps); const mainContext = await IModelApp.renderSystem.resolveGraphicDescriptionContext(workerContext.toProps(new Set()), iModel); return { iModel, workerContext, mainContext }; } const computeChordTolerance = () => 0; - const graphicTypes = [GraphicType.ViewBackground, GraphicType.Scene, GraphicType.WorldDecoration, GraphicType.WorldOverlay, GraphicType.ViewOverlay]; - - function expectOption(workerContext: WorkerGraphicDescriptionContext, options: Omit, option: "wantEdges" | "wantNormals" | "preserveOrder", expected: boolean): void { + const graphicTypes = [ + GraphicType.ViewBackground, + GraphicType.Scene, + GraphicType.WorldDecoration, + GraphicType.WorldOverlay, + GraphicType.ViewOverlay, + ]; + + function expectOption( + workerContext: WorkerGraphicDescriptionContext, + options: Omit, + option: "wantEdges" | "wantNormals" | "preserveOrder", + expected: boolean, + ): void { const builder = GraphicDescriptionBuilder.create({ ...options, context: workerContext, computeChordTolerance }); expect(builder[option]).to.equal(expected); } @@ -74,7 +114,12 @@ describe("GraphicDescriptionBuilder", () => { it("preserves order for overlay and background graphics", async () => { const { workerContext } = await createContexts(); for (const type of graphicTypes) { - expectOption(workerContext, { type }, "preserveOrder", type === GraphicType.ViewOverlay || type === GraphicType.WorldOverlay || type === GraphicType.ViewBackground); + expectOption( + workerContext, + { type }, + "preserveOrder", + type === GraphicType.ViewOverlay || type === GraphicType.WorldOverlay || type === GraphicType.ViewBackground, + ); } }); @@ -111,7 +156,10 @@ describe("GraphicDescriptionBuilder", () => { expect(builder.wantEdges).to.be.false; builder.setSymbology(ColorDef.blue, ColorDef.blue, 2); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -153,7 +201,10 @@ describe("GraphicDescriptionBuilder", () => { expect(builder.wantEdges).to.be.true; builder.setSymbology(ColorDef.blue, ColorDef.blue, 3, LinePixels.HiddenLine); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -213,7 +264,10 @@ describe("GraphicDescriptionBuilder", () => { builder.setSymbology(ColorDef.blue, ColorDef.blue, 3, LinePixels.HiddenLine); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -239,7 +293,10 @@ describe("GraphicDescriptionBuilder", () => { builder.setSymbology(ColorDef.blue, ColorDef.blue, 3, LinePixels.HiddenLine); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -270,7 +327,10 @@ describe("GraphicDescriptionBuilder", () => { }); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -326,7 +386,10 @@ describe("GraphicDescriptionBuilder", () => { }); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); const descr = finish(builder); @@ -406,7 +469,139 @@ describe("GraphicDescriptionBuilder", () => { // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. - const pngData: Uint8Array = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]); + const pngData: Uint8Array = new Uint8Array([ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]); const gradient = Gradient.Symb.fromJSON({ mode: 3, @@ -419,7 +614,12 @@ describe("GraphicDescriptionBuilder", () => { it("creates and resolves textures", async () => { const { workerContext } = await createContexts(); - function expectWorkerTexture(texture: WorkerTexture, type: RenderTexture.Type, source: ImageSource | ImageBuffer | URL | Gradient.Symb, transparency: TextureTransparency | undefined): void { + function expectWorkerTexture( + texture: WorkerTexture, + type: RenderTexture.Type, + source: ImageSource | ImageBuffer | URL | Gradient.Symb, + transparency: TextureTransparency | undefined, + ): void { expect(texture.type).to.equal(type); expect(texture.source.transparency).to.equal(transparency); if (source instanceof ImageSource) { @@ -508,7 +708,10 @@ describe("GraphicDescriptionBuilder", () => { const builder = GraphicDescriptionBuilder.create({ type: GraphicType.WorldDecoration, context: workerContext, computeChordTolerance }); const addShape = () => { builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); }; @@ -644,7 +847,7 @@ describe("GraphicDescriptionBuilder", () => { break; case 3: case 4: - expectMaterial(mat, { }); + expectMaterial(mat, {}); break; } } @@ -655,7 +858,7 @@ describe("GraphicDescriptionBuilder", () => { it("throws on invalid context", async () => { const worker = createWorker(); - await expect(worker.createGraphic({ } as any)).to.be.eventually.rejectedWith("Invalid WorkerGraphicDescriptionContextProps"); + await expect(worker.createGraphic({} as any)).to.be.eventually.rejectedWith("Invalid WorkerGraphicDescriptionContextProps"); worker.terminate(); expect(worker.isTerminated).to.be.true; }); diff --git a/core/frontend/src/test/render/GraphicPrimitive.test.ts b/core/frontend/src/test/render/GraphicPrimitive.test.ts index 2ff312510c4a..9dbcae0ffc46 100644 --- a/core/frontend/src/test/render/GraphicPrimitive.test.ts +++ b/core/frontend/src/test/render/GraphicPrimitive.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Arc3d, Loop, Path, Point2d, Point3d, Polyface, SolidPrimitive } from "@itwin/core-geometry"; -import { GraphicBuilder } from "../../render/GraphicBuilder"; -import { GraphicType } from "../../common/render/GraphicType"; -import { GraphicPrimitive } from "../../common/render/GraphicPrimitive"; +import { expect } from "chai"; import { _implementationProhibited } from "../../common/internal/Symbols"; +import { GraphicPrimitive } from "../../common/render/GraphicPrimitive"; +import { GraphicType } from "../../common/render/GraphicType"; +import { GraphicBuilder } from "../../render/GraphicBuilder"; describe("GraphicPrimitive", () => { class Builder extends GraphicBuilder { @@ -27,23 +27,53 @@ describe("GraphicPrimitive", () => { }); } - public override activateGraphicParams() { } - public override resolveGradient() { return undefined; } - public finish() { return {} as any; } - public finishTemplate() { return {} as any; } + public override activateGraphicParams() {} + public override resolveGradient() { + return undefined; + } + public finish() { + return {} as any; + } + public finishTemplate() { + return {} as any; + } - public override addLineString(points: Point3d[]) { this.primitive = { type: "linestring", points }; } - public override addLineString2d(points: Point2d[], zDepth: number) { this.primitive = { type: "linestring2d", points, zDepth }; } - public override addPointString(points: Point3d[]) { this.primitive = { type: "pointstring", points }; } - public override addPointString2d(points: Point2d[], zDepth: number) { this.primitive = { type: "pointstring2d", points, zDepth }; } - public override addShape(points: Point3d[]) { this.primitive = { type: "shape", points }; } - public override addShape2d(points: Point2d[], zDepth: number) { this.primitive = { type: "shape2d", points, zDepth }; } - public override addArc(arc: Arc3d, isEllipse: boolean, filled: boolean) { this.primitive = { type: "arc", arc, isEllipse, filled }; } - public override addArc2d(arc: Arc3d, isEllipse: boolean, filled: boolean, zDepth: number) { this.primitive = { type: "arc2d", arc, isEllipse, filled, zDepth }; } - public override addPath(path: Path) { this.primitive = { type: "path", path }; } - public override addLoop(loop: Loop) { this.primitive = { type: "loop", loop }; } - public override addPolyface(polyface: Polyface, filled: boolean) { this.primitive = { type: "polyface", polyface, filled }; } - public override addSolidPrimitive(solidPrimitive: SolidPrimitive) { this.primitive = { type: "solidPrimitive", solidPrimitive }; } + public override addLineString(points: Point3d[]) { + this.primitive = { type: "linestring", points }; + } + public override addLineString2d(points: Point2d[], zDepth: number) { + this.primitive = { type: "linestring2d", points, zDepth }; + } + public override addPointString(points: Point3d[]) { + this.primitive = { type: "pointstring", points }; + } + public override addPointString2d(points: Point2d[], zDepth: number) { + this.primitive = { type: "pointstring2d", points, zDepth }; + } + public override addShape(points: Point3d[]) { + this.primitive = { type: "shape", points }; + } + public override addShape2d(points: Point2d[], zDepth: number) { + this.primitive = { type: "shape2d", points, zDepth }; + } + public override addArc(arc: Arc3d, isEllipse: boolean, filled: boolean) { + this.primitive = { type: "arc", arc, isEllipse, filled }; + } + public override addArc2d(arc: Arc3d, isEllipse: boolean, filled: boolean, zDepth: number) { + this.primitive = { type: "arc2d", arc, isEllipse, filled, zDepth }; + } + public override addPath(path: Path) { + this.primitive = { type: "path", path }; + } + public override addLoop(loop: Loop) { + this.primitive = { type: "loop", loop }; + } + public override addPolyface(polyface: Polyface, filled: boolean) { + this.primitive = { type: "polyface", polyface, filled }; + } + public override addSolidPrimitive(solidPrimitive: SolidPrimitive) { + this.primitive = { type: "solidPrimitive", solidPrimitive }; + } public expectPrimitive(expected: GraphicPrimitive) { expect(this._primitive).not.to.be.undefined; @@ -53,26 +83,25 @@ describe("GraphicPrimitive", () => { } it("forwards to appropriate method with appropriate arguments", () => { - - const points = [ new Point3d(0, 1, 2) ]; - const pts2d = [ new Point2d(3, 4) ]; + const points = [new Point3d(0, 1, 2)]; + const pts2d = [new Point2d(3, 4)]; const zDepth = 42; const arc = Arc3d.createXYZXYZXYZ(1, 2, 3, 4, 5, 6, 7, 8, 9); type Test = [GraphicPrimitive, GraphicPrimitive | undefined]; const tests: Test[] = [ - [ { type: "linestring", points }, undefined ], - [ { type: "linestring2d", points: pts2d, zDepth }, undefined ], - [ { type: "pointstring", points }, undefined ], - [ { type: "pointstring2d", points: pts2d, zDepth }, undefined ], - [ { type: "shape", points }, undefined ], - [ { type: "shape2d", points: pts2d, zDepth }, undefined ], - [ { type: "arc", arc } , { type: "arc", arc, isEllipse: false, filled: false } ], - [ { type: "arc", arc, isEllipse: true, filled: true }, undefined ], - [ { type: "arc", arc, isEllipse: false, filled: false }, undefined ], - [ { type: "arc2d", zDepth, arc } , { type: "arc2d", arc, isEllipse: false, filled: false, zDepth } ], - [ { type: "arc2d", zDepth, arc, isEllipse: true, filled: true }, undefined ], - [ { type: "arc2d", zDepth, arc, isEllipse: false, filled: false }, undefined ], + [{ type: "linestring", points }, undefined], + [{ type: "linestring2d", points: pts2d, zDepth }, undefined], + [{ type: "pointstring", points }, undefined], + [{ type: "pointstring2d", points: pts2d, zDepth }, undefined], + [{ type: "shape", points }, undefined], + [{ type: "shape2d", points: pts2d, zDepth }, undefined], + [{ type: "arc", arc }, { type: "arc", arc, isEllipse: false, filled: false }], + [{ type: "arc", arc, isEllipse: true, filled: true }, undefined], + [{ type: "arc", arc, isEllipse: false, filled: false }, undefined], + [{ type: "arc2d", zDepth, arc }, { type: "arc2d", arc, isEllipse: false, filled: false, zDepth }], + [{ type: "arc2d", zDepth, arc, isEllipse: true, filled: true }, undefined], + [{ type: "arc2d", zDepth, arc, isEllipse: false, filled: false }, undefined], ]; const builder = new Builder(); diff --git a/core/frontend/src/test/render/GraphicTemplate.test.ts b/core/frontend/src/test/render/GraphicTemplate.test.ts index 97861e10e5a8..6f98605f974a 100644 --- a/core/frontend/src/test/render/GraphicTemplate.test.ts +++ b/core/frontend/src/test/render/GraphicTemplate.test.ts @@ -3,20 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { IModelApp } from "../../IModelApp"; +import { TransientIdSequence } from "@itwin/core-bentley"; import { EmptyLocalization } from "@itwin/core-common"; -import { GraphicType } from "../../common/render/GraphicType"; import { Point2d, Point3d, Transform } from "@itwin/core-geometry"; -import { RenderInstances } from "../../render/RenderSystem"; -import { _batch, _branch, _nodes } from "../../common/internal/Symbols"; -import { GraphicTemplate } from "../../render/GraphicTemplate"; -import { RenderInstancesParamsBuilder } from "../../common/render/RenderInstancesParams"; -import { TransientIdSequence } from "@itwin/core-bentley"; +import { expect } from "chai"; import { GraphicDescriptionImpl } from "../../common/internal/render/GraphicDescriptionBuilderImpl"; +import { _batch, _branch, _nodes } from "../../common/internal/Symbols"; import { GraphicDescriptionBuilder } from "../../common/render/GraphicDescriptionBuilder"; import { WorkerGraphicDescriptionContext } from "../../common/render/GraphicDescriptionContext"; +import { GraphicType } from "../../common/render/GraphicType"; +import { RenderInstancesParamsBuilder } from "../../common/render/RenderInstancesParams"; +import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; +import { GraphicTemplate } from "../../render/GraphicTemplate"; +import { RenderInstances } from "../../render/RenderSystem"; describe("GraphicTemplate", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); @@ -68,10 +68,12 @@ describe("GraphicTemplate", () => { const viewIndep = makeTemplate(true); expect(viewIndep.isInstanceable).to.be.false; - expect(() => IModelApp.renderSystem.createGraphicFromTemplate({ - template: viewIndep, - instances: makeInstances(), - })).to.throw("instanceable"); + expect(() => + IModelApp.renderSystem.createGraphicFromTemplate({ + template: viewIndep, + instances: makeInstances(), + }) + ).to.throw("instanceable"); }); it("produces a batch if features are specified", () => { diff --git a/core/frontend/src/test/render/InstancedGraphicPropsBuilder.test.ts b/core/frontend/src/test/render/InstancedGraphicPropsBuilder.test.ts index 10d1259df4c2..1a0aa8415f9d 100644 --- a/core/frontend/src/test/render/InstancedGraphicPropsBuilder.test.ts +++ b/core/frontend/src/test/render/InstancedGraphicPropsBuilder.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Id64String } from "@itwin/core-bentley"; import { Feature, FeatureTable, GeometryClass, LinePixels } from "@itwin/core-common"; +import { Point3d, Transform, XYZProps } from "@itwin/core-geometry"; +import { expect } from "chai"; import { InstancedGraphicPropsBuilder } from "../../common/internal/render/InstancedGraphicPropsBuilder"; +import { OvrFlags } from "../../common/internal/render/OvrFlags"; import { InstancedGraphicProps } from "../../common/render/InstancedGraphicParams"; import { Instance, InstanceSymbology } from "../../common/render/RenderInstancesParams"; -import { expect } from "chai"; -import { Point3d, Transform, XYZProps } from "@itwin/core-geometry"; -import { Id64String } from "@itwin/core-bentley"; -import { OvrFlags } from "../../common/internal/render/OvrFlags"; function build(instances: Instance[], haveFeatures = false): InstancedGraphicProps { const builder = new InstancedGraphicPropsBuilder(); @@ -84,13 +84,13 @@ describe("InstancedGraphicPropsBuilder", () => { { transform, symbology: { linePixels: 2.7 as LinePixels } }, { transform, symbology: { weight: 0 } }, - { transform, symbology: { weight: 31} }, + { transform, symbology: { weight: 31 } }, { transform, symbology: { weight: 32 } }, { transform, symbology: { weight: -1 } }, { transform, symbology: { weight: 12.7 } }, { transform, symbology: { color: { r: -1, g: 256, b: 127.7 } } }, - { transform, symbology: { color: { r:0, g: 255, b: 127.2 } } }, + { transform, symbology: { color: { r: 0, g: 255, b: 127.2 } } }, ]; const props = build(instances); @@ -123,10 +123,10 @@ describe("InstancedGraphicPropsBuilder", () => { expect(symbs[i + 7]).to.equal(0); } - expectOvrs(0, { rgb: [63, 127, 191]}); + expectOvrs(0, { rgb: [63, 127, 191] }); expectOvrs(1, { weight: 25 }); expectOvrs(2, { lineCode: 3 }); - expectOvrs(3, { }); + expectOvrs(3, {}); expectOvrs(4, { rgb: [123, 255, 0], weight: 15, lineCode: 7 }); // Any value that doesn't map to a LinePixels enum member is treated as line code zero (solid). @@ -191,8 +191,15 @@ describe("InstancedGraphicPropsBuilder", () => { ["0x123", "0", GeometryClass.Pattern], ], [ // But feature Ids are assigned at insertion time. - 0, 1, 0, 2, 3, 4, 1, 0, 4, + 0, + 1, + 0, + 2, + 3, + 4, + 1, + 0, + 4, ]); }); }); - diff --git a/core/frontend/src/test/render/MockRender.test.ts b/core/frontend/src/test/render/MockRender.test.ts index 711a431fc47c..77ac5a91ddb2 100644 --- a/core/frontend/src/test/render/MockRender.test.ts +++ b/core/frontend/src/test/render/MockRender.test.ts @@ -4,17 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; +import { ViewRect } from "../../common/ViewRect"; import { IModelApp } from "../../IModelApp"; import { MockRender } from "../../render/MockRender"; import { RenderGraphic } from "../../render/RenderGraphic"; import { RenderTarget } from "../../render/RenderTarget"; -import { ViewRect } from "../../common/ViewRect"; -class MyTarget extends MockRender.OffScreenTarget { } -class MyList extends MockRender.List { } +class MyTarget extends MockRender.OffScreenTarget {} +class MyList extends MockRender.List {} class MySystem extends MockRender.System { - public override createOffscreenTarget(rect: ViewRect): RenderTarget { return new MyTarget(this, rect); } - public override createGraphicList(list: RenderGraphic[]) { return new MyList(list); } + public override createOffscreenTarget(rect: ViewRect): RenderTarget { + return new MyTarget(this, rect); + } + public override createGraphicList(list: RenderGraphic[]) { + return new MyList(list); + } } describe("MockRender", () => { diff --git a/core/frontend/src/test/render/RealityMeshParams.test.ts b/core/frontend/src/test/render/RealityMeshParams.test.ts index 27021ec34222..7e62278de35b 100644 --- a/core/frontend/src/test/render/RealityMeshParams.test.ts +++ b/core/frontend/src/test/render/RealityMeshParams.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point3d, Range3d } from "@itwin/core-geometry"; import { QPoint3dBuffer } from "@itwin/core-common"; +import { Point3d, Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { RealityMeshParamsBuilder } from "../../render/RealityMeshParams"; describe("RealityMeshParamsBuilder", () => { @@ -105,7 +105,7 @@ describe("RealityMeshParamsBuilder", () => { wantNormals, }); - const addVertex = () => builder.addQuantizedVertex({ x: 0, y: 0, z: 0 }, { x: 0, y: 0}, supplyNormals ? 100 : undefined); + const addVertex = () => builder.addQuantizedVertex({ x: 0, y: 0, z: 0 }, { x: 0, y: 0 }, supplyNormals ? 100 : undefined); if (expectThrow) expect(addVertex).to.throw("Logic Error"); else diff --git a/core/frontend/src/test/render/RenderGraphic.test.ts b/core/frontend/src/test/render/RenderGraphic.test.ts index 59578b94f817..04130a527449 100644 --- a/core/frontend/src/test/render/RenderGraphic.test.ts +++ b/core/frontend/src/test/render/RenderGraphic.test.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/unbound-method */ -import { expect } from "chai"; import { IDisposable } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { ElementAlignedBox3d, RenderFeatureTable } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { GraphicBranch, GraphicBranchOptions } from "../../render/GraphicBranch"; import { MockRender } from "../../render/MockRender"; import { RenderGraphic } from "../../render/RenderGraphic"; diff --git a/core/frontend/src/test/render/RenderInstances.test.ts b/core/frontend/src/test/render/RenderInstances.test.ts index 942ff12e7286..d5cf37dc572a 100644 --- a/core/frontend/src/test/render/RenderInstances.test.ts +++ b/core/frontend/src/test/render/RenderInstances.test.ts @@ -2,20 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point2d, Range3d, Transform } from "@itwin/core-geometry"; -import { RenderInstancesParamsBuilder } from "../../common/render/RenderInstancesParams"; import { Id64 } from "@itwin/core-bentley"; -import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; +import { ColorDef, EmptyLocalization, Feature, LinePixels, ModelFeature, RenderMode } from "@itwin/core-common"; +import { Point2d, Range3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { GraphicType } from "../../common"; import { InstancedGraphicPropsBuilder } from "../../common/internal/render/InstancedGraphicPropsBuilder"; +import { _featureTable } from "../../common/internal/Symbols"; import { InstancedGraphicParams, InstancedGraphicProps } from "../../common/render/InstancedGraphicParams"; -import { InstanceBuffers, InstanceBuffersData } from "../../render/webgl/InstancedGeometry"; +import { RenderInstancesParamsBuilder } from "../../common/render/RenderInstancesParams"; +import { GraphicBranch, readGltfTemplate, StandardViewId } from "../../core-frontend"; import { IModelApp } from "../../IModelApp"; -import { ColorDef, EmptyLocalization, Feature, LinePixels, ModelFeature, RenderMode } from "@itwin/core-common"; -import { GraphicType } from "../../common"; +import { RenderInstancesParamsImpl } from "../../internal/render/RenderInstancesParamsImpl"; +import { InstanceBuffers, InstanceBuffersData } from "../../render/webgl/InstancedGeometry"; import { Color, openBlankViewport, readColorCounts, readUniqueColors, readUniqueFeatures } from "../openBlankViewport"; -import { GraphicBranch, readGltfTemplate, StandardViewId } from "../../core-frontend"; -import { _featureTable } from "../../common/internal/Symbols"; describe("RenderInstancesParamsBuilder", () => { it("throws if no instances supplied", () => { @@ -238,7 +238,7 @@ describe("RenderInstances", () => { instancesBuilder.add({ feature: "0x6", transform: Transform.createTranslationXYZ(0, -1, 0), - symbology: { color: {r: 0, g: 0, b: 255 } }, + symbology: { color: { r: 0, g: 0, b: 255 } }, }); const instances = IModelApp.renderSystem.createRenderInstances(instancesBuilder.finish())!; expect(instances[_featureTable]!.numFeatures).to.equal(4); @@ -331,7 +331,7 @@ describe("RenderInstances", () => { const background = colors.get(Color.fromColorDef(ColorDef.black))!; const red = colors.get(Color.fromColorDef(ColorDef.red))!; const blue = colors.get(Color.fromColorDef(ColorDef.blue))!; - const green= colors.get(Color.fromColorDef(ColorDef.green))!; + const green = colors.get(Color.fromColorDef(ColorDef.green))!; const white = colors.get(Color.fromColorDef(ColorDef.white))!; // dashed - fewer pixels diff --git a/core/frontend/src/test/render/VisibleFeature.test.ts b/core/frontend/src/test/render/VisibleFeature.test.ts index 7ee559299203..807259b0abcc 100644 --- a/core/frontend/src/test/render/VisibleFeature.test.ts +++ b/core/frontend/src/test/render/VisibleFeature.test.ts @@ -2,15 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { Point3d, Vector3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; import { QueryVisibleFeaturesOptions } from "../../render/VisibleFeature"; import { SpatialViewState } from "../../SpatialViewState"; import { ScreenViewport } from "../../Viewport"; import { createBlankConnection } from "../createBlankConnection"; -import { EmptyLocalization } from "@itwin/core-common"; describe("Visible feature query", () => { let imodel: IModelConnection; diff --git a/core/frontend/src/test/render/primitives/AuxChannelTable.test.ts b/core/frontend/src/test/render/primitives/AuxChannelTable.test.ts index d722172062ef..6feb8f63460d 100644 --- a/core/frontend/src/test/render/primitives/AuxChannelTable.test.ts +++ b/core/frontend/src/test/render/primitives/AuxChannelTable.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { AuxChannel, AuxChannelData, AuxChannelDataType, Geometry, Vector3d } from "@itwin/core-geometry"; import { OctEncodedNormal } from "@itwin/core-common"; -import { MockRender } from "../../../render/MockRender"; +import { AuxChannel, AuxChannelData, AuxChannelDataType, Geometry, Vector3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { AuxChannelTable } from "../../../common/internal/render/AuxChannelTable"; +import { MockRender } from "../../../render/MockRender"; describe("AuxChannelTable", () => { class System extends MockRender.System { diff --git a/core/frontend/src/test/render/primitives/DisplayParams.test.ts b/core/frontend/src/test/render/primitives/DisplayParams.test.ts index d80dc9df0482..368e3cca0892 100644 --- a/core/frontend/src/test/render/primitives/DisplayParams.test.ts +++ b/core/frontend/src/test/render/primitives/DisplayParams.test.ts @@ -3,12 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorByName, ColorDef, GraphicParams, LinePixels } from "@itwin/core-common"; +import { expect } from "chai"; import { DisplayParams } from "../../../common/internal/render/DisplayParams"; export class FakeDisplayParams extends DisplayParams { - public constructor() { super(DisplayParams.Type.Linear, ColorDef.black, ColorDef.black); } + public constructor() { + super(DisplayParams.Type.Linear, ColorDef.black, ColorDef.black); + } } describe("DisplayParams creation tests", () => { @@ -48,8 +50,7 @@ describe("DisplayParams equality tests", () => { it("two DisplayParams created with different colors should be non-equal", () => { const gf0: GraphicParams = new GraphicParams(); - gf0.lineColor = ColorDef.white - ; + gf0.lineColor = ColorDef.white; const gf1: GraphicParams = new GraphicParams(); gf1.lineColor = ColorDef.black; const dpMesh0: DisplayParams = DisplayParams.createForMesh(gf0, false); diff --git a/core/frontend/src/test/render/primitives/Geometry.test.ts b/core/frontend/src/test/render/primitives/Geometry.test.ts index 8a66a847a918..17ef5b3c6ad7 100644 --- a/core/frontend/src/test/render/primitives/Geometry.test.ts +++ b/core/frontend/src/test/render/primitives/Geometry.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { IndexedPolyface, LineString3d, Loop, Path, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ColorDef, GraphicParams } from "@itwin/core-common"; +import { IndexedPolyface, LineString3d, Loop, Path, Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { DisplayParams } from "../../../common/internal/render/DisplayParams"; import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; -import { StrokesPrimitiveList, StrokesPrimitivePointList, StrokesPrimitivePointLists } from "../../../common/internal/render/Strokes"; import { PolyfacePrimitive, PolyfacePrimitiveList } from "../../../common/internal/render/Polyface"; +import { StrokesPrimitiveList, StrokesPrimitivePointList, StrokesPrimitivePointLists } from "../../../common/internal/render/Strokes"; function pointIsInArray(pt: Point3d, arr: Point3d[]): boolean { for (const arrPt of arr) { diff --git a/core/frontend/src/test/render/primitives/GeometryAccumulator.test.ts b/core/frontend/src/test/render/primitives/GeometryAccumulator.test.ts index 6c55f7d90756..b9adfe3eb3cf 100644 --- a/core/frontend/src/test/render/primitives/GeometryAccumulator.test.ts +++ b/core/frontend/src/test/render/primitives/GeometryAccumulator.test.ts @@ -2,23 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { LineString3d, Loop, Path, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ColorDef, EmptyLocalization, GraphicParams } from "@itwin/core-common"; +import { LineString3d, Loop, Path, Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import { GraphicType } from "../../../common"; +import { DisplayParams } from "../../../common/internal/render/DisplayParams"; +import { GeometryAccumulator } from "../../../common/internal/render/GeometryAccumulator"; +import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; +import { _accumulator } from "../../../common/internal/Symbols"; import { IModelApp } from "../../../IModelApp"; import { IModelConnection } from "../../../IModelConnection"; +import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; import { RenderGraphic } from "../../../render/RenderGraphic"; -import { StandardViewId } from "../../../StandardView"; -import { SpatialViewState } from "../../../SpatialViewState"; import { Branch } from "../../../render/webgl/Graphic"; +import { SpatialViewState } from "../../../SpatialViewState"; +import { StandardViewId } from "../../../StandardView"; import { createBlankConnection } from "../../createBlankConnection"; import { FakeGeometry } from "./Fake"; -import { GraphicType } from "../../../common"; -import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; -import { GeometryAccumulator } from "../../../common/internal/render/GeometryAccumulator"; -import { DisplayParams } from "../../../common/internal/render/DisplayParams"; -import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; -import { _accumulator } from "../../../common/internal/Symbols"; describe("GeometryAccumulator tests", () => { let iModel: IModelConnection; diff --git a/core/frontend/src/test/render/primitives/MeshBuilder.test.ts b/core/frontend/src/test/render/primitives/MeshBuilder.test.ts index 2a4b861569d6..284a62cead7a 100644 --- a/core/frontend/src/test/render/primitives/MeshBuilder.test.ts +++ b/core/frontend/src/test/render/primitives/MeshBuilder.test.ts @@ -2,25 +2,37 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { Arc3d, AuxChannel, AuxChannelData, AuxChannelDataType, LineString3d, Loop, Point3d, PolyfaceAuxData, PolyfaceBuilder, Range3d, Transform } from "@itwin/core-geometry"; import { ColorDef, GraphicParams } from "@itwin/core-common"; -import { IModelApp } from "../../../IModelApp"; -import { MockRender } from "../../../render/MockRender"; -import { ScreenViewport } from "../../../Viewport"; -import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; -import { openBlankViewport } from "../../openBlankViewport"; -import { GraphicType } from "../../../common/render/GraphicType"; +import { + Arc3d, + AuxChannel, + AuxChannelData, + AuxChannelDataType, + LineString3d, + Loop, + Point3d, + PolyfaceAuxData, + PolyfaceBuilder, + Range3d, + Transform, +} from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { DisplayParams } from "../../../common/internal/render/DisplayParams"; +import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; import { MeshBuilder, MeshEdgeCreationOptions } from "../../../common/internal/render/MeshBuilder"; import { MeshPrimitiveType } from "../../../common/internal/render/MeshPrimitive"; +import { Mesh } from "../../../common/internal/render/MeshPrimitives"; +import { PolyfacePrimitive, PolyfacePrimitiveList } from "../../../common/internal/render/Polyface"; import { ToleranceRatio, Triangle } from "../../../common/internal/render/Primitives"; -import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; import { StrokesPrimitiveList, StrokesPrimitivePointLists } from "../../../common/internal/render/Strokes"; -import { PolyfacePrimitive, PolyfacePrimitiveList } from "../../../common/internal/render/Polyface"; -import { Mesh } from "../../../common/internal/render/MeshPrimitives"; import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; import { _accumulator } from "../../../common/internal/Symbols"; +import { GraphicType } from "../../../common/render/GraphicType"; +import { IModelApp } from "../../../IModelApp"; +import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; +import { MockRender } from "../../../render/MockRender"; +import { ScreenViewport } from "../../../Viewport"; +import { openBlankViewport } from "../../openBlankViewport"; class FakeDisplayParams extends DisplayParams { public constructor() { @@ -33,7 +45,7 @@ const edgeOptions = new MeshEdgeCreationOptions(MeshEdgeCreationOptions.Type.NoE describe("Mesh Builder Tests", () => { let viewport: ScreenViewport; - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await MockRender.App.startup(); viewport = openBlankViewport(); }); @@ -63,7 +75,7 @@ describe("Mesh Builder Tests", () => { }); it("addStrokePointLists", () => { - const primBuilder = new PrimitiveBuilder(IModelApp.renderSystem, {type: GraphicType.Scene, viewport }); + const primBuilder = new PrimitiveBuilder(IModelApp.renderSystem, { type: GraphicType.Scene, viewport }); const pointA = new Point3d(-100, 0, 0); const pointB = new Point3d(0, 100, 0); @@ -168,7 +180,6 @@ describe("Mesh Builder Tests", () => { }); it("addFromPolyfaceVisitor", () => { - const points: Point3d[] = []; points.push(new Point3d(0, 0, 0)); points.push(new Point3d(1, 0, 0)); @@ -261,7 +272,12 @@ describe("Mesh Builder Tests", () => { const triangleCount = visitor.pointCount - 2; const haveParam = includeParams && visitor.paramCount > 0; const triangleIndex = 0; - const vertices = mb.createTriangleVertices(triangleIndex, visitor, { edgeOptions, fillColor, includeParams, haveParam, triangleCount }, undefined); + const vertices = mb.createTriangleVertices( + triangleIndex, + visitor, + { edgeOptions, fillColor, includeParams, haveParam, triangleCount }, + undefined, + ); expect(vertices!.length).to.equal(3); }); @@ -304,7 +320,12 @@ describe("Mesh Builder Tests", () => { const triangleCount = visitor.pointCount - 2; const haveParam = includeParams && visitor.paramCount > 0; const triangleIndex = 0; - const triangle = mb.createTriangleVertices(triangleIndex, visitor, { edgeOptions, fillColor, includeParams, haveParam, triangleCount }, undefined); + const triangle = mb.createTriangleVertices( + triangleIndex, + visitor, + { edgeOptions, fillColor, includeParams, haveParam, triangleCount }, + undefined, + ); expect(triangle).to.not.be.undefined; }); @@ -390,7 +411,7 @@ describe("Mesh Builder Tests", () => { }); function createMeshBuilder(type: MeshPrimitiveType, range: Range3d, options?: Partial>): MeshBuilder { - options = options ?? { }; + options = options ?? {}; const tolerance = options.tolerance ?? 0.15; return MeshBuilder.create({ quantizePositions: false, @@ -490,12 +511,44 @@ describe("Mesh Builder Tests", () => { const aux = meshBuilder.mesh.auxChannels![0]; expect(aux.data[0].values).to.deep.equal([ - 0, 1, 2, 3, 4, 0xffff, 3, 4, 0xffff, - 0, 1, 2, 3, 4, 0xffff, 0, 1, 2, + 0, + 1, + 2, + 3, + 4, + 0xffff, + 3, + 4, + 0xffff, + 0, + 1, + 2, + 3, + 4, + 0xffff, + 0, + 1, + 2, ]); expectAuxChannelTable(meshBuilder.mesh, [ - 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0, 0, 0, 0xffff, 0xffff, 0xffff, 0, 0, 0, + 0, + 0, + 0, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0xffff, + 0, + 0, + 0, + 0xffff, + 0xffff, + 0xffff, + 0, + 0, + 0, ]); }); }); diff --git a/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts b/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts index 6eede955b61b..3bd00b19ecc4 100644 --- a/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts +++ b/core/frontend/src/test/render/primitives/MeshBuilderMap.test.ts @@ -2,26 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { Arc3d, LineString3d, Loop, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ColorDef, GraphicParams } from "@itwin/core-common"; +import { Arc3d, LineString3d, Loop, Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import { DisplayParams } from "../../../common/internal/render/DisplayParams"; +import { GeometryList } from "../../../common/internal/render/GeometryList"; +import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; +import { MeshBuilderMap } from "../../../common/internal/render/MeshBuilderMap"; +import { MeshPrimitiveType } from "../../../common/internal/render/MeshPrimitive"; +import { ToleranceRatio } from "../../../common/internal/render/Primitives"; +import { _accumulator } from "../../../common/internal/Symbols"; +import { GraphicType } from "../../../common/render/GraphicType"; import { IModelApp } from "../../../IModelApp"; import { IModelConnection } from "../../../IModelConnection"; +import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; import { MockRender } from "../../../render/MockRender"; import { SpatialViewState } from "../../../SpatialViewState"; -import { ScreenViewport } from "../../../Viewport"; import { StandardViewId } from "../../../StandardView"; +import { ScreenViewport } from "../../../Viewport"; import { createBlankConnection } from "../../createBlankConnection"; import { FakeDisplayParams } from "./Fake"; -import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; -import { GraphicType } from "../../../common/render/GraphicType"; -import { ToleranceRatio } from "../../../common/internal/render/Primitives"; -import { MeshBuilderMap } from "../../../common/internal/render/MeshBuilderMap"; -import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; -import { DisplayParams } from "../../../common/internal/render/DisplayParams"; -import { GeometryList } from "../../../common/internal/render/GeometryList"; -import { MeshPrimitiveType } from "../../../common/internal/render/MeshPrimitive"; -import { _accumulator } from "../../../common/internal/Symbols"; describe("MeshBuilderMap Tests", () => { let imodel: IModelConnection; @@ -33,7 +33,7 @@ describe("MeshBuilderMap Tests", () => { viewDiv.style.width = viewDiv.style.height = "1000px"; document.body.appendChild(viewDiv); - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await MockRender.App.startup(); imodel = createBlankConnection(); spatialView = SpatialViewState.createBlank(imodel, { x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }); diff --git a/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts b/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts index 220063c80c95..c0359f1d050c 100644 --- a/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts +++ b/core/frontend/src/test/render/primitives/MeshPrimitives.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; import { ColorDef, MeshPolyline, OctEncodedNormal } from "@itwin/core-common"; +import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { DisplayParams } from "../../../common/internal/render/DisplayParams"; import { MeshPrimitiveType } from "../../../common/internal/render/MeshPrimitive"; import { Mesh } from "../../../common/internal/render/MeshPrimitives"; @@ -12,7 +12,9 @@ import { Triangle } from "../../../common/internal/render/Primitives"; import { VertexKey } from "../../../common/internal/render/VertexKey"; export class FakeDisplayParams extends DisplayParams { - public constructor() { super(DisplayParams.Type.Linear, ColorDef.black, ColorDef.black); } + public constructor() { + super(DisplayParams.Type.Linear, ColorDef.black, ColorDef.black); + } } /** diff --git a/core/frontend/src/test/render/primitives/PolylineTesselator.test.ts b/core/frontend/src/test/render/primitives/PolylineTesselator.test.ts index af4f48c10bc6..b7cebe3c912d 100644 --- a/core/frontend/src/test/render/primitives/PolylineTesselator.test.ts +++ b/core/frontend/src/test/render/primitives/PolylineTesselator.test.ts @@ -2,29 +2,321 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point3d } from "@itwin/core-geometry"; import { QPoint3dList } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { tesselatePolyline } from "../../../common/internal/render/PolylineParams"; describe("PolylineTesselator", () => { it("produces joint triangles", () => { - const pts = [ new Point3d(0, 0, 0), new Point3d(0, 10, 0), new Point3d(10, 10, 0), new Point3d(10, 20, 0) ]; + const pts = [new Point3d(0, 0, 0), new Point3d(0, 10, 0), new Point3d(10, 10, 0), new Point3d(10, 20, 0)]; const qpts = QPoint3dList.fromPoints(pts); - const polylines = [ [0, 1, 2, 3] ]; + const polylines = [[0, 1, 2, 3]]; const tesselated = tesselatePolyline(polylines, qpts, true); expect(tesselated.indices.length).to.equal(72); - expect(tesselated.indices.decodeIndices()).to.deep.equal([0,1,0,0,1,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,2,2,1,2,1,1,2,2,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,2,2,3,3,2,3,2,2,3,3,2,2,2,2,2,2,2,2,2]); + expect(tesselated.indices.decodeIndices()).to.deep.equal([ + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 1, + 1, + 2, + 2, + 1, + 2, + 1, + 1, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 2, + 2, + 3, + 3, + 2, + 3, + 2, + 2, + 3, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + ]); - expect(tesselated.prevIndices.decodeIndices()).to.deep.equal([0,2,0,0,2,2,0,2,0,0,2,2,2,2,2,2,2,2,2,2,2,0,3,0,0,3,3,0,3,0,0,3,3,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,1,3,1,1,3,3,1,3,1,1,3,3,1,1,1,1,1,1,1,1,1]); + expect(tesselated.prevIndices.decodeIndices()).to.deep.equal([ + 0, + 2, + 0, + 0, + 2, + 2, + 0, + 2, + 0, + 0, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 0, + 3, + 0, + 0, + 3, + 3, + 0, + 3, + 0, + 0, + 3, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 1, + 3, + 1, + 1, + 3, + 3, + 1, + 3, + 1, + 1, + 3, + 3, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + ]); const next32 = Array.from(new Uint32Array(tesselated.nextIndicesAndParams.buffer)); const nextIndices = next32.map((x) => (x & 0x00ffffff) >>> 0); - expect(nextIndices).to.deep.equal([1,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,2,1,2,2,1,1,2,1,2,2,1,1,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,3,2,3,3,2,2,3,2,3,3,2,2,3,3,3,3,3,3,3,3,3]); + expect(nextIndices).to.deep.equal([ + 1, + 0, + 1, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 1, + 2, + 2, + 1, + 1, + 2, + 1, + 2, + 2, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 3, + 2, + 3, + 3, + 2, + 2, + 3, + 2, + 3, + 3, + 2, + 2, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + 3, + ]); const params = next32.map((x) => (x & 0xff000000) >>> 24); - expect(params).to.deep.equal([27,57,96,96,57,144,96,144,3,3,144,81,144,13,12,144,14,13,144,15,14,33,57,96,96,57,144,96,144,9,9,144,81,96,13,12,96,14,13,96,15,14,144,13,12,144,14,13,144,15,14,33,51,96,96,51,144,96,144,9,9,144,75,96,13,12,96,14,13,96,15,14]); + expect(params).to.deep.equal([ + 27, + 57, + 96, + 96, + 57, + 144, + 96, + 144, + 3, + 3, + 144, + 81, + 144, + 13, + 12, + 144, + 14, + 13, + 144, + 15, + 14, + 33, + 57, + 96, + 96, + 57, + 144, + 96, + 144, + 9, + 9, + 144, + 81, + 96, + 13, + 12, + 96, + 14, + 13, + 96, + 15, + 14, + 144, + 13, + 12, + 144, + 14, + 13, + 144, + 15, + 14, + 33, + 51, + 96, + 96, + 51, + 144, + 96, + 144, + 9, + 9, + 144, + 75, + 96, + 13, + 12, + 96, + 14, + 13, + 96, + 15, + 14, + ]); }); }); diff --git a/core/frontend/src/test/render/primitives/PrimitiveBuilder.test.ts b/core/frontend/src/test/render/primitives/PrimitiveBuilder.test.ts index 1a66ca8a3f0c..7310626ef5c9 100644 --- a/core/frontend/src/test/render/primitives/PrimitiveBuilder.test.ts +++ b/core/frontend/src/test/render/primitives/PrimitiveBuilder.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { GraphicType, IModelApp, RenderGraphic } from "../../../core-frontend"; import { PrimitiveBuilder } from "../../../internal/render/PrimitiveBuilder"; import { Batch, Branch, GraphicsArray, MeshGraphic } from "../../../webgl"; -import { EmptyLocalization } from "@itwin/core-common"; describe("PrimitiveBuilder", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/render/primitives/Primitives.test.ts b/core/frontend/src/test/render/primitives/Primitives.test.ts index 0b0eef5ccea5..8cbb62eb382d 100644 --- a/core/frontend/src/test/render/primitives/Primitives.test.ts +++ b/core/frontend/src/test/render/primitives/Primitives.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { LineString3d, Loop, Point3d, Range3d, Sample, Transform, Vector3d } from "@itwin/core-geometry"; import { GraphicParams } from "@itwin/core-common"; +import { LineString3d, Loop, Point3d, Range3d, Sample, Transform, Vector3d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { DisplayParams } from "../../../common/internal/render/DisplayParams"; import { GeometryList } from "../../../common/internal/render/GeometryList"; import { Geometry } from "../../../common/internal/render/GeometryPrimitives"; @@ -28,16 +28,22 @@ describe("GeometryList", () => { assert.isTrue(glist0.isEmpty); const gp = new GraphicParams(); const dp = DisplayParams.createForLinear(gp); - const g0 = Geometry.createFromLineString([Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0)], + const g0 = Geometry.createFromLineString( + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0)], Transform.createIdentity(), Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1), - dp, undefined); + dp, + undefined, + ); assert.isUndefined(g0.getPolyfaces(0.001)); - const g1 = Geometry.createFromPointString([Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0)], + const g1 = Geometry.createFromPointString( + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0)], Transform.createIdentity(), Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1), - dp, undefined); + dp, + undefined, + ); glist0.push(g0); assert.equal(g0, glist0.first); @@ -47,10 +53,15 @@ describe("GeometryList", () => { const glist1 = new GeometryList(); for (const y0 of [1, 2, 3]) { - glist1.push(Geometry.createFromLineString([Point3d.create(0, y0, 0), Point3d.create(1, y0, 0)], - Transform.createIdentity(), - Range3d.createXYZXYZ(0, y0, 0, 1, y0, 0), - dp, undefined)); + glist1.push( + Geometry.createFromLineString( + [Point3d.create(0, y0, 0), Point3d.create(1, y0, 0)], + Transform.createIdentity(), + Range3d.createXYZXYZ(0, y0, 0, 1, y0, 0), + dp, + undefined, + ), + ); } const length00 = glist0.length; const length1 = glist1.length; @@ -71,7 +82,6 @@ describe("GeometryList", () => { glist0.clear(); assert.isTrue(glist0.isEmpty); - }); it("Polyface", () => { const glist0 = new GeometryList(); @@ -79,8 +89,7 @@ describe("GeometryList", () => { const gp = new GraphicParams(); const dp = DisplayParams.createForLinear(gp); const origin = Point3d.create(1, 2, 3); - const polyface = Sample.createTriangularUnitGridPolyface(origin, - Vector3d.create(1, 0, 0), Vector3d.create(0, 2, 0), 4, 5, true, true, false); + const polyface = Sample.createTriangularUnitGridPolyface(origin, Vector3d.create(1, 0, 0), Vector3d.create(0, 2, 0), 4, 5, true, true, false); const polyfaceG0 = Geometry.createFromPolyface(polyface, Transform.createIdentity(), polyface.range(), dp, undefined); glist0.push(polyfaceG0); verifyGeometryQueries(polyfaceG0, false, true, false); // maybe this has to change someday? diff --git a/core/frontend/src/test/render/primitives/Strokes.test.ts b/core/frontend/src/test/render/primitives/Strokes.test.ts index b2705b586280..7f8eb3dd7858 100644 --- a/core/frontend/src/test/render/primitives/Strokes.test.ts +++ b/core/frontend/src/test/render/primitives/Strokes.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Point3d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { StrokesPrimitivePointList, StrokesPrimitivePointLists } from "../../../common/internal/render/Strokes"; describe("StrokesPrimitivePointList", () => { diff --git a/core/frontend/src/test/render/primitives/VertexKey.test.ts b/core/frontend/src/test/render/primitives/VertexKey.test.ts index 2dca59d1dc24..38c26aa2bb46 100644 --- a/core/frontend/src/test/render/primitives/VertexKey.test.ts +++ b/core/frontend/src/test/render/primitives/VertexKey.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point3d } from "@itwin/core-geometry"; import { OctEncodedNormal } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { VertexKey } from "../../../common/internal/render/VertexKey"; describe("VertexKey", () => { diff --git a/core/frontend/src/test/render/primitives/VertexTable.test.ts b/core/frontend/src/test/render/primitives/VertexTable.test.ts index 6085818f8cf1..4692d55a6525 100644 --- a/core/frontend/src/test/render/primitives/VertexTable.test.ts +++ b/core/frontend/src/test/render/primitives/VertexTable.test.ts @@ -2,14 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { + ColorIndex, + FeatureIndex, + FeatureIndexType, + FillFlags, + QParams2d, + QParams3d, + QPoint3d, + QPoint3dList, + RenderTexture, +} from "@itwin/core-common"; import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; -import { ColorIndex, FeatureIndex, FeatureIndexType, FillFlags, QParams2d, QParams3d, QPoint3d, QPoint3dList, RenderTexture } from "@itwin/core-common"; -import { MockRender } from "../../../render/MockRender"; +import { expect } from "chai"; import { Point3dList } from "../../../common/internal/render/MeshPrimitive"; -import { IModelApp } from "../../../IModelApp"; import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; +import { IModelApp } from "../../../IModelApp"; import { MeshArgs } from "../../../render/MeshArgs"; +import { MockRender } from "../../../render/MockRender"; function expectMeshParams(args: MeshArgs, colorIndex: ColorIndex, vertexBytes: number[][], expectedColors?: number[], quvParams?: QParams2d) { const params = createMeshParams(args, IModelApp.renderSystem.maxTextureSize, "non-indexed" !== IModelApp.tileAdmin.edgeOptions.type); @@ -44,9 +54,13 @@ function expectMeshParams(args: MeshArgs, colorIndex: ColorIndex, vertexBytes: n } class FakeTexture extends RenderTexture { - public constructor() { super(RenderTexture.Type.Normal); } - public dispose() { } - public get bytesUsed(): number { return 0; } + public constructor() { + super(RenderTexture.Type.Normal); + } + public dispose() {} + public get bytesUsed(): number { + return 0; + } } describe("VertexLUT", () => { @@ -71,19 +85,46 @@ describe("VertexLUT", () => { const expected = [ [ - 0x00, 0x00, 0x01, 0x00, // pos.x, pos.y - 0x02, 0x00, 0x00, 0x00, // pos.z, color index - 0x00, 0x00, 0x00, 0x00, // feature index + 0x00, + 0x00, + 0x01, + 0x00, // pos.x, pos.y + 0x02, + 0x00, + 0x00, + 0x00, // pos.z, color index + 0x00, + 0x00, + 0x00, + 0x00, // feature index ], [ - 0xff, 0x7f, 0x0d, 0xf0, - 0x01, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0xff, + 0x7f, + 0x0d, + 0xf0, + 0x01, + 0xc0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, ], [ - 0xad, 0xba, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0xad, + 0xba, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, ], ]; @@ -153,9 +194,18 @@ describe("VertexLUT", () => { // NB: The color values in VertexLUT.Params have premultiplied alpha, and alpha set to (255 - transparency) const expectedColors = [ - 0x00, 0x00, 0x00, 0x00, - 0x03, 0x02, 0x01, 0xff, - 0x00, 0x80, 0x00, 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x01, + 0xff, + 0x00, + 0x80, + 0x00, + 0x80, ]; expectMeshParams(args, args.colors, expected, expectedColors); @@ -180,25 +230,70 @@ describe("VertexLUT", () => { const makeExpected = () => [ [ - 0x00, 0x00, 0x00, 0x00, // pos.x - 0x00, 0x00, 0x80, 0x3f, // pos.y - 0x00, 0x00, 0x00, 0x40, // pos.z - 0x00, 0x00, 0x00, 0x00, // feature index - 0x00, 0x00, 0x00, 0x00, // color index; unused + 0x00, + 0x00, + 0x00, + 0x00, // pos.x + 0x00, + 0x00, + 0x80, + 0x3f, // pos.y + 0x00, + 0x00, + 0x00, + 0x40, // pos.z + 0x00, + 0x00, + 0x00, + 0x00, // feature index + 0x00, + 0x00, + 0x00, + 0x00, // color index; unused ], [ - 0x00, 0x00, 0x80, 0xbf, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x3f, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0x00, + 0x00, + 0x80, + 0xbf, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, ], [ - 0xa4, 0x70, 0x45, 0x41, - 0xf3, 0x4f, 0xc3, 0x47, - 0x1f, 0x85, 0xc5, 0xc2, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, + 0xa4, + 0x70, + 0x45, + 0x41, + 0xf3, + 0x4f, + 0xc3, + 0x47, + 0x1f, + 0x85, + 0xc5, + 0xc2, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, ], ]; @@ -289,9 +384,18 @@ describe("VertexLUT", () => { // NB: The color values in VertexLUT.Params have premultiplied alpha, and alpha set to (255 - transparency) const expectedColors = [ - 0x00, 0x00, 0x00, 0x00, - 0x03, 0x02, 0x01, 0xff, - 0x00, 0x80, 0x00, 0x80, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x01, + 0xff, + 0x00, + 0x80, + 0x00, + 0x80, ]; expectMeshParams(args, args.colors, transpose(exp), expectedColors); diff --git a/core/frontend/src/test/render/primitives/VertexTableSplitter.test.ts b/core/frontend/src/test/render/primitives/VertexTableSplitter.test.ts index 12e1a0900720..d8fe226a9720 100644 --- a/core/frontend/src/test/render/primitives/VertexTableSplitter.test.ts +++ b/core/frontend/src/test/render/primitives/VertexTableSplitter.test.ts @@ -2,27 +2,34 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; -import { Point2d, Point3d, Range2d, Range3d } from "@itwin/core-geometry"; import { - ColorDef, ColorIndex, Feature, FeatureIndex, FeatureTable, FillFlags, LinePixels, OctEncodedNormal, PackedFeatureTable, - QParams2d, QPoint3d, QPoint3dList, RenderMaterial, RenderTexture, + ColorDef, + ColorIndex, + Feature, + FeatureIndex, + FeatureTable, + FillFlags, + LinePixels, + OctEncodedNormal, + PackedFeatureTable, + QParams2d, + QPoint3d, + QPoint3dList, + RenderMaterial, + RenderTexture, } from "@itwin/core-common"; -import { - IModelApp, - MeshArgs, - MockRender, - PolylineArgs, -} from "../../../core-frontend"; +import { Point2d, Point3d, Range2d, Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { EdgeParams, SegmentEdgeParams } from "../../../common/internal/render/EdgeParams"; +import { MeshParams } from "../../../common/internal/render/MeshParams"; import { createPointStringParams, PointStringParams } from "../../../common/internal/render/PointStringParams"; -import { VertexTable } from "../../../common/internal/render/VertexTable"; +import { TesselatedPolyline } from "../../../common/internal/render/PolylineParams"; import { SurfaceType } from "../../../common/internal/render/SurfaceParams"; -import { MeshParams } from "../../../common/internal/render/MeshParams"; +import { VertexTable } from "../../../common/internal/render/VertexTable"; import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; -import { TesselatedPolyline } from "../../../common/internal/render/PolylineParams"; import { ComputeAnimationNodeId, IndexBuffer, splitMeshParams, splitPointStringParams } from "../../../common/internal/render/VertexTableSplitter"; -import { EdgeParams, SegmentEdgeParams } from "../../../common/internal/render/EdgeParams"; +import { IModelApp, MeshArgs, MockRender, PolylineArgs } from "../../../core-frontend"; interface Point { x: number; // quantized or unquantized x coordinate - y will be x+1 and z will be x+5. @@ -98,7 +105,7 @@ function makePointStringParams(pts: Point[], colors: ColorDef | ColorDef[], unqu linePixels: LinePixels.Solid, flags: { isPlanar: true, isDisjoint: true }, points, - polylines: [[...new Array(points.length).keys()] ], + polylines: [[...new Array(points.length).keys()]], }; const params = createPointStringParams(args, IModelApp.renderSystem.maxTextureSize)!; @@ -110,7 +117,11 @@ function makePointStringParams(pts: Point[], colors: ColorDef | ColorDef[], unqu } function getVertexTableData(vertexTable: VertexTable, numExtraRgba: number): Uint32Array { - let data = new Uint32Array(vertexTable.data.buffer, vertexTable.data.byteOffset, vertexTable.numVertices * vertexTable.numRgbaPerVertex + numExtraRgba); + let data = new Uint32Array( + vertexTable.data.buffer, + vertexTable.data.byteOffset, + vertexTable.numVertices * vertexTable.numRgbaPerVertex + numExtraRgba, + ); if (!vertexTable.usesUnquantizedPositions) return data; @@ -160,25 +171,27 @@ function expectBaseVertices(vertexTable: VertexTable, expectedPts: Point[], hasC const data = getVertexTableData(vertexTable, 0); const fpts = new Float32Array(data.buffer); - const getVertex = vertexTable.usesUnquantizedPositions ? (idx: number) => { - const x = fpts[idx]; - return { - x, - y: fpts[idx + 1], - z: fpts[idx + 2], - featureIndex: data[idx + 3], - colorIndex: (data[idx + 4] & 0x0000ffff), - }; - } : (idx: number) => { - const x = data[idx] & 0xffff; - return { - x, - y: (data[idx] & 0xffff0000) >>> 16, - z: data[idx + 1] & 0xffff, - colorIndex: (data[idx + 1] & 0xffff0000) >>> 16, - featureIndex: data[idx + 2] & 0x00ffffff, + const getVertex = vertexTable.usesUnquantizedPositions ? + (idx: number) => { + const x = fpts[idx]; + return { + x, + y: fpts[idx + 1], + z: fpts[idx + 2], + featureIndex: data[idx + 3], + colorIndex: (data[idx + 4] & 0x0000ffff), + }; + } : + (idx: number) => { + const x = data[idx] & 0xffff; + return { + x, + y: (data[idx] & 0xffff0000) >>> 16, + z: data[idx + 1] & 0xffff, + colorIndex: (data[idx + 1] & 0xffff0000) >>> 16, + featureIndex: data[idx + 2] & 0x00ffffff, + }; }; - }; for (let i = 0; i < vertexTable.numVertices; i++) { const idx = i * vertexTable.numRgbaPerVertex; @@ -218,7 +231,7 @@ interface TriMeshPoint extends Point { function makeTriangleStrip(firstPoint: TriMeshPoint, numTriangles: number, adjustPt?: (pt: TriMeshPoint) => TriMeshPoint): TriMeshPoint[] { adjustPt = adjustPt ?? ((pt: TriMeshPoint) => pt); - const strip = [ adjustPt(firstPoint) ]; + const strip = [adjustPt(firstPoint)]; const pointCount = numTriangles + 2; for (let i = 1; i < pointCount; i++) strip.push(adjustPt({ ...firstPoint, x: firstPoint.x + i })); @@ -255,7 +268,9 @@ function makeMeshParams(mesh: TriMesh): MeshParams { for (const point of mesh.points) qpoints.push(QPoint3d.fromScalars(point.x, point.x + 1, point.x + 5)); - const normals = SurfaceType.Lit === type || SurfaceType.TexturedLit === type ? mesh.points.map((pt) => new OctEncodedNormal(pt.normal!)) : undefined; + const normals = SurfaceType.Lit === type || SurfaceType.TexturedLit === type + ? mesh.points.map((pt) => new OctEncodedNormal(pt.normal!)) + : undefined; let textureMapping; if (mesh.texture) { textureMapping = { @@ -360,7 +375,11 @@ function expectPolyline(polyline: TesselatedPolyline, expected: PolylineIndices[ expect(polyline.nextIndicesAndParams.length).to.equal(4 * expected.length); let i = 0; - const niap = new Uint32Array(polyline.nextIndicesAndParams.buffer, polyline.nextIndicesAndParams.byteOffset, polyline.nextIndicesAndParams.length / 4); + const niap = new Uint32Array( + polyline.nextIndicesAndParams.buffer, + polyline.nextIndicesAndParams.byteOffset, + polyline.nextIndicesAndParams.length / 4, + ); const prevIter = polyline.prevIndices[Symbol.iterator](); for (const index of polyline.indices) { const pt = expected[i]; @@ -376,9 +395,9 @@ function expectPolyline(polyline: TesselatedPolyline, expected: PolylineIndices[ interface Edges { // index, other index, quad index - segments?: Array<[ number, number, number ]>; + segments?: Array<[number, number, number]>; // segments plus oct-encoded normal pair - silhouettes?: Array<[ number, number, number, number ]>; + silhouettes?: Array<[number, number, number, number]>; polylines?: PolylineIndices[]; } @@ -420,7 +439,9 @@ function makeEdgeParams(edges: Edges): EdgeParams { } return { - segments, silhouettes, indexed, + segments, + silhouettes, + indexed, polylines: edges.polylines ? makePolyline(edges.polylines) : undefined, weight: 12, linePixels: LinePixels.Invisible, @@ -432,7 +453,11 @@ function expectSegments(params: SegmentEdgeParams, expected: Array<[number, numb expect(params.indices.length).to.equal(expected.length); expect(params.endPointAndQuadIndices.length).to.equal(4 * expected.length); expect(params.endPointAndQuadIndices.length % 4).to.equal(0); - const epaq = new Uint32Array(params.endPointAndQuadIndices.buffer, params.endPointAndQuadIndices.byteOffset, params.endPointAndQuadIndices.length / 4); + const epaq = new Uint32Array( + params.endPointAndQuadIndices.buffer, + params.endPointAndQuadIndices.byteOffset, + params.endPointAndQuadIndices.length / 4, + ); for (const index of params.indices) { expect(index).to.equal(expected[i][0]); const endPointAndQuad = epaq[i]; @@ -456,7 +481,11 @@ function expectEdges(params: EdgeParams | undefined, expected: Edges | undefined expectSegments(params.silhouettes, expected.silhouettes!); expect(params.silhouettes.normalPairs.length).to.equal(expected.silhouettes!.length * 4); expect(params.silhouettes.normalPairs.length % 4).to.equal(0); - const normals = new Uint32Array(params.silhouettes.normalPairs.buffer, params.silhouettes.normalPairs.byteOffset, params.silhouettes.normalPairs.length / 4); + const normals = new Uint32Array( + params.silhouettes.normalPairs.buffer, + params.silhouettes.normalPairs.byteOffset, + params.silhouettes.normalPairs.length / 4, + ); for (let i = 0; i < expected.silhouettes!.length; i++) expect(normals[i]).to.equal(expected.silhouettes![i][3]); } @@ -469,13 +498,19 @@ function expectEdges(params: EdgeParams | undefined, expected: Edges | undefined describe("VertexTableSplitter", () => { class MockSystem extends MockRender.System { public static maxTextureSize = 2048; - public override get maxTextureSize() { return MockSystem.maxTextureSize; } + public override get maxTextureSize() { + return MockSystem.maxTextureSize; + } public static makeTexture(): RenderTexture { class Texture extends RenderTexture { - public constructor() { super(RenderTexture.Type.Normal); } - public dispose() { } - public get bytesUsed() { return 4; } + public constructor() { + super(RenderTexture.Type.Normal); + } + public dispose() {} + public get bytesUsed() { + return 4; + } } return new Texture(); @@ -520,7 +555,9 @@ describe("VertexTableSplitter", () => { expectPointStrings(params, ColorDef.red, points); const split = splitPointStringParams({ - params, featureTable, maxDimension: 2048, + params, + featureTable, + maxDimension: 2048, computeNodeId: makeComputeNodeId(featureTable, (id) => id.upper > 0 ? 1 : 0), }); expect(split.size).to.equal(2); @@ -540,7 +577,7 @@ describe("VertexTableSplitter", () => { it("reconstructs or collapses color tables and remaps color indices", () => { const featureTable = makePackedFeatureTable("0x1", "0x2"); - const colors = [ ColorDef.red, ColorDef.green, ColorDef.blue ]; + const colors = [ColorDef.red, ColorDef.green, ColorDef.blue]; const points = [ { x: 1, color: 2, feature: 0 }, @@ -553,12 +590,14 @@ describe("VertexTableSplitter", () => { expectPointStrings(params, colors, points); const split = splitPointStringParams({ - params, featureTable, maxDimension: 2048, + params, + featureTable, + maxDimension: 2048, computeNodeId: makeComputeNodeId(featureTable, (id) => id.lower), }); expect(split.size).to.equal(2); - expectPointStrings(split.get(1)!, [ ColorDef.blue, ColorDef.red ], [ + expectPointStrings(split.get(1)!, [ColorDef.blue, ColorDef.red], [ { x: 1, color: 0, feature: 0 }, { x: 2, color: 1, feature: 0 }, ]); @@ -579,7 +618,7 @@ describe("VertexTableSplitter", () => { expect(p.vertices.height).to.equal(h); }; - const colors = [ ColorDef.red, ColorDef.green, ColorDef.blue ]; + const colors = [ColorDef.red, ColorDef.green, ColorDef.blue]; const featureTable = makePackedFeatureTable("0x2", "0x20", "0x200", "0x2000"); const points = [ { x: 0, color: 0, feature: 0 }, @@ -600,14 +639,16 @@ describe("VertexTableSplitter", () => { expectPointStrings(params, colors, points); const split = splitPointStringParams({ - params, featureTable, maxDimension: 6, + params, + featureTable, + maxDimension: 6, computeNodeId: makeComputeNodeId(featureTable, (id) => id.lower), }); expect(split.size).to.equal(4); const p1 = split.get(0x2)!; expectDimensions(p1, 3, 3); - expectPointStrings(p1, [ ColorDef.red, ColorDef.green ], [ + expectPointStrings(p1, [ColorDef.red, ColorDef.green], [ { x: 0, color: 0, feature: 0 }, { x: 1, color: 1, feature: 0 }, ]); @@ -632,8 +673,10 @@ describe("VertexTableSplitter", () => { { x: 8, color: 0, feature: 3 }, ]); }); - function makeSurface(adjustPt?: (pt: TriMeshPoint) => TriMeshPoint): { params: MeshParams, colors: ColorDef | ColorDef[], featureTable: PackedFeatureTable, mesh: TriMesh } { - let colors: ColorDef | ColorDef[] = [ ColorDef.red, ColorDef.green, ColorDef.blue ]; + function makeSurface( + adjustPt?: (pt: TriMeshPoint) => TriMeshPoint, + ): { params: MeshParams, colors: ColorDef | ColorDef[], featureTable: PackedFeatureTable, mesh: TriMesh } { + let colors: ColorDef | ColorDef[] = [ColorDef.red, ColorDef.green, ColorDef.blue]; const featureTable = makePackedFeatureTable("0x1", "0x2", "0x3"); const mesh: TriMesh = { points: [ @@ -645,19 +688,37 @@ describe("VertexTableSplitter", () => { ], indices: [ // feature 0 - 0, 1, 2, - 1, 2, 3, - 4, 5, 6, + 0, + 1, + 2, + 1, + 2, + 3, + 4, + 5, + 6, // feature 1 - 7, 8, 9, - 10, 11, 12, - 10, 11, 13, + 7, + 8, + 9, + 10, + 11, + 12, + 10, + 11, + 13, // feature 2 - 14, 15, 16, - 16, 15, 17, - 14, 18, 17, + 14, + 15, + 16, + 16, + 15, + 17, + 14, + 18, + 17, ], colors, }; @@ -677,7 +738,9 @@ describe("VertexTableSplitter", () => { const texture = params.surface.textureMapping?.texture; const split = splitMeshParams({ - params, featureTable, maxDimension: 2048, + params, + featureTable, + maxDimension: 2048, computeNodeId: makeComputeNodeId(featureTable, (id) => id.lower), createMaterial: (args) => IModelApp.renderSystem.createRenderMaterial(args), }); @@ -685,14 +748,21 @@ describe("VertexTableSplitter", () => { expectMesh(split.get(1)!, { texture, - colors: texture ? ColorDef.from(1, 2, 3) : [ ColorDef.blue, ColorDef.red ], + colors: texture ? ColorDef.from(1, 2, 3) : [ColorDef.blue, ColorDef.red], points: [ ...makeTriangleStrip({ x: 0, color: 0, feature: 0 }, 2, adjustPt), ...makeTriangleStrip({ x: 10, color: 1, feature: 0 }, 1, adjustPt), - ], indices: [ - 0, 1, 2, - 1, 2, 3, - 4, 5, 6, + ], + indices: [ + 0, + 1, + 2, + 1, + 2, + 3, + 4, + 5, + 6, ], }); @@ -702,10 +772,17 @@ describe("VertexTableSplitter", () => { points: [ ...makeTriangleStrip({ x: 20, color: 0, feature: 1 }, 1, adjustPt), ...makeTriangleStrip({ x: 30, color: 0, feature: 1 }, 2, adjustPt), - ], indices: [ - 0, 1, 2, - 3, 4, 5, - 3, 4, 6, + ], + indices: [ + 0, + 1, + 2, + 3, + 4, + 5, + 3, + 4, + 6, ], }); @@ -714,9 +791,15 @@ describe("VertexTableSplitter", () => { colors: texture ? ColorDef.from(1, 2, 3) : ColorDef.red, points: makeTriangleStrip({ x: 40, color: 0, feature: 2 }, 3, adjustPt), indices: [ - 0, 1, 2, - 2, 1, 3, - 0, 4, 3, + 0, + 1, + 2, + 2, + 1, + 3, + 0, + 4, + 3, ], }); } @@ -762,7 +845,8 @@ describe("VertexTableSplitter", () => { [14, 16, 1], [15, 17, 2], [16, 18, 3], - ], silhouettes: [ + ], + silhouettes: [ [2, 3, 0, 123], [4, 6, 1, 987], @@ -772,7 +856,8 @@ describe("VertexTableSplitter", () => { [15, 16, 0, 0], [16, 17, 1, 789], [15, 18, 2, 0xdeadbeef], - ], polylines: [ + ], + polylines: [ [0, 0, 1, 0], [1, 0, 5, 1], [5, 1, 5, 2], @@ -793,7 +878,9 @@ describe("VertexTableSplitter", () => { const { params, featureTable } = surface; const split = splitMeshParams({ - params, featureTable, maxDimension: 2048, + params, + featureTable, + maxDimension: 2048, computeNodeId: makeComputeNodeId(featureTable, (id) => id.lower), createMaterial: (args) => IModelApp.renderSystem.createRenderMaterial(args), }); @@ -809,11 +896,12 @@ describe("VertexTableSplitter", () => { segments: [ [3, 5, 3], [3, 4, 0], - ], silhouettes: [ + ], + silhouettes: [ [0, 1, 2, 0xfedcba98], [1, 2, 3, 0xffffffff], ], - polylines: edges.polylines!.slice(3, 5).map((p) => [ p[0] - 7, p[1] - 7, p[2] - 7, p[3] ]), + polylines: edges.polylines!.slice(3, 5).map((p) => [p[0] - 7, p[1] - 7, p[2] - 7, p[3]]), }); expectEdges(split.get(3)!.edges, { @@ -821,12 +909,13 @@ describe("VertexTableSplitter", () => { [0, 2, 1], [1, 3, 2], [2, 4, 3], - ], silhouettes: [ + ], + silhouettes: [ [1, 2, 0, 0], [2, 3, 1, 789], [1, 4, 2, 0xdeadbeef], ], - polylines: edges.polylines!.slice(5, 10).map((p) => [ p[0] - 14, p[1] - 14, p[2] - 14, p[3] ]), + polylines: edges.polylines!.slice(5, 10).map((p) => [p[0] - 14, p[1] - 14, p[2] - 14, p[3]]), }); }); diff --git a/core/frontend/src/test/render/webgl/BranchUniforms.test.ts b/core/frontend/src/test/render/webgl/BranchUniforms.test.ts index ddaf3355cd40..7bada7c319a4 100644 --- a/core/frontend/src/test/render/webgl/BranchUniforms.test.ts +++ b/core/frontend/src/test/render/webgl/BranchUniforms.test.ts @@ -2,21 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { dispose } from "@itwin/core-bentley"; +import { ClipStyle, EmptyLocalization } from "@itwin/core-common"; import { ClipVector, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; -import { IModelApp } from "../../../IModelApp"; +import { expect } from "chai"; import { ViewRect } from "../../../common/ViewRect"; -import { createEmptyRenderPlan } from "../../../render/RenderPlan"; +import { SpatialViewState } from "../../../core-frontend"; +import { IModelApp } from "../../../IModelApp"; import { GraphicBranch } from "../../../render/GraphicBranch"; -import { Branch } from "../../../render/webgl/Graphic"; -import { ClipVolume } from "../../../render/webgl/ClipVolume"; +import { createEmptyRenderPlan } from "../../../render/RenderPlan"; +import { BranchUniforms } from "../../../render/webgl/BranchUniforms"; import { ClipStack } from "../../../render/webgl/ClipStack"; +import { ClipVolume } from "../../../render/webgl/ClipVolume"; +import { Branch } from "../../../render/webgl/Graphic"; import { Target } from "../../../render/webgl/Target"; -import { ClipStyle, EmptyLocalization } from "@itwin/core-common"; -import { BranchUniforms } from "../../../render/webgl/BranchUniforms"; import { ScreenViewport } from "../../../Viewport"; -import { SpatialViewState } from "../../../core-frontend"; import { createBlankConnection } from "../../createBlankConnection"; function makeClipVolume(): ClipVolume { @@ -37,7 +37,10 @@ function makeBranch(info: ClipInfo): Branch { const branch = new GraphicBranch(); if (undefined !== info.noViewClip) branch.viewFlagOverrides.clipVolume = !info.noViewClip; - const graphic = IModelApp.renderSystem.createGraphicBranch(branch, Transform.identity, { clipVolume: info.clip, disableClipStyle: info.disableClipStyle }); + const graphic = IModelApp.renderSystem.createGraphicBranch(branch, Transform.identity, { + clipVolume: info.clip, + disableClipStyle: info.disableClipStyle, + }); expect(graphic instanceof Branch).to.be.true; return graphic as Branch; } @@ -77,7 +80,14 @@ function expectClipStyle(uniforms: BranchUniforms, expectedAlphas: number[]): vo * - Optionally, the Clipstack's expected ClipStyle alpha values after the branches are pushed. * - Optionally, the viewport's ClipStyle alpha values - what is expected after the branches are popped. */ -function testBranches(viewClip: ClipInfo, branches: ClipInfo[], expectViewClip: boolean, expectedClips: Array<{ numRows: number }>, branchClipStyleAlphaValues?: number[], viewportClipStyleAlphaValues?: number[]): void { +function testBranches( + viewClip: ClipInfo, + branches: ClipInfo[], + expectViewClip: boolean, + expectedClips: Array<{ numRows: number }>, + branchClipStyleAlphaValues?: number[], + viewportClipStyleAlphaValues?: number[], +): void { const plan = { ...createEmptyRenderPlan(), clip: viewClip.clip?.clipVector }; plan.viewFlags = plan.viewFlags.with("clipVolume", true !== viewClip.noViewClip); @@ -159,7 +169,7 @@ describe("BranchUniforms", async () => { testBranches({ clip: viewClip }, [{ clip: outerClip }, { clip: innerClip }], true, [viewClip, outerClip, innerClip]); }); - it ("should disable clip style", async () => { + it("should disable clip style", async () => { const viewClip = makeClipVolume(); const branchClip = makeClipVolume(); @@ -175,26 +185,26 @@ describe("BranchUniforms", async () => { // create a clip style and assign it to the viewport const testStyle = ClipStyle.fromJSON({ - insideColor: {r: 255, g: 0, b: 0}, - outsideColor: {r: 0, g: 255, b: 0}, + insideColor: { r: 255, g: 0, b: 0 }, + outsideColor: { r: 0, g: 255, b: 0 }, intersectionStyle: { - color: {r: 0, g: 0, b: 255}, + color: { r: 0, g: 0, b: 255 }, width: 1, }, }); vp.clipStyle = testStyle; // disableClipStyle is undefined, so we expect the inside color, outside color, and intersection style width to all be 1 - testBranches({ clip: viewClip }, [{ clip: branchClip }], true, [viewClip, branchClip], [1,1,1]); + testBranches({ clip: viewClip }, [{ clip: branchClip }], true, [viewClip, branchClip], [1, 1, 1]); // disableClipStyle is true, so we expect the branch to have disabled the inside color, outside color, and intersection style width, // setting all of their alpha values to 0. After the branch is popped, we expect the viewport's clip style to be restored. - testBranches({ clip: viewClip }, [{ clip: branchClip, disableClipStyle: true }], true, [viewClip, branchClip], [0,0,0], [1,1,1]); + testBranches({ clip: viewClip }, [{ clip: branchClip, disableClipStyle: true }], true, [viewClip, branchClip], [0, 0, 0], [1, 1, 1]); IModelApp.viewManager.dropViewport(vp); }); - it("should inherit clip style from the top of the stack",async () => { + it("should inherit clip style from the top of the stack", async () => { const viewClip = makeClipVolume(); const firstClip = makeClipVolume(); const secondClip = makeClipVolume(); @@ -212,22 +222,28 @@ describe("BranchUniforms", async () => { // create a clip style and assign it to the viewport const testStyle = ClipStyle.fromJSON({ - insideColor: {r: 255, g: 0, b: 0}, - outsideColor: {r: 0, g: 255, b: 0}, + insideColor: { r: 255, g: 0, b: 0 }, + outsideColor: { r: 0, g: 255, b: 0 }, intersectionStyle: { - color: {r: 0, g: 0, b: 255}, + color: { r: 0, g: 0, b: 255 }, width: 1, }, }); vp.clipStyle = testStyle; - testBranches({ clip: viewClip }, [{ clip: firstClip, disableClipStyle: true }, { clip: secondClip}, {clip: thirdClip}], true, [viewClip, firstClip, secondClip, thirdClip], [0,0,0], [1,1,1]); + testBranches( + { clip: viewClip }, + [{ clip: firstClip, disableClipStyle: true }, { clip: secondClip }, { clip: thirdClip }], + true, + [viewClip, firstClip, secondClip, thirdClip], + [0, 0, 0], + [1, 1, 1], + ); IModelApp.viewManager.dropViewport(vp); }); it("should disable clip style in complex scene graphs", async () => { - // create a viewport const imodel = createBlankConnection("imodel"); const viewDiv = document.createElement("div"); @@ -240,10 +256,10 @@ describe("BranchUniforms", async () => { // create a clip style and assign it to the viewport const testStyle = ClipStyle.fromJSON({ - insideColor: {r: 255, g: 0, b: 0}, - outsideColor: {r: 0, g: 255, b: 0}, + insideColor: { r: 255, g: 0, b: 0 }, + outsideColor: { r: 0, g: 255, b: 0 }, intersectionStyle: { - color: {r: 0, g: 0, b: 255}, + color: { r: 0, g: 0, b: 255 }, width: 1, }, }); @@ -275,30 +291,30 @@ describe("BranchUniforms", async () => { target.pushBranch(branch1); // expect clip style to be enabled - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.pushBranch(branch1a); // expect clip style to be disabled - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.pushBranch(branch1a1); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.pushBranch(branch1a2); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); // after this pop, all branches have been popped target.popBranch(); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); /* scenario 2 scene graph: * branch 1 @@ -319,45 +335,45 @@ describe("BranchUniforms", async () => { const branch2a = makeBranch({ clip: makeClipVolume() }); target.pushBranch(branch1); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.pushBranch(branch1a); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.pushBranch(branch1a1); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.pushBranch(branch1a1a); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.pushBranch(branch1a2); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [0,0,0]); + expectClipStyle(uniforms, [0, 0, 0]); target.popBranch(); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.pushBranch(branch1b); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.popBranch(); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.popBranch(); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.pushBranch(branch2); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); target.pushBranch(branch2a); - expectClipStyle(uniforms, [1,1,1]); + expectClipStyle(uniforms, [1, 1, 1]); }); }); diff --git a/core/frontend/src/test/render/webgl/BufferHandle.test.ts b/core/frontend/src/test/render/webgl/BufferHandle.test.ts index 8dee2d9f6b28..c0d517b70b58 100644 --- a/core/frontend/src/test/render/webgl/BufferHandle.test.ts +++ b/core/frontend/src/test/render/webgl/BufferHandle.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; -import { GL } from "../../../render/webgl/GL"; import { BufferHandle } from "../../../render/webgl/AttributeBuffers"; -import { EmptyLocalization } from "@itwin/core-common"; +import { GL } from "../../../render/webgl/GL"; describe("BufferHandle", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/render/webgl/ClipStack.test.ts b/core/frontend/src/test/render/webgl/ClipStack.test.ts index cdc90089fcf7..9874f506c7dc 100644 --- a/core/frontend/src/test/render/webgl/ClipStack.test.ts +++ b/core/frontend/src/test/render/webgl/ClipStack.test.ts @@ -2,16 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { ClipVector, Point3d, Transform } from "@itwin/core-geometry"; -import { ClipVolume } from "../../../render/webgl/ClipVolume"; -import { ClipStack } from "../../../render/webgl/ClipStack"; +import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; -import { EmptyLocalization } from "@itwin/core-common"; +import { ClipStack } from "../../../render/webgl/ClipStack"; +import { ClipVolume } from "../../../render/webgl/ClipVolume"; function createClipVector(offset = 0): ClipVector { const clip = ClipVector.createEmpty(); - clip.appendShape([Point3d.create(offset + 1, 1, 0), Point3d.create(offset + 2, 1, 0), Point3d.create(offset + 2, 2, 0), Point3d.create(offset + 1, 2, 0)]); + clip.appendShape([ + Point3d.create(offset + 1, 1, 0), + Point3d.create(offset + 2, 1, 0), + Point3d.create(offset + 2, 2, 0), + Point3d.create(offset + 1, 2, 0), + ]); return clip; } @@ -54,12 +59,24 @@ describe("ClipStack", async () => { }; } - public get cpuBuffer() { return this._cpuBuffer; } - public get gpuBuffer() { return this._gpuBuffer; } - public get numTotalRows() { return this._numTotalRows; } - public get numRowsInUse() { return this._numRowsInUse; } - public get stack() { return this._stack; } - public get isStackDirty() { return this._isStackDirty; } + public get cpuBuffer() { + return this._cpuBuffer; + } + public get gpuBuffer() { + return this._gpuBuffer; + } + public get numTotalRows() { + return this._numTotalRows; + } + public get numRowsInUse() { + return this._numRowsInUse; + } + public get stack() { + return this._stack; + } + public get isStackDirty() { + return this._isStackDirty; + } public pushClip(offset = 0): void { const clip = createClipVector(offset); @@ -74,7 +91,11 @@ describe("ClipStack", async () => { } public reset() { - this.invoked.uploadTexture = this.invoked.allocateGpuBuffer = this.invoked.updateTexture = this.invoked.recomputeTexture = false; + this.invoked.uploadTexture = + this.invoked.allocateGpuBuffer = + this.invoked.updateTexture = + this.invoked.recomputeTexture = + false; } public expectInvoked(expected: Partial) { diff --git a/core/frontend/src/test/render/webgl/ClipVolume.test.ts b/core/frontend/src/test/render/webgl/ClipVolume.test.ts index 0700d0523f1e..0ab19419037a 100644 --- a/core/frontend/src/test/render/webgl/ClipVolume.test.ts +++ b/core/frontend/src/test/render/webgl/ClipVolume.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { ClipPrimitive, ClipShape, ClipVector, Point3d, Transform, UnionOfConvexClipPlaneSets } from "@itwin/core-geometry"; -import { ClipVolume } from "../../../render/webgl/ClipVolume"; +import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; -import { EmptyLocalization } from "@itwin/core-common"; +import { ClipVolume } from "../../../render/webgl/ClipVolume"; describe("ClipVolume", async () => { before(async () => { @@ -39,7 +39,7 @@ describe("ClipVolume", async () => { const shape = ClipShape.createShape(points, 1.0, 2.0)!; expect(shape).not.to.be.undefined; - const clipVector = ClipVector.create([ shape ]); + const clipVector = ClipVector.create([shape]); expect(clipVector).not.to.be.undefined; const clipVolume = ClipVolume.create(clipVector)!; @@ -54,7 +54,7 @@ describe("ClipVolume", async () => { it("should support compound ClipVectors", () => { const vec = ClipVector.createEmpty(); - expect(vec.appendShape([ Point3d.create(1, 1, 0), Point3d.create(2, 1, 0), Point3d.create(2, 2, 0), Point3d.create(1, 2, 0) ], 1, 2)).to.be.true; + expect(vec.appendShape([Point3d.create(1, 1, 0), Point3d.create(2, 1, 0), Point3d.create(2, 2, 0), Point3d.create(1, 2, 0)], 1, 2)).to.be.true; let vol = ClipVolume.create(vec)!; expect(vol).not.to.be.undefined; expect(vol.clipVector).to.equal(vec); diff --git a/core/frontend/src/test/render/webgl/ColorMap.test.ts b/core/frontend/src/test/render/webgl/ColorMap.test.ts index f46340f19edb..b4928cd88805 100644 --- a/core/frontend/src/test/render/webgl/ColorMap.test.ts +++ b/core/frontend/src/test/render/webgl/ColorMap.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { ColorDef, ColorIndex } from "@itwin/core-common"; +import { assert, expect } from "chai"; import { ColorMap } from "../../../common/internal/render/ColorMap"; describe("ColorMap", () => { diff --git a/core/frontend/src/test/render/webgl/Decorations.test.ts b/core/frontend/src/test/render/webgl/Decorations.test.ts index e1312204392e..2dba104c568d 100644 --- a/core/frontend/src/test/render/webgl/Decorations.test.ts +++ b/core/frontend/src/test/render/webgl/Decorations.test.ts @@ -2,18 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { ColorDef, EmptyLocalization, RenderMode } from "@itwin/core-common"; -import { IModelConnection } from "../../../IModelConnection"; -import { ScreenViewport } from "../../../Viewport"; +import { Point3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { ViewRect } from "../../../common/ViewRect"; import { IModelApp } from "../../../IModelApp"; +import { IModelConnection } from "../../../IModelConnection"; import { SpatialViewState } from "../../../SpatialViewState"; +import { StandardViewId } from "../../../StandardView"; +import { ScreenViewport } from "../../../Viewport"; +import { ViewState } from "../../../ViewState"; import { createBlankConnection } from "../../createBlankConnection"; -import { BoxDecorator, SphereDecorator, TestDecorator } from "../../TestDecorators"; import { expectColors } from "../../ExpectColors"; -import { ViewRect } from "../../../common/ViewRect"; -import { ViewState } from "../../../ViewState"; -import { StandardViewId } from "../../../StandardView"; +import { BoxDecorator, SphereDecorator, TestDecorator } from "../../TestDecorators"; describe("Decorations", () => { let imodel: IModelConnection; diff --git a/core/frontend/src/test/render/webgl/EarlyZBugWorkaround.test.ts b/core/frontend/src/test/render/webgl/EarlyZBugWorkaround.test.ts index 5cdee74c51ac..e035620c0bc6 100644 --- a/core/frontend/src/test/render/webgl/EarlyZBugWorkaround.test.ts +++ b/core/frontend/src/test/render/webgl/EarlyZBugWorkaround.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { EmptyLocalization } from "@itwin/core-common"; import { Capabilities } from "@itwin/webgl-compatibility"; -import { RenderSystem } from "../../../render/RenderSystem"; +import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; +import { RenderSystem } from "../../../render/RenderSystem"; import { CompileStatus, ShaderProgram } from "../../../render/webgl/ShaderProgram"; import { System } from "../../../render/webgl/System"; -import { EmptyLocalization } from "@itwin/core-common"; class TestSystem extends System { private static _simulateBug = true; diff --git a/core/frontend/src/test/render/webgl/EdgeSettings.test.ts b/core/frontend/src/test/render/webgl/EdgeSettings.test.ts index 3d2ab90ec1ab..aba303bd81ab 100644 --- a/core/frontend/src/test/render/webgl/EdgeSettings.test.ts +++ b/core/frontend/src/test/render/webgl/EdgeSettings.test.ts @@ -3,19 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef, HiddenLine, LinePixels, RenderMode, ViewFlags } from "@itwin/core-common"; +import { expect } from "chai"; +import { OvrFlags } from "../../../common/internal/render/OvrFlags"; import { EdgeSettings } from "../../../render/webgl/EdgeSettings"; -import { RenderPass } from "../../../render/webgl/RenderFlags"; import { LineCode } from "../../../render/webgl/LineCode"; -import { OvrFlags } from "../../../common/internal/render/OvrFlags"; +import { RenderPass } from "../../../render/webgl/RenderFlags"; describe("EdgeSettings", () => { it("defaults to overriding nothing", () => { const es = EdgeSettings.create(undefined); - for (const renderMode of [ RenderMode.Wireframe, RenderMode.SmoothShade ]) { + for (const renderMode of [RenderMode.Wireframe, RenderMode.SmoothShade]) { const vf = ViewFlags.fromJSON({ renderMode }); - for (const pass of [ RenderPass.OpaqueLinear, RenderPass.HiddenEdge ]) { + for (const pass of [RenderPass.OpaqueLinear, RenderPass.HiddenEdge]) { expect(es.computeOvrFlags(pass, vf)).to.equal(OvrFlags.None); es.init(undefined); expect(es.computeOvrFlags(pass, vf)).to.equal(OvrFlags.None); @@ -106,14 +106,14 @@ describe("EdgeSettings", () => { ]; for (const vf of vfs) - for (const pass of [ RenderPass.OpaqueLinear, RenderPass.HiddenEdge ]) + for (const pass of [RenderPass.OpaqueLinear, RenderPass.HiddenEdge]) expect(es.computeOvrFlags(pass, vf)).to.equal(OvrFlags.None); }); it("overrides defaults for certain render modes", () => { const es = EdgeSettings.create(undefined); - for (const renderMode of [ RenderMode.HiddenLine, RenderMode.SolidFill ]) - for (const pass of [ RenderPass.OpaqueLinear, RenderPass.HiddenEdge ]) { + for (const renderMode of [RenderMode.HiddenLine, RenderMode.SolidFill]) + for (const pass of [RenderPass.OpaqueLinear, RenderPass.HiddenEdge]) { const vf = ViewFlags.fromJSON({ renderMode }); // If color is not explicitly overridden in solid fill mode, the shader will compute a contrasting shade of grey for each element. @@ -125,7 +125,11 @@ describe("EdgeSettings", () => { it("clamps and inverts transparency threshold", () => { const inputsOutputs = [ - [ 0, 1 ], [ 1, 0 ], [ 0.75, 0.25 ], [ -1, 1 ], [ 2, 0 ], + [0, 1], + [1, 0], + [0.75, 0.25], + [-1, 1], + [2, 0], ]; for (const inputOutput of inputsOutputs) { @@ -143,7 +147,7 @@ describe("EdgeSettings", () => { expect(es.getWeight(RenderPass.HiddenEdge, vf)).to.equal(es.getWeight(RenderPass.OpaqueLinear, vf)); expect(es.getLineCode(RenderPass.HiddenEdge, vf)).to.equal(hiddenPattern); - es.init(HiddenLine.Settings.fromJSON({ visible: { width: 4, pattern: LinePixels.Code3 }, hidden: { } })); + es.init(HiddenLine.Settings.fromJSON({ visible: { width: 4, pattern: LinePixels.Code3 }, hidden: {} })); expect(es.getWeight(RenderPass.HiddenEdge, vf)).to.equal(es.getWeight(RenderPass.OpaqueLinear, vf)); expect(es.getLineCode(RenderPass.HiddenEdge, vf)).to.equal(hiddenPattern); }); diff --git a/core/frontend/src/test/render/webgl/FeatureOverrides.test.ts b/core/frontend/src/test/render/webgl/FeatureOverrides.test.ts index 056dbe6ddc6a..855b287055ac 100644 --- a/core/frontend/src/test/render/webgl/FeatureOverrides.test.ts +++ b/core/frontend/src/test/render/webgl/FeatureOverrides.test.ts @@ -2,22 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeEvent } from "@itwin/core-bentley"; +import { + ColorByName, + ColorDef, + EmptyLocalization, + Feature, + FeatureAppearance, + FeatureTable, + PackedFeatureTable, + RenderMode, + RgbColor, +} from "@itwin/core-common"; import { Point2d, Range3d, Transform } from "@itwin/core-geometry"; -import { ColorByName, ColorDef, EmptyLocalization, Feature, FeatureAppearance, FeatureTable, PackedFeatureTable, RenderMode, RgbColor } from "@itwin/core-common"; +import { expect } from "chai"; +import { OvrFlags } from "../../../common/internal/render/OvrFlags"; +import { GraphicType } from "../../../common/render/GraphicType"; import { ViewRect } from "../../../common/ViewRect"; import { IModelApp } from "../../../IModelApp"; import { FeatureSymbology } from "../../../render/FeatureSymbology"; import { GraphicBranch } from "../../../render/GraphicBranch"; +import { Batch, Branch } from "../../../render/webgl/Graphic"; import { Target } from "../../../render/webgl/Target"; import { Texture2DDataUpdater } from "../../../render/webgl/Texture"; -import { Batch, Branch } from "../../../render/webgl/Graphic"; -import { readUniqueColors, testBlankViewport } from "../../openBlankViewport"; -import { OvrFlags } from "../../../common/internal/render/OvrFlags"; -import { Decorator } from "../../../ViewManager"; import { DecorateContext } from "../../../ViewContext"; -import { GraphicType } from "../../../common/render/GraphicType"; +import { Decorator } from "../../../ViewManager"; +import { readUniqueColors, testBlankViewport } from "../../openBlankViewport"; describe("FeatureOverrides", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); @@ -343,7 +353,9 @@ describe("FeatureOverrides", () => { expect(target.hilites).to.equal(vp.iModel.hilited); expect(b1.perTargetData.data.length).to.equal(1); - const expected = new Set(expectedHilitedElements ? (typeof expectedHilitedElements === "string" ? [expectedHilitedElements] : expectedHilitedElements) : []); + const expected = new Set( + expectedHilitedElements ? (typeof expectedHilitedElements === "string" ? [expectedHilitedElements] : expectedHilitedElements) : [], + ); if (expected.size > 0) { expect(b1.perTargetData.data.length).to.equal(1); expect(b2.perTargetData.data.length).to.equal(1); @@ -505,7 +517,11 @@ describe("FeatureOverrides", () => { it("is the same as surfaces by default", () => { expectColors(FeatureAppearance.fromRgb(ColorDef.white), [ColorDef.white]); expectColors(FeatureAppearance.fromRgba(ColorDef.white.withTransparency(127)), [ColorDef.white.withTransparency(127)]); - expectColors(FeatureAppearance.fromTransparency(0.5), [lineColor.withTransparency(127), pointColor.withTransparency(127), shapeColor.withTransparency(127)]); + expectColors(FeatureAppearance.fromTransparency(0.5), [ + lineColor.withTransparency(127), + pointColor.withTransparency(127), + shapeColor.withTransparency(127), + ]); }); it("optionally ignores surface overrides", () => { diff --git a/core/frontend/src/test/render/webgl/FloatRGBA.test.ts b/core/frontend/src/test/render/webgl/FloatRGBA.test.ts index b6c4d5afe64d..f90360b6937e 100644 --- a/core/frontend/src/test/render/webgl/FloatRGBA.test.ts +++ b/core/frontend/src/test/render/webgl/FloatRGBA.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef } from "@itwin/core-common"; +import { expect } from "chai"; import { FloatRgb, FloatRgba } from "../../../render/webgl/FloatRGBA"; interface Rgb { diff --git a/core/frontend/src/test/render/webgl/FrameBuffer.test.ts b/core/frontend/src/test/render/webgl/FrameBuffer.test.ts index 841d90ebdf35..e54be2ba63e3 100644 --- a/core/frontend/src/test/render/webgl/FrameBuffer.test.ts +++ b/core/frontend/src/test/render/webgl/FrameBuffer.test.ts @@ -3,6 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { assert, expect } from "chai"; import { IModelApp } from "../../../IModelApp"; import { Debug } from "../../../render/webgl/Diagnostics"; @@ -10,7 +11,6 @@ import { FrameBuffer } from "../../../render/webgl/FrameBuffer"; import { GL } from "../../../render/webgl/GL"; import { RenderBuffer } from "../../../render/webgl/RenderBuffer"; import { TextureHandle } from "../../../render/webgl/Texture"; -import { EmptyLocalization } from "@itwin/core-common"; describe("FrameBuffer tests", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/render/webgl/FrustumUniforms.test.ts b/core/frontend/src/test/render/webgl/FrustumUniforms.test.ts index 6d8fdfdd0a7f..dd2c6449e197 100644 --- a/core/frontend/src/test/render/webgl/FrustumUniforms.test.ts +++ b/core/frontend/src/test/render/webgl/FrustumUniforms.test.ts @@ -10,8 +10,12 @@ class TestUniforms extends FrustumUniforms { super(); } - public testSetPlanes(top: number, bottom: number, left: number, right: number): void { this.setPlanes(top, bottom, left, right); } - public testSetFrustum(nearPlane: number, farPlane: number, type: FrustumUniformType): void { this.setFrustum(nearPlane, farPlane, type); } + public testSetPlanes(top: number, bottom: number, left: number, right: number): void { + this.setPlanes(top, bottom, left, right); + } + public testSetFrustum(nearPlane: number, farPlane: number, type: FrustumUniformType): void { + this.setFrustum(nearPlane, farPlane, type); + } } describe("FrustumUniforms", () => { @@ -26,18 +30,30 @@ describe("FrustumUniforms", () => { const p: Float32Array = fu.planes; let f: Float32Array = fu.frustum; - assert.isTrue(1.0 === p[0] && 2.0 === p[1] && 3.0 === p[2] && 4.0 === p[3], "should be able to retrieve same values of planes after setting them"); - assert.isTrue(5.0 === f[0] && 6.0 === f[1] && FrustumUniformType.Perspective === f[2], "should be able to retrieve same values of Perspective frustum after setting them"); + assert.isTrue( + 1.0 === p[0] && 2.0 === p[1] && 3.0 === p[2] && 4.0 === p[3], + "should be able to retrieve same values of planes after setting them", + ); + assert.isTrue( + 5.0 === f[0] && 6.0 === f[1] && FrustumUniformType.Perspective === f[2], + "should be able to retrieve same values of Perspective frustum after setting them", + ); expect(fu.is2d).to.be.false; fu.testSetFrustum(7.0, 8.0, FrustumUniformType.Orthographic); f = fu.frustum; - assert.isTrue(7.0 === f[0] && 8.0 === f[1] && FrustumUniformType.Orthographic === f[2], "should be able to retrieve same values of Orthographic frustum after setting them"); + assert.isTrue( + 7.0 === f[0] && 8.0 === f[1] && FrustumUniformType.Orthographic === f[2], + "should be able to retrieve same values of Orthographic frustum after setting them", + ); expect(fu.is2d).to.be.false; fu.testSetFrustum(0.0, 1.0, FrustumUniformType.TwoDee); f = fu.frustum; - assert.isTrue(0.0 === f[0] && 1.0 === f[1] && FrustumUniformType.TwoDee === f[2], "should be able to retrieve same values of TwoDee frustum after setting them"); + assert.isTrue( + 0.0 === f[0] && 1.0 === f[1] && FrustumUniformType.TwoDee === f[2], + "should be able to retrieve same values of TwoDee frustum after setting them", + ); expect(fu.is2d).to.be.true; fu.testSetPlanes(1.0, 2.0, 3.0, 4.0); diff --git a/core/frontend/src/test/render/webgl/Graphic.test.ts b/core/frontend/src/test/render/webgl/Graphic.test.ts index 182e0c3280fb..7929c46f1759 100644 --- a/core/frontend/src/test/render/webgl/Graphic.test.ts +++ b/core/frontend/src/test/render/webgl/Graphic.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { IModelApp } from "../../../IModelApp"; import { EmptyLocalization, FeatureTable, PackedFeatureTable } from "@itwin/core-common"; -import { RenderGraphic } from "../../../render/RenderGraphic"; import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; -import { GraphicBuilder } from "../../../render/GraphicBuilder"; -import { GraphicBranch } from "../../../render/GraphicBranch"; +import { expect } from "chai"; import { GraphicType } from "../../../common/render/GraphicType"; +import { IModelApp } from "../../../IModelApp"; +import { GraphicBranch } from "../../../render/GraphicBranch"; +import { GraphicBuilder } from "../../../render/GraphicBuilder"; +import { RenderGraphic } from "../../../render/RenderGraphic"; describe("Graphic", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/render/webgl/IndexedEdges.test.ts b/core/frontend/src/test/render/webgl/IndexedEdges.test.ts index 59aebcc789ae..68463a98ae90 100644 --- a/core/frontend/src/test/render/webgl/IndexedEdges.test.ts +++ b/core/frontend/src/test/render/webgl/IndexedEdges.test.ts @@ -2,14 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ByteStream } from "@itwin/core-bentley"; +import { + ColorIndex, + EmptyLocalization, + FeatureIndex, + FillFlags, + MeshEdge, + OctEncodedNormal, + OctEncodedNormalPair, + QPoint3dList, +} from "@itwin/core-common"; import { Point3d } from "@itwin/core-geometry"; -import { ColorIndex, EmptyLocalization, FeatureIndex, FillFlags, MeshEdge, OctEncodedNormal, OctEncodedNormalPair, QPoint3dList } from "@itwin/core-common"; -import { IModelApp } from "../../../IModelApp"; +import { expect } from "chai"; +import { createEdgeParams, EdgeParams, EdgeTable } from "../../../common/internal/render/EdgeParams"; import { MeshArgsEdges } from "../../../common/internal/render/MeshPrimitives"; import { VertexIndices } from "../../../common/internal/render/VertexIndices"; -import { createEdgeParams, EdgeParams, EdgeTable } from "../../../common/internal/render/EdgeParams"; +import { IModelApp } from "../../../IModelApp"; import { MeshArgs } from "../../../render/MeshArgs"; function makeNormalPair(n0: number, n1: number): OctEncodedNormalPair { @@ -159,27 +168,104 @@ describe("IndexedEdgeParams", () => { expect(edges.segments).to.be.undefined; expectIndices(edges.indexed!.indices, [ - 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 5, + 5, + 6, + 6, + 6, + 6, + 6, + 6, + 7, + 7, + 7, + 7, + 7, + 7, + 8, + 8, + 8, + 8, + 8, + 8, + 9, + 9, + 9, + 9, + 9, + 9, + 10, + 10, + 10, + 10, + 10, + 10, ]); expectEdgeTable(edges.indexed!.edges, [ // visible - 0, 1, 1, 3, 3, 4, + 0, + 1, + 1, + 3, + 3, + 4, // polylines - 0, 2, 2, 4, 2, 4, 3, 4, 1, 3, 0, 1, + 0, + 2, + 2, + 4, + 2, + 4, + 3, + 4, + 1, + 3, + 0, + 1, ], [ // silhouettes - 1, 2, 0, 0xffff, - 2, 3, 0x1234, 0xfedc, + 1, + 2, + 0, + 0xffff, + 2, + 3, + 0x1234, + 0xfedc, ]); }); @@ -189,29 +275,105 @@ describe("IndexedEdgeParams", () => { expect(edges).not.to.be.undefined; expect(edges.indexed).not.to.be.undefined; expectIndices(edges.indexed!.indices, [ - 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, - 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 2, + 2, + 2, + 2, + 3, + 3, + 3, + 3, + 3, + 3, + 4, + 4, + 4, + 4, + 4, + 4, + 5, + 5, + 5, + 5, + 5, + 5, + 6, + 6, + 6, + 6, + 6, + 6, + 7, + 7, + 7, + 7, + 7, + 7, + 8, + 8, + 8, + 8, + 8, + 8, + 9, + 9, + 9, + 9, + 9, + 9, + 10, + 10, + 10, + 10, + 10, + 10, ]); expectEdgeTable(edges.indexed!.edges, [ // visible - 0, 1, 1, 3, 3, 4, + 0, + 1, + 1, + 3, + 3, + 4, // polylines - 0, 2, 2, 4, 2, 4, 3, 4, 1, 3, 0, 1, + 0, + 2, + 2, + 4, + 2, + 4, + 3, + 4, + 1, + 3, + 0, + 1, ], [ // silhouettes - 1, 2, 0, 0xffff, - 2, 3, 0x1234, 0xfedc, - ], - 6); + 1, + 2, + 0, + 0xffff, + 2, + 3, + 0x1234, + 0xfedc, + ], 6); function makeEdgeTable(nSegs: number, nSils: number): EdgeTable { const meshargs = createMeshArgs(); diff --git a/core/frontend/src/test/render/webgl/LineCode.test.ts b/core/frontend/src/test/render/webgl/LineCode.test.ts index 342fd88611ee..32381c8247c2 100644 --- a/core/frontend/src/test/render/webgl/LineCode.test.ts +++ b/core/frontend/src/test/render/webgl/LineCode.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { LinePixels } from "@itwin/core-common"; +import { expect } from "chai"; import { LineCode } from "../../../render/webgl/LineCode"; describe("LineCode", () => { diff --git a/core/frontend/src/test/render/webgl/Material.test.ts b/core/frontend/src/test/render/webgl/Material.test.ts index cc064573c7c1..b3c6d6f8eac6 100644 --- a/core/frontend/src/test/render/webgl/Material.test.ts +++ b/core/frontend/src/test/render/webgl/Material.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef, RenderMaterial } from "@itwin/core-common"; +import { expect } from "chai"; import { Material } from "../../../render/webgl/Material"; // Equivalent to the glsl function used in glsl/Material.ts to unpack a vec3 material param from a packed float value. diff --git a/core/frontend/src/test/render/webgl/Matrix.test.ts b/core/frontend/src/test/render/webgl/Matrix.test.ts index 5c1ce017cb6a..6495da916e11 100644 --- a/core/frontend/src/test/render/webgl/Matrix.test.ts +++ b/core/frontend/src/test/render/webgl/Matrix.test.ts @@ -3,14 +3,24 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Matrix3d, Matrix4d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { fromNormalizedCrossProduct, Matrix3, Matrix4, normalizedDifference } from "../../../render/webgl/Matrix"; describe("Matrix3", () => { it("constructor works as expected", () => { // ensure correct conversion from 64 bit number to 32 bit number - const mat = Matrix3.fromValues(9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991); + const mat = Matrix3.fromValues( + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + ); mat.data.forEach((v) => assert.isTrue(v === 9007199254740992)); }); it("toMatrix3d works as expected", () => { @@ -59,7 +69,24 @@ describe("Matrix3", () => { describe("Matrix4", () => { it("constructor works as expected", () => { // ensure correct conversion from 64 bit number to 32 bit number - const mat = Matrix4.fromValues(9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991, 9007199254740991); + const mat = Matrix4.fromValues( + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + 9007199254740991, + ); mat.data.forEach((v) => assert.isTrue(v === 9007199254740992)); }); it("identity works as expected", () => { diff --git a/core/frontend/src/test/render/webgl/PickableDecorations.test.ts b/core/frontend/src/test/render/webgl/PickableDecorations.test.ts index eda184b6e2b5..c50dd687b999 100644 --- a/core/frontend/src/test/render/webgl/PickableDecorations.test.ts +++ b/core/frontend/src/test/render/webgl/PickableDecorations.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { GraphicType } from "../../../common/render/GraphicType"; import { IModelApp } from "../../../IModelApp"; import { DecorateContext } from "../../../ViewContext"; import { Viewport } from "../../../Viewport"; import { readUniquePixelData, testBlankViewport } from "../../openBlankViewport"; -import { GraphicType } from "../../../common/render/GraphicType"; describe("Pickable decorations", () => { class Decorator { diff --git a/core/frontend/src/test/render/webgl/PickableGraphics.test.ts b/core/frontend/src/test/render/webgl/PickableGraphics.test.ts index debc0de0b0f5..6897d4a2e974 100644 --- a/core/frontend/src/test/render/webgl/PickableGraphics.test.ts +++ b/core/frontend/src/test/render/webgl/PickableGraphics.test.ts @@ -2,18 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point3d, Vector3d } from "@itwin/core-geometry"; import { ColorDef, EmptyLocalization, Feature, GeometryClass, RenderMode } from "@itwin/core-common"; -import { IModelConnection } from "../../../IModelConnection"; -import { ScreenViewport } from "../../../Viewport"; -import { DecorateContext } from "../../../ViewContext"; +import { Point3d, Vector3d } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { GraphicType } from "../../../core-frontend"; import { IModelApp } from "../../../IModelApp"; +import { IModelConnection } from "../../../IModelConnection"; import { SpatialViewState } from "../../../SpatialViewState"; +import { DecorateContext } from "../../../ViewContext"; +import { ScreenViewport } from "../../../Viewport"; import { createBlankConnection } from "../../createBlankConnection"; -import { BoxDecorator, TestDecorator } from "../../TestDecorators"; import { expectColors } from "../../ExpectColors"; -import { GraphicType } from "../../../core-frontend"; +import { BoxDecorator, TestDecorator } from "../../TestDecorators"; describe("Pickable graphic", () => { let imodel: IModelConnection; diff --git a/core/frontend/src/test/render/webgl/RenderGraphicTileTree.test.ts b/core/frontend/src/test/render/webgl/RenderGraphicTileTree.test.ts index 0c4b6355f6c4..1cb34dc0ba39 100644 --- a/core/frontend/src/test/render/webgl/RenderGraphicTileTree.test.ts +++ b/core/frontend/src/test/render/webgl/RenderGraphicTileTree.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Feature } from "@itwin/core-common"; +import { Point3d } from "@itwin/core-geometry"; import { expect } from "chai"; -import { IModelApp } from "../../../IModelApp"; import { GraphicType, HitDetail, HitDetailProps, HitPriority, HitSource, TileTreeReference } from "../../../core-frontend"; +import { IModelApp } from "../../../IModelApp"; import { testBlankViewportAsync } from "../../openBlankViewport"; -import { Feature } from "@itwin/core-common"; -import { Point3d } from "@itwin/core-geometry"; describe("TileTreeReference.createFromRenderGraphic", () => { before(async () => IModelApp.startup()); diff --git a/core/frontend/src/test/render/webgl/RenderMemory.test.ts b/core/frontend/src/test/render/webgl/RenderMemory.test.ts index 9753999d0117..3ee13af50c85 100644 --- a/core/frontend/src/test/render/webgl/RenderMemory.test.ts +++ b/core/frontend/src/test/render/webgl/RenderMemory.test.ts @@ -2,19 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { + ColorDef, + ColorIndex, + EmptyLocalization, + FeatureIndex, + FillFlags, + ImageBuffer, + ImageBufferFormat, + MeshEdge, + QParams3d, + QPoint3dList, + RenderTexture, + TextureTransparency, +} from "@itwin/core-common"; import { Point2d, Point3d, Range3d } from "@itwin/core-geometry"; -import { ColorDef, ColorIndex, EmptyLocalization, FeatureIndex, FillFlags, ImageBuffer, ImageBufferFormat, MeshEdge, QParams3d, QPoint3dList, RenderTexture, TextureTransparency } from "@itwin/core-common"; +import { expect } from "chai"; +import { MeshArgsEdges } from "../../../common/internal/render/MeshPrimitives"; +import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; +import { InstancedGraphicParams, MeshArgs } from "../../../core-frontend"; import { IModelApp } from "../../../IModelApp"; import { IModelConnection } from "../../../IModelConnection"; -import { RenderMemory } from "../../../render/RenderMemory"; +import { RenderGeometry } from "../../../internal/render/RenderGeometry"; import { RenderGraphic } from "../../../render/RenderGraphic"; -import { MeshArgsEdges } from "../../../common/internal/render/MeshPrimitives"; -import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; +import { RenderMemory } from "../../../render/RenderMemory"; import { Texture } from "../../../render/webgl/Texture"; import { createBlankConnection } from "../../createBlankConnection"; -import { InstancedGraphicParams, MeshArgs } from "../../../core-frontend"; -import { RenderGeometry } from "../../../internal/render/RenderGeometry"; function expectMemory(consumer: RenderMemory.Consumers, total: number, max: number, count: number) { expect(consumer.totalBytes).to.equal(total); @@ -30,11 +43,11 @@ function createMeshGeometry(opts?: { texture?: RenderTexture, includeEdges?: boo if (opts?.texture) { textureMapping = { texture: opts.texture, - uvParams: [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ], + uvParams: [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0)], }; } - const points = [ new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0) ]; + const points = [new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0)]; const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); for (const point of points) qpoints.add(point); diff --git a/core/frontend/src/test/render/webgl/RenderState.test.ts b/core/frontend/src/test/render/webgl/RenderState.test.ts index 58a820ad2103..475f1e31a202 100644 --- a/core/frontend/src/test/render/webgl/RenderState.test.ts +++ b/core/frontend/src/test/render/webgl/RenderState.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { assert, expect } from "chai"; import { IModelApp } from "../../../IModelApp"; import { GL } from "../../../render/webgl/GL"; import { RenderState } from "../../../render/webgl/RenderState"; import { System } from "../../../render/webgl/System"; -import { EmptyLocalization } from "@itwin/core-common"; function withinTolerance(x: number, y: number): boolean { const tol: number = 0.1e-6; @@ -281,7 +281,6 @@ describe("RenderState", () => { [GL.Capability.StencilBackOpFail, rs.stencil.backOperation.fail], [GL.Capability.StencilBackOpZFail, rs.stencil.backOperation.zFail], [GL.Capability.StencilBackOpZPass, rs.stencil.backOperation.zPass], - // The WebGL spec states these are 32-bit unsigned integers and initially all bits are set. // Chrome or ANGLE appears to have a bug that always leaves the high bit unset, even if you explicitly // call e.g., stencilMask(0xffffffff). @@ -369,7 +368,10 @@ describe("RenderState", () => { prevState.copyFrom(newState); newState.blend.equationRgb = GL.BlendEquation.ReverseSubtract; newState.apply(prevState); - assert.isTrue(gl.getParameter(GL.Capability.BlendEquationRGB) === GL.BlendEquation.ReverseSubtract, "blend.equationRgb should now be ReverseSubtract"); + assert.isTrue( + gl.getParameter(GL.Capability.BlendEquationRGB) === GL.BlendEquation.ReverseSubtract, + "blend.equationRgb should now be ReverseSubtract", + ); prevState.copyFrom(newState); newState.blend.equationAlpha = GL.BlendEquation.Subtract; @@ -379,21 +381,33 @@ describe("RenderState", () => { prevState.copyFrom(newState); newState.blend.functionSourceRgb = GL.BlendFactor.OneMinusSrcColor; newState.apply(prevState); - assert.isTrue(gl.getParameter(GL.Capability.BlendSrcRgb) === GL.BlendFactor.OneMinusSrcColor, "blend.functionSourceRgb should now be OneMinusSrcColor"); + assert.isTrue( + gl.getParameter(GL.Capability.BlendSrcRgb) === GL.BlendFactor.OneMinusSrcColor, + "blend.functionSourceRgb should now be OneMinusSrcColor", + ); prevState.copyFrom(newState); newState.blend.functionSourceAlpha = GL.BlendFactor.OneMinusSrcAlpha; newState.apply(prevState); - assert.isTrue(gl.getParameter(GL.Capability.BlendSrcAlpha) === GL.BlendFactor.OneMinusSrcAlpha, "blend.functionSourceAlpha should now be OneMinusSrcAlpha"); + assert.isTrue( + gl.getParameter(GL.Capability.BlendSrcAlpha) === GL.BlendFactor.OneMinusSrcAlpha, + "blend.functionSourceAlpha should now be OneMinusSrcAlpha", + ); prevState.copyFrom(newState); newState.blend.functionDestRgb = GL.BlendFactor.OneMinusDstColor; newState.apply(prevState); - assert.isTrue(gl.getParameter(GL.Capability.BlendDstRgb) === GL.BlendFactor.OneMinusDstColor, "blend.functionDestRgb should now be OneMinusDstColor"); + assert.isTrue( + gl.getParameter(GL.Capability.BlendDstRgb) === GL.BlendFactor.OneMinusDstColor, + "blend.functionDestRgb should now be OneMinusDstColor", + ); prevState.copyFrom(newState); newState.blend.functionDestAlpha = GL.BlendFactor.OneMinusDstAlpha; newState.apply(prevState); - assert.isTrue(gl.getParameter(GL.Capability.BlendDstAlpha) === GL.BlendFactor.OneMinusDstAlpha, "blend.functionDestAlpha should now be OneMinusDstAlpha"); + assert.isTrue( + gl.getParameter(GL.Capability.BlendDstAlpha) === GL.BlendFactor.OneMinusDstAlpha, + "blend.functionDestAlpha should now be OneMinusDstAlpha", + ); }); }); diff --git a/core/frontend/src/test/render/webgl/ScreenSpaceEffectBuilder.test.ts b/core/frontend/src/test/render/webgl/ScreenSpaceEffectBuilder.test.ts index e9b391d48cd5..b2deb0940524 100644 --- a/core/frontend/src/test/render/webgl/ScreenSpaceEffectBuilder.test.ts +++ b/core/frontend/src/test/render/webgl/ScreenSpaceEffectBuilder.test.ts @@ -6,9 +6,7 @@ import { EmptyLocalization } from "@itwin/core-common"; import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; -import { - ScreenSpaceEffectBuilder, ScreenSpaceEffectBuilderParams, UniformType, VaryingType, -} from "../../../render/ScreenSpaceEffectBuilder"; +import { ScreenSpaceEffectBuilder, ScreenSpaceEffectBuilderParams, UniformType, VaryingType } from "../../../render/ScreenSpaceEffectBuilder"; import { System } from "../../../render/webgl/System"; describe("ScreenSpaceEffectBuilder", () => { diff --git a/core/frontend/src/test/render/webgl/ShaderBuilder.test.ts b/core/frontend/src/test/render/webgl/ShaderBuilder.test.ts index 0a172c3c4022..35fa73823677 100644 --- a/core/frontend/src/test/render/webgl/ShaderBuilder.test.ts +++ b/core/frontend/src/test/render/webgl/ShaderBuilder.test.ts @@ -3,13 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { EmptyLocalization } from "@itwin/core-common"; import { assert, expect } from "chai"; import { IModelApp } from "../../../IModelApp"; +import { ShaderVariable, ShaderVariables, VariablePrecision, VariableScope, VariableType } from "../../../render/webgl/ShaderBuilder"; import { ShaderProgram } from "../../../render/webgl/ShaderProgram"; -import { - ShaderVariable, ShaderVariables, VariablePrecision, VariableScope, VariableType, -} from "../../../render/webgl/ShaderBuilder"; -import { EmptyLocalization } from "@itwin/core-common"; describe("ShaderBuilder", () => { before(async () => IModelApp.startup({ localization: new EmptyLocalization() })); diff --git a/core/frontend/src/test/render/webgl/SkyRender.test.ts b/core/frontend/src/test/render/webgl/SkyRender.test.ts index 20f4e9640418..81fa6631c84b 100644 --- a/core/frontend/src/test/render/webgl/SkyRender.test.ts +++ b/core/frontend/src/test/render/webgl/SkyRender.test.ts @@ -2,18 +2,27 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ColorDef, EmptyLocalization, Environment, EnvironmentProps, ImageSource, ImageSourceFormat, RenderTexture, SkyBoxImageType } from "@itwin/core-common"; -import { IModelConnection } from "../../../IModelConnection"; -import { ScreenViewport } from "../../../Viewport"; +import { BeDuration } from "@itwin/core-bentley"; +import { + ColorDef, + EmptyLocalization, + Environment, + EnvironmentProps, + ImageSource, + ImageSourceFormat, + RenderTexture, + SkyBoxImageType, +} from "@itwin/core-common"; +import { expect } from "chai"; +import { imageElementFromImageSource } from "../../../common/ImageUtil"; +import { EnvironmentDecorations } from "../../../EnvironmentDecorations"; import { IModelApp } from "../../../IModelApp"; +import { IModelConnection } from "../../../IModelConnection"; import { SpatialViewState } from "../../../SpatialViewState"; +import { ScreenViewport } from "../../../Viewport"; +import { Texture2DHandle, TextureCubeHandle } from "../../../webgl"; import { createBlankConnection } from "../../createBlankConnection"; import { expectColors, expectNotTheseColors } from "../../ExpectColors"; -import { BeDuration } from "@itwin/core-bentley"; -import { EnvironmentDecorations } from "../../../EnvironmentDecorations"; -import { imageElementFromImageSource } from "../../../common/ImageUtil"; -import { expect } from "chai"; -import { Texture2DHandle, TextureCubeHandle } from "../../../webgl"; describe("Sky rendering", () => { let iModel: IModelConnection; @@ -24,7 +33,7 @@ describe("Sky rendering", () => { document.body.appendChild(div); function createView(env?: EnvironmentProps): SpatialViewState { - const view = SpatialViewState.createBlank(iModel, {x: 0, y: 0, z: 0}, {x: 1, y: 1, z: 1}); + const view = SpatialViewState.createBlank(iModel, { x: 0, y: 0, z: 0 }, { x: 1, y: 1, z: 1 }); if (env) view.displayStyle.environment = Environment.fromJSON(env); @@ -32,9 +41,15 @@ describe("Sky rendering", () => { } class Decorations extends EnvironmentDecorations { - public get sky() { return this._sky; } - public get ground() { return this._ground; } - public get environment() { return this._environment; } + public get sky() { + return this._sky; + } + public get ground() { + return this._ground; + } + public get environment() { + return this._environment; + } public constructor(view?: SpatialViewState, onLoad?: () => void, onDispose?: () => void) { super(view ?? createView(), onLoad ?? (() => undefined), onDispose ?? (() => undefined)); @@ -62,7 +77,127 @@ describe("Sky rendering", () => { await IModelApp.startup({ localization: new EmptyLocalization() }); // 1x1 red png image - const redPngData = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 1, 0, 0, 0, 1, 8, 2, 0, 0, 0, 144, 119, 83, 222, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 12, 73, 68, 65, 84, 24, 87, 99, 248, 207, 192, 0, 0, 3, 1, 1, 0, 99, 36, 85, 211, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]); + const redPngData = new Uint8Array([ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 8, + 2, + 0, + 0, + 0, + 144, + 119, + 83, + 222, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 12, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 207, + 192, + 0, + 0, + 3, + 1, + 1, + 0, + 99, + 36, + 85, + 211, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]); const textureImage = { image: await imageElementFromImageSource(new ImageSource(redPngData, ImageSourceFormat.Png)), @@ -111,9 +246,12 @@ describe("Sky rendering", () => { image: { type: SkyBoxImageType.Cube, textures: { - front: "0x1", back: "0x2", - left: "0x3", right: "0x4", - top: "0x5", bottom: "0x6", + front: "0x1", + back: "0x2", + left: "0x3", + right: "0x4", + top: "0x5", + bottom: "0x6", }, }, }, diff --git a/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts b/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts index 41f1560767ce..60b80a8e2e5f 100644 --- a/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts +++ b/core/frontend/src/test/render/webgl/SurfaceTransparency.test.ts @@ -2,31 +2,44 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Point2d, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { - ColorDef, ColorIndex, EmptyLocalization, FeatureIndex, FillFlags, ImageBuffer, ImageBufferFormat, QParams3d, QPoint3dList, RenderMaterial, RenderMode, RenderTexture, TextureMapping, TextureTransparency, + ColorDef, + ColorIndex, + EmptyLocalization, + FeatureIndex, + FillFlags, + ImageBuffer, + ImageBufferFormat, + QParams3d, + QPoint3dList, + RenderMaterial, + RenderMode, + RenderTexture, + TextureMapping, + TextureTransparency, } from "@itwin/core-common"; -import { RenderGraphic } from "../../../render/RenderGraphic"; -import { createRenderPlanFromViewport } from "../../../render/RenderPlan"; +import { Point2d, Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; import { IModelApp } from "../../../IModelApp"; import { IModelConnection } from "../../../IModelConnection"; -import { SpatialViewState } from "../../../SpatialViewState"; -import { ScreenViewport } from "../../../Viewport"; -import { Target } from "../../../render/webgl/Target"; +import { MeshArgs } from "../../../render/MeshArgs"; +import { RenderGraphic } from "../../../render/RenderGraphic"; +import { createRenderPlanFromViewport } from "../../../render/RenderPlan"; +import { MeshGraphic } from "../../../render/webgl/Mesh"; import { Primitive } from "../../../render/webgl/Primitive"; import { Pass, RenderPass, SinglePass } from "../../../render/webgl/RenderFlags"; -import { MeshGraphic } from "../../../render/webgl/Mesh"; import { SurfaceGeometry } from "../../../render/webgl/SurfaceGeometry"; +import { Target } from "../../../render/webgl/Target"; +import { SpatialViewState } from "../../../SpatialViewState"; +import { ScreenViewport } from "../../../Viewport"; import { createBlankConnection } from "../../createBlankConnection"; -import { createMeshParams } from "../../../common/internal/render/VertexTableBuilder"; -import { MeshArgs } from "../../../render/MeshArgs"; function createMesh(transparency: number, mat?: RenderMaterial | RenderTexture): RenderGraphic { const colors = new ColorIndex(); colors.initUniform(ColorDef.from(255, 0, 0, transparency)); - const points = [ new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0) ]; + const points = [new Point3d(0, 0, 0), new Point3d(1, 0, 0), new Point3d(0, 1, 0), new Point3d(1, 1, 0)]; const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createXYZXYZ(0, 0, 0, 1, 1, 1))); for (const point of points) qpoints.add(point); @@ -49,7 +62,7 @@ function createMesh(transparency: number, mat?: RenderMaterial | RenderTexture): } if (texture) - args.textureMapping = { texture, uvParams: [ new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0) ] }; + args.textureMapping = { texture, uvParams: [new Point2d(0, 1), new Point2d(1, 1), new Point2d(0, 0), new Point2d(1, 0)] }; const params = createMeshParams(args, IModelApp.renderSystem.maxTextureSize, "non-indexed" !== IModelApp.tileAdmin.edgeOptions.type); return IModelApp.renderSystem.createMesh(params)!; diff --git a/core/frontend/src/test/render/webgl/SyncToken.test.ts b/core/frontend/src/test/render/webgl/SyncToken.test.ts index b312d14b22d8..80e395a3539f 100644 --- a/core/frontend/src/test/render/webgl/SyncToken.test.ts +++ b/core/frontend/src/test/render/webgl/SyncToken.test.ts @@ -8,7 +8,7 @@ import { desync, isSynchronized, sync, SyncObserver } from "../../../render/webg describe("SyncObserver", () => { it("should synchronize with Sync", () => { const target = { syncKey: 0 }; - const observer: SyncObserver = { }; + const observer: SyncObserver = {}; expect(isSynchronized(target, observer)).to.be.false; expect(sync(target, observer)).to.be.false; diff --git a/core/frontend/src/test/render/webgl/System.test.ts b/core/frontend/src/test/render/webgl/System.test.ts index 2a0c3ed0c690..2b222cb67544 100644 --- a/core/frontend/src/test/render/webgl/System.test.ts +++ b/core/frontend/src/test/render/webgl/System.test.ts @@ -2,20 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { EmptyLocalization, - Gradient, ImageSource, ImageSourceFormat, RenderTexture, RgbColorProps, TextureMapping, TextureTransparency, + Gradient, + ImageSource, + ImageSourceFormat, + RenderTexture, + RgbColorProps, + TextureMapping, + TextureTransparency, } from "@itwin/core-common"; import { Capabilities } from "@itwin/webgl-compatibility"; +import { expect } from "chai"; import { IModelApp } from "../../../IModelApp"; -import { CreateRenderMaterialArgs } from "../../../render/CreateRenderMaterialArgs"; import { IModelConnection } from "../../../IModelConnection"; +import { CreateRenderMaterialArgs } from "../../../render/CreateRenderMaterialArgs"; import { MockRender } from "../../../render/MockRender"; -import { Material } from "../../../render/webgl/Material"; import { RenderSystem } from "../../../render/RenderSystem"; -import { TileAdmin } from "../../../tile/internal"; +import { Material } from "../../../render/webgl/Material"; import { System } from "../../../render/webgl/System"; +import { TileAdmin } from "../../../tile/internal"; import { createBlankConnection } from "../../createBlankConnection"; import { unpackAndNormalizeMaterialParam } from "./Material.test"; @@ -118,7 +124,12 @@ describe("System", () => { const defaultSys = System.create(); expectAttributes(defaultSys, { antialias: true, premultipliedAlpha: true, preserveDrawingBuffer: false, powerPreference: "high-performance" }); - const sys1Attrs: WebGLContextAttributes = { antialias: false, premultipliedAlpha: false, preserveDrawingBuffer: true, powerPreference: "low-power" }; + const sys1Attrs: WebGLContextAttributes = { + antialias: false, + premultipliedAlpha: false, + preserveDrawingBuffer: true, + powerPreference: "low-power", + }; const sys1 = System.create({ contextAttributes: sys1Attrs }); expectAttributes(sys1, sys1Attrs); @@ -156,12 +167,142 @@ describe("System", () => { // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. - const imageSource = new ImageSource(new Uint8Array([ - 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, - 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, - 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, - 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130, - ]), ImageSourceFormat.Png); + const imageSource = new ImageSource( + new Uint8Array([ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, + ]), + ImageSourceFormat.Png, + ); before(async () => { await IModelApp.startup({ @@ -181,7 +322,7 @@ describe("System", () => { function requestThematicGradient(stepCount: number) { const symb = Gradient.Symb.fromJSON({ mode: Gradient.Mode.Thematic, - thematicSettings: {stepCount}, + thematicSettings: { stepCount }, keys: [{ value: 0.6804815398789292, color: 610 }, { value: 0.731472008309797, color: 229 }], }); return IModelApp.renderSystem.getGradientTexture(symb, imodel); @@ -451,7 +592,7 @@ describe("System", () => { expect(actual).to.deep.equal(expected); }; - test({ }, defaults); + test({}, defaults); test(defaults); const color = { r: 1, g: 127, b: 255 }; diff --git a/core/frontend/src/test/render/webgl/Technique.test.ts b/core/frontend/src/test/render/webgl/Technique.test.ts index 43b787a8a56e..6a2f7245c3a5 100644 --- a/core/frontend/src/test/render/webgl/Technique.test.ts +++ b/core/frontend/src/test/render/webgl/Technique.test.ts @@ -2,20 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger, LogLevel } from "@itwin/core-bentley"; +import { EmptyLocalization } from "@itwin/core-common"; import { assert, expect } from "chai"; import { IModelApp } from "../../../IModelApp"; import { AttributeMap } from "../../../render/webgl/AttributeMap"; -import { CompileStatus } from "../../../render/webgl/ShaderProgram"; +import { ViewportQuadGeometry } from "../../../render/webgl/CachedGeometry"; import { DrawParams, ShaderProgramParams } from "../../../render/webgl/DrawCommand"; -import { FeatureMode, TechniqueFlags } from "../../../render/webgl/TechniqueFlags"; import { FragmentShaderComponent, ProgramBuilder, VariableType, VertexShaderComponent } from "../../../render/webgl/ShaderBuilder"; -import { SingularTechnique, Techniques } from "../../../render/webgl/Technique"; +import { CompileStatus } from "../../../render/webgl/ShaderProgram"; import { System } from "../../../render/webgl/System"; import { Target } from "../../../render/webgl/Target"; +import { SingularTechnique, Techniques } from "../../../render/webgl/Technique"; +import { FeatureMode, TechniqueFlags } from "../../../render/webgl/TechniqueFlags"; import { TechniqueId } from "../../../render/webgl/TechniqueId"; -import { ViewportQuadGeometry } from "../../../render/webgl/CachedGeometry"; -import { Logger, LogLevel } from "@itwin/core-bentley"; -import { EmptyLocalization } from "@itwin/core-common"; function createPurpleQuadBuilder(): ProgramBuilder { const builder = new ProgramBuilder(AttributeMap.findAttributeMap(undefined, false)); @@ -166,7 +166,7 @@ describe("Techniques", () => { let numBuilt = 0; let maxNumVaryings = 0; - ProgramBuilder.prototype.buildProgram = function (gl) { + ProgramBuilder.prototype.buildProgram = function(gl) { ++numBuilt; const numVaryings = this.vert.computeNumVaryingVectors(this.frag.buildSource()); expect(numVaryings).most(minGuaranteed); diff --git a/core/frontend/src/test/render/webgl/Texture.test.ts b/core/frontend/src/test/render/webgl/Texture.test.ts index 01c5d8244b22..ea9be6c9fd8a 100644 --- a/core/frontend/src/test/render/webgl/Texture.test.ts +++ b/core/frontend/src/test/render/webgl/Texture.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { assert as bAssert } from "@itwin/core-bentley"; import { EmptyLocalization, ImageBuffer, ImageBufferFormat, ImageSource, ImageSourceFormat, RenderTexture } from "@itwin/core-common"; +import { assert, expect } from "chai"; import { extractImageSourceDimensions, imageBufferToPngDataUrl, imageElementFromImageSource, imageElementFromUrl } from "../../../common/ImageUtil"; import { IModelApp } from "../../../IModelApp"; import { GL } from "../../../render/webgl/GL"; @@ -13,14 +13,168 @@ import { TextureHandle } from "../../../render/webgl/Texture"; // This is an encoded png containing a 3x3 square with white in top left pixel, blue in middle pixel, and green in // bottom right pixel. The rest of the square is red. -const pngData: Uint8Array = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0, 3, 0, 0, 0, 3, 8, 2, 0, 0, 0, 217, 74, 34, 232, 0, 0, 0, 1, 115, 82, 71, 66, 0, 174, 206, 28, 233, 0, 0, 0, 4, 103, 65, 77, 65, 0, 0, 177, 143, 11, 252, 97, 5, 0, 0, 0, 9, 112, 72, 89, 115, 0, 0, 14, 195, 0, 0, 14, 195, 1, 199, 111, 168, 100, 0, 0, 0, 24, 73, 68, 65, 84, 24, 87, 99, 248, 15, 4, 12, 12, 64, 4, 198, 64, 46, 132, 5, 162, 254, 51, 0, 0, 195, 90, 10, 246, 127, 175, 154, 145, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66, 96, 130]); +const pngData: Uint8Array = new Uint8Array([ + 137, + 80, + 78, + 71, + 13, + 10, + 26, + 10, + 0, + 0, + 0, + 13, + 73, + 72, + 68, + 82, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 3, + 8, + 2, + 0, + 0, + 0, + 217, + 74, + 34, + 232, + 0, + 0, + 0, + 1, + 115, + 82, + 71, + 66, + 0, + 174, + 206, + 28, + 233, + 0, + 0, + 0, + 4, + 103, + 65, + 77, + 65, + 0, + 0, + 177, + 143, + 11, + 252, + 97, + 5, + 0, + 0, + 0, + 9, + 112, + 72, + 89, + 115, + 0, + 0, + 14, + 195, + 0, + 0, + 14, + 195, + 1, + 199, + 111, + 168, + 100, + 0, + 0, + 0, + 24, + 73, + 68, + 65, + 84, + 24, + 87, + 99, + 248, + 15, + 4, + 12, + 12, + 64, + 4, + 198, + 64, + 46, + 132, + 5, + 162, + 254, + 51, + 0, + 0, + 195, + 90, + 10, + 246, + 127, + 175, + 154, + 145, + 0, + 0, + 0, + 0, + 73, + 69, + 78, + 68, + 174, + 66, + 96, + 130, +]); // This is a 4x2 RGB bitmap: // red green blue white // yellow cyan purple black const bitmapData = new Uint8Array([ - 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, ]); describe("Texture tests", () => { @@ -46,7 +200,12 @@ describe("Texture tests", () => { return; } - const texture: TextureHandle | undefined = TextureHandle.createForAttachment(1, 1, GL.Texture.Format.DepthComponent, GL.Texture.DataType.UnsignedInt); + const texture: TextureHandle | undefined = TextureHandle.createForAttachment( + 1, + 1, + GL.Texture.Format.DepthComponent, + GL.Texture.DataType.UnsignedInt, + ); assert(undefined !== texture); if (undefined === texture) { return; @@ -158,36 +317,110 @@ describe("ImageUtil", () => { const alphaBuffer = ImageBuffer.create(alphaBitmap, ImageBufferFormat.Alpha, 3); const expectedPixels = [ - 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x20, 0x20, 0x20, 0x20, - 0xdf, 0xdf, 0xdf, 0xdf, 0xef, 0xef, 0xef, 0xef, 0xff, 0xff, 0xff, 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, + 0x10, + 0x10, + 0x10, + 0x20, + 0x20, + 0x20, + 0x20, + 0xdf, + 0xdf, + 0xdf, + 0xdf, + 0xef, + 0xef, + 0xef, + 0xef, + 0xff, + 0xff, + 0xff, + 0xff, ]; await testImageBufferUrl(alphaBuffer, expectedPixels); }); it("should produce a data URL from an rgb ImageBuffer", async () => { const rgbBitmap = new Uint8Array([ - 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0xff, 0x7f, 0x7f, 0x7f, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0xff, + 0x7f, + 0x7f, + 0x7f, ]); const rgbBuffer = ImageBuffer.create(rgbBitmap, ImageBufferFormat.Rgb, 2); const expectedPixels = [ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x7f, 0x7f, 0x7f, 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0xff, + 0xff, + 0x7f, + 0x7f, + 0x7f, + 0xff, ]; await testImageBufferUrl(rgbBuffer, expectedPixels); }); it("should produce a data URL from an rgba ImageBuffer", async () => { const rgbaBitmap = [ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xdf, 0xef, 0xef, 0xef, 0xef, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xdf, + 0xef, + 0xef, + 0xef, + 0xef, ]; const rgbaBuffer = ImageBuffer.create(new Uint8Array(rgbaBitmap), ImageBufferFormat.Rgba, 2); const rgbaResult = [ - 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, // NB: premultiplied alpha: 0xff*0x00 => 0x00 - 0x00, 0x00, 0xff, 0xdf, 0xef, 0xef, 0xef, 0xef, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, // NB: premultiplied alpha: 0xff*0x00 => 0x00 + 0x00, + 0x00, + 0xff, + 0xdf, + 0xef, + 0xef, + 0xef, + 0xef, ]; await testImageBufferUrl(rgbaBuffer, rgbaResult); }); diff --git a/core/frontend/src/test/tile/GltfReader.test.ts b/core/frontend/src/test/tile/GltfReader.test.ts index b3b680069126..c4d6c640e411 100644 --- a/core/frontend/src/test/tile/GltfReader.test.ts +++ b/core/frontend/src/test/tile/GltfReader.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Range3d } from "@itwin/core-geometry"; import { EmptyLocalization, GltfV2ChunkTypes, GltfVersions, RenderTexture, TileFormat } from "@itwin/core-common"; -import { IModelConnection } from "../../IModelConnection"; -import { IModelApp } from "../../IModelApp"; +import { Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { GltfDocument, GltfId, GltfNode, GltfSampler, GltfWrapMode } from "../../common/gltf/GltfSchema"; +import { BatchedTileIdMap } from "../../core-frontend"; +import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; import { GltfGraphicsReader, GltfReaderProps } from "../../tile/GltfReader"; import { createBlankConnection } from "../createBlankConnection"; -import { BatchedTileIdMap } from "../../core-frontend"; const minimalBin = new Uint8Array([12, 34, 0xfe, 0xdc]); const minimalJson = { asset: { version: "02.00" }, meshes: [] }; @@ -144,11 +144,14 @@ describe("GltfReader", () => { it("rejects glb with multiple binary chunks", () => { const glb = glbFromChunks([{ - data: jsonToBytes(minimalJson), type: GltfV2ChunkTypes.JSON, + data: jsonToBytes(minimalJson), + type: GltfV2ChunkTypes.JSON, }, { - data: minimalBin, type: GltfV2ChunkTypes.Binary, + data: minimalBin, + type: GltfV2ChunkTypes.Binary, }, { - data: minimalBin, type: GltfV2ChunkTypes.Binary, + data: minimalBin, + type: GltfV2ChunkTypes.Binary, }]); expect(createReader(glb)).to.be.undefined; @@ -156,9 +159,11 @@ describe("GltfReader", () => { it("ignores unrecognized chunks", () => { const chunks = [{ - data: jsonToBytes(minimalJson), type: GltfV2ChunkTypes.JSON, + data: jsonToBytes(minimalJson), + type: GltfV2ChunkTypes.JSON, }, { - data: minimalBin, type: GltfV2ChunkTypes.Binary, + data: minimalBin, + type: GltfV2ChunkTypes.Binary, }]; chunks.push({ data: minimalBin, type: 0xdeadbeef as GltfV2ChunkTypes }); @@ -170,9 +175,11 @@ describe("GltfReader", () => { it("rejects glb with out-of-order chunks", () => { const glb = glbFromChunks([{ - data: minimalBin, type: GltfV2ChunkTypes.Binary, + data: minimalBin, + type: GltfV2ChunkTypes.Binary, }, { - data: jsonToBytes(minimalJson), type: GltfV2ChunkTypes.JSON, + data: jsonToBytes(minimalJson), + type: GltfV2ChunkTypes.JSON, }]); expect(createReader(glb)).to.be.undefined; @@ -183,15 +190,15 @@ describe("GltfReader", () => { ...minimalJson, meshes: [] as any, nodes: [ - { }, // 0 + {}, // 0 { children: [2] }, // 1 { children: [4, 5] }, // 2 - { }, // 3 - { }, // 4 - { }, // 5 + {}, // 3 + {}, // 4 + {}, // 5 ] as any, scenes: [ - { }, // 0 + {}, // 0 { nodes: [] }, // 1 { nodes: [0] }, // 2 { nodes: [2, 3] }, // 3 @@ -227,16 +234,16 @@ describe("GltfReader", () => { ...minimalJson, meshes: [] as any, nodes: [ - { }, // 0 + {}, // 0 { children: [2] }, // 1 { children: [4, 5] }, // 2 { children: [0] }, // 3 { children: [9, 8, 7, 6] }, // 4 - { }, // 5 - { }, // 6 + {}, // 5 + {}, // 6 ] as any, scenes: [ - { }, // 0 + {}, // 0 { nodes: [] }, // 1 { nodes: [0] }, // 2 { nodes: [1] }, // 3 @@ -286,7 +293,7 @@ describe("GltfReader", () => { 0: { children: ["0"] }, 1: { children: ["1"] }, 2: { children: ["2"] }, - 3: { }, + 3: {}, }, scenes: { 0: { nodes: ["0"] }, @@ -301,7 +308,7 @@ describe("GltfReader", () => { const reader = createReader(makeGlb(json, minimalBin))!; expect(reader).not.to.be.undefined; expect(() => { - for (const _ of reader.traverseScene()) { } + for (const _ of reader.traverseScene()) {} }).to.throw("Cycle detected while traversing glTF nodes"); } @@ -397,7 +404,7 @@ describe("GltfReader", () => { // This test includes a current deviation from the glTF spec: we currently do not support mirrored repeat. it("produces normal textures unless clamp-to-edge is specified", () => { expectTextureType(RenderTexture.Type.Normal, undefined); - expectTextureType(RenderTexture.Type.Normal, { }); + expectTextureType(RenderTexture.Type.Normal, {}); expectTextureType(RenderTexture.Type.Normal, { magFilter: 9728, minFilter: 9987 }); expectTextureType(RenderTexture.Type.Normal, { wrapS: GltfWrapMode.Repeat }); @@ -420,7 +427,7 @@ describe("GltfReader", () => { it("overrides default texture type if unspecified by sampler", () => { expectTextureType(RenderTexture.Type.TileSection, undefined, GltfWrapMode.ClampToEdge); - expectTextureType(RenderTexture.Type.TileSection, { }, GltfWrapMode.ClampToEdge); + expectTextureType(RenderTexture.Type.TileSection, {}, GltfWrapMode.ClampToEdge); expectTextureType(RenderTexture.Type.TileSection, { magFilter: 9728, minFilter: 9987 }, GltfWrapMode.ClampToEdge); expectTextureType(RenderTexture.Type.Normal, { wrapS: GltfWrapMode.Repeat }, GltfWrapMode.ClampToEdge); @@ -429,13 +436,25 @@ describe("GltfReader", () => { expectTextureType(RenderTexture.Type.Normal, { wrapS: GltfWrapMode.MirroredRepeat }, GltfWrapMode.ClampToEdge); expectTextureType(RenderTexture.Type.Normal, { wrapT: GltfWrapMode.MirroredRepeat }, GltfWrapMode.ClampToEdge); - expectTextureType(RenderTexture.Type.Normal, { wrapS: GltfWrapMode.MirroredRepeat, wrapT: GltfWrapMode.MirroredRepeat }, GltfWrapMode.ClampToEdge); + expectTextureType( + RenderTexture.Type.Normal, + { wrapS: GltfWrapMode.MirroredRepeat, wrapT: GltfWrapMode.MirroredRepeat }, + GltfWrapMode.ClampToEdge, + ); expectTextureType(RenderTexture.Type.TileSection, { wrapS: GltfWrapMode.ClampToEdge }, GltfWrapMode.ClampToEdge); expectTextureType(RenderTexture.Type.TileSection, { wrapT: GltfWrapMode.ClampToEdge }, GltfWrapMode.ClampToEdge); - expectTextureType(RenderTexture.Type.TileSection, { wrapS: GltfWrapMode.ClampToEdge, wrapT: GltfWrapMode.ClampToEdge }, GltfWrapMode.ClampToEdge); + expectTextureType( + RenderTexture.Type.TileSection, + { wrapS: GltfWrapMode.ClampToEdge, wrapT: GltfWrapMode.ClampToEdge }, + GltfWrapMode.ClampToEdge, + ); expectTextureType(RenderTexture.Type.TileSection, { wrapS: GltfWrapMode.Repeat, wrapT: GltfWrapMode.ClampToEdge }, GltfWrapMode.ClampToEdge); - expectTextureType(RenderTexture.Type.TileSection, { wrapS: GltfWrapMode.ClampToEdge, wrapT: GltfWrapMode.MirroredRepeat }, GltfWrapMode.ClampToEdge); + expectTextureType( + RenderTexture.Type.TileSection, + { wrapS: GltfWrapMode.ClampToEdge, wrapT: GltfWrapMode.MirroredRepeat }, + GltfWrapMode.ClampToEdge, + ); }); }); @@ -894,12 +913,12 @@ describe("GltfReader", () => { const compareArrays = (a: any[], b: any[]) => { for (let i = 0; i < a.length; i++) { - if(Array.isArray(a[i])){ - if (!compareArrays(a[i], b[i])){ + if (Array.isArray(a[i])) { + if (!compareArrays(a[i], b[i])) { return false; } - } else{ - if (a[i] !== b[i]){ + } else { + if (a[i] !== b[i]) { return false; } } @@ -908,19 +927,33 @@ describe("GltfReader", () => { }; describe("EXT_structural_metadata", () => { - - const instanceFeatures = [2,1,3,0]; - const expectedValuesUnsigned = [1,2,3,undefined]; - const expectedValuesBigUnsigned = ["1","2","3",undefined]; - const expectedValuesSigned = [-1,-2,-3,undefined]; - const expectedValuesBigSigned = ["-1","-2","-3",undefined]; - const expectedValuesString = ["one","two","three",undefined]; - - const expectedValuesVec2 = [[1,2],[3,4],[5,6],[7,8]]; - const expectedValuesVec3 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]; - const expectedValuesVec4 = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]; - const expectedValuesMat3 = [[1,2,3,4,5,6,7,8,9],[10,11,12,13,14,15,16,17,18],[19,20,21,22,23,24,25,26,27],[28,29,30,31,32,33,34,35,36]]; - const expectedValuesMat4 = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],[17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32], [33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48], [49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64]]; + const instanceFeatures = [2, 1, 3, 0]; + const expectedValuesUnsigned = [1, 2, 3, undefined]; + const expectedValuesBigUnsigned = ["1", "2", "3", undefined]; + const expectedValuesSigned = [-1, -2, -3, undefined]; + const expectedValuesBigSigned = ["-1", "-2", "-3", undefined]; + const expectedValuesString = ["one", "two", "three", undefined]; + + const expectedValuesVec2 = [[1, 2], [3, 4], [5, 6], [7, 8]]; + const expectedValuesVec3 = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]; + const expectedValuesVec4 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]; + const expectedValuesMat3 = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [10, 11, 12, 13, 14, 15, 16, 17, 18], [19, 20, 21, 22, 23, 24, 25, 26, 27], [ + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + ]]; + const expectedValuesMat4 = [ + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], + [17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], + [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48], + [49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], + ]; it("parses structural metadata", async () => { const reader = createReader(instanceFeaturesExt)!; @@ -933,45 +966,45 @@ describe("GltfReader", () => { expect(structuralMetadata.tables.length === 2); expect(structuralMetadata.tables[0].entries.length === 11); - for(const entry of structuralMetadata.tables[0].entries ?? []) { - if(entry.name === "UINT8_VALUES") { + for (const entry of structuralMetadata.tables[0].entries ?? []) { + if (entry.name === "UINT8_VALUES") { expect(compareArrays(entry.values, expectedValuesUnsigned)).to.be.true; - } else if(entry.name === "UINT16_VALUES") { + } else if (entry.name === "UINT16_VALUES") { expect(compareArrays(entry.values, expectedValuesUnsigned)).to.be.true; - } else if(entry.name === "UINT32_VALUES") { + } else if (entry.name === "UINT32_VALUES") { expect(compareArrays(entry.values, expectedValuesUnsigned)).to.be.true; - } else if(entry.name === "UINT64_VALUES") { + } else if (entry.name === "UINT64_VALUES") { expect(compareArrays(entry.values, expectedValuesBigUnsigned)).to.be.true; - } else if(entry.name === "INT8_VALUES") { + } else if (entry.name === "INT8_VALUES") { expect(compareArrays(entry.values, expectedValuesSigned)).to.be.true; - } else if(entry.name === "INT16_VALUES") { + } else if (entry.name === "INT16_VALUES") { expect(compareArrays(entry.values, expectedValuesSigned)).to.be.true; - } else if(entry.name === "INT32_VALUES") { + } else if (entry.name === "INT32_VALUES") { expect(compareArrays(entry.values, expectedValuesSigned)).to.be.true; - } else if(entry.name === "INT64_VALUES") { + } else if (entry.name === "INT64_VALUES") { expect(compareArrays(entry.values, expectedValuesBigSigned)).to.be.true; - }else if(entry.name === "FLOAT32_VALUES") { + } else if (entry.name === "FLOAT32_VALUES") { expect(compareArrays(entry.values, expectedValuesUnsigned)).to.be.true; - } else if(entry.name === "FLOAT64_VALUES") { + } else if (entry.name === "FLOAT64_VALUES") { expect(compareArrays(entry.values, expectedValuesUnsigned)).to.be.true; - } else if(entry.name === "STRING_VALUES") { + } else if (entry.name === "STRING_VALUES") { expect(compareArrays(entry.values, expectedValuesString)).to.be.true; } } expect(structuralMetadata.tables[1].entries.length === 6); - for(const entry of structuralMetadata.tables[1].entries ?? []) { - if(entry.name === "UINT8_VEC2_VALUES") { + for (const entry of structuralMetadata.tables[1].entries ?? []) { + if (entry.name === "UINT8_VEC2_VALUES") { expect(compareArrays(entry.values, expectedValuesVec2)).to.be.true; - } else if(entry.name === "UINT8_VEC3_VALUES") { + } else if (entry.name === "UINT8_VEC3_VALUES") { expect(compareArrays(entry.values, expectedValuesVec3)).to.be.true; - } else if(entry.name === "UINT8_VEC4_VALUES") { + } else if (entry.name === "UINT8_VEC4_VALUES") { expect(compareArrays(entry.values, expectedValuesVec4)).to.be.true; - } else if(entry.name === "UINT8_MAT2_VALUES") { + } else if (entry.name === "UINT8_MAT2_VALUES") { expect(compareArrays(entry.values, expectedValuesVec4)).to.be.true; - } else if(entry.name === "UINT8_MAT3_VALUES") { + } else if (entry.name === "UINT8_MAT3_VALUES") { expect(compareArrays(entry.values, expectedValuesMat3)).to.be.true; - } else if(entry.name === "UINT8_MAT4_VALUES") { + } else if (entry.name === "UINT8_MAT4_VALUES") { expect(compareArrays(entry.values, expectedValuesMat4)).to.be.true; } } @@ -987,46 +1020,46 @@ describe("GltfReader", () => { expect(result).not.to.be.undefined; let entryCount = 0; - for(const entry of idMap.entries()) { + for (const entry of idMap.entries()) { expect(entry).not.to.be.undefined; // Expect empty property set for noData = 4 | -4 | "four" - if(entryCount === 3){ + if (entryCount === 3) { expect(JSON.stringify(entry.properties.propertySet0) === JSON.stringify({})).to.be.true; } else { let propertyCount0 = 0; - for(const [key, value] of Object.entries(entry.properties.propertySet0)){ - if(key === "UINT8_VALUES") { + for (const [key, value] of Object.entries(entry.properties.propertySet0)) { + if (key === "UINT8_VALUES") { expect(value === expectedValuesUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "UINT16_VALUES") { + } else if (key === "UINT16_VALUES") { expect(value === expectedValuesUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "UINT32_VALUES") { + } else if (key === "UINT32_VALUES") { expect(value === expectedValuesUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "UINT64_VALUES") { + } else if (key === "UINT64_VALUES") { expect(value === expectedValuesBigUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "INT8_VALUES") { + } else if (key === "INT8_VALUES") { expect(value === expectedValuesSigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "INT16_VALUES") { + } else if (key === "INT16_VALUES") { expect(value === expectedValuesSigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "INT32_VALUES") { + } else if (key === "INT32_VALUES") { expect(value === expectedValuesSigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "INT64_VALUES") { + } else if (key === "INT64_VALUES") { expect(value === expectedValuesBigSigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "FLOAT32_VALUES") { + } else if (key === "FLOAT32_VALUES") { expect(value === expectedValuesUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "FLOAT64_VALUES") { + } else if (key === "FLOAT64_VALUES") { expect(value === expectedValuesUnsigned[entryCount]).to.be.true; propertyCount0++; - } else if(key === "STRING_VALUES") { + } else if (key === "STRING_VALUES") { expect(value === expectedValuesString[entryCount]).to.be.true; propertyCount0++; } @@ -1035,36 +1068,36 @@ describe("GltfReader", () => { } // Expect empty property set for null feature id = 3 - if(instanceFeatures[entryCount] === 3){ + if (instanceFeatures[entryCount] === 3) { expect(JSON.stringify(entry.properties.propertySet1) === JSON.stringify({})).to.be.true; } else { let propertyCount1 = 0; - for(const [key, value] of Object.entries(entry.properties.propertySet1)){ + for (const [key, value] of Object.entries(entry.properties.propertySet1)) { const array = value as any[]; - if(key === "UINT8_VEC2_VALUES") { - expect(compareArrays(array, expectedValuesVec2[instanceFeatures[entryCount]] )).to.be.true; + if (key === "UINT8_VEC2_VALUES") { + expect(compareArrays(array, expectedValuesVec2[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; - } else if(key === "UINT8_VEC3_VALUES") { - expect(compareArrays(array, expectedValuesVec3[instanceFeatures[entryCount]] )).to.be.true; + } else if (key === "UINT8_VEC3_VALUES") { + expect(compareArrays(array, expectedValuesVec3[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; - } else if(key === "UINT8_VEC4_VALUES") { - expect(compareArrays(array, expectedValuesVec4[instanceFeatures[entryCount]] )).to.be.true; + } else if (key === "UINT8_VEC4_VALUES") { + expect(compareArrays(array, expectedValuesVec4[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; - } else if(key === "UINT8_MAT2_VALUES") { - expect(compareArrays(array, expectedValuesVec4[instanceFeatures[entryCount]] )).to.be.true; + } else if (key === "UINT8_MAT2_VALUES") { + expect(compareArrays(array, expectedValuesVec4[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; - } else if(key === "UINT8_MAT3_VALUES") { - expect(compareArrays(array, expectedValuesMat3[instanceFeatures[entryCount]] )).to.be.true; + } else if (key === "UINT8_MAT3_VALUES") { + expect(compareArrays(array, expectedValuesMat3[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; - }else if(key === "UINT8_MAT4_VALUES") { - expect(compareArrays(array, expectedValuesMat4[instanceFeatures[entryCount]] )).to.be.true; + } else if (key === "UINT8_MAT4_VALUES") { + expect(compareArrays(array, expectedValuesMat4[instanceFeatures[entryCount]])).to.be.true; propertyCount1++; } } expect(propertyCount1 === 6).to.be.true; } - entryCount ++; + entryCount++; } expect(entryCount === 4).to.be.true; }); diff --git a/core/frontend/src/test/tile/ImdlParser.test.ts b/core/frontend/src/test/tile/ImdlParser.test.ts index 793294d6a996..43950be246c8 100644 --- a/core/frontend/src/test/tile/ImdlParser.test.ts +++ b/core/frontend/src/test/tile/ImdlParser.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { RenderSchedule as RS, TileReadStatus } from "@itwin/core-common"; import { expect, use } from "chai"; import chaiAsPromised from "chai-as-promised"; -import { RenderSchedule as RS, TileReadStatus } from "@itwin/core-common"; import { ImdlTimeline } from "../../common/imdl/ParseImdlDocument"; -import { acquireImdlParser, ImdlParser } from "../../tile/internal"; import { IModelApp } from "../../IModelApp"; +import { acquireImdlParser, ImdlParser } from "../../tile/internal"; use(chaiAsPromised); @@ -165,100 +165,1886 @@ describe("ImdlParser", () => { it("successfully parses the document", async () => { const tileData = new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, - 0x41, 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x83, 0x68, 0x7c, 0x54, 0x31, 0x5d, 0x86, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x06, 0x00, 0x00, 0xd0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, - 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, - 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, - 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, - 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, - 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, - 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, - 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, - 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x36, 0x33, 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, - 0x31, 0x31, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x31, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, - 0x38, 0x30, 0x39, 0x32, 0x32, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, - 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, - 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, - 0x3a, 0x5b, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, - 0x2c, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, - 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, - 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, - 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, - 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, - 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, - 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x83, + 0x68, + 0x7c, + 0x54, + 0x31, + 0x5d, + 0x86, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x58, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0xe0, + 0x06, + 0x00, + 0x00, + 0xd0, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, ]); const parser = acquireImdlParser({}); diff --git a/core/frontend/src/test/tile/LRUTileList.test.ts b/core/frontend/src/test/tile/LRUTileList.test.ts index 22e3f563b9a7..44ffc3a616a8 100644 --- a/core/frontend/src/test/tile/LRUTileList.test.ts +++ b/core/frontend/src/test/tile/LRUTileList.test.ts @@ -14,10 +14,18 @@ function mockTile(bytesUsed: number): Tile { } class List extends LRUTileList { - public get sentinel() { return this._sentinel; } - public get head() { return this._head; } - public get tail() { return this._tail; } - public override get totalBytesUsed() { return this._totalBytesUsed; } + public get sentinel() { + return this._sentinel; + } + public get head() { + return this._head; + } + public get tail() { + return this._tail; + } + public override get totalBytesUsed() { + return this._totalBytesUsed; + } public expectOrder(...expected: LRUTileListNode[]): void { expect(this.head.previous).to.be.undefined; @@ -39,9 +47,15 @@ class List extends LRUTileList { expect(j).to.equal(0); } - public moveTileToEnd(tile: Tile) { this.moveToEnd(tile); } - public moveTileBeforeSentinel(tile: Tile) { this.moveBeforeSentinel(tile); } - public moveTileAfterSentinel(tile: Tile) { this.moveAfterSentinel(tile); } + public moveTileToEnd(tile: Tile) { + this.moveToEnd(tile); + } + public moveTileBeforeSentinel(tile: Tile) { + this.moveBeforeSentinel(tile); + } + public moveTileAfterSentinel(tile: Tile) { + this.moveAfterSentinel(tile); + } } function expectUnlinked(node: LRUTileListNode): void { diff --git a/core/frontend/src/test/tile/TileAdmin.test.ts b/core/frontend/src/test/tile/TileAdmin.test.ts index 940ebbafc727..1ecf603c72e9 100644 --- a/core/frontend/src/test/tile/TileAdmin.test.ts +++ b/core/frontend/src/test/tile/TileAdmin.test.ts @@ -2,19 +2,30 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; -import { IModelConnection } from "../../IModelConnection"; +import { expect } from "chai"; import { IModelApp } from "../../IModelApp"; -import { SpatialViewState } from "../../SpatialViewState"; -import { ScreenViewport, Viewport } from "../../Viewport"; +import { IModelConnection } from "../../IModelConnection"; import { MockRender } from "../../render/MockRender"; import { RenderGraphic } from "../../render/RenderGraphic"; import { RenderMemory } from "../../render/RenderMemory"; +import { SpatialViewState } from "../../SpatialViewState"; import { - GpuMemoryLimit, GpuMemoryLimits, Tile, TileAdmin, TileContent, TiledGraphicsProvider, TileDrawArgs, TileLoadPriority, TileRequest, TileTree, - TileTreeOwner, TileTreeReference, TileTreeSupplier, + GpuMemoryLimit, + GpuMemoryLimits, + Tile, + TileAdmin, + TileContent, + TiledGraphicsProvider, + TileDrawArgs, + TileLoadPriority, + TileRequest, + TileTree, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, } from "../../tile/internal"; +import { ScreenViewport, Viewport } from "../../Viewport"; import { createBlankConnection } from "../createBlankConnection"; describe("TileAdmin", () => { @@ -24,7 +35,12 @@ describe("TileAdmin", () => { expect(admin.maxTotalTileContentBytes).to.equal(maxBytes); } - function expectAdmin(isMobile: boolean, limits: GpuMemoryLimit | GpuMemoryLimits | undefined, expectedLimit: GpuMemoryLimit, expectedMaxBytes: number | undefined): TileAdmin { + function expectAdmin( + isMobile: boolean, + limits: GpuMemoryLimit | GpuMemoryLimits | undefined, + expectedLimit: GpuMemoryLimit, + expectedMaxBytes: number | undefined, + ): TileAdmin { const admin = new TileAdmin(isMobile, undefined, undefined !== limits ? { gpuMemoryLimits: limits } : undefined); expectLimits(admin, expectedLimit, expectedMaxBytes); return admin; @@ -106,7 +122,7 @@ describe("TileAdmin", () => { stats.addTexture(this._size); } - public unionRange() { } + public unionRange() {} } class TestTile extends Tile { @@ -176,10 +192,18 @@ describe("TileAdmin", () => { this._rootTile = new TestTile(this, contentSize, retainMemory); } - public get rootTile(): TestTile { return this._rootTile; } - public get is3d() { return true; } - public get maxDepth() { return undefined; } - public get viewFlagOverrides() { return { }; } + public get rootTile(): TestTile { + return this._rootTile; + } + public get is3d() { + return true; + } + public get maxDepth() { + return undefined; + } + public get viewFlagOverrides() { + return {}; + } protected _selectTiles(args: TileDrawArgs): Tile[] { const tiles = []; @@ -202,7 +226,7 @@ describe("TileAdmin", () => { args.drawGraphics(); } - public prune() { } + public prune() {} } class Supplier implements TileTreeSupplier { @@ -225,7 +249,9 @@ describe("TileAdmin", () => { this._owner = tree.iModel.tiles.getTileTreeOwner(tree, supplier); } - public get treeOwner() { return this._owner; } + public get treeOwner() { + return this._owner; + } } class Provider implements TiledGraphicsProvider { diff --git a/core/frontend/src/test/tile/TileRequestChannel.test.ts b/core/frontend/src/test/tile/TileRequestChannel.test.ts index aa309c7e9c37..3561fbe73e70 100644 --- a/core/frontend/src/test/tile/TileRequestChannel.test.ts +++ b/core/frontend/src/test/tile/TileRequestChannel.test.ts @@ -2,18 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration } from "@itwin/core-bentley"; -import { Range3d, Transform } from "@itwin/core-geometry"; import { ServerTimeoutError } from "@itwin/core-common"; -import { IModelConnection } from "../../IModelConnection"; +import { Range3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { IModelApp } from "../../IModelApp"; -import { Viewport } from "../../Viewport"; +import { IModelConnection } from "../../IModelConnection"; import { MockRender } from "../../render/MockRender"; -import { createBlankConnection } from "../createBlankConnection"; import { - Tile, TileContent, TileContentDecodingStatistics, TileLoadPriority, TileLoadStatus, TileRequest, TileRequestChannel, TileRequestChannelStatistics, TileTree, + Tile, + TileContent, + TileContentDecodingStatistics, + TileLoadPriority, + TileLoadStatus, + TileRequest, + TileRequestChannel, + TileRequestChannelStatistics, + TileTree, } from "../../tile/internal"; +import { Viewport } from "../../Viewport"; +import { createBlankConnection } from "../createBlankConnection"; async function runMicroTasks(): Promise { return BeDuration.wait(1); @@ -156,20 +164,30 @@ class TestTree extends TileTree { this._rootTile = new TestTile(this, channel); } - public get rootTile(): TestTile { return this._rootTile; } - public get is3d() { return true; } - public get maxDepth() { return undefined; } - public get viewFlagOverrides() { return {}; } - protected _selectTiles(): Tile[] { return []; } - public draw() { } - public prune() { } + public get rootTile(): TestTile { + return this._rootTile; + } + public get is3d() { + return true; + } + public get maxDepth() { + return undefined; + } + public get viewFlagOverrides() { + return {}; + } + protected _selectTiles(): Tile[] { + return []; + } + public draw() {} + public prune() {} } function mockViewport(iModel: IModelConnection, viewportId = 1): Viewport { return { viewportId, iModel, - invalidateScene: () => { }, + invalidateScene: () => {}, } as Viewport; } @@ -768,13 +786,18 @@ describe("TileRequestChannel", () => { await processOnce(); channel1.expectRequests(0, 0); channel2.expectRequests(0, 0); - expect(tiles.map((x) => x.loadStatus)).to.deep.equal([TileLoadStatus.NotFound, TileLoadStatus.Ready, TileLoadStatus.Ready, TileLoadStatus.NotFound]); + expect(tiles.map((x) => x.loadStatus)).to.deep.equal([ + TileLoadStatus.NotFound, + TileLoadStatus.Ready, + TileLoadStatus.Ready, + TileLoadStatus.NotFound, + ]); }); it("records decoding time statistics", () => { const channel = new TileRequestChannel("test", 100); const tile = { isEmpty: false, isUndisplayable: false } as unknown as Tile; - const content = { }; + const content = {}; const expectStats = (expected: TileContentDecodingStatistics) => { const actual = channel.statistics.decoding; diff --git a/core/frontend/src/test/tile/TileRequestChannels.test.ts b/core/frontend/src/test/tile/TileRequestChannels.test.ts index 90cdb9018002..da5d83aa5a79 100644 --- a/core/frontend/src/test/tile/TileRequestChannels.test.ts +++ b/core/frontend/src/test/tile/TileRequestChannels.test.ts @@ -3,9 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { - Tile, TileContentDecodingStatistics, TileRequestChannel, TileRequestChannels, -} from "../../tile/internal"; +import { Tile, TileContentDecodingStatistics, TileRequestChannel, TileRequestChannels } from "../../tile/internal"; // Assumes no minification or uglification. function expectClassName(obj: Object, name: string): void { @@ -103,7 +101,7 @@ describe("TileRequestChannels", () => { channels.add(c3); const tile = { isEmpty: false, isUndisplayable: false } as unknown as Tile; - const content = { }; + const content = {}; const expectStats = (expected: TileContentDecodingStatistics) => { const actual = channels.statistics.decoding; diff --git a/core/frontend/src/test/tile/TileUserIdSet.test.ts b/core/frontend/src/test/tile/TileUserIdSet.test.ts index ca816a0bec68..05745e727b6d 100644 --- a/core/frontend/src/test/tile/TileUserIdSet.test.ts +++ b/core/frontend/src/test/tile/TileUserIdSet.test.ts @@ -16,19 +16,19 @@ function makeTileUserIdSet(ids: number[]): TileUserIdSet { describe("TileUserIdSet", () => { it("compares for equality", () => { const idLists = [ - [ ], - [ 1 ], - [ 2 ], - [ 1, 2 ], - [ 5, 199, 2, 4, 300 ], - [ 1, 1, 2, 2, 5, 4, 4, 3, 3, 1, 2 ], + [], + [1], + [2], + [1, 2], + [5, 199, 2, 4, 300], + [1, 1, 2, 2, 5, 4, 4, 3, 3, 1, 2], ]; for (let i = 0; i < idLists.length; i++) { const list = idLists[i]; const set = makeTileUserIdSet(list); expect(set.equals(set)).to.be.true; - const reverse = [ ...list ]; + const reverse = [...list]; reverse.reverse(); expect(set.equals(makeTileUserIdSet(reverse))).to.be.true; diff --git a/core/frontend/src/test/tile/TiledGraphicsProvider.test.ts b/core/frontend/src/test/tile/TiledGraphicsProvider.test.ts index 87d248192377..699dc35f77f2 100644 --- a/core/frontend/src/test/tile/TiledGraphicsProvider.test.ts +++ b/core/frontend/src/test/tile/TiledGraphicsProvider.test.ts @@ -2,18 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, BeEvent } from "@itwin/core-bentley"; +import { EmptyLocalization } from "@itwin/core-common"; import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; import { SpatialViewState } from "../../SpatialViewState"; -import { ScreenViewport, Viewport } from "../../Viewport"; -import { IModelApp } from "../../IModelApp"; import { - Tile, TileContent, TiledGraphicsProvider, TileLoadPriority, TileRequest, TileTree, TileTreeOwner, TileTreeReference, TileTreeSupplier, + Tile, + TileContent, + TiledGraphicsProvider, + TileLoadPriority, + TileRequest, + TileTree, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, } from "../../tile/internal"; +import { ScreenViewport, Viewport } from "../../Viewport"; import { createBlankConnection } from "../createBlankConnection"; -import { EmptyLocalization } from "@itwin/core-common"; class TestTile extends Tile { public constructor(tree: TileTree) { @@ -62,17 +70,25 @@ class TestTree extends TileTree { return BeDuration.wait(1); } - public get rootTile(): TestTile { return this._rootTile; } - public get is3d() { return true; } - public get maxDepth() { return undefined; } - public get viewFlagOverrides() { return {}; } + public get rootTile(): TestTile { + return this._rootTile; + } + public get is3d() { + return true; + } + public get maxDepth() { + return undefined; + } + public get viewFlagOverrides() { + return {}; + } protected _selectTiles(): Tile[] { return [this.rootTile]; } - public draw() { } - public prune() { } + public draw() {} + public prune() {} } class TestSupplier implements TileTreeSupplier { @@ -100,7 +116,9 @@ class TestRef extends TileTreeReference { this._owner.load(); } - public get treeOwner() { return this._owner; } + public get treeOwner() { + return this._owner; + } protected override get _isLoadingComplete(): boolean { return this.loadingComplete; @@ -239,10 +257,17 @@ describe("TiledGraphicsProvider", () => { ref.extents.scaleAboutCenterInPlace(2.0); expectExtents(ref.extents); - ref.extents = new Range3d(projExtents.low.x - 10, projExtents.low.y + 20, projExtents.low.z, - projExtents.high.x + 30, projExtents.high.y - 40, projExtents.high.z * 50); - - expectExtents(new Range3d(projExtents.low.x - 10, projExtents.low.y, projExtents.low.z, - projExtents.high.x + 30, projExtents.high.y, projExtents.high.z * 50)); + ref.extents = new Range3d( + projExtents.low.x - 10, + projExtents.low.y + 20, + projExtents.low.z, + projExtents.high.x + 30, + projExtents.high.y - 40, + projExtents.high.z * 50, + ); + + expectExtents( + new Range3d(projExtents.low.x - 10, projExtents.low.y, projExtents.low.z, projExtents.high.x + 30, projExtents.high.y, projExtents.high.z * 50), + ); }); }); diff --git a/core/frontend/src/test/tile/Tiles.test.ts b/core/frontend/src/test/tile/Tiles.test.ts index d515a4f043a1..24e73eb0d265 100644 --- a/core/frontend/src/test/tile/Tiles.test.ts +++ b/core/frontend/src/test/tile/Tiles.test.ts @@ -2,22 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Range3d, Transform } from "@itwin/core-geometry"; -import { IModelConnection } from "../../IModelConnection"; +import { expect } from "chai"; import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; import { MockRender } from "../../render/MockRender"; import { RenderGraphic } from "../../render/RenderGraphic"; import { RenderMemory } from "../../render/RenderMemory"; -import { - Tile, TileContent, TileDrawArgs, TileLoadPriority, TileRequest, TileTree, - TileTreeOwner, - TileTreeSupplier, -} from "../../tile/internal"; +import { Tile, TileContent, TileDrawArgs, TileLoadPriority, TileRequest, TileTree, TileTreeOwner, TileTreeSupplier } from "../../tile/internal"; import { createBlankConnection } from "../createBlankConnection"; describe("Tiles", () => { - class TestGraphic extends RenderGraphic { public constructor(private _size: number) { super(); @@ -32,7 +27,7 @@ describe("Tiles", () => { stats.addTexture(this._size); } - public unionRange() { } + public unionRange() {} } class TestTile extends Tile { @@ -102,10 +97,18 @@ describe("Tiles", () => { this._rootTile = new TestTile(this, contentSize, retainMemory); } - public get rootTile(): TestTile { return this._rootTile; } - public get is3d() { return true; } - public get maxDepth() { return undefined; } - public get viewFlagOverrides() { return { }; } + public get rootTile(): TestTile { + return this._rootTile; + } + public get is3d() { + return true; + } + public get maxDepth() { + return undefined; + } + public get viewFlagOverrides() { + return {}; + } protected _selectTiles(args: TileDrawArgs): Tile[] { const tiles = []; @@ -128,10 +131,10 @@ describe("Tiles", () => { args.drawGraphics(); } - public prune() { } + public prune() {} } - const createOnTileTreeLoadPromise: (treeOwner: TileTreeOwner) => Promise = async (treeOwner: TileTreeOwner) => { + const createOnTileTreeLoadPromise: (treeOwner: TileTreeOwner) => Promise = async (treeOwner: TileTreeOwner) => { return new Promise((resolve) => { IModelApp.tileAdmin.onTileTreeLoad.addListener((tileTreeOwner) => { if (treeOwner === tileTreeOwner) @@ -167,7 +170,6 @@ describe("Tiles", () => { }); it("resetTileTreeOwner should remove the tiletree", async () => { - const contentSize = 100; const tree1 = new TestTree(contentSize, imodel); const tree2 = new TestTree(contentSize, imodel); @@ -184,7 +186,7 @@ describe("Tiles", () => { await Promise.all(promises); let nbItems = 0; - for ( const _item of imodel.tiles) { + for (const _item of imodel.tiles) { nbItems++; } expect(nbItems).to.equals(2); @@ -197,7 +199,7 @@ describe("Tiles", () => { expect(tree2.isDisposed).to.be.false; nbItems = 0; - for ( const item of imodel.tiles) { + for (const item of imodel.tiles) { expect(item.id.id).to.equals(tree2.id); nbItems++; } diff --git a/core/frontend/src/test/tile/map/ArcGISImageryProvider.test.ts b/core/frontend/src/test/tile/map/ArcGISImageryProvider.test.ts index f213210a050f..82df32df3639 100644 --- a/core/frontend/src/test/tile/map/ArcGISImageryProvider.test.ts +++ b/core/frontend/src/test/tile/map/ArcGISImageryProvider.test.ts @@ -7,19 +7,16 @@ import { ImageMapLayerSettings } from "@itwin/core-common"; import chai from "chai"; import chaiAsPromised from "chai-as-promised"; import sinon from "sinon"; -import { - ArcGISImageryProvider, - -} from "../../../tile/internal"; -import { indexedArrayFromUrlParams } from "./MapLayerTestUtilities"; import { headersIncludeAuthMethod } from "../../../request/utils"; +import { ArcGISImageryProvider } from "../../../tile/internal"; +import { indexedArrayFromUrlParams } from "./MapLayerTestUtilities"; chai.use(chaiAsPromised); const sampleSource = { formatId: "ArcGIS", url: "https://sub.service.com/service", name: "Test" }; -class TestArcGISProvider extends ArcGISImageryProvider { - public override async constructUrl(_row: number, _column: number, _zoomLevel: number): Promise { +class TestArcGISProvider extends ArcGISImageryProvider { + public override async constructUrl(_row: number, _column: number, _zoomLevel: number): Promise { return ""; } @@ -35,22 +32,30 @@ describe("ArcGISImageryProvider", () => { }); it("should inject custom parameters before fetch call", async () => { - const settings = ImageMapLayerSettings.fromJSON({...sampleSource, subLayers: [{name:"layer1", id: "1", visible:false}, {name:"layer2", id: "2", visible:true}, {name:"layer3", id: "3", visible:true}]}); + const settings = ImageMapLayerSettings.fromJSON({ + ...sampleSource, + subLayers: [{ name: "layer1", id: "1", visible: false }, { name: "layer2", id: "2", visible: true }, { + name: "layer3", + id: "3", + visible: true, + }], + }); if (!settings) chai.assert.fail("Could not create settings"); const provider = new TestArcGISProvider(settings, true); - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { - - return Promise.resolve((({ - status: 200, - headers: new Headers({ "content-type": "application/json" }), - json: async () => {}, - } as unknown) as Response)); + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { + return Promise.resolve( + ({ + status: 200, + headers: new Headers({ "content-type": "application/json" }), + json: async () => {}, + } as unknown) as Response, + ); }); - const testUrl = `${settings.url }?testParam=test`; + const testUrl = `${settings.url}?testParam=test`; await provider.fetch(new URL(testUrl), { method: "GET" }); chai.expect(fetchStub.called).to.be.true; @@ -59,11 +64,11 @@ describe("ArcGISImageryProvider", () => { chai.expect(urlObj.toString()).to.equals(testUrl); const unsaved = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"], ["testParam", "BAD"]]); - const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_2"] ]); + const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_2"]]); settings.unsavedQueryParams = indexedArrayFromUrlParams(unsaved); settings.savedQueryParams = indexedArrayFromUrlParams(saved); - unsaved.delete("testParam"); // check that test' + unsaved.delete("testParam"); // check that test' await provider.fetch(new URL(testUrl), { method: "GET" }); chai.expect(fetchStub.called).to.be.true; urlObj = fetchStub.getCall(1).args[0]; @@ -77,5 +82,4 @@ describe("ArcGISImageryProvider", () => { const headers2 = new Headers([["www-authenticate", "ntlm"]]); chai.expect(headersIncludeAuthMethod(headers2, ["ntlm", "negotiate"])).to.be.true; }); - }); diff --git a/core/frontend/src/test/tile/map/ArcGISMapLayerDataset.ts b/core/frontend/src/test/tile/map/ArcGISMapLayerDataset.ts index 75c77a6560c0..e3413a04f226 100644 --- a/core/frontend/src/test/tile/map/ArcGISMapLayerDataset.ts +++ b/core/frontend/src/test/tile/map/ArcGISMapLayerDataset.ts @@ -6,7 +6,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class ArcGISMapLayerDataset { - public static readonly TilesOnlyDataset26918: any = { id: "ae830ad7b2a39acf", name: "Philadelphia2", @@ -18,103 +17,94 @@ export class ArcGISMapLayerDataset { access: "SECURE", status: "created", singleFusedMapCache: true, - spatialReference: - { - wkid: 26918, - latestWkid: 26918, - }, - initialExtent: - { - xmin: 442494.57455522625, - ymin: 4410580.203758644, - xmax: 536978.6719738642, - ymax: 4444183.334639749, - spatialReference: - { - wkid: 26918, - latestWkid: 26918, - }, - }, - fullExtent: - { - xmin: 475778.10840000026, - ymin: 4412107.618799999, - xmax: 503695.13810000004, - ymax: 4442655.9196, - spatialReference: - { - wkid: 26918, - latestWkid: 26918, - }, - }, + spatialReference: { + wkid: 26918, + latestWkid: 26918, + }, + initialExtent: { + xmin: 442494.57455522625, + ymin: 4410580.203758644, + xmax: 536978.6719738642, + ymax: 4444183.334639749, + spatialReference: { + wkid: 26918, + latestWkid: 26918, + }, + }, + fullExtent: { + xmin: 475778.10840000026, + ymin: 4412107.618799999, + xmax: 503695.13810000004, + ymax: 4442655.9196, + spatialReference: { + wkid: 26918, + latestWkid: 26918, + }, + }, minScale: 1.47914382E8, maxScale: 5842.0, minLOD: 0, maxLOD: 4, - tileInfo: - { - rows: 256, - cols: 256, - dpi: 96, - format: "PNG", - compressionQuality: 0, - storageFormat: "esriMapCacheStorageModeCompactV2", - origin: - { - x: -5120900.0, - y: 9998100.0, - }, - spatialReference: - { - wkid: 26918, - latestWkid: 26918, - }, - lods: [ - { - level: 0, - resolution: 66.1459656252646, - scale: 250000.0, - }, - { - level: 1, - resolution: 33.0729828126323, - scale: 125000.0, - }, - { - level: 2, - resolution: 16.933367200067735, - scale: 64000.0, - }, - { - level: 3, - resolution: 8.466683600033868, - scale: 32000.0, + tileInfo: { + rows: 256, + cols: 256, + dpi: 96, + format: "PNG", + compressionQuality: 0, + storageFormat: "esriMapCacheStorageModeCompactV2", + origin: { + x: -5120900.0, + y: 9998100.0, }, - { - level: 4, - resolution: 4.233341800016934, - scale: 16000.0, + spatialReference: { + wkid: 26918, + latestWkid: 26918, }, - ], - }, - documentInfo: - { - title: "Philadelphia2", - author: "mcayerbentley", - comments: "", - subject: "landmarks2", - category: "", - keywords: "philly", - credits: "", - Title: "", - Author: "", - Comments: "", - Subject: "landmarks", - Category: "", - AntialiasingMode: "Best", - TextAntialiasingMode: "Force", - Keywords: "philly", - }, + lods: [ + { + level: 0, + resolution: 66.1459656252646, + scale: 250000.0, + }, + { + level: 1, + resolution: 33.0729828126323, + scale: 125000.0, + }, + { + level: 2, + resolution: 16.933367200067735, + scale: 64000.0, + }, + { + level: 3, + resolution: 8.466683600033868, + scale: 32000.0, + }, + { + level: 4, + resolution: 4.233341800016934, + scale: 16000.0, + }, + ], + }, + documentInfo: { + title: "Philadelphia2", + author: "mcayerbentley", + comments: "", + subject: "landmarks2", + category: "", + keywords: "philly", + credits: "", + Title: "", + Author: "", + Comments: "", + Subject: "landmarks", + Category: "", + AntialiasingMode: "Best", + TextAntialiasingMode: "Force", + Keywords: "philly", + }, copyrightText: "", tileServers: null, maxExportTilesCount: 100000, @@ -141,9 +131,11 @@ export class ArcGISMapLayerDataset { public static readonly UsaTopoMaps: any = { currentVersion: 10.91, - serviceDescription: "This map presents land cover imagery for the world and detailed topographic maps for the United States. The map includes the National Park Service (NPS) Natural Earth physical map at 1.24km per pixel for the world at small scales, i-cubed eTOPO 1:250,000-scale maps for the contiguous United States at medium scales, and National Geographic TOPO! 1:100,000 and 1:24,000-scale maps (1:250,000 and 1:63,000 in Alaska) for the United States at large scales. The TOPO! maps are seamless, scanned images of United States Geological Survey (USGS) paper topographic maps. For more information on this map, including the terms of use, visit us online<\/a>.", + serviceDescription: + 'This map presents land cover imagery for the world and detailed topographic maps for the United States. The map includes the National Park Service (NPS) Natural Earth physical map at 1.24km per pixel for the world at small scales, i-cubed eTOPO 1:250,000-scale maps for the contiguous United States at medium scales, and National Geographic TOPO! 1:100,000 and 1:24,000-scale maps (1:250,000 and 1:63,000 in Alaska) for the United States at large scales. The TOPO! maps are seamless, scanned images of United States Geological Survey (USGS) paper topographic maps. For more information on this map, including the terms of use, visit us online<\/a>.', mapName: "Layers", - description: "This map presents land cover imagery for the world and detailed topographic maps for the United States. The map includes the National Park Service (NPS) Natural Earth physical map at 1.24km per pixel for the world at small scales, i-cubed eTOPO 1:250,000-scale maps for the contiguous United States at medium scales, and National Geographic TOPO! 1:100,000 and 1:24,000-scale maps (1:250,000 and 1:63,000 in Alaska) for the United States at large scales. The TOPO! maps are seamless, scanned images of United States Geological Survey (USGS) paper topographic maps. For more information on this map, including our terms of use, visit us online at http://goto.arcgisonline.com/maps/USA_Topo_Maps", + description: + "This map presents land cover imagery for the world and detailed topographic maps for the United States. The map includes the National Park Service (NPS) Natural Earth physical map at 1.24km per pixel for the world at small scales, i-cubed eTOPO 1:250,000-scale maps for the contiguous United States at medium scales, and National Geographic TOPO! 1:100,000 and 1:24,000-scale maps (1:250,000 and 1:63,000 in Alaska) for the United States at large scales. The TOPO! maps are seamless, scanned images of United States Geological Survey (USGS) paper topographic maps. For more information on this map, including our terms of use, visit us online at http://goto.arcgisonline.com/maps/USA_Topo_Maps", copyrightText: "Copyright:© 2013 National Geographic Society, i-cubed", supportsDynamicLayers: false, layers: [ @@ -747,9 +739,9 @@ export class ArcGISMapLayerDataset { ], supportsDatumTransformation: true, floorAwareMapProperties: { - defaultFloorFilterSettings: {isEnabled: true}, + defaultFloorFilterSettings: { isEnabled: true }, }, - archivingInfo: {supportsHistoricMoment: false}, + archivingInfo: { supportsHistoricMoment: false }, supportsClipping: true, supportsSpatialFilter: true, supportsTimeRelation: true, diff --git a/core/frontend/src/test/tile/map/ArcGISMapLayerImageryProvider.test.ts b/core/frontend/src/test/tile/map/ArcGISMapLayerImageryProvider.test.ts index 9b2a71a46b6a..3cea9cea0bd1 100644 --- a/core/frontend/src/test/tile/map/ArcGISMapLayerImageryProvider.test.ts +++ b/core/frontend/src/test/tile/map/ArcGISMapLayerImageryProvider.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Cartographic, EmptyLocalization, ImageMapLayerSettings, ServerError } from "@itwin/core-common"; +import { Range2dProps } from "@itwin/core-geometry"; import chai, { expect } from "chai"; import chaiAsPromised from "chai-as-promised"; import sinon from "sinon"; @@ -17,10 +18,8 @@ import { ArcGisUtilities, MapLayerImageryProvider, QuadId, - } from "../../../tile/internal"; import { ArcGISMapLayerDataset } from "./ArcGISMapLayerDataset"; -import { Range2dProps } from "@itwin/core-geometry"; import { indexedArrayFromUrlParams } from "./MapLayerTestUtilities"; chai.use(chaiAsPromised); @@ -28,15 +27,14 @@ chai.use(chaiAsPromised); const sampleSource = { formatId: "ArcGIS", url: "https://localhost/Mapserver", name: "Test" }; function stubJsonFetch(sandbox: sinon.SinonSandbox, json: string) { - - return sandbox.stub((ArcGISImageryProvider.prototype as any), "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { + return sandbox.stub(ArcGISImageryProvider.prototype as any, "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { const test = { headers: { "content-type": "application/json" }, json: async () => { return JSON.parse(json); }, status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need + } as unknown; // By using unknown type, I can define parts of Response I really need return (test as Response); }); } @@ -63,7 +61,7 @@ describe("ArcGISMapLayerImageryProvider", () => { if (!settings) chai.assert.fail("Could not create settings"); - stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.TilesOnlyDataset26918, accessTokenRequired:false}); + stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.TilesOnlyDataset26918, accessTokenRequired: false }); const provider = new ArcGISMapLayerImageryProvider(settings); await chai.expect(provider.initialize()).to.be.rejectedWith(ServerError, "Invalid coordinate system"); @@ -74,7 +72,7 @@ describe("ArcGISMapLayerImageryProvider", () => { if (!settings) chai.assert.fail("Could not create settings"); - stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired:false}); + stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired: false }); const provider = new ArcGISMapLayerImageryProvider(settings); await provider.initialize(); @@ -93,7 +91,7 @@ describe("ArcGISMapLayerImageryProvider", () => { const dataset = JSON.parse(JSON.stringify(ArcGISMapLayerDataset.UsaTopoMaps)); // Fake an unknown CS dataset.tileInfo.spatialReference.latestWkid = 1234; - const responseJson = {content: dataset, accessTokenRequired:false}; + const responseJson = { content: dataset, accessTokenRequired: false }; stubGetServiceJson(sandbox, responseJson); const provider = new ArcGISMapLayerImageryProvider(settings); @@ -106,7 +104,7 @@ describe("ArcGISMapLayerImageryProvider", () => { }); it("ArcGISIdentifyRequestUrl should create proper extent string ", async () => { - const range: Range2dProps = {low: {x:1, y:2}, high:{x:3, y:4}}; + const range: Range2dProps = { low: { x: 1, y: 2 }, high: { x: 3, y: 4 } }; let extentStr = ArcGISIdentifyRequestUrl.getExtentString(range, 2); chai.expect(extentStr).to.equals("1.00,2.00,3.00,4.00"); extentStr = ArcGISIdentifyRequestUrl.getExtentString(range, 3); @@ -114,33 +112,49 @@ describe("ArcGISMapLayerImageryProvider", () => { }); it("ArcGISIdentifyRequestUrl should create proper identify request ", async () => { - const range: Range2dProps = {low: {x:1, y:2}, high:{x:3, y:4}}; + const range: Range2dProps = { low: { x: 1, y: 2 }, high: { x: 3, y: 4 } }; const props: ArcGISIdentifyRequestUrlProps = { - geometry: {x: 1.00000000, y: 2.0000000000}, + geometry: { x: 1.00000000, y: 2.0000000000 }, geometryType: "esriGeometryPoint", tolerance: 1.0, mapExtent: range, - imageDisplay: {width: 256, height: 256, dpi: 96} }; + imageDisplay: { width: 256, height: 256, dpi: 96 }, + }; const baseUrl = "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer"; let url = ArcGISIdentifyRequestUrl.fromJSON(baseUrl, props); - chai.expect(url.toString()).to.equals("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?geometry=1%2C2&geometryType=esriGeometryPoint&tolerance=1&mapExtent=1%2C2%2C3%2C4&imageDisplay=256%2C256%2C96"); + chai.expect(url.toString()).to.equals( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?geometry=1%2C2&geometryType=esriGeometryPoint&tolerance=1&mapExtent=1%2C2%2C3%2C4&imageDisplay=256%2C256%2C96", + ); // exercise srFractionDigits url = ArcGISIdentifyRequestUrl.fromJSON(baseUrl, props, 2); - chai.expect(url.toString()).to.equals("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?geometry=1.00%2C2.00&geometryType=esriGeometryPoint&tolerance=1&mapExtent=1.00%2C2.00%2C3.00%2C4.00&imageDisplay=256%2C256%2C96"); + chai.expect(url.toString()).to.equals( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?geometry=1.00%2C2.00&geometryType=esriGeometryPoint&tolerance=1&mapExtent=1.00%2C2.00%2C3.00%2C4.00&imageDisplay=256%2C256%2C96", + ); // optional parameters - url = ArcGISIdentifyRequestUrl.fromJSON(baseUrl, {...props, + url = ArcGISIdentifyRequestUrl.fromJSON(baseUrl, { + ...props, f: "json", - layers: { prefix: "visible", layerIds: [ "2", "3" ] }, + layers: { prefix: "visible", layerIds: ["2", "3"] }, maxAllowableOffset: 2.00000000, - returnGeometry: true}, 2); - chai.expect(url.toString()).to.equals("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?f=json&geometry=1.00%2C2.00&geometryType=esriGeometryPoint&layers=visible%3A+2%2C3&tolerance=1&mapExtent=1.00%2C2.00%2C3.00%2C4.00&imageDisplay=256%2C256%2C96&returnGeometry=true&maxAllowableOffset=2.00"); + returnGeometry: true, + }, 2); + chai.expect(url.toString()).to.equals( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer/identify?f=json&geometry=1.00%2C2.00&geometryType=esriGeometryPoint&layers=visible%3A+2%2C3&tolerance=1&mapExtent=1.00%2C2.00%2C3.00%2C4.00&imageDisplay=256%2C256%2C96&returnGeometry=true&maxAllowableOffset=2.00", + ); }); it("getIdentifyData should create proper identify request", async () => { - const settings = ImageMapLayerSettings.fromJSON({...sampleSource, subLayers: [{name:"layer1", id: "1", visible:false}, {name:"layer2", id: "2", visible:true}, {name:"layer3", id: "3", visible:true}]}); + const settings = ImageMapLayerSettings.fromJSON({ + ...sampleSource, + subLayers: [{ name: "layer1", id: "1", visible: false }, { name: "layer2", id: "2", visible: true }, { + name: "layer3", + id: "3", + visible: true, + }], + }); if (!settings) chai.assert.fail("Could not create settings"); @@ -155,7 +169,13 @@ describe("ArcGISMapLayerImageryProvider", () => { sinon.stub(MapLayerImageryProvider.prototype, "getEPSG3857X").callsFake((_longitude: number) => i++); sinon.stub(MapLayerImageryProvider.prototype, "getEPSG3857Y").callsFake((_longitude: number) => i++); const maxAllowableOffset = 2.0; - (provider as any).getIdentifyData(new QuadId(3, 2, 1), Cartographic.fromRadians({longitude: 0.1, latitude: 0.2, height: 0.3}), 0.1, true, maxAllowableOffset); + (provider as any).getIdentifyData( + new QuadId(3, 2, 1), + Cartographic.fromRadians({ longitude: 0.1, latitude: 0.2, height: 0.3 }), + 0.1, + true, + maxAllowableOffset, + ); chai.expect(fromJSONSpy.called).to.be.true; const firstCall = fromJSONSpy.getCalls()[0]; @@ -171,7 +191,7 @@ describe("ArcGISMapLayerImageryProvider", () => { high: { x: 2, y: 4 }, }, imageDisplay: { width: 256, height: 256, dpi: 96 }, - layers: { prefix: "top", layerIds: [ "2", "3" ] }, + layers: { prefix: "top", layerIds: ["2", "3"] }, returnGeometry: true, maxAllowableOffset, }; @@ -183,25 +203,26 @@ describe("ArcGISMapLayerImageryProvider", () => { it("should pass fetch function to ArcGISTileMap object", async () => { const settings = ImageMapLayerSettings.fromJSON(sampleSource); const unsaved = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"], ["testParam", "BAD"]]); - const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_"] ]); + const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_"]]); settings.unsavedQueryParams = indexedArrayFromUrlParams(unsaved); settings.savedQueryParams = indexedArrayFromUrlParams(saved); if (!settings) chai.assert.fail("Could not create settings"); - stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired:false}); + stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired: false }); const provider = new ArcGISMapLayerImageryProvider(settings); await provider.initialize(); const resolveChildren = (_childIds: QuadId[]) => {}; - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { - - return Promise.resolve((({ - status: 200, - headers: new Headers({ "content-type": "application/json" }), - json: async () => {}, - } as unknown) as Response)); + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { + return Promise.resolve( + ({ + status: 200, + headers: new Headers({ "content-type": "application/json" }), + json: async () => {}, + } as unknown) as Response, + ); }); await (provider as any)._generateChildIds(QuadId.createFromContentId("1_0_0"), resolveChildren); diff --git a/core/frontend/src/test/tile/map/ArcGISTileMap.test.ts b/core/frontend/src/test/tile/map/ArcGISTileMap.test.ts index 70600126f6d5..4d54731e9fd3 100644 --- a/core/frontend/src/test/tile/map/ArcGISTileMap.test.ts +++ b/core/frontend/src/test/tile/map/ArcGISTileMap.test.ts @@ -7,10 +7,8 @@ import { ImageMapLayerSettings } from "@itwin/core-common"; import { expect } from "chai"; import * as sinon from "sinon"; -import { - ArcGISTileMap, QuadId, -} from "../../../tile/internal"; import { BeEvent } from "@itwin/core-bentley"; +import { ArcGISTileMap, QuadId } from "../../../tile/internal"; const fakeArcGisUrl = "https:localhost/test/rest"; // This tilemap for parent tile (9,5,5), @@ -18,63 +16,158 @@ const fakeArcGisUrl = "https:localhost/test/rest"; // From tilemap, only [10,10,10], 10,11,11] are availability const dataset1 = { tilemap: { - adjusted:false, - location:{left:9,top:9,width:4,height:4}, + adjusted: false, + location: { left: 9, top: 9, width: 4, height: 4 }, data: [ - 0,0,0,0, - 0,1,0,0, - 0,0,1,0, - 0,0,0,0], + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[true,false,false,true], + available: [true, false, false, true], parentContentId: "9_5_5", // NOTE: format is __ }; const dataset2 = { tilemap1: { - adjusted:true, - location:{left:7,top:7,width:4, height:8}, - data:[ - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 1, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0], + adjusted: true, + location: { left: 7, top: 7, width: 4, height: 8 }, + data: [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, tilemap2: { - adjusted:false, - location:{left:11,top:7,width:8, height:8}, + adjusted: false, + location: { left: 11, top: 7, width: 8, height: 8 }, data: [ - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, tilemap3: { - adjusted:true, - location:{left:11,top:7,width:0, height:0}, + adjusted: true, + location: { left: 11, top: 7, width: 0, height: 0 }, data: [], }, - availableClipped: [false,false,true,false], - available:[false,false,true,true], + availableClipped: [false, false, true, false], + available: [false, false, true, true], parentContentId: "9_5_5", }; // In this dataset the tilemap does not include any of the requested tiled const dataset4 = { tilemap1: { - adjusted:true, - location:{left:7,top:7,width:1, height:8}, - data:[ + adjusted: true, + location: { left: 7, top: 7, width: 1, height: 8 }, + data: [ 0, 0, 0, @@ -82,22 +175,80 @@ const dataset4 = { 0, 0, 0, - 0], + 0, + ], }, tilemap2: { - adjusted:false, - location:{left:10,top:10,width:8, height:8}, + adjusted: false, + location: { left: 10, top: 10, width: 8, height: 8 }, data: [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[false,false,false,true], + available: [false, false, false, true], parentContentId: "9_5_5", }; @@ -106,28 +257,85 @@ const dataset4 = { const dataset5 = { tilemap: { adjusted: true, - location:{left:7,top:7,width:0, height:0}, - data:[0], + location: { left: 7, top: 7, width: 0, height: 0 }, + data: [0], }, - available:[false,false,false,false], + available: [false, false, false, false], parentContentId: "9_5_5", }; const dataset3 = { tilemap: { - adjusted:false, - location:{left:0,top:0,width:8,height:8}, + adjusted: false, + location: { left: 0, top: 0, width: 8, height: 8 }, data: [ - 1, 1, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0], + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[true,true,true,true], + available: [true, true, true, true], parentContentId: "9_0_0", }; @@ -135,22 +343,79 @@ const dataset3 = { // the second one is only half visible const dataset6 = { tilemap: { - adjusted:false, - location:{left:37,top:37,width:8,height:8}, + adjusted: false, + location: { left: 37, top: 37, width: 8, height: 8 }, data: [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[true,true,true,true], // first parent, fully visible + available: [true, true, true, true], // first parent, fully visible parentContentId: "14_20_20", // NOTE: format is __ sibling: { - available:[true,false,true,false], // second parent tile: half of it is visible + available: [true, false, true, false], // second parent tile: half of it is visible parentContentId: "14_21_20", // NOTE: format is __ }, }; @@ -158,43 +423,160 @@ const dataset6 = { // dataset7 depends on dataset6 to test cache check const dataset7 = { tilemap: { - adjusted:false, - location:{ - left: dataset6.tilemap.location.left+dataset6.tilemap.location.width, - top:dataset6.tilemap.location.top, - width:8, height:8}, + adjusted: false, + location: { + left: dataset6.tilemap.location.left + dataset6.tilemap.location.width, + top: dataset6.tilemap.location.top, + width: 8, + height: 8, + }, data: [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[false,false,true,true], + available: [false, false, true, true], parentContentId: "14_22_20", // NOTE: format is __ }; const dataset8 = { tilemap: { - adjusted:false, - location:{ - left:dataset6.tilemap.location.left, - top:dataset6.tilemap.location.top+dataset6.tilemap.location.height, - width:8,height:8}, + adjusted: false, + location: { + left: dataset6.tilemap.location.left, + top: dataset6.tilemap.location.top + dataset6.tilemap.location.height, + width: 8, + height: 8, + }, data: [ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 0, - 1, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0], + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], }, - available:[false,false,true,true], + available: [false, false, true, true], parentContentId: "14_20_22", // NOTE: format is __ }; @@ -220,18 +602,20 @@ describe("ArcGISTileMap", () => { const childIds = parentTile.getChildIds(); const row = Math.max(childIds[0].row - offset, 0); const column = Math.max(childIds[0].column - offset, 0); - return {level:childIds[0].level, row, column}; + return { level: childIds[0].level, row, column }; }; const getChildrenAvailability = async (parentContentId: string, fakeTileMapData: any) => { - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - return fakeTileMapData; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + return fakeTileMapData; + }, + ); const parentQuadId = QuadId.createFromContentId(parentContentId); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); - const childIds = parentQuadId.getChildIds(); + const childIds = parentQuadId.getChildIds(); const available = await tileMap.getChildrenAvailability(parentQuadId.getChildIds()); - return {available, tileMap, getTileMapStub, childIds}; + return { available, tileMap, getTileMapStub, childIds }; }; afterEach(async () => { @@ -239,15 +623,13 @@ describe("ArcGISTileMap", () => { }); it("8x8 tilemap; simple children availability check", async () => { - - const {available, getTileMapStub} = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); + const { available, getTileMapStub } = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); expect(available).to.eql(dataset6.available); expect(getTileMapStub.calledOnce).to.be.true; }); it("8x8 tilemap; tile map cached", async () => { - - const {available, getTileMapStub, tileMap, childIds} = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); + const { available, getTileMapStub, tileMap, childIds } = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); expect(available).to.eql(dataset6.available); expect(getTileMapStub.calledOnce).to.be.true; @@ -258,16 +640,23 @@ describe("ArcGISTileMap", () => { }); it("8x8 tilemap; two children availability check, single server request", async () => { - // eslint-disable-next-line prefer-const - let {available, getTileMapStub, tileMap} = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); + let { available, getTileMapStub, tileMap } = await getChildrenAvailability(dataset6.parentContentId, dataset6.tilemap); expect(available).to.eql(dataset6.available); expect(getTileMapStub.calledOnce).to.be.true; // Make sure the request tile was put in the middle of the tilemap const parentQuadId = QuadId.createFromContentId(dataset6.parentContentId); const tilemapLocation = getTilemapLocation(parentQuadId, 3); - expect(getTileMapStub.calledWithExactly(tilemapLocation.level, tilemapLocation.row, tilemapLocation.column, tileMap.tileMapRequestSize, tileMap.tileMapRequestSize)).to.be.true; + expect( + getTileMapStub.calledWithExactly( + tilemapLocation.level, + tilemapLocation.row, + tilemapLocation.column, + tileMap.tileMapRequestSize, + tileMap.tileMapRequestSize, + ), + ).to.be.true; // Request parent tile next to the initial one (on the right), only the bottom,right child should exist // no server request should be made @@ -282,14 +671,16 @@ describe("ArcGISTileMap", () => { it("Tile map location should change if data already in cache", async () => { let selectedDataset = ""; // const getSelectedDataset = () => selectedDataset; - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - if (selectedDataset === "dataset6") - return dataset6.tilemap; - else if (selectedDataset === "dataset7") - return dataset7.tilemap; - else if (selectedDataset === "dataset8") - return dataset8.tilemap; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + if (selectedDataset === "dataset6") + return dataset6.tilemap; + else if (selectedDataset === "dataset7") + return dataset7.tilemap; + else if (selectedDataset === "dataset8") + return dataset8.tilemap; + }, + ); let parentQuadId = QuadId.createFromContentId(dataset6.parentContentId); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); @@ -306,45 +697,58 @@ describe("ArcGISTileMap", () => { parentQuadId = QuadId.createFromContentId(dataset7.parentContentId); expect(getTileMapStub.called).to.be.false; await tileMap.getChildrenAvailability(parentQuadId.getChildIds()); - expect(getTileMapStub.calledWithExactly(childIDs[0].level, dataset7.tilemap.location.top, dataset7.tilemap.location.left, - dataset7.tilemap.location.width, dataset7.tilemap.location.height)).to.be.true; + expect( + getTileMapStub.calledWithExactly( + childIDs[0].level, + dataset7.tilemap.location.top, + dataset7.tilemap.location.left, + dataset7.tilemap.location.width, + dataset7.tilemap.location.height, + ), + ).to.be.true; getTileMapStub.resetHistory(); selectedDataset = "dataset8"; parentQuadId = QuadId.createFromContentId(dataset8.parentContentId); expect(getTileMapStub.called).to.be.false; await tileMap.getChildrenAvailability(parentQuadId.getChildIds()); - expect(getTileMapStub.calledWithExactly(childIDs[0].level, dataset8.tilemap.location.top, dataset8.tilemap.location.left, - dataset8.tilemap.location.width, dataset8.tilemap.location.height)).to.be.true; - + expect( + getTileMapStub.calledWithExactly( + childIDs[0].level, + dataset8.tilemap.location.top, + dataset8.tilemap.location.left, + dataset8.tilemap.location.width, + dataset8.tilemap.location.height, + ), + ).to.be.true; }); it("should serialize async requests", async () => { - const waitingEvent = new BeEvent(); let firstRequest = true; const waitingPromise = new Promise(async (resolve, reject) => { try { if (firstRequest) { firstRequest = false; - waitingEvent.addListener(()=>resolve()); + waitingEvent.addListener(() => resolve()); } else { resolve(); } - } catch (err: any) { reject(); } }); - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - await waitingPromise; - return dataset6.tilemap; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + await waitingPromise; + return dataset6.tilemap; + }, + ); const parentQuadId = QuadId.createFromContentId(dataset6.parentContentId); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); - const requestPromise1 = tileMap.getChildrenAvailability(parentQuadId.getChildIds()); - const requestPromise2 = tileMap.getChildrenAvailability(parentQuadId.getChildIds()); + const requestPromise1 = tileMap.getChildrenAvailability(parentQuadId.getChildIds()); + const requestPromise2 = tileMap.getChildrenAvailability(parentQuadId.getChildIds()); waitingEvent.raiseEvent(); const results = await Promise.all([requestPromise1, requestPromise2]); @@ -359,10 +763,11 @@ describe("ArcGISTileMap", () => { // Since the parent tile is located on the edge of the LOD, // no offset should be applied the requested tile (i.e we should not end up with negatives values for row,columns) it("Test 8x8 tilemap request, top-left tile of LOD", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - return dataset3.tilemap; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + return dataset3.tilemap; + }, + ); const parentQuadId = QuadId.createFromContentId(dataset3.parentContentId); @@ -372,21 +777,28 @@ describe("ArcGISTileMap", () => { expect(available).to.eql(dataset3.available); const tilemapLocation = getTilemapLocation(parentQuadId, 0); - expect(getTileMapStub.calledWithExactly(tilemapLocation.level, tilemapLocation.row, tilemapLocation.column, tileMap.tileMapRequestSize,tileMap.tileMapRequestSize)).to.be.true; - + expect( + getTileMapStub.calledWithExactly( + tilemapLocation.level, + tilemapLocation.row, + tilemapLocation.column, + tileMap.tileMapRequestSize, + tileMap.tileMapRequestSize, + ), + ).to.be.true; }); describe("Clipped Tile map response", () => { - // Response contains an adjusted tilemap, a second request need to be made to get all tiles it("Should make second request when response got adjusted (partly clipped)", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { - if (row === 7 && column === 7) - return dataset2.tilemap1; - else - return dataset2.tilemap2; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { + if (row === 7 && column === 7) + return dataset2.tilemap1; + else + return dataset2.tilemap2; + }, + ); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -395,13 +807,14 @@ describe("ArcGISTileMap", () => { }); it("Should make second request when response got adjusted (fully clipped)", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { - if (row === 7 && column === 7) - return dataset4.tilemap1; - else - return dataset4.tilemap2; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { + if (row === 7 && column === 7) + return dataset4.tilemap1; + else + return dataset4.tilemap2; + }, + ); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -410,13 +823,14 @@ describe("ArcGISTileMap", () => { }); it("Should return consistent availability response when second request fail", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { - if (row === 7 && column === 7) - return dataset2.tilemap1; - else - return emptyBundleError; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { + if (row === 7 && column === 7) + return dataset2.tilemap1; + else + return emptyBundleError; + }, + ); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -425,10 +839,11 @@ describe("ArcGISTileMap", () => { }); it("Should stop making requests when none of missing tiles can be retrieved", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - return dataset5.tilemap; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + return dataset5.tilemap; + }, + ); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -437,13 +852,14 @@ describe("ArcGISTileMap", () => { }); it("Should stop making request if only a subset of missing tiles can be retrieved", async () => { - - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { - if (row === 7 && column === 7) - return dataset2.tilemap1; - else - return dataset2.tilemap3; - }); + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, row: unknown, column: unknown, _width: unknown, _height: unknown): Promise { + if (row === 7 && column === 7) + return dataset2.tilemap1; + else + return dataset2.tilemap3; + }, + ); const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -453,12 +869,13 @@ describe("ArcGISTileMap", () => { }); it("Test empty tilemap response", async () => { + const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake( + async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { + return emptyBundleError; + }, + ); - const getTileMapStub = sandbox.stub(ArcGISTileMap.prototype, "fetchTileMapFromServer" as any).callsFake(async function _(_level: unknown, _row: unknown, _column: unknown, _width: unknown, _height: unknown): Promise { - return emptyBundleError; - }); - - const allFalse = [false,false,false,false]; + const allFalse = [false, false, false, false]; const tileMap = new ArcGISTileMap(fakeArcGisUrl, settings, fakeFetchFunction); tileMap.tileMapRequestSize = 4; const available = await tileMap.getChildrenAvailability(QuadId.createFromContentId(dataset2.parentContentId).getChildIds()); @@ -472,7 +889,6 @@ describe("ArcGISTileMap", () => { }); it("should call the fetch function", async () => { - let fetchFunctionCalls = 0; const fetchFunction = async (_url: URL, _options?: RequestInit): Promise => { fetchFunctionCalls++; diff --git a/core/frontend/src/test/tile/map/ArcGisUtilities.test.ts b/core/frontend/src/test/tile/map/ArcGisUtilities.test.ts index df2f20f15889..8cb019d7f322 100644 --- a/core/frontend/src/test/tile/map/ArcGisUtilities.test.ts +++ b/core/frontend/src/test/tile/map/ArcGisUtilities.test.ts @@ -8,24 +8,25 @@ import sinon from "sinon"; import { MapLayerSource, MapLayerSourceStatus } from "../../../core-frontend"; import { ArcGisGetServiceJsonArgs, ArcGisUtilities } from "../../../tile/map/ArcGisUtilities"; import { ArcGISMapLayerDataset } from "./ArcGISMapLayerDataset"; -import { wsg84Lods256px, wsg84Lods512px } from "./Wgs84Lods"; import { indexedArrayFromUrlParams } from "./MapLayerTestUtilities"; +import { wsg84Lods256px, wsg84Lods512px } from "./Wgs84Lods"; -function stubGetServiceJson(sandbox: sinon.SinonSandbox, json: any ) { +function stubGetServiceJson(sandbox: sinon.SinonSandbox, json: any) { return sandbox.stub(ArcGisUtilities, "getServiceJson").callsFake(async function _(_args: ArcGisGetServiceJsonArgs) { return json; }); } const getSampleSource = () => { - return MapLayerSource.fromJSON({ + return MapLayerSource.fromJSON({ name: "dummyFeatureLayer", url: "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/MapServer", - formatId: "Arcgis"}); + formatId: "Arcgis", + }); }; const unsaved = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"], ["testParam", "BAD"]]); -const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_2"] ]); +const saved = new URLSearchParams([["key2_1", "value2_1"], ["key2_2", "value2_2"]]); const getSampleSourceWithQueryParams = () => { const source = getSampleSource(); @@ -45,7 +46,7 @@ const getSampleSourceWithQueryParamsAndCreds = () => { return source; }; -describe ("ArcGisUtilities", () => { +describe("ArcGisUtilities", () => { const tolerance = 0.1; const sandbox = sinon.createSandbox(); @@ -54,7 +55,7 @@ describe ("ArcGisUtilities", () => { }); it("should compute resolution and scale for LOD range", async () => { - let scales = ArcGisUtilities.computeZoomLevelsScales(5,10); + let scales = ArcGisUtilities.computeZoomLevelsScales(5, 10); expect(scales.length).to.equals(6); expect(scales[0].zoom).to.equals(5); expect(scales[5].zoom).to.equals(10); @@ -62,38 +63,36 @@ describe ("ArcGisUtilities", () => { // Test scales for 256px tiles scales = ArcGisUtilities.computeZoomLevelsScales(); expect(scales.length).to.equals(wsg84Lods256px.length); - for (let i=0 ; i < scales.length; i++) { + for (let i = 0; i < scales.length; i++) { expect(Math.abs(scales[i].resolution - wsg84Lods256px[i].resolution)).to.be.lessThan(tolerance); expect(Math.abs(scales[i].scale - wsg84Lods256px[i].scale)).to.be.lessThan(tolerance); } // Test scales for 512px tiles - scales = ArcGisUtilities.computeZoomLevelsScales(0,20,0,512); + scales = ArcGisUtilities.computeZoomLevelsScales(0, 20, 0, 512); expect(scales.length).to.equals(wsg84Lods512px.length); - for (let i=0 ; i < scales.length; i++) { + for (let i = 0; i < scales.length; i++) { expect(Math.abs(scales[i].resolution - wsg84Lods512px[i].resolution)).to.be.lessThan(tolerance); expect(Math.abs(scales[i].scale - wsg84Lods512px[i].scale)).to.be.lessThan(tolerance); } // Make sure we can get zooms level one by one. - for (let i=0 ; i < wsg84Lods256px.length; i++) { - scales = ArcGisUtilities.computeZoomLevelsScales(i,i,0,256); + for (let i = 0; i < wsg84Lods256px.length; i++) { + scales = ArcGisUtilities.computeZoomLevelsScales(i, i, 0, 256); expect(scales.length).to.equals(1); expect(Math.abs(scales[0].resolution - wsg84Lods256px[i].resolution)).to.be.lessThan(tolerance); expect(Math.abs(scales[0].scale - wsg84Lods256px[i].scale)).to.be.lessThan(tolerance); } // Test parameters validation - expect(ArcGisUtilities.computeZoomLevelsScales(-1,20,0,0, 256).length).to.equals(0); - expect(ArcGisUtilities.computeZoomLevelsScales(0,-20,0,0, 256).length).to.equals(0); - expect(ArcGisUtilities.computeZoomLevelsScales(4,1,0,256).length).to.equals(0); - expect(ArcGisUtilities.computeZoomLevelsScales(0,20,0,-256).length).to.equals(0); - expect(ArcGisUtilities.computeZoomLevelsScales(0,20,0,256,0).length).to.equals(0); - + expect(ArcGisUtilities.computeZoomLevelsScales(-1, 20, 0, 0, 256).length).to.equals(0); + expect(ArcGisUtilities.computeZoomLevelsScales(0, -20, 0, 0, 256).length).to.equals(0); + expect(ArcGisUtilities.computeZoomLevelsScales(4, 1, 0, 256).length).to.equals(0); + expect(ArcGisUtilities.computeZoomLevelsScales(0, 20, 0, -256).length).to.equals(0); + expect(ArcGisUtilities.computeZoomLevelsScales(0, 20, 0, 256, 0).length).to.equals(0); }); it("should match minScale/maxScale to corresponding LOD", async () => { - let lods = ArcGisUtilities.getZoomLevelsScales(22, 256); expect(lods.minLod).to.be.undefined; expect(lods.maxLod).to.be.undefined; @@ -115,26 +114,35 @@ describe ("ArcGisUtilities", () => { it("should validate by invoking getServiceJson with proper parameters ", async () => { const source = getSampleSourceWithQueryParamsAndCreds(); - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { - return Promise.resolve((({ - status: 200, - json: async () => {return {};}, - } as unknown) as Response)); + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { + return Promise.resolve( + ({ + status: 200, + json: async () => { + return {}; + }, + } as unknown) as Response, + ); + }); + await ArcGisUtilities.getServiceJson({ + url: source.url, + formatId: source.formatId, + userName: source.userName, + password: source.password, + queryParams: source.collectQueryParams(), }); - await ArcGisUtilities.getServiceJson({url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams()}); expect(fetchStub.calledOnce).to.be.true; const firstCall = fetchStub.getCalls()[0]; // eslint-disable-next-line @typescript-eslint/no-base-to-string expect(firstCall.args[0].toString()).to.equals(`${source.url}?f=json&${saved.toString()}&${unsaved.toString()}`); - }); it("should fetch service json with proper URL", async () => { - const stub = stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired:false}); + const stub = stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired: false }); const source = getSampleSourceWithQueryParamsAndCreds(); - await ArcGisUtilities.validateSource({source, ignoreCache: true, capabilitiesFilter: []}); + await ArcGisUtilities.validateSource({ source, ignoreCache: true, capabilitiesFilter: [] }); expect(stub.calledOnce).to.be.true; const firstCall = stub.getCalls()[0]; @@ -147,32 +155,46 @@ describe ("ArcGisUtilities", () => { }); it("should validate proper source", async () => { - stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired:false}); - const result = ArcGisUtilities.validateSource({source: getSampleSource()!, capabilitiesFilter: []}); + stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.UsaTopoMaps, accessTokenRequired: false }); + const result = ArcGisUtilities.validateSource({ source: getSampleSource()!, capabilitiesFilter: [] }); expect((await result).status).to.equals(MapLayerSourceStatus.Valid); }); it("validate should detect invalid coordinate system ", async () => { - stubGetServiceJson(sandbox, {content: ArcGISMapLayerDataset.TilesOnlyDataset26918, accessTokenRequired:false}); - const result = ArcGisUtilities.validateSource({source: getSampleSource()!, capabilitiesFilter: []}); + stubGetServiceJson(sandbox, { content: ArcGISMapLayerDataset.TilesOnlyDataset26918, accessTokenRequired: false }); + const result = ArcGisUtilities.validateSource({ source: getSampleSource()!, capabilitiesFilter: [] }); expect((await result).status).to.equals(MapLayerSourceStatus.InvalidCoordinateSystem); }); it("should validate url", async () => { - let status = ArcGisUtilities.validateUrl("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", "MapServer"); + let status = ArcGisUtilities.validateUrl( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", + "MapServer", + ); expect(status).to.equals(MapLayerSourceStatus.Valid); - status = ArcGisUtilities.validateUrl("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", "mapserver"); + status = ArcGisUtilities.validateUrl( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", + "mapserver", + ); expect(status).to.equals(MapLayerSourceStatus.Valid); - status = ArcGisUtilities.validateUrl("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/test/PhillyCityLandmarks/MapServer", "mapserver"); + status = ArcGisUtilities.validateUrl( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/test/PhillyCityLandmarks/MapServer", + "mapserver", + ); expect(status).to.equals(MapLayerSourceStatus.Valid); - status = ArcGisUtilities.validateUrl("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", "FeatureServer"); + status = ArcGisUtilities.validateUrl( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyCityLandmarks/MapServer", + "FeatureServer", + ); expect(status).to.equals(MapLayerSourceStatus.IncompatibleFormat); - status = ArcGisUtilities.validateUrl("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/restXYZ/services/PhillyCityLandmarks/MapServer", "FeatureServer"); + status = ArcGisUtilities.validateUrl( + "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/restXYZ/services/PhillyCityLandmarks/MapServer", + "FeatureServer", + ); expect(status).to.equals(MapLayerSourceStatus.InvalidUrl); - }); }); diff --git a/core/frontend/src/test/tile/map/FeatureGraphicsRenderer.test.ts b/core/frontend/src/test/tile/map/FeatureGraphicsRenderer.test.ts index 364012bbd312..ff0ab82e6d1e 100644 --- a/core/frontend/src/test/tile/map/FeatureGraphicsRenderer.test.ts +++ b/core/frontend/src/test/tile/map/FeatureGraphicsRenderer.test.ts @@ -3,19 +3,26 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Cartographic, DisplayStyle3dProps, EcefLocation, EmptyLocalization, GeoCoordinatesRequestProps, IModelConnectionProps, IModelCoordinatesRequestProps, PointWithStatus } from "@itwin/core-common"; +import { Guid, Mutable } from "@itwin/core-bentley"; +import { + Cartographic, + DisplayStyle3dProps, + EcefLocation, + EmptyLocalization, + GeoCoordinatesRequestProps, + IModelConnectionProps, + IModelCoordinatesRequestProps, + PointWithStatus, +} from "@itwin/core-common"; +import { Loop, Point3d, Range3d, Transform, XYZProps } from "@itwin/core-geometry"; import chai, { expect } from "chai"; import chaiAsPromised from "chai-as-promised"; import sinon from "sinon"; +import { BackgroundMapGeometry, DisplayStyle3dState, GraphicLineString, ScreenViewport, ViewState3d } from "../../../core-frontend"; +import { GeoServices, GeoServicesOptions } from "../../../GeoServices"; import { IModelApp } from "../../../IModelApp"; -import { - FeatureGraphicsRenderer, -} from "../../../tile/internal"; import { BlankConnection, IModelConnection } from "../../../IModelConnection"; -import { GeoServices, GeoServicesOptions } from "../../../GeoServices"; -import { Guid, Mutable } from "@itwin/core-bentley"; -import { Loop, Point3d, Range3d, Transform, XYZProps } from "@itwin/core-geometry"; -import { BackgroundMapGeometry, DisplayStyle3dState, GraphicLineString, ScreenViewport, ViewState3d } from "../../../core-frontend"; +import { FeatureGraphicsRenderer } from "../../../tile/internal"; import * as moq from "typemoq"; @@ -52,23 +59,25 @@ export class TestConnection extends BlankConnection { } }, }); - } public override getEcefTransform(): Transform { return Transform.identity; } - public override get noGcsDefined(): boolean { return this._noGcsDefined; } - public override get isClosed(): boolean { return false; } - + public override get noGcsDefined(): boolean { + return this._noGcsDefined; + } + public override get isClosed(): boolean { + return false; + } } const createImodelProps = () => { - return { + return { rootSubject: { name: "test-connection" }, projectExtents: new Range3d(-10000, -10000, -10000, 10000, 10000, 100), - ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: -75.152149, latitude: 39.9296167, height: 0 })), + ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: -75.152149, latitude: 39.9296167, height: 0 })), key: "", iTwinId: Guid.createValue(), }; @@ -118,21 +127,21 @@ const cloneCoords = (coords: XYZProps[]) => { }; const sampleGeoServicesProps = { - toIModelCoords: async ( request: IModelCoordinatesRequestProps) => cloneCoords(request.geoCoords), - fromIModelCoords: async ( request: GeoCoordinatesRequestProps) => cloneCoords(request.iModelCoords), + toIModelCoords: async (request: IModelCoordinatesRequestProps) => cloneCoords(request.geoCoords), + fromIModelCoords: async (request: GeoCoordinatesRequestProps) => cloneCoords(request.iModelCoords), }; const sampleiModelProps = { rootSubject: { name: "test-connection" }, projectExtents: new Range3d(-10, 10, -10, -10, 10, 100), - ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: -75.686694, latitude: 40.065757, height: 0 })), + ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: -75.686694, latitude: 40.065757, height: 0 })), key: "", iTwinId: Guid.createValue(), }; describe("FeatureGraphicsRenderer", () => { const sandbox = sinon.createSandbox(); - let viewportMock: ViewportMock|undefined; + let viewportMock: ViewportMock | undefined; beforeEach(async () => { await IModelApp.startup({ localization: new EmptyLocalization() }); viewportMock = new ViewportMock(); @@ -146,13 +155,17 @@ describe("FeatureGraphicsRenderer", () => { }); it("render non-filled paths correctly", async () => { - const renderer = new FeatureGraphicsRenderer({viewport: viewportMock!.object, crs: "webMercator"}); - const testLengths = [2,2]; + const renderer = new FeatureGraphicsRenderer({ viewport: viewportMock!.object, crs: "webMercator" }); + const testLengths = [2, 2]; const testCoords = [ - -8368830.26, 4866490.12, - -8368794.98, 4866483.84, - -8368804.29, 4866426.86, - -8368850.49, 4866434.57, + -8368830.26, + 4866490.12, + -8368794.98, + 4866483.84, + -8368804.29, + 4866426.86, + -8368850.49, + 4866434.57, ]; // We stub 'FeatureGraphicsRenderer.toSpatialFromEcf' to have the same input/output points, and simplify testing. We make sure @@ -170,21 +183,20 @@ describe("FeatureGraphicsRenderer", () => { expect(graphics.length).to.equals(2); for (const graphic of graphics) { expect(graphic.type).to.equals("linestring"); - const linestring = graphic as GraphicLineString; + const linestring = graphic as GraphicLineString; expect(linestring.points.length).to.equals(2); for (const pt of linestring.points) { expect(Math.abs(pt.x - testCoords[i++])).to.be.lessThan(tolerance); expect(Math.abs(pt.y - testCoords[i++])).to.be.lessThan(tolerance); } - } expect(graphics[0].type).to.equals("linestring"); - expect((graphics[0] as any).points.length ).to.equals(2); + expect((graphics[0] as any).points.length).to.equals(2); expect(toSpatialStub.called).to.be.true; }); it("render filled paths correctly", async () => { - const renderer = new FeatureGraphicsRenderer({viewport: viewportMock!.object, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: viewportMock!.object, crs: "webMercator" }); // We stub 'FeatureGraphicsRenderer.toSpatialFromEcf' to have the same input/output points, and simplify testing. We make sure // 'toSpatialFromEcf' is being called. @@ -193,17 +205,24 @@ describe("FeatureGraphicsRenderer", () => { }); const testCoords = [ - -8368830.26, 4866490.12, - -8368794.98, 4866483.84, - -8368804.29, 4866426.86, - -8368850.49, 4866434.57, - -8368853.17, 4866437.99, - -8368844.2, 4866492.5, - -8368830.26, 4866490.12, + -8368830.26, + 4866490.12, + -8368794.98, + 4866483.84, + -8368804.29, + 4866426.86, + -8368850.49, + 4866434.57, + -8368853.17, + 4866437.99, + -8368844.2, + 4866492.5, + -8368830.26, + 4866490.12, ]; // Make sure each render call makes translate into a single call to 'toIModelCoords' (i.e. points should NOT be converted one by one) - await renderer.renderPath([testCoords.length/2], testCoords, true, 2, false); + await renderer.renderPath([testCoords.length / 2], testCoords, true, 2, false); const graphics = renderer.moveGraphics(); expect(graphics.length).to.equals(1); expect(graphics[0].type).to.equals("loop"); @@ -213,18 +232,17 @@ describe("FeatureGraphicsRenderer", () => { let i = 0; const tolerance = 0.0000001; for (const child of loop.children) { - expect(Math.abs(child.startPoint().x - testCoords[i++])).to.be.lessThan(tolerance); - expect(Math.abs(child.startPoint().y - testCoords[i++])).to.be.lessThan(tolerance); - expect(Math.abs(child.endPoint().x - testCoords[i])).to.be.lessThan(tolerance); - expect(Math.abs(child.endPoint().y - testCoords[i+1])).to.be.lessThan(tolerance); + expect(Math.abs(child.startPoint().x - testCoords[i++])).to.be.lessThan(tolerance); + expect(Math.abs(child.startPoint().y - testCoords[i++])).to.be.lessThan(tolerance); + expect(Math.abs(child.endPoint().x - testCoords[i])).to.be.lessThan(tolerance); + expect(Math.abs(child.endPoint().y - testCoords[i + 1])).to.be.lessThan(tolerance); } expect(toSpatialStub.called).to.be.true; - }); it("render point correctly", async () => { - const renderer = new FeatureGraphicsRenderer({viewport: viewportMock!.object, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: viewportMock!.object, crs: "webMercator" }); // We stub 'FeatureGraphicsRenderer.toSpatialFromEcf' to have the same input/output points, and simplify testing. We make sure // 'toSpatialFromEcf' is being called. @@ -233,11 +251,12 @@ describe("FeatureGraphicsRenderer", () => { }); const testCoords = [ - -8368830.26, 4866490.12, + -8368830.26, + 4866490.12, ]; // Make sure each render call makes translate into a single call to 'toIModelCoords' (i.e. points should NOT be converted one by one) - await renderer.renderPoint([testCoords.length/2], testCoords, 2, false); + await renderer.renderPoint([testCoords.length / 2], testCoords, 2, false); const graphics = renderer.moveGraphics(); expect(graphics.length).to.equals(1); expect(graphics[0].type).to.equals("pointstring"); @@ -245,11 +264,10 @@ describe("FeatureGraphicsRenderer", () => { expect(points.length).to.equals(1); let i = 0; const tolerance = 0.0000001; - expect(Math.abs(points[0].x - testCoords[i++])).to.be.lessThan(tolerance); - expect(Math.abs(points[0].y - testCoords[i++])).to.be.lessThan(tolerance); + expect(Math.abs(points[0].x - testCoords[i++])).to.be.lessThan(tolerance); + expect(Math.abs(points[0].y - testCoords[i++])).to.be.lessThan(tolerance); expect(toSpatialStub.called).to.be.true; - }); it("coordinates reprojection RPC calls get batched if GCS defined", async () => { @@ -258,19 +276,27 @@ describe("FeatureGraphicsRenderer", () => { viewportMock!.imodel = connection; viewportMock!.displayStyle = new DisplayStyle3dState(styleProps, connection); viewportMock!.setup(); - const renderer = new FeatureGraphicsRenderer({viewport: viewportMock!.object, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: viewportMock!.object, crs: "webMercator" }); - const testLengths = [4,4]; + const testLengths = [4, 4]; const testCoords = [ - -8425593.033762699, 4875527.516249214, - -8425446.432177741, 4875531.597149869, - -8425405.243966147,4875392.564639658, - -8425582.24195651, 4875371.3119488945, + -8425593.033762699, + 4875527.516249214, + -8425446.432177741, + 4875531.597149869, + -8425405.243966147, + 4875392.564639658, + -8425582.24195651, + 4875371.3119488945, // duplicate - -8425593.033762699, 4875527.516249214, - -8425446.432177741, 4875531.597149869, - -8425405.243966147,4875392.564639658, - -8425582.24195651, 4875371.3119488945, + -8425593.033762699, + 4875527.516249214, + -8425446.432177741, + 4875531.597149869, + -8425405.243966147, + 4875392.564639658, + -8425582.24195651, + 4875371.3119488945, ]; // Make sure each render call makes translate into a single call to 'toIModelCoords' (i.e. points should NOT be converted one by one) @@ -286,7 +312,6 @@ describe("FeatureGraphicsRenderer", () => { connection.toIModelCoordsCount = 0; await renderer.renderPoint(testLengths, testCoords, 2, false); expect(connection.toIModelCoordsCount).to.equals(1); - }); it("coordinates reprojection RPC calls get batched if GCS defined", async () => { @@ -299,23 +324,30 @@ describe("FeatureGraphicsRenderer", () => { viewportMock!.imodel = connection; viewportMock!.displayStyle = new DisplayStyle3dState(styleProps, connection); viewportMock!.setup(); - const renderer = new FeatureGraphicsRenderer({viewport: viewportMock!.object, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: viewportMock!.object, crs: "webMercator" }); - const testLengths = [4,4]; + const testLengths = [4, 4]; const testCoords = [ - -8425593.033762699, 4875527.516249214, - -8425446.432177741, 4875531.597149869, - -8425405.243966147,4875392.564639658, - -8425582.24195651, 4875371.3119488945, + -8425593.033762699, + 4875527.516249214, + -8425446.432177741, + 4875531.597149869, + -8425405.243966147, + 4875392.564639658, + -8425582.24195651, + 4875371.3119488945, // duplicate - -8425593.033762699, 4875527.516249214, - -8425446.432177741, 4875531.597149869, - -8425405.243966147,4875392.564639658, - -8425582.24195651, 4875371.3119488945, + -8425593.033762699, + 4875527.516249214, + -8425446.432177741, + 4875531.597149869, + -8425405.243966147, + 4875392.564639658, + -8425582.24195651, + 4875371.3119488945, ]; await renderer.renderPath(testLengths, testCoords, false, 2, false); expect(connection.toIModelCoordsCount).to.equals(0); }); - }); diff --git a/core/frontend/src/test/tile/map/ImageryTileTree.test.ts b/core/frontend/src/test/tile/map/ImageryTileTree.test.ts index 24996410a4db..6893113bfd8a 100644 --- a/core/frontend/src/test/tile/map/ImageryTileTree.test.ts +++ b/core/frontend/src/test/tile/map/ImageryTileTree.test.ts @@ -6,17 +6,21 @@ import { ImageMapLayerProps, ImageMapLayerSettings } from "@itwin/core-common"; import { expect } from "chai"; import * as sinon from "sinon"; +import { IModelApp } from "../../../IModelApp"; +import { IModelConnection } from "../../../IModelConnection"; import { MockRender } from "../../../render/MockRender"; -import { createBlankConnection } from "../../createBlankConnection"; import { ImageryMapLayerTreeReference } from "../../../tile/map/ImageryTileTree"; -import { IModelConnection } from "../../../IModelConnection"; import { ImageryMapLayerFormat } from "../../../tile/map/MapLayerImageryFormats"; import { MapLayerImageryProvider } from "../../../tile/map/MapLayerImageryProvider"; -import { IModelApp } from "../../../IModelApp"; +import { createBlankConnection } from "../../createBlankConnection"; class CustomProvider extends MapLayerImageryProvider { - public override async constructUrl(_row: number, _column: number, _zoomLevel: number) { return this._settings.url;} - public override async initialize(): Promise {return;} + public override async constructUrl(_row: number, _column: number, _zoomLevel: number) { + return this._settings.url; + } + public override async initialize(): Promise { + return; + } } class BaseCustomFormat extends ImageryMapLayerFormat { @@ -46,10 +50,9 @@ interface DatasetEntry { } describe("ImageryTileTree", () => { - let imodel: IModelConnection; - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await MockRender.App.startup(); imodel = createBlankConnection(); IModelApp.mapLayerFormatRegistry.register(CustomFormat1); @@ -62,14 +65,19 @@ describe("ImageryTileTree", () => { }); it("tree supplier", async () => { - const baseProps: ImageMapLayerProps = { formatId: "Custom1", url: "https://dummy.com", name: "CustomLayer", subLayers: [{name: "sub0", visible: true}]}; + const baseProps: ImageMapLayerProps = { + formatId: "Custom1", + url: "https://dummy.com", + name: "CustomLayer", + subLayers: [{ name: "sub0", visible: true }], + }; const dataset: DatasetEntry[] = [ - {lhs: {...baseProps}, rhs: {...baseProps}, expectSameTileTree:true}, - {lhs: {...baseProps, name: "someName"}, rhs: {...baseProps}, expectSameTileTree:true}, - {lhs: {...baseProps, url: "https://someUrl.com"}, rhs: {...baseProps}, expectSameTileTree:false}, - {lhs: {...baseProps, formatId:"Custom2"}, rhs: {...baseProps}, expectSameTileTree:false}, - {lhs: {...baseProps, subLayers: [{name: "sub0", visible: false}]}, rhs: {...baseProps}, expectSameTileTree:false}, - {lhs: {...baseProps, subLayers: [{name: "sub1", visible: true}]}, rhs: {...baseProps}, expectSameTileTree:false}, + { lhs: { ...baseProps }, rhs: { ...baseProps }, expectSameTileTree: true }, + { lhs: { ...baseProps, name: "someName" }, rhs: { ...baseProps }, expectSameTileTree: true }, + { lhs: { ...baseProps, url: "https://someUrl.com" }, rhs: { ...baseProps }, expectSameTileTree: false }, + { lhs: { ...baseProps, formatId: "Custom2" }, rhs: { ...baseProps }, expectSameTileTree: false }, + { lhs: { ...baseProps, subLayers: [{ name: "sub0", visible: false }] }, rhs: { ...baseProps }, expectSameTileTree: false }, + { lhs: { ...baseProps, subLayers: [{ name: "sub1", visible: true }] }, rhs: { ...baseProps }, expectSameTileTree: false }, ]; for (const entry of dataset) { const settingsLhs = ImageMapLayerSettings.fromJSON(entry.lhs); diff --git a/core/frontend/src/test/tile/map/MapLayerFormat.test.ts b/core/frontend/src/test/tile/map/MapLayerFormat.test.ts index 2083bd6087c2..0bc4cb285837 100644 --- a/core/frontend/src/test/tile/map/MapLayerFormat.test.ts +++ b/core/frontend/src/test/tile/map/MapLayerFormat.test.ts @@ -3,15 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { - ImageryMapLayerTreeReference, - MapLayerFormat, - MapLayerFormatRegistry, - MapLayerImageryProvider, -} from "../../../tile/internal"; import { ImageMapLayerProps, ImageMapLayerSettings } from "@itwin/core-common"; +import { expect } from "chai"; import { IModelConnection } from "../../../IModelConnection"; +import { ImageryMapLayerTreeReference, MapLayerFormat, MapLayerFormatRegistry, MapLayerImageryProvider } from "../../../tile/internal"; class TestMapLayerFormat extends MapLayerFormat { public static override formatId = "TestMapLayerFormat"; @@ -31,7 +26,7 @@ class TestMapLayerImageryProvider extends MapLayerImageryProvider { } } -class TestMapLayerSettings extends ImageMapLayerSettings { } +class TestMapLayerSettings extends ImageMapLayerSettings {} const testMapLayer = { name: "TestName", diff --git a/core/frontend/src/test/tile/map/MapLayerImageryFormats.test.ts b/core/frontend/src/test/tile/map/MapLayerImageryFormats.test.ts index bb924c39fbd7..ffaa6875ec34 100644 --- a/core/frontend/src/test/tile/map/MapLayerImageryFormats.test.ts +++ b/core/frontend/src/test/tile/map/MapLayerImageryFormats.test.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { EmptyLocalization, ImageMapLayerSettings } from "@itwin/core-common"; -import * as sinon from "sinon"; import { assert, expect } from "chai"; +import * as sinon from "sinon"; +import { IModelApp } from "../../../IModelApp"; import { ArcGISMapLayerImageryProvider, ArcGisUtilities, @@ -19,13 +20,14 @@ import { WmsMapLayerImageryProvider, WmtsMapLayerImageryProvider, } from "../../../tile/internal"; -import { IModelApp } from "../../../IModelApp"; -const getSampleLayerSettings = ((formatId: string) => { +const getSampleLayerSettings = (formatId: string) => { return ImageMapLayerSettings.fromJSON({ - formatId, url: "https://localhost/service", name: `Test ${formatId}`, + formatId, + url: "https://localhost/service", + name: `Test ${formatId}`, }); -}); +}; describe("MapLayerImageryFormats", () => { const sandbox = sinon.createSandbox(); @@ -43,7 +45,6 @@ describe("MapLayerImageryFormats", () => { it("should create proper provider", () => { const registry = new MapLayerFormatRegistry({}); internalMapLayerImageryFormats.forEach((imageryFormat) => { - const layerSettings = getSampleLayerSettings(imageryFormat.formatId); expect(layerSettings).to.not.undefined; if (!layerSettings) @@ -84,11 +85,11 @@ describe("MapLayerImageryFormats", () => { }); const testValidateSource = async (source: MapLayerSource, url: string) => { - const stub = sandbox.stub(window, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { + const stub = sandbox.stub(window, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { return new Response(); }); const urlObj = new URL(url); - await IModelApp.mapLayerFormatRegistry.validateSource({source}); + await IModelApp.mapLayerFormatRegistry.validateSource({ source }); expect(stub.called).to.be.true; expect(stub.getCall(0).args[0]).to.equals(urlObj.toString()); @@ -98,14 +99,14 @@ describe("MapLayerImageryFormats", () => { source.unsavedQueryParams = {}; param1.forEach((value: string, key: string) => source.savedQueryParams![key] = value); param2.forEach((value: string, key: string) => source.unsavedQueryParams![key] = value); - await IModelApp.mapLayerFormatRegistry.validateSource({source, ignoreCache: true}); + await IModelApp.mapLayerFormatRegistry.validateSource({ source, ignoreCache: true }); expect(stub.called).to.be.true; expect(stub.getCall(1).args[0]).to.equals(urlObj.toString()); }; it("validate WMS source with proper URL", async () => { const url = "https://sub.service.com/service"; - const source = MapLayerSource.fromJSON({formatId:"WMS", name: "", url}); + const source = MapLayerSource.fromJSON({ formatId: "WMS", name: "", url }); if (!source) { assert.fail("Failed to create source"); return; @@ -115,7 +116,7 @@ describe("MapLayerImageryFormats", () => { it("validate WMTS source with proper URL", async () => { const url = "https://sub.service.com/service"; - const source = MapLayerSource.fromJSON({formatId:"WMTS", name: "", url}); + const source = MapLayerSource.fromJSON({ formatId: "WMTS", name: "", url }); if (!source) { assert.fail("Failed to create source"); return; @@ -126,7 +127,7 @@ describe("MapLayerImageryFormats", () => { it("validate ArcGIS source with proper URL", async () => { const url = "https://sub.service.com/service"; - const source = MapLayerSource.fromJSON({formatId:"ArcGIS", name: "", url}); + const source = MapLayerSource.fromJSON({ formatId: "ArcGIS", name: "", url }); if (!source) { assert.fail("Failed to create source"); return; diff --git a/core/frontend/src/test/tile/map/MapLayerSources.test.ts b/core/frontend/src/test/tile/map/MapLayerSources.test.ts index 2d0cd2c206ca..21617bd5a88a 100644 --- a/core/frontend/src/test/tile/map/MapLayerSources.test.ts +++ b/core/frontend/src/test/tile/map/MapLayerSources.test.ts @@ -13,13 +13,12 @@ const sampleSourceJson = { url: "https://testserver/wms", transparentBackground: true, baseMap: true, - queryParams: {testParam : "testValue"}, + queryParams: { testParam: "testValue" }, }; describe("MapLayerSources", () => { - it("should create MapLayerSource with defaults", async () => { - const testSourceProps: MapLayerSourceProps = {name: sampleSourceJson.name, url: sampleSourceJson.url}; + const testSourceProps: MapLayerSourceProps = { name: sampleSourceJson.name, url: sampleSourceJson.url }; const sampleSource = MapLayerSource.fromJSON(testSourceProps); expect(sampleSource).to.not.undefined; expect(sampleSource!.formatId).to.equals("WMS"); @@ -30,7 +29,6 @@ describe("MapLayerSources", () => { }); it("should create MapLayerSource from MapLayerSourceProps", async () => { - let sampleSource = MapLayerSource.fromJSON(sampleSourceJson); expect(sampleSource).to.not.undefined; expect(sampleSource!.formatId).to.equals(sampleSourceJson.formatId); @@ -61,7 +59,7 @@ describe("MapLayerSources", () => { // Save props not part of of props sampleSource!.userName = "testUser"; sampleSource!.password = "testPassword"; - sampleSource!.unsavedQueryParams = {unsavedParam : "unsavedParamValue"}; + sampleSource!.unsavedQueryParams = { unsavedParam: "unsavedParamValue" }; expect(sampleSource).to.not.undefined; if (!sampleSource) @@ -84,7 +82,7 @@ describe("MapLayerSources", () => { expect(sampleSource.userName).to.equals(settings.userName); expect(sampleSource.password).to.equals(settings.password); expect(JSON.stringify(sampleSource.savedQueryParams)).to.equals(JSON.stringify(settings.savedQueryParams)); - expect( JSON.stringify(sampleSource.unsavedQueryParams)).to.equals(JSON.stringify(settings.unsavedQueryParams)); + expect(JSON.stringify(sampleSource.unsavedQueryParams)).to.equals(JSON.stringify(settings.unsavedQueryParams)); expect(settings.subLayers).to.not.undefined; expect(settings.subLayers.length).to.equals(subLayers.length); expect(settings.subLayers[0].name).to.equals(subLayers[0].name); @@ -97,7 +95,7 @@ describe("MapLayerSources", () => { // Save props not part of of props (should have no impact on resulting JSON) sampleSource!.userName = "testUser"; sampleSource!.password = "testPassword"; - sampleSource!.unsavedQueryParams = {unsavedParam : "unsavedParamValue"}; + sampleSource!.unsavedQueryParams = { unsavedParam: "unsavedParamValue" }; const sourceProps = sampleSource!.toJSON(); expect(sampleSourceJson.formatId).to.equals(sourceProps.formatId); @@ -105,6 +103,5 @@ describe("MapLayerSources", () => { expect(sampleSourceJson.url).to.equals(sourceProps.url); expect(sampleSourceJson.transparentBackground).to.equals(sourceProps.transparentBackground); expect(sampleSourceJson.queryParams).to.equals(sourceProps.queryParams); - }); }); diff --git a/core/frontend/src/test/tile/map/MapLayerTestUtilities.ts b/core/frontend/src/test/tile/map/MapLayerTestUtilities.ts index 0d52f317bbb0..2c59ee38ce83 100644 --- a/core/frontend/src/test/tile/map/MapLayerTestUtilities.ts +++ b/core/frontend/src/test/tile/map/MapLayerTestUtilities.ts @@ -6,27 +6,29 @@ import { ByteStream } from "@itwin/core-bentley"; export const createFakeTileResponse = (contentType: string, data?: Uint8Array) => { const test = { - headers: new Headers( { "content-type" : contentType}), + headers: new Headers({ "content-type": contentType }), arrayBuffer: async () => { return Promise.resolve(data ? ByteStream.fromUint8Array(data).arrayBuffer : undefined); }, status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need - return (test as Response ); + } as unknown; // By using unknown type, I can define parts of Response I really need + return (test as Response); }; export const fakeTextFetch = (sandbox: sinon.SinonSandbox, text: string) => { - return sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { - return Promise.resolve((({ - text: async () => text, - ok: true, - status: 200, - } as unknown) as Response)); + return sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { + return Promise.resolve( + ({ + text: async () => text, + ok: true, + status: 200, + } as unknown) as Response, + ); }); }; -export const indexedArrayFromUrlParams = (urlParams: URLSearchParams): {[key: string]: string} => { - const array: {[key: string]: string} = {}; +export const indexedArrayFromUrlParams = (urlParams: URLSearchParams): { [key: string]: string } => { + const array: { [key: string]: string } = {}; urlParams.forEach((value: string, key: string) => { array[key] = value; }); diff --git a/core/frontend/src/test/tile/map/TileUrlImageryProvider.test.ts b/core/frontend/src/test/tile/map/TileUrlImageryProvider.test.ts index e5189fc12793..15ce0893a910 100644 --- a/core/frontend/src/test/tile/map/TileUrlImageryProvider.test.ts +++ b/core/frontend/src/test/tile/map/TileUrlImageryProvider.test.ts @@ -5,15 +5,13 @@ import { ImageMapLayerSettings } from "@itwin/core-common"; import * as chai from "chai"; -import { - TileUrlImageryProvider, -} from "../../../tile/internal"; +import { TileUrlImageryProvider } from "../../../tile/internal"; describe("TileUrlImageryProvider", () => { it("construct proper tile url", async () => { - const settings = ImageMapLayerSettings.fromJSON({formatId:"TileUrl", name: "", url: "https://sub.service.com/service/{level}/{column}/{row}"}); + const settings = ImageMapLayerSettings.fromJSON({ formatId: "TileUrl", name: "", url: "https://sub.service.com/service/{level}/{column}/{row}" }); let provider = new TileUrlImageryProvider(settings); - let url = await provider.constructUrl(0,0,0); + let url = await provider.constructUrl(0, 0, 0); let refUrl = `https://sub.service.com/service/0/0/0`; chai.expect(url).to.equals(refUrl); @@ -21,18 +19,18 @@ describe("TileUrlImageryProvider", () => { const param2 = new URLSearchParams([["key2_1", "value2_2"], ["key2_2", "value2_2"]]); settings.savedQueryParams = {}; settings.unsavedQueryParams = {}; - param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); - param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); + param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); + param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); provider = new TileUrlImageryProvider(settings); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.equals(`${refUrl}?${param1.toString()}&${param2.toString()}`); - const settings2 = settings.clone({url: "https://sub.service.com/service/{level}/{column}/{row}?test=1"}); + const settings2 = settings.clone({ url: "https://sub.service.com/service/{level}/{column}/{row}?test=1" }); settings2.savedQueryParams = settings.savedQueryParams; settings2.unsavedQueryParams = settings.unsavedQueryParams; provider = new TileUrlImageryProvider(settings2); refUrl = `${refUrl}?test=1`; - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.equals(`${refUrl}&${param1.toString()}&${param2.toString()}`); }); }); diff --git a/core/frontend/src/test/tile/map/Wgs84Lods.ts b/core/frontend/src/test/tile/map/Wgs84Lods.ts index 813cdac5c404..fd8ee8aa3d97 100644 --- a/core/frontend/src/test/tile/map/Wgs84Lods.ts +++ b/core/frontend/src/test/tile/map/Wgs84Lods.ts @@ -8,49 +8,51 @@ // Manually verified with values here: https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Resolution_and_Scale // Scales Values are slightly off compared to what ArcGIS provide in their documentation (Im assuming some rounding errors) // https://developers.arcgis.com/documentation/mapping-apis-and-services/reference/zoom-levels-and-scale/ -export const wsg84Lods256px = -[{zoom:0,resolution:156543.03392804097,scale:591658710.9091313}, - {zoom:1,resolution:78271.51696402048,scale:295829355.45456564}, - {zoom:2,resolution:39135.75848201024,scale:147914677.72728282}, - {zoom:3,resolution:19567.87924100512,scale:73957338.86364141}, - {zoom:4,resolution:9783.93962050256,scale:36978669.431820706}, - {zoom:5,resolution:4891.96981025128,scale:18489334.715910353}, - {zoom:6,resolution:2445.98490512564,scale:9244667.357955176}, - {zoom:7,resolution:1222.99245256282,scale:4622333.678977588}, - {zoom:8,resolution:611.49622628141,scale:2311166.839488794}, - {zoom:9,resolution:305.748113140705,scale:1155583.419744397}, - {zoom:10,resolution:152.8740565703525,scale:577791.7098721985}, - {zoom:11,resolution:76.43702828517625,scale:288895.85493609926}, - {zoom:12,resolution:38.21851414258813,scale:144447.92746804963}, - {zoom:13,resolution:19.109257071294063,scale:72223.96373402482}, - {zoom:14,resolution:9.554628535647032,scale:36111.98186701241}, - {zoom:15,resolution:4.777314267823516,scale:18055.990933506204}, - {zoom:16,resolution:2.388657133911758,scale:9027.995466753102}, - {zoom:17,resolution:1.194328566955879,scale:4513.997733376551}, - {zoom:18,resolution:0.5971642834779395,scale:2256.9988666882755}, - {zoom:19,resolution:0.29858214173896974,scale:1128.4994333441377}, - {zoom:20,resolution:0.14929107086948487,scale:564.2497166720689}]; +export const wsg84Lods256px = [ + { zoom: 0, resolution: 156543.03392804097, scale: 591658710.9091313 }, + { zoom: 1, resolution: 78271.51696402048, scale: 295829355.45456564 }, + { zoom: 2, resolution: 39135.75848201024, scale: 147914677.72728282 }, + { zoom: 3, resolution: 19567.87924100512, scale: 73957338.86364141 }, + { zoom: 4, resolution: 9783.93962050256, scale: 36978669.431820706 }, + { zoom: 5, resolution: 4891.96981025128, scale: 18489334.715910353 }, + { zoom: 6, resolution: 2445.98490512564, scale: 9244667.357955176 }, + { zoom: 7, resolution: 1222.99245256282, scale: 4622333.678977588 }, + { zoom: 8, resolution: 611.49622628141, scale: 2311166.839488794 }, + { zoom: 9, resolution: 305.748113140705, scale: 1155583.419744397 }, + { zoom: 10, resolution: 152.8740565703525, scale: 577791.7098721985 }, + { zoom: 11, resolution: 76.43702828517625, scale: 288895.85493609926 }, + { zoom: 12, resolution: 38.21851414258813, scale: 144447.92746804963 }, + { zoom: 13, resolution: 19.109257071294063, scale: 72223.96373402482 }, + { zoom: 14, resolution: 9.554628535647032, scale: 36111.98186701241 }, + { zoom: 15, resolution: 4.777314267823516, scale: 18055.990933506204 }, + { zoom: 16, resolution: 2.388657133911758, scale: 9027.995466753102 }, + { zoom: 17, resolution: 1.194328566955879, scale: 4513.997733376551 }, + { zoom: 18, resolution: 0.5971642834779395, scale: 2256.9988666882755 }, + { zoom: 19, resolution: 0.29858214173896974, scale: 1128.4994333441377 }, + { zoom: 20, resolution: 0.14929107086948487, scale: 564.2497166720689 }, +]; // NOTE: Zoom0 = Zoom1 of 256px tiles -export const wsg84Lods512px = - [{zoom:0,resolution:78271.51696402048,scale:295829355.45456564}, - {zoom:1,resolution:39135.75848201024,scale:147914677.72728282}, - {zoom:2,resolution:19567.87924100512,scale:73957338.86364141}, - {zoom:3,resolution:9783.93962050256,scale:36978669.431820706}, - {zoom:4,resolution:4891.96981025128,scale:18489334.715910353}, - {zoom:5,resolution:2445.98490512564,scale:9244667.357955176}, - {zoom:6,resolution:1222.99245256282,scale:4622333.678977588}, - {zoom:7,resolution:611.49622628141,scale:2311166.839488794}, - {zoom:8,resolution:305.748113140705,scale:1155583.419744397}, - {zoom:9,resolution:152.8740565703525,scale:577791.7098721985}, - {zoom:10,resolution:76.43702828517625,scale:288895.85493609926}, - {zoom:11,resolution:38.21851414258813,scale:144447.92746804963}, - {zoom:12,resolution:19.109257071294063,scale:72223.96373402482}, - {zoom:13,resolution:9.554628535647032,scale:36111.98186701241}, - {zoom:14,resolution:4.777314267823516,scale:18055.990933506204}, - {zoom:15,resolution:2.388657133911758,scale:9027.995466753102}, - {zoom:16,resolution:1.194328566955879,scale:4513.997733376551}, - {zoom:17,resolution:0.5971642834779395,scale:2256.9988666882755}, - {zoom:18,resolution:0.29858214173896974,scale:1128.4994333441377}, - {zoom:19,resolution:0.14929107086948487,scale:564.2497166720689}, - {zoom:20,resolution:0.07464553543474244,scale:282.12485833603444}]; +export const wsg84Lods512px = [ + { zoom: 0, resolution: 78271.51696402048, scale: 295829355.45456564 }, + { zoom: 1, resolution: 39135.75848201024, scale: 147914677.72728282 }, + { zoom: 2, resolution: 19567.87924100512, scale: 73957338.86364141 }, + { zoom: 3, resolution: 9783.93962050256, scale: 36978669.431820706 }, + { zoom: 4, resolution: 4891.96981025128, scale: 18489334.715910353 }, + { zoom: 5, resolution: 2445.98490512564, scale: 9244667.357955176 }, + { zoom: 6, resolution: 1222.99245256282, scale: 4622333.678977588 }, + { zoom: 7, resolution: 611.49622628141, scale: 2311166.839488794 }, + { zoom: 8, resolution: 305.748113140705, scale: 1155583.419744397 }, + { zoom: 9, resolution: 152.8740565703525, scale: 577791.7098721985 }, + { zoom: 10, resolution: 76.43702828517625, scale: 288895.85493609926 }, + { zoom: 11, resolution: 38.21851414258813, scale: 144447.92746804963 }, + { zoom: 12, resolution: 19.109257071294063, scale: 72223.96373402482 }, + { zoom: 13, resolution: 9.554628535647032, scale: 36111.98186701241 }, + { zoom: 14, resolution: 4.777314267823516, scale: 18055.990933506204 }, + { zoom: 15, resolution: 2.388657133911758, scale: 9027.995466753102 }, + { zoom: 16, resolution: 1.194328566955879, scale: 4513.997733376551 }, + { zoom: 17, resolution: 0.5971642834779395, scale: 2256.9988666882755 }, + { zoom: 18, resolution: 0.29858214173896974, scale: 1128.4994333441377 }, + { zoom: 19, resolution: 0.14929107086948487, scale: 564.2497166720689 }, + { zoom: 20, resolution: 0.07464553543474244, scale: 282.12485833603444 }, +]; diff --git a/core/frontend/src/test/tile/map/WmsCapabilities.test.ts b/core/frontend/src/test/tile/map/WmsCapabilities.test.ts index 8ca29faaea17..90c64c3e1fb4 100644 --- a/core/frontend/src/test/tile/map/WmsCapabilities.test.ts +++ b/core/frontend/src/test/tile/map/WmsCapabilities.test.ts @@ -18,7 +18,6 @@ describe("WmsCapabilities", () => { }); it("should parse WMS 1.1.1 capabilities", async () => { - const response = await fetch("assets/wms_capabilities/mapproxy_111.xml"); const text = await response.text(); fakeTextFetch(sandbox, text); @@ -40,7 +39,7 @@ describe("WmsCapabilities", () => { return; expect(subLayers?.length).to.equals(mapProxyDatasetNbLayers); - const subLayerNames = subLayers.map((sub)=>sub.name); + const subLayerNames = subLayers.map((sub) => sub.name); const subLayersCrs = capabilities.getSubLayersCrs(subLayerNames); expect(subLayersCrs).to.not.undefined; if (subLayersCrs === undefined) @@ -72,7 +71,7 @@ describe("WmsCapabilities", () => { return; expect(subLayers?.length).to.equals(mapProxyDatasetNbLayers); - const subLayerNames = subLayers.map((sub)=>sub.name); + const subLayerNames = subLayers.map((sub) => sub.name); const subLayersCrs = capabilities.getSubLayersCrs(subLayerNames); expect(subLayersCrs).to.not.undefined; if (subLayersCrs === undefined) @@ -80,22 +79,19 @@ describe("WmsCapabilities", () => { for (const subLayerCrs of subLayersCrs.values()) { expect(subLayerCrs).to.include("EPSG:4326"); } - }); it("should request proper URL", async () => { - - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { return new Response(); }); const sampleUrl = "https://service.server.com/rest/WMS"; const params = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"]]); - const queryParams: {[key: string]: string} = {}; - params.forEach((value: string, key: string) => queryParams[key] = value); + const queryParams: { [key: string]: string } = {}; + params.forEach((value: string, key: string) => queryParams[key] = value); await WmsCapabilities.create(sampleUrl, undefined, true, queryParams); expect(fetchStub.calledOnce).to.be.true; const firstCall = fetchStub.getCalls()[0]; expect(firstCall.args[0]).to.equals(`${sampleUrl}?request=GetCapabilities&service=WMS&${params.toString()}`); }); - }); diff --git a/core/frontend/src/test/tile/map/WmsMapLayerImageryProvider.test.ts b/core/frontend/src/test/tile/map/WmsMapLayerImageryProvider.test.ts index e5613b9a7973..b9aeb7116fc3 100644 --- a/core/frontend/src/test/tile/map/WmsMapLayerImageryProvider.test.ts +++ b/core/frontend/src/test/tile/map/WmsMapLayerImageryProvider.test.ts @@ -4,8 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Cartographic, EmptyLocalization, ImageMapLayerSettings, MapLayerProps, MapSubLayerSettings, ServerError } from "@itwin/core-common"; -import * as sinon from "sinon"; +import { Point2d } from "@itwin/core-geometry"; import * as chai from "chai"; +import * as sinon from "sinon"; +import { IModelApp } from "../../../IModelApp"; +import { RequestBasicCredentials } from "../../../request/Request"; import { ImageryMapTileTree, MapCartoRectangle, @@ -17,9 +20,6 @@ import { WmtsCapabilities, WmtsMapLayerImageryProvider, } from "../../../tile/internal"; -import { IModelApp } from "../../../IModelApp"; -import { RequestBasicCredentials } from "../../../request/Request"; -import { Point2d } from "@itwin/core-geometry"; import { createFakeTileResponse, fakeTextFetch } from "./MapLayerTestUtilities"; const wmsSampleSource = { formatId: "WMS", url: "https://localhost/wms", name: "Test WMS" }; @@ -38,12 +38,11 @@ describe("WmsMapLayerImageryProvider", () => { }); it("construct proper tile url", async () => { - sandbox.stub(WmsMapLayerImageryProvider.prototype, "getCrsSupport" as any).callsFake(() => { - return {support3857: true, support4326: false}; + return { support3857: true, support4326: false }; }); sandbox.stub(WmsMapLayerImageryProvider.prototype, "getVisibleLayers" as any).callsFake(() => { - return [MapSubLayerSettings.fromJSON({name: "sublayer"})]; + return [MapSubLayerSettings.fromJSON({ name: "sublayer" })]; }); // stub BBOX to avoid any floating point related issues @@ -55,22 +54,23 @@ describe("WmsMapLayerImageryProvider", () => { return {} as WmsCapabilities; }); - const settings = ImageMapLayerSettings.fromJSON({formatId:"WMS", name: "", url: "https://sub.service.com/service"}); - let provider = new WmsMapLayerImageryProvider(settings); + const settings = ImageMapLayerSettings.fromJSON({ formatId: "WMS", name: "", url: "https://sub.service.com/service" }); + let provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - let url = await provider.constructUrl(0,0,0); - const refUrl = "https://sub.service.com/service?SERVICE=WMS&VERSION=undefined&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=TRUE&LAYERS=sublayer&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3857&STYLES=&BBOX=1,2,3,4"; + let url = await provider.constructUrl(0, 0, 0); + const refUrl = + "https://sub.service.com/service?SERVICE=WMS&VERSION=undefined&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=TRUE&LAYERS=sublayer&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3857&STYLES=&BBOX=1,2,3,4"; chai.expect(url).to.equals(refUrl); const param1 = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"]]); const param2 = new URLSearchParams([["key2_1", "value2_2"], ["key2_2", "value2_2"]]); settings.savedQueryParams = {}; settings.unsavedQueryParams = {}; - param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); - param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); + param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); + param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.equals(`${refUrl}&${param1.toString()}&${param2.toString()}`); settings.savedQueryParams = {}; @@ -78,17 +78,16 @@ describe("WmsMapLayerImageryProvider", () => { settings.unsavedQueryParams.SERVICE = "BAD"; provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.equals(refUrl); }); it("construct proper tooltip url", async () => { - sandbox.stub(WmsMapLayerImageryProvider.prototype, "getCrsSupport" as any).callsFake(() => { - return {support3857: true, support4326: false}; + return { support3857: true, support4326: false }; }); sandbox.stub(WmsMapLayerImageryProvider.prototype, "getVisibleLayers" as any).callsFake(() => { - return [MapSubLayerSettings.fromJSON({name: "sublayer"})]; + return [MapSubLayerSettings.fromJSON({ name: "sublayer" })]; }); sandbox.stub(WmsMapLayerImageryProvider.prototype, "getQueryableLayers" as any).callsFake(() => { @@ -100,21 +99,27 @@ describe("WmsMapLayerImageryProvider", () => { return "1,2,3,4"; }); - sandbox.stub(MapCartoRectangle.prototype, "worldToLocal" ).callsFake((point: Point2d, _result?: Point2d) => { + sandbox.stub(MapCartoRectangle.prototype, "worldToLocal").callsFake((point: Point2d, _result?: Point2d) => { return point; }); sandbox.stub(WmsCapabilities, "create").callsFake(async (_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) => { - return {featureInfoFormats: ["text/html"] } as WmsCapabilities; + return { featureInfoFormats: ["text/html"] } as WmsCapabilities; }); const stub = sandbox.stub(WmsMapLayerImageryProvider.prototype, "toolTipFromUrl" as any).callsFake(async () => { }); - const settings = ImageMapLayerSettings.fromJSON({formatId:"WMS", name: "", url: "https://sub.service.com/service"}); - const provider = new WmsMapLayerImageryProvider(settings); + const settings = ImageMapLayerSettings.fromJSON({ formatId: "WMS", name: "", url: "https://sub.service.com/service" }); + const provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - await provider.getToolTip([], new QuadId(0,0,0), Cartographic.createZero(), ({getTileRectangle: ()=> MapCartoRectangle.createZero()} as unknown) as ImageryMapTileTree); - const refUrl = "https://sub.service.com/service?SERVICE=WMS&VERSION=undefined&REQUEST=GetFeatureInfo&LAYERS=sublayer&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3857&BBOX=1,2,3,4&QUERY_LAYERS=sublayer&x=0&y=256&info_format=text/html"; + await provider.getToolTip( + [], + new QuadId(0, 0, 0), + Cartographic.createZero(), + ({ getTileRectangle: () => MapCartoRectangle.createZero() } as unknown) as ImageryMapTileTree, + ); + const refUrl = + "https://sub.service.com/service?SERVICE=WMS&VERSION=undefined&REQUEST=GetFeatureInfo&LAYERS=sublayer&WIDTH=256&HEIGHT=256&SRS=EPSG%3A3857&BBOX=1,2,3,4&QUERY_LAYERS=sublayer&x=0&y=256&info_format=text/html"; chai.expect(stub.called).to.be.true; chai.expect(stub.getCall(0).args[1]).to.equals(refUrl); @@ -122,10 +127,15 @@ describe("WmsMapLayerImageryProvider", () => { const param2 = new URLSearchParams([["key2_1", "value2_2"], ["key2_2", "value2_2"]]); settings.savedQueryParams = {}; settings.unsavedQueryParams = {}; - param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); - param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); + param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); + param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); - await provider.getToolTip([], new QuadId(0,0,0), Cartographic.createZero(), ({getTileRectangle: ()=> MapCartoRectangle.createZero()} as unknown)as ImageryMapTileTree); + await provider.getToolTip( + [], + new QuadId(0, 0, 0), + Cartographic.createZero(), + ({ getTileRectangle: () => MapCartoRectangle.createZero() } as unknown) as ImageryMapTileTree, + ); chai.expect(stub.called).to.be.true; chai.expect(stub.getCall(1).args[1]).to.equals(`${refUrl}&${param1.toString()}&${param2.toString()}`); @@ -136,10 +146,12 @@ describe("WmsMapLayerImageryProvider", () => { if (!settings) chai.assert.fail("Could not create settings"); - const createSub = sandbox.stub(WmsCapabilities, "create").callsFake(async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { - // eslint-disable-next-line no-throw-literal - throw { status: 401 }; - }); + const createSub = sandbox.stub(WmsCapabilities, "create").callsFake( + async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { + // eslint-disable-next-line no-throw-literal + throw { status: 401 }; + }, + ); const provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); chai.expect(createSub.calledOnce).to.true; @@ -147,14 +159,16 @@ describe("WmsMapLayerImageryProvider", () => { }); it("initialize() should handle 401 error from WmtsCapabilities", async () => { - const settings =ImageMapLayerSettings.fromJSON(wmsSampleSource); + const settings = ImageMapLayerSettings.fromJSON(wmsSampleSource); if (!settings) chai.assert.fail("Could not create settings"); - const createSub = sandbox.stub(WmtsCapabilities, "create").callsFake(async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { - // eslint-disable-next-line no-throw-literal - throw { status: 401 }; - }); + const createSub = sandbox.stub(WmtsCapabilities, "create").callsFake( + async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { + // eslint-disable-next-line no-throw-literal + throw { status: 401 }; + }, + ); const provider = new WmtsMapLayerImageryProvider(settings); await provider.initialize(); chai.expect(createSub.calledOnce).to.true; @@ -178,24 +192,26 @@ describe("WmsMapLayerImageryProvider", () => { if (!settings) chai.assert.fail("Could not create settings"); - sandbox.stub(WmtsCapabilities, "create").callsFake(async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { - throw { someError: "error" }; // eslint-disable-line no-throw-literal - }); + sandbox.stub(WmtsCapabilities, "create").callsFake( + async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { + throw { someError: "error" }; // eslint-disable-line no-throw-literal + }, + ); const provider = new WmtsMapLayerImageryProvider(settings); await chai.expect(provider.initialize()).to.be.rejectedWith(ServerError); }); it("loadTile should not throw and return appropriate object", async () => { - const settings =ImageMapLayerSettings.fromJSON(wmsSampleSource); + const settings = ImageMapLayerSettings.fromJSON(wmsSampleSource); if (!settings) chai.assert.fail("Could not create settings"); - sandbox.stub(WmsMapLayerImageryProvider.prototype, "constructUrl").callsFake(async function (_row: number, _column: number, _zoomLevel: number) { + sandbox.stub(WmsMapLayerImageryProvider.prototype, "constructUrl").callsFake(async function(_row: number, _column: number, _zoomLevel: number) { return "https://fake/url"; }); // Test with empty body - let makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + let makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { return Promise.resolve(createFakeTileResponse("image/png", undefined)); }); const provider = new WmsMapLayerImageryProvider(settings); @@ -204,7 +220,7 @@ describe("WmsMapLayerImageryProvider", () => { // test fake png makeTileRequestStub.restore(); - makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { return Promise.resolve(createFakeTileResponse("image/png", Uint8Array.from([0, 0, 0]))); }); tileData = await provider.loadTile(0, 0, 0); @@ -212,7 +228,7 @@ describe("WmsMapLayerImageryProvider", () => { // test fake jpg makeTileRequestStub.restore(); - makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { return Promise.resolve(createFakeTileResponse("image/jpeg", Uint8Array.from([0, 0, 0]))); }); @@ -221,12 +237,11 @@ describe("WmsMapLayerImageryProvider", () => { // test invalid content type makeTileRequestStub.restore(); - sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { return Promise.resolve(createFakeTileResponse("image/strangeFormat", Uint8Array.from([0, 0, 0]))); }); tileData = await provider.loadTile(0, 0, 0); chai.expect(tileData).to.undefined; - }); it("should create a GetMap requests URL using the right 'CRS'", async () => { @@ -235,10 +250,11 @@ describe("WmsMapLayerImageryProvider", () => { url: "https://localhost/wms", name: "Test WMS", subLayers: [ - {name: "continents", id:0, visible:true}, - {name: "continents2", id:1, visible:false}, - ]}; - let settings =ImageMapLayerSettings.fromJSON(layerPros); + { name: "continents", id: 0, visible: true }, + { name: "continents2", id: 1, visible: false }, + ], + }; + let settings = ImageMapLayerSettings.fromJSON(layerPros); if (!settings) chai.assert.fail("Could not create settings"); @@ -248,17 +264,17 @@ describe("WmsMapLayerImageryProvider", () => { let provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - let url = await provider.constructUrl(0,0,0); + let url = await provider.constructUrl(0, 0, 0); let urlObj = new URL(url); chai.expect(urlObj.searchParams.get("CRS")).to.equals("EPSG:4326"); // Mark 'continents' and 'continents2' visible, in that case the request // should still be in EPSG:4326 because continents is only available in in EPSG:4326 layerPros.subLayers![1].visible = true; - settings =ImageMapLayerSettings.fromJSON(layerPros); + settings = ImageMapLayerSettings.fromJSON(layerPros); provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); urlObj = new URL(url); chai.expect(urlObj.searchParams.get("CRS")).to.equals("EPSG:4326"); @@ -266,20 +282,20 @@ describe("WmsMapLayerImageryProvider", () => { // URL should now be in EPSG:3857 because continents2 can be displayed in [4326,3857], // and 3857 is our favorite CRS. layerPros.subLayers![0].visible = false; - settings =ImageMapLayerSettings.fromJSON(layerPros); + settings = ImageMapLayerSettings.fromJSON(layerPros); provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); urlObj = new URL(url); chai.expect(urlObj.searchParams.get("CRS")).to.equals("EPSG:3857"); // Mark 'continents' and 'continents2' non-visible... leaving nothing to display. // An empty URL should be created in that case layerPros.subLayers![1].visible = false; - settings =ImageMapLayerSettings.fromJSON(layerPros); + settings = ImageMapLayerSettings.fromJSON(layerPros); provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.be.empty; }); @@ -289,8 +305,9 @@ describe("WmsMapLayerImageryProvider", () => { url: "https://localhost/wms2", name: "Test WMS", subLayers: [ - {name: "Default", id:0, visible:true}, - ]}; + { name: "Default", id: 0, visible: true }, + ], + }; const settings = ImageMapLayerSettings.fromJSON(layerPros); if (!settings) chai.assert.fail("Could not create settings"); @@ -301,14 +318,14 @@ describe("WmsMapLayerImageryProvider", () => { const provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - const url = await provider.constructUrl(0,0,0); + const url = await provider.constructUrl(0, 0, 0); const urlObj = new URL(url); chai.expect(urlObj.searchParams.get("SRS")).to.equals("EPSG:4326"); const bbox = urlObj.searchParams.get("BBOX"); chai.expect(bbox).to.not.null; if (!bbox) return; - const bboxArray = bbox?.split(",").map((value)=>Number(value)); + const bboxArray = bbox?.split(",").map((value) => Number(value)); // check x/y axis is in the right order const p1 = Point2d.create(bboxArray[0], bboxArray[1]); @@ -325,9 +342,10 @@ describe("WmsMapLayerImageryProvider", () => { url: "https://localhost/wms3", name: "Test WMS", subLayers: [ - {name: "Default", id:0, visible:true}, - ]}; - const settings =ImageMapLayerSettings.fromJSON(layerPros); + { name: "Default", id: 0, visible: true }, + ], + }; + const settings = ImageMapLayerSettings.fromJSON(layerPros); if (!settings) chai.assert.fail("Could not create settings"); @@ -337,7 +355,7 @@ describe("WmsMapLayerImageryProvider", () => { const provider = new WmsMapLayerImageryProvider(settings); await provider.initialize(); - const url = await provider.constructUrl(0,0,0); + const url = await provider.constructUrl(0, 0, 0); const urlObj = new URL(url); // 1.3.0 uses CRS instead of SRS chai.expect(urlObj.searchParams.get("CRS")).to.equals("EPSG:4326"); @@ -347,7 +365,7 @@ describe("WmsMapLayerImageryProvider", () => { chai.expect(bbox).to.not.null; if (!bbox) return; - const bboxArray = bbox?.split(",").map((value)=>Number(value)); + const bboxArray = bbox?.split(",").map((value) => Number(value)); const p1 = Point2d.create(bboxArray[0], bboxArray[1]); const refPoint1 = Point2d.create(-85.05112878, -180); const p2 = Point2d.create(bboxArray[2], bboxArray[3]); @@ -357,18 +375,18 @@ describe("WmsMapLayerImageryProvider", () => { }); it("loadTile() should call IModelApp.notifications.outputMessage", async () => { - const settings =ImageMapLayerSettings.fromJSON(wmsSampleSource); + const settings = ImageMapLayerSettings.fromJSON(wmsSampleSource); if (!settings) chai.assert.fail("Could not create settings"); const provider = new WmsMapLayerImageryProvider(settings); const outputMessageSpy = sinon.spy(IModelApp.notifications, "outputMessage"); - sandbox.stub(WmsMapLayerImageryProvider.prototype, "constructUrl").callsFake(async function (_row: number, _column: number, _zoomLevel: number) { + sandbox.stub(WmsMapLayerImageryProvider.prototype, "constructUrl").callsFake(async function(_row: number, _column: number, _zoomLevel: number) { return "https://fake/url"; }); // Make the tile fetch fails with error 401 - let makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + let makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { // eslint-disable-next-line no-throw-literal throw { status: 401 }; }); @@ -386,7 +404,7 @@ describe("WmsMapLayerImageryProvider", () => { // Now lets have a successful tile request makeTileRequestStub.restore(); - makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { return Promise.resolve(createFakeTileResponse("image/png")); }); await provider.loadTile(0, 0, 0); @@ -395,7 +413,7 @@ describe("WmsMapLayerImageryProvider", () => { // .. and now a 401 failure makeTileRequestStub.restore(); - makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function (_url: string) { + makeTileRequestStub = sandbox.stub(MapLayerImageryProvider.prototype, "makeTileRequest").callsFake(async function(_url: string) { // eslint-disable-next-line no-throw-literal throw { status: 401 }; }); diff --git a/core/frontend/src/test/tile/map/WmtsCapabilities.test.ts b/core/frontend/src/test/tile/map/WmtsCapabilities.test.ts index a195f8bd1c3a..145b497fbc91 100644 --- a/core/frontend/src/test/tile/map/WmtsCapabilities.test.ts +++ b/core/frontend/src/test/tile/map/WmtsCapabilities.test.ts @@ -36,11 +36,15 @@ describe("WmtsCapabilities", () => { if (capabilities?.operationsMetadata?.getCapabilities?.getDcpHttp) { expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[0].constraintName).to.equals("GetEncoding"); expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[0].encoding).to.equals("RESTful"); - expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[0].url).to.equals("https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS/1.0.0/WMTSCapabilities.xml"); + expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[0].url).to.equals( + "https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS/1.0.0/WMTSCapabilities.xml", + ); expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[1].constraintName).to.equals("GetEncoding"); expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[1].encoding).to.equals("KVP"); - expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[1].url).to.equals("https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS?"); + expect(capabilities.operationsMetadata.getCapabilities.getDcpHttp[1].url).to.equals( + "https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS?", + ); } // Test GetTile operation metadata @@ -52,11 +56,15 @@ describe("WmtsCapabilities", () => { if (capabilities?.operationsMetadata?.getTile?.getDcpHttp) { expect(capabilities.operationsMetadata.getTile.getDcpHttp[0].constraintName).to.equals("GetEncoding"); expect(capabilities.operationsMetadata.getTile.getDcpHttp[0].encoding).to.equals("RESTful"); - expect(capabilities.operationsMetadata.getTile.getDcpHttp[0].url).to.equals("https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS/tile/1.0.0/"); + expect(capabilities.operationsMetadata.getTile.getDcpHttp[0].url).to.equals( + "https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS/tile/1.0.0/", + ); expect(capabilities.operationsMetadata.getTile.getDcpHttp[1].constraintName).to.equals("GetEncoding"); expect(capabilities.operationsMetadata.getTile.getDcpHttp[1].encoding).to.equals("KVP"); - expect(capabilities.operationsMetadata.getTile.getDcpHttp[1].url).to.equals("https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS?"); + expect(capabilities.operationsMetadata.getTile.getDcpHttp[1].url).to.equals( + "https://basemap.nationalmap.gov/arcgis/rest/services/USGSHydroCached/MapServer/WMTS?", + ); } // Check that no GetFeatureInfo has been configured @@ -119,7 +127,9 @@ describe("WmtsCapabilities", () => { expect(capabilities?.contents?.tileMatrixSets[0].tileMatrix[0].scaleDenominator).to.not.undefined; if (capabilities?.contents?.tileMatrixSets[0].tileMatrix[0].scaleDenominator) - expect(Math.abs(capabilities.contents.tileMatrixSets[0].tileMatrix[0].scaleDenominator - (5.590822640285016E8))).to.lessThan(SMALL_DECIMAL_DIFFERENCE); + expect(Math.abs(capabilities.contents.tileMatrixSets[0].tileMatrix[0].scaleDenominator - (5.590822640285016E8))).to.lessThan( + SMALL_DECIMAL_DIFFERENCE, + ); expect(capabilities?.contents?.tileMatrixSets[0].tileMatrix[0].topLeftCorner).to.not.undefined; if (capabilities?.contents?.tileMatrixSets[0].tileMatrix[0].topLeftCorner) @@ -202,7 +212,7 @@ describe("WmtsCapabilities", () => { expect(capabilities?.contents).to.not.undefined; // layer - expect(capabilities?.contents?.layers.length).to.equal(2); // this sample capabilities has 2 layers + expect(capabilities?.contents?.layers.length).to.equal(2); // this sample capabilities has 2 layers expect(capabilities?.contents?.layers[0].identifier).to.equal("etopo2"); // tileMatrixSetLinks @@ -233,7 +243,7 @@ describe("WmtsCapabilities", () => { // Check the layer styles expect(capabilities?.contents?.layers).to.not.undefined; - expect(capabilities?.contents?.layers.length).to.equal(1); // this sample capabilities has 2 layers + expect(capabilities?.contents?.layers.length).to.equal(1); // this sample capabilities has 2 layers expect(capabilities?.contents?.layers[0].title).to.equal("Base of Hooray Sandstone and Equivalents"); expect(capabilities?.contents?.layers[0].styles.length).to.equal(2); expect(capabilities?.contents?.layers[0].styles[0].identifier).to.equal("gab:gab_formation_elevation_equalised_histogram"); @@ -248,14 +258,13 @@ describe("WmtsCapabilities", () => { }); it("should request proper URL", async () => { - - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input: RequestInfo | URL, _init?: RequestInit) { + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input: RequestInfo | URL, _init?: RequestInit) { return new Response(); }); const sampleUrl = "https://service.server.com/rest/WMTS"; const searchParams = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"]]); - const queryParams: {[key: string]: string} = {}; - searchParams.forEach((value: string, key: string) => queryParams[key] = value); + const queryParams: { [key: string]: string } = {}; + searchParams.forEach((value: string, key: string) => queryParams[key] = value); await WmtsCapabilities.create(sampleUrl, undefined, true, queryParams); expect(fetchStub.calledOnce).to.be.true; const firstCall = fetchStub.getCalls()[0]; diff --git a/core/frontend/src/test/tile/map/WmtsMapLayerImageryProvider.test.ts b/core/frontend/src/test/tile/map/WmtsMapLayerImageryProvider.test.ts index f42cf89fb953..f130b616dbae 100644 --- a/core/frontend/src/test/tile/map/WmtsMapLayerImageryProvider.test.ts +++ b/core/frontend/src/test/tile/map/WmtsMapLayerImageryProvider.test.ts @@ -4,14 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { EmptyLocalization, ImageMapLayerSettings, ServerError } from "@itwin/core-common"; -import * as sinon from "sinon"; import * as chai from "chai"; -import { - WmtsCapabilities, - WmtsMapLayerImageryProvider, -} from "../../../tile/internal"; +import * as sinon from "sinon"; import { IModelApp } from "../../../IModelApp"; import { RequestBasicCredentials } from "../../../request/Request"; +import { WmtsCapabilities, WmtsMapLayerImageryProvider } from "../../../tile/internal"; const wmtsSampleSource = { formatId: "WMTS", url: "https://localhost/wmts", name: "Test WMTS" }; describe("WmtsMapLayerImageryProvider", () => { @@ -28,25 +25,29 @@ describe("WmtsMapLayerImageryProvider", () => { }); it("initialize() should handle unknown exception from WmtsCapabilities", async () => { - const settings =ImageMapLayerSettings.fromJSON(wmtsSampleSource); + const settings = ImageMapLayerSettings.fromJSON(wmtsSampleSource); if (!settings) chai.assert.fail("Could not create settings"); - sandbox.stub(WmtsCapabilities, "create").callsFake(async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { - throw { someError: "error" }; // eslint-disable-line no-throw-literal - }); + sandbox.stub(WmtsCapabilities, "create").callsFake( + async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { + throw { someError: "error" }; // eslint-disable-line no-throw-literal + }, + ); const provider = new WmtsMapLayerImageryProvider(settings); await chai.expect(provider.initialize()).to.be.rejectedWith(ServerError); }); it("initialize() should handle unknown exception from WmtsCapabilities", async () => { - const settings =ImageMapLayerSettings.fromJSON(wmtsSampleSource); + const settings = ImageMapLayerSettings.fromJSON(wmtsSampleSource); if (!settings) chai.assert.fail("Could not create settings"); - sandbox.stub(WmtsCapabilities, "create").callsFake(async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { - throw { someError: "error" }; // eslint-disable-line no-throw-literal - }); + sandbox.stub(WmtsCapabilities, "create").callsFake( + async function _(_url: string, _credentials?: RequestBasicCredentials, _ignoreCache?: boolean) { + throw { someError: "error" }; // eslint-disable-line no-throw-literal + }, + ); const provider = new WmtsMapLayerImageryProvider(settings); await chai.expect(provider.initialize()).to.be.rejectedWith(ServerError); }); @@ -55,28 +56,29 @@ describe("WmtsMapLayerImageryProvider", () => { const tileMatrixLevel0Identifier = "0"; const tileMatrixSetIdentifier = "default"; sandbox.stub(WmtsMapLayerImageryProvider.prototype, "getDisplayedTileMatrixSetAndLimits" as any).callsFake(() => { - const tileMatrixSet = { - tileMatrix: [{identifier: tileMatrixLevel0Identifier}], + const tileMatrixSet = { + tileMatrix: [{ identifier: tileMatrixLevel0Identifier }], identifier: tileMatrixSetIdentifier, }; - return {tileMatrixSet}; + return { tileMatrixSet }; }); - const settings = ImageMapLayerSettings.fromJSON({formatId:"WMS", name: "", url: "https://sub.service.com/service"}); + const settings = ImageMapLayerSettings.fromJSON({ formatId: "WMS", name: "", url: "https://sub.service.com/service" }); let provider = new WmtsMapLayerImageryProvider(settings); - let url = await provider.constructUrl(0,0,0); - const refUrl = `https://sub.service.com/service?Service=WMTS&Version=1.0.0&Request=GetTile&Format=image%2Fpng&layer=&TileMatrixSet=${tileMatrixSetIdentifier}&TileMatrix=${tileMatrixLevel0Identifier}&TileCol=0&TileRow=0`; + let url = await provider.constructUrl(0, 0, 0); + const refUrl = + `https://sub.service.com/service?Service=WMTS&Version=1.0.0&Request=GetTile&Format=image%2Fpng&layer=&TileMatrixSet=${tileMatrixSetIdentifier}&TileMatrix=${tileMatrixLevel0Identifier}&TileCol=0&TileRow=0`; chai.expect(url).to.equals(refUrl); const param1 = new URLSearchParams([["key1_1", "value1_1"], ["key1_2", "value1_2"]]); const param2 = new URLSearchParams([["key2_1", "value2_2"], ["key2_2", "value2_2"]]); settings.savedQueryParams = {}; settings.unsavedQueryParams = {}; - param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); - param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); + param1.forEach((value: string, key: string) => settings.savedQueryParams![key] = value); + param2.forEach((value: string, key: string) => settings.unsavedQueryParams![key] = value); provider = new WmtsMapLayerImageryProvider(settings); - url = await provider.constructUrl(0,0,0); + url = await provider.constructUrl(0, 0, 0); chai.expect(url).to.equals(`${refUrl}&${param1.toString()}&${param2.toString()}`); }); }); diff --git a/core/frontend/src/test/utils/webpack.config.js b/core/frontend/src/test/utils/webpack.config.js index a342c2a9d042..3f3bf581909b 100644 --- a/core/frontend/src/test/utils/webpack.config.js +++ b/core/frontend/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -57,8 +57,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -68,10 +68,10 @@ function createConfig(shouldInstrument) { include: frontendLib, exclude: path.join(frontendLib, "test"), use: { - loader: 'babel-loader', + loader: "babel-loader", options: { - plugins: ['babel-plugin-istanbul'] - } + plugins: ["babel-plugin-istanbul"], + }, }, enforce: "post", }); @@ -83,5 +83,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/core/frontend/src/test/worker/test-worker.ts b/core/frontend/src/test/worker/test-worker.ts index 2393cba2d270..7585112701bd 100644 --- a/core/frontend/src/test/worker/test-worker.ts +++ b/core/frontend/src/test/worker/test-worker.ts @@ -4,12 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { Feature, GeometryClass } from "@itwin/core-common"; +import { Point2d, Point3d } from "@itwin/core-geometry"; +import { GraphicDescription, GraphicDescriptionBuilder, GraphicType } from "../../common"; import { - GraphicDescription, GraphicDescriptionBuilder, GraphicType, -} from "../../common"; + GraphicDescriptionContextProps, + WorkerGraphicDescriptionContext, + WorkerGraphicDescriptionContextProps, +} from "../../common/render/GraphicDescriptionContext"; import { registerWorker } from "../../workers/RegisterWorker"; -import { Point2d, Point3d } from "@itwin/core-geometry"; -import { GraphicDescriptionContextProps, WorkerGraphicDescriptionContext, WorkerGraphicDescriptionContextProps } from "../../common/render/GraphicDescriptionContext"; export interface WorkerGraphic { description: GraphicDescription; @@ -81,7 +83,10 @@ registerWorker({ builder.activateFeature(new Feature(context.transientIds.getNext(), "0x123", GeometryClass.Primary)); builder.addShape2d([ - new Point2d(0, 0), new Point2d(10, 0), new Point2d(10, 5), new Point2d(0, 5), + new Point2d(0, 0), + new Point2d(10, 0), + new Point2d(10, 5), + new Point2d(0, 5), ], 2); builder.activateFeature(new Feature("0x456", context.transientIds.getNext())); diff --git a/core/frontend/src/test/worker/webpack.config.js b/core/frontend/src/test/worker/webpack.config.js index 298ec0f0259b..dfddbba698c8 100644 --- a/core/frontend/src/test/worker/webpack.config.js +++ b/core/frontend/src/test/worker/webpack.config.js @@ -14,7 +14,7 @@ module.exports = [{ mode: "production", entry: globSync( path.resolve(frontendLib, "esm/test/worker/test-worker.js"), - { windowsPathsNoEscape: true } + { windowsPathsNoEscape: true }, ), output: { path: path.resolve(frontendLib, "test"), @@ -27,7 +27,7 @@ module.exports = [{ test: /\.js$/, use: "source-map-loader", sideEffects: false, - enforce: "pre" + enforce: "pre", }, { test: /@itwin/, @@ -38,7 +38,7 @@ module.exports = [{ // Enable side effects for core-geometry. // Otherwise, Path and Loop which both extend CurveChain get defined before CurveChain is defined. sideEffects: true, - } + }, ], }, stats: "errors-only", @@ -46,4 +46,3 @@ module.exports = [{ nodeEnv: "production", }, }]; - diff --git a/core/frontend/src/tile/B3dmReader.ts b/core/frontend/src/tile/B3dmReader.ts index 00c2ade33eb7..e2e12111273c 100644 --- a/core/frontend/src/tile/B3dmReader.ts +++ b/core/frontend/src/tile/B3dmReader.ts @@ -7,15 +7,13 @@ */ import { ByteStream, Id64String, JsonUtils } from "@itwin/core-bentley"; -import { Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { B3dmHeader, ColorDef, ElementAlignedBox3d, Feature, FeatureTable, TileReadStatus } from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; +import { Point3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { GltfDataType, GltfMeshPrimitive } from "../common/gltf/GltfSchema"; import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { IModelConnection } from "../IModelConnection"; import { RenderSystem } from "../render/RenderSystem"; -import { GltfDataType, GltfMeshPrimitive } from "../common/gltf/GltfSchema"; -import { - BatchedTileIdMap, GltfBufferData, GltfReader, GltfReaderProps, GltfReaderResult, ShouldAbortReadGltf, -} from "./internal"; +import { BatchedTileIdMap, GltfBufferData, GltfReader, GltfReaderProps, GltfReaderResult, ShouldAbortReadGltf } from "./internal"; /** * Deserializes a tile in [b3dm](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification/TileFormats/Batched3DModel) format. @@ -26,16 +24,32 @@ export class B3dmReader extends GltfReader { private _colors?: Array; private readonly _modelId: Id64String; - public static create(stream: ByteStream, iModel: IModelConnection, modelId: Id64String, is3d: boolean, range: ElementAlignedBox3d, - system: RenderSystem, yAxisUp: boolean, isLeaf: boolean, tileCenter: Point3d, transformToRoot?: Transform, - isCanceled?: ShouldAbortReadGltf, idMap?: BatchedTileIdMap, deduplicateVertices=false): B3dmReader | undefined { + public static create( + stream: ByteStream, + iModel: IModelConnection, + modelId: Id64String, + is3d: boolean, + range: ElementAlignedBox3d, + system: RenderSystem, + yAxisUp: boolean, + isLeaf: boolean, + tileCenter: Point3d, + transformToRoot?: Transform, + isCanceled?: ShouldAbortReadGltf, + idMap?: BatchedTileIdMap, + deduplicateVertices = false, + ): B3dmReader | undefined { const header = new B3dmHeader(stream); if (!header.isValid) return undefined; let returnToCenterTransform, pseudoRtcBias; if (header.featureTableJson && Array.isArray(header.featureTableJson.RTC_CENTER)) { - returnToCenterTransform = Transform.createTranslationXYZ(header.featureTableJson.RTC_CENTER[0], header.featureTableJson.RTC_CENTER[1], header.featureTableJson.RTC_CENTER[2]); + returnToCenterTransform = Transform.createTranslationXYZ( + header.featureTableJson.RTC_CENTER[0], + header.featureTableJson.RTC_CENTER[1], + header.featureTableJson.RTC_CENTER[2], + ); } else { /** * This is a workaround for tiles generated by @@ -54,16 +68,50 @@ export class B3dmReader extends GltfReader { const props = GltfReaderProps.create(stream.nextBytes(header.length - stream.curPos), yAxisUp); const batchTableLength = header.featureTableJson ? JsonUtils.asInt(header.featureTableJson.BATCH_LENGTH, 0) : 0; - return undefined !== props ? new B3dmReader(props, iModel, modelId, is3d, system, range, isLeaf, batchTableLength, - transformToRoot, header.batchTableJson, isCanceled, idMap, pseudoRtcBias, deduplicateVertices) : undefined; + return undefined !== props ? + new B3dmReader( + props, + iModel, + modelId, + is3d, + system, + range, + isLeaf, + batchTableLength, + transformToRoot, + header.batchTableJson, + isCanceled, + idMap, + pseudoRtcBias, + deduplicateVertices, + ) : + undefined; } - private constructor(props: GltfReaderProps, iModel: IModelConnection, modelId: Id64String, is3d: boolean, system: RenderSystem, - private _range: ElementAlignedBox3d, private _isLeaf: boolean, private _batchTableLength: number, private _transformToRoot?: Transform, private _batchTableJson?: any - , shouldAbort?: ShouldAbortReadGltf, _idMap?: BatchedTileIdMap, private _pseudoRtcBias?: Vector3d, deduplicateVertices=false) { + private constructor( + props: GltfReaderProps, + iModel: IModelConnection, + modelId: Id64String, + is3d: boolean, + system: RenderSystem, + private _range: ElementAlignedBox3d, + private _isLeaf: boolean, + private _batchTableLength: number, + private _transformToRoot?: Transform, + private _batchTableJson?: any, + shouldAbort?: ShouldAbortReadGltf, + _idMap?: BatchedTileIdMap, + private _pseudoRtcBias?: Vector3d, + deduplicateVertices = false, + ) { super({ - props, iModel, system, shouldAbort, deduplicateVertices, - is2d: !is3d, idMap: _idMap, + props, + iModel, + system, + shouldAbort, + deduplicateVertices, + is2d: !is3d, + idMap: _idMap, }); this._modelId = modelId; } @@ -154,7 +202,10 @@ export class B3dmReader extends GltfReader { if (this._batchTableLength > 0 && undefined !== this._batchTableJson && undefined !== json.attributes) { const view = this.getBufferView(json.attributes, "_BATCHID"); let batchIds: undefined | GltfBufferData; - if (undefined !== view && (undefined !== (batchIds = view.toBufferData(GltfDataType.UInt32)) || undefined !== (batchIds = view.toBufferData(GltfDataType.Float)))) { + if ( + undefined !== view && + (undefined !== (batchIds = view.toBufferData(GltfDataType.UInt32)) || undefined !== (batchIds = view.toBufferData(GltfDataType.Float))) + ) { const indices = []; const { colors, colorMap } = mesh; let colorRemap: Uint32Array | undefined; @@ -173,7 +224,6 @@ export class B3dmReader extends GltfReader { colors.push(colorRemap[batchId]); } mesh.features.setIndices(indices); - } } else { mesh.features.add(new Feature(this._modelId), 1); diff --git a/core/frontend/src/tile/BatchedTileIdMap.ts b/core/frontend/src/tile/BatchedTileIdMap.ts index c3f49b77d63d..5045ff3c5670 100644 --- a/core/frontend/src/tile/BatchedTileIdMap.ts +++ b/core/frontend/src/tile/BatchedTileIdMap.ts @@ -49,7 +49,7 @@ export class BatchedTileIdMap implements BatchTableProperties { return typeof props === "object" ? props : undefined; } - public * entries(): Iterable<{ id: Id64String, properties: Record }> { + public *entries(): Iterable<{ id: Id64String, properties: Record }> { if (this._idMap) { for (const [id, properties] of this._idMap) { if (typeof properties === "object") { diff --git a/core/frontend/src/tile/CesiumAssetProvider.ts b/core/frontend/src/tile/CesiumAssetProvider.ts index 802842c41faf..c0b4ab281e7f 100644 --- a/core/frontend/src/tile/CesiumAssetProvider.ts +++ b/core/frontend/src/tile/CesiumAssetProvider.ts @@ -8,7 +8,7 @@ * @internal */ export class CesiumIonAssetProvider { - public static osmBuildingId="OSMBuildings"; + public static osmBuildingId = "OSMBuildings"; /** Return true if this is a supported url to this service provider */ public static isProviderUrl(url: string): boolean { return url.includes("$CesiumIonAsset="); diff --git a/core/frontend/src/tile/ClassifierTileTree.ts b/core/frontend/src/tile/ClassifierTileTree.ts index 83dae2d884d9..02ab95bec9df 100644 --- a/core/frontend/src/tile/ClassifierTileTree.ts +++ b/core/frontend/src/tile/ClassifierTileTree.ts @@ -7,17 +7,30 @@ */ import { compareNumbers, comparePossiblyUndefined, compareStrings, compareStringsOrUndefined, Id64, Id64String } from "@itwin/core-bentley"; import { - BatchType, ClassifierTileTreeId, iModelTileTreeIdToString, RenderMode, RenderSchedule, SpatialClassifier, ViewFlagsProperties, + BatchType, + ClassifierTileTreeId, + iModelTileTreeIdToString, + RenderMode, + RenderSchedule, + SpatialClassifier, + ViewFlagsProperties, } from "@itwin/core-common"; import { DisplayStyleState } from "../DisplayStyleState"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { GeometricModelState } from "../ModelState"; +import { ActiveSpatialClassifier, SpatialClassifiersState } from "../SpatialClassifiersState"; import { SceneContext } from "../ViewContext"; import { ViewState } from "../ViewState"; -import { ActiveSpatialClassifier, SpatialClassifiersState } from "../SpatialClassifiersState"; import { - DisclosedTileTreeSet, IModelTileTree, iModelTileTreeParamsFromJSON, TileTree, TileTreeLoadStatus, TileTreeOwner, TileTreeReference, TileTreeSupplier, + DisclosedTileTreeSet, + IModelTileTree, + iModelTileTreeParamsFromJSON, + TileTree, + TileTreeLoadStatus, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, } from "./internal"; interface ClassifierTreeId extends ClassifierTileTreeId { @@ -69,7 +82,11 @@ class ClassifierTreeSupplier implements TileTreeSupplier { return Id64.isValid(id.modelId) ? iModel.tiles.getTileTreeOwner(id, this) : this._nonexistentTreeOwner; } - public addModelsAnimatedByScript(modelIds: Set, scriptSourceId: Id64String, trees: Iterable<{ id: ClassifierTreeId, owner: TileTreeOwner }>): void { + public addModelsAnimatedByScript( + modelIds: Set, + scriptSourceId: Id64String, + trees: Iterable<{ id: ClassifierTreeId, owner: TileTreeOwner }>, + ): void { // Note: This is invoked when an element hosting a schedule script is updated - it doesn't care about frontend schedule scripts. for (const tree of trees) if (scriptSourceId === tree.id.animationId) @@ -89,7 +106,9 @@ export abstract class SpatialClassifierTileTreeReference extends TileTreeReferen public abstract get isPlanar(): boolean; public abstract get activeClassifier(): ActiveSpatialClassifier | undefined; public abstract get viewFlags(): Partial; - public get transparency(): number | undefined { return undefined; } + public get transparency(): number | undefined { + return undefined; + } } /** @internal */ @@ -101,7 +120,12 @@ class ClassifierTreeReference extends SpatialClassifierTileTreeReference { private readonly _classifiedTree: TileTreeReference; private _owner: TileTreeOwner; - public constructor(classifiers: SpatialClassifiersState, classifiedTree: TileTreeReference, iModel: IModelConnection, source: ViewState | DisplayStyleState) { + public constructor( + classifiers: SpatialClassifiersState, + classifiedTree: TileTreeReference, + iModel: IModelConnection, + source: ViewState | DisplayStyleState, + ) { super(); this._id = createClassifierId(classifiers.active, source); this._source = source; @@ -111,8 +135,12 @@ class ClassifierTreeReference extends SpatialClassifierTileTreeReference { this._owner = classifierTreeSupplier.getOwner(this._id, iModel); } - public get classifiers(): SpatialClassifiersState { return this._classifiers; } - public get activeClassifier(): ActiveSpatialClassifier | undefined { return this.classifiers.activeClassifier; } + public get classifiers(): SpatialClassifiersState { + return this._classifiers; + } + public get activeClassifier(): ActiveSpatialClassifier | undefined { + return this.classifiers.activeClassifier; + } public override get castsShadows() { return false; @@ -149,7 +177,7 @@ class ClassifierTreeReference extends SpatialClassifierTileTreeReference { public get viewFlags(): Partial { return { renderMode: RenderMode.SmoothShade, - transparency: true, // Igored for point clouds as they don't support transparency. + transparency: true, // Igored for point clouds as they don't support transparency. textures: false, lighting: false, shadows: false, @@ -181,11 +209,15 @@ class ClassifierTreeReference extends SpatialClassifierTileTreeReference { context.setVolumeClassifier(classifier, classifiedTree.modelId); super.addToScene(context); } - } /** @internal */ -export function createClassifierTileTreeReference(classifiers: SpatialClassifiersState, classifiedTree: TileTreeReference, iModel: IModelConnection, source: ViewState | DisplayStyleState): SpatialClassifierTileTreeReference { +export function createClassifierTileTreeReference( + classifiers: SpatialClassifiersState, + classifiedTree: TileTreeReference, + iModel: IModelConnection, + source: ViewState | DisplayStyleState, +): SpatialClassifierTileTreeReference { return new ClassifierTreeReference(classifiers, classifiedTree, iModel, source); } diff --git a/core/frontend/src/tile/ContextShareProvider.ts b/core/frontend/src/tile/ContextShareProvider.ts index dac93b5fe4de..3dfe93aaa10a 100644 --- a/core/frontend/src/tile/ContextShareProvider.ts +++ b/core/frontend/src/tile/ContextShareProvider.ts @@ -22,7 +22,10 @@ export class ContextShareProvider { return false; } // If api.bentley.com/realitydata or api.bentley.com/reality-management is used, it is context share - if (tilesetUrl.toLowerCase().includes("api.bentley.com/realitydata") || tilesetUrl.toLowerCase().includes("api.bentley.com/reality-management/reality-data")) + if ( + tilesetUrl.toLowerCase().includes("api.bentley.com/realitydata") || + tilesetUrl.toLowerCase().includes("api.bentley.com/reality-management/reality-data") + ) return true; // detect if it is a RDS url const formattedUrl1 = attUrl.pathname.replace(/~2F/g, "/").replace(/\\/g, "/"); @@ -36,13 +39,16 @@ export class ContextShareProvider { } return false; }); - const isRDSUrl = (urlParts1[partOffset1] === "Repositories") && (urlParts1[partOffset1 + 1].match("S3MXECPlugin--*") !== null) && (urlParts1[partOffset1 + 2] === "S3MX"); + const isRDSUrl = (urlParts1[partOffset1] === "Repositories") && (urlParts1[partOffset1 + 1].match("S3MXECPlugin--*") !== null) && + (urlParts1[partOffset1 + 2] === "S3MX"); return isRDSUrl; } return false; } /** Return true if this is a supported url to this service provider */ - public static getInfoFromUrl(tilesetUrl: string): {provider: RealityDataProvider, format: RealityDataFormat, id: string, iTwinId: string | undefined} { + public static getInfoFromUrl( + tilesetUrl: string, + ): { provider: RealityDataProvider, format: RealityDataFormat, id: string, iTwinId: string | undefined } { const invalidUrlInfo = { provider: RealityDataProvider.TilesetUrl, format: RealityDataFormat.ThreeDTile, id: tilesetUrl, iTwinId: undefined }; let attUrl: URL; try { @@ -52,7 +58,10 @@ export class ContextShareProvider { return invalidUrlInfo; } // If api.bentley.com/realitydata or api.bentley.com/reality-management is used, it is context share - if (tilesetUrl.toLowerCase().includes("api.bentley.com/realitydata") || tilesetUrl.toLowerCase().includes("api.bentley.com/reality-management/reality-data")) { + if ( + tilesetUrl.toLowerCase().includes("api.bentley.com/realitydata") || + tilesetUrl.toLowerCase().includes("api.bentley.com/reality-management/reality-data") + ) { const lcTilesetUrl = tilesetUrl.toLowerCase(); // NOTICE: We assume it is a ThreeDTile BUT this could technically be a point cloud (OPC). // This method was used in typical workflow where format was always ThreeDTile and is here for legacy support. @@ -61,10 +70,10 @@ export class ContextShareProvider { let indexId = -1; let indexProjectId = -1; - if(tilesetUrl.toLowerCase().includes("reality-management/reality-data")) { + if (tilesetUrl.toLowerCase().includes("reality-management/reality-data")) { indexId = lcTilesetUrl.indexOf("reality-management/reality-data/") + 32; // length of "reality-management/reality-data/" = 32; indexProjectId = lcTilesetUrl.indexOf("itwinid=") + 8; // length of "itwinid=" = 8; - } else if(tilesetUrl.toLowerCase().includes("realitydata")) { + } else if (tilesetUrl.toLowerCase().includes("realitydata")) { indexId = lcTilesetUrl.indexOf("realitydata/") + 12; // length of "realitydata/" = 12; indexProjectId = lcTilesetUrl.indexOf("projectid=") + 10; // length of "projectid=" = 10; } @@ -90,7 +99,8 @@ export class ContextShareProvider { return false; }); const isOPC = attUrl.pathname.match(".opc*") !== null; - const isRDSUrl = (urlParts1[partOffset1] === "Repositories") && (urlParts1[partOffset1 + 1].match("S3MXECPlugin--*") !== null) && (urlParts1[partOffset1 + 2] === "S3MX"); + const isRDSUrl = (urlParts1[partOffset1] === "Repositories") && (urlParts1[partOffset1 + 1].match("S3MXECPlugin--*") !== null) && + (urlParts1[partOffset1 + 2] === "S3MX"); let projectId: string | undefined; const projectIdSection = urlParts1.find((val: string) => val.includes("--")); if (projectIdSection) @@ -110,17 +120,17 @@ export class ContextShareProvider { // Not a valid URL and not equal, probably $cesiumAsset return invalidUrlInfo; } - public static getInfoFromBlobUrl(blobUrl: string): {provider: RealityDataProvider, format: RealityDataFormat, id: string } { + public static getInfoFromBlobUrl(blobUrl: string): { provider: RealityDataProvider, format: RealityDataFormat, id: string } { let format = RealityDataFormat.ThreeDTile; let provider = RealityDataProvider.TilesetUrl; const url = new URL(blobUrl); // If we cannot interpret that url pass in parameter we just fallback to old implementation - if(!url.pathname) + if (!url.pathname) return { provider, format, id: blobUrl }; // const accountName = url.hostname.split(".")[0]; - let containerName= ""; + let containerName = ""; if (url.pathname) { const pathSplit = url.pathname.split("/"); containerName = pathSplit[1]; diff --git a/core/frontend/src/tile/DynamicIModelTile.ts b/core/frontend/src/tile/DynamicIModelTile.ts index a27dbdc68f2b..efa2b1749656 100644 --- a/core/frontend/src/tile/DynamicIModelTile.ts +++ b/core/frontend/src/tile/DynamicIModelTile.ts @@ -7,16 +7,41 @@ */ import { - assert, BeTimePoint, ByteStream, compareStrings, DbOpcode, Id64, Id64Array, Id64String, partitionArray, SortedArray, + assert, + BeTimePoint, + ByteStream, + compareStrings, + DbOpcode, + Id64, + Id64Array, + Id64String, + partitionArray, + SortedArray, } from "@itwin/core-bentley"; -import { Range3d, Transform } from "@itwin/core-geometry"; import { - BatchType, ElementGeometryChange, ElementGraphicsRequestProps, FeatureAppearance, FeatureAppearanceProvider, FeatureAppearanceSource, GeometryClass, TileFormat, + BatchType, + ElementGeometryChange, + ElementGraphicsRequestProps, + FeatureAppearance, + FeatureAppearanceProvider, + FeatureAppearanceSource, + GeometryClass, + TileFormat, } from "@itwin/core-common"; -import { RenderSystem } from "../render/RenderSystem"; +import { Range3d, Transform } from "@itwin/core-geometry"; import { IModelApp } from "../IModelApp"; +import { RenderSystem } from "../render/RenderSystem"; import { - ImdlReader, IModelTileTree, RootIModelTile, Tile, TileContent, TileDrawArgs, TileParams, TileRequest, TileRequestChannel, TileTree, + ImdlReader, + IModelTileTree, + RootIModelTile, + Tile, + TileContent, + TileDrawArgs, + TileParams, + TileRequest, + TileRequestChannel, + TileTree, } from "./internal"; /** The root tile for the branch of an [[IModelTileTree]] containing graphics for elements that have been modified during the current @@ -66,7 +91,9 @@ class RootTile extends DynamicIModelTile implements FeatureAppearanceProvider { public readonly transformToTree: Transform; private readonly _elements: ElementTiles; - private get _imodelRoot() { return this.parent as RootIModelTile; } + private get _imodelRoot() { + return this.parent as RootIModelTile; + } private get _elementChildren(): ElementTile[] { assert(undefined !== this.children); @@ -107,7 +134,18 @@ class RootTile extends DynamicIModelTile implements FeatureAppearanceProvider { return this; } - public getFeatureAppearance(source: FeatureAppearanceSource, elemLo: number, elemHi: number, subcatLo: number, subcatHi: number, geomClass: GeometryClass, modelLo: number, modelHi: number, type: BatchType, animationNodeId: number): FeatureAppearance | undefined { + public getFeatureAppearance( + source: FeatureAppearanceSource, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, + geomClass: GeometryClass, + modelLo: number, + modelHi: number, + type: BatchType, + animationNodeId: number, + ): FeatureAppearance | undefined { if (this._hiddenElements.has(elemLo, elemHi)) return undefined; @@ -390,7 +428,13 @@ class GraphicsTile extends Tile { assert(tree instanceof IModelTileTree); const { iModel, modelId, is3d, containsTransformNodes } = tree; const reader = ImdlReader.create({ - stream, iModel, modelId, is3d, system, isCanceled, containsTransformNodes, + stream, + iModel, + modelId, + is3d, + system, + isCanceled, + containsTransformNodes, type: tree.batchType, loadEdges: false !== tree.edgeOptions, options: { tileId: this.contentId }, diff --git a/core/frontend/src/tile/FetchCloudStorage.ts b/core/frontend/src/tile/FetchCloudStorage.ts index 5f747edf45aa..e835fbcce196 100644 --- a/core/frontend/src/tile/FetchCloudStorage.ts +++ b/core/frontend/src/tile/FetchCloudStorage.ts @@ -2,7 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { FrontendConfigDownloadInput, FrontendConfigUploadInput, FrontendStorage, FrontendUploadInMultiplePartsInput, FrontendUrlDownloadInput, FrontendUrlUploadInput, ObjectReference } from "@itwin/object-storage-core/lib/frontend"; +import type { + FrontendConfigDownloadInput, + FrontendConfigUploadInput, + FrontendStorage, + FrontendUploadInMultiplePartsInput, + FrontendUrlDownloadInput, + FrontendUrlUploadInput, + ObjectReference, +} from "@itwin/object-storage-core/lib/frontend"; /** @internal */ export class FetchCloudStorage implements FrontendStorage { diff --git a/core/frontend/src/tile/GltfReader.ts b/core/frontend/src/tile/GltfReader.ts index 6053fc341018..f3e3ac9e8e5a 100644 --- a/core/frontend/src/tile/GltfReader.ts +++ b/core/frontend/src/tile/GltfReader.ts @@ -7,40 +7,102 @@ */ import { - assert, ByteStream, compareBooleans, compareNumbers, compareStrings, Dictionary, JsonUtils, Logger, utf8ToString, + assert, + ByteStream, + compareBooleans, + compareNumbers, + compareStrings, + Dictionary, + JsonUtils, + Logger, + utf8ToString, } from "@itwin/core-bentley"; import { - Angle, IndexedPolyface, Matrix3d, Point2d, Point3d, Point4d, Range2d, Range3d, Transform, Vector3d, -} from "@itwin/core-geometry"; -import { - AxisAlignedBox3d, BatchType, ColorDef, ElementAlignedBox3d, Feature, FeatureIndex, FeatureIndexType, FeatureTable, FillFlags, GlbHeader, ImageSource, LinePixels, MeshEdge, - MeshEdges, MeshPolyline, MeshPolylineList, OctEncodedNormal, PackedFeatureTable, QParams2d, QParams3d, QPoint2dList, - QPoint3dList, Quantization, RenderMaterial, RenderMode, RenderTexture, TextureMapping, TextureTransparency, TileFormat, TileReadStatus, ViewFlagOverrides, + AxisAlignedBox3d, + BatchType, + ColorDef, + ElementAlignedBox3d, + Feature, + FeatureIndex, + FeatureIndexType, + FeatureTable, + FillFlags, + GlbHeader, + ImageSource, + LinePixels, + MeshEdge, + MeshEdges, + MeshPolyline, + MeshPolylineList, + OctEncodedNormal, + PackedFeatureTable, + QParams2d, + QParams3d, + QPoint2dList, + QPoint3dList, + Quantization, + RenderMaterial, + RenderMode, + RenderTexture, + TextureMapping, + TextureTransparency, + TileFormat, + TileReadStatus, + ViewFlagOverrides, } from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; -import { IModelApp } from "../IModelApp"; -import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; -import { RealityMeshParams } from "../render/RealityMeshParams"; -import { Mesh } from "../common/internal/render/MeshPrimitives"; -import { Triangle } from "../common/internal/render/Primitives"; -import { RenderGraphic } from "../render/RenderGraphic"; -import { RenderSystem } from "../render/RenderSystem"; -import { BatchedTileIdMap, decodeMeshoptBuffer, RealityTileGeometry, TileContent } from "./internal"; +import { Angle, IndexedPolyface, Matrix3d, Point2d, Point3d, Point4d, Range2d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import type { DracoLoader, DracoMesh } from "@loaders.gl/draco"; -import { CreateRenderMaterialArgs } from "../render/CreateRenderMaterialArgs"; -import { DisplayParams } from "../common/internal/render/DisplayParams"; import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; -import { getImageSourceFormatForMimeType, imageBitmapFromImageSource, imageElementFromImageSource, tryImageElementFromUrl } from "../common/ImageUtil"; -import { MeshPrimitiveType } from "../common/internal/render/MeshPrimitive"; -import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; -import { TextureImageSource } from "../common/render/TextureParams"; import { - DracoMeshCompression, getGltfNodeMeshIds, Gltf2Node, GltfAccessor, GltfBuffer, GltfBufferViewProps, GltfDataType, GltfDictionary, gltfDictionaryIterator, GltfDocument, GltfId, - GltfImage, GltfMaterial, GltfMesh, GltfMeshMode, GltfMeshPrimitive, GltfNode, GltfSampler, GltfScene, GltfStructuralMetadata, GltfTechniqueState, GltfTexture, GltfWrapMode, isGltf1Material, traverseGltfNodes, + DracoMeshCompression, + getGltfNodeMeshIds, + Gltf2Node, + GltfAccessor, + GltfBuffer, + GltfBufferViewProps, + GltfDataType, + GltfDictionary, + gltfDictionaryIterator, + GltfDocument, + GltfId, + GltfImage, + GltfMaterial, + GltfMesh, + GltfMeshMode, + GltfMeshPrimitive, + GltfNode, + GltfSampler, + GltfScene, + GltfStructuralMetadata, + GltfTechniqueState, + GltfTexture, + GltfWrapMode, + isGltf1Material, + traverseGltfNodes, } from "../common/gltf/GltfSchema"; +import { + getImageSourceFormatForMimeType, + imageBitmapFromImageSource, + imageElementFromImageSource, + tryImageElementFromUrl, +} from "../common/ImageUtil"; +import { DisplayParams } from "../common/internal/render/DisplayParams"; +import { MeshPrimitiveType } from "../common/internal/render/MeshPrimitive"; +import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { PointCloudArgs } from "../common/internal/render/PointCloudPrimitive"; +import { Triangle } from "../common/internal/render/Primitives"; import { PickableGraphicOptions } from "../common/render/BatchOptions"; -import { createGraphicTemplate, GraphicTemplate, GraphicTemplateBatch, GraphicTemplateBranch, GraphicTemplateNode } from "../render/GraphicTemplate"; +import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; +import { TextureImageSource } from "../common/render/TextureParams"; +import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; import { RenderGeometry } from "../internal/render/RenderGeometry"; +import { CreateRenderMaterialArgs } from "../render/CreateRenderMaterialArgs"; +import { createGraphicTemplate, GraphicTemplate, GraphicTemplateBatch, GraphicTemplateBranch, GraphicTemplateNode } from "../render/GraphicTemplate"; +import { RealityMeshParams } from "../render/RealityMeshParams"; +import { RenderGraphic } from "../render/RenderGraphic"; +import { RenderSystem } from "../render/RenderSystem"; +import { BatchedTileIdMap, decodeMeshoptBuffer, RealityTileGeometry, TileContent } from "./internal"; /* eslint-disable no-restricted-syntax */ @@ -123,7 +185,9 @@ class GltfBufferView { public readonly accessor: GltfAccessor; public readonly stride: number; - public get byteLength(): number { return this.data.length; } + public get byteLength(): number { + return this.data.length; + } public constructor(data: Uint8Array, count: number, type: GltfDataType, accessor: GltfAccessor, stride: number) { this.data = data; @@ -250,13 +314,13 @@ export class GltfReaderProps { } /** The GltfMeshData contains the raw GLTF mesh data. If the data is suitable to create a [[RealityMesh]] directly, basically in the quantized format produced by - * ContextCapture, then a RealityMesh is created directly from this data. Otherwise, the mesh primitive is populated from the raw data and a MeshPrimitive - * is generated. The MeshPrimitve path is much less efficient but should be rarely used. - * - * @internal - */ + * ContextCapture, then a RealityMesh is created directly from this data. Otherwise, the mesh primitive is populated from the raw data and a MeshPrimitive + * is generated. The MeshPrimitve path is much less efficient but should be rarely used. + * + * @internal + */ export class GltfMeshData { - public primitive: Mesh; // Populated with vertex and indices only if the mesh cannot be represented as [[RealityMesh]] + public primitive: Mesh; // Populated with vertex and indices only if the mesh cannot be represented as [[RealityMesh]] public pointQParams?: QParams3d; public points?: Uint16Array; public pointRange?: Range3d; @@ -284,7 +348,7 @@ type GltfPrimitiveData = GltfMeshData | GltfPointCloud; */ export type ShouldAbortReadGltf = (reader: GltfReader) => boolean; -const emptyDict = { }; +const emptyDict = {}; function colorFromJson(values: number[]): ColorDef { return ColorDef.from(values[0] * 255, values[1] * 255, values[2] * 255, (1.0 - values[3]) * 255); @@ -308,11 +372,19 @@ function colorFromMaterial(material: GltfMaterial, isTransparent: boolean): Colo return color; } -function trsMatrix(translation: [number, number, number] | undefined, rotation: [number, number, number, number] | undefined, scale: [number, number, number] | undefined, result?: Transform): Transform { +function trsMatrix( + translation: [number, number, number] | undefined, + rotation: [number, number, number, number] | undefined, + scale: [number, number, number] | undefined, + result?: Transform, +): Transform { // SPEC: To compose the local transformation matrix, TRS properties MUST be converted to matrices and postmultiplied in the T * R * S order; // first the scale is applied to the vertices, then the rotation, and then the translation. const scaleTf = Transform.createRefs(undefined, scale ? Matrix3d.createScale(scale[0], scale[1], scale[2]) : Matrix3d.identity); - const rotTf = Transform.createRefs(undefined, rotation ? Matrix3d.createFromQuaternion(Point4d.create(rotation[0], rotation[1], rotation[2], rotation[3])) : Matrix3d.identity); + const rotTf = Transform.createRefs( + undefined, + rotation ? Matrix3d.createFromQuaternion(Point4d.create(rotation[0], rotation[1], rotation[2], rotation[3])) : Matrix3d.identity, + ); rotTf.matrix.transposeInPlace(); // See comment on Matrix3d.createFromQuaternion const transTf = Transform.createTranslation(translation ? new Point3d(translation[0], translation[1], translation[2]) : Point3d.createZero()); const tf = rotTf.multiplyTransformTransform(scaleTf, result); @@ -341,9 +413,15 @@ class TransformStack { if (node.matrix) { const origin = Point3d.create(node.matrix[12], node.matrix[13], node.matrix[14]); const matrix = Matrix3d.createRowValues( - node.matrix[0], node.matrix[4], node.matrix[8], - node.matrix[1], node.matrix[5], node.matrix[9], - node.matrix[2], node.matrix[6], node.matrix[10], + node.matrix[0], + node.matrix[4], + node.matrix[8], + node.matrix[1], + node.matrix[5], + node.matrix[9], + node.matrix[2], + node.matrix[6], + node.matrix[10], ); nodeTransform = Transform.createOriginAndMatrix(origin, matrix); @@ -415,17 +493,17 @@ function compareTextureKeys(lhs: TextureKey, rhs: TextureKey): number { return compareNumbers(lhs.id, rhs.id); } -interface StructuralMetadataTableEntries{ +interface StructuralMetadataTableEntries { name: string; values: any[]; -}; +} -interface StructuralMetadataTable{ +interface StructuralMetadataTable { name: string; entries: StructuralMetadataTableEntries[]; -}; +} -interface StructuralMetadata{ +interface StructuralMetadata { tables: StructuralMetadataTable[]; } @@ -455,22 +533,44 @@ export abstract class GltfReader { protected _structuralMetadata?: StructuralMetadata; protected readonly _idMap?: BatchedTileIdMap; - protected get _nodes(): GltfDictionary { return this._glTF.nodes ?? emptyDict; } - protected get _meshes(): GltfDictionary { return this._glTF.meshes ?? emptyDict; } - protected get _accessors(): GltfDictionary { return this._glTF.accessors ?? emptyDict; } - protected get _bufferViews(): GltfDictionary { return this._glTF.bufferViews ?? emptyDict; } - protected get _materials(): GltfDictionary { return this._glTF.materials ?? emptyDict; } - protected get _samplers(): GltfDictionary { return this._glTF.samplers ?? emptyDict; } - protected get _textures(): GltfDictionary { return this._glTF.textures ?? emptyDict; } + protected get _nodes(): GltfDictionary { + return this._glTF.nodes ?? emptyDict; + } + protected get _meshes(): GltfDictionary { + return this._glTF.meshes ?? emptyDict; + } + protected get _accessors(): GltfDictionary { + return this._glTF.accessors ?? emptyDict; + } + protected get _bufferViews(): GltfDictionary { + return this._glTF.bufferViews ?? emptyDict; + } + protected get _materials(): GltfDictionary { + return this._glTF.materials ?? emptyDict; + } + protected get _samplers(): GltfDictionary { + return this._glTF.samplers ?? emptyDict; + } + protected get _textures(): GltfDictionary { + return this._glTF.textures ?? emptyDict; + } - protected get _images(): GltfDictionary { return this._glTF.images ?? emptyDict; } - protected get _buffers(): GltfDictionary { return this._glTF.buffers ?? emptyDict; } + protected get _images(): GltfDictionary { + return this._glTF.images ?? emptyDict; + } + protected get _buffers(): GltfDictionary { + return this._glTF.buffers ?? emptyDict; + } /** Asynchronously deserialize the tile data and return the result. */ public abstract read(): Promise; - protected get _isCanceled(): boolean { return undefined !== this._canceled && this._canceled(this); } - protected get _isVolumeClassifier(): boolean { return BatchType.VolumeClassifier === this._type; } + protected get _isCanceled(): boolean { + return undefined !== this._canceled && this._canceled(this); + } + protected get _isVolumeClassifier(): boolean { + return BatchType.VolumeClassifier === this._type; + } /** Traverse the nodes specified by their Ids, recursing into their child nodes. * @param nodeIds The Ids of the nodes to traverse. @@ -503,7 +603,9 @@ export abstract class GltfReader { transform = Transform.createIdentity(); if (this._yAxisUp) - transform = transform.multiplyTransformMatrix3d(Matrix3d.createRotationAroundVector(Vector3d.create(1.0, 0.0, 0.0), Angle.createRadians(Angle.piOver2Radians)) as Matrix3d); + transform = transform.multiplyTransformMatrix3d( + Matrix3d.createRotationAroundVector(Vector3d.create(1.0, 0.0, 0.0), Angle.createRadians(Angle.piOver2Radians)) as Matrix3d, + ); if (transformToRoot) transform = transformToRoot.multiplyTransformTransform(transform); @@ -512,12 +614,27 @@ export abstract class GltfReader { return transform; } - protected readGltfAndCreateGraphics(isLeaf: boolean, featureTable: FeatureTable | undefined, contentRange: ElementAlignedBox3d | undefined, transformToRoot?: Transform, pseudoRtcBias?: Vector3d, instances?: InstancedGraphicParams): GltfReaderResult { + protected readGltfAndCreateGraphics( + isLeaf: boolean, + featureTable: FeatureTable | undefined, + contentRange: ElementAlignedBox3d | undefined, + transformToRoot?: Transform, + pseudoRtcBias?: Vector3d, + instances?: InstancedGraphicParams, + ): GltfReaderResult { const result = this.readGltfAndCreateTemplate(isLeaf, featureTable, contentRange, true, transformToRoot, pseudoRtcBias, instances); return templateToGraphicResult(result, this._system); } - protected readGltfAndCreateTemplate(isLeaf: boolean, featureTable: FeatureTable | undefined, contentRange: ElementAlignedBox3d | undefined, noDispose: boolean, transformToRoot?: Transform, pseudoRtcBias?: Vector3d, instances?: InstancedGraphicParams): GltfTemplateResult { + protected readGltfAndCreateTemplate( + isLeaf: boolean, + featureTable: FeatureTable | undefined, + contentRange: ElementAlignedBox3d | undefined, + noDispose: boolean, + transformToRoot?: Transform, + pseudoRtcBias?: Vector3d, + instances?: InstancedGraphicParams, + ): GltfTemplateResult { if (this._isCanceled) return { readStatus: TileReadStatus.Canceled, isLeaf }; @@ -530,7 +647,7 @@ export abstract class GltfReader { // Save feature table model id in case we need to recreate it after reading instances const featureTableModelId = featureTable?.modelId; // Flush feature table if instance features are used - if(this._structuralMetadata && this._glTF.extensionsUsed?.includes("EXT_instance_features") && this._idMap){ + if (this._structuralMetadata && this._glTF.extensionsUsed?.includes("EXT_instance_features") && this._idMap) { featureTable = undefined; } @@ -544,15 +661,18 @@ export abstract class GltfReader { for (const nodeKey of this._sceneNodes) { assert(transformStack.isEmpty); const node = this._nodes[nodeKey]; - if (node && TileReadStatus.Success !== (readStatus = this.readTemplateNodes(templateNodes, node, featureTable, transformStack, instances, pseudoRtcBias))) + if ( + node && + TileReadStatus.Success !== (readStatus = this.readTemplateNodes(templateNodes, node, featureTable, transformStack, instances, pseudoRtcBias)) + ) return { readStatus, isLeaf }; } // Creates a feature table based on instance features // The table must be created after reading instances, since the maximum number of features is not known until all instances have been read. - if(this._instanceFeatures.length > 0 && this._idMap){ + if (this._instanceFeatures.length > 0 && this._idMap) { featureTable = new FeatureTable(this._instanceFeatures.length, featureTableModelId); - for(let instanceFeatureId = 0; instanceFeatureId < this._instanceFeatures.length; instanceFeatureId++){ + for (let instanceFeatureId = 0; instanceFeatureId < this._instanceFeatures.length; instanceFeatureId++) { featureTable.insertWithIndex(this._instanceFeatures[instanceFeatureId], instanceFeatureId); } } @@ -632,9 +752,10 @@ export abstract class GltfReader { mesh.uvParams.push(gltfMesh.uvQParams.unquantize(gltfMesh.uvs[j++], gltfMesh.uvs[j++])); } - if (gltfMesh.normals) + if (gltfMesh.normals) { for (const normal of gltfMesh.normals) mesh.normals.push(new OctEncodedNormal(normal)); + } return this._system.createGeometryFromMesh(mesh, undefined); } @@ -706,55 +827,52 @@ export abstract class GltfReader { transforms[idx + 11] = tf.origin.z; } - let featureIds = ((featureTable && featureTable.isUniform)) ? new Uint8Array(3 * count) : undefined; + let featureIds = (featureTable && featureTable.isUniform) ? new Uint8Array(3 * count) : undefined; // Resolve instance features if the EXT_instance_features if present const instanceFeaturesExt = node.extensions?.EXT_instance_features; - if(this._structuralMetadata && instanceFeaturesExt && this._idMap){ - if(!featureIds) + if (this._structuralMetadata && instanceFeaturesExt && this._idMap) { + if (!featureIds) featureIds = new Uint8Array(3 * count); // Resolve feature buffers before creating instance table const featureBuffers = new Map(); - for(const featureIdDesc of instanceFeaturesExt.featureIds){ - - if(featureIdDesc.attribute !== undefined){ - const bufferView = this.getBufferView(ext.attributes, `_FEATURE_ID_${ featureIdDesc.attribute}`); - if(bufferView){ + for (const featureIdDesc of instanceFeaturesExt.featureIds) { + if (featureIdDesc.attribute !== undefined) { + const bufferView = this.getBufferView(ext.attributes, `_FEATURE_ID_${featureIdDesc.attribute}`); + if (bufferView) { const bufferData = bufferView.toBufferData(bufferView.type)?.buffer; - if(bufferData){ + if (bufferData) { featureBuffers.set(featureIdDesc.attribute, bufferData); } } } } - for(let localInstanceId = 0; localInstanceId < count; localInstanceId++){ - + for (let localInstanceId = 0; localInstanceId < count; localInstanceId++) { const instanceProps: any = {}; - for(const featureIdDesc of instanceFeaturesExt.featureIds){ - + for (const featureIdDesc of instanceFeaturesExt.featureIds) { const table = this._structuralMetadata.tables[featureIdDesc.propertyTable]; instanceProps[table.name] = {}; // If the attribute is not defined, then the feature id corresponds to the instance id - if(featureIdDesc.attribute === undefined){ - for(const entries of table.entries){ - if(entries.values[localInstanceId] !== undefined){ + if (featureIdDesc.attribute === undefined) { + for (const entries of table.entries) { + if (entries.values[localInstanceId] !== undefined) { instanceProps[table.name][entries.name] = entries.values[localInstanceId]; } } - } else if(featureBuffers.has(featureIdDesc.attribute)) { + } else if (featureBuffers.has(featureIdDesc.attribute)) { const featureBuffer = featureBuffers.get(featureIdDesc.attribute); - if(!featureBuffer){ + if (!featureBuffer) { continue; } const featureId = featureBuffer[localInstanceId]; - if(featureIdDesc.nullFeatureId !== undefined && featureId === featureIdDesc.nullFeatureId){ + if (featureIdDesc.nullFeatureId !== undefined && featureId === featureIdDesc.nullFeatureId) { continue; } - for(const entries of table.entries){ - if(entries.values[featureId] !== undefined){ + for (const entries of table.entries) { + if (entries.values[featureId] !== undefined) { instanceProps[table.name][entries.name] = entries.values[featureId]; } } @@ -765,7 +883,7 @@ export abstract class GltfReader { // If the element id is already assigned to a previous instance, // reuse the previous feature id to avoid collision in the feature table - if(!this._instanceElementIdToFeatureId.has(instanceElementId)){ + if (!this._instanceElementIdToFeatureId.has(instanceElementId)) { this._instanceElementIdToFeatureId.set(instanceElementId, this._instanceFeatures.length); this._instanceFeatures.push(new Feature(instanceElementId)); } @@ -845,7 +963,13 @@ export abstract class GltfReader { return TileReadStatus.Success; } - private readNodeAndCreatePolyfaces(polyfaces: IndexedPolyface[], node: GltfNode, transformStack: TransformStack, needNormals: boolean, needParams: boolean): void { + private readNodeAndCreatePolyfaces( + polyfaces: IndexedPolyface[], + node: GltfNode, + transformStack: TransformStack, + needNormals: boolean, + needParams: boolean, + ): void { // IMPORTANT: Do not return without popping this node from the stack. transformStack.push(node); const meshes = this.readMeshPrimitives(node); @@ -867,7 +991,12 @@ export abstract class GltfReader { } } - private polyfaceFromGltfMesh(mesh: GltfMeshData, transform: Transform | undefined , needNormals: boolean, needParams: boolean): IndexedPolyface | undefined { + private polyfaceFromGltfMesh( + mesh: GltfMeshData, + transform: Transform | undefined, + needNormals: boolean, + needParams: boolean, + ): IndexedPolyface | undefined { if (!mesh.pointQParams || !mesh.points || !mesh.indices) return undefined; @@ -877,7 +1006,7 @@ export abstract class GltfReader { const includeParams = needParams && undefined !== uvQParams && undefined !== uvs; const polyface = IndexedPolyface.create(includeNormals, includeParams); - for (let i = 0; i < points.length; ) { + for (let i = 0; i < points.length;) { const point = pointQParams.unquantize(points[i++], points[i++], points[i++]); if (transform) transform.multiplyPoint3d(point, point); @@ -885,13 +1014,15 @@ export abstract class GltfReader { polyface.addPoint(point); } - if (includeNormals && normals) - for (let i = 0; i < normals.length; ) + if (includeNormals && normals) { + for (let i = 0; i < normals.length;) polyface.addNormal(OctEncodedNormal.decodeValue(normals[i++])); + } - if (includeParams && uvs && uvQParams) - for (let i = 0; i < uvs.length; ) + if (includeParams && uvs && uvQParams) { + for (let i = 0; i < uvs.length;) polyface.addParam(uvQParams.unquantize(uvs[i++], uvs[i++])); + } let j = 0; for (const index of indices) { @@ -976,10 +1107,18 @@ export abstract class GltfReader { } } - public readBufferData32(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { return this.readBufferData(json, accessorName, GltfDataType.UInt32); } - public readBufferData16(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { return this.readBufferData(json, accessorName, GltfDataType.UnsignedShort); } - public readBufferData8(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { return this.readBufferData(json, accessorName, GltfDataType.UnsignedByte); } - public readBufferDataFloat(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { return this.readBufferData(json, accessorName, GltfDataType.Float); } + public readBufferData32(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { + return this.readBufferData(json, accessorName, GltfDataType.UInt32); + } + public readBufferData16(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { + return this.readBufferData(json, accessorName, GltfDataType.UnsignedShort); + } + public readBufferData8(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { + return this.readBufferData(json, accessorName, GltfDataType.UnsignedByte); + } + public readBufferDataFloat(json: { [k: string]: any }, accessorName: string): GltfBufferData | undefined { + return this.readBufferData(json, accessorName, GltfDataType.Float); + } protected constructor(args: GltfReaderArgs) { this._glTF = args.props.glTF; @@ -988,9 +1127,10 @@ export abstract class GltfReader { this._baseUrl = args.props.baseUrl; const rtcCenter = args.props.glTF.extensions?.CESIUM_RTC?.center; - if (rtcCenter && 3 === rtcCenter.length) + if (rtcCenter && 3 === rtcCenter.length) { if (0 !== rtcCenter[0] || 0 !== rtcCenter[1] || 0 !== rtcCenter[2]) this._returnToCenter = Point3d.fromJSON(rtcCenter); + } this._iModel = args.iModel; this._is3d = true !== args.is2d; @@ -1027,7 +1167,9 @@ export abstract class GltfReader { return undefined !== view ? view.toBufferData(type) : undefined; } - protected readFeatureIndices(_json: any): number[] | undefined { return undefined; } + protected readFeatureIndices(_json: any): number[] | undefined { + return undefined; + } private extractId(value: any): string | undefined { switch (typeof value) { @@ -1051,7 +1193,7 @@ export abstract class GltfReader { // KHR_techniques_webgl extension const techniques = this._glTF.extensions?.KHR_techniques_webgl?.techniques; const ext = Array.isArray(techniques) ? material.extensions?.KHR_techniques_webgl : undefined; - if (techniques && undefined !== ext && typeof(ext.values) === "object") { + if (techniques && undefined !== ext && typeof (ext.values) === "object") { const uniforms = typeof ext.technique === "number" ? techniques[ext.technique].uniforms : undefined; if (typeof uniforms === "object") { for (const uniformName of Object.keys(uniforms)) { @@ -1096,7 +1238,9 @@ export abstract class GltfReader { const isTransparent = this.isMaterialTransparent(material); const textureId = this.extractTextureId(material); const normalMapId = this.extractNormalMapId(material); - let textureMapping = (undefined !== textureId || undefined !== normalMapId) ? this.findTextureMapping(textureId, isTransparent, normalMapId) : undefined; + let textureMapping = (undefined !== textureId || undefined !== normalMapId) + ? this.findTextureMapping(textureId, isTransparent, normalMapId) + : undefined; const color = colorFromMaterial(material, isTransparent); let renderMaterial: RenderMaterial | undefined; if (undefined !== textureMapping && undefined !== textureMapping.normalMapParams) { @@ -1105,13 +1249,29 @@ export abstract class GltfReader { // DisplayParams doesn't want a separate texture mapping if the material already has one. textureMapping = undefined; - } - return new DisplayParams(DisplayParams.Type.Mesh, color, color, 1, LinePixels.Solid, FillFlags.None, renderMaterial, undefined, hasBakedLighting, textureMapping); + return new DisplayParams( + DisplayParams.Type.Mesh, + color, + color, + 1, + LinePixels.Solid, + FillFlags.None, + renderMaterial, + undefined, + hasBakedLighting, + textureMapping, + ); } - private readMeshPrimitives(node: GltfNode, featureTable?: FeatureTable, thisTransform?: Transform, thisBias?: Vector3d, instances?: InstancedGraphicParams): GltfPrimitiveData[] { + private readMeshPrimitives( + node: GltfNode, + featureTable?: FeatureTable, + thisTransform?: Transform, + thisBias?: Vector3d, + instances?: InstancedGraphicParams, + ): GltfPrimitiveData[] { const meshes: GltfPrimitiveData[] = []; for (const meshKey of getGltfNodeMeshIds(node)) { const nodeMesh = this._meshes[meshKey]; @@ -1121,16 +1281,18 @@ export abstract class GltfReader { if (mesh) { meshes.push(mesh); if (this._computedContentRange && mesh.pointRange) { - const meshRange = thisTransform ? thisTransform .multiplyRange(mesh.pointRange) : mesh.pointRange; + const meshRange = thisTransform ? thisTransform.multiplyRange(mesh.pointRange) : mesh.pointRange; if (!instances) { this._computedContentRange.extendRange(meshRange); } else { const tfs = instances.transforms; const nodeRange = new Range3d(); const extendTransformedRange = (i: number, x: number, y: number, z: number) => { - nodeRange.extendXYZ(tfs[i + 3] + tfs[i + 0] * x + tfs[i + 1] * y + tfs[i + 2] * z, + nodeRange.extendXYZ( + tfs[i + 3] + tfs[i + 0] * x + tfs[i + 1] * y + tfs[i + 2] * z, tfs[i + 7] + tfs[i + 4] * x + tfs[i + 5] * y + tfs[i + 6] * z, - tfs[i + 11] + tfs[i + 8] * x + tfs[i + 9] * y + tfs[i + 10] * z); + tfs[i + 11] + tfs[i + 8] * x + tfs[i + 9] * y + tfs[i + 10] * z, + ); }; for (let i = 0; i < tfs.length; i += 3 * 4) { @@ -1167,7 +1329,7 @@ export abstract class GltfReader { } const materialName = JsonUtils.asString(primitive.material); - const material = 0 < materialName.length ? this._materials[materialName] : { }; + const material = 0 < materialName.length ? this._materials[materialName] : {}; if (!material) return undefined; @@ -1214,7 +1376,7 @@ export abstract class GltfReader { // We don't have real colormap - just load material color. This will be used if non-Bentley // tile or fit the color table is uniform. For a non-Bentley, non-Uniform, we'll set the // uv parameters to pick the colors out of the color map texture. - meshPrimitive.colorMap.insert(displayParams.fillColor.tbgr); // White... + meshPrimitive.colorMap.insert(displayParams.fillColor.tbgr); // White... // _COLORINDEX is an ancient holdover from glTF 1.0 and Bimium...unlikely to actually encounter it in the wild. const colorIndices = this.readBufferData16(primitive.attributes, "_COLORINDEX"); if (undefined !== colorIndices && material) { @@ -1278,7 +1440,10 @@ export abstract class GltfReader { case MeshPrimitiveType.Polyline: case MeshPrimitiveType.Point: { - if (undefined !== mesh.primitive.polylines && !this.readPolylines(mesh.primitive.polylines, primitive, "indices", MeshPrimitiveType.Point === primitiveType)) + if ( + undefined !== mesh.primitive.polylines && + !this.readPolylines(mesh.primitive.polylines, primitive, "indices", MeshPrimitiveType.Point === primitiveType) + ) return undefined; break; } @@ -1446,9 +1611,10 @@ export abstract class GltfReader { } const uvs = draco.attributes.TEXCOORD_0?.value; - if (uvs && (uvs.length % 2) === 0) + if (uvs && (uvs.length % 2) === 0) { for (let i = 0; i < uvs.length; i += 2) mesh.uvParams.push(new Point2d(uvs[i], uvs[i + 1])); + } const batchIds = draco.attributes._BATCHID?.value; if (batchIds && mesh.features) { @@ -1504,7 +1670,6 @@ export abstract class GltfReader { } /** - * * @param positions quantized points * @param primitive input json * @param pseudoRtcBias a bias applied to each point - this is a workaround for tiles generated by @@ -1747,7 +1912,6 @@ export abstract class GltfReader { default: assert(false); return false; - } return true; @@ -1815,10 +1979,11 @@ export abstract class GltfReader { for (const node of this.traverseScene()) { for (const meshId of getGltfNodeMeshIds(node)) { const mesh = this._meshes[meshId]; - if (mesh?.primitives) + if (mesh?.primitives) { for (const primitive of mesh.primitives) if (primitive.extensions?.KHR_draco_mesh_compression) dracoMeshes.push(primitive.extensions.KHR_draco_mesh_compression); + } } } @@ -1868,7 +2033,7 @@ export abstract class GltfReader { const offset = bv.byteOffset ?? 0; buf = buf.subarray(offset, offset + bv.byteLength); - const mesh = await loader.parse(buf, { }); // NB: `options` argument declared optional but will produce exception if not supplied. + const mesh = await loader.parse(buf, {}); // NB: `options` argument declared optional but will produce exception if not supplied. if (mesh) this._dracoMeshes.set(ext, mesh); } @@ -1908,7 +2073,10 @@ export abstract class GltfReader { if (image.resolvedImage) return; - interface BufferViewSource { bufferView?: GltfId, mimeType?: string } + interface BufferViewSource { + bufferView?: GltfId; + mimeType?: string; + } const bvSrc: BufferViewSource | undefined = undefined !== image.bufferView ? image : image.extensions?.KHR_binary_glTF; if (undefined !== bvSrc?.bufferView) { const format = undefined !== bvSrc.mimeType ? getImageSourceFormatForMimeType(bvSrc.mimeType) : undefined; @@ -2176,12 +2344,12 @@ export class GltfGraphicsReader extends GltfReader { }; } - private getGltfStructuralMetadataBuffer(id: GltfId, type: GltfStructuralMetadata.ClassPropertyComponentType){ + private getGltfStructuralMetadataBuffer(id: GltfId, type: GltfStructuralMetadata.ClassPropertyComponentType) { const bufferView = this._bufferViews[id]; if (!bufferView || undefined === bufferView.buffer) return undefined; - if(!bufferView.byteLength || bufferView.byteLength === 0){ + if (!bufferView.byteLength || bufferView.byteLength === 0) { return undefined; } @@ -2193,7 +2361,7 @@ export class GltfGraphicsReader extends GltfReader { const byteOffset = bufferView.byteOffset ?? 0; const subarray = bufferData.slice(byteOffset, byteOffset + bufferView.byteLength); - switch(type){ + switch (type) { case "INT8": return new Int8Array(subarray.buffer, 0, bufferView.byteLength); case "UINT8": @@ -2218,39 +2386,41 @@ export class GltfGraphicsReader extends GltfReader { return undefined; } - private getGltfStructuralMetadataPropertyValues(property: GltfStructuralMetadata.PropertyTableProperty, classProperty: GltfStructuralMetadata.ClassProperty, count: number){ + private getGltfStructuralMetadataPropertyValues( + property: GltfStructuralMetadata.PropertyTableProperty, + classProperty: GltfStructuralMetadata.ClassProperty, + count: number, + ) { // Not supported for now - if(classProperty.type === "ENUM" || classProperty.type === "BOOLEAN"){ + if (classProperty.type === "ENUM" || classProperty.type === "BOOLEAN") { return undefined; } let getPropertyValue: any; - if(classProperty.type === "STRING" && property.stringOffsets){ - + if (classProperty.type === "STRING" && property.stringOffsets) { const stringValues = this.getGltfStructuralMetadataBuffer(property.values, "UINT8") as Uint8Array; - if(!stringValues){ + if (!stringValues) { return undefined; } const stringOffsets = this.getGltfStructuralMetadataBuffer(property.stringOffsets, "UINT32") as Uint32Array; - if(!stringOffsets){ + if (!stringOffsets) { return undefined; } getPropertyValue = (index: number) => { const begin = stringOffsets[index]; - const end = stringOffsets[index+1]; + const end = stringOffsets[index + 1]; return utf8ToString(stringValues.subarray(begin, end)); }; } else { - - if(!classProperty.componentType){ + if (!classProperty.componentType) { return undefined; } let numComponents = -1; - switch(classProperty.type){ + switch (classProperty.type) { case "SCALAR": numComponents = 1; break; @@ -2274,23 +2444,23 @@ export class GltfGraphicsReader extends GltfReader { break; } - if(numComponents === -1){ + if (numComponents === -1) { return undefined; } const values = this.getGltfStructuralMetadataBuffer(property.values, classProperty.componentType); - if(!values){ + if (!values) { return undefined; } - if(numComponents === 1){ + if (numComponents === 1) { getPropertyValue = (index: number) => { return values[index]; }; } else { getPropertyValue = (index: number) => { const result = []; - for(let i = 0; i < numComponents; i++){ + for (let i = 0; i < numComponents; i++) { result.push(values[index * numComponents + i]); } return result; @@ -2299,12 +2469,12 @@ export class GltfGraphicsReader extends GltfReader { } const propertyValues: any[] = []; - for(let i = 0; i < count; i++){ + for (let i = 0; i < count; i++) { const value = getPropertyValue(i); - const propertyValue = (typeof value === "bigint" ) ? value.toString() : value; - if(!classProperty.noData || propertyValue !== classProperty.noData){ + const propertyValue = (typeof value === "bigint") ? value.toString() : value; + if (!classProperty.noData || propertyValue !== classProperty.noData) { propertyValues.push(propertyValue); - } else{ + } else { propertyValues.push(undefined); } } @@ -2312,21 +2482,20 @@ export class GltfGraphicsReader extends GltfReader { return propertyValues; } - private readGltfStructuralMetadata(){ + private readGltfStructuralMetadata() { const propertyTables = this._glTF.extensions?.EXT_structural_metadata?.propertyTables; const schema = this._glTF.extensions?.EXT_structural_metadata?.schema; - if(propertyTables && schema && schema.classes){ - + if (propertyTables && schema && schema.classes) { this._structuralMetadata = { tables: [] }; - for(const propertyTable of propertyTables){ - if(!propertyTable.properties || !schema.classes){ + for (const propertyTable of propertyTables) { + if (!propertyTable.properties || !schema.classes) { continue; } const propertyTableSchema = schema.classes[propertyTable.class]; - if(!propertyTableSchema || !propertyTableSchema.properties){ + if (!propertyTableSchema || !propertyTableSchema.properties) { continue; } @@ -2335,17 +2504,16 @@ export class GltfGraphicsReader extends GltfReader { entries: [], }; - for (const [propertyName, property] of Object.entries(propertyTable.properties)){ - + for (const [propertyName, property] of Object.entries(propertyTable.properties)) { const propertySchema = propertyTableSchema.properties[propertyName]; - if(!property || !propertySchema){ + if (!property || !propertySchema) { continue; } const propertyValues = this.getGltfStructuralMetadataPropertyValues(property, propertySchema, propertyTable.count); - if(!propertyValues){ + if (!propertyValues) { continue; } @@ -2370,9 +2538,19 @@ export class GltfGraphicsReader extends GltfReader { return templateToGraphicResult(result, this._system); } - public get structuralMetadata(): StructuralMetadata | undefined { return this._structuralMetadata; } - public get nodes(): GltfDictionary { return this._nodes; } - public get scenes(): GltfDictionary { return this._glTF.scenes ?? emptyDict; } - public get sceneNodes(): GltfId[] { return this._sceneNodes; } - public get textures(): GltfDictionary { return this._textures; } + public get structuralMetadata(): StructuralMetadata | undefined { + return this._structuralMetadata; + } + public get nodes(): GltfDictionary { + return this._nodes; + } + public get scenes(): GltfDictionary { + return this._glTF.scenes ?? emptyDict; + } + public get sceneNodes(): GltfId[] { + return this._sceneNodes; + } + public get textures(): GltfDictionary { + return this._textures; + } } diff --git a/core/frontend/src/tile/GraphicsCollector.ts b/core/frontend/src/tile/GraphicsCollector.ts index d7589c1eef44..e5767769caa1 100644 --- a/core/frontend/src/tile/GraphicsCollector.ts +++ b/core/frontend/src/tile/GraphicsCollector.ts @@ -6,8 +6,8 @@ * @module Tiles */ -import { Map4d } from "@itwin/core-geometry"; import { FrustumPlanes } from "@itwin/core-common"; +import { Map4d } from "@itwin/core-geometry"; import { GraphicBranch } from "../render/GraphicBranch"; import { RenderGraphic } from "../render/RenderGraphic"; import { SceneContext } from "../ViewContext"; @@ -32,8 +32,12 @@ export class GraphicsCollectorDrawArgs extends TileDrawArgs { this._collector = collector; } - public override get frustumPlanes(): FrustumPlanes { return this._planes; } - public override get worldToViewMap(): Map4d { return this._worldToViewMap; } + public override get frustumPlanes(): FrustumPlanes { + return this._planes; + } + public override get worldToViewMap(): Map4d { + return this._worldToViewMap; + } public override drawGraphicsWithType(_graphicType: TileGraphicType, graphics: GraphicBranch) { this._collector.addGraphic(this.context.createBranch(graphics, this.location)); } @@ -46,7 +50,13 @@ export class GraphicsCollectorDrawArgs extends TileDrawArgs { } } - public static create(context: SceneContext, collector: GraphicsCollector, ref: TileTreeReference, planes: FrustumPlanes, worldToViewMap: Map4d): TileDrawArgs | undefined { + public static create( + context: SceneContext, + collector: GraphicsCollector, + ref: TileTreeReference, + planes: FrustumPlanes, + worldToViewMap: Map4d, + ): TileDrawArgs | undefined { const args = ref.createDrawArgs(context); if (undefined === args) return undefined; diff --git a/core/frontend/src/tile/I3dmReader.ts b/core/frontend/src/tile/I3dmReader.ts index 7a4409ee6ac3..c61bb0df88a6 100644 --- a/core/frontend/src/tile/I3dmReader.ts +++ b/core/frontend/src/tile/I3dmReader.ts @@ -6,11 +6,11 @@ * @module Tiles */ import { ByteStream, Id64String, JsonUtils, utf8ToString } from "@itwin/core-bentley"; -import { AxisOrder, Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry"; import { ElementAlignedBox3d, Feature, FeatureTable, I3dmHeader, TileReadStatus } from "@itwin/core-common"; -import { IModelConnection } from "../IModelConnection"; -import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; +import { AxisOrder, Matrix3d, Point3d, Vector3d } from "@itwin/core-geometry"; import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; +import { IModelConnection } from "../IModelConnection"; import { RenderSystem } from "../render/RenderSystem"; import { BatchedTileIdMap, GltfReader, GltfReaderProps, GltfReaderResult, ShouldAbortReadGltf } from "./internal"; @@ -51,8 +51,19 @@ export class I3dmReader extends GltfReader { private _featureTable?: FeatureTable; private readonly _modelId: Id64String; - public static create(stream: ByteStream, iModel: IModelConnection, modelId: Id64String, is3d: boolean, range: ElementAlignedBox3d, - system: RenderSystem, yAxisUp: boolean, isLeaf: boolean, isCanceled?: ShouldAbortReadGltf, idMap?: BatchedTileIdMap, deduplicateVertices=false): I3dmReader | undefined { + public static create( + stream: ByteStream, + iModel: IModelConnection, + modelId: Id64String, + is3d: boolean, + range: ElementAlignedBox3d, + system: RenderSystem, + yAxisUp: boolean, + isLeaf: boolean, + isCanceled?: ShouldAbortReadGltf, + idMap?: BatchedTileIdMap, + deduplicateVertices = false, + ): I3dmReader | undefined { const header = new I3dmHeader(stream); if (!header.isValid) return undefined; @@ -66,17 +77,51 @@ export class I3dmReader extends GltfReader { if (undefined === featureStr) return undefined; - const featureBinary = new Uint8Array(stream.arrayBuffer, header.featureTableJsonPosition + header.featureTableJsonLength, header.featureTableBinaryLength); - return new I3dmReader(featureBinary, JSON.parse(featureStr), header.batchTableJson, props, iModel, modelId, is3d, system, - range, isLeaf, isCanceled, idMap, deduplicateVertices); + const featureBinary = new Uint8Array( + stream.arrayBuffer, + header.featureTableJsonPosition + header.featureTableJsonLength, + header.featureTableBinaryLength, + ); + return new I3dmReader( + featureBinary, + JSON.parse(featureStr), + header.batchTableJson, + props, + iModel, + modelId, + is3d, + system, + range, + isLeaf, + isCanceled, + idMap, + deduplicateVertices, + ); } - private constructor(private _featureBinary: Uint8Array, private _featureJson: any, private _batchTableJson: any, props: GltfReaderProps, - iModel: IModelConnection, modelId: Id64String, is3d: boolean, system: RenderSystem, private _range: ElementAlignedBox3d, - private _isLeaf: boolean, shouldAbort?: ShouldAbortReadGltf, _idMap?: BatchedTileIdMap, deduplicateVertices=false) { + private constructor( + private _featureBinary: Uint8Array, + private _featureJson: any, + private _batchTableJson: any, + props: GltfReaderProps, + iModel: IModelConnection, + modelId: Id64String, + is3d: boolean, + system: RenderSystem, + private _range: ElementAlignedBox3d, + private _isLeaf: boolean, + shouldAbort?: ShouldAbortReadGltf, + _idMap?: BatchedTileIdMap, + deduplicateVertices = false, + ) { super({ - props, iModel, system, shouldAbort, deduplicateVertices, - is2d: !is3d, idMap: _idMap, + props, + iModel, + system, + shouldAbort, + deduplicateVertices, + is2d: !is3d, + idMap: _idMap, }); this._modelId = modelId; } @@ -128,7 +173,9 @@ export class I3dmReader extends GltfReader { const upNormals = json.NORMAL_UP ? new Float32Array(binary.buffer, binary.byteOffset + json.NORMAL_UP.byteOffset, count * 3) : undefined; const rightNormals = json.NORMAL_RIGHT ? new Float32Array(binary.buffer, binary.byteOffset + json.NORMAL_RIGHT.byteOffset, count * 3) : undefined; const scales = json.SCALE ? new Float32Array(binary.buffer, binary.byteOffset + json.SCALE.byteOffset, count) : undefined; - const nonUniformScales = json.SCALE_NON_UNIFORM ? new Float32Array(binary.buffer, binary.byteOffset + json.SCALE_NON_UNIFORM.byteOffset, count * 3) : undefined; + const nonUniformScales = json.SCALE_NON_UNIFORM + ? new Float32Array(binary.buffer, binary.byteOffset + json.SCALE_NON_UNIFORM.byteOffset, count * 3) + : undefined; const matrix = Matrix3d.createIdentity(); const position = Point3d.createZero(); diff --git a/core/frontend/src/tile/IModelTile.ts b/core/frontend/src/tile/IModelTile.ts index afe48427fca6..a5bf377a3711 100644 --- a/core/frontend/src/tile/IModelTile.ts +++ b/core/frontend/src/tile/IModelTile.ts @@ -7,16 +7,33 @@ */ import { assert, BentleyError, BeTimePoint, ByteStream } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { - ColorDef, computeChildTileProps, computeChildTileRanges, computeTileChordTolerance, ElementAlignedBox3d, LinePixels, TileFormat, TileProps, + ColorDef, + computeChildTileProps, + computeChildTileRanges, + computeTileChordTolerance, + ElementAlignedBox3d, + LinePixels, + TileFormat, + TileProps, } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; import { IModelApp } from "../IModelApp"; import { GraphicBuilder } from "../render/GraphicBuilder"; import { RenderSystem } from "../render/RenderSystem"; import { - addRangeGraphic, IModelTileTree, Tile, TileBoundingBoxes, TileContent, TileDrawArgs, TileLoadStatus, TileParams, TileRequest, - TileRequestChannel, TileTreeLoadStatus, TileVisibility, + addRangeGraphic, + IModelTileTree, + Tile, + TileBoundingBoxes, + TileContent, + TileDrawArgs, + TileLoadStatus, + TileParams, + TileRequest, + TileRequestChannel, + TileTreeLoadStatus, + TileVisibility, } from "./internal"; /** Parameters used to construct an [[IModelTile]]. @@ -78,12 +95,22 @@ export class IModelTile extends Tile { } } - public get iModelTree(): IModelTileTree { return this.tree as IModelTileTree; } - public get iModelChildren(): IModelTile[] | undefined { return this.children as IModelTile[] | undefined; } - public get emptySubRangeMask(): number { return this._emptySubRangeMask ?? 0; } + public get iModelTree(): IModelTileTree { + return this.tree as IModelTileTree; + } + public get iModelChildren(): IModelTile[] | undefined { + return this.children as IModelTile[] | undefined; + } + public get emptySubRangeMask(): number { + return this._emptySubRangeMask ?? 0; + } - public get sizeMultiplier(): number | undefined { return this._sizeMultiplier; } - public get hasSizeMultiplier() { return undefined !== this.sizeMultiplier; } + public get sizeMultiplier(): number | undefined { + return this._sizeMultiplier; + } + public get hasSizeMultiplier() { + return undefined !== this.sizeMultiplier; + } public override get maximumSize(): number { return super.maximumSize * (this.sizeMultiplier ?? 1.0); } @@ -195,9 +222,10 @@ export class IModelTile extends Tile { // this node has been used recently. Keep it, but potentially unload its grandchildren. const children = this.iModelChildren; - if (undefined !== children) + if (undefined !== children) { for (const child of children) child.pruneChildren(olderThan); + } } public selectTiles(selected: Tile[], args: TileDrawArgs, numSkipped: number): SelectParent { diff --git a/core/frontend/src/tile/IModelTileRequestChannels.ts b/core/frontend/src/tile/IModelTileRequestChannels.ts index 387fac2bf1d6..159e1cdf7a7e 100644 --- a/core/frontend/src/tile/IModelTileRequestChannels.ts +++ b/core/frontend/src/tile/IModelTileRequestChannels.ts @@ -9,8 +9,8 @@ import { assert, compareStrings, SortedArray } from "@itwin/core-bentley"; import { TileTreeContentIds } from "@itwin/core-common"; import { IModelApp } from "../IModelApp"; -import { IpcApp } from "../IpcApp"; import { IModelConnection } from "../IModelConnection"; +import { IpcApp } from "../IpcApp"; import { IModelTile, IModelTileContent, Tile, TileRequest, TileRequestChannel, TileTree } from "./internal"; /** Handles requests to the cloud storage tile cache, if one is configured. If a tile's content is not found in the cache, subsequent requests for the same tile will diff --git a/core/frontend/src/tile/IModelTileTree.ts b/core/frontend/src/tile/IModelTileTree.ts index 1614bec03d34..2b283cfd74a2 100644 --- a/core/frontend/src/tile/IModelTileTree.ts +++ b/core/frontend/src/tile/IModelTileTree.ts @@ -7,19 +7,41 @@ */ import { assert, BeTimePoint, GuidString, Id64Array, Id64String } from "@itwin/core-bentley"; -import { Range3d, Transform } from "@itwin/core-geometry"; import { - BatchType, ContentIdProvider, EdgeOptions, ElementAlignedBox3d, ElementGeometryChange, FeatureAppearanceProvider, - IModelTileTreeId, IModelTileTreeProps, ModelGeometryChanges, RenderSchedule, TileProps, + BatchType, + ContentIdProvider, + EdgeOptions, + ElementAlignedBox3d, + ElementGeometryChange, + FeatureAppearanceProvider, + IModelTileTreeId, + IModelTileTreeProps, + ModelGeometryChanges, + RenderSchedule, + TileProps, } from "@itwin/core-common"; +import { Range3d, Transform } from "@itwin/core-geometry"; +import { GraphicalEditingScope } from "../GraphicalEditingScope"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; -import { GraphicalEditingScope } from "../GraphicalEditingScope"; -import { RenderSystem } from "../render/RenderSystem"; import { GraphicBranch } from "../render/GraphicBranch"; +import { RenderSystem } from "../render/RenderSystem"; import { - acquireImdlDecoder, DynamicIModelTile, ImdlDecoder, IModelTile, IModelTileParams, iModelTileParamsFromJSON, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileParams, TileRequest, - TileRequestChannel, TileTree, TileTreeParams, + acquireImdlDecoder, + DynamicIModelTile, + ImdlDecoder, + IModelTile, + IModelTileParams, + iModelTileParamsFromJSON, + Tile, + TileContent, + TileDrawArgs, + TileLoadPriority, + TileParams, + TileRequest, + TileRequestChannel, + TileTree, + TileTreeParams, } from "./internal"; /** @internal */ @@ -49,7 +71,12 @@ export interface IModelTileTreeParams extends TileTreeParams { } /** @internal */ -export function iModelTileTreeParamsFromJSON(props: IModelTileTreeProps, iModel: IModelConnection, modelId: Id64String, options: IModelTileTreeOptions): IModelTileTreeParams { +export function iModelTileTreeParamsFromJSON( + props: IModelTileTreeProps, + iModel: IModelConnection, + modelId: Id64String, + options: IModelTileTreeOptions, +): IModelTileTreeParams { const location = Transform.fromJSON(props.location); const { formatVersion, id, rootTile, contentIdQualifier, maxInitialTilesToSkip, geometryGuid } = props; const tileScreenSize = props.tileScreenSize ?? 512; @@ -163,7 +190,7 @@ class DynamicState { /** The tile tree has been disposed. */ class DisposedState { public readonly type = "disposed"; - public dispose(): void { } + public dispose(): void {} } const disposedState = new DisposedState(); @@ -314,7 +341,6 @@ class RootTile extends Tile { if (this._staticTreeContentRange && this.tree.contentRange) this._staticTreeContentRange.clone(this.tree.contentRange); - } public get tileScreenSize(): number { @@ -397,17 +423,35 @@ export class IModelTileTree extends TileTree { super.dispose(); } - public get maxDepth() { return 32; } - public get rootTile(): Tile { return this._rootTile; } + public get maxDepth() { + return 32; + } + public get rootTile(): Tile { + return this._rootTile; + } /** Exposed chiefly for tests. */ - public get staticBranch(): IModelTile { return this._rootTile.staticBranch; } - public get is3d() { return this._options.is3d; } - public override get isContentUnbounded() { return false; } - public get viewFlagOverrides() { return viewFlagOverrides; } - - public get batchType(): BatchType { return this._options.batchType; } - public get edgeOptions(): EdgeOptions | false { return this._options.edges; } - public get timeline(): RenderSchedule.ModelTimeline | undefined { return this._options.timeline; } + public get staticBranch(): IModelTile { + return this._rootTile.staticBranch; + } + public get is3d() { + return this._options.is3d; + } + public override get isContentUnbounded() { + return false; + } + public get viewFlagOverrides() { + return viewFlagOverrides; + } + + public get batchType(): BatchType { + return this._options.batchType; + } + public get edgeOptions(): EdgeOptions | false { + return this._options.edges; + } + public get timeline(): RenderSchedule.ModelTimeline | undefined { + return this._options.timeline; + } public override get loadPriority(): TileLoadPriority { // If the model has been modified, we want to prioritize keeping its graphics up to date. diff --git a/core/frontend/src/tile/ImdlDecoder.ts b/core/frontend/src/tile/ImdlDecoder.ts index df74a3b66650..3cc95d89769d 100644 --- a/core/frontend/src/tile/ImdlDecoder.ts +++ b/core/frontend/src/tile/ImdlDecoder.ts @@ -8,11 +8,11 @@ import type { ByteStream, Id64Set, Id64String } from "@itwin/core-bentley"; import { BatchType } from "@itwin/core-common"; +import type { ImdlTimeline } from "../common/imdl/ParseImdlDocument"; +import { BatchOptions } from "../common/render/BatchOptions"; import type { IModelConnection } from "../IModelConnection"; import { RenderSystem } from "../render/RenderSystem"; -import type { ImdlTimeline } from "../common/imdl/ParseImdlDocument"; import { acquireImdlParser, ImdlReaderResult, readImdlContent } from "./internal"; -import { BatchOptions } from "../common/render/BatchOptions"; /** Arguments supplied to [[ImdlDecoder.decode]]. * @internal diff --git a/core/frontend/src/tile/ImdlGraphicsCreator.ts b/core/frontend/src/tile/ImdlGraphicsCreator.ts index 8aa68d826fea..32e6ed796711 100644 --- a/core/frontend/src/tile/ImdlGraphicsCreator.ts +++ b/core/frontend/src/tile/ImdlGraphicsCreator.ts @@ -7,27 +7,25 @@ */ import { assert, Id64, JsonUtils } from "@itwin/core-bentley"; +import { ColorDef, Gradient, ImageSource, RenderMaterial, RenderTexture, TextureMapping } from "@itwin/core-common"; import { ClipVector, Point2d, Point3d, Range3d, Transform } from "@itwin/core-geometry"; -import { - ColorDef, Gradient, ImageSource, RenderMaterial, RenderTexture, TextureMapping, -} from "@itwin/core-common"; -import { AuxChannelTable } from "../common/internal/render/AuxChannelTable"; -import { createSurfaceMaterial } from "../common/internal/render/SurfaceParams"; import { ImdlModel as Imdl } from "../common/imdl/ImdlModel"; import { ImdlColorDef, ImdlNamedTexture, ImdlTextureMapping } from "../common/imdl/ImdlSchema"; import { convertFeatureTable, edgeParamsFromImdl, toMaterialParams, toVertexTable } from "../common/imdl/ParseImdlDocument"; +import { AuxChannelTable } from "../common/internal/render/AuxChannelTable"; +import { GraphicDescriptionImpl, isGraphicDescription } from "../common/internal/render/GraphicDescriptionBuilderImpl"; +import { createSurfaceMaterial } from "../common/internal/render/SurfaceParams"; import { VertexIndices } from "../common/internal/render/VertexIndices"; -import type { RenderGraphic } from "../render/RenderGraphic"; -import { GraphicBranch } from "../render/GraphicBranch"; -import type { RenderSystem } from "../render/RenderSystem"; -import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; -import type { IModelConnection } from "../IModelConnection"; +import { _implementationProhibited, _textures } from "../common/internal/Symbols"; import { GraphicDescription } from "../common/render/GraphicDescriptionBuilder"; -import { GraphicDescriptionImpl, isGraphicDescription } from "../common/internal/render/GraphicDescriptionBuilderImpl"; import { GraphicDescriptionContext } from "../common/render/GraphicDescriptionContext"; -import { _implementationProhibited, _textures } from "../common/internal/Symbols"; +import { InstancedGraphicParams } from "../common/render/InstancedGraphicParams"; +import type { IModelConnection } from "../IModelConnection"; import { RenderGeometry } from "../internal/render/RenderGeometry"; +import { GraphicBranch } from "../render/GraphicBranch"; import { createGraphicTemplate, GraphicTemplate, GraphicTemplateBatch, GraphicTemplateBranch } from "../render/GraphicTemplate"; +import type { RenderGraphic } from "../render/RenderGraphic"; +import type { RenderSystem } from "../render/RenderSystem"; /** Options provided to [[decodeImdlContent]]. * @internal @@ -99,10 +97,12 @@ async function loadNamedTextures(options: ImdlDecodeOptions): Promise { - if (tx) - result.set(name, tx); - })); + promises.push( + loadNamedTexture(name, namedTexture, options).then((tx) => { + if (tx) + result.set(name, tx); + }), + ); } } @@ -121,13 +121,18 @@ interface GraphicsOptions { patterns: Map; } -function constantLodParamPropsFromJson(propsJson: { repetitions?: number, offset?: number[], minDistClamp?: number, maxDistClamp?: number } | undefined): TextureMapping.ConstantLodParamProps | undefined { +function constantLodParamPropsFromJson( + propsJson: { repetitions?: number, offset?: number[], minDistClamp?: number, maxDistClamp?: number } | undefined, +): TextureMapping.ConstantLodParamProps | undefined { if (undefined === propsJson) return undefined; const constantLodPops: TextureMapping.ConstantLodParamProps = { repetitions: JsonUtils.asDouble(propsJson.repetitions, 1.0), - offset: { x: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[0]) : 0.0, y: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[1]) : 0.0 }, + offset: { + x: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[0]) : 0.0, + y: propsJson.offset ? JsonUtils.asDouble(propsJson.offset[1]) : 0.0, + }, minDistClamp: JsonUtils.asDouble(propsJson.minDistClamp, 1.0), maxDistClamp: JsonUtils.asDouble(propsJson.maxDistClamp, 4096.0 * 1024.0 * 1024.0), }; @@ -236,7 +241,7 @@ function getModifiers(primitive: Imdl.Primitive): { viOrigin?: Point3d, instance viOrigin: Point3d.fromJSON(mod.origin), }; default: - return { }; + return {}; } } @@ -414,9 +419,12 @@ export async function decodeImdlGraphics(options: ImdlDecodeOptions): Promise Promise.resolve(parseImdlDocument({ - ...options, - timeline, - })), + parse: async (options) => + Promise.resolve(parseImdlDocument({ + ...options, + timeline, + })), release: () => undefined, }; } diff --git a/core/frontend/src/tile/ImdlReader.ts b/core/frontend/src/tile/ImdlReader.ts index 88cdd1968b13..c639401df087 100644 --- a/core/frontend/src/tile/ImdlReader.ts +++ b/core/frontend/src/tile/ImdlReader.ts @@ -7,19 +7,17 @@ */ import { ByteStream, Id64Set, Id64String } from "@itwin/core-bentley"; +import { BatchType, decodeTileContentDescription, TileReadError, TileReadStatus } from "@itwin/core-common"; import { Point3d, Transform } from "@itwin/core-geometry"; -import { - BatchType, decodeTileContentDescription, TileReadError, TileReadStatus, -} from "@itwin/core-common"; +import { ImdlModel } from "../common/imdl/ImdlModel"; +import { convertFeatureTable, ImdlParseError, ImdlParserOptions, ImdlTimeline, parseImdlDocument } from "../common/imdl/ParseImdlDocument"; +import { BatchOptions } from "../common/render/BatchOptions"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { GraphicBranch } from "../render/GraphicBranch"; import { RenderGraphic } from "../render/RenderGraphic"; import { RenderSystem } from "../render/RenderSystem"; -import { ImdlModel } from "../common/imdl/ImdlModel"; -import { convertFeatureTable, ImdlParseError, ImdlParserOptions, ImdlTimeline, parseImdlDocument } from "../common/imdl/ParseImdlDocument"; import { decodeImdlGraphics, IModelTileContent } from "./internal"; -import { BatchOptions } from "../common/render/BatchOptions"; /* eslint-disable no-restricted-syntax */ @@ -37,10 +35,20 @@ export interface ImdlReaderResult extends IModelTileContent { * @public * @extensions */ -export async function readElementGraphics(bytes: Uint8Array, iModel: IModelConnection, modelId: Id64String, is3d: boolean, options?: BatchOptions | false): Promise { +export async function readElementGraphics( + bytes: Uint8Array, + iModel: IModelConnection, + modelId: Id64String, + is3d: boolean, + options?: BatchOptions | false, +): Promise { const stream = ByteStream.fromUint8Array(bytes); const reader = ImdlReader.create({ - stream, iModel, modelId, is3d, options, + stream, + iModel, + modelId, + is3d, + options, system: IModelApp.renderSystem, }); @@ -71,7 +79,9 @@ export interface ImdlReaderCreateArgs { } /** @internal */ -export async function readImdlContent(args: ImdlReaderCreateArgs & { parseDocument?: (parseOpts: ImdlParserOptions) => Promise }): Promise { +export async function readImdlContent( + args: ImdlReaderCreateArgs & { parseDocument?: (parseOpts: ImdlParserOptions) => Promise }, +): Promise { const isCanceled = args.isCanceled ?? (() => false); let content; try { diff --git a/core/frontend/src/tile/LRUTileList.ts b/core/frontend/src/tile/LRUTileList.ts index a90f4bb61296..1e084c69b5e7 100644 --- a/core/frontend/src/tile/LRUTileList.ts +++ b/core/frontend/src/tile/LRUTileList.ts @@ -92,7 +92,7 @@ export class TileUserIdSets extends SortedArray { public drop(userId: number): void { // Remove from all sets, and delete empty sets. let i = 0; - for (/* */; i < this._array.length; i++) { + for (; /* */ i < this._array.length; i++) { const set = this._array[i]; set.drop(userId); if (set.length === 0) @@ -101,7 +101,8 @@ export class TileUserIdSets extends SortedArray { // Collapse equivalent sets. i = 0; - for (let j = 1; j < this._array.length; /* */) { + for (let j = 1; j < this._array.length;/* */ + ) { if (this._array[i].equals(this._array[j])) { this._array.splice(i, 1); } else { diff --git a/core/frontend/src/tile/MeshoptCompression.ts b/core/frontend/src/tile/MeshoptCompression.ts index e55d10a2f950..cebcaa21339b 100644 --- a/core/frontend/src/tile/MeshoptCompression.ts +++ b/core/frontend/src/tile/MeshoptCompression.ts @@ -7,8 +7,8 @@ */ import { assert, Logger } from "@itwin/core-bentley"; -import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; import type { MeshoptDecoder } from "meshoptimizer"; +import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; import type { ExtMeshoptCompressionFilter, ExtMeshoptCompressionMode } from "../common/gltf/GltfSchema"; /** Arguments supplied to decodeMeshoptBuffer. diff --git a/core/frontend/src/tile/OPCFormatInterpreter.ts b/core/frontend/src/tile/OPCFormatInterpreter.ts index d730b58e0858..7cb9a4f9d89c 100644 --- a/core/frontend/src/tile/OPCFormatInterpreter.ts +++ b/core/frontend/src/tile/OPCFormatInterpreter.ts @@ -3,11 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BentleyError, Logger, LoggingMetaData, RealityDataStatus } from "@itwin/core-bentley"; import { Cartographic, EcefLocation } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; -import { ALong, CRSManager, Downloader, DownloaderXhr, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, PointCloudReader, UrlFS } from "@itwin/core-orbitgt"; +import { + ALong, + CRSManager, + Downloader, + DownloaderXhr, + OnlineEngine, + OPCReader, + OrbitGtBounds, + PageCachedFile, + PointCloudReader, + UrlFS, +} from "@itwin/core-orbitgt"; import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; -import { BentleyError, Logger, LoggingMetaData, RealityDataStatus } from "@itwin/core-bentley"; import { RealityDataError, SpatialLocationAndExtents } from "../RealityDataSource"; const loggerCategory: string = FrontendLoggerCategory.RealityData; @@ -16,7 +27,7 @@ const loggerCategory: string = FrontendLoggerCategory.RealityData; * This class provide methods used to interpret Orbit Point Cloud (OPC) format * @internal */ -export class OPCFormatInterpreter { +export class OPCFormatInterpreter { /** Gets an OPC file reader from a blobFileUrl * @param blobFileURL the name of the file. * @returns return a file reader open to read provided blob file @@ -34,8 +45,8 @@ export class OPCFormatInterpreter { // wrap a caching layer (16 MB) around the blob file const blobFileSize: ALong = await urlFS.getFileLength(blobFileURL); Logger.logTrace(loggerCategory, `OPC File Size is ${blobFileSize}`); - const blobFile: PageCachedFile = new PageCachedFile(urlFS, blobFileURL, blobFileSize, 128 * 1024 /* pageSize */, 128 /* maxPageCount */); - const fileReader: PointCloudReader = await OPCReader.openFile(blobFile, blobFileURL, true/* lazyLoading */); + const blobFile: PageCachedFile = new PageCachedFile(urlFS, blobFileURL, blobFileSize, 128 * 1024, /* pageSize */ 128 /* maxPageCount */); + const fileReader: PointCloudReader = await OPCReader.openFile(blobFile, blobFileURL, true /* lazyLoading */); return fileReader; } @@ -66,7 +77,14 @@ export class OPCFormatInterpreter { await CRSManager.ENGINE.prepareForArea(wgs84ECEFCrs, new OrbitGtBounds()); const ecefBounds = CRSManager.transformBounds(bounds, fileCrs, wgs84ECEFCrs); - const ecefRange = Range3d.createXYZXYZ(ecefBounds.getMinX(), ecefBounds.getMinY(), ecefBounds.getMinZ(), ecefBounds.getMaxX(), ecefBounds.getMaxY(), ecefBounds.getMaxZ()); + const ecefRange = Range3d.createXYZXYZ( + ecefBounds.getMinX(), + ecefBounds.getMinY(), + ecefBounds.getMinZ(), + ecefBounds.getMaxX(), + ecefBounds.getMaxY(), + ecefBounds.getMaxZ(), + ); const ecefCenter = ecefRange.localXYZToWorld(.5, .5, .5)!; const cartoCenter = Cartographic.fromEcef(ecefCenter)!; cartoCenter.height = 0; @@ -96,4 +114,3 @@ export class OPCFormatInterpreter { return spatialLocation; } } - diff --git a/core/frontend/src/tile/OrbitGtTileTree.ts b/core/frontend/src/tile/OrbitGtTileTree.ts index f8618631c635..67b86726166f 100644 --- a/core/frontend/src/tile/OrbitGtTileTree.ts +++ b/core/frontend/src/tile/OrbitGtTileTree.ts @@ -8,30 +8,72 @@ import { assert, BeTimePoint, compareStringsOrUndefined, Id64, Id64String } from "@itwin/core-bentley"; import { - BatchType, Cartographic, ColorDef, Feature, FeatureTable, Frustum, FrustumPlanes, GeoCoordStatus, OrbitGtBlobProps, PackedFeatureTable, QParams3d, - Quantization, RealityDataFormat, RealityDataProvider, RealityDataSourceKey, ViewFlagOverrides, + BatchType, + Cartographic, + ColorDef, + Feature, + FeatureTable, + Frustum, + FrustumPlanes, + GeoCoordStatus, + OrbitGtBlobProps, + PackedFeatureTable, + QParams3d, + Quantization, + RealityDataFormat, + RealityDataProvider, + RealityDataSourceKey, + ViewFlagOverrides, } from "@itwin/core-common"; import { Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { - ALong, CRSManager, Downloader, DownloaderXhr, OnlineEngine, OPCReader, OrbitGtAList, OrbitGtBlockIndex, OrbitGtBounds, OrbitGtCoordinate, - OrbitGtDataManager, OrbitGtFrameData, OrbitGtIProjectToViewForSort, OrbitGtIViewRequest, OrbitGtLevel, OrbitGtTileIndex, OrbitGtTileLoadSorter, - OrbitGtTransform, PageCachedFile, PointDataRaw, UrlFS, + ALong, + CRSManager, + Downloader, + DownloaderXhr, + OnlineEngine, + OPCReader, + OrbitGtAList, + OrbitGtBlockIndex, + OrbitGtBounds, + OrbitGtCoordinate, + OrbitGtDataManager, + OrbitGtFrameData, + OrbitGtIProjectToViewForSort, + OrbitGtIViewRequest, + OrbitGtLevel, + OrbitGtTileIndex, + OrbitGtTileLoadSorter, + OrbitGtTransform, + PageCachedFile, + PointDataRaw, + UrlFS, } from "@itwin/core-orbitgt"; import { calculateEcefToDbTransformAtLocation } from "../BackgroundMapGeometry"; +import { Mesh } from "../common/internal/render/MeshPrimitives"; import { DisplayStyleState } from "../DisplayStyleState"; import { HitDetail } from "../HitDetail"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { RealityDataSource } from "../RealityDataSource"; -import { Mesh } from "../common/internal/render/MeshPrimitives"; import { RenderGraphic } from "../render/RenderGraphic"; import { RenderMemory } from "../render/RenderMemory"; import { RenderSystem } from "../render/RenderSystem"; import { ViewingSpace } from "../ViewingSpace"; import { Viewport } from "../Viewport"; import { - RealityModelTileTree, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileParams, TileRequest, TileTree, TileTreeOwner, - TileTreeParams, TileTreeSupplier, TileUsageMarker, + RealityModelTileTree, + Tile, + TileContent, + TileDrawArgs, + TileLoadPriority, + TileParams, + TileRequest, + TileTree, + TileTreeOwner, + TileTreeParams, + TileTreeSupplier, + TileUsageMarker, } from "./internal"; const scratchRange = Range3d.create(); @@ -43,7 +85,8 @@ interface OrbitGtTreeId { } function compareSourceKeys(lhs: RealityDataSourceKey, rhs: RealityDataSourceKey): number { - return compareStringsOrUndefined(lhs.id, rhs.id) || compareStringsOrUndefined(lhs.format, rhs.format) || compareStringsOrUndefined(lhs.iTwinId, rhs.iTwinId); + return compareStringsOrUndefined(lhs.id, rhs.id) || compareStringsOrUndefined(lhs.format, rhs.format) || + compareStringsOrUndefined(lhs.iTwinId, rhs.iTwinId); } class OrbitGtTreeSupplier implements TileTreeSupplier { @@ -84,9 +127,16 @@ function transformFromOrbitGt(ogtTransform: OrbitGtTransform, result?: Transform result = Transform.createIdentity(); result.matrix.setRowValues( - ogtTransform.getElement(0, 0), ogtTransform.getElement(0, 1), ogtTransform.getElement(0, 2), - ogtTransform.getElement(1, 0), ogtTransform.getElement(1, 1), ogtTransform.getElement(1, 2), - ogtTransform.getElement(2, 0), ogtTransform.getElement(2, 1), ogtTransform.getElement(2, 2)); + ogtTransform.getElement(0, 0), + ogtTransform.getElement(0, 1), + ogtTransform.getElement(0, 2), + ogtTransform.getElement(1, 0), + ogtTransform.getElement(1, 1), + ogtTransform.getElement(1, 2), + ogtTransform.getElement(2, 0), + ogtTransform.getElement(2, 1), + ogtTransform.getElement(2, 2), + ); result.origin.x = ogtTransform.getElement(0, 3); result.origin.y = ogtTransform.getElement(1, 3); @@ -123,7 +173,9 @@ class OrbitGtTileTreeParams implements TileTreeParams { public id: string; public modelId: string; public iModel: IModelConnection; - public get priority(): TileLoadPriority { return TileLoadPriority.Context; } + public get priority(): TileLoadPriority { + return TileLoadPriority.Context; + } public constructor(rdSourceKey: RealityDataSourceKey, iModel: IModelConnection, modelId: Id64String, public location: Transform) { const key = rdSourceKey; @@ -134,13 +186,21 @@ class OrbitGtTileTreeParams implements TileTreeParams { } class OrbitGtRootTile extends Tile { - protected _loadChildren(_resolve: (children: Tile[] | undefined) => void, _reject: (error: Error) => void): void { } - public async requestContent(_isCanceled: () => boolean): Promise { return undefined; } - public get channel() { return IModelApp.tileAdmin.channels.getForHttp("itwinjs-orbitgit"); } - public async readContent(_data: TileRequest.ResponseData, _system: RenderSystem, _isCanceled?: () => boolean): Promise { return {}; } - public override freeMemory(): void { } + protected _loadChildren(_resolve: (children: Tile[] | undefined) => void, _reject: (error: Error) => void): void {} + public async requestContent(_isCanceled: () => boolean): Promise { + return undefined; + } + public get channel() { + return IModelApp.tileAdmin.channels.getForHttp("itwinjs-orbitgit"); + } + public async readContent(_data: TileRequest.ResponseData, _system: RenderSystem, _isCanceled?: () => boolean): Promise { + return {}; + } + public override freeMemory(): void {} - constructor(params: TileParams, tree: TileTree) { super(params, tree); } + constructor(params: TileParams, tree: TileTree) { + super(params, tree); + } } class OrbitGtViewRequest extends OrbitGtIViewRequest { @@ -171,9 +231,11 @@ class OrbitGtViewRequest extends OrbitGtIViewRequest { // get the world size of a screen pixel at the tile center const viewPt: Point3d = this._tileDrawArgs.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(worldCenter); const viewPt2: Point3d = new Point3d(viewPt.x + 1.0, viewPt.y, viewPt.z); - const pixelSizeAtCenter: number = this._tileDrawArgs.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance(this._tileDrawArgs.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2)); + const pixelSizeAtCenter: number = this._tileDrawArgs.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance( + this._tileDrawArgs.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2), + ); // stop splitting if the voxel size of the children becomes too small to improve quality - const split: boolean = (0.5 * voxelSize > 2.0 * pixelSizeAtCenter); + const split: boolean = 0.5 * voxelSize > 2.0 * pixelSizeAtCenter; return split; } } @@ -229,7 +291,13 @@ export class OrbitGtTileTree extends TileTree { public viewFlagOverrides: ViewFlagOverrides = {}; private _tileGraphics = new Map(); - public constructor(treeParams: TileTreeParams, private _dataManager: OrbitGtDataManager, cloudRange: Range3d, private _centerOffset: Vector3d, private _ecefTransform: Transform) { + public constructor( + treeParams: TileTreeParams, + private _dataManager: OrbitGtDataManager, + cloudRange: Range3d, + private _centerOffset: Vector3d, + private _ecefTransform: Transform, + ) { super(treeParams); const worldContentRange = this.iModelTransform.multiplyRange(cloudRange); @@ -254,10 +322,18 @@ export class OrbitGtTileTree extends TileTree { super.dispose(); } - protected _selectTiles(_args: TileDrawArgs): Tile[] { return []; } - public get is3d(): boolean { return true; } - public override get isContentUnbounded(): boolean { return false; } - public get maxDepth(): number | undefined { return undefined; } + protected _selectTiles(_args: TileDrawArgs): Tile[] { + return []; + } + public get is3d(): boolean { + return true; + } + public override get isContentUnbounded(): boolean { + return false; + } + public get maxDepth(): number | undefined { + return undefined; + } private _doPrune(olderThan: BeTimePoint) { for (const [key, graphic] of this._tileGraphics) @@ -280,7 +356,7 @@ export class OrbitGtTileTree extends TileTree { public draw(args: TileDrawArgs) { const debugControl = args.context.target.debugControl; const debugBuilder = (debugControl && debugControl.displayRealityTileRanges) ? args.context.createSceneGraphicBuilder() : undefined; - const doLogging = (debugControl && debugControl.logRealityTiles); + const doLogging = debugControl && debugControl.logRealityTiles; const viewRequest = new OrbitGtViewRequest(args, this._centerOffset); const levelsInView = new OrbitGtAList(); const blocksInView = new OrbitGtAList(); @@ -289,13 +365,22 @@ export class OrbitGtTileTree extends TileTree { this._dataManager.getViewTree().renderView3D(viewRequest, levelsInView, blocksInView, tilesInView, frameData.tilesToRender); this._dataManager.filterLoadList(levelsInView, blocksInView, tilesInView, frameData.levelsToLoad, frameData.blocksToLoad, frameData.tilesToLoad); - tilesInView.sort(new OrbitGtTileLoadSorter(this._dataManager.getViewTree(), new TileSortProjector(this.iModelTransform, args.context.viewingSpace, this._centerOffset))); + tilesInView.sort( + new OrbitGtTileLoadSorter( + this._dataManager.getViewTree(), + new TileSortProjector(this.iModelTransform, args.context.viewingSpace, this._centerOffset), + ), + ); let totalPointCount = 0; const tileCount = frameData.tilesToRender.size(); // Inform TileAdmin about tiles we are handling ourselves... - IModelApp.tileAdmin.addExternalTilesForUser(args.context.viewport, { requested: frameData.tilesToLoad.size() + (frameData.hasMissingData() ? 1 : 0), selected: tileCount, ready: tileCount }); + IModelApp.tileAdmin.addExternalTilesForUser(args.context.viewport, { + requested: frameData.tilesToLoad.size() + (frameData.hasMissingData() ? 1 : 0), + selected: tileCount, + ready: tileCount, + }); if (debugBuilder) debugBuilder.setSymbology(ColorDef.red, ColorDef.red, 1); @@ -364,9 +449,8 @@ export namespace OrbitGtTileTree { modelId?: Id64String; } function isValidSASToken(downloadUrl: string): boolean { - // Create fake URL for and parameter parsing and SAS token URI parsing - if(!downloadUrl.startsWith("http")) + if (!downloadUrl.startsWith("http")) downloadUrl = `http://x.com/x?${downloadUrl}`; const sasUrl = new URL(downloadUrl); @@ -383,16 +467,19 @@ export namespace OrbitGtTileTree { return false; } function isValidOrbitGtBlobProps(props: OrbitGtBlobProps): boolean { - // Check main OrbitGtBlobProps fields are defined - if(!props.accountName || !props.containerName || !props.blobFileName || !props.sasToken) + if (!props.accountName || !props.containerName || !props.blobFileName || !props.sasToken) return false; // Check SAS token is valid return isValidSASToken(props.sasToken); } - export async function createOrbitGtTileTree(rdSourceKey: RealityDataSourceKey, iModel: IModelConnection, modelId: Id64String): Promise { + export async function createOrbitGtTileTree( + rdSourceKey: RealityDataSourceKey, + iModel: IModelConnection, + modelId: Id64String, + ): Promise { const rdSource = await RealityDataSource.fromKey(rdSourceKey, iModel.iTwinId); const isContextShare = rdSourceKey.provider === RealityDataProvider.ContextShare; const isTilestUrl = rdSourceKey.provider === RealityDataProvider.TilesetUrl; @@ -400,7 +487,7 @@ export namespace OrbitGtTileTree { let blobStringUrl: string; if (isContextShare) { const realityData = rdSource ? rdSource.realityData : undefined; - if (rdSource === undefined || realityData === undefined ) + if (rdSource === undefined || realityData === undefined) return undefined; const docRootName = realityData.rootDocument; if (!docRootName) @@ -414,7 +501,7 @@ export namespace OrbitGtTileTree { const orbitGtBlobProps = RealityDataSource.createOrbitGtBlobPropsFromKey(rdSourceKey); if (orbitGtBlobProps === undefined) return undefined; - if(!isValidOrbitGtBlobProps(orbitGtBlobProps)) + if (!isValidOrbitGtBlobProps(orbitGtBlobProps)) return undefined; const { accountName, containerName, blobFileName, sasToken } = orbitGtBlobProps; blobStringUrl = blobFileName; @@ -432,8 +519,8 @@ export namespace OrbitGtTileTree { const urlFS: UrlFS = new UrlFS(); const blobFileSize: ALong = await urlFS.getFileLength(blobStringUrl); const cacheKilobytes = 128; - const cachedBlobFile = new PageCachedFile(urlFS, blobStringUrl, blobFileSize, cacheKilobytes * 1024 /* pageSize*/, 128/* maxPageCount*/); - const pointCloudReader = await OPCReader.openFile(cachedBlobFile, blobStringUrl, true/* lazyLoading*/); + const cachedBlobFile = new PageCachedFile(urlFS, blobStringUrl, blobFileSize, cacheKilobytes * 1024, /* pageSize*/ 128 /* maxPageCount*/); + const pointCloudReader = await OPCReader.openFile(cachedBlobFile, blobStringUrl, true /* lazyLoading*/); let pointCloudCRS = pointCloudReader.getFileCRS(); if (pointCloudCRS == null) pointCloudCRS = ""; @@ -448,7 +535,9 @@ export namespace OrbitGtTileTree { await CRSManager.ENGINE.prepareForArea(pointCloudCRS, pointCloudBounds); const wgs84CRS = "4978"; await CRSManager.ENGINE.prepareForArea(wgs84CRS, new OrbitGtBounds()); - const pointCloudToEcef = transformFromOrbitGt(CRSManager.createTransform(pointCloudCRS, new OrbitGtCoordinate(pointCloudCenter.x, pointCloudCenter.y, pointCloudCenter.z), wgs84CRS)); + const pointCloudToEcef = transformFromOrbitGt( + CRSManager.createTransform(pointCloudCRS, new OrbitGtCoordinate(pointCloudCenter.x, pointCloudCenter.y, pointCloudCenter.z), wgs84CRS), + ); const pointCloudCenterToEcef = pointCloudToEcef.multiplyTransformTransform(addCloudCenter); ecefTransform.setFrom(pointCloudCenterToEcef); @@ -462,7 +551,7 @@ export namespace OrbitGtTileTree { const ecefOrigin = pointCloudCenterToEcef.getOrigin(); const dbOrigin = ecefToDb.multiplyPoint3d(ecefOrigin); const realityOriginToProjectDistance = iModel.projectExtents.distanceToPoint(dbOrigin); - const maxProjectDistance = 1E5; // Only use the project GCS projection if within 100KM of the project. Don't attempt to use GCS if global reality model or in another locale - Results will be unreliable. + const maxProjectDistance = 1E5; // Only use the project GCS projection if within 100KM of the project. Don't attempt to use GCS if global reality model or in another locale - Results will be unreliable. if (realityOriginToProjectDistance < maxProjectDistance) { const cartographicOrigin = Cartographic.fromEcef(ecefOrigin); const geoConverter = iModel.noGcsDefined ? undefined : iModel.geoServices.getConverter("WGS84"); @@ -497,8 +586,12 @@ export class OrbitGtTreeReference extends RealityModelTileTree.Reference { protected _rdSourceKey: RealityDataSourceKey; private readonly _modelId: Id64String; - public override get castsShadows() { return false; } - public override get modelId() { return this._modelId; } + public override get castsShadows() { + return false; + } + public override get modelId() { + return this._modelId; + } public constructor(props: OrbitGtTileTree.ReferenceProps) { super(props); diff --git a/core/frontend/src/tile/PntsReader.ts b/core/frontend/src/tile/PntsReader.ts index 65f902b6aaad..a1beffd1f91b 100644 --- a/core/frontend/src/tile/PntsReader.ts +++ b/core/frontend/src/tile/PntsReader.ts @@ -7,11 +7,11 @@ */ import { ByteStream, Id64String, Logger, utf8ToString } from "@itwin/core-bentley"; -import { Point3d, Range3d } from "@itwin/core-geometry"; import { BatchType, Feature, FeatureTable, PackedFeatureTable, PntsHeader, QParams3d, QPoint3d, Quantization } from "@itwin/core-common"; +import { Point3d, Range3d } from "@itwin/core-geometry"; import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; -import { IModelConnection } from "../IModelConnection"; import { Mesh } from "../common/internal/render/MeshPrimitives"; +import { IModelConnection } from "../IModelConnection"; import { RenderGraphic } from "../render/RenderGraphic"; import { RenderSystem } from "../render/RenderSystem"; import { RealityTile } from "./internal"; @@ -202,7 +202,14 @@ async function decodeDracoPointCloud(buf: Uint8Array): Promise { +export async function readPointCloudTileContent( + stream: ByteStream, + iModel: IModelConnection, + modelId: Id64String, + _is3d: boolean, + tile: RealityTile, + system: RenderSystem, +): Promise<{ graphic: RenderGraphic | undefined, rtcCenter: Point3d | undefined }> { let graphic; let rtcCenter; const header = new PntsHeader(stream); diff --git a/core/frontend/src/tile/PrimaryTileTree.ts b/core/frontend/src/tile/PrimaryTileTree.ts index 0a01840da317..848fb6b42218 100644 --- a/core/frontend/src/tile/PrimaryTileTree.ts +++ b/core/frontend/src/tile/PrimaryTileTree.ts @@ -6,27 +6,44 @@ * @module Tiles */ +import { assert, comparePossiblyUndefined, compareStrings, Id64String, OrderedId64Iterable } from "@itwin/core-bentley"; import { - assert, comparePossiblyUndefined, compareStrings, Id64String, - OrderedId64Iterable, -} from "@itwin/core-bentley"; -import { - BatchType, compareIModelTileTreeIds, FeatureAppearance, FeatureAppearanceProvider, HiddenLine, iModelTileTreeIdToString, MapLayerSettings, ModelMapLayerSettings, - PrimaryTileTreeId, RenderMode, RenderSchedule, SpatialClassifier, ViewFlagOverrides, ViewFlagsProperties, + BatchType, + compareIModelTileTreeIds, + FeatureAppearance, + FeatureAppearanceProvider, + HiddenLine, + iModelTileTreeIdToString, + MapLayerSettings, + ModelMapLayerSettings, + PrimaryTileTreeId, + RenderMode, + RenderSchedule, + SpatialClassifier, + ViewFlagOverrides, + ViewFlagsProperties, } from "@itwin/core-common"; import { Range3d, StringifiedClipVector, Transform } from "@itwin/core-geometry"; +import { AnimationNodeId } from "../common/internal/render/AnimationNodeId"; import { DisplayStyleState } from "../DisplayStyleState"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { GeometricModel3dState, GeometricModelState } from "../ModelState"; import { formatAnimationBranchId } from "../render/GraphicBranch"; -import { AnimationNodeId } from "../common/internal/render/AnimationNodeId"; import { RenderClipVolume } from "../render/RenderClipVolume"; import { SpatialViewState } from "../SpatialViewState"; import { SceneContext } from "../ViewContext"; import { AttachToViewportArgs, ViewState, ViewState3d } from "../ViewState"; import { - IModelTileTree, IModelTileTreeParams, iModelTileTreeParamsFromJSON, MapLayerTileTreeReference, TileDrawArgs, TileGraphicType, TileTree, TileTreeOwner, TileTreeReference, + IModelTileTree, + IModelTileTreeParams, + iModelTileTreeParamsFromJSON, + MapLayerTileTreeReference, + TileDrawArgs, + TileGraphicType, + TileTree, + TileTreeOwner, + TileTreeReference, TileTreeSupplier, } from "./internal"; @@ -54,7 +71,7 @@ class PrimaryTreeSupplier implements TileTreeSupplier { public compareTileTreeIds(lhs: PrimaryTreeId, rhs: PrimaryTreeId): number { // NB: we don't compare isPlanProjection or is3d - they should always have the same value for a given modelId. return compareStrings(lhs.modelId, rhs.modelId) || compareIModelTileTreeIds(lhs.treeId, rhs.treeId) - || comparePossiblyUndefined((x, y) => x.compareTo(y), lhs.timeline, rhs.timeline); + || comparePossiblyUndefined((x, y) => x.compareTo(y), lhs.timeline, rhs.timeline); } public async createTileTree(id: PrimaryTreeId, iModel: IModelConnection): Promise { @@ -98,7 +115,11 @@ class PrimaryTreeSupplier implements TileTreeSupplier { return iModel.tiles.getTileTreeOwner(id, this); } - public addModelsAnimatedByScript(modelIds: Set, scriptSourceId: Id64String, trees: Iterable<{ id: PrimaryTreeId, owner: TileTreeOwner }>): void { + public addModelsAnimatedByScript( + modelIds: Set, + scriptSourceId: Id64String, + trees: Iterable<{ id: PrimaryTreeId, owner: TileTreeOwner }>, + ): void { // Note: This is invoked when an element hosting a schedule script is updated - it doesn't care about frontend schedule scripts. for (const tree of trees) if (scriptSourceId === tree.id.treeId.animationId) @@ -141,7 +162,13 @@ class PrimaryTreeReference extends TileTreeReference { private readonly _sectionCutAppearanceProvider?: FeatureAppearanceProvider; protected readonly _animationTransformNodeId?: number; - public constructor(view: ViewState, model: GeometricModelState, planProjection: boolean, transformNodeId: number | undefined, sectionClip?: StringifiedClipVector) { + public constructor( + view: ViewState, + model: GeometricModelState, + planProjection: boolean, + transformNodeId: number | undefined, + sectionClip?: StringifiedClipVector, + ) { super(); this.view = view; this.model = model; @@ -309,7 +336,9 @@ export class AnimatedTreeReference extends PrimaryTreeReference { } class PlanProjectionTreeReference extends PrimaryTreeReference { - private get _view3d() { return this.view as ViewState3d; } + private get _view3d() { + return this.view as ViewState3d; + } private readonly _baseTransform = Transform.createIdentity(); public constructor(view: ViewState3d, model: GeometricModelState, sectionCut?: StringifiedClipVector) { @@ -408,7 +437,9 @@ class MaskTreeReference extends TileTreeReference { protected _id: PrimaryTreeId; private _owner: TileTreeOwner; public readonly model: GeometricModelState; - public override get castsShadows() { return false; } + public override get castsShadows() { + return false; + } public constructor(view: ViewState, model: GeometricModelState) { super(); this.model = model; @@ -445,9 +476,19 @@ export function createMaskTreeReference(view: ViewState, model: GeometricModelSt export class ModelMapLayerTileTreeReference extends MapLayerTileTreeReference { private _id: PrimaryTreeId; private _owner: TileTreeOwner; - public get isPlanar() { return true; } - public get activeClassifier() { return this._classifier; } - public constructor(layerSettings: MapLayerSettings, private _classifier: SpatialClassifier, layerIndex: number, iModel: IModelConnection, private _source?: DisplayStyleState) { + public get isPlanar() { + return true; + } + public get activeClassifier() { + return this._classifier; + } + public constructor( + layerSettings: MapLayerSettings, + private _classifier: SpatialClassifier, + layerIndex: number, + iModel: IModelConnection, + private _source?: DisplayStyleState, + ) { super(layerSettings, layerIndex, iModel); this._id = { modelId: _classifier.modelId, @@ -475,7 +516,7 @@ export class ModelMapLayerTileTreeReference extends MapLayerTileTreeReference { public get viewFlags(): Partial { return { renderMode: RenderMode.SmoothShade, - transparency: true, // Igored for point clouds as they don't support transparency. + transparency: true, // Igored for point clouds as they don't support transparency. textures: true, lighting: false, shadows: false, @@ -489,8 +530,12 @@ export class ModelMapLayerTileTreeReference extends MapLayerTileTreeReference { } } /** @internal */ -export function createModelMapLayerTileTreeReference(layerSettings: ModelMapLayerSettings, layerIndex: number, iModel: IModelConnection): ModelMapLayerTileTreeReference | undefined { - const classifier = SpatialClassifier.fromModelMapLayer(layerSettings); +export function createModelMapLayerTileTreeReference( + layerSettings: ModelMapLayerSettings, + layerIndex: number, + iModel: IModelConnection, +): ModelMapLayerTileTreeReference | undefined { + const classifier = SpatialClassifier.fromModelMapLayer(layerSettings); return classifier ? new ModelMapLayerTileTreeReference(layerSettings, classifier, layerIndex, iModel) : undefined; } @@ -503,7 +548,11 @@ export interface SpatialTileTreeReferences extends Iterable { /** Requests that the set of [[TileTreeReference]]s be updated to match the current state of the view, e.g., after the model selector's contents have changed. */ update(): void; /** See SpatialViewState.setTileTreeReferencesDeactivated. */ - setDeactivated(modelIds: Id64String | Id64String[] | undefined, deactivated: boolean | undefined, refs: "all" | "animated" | "primary" | "section" | number[]): void; + setDeactivated( + modelIds: Id64String | Id64String[] | undefined, + deactivated: boolean | undefined, + refs: "all" | "animated" | "primary" | "section" | number[], + ): void; /** See SpatialViewState.attachToViewport. */ attachToViewport(args: AttachToViewportArgs): void; /** See SpatialViewState.detachFromViewport. */ @@ -570,9 +619,10 @@ class SpatialModelRefs implements Iterable { this._animatedRefs.length = 0; const nodeIds = script?.script.getTransformBatchIds(ref.model.id); - if (nodeIds) + if (nodeIds) { for (const nodeId of nodeIds) this._animatedRefs.push(new AnimatedTreeReference(ref.view, ref.model, nodeId)); + } } public updateSectionCut(clip: StringifiedClipVector | undefined): void { @@ -606,9 +656,10 @@ class SpatialModelRefs implements Iterable { if (("all" === which || "section" === which) && this._sectionCutRef) this._sectionCutRef.deactivated = deactivated ?? !this._sectionCutRef.deactivated; - if (("all" === which || "animated" === which)) + if (("all" === which || "animated" === which)) { for (const ref of this._animatedRefs) ref.deactivated = deactivated ?? !ref.deactivated; + } } private get _primaryRef(): PrimaryTreeReference | undefined { @@ -644,8 +695,8 @@ class SpatialRefs implements SpatialTileTreeReferences { this._allLoaded = false; } - public attachToViewport() { } - public detachFromViewport() { } + public attachToViewport() {} + public detachFromViewport() {} public *[Symbol.iterator](): Iterator { this.load(); @@ -659,7 +710,11 @@ class SpatialRefs implements SpatialTileTreeReferences { } } - public setDeactivated(modelIds: Id64String | Id64String[] | undefined, deactivated: boolean, refs: "all" | "animated" | "primary" | "section" | number[]): void { + public setDeactivated( + modelIds: Id64String | Id64String[] | undefined, + deactivated: boolean, + refs: "all" | "animated" | "primary" | "section" | number[], + ): void { if (undefined === modelIds) { for (const model of this._refs.values()) model.setDeactivated(deactivated, refs); @@ -684,7 +739,7 @@ class SpatialRefs implements SpatialTileTreeReferences { for (const modelId of modelIds) { if (!this._excludedModels?.has(modelId)) { const model = this._view.iModel.models.getLoaded(modelId); - assert(model !== undefined); // Models should be loaded by RealityModelTileTree + assert(model !== undefined); // Models should be loaded by RealityModelTileTree if (model?.asGeometricModel) { const treeRef = createMaskTreeReference(this._view, model.asGeometricModel); maskTreeRefs.push(treeRef); @@ -699,7 +754,9 @@ class SpatialRefs implements SpatialTileTreeReferences { * For non-batched tile trees this is not needed, so just return undefined. * @internal */ - public getModelsNotInMask(_maskModels: OrderedId64Iterable | undefined, _useVisible: boolean): Id64String[] | undefined { return undefined; } + public getModelsNotInMask(_maskModels: OrderedId64Iterable | undefined, _useVisible: boolean): Id64String[] | undefined { + return undefined; + } private load(): void { if (!this._allLoaded) { @@ -711,9 +768,10 @@ class SpatialRefs implements SpatialTileTreeReferences { const prevScript = this._scheduleScript; if (curScript !== prevScript) { this._scheduleScript = curScript; - if (!curScript || !prevScript || !curScript.script.equals(prevScript.script)) + if (!curScript || !prevScript || !curScript.script.equals(prevScript.script)) { for (const ref of this._refs.values()) ref.updateAnimated(curScript); + } } const sectionCut = this.getSectionCutFromView(); diff --git a/core/frontend/src/tile/RealityModelTileTree.ts b/core/frontend/src/tile/RealityModelTileTree.ts index 322f9509b4fe..d30b569aaa04 100644 --- a/core/frontend/src/tile/RealityModelTileTree.ts +++ b/core/frontend/src/tile/RealityModelTileTree.ts @@ -7,12 +7,27 @@ */ import { - assert, compareBooleans, compareBooleansOrUndefined, compareNumbers, comparePossiblyUndefined, compareStrings, - compareStringsOrUndefined, CompressedId64Set, Id64, Id64String, + assert, + compareBooleans, + compareBooleansOrUndefined, + compareNumbers, + comparePossiblyUndefined, + compareStrings, + compareStringsOrUndefined, + CompressedId64Set, + Id64, + Id64String, } from "@itwin/core-bentley"; import { - Cartographic, DefaultSupportedTypes, GeoCoordStatus, PlanarClipMaskPriority, PlanarClipMaskSettings, - RealityDataProvider, RealityDataSourceKey, RealityModelDisplaySettings, ViewFlagOverrides, + Cartographic, + DefaultSupportedTypes, + GeoCoordStatus, + PlanarClipMaskPriority, + PlanarClipMaskSettings, + RealityDataProvider, + RealityDataSourceKey, + RealityModelDisplaySettings, + ViewFlagOverrides, } from "@itwin/core-common"; import { Angle, Constant, Ellipsoid, Matrix3d, Point3d, Range3d, Ray3d, Transform, TransformProps, Vector3d, XYZ } from "@itwin/core-geometry"; import { calculateEcefToDbTransformAtLocation } from "../BackgroundMapGeometry"; @@ -23,14 +38,32 @@ import { IModelConnection } from "../IModelConnection"; import { PlanarClipMaskState } from "../PlanarClipMaskState"; import { RealityDataSource } from "../RealityDataSource"; import { RenderMemory } from "../render/RenderMemory"; +import { SpatialClassifiersState } from "../SpatialClassifiersState"; import { SceneContext } from "../ViewContext"; import { ViewState } from "../ViewState"; import { - BatchedTileIdMap, CesiumIonAssetProvider, createClassifierTileTreeReference, createDefaultViewFlagOverrides, DisclosedTileTreeSet, GeometryTileTreeReference, - getGcsConverterAvailable, RealityTile, RealityTileLoader, RealityTileParams, RealityTileTree, RealityTileTreeParams, SpatialClassifierTileTreeReference, Tile, - TileDrawArgs, TileLoadPriority, TileRequest, TileTree, TileTreeOwner, TileTreeReference, TileTreeSupplier, + BatchedTileIdMap, + CesiumIonAssetProvider, + createClassifierTileTreeReference, + createDefaultViewFlagOverrides, + DisclosedTileTreeSet, + GeometryTileTreeReference, + getGcsConverterAvailable, + RealityTile, + RealityTileLoader, + RealityTileParams, + RealityTileTree, + RealityTileTreeParams, + SpatialClassifierTileTreeReference, + Tile, + TileDrawArgs, + TileLoadPriority, + TileRequest, + TileTree, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, } from "./internal"; -import { SpatialClassifiersState } from "../SpatialClassifiersState"; function getUrl(content: any) { return content ? (content.url ? content.url : content.uri) : undefined; @@ -65,7 +98,8 @@ namespace RealityTreeId { } function compareRealityDataSourceKeys(lhs: RealityDataSourceKey, rhs: RealityDataSourceKey): number { - return compareStringsOrUndefined(lhs.id, rhs.id) || compareStringsOrUndefined(lhs.format, rhs.format) || compareStringsOrUndefined(lhs.iTwinId, rhs.iTwinId); + return compareStringsOrUndefined(lhs.id, rhs.id) || compareStringsOrUndefined(lhs.format, rhs.format) || + compareStringsOrUndefined(lhs.iTwinId, rhs.iTwinId); } export function compareWithoutModelId(lhs: RealityTreeId, rhs: RealityTreeId): number { @@ -126,12 +160,20 @@ export function createRealityTileTreeReference(props: RealityModelTileTree.Refer } const zeroPoint = Point3d.createZero(); -const earthEllipsoid = Ellipsoid.createCenterMatrixRadii(zeroPoint, undefined, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.polar); +const earthEllipsoid = Ellipsoid.createCenterMatrixRadii( + zeroPoint, + undefined, + Constant.earthRadiusWGS84.equator, + Constant.earthRadiusWGS84.equator, + Constant.earthRadiusWGS84.polar, +); const scratchRay = Ray3d.createXAxis(); /** @internal */ export class RealityTileRegion { - constructor(values: { minLongitude: number, minLatitude: number, minHeight: number, maxLongitude: number, maxLatitude: number, maxHeight: number }) { + constructor( + values: { minLongitude: number, minLatitude: number, minHeight: number, maxLongitude: number, maxLatitude: number, maxHeight: number }, + ) { this.minLongitude = values.minLongitude; this.minLatitude = values.minLatitude; this.minHeight = values.minHeight; @@ -157,7 +199,8 @@ export class RealityTileRegion { } public static isGlobal(boundingVolume: any) { - return Array.isArray(boundingVolume?.region) && (boundingVolume.region[2] - boundingVolume.region[0]) > Angle.piRadians && (boundingVolume.region[3] - boundingVolume.region[1]) > Angle.piOver2Radians; + return Array.isArray(boundingVolume?.region) && (boundingVolume.region[2] - boundingVolume.region[0]) > Angle.piRadians && + (boundingVolume.region[3] - boundingVolume.region[1]) > Angle.piOver2Radians; } public getRange(): { range: Range3d, corners?: Point3d[] } { const maxAngle = Math.max(Math.abs(this.maxLatitude - this.minLatitude), Math.abs(this.maxLongitude - this.minLongitude)); @@ -166,11 +209,11 @@ export class RealityTileRegion { if (maxAngle < Math.PI / 8) { corners = new Array(8); const chordTolerance = (1 - Math.cos(maxAngle / 2)) * Constant.earthRadiusWGS84.polar; - const addEllipsoidCorner = ((long: number, lat: number, index: number) => { + const addEllipsoidCorner = (long: number, lat: number, index: number) => { const ray = earthEllipsoid.radiansToUnitNormalRay(long, lat, scratchRay)!; corners[index] = ray.fractionToPoint(this.minHeight - chordTolerance); corners[index + 4] = ray.fractionToPoint(this.maxHeight + chordTolerance); - }); + }; addEllipsoidCorner(this.minLongitude, this.minLatitude, 0); addEllipsoidCorner(this.minLongitude, this.maxLatitude, 1); addEllipsoidCorner(this.maxLongitude, this.minLatitude, 2); @@ -205,7 +248,7 @@ export class RealityModelTileUtils { for (let j = 0; j < 2; j++) { for (let k = 0; k < 2; k++) { for (let l = 0; l < 2; l++) { - corners.push(center.plus3Scaled(ux, (j ? -1.0 : 1.0), uy, (k ? -1.0 : 1.0), uz, (l ? -1.0 : 1.0))); + corners.push(center.plus3Scaled(ux, j ? -1.0 : 1.0, uy, k ? -1.0 : 1.0, uz, l ? -1.0 : 1.0)); } } } @@ -221,10 +264,9 @@ export class RealityModelTileUtils { return { range: regionRange.range, corners: regionRange.corners, region }; } return range ? { range, corners } : undefined; - } public static maximumSizeFromGeometricTolerance(range: Range3d, geometricError: number): number { - const minToleranceRatio = true === IModelApp.renderSystem.isMobile ? IModelApp.tileAdmin.mobileRealityTileMinToleranceRatio : 1.0; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. + const minToleranceRatio = true === IModelApp.renderSystem.isMobile ? IModelApp.tileAdmin.mobileRealityTileMinToleranceRatio : 1.0; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. // NB: We increase the above minToleranceRatio on mobile devices in order to help avoid pruning too often based on the memory threshold for // pruning currently used by reality tile trees on mobile. @@ -232,7 +274,12 @@ export class RealityModelTileUtils { return minToleranceRatio * range.diagonal().magnitude() / geometricError; } public static transformFromJson(jTrans: number[] | undefined): Transform { - return (jTrans === undefined) ? Transform.createIdentity() : Transform.createOriginAndMatrix(Point3d.create(jTrans[12], jTrans[13], jTrans[14]), Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10])); + return (jTrans === undefined) + ? Transform.createIdentity() + : Transform.createOriginAndMatrix( + Point3d.create(jTrans[12], jTrans[13], jTrans[14]), + Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10]), + ); } } @@ -256,7 +303,7 @@ class RealityModelTileTreeProps { this.tilesetJson = root; this.rdSource = rdSource; this.location = tilesetToDbTransform; - this.doDrapeBackgroundMap = (json.root && json.root.SMMasterHeader && SMTextureType.Streaming === json.root.SMMasterHeader.IsTextured); + this.doDrapeBackgroundMap = json.root && json.root.SMMasterHeader && SMTextureType.Streaming === json.root.SMMasterHeader.IsTextured; if (json.asset.gltfUpAxis === undefined || json.asset.gltfUpAxis === "y" || json.asset.gltfUpAxis === "Y") this.yAxisUp = true; } @@ -270,11 +317,24 @@ class RealityModelTileTreeParams implements RealityTileTreeParams { public loader: RealityModelTileLoader; public rootTile: RealityTileParams; - public get location() { return this.loader.tree.location; } - public get yAxisUp() { return this.loader.tree.yAxisUp; } - public get priority() { return this.loader.priority; } + public get location() { + return this.loader.tree.location; + } + public get yAxisUp() { + return this.loader.tree.yAxisUp; + } + public get priority() { + return this.loader.priority; + } - public constructor(tileTreeId: string, iModel: IModelConnection, modelId: Id64String, loader: RealityModelTileLoader, public readonly gcsConverterAvailable: boolean, public readonly rootToEcef: Transform | undefined) { + public constructor( + tileTreeId: string, + iModel: IModelConnection, + modelId: Id64String, + loader: RealityModelTileLoader, + public readonly gcsConverterAvailable: boolean, + public readonly rootToEcef: Transform | undefined, + ) { this.loader = loader; this.id = tileTreeId; this.modelId = modelId; @@ -340,7 +400,9 @@ class RealityModelTileProps implements RealityTileParams { this.noContentButTerminateOnSelection = true; } - this.maximumSize = (this.noContentButTerminateOnSelection || hasContents) ? RealityModelTileUtils.maximumSizeFromGeometricTolerance(Range3d.fromJSON(this.range), json.geometricError) : 0; + this.maximumSize = (this.noContentButTerminateOnSelection || hasContents) + ? RealityModelTileUtils.maximumSizeFromGeometricTolerance(Range3d.fromJSON(this.range), json.geometricError) + : 0; if (args.usesGeometricError) this.geometricError = json.geometricError; } @@ -348,7 +410,7 @@ class RealityModelTileProps implements RealityTileParams { /** @internal */ class FindChildResult { - constructor(public id: string, public json: any, public transformToRoot?: Transform) { } + constructor(public id: string, public json: any, public transformToRoot?: Transform) {} } /** @internal */ @@ -388,9 +450,10 @@ function addUrlPrefix(subTree: any, prefix: string) { subTree.content.uri = assembleUrl(prefix, subTree.content.uri); } - if (undefined !== subTree.children) + if (undefined !== subTree.children) { for (const child of subTree.children) addUrlPrefix(child, prefix); + } } /** @internal */ @@ -414,7 +477,11 @@ class RealityModelTileLoader extends RealityTileLoader { private _viewFlagOverrides: ViewFlagOverrides; private readonly _deduplicateVertices: boolean; - public constructor(tree: RealityModelTileTreeProps, batchedIdMap?: BatchedTileIdMap, opts?: { deduplicateVertices?: boolean, produceGeometry?: boolean }) { + public constructor( + tree: RealityModelTileTreeProps, + batchedIdMap?: BatchedTileIdMap, + opts?: { deduplicateVertices?: boolean, produceGeometry?: boolean }, + ) { super(opts?.produceGeometry ?? false); this.tree = tree; this._batchedIdMap = batchedIdMap; @@ -433,15 +500,31 @@ class RealityModelTileLoader extends RealityTileLoader { this._viewFlagOverrides.wiremesh = undefined; } - public get doDrapeBackgroundMap(): boolean { return this.tree.doDrapeBackgroundMap; } - public override get wantDeduplicatedVertices() { return this._deduplicateVertices; } + public get doDrapeBackgroundMap(): boolean { + return this.tree.doDrapeBackgroundMap; + } + public override get wantDeduplicatedVertices() { + return this._deduplicateVertices; + } - public get maxDepth(): number { return Number.MAX_SAFE_INTEGER; } - public get minDepth(): number { return 0; } - public get priority(): TileLoadPriority { return TileLoadPriority.Context; } - public override getBatchIdMap(): BatchedTileIdMap | undefined { return this._batchedIdMap; } - public get clipLowResolutionTiles(): boolean { return true; } - public override get viewFlagOverrides(): ViewFlagOverrides { return this._viewFlagOverrides; } + public get maxDepth(): number { + return Number.MAX_SAFE_INTEGER; + } + public get minDepth(): number { + return 0; + } + public get priority(): TileLoadPriority { + return TileLoadPriority.Context; + } + public override getBatchIdMap(): BatchedTileIdMap | undefined { + return this._batchedIdMap; + } + public get clipLowResolutionTiles(): boolean { + return true; + } + public override get viewFlagOverrides(): ViewFlagOverrides { + return this._viewFlagOverrides; + } public override get maximumScreenSpaceError(): number | undefined { return this.tree.rdSource.maximumScreenSpaceError; } @@ -469,15 +552,17 @@ class RealityModelTileLoader extends RealityTileLoader { const foundChild = await this.findTileInJson(this.tree.tilesetJson, childId, "", undefined); if (undefined !== foundChild) { const refine = foundChild.json.refine; - props.push(new RealityModelTileProps({ - json: foundChild.json, - parent, - id: foundChild.id, - transformToRoot: foundChild.transformToRoot, - // If not specified explicitly, additiveRefinement is inherited from parent tile. - additiveRefinement: undefined !== refine ? refine === "ADD" : undefined, - usesGeometricError: this.tree.rdSource.usesGeometricError, - })); + props.push( + new RealityModelTileProps({ + json: foundChild.json, + parent, + id: foundChild.id, + transformToRoot: foundChild.transformToRoot, + // If not specified explicitly, additiveRefinement is inherited from parent tile. + additiveRefinement: undefined !== refine ? refine === "ADD" : undefined, + usesGeometricError: this.tree.rdSource.usesGeometricError, + }), + ); } } } @@ -499,7 +584,7 @@ class RealityModelTileLoader extends RealityTileLoader { private async findTileInJson(tilesetJson: any, id: string, parentId: string, transformToRoot?: Transform): Promise { if (id.length === 0) - return new FindChildResult(id, tilesetJson, transformToRoot); // Root. + return new FindChildResult(id, tilesetJson, transformToRoot); // Root. const separatorIndex = id.indexOf("_"); const childId = (separatorIndex < 0) ? id : id.substring(0, separatorIndex); @@ -543,7 +628,9 @@ export class RealityModelTileTree extends RealityTileTree { this.iModel.expandDisplayedExtents(worldContentRange); } } - public override get isContentUnbounded() { return this._isContentUnbounded; } + public override get isContentUnbounded() { + return this._isContentUnbounded; + } } /** @internal */ @@ -581,8 +668,12 @@ export namespace RealityModelTileTree { public abstract get modelId(): Id64String; // public get classifiers(): SpatialClassifiers | undefined { return undefined !== this._classifier ? this._classifier.classifiers : undefined; } - public get planarClipMask(): PlanarClipMaskState | undefined { return this._planarClipMask; } - public set planarClipMask(planarClipMask: PlanarClipMaskState | undefined) { this._planarClipMask = planarClipMask; } + public get planarClipMask(): PlanarClipMaskState | undefined { + return this._planarClipMask; + } + public set planarClipMask(planarClipMask: PlanarClipMaskState | undefined) { + this._planarClipMask = planarClipMask; + } public override get planarClipMaskPriority(): number { if (this._planarClipMask?.settings.priority !== undefined) @@ -618,7 +709,9 @@ export namespace RealityModelTileTree { this._classifier = createClassifierTileTreeReference(props.classifiers, this, props.iModel, props.source); } - public get planarClassifierTreeRef() { return this._classifier && this._classifier.activeClassifier && this._classifier.isPlanar ? this._classifier : undefined; } + public get planarClassifierTreeRef() { + return this._classifier && this._classifier.activeClassifier && this._classifier.isPlanar ? this._classifier : undefined; + } public override unionFitRange(union: Range3d): void { const contentRange = this.computeWorldContentRange(); @@ -740,7 +833,7 @@ export namespace RealityModelTileTree { const ecefOrigin = realityTileRange.localXYZToWorld(.5, .5, .5)!; const dbOrigin = rootTransform.multiplyPoint3d(ecefOrigin); const realityOriginToProjectDistance = iModel.projectExtents.distanceToPoint(dbOrigin); - const maxProjectDistance = 1E5; // Only use the project GCS projection if within 100KM of the project. Don't attempt to use GCS if global reality model or in another locale - Results will be unreliable. + const maxProjectDistance = 1E5; // Only use the project GCS projection if within 100KM of the project. Don't attempt to use GCS if global reality model or in another locale - Results will be unreliable. if (realityOriginToProjectDistance < maxProjectDistance && json.asset?.version !== "0.0" || undefined !== json.root?.iModelPublishVersion) { const cartographicOrigin = Cartographic.fromEcef(ecefOrigin); @@ -801,7 +894,9 @@ export class RealityTreeReference extends RealityModelTileTree.Reference { this._modelId = modelId ?? props.iModel.transientIds.getNext(); } - public override get modelId() { return this._modelId; } + public override get modelId() { + return this._modelId; + } private createTreeId(modelId: Id64String): RealityTreeId { return { @@ -882,7 +977,8 @@ export class RealityTreeReference extends RealityModelTileTree.Reference { } const tree = this.treeOwner.tileTree; - return tree instanceof RealityTileTree && hit.iModel === tree.iModel && undefined !== tree.batchTableProperties?.getFeatureProperties(hit.sourceId); + return tree instanceof RealityTileTree && hit.iModel === tree.iModel && + undefined !== tree.batchTableProperties?.getFeatureProperties(hit.sourceId); } public override async getToolTip(hit: HitDetail): Promise { @@ -932,14 +1028,17 @@ export class RealityTreeReference extends RealityModelTileTree.Reference { if (this._name) { strings.push(`${IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`); } else { - const cesiumAsset = this._rdSourceKey.provider === RealityDataProvider.CesiumIonAsset ? CesiumIonAssetProvider.parseCesiumUrl(this._rdSourceKey.id) : undefined; + const cesiumAsset = this._rdSourceKey.provider === RealityDataProvider.CesiumIonAsset + ? CesiumIonAssetProvider.parseCesiumUrl(this._rdSourceKey.id) + : undefined; strings.push(cesiumAsset ? `Cesium Asset: ${cesiumAsset.id}` : this._rdSourceKey.id); } - if (batch !== undefined) + if (batch !== undefined) { for (const key of Object.keys(batch)) - if (-1 === key.indexOf("#")) // Avoid internal cesium + if (-1 === key.indexOf("#")) // Avoid internal cesium strings.push(`${key}: ${JSON.stringify(batch[key])}`); + } const div = document.createElement("div"); div.innerHTML = strings.join("
"); @@ -949,8 +1048,14 @@ export class RealityTreeReference extends RealityModelTileTree.Reference { public override addLogoCards(cards: HTMLTableElement): void { if (this._rdSourceKey.provider === RealityDataProvider.CesiumIonAsset && !cards.dataset.openStreetMapLogoCard) { cards.dataset.openStreetMapLogoCard = "true"; - cards.appendChild(IModelApp.makeLogoCard({ heading: "OpenStreetMap", notice: `©
OpenStreetMap ${IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap:OpenStreetMapContributors")}` })); + cards.appendChild( + IModelApp.makeLogoCard({ + heading: "OpenStreetMap", + notice: `©OpenStreetMap ${ + IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap:OpenStreetMapContributors") + }`, + }), + ); } } } - diff --git a/core/frontend/src/tile/RealityTile.ts b/core/frontend/src/tile/RealityTile.ts index b46b302e81b2..218ff727972e 100644 --- a/core/frontend/src/tile/RealityTile.ts +++ b/core/frontend/src/tile/RealityTile.ts @@ -7,8 +7,8 @@ */ import { BeTimePoint, dispose } from "@itwin/core-bentley"; -import { ClipMaskXYZRangePlanes, ClipShape, ClipVector, IndexedPolyface, Point3d, Transform } from "@itwin/core-geometry"; import { ColorDef, Frustum } from "@itwin/core-common"; +import { ClipMaskXYZRangePlanes, ClipShape, ClipVector, IndexedPolyface, Point3d, Transform } from "@itwin/core-geometry"; import { IModelApp } from "../IModelApp"; import { GraphicBranch, GraphicBranchOptions } from "../render/GraphicBranch"; import { GraphicBuilder } from "../render/GraphicBuilder"; @@ -17,8 +17,21 @@ import { RenderSystem } from "../render/RenderSystem"; import { ViewingSpace } from "../ViewingSpace"; import { Viewport } from "../Viewport"; import { - RealityTileRegion, RealityTileTree, Tile, TileContent, TileDrawArgs, TileGeometryCollector, TileGraphicType, TileLoadStatus, TileParams, TileRequest, TileRequestChannel, - TileTreeLoadStatus, TileUser, TraversalDetails, TraversalSelectionContext, + RealityTileRegion, + RealityTileTree, + Tile, + TileContent, + TileDrawArgs, + TileGeometryCollector, + TileGraphicType, + TileLoadStatus, + TileParams, + TileRequest, + TileRequestChannel, + TileTreeLoadStatus, + TileUser, + TraversalDetails, + TraversalSelectionContext, } from "./internal"; /** @internal */ @@ -46,8 +59,17 @@ export interface RealityTileContent extends TileContent { } const scratchLoadedChildren = new Array(); -const scratchCorners = [Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()]; -const additiveRefinementThreshold = 10000; // Additive tiles (Cesium OSM tileset) are subdivided until their range diagonal falls below this threshold to ensure accurate reprojection. +const scratchCorners = [ + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), +]; +const additiveRefinementThreshold = 10000; // Additive tiles (Cesium OSM tileset) are subdivided until their range diagonal falls below this threshold to ensure accurate reprojection. const additiveRefinementDepthLimit = 20; const scratchFrustum = new Frustum(); @@ -113,23 +135,39 @@ export class RealityTile extends Tile { } /** @internal */ - public get realityChildren(): RealityTile[] | undefined { return this.children as RealityTile[] | undefined; } + public get realityChildren(): RealityTile[] | undefined { + return this.children as RealityTile[] | undefined; + } /** @internal */ - public get realityParent(): RealityTile { return this.parent as RealityTile; } + public get realityParent(): RealityTile { + return this.parent as RealityTile; + } /** @internal */ - public get realityRoot(): RealityTileTree { return this.tree as RealityTileTree; } + public get realityRoot(): RealityTileTree { + return this.tree as RealityTileTree; + } /** @internal */ - public get graphicType(): TileGraphicType | undefined { return undefined; } // If undefined, use tree type. + public get graphicType(): TileGraphicType | undefined { + return undefined; + } // If undefined, use tree type. /** @internal */ - public get maxDepth(): number { return this.realityRoot.loader.maxDepth; } + public get maxDepth(): number { + return this.realityRoot.loader.maxDepth; + } /** @internal */ - public get isPointCloud() { return this.realityRoot.loader.containsPointClouds; } + public get isPointCloud() { + return this.realityRoot.loader.containsPointClouds; + } /** @internal */ - public get isLoaded() { return this.loadStatus === TileLoadStatus.Ready; } // Reality tiles may depend on secondary tiles (maps) so can ge loaded but not ready. + public get isLoaded() { + return this.loadStatus === TileLoadStatus.Ready; + } // Reality tiles may depend on secondary tiles (maps) so can ge loaded but not ready. /** A representation of the tile's geometry. * This property is only available when using [[TileGeometryCollector]]. */ - public get geometry(): RealityTileGeometry | undefined { return this._geometry; } + public get geometry(): RealityTileGeometry | undefined { + return this._geometry; + } /** @internal */ public override get isDisplayable(): boolean { @@ -169,21 +207,22 @@ export class RealityTile extends Tile { // Create additive stepchildren only if we are this tile is additive and we are re-projecting and the radius exceeds the additiveRefinementThreshold. // This criteria is currently only met by the Cesium OSM tileset. const rangeDiagonal = this.rangeCorners ? this.rangeCorners[0].distance(this.rangeCorners[3]) : 0; - return this.additiveRefinement && this.isDisplayable && rangeDiagonal > additiveRefinementThreshold && this.depth < additiveRefinementDepthLimit && this.realityRoot.doReprojectChildren(this); + return this.additiveRefinement && this.isDisplayable && rangeDiagonal > additiveRefinementThreshold && + this.depth < additiveRefinementDepthLimit && this.realityRoot.doReprojectChildren(this); } /** @internal */ protected _loadChildren(resolve: (children: Tile[] | undefined) => void, reject: (error: Error) => void): void { this.realityRoot.loader.loadChildren(this).then((children: Tile[] | undefined) => { - /* If this is a large tile is to be included additively, but we are re-projecting (Cesium OSM) then we must add step-children to display the geometry as an overly large tile cannot be reprojected accurately. */ if (this.useAdditiveRefinementStepchildren()) - this.loadAdditiveRefinementChildren((stepChildren: Tile[]) => { children = children ? children?.concat(stepChildren) : stepChildren; }); + this.loadAdditiveRefinementChildren((stepChildren: Tile[]) => { + children = children ? children?.concat(stepChildren) : stepChildren; + }); if (children) - this.realityRoot.reprojectAndResolveChildren(this, children, resolve); /* Potentially reproject and resolve these children */ - + this.realityRoot.reprojectAndResolveChildren(this, children, resolve); /* Potentially reproject and resolve these children */ }).catch((err) => { reject(err); }); @@ -207,12 +246,14 @@ export class RealityTile extends Tile { /** Allow tile to select additional tiles (Terrain Imagery...) * @internal */ - public selectSecondaryTiles(_args: TileDrawArgs, _context: TraversalSelectionContext) { } + public selectSecondaryTiles(_args: TileDrawArgs, _context: TraversalSelectionContext) {} /** An upsampled tile is not loadable - will override to return loadable parent. * @internal */ - public get loadableTile(): RealityTile { return this; } + public get loadableTile(): RealityTile { + return this; + } /** @internal */ public preloadRealityTilesAtDepth(depth: number, context: TraversalSelectionContext, args: TileDrawArgs) { @@ -306,7 +347,9 @@ export class RealityTile extends Tile { return true; } /** @internal */ - protected forceSelectRealityTile(): boolean { return false; } + protected forceSelectRealityTile(): boolean { + return false; + } /** @internal */ protected minimumVisibleFactor(): number { if (this.additiveRefinement) @@ -336,7 +379,6 @@ export class RealityTile extends Tile { const shouldSelectThisTile = visibility >= 1 || this._anyChildNotFound || this.forceSelectRealityTile() || context.selectionCountExceeded; if (shouldSelectThisTile && this.isDisplayable) { // Select this tile - // Return early if tile is totally occluded if (this.isOccluded(args.viewingSpace)) return; @@ -347,9 +389,7 @@ export class RealityTile extends Tile { // This tile is visible but not loaded - Use higher resolution children if present if (!this.isReady) this.selectRealityChildrenAsFallback(context, args, traversalDetails); - } else { // Select children instead of this tile - // With additive refinement it is necessary to display this tile along with any displayed children if (this.additiveRefinement && this.isDisplayable && !this.useAdditiveRefinementStepchildren()) context.selectOrQueue(this, args, traversalDetails); @@ -384,7 +424,6 @@ export class RealityTile extends Tile { // Recurse through children to select them normally /** @internal */ protected selectRealityChildren(context: TraversalSelectionContext, args: TileDrawArgs, traversalDetails: TraversalDetails) { - // Load children if not yet requested const childrenLoadStatus = this.loadChildren(); // NB: asynchronous @@ -525,10 +564,11 @@ export class RealityTile extends Tile { /** @internal */ protected get _anyChildNotFound(): boolean { - if (undefined !== this.children) + if (undefined !== this.children) { for (const child of this.children) if (child.isNotFound) return true; + } return this._childrenLoadStatus === TileTreeLoadStatus.NotFound; } @@ -536,7 +576,7 @@ export class RealityTile extends Tile { /** @internal */ public override getSizeProjectionCorners(): Point3d[] | undefined { if (!this.tree.isContentUnbounded) - return undefined; // For a non-global tree use the standard size algorithm. + return undefined; // For a non-global tree use the standard size algorithm. // For global tiles (as in OSM buildings) return the range corners or X-Y corners only if bounded by region- this allows an algorithm that uses the area of the projected corners to attenuate horizon tiles. if (!this.rangeCorners) @@ -546,7 +586,9 @@ export class RealityTile extends Tile { } /** @internal */ - public get isStepChild() { return false; } + public get isStepChild() { + return false; + } /** @internal */ protected loadAdditiveRefinementChildren(resolve: (children: Tile[]) => void): void { @@ -567,11 +609,27 @@ export class RealityTile extends Tile { for (let i = 0, minLongitude = region.minLongitude, step = 0; i < 2; i++, minLongitude += longitudeDelta, step++) { for (let j = 0, minLatitude = region.minLatitude; j < 2; j++, minLatitude += latitudeDelta) { - const childRegion = new RealityTileRegion({ minLatitude, maxLatitude: minLatitude + latitudeDelta, minLongitude, maxLongitude: minLongitude + longitudeDelta, minHeight, maxHeight }); + const childRegion = new RealityTileRegion({ + minLatitude, + maxLatitude: minLatitude + latitudeDelta, + minLongitude, + maxLongitude: minLongitude + longitudeDelta, + minHeight, + maxHeight, + }); const childRange = childRegion.getRange(); const contentId = `${this.contentId}_S${step++}`; - const childParams: RealityTileParams = { rangeCorners: childRange.corners, contentId, range: childRange.range, maximumSize, parent: this, additiveRefinement: false, isLeaf, region: childRegion }; + const childParams: RealityTileParams = { + rangeCorners: childRange.corners, + contentId, + range: childRange.range, + maximumSize, + parent: this, + additiveRefinement: false, + isLeaf, + region: childRegion, + }; stepChildren.push(new AdditiveRefinementStepChild(childParams, this.realityRoot)); } @@ -622,8 +680,9 @@ export class RealityTile extends Tile { } break; - } // else fall through to "accept" + } // eslint-disable-next-line no-fallthrough + // else fall through to "accept" case "accept": if (!this.isReady) collector.addMissingTile(this.loadableTile); @@ -641,24 +700,37 @@ export class RealityTile extends Tile { * The stepchildren do not contain any tile graphics - they just create a branch with clipping and reprojection to display their additive refinement ancestor graphics. */ class AdditiveRefinementStepChild extends RealityTile { - public override get isStepChild() { return true; } + public override get isStepChild() { + return true; + } private _loadableTile: RealityTile; public constructor(props: RealityTileParams, tree: RealityTileTree) { super(props, tree); this._loadableTile = this.realityParent; - for (; this._loadableTile && this._loadableTile.isStepChild; this._loadableTile = this._loadableTile.realityParent) - ; + for (; this._loadableTile && this._loadableTile.isStepChild; this._loadableTile = this._loadableTile.realityParent); } public override get loadableTile(): RealityTile { return this._loadableTile; } - public override get isLoading(): boolean { return this._loadableTile.isLoading; } - public override get isQueued(): boolean { return this._loadableTile.isQueued; } - public override get isNotFound(): boolean { return this._loadableTile.isNotFound; } - public override get isReady(): boolean { return this._loadableTile.isReady; } - public override get isLoaded(): boolean { return this._loadableTile.isLoaded; } - public override get isEmpty() { return false; } + public override get isLoading(): boolean { + return this._loadableTile.isLoading; + } + public override get isQueued(): boolean { + return this._loadableTile.isQueued; + } + public override get isNotFound(): boolean { + return this._loadableTile.isNotFound; + } + public override get isReady(): boolean { + return this._loadableTile.isReady; + } + public override get isLoaded(): boolean { + return this._loadableTile.isLoaded; + } + public override get isEmpty() { + return false; + } public override produceGraphics(): RenderGraphic | undefined { if (undefined === this._graphic) { const parentGraphics = this._loadableTile.unprojectedGraphic; @@ -672,7 +744,9 @@ class AdditiveRefinementStepChild extends RealityTile { const branchOptions: GraphicBranchOptions = {}; if (this.rangeCorners) { const clipPolygon = [this.rangeCorners[0], this.rangeCorners[1], this.rangeCorners[3], this.rangeCorners[2]]; - branchOptions.clipVolume = renderSystem.createClipVolume(ClipVector.create([ClipShape.createShape(clipPolygon, undefined, undefined, this.tree.iModelTransform)!])); + branchOptions.clipVolume = renderSystem.createClipVolume( + ClipVector.create([ClipShape.createShape(clipPolygon, undefined, undefined, this.tree.iModelTransform)!]), + ); } this._graphic = renderSystem.createGraphicBranch(branch, this._reprojectionTransform, branchOptions); } diff --git a/core/frontend/src/tile/RealityTileDrawArgs.ts b/core/frontend/src/tile/RealityTileDrawArgs.ts index c6dd79c7ac21..0b5df9052d81 100644 --- a/core/frontend/src/tile/RealityTileDrawArgs.ts +++ b/core/frontend/src/tile/RealityTileDrawArgs.ts @@ -6,18 +6,28 @@ * @module Tiles */ -import { Map4d } from "@itwin/core-geometry"; import { FrustumPlanes } from "@itwin/core-common"; -import { TileDrawArgs } from "./internal"; +import { Map4d } from "@itwin/core-geometry"; import { RenderPlanarClassifier } from "../render/RenderPlanarClassifier"; +import { TileDrawArgs } from "./internal"; /** @internal */ export class RealityTileDrawArgs extends TileDrawArgs { private readonly _worldToViewMap: Map4d; - public override get worldToViewMap(): Map4d { return this._worldToViewMap; } - public override get secondaryClassifiers() { return this._secondaryClassifiers;} + public override get worldToViewMap(): Map4d { + return this._worldToViewMap; + } + public override get secondaryClassifiers() { + return this._secondaryClassifiers; + } - public constructor(args: TileDrawArgs, worldToViewMap: Map4d, frustumPlanes: FrustumPlanes, public maxSelectionCount?: number, private _secondaryClassifiers?: Map) { + public constructor( + args: TileDrawArgs, + worldToViewMap: Map4d, + frustumPlanes: FrustumPlanes, + public maxSelectionCount?: number, + private _secondaryClassifiers?: Map, + ) { super({ ...args, viewFlagOverrides: args.viewFlagOverrides, symbologyOverrides: args.symbologyOverrides, parentsAndChildrenExclusive: false }); this._worldToViewMap = worldToViewMap; diff --git a/core/frontend/src/tile/RealityTileLoader.ts b/core/frontend/src/tile/RealityTileLoader.ts index 8335e236d798..3df6a01ade3f 100644 --- a/core/frontend/src/tile/RealityTileLoader.ts +++ b/core/frontend/src/tile/RealityTileLoader.ts @@ -7,16 +7,32 @@ */ import { assert, ByteStream } from "@itwin/core-bentley"; -import { Point2d, Point3d, Transform } from "@itwin/core-geometry"; import { BatchType, CompositeTileHeader, TileFormat, ViewFlagOverrides } from "@itwin/core-common"; +import { Point2d, Point3d, Transform } from "@itwin/core-geometry"; +import { GltfWrapMode } from "../common/gltf/GltfSchema"; import { IModelApp } from "../IModelApp"; import { GraphicBranch } from "../render/GraphicBranch"; import { RenderSystem } from "../render/RenderSystem"; import { ScreenViewport, Viewport } from "../Viewport"; -import { GltfWrapMode } from "../common/gltf/GltfSchema"; import { - B3dmReader, BatchedTileIdMap, createDefaultViewFlagOverrides, GltfGraphicsReader, GltfReader, GltfReaderProps, I3dmReader, ImdlReader, readPointCloudTileContent, - RealityTile, RealityTileContent, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileRequest, TileRequestChannel, TileUser, + B3dmReader, + BatchedTileIdMap, + createDefaultViewFlagOverrides, + GltfGraphicsReader, + GltfReader, + GltfReaderProps, + I3dmReader, + ImdlReader, + readPointCloudTileContent, + RealityTile, + RealityTileContent, + Tile, + TileContent, + TileDrawArgs, + TileLoadPriority, + TileRequest, + TileRequestChannel, + TileUser, } from "./internal"; const defaultViewFlagOverrides = createDefaultViewFlagOverrides({}); @@ -45,28 +61,55 @@ export abstract class RealityTileLoader { public abstract loadChildren(tile: RealityTile): Promise; public abstract getRequestChannel(tile: Tile): TileRequestChannel; public abstract requestTileContent(tile: Tile, isCanceled: () => boolean): Promise; - public get wantDeduplicatedVertices(): boolean { return false; } + public get wantDeduplicatedVertices(): boolean { + return false; + } public abstract get maxDepth(): number; public abstract get minDepth(): number; public abstract get priority(): TileLoadPriority; - protected get _batchType(): BatchType { return BatchType.Primary; } - protected get _loadEdges(): boolean { return true; } - public getBatchIdMap(): BatchedTileIdMap | undefined { return undefined; } - public get isContentUnbounded(): boolean { return false; } - public get containsPointClouds(): boolean { return this._containsPointClouds; } - public get parentsAndChildrenExclusive(): boolean { return true; } - public forceTileLoad(_tile: Tile): boolean { return false; } - public get maximumScreenSpaceError(): number | undefined { return undefined; } + protected get _batchType(): BatchType { + return BatchType.Primary; + } + protected get _loadEdges(): boolean { + return true; + } + public getBatchIdMap(): BatchedTileIdMap | undefined { + return undefined; + } + public get isContentUnbounded(): boolean { + return false; + } + public get containsPointClouds(): boolean { + return this._containsPointClouds; + } + public get parentsAndChildrenExclusive(): boolean { + return true; + } + public forceTileLoad(_tile: Tile): boolean { + return false; + } + public get maximumScreenSpaceError(): number | undefined { + return undefined; + } - public processSelectedTiles(selected: Tile[], _args: TileDrawArgs): Tile[] { return selected; } + public processSelectedTiles(selected: Tile[], _args: TileDrawArgs): Tile[] { + return selected; + } // NB: The isCanceled arg is chiefly for tests...in usual case it just returns false if the tile is no longer in 'loading' state. - public async loadTileContent(tile: Tile, data: TileRequest.ResponseData, system: RenderSystem, isCanceled?: () => boolean): Promise { + public async loadTileContent( + tile: Tile, + data: TileRequest.ResponseData, + system: RenderSystem, + isCanceled?: () => boolean, + ): Promise { assert(data instanceof Uint8Array); const blob = data; const streamBuffer = ByteStream.fromUint8Array(blob); const realityTile = tile as RealityTile; - return this._produceGeometry ? this.loadGeometryFromStream(realityTile, streamBuffer, system) : this.loadGraphicsFromStream(realityTile, streamBuffer, system, isCanceled); + return this._produceGeometry + ? this.loadGeometryFromStream(realityTile, streamBuffer, system) + : this.loadGraphicsFromStream(realityTile, streamBuffer, system, isCanceled); } private _getFormat(streamBuffer: ByteStream) { @@ -74,7 +117,6 @@ export abstract class RealityTileLoader { const format = streamBuffer.readUint32(); streamBuffer.curPos = position; return format; - } public async loadGeometryFromStream(tile: RealityTile, streamBuffer: ByteStream, system: RenderSystem): Promise { @@ -83,14 +125,32 @@ export abstract class RealityTileLoader { return {}; const { is3d, yAxisUp, iModel, modelId } = tile.realityRoot; - const reader = B3dmReader.create(streamBuffer, iModel, modelId, is3d, tile.contentRange, system, yAxisUp, tile.isLeaf, tile.center, tile.transformToRoot, undefined, this.getBatchIdMap()); + const reader = B3dmReader.create( + streamBuffer, + iModel, + modelId, + is3d, + tile.contentRange, + system, + yAxisUp, + tile.isLeaf, + tile.center, + tile.transformToRoot, + undefined, + this.getBatchIdMap(), + ); if (reader) reader.defaultWrapMode = GltfWrapMode.ClampToEdge; return { geometry: reader?.readGltfAndCreateGeometry(tile.tree.iModelTransform) }; } - private async loadGraphicsFromStream(tile: RealityTile, streamBuffer: ByteStream, system: RenderSystem, isCanceled?: () => boolean): Promise { + private async loadGraphicsFromStream( + tile: RealityTile, + streamBuffer: ByteStream, + system: RenderSystem, + isCanceled?: () => boolean, + ): Promise { const format = this._getFormat(streamBuffer); if (undefined === isCanceled) isCanceled = () => !tile.isLoading; @@ -130,7 +190,21 @@ export abstract class RealityTileLoader { return { graphic }; case TileFormat.B3dm: - reader = B3dmReader.create(streamBuffer, iModel, modelId, is3d, tile.contentRange, system, yAxisUp, tile.isLeaf, tile.center, tile.transformToRoot, isCanceled, this.getBatchIdMap(), this.wantDeduplicatedVertices); + reader = B3dmReader.create( + streamBuffer, + iModel, + modelId, + is3d, + tile.contentRange, + system, + yAxisUp, + tile.isLeaf, + tile.center, + tile.transformToRoot, + isCanceled, + this.getBatchIdMap(), + this.wantDeduplicatedVertices, + ); if (reader) { // glTF spec defaults wrap mode to "repeat" but many reality tiles omit the wrap mode and should not repeat. // The render system also currently only produces mip-maps for repeating textures, and we don't want mip-maps for reality tile textures. @@ -140,7 +214,19 @@ export abstract class RealityTileLoader { break; case TileFormat.I3dm: - reader = I3dmReader.create(streamBuffer, iModel, modelId, is3d, tile.contentRange, system, yAxisUp, tile.isLeaf, isCanceled, undefined, this.wantDeduplicatedVertices); + reader = I3dmReader.create( + streamBuffer, + iModel, + modelId, + is3d, + tile.contentRange, + system, + yAxisUp, + tile.isLeaf, + isCanceled, + undefined, + this.wantDeduplicatedVertices, + ); break; case TileFormat.Gltf: const props = GltfReaderProps.create(streamBuffer.nextBytes(streamBuffer.arrayBuffer.byteLength), yAxisUp); @@ -165,7 +251,7 @@ export abstract class RealityTileLoader { const branch = new GraphicBranch(true); for (let i = 0; i < header.tileCount; i++) { const tilePosition = streamBuffer.curPos; - streamBuffer.advance(8); // Skip magic and version. + streamBuffer.advance(8); // Skip magic and version. const tileBytes = streamBuffer.readUint32(); streamBuffer.curPos = tilePosition; const result = await this.loadGraphicsFromStream(tile, streamBuffer, system, isCanceled); @@ -195,7 +281,9 @@ export abstract class RealityTileLoader { return content; } - public get viewFlagOverrides(): ViewFlagOverrides { return defaultViewFlagOverrides; } + public get viewFlagOverrides(): ViewFlagOverrides { + return defaultViewFlagOverrides; + } public static computeTileLocationPriority(tile: Tile, viewports: Iterable, location: Transform): number { // Compute a priority value for tiles that are: diff --git a/core/frontend/src/tile/RealityTileTree.ts b/core/frontend/src/tile/RealityTileTree.ts index 177f223d61bc..3d4ceed65c62 100644 --- a/core/frontend/src/tile/RealityTileTree.ts +++ b/core/frontend/src/tile/RealityTileTree.ts @@ -7,10 +7,8 @@ */ import { assert, BeTimePoint, Id64String, ProcessDetector } from "@itwin/core-bentley"; -import { - Matrix3d, Point3d, Range3d, Transform, Vector3d, XYZProps, -} from "@itwin/core-geometry"; import { Cartographic, ColorDef, GeoCoordStatus, ViewFlagOverrides } from "@itwin/core-common"; +import { Matrix3d, Point3d, Range3d, Transform, Vector3d, XYZProps } from "@itwin/core-geometry"; import { BackgroundMapGeometry } from "../BackgroundMapGeometry"; import { GeoConverter } from "../GeoServices"; import { IModelApp } from "../IModelApp"; @@ -18,8 +16,18 @@ import { GraphicBranch } from "../render/GraphicBranch"; import { GraphicBuilder } from "../render/GraphicBuilder"; import { SceneContext } from "../ViewContext"; import { - GraphicsCollectorDrawArgs, MapTile, RealityTile, RealityTileLoader, RealityTileParams, Tile, TileDrawArgs, TileGeometryCollector, - TileGraphicType, TileParams, TileTree, TileTreeParams, + GraphicsCollectorDrawArgs, + MapTile, + RealityTile, + RealityTileLoader, + RealityTileParams, + Tile, + TileDrawArgs, + TileGeometryCollector, + TileGraphicType, + TileParams, + TileTree, + TileTreeParams, } from "./internal"; /** @internal */ @@ -70,8 +78,15 @@ export class TraversalChildrenDetails { export class TraversalSelectionContext { public preloaded = new Set(); public missing = new Array(); - public get selectionCountExceeded() { return this._maxSelectionCount === undefined ? false : (this.missing.length + this.selected.length) > this._maxSelectionCount; } // Avoid selecting excessive number of tiles. - constructor(public selected: Tile[], public displayedDescendants: Tile[][], public preloadDebugBuilder?: GraphicBuilder, private _maxSelectionCount?: number) { } + public get selectionCountExceeded() { + return this._maxSelectionCount === undefined ? false : (this.missing.length + this.selected.length) > this._maxSelectionCount; + } // Avoid selecting excessive number of tiles. + constructor( + public selected: Tile[], + public displayedDescendants: Tile[][], + public preloadDebugBuilder?: GraphicBuilder, + private _maxSelectionCount?: number, + ) {} public selectOrQueue(tile: RealityTile, args: TileDrawArgs, traversalDetails: TraversalDetails) { tile.selectSecondaryTiles(args, this); @@ -124,7 +139,7 @@ const scratchMatrix = Matrix3d.createZero(), scratchTransform = Transform.create interface ChildReprojection { child: RealityTile; ecefCenter: Point3d; - dbPoints: Point3d[]; // Center, xEnd, yEnd, zEnd + dbPoints: Point3d[]; // Center, xEnd, yEnd, zEnd } /** Provides access to per-feature properties within a [[RealityTileTree]]. @@ -197,7 +212,7 @@ export class RealityTileTree extends TileTree { this.yAxisUp = true === params.yAxisUp; this._rootTile = this.createTile(params.rootTile); this.cartesianRange = BackgroundMapGeometry.getCartesianRange(this.iModel); - this.cartesianTransitionDistance = this.cartesianRange.diagonal().magnitudeXY() * .25; // Transition distance from elliptical to cartesian. + this.cartesianTransitionDistance = this.cartesianRange.diagonal().magnitudeXY() * .25; // Transition distance from elliptical to cartesian. this._gcsConverter = params.gcsConverterAvailable ? params.iModel.geoServices.getConverter("WGS84") : undefined; if (params.rootToEcef) { this._rootToEcef = params.rootToEcef; @@ -217,27 +232,47 @@ export class RealityTileTree extends TileTree { } /** @internal */ - public get rootTile(): RealityTile { return this._rootTile; } + public get rootTile(): RealityTile { + return this._rootTile; + } /** @internal */ - public get is3d() { return true; } + public get is3d() { + return true; + } /** @internal */ - public get maxDepth() { return this.loader.maxDepth; } + public get maxDepth() { + return this.loader.maxDepth; + } /** @internal */ - public get minDepth() { return this.loader.minDepth; } + public get minDepth() { + return this.loader.minDepth; + } /** @internal */ - public override get isContentUnbounded() { return this.loader.isContentUnbounded; } + public override get isContentUnbounded() { + return this.loader.isContentUnbounded; + } /** @internal */ - public get isTransparent() { return false; } + public get isTransparent() { + return false; + } /** @internal */ - protected _selectTiles(args: TileDrawArgs): Tile[] { return this.selectRealityTiles(args, []); } + protected _selectTiles(args: TileDrawArgs): Tile[] { + return this.selectRealityTiles(args, []); + } /** @internal */ - public get viewFlagOverrides(): ViewFlagOverrides { return this.loader.viewFlagOverrides; } + public get viewFlagOverrides(): ViewFlagOverrides { + return this.loader.viewFlagOverrides; + } /** @internal */ - public override get parentsAndChildrenExclusive() { return this.loader.parentsAndChildrenExclusive; } + public override get parentsAndChildrenExclusive() { + return this.loader.parentsAndChildrenExclusive; + } /** @internal */ - public createTile(props: TileParams): RealityTile { return new RealityTile(props, this); } + public createTile(props: TileParams): RealityTile { + return new RealityTile(props, this); + } /** Collect tiles from this tile tree based on the criteria implemented by `collector`. * @internal @@ -309,11 +344,12 @@ export class RealityTileTree extends TileTree { targetBranch.add(graphics); } else { clipVector.transformInPlace(args.location); - if (!this.isTransparent) + if (!this.isTransparent) { for (const primitive of clipVector.clips) for (const clipPlanes of primitive.fetchClipPlanesRef()!.convexSets) for (const plane of clipPlanes.planes) - plane.offsetDistance(-displayedDescendant.radius * .05); // Overlap with existing (high resolution) tile slightly to avoid cracks. + plane.offsetDistance(-displayedDescendant.radius * .05); // Overlap with existing (high resolution) tile slightly to avoid cracks. + } const branch = new GraphicBranch(false); branch.add(graphics); @@ -344,7 +380,12 @@ export class RealityTileTree extends TileTree { protected collectClassifierGraphics(args: TileDrawArgs, selectedTiles: RealityTile[]) { const classifier = args.context.planarClassifiers.get(this.modelId); if (classifier) - classifier.collectGraphics(args.context, { modelId: this.modelId, tiles: selectedTiles, location: args.location, isPointCloud: this.isPointCloud }); + classifier.collectGraphics(args.context, { + modelId: this.modelId, + tiles: selectedTiles, + location: args.location, + isPointCloud: this.isPointCloud, + }); } /** @internal */ @@ -372,7 +413,7 @@ export class RealityTileTree extends TileTree { return; } - const ecefToDb = this._ecefToDb!; // Tested for undefined in doReprojectChildren + const ecefToDb = this._ecefToDb!; // Tested for undefined in doReprojectChildren const rootToDb = this.iModelTransform; const dbToEcef = ecefToDb.inverse()!; const reprojectChildren = new Array(); @@ -395,7 +436,6 @@ export class RealityTileTree extends TileTree { const carto = Cartographic.fromEcef(ecefPoint, scratchCarto); if (carto) requestProps.push({ x: carto.longitudeDegrees, y: carto.latitudeDegrees, z: carto.height }); - } } @@ -403,7 +443,6 @@ export class RealityTileTree extends TileTree { resolve(children); else { this._gcsConverter!.getIModelCoordinatesFromGeoCoordinates(requestProps).then((response) => { - const reprojectedCoords = response.iModelCoords; const dbToRoot = rootToDb.inverse()!; const getReprojectedPoint = (original: Point3d, reprojectedXYZ: XYZProps) => { @@ -419,9 +458,21 @@ export class RealityTileTree extends TileTree { for (const reprojection of reprojectChildren) { if (reprojectedCoords.every((coord) => coord.s === GeoCoordStatus.Success)) { const reprojectedOrigin = getReprojectedPoint(reprojection.dbPoints[0], reprojectedCoords[responseIndex++].p).clone(scratchOrigin); - const xVector = Vector3d.createStartEnd(reprojectedOrigin, getReprojectedPoint(reprojection.dbPoints[1], reprojectedCoords[responseIndex++].p), scratchX); - const yVector = Vector3d.createStartEnd(reprojectedOrigin, getReprojectedPoint(reprojection.dbPoints[2], reprojectedCoords[responseIndex++].p), scratchY); - const zVector = Vector3d.createStartEnd(reprojectedOrigin, getReprojectedPoint(reprojection.dbPoints[3], reprojectedCoords[responseIndex++].p), scratchZ); + const xVector = Vector3d.createStartEnd( + reprojectedOrigin, + getReprojectedPoint(reprojection.dbPoints[1], reprojectedCoords[responseIndex++].p), + scratchX, + ); + const yVector = Vector3d.createStartEnd( + reprojectedOrigin, + getReprojectedPoint(reprojection.dbPoints[2], reprojectedCoords[responseIndex++].p), + scratchY, + ); + const zVector = Vector3d.createStartEnd( + reprojectedOrigin, + getReprojectedPoint(reprojection.dbPoints[3], reprojectedCoords[responseIndex++].p), + scratchZ, + ); const matrix = Matrix3d.createColumns(xVector, yVector, zVector, scratchMatrix); if (matrix !== undefined) { const dbReprojection = Transform.createMatrixPickupPutdown(matrix, reprojection.dbPoints[0], reprojectedOrigin, scratchTransform); @@ -435,20 +486,22 @@ export class RealityTileTree extends TileTree { resolve(children); }).catch(() => { - resolve(children); // Error occured in reprojection - just resolve with unprojected corners. + resolve(children); // Error occured in reprojection - just resolve with unprojected corners. }); } } } /** @internal */ - public getBaseRealityDepth(_sceneContext: SceneContext) { return -1; } + public getBaseRealityDepth(_sceneContext: SceneContext) { + return -1; + } /** Scan the list of currently selected reality tiles, and fire the viewport's 'onMapLayerScaleRangeVisibilityChanged ' event * if any scale range visibility change is detected for one more map-layer definition. * @internal */ - public reportTileVisibility(_args: TileDrawArgs, _selected: RealityTile[]) { } + public reportTileVisibility(_args: TileDrawArgs, _selected: RealityTile[]) {} /** @internal */ public selectRealityTiles(args: TileDrawArgs, displayedDescendants: RealityTile[][], preloadDebugBuilder?: GraphicBuilder): RealityTile[] { @@ -464,20 +517,21 @@ export class RealityTileTree extends TileTree { const baseDepth = this.getBaseRealityDepth(args.context); if (IModelApp.tileAdmin.isPreloadingAllowed && 0 === context.missing.length) { - if (baseDepth > 0) // Maps may force loading of low level globe tiles. + if (baseDepth > 0) // Maps may force loading of low level globe tiles. rootTile.preloadRealityTilesAtDepth(baseDepth, context, args); if (!freezeTiles) rootTile.preloadProtectedTiles(args, context); } - if (!freezeTiles) + if (!freezeTiles) { for (const tile of context.missing) { const loadableTile = tile.loadableTile; loadableTile.markUsed(args); args.insertMissing(loadableTile); } + } if (debugControl && debugControl.logRealityTiles) { this.logTiles("Selected: ", selected.values()); @@ -491,7 +545,7 @@ export class RealityTileTree extends TileTree { const imageryTiles: RealityTile[] = []; for (const selectedTile of selected) { if (selectedTile instanceof MapTile) { - const selectedImageryTiles = (selectedTile).imageryTiles; + const selectedImageryTiles = selectedTile.imageryTiles; if (selectedImageryTiles) selectedImageryTiles.forEach((tile) => imageryTiles.push(tile)); } diff --git a/core/frontend/src/tile/RenderGraphicTileTree.ts b/core/frontend/src/tile/RenderGraphicTileTree.ts index 5a3dc007a5a4..37dc29593ff5 100644 --- a/core/frontend/src/tile/RenderGraphicTileTree.ts +++ b/core/frontend/src/tile/RenderGraphicTileTree.ts @@ -8,12 +8,12 @@ import { compareStrings, Guid, GuidString, Id64String } from "@itwin/core-bentley"; import { ViewFlagOverrides } from "@itwin/core-common"; -import { Tile, TileDrawArgs, TileLoadPriority, TileTree, TileTreeOwner, TileTreeReference, TileTreeSupplier } from "./internal"; -import { RenderGraphic } from "../render/RenderGraphic"; -import { IModelConnection } from "../IModelConnection"; import { Range3d, Transform } from "@itwin/core-geometry"; -import { IModelApp } from "../IModelApp"; import { HitDetail } from "../HitDetail"; +import { IModelApp } from "../IModelApp"; +import { IModelConnection } from "../IModelConnection"; +import { RenderGraphic } from "../render/RenderGraphic"; +import { Tile, TileDrawArgs, TileLoadPriority, TileTree, TileTreeOwner, TileTreeReference, TileTreeSupplier } from "./internal"; /** Arguments supplied to [[TileTreeReference.createFromRenderGraphic]]. * @beta @@ -89,22 +89,30 @@ class GraphicTree extends TileTree { }); this._rootTile = new GraphicTile(this, args.graphic); - this._viewFlagOverrides = args.viewFlags ?? { }; + this._viewFlagOverrides = args.viewFlags ?? {}; } - public override get rootTile() { return this._rootTile; } + public override get rootTile() { + return this._rootTile; + } // ###TODO rm TileTree.is3d - only iModel tiles care about it. - public override get is3d() { return true; } - public override get maxDepth() { return undefined; } - public override get viewFlagOverrides() { return this._viewFlagOverrides; } + public override get is3d() { + return true; + } + public override get maxDepth() { + return undefined; + } + public override get viewFlagOverrides() { + return this._viewFlagOverrides; + } protected override _selectTiles(args: TileDrawArgs) { args.markUsed(this.rootTile); return [this.rootTile]; } - public override prune() { } + public override prune() {} public override draw(args: TileDrawArgs) { const tiles = this.selectTiles(args); @@ -141,8 +149,12 @@ class GraphicRef extends TileTreeReference { this._planarClipMaskPriority = args.planarClipMaskPriority; } - public override get treeOwner() { return this._owner; } - public override get planarClipMaskPriority(): number { return this._planarClipMaskPriority ?? super.planarClipMaskPriority; } + public override get treeOwner() { + return this._owner; + } + public override get planarClipMaskPriority(): number { + return this._planarClipMaskPriority ?? super.planarClipMaskPriority; + } public override canSupplyToolTip(hit: HitDetail): boolean { return undefined !== this._getToolTip && this._modelId === hit.modelId; diff --git a/core/frontend/src/tile/ThreeDTileFormatInterpreter.ts b/core/frontend/src/tile/ThreeDTileFormatInterpreter.ts index 5ae96b4e3c0b..96b9966f7386 100644 --- a/core/frontend/src/tile/ThreeDTileFormatInterpreter.ts +++ b/core/frontend/src/tile/ThreeDTileFormatInterpreter.ts @@ -22,7 +22,7 @@ export interface ThreeDTileFileInfo { * This class provide methods used to interpret Cesium 3dTile format * @internal */ -export class ThreeDTileFormatInterpreter { +export class ThreeDTileFormatInterpreter { /** Gets reality data spatial location and extents * @param json root document file in json format * @returns spatial location and volume of interest, in meters, centered around `spatial location` @@ -38,7 +38,7 @@ export class ThreeDTileFormatInterpreter { Logger.logWarning(loggerCategory, `Error getSpatialLocationAndExtents - no root in json`); // return first 1024 char from the json const getMetaData: LoggingMetaData = () => { - return {json: JSON.stringify(json).substring(0,1024)}; + return { json: JSON.stringify(json).substring(0, 1024) }; }; const error = new RealityDataError(RealityDataStatus.InvalidData, "Invalid or unknown data - no root in json", getMetaData); throw error; @@ -55,7 +55,11 @@ export class ThreeDTileFormatInterpreter { const ecefLow = (Cartographic.fromRadians({ longitude: region[0], latitude: region[1], height: region[4] })).toEcef(); const ecefHigh = (Cartographic.fromRadians({ longitude: region[2], latitude: region[3], height: region[5] })).toEcef(); const ecefRange = Range3d.create(ecefLow, ecefHigh); - const cartoCenter = Cartographic.fromRadians({ longitude: (region[0] + region[2]) / 2.0, latitude: (region[1] + region[3]) / 2.0, height: (region[4] + region[5]) / 2.0 }); + const cartoCenter = Cartographic.fromRadians({ + longitude: (region[0] + region[2]) / 2.0, + latitude: (region[1] + region[3]) / 2.0, + height: (region[4] + region[5]) / 2.0, + }); location = cartoCenter; const ecefLocation = EcefLocation.createFromCartographicOrigin(cartoCenter); // iModelDb.setEcefLocation(ecefLocation); @@ -78,7 +82,7 @@ export class ThreeDTileFormatInterpreter { if (worldToEcefTransform.matrix.isIdentity && (earthCenterToRangeCenterRayLenght < 1.0E5 || isNotNearEarthSurface)) { isGeolocated = false; worldRange.extendRange(Range3d.fromJSON(ecefRange)); - const centerOfEarth = new EcefLocation({ origin: { x: 0.0, y: 0.0, z: 0.0 }, orientation: { yaw: 0.0, pitch: 0.0, roll: 0.0 } }); + const centerOfEarth = new EcefLocation({ origin: { x: 0.0, y: 0.0, z: 0.0 }, orientation: { yaw: 0.0, pitch: 0.0, roll: 0.0 } }); location = centerOfEarth; Logger.logTrace(loggerCategory, "RealityData NOT Geolocated", () => ({ ...location })); } else { @@ -94,7 +98,11 @@ export class ThreeDTileFormatInterpreter { } location = ecefLocation; - Logger.logTrace(loggerCategory, "RealityData is worldToEcefTransform.matrix.isIdentity", () => ({ isIdentity: worldToEcefTransform!.matrix.isIdentity })); + Logger.logTrace( + loggerCategory, + "RealityData is worldToEcefTransform.matrix.isIdentity", + () => ({ isIdentity: worldToEcefTransform!.matrix.isIdentity }), + ); // iModelDb.setEcefLocation(ecefLocation); const ecefToWorld = ecefLocation.getTransform().inverse()!; worldRange.extendRange(Range3d.fromJSON(ecefToWorld.multiplyRange(ecefRange))); @@ -105,7 +113,7 @@ export class ThreeDTileFormatInterpreter { Logger.logWarning(loggerCategory, `Error getSpatialLocationAndExtents - cannot interpret json`); // return first 1024 char from the json const getMetaData: LoggingMetaData = () => { - return {json: JSON.stringify(json).substring(0,1024)}; + return { json: JSON.stringify(json).substring(0, 1024) }; }; const error = new RealityDataError(RealityDataStatus.InvalidData, "Invalid or unknown data", getMetaData); throw error; @@ -121,12 +129,12 @@ export class ThreeDTileFormatInterpreter { * @alpha */ public static getPublisherProductInfo(rootDocjson: any): PublisherProductInfo { - const info: PublisherProductInfo = {product: "", engine: "", version: ""}; + const info: PublisherProductInfo = { product: "", engine: "", version: "" }; if (rootDocjson && rootDocjson.root) { if (rootDocjson.root.SMPublisherInfo) { info.product = rootDocjson.root.SMPublisherInfo.Product ? rootDocjson.root.SMPublisherInfo.Product : ""; - info.engine = rootDocjson.root.SMPublisherInfo.Publisher ? rootDocjson.root.SMPublisherInfo.Publisher : ""; - info.version = rootDocjson.root.SMPublisherInfo["Publisher Version"] ? rootDocjson.root.SMPublisherInfo["Publisher Version"] : "" ; + info.engine = rootDocjson.root.SMPublisherInfo.Publisher ? rootDocjson.root.SMPublisherInfo.Publisher : ""; + info.version = rootDocjson.root.SMPublisherInfo["Publisher Version"] ? rootDocjson.root.SMPublisherInfo["Publisher Version"] : ""; } } return info; @@ -161,7 +169,7 @@ export class ThreeDTileFormatInterpreter { for (let j = 0; j < 2; j++) { for (let k = 0; k < 2; k++) { for (let l = 0; l < 2; l++) { - corners.push(center.plus3Scaled(ux, (j ? -1.0 : 1.0), uy, (k ? -1.0 : 1.0), uz, (l ? -1.0 : 1.0))); + corners.push(center.plus3Scaled(ux, j ? -1.0 : 1.0, uy, k ? -1.0 : 1.0, uz, l ? -1.0 : 1.0)); } } } @@ -178,13 +186,18 @@ export class ThreeDTileFormatInterpreter { * @internal */ public static maximumSizeFromGeometricTolerance(range: Range3d, geometricError: number): number { - const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. + const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. return minToleranceRatio * range.diagonal().magnitude() / geometricError; } /** Convert a boundingVolume into a range * @internal */ public static transformFromJson(jTrans: number[] | undefined): Transform | undefined { - return (jTrans === undefined) ? undefined : Transform.createOriginAndMatrix(Point3d.create(jTrans[12], jTrans[13], jTrans[14]), Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10])); + return (jTrans === undefined) + ? undefined + : Transform.createOriginAndMatrix( + Point3d.create(jTrans[12], jTrans[13], jTrans[14]), + Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10]), + ); } } diff --git a/core/frontend/src/tile/Tile.ts b/core/frontend/src/tile/Tile.ts index 0b5e0401b627..6299a375e434 100644 --- a/core/frontend/src/tile/Tile.ts +++ b/core/frontend/src/tile/Tile.ts @@ -7,8 +7,8 @@ */ import { assert, dispose } from "@itwin/core-bentley"; -import { Arc3d, ClipPlaneContainment, Matrix4d, Point2d, Point3d, Point4d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { BoundingSphere, ColorDef, ElementAlignedBox3d, Frustum, FrustumPlanes } from "@itwin/core-common"; +import { Arc3d, ClipPlaneContainment, Matrix4d, Point2d, Point3d, Point4d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { GraphicBuilder } from "../render/GraphicBuilder"; @@ -18,7 +18,17 @@ import { RenderSystem } from "../render/RenderSystem"; import { SceneContext } from "../ViewContext"; import { Viewport } from "../Viewport"; import { - LRUTileListNode, TileContent, TileDrawArgs, TileParams, TileRequest, TileRequestChannel, TileTree, TileTreeLoadStatus, TileUsageMarker, TileUser, TileUserIdSet, + LRUTileListNode, + TileContent, + TileDrawArgs, + TileParams, + TileRequest, + TileRequestChannel, + TileTree, + TileTreeLoadStatus, + TileUsageMarker, + TileUser, + TileUserIdSet, } from "./internal"; // cSpell:ignore undisplayable bitfield @@ -94,9 +104,13 @@ export abstract class Tile { /** The bounding sphere for this tile. */ public readonly boundingSphere: BoundingSphere; /** The point at the center of this tile's volume. */ - public get center(): Point3d { return this.boundingSphere.center; } + public get center(): Point3d { + return this.boundingSphere.center; + } /** The radius of a sphere fully encompassing this tile's volume - used for culling. */ - public get radius(): number { return this.boundingSphere.radius; } + public get radius(): number { + return this.boundingSphere.radius; + } /** Tracks the usage of this tile. After a period of disuse, the tile may be [[prune]]d to free up memory. */ public readonly usageMarker = new TileUsageMarker(); @@ -175,26 +189,42 @@ export abstract class Tile { /** This tile's child tiles, if they exist and are loaded. The children are fully contained within this tile's volume and provide higher-resolution graphics than this tile. * @see [[loadChildren]] */ - public get children(): Tile[] | undefined { return this._children; } + public get children(): Tile[] | undefined { + return this._children; + } /** The [[IModelConnection]] to which this tile belongs. */ - public get iModel(): IModelConnection { return this.tree.iModel; } + public get iModel(): IModelConnection { + return this.tree.iModel; + } /** Uniquely identifies this tile's content. */ - public get contentId(): string { return this._contentId; } + public get contentId(): string { + return this._contentId; + } /** True if this tile's content is currently being loaded. */ - public get isLoading(): boolean { return TileLoadStatus.Loading === this.loadStatus; } + public get isLoading(): boolean { + return TileLoadStatus.Loading === this.loadStatus; + } /** True if a request for this tile's content has been enqueued. */ - public get isQueued(): boolean { return TileLoadStatus.Queued === this.loadStatus; } + public get isQueued(): boolean { + return TileLoadStatus.Queued === this.loadStatus; + } /** True if an attempt to load this tile's content failed. */ - public get isNotFound(): boolean { return TileLoadStatus.NotFound === this.loadStatus; } + public get isNotFound(): boolean { + return TileLoadStatus.NotFound === this.loadStatus; + } /** True if this tile's content has been loaded and is ready to be drawn. */ - public get isReady(): boolean { return TileLoadStatus.Ready === this.loadStatus; } + public get isReady(): boolean { + return TileLoadStatus.Ready === this.loadStatus; + } /** Indicates the tile should not be selected for display because it is out of the range of LODs supported by the tile provider. * @see [[ImageryMapTile.isOutOfLodRange]]. * @alpha */ - public get isOutOfLodRange(): boolean { return false;} + public get isOutOfLodRange(): boolean { + return false; + } /** @public */ public setNotFound(): void { @@ -219,20 +249,34 @@ export abstract class Tile { } /** True if this tile has no child tiles. */ - public get isLeaf(): boolean { return this._isLeaf; } + public get isLeaf(): boolean { + return this._isLeaf; + } /** @internal */ - public get isEmpty(): boolean { return this.isReady && !this.hasGraphics && this.isLeaf; } + public get isEmpty(): boolean { + return this.isReady && !this.hasGraphics && this.isLeaf; + } /** @internal */ - public get isDisplayable(): boolean { return 0 < this.maximumSize; } + public get isDisplayable(): boolean { + return 0 < this.maximumSize; + } /** The maximum size in pixels this tile can be drawn. If the size of the tile on screen exceeds this maximum, a higher-resolution tile should be drawn in its place. */ - public get maximumSize(): number { return this._maximumSize; } + public get maximumSize(): number { + return this._maximumSize; + } /** @internal */ - public get isParentDisplayable(): boolean { return undefined !== this.parent && this.parent.isDisplayable; } + public get isParentDisplayable(): boolean { + return undefined !== this.parent && this.parent.isDisplayable; + } /** @internal */ - public get isUndisplayableRootTile(): boolean { return undefined === this.parent && !this.isDisplayable; } + public get isUndisplayableRootTile(): boolean { + return undefined === this.parent && !this.isDisplayable; + } /** @internal */ - public get request(): TileRequest | undefined { return this._request; } + public get request(): TileRequest | undefined { + return this._request; + } public set request(request: TileRequest | undefined) { assert(undefined === request || undefined === this.request); this._request = request; @@ -249,9 +293,13 @@ export abstract class Tile { } /** True if this tile has graphics ready to draw. */ - public get hasGraphics(): boolean { return undefined !== this._graphic; } + public get hasGraphics(): boolean { + return undefined !== this._graphic; + } /** True if this tile has a known volume tightly encompassing its graphics. */ - public get hasContentRange(): boolean { return undefined !== this._contentRange; } + public get hasContentRange(): boolean { + return undefined !== this._contentRange; + } /** A volume no larger than this tile's `range`, and optionally more tightly encompassing its contents, used for more accurate culling. */ public get contentRange(): ElementAlignedBox3d { if (undefined !== this._contentRange) @@ -321,7 +369,7 @@ export abstract class Tile { /** Disclose any resources owned by this tile, other than its [[RenderGraphic]]. * @internal */ - protected _collectStatistics(_stats: RenderMemory.Statistics): void { } + protected _collectStatistics(_stats: RenderMemory.Statistics): void {} /** Disclose resources owned by this tile and (by default) all of its child tiles. * @note Do not override this method! Override `_collectStatistics` instead. @@ -336,9 +384,10 @@ export abstract class Tile { return; const children = this.children; - if (undefined !== children) + if (undefined !== children) { for (const child of children) child.collectStatistics(stats); + } } /** If this tile's child tiles have not yet been requested, enqueue an asynchronous request to load them. @@ -414,7 +463,10 @@ export abstract class Tile { return true; // Test against intersection clip - reject if tile doesn't intersect (used for section-cut graphics). - if (testClipIntersection && undefined !== args.intersectionClip && ClipPlaneContainment.Ambiguous !== args.intersectionClip.classifyPointContainment(worldBox.points)) + if ( + testClipIntersection && undefined !== args.intersectionClip && + ClipPlaneContainment.Ambiguous !== args.intersectionClip.classifyPointContainment(worldBox.points) + ) return true; return false; @@ -473,7 +525,7 @@ export abstract class Tile { if (pt.w > .0001) range.extendXYZW(pt.x, pt.y, pt.z, pt.w); else - range.high.z = Math.max(1.0, range.high.z); // behind eye plane... + range.high.z = Math.max(1.0, range.high.z); // behind eye plane... } } else { for (const child of this.children) @@ -567,7 +619,9 @@ export abstract class Tile { /** Optional corners used to compute the screen size of the tile. These are used, e.g., by reality tiles with oriented bounding boxes to * produce more accurate size calculation. */ - public getSizeProjectionCorners(): Point3d[] | undefined { return undefined; } + public getSizeProjectionCorners(): Point3d[] | undefined { + return undefined; + } } /** Describes the current status of a [[Tile]]'s content. Tile content is loaded via an asynchronous [[TileRequest]]. @@ -656,7 +710,7 @@ export enum TileBoundingBoxes { } // TileLoadStatus is computed from the combination of Tile._state and, if Tile.request is defined, Tile.request.state. -const enum TileState {// eslint-disable-line no-restricted-syntax +const enum TileState { // eslint-disable-line no-restricted-syntax NotReady = TileLoadStatus.NotLoaded, // Tile requires loading, but no request has yet completed. Ready = TileLoadStatus.Ready, // request completed successfully, or no loading was required. NotFound = TileLoadStatus.NotFound, // request failed. diff --git a/core/frontend/src/tile/TileAdmin.ts b/core/frontend/src/tile/TileAdmin.ts index 9ac8c1f97bc5..df1fd3e7fd0d 100644 --- a/core/frontend/src/tile/TileAdmin.ts +++ b/core/frontend/src/tile/TileAdmin.ts @@ -6,21 +6,56 @@ * @module Tiles */ import { - assert, BeDuration, BeEvent, BentleyStatus, BeTimePoint, Id64, Id64Array, Id64String, IModelStatus, ProcessDetector, + assert, + BeDuration, + BeEvent, + BentleyStatus, + BeTimePoint, + Id64, + Id64Array, + Id64String, + IModelStatus, + ProcessDetector, } from "@itwin/core-bentley"; import { - BackendError, defaultTileOptions, EdgeOptions, ElementGraphicsRequestProps, getMaximumMajorTileFormatVersion, IModelError, IModelTileRpcInterface, - IModelTileTreeProps, RenderSchedule, RpcOperation, RpcResponseCacheControl, ServerTimeoutError, TileContentSource, TileVersionInfo, + BackendError, + defaultTileOptions, + EdgeOptions, + ElementGraphicsRequestProps, + getMaximumMajorTileFormatVersion, + IModelError, + IModelTileRpcInterface, + IModelTileTreeProps, + RenderSchedule, + RpcOperation, + RpcResponseCacheControl, + ServerTimeoutError, + TileContentSource, + TileVersionInfo, } from "@itwin/core-common"; +import type { FrontendStorage } from "@itwin/object-storage-core/lib/frontend"; import { IModelApp } from "../IModelApp"; -import { IpcApp } from "../IpcApp"; import { IModelConnection } from "../IModelConnection"; +import { IpcApp } from "../IpcApp"; import { Viewport } from "../Viewport"; import { - DisclosedTileTreeSet, FetchCloudStorage, IModelTileTree, LRUTileList, ReadonlyTileUserSet, Tile, TileContentDecodingStatistics, TileLoadStatus, - TileRequest, TileRequestChannels, TileStorage, TileTree, TileTreeOwner, TileUsageMarker, TileUser, UniqueTileUserSets, + DisclosedTileTreeSet, + FetchCloudStorage, + IModelTileTree, + LRUTileList, + ReadonlyTileUserSet, + Tile, + TileContentDecodingStatistics, + TileLoadStatus, + TileRequest, + TileRequestChannels, + TileStorage, + TileTree, + TileTreeOwner, + TileUsageMarker, + TileUser, + UniqueTileUserSets, } from "./internal"; -import type { FrontendStorage } from "@itwin/object-storage-core/lib/frontend"; /** Details about any tiles not handled by [[TileAdmin]]. At this time, that means OrbitGT point cloud tiles. * Used for bookkeeping by SelectedAndReadyTiles @@ -186,7 +221,9 @@ export class TileAdmin { } /** @internal */ - public get emptyTileUserSet(): ReadonlyTileUserSet { return UniqueTileUserSets.emptySet; } + public get emptyTileUserSet(): ReadonlyTileUserSet { + return UniqueTileUserSets.emptySet; + } /** Returns basic statistics about the TileAdmin's current state. */ public get statistics(): TileAdmin.Statistics { @@ -223,7 +260,9 @@ export class TileAdmin { this.channels = new TileRequestChannels(rpcConcurrency, true === options.cacheTileMetadata); this._maxActiveTileTreePropsRequests = options.maxActiveTileTreePropsRequests ?? 10; - this._defaultTileSizeModifier = (undefined !== options.defaultTileSizeModifier && options.defaultTileSizeModifier > 0) ? options.defaultTileSizeModifier : 1.0; + this._defaultTileSizeModifier = (undefined !== options.defaultTileSizeModifier && options.defaultTileSizeModifier > 0) + ? options.defaultTileSizeModifier + : 1.0; this._retryInterval = undefined !== options.retryInterval ? options.retryInterval : 1000; this._enableInstancing = options.enableInstancing ?? defaultTileOptions.enableInstancing; this.edgeOptions = { @@ -236,7 +275,10 @@ export class TileAdmin { this.ignoreAreaPatterns = options.ignoreAreaPatterns ?? defaultTileOptions.ignoreAreaPatterns; this.enableExternalTextures = options.enableExternalTextures ?? defaultTileOptions.enableExternalTextures; this.disableMagnification = options.disableMagnification ?? defaultTileOptions.disableMagnification; - this.percentGPUMemDisablePreload = Math.max(0, Math.min((options.percentGPUMemDisablePreload === undefined ? 80 : options.percentGPUMemDisablePreload), 80)); + this.percentGPUMemDisablePreload = Math.max( + 0, + Math.min(options.percentGPUMemDisablePreload === undefined ? 80 : options.percentGPUMemDisablePreload, 80), + ); this.alwaysRequestEdges = true === options.alwaysRequestEdges; this.alwaysSubdivideIncompleteTiles = options.alwaysSubdivideIncompleteTiles ?? defaultTileOptions.alwaysSubdivideIncompleteTiles; this.maximumMajorTileFormatVersion = options.maximumMajorTileFormatVersion ?? defaultTileOptions.maximumMajorTileFormatVersion; @@ -279,7 +321,7 @@ export class TileAdmin { const minTreeTime = ignoreMinimums ? 0.1 : 10; // If unspecified, tile expiration time defaults to 20 seconds. - this.tileExpirationTime = clamp((options.tileExpirationTime ?? 20), minTileTime, 60)!; + this.tileExpirationTime = clamp(options.tileExpirationTime ?? 20, minTileTime, 60)!; // If unspecified, trees never expire (will change this to use a default later). this.tileTreeExpirationTime = clamp(options.tileTreeExpirationTime ?? 300, minTreeTime, 3600); @@ -291,9 +333,12 @@ export class TileAdmin { this._removeIModelConnectionOnCloseListener = IModelConnection.onClose.addListener((iModel) => this.onIModelClosed(iModel)); // If unspecified preload 2 levels of parents for context tiles. - this.contextPreloadParentDepth = Math.max(0, Math.min((options.contextPreloadParentDepth === undefined ? 2 : options.contextPreloadParentDepth), 8)); + this.contextPreloadParentDepth = Math.max( + 0, + Math.min(options.contextPreloadParentDepth === undefined ? 2 : options.contextPreloadParentDepth, 8), + ); // If unspecified skip one level before preloading of parents of context tiles. - this.contextPreloadParentSkip = Math.max(0, Math.min((options.contextPreloadParentSkip === undefined ? 1 : options.contextPreloadParentSkip), 5)); + this.contextPreloadParentSkip = Math.max(0, Math.min(options.contextPreloadParentSkip === undefined ? 1 : options.contextPreloadParentSkip, 5)); const removals = [ this.onTileLoad.addListener(() => this.invalidateAllScenes()), @@ -329,7 +374,9 @@ export class TileAdmin { } /** @internal */ - public get enableInstancing() { return this._enableInstancing; } + public get enableInstancing() { + return this._enableInstancing; + } /** Given a numeric combined major+minor tile format version (typically obtained from a request to the backend to query the maximum tile format version it supports), * return the maximum *major* format version to be used to request tile content from the backend. @@ -348,7 +395,9 @@ export class TileAdmin { * Changing it after startup will change it for all Viewports that do not explicitly override it with their own multiplier. * This value must be greater than zero. */ - public get defaultTileSizeModifier() { return this._defaultTileSizeModifier; } + public get defaultTileSizeModifier() { + return this._defaultTileSizeModifier; + } public set defaultTileSizeModifier(modifier: number) { if (modifier !== this._defaultTileSizeModifier && modifier > 0 && !Number.isNaN(modifier)) { this._defaultTileSizeModifier = modifier; @@ -415,7 +464,9 @@ export class TileAdmin { * @internal */ public get isPreloadingAllowed(): boolean { - return !this._isMobile && this.percentGPUMemDisablePreload > 0 && (this._maxTotalTileContentBytes === undefined || this._lruList.totalBytesUsed / this._maxTotalTileContentBytes * 100 < this.percentGPUMemDisablePreload); + return !this._isMobile && this.percentGPUMemDisablePreload > 0 && + (this._maxTotalTileContentBytes === undefined || + this._lruList.totalBytesUsed / this._maxTotalTileContentBytes * 100 < this.percentGPUMemDisablePreload); } /** Invoked from the [[ToolAdmin]] event loop to process any pending or active requests for tiles. @@ -656,7 +707,14 @@ export class TileAdmin { throw new Error("Provided iModel has no iModelId"); const { guid, tokenProps, treeId } = this.getTileRequestProps(tile); - const content = await (await this.getTileStorage()).downloadTile(tokenProps, tile.iModelTree.iModel.iModelId, tile.iModelTree.iModel.changeset.id, treeId, tile.contentId, guid); + const content = await (await this.getTileStorage()).downloadTile( + tokenProps, + tile.iModelTree.iModel.iModelId, + tile.iModelTree.iModel.changeset.id, + treeId, + tile.contentId, + guid, + ); return content; } @@ -786,7 +844,10 @@ export class TileAdmin { * Otherwise, special tiles must be requested based on the script's sourceId (RenderTimeline or DisplayStyle element). * @internal */ - public getScriptInfoForTreeId(modelId: Id64String, script: RenderSchedule.ScriptReference | undefined): { timeline?: RenderSchedule.ModelTimeline, animationId?: Id64String } | undefined { + public getScriptInfoForTreeId( + modelId: Id64String, + script: RenderSchedule.ScriptReference | undefined, + ): { timeline?: RenderSchedule.ModelTimeline, animationId?: Id64String } | undefined { if (!script || !script.script.requiresBatching) return undefined; @@ -1319,10 +1380,13 @@ class TileTreePropsRequest { public readonly iModel: IModelConnection, private readonly _treeId: string, private readonly _resolve: (props: IModelTileTreeProps) => void, - private readonly _reject: (error: Error) => void) { + private readonly _reject: (error: Error) => void, + ) { } - public get isDispatched(): boolean { return this._isDispatched; } + public get isDispatched(): boolean { + return this._isDispatched; + } public dispatch(): void { if (this.isDispatched) diff --git a/core/frontend/src/tile/TileDrawArgs.ts b/core/frontend/src/tile/TileDrawArgs.ts index 44fd0e182a36..7d2e24a8f1fe 100644 --- a/core/frontend/src/tile/TileDrawArgs.ts +++ b/core/frontend/src/tile/TileDrawArgs.ts @@ -7,8 +7,9 @@ */ import { BeTimePoint } from "@itwin/core-bentley"; -import { ClipVector, Geometry, Map4d, Matrix4d, Point3d, Point4d, Range1d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; import { FeatureAppearanceProvider, FrustumPlanes, HiddenLine, ViewFlagOverrides } from "@itwin/core-common"; +import { ClipVector, Geometry, Map4d, Matrix4d, Point3d, Point4d, Range1d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; +import { CoordSystem } from "../CoordSystem"; import { FeatureSymbology } from "../render/FeatureSymbology"; import { GraphicBranch, GraphicBranchOptions } from "../render/GraphicBranch"; import { RenderClipVolume } from "../render/RenderClipVolume"; @@ -17,7 +18,6 @@ import { RenderPlanarClassifier } from "../render/RenderPlanarClassifier"; import { RenderTextureDrape } from "../render/RenderSystem"; import { SceneContext } from "../ViewContext"; import { ViewingSpace } from "../ViewingSpace"; -import { CoordSystem } from "../CoordSystem"; import { Tile, TileGraphicType, TileTree } from "./internal"; const scratchRange = new Range3d(); @@ -116,9 +116,13 @@ export class TileDrawArgs { /** For perspective views, the view-Z of the near plane. */ private readonly _nearFrontCenter?: Point3d; /** Overrides applied to the view's [ViewFlags]($common) when drawing the tiles. */ - public get viewFlagOverrides(): ViewFlagOverrides { return this.graphics.viewFlagOverrides; } + public get viewFlagOverrides(): ViewFlagOverrides { + return this.graphics.viewFlagOverrides; + } /** If defined, replaces the view's own symbology overrides when drawing the tiles. */ - public get symbologyOverrides(): FeatureSymbology.Overrides | undefined { return this.graphics.symbologyOverrides; } + public get symbologyOverrides(): FeatureSymbology.Overrides | undefined { + return this.graphics.symbologyOverrides; + } /** If defined, tiles will be culled if they do not intersect this clip. */ public intersectionClip?: ClipVector; /** If defined, a bounding range in tile tree coordinates outside of which tiles should not be selected. */ @@ -195,10 +199,10 @@ export class TileDrawArgs { if (viewZ.dotProduct(toFront) < radius) { center = this._nearFrontCenter; } else { - // Find point on sphere closest to eye. + // Find point on sphere closest to eye. const toEye = center.unitVectorTo(this.context.viewport.view.camera.eye); - if (toEye) { // Only if tile is not already behind the eye. + if (toEye) { // Only if tile is not already behind the eye. toEye.scaleInPlace(radius); center.addInPlace(toEye); } @@ -207,7 +211,9 @@ export class TileDrawArgs { const viewPt = this.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(center); const viewPt2 = new Point3d(viewPt.x + 1.0, viewPt.y, viewPt.z); - return this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance(this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2)); + return this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance( + this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2), + ); } /** Compute this size of a sphere on screen in pixels */ @@ -218,7 +224,9 @@ export class TileDrawArgs { const viewPt = this.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(center); const viewPt2 = new Point3d(viewPt.x + 1.0, viewPt.y, viewPt.z); - const pixelSizeAtPt = this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance(this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2)); + const pixelSizeAtPt = this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance( + this.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2), + ); return 0 !== pixelSizeAtPt ? radius / pixelSizeAtPt : 1.0e-3; } @@ -252,14 +260,14 @@ export class TileDrawArgs { let maxS = 0; let maxR = 0; if (scale[0] > scale[1]) - maxS = (scale[0] > scale[2] ? 0 : 2); + maxS = scale[0] > scale[2] ? 0 : 2; else - maxS = (scale[1] > scale[2] ? 1 : 2); + maxS = scale[1] > scale[2] ? 1 : 2; if (rangeDiag.x > rangeDiag.y) - maxR = (rangeDiag.x > rangeDiag.z ? 0 : 2); + maxR = rangeDiag.x > rangeDiag.z ? 0 : 2; else - maxR = (rangeDiag.y > rangeDiag.z ? 1 : 2); + maxR = rangeDiag.y > rangeDiag.z ? 1 : 2; return maxS !== maxR ? scale[maxS] : 1; } @@ -310,10 +318,14 @@ export class TileDrawArgs { * @see [[Viewport.tileSizeModifier]]. * @public */ - public get tileSizeModifier(): number { return this.context.viewport.tileSizeModifier; } + public get tileSizeModifier(): number { + return this.context.viewport.tileSizeModifier; + } /** @internal */ - public getTileCenter(tile: Tile): Point3d { return this.location.multiplyPoint3d(tile.center); } + public getTileCenter(tile: Tile): Point3d { + return this.location.multiplyPoint3d(tile.center); + } /** @internal */ public getTileRadius(tile: Tile): number { @@ -351,7 +363,7 @@ export class TileDrawArgs { return this._produceGraphicBranch(this.graphics); } /** @internal */ - public get secondaryClassifiers(): Map| undefined { + public get secondaryClassifiers(): Map | undefined { return undefined; } @@ -423,8 +435,10 @@ export class TileDrawArgs { /** Invoked by [[TileTree.selectTiles]]. This exists chiefly for [[SolarShadowMap]]. * @internal */ - public processSelectedTiles(_tiles: Tile[]): void { } + public processSelectedTiles(_tiles: Tile[]): void {} /* @internal */ - public get maxRealityTreeSelectionCount(): number | undefined { return undefined; } + public get maxRealityTreeSelectionCount(): number | undefined { + return undefined; + } } diff --git a/core/frontend/src/tile/TileGeometryCollector.ts b/core/frontend/src/tile/TileGeometryCollector.ts index c643b5e89f76..5c395d903bf3 100644 --- a/core/frontend/src/tile/TileGeometryCollector.ts +++ b/core/frontend/src/tile/TileGeometryCollector.ts @@ -8,9 +8,7 @@ import { IndexedPolyface, Range3d, Transform } from "@itwin/core-geometry"; import { IModelApp } from "../IModelApp"; -import { - Tile, TileTreeReference, TileUser, -} from "./internal"; +import { Tile, TileTreeReference, TileUser } from "./internal"; /** Enumerates the statuses returned by [[TileGeometryCollector.collectTile]]. * - "accept": The tile's geometry should be collected. diff --git a/core/frontend/src/tile/TileRequest.ts b/core/frontend/src/tile/TileRequest.ts index 87041e0228f9..cedcd99fbd67 100644 --- a/core/frontend/src/tile/TileRequest.ts +++ b/core/frontend/src/tile/TileRequest.ts @@ -44,10 +44,14 @@ export class TileRequest { } /** The request's current state. */ - public get state(): TileRequest.State { return this._state; } + public get state(): TileRequest.State { + return this._state; + } /** True if the request has been enqueued but not yet dispatched. */ - public get isQueued() { return TileRequest.State.Queued === this._state; } + public get isQueued() { + return TileRequest.State.Queued === this._state; + } /** True if the request has been canceled. */ public get isCanceled(): boolean { @@ -64,7 +68,9 @@ export class TileRequest { } /** The tile tree to which the requested [[Tile]] belongs. */ - public get tree(): TileTree { return this.tile.tree; } + public get tree(): TileTree { + return this.tile.tree; + } /** Indicate that the specified user is awaiting the result of this request. * @internal @@ -211,7 +217,7 @@ export namespace TileRequest { // eslint-disable-line no-redeclare /** The states through which a [[TileRequest]] proceeds. During the first 3 states, the [[Tile]]'s `request` member is defined, * and its [[Tile.LoadStatus]] is computed based on the state of its request. - *@ public + * @ public */ export enum State { /** Initial state. Request is pending but not yet dispatched. */ diff --git a/core/frontend/src/tile/TileRequestChannel.ts b/core/frontend/src/tile/TileRequestChannel.ts index 81b644e92eea..f2f5bfd76d69 100644 --- a/core/frontend/src/tile/TileRequestChannel.ts +++ b/core/frontend/src/tile/TileRequestChannel.ts @@ -291,15 +291,15 @@ export class TileRequestChannel { /** Invoked when a request that was previously dispatched is canceled before a response is received. * Some channels accumulate such requests for later cancellation in [[processCancellations]]. */ - public onActiveRequestCanceled(_request: TileRequest): void { } + public onActiveRequestCanceled(_request: TileRequest): void {} /** Invoked to do any additional work to cancel tiles accumulated by [[onActiveRequestCanceled]]. For example, a channel that requests tile content * over IPC may signal to the tile generation process that it should cease generating content for those tiles. */ - public processCancellations(): void { } + public processCancellations(): void {} /** Invoked when an iModel is closed, to clean up any state associated with that iModel. */ - public onIModelClosed(_iModel: IModelConnection): void { } + public onIModelClosed(_iModel: IModelConnection): void {} /** Request content for the specified tile. The default implementation simply forwards to [[Tile.requestContent]]. */ public async requestContent(tile: Tile, isCanceled: () => boolean): Promise { diff --git a/core/frontend/src/tile/TileRequestChannels.ts b/core/frontend/src/tile/TileRequestChannels.ts index 645910b7f3fc..6cad3e9efd0c 100644 --- a/core/frontend/src/tile/TileRequestChannels.ts +++ b/core/frontend/src/tile/TileRequestChannels.ts @@ -6,11 +6,9 @@ * @module Tiles */ -import { IpcApp } from "../IpcApp"; import { IModelConnection } from "../IModelConnection"; -import { - IModelTile, IModelTileRequestChannels, TileRequest, TileRequestChannel, TileRequestChannelStatistics, -} from "./internal"; +import { IpcApp } from "../IpcApp"; +import { IModelTile, IModelTileRequestChannels, TileRequest, TileRequestChannel, TileRequestChannelStatistics } from "./internal"; /** For an [[IpcApp]], allows backend element graphics requests in progress to be canceled. */ class ElementGraphicsChannel extends TileRequestChannel { diff --git a/core/frontend/src/tile/TileStorage.ts b/core/frontend/src/tile/TileStorage.ts index 230732b324b6..4e4a8b2e18bf 100644 --- a/core/frontend/src/tile/TileStorage.ts +++ b/core/frontend/src/tile/TileStorage.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import type { FrontendStorage, TransferConfig } from "@itwin/object-storage-core/lib/frontend"; import { getTileObjectReference, IModelRpcProps, IModelTileRpcInterface } from "@itwin/core-common"; +import type { FrontendStorage, TransferConfig } from "@itwin/object-storage-core/lib/frontend"; /** @beta */ export class TileStorage { - public constructor(public readonly storage: FrontendStorage) { } + public constructor(public readonly storage: FrontendStorage) {} private _transferConfigs: Map = new Map(); private _pendingTransferConfigRequests: Map> = new Map(); @@ -21,7 +21,7 @@ export class TileStorage { guid?: string, ): Promise { const transferConfig = await this.getTransferConfig(tokenProps, iModelId); - if(transferConfig === undefined) + if (transferConfig === undefined) return undefined; try { const buffer = await this.storage.download({ @@ -38,13 +38,14 @@ export class TileStorage { } private async getTransferConfig(tokenProps: IModelRpcProps, iModelId: string): Promise { - if(this._transferConfigs.has(iModelId)) { + if (this._transferConfigs.has(iModelId)) { const transferConfig = this._transferConfigs.get(iModelId); - if(transferConfig === undefined) + if (transferConfig === undefined) return undefined; - if(transferConfig.expiration > new Date()) + if (transferConfig.expiration > new Date()) return transferConfig; - else // Refresh expired transferConfig + // Refresh expired transferConfig + else return this.sendTransferConfigRequest(tokenProps, iModelId); } return this.sendTransferConfigRequest(tokenProps, iModelId); @@ -52,7 +53,7 @@ export class TileStorage { private async sendTransferConfigRequest(tokenProps: IModelRpcProps, iModelId: string): Promise { const pendingRequest = this._pendingTransferConfigRequests.get(iModelId); - if(pendingRequest !== undefined) + if (pendingRequest !== undefined) return pendingRequest; const request = (async () => { diff --git a/core/frontend/src/tile/TileTree.ts b/core/frontend/src/tile/TileTree.ts index 1925cf3bb796..f8a7ed773903 100644 --- a/core/frontend/src/tile/TileTree.ts +++ b/core/frontend/src/tile/TileTree.ts @@ -7,8 +7,8 @@ */ import { BeDuration, BeTimePoint, dispose, Id64String } from "@itwin/core-bentley"; -import { Matrix4d, Range3d, Transform } from "@itwin/core-geometry"; import { ElementAlignedBox3d, FrustumPlanes, ViewFlagOverrides } from "@itwin/core-common"; +import { Matrix4d, Range3d, Transform } from "@itwin/core-geometry"; import { calculateEcefToDbTransformAtLocation } from "../BackgroundMapGeometry"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; @@ -67,7 +67,9 @@ export abstract class TileTree { /** The length of time after which tiles belonging to this tree are considered elegible for disposal if they are no longer in use. */ public readonly expirationTime: BeDuration; /** @internal */ - public get loadPriority(): TileLoadPriority { return this._loadPriority; } + public get loadPriority(): TileLoadPriority { + return this._loadPriority; + } private readonly _loadPriority: TileLoadPriority; /** Optional tight bounding box around the entire contents of all of this tree's tiles. */ public readonly contentRange?: ElementAlignedBox3d; @@ -97,20 +99,32 @@ export abstract class TileTree { public abstract prune(): void; /** True if this tile tree contains 2d graphics. */ - public get is2d(): boolean { return !this.is3d; } + public get is2d(): boolean { + return !this.is3d; + } /** @internal */ - public get isPointCloud(): boolean { return false; } + public get isPointCloud(): boolean { + return false; + } /** @internal */ - public get clipVolume(): RenderClipVolume | undefined { return this._clipVolume; } + public get clipVolume(): RenderClipVolume | undefined { + return this._clipVolume; + } /** The volume of space occupied by this tile tree. */ - public get range(): ElementAlignedBox3d { return this.rootTile.range; } + public get range(): ElementAlignedBox3d { + return this.rootTile.range; + } /** The most recent time at which tiles [[selectTiles]] was called. */ - public get lastSelectedTime(): BeTimePoint { return this._lastSelected; } + public get lastSelectedTime(): BeTimePoint { + return this._lastSelected; + } /** True if a tile and its child tiles should not be drawn simultaneously. * Default: true. */ - public get parentsAndChildrenExclusive(): boolean { return true; } + public get parentsAndChildrenExclusive(): boolean { + return true; + } /** Constructor */ protected constructor(params: TileTreeParams) { @@ -139,7 +153,9 @@ export abstract class TileTree { } /** True if [[dispose]] has been called on this tile tree. */ - public get isDisposed(): boolean { return this._isDisposed; } + public get isDisposed(): boolean { + return this._isDisposed; + } /** Dispose of this tree and any resources owned by it. This is typically invoked by a [[TileTreeOwner]]. */ public dispose(): void { @@ -196,4 +212,3 @@ export abstract class TileTree { public collectTileGeometry(_collector: TileGeometryCollector): void { } } - diff --git a/core/frontend/src/tile/TileTreeParams.ts b/core/frontend/src/tile/TileTreeParams.ts index 9127ce85cbd9..edebfe96ebe5 100644 --- a/core/frontend/src/tile/TileTreeParams.ts +++ b/core/frontend/src/tile/TileTreeParams.ts @@ -7,8 +7,8 @@ */ import { BeDuration, Id64String } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { ElementAlignedBox3d } from "@itwin/core-common"; +import { Transform } from "@itwin/core-geometry"; import { IModelConnection } from "../IModelConnection"; import { RenderClipVolume } from "../render/RenderClipVolume"; import { TileLoadPriority } from "./internal"; diff --git a/core/frontend/src/tile/TileTreeReference.ts b/core/frontend/src/tile/TileTreeReference.ts index 3eb98b4304a2..7a3871d27ea2 100644 --- a/core/frontend/src/tile/TileTreeReference.ts +++ b/core/frontend/src/tile/TileTreeReference.ts @@ -7,8 +7,15 @@ */ import { assert, BeTimePoint } from "@itwin/core-bentley"; +import { + ElementAlignedBox3d, + FeatureAppearanceProvider, + FrustumPlanes, + HiddenLine, + PlanarClipMaskPriority, + ViewFlagOverrides, +} from "@itwin/core-common"; import { Matrix4d, Range1d, Range3d, Transform } from "@itwin/core-geometry"; -import { ElementAlignedBox3d, FeatureAppearanceProvider, FrustumPlanes, HiddenLine, PlanarClipMaskPriority, ViewFlagOverrides } from "@itwin/core-common"; import { HitDetail } from "../HitDetail"; import { FeatureSymbology } from "../render/FeatureSymbology"; import { RenderClipVolume } from "../render/RenderClipVolume"; @@ -16,7 +23,17 @@ import { RenderMemory } from "../render/RenderMemory"; import { DecorateContext, SceneContext } from "../ViewContext"; import { ScreenViewport } from "../Viewport"; import { - DisclosedTileTreeSet, GeometryTileTreeReference, MapFeatureInfoOptions, MapLayerFeatureInfo, RenderGraphicTileTreeArgs, TileDrawArgs, TileGeometryCollector, TileTree, TileTreeLoadStatus, TileTreeOwner, tileTreeReferenceFromRenderGraphic, + DisclosedTileTreeSet, + GeometryTileTreeReference, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + RenderGraphicTileTreeArgs, + TileDrawArgs, + TileGeometryCollector, + TileTree, + TileTreeLoadStatus, + TileTreeOwner, + tileTreeReferenceFromRenderGraphic, } from "./internal"; /** Describes the type of graphics produced by a [[TileTreeReference]]. @@ -79,7 +96,9 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { * If you *don't* override this method, override [[canSupplyToolTip]] to return false. * Callers who want to obtain a tooltip should prefer [[getToolTipPromise]]. */ - public async getToolTip(_hit: HitDetail): Promise { return undefined; } + public async getToolTip(_hit: HitDetail): Promise { + return undefined; + } /** Return whether this TileTreeReference can supply a tooltip describing the entity represented by the specified hit. * [[getToolTipPromise]] calls [[getToolTip]] if and only if `canSupplyToolTip` returns `true`. @@ -97,12 +116,14 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { /** Optionally return a MapLayerFeatureInfo object describing the hit.]. * @alpha */ - public async getMapFeatureInfo(_hit: HitDetail, _options?: MapFeatureInfoOptions): Promise { return undefined; } + public async getMapFeatureInfo(_hit: HitDetail, _options?: MapFeatureInfoOptions): Promise { + return undefined; + } /** Optionally add any decorations specific to this reference. For example, map tile trees may add a logo image and/or copyright attributions. * @note This is currently only invoked for background maps and TiledGraphicsProviders - others have no decorations, but if they did implement this it would not be called. */ - public decorate(_context: DecorateContext): void { } + public decorate(_context: DecorateContext): void {} /** Unions this reference's range with the supplied range to help compute a volume in world space for fitting a viewport to its contents. * Override this function if a reference's range should not be included in the fit range, or a range different from its tile tree's range should be used. @@ -171,7 +192,9 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { } /** @beta */ - public getTransformFromIModel(): Transform | undefined { return undefined; } + public getTransformFromIModel(): Transform | undefined { + return undefined; + } /** @internal */ protected getAnimationTransformNodeId(_tree: TileTree): number | undefined { @@ -245,7 +268,7 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { } /** @internal */ - public getTerrainHeight(_terrainHeights: Range1d): void { } + public getTerrainHeight(_terrainHeights: Range1d): void {} /** Return whether the geometry exposed by this tile tree reference should cast shadows on other geometry. */ public get castsShadows(): boolean { @@ -253,16 +276,20 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { } /** Return whether this reference has global coverage. Mapping data is global and some non-primary models such as the OSM building layer have global coverage */ - public get isGlobal(): boolean { return false; } + public get isGlobal(): boolean { + return false; + } /** The [PlanarClipMaskPriority]($common) of this tile tree used to determine which tile trees contribute to a clip mask when * using [PlanarClipMaskMode.Priority]($common). * @beta */ - public get planarClipMaskPriority(): number { return PlanarClipMaskPriority.DesignModel; } + public get planarClipMaskPriority(): number { + return PlanarClipMaskPriority.DesignModel; + } /** Add attribution logo cards for the tile tree source logo cards to the viewport's logo div. */ - public addLogoCards(_cards: HTMLTableElement, _vp: ScreenViewport): void { } + public addLogoCards(_cards: HTMLTableElement, _vp: ScreenViewport): void {} /** Create a tile tree reference equivalent to this one that also supplies an implementation of [[GeometryTileTreeReference.collectTileGeometry]]. * Return `undefined` if geometry collection is not supported. @@ -309,7 +336,7 @@ export abstract class TileTreeReference /* implements RenderMemory.Consumer */ { * The reference can be used to add dynamic content to a [[Viewport]]'s scene as a [[TiledGraphicsProvider]], as in the following example: * ```ts * [[include:TileTreeReference_createFromRenderGraphic]] - *``` + * ``` * Or, it can be used as a [[DynamicSpatialClassifier]] to contextualize a reality model, like so: * ```ts * [[include:TileTreeReference_DynamicClassifier]] diff --git a/core/frontend/src/tile/TileUser.ts b/core/frontend/src/tile/TileUser.ts index 31b51ff6ae45..33e2464dcc31 100644 --- a/core/frontend/src/tile/TileUser.ts +++ b/core/frontend/src/tile/TileUser.ts @@ -40,7 +40,7 @@ export namespace TileUser { } /** Iterate the subset of `users` that are [[Viewport]]s. */ - export function * viewportsFromUsers(users: Iterable): Iterable { + export function* viewportsFromUsers(users: Iterable): Iterable { for (const user of users) if (user instanceof Viewport) yield user; diff --git a/core/frontend/src/tile/TileUserSet.ts b/core/frontend/src/tile/TileUserSet.ts index d6c1dbd5f0e2..08dbf31d77a4 100644 --- a/core/frontend/src/tile/TileUserSet.ts +++ b/core/frontend/src/tile/TileUserSet.ts @@ -35,9 +35,15 @@ class TileUserSet extends ReadonlyTileUserSet { return clone; } - public insert(user: TileUser): number { return this._insert(user); } - public remove(user: TileUser): number { return this._remove(user); } - public clear(): void { this._clear(); } + public insert(user: TileUser): number { + return this._insert(user); + } + public remove(user: TileUser): number { + return this._remove(user); + } + public clear(): void { + this._clear(); + } } function compareTileUserSets(lhs: TileUserSet, rhs: TileUserSet): number { diff --git a/core/frontend/src/tile/TiledGraphicsProvider.ts b/core/frontend/src/tile/TiledGraphicsProvider.ts index 000f5d68bfe1..984ebbc29cca 100644 --- a/core/frontend/src/tile/TiledGraphicsProvider.ts +++ b/core/frontend/src/tile/TiledGraphicsProvider.ts @@ -6,8 +6,8 @@ * @module Views */ -import { Viewport } from "../Viewport"; import { SceneContext } from "../ViewContext"; +import { Viewport } from "../Viewport"; import { TileTreeReference } from "./internal"; /** Provides a way for applications to inject additional non-decorative graphics into a [[Viewport]] by supplying one or more [[TileTreeReference]]s capable of loading and drawing the graphics. diff --git a/core/frontend/src/tile/ViewFlagOverrides.ts b/core/frontend/src/tile/ViewFlagOverrides.ts index 41b48e08b519..ccbdb2e06730 100644 --- a/core/frontend/src/tile/ViewFlagOverrides.ts +++ b/core/frontend/src/tile/ViewFlagOverrides.ts @@ -12,7 +12,9 @@ import { RenderMode, ViewFlagOverrides, ViewFlags } from "@itwin/core-common"; * @param options Customize the overrides. Any properties left unspecified use the current view settings, except white-on-white reversal is always disabled. * @internal */ -export function createDefaultViewFlagOverrides(options: { clipVolume?: boolean, shadows?: boolean, lighting?: boolean, thematic?: false }): ViewFlagOverrides { +export function createDefaultViewFlagOverrides( + options: { clipVolume?: boolean, shadows?: boolean, lighting?: boolean, thematic?: false }, +): ViewFlagOverrides { const noLights = undefined !== options.lighting ? !options.lighting : undefined; const viewflags = ViewFlags.fromJSON({ renderMode: RenderMode.SmoothShade, diff --git a/core/frontend/src/tile/map/ArcGISTileMap.ts b/core/frontend/src/tile/map/ArcGISTileMap.ts index 86d7af2f89f0..3a17f37bd763 100644 --- a/core/frontend/src/tile/map/ArcGISTileMap.ts +++ b/core/frontend/src/tile/map/ArcGISTileMap.ts @@ -7,8 +7,8 @@ */ import { assert, compareStrings, Dictionary, Logger } from "@itwin/core-bentley"; -import { QuadId } from "../internal"; import { ImageMapLayerSettings } from "@itwin/core-common"; +import { QuadId } from "../internal"; const loggerCategory = "ArcGISTileMap"; /** @internal */ @@ -18,7 +18,6 @@ const nonVisibleChildren = [false, false, false, false]; /** @internal */ export class ArcGISTileMap { - // For similar reasons as the corner offset, we need to keep the tile map size not too big to avoid covering multiple bundles. public tileMapRequestSize = 8; private static maxLod = 30; @@ -26,9 +25,11 @@ export class ArcGISTileMap { // We want to query a tile map that covers an area all around the top-lef missing tile, we offset the top-left corner position of the tilemap. // We used to create a 32x32 tiles area around the missing tiles, but this was causing the tilemap top-left position // to fall outside the dataset bundle of the remote server, thus giving invalid response. - public get tileMapOffset() {return (this.tileMapRequestSize * 0.5);} + public get tileMapOffset() { + return (this.tileMapRequestSize * 0.5); + } - public fallbackTileMapRequestSize = 2; + public fallbackTileMapRequestSize = 2; private _callQueues: Array> | undefined; private _tilesCache = new Dictionary((lhs, rhs) => compareStrings(lhs, rhs)); @@ -36,13 +37,12 @@ export class ArcGISTileMap { private _fetchFunc: FetchFunction; private _settings: ImageMapLayerSettings; - constructor(restBaseUrl: string, settings: ImageMapLayerSettings, fetchFunc: FetchFunction ){ + constructor(restBaseUrl: string, settings: ImageMapLayerSettings, fetchFunc: FetchFunction) { this._restBaseUrl = restBaseUrl; this._fetchFunc = fetchFunc; this._settings = settings; // eslint-disable-next-line @typescript-eslint/no-floating-promises this._callQueues = new Array>(ArcGISTileMap.maxLod).fill(Promise.resolve(nonVisibleChildren)); - } protected async fetchTileMapFromServer(level: number, row: number, column: number, width: number, height: number): Promise { const tmpUrl = `${this._restBaseUrl}/tilemap/${level}/${row}/${column}/${width}/${height}?f=json`; @@ -50,7 +50,7 @@ export class ArcGISTileMap { return response.json(); } - protected getAvailableTilesFromCache(tiles: QuadId[]): {allTilesFound: boolean, available: boolean[]} { + protected getAvailableTilesFromCache(tiles: QuadId[]): { allTilesFound: boolean, available: boolean[] } { let allTilesFound = true; // Check children visibility from cache @@ -62,7 +62,7 @@ export class ArcGISTileMap { return avail ?? false; }); - return {allTilesFound, available}; + return { allTilesFound, available }; } public async getChildrenAvailability(childIds: QuadId[]): Promise { @@ -73,7 +73,6 @@ export class ArcGISTileMap { // let check if cache doesn't already contain what we are looking for. const cacheInfo = this.getAvailableTilesFromCache(childIds); if (cacheInfo.allTilesFound) { - if (cacheInfo.available.includes(false)) return cacheInfo.available; @@ -84,8 +83,8 @@ export class ArcGISTileMap { // However, we dont want several overlapping large tilemap request being made simultaneously for tiles on the same level. // To avoid this from happening, we 'serialize' async calls so that we wait until the first tilemap request has completed // before making another one. - const childLevel = childIds[0].level+1; - if (this._callQueues && childLevel < this._callQueues.length ) { + const childLevel = childIds[0].level + 1; + if (this._callQueues && childLevel < this._callQueues.length) { const res = this._callQueues[childLevel].then(async () => { return this.getChildrenAvailabilityFromServer(childIds); }); @@ -105,7 +104,7 @@ export class ArcGISTileMap { return missingTileFound; for (let j = startColumn; j <= endColumn && !missingTileFound; j++) { - for (let i = startRow; i<=endRow && !missingTileFound; i++) { + for (let i = startRow; i <= endRow && !missingTileFound; i++) { if (j >= 0 && i >= 0) { const contentId = QuadId.getTileContentId(level, j, i); if (this._tilesCache.get(contentId) === undefined) { @@ -117,14 +116,13 @@ export class ArcGISTileMap { return missingTileFound; } - private collectTilesMissingFromCache( missingQueryTiles: QuadId[]) { - const missingTiles: QuadId[] = []; + private collectTilesMissingFromCache(missingQueryTiles: QuadId[]) { + const missingTiles: QuadId[] = []; for (const quad of missingQueryTiles) { const contentId = QuadId.getTileContentId(quad.level, quad.column, quad.row); const avail = this._tilesCache.get(contentId); if (avail === undefined) missingTiles.push(quad); - } return missingTiles; } @@ -132,25 +130,25 @@ export class ArcGISTileMap { // Query tiles are tiles that we need to check availability // The array is assumed to be in in row major orientation, i.e.: [TileRow0Col0, TileRow0Col1, TileRow1Col0, TileRow1Col1,] public async fetchAndReadTilemap(queryTiles: QuadId[], reqWidth: number, reqHeight: number) { - let available = queryTiles.map(()=>false); - if (queryTiles.length === 0 ) { + let available = queryTiles.map(() => false); + if (queryTiles.length === 0) { return available; } // console.log(`queryTiles: ${queryTiles.map((quad) => quad.contentId)}`); // Find the top-left most corner of the extent covering the query tiles. - const getTopLeftCorner = (tiles: QuadId[]): {row: number|undefined, column: number|undefined} => { - let row: number|undefined; - let column: number|undefined; + const getTopLeftCorner = (tiles: QuadId[]): { row: number | undefined, column: number | undefined } => { + let row: number | undefined; + let column: number | undefined; for (const quad of tiles) { - if (row === undefined || quad.row <= row ) + if (row === undefined || quad.row <= row) row = quad.row; if (column === undefined || quad.column <= column) { - column = quad.column ; + column = quad.column; } } - return {row, column}; + return { row, column }; }; const level = queryTiles[0].level; // We assume all tiles to be on the same level @@ -158,37 +156,56 @@ export class ArcGISTileMap { let missingQueryTiles = this.collectTilesMissingFromCache(queryTiles); let gotAdjusted = false; let nbAttempt = 0; // Safety: We should never be making more requests than the number of queries tiles (otherwise something is wrong) - while (missingQueryTiles.length > 0 - && (nbAttempt++ < queryTiles.length) ) { + while ( + missingQueryTiles.length > 0 + && (nbAttempt++ < queryTiles.length) + ) { const tileMapTopLeft = getTopLeftCorner(missingQueryTiles); if (tileMapTopLeft.row === undefined || tileMapTopLeft.column === undefined) - return available; // Should not occurs since missingQueryTiles is non empty + return available; // Should not occurs since missingQueryTiles is non empty let tileMapRow = tileMapTopLeft.row; let tileMapColumn = tileMapTopLeft.column; - const logLocationOffset = (newRow: number, newCol: number) => `[Row:${newRow !== tileMapTopLeft.row ? `${tileMapTopLeft.row}->${newRow}` : `${newRow}`} Column:${newCol !== tileMapTopLeft.column ? `${tileMapTopLeft.column}->${newCol}` : `${newCol}`}]`; + const logLocationOffset = (newRow: number, newCol: number) => + `[Row:${newRow !== tileMapTopLeft.row ? `${tileMapTopLeft.row}->${newRow}` : `${newRow}`} Column:${ + newCol !== tileMapTopLeft.column ? `${tileMapTopLeft.column}->${newCol}` : `${newCol}` + }]`; // Position the top-left missing tile in the middle of the tilemap; minimizing requests if sibling tiles are requested right after // If previous response got adjusted, don't try to optimize tile map location if (queryTiles.length < this.tileMapRequestSize && !gotAdjusted) { const tileMapOffset = this.tileMapOffset - Math.floor(Math.sqrt(queryTiles.length) * 0.5); const missingTileBufferSize = Math.ceil(tileMapOffset * 0.5); - if (this.isCacheMissingTile(level, tileMapRow-missingTileBufferSize, tileMapColumn-missingTileBufferSize, tileMapRow-1, tileMapColumn-1)) { + if ( + this.isCacheMissingTile(level, tileMapRow - missingTileBufferSize, tileMapColumn - missingTileBufferSize, tileMapRow - 1, tileMapColumn - 1) + ) { tileMapRow = Math.max(tileMapRow - tileMapOffset, 0); tileMapColumn = Math.max(tileMapColumn - tileMapOffset, 0); Logger.logTrace(loggerCategory, `Offset applied to location in top-left direction: ${logLocationOffset(tileMapRow, tileMapColumn)}`); } else { - const leftMissingTiles = this.isCacheMissingTile(level, tileMapRow, tileMapColumn-missingTileBufferSize, tileMapRow+missingTileBufferSize, tileMapColumn-1); - const topMissingTiles = this.isCacheMissingTile(level, tileMapRow-missingTileBufferSize, tileMapColumn, tileMapRow-1, tileMapColumn+missingTileBufferSize); + const leftMissingTiles = this.isCacheMissingTile( + level, + tileMapRow, + tileMapColumn - missingTileBufferSize, + tileMapRow + missingTileBufferSize, + tileMapColumn - 1, + ); + const topMissingTiles = this.isCacheMissingTile( + level, + tileMapRow - missingTileBufferSize, + tileMapColumn, + tileMapRow - 1, + tileMapColumn + missingTileBufferSize, + ); if (leftMissingTiles && topMissingTiles) { tileMapRow = Math.max(tileMapRow - tileMapOffset, 0); - tileMapColumn = Math.max(tileMapColumn- tileMapOffset, 0); + tileMapColumn = Math.max(tileMapColumn - tileMapOffset, 0); Logger.logTrace(loggerCategory, `Offset applied to location in top-left direction. ${logLocationOffset(tileMapRow, tileMapColumn)}`); } else if (leftMissingTiles) { tileMapColumn = Math.max(tileMapColumn - tileMapOffset, 0); Logger.logTrace(loggerCategory, `Offset applied to location in left direction. ${logLocationOffset(tileMapRow, tileMapColumn)}`); - } else if (topMissingTiles) { + } else if (topMissingTiles) { tileMapRow = Math.max(tileMapRow - tileMapOffset, 0); Logger.logTrace(loggerCategory, `Offset applied to location in top direction: ${logLocationOffset(tileMapRow, tileMapColumn)}`); } else @@ -215,7 +232,7 @@ export class ArcGISTileMap { // Build cache from tile map response for (let j = 0; j < tileMapHeight; j++) { for (let i = 0; i < tileMapWidth; i++) { - const avail = json.data[(j*tileMapWidth)+i] !== 0; + const avail = json.data[(j * tileMapWidth) + i] !== 0; const curColumn = tileMapColumn + i; const curRow = tileMapRow + j; this._tilesCache.set(QuadId.getTileContentId(level, curColumn, curRow), avail); @@ -238,13 +255,13 @@ export class ArcGISTileMap { } } } - } // end loop missing tiles + } // end loop missing tiles if (nbAttempt > queryTiles.length) { Logger.logError(loggerCategory, `Request loop was terminated; unable to get missing tiles; `); } // Create final output array from cache - available = queryTiles.map((quad)=>this._tilesCache.get(quad.contentId) ?? false); + available = queryTiles.map((quad) => this._tilesCache.get(quad.contentId) ?? false); if (available.includes(false)) return available; @@ -253,14 +270,13 @@ export class ArcGISTileMap { } protected async getChildrenAvailabilityFromServer(childIds: QuadId[]): Promise { - let available; try { available = await this.fetchAndReadTilemap(childIds, this.tileMapRequestSize, this.tileMapRequestSize); } catch (err) { // if any error occurs, we assume tiles not to be visible Logger.logError(loggerCategory, `Error while fetching tile map data : ${err}`); - available = childIds.map(()=>false); + available = childIds.map(() => false); } return available; diff --git a/core/frontend/src/tile/map/ArcGisUtilities.ts b/core/frontend/src/tile/map/ArcGisUtilities.ts index 8a2b30599143..843ab7424468 100644 --- a/core/frontend/src/tile/map/ArcGisUtilities.ts +++ b/core/frontend/src/tile/map/ArcGisUtilities.ts @@ -2,11 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Angle, Constant } from "@itwin/core-geometry"; import { MapSubLayerProps } from "@itwin/core-common"; -import { MapCartoRectangle, MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerSource, MapLayerSourceStatus, MapLayerSourceValidation, ValidateSourceArgs} from "../internal"; +import { Angle, Constant } from "@itwin/core-geometry"; import { IModelApp } from "../../IModelApp"; import { headersIncludeAuthMethod } from "../../request/utils"; +import { + MapCartoRectangle, + MapLayerAccessClient, + MapLayerAccessToken, + MapLayerAccessTokenParams, + MapLayerSource, + MapLayerSourceStatus, + MapLayerSourceValidation, + ValidateSourceArgs, +} from "../internal"; /** @packageDocumentation * @module Tiles @@ -48,12 +57,12 @@ export interface ArcGisValidateSourceArgs extends ValidateSourceArgs { /** Arguments for fetching service metadata * @internal */ -export interface ArcGisGetServiceJsonArgs { +export interface ArcGisGetServiceJsonArgs { url: string; formatId: string; userName?: string; password?: string; - queryParams?: {[key: string]: string}; + queryParams?: { [key: string]: string }; ignoreCache?: boolean; requireToken?: boolean; } @@ -63,12 +72,13 @@ export interface ArcGisGetServiceJsonArgs { * @internal */ export class ArcGisUtilities { - private static getBBoxString(range?: MapCartoRectangle) { if (!range) range = MapCartoRectangle.createMaximum(); - return `${range.low.x * Angle.degreesPerRadian},${range.low.y * Angle.degreesPerRadian},${range.high.x * Angle.degreesPerRadian},${range.high.y * Angle.degreesPerRadian}`; + return `${range.low.x * Angle.degreesPerRadian},${range.low.y * Angle.degreesPerRadian},${range.high.x * Angle.degreesPerRadian},${ + range.high.y * Angle.degreesPerRadian + }`; } public static async getNationalMapSources(): Promise { @@ -80,7 +90,7 @@ export class ArcGisUtilities { return sources; for (const service of services) { - if (service.wmsUrl.length === 0) // Exclude Wfs.. + if (service.wmsUrl.length === 0) // Exclude Wfs.. continue; switch (service.serviceType) { case "ArcGIS": @@ -133,10 +143,18 @@ export class ArcGisUtilities { * @param url URL for the query. * @returns List of map layer sources. */ - public static async getSourcesFromQuery(range?: MapCartoRectangle, url = "https://usgs.maps.arcgis.com/sharing/rest/search"): Promise { + public static async getSourcesFromQuery( + range?: MapCartoRectangle, + url = "https://usgs.maps.arcgis.com/sharing/rest/search", + ): Promise { const sources = new Array(); for (let start = 1; start > 0;) { - const response = await fetch(`${url}?f=json&q=(group:9d1199a521334e77a7d15abbc29f8144) AND (type:"Map Service")&bbox=${ArcGisUtilities.getBBoxString(range)}&sortOrder=desc&start=${start}&num=100`, { method: "GET" }); + const response = await fetch( + `${url}?f=json&q=(group:9d1199a521334e77a7d15abbc29f8144) AND (type:"Map Service")&bbox=${ + ArcGisUtilities.getBBoxString(range) + }&sortOrder=desc&start=${start}&num=100`, + { method: "GET" }, + ); const json = await response.json(); if (!json) break; @@ -178,48 +196,55 @@ export class ArcGisUtilities { * Attempt to access an ArcGIS service, and validate its service metadata. * @param source Source to validate. * @param opts Validation options - */ + */ public static async validateSource(args: ArcGisValidateSourceArgs): Promise { - const {source, ignoreCache, capabilitiesFilter} = args; - const metadata = await this.getServiceJson({url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache}); + const { source, ignoreCache, capabilitiesFilter } = args; + const metadata = await this.getServiceJson({ + url: source.url, + formatId: source.formatId, + userName: source.userName, + password: source.password, + queryParams: source.collectQueryParams(), + ignoreCache, + }); const json = metadata?.content; if (json === undefined) { return { status: MapLayerSourceStatus.InvalidUrl }; } else if (json.error !== undefined) { - // If we got a 'Token Required' error, lets check what authentification methods this ESRI service offers // and return information needed to initiate the authentification process... the end-user // will have to provide his credentials before we can fully validate this source. // Note: Some servers will throw a error 403 (You do not have permissions to access this resource or perform this operation), // instead of 499 (TokenRequired) - if (json.error.code === ArcGisErrorCode.TokenRequired || json.error.code === ArcGisErrorCode.MissingPermissions) { - return (source.userName || source.password) ? {status: MapLayerSourceStatus.InvalidCredentials} : {status: MapLayerSourceStatus.RequireAuth}; + if (json.error.code === ArcGisErrorCode.TokenRequired || json.error.code === ArcGisErrorCode.MissingPermissions) { + return (source.userName || source.password) + ? { status: MapLayerSourceStatus.InvalidCredentials } + : { status: MapLayerSourceStatus.RequireAuth }; } else if (json.error.code === ArcGisErrorCode.InvalidCredentials) - return { status: MapLayerSourceStatus.InvalidCredentials}; + return { status: MapLayerSourceStatus.InvalidCredentials }; } // Check this service support the expected queries let hasCapabilities = false; let capsArray: string[] = []; - if (json.capabilities && typeof json.capabilities === "string" ) { + if (json.capabilities && typeof json.capabilities === "string") { const capabilities: string = json.capabilities; capsArray = capabilities.split(",").map((entry) => entry.toLowerCase()); const filtered = capsArray.filter((element, _index, _array) => capabilitiesFilter.includes(element)); - hasCapabilities = (filtered.length === capabilitiesFilter.length); + hasCapabilities = filtered.length === capabilitiesFilter.length; } if (!hasCapabilities) { - return { status: MapLayerSourceStatus.InvalidFormat}; + return { status: MapLayerSourceStatus.InvalidFormat }; } // Only EPSG:3857 is supported with pre-rendered tiles. if (json.tileInfo && capsArray.includes("tilesonly") && !ArcGisUtilities.isEpsg3857Compatible(json.tileInfo)) { - return { status: MapLayerSourceStatus.InvalidCoordinateSystem}; + return { status: MapLayerSourceStatus.InvalidCoordinateSystem }; } let subLayers; if (json.layers) { - subLayers = new Array(); for (const layer of json.layers) { @@ -240,7 +265,7 @@ export class ArcGisUtilities { return zeroLod.level === 0 && Math.abs(zeroLod.resolution - 156543.03392800014) < .001; } - private static _serviceCache = new Map(); + private static _serviceCache = new Map(); /** * Fetches an ArcGIS service metadata, and returns its JSON representation. @@ -255,14 +280,14 @@ export class ArcGisUtilities { * @param requireToken Flag to indicate if a token is required */ - public static async getServiceJson(args: ArcGisGetServiceJsonArgs): Promise { - const {url, formatId, userName, password, queryParams, ignoreCache, requireToken} = args; + public static async getServiceJson(args: ArcGisGetServiceJsonArgs): Promise { + const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args; if (!ignoreCache) { const cached = ArcGisUtilities._serviceCache.get(url); if (cached !== undefined) return cached; } - const appendParams = (urlObj: URL, params?: {[key: string]: string}) => { + const appendParams = (urlObj: URL, params?: { [key: string]: string }) => { if (params) { Object.keys(params).forEach((paramKey) => { if (!urlObj.searchParams.has(paramKey)) @@ -287,36 +312,37 @@ export class ArcGisUtilities { const accessClient = IModelApp.mapLayerFormatRegistry.getAccessClient(formatId); if (accessClient) { accessTokenRequired = true; - await ArcGisUtilities.appendSecurityToken(tmpUrl, accessClient, {mapLayerUrl: new URL(url), userName, password}); + await ArcGisUtilities.appendSecurityToken(tmpUrl, accessClient, { mapLayerUrl: new URL(url), userName, password }); } } let response = await fetch(tmpUrl, { method: "GET" }); if (response.status === 401 && !requireToken && headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"])) { // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication) - response = await fetch(tmpUrl, {method: "GET", credentials: "include" }); + response = await fetch(tmpUrl, { method: "GET", credentials: "include" }); } // Append security token when corresponding error code is returned by ArcGIS service let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response); - if (!accessTokenRequired - && (errorCode === ArcGisErrorCode.TokenRequired || errorCode === ArcGisErrorCode.MissingPermissions) ) { + if ( + !accessTokenRequired + && (errorCode === ArcGisErrorCode.TokenRequired || errorCode === ArcGisErrorCode.MissingPermissions) + ) { accessTokenRequired = true; // If token required const accessClient = IModelApp.mapLayerFormatRegistry.getAccessClient(formatId); if (accessClient) { tmpUrl = createUrlObj(); - await ArcGisUtilities.appendSecurityToken(tmpUrl, accessClient, {mapLayerUrl: new URL(url), userName, password}); + await ArcGisUtilities.appendSecurityToken(tmpUrl, accessClient, { mapLayerUrl: new URL(url), userName, password }); response = await fetch(tmpUrl.toString(), { method: "GET" }); errorCode = await ArcGisUtilities.checkForResponseErrorCode(response); } } const json = await response.json(); - const info = {content: json, accessTokenRequired}; + const info = { content: json, accessTokenRequired }; // Cache the response only if it doesn't contain any error. - ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined)); - return info; // Always return json, even though it contains an error code. - + ArcGisUtilities._serviceCache.set(url, errorCode === undefined ? info : undefined); + return info; // Always return json, even though it contains an error code. } catch (_error) { ArcGisUtilities._serviceCache.set(url, undefined); return undefined; @@ -327,7 +353,6 @@ export class ArcGisUtilities { public static async checkForResponseErrorCode(response: Response) { const tmpResponse = response; if (response.headers && tmpResponse.headers.get("content-type")?.toLowerCase().includes("json")) { - try { // Note: // Since response stream can only be read once (i.e. calls to .json() method) @@ -337,17 +362,19 @@ export class ArcGisUtilities { const json = await clonedResponse.json(); if (json?.error?.code !== undefined) return json?.error?.code as number; - } catch { } - + } catch {} } return undefined; } // return the appended access token if available. - public static async appendSecurityToken(url: URL, accessClient: MapLayerAccessClient, accessTokenParams: MapLayerAccessTokenParams): Promise { - + public static async appendSecurityToken( + url: URL, + accessClient: MapLayerAccessClient, + accessTokenParams: MapLayerAccessTokenParams, + ): Promise { // Append security token if available - let accessToken: MapLayerAccessToken|undefined; + let accessToken: MapLayerAccessToken | undefined; try { accessToken = await accessClient.getAccessToken(accessTokenParams); } catch {} @@ -371,21 +398,27 @@ export class ArcGisUtilities { * @param screenDpi Monitor resolution in dots per inch (i.e. typically 96dpi is used by Google Maps) * @returns An array containing resolution and scale values for each requested zoom level */ - public static computeZoomLevelsScales(startZoom: number = 0, endZoom: number = 20, latitude: number = 0, tileSize: number = 256, screenDpi = 96): {zoom: number, resolution: number, scale: number}[] { + public static computeZoomLevelsScales( + startZoom: number = 0, + endZoom: number = 20, + latitude: number = 0, + tileSize: number = 256, + screenDpi = 96, + ): { zoom: number, resolution: number, scale: number }[] { // Note: There is probably a more direct way to compute this, but I prefer to go for a simple and well documented approach. - if (startZoom <0 || endZoom < startZoom || tileSize < 0 || screenDpi < 1 || latitude < -90 || latitude > 90) + if (startZoom < 0 || endZoom < startZoom || tileSize < 0 || screenDpi < 1 || latitude < -90 || latitude > 90) return []; const inchPerMeter = 1 / 0.0254; - const results: {zoom: number, resolution: number, scale: number}[] = []; - const equatorLength = Constant.earthRadiusWGS84.equator * 2 * Math.PI; + const results: { zoom: number, resolution: number, scale: number }[] = []; + const equatorLength = Constant.earthRadiusWGS84.equator * 2 * Math.PI; const zoom0Resolution = equatorLength / tileSize; // in meters per pixel const cosLatitude = Math.cos(latitude); - for (let zoom = startZoom; zoom<= endZoom; zoom++) { + for (let zoom = startZoom; zoom <= endZoom; zoom++) { const resolution = zoom0Resolution * cosLatitude / Math.pow(2, zoom); - const scale = screenDpi * inchPerMeter * resolution; - results.push({zoom, resolution, scale}); + const scale = screenDpi * inchPerMeter * resolution; + results.push({ zoom, resolution, scale }); } return results; @@ -399,30 +432,34 @@ export class ArcGisUtilities { * @param maxScale Maximum scale value that needs to be matched to a LOD level * @returns minLod: LOD value matching minScale, maxLod: LOD value matching maxScale */ - public static getZoomLevelsScales( defaultMaxLod: number, tileSize: number, minScale?: number, maxScale?: number, tolerance: number = 0): {minLod?: number, maxLod?: number} { + public static getZoomLevelsScales( + defaultMaxLod: number, + tileSize: number, + minScale?: number, + maxScale?: number, + tolerance: number = 0, + ): { minLod?: number, maxLod?: number } { + let minLod: number | undefined, maxLod: number | undefined; - let minLod: number|undefined, maxLod: number|undefined; - - const zoomScales = ArcGisUtilities.computeZoomLevelsScales(0, defaultMaxLod, 0 /* latitude 0 = Equator*/, tileSize); + const zoomScales = ArcGisUtilities.computeZoomLevelsScales(0, defaultMaxLod, 0, /* latitude 0 = Equator*/ tileSize); if (zoomScales.length > 0) { - if (minScale) { minLod = 0; // We are looking for the largest scale value with a scale value smaller than minScale - for (; minLod < zoomScales.length && (zoomScales[minLod].scale > minScale && Math.abs(zoomScales[minLod].scale - minScale) > tolerance); minLod++) + for ( ; - + minLod < zoomScales.length && (zoomScales[minLod].scale > minScale && Math.abs(zoomScales[minLod].scale - minScale) > tolerance); + minLod++ + ); } if (maxScale) { maxLod = defaultMaxLod; // We are looking for the smallest scale value with a value greater than maxScale - for (; maxLod >= 0 && zoomScales[maxLod].scale < maxScale && Math.abs(zoomScales[maxLod].scale - maxScale) > tolerance; maxLod--) - ; + for (; maxLod >= 0 && zoomScales[maxLod].scale < maxScale && Math.abs(zoomScales[maxLod].scale - maxScale) > tolerance; maxLod--); } } - return {minLod, maxLod}; + return { minLod, maxLod }; } - } diff --git a/core/frontend/src/tile/map/BingElevation.ts b/core/frontend/src/tile/map/BingElevation.ts index 60dc4614cea9..eda67c25ecd0 100644 --- a/core/frontend/src/tile/map/BingElevation.ts +++ b/core/frontend/src/tile/map/BingElevation.ts @@ -6,11 +6,11 @@ /** @packageDocumentation * @module Tiles */ -import { request } from "../../request/Request"; -import { IModelApp } from "../../IModelApp"; -import { IModelConnection } from "../../IModelConnection"; import { Cartographic } from "@itwin/core-common"; import { Point3d, Range1d, Range2d } from "@itwin/core-geometry"; +import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; +import { request } from "../../request/Request"; // cspell:ignore atae qdng uyzv auje sealevel @@ -34,12 +34,10 @@ export class BingElevationProvider { this._heightRangeRequestTemplate = "https://dev.virtualearth.net/REST/v1/Elevation/Bounds?bounds={boundingBox}&rows=16&cols=16&heights=ellipsoid&key={BingMapsAPIKey}" .replace("{BingMapsAPIKey}", bingKey); - this._seaLevelOffsetRequestTemplate = - "https://dev.virtualearth.net/REST/v1/Elevation/SeaLevel?points={points}&key={BingMapsAPIKey}" - .replace("{BingMapsAPIKey}", bingKey); - this._heightListRequestTemplate = - "https://dev.virtualearth.net/REST/v1/Elevation/List?points={points}&heights={heights}&key={BingMapsAPIKey}" - .replace("{BingMapsAPIKey}", bingKey); + this._seaLevelOffsetRequestTemplate = "https://dev.virtualearth.net/REST/v1/Elevation/SeaLevel?points={points}&key={BingMapsAPIKey}" + .replace("{BingMapsAPIKey}", bingKey); + this._heightListRequestTemplate = "https://dev.virtualearth.net/REST/v1/Elevation/List?points={points}&heights={heights}&key={BingMapsAPIKey}" + .replace("{BingMapsAPIKey}", bingKey); } /** Return the height (altitude) at a given cartographic location. @@ -50,10 +48,9 @@ export class BingElevationProvider { if (undefined === carto) return 0.0; - const requestUrl = - this._heightListRequestTemplate - .replace("{points}", `${carto.latitudeDegrees},${carto.longitudeDegrees}`) - .replace("{heights}", geodetic ? "ellipsoid" : "sealevel"); + const requestUrl = this._heightListRequestTemplate + .replace("{points}", `${carto.latitudeDegrees},${carto.longitudeDegrees}`) + .replace("{heights}", geodetic ? "ellipsoid" : "sealevel"); try { const tileResponseBody = await request(requestUrl, "json"); diff --git a/core/frontend/src/tile/map/CesiumTerrainProvider.ts b/core/frontend/src/tile/map/CesiumTerrainProvider.ts index 489dc0d5f90d..fe4572dad441 100644 --- a/core/frontend/src/tile/map/CesiumTerrainProvider.ts +++ b/core/frontend/src/tile/map/CesiumTerrainProvider.ts @@ -6,17 +6,25 @@ /** @packageDocumentation * @module Tiles */ +import { MessageSeverity } from "@itwin/appui-abstract"; import { assert, BeDuration, BeTimePoint, ByteStream, JsonUtils, utf8ToString } from "@itwin/core-bentley"; -import { Point2d, Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { CesiumTerrainAssetId, nextPoint3d64FromByteStream, OctEncodedNormal, QPoint2d } from "@itwin/core-common"; -import { MessageSeverity } from "@itwin/appui-abstract"; -import { request, RequestOptions } from "../../request/Request"; +import { Point2d, Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; import { IModelApp } from "../../IModelApp"; import { RealityMeshParams, RealityMeshParamsBuilder } from "../../render/RealityMeshParams"; +import { request, RequestOptions } from "../../request/Request"; import { - GeographicTilingScheme, MapTile, MapTilingScheme, QuadId, ReadMeshArgs, RequestMeshDataArgs, TerrainMeshProvider, - TerrainMeshProviderOptions, Tile, TileAvailability, + GeographicTilingScheme, + MapTile, + MapTilingScheme, + QuadId, + ReadMeshArgs, + RequestMeshDataArgs, + TerrainMeshProvider, + TerrainMeshProviderOptions, + Tile, + TileAvailability, } from "../internal"; /** @internal */ @@ -74,7 +82,11 @@ function notifyTerrainError(detailedDescription?: string): void { return; notifiedTerrainError = true; - IModelApp.notifications.displayMessage(MessageSeverity.Information, IModelApp.localization.getLocalizedString(`iModelJs:BackgroundMap.CannotObtainTerrain`), detailedDescription); + IModelApp.notifications.displayMessage( + MessageSeverity.Information, + IModelApp.localization.getLocalizedString(`iModelJs:BackgroundMap.CannotObtainTerrain`), + detailedDescription, + ); } /** @internal */ @@ -126,7 +138,15 @@ export async function getCesiumTerrainProvider(opts: TerrainMeshProviderOptions) const maxDepth = JsonUtils.asInt(layers.maxzoom, 19); // TBD -- When we have an API extract the heights for the project from the terrain tiles - for use temporary Bing elevation. - return new CesiumTerrainProvider(opts, accessTokenAndEndpointUrl.token, tileUrlTemplate, maxDepth, tilingScheme, tileAvailability, layers.metadataAvailability); + return new CesiumTerrainProvider( + opts, + accessTokenAndEndpointUrl.token, + tileUrlTemplate, + maxDepth, + tilingScheme, + tileAvailability, + layers.metadataAvailability, + ); } function zigZagDecode(value: number) { @@ -173,7 +193,7 @@ class CesiumTerrainProvider extends TerrainMeshProvider { private static _scratchPoint = Point3d.createZero(); private static _scratchNormal = Vector3d.createZero(); private static _scratchHeightRange = Range1d.createNull(); - private static _tokenTimeoutInterval = BeDuration.fromSeconds(60 * 30); // Request a new access token every 30 minutes... + private static _tokenTimeoutInterval = BeDuration.fromSeconds(60 * 30); // Request a new access token every 30 minutes... private _tokenTimeOut: BeTimePoint; public override forceTileLoad(tile: Tile): boolean { @@ -182,8 +202,15 @@ class CesiumTerrainProvider extends TerrainMeshProvider { return undefined !== this._metaDataAvailableLevel && mapTile.quadId.level === this._metaDataAvailableLevel && !mapTile.everLoaded; } - constructor(opts: TerrainMeshProviderOptions, accessToken: string, tileUrlTemplate: string, maxDepth: number, tilingScheme: MapTilingScheme, - tileAvailability: TileAvailability | undefined, metaDataAvailableLevel: number | undefined) { + constructor( + opts: TerrainMeshProviderOptions, + accessToken: string, + tileUrlTemplate: string, + maxDepth: number, + tilingScheme: MapTilingScheme, + tileAvailability: TileAvailability | undefined, + metaDataAvailableLevel: number | undefined, + ) { super(); this._wantSkirts = opts.wantSkirts; this._exaggeration = opts.exaggeration; @@ -212,8 +239,12 @@ class CesiumTerrainProvider extends TerrainMeshProvider { cards.appendChild(card); } - public get maxDepth(): number { return this._maxDepth; } - public get tilingScheme(): MapTilingScheme { return this._tilingScheme; } + public get maxDepth(): number { + return this._maxDepth; + } + public get tilingScheme(): MapTilingScheme { + return this._tilingScheme; + } public override isTileAvailable(quadId: QuadId) { if (quadId.level > this.maxDepth) @@ -261,7 +292,7 @@ class CesiumTerrainProvider extends TerrainMeshProvider { const streamBuffer = ByteStream.fromUint8Array(blob); const center = nextPoint3d64FromByteStream(streamBuffer); const quadId = QuadId.createFromContentId(tile.contentId); - const skirtHeight = this.getLevelMaximumGeometricError(quadId.level + 1) * 10.0; // Add 1 to level to restore height calculation to before the quadId level was from root. (4326 unification) + const skirtHeight = this.getLevelMaximumGeometricError(quadId.level + 1) * 10.0; // Add 1 to level to restore height calculation to before the quadId level was from root. (4326 unification) const minHeight = this._exaggeration * streamBuffer.readFloat32(); const maxHeight = this._exaggeration * streamBuffer.readFloat32(); const boundCenter = nextPoint3d64FromByteStream(streamBuffer); @@ -271,7 +302,7 @@ class CesiumTerrainProvider extends TerrainMeshProvider { terrainTile.adjustHeights(minHeight, maxHeight); - if (undefined === center || undefined === boundCenter || undefined === boundRadius || undefined === horizonOcclusion) { } + if (undefined === center || undefined === boundCenter || undefined === boundRadius || undefined === horizonOcclusion) {} const pointCount = streamBuffer.readUint32(); const encodedVertexBuffer = new Uint16Array(blob.buffer, streamBuffer.curPos, pointCount * 3); streamBuffer.advance(pointCount * 6); @@ -352,7 +383,7 @@ class CesiumTerrainProvider extends TerrainMeshProvider { if (undefined !== metaData.available && undefined !== this._tileAvailability) { const availableTiles = metaData.available; for (let offset = 0; offset < availableTiles.length; ++offset) { - const availableLevel = tile.depth + offset; // Our depth is includes root (1 + cesium Depth) + const availableLevel = tile.depth + offset; // Our depth is includes root (1 + cesium Depth) const rangesAtLevel = availableTiles[offset]; for (const range of rangesAtLevel) @@ -372,8 +403,9 @@ class CesiumTerrainProvider extends TerrainMeshProvider { let initialIndexCapacity = indexCount; let initialVertexCapacity = pointCount; if (this._wantSkirts) { - initialIndexCapacity += 6 * (Math.max(0, northCount - 1) + Math.max(0, southCount - 1) + Math.max(0, eastCount - 1) + Math.max(0, westCount - 1)); - initialVertexCapacity += (northCount + southCount + eastCount + westCount); + initialIndexCapacity += 6 * + (Math.max(0, northCount - 1) + Math.max(0, southCount - 1) + Math.max(0, eastCount - 1) + Math.max(0, westCount - 1)); + initialVertexCapacity += northCount + southCount + eastCount + westCount; } const wantNormals = undefined !== encodedNormalsBuffer; diff --git a/core/frontend/src/tile/map/EllipsoidTerrainProvider.ts b/core/frontend/src/tile/map/EllipsoidTerrainProvider.ts index 5b7ee11fe8eb..105f809cc21e 100644 --- a/core/frontend/src/tile/map/EllipsoidTerrainProvider.ts +++ b/core/frontend/src/tile/map/EllipsoidTerrainProvider.ts @@ -10,7 +10,15 @@ import { assert } from "@itwin/core-bentley"; import { Angle, Ellipsoid, EllipsoidPatch, Point2d, Point3d, Range1d, Range3d, Transform } from "@itwin/core-geometry"; import { RealityMeshParams, RealityMeshParamsBuilder } from "../../render/RealityMeshParams"; import { - MapCartoRectangle, MapTile, MapTilingScheme, QuadId, ReadMeshArgs, TerrainMeshProvider, TerrainMeshProviderOptions, TileRequest, WebMercatorTilingScheme, + MapCartoRectangle, + MapTile, + MapTilingScheme, + QuadId, + ReadMeshArgs, + TerrainMeshProvider, + TerrainMeshProviderOptions, + TileRequest, + WebMercatorTilingScheme, } from "../internal"; const scratchPoint2d = Point2d.createZero(); @@ -37,7 +45,9 @@ export class EllipsoidTerrainProvider extends TerrainMeshProvider { } /** Implements [[TerrainMeshProvider.maxDepth]] to return a fixed maximum depth of 22. */ - public get maxDepth(): number { return 22; } + public get maxDepth(): number { + return 22; + } /** Implements [[TerrainMeshProvider.getChildHeightRange]] to return an empty range, because the ellipsoid is smooth. */ public override getChildHeightRange(_quadId: QuadId, _rectangle: MapCartoRectangle, _parent: MapTile): Range1d | undefined { @@ -64,7 +74,6 @@ export class EllipsoidTerrainProvider extends TerrainMeshProvider { Point2d.create(u, 1 - v, uv); builder.addUnquantizedVertex(projection.getPoint(u, v, 0, pos), uv); } - } builder.addQuad(0, 1, 2, 3); @@ -97,7 +106,7 @@ export class EllipsoidTerrainProvider extends TerrainMeshProvider { builder.addUnquantizedVertex(positions[i], uvs[i]); builder.addQuad(0, 2, 4, 6); - const reorder = [0, 2, 6, 4, 0]; + const reorder = [0, 2, 6, 4, 0]; for (let i = 0; i < 4; i++) { const iThis = reorder[i], iNext = reorder[i + 1]; builder.addQuad(iThis, iNext, iThis + 1, iNext + 1); diff --git a/core/frontend/src/tile/map/ImageryProviders/ArcGISImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/ArcGISImageryProvider.ts index e1d357d606f2..377f36e6c1fc 100644 --- a/core/frontend/src/tile/map/ImageryProviders/ArcGISImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/ArcGISImageryProvider.ts @@ -7,10 +7,18 @@ */ import { ImageMapLayerSettings } from "@itwin/core-common"; -import { ArcGisErrorCode, ArcGISServiceMetadata, ArcGisUtilities, MapLayerAccessClient, MapLayerAccessToken, MapLayerImageryProvider, MapLayerImageryProviderStatus } from "../../internal"; import { IModelApp } from "../../../IModelApp"; import { NotifyMessageDetails, OutputMessagePriority } from "../../../NotificationManager"; import { headersIncludeAuthMethod } from "../../../request/utils"; +import { + ArcGisErrorCode, + ArcGISServiceMetadata, + ArcGisUtilities, + MapLayerAccessClient, + MapLayerAccessToken, + MapLayerImageryProvider, + MapLayerImageryProviderStatus, +} from "../../internal"; /** Base class for ArcGIS map-layer imagery providers. * @@ -20,18 +28,19 @@ import { headersIncludeAuthMethod } from "../../../request/utils"; * @internal */ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { - - protected _accessClient: MapLayerAccessClient|undefined; - protected _lastAccessToken: MapLayerAccessToken|undefined; + protected _accessClient: MapLayerAccessClient | undefined; + protected _lastAccessToken: MapLayerAccessToken | undefined; /** Flag indicating if access token should be added to request. - * @note We assume a service to require access token for the entire viewing session. - */ + * @note We assume a service to require access token for the entire viewing session. + */ protected _accessTokenRequired = false; protected _querySupported = false; - public override get supportsMapFeatureInfo() { return this._querySupported;} + public override get supportsMapFeatureInfo() { + return this._querySupported; + } constructor(settings: ImageMapLayerSettings, usesCachedTiles: boolean) { super(settings, usesCachedTiles); @@ -40,10 +49,9 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { /** Updates the accessClient token state whenever the status of the provider change. * @internal - * */ + */ protected override onStatusUpdated(status: MapLayerImageryProviderStatus) { if (status === MapLayerImageryProviderStatus.RequireAuth) { - // Invalidate the token, so a new one get generated if (this._accessClient?.invalidateToken !== undefined && this._lastAccessToken !== undefined) { this._accessClient.invalidateToken(this._lastAccessToken); @@ -57,12 +65,17 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { /** * Fetch an ArcGIS service metadata, and returns its JSON representation. * This wrapper maintains token state and should be used instead of the the ArcGisUtilities version. - */ + */ protected async getServiceJson() { - let metadata: ArcGISServiceMetadata|undefined; + let metadata: ArcGISServiceMetadata | undefined; try { - metadata = await ArcGisUtilities.getServiceJson({url: this._settings.url, formatId: this._settings.formatId, userName: this._settings.userName, password: this._settings.password, queryParams: this._settings.collectQueryParams()}); - + metadata = await ArcGisUtilities.getServiceJson({ + url: this._settings.url, + formatId: this._settings.formatId, + userName: this._settings.userName, + password: this._settings.password, + queryParams: this._settings.collectQueryParams(), + }); } catch (_e) { } if (metadata && metadata.accessTokenRequired) { @@ -70,7 +83,7 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { if (accessClient) { try { // Keep track of last used access token, so we can invalidate it later when an errors occurs - const accessToken = await accessClient.getAccessToken({mapLayerUrl: new URL(this._settings.url)}); + const accessToken = await accessClient.getAccessToken({ mapLayerUrl: new URL(this._settings.url) }); this._lastAccessToken = accessToken; } catch { } @@ -88,7 +101,6 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { * Refer to fetch API for more details (https://developer.mozilla.org/en-US/docs/Web/API/fetch) */ protected async fetch(url: URL, options?: RequestInit) { - let errorCode: number | undefined; const urlObj = new URL(url); const queryParams = this._settings.collectQueryParams(); @@ -101,51 +113,54 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { this._lastAccessToken = await ArcGisUtilities.appendSecurityToken(urlObj, this._accessClient, { mapLayerUrl: new URL(this._settings.url), userName: this._settings.userName, - password: this._settings.password }); + password: this._settings.password, + }); } // We want to complete the first request before letting other requests go; // this done to avoid flooding server with requests missing credentials if (!this._firstRequestPromise) - this._firstRequestPromise = new Promise((resolve: any) => this.onFirstRequestCompleted.addOnce(()=>resolve())); + this._firstRequestPromise = new Promise((resolve: any) => this.onFirstRequestCompleted.addOnce(() => resolve())); else await this._firstRequestPromise; - let response: Response|undefined; + let response: Response | undefined; try { - response = await fetch(urlObj, {...options, credentials: this._includeUserCredentials ? "include" : undefined}); + response = await fetch(urlObj, { ...options, credentials: this._includeUserCredentials ? "include" : undefined }); if (response.status === 401 && !this._lastAccessToken && headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"])) { - // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication) - response = await fetch(urlObj, {...options, credentials: "include" }); + // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication) + response = await fetch(urlObj, { ...options, credentials: "include" }); if (response.status === 200) { - this._includeUserCredentials = true; // avoid going through 401 challenges over and over + this._includeUserCredentials = true; // avoid going through 401 challenges over and over } } - if ((this._lastAccessToken && response.status === 400) - || response.headers.get("content-type")?.toLowerCase().includes("htm")) { - // For some reasons when we make a request with the fetch() api and there is a token error - // we receive a status 400 instead of proper json response. (i.e doing the same request in the browser gives a different response) - // For some other request, we also seen error message in html. - // When it occurs, we fall back to root service request so we get a proper JSON response with error code. + if ( + (this._lastAccessToken && response.status === 400) + || response.headers.get("content-type")?.toLowerCase().includes("htm") + ) { + // For some reasons when we make a request with the fetch() api and there is a token error + // we receive a status 400 instead of proper json response. (i.e doing the same request in the browser gives a different response) + // For some other request, we also seen error message in html. + // When it occurs, we fall back to root service request so we get a proper JSON response with error code. const tmpUrl = new URL(this._settings.url); if (this._lastAccessToken && this._accessTokenRequired) tmpUrl.searchParams.append("token", this._lastAccessToken.token); - tmpUrl.searchParams.append("f","json"); - response = await fetch(tmpUrl.toString(), options); + tmpUrl.searchParams.append("f", "json"); + response = await fetch(tmpUrl.toString(), options); } errorCode = await ArcGisUtilities.checkForResponseErrorCode(response); - if (errorCode !== undefined && - ( errorCode === ArcGisErrorCode.TokenRequired - || errorCode === ArcGisErrorCode.InvalidToken - || errorCode === ArcGisErrorCode.MissingPermissions - ) ) { - - if (this._settings.userName && this._settings.userName.length > 0 && this._lastAccessToken ) { - // **** Legacy token ONLY *** + if ( + errorCode !== undefined && + (errorCode === ArcGisErrorCode.TokenRequired + || errorCode === ArcGisErrorCode.InvalidToken + || errorCode === ArcGisErrorCode.MissingPermissions) + ) { + if (this._settings.userName && this._settings.userName.length > 0 && this._lastAccessToken) { + // **** Legacy token ONLY *** // Token might have expired, make a second attempt by forcing new token. if (this._accessClient?.invalidateToken !== undefined && this._lastAccessToken !== undefined) @@ -154,28 +169,35 @@ export abstract class ArcGISImageryProvider extends MapLayerImageryProvider { const urlObj2 = new URL(url); if (this._accessClient) { try { - this._lastAccessToken = await ArcGisUtilities.appendSecurityToken(urlObj, this._accessClient, {mapLayerUrl: urlObj, userName: this._settings.userName, password: this._settings.password }); + this._lastAccessToken = await ArcGisUtilities.appendSecurityToken(urlObj, this._accessClient, { + mapLayerUrl: urlObj, + userName: this._settings.userName, + password: this._settings.password, + }); } catch { } } // Make a second attempt with refreshed token response = await fetch(urlObj2.toString(), options); - errorCode = await ArcGisUtilities.checkForResponseErrorCode(response); + errorCode = await ArcGisUtilities.checkForResponseErrorCode(response); } - if (errorCode !== undefined && - ( errorCode === ArcGisErrorCode.TokenRequired - || errorCode === ArcGisErrorCode.InvalidToken - || errorCode === ArcGisErrorCode.MissingPermissions - ) ) { + if ( + errorCode !== undefined && + (errorCode === ArcGisErrorCode.TokenRequired + || errorCode === ArcGisErrorCode.InvalidToken + || errorCode === ArcGisErrorCode.MissingPermissions) + ) { // Looks like the initially generated token has expired. - if (this.status === MapLayerImageryProviderStatus.Valid ) { + if (this.status === MapLayerImageryProviderStatus.Valid) { // Only report new status change to avoid spamming the UI this.setStatus(MapLayerImageryProviderStatus.RequireAuth); this.onStatusChanged.raiseEvent(this); - const msg = IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Messages.FetchTooltipTokenError", { layerName: this._settings.name }); + const msg = IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Messages.FetchTooltipTokenError", { + layerName: this._settings.name, + }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Warning, msg)); } } diff --git a/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts index 8a666946dd17..b1ff9096ec0a 100644 --- a/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/ArcGISMapLayerImageryProvider.ts @@ -5,19 +5,30 @@ /** @packageDocumentation * @module Tiles */ +import { PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; +import { Logger } from "@itwin/core-bentley"; import { Cartographic, ImageMapLayerSettings, ImageSource, IModelStatus, ServerError } from "@itwin/core-common"; +import { Point2d, Range2d, Range2dProps, XYProps } from "@itwin/core-geometry"; +import { HitDetail } from "../../../HitDetail"; import { IModelApp } from "../../../IModelApp"; import { - ArcGisErrorCode, ArcGisGeometryReaderJSON, ArcGISImageryProvider, ArcGISTileMap, ArcGisUtilities, - FeatureGraphicsRenderer, ImageryMapTileTree, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeature, - MapLayerFeatureInfo, MapLayerImageryProviderStatus, MapSubLayerFeatureInfo, QuadId, + ArcGisErrorCode, + ArcGisGeometryReaderJSON, + ArcGISImageryProvider, + ArcGISTileMap, + ArcGisUtilities, + FeatureGraphicsRenderer, + ImageryMapTileTree, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeature, + MapLayerFeatureInfo, + MapLayerImageryProviderStatus, + MapSubLayerFeatureInfo, + QuadId, } from "../../internal"; -import { PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; -import { Point2d, Range2d, Range2dProps, XYProps } from "@itwin/core-geometry"; -import { Logger } from "@itwin/core-bentley"; -import { HitDetail } from "../../../HitDetail"; -const loggerCategory = "MapLayerImageryProvider.ArcGISMapLayerImageryProvider"; +const loggerCategory = "MapLayerImageryProvider.ArcGISMapLayerImageryProvider"; /** @internal */ export interface ArcGISIdentifyImageDisplayProps { @@ -28,7 +39,7 @@ export interface ArcGISIdentifyImageDisplayProps { /** @internal */ export interface ArcGISIdentifyLayersProps { - prefix: "top"|"visible"|"all"; + prefix: "top" | "visible" | "all"; layerIds?: string[]; } @@ -45,7 +56,7 @@ export interface ArcGISIdentifyRequestUrlProps { /** The layers to perform the identify operation on. The default value is top. * Format: [top | visible | all]:layerId1,layerId2 - */ + */ layers?: ArcGISIdentifyLayersProps; /** The distance in screen pixels from the specified geometry within which the identify operation should be performed. @@ -54,7 +65,7 @@ export interface ArcGISIdentifyRequestUrlProps { tolerance: number; /** The extent or bounding box of the map currently being viewed. - * Format: , , , + * Format: , , , */ mapExtent: Range2dProps; @@ -74,14 +85,12 @@ export interface ArcGISIdentifyRequestUrlProps { /** The response format. The default response format is html. */ - f?: "json"|"html"; - + f?: "json" | "html"; } /** @internal */ export class ArcGISIdentifyRequestUrl { - public static fromJSON(baseUrl: URL|string, json: ArcGISIdentifyRequestUrlProps, srFractionDigits?: number): URL { - + public static fromJSON(baseUrl: URL | string, json: ArcGISIdentifyRequestUrlProps, srFractionDigits?: number): URL { const newUrl = new URL(baseUrl); newUrl.pathname = `${newUrl.pathname}/identify`; @@ -138,7 +147,7 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { private _tileMapSupported = false; private _mapSupported = false; private _tilesOnly = false; - private _tileMap: ArcGISTileMap|undefined; + private _tileMap: ArcGISTileMap | undefined; public serviceJson: any; constructor(settings: ImageMapLayerSettings) { @@ -146,14 +155,19 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { this._accessClient = IModelApp.mapLayerFormatRegistry.getAccessClient(settings.formatId); } - protected override get _filterByCartoRange() { return false; } // Can't trust footprint ranges (USGS Hydro) + protected override get _filterByCartoRange() { + return false; + } // Can't trust footprint ranges (USGS Hydro) - public override get minimumZoomLevel() { return Math.max(super.minimumZoomLevel, this._minDepthFromLod); } - public override get maximumZoomLevel() { return this._maxDepthFromLod > 0 ? this._maxDepthFromLod : super.maximumZoomLevel; } + public override get minimumZoomLevel() { + return Math.max(super.minimumZoomLevel, this._minDepthFromLod); + } + public override get maximumZoomLevel() { + return this._maxDepthFromLod > 0 ? this._maxDepthFromLod : super.maximumZoomLevel; + } public uintToString(uintArray: any) { return Buffer.from(uintArray).toJSON(); - } private async fetchTile(row: number, column: number, zoomLevel: number) { @@ -185,7 +199,7 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { protected override _generateChildIds(quadId: QuadId, resolveChildren: (childIds: QuadId[]) => void) { const childIds = this.getPotentialChildIds(quadId); - if (quadId.level < Math.max(1, this.minimumZoomLevel-1)) { + if (quadId.level < Math.max(1, this.minimumZoomLevel - 1)) { resolveChildren(childIds); return; } @@ -198,7 +212,7 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { if (availability[i]) availableChildIds.push(childIds[i]); - resolveChildren (availableChildIds); + resolveChildren(availableChildIds); }); } else if (this._usesCachedTiles && this.cartoRange) { // Filter children by range @@ -207,33 +221,38 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { for (let i = 0; i < childIds.length; i++) { const childExtent = this.getEPSG4326Extent(childIds[i].row, childIds[i].column, childIds[i].level); - const childRange = MapCartoRectangle.fromDegrees(childExtent.longitudeLeft, childExtent.latitudeBottom, childExtent.longitudeRight, childExtent.latitudeTop); + const childRange = MapCartoRectangle.fromDegrees( + childExtent.longitudeLeft, + childExtent.latitudeBottom, + childExtent.longitudeRight, + childExtent.latitudeTop, + ); if (childRange.intersectsRange(this.cartoRange)) { availableChildIds.push(childIds[i]); } } - resolveChildren (availableChildIds); + resolveChildren(availableChildIds); } else { - resolveChildren (childIds); // Resolve all children + resolveChildren(childIds); // Resolve all children } } public override async initialize(): Promise { - const metadata = await this.getServiceJson(); if (metadata?.content === undefined) throw new ServerError(IModelStatus.ValidationFailed, ""); const json = metadata.content; - if (json?.error?.code === ArcGisErrorCode.TokenRequired + if ( + json?.error?.code === ArcGisErrorCode.TokenRequired || json?.error?.code === ArcGisErrorCode.InvalidToken || json?.error?.code === ArcGisErrorCode.MissingPermissions ) { // Check again layer status, it might have change during await. if (this.status === MapLayerImageryProviderStatus.Valid) { this.setStatus(MapLayerImageryProviderStatus.RequireAuth); - return; // By returning (i.e not throwing), we ensure the tileTree get created and current provider is preserved to report status. + return; // By returning (i.e not throwing), we ensure the tileTree get created and current provider is preserved to report status. } } @@ -267,8 +286,11 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { if (this._usesCachedTiles) { // Read max LOD if (json.maxScale !== undefined && json.maxScale !== 0 && Array.isArray(json.tileInfo.lods)) { - for (; this._maxDepthFromLod < json.tileInfo.lods.length && json.tileInfo.lods[this._maxDepthFromLod].scale > json.maxScale; this._maxDepthFromLod++) + for ( ; + this._maxDepthFromLod < json.tileInfo.lods.length && json.tileInfo.lods[this._maxDepthFromLod].scale > json.maxScale; + this._maxDepthFromLod++ + ); } // Create tile map object only if we are going to request tiles from this server and it support tilemap requests. @@ -284,8 +306,9 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { if (json.fullExtent) { if (json.fullExtent.spatialReference.latestWkid === 3857 || json.fullExtent.spatialReference.wkid === 102100) { const range3857 = Range2d.createFrom({ - low: {x: json.fullExtent.xmin, y: json.fullExtent.ymin}, - high: {x: json.fullExtent.xmax, y: json.fullExtent.ymax} }); + low: { x: json.fullExtent.xmin, y: json.fullExtent.ymin }, + high: { x: json.fullExtent.xmax, y: json.fullExtent.ymax }, + }); const west = this.getEPSG4326Lon(range3857.xLow); const south = this.getEPSG4326Lat(range3857.yLow); @@ -313,7 +336,6 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { } } } - } public override addLogoCards(cards: HTMLTableElement): void { @@ -325,8 +347,13 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { // Translates the provided Cartographic into a EPSG:3857 point, and retrieve information. // tolerance is in pixels - private async getIdentifyData(quadId: QuadId, carto: Cartographic, tolerance: number, returnGeometry?: boolean, maxAllowableOffset?: number): Promise { - + private async getIdentifyData( + quadId: QuadId, + carto: Cartographic, + tolerance: number, + returnGeometry?: boolean, + maxAllowableOffset?: number, + ): Promise { const bbox = this.getEPSG3857Extent(quadId.row, quadId.column, quadId.level); const layerIds = new Array(); this._settings.subLayers.forEach((subLayer) => { @@ -335,17 +362,18 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { }); const urlObj = ArcGISIdentifyRequestUrl.fromJSON(this._settings.url, { f: "json", - geometry: {x: this.getEPSG3857X(carto.longitudeDegrees), y: this.getEPSG3857Y(carto.latitudeDegrees)}, + geometry: { x: this.getEPSG3857X(carto.longitudeDegrees), y: this.getEPSG3857Y(carto.latitudeDegrees) }, geometryType: "esriGeometryPoint", tolerance, - mapExtent: {low: {x: bbox.left, y: bbox.bottom}, high: {x: bbox.right, y: bbox.top}}, + mapExtent: { low: { x: bbox.left, y: bbox.bottom }, high: { x: bbox.right, y: bbox.top } }, sr: 3857, - imageDisplay: {width: this.tileSize, height: this.tileSize, dpi: 96}, - layers: {prefix: "top", layerIds}, + imageDisplay: { width: this.tileSize, height: this.tileSize, dpi: 96 }, + layers: { prefix: "top", layerIds }, returnGeometry, - maxAllowableOffset}, 3 /* 1mm accuracy*/); + maxAllowableOffset, + }, 3 /* 1mm accuracy*/); - const response = await this.fetch(urlObj, { method: "GET" } ); + const response = await this.fetch(urlObj, { method: "GET" }); return response.json(); } @@ -373,29 +401,35 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { } // Makes an identify request to ESRI MapService , and return it as a list MapLayerFeatureInfo object - public override async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree, hit: HitDetail, options?: MapFeatureInfoOptions): Promise { + public override async getFeatureInfo( + featureInfos: MapLayerFeatureInfo[], + quadId: QuadId, + carto: Cartographic, + _tree: ImageryMapTileTree, + hit: HitDetail, + options?: MapFeatureInfoOptions, + ): Promise { if (!this._querySupported) return; const tileExtent = this.getEPSG3857Extent(quadId.row, quadId.column, quadId.level); const toleranceWorld = (tileExtent.top - tileExtent.bottom) / this.tileSize; const maxAllowableOffsetFactor = 2; - const maxAllowableOffset = maxAllowableOffsetFactor*toleranceWorld; + const maxAllowableOffset = maxAllowableOffsetFactor * toleranceWorld; const tolerancePixel = options?.tolerance ?? 7; const json = await this.getIdentifyData(quadId, carto, tolerancePixel, true, maxAllowableOffset); if (json && Array.isArray(json.results)) { - const renderer = new FeatureGraphicsRenderer({viewport: hit.viewport, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: hit.viewport, crs: "webMercator" }); const layerInfo: MapLayerFeatureInfo = { layerName: this._settings.name, subLayerInfos: [] }; // The 'identify' service returns us a flat/unordered list of records.. // results may represent features for the a common subLayer. // For simplicity, we group together features for a given sub-layer. - const subLayers = new Map (); + const subLayers = new Map(); for (const result of json.results) { - let subLayerInfo = subLayers.get(result.layerName); if (!subLayerInfo) { subLayerInfo = { @@ -405,7 +439,7 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { }; subLayers.set(result.layerName, subLayerInfo); } - const feature: MapLayerFeature = {geometries: [], attributes: []}; + const feature: MapLayerFeature = { geometries: [], attributes: [] }; // Read all feature attributes for (const [key, value] of Object.entries(result.attributes)) { @@ -422,13 +456,12 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { await geomReader.readGeometry(result.geometry); const graphics = renderer.moveGraphics(); feature.geometries = graphics.map((graphic) => { - return {graphic}; + return { graphic }; }); subLayerInfo.features.push(feature); - } - for ( const value of subLayers.values()) { + for (const value of subLayers.values()) { layerInfo.subLayerInfos!.push(value); } @@ -453,7 +486,8 @@ export class ArcGISMapLayerImageryProvider extends ArcGISImageryProvider { tmpUrl = `${this._settings.url}/tile/${zoomLevel}/${row}/${column} `; } else { const bboxString = `${this.getEPSG3857ExtentString(row, column, zoomLevel)}&bboxSR=3857`; - tmpUrl = `${this._settings.url}/export?bbox=${bboxString}&size=${this.tileSize},${this.tileSize}&layers=${this.getLayerString()}&format=png&transparent=${this.transparentBackgroundString}&f=image&sr=3857&imagesr=3857`; + tmpUrl = + `${this._settings.url}/export?bbox=${bboxString}&size=${this.tileSize},${this.tileSize}&layers=${this.getLayerString()}&format=png&transparent=${this.transparentBackgroundString}&f=image&sr=3857&imagesr=3857`; } return tmpUrl; } diff --git a/core/frontend/src/tile/map/ImageryProviders/ArcGisGeometryReaderJSON.ts b/core/frontend/src/tile/map/ImageryProviders/ArcGisGeometryReaderJSON.ts index 232b3e6c9864..09113c05780f 100644 --- a/core/frontend/src/tile/map/ImageryProviders/ArcGisGeometryReaderJSON.ts +++ b/core/frontend/src/tile/map/ImageryProviders/ArcGisGeometryReaderJSON.ts @@ -23,7 +23,6 @@ export class ArcGisGeometryReaderJSON { public async readGeometry(geometry: any) { if (this._ringsOrPaths) { await this.readRingsAndPaths(geometry, this._renderer, this._fill, this._relativeCoords); - } else if (this._points) { await this.readPoints(geometry, this._renderer, this._relativeCoords); } diff --git a/core/frontend/src/tile/map/ImageryProviders/AzureMapsLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/AzureMapsLayerImageryProvider.ts index f148c2fb6ebc..9083a4c278ee 100644 --- a/core/frontend/src/tile/map/ImageryProviders/AzureMapsLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/AzureMapsLayerImageryProvider.ts @@ -12,7 +12,9 @@ import { MapLayerImageryProvider } from "../../internal"; /** @internal */ export class AzureMapsLayerImageryProvider extends MapLayerImageryProvider { - constructor(settings: ImageMapLayerSettings) { super(settings, true); } + constructor(settings: ImageMapLayerSettings) { + super(settings, true); + } // construct the Url from the desired Tile public async constructUrl(y: number, x: number, zoom: number): Promise { @@ -24,7 +26,12 @@ export class AzureMapsLayerImageryProvider extends MapLayerImageryProvider { public override addLogoCards(cards: HTMLTableElement): void { if (!cards.dataset.azureMapsLogoCard) { cards.dataset.azureMapsLogoCard = "true"; - cards.appendChild(IModelApp.makeLogoCard({ heading: "Azure Maps", notice: IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap.AzureMapsCopyright") })); + cards.appendChild( + IModelApp.makeLogoCard({ + heading: "Azure Maps", + notice: IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap.AzureMapsCopyright"), + }), + ); } } } diff --git a/core/frontend/src/tile/map/ImageryProviders/BingImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/BingImageryProvider.ts index 958af4af73e0..59bcb7d3c0d7 100644 --- a/core/frontend/src/tile/map/ImageryProviders/BingImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/BingImageryProvider.ts @@ -7,26 +7,25 @@ */ import { assert, BentleyError, IModelStatus } from "@itwin/core-bentley"; -import { Range2d } from "@itwin/core-geometry"; import { ImageMapLayerSettings, ImageSource } from "@itwin/core-common"; -import { request } from "../../../request/Request"; +import { Range2d } from "@itwin/core-geometry"; import { IModelApp } from "../../../IModelApp"; +import { request } from "../../../request/Request"; import { ScreenViewport } from "../../../Viewport"; -import { - MapLayerImageryProvider, MapTile, MapTilingScheme, QuadId, - Tile, WebMercatorTilingScheme, -} from "../../internal"; +import { MapLayerImageryProvider, MapTile, MapTilingScheme, QuadId, Tile, WebMercatorTilingScheme } from "../../internal"; /** Represents one range of geography and tile zoom levels for a bing data provider * @internal */ class Coverage { - constructor(private _lowerLeftLatitude: number, + constructor( + private _lowerLeftLatitude: number, private _lowerLeftLongitude: number, private _upperRightLatitude: number, private _upperRightLongitude: number, private _minimumZoomLevel: number, - private _maximumZoomLevel: number) { } + private _maximumZoomLevel: number, + ) {} public overlaps(quadId: QuadId, tilingScheme: MapTilingScheme): boolean { const range: Range2d = quadId.getLatLongRangeDegrees(tilingScheme); @@ -51,7 +50,7 @@ class Coverage { * @internal */ class BingAttribution { - constructor(public copyrightMessage: string, private _coverages: Coverage[]) { } + constructor(public copyrightMessage: string, private _coverages: Coverage[]) {} public matchesTile(tile: Tile, tilingScheme: MapTilingScheme): boolean { const quadId = QuadId.createFromContentId(tile.contentId); @@ -88,8 +87,12 @@ export class BingMapsImageryLayerProvider extends MapLayerImageryProvider { this._mapTilingScheme = new WebMercatorTilingScheme(); } - public get tileWidth(): number { return this._tileWidth; } - public get tileHeight(): number { return this._tileHeight; } + public get tileWidth(): number { + return this._tileWidth; + } + public get tileHeight(): number { + return this._tileHeight; + } private tileXYToQuadKey(tileX: number, tileY: number, zoomLevel: number) { // from C# example in bing documentation https://msdn.microsoft.com/en-us/library/bb259689.aspx @@ -134,7 +137,7 @@ export class BingMapsImageryLayerProvider extends MapLayerImageryProvider { const unmatchedSet: BingAttribution[] = this._attributions.slice(); for (const tile of tiles) { - if (tile instanceof MapTile) + if (tile instanceof MapTile) { // compare to the set of Bing attributions that we have not yet matched. for (let iAttr = 0; iAttr < unmatchedSet.length; iAttr++) { const attribution = unmatchedSet[iAttr]; @@ -143,6 +146,7 @@ export class BingMapsImageryLayerProvider extends MapLayerImageryProvider { delete unmatchedSet[iAttr]; } } + } } return matchingAttributions; } @@ -201,8 +205,14 @@ export class BingMapsImageryLayerProvider extends MapLayerImageryProvider { const copyrightMessage: string = thisAttributionProps.attribution; const coverages: Coverage[] = new Array(); for (const thisCoverageProps of thisAttributionProps.coverageAreas) { - const thisCoverage = new Coverage(thisCoverageProps.bbox[0], thisCoverageProps.bbox[1], thisCoverageProps.bbox[2], thisCoverageProps.bbox[3], - thisCoverageProps.zoomMin, thisCoverageProps.zoomMax); + const thisCoverage = new Coverage( + thisCoverageProps.bbox[0], + thisCoverageProps.bbox[1], + thisCoverageProps.bbox[2], + thisCoverageProps.bbox[3], + thisCoverageProps.zoomMin, + thisCoverageProps.zoomMax, + ); coverages.push(thisCoverage); } const thisAttribution: BingAttribution = new BingAttribution(copyrightMessage, coverages); diff --git a/core/frontend/src/tile/map/ImageryProviders/CoordinatesUtils.ts b/core/frontend/src/tile/map/ImageryProviders/CoordinatesUtils.ts index 149c3d873bd0..c50ccd2386c1 100644 --- a/core/frontend/src/tile/map/ImageryProviders/CoordinatesUtils.ts +++ b/core/frontend/src/tile/map/ImageryProviders/CoordinatesUtils.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ /** Converts an [[x1,y1], [x2,y2], ...] to [x1,y1,x2,y2, ...] - * stride is the number of dimensions - * https://github.com/openlayers/openlayers/blob/7a2f87caca9ddc1912d910f56eb5637445fc11f6/src/ol/geom/flat/deflate.js#L26 -* @internal -*/ + * stride is the number of dimensions + * https://github.com/openlayers/openlayers/blob/7a2f87caca9ddc1912d910f56eb5637445fc11f6/src/ol/geom/flat/deflate.js#L26 + * @internal + */ export function deflateCoordinates(coordinates: number[][], flatCoordinates: number[], stride: number, offset: number) { for (let i = 0, ii = coordinates.length; i < ii; ++i) { const coordinate = coordinates[i]; diff --git a/core/frontend/src/tile/map/ImageryProviders/FeatureGeometryRenderer.ts b/core/frontend/src/tile/map/ImageryProviders/FeatureGeometryRenderer.ts index b391f6170aa5..d16dbbbbb953 100644 --- a/core/frontend/src/tile/map/ImageryProviders/FeatureGeometryRenderer.ts +++ b/core/frontend/src/tile/map/ImageryProviders/FeatureGeometryRenderer.ts @@ -27,7 +27,9 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend } public abstract hasSymbologyRenderer(): this is FeatureSymbolizedRenderer; - public get transform() { return this._transform; } + public get transform() { + return this._transform; + } protected abstract beginPath(): void; protected abstract closePath(): void; @@ -45,7 +47,7 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend * @param geometryCoords Array that linearly encodes the vertices of each sub-path of a polyline / ring of a polygon * @param fill Indicates if the path should be filled or not. * @param stride Dimension of each vertices (i.e. 2 or 3. 3 could be X,Y,Z, X,YM) Currently 3rd dimension is ignored. - */ + */ public async renderPath(geometryLengths: number[], geometryCoords: number[], fill: boolean, stride: number, relativeCoords: boolean) { if (stride < 2 || stride > 3) { return; @@ -80,7 +82,6 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend this.moveTo(pX, pY); } else { - // Following vertices are relative to the previous one (sadly not really well documented by ESRI) // typically this happens when 'coordinates quantization' is active (i.e. no client side transformation is needed) if (relativeCoords) { @@ -95,7 +96,6 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend } this.lineTo(pX, pY); } - } coordsOffset += stride * vertexCount; if (fill) { @@ -108,7 +108,7 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend await this.fill(); } - await this.stroke(); // draw line path or polygon outline + await this.stroke(); // draw line path or polygon outline } /** @@ -117,9 +117,8 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend * @param geometryLengths Array be used to determine the start and end of each multi-point array, empty for single point. * @param geometryCoords Array that linearly encodes vertices. * @param stride Dimension of each vertices (i.e. 2 or 3. 3 could be X,Y,Z, X,YM) Currently 3rd dimension is ignored. - */ + */ public async renderPoint(geometryLengths: number[], geometryCoords: number[], stride: number, relativeCoords: boolean) { - if (stride < 2 || stride > 3) { return; } @@ -127,7 +126,6 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend if (geometryLengths.length === 0) { // Strangely, for points, 'lengths' array is empty, so we assume there is a single vertex in 'coords' array. if (geometryCoords.length >= stride) { - if (this._transform) { const transformedPoint = this._transform.multiplyPoint2d({ x: geometryCoords[0], y: geometryCoords[1] }); this.drawPoint(transformedPoint.x, transformedPoint.y); @@ -156,7 +154,6 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend } this.drawPoint(pX, pY); - } coordsOffset += stride * vertexCount; } @@ -164,4 +161,3 @@ export abstract class FeatureGeometryBaseRenderer implements FeatureGeometryRend await this.finishPoints(); } } - diff --git a/core/frontend/src/tile/map/ImageryProviders/FeatureGraphicsRenderer.ts b/core/frontend/src/tile/map/ImageryProviders/FeatureGraphicsRenderer.ts index 1071808b5d73..70ce73e13d8a 100644 --- a/core/frontend/src/tile/map/ImageryProviders/FeatureGraphicsRenderer.ts +++ b/core/frontend/src/tile/map/ImageryProviders/FeatureGraphicsRenderer.ts @@ -5,9 +5,9 @@ import { Logger } from "@itwin/core-bentley"; import { Cartographic } from "@itwin/core-common"; import { GrowableXYZArray, LineString3d, Loop, Point3d, Point3dArray, RegionOps } from "@itwin/core-geometry"; -import { FeatureGeometryBaseRenderer, FeatureGeometryRenderer, FeatureSymbolizedRenderer, WebMercator } from "../../internal"; -import { Viewport } from "../../../Viewport"; import { GraphicPrimitive } from "../../../common/render/GraphicPrimitive"; +import { Viewport } from "../../../Viewport"; +import { FeatureGeometryBaseRenderer, FeatureGeometryRenderer, FeatureSymbolizedRenderer, WebMercator } from "../../internal"; const loggerCategory = "MapLayerImageryProvider.FeatureGraphicsRenderer"; @@ -34,8 +34,9 @@ export interface GraphicsGeometryRenderer extends FeatureGeometryRenderer { * @internal */ export class FeatureGraphicsRenderer extends FeatureGeometryBaseRenderer implements GraphicsGeometryRenderer { - - public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer {return false;} + public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer { + return false; + } private _scratchPointsArray = new GrowableXYZArray(); private _scratchPaths: Point3d[][] = []; @@ -72,7 +73,6 @@ export class FeatureGraphicsRenderer extends FeatureGeometryBaseRenderer impleme } protected async moveTo(x: number, y: number) { - if (this._scratchPointsArray.length > 0) { this._scratchPaths.push(this._scratchPointsArray.getArray()); this._scratchPointsArray.clear(); @@ -131,7 +131,6 @@ export class FeatureGraphicsRenderer extends FeatureGeometryBaseRenderer impleme protected override async finishPoints() { if (this._scratchPointsArray.length > 0) { - // Backend reprojection const pointsArray = this._scratchPointsArray.getArray(); try { @@ -148,11 +147,13 @@ export class FeatureGraphicsRenderer extends FeatureGeometryBaseRenderer impleme private async toSpatial(geoPoints: Point3d[]) { const bgMapGeom = this._viewport.displayStyle.getBackgroundMapGeometry(); if (bgMapGeom) { - const cartoPts = geoPoints.map((pt) => Cartographic.fromDegrees({ - longitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lon(pt.x) : pt.x, - latitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lat(pt.y) : pt.y, - height: pt.z, - })); + const cartoPts = geoPoints.map((pt) => + Cartographic.fromDegrees({ + longitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lon(pt.x) : pt.x, + latitude: this._crs === "webMercator" ? WebMercator.getEPSG4326Lat(pt.y) : pt.y, + height: pt.z, + }) + ); return bgMapGeom.cartographicToDbFromWgs84Gcs(cartoPts); } diff --git a/core/frontend/src/tile/map/ImageryProviders/FeatureSymbologyRenderer.ts b/core/frontend/src/tile/map/ImageryProviders/FeatureSymbologyRenderer.ts index f158c6e1dd9d..01dd33427533 100644 --- a/core/frontend/src/tile/map/ImageryProviders/FeatureSymbologyRenderer.ts +++ b/core/frontend/src/tile/map/ImageryProviders/FeatureSymbologyRenderer.ts @@ -19,4 +19,3 @@ export interface FeatureSymbologyRenderer { export interface FeatureSymbolizedRenderer { symbolRenderer: FeatureSymbologyRenderer; } - diff --git a/core/frontend/src/tile/map/ImageryProviders/MapBoxLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/MapBoxLayerImageryProvider.ts index 31601708dbc9..abc5f45a08a3 100644 --- a/core/frontend/src/tile/map/ImageryProviders/MapBoxLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/MapBoxLayerImageryProvider.ts @@ -25,10 +25,18 @@ export class MapBoxLayerImageryProvider extends MapLayerImageryProvider { this._zoomMax = 20; } - public get tileWidth(): number { return 256; } - public get tileHeight(): number { return 256; } - public override get minimumZoomLevel(): number { return this._zoomMin; } - public override get maximumZoomLevel(): number { return this._zoomMax; } + public get tileWidth(): number { + return 256; + } + public get tileHeight(): number { + return 256; + } + public override get minimumZoomLevel(): number { + return this._zoomMin; + } + public override get maximumZoomLevel(): number { + return this._zoomMax; + } // construct the Url from the desired Tile public async constructUrl(row: number, column: number, zoomLevel: number): Promise { @@ -48,10 +56,12 @@ export class MapBoxLayerImageryProvider extends MapLayerImageryProvider { public override addLogoCards(cards: HTMLTableElement): void { if (!cards.dataset.mapboxLogoCard) { cards.dataset.mapboxLogoCard = "true"; - cards.appendChild(IModelApp.makeLogoCard({ heading: "Mapbox", notice: IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap.MapBoxCopyright") })); + cards.appendChild( + IModelApp.makeLogoCard({ heading: "Mapbox", notice: IModelApp.localization.getLocalizedString("iModelJs:BackgroundMap.MapBoxCopyright") }), + ); } } // no initialization needed for MapBoxImageryProvider. - public override async initialize(): Promise { } + public override async initialize(): Promise {} } diff --git a/core/frontend/src/tile/map/ImageryProviders/TileUrlImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/TileUrlImageryProvider.ts index 1522c6d6d456..2a5f7f43d980 100644 --- a/core/frontend/src/tile/map/ImageryProviders/TileUrlImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/TileUrlImageryProvider.ts @@ -13,14 +13,18 @@ const rowToken = "{row}"; const columnToken = "{column}"; /** Provide tiles from a url template in the a generic format ... i.e. https://b.tile.openstreetmap.org/{level}/{column}/{row}.png -* @internal -*/ + * @internal + */ export class TileUrlImageryProvider extends MapLayerImageryProvider { constructor(settings: ImageMapLayerSettings) { super(settings, true); } public static validateUrlTemplate(template: string): MapLayerSourceValidation { - return { status: (template.indexOf(levelToken) > 0 && template.indexOf(columnToken) > 0 && template.indexOf(rowToken) > 0) ? MapLayerSourceStatus.Valid : MapLayerSourceStatus.InvalidUrl }; + return { + status: (template.indexOf(levelToken) > 0 && template.indexOf(columnToken) > 0 && template.indexOf(rowToken) > 0) + ? MapLayerSourceStatus.Valid + : MapLayerSourceStatus.InvalidUrl, + }; } // construct the Url from the desired Tile diff --git a/core/frontend/src/tile/map/ImageryProviders/WebMercator.ts b/core/frontend/src/tile/map/ImageryProviders/WebMercator.ts index 6eae8ae3363e..339f77fccab4 100644 --- a/core/frontend/src/tile/map/ImageryProviders/WebMercator.ts +++ b/core/frontend/src/tile/map/ImageryProviders/WebMercator.ts @@ -7,15 +7,14 @@ import { Angle, Constant } from "@itwin/core-geometry"; /** @internal */ export class WebMercator { - // calculates the longitude in EPSG:4326 (WGS84) from the projected x cartesian coordinate in EPSG:3857 public static getEPSG4326Lon(x3857: number): number { - return Angle.radiansToDegrees(x3857/Constant.earthRadiusWGS84.equator); + return Angle.radiansToDegrees(x3857 / Constant.earthRadiusWGS84.equator); } // calculates the latitude in EPSG:4326 (WGS84) from the projected y cartesian coordinate in EPSG:3857 public static getEPSG4326Lat(y3857: number): number { - const y = 2 * Math.atan(Math.exp(y3857 / Constant.earthRadiusWGS84.equator)) - (Math.PI/2); + const y = 2 * Math.atan(Math.exp(y3857 / Constant.earthRadiusWGS84.equator)) - (Math.PI / 2); return Angle.radiansToDegrees(y); } } diff --git a/core/frontend/src/tile/map/ImageryProviders/WmsMapLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/WmsMapLayerImageryProvider.ts index eaf3a49c00ec..c28c06f1605e 100644 --- a/core/frontend/src/tile/map/ImageryProviders/WmsMapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/WmsMapLayerImageryProvider.ts @@ -9,8 +9,14 @@ import { IModelStatus } from "@itwin/core-bentley"; import { Cartographic, ImageMapLayerSettings, MapSubLayerSettings, ServerError } from "@itwin/core-common"; import { Point2d } from "@itwin/core-geometry"; import { - ImageryMapTileTree, MapCartoRectangle, MapLayerImageryProvider, MapLayerImageryProviderStatus, QuadId, WmsCapabilities, - WmsCapability, WmsUtilities, + ImageryMapTileTree, + MapCartoRectangle, + MapLayerImageryProvider, + MapLayerImageryProviderStatus, + QuadId, + WmsCapabilities, + WmsCapability, + WmsUtilities, } from "../../internal"; // eslint-disable-next-line prefer-const @@ -31,7 +37,7 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { private _subLayerRanges = new Map(); private _baseUrl: string; // eslint-disable-next-line @typescript-eslint/naming-convention - private _crsSupport: WmsCrsSupport|undefined; + private _crsSupport: WmsCrsSupport | undefined; constructor(settings: ImageMapLayerSettings) { super(settings, false); @@ -40,26 +46,29 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { public override async initialize(): Promise { try { - const credentials = (this._settings.userName && this._settings.password ? {user: this._settings.userName, password: this._settings.password} : undefined); + const credentials = this._settings.userName && this._settings.password + ? { user: this._settings.userName, password: this._settings.password } + : undefined; this._capabilities = await WmsCapabilities.create(this._baseUrl, credentials); if (undefined !== this._capabilities) { this._allLayersRange = this._capabilities.cartoRange; if (this._capabilities.layer && Array.isArray(this._capabilities.layer.subLayers)) { - const mapCartoRanges = ((subLayer: WmsCapability.SubLayer) => { + const mapCartoRanges = (subLayer: WmsCapability.SubLayer) => { if (Array.isArray(subLayer.children)) subLayer.children.forEach((child) => mapCartoRanges(child)); else if (subLayer.cartoRange) this._subLayerRanges.set(subLayer.name, subLayer.cartoRange); - }); + }; this._capabilities.layer.subLayers.forEach((subLayer) => mapCartoRanges(subLayer)); this._settings.subLayers.forEach((subLayer) => { if (subLayer.isNamed && this._settings.isSubLayerVisible(subLayer)) { const subLayerRange = this._subLayerRanges.get(subLayer.name); - if (subLayerRange) + if (subLayerRange) { if (this.cartoRange) this.cartoRange.extendRange(subLayerRange); else this.cartoRange = subLayerRange.clone(); + } } }); } @@ -82,12 +91,12 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { } private getVisibleLayerString() { - const layerNames = this.getVisibleLayers().map((layer)=>layer.name); + const layerNames = this.getVisibleLayers().map((layer) => layer.name); return layerNames.join("%2C"); } private getVisibleLayers(): MapSubLayerSettings[] { - return this._settings.subLayers.filter((subLayer) => this._settings.isSubLayerVisible(subLayer) && subLayer.isNamed); + return this._settings.subLayers.filter((subLayer) => this._settings.isSubLayerVisible(subLayer) && subLayer.isNamed); } private getVisibleLayersSrs() { @@ -98,7 +107,7 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { private getQueryableLayers(): string[] { const layerNames = new Array(); - const getQueryableSubLayers = ((subLayer: WmsCapability.SubLayer) => { + const getQueryableSubLayers = (subLayer: WmsCapability.SubLayer) => { if (!subLayer) return; @@ -106,7 +115,7 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { layerNames.push(subLayer.name); subLayer.children?.forEach((childSubLayer) => getQueryableSubLayers(childSubLayer)); - }); + }; this._capabilities?.layer?.subLayers?.forEach((subLayer) => getQueryableSubLayers(subLayer)); return layerNames; @@ -127,17 +136,17 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { public getCrsSupport(): WmsCrsSupport { const layersCrs = this.getVisibleLayersSrs(); - let support3857: boolean|undefined; - let support4326: boolean|undefined; + let support3857: boolean | undefined; + let support4326: boolean | undefined; if (layersCrs) { for (const [_layerName, crs] of layersCrs) { - if (crs.find((layerCrs) => layerCrs.includes("3857")) === undefined ) { + if (crs.find((layerCrs) => layerCrs.includes("3857")) === undefined) { support3857 = false; } else if (support3857 === undefined) { support3857 = true; } - if (crs.find((layerCrs) => layerCrs.includes("4326")) === undefined ) { + if (crs.find((layerCrs) => layerCrs.includes("4326")) === undefined) { support4326 = false; } else if (support4326 === undefined) { support4326 = true; @@ -145,41 +154,42 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { } } - return {support3857: support3857 ?? false, support4326: support4326 ?? false}; + return { support3857: support3857 ?? false, support4326: support4326 ?? false }; } // WMS standard requires 'TRUE' or 'FALSE' (case sensitive) values. - public override get transparentBackgroundString(): string { return this._settings.transparentBackground ? "TRUE" : "FALSE"; } + public override get transparentBackgroundString(): string { + return this._settings.transparentBackground ? "TRUE" : "FALSE"; + } // construct the Url from the desired Tile public async constructUrl(row: number, column: number, zoomLevel: number): Promise { - - let bboxString =""; - let crsString =""; + let bboxString = ""; + let crsString = ""; // We support 2 SRS: EPSG:3857 and EPSG:4326, we prefer EPSG:3857. if (this._crsSupport?.support3857) { bboxString = this.getEPSG3857ExtentString(row, column, zoomLevel); - crsString= "EPSG%3A3857"; + crsString = "EPSG%3A3857"; } else if (this._crsSupport?.support4326) { // The WMS 1.3.0 specification mandates using the axis ordering as defined in the EPSG database. // For instance, for EPSG:4326 the axis ordering is latitude/longitude, or north/east. // WMS 1.1.0 always requires the axis ordering to be longitude/latitude. *sigh* if (this._capabilities !== undefined) { bboxString = this.getEPSG4326TileExtentString(row, column, zoomLevel, this._capabilities?.isVersion13); // lat/long ordering - crsString= "EPSG%3A4326"; + crsString = "EPSG%3A4326"; } - } const layerString = this.getVisibleLayerString(); - if (bboxString.length === 0 || crsString.length === 0 ||layerString.length === 0) + if (bboxString.length === 0 || crsString.length === 0 || layerString.length === 0) return ""; const crsParamName = this._capabilities?.isVersion13 ? "CRS" : "SRS"; - const tmpUrl = `${this._baseUrl}?SERVICE=WMS&VERSION=${this._capabilities?.version}&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=${this.transparentBackgroundString}&LAYERS=${layerString}&WIDTH=${this.tileSize}&HEIGHT=${this.tileSize}&${crsParamName}=${crsString}&STYLES=&BBOX=${bboxString}`; + const tmpUrl = + `${this._baseUrl}?SERVICE=WMS&VERSION=${this._capabilities?.version}&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=${this.transparentBackgroundString}&LAYERS=${layerString}&WIDTH=${this.tileSize}&HEIGHT=${this.tileSize}&${crsParamName}=${crsString}&STYLES=&BBOX=${bboxString}`; return this.appendCustomParams(tmpUrl); } @@ -200,9 +210,10 @@ export class WmsMapLayerImageryProvider extends MapLayerImageryProvider { const fraction = rectangle.worldToLocal(Point2d.create(carto.longitude, carto.latitude, scratchPoint2d))!; const x = Math.floor(.5 + fraction.x * this.tileSize); const y = Math.floor(.5 + (1.0 - fraction.y) * this.tileSize); - const coordinateString = this._capabilities?.isVersion13 ? `&i=${x}&j=${y}` : `&x=${x}&y=${y}`; + const coordinateString = this._capabilities?.isVersion13 ? `&i=${x}&j=${y}` : `&x=${x}&y=${y}`; const crsParamName = this._capabilities?.isVersion13 ? "CRS" : "SRS"; - let getFeatureUrl = `${this._baseUrl}?SERVICE=WMS&VERSION=${this._capabilities?.version}&REQUEST=GetFeatureInfo&LAYERS=${layerString}&WIDTH=${this.tileSize}&HEIGHT=${this.tileSize}&${crsParamName}=EPSG%3A3857&BBOX=${bboxString}&QUERY_LAYERS=${layerString}${coordinateString}&info_format=${formatString}`; + let getFeatureUrl = + `${this._baseUrl}?SERVICE=WMS&VERSION=${this._capabilities?.version}&REQUEST=GetFeatureInfo&LAYERS=${layerString}&WIDTH=${this.tileSize}&HEIGHT=${this.tileSize}&${crsParamName}=EPSG%3A3857&BBOX=${bboxString}&QUERY_LAYERS=${layerString}${coordinateString}&info_format=${formatString}`; getFeatureUrl = this.appendCustomParams(getFeatureUrl); return this.toolTipFromUrl(strings, getFeatureUrl); } diff --git a/core/frontend/src/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.ts b/core/frontend/src/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.ts index 3c1c2a822c5a..edf63971f757 100644 --- a/core/frontend/src/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/ImageryProviders/WmtsMapLayerImageryProvider.ts @@ -11,10 +11,16 @@ import { MapLayerImageryProvider, MapLayerImageryProviderStatus, QuadId, - WmsUtilities, WmtsCapabilities, WmtsCapability, WmtsConstants, + WmsUtilities, + WmtsCapabilities, + WmtsCapability, + WmtsConstants, } from "../../internal"; -interface TileMatrixSetAndLimits { tileMatrixSet: WmtsCapability.TileMatrixSet, limits: WmtsCapability.TileMatrixSetLimits[] | undefined } +interface TileMatrixSetAndLimits { + tileMatrixSet: WmtsCapability.TileMatrixSet; + limits: WmtsCapability.TileMatrixSetLimits[] | undefined; +} /** @internal */ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { private _baseUrl: string; @@ -23,7 +29,9 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { private _preferredLayerStyle = new Map(); public displayedLayerName = ""; - public override get mutualExclusiveSubLayer(): boolean { return true; } + public override get mutualExclusiveSubLayer(): boolean { + return true; + } constructor(settings: ImageMapLayerSettings) { super(settings, true); @@ -65,16 +73,17 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { // We have to pick one for each layer: for now we look for a Google Maps compatible tile tree. private initPreferredTileMatrixSet() { const googleMapsTms = this._capabilities?.contents?.getGoogleMapsCompatibleTileMatrixSet(); - const wellGoogleKnownTms = googleMapsTms?.find((tms) => tms.wellKnownScaleSet?.toLowerCase().includes(WmtsConstants.GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME)); + const wellGoogleKnownTms = googleMapsTms?.find((tms) => + tms.wellKnownScaleSet?.toLowerCase().includes(WmtsConstants.GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME) + ); this._capabilities?.contents?.layers.forEach((layer) => { let preferredTms: WmtsCapability.TileMatrixSet | undefined; if (wellGoogleKnownTms && layer.tileMatrixSetLinks.some((tmsl) => tmsl.tileMatrixSet === wellGoogleKnownTms.identifier)) { // Favor tile matrix set that was explicitly marked as GoogleMaps compatible - preferredTms = wellGoogleKnownTms; + preferredTms = wellGoogleKnownTms; } else { - // Search all compatible tile set matrix if previous attempt didn't work. // If more than one candidate is found, pick the tile set with the most LODs. let tileMatrixSets = googleMapsTms?.filter((tms) => { @@ -92,12 +101,11 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { preferredTms = tileMatrixSets[0]; else if (tileMatrixSets && tileMatrixSets?.length > 1) preferredTms = tileMatrixSets.reduce((prev, current) => (prev.tileMatrix.length > current.tileMatrix.length) ? prev : current); - } if (preferredTms !== undefined) { - const tmsLink= layer.tileMatrixSetLinks.find((tmsl) => tmsl.tileMatrixSet === preferredTms!.identifier); - this._preferredLayerTileMatrixSet.set(layer.identifier, { tileMatrixSet: preferredTms, limits: tmsLink?.tileMatrixSetLimits } ); + const tmsLink = layer.tileMatrixSetLinks.find((tmsl) => tmsl.tileMatrixSet === preferredTms!.identifier); + this._preferredLayerTileMatrixSet.set(layer.identifier, { tileMatrixSet: preferredTms, limits: tmsLink?.tileMatrixSetLimits }); } }); } @@ -124,7 +132,6 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { private initCartoRange() { this._capabilities?.contents?.layers.forEach((layer) => { - if (layer.wsg84BoundingBox) { if (this.cartoRange) this.cartoRange.extendRange(layer.wsg84BoundingBox); @@ -134,14 +141,14 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { }); } private getDisplayedTileMatrixSetAndLimits(): TileMatrixSetAndLimits | undefined { - return this._preferredLayerTileMatrixSet.get(this.displayedLayerName); + return this._preferredLayerTileMatrixSet.get(this.displayedLayerName); } protected override _generateChildIds(quadId: QuadId, resolveChildren: (childIds: QuadId[]) => void) { const childIds = this.getPotentialChildIds(quadId); const matrixSetAndLimits = this.getDisplayedTileMatrixSetAndLimits(); if (!matrixSetAndLimits) { - assert(false); // Must always hava a matrix set. + assert(false); // Must always hava a matrix set. return; } const limits = matrixSetAndLimits.limits?.[quadId.level + 1]?.limits; @@ -159,7 +166,9 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { } public override get useGeographicTilingScheme(): boolean { const matrixSetAndLimits = this.getDisplayedTileMatrixSetAndLimits(); - return matrixSetAndLimits ? (matrixSetAndLimits?.tileMatrixSet.identifier?.includes("4326") || matrixSetAndLimits?.tileMatrixSet.supportedCrs?.includes("4326")) : false; + return matrixSetAndLimits + ? (matrixSetAndLimits?.tileMatrixSet.identifier?.includes("4326") || matrixSetAndLimits?.tileMatrixSet.supportedCrs?.includes("4326")) + : false; } public async constructUrl(row: number, column: number, zoomLevel: number): Promise { @@ -172,12 +181,12 @@ export class WmtsMapLayerImageryProvider extends MapLayerImageryProvider { if (matrixSetAndLimits && matrixSetAndLimits.tileMatrixSet.tileMatrix.length > zoomLevel) tileMatrix = matrixSetAndLimits.tileMatrixSet.tileMatrix[zoomLevel].identifier; - const styleParam = (style?.identifier === undefined ? "" : `&style=${style.identifier}`); + const styleParam = style?.identifier === undefined ? "" : `&style=${style.identifier}`; if (tileMatrix !== undefined && matrixSetAndLimits !== undefined) { - const tmpUrl = `${this._baseUrl}?Service=WMTS&Version=1.0.0&Request=GetTile&Format=image%2Fpng&layer=${this.displayedLayerName}${styleParam}&TileMatrixSet=${matrixSetAndLimits.tileMatrixSet.identifier}&TileMatrix=${tileMatrix}&TileCol=${column}&TileRow=${row}`; + const tmpUrl = + `${this._baseUrl}?Service=WMTS&Version=1.0.0&Request=GetTile&Format=image%2Fpng&layer=${this.displayedLayerName}${styleParam}&TileMatrixSet=${matrixSetAndLimits.tileMatrixSet.identifier}&TileMatrix=${tileMatrix}&TileCol=${column}&TileRow=${row}`; return this.appendCustomParams(tmpUrl); } return ""; - } } diff --git a/core/frontend/src/tile/map/ImageryTileTree.ts b/core/frontend/src/tile/map/ImageryTileTree.ts index 15e3d7e0fefc..a97cb8bb6b99 100644 --- a/core/frontend/src/tile/map/ImageryTileTree.ts +++ b/core/frontend/src/tile/map/ImageryTileTree.ts @@ -6,20 +6,40 @@ * @module Tiles */ -import { assert, compareBooleans, compareNumbers, compareStrings, compareStringsOrUndefined, dispose, Logger} from "@itwin/core-bentley"; -import { Angle, Range3d, Transform } from "@itwin/core-geometry"; +import { assert, compareBooleans, compareNumbers, compareStrings, compareStringsOrUndefined, dispose, Logger } from "@itwin/core-bentley"; import { Cartographic, ImageMapLayerSettings, ImageSource, MapLayerSettings, RenderTexture, ViewFlagOverrides } from "@itwin/core-common"; +import { Angle, Range3d, Transform } from "@itwin/core-geometry"; +import { HitDetail } from "../../HitDetail"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; import { RenderMemory } from "../../render/RenderMemory"; import { RenderSystem } from "../../render/RenderSystem"; import { ScreenViewport } from "../../Viewport"; import { - MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProvider, MapLayerTileTreeReference, MapTile, MapTileTreeScaleRangeVisibility, MapTilingScheme, QuadId, RealityTile, RealityTileLoader, RealityTileTree, - RealityTileTreeParams, Tile, TileContent, TileDrawArgs, TileLoadPriority, TileParams, TileRequest, TileTree, TileTreeLoadStatus, TileTreeOwner, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapLayerImageryProvider, + MapLayerTileTreeReference, + MapTile, + MapTileTreeScaleRangeVisibility, + MapTilingScheme, + QuadId, + RealityTile, + RealityTileLoader, + RealityTileTree, + RealityTileTreeParams, + Tile, + TileContent, + TileDrawArgs, + TileLoadPriority, + TileParams, + TileRequest, + TileTree, + TileTreeLoadStatus, + TileTreeOwner, TileTreeSupplier, } from "../internal"; -import { HitDetail } from "../../HitDetail"; const loggerCategory = "ImageryMapTileTree"; @@ -41,26 +61,42 @@ export class ImageryMapTile extends RealityTile { this._outOfLodRange = this.depth < imageryTree.minDepth; } - public get texture() { return this._texture; } - public get tilingScheme() { return this.imageryTree.tilingScheme; } - public override get isDisplayable() { return (this.depth > 1) && super.isDisplayable; } - public override get isOutOfLodRange(): boolean { return this._outOfLodRange;} + public get texture() { + return this._texture; + } + public get tilingScheme() { + return this.imageryTree.tilingScheme; + } + public override get isDisplayable() { + return (this.depth > 1) && super.isDisplayable; + } + public override get isOutOfLodRange(): boolean { + return this._outOfLodRange; + } public override setContent(content: ImageryTileContent): void { - this._texture = content.imageryTexture; // No dispose - textures may be shared by terrain tiles so let garbage collector dispose them. + this._texture = content.imageryTexture; // No dispose - textures may be shared by terrain tiles so let garbage collector dispose them. if (undefined === content.imageryTexture) - (this.parent! as ImageryMapTile).setLeaf(); // Avoid traversing bing branches after no graphics is found. + (this.parent! as ImageryMapTile).setLeaf(); // Avoid traversing bing branches after no graphics is found. this.setIsReady(); } - public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], highResolutionReplacementTiles: ImageryMapTile[], rectangleToDrape: MapCartoRectangle, drapePixelSize: number, args: TileDrawArgs): TileTreeLoadStatus { + public selectCartoDrapeTiles( + drapeTiles: ImageryMapTile[], + highResolutionReplacementTiles: ImageryMapTile[], + rectangleToDrape: MapCartoRectangle, + drapePixelSize: number, + args: TileDrawArgs, + ): TileTreeLoadStatus { // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. const isSmallerThanDrape = (this.rectangle.xLength() / this.maximumSize) < drapePixelSize; - if ( (this.isLeaf ) // Include leaves so tiles get stretched past max LOD levels. (Only for base imagery layer) + if ( + (this.isLeaf) // Include leaves so tiles get stretched past max LOD levels. (Only for base imagery layer) || isSmallerThanDrape - || this._anyChildNotFound) { - if (this.isOutOfLodRange ) { + || this._anyChildNotFound + ) { + if (this.isOutOfLodRange) { drapeTiles.push(this); this.setIsReady(); } else if (this.isLeaf && !isSmallerThanDrape && !this._anyChildNotFound) { @@ -107,7 +143,6 @@ export class ImageryMapTile extends RealityTile { } protected override _loadChildren(resolve: (children: Tile[] | undefined) => void, _reject: (error: Error) => void): void { - const imageryTree = this.imageryTree; const resolveChildren = (childIds: QuadId[]) => { const children = new Array(); @@ -120,7 +155,12 @@ export class ImageryMapTile extends RealityTile { const rectangle = imageryTree.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); const range = Range3d.createXYZXYZ(rectangle.low.x, rectangle.low.x, 0, rectangle.high.x, rectangle.high.y, 0); const maximumSize = imageryTree.imageryLoader.maximumScreenSize; - const tile = new ImageryMapTile({ parent: this, isLeaf: childrenAreLeaves, contentId: quadId.contentId, range, maximumSize}, imageryTree, quadId, rectangle); + const tile = new ImageryMapTile( + { parent: this, isLeaf: childrenAreLeaves, contentId: quadId.contentId, range, maximumSize }, + imageryTree, + quadId, + rectangle, + ); children.push(tile); }); @@ -168,7 +208,9 @@ export class ImageryTileTreeState { /** Get the scale range visibility of the imagery tile tree. * @returns the scale range visibility of the imagery tile tree. */ - public getScaleRangeVisibility() {return this._scaleRangeVis;} + public getScaleRangeVisibility() { + return this._scaleRangeVis; + } /** Makes a deep copy of the current object. */ @@ -193,8 +235,11 @@ export class ImageryTileTreeState { */ public setScaleRangeVisibility(visible: boolean) { if (this._scaleRangeVis === MapTileTreeScaleRangeVisibility.Unknown) { - this._scaleRangeVis = (visible ? MapTileTreeScaleRangeVisibility.Visible : MapTileTreeScaleRangeVisibility.Hidden); - } else if ((visible && this._scaleRangeVis === MapTileTreeScaleRangeVisibility.Hidden) || (!visible && this._scaleRangeVis === MapTileTreeScaleRangeVisibility.Visible)) { + this._scaleRangeVis = visible ? MapTileTreeScaleRangeVisibility.Visible : MapTileTreeScaleRangeVisibility.Hidden; + } else if ( + (visible && this._scaleRangeVis === MapTileTreeScaleRangeVisibility.Hidden) || + (!visible && this._scaleRangeVis === MapTileTreeScaleRangeVisibility.Visible) + ) { this._scaleRangeVis = MapTileTreeScaleRangeVisibility.Partial; } } @@ -207,7 +252,9 @@ export class ImageryMapTileTree extends RealityTileTree { const rootQuadId = new QuadId(_imageryLoader.imageryProvider.tilingScheme.rootLevel, 0, 0); this._rootTile = new ImageryMapTile(params.rootTile, this, rootQuadId, this.getTileRectangle(rootQuadId)); } - public get tilingScheme(): MapTilingScheme { return this._imageryLoader.imageryProvider.tilingScheme; } + public get tilingScheme(): MapTilingScheme { + return this._imageryLoader.imageryProvider.tilingScheme; + } public addLogoCards(cards: HTMLTableElement, vp: ScreenViewport): void { this._imageryLoader.addLogoCards(cards, vp); } @@ -215,7 +262,9 @@ export class ImageryMapTileTree extends RealityTileTree { public getTileRectangle(quadId: QuadId): MapCartoRectangle { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); } - public get imageryLoader(): ImageryTileLoader { return this._imageryLoader; } + public get imageryLoader(): ImageryTileLoader { + return this._imageryLoader; + } public override get is3d(): boolean { assert(false); return false; @@ -232,19 +281,28 @@ export class ImageryMapTileTree extends RealityTileTree { assert(false); return []; } - public override draw(_args: TileDrawArgs): void { assert(false); } + public override draw(_args: TileDrawArgs): void { + assert(false); + } private static _scratchDrapeRectangle = MapCartoRectangle.createZero(); private static _drapeIntersectionScale = 1.0 - 1.0E-5; - public selectCartoDrapeTiles(drapeTiles: ImageryMapTile[], highResolutionReplacementTiles: ImageryMapTile[], tileToDrape: MapTile, args: TileDrawArgs): TileTreeLoadStatus { + public selectCartoDrapeTiles( + drapeTiles: ImageryMapTile[], + highResolutionReplacementTiles: ImageryMapTile[], + tileToDrape: MapTile, + args: TileDrawArgs, + ): TileTreeLoadStatus { const drapeRectangle = tileToDrape.rectangle.clone(ImageryMapTileTree._scratchDrapeRectangle); // Base draping overlap on width rather than height so that tiling schemes with multiple root nodes overlay correctly. const drapePixelSize = 1.05 * tileToDrape.rectangle.xLength() / tileToDrape.maximumSize; - drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers. + drapeRectangle.scaleAboutCenterInPlace(ImageryMapTileTree._drapeIntersectionScale); // Contract slightly to avoid draping adjacent or slivers. return (this.rootTile as ImageryMapTile).selectCartoDrapeTiles(drapeTiles, highResolutionReplacementTiles, drapeRectangle, drapePixelSize, args); } - public cartoRectangleFromQuadId(quadId: QuadId): MapCartoRectangle { return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); } + public cartoRectangleFromQuadId(quadId: QuadId): MapCartoRectangle { + return this.tilingScheme.tileXYToRectangle(quadId.column, quadId.row, quadId.level); + } } class ImageryTileLoader extends RealityTileLoader { @@ -252,25 +310,46 @@ class ImageryTileLoader extends RealityTileLoader { super(); } public override computeTilePriority(tile: Tile): number { - return 25 * (this._imageryProvider.usesCachedTiles ? 2 : 1) - tile.depth; // Always cached first then descending by depth (high resolution/front first) - } // Prioritized fast, cached tiles first. + return 25 * (this._imageryProvider.usesCachedTiles ? 2 : 1) - tile.depth; // Always cached first then descending by depth (high resolution/front first) + } // Prioritized fast, cached tiles first. - public get maxDepth(): number { return this._imageryProvider.maximumZoomLevel; } - public get minDepth(): number { return this._imageryProvider.minimumZoomLevel; } - public get priority(): TileLoadPriority { return TileLoadPriority.Map; } + public get maxDepth(): number { + return this._imageryProvider.maximumZoomLevel; + } + public get minDepth(): number { + return this._imageryProvider.minimumZoomLevel; + } + public get priority(): TileLoadPriority { + return TileLoadPriority.Map; + } public addLogoCards(cards: HTMLTableElement, vp: ScreenViewport): void { this._imageryProvider.addLogoCards(cards, vp); } - public get maximumScreenSize(): number { return this._imageryProvider.maximumScreenSize; } - public get imageryProvider(): MapLayerImageryProvider { return this._imageryProvider; } - public async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { await this._imageryProvider.getToolTip(strings, quadId, carto, tree); } + public get maximumScreenSize(): number { + return this._imageryProvider.maximumScreenSize; + } + public get imageryProvider(): MapLayerImageryProvider { + return this._imageryProvider; + } + public async getToolTip(strings: string[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree): Promise { + await this._imageryProvider.getToolTip(strings, quadId, carto, tree); + } - public async getMapFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, tree: ImageryMapTileTree, hit: HitDetail, options?: MapFeatureInfoOptions): Promise { + public async getMapFeatureInfo( + featureInfos: MapLayerFeatureInfo[], + quadId: QuadId, + carto: Cartographic, + tree: ImageryMapTileTree, + hit: HitDetail, + options?: MapFeatureInfoOptions, + ): Promise { await this._imageryProvider.getFeatureInfo(featureInfos, quadId, carto, tree, hit, options); } - public generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void) { return this._imageryProvider.generateChildIds(tile, resolveChildren); } + public generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void) { + return this._imageryProvider.generateChildIds(tile, resolveChildren); + } /** Load this tile's children, possibly asynchronously. Pass them to `resolve`, or an error to `reject`. */ public async loadChildren(_tile: RealityTile): Promise { @@ -368,12 +447,21 @@ class ImageryMapLayerTreeSupplier implements TileTreeSupplier { const modelId = iModel.transientIds.getNext(); const tilingScheme = imageryProvider.tilingScheme; - const rootLevel = (1 === tilingScheme.numberOfLevelZeroTilesX && 1 === tilingScheme.numberOfLevelZeroTilesY) ? 0 : -1; + const rootLevel = (1 === tilingScheme.numberOfLevelZeroTilesX && 1 === tilingScheme.numberOfLevelZeroTilesY) ? 0 : -1; const rootTileId = new QuadId(rootLevel, 0, 0).contentId; const rootRange = Range3d.createXYZXYZ(-Angle.piRadians, -Angle.piOver2Radians, 0, Angle.piRadians, Angle.piOver2Radians, 0); const rootTileProps = { contentId: rootTileId, range: rootRange, maximumSize: 0 }; const loader = new ImageryTileLoader(imageryProvider, iModel); - const treeProps = { rootTile: rootTileProps, id: modelId, modelId, iModel, location: Transform.createIdentity(), priority: TileLoadPriority.Map, loader, gcsConverterAvailable: false }; + const treeProps = { + rootTile: rootTileProps, + id: modelId, + modelId, + iModel, + location: Transform.createIdentity(), + priority: TileLoadPriority.Map, + loader, + gcsConverterAvailable: false, + }; return new ImageryMapTileTree(treeProps, loader); } } @@ -394,7 +482,9 @@ export class ImageryMapLayerTreeReference extends MapLayerTileTreeReference { super(args.layerSettings, args.layerIndex, args.iModel); } - public override get castsShadows() { return false; } + public override get castsShadows() { + return false; + } /** Return the owner of the TileTree to draw. */ public get treeOwner(): TileTreeOwner { diff --git a/core/frontend/src/tile/map/MapCartoRectangle.ts b/core/frontend/src/tile/map/MapCartoRectangle.ts index 6654ac2827c8..3bc6baa41a95 100644 --- a/core/frontend/src/tile/map/MapCartoRectangle.ts +++ b/core/frontend/src/tile/map/MapCartoRectangle.ts @@ -6,8 +6,8 @@ * @module Tiles */ -import { Angle, Point2d, Range2d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; +import { Angle, Point2d, Range2d } from "@itwin/core-geometry"; import { GlobalLocation, GlobalLocationArea } from "../../ViewGlobalLocation"; import { MapTilingScheme } from "../internal"; @@ -73,31 +73,49 @@ export class MapCartoRectangle extends Range2d { } /** The western longitude in radians. */ - public get west() { return this.low.x; } - public set west(x: number) { this.low.x = x; } + public get west() { + return this.low.x; + } + public set west(x: number) { + this.low.x = x; + } /** The southern latitude in radians. */ - public get south() { return this.low.y; } - public set south(y: number) { this.low.y = y; } + public get south() { + return this.low.y; + } + public set south(y: number) { + this.low.y = y; + } /** The eastern longitude in radians. */ - public get east() { return this.high.x; } - public set east(x: number) { this.high.x = x; } + public get east() { + return this.high.x; + } + public set east(x: number) { + this.high.x = x; + } /** The northern latitude in radians. */ - public get north() { return this.high.y; } - public set north(y: number) { this.high.y = y; } + public get north() { + return this.high.y; + } + public set north(y: number) { + this.high.y = y; + } /** A non-localized string representation of this rectangle, for debugging purposes. */ public get latLongString() { - return `Latitude: ${this.low.y * Angle.degreesPerRadian} - ${this.high.y * Angle.degreesPerRadian} Longitude: ${this.low.x * Angle.degreesPerRadian} - ${this.high.x * Angle.degreesPerRadian}`; + return `Latitude: ${this.low.y * Angle.degreesPerRadian} - ${this.high.y * Angle.degreesPerRadian} Longitude: ${ + this.low.x * Angle.degreesPerRadian + } - ${this.high.x * Angle.degreesPerRadian}`; } /** A pair of [[Cartographic]]s representing the same area as this rectangle. */ public get globalLocationArea(): GlobalLocationArea { return { - southwest: Cartographic.fromRadians({longitude: this.west, latitude: this.south}), - northeast: Cartographic.fromRadians({longitude: this.east, latitude: this.north}), + southwest: Cartographic.fromRadians({ longitude: this.west, latitude: this.south }), + northeast: Cartographic.fromRadians({ longitude: this.east, latitude: this.north }), }; } diff --git a/core/frontend/src/tile/map/MapFeatureInfo.ts b/core/frontend/src/tile/map/MapFeatureInfo.ts index c00f38e4e53b..6001fe34f12b 100644 --- a/core/frontend/src/tile/map/MapFeatureInfo.ts +++ b/core/frontend/src/tile/map/MapFeatureInfo.ts @@ -12,7 +12,7 @@ import { GraphicPrimitive } from "../../common/render/GraphicPrimitive"; /** Options supplied to a `Viewport.getMapFeatureInfo` . * @beta - */ + */ export interface MapFeatureInfoOptions { /** The distance in screen pixels from the specified geometry within which the query operation should be performed. */ tolerance?: number; diff --git a/core/frontend/src/tile/map/MapLayerAuthentication.ts b/core/frontend/src/tile/map/MapLayerAuthentication.ts index beb794cc0325..9e7e078aa8b5 100644 --- a/core/frontend/src/tile/map/MapLayerAuthentication.ts +++ b/core/frontend/src/tile/map/MapLayerAuthentication.ts @@ -42,4 +42,3 @@ export interface MapLayerAccessClient { onOAuthProcessEnd?: BeEvent; } - diff --git a/core/frontend/src/tile/map/MapLayerFormatRegistry.ts b/core/frontend/src/tile/map/MapLayerFormatRegistry.ts index b6da163abce8..840bbe716510 100644 --- a/core/frontend/src/tile/map/MapLayerFormatRegistry.ts +++ b/core/frontend/src/tile/map/MapLayerFormatRegistry.ts @@ -10,7 +10,16 @@ import { assert, Logger } from "@itwin/core-bentley"; import { ImageMapLayerSettings, MapLayerKey, MapLayerSettings, MapSubLayerProps } from "@itwin/core-common"; import { IModelApp } from "../../IModelApp"; import { IModelConnection } from "../../IModelConnection"; -import { ImageryMapLayerTreeReference, internalMapLayerImageryFormats, MapLayerAccessClient, MapLayerAuthenticationInfo, MapLayerImageryProvider, MapLayerSource, MapLayerSourceStatus, MapLayerTileTreeReference } from "../internal"; +import { + ImageryMapLayerTreeReference, + internalMapLayerImageryFormats, + MapLayerAccessClient, + MapLayerAuthenticationInfo, + MapLayerImageryProvider, + MapLayerSource, + MapLayerSourceStatus, + MapLayerTileTreeReference, +} from "../internal"; const loggerCategory = "ArcGISFeatureProvider"; /** @@ -26,7 +35,9 @@ export class MapLayerFormat { public static formatId: string; /** Register the current format in the [[MapLayerFormatRegistry]]. */ - public static register() { IModelApp.mapLayerFormatRegistry.register(this); } + public static register() { + IModelApp.mapLayerFormatRegistry.register(this); + } /** * Allow a source of a specific format to be validated before being attached as a map-layer. @@ -36,11 +47,19 @@ export class MapLayerFormat { * @param _ignoreCache Flag to skip cache lookup (i.e. force a new server request). * @returns Validation Status. If successful, a list of available sub-layers may also be returned. */ - public static async validateSource(_url: string, _userName?: string, _password?: string, _ignoreCache?: boolean, _accesKey?: MapLayerKey): Promise { return { status: MapLayerSourceStatus.Valid }; } + public static async validateSource( + _url: string, + _userName?: string, + _password?: string, + _ignoreCache?: boolean, + _accesKey?: MapLayerKey, + ): Promise { + return { status: MapLayerSourceStatus.Valid }; + } /** Allow a source object to be validated before being attached as a map-layer. - * @beta - */ + * @beta + */ public static async validate(args: ValidateSourceArgs): Promise { return this.validateSource(args.source.url, args.source.userName, args.source.password, args.ignoreCache); } @@ -51,7 +70,9 @@ export class MapLayerFormat { * @returns Returns the new imagery provider. * @beta */ - public static createImageryProvider(_settings: MapLayerSettings): MapLayerImageryProvider | undefined { assert(false); } + public static createImageryProvider(_settings: MapLayerSettings): MapLayerImageryProvider | undefined { + assert(false); + } /** * Creates a MapLayerTileTreeReference for this map layer format. @@ -61,11 +82,14 @@ export class MapLayerFormat { * @returns Returns the new tile tree reference. * @beta */ - public static createMapLayerTree(_layerSettings: MapLayerSettings, _layerIndex: number, _iModel: IModelConnection): MapLayerTileTreeReference | undefined { + public static createMapLayerTree( + _layerSettings: MapLayerSettings, + _layerIndex: number, + _iModel: IModelConnection, + ): MapLayerTileTreeReference | undefined { assert(false); return undefined; } - } /** Options for validating sources @@ -131,7 +155,9 @@ export class MapLayerFormatRegistry { } private _formats = new Map(); - public isRegistered(formatId: string) { return this._formats.get(formatId) !== undefined; } + public isRegistered(formatId: string) { + return this._formats.get(formatId) !== undefined; + } public register(formatClass: MapLayerFormatType) { if (formatClass.formatId.length === 0) @@ -163,7 +189,11 @@ export class MapLayerFormatRegistry { } /** @internal */ - public createImageryMapLayerTree(layerSettings: ImageMapLayerSettings, layerIndex: number, iModel: IModelConnection): ImageryMapLayerTreeReference | undefined { + public createImageryMapLayerTree( + layerSettings: ImageMapLayerSettings, + layerIndex: number, + iModel: IModelConnection, + ): ImageryMapLayerTreeReference | undefined { const entry = this._formats.get(layerSettings.formatId); const format = entry?.type; if (format === undefined) { @@ -191,10 +221,22 @@ export class MapLayerFormatRegistry { /** @beta*/ public async validateSource(opts: ValidateSourceArgs): Promise; - public async validateSource(formatId: string, url: string, userName?: string, password?: string, ignoreCache?: boolean): Promise; + public async validateSource( + formatId: string, + url: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise; /** @internal*/ - public async validateSource(formatIdOrArgs: string|ValidateSourceArgs, url?: string, userName?: string, password?: string, ignoreCache?: boolean): Promise { + public async validateSource( + formatIdOrArgs: string | ValidateSourceArgs, + url?: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise { let format: typeof MapLayerFormat | undefined; let args: ValidateSourceArgs | undefined; @@ -203,13 +245,12 @@ export class MapLayerFormatRegistry { const entry = this._formats.get(formatId); format = entry?.type; if (format !== undefined) { - const source = MapLayerSource.fromJSON({name: "", formatId, url}); + const source = MapLayerSource.fromJSON({ name: "", formatId, url }); if (source !== undefined) { - args = {source, ignoreCache}; + args = { source, ignoreCache }; source.userName = userName; source.password = password; } - } } else if (typeof formatIdOrArgs !== "string") { const entry = this._formats.get(formatIdOrArgs.source.formatId); @@ -223,4 +264,3 @@ export class MapLayerFormatRegistry { return format.validate(args); } } - diff --git a/core/frontend/src/tile/map/MapLayerImageryFormats.ts b/core/frontend/src/tile/map/MapLayerImageryFormats.ts index b0f87a3c1fe6..49e39bde2be5 100644 --- a/core/frontend/src/tile/map/MapLayerImageryFormats.ts +++ b/core/frontend/src/tile/map/MapLayerImageryFormats.ts @@ -36,7 +36,11 @@ import { */ export class ImageryMapLayerFormat extends MapLayerFormat { /** @internal */ - public static override createMapLayerTree(layerSettings: ImageMapLayerSettings, layerIndex: number, iModel: IModelConnection): MapLayerTileTreeReference | undefined { + public static override createMapLayerTree( + layerSettings: ImageMapLayerSettings, + layerIndex: number, + iModel: IModelConnection, + ): MapLayerTileTreeReference | undefined { return new ImageryMapLayerTreeReference({ layerSettings, layerIndex, iModel }); } } @@ -47,23 +51,33 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat { public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { return new WmsMapLayerImageryProvider(settings); } - public static override async validateSource(url: string, userName?: string, password?: string, ignoreCache?: boolean): Promise { - const source = MapLayerSource.fromJSON({name: "", formatId: WmsMapLayerFormat.formatId, url}); + public static override async validateSource( + url: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise { + const source = MapLayerSource.fromJSON({ name: "", formatId: WmsMapLayerFormat.formatId, url }); if (source === undefined) return { status: MapLayerSourceStatus.InvalidFormat }; source.userName = userName; source.password = password; - return WmsMapLayerFormat.validate({source, ignoreCache}); + return WmsMapLayerFormat.validate({ source, ignoreCache }); } public static override async validate(args: ValidateSourceArgs): Promise { - const {source, ignoreCache} = args; + const { source, ignoreCache } = args; const { url, userName, password } = source; try { let subLayers: MapSubLayerProps[] | undefined; const maxVisibleSubLayers = 50; - const capabilities = await WmsCapabilities.create(url, (userName && password ? {user: userName, password} : undefined), ignoreCache, source.collectQueryParams()); + const capabilities = await WmsCapabilities.create( + url, + userName && password ? { user: userName, password } : undefined, + ignoreCache, + source.collectQueryParams(), + ); if (capabilities !== undefined) { subLayers = capabilities.getSubLayers(false); const rootsSubLayer = subLayers?.find((sublayer) => sublayer.parent === undefined); @@ -76,10 +90,12 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat { // In general for WMS, we prefer to have the children of root node visible, but not the root itself. // Thats simply to give more flexibility in the UI. // Two exceptions to this rule: If there are too many layers or the root node is not named. - if (subLayer.id && subLayer.id === rootsSubLayer?.id - && (!(subLayer.name && subLayer.name.length > 0) || hasTooManyLayers)) { + if ( + subLayer.id && subLayer.id === rootsSubLayer?.id + && (!(subLayer.name && subLayer.name.length > 0) || hasTooManyLayers) + ) { subLayer.visible = true; - break; // if root node is visible, don't bother turning ON any other layers + break; // if root node is visible, don't bother turning ON any other layers } // Make children of the root node visible. @@ -112,12 +128,11 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat { } catch (err: any) { let status = MapLayerSourceStatus.InvalidUrl; if (err?.status === 401) { - status = ((userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth); + status = (userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth; } - return { status}; + return { status }; } } - } class WmtsMapLayerFormat extends ImageryMapLayerFormat { @@ -127,26 +142,36 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat { return new WmtsMapLayerImageryProvider(settings); } - public static override async validateSource(url: string, userName?: string, password?: string, ignoreCache?: boolean): Promise { - const source = MapLayerSource.fromJSON({name: "", formatId: WmtsMapLayerFormat.formatId, url}); + public static override async validateSource( + url: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise { + const source = MapLayerSource.fromJSON({ name: "", formatId: WmtsMapLayerFormat.formatId, url }); if (source === undefined) return { status: MapLayerSourceStatus.InvalidFormat }; source.userName = userName; source.password = password; - return WmtsMapLayerFormat.validate({source, ignoreCache}); + return WmtsMapLayerFormat.validate({ source, ignoreCache }); } public static override async validate(args: ValidateSourceArgs): Promise { - const {source, ignoreCache} = args; + const { source, ignoreCache } = args; const { url, userName, password } = source; try { const subLayers: MapSubLayerProps[] = []; - const capabilities = await WmtsCapabilities.create(url, (userName && password ? {user: userName, password} : undefined), ignoreCache, source.collectQueryParams()); + const capabilities = await WmtsCapabilities.create( + url, + userName && password ? { user: userName, password } : undefined, + ignoreCache, + source.collectQueryParams(), + ); if (!capabilities) return { status: MapLayerSourceStatus.InvalidUrl }; // Only returns layer that can be published in the Google maps or WGS84 aligned tile trees. - let supportedTms: WmtsCapability.TileMatrixSet[] = []; + let supportedTms: WmtsCapability.TileMatrixSet[] = []; const googleMapsTms = capabilities?.contents?.getGoogleMapsCompatibleTileMatrixSet(); if (googleMapsTms) { supportedTms = googleMapsTms; @@ -170,7 +195,7 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat { subLayers.push({ name: layer.identifier, title: layer.title ?? layer.identifier, - visible: (subLayers.length === 0), // Make the first layer visible. + visible: (subLayers.length === 0), // Make the first layer visible. parent: undefined, children: undefined, id: subLayerId++, @@ -186,32 +211,36 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat { } catch (err: any) { let status = MapLayerSourceStatus.InvalidUrl; if (err?.status === 401) { - status = ((userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth); + status = (userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth; } - return { status}; + return { status }; } } - } class ArcGISMapLayerFormat extends ImageryMapLayerFormat { public static override formatId = "ArcGIS"; - public static override async validateSource(url: string, userName?: string, password?: string, ignoreCache?: boolean): Promise { - const source = MapLayerSource.fromJSON({name: "", formatId: WmtsMapLayerFormat.formatId, url}); + public static override async validateSource( + url: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise { + const source = MapLayerSource.fromJSON({ name: "", formatId: WmtsMapLayerFormat.formatId, url }); if (source === undefined) return { status: MapLayerSourceStatus.InvalidFormat }; source.userName = userName; source.password = password; - return WmtsMapLayerFormat.validate({source, ignoreCache}); + return WmtsMapLayerFormat.validate({ source, ignoreCache }); } public static override async validate(args: ValidateSourceArgs): Promise { const urlValidation = ArcGisUtilities.validateUrl(args.source.url, "MapServer"); if (urlValidation !== MapLayerSourceStatus.Valid) - return {status: urlValidation}; + return { status: urlValidation }; // Some Map service supporting only tiles don't include the 'Map' capabilities, thus we can't make it mandatory. - return ArcGisUtilities.validateSource({...args, capabilitiesFilter: []}); + return ArcGisUtilities.validateSource({ ...args, capabilitiesFilter: [] }); } public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { @@ -241,8 +270,17 @@ class MapBoxImageryMapLayerFormat extends ImageryMapLayerFormat { } class TileUrlMapLayerFormat extends ImageryMapLayerFormat { public static override formatId = "TileURL"; - public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { return new TileUrlImageryProvider(settings); } + public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { + return new TileUrlImageryProvider(settings); + } } /** @internal */ -export const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, ArcGISMapLayerFormat, /* AzureMapsMapLayerFormat, */ BingMapsMapLayerFormat, MapBoxImageryMapLayerFormat, TileUrlMapLayerFormat]; +export const internalMapLayerImageryFormats = [ + WmsMapLayerFormat, + WmtsMapLayerFormat, + ArcGISMapLayerFormat, + /* AzureMapsMapLayerFormat, */ BingMapsMapLayerFormat, + MapBoxImageryMapLayerFormat, + TileUrlMapLayerFormat, +]; diff --git a/core/frontend/src/tile/map/MapLayerImageryProvider.ts b/core/frontend/src/tile/map/MapLayerImageryProvider.ts index 0e2229f683d9..825939a180cf 100644 --- a/core/frontend/src/tile/map/MapLayerImageryProvider.ts +++ b/core/frontend/src/tile/map/MapLayerImageryProvider.ts @@ -9,12 +9,23 @@ import { assert, BeEvent } from "@itwin/core-bentley"; import { Cartographic, ImageMapLayerSettings, ImageSource, ImageSourceFormat } from "@itwin/core-common"; import { Angle } from "@itwin/core-geometry"; +import { HitDetail } from "../../HitDetail"; import { IModelApp } from "../../IModelApp"; import { NotifyMessageDetails, OutputMessagePriority } from "../../NotificationManager"; -import { ScreenViewport } from "../../Viewport"; -import { appendQueryParams, GeographicTilingScheme, ImageryMapTile, ImageryMapTileTree, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapTilingScheme, QuadId, WebMercatorTilingScheme } from "../internal"; -import { HitDetail } from "../../HitDetail"; import { headersIncludeAuthMethod, setBasicAuthorization, setRequestTimeout } from "../../request/utils"; +import { ScreenViewport } from "../../Viewport"; +import { + appendQueryParams, + GeographicTilingScheme, + ImageryMapTile, + ImageryMapTileTree, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapTilingScheme, + QuadId, + WebMercatorTilingScheme, +} from "../internal"; /** @internal */ const tileImageSize = 256, untiledImageSize = 256; @@ -30,8 +41,7 @@ export enum MapLayerImageryProviderStatus { } /** @internal */ -export interface WGS84Extent -{ +export interface WGS84Extent { longitudeLeft: number; longitudeRight: number; latitudeTop: number; @@ -62,37 +72,57 @@ export abstract class MapLayerImageryProvider { protected readonly onFirstRequestCompleted = new BeEvent<() => void>(); /** @internal */ - protected _firstRequestPromise: Promise|undefined; + protected _firstRequestPromise: Promise | undefined; /** @internal */ - public get status() { return this._status; } + public get status() { + return this._status; + } /** Determine if this provider supports map feature info. * For example, this can be used to show the map feature info tool only when a provider is registered to support it. * @returns true if provider supports map feature info else return false. * @public */ - public get supportsMapFeatureInfo(): boolean { return false; } + public get supportsMapFeatureInfo(): boolean { + return false; + } - public resetStatus() { this.setStatus(MapLayerImageryProviderStatus.Valid); } + public resetStatus() { + this.setStatus(MapLayerImageryProviderStatus.Valid); + } /** @internal */ - public get tileSize(): number { return this._usesCachedTiles ? tileImageSize : untiledImageSize; } + public get tileSize(): number { + return this._usesCachedTiles ? tileImageSize : untiledImageSize; + } /** @internal */ - public get maximumScreenSize() { return 2 * this.tileSize; } + public get maximumScreenSize() { + return 2 * this.tileSize; + } - public get minimumZoomLevel(): number { return this.defaultMinimumZoomLevel; } + public get minimumZoomLevel(): number { + return this.defaultMinimumZoomLevel; + } - public get maximumZoomLevel(): number { return this.defaultMaximumZoomLevel; } + public get maximumZoomLevel(): number { + return this.defaultMaximumZoomLevel; + } /** @internal */ - public get usesCachedTiles() { return this._usesCachedTiles; } + public get usesCachedTiles() { + return this._usesCachedTiles; + } - public get mutualExclusiveSubLayer(): boolean { return false; } + public get mutualExclusiveSubLayer(): boolean { + return false; + } /** @internal */ - public get useGeographicTilingScheme() { return false; } + public get useGeographicTilingScheme() { + return false; + } public cartoRange?: MapCartoRectangle; @@ -109,7 +139,9 @@ export abstract class MapLayerImageryProvider { protected readonly defaultMaximumZoomLevel = 22; /** @internal */ - protected get _filterByCartoRange() { return true; } + protected get _filterByCartoRange() { + return true; + } constructor(protected readonly _settings: ImageMapLayerSettings, protected _usesCachedTiles: boolean) { this._mercatorTilingScheme = new WebMercatorTilingScheme(); @@ -129,7 +161,9 @@ export abstract class MapLayerImageryProvider { public abstract constructUrl(row: number, column: number, zoomLevel: number): Promise; - public get tilingScheme(): MapTilingScheme { return this.useGeographicTilingScheme ? this._geographicTilingScheme : this._mercatorTilingScheme; } + public get tilingScheme(): MapTilingScheme { + return this.useGeographicTilingScheme ? this._geographicTilingScheme : this._mercatorTilingScheme; + } /** * Add attribution logo cards for the data supplied by this provider to the [[Viewport]]'s logo div. @@ -137,16 +171,20 @@ export abstract class MapLayerImageryProvider { * @param _viewport Viewport to add logo cards to. * @beta */ - public addLogoCards(_cards: HTMLTableElement, _viewport: ScreenViewport): void { } + public addLogoCards(_cards: HTMLTableElement, _viewport: ScreenViewport): void {} /** @internal */ protected _missingTileData?: Uint8Array; /** @internal */ - public get transparentBackgroundString(): string { return this._settings.transparentBackground ? "true" : "false"; } + public get transparentBackgroundString(): string { + return this._settings.transparentBackground ? "true" : "false"; + } /** @internal */ - protected async _areChildrenAvailable(_tile: ImageryMapTile): Promise { return true; } + protected async _areChildrenAvailable(_tile: ImageryMapTile): Promise { + return true; + } /** @internal */ public getPotentialChildIds(quadId: QuadId): QuadId[] { @@ -167,7 +205,10 @@ export abstract class MapLayerImageryProvider { /** @internal */ public generateChildIds(tile: ImageryMapTile, resolveChildren: (childIds: QuadId[]) => void) { - if (tile.depth >= this.maximumZoomLevel || (undefined !== this.cartoRange && this._filterByCartoRange && !this.cartoRange.intersectsRange(tile.rectangle))) { + if ( + tile.depth >= this.maximumZoomLevel || + (undefined !== this.cartoRange && this._filterByCartoRange && !this.cartoRange.intersectsRange(tile.rectangle)) + ) { tile.setLeaf(); return; } @@ -190,7 +231,14 @@ export abstract class MapLayerImageryProvider { } /** @internal */ - public async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], _quadId: QuadId, _carto: Cartographic, _tree: ImageryMapTileTree, _hit: HitDetail, _options?: MapFeatureInfoOptions): Promise { + public async getFeatureInfo( + featureInfos: MapLayerFeatureInfo[], + _quadId: QuadId, + _carto: Cartographic, + _tree: ImageryMapTileTree, + _hit: HitDetail, + _options?: MapFeatureInfoOptions, + ): Promise { // default implementation; simply return an empty feature info featureInfos.push({ layerName: this._settings.name }); } @@ -238,7 +286,7 @@ export abstract class MapLayerImageryProvider { /** Method called whenever the status changes, giving the opportunity to sub-classes to have a custom behavior. * @internal */ - protected onStatusUpdated(_newStatus: MapLayerImageryProviderStatus) { } + protected onStatusUpdated(_newStatus: MapLayerImageryProviderStatus) {} /** @internal */ protected setRequestAuthorization(headers: Headers) { @@ -249,15 +297,14 @@ export abstract class MapLayerImageryProvider { /** @internal */ public async makeTileRequest(url: string, timeoutMs?: number): Promise { - // We want to complete the first request before letting other requests go; // this done to avoid flooding server with requests missing credentials if (!this._firstRequestPromise) - this._firstRequestPromise = new Promise((resolve: any) => this.onFirstRequestCompleted.addOnce(()=>resolve())); + this._firstRequestPromise = new Promise((resolve: any) => this.onFirstRequestCompleted.addOnce(() => resolve())); else await this._firstRequestPromise; - let response: Response|undefined; + let response: Response | undefined; try { response = await this.makeRequest(url, timeoutMs); } finally { @@ -272,8 +319,7 @@ export abstract class MapLayerImageryProvider { /** @internal */ public async makeRequest(url: string, timeoutMs?: number) { - - let response: Response|undefined; + let response: Response | undefined; let headers: Headers | undefined; let hasCreds = false; @@ -293,19 +339,20 @@ export abstract class MapLayerImageryProvider { response = await fetch(url, opts); - if (response.status === 401 - && headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"]) - && !this._includeUserCredentials - && !hasCreds + if ( + response.status === 401 + && headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"]) + && !this._includeUserCredentials + && !hasCreds ) { // Removed the previous headers and make sure "include" credentials is set opts.headers = undefined; opts.credentials = "include"; // We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication) - response = await fetch(url, opts); + response = await fetch(url, opts); if (response.status === 200) { - this._includeUserCredentials = true; // avoid going through 401 challenges over and over + this._includeUserCredentials = true; // avoid going through 401 challenges over and over } } @@ -314,7 +361,6 @@ export abstract class MapLayerImageryProvider { /** Returns a map layer tile at the specified settings. */ public async loadTile(row: number, column: number, zoomLevel: number): Promise { - try { const tileUrl: string = await this.constructUrl(row, column, zoomLevel); if (tileUrl.length === 0) @@ -338,7 +384,6 @@ export abstract class MapLayerImageryProvider { const msg = IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Messages.LoadTileTokenError", { layerName: this._settings.name }); IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Warning, msg)); } - } return undefined; } @@ -470,16 +515,18 @@ export abstract class MapLayerImageryProvider { public getEPSG4326TileExtentString(row: number, column: number, zoomLevel: number, latLongAxisOrdering: boolean) { const tileExtent = this.getEPSG4326Extent(row, column, zoomLevel); return this.getEPSG4326ExtentString(tileExtent, latLongAxisOrdering); - } /** @internal */ public getEPSG4326ExtentString(tileExtent: WGS84Extent, latLongAxisOrdering: boolean) { - if (latLongAxisOrdering) { - return `${tileExtent.latitudeBottom.toFixed(8)},${tileExtent.longitudeLeft.toFixed(8)},${tileExtent.latitudeTop.toFixed(8)},${tileExtent.longitudeRight.toFixed(8)}`; + return `${tileExtent.latitudeBottom.toFixed(8)},${tileExtent.longitudeLeft.toFixed(8)},${tileExtent.latitudeTop.toFixed(8)},${ + tileExtent.longitudeRight.toFixed(8) + }`; } else { - return `${tileExtent.longitudeLeft.toFixed(8)},${tileExtent.latitudeBottom.toFixed(8)},${tileExtent.longitudeRight.toFixed(8)},${tileExtent.latitudeTop.toFixed(8)}`; + return `${tileExtent.longitudeLeft.toFixed(8)},${tileExtent.latitudeBottom.toFixed(8)},${tileExtent.longitudeRight.toFixed(8)},${ + tileExtent.latitudeTop.toFixed(8) + }`; } } diff --git a/core/frontend/src/tile/map/MapLayerSources.ts b/core/frontend/src/tile/map/MapLayerSources.ts index a67624b56450..07a837407ec4 100644 --- a/core/frontend/src/tile/map/MapLayerSources.ts +++ b/core/frontend/src/tile/map/MapLayerSources.ts @@ -8,7 +8,12 @@ import { compareStrings } from "@itwin/core-bentley"; import { - BackgroundMapProvider, BackgroundMapType, BaseMapLayerSettings, DeprecatedBackgroundMapProps, ImageMapLayerSettings, MapSubLayerProps, + BackgroundMapProvider, + BackgroundMapType, + BaseMapLayerSettings, + DeprecatedBackgroundMapProps, + ImageMapLayerSettings, + MapSubLayerProps, } from "@itwin/core-common"; import { Point2d } from "@itwin/core-geometry"; import { IModelApp } from "../../IModelApp"; @@ -57,7 +62,7 @@ export interface MapLayerSourceProps { /** List of query parameters that will get appended to the source. * @beta - */ + */ queryParams?: { [key: string]: string }; } @@ -75,15 +80,22 @@ export class MapLayerSource { /** List of query parameters that will get appended to the source URL that should be be persisted part of the JSON representation. * @beta - */ + */ public savedQueryParams?: { [key: string]: string }; /** List of query parameters that will get appended to the source URL that should *not* be be persisted part of the JSON representation. * @beta - */ + */ public unsavedQueryParams?: { [key: string]: string }; - private constructor(formatId = "WMS", name: string, url: string, baseMap = false, transparentBackground = true, savedQueryParams?: { [key: string]: string}) { + private constructor( + formatId = "WMS", + name: string, + url: string, + baseMap = false, + transparentBackground = true, + savedQueryParams?: { [key: string]: string }, + ) { this.formatId = formatId; this.name = name; this.url = url; @@ -100,7 +112,7 @@ export class MapLayerSource { } public async validateSource(ignoreCache?: boolean): Promise { - return IModelApp.mapLayerFormatRegistry.validateSource({source: this, ignoreCache}); + return IModelApp.mapLayerFormatRegistry.validateSource({ source: this, ignoreCache }); } /** @internal*/ @@ -117,8 +129,14 @@ export class MapLayerSource { return undefined; } - public toJSON(): Omit & {formatId: string} { - return { url: this.url, name: this.name, formatId: this.formatId, transparentBackground: this.transparentBackground, queryParams: this.savedQueryParams }; + public toJSON(): Omit & { formatId: string } { + return { + url: this.url, + name: this.name, + formatId: this.formatId, + transparentBackground: this.transparentBackground, + queryParams: this.savedQueryParams, + }; } public toLayerSettings(subLayers?: MapSubLayerProps[]): ImageMapLayerSettings | undefined { @@ -129,11 +147,11 @@ export class MapLayerSource { } if (this.savedQueryParams) { - layerSettings.savedQueryParams = {...this.savedQueryParams}; + layerSettings.savedQueryParams = { ...this.savedQueryParams }; } if (this.unsavedQueryParams) { - layerSettings.unsavedQueryParams = {...this.unsavedQueryParams}; + layerSettings.unsavedQueryParams = { ...this.unsavedQueryParams }; } return layerSettings; } @@ -143,18 +161,17 @@ export class MapLayerSource { } /** Collect all query parameters - * @beta - */ + * @beta + */ public collectQueryParams() { - let queryParams: {[key: string]: string} = {}; + let queryParams: { [key: string]: string } = {}; if (this.savedQueryParams) - queryParams = {...this.savedQueryParams}; + queryParams = { ...this.savedQueryParams }; if (this.unsavedQueryParams) - queryParams = {...queryParams, ...this.unsavedQueryParams}; + queryParams = { ...queryParams, ...this.unsavedQueryParams }; return queryParams; } - } /** A collection of [[MapLayerSource]] objects. @@ -162,9 +179,11 @@ export class MapLayerSource { */ export class MapLayerSources { private static _instance?: MapLayerSources; - private constructor(private _sources: MapLayerSource[]) { } + private constructor(private _sources: MapLayerSource[]) {} - public static getInstance() { return MapLayerSources._instance; } + public static getInstance() { + return MapLayerSources._instance; + } public findByName(name: string, baseMap: boolean = false): MapLayerSource | undefined { const nameTest = name.toLowerCase(); @@ -183,7 +202,9 @@ export class MapLayerSources { return layers; } - public get allSource() { return this._sources; } + public get allSource() { + return this._sources; + } public get bases(): MapLayerSource[] { const layers = new Array(); this._sources.forEach((source) => { @@ -196,17 +217,29 @@ export class MapLayerSources { private static getBingMapLayerSource(): MapLayerSource[] { const mapLayerSources: MapLayerSource[] = []; - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Street } })!); - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Aerial } })!); - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Hybrid } })!); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Street } })!, + ); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Aerial } })!, + ); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "BingProvider", providerData: { mapType: BackgroundMapType.Hybrid } })!, + ); return mapLayerSources; } private static getMapBoxLayerSource(): MapLayerSource[] { const mapLayerSources: MapLayerSource[] = []; - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Street } })!); - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Aerial } })!); - mapLayerSources.push(MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Hybrid } })!); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Street } })!, + ); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Aerial } })!, + ); + mapLayerSources.push( + MapLayerSource.fromBackgroundMapProps({ providerName: "MapBoxProvider", providerData: { mapType: BackgroundMapType.Hybrid } })!, + ); return mapLayerSources; } @@ -223,17 +256,22 @@ export class MapLayerSources { const cartoCenter = iModel.spatialToCartographicFromEcef(projectCenter); const globeRange = MapCartoRectangle.createMaximum(); const nearDelta = Point2d.create(globeRange.xLength() / 100, globeRange.yLength() / 100); - sourceRange = MapCartoRectangle.fromRadians(cartoCenter.longitude - nearDelta.x, cartoCenter.latitude - nearDelta.y, cartoCenter.longitude + nearDelta.x, cartoCenter.latitude + nearDelta.y); + sourceRange = MapCartoRectangle.fromRadians( + cartoCenter.longitude - nearDelta.x, + cartoCenter.latitude - nearDelta.y, + cartoCenter.longitude + nearDelta.x, + cartoCenter.latitude + nearDelta.y, + ); } const sources = new Array(); const urlSet = new Set(); - const addSource = ((source: MapLayerSource) => { + const addSource = (source: MapLayerSource) => { if (!urlSet.has(source.url)) { sources.push(source); urlSet.add(source.url); } - }); + }; this.getBingMapLayerSource().forEach((source) => { addSource(source); diff --git a/core/frontend/src/tile/map/MapLayerTileTreeReference.ts b/core/frontend/src/tile/map/MapLayerTileTreeReference.ts index ea8485efa313..057ea8b3d696 100644 --- a/core/frontend/src/tile/map/MapLayerTileTreeReference.ts +++ b/core/frontend/src/tile/map/MapLayerTileTreeReference.ts @@ -43,29 +43,44 @@ export abstract class MapLayerTileTreeReference extends TileTreeReference { } /* @internal */ - protected get _transparency() { return this._layerSettings.transparency ? this._layerSettings.transparency : undefined; } + protected get _transparency() { + return this._layerSettings.transparency ? this._layerSettings.transparency : undefined; + } /** Returns true if the associated map layer, including its sublayers, is opaque. */ public get isOpaque() { - return this._layerSettings.visible && (!this._layerSettings.allSubLayersInvisible) && !this._layerSettings.transparentBackground && 0 === this._layerSettings.transparency; + return this._layerSettings.visible && (!this._layerSettings.allSubLayersInvisible) && !this._layerSettings.transparentBackground && + 0 === this._layerSettings.transparency; } /* Returns the map layer name. */ - public get layerName() { return this._layerSettings.name; } + public get layerName() { + return this._layerSettings.name; + } /** Returns the imagery provider for the tile tree. */ - public get imageryProvider(): MapLayerImageryProvider | undefined { return undefined; } + public get imageryProvider(): MapLayerImageryProvider | undefined { + return undefined; + } - public set layerSettings(layerSettings: MapLayerSettings) { this._layerSettings = layerSettings; } + public set layerSettings(layerSettings: MapLayerSettings) { + this._layerSettings = layerSettings; + } /** Returns the layer settings for the map layer. */ - public get layerSettings(): MapLayerSettings { return this._layerSettings; } + public get layerSettings(): MapLayerSettings { + return this._layerSettings; + } /** Returns the index of the map layer associated with the tile tree. */ - public get layerIndex(): number { return this._layerIndex; } + public get layerIndex(): number { + return this._layerIndex; + } /** Returns the transparency value of the map layer. */ - public get transparency() { return this._transparency; } + public get transparency() { + return this._transparency; + } public override canSupplyToolTip(hit: HitDetail): boolean { const tree = this.treeOwner.tileTree; @@ -94,13 +109,17 @@ export abstract class MapLayerTileTreeReference extends TileTreeReference { * @returns Returns the new tile tree reference, either a ModelMapLayerTileTreeReference or an ImageryMapLayerTreeReference. * @internal */ -export function createMapLayerTreeReference(layerSettings: MapLayerSettings, layerIndex: number, iModel: IModelConnection): MapLayerTileTreeReference | undefined { +export function createMapLayerTreeReference( + layerSettings: MapLayerSettings, + layerIndex: number, + iModel: IModelConnection, +): MapLayerTileTreeReference | undefined { if (layerSettings instanceof ModelMapLayerSettings) { return createModelMapLayerTileTreeReference(layerSettings, layerIndex, iModel); } else if (layerSettings instanceof ImageMapLayerSettings) return IModelApp.mapLayerFormatRegistry.createImageryMapLayerTree(layerSettings, layerIndex, iModel); else { - assert (false); + assert(false); return undefined; } } diff --git a/core/frontend/src/tile/map/MapTile.ts b/core/frontend/src/tile/map/MapTile.ts index 42055ae8451a..69cdeea1c085 100644 --- a/core/frontend/src/tile/map/MapTile.ts +++ b/core/frontend/src/tile/map/MapTile.ts @@ -8,18 +8,51 @@ import { assert, dispose } from "@itwin/core-bentley"; import { ColorByName, ColorDef, FrustumPlanes, GlobeMode, PackedFeatureTable, RenderTexture } from "@itwin/core-common"; -import { AxisOrder, BilinearPatch, ClipPlane, ClipPrimitive, ClipShape, ClipVector, Constant, ConvexClipPlaneSet, EllipsoidPatch, LongitudeLatitudeNumber, Matrix3d, Point3d, PolygonOps, Range1d, Range2d, Range3d, Ray3d, Transform, Vector2d, Vector3d } from "@itwin/core-geometry"; +import { + AxisOrder, + BilinearPatch, + ClipPlane, + ClipPrimitive, + ClipShape, + ClipVector, + Constant, + ConvexClipPlaneSet, + EllipsoidPatch, + LongitudeLatitudeNumber, + Matrix3d, + Point3d, + PolygonOps, + Range1d, + Range2d, + Range3d, + Ray3d, + Transform, + Vector2d, + Vector3d, +} from "@itwin/core-geometry"; import { IModelApp } from "../../IModelApp"; import { GraphicBuilder } from "../../render/GraphicBuilder"; import { RealityMeshParams } from "../../render/RealityMeshParams"; -import { upsampleRealityMeshParams } from "../../render/UpsampleRealityMeshParams"; import { RenderGraphic } from "../../render/RenderGraphic"; import { RenderMemory } from "../../render/RenderMemory"; import { RenderSystem, RenderTerrainGeometry, TerrainTexture } from "../../render/RenderSystem"; +import { upsampleRealityMeshParams } from "../../render/UpsampleRealityMeshParams"; import { ViewingSpace } from "../../ViewingSpace"; import { - ImageryMapTile, MapCartoRectangle, MapTileLoader, MapTileTree, QuadId, RealityTile, RealityTileParams, Tile, TileContent, TileDrawArgs, TileGraphicType, - TileLoadStatus, TileTreeLoadStatus, TraversalSelectionContext, + ImageryMapTile, + MapCartoRectangle, + MapTileLoader, + MapTileTree, + QuadId, + RealityTile, + RealityTileParams, + Tile, + TileContent, + TileDrawArgs, + TileGraphicType, + TileLoadStatus, + TileTreeLoadStatus, + TraversalSelectionContext, } from "../internal"; /** @internal */ @@ -61,7 +94,9 @@ export abstract class MapTileProjection { public abstract getPoint(u: number, v: number, height: number, result?: Point3d): Point3d; /** @alpha */ - public get ellipsoidPatch(): EllipsoidPatch | undefined { return undefined; } + public get ellipsoidPatch(): EllipsoidPatch | undefined { + return undefined; + } /** @alpha */ public getGlobalPoint(u: number, v: number, z: number, result?: Point3d): Point3d { @@ -86,7 +121,9 @@ class EllipsoidProjection extends MapTileProjection { const ray = this._patch.anglesToUnitNormalRay(angles, EllipsoidProjection._scratchRay); return Point3d.createFrom(ray!.origin, result); } - public override get ellipsoidPatch() { return this._patch; } + public override get ellipsoidPatch() { + return this._patch; + } } /** @alpha */ @@ -97,7 +134,12 @@ class PlanarProjection extends MapTileProjection { constructor(patch: PlanarTilePatch, heightRange?: Range1d) { super(); this.transformFromLocal = Transform.createOriginAndMatrix(patch.corners[0], Matrix3d.createRigidHeadsUp(patch.normal, AxisOrder.ZYX)); - const planeCorners = this.transformFromLocal.multiplyInversePoint3dArray([patch.corners[0], patch.corners[1], patch.corners[2], patch.corners[3]])!; + const planeCorners = this.transformFromLocal.multiplyInversePoint3dArray([ + patch.corners[0], + patch.corners[1], + patch.corners[2], + patch.corners[3], + ])!; this.localRange = Range3d.createArray(planeCorners); this.localRange.low.z += heightRange ? heightRange.low : 0; this.localRange.high.z += heightRange ? heightRange.high : 0; @@ -122,8 +164,22 @@ export interface TerrainTileContent extends TileContent { const scratchNormal = Vector3d.create(); const scratchViewZ = Vector3d.create(); const scratchPoint = Point3d.create(); -const scratchClipPlanes = [ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint)]; -const scratchCorners = [Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()]; +const scratchClipPlanes = [ + ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), + ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), + ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), + ClipPlane.createNormalAndPoint(scratchNormal, scratchPoint), +]; +const scratchCorners = [ + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), +]; /** A [[Tile]] belonging to a [[MapTileTree]] representing a rectangular region of a map of the Earth. * @public @@ -134,7 +190,7 @@ export class MapTile extends RealityTile { private _hiddenTiles?: ImageryMapTile[]; private _highResolutionReplacementTiles?: ImageryMapTile[]; /** @internal */ - public everLoaded = false; // If the tile is only required for availability metadata, load it once and then allow it to be unloaded. + public everLoaded = false; // If the tile is only required for availability metadata, load it once and then allow it to be unloaded. /** @internal */ protected _heightRange: Range1d | undefined; /** @internal */ @@ -152,19 +208,31 @@ export class MapTile extends RealityTile { } /** @internal */ - public get renderGeometry() { return this._renderGeometry; } + public get renderGeometry() { + return this._renderGeometry; + } /** @internal */ - public get mesh() { return this._mesh; } + public get mesh() { + return this._mesh; + } /** @internal */ - public get loadableTerrainTile() { return this.loadableTile as MapTile; } + public get loadableTerrainTile() { + return this.loadableTile as MapTile; + } /** @internal */ - public get isPlanar(): boolean { return this._patch instanceof PlanarTilePatch; } + public get isPlanar(): boolean { + return this._patch instanceof PlanarTilePatch; + } /** @internal */ - public get imageryTiles(): ImageryMapTile[] | undefined { return this._imageryTiles; } + public get imageryTiles(): ImageryMapTile[] | undefined { + return this._imageryTiles; + } /** List of selected tiles but are currently in hidden state (i.e. scale range visibility) * @internal */ - public get hiddenImageryTiles(): ImageryMapTile[] | undefined { return this._hiddenTiles; } + public get hiddenImageryTiles(): ImageryMapTile[] | undefined { + return this._hiddenTiles; + } /** List of leafs tiles that have been selected as a replacement for missing high resolution tiles. * When this list is non-empty this means we are past the maximum LOD available of the tile tree. @@ -172,7 +240,9 @@ export class MapTile extends RealityTile { * in some cases this is preferred to have no tile at all. * @internal */ - public get highResolutionReplacementTiles(): ImageryMapTile[] | undefined { return this._highResolutionReplacementTiles; } + public get highResolutionReplacementTiles(): ImageryMapTile[] | undefined { + return this._highResolutionReplacementTiles; + } /** The [[MapTileTree]] to which this tile belongs. */ public readonly mapTree: MapTileTree; @@ -185,7 +255,15 @@ export class MapTile extends RealityTile { protected _cornerRays?: Ray3d[]; /** @internal */ - constructor(params: RealityTileParams, mapTree: MapTileTree, quadId: QuadId, patch: TilePatch, rectangle: MapCartoRectangle, heightRange: Range1d | undefined, cornerRays: Ray3d[] | undefined) { + constructor( + params: RealityTileParams, + mapTree: MapTileTree, + quadId: QuadId, + patch: TilePatch, + rectangle: MapCartoRectangle, + heightRange: Range1d | undefined, + cornerRays: Ray3d[] | undefined, + ) { super(params, mapTree); this.mapTree = mapTree; this.quadId = quadId; @@ -210,9 +288,10 @@ export class MapTile extends RealityTile { /** @internal */ public override markUsed(args: TileDrawArgs) { super.markUsed(args); - if (this._imageryTiles) + if (this._imageryTiles) { for (const imageryTile of this._imageryTiles) imageryTile.markUsed(args); + } } /** @internal */ @@ -224,9 +303,13 @@ export class MapTile extends RealityTile { } /** @internal */ - public get mapLoader() { return this.realityRoot.loader as MapTileLoader; } + public get mapLoader() { + return this.realityRoot.loader as MapTileLoader; + } /** @internal */ - public get isUpsampled() { return false; } + public get isUpsampled() { + return false; + } /** @internal */ public tileFromQuadId(quadId: QuadId): MapTile | undefined { @@ -425,10 +508,21 @@ export class MapTile extends RealityTile { const heightRange = this.mapTree.getChildHeightRange(quadId, rectangle, this); const diagonal = Math.max(corners[0].distance(corners[3]), corners[1].distance(corners[2])) / 2.0; - const chordHeight = globeMode === GlobeMode.Ellipsoid ? Math.sqrt(diagonal * diagonal + Constant.earthRadiusWGS84.equator * Constant.earthRadiusWGS84.equator) - Constant.earthRadiusWGS84.equator : 0.0; + const chordHeight = globeMode === GlobeMode.Ellipsoid + ? Math.sqrt(diagonal * diagonal + Constant.earthRadiusWGS84.equator * Constant.earthRadiusWGS84.equator) - + Constant.earthRadiusWGS84.equator + : 0.0; const rangeCorners = MapTile.computeRangeCorners(corners, normal, chordHeight, undefined, heightRange); const range = Range3d.createArray(rangeCorners); - const child = this.mapTree.createPlanarChild({ contentId: quadId.contentId, maximumSize: 512, range, parent: this, isLeaf: childrenAreLeaves }, quadId, corners, normal, rectangle, chordHeight, heightRange); + const child = this.mapTree.createPlanarChild( + { contentId: quadId.contentId, maximumSize: 512, range, parent: this, isLeaf: childrenAreLeaves }, + quadId, + corners, + normal, + rectangle, + chordHeight, + heightRange, + ); if (child) children.push(child); } @@ -458,7 +552,16 @@ export class MapTile extends RealityTile { if (undefined !== heightRange) range.expandInPlace(heightRange.high - heightRange.low); - children.push(this.mapTree.createGlobeChild({ contentId: quadId.contentId, maximumSize: 512, range, parent: this, isLeaf: false }, quadId, range.corners(), rectangle, ellipsoidPatch, heightRange)); + children.push( + this.mapTree.createGlobeChild( + { contentId: quadId.contentId, maximumSize: 512, range, parent: this, isLeaf: false }, + quadId, + range.corners(), + rectangle, + ellipsoidPatch, + heightRange, + ), + ); } } @@ -476,7 +579,7 @@ export class MapTile extends RealityTile { let index = 0; assert(corners.length === 4); - const deltaLow = normal.scale(- chordHeight + (heightRange ? heightRange.low : 0)); + const deltaLow = normal.scale(-chordHeight + (heightRange ? heightRange.low : 0)); const deltaHigh = normal.scale(chordHeight + (heightRange ? heightRange.high : 0)); for (const corner of corners) @@ -502,9 +605,10 @@ export class MapTile extends RealityTile { public clearLayers() { this.clearImageryTiles(); this._graphic = undefined; - if (this.children) + if (this.children) { for (const child of this.children) (child as MapTile).clearLayers(); + } } private clearImageryTiles() { @@ -531,7 +635,18 @@ export class MapTile extends RealityTile { const textures = this.getDrapeTextures(); const { baseColor, baseTransparent, layerClassifiers } = this.mapTree; - const graphic = IModelApp.renderSystem.createRealityMeshGraphic({ realityMesh: geometry, projection: this.getProjection(), tileRectangle: this.rectangle, featureTable: PackedFeatureTable.pack(this.mapLoader.featureTable), tileId: this.contentId, baseColor, baseTransparent, textures, layerClassifiers, disableClipStyle: true }, true); + const graphic = IModelApp.renderSystem.createRealityMeshGraphic({ + realityMesh: geometry, + projection: this.getProjection(), + tileRectangle: this.rectangle, + featureTable: PackedFeatureTable.pack(this.mapLoader.featureTable), + tileId: this.contentId, + baseColor, + baseTransparent, + textures, + layerClassifiers, + disableClipStyle: true, + }, true); // If there are no layer classifiers then we can save this graphic for re-use. If layer classifiers exist they are regenerated based on view and we must collate them with the imagery. if (this.imageryIsReady && 0 === this.mapTree.layerClassifiers.size) @@ -542,7 +657,9 @@ export class MapTile extends RealityTile { /** @internal */ public getClipShape(): Point3d[] { - return (this._patch instanceof PlanarTilePatch) ? this._patch.getClipShape() : [this._cornerRays![0].origin, this._cornerRays![1].origin, this._cornerRays![3].origin, this._cornerRays![2].origin]; + return (this._patch instanceof PlanarTilePatch) + ? this._patch.getClipShape() + : [this._cornerRays![0].origin, this._cornerRays![1].origin, this._cornerRays![3].origin, this._cornerRays![2].origin]; } /** @internal */ @@ -551,10 +668,11 @@ export class MapTile extends RealityTile { this._renderGeometry?.collectStatistics(stats); if (this._mesh) { - stats.addTerrain(this._mesh.indices.byteLength - + this._mesh.positions.points.byteLength - + this._mesh.uvs.points.byteLength - + (this._mesh.normals ? this._mesh.normals.byteLength : 0), + stats.addTerrain( + this._mesh.indices.byteLength + + this._mesh.positions.points.byteLength + + this._mesh.uvs.points.byteLength + + (this._mesh.normals ? this._mesh.normals.byteLength : 0), ); } } @@ -598,7 +716,9 @@ export class MapTile extends RealityTile { /** Obtain a [[MapTileProjection]] to project positions within this tile's area into 3d space. */ public getProjection(heightRange?: Range1d): MapTileProjection { - return this._patch instanceof PlanarTilePatch ? new PlanarProjection(this._patch, heightRange) : new EllipsoidProjection(this._patch, heightRange); + return this._patch instanceof PlanarTilePatch + ? new PlanarProjection(this._patch, heightRange) + : new EllipsoidProjection(this._patch, heightRange); } /** @internal */ @@ -713,8 +833,11 @@ export class MapTile extends RealityTile { if (imageryTile.texture) { drapeTextures.push(this.computeDrapeTexture(thisRectangle, thisDiagonal, imageryTile, imageryTile.rectangle)); - if ((bordersNorthPole && imageryTile.quadId.bordersNorthPole(imageryTile.tilingScheme) && imageryTile.rectangle.high.y < thisRectangle.high.y) || - (bordersSouthPole && imageryTile.quadId.bordersSouthPole(imageryTile.tilingScheme) && imageryTile.rectangle.low.y > thisRectangle.low.y)) { + if ( + (bordersNorthPole && imageryTile.quadId.bordersNorthPole(imageryTile.tilingScheme) && + imageryTile.rectangle.high.y < thisRectangle.high.y) || + (bordersSouthPole && imageryTile.quadId.bordersSouthPole(imageryTile.tilingScheme) && imageryTile.rectangle.low.y > thisRectangle.low.y) + ) { // Add separate texture stretching last sliver of tile imagery to cover pole. const sliverRectangle = imageryTile.rectangle.clone(MapTile._scratchRectangle1); const clipRectangle = thisRectangle.clone(MapTile._scratchRectangle2); @@ -748,28 +871,50 @@ export class MapTile extends RealityTile { private static _scratchIntersectRange = Range2d.createNull(); - private computeDrapeTexture(thisRectangle: Range2d, thisDiagonal: Vector2d, imageryTile: ImageryMapTile, drapeRectangle: Range2d, clipRectangle?: Range2d): TerrainTexture { + private computeDrapeTexture( + thisRectangle: Range2d, + thisDiagonal: Vector2d, + imageryTile: ImageryMapTile, + drapeRectangle: Range2d, + clipRectangle?: Range2d, + ): TerrainTexture { assert(imageryTile.texture !== undefined); // Compute transformation from the terrain tile texture coordinates (0-1) to the drape tile texture coordinates. const drapeDiagonal = drapeRectangle.diagonal(MapTile._scratchDrapeDiagonal); - const translate = Vector2d.create((thisRectangle.low.x - drapeRectangle.low.x) / drapeDiagonal.x, (thisRectangle.low.y - drapeRectangle.low.y) / drapeDiagonal.y); + const translate = Vector2d.create( + (thisRectangle.low.x - drapeRectangle.low.x) / drapeDiagonal.x, + (thisRectangle.low.y - drapeRectangle.low.y) / drapeDiagonal.y, + ); const scale = Vector2d.create(thisDiagonal.x / drapeDiagonal.x, thisDiagonal.y / drapeDiagonal.y); const featureIndex = this.mapLoader.getFeatureIndex(imageryTile.imageryTree.modelId); let clipRect; if (undefined !== clipRectangle) { const intersect = clipRectangle.intersect(drapeRectangle, MapTile._scratchIntersectRange); assert(!intersect.isNull); - clipRect = Range2d.createXYXY((intersect.low.x - drapeRectangle.low.x) / drapeDiagonal.x, (intersect.low.y - drapeRectangle.low.y) / drapeDiagonal.y, (intersect.high.x - drapeRectangle.low.x) / drapeDiagonal.x, (intersect.high.y - drapeRectangle.low.y) / drapeDiagonal.y); + clipRect = Range2d.createXYXY( + (intersect.low.x - drapeRectangle.low.x) / drapeDiagonal.x, + (intersect.low.y - drapeRectangle.low.y) / drapeDiagonal.y, + (intersect.high.x - drapeRectangle.low.x) / drapeDiagonal.x, + (intersect.high.y - drapeRectangle.low.y) / drapeDiagonal.y, + ); } const imageryModelId = imageryTile.tree.modelId; - return new TerrainTexture(imageryTile.texture, featureIndex, scale, translate, drapeRectangle, this.mapTree.getLayerIndex(imageryModelId), this.mapTree.getLayerTransparency(imageryModelId), clipRect); + return new TerrainTexture( + imageryTile.texture, + featureIndex, + scale, + translate, + drapeRectangle, + this.mapTree.getLayerIndex(imageryModelId), + this.mapTree.getLayerTransparency(imageryModelId), + clipRect, + ); } /** @internal */ public override setContent(content: TerrainTileContent): void { - if (this.quadId.level < this.maxDepth) { const childIds = this.quadId.getChildIds(); for (const childId of childIds) { @@ -786,7 +931,6 @@ export class MapTile extends RealityTile { const transform = geometryTransform ? iModelTransform.multiplyTransformTransform(geometryTransform) : iModelTransform; const polyface = content.terrain?.mesh ? RealityMeshParams.toPolyface(content.terrain.mesh, { transform }) : undefined; this._geometry = polyface ? { polyfaces: [polyface] } : undefined; - } else { dispose(this._renderGeometry); this._renderGeometry = content.terrain?.renderGeometry; @@ -816,19 +960,34 @@ export class MapTile extends RealityTile { /** A child tile that has no content of its own available. It instead produces content by up-sampling the content of an ancestor tile. * @internal - */ + */ export class UpsampledMapTile extends MapTile { /** The ancestor tile whose content will be up-sampled. */ private readonly _loadableTile: MapTile; - constructor(params: RealityTileParams, mapTree: MapTileTree, quadId: QuadId, patch: TilePatch, rectangle: MapCartoRectangle, heightRange: Range1d | undefined, cornerRays: Ray3d[] | undefined, loadableTile: MapTile) { + constructor( + params: RealityTileParams, + mapTree: MapTileTree, + quadId: QuadId, + patch: TilePatch, + rectangle: MapCartoRectangle, + heightRange: Range1d | undefined, + cornerRays: Ray3d[] | undefined, + loadableTile: MapTile, + ) { super(params, mapTree, quadId, patch, rectangle, heightRange, cornerRays); this._loadableTile = loadableTile; } - public override get isUpsampled() { return true; } - public override get isEmpty() { return false; } - public override get loadableTile(): RealityTile { return this._loadableTile; } + public override get isUpsampled() { + return true; + } + public override get isEmpty() { + return false; + } + public override get loadableTile(): RealityTile { + return this._loadableTile; + } private upsampleFromParent() { const parent = this.loadableTerrainTile; @@ -857,10 +1016,18 @@ export class UpsampledMapTile extends MapTile { return this._renderGeometry; } - public override get isLoading(): boolean { return this.loadableTile.isLoading; } - public override get isQueued(): boolean { return this.loadableTile.isQueued; } - public override get isNotFound(): boolean { return this.loadableTile.isNotFound; } - public override get isReady(): boolean { return (this._renderGeometry !== undefined || this.loadableTile.loadStatus === TileLoadStatus.Ready) && this.baseImageryIsReady; } + public override get isLoading(): boolean { + return this.loadableTile.isLoading; + } + public override get isQueued(): boolean { + return this.loadableTile.isQueued; + } + public override get isNotFound(): boolean { + return this.loadableTile.isNotFound; + } + public override get isReady(): boolean { + return (this._renderGeometry !== undefined || this.loadableTile.loadStatus === TileLoadStatus.Ready) && this.baseImageryIsReady; + } public override markUsed(args: TileDrawArgs): void { args.markUsed(this); diff --git a/core/frontend/src/tile/map/MapTileAvailability.ts b/core/frontend/src/tile/map/MapTileAvailability.ts index 1c43eeb54b70..a49f3ef83e82 100644 --- a/core/frontend/src/tile/map/MapTileAvailability.ts +++ b/core/frontend/src/tile/map/MapTileAvailability.ts @@ -6,9 +6,9 @@ * @module Tiles */ +import { SortedArray } from "@itwin/core-bentley"; import { Cartographic } from "@itwin/core-common"; import { MapCartoRectangle, MapTilingScheme } from "../internal"; -import { SortedArray } from "@itwin/core-bentley"; // portions adapted from Cesium.js Copyright 2011 - 2017 Cesium Contributors /** @internal */ @@ -26,7 +26,13 @@ class QuadTreeNode { public neNode?: QuadTreeNode; public extent: MapCartoRectangle; public rectangles = new SortedArray((lhs: RectangleWithLevel, rhs: RectangleWithLevel) => lhs.level - rhs.level, true); - constructor(public tilingScheme: MapTilingScheme, public parent: QuadTreeNode | undefined, public level: number, public x: number, public y: number) { + constructor( + public tilingScheme: MapTilingScheme, + public parent: QuadTreeNode | undefined, + public level: number, + public x: number, + public y: number, + ) { this.extent = tilingScheme.tileXYToRectangle(x, y, level + 1); } public get nw(): QuadTreeNode { @@ -77,7 +83,7 @@ function putRectangleInQuadtree(maxDepth: number, node: QuadTreeNode, rectangle: /** @internal */ export class TileAvailability { private _rootNodes = new Array(); - constructor(private _tilingScheme: MapTilingScheme, private _maximumLevel: number) { } + constructor(private _tilingScheme: MapTilingScheme, private _maximumLevel: number) {} public static rectangleScratch = MapCartoRectangle.createMaximum(); diff --git a/core/frontend/src/tile/map/MapTileLoader.ts b/core/frontend/src/tile/map/MapTileLoader.ts index 50a9f0d54169..8c06eccf5054 100644 --- a/core/frontend/src/tile/map/MapTileLoader.ts +++ b/core/frontend/src/tile/map/MapTileLoader.ts @@ -7,27 +7,51 @@ */ import { assert, Id64String } from "@itwin/core-bentley"; -import { Polyface, Range1d } from "@itwin/core-geometry"; import { Feature, FeatureTable } from "@itwin/core-common"; -import { IModelConnection } from "../../IModelConnection"; +import { Polyface, Range1d } from "@itwin/core-geometry"; import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; import { RenderSystem } from "../../render/RenderSystem"; -import { MapCartoRectangle, MapTile, QuadId, RealityTile, RealityTileLoader, TerrainMeshProvider, TerrainTileContent, Tile, TileLoadPriority, TileRequest } from "../internal"; +import { + MapCartoRectangle, + MapTile, + QuadId, + RealityTile, + RealityTileLoader, + TerrainMeshProvider, + TerrainTileContent, + Tile, + TileLoadPriority, + TileRequest, +} from "../internal"; /** Specialization of map tile loader that includes terrain geometry with map imagery draped on it. * @internal */ export class MapTileLoader extends RealityTileLoader { - public get priority(): TileLoadPriority { return TileLoadPriority.Terrain; } - public get clipLowResolutionTiles(): boolean { return true; } + public get priority(): TileLoadPriority { + return TileLoadPriority.Terrain; + } + public get clipLowResolutionTiles(): boolean { + return true; + } protected _applyLights = false; public readonly featureTable: FeatureTable; // public get heightRange(): Range1d | undefined { return this._heightRange; } protected readonly _heightRange: Range1d | undefined; - public override get isContentUnbounded(): boolean { return true; } - public isTileAvailable(quadId: QuadId) { return this.terrainProvider.isTileAvailable(quadId); } + public override get isContentUnbounded(): boolean { + return true; + } + public isTileAvailable(quadId: QuadId) { + return this.terrainProvider.isTileAvailable(quadId); + } - public constructor(protected _iModel: IModelConnection, protected _modelId: Id64String, protected _groundBias: number, private _terrainProvider: TerrainMeshProvider) { + public constructor( + protected _iModel: IModelConnection, + protected _modelId: Id64String, + protected _groundBias: number, + private _terrainProvider: TerrainMeshProvider, + ) { super(); this.featureTable = new FeatureTable(0xffff, this._modelId); this.featureTable.insert(new Feature(this._modelId)); @@ -36,9 +60,15 @@ export class MapTileLoader extends RealityTileLoader { return this.featureTable.insert(new Feature(layerModelId)); } - public get maxDepth(): number { return this._terrainProvider.maxDepth; } - public get minDepth(): number { return 0; } - public get terrainProvider(): TerrainMeshProvider { return this._terrainProvider; } + public get maxDepth(): number { + return this._terrainProvider.maxDepth; + } + public get minDepth(): number { + return 0; + } + public get terrainProvider(): TerrainMeshProvider { + return this._terrainProvider; + } public getRequestChannel(_tile: Tile) { // ###TODO use hostname from url - but so many layers to go through to get that... @@ -59,7 +89,12 @@ export class MapTileLoader extends RealityTileLoader { return this._terrainProvider.forceTileLoad(tile); } - public override async loadTileContent(tile: MapTile, data: TileRequest.ResponseData, system: RenderSystem, isCanceled?: () => boolean): Promise { + public override async loadTileContent( + tile: MapTile, + data: TileRequest.ResponseData, + system: RenderSystem, + isCanceled?: () => boolean, + ): Promise { assert("data" in data); isCanceled = isCanceled ?? (() => !tile.isLoading); @@ -72,12 +107,12 @@ export class MapTileLoader extends RealityTileLoader { return { contentRange: projection.transformFromLocal.multiplyRange(projection.localRange), - terrain: {mesh, renderGeometry: terrainGeometry}, + terrain: { mesh, renderGeometry: terrainGeometry }, }; } public loadPolyfaces(): Polyface[] | undefined { - assert (false, "load polyFaces not implmented for map tiles"); + assert(false, "load polyFaces not implmented for map tiles"); } public getChildHeightRange(quadId: QuadId, rectangle: MapCartoRectangle, parent: MapTile): Range1d | undefined { diff --git a/core/frontend/src/tile/map/MapTileTree.ts b/core/frontend/src/tile/map/MapTileTree.ts index a278b8c2b60b..d444e912dba7 100644 --- a/core/frontend/src/tile/map/MapTileTree.ts +++ b/core/frontend/src/tile/map/MapTileTree.ts @@ -6,33 +6,104 @@ * @module Tiles */ -import { assert, compareBooleans, compareBooleansOrUndefined, compareNumbers, compareStrings, compareStringsOrUndefined, CompressedId64Set, Id64String } from "@itwin/core-bentley"; import { - BackgroundMapSettings, BaseLayerSettings, Cartographic, ColorDef, FeatureAppearance, GeoCoordStatus, GlobeMode, MapLayerSettings, PlanarClipMaskPriority, TerrainHeightOriginMode, + assert, + compareBooleans, + compareBooleansOrUndefined, + compareNumbers, + compareStrings, + compareStringsOrUndefined, + CompressedId64Set, + Id64String, +} from "@itwin/core-bentley"; +import { + BackgroundMapSettings, + BaseLayerSettings, + Cartographic, + ColorDef, + FeatureAppearance, + GeoCoordStatus, + GlobeMode, + MapLayerSettings, + PlanarClipMaskPriority, + TerrainHeightOriginMode, } from "@itwin/core-common"; import { - Angle, AngleSweep, Constant, Ellipsoid, EllipsoidPatch, Point3d, Range1d, Range3d, Ray3d, Transform, Vector3d, XYZProps, + Angle, + AngleSweep, + Constant, + Ellipsoid, + EllipsoidPatch, + Point3d, + Range1d, + Range3d, + Ray3d, + Transform, + Vector3d, + XYZProps, } from "@itwin/core-geometry"; import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; import { TerrainDisplayOverrides } from "../../DisplayStyleState"; import { HitDetail } from "../../HitDetail"; -import { IModelConnection } from "../../IModelConnection"; import { IModelApp } from "../../IModelApp"; +import { IModelConnection } from "../../IModelConnection"; import { PlanarClipMaskState } from "../../PlanarClipMaskState"; import { FeatureSymbology } from "../../render/FeatureSymbology"; import { RenderPlanarClassifier } from "../../render/RenderPlanarClassifier"; import { SceneContext } from "../../ViewContext"; import { MapLayerScaleRangeVisibility, ScreenViewport } from "../../Viewport"; import { - BingElevationProvider, createDefaultViewFlagOverrides, createMapLayerTreeReference, DisclosedTileTreeSet, EllipsoidTerrainProvider, GeometryTileTreeReference, - GraphicsCollectorDrawArgs, ImageryMapLayerTreeReference, ImageryMapTileTree, ImageryTileTreeState, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProvider, MapLayerIndex, MapLayerTileTreeReference, MapTile, - MapTileLoader, MapTilingScheme, ModelMapLayerTileTreeReference, PlanarTilePatch, QuadId, - RealityTile, RealityTileDrawArgs, RealityTileTree, RealityTileTreeParams, TerrainMeshProviderOptions, Tile, TileDrawArgs, TileLoadPriority, TileParams, TileTree, - TileTreeLoadStatus, TileTreeOwner, TileTreeReference, TileTreeSupplier, UpsampledMapTile, WebMercatorTilingScheme, + BingElevationProvider, + createDefaultViewFlagOverrides, + createMapLayerTreeReference, + DisclosedTileTreeSet, + EllipsoidTerrainProvider, + GeometryTileTreeReference, + GraphicsCollectorDrawArgs, + ImageryMapLayerTreeReference, + ImageryMapTileTree, + ImageryTileTreeState, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapLayerImageryProvider, + MapLayerIndex, + MapLayerTileTreeReference, + MapTile, + MapTileLoader, + MapTilingScheme, + ModelMapLayerTileTreeReference, + PlanarTilePatch, + QuadId, + RealityTile, + RealityTileDrawArgs, + RealityTileTree, + RealityTileTreeParams, + TerrainMeshProviderOptions, + Tile, + TileDrawArgs, + TileLoadPriority, + TileParams, + TileTree, + TileTreeLoadStatus, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, + UpsampledMapTile, + WebMercatorTilingScheme, } from "../internal"; const scratchPoint = Point3d.create(); -const scratchCorners = [Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero(), Point3d.createZero()]; +const scratchCorners = [ + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), + Point3d.createZero(), +]; const scratchCorner = Point3d.createZero(); const scratchZNormal = Vector3d.create(0, 0, 1); @@ -58,13 +129,13 @@ export enum MapTileTreeScaleRangeVisibility { Hidden, /** currently selected tree tiles are partially visible (i.e some tiles are within the scale range, and some are outside.) */ - Partial + Partial, } /** -* Provides map layer information for a given tile tree. -* @internal -*/ + * Provides map layer information for a given tile tree. + * @internal + */ export interface MapLayerInfoFromTileTree { /** Indicate if the map layer represents the base layer */ isBaseLayer: boolean; @@ -135,8 +206,15 @@ export class MapTileTree extends RealityTileTree { public layerClassifiers = new Map(); /** @internal */ - constructor(params: RealityTileTreeParams, ecefToDb: Transform, bimElevationBias: number, geodeticOffset: number, - sourceTilingScheme: MapTilingScheme, id: MapTreeId, applyTerrain: boolean) { + constructor( + params: RealityTileTreeParams, + ecefToDb: Transform, + bimElevationBias: number, + geodeticOffset: number, + sourceTilingScheme: MapTilingScheme, + id: MapTreeId, + applyTerrain: boolean, + ) { super(params); this.ecefToDb = ecefToDb; this.bimElevationBias = bimElevationBias; @@ -146,7 +224,13 @@ export class MapTileTree extends RealityTileTree { this._mercatorFractionToDb = this._mercatorTilingScheme.computeMercatorFractionToDb(ecefToDb, bimElevationBias, params.iModel, applyTerrain); const quadId = new QuadId(sourceTilingScheme.rootLevel, 0, 0); this.globeOrigin = this.ecefToDb.getOrigin().clone(); - this.earthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.equator, Constant.earthRadiusWGS84.polar); + this.earthEllipsoid = Ellipsoid.createCenterMatrixRadii( + this.globeOrigin, + this.ecefToDb.matrix, + Constant.earthRadiusWGS84.equator, + Constant.earthRadiusWGS84.equator, + Constant.earthRadiusWGS84.polar, + ); const globalHeightRange = applyTerrain ? ApproximateTerrainHeights.instance.globalHeightRange : Range1d.createXX(0, 0); const globalRectangle = MapCartoRectangle.createMaximum(); @@ -158,8 +242,20 @@ export class MapTileTree extends RealityTileTree { this.baseTransparent = id.baseTransparent; this.mapTransparent = id.mapTransparent; if (applyTerrain) { - this.minEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.equator + globalHeightRange.low, Constant.earthRadiusWGS84.polar + globalHeightRange.low); - this.maxEarthEllipsoid = Ellipsoid.createCenterMatrixRadii(this.globeOrigin, this.ecefToDb.matrix, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.equator + globalHeightRange.high, Constant.earthRadiusWGS84.polar + globalHeightRange.high); + this.minEarthEllipsoid = Ellipsoid.createCenterMatrixRadii( + this.globeOrigin, + this.ecefToDb.matrix, + Constant.earthRadiusWGS84.equator + globalHeightRange.low, + Constant.earthRadiusWGS84.equator + globalHeightRange.low, + Constant.earthRadiusWGS84.polar + globalHeightRange.low, + ); + this.maxEarthEllipsoid = Ellipsoid.createCenterMatrixRadii( + this.globeOrigin, + this.ecefToDb.matrix, + Constant.earthRadiusWGS84.equator + globalHeightRange.high, + Constant.earthRadiusWGS84.equator + globalHeightRange.high, + Constant.earthRadiusWGS84.polar + globalHeightRange.high, + ); this.produceGeometry = id.produceGeometry; } else { this.minEarthEllipsoid = this.earthEllipsoid; @@ -167,7 +263,8 @@ export class MapTileTree extends RealityTileTree { } const rootPatch = EllipsoidPatch.createCapture( - this.maxEarthEllipsoid, AngleSweep.createStartSweepRadians(0, Angle.pi2Radians), + this.maxEarthEllipsoid, + AngleSweep.createStartSweepRadians(0, Angle.pi2Radians), AngleSweep.createStartSweepRadians(-Angle.piOver2Radians, Angle.piRadians), ); @@ -180,7 +277,14 @@ export class MapTileTree extends RealityTileTree { range = Range3d.createArray(MapTile.computeRangeCorners(corners, Vector3d.create(0, 0, 1), 0, scratchCorners, globalHeightRange)); } - this._rootTile = this.createGlobeChild({ contentId: quadId.contentId, maximumSize: 0, range }, quadId, range.corners(), globalRectangle, rootPatch, undefined); + this._rootTile = this.createGlobeChild( + { contentId: quadId.contentId, maximumSize: 0, range }, + quadId, + range.corners(), + globalRectangle, + rootPatch, + undefined, + ); } /** @internal */ @@ -237,8 +341,12 @@ export class MapTileTree extends RealityTileTree { this.layerClassifiers.forEach((layerClassifier: RenderPlanarClassifier) => { if (!(args instanceof GraphicsCollectorDrawArgs)) - layerClassifier.collectGraphics(args.context, { modelId: this.modelId, tiles: selectedTiles, location: args.location, isPointCloud: this.isPointCloud }); - + layerClassifier.collectGraphics(args.context, { + modelId: this.modelId, + tiles: selectedTiles, + location: args.location, + isPointCloud: this.isPointCloud, + }); }); } @@ -264,7 +372,15 @@ export class MapTileTree extends RealityTileTree { } /** @internal */ - public createPlanarChild(params: TileParams, quadId: QuadId, corners: Point3d[], normal: Vector3d, rectangle: MapCartoRectangle, chordHeight: number, heightRange?: Range1d): MapTile | undefined { + public createPlanarChild( + params: TileParams, + quadId: QuadId, + corners: Point3d[], + normal: Vector3d, + rectangle: MapCartoRectangle, + chordHeight: number, + heightRange?: Range1d, + ): MapTile | undefined { const childAvailable = this.mapLoader.isTileAvailable(quadId); if (!childAvailable && this.produceGeometry) return undefined; @@ -284,7 +400,14 @@ export class MapTileTree extends RealityTileTree { } /** @internal */ - public createGlobeChild(params: TileParams, quadId: QuadId, _rangeCorners: Point3d[], rectangle: MapCartoRectangle, ellipsoidPatch: EllipsoidPatch, heightRange?: Range1d): MapTile { + public createGlobeChild( + params: TileParams, + quadId: QuadId, + _rangeCorners: Point3d[], + rectangle: MapCartoRectangle, + ellipsoidPatch: EllipsoidPatch, + heightRange?: Range1d, + ): MapTile { return new MapTile(params, this, quadId, ellipsoidPatch, rectangle, heightRange, this.getCornerRays(rectangle)); } @@ -307,7 +430,9 @@ export class MapTileTree extends RealityTileTree { /** @internal */ public static minDisplayableDepth = 3; /** @internal */ - public get mapLoader() { return this.loader as MapTileLoader; } + public get mapLoader() { + return this.loader as MapTileLoader; + } /** @internal */ public override getBaseRealityDepth(sceneContext: SceneContext) { @@ -321,10 +446,10 @@ export class MapTileTree extends RealityTileTree { return false; const childDepth = tile.depth + 1; - if (childDepth < MapTileTree.maxGlobeDisplayDepth) // If the depth is too low (tile is too large) display as globe. + if (childDepth < MapTileTree.maxGlobeDisplayDepth) // If the depth is too low (tile is too large) display as globe. return true; - return false; // Display as globe if more than 100 KM from project. + return false; // Display as globe if more than 100 KM from project. } /** @internal */ @@ -333,7 +458,7 @@ export class MapTileTree extends RealityTileTree { return false; const childDepth = tile.depth + 1; - if (childDepth < MapTileTree.minReprojectionDepth) // If the depth is too low (tile is too large) omit reprojection. + if (childDepth < MapTileTree.minReprojectionDepth) // If the depth is too low (tile is too large) omit reprojection. return false; return this.cartesianRange.intersectsRange(tile.range); @@ -349,10 +474,18 @@ export class MapTileTree extends RealityTileTree { rays.push(this.earthEllipsoid.radiansToUnitNormalRay(rectangle.high.x, Cartographic.parametricLatitudeFromGeodeticLatitude(rectangle.low.y))!); } else { const mercatorFractionRange = rectangle.getTileFractionRange(this._mercatorTilingScheme); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.high.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.high.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.low.y), scratchZNormal)); - rays.push(Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.low.y), scratchZNormal)); + rays.push( + Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.high.y), scratchZNormal), + ); + rays.push( + Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.high.y), scratchZNormal), + ); + rays.push( + Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.low.x, mercatorFractionRange.low.y), scratchZNormal), + ); + rays.push( + Ray3d.createCapture(this._mercatorFractionToDb.multiplyXYZ(mercatorFractionRange.high.x, mercatorFractionRange.low.y), scratchZNormal), + ); } return rays; } @@ -375,9 +508,10 @@ export class MapTileTree extends RealityTileTree { } } // If not mercator already need to remap latitude... - if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) + if (!(this.sourceTilingScheme instanceof WebMercatorTilingScheme)) { for (const gridPoint of gridPoints) gridPoint.y = this._mercatorTilingScheme.latitudeToYFraction(this.sourceTilingScheme.yFractionToLatitude(gridPoint.y)); + } return gridPoints; } @@ -418,8 +552,14 @@ export class MapTileTree extends RealityTileTree { */ public async loadReprojectionCache(tile: MapTile): Promise { const quadId = tile.quadId; - const xRange = Range1d.createXX(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level)); - const yRange = Range1d.createXX(this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level)); + const xRange = Range1d.createXX( + this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), + this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), + ); + const yRange = Range1d.createXX( + this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), + this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), + ); const cacheDepth = 4, cacheDimension = 2 ** cacheDepth; const delta = 1.0 / cacheDimension; const requestProps = []; @@ -458,7 +598,11 @@ export class MapTileTree extends RealityTileTree { scratchCorner.clone(gridPoint); } else { this._mercatorTilingScheme.fractionToCartographic(gridPoint.x, gridPoint.y, MapTileTree._scratchCarto); - this.earthEllipsoid.radiansToPoint(MapTileTree._scratchCarto.longitude, Cartographic.parametricLatitudeFromGeodeticLatitude(MapTileTree._scratchCarto.latitude), gridPoint); + this.earthEllipsoid.radiansToPoint( + MapTileTree._scratchCarto.longitude, + Cartographic.parametricLatitudeFromGeodeticLatitude(MapTileTree._scratchCarto.latitude), + gridPoint, + ); const cartesianDistance = this.cartesianRange.distanceToPoint(scratchCorner); if (cartesianDistance < this.cartesianTransitionDistance) scratchCorner.interpolate(cartesianDistance / this.cartesianTransitionDistance, gridPoint, gridPoint); @@ -479,7 +623,7 @@ export class MapTileTree extends RealityTileTree { // be reloaded without expensive reprojection requests. this.loadReprojectionCache(tile).then(() => { const reprojected = this.getCachedReprojectedPoints(gridPoints); - assert(reprojected !== undefined); // We just cached them... they better be there now. + assert(reprojected !== undefined); // We just cached them... they better be there now. resolveCorners(gridPoints, reprojected); }).catch((_error: Error) => { resolveCorners(gridPoints); @@ -495,7 +639,6 @@ export class MapTileTree extends RealityTileTree { * @internal */ public override reportTileVisibility(args: TileDrawArgs, selected: RealityTile[]) { - const debugControl = args.context.target.debugControl; const layersVisibilityBefore = this.cloneImageryTreeState(); @@ -516,7 +659,9 @@ export class MapTileTree extends RealityTileTree { if (selectedTile instanceof MapTile) { let selectedImageryTiles = selectedTile.imageryTiles; if (selectedTile.hiddenImageryTiles) { - selectedImageryTiles = selectedImageryTiles ? [...selectedImageryTiles, ...selectedTile.hiddenImageryTiles] : selectedTile.hiddenImageryTiles; + selectedImageryTiles = selectedImageryTiles + ? [...selectedImageryTiles, ...selectedTile.hiddenImageryTiles] + : selectedTile.hiddenImageryTiles; } const leafTiles = selectedTile.highResolutionReplacementTiles; @@ -537,7 +682,6 @@ export class MapTileTree extends RealityTileTree { treeState.setScaleRangeVisibility(true); } } - } } } @@ -546,21 +690,22 @@ export class MapTileTree extends RealityTileTree { for (const [treeId, prevState] of layersVisibilityBefore) { const newState = this.getImageryTreeState(treeId); if (newState) { - const prevVisibility = prevState.getScaleRangeVisibility(); const visibility = newState.getScaleRangeVisibility(); if (prevVisibility !== visibility) { - if (debugControl && debugControl.logRealityTiles) { // eslint-disable-next-line no-console - console.log(`ImageryTileTree '${treeId}' changed prev state: '${MapTileTreeScaleRangeVisibility[prevVisibility]}' new state: '${MapTileTreeScaleRangeVisibility[visibility]}'`); + console.log( + `ImageryTileTree '${treeId}' changed prev state: '${MapTileTreeScaleRangeVisibility[prevVisibility]}' new state: '${ + MapTileTreeScaleRangeVisibility[visibility] + }'`, + ); } const mapLayersIndexes = args.context.viewport.getMapLayerIndexesFromIds(this.id, treeId); for (const index of mapLayersIndexes) { changes.push({ index: index.index, isOverlay: index.isOverlay, visibility }); } - } } } @@ -568,16 +713,39 @@ export class MapTileTree extends RealityTileTree { if (changes.length !== 0) { args.context.viewport.onMapLayerScaleRangeVisibilityChanged.raiseEvent(changes); } - } /** @internal */ public getFractionalTileCorners(quadId: QuadId): Point3d[] { const corners: Point3d[] = []; - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); - corners.push(Point3d.create(this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), 0.0)); + corners.push( + Point3d.create( + this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), + this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), + 0.0, + ), + ); + corners.push( + Point3d.create( + this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), + this.sourceTilingScheme.tileYToFraction(quadId.row, quadId.level), + 0.0, + ), + ); + corners.push( + Point3d.create( + this.sourceTilingScheme.tileXToFraction(quadId.column, quadId.level), + this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), + 0.0, + ), + ); + corners.push( + Point3d.create( + this.sourceTilingScheme.tileXToFraction(quadId.column + 1, quadId.level), + this.sourceTilingScheme.tileYToFraction(quadId.row + 1, quadId.level), + 0.0, + ), + ); return corners; } @@ -631,7 +799,9 @@ class MapTileTreeProps implements RealityTileTreeParams { public rootTile = { contentId: "", range: Range3d.createNull(), maximumSize: 0 }; public loader: MapTileLoader; public iModel: IModelConnection; - public get priority(): TileLoadPriority { return this.loader.priority; } + public get priority(): TileLoadPriority { + return this.loader.priority; + } public constructor(modelId: Id64String, loader: MapTileLoader, iModel: IModelConnection, public gcsConverterAvailable: boolean) { this.id = this.modelId = modelId; @@ -705,7 +875,13 @@ class MapTreeSupplier implements TileTreeSupplier { return cmp; } - private async computeHeightBias(heightOrigin: number, heightOriginMode: TerrainHeightOriginMode, exaggeration: number, iModel: IModelConnection, elevationProvider: BingElevationProvider): Promise { + private async computeHeightBias( + heightOrigin: number, + heightOriginMode: TerrainHeightOriginMode, + exaggeration: number, + iModel: IModelConnection, + elevationProvider: BingElevationProvider, + ): Promise { const projectCenter = iModel.projectExtents.center; switch (heightOriginMode) { case TerrainHeightOriginMode.Ground: @@ -736,7 +912,13 @@ class MapTreeSupplier implements TileTreeSupplier { await ApproximateTerrainHeights.instance.initialize(); const elevationProvider = new BingElevationProvider(); - bimElevationBias = - await this.computeHeightBias(id.terrainHeightOrigin, id.terrainHeightOriginMode, id.terrainExaggeration, iModel, elevationProvider); + bimElevationBias = -await this.computeHeightBias( + id.terrainHeightOrigin, + id.terrainHeightOriginMode, + id.terrainExaggeration, + iModel, + elevationProvider, + ); geodeticOffset = await elevationProvider.getGeodeticToSeaLevelOffset(iModel.projectExtents.center, iModel); const provider = IModelApp.terrainProviderRegistry.find(id.terrainProviderName); if (provider) @@ -791,7 +973,8 @@ export class MapTileTreeReference extends TileTreeReference { tileUserId: number, public isOverlay: boolean, private _isDrape: boolean, - private _overrideTerrainDisplay?: CheckTerrainDisplayOverride) { + private _overrideTerrainDisplay?: CheckTerrainDisplayOverride, + ) { super(); this._tileUserId = tileUserId; this._settings = settings; @@ -807,7 +990,7 @@ export class MapTileTreeReference extends TileTreeReference { } } - if (this._baseImageryLayerIncluded = (undefined !== tree)) + if (this._baseImageryLayerIncluded = undefined !== tree) this._layerTrees.push(tree); for (let i = 0; i < this._layerSettings.length; i++) @@ -828,13 +1011,19 @@ export class MapTileTreeReference extends TileTreeReference { } } - public override get isGlobal() { return true; } - public get baseColor(): ColorDef | undefined { return this._baseColor; } - public override get planarClipMaskPriority(): number { return PlanarClipMaskPriority.BackgroundMap; } + public override get isGlobal() { + return true; + } + public get baseColor(): ColorDef | undefined { + return this._baseColor; + } + public override get planarClipMaskPriority(): number { + return PlanarClipMaskPriority.BackgroundMap; + } protected override _createGeometryTreeReference(): GeometryTileTreeReference | undefined { if (!this._settings.applyTerrain || this._isDrape) - return undefined; // Don't bother generating non-terrain (flat) geometry. + return undefined; // Don't bother generating non-terrain (flat) geometry. const ref = new MapTileTreeReference(this._settings, undefined, [], this._iModel, this._tileUserId, false, false, () => { return { produceGeometry: true }; @@ -845,8 +1034,10 @@ export class MapTileTreeReference extends TileTreeReference { } /** Terrain tiles do not contribute to the range used by "fit view". */ - public override unionFitRange(_range: Range3d): void { } - public get settings(): BackgroundMapSettings { return this._settings; } + public override unionFitRange(_range: Range3d): void {} + public get settings(): BackgroundMapSettings { + return this._settings; + } public set settings(settings: BackgroundMapSettings) { this._settings = settings; this._planarClipMask = settings.planarClipMask ? PlanarClipMaskState.create(settings.planarClipMask) : undefined; @@ -885,7 +1076,7 @@ export class MapTileTreeReference extends TileTreeReference { this._layerSettings = layerSettings; const baseLayerIndex = this._baseImageryLayerIncluded ? 1 : 0; - this._layerTrees.length = Math.min(layerSettings.length + baseLayerIndex, this._layerTrees.length); // Truncate if number of layers reduced. + this._layerTrees.length = Math.min(layerSettings.length + baseLayerIndex, this._layerTrees.length); // Truncate if number of layers reduced. for (let i = 0; i < layerSettings.length; i++) { const treeIndex = i + baseLayerIndex; if (treeIndex >= this._layerTrees.length || !this._layerTrees[treeIndex]?.layerSettings.displayMatches(layerSettings[i])) @@ -920,7 +1111,7 @@ export class MapTileTreeReference extends TileTreeReference { let wantSkirts = (this.settings.applyTerrain || this.useDepthBuffer) && !this.settings.transparency && !this._baseTransparent; if (wantSkirts) { const maskTrans = this._planarClipMask?.settings.transparency; - wantSkirts = (undefined === maskTrans || maskTrans <= 0); + wantSkirts = undefined === maskTrans || maskTrans <= 0; } const id: MapTreeId = { @@ -963,8 +1154,8 @@ export class MapTileTreeReference extends TileTreeReference { } /** Return the map-layer scale range visibility for the provided map-layer index. - * @internal - */ + * @internal + */ public getMapLayerScaleRangeVisibility(index: number): MapTileTreeScaleRangeVisibility { const tree = this.treeOwner.tileTree as MapTileTree; if (undefined !== tree) { @@ -983,7 +1174,7 @@ export class MapTileTreeReference extends TileTreeReference { let hasLoadedTileTree = false; const tree = this.treeOwner.load() as MapTileTree; if (undefined === tree) { - return hasLoadedTileTree; // Not loaded yet. + return hasLoadedTileTree; // Not loaded yet. } tree.layerImageryTrees.length = 0; @@ -996,19 +1187,21 @@ export class MapTileTreeReference extends TileTreeReference { for (; treeIndex >= 1; treeIndex--) { const layerTreeRef = this._layerTrees[treeIndex]; if (layerTreeRef?.isOpaque) - break; // This layer is completely opaque and will obscure all others so ignore lower ones. + break; // This layer is completely opaque and will obscure all others so ignore lower ones. } for (; treeIndex < this._layerTrees.length; treeIndex++) { const layerTreeRef = this._layerTrees[treeIndex]; const hasValidTileTree = layerTreeRef && TileTreeLoadStatus.NotFound !== layerTreeRef.treeOwner.loadStatus; const isImageryMapLayer = layerTreeRef instanceof ImageryMapLayerTreeReference; - const isLayerVisible = (isImageryMapLayer || (!isImageryMapLayer && layerTreeRef?.layerSettings.visible)); + const isLayerVisible = isImageryMapLayer || (!isImageryMapLayer && layerTreeRef?.layerSettings.visible); // Load tile tree for each configured layer. // Note: Non-visible imagery layer are always added to allow proper tile tree scale range visibility reporting. - if (hasValidTileTree + if ( + hasValidTileTree && isLayerVisible - && !layerTreeRef.layerSettings.allSubLayersInvisible) { + && !layerTreeRef.layerSettings.allSubLayersInvisible + ) { const layerTree = layerTreeRef.treeOwner.load(); if (layerTree !== undefined) { hasLoadedTileTree = true; @@ -1036,7 +1229,7 @@ export class MapTileTreeReference extends TileTreeReference { const tree = this.treeOwner.load() as MapTileTree; if (undefined === tree || !this.initializeLayers(context)) - return; // Not loaded yet. + return; // Not loaded yet. if (this._planarClipMask && this._planarClipMask.settings.isValid) context.addPlanarClassifier(tree.modelId, undefined, this._planarClipMask); @@ -1101,17 +1294,26 @@ export class MapTileTreeReference extends TileTreeReference { public layerFromTreeModelIds(mapTreeModelId: Id64String, layerTreeModelId: Id64String): MapLayerInfoFromTileTree[] { const imageryTree = this.imageryTreeFromTreeModelIds(mapTreeModelId, layerTreeModelId); return imageryTree.map((tree) => { - const isBaseLayer = (this._baseImageryLayerIncluded && tree.layerIndex === 0); + const isBaseLayer = this._baseImageryLayerIncluded && tree.layerIndex === 0; return { isBaseLayer, index: isBaseLayer ? undefined : { isOverlay: this.isOverlay, index: this._baseImageryLayerIncluded ? tree.layerIndex - 1 : tree.layerIndex }, - settings: tree.layerSettings, provider: tree.imageryProvider, + settings: tree.layerSettings, + provider: tree.imageryProvider, }; }); } // Utility method that execute the provided function for every *imagery* tiles under a given HitDetail object. - private async forEachImageryTileHit(hit: HitDetail, func: (imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic, imageryTree: ImageryMapTileTree) => Promise): Promise { + private async forEachImageryTileHit( + hit: HitDetail, + func: ( + imageryTreeRef: ImageryMapLayerTreeReference, + quadId: QuadId, + cartoGraphic: Cartographic, + imageryTree: ImageryMapTileTree, + ) => Promise, + ): Promise { const tree = this.treeOwner.tileTree as MapTileTree; if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.modelId || !hit.viewport || !hit.viewport.view.is3d) return undefined; @@ -1142,18 +1344,18 @@ export class MapTileTreeReference extends TileTreeReference { const imageryTree = treeRef.treeOwner.tileTree as ImageryMapTileTree; if (imageryTree) { for (const imageryTile of terrainTile.imageryTiles) { - if (!processedTileIds.includes(imageryTile.contentId) + if ( + !processedTileIds.includes(imageryTile.contentId) && imageryTree === imageryTile.imageryTree - && imageryTile.rectangle.containsCartographic(cartoGraphic)) { + && imageryTile.rectangle.containsCartographic(cartoGraphic) + ) { processedTileIds.push(imageryTile.contentId); try { await func(treeRef, imageryTile.quadId, cartoGraphic, imageryTree); } catch { // continue iterating even though we got a failure. } - } - } } } @@ -1176,7 +1378,12 @@ export class MapTileTreeReference extends TileTreeReference { const strings: string[] = []; - const getTooltipFunc = async (imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic, imageryTree: ImageryMapTileTree) => { + const getTooltipFunc = async ( + imageryTreeRef: ImageryMapLayerTreeReference, + quadId: QuadId, + cartoGraphic: Cartographic, + imageryTree: ImageryMapTileTree, + ) => { strings.push(`${IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${imageryTreeRef.layerSettings.name}`); carto = cartoGraphic; await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree); @@ -1192,7 +1399,11 @@ export class MapTileTreeReference extends TileTreeReference { strings.push(`${IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Longitude")}: ${carto.longitudeDegrees.toFixed(4)}`); if (this.settings.applyTerrain && tree.terrainExaggeration !== 0.0) { const geodeticHeight = (carto.height - tree.bimElevationBias) / tree.terrainExaggeration; - strings.push(`${IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Height")}: ${geodeticHeight.toFixed(1)} ${IModelApp.localization.getLocalizedString("iModelJs:MapLayers.SeaLevel")}: ${(geodeticHeight - tree.geodeticOffset).toFixed(1)}`); + strings.push( + `${IModelApp.localization.getLocalizedString("iModelJs:MapLayers.Height")}: ${geodeticHeight.toFixed(1)} ${ + IModelApp.localization.getLocalizedString("iModelJs:MapLayers.SeaLevel") + }: ${(geodeticHeight - tree.geodeticOffset).toFixed(1)}`, + ); } } @@ -1209,8 +1420,12 @@ export class MapTileTreeReference extends TileTreeReference { const info: MapLayerFeatureInfo[] = []; const imageryTreeRef = this.imageryTreeFromTreeModelIds(hit.modelId, hit.sourceId); if (imageryTreeRef !== undefined) { - - const getFeatureInfoFunc = async (_imageryTreeRef: ImageryMapLayerTreeReference, quadId: QuadId, cartoGraphic: Cartographic, imageryTree: ImageryMapTileTree) => { + const getFeatureInfoFunc = async ( + _imageryTreeRef: ImageryMapLayerTreeReference, + quadId: QuadId, + cartoGraphic: Cartographic, + imageryTree: ImageryMapTileTree, + ) => { try { await imageryTree.imageryLoader.getMapFeatureInfo(info, quadId, cartoGraphic, imageryTree, hit, options); } catch { @@ -1221,7 +1436,6 @@ export class MapTileTreeReference extends TileTreeReference { } catch { // No results added } - } return info; diff --git a/core/frontend/src/tile/map/MapTiledGraphicsProvider.ts b/core/frontend/src/tile/map/MapTiledGraphicsProvider.ts index b3b52a4f864b..3881b6db910a 100644 --- a/core/frontend/src/tile/map/MapTiledGraphicsProvider.ts +++ b/core/frontend/src/tile/map/MapTiledGraphicsProvider.ts @@ -9,23 +9,32 @@ import { Id64String } from "@itwin/core-bentley"; import { BaseMapLayerSettings, MapImagerySettings, MapLayerSettings } from "@itwin/core-common"; import { DisplayStyleState } from "../../DisplayStyleState"; -import { ViewState } from "../../ViewState"; -import { Viewport } from "../../Viewport"; -import { DisclosedTileTreeSet, MapLayerImageryProvider, MapLayerInfoFromTileTree, MapTileTreeReference, TiledGraphicsProvider, TileTree, TileTreeOwner, TileTreeReference } from "../internal"; import { IModelApp } from "../../IModelApp"; +import { Viewport } from "../../Viewport"; +import { ViewState } from "../../ViewState"; +import { + DisclosedTileTreeSet, + MapLayerImageryProvider, + MapLayerInfoFromTileTree, + MapTileTreeReference, + TiledGraphicsProvider, + TileTree, + TileTreeOwner, + TileTreeReference, +} from "../internal"; /** Position of a map-layer in the display style's map (i.e. background/overlay map) * @public */ export interface MapLayerIndex { /** True if map-layer is part of [[DisplayStyleState]]'s overlay map, otherwise map-layer is part of [[DisplayStyleState]]'s background map - * @see [[DisplayStyleState.mapLayerAtIndex]]. - */ + * @see [[DisplayStyleState.mapLayerAtIndex]]. + */ isOverlay: boolean; /** Index of the map-layer in [[DisplayStyleState]]'s background/overlay map * @see [[DisplayStyleState.mapLayerAtIndex]]. - */ + */ index: number; } @@ -45,9 +54,26 @@ export class MapTiledGraphicsProvider implements TiledGraphicsProvider { constructor(viewportId: number, displayStyle: DisplayStyleState) { const mapSettings = displayStyle.backgroundMapSettings; const mapImagery = displayStyle.settings.mapImagery; - this.backgroundMap = new MapTileTreeReference(mapSettings, mapImagery.backgroundBase, mapImagery.backgroundLayers, displayStyle.iModel, viewportId, false, false, () => displayStyle.overrideTerrainDisplay()); + this.backgroundMap = new MapTileTreeReference( + mapSettings, + mapImagery.backgroundBase, + mapImagery.backgroundLayers, + displayStyle.iModel, + viewportId, + false, + false, + () => displayStyle.overrideTerrainDisplay(), + ); this.overlayMap = new MapTileTreeReference(mapSettings, undefined, mapImagery.overlayLayers, displayStyle.iModel, viewportId, true, false); - this.backgroundDrapeMap = new MapTileTreeReference(mapSettings, mapImagery.backgroundBase, mapImagery.backgroundLayers, displayStyle.iModel, viewportId, false, true); + this.backgroundDrapeMap = new MapTileTreeReference( + mapSettings, + mapImagery.backgroundBase, + mapImagery.backgroundLayers, + displayStyle.iModel, + viewportId, + false, + true, + ); const removals = this._detachFromDisplayStyle; removals.push(displayStyle.settings.onBackgroundMapChanged.addListener((settings) => { @@ -84,7 +110,7 @@ export class MapTiledGraphicsProvider implements TiledGraphicsProvider { // This is used in inital view setup and when views are synchronized. If view is being synchronized // we need to clear the layers which purges tile graphics if the settings or layers are changed. public setView(newView: ViewState) { - const layersMatch = ((layers1: MapLayerSettings[], layers2: MapLayerSettings[]): boolean => { + const layersMatch = (layers1: MapLayerSettings[], layers2: MapLayerSettings[]): boolean => { if (layers1.length !== layers2.length) return false; @@ -93,11 +119,14 @@ export class MapTiledGraphicsProvider implements TiledGraphicsProvider { return false; return true; - }); + }; const mapImagery = newView.displayStyle.settings.mapImagery; - if (!newView.displayStyle.backgroundMapSettings.equals(this.backgroundMap.settings) + if ( + !newView.displayStyle.backgroundMapSettings.equals(this.backgroundMap.settings) || !layersMatch(mapImagery.backgroundLayers, this.backgroundMap.layerSettings) - || (mapImagery.backgroundBase instanceof BaseMapLayerSettings && !layersMatch([mapImagery.backgroundBase], this.backgroundDrapeMap.layerSettings))) { + || (mapImagery.backgroundBase instanceof BaseMapLayerSettings && + !layersMatch([mapImagery.backgroundBase], this.backgroundDrapeMap.layerSettings)) + ) { this.backgroundMap.clearLayers(); this.backgroundDrapeMap.clearLayers(); } @@ -112,12 +141,16 @@ export class MapTiledGraphicsProvider implements TiledGraphicsProvider { /** @internal */ public getMapLayerImageryProvider(mapLayerIndex: MapLayerIndex): MapLayerImageryProvider | undefined { - const imageryTreeRef = mapLayerIndex.isOverlay ? this.overlayMap.getLayerImageryTreeRef(mapLayerIndex.index) : this.backgroundMap.getLayerImageryTreeRef(mapLayerIndex.index); + const imageryTreeRef = mapLayerIndex.isOverlay + ? this.overlayMap.getLayerImageryTreeRef(mapLayerIndex.index) + : this.backgroundMap.getLayerImageryTreeRef(mapLayerIndex.index); return imageryTreeRef?.imageryProvider; } public resetMapLayer(mapLayerIndex: MapLayerIndex) { - const imageryTreeRef = mapLayerIndex.isOverlay ? this.overlayMap.getLayerImageryTreeRef(mapLayerIndex.index) : this.backgroundMap.getLayerImageryTreeRef(mapLayerIndex.index); + const imageryTreeRef = mapLayerIndex.isOverlay + ? this.overlayMap.getLayerImageryTreeRef(mapLayerIndex.index) + : this.backgroundMap.getLayerImageryTreeRef(mapLayerIndex.index); imageryTreeRef?.resetTreeOwner(); } @@ -149,4 +182,3 @@ export class MapTiledGraphicsProvider implements TiledGraphicsProvider { return [...bgMapLayers, ...ovlMapLayers]; } } - diff --git a/core/frontend/src/tile/map/MapTilingScheme.ts b/core/frontend/src/tile/map/MapTilingScheme.ts index 6ee2f3d59686..0ac18240b94f 100644 --- a/core/frontend/src/tile/map/MapTilingScheme.ts +++ b/core/frontend/src/tile/map/MapTilingScheme.ts @@ -6,8 +6,8 @@ * @module Tiles */ -import { Angle, Matrix3d, Point2d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; +import { Angle, Matrix3d, Point2d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { IModelConnection } from "../../IModelConnection"; import { MapCartoRectangle } from "../internal"; @@ -66,7 +66,7 @@ export abstract class MapTilingScheme { * @param level The level of detail, with 0 corresponding to the root tile. */ public getNumberOfYTilesAtLevel(level: number): number { - return level < 0 ? 1 : this.numberOfLevelZeroTilesY << level; + return level < 0 ? 1 : this.numberOfLevelZeroTilesY << level; } /** @alpha */ @@ -169,7 +169,6 @@ export abstract class MapTilingScheme { public cartographicToTileXY(carto: Cartographic, level: number, result?: Point2d): Point2d { const fraction = this.cartographicToFraction(carto.latitude, carto.longitude, this._scratchPoint2d); return Point2d.create(this.xFractionToTileX(fraction.x, level), this.yFractionToTileY(fraction.y, level), result); - } /** Given fractional coordinates in the XY plane and an elevation, compute the corresponding cartographic position. */ @@ -190,7 +189,11 @@ export abstract class MapTilingScheme { /** @alpha */ private ecefToPixelFraction(point: Point3d, applyTerrain: boolean): Point3d { const cartoGraphic = Cartographic.fromEcef(point)!; - return Point3d.create(this.longitudeToXFraction(cartoGraphic.longitude), this.latitudeToYFraction(cartoGraphic.latitude), applyTerrain ? cartoGraphic.height : 0); + return Point3d.create( + this.longitudeToXFraction(cartoGraphic.longitude), + this.latitudeToYFraction(cartoGraphic.latitude), + applyTerrain ? cartoGraphic.height : 0, + ); } /** @alpha */ @@ -291,6 +294,6 @@ export class WebMercatorTilingScheme extends MapTilingScheme { latitude = -WebMercatorProjection.maximumLatitude; } const sinLatitude = Math.sin(latitude); - return (0.5 - Math.log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * Angle.piRadians)); // https://msdn.microsoft.com/en-us/library/bb259689.aspx + return (0.5 - Math.log((1.0 + sinLatitude) / (1.0 - sinLatitude)) / (4.0 * Angle.piRadians)); // https://msdn.microsoft.com/en-us/library/bb259689.aspx } } diff --git a/core/frontend/src/tile/map/QuadId.ts b/core/frontend/src/tile/map/QuadId.ts index 42b93a6b6f0c..3d3abde69a5f 100644 --- a/core/frontend/src/tile/map/QuadId.ts +++ b/core/frontend/src/tile/map/QuadId.ts @@ -7,8 +7,8 @@ */ import { assert, compareNumbers } from "@itwin/core-bentley"; -import { Angle, AngleSweep, Range2d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; +import { Angle, AngleSweep, Range2d } from "@itwin/core-geometry"; import { MapTilingScheme } from "../internal"; const scratchCartographic1 = Cartographic.createZero(); @@ -44,7 +44,7 @@ export class QuadId { /** @alpha */ public get contentId(): string { - return QuadId.getTileContentId(this.level, this.column, this.row); + return QuadId.getTileContentId(this.level, this.column, this.row); } /** @alpha */ diff --git a/core/frontend/src/tile/map/TerrainMeshProvider.ts b/core/frontend/src/tile/map/TerrainMeshProvider.ts index 6749e7e6edb3..ccc5f4ff1245 100644 --- a/core/frontend/src/tile/map/TerrainMeshProvider.ts +++ b/core/frontend/src/tile/map/TerrainMeshProvider.ts @@ -8,11 +8,9 @@ import { Range1d } from "@itwin/core-geometry"; import { ApproximateTerrainHeights } from "../../ApproximateTerrainHeights"; -import { ScreenViewport } from "../../Viewport"; import { RealityMeshParams } from "../../render/RealityMeshParams"; -import { - MapCartoRectangle, MapTile, MapTilingScheme, QuadId, -} from "../internal"; +import { ScreenViewport } from "../../Viewport"; +import { MapCartoRectangle, MapTile, MapTilingScheme, QuadId } from "../internal"; /** Options supplied to [[TerrainProvider.createTerrainMeshProvider]] to construct a [[TerrainMeshProvider]]. * @public @@ -93,7 +91,7 @@ export abstract class TerrainMeshProvider { * For example, a provider that produces meshes from [Bing Maps](https://docs.microsoft.com/en-us/bingmaps/rest-services/elevations/) would be required to * disclose any copyrighted data used in the production of those meshes. */ - public addLogoCards(_cards: HTMLTableElement, _vp: ScreenViewport): void { } + public addLogoCards(_cards: HTMLTableElement, _vp: ScreenViewport): void {} /** Return whether terrain data can be obtained for the [[MapTile]] specified by `quadId`. If it returns false, a terrain mesh will instead be produced for * that tile by up-sampling the terrain mesh provided by its parent tile. @@ -111,7 +109,9 @@ export abstract class TerrainMeshProvider { * The default implementation uses a fast approximation. */ public getChildHeightRange(quadId: QuadId, rectangle: MapCartoRectangle, parent: MapTile): Range1d | undefined { - return (quadId.level < ApproximateTerrainHeights.maxLevel) ? ApproximateTerrainHeights.instance.getMinimumMaximumHeights(rectangle) : parent.heightRange; + return (quadId.level < ApproximateTerrainHeights.maxLevel) + ? ApproximateTerrainHeights.instance.getMinimumMaximumHeights(rectangle) + : parent.heightRange; } /** The tiling scheme used by this provider to convert between tile coordinates and geodetic coordinates. */ @@ -121,5 +121,7 @@ export abstract class TerrainMeshProvider { * For example, a parent tile might contain information about the availability or height ranges of its child tiles that can be used to * implement [[isTileAvailable]] or [[getChildHeightRange]], respectively. */ - public forceTileLoad(_tile: MapTile): boolean { return false; } + public forceTileLoad(_tile: MapTile): boolean { + return false; + } } diff --git a/core/frontend/src/tile/map/UrlUtils.ts b/core/frontend/src/tile/map/UrlUtils.ts index d43e903c9af8..61b292603a34 100644 --- a/core/frontend/src/tile/map/UrlUtils.ts +++ b/core/frontend/src/tile/map/UrlUtils.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ /** Append custom parameters for settings to provided URL object. - * Make sure custom parameters do no override query parameters already part of the URL (lower case comparison) - * @internal - */ -export function appendQueryParams(url: string, queryParams?: {[key: string]: string}) { + * Make sure custom parameters do no override query parameters already part of the URL (lower case comparison) + * @internal + */ +export function appendQueryParams(url: string, queryParams?: { [key: string]: string }) { if (!queryParams) return url; @@ -18,8 +18,8 @@ export function appendQueryParams(url: string, queryParams?: {[key: string]: str currentParams.push(key.toLowerCase()); }); - const urlParamsFromIndexArray = (indexArray?: {[key: string]: string}, result?: URLSearchParams): URLSearchParams => { - const urlParams = (result ? result : new URLSearchParams()); + const urlParamsFromIndexArray = (indexArray?: { [key: string]: string }, result?: URLSearchParams): URLSearchParams => { + const urlParams = result ? result : new URLSearchParams(); if (!indexArray) return urlParams; Object.keys(indexArray).forEach((key) => { @@ -41,7 +41,7 @@ export function appendQueryParams(url: string, queryParams?: {[key: string]: str } return separator; }; - if ( params.size > 0) { + if (params.size > 0) { url = `${url}${getSeparator(url)}${params.toString()}`; } diff --git a/core/frontend/src/tile/map/WmsCapabilities.ts b/core/frontend/src/tile/map/WmsCapabilities.ts index 0f129dda3a52..552c0752281c 100644 --- a/core/frontend/src/tile/map/WmsCapabilities.ts +++ b/core/frontend/src/tile/map/WmsCapabilities.ts @@ -7,8 +7,8 @@ */ import { MapSubLayerProps } from "@itwin/core-common"; -import { RequestBasicCredentials } from "../../request/Request"; import WMS from "wms-capabilities"; +import { RequestBasicCredentials } from "../../request/Request"; import { MapCartoRectangle, WmsUtilities } from "../internal"; function rangeFromJSONArray(json: any): MapCartoRectangle | undefined { @@ -21,12 +21,13 @@ function rangeFromJSON(json: any): MapCartoRectangle | undefined { else if (Array.isArray(json.EX_GeographicBoundingBox)) { return rangeFromJSONArray(json.EX_GeographicBoundingBox); } else { - if (Array.isArray(json.BoundingBox)) + if (Array.isArray(json.BoundingBox)) { for (const boundingBox of json.BoundingBox) { if (boundingBox.crs === "CRS:84" || boundingBox.crs === "EPSG:4326") { return rangeFromJSONArray(boundingBox.extent); } } + } return undefined; } } @@ -39,7 +40,6 @@ function initArray(input: any): undefined | T[] { * @internal */ export namespace WmsCapability { - export class Service { public readonly name: string; public readonly title?: string; @@ -77,7 +77,7 @@ export namespace WmsCapability { const subLayers = new Array(); let index = 1; let childrenFound = false; - const pushSubLayer = ((subLayer: SubLayer, parent?: number) => { + const pushSubLayer = (subLayer: SubLayer, parent?: number) => { let children; const id = index++; if (subLayer.children) { @@ -89,7 +89,7 @@ export namespace WmsCapability { }); } subLayers.push({ name: subLayer.name, title: subLayer.title, visible, parent, children, id }); - }); + }; this.subLayers.forEach((subLayer) => pushSubLayer(subLayer)); if (!childrenFound) { @@ -106,7 +106,9 @@ export namespace WmsCapability { }); if (prefixed.size > 1) { // Preserve the root node if any. - const rootNode = (this.subLayers.length === 1 && this.subLayers[0].children && this.subLayers[0].children.length > 1) ? subLayers.find((curSubLayer) => this.subLayers[0].name === curSubLayer.name)?.id : undefined; + const rootNode = (this.subLayers.length === 1 && this.subLayers[0].children && this.subLayers[0].children.length > 1) + ? subLayers.find((curSubLayer) => this.subLayers[0].name === curSubLayer.name)?.id + : undefined; prefixed.forEach((children, parent) => { children.forEach((child) => { child.parent = index; @@ -114,7 +116,14 @@ export namespace WmsCapability { if (child.title && child.title.indexOf(parent + Layer.PREFIX_SEPARATOR) === 0) child.title = child.title.slice(parent.length + Layer.PREFIX_SEPARATOR.length); }); - subLayers.push({ name: "", title: parent, parent: rootNode, id: index++, children: children.map((child) => child.id as number), visible }); + subLayers.push({ + name: "", + title: parent, + parent: rootNode, + id: index++, + children: children.map((child) => child.id as number), + visible, + }); }); } } @@ -125,7 +134,7 @@ export namespace WmsCapability { public getSubLayersCrs(layerNameFilter: string[]): Map { const subLayerCrs = new Map(); - const processSubLayer = ((subLayer: SubLayer) => { + const processSubLayer = (subLayer: SubLayer) => { if (layerNameFilter.includes(subLayer.name)) { subLayerCrs.set(subLayer.name, subLayer.crs); } @@ -134,7 +143,7 @@ export namespace WmsCapability { processSubLayer(child); }); } - }); + }; this.subLayers.forEach((subLayer) => processSubLayer(subLayer)); return subLayerCrs; @@ -146,12 +155,11 @@ export namespace WmsCapability { public readonly name: string; public readonly title: string; public readonly crs: string[]; - public readonly ownCrs: string[]; // CRS specific to this layer (ie. not including inherited CRS) + public readonly ownCrs: string[]; // CRS specific to this layer (ie. not including inherited CRS) public readonly cartoRange?: MapCartoRectangle; public readonly children?: SubLayer[]; public readonly queryable: boolean; public constructor(_json: any, capabilities: WmsCapabilities, public readonly parent?: SubLayer) { - const getParentCrs = (parentLayer: SubLayer, crsSet: Set) => { parentLayer.crs.forEach((parentCrs) => crsSet.add(parentCrs)); if (parentLayer.parent) { @@ -187,11 +195,21 @@ export class WmsCapabilities { public readonly version?: string; public readonly isVersion13: boolean; public readonly layer?: WmsCapability.Layer; - public get json() { return this._json; } - public get maxLevel(): number { return this.layer ? this.layer.subLayers.length : - 1; } - public get cartoRange(): MapCartoRectangle | undefined { return this.layer?.cartoRange; } - public get featureInfoSupported() { return undefined !== this._json.Capability?.Request?.GetFeatureInfo; } - public get featureInfoFormats(): string[] | undefined { return Array.isArray(this._json.Capability?.Request?.GetFeatureInfo?.Format) ? this._json.Capability?.Request?.GetFeatureInfo?.Format : undefined; } + public get json() { + return this._json; + } + public get maxLevel(): number { + return this.layer ? this.layer.subLayers.length : -1; + } + public get cartoRange(): MapCartoRectangle | undefined { + return this.layer?.cartoRange; + } + public get featureInfoSupported() { + return undefined !== this._json.Capability?.Request?.GetFeatureInfo; + } + public get featureInfoFormats(): string[] | undefined { + return Array.isArray(this._json.Capability?.Request?.GetFeatureInfo?.Format) ? this._json.Capability?.Request?.GetFeatureInfo?.Format : undefined; + } constructor(private _json: any) { this.version = _json.version; this.isVersion13 = _json.version !== undefined && 0 === _json.version.indexOf("1.3"); @@ -200,7 +218,12 @@ export class WmsCapabilities { this.layer = new WmsCapability.Layer(_json.Capability.Layer, this); } - public static async create(url: string, credentials?: RequestBasicCredentials, ignoreCache?: boolean, queryParams?: {[key: string]: string}): Promise { + public static async create( + url: string, + credentials?: RequestBasicCredentials, + ignoreCache?: boolean, + queryParams?: { [key: string]: string }, + ): Promise { if (!ignoreCache) { const cached = WmsCapabilities._capabilitiesCache.get(url); if (cached !== undefined) diff --git a/core/frontend/src/tile/map/WmsUtilities.ts b/core/frontend/src/tile/map/WmsUtilities.ts index 15e61c33fd73..e07de0afd15f 100644 --- a/core/frontend/src/tile/map/WmsUtilities.ts +++ b/core/frontend/src/tile/map/WmsUtilities.ts @@ -18,13 +18,12 @@ export class WmsUtilities { } /** - * fetch XML from HTTP request - * @param url server URL to address the request - * @internal - */ + * fetch XML from HTTP request + * @param url server URL to address the request + * @internal + */ public static async fetchXml(url: string, credentials?: RequestBasicCredentials): Promise { - - let headers: Headers|undefined; + let headers: Headers | undefined; if (credentials && credentials.user && credentials.password) { headers = new Headers(); setBasicAuthorization(headers, credentials); @@ -32,7 +31,7 @@ export class WmsUtilities { let response = await fetch(url, { method: "GET", headers }); if (!credentials && response.status === 401 && headersIncludeAuthMethod(response.headers, ["ntlm", "negotiate"])) { - // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication) + // We got a http 401 challenge, lets try SSO (i.e. Windows Authentication) response = await fetch(url, { method: "GET", credentials: "include" }); } diff --git a/core/frontend/src/tile/map/WmtsCapabilities.ts b/core/frontend/src/tile/map/WmtsCapabilities.ts index c54a8e862adf..b7796d5d98c1 100644 --- a/core/frontend/src/tile/map/WmtsCapabilities.ts +++ b/core/frontend/src/tile/map/WmtsCapabilities.ts @@ -34,8 +34,7 @@ enum OwsConstants { TITLE_XMLTAG = "ows:Title", UPPERCORNER_XMLTAG = "ows:UpperCorner", VALUE_XMLTAG = "ows:Value", - WGS84BOUNDINGBOX_XMLTAG = "ows:WGS84BoundingBox" - + WGS84BOUNDINGBOX_XMLTAG = "ows:WGS84BoundingBox", } enum XmlConstants { @@ -61,7 +60,7 @@ enum XmlConstants { } /** @internal -*/ + */ export enum WmtsConstants { GOOGLEMAPS_LEVEL0_SCALE_DENOM = 559082264.0287178, GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME = "googlemapscompatible", @@ -74,13 +73,11 @@ export enum WmtsConstants { * @internal */ const getElementTextContent = (elem: Element, qualifiedName: string, defaultText?: string) => { - const tmpElem = elem.getElementsByTagName(qualifiedName); if (tmpElem.length > 0) { return tmpElem[0].textContent ?? defaultText; } else return defaultText; - }; /** Encapsulation of the capabilities for an WMTS server @@ -121,13 +118,19 @@ export namespace WmtsCapability { export class OperationMetadata { private _getCapabilities?: Operation; - public get getCapabilities(): Operation | undefined { return this._getCapabilities; } + public get getCapabilities(): Operation | undefined { + return this._getCapabilities; + } private _getFeatureInfo?: Operation; - public get getFeatureInfo(): Operation | undefined { return this._getFeatureInfo; } + public get getFeatureInfo(): Operation | undefined { + return this._getFeatureInfo; + } private _getTile?: Operation; - public get getTile(): Operation | undefined { return this._getTile; } + public get getTile(): Operation | undefined { + return this._getTile; + } private readOperation(op: Element) { const nameAttr = op.attributes.getNamedItem("name"); @@ -183,9 +186,13 @@ export namespace WmtsCapability { export class Operation { public readonly name?: string; private _getDcpHttp?: HttpDcp[]; - public get getDcpHttp(): HttpDcp[] | undefined { return this._getDcpHttp; } + public get getDcpHttp(): HttpDcp[] | undefined { + return this._getDcpHttp; + } private _postDcpHttp?: HttpDcp[]; - public get postDcpHttp(): HttpDcp[] | undefined { return this._postDcpHttp; } + public get postDcpHttp(): HttpDcp[] | undefined { + return this._postDcpHttp; + } constructor(elem: Element) { const name = elem.getAttribute("name"); @@ -238,7 +245,6 @@ export namespace WmtsCapability { for (const tmsElem of tms) this.tileMatrixSets.push(new TileMatrixSet(tmsElem)); } - } public getGoogleMapsCompatibleTileMatrixSet(): TileMatrixSet[] { @@ -246,10 +252,10 @@ export namespace WmtsCapability { this.tileMatrixSets.forEach((tms) => { if (tms.wellKnownScaleSet?.toLowerCase().includes(WmtsConstants.GOOGLEMAPS_COMPATIBLE_WELLKNOWNNAME)) googleMapsTms.push(tms); - // In case wellKnownScaleSet was not been set properly, infer from scaleDenominator // Note: some servers are quite inaccurate in their scale values, hence I used a delta value of 1. - else if (tms.tileMatrix.length > 0 + else if ( + tms.tileMatrix.length > 0 && Math.abs(tms.tileMatrix[0].scaleDenominator - WmtsConstants.GOOGLEMAPS_LEVEL0_SCALE_DENOM) < 1 && (tms.supportedCrs.includes("3857") || tms.supportedCrs.includes("900913")) ) @@ -305,7 +311,6 @@ export namespace WmtsCapability { public tileMatrix?: string; constructor(elem: Element) { - this.tileMatrix = getElementTextContent(elem, "TileMatrix"); const minTileRow = getElementTextContent(elem, "MinTileRow"); @@ -323,7 +328,6 @@ export namespace WmtsCapability { public readonly tileMatrixSetLimits = new Array(); constructor(elem: Element) { - this.tileMatrixSet = getElementTextContent(elem, "TileMatrixSet", "")!; const tileMatrixLimitsRoot = elem.getElementsByTagName("TileMatrixSetLimits"); @@ -444,7 +448,6 @@ export namespace WmtsCapability { public readonly tileMatrixSetLinks: TileMatrixSetLink[] = []; constructor(elem: Element) { - const identifier = getElementTextContent(elem, OwsConstants.IDENTIFIER_XMLTAG, ""); if (identifier) this.identifier = identifier; @@ -508,7 +511,6 @@ export class WmtsCapabilities { public readonly operationsMetadata?: WmtsCapability.OperationMetadata; constructor(xmlDoc: Document) { - const capabilities = xmlDoc.getElementsByTagName("Capabilities"); if (capabilities.length !== 0) { const capability = capabilities[0]; @@ -537,7 +539,12 @@ export class WmtsCapabilities { return new WmtsCapabilities(xmlDoc); } - public static async create(url: string, credentials?: RequestBasicCredentials, ignoreCache?: boolean, queryParams?: {[key: string]: string}): Promise { + public static async create( + url: string, + credentials?: RequestBasicCredentials, + ignoreCache?: boolean, + queryParams?: { [key: string]: string }, + ): Promise { if (!ignoreCache) { const cached = WmtsCapabilities._capabilitiesCache.get(url); if (cached !== undefined) diff --git a/core/frontend/src/tile/map/wms-capabilities.d.ts b/core/frontend/src/tile/map/wms-capabilities.d.ts index 274f241445ee..e207140ef96e 100644 --- a/core/frontend/src/tile/map/wms-capabilities.d.ts +++ b/core/frontend/src/tile/map/wms-capabilities.d.ts @@ -6,7 +6,7 @@ declare module "wms-capabilities" { export = WMS; declare class WMS { - constructor() { } + constructor() {} public parse(input: string): any; } } diff --git a/core/frontend/src/tools/AccuDrawTool.ts b/core/frontend/src/tools/AccuDrawTool.ts index 2ea7b162f7e0..536769c127f2 100644 --- a/core/frontend/src/tools/AccuDrawTool.ts +++ b/core/frontend/src/tools/AccuDrawTool.ts @@ -8,7 +8,18 @@ import { BentleyStatus } from "@itwin/core-bentley"; import { AxisOrder, Geometry, Matrix3d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; -import { AccuDraw, AccuDrawFlags, AccuDrawHintBuilder, CompassMode, ContextMode, ItemField, KeyinStatus, LockedStates, RotationMode, ThreeAxes } from "../AccuDraw"; +import { + AccuDraw, + AccuDrawFlags, + AccuDrawHintBuilder, + CompassMode, + ContextMode, + ItemField, + KeyinStatus, + LockedStates, + RotationMode, + ThreeAxes, +} from "../AccuDraw"; import { TentativeOrAccuSnap } from "../AccuSnap"; import { ACSDisplayOptions, AuxCoordSystemState } from "../AuxCoordSys"; import { SnapDetail, SnapHeat } from "../HitDetail"; @@ -147,9 +158,11 @@ export class AccuDrawShortcuts { break; case 3: - if (normalizedDifference(points[1], points[0], vec[0]) < 0.00001 || + if ( + normalizedDifference(points[1], points[0], vec[0]) < 0.00001 || normalizedDifference(points[2], points[0], vec[1]) < 0.00001 || - normalizedCrossProduct(vec[0], vec[1], vec[2]) < 0.00001) { + normalizedCrossProduct(vec[0], vec[1], vec[2]) < 0.00001 + ) { accept = true; break; } @@ -163,7 +176,9 @@ export class AccuDrawShortcuts { return accept; } - public static processPendingHints() { IModelApp.accuDraw.processHints(); } + public static processPendingHints() { + IModelApp.accuDraw.processHints(); + } public static requestInputFocus() { const accudraw = IModelApp.accuDraw; @@ -192,26 +207,26 @@ export class AccuDrawShortcuts { const vp = accudraw.currentView; const is3d = vp ? vp.view.is3d() : false; - const isPolar = (CompassMode.Polar === accudraw.compassMode); + const isPolar = CompassMode.Polar === accudraw.compassMode; switch (index) { case ItemField.DIST_Item: - index = ((is3d && !forward) ? ItemField.Z_Item : ItemField.ANGLE_Item); + index = (is3d && !forward) ? ItemField.Z_Item : ItemField.ANGLE_Item; break; case ItemField.ANGLE_Item: - index = ((is3d && forward) ? ItemField.Z_Item : ItemField.DIST_Item); + index = (is3d && forward) ? ItemField.Z_Item : ItemField.DIST_Item; break; case ItemField.X_Item: - index = ((is3d && !forward) ? ItemField.Z_Item : ItemField.Y_Item); + index = (is3d && !forward) ? ItemField.Z_Item : ItemField.Y_Item; break; case ItemField.Y_Item: - index = ((is3d && forward) ? ItemField.Z_Item : ItemField.X_Item); + index = (is3d && forward) ? ItemField.Z_Item : ItemField.X_Item; break; case ItemField.Z_Item: - index = (forward ? (isPolar ? ItemField.DIST_Item : ItemField.X_Item) : (isPolar ? ItemField.ANGLE_Item : ItemField.Y_Item)); + index = forward ? (isPolar ? ItemField.DIST_Item : ItemField.X_Item) : (isPolar ? ItemField.ANGLE_Item : ItemField.Y_Item); break; } @@ -220,7 +235,9 @@ export class AccuDrawShortcuts { accudraw.dontMoveFocus = true; } - public static itemFieldNewInput(index: ItemField): void { IModelApp.accuDraw.setKeyinStatus(index, KeyinStatus.Partial); } + public static itemFieldNewInput(index: ItemField): void { + IModelApp.accuDraw.setKeyinStatus(index, KeyinStatus.Partial); + } public static async itemFieldAcceptInput(index: ItemField, str: string): Promise { const accudraw = IModelApp.accuDraw; @@ -245,14 +262,14 @@ export class AccuDrawShortcuts { } const is3d = vp ? vp.view.is3d() : false; - const isPolar = (CompassMode.Polar === accudraw.compassMode); + const isPolar = CompassMode.Polar === accudraw.compassMode; switch (index) { case ItemField.DIST_Item: index = ItemField.ANGLE_Item; break; case ItemField.ANGLE_Item: - index = (is3d ? ItemField.Z_Item : ItemField.DIST_Item); + index = is3d ? ItemField.Z_Item : ItemField.DIST_Item; break; case ItemField.X_Item: @@ -260,11 +277,11 @@ export class AccuDrawShortcuts { break; case ItemField.Y_Item: - index = (is3d ? ItemField.Z_Item : ItemField.X_Item); + index = is3d ? ItemField.Z_Item : ItemField.X_Item; break; case ItemField.Z_Item: - index = (isPolar ? ItemField.DIST_Item : ItemField.X_Item); + index = isPolar ? ItemField.DIST_Item : ItemField.X_Item; break; } accudraw.setFocusItem(index); @@ -765,7 +782,9 @@ export class AccuDrawShortcuts { accudraw.refreshDecorationsAndDynamics(); } - public static rotateToBase(): void { this.setStandardRotation(IModelApp.accuDraw.flags.baseRotation); } + public static rotateToBase(): void { + this.setStandardRotation(IModelApp.accuDraw.flags.baseRotation); + } public static rotateToACS(): void { const accudraw = IModelApp.accuDraw; @@ -1235,11 +1254,21 @@ export class AccuDrawRotateViewTool extends Tool { /** @internal */ abstract class AccuDrawShortcutsTool extends InputCollector { private _complete = false; - protected get allowShortcut(): boolean { return this.wantActivateOnStart ? IModelApp.accuDraw.isEnabled : true; } - protected get wantActivateOnStart(): boolean { return false; } // Whether to automatically enable AccuDraw before the 1st data button... - protected get wantClearSnapOnStart(): boolean { return false; } // Whether to preserve active Tentative/AccuSnap on install... - protected get wantManipulationImmediate(): boolean { return false; } // Whether additional input is required to process on install... - protected get wantExitOnDataButtonUp(): boolean { return false; } // Whether to exit on button up instead of down (see rotate perpendicular)... + protected get allowShortcut(): boolean { + return this.wantActivateOnStart ? IModelApp.accuDraw.isEnabled : true; + } + protected get wantActivateOnStart(): boolean { + return false; + } // Whether to automatically enable AccuDraw before the 1st data button... + protected get wantClearSnapOnStart(): boolean { + return false; + } // Whether to preserve active Tentative/AccuSnap on install... + protected get wantManipulationImmediate(): boolean { + return false; + } // Whether additional input is required to process on install... + protected get wantExitOnDataButtonUp(): boolean { + return false; + } // Whether to exit on button up instead of down (see rotate perpendicular)... public override async onInstall(): Promise { if (!this.allowShortcut) @@ -1268,7 +1297,7 @@ abstract class AccuDrawShortcutsTool extends InputCollector { this.changeLocateState(false, true, undefined, CoordinateLockOverrides.None); } - this.doManipulation(undefined, true);; + this.doManipulation(undefined, true); } public override async onCleanup(): Promise { @@ -1302,19 +1331,29 @@ abstract class AccuDrawShortcutsTool extends InputCollector { this.doManipulation(ev, true); } - public onManipulationStart(): void { } - public onManipulationComplete(): AccuDrawFlags { return AccuDrawFlags.SetRMatrix; } + public onManipulationStart(): void {} + public onManipulationComplete(): AccuDrawFlags { + return AccuDrawFlags.SetRMatrix; + } public abstract doManipulation(ev: BeButtonEvent | undefined, isMotion: boolean): boolean; } /** @internal */ export class AccuDrawRotateAxesTool extends AccuDrawShortcutsTool { public static override toolId = "AccuDraw.RotateAxes"; - public static override get maxArgs(): number { return 1; } - public constructor(public aboutCurrentZ: boolean = true) { super(); } + public static override get maxArgs(): number { + return 1; + } + public constructor(public aboutCurrentZ: boolean = true) { + super(); + } - protected override get allowShortcut(): boolean { return IModelApp.accuDraw.isActive; } // Require compass to already be active for this shortcut... - protected override get wantActivateOnStart(): boolean { return true; } // State is demoted to inactive when a tool install, still need this... + protected override get allowShortcut(): boolean { + return IModelApp.accuDraw.isActive; + } // Require compass to already be active for this shortcut... + protected override get wantActivateOnStart(): boolean { + return true; + } // State is demoted to inactive when a tool install, still need this... protected override get wantManipulationImmediate(): boolean { if (TentativeOrAccuSnap.isHot) @@ -1362,8 +1401,12 @@ export class AccuDrawRotateElementTool extends AccuDrawShortcutsTool { public static override toolId = "AccuDraw.RotateElement"; private _moveOrigin = !IModelApp.accuDraw.isActive || IModelApp.tentativePoint.isActive; // Preserve current origin if AccuDraw already active and not tentative snap... - protected override get wantActivateOnStart(): boolean { return true; } - protected override get wantManipulationImmediate(): boolean { return IModelApp.tentativePoint.isSnapped; } + protected override get wantActivateOnStart(): boolean { + return true; + } + protected override get wantManipulationImmediate(): boolean { + return IModelApp.tentativePoint.isSnapped; + } public override onManipulationStart(): void { IModelApp.accuDraw.setContext(AccuDrawFlags.FixedOrigin); // Don't move compass when updateOrientation returns false... @@ -1410,7 +1453,9 @@ export class AccuDrawRotatePerpendicularTool extends AccuDrawRotateElementTool { public static override toolId = "AccuDraw.RotatePerpendicular"; protected _location?: { point: Point3d, viewport: ScreenViewport }; - protected override get wantExitOnDataButtonUp(): boolean { return true; } // Complete on button up since button down clears tentative... + protected override get wantExitOnDataButtonUp(): boolean { + return true; + } // Complete on button up since button down clears tentative... public override onManipulationComplete(): AccuDrawFlags { if (undefined !== this._location) { @@ -1448,7 +1493,7 @@ export class AccuDrawRotatePerpendicularTool extends AccuDrawRotateElementTool { const xVec = new Vector3d(); if (normalizedDifference(point, accudraw.origin, xVec) < Geometry.smallAngleRadians) - return false;; // Closest point and compass origin coincide... + return false; // Closest point and compass origin coincide... const yVec = xVec.unitCrossProduct(zVec); if (undefined === yVec) @@ -1476,7 +1521,9 @@ export class DefineACSByElementTool extends AccuDrawShortcutsTool { private _rMatrix = Matrix3d.createIdentity(); private _acs?: AuxCoordSystemState; - public override onManipulationStart(): void { CoreTools.outputPromptByKey("AccuDraw.DefineACSByElement.Prompts.FirstPoint"); } + public override onManipulationStart(): void { + CoreTools.outputPromptByKey("AccuDraw.DefineACSByElement.Prompts.FirstPoint"); + } public updateOrientation(snap: SnapDetail, vp: Viewport): boolean { const rMatrix = AccuDraw.getSnapRotation(snap, vp); diff --git a/core/frontend/src/tools/ClipViewTool.ts b/core/frontend/src/tools/ClipViewTool.ts index 690b841f0480..a6873f00ceb8 100644 --- a/core/frontend/src/tools/ClipViewTool.ts +++ b/core/frontend/src/tools/ClipViewTool.ts @@ -6,15 +6,38 @@ * @module Tools */ +import { DialogItem, DialogItemValue, DialogPropertySyncItem, PropertyDescription } from "@itwin/appui-abstract"; import { BeEvent, Id64, Id64Arg, Id64String } from "@itwin/core-bentley"; +import { ClipStyle, ColorDef, LinePixels, Placement2d } from "@itwin/core-common"; import { - AxisOrder, ClipMaskXYZRangePlanes, ClipPlane, ClipPrimitive, ClipShape, ClipUtilities, ClipVector, ConvexClipPlaneSet, FrameBuilder, Geometry, GeometryQuery, - GrowableXYZArray, LineString3d, Loop, Matrix3d, Path, Plane3dByOriginAndUnitNormal, Point3d, PolygonOps, PolylineOps, Range1d, Range3d, Ray3d, - Transform, Vector3d, + AxisOrder, + ClipMaskXYZRangePlanes, + ClipPlane, + ClipPrimitive, + ClipShape, + ClipUtilities, + ClipVector, + ConvexClipPlaneSet, + FrameBuilder, + Geometry, + GeometryQuery, + GrowableXYZArray, + LineString3d, + Loop, + Matrix3d, + Path, + Plane3dByOriginAndUnitNormal, + Point3d, + PolygonOps, + PolylineOps, + Range1d, + Range3d, + Ray3d, + Transform, + Vector3d, } from "@itwin/core-geometry"; -import { ClipStyle, ColorDef, LinePixels, Placement2d } from "@itwin/core-common"; -import { DialogItem, DialogItemValue, DialogPropertySyncItem, PropertyDescription } from "@itwin/appui-abstract"; import { AccuDrawHintBuilder, ContextRotationId } from "../AccuDraw"; +import { GraphicType } from "../common/render/GraphicType"; import { CoordSystem } from "../CoordSystem"; import { LocateResponse } from "../ElementLocateManager"; import { HitDetail } from "../HitDetail"; @@ -26,7 +49,6 @@ import { EditManipulator } from "./EditManipulator"; import { PrimitiveTool } from "./PrimitiveTool"; import { BeButtonEvent, CoordinateLockOverrides, CoreTools, EventHandled } from "./Tool"; import { ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection } from "./ToolAssistance"; -import { GraphicType } from "../common/render/GraphicType"; // cSpell:ignore geti @@ -75,12 +97,16 @@ export interface DrawClipOptions { * @public @extensions */ export class ViewClipTool extends PrimitiveTool { - constructor(protected _clipEventHandler?: ViewClipEventHandler) { super(); } + constructor(protected _clipEventHandler?: ViewClipEventHandler) { + super(); + } /** @internal */ protected static _orientationName = "enumAsOrientation"; /** @internal */ - protected static enumAsOrientationMessage(str: string) { return CoreTools.translate(`Settings.Orientation.${str}`); } + protected static enumAsOrientationMessage(str: string) { + return CoreTools.translate(`Settings.Orientation.${str}`); + } /** @internal */ protected static _getEnumAsOrientationDescription = (): PropertyDescription => { return { @@ -103,9 +129,13 @@ export class ViewClipTool extends PrimitiveTool { }; /** @internal */ - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); + } /** @internal */ public override async onPostInstall() { @@ -114,13 +144,19 @@ export class ViewClipTool extends PrimitiveTool { } /** @internal */ - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } /** @internal */ - public async onRestartTool(): Promise { return this.exitTool(); } + public async onRestartTool(): Promise { + return this.exitTool(); + } /** @internal */ - protected showPrompt(): void { } + protected showPrompt(): void {} /** @internal */ - protected setupAndPromptForNextAction(): void { this.showPrompt(); } + protected setupAndPromptForNextAction(): void { + this.showPrompt(); + } /** @internal */ public override async onResetButtonUp(_ev: BeButtonEvent): Promise { await this.onReinitialize(); @@ -188,7 +224,13 @@ export class ViewClipTool extends PrimitiveTool { if (range.isNull || range.isAlmostZeroX || range.isAlmostZeroY) return false; const clip = ClipVector.createEmpty(); - const block = ClipShape.createBlock(range, range.isAlmostZeroZ ? ClipMaskXYZRangePlanes.XAndY : ClipMaskXYZRangePlanes.All, false, false, transform); + const block = ClipShape.createBlock( + range, + range.isAlmostZeroZ ? ClipMaskXYZRangePlanes.XAndY : ClipMaskXYZRangePlanes.All, + false, + false, + transform, + ); clip.appendReference(block); return this.setViewClip(viewport, clip); } @@ -248,29 +290,40 @@ export class ViewClipTool extends PrimitiveTool { /** @internal */ public static drawClip(context: DecorateContext, clip: ClipVector, viewExtents?: Range3d, options?: DrawClipOptions): void { const clipShape = ViewClipTool.isSingleClipShape(clip); - const clipPlanes = (undefined === clipShape ? ViewClipTool.isSingleConvexClipPlaneSet(clip) : undefined); + const clipPlanes = undefined === clipShape ? ViewClipTool.isSingleConvexClipPlaneSet(clip) : undefined; if (undefined === clipShape && undefined === clipPlanes) return; - const viewRange = (viewExtents ? viewExtents : context.viewport.computeViewRange()); - const clipPlanesLoops = (undefined !== clipPlanes ? ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipPlanes, viewRange) : undefined); + const viewRange = viewExtents ? viewExtents : context.viewport.computeViewRange(); + const clipPlanesLoops = undefined !== clipPlanes ? ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipPlanes, viewRange) : undefined; if (undefined === clipShape && (undefined === clipPlanesLoops || 0 === clipPlanesLoops.length)) return; - const color = (options && options.color ? options.color : EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, context.viewport)); - const builderVis = context.createGraphicBuilder(GraphicType.WorldDecoration, clipShape ? clipShape.transformFromClip : undefined, (options ? options.id : undefined)); + const color = options && options.color ? options.color : EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, context.viewport); + const builderVis = context.createGraphicBuilder( + GraphicType.WorldDecoration, + clipShape ? clipShape.transformFromClip : undefined, + options ? options.id : undefined, + ); const builderHid = context.createGraphicBuilder(GraphicType.WorldOverlay, clipShape ? clipShape.transformFromClip : undefined); - builderVis.setSymbology(color, ColorDef.black, (options && options.visibleWidth ? options.visibleWidth : 3)); - builderHid.setSymbology(color, ColorDef.black, (options && options.hiddenWidth ? options.hiddenWidth : 1), (options && options.hiddenStyle ? options.hiddenStyle : LinePixels.Code2)); + builderVis.setSymbology(color, ColorDef.black, options && options.visibleWidth ? options.visibleWidth : 3); + builderHid.setSymbology( + color, + ColorDef.black, + options && options.hiddenWidth ? options.hiddenWidth : 1, + options && options.hiddenStyle ? options.hiddenStyle : LinePixels.Code2, + ); if (undefined !== clipPlanesLoops) { ViewClipTool.addClipPlanesLoops(builderVis, clipPlanesLoops, true); ViewClipTool.addClipPlanesLoops(builderHid, clipPlanesLoops, true); if (options && options.fillClipPlanes) { - const fill = (options.fill ? options.fill : EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), context.viewport)); + const fill = options.fill + ? options.fill + : EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), context.viewport); const builderFill = context.createGraphicBuilder(GraphicType.WorldDecoration); builderFill.setSymbology(fill, fill, 0); - ViewClipTool.addClipPlanesLoops(builderFill, (options.hasPrimaryPlane ? [clipPlanesLoops[0]] : clipPlanesLoops), false); + ViewClipTool.addClipPlanesLoops(builderFill, options.hasPrimaryPlane ? [clipPlanesLoops[0]] : clipPlanesLoops, false); context.addDecorationFromBuilder(builderFill); } } else if (undefined !== clipShape) { @@ -350,7 +403,15 @@ export class ViewClipTool extends PrimitiveTool { return prim; } - public static drawClipPlanesLoops(context: DecorateContext, loops: GeometryQuery[], color: ColorDef, weight: number, dashed?: boolean, fill?: ColorDef, id?: string): void { + public static drawClipPlanesLoops( + context: DecorateContext, + loops: GeometryQuery[], + color: ColorDef, + weight: number, + dashed?: boolean, + fill?: ColorDef, + id?: string, + ): void { if (loops.length < 1) return; @@ -443,7 +504,9 @@ export class ViewClipClearTool extends ViewClipTool { public static override toolId = "ViewClip.Clear"; public static override iconSpec = "icon-section-tool"; /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && ViewClipTool.hasClip(vp)); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && ViewClipTool.hasClip(vp)); + } /** @internal */ protected override showPrompt(): void { const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, CoreTools.translate("ViewClip.Clear.Prompts.FirstPoint")); @@ -483,18 +546,28 @@ export class ViewClipByPlaneTool extends ViewClipTool { /** @internal */ private _orientationValue: DialogItemValue = { value: ContextRotationId.Face }; - constructor(clipEventHandler?: ViewClipEventHandler, protected _clearExistingPlanes: boolean = false) { super(clipEventHandler); } + constructor(clipEventHandler?: ViewClipEventHandler, protected _clearExistingPlanes: boolean = false) { + super(clipEventHandler); + } /** @internal */ - public get orientation(): ContextRotationId { return this._orientationValue.value as ContextRotationId; } - public set orientation(option: ContextRotationId) { this._orientationValue.value = option; } + public get orientation(): ContextRotationId { + return this._orientationValue.value as ContextRotationId; + } + public set orientation(option: ContextRotationId) { + this._orientationValue.value = option; + } /** @internal */ public override supplyToolSettingsProperties(): DialogItem[] | undefined { const initialValue = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValue(this.toolId, ViewClipTool._orientationName); initialValue && (this._orientationValue = initialValue); const toolSettings = new Array(); - const settingsItem: DialogItem = { value: this._orientationValue, property: ViewClipTool._getEnumAsOrientationDescription(), editorPosition: { rowPriority: 0, columnIndex: 2 } }; + const settingsItem: DialogItem = { + value: this._orientationValue, + property: ViewClipTool._getEnumAsOrientationDescription(), + editorPosition: { rowPriority: 0, columnIndex: 2 }, + }; toolSettings.push(settingsItem); return toolSettings; } @@ -504,7 +577,10 @@ export class ViewClipByPlaneTool extends ViewClipTool { if (updatedValue.propertyName === ViewClipTool._orientationName) { this._orientationValue = updatedValue.value; if (this._orientationValue) { - IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: ViewClipTool._orientationName, value: this._orientationValue }); + IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { + propertyName: ViewClipTool._orientationName, + value: this._orientationValue, + }); return true; } } @@ -518,11 +594,39 @@ export class ViewClipByPlaneTool extends ViewClipTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -573,15 +677,23 @@ export class ViewClipByShapeTool extends ViewClipTool { protected _zHigh?: number; /** @internal */ - public get orientation(): ContextRotationId { return this._orientationValue.value as ContextRotationId; } - public set orientation(option: ContextRotationId) { this._orientationValue.value = option; } + public get orientation(): ContextRotationId { + return this._orientationValue.value as ContextRotationId; + } + public set orientation(option: ContextRotationId) { + this._orientationValue.value = option; + } /** @internal */ public override supplyToolSettingsProperties(): DialogItem[] | undefined { const initialValue = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValue(this.toolId, ViewClipTool._orientationName); initialValue && (this._orientationValue = initialValue); const toolSettings = new Array(); - toolSettings.push({ value: this._orientationValue, property: ViewClipTool._getEnumAsOrientationDescription(), editorPosition: { rowPriority: 0, columnIndex: 2 } }); + toolSettings.push({ + value: this._orientationValue, + property: ViewClipTool._getEnumAsOrientationDescription(), + editorPosition: { rowPriority: 0, columnIndex: 2 }, + }); return toolSettings; } @@ -595,7 +707,10 @@ export class ViewClipByShapeTool extends ViewClipTool { this._matrix = undefined; AccuDrawHintBuilder.deactivate(); this.setupAndPromptForNextAction(); - IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: ViewClipTool._orientationName, value: this._orientationValue }); + IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { + propertyName: ViewClipTool._orientationName, + value: this._orientationValue, + }); return true; } return false; @@ -623,16 +738,59 @@ export class ViewClipByShapeTool extends ViewClipTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (this._points.length > 1) - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (0 !== this._points.length) - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), + CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -802,17 +960,55 @@ export class ViewClipByRangeTool extends ViewClipTool { /** @internal */ protected override showPrompt(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, CoreTools.translate(undefined === this._corner ? "ViewClip.ByRange.Prompts.FirstPoint" : "ViewClip.ByRange.Prompts.NextPoint")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + CoreTools.translate(undefined === this._corner ? "ViewClip.ByRange.Prompts.FirstPoint" : "ViewClip.ByRange.Prompts.NextPoint"), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (undefined !== this._corner) - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), + CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -918,7 +1114,9 @@ export class ViewClipByElementTool extends ViewClipTool { public static override toolId = "ViewClip.ByElement"; public static override iconSpec = "icon-section-element"; - constructor(clipEventHandler?: ViewClipEventHandler, protected _alwaysUseRange: boolean = false) { super(clipEventHandler); } + constructor(clipEventHandler?: ViewClipEventHandler, protected _alwaysUseRange: boolean = false) { + super(clipEventHandler); + } /** @internal */ protected override showPrompt(): void { @@ -926,11 +1124,39 @@ export class ViewClipByElementTool extends ViewClipTool { const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -972,7 +1198,9 @@ export class ViewClipByElementTool extends ViewClipTool { if (0 === placements.length) return false; - const displayTransform = modelId && 1 === placements.length ? viewport.view.computeDisplayTransform({ modelId, elementId: placements[0].elementId }) : undefined; + const displayTransform = modelId && 1 === placements.length + ? viewport.view.computeDisplayTransform({ modelId, elementId: placements[0].elementId }) + : undefined; const range = new Range3d(); const transform = Transform.createIdentity(); if (!alwaysUseRange && 1 === placements.length) { @@ -1060,7 +1288,14 @@ export abstract class ViewClipModifyTool extends EditManipulator.HandleTool { protected _currentDistance: number = 0.0; private readonly _clipStyle: ClipStyle; - public constructor(manipulator: EditManipulator.HandleProvider, clip: ClipVector, vp: Viewport, hitId: string, ids: string[], controls: ViewClipControlArrow[]) { + public constructor( + manipulator: EditManipulator.HandleProvider, + clip: ClipVector, + vp: Viewport, + hitId: string, + ids: string[], + controls: ViewClipControlArrow[], + ) { super(manipulator); this._anchorIndex = ids.indexOf(hitId); this._ids = ids; @@ -1079,7 +1314,9 @@ export abstract class ViewClipModifyTool extends EditManipulator.HandleTool { } } - protected override get wantAccuSnap(): boolean { return false; } + protected override get wantAccuSnap(): boolean { + return false; + } protected override init(): void { super.init(); @@ -1094,7 +1331,11 @@ export abstract class ViewClipModifyTool extends EditManipulator.HandleTool { return undefined; // NOTE: Use AccuDraw z instead of view z if AccuDraw is explicitly enabled... - const anchorRay = ViewClipTool.getClipRayTransformed(this._controls[this._anchorIndex].origin, this._controls[this._anchorIndex].direction, transformFromClip); + const anchorRay = ViewClipTool.getClipRayTransformed( + this._controls[this._anchorIndex].origin, + this._controls[this._anchorIndex].direction, + transformFromClip, + ); const projectedPt = AccuDrawHintBuilder.projectPointToLineInView(ev.point, anchorRay.origin, anchorRay.direction, ev.viewport, true); if (undefined === projectedPt) return undefined; @@ -1114,7 +1355,11 @@ export abstract class ViewClipModifyTool extends EditManipulator.HandleTool { if (-1 === this._anchorIndex || Math.abs(this._currentDistance) < Geometry.smallMetricDistance) return; - const anchorRay = ViewClipTool.getClipRayTransformed(this._controls[this._anchorIndex].origin, this._controls[this._anchorIndex].direction, transformFromClip); + const anchorRay = ViewClipTool.getClipRayTransformed( + this._controls[this._anchorIndex].origin, + this._controls[this._anchorIndex].direction, + transformFromClip, + ); anchorRay.direction.scaleToLength(this._currentDistance, anchorRay.direction); const pt1 = anchorRay.fractionToPoint(0.0); const pt2 = anchorRay.fractionToPoint(1.0); @@ -1176,8 +1421,8 @@ export class ViewClipShapeModifyTool extends ViewClipModifyTool { const shapePts = ViewClipTool.getClipShapePoints(clipShape, 0.0); const adjustedPts: Point3d[] = []; for (let i = 0; i < shapePts.length; i++) { - const prevFace = (0 === i ? shapePts.length - 2 : i - 1); - const nextFace = (shapePts.length - 1 === i ? 0 : i); + const prevFace = 0 === i ? shapePts.length - 2 : i - 1; + const nextFace = shapePts.length - 1 === i ? 0 : i; const prevSelected = offsetAll || (prevFace === this._anchorIndex || this.manipulator.iModel.selectionSet.has(this._ids[prevFace])); const nextSelected = offsetAll || (nextFace === this._anchorIndex || this.manipulator.iModel.selectionSet.has(this._ids[nextFace])); if (prevSelected && nextSelected) { @@ -1210,8 +1455,8 @@ export class ViewClipShapeModifyTool extends ViewClipModifyTool { zLow = clipExtents.low - localOffset; if (zHighSelected) zHigh = clipExtents.high + localOffset; - const realZLow = (undefined === zLow ? clipExtents.low : zLow); - const realZHigh = (undefined === zHigh ? clipExtents.high : zHigh); + const realZLow = undefined === zLow ? clipExtents.low : zLow; + const realZHigh = undefined === zHigh ? clipExtents.high : zHigh; if (realZLow > realZHigh) { zLow = realZHigh; zHigh = realZLow; @@ -1334,10 +1579,18 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { this.iModel.selectionSet.replace(this._clipId); } - public get clipId(): string | undefined { return this._clipId; } - public get clipShape(): ClipShape | undefined { return this._clipShape; } - public get clipPlaneSet(): ConvexClipPlaneSet | undefined { return this._clipPlanes; } - public getControlIndex(id: string): number { return this._controlIds.indexOf(id); } + public get clipId(): string | undefined { + return this._clipId; + } + public get clipShape(): ClipShape | undefined { + return this._clipShape; + } + public get clipPlaneSet(): ConvexClipPlaneSet | undefined { + return this._clipPlanes; + } + public getControlIndex(id: string): number { + return this._controlIds.indexOf(id); + } protected override stop(): void { const selectedId = (undefined !== this._clipId && this.iModel.selectionSet.has(this._clipId)) ? this._clipId : undefined; @@ -1357,7 +1610,13 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { } private getClipData(): boolean { - this._clip = this._clipShape = this._clipShapeExtents = this._clipPlanes = this._clipPlanesLoops = this._clipPlanesLoopsNoncontributing = undefined; + this._clip = + this._clipShape = + this._clipShapeExtents = + this._clipPlanes = + this._clipPlanesLoops = + this._clipPlanesLoopsNoncontributing = + undefined; let clip = this._clipView.view.getViewClip(); if (undefined === clip) return false; @@ -1403,7 +1662,13 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { this._clip = clip; return true; } - const clipPlanesLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipPlanes, this._clipView.computeViewRange(), true, false, true); + const clipPlanesLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange( + clipPlanes, + this._clipView.computeViewRange(), + true, + false, + true, + ); if (undefined !== clipPlanesLoops && clipPlanesLoops.length > clipPlanes.planes.length) return false; this._clipPlanesLoops = clipPlanesLoops; @@ -1449,7 +1714,14 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { const zFillColor = ColorDef.from(150, 150, 250); this._controls[numControls - 2] = new ViewClipControlArrow(shapeArea.origin, Vector3d.unitZ(-1.0), 0.75, zFillColor, undefined, "zLow"); - this._controls[numControls - 1] = new ViewClipControlArrow(shapeArea.origin.plusScaled(Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), Vector3d.unitZ(), 0.75, zFillColor, undefined, "zHigh"); + this._controls[numControls - 1] = new ViewClipControlArrow( + shapeArea.origin.plusScaled(Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), + Vector3d.unitZ(), + 0.75, + zFillColor, + undefined, + "zHigh", + ); return true; } @@ -1499,7 +1771,13 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { const defaultOutwardNormal = plane.getNormalRef().negate(); const expandedRange = viewRange.clone(); expandedRange.extend(defaultOrigin); - const nonContribLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(ConvexClipPlaneSet.createPlanes([this._clipPlanes.planes[i]]), expandedRange, true, false, true); + const nonContribLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange( + ConvexClipPlaneSet.createPlanes([this._clipPlanes.planes[i]]), + expandedRange, + true, + false, + true, + ); const nonContribColor = ColorDef.from(250, 100, 100); if (undefined !== nonContribLoops && nonContribLoops.length > 0) { @@ -1582,7 +1860,7 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { const planeSet = ConvexClipPlaneSet.createEmpty(); for (let i: number = 0; i < this._clipPlanes.planes.length; i++) { - const plane = (i === index ? this._clipPlanes.planes[i].cloneNegated() : this._clipPlanes.planes[i]); + const plane = i === index ? this._clipPlanes.planes[i].cloneNegated() : this._clipPlanes.planes[i]; planeSet.addPlaneToConvexSet(plane); } @@ -1644,7 +1922,7 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { faces.push(cap1); for (let i: number = 0; i < shapePtsLo.length; i++) { - const next = (i === shapePtsLo.length - 1 ? 0 : i + 1); + const next = i === shapePtsLo.length - 1 ? 0 : i + 1; const side = Loop.createPolygon([shapePtsLo[i].clone(), shapePtsLo[next].clone(), shapePtsHi[next].clone(), shapePtsHi[i].clone()]); faces.push(side); } @@ -1718,12 +1996,16 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { return false; const vp = this._clipView; - const anchorRay = ViewClipTool.getClipRayTransformed(this._controls[index].origin, this._controls[index].direction, undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined); + const anchorRay = ViewClipTool.getClipRayTransformed( + this._controls[index].origin, + this._controls[index].direction, + undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined, + ); // Try to align x direction with clip plane loop... - const loops = (undefined !== this._clipPlanesLoops ? this._clipPlanesLoops : this.getClipShapeFaceLoops()); - const loop = (loops ? (1 === loops.length ? loops[0] : this.getMatchingLoop(loops, anchorRay)) : undefined); - const vectorX = (loop ? this.getLoopPreferredX(loop, anchorRay.direction) : undefined); + const loops = undefined !== this._clipPlanesLoops ? this._clipPlanesLoops : this.getClipShapeFaceLoops(); + const loop = loops ? (1 === loops.length ? loops[0] : this.getMatchingLoop(loops, anchorRay)) : undefined; + const vectorX = loop ? this.getLoopPreferredX(loop, anchorRay.direction) : undefined; const matrix = Matrix3d.createIdentity(); if (undefined === vectorX || undefined === Matrix3d.createRigidFromColumns(anchorRay.direction, vectorX, AxisOrder.ZXY, matrix)) @@ -1744,12 +2026,14 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { if (undefined === matrix) return undefined; const worldUp = matrix.getColumn(2); - const planePt = (viewport.isContextRotationRequired ? viewport.getAuxCoordOrigin() : (viewport.view.isSpatialView() ? viewport.view.iModel.globalOrigin : Point3d.createZero())); + const planePt = viewport.isContextRotationRequired + ? viewport.getAuxCoordOrigin() + : (viewport.view.isSpatialView() ? viewport.view.iModel.globalOrigin : Point3d.createZero()); return Plane3dByOriginAndUnitNormal.create(planePt, worldUp); } private isAlignedToWorldUpPlane(plane: Plane3dByOriginAndUnitNormal, transformFromClip?: Transform): boolean { - const normal = (undefined !== transformFromClip ? transformFromClip.multiplyVector(Vector3d.unitZ()) : Vector3d.unitZ()); + const normal = undefined !== transformFromClip ? transformFromClip.multiplyVector(Vector3d.unitZ()) : Vector3d.unitZ(); return plane.getNormalRef().isParallelTo(normal, true); } @@ -1803,7 +2087,7 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { this._clipShape.transformToClip.multiplyPoint3d(zHigh, zHigh); } - const reversed = (zLow.z > zHigh.z); + const reversed = zLow.z > zHigh.z; const shape = ClipShape.createFrom(this._clipShape); shape.initSecondaryProps(shape.isMask, reversed ? zHigh.z : zLow.z, reversed ? zLow.z : zHigh.z, this._clipShape.transformFromClip); @@ -1823,7 +2107,9 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { return (this._clipEventHandler.onRightClick(hit, ev) ? EventHandled.Yes : EventHandled.No); } - protected override async onTouchTap(hit: HitDetail, ev: BeButtonEvent): Promise { return (hit.sourceId === this._clipId ? EventHandled.No : super.onTouchTap(hit, ev)); } + protected override async onTouchTap(hit: HitDetail, ev: BeButtonEvent): Promise { + return (hit.sourceId === this._clipId ? EventHandled.No : super.onTouchTap(hit, ev)); + } public override onManipulatorEvent(eventType: EditManipulator.EventType): void { this._suspendDecorator = false; @@ -1832,13 +2118,17 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { this._clipEventHandler.onModifyClip(this._clipView); } - public testDecorationHit(id: string): boolean { return (id === this._clipId || this._controlIds.includes(id)); } + public testDecorationHit(id: string): boolean { + return (id === this._clipId || this._controlIds.includes(id)); + } public async getDecorationToolTip(hit: HitDetail): Promise { if (hit.sourceId === this._clipId) return CoreTools.translate("ViewClip.Message.Clip"); return CoreTools.translate("ViewClip.Message.ModifyClip"); } - protected override updateDecorationListener(_add: boolean): void { super.updateDecorationListener(undefined !== this._clipId); } // Decorator isn't just for resize controls... + protected override updateDecorationListener(_add: boolean): void { + super.updateDecorationListener(undefined !== this._clipId); + } // Decorator isn't just for resize controls... public override decorate(context: DecorateContext): void { if (this._suspendDecorator) @@ -1852,14 +2142,43 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { return; if (undefined !== this._clipShape) { - ViewClipTool.drawClipShape(context, this._clipShape, this._clipShapeExtents!, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), 3, this._clipId); + ViewClipTool.drawClipShape( + context, + this._clipShape, + this._clipShapeExtents!, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), + 3, + this._clipId, + ); } else if (undefined !== this._clipPlanes) { if (undefined !== this._clipPlanesLoops) - ViewClipTool.drawClipPlanesLoops(context, this._clipPlanesLoops, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), 3, false, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), vp), this._clipId); + ViewClipTool.drawClipPlanesLoops( + context, + this._clipPlanesLoops, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), + 3, + false, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), vp), + this._clipId, + ); if (undefined !== this._clipPlanesLoopsNoncontributing) - ViewClipTool.drawClipPlanesLoops(context, this._clipPlanesLoopsNoncontributing, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.red, vp), 1, true); + ViewClipTool.drawClipPlanesLoops( + context, + this._clipPlanesLoopsNoncontributing, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.red, vp), + 1, + true, + ); } else if (undefined !== this._clipPlanesLoops) { - ViewClipTool.drawClipPlanesLoops(context, this._clipPlanesLoops, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), 3, false, EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), vp), this._clipId); + ViewClipTool.drawClipPlanesLoops( + context, + this._clipPlanesLoops, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.white, vp), + 3, + false, + EditManipulator.HandleUtils.adjustForBackgroundColor(ColorDef.from(0, 255, 255, 225), vp), + this._clipId, + ); } if (!this._isActive) @@ -1898,13 +2217,19 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { } } } - } else if (undefined !== this._controls[iFace].floatingOrigin && vp.isPointVisibleXY(this._controls[iFace].floatingOrigin!, CoordSystem.World, 0.1)) { + } else if ( + undefined !== this._controls[iFace].floatingOrigin && vp.isPointVisibleXY(this._controls[iFace].floatingOrigin!, CoordSystem.World, 0.1) + ) { this._controls[iFace].origin.setFrom(this._controls[iFace].floatingOrigin); this._controls[iFace].floatingOrigin = undefined; } } - const anchorRay = ViewClipTool.getClipRayTransformed(this._controls[iFace].origin, this._controls[iFace].direction, undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined); + const anchorRay = ViewClipTool.getClipRayTransformed( + this._controls[iFace].origin, + this._controls[iFace].direction, + undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined, + ); const transform = EditManipulator.HandleUtils.getArrowTransform(vp, anchorRay.origin, anchorRay.direction, sizeInches); if (undefined === transform) continue; @@ -1986,7 +2311,12 @@ export class ViewClipDecoration extends EditManipulator.HandleProvider { * @public * @extensions */ -export enum ClipEventType { New, NewPlane, Modify, Clear } +export enum ClipEventType { + New, + NewPlane, + Modify, + Clear, +} /** An implementation of ViewClipEventHandler that responds to new clips by presenting clip modification handles * @public @extensions @@ -2005,8 +2335,12 @@ export class ViewClipDecorationProvider implements ViewClipEventHandler { */ public readonly onActiveClipRightClick = new BeEvent<(hit: HitDetail, ev: BeButtonEvent, provider: ViewClipDecorationProvider) => void>(); - public selectOnCreate(): boolean { return this.selectDecorationOnCreate; } - public clearOnDeselect(): boolean { return this.clearDecorationOnDeselect; } + public selectOnCreate(): boolean { + return this.selectDecorationOnCreate; + } + public clearOnDeselect(): boolean { + return this.clearDecorationOnDeselect; + } public onNewClip(viewport: ScreenViewport): void { ViewClipDecoration.create(viewport, this); @@ -2028,7 +2362,7 @@ export class ViewClipDecorationProvider implements ViewClipEventHandler { } public onRightClick(hit: HitDetail, ev: BeButtonEvent): boolean { - const decoration = (undefined !== ev.viewport ? ViewClipDecoration.get(ev.viewport) : undefined); + const decoration = undefined !== ev.viewport ? ViewClipDecoration.get(ev.viewport) : undefined; if (undefined === decoration) return false; if (0 === this.onActiveClipRightClick.numberOfListeners) @@ -2037,10 +2371,18 @@ export class ViewClipDecorationProvider implements ViewClipEventHandler { return true; } - public showDecoration(vp: ScreenViewport): void { ViewClipDecoration.create(vp, this); } - public hideDecoration(): void { ViewClipDecoration.clear(); } - public async toggleDecoration(vp: ScreenViewport) { return ViewClipDecoration.toggle(vp, this); } - public isDecorationActive(vp: ScreenViewport): boolean { return (undefined !== ViewClipDecoration.get(vp)); } + public showDecoration(vp: ScreenViewport): void { + ViewClipDecoration.create(vp, this); + } + public hideDecoration(): void { + ViewClipDecoration.clear(); + } + public async toggleDecoration(vp: ScreenViewport) { + return ViewClipDecoration.toggle(vp, this); + } + public isDecorationActive(vp: ScreenViewport): boolean { + return (undefined !== ViewClipDecoration.get(vp)); + } public static create(): ViewClipDecorationProvider { if (undefined === ViewClipDecorationProvider._provider) { diff --git a/core/frontend/src/tools/EditManipulator.ts b/core/frontend/src/tools/EditManipulator.ts index 178615fe3b5f..d034270a5d47 100644 --- a/core/frontend/src/tools/EditManipulator.ts +++ b/core/frontend/src/tools/EditManipulator.ts @@ -6,8 +6,8 @@ * @module Tools */ -import { AxisOrder, Matrix3d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { ColorDef } from "@itwin/core-common"; +import { AxisOrder, Matrix3d, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; import { AccuDrawHintBuilder } from "../AccuDraw"; import { HitDetail } from "../HitDetail"; import { IModelApp } from "../IModelApp"; @@ -26,7 +26,7 @@ import { ManipulatorToolEvent } from "./ToolAdmin"; * - Respond to button events on the control handle decoration and run a sub-class of [[EditManipulator.HandleTool]] to modify. * @public * @extensions -*/ + */ export namespace EditManipulator { /** Specifies the event for [[EditManipulator.HandleProvider.onManipulatorEvent]] */ export enum EventType { @@ -35,7 +35,7 @@ export namespace EditManipulator { /** Control handle modification was cancelled by user. */ Cancel, /** Control handle modification was accepted by user. */ - Accept + Accept, } /** Interactive control handle modification is done by installing an [[InputCollector]]. @@ -74,12 +74,16 @@ export namespace EditManipulator { /** Whether to call [[AccuSnap.enableSnap]] for handle modification. * @return true to enable snapping to elements. */ - protected get wantAccuSnap(): boolean { return true; } + protected get wantAccuSnap(): boolean { + return true; + } /** Called from reset button up event to allow modification to be cancelled. * @return true to cancel modification. */ - protected cancel(_ev: BeButtonEvent): boolean { return true; } + protected cancel(_ev: BeButtonEvent): boolean { + return true; + } /** Called from data button down event to check if enough input has been gathered to complete the modification. * @return true to complete modification. @@ -110,9 +114,15 @@ export namespace EditManipulator { return this.onComplete(ev, EventType.Cancel); } - public override async onTouchMove(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchMoveToMotion(ev); } - public override async onTouchComplete(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev); } - public override async onTouchCancel(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, BeButton.Reset); } + public override async onTouchMove(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchMoveToMotion(ev); + } + public override async onTouchComplete(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev); + } + public override async onTouchCancel(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, BeButton.Reset); + } public override async onPostInstall() { await super.onPostInstall(); @@ -134,7 +144,9 @@ export namespace EditManipulator { * Usually followed by a call to [[IModelApp.toolAdmin.startDefaultTool]] to immediately raise the [[ManipulatorToolEvent.Start]] event. */ public constructor(public iModel: IModelConnection) { - this._removeManipulatorToolListener = IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => this.onManipulatorToolEvent(tool, event)); + this._removeManipulatorToolListener = IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => + this.onManipulatorToolEvent(tool, event) + ); } /** Call to clear this handle provider. */ @@ -200,7 +212,7 @@ export namespace EditManipulator { } /** Sub-classes should override to display the pickable graphics for their controls. */ - public decorate(_context: DecorateContext): void { } + public decorate(_context: DecorateContext): void {} /** The provider is responsible for checking if modification by controls is valid. * May still wish to present controls for "transient" geometry in non-read/write applications, etc. @@ -215,7 +227,7 @@ export namespace EditManipulator { /** A provider can install an [[InputCollector]] to support interactive modification. * @return true if a tool was successfully run. * @see [[EditManipulator.HandleTool]] - */ + */ protected abstract modifyControls(_hit: HitDetail, _ev: BeButtonEvent): Promise; /* Create, update, or clear based on the current selection. */ @@ -234,13 +246,19 @@ export namespace EditManipulator { } /** Sub-classes can override to perform some operation for a double click on a handle. */ - protected async onDoubleClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { return EventHandled.No; } + protected async onDoubleClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Sub-classes can override to present a menu for a right click on a handle. */ - protected async onRightClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { return EventHandled.No; } + protected async onRightClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Sub-classes can override to respond to a touch tap on a handle. By default, handles are selected by touch drag and taps are ignored. */ - protected async onTouchTap(_hit: HitDetail, _ev: BeButtonEvent): Promise { return EventHandled.Yes; } + protected async onTouchTap(_hit: HitDetail, _ev: BeButtonEvent): Promise { + return EventHandled.Yes; + } /** Event raised by a PrimitiveTool that supports handle providers to allow a pickable decoration to respond to being located. */ public async onDecorationButtonEvent(hit: HitDetail, ev: BeButtonEvent): Promise { @@ -313,7 +331,15 @@ export namespace EditManipulator { } /** Return array of shape points representing a unit arrow in xy plane pointing in positive x direction. */ - public static getArrowShape(baseStart: number = 0.0, baseWidth: number = 0.15, tipStart: number = 0.55, tipEnd: number = 1.0, tipWidth: number = 0.3, flangeStart: number = tipStart, flangeWidth: number = baseWidth): Point3d[] { + public static getArrowShape( + baseStart: number = 0.0, + baseWidth: number = 0.15, + tipStart: number = 0.55, + tipEnd: number = 1.0, + tipWidth: number = 0.3, + flangeStart: number = tipStart, + flangeWidth: number = baseWidth, + ): Point3d[] { const shapePts: Point3d[] = []; shapePts[0] = Point3d.create(tipEnd, 0.0); shapePts[1] = Point3d.create(flangeStart, tipWidth); diff --git a/core/frontend/src/tools/ElementSetTool.ts b/core/frontend/src/tools/ElementSetTool.ts index 1c6927c22f77..32ca3bb3f3b6 100644 --- a/core/frontend/src/tools/ElementSetTool.ts +++ b/core/frontend/src/tools/ElementSetTool.ts @@ -10,6 +10,7 @@ import { CompressedId64Set, Id64, Id64Arg, Id64Array, Id64String, OrderedId64Arr import { ColorDef, QueryRowFormat } from "@itwin/core-common"; import { Point2d, Point3d, Range2d } from "@itwin/core-geometry"; import { AccuDrawHintBuilder } from "../AccuDraw"; +import { ViewRect } from "../common/ViewRect"; import { LocateFilterStatus, LocateResponse } from "../ElementLocateManager"; import { HitDetail } from "../HitDetail"; import { IModelApp } from "../IModelApp"; @@ -19,7 +20,6 @@ import { Pixel } from "../render/Pixel"; import { SelectionSet } from "../SelectionSet"; import { DecorateContext } from "../ViewContext"; import { Viewport } from "../Viewport"; -import { ViewRect } from "../common/ViewRect"; import { PrimitiveTool } from "./PrimitiveTool"; import { SelectionMethod } from "./SelectTool"; import { BeButton, BeButtonEvent, BeModifierKeys, CoreTools, EventHandled } from "./Tool"; @@ -51,7 +51,7 @@ export interface GroupMark { * and to manage their hilite state. * @see [[ElementSetTool]] * @public -*/ + */ export class ElementAgenda { /** The IDs of the elements in this agenda. * @note Prefer methods like [[ElementAgenda.add]] instead of modifying directly. @@ -62,7 +62,7 @@ export class ElementAgenda { */ public readonly groupMarks: GroupMark[] = []; public manageHiliteState = true; // Whether entries are hilited/unhilited as they are added/removed... - public constructor(public iModel: IModelConnection) { } + public constructor(public iModel: IModelConnection) {} /** Get the source for the last group added to this agenda, if applicable. The "source" is merely an indication of what the collection of elements represents. */ public getSource() { @@ -75,9 +75,15 @@ export class ElementAgenda { this.groupMarks[this.groupMarks.length - 1].source = val; } - public get isEmpty() { return this.length === 0; } - public get count() { return this.length; } - public get length() { return this.elements.length; } + public get isEmpty() { + return this.length === 0; + } + public get count() { + return this.length; + } + public get length() { + return this.elements.length; + } /** Create [[OrderedId64Array]] from agenda. */ public orderIds(): OrderedId64Array { @@ -131,10 +137,14 @@ export class ElementAgenda { } /** Return true if elementId is already in this agenda. */ - public has(id: string) { return this.elements.some((entry) => id === entry); } + public has(id: string) { + return this.elements.some((entry) => id === entry); + } /** Return true if elementId is already in this agenda. */ - public find(id: Id64String) { return this.has(id); } + public find(id: Id64String) { + return this.has(id); + } /** Add elements to this agenda. */ public add(arg: Id64Arg) { @@ -182,12 +192,12 @@ export class ElementAgenda { if (0 === groupEnd) { if (iMark + 1 === groupMarks.length) { markToErase = iMark; - removeSingleEntry = (ModifyElementSource.DragSelect === groupMarks[iMark].source); + removeSingleEntry = ModifyElementSource.DragSelect === groupMarks[iMark].source; groupStart = groupMarks[iMark].start; groupEnd = elements.length; } else if (groupMarks[iMark].start <= groupIndex && groupMarks[iMark + 1].start > groupIndex) { markToErase = iMark; - removeSingleEntry = (ModifyElementSource.DragSelect === groupMarks[iMark].source); + removeSingleEntry = ModifyElementSource.DragSelect === groupMarks[iMark].source; groupStart = groupMarks[iMark].start; groupEnd = groupMarks[iMark + 1].start; } @@ -198,7 +208,7 @@ export class ElementAgenda { if (removeSingleEntry) groupMarks[iMark].start -= 1; // Only removing single entry, not entire group... else - groupMarks[iMark].start -= (groupEnd - groupStart); // Adjust indices... + groupMarks[iMark].start -= groupEnd - groupStart; // Adjust indices... } if (removeSingleEntry) { // Only remove single entry... @@ -303,82 +313,110 @@ export abstract class ElementSetTool extends PrimitiveTool { } /** Convenience method to get current count from [[ElementSetTool.agenda]]. */ - protected get currentElementCount(): number { return undefined !== this._agenda ? this._agenda.count : 0; } + protected get currentElementCount(): number { + return undefined !== this._agenda ? this._agenda.count : 0; + } /** Minimum required number of elements for tool to be able to complete. * @return number to compare with [[ElementSetTool.currentElementCount]] to determine if more elements remain to be identified. * @note A tool to subtract elements is an example where returning 2 would be necessary. */ - protected get requiredElementCount(): number { return 1; } + protected get requiredElementCount(): number { + return 1; + } /** Whether to allow element identification by drag box or crossing line selection. * @return true to allow drag select as an element source when the ctrl key is down. * @note Use ctrl+left drag for box selection. Inside/overlap is based on left/right direction (shift key inverts). * @note Use ctrl+right drag for crossing line selection. */ - protected get allowDragSelect(): boolean { return false; } + protected get allowDragSelect(): boolean { + return false; + } /** Support operations on groups/assemblies independent of selection scope. * @return true to add or remove all members of an assembly from [[ElementSetTool.agenda]] when any single member is identified. * @note Applies to [[ElementSetTool.getLocateCandidates]] only. */ - protected get allowGroups(): boolean { return false; } + protected get allowGroups(): boolean { + return false; + } /** Whether [[ElementSetTool.agenda]] should be populated from an active selection set. * @return true to allow selection sets as an element source. * @note A selection set must have at least [[ElementSetTool.requiredElementCount]] elements to be considered. */ - protected get allowSelectionSet(): boolean { return false; } + protected get allowSelectionSet(): boolean { + return false; + } /** Whether to clear the active selection set for tools that return false for [[ElementSetTool.allowSelectionSet]]. * @return true to clear unsupported selection sets (desired default behavior). * @note It is expected that the selection set be cleared before using [[ElementLocateManager]] to identify elements. * This allows the element hilite to be a visual representation of the [[ElementSetTool.agenda]] contents. */ - protected get clearSelectionSet(): boolean { return !this.allowSelectionSet; } + protected get clearSelectionSet(): boolean { + return !this.allowSelectionSet; + } /** Whether a selection set should be processed immediately upon installation or require a data button to accept. * @return false only for tools without settings or a need for confirmation. * @note A tool to delete elements is an example where returning false could be desirable. */ - protected get requireAcceptForSelectionSetOperation(): boolean { return true; } + protected get requireAcceptForSelectionSetOperation(): boolean { + return true; + } /** Whether to begin dynamics for a selection set immediately or wait for a data button. * @return false for tools that can start showing dynamics without any additional input. * @note A tool to rotate elements by an active angle setting is an example where returning false could be desirable. */ - protected get requireAcceptForSelectionSetDynamics(): boolean { return true; } + protected get requireAcceptForSelectionSetDynamics(): boolean { + return true; + } /** Whether original source of elements being modified was the active selection set. * @return true when [[ElementSetTool.allowSelectionSet]] and active selection set count >= [[ElementSetTool.requiredElementCount]]. */ - protected get isSelectionSetModify(): boolean { return this._useSelectionSet; } + protected get isSelectionSetModify(): boolean { + return this._useSelectionSet; + } /** Whether drag box or crossing line selection is currently active. * @return true when [[ElementSetTool.allowDragSelect]] and corner points are currently being defined. */ - protected get isSelectByPoints(): boolean { return undefined !== this.dragStartPoint; } + protected get isSelectByPoints(): boolean { + return undefined !== this.dragStartPoint; + } /** Whether to continue selection of additional elements by holding the ctrl key down. * @return true to continue the element identification phase beyond [[ElementSetTool.requiredElementCount]] by holding down the ctrl key. */ - protected get controlKeyContinuesSelection(): boolean { return false; } + protected get controlKeyContinuesSelection(): boolean { + return false; + } /** Whether to invert selection of elements identified with the ctrl key held down. * @return true to allow ctrl to deselect already selected elements. */ - protected get controlKeyInvertsSelection(): boolean { return this.controlKeyContinuesSelection; } + protected get controlKeyInvertsSelection(): boolean { + return this.controlKeyContinuesSelection; + } /** Whether [[ElementSetTool.setupAndPromptForNextAction]] should call [[AccuSnap.enableSnap]] for current tool phase. * @return true to enable snapping to elements. * @note A tool that just needs to identify elements and doesn't care about location should not enable snapping. */ - protected get wantAccuSnap(): boolean { return false; } + protected get wantAccuSnap(): boolean { + return false; + } /** Whether to automatically start element dynamics after all required elements have been identified. * @return true if tool will implement [[InteractiveTool.onDynamicFrame]] to show element dynamics. */ - protected get wantDynamics(): boolean { return false; } + protected get wantDynamics(): boolean { + return false; + } /** Whether tool is done identifying elements and is ready to move to the next phase. * @return true when [[ElementSetTool.requiredElementCount]] is not yet satisfied or ctrl key is being used to extend selection. @@ -399,17 +437,21 @@ export abstract class ElementSetTool extends PrimitiveTool { * @return true if tool does not yet have enough information to complete. * @note When [[ElementSetTool.wantDynamics]] is true an additional point is automatically required to support the dynamic preview. */ - protected get wantAdditionalInput(): boolean { return (!this.isDynamicsStarted && this.wantDynamics); } + protected get wantAdditionalInput(): boolean { + return (!this.isDynamicsStarted && this.wantDynamics); + } /** Whether the tool is ready for [[ElementSetTool.processAgenda]] to be called to complete the tool operation. * Sub-classes should override to collect additional point input before calling super or [[ElementSetTool.wantAdditionalInput]]. * @return true if tool has enough information and is ready to complete. */ - protected wantProcessAgenda(_ev: BeButtonEvent): boolean { return !this.wantAdditionalInput; } + protected wantProcessAgenda(_ev: BeButtonEvent): boolean { + return !this.wantAdditionalInput; + } /** Whether tool should operate on an existing selection set or instead prompt user to identity elements. * Unsupported selection sets will be cleared when [[ElementSetTool.clearSelectionSet]] is true. - */ + */ protected setPreferredElementSource(): void { this._useSelectionSet = false; if (!this.iModel.selectionSet.isActive) @@ -457,12 +499,13 @@ export abstract class ElementSetTool extends PrimitiveTool { try { // When assembly parent is selected, pick all geometric elements with it as the parent. // When assembly member is selected, pick the parent as well as all the other members. - const ecsql = `SELECT ECInstanceId as id, Parent.Id as parentId FROM BisCore.GeometricElement WHERE Parent.Id IN (SELECT Parent.Id as parentId FROM BisCore.GeometricElement WHERE (parent.Id IS NOT NULL AND ECInstanceId IN (${id})) OR parent.Id IN (${id}))`; + const ecsql = + `SELECT ECInstanceId as id, Parent.Id as parentId FROM BisCore.GeometricElement WHERE Parent.Id IN (SELECT Parent.Id as parentId FROM BisCore.GeometricElement WHERE (parent.Id IS NOT NULL AND ECInstanceId IN (${id})) OR parent.Id IN (${id}))`; for await (const row of this.iModel.createQueryReader(ecsql, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { ids.add(row.parentId as Id64String); ids.add(row.id as Id64String); } - } catch { } + } catch {} return ids; } @@ -502,7 +545,13 @@ export abstract class ElementSetTool extends PrimitiveTool { /** Get element ids to process from drag box or crossing line selection. * Sub-classes may override to support selection scopes or apply tool specific filtering. */ - protected async getDragSelectCandidates(vp: Viewport, origin: Point3d, corner: Point3d, method: SelectionMethod, overlap: boolean): Promise { + protected async getDragSelectCandidates( + vp: Viewport, + origin: Point3d, + corner: Point3d, + method: SelectionMethod, + overlap: boolean, + ): Promise { let contents = new Set(); // TODO: Include option to use IModelConnection.getGeometryContainment instead of readPixels. No/Yes/2dOnly... @@ -653,7 +702,7 @@ export abstract class ElementSetTool extends PrimitiveTool { return (undefined !== hit && this.buildLocateAgenda(hit)); // If next element is already in agenda (part of a group, etc.) don't re-add group... - const addNext = (undefined !== hit && !this.agenda.has(hit.sourceId)); + const addNext = undefined !== hit && !this.agenda.has(hit.sourceId); this.agenda.popGroup(); if (!addNext || !await this.buildLocateAgenda(hit)) @@ -671,7 +720,7 @@ export abstract class ElementSetTool extends PrimitiveTool { return false; const pt1 = ev.viewport.worldToView(this.dragStartPoint); const pt2 = ev.viewport.worldToView(ev.point); - const overlapMode = (pt1.x > pt2.x); + const overlapMode = pt1.x > pt2.x; return (ev.isShiftKey ? !overlapMode : overlapMode); // Shift inverts inside/overlap selection... } @@ -724,9 +773,9 @@ export abstract class ElementSetTool extends PrimitiveTool { return; const vp = context.viewport; - const bestContrastIsBlack = (ColorDef.black === vp.getContrastToBackgroundColor()); - const crossingLine = (BeButton.Reset === ev.button); - const overlapSelection = (crossingLine || this.useOverlapSelection(ev)); + const bestContrastIsBlack = ColorDef.black === vp.getContrastToBackgroundColor(); + const crossingLine = BeButton.Reset === ev.button; + const overlapSelection = crossingLine || this.useOverlapSelection(ev); const position = vp.worldToView(this.dragStartPoint); position.x = Math.floor(position.x) + 0.5; @@ -757,7 +806,9 @@ export abstract class ElementSetTool extends PrimitiveTool { } /** Show graphics for when drag selection is active. */ - public override decorate(context: DecorateContext): void { this.selectByPointsDecorate(context); } + public override decorate(context: DecorateContext): void { + this.selectByPointsDecorate(context); + } /** Make sure drag selection graphics are updated when mouse moves. */ public override async onMouseMotion(ev: BeButtonEvent): Promise { @@ -945,23 +996,27 @@ export abstract class ElementSetTool extends PrimitiveTool { /** Sub-classes can override to be notified of [[ElementSetTool.agenda]] changes by other methods. * @note Tools should not modify [[ElementSetTool.agenda]] in this method, it should merely serve as a convenient place * to update information, such as element graphics once dynamics has started, ex. [[ElementSetTool.chooseNextHit]]. - */ - protected async onAgendaModified(): Promise { } + */ + protected async onAgendaModified(): Promise {} /** Sub-classes can override to continue with current [[ElementSetTool.agenda]] or restart after processing has completed. */ - protected async onProcessComplete(): Promise { return this.onReinitialize(); } + protected async onProcessComplete(): Promise { + return this.onReinitialize(); + } /** Sub-classes that return false for [[ElementSetTool.requireAcceptForSelectionSetOperation]] should override to apply the tool operation to [[ElementSetTool.agenda]]. */ - protected async processAgendaImmediate(): Promise { } + protected async processAgendaImmediate(): Promise {} /** Sub-classes that require and use the accept point should override to apply the tool operation to [[ElementSetTool.agenda]]. * @note Not called for [[ElementSetTool.isSelectionSetModify]] when [[ElementSetTool.requireAcceptForSelectionSetOperation]] is false. */ - protected async processAgenda(_ev: BeButtonEvent): Promise { return this.processAgendaImmediate(); } + protected async processAgenda(_ev: BeButtonEvent): Promise { + return this.processAgendaImmediate(); + } /** Support either [[ElementSetTool.requireAcceptForSelectionSetOperation]] or [[ElementSetTool.requireAcceptForSelectionSetDynamics]] returning false. */ protected async doProcessSelectionSetImmediate(): Promise { - const buildImmediate = (!this.requireAcceptForSelectionSetOperation || (this.wantDynamics && !this.requireAcceptForSelectionSetDynamics)); + const buildImmediate = !this.requireAcceptForSelectionSetOperation || (this.wantDynamics && !this.requireAcceptForSelectionSetDynamics); if (!buildImmediate) return; @@ -1008,8 +1063,14 @@ export abstract class ElementSetTool extends PrimitiveTool { this.provideToolAssistance(); } - protected get shouldEnableLocate(): boolean { return this.isSelectByPoints ? false : this.wantAdditionalElements; } - protected get shouldEnableSnap(): boolean { return this.isSelectByPoints ? false : (this.wantAccuSnap && (!this.isControlDown || !this.controlKeyContinuesSelection || !this.wantAdditionalElements)); } + protected get shouldEnableLocate(): boolean { + return this.isSelectByPoints ? false : this.wantAdditionalElements; + } + protected get shouldEnableSnap(): boolean { + return this.isSelectByPoints + ? false + : (this.wantAccuSnap && (!this.isControlDown || !this.controlKeyContinuesSelection || !this.wantAdditionalElements)); + } /** Setup auto-locate, AccuSnap, AccuDraw, and supply tool assistance. */ protected setupAndPromptForNextAction(): void { @@ -1063,16 +1124,48 @@ export abstract class ElementSetTool extends PrimitiveTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse), + ); + + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse), + ); if (addDragInstr) { - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.BoxCorners"), false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.RightClickDrag, CoreTools.translate("ElementSet.Inputs.CrossingLine"), false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.BoxCorners"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.RightClickDrag, + CoreTools.translate("ElementSet.Inputs.CrossingLine"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.OverlapSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } if (undefined !== additionalInstr) { @@ -1088,7 +1181,10 @@ export abstract class ElementSetTool extends PrimitiveTool { sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel)); - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, undefined !== mainInstrText ? mainInstrText : CoreTools.translate(mainMsg)); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + undefined !== mainInstrText ? mainInstrText : CoreTools.translate(mainMsg), + ); const instructions = ToolAssistance.createInstructions(mainInstruction, sections); IModelApp.notifications.setToolAssistance(instructions); } diff --git a/core/frontend/src/tools/EventController.ts b/core/frontend/src/tools/EventController.ts index 5652b6767d67..e52a71bd331d 100644 --- a/core/frontend/src/tools/EventController.ts +++ b/core/frontend/src/tools/EventController.ts @@ -24,7 +24,18 @@ export class EventController { return; // Put events on the parentDiv to allows us to stopPropagation of events to the view canvas when they are meant for a sibling of view canvas (markup canvas, for example). - this.addDomListeners(["mousedown", "mouseup", "mousemove", "mouseover", "mouseout", "wheel", "touchstart", "touchend", "touchcancel", "touchmove"], element); + this.addDomListeners([ + "mousedown", + "mouseup", + "mousemove", + "mouseover", + "mouseout", + "wheel", + "touchstart", + "touchend", + "touchcancel", + "touchmove", + ], element); element.oncontextmenu = element.onselectstart = () => false; } diff --git a/core/frontend/src/tools/IdleTool.ts b/core/frontend/src/tools/IdleTool.ts index cc55bd4bebc7..033ee1e5749a 100644 --- a/core/frontend/src/tools/IdleTool.ts +++ b/core/frontend/src/tools/IdleTool.ts @@ -100,7 +100,9 @@ export class IdleTool extends InteractiveTool { return EventHandled.Yes; } - public override async onMouseWheel(ev: BeWheelEvent) { return IModelApp.toolAdmin.processWheelEvent(ev, true); } + public override async onMouseWheel(ev: BeWheelEvent) { + return IModelApp.toolAdmin.processWheelEvent(ev, true); + } public override async onTouchMoveStart(ev: BeTouchEvent, startEv: BeTouchEvent): Promise { const tool = new DefaultViewTouchTool(startEv, ev); @@ -124,6 +126,8 @@ export class IdleTool extends InteractiveTool { return EventHandled.No; } - public async exitTool() { } - public override async run() { return true; } + public async exitTool() {} + public override async run() { + return true; + } } diff --git a/core/frontend/src/tools/MeasureTool.ts b/core/frontend/src/tools/MeasureTool.ts index a35596f2ce0f..fcfb0062101f 100644 --- a/core/frontend/src/tools/MeasureTool.ts +++ b/core/frontend/src/tools/MeasureTool.ts @@ -6,15 +6,32 @@ * @module Measure */ +import { DialogItem, DialogItemValue, DialogPropertySyncItem, PropertyDescription } from "@itwin/appui-abstract"; import { Id64, Id64Array, Id64String } from "@itwin/core-bentley"; import { - AxisOrder, IModelJson, Matrix3d, Plane3dByOriginAndUnitNormal, Point2d, Point3d, PointString3d, PolygonOps, Vector3d, XAndY, XYAndZ, -} from "@itwin/core-geometry"; -import { - BentleyStatus, ColorDef, GeometryStreamProps, LinePixels, MassPropertiesOperation, MassPropertiesRequestProps, MassPropertiesResponseProps, + BentleyStatus, + ColorDef, + GeometryStreamProps, + LinePixels, + MassPropertiesOperation, + MassPropertiesRequestProps, + MassPropertiesResponseProps, } from "@itwin/core-common"; -import { DialogItem, DialogItemValue, DialogPropertySyncItem, PropertyDescription } from "@itwin/appui-abstract"; +import { + AxisOrder, + IModelJson, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + PointString3d, + PolygonOps, + Vector3d, + XAndY, + XYAndZ, +} from "@itwin/core-geometry"; import { AccuDrawHintBuilder, ContextRotationId } from "../AccuDraw"; +import { GraphicType } from "../common/render/GraphicType"; import { LocateFilterStatus, LocateResponse } from "../ElementLocateManager"; import { HitDetail, HitGeomType } from "../HitDetail"; import { IModelApp } from "../IModelApp"; @@ -27,7 +44,6 @@ import { Viewport } from "../Viewport"; import { PrimitiveTool } from "./PrimitiveTool"; import { BeButtonEvent, BeModifierKeys, CoreTools, EventHandled, InputSource } from "./Tool"; import { ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection } from "./ToolAssistance"; -import { GraphicType } from "../common/render/GraphicType"; function translateBold(key: string) { return `${CoreTools.translate(`Measure.Labels.${key}`)}: `; @@ -102,7 +118,9 @@ class MeasureMarker extends Marker { this.labelOffset = { x: 0, y: -1 }; } - public override onMouseButton(_ev: BeButtonEvent): boolean { return true; } // Never forward event to active tool... + public override onMouseButton(_ev: BeButtonEvent): boolean { + return true; + } // Never forward event to active tool... public override onMouseEnter(ev: BeButtonEvent) { super.onMouseEnter(ev); @@ -118,9 +136,24 @@ class MeasureMarker extends Marker { } /** @internal */ -interface Location { point: Point3d, adjustedPoint: Point3d, refAxes: Matrix3d } +interface Location { + point: Point3d; + adjustedPoint: Point3d; + refAxes: Matrix3d; +} /** @internal */ -interface Segment { distance: number, slope: number, start: Point3d, end: Point3d, delta: Vector3d, adjustedStart: Point3d, adjustedEnd: Point3d, adjustedDelta: Vector3d, refAxes: Matrix3d, marker: MeasureMarker } +interface Segment { + distance: number; + slope: number; + start: Point3d; + end: Point3d; + delta: Vector3d; + adjustedStart: Point3d; + adjustedEnd: Point3d; + adjustedDelta: Vector3d; + refAxes: Matrix3d; + marker: MeasureMarker; +} /** @internal */ function adjustPoint(ev: BeButtonEvent, segments?: Array, locations?: Array): Point3d { @@ -145,10 +178,11 @@ function adjustPoint(ev: BeButtonEvent, segments?: Array, locations?: A } } - if (locations) + if (locations) { for (const loc of locations) if (loc.point.isExactEqual(ev.point)) return loc.adjustedPoint.clone(); + } return ev.point; } @@ -175,13 +209,21 @@ export class MeasureDistanceTool extends PrimitiveTool { protected _lastMotionAdjustedPt?: Point3d; /** @internal */ - protected allowView(vp: Viewport) { return vp.view.isSpatialView() || vp.view.isDrawingView(); } + protected allowView(vp: Viewport) { + return vp.view.isSpatialView() || vp.view.isDrawingView(); + } /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); + } /** @internal */ - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } /** @internal */ - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } /** @internal */ public override async onPostInstall() { await super.onPostInstall(); @@ -189,27 +231,89 @@ export class MeasureDistanceTool extends PrimitiveTool { } /** @internal */ - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } /** @internal */ protected showPrompt(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, CoreTools.translate(0 === this._locationData.length ? "Measure.Distance.Prompts.FirstPoint" : "Measure.Distance.Prompts.NextPoint")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + CoreTools.translate(0 === this._locationData.length ? "Measure.Distance.Prompts.FirstPoint" : "Measure.Distance.Prompts.NextPoint"), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (0 === this._locationData.length) { if (this._acceptedSegments.length > 0) { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } } else { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Cancel"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Cancel"), false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Cancel"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Cancel"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), + CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } const sections: ToolAssistanceSection[] = []; @@ -232,7 +336,9 @@ export class MeasureDistanceTool extends PrimitiveTool { } /** @internal */ - public override testDecorationHit(id: string): boolean { return id === this._snapGeomId; } + public override testDecorationHit(id: string): boolean { + return id === this._snapGeomId; + } /** @internal */ protected getSnapPoints(): Point3d[] | undefined { @@ -247,9 +353,10 @@ export class MeasureDistanceTool extends PrimitiveTool { snapPoints.push(seg.end); } - if (this._locationData.length > 1) + if (this._locationData.length > 1) { for (const loc of this._locationData) snapPoints.push(loc.point); + } return snapPoints; } @@ -402,9 +509,13 @@ export class MeasureDistanceTool extends PrimitiveTool { } /** @internal */ - public override decorate(context: DecorateContext): void { this.createDecorations(context, false); } + public override decorate(context: DecorateContext): void { + this.createDecorations(context, false); + } /** @internal */ - public override decorateSuspended(context: DecorateContext): void { this.createDecorations(context, true); } + public override decorateSuspended(context: DecorateContext): void { + this.createDecorations(context, true); + } /** @internal */ public override async onMouseMotion(ev: BeButtonEvent): Promise { @@ -425,7 +536,9 @@ export class MeasureDistanceTool extends PrimitiveTool { protected reportMeasurements(): void { if (undefined === this._totalDistanceMarker) return; - const briefMsg = `${CoreTools.translate(this._acceptedSegments.length > 1 ? "Measure.Labels.CumulativeDistance" : "Measure.Labels.Distance")}: ${this._totalDistanceMarker.label}`; + const briefMsg = `${ + CoreTools.translate(this._acceptedSegments.length > 1 ? "Measure.Labels.CumulativeDistance" : "Measure.Labels.Distance") + }: ${this._totalDistanceMarker.label}`; const msgDetail = new NotifyMessageDetails(OutputMessagePriority.Info, briefMsg, undefined, OutputMessageType.Sticky); IModelApp.notifications.outputMessage(msgDetail); } @@ -448,8 +561,8 @@ export class MeasureDistanceTool extends PrimitiveTool { } protected async getMarkerToolTip(distance: number, slope: number, start: Point3d, end: Point3d, delta?: Vector3d): Promise { - const is3d = (undefined === this.targetView || this.targetView.view.is3d()); - const isSpatial = (undefined !== this.targetView && this.targetView.view.isSpatialView()); + const is3d = undefined === this.targetView || this.targetView.view.is3d(); + const isSpatial = undefined !== this.targetView && this.targetView.view.isSpatialView(); const toolTip = document.createElement("div"); const distanceFormatterSpec = await IModelApp.quantityFormatter.getFormatterSpecByQuantityType(QuantityType.Length); @@ -512,7 +625,13 @@ export class MeasureDistanceTool extends PrimitiveTool { /** @internal */ protected async updateSelectedMarkerToolTip(seg: any, ev: BeButtonEvent, reopenToolTip: boolean): Promise { - seg.marker.title = await this.getMarkerToolTip(seg.distance, seg.slope, seg.adjustedStart, seg.adjustedEnd, seg.marker.isSelected ? seg.adjustedDelta : undefined); + seg.marker.title = await this.getMarkerToolTip( + seg.distance, + seg.slope, + seg.adjustedStart, + seg.adjustedEnd, + seg.marker.isSelected ? seg.adjustedDelta : undefined, + ); if (!reopenToolTip || undefined === ev.viewport || !IModelApp.notifications.isToolTipOpen) return; IModelApp.notifications.clearToolTip(); @@ -528,7 +647,7 @@ export class MeasureDistanceTool extends PrimitiveTool { const distance = adjustedStart.distance(adjustedEnd); const xyDist = adjustedStart.distanceXY(adjustedEnd); const zDist = adjustedEnd.z - adjustedStart.z; - const slope = (0.0 === xyDist ? Math.PI : Math.atan(zDist / xyDist)); + const slope = 0.0 === xyDist ? Math.PI : Math.atan(zDist / xyDist); const adjustedDelta = Vector3d.createStartEnd(adjustedStart, adjustedEnd); const refAxes = this._locationData[i].refAxes; refAxes.multiplyTransposeVectorInPlace(adjustedDelta); @@ -538,7 +657,12 @@ export class MeasureDistanceTool extends PrimitiveTool { refAxes.multiplyTransposeVectorInPlace(delta); const toolTip = await this.getMarkerToolTip(distance, slope, adjustedStart, adjustedEnd); - const marker = new MeasureMarker((this._acceptedSegments.length + 1).toString(), toolTip, start.interpolate(0.5, end), Point2d.create(25, 25)); + const marker = new MeasureMarker( + (this._acceptedSegments.length + 1).toString(), + toolTip, + start.interpolate(0.5, end), + Point2d.create(25, 25), + ); const segMarkerButtonFunc = (ev: BeButtonEvent) => { if (ev.isDown) @@ -549,16 +673,16 @@ export class MeasureDistanceTool extends PrimitiveTool { for (const seg of this._acceptedSegments) { if (!seg.marker.pick(ev.viewPoint)) continue; - selectedMarker = (seg.marker.isSelected ? undefined : seg.marker); + selectedMarker = seg.marker.isSelected ? undefined : seg.marker; pickedMarker = seg.marker; break; } for (const seg of this._acceptedSegments) { const wasSelected = seg.marker.isSelected; - seg.marker.isSelected = (seg.marker === selectedMarker); + seg.marker.isSelected = seg.marker === selectedMarker; if (wasSelected !== seg.marker.isSelected) - this.updateSelectedMarkerToolTip(seg, ev, (seg.marker === pickedMarker)); // eslint-disable-line @typescript-eslint/no-floating-promises + this.updateSelectedMarkerToolTip(seg, ev, seg.marker === pickedMarker); // eslint-disable-line @typescript-eslint/no-floating-promises } if (undefined !== ev.viewport) @@ -596,7 +720,11 @@ export class MeasureDistanceTool extends PrimitiveTool { if (undefined !== snap) { if (undefined !== snap.primitive) { const locDetail = snap.primitive.closestPoint(point, false); - if (undefined !== locDetail && (HitGeomType.Segment === snap.geomType || snap.primitive.isInPlane(Plane3dByOriginAndUnitNormal.create(point, undefined !== snap.normal ? snap.normal : normal)!))) { + if ( + undefined !== locDetail && + (HitGeomType.Segment === snap.geomType || + snap.primitive.isInPlane(Plane3dByOriginAndUnitNormal.create(point, undefined !== snap.normal ? snap.normal : normal)!)) + ) { const locRay = snap.primitive.fractionToPointAndUnitTangent(locDetail.fraction); tangent.setFrom(locRay.direction); if (undefined !== snap.normal) @@ -681,13 +809,21 @@ export class MeasureLocationTool extends PrimitiveTool { /** @internal */ protected readonly _acceptedLocations: MeasureMarker[] = []; /** @internal */ - protected allowView(vp: Viewport) { return vp.view.isSpatialView() || vp.view.isDrawingView(); } + protected allowView(vp: Viewport) { + return vp.view.isSpatialView() || vp.view.isDrawingView(); + } /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); + } /** @internal */ - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } /** @internal */ - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } /** @internal */ public override async onPostInstall() { await super.onPostInstall(); @@ -695,7 +831,9 @@ export class MeasureLocationTool extends PrimitiveTool { } /** @internal */ - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } /** @internal */ protected showPrompt(): void { @@ -704,11 +842,39 @@ export class MeasureLocationTool extends PrimitiveTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (0 !== this._acceptedLocations.length) { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } const sections: ToolAssistanceSection[] = []; @@ -726,8 +892,8 @@ export class MeasureLocationTool extends PrimitiveTool { } protected async getMarkerToolTip(point: Point3d): Promise { - const is3d = (undefined === this.targetView || this.targetView.view.is3d()); - const isSpatial = (undefined !== this.targetView && this.targetView.view.isSpatialView()); + const is3d = undefined === this.targetView || this.targetView.view.is3d(); + const isSpatial = undefined !== this.targetView && this.targetView.view.isSpatialView(); const toolTip = document.createElement("div"); let toolTipHtml = ""; @@ -760,7 +926,7 @@ export class MeasureLocationTool extends PrimitiveTool { const longDir = CoreTools.translate(cartographic.longitude < 0 ? "Measure.Labels.W" : "Measure.Labels.E"); toolTipHtml += `${translateBold("LatLong") + formattedLat + latDir}, ${formattedLong}${longDir}
`; toolTipHtml += `${translateBold("Altitude") + formattedHeight}
`; - } catch { } + } catch {} } } @@ -776,7 +942,9 @@ export class MeasureLocationTool extends PrimitiveTool { this._acceptedLocations.forEach((marker) => marker.addDecoration(context)); } /** @internal */ - public override decorateSuspended(context: DecorateContext): void { this.decorate(context); } + public override decorateSuspended(context: DecorateContext): void { + this.decorate(context); + } protected reportMeasurements(): void { if (0 === this._acceptedLocations.length) @@ -860,13 +1028,19 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { protected _lastMotionPt?: Point3d; /** @internal */ - public get orientation(): ContextRotationId { return this._orientationValue.value as ContextRotationId; } - public set orientation(option: ContextRotationId) { this._orientationValue.value = option; } + public get orientation(): ContextRotationId { + return this._orientationValue.value as ContextRotationId; + } + public set orientation(option: ContextRotationId) { + this._orientationValue.value = option; + } /** @internal */ protected static _orientationName = "enumAsOrientation"; /** @internal */ - protected static enumAsOrientationMessage(str: string) { return CoreTools.translate(`Settings.Orientation.${str}`); } + protected static enumAsOrientationMessage(str: string) { + return CoreTools.translate(`Settings.Orientation.${str}`); + } /** @internal */ protected static _getEnumAsOrientationDescription = (): PropertyDescription => { return { @@ -893,7 +1067,11 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { const initialValue = IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValue(this.toolId, MeasureAreaByPointsTool._orientationName); initialValue && (this._orientationValue = initialValue); const toolSettings = new Array(); - toolSettings.push({ value: this._orientationValue, property: MeasureAreaByPointsTool._getEnumAsOrientationDescription(), editorPosition: { rowPriority: 0, columnIndex: 2 } }); + toolSettings.push({ + value: this._orientationValue, + property: MeasureAreaByPointsTool._getEnumAsOrientationDescription(), + editorPosition: { rowPriority: 0, columnIndex: 2 }, + }); return toolSettings; } @@ -903,7 +1081,10 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { this._orientationValue = updatedValue.value; if (!this._orientationValue) return false; - IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: MeasureAreaByPointsTool._orientationName, value: this._orientationValue }); + IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { + propertyName: MeasureAreaByPointsTool._orientationName, + value: this._orientationValue, + }); await this.onReinitialize(); return true; } @@ -911,13 +1092,21 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { } /** @internal */ - protected allowView(vp: Viewport) { return vp.view.isSpatialView() || vp.view.isDrawingView(); } + protected allowView(vp: Viewport) { + return vp.view.isSpatialView() || vp.view.isDrawingView(); + } /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); + } /** @internal */ - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } /** @internal */ - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } /** @internal */ public override async onPostInstall() { await super.onPostInstall(); @@ -925,7 +1114,9 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { } /** @internal */ - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } /** @internal */ protected showPrompt(): void { @@ -958,9 +1149,24 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, resetMsg, false, ToolAssistanceInputMethod.Mouse)); if (this._points.length > 1) - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AdditionalPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (0 !== this._points.length) - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo([ToolAssistance.ctrlKey, "Z"]), + CoreTools.translate("ElementSet.Inputs.UndoLastPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -1089,8 +1295,8 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { } protected async getMarkerToolTip(): Promise { - const is3d = (undefined === this.targetView || this.targetView.view.is3d()); - const isSpatial = (undefined !== this.targetView && this.targetView.view.isSpatialView()); + const is3d = undefined === this.targetView || this.targetView.view.is3d(); + const isSpatial = undefined !== this.targetView && this.targetView.view.isSpatialView(); const toolTip = document.createElement("div"); let toolTipHtml = ""; @@ -1145,7 +1351,7 @@ export class MeasureAreaByPointsTool extends PrimitiveTool { this._centroid.setFrom(result.origin); this._perimeter = 0.0; for (let i = 1; i < this._points.length; i++) - this._perimeter += (this._points[i - 1].distance(this._points[i])); + this._perimeter += this._points[i - 1].distance(this._points[i]); const toolTip = await this.getMarkerToolTip(); this._acceptedMeasurement = new MeasureMarker("1", toolTip, this._centroid, Point2d.create(25, 25)); @@ -1257,13 +1463,19 @@ export abstract class MeasureElementTool extends PrimitiveTool { /** @internal */ protected allowView(vp: Viewport) { - return (MassPropertiesOperation.AccumulateVolumes === this.getOperation() ? vp.view.isSpatialView() : (vp.view.isSpatialView() || vp.view.isDrawingView())); + return (MassPropertiesOperation.AccumulateVolumes === this.getOperation() + ? vp.view.isSpatialView() + : (vp.view.isSpatialView() || vp.view.isDrawingView())); } /** @internal */ - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); + } /** @internal */ - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } /** @internal */ public override async onPostInstall() { await super.onPostInstall(); @@ -1277,31 +1489,105 @@ export abstract class MeasureElementTool extends PrimitiveTool { } /** @internal */ - public override async onUnsuspend() { this.showPrompt(); } + public override async onUnsuspend() { + this.showPrompt(); + } /** @internal */ protected showPrompt(): void { - const mainMsg = (this._useSelection ? (0 === this._acceptedMeasurements.length ? "ElementSet.Prompts.ConfirmSelection" : "ElementSet.Prompts.InspectResult") : "ElementSet.Prompts.IdentifyElement"); + const mainMsg = this._useSelection + ? (0 === this._acceptedMeasurements.length ? "ElementSet.Prompts.ConfirmSelection" : "ElementSet.Prompts.InspectResult") + : "ElementSet.Prompts.IdentifyElement"; const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, CoreTools.translate(mainMsg)); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; if (this._useSelection) { if (0 === this._acceptedMeasurements.length) { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptSelection"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptSelection"), false, ToolAssistanceInputMethod.Mouse)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.RejectSelection"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.RejectSelection"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptSelection"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.RejectSelection"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.RejectSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } else { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Exit"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Exit"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } } else { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (0 !== this._acceptedMeasurements.length) { - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate("ElementSet.Inputs.Restart"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TwoTouchTap, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + CoreTools.translate("ElementSet.Inputs.Restart"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } } @@ -1315,7 +1601,7 @@ export abstract class MeasureElementTool extends PrimitiveTool { /** @internal */ protected setupAndPromptForNextAction(): void { - this._useSelection = (undefined !== this.targetView && this.targetView.iModel.selectionSet.isActive); + this._useSelection = undefined !== this.targetView && this.targetView.iModel.selectionSet.isActive; if (!this._useSelection) this.initLocateElements(); this.showPrompt(); @@ -1332,7 +1618,9 @@ export abstract class MeasureElementTool extends PrimitiveTool { } /** @internal */ - public override decorateSuspended(context: DecorateContext): void { this.decorate(context); } + public override decorateSuspended(context: DecorateContext): void { + this.decorate(context); + } protected reportMeasurements(): void { if (undefined === this._totalMarker) @@ -1357,8 +1645,8 @@ export abstract class MeasureElementTool extends PrimitiveTool { } protected async getMarkerToolTip(responseProps: MassPropertiesResponseProps): Promise { - const is3d = (undefined === this.targetView || this.targetView.view.is3d()); - const isSpatial = (undefined !== this.targetView && this.targetView.view.isSpatialView()); + const is3d = undefined === this.targetView || this.targetView.view.is3d(); + const isSpatial = undefined !== this.targetView && this.targetView.view.isSpatialView(); const toolTip = document.createElement("div"); let toolTipHtml = ""; @@ -1553,7 +1841,9 @@ export abstract class MeasureElementTool extends PrimitiveTool { await this.doMeasureSelectedElements(ev.viewport); if (0 !== this._acceptedMeasurements.length) return EventHandled.Yes; - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.NotSupportedElmType"))); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.NotSupportedElmType")), + ); await this.onReinitialize(); } return EventHandled.Yes; @@ -1612,7 +1902,9 @@ export abstract class MeasureElementTool extends PrimitiveTool { export class MeasureLengthTool extends MeasureElementTool { public static override toolId = "Measure.Length"; public static override iconSpec = "icon-measure"; - protected getOperation(): MassPropertiesOperation { return MassPropertiesOperation.AccumulateLengths; } + protected getOperation(): MassPropertiesOperation { + return MassPropertiesOperation.AccumulateLengths; + } /** @internal */ public async onRestartTool(): Promise { @@ -1628,7 +1920,9 @@ export class MeasureLengthTool extends MeasureElementTool { export class MeasureAreaTool extends MeasureElementTool { public static override toolId = "Measure.Area"; public static override iconSpec = "icon-measure-area"; - protected getOperation(): MassPropertiesOperation { return MassPropertiesOperation.AccumulateAreas; } + protected getOperation(): MassPropertiesOperation { + return MassPropertiesOperation.AccumulateAreas; + } /** @internal */ public async onRestartTool(): Promise { @@ -1644,7 +1938,9 @@ export class MeasureAreaTool extends MeasureElementTool { export class MeasureVolumeTool extends MeasureElementTool { public static override toolId = "Measure.Volume"; public static override iconSpec = "icon-measure-3d"; - protected getOperation(): MassPropertiesOperation { return MassPropertiesOperation.AccumulateVolumes; } + protected getOperation(): MassPropertiesOperation { + return MassPropertiesOperation.AccumulateVolumes; + } /** @internal */ public async onRestartTool(): Promise { diff --git a/core/frontend/src/tools/PrimitiveTool.ts b/core/frontend/src/tools/PrimitiveTool.ts index d676866817d9..1f7884758d75 100644 --- a/core/frontend/src/tools/PrimitiveTool.ts +++ b/core/frontend/src/tools/PrimitiveTool.ts @@ -7,7 +7,7 @@ */ import { assert } from "@itwin/core-bentley"; -import {BriefcaseConnection} from "../BriefcaseConnection"; +import { BriefcaseConnection } from "../BriefcaseConnection"; import { IModelApp } from "../IModelApp"; import { IModelConnection } from "../IModelConnection"; import { NotifyMessageDetails, OutputMessagePriority } from "../NotificationManager"; @@ -26,8 +26,12 @@ export abstract class PrimitiveTool extends InteractiveTool { */ public targetView?: Viewport; private _targetModelId?: string; - public get targetModelId() { return this._targetModelId; } - public set targetModelId(v: string | undefined) { this._targetModelId = v; } + public get targetModelId() { + return this._targetModelId; + } + public set targetModelId(v: string | undefined) { + this._targetModelId = v; + } public targetIsLocked: boolean = false; // If target model is known, set this to true in constructor and override getTargetModel. /** Get the iModel on which this tool operates. @@ -127,7 +131,9 @@ export abstract class PrimitiveTool extends InteractiveTool { return true; if (isButtonEvent && ev.isDown) - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.ProjectExtents"))); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, CoreTools.translate("ElementSet.Error.ProjectExtents")), + ); return false; } @@ -141,10 +147,14 @@ export abstract class PrimitiveTool extends InteractiveTool { } /** Returns the prompt based on the tool's current state. */ - public getPrompt(): string { return ""; } + public getPrompt(): string { + return ""; + } /** Called from isCompatibleViewport to check for a read only iModel, which is not a valid target for tools that create or modify elements. */ - public requireWriteableTarget(): boolean { return true; } + public requireWriteableTarget(): boolean { + return true; + } /** * Called when active view changes. Tool may choose to restart or exit based on current view type. @@ -172,15 +182,21 @@ export abstract class PrimitiveTool extends InteractiveTool { /** * Called to reset tool to initial state. PrimitiveTool implements this method to call onRestartTool. */ - public override async onReinitialize(): Promise { return this.onRestartTool(); } + public override async onReinitialize(): Promise { + return this.onRestartTool(); + } - public async exitTool() { return IModelApp.toolAdmin.startDefaultTool(); } + public async exitTool() { + return IModelApp.toolAdmin.startDefaultTool(); + } /** * Called to reverse to a previous tool state (ex. undo last data button). * @return false to instead reverse the most recent transaction. */ - public async onUndoPreviousStep(): Promise { return false; } + public async onUndoPreviousStep(): Promise { + return false; + } /** @internal */ public async undoPreviousStep(): Promise { @@ -198,7 +214,9 @@ export abstract class PrimitiveTool extends InteractiveTool { * Called to reinstate to a previous tool state (ex. redo last data button). * @return false to instead reinstate the most recent transaction. */ - public async onRedoPreviousStep(): Promise { return false; } + public async onRedoPreviousStep(): Promise { + return false; + } /** @internal */ public async redoPreviousStep(): Promise { diff --git a/core/frontend/src/tools/SelectTool.ts b/core/frontend/src/tools/SelectTool.ts index c1751eb8478b..ba9908499e9d 100644 --- a/core/frontend/src/tools/SelectTool.ts +++ b/core/frontend/src/tools/SelectTool.ts @@ -6,19 +6,24 @@ * @module SelectionSet */ -import { Id64, Id64Arg } from "@itwin/core-bentley"; -import { Point2d, Point3d, Range2d } from "@itwin/core-geometry"; -import { ColorDef } from "@itwin/core-common"; import { - ButtonGroupEditorParams, DialogItem, DialogItemValue, DialogPropertySyncItem, PropertyDescription, PropertyEditorParamTypes, + ButtonGroupEditorParams, + DialogItem, + DialogItemValue, + DialogPropertySyncItem, + PropertyDescription, + PropertyEditorParamTypes, SuppressLabelEditorParams, } from "@itwin/appui-abstract"; +import { Id64, Id64Arg } from "@itwin/core-bentley"; +import { ColorDef } from "@itwin/core-common"; +import { Point2d, Point3d, Range2d } from "@itwin/core-geometry"; +import { ViewRect } from "../common/ViewRect"; import { LocateFilterStatus, LocateResponse } from "../ElementLocateManager"; import { HitDetail } from "../HitDetail"; import { IModelApp } from "../IModelApp"; import { Pixel } from "../render/Pixel"; import { DecorateContext } from "../ViewContext"; -import { ViewRect } from "../common/ViewRect"; import { PrimitiveTool } from "./PrimitiveTool"; import { BeButton, BeButtonEvent, BeModifierKeys, BeTouchEvent, CoordinateLockOverrides, CoreTools, EventHandled, InputSource } from "./Tool"; import { ManipulatorToolEvent } from "./ToolAdmin"; @@ -80,20 +85,40 @@ export class SelectionTool extends PrimitiveTool { private _selectionMethodValue: DialogItemValue = { value: SelectionMethod.Pick }; private _selectionModeValue: DialogItemValue = { value: SelectionMode.Replace }; - public override requireWriteableTarget(): boolean { return false; } - public override autoLockTarget(): void { } // NOTE: For selecting elements we only care about iModel, so don't lock target model automatically. + public override requireWriteableTarget(): boolean { + return false; + } + public override autoLockTarget(): void {} // NOTE: For selecting elements we only care about iModel, so don't lock target model automatically. - protected wantSelectionClearOnMiss(_ev: BeButtonEvent): boolean { return SelectionMode.Replace === this.selectionMode; } - protected wantEditManipulators(): boolean { return SelectionMethod.Pick === this.selectionMethod; } - protected wantPickableDecorations(): boolean { return this.wantEditManipulators(); } // Allow pickable decorations selection to be independent of manipulators... - protected wantToolSettings(): boolean { return true; } + protected wantSelectionClearOnMiss(_ev: BeButtonEvent): boolean { + return SelectionMode.Replace === this.selectionMode; + } + protected wantEditManipulators(): boolean { + return SelectionMethod.Pick === this.selectionMethod; + } + protected wantPickableDecorations(): boolean { + return this.wantEditManipulators(); + } // Allow pickable decorations selection to be independent of manipulators... + protected wantToolSettings(): boolean { + return true; + } - public get selectionMethod(): SelectionMethod { return this._selectionMethodValue.value as SelectionMethod; } - public set selectionMethod(method: SelectionMethod) { this._selectionMethodValue.value = method; } - public get selectionMode(): SelectionMode { return this._selectionModeValue.value as SelectionMode; } - public set selectionMode(mode: SelectionMode) { this._selectionModeValue.value = mode; } + public get selectionMethod(): SelectionMethod { + return this._selectionMethodValue.value as SelectionMethod; + } + public set selectionMethod(method: SelectionMethod) { + this._selectionMethodValue.value = method; + } + public get selectionMode(): SelectionMode { + return this._selectionModeValue.value as SelectionMode; + } + public set selectionMode(mode: SelectionMode) { + this._selectionModeValue.value = mode; + } - private static methodsMessage(str: string) { return CoreTools.translate(`ElementSet.SelectionMethods.${str}`); } + private static methodsMessage(str: string) { + return CoreTools.translate(`ElementSet.SelectionMethods.${str}`); + } private static _methodsName = "selectionMethods"; /* The property descriptions used to generate ToolSettings UI. */ private static _getMethodsDescription(): PropertyDescription { @@ -113,8 +138,7 @@ export class SelectionTool extends PrimitiveTool { } as ButtonGroupEditorParams, { type: PropertyEditorParamTypes.SuppressEditorLabel, suppressLabelPlaceholder: true, - } as SuppressLabelEditorParams, - ], + } as SuppressLabelEditorParams], }, enum: { choices: [ @@ -126,7 +150,9 @@ export class SelectionTool extends PrimitiveTool { }; } - private static modesMessage(str: string) { return CoreTools.translate(`ElementSet.SelectionModes.${str}`); } + private static modesMessage(str: string) { + return CoreTools.translate(`ElementSet.SelectionModes.${str}`); + } private static _modesName = "selectionModes"; /* The property descriptions used to generate ToolSettings UI. */ private static _getModesDescription(): PropertyDescription { @@ -152,8 +178,7 @@ export class SelectionTool extends PrimitiveTool { } as ButtonGroupEditorParams, { type: PropertyEditorParamTypes.SuppressEditorLabel, suppressLabelPlaceholder: true, - } as SuppressLabelEditorParams, - ], + } as SuppressLabelEditorParams], }, enum: { choices: [ @@ -172,10 +197,10 @@ export class SelectionTool extends PrimitiveTool { mainMsg += "IdentifyElement"; break; case SelectionMethod.Line: - mainMsg += (0 === this._points.length ? "StartPoint" : "EndPoint"); + mainMsg += 0 === this._points.length ? "StartPoint" : "EndPoint"; break; case SelectionMethod.Box: - mainMsg += (0 === this._points.length ? "StartCorner" : "OppositeCorner"); + mainMsg += 0 === this._points.length ? "StartCorner" : "OppositeCorner"; break; } @@ -185,42 +210,144 @@ export class SelectionTool extends PrimitiveTool { switch (method) { case SelectionMethod.Pick: const mousePickInstructions: ToolAssistanceInstruction[] = []; - mousePickInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Mouse)); - mousePickInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.BoxCorners"), false, ToolAssistanceInputMethod.Mouse)); - mousePickInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClickDrag, CoreTools.translate("ElementSet.Inputs.CrossingLine"), false, ToolAssistanceInputMethod.Mouse)); - mousePickInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistanceInputMethod.Mouse)); + mousePickInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mousePickInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.BoxCorners"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mousePickInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClickDrag, + CoreTools.translate("ElementSet.Inputs.CrossingLine"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mousePickInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.OverlapSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (SelectionMode.Replace === mode) { - mousePickInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.ctrlKeyboardInfo, CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistanceInputMethod.Mouse)); - mousePickInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.CursorClick, CoreTools.translate("ElementSet.Inputs.ClearSelection"), false, ToolAssistanceInputMethod.Mouse)); + mousePickInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.ctrlKeyboardInfo, + CoreTools.translate("ElementSet.Inputs.InvertSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mousePickInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.CursorClick, + CoreTools.translate("ElementSet.Inputs.ClearSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); } sections.push(ToolAssistance.createSection(mousePickInstructions, ToolAssistance.inputsLabel)); const touchPickInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchPickInstructions)) - touchPickInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate("ElementSet.Inputs.AcceptElement"), false, ToolAssistanceInputMethod.Touch)); + touchPickInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + CoreTools.translate("ElementSet.Inputs.AcceptElement"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); sections.push(ToolAssistance.createSection(touchPickInstructions, ToolAssistance.inputsLabel)); break; case SelectionMethod.Line: const mouseLineInstructions: ToolAssistanceInstruction[] = []; - mouseLineInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); + mouseLineInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (SelectionMode.Replace === mode) - mouseLineInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistanceInputMethod.Mouse)); + mouseLineInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.InvertSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); sections.push(ToolAssistance.createSection(mouseLineInstructions, ToolAssistance.inputsLabel)); const touchLineInstructions: ToolAssistanceInstruction[] = []; - touchLineInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchDrag, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); + touchLineInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchDrag, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); sections.push(ToolAssistance.createSection(touchLineInstructions, ToolAssistance.inputsLabel)); break; case SelectionMethod.Box: const mouseBoxInstructions: ToolAssistanceInstruction[] = []; - mouseBoxInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Mouse)); - mouseBoxInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistanceInputMethod.Mouse)); + mouseBoxInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseBoxInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.OverlapSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); if (SelectionMode.Replace === mode) - mouseBoxInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistanceInputMethod.Mouse)); + mouseBoxInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.InvertSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); sections.push(ToolAssistance.createSection(mouseBoxInstructions, ToolAssistance.inputsLabel)); const touchBoxInstructions: ToolAssistanceInstruction[] = []; - touchBoxInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchDrag, CoreTools.translate("ElementSet.Inputs.AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); + touchBoxInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchDrag, + CoreTools.translate("ElementSet.Inputs.AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); sections.push(ToolAssistance.createSection(touchBoxInstructions, ToolAssistance.inputsLabel)); break; } @@ -274,14 +401,16 @@ export class SelectionTool extends PrimitiveTool { return returnValue; } - public async processSelection(elementId: Id64Arg, process: SelectionProcessing): Promise { return this.updateSelection(elementId, process); } + public async processSelection(elementId: Id64Arg, process: SelectionProcessing): Promise { + return this.updateSelection(elementId, process); + } protected useOverlapSelection(ev: BeButtonEvent): boolean { if (undefined === ev.viewport) return false; const pt1 = ev.viewport.worldToView(this._points[0]); const pt2 = ev.viewport.worldToView(ev.point); - const overlapMode = (pt1.x > pt2.x); + const overlapMode = pt1.x > pt2.x; return (ev.isShiftKey ? !overlapMode : overlapMode); // Shift inverts inside/overlap selection... } @@ -295,9 +424,10 @@ export class SelectionTool extends PrimitiveTool { return; const vp = context.viewport; - const bestContrastIsBlack = (ColorDef.black === vp.getContrastToBackgroundColor()); - const crossingLine = (SelectionMethod.Line === this.selectionMethod || (SelectionMethod.Pick === this.selectionMethod && BeButton.Reset === ev.button)); - const overlapSelection = (crossingLine || this.useOverlapSelection(ev)); + const bestContrastIsBlack = ColorDef.black === vp.getContrastToBackgroundColor(); + const crossingLine = SelectionMethod.Line === this.selectionMethod || + (SelectionMethod.Pick === this.selectionMethod && BeButton.Reset === ev.button); + const overlapSelection = crossingLine || this.useOverlapSelection(ev); const position = vp.worldToView(this._points[0]); position.x = Math.floor(position.x) + 0.5; @@ -481,7 +611,9 @@ export class SelectionTool extends PrimitiveTool { currHit = await IModelApp.locateManager.doLocate(new LocateResponse(), true, ev.point, ev.viewport, ev.inputSource); if (undefined !== currHit) - return (currHit.isElementHit ? IModelApp.viewManager.overrideElementButtonEvent(currHit, ev) : IModelApp.viewManager.onDecorationButtonEvent(currHit, ev)); + return (currHit.isElementHit + ? IModelApp.viewManager.overrideElementButtonEvent(currHit, ev) + : IModelApp.viewManager.onDecorationButtonEvent(currHit, ev)); return EventHandled.No; } @@ -492,7 +624,10 @@ export class SelectionTool extends PrimitiveTool { switch (this.selectionMode) { case SelectionMode.Replace: - await this.processSelection(hit.sourceId, ev.isControlKey ? SelectionProcessing.InvertElementInSelection : SelectionProcessing.ReplaceSelectionWithElement); + await this.processSelection( + hit.sourceId, + ev.isControlKey ? SelectionProcessing.InvertElementInSelection : SelectionProcessing.ReplaceSelectionWithElement, + ); break; case SelectionMode.Add: @@ -624,7 +759,9 @@ export class SelectionTool extends PrimitiveTool { return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, BeButton.Reset); } - public override decorate(context: DecorateContext): void { this.selectByPointsDecorate(context); } + public override decorate(context: DecorateContext): void { + this.selectByPointsDecorate(context); + } public override async onModifierKeyTransition(_wentDown: boolean, modifier: BeModifierKeys, _event: KeyboardEvent): Promise { return (modifier === BeModifierKeys.Shift && this._isSelectByPoints) ? EventHandled.Yes : EventHandled.No; @@ -639,13 +776,15 @@ export class SelectionTool extends PrimitiveTool { return LocateFilterStatus.Accept; const isSelected = this.iModel.selectionSet.has(hit.sourceId); - const status = ((SelectionMode.Add === mode ? !isSelected : isSelected) ? LocateFilterStatus.Accept : LocateFilterStatus.Reject); + const status = (SelectionMode.Add === mode ? !isSelected : isSelected) ? LocateFilterStatus.Accept : LocateFilterStatus.Reject; if (out && LocateFilterStatus.Reject === status) out.explanation = CoreTools.translate(`ElementSet.Error.${isSelected ? "AlreadySelected" : "NotSelected"}`); return status; } - public async onRestartTool(): Promise { return this.exitTool(); } + public async onRestartTool(): Promise { + return this.exitTool(); + } public override async onCleanup() { if (this.wantEditManipulators()) @@ -661,7 +800,9 @@ export class SelectionTool extends PrimitiveTool { this.initSelectTool(); } - public static async startTool(): Promise { return new SelectionTool().run(); } + public static async startTool(): Promise { + return new SelectionTool().run(); + } private syncSelectionMode(): void { if (SelectionMode.Remove === this.selectionMode && !this.iModel.selectionSet.isActive) { @@ -692,13 +833,24 @@ export class SelectionTool extends PrimitiveTool { // Make sure a mode of SelectionMode.Remove is valid if (SelectionMode.Remove === this.selectionMode && !this.iModel.selectionSet.isActive) { this.selectionMode = SelectionMode.Replace; - IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: SelectionTool._modesName, value: this._selectionModeValue }); + IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { + propertyName: SelectionTool._modesName, + value: this._selectionModeValue, + }); } const toolSettings = new Array(); // generate 3 columns - label will be placed in column 0 and button group editors in columns 1 and 2. - toolSettings.push({ value: this._selectionMethodValue, property: SelectionTool._getMethodsDescription(), editorPosition: { rowPriority: 0, columnIndex: 1 } }); - toolSettings.push({ value: this._selectionModeValue, property: SelectionTool._getModesDescription(), editorPosition: { rowPriority: 0, columnIndex: 2 } }); + toolSettings.push({ + value: this._selectionMethodValue, + property: SelectionTool._getMethodsDescription(), + editorPosition: { rowPriority: 0, columnIndex: 1 }, + }); + toolSettings.push({ + value: this._selectionModeValue, + property: SelectionTool._getModesDescription(), + editorPosition: { rowPriority: 0, columnIndex: 2 }, + }); return toolSettings; } @@ -721,7 +873,10 @@ export class SelectionTool extends PrimitiveTool { this._selectionModeValue = updatedValue.value; if (this._selectionModeValue) { if (this.wantToolSettings()) - IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { propertyName: SelectionTool._modesName, value: this._selectionModeValue }); + IModelApp.toolAdmin.toolSettingsState.saveToolSettingProperty(this.toolId, { + propertyName: SelectionTool._modesName, + value: this._selectionModeValue, + }); changed = true; } } diff --git a/core/frontend/src/tools/Tool.ts b/core/frontend/src/tools/Tool.ts index 8c93edebf59f..df0aa2384e42 100644 --- a/core/frontend/src/tools/Tool.ts +++ b/core/frontend/src/tools/Tool.ts @@ -33,7 +33,11 @@ export type ToolList = ToolType[]; * @public * @extensions */ -export enum BeButton { Data = 0, Reset = 1, Middle = 2 } +export enum BeButton { + Data = 0, + Reset = 1, + Middle = 2, +} /** * @public @@ -42,7 +46,7 @@ export enum BeButton { Data = 0, Reset = 1, Middle = 2 } export enum CoordinateLockOverrides { None = 0, ACS = 1 << 1, - Grid = 1 << 2, // also overrides unit lock + Grid = 1 << 2, // also overrides unit lock All = 0xffff, } @@ -78,7 +82,12 @@ export enum CoordSource { * @public * @extensions */ -export enum BeModifierKeys { None = 0, Control = 1 << 0, Shift = 1 << 1, Alt = 1 << 2 } +export enum BeModifierKeys { + None = 0, + Control = 1 << 0, + Shift = 1 << 1, + Alt = 1 << 2, +} /** * @public @@ -93,12 +102,28 @@ export class BeButtonState { public isDragging: boolean = false; public inputSource: InputSource = InputSource.Unknown; - public get downRawPt() { return this._downRawPt; } - public set downRawPt(pt: Point3d) { this._downRawPt.setFrom(pt); } - public get downUorPt() { return this._downUorPt; } - public set downUorPt(pt: Point3d) { this._downUorPt.setFrom(pt); } + public get downRawPt() { + return this._downRawPt; + } + public set downRawPt(pt: Point3d) { + this._downRawPt.setFrom(pt); + } + public get downUorPt() { + return this._downUorPt; + } + public set downUorPt(pt: Point3d) { + this._downUorPt.setFrom(pt); + } - public init(downUorPt: Point3d, downRawPt: Point3d, downTime: number, isDown: boolean, isDoubleClick: boolean, isDragging: boolean, source: InputSource) { + public init( + downUorPt: Point3d, + downRawPt: Point3d, + downTime: number, + isDown: boolean, + isDoubleClick: boolean, + isDragging: boolean, + source: InputSource, + ) { this.downUorPt = downUorPt; this.downRawPt = downRawPt; this.downTime = downTime; @@ -175,28 +200,48 @@ export class BeButtonEvent implements BeButtonEventProps { /** Determine whether this BeButtonEvent has valid data. * @note BeButtonEvents may be constructed as "blank", and are not considered to hold valid data unless the [[viewport]] member is defined. */ - public get isValid(): boolean { return this.viewport !== undefined; } + public get isValid(): boolean { + return this.viewport !== undefined; + } /** The point for this event, in world coordinates. * @note these coordinates may have been *adjusted* for some reason (e.g. snapping, locks, etc.) from the [[rawPoint]]. */ - public get point() { return this._point; } - public set point(pt: Point3d) { this._point.setFrom(pt); } + public get point() { + return this._point; + } + public set point(pt: Point3d) { + this._point.setFrom(pt); + } /** The *raw* (unadjusted) point for this event, in world coordinates. */ - public get rawPoint() { return this._rawPoint; } - public set rawPoint(pt: Point3d) { this._rawPoint.setFrom(pt); } + public get rawPoint() { + return this._rawPoint; + } + public set rawPoint(pt: Point3d) { + this._rawPoint.setFrom(pt); + } /** The point, in screen coordinates for this event. * @note generally the z value is not useful, but some 3d pointing devices do supply it. */ - public get viewPoint() { return this._viewPoint; } - public set viewPoint(pt: Point3d) { this._viewPoint.setFrom(pt); } + public get viewPoint() { + return this._viewPoint; + } + public set viewPoint(pt: Point3d) { + this._viewPoint.setFrom(pt); + } /** The difference in screen coordinates from previous motion event * @internal */ - public get movement(): XAndY | undefined { return this._movement; } - public set movement(mov: XAndY | undefined) { this._movement = mov; } + public get movement(): XAndY | undefined { + return this._movement; + } + public set movement(mov: XAndY | undefined) { + this._movement = mov; + } /** Mark this BeButtonEvent as invalid. Can only become valid again by calling [[init]] */ - public invalidate() { this.viewport = undefined; } + public invalidate() { + this.viewport = undefined; + } /** Initialize the values of this BeButtonEvent. */ public init(props: BeButtonEventProps) { @@ -225,11 +270,17 @@ export class BeButtonEvent implements BeButtonEventProps { } /** Determine whether the control key was pressed */ - public get isControlKey() { return 0 !== (this.keyModifiers & BeModifierKeys.Control); } + public get isControlKey() { + return 0 !== (this.keyModifiers & BeModifierKeys.Control); + } /** Determine whether the shift key was pressed */ - public get isShiftKey() { return 0 !== (this.keyModifiers & BeModifierKeys.Shift); } + public get isShiftKey() { + return 0 !== (this.keyModifiers & BeModifierKeys.Shift); + } /** Determine whether the alt key was pressed */ - public get isAltKey() { return 0 !== (this.keyModifiers & BeModifierKeys.Alt); } + public get isAltKey() { + return 0 !== (this.keyModifiers & BeModifierKeys.Alt); + } /** Copy the values from another BeButtonEvent into this BeButtonEvent */ public setFrom(src: BeButtonEvent): this { @@ -247,7 +298,9 @@ export class BeButtonEvent implements BeButtonEventProps { return this; } /** Make a copy of this BeButtonEvent. */ - public clone(): this { return new (this.constructor as typeof BeButtonEvent)(this) as this; } + public clone(): this { + return new (this.constructor as typeof BeButtonEvent)(this) as this; + } } /** Properties for initializing a BeTouchEvent @@ -265,12 +318,24 @@ export interface BeTouchEventProps extends BeButtonEventProps { export class BeTouchEvent extends BeButtonEvent implements BeTouchEventProps { public tapCount: number = 0; public touchEvent: TouchEvent; - public get touchCount(): number { return this.touchEvent.targetTouches.length; } - public get isSingleTouch(): boolean { return 1 === this.touchCount; } - public get isTwoFingerTouch(): boolean { return 2 === this.touchCount; } - public get isSingleTap(): boolean { return 1 === this.tapCount && 1 === this.touchCount; } - public get isDoubleTap(): boolean { return 2 === this.tapCount && 1 === this.touchCount; } - public get isTwoFingerTap(): boolean { return 1 === this.tapCount && 2 === this.touchCount; } + public get touchCount(): number { + return this.touchEvent.targetTouches.length; + } + public get isSingleTouch(): boolean { + return 1 === this.touchCount; + } + public get isTwoFingerTouch(): boolean { + return 2 === this.touchCount; + } + public get isSingleTap(): boolean { + return 1 === this.tapCount && 1 === this.touchCount; + } + public get isDoubleTap(): boolean { + return 2 === this.tapCount && 1 === this.touchCount; + } + public get isTwoFingerTap(): boolean { + return 1 === this.tapCount && 2 === this.touchCount; + } public constructor(props: BeTouchEventProps) { super(props); this.touchEvent = props.touchEvent; @@ -368,21 +433,27 @@ export class Tool { public static namespace: string; /** @internal */ - public get ctor() { return this.constructor as ToolType; } + public get ctor() { + return this.constructor as ToolType; + } - public constructor(..._args: any[]) { } + public constructor(..._args: any[]) {} /** The minimum number of arguments allowed by [[parseAndRun]]. If subclasses override [[parseAndRun]], they should also * override this method to indicate the minimum number of arguments their implementation expects. UI controls can use * this information to ensure the tool has enough information to execute. */ - public static get minArgs(): number { return 0; } + public static get minArgs(): number { + return 0; + } /** The maximum number of arguments allowed by [[parseAndRun]], or undefined if there is no maximum. * If subclasses override [[parseAndRun]], they should also override this method to indicate the maximum * number of arguments their implementation expects. */ - public static get maxArgs(): number | undefined { return 0; } + public static get maxArgs(): number | undefined { + return 0; + } /** * Register this Tool class with the [[ToolRegistry]]. @@ -441,33 +512,45 @@ export class Tool { * Get the toolId string for this Tool class. This string is used to identify the Tool in the ToolRegistry and is used to localize * the keyin, description, etc. from the current locale. */ - public get toolId(): string { return this.ctor.toolId; } + public get toolId(): string { + return this.ctor.toolId; + } /** Get the localized keyin string from this Tool's class * @see `static get keyin()` */ - public get keyin(): string { return this.ctor.keyin; } + public get keyin(): string { + return this.ctor.keyin; + } /** Get the localized flyover string from this Tool's class * @see `static get flyover()` */ - public get flyover(): string { return this.ctor.flyover; } + public get flyover(): string { + return this.ctor.flyover; + } /** Get the localized description string from this Tool's class * @see `static get description()` */ - public get description(): string { return this.ctor.description; } + public get description(): string { + return this.ctor.description; + } /** Get the iconSpec from this Tool's class. * @see `static iconSpec` */ - public get iconSpec(): string { return this.ctor.iconSpec; } + public get iconSpec(): string { + return this.ctor.iconSpec; + } /** * Run this instance of a Tool. Subclasses should override to perform some action. * @returns `true` if the tool executed successfully. */ - public async run(..._args: any[]): Promise { return true; } + public async run(..._args: any[]): Promise { + return true; + } /** Run this instance of a tool using a series of string arguments. Override this method to parse the arguments, and if they're * acceptable, execute your [[run]] method. If the arguments aren't valid, return `false`. @@ -484,7 +567,10 @@ export class Tool { * @public * @extensions */ -export enum EventHandled { No = 0, Yes = 1 } +export enum EventHandled { + No = 0, + Yes = 1, +} /** A Tool that may be installed, via [[ToolAdmin]], to handle user input. The ToolAdmin manages the currently installed ViewingTool, PrimitiveTool, * InputCollector, and IdleTool. Each must derive from this class and there may only be one of each type installed at a time. @@ -492,91 +578,110 @@ export enum EventHandled { No = 0, Yes = 1 } * @extensions */ export abstract class InteractiveTool extends Tool { - /** Used to avoid sending tools up events for which they did not receive the down event. */ public receivedDownEvent = false; /** Override to execute additional logic when tool is installed. Return false to prevent this tool from becoming active */ - public async onInstall(): Promise { return true; } + public async onInstall(): Promise { + return true; + } /** Override to execute additional logic after tool becomes active */ - public async onPostInstall(): Promise { } + public async onPostInstall(): Promise {} public abstract exitTool(): Promise; /** Override Call to reset tool to initial state */ - public async onReinitialize(): Promise { } + public async onReinitialize(): Promise {} /** Invoked when the tool becomes no longer active, to perform additional cleanup logic */ - public async onCleanup(): Promise { } + public async onCleanup(): Promise {} /** Notification of a ViewTool or InputCollector starting and this tool is being suspended. * @note Applies only to PrimitiveTool and InputCollector, a ViewTool can't be suspended. */ - public async onSuspend(): Promise { } + public async onSuspend(): Promise {} /** Notification of a ViewTool or InputCollector exiting and this tool is being unsuspended. * @note Applies only to PrimitiveTool and InputCollector, a ViewTool can't be suspended. */ - public async onUnsuspend(): Promise { } + public async onUnsuspend(): Promise {} /** Called to support operations on pickable decorations, like snapping. */ - public testDecorationHit(_id: string): boolean { return false; } + public testDecorationHit(_id: string): boolean { + return false; + } /** Called to allow snapping to pickable decoration geometry. * @note Snap geometry can be different from decoration geometry (ex. center point of a + symbol). Valid decoration geometry for snapping should be "stable" and not change based on the current cursor location. */ - public getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined { return undefined; } + public getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined { + return undefined; + } /** * Called to allow an active tool to display non-element decorations in overlay mode. * This method is NOT called while the tool is suspended by a viewing tool or input collector. */ - public decorate(_context: DecorateContext): void { } + public decorate(_context: DecorateContext): void {} /** * Called to allow a suspended tool to display non-element decorations in overlay mode. * This method is ONLY called when the tool is suspended by a viewing tool or input collector. * @note Applies only to PrimitiveTool and InputCollector, a ViewTool can't be suspended. */ - public decorateSuspended(_context: DecorateContext): void { } + public decorateSuspended(_context: DecorateContext): void {} /** Invoked when the reset button is pressed. * @return No by default. Sub-classes may ascribe special meaning to this status. * @note To support right-press menus, a tool should put its reset event processing in onResetButtonUp instead of onResetButtonDown. */ - public async onResetButtonDown(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onResetButtonDown(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the reset button is released. * @return No by default. Sub-classes may ascribe special meaning to this status. */ - public async onResetButtonUp(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onResetButtonUp(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the data button is pressed. * @return No by default. Sub-classes may ascribe special meaning to this status. */ - public async onDataButtonDown(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onDataButtonDown(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the data button is released. * @return No by default. Sub-classes may ascribe special meaning to this status. */ - public async onDataButtonUp(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onDataButtonUp(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the middle mouse button is pressed. * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. */ - public async onMiddleButtonDown(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onMiddleButtonDown(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the middle mouse button is released. * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. */ - public async onMiddleButtonUp(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onMiddleButtonUp(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the cursor is moving */ - public async onMouseMotion(_ev: BeButtonEvent): Promise { } + public async onMouseMotion(_ev: BeButtonEvent): Promise {} /** Invoked when the cursor begins moving while a button is depressed. * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. */ - public async onMouseStartDrag(_ev: BeButtonEvent): Promise { return EventHandled.No; } + public async onMouseStartDrag(_ev: BeButtonEvent): Promise { + return EventHandled.No; + } /** Invoked when the button is released after onMouseStartDrag. * @note default placement tool behavior is to treat press, drag, and release of data button the same as click, click by calling onDataButtonDown. * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. @@ -596,7 +701,9 @@ export abstract class InteractiveTool extends Tool { /** Invoked when the mouse wheel moves. * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. */ - public async onMouseWheel(_ev: BeWheelEvent): Promise { return EventHandled.No; } + public async onMouseWheel(_ev: BeWheelEvent): Promise { + return EventHandled.No; + } /** Called when Control, Shift, or Alt modifier keys are pressed or released. * @param _wentDown up or down key event @@ -604,7 +711,9 @@ export abstract class InteractiveTool extends Tool { * @param _event The event that caused this call * @return Yes to refresh view decorations or update dynamics. */ - public async onModifierKeyTransition(_wentDown: boolean, _modifier: BeModifierKeys, _event: KeyboardEvent): Promise { return EventHandled.No; } + public async onModifierKeyTransition(_wentDown: boolean, _modifier: BeModifierKeys, _event: KeyboardEvent): Promise { + return EventHandled.No; + } /** Called when any key is pressed or released. * @param _wentDown up or down key event @@ -612,42 +721,52 @@ export abstract class InteractiveTool extends Tool { * @return Yes to prevent further processing of this event * @see [[onModifierKeyTransition]] */ - public async onKeyTransition(_wentDown: boolean, _keyEvent: KeyboardEvent): Promise { return EventHandled.No; } + public async onKeyTransition(_wentDown: boolean, _keyEvent: KeyboardEvent): Promise { + return EventHandled.No; + } /** Called when user adds a touch point by placing a finger or stylus on the surface. */ - public async onTouchStart(_ev: BeTouchEvent): Promise { } + public async onTouchStart(_ev: BeTouchEvent): Promise {} /** Called when user removes a touch point by lifting a finger or stylus from the surface. */ - public async onTouchEnd(_ev: BeTouchEvent): Promise { } + public async onTouchEnd(_ev: BeTouchEvent): Promise {} /** Called when the last touch point is removed from the surface completing the current gesture. This is a convenience event sent following onTouchEnd when no target touch points remain on the surface. */ - public async onTouchComplete(_ev: BeTouchEvent): Promise { } + public async onTouchComplete(_ev: BeTouchEvent): Promise {} /** Called when a touch point is interrupted in some way and needs to be dropped from the list of target touches. */ - public async onTouchCancel(_ev: BeTouchEvent): Promise { } + public async onTouchCancel(_ev: BeTouchEvent): Promise {} /** Called when a touch point moves along the surface. */ - public async onTouchMove(_ev: BeTouchEvent): Promise { } + public async onTouchMove(_ev: BeTouchEvent): Promise {} /** Called after at least one touch point has moved for an appreciable time and distance along the surface to not be considered a tap. * @param _ev The event that caused this call * @param _startEv The event from the last call to onTouchStart * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. */ - public async onTouchMoveStart(_ev: BeTouchEvent, _startEv: BeTouchEvent): Promise { return EventHandled.No; } + public async onTouchMoveStart(_ev: BeTouchEvent, _startEv: BeTouchEvent): Promise { + return EventHandled.No; + } /** Called when touch point(s) are added and removed from a surface within a small time window without any touch point moving. * @param _ev The event that caused this call * @return Yes if event completely handled by tool and event should not be passed on to the IdleTool. * @note A double or triple tap event will not be preceded by a single tap event. */ - public async onTouchTap(_ev: BeTouchEvent): Promise { return EventHandled.No; } + public async onTouchTap(_ev: BeTouchEvent): Promise { + return EventHandled.No; + } - public isCompatibleViewport(_vp: ScreenViewport, _isSelectedViewChange: boolean): boolean { return true; } - public isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } + public isCompatibleViewport(_vp: ScreenViewport, _isSelectedViewChange: boolean): boolean { + return true; + } + public isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } /** * Called when active view changes. Tool may choose to restart or exit based on current view type. * @param previous The previously active view. * @param current The new active view. */ - public onSelectedViewportChanged(_previous: ScreenViewport | undefined, _current: ScreenViewport | undefined): void { } + public onSelectedViewportChanged(_previous: ScreenViewport | undefined, _current: ScreenViewport | undefined): void {} /** * Invoked before the locate tooltip is displayed to retrieve the information about the located element. Allows the tool to override the toolTip. @@ -655,30 +774,44 @@ export abstract class InteractiveTool extends Tool { * @return A Promise for the HTMLElement or string to describe the hit. * @note If you override this method, you may decide whether to call your superclass' implementation or not (it is not required). */ - public async getToolTip(_hit: HitDetail): Promise { return _hit.getToolTip(); } + public async getToolTip(_hit: HitDetail): Promise { + return _hit.getToolTip(); + } /** Convenience method to check whether control key is currently down without needing a button event. */ - public get isControlDown(): boolean { return IModelApp.toolAdmin.currentInputState.isControlDown; } + public get isControlDown(): boolean { + return IModelApp.toolAdmin.currentInputState.isControlDown; + } /** Fill the supplied button event from the current cursor location. */ - public getCurrentButtonEvent(ev: BeButtonEvent): void { IModelApp.toolAdmin.fillEventFromCursorLocation(ev); } + public getCurrentButtonEvent(ev: BeButtonEvent): void { + IModelApp.toolAdmin.fillEventFromCursorLocation(ev); + } /** Call to find out if dynamics are currently active. */ - public get isDynamicsStarted(): boolean { return IModelApp.viewManager.inDynamicsMode; } + public get isDynamicsStarted(): boolean { + return IModelApp.viewManager.inDynamicsMode; + } /** Call to initialize dynamics mode. While dynamics are active onDynamicFrame will be called. Dynamics are typically only used by a PrimitiveTool that creates or modifies geometric elements. */ - public beginDynamics(): void { IModelApp.toolAdmin.beginDynamics(); } + public beginDynamics(): void { + IModelApp.toolAdmin.beginDynamics(); + } /** Call to terminate dynamics mode. */ - public endDynamics(): void { IModelApp.toolAdmin.endDynamics(); } + public endDynamics(): void { + IModelApp.toolAdmin.endDynamics(); + } /** Called to allow Tool to display dynamic elements. */ - public onDynamicFrame(_ev: BeButtonEvent, _context: DynamicsContext): void { } + public onDynamicFrame(_ev: BeButtonEvent, _context: DynamicsContext): void {} /** Invoked to allow tools to filter which elements can be located. * @return Reject if hit is unacceptable for this tool (fill out response with explanation, if it is defined) */ - public async filterHit(_hit: HitDetail, _out?: LocateResponse): Promise { return LocateFilterStatus.Accept; } + public async filterHit(_hit: HitDetail, _out?: LocateResponse): Promise { + return LocateFilterStatus.Accept; + } /** Helper method to keep the view cursor, display of locate circle, and coordinate lock overrides consistent with [[AccuSnap.isLocateEnabled]] and [[AccuSnap.isSnapEnabled]]. * @param enableLocate Value to pass to [[AccuSnap.enableLocate]]. Tools that locate elements should always pass true to give the user feedback regarding the element at the current cursor location. @@ -813,13 +946,17 @@ export abstract class InteractiveTool extends Tool { * @see [[initializeToolSettingPropertyValues]] * @public */ - public supplyToolSettingsProperties(): DialogItem[] | undefined { return undefined; } + public supplyToolSettingsProperties(): DialogItem[] | undefined { + return undefined; + } /** Used to receive property changes from UI. Return false if there was an error applying updatedValue. * @see [[changeToolSettingPropertyValue]] * @public */ - public async applyToolSettingPropertyChange(_updatedValue: DialogPropertySyncItem): Promise { return true; } + public async applyToolSettingPropertyChange(_updatedValue: DialogPropertySyncItem): Promise { + return true; + } /** Called by tool to synchronize the UI with property changes made by tool. This is typically used to provide user feedback during tool dynamics. * If the syncData contains a quantity value and if the displayValue is not defined, the displayValue will be generated in the UI layer before displaying the value. @@ -842,7 +979,9 @@ export abstract class InteractiveTool extends Tool { * Return true if the setting was successfully bumped. * @public */ - public async bumpToolSetting(_settingIndex?: number): Promise { return false; } + public async bumpToolSetting(_settingIndex?: number): Promise { + return false; + } } /** The InputCollector class can be used to implement a command for gathering input @@ -967,7 +1106,7 @@ export class ToolRegistry { throw new IModelError(-1, "Tools must have a namespace"); this.tools.set(toolClass.toolId, toolClass); - this._keyinList = undefined; // throw away the current keyinList so we'll produce a new one next time we're asked. + this._keyinList = undefined; // throw away the current keyinList so we'll produce a new one next time we're asked. } /** @@ -975,7 +1114,7 @@ export class ToolRegistry { * @param modelObj the module to search for subclasses of Tool. */ public registerModule(moduleObj: any, namespace?: string) { - for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in + for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in const thisTool = moduleObj[thisMember]; if (thisTool.prototype instanceof Tool) { this.register(thisTool, namespace); @@ -1161,8 +1300,10 @@ export class ToolRegistry { const parsed = this.parseKeyin(keyin); if (!parsed.ok) { switch (parsed.error) { - case KeyinParseError.MismatchedQuotes: return ParseAndRunResult.MismatchedQuotes; - case KeyinParseError.ToolNotFound: return ParseAndRunResult.ToolNotFound; + case KeyinParseError.MismatchedQuotes: + return ParseAndRunResult.MismatchedQuotes; + case KeyinParseError.ToolNotFound: + return ParseAndRunResult.ToolNotFound; } } @@ -1202,6 +1343,10 @@ export class ToolRegistry { export class CoreTools { public static namespace = "CoreTools"; public static tools = "CoreTools:tools."; - public static translate(prompt: string) { return IModelApp.localization.getLocalizedString(this.tools + prompt); } - public static outputPromptByKey(key: string) { return IModelApp.notifications.outputPromptByKey(this.tools + key); } + public static translate(prompt: string) { + return IModelApp.localization.getLocalizedString(this.tools + prompt); + } + public static outputPromptByKey(key: string) { + return IModelApp.notifications.outputPromptByKey(this.tools + key); + } } diff --git a/core/frontend/src/tools/ToolAdmin.ts b/core/frontend/src/tools/ToolAdmin.ts index 9306d1583e66..45200e450154 100644 --- a/core/frontend/src/tools/ToolAdmin.ts +++ b/core/frontend/src/tools/ToolAdmin.ts @@ -6,13 +6,13 @@ * @module Tools */ +import { DialogItemValue, DialogPropertyItem, DialogPropertySyncItem } from "@itwin/appui-abstract"; import { AbandonedError, assert, BeEvent, BeTimePoint, IModelStatus, Logger } from "@itwin/core-bentley"; -import { Matrix3d, Point2d, Point3d, Transform, Vector3d, XAndY } from "@itwin/core-geometry"; import { Easing, GeometryStreamProps, NpcCenter } from "@itwin/core-common"; -import { DialogItemValue, DialogPropertyItem, DialogPropertySyncItem } from "@itwin/appui-abstract"; +import { Matrix3d, Point2d, Point3d, Transform, Vector3d, XAndY } from "@itwin/core-geometry"; import { AccuSnap, TentativeOrAccuSnap } from "../AccuSnap"; -import { LocateOptions } from "../ElementLocateManager"; import { FrontendLoggerCategory } from "../common/FrontendLoggerCategory"; +import { LocateOptions } from "../ElementLocateManager"; import { HitDetail } from "../HitDetail"; import { IModelApp } from "../IModelApp"; import { linePlaneIntersect } from "../LinePlaneIntersect"; @@ -25,8 +25,19 @@ import { ScreenViewport, Viewport } from "../Viewport"; import { ViewStatus } from "../ViewStatus"; import { PrimitiveTool } from "./PrimitiveTool"; import { - BeButton, BeButtonEvent, BeButtonState, BeModifierKeys, BeTouchEvent, BeWheelEvent, CoordinateLockOverrides, CoordSource, EventHandled, - InputCollector, InputSource, InteractiveTool, Tool, + BeButton, + BeButtonEvent, + BeButtonState, + BeModifierKeys, + BeTouchEvent, + BeWheelEvent, + CoordinateLockOverrides, + CoordSource, + EventHandled, + InputCollector, + InputSource, + InteractiveTool, + Tool, } from "./Tool"; import { ToolSettings } from "./ToolSettings"; import { ViewTool } from "./ViewTool"; @@ -35,15 +46,27 @@ import { ViewTool } from "./ViewTool"; * @public * @extensions */ -export enum StartOrResume { Start = 1, Resume = 2 } +export enum StartOrResume { + Start = 1, + Resume = 2, +} /** * @public * @extensions */ -export enum ManipulatorToolEvent { Start = 1, Stop = 2, Suspend = 3, Unsuspend = 4 } +export enum ManipulatorToolEvent { + Start = 1, + Stop = 2, + Suspend = 3, + Unsuspend = 4, +} -const enum MouseButton { Left = 0, Middle = 1, Right = 2 } // eslint-disable-line no-restricted-syntax +const enum MouseButton { + Left = 0, + Middle = 1, + Right = 2, +} // eslint-disable-line no-restricted-syntax /** Maintains the state of tool settings properties for the current session. * @see [[ToolAdmin.toolSettingsState]] to access the state for the current session. @@ -157,31 +180,57 @@ export class CurrentInputState { public touchTapTimer?: number; public touchTapCount?: number; - public get rawPoint() { return this._rawPoint; } - public set rawPoint(pt: Point3d) { this._rawPoint.setFrom(pt); } - public get point() { return this._point; } - public set point(pt: Point3d) { this._point.setFrom(pt); } - public get viewPoint() { return this._viewPoint; } - public set viewPoint(pt: Point3d) { this._viewPoint.setFrom(pt); } - public get isShiftDown() { return 0 !== (this.qualifiers & BeModifierKeys.Shift); } - public get isControlDown() { return 0 !== (this.qualifiers & BeModifierKeys.Control); } - public get isAltDown() { return 0 !== (this.qualifiers & BeModifierKeys.Alt); } - - public isDragging(button: BeButton) { return this.button[button].isDragging; } - public onStartDrag(button: BeButton) { this.button[button].isDragging = true; } + public get rawPoint() { + return this._rawPoint; + } + public set rawPoint(pt: Point3d) { + this._rawPoint.setFrom(pt); + } + public get point() { + return this._point; + } + public set point(pt: Point3d) { + this._point.setFrom(pt); + } + public get viewPoint() { + return this._viewPoint; + } + public set viewPoint(pt: Point3d) { + this._viewPoint.setFrom(pt); + } + public get isShiftDown() { + return 0 !== (this.qualifiers & BeModifierKeys.Shift); + } + public get isControlDown() { + return 0 !== (this.qualifiers & BeModifierKeys.Control); + } + public get isAltDown() { + return 0 !== (this.qualifiers & BeModifierKeys.Alt); + } + + public isDragging(button: BeButton) { + return this.button[button].isDragging; + } + public onStartDrag(button: BeButton) { + this.button[button].isDragging = true; + } public onInstallTool() { this.clearKeyQualifiers(); this.lastWheelEvent = undefined; this.lastTouchStart = this.touchTapTimer = this.touchTapCount = undefined; } - public clearKeyQualifiers() { this.qualifiers = BeModifierKeys.None; } + public clearKeyQualifiers() { + this.qualifiers = BeModifierKeys.None; + } public clearViewport(vp: Viewport) { if (vp === this.viewport) this.viewport = undefined; } - private isAnyDragging() { return this.button.some((button) => button.isDragging); } + private isAnyDragging() { + return this.button.some((button) => button.isDragging); + } private setKeyQualifier(qual: BeModifierKeys, down: boolean) { this.qualifiers = down ? (this.qualifiers | qual) : (this.qualifiers & (~qual)); } @@ -205,7 +254,9 @@ export class CurrentInputState { ev.viewPoint = ev.viewport.worldToView(ev.rawPoint); } - public updateDownPoint(ev: BeButtonEvent) { this.button[ev.button].downUorPt = ev.point; } + public updateDownPoint(ev: BeButtonEvent) { + this.button[ev.button].downUorPt = ev.point; + } public onButtonDown(button: BeButton) { const viewPt = this.viewport!.worldToView(this.button[button].downRawPt); @@ -213,7 +264,8 @@ export class CurrentInputState { viewPt.z = center.z; const now = Date.now(); - const isDoubleClick = ((now - this.button[button].downTime) < ToolSettings.doubleClickTimeout.milliseconds) && (viewPt.distance(this.viewPoint) < this.viewport!.pixelsFromInches(ToolSettings.doubleClickToleranceInches)); + const isDoubleClick = ((now - this.button[button].downTime) < ToolSettings.doubleClickTimeout.milliseconds) && + (viewPt.distance(this.viewPoint) < this.viewport!.pixelsFromInches(ToolSettings.doubleClickToleranceInches)); this.button[button].init(this.point, this.rawPoint, now, true, isDoubleClick, false, this.inputSource); this.lastButton = button; @@ -245,9 +297,16 @@ export class CurrentInputState { const buttonState = this.button[this.lastButton]; ev.init({ - point, rawPoint: this.rawPoint, viewPoint: this.viewPoint, viewport, coordsFrom, - keyModifiers: this.qualifiers, button: this.lastButton, isDown: buttonState.isDown, - isDoubleClick: buttonState.isDoubleClick, isDragging: buttonState.isDragging, + point, + rawPoint: this.rawPoint, + viewPoint: this.viewPoint, + viewport, + coordsFrom, + keyModifiers: this.qualifiers, + button: this.lastButton, + isDown: buttonState.isDown, + isDoubleClick: buttonState.isDoubleClick, + isDragging: buttonState.isDragging, inputSource: this.inputSource, }); } @@ -265,9 +324,17 @@ export class CurrentInputState { const rawPoint = state.downRawPt; const viewPoint = this.viewport ? this.viewport.worldToView(rawPoint) : Point3d.create(); // BeButtonEvent is invalid when viewport is undefined ev.init({ - point, rawPoint, viewPoint, viewport: this.viewport!, coordsFrom: CoordSource.User, - keyModifiers: this.qualifiers, button: BeButton.Data, isDown: state.isDown, - isDoubleClick: state.isDoubleClick, isDragging: state.isDragging, inputSource: state.inputSource, + point, + rawPoint, + viewPoint, + viewport: this.viewport!, + coordsFrom: CoordSource.User, + keyModifiers: this.qualifiers, + button: BeButton.Data, + isDown: state.isDown, + isDoubleClick: state.isDoubleClick, + isDragging: state.isDragging, + inputSource: state.inputSource, }); } @@ -440,18 +507,22 @@ export class ToolAdmin { private _toolSettingsChangeHandler: ((toolId: string, syncProperties: DialogPropertySyncItem[]) => void) | undefined = undefined; /** Returns the handler registered by the UI layer that allows it to display property changes made by the active Tool. */ - public get toolSettingsChangeHandler() { return this._toolSettingsChangeHandler; } + public get toolSettingsChangeHandler() { + return this._toolSettingsChangeHandler; + } public set toolSettingsChangeHandler(handler: ((toolId: string, syncProperties: DialogPropertySyncItem[]) => void) | undefined) { this._toolSettingsChangeHandler = handler; } /** The registered handler method that will inform the UI to reload tool setting with properties from active tool. - * @internal - */ + * @internal + */ private _reloadToolSettingsHandler: (() => void) | undefined = undefined; /** Returns the handler registered by the UI layer that allows it to display property changes made by the active Tool. */ - public get reloadToolSettingsHandler() { return this._reloadToolSettingsHandler; } + public get reloadToolSettingsHandler() { + return this._reloadToolSettingsHandler; + } public set reloadToolSettingsHandler(handler: (() => void) | undefined) { this._reloadToolSettingsHandler = handler; } @@ -462,7 +533,9 @@ export class ToolAdmin { private _toolSyncUiEventDispatcher: ((syncEventId: string, useImmediateDispatch?: boolean) => void) | undefined = undefined; /** Returns the handler registered by the UI layer that will trigger UiSyncEvent processing that informs UI component to refresh their state. */ - public get toolSyncUiEventDispatcher() { return this._toolSyncUiEventDispatcher; } + public get toolSyncUiEventDispatcher() { + return this._toolSyncUiEventDispatcher; + } public set toolSyncUiEventDispatcher(handler: ((syncEventId: string, useImmediateDispatch?: boolean) => void) | undefined) { this._toolSyncUiEventDispatcher = handler; } @@ -476,7 +549,7 @@ export class ToolAdmin { /** @internal */ public onInitialized() { if (typeof document === "undefined") - return; // if document isn't defined, we're probably running in a test environment. At any rate, we can't have interactive tools. + return; // if document isn't defined, we're probably running in a test environment. At any rate, we can't have interactive tools. this._idleTool = IModelApp.tools.create("Idle") as InteractiveTool; @@ -498,7 +571,9 @@ export class ToolAdmin { } /** Get the ScreenViewport where the cursor is currently, if any. */ - public get cursorView(): ScreenViewport | undefined { return this.currentInputState.viewport; } + public get cursorView(): ScreenViewport | undefined { + return this.currentInputState.viewport; + } /** Called from ViewManager.dropViewport to prevent tools from continuing to operate on the dropped viewport. * @internal @@ -524,9 +599,12 @@ export class ToolAdmin { private getMouseButton(button: number) { switch (button) { - case MouseButton.Middle: return BeButton.Middle; - case MouseButton.Right: return BeButton.Reset; - default: return BeButton.Data; + case MouseButton.Middle: + return BeButton.Middle; + case MouseButton.Right: + return BeButton.Reset; + default: + return BeButton.Data; } } @@ -604,8 +682,8 @@ export class ToolAdmin { return; const touchEv = current.lastTouchStart; - const numTouches = (undefined !== current.lastTouchStart ? current.lastTouchStart.touchCount : 0); - const numTaps = (undefined !== current.touchTapCount ? current.touchTapCount : 0); + const numTouches = undefined !== current.lastTouchStart ? current.lastTouchStart.touchCount : 0; + const numTaps = undefined !== current.touchTapCount ? current.touchTapCount : 0; current.touchTapTimer = current.touchTapCount = current.lastTouchStart = undefined; if (undefined === touchEv || 0 > numTouches || 0 > numTaps) @@ -784,18 +862,30 @@ export class ToolAdmin { return; // nothing in queue switch (event.ev.type) { - case "mousedown": return this.onMouseButton(event, true); - case "mouseup": return this.onMouseButton(event, false); - case "mousemove": return this.onMouseMove(event); - case "mouseover": return this.onMouseEnter(event); - case "mouseout": return this.onMouseLeave(event.vp!); - case "wheel": return this.onWheel(event); - case "keydown": return this.onKeyTransition(event, true); - case "keyup": return this.onKeyTransition(event, false); - case "touchstart": return this.onTouch(event); - case "touchend": return this.onTouch(event); - case "touchcancel": return this.onTouch(event); - case "touchmove": return this.onTouch(event); + case "mousedown": + return this.onMouseButton(event, true); + case "mouseup": + return this.onMouseButton(event, false); + case "mousemove": + return this.onMouseMove(event); + case "mouseover": + return this.onMouseEnter(event); + case "mouseout": + return this.onMouseLeave(event.vp!); + case "wheel": + return this.onWheel(event); + case "keydown": + return this.onKeyTransition(event, true); + case "keyup": + return this.onKeyTransition(event, false); + case "touchstart": + return this.onTouch(event); + case "touchend": + return this.onTouch(event); + case "touchcancel": + return this.onTouch(event); + case "touchmove": + return this.onTouch(event); } } @@ -809,7 +899,7 @@ export class ToolAdmin { return; // we're still working on the previous event. try { - this._processingEvent = true; // we can't allow any further event processing until the current event completes. + this._processingEvent = true; // we can't allow any further event processing until the current event completes. await this.processNextEvent(); } catch (exception) { await ToolAdmin.exceptionHandler(exception); // we don't attempt to exit here @@ -843,10 +933,16 @@ export class ToolAdmin { } /** @internal */ - public async onPostInstallTool(tool: InteractiveTool) { return tool.onPostInstall(); } + public async onPostInstallTool(tool: InteractiveTool) { + return tool.onPostInstall(); + } - public get viewTool(): ViewTool | undefined { return this._viewTool; } - public get primitiveTool(): PrimitiveTool | undefined { return this._primitiveTool; } + public get viewTool(): ViewTool | undefined { + return this._viewTool; + } + public get primitiveTool(): PrimitiveTool | undefined { + return this._primitiveTool; + } /** The currently active InteractiveTool. May be ViewTool, InputCollector, PrimitiveTool, undefined - in that priority order. */ public get activeTool(): InteractiveTool | undefined { @@ -854,13 +950,19 @@ export class ToolAdmin { } /** The current tool. May be ViewTool, InputCollector, PrimitiveTool, or IdleTool - in that priority order. */ - public get currentTool(): InteractiveTool { return this.activeTool ? this.activeTool : this.idleTool; } + public get currentTool(): InteractiveTool { + return this.activeTool ? this.activeTool : this.idleTool; + } /** Allow applications to inhibit specific tooltips, such as for maps. */ - public wantToolTip(_hit: HitDetail): boolean { return true; } + public wantToolTip(_hit: HitDetail): boolean { + return true; + } /** Ask the current tool to provide tooltip contents for the supplied HitDetail. */ - public async getToolTip(hit: HitDetail): Promise { return this.currentTool.getToolTip(hit); } + public async getToolTip(hit: HitDetail): Promise { + return this.currentTool.getToolTip(hit); + } /** * Event raised whenever the active tool changes. This includes PrimitiveTool, ViewTool, and InputCollector. @@ -950,7 +1052,7 @@ export class ToolAdmin { const context = new DynamicsContext(vp); tool.onDynamicFrame(motion, context); context.changeDynamics(); - }).catch((_) => { }); + }).catch((_) => {}); } public async sendEndDragEvent(ev: BeButtonEvent): Promise { @@ -1089,7 +1191,7 @@ export class ToolAdmin { IModelApp.accuDraw.onMotion(ev); let tool = this.activeTool; - const isValidLocation = (undefined !== tool ? tool.isValidLocation(ev, false) : true); + const isValidLocation = undefined !== tool ? tool.isValidLocation(ev, false) : true; this.setIncompatibleViewportCursor(isValidLocation); if (forceStartDrag || current.isStartDrag(ev.button)) { @@ -1130,7 +1232,7 @@ export class ToolAdmin { if (!snapOk || snapPromise !== this._snapMotionPromise) return; return processMotion(); - }).catch((_) => { }); + }).catch((_) => {}); } // Called when we detect that the motion stopped @@ -1379,9 +1481,12 @@ export class ToolAdmin { private static getModifierKey(event: KeyboardEvent): BeModifierKeys { switch (event.key) { - case "Alt": return BeModifierKeys.Alt; - case "Shift": return BeModifierKeys.Shift; - case "Control": return BeModifierKeys.Control; + case "Alt": + return BeModifierKeys.Alt; + case "Shift": + return BeModifierKeys.Shift; + case "Control": + return BeModifierKeys.Control; } return BeModifierKeys.None; } @@ -1572,7 +1677,6 @@ export class ToolAdmin { /** @internal */ public async startViewTool(newTool: ViewTool) { - IModelApp.notifications.outputPrompt(""); IModelApp.accuDraw.onViewToolInstall(); @@ -1747,10 +1851,14 @@ export class ToolAdmin { } /** @internal */ - public testDecorationHit(id: string): boolean { return this.currentTool.testDecorationHit(id); } + public testDecorationHit(id: string): boolean { + return this.currentTool.testDecorationHit(id); + } /** @internal */ - public getDecorationGeometry(hit: HitDetail): GeometryStreamProps | undefined { return this.currentTool.getDecorationGeometry(hit); } + public getDecorationGeometry(hit: HitDetail): GeometryStreamProps | undefined { + return this.currentTool.getDecorationGeometry(hit); + } /** @internal */ public decorate(context: DecorateContext): void { @@ -1801,11 +1909,17 @@ export class ToolAdmin { } /** Fill the supplied button event from the current cursor location. */ - public fillEventFromCursorLocation(ev: BeButtonEvent, useSnap = true) { this.currentInputState.toEvent(ev, useSnap); } + public fillEventFromCursorLocation(ev: BeButtonEvent, useSnap = true) { + this.currentInputState.toEvent(ev, useSnap); + } /** Fill the supplied button event from the last data button location. */ - public fillEventFromLastDataButton(ev: BeButtonEvent) { this.currentInputState.toEventFromLastDataPoint(ev); } + public fillEventFromLastDataButton(ev: BeButtonEvent) { + this.currentInputState.toEventFromLastDataPoint(ev); + } /** @internal */ - public setAdjustedDataPoint(ev: BeButtonEvent) { this.currentInputState.adjustLastDataPoint(ev); } + public setAdjustedDataPoint(ev: BeButtonEvent) { + this.currentInputState.adjustLastDataPoint(ev); + } /** Can be called by tools that wish to emulate mouse button down/up events for onTouchTap. */ public async convertTouchTapToButtonDownAndUp(ev: BeTouchEvent, button: BeButton = BeButton.Data): Promise { @@ -1905,8 +2019,12 @@ export class ToolAdmin { } /** Controls how the button event location is adjusted for the active tool */ - public get coordinateLockOverrides(): CoordinateLockOverrides { return this.toolState.coordLockOvr; } - public set coordinateLockOverrides(coordLockOvr: CoordinateLockOverrides) { this.toolState.coordLockOvr = coordLockOvr; } + public get coordinateLockOverrides(): CoordinateLockOverrides { + return this.toolState.coordLockOvr; + } + public set coordinateLockOverrides(coordLockOvr: CoordinateLockOverrides) { + this.toolState.coordLockOvr = coordLockOvr; + } /** @internal */ public async callOnCleanup() { @@ -1978,9 +2096,11 @@ export class WheelEventProcessor { if (view.is3d() && view.isCameraOn) { if (!isSnapOrPrecision) { let lastEvent = currentInputState.lastWheelEvent; - if (undefined !== lastEvent && lastEvent.viewport && + if ( + undefined !== lastEvent && lastEvent.viewport && now - lastEvent.time < ToolSettings.doubleClickTimeout.milliseconds && - lastEvent.viewport.view.equals(view) && lastEvent.viewPoint.distanceSquaredXY(ev.viewPoint) < 10) { + lastEvent.viewport.view.equals(view) && lastEvent.viewPoint.distanceSquaredXY(ev.viewPoint) < 10 + ) { target.setFrom(lastEvent.point); lastEvent.time = now; } else { @@ -2012,7 +2132,16 @@ export class WheelEventProcessor { const zDir = view.getZVector(); target.setFrom(newEye.plusScaled(zDir, zDir.dotProduct(newEye.vectorTo(target)))); - if (ViewStatus.Success === (status = view.lookAt({ eyePoint: newEye, targetPoint: target, upVector: view.getYVector(), lensAngle: view.camera.lens, opts: animationOptions }))) + if ( + ViewStatus.Success === + (status = view.lookAt({ + eyePoint: newEye, + targetPoint: target, + upVector: view.getYVector(), + lensAngle: view.camera.lens, + opts: animationOptions, + })) + ) vp.synchWithView(animationOptions); } else { const targetNpc = vp.worldToNpc(target); diff --git a/core/frontend/src/tools/ToolAssistance.ts b/core/frontend/src/tools/ToolAssistance.ts index 6a1fba05752d..ff08d5fd3a89 100644 --- a/core/frontend/src/tools/ToolAssistance.ts +++ b/core/frontend/src/tools/ToolAssistance.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. @@ -78,7 +77,17 @@ export type ToolAssistancePromptKey = "IdentifyElement" | "IdentifyPoint" | "Sta * @public * @extensions */ -export type ToolAssistanceInputKey = "AcceptSelection" | "AcceptElement" | "AcceptPoint" | "AdditionalElement" | "AdditionalPoint" | "Accept" | "Complete" | "Cancel" | "Restart" | "Exit"; +export type ToolAssistanceInputKey = + | "AcceptSelection" + | "AcceptElement" + | "AcceptPoint" + | "AdditionalElement" + | "AdditionalPoint" + | "Accept" + | "Complete" + | "Cancel" + | "Restart" + | "Exit"; /** Tool Assistance image keyboard keys * @public @@ -137,7 +146,6 @@ export interface ToolAssistanceInstructions { * @extensions */ export class ToolAssistance { - /** Up key symbol. */ public static readonly upSymbol: string = "\u2bc5"; /** Down key symbol. */ @@ -153,8 +161,12 @@ export class ToolAssistance { bottomKeys: [ToolAssistance.leftSymbol, ToolAssistance.downSymbol, ToolAssistance.rightSymbol], }; - private static translateKey(key: string) { return IModelApp.localization.getLocalizedString(`${CoreTools.namespace}:toolAssistance.${key}`); } - private static translateTouch(cursor: string) { return IModelApp.localization.getLocalizedString(`${CoreTools.namespace}:touchCursor.${cursor}`); } + private static translateKey(key: string) { + return IModelApp.localization.getLocalizedString(`${CoreTools.namespace}:toolAssistance.${key}`); + } + private static translateTouch(cursor: string) { + return IModelApp.localization.getLocalizedString(`${CoreTools.namespace}:touchCursor.${cursor}`); + } /** Return the translated string for the specified main instruction key */ public static translatePrompt(key: ToolAssistancePromptKey): string { @@ -232,7 +244,13 @@ export class ToolAssistance { /** Creates a [[ToolAssistanceInstruction]]. */ - public static createInstruction(image: string | ToolAssistanceImage, text: string, isNew?: boolean, inputMethod?: ToolAssistanceInputMethod, keyboardInfo?: ToolAssistanceKeyboardInfo): ToolAssistanceInstruction { + public static createInstruction( + image: string | ToolAssistanceImage, + text: string, + isNew?: boolean, + inputMethod?: ToolAssistanceInputMethod, + keyboardInfo?: ToolAssistanceKeyboardInfo, + ): ToolAssistanceInstruction { if (inputMethod === undefined) inputMethod = ToolAssistanceInputMethod.Both; @@ -248,7 +266,12 @@ export class ToolAssistance { /** Creates a [[ToolAssistanceInstruction]] with a [[ToolAssistanceKeyboardInfo]]. */ - public static createKeyboardInstruction(keyboardInfo: ToolAssistanceKeyboardInfo, text: string, isNew?: boolean, inputMethod?: ToolAssistanceInputMethod): ToolAssistanceInstruction { + public static createKeyboardInstruction( + keyboardInfo: ToolAssistanceKeyboardInfo, + text: string, + isNew?: boolean, + inputMethod?: ToolAssistanceInputMethod, + ): ToolAssistanceInstruction { if (inputMethod === undefined) inputMethod = ToolAssistanceInputMethod.Mouse; @@ -264,7 +287,13 @@ export class ToolAssistance { /** Creates a [[ToolAssistanceInstruction]] with a modifier key and an image. */ - public static createModifierKeyInstruction(modifierKey: string, image: string | ToolAssistanceImage, text: string, isNew?: boolean, inputMethod?: ToolAssistanceInputMethod): ToolAssistanceInstruction { + public static createModifierKeyInstruction( + modifierKey: string, + image: string | ToolAssistanceImage, + text: string, + isNew?: boolean, + inputMethod?: ToolAssistanceInputMethod, + ): ToolAssistanceInstruction { if (inputMethod === undefined) inputMethod = ToolAssistanceInputMethod.Both; @@ -296,11 +325,27 @@ export class ToolAssistance { public static createTouchCursorInstructions(instructions: ToolAssistanceInstruction[]): boolean { const accuSnap = IModelApp.accuSnap; if (undefined === accuSnap.touchCursor && accuSnap.wantVirtualCursor) { - instructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, this.translateTouch("Activate"), false, ToolAssistanceInputMethod.Touch)); + instructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, this.translateTouch("Activate"), false, ToolAssistanceInputMethod.Touch), + ); return true; } else if (undefined !== accuSnap.touchCursor) { - instructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TouchCursorDrag, this.translateTouch("IdentifyPoint"), false, ToolAssistanceInputMethod.Touch)); - instructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TouchCursorTap, this.translateTouch("AcceptPoint"), false, ToolAssistanceInputMethod.Touch)); + instructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TouchCursorDrag, + this.translateTouch("IdentifyPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + instructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TouchCursorTap, + this.translateTouch("AcceptPoint"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); return true; } return false; diff --git a/core/frontend/src/tools/ViewTool.ts b/core/frontend/src/tools/ViewTool.ts index a03034b9b607..052fb917f51b 100644 --- a/core/frontend/src/tools/ViewTool.ts +++ b/core/frontend/src/tools/ViewTool.ts @@ -6,17 +6,36 @@ * @module Tools */ +import { DialogItem, DialogProperty, DialogPropertySyncItem, PropertyDescriptionHelper } from "@itwin/appui-abstract"; import { BeDuration, BeTimePoint } from "@itwin/core-bentley"; -import { - Angle, AngleSweep, Arc3d, AxisOrder, ClipUtilities, Constant, CurveLocationDetail, Geometry, LineString3d, Matrix3d, Plane3dByOriginAndUnitNormal, - Point2d, Point3d, Range2d, Range3d, Ray3d, Transform, Vector2d, Vector3d, XAndY, YawPitchRollAngles, -} from "@itwin/core-geometry"; import { Cartographic, ColorDef, Frustum, LinePixels, NpcCenter } from "@itwin/core-common"; import { - DialogItem, DialogProperty, DialogPropertySyncItem, PropertyDescriptionHelper, -} from "@itwin/appui-abstract"; + Angle, + AngleSweep, + Arc3d, + AxisOrder, + ClipUtilities, + Constant, + CurveLocationDetail, + Geometry, + LineString3d, + Matrix3d, + Plane3dByOriginAndUnitNormal, + Point2d, + Point3d, + Range2d, + Range3d, + Ray3d, + Transform, + Vector2d, + Vector3d, + XAndY, + YawPitchRollAngles, +} from "@itwin/core-geometry"; import { AccuDraw, AccuDrawHintBuilder } from "../AccuDraw"; import { BingLocationProvider } from "../BingLocation"; +import { GraphicType } from "../common/render/GraphicType"; +import { ViewRect } from "../common/ViewRect"; import { CoordSystem } from "../CoordSystem"; import { IModelApp } from "../IModelApp"; import { LengthDescription } from "../properties/LengthDescription"; @@ -25,22 +44,33 @@ import { StandardViewId } from "../StandardView"; import { Animator, MarginOptions, OnViewExtentsError, ViewChangeOptions } from "../ViewAnimation"; import { DecorateContext } from "../ViewContext"; import { - eyeToCartographicOnGlobeFromGcs, GlobalLocation, queryTerrainElevationOffset, rangeToCartographicArea, viewGlobalLocation, + eyeToCartographicOnGlobeFromGcs, + GlobalLocation, + queryTerrainElevationOffset, + rangeToCartographicArea, + viewGlobalLocation, ViewGlobalLocationConstants, } from "../ViewGlobalLocation"; import { DepthPointSource, ScreenViewport, Viewport } from "../Viewport"; import { ViewPose } from "../ViewPose"; -import { ViewRect } from "../common/ViewRect"; import { ViewState3d } from "../ViewState"; import { ViewStatus } from "../ViewStatus"; import { EditManipulator } from "./EditManipulator"; import { PrimitiveTool } from "./PrimitiveTool"; import { - BeButton, BeButtonEvent, BeModifierKeys, BeTouchEvent, BeWheelEvent, CoordSource, CoreTools, EventHandled, InputSource, InteractiveTool, + BeButton, + BeButtonEvent, + BeModifierKeys, + BeTouchEvent, + BeWheelEvent, + CoordSource, + CoreTools, + EventHandled, + InputSource, + InteractiveTool, } from "./Tool"; import { ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection } from "./ToolAssistance"; import { ToolSettings } from "./ToolSettings"; -import { GraphicType } from "../common/render/GraphicType"; // cspell:ignore wasd, arrowright, arrowleft, pagedown, pageup, arrowup, arrowdown /* eslint-disable no-restricted-syntax */ @@ -76,7 +106,11 @@ const enum ViewManipPriority { High = 1000, } -const enum NavigateMode { Pan = 0, Look = 1, Travel = 2 } +const enum NavigateMode { + Pan = 0, + Look = 1, + Travel = 2, +} /* eslint-enable no-restricted-syntax */ @@ -90,11 +124,17 @@ const inertialDampen = (pt: Vector3d) => { * @extensions */ export abstract class ViewTool extends InteractiveTool { - public static translate(val: string) { return CoreTools.translate(`View.${val}`); } + public static translate(val: string) { + return CoreTools.translate(`View.${val}`); + } public inDynamicUpdate = false; - public beginDynamicUpdate() { this.inDynamicUpdate = true; } - public endDynamicUpdate() { this.inDynamicUpdate = false; } + public beginDynamicUpdate() { + this.inDynamicUpdate = true; + } + public endDynamicUpdate() { + this.inDynamicUpdate = false; + } public override async run(..._args: any[]): Promise { const toolAdmin = IModelApp.toolAdmin; if (undefined !== this.viewport && this.viewport === toolAdmin.markupView) { @@ -119,7 +159,9 @@ export abstract class ViewTool extends InteractiveTool { } /** Do not override. */ - public async exitTool() { return IModelApp.toolAdmin.exitViewTool(); } + public async exitTool() { + return IModelApp.toolAdmin.exitViewTool(); + } public static showPrompt(prompt: string) { IModelApp.notifications.outputPrompt(ViewTool.translate(prompt)); } @@ -133,29 +175,59 @@ export abstract class ViewingToolHandle { constructor(public viewTool: ViewManip) { this._depthPoint = undefined; } - public onReinitialize(): void { } - public onCleanup(): void { } - public focusOut(): void { } - public motion(_ev: BeButtonEvent): boolean { return false; } - public checkOneShot(): boolean { return true; } - public getHandleCursor(): string { return "default"; } + public onReinitialize(): void {} + public onCleanup(): void {} + public focusOut(): void {} + public motion(_ev: BeButtonEvent): boolean { + return false; + } + public checkOneShot(): boolean { + return true; + } + public getHandleCursor(): string { + return "default"; + } public abstract doManipulation(ev: BeButtonEvent, inDynamics: boolean): boolean; public abstract firstPoint(ev: BeButtonEvent): boolean; public abstract testHandleForHit(ptScreen: Point3d, out: { distance: number, priority: ViewManipPriority }): boolean; public abstract get handleType(): ViewHandleType; - public focusIn(): void { IModelApp.toolAdmin.setCursor(this.getHandleCursor()); } - public drawHandle(_context: DecorateContext, _hasFocus: boolean): void { } - public onWheel(_ev: BeWheelEvent): boolean { return false; } - public onTouchStart(_ev: BeTouchEvent): boolean { return false; } - public onTouchEnd(_ev: BeTouchEvent): boolean { return false; } - public async onTouchComplete(_ev: BeTouchEvent): Promise { return false; } - public async onTouchCancel(_ev: BeTouchEvent): Promise { return false; } - public onTouchMove(_ev: BeTouchEvent): boolean { return false; } - public onTouchMoveStart(_ev: BeTouchEvent, _startEv: BeTouchEvent): boolean { return false; } - public onTouchTap(_ev: BeTouchEvent): boolean { return false; } - public onKeyTransition(_wentDown: boolean, _keyEvent: KeyboardEvent): boolean { return false; } - public onModifierKeyTransition(_wentDown: boolean, _modifier: BeModifierKeys, _event: KeyboardEvent): boolean { return false; } - public needDepthPoint(_ev: BeButtonEvent, _isPreview: boolean): boolean { return false; } + public focusIn(): void { + IModelApp.toolAdmin.setCursor(this.getHandleCursor()); + } + public drawHandle(_context: DecorateContext, _hasFocus: boolean): void {} + public onWheel(_ev: BeWheelEvent): boolean { + return false; + } + public onTouchStart(_ev: BeTouchEvent): boolean { + return false; + } + public onTouchEnd(_ev: BeTouchEvent): boolean { + return false; + } + public async onTouchComplete(_ev: BeTouchEvent): Promise { + return false; + } + public async onTouchCancel(_ev: BeTouchEvent): Promise { + return false; + } + public onTouchMove(_ev: BeTouchEvent): boolean { + return false; + } + public onTouchMoveStart(_ev: BeTouchEvent, _startEv: BeTouchEvent): boolean { + return false; + } + public onTouchTap(_ev: BeTouchEvent): boolean { + return false; + } + public onKeyTransition(_wentDown: boolean, _keyEvent: KeyboardEvent): boolean { + return false; + } + public onModifierKeyTransition(_wentDown: boolean, _modifier: BeModifierKeys, _event: KeyboardEvent): boolean { + return false; + } + public needDepthPoint(_ev: BeButtonEvent, _isPreview: boolean): boolean { + return false; + } public adjustDepthPoint(isValid: boolean, _vp: Viewport, _plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource): boolean { switch (source) { case DepthPointSource.Geometry: @@ -188,7 +260,7 @@ export class ViewHandleArray { public focus = -1; public focusDrag = false; public hitHandleIndex = 0; - constructor(public viewTool: ViewManip) { } + constructor(public viewTool: ViewManip) {} public empty() { this.focus = -1; @@ -197,12 +269,24 @@ export class ViewHandleArray { this.handles.length = 0; } - public get count(): number { return this.handles.length; } - public get hitHandle(): ViewingToolHandle | undefined { return this.getByIndex(this.hitHandleIndex); } - public get focusHandle(): ViewingToolHandle | undefined { return this.getByIndex(this.focus); } - public add(handle: ViewingToolHandle): void { this.handles.push(handle); } - public getByIndex(index: number): ViewingToolHandle | undefined { return (index >= 0 && index < this.count) ? this.handles[index] : undefined; } - public focusHitHandle(): void { this.setFocus(this.hitHandleIndex); } + public get count(): number { + return this.handles.length; + } + public get hitHandle(): ViewingToolHandle | undefined { + return this.getByIndex(this.hitHandleIndex); + } + public get focusHandle(): ViewingToolHandle | undefined { + return this.getByIndex(this.focus); + } + public add(handle: ViewingToolHandle): void { + this.handles.push(handle); + } + public getByIndex(index: number): ViewingToolHandle | undefined { + return (index >= 0 && index < this.count) ? this.handles[index] : undefined; + } + public focusHitHandle(): void { + this.setFocus(this.hitHandleIndex); + } public testHit(ptScreen: Point3d, forced = ViewHandleType.None): boolean { this.hitHandleIndex = -1; @@ -284,9 +368,15 @@ export class ViewHandleArray { vp.invalidateDecorations(); } - public onReinitialize(): void { this.handles.forEach((handle) => handle.onReinitialize()); } - public onCleanup(): void { this.handles.forEach((handle) => handle.onCleanup()); } - public motion(ev: BeButtonEvent): void { this.handles.forEach((handle) => handle.motion(ev)); } + public onReinitialize(): void { + this.handles.forEach((handle) => handle.onReinitialize()); + } + public onCleanup(): void { + this.handles.forEach((handle) => handle.onCleanup()); + } + public motion(ev: BeButtonEvent): void { + this.handles.forEach((handle) => handle.motion(ev)); + } public onWheel(ev: BeWheelEvent): boolean { let preventDefault = false; this.handles.forEach((handle) => { @@ -297,7 +387,9 @@ export class ViewHandleArray { } /** determine whether a handle of a specific type exists */ - public hasHandle(handleType: ViewHandleType): boolean { return this.handles.some((handle) => handle.handleType === handleType); } + public hasHandle(handleType: ViewHandleType): boolean { + return this.handles.some((handle) => handle.handleType === handleType); + } } /** Base class for tools that manipulate the frustum of a Viewport. @@ -317,7 +409,14 @@ export abstract class ViewManip extends ViewTool { /** @internal */ public forcedHandle = ViewHandleType.None; /** @internal */ - protected _depthPreview?: { testPoint: Point3d, pickRadius: number, plane: Plane3dByOriginAndUnitNormal, source: DepthPointSource, isDefaultDepth: boolean, sourceId?: string }; + protected _depthPreview?: { + testPoint: Point3d; + pickRadius: number; + plane: Plane3dByOriginAndUnitNormal; + source: DepthPointSource; + isDefaultDepth: boolean; + sourceId?: string; + }; /** @internal */ protected _startPose?: ViewPose; @@ -356,7 +455,9 @@ export abstract class ViewManip extends ViewTool { const radius = this._depthPreview.pickRadius * pixelSize; const rMatrix = Matrix3d.createRigidHeadsUp(normal); const ellipse = Arc3d.createScaledXYColumns(origin, rMatrix, radius, radius / skew, AngleSweep.create360()); - const colorBase = (this._depthPreview.isDefaultDepth ? ColorDef.red : (DepthPointSource.Geometry === this._depthPreview.source ? ColorDef.green : context.viewport.hilite.color)); + const colorBase = this._depthPreview.isDefaultDepth + ? ColorDef.red + : (DepthPointSource.Geometry === this._depthPreview.source ? ColorDef.green : context.viewport.hilite.color); const colorLine = EditManipulator.HandleUtils.adjustForBackgroundColor(colorBase, cursorVp).withTransparency(50); const colorFill = colorLine.withTransparency(200); @@ -421,7 +522,14 @@ export abstract class ViewManip extends ViewTool { isValidDepth = this.viewHandles.hitHandle.adjustDepthPoint(isValidDepth, vp, result.plane, result.source); if (isPreview) - this._depthPreview = { testPoint: ev.rawPoint, pickRadius: pickRadiusPixels, plane: result.plane, source: result.source, isDefaultDepth: !isValidDepth, sourceId: result.sourceId }; + this._depthPreview = { + testPoint: ev.rawPoint, + pickRadius: pickRadiusPixels, + plane: result.plane, + source: result.source, + isDefaultDepth: !isValidDepth, + sourceId: result.sourceId, + }; return (isValidDepth || isPreview ? result.plane.getOriginRef() : undefined); } @@ -527,7 +635,7 @@ export abstract class ViewManip extends ViewTool { this.viewHandles.motion(ev); const prevSourceId = this.getDepthPointGeometryId(); - const showDepthChanged = (undefined !== this.pickDepthPoint(ev, true) || this.clearDepthPoint()); + const showDepthChanged = undefined !== this.pickDepthPoint(ev, true) || this.clearDepthPoint(); if (ev.viewport && (showDepthChanged || prevSourceId)) { const currSourceId = this.getDepthPointGeometryId(); if (currSourceId !== prevSourceId) @@ -676,7 +784,7 @@ export abstract class ViewManip extends ViewTool { if (!this.viewport.view.allow3dManipulations()) this.targetCenterWorld.z = 0.0; - this.viewport.viewCmdTargetCenter = (saveTarget ? pt : undefined); + this.viewport.viewCmdTargetCenter = saveTarget ? pt : undefined; } public updateTargetCenter(): void { @@ -783,7 +891,7 @@ export abstract class ViewManip extends ViewTool { /** @internal */ public static computeFitRange(viewport: ScreenViewport): Range3d { const range = viewport.computeViewRange(); - const clip = (viewport.viewFlags.clipVolume ? viewport.view.getViewClip() : undefined); + const clip = viewport.viewFlags.clipVolume ? viewport.view.getViewClip() : undefined; if (undefined !== clip) { const clipRange = ClipUtilities.rangeOfClipperIntersectionWithRange(clip, range); if (!clipRange.isNull) @@ -811,7 +919,7 @@ export abstract class ViewManip extends ViewTool { (async () => { await viewport.animateFlyoverToGlobalLocation({ center: cartographicCenter, area: cartographicArea }); // NOTE: Turns on camera...which is why we checked that it was already on... viewport.viewCmdTargetCenter = undefined; - })().catch(() => { }); + })().catch(() => {}); return; } } @@ -910,8 +1018,12 @@ export abstract class ViewManip extends ViewTool { /** ViewingToolHandle for modifying the view's target point for operations like rotate */ class ViewTargetCenter extends ViewingToolHandle { - public get handleType() { return ViewHandleType.TargetCenter; } - public override checkOneShot(): boolean { return false; } // Don't exit tool after moving target in single-shot mode... + public get handleType() { + return ViewHandleType.TargetCenter; + } + public override checkOneShot(): boolean { + return false; + } // Don't exit tool after moving target in single-shot mode... public firstPoint(ev: BeButtonEvent) { if (undefined === ev.viewport) return false; @@ -1046,7 +1158,7 @@ abstract class HandleWithInertia extends ViewingToolHandle implements Animator { // get the fraction of the inertia duration that remains. The decay is a combination of the number of iterations (see damping below) // and time. That way the handle slows down even if the framerate is lower. - const remaining = ((this._end.milliseconds - BeTimePoint.now().milliseconds) / this._duration.milliseconds); + const remaining = (this._end.milliseconds - BeTimePoint.now().milliseconds) / this._duration.milliseconds; const pt = this._lastPtNpc.plusScaled(this._inertiaVec, remaining); // if we're not moving any more, or if the duration has elapsed, we're done @@ -1059,14 +1171,18 @@ abstract class HandleWithInertia extends ViewingToolHandle implements Animator { return false; } - public interrupt() { } + public interrupt() {} protected abstract perform(thisPtNpc: Point3d): boolean; } /** ViewingToolHandle for performing the "pan view" operation */ class ViewPan extends HandleWithInertia { - public get handleType() { return ViewHandleType.Pan; } - public override getHandleCursor() { return this.viewTool.inHandleModify ? IModelApp.viewManager.grabbingCursor : IModelApp.viewManager.grabCursor; } + public get handleType() { + return ViewHandleType.Pan; + } + public override getHandleCursor() { + return this.viewTool.inHandleModify ? IModelApp.viewManager.grabbingCursor : IModelApp.viewManager.grabCursor; + } public firstPoint(ev: BeButtonEvent) { const tool = this.viewTool; @@ -1128,8 +1244,12 @@ class ViewRotate extends HandleWithInertia { private readonly _frustum = new Frustum(); private readonly _activeFrustum = new Frustum(); private readonly _anchorPtNpc = new Point3d(); - public get handleType() { return ViewHandleType.Rotate; } - public override getHandleCursor() { return IModelApp.viewManager.rotateCursor; } + public get handleType() { + return ViewHandleType.Rotate; + } + public override getHandleCursor() { + return IModelApp.viewManager.rotateCursor; + } public testHandleForHit(_ptScreen: Point3d, out: { distance: number, priority: ViewManipPriority }): boolean { out.distance = 0.0; @@ -1195,17 +1315,23 @@ class ViewRotate extends HandleWithInertia { vp.npcToView(ptNpc, currPt); const firstPt = vp.npcToView(this._anchorPtNpc); - const xDelta = (currPt.x - firstPt.x); - const yDelta = (currPt.y - firstPt.y); + const xDelta = currPt.x - firstPt.x; + const yDelta = currPt.y - firstPt.y; // Movement in screen x == rotation about drawing Z (preserve up) or rotation about screen Y... - const xAxis = ToolSettings.preserveWorldUp && !vp.viewingGlobe ? (undefined !== this._depthPoint ? vp.view.getUpVector(this._depthPoint) : Vector3d.unitZ()) : vp.rotation.getRow(1); + const xAxis = ToolSettings.preserveWorldUp && !vp.viewingGlobe + ? (undefined !== this._depthPoint ? vp.view.getUpVector(this._depthPoint) : Vector3d.unitZ()) + : vp.rotation.getRow(1); // Movement in screen y == rotation about screen X... const yAxis = vp.rotation.getRow(0); - const xRMatrix = xDelta ? Matrix3d.createRotationAroundVector(xAxis, Angle.createRadians(Math.PI / (viewRect.width / xDelta)))! : Matrix3d.identity; - const yRMatrix = yDelta ? Matrix3d.createRotationAroundVector(yAxis, Angle.createRadians(Math.PI / (viewRect.height / yDelta)))! : Matrix3d.identity; + const xRMatrix = xDelta + ? Matrix3d.createRotationAroundVector(xAxis, Angle.createRadians(Math.PI / (viewRect.width / xDelta)))! + : Matrix3d.identity; + const yRMatrix = yDelta + ? Matrix3d.createRotationAroundVector(yAxis, Angle.createRadians(Math.PI / (viewRect.height / yDelta)))! + : Matrix3d.identity; const worldRMatrix = yRMatrix.multiplyMatrixMatrix(xRMatrix); const result = worldRMatrix.getAxisAndAngleOfRotation(); angle = Angle.createRadians(-result.angle.radians); @@ -1265,8 +1391,12 @@ class ViewLook extends ViewingToolHandle { private _firstPtView = new Point3d(); private _rotation = new Matrix3d(); private _frustum = new Frustum(); - public get handleType() { return ViewHandleType.Look; } - public override getHandleCursor(): string { return IModelApp.viewManager.lookCursor; } + public get handleType() { + return ViewHandleType.Look; + } + public override getHandleCursor(): string { + return IModelApp.viewManager.lookCursor; + } public testHandleForHit(_ptScreen: Point3d, out: { distance: number, priority: ViewManipPriority }): boolean { out.distance = 0.0; @@ -1320,8 +1450,8 @@ class ViewLook extends ViewingToolHandle { const viewRect = vp.viewRect; const xExtent = viewRect.width; const yExtent = viewRect.height; - const xDelta = (currPt.x - firstPt.x); - const yDelta = (currPt.y - firstPt.y); + const xDelta = currPt.x - firstPt.x; + const yDelta = currPt.y - firstPt.y; const xAngle = -(xDelta / xExtent) * Math.PI; const yAngle = -(yDelta / yExtent) * Math.PI; @@ -1366,7 +1496,7 @@ abstract class AnimatedHandle extends ViewingToolHandle { } // called when animation is interrupted - public interrupt(): void { } + public interrupt(): void {} public animate(): boolean { // Don't continue animation when mouse is outside view, and don't jump if it returns... if (undefined !== IModelApp.toolAdmin.cursorView) @@ -1430,8 +1560,12 @@ abstract class AnimatedHandle extends ViewingToolHandle { /** ViewingToolHandle for performing the "scroll view" operation */ class ViewScroll extends AnimatedHandle { - public get handleType() { return ViewHandleType.Scroll; } - public override getHandleCursor(): string { return "move"; } + public get handleType() { + return ViewHandleType.Scroll; + } + public override getHandleCursor(): string { + return "move"; + } public override drawHandle(context: DecorateContext, _hasFocus: boolean): void { if (context.viewport !== this.viewTool.viewport || !this.viewTool.inDynamicUpdate) @@ -1532,8 +1666,12 @@ class ViewZoom extends ViewingToolHandle { protected readonly _startEyePoint = new Point3d(); protected _startFrust?: Frustum; protected _lastZoomRatio = 1.0; - public get handleType() { return ViewHandleType.Zoom; } - public override getHandleCursor() { return IModelApp.viewManager.zoomCursor; } + public get handleType() { + return ViewHandleType.Zoom; + } + public override getHandleCursor() { + return IModelApp.viewManager.zoomCursor; + } public testHandleForHit(_ptScreen: Point3d, out: { distance: number, priority: ViewManipPriority }): boolean { out.distance = 0.0; @@ -1635,7 +1773,10 @@ class ViewZoom extends ViewingToolHandle { this._lastZoomRatio = zoomRatio; const frustum = this._startFrust.clone(); - const transform = Transform.createFixedPointAndMatrix(this._anchorPtWorld, Matrix3d.createScale(zoomRatio, zoomRatio, view.is3d() ? zoomRatio : 1.0)); + const transform = Transform.createFixedPointAndMatrix( + this._anchorPtWorld, + Matrix3d.createScale(zoomRatio, zoomRatio, view.is3d() ? zoomRatio : 1.0), + ); if (view.is3d() && view.isCameraOn) { const oldEyePoint = this._startEyePoint; @@ -1664,14 +1805,16 @@ class ViewZoom extends ViewingToolHandle { class NavigateMotion { private _seconds = 0; public readonly transform = Transform.createIdentity(); - constructor(public viewport: Viewport) { } + constructor(public viewport: Viewport) {} public init(seconds: number) { this._seconds = seconds; this.transform.setIdentity(); } - public getViewUp(result?: Vector3d) { return this.viewport.rotation.getRow(1, result); } + public getViewUp(result?: Vector3d) { + return this.viewport.rotation.getRow(1, result); + } public getViewDirection(result?: Vector3d): Vector3d { const forward = this.viewport.rotation.getRow(2, result); @@ -1810,7 +1953,9 @@ class NavigateMotion { this.moveAndLook(travel, yawRate, pitchRate, isConstrainedToXY); } - public look(yawRate: number, pitchRate: number): void { this.generateRotationTransform(yawRate, pitchRate, this.transform); } + public look(yawRate: number, pitchRate: number): void { + this.generateRotationTransform(yawRate, pitchRate, this.transform); + } /** reset pitch of view to zero */ public resetToLevel(): void { @@ -1828,14 +1973,23 @@ abstract class ViewNavigate extends AnimatedHandle { private _initialized = false; protected abstract getNavigateMotion(seconds: number): NavigateMotion | undefined; - public override getHandleCursor() { return IModelApp.viewManager.walkCursor; } - public getMaxLinearVelocity() { return ToolSettings.walkVelocity; } - public getMaxAngularVelocity() { return Math.PI / 4; } + public override getHandleCursor() { + return IModelApp.viewManager.walkCursor; + } + public getMaxLinearVelocity() { + return ToolSettings.walkVelocity; + } + public getMaxAngularVelocity() { + return Math.PI / 4; + } public getNavigateMode(): NavigateMode { const state = IModelApp.toolAdmin.currentInputState; - return (state.isShiftDown || !this.viewTool.viewport!.isCameraOn) ? NavigateMode.Pan : - state.isControlDown ? NavigateMode.Look : NavigateMode.Travel; + return (state.isShiftDown || !this.viewTool.viewport!.isCameraOn) ? + NavigateMode.Pan : + state.isControlDown + ? NavigateMode.Look + : NavigateMode.Travel; } // called in animation loop @@ -1930,8 +2084,12 @@ class ViewLookAndMove extends ViewNavigate { this._navigateMotion = new NavigateMotion(this.viewTool.viewport!); } - public get handleType(): ViewHandleType { return ViewHandleType.LookAndMove; } - public override getHandleCursor(): string { return IModelApp.viewManager.lookCursor; } + public get handleType(): ViewHandleType { + return ViewHandleType.LookAndMove; + } + public override getHandleCursor(): string { + return IModelApp.viewManager.lookCursor; + } public override testHandleForHit(_ptScreen: Point3d, out: { distance: number, priority: ViewManipPriority }): boolean { out.distance = 0.0; @@ -2059,13 +2217,17 @@ class ViewLookAndMove extends ViewNavigate { return (this._touchSpeedUp ? maxLinearVelocity * 2.0 : maxLinearVelocity); const speedFactor = Geometry.clamp(ToolSettings.walkVelocityChange + (ToolSettings.walkVelocityChange > 0 ? 1 : -1), -10, 10); - const speedMultiplier = (speedFactor >= 0 ? speedFactor : 1 / Math.abs(speedFactor)); + const speedMultiplier = speedFactor >= 0 ? speedFactor : 1 / Math.abs(speedFactor); return maxLinearVelocity * speedMultiplier; } - protected getMaxAngularVelocityX() { return 2 * this.getMaxAngularVelocity(); } // Allow turning to be faster than looking up/down... - protected getMaxAngularVelocityY() { return this.getMaxAngularVelocity(); } + protected getMaxAngularVelocityX() { + return 2 * this.getMaxAngularVelocity(); + } // Allow turning to be faster than looking up/down... + protected getMaxAngularVelocityY() { + return this.getMaxAngularVelocity(); + } protected getLinearVelocity(): Vector3d { const positionInput = Vector3d.create(); @@ -2152,7 +2314,7 @@ class ViewLookAndMove extends ViewNavigate { if (0 === contourLine.numPoints()) { if (undefined === this._lastReference) { - const refPt = (ToolSettings.walkDetectFloor ? eyePt.plusScaled(Vector3d.unitZ(), -ToolSettings.walkEyeHeight) : hitPointWorld); + const refPt = ToolSettings.walkDetectFloor ? eyePt.plusScaled(Vector3d.unitZ(), -ToolSettings.walkEyeHeight) : hitPointWorld; this._lastReference = Plane3dByOriginAndUnitNormal.create(refPt, Vector3d.unitZ()); detectStepUp = ToolSettings.walkDetectFloor; } else if (undefined !== this._lastContour && this._lastContour.numPoints() > 1) { @@ -2168,7 +2330,10 @@ class ViewLookAndMove extends ViewNavigate { this._lastContour.appendPlaneIntersectionPoints(yPlaneHi, resultHi); for (const intersectionHi of resultHi) { - if ((undefined === fractHi || intersectionHi.fraction < fractHi) && intersectionHi.point.distance(hitPointWorld) < ToolSettings.walkEyeHeight) + if ( + (undefined === fractHi || intersectionHi.fraction < fractHi) && + intersectionHi.point.distance(hitPointWorld) < ToolSettings.walkEyeHeight + ) fractHi = intersectionHi.fraction; } @@ -2238,7 +2403,7 @@ class ViewLookAndMove extends ViewNavigate { if (undefined !== stepPt) { const xyDist = start.distanceXY(stepPt); const zDist = stepPt.z - start.z; - const slope = (0.0 === xyDist ? Math.PI : Math.atan(zDist / xyDist)); + const slope = 0.0 === xyDist ? Math.PI : Math.atan(zDist / xyDist); if (slope > Angle.createDegrees(10.0).radians && slope < Angle.createDegrees(50.0).radians) { const slopeRay = Ray3d.create(start, Vector3d.createStartEnd(stepPt, start)); @@ -2474,7 +2639,14 @@ class ViewLookAndMove extends ViewNavigate { return false; const pt = vp.view.getTargetPoint(); - const ev = new BeButtonEvent({ point: pt, rawPoint: pt, viewPoint: vp.worldToView(pt), viewport: vp, inputSource: InputSource.Mouse, isDown: true }); + const ev = new BeButtonEvent({ + point: pt, + rawPoint: pt, + viewPoint: vp.worldToView(pt), + viewport: vp, + inputSource: InputSource.Mouse, + isDown: true, + }); this.viewTool.changeViewport(ev.viewport); if (!this.viewTool.processFirstPoint(ev)) return false; @@ -2630,12 +2802,18 @@ class ViewLookAndMove extends ViewNavigate { public override onTouchEnd(ev: BeTouchEvent): boolean { let changed = false; - if (undefined !== this._touchStartL && undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartL.touchEvent.changedTouches[0].identifier)) { + if ( + undefined !== this._touchStartL && + undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartL.touchEvent.changedTouches[0].identifier) + ) { this._touchStartL = undefined; changed = true; } - if (undefined !== this._touchStartR && undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartR.touchEvent.changedTouches[0].identifier)) { + if ( + undefined !== this._touchStartR && + undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartR.touchEvent.changedTouches[0].identifier) + ) { this._touchStartR = undefined; changed = true; } @@ -2663,10 +2841,16 @@ class ViewLookAndMove extends ViewNavigate { let changed = false; - if (undefined !== this._touchStartL && undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartL.touchEvent.changedTouches[0].identifier)) + if ( + undefined !== this._touchStartL && + undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartL.touchEvent.changedTouches[0].identifier) + ) changed = true; - if (undefined !== this._touchStartR && undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartR.touchEvent.changedTouches[0].identifier)) + if ( + undefined !== this._touchStartR && + undefined !== BeTouchEvent.findTouchById(ev.touchEvent.changedTouches, this._touchStartR.touchEvent.changedTouches[0].identifier) + ) changed = true; if (changed) { @@ -2737,7 +2921,7 @@ class ViewLookAndMove extends ViewNavigate { addArrow(0); addArrow(Math.PI); - ctx.strokeStyle = (1 === this._lastCollision ? "red" : "white"); + ctx.strokeStyle = 1 === this._lastCollision ? "red" : "white"; ctx.lineWidth = 1; addArrow(0); addArrow(Math.PI); @@ -2746,7 +2930,7 @@ class ViewLookAndMove extends ViewNavigate { ctx.strokeStyle = "black"; ctx.lineWidth = 5; addArrow(-Math.PI / 2); - ctx.strokeStyle = (2 === this._lastCollision ? "red" : "white"); + ctx.strokeStyle = 2 === this._lastCollision ? "red" : "white"; ctx.lineWidth = 1; addArrow(-Math.PI / 2); } @@ -2756,7 +2940,7 @@ class ViewLookAndMove extends ViewNavigate { if ((0 !== ToolSettings.walkVelocityChange || this._touchSpeedUp) && this.viewTool.inDynamicUpdate) { const arrowSize = 12; - const speedUp = (ToolSettings.walkVelocityChange > 0 || this._touchSpeedUp ? true : false); + const speedUp = ToolSettings.walkVelocityChange > 0 || this._touchSpeedUp ? true : false; const position = this._anchorPtView.clone(); position.x = Math.floor(position.x) + 0.5; position.y = Math.floor(position.y + (arrowSize / 3)) + 0.5; @@ -2852,7 +3036,9 @@ class ViewWalk extends ViewNavigate { super(viewManip); this._navigateMotion = new NavigateMotion(this.viewTool.viewport!); } - public get handleType(): ViewHandleType { return ViewHandleType.Walk; } + public get handleType(): ViewHandleType { + return ViewHandleType.Walk; + } public override firstPoint(ev: BeButtonEvent): boolean { this.viewTool.provideToolAssistance("Walk.Prompts.NextPoint"); return super.firstPoint(ev); @@ -2892,7 +3078,9 @@ class ViewFly extends ViewNavigate { super(viewManip); this._navigateMotion = new NavigateMotion(this.viewTool.viewport!); } - public get handleType(): ViewHandleType { return ViewHandleType.Fly; } + public get handleType(): ViewHandleType { + return ViewHandleType.Fly; + } public override firstPoint(ev: BeButtonEvent): boolean { this.viewTool.provideToolAssistance("Fly.Prompts.NextPoint"); return super.firstPoint(ev); @@ -3012,7 +3200,7 @@ export class LookAndMoveTool extends ViewManip { public static override toolId = "View.LookAndMove"; public static override iconSpec = "icon-walk"; constructor(vp: ScreenViewport, oneShot = false, isDraggingRequired = false) { - const viewport = (undefined === vp ? IModelApp.viewManager.selectedView : vp); // Need vp to enable camera/check lens in onReinitialize... + const viewport = undefined === vp ? IModelApp.viewManager.selectedView : vp; // Need vp to enable camera/check lens in onReinitialize... super(viewport, ViewHandleType.LookAndMove | ViewHandleType.Pan, oneShot, isDraggingRequired); } public override async onReinitialize() { @@ -3026,24 +3214,93 @@ export class LookAndMoveTool extends ViewManip { const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; - const acceptMsg = this.inDynamicUpdate ? CoreTools.translate("ElementSet.Inputs.AcceptPoint") : ViewTool.translate("LookAndMove.Inputs.AcceptLookPoint"); + const acceptMsg = this.inDynamicUpdate + ? CoreTools.translate("ElementSet.Inputs.AcceptPoint") + : ViewTool.translate("LookAndMove.Inputs.AcceptLookPoint"); const rejectMsg = CoreTools.translate("ElementSet.Inputs.Exit"); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse)); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo(["W"], ["A", "S", "D"]), ViewTool.translate("LookAndMove.Inputs.WalkKeys"), false)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.arrowKeyboardInfo, ViewTool.translate("LookAndMove.Inputs.WalkKeys"), false)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo(["Q", "E"]), ViewTool.translate("LookAndMove.Inputs.ElevateKeys"), false)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo(["\u21de", "\u21df"]), ViewTool.translate("LookAndMove.Inputs.ElevateKeys"), false)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo(["C", "Z"]), ViewTool.translate("LookAndMove.Inputs.CollideKeys"), false)); - mouseInstructions.push(ToolAssistance.createKeyboardInstruction(ToolAssistance.createKeyboardInfo(["+", "-"]), ViewTool.translate("LookAndMove.Inputs.VelocityChange"), false)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.MouseWheel, ViewTool.translate("LookAndMove.Inputs.VelocityChange"), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TouchCursorDrag, ViewTool.translate("LookAndMove.Inputs.TouchZoneLL"), false, ToolAssistanceInputMethod.Touch)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TouchCursorDrag, ViewTool.translate("LookAndMove.Inputs.TouchZoneLR"), false, ToolAssistanceInputMethod.Touch)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, ViewTool.translate("LookAndMove.Inputs.TouchTapLL"), false, ToolAssistanceInputMethod.Touch)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, ViewTool.translate("LookAndMove.Inputs.TouchTapLR"), false, ToolAssistanceInputMethod.Touch)); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo(["W"], ["A", "S", "D"]), + ViewTool.translate("LookAndMove.Inputs.WalkKeys"), + false, + ), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction(ToolAssistance.arrowKeyboardInfo, ViewTool.translate("LookAndMove.Inputs.WalkKeys"), false), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo(["Q", "E"]), + ViewTool.translate("LookAndMove.Inputs.ElevateKeys"), + false, + ), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo(["\u21de", "\u21df"]), + ViewTool.translate("LookAndMove.Inputs.ElevateKeys"), + false, + ), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo(["C", "Z"]), + ViewTool.translate("LookAndMove.Inputs.CollideKeys"), + false, + ), + ); + mouseInstructions.push( + ToolAssistance.createKeyboardInstruction( + ToolAssistance.createKeyboardInfo(["+", "-"]), + ViewTool.translate("LookAndMove.Inputs.VelocityChange"), + false, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.MouseWheel, + ViewTool.translate("LookAndMove.Inputs.VelocityChange"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TouchCursorDrag, + ViewTool.translate("LookAndMove.Inputs.TouchZoneLL"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.TouchCursorDrag, + ViewTool.translate("LookAndMove.Inputs.TouchZoneLR"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + ViewTool.translate("LookAndMove.Inputs.TouchTapLL"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchTap, + ViewTool.translate("LookAndMove.Inputs.TouchTapLR"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchDrag, acceptMsg, false, ToolAssistanceInputMethod.Touch)); touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch)); @@ -3063,7 +3320,7 @@ export class WalkViewTool extends ViewManip { public static override toolId = "View.Walk"; public static override iconSpec = "icon-walk"; constructor(vp: ScreenViewport, oneShot = false, isDraggingRequired = false) { - const viewport = (undefined === vp ? IModelApp.viewManager.selectedView : vp); // Need vp to enable camera/check lens in onReinitialize... + const viewport = undefined === vp ? IModelApp.viewManager.selectedView : vp; // Need vp to enable camera/check lens in onReinitialize... super(viewport, ViewHandleType.Walk | ViewHandleType.Pan, oneShot, isDraggingRequired); } public override async onReinitialize() { @@ -3074,8 +3331,24 @@ export class WalkViewTool extends ViewManip { /** @beta */ public override provideToolAssistance(mainInstrKey: string): void { const walkInstructions: ToolAssistanceInstruction[] = []; - walkInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClickDrag, ViewTool.translate("Pan.flyover"), false, ToolAssistanceInputMethod.Mouse)); - walkInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClickDrag, ViewTool.translate("Look.flyover"), false, ToolAssistanceInputMethod.Mouse)); + walkInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClickDrag, + ViewTool.translate("Pan.flyover"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + walkInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClickDrag, + ViewTool.translate("Look.flyover"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); super.provideToolAssistance(mainInstrKey, walkInstructions); } } @@ -3097,8 +3370,24 @@ export class FlyViewTool extends ViewManip { /** @beta */ public override provideToolAssistance(mainInstrKey: string): void { const flyInstructions: ToolAssistanceInstruction[] = []; - flyInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClickDrag, ViewTool.translate("Pan.flyover"), false, ToolAssistanceInputMethod.Mouse)); - flyInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClickDrag, ViewTool.translate("Look.flyover"), false, ToolAssistanceInputMethod.Mouse)); + flyInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClickDrag, + ViewTool.translate("Pan.flyover"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + flyInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClickDrag, + ViewTool.translate("Look.flyover"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); super.provideToolAssistance(mainInstrKey, flyInstructions); } } @@ -3196,7 +3485,7 @@ export class ViewGlobeSatelliteTool extends ViewTool { if (viewport) { (async () => { await this._beginSatelliteView(viewport, this.oneShot, this.doAnimate); - })().catch(() => { }); + })().catch(() => {}); } } @@ -3270,7 +3559,12 @@ export class ViewGlobeBirdTool extends ViewTool { } private async _doBirdView(viewport: ScreenViewport, oneShot: boolean, doAnimate = true, elevationOffset = 0): Promise { - viewGlobalLocation(viewport, doAnimate, ViewGlobalLocationConstants.birdHeightAboveEarthInMeters + elevationOffset, ViewGlobalLocationConstants.birdPitchAngleRadians); + viewGlobalLocation( + viewport, + doAnimate, + ViewGlobalLocationConstants.birdHeightAboveEarthInMeters + elevationOffset, + ViewGlobalLocationConstants.birdPitchAngleRadians, + ); if (oneShot) await this.exitTool(); return oneShot; @@ -3296,14 +3590,18 @@ export class ViewGlobeLocationTool extends ViewTool { this.doAnimate = doAnimate; } - public static override get minArgs() { return 1; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return undefined; + } /** This runs the tool based on the provided location arguments. * arguments: latitude longitude | string * If specified, the latitude and longitude arguments are numbers specified in degrees. * If specified, the string argument contains a location name. Examples of location name include named geographic areas like "Seattle, WA" or "Alaska", a specific address like "1600 Pennsylvania Avenue NW, Washington, DC 20500", or a place name like "Philadelphia Museum of Art". - **/ + */ public override async parseAndRun(...args: string[]): Promise { if (2 === args.length) { // try to parse latitude and longitude const latitude = parseFloat(args[0]); @@ -3394,7 +3692,7 @@ export class ViewGlobeIModelTool extends ViewTool { const cartographicArea = rangeToCartographicArea(view3d, extents); (async () => { await viewport.animateFlyoverToGlobalLocation({ center: cartographicCenter, area: cartographicArea }); - })().catch(() => { }); + })().catch(() => {}); } } if (this.oneShot) @@ -3409,7 +3707,9 @@ export class ViewGlobeIModelTool extends ViewTool { export class StandardViewTool extends ViewTool { public static override toolId = "View.Standard"; public static override iconSpec = "icon-cube-faces-top"; - constructor(viewport: ScreenViewport, private _standardViewId: StandardViewId) { super(viewport); } + constructor(viewport: ScreenViewport, private _standardViewId: StandardViewId) { + super(viewport); + } public override async onPostInstall() { await super.onPostInstall(); @@ -3468,7 +3768,10 @@ export class WindowAreaTool extends ViewTool { /** @beta */ public provideToolAssistance(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, ViewTool.translate(this._haveFirstPoint ? "WindowArea.Prompts.NextPoint" : "WindowArea.Prompts.FirstPoint")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + ViewTool.translate(this._haveFirstPoint ? "WindowArea.Prompts.NextPoint" : "WindowArea.Prompts.FirstPoint"), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; @@ -3478,7 +3781,14 @@ export class WindowAreaTool extends ViewTool { touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchDrag, acceptMsg, false, ToolAssistanceInputMethod.Touch)); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse)); touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, exitMsg, false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, this._haveFirstPoint ? restartMsg : exitMsg, false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.RightClick, + this._haveFirstPoint ? restartMsg : exitMsg, + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -3519,8 +3829,12 @@ export class WindowAreaTool extends ViewTool { return EventHandled.Yes; } - public override async onMouseMotion(ev: BeButtonEvent) { this.doManipulation(ev, true); } - public override async onTouchTap(ev: BeTouchEvent): Promise { return ev.isSingleTap ? EventHandled.Yes : EventHandled.No; } // Prevent IdleTool from converting single tap into data button down/up... + public override async onMouseMotion(ev: BeButtonEvent) { + this.doManipulation(ev, true); + } + public override async onTouchTap(ev: BeTouchEvent): Promise { + return ev.isSingleTap ? EventHandled.Yes : EventHandled.No; + } // Prevent IdleTool from converting single tap into data button down/up... public override async onTouchMoveStart(ev: BeTouchEvent, startEv: BeTouchEvent): Promise { if (!this._haveFirstPoint && startEv.isSingleTouch) await IModelApp.toolAdmin.convertTouchMoveStartToButtonDownAndMotion(startEv, ev); @@ -3595,7 +3909,11 @@ export class WindowAreaTool extends ViewTool { this._shapePts[1].x = this._shapePts[2].x = corners[1].x; this._shapePts[0].y = this._shapePts[1].y = corners[0].y; this._shapePts[2].y = this._shapePts[3].y = corners[1].y; - this._shapePts[0].z = this._shapePts[1].z = this._shapePts[2].z = this._shapePts[3].z = corners[0].z; + this._shapePts[0].z = + this._shapePts[1].z = + this._shapePts[2].z = + this._shapePts[3].z = + corners[0].z; this._shapePts[4].setFrom(this._shapePts[0]); vp.viewToWorldArray(this._shapePts); @@ -3624,7 +3942,7 @@ export class WindowAreaTool extends ViewTool { const drawDecoration = (ctx: CanvasRenderingContext2D) => { ctx.beginPath(); - ctx.strokeStyle = (ColorDef.black === color ? "black" : "white"); + ctx.strokeStyle = ColorDef.black === color ? "black" : "white"; ctx.lineWidth = 1; ctx.moveTo(viewRect.left, cursorPt.y); ctx.lineTo(viewRect.right, cursorPt.y); @@ -3676,9 +3994,9 @@ export class WindowAreaTool extends ViewTool { vp.worldToNpcArray(corners); corners[0].z = corners[1].z = npcZValues.maximum; - vp.npcToWorldArray(corners); // Put corners back in world at correct depth + vp.npcToWorldArray(corners); // Put corners back in world at correct depth const viewPts: Point3d[] = [corners[0].clone(), corners[1].clone()]; - vp.rotation.multiplyVectorArrayInPlace(viewPts); // rotate to view orientation to get extents + vp.rotation.multiplyVectorArrayInPlace(viewPts); // rotate to view orientation to get extents const range = Range3d.createArray(viewPts); delta = Vector3d.createStartEnd(range.low, range.high); @@ -3742,7 +4060,7 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { // get the fraction of the inertia duration that remains. The decay is a combination of the number of iterations (see damping below) // and time. That way the handle slows down even if the framerate is lower. - const remaining = ((this._end.milliseconds - BeTimePoint.now().milliseconds) / this._duration.milliseconds); + const remaining = (this._end.milliseconds - BeTimePoint.now().milliseconds) / this._duration.milliseconds; const pt = this._lastPtView.plusScaled(this._inertiaVec, remaining); const vec = this._lastPtView.minus(pt); @@ -3758,7 +4076,7 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { return false; } - public interrupt() { } + public interrupt() {} constructor(startEv: BeTouchEvent, ev: BeTouchEvent, only2dManipulations = false) { super(startEv.viewport, 0, true, false); @@ -3783,8 +4101,13 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { this._rotate2dThreshold = undefined; this._lastPtView.setFrom(this._startPtView); this._startTouchCount = ev.touchCount; - this._startDirection = (2 <= ev.touchCount ? Vector2d.createStartEnd(BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp), BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp)) : Vector2d.createZero()); - this._startDistance = (2 === ev.touchCount ? this._startDirection.magnitude() : 0.0); + this._startDirection = 2 <= ev.touchCount + ? Vector2d.createStartEnd( + BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp), + BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp), + ) + : Vector2d.createZero(); + this._startDistance = 2 === ev.touchCount ? this._startDirection.magnitude() : 0.0; } private computeZoomRatio(ev?: BeTouchEvent): number { @@ -3792,7 +4115,9 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { return 1.0; const vp = this.viewport!; - const distance = (2 === ev.touchCount ? BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp).distance(BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp)) : 0.0); + const distance = 2 === ev.touchCount + ? BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp).distance(BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp)) + : 0.0; const threshold = this.viewport!.pixelsFromInches(ToolSettings.touchZoomChangeThresholdInches); if (0.0 === distance || Math.abs(this._startDistance - distance) < threshold) @@ -3800,7 +4125,7 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { // Remove inertia if the viewing operation includes zoom, only use it for pan and rotate. this._inertiaVec = undefined; - const adjustedDist = (distance > this._startDistance ? (distance - threshold) : (distance + threshold)); // Avoid sudden jump in zoom scale by subtracting zoom threshold distance... + const adjustedDist = distance > this._startDistance ? (distance - threshold) : (distance + threshold); // Avoid sudden jump in zoom scale by subtracting zoom threshold distance... return Geometry.clamp(this._startDistance / adjustedDist, .1, 10); } @@ -3809,7 +4134,10 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { return Angle.createDegrees(0.0); const vp = this.viewport!; - const direction = Vector2d.createStartEnd(BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp), BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp)); + const direction = Vector2d.createStartEnd( + BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[0], vp), + BeTouchEvent.getTouchPosition(ev.touchEvent.targetTouches[1], vp), + ); const rotation = this._startDirection.angleTo(direction); if (undefined === this._rotate2dThreshold) { @@ -3862,8 +4190,12 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { const xAxis = ToolSettings.preserveWorldUp ? Vector3d.unitZ() : vp.rotation.getRow(1); const yAxis = vp.rotation.getRow(0); - const xRMatrix = (0.0 !== xDelta) ? Matrix3d.createRotationAroundVector(xAxis, Angle.createRadians(Math.PI / (xExtent / xDelta)))! : Matrix3d.identity; - const yRMatrix = (0.0 !== yDelta) ? Matrix3d.createRotationAroundVector(yAxis, Angle.createRadians(Math.PI / (yExtent / yDelta)))! : Matrix3d.identity; + const xRMatrix = (0.0 !== xDelta) + ? Matrix3d.createRotationAroundVector(xAxis, Angle.createRadians(Math.PI / (xExtent / xDelta)))! + : Matrix3d.identity; + const yRMatrix = (0.0 !== yDelta) + ? Matrix3d.createRotationAroundVector(yAxis, Angle.createRadians(Math.PI / (yExtent / yDelta)))! + : Matrix3d.identity; const worldRMatrix = yRMatrix.multiplyMatrixMatrix(xRMatrix); const result = worldRMatrix.getAxisAndAngleOfRotation(); @@ -3954,11 +4286,17 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { const singleTouch = this._singleTouch; return (!this._only2dManipulations && vp.view.allow3dManipulations()) ? singleTouch ? this.handle3dRotate() : this.handle3dPanZoom(ev) : - singleTouch ? this.handle2dPan() : this.handle2dRotateZoom(ev); + singleTouch + ? this.handle2dPan() + : this.handle2dRotateZoom(ev); } - public override async onDataButtonDown(_ev: BeButtonEvent) { return EventHandled.Yes; } - public override async onDataButtonUp(_ev: BeButtonEvent) { return EventHandled.Yes; } + public override async onDataButtonDown(_ev: BeButtonEvent) { + return EventHandled.Yes; + } + public override async onDataButtonUp(_ev: BeButtonEvent) { + return EventHandled.Yes; + } public override async onTouchStart(ev: BeTouchEvent): Promise { if (undefined !== this.viewport) this.onStart(ev); @@ -3966,7 +4304,9 @@ export class DefaultViewTouchTool extends ViewManip implements Animator { public override async onTouchMove(ev: BeTouchEvent): Promise { this.handleEvent(ev); } - public override async onTouchCancel(_ev: BeTouchEvent): Promise { return this.exitTool(); } + public override async onTouchCancel(_ev: BeTouchEvent): Promise { + return this.exitTool(); + } public override async onTouchComplete(_ev: BeTouchEvent): Promise { // if we were moving when the touch ended, add inertia to the viewing operation if (this._inertiaVec) { @@ -4016,7 +4356,9 @@ export class ViewToggleCameraTool extends ViewTool { public static override toolId = "View.ToggleCamera"; public static override iconSpec = "icon-camera"; - public override async onInstall(): Promise { return (undefined !== this.viewport && this.viewport.view.allow3dManipulations()); } + public override async onInstall(): Promise { + return (undefined !== this.viewport && this.viewport.view.allow3dManipulations()); + } public override async onPostInstall() { if (this.viewport) { @@ -4045,15 +4387,23 @@ export class SetupCameraTool extends PrimitiveTool { protected _eyePtWorld: Point3d = Point3d.create(); protected _targetPtWorld: Point3d = Point3d.create(); - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); } - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } - public override requireWriteableTarget(): boolean { return false; } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); + } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } + public override requireWriteableTarget(): boolean { + return false; + } public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); } - public override async onUnsuspend() { this.provideToolAssistance(); } + public override async onUnsuspend() { + this.provideToolAssistance(); + } protected setupAndPromptForNextAction(): void { IModelApp.accuSnap.enableSnap(true); this.provideToolAssistance(); @@ -4070,7 +4420,10 @@ export class SetupCameraTool extends PrimitiveTool { /** @beta */ protected provideToolAssistance(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, ViewTool.translate(this._haveEyePt ? "SetupCamera.Prompts.NextPoint" : "SetupCamera.Prompts.FirstPoint")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + ViewTool.translate(this._haveEyePt ? "SetupCamera.Prompts.NextPoint" : "SetupCamera.Prompts.FirstPoint"), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; @@ -4096,8 +4449,12 @@ export class SetupCameraTool extends PrimitiveTool { return this.exitTool(); } - protected getAdjustedEyePoint() { return this.useCameraHeight ? this._eyePtWorld.plusScaled(Vector3d.unitZ(), this.cameraHeight) : this._eyePtWorld; } - protected getAdjustedTargetPoint() { return this.useTargetHeight ? this._targetPtWorld.plusScaled(Vector3d.unitZ(), this.targetHeight) : this._targetPtWorld; } + protected getAdjustedEyePoint() { + return this.useCameraHeight ? this._eyePtWorld.plusScaled(Vector3d.unitZ(), this.cameraHeight) : this._eyePtWorld; + } + protected getAdjustedTargetPoint() { + return this.useTargetHeight ? this._targetPtWorld.plusScaled(Vector3d.unitZ(), this.targetHeight) : this._targetPtWorld; + } public override async onDataButtonDown(ev: BeButtonEvent): Promise { if (undefined === ev.viewport) { @@ -4134,7 +4491,14 @@ export class SetupCameraTool extends PrimitiveTool { IModelApp.viewManager.invalidateDecorationsAllViews(); } - public static drawCameraFrustum(context: DecorateContext, vp: ScreenViewport, eyePtWorld: Point3d, targetPtWorld: Point3d, eyeSnapPtWorld?: Point3d, targetSnapPtWorld?: Point3d) { + public static drawCameraFrustum( + context: DecorateContext, + vp: ScreenViewport, + eyePtWorld: Point3d, + targetPtWorld: Point3d, + eyeSnapPtWorld?: Point3d, + targetSnapPtWorld?: Point3d, + ) { if (!vp.view.is3d() || vp.view.iModel !== context.viewport.view.iModel) return; @@ -4217,10 +4581,19 @@ export class SetupCameraTool extends PrimitiveTool { public override decorate(context: DecorateContext): void { if (!this._haveEyePt || undefined === this.viewport) return; - SetupCameraTool.drawCameraFrustum(context, this.viewport, this.getAdjustedEyePoint(), this.getAdjustedTargetPoint(), this.useCameraHeight ? this._eyePtWorld : undefined, this.useTargetHeight ? this._targetPtWorld : undefined); + SetupCameraTool.drawCameraFrustum( + context, + this.viewport, + this.getAdjustedEyePoint(), + this.getAdjustedTargetPoint(), + this.useCameraHeight ? this._eyePtWorld : undefined, + this.useTargetHeight ? this._targetPtWorld : undefined, + ); } - public override decorateSuspended(context: DecorateContext): void { this.decorate(context); } + public override decorateSuspended(context: DecorateContext): void { + this.decorate(context); + } private doManipulation(): void { const vp = this.viewport; @@ -4244,41 +4617,73 @@ export class SetupCameraTool extends PrimitiveTool { public get useCameraHeightProperty() { if (!this._useCameraHeightProperty) this._useCameraHeightProperty = new DialogProperty( - PropertyDescriptionHelper.buildLockPropertyDescription("useCameraHeight"), false, undefined, false); + PropertyDescriptionHelper.buildLockPropertyDescription("useCameraHeight"), + false, + undefined, + false, + ); return this._useCameraHeightProperty; } - public get useCameraHeight(): boolean { return this.useCameraHeightProperty.value; } - public set useCameraHeight(option: boolean) { this.useCameraHeightProperty.value = option; } + public get useCameraHeight(): boolean { + return this.useCameraHeightProperty.value; + } + public set useCameraHeight(option: boolean) { + this.useCameraHeightProperty.value = option; + } private _cameraHeightProperty: DialogProperty | undefined; public get cameraHeightProperty() { if (!this._cameraHeightProperty) - this._cameraHeightProperty = new DialogProperty(new LengthDescription("cameraHeight", ViewTool.translate("SetupCamera.Labels.CameraHeight")), - 0.0, undefined, !this.useCameraHeight); + this._cameraHeightProperty = new DialogProperty( + new LengthDescription("cameraHeight", ViewTool.translate("SetupCamera.Labels.CameraHeight")), + 0.0, + undefined, + !this.useCameraHeight, + ); return this._cameraHeightProperty; } - public get cameraHeight(): number { return this.cameraHeightProperty.value; } - public set cameraHeight(value: number) { this.cameraHeightProperty.value = value; } + public get cameraHeight(): number { + return this.cameraHeightProperty.value; + } + public set cameraHeight(value: number) { + this.cameraHeightProperty.value = value; + } private _useTargetHeightProperty: DialogProperty | undefined; public get useTargetHeightProperty() { if (!this._useTargetHeightProperty) this._useTargetHeightProperty = new DialogProperty( - PropertyDescriptionHelper.buildLockPropertyDescription("useTargetHeight"), false, undefined, false); + PropertyDescriptionHelper.buildLockPropertyDescription("useTargetHeight"), + false, + undefined, + false, + ); return this._useTargetHeightProperty; } - public get useTargetHeight(): boolean { return this.useTargetHeightProperty.value; } - public set useTargetHeight(value: boolean) { this.useTargetHeightProperty.value = value; } + public get useTargetHeight(): boolean { + return this.useTargetHeightProperty.value; + } + public set useTargetHeight(value: boolean) { + this.useTargetHeightProperty.value = value; + } private _targetHeightProperty: DialogProperty | undefined; public get targetHeightProperty() { if (!this._targetHeightProperty) - this._targetHeightProperty = new DialogProperty(new LengthDescription("targetHeight", ViewTool.translate("SetupCamera.Labels.TargetHeight")), - 0.0, undefined, !this.useTargetHeight); + this._targetHeightProperty = new DialogProperty( + new LengthDescription("targetHeight", ViewTool.translate("SetupCamera.Labels.TargetHeight")), + 0.0, + undefined, + !this.useTargetHeight, + ); return this._targetHeightProperty; } - public get targetHeight(): number { return this.targetHeightProperty.value; } - public set targetHeight(value: number) { this.targetHeightProperty.value = value; } + public get targetHeight(): number { + return this.targetHeightProperty.value; + } + public set targetHeight(value: number) { + this.targetHeightProperty.value = value; + } private syncCameraHeightState(): void { this.cameraHeightProperty.displayValue = (this.cameraHeightProperty.description as LengthDescription).format(this.cameraHeight); @@ -4313,10 +4718,12 @@ export class SetupCameraTool extends PrimitiveTool { public override supplyToolSettingsProperties(): DialogItem[] | undefined { // load latest values from session - IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, - [ - this.useCameraHeightProperty.name, this.useTargetHeightProperty.name, this.cameraHeightProperty.name, this.targetHeightProperty.name, - ]) + IModelApp.toolAdmin.toolSettingsState.getInitialToolSettingValues(this.toolId, [ + this.useCameraHeightProperty.name, + this.useTargetHeightProperty.name, + this.cameraHeightProperty.name, + this.targetHeightProperty.name, + ]) ?.forEach((value) => { if (value.propertyName === this.useCameraHeightProperty.name) this.useCameraHeightProperty.dialogItemValue = value.value; @@ -4353,15 +4760,23 @@ export class SetupWalkCameraTool extends PrimitiveTool { protected _eyePtWorld: Point3d = Point3d.create(); protected _targetPtWorld: Point3d = Point3d.create(); - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); } - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } - public override requireWriteableTarget(): boolean { return false; } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.allow3dManipulations()); + } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } + public override requireWriteableTarget(): boolean { + return false; + } public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); } - public override async onUnsuspend() { this.provideToolAssistance(); } + public override async onUnsuspend() { + this.provideToolAssistance(); + } protected setupAndPromptForNextAction(): void { IModelApp.accuSnap.enableSnap(true); this.provideToolAssistance(); @@ -4378,7 +4793,10 @@ export class SetupWalkCameraTool extends PrimitiveTool { /** @beta */ protected provideToolAssistance(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, ViewTool.translate(this._haveEyePt ? "SetupWalkCamera.Prompts.NextPoint" : "SetupWalkCamera.Prompts.FirstPoint")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + ViewTool.translate(this._haveEyePt ? "SetupWalkCamera.Prompts.NextPoint" : "SetupWalkCamera.Prompts.FirstPoint"), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; @@ -4404,8 +4822,12 @@ export class SetupWalkCameraTool extends PrimitiveTool { return this.exitTool(); } - protected getAdjustedEyePoint() { return this._eyePtWorld.plusScaled(Vector3d.unitZ(), ToolSettings.walkEyeHeight); } - protected getAdjustedTargetPoint() { return Point3d.create(this._targetPtWorld.x, this._targetPtWorld.y, this.getAdjustedEyePoint().z); } + protected getAdjustedEyePoint() { + return this._eyePtWorld.plusScaled(Vector3d.unitZ(), ToolSettings.walkEyeHeight); + } + protected getAdjustedTargetPoint() { + return Point3d.create(this._targetPtWorld.x, this._targetPtWorld.y, this.getAdjustedEyePoint().z); + } public override async onDataButtonDown(ev: BeButtonEvent): Promise { if (undefined === ev.viewport) { @@ -4524,10 +4946,19 @@ export class SetupWalkCameraTool extends PrimitiveTool { if (!this._haveEyePt || undefined === this.viewport) return; SetupWalkCameraTool.drawFigure(context, this.viewport, this._eyePtWorld, ToolSettings.walkEyeHeight); - SetupCameraTool.drawCameraFrustum(context, this.viewport, this.getAdjustedEyePoint(), this.getAdjustedTargetPoint(), this._eyePtWorld, this._targetPtWorld); + SetupCameraTool.drawCameraFrustum( + context, + this.viewport, + this.getAdjustedEyePoint(), + this.getAdjustedTargetPoint(), + this._eyePtWorld, + this._targetPtWorld, + ); } - public override decorateSuspended(context: DecorateContext): void { this.decorate(context); } + public override decorateSuspended(context: DecorateContext): void { + this.decorate(context); + } private doManipulation(): void { const vp = this.viewport; diff --git a/core/frontend/src/workers/ImdlParser/webpack.config.js b/core/frontend/src/workers/ImdlParser/webpack.config.js index 88c11e89493d..6ddf31f3267b 100644 --- a/core/frontend/src/workers/ImdlParser/webpack.config.js +++ b/core/frontend/src/workers/ImdlParser/webpack.config.js @@ -14,7 +14,7 @@ module.exports = [{ mode: "production", entry: globSync( path.resolve(frontendLib, "esm/workers/ImdlParser/Worker.js"), - { windowsPathsNoEscape: true } + { windowsPathsNoEscape: true }, ), output: { path: path.resolve(frontendLib, "workers/webpack/"), @@ -27,7 +27,7 @@ module.exports = [{ test: /\.js$/, use: "source-map-loader", sideEffects: false, - enforce: "pre" + enforce: "pre", }, { test: /@itwin/, @@ -37,6 +37,6 @@ module.exports = [{ }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, }]; diff --git a/core/geometry/eslint.config.js b/core/geometry/eslint.config.js index ddde19863db5..70625db337d5 100644 --- a/core/geometry/eslint.config.js +++ b/core/geometry/eslint.config.js @@ -11,8 +11,8 @@ module.exports = [ rules: { "@typescript-eslint/indent": "off", "max-statements-per-line": "off", - "nonblock-statement-body-position": "off" - } + "nonblock-statement-body-position": "off", + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/geometry/src/Geometry.ts b/core/geometry/src/Geometry.ts index 1026f8f6cbff..4254f0b72d7e 100644 --- a/core/geometry/src/Geometry.ts +++ b/core/geometry/src/Geometry.ts @@ -187,11 +187,11 @@ export interface BeJSONFunctions { * @public */ export type AngleProps = - { degrees: number } | - { radians: number } | - { _radians: number } | - { _degrees: number } | - number; + | { degrees: number } + | { radians: number } + | { _radians: number } + | { _degrees: number } + | number; /** * The properties for a JSON representation of an `AngleSweep`. * * The json data is always *start* and *end* angles as a pair in an array. @@ -203,15 +203,15 @@ export type AngleProps = * @public */ export type AngleSweepProps = - AngleSweep | - { degrees: [number, number] } | - { radians: [number, number] } | - [number, number]; + | AngleSweep + | { degrees: [number, number] } + | { radians: [number, number] } + | [number, number]; /** -* Interface for method with a clone operation. -* @public -* @deprecated in 4.x. Use ICloneable. -*/ + * Interface for method with a clone operation. + * @public + * @deprecated in 4.x. Use ICloneable. + */ export interface Cloneable { /** Required method to return a deep clone. */ clone(): T | undefined; @@ -357,7 +357,7 @@ export class Geometry { /** * Boolean test for metric coordinate near-equality (i.e., if `x` and `y` are almost equal) using * `tolerance = toleranceFactor * smallMetricDistance` - * */ + */ public static isSameCoordinateWithToleranceFactor(x: number, y: number, toleranceFactor: number): boolean { return Geometry.isSameCoordinate(x, y, toleranceFactor * Geometry.smallMetricDistance); } @@ -367,7 +367,11 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSameCoordinateXY( - x0: number, y0: number, x1: number, y1: number, tolerance: number = Geometry.smallMetricDistance, + x0: number, + y0: number, + x1: number, + y1: number, + tolerance: number = Geometry.smallMetricDistance, ): boolean { let d = x1 - x0; if (d < 0) @@ -385,7 +389,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSameCoordinateSquared( - x: number, y: number, tolerance: number = Geometry.smallMetricDistance, + x: number, + y: number, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return Math.abs(Math.sqrt(x) - Math.sqrt(y)) <= tolerance; } @@ -394,7 +400,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSamePoint3d( - dataA: Point3d, dataB: Point3d, tolerance: number = Geometry.smallMetricDistance, + dataA: Point3d, + dataB: Point3d, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distance(dataB) <= tolerance; } @@ -404,7 +412,9 @@ export class Geometry { * * Note that Point3d and Vector3d are both derived from XYZ, so this method tolerates mixed types. */ public static isSameXYZ( - dataA: XYZ, dataB: XYZ, tolerance: number = Geometry.smallMetricDistance, + dataA: XYZ, + dataB: XYZ, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distance(dataB) <= tolerance; } @@ -413,7 +423,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSamePoint3dXY( - dataA: Point3d, dataB: Point3d, tolerance: number = Geometry.smallMetricDistance, + dataA: Point3d, + dataB: Point3d, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distanceXY(dataB) <= tolerance; } @@ -422,7 +434,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSameVector3d( - dataA: Vector3d, dataB: Vector3d, tolerance: number = Geometry.smallMetricDistance, + dataA: Vector3d, + dataB: Vector3d, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distance(dataB) <= tolerance; } @@ -431,7 +445,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSamePoint2d( - dataA: Point2d, dataB: Point2d, tolerance: number = Geometry.smallMetricDistance, + dataA: Point2d, + dataB: Point2d, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distance(dataB) <= tolerance; } @@ -440,7 +456,9 @@ export class Geometry { * * [[smallMetricDistance]] is used if tolerance is `undefined`. */ public static isSameVector2d( - dataA: Vector2d, dataB: Vector2d, tolerance: number = Geometry.smallMetricDistance, + dataA: Vector2d, + dataB: Vector2d, + tolerance: number = Geometry.smallMetricDistance, ): boolean { return dataA.distance(dataB) <= tolerance; } @@ -738,9 +756,15 @@ export class Geometry { * common vertex. */ public static tripleProduct( - ux: number, uy: number, uz: number, - vx: number, vy: number, vz: number, - wx: number, wy: number, wz: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, + wx: number, + wy: number, + wz: number, ): number { return ux * (vy * wz - vz * wy) + uy * (vz * wx - vx * wz) @@ -748,10 +772,22 @@ export class Geometry { } /** Returns the determinant of the 4x4 matrix unrolled as the 16 parameters */ public static determinant4x4( - xx: number, xy: number, xz: number, xw: number, - yx: number, yy: number, yz: number, yw: number, - zx: number, zy: number, zz: number, zw: number, - wx: number, wy: number, wz: number, ww: number, + xx: number, + xy: number, + xz: number, + xw: number, + yx: number, + yy: number, + yz: number, + yw: number, + zx: number, + zy: number, + zz: number, + zw: number, + wx: number, + wy: number, + wz: number, + ww: number, ): number { return xx * this.tripleProduct(yy, yz, yw, zy, zz, zw, wy, wz, ww) - yx * this.tripleProduct(xy, xz, xw, zy, zz, zw, wy, wz, ww) @@ -766,14 +802,23 @@ export class Geometry { * [ weightA weightB weightC ] */ public static tripleProductXYW( - columnA: XAndY, weightA: number, - columnB: XAndY, weightB: number, - columnC: XAndY, weightC: number, + columnA: XAndY, + weightA: number, + columnB: XAndY, + weightB: number, + columnC: XAndY, + weightC: number, ): number { return Geometry.tripleProduct( - columnA.x, columnB.x, columnC.x, - columnA.y, columnB.y, columnC.y, - weightA, weightB, weightC, + columnA.x, + columnB.x, + columnC.x, + columnA.y, + columnB.y, + columnC.y, + weightA, + weightB, + weightC, ); } /** @@ -784,9 +829,15 @@ export class Geometry { */ public static tripleProductPoint4dXYW(columnA: Point4d, columnB: Point4d, columnC: Point4d): number { return Geometry.tripleProduct( - columnA.x, columnB.x, columnC.x, - columnA.y, columnB.y, columnC.y, - columnA.w, columnB.w, columnC.w, + columnA.x, + columnB.x, + columnC.x, + columnA.y, + columnB.y, + columnC.y, + columnA.w, + columnB.w, + columnC.w, ); } /** @@ -800,7 +851,13 @@ export class Geometry { } /** 3D cross product of vectors with the vectors presented as numbers. */ public static crossProductXYZXYZ( - ux: number, uy: number, uz: number, vx: number, vy: number, vz: number, result?: Vector3d, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, + result?: Vector3d, ): Vector3d { return Vector3d.create( uy * vz - uz * vy, @@ -811,7 +868,12 @@ export class Geometry { } /** Magnitude of 3D cross product of vectors with the vectors presented as numbers. */ public static crossProductMagnitude( - ux: number, uy: number, uz: number, vx: number, vy: number, vz: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, ): number { return Geometry.hypotenuseXYZ( uy * vz - uz * vy, @@ -857,8 +919,12 @@ export class Geometry { * @param vz second derivative z component */ public static curvatureMagnitude( - ux: number, uy: number, uz: number, - vx: number, vy: number, vz: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, ): number { let q = uy * vz - uz * vy; let sum = q * q; @@ -929,7 +995,7 @@ export class Geometry { private static interpolateByte(color0: number, fraction: number, color1: number, shiftBits: number): number { color0 = (color0 >>> shiftBits) & 0xFF; color1 = (color1 >>> shiftBits) & 0xFF; - const color = Math.floor(color0 + fraction * (color1 - color0)) & 0xFF; // in range [0,255] + const color = Math.floor(color0 + fraction * (color1 - color0)) & 0xFF; // in range [0,255] return color << shiftBits; } /** @@ -1025,7 +1091,9 @@ export class Geometry { * @returns return `numerator/denominator` but if the ratio exceeds `largestResult`, return `undefined`. */ public static conditionalDivideCoordinate( - numerator: number, denominator: number, largestResult: number = Geometry.largeCoordinateResult, + numerator: number, + denominator: number, + largestResult: number = Geometry.largeCoordinateResult, ): number | undefined { if (0 === denominator) return undefined; @@ -1086,7 +1154,12 @@ export class Geometry { * Return `defaultResult` if `(fTarget - f0) / (f1 - f0)` exceeds [[largeFractionResult]]. */ public static inverseInterpolate( - x0: number, f0: number, x1: number, f1: number, fTarget: number = 0, defaultResult?: number, + x0: number, + f0: number, + x1: number, + f1: number, + fTarget: number = 0, + defaultResult?: number, ): number | undefined { /** * Line equation is "fTarget-f0 = (f1-f0)/(x1-x0) * (x-x0)" or "(fTarget-f0)/(f1-f0) = (x-x0)/(x1-x0)". @@ -1233,7 +1306,9 @@ export class Geometry { * Returns `true` if both arrays have the same length and have the same entries (or both are empty arrays). */ public static almostEqualArrays( - a: T[] | undefined, b: T[] | undefined, testFunction: (p: T, q: T) => boolean, + a: T[] | undefined, + b: T[] | undefined, + testFunction: (p: T, q: T) => boolean, ): boolean { if (Array.isArray(a) && a.length === 0) a = undefined; @@ -1257,7 +1332,8 @@ export class Geometry { * Returns `true` if both arrays have the same length and have the same entries (or both are empty arrays). */ public static almostEqualNumberArrays( - a: number[] | Float64Array | undefined, b: number[] | Float64Array | undefined, + a: number[] | Float64Array | undefined, + b: number[] | Float64Array | undefined, testFunction: (p: number, q: number) => boolean, ): boolean { if (Array.isArray(a) && a.length === 0) @@ -1286,7 +1362,9 @@ export class Geometry { * but not equal or if one is defined and the other undefined. */ public static areEqualAllowUndefined( - a: T | undefined, b: T | undefined, resultIfBothUndefined: boolean = true, + a: T | undefined, + b: T | undefined, + resultIfBothUndefined: boolean = true, ): boolean { if (a === undefined && b === undefined) return resultIfBothUndefined; diff --git a/core/geometry/src/bspline/AkimaCurve3d.ts b/core/geometry/src/bspline/AkimaCurve3d.ts index 395ce86c6f0e..0f8d447db9cc 100644 --- a/core/geometry/src/bspline/AkimaCurve3d.ts +++ b/core/geometry/src/bspline/AkimaCurve3d.ts @@ -6,25 +6,25 @@ * @module Bspline */ -import { Point3d } from "../geometry3d/Point3dVector3d"; -import { Geometry } from "../Geometry"; -import { Point3dArray } from "../geometry3d/PointHelpers"; -import { ProxyCurve } from "../curve/ProxyCurve"; import { CurvePrimitive } from "../curve/CurvePrimitive"; -import { BSplineCurve3d } from "./BSplineCurve"; import { GeometryQuery } from "../curve/GeometryQuery"; -import { Transform } from "../geometry3d/Transform"; +import { ProxyCurve } from "../curve/ProxyCurve"; +import { Geometry } from "../Geometry"; import { GeometryHandler } from "../geometry3d/GeometryHandler"; +import { Point3d } from "../geometry3d/Point3dVector3d"; +import { Point3dArray } from "../geometry3d/PointHelpers"; +import { Transform } from "../geometry3d/Transform"; import { XYZProps } from "../geometry3d/XYZProps"; +import { BSplineCurve3d } from "./BSplineCurve"; /** * fitPoints [[AkimaCurve3d]] * * This is a "json compatible" version of the serializer-friendly [[AkimaCurve3dOptions]] * @public */ - export interface AkimaCurve3dProps { - /** Points that the curve must pass through */ - fitPoints: XYZProps[]; +export interface AkimaCurve3dProps { + /** Points that the curve must pass through */ + fitPoints: XYZProps[]; } /** @@ -36,15 +36,14 @@ import { XYZProps } from "../geometry3d/XYZProps"; export class AkimaCurve3dOptions { public fitPoints: Point3d[]; /** - * * @param fitPoints points to CAPTURE * @param knots array to CAPTURE */ public constructor(fitPoints?: Point3d[]) { - this.fitPoints = fitPoints ? fitPoints : []; + this.fitPoints = fitPoints ? fitPoints : []; } - /** Points that the curve must pass through. + /** Points that the curve must pass through. * First and last 2 points are "beyond the end" for control of end slope. fitPoints: Point3d[]; @@ -55,23 +54,23 @@ export class AkimaCurve3dOptions { }; return props; } -/** Clone with strongly typed members reduced to simple json. */ + /** Clone with strongly typed members reduced to simple json. */ public clone(): AkimaCurve3dOptions { const clone = new AkimaCurve3dOptions(Point3dArray.clonePoint3dArray(this.fitPoints)); return clone; } -/** Clone with strongly typed members reduced to simple json. */ -public static create(source: AkimaCurve3dProps): AkimaCurve3dOptions { - const result = new AkimaCurve3dOptions(Point3dArray.clonePoint3dArray(source.fitPoints)); - return result; -} + /** Clone with strongly typed members reduced to simple json. */ + public static create(source: AkimaCurve3dProps): AkimaCurve3dOptions { + const result = new AkimaCurve3dOptions(Point3dArray.clonePoint3dArray(source.fitPoints)); + return result; + } public static areAlmostEqual(dataA: AkimaCurve3dOptions | undefined, dataB: AkimaCurve3dOptions | undefined): boolean { if (dataA === undefined && dataB === undefined) return true; if (dataA !== undefined && dataB !== undefined) { - return Geometry.almostEqualArrays(dataA.fitPoints, dataB.fitPoints, (a: Point3d, b: Point3d) => a.isAlmostEqual(b)); + return Geometry.almostEqualArrays(dataA.fitPoints, dataB.fitPoints, (a: Point3d, b: Point3d) => a.isAlmostEqual(b)); } return false; } @@ -84,24 +83,24 @@ public static create(source: AkimaCurve3dProps): AkimaCurve3dOptions { * * * @public */ -export class AkimaCurve3d extends ProxyCurve { +export class AkimaCurve3d extends ProxyCurve { public readonly curvePrimitiveType = "interpolationCurve"; private _options: AkimaCurve3dOptions; /** * CAPTURE properties and proxy curve. */ -private constructor(properties: AkimaCurve3dOptions, proxyCurve: CurvePrimitive) { + private constructor(properties: AkimaCurve3dOptions, proxyCurve: CurvePrimitive) { super(proxyCurve); - this._options = properties; + this._options = properties; } public override dispatchToGeometryHandler(handler: GeometryHandler) { return handler.handleAkimaCurve3d(this); } -/** - * Create an [[AkimaCurve3d]] based on points, knots, and other properties in the [[AkimaCurve3dProps]] or [[AkimaCurve3dOptions]]. - * * This saves a COPY OF the options or props. - * * Use createCapture () if the options or props can be used without copy - */ + /** + * Create an [[AkimaCurve3d]] based on points, knots, and other properties in the [[AkimaCurve3dProps]] or [[AkimaCurve3dOptions]]. + * * This saves a COPY OF the options or props. + * * Use createCapture () if the options or props can be used without copy + */ public static create(options: AkimaCurve3dOptions | AkimaCurve3dProps): AkimaCurve3d | undefined { let optionsCopy; if (options instanceof AkimaCurve3dOptions) { @@ -112,7 +111,7 @@ private constructor(properties: AkimaCurve3dOptions, proxyCurve: CurvePrimitive) return AkimaCurve3d.createCapture(optionsCopy); } - public static createCapture(options: AkimaCurve3dOptions): AkimaCurve3d | undefined{ + public static createCapture(options: AkimaCurve3dOptions): AkimaCurve3d | undefined { const proxyCurve = BSplineCurve3d.createFromAkimaCurve3dOptions(options); if (proxyCurve) return new AkimaCurve3d(options, proxyCurve); @@ -161,9 +160,11 @@ private constructor(properties: AkimaCurve3dOptions, proxyCurve: CurvePrimitive) } /** Test if `other` is also an [[AkimaCurve3d]] */ - public isSameGeometryClass(other: GeometryQuery): boolean { return other instanceof AkimaCurve3d; } + public isSameGeometryClass(other: GeometryQuery): boolean { + return other instanceof AkimaCurve3d; + } - public override isAlmostEqual(other: GeometryQuery): boolean{ + public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof AkimaCurve3d) { return AkimaCurve3dOptions.areAlmostEqual(this._options, other._options); } diff --git a/core/geometry/src/bspline/BSpline1dNd.ts b/core/geometry/src/bspline/BSpline1dNd.ts index a048b655b6a9..04aee2e873bb 100644 --- a/core/geometry/src/bspline/BSpline1dNd.ts +++ b/core/geometry/src/bspline/BSpline1dNd.ts @@ -26,17 +26,27 @@ export class BSpline1dNd { /** (property accessor) Return the number of numeric values per pole. */ public poleLength: number; /** (property accessor) Return the degree of the polynomials. */ - public get degree(): number { return this.knots.degree; } + public get degree(): number { + return this.knots.degree; + } /** (property accessor) Return the number of order (one more than degree) of the polynomials */ - public get order(): number { return this.knots.degree + 1; } + public get order(): number { + return this.knots.degree + 1; + } /** (property accessor) Return the number of bezier spans (including null spans at multiple knots)*/ - public get numSpan(): number { return this.numPoles - this.knots.degree; } + public get numSpan(): number { + return this.numPoles - this.knots.degree; + } /** (property accessor) Return the number of poles*/ - public get numPoles(): number { return this.packedData.length / this.poleLength; } + public get numPoles(): number { + return this.packedData.length / this.poleLength; + } /** copy 3 values of pole `i` into a point. * * The calling class is responsible for knowing if this is an appropriate access to the blocked data. */ - public getPoint3dPole(i: number, result?: Point3d): Point3d | undefined { return Point3d.createFromPacked(this.packedData, i, result); } + public getPoint3dPole(i: number, result?: Point3d): Point3d | undefined { + return Point3d.createFromPacked(this.packedData, i, result); + } /** preallocated array (length === `order`) used as temporary in evaluations */ public basisBuffer: Float64Array; // one set of basis function values. ALLOCATED BY CTOR FOR FREQUENT REUSE /** preallocated array (length === `poleLength`) used as temporary in evaluations */ @@ -87,7 +97,7 @@ export class BSpline1dNd { /** * Evaluate the `order` basis functions (and optionally one or two derivatives) at a given fractional position within indexed span. * @returns true if and only if output arrays are sufficiently sized - */ + */ public evaluateBasisFunctionsInSpan(spanIndex: number, spanFraction: number, f: Float64Array, df?: Float64Array, ddf?: Float64Array): boolean { if (spanIndex < 0) spanIndex = 0; if (spanIndex >= this.numSpan) spanIndex = this.numSpan - 1; @@ -102,7 +112,7 @@ export class BSpline1dNd { * * Evaluations are stored in the preallocated `this.basisBuffer` * * Immediately do the summations of the basis values times the respective control points * * Summations are stored in the preallocated `this.poleBuffer` - * */ + */ public evaluateBuffersInSpan(spanIndex: number, spanFraction: number) { this.evaluateBasisFunctionsInSpan(spanIndex, spanFraction, this.basisBuffer); this.sumPoleBufferForSpan(spanIndex); @@ -112,7 +122,7 @@ export class BSpline1dNd { * * Evaluations are stored in the preallocated `this.basisBuffer` * * Immediately do the summations of the basis values times the respective control points * * Summations are stored in the preallocated `this.poleBuffer` and `this.poleBuffer1` - * */ + */ public evaluateBuffersInSpan1(spanIndex: number, spanFraction: number) { this.evaluateBasisFunctionsInSpan(spanIndex, spanFraction, this.basisBuffer, this.basisBuffer1); this.sumPoleBufferForSpan(spanIndex); @@ -170,9 +180,7 @@ export class BSpline1dNd { // reverse poles in blocks ... const b = this.poleLength; const data = this.packedData; - for (let i0 = 0, j0 = b * (this.numPoles - 1); - i0 < j0; - i0 += b, j0 -= b) { + for (let i0 = 0, j0 = b * (this.numPoles - 1); i0 < j0; i0 += b, j0 -= b) { let t = 0; for (let i = 0; i < b; i++) { t = data[i0 + i]; @@ -223,7 +231,7 @@ export class BSpline1dNd { */ public addKnot(knot: number, totalMultiplicity: number): boolean { if (knot < this.knots.leftKnot || knot > this.knots.rightKnot) - return false; // invalid input + return false; // invalid input let iLeftKnot = this.knots.knotToLeftKnotIndex(knot); // snap input if too close to an existing knot @@ -232,12 +240,12 @@ export class BSpline1dNd { } else if (Math.abs(knot - this.knots.knots[iLeftKnot + 1]) < KnotVector.knotTolerance) { iLeftKnot += this.knots.getKnotMultiplicityAtIndex(iLeftKnot + 1); if (iLeftKnot > this.knots.rightKnotIndex) - return true; // nothing to do + return true; // nothing to do knot = this.knots.knots[iLeftKnot]; // snap to left knot of next bracket } const numKnotsToAdd = Math.min(totalMultiplicity, this.degree) - this.knots.getKnotMultiplicity(knot); if (numKnotsToAdd <= 0) - return true; // nothing to do + return true; // nothing to do // working arrays and pole buffer let currKnotCount = this.knots.knots.length; @@ -248,7 +256,7 @@ export class BSpline1dNd { const newPackedData = new Float64Array(this.packedData.length + (numKnotsToAdd * this.poleLength)); for (let i = 0; i < this.packedData.length; ++i) newPackedData[i] = this.packedData[i]; - const dataBuf = new Float64Array(this.degree * this.poleLength); // holds degree poles + const dataBuf = new Float64Array(this.degree * this.poleLength); // holds degree poles // each iteration adds one knot and one pole to the working arrays (cf. Farin 4e) for (let iter = 0; iter < numKnotsToAdd; ++iter) { @@ -263,10 +271,14 @@ export class BSpline1dNd { } // overwrite degree-1 poles with degree new poles, shifting tail to the right by one - newPackedData.copyWithin((iStart + this.degree) * this.poleLength, (iStart + this.degree - 1) * this.poleLength, currPoleCount * this.poleLength); + newPackedData.copyWithin( + (iStart + this.degree) * this.poleLength, + (iStart + this.degree - 1) * this.poleLength, + currPoleCount * this.poleLength, + ); let iData = iStart * this.poleLength; for (const d of dataBuf) - newPackedData[iData++] = d; // overwrite degree new poles + newPackedData[iData++] = d; // overwrite degree new poles // add the knot to newKnots in position, shifting tail to the right by one newKnots.copyWithin(iLeftKnot + 2, iLeftKnot + 1, currKnotCount); diff --git a/core/geometry/src/bspline/BSplineCurve.ts b/core/geometry/src/bspline/BSplineCurve.ts index 38e473351486..3117e6d7568d 100644 --- a/core/geometry/src/bspline/BSplineCurve.ts +++ b/core/geometry/src/bspline/BSplineCurve.ts @@ -88,34 +88,54 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { /** The underlying blocked-pole spline, with simple x,y,z poles */ protected _bcurve: BSpline1dNd; private _definitionData?: any; - public set definitionData(data: any) { this._definitionData = data; } - public get definitionData(): any { return this._definitionData; } + public set definitionData(data: any) { + this._definitionData = data; + } + public get definitionData(): any { + return this._definitionData; + } protected constructor(poleDimension: number, numPoles: number, order: number, knots: KnotVector) { super(); this._bcurve = BSpline1dNd.create(numPoles, poleDimension, order, knots) as BSpline1dNd; } /** Return the degree (one less than the order) of the curve */ - public get degree(): number { return this._bcurve.degree; } + public get degree(): number { + return this._bcurve.degree; + } /** Return the order (one more than degree) of the curve */ - public get order(): number { return this._bcurve.order; } + public get order(): number { + return this._bcurve.order; + } /** Return the number of bezier spans in the curve. Note that this number includes the number of null spans at repeated knows */ - public get numSpan(): number { return this._bcurve.numSpan; } + public get numSpan(): number { + return this._bcurve.numSpan; + } /** Return the number of poles */ - public get numPoles(): number { return this._bcurve.numPoles; } + public get numPoles(): number { + return this._bcurve.numPoles; + } /** Return live reference to the packed control point coordinates of the curve. */ - public get polesRef(): Float64Array { return this._bcurve.packedData; } + public get polesRef(): Float64Array { + return this._bcurve.packedData; + } /** Return live reference to the knots of the curve. */ - public get knotsRef(): Float64Array { return this._bcurve.knots.knots; } + public get knotsRef(): Float64Array { + return this._bcurve.knots.knots; + } /** Number of components per pole. * * 3 for conventional (x,y,z) curve * * 4 for weighted (wx,wy,wz,w) curve */ - public get poleDimension(): number { return this._bcurve.poleLength; } + public get poleDimension(): number { + return this._bcurve.poleLength; + } /** * return a simple array form of the knots. optionally replicate the first and last * in classic over-clamped manner */ - public copyKnots(includeExtraEndKnot: boolean): number[] { return this._bcurve.knots.copyKnots(includeExtraEndKnot); } + public copyKnots(includeExtraEndKnot: boolean): number[] { + return this._bcurve.knots.copyKnots(includeExtraEndKnot); + } /** Get the flag indicating the curve might be suitable for having wrapped "closed" interpretation. */ public getWrappable(): BSplineWrapMode { @@ -180,16 +200,22 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { /** * Return the start point of the curve. */ - public override startPoint(): Point3d { return this.evaluatePointInSpan(0, 0.0); } + public override startPoint(): Point3d { + return this.evaluatePointInSpan(0, 0.0); + } /** * Return the end point of the curve */ - public override endPoint(): Point3d { return this.evaluatePointInSpan(this.numSpan - 1, 1.0); } + public override endPoint(): Point3d { + return this.evaluatePointInSpan(this.numSpan - 1, 1.0); + } /** Reverse the curve in place. * * Poles are reversed * * knot values are mirrored around the middle of the */ - public reverseInPlace(): void { this._bcurve.reverseInPlace(); } + public reverseInPlace(): void { + this._bcurve.reverseInPlace(); + } /** * Return an array with this curve's bezier fragments. */ @@ -206,11 +232,11 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { return result; } /** - * Return a BezierCurveBase for this curve. The concrete return type may be BezierCurve3d or BezierCurve3dH according to the instance type and the prefer3dH parameter. - * @param spanIndex - * @param prefer3dH true to force promotion to homogeneous. - * @param result optional reusable curve. This will only be reused if it is a BezierCurve3d with matching order. - */ + * Return a BezierCurveBase for this curve. The concrete return type may be BezierCurve3d or BezierCurve3dH according to the instance type and the prefer3dH parameter. + * @param spanIndex + * @param prefer3dH true to force promotion to homogeneous. + * @param result optional reusable curve. This will only be reused if it is a BezierCurve3d with matching order. + */ public abstract getSaturatedBezierSpan3dOr3dH(spanIndex: number, prefer3dH: boolean, result?: BezierCurveBase): BezierCurveBase | undefined; /** Return a specified pole as a Point4d. * * BSplineCurve3d appends weight 1 to its xyz @@ -263,7 +289,7 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { return result; } - /** Return a deep clone. */ + /** Return a deep clone. */ public abstract override clone(): BSplineCurve3dBase; /** Return a transformed deep clone. */ @@ -286,9 +312,11 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { clone._bcurve.addKnot(knotB, clone.degree); if (origNumKnots === clone._bcurve.knots.knots.length) - return clone; // full curve + return clone; // full curve if (knotA > knotB) { - const tmp = knotA; knotA = knotB; knotB = tmp; + const tmp = knotA; + knotA = knotB; + knotB = tmp; } // choose first/last knot and pole such that knotA/knotB has degree multiplicity in the new knot sequence @@ -298,13 +326,13 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { let iLastKnotLeftMultiple = iLastKnot - clone._bcurve.knots.getKnotMultiplicityAtIndex(iLastKnot) + 1; if (clone._bcurve.knots.knots[iLastKnot] < knotB) iLastKnotLeftMultiple = iLastKnot + 1; - const iEndPole = (iLastKnotLeftMultiple + 1) * clone._bcurve.poleLength; // one past last pole - const iEndKnot = iLastKnotLeftMultiple + clone.degree; // one past last knot + const iEndPole = (iLastKnotLeftMultiple + 1) * clone._bcurve.poleLength; // one past last pole + const iEndKnot = iLastKnotLeftMultiple + clone.degree; // one past last knot // trim the arrays (leave knots unnormalized!) clone._bcurve.knots.setKnotsCapture(clone._bcurve.knots.knots.slice(iStartKnot, iEndKnot)); clone._bcurve.packedData = clone._bcurve.packedData.slice(iStartPole, iEndPole); - clone.setWrappable(BSplineWrapMode.None); // always open + clone.setWrappable(BSplineWrapMode.None); // always open return clone; } @@ -312,7 +340,7 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { * @param plane A plane (e.g. specific type Plane3dByOriginAndUnitNormal or Point4d) * @param result growing array of plane intersections * @return number of intersections appended to the array. - */ + */ public override appendPlaneIntersectionPoints(plane: PlaneAltitudeEvaluator, result: CurveLocationDetail[]): number { const numPole = this.numPoles; const order = this.order; @@ -335,7 +363,7 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { let previousFraction = -1000.0; if (minMax.containsX(0.0)) { for (let spanIndex = 0; spanIndex < numSpan; spanIndex++) { - if (this._bcurve.knots.isIndexOfRealSpan(spanIndex)) { // ignore trivial knot intervals. + if (this._bcurve.knots.isIndexOfRealSpan(spanIndex)) { // ignore trivial knot intervals. // outer range test ... minMax.setNull(); minMax.extendArraySubset(allCoffs, spanIndex, order); @@ -393,7 +421,6 @@ export abstract class BSplineCurve3dBase extends CurvePrimitive { * @public */ export class BSplineCurve3d extends BSplineCurve3dBase { - private _workBezier?: BezierCurve3d; private initializeWorkBezier(): BezierCurve3d { if (this._workBezier === undefined) @@ -401,9 +428,14 @@ export class BSplineCurve3d extends BSplineCurve3dBase { return this._workBezier; } /** test of `other` is an instance of BSplineCurve3d */ - public isSameGeometryClass(other: any): boolean { return other instanceof BSplineCurve3d; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BSplineCurve3d; + } /** Apply `transform` to the poles. */ - public tryTransformInPlace(transform: Transform): boolean { Point3dArray.multiplyInPlace(transform, this._bcurve.packedData); return true; } + public tryTransformInPlace(transform: Transform): boolean { + Point3dArray.multiplyInPlace(transform, this._bcurve.packedData); + return true; + } /** Get a pole as simple Point3d. */ public getPolePoint3d(poleIndex: number, result?: Point3d): Point3d | undefined { const k = this.poleIndexToDataIndex(poleIndex); @@ -430,14 +462,20 @@ export class BSplineCurve3d extends BSplineCurve3dBase { super(3, numPoles, order, knots); } /** Return a simple array of arrays with the control points as `[[x,y,z],[x,y,z],..]` */ - public copyPoints(): any[] { return Point3dArray.unpackNumbersToNestedArrays(this._bcurve.packedData, 3); } + public copyPoints(): any[] { + return Point3dArray.unpackNumbersToNestedArrays(this._bcurve.packedData, 3); + } /** Return a simple array of the control points coordinates */ - public copyPointsFloat64Array(): Float64Array { return this._bcurve.packedData.slice(); } + public copyPointsFloat64Array(): Float64Array { + return this._bcurve.packedData.slice(); + } /** * return a simple array form of the knots. optionally replicate the first and last * in classic over-clamped manner */ - public override copyKnots(includeExtraEndKnot: boolean): number[] { return this._bcurve.knots.copyKnots(includeExtraEndKnot); } + public override copyKnots(includeExtraEndKnot: boolean): number[] { + return this._bcurve.knots.copyKnots(includeExtraEndKnot); + } /** Create a bspline with uniform knots. */ public static createUniformKnots(poles: Point3d[] | Float64Array | GrowableXYZArray, order: number): BSplineCurve3d | undefined { @@ -464,7 +502,7 @@ export class BSplineCurve3d extends BSplineCurve3dBase { /** Create a smoothly closed B-spline curve with uniform knots. * Note that the curve does not start at the first pole! - */ + */ public static createPeriodicUniformKnots(poles: Point3d[] | Float64Array | GrowableXYZArray, order: number): BSplineCurve3d | undefined { if (order < 2) return undefined; @@ -488,7 +526,7 @@ export class BSplineCurve3d extends BSplineCurve3dBase { endPoint.setFromPoint3d(poles[numPoles - 1]); } if (hasClosurePoint = startPoint.isAlmostEqual(endPoint)) - --numPoles; // remove wraparound pole if found + --numPoles; // remove wraparound pole if found } while (hasClosurePoint && numPoles > 1); if (numPoles < order) @@ -537,11 +575,10 @@ export class BSplineCurve3d extends BSplineCurve3dBase { } /** - * * @param options collection of points and end conditions. */ public static createFromAkimaCurve3dOptions(options: AkimaCurve3dOptions): BSplineCurve3d | undefined { - return BSplineCurveOps.createThroughPoints(options.fitPoints, 4); // temporary + return BSplineCurveOps.createThroughPoints(options.fitPoints, 4); // temporary } /** @@ -554,18 +591,22 @@ export class BSplineCurve3d extends BSplineCurve3dBase { * * If poleArray.length + order === knotArray.length, the first and last are assumed to be the extraneous knots of classic clamping. * * If poleArray.length + order === knotArray.length + 2, the knots are in modern form. */ - public static create(poleArray: Float64Array | Point3d[] | number[][], knotArray: Float64Array | number[], order: number): BSplineCurve3d | undefined { + public static create( + poleArray: Float64Array | Point3d[] | number[][], + knotArray: Float64Array | number[], + order: number, + ): BSplineCurve3d | undefined { if (order < 2) return undefined; let numPoles = poleArray.length; if (poleArray instanceof Float64Array) - numPoles = Math.floor(numPoles / 3); // blocked as xyz + numPoles = Math.floor(numPoles / 3); // blocked as xyz if (numPoles < order) return undefined; const numKnots = knotArray.length; - const skipFirstAndLast = (numPoles + order === numKnots); // classic over-clamped input knots + const skipFirstAndLast = numPoles + order === numKnots; // classic over-clamped input knots if (!skipFirstAndLast && numPoles + order !== numKnots + 2) // modern knots return undefined; const knots = KnotVector.create(knotArray, order - 1, skipFirstAndLast); @@ -612,7 +653,8 @@ export class BSplineCurve3d extends BSplineCurve3dBase { this._bcurve.evaluateBuffersInSpan1(spanIndex, spanFraction); return Ray3d.createCapture( Point3d.createFrom(this._bcurve.poleBuffer), - Vector3d.createFrom(this._bcurve.poleBuffer1)); + Vector3d.createFrom(this._bcurve.poleBuffer1), + ); } /** Evaluate at a position given by a knot value. */ @@ -623,9 +665,11 @@ export class BSplineCurve3d extends BSplineCurve3dBase { /** Evaluate at a position given by a knot value. */ public knotToPointAndDerivative(u: number, result?: Ray3d): Ray3d { this._bcurve.evaluateBuffersAtKnot(u, 1); - if (!result) return Ray3d.createCapture( - Point3d.createFrom(this._bcurve.poleBuffer), - Vector3d.createFrom(this._bcurve.poleBuffer1)); + if (!result) + return Ray3d.createCapture( + Point3d.createFrom(this._bcurve.poleBuffer), + Vector3d.createFrom(this._bcurve.poleBuffer1), + ); result.origin.setFrom(this._bcurve.poleBuffer); result.direction.setFrom(this._bcurve.poleBuffer1); return result; @@ -635,9 +679,17 @@ export class BSplineCurve3d extends BSplineCurve3dBase { public knotToPointAnd2Derivatives(u: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { this._bcurve.evaluateBuffersAtKnot(u, 2); return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - this._bcurve.poleBuffer[0], this._bcurve.poleBuffer[1], this._bcurve.poleBuffer[2], - this._bcurve.poleBuffer1[0], this._bcurve.poleBuffer1[1], this._bcurve.poleBuffer1[2], - this._bcurve.poleBuffer2[0], this._bcurve.poleBuffer2[1], this._bcurve.poleBuffer2[2], result); + this._bcurve.poleBuffer[0], + this._bcurve.poleBuffer[1], + this._bcurve.poleBuffer[2], + this._bcurve.poleBuffer1[0], + this._bcurve.poleBuffer1[1], + this._bcurve.poleBuffer1[2], + this._bcurve.poleBuffer2[0], + this._bcurve.poleBuffer2[1], + this._bcurve.poleBuffer2[2], + result, + ); } /** test if almost the same curve as `other` */ @@ -653,7 +705,9 @@ export class BSplineCurve3d extends BSplineCurve3dBase { return Point3dArray.isCloseToPlane(this._bcurve.packedData, plane); } /** Return the control polygon length as approximation (always overestimate) of the curve length. */ - public quickLength(): number { return Point3dArray.sumEdgeLengths(this._bcurve.packedData); } + public quickLength(): number { + return Point3dArray.sumEdgeLengths(this._bcurve.packedData); + } /** Emit beziers or strokes (selected by the stroke options) to the handler. */ public emitStrokableParts(handler: IStrokeHandler, options?: StrokeOptions): void { const needBeziers = handler.announceBezierCurve !== undefined; @@ -665,15 +719,21 @@ export class BSplineCurve3d extends BSplineCurve3dBase { if (bezier) { numStrokes = bezier.computeStrokeCountForOptions(options); if (needBeziers) { - handler.announceBezierCurve!(bezier, numStrokes, this, + handler.announceBezierCurve!( + bezier, + numStrokes, + this, spanIndex, this._bcurve.knots.spanFractionToFraction(spanIndex, 0.0), - this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0)); - + this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0), + ); } else { - handler.announceIntervalForUniformStepStrokes(this, numStrokes, + handler.announceIntervalForUniformStepStrokes( + this, + numStrokes, this._bcurve.knots.spanFractionToFraction(spanIndex, 0.0), - this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0)); + this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0), + ); } } } @@ -729,7 +789,7 @@ export class BSplineCurve3d extends BSplineCurve3dBase { * Test knots and control points to determine if it is possible to close (aka "wrap") the curve. * @returns the manner in which it is possible to close the curve. See `BSplineWrapMode` for particulars of each mode. */ - public get isClosable(): BSplineWrapMode { + public get isClosable(): BSplineWrapMode { return this.isClosableCurve; } /** @@ -801,5 +861,4 @@ export class BSplineCurve3d extends BSplineCurve3dBase { rangeToExtend.extendXYZ(buffer[i0], buffer[i0 + 1], buffer[i0 + 2]); } } - } diff --git a/core/geometry/src/bspline/BSplineCurve3dH.ts b/core/geometry/src/bspline/BSplineCurve3dH.ts index 01a40a8bb78d..712383f82b8e 100644 --- a/core/geometry/src/bspline/BSplineCurve3dH.ts +++ b/core/geometry/src/bspline/BSplineCurve3dH.ts @@ -37,9 +37,14 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { return this._workBezier; } /** Test if `other` is an instance of `BSplineCurve3dH` */ - public isSameGeometryClass(other: any): boolean { return other instanceof BSplineCurve3dH; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BSplineCurve3dH; + } /** Apply `transform` to the curve */ - public tryTransformInPlace(transform: Transform): boolean { Point4dArray.multiplyInPlace(transform, this._bcurve.packedData); return true; } + public tryTransformInPlace(transform: Transform): boolean { + Point4dArray.multiplyInPlace(transform, this._bcurve.packedData); + return true; + } /** Get a pole, normalized to Point3d. */ public getPolePoint3d(poleIndex: number, result?: Point3d): Point3d | undefined { const k = this.poleIndexToDataIndex(poleIndex); @@ -68,9 +73,13 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { super(4, numPoles, order, knots); } /** Return a simple array of arrays with the control points as `[[x,y,z,w],[x,y,z,w],..]` */ - public copyPoints(): any[] { return Point3dArray.unpackNumbersToNestedArrays(this._bcurve.packedData, 4); } + public copyPoints(): any[] { + return Point3dArray.unpackNumbersToNestedArrays(this._bcurve.packedData, 4); + } /** Return a simple array of the control points coordinates */ - public copyPointsFloat64Array(): Float64Array { return this._bcurve.packedData.slice(); } + public copyPointsFloat64Array(): Float64Array { + return this._bcurve.packedData.slice(); + } /** Return a simple array of the control points xyz coordinates. */ public copyXYZFloat64Array(deweighted: boolean): Float64Array { const numValue = this.numPoles * 3; @@ -84,7 +93,6 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { result[k++] = this._bcurve.packedData[i++] * dw; result[k++] = this._bcurve.packedData[i++] * dw; result[k++] = this._bcurve.packedData[i++] * dw; - } else { result[k++] = this._bcurve.packedData[i++]; result[k++] = this._bcurve.packedData[i++]; @@ -170,7 +178,7 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { endPoint.set(poles[numPoles - 1].x, poles[numPoles - 1].y, poles[numPoles - 1].z, is4d ? (poles[numPoles - 1] as Point4d).w : 1.0); } if (hasClosurePoint = startPoint.isAlmostEqual(endPoint)) - --numPoles; // remove wraparound pole if found + --numPoles; // remove wraparound pole if found } while (hasClosurePoint && numPoles > 1); if (numPoles < order) @@ -210,7 +218,9 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { * Assemble a variously structured control points into packed array of [xyzw]. * @param controlPoints */ - public static assemblePackedXYZW(controlPoints: Float64Array | Point4d[] | { xyz: Float64Array, weights: Float64Array } | Point3d[] | number[][]): Float64Array | undefined { + public static assemblePackedXYZW( + controlPoints: Float64Array | Point4d[] | { xyz: Float64Array, weights: Float64Array } | Point3d[] | number[][], + ): Float64Array | undefined { if (controlPoints instanceof Float64Array) return controlPoints.slice(); @@ -279,7 +289,11 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { * * If poleArray.length + order == knotArray.length, the first and last are assumed to be the extraneous knots of classic clamping. * * If poleArray.length + order == knotArray.length + 2, the knots are in modern form. */ - public static create(controlPointData: Float64Array | Point4d[] | { xyz: Float64Array, weights: Float64Array } | Point3d[] | number[][], knotArray: Float64Array | number[], order: number): BSplineCurve3dH | undefined { + public static create( + controlPointData: Float64Array | Point4d[] | { xyz: Float64Array, weights: Float64Array } | Point3d[] | number[][], + knotArray: Float64Array | number[], + order: number, + ): BSplineCurve3dH | undefined { if (order < 2) return undefined; @@ -292,7 +306,7 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { return undefined; const numKnots = knotArray.length; - const skipFirstAndLast = (numPoles + order === numKnots); // classic over-clamped input knots + const skipFirstAndLast = numPoles + order === numKnots; // classic over-clamped input knots if (!skipFirstAndLast && numPoles + order !== numKnots + 2) // modern knots return undefined; const knots = KnotVector.create(knotArray, order - 1, skipFirstAndLast); @@ -326,8 +340,16 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { const xyzw = this._bcurve.poleBuffer; const dXYZW = this._bcurve.poleBuffer1; return Point4d.createRealDerivativeRay3dDefault000( - xyzw[0], xyzw[1], xyzw[2], xyzw[3], - dXYZW[0], dXYZW[1], dXYZW[2], dXYZW[3], result); + xyzw[0], + xyzw[1], + xyzw[2], + xyzw[3], + dXYZW[0], + dXYZW[1], + dXYZW[2], + dXYZW[3], + result, + ); } /** Evaluate at a position given by a knot value. */ @@ -342,8 +364,16 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { const xyzw = this._bcurve.poleBuffer; const dXYZW = this._bcurve.poleBuffer1; return Point4d.createRealDerivativeRay3dDefault000( - xyzw[0], xyzw[1], xyzw[2], xyzw[3], - dXYZW[0], dXYZW[1], dXYZW[2], dXYZW[3], result); + xyzw[0], + xyzw[1], + xyzw[2], + xyzw[3], + dXYZW[0], + dXYZW[1], + dXYZW[2], + dXYZW[3], + result, + ); } /** Evaluate at a position given by a knot value. Return point with 2 derivatives. */ @@ -353,10 +383,20 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { const dXYZW = this._bcurve.poleBuffer1; const ddXYZW = this._bcurve.poleBuffer2; return Point4d.createRealDerivativePlane3dByOriginAndVectorsDefault000( - xyzw[0], xyzw[1], xyzw[2], xyzw[3], - dXYZW[0], dXYZW[1], dXYZW[2], dXYZW[3], - ddXYZW[0], ddXYZW[1], ddXYZW[2], ddXYZW[3], - result); + xyzw[0], + xyzw[1], + xyzw[2], + xyzw[3], + dXYZW[0], + dXYZW[1], + dXYZW[2], + dXYZW[3], + ddXYZW[0], + ddXYZW[1], + ddXYZW[2], + ddXYZW[3], + result, + ); } /** test if the curve is almost equal to `other` */ public override isAlmostEqual(other: any): boolean { @@ -371,7 +411,9 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { return Point4dArray.isCloseToPlane(this._bcurve.packedData, plane); } /** Return the control polygon length as quick approximation to the curve length. */ - public quickLength(): number { return Point3dArray.sumEdgeLengths(this._bcurve.packedData); } + public quickLength(): number { + return Point3dArray.sumEdgeLengths(this._bcurve.packedData); + } /** call a handler with interval data for stroking. */ public emitStrokableParts(handler: IStrokeHandler, options?: StrokeOptions): void { const needBeziers = (handler as any).announceBezierCurve; @@ -383,15 +425,21 @@ export class BSplineCurve3dH extends BSplineCurve3dBase { if (bezier) { numStrokes = bezier.computeStrokeCountForOptions(options); if (needBeziers) { - (handler as any).announceBezierCurve(bezier, numStrokes, this, + (handler as any).announceBezierCurve( + bezier, + numStrokes, + this, spanIndex, this._bcurve.knots.spanFractionToFraction(spanIndex, 0.0), - this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0)); - + this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0), + ); } else { - handler.announceIntervalForUniformStepStrokes(this, numStrokes, + handler.announceIntervalForUniformStepStrokes( + this, + numStrokes, this._bcurve.knots.spanFractionToFraction(spanIndex, 0.0), - this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0)); + this._bcurve.knots.spanFractionToFraction(spanIndex, 1.0), + ); } } } diff --git a/core/geometry/src/bspline/BSplineCurveOps.ts b/core/geometry/src/bspline/BSplineCurveOps.ts index 9d3ebf7764aa..7586ce62b06f 100644 --- a/core/geometry/src/bspline/BSplineCurveOps.ts +++ b/core/geometry/src/bspline/BSplineCurveOps.ts @@ -31,7 +31,7 @@ export class BSplineCurveOps { if (order > numPoints || order < 2) return undefined; const degree = order - 1; - const bw = 1 + 2 * degree; // probably less than that . . just zeros at fringe. + const bw = 1 + 2 * degree; // probably less than that . . just zeros at fringe. const matrix = new Float64Array(bw * numPoints); const basisFunctions = new Float64Array(order); const rhs = new GrowableXYZArray(); @@ -185,8 +185,12 @@ export namespace BSplineCurveOps { * @param isChordLength whether knots are computed using distances between successive fit points * @param closed whether curve is periodically defined * @return fit parameters, one per fit point - */ - public static constructFitParametersFromPoints(fitPoints: Point3d[], isChordLength: number | undefined, closed: boolean | undefined): number[] | undefined { + */ + public static constructFitParametersFromPoints( + fitPoints: Point3d[], + isChordLength: number | undefined, + closed: boolean | undefined, + ): number[] | undefined { let params: number[] | undefined; if (isChordLength || !closed) params = this.constructChordLengthParameters(fitPoints); @@ -199,7 +203,7 @@ export namespace BSplineCurveOps { * @param options validated as per validateOptions, possibly modified * @return whether fit parameters are valid */ - public static constructFitParameters(options: InterpolationCurve3dOptions): boolean { + public static constructFitParameters(options: InterpolationCurve3dOptions): boolean { if (undefined === options.knots) options.knots = this.constructFitParametersFromPoints(options.fitPoints, options.isChordLenKnots, options.closed); return options.knots?.length === options.fitPoints.length; @@ -211,7 +215,16 @@ export namespace BSplineCurveOps { * @param gamma super-diagonal, length = # fit points * @param index 0-based row index to set */ - private static computeAlphaBetaGamma(alpha: number[], beta: number[], gamma: number[], index: number, deltaIPlus1: number, deltaI: number, deltaIMinus1: number, deltaIMinus2: number) { + private static computeAlphaBetaGamma( + alpha: number[], + beta: number[], + gamma: number[], + index: number, + deltaIPlus1: number, + deltaI: number, + deltaIMinus1: number, + deltaIMinus2: number, + ) { let denomReciprocal = 1.0 / (deltaIMinus2 + deltaIMinus1 + deltaI); alpha[index] = deltaI * deltaI * denomReciprocal; beta[index] = deltaI * (deltaIMinus2 + deltaIMinus1) * denomReciprocal; @@ -236,7 +249,11 @@ export namespace BSplineCurveOps { return false; // identity matrix - alpha[0] = alpha[1] = gamma[0] = gamma[1] = 0.0; + alpha[0] = + alpha[1] = + gamma[0] = + gamma[1] = + 0.0; beta[0] = beta[1] = 1.0; return true; } @@ -249,7 +266,14 @@ export namespace BSplineCurveOps { * @param useNaturalStartTangent whether to bake the natural end condition into the first row * @param useNaturalEndTangent whether to bake the natural end condition into the last row */ - private static setUpSystem3Points(alpha: number[], beta: number[], gamma: number[], options: InterpolationCurve3dOptions, useNaturalStartTangent: boolean, useNaturalEndTangent: boolean): boolean { + private static setUpSystem3Points( + alpha: number[], + beta: number[], + gamma: number[], + options: InterpolationCurve3dOptions, + useNaturalStartTangent: boolean, + useNaturalEndTangent: boolean, + ): boolean { if (undefined === options.knots) return false; if (alpha.length !== 3 || beta.length !== 3 || gamma.length !== 3) @@ -279,7 +303,7 @@ export namespace BSplineCurveOps { sumReciprocal = 1.0 / (deltaIMinus1 + deltaI); sumReciprocal *= sumReciprocal; alpha[1] = deltaI * deltaI * sumReciprocal; - beta[1] = 2.0 * (deltaI * deltaIMinus1) * sumReciprocal; + beta[1] = 2.0 * (deltaI * deltaIMinus1) * sumReciprocal; gamma[1] = deltaIMinus1 * deltaIMinus1 * sumReciprocal; // last row @@ -306,7 +330,14 @@ export namespace BSplineCurveOps { * @param useNaturalStartTangent whether to bake the natural end condition into the first row * @param useNaturalEndTangent whether to bake the natural end condition into the last row */ - private static setUpSystem4PointsOrMore(alpha: number[], beta: number[], gamma: number[], options: InterpolationCurve3dOptions, useNaturalStartTangent: boolean, useNaturalEndTangent: boolean): boolean { + private static setUpSystem4PointsOrMore( + alpha: number[], + beta: number[], + gamma: number[], + options: InterpolationCurve3dOptions, + useNaturalStartTangent: boolean, + useNaturalEndTangent: boolean, + ): boolean { if (undefined === options.knots) return false; if (alpha.length !== beta.length || alpha.length !== gamma.length || alpha.length !== options.knots.length) @@ -404,8 +435,8 @@ export namespace BSplineCurveOps { let useNaturalStartTangent = false; let useNaturalEndTangent = false; if (options.isNaturalTangents && !options.closed) { - useNaturalStartTangent = (undefined === options.startTangent); - useNaturalEndTangent = (undefined === options.endTangent); + useNaturalStartTangent = undefined === options.startTangent; + useNaturalEndTangent = undefined === options.endTangent; } let succeeded = false; @@ -431,7 +462,7 @@ export namespace BSplineCurveOps { if (undefined === options.knots) return false; - const scale = 1.0/3.0; + const scale = 1.0 / 3.0; const numIntervals = options.fitPoints.length - 1; if (1 === numIntervals) { // linear Bezier @@ -455,15 +486,20 @@ export namespace BSplineCurveOps { // numIntervals > 2 if (atStart) { - const alpha = (options.knots[2] - options.knots[1]) / (options.knots[2] - options.knots[0]); - const beta = 1.0 - alpha; - const temp = dataPts[2].plus2Scaled(dataPts[0], -alpha * alpha, dataPts[3], -beta * beta); - Point3d.createAdd2Scaled(temp, 1.0 / (2.0 * alpha), dataPts[0], alpha).interpolate(scale, dataPts[0], dataPts[1]); + const alpha = (options.knots[2] - options.knots[1]) / (options.knots[2] - options.knots[0]); + const beta = 1.0 - alpha; + const temp = dataPts[2].plus2Scaled(dataPts[0], -alpha * alpha, dataPts[3], -beta * beta); + Point3d.createAdd2Scaled(temp, 1.0 / (2.0 * alpha), dataPts[0], alpha).interpolate(scale, dataPts[0], dataPts[1]); } else { - const alpha = (options.knots[numIntervals] - options.knots[numIntervals - 1]) / (options.knots[numIntervals] - options.knots[numIntervals - 2]); - const beta = 1.0 - alpha; - const temp = dataPts[numIntervals].plus2Scaled(dataPts[numIntervals - 1], -alpha * alpha, dataPts[numIntervals + 2], -beta * beta); - Point3d.createAdd2Scaled(temp, 1.0 / (2.0 * beta), dataPts[numIntervals + 2], beta).interpolate(scale, dataPts[numIntervals + 2], dataPts[numIntervals + 1]); + const alpha = (options.knots[numIntervals] - options.knots[numIntervals - 1]) / + (options.knots[numIntervals] - options.knots[numIntervals - 2]); + const beta = 1.0 - alpha; + const temp = dataPts[numIntervals].plus2Scaled(dataPts[numIntervals - 1], -alpha * alpha, dataPts[numIntervals + 2], -beta * beta); + Point3d.createAdd2Scaled(temp, 1.0 / (2.0 * beta), dataPts[numIntervals + 2], beta).interpolate( + scale, + dataPts[numIntervals + 2], + dataPts[numIntervals + 1], + ); } return true; } @@ -572,13 +608,15 @@ export namespace BSplineCurveOps { */ private static setPhysicallyClosedEndCondition(dataPts: Point3d[], options: InterpolationCurve3dOptions): boolean { const numIntervals = options.fitPoints.length - 1; - if (!options.isColinearTangents - || numIntervals <= 2 - || (undefined !== options.startTangent && undefined !== options.endTangent) - || options.isNaturalTangents - || !dataPts[0].isAlmostEqual(dataPts[numIntervals + 2])) { + if ( + !options.isColinearTangents + || numIntervals <= 2 + || (undefined !== options.startTangent && undefined !== options.endTangent) + || options.isNaturalTangents + || !dataPts[0].isAlmostEqual(dataPts[numIntervals + 2]) + ) { return true; - } + } // force parallel start/end tangents, using chord length scale for undefined tangents if (undefined !== options.startTangent) { // start tangent is supplied; compute a parallel end tangent const outwardStartTangent = Vector3d.createStartEnd(dataPts[1], dataPts[0]).normalize(); @@ -586,13 +624,13 @@ export namespace BSplineCurveOps { const endTangentMag = dataPts[numIntervals + 2].distance(dataPts[numIntervals + 1]); dataPts[numIntervals + 2].plusScaled(outwardStartTangent, endTangentMag, dataPts[numIntervals + 1]); } - } else if (undefined !== options.endTangent) { // end tangent is supplied; compute a parallel start tangent + } else if (undefined !== options.endTangent) { // end tangent is supplied; compute a parallel start tangent const outwardEndTangent = Vector3d.createStartEnd(dataPts[numIntervals + 1], dataPts[numIntervals + 2]).normalize(); if (undefined !== outwardEndTangent) { const startTangentMag = dataPts[0].distance(dataPts[1]); dataPts[0].plusScaled(outwardEndTangent, startTangentMag, dataPts[1]); } - } else { // neither tangent is supplied, compute both along same vector + } else { // neither tangent is supplied, compute both along same vector const commonTangent = Vector3d.createStartEnd(dataPts[numIntervals + 1], dataPts[1]).normalize(); if (undefined !== commonTangent) { const startTangentMag = dataPts[0].distance(dataPts[1]); @@ -658,12 +696,12 @@ export namespace BSplineCurveOps { return undefined; const poles: Point3d[] = []; const numIntervals = fitPts.length - 1; - const leftPts = fitPts.slice(0, -1); // last fitPt is ignored + const leftPts = fitPts.slice(0, -1); // last fitPt is ignored let tmp: number | undefined = 0.0; // first forward substitution for (let i = 1; i < numIntervals; ++i) { - if (undefined === (tmp = Geometry.conditionalDivideFraction(- alpha[i], beta[i - 1]))) + if (undefined === (tmp = Geometry.conditionalDivideFraction(-alpha[i], beta[i - 1]))) return undefined; beta[i] += tmp * gamma[i - 1]; alpha[i] = tmp * alpha[i - 1]; @@ -678,8 +716,8 @@ export namespace BSplineCurveOps { for (let i = numIntervals - 2; i >= 0; --i) { if (undefined === (tmp = Geometry.conditionalDivideFraction(1.0, beta[i]))) return undefined; - Point3d.createScale(leftPts[i].plus2Scaled(leftPts[i + 1], - gamma[i], leftPts[numIntervals - 1], - alpha[i]), tmp, leftPts[i]); - gamma[i] = - (gamma[i] * gamma[i + 1] + alpha[i] * gamma[numIntervals - 1]) * tmp; + Point3d.createScale(leftPts[i].plus2Scaled(leftPts[i + 1], -gamma[i], leftPts[numIntervals - 1], -alpha[i]), tmp, leftPts[i]); + gamma[i] = -(gamma[i] * gamma[i + 1] + alpha[i] * gamma[numIntervals - 1]) * tmp; } // second forward substitution @@ -687,7 +725,7 @@ export namespace BSplineCurveOps { return undefined; poles.push(Point3d.createScale(leftPts[0], tmp)); for (let i = 1; i < numIntervals; ++i) { - poles.push(leftPts[i].plusScaled(poles[0], - gamma[i])); + poles.push(leftPts[i].plusScaled(poles[0], -gamma[i])); } return poles; } @@ -701,7 +739,7 @@ export namespace BSplineCurveOps { // remove relevant exterior knots so knots and fit points align *before* we start compressing fit points. options.knots = this.convertCubicKnotVectorToFitParams(options.knots, options.fitPoints.length, true); - // compress out duplicate fit points (and their corresponding knots) + // compress out duplicate fit points (and their corresponding knots) if (!this.removeDuplicateFitPoints(options)) return false; @@ -723,8 +761,10 @@ export namespace BSplineCurveOps { if (options.closed) { if (!hasClosurePoint) { options.fitPoints.push(options.fitPoints[0].clone()); - if (undefined !== options.knots) { // best guess: uniform knots - options.knots.push(options.knots[options.knots.length - 1] + (options.knots[options.knots.length - 1] - options.knots[0]) / (options.knots.length - 1)); + if (undefined !== options.knots) { // best guess: uniform knots + options.knots.push( + options.knots[options.knots.length - 1] + (options.knots[options.knots.length - 1] - options.knots[0]) / (options.knots.length - 1), + ); } } if (options.fitPoints.length <= 4) @@ -755,24 +795,24 @@ export namespace BSplineCurveOps { * @param knots cubic knot vector, unmodified * @param numFitPoints number of fit points * @return fit parameters, or undefined if unexpected input - **/ + */ public static convertCubicKnotVectorToFitParams(knots: number[] | undefined, numFitPoints: number, normalize?: boolean): number[] | undefined { let params = knots?.slice(); if (undefined !== params) { const numExtraKnots = params.length - numFitPoints; switch (numExtraKnots) { - case 0: { // ASSUME caller passed in interior knots + case 0: { // ASSUME caller passed in interior knots break; } - case 4: // modern full cubic knots - case 6: { // legacy full cubic knots + case 4: // modern full cubic knots + case 6: { // legacy full cubic knots for (let i = 0; i < numExtraKnots / 2; ++i) { params.pop(); params.shift(); } break; } - default: { // other knot configurations are unusable + default: { // other knot configurations are unusable params = undefined; break; } @@ -786,7 +826,7 @@ export namespace BSplineCurveOps { /** Return fit parameters augmented to a full cubic knot vector. * @param params fit parameters, unmodified * @param legacy whether to create a legacy (DGN) full knot vector, or modern vector with two less knots - **/ + */ public static convertFitParamsToCubicKnotVector(params: number[] | undefined, closed?: boolean, legacy?: boolean): number[] | undefined { const knots = params?.slice(); if (undefined !== knots) { @@ -794,8 +834,8 @@ export namespace BSplineCurveOps { if (closed) { const iTail = knots.length - 2; for (let iHead = 2; iHead <= numExtraKnots; iHead += 2) { - knots.unshift(knots[iTail] - 1.0); // index is constant - knots.push(1.0 + knots[iHead]); // index increments by two + knots.unshift(knots[iTail] - 1.0); // index is constant + knots.push(1.0 + knots[iHead]); // index increments by two } } else { for (let i = 0; i < numExtraKnots / 2; ++i) { @@ -847,9 +887,9 @@ export namespace BSplineCurveOps { matrix[iMatrixRead++] = alpha[iRow]; matrix[iMatrixRead++] = beta[iRow]; matrix[iMatrixRead++] = gamma[iRow]; - rhs[iRhsRead++] = dataPts[iRow+1].x; - rhs[iRhsRead++] = dataPts[iRow+1].y; - rhs[iRhsRead++] = dataPts[iRow+1].z; + rhs[iRhsRead++] = dataPts[iRow + 1].x; + rhs[iRhsRead++] = dataPts[iRow + 1].y; + rhs[iRhsRead++] = dataPts[iRow + 1].z; } const solution = BandedSystem.solveBandedSystemMultipleRHS(numRow, 3, matrix, 3, rhs); @@ -862,7 +902,7 @@ export namespace BSplineCurveOps { poles[iWrite++] = options.fitPoints[0].x; poles[iWrite++] = options.fitPoints[0].y; poles[iWrite++] = options.fitPoints[0].z; - for (let iRead = 0; iRead < solution.length; ) { + for (let iRead = 0; iRead < solution.length;) { poles[iWrite++] = solution[iRead++]; } poles[iWrite++] = options.fitPoints[options.fitPoints.length - 1].x; @@ -871,7 +911,7 @@ export namespace BSplineCurveOps { } else { // closed if (undefined !== (poles = this.solveNearTridiagonal(options.fitPoints, alpha, beta, gamma))) { if (poles.length > 2) { - poles.unshift(poles.pop()!); // shift poles right to line up with the knots + poles.unshift(poles.pop()!); // shift poles right to line up with the knots for (let i = 0; i < options.order - 1; ++i) poles.push(poles[i].clone()); // periodically extend (the modern way) } diff --git a/core/geometry/src/bspline/BSplineSurface.ts b/core/geometry/src/bspline/BSplineSurface.ts index 99ee627022ff..01c4513d1723 100644 --- a/core/geometry/src/bspline/BSplineSurface.ts +++ b/core/geometry/src/bspline/BSplineSurface.ts @@ -32,7 +32,7 @@ export enum UVSelect { */ VDirection = 1, /** index of v direction */ - vDirection = 1, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values + vDirection = 1, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values } /** * Enumeration of how weights are carried @@ -49,12 +49,12 @@ export enum WeightStyle { /** * * Data is weighted. * * The point with normalized coordinate `[x,y,z]` and weight `w` is stored as `[x*w,y*w,z*w,w]` - * */ + */ WeightsAlreadyAppliedToCoordinates = 1, /** * * Data is weighted. * * The point with normalized coordinate `[x,y,z]` and weight `w` is stored as `[x,y,z,w]` - * */ + */ WeightsSeparateFromCoordinates = 2, } /** @@ -71,7 +71,7 @@ export interface PackedPointGrid { points: number[][][]; /** * Description of how weights are present in the coordinate data. - */ + */ weightStyle?: WeightStyle; /** * number of cartesian dimensions, e.g. 2 or 3. @@ -146,11 +146,11 @@ export interface BSplineSurface3dQuery { poleStepUV(select: UVSelect): number; /** - * Return control points json arrays. - * * Each row of points is an an array. - * * Within the array for each row, each point is an array [x,y,z] or [x,y,z,w]. - * * The PackedPointGrid indicates if weights are present. - */ + * Return control points json arrays. + * * Each row of points is an an array. + * * Within the array for each row, each point is an array [x,y,z] or [x,y,z,w]. + * * The PackedPointGrid indicates if weights are present. + */ getPointGridJSON(): PackedPointGrid; } /** Bspline knots and poles for 2d-to-Nd. @@ -172,17 +172,29 @@ export abstract class BSpline2dNd extends GeometryQuery { public poleDimension: number; private _numPoles: number[]; /** Return the degree (one less than order) for the `select` direction (0 or 1) */ - public degreeUV(select: UVSelect): number { return this.knots[select].degree; } + public degreeUV(select: UVSelect): number { + return this.knots[select].degree; + } /** Return the order (one more than degree) for the `select` direction (0 or 1) */ - public orderUV(select: UVSelect): number { return this.knots[select].degree + 1; } + public orderUV(select: UVSelect): number { + return this.knots[select].degree + 1; + } /** Return the number of spans (INCLUDING NULL SPANS) for the `select` direction (0 or 1) */ - public numSpanUV(select: UVSelect): number { return this._numPoles[select] - this.knots[select].degree; } + public numSpanUV(select: UVSelect): number { + return this._numPoles[select] - this.knots[select].degree; + } /** Return the total number of poles (product of x and y pole counts) */ - public numPolesTotal(): number { return this.coffs.length / this.poleDimension; } + public numPolesTotal(): number { + return this.coffs.length / this.poleDimension; + } /** Return the number of poles for the `select` direction (0 or 1) */ - public numPolesUV(select: UVSelect): number { return this._numPoles[select]; } + public numPolesUV(select: UVSelect): number { + return this._numPoles[select]; + } /** Return the step between adjacent poles for the `select` direction (0 or 1) */ - public poleStepUV(select: UVSelect): number { return select === 0 ? 1 : this._numPoles[0]; } + public poleStepUV(select: UVSelect): number { + return select === 0 ? 1 : this._numPoles[0]; + } /** Confirm that order and pole counts agree for both u and v directions */ public static validOrderAndPoleCounts(orderU: number, numPolesU: number, orderV: number, numPolesV: number, numUV: number): boolean { if (orderU < 2 || numPolesU < orderU) @@ -221,7 +233,9 @@ export abstract class BSpline2dNd extends GeometryQuery { * Return 0 for 0 input, 1 for any nonzero input. * @param value numeric value to convert to strict 0 or 1. */ - public numberToUVSelect(value: number): UVSelect { return value === 0 ? 0 : 1; } + public numberToUVSelect(value: number): UVSelect { + return value === 0 ? 0 : 1; + } /** extend a range, treating each block as simple XYZ */ public extendRangeXYZ(rangeToExtend: Range3d, transform?: Transform) { const buffer = this.coffs; @@ -248,10 +262,7 @@ export abstract class BSpline2dNd extends GeometryQuery { w = buffer[i0 + 3]; if (w !== 0.0) { divW = 1.0 / w; - rangeToExtend.extendTransformedXYZ(transform, - buffer[i0] * divW, - buffer[i0 + 1] * divW, - buffer[i0 + 2] * divW); + rangeToExtend.extendTransformedXYZ(transform, buffer[i0] * divW, buffer[i0 + 1] * divW, buffer[i0 + 2] * divW); } } } else { @@ -262,7 +273,8 @@ export abstract class BSpline2dNd extends GeometryQuery { rangeToExtend.extendXYZ( buffer[i0] * divW, buffer[i0 + 1] * divW, - buffer[i0 + 2] * divW); + buffer[i0 + 2] * divW, + ); } } } @@ -274,7 +286,11 @@ export abstract class BSpline2dNd extends GeometryQuery { * @param _fractionV v parameter * @param _result optional result. */ - public abstract fractionToPointAndDerivatives(_fractionU: number, _fractionV: number, _result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors | undefined; + public abstract fractionToPointAndDerivatives( + _fractionU: number, + _fractionV: number, + _result?: Plane3dByOriginAndVectors, + ): Plane3dByOriginAndVectors | undefined; /** * evaluate the surface at u and v fractions. Return a (squared, right handed) coordinate frame at that point on the surface. * @param fractionU u parameter @@ -285,8 +301,7 @@ export abstract class BSpline2dNd extends GeometryQuery { const skewVectors = this.fractionToPointAndDerivatives(fractionU, fractionV); if (!skewVectors) return undefined; - const axes = Matrix3d.createColumnsInAxisOrder(AxisOrder.XYZ, - skewVectors.vectorU, skewVectors.vectorV, undefined); + const axes = Matrix3d.createColumnsInAxisOrder(AxisOrder.XYZ, skewVectors.vectorU, skewVectors.vectorV, undefined); const axes1 = Matrix3d.createRigidFromMatrix3d(axes, AxisOrder.XYZ, axes); if (axes1) result = Transform.createOriginAndMatrix(skewVectors.origin, axes1, result); @@ -301,7 +316,7 @@ export abstract class BSpline2dNd extends GeometryQuery { protected _poleBuffer: Float64Array; // one set of target values. ALLOCATED BY CTOR FOR FREQUENT REUSE /** array of 2 scratch array, each sized for one pole * * used in derivative evaluations, with respective u and v derivatives in the respective arrays. - */ + */ protected _poleBuffer1UV: Float64Array[]; // one set of target values. ALLOCATED BY CTOR FOR FREQUENT REUSE /** @@ -320,7 +335,6 @@ export abstract class BSpline2dNd extends GeometryQuery { this._numPoles = [numPolesU, numPolesV]; this._poleBuffer = new Float64Array(poleLength); this._poleBuffer1UV = [new Float64Array(poleLength), new Float64Array(poleLength)]; - } /** * Map a position, specified as (uv direction, bezier span, fraction within the bezier), to an overall knot value. @@ -460,9 +474,7 @@ export abstract class BSpline2dNd extends GeometryQuery { } else { // swap full rows .. const numPerRow = m * numU; - for (let i0 = 0, i1 = (numV - 1) * numPerRow; - i0 < i1; - i0 += numPerRow, i1 -= numPerRow) { + for (let i0 = 0, i1 = (numV - 1) * numPerRow; i0 < i1; i0 += numPerRow, i1 -= numPerRow) { this.swapBlocks(i0, i1, numPerRow); } } @@ -490,7 +502,14 @@ export abstract class BSpline2dNd extends GeometryQuery { * @param select 0 to test first/last columns of points; 1 to test first/last rows of points * @returns true if coordinates matched */ - public static isWrappedGrid(data: Float64Array, numRows: number, numColumns: number, dimension: number, blockLength: number, select: UVSelect): boolean { + public static isWrappedGrid( + data: Float64Array, + numRows: number, + numColumns: number, + dimension: number, + blockLength: number, + select: UVSelect, + ): boolean { const rowToRowStep = numColumns * dimension; if (UVSelect.uDirection === select) { // Test the contiguous block at the start/end of each row @@ -523,9 +542,23 @@ export abstract class BSpline2dNd extends GeometryQuery { if (mode === undefined) mode = this.knots[select].wrappable; if (mode === BSplineWrapMode.OpenByAddingControlPoints) // the last degree poles equal the first degree poles - return BSpline2dNd.isWrappedGrid(this.coffs, this.numPolesUV(UVSelect.vDirection), this.numPolesUV(UVSelect.uDirection), this.poleDimension, this.degreeUV(select), select); + return BSpline2dNd.isWrappedGrid( + this.coffs, + this.numPolesUV(UVSelect.vDirection), + this.numPolesUV(UVSelect.uDirection), + this.poleDimension, + this.degreeUV(select), + select, + ); if (mode === BSplineWrapMode.OpenByRemovingKnots) // the last pole equals the first pole - return BSpline2dNd.isWrappedGrid(this.coffs, this.numPolesUV(UVSelect.vDirection), this.numPolesUV(UVSelect.uDirection), this.poleDimension, 1, select); + return BSpline2dNd.isWrappedGrid( + this.coffs, + this.numPolesUV(UVSelect.vDirection), + this.numPolesUV(UVSelect.uDirection), + this.poleDimension, + 1, + select, + ); return false; } /** @@ -564,9 +597,14 @@ export abstract class BSpline2dNd extends GeometryQuery { */ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQuery, UVSurface { /** Test if `other` is an instance of `BSplineSurface3d */ - public isSameGeometryClass(other: any): boolean { return other instanceof BSplineSurface3d; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BSplineSurface3d; + } /** Apply the transform to the poles */ - public tryTransformInPlace(transform: Transform): boolean { Point3dArray.multiplyInPlace(transform, this.coffs); return true; } + public tryTransformInPlace(transform: Transform): boolean { + Point3dArray.multiplyInPlace(transform, this.coffs); + return true; + } /** Return a pole by u and v indices */ public getPole(i: number, j: number, result?: Point3d): Point3d | undefined { return this.getPoint3dPole(i, j, result); @@ -601,12 +639,16 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue } /** Return a simple array of the control points coordinates */ - public copyPointsFloat64Array(): Float64Array { return this.coffs.slice(); } + public copyPointsFloat64Array(): Float64Array { + return this.coffs.slice(); + } /** * return a simple array form of the knots. optionally replicate the first and last * in classic over-clamped manner */ - public copyKnots(select: UVSelect, includeExtraEndKnot: boolean): number[] { return this.knots[select].copyKnots(includeExtraEndKnot); } + public copyKnots(select: UVSelect, includeExtraEndKnot: boolean): number[] { + return this.knots[select].copyKnots(includeExtraEndKnot); + } /** * Create a bspline surface. @@ -627,13 +669,15 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue * @param orderV order for the V direction polynomial (`order` is one more than the `degree`. "cubic" polynomial is order 4.) * @param knotArrayV knots for the V direction. See note above about knot counts. */ - public static create(controlPointArray: Point3d[] | Float64Array, + public static create( + controlPointArray: Point3d[] | Float64Array, numPolesU: number, orderU: number, knotArrayU: number[] | Float64Array | undefined, numPolesV: number, orderV: number, - knotArrayV: number[] | Float64Array | undefined): BSplineSurface3d | undefined { + knotArrayV: number[] | Float64Array | undefined, + ): BSplineSurface3d | undefined { let numPoles = controlPointArray.length; if (controlPointArray instanceof Float64Array) numPoles /= 3; @@ -642,8 +686,8 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue // shift knots-of-interest limits for over-clamped case ... const numKnotsU = knotArrayU ? knotArrayU.length : numPolesU + orderU - 2; const numKnotsV = knotArrayV ? knotArrayV.length : numPolesV + orderV - 2; - const skipFirstAndLastU = (numPolesU + orderU === numKnotsU); - const skipFirstAndLastV = (numPolesV + orderV === numKnotsV); + const skipFirstAndLastU = numPolesU + orderU === numKnotsU; + const skipFirstAndLastV = numPolesV + orderV === numKnotsV; const knotsU = knotArrayU ? KnotVector.create(knotArrayU, orderU - 1, skipFirstAndLastU) : @@ -683,11 +727,13 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue * @param orderV order for the V direction polynomial (`order` is one more than the `degree`. "cubic" polynomial is order 4.) * @param knotArrayV knots for the V direction. See note above about knot counts. */ - public static createGrid(points: number[][][], + public static createGrid( + points: number[][][], orderU: number, knotArrayU: number[] | Float64Array | undefined, orderV: number, - knotArrayV: number[] | Float64Array | undefined): BSplineSurface3d | undefined { + knotArrayV: number[] | Float64Array | undefined, + ): BSplineSurface3d | undefined { const numPolesV = points.length; const numPolesU = points[0].length; const numPoles = numPolesU * numPolesV; @@ -699,8 +745,8 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue // shift knots-of-interest limits for overclamped case ... const numKnotsU = knotArrayU ? knotArrayU.length : numPolesU + orderU - 2; const numKnotsV = knotArrayV ? knotArrayV.length : numPolesV + orderV - 2; - const skipFirstAndLastU = (numPolesU + orderU === numKnotsU); - const skipFirstAndLastV = (numPolesV + orderV === numKnotsV); + const skipFirstAndLastU = numPolesU + orderU === numKnotsU; + const skipFirstAndLastV = numPolesV + orderV === numKnotsV; const knotsU = knotArrayU ? KnotVector.create(knotArrayU, orderU - 1, skipFirstAndLastU) : @@ -743,7 +789,7 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue /** Evaluate at a position given by u and v coordinates in knot space. * @param u u value, in knot range. * @param v v value in knot range. - * @returns Return the xyz coordinates on the surface. + * @returns Return the xyz coordinates on the surface. */ public knotToPoint(u: number, v: number): Point3d { this.evaluateBuffersAtKnot(u, v); @@ -753,11 +799,15 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue public knotToPointAndDerivatives(u: number, v: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { this.evaluateBuffersAtKnot(u, v, 1); return Plane3dByOriginAndVectors.createOriginAndVectorsArrays( - this._poleBuffer, this._poleBuffer1UV[0], this._poleBuffer1UV[1], result); + this._poleBuffer, + this._poleBuffer1UV[0], + this._poleBuffer1UV[1], + result, + ); } /** Evaluate at a position given by fractional coordinate in each direction. - * @param fractionU u coordinate, as a fraction of the knot range. - * @param fractionV v coordinate, as a fraction of the knot range. + * @param fractionU u coordinate, as a fraction of the knot range. + * @param fractionV v coordinate, as a fraction of the knot range. * @returns Return the xyz coordinates on the surface. */ public fractionToPoint(fractionU: number, fractionV: number): Point3d { @@ -810,7 +860,6 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue public extendRange(rangeToExtend: Range3d, transform?: Transform): void { this.extendRangeXYZ(rangeToExtend, transform); } - } /** BSpline Surface in xyzw homogeneous space @@ -818,10 +867,13 @@ export class BSplineSurface3d extends BSpline2dNd implements BSplineSurface3dQue */ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQuery, UVSurface { /** Test if `other` is an instance of `BSplineSurface3dH */ - public isSameGeometryClass(other: any): boolean { return other instanceof BSplineSurface3dH; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BSplineSurface3dH; + } /** Apply the transform to the poles */ public tryTransformInPlace(transform: Transform): boolean { - Point4dArray.multiplyInPlace(transform, this.coffs); return true; + Point4dArray.multiplyInPlace(transform, this.coffs); + return true; } /** Return a pole by u and v indices */ public getPole(i: number, j: number, result?: Point3d): Point3d | undefined { @@ -832,7 +884,9 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu super(numPolesU, numPolesV, 4, knotsU, knotsV, coffs); } /** Unpack the control points to a Point4d array of form [wx,wy,wz,w]. */ - public copyPoints4d(): Point4d[] { return Point4dArray.unpackToPoint4dArray(this.coffs); } + public copyPoints4d(): Point4d[] { + return Point4dArray.unpackToPoint4dArray(this.coffs); + } /** * Unpack the control points to a Point3d array and an array of weights. @@ -840,8 +894,11 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu * @param weights output weights * @param formatter optional xyz formatter. By default, returns a Point3d of form [wx,wy,wz]. */ - public copyPointsAndWeights(points: Point3d[], weights: number[], - formatter: (x: number, y: number, z: number) => any = (x, y, z) => Point3d.create(x, y, z)) { + public copyPointsAndWeights( + points: Point3d[], + weights: number[], + formatter: (x: number, y: number, z: number) => any = (x, y, z) => Point3d.create(x, y, z), + ) { Point4dArray.unpackFloat64ArrayToPointsAndWeights(this.coffs, points, weights, formatter); } /** @@ -863,7 +920,6 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu result[j++] = this.coffs[ix]; result[j++] = this.coffs[ix + 1]; result[j++] = this.coffs[ix + 2]; - } } return result; @@ -884,7 +940,9 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu * return a simple array form of the knots. optionally replicate the first and last * in classic over-clamped manner */ - public copyKnots(select: UVSelect, includeExtraEndKnot: boolean): number[] { return this.knots[select].copyKnots(includeExtraEndKnot); } + public copyKnots(select: UVSelect, includeExtraEndKnot: boolean): number[] { + return this.knots[select].copyKnots(includeExtraEndKnot); + } /** * Create a weighted bspline surface, with control points and weights each organized as flattened arrays continuing from one U row to the next. @@ -912,15 +970,16 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu knotArrayU: number[] | Float64Array | undefined, numPolesV: number, orderV: number, - knotArrayV: number[] | Float64Array | undefined): BSplineSurface3dH | undefined { + knotArrayV: number[] | Float64Array | undefined, + ): BSplineSurface3dH | undefined { const numPoles = numPolesU * numPolesV; if (!this.validOrderAndPoleCounts(orderU, numPolesU, orderV, numPolesV, numPoles)) return undefined; const numKnotsU = knotArrayU ? knotArrayU.length : numPolesU + orderU - 2; const numKnotsV = knotArrayV ? knotArrayV.length : numPolesV + orderV - 2; - const skipFirstAndLastU = (numPolesU + orderU === numKnotsU); - const skipFirstAndLastV = (numPolesV + orderV === numKnotsV); + const skipFirstAndLastU = numPolesU + orderU === numKnotsU; + const skipFirstAndLastV = numPolesV + orderV === numKnotsV; const knotsU = knotArrayU ? KnotVector.create(knotArrayU, orderU - 1, skipFirstAndLastU) : @@ -929,7 +988,7 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu KnotVector.create(knotArrayV, orderV - 1, skipFirstAndLastV) : KnotVector.createUniformClamped(numPolesV, orderV - 1, 0.0, 1.0); if (undefined === weightArray) - weightArray = Array(numPoles).fill(1.0); // unit weights + weightArray = Array(numPoles).fill(1.0); // unit weights const coffs = Point4dArray.packPointsAndWeightsToFloat64Array(controlPointArray, weightArray); if (coffs === undefined || coffs.length !== 4 * numPolesU * numPolesV) return undefined; @@ -960,7 +1019,8 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu orderU: number, knotArrayU: number[] | Float64Array | undefined, orderV: number, - knotArrayV: number[] | Float64Array | undefined): BSplineSurface3dH | undefined { + knotArrayV: number[] | Float64Array | undefined, + ): BSplineSurface3dH | undefined { const numPolesV = xyzwGrid.length; const numPolesU = xyzwGrid[0].length; const numPoles = numPolesU * numPolesV; @@ -972,10 +1032,10 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu // validate knot counts const numKnotsU = knotArrayU ? knotArrayU.length : numPolesU + orderU - 2; const numKnotsV = knotArrayV ? knotArrayV.length : numPolesV + orderV - 2; - const skipFirstAndLastU = (numPolesU + orderU === numKnotsU); // classic over-clamped input knots + const skipFirstAndLastU = numPolesU + orderU === numKnotsU; // classic over-clamped input knots if (!skipFirstAndLastU && numPolesU + orderU !== numKnotsU + 2) // modern knots return undefined; - const skipFirstAndLastV = (numPolesV + orderV === numKnotsV); // classic + const skipFirstAndLastV = numPolesV + orderV === numKnotsV; // classic if (!skipFirstAndLastV && numPolesV + orderV !== numKnotsV + 2) // modern return undefined; @@ -1033,8 +1093,7 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu public clone(): BSplineSurface3dH { const knotVector1U = this.knots[0].clone(); const knotVector1V = this.knots[1].clone(); - const surface1 = new BSplineSurface3dH(this.numPolesUV(0), this.numPolesUV(1), knotVector1U, knotVector1V, - this.coffs.slice()); + const surface1 = new BSplineSurface3dH(this.numPolesUV(0), this.numPolesUV(1), knotVector1U, knotVector1V, this.coffs.slice()); surface1.coffs = this.coffs.slice(); return surface1; } @@ -1045,10 +1104,10 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu return surface1; } /** - * Return control points json arrays. - * * Each row of points is an an array. - * * Within the array for each row, each point is an array [wx,wy,wz,w]. - */ + * Return control points json arrays. + * * Each row of points is an an array. + * * Within the array for each row, each point is an array [wx,wy,wz,w]. + */ public getPointGridJSON(): PackedPointGrid { const result = { points: Point3dArray.unpackNumbersToNestedArraysIJK(this.coffs, 4, this.numPolesUV(0)), @@ -1088,12 +1147,12 @@ export class BSplineSurface3dH extends BSpline2dNd implements BSplineSurface3dQu return point4d.realPointDefault000(result); } /** - * * evaluate the surface and return the cartesian (weight = 1) point. - * * if the surface XYZW point has weight0, returns point3d at 000. - * @param knotU u direction knot - * @param knotV v direction knot - * @param result optional result - */ + * * evaluate the surface and return the cartesian (weight = 1) point. + * * if the surface XYZW point has weight0, returns point3d at 000. + * @param knotU u direction knot + * @param knotV v direction knot + * @param result optional result + */ public knotToPoint(knotU: number, knotV: number, result?: Point3d): Point3d { const point4d = this.knotToPoint4d(knotU, knotV); return point4d.realPointDefault000(result); diff --git a/core/geometry/src/bspline/Bezier1dNd.ts b/core/geometry/src/bspline/Bezier1dNd.ts index 220303b6ea51..585c80e60240 100644 --- a/core/geometry/src/bspline/Bezier1dNd.ts +++ b/core/geometry/src/bspline/Bezier1dNd.ts @@ -47,9 +47,13 @@ export class Bezier1dNd { return result; } /** Return the bezier order */ - public get order() { return this._order; } + public get order() { + return this._order; + } /** return the packed data array. This is a REFERENCE to the array. */ - public get packedData() { return this._packedData; } + public get packedData() { + return this._packedData; + } /** Create a Bezier1dNd, using the structure of `data[0]` to determine the bezier order. */ public static create(data: Point2d[] | Point3d[] | Point4d[]): Bezier1dNd | undefined { if (data.length < 1) @@ -199,7 +203,7 @@ export class Bezier1dNd { let i0 = poleIndexA * this._blockSize; let i1 = poleIndexB * this._blockSize; const data = this._packedData; - for (let i = 0; i < this._blockSize; i++ , i0++ , i1++) { + for (let i = 0; i < this._blockSize; i++, i0++, i1++) { data[i0] += fraction * (data[i1] - data[i0]); } } @@ -228,7 +232,7 @@ export class Bezier1dNd { let k0 = kA - numInsert; if (knotArray[k0] < knotA) { let k1 = kB; - for (let i = 0; i < numInsert; i++ , k0++ , k1++) { + for (let i = 0; i < numInsert; i++, k0++, k1++) { const knot0 = knotArray[k0]; const knot1 = knotArray[k1]; const fraction = (knotA - knot0) / (knot1 - knot0); @@ -239,7 +243,7 @@ export class Bezier1dNd { for (let numInsert = degree - 1; numInsert > 0; numInsert--) { let k2 = kB + numInsert; if (knotArray[k2] > knotB) { - for (let i = 0; i < numInsert; i++ , k2--) { + for (let i = 0; i < numInsert; i++, k2--) { const knot2 = knotArray[k2]; // right side of moving window // left side of window ia always the (previously saturated) knotA const fraction = (knotB - knot2) / (knotA - knot2); @@ -273,7 +277,7 @@ export class Bezier1dNd { let k0 = kA - numInsert; if (knotArray[k0] < knotA) { let k1 = kB; - for (let i = 0; i < numInsert; i++ , k0++ , k1++) { + for (let i = 0; i < numInsert; i++, k0++, k1++) { const knot0 = knotArray[k0]; const knot1 = knotArray[k1]; const fraction = (knotA - knot0) / (knot1 - knot0); @@ -285,7 +289,7 @@ export class Bezier1dNd { let k2 = kB + numInsert; let k; if (knotArray[k2] > knotB) { - for (let i = 0; i < numInsert; i++ , k2--) { + for (let i = 0; i < numInsert; i++, k2--) { const knot2 = knotArray[k2]; // right side of moving window // left side of window is always the (previously saturated) knotA const fraction = (knotB - knot2) / (knotA - knot2); @@ -306,7 +310,7 @@ export class Bezier1dNd { return true; if (Geometry.isAlmostEqualNumber(fraction, 0.0)) return false; - const g = 1.0 - fraction; // interpolations will pull towards right indices + const g = 1.0 - fraction; // interpolations will pull towards right indices const order = this.order; for (let level = 1; level < order; level++) { for (let i1 = order - 1; i1 >= level; i1--) { @@ -329,7 +333,7 @@ export class Bezier1dNd { const order = this.order; for (let level = 1; level < order; level++) { for (let i0 = 0; i0 + level < order; i0++) - this.interpolatePoleInPlace(i0, fraction, i0 + 1); // leave updates to left. + this.interpolatePoleInPlace(i0, fraction, i0 + 1); // leave updates to left. } return true; } @@ -360,5 +364,7 @@ export class Bezier1dNd { this.interval = Segment1d.create(a, b, this.interval); } /** map a fraction to the parent space. */ - public fractionToParentFraction(fraction: number): number { return this.interval ? this.interval.fractionToPoint(fraction) : fraction; } + public fractionToParentFraction(fraction: number): number { + return this.interval ? this.interval.fractionToPoint(fraction) : fraction; + } } diff --git a/core/geometry/src/bspline/BezierCurve3d.ts b/core/geometry/src/bspline/BezierCurve3d.ts index f051c5b89802..454e82af7c37 100644 --- a/core/geometry/src/bspline/BezierCurve3d.ts +++ b/core/geometry/src/bspline/BezierCurve3d.ts @@ -29,7 +29,9 @@ import { BezierCurveBase } from "./BezierCurveBase"; */ export class BezierCurve3d extends BezierCurveBase { /** test if `other` is also a BezierCurve3d. */ - public isSameGeometryClass(other: any): boolean { return other instanceof BezierCurve3d; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BezierCurve3d; + } /** apply the transform to the control points. */ public tryTransformInPlace(transform: Transform): boolean { const data = this._workData0; @@ -75,7 +77,6 @@ export class BezierCurve3d extends BezierCurveBase { /** Create a curve with given points. * * If input is `Point2d[]`, the points are promoted with `z=0` and `w=1` * * If input is `Point3d[]`, the points are promoted with w=1` - * */ public static create(data: Point3d[] | Point2d[]): BezierCurve3d | undefined { if (data.length < 1) @@ -122,7 +123,15 @@ export class BezierCurve3d extends BezierCurveBase { public fractionToPointAndDerivative(fraction: number, result?: Ray3d): Ray3d { this._polygon.evaluate(fraction, this._workData0); this._polygon.evaluateDerivative(fraction, this._workData1); - return Ray3d.createXYZUVW(this._workData0[0], this._workData0[1], this._workData0[2], this._workData1[0], this._workData1[1], this._workData1[2], result); + return Ray3d.createXYZUVW( + this._workData0[0], + this._workData0[1], + this._workData0[2], + this._workData1[0], + this._workData1[1], + this._workData1[2], + result, + ); } /** Construct a plane with * * origin at the fractional position along the arc @@ -180,7 +189,7 @@ export class BezierCurve3d extends BezierCurveBase { } else { this.allocateAndZeroBezierWorkData(order - 1, order, 0); const bezier = this._workBezier!; - const componentCoffs = this._workCoffsA!; // to hold transformed copy of x,y,z in turn. + const componentCoffs = this._workCoffsA!; // to hold transformed copy of x,y,z in turn. this.getPolePoint3d(0, this._workPoint0); rangeToExtend.extendTransformedPoint(transform, this._workPoint0); @@ -200,7 +209,6 @@ export class BezierCurve3d extends BezierCurveBase { } } } - } } } diff --git a/core/geometry/src/bspline/BezierCurve3dH.ts b/core/geometry/src/bspline/BezierCurve3dH.ts index 52c008b076c4..fa61800bc84a 100644 --- a/core/geometry/src/bspline/BezierCurve3dH.ts +++ b/core/geometry/src/bspline/BezierCurve3dH.ts @@ -27,7 +27,9 @@ import { BezierCurveBase } from "./BezierCurveBase"; */ export class BezierCurve3dH extends BezierCurveBase { /** test if `other` is also a BezierCurve3dH. */ - public isSameGeometryClass(other: any): boolean { return other instanceof BezierCurve3dH; } + public isSameGeometryClass(other: any): boolean { + return other instanceof BezierCurve3dH; + } /** * Apply (multiply by) an affine transform * @param transform @@ -95,7 +97,6 @@ export class BezierCurve3dH extends BezierCurveBase { /** Create a curve with given points. * * If input is `Point2d[]`, the points are promoted with `z=0` and `w=1` * * If input is `Point3d[]`, the points are promoted with w=1` - * */ public static create(data: Point3d[] | Point4d[] | Point2d[]): BezierCurve3dH | undefined { if (data.length < 1) @@ -221,9 +222,12 @@ export class BezierCurve3dH extends BezierCurveBase { * @param detail pre-allocated detail to record (evolving) closest point. * @returns true if an updated occurred, false if either (a) no perpendicular projections or (b) perpendiculars were not closer. */ - public updateClosestPointByTruePerpendicular(spacePoint: Point3d, detail: CurveLocationDetail, + public updateClosestPointByTruePerpendicular( + spacePoint: Point3d, + detail: CurveLocationDetail, testAt0: boolean = false, - testAt1: boolean = false): boolean { + testAt1: boolean = false, + ): boolean { let numUpdates = 0; let roots: number[] | undefined; if (this.isUnitWeight()) { @@ -234,9 +238,36 @@ export class BezierCurve3dH extends BezierCurveBase { // closestPoint condition is: // (spacePoint - curvePoint) DOT curveTangent = 0; // Each product (x,y,z) of the DOT is the product of two bezier polynomials - BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta(bezier.coffs, this._polygon.packedData, 4, this.order, 1.0, 0, -spacePoint.x, 0); - BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta(bezier.coffs, this._polygon.packedData, 4, this.order, 1.0, 1, -spacePoint.y, 1); - BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta(bezier.coffs, this._polygon.packedData, 4, this.order, 1.0, 2, -spacePoint.z, 2); + BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta( + bezier.coffs, + this._polygon.packedData, + 4, + this.order, + 1.0, + 0, + -spacePoint.x, + 0, + ); + BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta( + bezier.coffs, + this._polygon.packedData, + 4, + this.order, + 1.0, + 1, + -spacePoint.y, + 1, + ); + BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta( + bezier.coffs, + this._polygon.packedData, + 4, + this.order, + 1.0, + 2, + -spacePoint.z, + 2, + ); roots = bezier.roots(0.0, true); } else { // This bezier has weights. @@ -255,10 +286,18 @@ export class BezierCurve3dH extends BezierCurveBase { for (let i = 0; i < 3; i++) { // x representing loop pass: (w * spacePoint.x - curve.x(s)) * (curveDelta.x(s) * curve.w(s) - curve.x(s) * curveDelta.w(s)) // (and p.w is always 1) - for (let k = 0; k < workA.length; k++)workA[k] = 0; - for (let k = 0; k < workB.length; k++)workB[k] = 0; - BezierPolynomialAlgebra.scaledComponentSum(workA, packedData, 4, orderA, 3, spacePoint.at(i), // w * spacePoint.x - i, -1.0); // curve.x(s) * 1.0 + for (let k = 0; k < workA.length; k++) workA[k] = 0; + for (let k = 0; k < workB.length; k++) workB[k] = 0; + BezierPolynomialAlgebra.scaledComponentSum( + workA, + packedData, + 4, + orderA, + 3, + spacePoint.at(i), // w * spacePoint.x + i, + -1.0, + ); // curve.x(s) * 1.0 BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta(workB, packedData, 4, orderA, 1.0, 3, 0.0, i); BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta(workB, packedData, 4, orderA, -1.0, i, 0.0, 3); BezierPolynomialAlgebra.accumulateProduct(bezier.coffs, workA, workB); @@ -273,16 +312,16 @@ export class BezierCurve3dH extends BezierCurveBase { } } if (testAt0) - numUpdates += this.updateDetailAtFraction (detail, 0.0, spacePoint) ? 1 : 0; + numUpdates += this.updateDetailAtFraction(detail, 0.0, spacePoint) ? 1 : 0; if (testAt1) - numUpdates += this.updateDetailAtFraction (detail, 1.0, spacePoint) ? 1 : 0; + numUpdates += this.updateDetailAtFraction(detail, 1.0, spacePoint) ? 1 : 0; return numUpdates > 0; } - private updateDetailAtFraction(detail: CurveLocationDetail, fraction: number, spacePoint: Point3d): boolean{ + private updateDetailAtFraction(detail: CurveLocationDetail, fraction: number, spacePoint: Point3d): boolean { const xyz = this.fractionToPoint(fraction); const a = xyz.distance(spacePoint); - return detail.updateIfCloserCurveFractionPointDistance (this, fraction, xyz, a); - } + return detail.updateIfCloserCurveFractionPointDistance(this, fraction, xyz, a); + } /** Extend `rangeToExtend`, using candidate extrema at * * both end points * * any internal extrema in x,y,z @@ -309,16 +348,24 @@ export class BezierCurve3dH extends BezierCurveBase { bezier.zero(); BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta( bezier.coffs, - data, 4, order, + data, + 4, + order, 1.0, - axisIndex, 0.0, - 3); + axisIndex, + 0.0, + 3, + ); BezierPolynomialAlgebra.accumulateScaledShiftedComponentTimesComponentDelta( bezier.coffs, - data, 4, order, + data, + 4, + order, -1.0, - 3, 0.0, - axisIndex); + 3, + 0.0, + axisIndex, + ); const roots = bezier.roots(0.0, true); if (roots) { for (const r of roots) { @@ -329,8 +376,8 @@ export class BezierCurve3dH extends BezierCurveBase { } } else { this.allocateAndZeroBezierWorkData(order * 2 - 2, order, order); - const componentCoffs = this._workCoffsA!; // to hold transformed copy of x,y,z in turn. - const weightCoffs = this._workCoffsB!; // to hold weights + const componentCoffs = this._workCoffsA!; // to hold transformed copy of x,y,z in turn. + const weightCoffs = this._workCoffsB!; // to hold weights const bezier = this._workBezier!; this.getPolePoint3d(0, this._workPoint0); @@ -338,7 +385,7 @@ export class BezierCurve3dH extends BezierCurveBase { this.getPolePoint3d(order - 1, this._workPoint0); rangeToExtend.extendTransformedPoint(transform, this._workPoint0); - const data = this._polygon.packedData; // Example: + const data = this._polygon.packedData; // Example: // For x component ... // coefficients of (weighted x) are at axisIndex=0 // deweighted polynomial is (x(s)/w(s)) diff --git a/core/geometry/src/bspline/BezierCurveBase.ts b/core/geometry/src/bspline/BezierCurveBase.ts index 6b6b04d517c2..9ee03b09b8d2 100644 --- a/core/geometry/src/bspline/BezierCurveBase.ts +++ b/core/geometry/src/bspline/BezierCurveBase.ts @@ -57,17 +57,19 @@ export abstract class BezierCurveBase extends CurvePrimitive { this._workPoint1 = Point3d.create(); this._workData0 = new Float64Array(blockSize); this._workData1 = new Float64Array(blockSize); - } /** reverse the poles in place */ - public reverseInPlace(): void { this._polygon.reverseInPlace(); } + public reverseInPlace(): void { + this._polygon.reverseInPlace(); + } /** saturate the pole in place, using knot intervals from `spanIndex` of the `knotVector` */ public saturateInPlace(knotVector: KnotVector, spanIndex: number): boolean { const boolStat = this._polygon.saturateInPlace(knotVector, spanIndex); if (boolStat) { this.setInterval( knotVector.spanFractionToFraction(spanIndex, 0.0), - knotVector.spanFractionToFraction(spanIndex, 1.0)); + knotVector.spanFractionToFraction(spanIndex, 1.0), + ); } return boolStat; } @@ -76,9 +78,13 @@ export abstract class BezierCurveBase extends CurvePrimitive { return this._polygon.order - 1; } /** (property accessor) Return the polynomial order */ - public get order(): number { return this._polygon.order; } + public get order(): number { + return this._polygon.order; + } /** (property accessor) Return the number of poles (aka control points) */ - public get numPoles(): number { return this._polygon.order; } + public get numPoles(): number { + return this._polygon.order; + } /** Get pole `i` as a Point3d. * * For 3d curve, this is simple a pole access, and only fails (return `undefined`) for invalid index * * For 4d curve, this deweights the homogeneous pole and can fail due to 0 weight. @@ -91,11 +97,15 @@ export abstract class BezierCurveBase extends CurvePrimitive { */ public abstract getPolePoint4d(i: number, point?: Point4d): Point4d | undefined; /** Set mapping to parent curve (e.g. if this bezier is a span extracted from a bspline, this is the knot interval of the span) */ - public setInterval(a: number, b: number) { this._polygon.setInterval(a, b); } + public setInterval(a: number, b: number) { + this._polygon.setInterval(a, b); + } /** map `fraction` from this Bezier curves inherent 0..1 range to the (a,b) range of parent * * ( The parent range should have been previously defined with `setInterval`) */ - public fractionToParentFraction(fraction: number): number { return this._polygon.fractionToParentFraction(fraction); } + public fractionToParentFraction(fraction: number): number { + return this._polygon.fractionToParentFraction(fraction); + } /** append stroke points to a linestring, based on `strokeCount` and `fractionToPoint` from derived class*/ public emitStrokes(dest: LineString3d, options?: StrokeOptions): void { @@ -113,17 +123,19 @@ export abstract class BezierCurveBase extends CurvePrimitive { handler.announceIntervalForUniformStepStrokes(this, numPerSpan, 0.0, 1.0); } /** Return a simple array of arrays with the control points as `[[x,y,z],[x,y,z],..]` */ - public copyPolesAsJsonArray(): any[] { return this._polygon.unpackToJsonArrays(); } + public copyPolesAsJsonArray(): any[] { + return this._polygon.unpackToJsonArrays(); + } /** return true if all poles are on a plane. */ public isInPlane(plane: Plane3dByOriginAndUnitNormal): boolean { let point: Point3d | undefined = this._workPoint0; - for (let i = 0; ; i++) { + for (let i = 0;; i++) { point = this.getPolePoint3d(i, point); if (!point) return true; if (!plane.isPointInPlane(point)) - break; // which gets to return false, which is otherwise unreachable . . . + break; // which gets to return false, which is otherwise unreachable . . . } return false; } @@ -141,16 +153,18 @@ export abstract class BezierCurveBase extends CurvePrimitive { } /** Return the start point. (first control point) */ public override startPoint(): Point3d { - const result = this.getPolePoint3d(0)!; // ASSUME non-trivial pole set -- if null comes back, it bubbles out + const result = this.getPolePoint3d(0)!; // ASSUME non-trivial pole set -- if null comes back, it bubbles out return result; } /** Return the end point. (last control point) */ public override endPoint(): Point3d { - const result = this.getPolePoint3d(this.order - 1)!; // ASSUME non-trivial pole set + const result = this.getPolePoint3d(this.order - 1)!; // ASSUME non-trivial pole set return result; } /** Return the control polygon length as a quick length estimate. */ - public quickLength(): number { return this.polygonLength(); } + public quickLength(): number { + return this.polygonLength(); + } /** Concrete classes must implement extendRange . . . */ public abstract override extendRange(rangeToExtend: Range3d, transform?: Transform): void; /** @@ -199,7 +213,6 @@ export abstract class BezierCurveBase extends CurvePrimitive { * @param options stroke options structure. */ public computeStrokeCountForOptions(options?: StrokeOptions): number { - this.getPolePoint3d(0, this._workPoint0); this.getPolePoint3d(1, this._workPoint1); let numStrokes = 1; @@ -230,15 +243,14 @@ export abstract class BezierCurveBase extends CurvePrimitive { dz0 = dz1; this._workPoint0.setFrom(this._workPoint1); } - const length1 = maxLength * this.degree; // This may be larger than sumLength - const length2 = Math.sqrt(length1 * sumLength); // This is in between - let radians1 = maxRadians * (this.degree - 1); // As if worst case keeps happening. + const length1 = maxLength * this.degree; // This may be larger than sumLength + const length2 = Math.sqrt(length1 * sumLength); // This is in between + let radians1 = maxRadians * (this.degree - 1); // As if worst case keeps happening. if (this.degree < 3) - radians1 *= 3; // so quadratics aren't under-stroked + radians1 *= 3; // so quadratics aren't under-stroked const radians2 = Math.sqrt(radians1 * sumRadians); const minCount = this.degree; // NOTE: this means 1) a small, nontrivial, straight Bezier is over-stroked, and 2) options.minStrokesPerPrimitive is ignored - numStrokes = StrokeOptions.applyAngleTol(options, - StrokeOptions.applyMaxEdgeLength(options, minCount, length2), radians2, 0.1); + numStrokes = StrokeOptions.applyAngleTol(options, StrokeOptions.applyMaxEdgeLength(options, minCount, length2), radians2, 0.1); if (options) { numStrokes = options.applyChordTolToLengthAndRadians(numStrokes, sumLength, radians1); } @@ -273,7 +285,7 @@ export abstract class BezierCurveBase extends CurvePrimitive { * @param fractionA [in] start fraction * @param fractionB [in] end fraction */ - public override clonePartialCurve(fractionA: number, fractionB: number): BezierCurveBase { + public override clonePartialCurve(fractionA: number, fractionB: number): BezierCurveBase { const partialCurve = this.clone(); partialCurve._polygon.subdivideToIntervalInPlace(fractionA, fractionB); return partialCurve; diff --git a/core/geometry/src/bspline/InterpolationCurve3d.ts b/core/geometry/src/bspline/InterpolationCurve3d.ts index b443d56b7ea0..f732d9a3b7b0 100644 --- a/core/geometry/src/bspline/InterpolationCurve3d.ts +++ b/core/geometry/src/bspline/InterpolationCurve3d.ts @@ -6,17 +6,17 @@ * @module Bspline */ -import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; -import { Geometry } from "../Geometry"; -import { Point3dArray } from "../geometry3d/PointHelpers"; -import { ProxyCurve } from "../curve/ProxyCurve"; -import { CurvePrimitive } from "../curve/CurvePrimitive"; import { BSplineCurveOps } from "../bspline/BSplineCurveOps"; -import { BSplineCurve3d } from "./BSplineCurve"; +import { CurvePrimitive } from "../curve/CurvePrimitive"; import { GeometryQuery } from "../curve/GeometryQuery"; -import { Transform } from "../geometry3d/Transform"; +import { ProxyCurve } from "../curve/ProxyCurve"; +import { Geometry } from "../Geometry"; import { GeometryHandler } from "../geometry3d/GeometryHandler"; +import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; +import { Point3dArray } from "../geometry3d/PointHelpers"; +import { Transform } from "../geometry3d/Transform"; import { XYZProps } from "../geometry3d/XYZProps"; +import { BSplineCurve3d } from "./BSplineCurve"; /** * fitPoints and end condition data for [[InterpolationCurve3d]] @@ -75,35 +75,75 @@ export class InterpolationCurve3dOptions { private _knots?: number[]; /** `order` as property */ - public get order(): number { return Geometry.resolveNumber(this._order, 4); } - public set order(val: number) { this._order = val; } + public get order(): number { + return Geometry.resolveNumber(this._order, 4); + } + public set order(val: number) { + this._order = val; + } /** `closed` as property */ - public get closed(): boolean { return Geometry.resolveValue(this._closed, false); } - public set closed(val: boolean) { this._closed = val; } + public get closed(): boolean { + return Geometry.resolveValue(this._closed, false); + } + public set closed(val: boolean) { + this._closed = val; + } /** `isChordLenKnots` as property */ - public get isChordLenKnots(): number { return Geometry.resolveNumber(this._isChordLenKnots, 0); } - public set isChordLenKnots(val: number) { this._isChordLenKnots = val; } + public get isChordLenKnots(): number { + return Geometry.resolveNumber(this._isChordLenKnots, 0); + } + public set isChordLenKnots(val: number) { + this._isChordLenKnots = val; + } /** `isColinearTangents` as property */ - public get isColinearTangents(): number { return Geometry.resolveNumber(this._isColinearTangents, 0); } - public set isColinearTangents(val: number) { this._isColinearTangents = val; } + public get isColinearTangents(): number { + return Geometry.resolveNumber(this._isColinearTangents, 0); + } + public set isColinearTangents(val: number) { + this._isColinearTangents = val; + } /** `isChordLenTangents` as property */ - public get isChordLenTangents(): number { return Geometry.resolveNumber(this._isChordLenTangents, 0); } - public set isChordLenTangents(val: number) { this._isChordLenTangents = val; } + public get isChordLenTangents(): number { + return Geometry.resolveNumber(this._isChordLenTangents, 0); + } + public set isChordLenTangents(val: number) { + this._isChordLenTangents = val; + } /** `isNaturalTangents` as property */ - public get isNaturalTangents(): number { return Geometry.resolveNumber(this._isNaturalTangents, 0); } - public set isNaturalTangents(val: number) { this._isNaturalTangents = val; } + public get isNaturalTangents(): number { + return Geometry.resolveNumber(this._isNaturalTangents, 0); + } + public set isNaturalTangents(val: number) { + this._isNaturalTangents = val; + } /** access POSSIBLY UNDEFINED start tangent. Setter CAPTURES. */ - public get startTangent(): Vector3d | undefined { return this._startTangent; } - public set startTangent(val: Vector3d | undefined) { this._startTangent = val; } + public get startTangent(): Vector3d | undefined { + return this._startTangent; + } + public set startTangent(val: Vector3d | undefined) { + this._startTangent = val; + } /** access POSSIBLY UNDEFINED end tangent. Setter CAPTURES. */ - public get endTangent(): Vector3d | undefined { return this._endTangent; } - public set endTangent(val: Vector3d | undefined) { this._endTangent = val; } + public get endTangent(): Vector3d | undefined { + return this._endTangent; + } + public set endTangent(val: Vector3d | undefined) { + this._endTangent = val; + } /** access POINTER TO fit points. Setter CAPTURES. */ - public get fitPoints(): Point3d[] { return this._fitPoints; } - public set fitPoints(val: Point3d[]) { this._fitPoints = val; } + public get fitPoints(): Point3d[] { + return this._fitPoints; + } + public set fitPoints(val: Point3d[]) { + this._fitPoints = val; + } /** access POSSIBLY UNDEFINED knots array. Setter CAPTURES. */ - public get knots(): number[] | undefined { return this._knots; } - public set knots(val: number[] | undefined) { this._knots = val; } + public get knots(): number[] | undefined { + return this._knots; + } + public set knots(val: number[] | undefined) { + this._knots = val; + } /** One step setup of properties not named in constructor. * * CAPTURE pointers to tangents. @@ -127,7 +167,6 @@ export class InterpolationCurve3dOptions { this._isNaturalTangents = Geometry.resolveToUndefined(isNaturalTangents, 0); this._startTangent = startTangent; this._endTangent = endTangent; - } /** Clone with strongly typed members reduced to simple json, with "undefined" members omitted */ public cloneAsInterpolationCurve3dProps(): InterpolationCurve3dProps { @@ -195,21 +234,23 @@ export class InterpolationCurve3dOptions { if (dataA === undefined && dataB === undefined) return true; if (dataA !== undefined && dataB !== undefined) { - if (Geometry.areEqualAllowUndefined(dataA.order, dataB.order) + if ( + Geometry.areEqualAllowUndefined(dataA.order, dataB.order) && Geometry.areEqualAllowUndefined(dataA.closed, dataB.closed) && Geometry.areEqualAllowUndefined(dataA.isChordLenKnots, dataB.isChordLenKnots) && Geometry.areEqualAllowUndefined(dataA.isColinearTangents, dataB.isColinearTangents) && Geometry.areEqualAllowUndefined(dataA.isNaturalTangents, dataB.isNaturalTangents) && this.areAlmostEqualAllow000AsUndefined(dataA.startTangent, dataB.startTangent) && this.areAlmostEqualAllow000AsUndefined(dataA.endTangent, dataB.endTangent) - && Geometry.almostEqualArrays(dataA.fitPoints, dataB.fitPoints, (a: Point3d, b: Point3d) => a.isAlmostEqual(b))) { + && Geometry.almostEqualArrays(dataA.fitPoints, dataB.fitPoints, (a: Point3d, b: Point3d) => a.isAlmostEqual(b)) + ) { if (Geometry.almostEqualNumberArrays(dataA.knots, dataB.knots, (a: number, b: number) => a === b)) return true; if (dataA.knots === undefined && dataB.knots === undefined) return true; /* alas .. need to allow tricky mismatch of end replication */ let knotsA = dataA.knots, knotsB = dataB.knots; - if (dataA.knots === undefined) // construct undefined knots to compare against defined knots + if (dataA.knots === undefined) // construct undefined knots to compare against defined knots knotsA = BSplineCurveOps.C2CubicFit.constructFitParametersFromPoints(dataA.fitPoints, dataA.isChordLenKnots, dataA.closed); else if (dataB.knots === undefined) knotsB = BSplineCurveOps.C2CubicFit.constructFitParametersFromPoints(dataB.fitPoints, dataB.isChordLenKnots, dataB.closed); @@ -297,7 +338,9 @@ export class InterpolationCurve3d extends ProxyCurve { } /** return the options pointer */ - public get options(): InterpolationCurve3dOptions { return this._options; } + public get options(): InterpolationCurve3dOptions { + return this._options; + } /** * Reverse the curve direction. @@ -335,6 +378,7 @@ export class InterpolationCurve3d extends ProxyCurve { } /** Test if `other` is also an [[InterpolationCurve3d]] */ - public isSameGeometryClass(other: GeometryQuery): boolean { return other instanceof InterpolationCurve3d; } - + public isSameGeometryClass(other: GeometryQuery): boolean { + return other instanceof InterpolationCurve3d; + } } diff --git a/core/geometry/src/bspline/KnotVector.ts b/core/geometry/src/bspline/KnotVector.ts index d04c8157ff5e..828fffe52eca 100644 --- a/core/geometry/src/bspline/KnotVector.ts +++ b/core/geometry/src/bspline/KnotVector.ts @@ -53,20 +53,33 @@ export class KnotVector { /** tolerance for considering two knots to be the same. */ public static readonly knotTolerance = 1.0e-9; /** Return the leftmost knot value (of the active interval, ignoring unclamped leading knots)*/ - public get leftKnot() { return this._knot0; } + public get leftKnot() { + return this._knot0; + } /** Return the rightmost knot value (of the active interval, ignoring unclamped leading knots)*/ - public get rightKnot() { return this._knot1; } + public get rightKnot() { + return this._knot1; + } /** Return the index of the leftmost knot of the active interval */ - public get leftKnotIndex() { return this.degree - 1; } + public get leftKnotIndex() { + return this.degree - 1; + } /** Return the index of the rightmost knot of the active interval */ - public get rightKnotIndex() { return this.knots.length - this.degree; } + public get rightKnotIndex() { + return this.knots.length - this.degree; + } /** Whether this KnotVector was created by converting legacy periodic data during deserialization. The conversion used is specified by BSplineWrapMode, and is reversed at serialization time. */ - public get wrappable() { return this._wrapMode === undefined ? BSplineWrapMode.None : this._wrapMode; } - public set wrappable(value: BSplineWrapMode) { this._wrapMode = value; } + public get wrappable() { + return this._wrapMode === undefined ? BSplineWrapMode.None : this._wrapMode; + } + public set wrappable(value: BSplineWrapMode) { + this._wrapMode = value; + } /** Return the number of bezier spans. Note that this includes zero-length spans if there are repeated knots. */ - public get numSpans() { return this.rightKnotIndex - this.leftKnotIndex; } + public get numSpans() { + return this.rightKnotIndex - this.leftKnotIndex; + } /** - * * * If knots is a number array or Float64Array, the those values become the local knot array. * * If knots is a simple number, the local knot array is allocated to that size but left as zeros. * @param knots @@ -91,7 +104,9 @@ export class KnotVector { } } /** copy degree and knots to a new KnotVector. */ - public clone(): KnotVector { return new KnotVector(this.knots, this.degree, this.wrappable); } + public clone(): KnotVector { + return new KnotVector(this.knots, this.degree, this.wrappable); + } private setupFixedValues() { if (this.degree > 0 && this.knots.length > this.degree) { this._knot0 = this.knots[this.degree - 1]; @@ -99,7 +114,9 @@ export class KnotVector { } } /** Return the total knot distance from beginning to end. */ - public get knotLength01(): number { return this._knot1 - this._knot0; } + public get knotLength01(): number { + return this._knot1 - this._knot0; + } /** * Returns true if all numeric values have wraparound conditions that allow the knots to be closed with specified wrap mode. * @param mode optional test mode. If undefined, use this.wrappable. @@ -159,18 +176,18 @@ export class KnotVector { let m = 0; if (knotIndex >= 0 && knotIndex < this.knots.length) { const knot = this.knots[knotIndex]; - ++m; // count this knot + ++m; // count this knot for (let i = knotIndex - 1; i >= 0; --i) { const k = this.knots[i]; if (Math.abs(k - knot) < KnotVector.knotTolerance) - ++m; // found multiple to left of knot + ++m; // found multiple to left of knot else if (knot > k) break; } for (let i = knotIndex + 1; i < this.knots.length; ++i) { const k = this.knots[i]; if (Math.abs(k - knot) < KnotVector.knotTolerance) - ++m; // found multiple to right of knot + ++m; // found multiple to right of knot else if (knot < k) break; } @@ -205,7 +222,6 @@ export class KnotVector { if (skipFirstAndLast) { for (let i = 1; i + 1 < knots.length; i++) this.knots[i - 1] = knots[i]; - } else { for (let i = 0; i < knots.length; i++) this.knots[i] = knots[i]; @@ -229,11 +245,11 @@ export class KnotVector { public static createUniformClamped(numPoles: number, degree: number, a0: number, a1: number): KnotVector { const knots = new KnotVector(numPoles + degree - 1, degree); let k = 0; - for (let m = 0; m < degree; m++)knots.knots[k++] = a0; + for (let m = 0; m < degree; m++) knots.knots[k++] = a0; const du = 1.0 / (numPoles - degree); for (let i = 1; i + degree < numPoles; i++) knots.knots[k++] = a0 + i * du * (a1 - a0); - for (let m = 0; m < degree; m++)knots.knots[k++] = a1; + for (let m = 0; m < degree; m++) knots.knots[k++] = a1; knots.setupFixedValues(); return knots; } @@ -279,7 +295,9 @@ export class KnotVector { return sum / this.degree; } /** Return an array sized for a set of the basis function values. */ - public createBasisArray(): Float64Array { return new Float64Array(this.degree + 1); } + public createBasisArray(): Float64Array { + return new Float64Array(this.degree + 1); + } /** Convert localFraction within the interval following an indexed knot to a knot value. */ public baseKnotFractionToKnot(knotIndex0: number, localFraction: number): number { const knot0 = this.knots[knotIndex0]; @@ -299,7 +317,7 @@ export class KnotVector { } /** Return fraction of active knot range to knot value. */ public fractionToKnot(fraction: number): number { - fraction = Geometry.clamp(fraction, 0, 1); // B-splines are not extendable + fraction = Geometry.clamp(fraction, 0, 1); // B-splines are not extendable return Geometry.interpolate(this.knots[this.degree - 1], fraction, this.knots[this.knots.length - this.degree]); } /** @@ -356,7 +374,8 @@ export class KnotVector { return false; if (ddf && ddf.length < this.degree + 1) return false; - f[0] = 1.0; df[0] = 0.0; + f[0] = 1.0; + df[0] = 0.0; if (this.degree < 1) return true; // direct compute for linear part ... @@ -367,9 +386,11 @@ export class KnotVector { let ah = 1.0 / (u1 - u0); f[1] = (u - u0) * ah; f[0] = 1.0 - f[1]; - df[0] = -ah; df[1] = ah; - if (ddf) { // first derivative started constant, second derivative started zero. - ddf[0] = 0.0; ddf[1] = 0.0; + df[0] = -ah; + df[1] = ah; + if (ddf) { // first derivative started constant, second derivative started zero. + ddf[0] = 0.0; + ddf[1] = 0.0; } if (this.degree < 2) return true; @@ -402,7 +423,7 @@ export class KnotVector { df[step] = dgCarry + dg0; gCarry = g1; dgCarry = dg1; - if (ddf) { // do the backward reference to df before rewriting df !!! + if (ddf) { // do the backward reference to df before rewriting df !!! const ddg1 = ddf[step] * fraction + dfSave; const ddg0 = ddf[step] * fraction1 - dfSave; ddf[step] = ddgCarry + ddg0; @@ -468,7 +489,7 @@ export class KnotVector { /** Return a simple array form of the knots. Optionally replicate the first and last in classic over-clamped manner. */ public static copyKnots(knots: number[] | Float64Array, degree: number, includeExtraEndKnot?: boolean, wrapMode?: BSplineWrapMode): number[] { - const isExtraEndKnotPeriodic = (includeExtraEndKnot && wrapMode === BSplineWrapMode.OpenByAddingControlPoints); + const isExtraEndKnotPeriodic = includeExtraEndKnot && wrapMode === BSplineWrapMode.OpenByAddingControlPoints; const leftIndex = degree - 1; const rightIndex = knots.length - degree; const a0 = knots[leftIndex]; diff --git a/core/geometry/src/bspline/SurfaceLocationDetail.ts b/core/geometry/src/bspline/SurfaceLocationDetail.ts index 0aea4b56a765..88bccc79537e 100644 --- a/core/geometry/src/bspline/SurfaceLocationDetail.ts +++ b/core/geometry/src/bspline/SurfaceLocationDetail.ts @@ -58,7 +58,6 @@ export class UVSurfaceLocationDetail { detail.point.setFromPoint3d(point); return detail; } - } /** * Carrier for both curve and surface data, e.g. from intersection calculations. diff --git a/core/geometry/src/clipping/AlternatingConvexClipTree.ts b/core/geometry/src/clipping/AlternatingConvexClipTree.ts index 142bb01f340c..1d88f3290ca3 100644 --- a/core/geometry/src/clipping/AlternatingConvexClipTree.ts +++ b/core/geometry/src/clipping/AlternatingConvexClipTree.ts @@ -51,10 +51,10 @@ export class AlternatingCCTreeNode implements PolygonClipper { public points: Point3d[] = []; public planes: ConvexClipPlaneSet = ConvexClipPlaneSet.createEmpty(); public children: AlternatingCCTreeNode[] = []; - public startIdx: number = -1; // Start index into the master array (not the local points array) - public numPoints: number = -1; // Number of points used in the master array + public startIdx: number = -1; // Start index into the master array (not the local points array) + public numPoints: number = -1; // Number of points used in the master array - private constructor() { } + private constructor() {} /** Initialize this node with index data referencing the parent polygon. */ public static createWithIndices(index0: number, numPoints: number, result?: AlternatingCCTreeNode): AlternatingCCTreeNode { @@ -74,7 +74,7 @@ export class AlternatingCCTreeNode implements PolygonClipper { result = result ? result : new AlternatingCCTreeNode(); result.empty(); const builder = AlternatingCCTreeBuilder.createPointsRef(points); - builder.buildHullTree(result); // <-- Currently ALWAYS returns true + builder.buildHullTree(result); // <-- Currently ALWAYS returns true return result; } /** Build the outer convex hull with inlets as first level children. */ @@ -82,7 +82,7 @@ export class AlternatingCCTreeNode implements PolygonClipper { result = result ? result : new AlternatingCCTreeNode(); result.empty(); const builder = AlternatingCCTreeBuilder.createPointsRef(points); - builder.buildHullAndInletsForPolygon(result); // <-- Currently ALWAYS returns true + builder.buildHullAndInletsForPolygon(result); // <-- Currently ALWAYS returns true return result; } private extractLoopsGo(loops: Point3d[][]) { @@ -151,14 +151,18 @@ export class AlternatingCCTreeNode implements PolygonClipper { } /** Append start-end positions for curve intervals classified as inside or outside. */ public appendCurvePrimitiveClipIntervals( - curve: CurvePrimitive, insideIntervals: CurveLocationDetailPair[], outsideIntervals: CurveLocationDetailPair[], + curve: CurvePrimitive, + insideIntervals: CurveLocationDetailPair[], + outsideIntervals: CurveLocationDetailPair[], ): void { const clipper = new AlternatingCCTreeNodeCurveClipper(); clipper.appendSingleClipPrimitive(this, curve, insideIntervals, outsideIntervals); } /** Append start-end positions for curve intervals classified as inside or outside. */ public appendCurveCollectionClipIntervals( - curves: CurveCollection, insideIntervals: CurveLocationDetailPair[], outsideIntervals: CurveLocationDetailPair[], + curves: CurveCollection, + insideIntervals: CurveLocationDetailPair[], + outsideIntervals: CurveLocationDetailPair[], ): void { const clipper = new AlternatingCCTreeNodeCurveClipper(); clipper.appendCurveCollectionClip(this, curves, insideIntervals, outsideIntervals); @@ -197,7 +201,7 @@ export class AlternatingCCTreeNode implements PolygonClipper { arrayCache.dropToCache(shard); } tempAB = carryForwardB; - carryForwardB = carryForwardA; // and that is empty + carryForwardB = carryForwardA; // and that is empty carryForwardA = tempAB; } while (undefined !== (shard = carryForwardA.pop())) { @@ -226,7 +230,7 @@ export class AlternatingCCTreeBuilder { private _points: Point3d[] = []; private _stack: number[] = []; - private constructor() { } + private constructor() {} public static createPointsRef(points: Point3d[], result?: AlternatingCCTreeBuilder): AlternatingCCTreeBuilder { result = result ? result : new AlternatingCCTreeBuilder(); @@ -257,7 +261,7 @@ export class AlternatingCCTreeBuilder { return sign * AlternatingCCTreeBuilder.cross(pointA, pointB, pointC) > 0; } */ - public cyclicStackPoint(cyclicIndex: number): Point3d { // SIGNED index -- but negatives must be in first 10 periods? + public cyclicStackPoint(cyclicIndex: number): Point3d { // SIGNED index -- but negatives must be in first 10 periods? let stackIndex: number; const stack = this._stack; if (cyclicIndex > 0) @@ -327,7 +331,9 @@ export class AlternatingCCTreeBuilder { } } private buildHullTreeGo( - root: AlternatingCCTreeNode, isPositiveArea: boolean, recurseToChildren: boolean = true, + root: AlternatingCCTreeNode, + isPositiveArea: boolean, + recurseToChildren: boolean = true, ): boolean { this.collectHullChain(root.startIdx, root.numPoints, isPositiveArea ? 1.0 : -1.0); root.points.length = 0; @@ -343,7 +349,10 @@ export class AlternatingCCTreeBuilder { if (k1 === this.indexAfter(k0)) { // two original points in sequence -- need a clip plane right here!!! const plane = ClipPlane.createEdgeAndUpVector( - points[k0], points[k1], Vector3d.create(0, 0, 1), Angle.createRadians(0), + points[k0], + points[k1], + Vector3d.create(0, 0, 1), + Angle.createRadians(0), ); if (plane !== undefined) { if (isPositiveArea) @@ -364,7 +373,7 @@ export class AlternatingCCTreeBuilder { for (const child of root.children) this.collectHullPointsInArray(child.points, child.startIdx, child.numPoints, isPositiveArea ? -1.0 : 1.0); } - return true; // Are there failure modes? What happens with crossing data?.. + return true; // Are there failure modes? What happens with crossing data?.. } /** *
    @@ -404,16 +413,18 @@ export class AlternatingCCTreeNodeCurveClipper { this._intervalStack = []; } - private setCurveRef(curve: CurvePrimitive) { this._curve = curve; } + private setCurveRef(curve: CurvePrimitive) { + this._curve = curve; + } private popSegmentFrame() { if (this._stackDepth > 0) { - this._topOfStack.length = 0; // formality. + this._topOfStack.length = 0; // formality. this._stackDepth -= 1; } } private clearSegmentStack() { while (this._stackDepth > 0) - this.popSegmentFrame(); // and that will reduce stack depth + this.popSegmentFrame(); // and that will reduce stack depth } private pushEmptySegmentFrame() { this._stackDepth += 1; @@ -421,7 +432,9 @@ export class AlternatingCCTreeNodeCurveClipper { this._intervalStack.push([]); this._topOfStack.length = 0; } - private get _topOfStack(): Range1d[] { return this._intervalStack[this._stackDepth - 1]; } + private get _topOfStack(): Range1d[] { + return this._intervalStack[this._stackDepth - 1]; + } // set the top of the stack (as defined by stackDepth -- not array length) private set _topOfStack(value: Range1d[]) { const n = this._stackDepth; @@ -447,22 +460,26 @@ export class AlternatingCCTreeNodeCurveClipper { const segment = this._curve; let f0: number; let f1: number; - if (segment.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { f0 = a0; f1 = a1; })) { + if ( + segment.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { + f0 = a0; + f1 = a1; + }) + ) { insideSegments.push(Range1d.createXX(f0!, f1!)); } return true; - } else if (this._curve instanceof Arc3d) { const arc = this._curve; fractionIntervals.length = 0; arc.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { - fractionIntervals.push(a0); fractionIntervals.push(a1); + fractionIntervals.push(a0); + fractionIntervals.push(a1); }); for (let i = 0; i < fractionIntervals.length; i += 2) insideSegments.push(Range1d.createXX(fractionIntervals[i], fractionIntervals[i + 1])); return true; - - } else if (this._curve instanceof LineString3d && (this._curve).points.length > 1) { + } else if (this._curve instanceof LineString3d && this._curve.points.length > 1) { const linestring = this._curve; let f0: number; let f1: number; @@ -470,17 +487,22 @@ export class AlternatingCCTreeNodeCurveClipper { const df = 1.0 / (nPoints - 1); for (let i = 0; i < nPoints - 1; i++) { const segment = LineSegment3d.create(linestring.points[i], linestring.points[i + 1]); - if (segment.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { f0 = a0; f1 = a1; })) { + if ( + segment.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { + f0 = a0; + f1 = a1; + }) + ) { insideSegments.push(Range1d.createXX((i + f0!) * df, (i + f1!) * df)); } } return true; - } else if (this._curve instanceof BSplineCurve3d) { const bcurve = this._curve; fractionIntervals.length = 0; bcurve.announceClipIntervals(planes, (a0: number, a1: number, _cp: CurvePrimitive) => { - fractionIntervals.push(a0); fractionIntervals.push(a1); + fractionIntervals.push(a0); + fractionIntervals.push(a1); }); for (let i = 0; i < fractionIntervals.length; i += 2) insideSegments.push(Range1d.createXX(fractionIntervals[i], fractionIntervals[i + 1])); @@ -516,8 +538,12 @@ export class AlternatingCCTreeNodeCurveClipper { * Modifies the insideIntervals array given in place. * Note: curve given is passed by reference and stored. */ - public appendSingleClipPrimitive(root: AlternatingCCTreeNode, curve: CurvePrimitive, - insideIntervals: CurveLocationDetailPair[], _outsideIntervals: CurveLocationDetailPair[]) { + public appendSingleClipPrimitive( + root: AlternatingCCTreeNode, + curve: CurvePrimitive, + insideIntervals: CurveLocationDetailPair[], + _outsideIntervals: CurveLocationDetailPair[], + ) { this.setCurveRef(curve); this.clearSegmentStack(); this.recurse(root); @@ -540,8 +566,12 @@ export class AlternatingCCTreeNodeCurveClipper { * Modifies the insideIntervals array given in place. * Note: curve given is passed by reference and stored. */ - public appendCurveCollectionClip(root: AlternatingCCTreeNode, curve: CurveCollection, - insideIntervals: CurveLocationDetailPair[], outsideIntervals: CurveLocationDetailPair[]) { + public appendCurveCollectionClip( + root: AlternatingCCTreeNode, + curve: CurveCollection, + insideIntervals: CurveLocationDetailPair[], + outsideIntervals: CurveLocationDetailPair[], + ) { for (const cp of curve.children) { if (cp instanceof CurvePrimitive) this.appendSingleClipPrimitive(root, cp, insideIntervals, outsideIntervals); diff --git a/core/geometry/src/clipping/BooleanClipNode.ts b/core/geometry/src/clipping/BooleanClipNode.ts index 47334e4fc90f..f4d74c8e70bd 100644 --- a/core/geometry/src/clipping/BooleanClipNode.ts +++ b/core/geometry/src/clipping/BooleanClipNode.ts @@ -96,7 +96,10 @@ export abstract class BooleanClipNode implements Clipper { * * Return 0 if not called, 1 if called. */ protected testedAnnounceNNC( - a0: number, a1: number, cp: CurvePrimitive, announce?: AnnounceNumberNumberCurvePrimitive, + a0: number, + a1: number, + cp: CurvePrimitive, + announce?: AnnounceNumberNumberCurvePrimitive, ): number { if (a0 < a1) { if (announce) @@ -116,7 +119,11 @@ export abstract class BooleanClipNode implements Clipper { * * Return true if any intervals announced. */ protected announcePartsNN( - keepInside: boolean, intervals: Range1d[], f0: number, f1: number, announce?: AnnounceNumberNumber, + keepInside: boolean, + intervals: Range1d[], + f0: number, + f1: number, + announce?: AnnounceNumberNumber, ): boolean { let numAnnounce = 0; if (!keepInside) { @@ -139,7 +146,12 @@ export abstract class BooleanClipNode implements Clipper { * * Return true if any intervals announced. */ protected announcePartsNNC( - keepInside: boolean, intervals: Range1d[], f0: number, f1: number, cp: CurvePrimitive, announce?: AnnounceNumberNumberCurvePrimitive, + keepInside: boolean, + intervals: Range1d[], + f0: number, + f1: number, + cp: CurvePrimitive, + announce?: AnnounceNumberNumberCurvePrimitive, ): boolean { let numAnnounce = 0; if (!keepInside) { @@ -164,7 +176,11 @@ export abstract class BooleanClipNode implements Clipper { } /** Announce "in" portions of a line segment. See `Clipper.announceClippedSegmentIntervals` */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: AnnounceNumberNumber, ): boolean { this._intervalsA.length = 0; const announceIntervalB = (a0: number, a1: number) => { @@ -217,7 +233,9 @@ export abstract class BooleanClipNode implements Clipper { * @internal */ export class BooleanClipNodeUnion extends BooleanClipNode { - public get operationName(): string { return this._keepInside ? "OR" : "NOR"; } + public get operationName(): string { + return this._keepInside ? "OR" : "NOR"; + } public constructor(keepInside: boolean) { super(keepInside); } @@ -257,7 +275,9 @@ export class BooleanClipNodeUnion extends BooleanClipNode { * @internal */ export class BooleanClipNodeParity extends BooleanClipNode { - public get operationName(): string { return this._keepInside ? "XOR" : "NXOR"; } + public get operationName(): string { + return this._keepInside ? "XOR" : "NXOR"; + } public constructor(keepInside: boolean) { super(keepInside); } @@ -294,7 +314,9 @@ export class BooleanClipNodeParity extends BooleanClipNode { * @internal */ export class BooleanClipNodeIntersection extends BooleanClipNode implements PolygonClipper { - public get operationName(): string { return this._keepInside ? "AND" : "NAND"; } + public get operationName(): string { + return this._keepInside ? "AND" : "NAND"; + } public constructor(keepInside: boolean) { super(keepInside); } @@ -315,7 +337,6 @@ export class BooleanClipNodeIntersection extends BooleanClipNode implements Poly outsideFragments: GrowableXYZArray[], arrayCache: GrowableXYZArrayCache, ) { - ClipUtilities.doPolygonClipSequence( xyz, this._clippers, diff --git a/core/geometry/src/clipping/ClipPlane.ts b/core/geometry/src/clipping/ClipPlane.ts index 4ffdf782a089..5e40aec19806 100644 --- a/core/geometry/src/clipping/ClipPlane.ts +++ b/core/geometry/src/clipping/ClipPlane.ts @@ -106,7 +106,10 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { } /** Create a ClipPlane from Plane3dByOriginAndUnitNormal. */ public static createPlane( - plane: Plane3dByOriginAndUnitNormal, invisible: boolean = false, interior: boolean = false, result?: ClipPlane, + plane: Plane3dByOriginAndUnitNormal, + invisible: boolean = false, + interior: boolean = false, + result?: ClipPlane, ): ClipPlane { const distance = plane.getNormalRef().dotProduct(plane.getOriginRef()); if (result) { @@ -123,7 +126,11 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { * * The vector is normalized for storage. */ public static createNormalAndDistance( - normal: Vector3d, distance: number, invisible: boolean = false, interior: boolean = false, result?: ClipPlane, + normal: Vector3d, + distance: number, + invisible: boolean = false, + interior: boolean = false, + result?: ClipPlane, ): ClipPlane | undefined { const normalized = normal.normalize(); if (normalized) { @@ -145,7 +152,11 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { * a vector from the origin.) */ public static createNormalAndPoint( - normal: Vector3d, point: Point3d, invisible: boolean = false, interior: boolean = false, result?: ClipPlane, + normal: Vector3d, + point: Point3d, + invisible: boolean = false, + interior: boolean = false, + result?: ClipPlane, ): ClipPlane | undefined { const normalized = normal.normalize(); if (normalized) { @@ -188,9 +199,14 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { * as a vector from the origin.) */ public static createNormalAndPointXYZXYZ( - normalX: number, normalY: number, normalZ: number, - originX: number, originY: number, originZ: number, - invisible: boolean = false, interior: boolean = false, + normalX: number, + normalY: number, + normalZ: number, + originX: number, + originY: number, + originZ: number, + invisible: boolean = false, + interior: boolean = false, result?: ClipPlane, ): ClipPlane | undefined { const q = Geometry.hypotenuseXYZ(normalX, normalY, normalZ); @@ -227,7 +243,10 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { public static fromJSON(json: ClipPlaneProps, result?: ClipPlane): ClipPlane | undefined { if (json && json.normal && undefined !== json.dist && Number.isFinite(json.dist)) return ClipPlane.createNormalAndDistance( - Vector3d.fromJSON(json.normal), json.dist, !!json.invisible, !!json.interior, + Vector3d.fromJSON(json.normal), + json.dist, + !!json.invisible, + !!json.interior, ); return ClipPlane.createNormalAndDistance(Vector3d.unitZ(), 0, false, false, result); } @@ -261,7 +280,11 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { * @param result optional preallocated plane */ public static createEdgeAndUpVector( - point0: Point3d, point1: Point3d, upVector: Vector3d, tiltAngle?: Angle, result?: ClipPlane, + point0: Point3d, + point1: Point3d, + upVector: Vector3d, + tiltAngle?: Angle, + result?: ClipPlane, ): ClipPlane | undefined { const edgeVector = Vector3d.createFrom(point1.minus(point0)); let normal = (upVector.crossProduct(edgeVector)).normalize(); @@ -305,7 +328,10 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { */ public getPlane4d(): Point4d { return Point4d.create( - this._inwardNormal.x, this._inwardNormal.y, this._inwardNormal.z, - this._distanceFromOrigin, + this._inwardNormal.x, + this._inwardNormal.y, + this._inwardNormal.z, + -this._distanceFromOrigin, ); } /** @@ -424,7 +450,12 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { const beta = this.velocity(arcVectors.vector0); const gamma = this.velocity(arcVectors.vector90); AnalyticRoots.appendImplicitLineUnitCircleIntersections( - alpha, beta, gamma, undefined, undefined, intersectionRadians, + alpha, + beta, + gamma, + undefined, + undefined, + intersectionRadians, ); } private static _clipArcFractionArray = new GrowableFloat64Array(); @@ -453,7 +484,7 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { if (h0 === 0.0 && h1 === 0.0) { return undefined; } - return - h0 / (h1 - h0); + return -h0 / (h1 - h0); } /** Apply transform to the origin. Apply inverse transpose of the matrix part to th normal vector. */ public transformInPlace(transform: Transform): boolean { @@ -481,7 +512,7 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { /** Reverse the sign of all coefficients, so outside and inside reverse */ public negateInPlace() { this._inwardNormal = this._inwardNormal.negate(); - this._distanceFromOrigin = - this._distanceFromOrigin; + this._distanceFromOrigin = -this._distanceFromOrigin; } /** * Move the plane INWARD by given distance @@ -535,16 +566,23 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { } /** Announce the interval (if any) where a line is within the clip plane half space. */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: (fraction0: number, fraction1: number) => void, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: (fraction0: number, fraction1: number) => void, ): boolean { if (f1 < f0) return false; - const h0 = - this.altitude(pointA); - const h1 = - this.altitude(pointB); + const h0 = -this.altitude(pointA); + const h1 = -this.altitude(pointB); const delta = h1 - h0; const f = Geometry.conditionalDivideFraction(-h0, delta); if (f === undefined) { // The segment is parallel to the plane. - if (h0 <= 0.0) { if (announce) announce(f0, f1); return true; } + if (h0 <= 0.0) { + if (announce) announce(f0, f1); + return true; + } return false; } if (delta > 0) { // segment aims OUT @@ -618,7 +656,11 @@ export class ClipPlane extends Plane3d implements Clipper, PolygonClipper { const newInside = arrayCache.grabFromCache(); const newOutside = arrayCache.grabFromCache(); IndexedXYZCollectionPolygonOps.splitConvexPolygonInsideOutsidePlane( - this, xyz, newInside, newOutside, perpendicularRange, + this, + xyz, + newInside, + newOutside, + perpendicularRange, ); ClipUtilities.captureOrDrop(newInside, 3, insideFragments, arrayCache); ClipUtilities.captureOrDrop(newOutside, 3, outsideFragments, arrayCache); diff --git a/core/geometry/src/clipping/ClipPrimitive.ts b/core/geometry/src/clipping/ClipPrimitive.ts index de254df2d3a4..efae8cfffabc 100644 --- a/core/geometry/src/clipping/ClipPrimitive.ts +++ b/core/geometry/src/clipping/ClipPrimitive.ts @@ -7,25 +7,25 @@ * @module CartesianGeometry */ +import { Arc3d } from "../curve/Arc3d"; +import { AnnounceNumberNumber, AnnounceNumberNumberCurvePrimitive } from "../curve/CurvePrimitive"; import { Geometry } from "../Geometry"; import { Vector2d } from "../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; +import { Point3dArray } from "../geometry3d/PointHelpers"; import { PolygonOps } from "../geometry3d/PolygonOps"; -import { TransformProps, XYZProps } from "../geometry3d/XYZProps"; +import { PolylineOps } from "../geometry3d/PolylineOps"; import { Range3d } from "../geometry3d/Range"; import { Transform } from "../geometry3d/Transform"; +import { TransformProps, XYZProps } from "../geometry3d/XYZProps"; import { Matrix4d } from "../geometry4d/Matrix4d"; import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "../topology/Graph"; import { Triangulator } from "../topology/Triangulation"; +import { AlternatingCCTreeNode } from "./AlternatingConvexClipTree"; import { ClipPlane } from "./ClipPlane"; import { Clipper, ClipPlaneContainment } from "./ClipUtils"; import { ConvexClipPlaneSet } from "./ConvexClipPlaneSet"; import { UnionOfConvexClipPlaneSets, UnionOfConvexClipPlaneSetsProps } from "./UnionOfConvexClipPlaneSets"; -import { AlternatingCCTreeNode } from "./AlternatingConvexClipTree"; -import { Point3dArray } from "../geometry3d/PointHelpers"; -import { PolylineOps } from "../geometry3d/PolylineOps"; -import { Arc3d } from "../curve/Arc3d"; -import { AnnounceNumberNumber, AnnounceNumberNumberCurvePrimitive } from "../curve/CurvePrimitive"; // cspell:word zlow // cspell:word zhigh /** @@ -142,7 +142,8 @@ export class ClipPrimitive implements Clipper { * @param isInvisible set the invisible flag on the ClipPrimitive */ public static createCapture( - planes: UnionOfConvexClipPlaneSets | ConvexClipPlaneSet | undefined, isInvisible: boolean = false, + planes: UnionOfConvexClipPlaneSets | ConvexClipPlaneSet | undefined, + isInvisible: boolean = false, ): ClipPrimitive { let planeData; if (planes instanceof UnionOfConvexClipPlaneSets) @@ -183,7 +184,7 @@ export class ClipPrimitive implements Clipper { * * In derived class, on first call create planes sets from defining data (e.g. swept shape). * * In derived class, if planes are present leave them alone. */ - public ensurePlaneSets() { } + public ensurePlaneSets() {} /** * Return true if the point lies inside/on this polygon (or not inside/on if this polygon is a mask). Otherwise, * return false. @@ -213,7 +214,11 @@ export class ClipPrimitive implements Clipper { * * Implement as dispatch to clipPlaneSets as supplied by derived class. */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: AnnounceNumberNumber, ): boolean { this.ensurePlaneSets(); let hasInsideParts = false; @@ -244,7 +249,7 @@ export class ClipPrimitive implements Clipper { * * Both params default to true to get the full effect of transforming space. */ public multiplyPlanesByMatrix4d(matrix: Matrix4d, invert: boolean = true, transpose: boolean = true): boolean { - if (invert) { // form inverse once here, reuse for all planes + if (invert) { // form inverse once here, reuse for all planes const inverse = matrix.createInverse(); if (!inverse) return false; @@ -269,11 +274,12 @@ export class ClipPrimitive implements Clipper { * (b) finite distance from origin. */ public containsZClip(): boolean { - if (this.fetchClipPlanesRef() !== undefined) + if (this.fetchClipPlanesRef() !== undefined) { for (const convexSet of this._clipPlanes!.convexSets) for (const plane of convexSet.planes) if (Math.abs(plane.inwardNormalRef.z) > 1.0e-6 && Math.abs(plane.distance) !== Number.MAX_VALUE) return true; + } return false; } /** @@ -288,7 +294,7 @@ export class ClipPrimitive implements Clipper { let inside = ClipPlaneContainment.StronglyInside; if (planes) inside = planes.classifyPointContainment(points, false); - if (this._invisible && !ignoreInvisibleSetting) + if (this._invisible && !ignoreInvisibleSetting) { switch (inside) { case ClipPlaneContainment.StronglyInside: return ClipPlaneContainment.StronglyOutside; @@ -297,6 +303,7 @@ export class ClipPrimitive implements Clipper { case ClipPlaneContainment.Ambiguous: return ClipPlaneContainment.Ambiguous; } + } return inside; } /** @@ -371,7 +378,12 @@ export class ClipShape extends ClipPrimitive { protected _transformToClip?: Transform; protected constructor( - polygon: Point3d[] = [], zLow?: number, zHigh?: number, transform?: Transform, isMask: boolean = false, invisible: boolean = false, + polygon: Point3d[] = [], + zLow?: number, + zHigh?: number, + transform?: Transform, + isMask: boolean = false, + invisible: boolean = false, ) { super(undefined, invisible); // ClipPlaneSets will be set up later after storing points this._isMask = false; @@ -565,7 +577,10 @@ export class ClipShape extends ClipPrimitive { } /** Creates a new ClipShape with undefined members and a polygon points array of zero length. */ public static createEmpty( - isMask = false, invisible: boolean = false, transform?: Transform, result?: ClipShape, + isMask = false, + invisible: boolean = false, + transform?: Transform, + result?: ClipShape, ): ClipShape { if (result) { result._clipPlanes = undefined; @@ -615,7 +630,10 @@ export class ClipShape extends ClipPrimitive { * defining the bounded region of linear planes. Returns true if successful. */ private parseLinearPlanes( - set: UnionOfConvexClipPlaneSets, start: Point3d, end: Point3d, cameraFocalLength?: number, + set: UnionOfConvexClipPlaneSets, + start: Point3d, + end: Point3d, + cameraFocalLength?: number, ): boolean { // Handles the degenerate case of 2 distinct points (used by select by line). const normal = start.vectorTo(end); @@ -708,18 +726,21 @@ export class ClipShape extends ClipPrimitive { for (const edge of edges) convexSet.planes.push(ClipPlane.createNormalAndPoint(Vector3d.create(edge.normal.x, edge.normal.y), edge.pointA)!); } else { - if (reverse) + if (reverse) { for (const edge of edges) convexSet.planes.push( ClipPlane.createNormalAndDistance( - Vector3d.createFrom(edge.pointA).crossProduct(Vector3d.createFrom(edge.pointB)).normalize()!, 0.0, + Vector3d.createFrom(edge.pointA).crossProduct(Vector3d.createFrom(edge.pointB)).normalize()!, + 0.0, )!, ); + } else for (const edge of edges) convexSet.planes.push( ClipPlane.createNormalAndDistance( - Vector3d.createFrom(edge.pointB).crossProduct(Vector3d.createFrom(edge.pointA)).normalize()!, 0.0, + Vector3d.createFrom(edge.pointB).crossProduct(Vector3d.createFrom(edge.pointA)).normalize()!, + 0.0, )!, ); } @@ -732,8 +753,7 @@ export class ClipShape extends ClipPrimitive { * Given a (possibly non-convex) polygon defined as an array of points, populate the given UnionOfConvexClipPlaneSets * with multiple ConvexClipPlaneSets defining the bounded region. Returns true if successful. */ - private parsePolygonPlanes(set: UnionOfConvexClipPlaneSets, polygon: Point3d[], isMask: boolean, cameraFocalLength?: number, - ): boolean { + private parsePolygonPlanes(set: UnionOfConvexClipPlaneSets, polygon: Point3d[], isMask: boolean, cameraFocalLength?: number): boolean { const cleanPolygon = PolylineOps.compressDanglers(polygon, true); const announceFace = (_graph: HalfEdgeGraph, edge: HalfEdge): boolean => { if (!edge.isMaskSet(HalfEdgeMask.EXTERIOR)) { diff --git a/core/geometry/src/clipping/ClipUtils.ts b/core/geometry/src/clipping/ClipUtils.ts index b3343e85bb1e..e699cbd296e0 100644 --- a/core/geometry/src/clipping/ClipUtils.ts +++ b/core/geometry/src/clipping/ClipUtils.ts @@ -99,7 +99,11 @@ export interface Clipper { * @returns true if a segment was announced, false if entirely outside. */ announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: AnnounceNumberNumber, ): boolean; /** * Find the portion (or portions) of the arc (if any) that are within the convex clip volume. @@ -129,7 +133,7 @@ type AppendPolygonClipFunction = ( xyz: IndexedXYZCollection, insideFragments: GrowableXYZArray[], outsideFragments: GrowableXYZArray[], - arrayCache: GrowableXYZArrayCache + arrayCache: GrowableXYZArrayCache, ) => void; /** @@ -198,7 +202,9 @@ export class ClipUtilities { * @param announce function to receive data */ public static announceNNC( - intervals: Range1d[], cp: CurvePrimitive, announce?: AnnounceNumberNumberCurvePrimitive, + intervals: Range1d[], + cp: CurvePrimitive, + announce?: AnnounceNumberNumberCurvePrimitive, ): boolean { if (announce) { for (const ab of intervals) { @@ -316,7 +322,8 @@ export class ClipUtilities { * @return An multidimensional array of points, where each array is the boundary of part of the remaining polygon. */ public static clipPolygonToClipShapeReturnGrowableXYZArrays( - polygon: Point3d[], clipShape: ClipPrimitive, + polygon: Point3d[], + clipShape: ClipPrimitive, ): GrowableXYZArray[] { const output: GrowableXYZArray[] = []; const clipper = clipShape.fetchClipPlanesRef(); @@ -333,7 +340,9 @@ export class ClipUtilities { * * ClipStatus.TrivialReject if neither of those occurred. */ public static pointSetSingleClipStatus( - points: GrowableXYZArray, planeSet: UnionOfConvexClipPlaneSets, tolerance: number, + points: GrowableXYZArray, + planeSet: UnionOfConvexClipPlaneSets, + tolerance: number, ): ClipStatus { if (planeSet.convexSets.length === 0) return ClipStatus.TrivialAccept; @@ -360,7 +369,7 @@ export class ClipUtilities { } } - if (!anyOutside) // totally inside this set - no clip required + if (!anyOutside) // totally inside this set - no clip required return ClipStatus.TrivialAccept; if (!allOutsideSinglePlane) return ClipStatus.ClipRequired; @@ -398,7 +407,7 @@ export class ClipUtilities { loopFunction(finalPoints); } } - } else { // `convexSet` is just one plane ... + } else { // `convexSet` is just one plane ... if (ignoreInvisiblePlanes && convexSet.invisible) { // skip it ! } else { @@ -448,18 +457,28 @@ export class ClipUtilities { const result: GeometryQuery[] = []; if (allClippers instanceof UnionOfConvexClipPlaneSets) { for (const clipper of allClippers.convexSets) { - this.announceLoopsOfConvexClipPlaneSetIntersectRange(clipper, range, + this.announceLoopsOfConvexClipPlaneSetIntersectRange( + clipper, + range, (points: GrowableXYZArray) => { if (points.length > 0) result.push(Loop.createPolygon(points)); }, - includeConvexSetFaces, includeRangeFaces, ignoreInvisiblePlanes); + includeConvexSetFaces, + includeRangeFaces, + ignoreInvisiblePlanes, + ); } } else if (allClippers instanceof ConvexClipPlaneSet || allClippers instanceof ClipPlane) { - this.announceLoopsOfConvexClipPlaneSetIntersectRange(allClippers, range, + this.announceLoopsOfConvexClipPlaneSetIntersectRange( + allClippers, + range, (points: GrowableXYZArray) => { if (points.length > 0) result.push(Loop.createPolygon(points)); }, - includeConvexSetFaces, includeRangeFaces, ignoreInvisiblePlanes); + includeConvexSetFaces, + includeRangeFaces, + ignoreInvisiblePlanes, + ); } return result; } @@ -471,11 +490,16 @@ export class ClipUtilities { */ public static rangeOfConvexClipPlaneSetIntersectionWithRange(convexSet: ConvexClipPlaneSet, range: Range3d): Range3d { const result = Range3d.createNull(); - this.announceLoopsOfConvexClipPlaneSetIntersectRange(convexSet, range, + this.announceLoopsOfConvexClipPlaneSetIntersectRange( + convexSet, + range, (points: GrowableXYZArray) => { if (points.length > 0) result.extendArray(points); }, - true, true, false); + true, + true, + false, + ); return result; } /** @@ -524,7 +548,6 @@ export class ClipUtilities { } } return rangeIntersection; - } return range.clone(); } @@ -562,7 +585,7 @@ export class ClipUtilities { } if (clipper instanceof ClipPrimitive) { - if (observeInvisibleFlag && clipper.invisible) // um is there an easy way to detect range-completely-inside? + if (observeInvisibleFlag && clipper.invisible) // um is there an easy way to detect range-completely-inside? return true; return this.doesClipperIntersectRange(clipper.fetchClipPlanesRef(), range); } @@ -633,8 +656,12 @@ export class ClipUtilities { * @param transform how to transform the range (NOTE: applied to the range faces without swelling the range volume) * @param degeneratePoints optionally populated with the 1 or 2 points defining the transformed range if it is degenerate (all points colinear/coincident); otherwise untouched * @returns newly constructed clipper. If no clip planes could be computed, fill `degeneratePoints` and return undefined. - */ - private static createClipperFromTransformedRange3d(range: Range3d, transform: Transform, degeneratePoints?: Point3d[]): ConvexClipPlaneSet | undefined { + */ + private static createClipperFromTransformedRange3d( + range: Range3d, + transform: Transform, + degeneratePoints?: Point3d[], + ): ConvexClipPlaneSet | undefined { if (!transform) transform = Transform.createIdentity(); const builder = PolyfaceBuilder.create(); @@ -667,7 +694,8 @@ export class ClipUtilities { (f0: number, f1: number, cp: CurvePrimitive) => { intersection.extendPoint(cp.fractionToPoint(f0), localToWorld); intersection.extendPoint(cp.fractionToPoint(f1), localToWorld); - } : undefined; + } : + undefined; let hasIntersection = false; if (points.length > 1) { const segment = LineSegment3d.createCapture(points[0], points[1]); @@ -691,7 +719,11 @@ export class ClipUtilities { * @return whether the local ranges are adjacent or intersect. Also returns false if local1ToWorld is singular. */ public static doLocalRangesIntersect( - range0: Range3d, local0ToWorld: Transform, range1: Range3d, local1ToWorld: Transform, range1Margin?: number, + range0: Range3d, + local0ToWorld: Transform, + range1: Range3d, + local1ToWorld: Transform, + range1Margin?: number, ): boolean { const worldToLocal1 = this._workTransform = local1ToWorld.inverse(this._workTransform); if (!worldToLocal1) @@ -718,7 +750,13 @@ export class ClipUtilities { * @param result optional pre-allocated range to fill and return * @return range of the intersection (aligned to world axes). Returns null range if local1ToWorld is singular. */ - public static rangeOfIntersectionOfLocalRanges(range0: Range3d, local0ToWorld: Transform, range1: Range3d, local1ToWorld: Transform, result?: Range3d): Range3d { + public static rangeOfIntersectionOfLocalRanges( + range0: Range3d, + local0ToWorld: Transform, + range1: Range3d, + local1ToWorld: Transform, + result?: Range3d, + ): Range3d { const myResult = Range3d.createNull(result); const worldToLocal1 = this._workTransform = local1ToWorld.inverse(this._workTransform); if (!worldToLocal1) @@ -728,7 +766,9 @@ export class ClipUtilities { // convert range0 into a clipper in local1 coordinates, then intersect with range1 const clipper = this.createClipperFromTransformedRange3d(range0, local0ToLocal1, degeneratePoints); if (clipper) - this.announceLoopsOfConvexClipPlaneSetIntersectRange(clipper, range1, (loopPoints: GrowableXYZArray) => { loopPoints.extendRange(myResult, local1ToWorld); }); + this.announceLoopsOfConvexClipPlaneSetIntersectRange(clipper, range1, (loopPoints: GrowableXYZArray) => { + loopPoints.extendRange(myResult, local1ToWorld); + }); else this.rangeIntersectPointOrSegment(range1, degeneratePoints, local1ToWorld, myResult); return myResult; @@ -739,9 +779,11 @@ export class ClipUtilities { */ public static isClipper(obj: any): boolean { if (obj) { - if (obj.isPointOnOrInside + if ( + obj.isPointOnOrInside && obj.announceClippedSegmentIntervals - && obj.announceClippedArcIntervals) + && obj.announceClippedArcIntervals + ) return true; } return false; @@ -763,7 +805,10 @@ export class ClipUtilities { * @param cache cache for array management */ public static restoreSingletonInPlaceOfMultipleShards( - fragments: GrowableXYZArray[] | undefined, baseCount: number, singleton: IndexedXYZCollection, arrayCache: GrowableXYZArrayCache, + fragments: GrowableXYZArray[] | undefined, + baseCount: number, + singleton: IndexedXYZCollection, + arrayCache: GrowableXYZArrayCache, ): void { if (fragments && fragments.length > baseCount + 1) { while (fragments.length > baseCount) { @@ -783,17 +828,29 @@ export class ClipUtilities { * @alpha */ public static createXYOffsetClipFromLineString( - points: Point3d[] | IndexedXYZCollection, leftOffset: number, rightOffset: number, z0: number, z1: number, + points: Point3d[] | IndexedXYZCollection, + leftOffset: number, + rightOffset: number, + z0: number, + z1: number, ): UnionOfConvexClipPlaneSets { if (Array.isArray(points)) { return LineStringOffsetClipperContext.createClipBetweenOffsets( - new Point3dArrayCarrier(points), leftOffset, rightOffset, z0, z1); + new Point3dArrayCarrier(points), + leftOffset, + rightOffset, + z0, + z1, + ); } return LineStringOffsetClipperContext.createClipBetweenOffsets(points, leftOffset, rightOffset, z0, z1); } /** If data.length >= minLength threshold, push it to destination; if smaller drop it back to the cache. */ public static captureOrDrop( - data: GrowableXYZArray, minLength: number, destination: GrowableXYZArray[], cache: GrowableXYZArrayCache, + data: GrowableXYZArray, + minLength: number, + destination: GrowableXYZArray[], + cache: GrowableXYZArrayCache, ): void { if (data.length >= minLength) destination.push(data); @@ -812,10 +869,15 @@ export class ClipUtilities { * @param segmentPoint0 First point of clipped segment * @param segmentPoint1 Second point of clipped segment * @param interval Live interval. - * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line + * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line */ public static clipSegmentToLLeftOfLineXY( - linePointA: XAndY, linePointB: XAndY, segmentPoint0: XAndY, segmentPoint1: XAndY, interval: Range1d, absoluteTolerance: number = 1.0e-14, + linePointA: XAndY, + linePointB: XAndY, + segmentPoint0: XAndY, + segmentPoint1: XAndY, + interval: Range1d, + absoluteTolerance: number = 1.0e-14, ): void { const ux = linePointB.x - linePointA.x; const uy = linePointB.y - linePointA.y; @@ -859,7 +921,13 @@ export class ClipUtilities { * @param absoluteTolerance absolute tolerance for begin "on a line" */ public static clipSegmentToCCWTriangleXY( - pointA: XAndY, pointB: XAndY, pointC: XAndY, segment0: XAndY, segment1: XAndY, interval: Range1d, absoluteTolerance: number = 1.0e-14, + pointA: XAndY, + pointB: XAndY, + pointC: XAndY, + segment0: XAndY, + segment1: XAndY, + interval: Range1d, + absoluteTolerance: number = 1.0e-14, ): void { if (!interval.isNull) { this.clipSegmentToLLeftOfLineXY(pointA, pointB, segment0, segment1, interval, absoluteTolerance); @@ -883,10 +951,14 @@ export class ClipUtilities { * @param segmentPoint0 First point of clipped segment * @param segmentPoint1 Second point of clipped segment * @param interval Live interval. - * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line + * @param absoluteTolerance absolute tolerance for both cross product values to indicate "on" the line */ public static clipSegmentBelowPlaneXY( - plane: Plane3dByOriginAndUnitNormal, segmentPoint0: XAndY, segmentPoint1: XAndY, interval: Range1d, absoluteTolerance: number = 1.0e-14, + plane: Plane3dByOriginAndUnitNormal, + segmentPoint0: XAndY, + segmentPoint1: XAndY, + interval: Range1d, + absoluteTolerance: number = 1.0e-14, ): void { // negative is in positive is out ... const h0 = plane.altitudeXY(segmentPoint0.x, segmentPoint0.y); @@ -928,7 +1000,11 @@ export class ClipUtilities { * @param absoluteTolerance absolute tolerance for begin "on a line" */ public static clipSegmentBelowPlanesXY( - planes: Plane3dByOriginAndUnitNormal[], segment0: XAndY, segment1: XAndY, interval: Range1d, signedAltitude: number = 1.0e-14, + planes: Plane3dByOriginAndUnitNormal[], + segment0: XAndY, + segment1: XAndY, + interval: Range1d, + signedAltitude: number = 1.0e-14, ): void { const numPlanes = planes.length; for (let i = 0; (!interval.isNull) && i < numPlanes; i++) { @@ -942,13 +1018,14 @@ export class ClipUtilities { * @param announce caller's handler for simple point pairs. */ public static announcePolylineClip( - clipper: Clipper, points: Point3d[], announce: (point0: Point3d, point1: Point3d) => void, + clipper: Clipper, + points: Point3d[], + announce: (point0: Point3d, point1: Point3d) => void, ): void { for (let i = 0; i + 1 < points.length; i++) { - clipper.announceClippedSegmentIntervals(0, 1, points[i], points[i + 1], - (f0: number, f1: number) => { - announce(points[i].interpolate(f0, points[i + 1]), points[i].interpolate(f1, points[i + 1])); - }); + clipper.announceClippedSegmentIntervals(0, 1, points[i], points[i + 1], (f0: number, f1: number) => { + announce(points[i].interpolate(f0, points[i + 1]), points[i].interpolate(f1, points[i + 1])); + }); } } /** @@ -960,8 +1037,9 @@ export class ClipUtilities { let s = 0; for (let i = 0; i + 1 < points.length; i++) { const a = points[i].distance(points[i + 1]); - clipper.announceClippedSegmentIntervals(0, 1, points[i], points[i + 1], - (f0: number, f1: number) => { s += Math.abs(f1 - f0) * a; }); + clipper.announceClippedSegmentIntervals(0, 1, points[i], points[i + 1], (f0: number, f1: number) => { + s += Math.abs(f1 - f0) * a; + }); } return s; } @@ -1015,7 +1093,9 @@ export class ClipUtilities { arrayCache.dropToCache(shard); } // candidates is empty !! - const temp = candidates; candidates = nextCandidates; nextCandidates = temp; + const temp = candidates; + candidates = nextCandidates; + nextCandidates = temp; } } distributeFragments(finalFragmentAction, candidates, acceptedIn, acceptedOut, finalCandidates, arrayCache); @@ -1064,8 +1144,12 @@ export class ClipUtilities { arrayCache.dropToCache(shard); } // reload each candidate step - const tempA = candidatesIn; candidatesIn = nextCandidatesIn; nextCandidatesIn = tempA; - const tempB = candidatesOut; candidatesOut = nextCandidatesOut; nextCandidatesOut = tempB; + const tempA = candidatesIn; + candidatesIn = nextCandidatesIn; + nextCandidatesIn = tempA; + const tempB = candidatesOut; + candidatesOut = nextCandidatesOut; + nextCandidatesOut = tempB; } } // candidatesIn and candidatesOut are final .... diff --git a/core/geometry/src/clipping/ClipVector.ts b/core/geometry/src/clipping/ClipVector.ts index 9231b2dacdba..9276d4577e16 100644 --- a/core/geometry/src/clipping/ClipVector.ts +++ b/core/geometry/src/clipping/ClipVector.ts @@ -49,12 +49,16 @@ export class ClipVector implements Clipper { */ public boundingRange: Range3d = Range3d.createNull(); /** Returns a reference to the array of ClipShapes. */ - public get clips() { return this._clips; } + public get clips() { + return this._clips; + } private constructor(clips?: ClipPrimitive[]) { this._clips = clips ? clips : []; } /** Returns true if this ClipVector contains a ClipPrimitive. */ - public get isValid(): boolean { return this._clips.length > 0; } + public get isValid(): boolean { + return this._clips.length > 0; + } /** Create a ClipVector with an empty set of ClipShapes. */ public static createEmpty(result?: ClipVector): ClipVector { if (result) { @@ -125,8 +129,14 @@ export class ClipVector implements Clipper { this._clips.push(clip); } /** Create and append a new ClipPrimitive to the array given a shape as an array of points. Returns true if successful. */ - public appendShape(shape: Point3d[], zLow?: number, zHigh?: number, - transform?: Transform, isMask: boolean = false, invisible: boolean = false): boolean { + public appendShape( + shape: Point3d[], + zLow?: number, + zHigh?: number, + transform?: Transform, + isMask: boolean = false, + invisible: boolean = false, + ): boolean { const clip = ClipShape.createShape(shape, zLow, zHigh, transform, isMask, invisible); if (!clip) return false; @@ -172,7 +182,11 @@ export class ClipVector implements Clipper { * * Implement as dispatch to clipPlaneSets as supplied by derived class. */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: AnnounceNumberNumber, ): boolean { this.ensureProxyClipNode(); if (this._clipNodeProxy) @@ -193,7 +207,8 @@ export class ClipVector implements Clipper { xyz: IndexedXYZCollection, insideFragments: GrowableXYZArray[], outsideFragments: GrowableXYZArray[], - arrayCache: GrowableXYZArrayCache) { + arrayCache: GrowableXYZArrayCache, + ) { this.ensureProxyClipNode(); if (this._clipNodeProxy) this._clipNodeProxy.appendPolygonClip(xyz, insideFragments, outsideFragments, arrayCache); @@ -238,7 +253,7 @@ export class ClipVector implements Clipper { for (const clip of this._clips) { if (clip instanceof ClipShape) { - if (firstClipShape !== undefined && clip !== firstClipShape) { // Is not the first iteration + if (firstClipShape !== undefined && clip !== firstClipShape) { // Is not the first iteration let fwdTrans = Transform.createIdentity(); let invTrans = Transform.createIdentity(); @@ -303,7 +318,7 @@ export class ClipVector implements Clipper { * @returns false if matrix inversion fails. */ public multiplyPlanesByMatrix4d(matrix: Matrix4d, invert: boolean = true, transpose: boolean = true): boolean { - if (invert) { // form inverse once here, reuse for all planes + if (invert) { // form inverse once here, reuse for all planes const inverse = matrix.createInverse(); if (!inverse) return false; @@ -365,7 +380,7 @@ export class ClipVector implements Clipper { public sumSizes(intervals: Segment1d[], begin: number, end: number): number { let s = 0.0; for (let i = begin; i < end; i++) - s += (intervals[i].x1 - intervals[i].x0); + s += intervals[i].x1 - intervals[i].x0; return s; } private static readonly _TARGET_FRACTION_SUM = 0.99999999; @@ -434,7 +449,7 @@ export class ClipVector implements Clipper { } function formatPlane(plane: ClipPlane) { let flags = plane.invisible ? 1 : 0; - flags |= (plane.interior ? 2 : 0); + flags |= plane.interior ? 2 : 0; return `${formatFlags(flags)}${formatVector3d(plane.inwardNormalRef)}${formatNumber(plane.distance)}`; } function formatPlaneSet(set: ConvexClipPlaneSet) { diff --git a/core/geometry/src/clipping/ConvexClipPlaneSet.ts b/core/geometry/src/clipping/ConvexClipPlaneSet.ts index 6cf63bce47db..72a692d60572 100644 --- a/core/geometry/src/clipping/ConvexClipPlaneSet.ts +++ b/core/geometry/src/clipping/ConvexClipPlaneSet.ts @@ -93,7 +93,8 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * * The input array itself is NOT taken into the result. */ public static createPlanes( - planes: (ClipPlane | Plane3dByOriginAndUnitNormal)[], result?: ConvexClipPlaneSet, + planes: (ClipPlane | Plane3dByOriginAndUnitNormal)[], + result?: ConvexClipPlaneSet, ): ConvexClipPlaneSet { result = result ? result : new ConvexClipPlaneSet(); for (const plane of planes) { @@ -164,7 +165,11 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * * More details can be found at docs/learning/geometry/Clipping.md */ public static createXYBox( - x0: number, y0: number, x1: number, y1: number, result?: ConvexClipPlaneSet, + x0: number, + y0: number, + x1: number, + y1: number, + result?: ConvexClipPlaneSet, ): ConvexClipPlaneSet { result = result ? result : new ConvexClipPlaneSet(); result._planes.length = 0; @@ -186,7 +191,10 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param leftIsInside if true, the interior is "to the left" of the segments. If false, interior is "to the right". */ public static createXYPolyLine( - points: Point3d[], interior: boolean[] | undefined, leftIsInside: boolean, result?: ConvexClipPlaneSet, + points: Point3d[], + interior: boolean[] | undefined, + leftIsInside: boolean, + result?: ConvexClipPlaneSet, ): ConvexClipPlaneSet { result = result ? result : new ConvexClipPlaneSet(); result._planes.length = 0; @@ -243,7 +251,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { let y0 = points.getYAtUncheckedPointIndex(i0); let x1, y1, nx, ny; frustum._planes.length = 0; - const z0 = points.getZAtUncheckedPointIndex(i0); // z for planes can stay fixed + const z0 = points.getZAtUncheckedPointIndex(i0); // z for planes can stay fixed const planeNormal = points.crossProductIndexIndexIndex(0, 2, 1)!; ClipPlane.createNormalAndPointXYZXYZ(planeNormal.x, planeNormal.y, planeNormal.z, x0, y0, z0, false, false, planeOfPolygon); if (planeNormal.normalizeInPlace()) { @@ -293,9 +301,9 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { if (Math.abs(vD) <= velocityTolerance) { // Ray is parallel... No need to continue testing if outside halfspace. if (vN < -tolerance) - return false; // and result is a null range. + return false; // and result is a null range. } else { - const rayFraction = - vN / vD; + const rayFraction = -vN / vD; if (vD < 0.0) { if (rayFraction < t1) t1 = rayFraction; @@ -306,7 +314,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { } } if (t1 < t0) - return false; // and result is a null range. + return false; // and result is a null range. if (result) { result.extendX(t0); result.extendX(t1); @@ -325,7 +333,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param matrix matrix to apply */ public multiplyPlanesByMatrix4d(matrix: Matrix4d, invert: boolean = true, transpose: boolean = true): boolean { - if (invert) { // form inverse once here, reuse for all planes + if (invert) { // form inverse once here, reuse for all planes const inverse = matrix.createInverse(); if (!inverse) return false; @@ -348,9 +356,9 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { /** Return true if `point` satisfies `point.isPointOnOrInside` for all planes */ public isPointOnOrInside(point: Point3d, tolerance: number = Geometry.smallMetricDistance): boolean { - const interiorTolerance = Math.abs(tolerance); // Interior tolerance should always be positive. (TFS# 246598). + const interiorTolerance = Math.abs(tolerance); // Interior tolerance should always be positive. (TFS# 246598). for (const plane of this._planes) { - if (!plane.isPointOnOrInside(point, (plane.interior ? interiorTolerance : tolerance))) + if (!plane.isPointOnOrInside(point, plane.interior ? interiorTolerance : tolerance)) return false; } return true; @@ -384,7 +392,11 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @returns true if a segment was announced, false if entirely outside. */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: AnnounceNumberNumber, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: AnnounceNumberNumber, ): boolean { let fraction: number | undefined; if (f1 < f0) @@ -392,7 +404,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { for (const plane of this._planes) { const hA = -plane.altitude(pointA); const hB = -plane.altitude(pointB); - fraction = Geometry.conditionalDivideFraction(-hA, (hB - hA)); + fraction = Geometry.conditionalDivideFraction(-hA, hB - hA); if (fraction === undefined) { // Line parallel to the plane. If positive, it is all OUT if (hA > 0.0) @@ -459,7 +471,9 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param tolerance tolerance for "on plane" decision. */ public clipConvexPolygonInPlace( - xyz: GrowableXYZArray, work: GrowableXYZArray, tolerance: number = Geometry.smallMetricDistance, + xyz: GrowableXYZArray, + work: GrowableXYZArray, + tolerance: number = Geometry.smallMetricDistance, ): void { for (const plane of this._planes) { plane.clipConvexPolygonInPlace(xyz, work, true, tolerance); @@ -475,23 +489,29 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @return the surviving inside part (if any) */ public clipInsidePushOutside( - xyz: IndexedXYZCollection, outsideFragments: GrowableXYZArray[] | undefined, arrayCache: GrowableXYZArrayCache, + xyz: IndexedXYZCollection, + outsideFragments: GrowableXYZArray[] | undefined, + arrayCache: GrowableXYZArrayCache, ): GrowableXYZArray | undefined { const perpendicularRange = Range1d.createNull(); let newInside = arrayCache.grabFromCache(); let newOutside = arrayCache.grabFromCache(); - let insidePart = arrayCache.grabFromCache(); // this is empty ... + let insidePart = arrayCache.grabFromCache(); // this is empty ... insidePart.pushFrom(xyz); // While looping through planes . . // the outside part for the current plane is definitely outside and can be stashed to the final outside // the inside part for the current plane passes forward to be further split by the remaining planes. for (const plane of this._planes) { IndexedXYZCollectionPolygonOps.splitConvexPolygonInsideOutsidePlane( - plane, insidePart, newInside, newOutside, perpendicularRange, + plane, + insidePart, + newInside, + newOutside, + perpendicularRange, ); if (newOutside.length > 0) { // the newOutside fragment is definitely outside the ConvexClipPlaneSet - if (outsideFragments) // save the definitely outside part as return data. + if (outsideFragments) // save the definitely outside part as return data. ClipUtilities.captureOrDrop(newOutside, 3, outsideFragments, arrayCache); newOutside = arrayCache.grabFromCache(); if (newInside.length === 0) { @@ -528,7 +548,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { public classifyPointContainment(points: Point3d[], onIsOutside: boolean): ClipPlaneContainment { let allInside = true; const onTolerance = onIsOutside ? 1.0e-8 : -1.0e-8; - const interiorTolerance = 1.0e-8; // Interior tolerance should always be positive + const interiorTolerance = 1.0e-8; // Interior tolerance should always be positive for (const plane of this._planes) { let nOutside = 0; @@ -554,7 +574,9 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param tiltAngle angle to tilt sweep planes away from the sweep direction. */ public static createSweptPolyline( - points: Point3d[], upVector: Vector3d, tiltAngle?: Angle, + points: Point3d[], + upVector: Vector3d, + tiltAngle?: Angle, ): ConvexClipPlaneSet | undefined { const result = ConvexClipPlaneSet.createEmpty(); let reverse = false; @@ -567,14 +589,14 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { for (let i = 0; (i + 1) < points.length; i++) { if (reverse) { const toAdd = ClipPlane.createEdgeAndUpVector(points[i + 1], points[i], upVector, tiltAngle); - if (toAdd) { // clipPlane creation could result in undefined + if (toAdd) { // clipPlane creation could result in undefined result.addPlaneToConvexSet(toAdd); } else { return undefined; } } else { const toAdd = ClipPlane.createEdgeAndUpVector(points[i], points[i + 1], upVector, tiltAngle); - if (toAdd) { // clipPlane creation could result in undefined + if (toAdd) { // clipPlane creation could result in undefined result.addPlaneToConvexSet(toAdd); } else { return undefined; @@ -623,7 +645,10 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param containingPlane if this plane is found in the convex set, it is NOT applied. */ public polygonClip( - input: GrowableXYZArray | Point3d[], output: GrowableXYZArray, work: GrowableXYZArray, planeToSkip?: ClipPlane, + input: GrowableXYZArray | Point3d[], + output: GrowableXYZArray, + work: GrowableXYZArray, + planeToSkip?: ClipPlane, ): void { if (input instanceof GrowableXYZArray) input.clone(output); @@ -663,14 +688,20 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { if (xyz0.isAlmostEqual(xyz1)) continue; const edgeVector: Vector3d = Vector3d.createStartEnd(xyz0, xyz1); - const inwardNormal: Vector3d = Vector3d.createCrossProduct(sweepDirection.x, sweepDirection.y, sweepDirection.z, - edgeVector.x, edgeVector.y, edgeVector.z); + const inwardNormal: Vector3d = Vector3d.createCrossProduct( + sweepDirection.x, + sweepDirection.y, + sweepDirection.z, + edgeVector.x, + edgeVector.y, + edgeVector.z, + ); const inwardNormalNormalized = inwardNormal.normalize(); let distance; if (inwardNormalNormalized) { // should never fail... simply a check due to the format of the normalize function return distance = inwardNormalNormalized.dotProduct(xyz0); const clipToAdd = ClipPlane.createNormalAndDistance(inwardNormalNormalized, distance, false, false); - if (clipToAdd) { this._planes.push(clipToAdd); } // clipPlane creation could result in undefined + if (clipToAdd) { this._planes.push(clipToAdd); } // clipPlane creation could result in undefined } } if (sideSelect !== 0.0) { @@ -682,7 +713,7 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { const xyz0: Point3d = points[0]; const distance = planeNormalNormalized.dotProduct(xyz0); const clipToAdd = ClipPlane.createNormalAndDistance(planeNormalNormalized, distance, false, false); - if (clipToAdd) { this._planes.push(clipToAdd); } // clipPlane creation could result in undefined + if (clipToAdd) { this._planes.push(clipToAdd); } // clipPlane creation could result in undefined } } return isCCW ? 1 : -1; @@ -718,10 +749,17 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { for (let j = i + 1; j < n; j++) for (let k = j + 1; k < n; k++) { Matrix3d.createRowValues( - allPlanes[i].inwardNormalRef.x, allPlanes[i].inwardNormalRef.y, allPlanes[i].inwardNormalRef.z, - allPlanes[j].inwardNormalRef.x, allPlanes[j].inwardNormalRef.y, allPlanes[j].inwardNormalRef.z, - allPlanes[k].inwardNormalRef.x, allPlanes[k].inwardNormalRef.y, allPlanes[k].inwardNormalRef.z, - normalRows); + allPlanes[i].inwardNormalRef.x, + allPlanes[i].inwardNormalRef.y, + allPlanes[i].inwardNormalRef.z, + allPlanes[j].inwardNormalRef.x, + allPlanes[j].inwardNormalRef.y, + allPlanes[j].inwardNormalRef.z, + allPlanes[k].inwardNormalRef.x, + allPlanes[k].inwardNormalRef.y, + allPlanes[k].inwardNormalRef.z, + normalRows, + ); if (normalRows.computeCachedInverse(false)) { const xyz = normalRows.multiplyInverseXYZAsPoint3d(allPlanes[i].distance, allPlanes[j].distance, allPlanes[k].distance)!; if (!testContainment || this.isPointOnOrInside(xyz, Geometry.smallMetricDistance)) { @@ -788,9 +826,10 @@ export class ConvexClipPlaneSet implements Clipper, PolygonClipper { * @param convexMesh input mesh. For best results, the mesh should be closed and convex. * @param result optional preallocated result to reuse and return * @return clipper and volume (zero if mesh is not closed) - */ + */ public static createConvexPolyface( - convexMesh: Polyface | PolyfaceVisitor, result?: ConvexClipPlaneSet, + convexMesh: Polyface | PolyfaceVisitor, + result?: ConvexClipPlaneSet, ): { clipper: ConvexClipPlaneSet, volume: number } { result = this.createEmpty(result); let vol = 0; diff --git a/core/geometry/src/clipping/UnionOfConvexClipPlaneSets.ts b/core/geometry/src/clipping/UnionOfConvexClipPlaneSets.ts index cbfe73bb29f1..ae2211c9de34 100644 --- a/core/geometry/src/clipping/UnionOfConvexClipPlaneSets.ts +++ b/core/geometry/src/clipping/UnionOfConvexClipPlaneSets.ts @@ -53,7 +53,8 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { } /** Convert json `UnionOfConvexClipPlaneSets`, using `setFromJSON`. */ public static fromJSON( - json: UnionOfConvexClipPlaneSetsProps | undefined, result?: UnionOfConvexClipPlaneSets, + json: UnionOfConvexClipPlaneSetsProps | undefined, + result?: UnionOfConvexClipPlaneSets, ): UnionOfConvexClipPlaneSets { result = result ? result : new UnionOfConvexClipPlaneSets(); result._convexSets.length = 0; @@ -87,7 +88,8 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { } /** Create a `UnionOfConvexClipPlaneSets` with given `ConvexClipPlaneSet` members. */ public static createConvexSets( - convexSets: ConvexClipPlaneSet[], result?: UnionOfConvexClipPlaneSets, + convexSets: ConvexClipPlaneSet[], + result?: UnionOfConvexClipPlaneSets, ): UnionOfConvexClipPlaneSets { result = result ? result : new UnionOfConvexClipPlaneSets(); for (const set of convexSets) @@ -182,9 +184,13 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { /** Returns the fractions of the segment that pass through the set region, as 1 dimensional pieces. */ public appendIntervalsFromSegment(segment: LineSegment3d, intervals: Segment1d[]) { for (const convexSet of this._convexSets) { - convexSet.announceClippedSegmentIntervals(0.0, 1.0, segment.point0Ref, segment.point1Ref, - (fraction0: number, fraction1: number) => - intervals.push(Segment1d.create(fraction0, fraction1))); + convexSet.announceClippedSegmentIntervals( + 0.0, + 1.0, + segment.point0Ref, + segment.point1Ref, + (fraction0: number, fraction1: number) => intervals.push(Segment1d.create(fraction0, fraction1)), + ); } } /** Apply `transform` to all the ConvexClipPlaneSet's. */ @@ -230,7 +236,11 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { * @returns Return true if any announcements are made. */ public announceClippedSegmentIntervals( - f0: number, f1: number, pointA: Point3d, pointB: Point3d, announce?: (fraction0: number, fraction1: number) => void, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + announce?: (fraction0: number, fraction1: number) => void, ): boolean { let numAnnounce = 0; for (const convexSet of this._convexSets) { @@ -266,7 +276,10 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { * @returns number of points. */ public computePlanePlanePlaneIntersectionsInAllConvexSets( - points: Point3d[] | undefined, rangeToExtend: Range3d | undefined, transform?: Transform, testContainment: boolean = true, + points: Point3d[] | undefined, + rangeToExtend: Range3d | undefined, + transform?: Transform, + testContainment: boolean = true, ): number { let n = 0; for (const convexSet of this._convexSets) { @@ -286,7 +299,7 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { * @param matrix matrix to apply */ public multiplyPlanesByMatrix4d(matrix: Matrix4d, invert: boolean = true, transpose: boolean = true): boolean { - if (invert) { // form inverse once here, reuse for all planes + if (invert) { // form inverse once here, reuse for all planes const inverse = matrix.createInverse(); if (!inverse) return false; @@ -354,7 +367,7 @@ export class UnionOfConvexClipPlaneSets implements Clipper, PolygonClipper { arrayCache.dropToCache(shard); } tempAB = carryForwardB; - carryForwardB = carryForwardA; // and that is empty + carryForwardB = carryForwardA; // and that is empty carryForwardA = tempAB; } while (undefined !== (shard = carryForwardA.pop())) { diff --git a/core/geometry/src/clipping/internalContexts/LineStringOffsetClipperContext.ts b/core/geometry/src/clipping/internalContexts/LineStringOffsetClipperContext.ts index b9e504006626..16b16abb09fd 100644 --- a/core/geometry/src/clipping/internalContexts/LineStringOffsetClipperContext.ts +++ b/core/geometry/src/clipping/internalContexts/LineStringOffsetClipperContext.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Geometry } from "../../Geometry"; +import { IndexedXYZCollection } from "../../geometry3d/IndexedXYZCollection"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { UnionOfConvexClipPlaneSets } from "../UnionOfConvexClipPlaneSets"; -import { ConvexClipPlaneSet } from "../ConvexClipPlaneSet"; import { ClipPlane } from "../ClipPlane"; -import { IndexedXYZCollection } from "../../geometry3d/IndexedXYZCollection"; +import { ConvexClipPlaneSet } from "../ConvexClipPlaneSet"; +import { UnionOfConvexClipPlaneSets } from "../UnionOfConvexClipPlaneSets"; /** * Class for building clip sets for offset regions. * @internal @@ -32,7 +32,10 @@ export class LineStringOffsetClipperContext { * @param closed indicates that first and last points are identical and need wrap logic. */ public static createUnit( - points: IndexedXYZCollection, index0: number, closed: boolean, xyOnly: boolean = true, + points: IndexedXYZCollection, + index0: number, + closed: boolean, + xyOnly: boolean = true, ): Vector3d | undefined { // pick two indices of active points, allowing for wrap if needed: // normally use index0 and index0 + 1 @@ -42,13 +45,16 @@ export class LineStringOffsetClipperContext { const last = points.length - 1; if (closed) { if (index0 < 0) { - k0 = last - 1; k1 = last; + k0 = last - 1; + k1 = last; } else if (index0 >= last) { - k0 = 0; k1 = 1; + k0 = 0; + k1 = 1; } } else { if (index0 === 0) { - k0 = 0; k1 = 1; + k0 = 0; + k1 = 1; } else if (k1 > last) { k0 = last - 1; k1 = last; @@ -63,12 +69,21 @@ export class LineStringOffsetClipperContext { return undefined; } private static createDirectedPlane( - basePoint: Point3d, vector: Vector3d, shift: number, normalScale: number, interior: boolean = false, + basePoint: Point3d, + vector: Vector3d, + shift: number, + normalScale: number, + interior: boolean = false, ): ClipPlane | undefined { return ClipPlane.createNormalAndPointXYZXYZ( - vector.x * normalScale, vector.y * normalScale, vector.z * normalScale, - basePoint.x + shift * vector.x, basePoint.y + shift * vector.y, basePoint.z + shift * vector.z, - interior, interior, + vector.x * normalScale, + vector.y * normalScale, + vector.z * normalScale, + basePoint.x + shift * vector.x, + basePoint.y + shift * vector.y, + basePoint.z + shift * vector.z, + interior, + interior, ); } /** @@ -173,8 +188,13 @@ export class LineStringOffsetClipperContext { const unitVectorA = this.createUnit(points, i - 1, closed); const unitVectorB = this.createUnit(points, i, closed); const unitVectorC = this.createUnit(points, i + 1, closed); - const clipSet = context.createOffsetFromSegment(points.getPoint3dAtUncheckedPointIndex(i), - points.getPoint3dAtUncheckedPointIndex(i + 1), unitVectorA, unitVectorB, unitVectorC); + const clipSet = context.createOffsetFromSegment( + points.getPoint3dAtUncheckedPointIndex(i), + points.getPoint3dAtUncheckedPointIndex(i + 1), + unitVectorA, + unitVectorB, + unitVectorC, + ); clipSet?.addZClipPlanes(false, z0, z1); if (clipSet) result.addConvexSet(clipSet); diff --git a/core/geometry/src/core-geometry.ts b/core/geometry/src/core-geometry.ts index 8a1f1757b01e..a9f7637a0c94 100644 --- a/core/geometry/src/core-geometry.ts +++ b/core/geometry/src/core-geometry.ts @@ -56,7 +56,6 @@ * * Point2dArray, Point3dArray, Point4dArray, Vector3dArray -- miscellaneous operations on arrays of 2d and 3d points. * * Interfaces * * GeometryHandler -- a double-dispatch protocol used for efficient implementation of algorithms that work on many geometry types. - * */ // doc:export class ArraysAndInterfacesDoc { } diff --git a/core/geometry/src/curve/Arc3d.ts b/core/geometry/src/curve/Arc3d.ts index d07ca6322568..92ef1a301637 100644 --- a/core/geometry/src/curve/Arc3d.ts +++ b/core/geometry/src/curve/Arc3d.ts @@ -155,7 +155,11 @@ export class EllipticalArcApproximationOptions { /** Clone the options. */ public clone(): EllipticalArcApproximationOptions { return new EllipticalArcApproximationOptions( - this.sampleMethod, this.numSamplesInQuadrant, this.maxError, this.remapFunction, this.forcePath, + this.sampleMethod, + this.numSamplesInQuadrant, + this.maxError, + this.remapFunction, + this.forcePath, ); } /** Method used to sample the elliptical arc. */ @@ -284,7 +288,7 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * Return a clone of the arc, with transform applied * @param transform */ - public cloneTransformed(transform: Transform): Arc3d { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): Arc3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -343,7 +347,12 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional preallocated result. */ public static createScaledXYColumns( - center: Point3d | undefined, matrix: Matrix3d, radius0: number, radius90: number, sweep?: AngleSweep, result?: Arc3d, + center: Point3d | undefined, + matrix: Matrix3d, + radius0: number, + radius90: number, + sweep?: AngleSweep, + result?: Arc3d, ): Arc3d { const vector0 = matrix.columnX(); const vector90 = matrix.columnY(); @@ -357,7 +366,10 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional preallocated result. */ public static createCenterNormalRadius( - center: Point3d | undefined, normal: Vector3d, radius: number, result?: Arc3d, + center: Point3d | undefined, + normal: Vector3d, + radius: number, + result?: Arc3d, ): Arc3d { const frame = Matrix3d.createRigidHeadsUp(normal); return Arc3d.createScaledXYColumns(center, frame, radius, radius, undefined, result); @@ -371,7 +383,11 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional preallocated result */ public static create( - center: Point3d | undefined, vector0: Vector3d, vector90: Vector3d, sweep?: AngleSweep, result?: Arc3d, + center: Point3d | undefined, + vector0: Vector3d, + vector90: Vector3d, + sweep?: AngleSweep, + result?: Arc3d, ): Arc3d { const normal = vector0.unitCrossProductWithDefault(vector90, 0, 0, 0); // normal will be 000 for degenerate case const matrix = Matrix3d.createColumns(vector0, vector90, normal); @@ -394,7 +410,11 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @returns elliptical arc, or undefined if construction impossible. */ public static createStartMiddleEnd( - start: XYAndZ, middle: XYAndZ, end: XYAndZ, sweep?: AngleSweep, result?: Arc3d, + start: XYAndZ, + middle: XYAndZ, + end: XYAndZ, + sweep?: AngleSweep, + result?: Arc3d, ): Arc3d | undefined { const center = Point3d.createAdd2Scaled(start, 0.5, end, 0.5); const vector0 = Vector3d.createStartEnd(center, start); @@ -419,7 +439,10 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * * If `tangentAtStart` is parallel to the line segment from `start` to `end`, return the line segment. */ public static createCircularStartTangentEnd( - start: Point3d, tangentAtStart: Vector3d, end: Point3d, result?: Arc3d, + start: Point3d, + tangentAtStart: Vector3d, + end: Point3d, + result?: Arc3d, ): Arc3d | LineSegment3d { // see itwinjs-core\core\geometry\internaldocs\Arc3d.md to clarify below algorithm const startToEnd = Vector3d.createStartEnd(start, end); @@ -455,7 +478,11 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param sweep angular range. If single `Angle` is given, start angle is at 0 degrees (the start point). */ public static createCircularStartTangentRadius( - start: Point3d, tangentAtStart: Vector3d, radius: number, upVector?: Vector3d, sweep?: Angle | AngleSweep, + start: Point3d, + tangentAtStart: Vector3d, + radius: number, + upVector?: Vector3d, + sweep?: Angle | AngleSweep, ): Arc3d | undefined { if (upVector === undefined) upVector = Vector3d.unitZ(); @@ -512,9 +539,15 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { if (z === undefined) z = this._center.z; return Arc3d.createXYZXYZXYZ( - this._center.x, this._center.y, z, - this._matrix.coffs[0], this._matrix.coffs[3], 0, - this._matrix.coffs[1], this._matrix.coffs[4], 0, + this._center.x, + this._center.y, + z, + this._matrix.coffs[0], + this._matrix.coffs[3], + 0, + this._matrix.coffs[1], + this._matrix.coffs[4], + 0, this._sweep, ); } @@ -524,13 +557,24 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional preallocated result */ public static createXYZXYZXYZ( - cx: number, cy: number, cz: number, - ux: number, uy: number, uz: number, - vx: number, vy: number, vz: number, - sweep?: AngleSweep, result?: Arc3d, + cx: number, + cy: number, + cz: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, + sweep?: AngleSweep, + result?: Arc3d, ): Arc3d { return Arc3d.create( - Point3d.create(cx, cy, cz), Vector3d.create(ux, uy, uz), Vector3d.create(vx, vy, vz), sweep, result, + Point3d.create(cx, cy, cz), + Vector3d.create(ux, uy, uz), + Vector3d.create(vx, vy, vz), + sweep, + result, ); } /** @@ -551,7 +595,10 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * If the points are colinear, assemble them into a linestring. */ public static createCircularStartMiddleEnd( - pointA: XYAndZ, pointB: XYAndZ, pointC: XYAndZ, result?: Arc3d, + pointA: XYAndZ, + pointB: XYAndZ, + pointC: XYAndZ, + result?: Arc3d, ): Arc3d | LineString3d { const vectorAB = Vector3d.createStartEnd(pointA, pointB); const vectorAC = Vector3d.createStartEnd(pointA, pointC); @@ -560,10 +607,16 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { const normal = vectorAB.sizedCrossProduct(vectorAC, Math.sqrt(Math.sqrt(ab2 * ac2))); if (normal) { const vectorToCenter = SmallSystem.linearSystem3d( - normal.x, normal.y, normal.z, - vectorAB.x, vectorAB.y, vectorAB.z, - vectorAC.x, vectorAC.y, vectorAC.z, - 0, // vectorToCenter DOT normal = 0 (ensure normal is perp to the plane of the 3 points) + normal.x, + normal.y, + normal.z, + vectorAB.x, + vectorAB.y, + vectorAB.z, + vectorAC.x, + vectorAC.y, + vectorAC.z, + 0, // vectorToCenter DOT normal = 0 (ensure normal is perp to the plane of the 3 points) 0.5 * ab2, // vectorToCenter DOT vectorAB = ab2 / 2 (ensure the projection of vectorToCenter on AB bisects AB) 0.5 * ac2, // vectorToCenter DOT vectorAC = ac2 / 2 (ensure the projection of vectorToCenter on AC bisects AC) ); @@ -577,7 +630,11 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { if (sweepAngle.radians < 0.0) sweepAngle.addMultipleOf2PiInPlace(1.0); return Arc3d.create( - center, vectorX, vectorY, AngleSweep.createStartEndRadians(0.0, sweepAngle.radians), result, + center, + vectorX, + vectorY, + AngleSweep.createStartEndRadians(0.0, sweepAngle.radians), + result, ); } } @@ -608,7 +665,10 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { public fractionAndRadialFractionToPoint(arcFraction: number, radialFraction: number, result?: Point3d): Point3d { const radians = this._sweep.fractionToRadians(arcFraction); return this._matrix.originPlusMatrixTimesXY( - this._center, radialFraction * Math.cos(radians), radialFraction * Math.sin(radians), result, + this._center, + radialFraction * Math.cos(radians), + radialFraction * Math.sin(radians), + result, ); } /** @@ -766,7 +826,7 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { if (numInterval < 4) numInterval += 3; else if (numInterval < 6) - numInterval += 2; // force extras for short arcs + numInterval += 2; // force extras for short arcs const pointA = Arc3d._workPointA; const pointB = Arc3d._workPointB; let chordSum = 0.0; @@ -788,7 +848,10 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * * Nonzero length line generates `CurveSearchStatus.success` or `CurveSearchStatus.stoppedAtBoundary` */ public override moveSignedDistanceFromFraction( - startFraction: number, signedDistance: number, allowExtension: false, result?: CurveLocationDetail, + startFraction: number, + signedDistance: number, + allowExtension: false, + result?: CurveLocationDetail, ): CurveLocationDetail { if (!this.isCircular) // suppress extension !!! return super.moveSignedDistanceFromFractionGeneric(startFraction, signedDistance, allowExtension, result); @@ -796,7 +859,12 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { const signedFractionMove = Geometry.conditionalDivideFraction(signedDistance, totalLength); if (signedFractionMove === undefined) { return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, startFraction, this.fractionToPoint(startFraction), 0.0, CurveSearchStatus.error); + this, + startFraction, + this.fractionToPoint(startFraction), + 0.0, + CurveSearchStatus.error, + ); } return CurveLocationDetail.createConditionalMoveSignedDistance( allowExtension, @@ -804,7 +872,8 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { startFraction, startFraction + signedFractionMove, signedDistance, - result); + result, + ); } /** * Return all radian angles where the ellipse tangent is perpendicular to the vector to a spacePoint. @@ -841,7 +910,9 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional preallocated result. */ public override closestPoint( - spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail, + spacePoint: Point3d, + extend: VariantCurveExtendParameter, + result?: CurveLocationDetail, ): CurveLocationDetail { result = CurveLocationDetail.create(this, result); const allRadians = this.allPerpendicularAngles(spacePoint, true, true); @@ -1006,7 +1077,8 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { */ public override rangeBetweenFractions(fraction0: number, fraction1: number, transform?: Transform): Range3d { const sweep = AngleSweep.createStartEndRadians( - this.sweep.fractionToRadians(fraction0), this.sweep.fractionToRadians(fraction1), + this.sweep.fractionToRadians(fraction0), + this.sweep.fractionToRadians(fraction1), ); const range = Range3d.create(); this.extendRangeInSweep(range, sweep, transform); @@ -1020,16 +1092,19 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @internal */ public getPlaneAltitudeSineCosinePolynomial( - plane: PlaneAltitudeEvaluator, result?: SineCosinePolynomial, + plane: PlaneAltitudeEvaluator, + result?: SineCosinePolynomial, ): SineCosinePolynomial { if (!result) result = new SineCosinePolynomial(0, 0, 0); // altitude function of angle t, given plane with origin o and unit normal n: // A(t) = (c + u cos(t) + v sin(t)) . n = (c-o).n + u.n cos(t) + v.n sin(t) // Note the different functions for computing dot product against a point vs. a vector! - result.set(plane.altitude(this._center), + result.set( + plane.altitude(this._center), plane.velocityXYZ(this._matrix.coffs[0], this._matrix.coffs[3], this._matrix.coffs[6]), - plane.velocityXYZ(this._matrix.coffs[1], this._matrix.coffs[4], this._matrix.coffs[7])); + plane.velocityXYZ(this._matrix.coffs[1], this._matrix.coffs[4], this._matrix.coffs[7]), + ); return result; } /** Create a new arc which is a unit circle in the xy-plane centered at the origin. */ @@ -1056,7 +1131,8 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { center: Point3d, radiusA: number, radiusB: number, - sweep: AngleSweep = AngleSweep.create360()): Arc3d { + sweep: AngleSweep = AngleSweep.create360(), + ): Arc3d { return new Arc3d(center.clone(), Matrix3d.createScale(radiusA, radiusB, 1.0), sweep.clone()); } /** @@ -1065,8 +1141,7 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param vector90 vector from center to ellipse point at 90 degrees in parameter space */ public setVector0Vector90(vector0: Vector3d, vector90: Vector3d) { - this._matrix.setColumns(vector0, vector90, - vector0.unitCrossProductWithDefault(vector90, 0, 0, 0), // normal will be 000 for degenerate case !!!; + this._matrix.setColumns(vector0, vector90, vector0.unitCrossProductWithDefault(vector90, 0, 0, 0) // normal will be 000 for degenerate case !!!; ); } /** Return the arc definition with rigid matrix form with axis radii */ @@ -1101,12 +1176,13 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { public toTransformedVectors( transform?: Transform, ): { center: Point3d, vector0: Vector3d, vector90: Vector3d, sweep: AngleSweep } { - return transform ? { - center: transform.multiplyPoint3d(this._center), - vector0: transform.multiplyVector(this._matrix.columnX()), - vector90: transform.multiplyVector(this._matrix.columnY()), - sweep: this.sweep.clone(), - } + return transform ? + { + center: transform.multiplyPoint3d(this._center), + vector0: transform.multiplyVector(this._matrix.columnX()), + vector90: transform.multiplyVector(this._matrix.columnY()), + sweep: this.sweep.clone(), + } : { center: this._center.clone(), vector0: this._matrix.columnX(), @@ -1160,7 +1236,11 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { }; } /** Test if this arc is almost equal to another GeometryQuery object */ - public override isAlmostEqual(otherGeometry: GeometryQuery, distanceTol: number = Geometry.smallMetricDistance, radianTol: number = Geometry.smallAngleRadians): boolean { + public override isAlmostEqual( + otherGeometry: GeometryQuery, + distanceTol: number = Geometry.smallMetricDistance, + radianTol: number = Geometry.smallAngleRadians, + ): boolean { if (otherGeometry instanceof Arc3d) { const other = otherGeometry; return this._center.isAlmostEqual(other._center, distanceTol) @@ -1231,7 +1311,8 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { const vector0 = this._matrix.multiplyXY(c, s); const vector90 = this._matrix.multiplyXY(-s, c); const newSweep = AngleSweep.createStartEndRadians( - this._sweep.startRadians - theta.radians, this._sweep.endRadians - theta.radians, + this._sweep.startRadians - theta.radians, + this._sweep.endRadians - theta.radians, ); const arcB = Arc3d.create(this._center.clone(), vector0, vector90, newSweep); return arcB; @@ -1283,7 +1364,6 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { * @param point1 second point of path (the point of inflection) * @param point2 third point of path (the point after the point of inflection) * @param radius arc radius - * */ public static createFilletArc(point0: Point3d, point1: Point3d, point2: Point3d, radius: number): ArcBlendData { const vector10 = Vector3d.createStartEnd(point1, point0); @@ -1297,9 +1377,9 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { // vector10, vector12, and bisector are UNIT vectors // bisector splits the angle between vector10 and vector12 const perpendicular = vector12.minus(vector10); - const perpendicularMagnitude = perpendicular.magnitude(); // == 2 * sin(theta) + const perpendicularMagnitude = perpendicular.magnitude(); // == 2 * sin(theta) const sinTheta = 0.5 * perpendicularMagnitude; - if (!Geometry.isSmallAngleRadians(sinTheta)) { // (for small theta, sinTheta is almost equal to theta) + if (!Geometry.isSmallAngleRadians(sinTheta)) { // (for small theta, sinTheta is almost equal to theta) const cosTheta = Math.sqrt(1 - sinTheta * sinTheta); const tanTheta = sinTheta / cosTheta; const alphaRadians = Math.acos(sinTheta); @@ -1324,15 +1404,18 @@ export class Arc3d extends CurvePrimitive implements BeJSONFunctions { /** Return the (signed!) area between (a fractional portion of) the arc and the chord between those points */ public areaToChordXY(fraction0: number, fraction1: number): number { let detJ = Geometry.crossProductXYXY( - this._matrix.coffs[0], this._matrix.coffs[3], - this._matrix.coffs[1], this._matrix.coffs[4]); + this._matrix.coffs[0], + this._matrix.coffs[3], + this._matrix.coffs[1], + this._matrix.coffs[4], + ); // areas in arc of unit circle with radians limits const radians0 = this._sweep.fractionToRadians(fraction0); const radians1 = this._sweep.fractionToRadians(fraction1); // const midRadians = 0.5 * (radians0 + radians1); const alpha = 0.5 * (radians1 - radians0); if (alpha < 0.0) - detJ = - detJ; + detJ = -detJ; const wedgeArea = Math.cos(alpha) * Math.sin(alpha); return (alpha - wedgeArea) * detJ; } diff --git a/core/geometry/src/curve/ConstructCurveBetweenCurves.ts b/core/geometry/src/curve/ConstructCurveBetweenCurves.ts index 30fd599b01bd..dee911d942dc 100644 --- a/core/geometry/src/curve/ConstructCurveBetweenCurves.ts +++ b/core/geometry/src/curve/ConstructCurveBetweenCurves.ts @@ -42,7 +42,8 @@ export class ConstructCurveBetweenCurves extends NullGeometryHandler { const segment1 = this._geometry1; return LineSegment3d.create( segment0.startPoint().interpolate(this._fraction, segment1.startPoint()), - segment0.endPoint().interpolate(this._fraction, segment1.endPoint())); + segment0.endPoint().interpolate(this._fraction, segment1.endPoint()), + ); } return undefined; } @@ -86,7 +87,6 @@ export class ConstructCurveBetweenCurves extends NullGeometryHandler { ls1.packedDerivatives.getVector3dAtCheckedVectorIndex(i, workVector1); ls.addDerivative(workVector0.interpolate(fraction, workVector1)); } - } return ls; } @@ -105,7 +105,8 @@ export class ConstructCurveBetweenCurves extends NullGeometryHandler { arc0.center.interpolate(this._fraction, arc1.center), arc0.vector0.interpolate(this._fraction, arc1.vector0), arc0.vector90.interpolate(this._fraction, arc1.vector90), - arc0.sweep.interpolate(this._fraction, arc1.sweep)); + arc0.sweep.interpolate(this._fraction, arc1.sweep), + ); } return undefined; } diff --git a/core/geometry/src/curve/CurveChainWithDistanceIndex.ts b/core/geometry/src/curve/CurveChainWithDistanceIndex.ts index 05a28fd0b56c..6fed0dd69457 100644 --- a/core/geometry/src/curve/CurveChainWithDistanceIndex.ts +++ b/core/geometry/src/curve/CurveChainWithDistanceIndex.ts @@ -124,7 +124,9 @@ export class PathFragment { */ public chainDistanceToAccurateChildFraction(chainDistance: number, allowExtrapolation?: boolean): number { const childDetail = this.childCurve.moveSignedDistanceFromFraction( - this.childFraction0, chainDistance - this.chainDistance0, allowExtrapolation ?? false, + this.childFraction0, + chainDistance - this.chainDistance0, + allowExtrapolation ?? false, ); return childDetail.fraction; } @@ -177,36 +179,42 @@ class DistanceIndexConstructionContext implements IStrokeHandler { this._fragments = []; } // ignore curve announcements -- they are repeated in stroke announcements - public startParentCurvePrimitive(_cp: CurvePrimitive) { } - public startCurvePrimitive(_cp: CurvePrimitive) { } - public endParentCurvePrimitive(_cp: CurvePrimitive) { } - public endCurvePrimitive(_cp: CurvePrimitive) { } - public announcePointTangent(_xyz: Point3d, _fraction: number, _tangent: Vector3d) { } + public startParentCurvePrimitive(_cp: CurvePrimitive) {} + public startCurvePrimitive(_cp: CurvePrimitive) {} + public endParentCurvePrimitive(_cp: CurvePrimitive) {} + public endCurvePrimitive(_cp: CurvePrimitive) {} + public announcePointTangent(_xyz: Point3d, _fraction: number, _tangent: Vector3d) {} public announceSegmentInterval( - cp: CurvePrimitive, point0: Point3d, point1: Point3d, numStrokes: number, fraction0: number, fraction1: number, + cp: CurvePrimitive, + point0: Point3d, + point1: Point3d, + numStrokes: number, + fraction0: number, + fraction1: number, ): void { const fragmentPoint0 = point0.clone(); const fragmentPoint1 = point1.clone(); let d0 = this._accumulatedDistance; if (numStrokes <= 1) { this._accumulatedDistance += point0.distance(point1); - this._fragments.push(new PathFragment(fraction0, fraction1, d0, this._accumulatedDistance, cp, - Range3d.create(fragmentPoint0, fragmentPoint1))); + this._fragments.push(new PathFragment(fraction0, fraction1, d0, this._accumulatedDistance, cp, Range3d.create(fragmentPoint0, fragmentPoint1))); } else { let f1; for (let i = 1, f0 = fraction0; i <= numStrokes; i++, f0 = f1) { f1 = Geometry.interpolate(fraction0, i / numStrokes, fraction1); point0.interpolate(f1, point1, fragmentPoint1); d0 = this._accumulatedDistance; - this._accumulatedDistance += (Math.abs(f1 - f0) * point0.distance(point1)); - this._fragments.push(new PathFragment(f0, f1, d0, this._accumulatedDistance, cp, - Range3d.create(fragmentPoint0, fragmentPoint1))); + this._accumulatedDistance += Math.abs(f1 - f0) * point0.distance(point1); + this._fragments.push(new PathFragment(f0, f1, d0, this._accumulatedDistance, cp, Range3d.create(fragmentPoint0, fragmentPoint1))); fragmentPoint0.setFrom(fragmentPoint1); } } } public announceIntervalForUniformStepStrokes( - cp: CurvePrimitive, numStrokes: number, fraction0: number, fraction1: number, + cp: CurvePrimitive, + numStrokes: number, + fraction0: number, + fraction1: number, ): void { let f1, d, d0; for (let i = 1, f0 = fraction0; i <= numStrokes; i++, f0 = f1) { @@ -304,7 +312,11 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * @param fractionB end fraction or chain detail * @param options how finely to stroke the path to create the distance index */ - public override clonePartialCurve(fractionA: number | CurveLocationDetail, fractionB: number | CurveLocationDetail, options?: StrokeOptions): CurveChainWithDistanceIndex | undefined { + public override clonePartialCurve( + fractionA: number | CurveLocationDetail, + fractionB: number | CurveLocationDetail, + options?: StrokeOptions, + ): CurveChainWithDistanceIndex | undefined { const haveDetailA = fractionA instanceof CurveLocationDetail; const haveDetailB = fractionB instanceof CurveLocationDetail; let chainFractionA = haveDetailA ? fractionA.fraction : fractionA; @@ -328,12 +340,19 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { const childCurveIndexB = this._path.childIndex(fragmentB.childCurve, true); if (undefined === childCurveIndexB) return undefined; - const childFractionA = haveDetailA && fractionA.childDetail ? fractionA.childDetail.fraction : fragmentA.chainDistanceToAccurateChildFraction(chainDistanceA, true); - const childFractionB = haveDetailB && fractionB.childDetail ? fractionB.childDetail.fraction : fragmentB.chainDistanceToAccurateChildFraction(chainDistanceB, true); + const childFractionA = haveDetailA && fractionA.childDetail + ? fractionA.childDetail.fraction + : fragmentA.chainDistanceToAccurateChildFraction(chainDistanceA, true); + const childFractionB = haveDetailB && fractionB.childDetail + ? fractionB.childDetail.fraction + : fragmentB.chainDistanceToAccurateChildFraction(chainDistanceB, true); // add a (possibly reversed) partial clone to newPath const newPath = Path.create(); const addPartialChild = ( - childCurve: CurvePrimitive, childFraction0: number, childFraction1: number, reversedClone: boolean, + childCurve: CurvePrimitive, + childFraction0: number, + childFraction1: number, + reversedClone: boolean, ): boolean => { if (childFraction0 === childFraction1) return false; @@ -429,7 +448,9 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * segment of a [[LineString3d]] child. If false, push only the [[LineString3d]]. */ public override collectCurvePrimitivesGo( - collectorArray: CurvePrimitive[], smallestPossiblePrimitives: boolean = false, explodeLineStrings: boolean = false, + collectorArray: CurvePrimitive[], + smallestPossiblePrimitives: boolean = false, + explodeLineStrings: boolean = false, ): void { if (smallestPossiblePrimitives) { for (const c of this._path.children) { @@ -468,9 +489,13 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { } /** Flatten CurveChainWithDistanceIndex children in the input chain. * @return cloned flattened CurveChain, or reference to the input chain if no nesting - */ + */ private static flattenNestedChains(chain: CurveChain): CurveChain { - if (-1 === chain.children.findIndex((child: CurvePrimitive) => { return child instanceof CurveChainWithDistanceIndex; })) + if ( + -1 === chain.children.findIndex((child: CurvePrimitive) => { + return child instanceof CurveChainWithDistanceIndex; + }) + ) return chain; const flatChain = chain.clone() as CurveChain; const flatChildren = flatChain.children.flatMap((child: CurvePrimitive) => { @@ -478,8 +503,7 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { return child.path.children; else return [child]; - }, - ); + }); flatChain.children.splice(0, Infinity, ...flatChildren); return flatChain; } @@ -489,7 +513,7 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * @param options how finely to stroke the path to create the distance index */ public static createCapture(path: CurveChain, options?: StrokeOptions): CurveChainWithDistanceIndex { - path = this.flattenNestedChains(path); // nested chains not allowed + path = this.flattenNestedChains(path); // nested chains not allowed const fragments = DistanceIndexConstructionContext.createPathFragmentIndex(path, options); return new CurveChainWithDistanceIndex(path, fragments); } @@ -629,7 +653,8 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * derivative's change. */ public fractionToPointAnd2Derivatives( - fraction: number, result?: Plane3dByOriginAndVectors, + fraction: number, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors | undefined { const distanceAlongPath = fraction * this._totalLength; const fragment = this.chainDistanceToFragment(distanceAlongPath, true)!; @@ -695,17 +720,28 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * has pointer to an additional detail for the child curve. */ public override moveSignedDistanceFromFraction( - startFraction: number, signedDistance: number, allowExtension: boolean, result?: CurveLocationDetail, + startFraction: number, + signedDistance: number, + allowExtension: boolean, + result?: CurveLocationDetail, ): CurveLocationDetail { const distanceA = startFraction * this._totalLength; const distanceB = distanceA + signedDistance; const fragmentB = this.chainDistanceToFragment(distanceB, true)!; const childDetail = fragmentB.childCurve.moveSignedDistanceFromFraction( - fragmentB.childFraction0, distanceB - fragmentB.chainDistance0, allowExtension, result?.childDetail, + fragmentB.childFraction0, + distanceB - fragmentB.chainDistance0, + allowExtension, + result?.childDetail, ); // local detail related to the child curve const endFraction = startFraction + (signedDistance / this._totalLength); const chainDetail = CurveLocationDetail.createConditionalMoveSignedDistance( - allowExtension, this, startFraction, endFraction, signedDistance, result, + allowExtension, + this, + startFraction, + endFraction, + signedDistance, + result, ); // global detail related to the curve chain chainDetail.childDetail = childDetail; return chainDetail; @@ -772,7 +808,9 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { CurveChainWithDistanceIndex._numTested++; const child = sortedFragment.childCurve; detailA = child.closestPoint( - spacePoint, sortedFragment === fragment0 ? extend0 : sortedFragment === fragment1 ? extend1 : false, detailA, + spacePoint, + sortedFragment === fragment0 ? extend0 : sortedFragment === fragment1 ? extend1 : false, + detailA, ); if (detailA && detailA.a < aMin) { aMin = detailA.a; @@ -850,7 +888,13 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { * @return the converted array * @internal */ - public static convertChildDetailToChainDetail(pairs: CurveLocationDetailPair[], index0: number, chainA?: CurveChainWithDistanceIndex, chainB?: CurveChainWithDistanceIndex, compressAdjacent?: boolean): CurveLocationDetailPair[] { + public static convertChildDetailToChainDetail( + pairs: CurveLocationDetailPair[], + index0: number, + chainA?: CurveChainWithDistanceIndex, + chainB?: CurveChainWithDistanceIndex, + compressAdjacent?: boolean, + ): CurveLocationDetailPair[] { for (let i = index0; i < pairs.length; ++i) { const childDetailPair = pairs[i]; if (chainA) { @@ -868,5 +912,4 @@ export class CurveChainWithDistanceIndex extends CurvePrimitive { pairs = CurveLocationDetailPair.removeAdjacentDuplicates(pairs, index0); return pairs; } - } diff --git a/core/geometry/src/curve/CurveCollection.ts b/core/geometry/src/curve/CurveCollection.ts index 179b4920aef6..c2562529daaf 100644 --- a/core/geometry/src/curve/CurveCollection.ts +++ b/core/geometry/src/curve/CurveCollection.ts @@ -29,8 +29,8 @@ import { LineString3d } from "./LineString3d"; import { ProxyCurve } from "./ProxyCurve"; import { StrokeOptions } from "./StrokeOptions"; -import type { Path } from "./Path"; import type { Loop } from "./Loop"; +import type { Path } from "./Path"; /** Note: CurveChain and BagOfCurves classes are located in this file to prevent circular dependency. */ @@ -124,7 +124,9 @@ export abstract class CurveCollection extends GeometryQuery { * of the Loop are pushed onto `results`. */ private collectCurvePrimitivesGo( - results: CurvePrimitive[], smallestPossiblePrimitives: boolean, explodeLinestrings: boolean = false, + results: CurvePrimitive[], + smallestPossiblePrimitives: boolean, + explodeLinestrings: boolean = false, ): void { if (this.children) { for (const child of this.children) { @@ -145,7 +147,9 @@ export abstract class CurveCollection extends GeometryQuery { * it recurses to its (otherwise hidden) children. */ public collectCurvePrimitives( - collectorArray?: CurvePrimitive[], smallestPossiblePrimitives: boolean = false, explodeLineStrings: boolean = false, + collectorArray?: CurvePrimitive[], + smallestPossiblePrimitives: boolean = false, + explodeLineStrings: boolean = false, ): CurvePrimitive[] { const results: CurvePrimitive[] = collectorArray === undefined ? [] : collectorArray; this.collectCurvePrimitivesGo(results, smallestPossiblePrimitives, explodeLineStrings); @@ -228,18 +232,20 @@ export abstract class CurveCollection extends GeometryQuery { * @param fraction fraction to use in `curve.fractionToPoint(fraction)` */ public static createCurveLocationDetailOnAnyCurvePrimitive( - source: GeometryQuery | undefined, fraction: number = 0.5, + source: GeometryQuery | undefined, + fraction: number = 0.5, ): CurveLocationDetail | undefined { if (!source) return undefined; if (source instanceof CurvePrimitive) { return CurveLocationDetail.createCurveEvaluatedFraction(source, fraction); - } else if (source instanceof CurveCollection && source.children !== undefined) + } else if (source instanceof CurveCollection && source.children !== undefined) { for (const child of source.children) { const detail = this.createCurveLocationDetailOnAnyCurvePrimitive(child, fraction); if (detail) return detail; } + } return undefined; } /** @@ -370,7 +376,10 @@ export abstract class CurveChain extends CurveCollection { } /** Evaluate an indexed curve at a fraction. Return as a CurveLocationDetail that indicates the primitive. */ public primitiveIndexAndFractionToCurveLocationDetailPointAndDerivative( - index: number, fraction: number, cyclic: boolean = false, result?: CurveLocationDetail, + index: number, + fraction: number, + cyclic: boolean = false, + result?: CurveLocationDetail, ): CurveLocationDetail | undefined { const primitive = this.cyclicCurvePrimitive(index, cyclic); if (primitive) { diff --git a/core/geometry/src/curve/CurveCurve.ts b/core/geometry/src/curve/CurveCurve.ts index 4c73a173bafa..cc998a25cbea 100644 --- a/core/geometry/src/curve/CurveCurve.ts +++ b/core/geometry/src/curve/CurveCurve.ts @@ -71,7 +71,10 @@ export class CurveCurve { * @returns array of intersections structured as CurveLocationDetailPair[] */ public static intersectionXYZPairs( - curveA: AnyCurve, extendA: boolean, curveB: AnyCurve, extendB: boolean, + curveA: AnyCurve, + extendA: boolean, + curveB: AnyCurve, + extendB: boolean, ): CurveLocationDetailPair[] { const handler = new CurveCurveIntersectXYZ(extendA, curveB, extendB); curveA.dispatchToGeometryHandler(handler); @@ -83,7 +86,8 @@ export class CurveCurve { * @param tolerance optional distance tolerance for coincidence */ public static allIntersectionsAmongPrimitivesXY( - primitives: CurvePrimitive[], tolerance: number = Geometry.smallMetricDistance, + primitives: CurvePrimitive[], + tolerance: number = Geometry.smallMetricDistance, ): CurveLocationDetailPair[] { const handler = new CurveCurveIntersectXY(undefined, false, undefined, false, tolerance); for (let i = 0; i < primitives.length; i++) { @@ -109,7 +113,9 @@ export class CurveCurve { * Close approaches further than this xy-distance are not returned. */ public static closeApproachProjectedXYPairs( - curveA: AnyCurve, curveB: AnyCurve, maxDistance: number, + curveA: AnyCurve, + curveB: AnyCurve, + maxDistance: number, ): CurveLocationDetailPair[] { const handler = new CurveCurveCloseApproachXY(curveB); handler.maxDistanceToAccept = maxDistance; diff --git a/core/geometry/src/curve/CurveExtendMode.ts b/core/geometry/src/curve/CurveExtendMode.ts index 51f93cc24c6f..ffdb97737be5 100644 --- a/core/geometry/src/curve/CurveExtendMode.ts +++ b/core/geometry/src/curve/CurveExtendMode.ts @@ -42,11 +42,9 @@ export class CurveExtendOptions { return param; } /** - * * * if fraction is between 0 and 1 return it unchanged. * * if fraction is less than 0 use the variant param to choose the fraction or 0 * * if fraction is greater than 1 use the variant param to choose the fraction or 1 - * */ public static correctFraction(extendParam: VariantCurveExtendParameter, fraction: number): number { if (fraction < 0) { @@ -85,7 +83,7 @@ export class CurveExtendOptions { } else if (mode1 !== CurveExtendMode.None) { if (fraction < 0.0) fraction += fractionPeriod; - } else { // both clamped !!!! + } else { // both clamped !!!! fraction = Geometry.clamp(fraction, 0, 1); } } diff --git a/core/geometry/src/curve/CurveFactory.ts b/core/geometry/src/curve/CurveFactory.ts index e789208ced16..7af2d2d93575 100644 --- a/core/geometry/src/curve/CurveFactory.ts +++ b/core/geometry/src/curve/CurveFactory.ts @@ -31,9 +31,9 @@ import { Cone } from "../solid/Cone"; import { RuledSweep } from "../solid/RuledSweep"; import { TorusPipe } from "../solid/TorusPipe"; import { Arc3d, ArcBlendData } from "./Arc3d"; -import { AnyCurve } from "./CurveTypes"; import { CurveChain } from "./CurveCollection"; import { CurvePrimitive } from "./CurvePrimitive"; +import { AnyCurve } from "./CurveTypes"; import { GeometryQuery } from "./GeometryQuery"; import { LineSegment3d } from "./LineSegment3d"; import { LineString3d } from "./LineString3d"; @@ -97,7 +97,14 @@ export interface MiteredSweepOptions { */ export class CurveFactory { /** (cautiously) construct and save a line segment between fractional positions. */ - private static addPartialSegment(path: Path, allowBackup: boolean, pointA: Point3d | undefined, pointB: Point3d | undefined, fraction0: number, fraction1: number) { + private static addPartialSegment( + path: Path, + allowBackup: boolean, + pointA: Point3d | undefined, + pointB: Point3d | undefined, + fraction0: number, + fraction1: number, + ) { if (allowBackup || (fraction1 > fraction0)) { if (pointA !== undefined && pointB !== undefined && !Geometry.isAlmostEqualNumber(fraction0, fraction1)) path.tryAddChild(LineSegment3d.create(pointA.interpolate(fraction0, pointB), pointA.interpolate(fraction1, pointB))); @@ -125,7 +132,11 @@ export class CurveFactory { * @param radius fillet radius or array of radii indexed to correspond to the points. * @param allowBackupAlongEdge true to allow edges to be created going "backwards" along edges if needed to create the blend. */ - public static createFilletsInLineString(points: LineString3d | IndexedXYZCollection | Point3d[], radius: number | number[], allowBackupAlongEdge: boolean = true): Path | undefined { + public static createFilletsInLineString( + points: LineString3d | IndexedXYZCollection | Point3d[], + radius: number | number[], + allowBackupAlongEdge: boolean = true, + ): Path | undefined { if (Array.isArray(points)) return this.createFilletsInLineString(new Point3dArrayCarrier(points), radius, allowBackupAlongEdge); if (points instanceof LineString3d) @@ -162,10 +173,12 @@ export class CurveFactory { // suppress arcs that have overlap with both neighbors or flood either neighbor .. for (let i = 1; i + 1 < n; i++) { const b = blendArray[i]; - if (b.fraction10 > 1.0 + if ( + b.fraction10 > 1.0 || b.fraction12 > 1.0 || 1.0 - b.fraction10 < blendArray[i - 1].fraction12 - || b.fraction12 > 1.0 - blendArray[i + 1].fraction10) { + || b.fraction12 > 1.0 - blendArray[i + 1].fraction10 + ) { b.fraction10 = 0.0; b.fraction12 = 0.0; blendArray[i].arc = undefined; @@ -185,7 +198,14 @@ export class CurveFactory { } */ } const path = Path.create(); - this.addPartialSegment(path, allowBackupAlongEdge, blendArray[0].point, blendArray[1].point, blendArray[0].fraction12, 1.0 - blendArray[1].fraction10); + this.addPartialSegment( + path, + allowBackupAlongEdge, + blendArray[0].point, + blendArray[1].point, + blendArray[0].fraction12, + 1.0 - blendArray[1].fraction10, + ); // add each path and successor edge ... for (let i = 1; i + 1 < points.length; i++) { const b0 = blendArray[i]; @@ -199,7 +219,7 @@ export class CurveFactory { /** Create a `Loop` with given xy corners and fixed z. * * The corners always proceed counter clockwise from lower left. * * If the radius is too large for the outer rectangle size, it is reduced to half of the the smaller x or y size. - */ + */ public static createRectangleXY(x0: number, y0: number, x1: number, y1: number, z: number = 0, filletRadius?: number): Loop { let radius = Geometry.correctSmallMetricDistance(filletRadius); const xMin = Math.min(x0, x1); @@ -208,7 +228,13 @@ export class CurveFactory { const yMax = Math.max(y0, y1); radius = Math.min(Math.abs(radius), 0.5 * (xMax - xMin), 0.5 * (yMax - yMin)); if (radius === 0.0) - return Loop.createPolygon([Point3d.create(xMin, yMin, z), Point3d.create(xMax, yMin, z), Point3d.create(xMax, yMax, z), Point3d.create(xMin, yMax, z), Point3d.create(xMin, yMin, z)]); + return Loop.createPolygon([ + Point3d.create(xMin, yMin, z), + Point3d.create(xMax, yMin, z), + Point3d.create(xMax, yMax, z), + Point3d.create(xMin, yMax, z), + Point3d.create(xMin, yMin, z), + ]); else { const vectorU = Vector3d.create(radius, 0, 0); const vectorV = Vector3d.create(0, radius, 0); @@ -254,14 +280,20 @@ export class CurveFactory { startB.direction.scaleInPlace(-1.0); if (endA.isAlmostEqual(startB)) { - arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians + sweepSign * arcB.sweep.sweepRadians); + arcA.sweep.setStartEndRadians( + arcA.sweep.startRadians, + arcA.sweep.startRadians + arcA.sweep.sweepRadians + sweepSign * arcB.sweep.sweepRadians, + ); return true; } // Also ok if negated tangent . .. if (allowReverse) { startB.direction.scaleInPlace(-1.0); if (endA.isAlmostEqual(startB)) { - arcA.sweep.setStartEndRadians(arcA.sweep.startRadians, arcA.sweep.startRadians + arcA.sweep.sweepRadians - sweepSign * arcB.sweep.sweepRadians); + arcA.sweep.setStartEndRadians( + arcA.sweep.startRadians, + arcA.sweep.startRadians + arcA.sweep.sweepRadians - sweepSign * arcB.sweep.sweepRadians, + ); return true; } } @@ -276,13 +308,18 @@ export class CurveFactory { * @param pathPoints * @param fractionForIntermediateNormal fractional position for surface normal used to create the section plane. */ - public static assembleArcChainOnEllipsoid(ellipsoid: Ellipsoid, pathPoints: GeodesicPathPoint[], fractionForIntermediateNormal: number = 0.5): Path { + public static assembleArcChainOnEllipsoid( + ellipsoid: Ellipsoid, + pathPoints: GeodesicPathPoint[], + fractionForIntermediateNormal: number = 0.5, + ): Path { const arcPath = Path.create(); for (let i = 0; i + 1 < pathPoints.length; i++) { const arc = ellipsoid.sectionArcWithIntermediateNormal( pathPoints[i].toAngles(), fractionForIntermediateNormal, - pathPoints[i + 1].toAngles()); + pathPoints[i + 1].toAngles(), + ); arcPath.tryAddChild(arc); } return arcPath; @@ -295,7 +332,6 @@ export class CurveFactory { for (const p of candidate) this.appendGeometryQueryArray(p, result); } - } /** @@ -403,16 +439,23 @@ export class CurveFactory { * @param options options for computation and output * @return array of sections, starting with `initialSection` projected along the first edge to the first plane. */ - public static createMiteredSweepSections(centerline: IndexedXYZCollection | Point3d[], initialSection: AnyCurve, options: MiteredSweepOptions): SectionSequenceWithPlanes | undefined { + public static createMiteredSweepSections( + centerline: IndexedXYZCollection | Point3d[], + initialSection: AnyCurve, + options: MiteredSweepOptions, + ): SectionSequenceWithPlanes | undefined { const sectionData: SectionSequenceWithPlanes = { sections: [], planes: [] }; const planes = PolylineOps.createBisectorPlanesForDistinctPoints(centerline, options.wrapIfPhysicallyClosed); if (planes !== undefined && planes.length > 1) { // Projection to target plane, constructing sweep direction from two given planes. // If successful, push the target plane and swept section to the output arrays and return the swept section. // If unsuccessful, leave the output arrays alone and return the input section. - const doSweepToPlane = function (edgePlane0: Plane3dByOriginAndUnitNormal, edgePlane1: Plane3dByOriginAndUnitNormal, + const doSweepToPlane = function( + edgePlane0: Plane3dByOriginAndUnitNormal, + edgePlane1: Plane3dByOriginAndUnitNormal, targetPlane: Plane3dByOriginAndUnitNormal, - section: AnyCurve) { + section: AnyCurve, + ) { const sweepVector = Vector3d.createStartEnd(edgePlane0.getOriginRef(), edgePlane1.getOriginRef()); const transform = Transform.createFlattenAlongVectorToPlane(sweepVector, targetPlane.getOriginRef(), targetPlane.getNormalRef()); if (transform === undefined) @@ -456,7 +499,11 @@ export class CurveFactory { * @param sweep angular range. If single `Angle` is given, start angle is at 0 degrees (the start point). */ public static createArcPointTangentRadius( - start: Point3d, tangentAtStart: Vector3d, radius: number, upVector?: Vector3d, sweep?: Angle | AngleSweep, + start: Point3d, + tangentAtStart: Vector3d, + radius: number, + upVector?: Vector3d, + sweep?: Angle | AngleSweep, ): Arc3d | undefined { return Arc3d.createCircularStartTangentRadius(start, tangentAtStart, radius, upVector, sweep); } @@ -488,24 +535,48 @@ export class CurveFactory { const frameA = Transform.createRefs(startPoint.clone(), axesA); // We know how much it has to turn, and but not the length or end radius. // make a spiral of referenceLength and scale it back to the junction line - const spiralARefLength = IntegratedSpiral3d.createFrom4OutOf5(spiralType, 0.0, undefined, - Angle.createRadians(0), Angle.createRadians(spiralTurnRadians), referenceLength, undefined, frameA); + const spiralARefLength = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0.0, + undefined, + Angle.createRadians(0), + Angle.createRadians(spiralTurnRadians), + referenceLength, + undefined, + frameA, + ); if (spiralARefLength) { const midPlanePerpendicularRadians = radiansAB + spiralTurnRadians; const midPlanePerpendicularVector = Vector3d.createPolar(1.0, Angle.createRadians(midPlanePerpendicularRadians)); const altitudeB = midPlanePerpendicularVector.dotProductStartEnd(startPoint, shoulderPoint); const altitudeSpiralEnd = midPlanePerpendicularVector.dotProductStartEnd(startPoint, spiralARefLength.endPoint()); const scaleFactor = altitudeB / altitudeSpiralEnd; - const spiralA = IntegratedSpiral3d.createFrom4OutOf5(spiralType, 0.0, undefined, - Angle.createRadians(0), Angle.createRadians(spiralTurnRadians), referenceLength * scaleFactor, undefined, frameA)!; + const spiralA = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0.0, + undefined, + Angle.createRadians(0), + Angle.createRadians(spiralTurnRadians), + referenceLength * scaleFactor, + undefined, + frameA, + )!; const distanceAB = vectorAB.magnitude(); const vectorBC = Vector3d.createStartEnd(shoulderPoint, targetPoint); vectorBC.scaleToLength(distanceAB, vectorBC); const pointC = shoulderPoint.plus(vectorBC); const axesC = Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createRadians(radiansBC + Math.PI)); const frameC = Transform.createRefs(pointC, axesC); - const spiralC = IntegratedSpiral3d.createFrom4OutOf5(spiralType, - 0, -spiralA.radius01.x1, Angle.zero(), undefined, spiralA.curveLength(), Segment1d.create(1, 0), frameC)!; + const spiralC = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + -spiralA.radius01.x1, + Angle.zero(), + undefined, + spiralA.curveLength(), + Segment1d.create(1, 0), + frameC, + )!; return [spiralA, spiralC]; } return undefined; @@ -535,8 +606,16 @@ export class CurveFactory { const spiralTurnRadians = 0.5 * lineTurnAngle.radians; const bisectorRadians = 0.5 * (Math.PI - lineTurnAngle.radians); const radiansCB = Math.atan2(-vectorBC.y, -vectorBC.x); - const spiralAB0 = IntegratedSpiral3d.createFrom4OutOf5(spiralType, 0, undefined, Angle.zero(), Angle.createRadians(spiralTurnRadians), - spiralLength, undefined, Transform.createIdentity()); + const spiralAB0 = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + undefined, + Angle.zero(), + Angle.createRadians(spiralTurnRadians), + spiralLength, + undefined, + Transform.createIdentity(), + ); if (spiralAB0) { const localEndPoint = spiralAB0.fractionToPoint(1); const distanceAB = pointA.distance(pointB); @@ -550,13 +629,29 @@ export class CurveFactory { const axesA = Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createRadians(radiansAB)); const frameAOrigin = pointA.interpolate(xFractionAB, pointB); const frameA = Transform.createRefs(frameAOrigin, axesA); - const spiralAB = IntegratedSpiral3d.createFrom4OutOf5(spiralType, 0, undefined, Angle.zero(), Angle.createRadians(spiralTurnRadians), - spiralLength, undefined, frameA)!; + const spiralAB = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + undefined, + Angle.zero(), + Angle.createRadians(spiralTurnRadians), + spiralLength, + undefined, + frameA, + )!; const axesB = Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createRadians(radiansCB)); const frameBOrigin = pointC.interpolate(xFractionCB, pointB); const frameB = Transform.createRefs(frameBOrigin, axesB); - const spiralBC = IntegratedSpiral3d.createFrom4OutOf5(spiralType, 0, undefined, Angle.zero(), Angle.createRadians(-spiralTurnRadians), - spiralLength, undefined, frameB)!; + const spiralBC = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + undefined, + Angle.zero(), + Angle.createRadians(-spiralTurnRadians), + spiralLength, + undefined, + frameB, + )!; return [spiralAB, spiralBC]; } } @@ -582,8 +677,10 @@ export class CurveFactory { lengthB: number, arcRadius: number, ): GeometryQuery[] | undefined { - const vectorAB = Vector3d.createStartEnd(pointA, pointB); vectorAB.z = 0; - const vectorCB = Vector3d.createStartEnd(pointC, pointB); vectorCB.z = 0; + const vectorAB = Vector3d.createStartEnd(pointA, pointB); + vectorAB.z = 0; + const vectorCB = Vector3d.createStartEnd(pointC, pointB); + vectorCB.z = 0; const unitAB = vectorAB.normalize(); const unitCB = vectorCB.normalize(); if (unitAB === undefined || unitCB === undefined) @@ -592,13 +689,29 @@ export class CurveFactory { const unitPerpCB = unitCB.unitPerpendicularXY(); const thetaABC = vectorAB.angleToXY(vectorCB); const sideA = Geometry.split3WaySign(thetaABC.radians, 1, -1, -1); - const sideB = - sideA; + const sideB = -sideA; const radiusA = sideA * Math.abs(arcRadius); const radiusB = sideB * Math.abs(arcRadius); - const spiralA = IntegratedSpiral3d.createFrom4OutOf5(spiralType, - 0, radiusA, Angle.zero(), undefined, lengthA, undefined, Transform.createIdentity())!; - const spiralB = IntegratedSpiral3d.createFrom4OutOf5(spiralType, - 0, radiusB, Angle.zero(), undefined, lengthB, undefined, Transform.createIdentity())!; + const spiralA = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + radiusA, + Angle.zero(), + undefined, + lengthA, + undefined, + Transform.createIdentity(), + )!; + const spiralB = IntegratedSpiral3d.createFrom4OutOf5( + spiralType, + 0, + radiusB, + Angle.zero(), + undefined, + lengthB, + undefined, + Transform.createIdentity(), + )!; const spiralEndA = spiralA.fractionToPointAndUnitTangent(1.0); const spiralEndB = spiralB.fractionToPointAndUnitTangent(1.0); // From the end of spiral, step away to arc center (and this is in local coordinates of each spiral) @@ -612,10 +725,17 @@ export class CurveFactory { const vectorA = Vector3d.createAdd2Scaled(unitAB, sA, unitPerpAB, tA); const vectorB = Vector3d.createAdd2Scaled(unitCB, sB, unitPerpCB, tB); const uv = Vector2d.create(); - if (SmallSystem.linearSystem2d( - unitAB.x, -unitCB.x, - unitAB.y, -unitCB.y, - vectorB.x - vectorA.x, vectorB.y - vectorA.y, uv)) { + if ( + SmallSystem.linearSystem2d( + unitAB.x, + -unitCB.x, + unitAB.y, + -unitCB.y, + vectorB.x - vectorA.x, + vectorB.y - vectorA.y, + uv, + ) + ) { const tangencyAB = pointB.plusScaled(unitAB, uv.x); const tangencyCB = pointB.plusScaled(unitCB, uv.y); const frameA = Transform.createOriginAndMatrixColumns(tangencyAB, unitAB, unitPerpAB, Vector3d.unitZ()); @@ -627,7 +747,7 @@ export class CurveFactory { rayB0.direction.scaleInPlace(-1.0); const sweep = rayA1.direction.angleToXY(rayB0.direction); if (radiusA < 0) - sweep.setRadians(- sweep.radians); + sweep.setRadians(-sweep.radians); const arc = CurveFactory.createArcPointTangentRadius(rayA1.origin, rayA1.direction, radiusA, undefined, sweep)!; return [spiralA, arc, spiralB]; } @@ -640,7 +760,9 @@ export class CurveFactory { * @param planeC */ public static planePlaneIntersectionRay( - planeA: PlaneAltitudeEvaluator, planeB: PlaneAltitudeEvaluator): Ray3d | undefined { + planeA: PlaneAltitudeEvaluator, + planeB: PlaneAltitudeEvaluator, + ): Ray3d | undefined { const altitudeA = planeA.altitudeXYZ(0, 0, 0); const altitudeB = planeB.altitudeXYZ(0, 0, 0); const normalAx = planeA.normalX(); @@ -653,16 +775,24 @@ export class CurveFactory { const normalCy = Geometry.crossProductXYXY(normalAz, normalAx, normalBz, normalBx); const normalCz = Geometry.crossProductXYXY(normalAx, normalAy, normalBx, normalBy); const rayOrigin = SmallSystem.linearSystem3d( - normalAx, normalAy, normalAz, - normalBx, normalBy, normalBz, - normalCx, normalCy, normalCz, - -altitudeA, -altitudeB, 0.0); + normalAx, + normalAy, + normalAz, + normalBx, + normalBy, + normalBz, + normalCx, + normalCy, + normalCz, + -altitudeA, + -altitudeB, + 0.0, + ); if (rayOrigin !== undefined) { return Ray3d.createXYZUVW(rayOrigin.x, rayOrigin.y, rayOrigin.z, normalCx, normalCy, normalCz); } return undefined; } - } /** diff --git a/core/geometry/src/curve/CurveLocationDetail.ts b/core/geometry/src/curve/CurveLocationDetail.ts index 231ea0139e57..d70fb0cb9f6a 100644 --- a/core/geometry/src/curve/CurveLocationDetail.ts +++ b/core/geometry/src/curve/CurveLocationDetail.ts @@ -198,7 +198,10 @@ export class CurveLocationDetail { } /** Create a new detail using CurvePrimitive pointer, fraction, and point coordinates. */ public static createCurveFractionPoint( - curve: CurvePrimitive | undefined, fraction: number, point: Point3d, result?: CurveLocationDetail, + curve: CurvePrimitive | undefined, + fraction: number, + point: Point3d, + result?: CurveLocationDetail, ): CurveLocationDetail { result = result ? result : new CurveLocationDetail(); result.curve = curve; @@ -212,7 +215,10 @@ export class CurveLocationDetail { } /** Create a new detail with only ray, fraction, and point. */ public static createRayFractionPoint( - ray: Ray3d, fraction: number, point: Point3d, result?: CurveLocationDetail, + ray: Ray3d, + fraction: number, + point: Point3d, + result?: CurveLocationDetail, ): CurveLocationDetail { result = result ? result : new CurveLocationDetail(); result.fraction = fraction; @@ -253,7 +259,7 @@ export class CurveLocationDetail { if (!allowExtension && !Geometry.isIn01(endFraction)) { // cap the movement at the endpoint if (endFraction < 0.0) { - a = - curve.curveLengthBetweenFractions(startFraction, 0.0); + a = -curve.curveLengthBetweenFractions(startFraction, 0.0); endFraction = 0.0; status = CurveSearchStatus.stoppedAtBoundary; } else if (endFraction > 1.0) { @@ -274,7 +280,9 @@ export class CurveLocationDetail { } /** Create with CurvePrimitive pointer and fraction for evaluation. */ public static createCurveEvaluatedFraction( - curve: CurvePrimitive, fraction: number, result?: CurveLocationDetail, + curve: CurvePrimitive, + fraction: number, + result?: CurveLocationDetail, ): CurveLocationDetail { result = result ? result : new CurveLocationDetail(); result.curve = curve; @@ -288,7 +296,9 @@ export class CurveLocationDetail { } /** Create with CurvePrimitive pointer and fraction for evaluation. */ public static createCurveEvaluatedFractionPointAndDerivative( - curve: CurvePrimitive, fraction: number, result?: CurveLocationDetail, + curve: CurvePrimitive, + fraction: number, + result?: CurveLocationDetail, ): CurveLocationDetail { result = result ? result : new CurveLocationDetail(); result.curve = curve; @@ -303,7 +313,10 @@ export class CurveLocationDetail { } /** Create with CurvePrimitive pointer and 2 fractions for evaluation. */ public static createCurveEvaluatedFractionFraction( - curve: CurvePrimitive, fraction0: number, fraction1: number, result?: CurveLocationDetail, + curve: CurvePrimitive, + fraction0: number, + fraction1: number, + result?: CurveLocationDetail, ): CurveLocationDetail { result = result ? result : new CurveLocationDetail(); result.curve = curve; @@ -344,7 +357,10 @@ export class CurveLocationDetail { * @returns true if the given distance is smaller (and hence this detail was updated.) */ public updateIfCloserCurveFractionPointDistance( - curve: CurvePrimitive, fraction: number, point: Point3d, a: number, + curve: CurvePrimitive, + fraction: number, + point: Point3d, + a: number, ): boolean { if (this.a < a) return false; @@ -383,7 +399,8 @@ export class CurveLocationDetail { * @param detailB second candidate */ public static chooseSmallerA( - detailA: CurveLocationDetail | undefined, detailB: CurveLocationDetail | undefined, + detailA: CurveLocationDetail | undefined, + detailB: CurveLocationDetail | undefined, ): CurveLocationDetail | undefined { if (detailA) { if (!detailB) @@ -393,7 +410,7 @@ export class CurveLocationDetail { return detailB; } /** Compare only the curve and fraction of this detail with `other`. */ - public isSameCurveAndFraction(other: CurveLocationDetail | {curve: CurvePrimitive, fraction: number}): boolean { + public isSameCurveAndFraction(other: CurveLocationDetail | { curve: CurvePrimitive, fraction: number }): boolean { return this.curve === other.curve && Geometry.isAlmostEqualNumber(this.fraction, other.fraction); } /** @@ -464,7 +481,9 @@ export class CurveLocationDetailPair { } /** Create a curve detail pair using references to two CurveLocationDetails */ public static createCapture( - detailA: CurveLocationDetail, detailB: CurveLocationDetail, result?: CurveLocationDetailPair, + detailA: CurveLocationDetail, + detailB: CurveLocationDetail, + result?: CurveLocationDetailPair, ): CurveLocationDetailPair { result = result ? result : new CurveLocationDetailPair(); result.detailA = detailA; @@ -476,13 +495,15 @@ export class CurveLocationDetailPair { * * optionally install in reversed positions */ public static createCaptureOptionalReverse( - detailA: CurveLocationDetail, detailB: CurveLocationDetail, reversed: boolean, result?: CurveLocationDetailPair, + detailA: CurveLocationDetail, + detailB: CurveLocationDetail, + reversed: boolean, + result?: CurveLocationDetailPair, ): CurveLocationDetailPair { result = result ? result : new CurveLocationDetailPair(); if (reversed) { result.detailA = detailA; result.detailB = detailB; - } else { result.detailA = detailA; result.detailB = detailB; @@ -520,12 +541,12 @@ export class CurveLocationDetailPair { if (!pair.detailA.hasFraction1 && !pair.detailB.hasFraction1) { if (pair.detailA.isSameCurveAndFraction(arr[i - 1].detailA)) { if (pair.detailB.isSameCurveAndFraction(arr[i - 1].detailB)) { - return []; // remove the i_th pair + return []; // remove the i_th pair } } } } - return [pair]; // preserve the i_th pair + return [pair]; // preserve the i_th pair }, ); } diff --git a/core/geometry/src/curve/CurveOps.ts b/core/geometry/src/curve/CurveOps.ts index a70a27a6f5ad..12c6d0ca51af 100644 --- a/core/geometry/src/curve/CurveOps.ts +++ b/core/geometry/src/curve/CurveOps.ts @@ -89,7 +89,11 @@ export class CurveOps { * @param gapTolerance distance to be treated as "effectively zero" when joining head-to-tail * @returns object with named chains, insideOffsets, outsideOffsets */ - public static collectInsideAndOutsideXYOffsets(fragments: AnyCurve[], offsetDistance: number, gapTolerance: number): { insideOffsets: AnyCurve[], outsideOffsets: AnyCurve[], chains?: AnyChain } { + public static collectInsideAndOutsideXYOffsets( + fragments: AnyCurve[], + offsetDistance: number, + gapTolerance: number, + ): { insideOffsets: AnyCurve[], outsideOffsets: AnyCurve[], chains?: AnyChain } { const collector = new MultiChainCollector(gapTolerance, gapTolerance); for (const s of fragments) { collector.captureCurve(s); @@ -119,7 +123,10 @@ export class CurveOps { * @param curve primitive to offset * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object */ - public static createSingleOffsetPrimitiveXY(curve: CurvePrimitive, offsetDistanceOrOptions: number | OffsetOptions): CurvePrimitive | CurvePrimitive[] | undefined { + public static createSingleOffsetPrimitiveXY( + curve: CurvePrimitive, + offsetDistanceOrOptions: number | OffsetOptions, + ): CurvePrimitive | CurvePrimitive[] | undefined { return CurveChainWireOffsetContext.createSingleOffsetPrimitiveXY(curve, offsetDistanceOrOptions); } /** @@ -130,7 +137,11 @@ export class CurveOps { * @param planeTolerance tolerance for considering a closed chain to be planar. If undefined, only create Path. If defined, create Loops for closed chains within tolerance of a plane. * @returns chains, possibly wrapped in a [[BagOfCurves]]. */ - public static collectChains(fragments: AnyCurve[], gapTolerance: number = Geometry.smallMetricDistance, planeTolerance?: number): AnyChain | undefined { + public static collectChains( + fragments: AnyCurve[], + gapTolerance: number = Geometry.smallMetricDistance, + planeTolerance?: number, + ): AnyChain | undefined { const collector = new MultiChainCollector(gapTolerance, planeTolerance); for (const s of fragments) { collector.captureCurve(s); @@ -146,7 +157,13 @@ export class CurveOps { * @param gapTolerance distance to be treated as "effectively zero" when assembling fragments head-to-tail. Also used for removing duplicate points in the stroked chains. * @param _planeTolerance unused, pass undefined */ - public static collectChainsAsLineString3d(fragments: AnyCurve[], announceChain: (chainPoints: LineString3d) => void, strokeOptions?: StrokeOptions, gapTolerance: number = Geometry.smallMetricDistance, _planeTolerance?: number) { + public static collectChainsAsLineString3d( + fragments: AnyCurve[], + announceChain: (chainPoints: LineString3d) => void, + strokeOptions?: StrokeOptions, + gapTolerance: number = Geometry.smallMetricDistance, + _planeTolerance?: number, + ) { const collector = new MultiChainCollector(gapTolerance); // no planarity tolerance needed for (const s of fragments) { collector.captureCurve(s); diff --git a/core/geometry/src/curve/CurvePrimitive.ts b/core/geometry/src/curve/CurvePrimitive.ts index d1a68d05b65f..fc8934cd3c2d 100644 --- a/core/geometry/src/curve/CurvePrimitive.ts +++ b/core/geometry/src/curve/CurvePrimitive.ts @@ -21,21 +21,21 @@ import { CurveLengthContext } from "./internalContexts/CurveLengthContext"; import { LineString3d } from "./LineString3d"; import type { AkimaCurve3d } from "../bspline/AkimaCurve3d"; -import type { Arc3d } from "./Arc3d"; import type { BezierCurve3d } from "../bspline/BezierCurve3d"; import type { BSplineCurve3d } from "../bspline/BSplineCurve"; -import type { Clipper } from "../clipping/ClipUtils"; -import type { CurveChainWithDistanceIndex } from "./CurveChainWithDistanceIndex"; -import type { DirectSpiral3d } from "./spiral/DirectSpiral3d"; -import type { IntegratedSpiral3d } from "./spiral/IntegratedSpiral3d"; import type { InterpolationCurve3d } from "../bspline/InterpolationCurve3d"; +import type { Clipper } from "../clipping/ClipUtils"; import type { IStrokeHandler } from "../geometry3d/GeometryHandler"; -import type { LineSegment3d } from "./LineSegment3d"; -import type { OffsetOptions } from "./OffsetOptions"; import type { Plane3dByOriginAndUnitNormal } from "../geometry3d/Plane3dByOriginAndUnitNormal"; import type { Plane3dByOriginAndVectors } from "../geometry3d/Plane3dByOriginAndVectors"; -import type { StrokeOptions } from "./StrokeOptions"; +import type { Arc3d } from "./Arc3d"; +import type { CurveChainWithDistanceIndex } from "./CurveChainWithDistanceIndex"; import type { VariantCurveExtendParameter } from "./CurveExtendMode"; +import type { LineSegment3d } from "./LineSegment3d"; +import type { OffsetOptions } from "./OffsetOptions"; +import type { DirectSpiral3d } from "./spiral/DirectSpiral3d"; +import type { IntegratedSpiral3d } from "./spiral/IntegratedSpiral3d"; +import type { StrokeOptions } from "./StrokeOptions"; /** * Describes the concrete type of a [[CurvePrimitive]]. Each type name maps to a specific subclass and can be used @@ -53,13 +53,32 @@ import type { VariantCurveExtendParameter } from "./CurveExtendMode"; * @see [[AnyCurvePrimitive]] for a union type that supports compile-time type narrowing. * @public */ -export type CurvePrimitiveType = "arc" | "lineSegment" | "lineString" | "bsplineCurve" | "bezierCurve" | "transitionSpiral" | "curveChainWithDistanceIndex" | "interpolationCurve" | "akimaCurve"; +export type CurvePrimitiveType = + | "arc" + | "lineSegment" + | "lineString" + | "bsplineCurve" + | "bezierCurve" + | "transitionSpiral" + | "curveChainWithDistanceIndex" + | "interpolationCurve" + | "akimaCurve"; /** * Union type for subclasses of [[CurvePrimitive]]. Specific subclasses can be discriminated at compile- or run-time * using [[CurvePrimitive.curvePrimitiveType]]. * @public */ -export type AnyCurvePrimitive = Arc3d | LineSegment3d | LineString3d | BSplineCurve3d | BezierCurve3d | DirectSpiral3d | IntegratedSpiral3d | CurveChainWithDistanceIndex | InterpolationCurve3d | AkimaCurve3d; +export type AnyCurvePrimitive = + | Arc3d + | LineSegment3d + | LineString3d + | BSplineCurve3d + | BezierCurve3d + | DirectSpiral3d + | IntegratedSpiral3d + | CurveChainWithDistanceIndex + | InterpolationCurve3d + | AkimaCurve3d; /** * Union type for a linear [[CurvePrimitive]]. * @public @@ -170,7 +189,8 @@ export abstract class CurvePrimitive extends GeometryQuery { * second derivatives are in fact derivatives of the parametric equation. */ public abstract fractionToPointAnd2Derivatives( - fraction: number, result?: Plane3dByOriginAndVectors + fraction: number, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors | undefined; /** * Construct a frenet frame: @@ -289,7 +309,11 @@ export abstract class CurvePrimitive extends GeometryQuery { * to any increase in size. */ public rangeBetweenFractionsByCount( - fraction0: number, fraction1: number, count: number, transform?: Transform, extrapolationFactor: number = 0.0, + fraction0: number, + fraction1: number, + count: number, + transform?: Transform, + extrapolationFactor: number = 0.0, ): Range3d { const range = Range3d.createNull(); const workPoint = Point3d.create(); @@ -317,7 +341,7 @@ export abstract class CurvePrimitive extends GeometryQuery { // excess value. same interior step, but shift to interval midpoints. const baseRange = range.clone(); const interiorCount1 = interiorCount + 1; - const localFraction0 = 0.5 / interiorCount1; // we only evaluate at new midpoints. + const localFraction0 = 0.5 / interiorCount1; // we only evaluate at new midpoints. const globalFractionStep = 2 * localFraction0 * (fraction1 - fraction0); // same as above, but avoids special logic for interiorCount = 0 evaluateSteps(fraction0 + globalFractionStep * 0.5, globalFractionStep, interiorCount1); range.extendWhenLarger(baseRange, extrapolationFactor); @@ -337,7 +361,10 @@ export abstract class CurvePrimitive extends GeometryQuery { * @param numInterval number of quadrature intervals */ public curveLengthWithFixedIntervalCountQuadrature( - fraction0: number, fraction1: number, numInterval: number, numGauss: number = 5, + fraction0: number, + fraction1: number, + numInterval: number, + numGauss: number = 5, ): number { if (fraction0 > fraction1) { const fSave = fraction0; @@ -384,7 +411,10 @@ export abstract class CurvePrimitive extends GeometryQuery { * member */ public moveSignedDistanceFromFraction( - startFraction: number, signedDistance: number, allowExtension: boolean, result?: CurveLocationDetail, + startFraction: number, + signedDistance: number, + allowExtension: boolean, + result?: CurveLocationDetail, ): CurveLocationDetail { const scale = this.getFractionToDistanceScale(); if (scale !== undefined) { @@ -394,7 +424,12 @@ export abstract class CurvePrimitive extends GeometryQuery { const signedFractionMove = Geometry.conditionalDivideFraction(signedDistance, totalLength); if (signedFractionMove === undefined) { return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, startFraction, this.fractionToPoint(startFraction), 0.0, CurveSearchStatus.error); + this, + startFraction, + this.fractionToPoint(startFraction), + 0.0, + CurveSearchStatus.error, + ); } return CurveLocationDetail.createConditionalMoveSignedDistance( allowExtension, @@ -426,10 +461,13 @@ export abstract class CurvePrimitive extends GeometryQuery { * @param result */ protected moveSignedDistanceFromFractionGeneric( - startFraction: number, signedDistance: number, allowExtension: boolean, result?: CurveLocationDetail, + startFraction: number, + signedDistance: number, + allowExtension: boolean, + result?: CurveLocationDetail, ): CurveLocationDetail { let limitFraction: number; - const slackFraction = 0.1; // slack to use when integration would otherwise have no room to work + const slackFraction = 0.1; // slack to use when integration would otherwise have no room to work if (signedDistance === 0.0) return CurveLocationDetail.createCurveEvaluatedFraction(this, startFraction, result); // no movement, just evaluate at startFraction if (signedDistance > 0.0) { @@ -495,7 +533,12 @@ export abstract class CurvePrimitive extends GeometryQuery { } if (numConverged > 1) return CurveLocationDetail.createConditionalMoveSignedDistance( - allowExtension, this, startFraction, fractionB, signedDistance, result, + allowExtension, + this, + startFraction, + fractionB, + signedDistance, + result, ); result = CurveLocationDetail.createCurveEvaluatedFraction(this, startFraction, result); result.curveSearchStatus = CurveSearchStatus.error; @@ -536,7 +579,9 @@ export abstract class CurvePrimitive extends GeometryQuery { * @returns Returns a CurveLocationDetail structure that holds the details of the close point. */ public closestPoint( - spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail, + spacePoint: Point3d, + extend: VariantCurveExtendParameter, + result?: CurveLocationDetail, ): CurveLocationDetail | undefined { const strokeHandler = new ClosestPointStrokeHandler(spacePoint, extend, result); this.emitStrokableParts(strokeHandler); @@ -719,7 +764,8 @@ export abstract class CurvePrimitive extends GeometryQuery { CurvePrimitive.installStrokeCountMap( this, StrokeCountMap.createWithCurvePrimitive(this, n, a, 0, a), - parentMap); + parentMap, + ); } /** * Evaluate strokes at fractions indicated in a StrokeCountMap. @@ -764,7 +810,9 @@ export abstract class CurvePrimitive extends GeometryQuery { * push only the [[LineString3d]]. */ public collectCurvePrimitivesGo( - collectorArray: CurvePrimitive[], _smallestPossiblePrimitives: boolean, _explodeLinestrings: boolean = false, + collectorArray: CurvePrimitive[], + _smallestPossiblePrimitives: boolean, + _explodeLinestrings: boolean = false, ): void { collectorArray.push(this); } @@ -777,7 +825,9 @@ export abstract class CurvePrimitive extends GeometryQuery { * it recurses to its (otherwise hidden) children. */ public collectCurvePrimitives( - collectorArray?: CurvePrimitive[], smallestPossiblePrimitives: boolean = false, explodeLinestrings: boolean = false, + collectorArray?: CurvePrimitive[], + smallestPossiblePrimitives: boolean = false, + explodeLinestrings: boolean = false, ): CurvePrimitive[] { const results: CurvePrimitive[] = collectorArray === undefined ? [] : collectorArray; this.collectCurvePrimitivesGo(results, smallestPossiblePrimitives, explodeLinestrings); @@ -791,7 +841,7 @@ export abstract class CurvePrimitive extends GeometryQuery { * @param offsetDistanceOrOptions offset distance (positive to left of the instance curve), or options object */ public abstract constructOffsetXY( - offsetDistanceOrOptions: number | OffsetOptions + offsetDistanceOrOptions: number | OffsetOptions, ): CurvePrimitive | CurvePrimitive[] | undefined; /** diff --git a/core/geometry/src/curve/CurveProcessor.ts b/core/geometry/src/curve/CurveProcessor.ts index 9eef24f6db66..96db358591ae 100644 --- a/core/geometry/src/curve/CurveProcessor.ts +++ b/core/geometry/src/curve/CurveProcessor.ts @@ -5,9 +5,9 @@ /** @packageDocumentation * @module Curve */ -import { AnyCurve } from "./CurveTypes"; import { BagOfCurves, CurveCollection } from "./CurveCollection"; import { CurvePrimitive } from "./CurvePrimitive"; +import { AnyCurve } from "./CurveTypes"; import { Loop } from "./Loop"; import { ParityRegion } from "./ParityRegion"; import { Path } from "./Path"; @@ -25,9 +25,9 @@ export abstract class RecursiveCurveProcessor { } /** process error content */ - public announceUnexpected(_data: AnyCurve, _indexInParent: number) { } + public announceUnexpected(_data: AnyCurve, _indexInParent: number) {} /** process a leaf primitive. */ - public announceCurvePrimitive(_data: CurvePrimitive, _indexInParent = -1): void { } + public announceCurvePrimitive(_data: CurvePrimitive, _indexInParent = -1): void {} /** announce a path (recurse to children) */ public announcePath(data: Path, _indexInParent: number = -1): void { @@ -86,16 +86,20 @@ export abstract class RecursiveCurveProcessorWithStack extends RecursiveCurvePro /** Push `data` onto the stack so its status is available during processing of children. * * Called when `data` is coming into scope. */ - public enter(data: CurveCollection) { this._stack.push(data); } + public enter(data: CurveCollection) { + this._stack.push(data); + } /** Pop the stack * * called when the top of the stack goes out of scope */ - public leave(): CurveCollection | undefined { return this._stack.pop(); } + public leave(): CurveCollection | undefined { + return this._stack.pop(); + } /** process error content */ - public override announceUnexpected(_data: AnyCurve, _indexInParent: number) { } + public override announceUnexpected(_data: AnyCurve, _indexInParent: number) {} /** process a leaf primitive. */ - public override announceCurvePrimitive(_data: CurvePrimitive, _indexInParent = -1): void { } + public override announceCurvePrimitive(_data: CurvePrimitive, _indexInParent = -1): void {} /** announce a path (recurse to children) */ public override announcePath(data: Path, indexInParent: number = -1): void { diff --git a/core/geometry/src/curve/CurveTypes.ts b/core/geometry/src/curve/CurveTypes.ts index b87571484c4e..6fd7e441474d 100644 --- a/core/geometry/src/curve/CurveTypes.ts +++ b/core/geometry/src/curve/CurveTypes.ts @@ -10,8 +10,8 @@ import type { BagOfCurves, CurveCollection } from "./CurveCollection"; import type { CurvePrimitive } from "./CurvePrimitive"; import type { Loop } from "./Loop"; -import type { Path } from "./Path"; import type { ParityRegion } from "./ParityRegion"; +import type { Path } from "./Path"; import type { UnionRegion } from "./UnionRegion"; /** diff --git a/core/geometry/src/curve/CurveWireMomentsXYZ.ts b/core/geometry/src/curve/CurveWireMomentsXYZ.ts index e46c856ab941..79a291419acf 100644 --- a/core/geometry/src/curve/CurveWireMomentsXYZ.ts +++ b/core/geometry/src/curve/CurveWireMomentsXYZ.ts @@ -14,9 +14,9 @@ import { IStrokeHandler } from "../geometry3d/GeometryHandler"; import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; import { MomentData } from "../geometry4d/MomentData"; import { GaussMapper } from "../numerics/Quadrature"; -import { AnyCurve } from "./CurveTypes"; import { CurveCollection } from "./CurveCollection"; import { CurvePrimitive } from "./CurvePrimitive"; +import { AnyCurve } from "./CurveTypes"; /** * Class to visit curve primitives and accumulate wire moment integrations. @@ -31,24 +31,27 @@ export class CurveWireMomentsXYZ implements IStrokeHandler { this._activeMomentData.needOrigin = true; this._gaussMapper = new GaussMapper(numGaussPoints); } - public get momentData(): MomentData { return this._activeMomentData; } + public get momentData(): MomentData { + return this._activeMomentData; + } - public startParentCurvePrimitive(_cp: CurvePrimitive) { } - public startCurvePrimitive(_cp: CurvePrimitive) { } - public endCurvePrimitive(_cp: CurvePrimitive) { } - public endParentCurvePrimitive(_cp: CurvePrimitive) { } + public startParentCurvePrimitive(_cp: CurvePrimitive) {} + public startCurvePrimitive(_cp: CurvePrimitive) {} + public endCurvePrimitive(_cp: CurvePrimitive) {} + public endParentCurvePrimitive(_cp: CurvePrimitive) {} public announceIntervalForUniformStepStrokes( cp: CurvePrimitive, numStrokes: number, fraction0: number, - fraction1: number): void { + fraction1: number, + ): void { this.startCurvePrimitive(cp); if (numStrokes < 1) numStrokes = 1; const df = 1.0 / numStrokes; let scaleFactor, fraction; for (let i = 1; i <= numStrokes; i++) { const fractionA = Geometry.interpolate(fraction0, (i - 1) * df, fraction1); - const fractionB = i === numStrokes ? fraction1 : Geometry.interpolate(fraction0, (i) * df, fraction1); + const fractionB = i === numStrokes ? fraction1 : Geometry.interpolate(fraction0, i * df, fraction1); const numGauss = this._gaussMapper.mapXAndW(fractionA, fractionB); for (let k = 0; k < numGauss; k++) { fraction = this._gaussMapper.gaussX[k]; @@ -65,7 +68,8 @@ export class CurveWireMomentsXYZ implements IStrokeHandler { point1: Point3d, _numStrokes: number, _fraction0: number, - _fraction1: number): void { + _fraction1: number, + ): void { this._activeMomentData.accumulateLineMomentsXYZ(point0, point1); } public announcePointTangent(_xyz: Point3d, _fraction: number, _tangent: Vector3d): void { diff --git a/core/geometry/src/curve/LineSegment3d.ts b/core/geometry/src/curve/LineSegment3d.ts index 87a24a4eb359..ff1f8f2b4e71 100644 --- a/core/geometry/src/curve/LineSegment3d.ts +++ b/core/geometry/src/curve/LineSegment3d.ts @@ -100,12 +100,18 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { } /** Return a (clone of) the start point (This is NOT a reference to the stored start point) */ public override startPoint(result?: Point3d): Point3d { - if (result) { result.setFrom(this._point0); return result; } + if (result) { + result.setFrom(this._point0); + return result; + } return this._point0.clone(); } /** Return a (clone of) the end point (This is NOT a reference to the stored end point) */ public override endPoint(result?: Point3d): Point3d { - if (result) { result.setFrom(this._point1); return result; } + if (result) { + result.setFrom(this._point1); + return result; + } return this._point1.clone(); } /** Return the point and derivative vector at fractional position along the line segment. */ @@ -133,7 +139,7 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { return LineSegment3d.create(this._point0, this._point1); } /** Clone and apply transform to the clone. */ - public cloneTransformed(transform: Transform): LineSegment3d { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): LineSegment3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -141,7 +147,7 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { /** Create with start and end points. The point contents are cloned into the LineSegment3d. */ public static create(point0: Point3d, point1: Point3d, result?: LineSegment3d): LineSegment3d { if (result) { - result.set(point0, point1); // and this will clone them !! + result.set(point0, point1); // and this will clone them !! return result; } return new LineSegment3d(point0.clone(), point1.clone()); @@ -177,7 +183,13 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { * @param result optional existing LineSegment to be reinitialized. */ public static createXYZXYZ( - x0: number, y0: number, z0: number, x1: number, y1: number, z1: number, result?: LineSegment3d, + x0: number, + y0: number, + z0: number, + x1: number, + y1: number, + z1: number, + result?: LineSegment3d, ): LineSegment3d { if (result) { result._point0.set(x0, y0, z0); @@ -211,7 +223,9 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { * @returns detail, with `a` field set to the distance from `spacePoint` to the closest point */ public override closestPoint( - spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail, + spacePoint: Point3d, + extend: VariantCurveExtendParameter, + result?: CurveLocationDetail, ): CurveLocationDetail { let fraction = spacePoint.fractionOfProjectionToLine(this._point0, this._point1, 0.0); fraction = CurveExtendOptions.correctFraction(extend, fraction); @@ -242,7 +256,9 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { const unboundedFractions = Vector2d.create(); if (result === undefined) result = CurveLocationDetailPair.createCapture(CurveLocationDetail.create(), CurveLocationDetail.create()); - if (SmallSystem.lineSegment3dClosestApproachUnbounded(segmentA._point0, segmentA._point1, segmentB._point0, segmentB._point1, unboundedFractions)) { + if ( + SmallSystem.lineSegment3dClosestApproachUnbounded(segmentA._point0, segmentA._point1, segmentB._point0, segmentB._point1, unboundedFractions) + ) { // There is a simple approach between the unbounded segments. Maybe its a really easy case ... const fractionA = CurveExtendOptions.correctFraction(extendA, unboundedFractions.x); const fractionB = CurveExtendOptions.correctFraction(extendB, unboundedFractions.y); @@ -387,8 +403,10 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { } else if (json.startPoint && json.endPoint) { // {startPoint:json point, endPoint:json point} this._point0.setFromJSON(json.startPoint); this._point1.setFromJSON(json.endPoint); - } else if (Array.isArray(json) - && json.length > 1) { // [json point, json point] + } else if ( + Array.isArray(json) + && json.length > 1 + ) { // [json point, json point] this._point0.setFromJSON(json[0]); this._point1.setFromJSON(json[1]); } @@ -454,7 +472,10 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { */ public override announceClipIntervals(clipper: Clipper, announce?: AnnounceNumberNumberCurvePrimitive): boolean { return clipper.announceClippedSegmentIntervals( - 0.0, 1.0, this._point0, this._point1, + 0.0, + 1.0, + this._point0, + this._point1, announce ? (fraction0: number, fraction1: number) => announce(fraction0, fraction1, this) : undefined, ); } @@ -498,7 +519,8 @@ export class LineSegment3d extends CurvePrimitive implements BeJSONFunctions { offsetVec.rotate90CCWXY(offsetVec); const offsetDist = OffsetOptions.getOffsetDistance(offsetDistanceOrOptions); return LineSegment3d.create( - this._point0.plusScaled(offsetVec, offsetDist), this._point1.plusScaled(offsetVec, offsetDist), + this._point0.plusScaled(offsetVec, offsetDist), + this._point1.plusScaled(offsetVec, offsetDist), ); } return undefined; diff --git a/core/geometry/src/curve/LineString3d.ts b/core/geometry/src/curve/LineString3d.ts index 9d2f6aea71d6..5655337b1b43 100644 --- a/core/geometry/src/curve/LineString3d.ts +++ b/core/geometry/src/curve/LineString3d.ts @@ -160,7 +160,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { this._points = new GrowableXYZArray(); } /** Clone this linestring and apply the transform to the clone points. */ - public cloneTransformed(transform: Transform): LineString3d { // we know tryTransformInPlace succeeds. + public cloneTransformed(transform: Transform): LineString3d { // we know tryTransformInPlace succeeds. const c = this.clone(); c.tryTransformInPlace(transform); return c; @@ -189,7 +189,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { const distance = xyz.distanceIndexIndex(0, xyz.length - 1); if (distance !== undefined && distance !== 0.0) { if (Geometry.isSameCoordinate(0, distance)) { - xyz.pop(); // nonzero but small distance -- to be replaced by point 0 exactly. + xyz.pop(); // nonzero but small distance -- to be replaced by point 0 exactly. const xyzA = xyz.front(); xyz.push(xyzA!); } @@ -400,12 +400,15 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * is outside circle (radius to edges) */ public static createRegularPolygonXY( - center: Point3d, edgeCount: number, radius: number, radiusToVertices: boolean = true, + center: Point3d, + edgeCount: number, + radius: number, + radiusToVertices: boolean = true, ): LineString3d { if (edgeCount < 3) edgeCount = 3; const ls = LineString3d.create(); - const i0 = radiusToVertices ? 0 : -1; // offset to make first vector (radius,0,0) + const i0 = radiusToVertices ? 0 : -1; // offset to make first vector (radius,0,0) const radiansStep = Math.PI / edgeCount; let c; let s; @@ -511,7 +514,9 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * * See `LineString3d.setFromJSON ()` for remarks on `json` structure. */ public static fromJSON(json?: any): LineString3d { - const ls = new LineString3d(); ls.setFromJSON(json); return ls; + const ls = new LineString3d(); + ls.setFromJSON(json); + return ls; } /** * Evaluate a point a fractional position along this linestring. @@ -619,7 +624,8 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { segmentIndex = 0; else if (globalFraction >= 1) segmentIndex = numSegment - 1; - else // globalFraction in (0,1) + // globalFraction in (0,1) + else segmentIndex = Math.floor(scaledGlobalFraction); return { index: segmentIndex, fraction: scaledGlobalFraction - segmentIndex }; } @@ -644,7 +650,8 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { if (n === 2) return Transform.createRefs( this._points.interpolate(0, fraction, 1), - Matrix3d.createRigidHeadsUp(this._points.vectorIndexIndex(0, 1)!, AxisOrder.XYZ)); + Matrix3d.createRigidHeadsUp(this._points.vectorIndexIndex(0, 1)!, AxisOrder.XYZ), + ); /** 3 or more points. */ const numSegment = n - 1; const df = 1.0 / numSegment; @@ -665,13 +672,13 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { // tricky stuff to handle colinear points. But if vectorA is zero it is still a mess . .. const normal = Vector3d.create(); const workVector = Vector3d.create(); - if (baseIndex === 0) { // only look forward + if (baseIndex === 0) { // only look forward accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex + 1, 1, 1.0, normal, workVector); } else if (baseIndex + 2 >= n) { // only look back accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex - 1, -1, 1.0, normal, workVector); } else { - accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex - 1, -1, (1.0 - localFraction), normal, workVector); - accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex + 1, 1, (localFraction), normal, workVector); + accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex - 1, -1, 1.0 - localFraction, normal, workVector); + accumulateGoodUnitPerpendicular(this._points, vectorA, baseIndex + 1, 1, localFraction, normal, workVector); } const matrix = Matrix3d.createRigidFromColumns(normal, vectorA, AxisOrder.ZXY); if (matrix) @@ -805,11 +812,14 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * @param result */ public override moveSignedDistanceFromFraction( - startFraction: number, signedDistance: number, allowExtension: false, result?: CurveLocationDetail, + startFraction: number, + signedDistance: number, + allowExtension: false, + result?: CurveLocationDetail, ): CurveLocationDetail { const numSegments = this._points.length - 1; const scaledFraction = startFraction * numSegments; - let leftPointIndex = Geometry.restrictToInterval(Math.floor(scaledFraction), 0, numSegments - 1); // lower point index on active segment. + let leftPointIndex = Geometry.restrictToInterval(Math.floor(scaledFraction), 0, numSegments - 1); // lower point index on active segment. const localFraction = scaledFraction - leftPointIndex; const point0 = this._points.interpolate(leftPointIndex, localFraction, leftPointIndex + 1, LineString3d._workPointA)!; const point1 = LineString3d._workPointB; @@ -821,15 +831,24 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { this._points.getPoint3dAtCheckedPointIndex(leftPointIndex, point1); if (context.announcePoint(point1, leftPointIndex / numSegments)) return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, context.fraction0, context.point0, signedDistance, CurveSearchStatus.success, result, + this, + context.fraction0, + context.point0, + signedDistance, + CurveSearchStatus.success, + result, ); } // fall through for extrapolation from final segment if (allowExtension) - context.announceExtrapolation(this._points, numSegments - 1, numSegments, - (numSegments - 1) / numSegments, 1.0); + context.announceExtrapolation(this._points, numSegments - 1, numSegments, (numSegments - 1) / numSegments, 1.0); return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, context.fraction0, context.point0, signedDistance, context.distanceStatus(), result, + this, + context.fraction0, + context.point0, + signedDistance, + context.distanceStatus(), + result, ); } else { // (moving backwards) if (localFraction <= 0.0) @@ -838,19 +857,31 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { this._points.getPoint3dAtCheckedPointIndex(leftPointIndex, point1); if (context.announcePoint(point1, leftPointIndex / numSegments)) return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, context.fraction0, context.point0, signedDistance, CurveSearchStatus.success, result, + this, + context.fraction0, + context.point0, + signedDistance, + CurveSearchStatus.success, + result, ); } // fall through for backward extrapolation from initial segment if (allowExtension) context.announceExtrapolation(this._points, 1, 0, 1.0 / numSegments, 0.0); return CurveLocationDetail.createCurveFractionPointDistanceCurveSearchStatus( - this, context.fraction0, context.point0, -context.distance0, context.distanceStatus(), result, + this, + context.fraction0, + context.point0, + -context.distance0, + context.distanceStatus(), + result, ); } } /** Sum lengths of segments in the linestring. (This is a true length.) */ - public quickLength(): number { return this.curveLength(); } + public quickLength(): number { + return this.curveLength(); + } /** * Compute and normalize cross product among 3 points on the linestring. * * Essentially 3 random points are used to form the cross product. @@ -872,7 +903,9 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { } /** Find the point on the linestring (including its segment interiors) that is closest to spacePoint. */ public override closestPoint( - spacePoint: Point3d, extend: VariantCurveExtendParameter, result?: CurveLocationDetail, + spacePoint: Point3d, + extend: VariantCurveExtendParameter, + result?: CurveLocationDetail, ): CurveLocationDetail { result = CurveLocationDetail.create(this, result); const extend0 = CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(extend, 0); @@ -887,7 +920,8 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { let d = 0; for (let i = 1; i < numPoints; i++) { segmentFraction = spacePoint.fractionOfProjectionToLine( - this._points.getPoint3dAtUncheckedPointIndex(i - 1), this._points.getPoint3dAtUncheckedPointIndex(i), + this._points.getPoint3dAtUncheckedPointIndex(i - 1), + this._points.getPoint3dAtUncheckedPointIndex(i), ); if (segmentFraction < 0) { if (!extend0 || i > 1) @@ -901,7 +935,10 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { d = result.pointQ.distance(spacePoint); if (d < result.a) { result.setFP( - this.segmentIndexAndLocalFractionToGlobalFraction(i - 1, segmentFraction), result.pointQ, undefined, d, + this.segmentIndexAndLocalFractionToGlobalFraction(i - 1, segmentFraction), + result.pointQ, + undefined, + d, ); } } @@ -915,13 +952,17 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { } /** Push a hit, fixing up the prior entry if needed. */ private static pushVertexHit( - result: CurveLocationDetail[], counter: number, cp: CurvePrimitive, fraction: number, point: Point3d, + result: CurveLocationDetail[], + counter: number, + cp: CurvePrimitive, + fraction: number, + point: Point3d, ): void { const detail = CurveLocationDetail.createCurveFractionPoint(cp, fraction, point); result.push(detail); if (counter === 0) { detail.setIntervalRole(CurveIntervalRole.isolatedAtVertex); - } else if (counter === 1) { // last entry must be isolatedAtVertex !!! + } else if (counter === 1) { // last entry must be isolatedAtVertex !!! result[result.length - 2].setIntervalRole(CurveIntervalRole.intervalStart); detail.setIntervalRole(CurveIntervalRole.intervalEnd); } else { @@ -953,7 +994,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { if (hB === 0.0) LineString3d.pushVertexHit(result, numConsecutiveZero++, this, i / divisor, pointB); else { - if (hA * hB < 0.0) { // at point0, hA=0 will keep us out of here . .. + if (hA * hB < 0.0) { // at point0, hA=0 will keep us out of here . .. segmentFraction = hA / (hA - hB); // this division is safe because the signs are different. pointA.interpolate(segmentFraction, pointB, pointC); const detail = CurveLocationDetail.createCurveFractionPoint(this, (i - 1 + segmentFraction) / divisor, pointC); @@ -1036,7 +1077,6 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { this._points.push(ray.origin); if (this._derivatives) this._derivatives.push(ray.direction); - } else { const point = curve.fractionToPoint(fraction, LineString3d._workPointA); if (this._fractions) @@ -1088,7 +1128,11 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * @param include01 if false, points at fraction0 and fraction1 are omitted. */ public appendFractionalStrokePoints( - curve: CurvePrimitive, numStrokes: number, fraction0: number = 0, fraction1: number = 1, include01: boolean = true, + curve: CurvePrimitive, + numStrokes: number, + fraction0: number = 0, + fraction1: number = 1, + include01: boolean = true, ): void { let i0 = 1; let i1 = numStrokes - 1; @@ -1164,16 +1208,27 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { if (options && options.hasMaxEdgeLength) { for (let i = 1; i < n; i++) { const numStroke = options.applyMaxEdgeLength( - 1, this._points.getPoint3dAtUncheckedPointIndex(i - 1).distance(this._points.getPoint3dAtUncheckedPointIndex(i)), + 1, + this._points.getPoint3dAtUncheckedPointIndex(i - 1).distance(this._points.getPoint3dAtUncheckedPointIndex(i)), ); handler.announceSegmentInterval( - this, this._points.getPoint3dAtUncheckedPointIndex(i - 1), this._points.getPoint3dAtUncheckedPointIndex(i), numStroke, (i - 1) * df, i * df, + this, + this._points.getPoint3dAtUncheckedPointIndex(i - 1), + this._points.getPoint3dAtUncheckedPointIndex(i), + numStroke, + (i - 1) * df, + i * df, ); } } else { for (let i = 1; i < n; i++) { handler.announceSegmentInterval( - this, this._points.getPoint3dAtUncheckedPointIndex(i - 1), this._points.getPoint3dAtUncheckedPointIndex(i), 1, (i - 1) * df, i * df, + this, + this._points.getPoint3dAtUncheckedPointIndex(i - 1), + this._points.getPoint3dAtUncheckedPointIndex(i), + 1, + (i - 1) * df, + i * df, ); } } @@ -1251,7 +1306,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { } return status; } - private static _indexPoint = Point3d.create(); // private point for addResolvedPoint + private static _indexPoint = Point3d.create(); // private point for addResolvedPoint /** @param fraction used to interpolate between points at index and index + 1 */ private addResolvedPoint(index: number, fraction: number, dest: GrowableXYZArray) { const n = this._points.length; @@ -1293,7 +1348,7 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { if (fractionB > 1) fractionB = 1; } - let index0, index1: number; // range of original vertices to copy into clone + let index0, index1: number; // range of original vertices to copy into clone const localA = this.globalFractionToSegmentIndexAndLocalFraction(fractionA); const localB = this.globalFractionToSegmentIndexAndLocalFraction(fractionB); if (fractionA < 0) { @@ -1304,10 +1359,10 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { index0 = n; // no original vertices in clone } if (fractionB < 0) { - index1 = -1; // no original vertices in clone + index1 = -1; // no original vertices in clone } else if (0 <= fractionB && fractionB <= 1) { index1 = Geometry.isSmallRelative(localB.fraction) ? localB.index - 1 : localB.index; - } else { // 1 < fractionB + } else { // 1 < fractionB index1 = n - 2; // last original vertex is not in clone } const result = LineString3d.create(); @@ -1325,7 +1380,9 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { public getIndexedSegment(index: number, result?: LineSegment3d): LineSegment3d | undefined { if (index >= 0 && index + 1 < this._points.length) return LineSegment3d.create( - this._points.getPoint3dAtCheckedPointIndex(index)!, this._points.getPoint3dAtCheckedPointIndex(index + 1)!, result, + this._points.getPoint3dAtCheckedPointIndex(index)!, + this._points.getPoint3dAtCheckedPointIndex(index + 1)!, + result, ); return undefined; } @@ -1366,10 +1423,9 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { const outputFraction = segmentMap.fractionToA(fraction); destLinestring.addPoint(pointA.interpolate(fraction, pointB, pointC)); if (needFractions) - destLinestring._fractions!.push((outputFraction)); + destLinestring._fractions!.push(outputFraction); if (needDerivatives) destLinestring._derivatives!.push(vectorAB); - } } } @@ -1400,7 +1456,9 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * @param explodeLinestrings if true, push a [[LineSegment3d]] for each segment. If false, only push `this`. */ public override collectCurvePrimitivesGo( - collectorArray: CurvePrimitive[], _smallestPossiblePrimitives: boolean, explodeLinestrings: boolean = false, + collectorArray: CurvePrimitive[], + _smallestPossiblePrimitives: boolean, + explodeLinestrings: boolean = false, ): void { if (explodeLinestrings) { let segment: LineSegment3d | undefined; @@ -1456,7 +1514,13 @@ export class LineString3d extends CurvePrimitive implements BeJSONFunctions { * @param child optional pre-allocated detail to use to clone the child data * @returns reference to input detail, with both linestring and segment data */ - public static convertLocalToGlobalDetail(detail: CurveLocationDetail, segmentIndex: number, numSegment: number, parent?: LineString3d, child?: CurveLocationDetail): CurveLocationDetail { + public static convertLocalToGlobalDetail( + detail: CurveLocationDetail, + segmentIndex: number, + numSegment: number, + parent?: LineString3d, + child?: CurveLocationDetail, + ): CurveLocationDetail { detail.childDetail = detail.clone(child); detail.childDetail.a = segmentIndex; detail.fraction = this.mapLocalToGlobalFraction(segmentIndex, detail.fraction, numSegment); @@ -1485,10 +1549,10 @@ export class AnnotatedLineString3d { * Context to be called to incrementally accumulate distance along line segments. */ class MoveByDistanceContext { - public distance0: number; // accumulated distance through point0 - public point0: Point3d; // most recent point - public fraction0: number; // most recent fraction position - public targetDistance: number; // this is always positive. + public distance0: number; // accumulated distance through point0 + public point0: Point3d; // most recent point + public fraction0: number; // most recent fraction position + public targetDistance: number; // this is always positive. /** CAPTURE point0, fraction0, targetDistance */ public constructor(point0: Point3d, fraction0: number, targetDistance: number) { this.point0 = point0; @@ -1499,7 +1563,8 @@ class MoveByDistanceContext { // Return CurveSearchStatus indicating whether the accumulated distance has reached the target. public distanceStatus(): CurveSearchStatus { return Geometry.isSameCoordinate(this.distance0, this.targetDistance) ? - CurveSearchStatus.success : CurveSearchStatus.stoppedAtBoundary; + CurveSearchStatus.success : + CurveSearchStatus.stoppedAtBoundary; } /** * Announce next point on the polyline. @@ -1541,9 +1606,7 @@ class MoveByDistanceContext { * @param result * @param CurveLocationDetail */ - public announceExtrapolation(points: GrowableXYZArray, - index0: number, index1: number, - fraction0: number, fraction1: number): boolean { + public announceExtrapolation(points: GrowableXYZArray, index0: number, index1: number, fraction0: number, fraction1: number): boolean { const residual = this.targetDistance - this.distance0; const d01 = points.distanceIndexIndex(index0, index1); if (!d01) diff --git a/core/geometry/src/curve/Loop.ts b/core/geometry/src/curve/Loop.ts index 9c4c23f23e04..09b88addd55a 100644 --- a/core/geometry/src/curve/Loop.ts +++ b/core/geometry/src/curve/Loop.ts @@ -113,7 +113,10 @@ export class LoopCurveLoopCurve { public curveB?: CurvePrimitive; /** Constructor */ public constructor( - loopA: Loop | undefined, curveA: CurvePrimitive | undefined, loopB: Loop | undefined, curveB: CurvePrimitive | undefined, + loopA: Loop | undefined, + curveA: CurvePrimitive | undefined, + loopB: Loop | undefined, + curveB: CurvePrimitive | undefined, ) { this.loopA = loopA; this.curveA = curveA; diff --git a/core/geometry/src/curve/OffsetOptions.ts b/core/geometry/src/curve/OffsetOptions.ts index 107a246ead2a..98ba65d926e2 100644 --- a/core/geometry/src/curve/OffsetOptions.ts +++ b/core/geometry/src/curve/OffsetOptions.ts @@ -53,8 +53,11 @@ export class JointOptions { * * minArcDegrees and maxChamferDegrees are optional. */ constructor( - leftOffsetDistance: number, minArcDegrees = 180, maxChamferDegrees = 90, - preserveEllipticalArcs = false, allowSharpestCorners = false, + leftOffsetDistance: number, + minArcDegrees = 180, + maxChamferDegrees = 90, + preserveEllipticalArcs = false, + allowSharpestCorners = false, ) { this.leftOffsetDistance = leftOffsetDistance; this.minArcDegrees = minArcDegrees; @@ -65,8 +68,11 @@ export class JointOptions { /** Return a deep clone. */ public clone(): JointOptions { return new JointOptions( - this.leftOffsetDistance, this.minArcDegrees, this.maxChamferTurnDegrees, - this.preserveEllipticalArcs, this.allowSharpestCorners, + this.leftOffsetDistance, + this.minArcDegrees, + this.maxChamferTurnDegrees, + this.preserveEllipticalArcs, + this.allowSharpestCorners, ); } /** Copy values of input options */ diff --git a/core/geometry/src/curve/ParityRegion.ts b/core/geometry/src/curve/ParityRegion.ts index 503db847865a..c5d90d5c9552 100644 --- a/core/geometry/src/curve/ParityRegion.ts +++ b/core/geometry/src/curve/ParityRegion.ts @@ -8,9 +8,9 @@ */ import { GeometryHandler } from "../geometry3d/GeometryHandler"; -import { AnyCurve } from "./CurveTypes"; import { CurveCollection } from "./CurveCollection"; import { RecursiveCurveProcessor } from "./CurveProcessor"; +import { AnyCurve } from "./CurveTypes"; import { GeometryQuery } from "./GeometryQuery"; import { Loop } from "./Loop"; import { StrokeOptions } from "./StrokeOptions"; diff --git a/core/geometry/src/curve/ProxyCurve.ts b/core/geometry/src/curve/ProxyCurve.ts index 7cd7006bc826..8174c9ebf7ec 100644 --- a/core/geometry/src/curve/ProxyCurve.ts +++ b/core/geometry/src/curve/ProxyCurve.ts @@ -12,12 +12,12 @@ import { CurvePrimitive } from "../curve/CurvePrimitive"; import type { GeometryHandler, IStrokeHandler } from "../geometry3d/GeometryHandler"; import type { Plane3dByOriginAndUnitNormal } from "../geometry3d/Plane3dByOriginAndUnitNormal"; import type { Plane3dByOriginAndVectors } from "../geometry3d/Plane3dByOriginAndVectors"; -import type { Ray3d } from "../geometry3d/Ray3d"; -import type { Transform } from "../geometry3d/Transform"; import type { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; import type { Range1d, Range3d } from "../geometry3d/Range"; -import type { OffsetOptions } from "./OffsetOptions"; +import type { Ray3d } from "../geometry3d/Ray3d"; +import type { Transform } from "../geometry3d/Transform"; import type { LineString3d } from "./LineString3d"; +import type { OffsetOptions } from "./OffsetOptions"; import type { StrokeOptions } from "./StrokeOptions"; /** @@ -91,7 +91,8 @@ export abstract class ProxyCurve extends CurvePrimitive { } /** Implement by proxyCurve */ public fractionToPointAnd2Derivatives( - fraction: number, result?: Plane3dByOriginAndVectors, + fraction: number, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors | undefined { return this._proxyCurve.fractionToPointAnd2Derivatives(fraction, result); } diff --git a/core/geometry/src/curve/Query/ConsolidateAdjacentPrimitivesContext.ts b/core/geometry/src/curve/Query/ConsolidateAdjacentPrimitivesContext.ts index 81d0f6d7fae0..b6aec86621c9 100644 --- a/core/geometry/src/curve/Query/ConsolidateAdjacentPrimitivesContext.ts +++ b/core/geometry/src/curve/Query/ConsolidateAdjacentPrimitivesContext.ts @@ -65,7 +65,11 @@ export class ConsolidateAdjacentCurvePrimitivesContext extends NullGeometryHandl const compressedPointsB = PolylineOps.compressByPerpendicularDistance(compressedPointsA, this._options.colinearPointTolerance); if (i0 === 0 && i1 === numOriginal) { // points is the entire curve, and the curve is closed. Maybe the first and last segments are colinear. - PolylineCompressionContext.compressColinearWrapInPlace(compressedPointsB, this._options.duplicatePointTolerance, this._options.colinearPointTolerance); + PolylineCompressionContext.compressColinearWrapInPlace( + compressedPointsB, + this._options.duplicatePointTolerance, + this._options.colinearPointTolerance, + ); } if (compressedPointsB.length < 2) { // Collapsed to a point? Make a single point linestring @@ -90,7 +94,7 @@ export class ConsolidateAdjacentCurvePrimitivesContext extends NullGeometryHandl break; } // i0 has already advanced - g.children[numAccept++] = basePrimitive; // which has been extended 0 or more times. + g.children[numAccept++] = basePrimitive; // which has been extended 0 or more times. } else { g.children[numAccept++] = basePrimitive; i0++; @@ -99,8 +103,12 @@ export class ConsolidateAdjacentCurvePrimitivesContext extends NullGeometryHandl g.children.length = numAccept; } - public override handlePath(g: Path): any { return this.handleCurveChain(g); } - public override handleLoop(g: Loop): any { return this.handleCurveChain(g); } + public override handlePath(g: Path): any { + return this.handleCurveChain(g); + } + public override handleLoop(g: Loop): any { + return this.handleCurveChain(g); + } public override handleParityRegion(g: ParityRegion): any { for (const child of g.children) child.dispatchToGeometryHandler(this); diff --git a/core/geometry/src/curve/Query/CurveSplitContext.ts b/core/geometry/src/curve/Query/CurveSplitContext.ts index 4e0ccc049d18..2f8e344dcb28 100644 --- a/core/geometry/src/curve/Query/CurveSplitContext.ts +++ b/core/geometry/src/curve/Query/CurveSplitContext.ts @@ -8,11 +8,11 @@ */ import { Geometry } from "../../Geometry"; -import { AnyCurve } from "../CurveTypes"; import { CurveChain, CurveCollection } from "../CurveCollection"; import { CurveCurve } from "../CurveCurve"; import { CurveLocationDetail, CurveLocationDetailPair } from "../CurveLocationDetail"; import { CurvePrimitive } from "../CurvePrimitive"; +import { AnyCurve } from "../CurveTypes"; import { Path } from "../Path"; /** @@ -75,8 +75,11 @@ export class CurveSplitContext { /** Collect fragments from an intersections array, with the array detailA entries all referencing to curveToCut. * * The `intersections` array is sorted on its detailA field. */ - private collectSinglePrimitiveFragments(curveToCut: CurvePrimitive, intersections: CurveLocationDetailPair[] | undefined, fragments: CurvePrimitive[]) { - + private collectSinglePrimitiveFragments( + curveToCut: CurvePrimitive, + intersections: CurveLocationDetailPair[] | undefined, + fragments: CurvePrimitive[], + ) { if (intersections === undefined || !CurveSplitContext.hasInteriorDetailAIntersections(intersections)) { fragments.push(curveToCut.clone()); return; diff --git a/core/geometry/src/curve/Query/CylindricalRange.ts b/core/geometry/src/curve/Query/CylindricalRange.ts index 4ed36f1ba681..6d4c54e87c7a 100644 --- a/core/geometry/src/curve/Query/CylindricalRange.ts +++ b/core/geometry/src/curve/Query/CylindricalRange.ts @@ -100,7 +100,7 @@ export class CylindricalRangeQuery extends RecurseToCurvesGeometryHandler { const normals = geometry.ensureEmptySurfaceNormals(); if (derivatives && normals) { const vectorU = Vector3d.create(); - const vectorV = Vector3d.create(); // v direction (forwward along sweep) for surface of rotation. + const vectorV = Vector3d.create(); // v direction (forwward along sweep) for surface of rotation. const xyz = Point3d.create(); const n = points.length; for (let i = 0; i < n; i++) { @@ -111,7 +111,7 @@ export class CylindricalRangeQuery extends RecurseToCurvesGeometryHandler { else axis.direction.crossProduct(vectorU, vectorV); geometry.packedDerivatives.getVector3dAtCheckedVectorIndex(i, vectorU); // reuse vector U as curve derivative - vectorU.crossProduct(vectorV, vectorV); // reuse vector V as normal! + vectorU.crossProduct(vectorV, vectorV); // reuse vector V as normal! vectorV.normalizeInPlace(); normals.push(vectorV); } diff --git a/core/geometry/src/curve/Query/InOutTests.ts b/core/geometry/src/curve/Query/InOutTests.ts index b5ae03bb5db8..9325c9a0e76b 100644 --- a/core/geometry/src/curve/Query/InOutTests.ts +++ b/core/geometry/src/curve/Query/InOutTests.ts @@ -11,9 +11,9 @@ import { Geometry } from "../../Geometry"; import { Angle } from "../../geometry3d/Angle"; import { Plane3dByOriginAndUnitNormal } from "../../geometry3d/Plane3dByOriginAndUnitNormal"; import { Point3d } from "../../geometry3d/Point3dVector3d"; -import { AnyRegion } from "../CurveTypes"; import { CurveIntervalRole, CurveLocationDetail } from "../CurveLocationDetail"; import { CurvePrimitive } from "../CurvePrimitive"; +import { AnyRegion } from "../CurveTypes"; import { Loop } from "../Loop"; import { ParityRegion } from "../ParityRegion"; import { UnionRegion } from "../UnionRegion"; @@ -55,8 +55,10 @@ export class PointInOnOutContext { // If there are any tricky ones, go around with a different plane. // A intently devious tester could make every plane hit tricky things. for (const intersection of intersections) { - if (intersection.intervalRole !== CurveIntervalRole.isolated - && intersection.intervalRole !== undefined) { + if ( + intersection.intervalRole !== CurveIntervalRole.isolated + && intersection.intervalRole !== undefined + ) { numTricky++; } wx = intersection.point.x - x; @@ -94,7 +96,7 @@ export class PointInOnOutContext { if (q === 0) return 0; if (q > 0) - result = - result; + result = -result; } } return result; @@ -116,5 +118,4 @@ export class PointInOnOutContext { return this.testPointInOnOutUnionRegionXY(parent, x, y); return -1; } - } diff --git a/core/geometry/src/curve/Query/PlanarSubdivision.ts b/core/geometry/src/curve/Query/PlanarSubdivision.ts index e9f3f4845200..952c7d4bf4b1 100644 --- a/core/geometry/src/curve/Query/PlanarSubdivision.ts +++ b/core/geometry/src/curve/Query/PlanarSubdivision.ts @@ -63,8 +63,18 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray { const p0 = p.clonePartialCurve(0.0, 0.5); const p1 = p.clonePartialCurve(0.5, 1.0); if (p0 && p1) { - this.insertPair(CurveLocationDetailPair.createCapture(CurveLocationDetail.createCurveEvaluatedFraction(p0, 0.0), CurveLocationDetail.createCurveEvaluatedFraction(p1, 1.0))); - this.insertPair(CurveLocationDetailPair.createCapture(CurveLocationDetail.createCurveEvaluatedFraction(p0, 1.0), CurveLocationDetail.createCurveEvaluatedFraction(p1, 0.0))); + this.insertPair( + CurveLocationDetailPair.createCapture( + CurveLocationDetail.createCurveEvaluatedFraction(p0, 0.0), + CurveLocationDetail.createCurveEvaluatedFraction(p1, 1.0), + ), + ); + this.insertPair( + CurveLocationDetailPair.createCapture( + CurveLocationDetail.createCurveEvaluatedFraction(p0, 1.0), + CurveLocationDetail.createCurveEvaluatedFraction(p1, 0.0), + ), + ); } } } @@ -76,12 +86,16 @@ class MapCurvePrimitiveToCurveLocationDetailPairArray { */ export class PlanarSubdivision { /** Create a graph from an array of curves, and an array of the curves' precomputed intersections. Z-coordinates are ignored. */ - public static assembleHalfEdgeGraph(primitives: CurvePrimitive[], allPairs: CurveLocationDetailPair[], mergeTolerance: number = Geometry.smallMetricDistance): HalfEdgeGraph { - const detailByPrimitive = new MapCurvePrimitiveToCurveLocationDetailPairArray(); // map from key CurvePrimitive to CurveLocationDetailPair. + public static assembleHalfEdgeGraph( + primitives: CurvePrimitive[], + allPairs: CurveLocationDetailPair[], + mergeTolerance: number = Geometry.smallMetricDistance, + ): HalfEdgeGraph { + const detailByPrimitive = new MapCurvePrimitiveToCurveLocationDetailPairArray(); // map from key CurvePrimitive to CurveLocationDetailPair. for (const pair of allPairs) detailByPrimitive.insertPair(pair); if (primitives.length > detailByPrimitive.primitiveToPair.size) - detailByPrimitive.splitAndAppendMissingClosedPrimitives(primitives, mergeTolerance); // otherwise, these single-primitive loops are missing from the graph + detailByPrimitive.splitAndAppendMissingClosedPrimitives(primitives, mergeTolerance); // otherwise, these single-primitive loops are missing from the graph const graph = new HalfEdgeGraph(); for (const entry of detailByPrimitive.primitiveToPair.entries()) { const p = entry[0]; @@ -100,7 +114,7 @@ export class PlanarSubdivision { const fractionB = getFractionOnCurve(pairB, p)!; return fractionA - fractionB; }); - let last = {point: p.startPoint(), fraction: 0.0}; + let last = { point: p.startPoint(), fraction: 0.0 }; for (const detailPair of details) { const detail = getDetailOnCurve(detailPair, p)!; const detailFraction = Geometry.restrictToInterval(detail.fraction, 0, 1); // truncate fraction, but don't snap point; clustering happens later @@ -122,9 +136,17 @@ export class PlanarSubdivision { * @param fraction1 end fraction * @returns end point and fraction, or start point and fraction if no action */ - private static addHalfEdge(graph: HalfEdgeGraph, p: CurvePrimitive, point0: Point3d, fraction0: number, point1: Point3d, fraction1: number, mergeTolerance: number = Geometry.smallMetricDistance): {point: Point3d, fraction: number} { + private static addHalfEdge( + graph: HalfEdgeGraph, + p: CurvePrimitive, + point0: Point3d, + fraction0: number, + point1: Point3d, + fraction1: number, + mergeTolerance: number = Geometry.smallMetricDistance, + ): { point: Point3d, fraction: number } { if (point0.isAlmostEqualXY(point1, mergeTolerance)) - return {point: point0, fraction: fraction0}; + return { point: point0, fraction: fraction0 }; const halfEdge = graph.createEdgeXYAndZ(point0, 0, point1, 0); const detail01 = CurveLocationDetail.createCurveEvaluatedFractionFraction(p, fraction0, fraction1); const mate = halfEdge.edgeMate; @@ -134,15 +156,15 @@ export class PlanarSubdivision { mate.sortData = -1.0; halfEdge.sortAngle = sortAngle(p, fraction0, false); mate.sortAngle = sortAngle(p, fraction1, true); - return {point: point1, fraction: fraction1}; - } + return { point: point1, fraction: fraction1 }; + } /** * Based on computed (and toleranced) area, push the loop (pointer) onto the appropriate array of positive, negative, or sliver loops. * @param zeroAreaTolerance absolute area tolerance for sliver face detection * @param isSliverFace whether the loop is known a priori (e.g., via topology) to have zero area * @returns the area (forced to zero if within tolerance) */ - public static collectSignedLoop(loop: Loop, outLoops: SignedLoops, zeroAreaTolerance: number = 1.0e-10, isSliverFace?: boolean): number{ + public static collectSignedLoop(loop: Loop, outLoops: SignedLoops, zeroAreaTolerance: number = 1.0e-10, isSliverFace?: boolean): number { let area = isSliverFace ? 0.0 : RegionOps.computeXYArea(loop); if (area === undefined) area = 0; @@ -157,8 +179,7 @@ export class PlanarSubdivision { outLoops.slivers.push(loop); return area; } - public static createLoopInFace(faceSeed: HalfEdge, - announce?: (he: HalfEdge, curve: CurvePrimitive, loop: Loop) => void): Loop { + public static createLoopInFace(faceSeed: HalfEdge, announce?: (he: HalfEdge, curve: CurvePrimitive, loop: Loop) => void): Loop { let he = faceSeed; const loop = Loop.create(); do { @@ -181,22 +202,22 @@ export class PlanarSubdivision { } // Return true if there are only two edges in the face loop, and their start curvatures are the same. private static isNullFace(he: HalfEdge): boolean { - const faceHasTwoEdges = (he.faceSuccessor.faceSuccessor === he); + const faceHasTwoEdges = he.faceSuccessor.faceSuccessor === he; let faceIsBanana = false; if (faceHasTwoEdges) { const c0 = HalfEdgeGraphMerge.curvatureSortKey(he); const c1 = HalfEdgeGraphMerge.curvatureSortKey(he.faceSuccessor.edgeMate); if (!Geometry.isSameCoordinate(c0, c1)) // default tol! - faceIsBanana = true; // heuristic: we could also check end curvatures, and/or higher derivatives... + faceIsBanana = true; // heuristic: we could also check end curvatures, and/or higher derivatives... } return faceHasTwoEdges && !faceIsBanana; } // Look across edge mates (possibly several) for a nonnull mate face. private static nonNullEdgeMate(_graph: HalfEdgeGraph, e: HalfEdge): HalfEdge | undefined { - if (this.isNullFace (e)) + if (this.isNullFace(e)) return undefined; let e1 = e.edgeMate; - while (this.isNullFace(e1)){ + while (this.isNullFace(e1)) { e1 = e1.faceSuccessor.edgeMate; if (e1 === e) return undefined; diff --git a/core/geometry/src/curve/Query/StrokeCountChain.ts b/core/geometry/src/curve/Query/StrokeCountChain.ts index 889a44311796..7d725e5dfe7a 100644 --- a/core/geometry/src/curve/Query/StrokeCountChain.ts +++ b/core/geometry/src/curve/Query/StrokeCountChain.ts @@ -9,8 +9,8 @@ import { Geometry } from "../../Geometry"; import { Point3d } from "../../geometry3d/Point3dVector3d"; import { Range1d } from "../../geometry3d/Range"; -import { AnyCurve } from "../CurveTypes"; import { CurveChain, CurveCollection } from "../CurveCollection"; +import { AnyCurve } from "../CurveTypes"; import { LineString3d } from "../LineString3d"; import { Loop } from "../Loop"; import { ParityRegion } from "../ParityRegion"; @@ -52,7 +52,9 @@ export abstract class StrokeCountMapMultipassVisitor { * @param componentIndex optional component index. * @returns the number of sweeps to perform. */ - public startSweeps(_chainIndex: number, _primitiveIndex: number, _componentIndex?: number): boolean { return true; } + public startSweeps(_chainIndex: number, _primitiveIndex: number, _componentIndex?: number): boolean { + return true; + } /** * announce the beginning of a sweep pass. * @param pass the index (0,1...) for this sweep pass. @@ -71,8 +73,9 @@ export abstract class StrokeCountMapMultipassVisitor { * announce the end of handling for particular chainIndex and primitiveIndex; * @return true to continue outer loops. */ - public endSweeps(_chainIndex: number, _primitiveIndex: number, _componentIndex?: number): boolean { return true; } - + public endSweeps(_chainIndex: number, _primitiveIndex: number, _componentIndex?: number): boolean { + return true; + } } /** * * pass 1: determine max numStroke @@ -112,7 +115,9 @@ export class StrokeCountMapVisitorApplyMaxCount extends StrokeCountMapMultipassV return false; } - public endPass(_pass: number): boolean { return true; } + public endPass(_pass: number): boolean { + return true; + } } /** * * pass 1: determine max curveLength among maps presented. @@ -152,7 +157,9 @@ export class StrokeCountMapVisitorApplyMaxCurveLength extends StrokeCountMapMult return false; } - public endPass(_pass: number): boolean { return true; } + public endPass(_pass: number): boolean { + return true; + } } /** * class `StrokeCountChain` contains: @@ -201,7 +208,6 @@ export class StrokeCountChain { m.primitive.addMappedStrokesToLineString3D(m, ls); } return ls; - } /** internal form of */ private static applySummed01LimitsWithinArray(maps: StrokeCountMap[], incomingSum: number): number { @@ -243,7 +249,10 @@ export class StrokeCountChain { export class StrokeCountSection { public chains: StrokeCountChain[]; public parent?: CurveCollection; - private constructor(parent?: CurveCollection) { this.parent = parent; this.chains = []; } + private constructor(parent?: CurveCollection) { + this.parent = parent; + this.chains = []; + } /** * construct array of arrays of `StrokeCountMap`s * @param parent @@ -263,7 +272,7 @@ export class StrokeCountSection { /** test if all sections have the same structure. */ public static areSectionsCompatible(sections: StrokeCountSection[], enforceCounts: boolean): boolean { if (sections.length < 2) - return true; // hm.. don't know if that is useful, but nothing to check here. + return true; // hm.. don't know if that is useful, but nothing to check here. const numChains = sections[0].chains.length; for (let i = 1; i < sections.length; i++) { // first level: must match number of paths or loops @@ -279,7 +288,6 @@ export class StrokeCountSection { return false; } } - } return true; } @@ -295,13 +303,18 @@ export class StrokeCountSection { } } - private static applyMultipassVisitorCallbackNoComponents(sections: StrokeCountSection[], chainIndex: number, primitiveIndex: number, - componentIndex: number | undefined, callback: StrokeCountMapMultipassVisitor) { + private static applyMultipassVisitorCallbackNoComponents( + sections: StrokeCountSection[], + chainIndex: number, + primitiveIndex: number, + componentIndex: number | undefined, + callback: StrokeCountMapMultipassVisitor, + ) { const numSection = sections.length; if (!callback.startSweeps(chainIndex, primitiveIndex, componentIndex)) return false; if (componentIndex === undefined) { // there are corresponding primitives directly at the section, chain, primitive index: - for (let pass = 0; ; pass++) { + for (let pass = 0;; pass++) { if (!callback.startPass(pass)) break; for (let sectionIndex = 0; sectionIndex < numSection; sectionIndex++) @@ -313,7 +326,7 @@ export class StrokeCountSection { } else { // there are corresponding primitives at the section, chain, primitive,componentIndex // there are corresponding primitives directly at the section, chain, primitive index: - for (let pass = 0; ; pass++) { + for (let pass = 0;; pass++) { if (!callback.startPass(pass)) break; for (let sectionIndex = 0; sectionIndex < numSection; sectionIndex++) @@ -322,7 +335,6 @@ export class StrokeCountSection { if (!callback.endPass(pass)) return false; } - } if (!callback.endSweeps(chainIndex, primitiveIndex, componentIndex)) return false; return true; @@ -343,7 +355,6 @@ export class StrokeCountSection { for (let i = 0; i < numComponent; i++) if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, i, callback)) return false; - } else { if (!this.applyMultipassVisitorCallbackNoComponents(sections, chainIndex, primitiveIndex, undefined, callback)) return false; @@ -359,7 +370,6 @@ export class StrokeCountSection { * @param sections array of per-section stroke count entries */ public static enforceStrokeCountCompatibility(sections: StrokeCountSection[]): boolean { - if (sections.length < 2) return true; if (!StrokeCountSection.areSectionsCompatible(sections, false)) @@ -367,7 +377,6 @@ export class StrokeCountSection { const visitor = new StrokeCountMapVisitorApplyMaxCount(); this.runMultiPassVisitorAtCorrespondingPrimitives(sections, visitor); return true; - } /** * * Confirm that all sections in the array have the same structure. @@ -376,7 +385,6 @@ export class StrokeCountSection { * @param sections array of per-section stroke count entries */ public static enforceCompatibleDistanceSums(sections: StrokeCountSection[]): boolean { - if (sections.length < 2) return true; if (!StrokeCountSection.areSectionsCompatible(sections, false)) @@ -385,7 +393,6 @@ export class StrokeCountSection { this.runMultiPassVisitorAtCorrespondingPrimitives(sections, visitor); this.remapa0a1WithinEachChain(sections); return true; - } /** diff --git a/core/geometry/src/curve/Query/StrokeCountMap.ts b/core/geometry/src/curve/Query/StrokeCountMap.ts index 1dafcbfe7696..ee55d7f569eb 100644 --- a/core/geometry/src/curve/Query/StrokeCountMap.ts +++ b/core/geometry/src/curve/Query/StrokeCountMap.ts @@ -64,7 +64,12 @@ export class StrokeCountMap { * @param componentData */ public static createWithCurvePrimitive( - primitive: CurvePrimitive, numStroke: number, curveLength: number, a0: number, a1: number, componentData?: StrokeCountMap[], + primitive: CurvePrimitive, + numStroke: number, + curveLength: number, + a0: number, + a1: number, + componentData?: StrokeCountMap[], ): StrokeCountMap { const result = new StrokeCountMap(numStroke, curveLength, a0, a1, componentData); result.primitive = primitive; @@ -79,7 +84,11 @@ export class StrokeCountMap { * @param a1 */ public static createWithComponentIndex( - componentIndex: number = 0, numStroke: number = 0, curveLength: number = 0, a0: number = 0, a1: number = 0, + componentIndex: number = 0, + numStroke: number = 0, + curveLength: number = 0, + a0: number = 0, + a1: number = 0, ): StrokeCountMap { const result = new StrokeCountMap(numStroke, curveLength, a0, a1); result.componentIndex = componentIndex; @@ -93,7 +102,9 @@ export class StrokeCountMap { * @param componentData optional array of component StrokeCountMaps. */ public static createWithCurvePrimitiveAndOptionalParent( - curvePrimitive: CurvePrimitive, parentMap?: StrokeCountMap, componentData?: StrokeCountMap[], + curvePrimitive: CurvePrimitive, + parentMap?: StrokeCountMap, + componentData?: StrokeCountMap[], ): StrokeCountMap { const a0 = parentMap ? parentMap.a1 : 0.0; const result = new StrokeCountMap(0, 0, a0, a0, componentData); @@ -111,7 +122,8 @@ export class StrokeCountMap { const a2 = this.a1 + curveLength; if (this.componentData) { this.componentData.push( - new StrokeCountMap(numStroke, curveLength, this.a1, a2)); + new StrokeCountMap(numStroke, curveLength, this.a1, a2), + ); } this.numStroke += numStroke; this.curveLength += curveLength; diff --git a/core/geometry/src/curve/RegionMomentsXY.ts b/core/geometry/src/curve/RegionMomentsXY.ts index e18c8552db18..4d94ea9cbc40 100644 --- a/core/geometry/src/curve/RegionMomentsXY.ts +++ b/core/geometry/src/curve/RegionMomentsXY.ts @@ -21,8 +21,8 @@ import { LineSegment3d } from "./LineSegment3d"; import { LineString3d } from "./LineString3d"; import { Loop } from "./Loop"; import { ParityRegion } from "./ParityRegion"; -import { StrokeOptions } from "./StrokeOptions"; import { TransitionSpiral3d } from "./spiral/TransitionSpiral3d"; +import { StrokeOptions } from "./StrokeOptions"; import { UnionRegion } from "./UnionRegion"; /** @@ -114,7 +114,6 @@ export class RegionMomentsXY extends NullGeometryHandler { maxAbsArea = q; largestChildMoments = childMoments; } - } } } @@ -166,10 +165,15 @@ export class RegionMomentsXY extends NullGeometryHandler { this.handleLineString3d(strokes); } /** handle strongly typed BSplineCurve3d as generic curve primitive */ - public override handleBSplineCurve3d(g: BSplineCurve3d) { return this.handleCurvePrimitive(g); } + public override handleBSplineCurve3d(g: BSplineCurve3d) { + return this.handleCurvePrimitive(g); + } /** handle strongly typed BSplineCurve3dH as generic curve primitive */ - public override handleBSplineCurve3dH(g: BSplineCurve3dH) { return this.handleCurvePrimitive(g); } + public override handleBSplineCurve3dH(g: BSplineCurve3dH) { + return this.handleCurvePrimitive(g); + } /** handle strongly typed TransitionSpiral as generic curve primitive */ - public override handleTransitionSpiral(g: TransitionSpiral3d) { return this.handleCurvePrimitive(g); } - + public override handleTransitionSpiral(g: TransitionSpiral3d) { + return this.handleCurvePrimitive(g); + } } diff --git a/core/geometry/src/curve/RegionOps.ts b/core/geometry/src/curve/RegionOps.ts index d5df01ea9ef4..28912449e1c1 100644 --- a/core/geometry/src/curve/RegionOps.ts +++ b/core/geometry/src/curve/RegionOps.ts @@ -10,7 +10,10 @@ import { Geometry } from "../Geometry"; import { GrowableXYZArray } from "../geometry3d/GrowableXYZArray"; import { - IndexedReadWriteXYZCollection, IndexedXYZCollection, LineStringDataVariant, MultiLineStringDataVariant, + IndexedReadWriteXYZCollection, + IndexedXYZCollection, + LineStringDataVariant, + MultiLineStringDataVariant, } from "../geometry3d/IndexedXYZCollection"; import { Point3dArrayCarrier } from "../geometry3d/Point3dArrayCarrier"; import { Point3d } from "../geometry3d/Point3dVector3d"; @@ -103,7 +106,7 @@ export class RegionOps { * Return an area tolerance for a given xy-range and optional distance tolerance. * @param range range of planar region to tolerance * @param distanceTolerance optional absolute distance tolerance - */ + */ public static computeXYAreaTolerance(range: Range3d, distanceTolerance: number = Geometry.smallMetricDistance): number { // if A = bh and e is distance tolerance, then A' := (b+e/2)(h+e/2) = A + e/2(b+h+e/2), so A'-A = e/2(b+h+e/2). const halfDistTol = 0.5 * distanceTolerance; @@ -164,7 +167,6 @@ export class RegionOps { const loopSeed = Triangulator.directCreateFaceLoopFromCoordinates(graph, data as LineStringDataVariant); if (loopSeed !== undefined) announceIsolatedLoop(graph, loopSeed); - } else if (data[0] instanceof IndexedXYZCollection) { for (const loop of data) { const loopSeed = Triangulator.directCreateFaceLoopFromCoordinates(graph, loop as IndexedXYZCollection); @@ -186,7 +188,10 @@ export class RegionOps { * @internal */ public static addLoopsWithEdgeTagToGraph( - graph: HalfEdgeGraph, data: MultiLineStringDataVariant, mask: HalfEdgeMask, edgeTag: any, + graph: HalfEdgeGraph, + data: MultiLineStringDataVariant, + mask: HalfEdgeMask, + edgeTag: any, ): HalfEdge[] | undefined { const loopSeeds: HalfEdge[] = []; this.addLoopsToGraph(graph, data, (_graph: HalfEdgeGraph, seed: HalfEdge) => { @@ -225,7 +230,9 @@ export class RegionOps { * @param triangulate whether to triangulate the result */ public static polygonXYAreaIntersectLoopsToPolyface( - loopsA: MultiLineStringDataVariant, loopsB: MultiLineStringDataVariant, triangulate: boolean = false, + loopsA: MultiLineStringDataVariant, + loopsB: MultiLineStringDataVariant, + triangulate: boolean = false, ): Polyface | undefined { const graph = RegionOpsFaceToFaceSearch.doPolygonBoolean( loopsA, @@ -245,7 +252,9 @@ export class RegionOps { * @param triangulate whether to triangulate the result */ public static polygonXYAreaUnionLoopsToPolyface( - loopsA: MultiLineStringDataVariant, loopsB: MultiLineStringDataVariant, triangulate: boolean = false, + loopsA: MultiLineStringDataVariant, + loopsB: MultiLineStringDataVariant, + triangulate: boolean = false, ): Polyface | undefined { const graph = RegionOpsFaceToFaceSearch.doPolygonBoolean( loopsA, @@ -265,7 +274,9 @@ export class RegionOps { * @param triangulate whether to triangulate the result */ public static polygonXYAreaDifferenceLoopsToPolyface( - loopsA: MultiLineStringDataVariant, loopsB: MultiLineStringDataVariant, triangulate: boolean = false, + loopsA: MultiLineStringDataVariant, + loopsB: MultiLineStringDataVariant, + triangulate: boolean = false, ): Polyface | undefined { const graph = RegionOpsFaceToFaceSearch.doPolygonBoolean( loopsA, @@ -336,9 +347,11 @@ export class RegionOps { triangulate: boolean = false, ): Polyface | undefined { const graph = RegionOpsFaceToFaceSearch.doBinaryBooleanBetweenMultiLoopInputs( - inputA, RegionGroupOpType.Union, + inputA, + RegionGroupOpType.Union, operation, - inputB, RegionGroupOpType.Union, + inputB, + RegionGroupOpType.Union, true, ); return this.finishGraphToPolyface(graph, triangulate); @@ -395,7 +408,9 @@ export class RegionOps { * object. */ public static constructPolygonWireXYOffset( - points: Point3d[], wrap: boolean, offsetDistanceOrOptions: number | JointOptions, + points: Point3d[], + wrap: boolean, + offsetDistanceOrOptions: number | JointOptions, ): CurveChain | undefined { const context = new PolygonWireOffsetContext(); return context.constructPolygonWireXYOffset(points, wrap, offsetDistanceOrOptions); @@ -409,7 +424,8 @@ export class RegionOps { * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object. */ public static constructCurveXYOffset( - curves: Path | Loop, offsetDistanceOrOptions: number | JointOptions | OffsetOptions, + curves: Path | Loop, + offsetDistanceOrOptions: number | JointOptions | OffsetOptions, ): CurveCollection | undefined { const offsetOptions = OffsetOptions.create(offsetDistanceOrOptions); return CurveOps.constructCurveXYOffset(curves, offsetOptions); @@ -435,7 +451,9 @@ export class RegionOps { * @param consolidateAdjacentPrimitives whether to simplify the result by calling [[consolidateAdjacentPrimitives]] */ public static createLoopPathOrBagOfCurves( - curves: CurvePrimitive[], wrap: boolean = true, consolidateAdjacentPrimitives: boolean = false, + curves: CurvePrimitive[], + wrap: boolean = true, + consolidateAdjacentPrimitives: boolean = false, ): CurveCollection | undefined { const n = curves.length; if (n === 0) @@ -477,7 +495,8 @@ export class RegionOps { * @param cutterCurves input curves to intersect with `curvesToCut` */ public static cloneCurvesWithXYSplits( - curvesToCut: AnyCurve | undefined, cutterCurves: CurveCollection, + curvesToCut: AnyCurve | undefined, + cutterCurves: CurveCollection, ): AnyCurve | undefined { return CurveSplitContext.cloneCurvesWithXYSplits(curvesToCut, cutterCurves); } @@ -510,7 +529,9 @@ export class RegionOps { * @returns object with named chains, insideOffsets, outsideOffsets */ public static collectInsideAndOutsideOffsets( - fragments: AnyCurve[], offsetDistance: number, gapTolerance: number, + fragments: AnyCurve[], + offsetDistance: number, + gapTolerance: number, ): { insideOffsets: AnyCurve[], outsideOffsets: AnyCurve[], chains?: AnyChain } { return CurveOps.collectInsideAndOutsideXYOffsets(fragments, offsetDistance, gapTolerance); } @@ -530,7 +551,8 @@ export class RegionOps { * @returns output object with all fragments split among `insideParts`, `outsideParts`, and `coincidentParts` */ public static splitPathsByRegionInOnOutXY( - curvesToCut: AnyCurve | undefined, region: AnyRegion, + curvesToCut: AnyCurve | undefined, + region: AnyRegion, ): { insideParts: AnyCurve[], outsideParts: AnyCurve[], coincidentParts: AnyCurve[] } { const result = { insideParts: [], outsideParts: [], coincidentParts: [] }; const pathWithIntersectionMarkup = RegionOps.cloneCurvesWithXYSplits(curvesToCut, region); @@ -568,7 +590,8 @@ export class RegionOps { * normal in z column. If not a rectangle, return undefined. */ public static rectangleEdgeTransform( - data: AnyCurve | Point3d[] | IndexedXYZCollection, requireClosurePoint: boolean = true, + data: AnyCurve | Point3d[] | IndexedXYZCollection, + requireClosurePoint: boolean = true, ): Transform | undefined { if (data instanceof LineString3d) { return this.rectangleEdgeTransform(data.packedPoints); @@ -592,11 +615,16 @@ export class RegionOps { const vector03 = dataToUse.vectorIndexIndex(0, 3)!; const vector12 = dataToUse.vectorIndexIndex(1, 2)!; const normalVector = vector01.crossProduct(vector03); - if (normalVector.normalizeInPlace() + if ( + normalVector.normalizeInPlace() && vector12.isAlmostEqual(vector03) - && vector01.isPerpendicularTo(vector03)) { + && vector01.isPerpendicularTo(vector03) + ) { return Transform.createOriginAndMatrixColumns( - dataToUse.getPoint3dAtUncheckedPointIndex(0), vector01, vector03, normalVector, + dataToUse.getPoint3dAtUncheckedPointIndex(0), + vector01, + vector03, + normalVector, ); } } else if (Array.isArray(data)) { @@ -629,7 +657,8 @@ export class RegionOps { * @param options options for tolerance and selective simplification. */ public static consolidateAdjacentPrimitives( - curves: CurveCollection, options?: ConsolidateAdjacentCurvePrimitivesOptions, + curves: CurveCollection, + options?: ConsolidateAdjacentCurvePrimitivesOptions, ): void { const context = new ConsolidateAdjacentCurvePrimitivesContext(options); curves.dispatchToGeometryHandler(context); @@ -679,7 +708,8 @@ export class RegionOps { * to the edge and a constituent curve in each. */ public static constructAllXYRegionLoops( - curvesAndRegions: AnyCurve | AnyCurve[], tolerance: number = Geometry.smallMetricDistance, + curvesAndRegions: AnyCurve | AnyCurve[], + tolerance: number = Geometry.smallMetricDistance, ): SignedLoops[] { const primitives = RegionOps.collectCurvePrimitives(curvesAndRegions, undefined, true, true); const range = this.curveArrayRange(primitives); @@ -871,7 +901,7 @@ export class RegionOps { * @param polygon polygon and hole loops, e.g., as returned by [[CurveCollection.cloneStroked]] on a Loop or ParityRegion. All z-coordinates are ignored. * @param maximize whether to return maximally convex polygons. If false, triangles are returned. * @returns array of convex polygons, or undefined if triangulation failed - */ + */ public static convexDecomposePolygonXY(polygon: MultiLineStringDataVariant, maximize: boolean = true): GrowableXYZArray[] | undefined { const graph = RegionOps.triangulateStrokedRegionComponent(polygon); if (!graph) @@ -881,7 +911,9 @@ export class RegionOps { const convexPolygons: GrowableXYZArray[] = []; graph.announceFaceLoops((_graph, seed) => { if (!seed.isMaskSet(HalfEdgeMask.EXTERIOR)) - convexPolygons.push(GrowableXYZArray.create(seed.collectAroundFace((node) => { return node.getPoint3d(); }))); + convexPolygons.push(GrowableXYZArray.create(seed.collectAroundFace((node) => { + return node.getPoint3d(); + }))); return true; }); return convexPolygons; @@ -889,7 +921,11 @@ export class RegionOps { } /** @internal */ function pushToInOnOutArrays( - curve: AnyCurve, select: number, arrayNegative: AnyCurve[], array0: AnyCurve[], arrayPositive: AnyCurve[], + curve: AnyCurve, + select: number, + arrayNegative: AnyCurve[], + array0: AnyCurve[], + arrayPositive: AnyCurve[], ): void { if (select > 0) arrayPositive.push(curve); diff --git a/core/geometry/src/curve/RegionOpsClassificationSweeps.ts b/core/geometry/src/curve/RegionOpsClassificationSweeps.ts index 387ff34853ee..74c66574f6e9 100644 --- a/core/geometry/src/curve/RegionOpsClassificationSweeps.ts +++ b/core/geometry/src/curve/RegionOpsClassificationSweeps.ts @@ -48,13 +48,21 @@ import { UnionRegion } from "./UnionRegion"; */ abstract class RegionOpsFaceToFaceSearchCallbacks { /** Announce a representative node on the outer face of a component */ - public startComponent(_node: HalfEdge): boolean { return true; } + public startComponent(_node: HalfEdge): boolean { + return true; + } /** Announce return to outer face */ - public finishComponent(_node: HalfEdge): boolean { return true; } + public finishComponent(_node: HalfEdge): boolean { + return true; + } /** Announce face entry */ - public enterFace(_facePathStack: HalfEdge[], _newFaceNode: HalfEdge): boolean { return true; } + public enterFace(_facePathStack: HalfEdge[], _newFaceNode: HalfEdge): boolean { + return true; + } /** Announce face exit */ - public leaveFace(_facePathStack: HalfEdge[], _newFaceNode: HalfEdge): boolean { return true; } + public leaveFace(_facePathStack: HalfEdge[], _newFaceNode: HalfEdge): boolean { + return true; + } } /** Function signature to test if a pair of boolean states is to be accepted by area booleans (during face-to-face sweeps) * @internal @@ -99,7 +107,10 @@ class RegionOpsBinaryBooleanSweepCallbacks extends RegionOpsFaceToFaceSearchCall this._faceSelectFunction = acceptFaceFunction; } /** Mark this face as exterior */ - public override startComponent(node: HalfEdge): boolean { node.setMaskAroundFace(this._exteriorMask); return true; } + public override startComponent(node: HalfEdge): boolean { + node.setMaskAroundFace(this._exteriorMask); + return true; + } /** * * If necessary, toggle a term state. * * if indicated, mark this face exterior. @@ -135,9 +146,14 @@ export class RegionOpsFaceToFaceSearch { * @param seed first node to visit. * @param faceHasBeenVisited mask marking faces that have been seen. * @param nodeHasBeenVisited mask marking node-to-node step around face. - * */ - public static faceToFaceSearchFromOuterLoop(_graph: HalfEdgeGraph, seed: HalfEdge, faceHasBeenVisited: HalfEdgeMask, nodeHasBeenVisited: HalfEdgeMask, callbacks: RegionOpsFaceToFaceSearchCallbacks) { + public static faceToFaceSearchFromOuterLoop( + _graph: HalfEdgeGraph, + seed: HalfEdge, + faceHasBeenVisited: HalfEdgeMask, + nodeHasBeenVisited: HalfEdgeMask, + callbacks: RegionOpsFaceToFaceSearchCallbacks, + ) { if (seed.isMaskSet(faceHasBeenVisited)) return; if (!callbacks.startComponent(seed)) @@ -159,7 +175,7 @@ export class RegionOpsFaceToFaceSearch { mate.setMaskAroundFace(faceHasBeenVisited); entryNode = mate; if (callbacks.enterFace(facePathStack, mate)) { - for (; ;) { + for (;;) { mate = faceNode.edgeMate; if (!mate.isMaskSet(faceHasBeenVisited)) { mate.setMaskAroundFace(faceHasBeenVisited); @@ -205,7 +221,12 @@ export class RegionOpsFaceToFaceSearch { * * sort edges around vertices * * add regularization edges so holes are connected to their parent. */ - public static doPolygonBoolean(loopsA: MultiLineStringDataVariant, loopsB: MultiLineStringDataVariant, faceSelectFunction: (inA: boolean, inB: boolean) => boolean, graphCheckPoint?: GraphCheckPointFunction): HalfEdgeGraph | undefined { + public static doPolygonBoolean( + loopsA: MultiLineStringDataVariant, + loopsB: MultiLineStringDataVariant, + faceSelectFunction: (inA: boolean, inB: boolean) => boolean, + graphCheckPoint?: GraphCheckPointFunction, + ): HalfEdgeGraph | undefined { const graph = new HalfEdgeGraph(); const baseMask = HalfEdgeMask.BOUNDARY_EDGE | HalfEdgeMask.PRIMARY_EDGE; const seedA = RegionOps.addLoopsWithEdgeTagToGraph(graph, loopsA, baseMask, 1); @@ -328,7 +349,9 @@ class RegionGroupMember { this.parentGroup = parentGroup; this.sweepState = 0; } - public clearState() { this.sweepState = 0; } + public clearState() { + this.sweepState = 0; + } } /** * A `RegionGroup` is @@ -397,7 +420,6 @@ export class RegionGroup { } } else if (allowLineSegment && data instanceof LineSegment3d) { this.members.push(new RegionGroupMember(data, this)); - } } // update the "in" count _numIn according to old and new states (parity counts) for some member region. @@ -479,15 +501,19 @@ export class RegionBooleanContext implements RegionOpsFaceToFaceSearchCallbacks const rangeAB = rangeA.union(rangeB); const areaTol = RegionOps.computeXYAreaTolerance(rangeAB); let margin = 0.1; - this._workSegment = PlaneAltitudeRangeContext.findExtremePointsInDirection(rangeAB.corners(), RegionBooleanContext._bridgeDirection, this._workSegment); + this._workSegment = PlaneAltitudeRangeContext.findExtremePointsInDirection( + rangeAB.corners(), + RegionBooleanContext._bridgeDirection, + this._workSegment, + ); if (this._workSegment) - margin *= this._workSegment.point0Ref.distanceXY(this._workSegment.point1Ref); // how much further to extend each bridge ray + margin *= this._workSegment.point0Ref.distanceXY(this._workSegment.point1Ref); // how much further to extend each bridge ray const maxPoints: Point3d[] = []; const findExtremePointsInLoop = (region: Loop) => { const area = RegionOps.computeXYArea(region); if (area === undefined || Math.abs(area) < areaTol) - return; // avoid bridging trivial faces + return; // avoid bridging trivial faces this._workSegment = PlaneAltitudeRangeContext.findExtremePointsInDirection(region, RegionBooleanContext._bridgeDirection, this._workSegment); if (this._workSegment) maxPoints.push(this._workSegment.point1Ref); @@ -557,7 +583,8 @@ export class RegionBooleanContext implements RegionOpsFaceToFaceSearchCallbacks */ public runClassificationSweep( binaryOp: RegionBinaryOpType, - announceFaceFunction?: AnnounceClassifiedFace) { + announceFaceFunction?: AnnounceClassifiedFace, + ) { this._announceFaceFunction = announceFaceFunction; this.binaryOp = binaryOp; this.graph.clearMask(HalfEdgeMask.EXTERIOR); @@ -624,7 +651,7 @@ export class RegionBooleanContext implements RegionOpsFaceToFaceSearchCallbacks private recordTransitionAcrossEdge(node: HalfEdge, delta: number): RegionGroupMember | undefined { const updateRegionGroupMemberState = (member: RegionGroupMember): RegionGroupMember => { if (member.parentGroup.groupOpType === RegionGroupOpType.NonBounding) - return member; // no transition across a bridge edge + return member; // no transition across a bridge edge if (delta !== 0) { const oldSweepState = member.sweepState; member.sweepState += delta; @@ -691,7 +718,6 @@ function areaUnderPartialCurveXY(detail: CurveLocationDetail | undefined, xyStar } let areaToChord = 0.0; if (detail && detail.curve && detail.hasFraction1) { - if (detail.curve instanceof LineSegment3d) { // ah .. nothing to do for a line segment } else if (detail.curve instanceof Arc3d) { @@ -705,7 +731,7 @@ function faceAreaFromCurvedEdgeData(faceSeed: HalfEdge): number { let area = 0.0; let edge = faceSeed; do { - area += (edge.sortData as number) * areaUnderPartialCurveXY((edge.edgeTag as CurveLocationDetail), edge, edge.faceSuccessor, faceSeed); + area += (edge.sortData as number) * areaUnderPartialCurveXY(edge.edgeTag as CurveLocationDetail, edge, edge.faceSuccessor, faceSeed); } while ((edge = edge.faceSuccessor) !== faceSeed); return area; } diff --git a/core/geometry/src/curve/StrokeOptions.ts b/core/geometry/src/curve/StrokeOptions.ts index fae64a0371bf..a27d77dfbb6e 100644 --- a/core/geometry/src/curve/StrokeOptions.ts +++ b/core/geometry/src/curve/StrokeOptions.ts @@ -139,7 +139,10 @@ export class StrokeOptions { * from the options. */ public static applyAngleTol( - options: StrokeOptions | undefined, minCount: number, sweepRadians: number, defaultStepRadians?: number, + options: StrokeOptions | undefined, + minCount: number, + sweepRadians: number, + defaultStepRadians?: number, ): number { sweepRadians = Math.abs(sweepRadians); let stepRadians = defaultStepRadians ? defaultStepRadians : Math.PI / 8.0; @@ -156,10 +159,12 @@ export class StrokeOptions { * @param edgeLength */ public static applyMaxEdgeLength( - options: StrokeOptions | undefined, minCount: number, edgeLength: number, + options: StrokeOptions | undefined, + minCount: number, + edgeLength: number, ): number { if (edgeLength < 0) - edgeLength = - edgeLength; + edgeLength = -edgeLength; if (minCount < 1) minCount = 1; if (options && options.maxEdgeLength && options.maxEdgeLength * minCount < edgeLength) { @@ -183,7 +188,7 @@ export class StrokeOptions { public applyChordTol(minCount: number, radius: number, sweepRadians: number): number { if (this.chordTol && this.chordTol > 0.0 && this.chordTol < radius) { const a = this.chordTol; - const stepRadians = 2.0 * Math.acos((1.0 - a / radius)); + const stepRadians = 2.0 * Math.acos(1.0 - a / radius); minCount = Geometry.stepCount(stepRadians, sweepRadians, minCount); } return minCount; @@ -202,8 +207,10 @@ export class StrokeOptions { } /** Return stroke count which is the larger of existing count or `this.minStrokesPerPrimitive` */ public applyMinStrokesPerPrimitive(minCount: number): number { - if (this.minStrokesPerPrimitive !== undefined && Number.isFinite(this.minStrokesPerPrimitive) - && this.minStrokesPerPrimitive > minCount) + if ( + this.minStrokesPerPrimitive !== undefined && Number.isFinite(this.minStrokesPerPrimitive) + && this.minStrokesPerPrimitive > minCount + ) minCount = this.minStrokesPerPrimitive; return minCount; } diff --git a/core/geometry/src/curve/UnionRegion.ts b/core/geometry/src/curve/UnionRegion.ts index 793ea5585a77..5b096f2edcc4 100644 --- a/core/geometry/src/curve/UnionRegion.ts +++ b/core/geometry/src/curve/UnionRegion.ts @@ -7,9 +7,9 @@ * @module Curve */ import { GeometryHandler } from "../geometry3d/GeometryHandler"; -import { AnyCurve } from "./CurveTypes"; import { CurveCollection } from "./CurveCollection"; import { RecursiveCurveProcessor } from "./CurveProcessor"; +import { AnyCurve } from "./CurveTypes"; import { GeometryQuery } from "./GeometryQuery"; import { Loop } from "./Loop"; import { ParityRegion } from "./ParityRegion"; diff --git a/core/geometry/src/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.ts b/core/geometry/src/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.ts index 37657efdfd18..51515866c674 100644 --- a/core/geometry/src/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.ts +++ b/core/geometry/src/curve/internalContexts/AppendPlaneIntersectionStrokeHandler.ts @@ -43,7 +43,7 @@ export class AppendPlaneIntersectionStrokeHandler extends NewtonRtoRStrokeHandle } public get getDerivativeB() { - return this._derivativeB; // <--- _derivativeB is not currently used anywhere. Provided getter to suppress lint error + return this._derivativeB; // <--- _derivativeB is not currently used anywhere. Provided getter to suppress lint error } public constructor(plane: PlaneAltitudeEvaluator, intersections: CurveLocationDetail[]) { @@ -70,7 +70,8 @@ export class AppendPlaneIntersectionStrokeHandler extends NewtonRtoRStrokeHandle cp: CurvePrimitive, numStrokes: number, fraction0: number, - fraction1: number): void { + fraction1: number, + ): void { this.startCurvePrimitive(cp); if (numStrokes < 1) numStrokes = 1; const df = 1.0 / numStrokes; @@ -87,7 +88,8 @@ export class AppendPlaneIntersectionStrokeHandler extends NewtonRtoRStrokeHandle point1: Point3d, _numStrokes: number, fraction0: number, - fraction1: number): void { + fraction1: number, + ): void { const h0 = this._plane.altitude(point0); const h1 = this._plane.altitude(point1); if (h0 * h1 > 0.0) diff --git a/core/geometry/src/curve/internalContexts/ChainCollectorContext.ts b/core/geometry/src/curve/internalContexts/ChainCollectorContext.ts index b4ffc2349b3b..d49a1c55e38a 100644 --- a/core/geometry/src/curve/internalContexts/ChainCollectorContext.ts +++ b/core/geometry/src/curve/internalContexts/ChainCollectorContext.ts @@ -55,7 +55,6 @@ export class ChainCollectorContext { } private _xyzWork0?: Point3d; private findAnyChainToConnect(xyz: Point3d): { chainIndex: number, atEnd: boolean } | undefined { - for (let chainIndexA = 0; chainIndexA < this._chains.length; chainIndexA++) { const path = this._chains[chainIndexA]; this._xyzWork1 = path[path.length - 1].endPoint(this._xyzWork1); @@ -112,7 +111,7 @@ export class ChainCollectorContext { } else { this._xyzWork0 = candidate.endPoint(this._xyzWork0); connect = this.findAnyChainToConnect(this._xyzWork0); - if (connect) { // START of new primitive .. + if (connect) { // START of new primitive .. if (connect.atEnd) { candidate.reverseInPlace(); this._chains[connect.chainIndex].push(candidate); @@ -169,7 +168,11 @@ export class ChainCollectorContext { * * primitiveB.startCut * * physical gap between primitives. */ - public static needBreakBetweenPrimitives(primitiveA: CurvePrimitive | undefined, primitiveB: CurvePrimitive | undefined, isXYOnly: boolean = false): boolean { + public static needBreakBetweenPrimitives( + primitiveA: CurvePrimitive | undefined, + primitiveB: CurvePrimitive | undefined, + isXYOnly: boolean = false, + ): boolean { if (primitiveA === undefined) return true; if (primitiveB === undefined) diff --git a/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts b/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts index 47000a0f0c6a..3f0c3ed83cd3 100644 --- a/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts +++ b/core/geometry/src/curve/internalContexts/CloneCurvesContext.ts @@ -38,7 +38,8 @@ export class CloneCurvesContext extends RecursiveCurveProcessorWithStack { if (result) { if (this._stack.length === 0) // this should only happen once !!! this._result = result; - else // push this result to top of stack. + // push this result to top of stack. + else this._stack[this._stack.length - 1].tryAddChild(result); } return result; @@ -53,7 +54,7 @@ export class CloneCurvesContext extends RecursiveCurveProcessorWithStack { const c = this.doClone(primitive); if (c !== undefined && this._stack.length > 0) { const parent = this._stack[this._stack.length - 1]; - if (parent instanceof CurveChain || parent instanceof BagOfCurves) + if (parent instanceof CurveChain || parent instanceof BagOfCurves) { if (Array.isArray(c)) { for (const c1 of c) { parent.tryAddChild(c1); @@ -61,6 +62,7 @@ export class CloneCurvesContext extends RecursiveCurveProcessorWithStack { } else { parent.tryAddChild(c); } + } } } } diff --git a/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts b/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts index 048812ce2d09..f0476668fac8 100644 --- a/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts +++ b/core/geometry/src/curve/internalContexts/CloneWithExpandedLineStrings.ts @@ -29,7 +29,9 @@ export class CloneWithExpandedLineStrings extends CloneCurvesContext { const n = packedPoints.length; const segments = []; for (let i = 0; i + 1 < n; i++) { - segments.push(LineSegment3d.createCapture(packedPoints.getPoint3dAtUncheckedPointIndex(i), packedPoints.getPoint3dAtUncheckedPointIndex(i + 1))); + segments.push( + LineSegment3d.createCapture(packedPoints.getPoint3dAtUncheckedPointIndex(i), packedPoints.getPoint3dAtUncheckedPointIndex(i + 1)), + ); } return segments; } diff --git a/core/geometry/src/curve/internalContexts/ClosestPointStrokeHandler.ts b/core/geometry/src/curve/internalContexts/ClosestPointStrokeHandler.ts index 19ea3149675d..107e60b26d60 100644 --- a/core/geometry/src/curve/internalContexts/ClosestPointStrokeHandler.ts +++ b/core/geometry/src/curve/internalContexts/ClosestPointStrokeHandler.ts @@ -96,7 +96,14 @@ export class ClosestPointStrokeHandler extends NewtonRtoRStrokeHandler implement this._closestPoint.curve = this._parentCurvePrimitive; } - public announceSegmentInterval(cp: CurvePrimitive, point0: Point3d, point1: Point3d, _numStrokes: number, fraction0: number, fraction1: number): void { + public announceSegmentInterval( + cp: CurvePrimitive, + point0: Point3d, + point1: Point3d, + _numStrokes: number, + fraction0: number, + fraction1: number, + ): void { let localFraction = this._spacePoint.fractionOfProjectionToLine(point0, point1, 0.0); // only consider extending the segment if the immediate caller says we are at endpoints ... if (!this._extend) diff --git a/core/geometry/src/curve/internalContexts/CurveCurveCloseApproachXY.ts b/core/geometry/src/curve/internalContexts/CurveCurveCloseApproachXY.ts index fb65db5426dc..f27d4d340509 100644 --- a/core/geometry/src/curve/internalContexts/CurveCurveCloseApproachXY.ts +++ b/core/geometry/src/curve/internalContexts/CurveCurveCloseApproachXY.ts @@ -16,7 +16,10 @@ import { GrowableFloat64Array } from "../../geometry3d/GrowableFloat64Array"; import { Point3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { - CurveCurveCloseApproachXYRRtoRRD, CurvePointCloseApproachXYRtoRD, Newton1dUnbounded, Newton2dUnboundedWithDerivative, + CurveCurveCloseApproachXYRRtoRRD, + CurvePointCloseApproachXYRtoRD, + Newton1dUnbounded, + Newton2dUnboundedWithDerivative, } from "../../numerics/Newton"; import { AnalyticRoots, SmallSystem } from "../../numerics/Polynomials"; import { Arc3d } from "../Arc3d"; @@ -119,7 +122,13 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { * the approach from pointA to pointB. */ private testAndRecordPointPairApproach( - cpA: CurvePrimitive, fA: number, pointA: Point3d, cpB: CurvePrimitive, fB: number, pointB: Point3d, reversed: boolean, + cpA: CurvePrimitive, + fA: number, + pointA: Point3d, + cpB: CurvePrimitive, + fB: number, + pointB: Point3d, + reversed: boolean, ): void { const d2 = pointA.distanceSquaredXY(pointB); if (d2 < this._maxDistanceSquared) { @@ -176,20 +185,28 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { const oldDetailA = this._results[numPrevious - 1].detailA; const oldDetailB = this._results[numPrevious - 1].detailB; if (reversed) { - if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } else { - if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } } const detailA = CurveLocationDetail.createCurveFractionPoint( - cpA, globalFractionA, cpA.fractionToPoint(globalFractionA), + cpA, + globalFractionA, + cpA.fractionToPoint(globalFractionA), ); const detailB = CurveLocationDetail.createCurveFractionPoint( - cpB, globalFractionB, cpB.fractionToPoint(globalFractionB), + cpB, + globalFractionB, + cpB.fractionToPoint(globalFractionB), ); if (isInterval) { detailA.captureFraction1Point1(globalFractionA1, cpA.fractionToPoint(globalFractionA1)); @@ -238,12 +255,16 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { const oldDetailA = this._results[numPrevious - 1].detailA; const oldDetailB = this._results[numPrevious - 1].detailB; if (reversed) { - if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } else { - if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } } @@ -264,12 +285,24 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB). */ public recordPairs( - cpA: CurvePrimitive, cpB: CurvePrimitive, pairs: CurveLocationDetailPair[] | undefined, reversed: boolean, + cpA: CurvePrimitive, + cpB: CurvePrimitive, + pairs: CurveLocationDetailPair[] | undefined, + reversed: boolean, ): void { if (pairs !== undefined) { for (const p of pairs) { this.recordPointWithLocalFractions( - p.detailA.fraction, cpA, 0, 1, p.detailB.fraction, cpB, 0, 1, reversed, p, + p.detailA.fraction, + cpA, + 0, + 1, + p.detailB.fraction, + cpB, + 0, + 1, + reversed, + p, ); } } @@ -281,7 +314,9 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { * @param reversed whether to reverse the details in the pair (e.g., so that detailB refers to geometryB). */ public captureDetailPair( - detailA: CurveLocationDetail | undefined, detailB: CurveLocationDetail | undefined, reversed: boolean, + detailA: CurveLocationDetail | undefined, + detailB: CurveLocationDetail | undefined, + reversed: boolean, ): void { if (detailA && detailB) { if (reversed) { @@ -298,7 +333,7 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { pointB1: Point3d, fractionB: number, maxDistanceSquared: number, - closestApproach: CurveLocationDetailPair, // modified on return + closestApproach: CurveLocationDetailPair, // modified on return ): boolean { let updated = false; if (fractionB < 0) @@ -441,7 +476,7 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { } const seeds = [0.2, 0.4, 0.6, 0.8]; // HEURISTIC: arcs have up to 4 perpendiculars; lines have only 1 const newtonEvaluator = new CurvePointCloseApproachXYRtoRD(curveP, pointQ); - const newtonSearcher = new Newton1dUnbounded(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 66 iters + const newtonSearcher = new Newton1dUnbounded(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 66 iters let minCloseApproachLength = Geometry.largeCoordinateResult; let minCurvePFraction: number | undefined; let minPointP: Point3d | undefined; @@ -469,9 +504,15 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { * * Does not test the endpoints of `cpB`. * * The only types supported for `cpB` are Arc3d, LineSegment3d, and LineString3d. * * If `cpB` is a LineString3d, then the interval `[fB0, fB1]` must correspond to a segment of the line string. - */ + */ private testAndRecordProjection( - cpA: CurvePrimitive, fA: number, pointA: Point3d, cpB: CurvePrimitive, fB0: number, fB1: number, reversed: boolean, + cpA: CurvePrimitive, + fA: number, + pointA: Point3d, + cpB: CurvePrimitive, + fB0: number, + fB1: number, + reversed: boolean, ) { let detail: CurveLocationDetail | undefined; if (cpB instanceof LineString3d) { @@ -511,7 +552,11 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { ): void { // compute a pair with fractions local to segments const approach = CurveCurveCloseApproachXY.segmentSegmentBoundedApproach( - pointA0, pointA1, pointB0, pointB1, this._maxDistanceSquared, + pointA0, + pointA1, + pointB0, + pointB1, + this._maxDistanceSquared, ); // adjust the pair to refer to input curves and global fractions, then record it if new if (approach) { @@ -535,8 +580,16 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { reversed: boolean, ): void { this.computeSegmentSegment3D( - cpA, pointA0, fractionA0, pointA1, fractionA1, - cpB, pointB0, fractionB0, pointB1, fractionB1, + cpA, + pointA0, + fractionA0, + pointA1, + fractionA1, + cpB, + pointB0, + fractionB0, + pointB1, + fractionB1, reversed, ); } @@ -553,7 +606,15 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { * @param arc the arc * @param reversed swap the details in the recorded pair (default: false) */ - public allPerpendicularsSegmentArcBounded(cpA: CurvePrimitive, pointA0: Point3d, fractionA0: number, pointA1: Point3d, fractionA1: number, arc: Arc3d, reversed: boolean = false): void { + public allPerpendicularsSegmentArcBounded( + cpA: CurvePrimitive, + pointA0: Point3d, + fractionA0: number, + pointA1: Point3d, + fractionA1: number, + arc: Arc3d, + reversed: boolean = false, + ): void { const dotUT = arc.vector0.crossProductStartEndXY(pointA0, pointA1); const dotVT = arc.vector90.crossProductStartEndXY(pointA0, pointA1); const parallelRadians = Math.atan2(dotVT, dotUT); @@ -611,18 +672,34 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { const sines = new GrowableFloat64Array(2); const radians = new GrowableFloat64Array(2); const numRoots = AnalyticRoots.appendImplicitLineUnitCircleIntersections( // solve the equation - alpha, beta, gamma, cosines, sines, radians, + alpha, + beta, + gamma, + cosines, + sines, + radians, ); for (let i = 0; i < numRoots; i++) { const arcPoint = data.center.plus2Scaled( - data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i), + data.vector0, + cosines.atUncheckedIndex(i), + data.vector90, + sines.atUncheckedIndex(i), ); const arcFraction = data.sweep.radiansToSignedPeriodicFraction(radians.atUncheckedIndex(i)); const lineFraction = SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint); // only add if the point is within the start and end fractions of both line segment and arc if (lineFraction !== undefined && this.acceptFraction(lineFraction) && this.acceptFraction(arcFraction)) { this.recordPointWithLocalFractions( - lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed, + lineFraction, + cpA, + fractionA0, + fractionA1, + arcFraction, + arc, + 0, + 1, + reversed, ); intersectionFound = true; } @@ -645,9 +722,9 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { public allPerpendicularsArcArcBounded(arc0: Arc3d, arc1: Arc3d, reversed: boolean = false): void { const newtonEvaluator = new CurveCurveCloseApproachXYRRtoRRD(arc0, arc1); // HEURISTIC: 2 ellipses have up to 8 perpendiculars and up to 4 intersections - const seedDelta = 1 / 10; // denominator 9 fails the unit test + const seedDelta = 1 / 10; // denominator 9 fails the unit test const seedStart = seedDelta / 2; - const newtonSearcher = new Newton2dUnboundedWithDerivative(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 49 iters + const newtonSearcher = new Newton2dUnboundedWithDerivative(newtonEvaluator, 100); // observed convergence to 1.0e-11 in 49 iters for (let seedU = seedStart; seedU < 1; seedU += seedDelta) { for (let seedV = seedStart; seedV < 1; seedV += seedDelta) { newtonSearcher.setUV(seedU, seedV); @@ -681,7 +758,9 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { } /** Low level dispatch of (beziers of) a bspline curve with (beziers of) a bspline curve */ private dispatchBSplineCurve3dBSplineCurve3d( - bcurveA: BSplineCurve3dBase, bcurveB: BSplineCurve3dBase, reversed: boolean, + bcurveA: BSplineCurve3dBase, + bcurveB: BSplineCurve3dBase, + reversed: boolean, ): void { const lsA = LineString3d.create(); bcurveA.emitStrokes(lsA); @@ -711,7 +790,7 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { const pointB1 = CurveCurveCloseApproachXY._workPointBB1; for (let i = 0; i < numB - 1; ++i) { const fB0 = i * deltaFracB; // global linestring fractions - const fB1 = (i + 1 === numB - 1) ? 1.0 : (i + 1) * deltaFracB; // make sure we nail the end fraction + const fB1 = (i + 1 === numB - 1) ? 1.0 : (i + 1) * deltaFracB; // make sure we nail the end fraction lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i, pointB0); lsB.packedPoints.getPoint3dAtUncheckedPointIndex(i + 1, pointB1); this.dispatchSegmentSegment(segA, pointA0, 0.0, pointA1, 1.0, lsB, pointB0, fB0, pointB1, fB1, reversed); @@ -743,14 +822,14 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { } /** Low level dispatch of curve collection. */ private dispatchCurveCollection(geomA: AnyCurve, geomAHandler: (geomA: any) => any): void { - const geomB = this._geometryB; // save + const geomB = this._geometryB; // save if (!geomB || !geomB.children || !(geomB instanceof CurveCollection)) return; for (const child of geomB.children) { this.resetGeometry(child); geomAHandler(geomA); } - this._geometryB = geomB; // restore + this._geometryB = geomB; // restore } /** Low level dispatch to geomA given a CurveChainWithDistanceIndex in geometryB. */ private dispatchCurveChainWithDistanceIndex(geomA: AnyCurve, geomAHandler: (geomA: any) => any): void { @@ -761,12 +840,12 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { return; } const index0 = this._results.length; - const geomB = this._geometryB; // save + const geomB = this._geometryB; // save for (const child of geomB.path.children) { this.resetGeometry(child); geomAHandler(geomA); } - this.resetGeometry(geomB); // restore + this.resetGeometry(geomB); // restore this._results = CurveChainWithDistanceIndex.convertChildDetailToChainDetail(this._results, index0, undefined, geomB, true); } /** Double dispatch handler for strongly typed segment. */ @@ -774,8 +853,16 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { if (this._geometryB instanceof LineSegment3d) { const segmentB = this._geometryB; this.dispatchSegmentSegment( - segmentA, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, - segmentB, segmentB.point0Ref, 0.0, segmentB.point1Ref, 1.0, + segmentA, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + segmentB, + segmentB.point0Ref, + 0.0, + segmentB.point1Ref, + 1.0, false, ); } else if (this._geometryB instanceof LineString3d) { @@ -889,7 +976,13 @@ export class CurveCurveCloseApproachXY extends RecurseToCurvesGeometryHandler { public override handleArc3d(arc0: Arc3d): any { if (this._geometryB instanceof LineSegment3d) { this.dispatchSegmentArc( - this._geometryB, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, arc0, true, + this._geometryB, + this._geometryB.point0Ref, + 0.0, + this._geometryB.point1Ref, + 1.0, + arc0, + true, ); } else if (this._geometryB instanceof LineString3d) { this.computeArcLineString(arc0, this._geometryB, false); diff --git a/core/geometry/src/curve/internalContexts/CurveCurveIntersectXY.ts b/core/geometry/src/curve/internalContexts/CurveCurveIntersectXY.ts index 8cfd4f65d3c9..64ac270b3e4b 100644 --- a/core/geometry/src/curve/internalContexts/CurveCurveIntersectXY.ts +++ b/core/geometry/src/curve/internalContexts/CurveCurveIntersectXY.ts @@ -187,20 +187,28 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const oldDetailA = this._results[numPrevious - 1].detailA; const oldDetailB = this._results[numPrevious - 1].detailB; if (reversed) { - if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } else { - if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } } const detailA = CurveLocationDetail.createCurveFractionPoint( - cpA, globalFractionA, cpA.fractionToPoint(globalFractionA), + cpA, + globalFractionA, + cpA.fractionToPoint(globalFractionA), ); const detailB = CurveLocationDetail.createCurveFractionPoint( - cpB, globalFractionB, cpB.fractionToPoint(globalFractionB), + cpB, + globalFractionB, + cpB.fractionToPoint(globalFractionB), ); if (isInterval) { detailA.captureFraction1Point1(globalFractionA1, cpA.fractionToPoint(globalFractionA1)); @@ -223,12 +231,24 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { * @param reversed true to have order reversed in final structures. */ public recordPairs( - cpA: CurvePrimitive, cpB: CurvePrimitive, pairs: CurveLocationDetailPair[] | undefined, reversed: boolean, + cpA: CurvePrimitive, + cpB: CurvePrimitive, + pairs: CurveLocationDetailPair[] | undefined, + reversed: boolean, ): void { if (pairs !== undefined) { for (const p of pairs) { this.recordPointWithLocalFractions( - p.detailA.fraction, cpA, 0, 1, p.detailB.fraction, cpB, 0, 1, reversed, p, + p.detailA.fraction, + cpA, + 0, + 1, + p.detailB.fraction, + cpB, + 0, + 1, + reversed, + p, ); } } @@ -258,19 +278,37 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { // So do the overlap first. This should do a quick exit in non-coincident case. const overlap = this._coincidentGeometryContext.coincidentSegmentRangeXY(pointA0, pointA1, pointB0, pointB1, false); if (overlap) { // the lines are coincident - if (this._coincidentGeometryContext.clampCoincidentOverlapToSegmentBounds( - overlap, pointA0, pointA1, pointB0, pointB1, - extendA0, extendA1, extendB0, extendB1, - )) { + if ( + this._coincidentGeometryContext.clampCoincidentOverlapToSegmentBounds( + overlap, + pointA0, + pointA1, + pointB0, + pointB1, + extendA0, + extendA1, + extendB0, + extendB1, + ) + ) { this.recordPointWithLocalFractions( - overlap.detailA.fraction, cpA, fractionA0, fractionA1, - overlap.detailB.fraction, cpB, fractionB0, fractionB1, - reversed, overlap, + overlap.detailA.fraction, + cpA, + fractionA0, + fractionA1, + overlap.detailB.fraction, + cpB, + fractionB0, + fractionB1, + reversed, + overlap, ); } } else if (SmallSystem.lineSegment3dXYTransverseIntersectionUnbounded(pointA0, pointA1, pointB0, pointB1, uv)) { - if (this.acceptFractionOnLine(extendA0, uv.x, extendA1, pointA0, pointA1, this._coincidentGeometryContext.tolerance) && - this.acceptFractionOnLine(extendB0, uv.y, extendB1, pointB0, pointB1, this._coincidentGeometryContext.tolerance)) { + if ( + this.acceptFractionOnLine(extendA0, uv.x, extendA1, pointA0, pointA1, this._coincidentGeometryContext.tolerance) && + this.acceptFractionOnLine(extendB0, uv.y, extendB1, pointB0, pointB1, this._coincidentGeometryContext.tolerance) + ) { this.recordPointWithLocalFractions(uv.x, cpA, fractionA0, fractionA1, uv.y, cpB, fractionB0, fractionB1, reversed); } } @@ -311,7 +349,15 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { if (this.acceptFraction(extendA0, fractionA, extendA1) && this.acceptFraction(extendB0, fractionB, extendB1)) { // final fraction acceptance uses original world points, with perspective-aware fractions this.recordPointWithLocalFractions( - fractionA, cpA, fractionA0, fractionA1, fractionB, cpB, fractionB0, fractionB1, reversed, + fractionA, + cpA, + fractionA0, + fractionA1, + fractionB, + cpB, + fractionB0, + fractionB1, + reversed, ); } } @@ -341,22 +387,56 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { // non-perspective projection CurveCurveIntersectXY.setTransformedWorkPoints(this._worldToLocalAffine, pointA0, pointA1, pointB0, pointB1); this.computeSegmentSegment3D( - cpA, extendA0, CurveCurveIntersectXY._workPointA0, - fractionA0, CurveCurveIntersectXY._workPointA1, fractionA1, extendA1, - cpB, extendB0, CurveCurveIntersectXY._workPointB0, - fractionB0, CurveCurveIntersectXY._workPointB1, fractionB1, extendB1, + cpA, + extendA0, + CurveCurveIntersectXY._workPointA0, + fractionA0, + CurveCurveIntersectXY._workPointA1, + fractionA1, + extendA1, + cpB, + extendB0, + CurveCurveIntersectXY._workPointB0, + fractionB0, + CurveCurveIntersectXY._workPointB1, + fractionB1, + extendB1, reversed, ); } else if (this._worldToLocalPerspective) { this.computeSegmentSegment3DH( - cpA, extendA0, pointA0, fractionA0, pointA1, fractionA1, extendA1, - cpB, extendB0, pointB0, fractionB0, pointB1, fractionB1, extendB1, + cpA, + extendA0, + pointA0, + fractionA0, + pointA1, + fractionA1, + extendA1, + cpB, + extendB0, + pointB0, + fractionB0, + pointB1, + fractionB1, + extendB1, reversed, ); } else { this.computeSegmentSegment3D( - cpA, extendA0, pointA0, fractionA0, pointA1, fractionA1, extendA1, - cpB, extendB0, pointB0, fractionB0, pointB1, fractionB1, extendB1, + cpA, + extendA0, + pointA0, + fractionA0, + pointA1, + fractionA1, + extendA1, + cpB, + extendB0, + pointB0, + fractionB0, + pointB1, + fractionB1, + extendB1, reversed, ); } @@ -396,17 +476,27 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const sines = new GrowableFloat64Array(2); const radians = new GrowableFloat64Array(2); const numRoots = AnalyticRoots.appendImplicitLineUnitCircleIntersections( - alpha, beta, gamma, cosines, sines, radians, + alpha, + beta, + gamma, + cosines, + sines, + radians, ); for (let i = 0; i < numRoots; i++) { const arcPoint = data.center.plus2Scaled( - data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i), + data.vector0, + cosines.atUncheckedIndex(i), + data.vector90, + sines.atUncheckedIndex(i), ); const arcFraction = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(i), extendB0); const lineFraction = SmallSystem.lineSegment3dHXYClosestPointUnbounded(pointA0H, pointA1H, arcPoint); - if (lineFraction !== undefined && + if ( + lineFraction !== undefined && this.acceptFraction(extendA0, lineFraction, extendA1) && - this.acceptFraction(extendB0, arcFraction, extendB1)) { + this.acceptFraction(extendB0, arcFraction, extendB1) + ) { this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed); } } @@ -425,19 +515,29 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const sines = new GrowableFloat64Array(2); const radians = new GrowableFloat64Array(2); const numRoots = AnalyticRoots.appendImplicitLineUnitCircleIntersections( - alpha, beta, gamma, cosines, sines, radians, + alpha, + beta, + gamma, + cosines, + sines, + radians, ); - const lineFractionTol = 1.0e-10; // TODO: why are we loosening tolerances here? + const lineFractionTol = 1.0e-10; // TODO: why are we loosening tolerances here? const arcFractionTol = 1.0e-7; for (let i = 0; i < numRoots; i++) { const arcPoint = data.center.plus2Scaled( - data.vector0, cosines.atUncheckedIndex(i), data.vector90, sines.atUncheckedIndex(i), + data.vector0, + cosines.atUncheckedIndex(i), + data.vector90, + sines.atUncheckedIndex(i), ); const arcFraction = data.sweep.radiansToSignedFraction(radians.atUncheckedIndex(i), extendB0); const lineFraction = SmallSystem.lineSegment3dXYClosestPointUnbounded(pointA0Local, pointA1Local, arcPoint); - if (lineFraction !== undefined && + if ( + lineFraction !== undefined && this.acceptFraction(extendA0, lineFraction, extendA1, lineFractionTol) && - this.acceptFraction(extendB0, arcFraction, extendB1, arcFractionTol)) { + this.acceptFraction(extendB0, arcFraction, extendB1, arcFractionTol) + ) { this.recordPointWithLocalFractions(lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed); } } @@ -468,10 +568,17 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const circleRadians: number[] = []; // find the intersection of the transformed arcs TrigPolynomial.solveUnitCircleHomogeneousEllipseIntersection( - localB.coffs[2], localB.coffs[5], localB.coffs[8], // center xyw - localB.coffs[0], localB.coffs[3], localB.coffs[6], // vector0 xyw - localB.coffs[1], localB.coffs[4], localB.coffs[7], // vector90 xyw - ellipseRadians, circleRadians, + localB.coffs[2], + localB.coffs[5], + localB.coffs[8], // center xyw + localB.coffs[0], + localB.coffs[3], + localB.coffs[6], // vector0 xyw + localB.coffs[1], + localB.coffs[4], + localB.coffs[7], // vector90 xyw + ellipseRadians, + circleRadians, ); // the intersections are transform-invariant, so the solution angles apply directly to the input arcs for (let i = 0; i < ellipseRadians.length; i++) { @@ -491,7 +598,13 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { * 5- Convert intersection angles to fractions and record intersections. */ private dispatchArcArc( - cpA: Arc3d, extendA0: boolean, extendA1: boolean, cpB: Arc3d, extendB0: boolean, extendB1: boolean, reversed: boolean, + cpA: Arc3d, + extendA0: boolean, + extendA1: boolean, + cpB: Arc3d, + extendB0: boolean, + extendB1: boolean, + reversed: boolean, ): void { let matrixA: Matrix3d; let matrixB: Matrix3d; @@ -499,10 +612,20 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const dataA = cpA.toTransformedPoint4d(this._worldToLocalPerspective); const dataB = cpB.toTransformedPoint4d(this._worldToLocalPerspective); matrixA = Matrix3d.createColumnsXYW( - dataA.vector0, dataA.vector0.w, dataA.vector90, dataA.vector90.w, dataA.center, dataA.center.w, + dataA.vector0, + dataA.vector0.w, + dataA.vector90, + dataA.vector90.w, + dataA.center, + dataA.center.w, ); matrixB = Matrix3d.createColumnsXYW( - dataB.vector0, dataB.vector0.w, dataB.vector90, dataA.vector90.w, dataB.center, dataB.center.w, + dataB.vector0, + dataB.vector0.w, + dataB.vector90, + dataA.vector90.w, + dataB.center, + dataB.center.w, ); } else { const dataA = cpA.toTransformedVectors(this._worldToLocalAffine); @@ -531,7 +654,13 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } } private dispatchArcBsplineCurve3d( - cpA: Arc3d, extendA0: boolean, extendA1: boolean, cpB: BSplineCurve3d, extendB0: boolean, extendB1: boolean, reversed: boolean, + cpA: Arc3d, + extendA0: boolean, + extendA1: boolean, + cpB: BSplineCurve3d, + extendB0: boolean, + extendB1: boolean, + reversed: boolean, ): void { // Arc: X = C + cU + sV // implicitize the arc as viewed. This "3d" matrix is homogeneous "XYW" not "xyz" @@ -539,7 +668,12 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { if (this._worldToLocalPerspective) { const dataA = cpA.toTransformedPoint4d(this._worldToLocalPerspective); matrixA = Matrix3d.createColumnsXYW( - dataA.vector0, dataA.vector0.w, dataA.vector90, dataA.vector90.w, dataA.center, dataA.center.w, + dataA.vector0, + dataA.vector0.w, + dataA.vector90, + dataA.vector90.w, + dataA.center, + dataA.center.w, ); } else { const dataA = cpA.toTransformedVectors(this._worldToLocalAffine); @@ -570,7 +704,7 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { if (matrixAInverse) { let bezier: BezierCurve3dH | undefined; - for (let spanIndex = 0; ; spanIndex++) { + for (let spanIndex = 0;; spanIndex++) { bezier = cpB.getSaturatedBezierSpan3dH(spanIndex, bezier); if (!bezier) break; if (this._worldToLocalPerspective) @@ -593,8 +727,10 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const c = bcurvePoint4d.dotProductXYZW(axx, axy, axz, axw); const s = bcurvePoint4d.dotProductXYZW(ayx, ayy, ayz, ayw); const arcFraction = cpA.sweep.radiansToSignedFraction(Math.atan2(s, c), extendA0); - if (this.acceptFraction(extendA0, arcFraction, extendA1) && - this.acceptFraction(extendB0, fractionB, extendB1)) { + if ( + this.acceptFraction(extendA0, arcFraction, extendA1) && + this.acceptFraction(extendB0, fractionB, extendB1) + ) { this.recordPointWithLocalFractions(arcFraction, cpA, 0, 1, fractionB, cpB, 0, 1, reversed); } } @@ -626,7 +762,7 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { bezierB: BezierCurve3dH, bcurveB: BSplineCurve3dBase, _strokeCountB: number, - univariateBezierB: UnivariateBezier, // caller-allocated for univariate coefficients. + univariateBezierB: UnivariateBezier, // caller-allocated for univariate coefficients. reversed: boolean, ): void { if (!this._xyzwA0) @@ -664,7 +800,11 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { bezierA.fractionToPoint4d(f1, this._xyzwA1); Point4d.createPlanePointPointZ(this._xyzwA0, this._xyzwA1, this._xyzwPlane); bezierB.poleProductsXYZW( - univariateBezierB.coffs, this._xyzwPlane.x, this._xyzwPlane.y, this._xyzwPlane.z, this._xyzwPlane.w, + univariateBezierB.coffs, + this._xyzwPlane.x, + this._xyzwPlane.y, + this._xyzwPlane.z, + this._xyzwPlane.w, ); let errors = 0; const roots = univariateBezierB.roots(0.0, true); @@ -673,7 +813,9 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { let bezierBFraction = r; bezierB.fractionToPoint4d(bezierBFraction, this._xyzwB); const segmentAFraction = SmallSystem.lineSegment3dHXYClosestPointUnbounded( - this._xyzwA0, this._xyzwA1, this._xyzwB, + this._xyzwA0, + this._xyzwA1, + this._xyzwB, ); if (segmentAFraction && Geometry.isIn01WithTolerance(segmentAFraction, intervalTolerance)) { let bezierAFraction = Geometry.interpolate(f0, segmentAFraction, f1); @@ -704,7 +846,15 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } if (this.acceptFraction(false, bcurveAFraction, false) && this.acceptFraction(false, bcurveBFraction, false)) { this.recordPointWithLocalFractions( - bcurveAFraction, bcurveA, 0, 1, bcurveBFraction, bcurveB, 0, 1, reversed, + bcurveAFraction, + bcurveA, + 0, + 1, + bcurveBFraction, + bcurveB, + 0, + 1, + reversed, ); } } @@ -713,7 +863,9 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } } private dispatchBSplineCurve3dBSplineCurve3d( - bcurveA: BSplineCurve3dBase, bcurveB: BSplineCurve3dBase, _reversed: boolean, + bcurveA: BSplineCurve3dBase, + bcurveB: BSplineCurve3dBase, + _reversed: boolean, ): void { const bezierSpanA = bcurveA.collectBezierSpans(true) as BezierCurve3dH[]; const bezierSpanB = bcurveB.collectBezierSpans(true) as BezierCurve3dH[]; @@ -734,11 +886,25 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const strokeCountB = bezierSpanB[b].computeStrokeCountForOptions(); if (strokeCountA < strokeCountB) this.dispatchBezierBezierStrokeFirst( - bezierSpanA[a], bcurveA, strokeCountA, bezierSpanB[b], bcurveB, strokeCountB, univariateCoffsB, _reversed, + bezierSpanA[a], + bcurveA, + strokeCountA, + bezierSpanB[b], + bcurveB, + strokeCountB, + univariateCoffsB, + _reversed, ); else this.dispatchBezierBezierStrokeFirst( - bezierSpanB[b], bcurveB, strokeCountB, bezierSpanA[a], bcurveA, strokeCountA, univariateCoffsA, !_reversed, + bezierSpanB[b], + bcurveB, + strokeCountB, + bezierSpanA[a], + bcurveA, + strokeCountA, + univariateCoffsA, + !_reversed, ); } } @@ -810,8 +976,13 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } /** Low level dispatch of linestring with (beziers of) a bspline curve. */ public dispatchLineStringBSplineCurve( - lsA: LineString3d, extendA0: boolean, extendA1: boolean, - curveB: BSplineCurve3d, extendB0: boolean, extendB1: boolean, reversed: boolean, + lsA: LineString3d, + extendA0: boolean, + extendA1: boolean, + curveB: BSplineCurve3d, + extendB0: boolean, + extendB1: boolean, + reversed: boolean, ): any { const numA = lsA.numPoints(); if (numA > 1) { @@ -826,16 +997,30 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { lsA.pointAt(iA, pointA1); fA1 = iA * dfA; this.dispatchSegmentBsplineCurve( - lsA, iA === 1 && extendA0, pointA0, fA0, pointA1, fA1, (iA + 1) === numA && extendA1, - curveB, extendB0, extendB1, reversed); + lsA, + iA === 1 && extendA0, + pointA0, + fA0, + pointA1, + fA1, + (iA + 1) === numA && extendA1, + curveB, + extendB0, + extendB1, + reversed, + ); } } return undefined; } /** Detail computation for segment intersecting linestring. */ public computeSegmentLineString( - lsA: LineSegment3d, extendA0: boolean, extendA1: boolean, - lsB: LineString3d, extendB0: boolean, extendB1: boolean, + lsA: LineSegment3d, + extendA0: boolean, + extendA1: boolean, + lsB: LineString3d, + extendB0: boolean, + extendB1: boolean, reversed: boolean, ): any { const pointA0 = lsA.point0Ref; @@ -853,8 +1038,20 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentSegment( - lsA, extendA0, pointA0, 0.0, pointA1, 1.0, extendA1, - lsB, ib === 1 && extendB0, pointB0, fB0, pointB1, fB1, (ib + 1) === numB && extendB1, + lsA, + extendA0, + pointA0, + 0.0, + pointA1, + 1.0, + extendA1, + lsB, + ib === 1 && extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && extendB1, reversed, ); } @@ -863,8 +1060,12 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } /** Detail computation for arc intersecting linestring. */ public computeArcLineString( - arcA: Arc3d, extendA0: boolean, extendA1: boolean, - lsB: LineString3d, extendB0: boolean, extendB1: boolean, + arcA: Arc3d, + extendA0: boolean, + extendA1: boolean, + lsB: LineString3d, + extendB0: boolean, + extendB1: boolean, reversed: boolean, ): any { const pointB0 = CurveCurveIntersectXY._workPointBB0; @@ -880,8 +1081,17 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentArc( - lsB, ib === 1 && extendB0, pointB0, fB0, pointB1, fB1, - (ib + 1) === numB && extendB1, arcA, extendA0, extendA1, !reversed, + lsB, + ib === 1 && extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && extendB1, + arcA, + extendA0, + extendA1, + !reversed, ); } } @@ -913,8 +1123,20 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentSegment( - lsA, ia === 1 && this._extendA0, pointA0, fA0, pointA1, fA1, (ia + 1) === numA && this._extendA1, - lsB, ib === 1 && this._extendB0, pointB0, fB0, pointB1, fB1, (ib + 1) === numB && this._extendB1, + lsA, + ia === 1 && this._extendA0, + pointA0, + fA0, + pointA1, + fA1, + (ia + 1) === numA && this._extendA1, + lsB, + ib === 1 && this._extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && this._extendB1, reversed, ); } @@ -922,7 +1144,11 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { } } private static setTransformedWorkPoints( - transform: Transform, pointA0: Point3d, pointA1: Point3d, pointB0: Point3d, pointB1: Point3d, + transform: Transform, + pointA0: Point3d, + pointA1: Point3d, + pointB0: Point3d, + pointB1: Point3d, ): void { transform.multiplyPoint3d(pointA0, this._workPointA0); transform.multiplyPoint3d(pointA1, this._workPointA1); @@ -934,7 +1160,7 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { * We take care of extend variables of geometry's children here if geometry is Path or Loop. */ private dispatchCurveCollection(geomA: AnyCurve, geomAHandler: (geomA: any) => any): void { - const geomB = this._geometryB; // save + const geomB = this._geometryB; // save if (!geomB || !geomB.children || !(geomB instanceof CurveCollection)) return; const children = geomB.children; @@ -975,7 +1201,11 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { this.dispatchCurveCollection(geomA, geomAHandler); this.resetGeometry(geomB); // restore this._results = CurveChainWithDistanceIndex.convertChildDetailToChainDetail( - this._results, index0, undefined, geomB, true, + this._results, + index0, + undefined, + geomB, + true, ); } /** @@ -986,7 +1216,7 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { const children = g.children; const extendA0 = this._extendA0; // save const extendA1 = this._extendA1; // save - if (children) + if (children) { for (let i = 0; i < children.length; i++) { if (g instanceof Path && children.length > 1) { if (i === 0) @@ -1002,29 +1232,66 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { this._extendA0 = extendA0; // restore this._extendA1 = extendA1; // restore } + } } /** Double dispatch handler for strongly typed segment. */ public override handleLineSegment3d(segmentA: LineSegment3d): any { if (this._geometryB instanceof LineSegment3d) { const segmentB = this._geometryB; this.dispatchSegmentSegment( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - segmentB, this._extendB0, segmentB.point0Ref, 0.0, segmentB.point1Ref, 1.0, this._extendB1, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + segmentB, + this._extendB0, + segmentB.point0Ref, + 0.0, + segmentB.point1Ref, + 1.0, + this._extendB1, false, ); } else if (this._geometryB instanceof LineString3d) { this.computeSegmentLineString( - segmentA, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof Arc3d) { this.dispatchSegmentArc( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchSegmentBsplineCurve( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(segmentA, this.handleLineSegment3d.bind(this)); @@ -1040,15 +1307,33 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { this.computeLineStringLineString(lsA, lsB, false); } else if (this._geometryB instanceof LineSegment3d) { this.computeSegmentLineString( - this._geometryB, this._extendB0, this._extendB1, lsA, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + lsA, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof Arc3d) { this.computeArcLineString( - this._geometryB, this._extendB0, this._extendB1, lsA, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + lsA, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchLineStringBSplineCurve( - lsA, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + lsA, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(lsA, this.handleLineString3d.bind(this)); @@ -1061,18 +1346,39 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { public override handleArc3d(arc0: Arc3d): any { if (this._geometryB instanceof LineSegment3d) { this.dispatchSegmentArc( - this._geometryB, this._extendB0, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, this._extendB1, - arc0, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._geometryB.point0Ref, + 0.0, + this._geometryB.point1Ref, + 1.0, + this._extendB1, + arc0, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof LineString3d) { this.computeArcLineString( - arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + arc0, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof Arc3d) { this.dispatchArcArc(arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchArcBsplineCurve3d( - arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + arc0, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(arc0, this.handleArc3d.bind(this)); @@ -1085,15 +1391,37 @@ export class CurveCurveIntersectXY extends RecurseToCurvesGeometryHandler { public override handleBSplineCurve3d(curve: BSplineCurve3d): any { if (this._geometryB instanceof LineSegment3d) { this.dispatchSegmentBsplineCurve( - this._geometryB, this._extendB0, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, this._extendB1, - curve, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._geometryB.point0Ref, + 0.0, + this._geometryB.point1Ref, + 1.0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof LineString3d) { this.dispatchLineStringBSplineCurve( - this._geometryB, this._extendB0, this._extendB1, curve, this._extendA0, this._extendA1, true); + this._geometryB, + this._extendB0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, + ); } else if (this._geometryB instanceof Arc3d) { this.dispatchArcBsplineCurve3d( - this._geometryB, this._extendB0, this._extendB1, curve, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof BSplineCurve3dBase) { this.dispatchBSplineCurve3dBSplineCurve3d(curve, this._geometryB, false); diff --git a/core/geometry/src/curve/internalContexts/CurveCurveIntersectXYZ.ts b/core/geometry/src/curve/internalContexts/CurveCurveIntersectXYZ.ts index 33a0881c53fe..b4f79e1cab84 100644 --- a/core/geometry/src/curve/internalContexts/CurveCurveIntersectXYZ.ts +++ b/core/geometry/src/curve/internalContexts/CurveCurveIntersectXYZ.ts @@ -110,12 +110,16 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { const oldDetailA = this._results[numPrevious - 1].detailA; const oldDetailB = this._results[numPrevious - 1].detailB; if (reversed) { - if (oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailB.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailA.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } else { - if (oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && - oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB })) + if ( + oldDetailA.isSameCurveAndFraction({ curve: cpA, fraction: globalFractionA }) && + oldDetailB.isSameCurveAndFraction({ curve: cpB, fraction: globalFractionB }) + ) return; } } @@ -158,8 +162,10 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { reversed: boolean, ): void { const uv = CurveCurveIntersectXYZ._workVector2dA; - if (SmallSystem.lineSegment3dClosestApproachUnbounded(pointA0, pointA1, pointB0, pointB1, uv) && - this.acceptFraction(extendA0, uv.x, extendA1) && this.acceptFraction(extendB0, uv.y, extendB1)) { + if ( + SmallSystem.lineSegment3dClosestApproachUnbounded(pointA0, pointA1, pointB0, pointB1, uv) && + this.acceptFraction(extendA0, uv.x, extendA1) && this.acceptFraction(extendB0, uv.y, extendB1) + ) { this.recordPointWithLocalFractions(uv.x, cpA, fractionA0, fractionA1, uv.y, cpB, fractionB0, fractionB1, reversed); } } @@ -185,8 +191,20 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { reversed: boolean, ): void { this.computeSegmentSegment3D( - cpA, extendA0, pointA0, fractionA0, pointA1, fractionA1, extendA1, - cpB, extendB0, pointB0, fractionB0, pointB1, fractionB1, extendB1, + cpA, + extendA0, + pointA0, + fractionA0, + pointA1, + fractionA1, + extendA1, + cpB, + extendB0, + pointB0, + fractionB0, + pointB1, + fractionB1, + extendB1, reversed, ); } @@ -205,7 +223,11 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { * @param vectorC second candidate for additional in-plane vector */ public createPlaneWithPreferredPerpendicular( - origin: Point3d, vectorA: Vector3d, cosineValue: number, vectorB: Vector3d, vectorC: Vector3d, + origin: Point3d, + vectorA: Vector3d, + cosineValue: number, + vectorB: Vector3d, + vectorC: Vector3d, ): Plane3dByOriginAndUnitNormal | undefined { cosineValue = Geometry.restrictToInterval(Math.abs(cosineValue), 0.0, 1.0 - Geometry.smallFraction); const dotAA = vectorA.magnitudeSquared(); @@ -237,7 +259,11 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { const lineVector = Vector3d.createStartEnd(pointA0, pointA1); const cosValue = 0.94; // cosine of 20 degrees const plane = this.createPlaneWithPreferredPerpendicular( - pointA0, lineVector, cosValue, arc.perpendicularVector, arc.vector0, + pointA0, + lineVector, + cosValue, + arc.perpendicularVector, + arc.vector0, ); if (plane !== undefined) { const candidates: CurveLocationDetail[] = []; @@ -252,7 +278,15 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { linePoint = pointA0.interpolate(lineFraction, pointA1, linePoint); if (linePoint.isAlmostEqualMetric(c.point) && this.acceptFraction(extendA0, lineFraction, extendA1)) { this.recordPointWithLocalFractions( - lineFraction, cpA, fractionA0, fractionA1, arcFraction, arc, 0, 1, reversed, + lineFraction, + cpA, + fractionA0, + fractionA1, + arcFraction, + arc, + 0, + 1, + reversed, ); } } @@ -265,17 +299,30 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { // Solves the arc-arc equations for that local ellipse with unit circle. // Solution fractions map directly to original arcs. private dispatchArcArcInPlane( - cpA: Arc3d, extendA0: boolean, extendA1: boolean, cpB: Arc3d, extendB0: boolean, extendB1: boolean, reversed: boolean, + cpA: Arc3d, + extendA0: boolean, + extendA1: boolean, + cpB: Arc3d, + extendB0: boolean, + extendB1: boolean, + reversed: boolean, ): void { const otherVectors = cpA.otherArcAsLocalVectors(cpB); if (otherVectors !== undefined) { const ellipseRadians: number[] = []; const circleRadians: number[] = []; TrigPolynomial.solveUnitCircleHomogeneousEllipseIntersection( - otherVectors.center.x, otherVectors.center.y, 1.0, - otherVectors.vector0.x, otherVectors.vector0.y, 0.0, - otherVectors.vector90.x, otherVectors.vector90.y, 0.0, - ellipseRadians, circleRadians, + otherVectors.center.x, + otherVectors.center.y, + 1.0, + otherVectors.vector0.x, + otherVectors.vector0.y, + 0.0, + otherVectors.vector90.x, + otherVectors.vector90.y, + 0.0, + ellipseRadians, + circleRadians, ); for (let i = 0; i < ellipseRadians.length; i++) { const fractionA = cpA.sweep.radiansToSignedFraction(circleRadians[i], extendA0); @@ -291,7 +338,13 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { // Selects the best conditioned arc (in xy parts) as "circle after inversion". // Solves the arc-arc equations. private dispatchArcArc( - cpA: Arc3d, extendA0: boolean, extendA1: boolean, cpB: Arc3d, extendB0: boolean, extendB1: boolean, reversed: boolean, + cpA: Arc3d, + extendA0: boolean, + extendA1: boolean, + cpB: Arc3d, + extendB0: boolean, + extendB1: boolean, + reversed: boolean, ): void { // If arcs are in different planes: // 1) Intersect each plane with the other arc (quadratic) @@ -315,8 +368,10 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { if (detailA.point.isAlmostEqual(detailB.point)) { const arcFractionA = cpA.sweep.fractionToSignedPeriodicFraction(detailA.fraction, extendA0); const arcFractionB = cpB.sweep.fractionToSignedPeriodicFraction(detailB.fraction, extendB0); - if (this.acceptFraction(extendA0, arcFractionA, extendA1) - && this.acceptFraction(extendB0, arcFractionB, extendB1)) { + if ( + this.acceptFraction(extendA0, arcFractionA, extendA1) + && this.acceptFraction(extendB0, arcFractionB, extendB1) + ) { this.recordPointWithLocalFractions(arcFractionA, cpA, 0, 1, arcFractionB, cpB, 0, 1, reversed); } } @@ -525,7 +580,9 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { // Selects the best conditioned arc (in xy parts) as "circle after inversion". // Solves the arc-arc equations. private dispatchBSplineCurve3dBSplineCurve3d( - _bcurveA: BSplineCurve3dBase, _bcurveB: BSplineCurve3dBase, _reversed: boolean, + _bcurveA: BSplineCurve3dBase, + _bcurveB: BSplineCurve3dBase, + _reversed: boolean, ): void { // TODO: B-spline XYZ intersection implementation /* @@ -687,8 +744,20 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentSegment( - lsA, extendA0, pointA0, 0.0, pointA1, 1.0, extendA1, - lsB, ib === 1 && extendB0, pointB0, fB0, pointB1, fB1, (ib + 1) === numB && extendB1, + lsA, + extendA0, + pointA0, + 0.0, + pointA1, + 1.0, + extendA1, + lsB, + ib === 1 && extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && extendB1, reversed, ); } @@ -718,8 +787,17 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentArc( - lsB, ib === 1 && extendB0, pointB0, fB0, pointB1, fB1, - (ib + 1) === numB && extendB1, arcA, extendA0, extendA1, !reversed, + lsB, + ib === 1 && extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && extendB1, + arcA, + extendA0, + extendA1, + !reversed, ); } } @@ -751,8 +829,20 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { lsB.pointAt(ib, pointB1); fB1 = ib * dfB; this.dispatchSegmentSegment( - lsA, ia === 1 && this._extendA0, pointA0, fA0, pointA1, fA1, (ia + 1) === numA && this._extendA1, - lsB, ib === 1 && this._extendB0, pointB0, fB0, pointB1, fB1, (ib + 1) === numB && this._extendB1, + lsA, + ia === 1 && this._extendA0, + pointA0, + fA0, + pointA1, + fA1, + (ia + 1) === numA && this._extendA1, + lsB, + ib === 1 && this._extendB0, + pointB0, + fB0, + pointB1, + fB1, + (ib + 1) === numB && this._extendB1, reversed, ); } @@ -805,18 +895,22 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { this.dispatchCurveCollection(geomA, geomAHandler); this.resetGeometry(geomB); // restore this._results = CurveChainWithDistanceIndex.convertChildDetailToChainDetail( - this._results, index0, undefined, geomB, true, + this._results, + index0, + undefined, + geomB, + true, ); } /** - * Invoke `child.dispatchToGeometryHandler(this)` for each child in the array returned by the query `g.children`. - * We take care of extend variables of geometry's children here if geometry is Path or Loop. - */ + * Invoke `child.dispatchToGeometryHandler(this)` for each child in the array returned by the query `g.children`. + * We take care of extend variables of geometry's children here if geometry is Path or Loop. + */ public override handleChildren(g: GeometryQuery): any { const children = g.children; const extendA0 = this._extendA0; // save const extendA1 = this._extendA1; // save - if (children) + if (children) { for (let i = 0; i < children.length; i++) { if (g instanceof Path && children.length > 1) { if (i === 0) @@ -832,29 +926,66 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { this._extendA0 = extendA0; // restore this._extendA1 = extendA1; // restore } + } } /** Double dispatch handler for strongly typed segment. */ public override handleLineSegment3d(segmentA: LineSegment3d): any { if (this._geometryB instanceof LineSegment3d) { const segmentB = this._geometryB; this.dispatchSegmentSegment( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - segmentB, this._extendB0, segmentB.point0Ref, 0.0, segmentB.point1Ref, 1.0, this._extendB1, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + segmentB, + this._extendB0, + segmentB.point0Ref, + 0.0, + segmentB.point1Ref, + 1.0, + this._extendB1, false, ); } else if (this._geometryB instanceof LineString3d) { this.computeSegmentLineString( - segmentA, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof Arc3d) { this.dispatchSegmentArc( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchSegmentBsplineCurve( - segmentA, this._extendA0, segmentA.point0Ref, 0.0, segmentA.point1Ref, 1.0, this._extendA1, - this._geometryB, this._extendB0, this._extendB1, false, + segmentA, + this._extendA0, + segmentA.point0Ref, + 0.0, + segmentA.point1Ref, + 1.0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(segmentA, this.handleLineSegment3d.bind(this)); @@ -870,15 +1001,33 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { this.computeLineStringLineString(lsA, lsB, false); } else if (this._geometryB instanceof LineSegment3d) { this.computeSegmentLineString( - this._geometryB, this._extendB0, this._extendB1, lsA, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + lsA, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof Arc3d) { this.computeArcLineString( - this._geometryB, this._extendB0, this._extendB1, lsA, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + lsA, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchLineStringBSplineCurve( - lsA, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + lsA, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(lsA, this.handleLineString3d.bind(this)); @@ -891,20 +1040,47 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { public override handleArc3d(arc0: Arc3d): any { if (this._geometryB instanceof LineSegment3d) { this.dispatchSegmentArc( - this._geometryB, this._extendB0, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, this._extendB1, - arc0, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._geometryB.point0Ref, + 0.0, + this._geometryB.point1Ref, + 1.0, + this._extendB1, + arc0, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof LineString3d) { this.computeArcLineString( - arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + arc0, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof Arc3d) { this.dispatchArcArc( - arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + arc0, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof BSplineCurve3d) { this.dispatchArcBsplineCurve3d( - arc0, this._extendA0, this._extendA1, this._geometryB, this._extendB0, this._extendB1, false, + arc0, + this._extendA0, + this._extendA1, + this._geometryB, + this._extendB0, + this._extendB1, + false, ); } else if (this._geometryB instanceof CurveCollection) { this.dispatchCurveCollection(arc0, this.handleArc3d.bind(this)); @@ -917,17 +1093,37 @@ export class CurveCurveIntersectXYZ extends RecurseToCurvesGeometryHandler { public override handleBSplineCurve3d(curve: BSplineCurve3d): any { if (this._geometryB instanceof LineSegment3d) { this.dispatchSegmentBsplineCurve( - this._geometryB, this._extendB0, this._geometryB.point0Ref, 0.0, this._geometryB.point1Ref, 1.0, this._extendB1, - curve, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._geometryB.point0Ref, + 0.0, + this._geometryB.point1Ref, + 1.0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof LineString3d) { this.dispatchLineStringBSplineCurve( - this._geometryB, this._extendB0, this._extendB1, curve, this._extendA0, this._extendA1, true, + this._geometryB, + this._extendB0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof Arc3d) { this.dispatchArcBsplineCurve3d( - this._geometryB, this._extendB0, this._extendB1, curve, this._extendA0, this._extendA1, true, - + this._geometryB, + this._extendB0, + this._extendB1, + curve, + this._extendA0, + this._extendA1, + true, ); } else if (this._geometryB instanceof BSplineCurve3dBase) { this.dispatchBSplineCurve3dBSplineCurve3d(curve, this._geometryB, false); diff --git a/core/geometry/src/curve/internalContexts/CurveLengthContext.ts b/core/geometry/src/curve/internalContexts/CurveLengthContext.ts index 501ca8bdf116..4c11df1d064b 100644 --- a/core/geometry/src/curve/internalContexts/CurveLengthContext.ts +++ b/core/geometry/src/curve/internalContexts/CurveLengthContext.ts @@ -90,7 +90,14 @@ export class CurveLengthContext implements IStrokeHandler { } } - public announceSegmentInterval(_cp: CurvePrimitive, point0: Point3d, point1: Point3d, _numStrokes: number, fraction0: number, fraction1: number): void { + public announceSegmentInterval( + _cp: CurvePrimitive, + point0: Point3d, + point1: Point3d, + _numStrokes: number, + fraction0: number, + fraction1: number, + ): void { const segmentLength = point0.distance(point1); if (this._fraction0 <= fraction0 && fraction1 <= this._fraction1) this._summedLength += segmentLength; diff --git a/core/geometry/src/curve/internalContexts/CurveOffsetXYHandler.ts b/core/geometry/src/curve/internalContexts/CurveOffsetXYHandler.ts index a2c7cc05c23d..9927191b2970 100644 --- a/core/geometry/src/curve/internalContexts/CurveOffsetXYHandler.ts +++ b/core/geometry/src/curve/internalContexts/CurveOffsetXYHandler.ts @@ -34,12 +34,10 @@ export class CurveOffsetXYHandler implements IStrokeHandler { this._offsetDistance = offsetDistance; this._fitOptions = new InterpolationCurve3dOptions(); const startTangent = cp.fractionToPointAndUnitTangent(0.0, this._r0).direction.clone(); - const endTangent = cp.fractionToPointAndUnitTangent(1.0, this._r0).direction.negate(); // points into curve + const endTangent = cp.fractionToPointAndUnitTangent(1.0, this._r0).direction.negate(); // points into curve this._fitOptions.startTangent = startTangent; this._fitOptions.endTangent = endTangent; - if (this._fitOptions.closed = ( - cp.startPoint(this._p0).isAlmostEqual(cp.endPoint(this._p1)) && startTangent.isParallelTo(endTangent, true) - )) + if (this._fitOptions.closed = cp.startPoint(this._p0).isAlmostEqual(cp.endPoint(this._p1)) && startTangent.isParallelTo(endTangent, true)) this._fitOptions.isChordLenKnots = 1; } private pushOffsetPoint(xyz: Point3d, tangent: Vector3d) { @@ -49,12 +47,15 @@ export class CurveOffsetXYHandler implements IStrokeHandler { public needPrimaryGeometryForStrokes() { return true; } - public startParentCurvePrimitive(_cp: CurvePrimitive) { } - public startCurvePrimitive(_cp: CurvePrimitive) { } - public endCurvePrimitive(_cp: CurvePrimitive) { } - public endParentCurvePrimitive(_cp: CurvePrimitive) { } + public startParentCurvePrimitive(_cp: CurvePrimitive) {} + public startCurvePrimitive(_cp: CurvePrimitive) {} + public endCurvePrimitive(_cp: CurvePrimitive) {} + public endParentCurvePrimitive(_cp: CurvePrimitive) {} public announceIntervalForUniformStepStrokes( - cp: CurvePrimitive, numStrokes: number, fraction0: number, fraction1: number, + cp: CurvePrimitive, + numStrokes: number, + fraction0: number, + fraction1: number, ): void { // announce both start and end; adjacent duplicates will be filtered by c2 cubic fit logic for (let i = 0; i <= numStrokes; ++i) { @@ -64,7 +65,12 @@ export class CurveOffsetXYHandler implements IStrokeHandler { } } public announceSegmentInterval( - _cp: CurvePrimitive, point0: Point3d, point1: Point3d, numStrokes: number, _fraction0: number, _fraction1: number, + _cp: CurvePrimitive, + point0: Point3d, + point1: Point3d, + numStrokes: number, + _fraction0: number, + _fraction1: number, ): void { if (numStrokes > 0) { const tangent = Vector3d.createStartEnd(point0, point1, this._v1); diff --git a/core/geometry/src/curve/internalContexts/EllipticalArcApproximationContext.ts b/core/geometry/src/curve/internalContexts/EllipticalArcApproximationContext.ts index 5f618b319b03..30d35e2e778a 100644 --- a/core/geometry/src/curve/internalContexts/EllipticalArcApproximationContext.ts +++ b/core/geometry/src/curve/internalContexts/EllipticalArcApproximationContext.ts @@ -30,7 +30,7 @@ function compareFractionsIncreasing(f0: number, f1: number): number { if (Geometry.isAlmostEqualNumber(f0, f1, Geometry.smallFraction)) return 0; return f0 < f1 ? -1 : 1; -}; +} /** * Comparison callback to sort fractions in decreasing order with suitable tolerance for equality. * @internal @@ -39,12 +39,12 @@ function compareFractionsDecreasing(f0: number, f1: number): number { if (Geometry.isAlmostEqualNumber(f0, f1, Geometry.smallFraction)) return 0; return f0 < f1 ? 1 : -1; -}; +} /** * Structured data carrier used by the elliptical arc sampler. * @internal -*/ + */ export class QuadrantFractions { private _quadrant: 1 | 2 | 3 | 4; private _fractions: number[]; @@ -52,7 +52,10 @@ export class QuadrantFractions { private _interpolateEndTangent: boolean; private _averageAdded: boolean; private constructor( - quadrant: 1 | 2 | 3 | 4, fractions: number[], interpolateStartTangent: boolean, interpolateEndTangent: boolean, + quadrant: 1 | 2 | 3 | 4, + fractions: number[], + interpolateStartTangent: boolean, + interpolateEndTangent: boolean, ) { this._quadrant = quadrant; this._fractions = fractions; @@ -120,7 +123,7 @@ export class QuadrantFractions { * with circular arcs. * * This flag is set if a given sample method/arc yielded only two fractions, so their average was inserted in the * fractions array to meet this minimum three-sample requirement. - */ + */ public get averageAdded(): boolean { return this._fractions.length === 3 ? this._averageAdded : false; } @@ -136,19 +139,28 @@ export class QuadrantFractions { * * The returned sweep is always counterclockwise: angle0 < angle1. */ public static getQuadrantRadians( - radians0: number, radians1: number, + radians0: number, + radians1: number, ): { quadrant: 1 | 2 | 3 | 4, angle0: number, angle1: number } | undefined { - if (AngleSweep.isRadiansInStartEnd(radians0, 0, Angle.piOver2Radians) - && AngleSweep.isRadiansInStartEnd(radians1, 0, Angle.piOver2Radians)) + if ( + AngleSweep.isRadiansInStartEnd(radians0, 0, Angle.piOver2Radians) + && AngleSweep.isRadiansInStartEnd(radians1, 0, Angle.piOver2Radians) + ) return { quadrant: 1, angle0: 0, angle1: Angle.piOver2Radians }; - if (AngleSweep.isRadiansInStartEnd(radians0, Angle.piOver2Radians, Angle.piRadians) - && AngleSweep.isRadiansInStartEnd(radians1, Angle.piOver2Radians, Angle.piRadians)) + if ( + AngleSweep.isRadiansInStartEnd(radians0, Angle.piOver2Radians, Angle.piRadians) + && AngleSweep.isRadiansInStartEnd(radians1, Angle.piOver2Radians, Angle.piRadians) + ) return { quadrant: 2, angle0: Angle.piOver2Radians, angle1: Angle.piRadians }; - if (AngleSweep.isRadiansInStartEnd(radians0, Angle.piRadians, Angle.pi3Over2Radians) - && AngleSweep.isRadiansInStartEnd(radians1, Angle.piRadians, Angle.pi3Over2Radians)) + if ( + AngleSweep.isRadiansInStartEnd(radians0, Angle.piRadians, Angle.pi3Over2Radians) + && AngleSweep.isRadiansInStartEnd(radians1, Angle.piRadians, Angle.pi3Over2Radians) + ) return { quadrant: 3, angle0: Angle.piRadians, angle1: Angle.pi3Over2Radians }; - if (AngleSweep.isRadiansInStartEnd(radians0, Angle.pi3Over2Radians, Angle.pi2Radians) - && AngleSweep.isRadiansInStartEnd(radians1, Angle.pi3Over2Radians, Angle.pi2Radians)) + if ( + AngleSweep.isRadiansInStartEnd(radians0, Angle.pi3Over2Radians, Angle.pi2Radians) + && AngleSweep.isRadiansInStartEnd(radians1, Angle.pi3Over2Radians, Angle.pi2Radians) + ) return { quadrant: 4, angle0: Angle.pi3Over2Radians, angle1: Angle.pi2Radians }; return undefined; } @@ -169,7 +181,7 @@ export class QuadrantFractions { this._fractions.reverse(); [this._interpolateStartTangent, this._interpolateEndTangent] = [this._interpolateEndTangent, this._interpolateStartTangent]; } -}; +} /** * Base class specifying callbacks for processing samples of an elliptical arc. @@ -182,7 +194,9 @@ class QuadrantFractionsProcessor { * announced in the opposite order and with the opposite orientation. * @return whether to process `q` */ - public announceQuadrantBegin(_q: QuadrantFractions, _reversed: boolean): boolean { return true; } + public announceQuadrantBegin(_q: QuadrantFractions, _reversed: boolean): boolean { + return true; + } /** * Retrieve the fraction preceding the input fraction in process order. * * This optional callback facilitates processors like [[AdaptiveSubdivisionQ1ErrorProcessor]] whose implementation @@ -202,14 +216,14 @@ class QuadrantFractionsProcessor { * @param _f0 fractional parameter of E at which point `arc` starts * @param _f1 fractional parameter of E at which point `arc` ends */ - public announceArc(_arc: Arc3d, _fPrev: number | undefined, _f0: number, _f1: number): void { } + public announceArc(_arc: Arc3d, _fPrev: number | undefined, _f0: number, _f1: number): void {} /** * Announce the end of processing for quadrant `q`. * @param _reversed whether `q.reverse()` was invoked before processing (see [[announceQuadrantBegin]]). If so, * after this call `q.reverse()` is invoked again. */ - public announceQuadrantEnd(_q: QuadrantFractions, _reversed: boolean): void { } -}; + public announceQuadrantEnd(_q: QuadrantFractions, _reversed: boolean): void {} +} /** * Processor for computing the error of a sample-based arc chain approximation. @@ -284,7 +298,7 @@ class ArcChainErrorProcessor extends QuadrantFractionsProcessor { const childPerp = ArcChainErrorProcessor.computePrimitiveErrorXY(childApproximation, this.ellipticalArc, f0, f1); if (childPerp && (!this.maxPerpendicular || this.maxPerpendicular.detailA.a < childPerp.detailA.a)) this.maxPerpendicular = childPerp; - }; + } public override announceArc(arc: Arc3d, _fPrev: number | undefined, f0: number, f1: number): void { this.updateMaxPerpendicular(arc, f0, f1); } @@ -355,7 +369,8 @@ class AdaptiveSubdivisionQ1IntervalErrorProcessor extends QuadrantFractionsProce if (perp) { if (this.f === f1) this._error0 = perp.detailA.a; // first arc error - else // f === f0 + // f === f0 + else this._error1 = perp.detailA.a; // second arc error } } @@ -505,7 +520,7 @@ interface EllipticalArcSampler { * @return array of radian angles */ computeRadiansStrictlyInsideQuadrant1(result?: number[]): number[]; -}; +} /** * Implementation for method `EllipticalArcSampleMethod.UniformParameter` @@ -519,7 +534,8 @@ class UniformParameterSampler implements EllipticalArcSampler { this._options = o; } public static create( - context: EllipticalArcApproximationContext, options: EllipticalArcApproximationOptions, + context: EllipticalArcApproximationContext, + options: EllipticalArcApproximationOptions, ): UniformParameterSampler { return new UniformParameterSampler(context, options); } @@ -533,7 +549,7 @@ class UniformParameterSampler implements EllipticalArcSampler { } return result; } -}; +} /** * Implementation for method `EllipticalArcSampleMethod.NonUniformCurvature` @@ -554,7 +570,8 @@ class NonUniformCurvatureSampler implements EllipticalArcSampler { this._curvatureRange = Range1d.createXX(Math.sqrt(this._xMag2) / this._yMag2, Math.sqrt(this._yMag2) / this._xMag2); } public static create( - context: EllipticalArcApproximationContext, options: EllipticalArcApproximationOptions, + context: EllipticalArcApproximationContext, + options: EllipticalArcApproximationOptions, ): NonUniformCurvatureSampler { return new NonUniformCurvatureSampler(context, options); } @@ -606,7 +623,7 @@ class NonUniformCurvatureSampler implements EllipticalArcSampler { } return result; } -}; +} /** * Implementation for method `EllipticalArcSampleMethod.UniformCurvature`. @@ -619,11 +636,12 @@ class UniformCurvatureSampler extends NonUniformCurvatureSampler implements Elli this._options.remapFunction = (x: number) => x; // identity map } public static override create( - context: EllipticalArcApproximationContext, options: EllipticalArcApproximationOptions, + context: EllipticalArcApproximationContext, + options: EllipticalArcApproximationOptions, ): UniformCurvatureSampler { return new UniformCurvatureSampler(context, options); } -}; +} /** * Implementation for method `EllipticalArcSampleMethod.AdaptiveSubdivision` @@ -645,7 +663,7 @@ class AdaptiveSubdivisionSampler implements EllipticalArcSampler { * Return a copy of the arc to approximate, transformed to local coordinates, and with full sweep. * * Local coordinates allows us to ignore z in determining approximation error. * * Full sweep guarantees we have the first quadrant in which to do our computations. - */ + */ public get fullEllipseXY(): Arc3d { return this._fullEllipseXY; } @@ -660,7 +678,7 @@ class AdaptiveSubdivisionSampler implements EllipticalArcSampler { } while (processor.isRefined); return processor.getRefinedInteriorQ1Angles(result); } -}; +} /** * Processor for constructing a sample-based circular arc chain approximation. @@ -696,7 +714,7 @@ class ArcChainConstructionProcessor extends QuadrantFractionsProcessor { this._chain.tryAddChild(child); // captured! } } -}; +} /** * Context for sampling a non-circular Arc3d and for constructing an approximation to it based on interpolation @@ -791,9 +809,11 @@ export class EllipticalArcApproximationContext { * @param quadrants structured samples, may be temporarily reversed for symmetry * @param processor callbacks for handling the constructed arcs * @internal - */ + */ public static processQuadrantFractions( - ellipticalArc: Arc3d, quadrants: QuadrantFractions[], processor: QuadrantFractionsProcessor, + ellipticalArc: Arc3d, + quadrants: QuadrantFractions[], + processor: QuadrantFractionsProcessor, ): void { const pt0 = this.workPt0; const pt1 = this.workPt1; @@ -934,7 +954,8 @@ export class EllipticalArcApproximationContext { * @internal */ public computeSampleFractions( - options: EllipticalArcApproximationOptions, structuredOutput: boolean = false, + options: EllipticalArcApproximationOptions, + structuredOutput: boolean = false, ): QuadrantFractions[] | number[] { if (!this.isValidEllipticalArc) return []; @@ -949,7 +970,8 @@ export class EllipticalArcApproximationContext { return a0 < a1 ? 1 : -1; }; const compareQuadrantFractions: OrderedComparator = ( - q0: QuadrantFractions, q1: QuadrantFractions, + q0: QuadrantFractions, + q1: QuadrantFractions, ): number => { // ASSUME QuadrantFractions.fractions arrays are sorted (increasing) and have only trivial overlap if (compareFractionsIncreasing(q0.fractions[q0.fractions.length - 1], q1.fractions[0]) <= 0) @@ -968,7 +990,11 @@ export class EllipticalArcApproximationContext { return { angle, inSweep }; }; const convertAndAddRadiansToFractionInRange = ( - dest: OrderedSet, radians: number, sweep: AngleSweep, f0?: number, f1?: number, + dest: OrderedSet, + radians: number, + sweep: AngleSweep, + f0?: number, + f1?: number, ): number | undefined => { if (undefined === f0) f0 = 0; @@ -984,7 +1010,10 @@ export class EllipticalArcApproximationContext { return fraction; }; const convertQ1RadiansInSweepToQuadrantFractions = ( - anglesInQ1: number[], angle0: number, angle1: number, sweep: AngleSweep, + anglesInQ1: number[], + angle0: number, + angle1: number, + sweep: AngleSweep, ): QuadrantFractions | undefined => { if (angle0 > angle1) return convertQ1RadiansInSweepToQuadrantFractions(anglesInQ1, angle1, angle0, sweep); diff --git a/core/geometry/src/curve/internalContexts/MultiChainCollector.ts b/core/geometry/src/curve/internalContexts/MultiChainCollector.ts index 7748c8afc8a0..bfe9c823d5d7 100644 --- a/core/geometry/src/curve/internalContexts/MultiChainCollector.ts +++ b/core/geometry/src/curve/internalContexts/MultiChainCollector.ts @@ -113,7 +113,7 @@ export class MultiChainCollector { } /** If allowed by the geometry type, move an endpoint. */ private static simpleEndPointMove(curve: CurvePrimitive, atEnd: boolean, to: XYAndZ): boolean { - if (curve instanceof (LineSegment3d)) { + if (curve instanceof LineSegment3d) { if (atEnd) { curve.point1Ref.setFrom(to); } else { @@ -332,7 +332,7 @@ export class MultiChainCollector { /** * Return chains as individual calls to announceChain. * * Does not use planeTolerance. - */ + */ public announceChainsAsLineString3d(announceChain: (ls: LineString3d) => void, options?: StrokeOptions): void { const chains = this._chains; if (chains.length === 1) { diff --git a/core/geometry/src/curve/internalContexts/PlaneAltitudeRangeContext.ts b/core/geometry/src/curve/internalContexts/PlaneAltitudeRangeContext.ts index 9675624a47ab..45921e535c4e 100644 --- a/core/geometry/src/curve/internalContexts/PlaneAltitudeRangeContext.ts +++ b/core/geometry/src/curve/internalContexts/PlaneAltitudeRangeContext.ts @@ -110,20 +110,21 @@ export class PlaneAltitudeRangeContext extends RecurseToCurvesGeometryHandler { this._sineCosinePolynomial = g.getPlaneAltitudeSineCosinePolynomial(this.plane, this._sineCosinePolynomial); let radians = this._sineCosinePolynomial.referenceMinMaxRadians(); if (g.sweep.isRadiansInSweep(radians)) - this.announcePoint((this._workPoint = g.radiansToPoint(radians, this._workPoint))); + this.announcePoint(this._workPoint = g.radiansToPoint(radians, this._workPoint)); radians += Math.PI; if (g.sweep.isRadiansInSweep(radians)) - this.announcePoint((this._workPoint = g.radiansToPoint(radians, this._workPoint))); - this.announcePoint((this._workPoint = g.startPoint(this._workPoint))); - this.announcePoint((this._workPoint = g.endPoint(this._workPoint))); + this.announcePoint(this._workPoint = g.radiansToPoint(radians, this._workPoint)); + this.announcePoint(this._workPoint = g.startPoint(this._workPoint)); + this.announcePoint(this._workPoint = g.endPoint(this._workPoint)); } private static findExtremesInDirection( - geometry: GeometryQuery | GrowableXYZArray | Point3d[], direction: Vector3d | Ray3d, + geometry: GeometryQuery | GrowableXYZArray | Point3d[], + direction: Vector3d | Ray3d, ): PlaneAltitudeRangeContext | undefined { const origin = direction instanceof Ray3d ? direction.origin : Point3d.createZero(); const vector = direction instanceof Ray3d ? direction.direction : direction; - const plane = Plane3dByOriginAndUnitNormal.create(origin, vector); // vector is normalized, so altitudes are distances + const plane = Plane3dByOriginAndUnitNormal.create(origin, vector); // vector is normalized, so altitudes are distances if (plane) { const context = new PlaneAltitudeRangeContext(plane); if (geometry instanceof GeometryQuery) { @@ -145,9 +146,11 @@ export class PlaneAltitudeRangeContext extends RecurseToCurvesGeometryHandler { * @param direction vector or ray on which to project the instance. A `Vector3d` is treated as a `Ray3d` with * zero origin. * @param lowHigh optional receiver for output - */ + */ public static findExtremePointsInDirection( - geometry: GeometryQuery | GrowableXYZArray | Point3d[], direction: Vector3d | Ray3d, lowHigh?: LineSegment3d, + geometry: GeometryQuery | GrowableXYZArray | Point3d[], + direction: Vector3d | Ray3d, + lowHigh?: LineSegment3d, ): LineSegment3d | undefined { const context = this.findExtremesInDirection(geometry, direction); if (context && context.highPoint && context.lowPoint) @@ -162,9 +165,11 @@ export class PlaneAltitudeRangeContext extends RecurseToCurvesGeometryHandler { * @param direction vector or ray on which to project the instance. A `Vector3d` is treated as a `Ray3d` with * zero origin. * @param lowHigh optional receiver for output - */ + */ public static findExtremeAltitudesInDirection( - geometry: GeometryQuery | GrowableXYZArray | Point3d[], direction: Vector3d | Ray3d, lowHigh?: Range1d, + geometry: GeometryQuery | GrowableXYZArray | Point3d[], + direction: Vector3d | Ray3d, + lowHigh?: Range1d, ): Range1d | undefined { const context = this.findExtremesInDirection(geometry, direction); if (context && !context.range.isNull) @@ -180,7 +185,9 @@ export class PlaneAltitudeRangeContext extends RecurseToCurvesGeometryHandler { * @param lowHigh optional receiver for output */ public static findExtremeFractionsAlongDirection( - geometry: GeometryQuery | GrowableXYZArray | Point3d[], direction: Vector3d | Ray3d, lowHigh?: Range1d, + geometry: GeometryQuery | GrowableXYZArray | Point3d[], + direction: Vector3d | Ray3d, + lowHigh?: Range1d, ): Range1d | undefined { const range = this.findExtremeAltitudesInDirection(geometry, direction, lowHigh); if (undefined !== range) { diff --git a/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts b/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts index 9ef146f09e4f..f7ab0ffe413f 100644 --- a/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts +++ b/core/geometry/src/curve/internalContexts/PolygonOffsetContext.ts @@ -62,7 +62,9 @@ class Joint { public previousJoint?: Joint; // capture references to all data . . . public constructor( - curve0: CurvePrimitive | undefined, curve1: CurvePrimitive | undefined, swingPoint: Point3d | undefined, + curve0: CurvePrimitive | undefined, + curve1: CurvePrimitive | undefined, + swingPoint: Point3d | undefined, ) { this.curve0 = curve0; this.curve1 = curve1; @@ -204,7 +206,10 @@ class Joint { */ public static annotateChain(start: Joint | undefined, options: JointOptions, maxTest: number = 100) { if (start) - Joint.visitJointsOnChain(start, (joint: Joint) => { joint.annotateJointMode(options); return true; }, maxTest); + Joint.visitJointsOnChain(start, (joint: Joint) => { + joint.annotateJointMode(options); + return true; + }, maxTest); } /** * Visit joints on a chain. @@ -233,7 +238,7 @@ class Joint { if (this.curve0 && this.curve1) { const ray0 = this.curve0.fractionToPointAndDerivative(1.0); const ray1 = this.curve1.fractionToPointAndDerivative(0.0); - ray0.direction.z = ray1.direction.z = 0.0; // xy-offset + ray0.direction.z = ray1.direction.z = 0.0; // xy-offset const intersection = Ray3d.closestApproachRay3dRay3d(ray0, ray1); // intersection of the 2 ray lines if (intersection.approachType === CurveCurveApproachType.Intersection) { if (intersection.detailA.fraction >= 0.0 && intersection.detailB.fraction <= 0.0) { @@ -283,7 +288,9 @@ class Joint { } /** Select the index at which summed fraction difference is smallest */ private selectIntersectionIndexByFraction( - fractionA: number, fractionB: number, intersections: CurveLocationDetailPair[], + fractionA: number, + fractionB: number, + intersections: CurveLocationDetailPair[], ): number { let index = -1; let aMin = Number.MAX_VALUE; @@ -320,9 +327,11 @@ class Joint { } else if (this.curve0 instanceof LineSegment3d && this.curve1 instanceof LineSegment3d) { // pair of lines const ray0 = this.curve0.fractionToPointAndDerivative(0.0); const ray1 = this.curve1.fractionToPointAndDerivative(0.0); - ray0.direction.z = ray1.direction.z = 0.0; // xy-offset + ray0.direction.z = ray1.direction.z = 0.0; // xy-offset const intersection = Ray3d.closestApproachRay3dRay3d(ray0, ray1); // intersection of the 2 ray lines - if (intersection.approachType === CurveCurveApproachType.Intersection || intersection.approachType === CurveCurveApproachType.PerpendicularChord) { + if ( + intersection.approachType === CurveCurveApproachType.Intersection || intersection.approachType === CurveCurveApproachType.PerpendicularChord + ) { this.fraction0 = intersection.detailA.fraction; this.fraction1 = intersection.detailB.fraction; if (this.fraction0 >= 1.0 && this.fraction1 <= 0.0) { // need to extend @@ -356,7 +365,9 @@ class Joint { * @param start */ public static removeDegeneratePrimitives( - start: Joint, options: JointOptions, maxTest: number, + start: Joint, + options: JointOptions, + maxTest: number, ): { newStart: Joint, numJointRemoved: number } { /* if (Checker.noisy.PolygonOffset) @@ -369,7 +380,8 @@ class Joint { if (jointA) { while (jointA !== undefined && numTest++ < maxTest) { const jointB = jointA.nextJoint; - if (jointA + if ( + jointA && jointB && jointA.previousJoint && jointB.nextJoint @@ -447,17 +459,19 @@ class Joint { */ export class PolygonWireOffsetContext { /** Construct a context. */ - public constructor() { } + public constructor() {} private static _unitAlong = Vector3d.create(); private static _unitPerp = Vector3d.create(); private static _offsetA = Point3d.create(); private static _offsetB = Point3d.create(); // Construct a single offset from base points private static createOffsetSegment( - basePointA: Point3d, basePointB: Point3d, distance: number, + basePointA: Point3d, + basePointB: Point3d, + distance: number, ): CurvePrimitive | undefined { Vector3d.createStartEnd(basePointA, basePointB, this._unitAlong); - this._unitAlong.z = 0.0; // xy-offset + this._unitAlong.z = 0.0; // xy-offset if (this._unitAlong.normalizeInPlace()) { this._unitAlong.rotate90CCWXY(this._unitPerp); const segment = LineSegment3d.create( @@ -481,7 +495,9 @@ export class PolygonWireOffsetContext { * object. */ public constructPolygonWireXYOffset( - points: Point3d[], wrap: boolean, leftOffsetDistanceOrOptions: number | JointOptions, + points: Point3d[], + wrap: boolean, + leftOffsetDistanceOrOptions: number | JointOptions, ): CurveChain | undefined { if (wrap && !points[0].isAlmostEqual(points[points.length - 1])) wrap = false; // no wrap possible for polylines @@ -496,7 +512,7 @@ export class PolygonWireOffsetContext { previousJoint = joint0 = new Joint(undefined, fragment0, points[i]); } else { const fragment1 = PolygonWireOffsetContext.createOffsetSegment(points[i], points[i + 1], options.leftOffsetDistance); - if (fragment1) { // append the next nontrivial xy-segment + if (fragment1) { // append the next nontrivial xy-segment const newJoint = new Joint(fragment0, fragment1, points[i]); Joint.link(previousJoint, newJoint); previousJoint = newJoint; @@ -523,7 +539,7 @@ export class PolygonWireOffsetContext { */ } const chain = LineString3d.create(); - Joint.collectStrokesFromChain(joint0, chain, numPoints); // compute offset corners (by extension/trim) + Joint.collectStrokesFromChain(joint0, chain, numPoints); // compute offset corners (by extension/trim) const n = chain.packedPoints.length; if (n > 1) { if (chain.packedPoints.front()!.isAlmostEqual(chain.packedPoints.back()!)) @@ -541,7 +557,7 @@ export class PolygonWireOffsetContext { */ export class CurveChainWireOffsetContext { /** construct a context. */ - public constructor() { } + public constructor() {} /** * Annotate a CurvePrimitive with properties `baseCurveStart` and `baseCurveEnd`. * @param cp curve primitive to annotate @@ -550,7 +566,9 @@ export class CurveChainWireOffsetContext { * @return the input CurvePrimitive with annotations */ public static applyBasePoints( - cp: CurvePrimitive | undefined, startPoint: Point3d | undefined, endPoint: Point3d | undefined, + cp: CurvePrimitive | undefined, + startPoint: Point3d | undefined, + endPoint: Point3d | undefined, ): CurvePrimitive | undefined { if (cp !== undefined) { if (startPoint !== undefined) @@ -569,7 +587,8 @@ export class CurveChainWireOffsetContext { * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object */ public static createSingleOffsetPrimitiveXY( - curve: CurvePrimitive, offsetDistanceOrOptions: number | OffsetOptions, + curve: CurvePrimitive, + offsetDistanceOrOptions: number | OffsetOptions, ): CurvePrimitive | CurvePrimitive[] | undefined { const offset = curve.constructOffsetXY(offsetDistanceOrOptions); if (offset === undefined) @@ -594,7 +613,8 @@ export class CurveChainWireOffsetContext { * @param offsetDistanceOrOptions offset distance (positive to left of curve, negative to right) or options object. */ public static constructCurveXYOffset( - curves: Path | Loop, offsetDistanceOrOptions: number | JointOptions | OffsetOptions, + curves: Path | Loop, + offsetDistanceOrOptions: number | JointOptions | OffsetOptions, ): CurveCollection | undefined { const wrap: boolean = curves instanceof Loop; const offsetOptions = OffsetOptions.create(offsetDistanceOrOptions); @@ -621,9 +641,10 @@ export class CurveChainWireOffsetContext { for (const fragment1 of simpleOffsets) { if (fragment1) { newJoint = new Joint(fragment0, fragment1, fragment1.fractionToPoint(0.0)); - if (newJoint !== undefined) + if (newJoint !== undefined) { if (joint0 === undefined) joint0 = newJoint; + } if (previousJoint) Joint.link(previousJoint, newJoint); previousJoint = newJoint; diff --git a/core/geometry/src/curve/internalContexts/TransformInPlaceContext.ts b/core/geometry/src/curve/internalContexts/TransformInPlaceContext.ts index 7f6f90fa32a8..de21c5304f4c 100644 --- a/core/geometry/src/curve/internalContexts/TransformInPlaceContext.ts +++ b/core/geometry/src/curve/internalContexts/TransformInPlaceContext.ts @@ -17,7 +17,12 @@ export class TransformInPlaceContext extends RecursiveCurveProcessor { public numFail: number; public numOK: number; public transform: Transform; - constructor(transform: Transform) { super(); this.numFail = 0; this.numOK = 0; this.transform = transform; } + constructor(transform: Transform) { + super(); + this.numFail = 0; + this.numOK = 0; + this.transform = transform; + } public static tryTransformInPlace(target: CurveCollection, transform: Transform): boolean { const context = new TransformInPlaceContext(transform); target.announceToCurveProcessor(context); diff --git a/core/geometry/src/curve/spiral/AustralianRailCorpXYEvaluator.ts b/core/geometry/src/curve/spiral/AustralianRailCorpXYEvaluator.ts index d3542a7f8516..91c936190bc8 100644 --- a/core/geometry/src/curve/spiral/AustralianRailCorpXYEvaluator.ts +++ b/core/geometry/src/curve/spiral/AustralianRailCorpXYEvaluator.ts @@ -24,9 +24,15 @@ export class AustralianRailCorpXYEvaluator extends CubicEvaluator { this._nominalLength1 = nominalLength1; this._nominalRadius1 = nominalRadius1; } - public get nominalLength1() { return this._nominalLength1; } - public get nominalRadius1() { return this._nominalRadius1; } - public clone(): AustralianRailCorpXYEvaluator { return new AustralianRailCorpXYEvaluator(this._nominalLength1, this._nominalRadius1, this._axisLength, this._cubicM); } + public get nominalLength1() { + return this._nominalLength1; + } + public get nominalRadius1() { + return this._nominalRadius1; + } + public clone(): AustralianRailCorpXYEvaluator { + return new AustralianRailCorpXYEvaluator(this._nominalLength1, this._nominalRadius1, this._axisLength, this._cubicM); + } public static create(nominalLength1: number, nominalRadius1: number): AustralianRailCorpXYEvaluator | undefined { const axisLength = AustralianRailCorpXYEvaluator.radiusAndNominalLengthToAxisLength(nominalRadius1, nominalLength1); const phi = this.radiusAndAxisLengthToPhi(nominalRadius1, axisLength); @@ -41,8 +47,8 @@ export class AustralianRailCorpXYEvaluator extends CubicEvaluator { */ public static radiusAndAxisLengthToPhi(nominalRadius1: number, axisLength: number): number { const xc = axisLength; - const expr1 = (2. / Math.sqrt(3.)); - let expr2 = (-(3. / 4.) * Math.sqrt(3.) * xc / nominalRadius1); + const expr1 = 2. / Math.sqrt(3.); + let expr2 = -(3. / 4.) * Math.sqrt(3.) * xc / nominalRadius1; if (expr2 < -1.0) expr2 = -1.0; if (expr2 > 1.0) @@ -59,10 +65,13 @@ export class AustralianRailCorpXYEvaluator extends CubicEvaluator { super.scaleInPlace(scaleFactor); } /** Compute length along axis for AustralianRail spiral nominal radius and length. - * */ - public static radiusAndNominalLengthToAxisLength(nominalRadius1: number, nominalLength1: number, tolerance: number = 1.0e-5, - requiredConvergenceCount: number = 2) { + public static radiusAndNominalLengthToAxisLength( + nominalRadius1: number, + nominalLength1: number, + tolerance: number = 1.0e-5, + requiredConvergenceCount: number = 2, + ) { const R = nominalRadius1; let idx = 0; let m, phi, xc2; @@ -84,9 +93,12 @@ export class AustralianRailCorpXYEvaluator extends CubicEvaluator { const m2x4 = m * m * xc2 * xc2; const correction = xc * m2x4 * ( (9. / 10) + m2x4 * ( - -(9. / 8.) + m2x4 * ( - +(729. / 208.) + m2x4 * - -(32805. / 2176.)))); + -(9. / 8.) + m2x4 * ( + +(729. / 208.) + m2x4 * + -(32805. / 2176.) + ) + ) + ); const correctedLength = xc + correction; xc = (nominalLength1 / correctedLength) * xc; diff --git a/core/geometry/src/curve/spiral/ClothoidSeries.ts b/core/geometry/src/curve/spiral/ClothoidSeries.ts index 287aae06d52f..7c3821a2fd15 100644 --- a/core/geometry/src/curve/spiral/ClothoidSeries.ts +++ b/core/geometry/src/curve/spiral/ClothoidSeries.ts @@ -8,8 +8,8 @@ */ import { Geometry } from "../../Geometry"; -import { XYCurveEvaluator } from "./XYCurveEvaluator"; import { SimpleNewton } from "../../numerics/Newton"; +import { XYCurveEvaluator } from "./XYCurveEvaluator"; /** * Methods to evaluate caller-specified number of terms of the x and y series for a clothoid. * Each instance has @@ -36,7 +36,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { } public scaleInPlace(scaleFactor: number) { this.nominalLength1 *= scaleFactor; - this.constantDiv2LR /= (scaleFactor * scaleFactor); + this.constantDiv2LR /= scaleFactor * scaleFactor; } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { @@ -52,34 +52,46 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { * Evaluate the X series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToX(fraction: number): number { return this.fractionToXGo(fraction, this.numXTerms); } + public fractionToX(fraction: number): number { + return this.fractionToXGo(fraction, this.numXTerms); + } /** * Evaluate the Y series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToY(fraction: number): number { return this.fractionToYGo(fraction, this.numYTerms); } + public fractionToY(fraction: number): number { + return this.fractionToYGo(fraction, this.numYTerms); + } /** * Evaluate the derivative of the X series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToDX(fraction: number): number { return this.fractionToDXGo(fraction, this.numXTerms); } + public fractionToDX(fraction: number): number { + return this.fractionToDXGo(fraction, this.numXTerms); + } /** * Evaluate the derivative of the Y series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToDY(fraction: number): number { return this.fractionToDYGo(fraction, this.numYTerms); } + public fractionToDY(fraction: number): number { + return this.fractionToDYGo(fraction, this.numYTerms); + } /** * Evaluate the derivative of the X series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToDDX(fraction: number): number { return this.fractionToDDXGo(fraction, this.numXTerms); } + public fractionToDDX(fraction: number): number { + return this.fractionToDDXGo(fraction, this.numXTerms); + } /** * Evaluate the derivative of the Y series at a nominal distance along the curve. * @param fraction fractional position along the curve. */ - public fractionToDDY(fraction: number): number { return this.fractionToDDYGo(fraction, this.numYTerms); } + public fractionToDDY(fraction: number): number { + return this.fractionToDDYGo(fraction, this.numYTerms); + } /** * Evaluate the X series at a nominal distance along the curve. @@ -97,7 +109,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { if (numTerms < 2) return result; const q1 = s * s * this.constantDiv2LR; - const beta = - q1 * q1; + const beta = -q1 * q1; let alpha = s; let m = 1; let n = 5; @@ -119,7 +131,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { let result = q1 * s / 3; if (numTerms < 2) return result; - const beta = - q1 * q1; + const beta = -q1 * q1; let alpha = q1 * s; let m = 2; let n = 7; @@ -143,7 +155,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { return result * this.nominalLength1; } const q1 = s * s * this.constantDiv2LR; - const beta = - q1 * q1; + const beta = -q1 * q1; let alpha = 1.0; let m = 1; for (let i = 1; i < numTerms; i++) { @@ -165,7 +177,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { let result = q1; if (numTerms < 2) return result * this.nominalLength1; - const beta = - q1 * q1; + const beta = -q1 * q1; let alpha = q1; let m = 2; for (let i = 1; i < numTerms; i++) { @@ -183,7 +195,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { const dTheta = 2 * this.constantDiv2LR * s; const sine = this.fractionToDYGo(fraction, numTerms - 1); - const resultA = (- dTheta * sine * this.nominalLength1); + const resultA = -dTheta * sine * this.nominalLength1; return resultA; } public fractionToDDYGo(fraction: number, numTerms: number): number { @@ -206,7 +218,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { const d2Theta = 2.0 * this.constantDiv2LR; const sine = this.fractionToDYGo(fraction, this.numXTerms - 1); const cosine = this.fractionToDXGo(fraction, this.numXTerms - 1); - return (- cosine * dTheta * dTheta - sine * d2Theta) * this.nominalLength1 * this.nominalLength1; + return (-cosine * dTheta * dTheta - sine * d2Theta) * this.nominalLength1 * this.nominalLength1; } public fractionToD3Y(fraction: number): number { // DY is "sine" @@ -224,9 +236,7 @@ export class ClothoidSeriesRLEvaluator extends XYCurveEvaluator { public xToFraction(x: number): number | undefined { const fraction0 = x / this.nominalLength1; - const fraction1 = SimpleNewton.runNewton1D(fraction0, - (f: number) => (this.fractionToX(f) - x), - (f: number) => this.fractionToDX(f)); + const fraction1 = SimpleNewton.runNewton1D(fraction0, (f: number) => (this.fractionToX(f) - x), (f: number) => this.fractionToDX(f)); if (fraction1 === undefined) return undefined; return fraction1; diff --git a/core/geometry/src/curve/spiral/CubicEvaluator.ts b/core/geometry/src/curve/spiral/CubicEvaluator.ts index eca70f74859d..f06c5f089bc5 100644 --- a/core/geometry/src/curve/spiral/CubicEvaluator.ts +++ b/core/geometry/src/curve/spiral/CubicEvaluator.ts @@ -25,8 +25,12 @@ export abstract class CubicEvaluator extends XYCurveEvaluator { this._axisLength = axisLength; this._cubicM = cubicM; } - public get axisLength() { return this._axisLength; } - public get cubicM() { return this._cubicM; } + public get axisLength() { + return this._axisLength; + } + public get cubicM() { + return this._cubicM; + } /** * Apply `scaleFactor` to the xLength and cubicM. * * Derived classes commonly call this as `super.scaleInPlace()`, and additionally apply the scale to their members. @@ -35,16 +39,24 @@ export abstract class CubicEvaluator extends XYCurveEvaluator { public scaleInPlace(scaleFactor: number) { this._axisLength *= scaleFactor; // "x" arriving at "m * x^3" will be scaled. "m" has to be divided by the scale to cancel 2 of the 3 . . - this._cubicM /= (scaleFactor * scaleFactor); + this._cubicM /= scaleFactor * scaleFactor; } /** Evaluate X at fraction. */ - public fractionToX(fraction: number): number { return fraction * this._axisLength; } + public fractionToX(fraction: number): number { + return fraction * this._axisLength; + } /** Evaluate derivative of X with respect to fraction */ - public fractionToDX(_fraction: number): number { return this._axisLength; } + public fractionToDX(_fraction: number): number { + return this._axisLength; + } /** Evaluate second derivative of X with respect to fraction */ - public fractionToDDX(_fraction: number): number { return 0.0; } + public fractionToDDX(_fraction: number): number { + return 0.0; + } /** Evaluate third derivative of X with respect to fraction */ - public fractionToD3X(_fraction: number): number { return 0.0; } + public fractionToD3X(_fraction: number): number { + return 0.0; + } /** Evaluate Y at fraction. */ public fractionToY(fraction: number): number { const x = fraction * this._axisLength; @@ -65,5 +77,7 @@ export abstract class CubicEvaluator extends XYCurveEvaluator { return 6.0 * this._cubicM * this._axisLength * this._axisLength * this._axisLength; } /** Evaluate fraction at x. */ - public xToFraction(x: number): number { return x / this._axisLength; } + public xToFraction(x: number): number { + return x / this._axisLength; + } } diff --git a/core/geometry/src/curve/spiral/CzechSpiralEvaluator.ts b/core/geometry/src/curve/spiral/CzechSpiralEvaluator.ts index cb53930d3c7d..b0c505bcc402 100644 --- a/core/geometry/src/curve/spiral/CzechSpiralEvaluator.ts +++ b/core/geometry/src/curve/spiral/CzechSpiralEvaluator.ts @@ -7,8 +7,8 @@ * @module Curve */ import { Geometry } from "../../Geometry"; -import { CubicEvaluator } from "./CubicEvaluator"; import { SimpleNewton } from "../../numerics/Newton"; +import { CubicEvaluator } from "./CubicEvaluator"; /** * Czech cubic. * This is y= m*x^3 with @@ -50,7 +50,7 @@ export class CzechSpiralEvaluator extends CubicEvaluator { if (gamma === undefined) return undefined; // If radius is negative, it shows up in gamma. But the a signed denominator undoes it. So take abs of denominator. - return gamma / Math.abs((6.0 * radius1 * length1)); + return gamma / Math.abs(6.0 * radius1 * length1); } public static create(length1: number, radius1: number): CzechSpiralEvaluator | undefined { @@ -66,7 +66,9 @@ export class CzechSpiralEvaluator extends CubicEvaluator { super.scaleInPlace(scaleFactor); } /** return a deep copy of the evaluator */ - public clone(): CzechSpiralEvaluator { return new CzechSpiralEvaluator(this.nominalLength1, this.nominalRadius1, this.cubicM); } + public clone(): CzechSpiralEvaluator { + return new CzechSpiralEvaluator(this.nominalLength1, this.nominalRadius1, this.cubicM); + } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { if (other instanceof CzechSpiralEvaluator) { @@ -89,16 +91,15 @@ export class CzechSpiralEvaluator extends CubicEvaluator { * Return the inverse of the `forwardL2R2Map` function. * * The undefined result can only occur for distances outside the usual spirals. * @param s (approximate) distance along the spiral. - * */ public czechApproximateDistanceToX(d: number): number | undefined { return CzechSpiralEvaluator.inverseL2R2Map(d, 1.0, this.nominalLength1, this.nominalRadius1); } /** - * evaluate a series expansion that is used with varying signs (plus or minus 1) in czech and italian spirals. - * @param x distance along the x axis. - */ + * evaluate a series expansion that is used with varying signs (plus or minus 1) in czech and italian spirals. + * @param x distance along the x axis. + */ public static forwardL2R2Map(x: number, sign: number, length: number, radius: number): number { const l2 = length * length; const r2 = radius * radius; @@ -110,22 +111,19 @@ export class CzechSpiralEvaluator extends CubicEvaluator { * Return the inverse of the `forwardL2R2Map` function. * * The undefined result can only occur for distances outside the usual spirals. * @param s (approximate) distance along the spiral. - * */ public static inverseL2R2Map(b: number, sign: number, length: number, radius: number): number | undefined { const l2 = length * length; const r2 = radius * radius; const Q = 4.0 * r2 - l2; const a = sign / (10.0 * Q * l2); - return SimpleNewton.runNewton1D(b, - (x: number) => { - const xx = x * x; - return x * (1.0 + xx * xx * a) - b; - }, - (x: number) => { - const xx = x * x; - return 1.0 + 5 * xx * xx * a; - }); + return SimpleNewton.runNewton1D(b, (x: number) => { + const xx = x * x; + return x * (1.0 + xx * xx * a) - b; + }, (x: number) => { + const xx = x * x; + return 1.0 + 5 * xx * xx * a; + }); } } /** @@ -155,7 +153,7 @@ export class ItalianSpiralEvaluator extends CubicEvaluator { if (gamma === undefined) return undefined; // If radius is negative, it shows up in gamma. But the a signed denominator undoes it. So take abs of denominator. - return gamma / Math.abs((6.0 * radius1 * lengthXByForward)); + return gamma / Math.abs(6.0 * radius1 * lengthXByForward); } /** Constructor is private. Caller responsible for cubicM validity. */ @@ -182,7 +180,9 @@ export class ItalianSpiralEvaluator extends CubicEvaluator { super.scaleInPlace(scaleFactor); } /** return a deep copy of the evaluator */ - public clone(): ItalianSpiralEvaluator { return new ItalianSpiralEvaluator(this.nominalLength1, this.nominalRadius1, super.axisLength, this.cubicM); } + public clone(): ItalianSpiralEvaluator { + return new ItalianSpiralEvaluator(this.nominalLength1, this.nominalRadius1, super.axisLength, this.cubicM); + } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { if (other instanceof ItalianSpiralEvaluator) { @@ -192,11 +192,11 @@ export class ItalianSpiralEvaluator extends CubicEvaluator { return false; } /** - * Return a (fast but mediocre) approximation of spiral length as a function of x axis position. - * * This x-to-distance relation is not as precise as the CurvePrimitive method moveSignedDistanceFromFraction. - * * It is supported here for users interested in replicating the Czech distance mapping rather than the more accurate CurvePrimitive measurements. - * @param x distance along the x axis. - */ + * Return a (fast but mediocre) approximation of spiral length as a function of x axis position. + * * This x-to-distance relation is not as precise as the CurvePrimitive method moveSignedDistanceFromFraction. + * * It is supported here for users interested in replicating the Czech distance mapping rather than the more accurate CurvePrimitive measurements. + * @param x distance along the x axis. + */ public distanceToItalianApproximateX(x: number): number { return CzechSpiralEvaluator.forwardL2R2Map(x, -1.0, this.nominalLength1, this.nominalRadius1); } @@ -204,7 +204,6 @@ export class ItalianSpiralEvaluator extends CubicEvaluator { * Return the inverse of the `forwardL2R2Map` function. * * The undefined result can only occur for distances outside the usual spirals. * @param s (approximate) distance along the spiral. - * */ public xToItalianApproximateDistance(d: number): number | undefined { return CzechSpiralEvaluator.inverseL2R2Map(d, -1.0, this.nominalLength1, this.nominalRadius1); diff --git a/core/geometry/src/curve/spiral/DirectHalfCosineSpiralEvaluator.ts b/core/geometry/src/curve/spiral/DirectHalfCosineSpiralEvaluator.ts index 90f6c4cea81e..8283f415da5e 100644 --- a/core/geometry/src/curve/spiral/DirectHalfCosineSpiralEvaluator.ts +++ b/core/geometry/src/curve/spiral/DirectHalfCosineSpiralEvaluator.ts @@ -7,8 +7,8 @@ * @module Curve */ import { Geometry } from "../../Geometry"; -import { XYCurveEvaluator } from "./XYCurveEvaluator"; import { SimpleNewton } from "../../numerics/Newton"; +import { XYCurveEvaluator } from "./XYCurveEvaluator"; /** * @internal */ @@ -38,7 +38,9 @@ export class DirectHalfCosineSpiralEvaluator extends XYCurveEvaluator { this.updateConstants(); } /** return a deep copy of the evaluator */ - public clone(): DirectHalfCosineSpiralEvaluator { return new DirectHalfCosineSpiralEvaluator(this.nominalLength1, this.nominalRadius1); } + public clone(): DirectHalfCosineSpiralEvaluator { + return new DirectHalfCosineSpiralEvaluator(this.nominalLength1, this.nominalRadius1); + } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { if (other instanceof DirectHalfCosineSpiralEvaluator) { @@ -49,14 +51,18 @@ export class DirectHalfCosineSpiralEvaluator extends XYCurveEvaluator { return false; } /** Evaluate X at fractional position. */ - public fractionToX(fraction: number): number { return fraction * this.nominalLength1; } + public fractionToX(fraction: number): number { + return fraction * this.nominalLength1; + } /** Evaluate Y at fractional position. */ public fractionToY(fraction: number): number { const theta = fraction * Math.PI; return this._c * (this._c2 * fraction * fraction - this._c1 * (1.0 - Math.cos(theta))); } /** Evaluate derivative of X with respect to fraction at fractional position. */ - public fractionToDX(_fraction: number): number { return this.nominalLength1; } + public fractionToDX(_fraction: number): number { + return this.nominalLength1; + } /** Evaluate derivative of Y with respect to fraction at fractional position. */ @@ -66,7 +72,9 @@ export class DirectHalfCosineSpiralEvaluator extends XYCurveEvaluator { return this._c * (2.0 * this._c2 * fraction - this._c1 * pi * Math.sin(theta)); } /** Evaluate second derivative of X with respect to fraction at fractional position. */ - public fractionToDDX(_fraction: number): number { return 0.0; } + public fractionToDDX(_fraction: number): number { + return 0.0; + } /** Evaluate third derivative of Y with respect to fraction at fractional position. */ @@ -76,7 +84,9 @@ export class DirectHalfCosineSpiralEvaluator extends XYCurveEvaluator { return this._c * (2.0 * this._c2 - this._c1 * pi * pi * Math.cos(theta)); } /** Evaluate second derivative of X with respect to fraction at fractional position. */ - public fractionToD3X(_fraction: number): number { return 0.0; } + public fractionToD3X(_fraction: number): number { + return 0.0; + } /** Evaluate third derivative of Y with respect to fraction at fractional position. */ @@ -90,17 +100,13 @@ export class DirectHalfCosineSpiralEvaluator extends XYCurveEvaluator { public override fractionToTangentMagnitude(fraction: number): number { return Geometry.hypotenuseXY(this.fractionToDX(fraction), this.fractionToDY(fraction)); - } /** Invert the fractionToX function for given X. */ public xToFraction(x: number): number | undefined { const fraction0 = x / this.nominalLength1; - const fraction1 = SimpleNewton.runNewton1D(fraction0, - (f: number) => (this.fractionToX(f) - x), - (f: number) => this.fractionToDX(f)); + const fraction1 = SimpleNewton.runNewton1D(fraction0, (f: number) => (this.fractionToX(f) - x), (f: number) => this.fractionToDX(f)); if (fraction1 === undefined) return undefined; return fraction1; - } } diff --git a/core/geometry/src/curve/spiral/DirectSpiral3d.ts b/core/geometry/src/curve/spiral/DirectSpiral3d.ts index 06c9a32c6844..39dc16ea32d3 100644 --- a/core/geometry/src/curve/spiral/DirectSpiral3d.ts +++ b/core/geometry/src/curve/spiral/DirectSpiral3d.ts @@ -28,23 +28,22 @@ import { TransitionSpiral3d } from "./TransitionSpiral3d"; import { XYCurveEvaluator } from "./XYCurveEvaluator"; /** -* DirectSpiral3d acts like a TransitionSpiral3d for serialization purposes, but implements spiral types that have "direct" xy calculations without the integrations required -* for IntegratedSpiral3d. -* * Each DirectSpiral3d carries an XYCurveEvaluator to give it specialized behavior. -* * Direct spirals that flow through serialization to native imodel02 are create with these static methods: -* * createArema -* * createJapaneseCubic -* * createAustralianRail -* * createDirectHalfCosine -* * createChineseCubic -* * createCzechCubic -* * createPolishCubic -* * createItalian -* * createWesternAustralian -* @public -*/ + * DirectSpiral3d acts like a TransitionSpiral3d for serialization purposes, but implements spiral types that have "direct" xy calculations without the integrations required + * for IntegratedSpiral3d. + * * Each DirectSpiral3d carries an XYCurveEvaluator to give it specialized behavior. + * * Direct spirals that flow through serialization to native imodel02 are create with these static methods: + * * createArema + * * createJapaneseCubic + * * createAustralianRail + * * createDirectHalfCosine + * * createChineseCubic + * * createCzechCubic + * * createPolishCubic + * * createItalian + * * createWesternAustralian + * @public + */ export class DirectSpiral3d extends TransitionSpiral3d { - /** String name for schema properties */ public readonly curvePrimitiveType = "transitionSpiral"; @@ -57,22 +56,32 @@ export class DirectSpiral3d extends TransitionSpiral3d { */ private _activeStrokes?: LineString3d; /** Return the internal stroked form of the (possibly partial) spiral */ - public get activeStrokes(): LineString3d { return this._activeStrokes !== undefined ? this._activeStrokes : this._globalStrokes; } + public get activeStrokes(): LineString3d { + return this._activeStrokes !== undefined ? this._activeStrokes : this._globalStrokes; + } private _nominalL1: number; private _nominalR1: number; private _evaluator: XYCurveEvaluator; /** Return the nominal end radius. */ - public get nominalR1(): number { return this._nominalR1; } + public get nominalR1(): number { + return this._nominalR1; + } /** Return the nominal distance from inflection to endpoint. */ - public get nominalL1(): number { return this._nominalL1; } + public get nominalL1(): number { + return this._nominalL1; + } /** Return the nominal end curvature */ - public get nominalCurvature1(): number { return TransitionSpiral3d.radiusToCurvature(this._nominalR1); } + public get nominalCurvature1(): number { + return TransitionSpiral3d.radiusToCurvature(this._nominalR1); + } /** Return the low level evaluator * @internal */ - public get evaluator(): XYCurveEvaluator { return this._evaluator; } + public get evaluator(): XYCurveEvaluator { + return this._evaluator; + } // constructor demands radius1 and distance1 for nominal construction. // caller is responsible for managing intervals of partial spiral @@ -83,7 +92,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { nominalL1: number, nominalR1: number, activeFractionInterval: Segment1d | undefined, - evaluator: XYCurveEvaluator) { + evaluator: XYCurveEvaluator, + ) { super(spiralType, localToWorld, activeFractionInterval, originalProperties); this._nominalL1 = nominalL1; this._nominalR1 = nominalR1; @@ -110,12 +120,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { for (let i = 0; i <= numInterval; i++) { const fraction = Geometry.interpolate(fractionA, i / numInterval, fractionB); const nominalDistanceAlong = fraction * nominalIntervalLength; - strokes.packedPoints.pushXYZ(this._evaluator.fractionToX(fraction), - this._evaluator.fractionToY(fraction), 0); + strokes.packedPoints.pushXYZ(this._evaluator.fractionToX(fraction), this._evaluator.fractionToY(fraction), 0); distances.pushXY(fraction, nominalDistanceAlong); // the second distance will be updated below } if (applyLocalToWorld) - strokes.tryTransformInPlace (this._localToWorld); + strokes.tryTransformInPlace(this._localToWorld); let fraction0 = distances.getXAtUncheckedPointIndex(0); let trueDistance0 = distances.getYAtUncheckedPointIndex(0); // whatever was assigned as start distance is fine let trueDistance1, fraction1; @@ -126,7 +135,6 @@ export class DirectSpiral3d extends TransitionSpiral3d { fraction0 = fraction1; trueDistance0 = trueDistance1; } - } /** Recompute strokes */ public override refreshComputedProperties() { @@ -136,8 +144,7 @@ export class DirectSpiral3d extends TransitionSpiral3d { this.computeStrokes(this._globalStrokes, 0, 1, numInterval); const numActiveInterval = Math.ceil(this._activeFractionInterval.absoluteDelta() * numInterval); this._activeStrokes = LineString3d.create(); - this.computeStrokes(this._activeStrokes, this._activeFractionInterval.x0, this._activeFractionInterval.x1, - numActiveInterval); + this.computeStrokes(this._activeStrokes, this._activeFractionInterval.x0, this._activeFractionInterval.x1, numActiveInterval); } /** * Create a spiral object which uses numXTerm terms from the clothoid X series and numYTerm from the clothoid Y series. @@ -151,10 +158,13 @@ export class DirectSpiral3d extends TransitionSpiral3d { public static createTruncatedClothoid( spiralType: string, localToWorld: Transform, - numXTerm: number, numYTerm: number, + numXTerm: number, + numYTerm: number, originalProperties: TransitionConditionalProperties | undefined, - nominalL1: number, nominalR1: number, - activeInterval: Segment1d | undefined): DirectSpiral3d | undefined { + nominalL1: number, + nominalR1: number, + activeInterval: Segment1d | undefined, + ): DirectSpiral3d | undefined { if (numXTerm < 1) numXTerm = 1; if (numYTerm < 1) @@ -164,8 +174,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), spiralType, originalProperties, - nominalL1, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalL1, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } /** * Create an Japanese spiral clothoid approximation @@ -181,7 +194,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { return this.createTruncatedClothoid("JapaneseCubic", localToWorld, 1, 1, undefined, nominalL1, nominalR1, activeInterval); } /** @@ -201,7 +215,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalLx: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { const evaluator = CzechSpiralEvaluator.create(nominalLx, nominalR1); if (evaluator === undefined) return undefined; @@ -209,8 +224,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), "Czech", undefined, - nominalLx, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalLx, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } /** * Create an italian spiral @@ -230,7 +248,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { const evaluator = ItalianSpiralEvaluator.create(nominalL1, nominalR1); if (evaluator === undefined) return undefined; @@ -238,8 +257,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), "Italian", undefined, - nominalL1, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalL1, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } /** @@ -259,7 +281,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { const evaluator = MXCubicAlongArcEvaluator.create(nominalL1, nominalR1); if (evaluator === undefined) return undefined; @@ -267,8 +290,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), "MXCubicAlongArc", undefined, - nominalL1, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalL1, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } /** @@ -285,7 +311,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { const evaluator = PolishCubicEvaluator.create(nominalL1, nominalR1); if (evaluator === undefined) return undefined; @@ -293,8 +320,11 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), "PolishCubic", undefined, - nominalL1, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalL1, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } /** @@ -314,7 +344,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { const evaluator = AustralianRailCorpXYEvaluator.create(nominalL1, nominalR1); if (evaluator === undefined) return undefined; @@ -322,17 +353,28 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld.clone(), "AustralianRailCorp", undefined, - nominalL1, nominalR1, - activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), evaluator); + nominalL1, + nominalR1, + activeInterval ? activeInterval.clone() : Segment1d.create(0, 1), + evaluator, + ); } public static createDirectHalfCosine( localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { - return new this(localToWorld, "HalfCosine", undefined, nominalL1, nominalR1, activeInterval, - new DirectHalfCosineSpiralEvaluator(nominalL1, nominalR1)); + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { + return new this( + localToWorld, + "HalfCosine", + undefined, + nominalL1, + nominalR1, + activeInterval, + new DirectHalfCosineSpiralEvaluator(nominalL1, nominalR1), + ); } /** * Create an Arema spiral clothoid approximation @@ -348,7 +390,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { return this.createTruncatedClothoid("Arema", localToWorld, 2, 2, undefined, nominalL1, nominalR1, activeInterval); } @@ -366,7 +409,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { return this.createTruncatedClothoid("ChineseCubic", localToWorld, 2, 2, undefined, nominalL1, nominalR1, activeInterval); } /** @@ -382,7 +426,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { localToWorld: Transform, nominalL1: number, nominalR1: number, - activeInterval?: Segment1d): DirectSpiral3d | undefined { + activeInterval?: Segment1d, + ): DirectSpiral3d | undefined { return this.createTruncatedClothoid("WesternAustralian", localToWorld, 2, 1, undefined, nominalL1, nominalR1, activeInterval); } /** @@ -412,7 +457,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { _bearing1: Angle | undefined, arcLength: number | undefined, activeInterval: undefined | Segment1d, - localToWorld: Transform): TransitionSpiral3d | undefined { + localToWorld: Transform, + ): TransitionSpiral3d | undefined { if (bearing0 !== undefined && !bearing0.isAlmostZero) return undefined; if (radius0 !== undefined && !Geometry.isSmallMetricDistance(radius0)) @@ -452,7 +498,8 @@ export class DirectSpiral3d extends TransitionSpiral3d { this._nominalL1, this._nominalR1, this._activeFractionInterval?.clone(), - this._evaluator.clone()); + this._evaluator.clone(), + ); } /** apply `transform` to this spiral's local to world transform. */ @@ -468,9 +515,13 @@ export class DirectSpiral3d extends TransitionSpiral3d { } /** Return the spiral start point. */ - public override startPoint(): Point3d { return this.activeStrokes.startPoint(); } + public override startPoint(): Point3d { + return this.activeStrokes.startPoint(); + } /** return the spiral end point. */ - public override endPoint(): Point3d { return this.activeStrokes.endPoint(); } + public override endPoint(): Point3d { + return this.activeStrokes.endPoint(); + } /** test if the local to world transform places the spiral xy plane into `plane` */ public isInPlane(plane: Plane3dByOriginAndUnitNormal): boolean { return plane.isPointInPlane(this.localToWorld.origin as Point3d) @@ -490,12 +541,16 @@ export class DirectSpiral3d extends TransitionSpiral3d { */ // use the generic integrator ... public override curveLength() { return this.quickLength(); } /** Test if `other` is an instance of `TransitionSpiral3d` */ - public isSameGeometryClass(other: any): boolean { return other instanceof DirectSpiral3d; } + public isSameGeometryClass(other: any): boolean { + return other instanceof DirectSpiral3d; + } /** Add strokes from this spiral to `dest`. * * Linestrings will usually stroke as just their points. * * If maxEdgeLength is given, this will sub-stroke within the linestring -- not what we want. */ - public emitStrokes(dest: LineString3d, options?: StrokeOptions): void { this.activeStrokes.emitStrokes(dest, options); } + public emitStrokes(dest: LineString3d, options?: StrokeOptions): void { + this.activeStrokes.emitStrokes(dest, options); + } /** emit stroke fragments to `dest` handler. */ public emitStrokableParts(dest: IStrokeHandler, options?: StrokeOptions): void { const n = this.computeStrokeCountForOptions(options); diff --git a/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts b/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts index 84af2b63325f..3262e40582d7 100644 --- a/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts +++ b/core/geometry/src/curve/spiral/IntegratedSpiral3d.ts @@ -6,24 +6,24 @@ * @module Curve */ -import { TransitionSpiral3d } from "./TransitionSpiral3d"; -import { Segment1d } from "../../geometry3d/Segment1d"; +import { AxisOrder, Geometry } from "../../Geometry"; +import { Angle } from "../../geometry3d/Angle"; import { AngleSweep } from "../../geometry3d/AngleSweep"; -import { Transform } from "../../geometry3d/Transform"; -import { LineString3d } from "../LineString3d"; -import { NormalizedTransition } from "./NormalizedTransition"; -import { TransitionConditionalProperties } from "./TransitionConditionalProperties"; -import { Quadrature } from "../../numerics/Quadrature"; -import { Point3d } from "../../geometry3d/Point3dVector3d"; +import { GeometryHandler, IStrokeHandler } from "../../geometry3d/GeometryHandler"; import { Matrix3d } from "../../geometry3d/Matrix3d"; -import { Angle } from "../../geometry3d/Angle"; import { Plane3dByOriginAndUnitNormal } from "../../geometry3d/Plane3dByOriginAndUnitNormal"; -import { AxisOrder, Geometry } from "../../Geometry"; -import { StrokeOptions } from "../StrokeOptions"; -import { GeometryHandler, IStrokeHandler } from "../../geometry3d/GeometryHandler"; -import { Ray3d } from "../../geometry3d/Ray3d"; import { Plane3dByOriginAndVectors } from "../../geometry3d/Plane3dByOriginAndVectors"; +import { Point3d } from "../../geometry3d/Point3dVector3d"; +import { Ray3d } from "../../geometry3d/Ray3d"; +import { Segment1d } from "../../geometry3d/Segment1d"; +import { Transform } from "../../geometry3d/Transform"; +import { Quadrature } from "../../numerics/Quadrature"; import { GeometryQuery } from "../GeometryQuery"; +import { LineString3d } from "../LineString3d"; +import { StrokeOptions } from "../StrokeOptions"; +import { NormalizedTransition } from "./NormalizedTransition"; +import { TransitionConditionalProperties } from "./TransitionConditionalProperties"; +import { TransitionSpiral3d } from "./TransitionSpiral3d"; /** * An IntegratedSpiral3d is a curve defined by integrating its curvature. * * The first integral of curvature (with respect to distance along the curve) is the bearing angle (in radians) @@ -48,7 +48,9 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { */ private _activeStrokes?: LineString3d; /** Return the internal stroked form of the (possibly partial) spiral */ - public get activeStrokes(): LineString3d { return this._activeStrokes !== undefined ? this._activeStrokes : this._globalStrokes; } + public get activeStrokes(): LineString3d { + return this._activeStrokes !== undefined ? this._activeStrokes : this._globalStrokes; + } private _evaluator: NormalizedTransition; /** Total curve arc length (computed) */ private _arcLength01: number; @@ -56,14 +58,16 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { private _curvature01: Segment1d; /** evaluator for transition */ // constructor demands all bearing, radius, and length data -- caller determines usual dependency of "any 4 determine the 5th" - private constructor(spiralType: string | undefined, + private constructor( + spiralType: string | undefined, evaluator: NormalizedTransition, radius01: Segment1d, bearing01: AngleSweep, activeFractionInterval: Segment1d, localToWorld: Transform, arcLength: number, - properties: TransitionConditionalProperties | undefined) { + properties: TransitionConditionalProperties | undefined, + ) { super(spiralType, localToWorld, activeFractionInterval, properties); this._evaluator = evaluator; this.radius01 = radius01; @@ -94,7 +98,8 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { public fractionToBearingRadians(activeFraction: number): number { const fraction = this.activeFractionInterval.fractionToPoint(activeFraction); - return this.bearing01.startRadians + fraction * this._arcLength01 * (this._curvature01.x0 + 0.5 * fraction * (this._curvature01.x1 - this._curvature01.x0)); + return this.bearing01.startRadians + + fraction * this._arcLength01 * (this._curvature01.x0 + 0.5 * fraction * (this._curvature01.x1 - this._curvature01.x0)); } /** Return the curvature at given fraction of the active interval ... * * The `undefined` result is to match the abstract class -- it cannot actually occur. @@ -142,13 +147,13 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { Matrix3d.xyzPlusMatrixTimesXYZ(xyz, this.localToWorld.matrix, { x: dx, y: dy, z: 0.0 }, xyz); else xyz.addXYZInPlace(dx, dy, 0.0); - } /** Recompute strokes */ public override refreshComputedProperties() { this._curvature01 = Segment1d.create( TransitionSpiral3d.radiusToCurvature(this.radius01.x0), - TransitionSpiral3d.radiusToCurvature(this.radius01.x1)); + TransitionSpiral3d.radiusToCurvature(this.radius01.x1), + ); this._globalStrokes.clear(); const currentPoint = Point3d.create(); this._globalStrokes.appendStrokePoint(currentPoint); @@ -181,19 +186,29 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { * @param activeFractionInterval fractional limits of the active portion of the spiral. * @param localToWorld placement frame. Fractional coordinate 0 is at the origin. */ - public static createRadiusRadiusBearingBearing(radius01: Segment1d, bearing01: AngleSweep, activeFractionInterval: Segment1d, localToWorld: Transform, typeName?: string) { + public static createRadiusRadiusBearingBearing( + radius01: Segment1d, + bearing01: AngleSweep, + activeFractionInterval: Segment1d, + localToWorld: Transform, + typeName?: string, + ) { const arcLength = TransitionSpiral3d.radiusRadiusSweepRadiansToArcLength(radius01.x0, radius01.x1, bearing01.sweepRadians); if (typeName === undefined) typeName = "clothoid"; const evaluator = NormalizedTransition.findEvaluator(typeName); if (!evaluator) return undefined; - return new IntegratedSpiral3d(typeName, evaluator, + return new IntegratedSpiral3d( + typeName, + evaluator, radius01.clone(), - bearing01.clone(), activeFractionInterval.clone(), localToWorld.clone(), arcLength, - new TransitionConditionalProperties(radius01.x0, radius01.x1, - bearing01.startAngle.clone(), bearing01.endAngle.clone(), - undefined)); + bearing01.clone(), + activeFractionInterval.clone(), + localToWorld.clone(), + arcLength, + new TransitionConditionalProperties(radius01.x0, radius01.x1, bearing01.startAngle.clone(), bearing01.endAngle.clone(), undefined), + ); } /** * Create a transition spiral. @@ -214,7 +229,8 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { bearing1: Angle | undefined, arcLength: number | undefined, fractionInterval: undefined | Segment1d, - localToWorld: Transform): IntegratedSpiral3d | undefined { + localToWorld: Transform, + ): IntegratedSpiral3d | undefined { if (spiralType === undefined) spiralType = "clothoid"; const evaluator = NormalizedTransition.findEvaluator(spiralType); @@ -232,7 +248,10 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { Segment1d.create(data.radius0, data.radius1), AngleSweep.createStartEnd(data.bearing0!, data.bearing1!), fractionInterval ? fractionInterval.clone() : Segment1d.create(0, 1), - localToWorld, data.curveLength!, data1); + localToWorld, + data.curveLength!, + data1, + ); } /** Copy all defining data from another spiral. */ public setFrom(other: IntegratedSpiral3d): IntegratedSpiral3d { @@ -247,15 +266,20 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { } /** Deep clone of this spiral */ public override clone(): IntegratedSpiral3d { - return new IntegratedSpiral3d(this._spiralType, this._evaluator, - this.radius01.clone(), this.bearing01.clone(), - this.activeFractionInterval.clone(), this.localToWorld.clone(), this._arcLength01, - this._designProperties?.clone()); + return new IntegratedSpiral3d( + this._spiralType, + this._evaluator, + this.radius01.clone(), + this.bearing01.clone(), + this.activeFractionInterval.clone(), + this.localToWorld.clone(), + this._arcLength01, + this._designProperties?.clone(), + ); } /** apply `transform` to this spiral's local to world transform. */ public tryTransformInPlace(transformA: Transform): boolean { - const rigidData = this.applyRigidPartOfTransform(transformA); if (rigidData !== undefined) { this._curvature01.x0 /= rigidData.scale; @@ -269,9 +293,13 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { } /** Return the spiral start point. */ - public override startPoint(): Point3d { return this.activeStrokes.startPoint(); } + public override startPoint(): Point3d { + return this.activeStrokes.startPoint(); + } /** return the spiral end point. */ - public override endPoint(): Point3d { return this.activeStrokes.endPoint(); } + public override endPoint(): Point3d { + return this.activeStrokes.endPoint(); + } /** test if the local to world transform places the spiral xy plane into `plane` */ public isInPlane(plane: Plane3dByOriginAndUnitNormal): boolean { return plane.isPointInPlane(this.localToWorld.origin as Point3d) @@ -279,20 +307,28 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { && Geometry.isSameCoordinate(0.0, this.localToWorld.matrix.dotColumnY(plane.getNormalRef())); } /** Return length of the spiral. Because TransitionSpiral is parameterized directly in terms of distance along, this is a simple return value. */ - public quickLength() { return this.curveLength(); } + public quickLength() { + return this.curveLength(); + } /** Return length of the spiral. Because TransitionSpiral is parameterized directly in terms of distance along, this is a simple return value. */ - public override curveLength() { return this._arcLength01 * (this._activeFractionInterval.absoluteDelta()); } + public override curveLength() { + return this._arcLength01 * (this._activeFractionInterval.absoluteDelta()); + } /** Return (unsigned) length of the spiral between fractions. Because TransitionSpiral is parameterized directly in terms of distance along, this is a simple return value. */ public override curveLengthBetweenFractions(fraction0: number, fraction1: number) { return this._arcLength01 * (this._activeFractionInterval.absoluteDelta() * Math.abs(fraction1 - fraction0)); } /** Test if `other` is an instance of `TransitionSpiral3d` */ - public isSameGeometryClass(other: any): boolean { return other instanceof TransitionSpiral3d; } + public isSameGeometryClass(other: any): boolean { + return other instanceof TransitionSpiral3d; + } /** Add strokes from this spiral to `dest`. * * Linestrings will usually stroke as just their points. * * If maxEdgeLength is given, this will sub-stroke within the linestring -- not what we want. */ - public emitStrokes(dest: LineString3d, options?: StrokeOptions): void { this.activeStrokes.emitStrokes(dest, options); } + public emitStrokes(dest: LineString3d, options?: StrokeOptions): void { + this.activeStrokes.emitStrokes(dest, options); + } /** emit stroke fragments to `dest` handler. */ public emitStrokableParts(dest: IStrokeHandler, options?: StrokeOptions): void { const n = this.computeStrokeCountForOptions(options); @@ -368,7 +404,6 @@ export class IntegratedSpiral3d extends TransitionSpiral3d { result = this._globalStrokes.packedPoints.getPoint3dAtUncheckedPointIndex(index0, result); // GeometryCoreTestIO.consoleLog(" fractionToPoint ", activeFraction, this.activeFractionInterval, "( global integration " + globalFraction0 + " to " + globalFraction + ")", index0); this.fullSpiralIncrementalIntegral(result, globalFraction0, targetGlobalFraction, true); - } return result; } diff --git a/core/geometry/src/curve/spiral/MXCubicAlongArcSpiralEvaluator.ts b/core/geometry/src/curve/spiral/MXCubicAlongArcSpiralEvaluator.ts index c52cb4f5a68f..c6a2ea93d721 100644 --- a/core/geometry/src/curve/spiral/MXCubicAlongArcSpiralEvaluator.ts +++ b/core/geometry/src/curve/spiral/MXCubicAlongArcSpiralEvaluator.ts @@ -54,7 +54,9 @@ export class MXCubicAlongArcEvaluator extends CubicEvaluator { super.scaleInPlace(scaleFactor); } /** return a deep copy of the evaluator */ - public clone(): MXCubicAlongArcEvaluator { return new MXCubicAlongArcEvaluator(this.nominalLength1, this.nominalRadius1, this.axisLength, this.cubicM); } + public clone(): MXCubicAlongArcEvaluator { + return new MXCubicAlongArcEvaluator(this.nominalLength1, this.nominalRadius1, this.axisLength, this.cubicM); + } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { if (other instanceof MXCubicAlongArcEvaluator) { diff --git a/core/geometry/src/curve/spiral/NormalizedTransition.ts b/core/geometry/src/curve/spiral/NormalizedTransition.ts index 457f8a1c1688..fba48545924e 100644 --- a/core/geometry/src/curve/spiral/NormalizedTransition.ts +++ b/core/geometry/src/curve/spiral/NormalizedTransition.ts @@ -21,7 +21,7 @@ */ export abstract class NormalizedTransition { /** Constructor initializes with 0..1 values .. call "setBearingCurvatureLengthCurvature" to apply real values */ - constructor() { } + constructor() {} /** At fractional position on the x axis, return the (normalized) curvature fraction. */ public abstract fractionToCurvatureFraction(fractionX: number): number; /** Return the derivative of the (normalized) curvature fraction */ @@ -68,11 +68,17 @@ export abstract class NormalizedTransition { * @internal */ export class NormalizedClothoidTransition extends NormalizedTransition { - constructor() { super(); } + constructor() { + super(); + } /** At fractional position on the x axis, return the (normalized) curvature fraction. */ - public fractionToCurvatureFraction(fractionX: number): number { return fractionX; } + public fractionToCurvatureFraction(fractionX: number): number { + return fractionX; + } /** Return the derivative of the (normalized) curvature fraction */ - public fractionToCurvatureFractionDerivative(_u: number): number { return 1.0; } + public fractionToCurvatureFractionDerivative(_u: number): number { + return 1.0; + } /** Return the integrated area under the curve. * * This fraction is the angular change fraction. */ @@ -93,9 +99,13 @@ export class NormalizedBlossTransition extends NormalizedTransition { // derivatives zero at 0,1 // inflection zero at 0.5 // integral is x^3 - x^4 / 2 = x^3 ( 1-x/2) - constructor() { super(); } + constructor() { + super(); + } /** At fractional position on the x axis, return the (normalized) curvature fraction. */ - public fractionToCurvatureFraction(u: number): number { return u * u * (3 - 2 * u); } + public fractionToCurvatureFraction(u: number): number { + return u * u * (3 - 2 * u); + } /** Return the derivative of the (normalized) curvature fraction */ public fractionToCurvatureFractionDerivative(u: number): number { return 6.0 * u * (1.0 - u); @@ -116,10 +126,18 @@ export class NormalizedBlossTransition extends NormalizedTransition { * @internal */ export class NormalizedBiQuadraticTransition extends NormalizedTransition { - constructor() { super(); } - private integratedBasis(u: number): number { return u * u * u * (2.0 / 3.0); } - private basis(u: number): number { return 2 * u * u; } - private basisDerivative(u: number): number { return 4 * u; } + constructor() { + super(); + } + private integratedBasis(u: number): number { + return u * u * u * (2.0 / 3.0); + } + private basis(u: number): number { + return 2 * u * u; + } + private basisDerivative(u: number): number { + return 4 * u; + } /** At fractional position on the x axis, return the (normalized) curvature fraction. * * * For [u <= 0.5, u >= 0.5] * * f(u) = [2 u^2, 1 - 2 (1-u)^2] @@ -152,7 +170,9 @@ export class NormalizedBiQuadraticTransition extends NormalizedTransition { * @internal */ export class NormalizedSineTransition extends NormalizedTransition { - constructor() { super(); } + constructor() { + super(); + } /** At fractional position on the x axis, return the (normalized) curvature fraction. */ public fractionToCurvatureFraction(u: number): number { const a = 2.0 * Math.PI; @@ -177,7 +197,9 @@ export class NormalizedSineTransition extends NormalizedTransition { * @internal */ export class NormalizedCosineTransition extends NormalizedTransition { - constructor() { super(); } + constructor() { + super(); + } /** At fractional position on the x axis, return the (normalized) curvature fraction. */ public fractionToCurvatureFraction(u: number): number { const a = Math.PI; diff --git a/core/geometry/src/curve/spiral/PolishCubicSpiralEvaluator.ts b/core/geometry/src/curve/spiral/PolishCubicSpiralEvaluator.ts index dfa8ff75baf9..f32113d07ffa 100644 --- a/core/geometry/src/curve/spiral/PolishCubicSpiralEvaluator.ts +++ b/core/geometry/src/curve/spiral/PolishCubicSpiralEvaluator.ts @@ -55,7 +55,9 @@ export class PolishCubicEvaluator extends CubicEvaluator { super.scaleInPlace(scaleFactor); } /** return a deep copy of the evaluator */ - public clone(): PolishCubicEvaluator { return new PolishCubicEvaluator(this.nominalLength1, this.nominalRadius1, this.axisLength, this.cubicM); } + public clone(): PolishCubicEvaluator { + return new PolishCubicEvaluator(this.nominalLength1, this.nominalRadius1, this.axisLength, this.cubicM); + } /** Member by member matchup ... */ public isAlmostEqual(other: any): boolean { if (other instanceof PolishCubicEvaluator) { @@ -106,15 +108,17 @@ export class PolishCubicEvaluator extends CubicEvaluator { // 1/72==> 9/72 = 1/8 // 1/208==>13/208=1/16 // 1/2176==>17/2176= 1/128 - const ds = (1.0 + ax4 * (0.5 + ax4 * (-1.0 / 8.0 + ax4 * (1.0 / 16.0 - 5.0 * ax4 / 128.0)))); + const ds = 1.0 + ax4 * (0.5 + ax4 * (-1.0 / 8.0 + ax4 * (1.0 / 16.0 - 5.0 * ax4 / 128.0))); return ds; } /** Invert the xToApproximateDistance function. */ public static approximateDistanceAlongToX(s: number, radius1: number, length1: number): number | undefined { - const root = SimpleNewton.runNewton1D(s, + const root = SimpleNewton.runNewton1D( + s, (x: number) => (this.xToApproximateDistance(x, radius1, length1) - s), - (x: number) => this.xToApproximateDistanceDerivative(x, radius1, length1)); + (x: number) => this.xToApproximateDistanceDerivative(x, radius1, length1), + ); return root; } } diff --git a/core/geometry/src/curve/spiral/TransitionConditionalProperties.ts b/core/geometry/src/curve/spiral/TransitionConditionalProperties.ts index 60fb53f3edc2..b987b94ce62f 100644 --- a/core/geometry/src/curve/spiral/TransitionConditionalProperties.ts +++ b/core/geometry/src/curve/spiral/TransitionConditionalProperties.ts @@ -45,7 +45,8 @@ export class TransitionConditionalProperties { radius1: number | undefined, bearing0: Angle | undefined, bearing1: Angle | undefined, - arcLength: number | undefined) { + arcLength: number | undefined, + ) { this.radius0 = radius0; this.radius1 = radius1; this.bearing0 = bearing0; @@ -67,14 +68,20 @@ export class TransitionConditionalProperties { this.radius1, this.bearing0 === undefined ? undefined : this.bearing0.clone(), this.bearing1 === undefined ? undefined : this.bearing1.clone(), - this.curveLength); + this.curveLength, + ); } /** Return true if all components are defined and agree equationally. */ public getIsValidCompleteSet() { - if (this.curveLength !== undefined && this.bearing0 !== undefined && this.bearing1 !== undefined - && this.radius0 !== undefined && this.radius1 !== undefined) { - const length1 = TransitionSpiral3d.radiusRadiusSweepRadiansToArcLength(this.radius0, this.radius1, - this.bearing1.radians - this.bearing0.radians); + if ( + this.curveLength !== undefined && this.bearing0 !== undefined && this.bearing1 !== undefined + && this.radius0 !== undefined && this.radius1 !== undefined + ) { + const length1 = TransitionSpiral3d.radiusRadiusSweepRadiansToArcLength( + this.radius0, + this.radius1, + this.bearing1.radians - this.bearing0.radians, + ); return Geometry.isSameCoordinate(this.curveLength, length1); } return false; @@ -106,12 +113,16 @@ export class TransitionConditionalProperties { return false; if (this.bearing0) { // bearing 1 is undefined - this.bearing1 = Angle.createRadians(this.bearing0.radians + TransitionSpiral3d.radiusRadiusLengthToSweepRadians(this.radius0, this.radius1, this.curveLength)); + this.bearing1 = Angle.createRadians( + this.bearing0.radians + TransitionSpiral3d.radiusRadiusLengthToSweepRadians(this.radius0, this.radius1, this.curveLength), + ); return true; } if (this.bearing1) { // bearing 0 is undefined - this.bearing0 = Angle.createRadians(this.bearing1.radians - TransitionSpiral3d.radiusRadiusLengthToSweepRadians(this.radius0, this.radius1, this.curveLength)); + this.bearing0 = Angle.createRadians( + this.bearing1.radians - TransitionSpiral3d.radiusRadiusLengthToSweepRadians(this.radius0, this.radius1, this.curveLength), + ); return true; } return false; diff --git a/core/geometry/src/curve/spiral/TransitionSpiral3d.ts b/core/geometry/src/curve/spiral/TransitionSpiral3d.ts index 03d41bac69d5..51afe0b0fca1 100644 --- a/core/geometry/src/curve/spiral/TransitionSpiral3d.ts +++ b/core/geometry/src/curve/spiral/TransitionSpiral3d.ts @@ -43,17 +43,16 @@ export type IntegratedSpiralTypeName = "clothoid" | "bloss" | "biquadratic" | "c * @public */ export type DirectSpiralTypeName = - "JapaneseCubic" // 1 term from each of the X,Y clothoid series expansions: y = x^3 / (6RL) - | "Arema" // 2 terms from each of the X,Y clothoid series expansions. Identical to ChineseCubic! - | "ChineseCubic" // Identical to Arema! - | "HalfCosine" // high continuity cosine variation from quadratic. + | "JapaneseCubic" // 1 term from each of the X,Y clothoid series expansions: y = x^3 / (6RL) + | "Arema" // 2 terms from each of the X,Y clothoid series expansions. Identical to ChineseCubic! + | "ChineseCubic" // Identical to Arema! + | "HalfCosine" // high continuity cosine variation from quadratic. | "AustralianRailCorp" // cubic with high accuracy distance series - | "WesternAustralian" // simple cubic -- 2 terms of x series, 1 term of y series. - | "Czech" // simple cubic with two term distance approximation - | "MXCubicAlongArc" // x obtained from fractional distance via 2-terms from series, y = x^3/ (6RL) + | "WesternAustralian" // simple cubic -- 2 terms of x series, 1 term of y series. + | "Czech" // simple cubic with two term distance approximation + | "MXCubicAlongArc" // x obtained from fractional distance via 2-terms from series, y = x^3/ (6RL) | "Polish" - | "Italian" - ; + | "Italian"; /** * TransitionSpiral3d is a base class for multiple variants of spirals. @@ -79,15 +78,24 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { */ protected _activeFractionInterval: Segment1d; /** Return (reference to) the active portion of the reference spiral. */ - public get activeFractionInterval(): Segment1d { return this._activeFractionInterval; } + public get activeFractionInterval(): Segment1d { + return this._activeFractionInterval; + } /** strokes in the active portion */ public abstract get activeStrokes(): LineString3d; /** Placement transform */ protected _localToWorld: Transform; /** (reference to) placement transform. */ - public get localToWorld(): Transform { return this._localToWorld; } + public get localToWorld(): Transform { + return this._localToWorld; + } - protected constructor(spiralType: string | undefined, localToWorld: Transform, activeFractionInterval: Segment1d | undefined, designProperties: TransitionConditionalProperties | undefined) { + protected constructor( + spiralType: string | undefined, + localToWorld: Transform, + activeFractionInterval: Segment1d | undefined, + designProperties: TransitionConditionalProperties | undefined, + ) { super(); this._spiralType = spiralType ? spiralType : "unknownSpiralType"; this._designProperties = designProperties; @@ -95,9 +103,13 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { this._activeFractionInterval = activeFractionInterval ? activeFractionInterval : Segment1d.create(0, 1); } - public get spiralType(): string { return this._spiralType; } + public get spiralType(): string { + return this._spiralType; + } /** Return 1/r with convention that if true zero is given as radius it represents infinite radius (0 curvature, straight line) */ - public static radiusToCurvature(radius: number): number { return (radius === 0.0) ? 0.0 : 1.0 / radius; } + public static radiusToCurvature(radius: number): number { + return (radius === 0.0) ? 0.0 : 1.0 / radius; + } /** Return 1/k with convention that if near-zero is given as curvature, its infinite radius is returned as 0 */ public static curvatureToRadius(curvature: number): number { @@ -169,7 +181,9 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { return TransitionSpiral3d.curvatureToRadius((2.0 * sweepRadians / arcLength) - TransitionSpiral3d.radiusToCurvature(radius1)); } /** Return the original defining properties (if any) saved by the constructor. */ - public get designProperties(): TransitionConditionalProperties | undefined { return this._designProperties; } + public get designProperties(): TransitionConditionalProperties | undefined { + return this._designProperties; + } /** * * If transformA is rigid with uniform scale, apply the rigid part of transformA to the localToWorld transform and return the scale and rigid separation. * * If not rigid, do nothing and return undefined. @@ -207,20 +221,20 @@ export abstract class TransitionSpiral3d extends CurvePrimitive { } /** extend the range by the strokes of the spiral */ public override extendRange(rangeToExtend: Range3d, transform?: Transform): void { - const myRange = this.rangeBetweenFractions (0.0, 1.0, transform); - rangeToExtend.extendRange (myRange); + const myRange = this.rangeBetweenFractions(0.0, 1.0, transform); + rangeToExtend.extendRange(myRange); } /** return the range of spiral between fractions of the activeStrokes. * * Use activeStrokes point count times interval factor for initial evaluation count, but do at least 5 */ - public override rangeBetweenFractions(fractionA: number, fractionB: number, transform?: Transform): Range3d { + public override rangeBetweenFractions(fractionA: number, fractionB: number, transform?: Transform): Range3d { const strokes = this.activeStrokes; if (undefined === strokes) - return Range3d.createNull (); - let count = Math.ceil (strokes.numPoints() * Math.abs (fractionB - fractionA)); - count = Geometry.clamp (5, count, 30); - return this.rangeBetweenFractionsByCount (fractionA, fractionB, count, transform, 0.5); + return Range3d.createNull(); + let count = Math.ceil(strokes.numPoints() * Math.abs(fractionB - fractionA)); + count = Geometry.clamp(5, count, 30); + return this.rangeBetweenFractionsByCount(fractionA, fractionB, count, transform, 0.5); } /** Project instance geometry (via dispatch) onto the given ray, and return the extreme fractional parameters of projection. * @param ray ray onto which the instance is projected. A `Vector3d` is treated as a `Ray3d` with zero origin. diff --git a/core/geometry/src/curve/spiral/XYCurveEvaluator.ts b/core/geometry/src/curve/spiral/XYCurveEvaluator.ts index 1e1a54b2f0c6..c750050ceb19 100644 --- a/core/geometry/src/curve/spiral/XYCurveEvaluator.ts +++ b/core/geometry/src/curve/spiral/XYCurveEvaluator.ts @@ -10,8 +10,8 @@ import { Geometry } from "../../Geometry"; import { Plane3dByOriginAndVectors } from "../../geometry3d/Plane3dByOriginAndVectors"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Ray3d } from "../../geometry3d/Ray3d"; -import { Quadrature } from "../../numerics/Quadrature"; import { SimpleNewton } from "../../numerics/Newton"; +import { Quadrature } from "../../numerics/Quadrature"; /** * XYCurveEvaluator is an abstract with methods for evaluating X and Y parts of a curve parameterized by a fraction. * * The required methods call for independent X and Y evaluation. @@ -48,17 +48,30 @@ export abstract class XYCurveEvaluator { } /** Evaluate both X and Y and their first derivatives at fractional coordinate, return bundled as origin and (non-unit) direction vector. */ public fractionToPointAndDerivative(fraction: number, result?: Ray3d): Ray3d { - return Ray3d.createXYZUVW(this.fractionToX(fraction), this.fractionToY(fraction), 0.0, - this.fractionToDX(fraction), this.fractionToDY(fraction), 0, - result); + return Ray3d.createXYZUVW( + this.fractionToX(fraction), + this.fractionToY(fraction), + 0.0, + this.fractionToDX(fraction), + this.fractionToDY(fraction), + 0, + result, + ); } /** Evaluate both X and Y and their second derivatives at fractional coordinate, return bundled as origin and (non-unit) vectorU an vectorV. */ public fractionToPointAnd2Derivatives(fraction: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - this.fractionToX(fraction), this.fractionToY(fraction), 0.0, - this.fractionToDX(fraction), this.fractionToDY(fraction), 0, - this.fractionToDDX(fraction), this.fractionToDDY(fraction), 0, - result); + this.fractionToX(fraction), + this.fractionToY(fraction), + 0.0, + this.fractionToDX(fraction), + this.fractionToDY(fraction), + 0, + this.fractionToDDX(fraction), + this.fractionToDDY(fraction), + 0, + result, + ); } /** * Return the magnitude of the tangent vector at fraction. @@ -108,21 +121,24 @@ export abstract class XYCurveEvaluator { * @param distance1 distance at end * @param targetDistance intermediate distance. */ - public inverseDistanceFraction(fraction0: number, fraction1: number, distance0: number, distance1: number, targetDistance: number): number | undefined { + public inverseDistanceFraction( + fraction0: number, + fraction1: number, + distance0: number, + distance1: number, + targetDistance: number, + ): number | undefined { const startFraction = Geometry.inverseInterpolate(fraction0, distance0, fraction1, distance1, targetDistance); if (startFraction !== undefined) { - return SimpleNewton.runNewton1D(startFraction, - (fraction: number) => { - const d = this.integrateDistanceBetweenFractions(fraction0, fraction); - return distance0 + d - targetDistance; - }, - (fraction: number) => this.fractionToTangentMagnitude(fraction)); + return SimpleNewton.runNewton1D(startFraction, (fraction: number) => { + const d = this.integrateDistanceBetweenFractions(fraction0, fraction); + return distance0 + d - targetDistance; + }, (fraction: number) => this.fractionToTangentMagnitude(fraction)); } return undefined; } /** - * * @param fraction fractional position along x axis * @param xy xy coordinates of point on the curve * @param d1xy diff --git a/core/geometry/src/geometry3d/Angle.ts b/core/geometry/src/geometry3d/Angle.ts index 6474678223ff..19fea9a6ff59 100644 --- a/core/geometry/src/geometry3d/Angle.ts +++ b/core/geometry/src/geometry3d/Angle.ts @@ -339,8 +339,7 @@ export class Angle implements BeJSONFunctions { * @param radiansB second radians value * @param radianTol radian tolerance with default value of Geometry.smallAngleRadians */ - public static isAlmostEqualRadiansAllowPeriodShift(radiansA: number, radiansB: number, - radianTol: number = Geometry.smallAngleRadians): boolean { + public static isAlmostEqualRadiansAllowPeriodShift(radiansA: number, radiansB: number, radianTol: number = Geometry.smallAngleRadians): boolean { const delta = Math.abs(radiansA - radiansB); if (delta <= radianTol) return true; @@ -352,9 +351,9 @@ export class Angle implements BeJSONFunctions { return Math.abs(delta1) <= radianTol; } /** - * Test if this angle has magnitude no greater than that of `other`. - * @param other the other angle - */ + * Test if this angle has magnitude no greater than that of `other`. + * @param other the other angle + */ public isMagnitudeLessThanOrEqual(other: Angle): boolean { return Math.abs(this.radians) <= Math.abs(other.radians); } @@ -373,8 +372,7 @@ export class Angle implements BeJSONFunctions { * @param radiansB second radians value * @param radianTol radian tolerance with default value of Geometry.smallAngleRadians */ - public static isAlmostEqualRadiansNoPeriodShift(radiansA: number, radiansB: number, - radianTol: number = Geometry.smallAngleRadians): boolean { + public static isAlmostEqualRadiansNoPeriodShift(radiansA: number, radiansB: number, radianTol: number = Geometry.smallAngleRadians): boolean { return Math.abs(radiansA - radiansB) < radianTol; } /** @@ -470,7 +468,10 @@ export class Angle implements BeJSONFunctions { * @return the angle t0 and its cosine and sine. */ public static dotProductsToHalfAngleTrigValues( - dotUU: number, dotVV: number, dotUV: number, favorZero: boolean = true, + dotUU: number, + dotVV: number, + dotUV: number, + favorZero: boolean = true, ): TrigValues { const cos2t0 = dotUU - dotVV; const sin2t0 = 2.0 * dotUV; @@ -489,7 +490,12 @@ export class Angle implements BeJSONFunctions { * @param vz z component of vector v */ public static radiansBetweenVectorsXYZ( - ux: number, uy: number, uz: number, vx: number, vy: number, vz: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, ): number { const uDotV = ux * vx + uy * vy + uz * vz; return Math.atan2(Geometry.crossProductMagnitude(ux, uy, uz, vx, vy, vz), uDotV); @@ -513,9 +519,15 @@ export class Angle implements BeJSONFunctions { * signed (-PI < radians <= PI) */ public static orientedRadiansBetweenVectorsXYZ( - ux: number, uy: number, uz: number, - vx: number, vy: number, vz: number, - upVectorX: number, upVectorY: number, upVectorZ: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, + upVectorX: number, + upVectorY: number, + upVectorZ: number, adjustToPositive: boolean = false, ): number { const uDotV = ux * vx + uy * vy + uz * vz; diff --git a/core/geometry/src/geometry3d/AngleSweep.ts b/core/geometry/src/geometry3d/AngleSweep.ts index 8cda7035aa02..ac95d5b87dad 100644 --- a/core/geometry/src/geometry3d/AngleSweep.ts +++ b/core/geometry/src/geometry3d/AngleSweep.ts @@ -295,7 +295,12 @@ export class AngleSweep implements BeJSONFunctions { * @param zeroSweepDefault return value when the sweep is empty (default 0) * @returns nonnegative fraction, or `zeroSweepDefault` if the sweep is empty. */ - public static radiansToPositivePeriodicFractionStartEnd(radians: number, radians0: number, radians1: number, zeroSweepDefault: number = 0.0): number { + public static radiansToPositivePeriodicFractionStartEnd( + radians: number, + radians0: number, + radians1: number, + zeroSweepDefault: number = 0.0, + ): number { const zeroSweepMarker = Geometry.largeCoordinateResult; let fraction = this.radiansToSignedPeriodicFractionStartEnd(radians, radians0, radians1, zeroSweepMarker); if (fraction === zeroSweepMarker) @@ -430,7 +435,13 @@ export class AngleSweep implements BeJSONFunctions { * @param zeroSweepDefault return value when the sweep is empty (default 0). * @returns fraction, or `zeroSweepDefault` if the sweep is empty */ - public static radiansToSignedFractionStartEnd(radians: number, radians0: number, radians1: number, toNegativeFraction: boolean = false, zeroSweepDefault: number = 0.0): number { + public static radiansToSignedFractionStartEnd( + radians: number, + radians0: number, + radians1: number, + toNegativeFraction: boolean = false, + zeroSweepDefault: number = 0.0, + ): number { const zeroSweepMarker = Geometry.largeCoordinateResult; let fraction = this.radiansToSignedPeriodicFractionStartEnd(radians, radians0, radians1, zeroSweepMarker); if (fraction === zeroSweepMarker) @@ -481,7 +492,9 @@ export class AngleSweep implements BeJSONFunctions { if (delta0 * delta1 <= 0.0) return true; if (radians0 === radians1) - return allowPeriodShift ? Angle.isAlmostEqualRadiansAllowPeriodShift(radians, radians0) : Angle.isAlmostEqualRadiansNoPeriodShift(radians, radians0); + return allowPeriodShift + ? Angle.isAlmostEqualRadiansAllowPeriodShift(radians, radians0) + : Angle.isAlmostEqualRadiansNoPeriodShift(radians, radians0); return allowPeriodShift ? this.radiansToPositivePeriodicFractionStartEnd(radians, radians0, radians1, 1000.0) <= 1.0 : false; } /** Test if the given angle (as radians) is within sweep */ diff --git a/core/geometry/src/geometry3d/BarycentricTriangle.ts b/core/geometry/src/geometry3d/BarycentricTriangle.ts index de4d57657b6e..751fea211d09 100644 --- a/core/geometry/src/geometry3d/BarycentricTriangle.ts +++ b/core/geometry/src/geometry3d/BarycentricTriangle.ts @@ -182,9 +182,15 @@ export class BarycentricTriangle { * @param result optional pre-allocated triangle. */ public static createXYZXYZXYZ( - x0: number, y0: number, z0: number, - x1: number, y1: number, z1: number, - x2: number, y2: number, z2: number, + x0: number, + y0: number, + z0: number, + x1: number, + y1: number, + z1: number, + x2: number, + y2: number, + z2: number, result?: BarycentricTriangle, ): BarycentricTriangle { if (!result) @@ -196,7 +202,10 @@ export class BarycentricTriangle { } /** Create a triangle with coordinates cloned from given points. */ public static create( - point0: Point3d, point1: Point3d, point2: Point3d, result?: BarycentricTriangle, + point0: Point3d, + point1: Point3d, + point2: Point3d, + result?: BarycentricTriangle, ): BarycentricTriangle { if (!result) return new this(point0.clone(), point1.clone(), point2.clone()); @@ -238,7 +247,9 @@ export class BarycentricTriangle { /** Return area divided by sum of squared lengths. */ public get aspectRatio(): number { return Geometry.safeDivideFraction( - this.area, this.edgeLengthSquared(0) + this.edgeLengthSquared(1) + this.edgeLengthSquared(2), 0, + this.area, + this.edgeLengthSquared(0) + this.edgeLengthSquared(1) + this.edgeLengthSquared(2), + 0, ); } /** Return the perimeter of the triangle. */ @@ -418,8 +429,12 @@ export class BarycentricTriangle { const j = Geometry.cyclic3dAxis(i + 1); const k = Geometry.cyclic3dAxis(j + 1); return Geometry.dotProductXYZXYZ( - this.points[j].x - this.points[i].x, this.points[j].y - this.points[i].y, this.points[j].z - this.points[i].z, - this.points[k].x - this.points[i].x, this.points[k].y - this.points[i].y, this.points[k].z - this.points[i].z, + this.points[j].x - this.points[i].x, + this.points[j].y - this.points[i].y, + this.points[j].z - this.points[i].z, + this.points[k].x - this.points[i].x, + this.points[k].y - this.points[i].y, + this.points[k].z - this.points[i].z, ); } /** @@ -463,7 +478,7 @@ export class BarycentricTriangle { */ public closestPoint(b0: number, b1: number, b2: number): { closestEdgeIndex: number, closestEdgeParam: number } { const b: number[] = [b0, b1, b2]; - let edgeIndex = -1; // opposite-vertex index + let edgeIndex = -1; // opposite-vertex index let edgeParam = 0.0; if (BarycentricTriangle.isInsideTriangle(b0, b1, b2)) { // projects to any edge edgeIndex = BarycentricTriangle.indexOfMinimum((i: number) => { @@ -486,7 +501,7 @@ export class BarycentricTriangle { } else if ((edgeIndex = BarycentricTriangle.isInRegionBeyondEdge(b0, b1, b2)) >= 0) { // projects to the edge or its vertices edgeParam = this.computeProjectionToEdge(edgeIndex, b); if (edgeParam < 0) { - edgeParam = 0.0; // start of this edge + edgeParam = 0.0; // start of this edge } else if (edgeParam > 1) { edgeParam = 0.0; edgeIndex = Geometry.cyclic3dAxis(edgeIndex + 1); // end of this edge = start of next edge @@ -518,7 +533,7 @@ export class BarycentricTriangle { * * `d.classify` can be used to determine where the intersection lies with respect to the triangle. * * Visualization can be found at https://www.itwinjs.org/sandbox/SaeedTorabi/RayTriangleIntersection * @see [[pointToFraction]] - */ + */ public intersectRay3d(ray: Ray3d, result?: TriangleLocationDetail): TriangleLocationDetail { result = TriangleLocationDetail.create(result); /** @@ -531,16 +546,20 @@ export class BarycentricTriangle { const r0 = ray.origin; const d = ray.direction; const u = BarycentricTriangle._workVector0 = Vector3d.createStartEnd( - this.points[0], this.points[1], BarycentricTriangle._workVector0, + this.points[0], + this.points[1], + BarycentricTriangle._workVector0, ); const v = BarycentricTriangle._workVector1 = Vector3d.createStartEnd( - this.points[0], this.points[2], BarycentricTriangle._workVector1, + this.points[0], + this.points[2], + BarycentricTriangle._workVector1, ); const M = BarycentricTriangle._workMatrix = Matrix3d.createColumns(u, v, d, BarycentricTriangle._workMatrix); - const c = Vector3d.createStartEnd(this.points[0], r0, BarycentricTriangle._workVector0); // reuse workVector0 - const solution = BarycentricTriangle._workVector1; // reuse workVector1 + const c = Vector3d.createStartEnd(this.points[0], r0, BarycentricTriangle._workVector0); // reuse workVector0 + const solution = BarycentricTriangle._workVector1; // reuse workVector1 if (undefined === M.multiplyInverse(c, solution)) - return result; // invalid + return result; // invalid result.a = -solution.z; // = -(-s) = s ray.fractionToPoint(result.a, result.world); result.local.set(1.0 - solution.x - solution.y, solution.x, solution.y); // = (1 - b1 - b2, b1, b2) = (b0 , b1, b2) @@ -559,7 +578,7 @@ export class BarycentricTriangle { * * `d.classify` can be used to determine where the intersection lies with respect to the triangle. * * `d.a` is the intersection parameter. If `d.a` is in [0,1], the segment intersects the plane of the triangle. * @see [[intersectRay3d]] - */ + */ public intersectSegment(point0: Point3d, point1: Point3d, result?: TriangleLocationDetail): TriangleLocationDetail { BarycentricTriangle._workRay = Ray3d.createStartEnd(point0, point1, BarycentricTriangle._workRay); return this.intersectRay3d(BarycentricTriangle._workRay, result); @@ -598,9 +617,11 @@ export class BarycentricTriangle { BarycentricTriangle.isOnBoundedEdge(location.local.x, location.local.y, location.local.z), ); location.closestEdgeParam = 1.0 - location.local.at(location.closestEdgeIndex); - } else { // 2 snapped, at vertex + } else { // 2 snapped, at vertex location.closestEdgeIndex = BarycentricTriangle.isOnVertex( - location.local.x, location.local.y, location.local.z, + location.local.x, + location.local.y, + location.local.z, ); location.closestEdgeParam = 0.0; } @@ -614,7 +635,9 @@ export class BarycentricTriangle { const j = (i + 1) % 3; const k = (j + 1) % 3; const edgeProjection = BarycentricTriangle._workPoint = this.points[i].interpolate( - location.closestEdgeParam, this.points[j], BarycentricTriangle._workPoint, + location.closestEdgeParam, + this.points[j], + BarycentricTriangle._workPoint, ); const dist = location.world.distance(edgeProjection); if (dist > 0.0 && dist < distanceTolerance) { @@ -635,10 +658,14 @@ export class BarycentricTriangle { */ public dotProductOfCrossProductsFromOrigin(other: BarycentricTriangle): number { BarycentricTriangle._workVector0 = this.points[0].crossProductToPoints( - this.points[1], this.points[2], BarycentricTriangle._workVector0, + this.points[1], + this.points[2], + BarycentricTriangle._workVector0, ); BarycentricTriangle._workVector1 = other.points[0].crossProductToPoints( - other.points[1], other.points[2], BarycentricTriangle._workVector1, + other.points[1], + other.points[2], + BarycentricTriangle._workVector1, ); return BarycentricTriangle._workVector0.dotProduct(BarycentricTriangle._workVector1); } diff --git a/core/geometry/src/geometry3d/BilinearPatch.ts b/core/geometry/src/geometry3d/BilinearPatch.ts index 6993d7903ce2..316d108e564e 100644 --- a/core/geometry/src/geometry3d/BilinearPatch.ts +++ b/core/geometry/src/geometry3d/BilinearPatch.ts @@ -82,10 +82,18 @@ export class BilinearPatch implements UVSurface { } /** Create a patch from xyz values of the 4 corners. */ public static createXYZ( - x00: number, y00: number, z00: number, - x10: number, y10: number, z10: number, - x01: number, y01: number, z01: number, - x11: number, y11: number, z11: number, + x00: number, + y00: number, + z00: number, + x10: number, + y10: number, + z10: number, + x01: number, + y01: number, + z01: number, + x11: number, + y11: number, + z11: number, ) { return new BilinearPatch( Point3d.create(x00, y00, z00), @@ -217,17 +225,25 @@ export class BilinearPatch implements UVSurface { SmallSystem.eliminateFromPivot(coffs[0], 0, coffs[1], -1.0); SmallSystem.eliminateFromPivot(coffs[0], 0, coffs[2], -1.0); const uvArray = SmallSystem.solveBilinearPair( - coffs[1][1], coffs[1][2], coffs[1][3], coffs[1][4], - coffs[2][1], coffs[2][2], coffs[2][3], coffs[2][4], + coffs[1][1], + coffs[1][2], + coffs[1][3], + coffs[1][4], + coffs[2][1], + coffs[2][2], + coffs[2][3], + coffs[2][4], ); if (uvArray) { const result: CurveAndSurfaceLocationDetail[] = []; for (const uv of uvArray) { const t = -(coffs[0][1] + coffs[0][2] * uv.x + (coffs[0][3] + coffs[0][4] * uv.x) * uv.y) / coffs[0][0]; const point = ray.fractionToPoint(t); - result.push(new CurveAndSurfaceLocationDetail( - CurveLocationDetail.createRayFractionPoint(ray, t, point), - UVSurfaceLocationDetail.createSurfaceUVPoint(this, uv, point)), + result.push( + new CurveAndSurfaceLocationDetail( + CurveLocationDetail.createRayFractionPoint(ray, t, point), + UVSurfaceLocationDetail.createSurfaceUVPoint(this, uv, point), + ), ); } return result; diff --git a/core/geometry/src/geometry3d/CoincidentGeometryOps.ts b/core/geometry/src/geometry3d/CoincidentGeometryOps.ts index 046c8de361f0..03e8495700e4 100644 --- a/core/geometry/src/geometry3d/CoincidentGeometryOps.ts +++ b/core/geometry/src/geometry3d/CoincidentGeometryOps.ts @@ -40,8 +40,14 @@ export class CoincidentGeometryQuery { * * Assign both the fraction and fraction1 values in the detail, possibly swapped. * * reevaluate the points as simple interpolation between given points. */ - public static assignDetailInterpolatedFractionsAndPoints(detail: CurveLocationDetail, f0: number, f1: number, - pointA: Point3d, pointB: Point3d, swap: boolean = false) { + public static assignDetailInterpolatedFractionsAndPoints( + detail: CurveLocationDetail, + f0: number, + f1: number, + pointA: Point3d, + pointB: Point3d, + swap: boolean = false, + ) { if (swap) { detail.fraction = f1; detail.fraction1 = f0; @@ -51,7 +57,6 @@ export class CoincidentGeometryQuery { } detail.point = pointA.interpolate(detail.fraction, pointB, detail.point); detail.point1 = pointA.interpolate(detail.fraction1, pointB, detail.point1); - } /** Return a curve location detail with projection of a `spacePoint` to the line segment with `pointA` and `pointB` */ @@ -61,8 +66,7 @@ export class CoincidentGeometryQuery { const uDotU = this._vectorU.dotProductXY(this._vectorU); const uDotV = this._vectorU.dotProductXY(this._vectorV); const fraction = Geometry.safeDivideFraction(uDotV, uDotU, 0.0); - return CurveLocationDetail.createCurveFractionPoint(undefined, fraction, - pointA.interpolate(fraction, pointB)); + return CurveLocationDetail.createCurveFractionPoint(undefined, fraction, pointA.interpolate(fraction, pointB)); } /** * Given a detail pair representing the projection of each of two colinear line segments onto the other, @@ -78,9 +82,16 @@ export class CoincidentGeometryQuery { * @param extendB1 whether to extend segment B beyond its end * @return reference to the input clamped in place, or undefined (leaving interval untouched) if clamping would result in empty interval. */ - public clampCoincidentOverlapToSegmentBounds(overlap: CurveLocationDetailPair, - pointA0: Point3d, pointA1: Point3d, pointB0: Point3d, pointB1: Point3d, - extendA0: boolean = false, extendA1: boolean = false, extendB0: boolean = false, extendB1: boolean = false, + public clampCoincidentOverlapToSegmentBounds( + overlap: CurveLocationDetailPair, + pointA0: Point3d, + pointA1: Point3d, + pointB0: Point3d, + pointB1: Point3d, + extendA0: boolean = false, + extendA1: boolean = false, + extendB0: boolean = false, + extendB1: boolean = false, ): CurveLocationDetailPair | undefined { const rangeA = Segment1d.create(overlap.detailA.fraction, overlap.detailA.hasFraction1 ? overlap.detailA.fraction1 : overlap.detailA.fraction); const rangeB = Segment1d.create(overlap.detailB.fraction, overlap.detailB.hasFraction1 ? overlap.detailB.fraction1 : overlap.detailB.fraction); @@ -100,9 +111,9 @@ export class CoincidentGeometryQuery { const haveIntervalB = rangeB.clampDirectedTo01(!extendB0, !extendB1, false); if (haveIntervalA && haveIntervalB) { if (Geometry.isAlmostEqualNumber(rangeA.absoluteDelta(), rangeB.absoluteDelta(), Geometry.smallFraction)) - return updateIntervalFromRangesAndInterpolatedPoints(); // intersection of partially clamped ranges + return updateIntervalFromRangesAndInterpolatedPoints(); // intersection of partially clamped ranges else if (rangeA.clampDirectedTo01(true, true, false) && rangeB.clampDirectedTo01(true, true, false)) - return updateIntervalFromRangesAndInterpolatedPoints(); // intersection of fully clamped ranges + return updateIntervalFromRangesAndInterpolatedPoints(); // intersection of fully clamped ranges } const collapseToSingleton = (pointA: Point3d, pointB: Point3d, atStartA: boolean, atStartB: boolean): CurveLocationDetailPair => { @@ -144,7 +155,13 @@ export class CoincidentGeometryQuery { * @param restrictToBounds whether to clip the coincident segment details to the segment bounds * @return detail pair for the coincident interval (`detailA` has fractions along segment A, and `detailB` has fractions along segment B), or undefined if no coincidence */ - public coincidentSegmentRangeXY(pointA0: Point3d, pointA1: Point3d, pointB0: Point3d, pointB1: Point3d, restrictToBounds: boolean = true): CurveLocationDetailPair | undefined { + public coincidentSegmentRangeXY( + pointA0: Point3d, + pointA1: Point3d, + pointB0: Point3d, + pointB1: Point3d, + restrictToBounds: boolean = true, + ): CurveLocationDetailPair | undefined { const detailA0OnB = this.projectPointToSegmentXY(pointA0, pointB0, pointB1); if (pointA0.distanceXY(detailA0OnB.point) > this._tolerance) return undefined; @@ -160,7 +177,7 @@ export class CoincidentGeometryQuery { return undefined; detailA0OnB.fraction1 = detailA1OnB.fraction; - detailA0OnB.point1 = detailA1OnB.point; // capture -- detailA1OnB is not reused. + detailA0OnB.point1 = detailA1OnB.point; // capture -- detailA1OnB is not reused. detailB0OnA.fraction1 = detailB1OnA.fraction; detailB0OnA.point1 = detailB1OnA.point; const interval = CurveLocationDetailPair.createCapture(detailB0OnA, detailA0OnB); @@ -176,7 +193,14 @@ export class CoincidentGeometryQuery { * @param fractionB1 curveB end in fraction space of curveA * @param reverse whether curveB and curveA have opposite direction */ - private createDetailPair(cpA: CurvePrimitive, cpB: CurvePrimitive, fractionsOnA: Segment1d, fractionB0: number, fractionB1: number, reverse: boolean): CurveLocationDetailPair | undefined { + private createDetailPair( + cpA: CurvePrimitive, + cpB: CurvePrimitive, + fractionsOnA: Segment1d, + fractionB0: number, + fractionB1: number, + reverse: boolean, + ): CurveLocationDetailPair | undefined { const deltaB = fractionB1 - fractionB0; const g0 = Geometry.conditionalDivideFraction(fractionsOnA.x0 - fractionB0, deltaB); const g1 = Geometry.conditionalDivideFraction(fractionsOnA.x1 - fractionB0, deltaB); @@ -189,7 +213,10 @@ export class CoincidentGeometryQuery { } return undefined; } - private appendDetailPair(result: CurveLocationDetailPair[] | undefined, pair: CurveLocationDetailPair | undefined): CurveLocationDetailPair[] | undefined { + private appendDetailPair( + result: CurveLocationDetailPair[] | undefined, + pair: CurveLocationDetailPair | undefined, + ): CurveLocationDetailPair[] | undefined { if (pair === undefined) return result; if (result === undefined) @@ -209,27 +236,31 @@ export class CoincidentGeometryQuery { if (arcA.center.isAlmostEqual(arcB.center, this.tolerance)) { const matrixBToA = arcA.matrixRef.multiplyMatrixInverseMatrix(arcB.matrixRef); if (matrixBToA) { - const ux = matrixBToA.at(0, 0); const uy = matrixBToA.at(1, 0); - const vx = matrixBToA.at(0, 1); const vy = matrixBToA.at(1, 1); + const ux = matrixBToA.at(0, 0); + const uy = matrixBToA.at(1, 0); + const vx = matrixBToA.at(0, 1); + const vy = matrixBToA.at(1, 1); const ru = Geometry.hypotenuseXY(ux, uy); const rv = Geometry.hypotenuseXY(vx, vy); const dot = Geometry.dotProductXYXY(ux, uy, vx, vy); const cross = Geometry.crossProductXYXY(ux, uy, vx, vy); - if (Geometry.isAlmostEqualNumber(ru, 1.0) + if ( + Geometry.isAlmostEqualNumber(ru, 1.0) && Geometry.isAlmostEqualNumber(rv, 1.0) - && Geometry.isAlmostEqualNumber(0, dot)) { - const alphaB0Radians = Math.atan2(uy, ux); // angular position of arcB 0 point in arcA sweep - const sweepDirection = cross > 0 ? 1.0 : -1.0; // 1 if arcB parameter space sweeps in same direction as arcA, -1 if opposite - const betaStartRadians = alphaB0Radians + sweepDirection * arcB.sweep.startRadians; // arcB start in arcA parameter space - const betaEndRadians = alphaB0Radians + sweepDirection * arcB.sweep.endRadians; // arcB end in arcA parameter space + && Geometry.isAlmostEqualNumber(0, dot) + ) { + const alphaB0Radians = Math.atan2(uy, ux); // angular position of arcB 0 point in arcA sweep + const sweepDirection = cross > 0 ? 1.0 : -1.0; // 1 if arcB parameter space sweeps in same direction as arcA, -1 if opposite + const betaStartRadians = alphaB0Radians + sweepDirection * arcB.sweep.startRadians; // arcB start in arcA parameter space + const betaEndRadians = alphaB0Radians + sweepDirection * arcB.sweep.endRadians; // arcB end in arcA parameter space const fractionSpacesReversed = (sweepDirection * arcA.sweep.sweepRadians * arcB.sweep.sweepRadians) < 0; const sweepB = AngleSweep.createStartEndRadians(betaStartRadians, betaEndRadians); const sweepA = arcA.sweep; const fractionPeriodA = sweepA.fractionPeriod(); - const fractionB0 = sweepA.radiansToPositivePeriodicFraction(sweepB.startRadians); // arcB start in arcA fraction space + const fractionB0 = sweepA.radiansToPositivePeriodicFraction(sweepB.startRadians); // arcB start in arcA fraction space assert(fractionB0 >= 0.0); - const fractionSweep = sweepB.sweepRadians / sweepA.sweepRadians; // arcB sweep in arcA fraction space - const fractionB1 = fractionB0 + fractionSweep; // arcB end in arcA fraction space + const fractionSweep = sweepB.sweepRadians / sweepA.sweepRadians; // arcB sweep in arcA fraction space + const fractionB1 = fractionB0 + fractionSweep; // arcB end in arcA fraction space const fractionSweepB = Segment1d.create(fractionB0, fractionB1); /** lambda to add a coincident interval or isolated intersection, given inputs in arcA fraction space @@ -242,8 +273,11 @@ export class CoincidentGeometryQuery { const arcBStart = arcBInArcAFractionSpace.x0; const arcBEnd = arcBInArcAFractionSpace.x1; if (arcBInArcAFractionSpace.clampDirectedTo01() && !Geometry.isSmallRelative(arcBInArcAFractionSpace.absoluteDelta())) { - result = this.appendDetailPair(result, this.createDetailPair(arcA, arcB, arcBInArcAFractionSpace, arcBStart, arcBEnd, fractionSpacesReversed)); - } else { // test isolated intersection + result = this.appendDetailPair( + result, + this.createDetailPair(arcA, arcB, arcBInArcAFractionSpace, arcBStart, arcBEnd, fractionSpacesReversed), + ); + } else { // test isolated intersection const testStartOfArcB = fractionSpacesReversed ? testStartOfArcA : !testStartOfArcA; const arcAPt = this._point0 = testStartOfArcA ? arcA.startPoint(this._point0) : arcA.endPoint(this._point0); const arcBPt = this._point1 = testStartOfArcB ? arcB.startPoint(this._point1) : arcB.endPoint(this._point1); @@ -256,7 +290,7 @@ export class CoincidentGeometryQuery { return result !== undefined && result.length > size; }; - appendCoincidentIntersection(fractionSweepB, false); // compute overlap in strict interior, or at end of arcA + appendCoincidentIntersection(fractionSweepB, false); // compute overlap in strict interior, or at end of arcA // check overlap at start of arcA with a periodic shift of fractionSweepB if (fractionB1 >= fractionPeriodA) diff --git a/core/geometry/src/geometry3d/Ellipsoid.ts b/core/geometry/src/geometry3d/Ellipsoid.ts index efa1dced8dae..a82a6ea6ec9b 100644 --- a/core/geometry/src/geometry3d/Ellipsoid.ts +++ b/core/geometry/src/geometry3d/Ellipsoid.ts @@ -77,7 +77,6 @@ class EllipsoidComponentExtrema { this.sinPhi0 = Math.sin(this.phi0Radians); this._axisRange = Range1d.createNull(); this._trigForm = new SineCosinePolynomial(0, 0, 0); - } /** * Create a component object with coefficients from a row of a `Transform`. @@ -86,18 +85,28 @@ class EllipsoidComponentExtrema { */ public static createTransformRow(transform: Transform, axisIndex: AxisIndex): EllipsoidComponentExtrema { const matrix = transform.matrix; - return new EllipsoidComponentExtrema(transform.origin.at(axisIndex), matrix.at(axisIndex, 0), matrix.at(axisIndex, 1), matrix.at(axisIndex, 2), axisIndex); + return new EllipsoidComponentExtrema( + transform.origin.at(axisIndex), + matrix.at(axisIndex, 0), + matrix.at(axisIndex, 1), + matrix.at(axisIndex, 2), + axisIndex, + ); } public extendRangeForSmoothSurfacePoints(range: Range3d, theta0Radians: number, theta1Radians: number, phi0Radians: number, phi1Radians: number) { const delta = (this.u * this.cosTheta0 + this.v * this.sinTheta0) * this.cosPhi0 + this.w * this.sinPhi0; - if (AngleSweep.isRadiansInStartEnd(this.theta0Radians, theta0Radians, theta1Radians) - && AngleSweep.isRadiansInStartEnd(this.phi0Radians, phi0Radians, phi1Radians, false)) { + if ( + AngleSweep.isRadiansInStartEnd(this.theta0Radians, theta0Radians, theta1Radians) + && AngleSweep.isRadiansInStartEnd(this.phi0Radians, phi0Radians, phi1Radians, false) + ) { range.extendSingleAxis(this.c + delta, this.axisIndex); } const thetaRadians = this.theta0Radians + Math.PI; const phiRadians = -this.phi0Radians; - if (AngleSweep.isRadiansInStartEnd(thetaRadians, theta0Radians, theta1Radians) - && AngleSweep.isRadiansInStartEnd(phiRadians, phi0Radians, phi1Radians, false)) { + if ( + AngleSweep.isRadiansInStartEnd(thetaRadians, theta0Radians, theta1Radians) + && AngleSweep.isRadiansInStartEnd(phiRadians, phi0Radians, phi1Radians, false) + ) { // cosTheta and sinTheta are both negated // sinPhi is negated // delta is negated @@ -114,7 +123,7 @@ class EllipsoidComponentExtrema { public extendRangeForConstantThetaArc(range: Range3d, thetaRadians: number, phi0Radians: number, phi1Radians: number) { const cosTheta = Math.cos(thetaRadians); const sinTheta = Math.sin(thetaRadians); - this._trigForm.set(this.c, (this.u * cosTheta + this.v * sinTheta), this.w); + this._trigForm.set(this.c, this.u * cosTheta + this.v * sinTheta, this.w); this._trigForm.rangeInStartEndRadians(phi0Radians, phi1Radians, this._axisRange); range.extendSingleAxis(this._axisRange.low, this.axisIndex); range.extendSingleAxis(this._axisRange.high, this.axisIndex); @@ -193,7 +202,9 @@ export class Ellipsoid implements Clipper { * * In the sphere space, an xyz (vector from origin) with magnitude less than 1 is INSIDE the sphere (hence its world image is INSIDE the ellipsoid) * * In the sphere space, an xyz (vector from origin) with magnitude greater than 1 is OUTSIDE the sphere (hence its world image is OUTSIDE the ellipsoid) */ - public get transformRef(): Transform { return this._transform; } + public get transformRef(): Transform { + return this._transform; + } /** * * Convert a world point to point within the underlying mapped sphere space. * * In the sphere space, an xyz (vector from origin) with magnitude equal to 1 is ON the sphere (hence its world image is ON the ellipsoid) @@ -257,7 +268,7 @@ export class Ellipsoid implements Clipper { const localPlaneB = localPlaneA.toPlane3dByOriginAndUnitNormal(); // if the silhouette plane has origin inside the sphere, there is a silhouette with center at the plane origin. if (localPlaneB) { - const rr = 1.0 - localPlaneB.getOriginRef().magnitudeSquared(); // squared distance radius of silhouette arc + const rr = 1.0 - localPlaneB.getOriginRef().magnitudeSquared(); // squared distance radius of silhouette arc if (rr > 0.0 && rr <= 1.0) { const arc = Arc3d.createCenterNormalRadius(localPlaneB.getOriginRef(), localPlaneB.getNormalRef(), Math.sqrt(rr)); if (arc.tryTransformInPlace(this._transform)) @@ -277,7 +288,12 @@ export class Ellipsoid implements Clipper { * * For each optional array, caller must of course initialize an array (usually empty) * * return 0 if ray length is too small. */ - public intersectRay(ray: Ray3d, rayFractions: number[] | undefined, xyz: Point3d[] | undefined, thetaPhiRadians: LongitudeLatitudeNumber[] | undefined): number { + public intersectRay( + ray: Ray3d, + rayFractions: number[] | undefined, + xyz: Point3d[] | undefined, + thetaPhiRadians: LongitudeLatitudeNumber[] | undefined, + ): number { if (xyz) xyz.length = 0; if (thetaPhiRadians !== undefined) @@ -309,7 +325,13 @@ export class Ellipsoid implements Clipper { } /** Return the range of a uv-aligned patch of the sphere. */ - public patchRangeStartEndRadians(theta0Radians: number, theta1Radians: number, phi0Radians: number, phi1Radians: number, result?: Range3d): Range3d { + public patchRangeStartEndRadians( + theta0Radians: number, + theta1Radians: number, + phi0Radians: number, + phi1Radians: number, + result?: Range3d, + ): Range3d { const xExtreme = EllipsoidComponentExtrema.createTransformRow(this._transform, 0); const yExtreme = EllipsoidComponentExtrema.createTransformRow(this._transform, 1); const zExtreme = EllipsoidComponentExtrema.createTransformRow(this._transform, 2); @@ -374,9 +396,12 @@ export class Ellipsoid implements Clipper { * @param result optional preallocated result */ public radiansPairToGreatArc( - thetaARadians: number, phiARadians: number, - thetaBRadians: number, phiBRadians: number, - result?: Arc3d): Arc3d | undefined { + thetaARadians: number, + phiARadians: number, + thetaBRadians: number, + phiBRadians: number, + result?: Arc3d, + ): Arc3d | undefined { SphereImplicit.radiansToUnitSphereXYZ(thetaARadians, phiARadians, this._unitVectorA); SphereImplicit.radiansToUnitSphereXYZ(thetaBRadians, phiBRadians, this._unitVectorB); const sweepAngle = this._unitVectorA.angleTo(this._unitVectorB); @@ -384,8 +409,13 @@ export class Ellipsoid implements Clipper { const matrix = Matrix3d.createRigidFromColumns(this._unitVectorA, this._unitVectorB, AxisOrder.XYZ)!; if (matrix !== undefined) { const matrix1 = this._transform.matrix.multiplyMatrixMatrix(matrix); - return Arc3d.create(this._transform.getOrigin(), matrix1.columnX(), matrix1.columnY(), - AngleSweep.createStartEndRadians(0.0, sweepAngle.radians), result); + return Arc3d.create( + this._transform.getOrigin(), + matrix1.columnX(), + matrix1.columnY(), + AngleSweep.createStartEndRadians(0.0, sweepAngle.radians), + result, + ); } return undefined; } @@ -394,7 +424,12 @@ export class Ellipsoid implements Clipper { */ public anglePairToGreatArc(angleA: LongitudeLatitudeNumber, angleB: LongitudeLatitudeNumber, result?: Arc3d): Arc3d | undefined { return this.radiansPairToGreatArc( - angleA.longitudeRadians, angleA.latitudeRadians, angleB.longitudeRadians, angleB.latitudeRadians, result); + angleA.longitudeRadians, + angleA.latitudeRadians, + angleB.longitudeRadians, + angleB.latitudeRadians, + result, + ); } /** * Construct an arc for the section cut of a plane with the ellipsoid. @@ -428,8 +463,12 @@ export class Ellipsoid implements Clipper { * * ends at pointB (defined by its angle position) * * contains the 3rd vector as an in-plane point. */ - public createSectionArcPointPointVectorInPlane(pointAnglesA: LongitudeLatitudeNumber, pointAnglesB: LongitudeLatitudeNumber, inPlaneVector: Vector3d, - result?: Arc3d): Arc3d | undefined { + public createSectionArcPointPointVectorInPlane( + pointAnglesA: LongitudeLatitudeNumber, + pointAnglesB: LongitudeLatitudeNumber, + inPlaneVector: Vector3d, + result?: Arc3d, + ): Arc3d | undefined { const xyzA = this.radiansToPoint(pointAnglesA.longitudeRadians, pointAnglesA.latitudeRadians); const xyzB = this.radiansToPoint(pointAnglesB.longitudeRadians, pointAnglesB.latitudeRadians); const localA = this._transform.multiplyInversePoint3d(xyzA); @@ -470,9 +509,12 @@ export class Ellipsoid implements Clipper { * @param result optional preallocated result */ public radiansPairToEquatorialEllipsoid( - thetaARadians: number, phiARadians: number, - thetaBRadians: number, phiBRadians: number, - result?: Ellipsoid): Ellipsoid | undefined { + thetaARadians: number, + phiARadians: number, + thetaBRadians: number, + phiBRadians: number, + result?: Ellipsoid, + ): Ellipsoid | undefined { SphereImplicit.radiansToUnitSphereXYZ(thetaARadians, phiARadians, this._unitVectorA); SphereImplicit.radiansToUnitSphereXYZ(thetaBRadians, phiBRadians, this._unitVectorB); @@ -515,8 +557,10 @@ export class Ellipsoid implements Clipper { return undefined; const cosPhi = latitude.cos(); const sinPhi = latitude.sin(); - const vector0 = this._transform.matrix.columnX(); vector0.scaleInPlace(cosPhi); - const vector90 = this._transform.matrix.columnY(); vector90.scaleInPlace(cosPhi); + const vector0 = this._transform.matrix.columnX(); + vector0.scaleInPlace(cosPhi); + const vector90 = this._transform.matrix.columnY(); + vector90.scaleInPlace(cosPhi); const center = this._transform.multiplyXYZ(0, 0, sinPhi); return Arc3d.create(center, vector0, vector90, longitudeSweep, result); } @@ -530,7 +574,8 @@ export class Ellipsoid implements Clipper { public sectionArcWithIntermediateNormal( angleA: LongitudeLatitudeNumber, intermediateNormalFraction: number, - angleB: LongitudeLatitudeNumber): Arc3d { + angleB: LongitudeLatitudeNumber, + ): Arc3d { const normalA = this.radiansToUnitNormalRay(angleA.longitudeRadians, angleA.latitudeRadians)!; const normalB = this.radiansToUnitNormalRay(angleB.longitudeRadians, angleB.latitudeRadians)!; const normal = normalA.direction.interpolate(intermediateNormalFraction, normalB.direction); @@ -549,7 +594,12 @@ export class Ellipsoid implements Clipper { * * If false, omit he cos(phi) factor on the derivative wrt theta. This ensures it is always nonzero and can be safely used in cross product for surface normal. * @param result optional plane result */ - public radiansToPointAndDerivatives(thetaRadians: number, phiRadians: number, applyCosPhiFactor = true, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { + public radiansToPointAndDerivatives( + thetaRadians: number, + phiRadians: number, + applyCosPhiFactor = true, + result?: Plane3dByOriginAndVectors, + ): Plane3dByOriginAndVectors { const cosTheta = Math.cos(thetaRadians); const sinTheta = Math.sin(thetaRadians); const cosPhi = Math.cos(phiRadians); @@ -560,7 +610,8 @@ export class Ellipsoid implements Clipper { return Plane3dByOriginAndVectors.createCapture( this._transform.multiplyXYZ(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi), matrix.multiplyXYZ(-sinTheta * cosPhiA, cosTheta * cosPhiA, 0), - matrix.multiplyXYZ(-sinPhi * cosTheta, -sinPhi * sinTheta, cosPhi)); + matrix.multiplyXYZ(-sinPhi * cosTheta, -sinPhi * sinTheta, cosPhi), + ); // in place modification requires direct reference to members of the result ... this._transform.multiplyXYZ(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi, result.origin); matrix.multiplyXYZ(-sinTheta * cosPhiA, cosTheta * cosPhiA, 0, result.vectorU); @@ -580,13 +631,16 @@ export class Ellipsoid implements Clipper { * @param d2ThetaPhi (returned) second derivative wrt theta and phi * @param result optional plane result */ - public radiansToPointAnd2Derivatives(thetaRadians: number, phiRadians: number, + public radiansToPointAnd2Derivatives( + thetaRadians: number, + phiRadians: number, point: Point3d, d1Theta: Vector3d, d1Phi: Vector3d, d2ThetaTheta: Vector3d, d2PhiPhi: Vector3d, - d2ThetaPhi: Vector3d) { + d2ThetaPhi: Vector3d, + ) { const cosTheta = Math.cos(thetaRadians); const sinTheta = Math.sin(thetaRadians); const cosPhi = Math.cos(phiRadians); @@ -611,7 +665,6 @@ export class Ellipsoid implements Clipper { * @param thetaRadians longitude, in radians * @param phiRadians latitude, in radians * @param result optional transform result - * */ public radiansToFrenetFrame(thetaRadians: number, phiRadians: number, result?: Transform): Transform | undefined { const plane = this.radiansToPointAndDerivatives(thetaRadians, phiRadians, false); @@ -622,7 +675,6 @@ export class Ellipsoid implements Clipper { * @param thetaRadians longitude, in radians * @param phiRadians latitude, in radians * @param result optional transform result - * */ public radiansToUnitNormalRay(thetaRadians: number, phiRadians: number, result?: Ray3d): Ray3d | undefined { const plane = this.radiansToPointAndDerivatives(thetaRadians, phiRadians, false); @@ -648,7 +700,11 @@ export class Ellipsoid implements Clipper { * * If `other` is undefined, default to unit sphere. * * Find the angles for the same normal on `this` ellipsoid */ - public otherEllipsoidAnglesToThisEllipsoidAngles(otherEllipsoid: Ellipsoid | undefined, otherAngles: LongitudeLatitudeNumber, result?: LongitudeLatitudeNumber): LongitudeLatitudeNumber | undefined { + public otherEllipsoidAnglesToThisEllipsoidAngles( + otherEllipsoid: Ellipsoid | undefined, + otherAngles: LongitudeLatitudeNumber, + result?: LongitudeLatitudeNumber, + ): LongitudeLatitudeNumber | undefined { const normal = Ellipsoid.radiansToUnitNormalRay(otherEllipsoid, otherAngles.longitudeRadians, otherAngles.latitudeRadians); if (normal !== undefined) return this.surfaceNormalToAngles(normal.direction, result); @@ -658,7 +714,12 @@ export class Ellipsoid implements Clipper { * * if ellipsoid is given, return its surface point and unit normal as a Ray3d. * * if not given, return surface point and unit normal for unit sphere. */ - public static radiansToUnitNormalRay(ellipsoid: Ellipsoid | undefined, thetaRadians: number, phiRadians: number, result?: Ray3d): Ray3d | undefined { + public static radiansToUnitNormalRay( + ellipsoid: Ellipsoid | undefined, + thetaRadians: number, + phiRadians: number, + result?: Ray3d, + ): Ray3d | undefined { if (ellipsoid) { return ellipsoid.radiansToUnitNormalRay(thetaRadians, phiRadians, result); } @@ -718,9 +779,11 @@ export class Ellipsoid implements Clipper { public announceClippedArcIntervals(arc: Arc3d, announce?: AnnounceNumberNumberCurvePrimitive): boolean { const arcData = arc.toVectors(); let numAnnounce = 0; - if (this._transform.multiplyInversePoint3d(arcData.center, arcData.center) + if ( + this._transform.multiplyInversePoint3d(arcData.center, arcData.center) && this._transform.matrix.multiplyInverse(arcData.vector0, arcData.vector0) - && this._transform.matrix.multiplyInverse(arcData.vector90, arcData.vector90)) { + && this._transform.matrix.multiplyInverse(arcData.vector90, arcData.vector90) + ) { // in local coordinates the arc parameterization is X = center + vector0 * cos(theta) + vector90 * sin(theta) // We want X DOT X === 1, viz // center DOT center + 2 * cos(theta) * center DOT vector0 + 2 * sin(theta) * center DOT vector90 + cos(theta) ^2 * vector0 DOT vector0 + sin (theta)^2 * vector90 DOT vector90 = 1 @@ -732,10 +795,17 @@ export class Ellipsoid implements Clipper { const vv = Vector3d.dotProductAsXYAndZ(arcData.vector90, arcData.vector90); const intersectionRadians: number[] = []; - if (TrigPolynomial.solveUnitCircleImplicitQuadricIntersection( - uu, 2.0 * uv, vv, - 2.0 * cu, 2.0 * cv, cc - 1.0, - intersectionRadians)) { + if ( + TrigPolynomial.solveUnitCircleImplicitQuadricIntersection( + uu, + 2.0 * uv, + vv, + 2.0 * cu, + 2.0 * cv, + cc - 1.0, + intersectionRadians, + ) + ) { const fractions = [0.0, 1.0]; for (const radians of intersectionRadians) { const fraction = arc.sweep.radiansToSignedPeriodicFraction(radians); @@ -795,24 +865,39 @@ export class EllipsoidPatch implements UVSurface { } /** Return the point on the ellipsoid at fractional positions in the angular ranges. */ public uvFractionToPoint(longitudeFraction: number, latitudeFraction: number, result?: Point3d): Point3d { - return this.ellipsoid.radiansToPoint(this.longitudeSweep.fractionToRadians(longitudeFraction), this.latitudeSweep.fractionToRadians(latitudeFraction), result); + return this.ellipsoid.radiansToPoint( + this.longitudeSweep.fractionToRadians(longitudeFraction), + this.latitudeSweep.fractionToRadians(latitudeFraction), + result, + ); } /** Return the point and derivative vectors on the ellipsoid at fractional positions in the angular ranges. * * Derivatives are with respect to fractional position. */ - public uvFractionToPointAndTangents(longitudeFraction: number, latitudeFraction: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { + public uvFractionToPointAndTangents( + longitudeFraction: number, + latitudeFraction: number, + result?: Plane3dByOriginAndVectors, + ): Plane3dByOriginAndVectors { result = this.ellipsoid.radiansToPointAndDerivatives( this.longitudeSweep.fractionToRadians(longitudeFraction), this.latitudeSweep.fractionToRadians(latitudeFraction), true, - result); + result, + ); result.vectorU.scale(this.longitudeSweep.sweepRadians); result.vectorV.scale(this.latitudeSweep.sweepRadians); return result; } /** Return the range of the patch, considering both boundary and internal extrema. */ public range(result?: Range3d): Range3d { - return this.ellipsoid.patchRangeStartEndRadians(this.longitudeSweep.startRadians, this.longitudeSweep.endRadians, this.latitudeSweep.startRadians, this.latitudeSweep.endRadians, result); + return this.ellipsoid.patchRangeStartEndRadians( + this.longitudeSweep.startRadians, + this.longitudeSweep.endRadians, + this.latitudeSweep.startRadians, + this.latitudeSweep.endRadians, + result, + ); } /** Return intersections of the ray and surface. * * uv values in the intersections are in radians unless `convertIntersectionRadiansToFractions` is true requesting conversion to patch fractions. @@ -827,19 +912,27 @@ export class EllipsoidPatch implements UVSurface { const longitudeRadians = thetaPhi[i].longitudeRadians; const latitudeRadians = thetaPhi[i].latitudeRadians; - if (!restrictToPatch + if ( + !restrictToPatch || (this.longitudeSweep.isRadiansInSweep(longitudeRadians) - && this.latitudeSweep.isRadiansInSweep(latitudeRadians))) { + && this.latitudeSweep.isRadiansInSweep(latitudeRadians)) + ) { if (convertIntersectionRadiansToFractions) { const uFraction = this.longitudeSweep.radiansToSignedPeriodicFraction(longitudeRadians); const vFraction = this.latitudeSweep.radiansToSignedPeriodicFraction(latitudeRadians); - result.push(new CurveAndSurfaceLocationDetail( - CurveLocationDetail.createRayFractionPoint(ray, rayFractions[i], xyz[i]), - UVSurfaceLocationDetail.createSurfaceUVNumbersPoint(this, uFraction, vFraction, xyz[i]))); + result.push( + new CurveAndSurfaceLocationDetail( + CurveLocationDetail.createRayFractionPoint(ray, rayFractions[i], xyz[i]), + UVSurfaceLocationDetail.createSurfaceUVNumbersPoint(this, uFraction, vFraction, xyz[i]), + ), + ); } else { - result.push(new CurveAndSurfaceLocationDetail( - CurveLocationDetail.createRayFractionPoint(ray, rayFractions[i], xyz[i]), - UVSurfaceLocationDetail.createSurfaceUVNumbersPoint(this, longitudeRadians, latitudeRadians, xyz[i]))); + result.push( + new CurveAndSurfaceLocationDetail( + CurveLocationDetail.createRayFractionPoint(ray, rayFractions[i], xyz[i]), + UVSurfaceLocationDetail.createSurfaceUVNumbersPoint(this, longitudeRadians, latitudeRadians, xyz[i]), + ), + ); } } } @@ -863,7 +956,6 @@ export class EllipsoidPatch implements UVSurface { * * ray.origin is the point at requested altitude. * * ray.direction is an outward-directed unit vector * @param position longitude, latitude, and height - * */ public anglesToUnitNormalRay(position: LongitudeLatitudeNumber, result?: Ray3d): Ray3d | undefined { const ray = this.ellipsoid.radiansToUnitNormalRay(position.longitudeRadians, position.latitudeRadians, result); @@ -879,8 +971,18 @@ export class EllipsoidPatch implements UVSurface { * @param h optional altitude * @param result optional preallocated result. */ - public uvFractionToAngles(longitudeFraction: number, phiFraction: number, h: number = 0, result?: LongitudeLatitudeNumber): LongitudeLatitudeNumber { - return LongitudeLatitudeNumber.createRadians(this.longitudeSweep.fractionToRadians(longitudeFraction), this.latitudeSweep.fractionToRadians(phiFraction), h, result); + public uvFractionToAngles( + longitudeFraction: number, + phiFraction: number, + h: number = 0, + result?: LongitudeLatitudeNumber, + ): LongitudeLatitudeNumber { + return LongitudeLatitudeNumber.createRadians( + this.longitudeSweep.fractionToRadians(longitudeFraction), + this.latitudeSweep.fractionToRadians(phiFraction), + h, + result, + ); } /** Find the closest point of the (patch of the) ellipsoid. */ public projectPointToSurface(spacePoint: Point3d): LongitudeLatitudeNumber | undefined { @@ -928,20 +1030,32 @@ class EllipsoidClosestPoint extends NewtonEvaluatorRRtoRRD { return LongitudeLatitudeNumber.createRadians(uv.thetaRadians, uv.phiRadians, 0.0); } public evaluate(thetaRadians: number, phiRadians: number): boolean { - this._ellipsoid.radiansToPointAnd2Derivatives(thetaRadians, phiRadians, + this._ellipsoid.radiansToPointAnd2Derivatives( + thetaRadians, + phiRadians, this._surfacePoint, - this._d1Theta, this._d1Phi, - this._d2Theta, this._d2Phi, - this._d2ThetaPhi); + this._d1Theta, + this._d1Phi, + this._d2Theta, + this._d2Phi, + this._d2ThetaPhi, + ); Vector3d.createStartEnd(this._spacePoint, this._surfacePoint, this._delta); const q = this._d1Theta.dotProduct(this._d1Phi) + this._delta.dotProduct(this._d2ThetaPhi); this.currentF.setOriginAndVectorsXYZ( // f,g,0 - this._delta.dotProduct(this._d1Theta), this._delta.dotProduct(this._d1Phi), 0, + this._delta.dotProduct(this._d1Theta), + this._delta.dotProduct(this._d1Phi), + 0, // df/dTheta, dg/dTheta, 0 - this._d1Theta.dotProduct(this._d1Theta) + this._delta.dotProduct(this._d2Theta), q, 0, + this._d1Theta.dotProduct(this._d1Theta) + this._delta.dotProduct(this._d2Theta), + q, + 0, // df/dPhi, dg/dPhi, 0 - q, this._d1Phi.dotProduct(this._d1Phi) + this._delta.dotProduct(this._d2Phi), 0); + q, + this._d1Phi.dotProduct(this._d1Phi) + this._delta.dotProduct(this._d2Phi), + 0, + ); return true; } @@ -975,7 +1089,16 @@ export class GeodesicPathPoint { } /** Fill all evaluations at given theta and phi. */ public evaluateDerivativesAtCurrentAngles(ellipsoid: Ellipsoid) { - ellipsoid.radiansToPointAnd2Derivatives(this.thetaRadians, this.phiRadians, this.point, this.dTheta, this.dPhi, this.d2Theta, this.d2Phi, this.d2ThetaPhi); + ellipsoid.radiansToPointAnd2Derivatives( + this.thetaRadians, + this.phiRadians, + this.point, + this.dTheta, + this.dPhi, + this.d2Theta, + this.d2Phi, + this.d2ThetaPhi, + ); this.dTheta.crossProduct(this.dPhi, this.d1Cross); } private static _vectorAB?: Vector3d; @@ -999,8 +1122,8 @@ export class GeodesicPathPoint { values[0] = this._vectorCross.dotProduct(pointB.d1Cross); // Derivatives wrt phi at A, B, C creates derivatives of values[0] wrt each. // derivatives at neighbor appear only on their point-to-point vector, and with negative sign .. - values[1] = - pointA.dPhi.tripleProduct(this._vectorCB, pointB.d1Cross); - values[3] = - this._vectorAB.tripleProduct(pointC.dPhi, pointB.d1Cross); + values[1] = -pointA.dPhi.tripleProduct(this._vectorCB, pointB.d1Cross); + values[3] = -this._vectorAB.tripleProduct(pointC.dPhi, pointB.d1Cross); // values from pointB appear with positive sign everywhere . .. values[2] = pointB.dPhi.tripleProduct(this._vectorCB, pointB.d1Cross) + this._vectorAB.tripleProduct(pointB.dPhi, pointB.d1Cross) @@ -1029,19 +1152,30 @@ export class GeodesicPathSolver { this._defaultArc = defaultArc; } /** - * * @param originalEllipsoid Given start and endpoints on an ellipsoid, compute points along a near-optimal shortest path. * * The points are located so that at each point the local surface normal is contained in the plane of the point and its two neighbors. * @param startAngles angles for the start of the path * @param endAngles angles for the end of the path * @param density If this is a number, it is the requested edge count. If this is an angle, it ias an angular spacing measured in the great arc through the two points. */ - public static createGeodesicPath(originalEllipsoid: Ellipsoid, - startAngles: LongitudeLatitudeNumber, endAngles: LongitudeLatitudeNumber, density: number | Angle): GeodesicPathPoint[] | undefined { - const workEllipsoid1 = originalEllipsoid.radiansPairToEquatorialEllipsoid(startAngles.longitudeRadians, startAngles.latitudeRadians, - endAngles.longitudeRadians, endAngles.latitudeRadians); - const workArc = originalEllipsoid.radiansPairToGreatArc(startAngles.longitudeRadians, startAngles.latitudeRadians, - endAngles.longitudeRadians, endAngles.latitudeRadians); + public static createGeodesicPath( + originalEllipsoid: Ellipsoid, + startAngles: LongitudeLatitudeNumber, + endAngles: LongitudeLatitudeNumber, + density: number | Angle, + ): GeodesicPathPoint[] | undefined { + const workEllipsoid1 = originalEllipsoid.radiansPairToEquatorialEllipsoid( + startAngles.longitudeRadians, + startAngles.latitudeRadians, + endAngles.longitudeRadians, + endAngles.latitudeRadians, + ); + const workArc = originalEllipsoid.radiansPairToGreatArc( + startAngles.longitudeRadians, + startAngles.latitudeRadians, + endAngles.longitudeRadians, + endAngles.latitudeRadians, + ); if (workEllipsoid1 === undefined || workArc === undefined) return undefined; let numEdges = 4; @@ -1155,11 +1289,14 @@ export class GeodesicPathSolver { * @param normalInterpolationFraction0 * @param normalInterpolationFraction1 */ - public static approximateMinimumLengthSectionArc(ellipsoid: Ellipsoid, + public static approximateMinimumLengthSectionArc( + ellipsoid: Ellipsoid, angleA: LongitudeLatitudeNumber, - angleB: LongitudeLatitudeNumber, numSample: number, + angleB: LongitudeLatitudeNumber, + numSample: number, normalInterpolationFraction0: number, - normalInterpolationFraction1: number): { minLengthArc: Arc3d, minLengthNormalInterpolationFraction: number } | undefined { + normalInterpolationFraction1: number, + ): { minLengthArc: Arc3d, minLengthNormalInterpolationFraction: number } | undefined { numSample = Geometry.clampToStartEnd(numSample, 2, 200); const normalA = ellipsoid.radiansToUnitNormalRay(angleA.longitudeRadians, angleA.latitudeRadians); const normalB = ellipsoid.radiansToUnitNormalRay(angleB.longitudeRadians, angleB.latitudeRadians); @@ -1187,5 +1324,4 @@ export class GeodesicPathSolver { } return undefined; } - } diff --git a/core/geometry/src/geometry3d/FrameBuilder.ts b/core/geometry/src/geometry3d/FrameBuilder.ts index e521b813d3a8..a665a8cb40ad 100644 --- a/core/geometry/src/geometry3d/FrameBuilder.ts +++ b/core/geometry/src/geometry3d/FrameBuilder.ts @@ -53,7 +53,9 @@ export class FrameBuilder { private static _workPoint?: Point3d; // test if both vectors are defined and have significant angle between. private areStronglyIndependentVectors( - vector0: Vector3d, vector1: Vector3d, radiansTolerance: number = Geometry.smallAngleRadians, + vector0: Vector3d, + vector1: Vector3d, + radiansTolerance: number = Geometry.smallAngleRadians, ): boolean { if (vector0 !== undefined && vector1 !== undefined) { const q = vector0.smallerUnorientedRadiansTo(vector1); @@ -222,12 +224,13 @@ export class FrameBuilder { } } } else if (data instanceof CurveCollection) { - if (data.children) + if (data.children) { for (const child of data.children) { this.announce(child); if (this.savedVectorCount() > 1) break; } + } } else if (data instanceof GrowableXYZArray) { const point = Point3d.create(); for (let i = 0; this.savedVectorCount() < 2; i++) { @@ -328,7 +331,7 @@ export class FrameBuilder { */ public static createFrameWithCCWPolygon(points: Point3d[], result?: Transform): Transform | undefined { if (points.length > 2) { - const ray = PolygonOps.centroidAreaNormal(points); // can't pass pre-allocated ray... + const ray = PolygonOps.centroidAreaNormal(points); // can't pass pre-allocated ray... if (ray) return ray.toRigidZFrame(result); } diff --git a/core/geometry/src/geometry3d/FrustumAnimation.ts b/core/geometry/src/geometry3d/FrustumAnimation.ts index c01b739c39cc..73a232f1ec84 100644 --- a/core/geometry/src/geometry3d/FrustumAnimation.ts +++ b/core/geometry/src/geometry3d/FrustumAnimation.ts @@ -43,9 +43,13 @@ export class SmoothTransformBetweenFrusta { private _localToWorldA: Transform; private _localToWorldB: Transform; /** (property accessor) rigid frame at start of motion */ - public get localToWorldA(): Transform { return this._localToWorldA; } + public get localToWorldA(): Transform { + return this._localToWorldA; + } /** (property accessor) rigid frame at end of motion */ - public get localToWorldB(): Transform { return this._localToWorldB; } + public get localToWorldB(): Transform { + return this._localToWorldB; + } private _rotationAxis: Vector3d; private _rotationAngle: Angle; @@ -58,7 +62,14 @@ export class SmoothTransformBetweenFrusta { * @param rotationAxis * @param rotationAngle */ - private constructor(localToWorldA: Transform, localCornerA: Point3d[], localToWorldB: Transform, localCornerB: Point3d[], rotationAxis: Vector3d, rotationAngle: Angle) { + private constructor( + localToWorldA: Transform, + localCornerA: Point3d[], + localToWorldB: Transform, + localCornerB: Point3d[], + rotationAxis: Vector3d, + rotationAngle: Angle, + ) { this._localCornerA = localCornerA; this._localCornerB = localCornerB; this._localToWorldA = localToWorldA; @@ -97,13 +108,11 @@ export class SmoothTransformBetweenFrusta { const rigidB1 = Transform.createOriginAndMatrix(spinCenter, rigidB.matrix); const localCornerA1 = rigidA1.multiplyInversePoint3dArray(cornerA)!; const localCornerB1 = rigidB1.multiplyInversePoint3dArray(cornerB)!; - return new SmoothTransformBetweenFrusta(rigidA1, localCornerA1, rigidB1, localCornerB1, - spinAxis.axis, spinAxis.angle); + return new SmoothTransformBetweenFrusta(rigidA1, localCornerA1, rigidB1, localCornerB1, spinAxis.axis, spinAxis.angle); } } } - return new SmoothTransformBetweenFrusta(rigidA, localCornerA, rigidB, localCornerB, - spinAxis.axis, spinAxis.angle); + return new SmoothTransformBetweenFrusta(rigidA, localCornerA, rigidB, localCornerB, spinAxis.axis, spinAxis.angle); } return undefined; } @@ -124,8 +133,7 @@ export class SmoothTransformBetweenFrusta { */ public fractionToWorldCorners(fraction: number, result?: Point3d[]): Point3d[] { const corners = this.interpolateLocalCorners(fraction, result); - const fractionalRotation = Matrix3d.createRotationAroundVector(this._rotationAxis, - this._rotationAngle.cloneScaled(fraction))!; + const fractionalRotation = Matrix3d.createRotationAroundVector(this._rotationAxis, this._rotationAngle.cloneScaled(fraction))!; const axes0 = this._localToWorldA.matrix; const fractionalAxes = fractionalRotation.multiplyMatrixMatrix(axes0); const fractionalOrigin = this._localToWorldA.getOrigin().interpolate(fraction, this._localToWorldB.origin); diff --git a/core/geometry/src/geometry3d/GeometryHandler.ts b/core/geometry/src/geometry3d/GeometryHandler.ts index 5ef85298fe97..8466f22858ed 100644 --- a/core/geometry/src/geometry3d/GeometryHandler.ts +++ b/core/geometry/src/geometry3d/GeometryHandler.ts @@ -56,7 +56,7 @@ export abstract class GeometryHandler { /** Handle strongly typed [[Arc3d]] */ public abstract handleArc3d(g: Arc3d): any; /** Handle strongly typed [[CurveCollection]] */ - public handleCurveCollection(_g: CurveCollection): any { } + public handleCurveCollection(_g: CurveCollection): any {} /** Handle strongly typed [[BSplineCurve3d]] */ public abstract handleBSplineCurve3d(g: BSplineCurve3d): any; /** Handle strongly typed [[InterpolationCurve3d]] */ @@ -98,7 +98,7 @@ export abstract class GeometryHandler { /** Handle strongly typed [[CurveChainWithDistanceIndex]] (base class method calls [[handlePath]] or [[handleLoop]]) */ public handleCurveChainWithDistanceIndex(g: CurveChainWithDistanceIndex): any { return this.handlePath(g.path); - } + } /** Handle strongly typed Sphere */ public abstract handleSphere(g: Sphere): any; /** Handle strongly typed Cone */ @@ -307,10 +307,11 @@ export class RecurseToCurvesGeometryHandler extends GeometryHandler { /** Invoke `child.dispatchToGeometryHandler(this)` for each child in the array returned by the query `g.children` */ public handleChildren(g: GeometryQuery): any { const children = g.children; - if (children) + if (children) { for (const child of children) { child.dispatchToGeometryHandler(this); } + } } /** Recurse to children */ public override handleCurveCollection(g: CurveCollection): any { @@ -398,18 +399,26 @@ export interface IStrokeHandler { * * Note that this method is permitted (expected) to provide pre-stroked data if available. * * In th pre-stroked case, the cp passed to the handler will be the stroked image, not the original. * * Callers that want summary data should implement (and return true from) needPrimaryDataForStrokes - */ + */ announceIntervalForUniformStepStrokes( - cp: CurvePrimitive, numStrokes: number, fraction0: number, fraction1: number, + cp: CurvePrimitive, + numStrokes: number, + fraction0: number, + fraction1: number, ): void; /** * OPTIONAL method for a handler to indicate that it wants primary geometry (e.g. spirals) rather than strokes. * @returns true if primary geometry should be passed (rather than stroked or otherwise simplified) - */ + */ needPrimaryGeometryForStrokes?(): boolean; /** Announce numPoints interpolated between point0 and point1, with associated fractions */ announceSegmentInterval( - cp: CurvePrimitive, point0: Point3d, point1: Point3d, numStrokes: number, fraction0: number, fraction1: number, + cp: CurvePrimitive, + point0: Point3d, + point1: Point3d, + numStrokes: number, + fraction0: number, + fraction1: number, ): void; /** Announce that all data about `cp` has been announced. */ endCurvePrimitive(cp: CurvePrimitive): void; @@ -457,7 +466,9 @@ export interface UVSurface { * @param result optional pre-allocated carrier for point and vectors */ uvFractionToPointAndTangents( - uFraction: number, vFraction: number, result?: Plane3dByOriginAndVectors, + uFraction: number, + vFraction: number, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors; } /** diff --git a/core/geometry/src/geometry3d/GrowableBlockedArray.ts b/core/geometry/src/geometry3d/GrowableBlockedArray.ts index 38a354ece73a..920ddbe83621 100644 --- a/core/geometry/src/geometry3d/GrowableBlockedArray.ts +++ b/core/geometry/src/geometry3d/GrowableBlockedArray.ts @@ -21,7 +21,7 @@ export class GrowableBlockedArray { /** number of numbers per block in the array. * * If viewing the array as a two dimensional array, this is the row size. */ - protected _blockSize: number; // positive integer !!! + protected _blockSize: number; // positive integer !!! /** * multiplier used by ensureBlockCapacity to expand requested reallocation size */ @@ -48,13 +48,13 @@ export class GrowableBlockedArray { * @param destOffset copy to instance array starting at this block index; zero if undefined * @return count and offset of blocks copied */ - protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): {count: number, offset: number} { + protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): { count: number, offset: number } { // validate inputs and convert from blocks to entries let myOffset = (undefined !== destOffset) ? destOffset * this.numPerBlock : 0; if (myOffset < 0) myOffset = 0; if (myOffset >= this._data.length) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; let myCount = (undefined !== sourceCount) ? sourceCount * this.numPerBlock : source.length; if (myCount > 0) { if (myCount > source.length) @@ -65,14 +65,14 @@ export class GrowableBlockedArray { myCount -= myCount % this.numPerBlock; } if (myCount <= 0) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; if (myCount === source.length) this._data.set(source, myOffset); else if (source instanceof Float64Array) this._data.set(source.subarray(0, myCount), myOffset); else this._data.set(source.slice(0, myCount), myOffset); - return {count: myCount / this.numPerBlock, offset: myOffset / this.numPerBlock}; + return { count: myCount / this.numPerBlock, offset: myOffset / this.numPerBlock }; } /** @@ -87,11 +87,17 @@ export class GrowableBlockedArray { } /** computed property: length (in blocks, not doubles) */ - public get length(): number { return this._inUse; } + public get length(): number { + return this._inUse; + } /** computed property: length (in blocks, not doubles) */ - public get numBlocks(): number { return this._inUse; } + public get numBlocks(): number { + return this._inUse; + } /** property: number of data values per block */ - public get numPerBlock(): number { return this._blockSize; } + public get numPerBlock(): number { + return this._blockSize; + } /** * Return a single value indexed within a block. Indices are unchecked. * @param blockIndex index of block to read @@ -101,7 +107,9 @@ export class GrowableBlockedArray { return this._data[blockIndex * this._blockSize + indexWithinBlock]; } /** clear the block count to zero, but maintain the allocated memory */ - public clear() { this._inUse = 0; } + public clear() { + this._inUse = 0; + } /** Return the capacity in blocks (not doubles) */ public blockCapacity() { return this._data.length / this._blockSize; @@ -114,7 +122,7 @@ export class GrowableBlockedArray { const prevData = this._data; this._data = new Float64Array(blockCapacity * this._blockSize); this.copyData(prevData, this._inUse); - } + } } /** Add a new block of data. * * If newData has fewer than numPerBlock entries, the remaining part of the new block is zeros. @@ -150,7 +158,9 @@ export class GrowableBlockedArray { this._inUse--; } /** convert a block index to the simple index to the underlying Float64Array. */ - protected blockIndexToDoubleIndex(blockIndex: number) { return this._blockSize * blockIndex; } + protected blockIndexToDoubleIndex(blockIndex: number) { + return this._blockSize * blockIndex; + } /** Access a single double at offset within a block, with index checking and return undefined if indexing is invalid. */ public checkedComponent(blockIndex: number, componentIndex: number): number | undefined { if (blockIndex >= this._inUse || blockIndex < 0 || componentIndex < 0 || componentIndex >= this._blockSize) @@ -179,18 +189,21 @@ export class GrowableBlockedArray { return ia - ib; // so original order is maintained among duplicates !!!! } /** Return an array of block indices sorted per compareLexicalBlock function */ - public sortIndicesLexical(compareBlocks: BlockComparisonFunction = (dataArray, size, iA, iB) => GrowableBlockedArray.compareLexicalBlock(dataArray, size, iA, iB)): Uint32Array { + public sortIndicesLexical( + compareBlocks: BlockComparisonFunction = (dataArray, size, iA, iB) => GrowableBlockedArray.compareLexicalBlock(dataArray, size, iA, iB), + ): Uint32Array { const n = this._inUse; // let numCompare = 0; const result = new Uint32Array(n); const data = this._data; const blockSize = this._blockSize; - for (let i = 0; i < n; i++)result[i] = i; + for (let i = 0; i < n; i++) result[i] = i; result.sort( (blockIndexA: number, blockIndexB: number) => { // numCompare++; return compareBlocks(data, blockSize, blockIndexA * blockSize, blockIndexB * blockSize); - }); + }, + ); // console.log (n, numCompare); return result; } diff --git a/core/geometry/src/geometry3d/GrowableFloat64Array.ts b/core/geometry/src/geometry3d/GrowableFloat64Array.ts index babb547d660e..f118a570255a 100644 --- a/core/geometry/src/geometry3d/GrowableFloat64Array.ts +++ b/core/geometry/src/geometry3d/GrowableFloat64Array.ts @@ -47,12 +47,12 @@ export class GrowableFloat64Array { * @param destOffset copy to instance array starting at this index; zero if undefined * @return count and offset of entries copied */ - protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): {count: number, offset: number} { + protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): { count: number, offset: number } { let myOffset = destOffset ?? 0; if (myOffset < 0) myOffset = 0; if (myOffset >= this._data.length) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; let myCount = sourceCount ?? source.length; if (myCount > 0) { if (myCount > source.length) @@ -61,14 +61,14 @@ export class GrowableFloat64Array { myCount = this._data.length - myOffset; } if (myCount <= 0) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; if (myCount === source.length) this._data.set(source, myOffset); else if (source instanceof Float64Array) this._data.set(source.subarray(0, myCount), myOffset); else this._data.set(source.slice(0, myCount), myOffset); - return {count: myCount, offset: myOffset}; + return { count: myCount, offset: myOffset }; } /** @@ -290,5 +290,4 @@ export class GrowableFloat64Array { } this._inUse = numAccepted; } - } diff --git a/core/geometry/src/geometry3d/GrowableXYArray.ts b/core/geometry/src/geometry3d/GrowableXYArray.ts index d1eca5aeb320..0aff08e6caf9 100644 --- a/core/geometry/src/geometry3d/GrowableXYArray.ts +++ b/core/geometry/src/geometry3d/GrowableXYArray.ts @@ -45,7 +45,7 @@ export class GrowableXYArray extends IndexedXYCollection { */ public constructor(numPoints: number = 8, growthFactor?: number) { super(); - this._data = new Float64Array(numPoints * 2); // 2 values per point + this._data = new Float64Array(numPoints * 2); // 2 values per point this._xyInUse = 0; this._xyCapacity = numPoints; this._growthFactor = (undefined !== growthFactor && growthFactor >= 1.0) ? growthFactor : 1.5; @@ -57,13 +57,13 @@ export class GrowableXYArray extends IndexedXYCollection { * @param destOffset copy to instance array starting at this point index; zero if undefined * @return count and offset of points copied */ - protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): {count: number, offset: number} { + protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): { count: number, offset: number } { // validate inputs and convert from points to entries let myOffset = (undefined !== destOffset) ? destOffset * 2 : 0; if (myOffset < 0) myOffset = 0; if (myOffset >= this._data.length) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; let myCount = (undefined !== sourceCount) ? sourceCount * 2 : source.length; if (myCount > 0) { if (myCount > source.length) @@ -74,26 +74,34 @@ export class GrowableXYArray extends IndexedXYCollection { myCount -= myCount % 2; } if (myCount <= 0) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; if (myCount === source.length) this._data.set(source, myOffset); else if (source instanceof Float64Array) this._data.set(source.subarray(0, myCount), myOffset); else this._data.set(source.slice(0, myCount), myOffset); - return {count: myCount / 2, offset: myOffset / 2}; + return { count: myCount / 2, offset: myOffset / 2 }; } /** The number of points in use. When the length is increased, the array is padded with zeroes. */ - public override get length() { return this._xyInUse; } - public set length(newLength: number) { this.resize(newLength, true); } + public override get length() { + return this._xyInUse; + } + public set length(newLength: number) { + this.resize(newLength, true); + } /** Return the number of float64 in use. */ - public get float64Length() { return this._xyInUse * 2; } + public get float64Length() { + return this._xyInUse * 2; + } /** Return the raw packed data. * * Note that the length of the returned Float64Array is a count of doubles, and includes the excess capacity */ - public float64Data(): Float64Array { return this._data; } + public float64Data(): Float64Array { + return this._data; + } /** If necessary, increase the capacity to a new pointCount. Current coordinates and point count (length) are unchanged. */ public ensureCapacity(pointCapacity: number, applyGrowthFactor: boolean = true) { @@ -112,7 +120,7 @@ export class GrowableXYArray extends IndexedXYCollection { * @param pointCount new number of active points in array * @param padWithZero when increasing point count, whether to zero out new points (default false) */ - public resize(pointCount: number, padWithZero?: boolean) { + public resize(pointCount: number, padWithZero?: boolean) { if (pointCount >= 0 && pointCount < this._xyInUse) this._xyInUse = pointCount; else if (pointCount > this._xyInUse) { @@ -377,7 +385,8 @@ export class GrowableXYArray extends IndexedXYCollection { j = 2 * j; this.pushXY( fraction0 * data[i] + fraction * data[j], - fraction0 * data[i + 1] + fraction * data[j + 1]); + fraction0 * data[i + 1] + fraction * data[j + 1], + ); } } @@ -455,7 +464,7 @@ export class GrowableXYArray extends IndexedXYCollection { * Set the coordinates of a single point given as coordinates. * @deprecated in 3.x. Use setXYAtCheckedPointIndex instead */ - public setXYZAtCheckedPointIndex(pointIndex: number, x: number, y: number): boolean { + public setXYZAtCheckedPointIndex(pointIndex: number, x: number, y: number): boolean { return this.setXYAtCheckedPointIndex(pointIndex, x, y); } @@ -479,10 +488,14 @@ export class GrowableXYArray extends IndexedXYCollection { for (let i0 = 0, i1 = n - 1; i0 < i1; i0++, i1--) { j0 = 2 * i0; j1 = 2 * i1; - a = data[j0]; data[j0] = data[j1]; data[j1] = a; + a = data[j0]; + data[j0] = data[j1]; + data[j1] = a; j0++; j1++; - a = data[j0]; data[j0] = data[j1]; data[j1] = a; + a = data[j0]; + data[j0] = data[j1]; + data[j1] = a; } } @@ -551,17 +564,18 @@ export class GrowableXYArray extends IndexedXYCollection { } else { for (let i = 0; i + 1 < numDouble; i += 2) rangeToExtend.extendXY(data[i], data[i + 1]); - } } /** sum the lengths of segments between points. */ public sumLengths(): number { let sum = 0.0; - const n = 2 * (this._xyInUse - 1); // Length already takes into account what specifically is in use + const n = 2 * (this._xyInUse - 1); // Length already takes into account what specifically is in use const data = this._data; - for (let i = 0; i < n; i += 2) sum += Geometry.hypotenuseXY( - data[i + 2] - data[i], - data[i + 3] - data[i + 1]); + for (let i = 0; i < n; i += 2) + sum += Geometry.hypotenuseXY( + data[i + 2] - data[i], + data[i + 3] - data[i + 1], + ); return sum; } /** @@ -584,7 +598,9 @@ export class GrowableXYArray extends IndexedXYCollection { j = 2 * j; return Point2d.create( fraction0 * data[i] + fraction * data[j], - fraction0 * data[i + 1] + fraction * data[j + 1], result); + fraction0 * data[i + 1] + fraction * data[j + 1], + result, + ); } return undefined; } @@ -592,7 +608,7 @@ export class GrowableXYArray extends IndexedXYCollection { /** Sum the signed areas of the projection to xy plane */ public areaXY(): number { let area = 0.0; - const n = 2 * this._xyInUse; // float count !! + const n = 2 * this._xyInUse; // float count !! if (n > 4) { const x0 = this._data[n - 2]; const y0 = this._data[n - 1]; @@ -626,7 +642,9 @@ export class GrowableXYArray extends IndexedXYCollection { j = 2 * j; return Vector2d.create( data[j] - origin.x, - data[j + 1] - origin.y, result); + data[j + 1] - origin.y, + result, + ); } return undefined; } @@ -639,8 +657,11 @@ export class GrowableXYArray extends IndexedXYCollection { const k = targetBIndex * 2; const data = this._data; return Geometry.crossProductXYXY( - data[j] - data[i], data[j + 1] - data[i + 1], - data[k] - data[i], data[k + 1] - data[i + 1]); + data[j] - data[i], + data[j + 1] - data[i + 1], + data[k] - data[i], + data[k + 1] - data[i + 1], + ); } return undefined; } @@ -652,8 +673,11 @@ export class GrowableXYArray extends IndexedXYCollection { const k = targetBIndex * 2; const data = this._data; return Geometry.crossProductXYXY( - data[j] - origin.x, data[j + 1] - origin.y, - data[k] - origin.x, data[k + 1] - origin.y); + data[j] - origin.x, + data[j + 1] - origin.y, + data[k] - origin.x, + data[k + 1] - origin.y, + ); } return undefined; } @@ -665,7 +689,8 @@ export class GrowableXYArray extends IndexedXYCollection { const j0 = 2 * j; return Geometry.hypotenuseXY( this._data[j0] - this._data[i0], - this._data[j0 + 1] - this._data[i0 + 1]); + this._data[j0 + 1] - this._data[i0 + 1], + ); } return undefined; } @@ -675,7 +700,8 @@ export class GrowableXYArray extends IndexedXYCollection { const i0 = 2 * i; return Geometry.hypotenuseXY( spacePoint.x - this._data[i0], - spacePoint.y - this._data[i0 + 1]); + spacePoint.y - this._data[i0 + 1], + ); } return undefined; } @@ -703,7 +729,8 @@ export class GrowableXYArray extends IndexedXYCollection { (blockIndexA: number, blockIndexB: number) => { // numCompare++; return this.compareLexicalBlock(blockIndexA, blockIndexB); - }); + }, + ); // console.log (n, numCompare); return result; } diff --git a/core/geometry/src/geometry3d/GrowableXYZArray.ts b/core/geometry/src/geometry3d/GrowableXYZArray.ts index 580e789540fa..4287cdaf20a7 100644 --- a/core/geometry/src/geometry3d/GrowableXYZArray.ts +++ b/core/geometry/src/geometry3d/GrowableXYZArray.ts @@ -46,7 +46,7 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { */ public constructor(numPoints: number = 8, growthFactor?: number) { super(); - this._data = new Float64Array(numPoints * 3); // 3 values per point + this._data = new Float64Array(numPoints * 3); // 3 values per point this._xyzInUse = 0; this._xyzCapacity = numPoints; this._growthFactor = (undefined !== growthFactor && growthFactor >= 1.0) ? growthFactor : 1.5; @@ -58,13 +58,13 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { * @param destOffset copy to instance array starting at this point index; zero if undefined * @return count and offset of points copied */ - protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): {count: number, offset: number} { + protected copyData(source: Float64Array | number[], sourceCount?: number, destOffset?: number): { count: number, offset: number } { // validate inputs and convert from points to entries let myOffset = (undefined !== destOffset) ? destOffset * 3 : 0; if (myOffset < 0) myOffset = 0; if (myOffset >= this._data.length) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; let myCount = (undefined !== sourceCount) ? sourceCount * 3 : source.length; if (myCount > 0) { if (myCount > source.length) @@ -75,26 +75,34 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { myCount -= myCount % 3; } if (myCount <= 0) - return {count: 0, offset: 0}; + return { count: 0, offset: 0 }; if (myCount === source.length) this._data.set(source, myOffset); else if (source instanceof Float64Array) this._data.set(source.subarray(0, myCount), myOffset); else this._data.set(source.slice(0, myCount), myOffset); - return {count: myCount / 3, offset: myOffset / 3}; + return { count: myCount / 3, offset: myOffset / 3 }; } /** The number of points in use. When the length is increased, the array is padded with zeroes. */ - public get length() { return this._xyzInUse; } - public set length(newLength: number) { this.resize(newLength, true); } + public get length() { + return this._xyzInUse; + } + public set length(newLength: number) { + this.resize(newLength, true); + } /** Return the number of float64 in use. */ - public get float64Length() { return this._xyzInUse * 3; } + public get float64Length() { + return this._xyzInUse * 3; + } /** Return the raw packed data. * * Note that the length of the returned Float64Array is a count of doubles, and includes the excess capacity */ - public float64Data(): Float64Array { return this._data; } + public float64Data(): Float64Array { + return this._data; + } /** If necessary, increase the capacity to the new number of points. Current coordinates and point count (length) are unchanged. */ public ensureCapacity(pointCapacity: number, applyGrowthFactor: boolean = true) { @@ -112,7 +120,7 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { * * If pointCount is greater than current length, reallocate to exactly pointCount, copy existing points, and optionally pad excess with zero. * @param pointCount new number of active points in array * @param padWithZero when increasing point count, whether to zero out new points (default false) - */ + */ public resize(pointCount: number, padWithZero?: boolean) { if (pointCount >= 0 && pointCount < this._xyzInUse) this._xyzInUse = pointCount; @@ -132,7 +140,7 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { result = new GrowableXYZArray(this.length); else { if (result.length !== this.length) - result.clear(); // force resize to trim excess capacity + result.clear(); // force resize to trim excess capacity result.resize(this.length); } result.copyData(this._data, this.length); @@ -249,7 +257,7 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { /** Shift all data forward to make space for numPoints at the front. * * Leading (3*numPoints) doubles are left with prior contents. * * _xyzInUse count is increased - */ + */ private shiftForward(numPoints: number) { if (numPoints <= 0) return; @@ -269,7 +277,6 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { this._data[2] = z; } /** prepend a new point at the front of the array. - * */ public pushFront(toPush: XYAndZ) { this.pushFrontXYZ(toPush.x, toPush.y, toPush.z); @@ -468,7 +475,7 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { result.push(Point3d.create(data[i], data[i + 1], data[i + 2])); return result; } - /** multiply each point by the transform, replace values. */ + /** multiply each point by the transform, replace values. */ public static multiplyTransformInPlace(transform: Transform, data: GrowableXYZArray[] | GrowableXYZArray) { if (Array.isArray(data)) { for (const d of data) @@ -509,13 +516,19 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { for (let i0 = 0, i1 = n - 1; i0 < i1; i0++, i1--) { j0 = 3 * i0; j1 = 3 * i1; - a = data[j0]; data[j0] = data[j1]; data[j1] = a; + a = data[j0]; + data[j0] = data[j1]; + data[j1] = a; j0++; j1++; - a = data[j0]; data[j0] = data[j1]; data[j1] = a; + a = data[j0]; + data[j0] = data[j1]; + data[j1] = a; j0++; j1++; - a = data[j0]; data[j0] = data[j1]; data[j1] = a; + a = data[j0]; + data[j0] = data[j1]; + data[j1] = a; } } @@ -568,7 +581,9 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { a = x1 * x1 + y1 * y1 + z1 * z1; if (a < tol) { // put the originals back .. - x1 = x; y1 = y; z1 = z; + x1 = x; + y1 = y; + z1 = z; numFail++; } else if (Math.abs(a - 1.0) > tol) { q = 1.0 / Math.sqrt(a); @@ -584,7 +599,6 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { } /** multiply each xyz (as a point) by a homogeneous matrix and update as the normalized point - * */ public multiplyMatrix4dAndQuietRenormalizeMatrix4d(matrix: Matrix4d) { const data = this._data; @@ -634,7 +648,6 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { } else { for (let i = 0; i + 2 < numDouble; i += 3) rangeToExtend.extendXYZ(data[i], data[i + 1], data[i + 2]); - } } /** get range of points. */ @@ -653,12 +666,14 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { /** Sum the lengths of segments between points. */ public sumLengths(): number { let sum = 0.0; - const n = 3 * (this._xyzInUse - 1); // Length already takes into account what specifically is in use + const n = 3 * (this._xyzInUse - 1); // Length already takes into account what specifically is in use const data = this._data; - for (let i = 0; i < n; i += 3) sum += Geometry.hypotenuseXYZ( - data[i + 3] - data[i], - data[i + 4] - data[i + 1], - data[i + 5] - data[i + 2]); + for (let i = 0; i < n; i += 3) + sum += Geometry.hypotenuseXYZ( + data[i + 3] - data[i], + data[i + 4] - data[i + 1], + data[i + 5] - data[i + 2], + ); return sum; } /** @@ -711,7 +726,9 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Point3d.create( fraction0 * data[i] + fraction * data[j], fraction0 * data[i + 1] + fraction * data[j + 1], - fraction0 * data[i + 2] + fraction * data[j + 2], result); + fraction0 * data[i + 2] + fraction * data[j + 2], + result, + ); } return undefined; } @@ -729,14 +746,15 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { this.pushXYZ( fraction0 * data[i] + fraction * data[j], fraction0 * data[i + 1] + fraction * data[j + 1], - fraction0 * data[i + 2] + fraction * data[j + 2]); + fraction0 * data[i + 2] + fraction * data[j + 2], + ); } } /** Sum the signed areas of the projection to xy plane */ public areaXY(): number { let area = 0.0; - const n = 3 * this._xyzInUse; // float count !! + const n = 3 * this._xyzInUse; // float count !! if (n > 6) { const x0 = this._data[n - 3]; const y0 = this._data[n - 2]; @@ -763,7 +781,9 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Vector3d.create( data[j] - data[i], data[j + 1] - data[i + 1], - data[j + 2] - data[i + 2], result); + data[j + 2] - data[i + 2], + result, + ); } /** Compute a vector from origin to indexed target j */ @@ -774,7 +794,9 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Vector3d.create( data[j] - origin.x, data[j + 1] - origin.y, - data[j + 2] - origin.z, result); + data[j + 2] - origin.z, + result, + ); } return undefined; } @@ -787,9 +809,14 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { const k = targetBIndex * 3; const data = this._data; return Geometry.crossProductXYZXYZ( - data[j] - data[i], data[j + 1] - data[i + 1], data[j + 2] - data[i + 2], - data[k] - data[i], data[k + 1] - data[i + 1], data[k + 2] - data[i + 2], - result); + data[j] - data[i], + data[j + 1] - data[i + 1], + data[j + 2] - data[i + 2], + data[k] - data[i], + data[k + 1] - data[i + 1], + data[k + 2] - data[i + 2], + result, + ); } return undefined; } @@ -818,10 +845,17 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { const k = targetBIndex * 3; const data = this._data; result.addCrossProductToTargetsInPlace( - data[i], data[i + 1], data[i + 2], - data[j], data[j + 1], data[j + 2], - data[k], data[k + 1], data[k + 2]); - } + data[i], + data[i + 1], + data[i + 2], + data[j], + data[j + 1], + data[j + 2], + data[k], + data[k + 1], + data[k + 2], + ); + } } /** @@ -845,9 +879,14 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { const k = targetBIndex * 3; const data = this._data; return Geometry.crossProductXYZXYZ( - data[j] - origin.x, data[j + 1] - origin.y, data[j + 2] - origin.z, - data[k] - origin.x, data[k + 1] - origin.y, data[k + 2] - origin.z, - result); + data[j] - origin.x, + data[j + 1] - origin.y, + data[j + 2] - origin.z, + data[k] - origin.x, + data[k + 1] - origin.y, + data[k + 2] - origin.z, + result, + ); } return undefined; } @@ -859,7 +898,8 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Geometry.hypotenuseXYZ( spacePoint.x - this._data[i0], spacePoint.y - this._data[i0 + 1], - spacePoint.z - this._data[i0 + 2]); + spacePoint.z - this._data[i0 + 2], + ); } return undefined; } @@ -876,7 +916,8 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Geometry.hypotenuseSquaredXYZ( this._data[j0] - this._data[i0], this._data[j0 + 1] - this._data[i0 + 1], - this._data[j0 + 2] - this._data[i0 + 2]); + this._data[j0 + 2] - this._data[i0 + 2], + ); } return undefined; } @@ -892,7 +933,8 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Geometry.hypotenuseXYZ( this._data[j0] - this._data[i0], this._data[j0 + 1] - this._data[i0 + 1], - this._data[j0 + 2] - this._data[i0 + 2]); + this._data[j0 + 2] - this._data[i0 + 2], + ); } return undefined; } @@ -904,7 +946,8 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { return Geometry.hypotenuseXYZ( arrayB._data[j0] - arrayA._data[i0], arrayB._data[j0 + 1] - arrayA._data[i0 + 1], - arrayB._data[j0 + 2] - arrayA._data[i0 + 2]); + arrayB._data[j0 + 2] - arrayA._data[i0 + 2], + ); } return undefined; } @@ -932,7 +975,8 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { (blockIndexA: number, blockIndexB: number) => { // numCompare++; return this.compareLexicalBlock(blockIndexA, blockIndexB); - }); + }, + ); // console.log (n, numCompare); return result; } @@ -1025,9 +1069,20 @@ export class GrowableXYZArray extends IndexedReadWriteXYZCollection { const vy = data[i0++] - ay; const vz = data[i0++] - az; result = Transform.createRowValues( - ux, vx, 0, ax, - uy, vy, 0, ay, - uz, vz, 1, az, result); + ux, + vx, + 0, + ax, + uy, + vy, + 0, + ay, + uz, + vz, + 1, + az, + result, + ); return result.computeCachedInverse() ? result : undefined; } return undefined; diff --git a/core/geometry/src/geometry3d/IndexedCollectionInterval.ts b/core/geometry/src/geometry3d/IndexedCollectionInterval.ts index c751c2035e78..e4be18155e9d 100644 --- a/core/geometry/src/geometry3d/IndexedCollectionInterval.ts +++ b/core/geometry/src/geometry3d/IndexedCollectionInterval.ts @@ -116,5 +116,4 @@ export class IndexedCollectionInterval { * @public */ export class IndexedXYZCollectionInterval extends IndexedCollectionInterval { - } diff --git a/core/geometry/src/geometry3d/IndexedXYCollection.ts b/core/geometry/src/geometry3d/IndexedXYCollection.ts index 9c9480df90f9..d404090917e5 100644 --- a/core/geometry/src/geometry3d/IndexedXYCollection.ts +++ b/core/geometry/src/geometry3d/IndexedXYCollection.ts @@ -84,7 +84,7 @@ export abstract class IndexedXYCollection { public getXAtUncheckedPointIndex(pointIndex: number): number { const pt = this.getPoint2dAtCheckedPointIndex(pointIndex, IndexedXYCollection._workPoint); if (undefined === IndexedXYCollection._workPoint) - IndexedXYCollection._workPoint = pt; // allocate the cache + IndexedXYCollection._workPoint = pt; // allocate the cache return pt ? pt.x : 0.0; } @@ -94,7 +94,7 @@ export abstract class IndexedXYCollection { public getYAtUncheckedPointIndex(pointIndex: number): number { const pt = this.getPoint2dAtCheckedPointIndex(pointIndex, IndexedXYCollection._workPoint); if (undefined === IndexedXYCollection._workPoint) - IndexedXYCollection._workPoint = pt; // allocate the cache + IndexedXYCollection._workPoint = pt; // allocate the cache return pt ? pt.y : 0.0; } diff --git a/core/geometry/src/geometry3d/IndexedXYZCollection.ts b/core/geometry/src/geometry3d/IndexedXYZCollection.ts index 715fb7154f9a..134a9702c389 100644 --- a/core/geometry/src/geometry3d/IndexedXYZCollection.ts +++ b/core/geometry/src/geometry3d/IndexedXYZCollection.ts @@ -32,7 +32,9 @@ class PointsIterator implements Iterator, Iterable { }; } - public [Symbol.iterator](): Iterator { return this; } + public [Symbol.iterator](): Iterator { + return this; + } } /** * abstract base class for read-only access to XYZ data with indexed reference. @@ -106,8 +108,8 @@ export abstract class IndexedXYZCollection { const y0 = this.getYAtUncheckedPointIndex(origin); const z0 = this.getZAtUncheckedPointIndex(origin); return (this.getXAtUncheckedPointIndex(indexA) - x0) * (this.getXAtUncheckedPointIndex(indexB) - x0) + - (this.getYAtUncheckedPointIndex(indexA) - y0) * (this.getYAtUncheckedPointIndex(indexB) - y0) + - (this.getZAtUncheckedPointIndex(indexA) - z0) * (this.getZAtUncheckedPointIndex(indexB) - z0); + (this.getYAtUncheckedPointIndex(indexA) - y0) * (this.getYAtUncheckedPointIndex(indexB) - y0) + + (this.getZAtUncheckedPointIndex(indexA) - z0) * (this.getZAtUncheckedPointIndex(indexB) - z0); } /** * Return the dot product of the vectors from the point at `origin` to the point at `indexA` and to `targetB`. @@ -123,8 +125,8 @@ export abstract class IndexedXYZCollection { const y0 = this.getYAtUncheckedPointIndex(origin); const z0 = this.getZAtUncheckedPointIndex(origin); return (this.getXAtUncheckedPointIndex(indexA) - x0) * (targetB.x - x0) + - (this.getYAtUncheckedPointIndex(indexA) - y0) * (targetB.y - y0) + - (this.getZAtUncheckedPointIndex(indexA) - z0) * (targetB.z - z0); + (this.getYAtUncheckedPointIndex(indexA) - y0) * (targetB.y - y0) + + (this.getZAtUncheckedPointIndex(indexA) - z0) * (targetB.z - z0); } /** * Return the cross product of the vectors from `origin` to points at `indexA` and `indexB` @@ -149,12 +151,15 @@ export abstract class IndexedXYZCollection { const x0 = this.getXAtUncheckedPointIndex(origin); const y0 = this.getYAtUncheckedPointIndex(origin); const z0 = this.getZAtUncheckedPointIndex(origin); - return Vector3d.createCrossProduct(this.getXAtUncheckedPointIndex(indexA) - x0, - this.getYAtUncheckedPointIndex(indexA) - y0, - this.getZAtUncheckedPointIndex(indexA) - z0, - targetB.x - x0, - targetB.y - y0, - targetB.z - z0, result); + return Vector3d.createCrossProduct( + this.getXAtUncheckedPointIndex(indexA) - x0, + this.getYAtUncheckedPointIndex(indexA) - y0, + this.getZAtUncheckedPointIndex(indexA) - z0, + targetB.x - x0, + targetB.y - y0, + targetB.z - z0, + result, + ); } /** * Return the cross product of vectors from `origin` to points at `indexA` and `indexB` @@ -196,7 +201,8 @@ export abstract class IndexedXYZCollection { return Geometry.hypotenuseSquaredXYZ( target.x - this.getXAtUncheckedPointIndex(index0), target.y - this.getYAtUncheckedPointIndex(index0), - target.z - this.getZAtUncheckedPointIndex(index0)); + target.z - this.getZAtUncheckedPointIndex(index0), + ); } /** * Return distance between indicated points. @@ -253,7 +259,7 @@ export abstract class IndexedXYZCollection { * @param scales array of scales. For best results, scales should have same length as the instance. * @param result optional pre-allocated object to fill and return * @return s = sum(p_i * s_i), where i ranges from 0 to min(this.length, scales.length). - */ + */ public linearCombination(scales: number[], result?: Point3d | Vector3d): XYZ { const n = Math.min(this.length, scales.length); const sum = (result instanceof Vector3d) ? Vector3d.createZero(result) : Point3d.createZero(result); @@ -276,9 +282,12 @@ export abstract class IndexedXYZCollection { public interpolateIndexIndex(index0: number, fraction: number, index1: number, result?: Point3d): Point3d | undefined { if (index0 < 0 || index0 >= this.length || index1 < 0 || index1 >= this.length) return undefined; - return Point3d.create(Geometry.interpolate(this.getXAtUncheckedPointIndex(index0), fraction, this.getXAtUncheckedPointIndex(index1)), - Geometry.interpolate(this.getYAtUncheckedPointIndex(index0), fraction, this.getYAtUncheckedPointIndex(index1)), - Geometry.interpolate(this.getZAtUncheckedPointIndex(index0), fraction, this.getZAtUncheckedPointIndex(index1)), result); + return Point3d.create( + Geometry.interpolate(this.getXAtUncheckedPointIndex(index0), fraction, this.getXAtUncheckedPointIndex(index1)), + Geometry.interpolate(this.getYAtUncheckedPointIndex(index0), fraction, this.getYAtUncheckedPointIndex(index1)), + Geometry.interpolate(this.getZAtUncheckedPointIndex(index0), fraction, this.getZAtUncheckedPointIndex(index1)), + result, + ); } /** access x of indexed point */ diff --git a/core/geometry/src/geometry3d/LongitudeLatitudeAltitude.ts b/core/geometry/src/geometry3d/LongitudeLatitudeAltitude.ts index f3ba5f1aa667..857ae7c1d79b 100644 --- a/core/geometry/src/geometry3d/LongitudeLatitudeAltitude.ts +++ b/core/geometry/src/geometry3d/LongitudeLatitudeAltitude.ts @@ -23,26 +23,46 @@ export class LongitudeLatitudeNumber implements BeJSONFunctions { private _latitude: Angle; private _altitude: number; /** (property getter) longitude in radians */ - public get longitudeRadians(): number { return this._longitude.radians; } + public get longitudeRadians(): number { + return this._longitude.radians; + } /** (property getter) longitude in degrees */ - public get longitudeDegrees(): number { return this._longitude.degrees; } + public get longitudeDegrees(): number { + return this._longitude.degrees; + } /** (property getter) (reference to) longitude as a strongly typed `Angle` */ - public get longitudeRef(): Angle { return this._longitude; } + public get longitudeRef(): Angle { + return this._longitude; + } /** (property getter) (clone of) longitude as a strongly typed `Angle` */ - public get longitude(): Angle { return this._longitude.clone(); } + public get longitude(): Angle { + return this._longitude.clone(); + } /** (property getter) latitude in radians */ - public get latitudeRadians(): number { return this._latitude.radians; } + public get latitudeRadians(): number { + return this._latitude.radians; + } /** (property getter) latitude in degrees */ - public get latitudeDegrees(): number { return this._latitude.degrees; } + public get latitudeDegrees(): number { + return this._latitude.degrees; + } /** (property getter) (reference to) latitude as a strongly typed `Angle` */ - public get latitudeRef(): Angle { return this._latitude; } + public get latitudeRef(): Angle { + return this._latitude; + } /** (property getter) (clone of) latitude as a strongly typed `Angle` */ - public get latitude(): Angle { return this._latitude.clone(); } + public get latitude(): Angle { + return this._latitude.clone(); + } /** Get or set the altitude. */ - public get altitude(): number { return this._altitude; } - public set altitude(value: number) { this._altitude = value; } + public get altitude(): number { + return this._altitude; + } + public set altitude(value: number) { + this._altitude = value; + } /** Constructor: Capture angles and altitude */ private constructor(longitude: Angle, latitude: Angle, altitude: number) { this._longitude = longitude; @@ -50,7 +70,9 @@ export class LongitudeLatitudeNumber implements BeJSONFunctions { this._altitude = altitude; } /** Create with all zero angles and altitude. */ - public static createZero(): LongitudeLatitudeNumber { return new LongitudeLatitudeNumber(Angle.createDegrees(0), Angle.createDegrees(0), 0); } + public static createZero(): LongitudeLatitudeNumber { + return new LongitudeLatitudeNumber(Angle.createDegrees(0), Angle.createDegrees(0), 0); + } /** Create with strongly typed `Angle` inputs */ public static create(longitude: Angle, latitude: Angle, h: number = 0, result?: LongitudeLatitudeNumber): LongitudeLatitudeNumber { if (result) { @@ -62,7 +84,12 @@ export class LongitudeLatitudeNumber implements BeJSONFunctions { return new LongitudeLatitudeNumber(longitude.clone(), latitude.clone(), h); } /** Create with angles in radians. */ - public static createRadians(longitudeRadians: number, latitudeRadians: number, h: number = 0, result?: LongitudeLatitudeNumber): LongitudeLatitudeNumber { + public static createRadians( + longitudeRadians: number, + latitudeRadians: number, + h: number = 0, + result?: LongitudeLatitudeNumber, + ): LongitudeLatitudeNumber { if (result) { result._longitude.setRadians(longitudeRadians); result._latitude.setRadians(latitudeRadians); @@ -72,7 +99,12 @@ export class LongitudeLatitudeNumber implements BeJSONFunctions { return new LongitudeLatitudeNumber(Angle.createRadians(longitudeRadians), Angle.createRadians(latitudeRadians), h); } /** Create with angles in degrees. */ - public static createDegrees(longitudeDegrees: number, latitudeDegrees: number, h: number = 0, result?: LongitudeLatitudeNumber): LongitudeLatitudeNumber { + public static createDegrees( + longitudeDegrees: number, + latitudeDegrees: number, + h: number = 0, + result?: LongitudeLatitudeNumber, + ): LongitudeLatitudeNumber { if (result) { result._longitude.setRadians(longitudeDegrees); result._latitude.setRadians(latitudeDegrees); @@ -84,7 +116,6 @@ export class LongitudeLatitudeNumber implements BeJSONFunctions { /** * Set content from a JSON object. * If the json object is undefined or unrecognized, always set a default value. - * */ public setFromJSON(json: any) { if (json.latitude !== undefined) { diff --git a/core/geometry/src/geometry3d/Matrix3d.ts b/core/geometry/src/geometry3d/Matrix3d.ts index b71138ddefd7..cb00d1da30f5 100644 --- a/core/geometry/src/geometry3d/Matrix3d.ts +++ b/core/geometry/src/geometry3d/Matrix3d.ts @@ -41,13 +41,25 @@ export class PackedMatrix3dOps { */ public static loadMatrix( dest: Float64Array, - a00: number, a01: number, a02: number, - a10: number, a11: number, a12: number, - a20: number, a21: number, a22: number, + a00: number, + a01: number, + a02: number, + a10: number, + a11: number, + a12: number, + a20: number, + a21: number, + a22: number, ) { - dest[0] = a00; dest[1] = a01; dest[2] = a02; - dest[3] = a10; dest[4] = a11; dest[5] = a12; - dest[6] = a20; dest[7] = a21; dest[8] = a22; + dest[0] = a00; + dest[1] = a01; + dest[2] = a02; + dest[3] = a10; + dest[4] = a11; + dest[5] = a12; + dest[6] = a20; + dest[7] = a21; + dest[8] = a22; } /** * Multiply 3x3 matrix `a*b`, store in `result`. @@ -61,15 +73,15 @@ export class PackedMatrix3dOps { result = new Float64Array(9); PackedMatrix3dOps.loadMatrix( result, - (a[0] * b[0] + a[1] * b[3] + a[2] * b[6]), - (a[0] * b[1] + a[1] * b[4] + a[2] * b[7]), - (a[0] * b[2] + a[1] * b[5] + a[2] * b[8]), - (a[3] * b[0] + a[4] * b[3] + a[5] * b[6]), - (a[3] * b[1] + a[4] * b[4] + a[5] * b[7]), - (a[3] * b[2] + a[4] * b[5] + a[5] * b[8]), - (a[6] * b[0] + a[7] * b[3] + a[8] * b[6]), - (a[6] * b[1] + a[7] * b[4] + a[8] * b[7]), - (a[6] * b[2] + a[7] * b[5] + a[8] * b[8]), + a[0] * b[0] + a[1] * b[3] + a[2] * b[6], + a[0] * b[1] + a[1] * b[4] + a[2] * b[7], + a[0] * b[2] + a[1] * b[5] + a[2] * b[8], + a[3] * b[0] + a[4] * b[3] + a[5] * b[6], + a[3] * b[1] + a[4] * b[4] + a[5] * b[7], + a[3] * b[2] + a[4] * b[5] + a[5] * b[8], + a[6] * b[0] + a[7] * b[3] + a[8] * b[6], + a[6] * b[1] + a[7] * b[4] + a[8] * b[7], + a[6] * b[2] + a[7] * b[5] + a[8] * b[8], ); return result; } @@ -85,15 +97,15 @@ export class PackedMatrix3dOps { result = new Float64Array(9); PackedMatrix3dOps.loadMatrix( result, - (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]), - (a[0] * b[3] + a[1] * b[4] + a[2] * b[5]), - (a[0] * b[6] + a[1] * b[7] + a[2] * b[8]), - (a[3] * b[0] + a[4] * b[1] + a[5] * b[2]), - (a[3] * b[3] + a[4] * b[4] + a[5] * b[5]), - (a[3] * b[6] + a[4] * b[7] + a[5] * b[8]), - (a[6] * b[0] + a[7] * b[1] + a[8] * b[2]), - (a[6] * b[3] + a[7] * b[4] + a[8] * b[5]), - (a[6] * b[6] + a[7] * b[7] + a[8] * b[8]), + a[0] * b[0] + a[1] * b[1] + a[2] * b[2], + a[0] * b[3] + a[1] * b[4] + a[2] * b[5], + a[0] * b[6] + a[1] * b[7] + a[2] * b[8], + a[3] * b[0] + a[4] * b[1] + a[5] * b[2], + a[3] * b[3] + a[4] * b[4] + a[5] * b[5], + a[3] * b[6] + a[4] * b[7] + a[5] * b[8], + a[6] * b[0] + a[7] * b[1] + a[8] * b[2], + a[6] * b[3] + a[7] * b[4] + a[8] * b[5], + a[6] * b[6] + a[7] * b[7] + a[8] * b[8], ); return result; } @@ -109,23 +121,29 @@ export class PackedMatrix3dOps { result = new Float64Array(9); PackedMatrix3dOps.loadMatrix( result, - (a[0] * b[0] + a[3] * b[3] + a[6] * b[6]), - (a[0] * b[1] + a[3] * b[4] + a[6] * b[7]), - (a[0] * b[2] + a[3] * b[5] + a[6] * b[8]), - (a[1] * b[0] + a[4] * b[3] + a[7] * b[6]), - (a[1] * b[1] + a[4] * b[4] + a[7] * b[7]), - (a[1] * b[2] + a[4] * b[5] + a[7] * b[8]), - (a[2] * b[0] + a[5] * b[3] + a[8] * b[6]), - (a[2] * b[1] + a[5] * b[4] + a[8] * b[7]), - (a[2] * b[2] + a[5] * b[5] + a[8] * b[8]), + a[0] * b[0] + a[3] * b[3] + a[6] * b[6], + a[0] * b[1] + a[3] * b[4] + a[6] * b[7], + a[0] * b[2] + a[3] * b[5] + a[6] * b[8], + a[1] * b[0] + a[4] * b[3] + a[7] * b[6], + a[1] * b[1] + a[4] * b[4] + a[7] * b[7], + a[1] * b[2] + a[4] * b[5] + a[7] * b[8], + a[2] * b[0] + a[5] * b[3] + a[8] * b[6], + a[2] * b[1] + a[5] * b[4] + a[8] * b[7], + a[2] * b[2] + a[5] * b[5] + a[8] * b[8], ); return result; } /** Transpose 3x3 matrix `a` in place */ public static transposeInPlace(a: Float64Array) { - let q = a[1]; a[1] = a[3]; a[3] = q; - q = a[2]; a[2] = a[6]; a[6] = q; - q = a[5]; a[5] = a[7]; a[7] = q; + let q = a[1]; + a[1] = a[3]; + a[3] = q; + q = a[2]; + a[2] = a[6]; + a[6] = q; + q = a[5]; + a[5] = a[7]; + a[7] = q; } /** * Compute transpose of 3x3 matrix `a`, store in `dest`. @@ -139,18 +157,30 @@ export class PackedMatrix3dOps { } else { if (!dest || dest.length < 9) dest = new Float64Array(9); - dest[0] = a[0]; dest[1] = a[3]; dest[2] = a[6]; - dest[3] = a[1]; dest[4] = a[4]; dest[5] = a[7]; - dest[6] = a[2]; dest[7] = a[5]; dest[8] = a[8]; + dest[0] = a[0]; + dest[1] = a[3]; + dest[2] = a[6]; + dest[3] = a[1]; + dest[4] = a[4]; + dest[5] = a[7]; + dest[6] = a[2]; + dest[7] = a[5]; + dest[8] = a[8]; } return dest; } /** Copy matrix `a` entries into `dest` */ public static copy(a: Float64Array, dest: Float64Array): Float64Array { if (dest !== a) { - dest[0] = a[0]; dest[1] = a[1]; dest[2] = a[2]; - dest[3] = a[3]; dest[4] = a[4]; dest[5] = a[5]; - dest[6] = a[6]; dest[7] = a[7]; dest[8] = a[8]; + dest[0] = a[0]; + dest[1] = a[1]; + dest[2] = a[2]; + dest[3] = a[3]; + dest[4] = a[4]; + dest[5] = a[5]; + dest[6] = a[6]; + dest[7] = a[7]; + dest[8] = a[8]; } return dest; } @@ -208,7 +238,7 @@ export enum InverseMatrixState { */ export class Matrix3d implements BeJSONFunctions { /** Control flag for whether this class uses cached inverse of matrices. */ - public static useCachedInverse = true; // cached inverse can be suppressed for testing. + public static useCachedInverse = true; // cached inverse can be suppressed for testing. /** Total number of times a cached inverse was used to avoid recompute */ public static numUseCache = 0; /** Total number of times a cached inverse was computed. */ @@ -272,9 +302,11 @@ export class Matrix3d implements BeJSONFunctions { * `[ [1, 2, 3],[ 4, 5, 6], [7, 8, 9] ]` */ public toJSON(): Matrix3dProps { - return [[this.coffs[0], this.coffs[1], this.coffs[2]], - [this.coffs[3], this.coffs[4], this.coffs[5]], - [this.coffs[6], this.coffs[7], this.coffs[8]]]; + return [[this.coffs[0], this.coffs[1], this.coffs[2]], [this.coffs[3], this.coffs[4], this.coffs[5]], [ + this.coffs[6], + this.coffs[7], + this.coffs[8], + ]]; } /** * Copy data from various input forms to this matrix. @@ -300,23 +332,44 @@ export class Matrix3d implements BeJSONFunctions { // if json is Matrix3dProps and is an array of arrays if (Geometry.isArrayOfNumberArray(json, 3, 3)) { this.setRowValues( - json[0][0], json[0][1], json[0][2], - json[1][0], json[1][1], json[1][2], - json[2][0], json[2][1], json[2][2]); + json[0][0], + json[0][1], + json[0][2], + json[1][0], + json[1][1], + json[1][2], + json[2][0], + json[2][1], + json[2][2], + ); return; } // if json is Matrix3dProps and is an array of numbers if (json.length === 9) { this.setRowValues( - json[0], json[1], json[2], - json[3], json[4], json[5], - json[6], json[7], json[8]); + json[0], + json[1], + json[2], + json[3], + json[4], + json[5], + json[6], + json[7], + json[8], + ); return; } else if (json.length === 4) { this.setRowValues( - json[0], json[1], 0, - json[2], json[3], 0, - 0, 0, 1); + json[0], + json[1], + 0, + json[2], + json[3], + 0, + 0, + 0, + 1, + ); return; } // if json is Matrix3dProps but is not the right size @@ -344,7 +397,8 @@ export class Matrix3d implements BeJSONFunctions { const max = Geometry.maxAbsXYZ( this.coffs[columnIndex] - other.coffs[columnIndex], this.coffs[columnIndex + 3] - other.coffs[columnIndex + 3], - this.coffs[columnIndex + 6] - other.coffs[columnIndex + 6]); + this.coffs[columnIndex + 6] - other.coffs[columnIndex + 6], + ); return Geometry.isDistanceWithinTol(max, tol); } /** @@ -355,7 +409,8 @@ export class Matrix3d implements BeJSONFunctions { const max = Geometry.maxAbsXYZ( this.coffs[columnIndex] - ax, this.coffs[columnIndex + 3] - ay, - this.coffs[columnIndex + 6] - az); + this.coffs[columnIndex + 6] - az, + ); return Geometry.isDistanceWithinTol(max, tol); } /** @@ -369,8 +424,12 @@ export class Matrix3d implements BeJSONFunctions { return true; if (this.isAlmostEqualColumn(AxisIndex.Z, other, tol)) { const radians = Angle.radiansBetweenVectorsXYZ( - this.coffs[0], this.coffs[3], this.coffs[6], - other.coffs[0], other.coffs[3], other.coffs[6], + this.coffs[0], + this.coffs[3], + this.coffs[6], + other.coffs[0], + other.coffs[3], + other.coffs[6], ); const angle = Angle.createRadians(radians); // angle between X columns in `this` and `other` const columnX = this.columnX(); @@ -426,16 +485,28 @@ export class Matrix3d implements BeJSONFunctions { * @param azz row z, column z(2, 3) entry */ public static createRowValues( - axx: number, axy: number, axz: number, - ayx: number, ayy: number, ayz: number, - azx: number, azy: number, azz: number, + axx: number, + axy: number, + axz: number, + ayx: number, + ayy: number, + ayz: number, + azx: number, + azy: number, + azz: number, result?: Matrix3d, ): Matrix3d { result = result ? result : new Matrix3d(); result.inverseState = InverseMatrixState.unknown; - result.coffs[0] = axx; result.coffs[1] = axy; result.coffs[2] = axz; - result.coffs[3] = ayx; result.coffs[4] = ayy; result.coffs[5] = ayz; - result.coffs[6] = azx; result.coffs[7] = azy; result.coffs[8] = azz; + result.coffs[0] = axx; + result.coffs[1] = axy; + result.coffs[2] = axz; + result.coffs[3] = ayx; + result.coffs[4] = ayy; + result.coffs[5] = ayz; + result.coffs[6] = azx; + result.coffs[7] = azy; + result.coffs[8] = azz; return result; } /** @@ -469,8 +540,11 @@ export class Matrix3d implements BeJSONFunctions { * go to the third column, and third letter X means columnC should go to the first column. */ public static createColumnsInAxisOrder( - axisOrder: AxisOrder, columnA: Vector3d | undefined, columnB: Vector3d | undefined, - columnC: Vector3d | undefined, result?: Matrix3d, + axisOrder: AxisOrder, + columnA: Vector3d | undefined, + columnB: Vector3d | undefined, + columnC: Vector3d | undefined, + result?: Matrix3d, ): Matrix3d { if (!result) result = new Matrix3d(); if (axisOrder === AxisOrder.YZX) { @@ -483,7 +557,7 @@ export class Matrix3d implements BeJSONFunctions { result.setColumns(columnB, columnA, columnC); } else if (axisOrder === AxisOrder.ZYX) { result.setColumns(columnC, columnB, columnA); - } else { // AxisOrder.XYZ + } else { // AxisOrder.XYZ result.setColumns(columnA, columnB, columnC); } return result; @@ -507,9 +581,15 @@ export class Matrix3d implements BeJSONFunctions { const coffs = this.coffs; this.inverseState = InverseMatrixState.inverseStored; this.inverseCoffs = Float64Array.from([ - coffs[0], coffs[3], coffs[6], - coffs[1], coffs[4], coffs[7], - coffs[2], coffs[5], coffs[8], + coffs[0], + coffs[3], + coffs[6], + coffs[1], + coffs[4], + coffs[7], + coffs[2], + coffs[5], + coffs[8], ]); } /** @@ -525,12 +605,25 @@ export class Matrix3d implements BeJSONFunctions { * @param azz row z, column z (2,3) entry */ public setRowValues( - axx: number, axy: number, axz: number, - ayx: number, ayy: number, ayz: number, - azx: number, azy: number, azz: number): void { - this.coffs[0] = axx; this.coffs[1] = axy; this.coffs[2] = axz; - this.coffs[3] = ayx; this.coffs[4] = ayy; this.coffs[5] = ayz; - this.coffs[6] = azx; this.coffs[7] = azy; this.coffs[8] = azz; + axx: number, + axy: number, + axz: number, + ayx: number, + ayy: number, + ayz: number, + azx: number, + azy: number, + azz: number, + ): void { + this.coffs[0] = axx; + this.coffs[1] = axy; + this.coffs[2] = axz; + this.coffs[3] = ayx; + this.coffs[4] = ayy; + this.coffs[5] = ayz; + this.coffs[6] = azx; + this.coffs[7] = azy; + this.coffs[8] = azz; this.inverseState = InverseMatrixState.unknown; } /** Set the matrix to an identity. */ @@ -559,7 +652,7 @@ export class Matrix3d implements BeJSONFunctions { this.inverseState = InverseMatrixState.inverseStored; } else if (other.inverseState !== InverseMatrixState.inverseStored) { this.inverseState = other.inverseState; - } else { // This is reached when other says stored but does not have coffs. This should not happen. + } else { // This is reached when other says stored but does not have coffs. This should not happen. this.inverseState = InverseMatrixState.unknown; } } @@ -598,7 +691,6 @@ export class Matrix3d implements BeJSONFunctions { * equation * \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1\end{bmatrix} * ``` - * */ public static createIdentity(result?: Matrix3d): Matrix3d { result = result ? result : new Matrix3d(); @@ -613,7 +705,10 @@ export class Matrix3d implements BeJSONFunctions { * ``` */ public static createScale( - scaleFactorX: number, scaleFactorY: number, scaleFactorZ: number, result?: Matrix3d, + scaleFactorX: number, + scaleFactorY: number, + scaleFactorZ: number, + result?: Matrix3d, ): Matrix3d { if (result) result.setZero(); @@ -627,9 +722,7 @@ export class Matrix3d implements BeJSONFunctions { } else { result.inverseState = InverseMatrixState.inverseStored; result.inverseCoffs = Float64Array.from( - [1 / scaleFactorX, 0, 0, - 0, 1 / scaleFactorY, 0, - 0, 0, 1 / scaleFactorZ], + [1 / scaleFactorX, 0, 0, 0, 1 / scaleFactorY, 0, 0, 0, 1 / scaleFactorZ], ); } return result; @@ -652,7 +745,7 @@ export class Matrix3d implements BeJSONFunctions { */ public static createPerpendicularVectorFavorXYPlane(vectorA: Vector3d, result?: Vector3d): Vector3d { const a = vectorA.magnitude(); - const scale = 64.0; // A constant from the dawn of time in the CAD industry + const scale = 64.0; // A constant from the dawn of time in the CAD industry const b = a / scale; // if vectorA is close to the Z axis if (Math.abs(vectorA.x) < b && Math.abs(vectorA.y) < b) { @@ -684,7 +777,11 @@ export class Matrix3d implements BeJSONFunctions { * to the column Z (column 3), and X is at index 2 so vectorW goes to the column X (column 1) */ public static createShuffledColumns( - vectorU: Vector3d, vectorV: Vector3d, vectorW: Vector3d, axisOrder: AxisOrder, result?: Matrix3d, + vectorU: Vector3d, + vectorV: Vector3d, + vectorW: Vector3d, + axisOrder: AxisOrder, + result?: Matrix3d, ): Matrix3d { const target = Matrix3d._create(result); target.setColumn(Geometry.axisOrderToAxis(axisOrder, 0), vectorU); @@ -703,7 +800,10 @@ export class Matrix3d implements BeJSONFunctions { * * This function internally uses createShuffledColumns. */ public static createRigidFromColumns( - vectorA: Vector3d, vectorB: Vector3d, axisOrder: AxisOrder, result?: Matrix3d, + vectorA: Vector3d, + vectorB: Vector3d, + axisOrder: AxisOrder, + result?: Matrix3d, ): Matrix3d | undefined { const vectorA1 = vectorA.normalize(); if (vectorA1) { @@ -729,7 +829,9 @@ export class Matrix3d implements BeJSONFunctions { * * Visualization can be found at https://www.itwinjs.org/sandbox/SaeedTorabi/2PerpendicularVectorsTo1Vector */ public static createRigidHeadsUp( - vectorA: Vector3d, axisOrder: AxisOrder = AxisOrder.ZXY, result?: Matrix3d, + vectorA: Vector3d, + axisOrder: AxisOrder = AxisOrder.ZXY, + result?: Matrix3d, ): Matrix3d { const vectorB = Matrix3d.createPerpendicularVectorFavorXYPlane(vectorA); const matrix = Matrix3d.createRigidFromColumns(vectorA, vectorB, axisOrder, result); @@ -755,9 +857,15 @@ export class Matrix3d implements BeJSONFunctions { const unit = axis.normalize(); if (unit) { const retVal = Matrix3d.createRowValues( - unit.x * unit.x * v + c, unit.x * unit.y * v - s * unit.z, unit.x * unit.z * v + s * unit.y, - unit.y * unit.x * v + s * unit.z, unit.y * unit.y * v + c, unit.y * unit.z * v - s * unit.x, - unit.z * unit.x * v - s * unit.y, unit.z * unit.y * v + s * unit.x, unit.z * unit.z * v + c, + unit.x * unit.x * v + c, + unit.x * unit.y * v - s * unit.z, + unit.x * unit.z * v + s * unit.y, + unit.y * unit.x * v + s * unit.z, + unit.y * unit.y * v + c, + unit.y * unit.z * v - s * unit.x, + unit.z * unit.x * v - s * unit.y, + unit.z * unit.y * v + s * unit.x, + unit.z * unit.z * v + c, result, ); retVal.setupInverseTranspose(); @@ -777,22 +885,43 @@ export class Matrix3d implements BeJSONFunctions { let myResult; if (axisIndex === AxisIndex.X) { myResult = Matrix3d.createRowValues( - 1, 0, 0, - 0, c, -s, - 0, s, c, - result); + 1, + 0, + 0, + 0, + c, + -s, + 0, + s, + c, + result, + ); } else if (axisIndex === AxisIndex.Y) { myResult = Matrix3d.createRowValues( - c, 0, s, - 0, 1, 0, - -s, 0, c, - result); + c, + 0, + s, + 0, + 1, + 0, + -s, + 0, + c, + result, + ); } else { myResult = Matrix3d.createRowValues( - c, -s, 0, - s, c, 0, - 0, 0, 1, - result); + c, + -s, + 0, + s, + c, + 0, + 0, + 0, + 1, + result, + ); } myResult.setupInverseTranspose(); return myResult; @@ -844,13 +973,18 @@ export class Matrix3d implements BeJSONFunctions { * ``` */ public static createColumns(vectorU: Vector3d, vectorV: Vector3d, vectorW: Vector3d, result?: Matrix3d): Matrix3d { - return Matrix3d.createRowValues - ( - vectorU.x, vectorV.x, vectorW.x, - vectorU.y, vectorV.y, vectorW.y, - vectorU.z, vectorV.z, vectorW.z, - result, - ); + return Matrix3d.createRowValues( + vectorU.x, + vectorV.x, + vectorW.x, + vectorU.y, + vectorV.y, + vectorW.y, + vectorU.z, + vectorV.z, + vectorW.z, + result, + ); } /** * Create a matrix with each column's _x,y_ parts given `XAndY` and separate numeric z values. @@ -860,18 +994,26 @@ export class Matrix3d implements BeJSONFunctions { * ``` */ public static createColumnsXYW( - vectorU: XAndY, u: number, - vectorV: XAndY, v: number, - vectorW: XAndY, w: number, + vectorU: XAndY, + u: number, + vectorV: XAndY, + v: number, + vectorW: XAndY, + w: number, result?: Matrix3d, ): Matrix3d { - return Matrix3d.createRowValues - ( - vectorU.x, vectorV.x, vectorW.x, - vectorU.y, vectorV.y, vectorW.y, - u, v, w, - result, - ); + return Matrix3d.createRowValues( + vectorU.x, + vectorV.x, + vectorW.x, + vectorU.y, + vectorV.y, + vectorW.y, + u, + v, + w, + result, + ); } /** * Create a matrix from "as viewed" right and up vectors. @@ -909,7 +1051,10 @@ export class Matrix3d implements BeJSONFunctions { * by leftNoneRight and topNoneBottom. Returns undefined if rightVector and upVector are parallel. */ public static createViewedAxes( - rightVector: Vector3d, upVector: Vector3d, leftNoneRight: number = 0, topNoneBottom: number = 0, + rightVector: Vector3d, + upVector: Vector3d, + leftNoneRight: number = 0, + topNoneBottom: number = 0, ): Matrix3d | undefined { const columnZ = rightVector.crossProduct(upVector); if (columnZ.normalizeInPlace()) { @@ -954,43 +1099,80 @@ export class Matrix3d implements BeJSONFunctions { * @param result optional result. */ public static createStandardWorldToView( - index: StandardViewIndex, invert: boolean = false, result?: Matrix3d, + index: StandardViewIndex, + invert: boolean = false, + result?: Matrix3d, ): Matrix3d { switch (index) { // Start with TOP view, ccw rotation by 180 degrees around X case StandardViewIndex.Bottom: result = Matrix3d.createRowValues( - 1, 0, 0, - 0, -1, 0, - 0, 0, -1); + 1, + 0, + 0, + 0, + -1, + 0, + 0, + 0, + -1, + ); break; // Start with TOP view, ccw rotation by -90 degrees around X and by 90 degrees around Z case StandardViewIndex.Left: result = Matrix3d.createRowValues( - 0, -1, 0, - 0, 0, 1, - -1, 0, 0); + 0, + -1, + 0, + 0, + 0, + 1, + -1, + 0, + 0, + ); break; // Start with TOP view, ccw rotation by -90 degrees around X and by -90 degrees around Z case StandardViewIndex.Right: result = Matrix3d.createRowValues( - 0, 1, 0, - 0, 0, 1, - 1, 0, 0); + 0, + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 0, + ); break; // Start with TOP view, ccw rotation by -90 degrees around X case StandardViewIndex.Front: result = Matrix3d.createRowValues( - 1, 0, 0, - 0, 0, 1, - 0, -1, 0); + 1, + 0, + 0, + 0, + 0, + 1, + 0, + -1, + 0, + ); break; // Start with TOP view, ccw rotation by -90 degrees around X and by 180 degrees around Z case StandardViewIndex.Back: result = Matrix3d.createRowValues( - -1, 0, 0, - 0, 0, 1, - 0, 1, 0); + -1, + 0, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + ); break; /** * Isometric view @@ -1001,16 +1183,30 @@ export class Matrix3d implements BeJSONFunctions { */ case StandardViewIndex.Iso: result = Matrix3d.createRowValues( - 0.707106781186548, -0.70710678118654757, 0.00000000000000000, - 0.408248290463863, 0.40824829046386302, 0.81649658092772603, - -0.577350269189626, -0.57735026918962573, 0.57735026918962573); + 0.707106781186548, + -0.70710678118654757, + 0.00000000000000000, + 0.408248290463863, + 0.40824829046386302, + 0.81649658092772603, + -0.577350269189626, + -0.57735026918962573, + 0.57735026918962573, + ); break; // Start with FRONT view, ccw rotation by 45 degrees around Y and by 35.264 degrees around X case StandardViewIndex.RightIso: result = Matrix3d.createRowValues( - 0.707106781186548, 0.70710678118654757, 0.00000000000000000, - -0.408248290463863, 0.40824829046386302, 0.81649658092772603, - 0.577350269189626, -0.57735026918962573, 0.57735026918962573); + 0.707106781186548, + 0.70710678118654757, + 0.00000000000000000, + -0.408248290463863, + 0.40824829046386302, + 0.81649658092772603, + 0.577350269189626, + -0.57735026918962573, + 0.57735026918962573, + ); break; // no rotation case StandardViewIndex.Top: @@ -1185,7 +1381,7 @@ export class Matrix3d implements BeJSONFunctions { } // sin is close to 0 then we got to special cases (angle 0 or 180) which needs to be handled differently if (Math.abs(s) < Geometry.smallAngleRadians) { - if (c > 0) // sin = 0 and cos = 1 so angle = 0 (i.e., no rotation) + if (c > 0) // sin = 0 and cos = 1 so angle = 0 (i.e., no rotation) return { axis: Vector3d.create(0, 0, 1), angle: Angle.createRadians(0), ok: true }; /** * If sin = 0 and cos = -1 then angle = 180 (i.e., 180 degree rotation around some axis) @@ -1335,7 +1531,10 @@ export class Matrix3d implements BeJSONFunctions { * @param result optional result matrix. */ public static createPartialRotationVectorToVector( - vectorA: Vector3d, fraction: number, vectorB: Vector3d, result?: Matrix3d, + vectorA: Vector3d, + fraction: number, + vectorB: Vector3d, + result?: Matrix3d, ): Matrix3d | undefined { let upVector = vectorA.unitCrossProduct(vectorB); // the usual case (both vectors and also their cross product is non-zero) @@ -1346,8 +1545,10 @@ export class Matrix3d implements BeJSONFunctions { ); } // if either vector is zero - if (Geometry.isSmallMetricDistance(vectorA.magnitude()) - || Geometry.isSmallMetricDistance(vectorB.magnitude())) + if ( + Geometry.isSmallMetricDistance(vectorA.magnitude()) + || Geometry.isSmallMetricDistance(vectorB.magnitude()) + ) return undefined; // aligned vectors (cross product = 0, dot product > 0) if (vectorA.dotProduct(vectorB) > 0.0) @@ -1358,7 +1559,9 @@ export class Matrix3d implements BeJSONFunctions { } /** Returns a matrix that rotates from vectorA to vectorB. */ public static createRotationVectorToVector( - vectorA: Vector3d, vectorB: Vector3d, result?: Matrix3d, + vectorA: Vector3d, + vectorB: Vector3d, + result?: Matrix3d, ): Matrix3d | undefined { return this.createPartialRotationVectorToVector(vectorA, 1.0, vectorB, result); } @@ -1367,23 +1570,44 @@ export class Matrix3d implements BeJSONFunctions { axisIndex = Geometry.cyclic3dAxis(axisIndex); if (axisIndex === 0) { const retVal = Matrix3d.createRowValues( - 1, 0, 0, - 0, 0, -1, - 0, 1, 0); + 1, + 0, + 0, + 0, + 0, + -1, + 0, + 1, + 0, + ); retVal.setupInverseTranspose(); return retVal; } else if (axisIndex === 1) { const retVal = Matrix3d.createRowValues( - 0, 0, 1, - 0, 1, 0, - -1, 0, 0); + 0, + 0, + 1, + 0, + 1, + 0, + -1, + 0, + 0, + ); retVal.setupInverseTranspose(); return retVal; } else { const retVal = Matrix3d.createRowValues( - 0, -1, 0, - 1, 0, 0, - 0, 0, 1); + 0, + -1, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + ); retVal.setupInverseTranspose(); return retVal; } @@ -1427,8 +1651,12 @@ export class Matrix3d implements BeJSONFunctions { /** Return magnitude of columnX cross columnY. */ public columnXYCrossProductMagnitude(): number { return Geometry.crossProductMagnitude( - this.coffs[0], this.coffs[3], this.coffs[6], - this.coffs[1], this.coffs[4], this.coffs[7], + this.coffs[0], + this.coffs[3], + this.coffs[6], + this.coffs[1], + this.coffs[4], + this.coffs[7], ); } /** Return the X row magnitude */ @@ -1522,16 +1750,29 @@ export class Matrix3d implements BeJSONFunctions { /** Return the cross product of the Z column with the vector parameter. */ public columnZCrossVector(vector: XYZ, result?: Vector3d): Vector3d { return Geometry.crossProductXYZXYZ( - this.coffs[2], this.coffs[5], this.coffs[8], vector.x, vector.y, vector.z, result, + this.coffs[2], + this.coffs[5], + this.coffs[8], + vector.x, + vector.y, + vector.z, + result, ); } /** Set data from xyz parts of Point4d (w part of Point4d ignored) */ public setColumnsPoint4dXYZ(vectorU: Point4d, vectorV: Point4d, vectorW: Point4d) { this.inverseState = InverseMatrixState.unknown; this.setRowValues( - vectorU.x, vectorV.x, vectorW.x, - vectorU.y, vectorV.y, vectorW.y, - vectorU.z, vectorV.z, vectorW.z); + vectorU.x, + vectorV.x, + vectorW.x, + vectorU.y, + vectorV.y, + vectorW.y, + vectorU.z, + vectorV.z, + vectorW.z, + ); } /** * Set entries in one column of the matrix. @@ -1611,13 +1852,18 @@ export class Matrix3d implements BeJSONFunctions { * ``` */ public static createRows(vectorU: Vector3d, vectorV: Vector3d, vectorW: Vector3d, result?: Matrix3d): Matrix3d { - return Matrix3d.createRowValues - ( - vectorU.x, vectorU.y, vectorU.z, - vectorV.x, vectorV.y, vectorV.z, - vectorW.x, vectorW.y, vectorW.z, - result, - ); + return Matrix3d.createRowValues( + vectorU.x, + vectorU.y, + vectorU.z, + vectorV.x, + vectorV.y, + vectorV.z, + vectorW.x, + vectorW.y, + vectorW.z, + result, + ); } /** * Create a matrix that scales along a specified `direction`. This means if you multiply the returned matrix @@ -1642,9 +1888,15 @@ export class Matrix3d implements BeJSONFunctions { const z = unit.z; const a = scale - 1; return Matrix3d.createRowValues( - 1 + a * x * x, a * x * y, a * x * z, - a * y * x, 1 + a * y * y, a * y * z, - a * z * x, a * z * y, 1 + a * z * z, + 1 + a * x * x, + a * x * y, + a * x * z, + a * y * x, + 1 + a * y * y, + a * y * z, + a * z * x, + a * z * y, + 1 + a * z * z, result, ); } @@ -1673,7 +1925,7 @@ export class Matrix3d implements BeJSONFunctions { // Note W * N^T is a 3x3 matrix. By associativity of matrix multiplication: // `U1 = (I - W * N^T / W DOT N) * U0` // and the matrix to do the sweep for any vector in place of U0 is `I - W * N^T / W DOT N`. - const result = Matrix3d.createIdentity(); + const result = Matrix3d.createIdentity(); const dot = sweepVector.dotProduct(planeNormal); const inverse = Geometry.conditionalDivideCoordinate(1.0, -dot); if (inverse !== undefined) { @@ -1683,13 +1935,13 @@ export class Matrix3d implements BeJSONFunctions { return undefined; } /** - * Multiply `matrix * point`, treating the point as a column vector on the right. - * ``` - * equation - * \matrixXY{A}\columnSubXYZ{U} - * ``` - * @return the point result - */ + * Multiply `matrix * point`, treating the point as a column vector on the right. + * ``` + * equation + * \matrixXY{A}\columnSubXYZ{U} + * ``` + * @return the point result + */ public multiplyPoint(point: Point3d, result?: Point3d): Point3d { const x = point.x; const y = point.y; @@ -1726,11 +1978,12 @@ export class Matrix3d implements BeJSONFunctions { * * Each `vector` is updated to be `matrix * vector` */ public multiplyVectorArrayInPlace(data: XYZ[]): void { - for (const v of data) v.set( - this.coffs[0] * v.x + this.coffs[1] * v.y + this.coffs[2] * v.z, - this.coffs[3] * v.x + this.coffs[4] * v.y + this.coffs[5] * v.z, - this.coffs[6] * v.x + this.coffs[7] * v.y + this.coffs[8] * v.z, - ); + for (const v of data) + v.set( + this.coffs[0] * v.x + this.coffs[1] * v.y + this.coffs[2] * v.z, + this.coffs[3] * v.x + this.coffs[4] * v.y + this.coffs[5] * v.z, + this.coffs[6] * v.x + this.coffs[7] * v.y + this.coffs[8] * v.z, + ); } /** Compute `origin - matrix * vector` */ public static xyzMinusMatrixTimesXYZ(origin: XYAndZ, matrix: Matrix3d, vector: XYAndZ, result?: Point3d): Point3d { @@ -1777,7 +2030,12 @@ export class Matrix3d implements BeJSONFunctions { } /** Compute `origin + matrix * vector` where the final vector is given as direct x,y,z coordinates */ public static xyzPlusMatrixTimesCoordinates( - origin: XYZ, matrix: Matrix3d, x: number, y: number, z: number, result?: Point3d, + origin: XYZ, + matrix: Matrix3d, + x: number, + y: number, + z: number, + result?: Point3d, ): Point3d { return Point3d.create( origin.x + matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z, @@ -1802,7 +2060,13 @@ export class Matrix3d implements BeJSONFunctions { * @param result optional preallocated result. */ public static xyzPlusMatrixTimesWeightedCoordinates( - origin: XYZ, matrix: Matrix3d, x: number, y: number, z: number, w: number, result?: Point4d, + origin: XYZ, + matrix: Matrix3d, + x: number, + y: number, + z: number, + w: number, + result?: Point4d, ): Point4d { return Point4d.create( matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z + origin.x * w, @@ -1828,7 +2092,13 @@ export class Matrix3d implements BeJSONFunctions { * @param result optional preallocated result. If length < 4, a new array is returned. */ public static xyzPlusMatrixTimesWeightedCoordinatesToFloat64Array( - origin: XYZ, matrix: Matrix3d, x: number, y: number, z: number, w: number, result?: Float64Array, + origin: XYZ, + matrix: Matrix3d, + x: number, + y: number, + z: number, + w: number, + result?: Float64Array, ): Float64Array { if (!result || result.length < 4) result = new Float64Array(4); @@ -1853,7 +2123,12 @@ export class Matrix3d implements BeJSONFunctions { * @param result optional preallocated result. If length < 3, a new array is returned. */ public static xyzPlusMatrixTimesCoordinatesToFloat64Array( - origin: XYZ, matrix: Matrix3d, x: number, y: number, z: number, result?: Float64Array, + origin: XYZ, + matrix: Matrix3d, + x: number, + y: number, + z: number, + result?: Float64Array, ): Float64Array { if (!result || result.length < 3) result = new Float64Array(3); @@ -2081,7 +2356,8 @@ export class Matrix3d implements BeJSONFunctions { * `f` must be a matrix*matrix operation. Otherwise, the function does not generate the inverse properly. */ private finishInverseCoffs( - f: (factorA: Float64Array, factorB: Float64Array, result: Float64Array) => void, coffA?: Float64Array, + f: (factorA: Float64Array, factorB: Float64Array, result: Float64Array) => void, + coffA?: Float64Array, coffB?: Float64Array, ): void { if (coffA && coffB) { @@ -2105,11 +2381,15 @@ export class Matrix3d implements BeJSONFunctions { public multiplyMatrixMatrix(other: Matrix3d, result?: Matrix3d): Matrix3d { result = result ? result : new Matrix3d(); PackedMatrix3dOps.multiplyMatrixMatrix(this.coffs, other.coffs, result.coffs); - if (this.inverseState === InverseMatrixState.inverseStored - && other.inverseState === InverseMatrixState.inverseStored) + if ( + this.inverseState === InverseMatrixState.inverseStored + && other.inverseState === InverseMatrixState.inverseStored + ) result.finishInverseCoffs((a, b, _result) => PackedMatrix3dOps.multiplyMatrixMatrix(a, b, _result), other.inverseCoffs, this.inverseCoffs); - else if (this.inverseState === InverseMatrixState.singular - || other.inverseState === InverseMatrixState.singular) + else if ( + this.inverseState === InverseMatrixState.singular + || other.inverseState === InverseMatrixState.singular + ) result.inverseState = InverseMatrixState.singular; else result.inverseState = InverseMatrixState.unknown; @@ -2159,7 +2439,11 @@ export class Matrix3d implements BeJSONFunctions { result = result ? result : new Matrix3d(); PackedMatrix3dOps.multiplyMatrixMatrixTranspose(this.coffs, other.coffs, result.coffs); if (this.inverseState === InverseMatrixState.inverseStored && other.inverseState === InverseMatrixState.inverseStored) - result.finishInverseCoffs((a, b, _result) => PackedMatrix3dOps.multiplyMatrixTransposeMatrix(a, b, _result), other.inverseCoffs, this.inverseCoffs); + result.finishInverseCoffs( + (a, b, _result) => PackedMatrix3dOps.multiplyMatrixTransposeMatrix(a, b, _result), + other.inverseCoffs, + this.inverseCoffs, + ); else if (this.inverseState === InverseMatrixState.singular || other.inverseState === InverseMatrixState.singular) result.inverseState = InverseMatrixState.singular; else @@ -2178,7 +2462,11 @@ export class Matrix3d implements BeJSONFunctions { result = result ? result : new Matrix3d(); PackedMatrix3dOps.multiplyMatrixTransposeMatrix(this.coffs, other.coffs, result.coffs); if (this.inverseState === InverseMatrixState.inverseStored && other.inverseState === InverseMatrixState.inverseStored) - result.finishInverseCoffs((a, b, _result) => PackedMatrix3dOps.multiplyMatrixMatrixTranspose(a, b, _result), other.inverseCoffs, this.inverseCoffs); + result.finishInverseCoffs( + (a, b, _result) => PackedMatrix3dOps.multiplyMatrixMatrixTranspose(a, b, _result), + other.inverseCoffs, + this.inverseCoffs, + ); else if (this.inverseState === InverseMatrixState.singular || other.inverseState === InverseMatrixState.singular) result.inverseState = InverseMatrixState.singular; else @@ -2222,7 +2510,7 @@ export class Matrix3d implements BeJSONFunctions { result.inverseState = InverseMatrixState.inverseStored; result.inverseCoffs = PackedMatrix3dOps.copyTransposed(this.inverseCoffs, result.inverseCoffs); } else { - result.inverseState = this.inverseState; // singular or unknown. + result.inverseState = this.inverseState; // singular or unknown. result.inverseCoffs = undefined; } return result; @@ -2268,7 +2556,10 @@ export class Matrix3d implements BeJSONFunctions { * * **Note:** We don't validate row/column numbers. Pass 0/3/6 for row 0/1/2 and pass 0/1/2 for column 0/1/2. */ private static rowColumnDot( - coffA: Float64Array, rowStartA: number, coffB: Float64Array, columnStartB: number, + coffA: Float64Array, + rowStartA: number, + coffB: Float64Array, + columnStartB: number, ): number { return coffA[rowStartA] * coffB[columnStartB] + coffA[rowStartA + 1] * coffB[columnStartB + 3] + @@ -2280,7 +2571,11 @@ export class Matrix3d implements BeJSONFunctions { * * **Note:** We don't validate row/column numbers. Pass 0/3/6 for row 0/1/2 and pass 0/1/2 for column 0/1/2. */ private static indexedRowCrossProduct( - source: Float64Array, rowStart0: number, rowStart1: number, dest: Float64Array, columnStart: number, + source: Float64Array, + rowStart0: number, + rowStart1: number, + dest: Float64Array, + columnStart: number, ): void { dest[columnStart] = source[rowStart0 + 1] * source[rowStart1 + 2] - source[rowStart0 + 2] * source[rowStart1 + 1]; dest[columnStart + 3] = source[rowStart0 + 2] * source[rowStart1] - source[rowStart0] * source[rowStart1 + 2]; @@ -2465,9 +2760,15 @@ export class Matrix3d implements BeJSONFunctions { */ public scale(scale: number, result?: Matrix3d): Matrix3d { return Matrix3d.createRowValues( - this.coffs[0] * scale, this.coffs[1] * scale, this.coffs[2] * scale, - this.coffs[3] * scale, this.coffs[4] * scale, this.coffs[5] * scale, - this.coffs[6] * scale, this.coffs[7] * scale, this.coffs[8] * scale, + this.coffs[0] * scale, + this.coffs[1] * scale, + this.coffs[2] * scale, + this.coffs[3] * scale, + this.coffs[4] * scale, + this.coffs[5] * scale, + this.coffs[6] * scale, + this.coffs[7] * scale, + this.coffs[8] * scale, result, ); } @@ -2480,9 +2781,15 @@ export class Matrix3d implements BeJSONFunctions { */ public scaleColumns(scaleX: number, scaleY: number, scaleZ: number, result?: Matrix3d): Matrix3d { return Matrix3d.createRowValues( - this.coffs[0] * scaleX, this.coffs[1] * scaleY, this.coffs[2] * scaleZ, - this.coffs[3] * scaleX, this.coffs[4] * scaleY, this.coffs[5] * scaleZ, - this.coffs[6] * scaleX, this.coffs[7] * scaleY, this.coffs[8] * scaleZ, + this.coffs[0] * scaleX, + this.coffs[1] * scaleY, + this.coffs[2] * scaleZ, + this.coffs[3] * scaleX, + this.coffs[4] * scaleY, + this.coffs[5] * scaleZ, + this.coffs[6] * scaleX, + this.coffs[7] * scaleY, + this.coffs[8] * scaleZ, result, ); } @@ -2493,18 +2800,30 @@ export class Matrix3d implements BeJSONFunctions { * @param scaleZ scale factor for column 2 */ public scaleColumnsInPlace(scaleX: number, scaleY: number, scaleZ: number) { - this.coffs[0] *= scaleX; this.coffs[1] *= scaleY; this.coffs[2] *= scaleZ; - this.coffs[3] *= scaleX; this.coffs[4] *= scaleY; this.coffs[5] *= scaleZ; - this.coffs[6] *= scaleX; this.coffs[7] *= scaleY; this.coffs[8] *= scaleZ; + this.coffs[0] *= scaleX; + this.coffs[1] *= scaleY; + this.coffs[2] *= scaleZ; + this.coffs[3] *= scaleX; + this.coffs[4] *= scaleY; + this.coffs[5] *= scaleZ; + this.coffs[6] *= scaleX; + this.coffs[7] *= scaleY; + this.coffs[8] *= scaleZ; if (this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined) { // apply reciprocal scales to the ROWS of the inverse const divX = Geometry.conditionalDivideFraction(1.0, scaleX); const divY = Geometry.conditionalDivideFraction(1.0, scaleY); const divZ = Geometry.conditionalDivideFraction(1.0, scaleZ); if (divX !== undefined && divY !== undefined && divZ !== undefined) { - this.inverseCoffs[0] *= divX; this.inverseCoffs[1] *= divX; this.inverseCoffs[2] *= divX; - this.inverseCoffs[3] *= divY; this.inverseCoffs[4] *= divY; this.inverseCoffs[5] *= divY; - this.inverseCoffs[6] *= divZ; this.inverseCoffs[7] *= divZ; this.inverseCoffs[8] *= divZ; + this.inverseCoffs[0] *= divX; + this.inverseCoffs[1] *= divX; + this.inverseCoffs[2] *= divX; + this.inverseCoffs[3] *= divY; + this.inverseCoffs[4] *= divY; + this.inverseCoffs[5] *= divY; + this.inverseCoffs[6] *= divZ; + this.inverseCoffs[7] *= divZ; + this.inverseCoffs[8] *= divZ; } else this.inverseState = InverseMatrixState.singular; } @@ -2518,9 +2837,15 @@ export class Matrix3d implements BeJSONFunctions { */ public scaleRows(scaleX: number, scaleY: number, scaleZ: number, result?: Matrix3d): Matrix3d { return Matrix3d.createRowValues( - this.coffs[0] * scaleX, this.coffs[1] * scaleX, this.coffs[2] * scaleX, - this.coffs[3] * scaleY, this.coffs[4] * scaleY, this.coffs[5] * scaleY, - this.coffs[6] * scaleZ, this.coffs[7] * scaleZ, this.coffs[8] * scaleZ, + this.coffs[0] * scaleX, + this.coffs[1] * scaleX, + this.coffs[2] * scaleX, + this.coffs[3] * scaleY, + this.coffs[4] * scaleY, + this.coffs[5] * scaleY, + this.coffs[6] * scaleZ, + this.coffs[7] * scaleZ, + this.coffs[8] * scaleZ, result, ); } @@ -2531,18 +2856,30 @@ export class Matrix3d implements BeJSONFunctions { * @param scaleZ scale factor for row 2 */ public scaleRowsInPlace(scaleX: number, scaleY: number, scaleZ: number) { - this.coffs[0] *= scaleX; this.coffs[1] *= scaleX; this.coffs[2] *= scaleX; - this.coffs[3] *= scaleY; this.coffs[4] *= scaleY; this.coffs[5] *= scaleY; - this.coffs[6] *= scaleZ; this.coffs[7] *= scaleZ; this.coffs[8] *= scaleZ; + this.coffs[0] *= scaleX; + this.coffs[1] *= scaleX; + this.coffs[2] *= scaleX; + this.coffs[3] *= scaleY; + this.coffs[4] *= scaleY; + this.coffs[5] *= scaleY; + this.coffs[6] *= scaleZ; + this.coffs[7] *= scaleZ; + this.coffs[8] *= scaleZ; if (this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined) { // apply reciprocal scales to the COLUMNs of the inverse const divX = Geometry.conditionalDivideFraction(1.0, scaleX); const divY = Geometry.conditionalDivideFraction(1.0, scaleY); const divZ = Geometry.conditionalDivideFraction(1.0, scaleZ); if (divX !== undefined && divY !== undefined && divZ !== undefined) { - this.inverseCoffs[0] *= divX; this.inverseCoffs[1] *= divY; this.inverseCoffs[2] *= divZ; - this.inverseCoffs[3] *= divX; this.inverseCoffs[4] *= divY; this.inverseCoffs[5] *= divZ; - this.inverseCoffs[6] *= divX; this.inverseCoffs[7] *= divY; this.inverseCoffs[8] *= divZ; + this.inverseCoffs[0] *= divX; + this.inverseCoffs[1] *= divY; + this.inverseCoffs[2] *= divZ; + this.inverseCoffs[3] *= divX; + this.inverseCoffs[4] *= divY; + this.inverseCoffs[5] *= divZ; + this.inverseCoffs[6] *= divX; + this.inverseCoffs[7] *= divY; + this.inverseCoffs[8] *= divZ; } else this.inverseState = InverseMatrixState.singular; } @@ -2631,9 +2968,16 @@ export class Matrix3d implements BeJSONFunctions { const s = y / rxy; // if coordinate is (x,y,0), e.g., Front or Back or Left or Right view (for those 4 views x or y is 0 not both) result.setRowValues( - -s, 0, c, - c, 0, s, - 0, 1, 0); + -s, + 0, + c, + c, + 0, + s, + 0, + 1, + 0, + ); // if coordinate is (x,y,z) and z is not 0, i.e., other views such as Iso or RightIso if (z !== 0.0) { const r = Geometry.hypotenuseXYZ(x, y, z); @@ -2660,8 +3004,7 @@ export class Matrix3d implements BeJSONFunctions { */ public conditionNumber(): number { const determinant = Math.abs(this.determinant()); - const columnMagnitudeSum = - Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[3], this.coffs[6]) + const columnMagnitudeSum = Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[3], this.coffs[6]) + Geometry.hypotenuseXYZ(this.coffs[1], this.coffs[4], this.coffs[7]) + Geometry.hypotenuseXYZ(this.coffs[2], this.coffs[5], this.coffs[8]); return Geometry.safeDivideFraction(determinant, columnMagnitudeSum, 0.0); @@ -2746,7 +3089,8 @@ export class Matrix3d implements BeJSONFunctions { const sumAll = this.sumSquares(); const sumDiagonal = this.sumDiagonalSquares(); const sumOff = Math.abs(sumAll - sumDiagonal); - if (Math.sqrt(sumOff) <= Geometry.smallAngleRadians * (1.0 + Math.sqrt(sumAll)) + if ( + Math.sqrt(sumOff) <= Geometry.smallAngleRadians * (1.0 + Math.sqrt(sumAll)) && Geometry.isSameCoordinate(this.coffs[0], this.coffs[4]) && Geometry.isSameCoordinate(this.coffs[0], this.coffs[8]) ) @@ -2766,7 +3110,7 @@ export class Matrix3d implements BeJSONFunctions { * Test if the matrix is a `rigid` matrix (or `pure rotation`, i.e., columns and rows are unit length and * pairwise perpendicular and determinant is +1). * @param allowMirror whether to widen the test to return true if the matrix is a `mirror` (determinant is -1). - */ + */ public isRigid(allowMirror: boolean = false): boolean { return this.testPerpendicularUnitRowsAndColumns() && (allowMirror || this.determinant() > 0); } @@ -2801,8 +3145,10 @@ export class Matrix3d implements BeJSONFunctions { } else if (q === 1 || q === -1) { count++; // if the rest of this row and column should be 0 ("at" will apply cyclic indexing) - if ((this.at(row + 1, col) !== 0) || (this.at(row + 2, col) !== 0) || - (this.at(row, col + 1) !== 0) || (this.at(row, col + 2) !== 0)) + if ( + (this.at(row + 1, col) !== 0) || (this.at(row + 2, col) !== 0) || + (this.at(row, col + 1) !== 0) || (this.at(row, col + 2) !== 0) + ) return false; } else { // entry is not 0, 1, or -1 return false; @@ -2835,7 +3181,9 @@ export class Matrix3d implements BeJSONFunctions { * * This function internally uses `axisOrderCrossProductsInPlace` to make the matrix rigid. */ public static createRigidFromMatrix3d( - source: Matrix3d, axisOrder: AxisOrder = AxisOrder.XYZ, result?: Matrix3d, + source: Matrix3d, + axisOrder: AxisOrder = AxisOrder.XYZ, + result?: Matrix3d, ): Matrix3d | undefined { result = source.clone(result); if (result.makeRigid(axisOrder)) @@ -2932,14 +3280,12 @@ export class Matrix3d implements BeJSONFunctions { result.x = Matrix3d.computeQuatTerm(props[0][1] + props[1][0], result.y, denom, dSum[0]); result.z = Matrix3d.computeQuatTerm(props[1][2] + props[2][1], result.y, denom, dSum[2]); result.w = Matrix3d.computeQuatTerm(props[0][2] - props[2][0], result.y, denom, dSum[3]); - } else if (maxIndex === 2) { result.z = 0.5 * Math.sqrt(dSum[2]); denom = 1.0 / (4.0 * result.z); result.x = Matrix3d.computeQuatTerm(props[0][2] + props[2][0], result.z, denom, dSum[0]); result.y = Matrix3d.computeQuatTerm(props[1][2] + props[2][1], result.z, denom, dSum[1]); result.w = Matrix3d.computeQuatTerm(props[1][0] - props[0][1], result.z, denom, dSum[3]); - } else { result.w = 0.5 * Math.sqrt(dSum[3]); denom = 1.0 / (4.0 * result.w); diff --git a/core/geometry/src/geometry3d/OrderedRotationAngles.ts b/core/geometry/src/geometry3d/OrderedRotationAngles.ts index 0f58ba7c5f6b..34e0a3698cec 100644 --- a/core/geometry/src/geometry3d/OrderedRotationAngles.ts +++ b/core/geometry/src/geometry3d/OrderedRotationAngles.ts @@ -104,8 +104,14 @@ export class OrderedRotationAngles { * * if xyzRotationIsClockwise is undefined it's set to [false, false, false]. * @param result caller-allocated OrderedRotationAngles */ - public static createRadians(xRadians: number, yRadians: number, zRadians: number, order: AxisOrder, - xyzRotationIsClockwise?: [boolean, boolean, boolean], result?: OrderedRotationAngles): OrderedRotationAngles { + public static createRadians( + xRadians: number, + yRadians: number, + zRadians: number, + order: AxisOrder, + xyzRotationIsClockwise?: [boolean, boolean, boolean], + result?: OrderedRotationAngles, + ): OrderedRotationAngles { if (!xyzRotationIsClockwise) { xyzRotationIsClockwise = [false, false, false]; } @@ -141,8 +147,14 @@ export class OrderedRotationAngles { * * if xyzRotationIsClockwise is undefined it's set to [false, false, false]. * @param result caller-allocated OrderedRotationAngles */ - public static createDegrees(xDegrees: number, yDegrees: number, zDegrees: number, order: AxisOrder, - xyzRotationIsClockwise?: [boolean, boolean, boolean], result?: OrderedRotationAngles): OrderedRotationAngles { + public static createDegrees( + xDegrees: number, + yDegrees: number, + zDegrees: number, + order: AxisOrder, + xyzRotationIsClockwise?: [boolean, boolean, boolean], + result?: OrderedRotationAngles, + ): OrderedRotationAngles { return OrderedRotationAngles.createRadians( Angle.degreesToRadians(xDegrees), Angle.degreesToRadians(yDegrees), @@ -167,8 +179,14 @@ export class OrderedRotationAngles { * * if xyzRotationIsClockwise is undefined it's set to [false, false, false]. * @param result caller-allocated OrderedRotationAngles */ - public static createAngles(xRotation: Angle, yRotation: Angle, zRotation: Angle, order: AxisOrder, - xyzRotationIsClockwise?: [boolean, boolean, boolean], result?: OrderedRotationAngles): OrderedRotationAngles { + public static createAngles( + xRotation: Angle, + yRotation: Angle, + zRotation: Angle, + order: AxisOrder, + xyzRotationIsClockwise?: [boolean, boolean, boolean], + result?: OrderedRotationAngles, + ): OrderedRotationAngles { return OrderedRotationAngles.createRadians( xRotation.radians, yRotation.radians, @@ -187,8 +205,7 @@ export class OrderedRotationAngles { * * In the failure case, if the optional result was supplied, that result will nonetheless be filled with * a set of angles. */ - public static createFromMatrix3d(matrix: Matrix3d, order: AxisOrder, result?: OrderedRotationAngles): - OrderedRotationAngles | undefined { + public static createFromMatrix3d(matrix: Matrix3d, order: AxisOrder, result?: OrderedRotationAngles): OrderedRotationAngles | undefined { // treat vector as columns let m11 = matrix.coffs[0], m12 = matrix.coffs[1], m13 = matrix.coffs[2]; let m21 = matrix.coffs[3], m22 = matrix.coffs[4], m23 = matrix.coffs[5]; @@ -229,7 +246,8 @@ export class OrderedRotationAngles { zRad = 0; } break; - } case AxisOrder.YXZ: { + } + case AxisOrder.YXZ: { xRad = Math.asin(Math.max(-1, Math.min(1, m32))); // limit asin domain to [-1,1] if (Math.abs(m32) < 0.99999) { @@ -240,7 +258,8 @@ export class OrderedRotationAngles { zRad = 0; } break; - } case AxisOrder.ZXY: { + } + case AxisOrder.ZXY: { xRad = Math.asin(Math.max(-1, Math.min(1, -m23))); // limit asin domain to [-1,1] if (Math.abs(m23) < 0.99999) { @@ -251,7 +270,8 @@ export class OrderedRotationAngles { zRad = Math.atan2(-m12, m11); } break; - } case AxisOrder.ZYX: { + } + case AxisOrder.ZYX: { yRad = Math.asin(Math.max(-1, Math.min(1, m13))); // limit asin domain to [-1,1] if (Math.abs(m13) < 0.99999) { @@ -262,7 +282,8 @@ export class OrderedRotationAngles { zRad = Math.atan2(m21, m22); } break; - } case AxisOrder.YZX: { + } + case AxisOrder.YZX: { zRad = Math.asin(Math.max(-1, Math.min(1, -m12))); // limit asin domain to [-1,1] if (Math.abs(m12) < 0.99999) { @@ -273,7 +294,8 @@ export class OrderedRotationAngles { yRad = Math.atan2(-m31, m33); } break; - } case AxisOrder.XZY: { + } + case AxisOrder.XZY: { zRad = Math.asin(Math.max(-1, Math.min(1, m21))); // limit asin domain to [-1,1] if (Math.abs(m21) < 0.99999) { @@ -284,7 +306,8 @@ export class OrderedRotationAngles { yRad = 0; } break; - } default: { + } + default: { xRad = yRad = zRad = 0; } } @@ -307,7 +330,7 @@ export class OrderedRotationAngles { /** * Create a 3x3 rotational matrix from this OrderedRotationAngles. ** math details can be found at docs/learning/geometry/Angle.md - **/ + */ public toMatrix3d(result?: Matrix3d): Matrix3d { const rot = (result !== undefined) ? result : new Matrix3d(); const axisOrder = this.order; @@ -324,39 +347,75 @@ export class OrderedRotationAngles { // the rotation matrix we build below is created using column-based base rotation matrixes if (axisOrder === AxisOrder.XYZ) { rot.setRowValues( - cy * cz, sxcz * sy - cxsz, cxcz * sy + sxsz, - cy * sz, cxcz + sxsz * sy, cxsz * sy - sxcz, - -sy, sx * cy, cx * cy, + cy * cz, + sxcz * sy - cxsz, + cxcz * sy + sxsz, + cy * sz, + cxcz + sxsz * sy, + cxsz * sy - sxcz, + -sy, + sx * cy, + cx * cy, ); } else if (axisOrder === AxisOrder.YXZ) { rot.setRowValues( - cycz - sysz * sx, -cx * sz, cysz * sx + sycz, - sycz * sx + cysz, cx * cz, sysz - cycz * sx, - -cx * sy, sx, cx * cy, + cycz - sysz * sx, + -cx * sz, + cysz * sx + sycz, + sycz * sx + cysz, + cx * cz, + sysz - cycz * sx, + -cx * sy, + sx, + cx * cy, ); } else if (axisOrder === AxisOrder.ZXY) { rot.setRowValues( - cycz + sysz * sx, sycz * sx - cysz, cx * sy, - cx * sz, cx * cz, -sx, - cysz * sx - sycz, cycz * sx + sysz, cx * cy, + cycz + sysz * sx, + sycz * sx - cysz, + cx * sy, + cx * sz, + cx * cz, + -sx, + cysz * sx - sycz, + cycz * sx + sysz, + cx * cy, ); } else if (axisOrder === AxisOrder.ZYX) { rot.setRowValues( - cy * cz, -cy * sz, sy, - sxcz * sy + cxsz, cxcz - sxsz * sy, -sx * cy, - sxsz - cxcz * sy, sxcz + cxsz * sy, cx * cy, + cy * cz, + -cy * sz, + sy, + sxcz * sy + cxsz, + cxcz - sxsz * sy, + -sx * cy, + sxsz - cxcz * sy, + sxcz + cxsz * sy, + cx * cy, ); } else if (axisOrder === AxisOrder.YZX) { rot.setRowValues( - cy * cz, -sz, sy * cz, - sxsy + cxcy * sz, cx * cz, cxsy * sz - sxcy, - sxcy * sz - cxsy, sx * cz, cxcy + sxsy * sz, + cy * cz, + -sz, + sy * cz, + sxsy + cxcy * sz, + cx * cz, + cxsy * sz - sxcy, + sxcy * sz - cxsy, + sx * cz, + cxcy + sxsy * sz, ); } else if (axisOrder === AxisOrder.XZY) { rot.setRowValues( - cy * cz, sxsy - cxcy * sz, cxsy + sxcy * sz, - sz, cx * cz, -sx * cz, - -sy * cz, sxcy + cxsy * sz, cxcy - sxsy * sz, + cy * cz, + sxsy - cxcy * sz, + cxsy + sxcy * sz, + sz, + cx * cz, + -sx * cz, + -sy * cz, + sxcy + cxsy * sz, + cxcy - sxsy * sz, ); } else { rot.setIdentity(); diff --git a/core/geometry/src/geometry3d/Plane3d.ts b/core/geometry/src/geometry3d/Plane3d.ts index 912928c5886a..b2f0b37d0a98 100644 --- a/core/geometry/src/geometry3d/Plane3d.ts +++ b/core/geometry/src/geometry3d/Plane3d.ts @@ -66,7 +66,6 @@ export abstract class Plane3d implements PlaneAltitudeEvaluator { /** * Return a value -1, 0, 1 giving a signed indicator of whether the toleranced altitude of the point is * negative, near zero, or positive. - * */ public classifyAltitude(point: Point3d, tolerance: number = Geometry.smallMetricDistance): -1 | 0 | 1 { return Geometry.split3Way01(this.altitude(point), tolerance); @@ -74,10 +73,12 @@ export abstract class Plane3d implements PlaneAltitudeEvaluator { /** * Return a value -1, 0, 1 giving a signed indicator of whether the toleranced altitude of x,y,z is * negative, near zero, or positive. - * */ public classifyAltitudeXYZ( - x: number, y: number, z: number, tolerance: number = Geometry.smallMetricDistance, + x: number, + y: number, + z: number, + tolerance: number = Geometry.smallMetricDistance, ): -1 | 0 | 1 { return Geometry.split3Way01(this.altitudeXYZ(x, y, z), tolerance); } diff --git a/core/geometry/src/geometry3d/Plane3dByOriginAndUnitNormal.ts b/core/geometry/src/geometry3d/Plane3dByOriginAndUnitNormal.ts index 0b829293c07a..73d83985dc04 100644 --- a/core/geometry/src/geometry3d/Plane3dByOriginAndUnitNormal.ts +++ b/core/geometry/src/geometry3d/Plane3dByOriginAndUnitNormal.ts @@ -7,10 +7,10 @@ * @module CartesianGeometry */ import { AxisOrder, BeJSONFunctions, Geometry } from "../Geometry"; -import { Plane3d } from "./Plane3d"; import { Point4d } from "../geometry4d/Point4d"; import { Angle } from "./Angle"; import { Matrix3d } from "./Matrix3d"; +import { Plane3d } from "./Plane3d"; import { Point3d, Vector3d } from "./Point3dVector3d"; import { Transform } from "./Transform"; import { XAndY } from "./XYZProps"; @@ -67,7 +67,9 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * * Returns undefined if `normal.normalize()` returns undefined. */ public static create( - origin: Point3d, normal: Vector3d, result?: Plane3dByOriginAndUnitNormal, + origin: Point3d, + normal: Vector3d, + result?: Plane3dByOriginAndUnitNormal, ): Plane3dByOriginAndUnitNormal | undefined { if (result) { if (normal.normalize(result._normal) === undefined) @@ -86,7 +88,8 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * * Returns undefined if `source.getUnitNormal()` returns undefined. */ public static createFrom( - source: Plane3d, result?: Plane3dByOriginAndUnitNormal, + source: Plane3d, + result?: Plane3dByOriginAndUnitNormal, ): Plane3dByOriginAndUnitNormal | undefined { if (source instanceof Plane3dByOriginAndUnitNormal) return source.clone(result); @@ -108,7 +111,13 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * * If unable to normalize return undefined. (And if result is given it is left unchanged) */ public static createXYZUVW( - ax: number, ay: number, az: number, ux: number, uy: number, uz: number, result?: Plane3dByOriginAndUnitNormal, + ax: number, + ay: number, + az: number, + ux: number, + uy: number, + uz: number, + result?: Plane3dByOriginAndUnitNormal, ): Plane3dByOriginAndUnitNormal | undefined { const magU = Geometry.hypotenuseXYZ(ux, uy, uz); if (magU < Geometry.smallMetricDistance) @@ -128,7 +137,9 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * * Returns undefined if the normal vector is all zeros. */ public static createOriginAndTargetXY( - origin: XAndY, target: XAndY, result?: Plane3dByOriginAndUnitNormal, + origin: XAndY, + target: XAndY, + result?: Plane3dByOriginAndUnitNormal, ): Plane3dByOriginAndUnitNormal | undefined { const ux = target.x - origin.x; const uy = target.y - origin.y; @@ -139,7 +150,10 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * * Returns undefined if the normal vector is all zeros. */ public static createXYAngle( - x: number, y: number, normalAngleFromX: Angle, result?: Plane3dByOriginAndUnitNormal, + x: number, + y: number, + normalAngleFromX: Angle, + result?: Plane3dByOriginAndUnitNormal, ): Plane3dByOriginAndUnitNormal { if (result) { result._origin.set(x, y, 0.0); @@ -147,7 +161,8 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct return result; } return new Plane3dByOriginAndUnitNormal( - Point3d.create(x, y, 0), Vector3d.create(normalAngleFromX.cos(), normalAngleFromX.sin()), + Point3d.create(x, y, 0), + Vector3d.create(normalAngleFromX.cos(), normalAngleFromX.sin()), ); } /** @@ -157,7 +172,9 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * @param vector any vector in the plane but not parallel to the vector from pointA to pointB */ public static createPointPointVectorInPlane( - pointA: Point3d, pointB: Point3d, vector: Vector3d, + pointA: Point3d, + pointB: Point3d, + vector: Vector3d, ): Plane3dByOriginAndUnitNormal | undefined { const cross = vector.crossProductStartEnd(pointA, pointB); if (cross.tryNormalizeInPlace()) @@ -171,7 +188,9 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * @param pointC any third point in the plane but not on the line of pointA and pointB */ public static createOriginAndTargets( - pointA: Point3d, pointB: Point3d, pointC: Point3d, + pointA: Point3d, + pointB: Point3d, + pointC: Point3d, ): Plane3dByOriginAndUnitNormal | undefined { const cross = pointA.crossProductToPoints(pointB, pointC); if (cross.tryNormalizeInPlace()) @@ -185,7 +204,9 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct * @param vectorC any vector in the plane but not parallel to vectorB */ public static createOriginAndVectors( - pointA: Point3d, vectorB: Vector3d, vectorC: Vector3d, + pointA: Point3d, + vectorB: Vector3d, + vectorC: Vector3d, ): Plane3dByOriginAndUnitNormal | undefined { const cross = vectorB.crossProduct(vectorC); if (cross.tryNormalizeInPlace()) @@ -265,13 +286,17 @@ export class Plane3dByOriginAndUnitNormal extends Plane3d implements BeJSONFunct const result = this.clone(); if (inverse) { transform.multiplyInversePoint3d(result._origin, result._origin); - if (transform.matrix.multiplyTransposeVector(result._normal, result._normal) !== undefined - && result._normal.normalizeInPlace()) + if ( + transform.matrix.multiplyTransposeVector(result._normal, result._normal) !== undefined + && result._normal.normalizeInPlace() + ) return result; } else { transform.multiplyPoint3d(result._origin, result._origin); - if (transform.matrix.multiplyInverseTranspose(result._normal, result._normal) !== undefined - && result._normal.normalizeInPlace()) + if ( + transform.matrix.multiplyInverseTranspose(result._normal, result._normal) !== undefined + && result._normal.normalizeInPlace() + ) return result; } return undefined; diff --git a/core/geometry/src/geometry3d/Plane3dByOriginAndVectors.ts b/core/geometry/src/geometry3d/Plane3dByOriginAndVectors.ts index e4a08969a36c..1c9d8961def8 100644 --- a/core/geometry/src/geometry3d/Plane3dByOriginAndVectors.ts +++ b/core/geometry/src/geometry3d/Plane3dByOriginAndVectors.ts @@ -7,13 +7,13 @@ * @module CartesianGeometry */ import { AxisOrder, BeJSONFunctions, Geometry } from "../Geometry"; -import { Plane3d } from "./Plane3d"; import { Point4d } from "../geometry4d/Point4d"; +import { Matrix3d } from "./Matrix3d"; +import { Plane3d } from "./Plane3d"; import { Point3d, Vector3d } from "./Point3dVector3d"; import { Ray3d } from "./Ray3d"; import { Transform } from "./Transform"; import { XYAndZ } from "./XYZProps"; -import { Matrix3d } from "./Matrix3d"; /** * A Plane3dByOriginAndVectors is an origin and a pair of vectors. @@ -45,7 +45,10 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction } /** Create a new plane from origin and 2 in-plane vectors. */ public static createOriginAndVectors( - origin: Point3d, vectorU: Vector3d, vectorV: Vector3d, result?: Plane3dByOriginAndVectors, + origin: Point3d, + vectorU: Vector3d, + vectorV: Vector3d, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { if (result) { result.origin.setFrom(origin); @@ -92,7 +95,10 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction * @param result optional preexisting result */ public static createFromTransformColumnsXYAndLengths( - transform: Transform, xLength: number | undefined, yLength: number | undefined, result?: Plane3dByOriginAndVectors, + transform: Transform, + xLength: number | undefined, + yLength: number | undefined, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { if (result) { result.origin.setFrom(transform.getOrigin()); @@ -102,7 +108,8 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction result = new Plane3dByOriginAndVectors( transform.getOrigin(), transform.matrix.columnX(), - transform.matrix.columnY()); + transform.matrix.columnY(), + ); } if (xLength !== undefined) result.vectorU.scaleToLength(xLength, result.vectorU); @@ -112,7 +119,10 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction } /** Capture origin and directions in a new plane. */ public static createCapture( - origin: Point3d, vectorU: Vector3d, vectorV: Vector3d, result?: Plane3dByOriginAndVectors, + origin: Point3d, + vectorU: Vector3d, + vectorV: Vector3d, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { if (!result) return new Plane3dByOriginAndVectors(origin, vectorU, vectorV); @@ -124,7 +134,15 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction /** Set all origin and both vectors from direct numeric parameters */ public setOriginAndVectorsXYZ( - x0: number, y0: number, z0: number, ux: number, uy: number, uz: number, vx: number, vy: number, vz: number, + x0: number, + y0: number, + z0: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, ): Plane3dByOriginAndVectors { this.origin.set(x0, y0, z0); this.vectorU.set(ux, uy, uz); @@ -143,15 +161,23 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction } /** Create a new plane from direct numeric parameters */ public static createOriginAndVectorsXYZ( - x0: number, y0: number, z0: number, - ux: number, uy: number, uz: number, - vx: number, vy: number, vz: number, + x0: number, + y0: number, + z0: number, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { if (result) return result.setOriginAndVectorsXYZ(x0, y0, z0, ux, uy, uz, vx, vy, vz); return new Plane3dByOriginAndVectors( - Point3d.create(x0, y0, z0), Vector3d.create(ux, uy, uz), Vector3d.create(vx, vy, vz), + Point3d.create(x0, y0, z0), + Vector3d.create(ux, uy, uz), + Vector3d.create(vx, vy, vz), ); } /** @@ -162,12 +188,21 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction * @param result optional result. */ public static createOriginAndTargets( - origin: Point3d, targetU: Point3d, targetV: Point3d, result?: Plane3dByOriginAndVectors, + origin: Point3d, + targetU: Point3d, + targetV: Point3d, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - origin.x, origin.y, origin.z, - targetU.x - origin.x, targetU.y - origin.y, targetU.z - origin.z, - targetV.x - origin.x, targetV.y - origin.y, targetV.z - origin.z, + origin.x, + origin.y, + origin.z, + targetU.x - origin.x, + targetU.y - origin.y, + targetU.z - origin.z, + targetV.x - origin.x, + targetV.y - origin.y, + targetV.z - origin.z, result, ); } @@ -182,12 +217,21 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction * @param vectorV x,y,z of vectorV */ public static createOriginAndVectorsArrays( - origin: Float64Array, vectorU: Float64Array, vectorV: Float64Array, result?: Plane3dByOriginAndVectors, + origin: Float64Array, + vectorU: Float64Array, + vectorV: Float64Array, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - origin[0], origin[1], origin[2], - vectorU[0], vectorU[1], vectorU[2], - vectorV[0], vectorV[1], vectorV[2], + origin[0], + origin[1], + origin[2], + vectorU[0], + vectorU[1], + vectorU[2], + vectorV[0], + vectorV[1], + vectorV[2], result, ); } @@ -198,7 +242,10 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction * @param vectorV x,y,z,w of vectorV */ public static createOriginAndVectorsWeightedArrays( - originW: Float64Array, vectorUw: Float64Array, vectorVw: Float64Array, result?: Plane3dByOriginAndVectors, + originW: Float64Array, + vectorUw: Float64Array, + vectorVw: Float64Array, + result?: Plane3dByOriginAndVectors, ): Plane3dByOriginAndVectors { const w = originW[3]; result = Plane3dByOriginAndVectors.createXYPlane(result); @@ -216,10 +263,26 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction // Here the X' and its w' are taken from each vectorUw and vectorVw result.origin.set(originW[0] * dw, originW[1] * dw, originW[2] * dw); Vector3d.createAdd2ScaledXYZ( - vectorUw[0], vectorUw[1], vectorUw[2], dw, originW[0], originW[1], originW[2], -au, result.vectorU, + vectorUw[0], + vectorUw[1], + vectorUw[2], + dw, + originW[0], + originW[1], + originW[2], + -au, + result.vectorU, ); Vector3d.createAdd2ScaledXYZ( - vectorVw[0], vectorVw[1], vectorVw[2], dw, originW[0], originW[1], originW[2], -av, result.vectorV, + vectorVw[0], + vectorVw[1], + vectorVw[2], + dw, + originW[0], + originW[1], + originW[2], + -av, + result.vectorV, ); return result; } @@ -358,8 +421,13 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction if (unitNormal === undefined) return 0.0; return Geometry.dotProductXYZXYZ( - (xyz.x - this.origin.x), (xyz.y - this.origin.y), (xyz.z - this.origin.z), - unitNormal.x, unitNormal.y, unitNormal.z); + xyz.x - this.origin.x, + xyz.y - this.origin.y, + xyz.z - this.origin.z, + unitNormal.x, + unitNormal.y, + unitNormal.z, + ); } /** Return signed cartesian altitude perpendicular to the plane. This uses the normalized cross product as normal. */ public altitudeXYZ(x: number, y: number, z: number): number { @@ -367,8 +435,13 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction if (unitNormal === undefined) return 0.0; return Geometry.dotProductXYZXYZ( - (x - this.origin.x), (y - this.origin.y), (z - this.origin.z), - unitNormal.x, unitNormal.y, unitNormal.z); + x - this.origin.x, + y - this.origin.y, + z - this.origin.z, + unitNormal.x, + unitNormal.y, + unitNormal.z, + ); } /** Return signed projection of the input vector to the plane normal. This uses the normalized cross product as normal. */ public velocity(xyzVector: XYAndZ): number { @@ -376,8 +449,13 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction if (unitNormal === undefined) return 0.0; return Geometry.dotProductXYZXYZ( - xyzVector.x, xyzVector.y, xyzVector.z, - unitNormal.x, unitNormal.y, unitNormal.z); + xyzVector.x, + xyzVector.y, + xyzVector.z, + unitNormal.x, + unitNormal.y, + unitNormal.z, + ); } /** Return signed projection of the input vector to the plane normal. This uses the normalized cross product as normal. */ public velocityXYZ(x: number, y: number, z: number): number { @@ -385,8 +463,13 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction if (unitNormal === undefined) return 0.0; return Geometry.dotProductXYZXYZ( - x, y, z, - unitNormal.x, unitNormal.y, unitNormal.z); + x, + y, + z, + unitNormal.x, + unitNormal.y, + unitNormal.z, + ); } /** * Return triple product of homogeneous difference {(xyzw - w * origin)} with vectorU and vectorV. @@ -396,9 +479,16 @@ export class Plane3dByOriginAndVectors extends Plane3d implements BeJSONFunction public weightedAltitude(xyzw: Point4d) { const w = xyzw.w; return Geometry.tripleProduct( - (xyzw.x - this.origin.x * w), (xyzw.y - this.origin.y * w), (xyzw.z - this.origin.z * w), - this.vectorU.x, this.vectorU.y, this.vectorU.z, - this.vectorV.x, this.vectorV.y, this.vectorV.z); + xyzw.x - this.origin.x * w, + xyzw.y - this.origin.y * w, + xyzw.z - this.origin.z * w, + this.vectorU.x, + this.vectorU.y, + this.vectorU.z, + this.vectorV.x, + this.vectorV.y, + this.vectorV.z, + ); } /** * Return the projection of spacePoint onto the plane. diff --git a/core/geometry/src/geometry3d/Point2dArrayCarrier.ts b/core/geometry/src/geometry3d/Point2dArrayCarrier.ts index ee2042b51131..9638d0750230 100644 --- a/core/geometry/src/geometry3d/Point2dArrayCarrier.ts +++ b/core/geometry/src/geometry3d/Point2dArrayCarrier.ts @@ -17,7 +17,7 @@ import { XAndY } from "./XYZProps"; * * The actual array may be replaced by the user as needed. * * When replaced, there is no cached data to be updated. * @public -*/ + */ export class Point2dArrayCarrier extends IndexedXYCollection { /** reference to array being queried. */ public data: Point2d[]; diff --git a/core/geometry/src/geometry3d/Point2dVector2d.ts b/core/geometry/src/geometry3d/Point2dVector2d.ts index a6700b5a21e2..7f62856b8353 100644 --- a/core/geometry/src/geometry3d/Point2dVector2d.ts +++ b/core/geometry/src/geometry3d/Point2dVector2d.ts @@ -158,7 +158,8 @@ export class XY implements XAndY { return Vector2d.create( other.x - this.x, other.y - this.y, - result); + result, + ); } /** Return a unit vector from this point to other */ public unitVectorTo(other: XAndY, result?: Vector2d): Vector2d | undefined { @@ -167,7 +168,11 @@ export class XY implements XAndY { /** Cross product of vectors from origin to targets */ public static crossProductToPoints(origin: XAndY, targetA: XAndY, targetB: XAndY): number { return Geometry.crossProductXYXY( - targetA.x - origin.x, targetA.y - origin.y, targetB.x - origin.x, targetB.y - origin.y); + targetA.x - origin.x, + targetA.y - origin.y, + targetB.x - origin.x, + targetB.y - origin.y, + ); } } @@ -288,7 +293,8 @@ export class Point2d extends XY implements BeJSONFunctions { public plusXY(dx: number = 0, dy: number = 0, result?: Point2d): Point2d { return Point2d.create( this.x + dx, - this.y + dy, result, + this.y + dy, + result, ); } /** Return point + vector * scalar */ @@ -308,8 +314,7 @@ export class Point2d extends XY implements BeJSONFunctions { ); } /** Return point + vectorA * scalarA + vectorB * scalarB + vectorC * scalarC */ - public plus3Scaled(vectorA: XAndY, scalarA: number, vectorB: XAndY, scalarB: number, - vectorC: XAndY, scalarC: number, result?: Point2d): Point2d { + public plus3Scaled(vectorA: XAndY, scalarA: number, vectorB: XAndY, scalarB: number, vectorC: XAndY, scalarC: number, result?: Point2d): Point2d { return Point2d.create( this.x + vectorA.x * scalarA + vectorB.x * scalarB + vectorC.x * scalarC, this.y + vectorA.y * scalarA + vectorB.y * scalarB + vectorC.y * scalarC, @@ -533,11 +538,11 @@ export class Vector2d extends XY implements BeJSONFunctions { } /** * Return a vector computed at fractional position between this vector and vectorB - * @param fraction fractional position. 0 is at `this`. 1 is at `vectorB`. - * True fractions are "between", negatives are "before this", beyond 1 is "beyond vectorB". - * @param vectorB second vector - * @param result optional preallocated result. - */ + * @param fraction fractional position. 0 is at `this`. 1 is at `vectorB`. + * True fractions are "between", negatives are "before this", beyond 1 is "beyond vectorB". + * @param vectorB second vector + * @param result optional preallocated result. + */ public interpolate(fraction: number, vectorB: Vector2d, result?: Vector2d): Vector2d { result = result ? result : new Vector2d(); /* @@ -637,8 +642,12 @@ export class Vector2d extends XY implements BeJSONFunctions { * @param oppositeIsParallel whether to consider diametrically opposed vectors as parallel. * @param options optional radian and distance tolerances. */ - public isParallelTo(other: Vector2d, oppositeIsParallel: boolean = false, - returnValueIfAnInputIsZeroLength: boolean = false, options?: PerpParallelOptions): boolean { + public isParallelTo( + other: Vector2d, + oppositeIsParallel: boolean = false, + returnValueIfAnInputIsZeroLength: boolean = false, + options?: PerpParallelOptions, + ): boolean { const radianSquaredTol: number = options?.radianSquaredTol ?? Geometry.smallAngleRadiansSquared; const distanceSquaredTol: number = options?.distanceSquaredTol ?? Geometry.smallMetricDistanceSquared; const a2 = this.magnitudeSquared(); @@ -663,7 +672,9 @@ export class Vector2d extends XY implements BeJSONFunctions { * @param options optional radian and distance tolerances. */ public isPerpendicularTo( - other: Vector2d, returnValueIfAnInputIsZeroLength: boolean = false, options?: PerpParallelOptions, + other: Vector2d, + returnValueIfAnInputIsZeroLength: boolean = false, + options?: PerpParallelOptions, ): boolean { const radianSquaredTol: number = options?.radianSquaredTol ?? Geometry.smallAngleRadiansSquared; const distanceSquaredTol: number = options?.distanceSquaredTol ?? Geometry.smallMetricDistanceSquared; diff --git a/core/geometry/src/geometry3d/Point3dArrayCarrier.ts b/core/geometry/src/geometry3d/Point3dArrayCarrier.ts index 53cb2ead9ff3..f6c10eb8939a 100644 --- a/core/geometry/src/geometry3d/Point3dArrayCarrier.ts +++ b/core/geometry/src/geometry3d/Point3dArrayCarrier.ts @@ -120,7 +120,10 @@ export class Point3dArrayCarrier extends IndexedReadWriteXYZCollection { * @returns undefined if either index is out of bounds */ public crossProductXYAndZIndexIndex( - origin: XYAndZ, indexA: number, indexB: number, result?: Vector3d, + origin: XYAndZ, + indexA: number, + indexB: number, + result?: Vector3d, ): Vector3d | undefined { if (this.isValidIndex(indexA) && this.isValidIndex(indexB)) return Vector3d.createCrossProductToPoints(origin, this.data[indexA], this.data[indexB], result); @@ -135,7 +138,10 @@ export class Point3dArrayCarrier extends IndexedReadWriteXYZCollection { * @returns return true if indexA, indexB both valid */ public crossProductIndexIndexIndex( - originIndex: number, indexA: number, indexB: number, result?: Vector3d, + originIndex: number, + indexA: number, + indexB: number, + result?: Vector3d, ): Vector3d | undefined { if (this.isValidIndex(originIndex) && this.isValidIndex(indexA) && this.isValidIndex(indexB)) return Vector3d.createCrossProductToPoints(this.data[originIndex], this.data[indexA], this.data[indexB], result); @@ -153,9 +159,15 @@ export class Point3dArrayCarrier extends IndexedReadWriteXYZCollection { const data = this.data; if (this.isValidIndex(originIndex) && this.isValidIndex(indexA) && this.isValidIndex(indexB)) result.addCrossProductToTargetsInPlace( - data[originIndex].x, data[originIndex].y, data[originIndex].z, - data[indexA].x, data[indexA].y, data[indexA].z, - data[indexB].x, data[indexB].y, data[indexB].z, + data[originIndex].x, + data[originIndex].y, + data[originIndex].z, + data[indexA].x, + data[indexA].y, + data[indexA].z, + data[indexB].x, + data[indexB].y, + data[indexB].z, ); } /** Accumulate scale times the x,y,z values at index to the sum. No action if index is out of bounds */ diff --git a/core/geometry/src/geometry3d/Point3dVector3d.ts b/core/geometry/src/geometry3d/Point3dVector3d.ts index 40926f736bfe..4c57a8352b8e 100644 --- a/core/geometry/src/geometry3d/Point3dVector3d.ts +++ b/core/geometry/src/geometry3d/Point3dVector3d.ts @@ -174,7 +174,7 @@ export class XYZ implements XYAndZ { /** * Return true if this and {other + vector*scale} have equal x,y,z parts within Geometry.smallMetricDistance. * * this method is useful in testing "point on ray" without explicitly constructing the projection point - */ + */ public isAlmostEqualPointPlusScaledVector(other: XYAndZ, vector: XYAndZ, scale: number, tol?: number): boolean { return Geometry.isSameCoordinate(this.x, other.x + vector.x * scale, tol) && Geometry.isSameCoordinate(this.y, other.y + vector.y * scale, tol) @@ -358,9 +358,7 @@ export class XYZ implements XYAndZ { } /** Return a multiple of a the (full length) vector from this point to other */ public scaledVectorTo(other: XYAndZ, scale: number, result?: Vector3d): Vector3d { - return Vector3d.create(scale * (other.x - this.x), - scale * (other.y - this.y), - scale * (other.z - this.z), result); + return Vector3d.create(scale * (other.x - this.x), scale * (other.y - this.y), scale * (other.z - this.z), result); } /** * Return a unit vector from this vector to other. Return a 000 vector if the input is too small to normalize. @@ -513,16 +511,24 @@ export class Point3d extends XYZ { */ public crossProductToPoints(pointA: Point3d, pointB: Point3d, result?: Vector3d): Vector3d { return Vector3d.createCrossProduct( - pointA.x - this.x, pointA.y - this.y, pointA.z - this.z, - pointB.x - this.x, pointB.y - this.y, pointB.z - this.z, + pointA.x - this.x, + pointA.y - this.y, + pointA.z - this.z, + pointB.x - this.x, + pointB.y - this.y, + pointB.z - this.z, result, ); } /** Return the magnitude of the cross product of the vectors from this to pointA and pointB */ public crossProductToPointsMagnitude(pointA: Point3d, pointB: Point3d): number { return Geometry.crossProductMagnitude( - pointA.x - this.x, pointA.y - this.y, pointA.z - this.z, - pointB.x - this.x, pointB.y - this.y, pointB.z - this.z, + pointA.x - this.x, + pointA.y - this.y, + pointA.z - this.z, + pointB.x - this.x, + pointB.y - this.y, + pointB.z - this.z, ); } /** @@ -532,9 +538,15 @@ export class Point3d extends XYZ { */ public tripleProductToPoints(pointA: Point3d, pointB: Point3d, pointC: Point3d): number { return Geometry.tripleProduct( - pointA.x - this.x, pointA.y - this.y, pointA.z - this.z, - pointB.x - this.x, pointB.y - this.y, pointB.z - this.z, - pointC.x - this.x, pointC.y - this.y, pointC.z - this.z, + pointA.x - this.x, + pointA.y - this.y, + pointA.z - this.z, + pointB.x - this.x, + pointB.y - this.y, + pointB.z - this.z, + pointC.x - this.x, + pointC.y - this.y, + pointC.z - this.z, ); } /** @@ -568,7 +580,11 @@ export class Point3d extends XYZ { } /** Return a point with independent x,y,z fractional interpolation. */ public interpolateXYZ( - fractionX: number, fractionY: number, fractionZ: number, other: Point3d, result?: Point3d, + fractionX: number, + fractionY: number, + fractionZ: number, + other: Point3d, + result?: Point3d, ): Point3d { return Point3d.create( Geometry.interpolate(this.x, fractionX, other.x), @@ -579,7 +595,10 @@ export class Point3d extends XYZ { } /** Interpolate between points, then add a shift in the xy plane by a fraction of the XY projection perpendicular. */ public interpolatePerpendicularXY( - fraction: number, pointB: Point3d, fractionXYPerp: number, result?: Point3d, + fraction: number, + pointB: Point3d, + fractionXYPerp: number, + result?: Point3d, ): Point3d { result = result ? result : new Point3d(); const vector = pointB.minus(this); @@ -602,15 +621,12 @@ export class Point3d extends XYZ { } /** Return point + vector * scalar */ public plusScaled(vector: XYAndZ, scaleFactor: number, result?: Point3d): Point3d { - return Point3d.create(this.x + vector.x * scaleFactor, - this.y + vector.y * scaleFactor, - this.z + vector.z * scaleFactor, - result, - ); + return Point3d.create(this.x + vector.x * scaleFactor, this.y + vector.y * scaleFactor, this.z + vector.z * scaleFactor, result); } /** Return point + vectorA * scalarA + vectorB * scalarB */ public plus2Scaled(vectorA: XYAndZ, scalarA: number, vectorB: XYZ, scalarB: number, result?: Point3d): Point3d { - return Point3d.create(this.x + vectorA.x * scalarA + vectorB.x * scalarB, + return Point3d.create( + this.x + vectorA.x * scalarA + vectorB.x * scalarB, this.y + vectorA.y * scalarA + vectorB.y * scalarB, this.z + vectorA.z * scalarA + vectorB.z * scalarB, result, @@ -618,7 +634,13 @@ export class Point3d extends XYZ { } /** Return point + vectorA * scalarA + vectorB * scalarB + vectorC * scalarC */ public plus3Scaled( - vectorA: XYAndZ, scalarA: number, vectorB: XYAndZ, scalarB: number, vectorC: XYAndZ, scalarC: number, result?: Point3d, + vectorA: XYAndZ, + scalarA: number, + vectorB: XYAndZ, + scalarB: number, + vectorC: XYAndZ, + scalarC: number, + result?: Point3d, ): Point3d { return Point3d.create( this.x + vectorA.x * scalarA + vectorB.x * scalarB + vectorC.x * scalarC, @@ -644,7 +666,11 @@ export class Point3d extends XYZ { * @param scaleB scale factor for pointB */ public static createAdd2Scaled( - pointA: XYAndZ, scaleA: number, pointB: XYAndZ, scaleB: number, result?: Point3d, + pointA: XYAndZ, + scaleA: number, + pointB: XYAndZ, + scaleB: number, + result?: Point3d, ): Point3d { return Point3d.create( pointA.x * scaleA + pointB.x * scaleB, @@ -662,7 +688,13 @@ export class Point3d extends XYZ { * @param scaleC scale factor for pointC */ public static createAdd3Scaled( - pointA: XYAndZ, scaleA: number, pointB: XYAndZ, scaleB: number, pointC: XYAndZ, scaleC: number, result?: Point3d, + pointA: XYAndZ, + scaleA: number, + pointB: XYAndZ, + scaleB: number, + pointC: XYAndZ, + scaleC: number, + result?: Point3d, ): Point3d { return Point3d.create( pointA.x * scaleA + pointB.x * scaleB + pointC.x * scaleC, @@ -742,7 +774,13 @@ export class Vector3d extends XYZ { * @param result optional result vector. */ public static createCrossProduct( - ux: number, uy: number, uz: number, vx: number, vy: number, vz: number, result?: Vector3d, + ux: number, + uy: number, + uz: number, + vx: number, + vy: number, + vz: number, + result?: Vector3d, ): Vector3d { return Vector3d.create(uy * vz - uz * vy, uz * vx - ux * vz, ux * vy - uy * vx, result); } @@ -759,7 +797,15 @@ export class Vector3d extends XYZ { * @param cz z coordinate of target point c */ public addCrossProductToTargetsInPlace( - ax: number, ay: number, az: number, bx: number, by: number, bz: number, cx: number, cy: number, cz: number, + ax: number, + ay: number, + az: number, + bx: number, + by: number, + bz: number, + cx: number, + cy: number, + cz: number, ) { const ux = bx - ax; const uy = by - ay; @@ -778,8 +824,15 @@ export class Vector3d extends XYZ { * * the magnitude of the vector is twice the area of the triangle. */ public static createCrossProductToPoints(origin: XYAndZ, pointA: XYAndZ, pointB: XYAndZ, result?: Vector3d): Vector3d { - return Vector3d.createCrossProduct(pointA.x - origin.x, pointA.y - origin.y, pointA.z - origin.z, - pointB.x - origin.x, pointB.y - origin.y, pointB.z - origin.z, result); + return Vector3d.createCrossProduct( + pointA.x - origin.x, + pointA.y - origin.y, + pointA.z - origin.z, + pointB.x - origin.x, + pointB.y - origin.y, + pointB.z - origin.z, + result, + ); } /** * Return the NORMALIZED cross product of the vectors from origin to pointA and pointB, or undefined @@ -789,8 +842,15 @@ export class Vector3d extends XYZ { * * the magnitude of the vector is twice the area of the triangle. */ public static createUnitCrossProductToPoints(origin: XYAndZ, pointA: XYAndZ, pointB: XYAndZ, result?: Vector3d): Vector3d | undefined { - const vector = Vector3d.createCrossProduct(pointA.x - origin.x, pointA.y - origin.y, pointA.z - origin.z, - pointB.x - origin.x, pointB.y - origin.y, pointB.z - origin.z, result); + const vector = Vector3d.createCrossProduct( + pointA.x - origin.x, + pointA.y - origin.y, + pointA.z - origin.z, + pointB.x - origin.x, + pointB.y - origin.y, + pointB.z - origin.z, + result, + ); return vector.normalize(); } /** @@ -869,7 +929,13 @@ export class Vector3d extends XYZ { * @param result optional result vector. */ public static createStartEndXYZXYZ( - x0: number, y0: number, z0: number, x1: number, y1: number, z1: number, result?: Vector3d, + x0: number, + y0: number, + z0: number, + x1: number, + y1: number, + z1: number, + result?: Vector3d, ): Vector3d { return this.create(x1 - x0, y1 - y0, z1 - z0, result); } @@ -929,7 +995,7 @@ export class Vector3d extends XYZ { * @param denominator number by which to divide the coordinates of this instance * @param result optional pre-allocated object to return * @return scaled vector, or undefined if `denominator` is exactly zero (in which case instance is untouched). - */ + */ public safeDivideOrNull(denominator: number, result?: Vector3d): Vector3d | undefined { if (denominator !== 0.0) { return this.scale(1.0 / denominator, result); @@ -970,7 +1036,7 @@ export class Vector3d extends XYZ { * Create a normalized vector from the inputs. * @param result optional result * @returns undefined if and only if normalization fails - */ + */ public static createNormalized(x: number = 0, y: number = 0, z: number = 0, result?: Vector3d): Vector3d | undefined { if (undefined === result) result = Vector3d.create(x, y, z); @@ -986,7 +1052,7 @@ export class Vector3d extends XYZ { * @param endPoint end point of vector * @param result optional result * @returns undefined if and only if normalization fails. - */ + */ public static createNormalizedStartEnd(startPoint: XYAndZ, endPoint: XYAndZ, result?: Vector3d): Vector3d | undefined { result = Vector3d.createStartEnd(startPoint, endPoint, result); if (result.normalizeInPlace()) @@ -1003,7 +1069,7 @@ export class Vector3d extends XYZ { * @param target the target vector * @param defaultFraction the returned value in case the magnitude of `target` is too small * @returns the signed length of the projection divided by the length of `target` - * */ + */ public fractionOfProjectionToVector(target: Vector3d, defaultFraction: number = 0): number { /* * Projection vector is ((this.target)/||target||)(target/||target||) = ((this.target)/||target||^2)target @@ -1178,8 +1244,15 @@ export class Vector3d extends XYZ { } /** Return the (strongly typed Vector3d) `thisVector3d + vectorA * scalarA + vectorB * scalarB + vectorC * scalarC` */ - public plus3Scaled(vectorA: XYAndZ, scalarA: number, vectorB: XYAndZ, scalarB: number, vectorC: XYAndZ, scalarC: number, - result?: Vector3d): Vector3d { + public plus3Scaled( + vectorA: XYAndZ, + scalarA: number, + vectorB: XYAndZ, + scalarB: number, + vectorC: XYAndZ, + scalarC: number, + result?: Vector3d, + ): Vector3d { result = result ? result : new Vector3d(); result.x = this.x + vectorA.x * scalarA + vectorB.x * scalarB + vectorC.x * scalarC; result.y = this.y + vectorA.y * scalarA + vectorB.y * scalarB + vectorC.y * scalarC; @@ -1187,32 +1260,47 @@ export class Vector3d extends XYZ { return result; } /** Return the (strongly typed Vector3d) `thisVector3d + vectorA * scalarA + vectorB * scalarB` */ - public static createAdd2Scaled(vectorA: XYAndZ, scaleA: number, vectorB: XYAndZ, scaleB: number, - result?: Vector3d): Vector3d { - return Vector3d.create(vectorA.x * scaleA + vectorB.x * scaleB, + public static createAdd2Scaled(vectorA: XYAndZ, scaleA: number, vectorB: XYAndZ, scaleB: number, result?: Vector3d): Vector3d { + return Vector3d.create( + vectorA.x * scaleA + vectorB.x * scaleB, vectorA.y * scaleA + vectorB.y * scaleB, vectorA.z * scaleA + vectorB.z * scaleB, - result); + result, + ); } /** * Return the (strongly typed Vector3d) `thisVector3d + vectorA * scalarA + vectorB * scalarB` * with all components presented as numbers */ - public static createAdd2ScaledXYZ(ax: number, ay: number, az: number, scaleA: number, - bx: number, by: number, bz: number, scaleB: number, result?: Vector3d): Vector3d { - return Vector3d.create(ax * scaleA + bx * scaleB, - ay * scaleA + by * scaleB, - az * scaleA + bz * scaleB, - result); + public static createAdd2ScaledXYZ( + ax: number, + ay: number, + az: number, + scaleA: number, + bx: number, + by: number, + bz: number, + scaleB: number, + result?: Vector3d, + ): Vector3d { + return Vector3d.create(ax * scaleA + bx * scaleB, ay * scaleA + by * scaleB, az * scaleA + bz * scaleB, result); } /** Return the (strongly typed Vector3d) `thisVector3d + vectorA * scaleA + vectorB * scaleB + vectorC * scaleC` */ public static createAdd3Scaled( - vectorA: XYAndZ, scaleA: number, vectorB: XYAndZ, scaleB: number, vectorC: XYAndZ, scaleC: number, result?: Vector3d, + vectorA: XYAndZ, + scaleA: number, + vectorB: XYAndZ, + scaleB: number, + vectorC: XYAndZ, + scaleC: number, + result?: Vector3d, ): Vector3d { - return Vector3d.create(vectorA.x * scaleA + vectorB.x * scaleB + vectorC.x * scaleC, + return Vector3d.create( + vectorA.x * scaleA + vectorB.x * scaleB + vectorC.x * scaleC, vectorA.y * scaleA + vectorB.y * scaleB + vectorC.y * scaleC, vectorA.z * scaleA + vectorB.z * scaleB + vectorC.z * scaleC, - result); + result, + ); } /** Return vector * scalar */ public scale(scale: number, result?: Vector3d): Vector3d { @@ -1364,7 +1452,13 @@ export class Vector3d extends XYZ { /** Cross product with vector from pointA to pointB */ public crossProductStartEnd(pointA: Point3d, pointB: Point3d, result?: Vector3d): Vector3d { return Vector3d.createCrossProduct( - this.x, this.y, this.z, pointB.x - pointA.x, pointB.y - pointA.y, pointB.z - pointA.z, result, + this.x, + this.y, + this.z, + pointB.x - pointA.x, + pointB.y - pointA.y, + pointB.z - pointA.z, + result, ); } /** Cross product (xy parts only) with vector from pointA to pointB */ @@ -1411,8 +1505,7 @@ export class Vector3d extends XYZ { } /** Return the triple product of the instance, vectorB, and vectorC */ public tripleProduct(vectorB: Vector3d, vectorC: Vector3d): number { - return Geometry.tripleProduct(this.x, this.y, this.z, vectorB.x, vectorB.y, vectorB.z, - vectorC.x, vectorC.y, vectorC.z); + return Geometry.tripleProduct(this.x, this.y, this.z, vectorB.x, vectorB.y, vectorB.z, vectorC.x, vectorC.y, vectorC.z); } /** Return the cross product of the instance and vectorB, using only the x and y parts. */ public crossProductXY(vectorB: Vector3d): number { @@ -1537,7 +1630,7 @@ export class Vector3d extends XYZ { /* * projection of vector 'v' on normal 'n' is given by vProj = [dot(v,n)/||n||^2]*n * and projection of 'v' on the plane is given by 'v - vProj' - */ + */ const thisProj: Vector3d = this.plusScaled(planeNormal, -this.dotProduct(planeNormal) * factor); const vectorBProj: Vector3d = vectorB.plusScaled(planeNormal, -vectorB.dotProduct(planeNormal) * factor); return thisProj.signedRadiansTo(vectorBProj, planeNormal); @@ -1577,8 +1670,12 @@ export class Vector3d extends XYZ { * @param returnValueIfAnInputIsZeroLength if either vector is near zero length, return this value. * @param options optional radian and distance tolerances. */ - public isParallelTo(other: Vector3d, oppositeIsParallel: boolean = false, - returnValueIfAnInputIsZeroLength: boolean = false, options?: PerpParallelOptions): boolean { + public isParallelTo( + other: Vector3d, + oppositeIsParallel: boolean = false, + returnValueIfAnInputIsZeroLength: boolean = false, + options?: PerpParallelOptions, + ): boolean { const radianSquaredTol: number = options?.radianSquaredTol ?? Geometry.smallAngleRadiansSquared; const distanceSquaredTol: number = options?.distanceSquaredTol ?? Geometry.smallMetricDistanceSquared; const a2 = this.magnitudeSquared(); @@ -1603,7 +1700,9 @@ export class Vector3d extends XYZ { * @param options optional radian and distance tolerances. */ public isPerpendicularTo( - other: Vector3d, returnValueIfAnInputIsZeroLength: boolean = false, options?: PerpParallelOptions, + other: Vector3d, + returnValueIfAnInputIsZeroLength: boolean = false, + options?: PerpParallelOptions, ): boolean { const radianSquaredTol: number = options?.radianSquaredTol ?? Geometry.smallAngleRadiansSquared; const distanceSquaredTol: number = options?.distanceSquaredTol ?? Geometry.smallMetricDistanceSquared; diff --git a/core/geometry/src/geometry3d/PointHelpers.ts b/core/geometry/src/geometry3d/PointHelpers.ts index 14cbcc07989f..3ea798be3f04 100644 --- a/core/geometry/src/geometry3d/PointHelpers.ts +++ b/core/geometry/src/geometry3d/PointHelpers.ts @@ -20,13 +20,11 @@ import { Transform } from "./Transform"; import { XAndY, XYAndZ, XYZProps } from "./XYZProps"; /** - * * @param numA first candidate -- presumed 0 or positive * @param numB second candidate -- may be undefined, invalid if outside closed interval 0..numA * @param multiplyBy second candidate multiplier (applied only if candidate is defined) */ function selectOptionalClampedMin(numA: number, numB: number | undefined, multiplyBy: number): number { - if (numB !== undefined) { const numC = numB * multiplyBy; if (numC >= 0 && numC <= numA) @@ -74,7 +72,8 @@ export class NumberArray { public static isAlmostEqual( dataA: number[] | Float64Array | undefined, dataB: number[] | Float64Array | undefined, - tolerance: number = Geometry.smallMetricDistance): boolean { + tolerance: number = Geometry.smallMetricDistance, + ): boolean { if (dataA && dataB) { if (dataA.length !== dataB.length) return false; @@ -301,7 +300,7 @@ export class NumberArray { // compute a convex combination of each byte for (let iByte = 0, shiftBits = 0; iByte < 4; ++iByte, shiftBits += 8) { for (let iTerm = 0; iTerm < numTerms; ++iTerm) { - const fraction = Geometry.clamp(scales[iTerm], 0, 1); // chop slop + const fraction = Geometry.clamp(scales[iTerm], 0, 1); // chop slop const colorComponent = (colors[iTerm] >>> shiftBits) & 0xFF; bytes[iByte] += fraction * colorComponent; } @@ -353,7 +352,6 @@ export class Point2dArray { } return n; } - } /** @@ -394,7 +392,11 @@ export class Point4dArray { * @param result optional destination array. If insufficiently sized, a new array is returned. * @return packed weighted point array */ - public static packPointsAndWeightsToFloat64Array(data: Point3d[] | Float64Array | number[], weights: number[] | Float64Array, result?: Float64Array): Float64Array | undefined { + public static packPointsAndWeightsToFloat64Array( + data: Point3d[] | Float64Array | number[], + weights: number[] | Float64Array, + result?: Float64Array, + ): Float64Array | undefined { let points: Point3d[] | Float64Array | number[]; if (Array.isArray(data) && data[0] instanceof Point3d) { points = data as Point3d[]; @@ -463,8 +465,12 @@ export class Point4dArray { * @param weights output weights (w portion of input) * @param pointFormatter optional xyz formatter. By default, returns a Point3d created from the xyz portion of the input. */ - public static unpackFloat64ArrayToPointsAndWeights(data: Float64Array, points: Point3d[], weights: number[], - pointFormatter: (x: number, y: number, z: number) => any = (x, y, z) => Point3d.create(x, y, z)) { + public static unpackFloat64ArrayToPointsAndWeights( + data: Float64Array, + points: Point3d[], + weights: number[], + pointFormatter: (x: number, y: number, z: number) => any = (x, y, z) => Point3d.create(x, y, z), + ) { points.length = 0; weights.length = 0; for (let i = 0; i + 3 < data.length; i += 4) { @@ -504,16 +510,18 @@ export class Point4dArray { for (let i = 0; i < dataA.length; i++) if (!dataA[i].isAlmostEqual(dataB[i])) return false; - } else { // different types + } else { // different types const points = dataA instanceof Float64Array ? dataB as Point4d[] : dataA; const numbers = dataA instanceof Float64Array ? dataA : dataB as Float64Array; if (numbers.length !== points.length * 4) return false; for (let iPoint = 0; iPoint < points.length; ++iPoint) { - if (!Geometry.isSameCoordinate(points[iPoint].x, numbers[4 * iPoint]) || + if ( + !Geometry.isSameCoordinate(points[iPoint].x, numbers[4 * iPoint]) || !Geometry.isSameCoordinate(points[iPoint].y, numbers[4 * iPoint + 1]) || !Geometry.isSameCoordinate(points[iPoint].z, numbers[4 * iPoint + 2]) || - !Geometry.isSameCoordinate(points[iPoint].w, numbers[4 * iPoint + 3])) + !Geometry.isSameCoordinate(points[iPoint].w, numbers[4 * iPoint + 3]) + ) return false; } } @@ -523,7 +531,11 @@ export class Point4dArray { return (dataA === undefined && dataB === undefined); } /** return true iff all xyzw points' altitudes are within tolerance of the plane.*/ - public static isCloseToPlane(data: Point4d[] | Float64Array, plane: Plane3dByOriginAndUnitNormal, tolerance: number = Geometry.smallMetricDistance): boolean { + public static isCloseToPlane( + data: Point4d[] | Float64Array, + plane: Plane3dByOriginAndUnitNormal, + tolerance: number = Geometry.smallMetricDistance, + ): boolean { if (Array.isArray(data)) { for (const xyzw of data) { if (Math.abs(plane.altitudeXYZW(xyzw.x, xyzw.y, xyzw.z, xyzw.w)) > tolerance) @@ -538,7 +550,6 @@ export class Point4dArray { } return true; } - } /** * The `Point3dArray` class contains static methods that act on arrays of 3d points. @@ -595,7 +606,6 @@ export class Point3dArray { * @param w1 high w weight */ public static evaluateTrilinearWeights(weights: Float64Array, u0: number, u1: number, v0: number, v1: number, w0: number, w1: number) { - weights[0] = u0 * v0 * w0; weights[1] = u1 * v0 * w0; weights[2] = u0 * v1 * w0; @@ -684,10 +694,20 @@ export class Point3dArray { this.evaluateTrilinearWeights(this._weightDV, 1 - u, u, -1, 1, 1 - w, w); this.evaluateTrilinearWeights(this._weightDW, 1 - u, u, 1 - v, v, -1, 1); return Transform.createRowValues( - this.sumWeightedX(this._weightDU, points), this.sumWeightedX(this._weightDV, points), this.sumWeightedX(this._weightDW, points), this.sumWeightedX(this._weightUVW, points), - this.sumWeightedY(this._weightDU, points), this.sumWeightedY(this._weightDV, points), this.sumWeightedY(this._weightDW, points), this.sumWeightedY(this._weightUVW, points), - this.sumWeightedZ(this._weightDU, points), this.sumWeightedZ(this._weightDV, points), this.sumWeightedZ(this._weightDW, points), this.sumWeightedZ(this._weightUVW, points), - result); + this.sumWeightedX(this._weightDU, points), + this.sumWeightedX(this._weightDV, points), + this.sumWeightedX(this._weightDW, points), + this.sumWeightedX(this._weightUVW, points), + this.sumWeightedY(this._weightDU, points), + this.sumWeightedY(this._weightDV, points), + this.sumWeightedY(this._weightDW, points), + this.sumWeightedY(this._weightUVW, points), + this.sumWeightedZ(this._weightDU, points), + this.sumWeightedZ(this._weightDV, points), + this.sumWeightedZ(this._weightDW, points), + this.sumWeightedZ(this._weightUVW, points), + result, + ); } /** unpack from a number array or Float64Array to an array of `Point3d` */ public static unpackNumbersToPoint3dArray(data: Float64Array | number[]): Point3d[] { @@ -777,15 +797,17 @@ export class Point3dArray { for (let i = 0; i < dataA.length; i++) if (!dataA[i].isAlmostEqual(dataB[i])) return false; - } else { // different types + } else { // different types const points = dataA instanceof Float64Array ? dataB as Point3d[] : dataA; const numbers = dataA instanceof Float64Array ? dataA : dataB as Float64Array; if (numbers.length !== points.length * 3) return false; for (let iPoint = 0; iPoint < points.length; ++iPoint) { - if (!Geometry.isSameCoordinate(points[iPoint].x, numbers[3 * iPoint]) || + if ( + !Geometry.isSameCoordinate(points[iPoint].x, numbers[3 * iPoint]) || !Geometry.isSameCoordinate(points[iPoint].y, numbers[3 * iPoint + 1]) || - !Geometry.isSameCoordinate(points[iPoint].z, numbers[3 * iPoint + 2])) + !Geometry.isSameCoordinate(points[iPoint].z, numbers[3 * iPoint + 2]) + ) return false; } } @@ -803,7 +825,9 @@ export class Point3dArray { if (points.length > 0) { for (let i = 0; i < points.length; i++) { points.getPoint3dAtCheckedPointIndex(i, p); - result.x += p.x; result.y += p.y; result.z += p.z; + result.x += p.x; + result.y += p.y; + result.z += p.z; } result.scaleInPlace(1.0 / points.length); } @@ -831,7 +855,12 @@ export class Point3dArray { return result; } /** return the index of the point whose vector from space point has the largest magnitude of cross product with given vector. */ - public static indexOfPointWithMaxCrossProductMagnitude(points: Point3d[], spacePoint: Point3d, vector: Vector3d, farVector: Vector3d): number | undefined { + public static indexOfPointWithMaxCrossProductMagnitude( + points: Point3d[], + spacePoint: Point3d, + vector: Vector3d, + farVector: Vector3d, + ): number | undefined { if (points.length === 0) return undefined; let dMax = -1; @@ -868,7 +897,11 @@ export class Point3dArray { return index; } /** return true iff all points' altitudes are within tolerance of the plane.*/ - public static isCloseToPlane(data: Point3d[] | Float64Array, plane: Plane3dByOriginAndUnitNormal, tolerance: number = Geometry.smallMetricDistance): boolean { + public static isCloseToPlane( + data: Point3d[] | Float64Array, + plane: Plane3dByOriginAndUnitNormal, + tolerance: number = Geometry.smallMetricDistance, + ): boolean { if (Array.isArray(data)) { let xyz; for (xyz of data) { @@ -897,19 +930,14 @@ export class Point3dArray { for (let i = 0; i < n; i++) sum += data[i].distance(data[i + 1]); if (addClosureEdge && n > 0) sum += data[0].distance(data[n]); - } else if (data instanceof Float64Array) { const numXYZ = selectOptionalClampedMin(data.length, maxPointsToUse, 3); let i = 0; - for (; i + 5 < numXYZ; i += 3) { // final i points at final point x - sum += Geometry.hypotenuseXYZ(data[i + 3] - data[i], - data[i + 4] - data[i + 1], - data[i + 5] - data[i + 2]); + for (; i + 5 < numXYZ; i += 3) { // final i points at final point x + sum += Geometry.hypotenuseXYZ(data[i + 3] - data[i], data[i + 4] - data[i + 1], data[i + 5] - data[i + 2]); } if (addClosureEdge && i >= 3) { - sum += Geometry.hypotenuseXYZ(data[0] - data[i], - data[1] - data[i + 1], - data[2] - data[i + 2]); + sum += Geometry.hypotenuseXYZ(data[0] - data[i], data[1] - data[i + 1], data[2] - data[i + 2]); } } return sum; @@ -979,12 +1007,13 @@ export class Point3dArray { for (let k = 1; k < n; k++) result.push(points[i - 1].interpolate(k / n, points[i])); result.push(points[i]); - } return result; } /** Pack isolated x,y,z args as a json `[x,y,z]` */ - private static xyzToArray(x: number, y: number, z: number): number[] { return [x, y, z]; } + private static xyzToArray(x: number, y: number, z: number): number[] { + return [x, y, z]; + } /** * return similarly-structured array, array of arrays, etc, with the lowest level point data specifically structured as arrays of 3 numbers `[1,2,3]` @@ -1069,7 +1098,7 @@ export class Point3dArray { return vectorV.magnitude(); // AC is degenerate; return ||B-A|| if (!extrapolate) { if (fraction > 1.0) - return points[indexB].distance(points[indexC]); // return ||B-C|| + return points[indexB].distance(points[indexC]); // return ||B-C|| if (fraction < 0.0) return vectorV.magnitude(); // return ||B-A|| } @@ -1087,7 +1116,10 @@ export class Point3dArray { * @param addClosurePoint whether to append the first hull point to `hullPoints`. */ public static computeConvexHullXY( - points: Point3d[], hullPoints: Point3d[], insidePoints: Point3d[], addClosurePoint: boolean = false, + points: Point3d[], + hullPoints: Point3d[], + insidePoints: Point3d[], + addClosurePoint: boolean = false, ): void { hullPoints.length = 0; insidePoints.length = 0; diff --git a/core/geometry/src/geometry3d/PointStreaming.ts b/core/geometry/src/geometry3d/PointStreaming.ts index 329aa43dd46d..93cf84da3666 100644 --- a/core/geometry/src/geometry3d/PointStreaming.ts +++ b/core/geometry/src/geometry3d/PointStreaming.ts @@ -23,9 +23,9 @@ import { Range3d } from "./Range"; * @internal */ export class PointStreamXYZHandlerBase { - public startChain(_chainData: MultiLineStringDataVariant, _isLeaf: boolean): void { } - public handleXYZ(_x: number, _y: number, _z: number): void { } - public endChain(_chainData: MultiLineStringDataVariant, _isLeaf: boolean): void { } + public startChain(_chainData: MultiLineStringDataVariant, _isLeaf: boolean): void {} + public handleXYZ(_x: number, _y: number, _z: number): void {} + public endChain(_chainData: MultiLineStringDataVariant, _isLeaf: boolean): void {} } /** Base class for handling points in pairs. * * Callers implement handleXYZXYZ to receive point pairs. @@ -57,7 +57,7 @@ export class PointStreamXYZXYZHandlerBase extends PointStreamXYZHandlerBase { * @param _y1 y coordinate of point 1 * @param _z1 z coordinate of point 1 */ - public handleXYZXYZ(_x0: number, _y0: number, _z0: number, _x1: number, _y1: number, _z1: number): void { } + public handleXYZXYZ(_x0: number, _y0: number, _z0: number, _x1: number, _y1: number, _z1: number): void {} } /** * Concrete class to handle startChain, handleXYZ and endChain calls and return a (one-level deep array of @@ -115,7 +115,6 @@ export class PointStringDeepXYZArrayCollector { private _resultStack: any[]; private _xyzFunction: (x: number, y: number, z: number) => any; /** - * * @param xyzFunction function to map (x,y,z) to the leaf object type in the arrays. */ public constructor(xyzFunction: (x: number, y: number, z: number) => any) { @@ -192,5 +191,4 @@ export class VariantPointDataStream { } return numPoint; } - } diff --git a/core/geometry/src/geometry3d/PolygonOps.ts b/core/geometry/src/geometry3d/PolygonOps.ts index c8d8bacb3ed5..3f3fe7e05434 100644 --- a/core/geometry/src/geometry3d/PolygonOps.ts +++ b/core/geometry/src/geometry3d/PolygonOps.ts @@ -128,7 +128,11 @@ export class PolygonLocationDetailPair { this.detailB = detailB ? detailB : PolygonLocationDetail.create(); } /** Create an instance by capturing inputs */ - public static create(detailA: PolygonLocationDetail, detailB: PolygonLocationDetail, result?: PolygonLocationDetailPair): PolygonLocationDetailPair { + public static create( + detailA: PolygonLocationDetail, + detailB: PolygonLocationDetail, + result?: PolygonLocationDetailPair, + ): PolygonLocationDetailPair { if (!result) return new PolygonLocationDetailPair(detailA, detailB); result.detailA = detailA; @@ -193,9 +197,8 @@ export class CutLoop { this.sortCoordinate0 = a; this.sortCoordinate1 = a + this.sortDelta; } else { - this.sortCoordinate0 = a + this.sortDelta; // and sortDelta is negative !!! + this.sortCoordinate0 = a + this.sortDelta; // and sortDelta is negative !!! this.sortCoordinate1 = a; - } } /** Return @@ -204,10 +207,12 @@ export class CutLoop { * * -1 if other sort limits are strictly contained in opposite direction. */ public containsSortLimits(other: CutLoop): number { - if (other.sortCoordinate0 >= this.sortCoordinate1 + if ( + other.sortCoordinate0 >= this.sortCoordinate1 || other.sortCoordinate0 <= this.sortCoordinate0 || other.sortCoordinate1 <= this.sortCoordinate0 - || other.sortCoordinate1 >= this.sortCoordinate1) + || other.sortCoordinate1 >= this.sortCoordinate1 + ) return 0; return this.sortDelta * other.sortDelta > 0 ? 1 : -1; } @@ -229,12 +234,15 @@ export class CutLoop { /** Return first point coordinates. * * For type checking, assume array is not empty. */ - public front(result?: Point3d): Point3d { return this.xyz.front(result)!; } + public front(result?: Point3d): Point3d { + return this.xyz.front(result)!; + } /** Return last point coordinates. * * For type checking, assume array is not empty. */ - public back(result?: Point3d): Point3d { return this.xyz.back(result)!; } - + public back(result?: Point3d): Point3d { + return this.xyz.back(result)!; + } } /** * Context to hold an array of input loops and apply sort logic. @@ -295,7 +303,6 @@ export class CutLoopMergeContext { for (const loop of this.inputLoops) loop.setSortCoordinates(sortRay); this.inputLoops.sort((loopA, loopB) => CutLoop.sortFunction(loopA, loopB)); - } } /** @@ -319,7 +326,7 @@ export class CutLoopMergeContext { if (!topOfStack.isNotch) outputs.push(topOfStack); stack.pop(); - continue; // a larger topOfStack may have appeared ! + continue; // a larger topOfStack may have appeared ! candidate.isNotch = false; } else if (containment === 1) { candidate.isNotch = false; @@ -435,15 +442,45 @@ export class PolygonOps { /** These values are the integrated area moment products [xx,xy,xz, x] * for a right triangle in the first quadrant at the origin -- (0,0),(1,0),(0,1) */ - private static readonly _triangleMomentWeights = Matrix4d.createRowValues(2.0 / 24.0, 1.0 / 24.0, 0, 4.0 / 24.0, 1.0 / 24.0, 2.0 / 24.0, 0, 4.0 / 24.0, 0, 0, 0, 0, 4.0 / 24.0, 4.0 / 24.0, 0, 12.0 / 24.0); + private static readonly _triangleMomentWeights = Matrix4d.createRowValues( + 2.0 / 24.0, + 1.0 / 24.0, + 0, + 4.0 / 24.0, + 1.0 / 24.0, + 2.0 / 24.0, + 0, + 4.0 / 24.0, + 0, + 0, + 0, + 0, + 4.0 / 24.0, + 4.0 / 24.0, + 0, + 12.0 / 24.0, + ); /** These values are the integrated volume moment products [xx,xy,xz, x, yx,yy,yz,y, zx,zy,zz,z,x,y,z,1] * for a tetrahedron in the first quadrant at the origin -- (0,00),(1,0,0),(0,1,0),(0,0,1) */ private static readonly _tetrahedralMomentWeights = Matrix4d.createRowValues( - 1.0 / 60.0, 1.0 / 120, 1.0 / 120, 1.0 / 24.0, - 1.0 / 120, 1.0 / 60.0, 1.0 / 120, 1.0 / 24.0, - 1.0 / 120, 1.0 / 120, 1.0 / 60.0, 1.0 / 24.0, - 1.0 / 24.0, 1.0 / 24.0, 1.0 / 24.0, 1.0 / 6.0); + 1.0 / 60.0, + 1.0 / 120, + 1.0 / 120, + 1.0 / 24.0, + 1.0 / 120, + 1.0 / 60.0, + 1.0 / 120, + 1.0 / 24.0, + 1.0 / 120, + 1.0 / 120, + 1.0 / 60.0, + 1.0 / 24.0, + 1.0 / 24.0, + 1.0 / 24.0, + 1.0 / 24.0, + 1.0 / 6.0, + ); // statics for shared reuse. // many methods use these. // only use them in "leaf" methods that are certain not to call other users . . . @@ -543,7 +580,6 @@ export class PolygonOps { return undefined; } if (n >= 3) { - const areaNormal = Vector3d.createZero(); // This will work with or without closure edge. If closure is given, the last vector is 000. for (let i = 2; i < n; i++) { @@ -563,7 +599,7 @@ export class PolygonOps { for (let i = 2; i < n; i++) { points.vectorXYAndZIndex(origin, i, vector1); cross = vector0.crossProduct(vector1, cross); - signedTriangleArea = areaNormal.dotProduct(cross); // well, actually twice the area. + signedTriangleArea = areaNormal.dotProduct(cross); // well, actually twice the area. normalSum.addInPlace(cross); // this grows to twice the area const b = signedTriangleArea / 6.0; centroidSum.plus2Scaled(vector0, b, vector1, b, centroidSum); @@ -619,7 +655,7 @@ export class PolygonOps { result.setZero(); let n = points.length; if (n > 1 && points.getPoint3dAtUncheckedPointIndex(0).isExactEqual(points.getPoint3dAtUncheckedPointIndex(n - 1))) - --n; // ignore closure point + --n; // ignore closure point if (n === 3) { points.crossProductIndexIndexIndex(0, 1, 2, result); return result.normalizeInPlace(); @@ -665,9 +701,13 @@ export class PolygonOps { * * `frameType===2` has xy vectors in the plane of the polygon, plus a unit normal z. (Used for area integrals) * * `frameType===3` has vectors from origin to 3 points in the triangle. (Used for volume integrals) */ - private static addSecondMomentTransformedProducts(firstQuadrantMoments: Matrix4d, points: IndexedXYZCollection, origin: Point3d, + private static addSecondMomentTransformedProducts( + firstQuadrantMoments: Matrix4d, + points: IndexedXYZCollection, + origin: Point3d, frameType: 2 | 3, - moments: Matrix4d) { + moments: Matrix4d, + ) { const unitNormal = PolygonOps._normal; if (PolygonOps.unitNormal(points, unitNormal)) { // The direction of the normal makes the various detJ values positive or negative so that non-convex polygons @@ -745,7 +785,7 @@ export class PolygonOps { return this.isConvex(new Point3dArrayCarrier(polygon)); let n = polygon.length; if (n > 1 && polygon.getPoint3dAtUncheckedPointIndex(0).isExactEqual(polygon.getPoint3dAtUncheckedPointIndex(n - 1))) - --n; // ignore closure point + --n; // ignore closure point const normal = Vector3d.create(); if (!this.unitNormal(polygon, normal)) return false; @@ -817,7 +857,14 @@ export class PolygonOps { i1 = i0 + 1; if (i1 >= n) i1 = 0; - if (context.tryStartEdge(points.getXAtUncheckedPointIndex(i0), points.getYAtUncheckedPointIndex(i0), points.getXAtUncheckedPointIndex(i1), points.getYAtUncheckedPointIndex(i1))) { + if ( + context.tryStartEdge( + points.getXAtUncheckedPointIndex(i0), + points.getYAtUncheckedPointIndex(i0), + points.getXAtUncheckedPointIndex(i1), + points.getYAtUncheckedPointIndex(i1), + ) + ) { iLast = i1; break; } @@ -840,7 +887,10 @@ export class PolygonOps { * @param outwardNormal * @return the number of loops reversed. */ - public static orientLoopsCCWForOutwardNormalInPlace(loops: IndexedReadWriteXYZCollection | IndexedReadWriteXYZCollection[], outwardNormal: Vector3d): number { + public static orientLoopsCCWForOutwardNormalInPlace( + loops: IndexedReadWriteXYZCollection | IndexedReadWriteXYZCollection[], + outwardNormal: Vector3d, + ): number { if (loops instanceof IndexedXYZCollection) return this.orientLoopsCCWForOutwardNormalInPlace([loops], outwardNormal); const unitNormal = Vector3d.create(); @@ -879,7 +929,10 @@ export class PolygonOps { * @param defaultNormal optional normal for the loops, if known * @see [[sortOuterAndHoleLoopsXY]] */ - public static sortOuterAndHoleLoops(loops: IndexedReadWriteXYZCollection[], defaultNormal: Vector3d | undefined): IndexedReadWriteXYZCollection[][] { + public static sortOuterAndHoleLoops( + loops: IndexedReadWriteXYZCollection[], + defaultNormal: Vector3d | undefined, + ): IndexedReadWriteXYZCollection[][] { const localToWorld = FrameBuilder.createRightHandedFrame(defaultNormal, loops); const worldToLocal = localToWorld?.inverse(); @@ -923,8 +976,13 @@ export class PolygonOps { * * `d.code` classifies the closest point as a vertex (`PolygonLocation.OnPolygonVertex`) or as a point on an edge (`PolygonLocation.OnPolygonEdgeInterior`). * * `d.a` is the distance from testPoint to the closest point. * * `d.v` can be used to classify p (if p and polygon are coplanar): if n is the polygon normal then `d.v.dotProduct(n)` is +/-/0 if and only if p is inside/outside/on the polygon. - */ - public static closestPointOnBoundary(polygon: Point3d[] | IndexedXYZCollection, testPoint: Point3d, tolerance: number = Geometry.smallMetricDistance, result?: PolygonLocationDetail): PolygonLocationDetail { + */ + public static closestPointOnBoundary( + polygon: Point3d[] | IndexedXYZCollection, + testPoint: Point3d, + tolerance: number = Geometry.smallMetricDistance, + result?: PolygonLocationDetail, + ): PolygonLocationDetail { if (!(polygon instanceof IndexedXYZCollection)) return this.closestPointOnBoundary(new Point3dArrayCarrier(polygon), testPoint, tolerance, result); @@ -939,7 +997,7 @@ export class PolygonOps { result = PolygonLocationDetail.create(result); if (0 === numPoints) - return result; // invalid + return result; // invalid if (1 === numPoints) { polygon.getPoint3dAtUncheckedPointIndex(0, result.point); result.a = result.point.distance(testPoint); @@ -963,7 +1021,7 @@ export class PolygonOps { const vDotV = polygon.distanceSquaredIndexXYAndZ(iBase, testPoint)!; const uDotV = polygon.dotProductIndexIndexXYAndZ(iBase, iNext, testPoint)!; - const edgeParam = uDotV / uDotU; // param of projection of testPoint onto this edge + const edgeParam = uDotV / uDotU; // param of projection of testPoint onto this edge if (edgeParam <= 0.0) { // testPoint projects to/before edge start const distToStart2 = vDotV; @@ -989,7 +1047,7 @@ export class PolygonOps { minDist2 = distToStart2; } } - } else if (edgeParam <= 1.0) { // testPoint projects inside edge, or to edge end + } else if (edgeParam <= 1.0) { // testPoint projects inside edge, or to edge end const projDist2 = vDotV - edgeParam * edgeParam * uDotU; if (projDist2 <= distTol2) { // testPoint is on edge; we are done @@ -1034,7 +1092,7 @@ export class PolygonOps { result.closestEdgeParam = edgeParam; minDist2 = projDist2; } - } else { // edgeParam > 1.0 + } else { // edgeParam > 1.0 // NOOP: testPoint projects beyond edge end, handled by next edge } iPrev = iBase; @@ -1055,17 +1113,30 @@ export class PolygonOps { * * `d.code` classifies the closest point: `PolygonLocation.OnPolygonVertex`, `PolygonLocation.OnPolygonEdgeInterior`, `PolygonLocation.InsidePolygonProjectsToVertex`, or `PolygonLocation.InsidePolygonProjectsToEdgeInterior`. * * `d.a` is the distance from testPoint to the closest point. */ - public static closestPoint(polygon: Point3d[] | IndexedXYZCollection, testPoint: Point3d, tolerance: number = Geometry.smallMetricDistance, result?: PolygonLocationDetail): PolygonLocationDetail { + public static closestPoint( + polygon: Point3d[] | IndexedXYZCollection, + testPoint: Point3d, + tolerance: number = Geometry.smallMetricDistance, + result?: PolygonLocationDetail, + ): PolygonLocationDetail { if (!(polygon instanceof IndexedXYZCollection)) return this.closestPoint(new Point3dArrayCarrier(polygon), testPoint, tolerance, result); if (!this.unitNormal(polygon, this._normal)) - return PolygonLocationDetail.create(result); // invalid - const polygonPlane = this._workPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(polygon.getXAtUncheckedPointIndex(0), polygon.getYAtUncheckedPointIndex(0), polygon.getZAtUncheckedPointIndex(0), this._normal.x, this._normal.y, this._normal.z, this._workPlane)!; + return PolygonLocationDetail.create(result); // invalid + const polygonPlane = this._workPlane = Plane3dByOriginAndUnitNormal.createXYZUVW( + polygon.getXAtUncheckedPointIndex(0), + polygon.getYAtUncheckedPointIndex(0), + polygon.getZAtUncheckedPointIndex(0), + this._normal.x, + this._normal.y, + this._normal.z, + this._workPlane, + )!; const planePoint = this._workXYZ = polygonPlane.projectPointToPlane(testPoint, this._workXYZ); result = this.closestPointOnBoundary(polygon, planePoint, tolerance, result); if (result.isValid) { const dot = result.v.dotProduct(this._normal); - if (dot > 0.0) { // planePoint is inside, so return it instead of the closest boundary point + if (dot > 0.0) { // planePoint is inside, so return it instead of the closest boundary point result.point.setFrom(planePoint); if (PolygonLocation.OnPolygonVertex === result.code) result.code = PolygonLocation.InsidePolygonProjectsToVertex; @@ -1098,12 +1169,25 @@ export class PolygonOps { * * `d.a` is the ray intersection parameter. If `d.a` >= 0, the ray intersects the plane of the polygon. * * `d.edgeIndex` and `d.edgeParam` specify the location of the closest point on the polygon to the intersection, within `distTol`. */ - public static intersectRay3d(polygon: Point3d[] | IndexedXYZCollection, ray: Ray3d, tolerance: number = Geometry.smallMetricDistance, result?: PolygonLocationDetail): PolygonLocationDetail { + public static intersectRay3d( + polygon: Point3d[] | IndexedXYZCollection, + ray: Ray3d, + tolerance: number = Geometry.smallMetricDistance, + result?: PolygonLocationDetail, + ): PolygonLocationDetail { if (!(polygon instanceof IndexedXYZCollection)) return this.intersectRay3d(new Point3dArrayCarrier(polygon), ray, tolerance, result); if (!this.unitNormal(polygon, this._normal)) return PolygonLocationDetail.create(result); // invalid - this._workPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(polygon.getXAtUncheckedPointIndex(0), polygon.getYAtUncheckedPointIndex(0), polygon.getZAtUncheckedPointIndex(0), this._normal.x, this._normal.y, this._normal.z, this._workPlane)!; + this._workPlane = Plane3dByOriginAndUnitNormal.createXYZUVW( + polygon.getXAtUncheckedPointIndex(0), + polygon.getYAtUncheckedPointIndex(0), + polygon.getZAtUncheckedPointIndex(0), + this._normal.x, + this._normal.y, + this._normal.z, + this._workPlane, + )!; const intersectionPoint = this._workXYZ = Point3d.createZero(this._workXYZ); const rayParam = ray.intersectionWithPlane(this._workPlane, intersectionPoint); if (undefined === rayParam) @@ -1139,7 +1223,13 @@ export class PolygonOps { * * `d.edgeIndex` and `d.edgeParam` specify the location of the closest point on the polygon to the intersection, within `distTol`. * @see intersectRay3d */ - public static intersectSegment(polygon: Point3d[] | IndexedXYZCollection, point0: Point3d, point1: Point3d, tolerance: number = Geometry.smallMetricDistance, result?: PolygonLocationDetail): PolygonLocationDetail { + public static intersectSegment( + polygon: Point3d[] | IndexedXYZCollection, + point0: Point3d, + point1: Point3d, + tolerance: number = Geometry.smallMetricDistance, + result?: PolygonLocationDetail, + ): PolygonLocationDetail { this._workRay = Ray3d.createStartEnd(point0, point1, this._workRay); return this.intersectRay3d(polygon, this._workRay, tolerance, result); } @@ -1153,15 +1243,27 @@ export class PolygonOps { * @param result optional pre-allocated result * @returns x: signed projection distance of `point` to the edge, y: edge parameter of the projection */ - private static computeEdgeDataXY(polygon: IndexedXYZCollection, edgeStartVertexIndex: number, point: XYAndZ, edgeOutwardUnitNormal: Vector3d, tolerance: number = Geometry.smallMetricDistance, result?: Point2d): Point2d { + private static computeEdgeDataXY( + polygon: IndexedXYZCollection, + edgeStartVertexIndex: number, + point: XYAndZ, + edgeOutwardUnitNormal: Vector3d, + tolerance: number = Geometry.smallMetricDistance, + result?: Point2d, + ): Point2d { const i0 = edgeStartVertexIndex % polygon.length; const i1 = (i0 + 1) % polygon.length; - polygon.vectorIndexIndex(i0, i1, edgeOutwardUnitNormal)!.unitPerpendicularXY(edgeOutwardUnitNormal).negate(edgeOutwardUnitNormal); // z is zero + polygon.vectorIndexIndex(i0, i1, edgeOutwardUnitNormal)!.unitPerpendicularXY(edgeOutwardUnitNormal).negate(edgeOutwardUnitNormal); // z is zero const hypDeltaX = polygon.getXAtUncheckedPointIndex(i0) - point.x; const hypDeltaY = polygon.getYAtUncheckedPointIndex(i0) - point.y; let projDist = Geometry.dotProductXYXY(hypDeltaX, hypDeltaY, edgeOutwardUnitNormal.x, edgeOutwardUnitNormal.y); const edgeDist = Geometry.crossProductXYXY(hypDeltaX, hypDeltaY, edgeOutwardUnitNormal.x, edgeOutwardUnitNormal.y); - const edgeLength = Geometry.distanceXYXY(polygon.getXAtUncheckedPointIndex(i0), polygon.getYAtUncheckedPointIndex(i0), polygon.getXAtUncheckedPointIndex(i1), polygon.getYAtUncheckedPointIndex(i1)); + const edgeLength = Geometry.distanceXYXY( + polygon.getXAtUncheckedPointIndex(i0), + polygon.getYAtUncheckedPointIndex(i0), + polygon.getXAtUncheckedPointIndex(i1), + polygon.getYAtUncheckedPointIndex(i1), + ); let edgeParam = Geometry.safeDivideFraction(edgeDist, edgeLength, 0.0); if (Geometry.isSameCoordinate(0.0, projDist, tolerance)) projDist = 0.0; @@ -1183,7 +1285,16 @@ export class PolygonOps { * @param coords pre-allocated barycentric coordinate array to return, assumed to have length at least `polygon.length` * @returns barycentric coordinates, or undefined if not on either edge */ - private static convexBarycentricCoordinatesOnEdge(polygon: IndexedXYZCollection, iPrev: number, prevNormal: Vector3d, prevProj: XAndY, i: number, normal: Vector3d, proj: XAndY, coords: number[]): number[] | undefined { + private static convexBarycentricCoordinatesOnEdge( + polygon: IndexedXYZCollection, + iPrev: number, + prevNormal: Vector3d, + prevProj: XAndY, + i: number, + normal: Vector3d, + proj: XAndY, + coords: number[], + ): number[] | undefined { // ignore degenerate edges const pointIsOnPrevEdge = !prevNormal.isZero && (0.0 === prevProj.x) && Geometry.isIn01(prevProj.y); const pointIsOnEdge = !normal.isZero && (0.0 === proj.x) && Geometry.isIn01(proj.y); @@ -1211,7 +1322,7 @@ export class PolygonOps { coords[i1] = edgeParam; return coords; } - return undefined; // not on edge + return undefined; // not on edge } // cspell:word CAGD @@ -1222,19 +1333,30 @@ export class PolygonOps { * @return barycentric coordinates of the interior point, or undefined if invalid polygon or exterior point. Length is same as `polygon.length`. * @see BarycentricTriangle.pointToFraction */ - public static convexBarycentricCoordinates(polygon: Point3d[] | IndexedXYZCollection, point: Point3d, tolerance: number = Geometry.smallMetricDistance): number[] | undefined { + public static convexBarycentricCoordinates( + polygon: Point3d[] | IndexedXYZCollection, + point: Point3d, + tolerance: number = Geometry.smallMetricDistance, + ): number[] | undefined { // cf. "Barycentric Coordinates for Convex Sets", by Warren et al., CAGD (2003) if (Array.isArray(polygon)) return this.convexBarycentricCoordinates(new Point3dArrayCarrier(polygon), point); let n = polygon.length; while (n > 1 && polygon.getPoint3dAtUncheckedPointIndex(0).isExactEqual(polygon.getPoint3dAtUncheckedPointIndex(n - 1))) - --n; // ignore closure point(s) + --n; // ignore closure point(s) if (n < 3 || !PolygonOps.unitNormal(polygon, this._normal)) return undefined; const localToWorld = this._workMatrix3d = Matrix3d.createRigidHeadsUp(this._normal, AxisOrder.ZXY, this._workMatrix3d); const polygonXY = new GrowableXYZArray(n); for (let i = 0; i < n; ++i) - polygonXY.push(localToWorld.multiplyInverseXYZAsPoint3d(polygon.getXAtUncheckedPointIndex(i), polygon.getYAtUncheckedPointIndex(i), polygon.getZAtUncheckedPointIndex(i), this._workXYZ)!); + polygonXY.push( + localToWorld.multiplyInverseXYZAsPoint3d( + polygon.getXAtUncheckedPointIndex(i), + polygon.getYAtUncheckedPointIndex(i), + polygon.getZAtUncheckedPointIndex(i), + this._workXYZ, + )!, + ); const pointXY = this._workXYZ = localToWorld.multiplyInverseXYZAsPoint3d(point.x, point.y, point.z, this._workXYZ)!; // now we know polygon orientation is ccw, its last edge has positive length, and we can ignore z-coords let iPrev = n - 1; @@ -1250,10 +1372,24 @@ export class PolygonOps { let coordSum = 0.0; for (let i = 0; i < n; ++i) { const outwardUnitNormalOfEdge = Vector3d.createFrom(outwardUnitNormalOfLastEdge, this._vector2); - const projToEdge = this._workXY2 = (i < n - 1) ? this.computeEdgeDataXY(polygonXY, i, pointXY, outwardUnitNormalOfEdge, tolerance, this._workXY2) : Point2d.createFrom(projToLastEdge, this._workXY2); + const projToEdge = this._workXY2 = (i < n - 1) + ? this.computeEdgeDataXY(polygonXY, i, pointXY, outwardUnitNormalOfEdge, tolerance, this._workXY2) + : Point2d.createFrom(projToLastEdge, this._workXY2); if (projToEdge.x < 0.0) return undefined; // point is outside polygon, or polygon is nonconvex - if (undefined !== this.convexBarycentricCoordinatesOnEdge(polygonXY, iPrev, outwardUnitNormalOfPrevEdge, projToPrevEdge, i, outwardUnitNormalOfEdge, projToEdge, coords)) + if ( + undefined !== + this.convexBarycentricCoordinatesOnEdge( + polygonXY, + iPrev, + outwardUnitNormalOfPrevEdge, + projToPrevEdge, + i, + outwardUnitNormalOfEdge, + projToEdge, + coords, + ) + ) return coords; // point is on vertex or edge; we are done if (outwardUnitNormalOfEdge.x === 0.0 && outwardUnitNormalOfEdge.y === 0.0) continue; // edge is degenerate; coords[i] = 0; keep previous edge data @@ -1305,7 +1441,10 @@ export class PolygonOps { * @param polygon input polygon * @param tolerance closure distance tolerance */ - public static ensureClosed(polygon: Point3d[] | IndexedXYZCollection, tolerance: number = Geometry.smallMetricDistance): Point3d[] | IndexedXYZCollection { + public static ensureClosed( + polygon: Point3d[] | IndexedXYZCollection, + tolerance: number = Geometry.smallMetricDistance, + ): Point3d[] | IndexedXYZCollection { if (polygon.length >= 2) { let forceClosure = false; if (polygon instanceof IndexedXYZCollection) @@ -1371,10 +1510,13 @@ export class IndexedXYZCollectionPolygonOps { * @param xyzNegative array to receive outside part * @param altitudeRange min and max altitudes encountered. */ - public static splitConvexPolygonInsideOutsidePlane(plane: PlaneAltitudeEvaluator, + public static splitConvexPolygonInsideOutsidePlane( + plane: PlaneAltitudeEvaluator, xyz: IndexedXYZCollection, xyzPositive: IndexedReadWriteXYZCollection, - xyzNegative: IndexedReadWriteXYZCollection, altitudeRange: Range1d) { + xyzNegative: IndexedReadWriteXYZCollection, + altitudeRange: Range1d, + ) { const xyz0 = IndexedXYZCollectionPolygonOps._xyz0Work; const xyz1 = IndexedXYZCollectionPolygonOps._xyz1Work; const xyzInterpolated = IndexedXYZCollectionPolygonOps._xyz2Work; @@ -1397,7 +1539,7 @@ export class IndexedXYZCollectionPolygonOps { let nearZero = false; if (a0 * a1 < 0.0) { // simple crossing. . . - const f = - a0 / (a1 - a0); + const f = -a0 / (a1 - a0); if (f > 1.0 - fractionTol && a1 >= 0.0) { // the endpoint will be saved -- avoid the duplicate nearZero = true; @@ -1429,7 +1571,13 @@ export class IndexedXYZCollectionPolygonOps { * @param tolerance tolerance for "on plane" decision. * @return the number of crossings. If this is larger than 2, the result is "correct" in a parity sense but may have overlapping (hence cancelling) parts. */ - public static clipConvexPolygonInPlace(plane: PlaneAltitudeEvaluator, xyz: GrowableXYZArray, work: GrowableXYZArray, keepPositive: boolean = true, tolerance: number = Geometry.smallMetricDistance): number { + public static clipConvexPolygonInPlace( + plane: PlaneAltitudeEvaluator, + xyz: GrowableXYZArray, + work: GrowableXYZArray, + keepPositive: boolean = true, + tolerance: number = Geometry.smallMetricDistance, + ): number { work.clear(); const s = keepPositive ? 1.0 : -1.0; const n = xyz.length; @@ -1453,7 +1601,7 @@ export class IndexedXYZCollectionPolygonOps { numNegative++; if (a0 * a1 < 0.0) { // simple crossing . . . - const f = - a0 / (a1 - a0); + const f = -a0 / (a1 - a0); if (f > 1.0 - fractionTol && a1 >= 0.0) { // the endpoint will be saved -- avoid the duplicate } else { @@ -1498,10 +1646,10 @@ export class IndexedXYZCollectionPolygonOps { const a1 = plane.altitude(xyz1); if (a0 * a1 < 0.0) { // simple crossing. . . - const f = - a0 / (a1 - a0); + const f = -a0 / (a1 - a0); crossings.push(xyz0.interpolate(f, xyz1)); } - if (a1 === 0.0) { // IMPORTANT -- every point is directly tested here + if (a1 === 0.0) { // IMPORTANT -- every point is directly tested here crossings.push(xyz1.clone()); } xyz0.setFromPoint3d(xyz1); @@ -1517,7 +1665,12 @@ export class IndexedXYZCollectionPolygonOps { * * `minChainLength` indicates the shortest chain to be returned. * @internal */ - public static gatherCutLoopsFromPlaneClip(plane: PlaneAltitudeEvaluator, xyz: GrowableXYZArray, minChainLength: number = 3, tolerance: number = Geometry.smallMetricDistance): CutLoopMergeContext { + public static gatherCutLoopsFromPlaneClip( + plane: PlaneAltitudeEvaluator, + xyz: GrowableXYZArray, + minChainLength: number = 3, + tolerance: number = Geometry.smallMetricDistance, + ): CutLoopMergeContext { const result: CutLoopMergeContext = new CutLoopMergeContext(); // find the first on-plane point let firstOnPlaneIndex = 0; @@ -1543,9 +1696,10 @@ export class IndexedXYZCollectionPolygonOps { } candidateB++; } - if (candidateB === n) + if (candidateB === n) { for (let i = 0; i <= firstOnPlaneIndex; i++) currentChain.pushFromGrowableXYZArray(xyz, i); + } if (currentChain.length >= minChainLength) result.inputLoops.push(CutLoop.createCaptureWithReturnEdge(currentChain)); candidateA = candidateB; @@ -1640,7 +1794,13 @@ export class Point3dArrayPolygonOps { * @param xyzOut array to receive outside part * @param altitudeRange min and max altitudes encountered. */ - public static convexPolygonSplitInsideOutsidePlane(plane: PlaneAltitudeEvaluator, xyz: Point3d[], xyzIn: Point3d[], xyzOut: Point3d[], altitudeRange: Range1d): void { + public static convexPolygonSplitInsideOutsidePlane( + plane: PlaneAltitudeEvaluator, + xyz: Point3d[], + xyzIn: Point3d[], + xyzOut: Point3d[], + altitudeRange: Range1d, + ): void { const xyzCarrier = new Point3dArrayCarrier(xyz); const xyzInCarrier = new Point3dArrayCarrier(xyzIn); const xyzOutCarrier = new Point3dArrayCarrier(xyzOut); @@ -1661,7 +1821,12 @@ export class Point3dArrayPolygonOps { * @param work scratch object * @param tolerance tolerance for on-plane decision. */ - public static convexPolygonClipInPlace(plane: PlaneAltitudeEvaluator, xyz: Point3d[], work: Point3d[] | undefined, tolerance: number = Geometry.smallMetricDistance) { + public static convexPolygonClipInPlace( + plane: PlaneAltitudeEvaluator, + xyz: Point3d[], + work: Point3d[] | undefined, + tolerance: number = Geometry.smallMetricDistance, + ) { if (work === undefined) work = []; work.length = 0; @@ -1679,7 +1844,7 @@ export class Point3dArrayPolygonOps { numNegative++; if (a0 * a1 < 0.0) { // simple crossing . . . - const f = - a0 / (a1 - a0); + const f = -a0 / (a1 - a0); if (f > 1.0 - fractionTol && a1 >= 0.0) { // the endpoint will be saved -- avoid the duplicate } else { diff --git a/core/geometry/src/geometry3d/PolylineCompressionByEdgeOffset.ts b/core/geometry/src/geometry3d/PolylineCompressionByEdgeOffset.ts index dddaa34392e5..fba03d13f4f0 100644 --- a/core/geometry/src/geometry3d/PolylineCompressionByEdgeOffset.ts +++ b/core/geometry/src/geometry3d/PolylineCompressionByEdgeOffset.ts @@ -99,7 +99,6 @@ export class PolylineCompressionContext { return maxDeviationIndex; } /** - * * @param i0 first active point index * @param i1 last active point index (INCLUSIVE -- not "one beyond") * @param chordTolerance diff --git a/core/geometry/src/geometry3d/PolylineOps.ts b/core/geometry/src/geometry3d/PolylineOps.ts index 2f4d37cd47f0..128fb539ba9f 100644 --- a/core/geometry/src/geometry3d/PolylineOps.ts +++ b/core/geometry/src/geometry3d/PolylineOps.ts @@ -75,7 +75,6 @@ export class PolylineOps { * @param source input points * @param maxDistance omit points if this close to edge between points before and after * @param numPass max number of times to run the filter. numPass=2 is observed to behave well. - * */ public static compressByPerpendicularDistance(source: Point3d[], maxDistance: number, numPass: number = 2): Point3d[] { const dest = GrowableXYZArray.create(source); @@ -104,7 +103,13 @@ export class PolylineOps { * @param pointQ * @param tolerance */ - private static isDanglerConfiguration(points: Point3d[], indexA: number, indexB: number, pointQ: Point3d, squaredDistanceTolerance: number): boolean { + private static isDanglerConfiguration( + points: Point3d[], + indexA: number, + indexB: number, + pointQ: Point3d, + squaredDistanceTolerance: number, + ): boolean { if (indexA < 0 || indexA >= points.length) return false; const pointA = points[indexA]; @@ -138,17 +143,18 @@ export class PolylineOps { return distanceSquared < squaredDistanceTolerance; } /** - * Return a simplified subset of given points, omitting points on "danglers" that depart and return on a single path. - * @param source input points - * @param closed if true, an edge returning to point 0 is implied even if final point does not match. - * @param tolerance tolerance for near-zero distance. - */ + * Return a simplified subset of given points, omitting points on "danglers" that depart and return on a single path. + * @param source input points + * @param closed if true, an edge returning to point 0 is implied even if final point does not match. + * @param tolerance tolerance for near-zero distance. + */ public static compressDanglers(source: Point3d[], closed: boolean = false, tolerance: number = Geometry.smallMetricDistance): Point3d[] { let n = source.length; const squaredDistanceTolerance = tolerance * tolerance; - if (closed) + if (closed) { while (n > 1 && source[n - 1].distanceSquared(source[0]) <= squaredDistanceTolerance) n--; + } const dest = []; dest.push(source[0].clone()); for (let i = 1; i < n; i++) { @@ -228,8 +234,11 @@ export class PolylineOps { * @param centerline points to reside in output planes * @param wrapIfPhysicallyClosed if true and the first and last centerline points are the same, then the first and last output planes are averaged and equated (cloned). */ - public static createBisectorPlanesForDistinctPoints(centerline: IndexedXYZCollection | Point3d[], wrapIfPhysicallyClosed: boolean = false): Plane3dByOriginAndUnitNormal[] | undefined { - const packedPoints = PolylineOps.compressShortEdges(centerline, 2.0 * Geometry.smallMetricDistance); // double the tolerance to ensure normalized vectors exist. + public static createBisectorPlanesForDistinctPoints( + centerline: IndexedXYZCollection | Point3d[], + wrapIfPhysicallyClosed: boolean = false, + ): Plane3dByOriginAndUnitNormal[] | undefined { + const packedPoints = PolylineOps.compressShortEdges(centerline, 2.0 * Geometry.smallMetricDistance); // double the tolerance to ensure normalized vectors exist. if (packedPoints.length < 2) return undefined; const bisectorPlanes: Plane3dByOriginAndUnitNormal[] = []; @@ -331,7 +340,16 @@ export class PolylineOps { for (let indexB = 0; indexB < numSegmentB; indexB++) { this._workSegmentB = fillSegment(pointsB, indexB, this._workSegmentB); convertExtend(extendSegB, extendB, indexB, numSegmentB); - if (undefined !== (this._workLocalDetailPair = LineSegment3d.closestApproach(this._workSegmentA, extendSegA, this._workSegmentB, extendSegB, this._workLocalDetailPair))) { + if ( + undefined !== + (this._workLocalDetailPair = LineSegment3d.closestApproach( + this._workSegmentA, + extendSegA, + this._workSegmentB, + extendSegB, + this._workLocalDetailPair, + )) + ) { const d = this._workLocalDetailPair.detailA.a; if (d < dMin) { const childDetailA = result?.detailA.childDetail; // save and reuse diff --git a/core/geometry/src/geometry3d/Range.ts b/core/geometry/src/geometry3d/Range.ts index 974229142425..85fa1cb75f6d 100644 --- a/core/geometry/src/geometry3d/Range.ts +++ b/core/geometry/src/geometry3d/Range.ts @@ -151,8 +151,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } // explicit ctor - no enforcement of value relationships public constructor( - lowX: number = RangeBase._EXTREME_POSITIVE, lowY: number = RangeBase._EXTREME_POSITIVE, lowZ: number = RangeBase._EXTREME_POSITIVE, - highX: number = RangeBase._EXTREME_NEGATIVE, highY: number = RangeBase._EXTREME_NEGATIVE, highZ: number = RangeBase._EXTREME_NEGATIVE, + lowX: number = RangeBase._EXTREME_POSITIVE, + lowY: number = RangeBase._EXTREME_POSITIVE, + lowZ: number = RangeBase._EXTREME_POSITIVE, + highX: number = RangeBase._EXTREME_NEGATIVE, + highY: number = RangeBase._EXTREME_NEGATIVE, + highZ: number = RangeBase._EXTREME_NEGATIVE, ) { super(); this.low = Point3d.create(lowX, lowY, lowZ); @@ -175,8 +179,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions return result; } return this.createXYZXYZOrCorrectToNull( - other.low.x, other.low.y, other.low.z, - other.high.x, other.high.y, other.high.z, + other.low.x, + other.low.y, + other.low.z, + other.high.x, + other.high.y, + other.high.z, result, ); } @@ -250,8 +258,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions result = result ? result : new (this.constructor as any)() as this; if (!this.isNull) result.setDirect( - this.low.x + shift.x, this.low.y + shift.y, this.low.z + shift.z, - this.high.x + shift.x, this.high.y + shift.y, this.high.z + shift.z, + this.low.x + shift.x, + this.low.y + shift.y, + this.low.z + shift.z, + this.high.x + shift.x, + this.high.y + shift.y, + this.high.z + shift.z, false, ); return result; @@ -293,7 +305,8 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Create a Range3d enclosing the transformed points. */ public static createTransformedArray( - transform: Transform, points: Point3d[] | GrowableXYZArray, + transform: Transform, + points: Point3d[] | GrowableXYZArray, ): T { const result = this.createNull(); result.extendArray(points, transform); @@ -301,7 +314,8 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Create a Range3d enclosing the points after inverse transform. */ public static createInverseTransformedArray( - transform: Transform, points: Point3d[] | GrowableXYZArray, + transform: Transform, + points: Point3d[] | GrowableXYZArray, ): T { const result = this.createNull(); result.extendInverseTransformedArray(points, transform); @@ -321,12 +335,22 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Create a box with 2 pairs of xyz candidates. Theses are compared and shuffled as needed for the box. */ public static createXYZXYZ( - xA: number, yA: number, zA: number, xB: number, yB: number, zB: number, result?: T, + xA: number, + yA: number, + zA: number, + xB: number, + yB: number, + zB: number, + result?: T, ): T { result = result ? result : new this() as T; result.setDirect( - Math.min(xA, xB), Math.min(yA, yB), Math.min(zA, zB), - Math.max(xA, xB), Math.max(yA, yB), Math.max(zA, zB), + Math.min(xA, xB), + Math.min(yA, yB), + Math.min(zA, zB), + Math.max(xA, xB), + Math.max(yA, yB), + Math.max(zA, zB), false, ); return result; @@ -334,14 +358,24 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions /** Create a box with 2 pairs of xyz candidates. If any direction has order flip, create null. */ public static createXYZXYZOrCorrectToNull( - xA: number, yA: number, zA: number, xB: number, yB: number, zB: number, result?: T, + xA: number, + yA: number, + zA: number, + xB: number, + yB: number, + zB: number, + result?: T, ): T { result = result ? result : new this() as T; if (xA > xB || yA > yB || zA > zB) return this.createNull(result); result.setDirect( - Math.min(xA, xB), Math.min(yA, yB), Math.min(zA, zB), - Math.max(xA, xB), Math.max(yA, yB), Math.max(zA, zB), + Math.min(xA, xB), + Math.min(yA, yB), + Math.min(zA, zB), + Math.max(xA, xB), + Math.max(yA, yB), + Math.max(zA, zB), true, ); return result; @@ -365,36 +399,41 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Extend a range around an array of points (optionally transformed) */ public extendArray(points: Point3d[] | GrowableXYZArray, transform?: Transform) { - if (Array.isArray(points)) - if (transform) + if (Array.isArray(points)) { + if (transform) { for (const point of points) this.extendTransformedXYZ(transform, point.x, point.y, point.z); + } else for (const point of points) this.extendXYZ(point.x, point.y, point.z); - else // growable array -- this should be implemented without point extraction !!! - if (transform) - for (let i = 0; i < points.length; i++) - this.extendTransformedXYZ( - transform, - points.getXAtUncheckedPointIndex(i), - points.getYAtUncheckedPointIndex(i), - points.getZAtUncheckedPointIndex(i), - ); - else - for (let i = 0; i < points.length; i++) - this.extendXYZ( - points.getXAtUncheckedPointIndex(i), - points.getYAtUncheckedPointIndex(i), - points.getZAtUncheckedPointIndex(i), - ); + } + // growable array -- this should be implemented without point extraction !!! + else if (transform) { + for (let i = 0; i < points.length; i++) + this.extendTransformedXYZ( + transform, + points.getXAtUncheckedPointIndex(i), + points.getYAtUncheckedPointIndex(i), + points.getZAtUncheckedPointIndex(i), + ); + } + else + for (let i = 0; i < points.length; i++) + this.extendXYZ( + points.getXAtUncheckedPointIndex(i), + points.getYAtUncheckedPointIndex(i), + points.getZAtUncheckedPointIndex(i), + ); } /** Extend a range around an array of points (optionally transformed) */ public extendInverseTransformedArray(points: Point3d[] | GrowableXYZArray, transform: Transform) { - if (Array.isArray(points)) + if (Array.isArray(points)) { for (const point of points) this.extendInverseTransformedXYZ(transform, point.x, point.y, point.z); - else // growable array -- this should be implemented without point extraction !!! + } + // growable array -- this should be implemented without point extraction !!! + else for (let i = 0; i < points.length; i++) this.extendInverseTransformedXYZ( transform, @@ -443,7 +482,11 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Extend the range by the two transforms applied to xyz */ public extendTransformTransformedXYZ( - transformA: Transform, transformB: Transform, x: number, y: number, z: number, + transformA: Transform, + transformB: Transform, + x: number, + y: number, + z: number, ): void { const origin = transformB.origin; const coffs = transformB.matrix.coffs; @@ -502,15 +545,18 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions } /** Return the length of the box in the x direction */ public xLength(): number { - const a = this.high.x - this.low.x; return a > 0.0 ? a : 0.0; + const a = this.high.x - this.low.x; + return a > 0.0 ? a : 0.0; } /** Return the length of the box in the y direction */ public yLength(): number { - const a = this.high.y - this.low.y; return a > 0.0 ? a : 0.0; + const a = this.high.y - this.low.y; + return a > 0.0 ? a : 0.0; } /** Return the length of the box in the z direction */ public zLength(): number { - const a = this.high.z - this.low.z; return a > 0.0 ? a : 0.0; + const a = this.high.z - this.low.z; + return a > 0.0 ? a : 0.0; } /** Return the largest of the x,y, z lengths of the range. */ public maxLength(): number { @@ -539,7 +585,10 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions * Returns undefined if the range is null. */ public localXYZToWorld( - fractionX: number, fractionY: number, fractionZ: number, result?: Point3d, + fractionX: number, + fractionY: number, + fractionZ: number, + result?: Point3d, ): Point3d | undefined { if (this.isNull) return undefined; return this.low.interpolateXYZ(fractionX, fractionY, fractionZ, this.high, result); @@ -655,7 +704,9 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions * @returns rectangle points */ public rectangleXY( - zFraction: number = 0.0, upwardNormal: boolean = true, addClosure: boolean = true, + zFraction: number = 0.0, + upwardNormal: boolean = true, + addClosure: boolean = true, ): Point3d[] | undefined { if (this.isNull) return undefined; @@ -791,14 +842,16 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions this.extendXYZ( xyz0.x + fraction * (xyz1.x - xyz0.x), xyz0.y + fraction * (xyz1.y - xyz0.y), - xyz0.z + fraction * (xyz1.z - xyz0.z)); + xyz0.z + fraction * (xyz1.z - xyz0.z), + ); } else { // use reversed formulas for best accuracy at fraction=1.0 const g = 1.0 - fraction; this.extendXYZ( xyz1.x + g * (xyz0.x - xyz1.x), xyz1.y + g * (xyz0.y - xyz1.y), - xyz1.z + g * (xyz0.z - xyz1.z)); + xyz1.z + g * (xyz0.z - xyz1.z), + ); } } /** Expand this range by distances a in only the x direction. */ @@ -874,8 +927,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions if (!this.intersectsRange(other)) return Range3d.createNull(result); return Range3d.createXYZXYZOrCorrectToNull( - Math.max(this.low.x, other.low.x), Math.max(this.low.y, other.low.y), Math.max(this.low.z, other.low.z), - Math.min(this.high.x, other.high.x), Math.min(this.high.y, other.high.y), Math.min(this.high.z, other.high.z), + Math.max(this.low.x, other.low.x), + Math.max(this.low.y, other.low.y), + Math.max(this.low.z, other.low.z), + Math.min(this.high.x, other.high.x), + Math.min(this.high.y, other.high.y), + Math.min(this.high.z, other.high.z), result, ); } @@ -887,8 +944,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions return this.clone(result as this); // we trust null ranges have EXTREME values, so a null in either input leads to expected results. return Range3d.createXYZXYZOrCorrectToNull( - Math.min(this.low.x, other.low.x), Math.min(this.low.y, other.low.y), Math.min(this.low.z, other.low.z), - Math.max(this.high.x, other.high.x), Math.max(this.high.y, other.high.y), Math.max(this.high.z, other.high.z), + Math.min(this.low.x, other.low.x), + Math.min(this.low.y, other.low.y), + Math.min(this.low.z, other.low.z), + Math.max(this.high.x, other.high.x), + Math.max(this.high.y, other.high.y), + Math.max(this.high.z, other.high.z), result, ); } @@ -920,8 +981,12 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions */ public expandInPlace(delta: number): void { this.setDirect( - this.low.x - delta, this.low.y - delta, this.low.z - delta, - this.high.x + delta, this.high.y + delta, this.high.z + delta, + this.low.x - delta, + this.low.y - delta, + this.low.z - delta, + this.high.x + delta, + this.high.y + delta, + this.high.z + delta, true, ); } @@ -930,9 +995,15 @@ export class Range3d extends RangeBase implements LowAndHighXYZ, BeJSONFunctions return Transform.createOriginAndMatrix( Point3d.create(this.low.x, this.low.y, this.low.z), Matrix3d.createRowValues( - this.high.x - this.low.x, 0, 0, - 0, this.high.y - this.low.y, 0, - 0, 0, this.high.z - this.low.z, + this.high.x - this.low.x, + 0, + 0, + 0, + this.high.y - this.low.y, + 0, + 0, + 0, + this.high.z - this.low.z, ), result, ); @@ -1004,7 +1075,8 @@ export class Range1d extends RangeBase { // explicit ctor - no enforcement of value relationships private constructor(low: number = RangeBase._EXTREME_POSITIVE, high: number = RangeBase._EXTREME_NEGATIVE) { super(); - this.low = low; this.high = high; // duplicates set_direct, but compiler is not convinced they are set. + this.low = low; + this.high = high; // duplicates set_direct, but compiler is not convinced they are set. this.setDirect(low, high); } /** Returns true if this and other have equal low and high parts, or both are null ranges. */ @@ -1115,9 +1187,11 @@ export class Range1d extends RangeBase { */ public setXXUnordered(x0: number, x1: number) { if (x0 <= x1) { - this.low = x0; this.high = x1; + this.low = x0; + this.high = x1; } else { - this.low = x1; this.high = x0; + this.low = x1; + this.high = x0; } } /** Check if low is 0 and high is 1 */ @@ -1298,11 +1372,11 @@ export class Range1d extends RangeBase { /** Return the union of ranges. */ public union(other: Range1d, result?: Range1d): Range1d { // we trust null ranges have EXTREME values, so a null in either input leads to expected results. - return Range1d.createXX - ( - Math.min(this.low, other.low), - Math.max(this.high, other.high), - result); + return Range1d.createXX( + Math.min(this.low, other.low), + Math.max(this.high, other.high), + result, + ); } /** * Move low and high points by scaleFactor around the center point. @@ -1327,7 +1401,9 @@ export class Range1d extends RangeBase { public expandInPlace(delta: number): void { this.setDirect( this.low - delta, - this.high + delta, true); + this.high + delta, + true, + ); } /** * Clip this range to a linear half space condition @@ -1426,8 +1502,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { } // explicit constructor - no enforcement of value relationships public constructor( - lowX = Range2d._EXTREME_POSITIVE, lowY = Range2d._EXTREME_POSITIVE, - highX = Range2d._EXTREME_NEGATIVE, highY = Range2d._EXTREME_NEGATIVE, + lowX = Range2d._EXTREME_POSITIVE, + lowY = Range2d._EXTREME_POSITIVE, + highX = Range2d._EXTREME_NEGATIVE, + highY = Range2d._EXTREME_NEGATIVE, ) { super(); this.low = Point2d.create(lowX, lowY); @@ -1445,7 +1523,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { } /** Create a new Range2d from any `other` that has low and high xy data. */ public static createFrom(other: LowAndHighXY, result?: T): T { - if (result) { result.setFrom(other); return result; } + if (result) { + result.setFrom(other); + return result; + } return this.createXYXYOrCorrectToNull(other.low.x, other.low.y, other.high.x, other.high.y, result) as T; } /** Treat any array of numbers as numbers to be inserted !!! */ @@ -1509,8 +1590,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { result = result ? result : new (this.constructor as any)() as this; if (!this.isNull) result.setDirect( - this.low.x + shift.x, this.low.y + shift.y, - this.high.x + shift.x, this.high.y + shift.y, + this.low.x + shift.x, + this.low.y + shift.y, + this.high.x + shift.x, + this.high.y + shift.y, false, ); return result; @@ -1537,32 +1620,50 @@ export class Range2d extends RangeBase implements LowAndHighXY { public static createXYXY(xA: number, yA: number, xB: number, yB: number, result?: T): T { result = result ? result : new this() as T; result.setDirect( - Math.min(xA, xB), Math.min(yA, yB), - Math.max(xA, xB), Math.max(yA, yB), false); + Math.min(xA, xB), + Math.min(yA, yB), + Math.max(xA, xB), + Math.max(yA, yB), + false, + ); return result; } /** Create a box with 3 pairs of xy candidates. Theses are compared and shuffled as needed for the box. */ public static createXYXYXY( - xA: number, yA: number, xB: number, yB: number, xC: number, yC: number, result?: T, + xA: number, + yA: number, + xB: number, + yB: number, + xC: number, + yC: number, + result?: T, ): T { result = result ? result : new this() as T; result.setDirect( - Math.min(xA, xB, xC), Math.min(yA, yB, yC), - Math.max(xA, xB, xC), Math.max(yA, yB, yC), + Math.min(xA, xB, xC), + Math.min(yA, yB, yC), + Math.max(xA, xB, xC), + Math.max(yA, yB, yC), false, ); return result; } /** Create a box with 2 pairs of xy candidates. If any direction has order flip, create null. */ public static createXYXYOrCorrectToNull( - xA: number, yA: number, xB: number, yB: number, result?: T, + xA: number, + yA: number, + xB: number, + yB: number, + result?: T, ): T { if (xA > xB || yA > yB) return this.createNull(result); result = result ? result : new this() as T; result.setDirect( - Math.min(xA, xB), Math.min(yA, yB), - Math.max(xA, xB), Math.max(yA, yB), + Math.min(xA, xB), + Math.min(yA, yB), + Math.max(xA, xB), + Math.max(yA, yB), true, ); return result; @@ -1758,8 +1859,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { if (!this.intersectsRange(other)) return Range2d.createNull(result); return Range2d.createXYXY( - Math.max(this.low.x, other.low.x), Math.max(this.low.y, other.low.y), - Math.min(this.high.x, other.high.x), Math.min(this.high.y, other.high.y), + Math.max(this.low.x, other.low.x), + Math.max(this.low.y, other.low.y), + Math.min(this.high.x, other.high.x), + Math.min(this.high.y, other.high.y), result, ); } @@ -1771,8 +1874,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { return this.clone(result as this); // we trust null ranges have EXTREME values, so a null in either input leads to expected results. return Range2d.createXYXY( - Math.min(this.low.x, other.low.x), Math.min(this.low.y, other.low.y), - Math.max(this.high.x, other.high.x), Math.max(this.high.y, other.high.y), + Math.min(this.low.x, other.low.x), + Math.min(this.low.y, other.low.y), + Math.max(this.high.x, other.high.x), + Math.max(this.high.y, other.high.y), result, ); } @@ -1801,8 +1906,10 @@ export class Range2d extends RangeBase implements LowAndHighXY { */ public expandInPlace(delta: number): void { this.setDirect( - this.low.x - delta, this.low.y - delta, - this.high.x + delta, this.high.y + delta, + this.low.x - delta, + this.low.y - delta, + this.high.x + delta, + this.high.y + delta, true, ); } diff --git a/core/geometry/src/geometry3d/Ray2d.ts b/core/geometry/src/geometry3d/Ray2d.ts index 48914f01f537..9e2e9fafaa98 100644 --- a/core/geometry/src/geometry3d/Ray2d.ts +++ b/core/geometry/src/geometry3d/Ray2d.ts @@ -66,9 +66,13 @@ export class Ray2d { return new Ray2d(origin, direction); } /** Get the reference to the ray origin. */ - public get origin() { return this._origin; } + public get origin() { + return this._origin; + } /** Get the reference to the ray direction. */ - public get direction() { return this._direction; } + public get direction() { + return this._direction; + } /** * Return a parallel ray to the left of this ray. * @param leftFraction distance between rays, as a fraction of the magnitude of this ray's direction vector diff --git a/core/geometry/src/geometry3d/Ray3d.ts b/core/geometry/src/geometry3d/Ray3d.ts index fa6e289b2655..be41e12cb224 100644 --- a/core/geometry/src/geometry3d/Ray3d.ts +++ b/core/geometry/src/geometry3d/Ray3d.ts @@ -147,7 +147,9 @@ export class Ray3d implements BeJSONFunctions { * @param result */ public static createWeightedDerivative( - weightedPoint: Float64Array, weightedDerivative: Float64Array, result?: Ray3d, + weightedPoint: Float64Array, + weightedDerivative: Float64Array, + result?: Ray3d, ): Ray3d | undefined { const w = weightedPoint[3]; const dw = weightedDerivative[3]; @@ -162,15 +164,23 @@ export class Ray3d implements BeJSONFunctions { const divW = 1.0 / w; const divWW = divW * divW; return Ray3d.createXYZUVW( - x * divW, y * divW, z * divW, - dx * divWW, dy * divWW, dz * divWW, + x * divW, + y * divW, + z * divW, + dx * divWW, + dy * divWW, + dz * divWW, result, ); } /** Create from coordinates of the origin and direction. */ public static createXYZUVW( - originX: number, originY: number, originZ: number, - directionX: number, directionY: number, directionZ: number, + originX: number, + originY: number, + originZ: number, + directionX: number, + directionY: number, + directionZ: number, result?: Ray3d, ): Ray3d { if (result) { @@ -241,7 +251,10 @@ export class Ray3d implements BeJSONFunctions { return Ray3d.create( transform.multiplyInversePoint3d(this.origin, result?.origin)!, transform.matrix.multiplyInverseXYZAsVector3d( - this.direction.x, this.direction.y, this.direction.z, result?.direction, + this.direction.x, + this.direction.y, + this.direction.z, + result?.direction, )!, result, ); @@ -373,7 +386,8 @@ export class Ray3d implements BeJSONFunctions { if (range.isNull) return Range1d.createNull(result); const interval = Range1d.createXX(-Geometry.largeCoordinateResult, Geometry.largeCoordinateResult, result); - if (interval.clipLinearMapToInterval(this.origin.x, this.direction.x, range.low.x, range.high.x) + if ( + interval.clipLinearMapToInterval(this.origin.x, this.direction.x, range.low.x, range.high.x) && interval.clipLinearMapToInterval(this.origin.y, this.direction.y, range.low.y, range.high.y) && interval.clipLinearMapToInterval(this.origin.z, this.direction.z, range.low.z, range.high.z) ) @@ -392,9 +406,14 @@ export class Ray3d implements BeJSONFunctions { * a triangle edge or vertex (if tolerance is not provided, Geometry.smallFloatingPoint is used) * @param result optional pre-allocated object to fill and return * @returns the intersection point if ray intersects the triangle. Otherwise, return undefined. - */ + */ public intersectionWithTriangle( - vertex0: Point3d, vertex1: Point3d, vertex2: Point3d, distanceTol?: number, parameterTol?: number, result?: Point3d, + vertex0: Point3d, + vertex1: Point3d, + vertex2: Point3d, + distanceTol?: number, + parameterTol?: number, + result?: Point3d, ): Point3d | undefined { /** * Suppose ray is shown by "rayOrigin + t*rayVector" and barycentric coordinate of point @@ -463,12 +482,12 @@ export class Ray3d implements BeJSONFunctions { if (v > -parameterTol) v = 0.0; else - return undefined; // ray does not intersect the triangle + return undefined; // ray does not intersect the triangle } else if (u + v > 1.0) { if (u + v < 1.0 + parameterTol) v = 1.0 - u; else - return undefined; // ray does not intersect the triangle + return undefined; // ray does not intersect the triangle } // at this stage, we know the line (parameterized as the ray) intersects the triangle const t = f * edge2.dotProduct(q); @@ -507,8 +526,18 @@ export class Ray3d implements BeJSONFunctions { let pairType; if ( SmallSystem.ray3dXYZUVWClosestApproachUnbounded( - rayA.origin.x, rayA.origin.y, rayA.origin.z, rayA.direction.x, rayA.direction.y, rayA.direction.z, - rayB.origin.x, rayB.origin.y, rayB.origin.z, rayB.direction.x, rayB.direction.y, rayB.direction.z, + rayA.origin.x, + rayA.origin.y, + rayA.origin.z, + rayA.direction.x, + rayA.direction.y, + rayA.direction.z, + rayB.origin.x, + rayB.origin.y, + rayB.origin.z, + rayB.direction.x, + rayB.direction.y, + rayB.direction.z, intersectionFractions, ) ) { @@ -517,18 +546,21 @@ export class Ray3d implements BeJSONFunctions { pointA = rayA.fractionToPoint(fractionA); pointB = rayB.fractionToPoint(fractionB); pairType = pointA.isAlmostEqualMetric(pointB) ? - CurveCurveApproachType.Intersection : CurveCurveApproachType.PerpendicularChord; + CurveCurveApproachType.Intersection : + CurveCurveApproachType.PerpendicularChord; } else { fractionB = 0.0; fractionA = rayA.pointToFraction(rayB.origin); pointA = rayA.fractionToPoint(fractionA); pointB = rayB.fractionToPoint(fractionB); pairType = pointA.isAlmostEqualMetric(pointB) ? - CurveCurveApproachType.CoincidentGeometry : CurveCurveApproachType.ParallelGeometry; + CurveCurveApproachType.CoincidentGeometry : + CurveCurveApproachType.ParallelGeometry; } const pair = CurveLocationDetailPair.createCapture( CurveLocationDetail.createRayFractionPoint(rayA, fractionA, rayA.fractionToPoint(fractionA)), - CurveLocationDetail.createRayFractionPoint(rayB, fractionB, rayB.fractionToPoint(fractionB))); + CurveLocationDetail.createRayFractionPoint(rayB, fractionB, rayB.fractionToPoint(fractionB)), + ); pair.approachType = pairType; return pair; } @@ -542,7 +574,11 @@ export class Ray3d implements BeJSONFunctions { * @param result optional receiver. */ public static interpolatePointAndTangent( - pt1: XYAndZ, fraction: number, pt2: XYAndZ, tangentScale: number, result?: Ray3d, + pt1: XYAndZ, + fraction: number, + pt2: XYAndZ, + tangentScale: number, + result?: Ray3d, ): Ray3d { result = result ?? Ray3d.createZero(); const dx = pt2.x - pt1.x; diff --git a/core/geometry/src/geometry3d/ReusableObjectCache.ts b/core/geometry/src/geometry3d/ReusableObjectCache.ts index f989fd4c74b9..01f56724a514 100644 --- a/core/geometry/src/geometry3d/ReusableObjectCache.ts +++ b/core/geometry/src/geometry3d/ReusableObjectCache.ts @@ -73,9 +73,15 @@ export abstract class ReusableObjectCache { * @internal */ export class GrowableXYZArrayCache extends ReusableObjectCache { - protected clearForCache(data: GrowableXYZArray): void { data.length = 0; } - protected createForCache(): GrowableXYZArray { return new GrowableXYZArray(10); } - public constructor() { super(); } + protected clearForCache(data: GrowableXYZArray): void { + data.length = 0; + } + protected createForCache(): GrowableXYZArray { + return new GrowableXYZArray(10); + } + public constructor() { + super(); + } /** * Grab an array from the cache and immediately fill from a source * @param source @@ -84,6 +90,5 @@ export class GrowableXYZArrayCache extends ReusableObjectCache const dest = this.grabFromCache(); dest.pushFrom(source); return dest; - } } diff --git a/core/geometry/src/geometry3d/Segment1d.ts b/core/geometry/src/geometry3d/Segment1d.ts index 15ced561484c..e12baaa7d067 100644 --- a/core/geometry/src/geometry3d/Segment1d.ts +++ b/core/geometry/src/geometry3d/Segment1d.ts @@ -38,12 +38,16 @@ export class Segment1d { * @param x0 new x0 value * @param x1 new y0 value */ - public set(x0: number, x1: number) { this.x0 = x0, this.x1 = x1; } + public set(x0: number, x1: number) { + this.x0 = x0, this.x1 = x1; + } /** * shift (translate) the segment along its axis by adding `dx` to both `x0` and `x1`. * @param dx value to add to both x0 and x1 */ - public shift(dx: number) { this.x0 += dx, this.x1 += dx; } + public shift(dx: number) { + this.x0 += dx, this.x1 += dx; + } /** * create segment1d with given end values * @param x0 start value @@ -60,37 +64,51 @@ export class Segment1d { * Copy both end values from other Segment1d * @param other source Segment1d */ - public setFrom(other: Segment1d) { this.x0 = other.x0; this.x1 = other.x1; } + public setFrom(other: Segment1d) { + this.x0 = other.x0; + this.x1 = other.x1; + } /** * clone this Segment1d, return as a separate object. */ - public clone(): Segment1d { return new Segment1d(this.x0, this.x1); } + public clone(): Segment1d { + return new Segment1d(this.x0, this.x1); + } /** * Returns true if both coordinates (`x0` and `x1`) are in the 0..1 range. */ public get isIn01() { return Geometry.isIn01(this.x0) && Geometry.isIn01(this.x1); - } /** * Evaluate the segment at fractional position * @returns position within the segment * @param fraction fractional position within this segment */ - public fractionToPoint(fraction: number): number { return Geometry.interpolate(this.x0, fraction, this.x1); } + public fractionToPoint(fraction: number): number { + return Geometry.interpolate(this.x0, fraction, this.x1); + } /** * Return the signed start-to-end shift (aka signed distance) */ - public signedDelta(): number { return this.x1 - this.x0; } + public signedDelta(): number { + return this.x1 - this.x0; + } /** * Return the absolute start-to-end shift (aka distance) */ - public absoluteDelta(): number { return Math.abs(this.x1 - this.x0); } + public absoluteDelta(): number { + return Math.abs(this.x1 - this.x0); + } /** * * swap the x0 and x1 member values. * * This makes the fractionToPoint evaluates reverse direction. */ - public reverseInPlace(): void { const x = this.x0; this.x0 = this.x1; this.x1 = x; } + public reverseInPlace(): void { + const x = this.x0; + this.x0 = this.x1; + this.x1 = x; + } /** * * if `x1-x0` multiplied by the scale factor is (strictly) negative, swap the x0 and x1 member values. * * This makes the fractionToPoint evaluates reverse direction. @@ -108,11 +126,15 @@ export class Segment1d { /** * Return true if the segment limits are (exactly) 0 and 1 */ - public get isExact01(): boolean { return this.x0 === 0.0 && this.x1 === 1.0; } + public get isExact01(): boolean { + return this.x0 === 0.0 && this.x1 === 1.0; + } /** * Return true if the segment limits are (exactly) 1 and 0 */ - public get isExact01Reversed(): boolean { return this.x0 === 1.0 && this.x1 === 0.0; } + public get isExact01Reversed(): boolean { + return this.x0 === 1.0 && this.x1 === 0.0; + } /** On input, `this` is an interval of a line. On output, the interval has been clipped to positive parts of a linear function * * f0 and f1 are values at parameter values 0 and 1 (which are in general NOT x0 and x1) @@ -134,7 +156,7 @@ export class Segment1d { this.x1 = this.x0 + u * (this.x1 - this.x0); return true; } else if (fA < 0) { - if (fB < 0) return false; // outside at both ends. + if (fB < 0) return false; // outside at both ends. /** There is an outside to inside crossing crossing. The division is safe ... (and value between 0 and 1) */ const u = -fA / dfAB; this.x0 = this.x0 + u * (this.x1 - this.x0); diff --git a/core/geometry/src/geometry3d/SortablePolygon.ts b/core/geometry/src/geometry3d/SortablePolygon.ts index 2d5e0ea091bb..be586553b9bf 100644 --- a/core/geometry/src/geometry3d/SortablePolygon.ts +++ b/core/geometry/src/geometry3d/SortablePolygon.ts @@ -6,9 +6,9 @@ /** @packageDocumentation * @module CartesianGeometry */ -import { AnyRegion } from "../curve/CurveTypes"; import { CurveChain } from "../curve/CurveCollection"; import { CurvePrimitive } from "../curve/CurvePrimitive"; +import { AnyRegion } from "../curve/CurveTypes"; import { LineString3d } from "../curve/LineString3d"; import { Loop } from "../curve/Loop"; import { ParityRegion } from "../curve/ParityRegion"; @@ -54,7 +54,9 @@ abstract class SimpleRegionCarrier { class PolygonCarrier extends SimpleRegionCarrier { public data: IndexedReadWriteXYZCollection; private _signedArea: number; - public get signedArea(): number { return this._signedArea; } + public get signedArea(): number { + return this._signedArea; + } public constructor(data: IndexedReadWriteXYZCollection) { super(); this.data = data; @@ -79,7 +81,9 @@ class PolygonCarrier extends SimpleRegionCarrier { } return undefined; } - public grabPolygon(): IndexedReadWriteXYZCollection | undefined { return this.data; } + public grabPolygon(): IndexedReadWriteXYZCollection | undefined { + return this.data; + } public grabLoop(): Loop | undefined { return Loop.createPolygon(this.data); } @@ -109,7 +113,6 @@ class PolygonCarrier extends SimpleRegionCarrier { } return undefined; } - } /** * Implement `LoopCarrier` queries with the area as a strongly typed `Loop` @@ -117,7 +120,9 @@ class PolygonCarrier extends SimpleRegionCarrier { class LoopCarrier extends SimpleRegionCarrier { public data: Loop; private _signedArea: number; - public get signedArea(): number { return this._signedArea; } + public get signedArea(): number { + return this._signedArea; + } public constructor(data: Loop) { super(); this.data = data; @@ -196,7 +201,6 @@ export class SortablePolygon { public isHole: boolean; public outputSetIndex?: number; /** - * * @param loop Loop to capture. */ public constructor(loop: IndexedReadWriteXYZCollection | Loop, range: Range3d) { diff --git a/core/geometry/src/geometry3d/Transform.ts b/core/geometry/src/geometry3d/Transform.ts index 69291160e1eb..76f2522de732 100644 --- a/core/geometry/src/geometry3d/Transform.ts +++ b/core/geometry/src/geometry3d/Transform.ts @@ -85,18 +85,30 @@ export class Transform implements BeJSONFunctions { } if (Geometry.isArrayOfNumberArray(json, 3, 4)) { this._matrix.setRowValues( - json[0][0], json[0][1], json[0][2], - json[1][0], json[1][1], json[1][2], - json[2][0], json[2][1], json[2][2], + json[0][0], + json[0][1], + json[0][2], + json[1][0], + json[1][1], + json[1][2], + json[2][0], + json[2][1], + json[2][2], ); this._origin.set(json[0][3], json[1][3], json[2][3]); return; } if (Geometry.isNumberArray(json, 12)) { this._matrix.setRowValues( - json[0], json[1], json[2], - json[4], json[5], json[6], - json[8], json[9], json[10], + json[0], + json[1], + json[2], + json[4], + json[5], + json[6], + json[8], + json[9], + json[10], ); this._origin.set(json[3], json[7], json[11]); return; @@ -134,7 +146,7 @@ export class Transform implements BeJSONFunctions { /** * Return a 3 by 4 matrix containing the rows of this Transform. * * The transform's origin coordinates are the last entries of the 3 json arrays - */ + */ public toJSON(): TransformProps { return this.toRows(); } @@ -179,9 +191,18 @@ export class Transform implements BeJSONFunctions { } /** Create a Transform with complete contents given. `q` inputs make the matrix and `a` inputs make the origin */ public static createRowValues( - qxx: number, qxy: number, qxz: number, ax: number, - qyx: number, qyy: number, qyz: number, ay: number, - qzx: number, qzy: number, qzz: number, az: number, + qxx: number, + qxy: number, + qxz: number, + ax: number, + qyx: number, + qyy: number, + qyz: number, + ay: number, + qzx: number, + qzy: number, + qzz: number, + az: number, result?: Transform, ): Transform { if (result) { @@ -264,7 +285,9 @@ export class Transform implements BeJSONFunctions { * * If origin is `undefined`, (0,0,0) is used. If matrix is `undefined` the identity matrix is used. */ public static createOriginAndMatrix( - origin: XYZ | undefined, matrix: Matrix3d | undefined, result?: Transform, + origin: XYZ | undefined, + matrix: Matrix3d | undefined, + result?: Transform, ): Transform { if (result) { result._origin.setFromPoint3d(origin); @@ -279,7 +302,10 @@ export class Transform implements BeJSONFunctions { } /** Create a Transform using the given `origin` and columns of the `matrix`. If `undefined` zero is used. */ public setOriginAndMatrixColumns( - origin: XYZ | undefined, vectorX: Vector3d | undefined, vectorY: Vector3d | undefined, vectorZ: Vector3d | undefined, + origin: XYZ | undefined, + vectorX: Vector3d | undefined, + vectorY: Vector3d | undefined, + vectorZ: Vector3d | undefined, ): void { if (origin !== undefined) this._origin.setFrom(origin); @@ -287,7 +313,11 @@ export class Transform implements BeJSONFunctions { } /** Create a Transform using the given `origin` and columns of the `matrix` */ public static createOriginAndMatrixColumns( - origin: XYZ, vectorX: Vector3d, vectorY: Vector3d, vectorZ: Vector3d, result?: Transform, + origin: XYZ, + vectorX: Vector3d, + vectorY: Vector3d, + vectorZ: Vector3d, + result?: Transform, ): Transform { if (result) result.setOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ); @@ -300,7 +330,11 @@ export class Transform implements BeJSONFunctions { * @see [[Matrix3d.createRigidFromColumns]] for details of how the matrix is created to be rigid. */ public static createRigidFromOriginAndColumns( - origin: XYZ | undefined, vectorX: Vector3d, vectorY: Vector3d, axisOrder: AxisOrder, result?: Transform, + origin: XYZ | undefined, + vectorX: Vector3d, + vectorY: Vector3d, + axisOrder: AxisOrder, + result?: Transform, ): Transform | undefined { const matrix = Matrix3d.createRigidFromColumns(vectorX, vectorY, axisOrder, result ? result._matrix : undefined); if (!matrix) @@ -326,7 +360,9 @@ export class Transform implements BeJSONFunctions { * where `f` is the fixedPoint (i.e., `Tp = M*(p-f) + f`). */ public static createFixedPointAndMatrix( - fixedPoint: XYAndZ | undefined, matrix: Matrix3d, result?: Transform, + fixedPoint: XYAndZ | undefined, + matrix: Matrix3d, + result?: Transform, ): Transform { if (fixedPoint) { /** @@ -343,7 +379,10 @@ export class Transform implements BeJSONFunctions { * point `p` to `M*(p-a) + b` (i.e., `Tp = M*(p-a) + b`), so maps `a` to `b`. */ public static createMatrixPickupPutdown( - matrix: Matrix3d, a: Point3d, b: Point3d, result?: Transform, + matrix: Matrix3d, + a: Point3d, + b: Point3d, + result?: Transform, ): Transform { // we define the origin o = b - M*a so Tp = M*p + o = M*p + (b - M*a) = M*(p-a) + b const origin = Matrix3d.xyzMinusMatrixTimesXYZ(b, matrix, a); diff --git a/core/geometry/src/geometry3d/UVSurfaceOps.ts b/core/geometry/src/geometry3d/UVSurfaceOps.ts index 760c27edb6b0..ce756508044f 100644 --- a/core/geometry/src/geometry3d/UVSurfaceOps.ts +++ b/core/geometry/src/geometry3d/UVSurfaceOps.ts @@ -54,16 +54,16 @@ export class UVSurfaceOps { } /** Return the range of sampled points at specified offset from the surface. - * * point counts in each direction may be set in the optional `options` structure, with angle ranges from the ellipsoid. - * * Default evaluation is at 5 degree intervals. - */ + * * point counts in each direction may be set in the optional `options` structure, with angle ranges from the ellipsoid. + * * Default evaluation is at 5 degree intervals. + */ public static sampledRangeOfOffsetEllipsoidPatch(patch: EllipsoidPatch, offsetDistance: number | undefined, options?: StrokeOptions): Range3d { const numU = StrokeOptions.applyAngleTol(options, 2, patch.latitudeSweep.sweepRadians, Angle.degreesToRadians(5.0)); const numV = StrokeOptions.applyAngleTol(options, 2, patch.longitudeSweep.sweepRadians, Angle.degreesToRadians(5.0)); return this.sampledRangeOfOffsetPatch(patch, offsetDistance, numU, numV); } - private constructor() { } // private constructor -- no instances. + private constructor() {} // private constructor -- no instances. /** * * evaluate `numEdge+1` points at surface uv parameters interpolated between (u0,v0) and (u1,v1) * * accumulate the xyz in a linestring. @@ -88,8 +88,8 @@ export class UVSurfaceOps { v1: number, numEdge: number, saveUV: boolean = false, - saveFraction: boolean = false): LineString3d { - + saveFraction: boolean = false, + ): LineString3d { const ls = LineString3d.create(); const xyz = Point3d.create(); let fraction, u, v; diff --git a/core/geometry/src/geometry3d/XYZProps.ts b/core/geometry/src/geometry3d/XYZProps.ts index 73da74ddb076..1b2340db8e25 100644 --- a/core/geometry/src/geometry3d/XYZProps.ts +++ b/core/geometry/src/geometry3d/XYZProps.ts @@ -94,7 +94,10 @@ export type LowAndHighXY = Readonly; /** JSON representation of [[LowAndHighXY]]. * @public */ -export interface LowAndHighXYProps { low: XYProps, high: XYProps } +export interface LowAndHighXYProps { + low: XYProps; + high: XYProps; +} /** * Interface for type with readable `low` and `high` members which have `x`, `y`, and `z` number members. @@ -105,7 +108,10 @@ export type LowAndHighXYZ = Readonly; /** JSON representation of [[LowAndHighXYZ]]. * @public */ -export interface LowAndHighXYZProps { low: XYZProps, high: XYZProps } +export interface LowAndHighXYZProps { + low: XYZProps; + high: XYZProps; +} /** * Interface for variant json (one of) diff --git a/core/geometry/src/geometry3d/YawPitchRollAngles.ts b/core/geometry/src/geometry3d/YawPitchRollAngles.ts index 64f75df58d66..ef9c317686f3 100644 --- a/core/geometry/src/geometry3d/YawPitchRollAngles.ts +++ b/core/geometry/src/geometry3d/YawPitchRollAngles.ts @@ -172,32 +172,38 @@ export class YawPitchRollAngles { const cx = Math.cos(this.roll.radians); const sx = Math.sin(this.roll.radians); /** - * The axis order is XYZ (i.e., RPY) so the rotation matrix is calculated via rZ*rY*rX where - * rX, rY, and rZ are base rotation matrixes: - * - * const rX = Matrix3d.createRowValues( - * 1, 0, 0, - * 0, Math.cos(x), -Math.sin(x), - * 0, Math.sin(x), Math.cos(x), - * ); - * const rY = Matrix3d.createRowValues( - * Math.cos(y), 0, Math.sin(y), - * 0, 1, 0, - * -Math.sin(y), 0, Math.cos(y), - * ); - * const rZ = Matrix3d.createRowValues( - * Math.cos(z), -Math.sin(z), 0, - * Math.sin(z), Math.cos(z), 0, - * 0, 0, 1, - * ); - * - * Then we replace sin(y) with -sin(y) because y rotation (i.e., pitch) is clockwise (alternatively, you - * can use transpose of rY in the matrix multiplication to get the same result) - */ + * The axis order is XYZ (i.e., RPY) so the rotation matrix is calculated via rZ*rY*rX where + * rX, rY, and rZ are base rotation matrixes: + * + * const rX = Matrix3d.createRowValues( + * 1, 0, 0, + * 0, Math.cos(x), -Math.sin(x), + * 0, Math.sin(x), Math.cos(x), + * ); + * const rY = Matrix3d.createRowValues( + * Math.cos(y), 0, Math.sin(y), + * 0, 1, 0, + * -Math.sin(y), 0, Math.cos(y), + * ); + * const rZ = Matrix3d.createRowValues( + * Math.cos(z), -Math.sin(z), 0, + * Math.sin(z), Math.cos(z), 0, + * 0, 0, 1, + * ); + * + * Then we replace sin(y) with -sin(y) because y rotation (i.e., pitch) is clockwise (alternatively, you + * can use transpose of rY in the matrix multiplication to get the same result) + */ return Matrix3d.createRowValues( - cz * cy, -(sz * cx + cz * sy * sx), (sz * sx - cz * sy * cx), - sz * cy, (cz * cx - sz * sy * sx), -(cz * sx + sz * sy * cx), - sy, cy * sx, cy * cx, + cz * cy, + -(sz * cx + cz * sy * sx), + sz * sx - cz * sy * cx, + sz * cy, + cz * cx - sz * sy * sx, + -(cz * sx + sz * sy * cx), + sy, + cy * sx, + cy * cx, result, ); } diff --git a/core/geometry/src/geometry4d/Map4d.ts b/core/geometry/src/geometry4d/Map4d.ts index 60817c81d0ce..61dbaae858f5 100644 --- a/core/geometry/src/geometry4d/Map4d.ts +++ b/core/geometry/src/geometry4d/Map4d.ts @@ -63,7 +63,11 @@ export class Map4d implements BeJSONFunctions { * @param highB high point of box B */ public static createBoxMap( - lowA: Point3d, highA: Point3d, lowB: Point3d, highB: Point3d, result?: Map4d, + lowA: Point3d, + highA: Point3d, + lowB: Point3d, + highB: Point3d, + result?: Map4d, ): Map4d | undefined { const t0 = Matrix4d.createBoxToBox(lowA, highA, lowB, highB, result ? result.transform0 : undefined); const t1 = Matrix4d.createBoxToBox(lowB, highB, lowA, highA, result ? result.transform1 : undefined); @@ -119,7 +123,11 @@ export class Map4d implements BeJSONFunctions { * @param fraction front size divided by rear size. */ public static createVectorFrustum( - origin: Point3d, uVector: Vector3d, vVector: Vector3d, wVector: Vector3d, fraction: number, + origin: Point3d, + uVector: Vector3d, + vVector: Vector3d, + wVector: Vector3d, + fraction: number, ): Map4d | undefined { fraction = Math.max(fraction, 1.0e-8); const slabToWorld = Transform.createOriginAndMatrix(origin, Matrix3d.createColumns(uVector, vVector, wVector)); diff --git a/core/geometry/src/geometry4d/Matrix4d.ts b/core/geometry/src/geometry4d/Matrix4d.ts index f5e7d3b19736..90cd4e820b99 100644 --- a/core/geometry/src/geometry4d/Matrix4d.ts +++ b/core/geometry/src/geometry4d/Matrix4d.ts @@ -36,7 +36,9 @@ export type Matrix4dProps = Point4dProps[]; */ export class Matrix4d implements BeJSONFunctions { private _coffs: Float64Array; - private constructor() { this._coffs = new Float64Array(16); } + private constructor() { + this._coffs = new Float64Array(16); + } /** Copy matrix entries from `other` */ public setFrom(other: Matrix4d): void { for (let i = 0; i < 16; i++) @@ -61,7 +63,11 @@ export class Matrix4d implements BeJSONFunctions { public setIdentity(): void { for (let i = 0; i < 16; i++) this._coffs[i] = 0; - this._coffs[0] = this._coffs[5] = this._coffs[10] = this._coffs[15] = 1.0; + this._coffs[0] = + this._coffs[5] = + this._coffs[10] = + this._coffs[15] = + 1.0; } private static is1000(a: number, b: number, c: number, d: number, tol: number): boolean { return Math.abs(a - 1.0) <= tol @@ -85,7 +91,25 @@ export class Matrix4d implements BeJSONFunctions { return new Matrix4d(); // this is zero. } /** create a Matrix4d with values supplied "across the rows" */ - public static createRowValues(cxx: number, cxy: number, cxz: number, cxw: number, cyx: number, cyy: number, cyz: number, cyw: number, czx: number, czy: number, czz: number, czw: number, cwx: number, cwy: number, cwz: number, cww: number, result?: Matrix4d): Matrix4d { + public static createRowValues( + cxx: number, + cxy: number, + cxz: number, + cxw: number, + cyx: number, + cyy: number, + cyz: number, + cyw: number, + czx: number, + czy: number, + czz: number, + czw: number, + cwx: number, + cwy: number, + cwz: number, + cww: number, + result?: Matrix4d, + ): Matrix4d { result = result ? result : new Matrix4d(); result._coffs[0] = cxx; result._coffs[1] = cxy; @@ -108,10 +132,24 @@ export class Matrix4d implements BeJSONFunctions { /** Create a `Matrix4d` from 16 values appearing as `Point4d` for each row. */ public static createRows(rowX: Point4d, rowY: Point4d, rowZ: Point4d, rowW: Point4d, result?: Matrix4d): Matrix4d { return this.createRowValues( - rowX.x, rowX.y, rowX.z, rowX.w, - rowY.x, rowY.y, rowY.z, rowY.w, - rowZ.x, rowZ.y, rowZ.z, rowZ.w, - rowW.x, rowW.y, rowW.z, rowW.w, result); + rowX.x, + rowX.y, + rowX.z, + rowX.w, + rowY.x, + rowY.y, + rowY.z, + rowY.w, + rowZ.x, + rowZ.y, + rowZ.z, + rowZ.w, + rowW.x, + rowW.y, + rowW.z, + rowW.w, + result, + ); } /** directly set columns from typical 3d data: * @@ -140,7 +178,25 @@ export class Matrix4d implements BeJSONFunctions { public static createTransform(source: Transform, result?: Matrix4d): Matrix4d { const matrix = source.matrix; const point = source.origin; - return Matrix4d.createRowValues(matrix.coffs[0], matrix.coffs[1], matrix.coffs[2], point.x, matrix.coffs[3], matrix.coffs[4], matrix.coffs[5], point.y, matrix.coffs[6], matrix.coffs[7], matrix.coffs[8], point.z, 0, 0, 0, 1, result); + return Matrix4d.createRowValues( + matrix.coffs[0], + matrix.coffs[1], + matrix.coffs[2], + point.x, + matrix.coffs[3], + matrix.coffs[4], + matrix.coffs[5], + point.y, + matrix.coffs[6], + matrix.coffs[7], + matrix.coffs[8], + point.z, + 0, + 0, + 0, + 1, + result, + ); } /** return an identity matrix. */ public static createIdentity(result?: Matrix4d): Matrix4d { @@ -186,7 +242,15 @@ export class Matrix4d implements BeJSONFunctions { * @param scaleZ z diagonal entry * @param result optional result. */ - public static createTranslationAndScaleXYZ(tx: number, ty: number, tz: number, scaleX: number, scaleY: number, scaleZ: number, result?: Matrix4d): Matrix4d { + public static createTranslationAndScaleXYZ( + tx: number, + ty: number, + tz: number, + scaleX: number, + scaleY: number, + scaleZ: number, + result?: Matrix4d, + ): Matrix4d { return Matrix4d.createRowValues(scaleX, 0, 0, tx, 0, scaleY, 0, ty, 0, 0, scaleZ, tz, 0, 0, 0, 1, result); } /** @@ -246,7 +310,9 @@ export class Matrix4d implements BeJSONFunctions { return Geometry.isSmallMetricDistance(this.maxDiff(other)); } /** Test for exact (bitwise) equality with other. */ - public isExactEqual(other: Matrix4d): boolean { return this.maxDiff(other) === 0.0; } + public isExactEqual(other: Matrix4d): boolean { + return this.maxDiff(other) === 0.0; + } /** * Convert an Matrix4d to a Matrix4dProps. */ @@ -280,21 +346,37 @@ export class Matrix4d implements BeJSONFunctions { return Point4d.create(this._coffs[i0], this._coffs[i0 + step], this._coffs[i0 + 2 * step], this._coffs[i0 + 3 * step], result); } /** Return column 0 as Point4d. */ - public columnX(): Point4d { return this.getSteppedPoint(0, 4); } + public columnX(): Point4d { + return this.getSteppedPoint(0, 4); + } /** Return column 1 as Point4d. */ - public columnY(): Point4d { return this.getSteppedPoint(1, 4); } + public columnY(): Point4d { + return this.getSteppedPoint(1, 4); + } /** Return column 2 as Point4d. */ - public columnZ(): Point4d { return this.getSteppedPoint(2, 4); } + public columnZ(): Point4d { + return this.getSteppedPoint(2, 4); + } /** Return column 3 as Point4d. */ - public columnW(): Point4d { return this.getSteppedPoint(3, 4); } + public columnW(): Point4d { + return this.getSteppedPoint(3, 4); + } /** Return row 0 as Point4d. */ - public rowX(): Point4d { return this.getSteppedPoint(0, 1); } + public rowX(): Point4d { + return this.getSteppedPoint(0, 1); + } /** Return row 1 as Point4d. */ - public rowY(): Point4d { return this.getSteppedPoint(4, 1); } + public rowY(): Point4d { + return this.getSteppedPoint(4, 1); + } /** Return row 2 as Point4d. */ - public rowZ(): Point4d { return this.getSteppedPoint(8, 1); } + public rowZ(): Point4d { + return this.getSteppedPoint(8, 1); + } /** Return row 3 as Point4d. */ - public rowW(): Point4d { return this.getSteppedPoint(12, 1); } + public rowW(): Point4d { + return this.getSteppedPoint(12, 1); + } /** * Returns true if the w row has content other than [0,0,0,1] */ @@ -307,12 +389,26 @@ export class Matrix4d implements BeJSONFunctions { /** * Return a Point4d with the diagonal entries of the matrix */ - public diagonal(): Point4d { return this.getSteppedPoint(0, 5); } + public diagonal(): Point4d { + return this.getSteppedPoint(0, 5); + } /** return the weight component of this matrix */ - public weight(): number { return this._coffs[15]; } + public weight(): number { + return this._coffs[15]; + } /** return the leading 3x3 matrix part of this matrix */ public matrixPart(): Matrix3d { - return Matrix3d.createRowValues(this._coffs[0], this._coffs[1], this._coffs[2], this._coffs[4], this._coffs[5], this._coffs[6], this._coffs[8], this._coffs[9], this._coffs[10]); + return Matrix3d.createRowValues( + this._coffs[0], + this._coffs[1], + this._coffs[2], + this._coffs[4], + this._coffs[5], + this._coffs[6], + this._coffs[8], + this._coffs[9], + this._coffs[10], + ); } /** * Return the (affine, non-perspective) Transform with the upper 3 rows of this matrix @@ -321,15 +417,27 @@ export class Matrix4d implements BeJSONFunctions { public get asTransform(): Transform | undefined { if (this.hasPerspective) return undefined; - return Transform.createRowValues(this._coffs[0], this._coffs[1], this._coffs[2], this._coffs[3], this._coffs[4], this._coffs[5], this._coffs[6], this._coffs[7], this._coffs[8], this._coffs[9], this._coffs[10], this._coffs[11]); + return Transform.createRowValues( + this._coffs[0], + this._coffs[1], + this._coffs[2], + this._coffs[3], + this._coffs[4], + this._coffs[5], + this._coffs[6], + this._coffs[7], + this._coffs[8], + this._coffs[9], + this._coffs[10], + this._coffs[11], + ); } /** multiply this * other. */ public multiplyMatrixMatrix(other: Matrix4d, result?: Matrix4d): Matrix4d { result = (result && result !== this && result !== other) ? result : new Matrix4d(); for (let i0 = 0; i0 < 16; i0 += 4) { for (let k = 0; k < 4; k++) - result._coffs[i0 + k] = - this._coffs[i0] * other._coffs[k] + + result._coffs[i0 + k] = this._coffs[i0] * other._coffs[k] + this._coffs[i0 + 1] * other._coffs[k + 4] + this._coffs[i0 + 2] * other._coffs[k + 8] + this._coffs[i0 + 3] * other._coffs[k + 12]; @@ -342,8 +450,7 @@ export class Matrix4d implements BeJSONFunctions { let j = 0; for (let i0 = 0; i0 < 16; i0 += 4) { for (let k = 0; k < 16; k += 4) - result._coffs[j++] = - this._coffs[i0] * other._coffs[k] + + result._coffs[j++] = this._coffs[i0] * other._coffs[k] + this._coffs[i0 + 1] * other._coffs[k + 1] + this._coffs[i0 + 2] * other._coffs[k + 2] + this._coffs[i0 + 3] * other._coffs[k + 3]; @@ -356,8 +463,7 @@ export class Matrix4d implements BeJSONFunctions { let j = 0; for (let i0 = 0; i0 < 4; i0 += 1) { for (let k0 = 0; k0 < 4; k0 += 1) - result._coffs[j++] = - this._coffs[i0] * other._coffs[k0] + + result._coffs[j++] = this._coffs[i0] * other._coffs[k0] + this._coffs[i0 + 4] * other._coffs[k0 + 4] + this._coffs[i0 + 8] * other._coffs[k0 + 8] + this._coffs[i0 + 12] * other._coffs[k0 + 12]; @@ -366,12 +472,35 @@ export class Matrix4d implements BeJSONFunctions { } /** Return a transposed matrix. */ public cloneTransposed(result?: Matrix4d): Matrix4d { - return Matrix4d.createRowValues(this._coffs[0], this._coffs[4], this._coffs[8], this._coffs[12], this._coffs[1], this._coffs[5], this._coffs[9], this._coffs[13], this._coffs[2], this._coffs[6], this._coffs[10], this._coffs[14], this._coffs[3], this._coffs[7], this._coffs[11], this._coffs[15], result); + return Matrix4d.createRowValues( + this._coffs[0], + this._coffs[4], + this._coffs[8], + this._coffs[12], + this._coffs[1], + this._coffs[5], + this._coffs[9], + this._coffs[13], + this._coffs[2], + this._coffs[6], + this._coffs[10], + this._coffs[14], + this._coffs[3], + this._coffs[7], + this._coffs[11], + this._coffs[15], + result, + ); } /** multiply matrix times column [x,y,z,w]. return as Point4d. (And the returned value is NOT normalized down to unit w) */ public multiplyXYZW(x: number, y: number, z: number, w: number, result?: Point4d): Point4d { result = result ? result : Point4d.createZero(); - return result.set(this._coffs[0] * x + this._coffs[1] * y + this._coffs[2] * z + this._coffs[3] * w, this._coffs[4] * x + this._coffs[5] * y + this._coffs[6] * z + this._coffs[7] * w, this._coffs[8] * x + this._coffs[9] * y + this._coffs[10] * z + this._coffs[11] * w, this._coffs[12] * x + this._coffs[13] * y + this._coffs[14] * z + this._coffs[15] * w); + return result.set( + this._coffs[0] * x + this._coffs[1] * y + this._coffs[2] * z + this._coffs[3] * w, + this._coffs[4] * x + this._coffs[5] * y + this._coffs[6] * z + this._coffs[7] * w, + this._coffs[8] * x + this._coffs[9] * y + this._coffs[10] * z + this._coffs[11] * w, + this._coffs[12] * x + this._coffs[13] * y + this._coffs[14] * z + this._coffs[15] * w, + ); } /** multiply matrix times column vectors [x,y,z,w] where [x,y,z,w] appear in blocks in an array. * replace the xyzw in the block @@ -396,12 +525,19 @@ export class Matrix4d implements BeJSONFunctions { } /** multiply matrix times and array of XYAndZ. return as array of Point4d (And the returned value is NOT normalized down to unit w) */ public multiplyPoint3dArray(pts: XYAndZ[], results: Point4d[], w: number = 1.0): void { - pts.forEach((pt, i) => { results[i] = this.multiplyXYZW(pt.x, pt.y, pt.z, w, results[i]); }); + pts.forEach((pt, i) => { + results[i] = this.multiplyXYZW(pt.x, pt.y, pt.z, w, results[i]); + }); } /** multiply [x,y,z,w] times matrix. return as Point4d. (And the returned value is NOT normalized down to unit w) */ public multiplyTransposeXYZW(x: number, y: number, z: number, w: number, result?: Point4d): Point4d { result = result ? result : Point4d.createZero(); - return result.set(this._coffs[0] * x + this._coffs[4] * y + this._coffs[8] * z + this._coffs[12] * w, this._coffs[1] * x + this._coffs[5] * y + this._coffs[9] * z + this._coffs[13] * w, this._coffs[2] * x + this._coffs[6] * y + this._coffs[10] * z + this._coffs[14] * w, this._coffs[3] * x + this._coffs[7] * y + this._coffs[11] * z + this._coffs[15] * w); + return result.set( + this._coffs[0] * x + this._coffs[4] * y + this._coffs[8] * z + this._coffs[12] * w, + this._coffs[1] * x + this._coffs[5] * y + this._coffs[9] * z + this._coffs[13] * w, + this._coffs[2] * x + this._coffs[6] * y + this._coffs[10] * z + this._coffs[14] * w, + this._coffs[3] * x + this._coffs[7] * y + this._coffs[11] * z + this._coffs[15] * w, + ); } /** Returns dot product of row rowIndex of this with column columnIndex of other. */ @@ -469,7 +605,11 @@ export class Matrix4d implements BeJSONFunctions { */ public multiplyXYZWQuietRenormalize(x: number, y: number, z: number, w: number, result?: Point3d): Point3d { result = result ? result : Point3d.createZero(); - result.set(this._coffs[0] * x + this._coffs[1] * y + this._coffs[2] * z + this._coffs[3] * w, this._coffs[4] * x + this._coffs[5] * y + this._coffs[6] * z + this._coffs[7] * w, this._coffs[8] * x + this._coffs[9] * y + this._coffs[10] * z + this._coffs[11] * w); + result.set( + this._coffs[0] * x + this._coffs[1] * y + this._coffs[2] * z + this._coffs[3] * w, + this._coffs[4] * x + this._coffs[5] * y + this._coffs[6] * z + this._coffs[7] * w, + this._coffs[8] * x + this._coffs[9] * y + this._coffs[10] * z + this._coffs[11] * w, + ); const w1 = this._coffs[12] * x + this._coffs[13] * y + this._coffs[14] * z + this._coffs[15] * w; const qx = Geometry.conditionalDivideCoordinate(result.x, w1); const qy = Geometry.conditionalDivideCoordinate(result.y, w1); @@ -483,7 +623,9 @@ export class Matrix4d implements BeJSONFunctions { } /** multiply matrix * an array of Point4d. immediately renormalize to return in an array of Point3d. */ public multiplyPoint4dArrayQuietRenormalize(pts: Point4d[], results: Point3d[]): void { - pts.forEach((pt, i) => { results[i] = this.multiplyXYZWQuietRenormalize(pt.x, pt.y, pt.z, pt.w, results[i]); }); + pts.forEach((pt, i) => { + results[i] = this.multiplyXYZWQuietRenormalize(pt.x, pt.y, pt.z, pt.w, results[i]); + }); } /** multiply a Point4d, return with the optional result convention. */ public multiplyPoint4d(point: Point4d, result?: Point4d): Point4d { @@ -549,17 +691,30 @@ export class Matrix4d implements BeJSONFunctions { return; let iA = rowIndexA * 4 + firstColumnIndex; let iB = rowIndexB * 4 + firstColumnIndex; - for (let i = firstColumnIndex; i < 4; i++ , iA++ , iB++) + for (let i = firstColumnIndex; i < 4; i++, iA++, iB++) this._coffs[iB] += scale * this._coffs[iA]; } /** Return the determinant of the matrix. */ public determinant(): number { const c = this._coffs; return Geometry.determinant4x4( - c[0], c[1], c[2], c[3], - c[4], c[5], c[6], c[7], - c[8], c[9], c[10], c[11], - c[12], c[13], c[14], c[15]); + c[0], + c[1], + c[2], + c[3], + c[4], + c[5], + c[6], + c[7], + c[8], + c[9], + c[10], + c[11], + c[12], + c[13], + c[14], + c[15], + ); } /** Compute an inverse matrix. * * This uses direct formulas with various determinants. @@ -590,7 +745,7 @@ export class Matrix4d implements BeJSONFunctions { columnC.scale(divMaxAbsC, columnC); columnD.scale(divMaxAbsD, columnD); const rowBCD = Point4d.perpendicularPoint4dPlane(columnB, columnC, columnD); - const rowCDA = Point4d.perpendicularPoint4dPlane(columnA, columnD, columnC); // order for negation ! + const rowCDA = Point4d.perpendicularPoint4dPlane(columnA, columnD, columnC); // order for negation ! const rowDAB = Point4d.perpendicularPoint4dPlane(columnD, columnA, columnB); const rowABC = Point4d.perpendicularPoint4dPlane(columnC, columnB, columnA); // order for negation ! // The matrix is singular if the determinant is zero. @@ -606,9 +761,11 @@ export class Matrix4d implements BeJSONFunctions { const determinantC = rowDAB.dotProduct(columnC); const determinantD = rowABC.dotProduct(columnD); const maxAbs1 = result.maxAbs(); - if (determinantA * determinantB > 0.0 + if ( + determinantA * determinantB > 0.0 && determinantA * determinantC > 0.0 - && determinantA * determinantD > 0.0) { + && determinantA * determinantD > 0.0 + ) { const divisionTest = Geometry.conditionalDivideCoordinate(maxAbs1, determinantA); if (divisionTest !== undefined) { const divDet = 1.0 / determinantA; @@ -629,13 +786,15 @@ export class Matrix4d implements BeJSONFunctions { [f(this._coffs[0]), f(this._coffs[1]), f(this._coffs[2]), f(this._coffs[3])], [f(this._coffs[4]), f(this._coffs[5]), f(this._coffs[6]), f(this._coffs[7])], [f(this._coffs[8]), f(this._coffs[9]), f(this._coffs[10]), f(this._coffs[11])], - [f(this._coffs[12]), f(this._coffs[13]), f(this._coffs[14]), f(this._coffs[15])]]; + [f(this._coffs[12]), f(this._coffs[13]), f(this._coffs[14]), f(this._coffs[15])], + ]; else return [ [this._coffs[0], this._coffs[1], this._coffs[2], this._coffs[3]], [this._coffs[4], this._coffs[5], this._coffs[6], this._coffs[7]], [this._coffs[8], this._coffs[9], this._coffs[10], this._coffs[11]], - [this._coffs[12], this._coffs[13], this._coffs[14], this._coffs[15]]]; + [this._coffs[12], this._coffs[13], this._coffs[14], this._coffs[15]], + ]; } /** * Scale each row by respective scale factors. @@ -752,19 +911,19 @@ export class Matrix4d implements BeJSONFunctions { const axBeta = ax * beta; const ayBeta = ay * beta; const azBeta = az * beta; - this._coffs[0] += (ax * bx + cx * ax + ax * axBeta); - this._coffs[1] += (ay * bx + cy * ax + ax * ayBeta); - this._coffs[2] += (az * bx + cz * ax + ax * azBeta); + this._coffs[0] += ax * bx + cx * ax + ax * axBeta; + this._coffs[1] += ay * bx + cy * ax + ax * ayBeta; + this._coffs[2] += az * bx + cz * ax + ax * azBeta; this._coffs[3] += axBeta; - this._coffs[4] += (ax * by + cx * ay + ay * axBeta); - this._coffs[5] += (ay * by + cy * ay + ay * ayBeta); - this._coffs[6] += (az * by + cz * ay + ay * azBeta); + this._coffs[4] += ax * by + cx * ay + ay * axBeta; + this._coffs[5] += ay * by + cy * ay + ay * ayBeta; + this._coffs[6] += az * by + cz * ay + ay * azBeta; this._coffs[7] += ayBeta; - this._coffs[8] += (ax * bz + cx * az + az * axBeta); - this._coffs[9] += (ay * bz + cy * az + az * ayBeta); - this._coffs[10] += (az * bz + cz * az + az * azBeta); + this._coffs[8] += ax * bz + cx * az + az * axBeta; + this._coffs[9] += ay * bz + cy * az + az * ayBeta; + this._coffs[10] += az * bz + cz * az + az * azBeta; this._coffs[11] += azBeta; this._coffs[12] += axBeta; diff --git a/core/geometry/src/geometry4d/MomentData.ts b/core/geometry/src/geometry4d/MomentData.ts index 06f02fdd6063..a477dc0b7904 100644 --- a/core/geometry/src/geometry4d/MomentData.ts +++ b/core/geometry/src/geometry4d/MomentData.ts @@ -52,7 +52,9 @@ export class MomentData { /** Return the lower-right (3,3) entry in the sums. * * This is the quantity (i.e. length, area, or volume) summed */ - public get quantitySum(): number { return this.sums.atIJ(3, 3); } + public get quantitySum(): number { + return this.sums.atIJ(3, 3); + } /** Return a scale factor to make these sums match the target orientation sign. * * 1.0 if `this.quantitySum` has the same sign as `targetSign`. * * -1.0 if `this.quantitySum` has the opposite sign from `targetSign` @@ -63,7 +65,6 @@ export class MomentData { /** * If `this.needOrigin` flag is set, copy `origin` to `this.origin` and clear the flag. - * */ public setOriginIfNeeded(origin: Point3d) { if (this.needOrigin) { @@ -73,7 +74,6 @@ export class MomentData { } /** * If `this.needOrigin` flag is set, copy `origin` to `this.origin` and clear the flag. - * */ public setOriginFromGrowableXYZArrayIfNeeded(points: GrowableXYZArray) { if (this.needOrigin && points.length > 0) { @@ -84,7 +84,6 @@ export class MomentData { /** * If `this.needOrigin` flag is set, copy `origin` to `this.origin` and clear the flag. - * */ public setOriginXYZIfNeeded(x: number, y: number, z: number) { if (this.needOrigin) { @@ -97,7 +96,6 @@ export class MomentData { */ public radiusOfGyration: Vector3d; /** principal quantity (e.g. length, area, or volume). This is undefined in raw moments, and becomes defined by - * */ public absoluteQuantity?: number; @@ -107,7 +105,7 @@ export class MomentData { this.localToWorldMap = Transform.createIdentity(); this.radiusOfGyration = Vector3d.create(); this.needOrigin = false; - this.absoluteQuantity = 0.1; // so optimizer sees its type + this.absoluteQuantity = 0.1; // so optimizer sees its type this.absoluteQuantity = undefined; } /** Create moments with optional origin. @@ -116,7 +114,7 @@ export class MomentData { * * (origin) sets up to use that durable origin, set needsOrigin flag false * * (origin, true) the "true" is meaningless * * (undefined, false) makes 000 the durable origin - */ + */ public static create(origin?: Point3d | undefined, needOrigin: boolean = false): MomentData { const data = new MomentData(); data.needOrigin = needOrigin; @@ -199,7 +197,10 @@ export class MomentData { axisVectors.scaleColumnsInPlace(1, -1, -1); moments.localToWorldMap = Transform.createOriginAndMatrix(moments.origin, axisVectors); moments.radiusOfGyration.set( - Math.sqrt(Math.abs(moment2.x)), Math.sqrt(Math.abs(moment2.y)), Math.sqrt(Math.abs(moment2.z))); + Math.sqrt(Math.abs(moment2.x)), + Math.sqrt(Math.abs(moment2.y)), + Math.sqrt(Math.abs(moment2.z)), + ); moments.radiusOfGyration.scaleInPlace(1.0 / Math.sqrt(Math.abs(w))); moments.absoluteQuantity = Math.abs(w); return moments; @@ -219,10 +220,14 @@ export class MomentData { * @param dataB second set of moments */ public static areEquivalentPrincipalAxes(dataA: MomentData | undefined, dataB: MomentData | undefined): boolean { - if (dataA && dataB - && Geometry.isSameCoordinate(dataA.quantitySum, dataB.quantitySum)) { // um.. need different tolerance for area, volume?) - if (dataA.localToWorldMap.getOrigin().isAlmostEqual(dataB.localToWorldMap.getOrigin()) - && dataA.radiusOfGyration.isAlmostEqual(dataB.radiusOfGyration)) { + if ( + dataA && dataB + && Geometry.isSameCoordinate(dataA.quantitySum, dataB.quantitySum) + ) { // um.. need different tolerance for area, volume?) + if ( + dataA.localToWorldMap.getOrigin().isAlmostEqual(dataB.localToWorldMap.getOrigin()) + && dataA.radiusOfGyration.isAlmostEqual(dataB.radiusOfGyration) + ) { if (Geometry.isSameCoordinate(dataA.radiusOfGyration.x, dataA.radiusOfGyration.y)) { // We have at least xy symmetry .... if (Geometry.isSameCoordinate(dataA.radiusOfGyration.x, dataA.radiusOfGyration.z)) @@ -265,7 +270,8 @@ export class MomentData { p.x - this.origin.x, p.y - this.origin.y, p.z - this.origin.z, - 1.0); + 1.0, + ); } } /** revise the accumulated sums to be "around the centroid" */ @@ -281,7 +287,7 @@ export class MomentData { /** revise the accumulated sums * * add ax,ay,ax to the origin coordinates. * * apply the negative translation to the sums. - */ + */ public shiftOriginAndSumsByXYZ(ax: number, ay: number, az: number) { this.origin.addXYZInPlace(ax, ay, az); this.sums.multiplyTranslationSandwichInPlace(-ax, -ay, -az); @@ -298,14 +304,14 @@ export class MomentData { * Accumulate them to this.sums. * * If `pointA` is undefined, use `this.origin` as pointA. * * If `this.needOrigin` is set, pointB is used - */ + */ public accumulateTriangleMomentsXY(pointA: XAndY | undefined, pointB: XAndY, pointC: XAndY) { this.setOriginXYZIfNeeded(pointB.x, pointB.y, 0.0); const x0 = this.origin.x; const y0 = this.origin.y; - const vectorA = MomentData._vectorA = - pointA !== undefined ? Point4d.create(pointA.x - x0, pointA.y - y0, 0.0, 1.0, MomentData._vectorA) - : Point4d.create(this.origin.x, this.origin.y, 0.0, 1.0, MomentData._vectorA); + const vectorA = MomentData._vectorA = pointA !== undefined ? + Point4d.create(pointA.x - x0, pointA.y - y0, 0.0, 1.0, MomentData._vectorA) + : Point4d.create(this.origin.x, this.origin.y, 0.0, 1.0, MomentData._vectorA); const vectorB = MomentData._vectorB = Point4d.create(pointB.x - x0, pointB.y - y0, 0.0, 1.0, MomentData._vectorB); const vectorC = MomentData._vectorC = Point4d.create(pointC.x - x0, pointC.y - y0, 0.0, 1.0, MomentData._vectorC); @@ -333,7 +339,13 @@ export class MomentData { /** add scaled outer product of (4d, unit weight) point to this.sums */ public accumulateScaledOuterProduct(point: XYAndZ, scaleFactor: number) { this.setOriginXYZIfNeeded(point.x, point.y, 0.0); - const vectorA = MomentData._vectorA = Point4d.create(point.x - this.origin.x, point.y - this.origin.y, point.z - this.origin.z, 1.0, MomentData._vectorA); + const vectorA = MomentData._vectorA = Point4d.create( + point.x - this.origin.x, + point.y - this.origin.y, + point.z - this.origin.z, + 1.0, + MomentData._vectorA, + ); this.sums.addScaledOuterProductInPlace(vectorA, vectorA, scaleFactor); } /** Accumulate wire moment integral from pointA to pointB */ @@ -351,7 +363,6 @@ export class MomentData { this.sums.addScaledOuterProductInPlace(vectorA, vectorB, r1_6); this.sums.addScaledOuterProductInPlace(vectorB, vectorA, r1_6); this.sums.addScaledOuterProductInPlace(vectorB, vectorB, r1_3); - } private _point0 = Point3d.create(); @@ -360,7 +371,6 @@ export class MomentData { * Accumulate them to this.sums. * * If `pointA` is undefined, use `this.origin` as pointA. * * If `this.needOrigin` is set, the first point of the array is captured as local origin for subsequent sums. - * */ public accumulateTriangleToLineStringMomentsXY(sweepBase: XAndY | undefined, points: GrowableXYZArray) { const n = points.length; @@ -386,19 +396,52 @@ export class MomentData { * @param vectorU Caller's U axis (not necessarily unit) * @param vectorV Caller's V axis (not necessarily unit) */ - public accumulateXYProductsInCentroidalFrame(productXX: number, productXY: number, productYY: number, area: number, - origin: XAndY, vectorU: XAndY, vectorV: XAndY) { + public accumulateXYProductsInCentroidalFrame( + productXX: number, + productXY: number, + productYY: number, + area: number, + origin: XAndY, + vectorU: XAndY, + vectorV: XAndY, + ) { const centroidalProducts = Matrix4d.createRowValues( - productXX, productXY, 0, 0, - productXY, productYY, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, area); + productXX, + productXY, + 0, + 0, + productXY, + productYY, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + area, + ); const detJ = Geometry.crossProductXYXY(vectorU.x, vectorV.x, vectorU.y, vectorV.y); const placement = Matrix4d.createRowValues( - vectorU.x, vectorV.x, 0, origin.x - this.origin.x, - vectorU.y, vectorV.y, 0, origin.y - this.origin.y, - 0, 0, 0, 0, - 0, 0, 0, 1); + vectorU.x, + vectorV.x, + 0, + origin.x - this.origin.x, + vectorU.y, + vectorV.y, + 0, + origin.y - this.origin.y, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + ); const AB = placement.multiplyMatrixMatrix(centroidalProducts); const ABAT = AB.multiplyMatrixMatrixTranspose(placement); this.sums.addScaledInPlace(ABAT, detJ); @@ -411,15 +454,21 @@ export class MomentData { */ public accumulateProducts(other: MomentData, scale: number) { this.setOriginIfNeeded(other.origin); - this.sums.addTranslationSandwichInPlace(other.sums, this.origin.x - other.origin.x, this.origin.y - other.origin.y, this.origin.z - other.origin.z, scale); + this.sums.addTranslationSandwichInPlace( + other.sums, + this.origin.x - other.origin.x, + this.origin.y - other.origin.y, + this.origin.z - other.origin.z, + scale, + ); } /** - * Accumulate sums from Matrix4d and origin. - * * scale by given scaleFactor (e.g. sign to correct orientation) - * * trap the origin if `this` needs an origin. - * * - */ + * Accumulate sums from Matrix4d and origin. + * * scale by given scaleFactor (e.g. sign to correct orientation) + * * trap the origin if `this` needs an origin. + * * + */ public accumulateProductsFromOrigin(origin: Point3d, products: Matrix4d, scale: number) { this.setOriginIfNeeded(origin); this.sums.addTranslationSandwichInPlace(products, this.origin.x - origin.x, this.origin.y - origin.y, this.origin.z - origin.z, scale); diff --git a/core/geometry/src/geometry4d/PlaneByOriginAndVectors4d.ts b/core/geometry/src/geometry4d/PlaneByOriginAndVectors4d.ts index b2dd71491abd..14a3a20d2bcc 100644 --- a/core/geometry/src/geometry4d/PlaneByOriginAndVectors4d.ts +++ b/core/geometry/src/geometry4d/PlaneByOriginAndVectors4d.ts @@ -51,7 +51,12 @@ export class PlaneByOriginAndVectors4d { } /** Create a plane with (copies of) origin, vectorU, vectorV parameters, all given as full 4d points. */ - public static createOriginAndVectors(origin: Point4d, vectorU: Point4d, vectorV: Point4d, result?: PlaneByOriginAndVectors4d): PlaneByOriginAndVectors4d { + public static createOriginAndVectors( + origin: Point4d, + vectorU: Point4d, + vectorV: Point4d, + result?: PlaneByOriginAndVectors4d, + ): PlaneByOriginAndVectors4d { if (result) { result.setOriginAndVectors(origin, vectorU, vectorV); return result; @@ -59,7 +64,20 @@ export class PlaneByOriginAndVectors4d { return new PlaneByOriginAndVectors4d(origin.clone(), vectorU.clone(), vectorV.clone()); } /** Set all numeric data from complete list of (x,y,z,w) in origin, vectorU, and vectorV */ - public setOriginAndVectorsXYZW(x0: number, y0: number, z0: number, w0: number, ux: number, uy: number, uz: number, uw: number, vx: number, vy: number, vz: number, vw: number): PlaneByOriginAndVectors4d { + public setOriginAndVectorsXYZW( + x0: number, + y0: number, + z0: number, + w0: number, + ux: number, + uy: number, + uz: number, + uw: number, + vx: number, + vy: number, + vz: number, + vw: number, + ): PlaneByOriginAndVectors4d { this.origin.set(x0, y0, z0, w0); this.vectorU.set(ux, uy, uz, uw); this.vectorV.set(vx, vy, vz, vw); @@ -73,14 +91,47 @@ export class PlaneByOriginAndVectors4d { return this; } /** Create from complete list of (x,y,z,w) in origin, vectorU, and vectorV */ - public static createOriginAndVectorsXYZW(x0: number, y0: number, z0: number, w0: number, ux: number, uy: number, uz: number, uw: number, vx: number, vy: number, vz: number, vw: number, result?: PlaneByOriginAndVectors4d): PlaneByOriginAndVectors4d { + public static createOriginAndVectorsXYZW( + x0: number, + y0: number, + z0: number, + w0: number, + ux: number, + uy: number, + uz: number, + uw: number, + vx: number, + vy: number, + vz: number, + vw: number, + result?: PlaneByOriginAndVectors4d, + ): PlaneByOriginAndVectors4d { if (result) return result.setOriginAndVectorsXYZW(x0, y0, z0, w0, ux, uy, uz, uw, vx, vy, vz, vw); return new PlaneByOriginAndVectors4d(Point4d.create(x0, y0, z0, w0), Point4d.create(ux, uy, uz, uw), Point4d.create(vx, vy, vz, uw)); } /** create from origin point, (u=1,v=0) point, and (u=0,v=1) point. */ - public static createOriginAndTargets3d(origin: Point3d, targetU: Point3d, targetV: Point3d, result?: PlaneByOriginAndVectors4d): PlaneByOriginAndVectors4d { - return PlaneByOriginAndVectors4d.createOriginAndVectorsXYZW(origin.x, origin.y, origin.z, 1.0, targetU.x - origin.x, targetU.y - origin.y, targetU.z - origin.z, 0.0, targetV.x - origin.x, targetV.y - origin.y, targetV.z - origin.z, 0.0, result); + public static createOriginAndTargets3d( + origin: Point3d, + targetU: Point3d, + targetV: Point3d, + result?: PlaneByOriginAndVectors4d, + ): PlaneByOriginAndVectors4d { + return PlaneByOriginAndVectors4d.createOriginAndVectorsXYZW( + origin.x, + origin.y, + origin.z, + 1.0, + targetU.x - origin.x, + targetU.y - origin.y, + targetU.z - origin.z, + 0.0, + targetV.x - origin.x, + targetV.y - origin.y, + targetV.z - origin.z, + 0.0, + result, + ); } /** evaluate plane point (full 3d) at given (u,v) coordinate. */ public fractionToPoint(u: number, v: number, result?: Point4d): Point4d { diff --git a/core/geometry/src/geometry4d/Point4d.ts b/core/geometry/src/geometry4d/Point4d.ts index 04e992019450..d474d857d5b1 100644 --- a/core/geometry/src/geometry4d/Point4d.ts +++ b/core/geometry/src/geometry4d/Point4d.ts @@ -21,7 +21,6 @@ import { XAndY, XYAndZ } from "../geometry3d/XYZProps"; */ export type Point4dProps = number[]; /** - * * @param ddg numerator second derivative * @param dh denominator derivative * @param ddh denominator second derivative @@ -30,8 +29,7 @@ export type Point4dProps = number[]; * @param divH = (1/h) * @internal */ -function quotientDerivative2(ddg: number, dh: number, ddh: number, - f: number, df: number, divH: number): number { +function quotientDerivative2(ddg: number, dh: number, ddh: number, f: number, df: number, divH: number): number { return divH * (ddg - 2.0 * df * dh - f * ddh); } @@ -63,17 +61,33 @@ export class Point4d extends Plane3d implements BeJSONFunctions { } } /** The x component. */ - public get x() { return this.xyzw[0]; } - public set x(val: number) { this.xyzw[0] = val; } + public get x() { + return this.xyzw[0]; + } + public set x(val: number) { + this.xyzw[0] = val; + } /** The y component. */ - public get y() { return this.xyzw[1]; } - public set y(val: number) { this.xyzw[1] = val; } + public get y() { + return this.xyzw[1]; + } + public set y(val: number) { + this.xyzw[1] = val; + } /** The z component. */ - public get z() { return this.xyzw[2]; } - public set z(val: number) { this.xyzw[2] = val; } + public get z() { + return this.xyzw[2]; + } + public set z(val: number) { + this.xyzw[2] = val; + } /** The w component of this point. */ - public get w() { return this.xyzw[3]; } - public set w(val: number) { this.xyzw[3] = val; } + public get w() { + return this.xyzw[3]; + } + public set w(val: number) { + this.xyzw[3] = val; + } /** Construct from coordinates. */ protected constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 0) { super(); @@ -153,13 +167,23 @@ export class Point4d extends Plane3d implements BeJSONFunctions { * * x,y,z,w all participate without normalization. */ public distanceXYZW(other: Point4d): number { - return Geometry.hypotenuseXYZW(other.xyzw[0] - this.xyzw[0], other.xyzw[1] - this.xyzw[1], other.xyzw[2] - this.xyzw[2], other.xyzw[3] - this.xyzw[3]); + return Geometry.hypotenuseXYZW( + other.xyzw[0] - this.xyzw[0], + other.xyzw[1] - this.xyzw[1], + other.xyzw[2] - this.xyzw[2], + other.xyzw[3] - this.xyzw[3], + ); } /** Return the squared 4d distance from this point to other, with all 4 components squared into the hypotenuse. * * x,y,z,w all participate without normalization. */ public distanceSquaredXYZW(other: Point4d): number { - return Geometry.hypotenuseSquaredXYZW(other.xyzw[0] - this.xyzw[0], other.xyzw[1] - this.xyzw[1], other.xyzw[2] - this.xyzw[2], other.xyzw[3] - this.xyzw[3]); + return Geometry.hypotenuseSquaredXYZW( + other.xyzw[0] - this.xyzw[0], + other.xyzw[1] - this.xyzw[1], + other.xyzw[2] - this.xyzw[2], + other.xyzw[3] - this.xyzw[3], + ); } /** Return the distance between the instance and other after normalizing by weights */ @@ -174,7 +198,12 @@ export class Point4d extends Plane3d implements BeJSONFunctions { * * x,y,z,w all participate without normalization. */ public maxDiff(other: Point4d): number { - return Math.max(Math.abs(other.xyzw[0] - this.xyzw[0]), Math.abs(other.xyzw[1] - this.xyzw[1]), Math.abs(other.xyzw[2] - this.xyzw[2]), Math.abs(other.xyzw[3] - this.xyzw[3])); + return Math.max( + Math.abs(other.xyzw[0] - this.xyzw[0]), + Math.abs(other.xyzw[1] - this.xyzw[1]), + Math.abs(other.xyzw[2] - this.xyzw[2]), + Math.abs(other.xyzw[3] - this.xyzw[3]), + ); } /** Return the largest absolute entry of all 4 components x,y,z,w */ public maxAbs(): number { @@ -191,13 +220,24 @@ export class Point4d extends Plane3d implements BeJSONFunctions { /** Return the difference (this-other) using all 4 components x,y,z,w */ public minus(other: Point4d, result?: Point4d): Point4d { - return Point4d.create(this.xyzw[0] - other.xyzw[0], this.xyzw[1] - other.xyzw[1], this.xyzw[2] - other.xyzw[2], this.xyzw[3] - other.xyzw[3], result); + return Point4d.create( + this.xyzw[0] - other.xyzw[0], + this.xyzw[1] - other.xyzw[1], + this.xyzw[2] - other.xyzw[2], + this.xyzw[3] - other.xyzw[3], + result, + ); } /** Return `((other.w * this) - (this.w * other))` */ public crossWeightedMinus(other: Point4d, result?: Vector3d): Vector3d { const wa = this.xyzw[3]; const wb = other.xyzw[3]; - return Vector3d.create(wb * this.xyzw[0] - wa * other.xyzw[0], wb * this.xyzw[1] - wa * other.xyzw[1], wb * this.xyzw[2] - wa * other.xyzw[2], result); + return Vector3d.create( + wb * this.xyzw[0] - wa * other.xyzw[0], + wb * this.xyzw[1] - wa * other.xyzw[1], + wb * this.xyzw[2] - wa * other.xyzw[2], + result, + ); } /** Return `((other.w * this) - (this.w * other))`, with other.w known to be 1 */ public crossWeightedMinusPoint3d(other: Point3d, result?: Vector3d): Vector3d { @@ -206,21 +246,35 @@ export class Point4d extends Plane3d implements BeJSONFunctions { } /** Return the sum of this and other, using all 4 components x,y,z,w */ public plus(other: Point4d, result?: Point4d): Point4d { - return Point4d.create(this.xyzw[0] + other.xyzw[0], this.xyzw[1] + other.xyzw[1], this.xyzw[2] + other.xyzw[2], this.xyzw[3] + other.xyzw[3], result); + return Point4d.create( + this.xyzw[0] + other.xyzw[0], + this.xyzw[1] + other.xyzw[1], + this.xyzw[2] + other.xyzw[2], + this.xyzw[3] + other.xyzw[3], + result, + ); } /** Test if all components are nearly zero. */ public get isAlmostZero(): boolean { return Geometry.isSmallMetricDistance(this.maxAbs()); } /** Create a point with zero in all coordinates. */ - public static createZero(): Point4d { return new Point4d(0, 0, 0, 0); } + public static createZero(): Point4d { + return new Point4d(0, 0, 0, 0); + } /** * Create plane coefficients for the plane containing pointA, pointB, and 0010. * @param pointA first point * @param pointB second point */ public static createPlanePointPointZ(pointA: Point4d, pointB: Point4d, result?: Point4d) { - return Point4d.create(pointA.y * pointB.w - pointA.w * pointB.y, pointA.w * pointB.x - pointA.x * pointB.w, 0.0, pointA.x * pointB.y - pointA.y * pointB.x, result); + return Point4d.create( + pointA.y * pointB.w - pointA.w * pointB.y, + pointA.w * pointB.x - pointA.x * pointB.w, + 0.0, + pointA.x * pointB.y - pointA.y * pointB.x, + result, + ); } /** * extract 3 consecutive numbers from a Float64Array into the xyz values of a Point4d with w = 1. @@ -282,33 +336,84 @@ export class Point4d extends Plane3d implements BeJSONFunctions { const z = point.hasOwnProperty("z") ? (point as any).z : 0.0; const w = point.hasOwnProperty("w") ? (point as any).w : 1.0; return new Point4d(x, y, z, w); - } /** Return `point + vector * scalar` */ public plusScaled(vector: Point4d, scaleFactor: number, result?: Point4d): Point4d { - return Point4d.create(this.xyzw[0] + vector.xyzw[0] * scaleFactor, this.xyzw[1] + vector.xyzw[1] * scaleFactor, this.xyzw[2] + vector.xyzw[2] * scaleFactor, this.xyzw[3] + vector.xyzw[3] * scaleFactor, result); + return Point4d.create( + this.xyzw[0] + vector.xyzw[0] * scaleFactor, + this.xyzw[1] + vector.xyzw[1] * scaleFactor, + this.xyzw[2] + vector.xyzw[2] * scaleFactor, + this.xyzw[3] + vector.xyzw[3] * scaleFactor, + result, + ); } /** Return interpolation between instance and pointB at fraction */ public interpolate(fraction: number, pointB: Point4d, result?: Point4d): Point4d { const v = 1.0 - fraction; - return Point4d.create(this.xyzw[0] * v + pointB.xyzw[0] * fraction, this.xyzw[1] * v + pointB.xyzw[1] * fraction, this.xyzw[2] * v + pointB.xyzw[2] * fraction, this.xyzw[3] * v + pointB.xyzw[3] * fraction, result); + return Point4d.create( + this.xyzw[0] * v + pointB.xyzw[0] * fraction, + this.xyzw[1] * v + pointB.xyzw[1] * fraction, + this.xyzw[2] * v + pointB.xyzw[2] * fraction, + this.xyzw[3] * v + pointB.xyzw[3] * fraction, + result, + ); } /** Return `point + vectorA * scalarA + vectorB * scalarB` */ public plus2Scaled(vectorA: Point4d, scalarA: number, vectorB: Point4d, scalarB: number, result?: Point4d): Point4d { - return Point4d.create(this.xyzw[0] + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB, this.xyzw[1] + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB, this.xyzw[2] + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB, this.xyzw[3] + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB, result); + return Point4d.create( + this.xyzw[0] + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB, + this.xyzw[1] + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB, + this.xyzw[2] + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB, + this.xyzw[3] + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB, + result, + ); } /** Return `point + vectorA * scalarA + vectorB * scalarB + vectorC * scalarC` */ - public plus3Scaled(vectorA: Point4d, scalarA: number, vectorB: Point4d, scalarB: number, vectorC: Point4d, scalarC: number, result?: Point4d): Point4d { - return Point4d.create(this.xyzw[0] + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB + vectorC.xyzw[0] * scalarC, this.xyzw[1] + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB + vectorC.xyzw[1] * scalarC, this.xyzw[2] + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB + vectorC.xyzw[2] * scalarC, this.xyzw[3] + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB + vectorC.xyzw[3] * scalarC, result); + public plus3Scaled( + vectorA: Point4d, + scalarA: number, + vectorB: Point4d, + scalarB: number, + vectorC: Point4d, + scalarC: number, + result?: Point4d, + ): Point4d { + return Point4d.create( + this.xyzw[0] + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB + vectorC.xyzw[0] * scalarC, + this.xyzw[1] + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB + vectorC.xyzw[1] * scalarC, + this.xyzw[2] + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB + vectorC.xyzw[2] * scalarC, + this.xyzw[3] + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB + vectorC.xyzw[3] * scalarC, + result, + ); } /** Return `point + vectorA * scalarA + vectorB * scalarB` */ public static createAdd2Scaled(vectorA: Point4d, scalarA: number, vectorB: Point4d, scalarB: number, result?: Point4d): Point4d { - return Point4d.create(vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB, vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB, vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB, vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB, result); + return Point4d.create( + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB, + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB, + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB, + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB, + result, + ); } /** Return `point + vectorA \ scalarA + vectorB * scalarB + vectorC * scalarC` */ - public static createAdd3Scaled(vectorA: Point4d, scalarA: number, vectorB: Point4d, scalarB: number, vectorC: Point4d, scalarC: number, result?: Point4d): Point4d { - return Point4d.create(vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB + vectorC.xyzw[0] * scalarC, vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB + vectorC.xyzw[1] * scalarC, vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB + vectorC.xyzw[2] * scalarC, vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB + vectorC.xyzw[3] * scalarC, result); + public static createAdd3Scaled( + vectorA: Point4d, + scalarA: number, + vectorB: Point4d, + scalarB: number, + vectorC: Point4d, + scalarC: number, + result?: Point4d, + ): Point4d { + return Point4d.create( + vectorA.xyzw[0] * scalarA + vectorB.xyzw[0] * scalarB + vectorC.xyzw[0] * scalarC, + vectorA.xyzw[1] * scalarA + vectorB.xyzw[1] * scalarB + vectorC.xyzw[1] * scalarC, + vectorA.xyzw[2] * scalarA + vectorB.xyzw[2] * scalarB + vectorC.xyzw[2] * scalarC, + vectorA.xyzw[3] * scalarA + vectorB.xyzw[3] * scalarB + vectorC.xyzw[3] * scalarC, + result, + ); } /** Return dot product of (4d) vectors from the instance to targetA and targetB */ public dotVectorsToTargets(targetA: Point4d, targetB: Point4d): number { @@ -348,24 +453,38 @@ export class Point4d extends Plane3d implements BeJSONFunctions { /** * Return the x component of the normal used to evaluate altitude. */ - public normalX(): number { return this.x; } + public normalX(): number { + return this.x; + } /** - * Return the x component of the normal used to evaluate altitude. - */ - public normalY(): number { return this.y; } + * Return the x component of the normal used to evaluate altitude. + */ + public normalY(): number { + return this.y; + } /** - * Return the z component of the normal used to evaluate altitude. - */ - public normalZ(): number { return this.z; } + * Return the z component of the normal used to evaluate altitude. + */ + public normalZ(): number { + return this.z; + } /** unit X vector */ - public static unitX(): Point4d { return new Point4d(1, 0, 0, 0); } + public static unitX(): Point4d { + return new Point4d(1, 0, 0, 0); + } /** unit Y vector */ - public static unitY(): Point4d { return new Point4d(0, 1, 0, 0); } + public static unitY(): Point4d { + return new Point4d(0, 1, 0, 0); + } /** unit Z vector */ - public static unitZ(): Point4d { return new Point4d(0, 0, 1, 0); } + public static unitZ(): Point4d { + return new Point4d(0, 0, 1, 0); + } /** unit W vector */ - public static unitW(): Point4d { return new Point4d(0, 0, 0, 1); } + public static unitW(): Point4d { + return new Point4d(0, 0, 0, 1); + } /** Divide by denominator, but return undefined if denominator is zero. */ public safeDivideOrNull(denominator: number, result?: Point4d): Point4d | undefined { if (denominator !== 0.0) { @@ -464,7 +583,17 @@ export class Point4d extends Plane3d implements BeJSONFunctions { * @param dw w coordinate of derivative * @param result optional result */ - public static createRealDerivativeRay3dDefault000(x: number, y: number, z: number, w: number, dx: number, dy: number, dz: number, dw: number, result?: Ray3d): Ray3d { + public static createRealDerivativeRay3dDefault000( + x: number, + y: number, + z: number, + w: number, + dx: number, + dy: number, + dz: number, + dw: number, + result?: Ray3d, + ): Ray3d { const mag = Geometry.correctSmallFraction(w); // real point is X/w. // real derivative is (X' * w - X *w) / ww, and weight is always 0 by cross products. @@ -485,7 +614,21 @@ export class Point4d extends Plane3d implements BeJSONFunctions { * @param dw w coordinate of derivative * @param result optional result */ - public static createRealDerivativePlane3dByOriginAndVectorsDefault000(x: number, y: number, z: number, w: number, dx: number, dy: number, dz: number, dw: number, ddx: number, ddy: number, ddz: number, ddw: number, result?: Plane3dByOriginAndVectors): Plane3dByOriginAndVectors { + public static createRealDerivativePlane3dByOriginAndVectorsDefault000( + x: number, + y: number, + z: number, + w: number, + dx: number, + dy: number, + dz: number, + dw: number, + ddx: number, + ddy: number, + ddz: number, + ddw: number, + result?: Plane3dByOriginAndVectors, + ): Plane3dByOriginAndVectors { const mag = Geometry.correctSmallFraction(w); // real point is X/w. // real derivative is (X' * w - X *w) / ww, and weight is always 0 by cross products. @@ -497,7 +640,18 @@ export class Point4d extends Plane3d implements BeJSONFunctions { const dfx = (dx * w - dw * x) * aa; const dfy = (dy * w - dw * y) * aa; const dfz = (dz * w - dw * z) * aa; - return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ(fx, fy, fz, dfx, dfy, dfz, quotientDerivative2(ddx, dw, ddw, fx, dfx, a), quotientDerivative2(ddy, dw, ddw, fy, dfy, a), quotientDerivative2(ddz, dw, ddw, fz, dfz, a), result); + return Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( + fx, + fy, + fz, + dfx, + dfy, + dfz, + quotientDerivative2(ddx, dw, ddw, fx, dfx, a), + quotientDerivative2(ddy, dw, ddw, fy, dfy, a), + quotientDerivative2(ddz, dw, ddw, fz, dfz, a), + result, + ); } /** * * If this.w is nonzero, return Point3d with x/w,y/w,z/w. @@ -527,9 +681,16 @@ export class Point4d extends Plane3d implements BeJSONFunctions { */ public static determinantIndexed3X3(pointA: Point4d, pointB: Point4d, pointC: Point4d, i: number, j: number, k: number) { return Geometry.tripleProduct( - pointA.xyzw[i], pointA.xyzw[j], pointA.xyzw[k], - pointB.xyzw[i], pointB.xyzw[j], pointB.xyzw[k], - pointC.xyzw[i], pointC.xyzw[j], pointC.xyzw[k]); + pointA.xyzw[i], + pointA.xyzw[j], + pointA.xyzw[k], + pointB.xyzw[i], + pointB.xyzw[j], + pointB.xyzw[k], + pointC.xyzw[i], + pointC.xyzw[j], + pointC.xyzw[k], + ); } /** * Return a Point4d perpendicular to all 3 inputs. (A higher level cross product concept) @@ -542,7 +703,8 @@ export class Point4d extends Plane3d implements BeJSONFunctions { Point4d.determinantIndexed3X3(pointA, pointB, pointC, 1, 2, 3), -Point4d.determinantIndexed3X3(pointA, pointB, pointC, 2, 3, 0), Point4d.determinantIndexed3X3(pointA, pointB, pointC, 3, 0, 1), - -Point4d.determinantIndexed3X3(pointA, pointB, pointC, 0, 1, 2)); + -Point4d.determinantIndexed3X3(pointA, pointB, pointC, 0, 1, 2), + ); } /** Treating this Point4d as plane coefficients, convert to origin and normal form. */ public toPlane3dByOriginAndUnitNormal(result?: Plane3dByOriginAndUnitNormal): Plane3dByOriginAndUnitNormal | undefined { @@ -607,7 +769,7 @@ export class Point4d extends Plane3d implements BeJSONFunctions { // create orthonormal basis {q0, q2} const q2 = new Point4d(); - q1.plusScaled(q0, -dot, q2); // bsiDPoint4d_addScaledDPoint4d(& q2, & q1, & q0, -dot); + q1.plusScaled(q0, -dot, q2); // bsiDPoint4d_addScaledDPoint4d(& q2, & q1, & q0, -dot); q2.normalizeQuaternion(); const angle = Math.acos(dot); @@ -621,7 +783,7 @@ export class Point4d extends Plane3d implements BeJSONFunctions { public radiansToPoint4dXYZW(other: Point4d): number | undefined { const magA = this.magnitudeXYZW(); const magB = other.magnitudeXYZW(); - const dot = this.dotProduct(other); // == cos (theta) * magA * magB + const dot = this.dotProduct(other); // == cos (theta) * magA * magB const cos = Geometry.conditionalDivideFraction(dot, magA * magB); if (cos === undefined) return undefined; diff --git a/core/geometry/src/numerics/BandedSystem.ts b/core/geometry/src/numerics/BandedSystem.ts index 1b01a5ceae33..7e53dae7827f 100644 --- a/core/geometry/src/numerics/BandedSystem.ts +++ b/core/geometry/src/numerics/BandedSystem.ts @@ -12,7 +12,7 @@ export class BandedSystem { /** apply LU decomposition to a banded system */ public static decomposeLU( numRow: number, - bw: number, /* band width */ + bw: number, /* band width */ data: Float64Array, ): boolean { const n = numRow - 1; @@ -45,7 +45,7 @@ export class BandedSystem { for (let k = kl; k < i; k++) sum += data[j * bw + k - j + sbw] * data[k * bw + i - k + sbw]; - if (Math.abs(data[i * bw + sbw]) < 1e-9) // TODO -- tolerance !!! + if (Math.abs(data[i * bw + sbw]) < 1e-9) // TODO -- tolerance !!! return false; data[j * bw + i - j + sbw] = (data[j * bw + i - j + sbw] - sum) / data[i * bw + sbw]; @@ -55,7 +55,6 @@ export class BandedSystem { } /** - * * @param sum evolving sum. sum.length * @param source data being added * @param sourceRow row in source. Plain offset is sourceRow * sum.length @@ -78,7 +77,15 @@ export class BandedSystem { } } // dest[destRow][*] = sourceA[sourceBRow][*] * scaleA - sourceB[*] * scaleB - private static blockSumOfScaledBlockScaledArray(dest: Float64Array, destRow: number, sourceA: Float64Array, sourceBRow: number, scaleA: number, sourceB: Float64Array, scaleB: number) { + private static blockSumOfScaledBlockScaledArray( + dest: Float64Array, + destRow: number, + sourceA: Float64Array, + sourceBRow: number, + scaleA: number, + sourceB: Float64Array, + scaleB: number, + ) { const n = sourceB.length; let destIndex = destRow * n; let sourceBIndex = sourceBRow * n; @@ -101,7 +108,7 @@ export class BandedSystem { */ public static solveBandedSystemMultipleRHS( numRow: number, - bw: number, /* band width */ + bw: number, /* band width */ matrix: Float64Array, numRHS: number, // number of components in each RHS row. rhs: Float64Array, // RHS data, packed, overwritten by solution @@ -151,7 +158,7 @@ export class BandedSystem { */ public static multiplyBandedTimesFull( numRow: number, - bw: number, /* band width */ + bw: number, /* band width */ bandedMatrix: Float64Array, numRHS: number, // number of components in each RHS row. rhs: Float64Array, // RHS data, packed, overwritten by solution diff --git a/core/geometry/src/numerics/BezierPolynomials.ts b/core/geometry/src/numerics/BezierPolynomials.ts index 3279a0076d57..cc8e12f10a56 100644 --- a/core/geometry/src/numerics/BezierPolynomials.ts +++ b/core/geometry/src/numerics/BezierPolynomials.ts @@ -99,11 +99,14 @@ export abstract class BezierCoffs { */ public abstract evaluate(u: number): number; /** The order (number of coefficients) as a readable property */ - public get order(): number { return this.coffs.length; } + public get order(): number { + return this.coffs.length; + } /** Copy coefficients from other Bezier. Note that the coefficient count (order) of "this" can change. */ public copyFrom(other: BezierCoffs): void { - if (this.order === other.order) + if (this.order === other.order) { for (let i = 0; i < this.coffs.length; i++) { this.coffs[i] = other.coffs[i]; } + } else this.coffs = other.coffs.slice(); } /** @@ -127,7 +130,7 @@ export abstract class BezierCoffs { */ public roots(targetValue: number, _restrictTo01: boolean): number[] | undefined { const bezier = UnivariateBezier.create(this); - bezier.addInPlace(- targetValue); + bezier.addInPlace(-targetValue); const roots = UnivariateBezier.deflateRoots(bezier); return this.filter01(roots, true); } @@ -212,8 +215,9 @@ export class BezierPolynomialAlgebra { scale: number, indexA: number, constA: number, - indexB: number) { - const orderB = dataOrder - 1; // coefficients of the first difference are implicitly present as differences of adjacent entries. + indexB: number, + ) { + const orderB = dataOrder - 1; // coefficients of the first difference are implicitly present as differences of adjacent entries. const orderA = dataOrder; const orderC = dataOrder + orderB - 1; if (product.length !== orderC) return; @@ -237,7 +241,16 @@ export class BezierPolynomialAlgebra { * * * Take no action if product length is other than `dataOrder + dataOrder - 2` */ - public static scaledComponentSum(sum: Float64Array, data: Float64Array, dataBlockSize: number, dataOrder: number, indexA: number, constA: number, indexB: number, constB: number) { + public static scaledComponentSum( + sum: Float64Array, + data: Float64Array, + dataBlockSize: number, + dataOrder: number, + indexA: number, + constA: number, + indexB: number, + constB: number, + ) { const orderA = dataOrder; if (sum.length !== orderA) return; for (let a = 0, rowBase = 0; a < orderA; a++, rowBase += dataBlockSize) { @@ -290,7 +303,7 @@ export class BezierPolynomialAlgebra { * * Take no action if product length is other than `orderA + orderB - 2` */ public static accumulateProductWithDifferences(product: Float64Array, dataA: Float64Array, dataB: Float64Array, scale: number = 1.0) { - const orderA = dataA.length - 1; // We deal with its differences, which are lower order !!! + const orderA = dataA.length - 1; // We deal with its differences, which are lower order !!! const orderB = dataB.length; const orderC = orderA + orderB - 1; if (product.length !== orderC) return; @@ -315,10 +328,11 @@ export class BezierPolynomialAlgebra { */ public static univariateDifference(data: Float64Array, difference: Float64Array) { const differenceOrder = difference.length; - if (difference.length + 1 !== differenceOrder) + if (difference.length + 1 !== differenceOrder) { for (let i = 0; i < differenceOrder; i++) { difference[i] = data[i + 1] - data[i]; } + } } /** * * Univariate bezierA has its coefficients in dataA[i] @@ -332,7 +346,6 @@ export class BezierPolynomialAlgebra { resultB[i] += dataA[i]; } } - } /** * * The UnivariateBezier class is a univariate bezier polynomial with no particular order. @@ -349,7 +362,9 @@ export class BezierPolynomialAlgebra { export class UnivariateBezier extends BezierCoffs { private _order: number; /** Query the order of this bezier. */ - public override get order() { return this._order; } + public override get order() { + return this._order; + } public constructor(data: number | Float64Array | number[]) { super(data); this._order = super.order; @@ -400,7 +415,6 @@ export class UnivariateBezier extends BezierCoffs { * @param index0 first index to access * @param order number of coefficients, i.e. order for the result * @param result optional result. - * */ public static createArraySubset(coffs: number[] | Float64Array, index0: number, order: number, result?: UnivariateBezier): UnivariateBezier { if (!result) @@ -591,7 +605,7 @@ export class UnivariateBezier extends BezierCoffs { */ public deflateRoot(root: number): number { const orderA = this.order; - const orderC = orderA - 1; // the order of the deflated bezier. + const orderC = orderA - 1; // the order of the deflated bezier. if (orderA === 1) { this._order = 0; return this.coffs[0]; @@ -628,10 +642,10 @@ export class UnivariateBezier extends BezierCoffs { for (let i = orderA - 2; i > 0; i--) { a1 = this.coffs[i] * pascalA[i]; c0 = (a1 - c1 * b0) / b1; - this.coffs[i] = c0 / pascalC[i - 1]; // pascalC index is from destination, which is not shifted. + this.coffs[i] = c0 / pascalC[i - 1]; // pascalC index is from destination, which is not shifted. c1 = c0; } - remainder = (this.coffs[0] - c1 * b0); + remainder = this.coffs[0] - c1 * b0; for (let i = 0; i < orderC; i++) this.coffs[i] = this.coffs[i + 1]; } @@ -763,7 +777,7 @@ export class Order2Bezier extends BezierCoffs { * but if the fraction would exceed Geometry.largeFractionResult, return undefined. */ public static solveCoffs(a0: number, a1: number): number | undefined { - return Geometry.conditionalDivideFraction(-a0, (a1 - a0)); + return Geometry.conditionalDivideFraction(-a0, a1 - a0); } /** * Evaluate the basis functions at specified u. @@ -970,7 +984,8 @@ export class Order4Bezier extends BezierCoffs { factorA.coffs[0] * factorB.coffs[0], (factorA.coffs[0] * factorB.coffs[1] + 2.0 * factorA.coffs[1] * factorB.coffs[0]) / 3.0, (2.0 * factorA.coffs[1] * factorB.coffs[1] + factorA.coffs[2] * factorB.coffs[0]) / 3.0, - factorA.coffs[2] * factorB.coffs[1]); + factorA.coffs[2] * factorB.coffs[1], + ); } /** * Evaluate the basis functions at specified u. @@ -1048,8 +1063,8 @@ export class Order4Bezier extends BezierCoffs { const v3 = v2 * v1; return this.coffs[0] * v3 + u * (3.0 * this.coffs[1] * v2 - + u * (3.0 * this.coffs[2] * v1 - + u * this.coffs[3])); + + u * (3.0 * this.coffs[2] * v1 + + u * this.coffs[3])); } /** * convert a power polynomial to bezier @@ -1086,18 +1101,17 @@ export class Order4Bezier extends BezierCoffs { roots.push(1.0 / 3.0); roots.push(2.0 / 3.0); roots.push(1.0); - return; // p(x) == 0 has infinite roots .... return 4, which is a red flag for cubic + return; // p(x) == 0 has infinite roots .... return 4, which is a red flag for cubic } - cc[0] = (y0 - e); + cc[0] = y0 - e; cc[1] = 3.0 * (y1 - y0); cc[2] = 3.0 * (y0 - 2.0 * y1 + y2); - cc[3] = - y0 + 3.0 * y1 - 3.0 * y2 + y3; - AnalyticRoots.appendCubicRoots(cc, roots); // can't have zero solutions after passing min/max conditions . . . + cc[3] = -y0 + 3.0 * y1 - 3.0 * y2 + y3; + AnalyticRoots.appendCubicRoots(cc, roots); // can't have zero solutions after passing min/max conditions . . . if (restrictTo01) roots.reassign(0, 1); return; } - } /** Bezier polynomial specialized to order 5 (5 coefficients, quartic function) * @internal @@ -1217,9 +1231,9 @@ export class Order5Bezier extends BezierCoffs { const v4 = v2 * v2; return this.coffs[0] * v4 + u * (4.0 * this.coffs[1] * v3 - + u * (6.0 * this.coffs[2] * v2 - + u * (4.0 * this.coffs[3] * v1 - + u * this.coffs[4]))); + + u * (6.0 * this.coffs[2] * v2 + + u * (4.0 * this.coffs[3] * v1 + + u * this.coffs[4]))); } /** Add the product of a pair of Order3Bezier to this one. */ public addProductOrder3BezierOrder3Bezier(f: Order3Bezier, g: Order3Bezier, a: number) { @@ -1262,11 +1276,11 @@ export class Order5Bezier extends BezierCoffs { const cc = new Float64Array(5); - cc[0] = (y0 - e); + cc[0] = y0 - e; cc[1] = 4.0 * (-y0 + y1); cc[2] = 6.0 * (y0 - 2.0 * y1 + y2); cc[3] = 4.0 * (-y0 + 3.0 * y1 - 3.0 * y2 + y3); - cc[4] = (y0 - 4.0 * y1 + 6.0 * y2 - 4.0 * y3 + y4); + cc[4] = y0 - 4.0 * y1 + 6.0 * y2 - 4.0 * y3 + y4; AnalyticRoots.appendQuarticRoots(cc, roots); if (restrictTo01) diff --git a/core/geometry/src/numerics/ClusterableArray.ts b/core/geometry/src/numerics/ClusterableArray.ts index 6fcbabe336a6..f801090338e3 100644 --- a/core/geometry/src/numerics/ClusterableArray.ts +++ b/core/geometry/src/numerics/ClusterableArray.ts @@ -24,7 +24,7 @@ export class ClusterableArray extends GrowableBlockedArray { // The sort vector is (1,c, c*c, ...) // Setting c = 1 makes it 1,1,1 which may be useful for visual scans during debug. // c with some non-obvious digits makes it unlikely that there will be multiple points on a perpendicular to the sort vector. - private static readonly _vectorFactor = 0.8732; // use 1.0 to rig easy tests. + private static readonly _vectorFactor = 0.8732; // use 1.0 to rig easy tests. /** Return a component of the sort vector. */ public static sortVectorComponent(index: number): number { let c = 1.0; @@ -124,7 +124,9 @@ export class ClusterableArray extends GrowableBlockedArray { /** this value is used as cluster terminator in the Uint232Array of indices. */ public static readonly clusterTerminator = 0xFFffFFff; /** Test if `x` is the cluster terminator value. */ - public static isClusterTerminator(x: number): boolean { return x === ClusterableArray.clusterTerminator; } + public static isClusterTerminator(x: number): boolean { + return x === ClusterableArray.clusterTerminator; + } /** Return an array giving clusters of blocks with similar coordinates. * * * The contents of each block is assumed to be set up so the primary sort coordinate is first. @@ -142,8 +144,8 @@ export class ClusterableArray extends GrowableBlockedArray { this.setupPrimaryClusterSort(); // presort by all coordinates .... const firstSort = this.sortIndicesLexical(); - const clusterIndices = new Uint32Array(2 * firstSort.length); // worst case: no duplicates, each index goes in followed by terminator. - let m = 0; // number of cluster indices + const clusterIndices = new Uint32Array(2 * firstSort.length); // worst case: no duplicates, each index goes in followed by terminator. + let m = 0; // number of cluster indices const n = this.numBlocks; // and this must match firstSort.length !! let clusterStartBlockIndex = 0; let candidateBlockIndex = 0; @@ -151,7 +153,7 @@ export class ClusterableArray extends GrowableBlockedArray { let i = 0; let j = 0; - const k0 = 1; // beginning of active column for distance + const k0 = 1; // beginning of active column for distance const k1 = 1 + this._numCoordinatePerPoint; for (i = 0; i < n; i++) { clusterStartBlockIndex = firstSort[i]; @@ -165,8 +167,8 @@ export class ClusterableArray extends GrowableBlockedArray { if (candidateBlockIndex === ClusterableArray.clusterTerminator) continue; // nearby in sort direction but already in a cluster. if (this.component(candidateBlockIndex, 0) >= barrierU) break; if (this.distanceBetweenSubBlocks(clusterStartBlockIndex, candidateBlockIndex, k0, k1) < clusterTolerance) { - clusterIndices[m++] = candidateBlockIndex; // The candidate is in the block - firstSort[j] = ClusterableArray.clusterTerminator; // and it will not be reused as future block base + clusterIndices[m++] = candidateBlockIndex; // The candidate is in the block + firstSort[j] = ClusterableArray.clusterTerminator; // and it will not be reused as future block base } } clusterIndices[m++] = ClusterableArray.clusterTerminator; @@ -203,7 +205,7 @@ export class ClusterableArray extends GrowableBlockedArray { let i = this.blockIndexToDoubleIndex(b); const chunk: any[] = [b, this._data[i++]]; const coordinates = []; - for (let c = 0; c < this._numCoordinatePerPoint; c++)coordinates.push(this._data[i++]); + for (let c = 0; c < this._numCoordinatePerPoint; c++) coordinates.push(this._data[i++]); chunk.push(coordinates); for (let c = 0; c < this._numExtraDataPerPoint; c++) chunk.push(this._data[i++]); @@ -316,8 +318,7 @@ export class ClusterableArray extends GrowableBlockedArray { * Returns packed points with indices mapping old to new. * @param data points to cluster. */ - public static clusterPoint3dArray(data: Point3d[], tolerance: number = Geometry.smallMetricDistance): - PackedPointsWithIndex { + public static clusterPoint3dArray(data: Point3d[], tolerance: number = Geometry.smallMetricDistance): PackedPointsWithIndex { const clusterArray = new ClusterableArray(3, 0, data.length); data.forEach((p: Point3d) => { clusterArray.addDirect(p.x, p.y, p.z); @@ -346,7 +347,9 @@ export class ClusterableArray extends GrowableBlockedArray { */ public static clusterNumberArray(data: number[], tolerance: number = Geometry.smallMetricDistance): PackedNumbersWithIndex { const clusterArray = new ClusterableArray(1, 0, data.length); - data.forEach((x: number) => {clusterArray.addDirect(x);}); + data.forEach((x: number) => { + clusterArray.addDirect(x); + }); const order = clusterArray.clusterIndicesLexical(tolerance); const result = new PackedNumbersWithIndex(data.length); let currentClusterIndex = 0; @@ -400,8 +403,7 @@ export class ClusterableArray extends GrowableBlockedArray { * Returns packed points with indices mapping old to new. * @param data points to cluster. */ - public static clusterGrowablePoint3dArray(source: GrowableXYZArray, tolerance: number = Geometry.smallMetricDistance): - PackedPointsWithIndex { + public static clusterGrowablePoint3dArray(source: GrowableXYZArray, tolerance: number = Geometry.smallMetricDistance): PackedPointsWithIndex { const clusterArray = new ClusterableArray(3, 0, source.length); const p = Point3d.create(); const numSourcePoint = source.length; @@ -515,7 +517,7 @@ class PackedPoint2dsWithIndex { /** * @internal */ - class PackedNumbersWithIndex { +class PackedNumbersWithIndex { /** Array of numbers */ public packedNumbers: number[]; /** mapping from old point index to new point index. */ diff --git a/core/geometry/src/numerics/Complex.ts b/core/geometry/src/numerics/Complex.ts index 8aea156441fb..ae1736a46ab6 100644 --- a/core/geometry/src/numerics/Complex.ts +++ b/core/geometry/src/numerics/Complex.ts @@ -15,23 +15,44 @@ import { Angle } from "../geometry3d/Angle"; export class Complex implements BeJSONFunctions { private _x: number; /** Real part */ - public get x(): number { return this._x; } - public set x(value: number) { this._x = value; } + public get x(): number { + return this._x; + } + public set x(value: number) { + this._x = value; + } private _y: number; /** Imaginary part */ - public get y(): number { return this._y; } - public set y(value: number) { this._y = value; } + public get y(): number { + return this._y; + } + public set y(value: number) { + this._y = value; + } - public constructor(x: number = 0, y: number = 0) { this._x = x; this._y = y; } + public constructor(x: number = 0, y: number = 0) { + this._x = x; + this._y = y; + } /** set x and y parts from args. */ - public set(x: number = 0, y: number = 0): void { this.x = x; this.y = y; } + public set(x: number = 0, y: number = 0): void { + this.x = x; + this.y = y; + } /** set `this.x` and `this.y` from `other.x` and `other.y` */ - public setFrom(other: Complex) { this.x = other.x; this.y = other.y; } + public setFrom(other: Complex) { + this.x = other.x; + this.y = other.y; + } /** clone the complex x,y */ - public clone(): Complex { return new Complex(this.x, this.y); } + public clone(): Complex { + return new Complex(this.x, this.y); + } /** test for near equality using coordinate tolerances */ - public isAlmostEqual(other: Complex): boolean { return Geometry.isAlmostEqualNumber(this.x, other.x) && Geometry.isAlmostEqualNumber(this.x, other.x); } + public isAlmostEqual(other: Complex): boolean { + return Geometry.isAlmostEqualNumber(this.x, other.x) && Geometry.isAlmostEqualNumber(this.x, other.x); + } /** Create a new Complex instance from given x and y. */ public static create(x: number = 0, y: number = 0, result?: Complex): Complex { if (result) { @@ -42,33 +63,45 @@ export class Complex implements BeJSONFunctions { return new Complex(x, y); } /** Return the complex sum `this+other` */ - public plus(other: Complex, result?: Complex): Complex { return Complex.create(this.x + other.x, this.y + other.y, result); } + public plus(other: Complex, result?: Complex): Complex { + return Complex.create(this.x + other.x, this.y + other.y, result); + } /** Return the complex difference `this-other` */ - public minus(other: Complex, result?: Complex): Complex { return Complex.create(this.x - other.x, this.y - other.y, result); } + public minus(other: Complex, result?: Complex): Complex { + return Complex.create(this.x - other.x, this.y - other.y, result); + } /** Return the complex product `this * other` */ public times(other: Complex, result?: Complex): Complex { return Complex.create( this.x * other.x - this.y * other.y, this.x * other.y + this.y * other.x, - result); + result, + ); } /** Return the complex product `this * x+i*y`. That is, the second Complex value exists via the args without being formally created as an instance. */ public timesXY(x: number, y: number, result?: Complex): Complex { return Complex.create( this.x * x - this.y * y, this.x * y + this.y * x, - result); + result, + ); } /** Return the mangitude of the complex number */ - public magnitude(): number { return Geometry.hypotenuseXY(this.x, this.y); } + public magnitude(): number { + return Geometry.hypotenuseXY(this.x, this.y); + } /** Return the angle from x axis to the vector (x,y) */ - public angle(): Angle { return Angle.createAtan2(this.y, this.x); } + public angle(): Angle { + return Angle.createAtan2(this.y, this.x); + } /** Return the xy plane distance between this and other */ public distance(other: Complex) { return Geometry.hypotenuseXY(this.x - other.x, this.y - other.y); } /** Return the squared xy plane distance between this and other. */ - public magnitudeSquared(): number { return this.x * this.x + this.y * this.y; } + public magnitudeSquared(): number { + return this.x * this.x + this.y * this.y; + } /** Return the complex division `this / other` */ public divide(other: Complex, result?: Complex): Complex | undefined { const bb = other.magnitudeSquared(); @@ -78,7 +111,8 @@ export class Complex implements BeJSONFunctions { return Complex.create( (this.x * other.x + this.y * other.y) * divbb, (this.y * other.x - this.x * other.y) * divbb, - result); + result, + ); } /** Return the complex square root of this. */ public sqrt(result?: Complex): Complex { @@ -118,12 +152,17 @@ export class Complex implements BeJSONFunctions { } } /** Create a `Complex` instance from a json object. */ - public static fromJSON(json?: any): Complex { const result = new Complex(); result.setFromJSON(json); return result; } + public static fromJSON(json?: any): Complex { + const result = new Complex(); + result.setFromJSON(json); + return result; + } /** * Convert an Complex to a JSON object. * @return {*} [x,y] */ - public toJSON(): any { return [this.x, this.y]; } - + public toJSON(): any { + return [this.x, this.y]; + } } diff --git a/core/geometry/src/numerics/ConvexPolygon2d.ts b/core/geometry/src/numerics/ConvexPolygon2d.ts index ced53dca0298..001e3d4cd046 100644 --- a/core/geometry/src/numerics/ConvexPolygon2d.ts +++ b/core/geometry/src/numerics/ConvexPolygon2d.ts @@ -145,7 +145,7 @@ export class ConvexPolygon2d { * * Range has extreme values if less than 3 points, distanceA > distanceB, or if cross product < 0. */ public clipRay(ray: Ray2d): Range1d { - let distanceA = - Number.MAX_VALUE; + let distanceA = -Number.MAX_VALUE; let distanceB = Number.MAX_VALUE; const n = this._hullPoints.length; diff --git a/core/geometry/src/numerics/Newton.ts b/core/geometry/src/numerics/Newton.ts index da90e8e224bb..ebeb711264bc 100644 --- a/core/geometry/src/numerics/Newton.ts +++ b/core/geometry/src/numerics/Newton.ts @@ -7,8 +7,8 @@ * @module Numerics */ -import { Geometry } from "../Geometry"; import { CurvePrimitive } from "../curve/CurvePrimitive"; +import { Geometry } from "../Geometry"; import { Plane3dByOriginAndVectors } from "../geometry3d/Plane3dByOriginAndVectors"; import { Point2d, Vector2d } from "../geometry3d/Point2dVector2d"; import { Point3d } from "../geometry3d/Point3dVector3d"; @@ -383,7 +383,7 @@ export class SimpleNewton { tolerance = absoluteTolerance + Math.abs(x) * relTol; if (Math.abs(dx) < tolerance) { numConverged++; - if (dx === 0.0 || numConverged > 1) // bypass convergence count on true 0 dx + if (dx === 0.0 || numConverged > 1) // bypass convergence count on true 0 dx return x; } else { numConverged = 0; @@ -423,9 +423,15 @@ export class CurveCurveIntersectionXYRRToRRD extends NewtonEvaluatorRRtoRRD { this._curveP.fractionToPointAndDerivative(fractionU, this._rayP); this._curveQ.fractionToPointAndDerivative(fractionV, this._rayQ); this.currentF.setOriginAndVectorsXYZ( - this._rayP.origin.x - this._rayQ.origin.x, this._rayP.origin.y - this._rayQ.origin.y, 0.0, - this._rayP.direction.x, this._rayP.direction.y, 0.0, - -this._rayQ.direction.x, -this._rayQ.direction.y, 0.0, + this._rayP.origin.x - this._rayQ.origin.x, + this._rayP.origin.y - this._rayQ.origin.y, + 0.0, + this._rayP.direction.x, + this._rayP.direction.y, + 0.0, + -this._rayQ.direction.x, + -this._rayQ.direction.y, + 0.0, ); return true; } diff --git a/core/geometry/src/numerics/PascalCoefficients.ts b/core/geometry/src/numerics/PascalCoefficients.ts index 34510eb9d115..bada46666291 100644 --- a/core/geometry/src/numerics/PascalCoefficients.ts +++ b/core/geometry/src/numerics/PascalCoefficients.ts @@ -55,13 +55,13 @@ export class PascalCoefficients { result[i] = pascalRow[i]; // multiply by increasing powers of u ... let p = u; - for (let i = 1; i < order; i++ , p *= u) { + for (let i = 1; i < order; i++, p *= u) { result[i] *= p; } // multiply by powers of (1-u), working from right const v = 1.0 - u; p = v; - for (let i = order - 2; i >= 0; i-- , p *= v) { + for (let i = order - 2; i >= 0; i--, p *= v) { result[i] *= p; } return result; @@ -84,7 +84,7 @@ export class PascalCoefficients { for (let k = order - 2; k > 0; k--) { result[k] = f * (result[k - 1] - result[k]); } - result[0] = - f * result[0]; + result[0] = -f * result[0]; return result; } } diff --git a/core/geometry/src/numerics/PolarData.ts b/core/geometry/src/numerics/PolarData.ts index 15d1adad4a30..894a70dc3dec 100644 --- a/core/geometry/src/numerics/PolarData.ts +++ b/core/geometry/src/numerics/PolarData.ts @@ -18,7 +18,6 @@ export enum ConstraintState { singlePoint = 1, impossibleValues = -1, onCurve = 2, - } /** @@ -27,7 +26,9 @@ export enum ConstraintState { */ export class PolarData { private static _defaultRadius = 1.0; - public static get defaultRadius(): number { return PolarData._defaultRadius; } + public static get defaultRadius(): number { + return PolarData._defaultRadius; + } /** x coordinate, possibly unknown */ public x?: number; /** y coordinate, possibly unknown */ @@ -81,7 +82,15 @@ export class PolarData { // .. "free on curve" has curve filled in, with finite curve range controlled by PolarData.defaultRadius. if (known.x !== undefined) { if (known.y !== undefined) { - result.push(PolarData.createMixedScalars(ConstraintState.singlePoint, known.x, known.y, Geometry.hypotenuseXY(known.x, known.y), Angle.createAtan2(known.y, known.x))); + result.push( + PolarData.createMixedScalars( + ConstraintState.singlePoint, + known.x, + known.y, + Geometry.hypotenuseXY(known.x, known.y), + Angle.createAtan2(known.y, known.x), + ), + ); } else if (known.r !== undefined) { const rr = known.r * known.r; const xx = known.x * known.x; @@ -104,11 +113,11 @@ export class PolarData { const y = r * known.theta.sin(); result.push(PolarData.createMixedScalars(ConstraintState.singlePoint, known.x, y, r, known.theta)); } - } else { // only x known --- fill out a vertical line + } else { // only x known --- fill out a vertical line const q = known.cloneScalarsWithState(ConstraintState.onCurve); q.geometry = LineSegment3d.createXYZXYZ(known.x, PolarData._defaultRadius, 0, known.x, PolarData._defaultRadius, 0); } - } else if (known.y !== undefined) { // and we already know x is undefined ..... + } else if (known.y !== undefined) { // and we already know x is undefined ..... if (known.r !== undefined) { const rr = known.r * known.r; const yy = known.y * known.y; @@ -131,13 +140,15 @@ export class PolarData { const x = r * known.theta.cos(); result.push(PolarData.createMixedScalars(ConstraintState.singlePoint, x, known.y, r, known.theta)); } - } else { // only x known --- fill out a horizontal line + } else { // only x known --- fill out a horizontal line const q = known.cloneScalarsWithState(ConstraintState.onCurve); q.geometry = LineSegment3d.createXYZXYZ(PolarData._defaultRadius, known.y, 0, PolarData._defaultRadius, known.y, 0); } } else if (known.r !== undefined) { if (known.theta !== undefined) { - result.push(PolarData.createMixedScalars(ConstraintState.singlePoint, known.r * known.theta.cos(), known.r * known.theta.sin(), known.r, known.theta)); + result.push( + PolarData.createMixedScalars(ConstraintState.singlePoint, known.r * known.theta.cos(), known.r * known.theta.sin(), known.r, known.theta), + ); } else { const q = known.cloneScalarsWithState(ConstraintState.onCurve); q.geometry = Arc3d.createXY(Point3d.create(0, 0, 0), known.r); diff --git a/core/geometry/src/numerics/Polynomials.ts b/core/geometry/src/numerics/Polynomials.ts index aec17e6c02a2..75f7e34b658d 100644 --- a/core/geometry/src/numerics/Polynomials.ts +++ b/core/geometry/src/numerics/Polynomials.ts @@ -112,10 +112,10 @@ export class Degree2PowerPolynomial { public static fromRootsAndC2(root0: number, root1: number, c2: number = 1): Degree2PowerPolynomial { return new Degree2PowerPolynomial( c2 * root0 * root1, - - c2 * (root0 + root1), - c2); + -c2 * (root0 + root1), + c2, + ); } - } /** * degree 3 (cubic) polynomial in for y = c0 + c1*x + c2*x^2 + c3*x^3 @@ -160,8 +160,9 @@ export class Degree3PowerPolynomial { return new Degree3PowerPolynomial( -c3 * root0 * root1 * root2, c3 * (root0 * root1 + root1 * root2 + root0 * root2), - - c3 * (root0 + root1 + root2), - c3); + -c3 * (root0 + root1 + root2), + c3, + ); } } /** @@ -203,9 +204,9 @@ export class Degree4PowerPolynomial { -c4 * (root0 * root1 * root2 + root0 * root1 * root3 + root0 * root2 * root3 + root1 * root2 * root3), c4 * (root0 * root1 + root0 * root2 + root0 * root3 + root1 * root2 + root1 * root3 + root2 * root3), -c4 * (root0 + root1 + root2 + root3), - c4); + c4, + ); } - } /** * polynomial services for an implicit torus with @@ -366,7 +367,9 @@ export class TorusImplicit { export class SphereImplicit { /** Radius of sphere. */ public radius: number; - constructor(r: number) { this.radius = r; } + constructor(r: number) { + this.radius = r; + } /** Evaluate the implicit function at coordinates x,y,z */ public evaluateImplicitFunction(x: number, y: number, z: number): number { @@ -404,10 +407,18 @@ export class SphereImplicit { valid = false; } } - return { thetaRadians: (theta), phiRadians: (phi), r, valid }; + return { thetaRadians: theta, phiRadians: phi, r, valid }; } /** Return the range of a uv-aligned patch of the sphere. */ - public static patchRangeStartEndRadians(center: Point3d, radius: number, theta0Radians: number, theta1Radians: number, phi0Radians: number, phi1Radians: number, result?: Range3d): Range3d { + public static patchRangeStartEndRadians( + center: Point3d, + radius: number, + theta0Radians: number, + theta1Radians: number, + phi0Radians: number, + phi1Radians: number, + result?: Range3d, + ): Range3d { const thetaSweep = AngleSweep.createStartEndRadians(theta0Radians, theta1Radians); const phiSweep = AngleSweep.createStartEndRadians(phi0Radians, phi1Radians); const range = Range3d.createNull(result); @@ -423,13 +434,16 @@ export class SphereImplicit { const piOver2 = 0.5 * Math.PI; let phi, theta; // 6 candidate interior extreme points on equator and 0, 90 degree meridians - for (const thetaPhi of [ - [0.0, 0.0], - [pi, 0.0], - [piOver2, 0.0], - [-piOver2, 0.0], - [theta0Radians, piOver2], - [theta0Radians, -piOver2]]) { + for ( + const thetaPhi of [ + [0.0, 0.0], + [pi, 0.0], + [piOver2, 0.0], + [-piOver2, 0.0], + [theta0Radians, piOver2], + [theta0Radians, -piOver2], + ] + ) { theta = thetaPhi[0]; phi = thetaPhi[1]; if (thetaSweep.isRadiansInSweep(theta) && phiSweep.isRadiansInSweep(phi)) @@ -448,10 +462,12 @@ export class SphereImplicit { for (const cosPhi of [cosPhi0, cosPhi1]) { trigForm.set(0, cosPhi * radius, 0); trigForm.rangeInSweep(thetaSweep, axisRange); - range.extendXOnly(axisRange.low); range.extendXOnly(axisRange.high); + range.extendXOnly(axisRange.low); + range.extendXOnly(axisRange.high); trigForm.set(0, 0, cosPhi * radius); trigForm.rangeInSweep(thetaSweep, axisRange); - range.extendYOnly(axisRange.low); range.extendYOnly(axisRange.high); + range.extendYOnly(axisRange.low); + range.extendYOnly(axisRange.high); } range.extendZOnly(sinPhi0 * radius); range.extendZOnly(sinPhi1 * radius); @@ -462,11 +478,13 @@ export class SphereImplicit { const sinThetaR = Math.sin(thetaRadians) * radius; trigForm.set(0, cosThetaR, 0); trigForm.rangeInSweep(phiSweep, axisRange); - range.extendXOnly(axisRange.low); range.extendXOnly(axisRange.high); + range.extendXOnly(axisRange.low); + range.extendXOnly(axisRange.high); trigForm.set(0, sinThetaR, 0); trigForm.rangeInSweep(phiSweep, axisRange); - range.extendYOnly(axisRange.low); range.extendYOnly(axisRange.high); + range.extendYOnly(axisRange.low); + range.extendYOnly(axisRange.high); } range.cloneTranslated(center, range); } @@ -480,7 +498,14 @@ export class SphereImplicit { * * thetaPhiRadians = sphere longitude and latitude in radians. * * For each optional array, caller must of course initialize an array (usually empty) */ - public static intersectSphereRay(center: Point3d, radius: number, ray: Ray3d, rayFractions: number[] | undefined, xyz: Point3d[] | undefined, thetaPhiRadians: LongitudeLatitudeNumber[] | undefined): number { + public static intersectSphereRay( + center: Point3d, + radius: number, + ray: Ray3d, + rayFractions: number[] | undefined, + xyz: Point3d[] | undefined, + thetaPhiRadians: LongitudeLatitudeNumber[] | undefined, + ): number { const vx = ray.origin.x - center.x; const vy = ray.origin.y - center.y; const vz = ray.origin.z - center.z; @@ -502,8 +527,9 @@ export class SphereImplicit { return 0; } const sphere = new SphereImplicit(radius); - if (rayFractions !== undefined) + if (rayFractions !== undefined) { for (const f of parameters) rayFractions.push(f); + } if (xyz !== undefined || thetaPhiRadians !== undefined) { for (const f of parameters) { const point = ray.fractionToPoint(f); @@ -598,7 +624,6 @@ export class SphereImplicit { } /** AnalyticRoots has static methods for solving quadratic, cubic, and quartic equations. * @internal - * */ export class AnalyticRoots { private static readonly _EQN_EPS = 1.0e-9; @@ -618,10 +643,10 @@ export class AnalyticRoots { } /** Return the (real, signed) principal cube root of x */ public static cbrt(x: number): number { - return ((x) > 0.0 - ? Math.pow((x), 1.0 / 3.0) - : ((x) < 0.0 - ? -Math.pow(-(x), 1.0 / 3.0) + return (x > 0.0 + ? Math.pow(x, 1.0 / 3.0) + : (x < 0.0 + ? -Math.pow(-x, 1.0 / 3.0) : 0.0)); } /** @@ -663,13 +688,16 @@ export class AnalyticRoots { return undefined; } private static improveRoots( - coffs: Float64Array | number[], degree: number, roots: GrowableFloat64Array, restrictOrderChanges: boolean, + coffs: Float64Array | number[], + degree: number, + roots: GrowableFloat64Array, + restrictOrderChanges: boolean, ) { const relTol = 1.0e-10; // Loop through each root for (let i = 0; i < roots.length; i++) { let dx = this.newtonMethodAdjustment(coffs, roots.atUncheckedIndex(i), degree); - if (dx === undefined || dx === 0.0) continue; // skip if newton step had divide by zero. + if (dx === undefined || dx === 0.0) continue; // skip if newton step had divide by zero. const originalValue = roots.atUncheckedIndex(i); let counter = 0; let convergenceCounter = 0; @@ -731,7 +759,7 @@ export class AnalyticRoots { */ public static mostDistantFromMean(data: GrowableFloat64Array | undefined): number { if (!data || data.length === 0) return 0; - let a = 0.0; // to become the sum and finally the average. + let a = 0.0; // to become the sum and finally the average. for (let i = 0; i < data.length; i++) a += data.atUncheckedIndex(i); a /= data.length; let dMax = 0.0; @@ -771,7 +799,7 @@ export class AnalyticRoots { return; } else if (D > 0) { const sqrt_D = Math.sqrt(D); - this.append2Solutions(sqrt_D - p, - sqrt_D - p, values); + this.append2Solutions(sqrt_D - p, -sqrt_D - p, values); return; } return; @@ -796,7 +824,7 @@ export class AnalyticRoots { const q = b * b - 3.0 * a * c; const aa = a * a; const delta2 = q / (9.0 * aa); - const xN = - b / (3.0 * a); + const xN = -b / (3.0 * a); const yN = d + xN * (c + xN * (b + xN * a)); const yN2 = yN * yN; const h2 = 4.0 * a * a * delta2 * delta2 * delta2; @@ -978,11 +1006,11 @@ export class AnalyticRoots { } // the two quadratic equations coffs[0] = z - u; - coffs[1] = ((q < 0) ? (-v) : (v)); + coffs[1] = (q < 0) ? (-v) : v; coffs[2] = 1; this.appendQuadraticRoots(coffs, results); coffs[0] = z + u; - coffs[1] = ((q < 0) ? (v) : (-v)); + coffs[1] = (q < 0) ? v : (-v); coffs[2] = 1; this.appendQuadraticRoots(coffs, results); } @@ -992,8 +1020,13 @@ export class AnalyticRoots { return; } - private static appendCosSinRadians(c: number, s: number, cosValues: OptionalGrowableFloat64Array, sinValues: OptionalGrowableFloat64Array, - radiansValues: OptionalGrowableFloat64Array) { + private static appendCosSinRadians( + c: number, + s: number, + cosValues: OptionalGrowableFloat64Array, + sinValues: OptionalGrowableFloat64Array, + radiansValues: OptionalGrowableFloat64Array, + ) { if (cosValues) cosValues.push(c); if (sinValues) sinValues.push(s); if (radiansValues) radiansValues.push(Math.atan2(s, c)); @@ -1043,7 +1076,7 @@ export class AnalyticRoots { if (delta2 <= 0.0) { solutionType = (alpha === 0) ? -2 : -1; } else { - const lambda = - alpha / delta2; + const lambda = -alpha / delta2; const a2 = alpha2 / delta2; const D2 = 1.0 - a2; if (D2 < -twoTol) { @@ -1054,7 +1087,7 @@ export class AnalyticRoots { solutionType = 0; } else if (D2 < twoTol) { const delta = Math.sqrt(delta2); - const iota = (alpha < 0) ? (1.0 / delta) : (- 1.0 / delta); + const iota = (alpha < 0) ? (1.0 / delta) : (-1.0 / delta); this.appendCosSinRadians(lambda * beta, lambda * gamma, cosValues, sinValues, radiansValues); this.appendCosSinRadians(beta * iota, gamma * iota, cosValues, sinValues, radiansValues); solutionType = 1; @@ -1158,7 +1191,10 @@ export class TrigPolynomial { * @return false if equation is all zeros. This usually means any angle is a solution. */ public static solveAngles( - coff: Float64Array, nominalDegree: number, referenceCoefficient: number, radians: number[], + coff: Float64Array, + nominalDegree: number, + referenceCoefficient: number, + radians: number[], ): boolean { let maxCoff = Math.abs(referenceCoefficient); let a; @@ -1220,7 +1256,13 @@ export class TrigPolynomial { * @param radians solution angles */ public static solveUnitCircleImplicitQuadricIntersection( - axx: number, axy: number, ayy: number, ax: number, ay: number, a: number, radians: number[], + axx: number, + axy: number, + ayy: number, + ax: number, + ay: number, + a: number, + radians: number[], ): boolean { const coffs = new Float64Array(5); PowerPolynomial.zero(coffs); @@ -1241,7 +1283,12 @@ export class TrigPolynomial { degree = 2; } const maxCoff = Math.max( - Math.abs(axx), Math.abs(ayy), Math.abs(axy), Math.abs(ax), Math.abs(ay), Math.abs(a), + Math.abs(axx), + Math.abs(ayy), + Math.abs(axy), + Math.abs(ax), + Math.abs(ay), + Math.abs(a), ); const b = this.solveAngles(coffs, degree, maxCoff, radians); /* @@ -1269,10 +1316,14 @@ export class TrigPolynomial { * @param circleRadians solution angles in circle parameter space */ public static solveUnitCircleEllipseIntersection( - cx: number, cy: number, - ux: number, uy: number, - vx: number, vy: number, - ellipseRadians: number[], circleRadians: number[], + cx: number, + cy: number, + ux: number, + uy: number, + vx: number, + vy: number, + ellipseRadians: number[], + circleRadians: number[], ): boolean { circleRadians.length = 0; // see core\geometry\internaldocs\unitCircleEllipseIntersection.md for derivation of these coefficients: @@ -1308,10 +1359,17 @@ export class TrigPolynomial { * @param circleRadians solution angles in circle parameter space */ public static solveUnitCircleHomogeneousEllipseIntersection( - cx: number, cy: number, cw: number, - ux: number, uy: number, uw: number, - vx: number, vy: number, vw: number, - ellipseRadians: number[], circleRadians: number[], + cx: number, + cy: number, + cw: number, + ux: number, + uy: number, + uw: number, + vx: number, + vy: number, + vw: number, + ellipseRadians: number[], + circleRadians: number[], ): boolean { circleRadians.length = 0; // see core\geometry\internaldocs\unitCircleEllipseIntersection.md for derivation of these coefficients: @@ -1322,7 +1380,13 @@ export class TrigPolynomial { const as = 2.0 * (vx * cx + vy * cy - vw * cw); const a = cx * cx + cy * cy - cw * cw; const status = this.solveUnitCircleImplicitQuadricIntersection( - acc, acs, ass, ac, as, a, ellipseRadians, + acc, + acs, + ass, + ac, + as, + a, + ellipseRadians, ); for (const radians of ellipseRadians) { const cc = Math.cos(radians); @@ -1348,8 +1412,7 @@ export class SmallSystem { * @param b1 end point of line b * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ - public static lineSegment2dXYTransverseIntersectionUnbounded(a0: Point2d, a1: Point2d, b0: Point2d, b1: Point2d, - result: Vector2d): boolean { + public static lineSegment2dXYTransverseIntersectionUnbounded(a0: Point2d, a1: Point2d, b0: Point2d, b1: Point2d, result: Vector2d): boolean { const ux = a1.x - a0.x; const uy = a1.y - a0.y; @@ -1379,10 +1442,16 @@ export class SmallSystem { * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ public static lineSegmentXYUVTransverseIntersectionUnbounded( - ax0: number, ay0: number, ux: number, uy: number, - bx0: number, by0: number, vx: number, vy: number, - result: Vector2d): boolean { - + ax0: number, + ay0: number, + ux: number, + uy: number, + bx0: number, + by0: number, + vx: number, + vy: number, + result: Vector2d, + ): boolean { const cx = bx0 - ax0; const cy = by0 - ay0; @@ -1408,8 +1477,7 @@ export class SmallSystem { * @param b1 end point of line b * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ - public static lineSegment3dXYTransverseIntersectionUnbounded(a0: Point3d, a1: Point3d, b0: Point3d, b1: Point3d, - result: Vector2d): boolean { + public static lineSegment3dXYTransverseIntersectionUnbounded(a0: Point3d, a1: Point3d, b0: Point3d, b1: Point3d, result: Vector2d): boolean { const ux = a1.x - a0.x; const uy = a1.y - a0.y; @@ -1441,28 +1509,62 @@ export class SmallSystem { * @param hB1 homogeneous end point of line b * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ - public static lineSegment3dHXYTransverseIntersectionUnbounded(hA0: Point4d, hA1: Point4d, hB0: Point4d, hB1: Point4d, result?: Vector2d): Vector2d | undefined { + public static lineSegment3dHXYTransverseIntersectionUnbounded( + hA0: Point4d, + hA1: Point4d, + hB0: Point4d, + hB1: Point4d, + result?: Vector2d, + ): Vector2d | undefined { // Considering only x,y,w parts.... // Point Q along B is (in full homogeneous) `(1-lambda) B0 + lambda 1` // PointQ is colinear with A0,A1 when the determinant det (A0,A1,Q) is zero. (Each column takes xyw parts) const alpha0 = Geometry.tripleProduct( - hA0.x, hA1.x, hB0.x, - hA0.y, hA1.y, hB0.y, - hA0.w, hA1.w, hB0.w); + hA0.x, + hA1.x, + hB0.x, + hA0.y, + hA1.y, + hB0.y, + hA0.w, + hA1.w, + hB0.w, + ); const alpha1 = Geometry.tripleProduct( - hA0.x, hA1.x, hB1.x, - hA0.y, hA1.y, hB1.y, - hA0.w, hA1.w, hB1.w); + hA0.x, + hA1.x, + hB1.x, + hA0.y, + hA1.y, + hB1.y, + hA0.w, + hA1.w, + hB1.w, + ); const fractionB = Geometry.conditionalDivideFraction(-alpha0, alpha1 - alpha0); if (fractionB !== undefined) { const beta0 = Geometry.tripleProduct( - hB0.x, hB1.x, hA0.x, - hB0.y, hB1.y, hA0.y, - hB0.w, hB1.w, hA0.w); + hB0.x, + hB1.x, + hA0.x, + hB0.y, + hB1.y, + hA0.y, + hB0.w, + hB1.w, + hA0.w, + ); const beta1 = Geometry.tripleProduct( - hB0.x, hB1.x, hA1.x, - hB0.y, hB1.y, hA1.y, - hB0.w, hB1.w, hA1.w); + hB0.x, + hB1.x, + hA1.x, + hB0.y, + hB1.y, + hA1.y, + hB0.w, + hB1.w, + hA1.w, + ); const fractionA = Geometry.conditionalDivideFraction(-beta0, beta1 - beta0); if (fractionA !== undefined) return Vector2d.create(fractionA, fractionB, result); @@ -1485,13 +1587,27 @@ export class SmallSystem { const tx = hA1.x * hA0.w - hA0.x * hA1.w; const ty = hA1.y * hA0.w - hA0.y * hA1.w; const det0 = Geometry.tripleProduct( - hA0.x, -ty, spacePoint.x, - hA0.y, tx, spacePoint.y, - hA0.w, 0, spacePoint.w); + hA0.x, + -ty, + spacePoint.x, + hA0.y, + tx, + spacePoint.y, + hA0.w, + 0, + spacePoint.w, + ); const det1 = Geometry.tripleProduct( - hA1.x, -ty, spacePoint.x, - hA1.y, tx, spacePoint.y, - hA1.w, 0, spacePoint.w); + hA1.x, + -ty, + spacePoint.x, + hA1.y, + tx, + spacePoint.y, + hA1.w, + 0, + spacePoint.w, + ); return Geometry.conditionalDivideFraction(-det0, det1 - det0); } @@ -1539,14 +1655,22 @@ export class SmallSystem { * @param b1 end point of line b * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ - public static lineSegment3dClosestApproachUnbounded(a0: Point3d, a1: Point3d, b0: Point3d, b1: Point3d, - result: Vector2d): boolean { + public static lineSegment3dClosestApproachUnbounded(a0: Point3d, a1: Point3d, b0: Point3d, b1: Point3d, result: Vector2d): boolean { return this.ray3dXYZUVWClosestApproachUnbounded( - a0.x, a0.y, a0.z, - a1.x - a0.x, a1.y - a0.y, a1.z - a0.z, - b0.x, b0.y, b0.z, - b1.x - b0.x, b1.y - b0.y, b1.z - b0.z, - result); + a0.x, + a0.y, + a0.z, + a1.x - a0.x, + a1.y - a0.y, + a1.z - a0.z, + b0.x, + b0.y, + b0.z, + b1.x - b0.x, + b1.y - b0.y, + b1.z - b0.z, + result, + ); } /** * Return true if the given rays have closest approach (go by each other) in 3d @@ -1566,10 +1690,20 @@ export class SmallSystem { * @param result point to receive fractional coordinates of intersection. result.x is fraction on line a. result.y is fraction on line b. */ public static ray3dXYZUVWClosestApproachUnbounded( - ax: number, ay: number, az: number, au: number, av: number, aw: number, - bx: number, by: number, bz: number, bu: number, bv: number, bw: number, - result: Vector2d): boolean { - + ax: number, + ay: number, + az: number, + au: number, + av: number, + aw: number, + bx: number, + by: number, + bz: number, + bu: number, + bv: number, + bw: number, + result: Vector2d, + ): boolean { const cx = bx - ax; const cy = by - ay; const cz = bz - az; @@ -1594,9 +1728,12 @@ export class SmallSystem { * @param result (x,y) solution (MUST be preallocated by caller) */ public static linearSystem2d( - ux: number, vx: number, // first row of matrix - uy: number, vy: number, // second row of matrix - cx: number, cy: number, // right side + ux: number, + vx: number, // first row of matrix + uy: number, + vy: number, // second row of matrix + cx: number, + cy: number, // right side result: Vector2d, ): boolean { const uv = Geometry.crossProductXYXY(ux, uy, vx, vy); @@ -1632,10 +1769,18 @@ export class SmallSystem { * @returns solution vector (u,v,w) or `undefined` if system is singular. */ public static linearSystem3d( - axx: number, axy: number, axz: number, // first row of matrix - ayx: number, ayy: number, ayz: number, // second row of matrix - azx: number, azy: number, azz: number, // second row of matrix - cx: number, cy: number, cz: number, // right side + axx: number, + axy: number, + axz: number, // first row of matrix + ayx: number, + ayy: number, + ayz: number, // second row of matrix + azx: number, + azy: number, + azz: number, // second row of matrix + cx: number, + cy: number, + cz: number, // right side result?: Vector3d, ): Vector3d | undefined { // determinants of various combinations of columns ... @@ -1663,16 +1808,29 @@ export class SmallSystem { * @returns intersection point of the three planes (as a Vector3d), or undefined if at least two planes are parallel. */ public static intersect3Planes( - xyzA: Point3d, normalA: Vector3d, - xyzB: Point3d, normalB: Vector3d, - xyzC: Point3d, normalC: Vector3d, result?: Vector3d): Vector3d | undefined { + xyzA: Point3d, + normalA: Vector3d, + xyzB: Point3d, + normalB: Vector3d, + xyzC: Point3d, + normalC: Vector3d, + result?: Vector3d, + ): Vector3d | undefined { return this.linearSystem3d( - normalA.x, normalA.y, normalA.z, - normalB.x, normalB.y, normalB.z, - normalC.x, normalC.y, normalC.z, + normalA.x, + normalA.y, + normalA.z, + normalB.x, + normalB.y, + normalB.z, + normalC.x, + normalC.y, + normalC.z, Geometry.dotProductXYZXYZ(xyzA.x, xyzA.y, xyzA.z, normalA.x, normalA.y, normalA.z), Geometry.dotProductXYZXYZ(xyzB.x, xyzB.y, xyzB.z, normalB.x, normalB.y, normalB.z), - Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), result); + Geometry.dotProductXYZXYZ(xyzC.x, xyzC.y, xyzC.z, normalC.x, normalC.y, normalC.z), + result, + ); } /** @@ -1695,8 +1853,16 @@ export class SmallSystem { * * First equation: `a0 + b0 * u + c0 * v + d0 * u * v = 0` * * Second equation: `a0 + b0 * u + c0 * v + d0 * u * v = 0` */ - public static solveBilinearPair(a0: number, b0: number, c0: number, d0: number, - a1: number, b1: number, c1: number, d1: number): Point2d[] | undefined { + public static solveBilinearPair( + a0: number, + b0: number, + c0: number, + d0: number, + a1: number, + b1: number, + c1: number, + d1: number, + ): Point2d[] | undefined { // constant linear, and quadratic coefficients for c0 + c1 * u + c2 * u*u = 0 const e0 = Geometry.crossProductXYXY(a0, a1, c0, c1); const e1 = Geometry.crossProductXYXY(b0, b1, c0, c1) + Geometry.crossProductXYXY(a0, a1, d0, d1); @@ -1731,7 +1897,6 @@ export class BilinearPolynomial { /** uv coefficient */ public d: number; /** - * * @param a constant coefficient * @param b `u` coefficient * @param c `v` coefficient @@ -1764,8 +1929,7 @@ export class BilinearPolynomial { * @param qValue */ public static solvePair(p: BilinearPolynomial, pValue: number, q: BilinearPolynomial, qValue: number): Point2d[] | undefined { - return SmallSystem.solveBilinearPair(p.a - pValue, p.b, p.c, p.d, - q.a - qValue, q.b, q.c, q.d); + return SmallSystem.solveBilinearPair(p.a - pValue, p.b, p.c, p.d, q.a - qValue, q.b, q.c, q.d); } } @@ -1781,7 +1945,6 @@ export class SineCosinePolynomial { /** sine coefficient */ public sineCoff: number; /** - * * @param a constant coefficient * @param cosineCoff `cos(theta)` coefficient * @param sinCoff `sin(theta)` coefficient @@ -1845,8 +2008,8 @@ export class ImplicitLineXY { */ public a: number; /** - * x coefficient - */ + * x coefficient + */ public ax: number; /** * y coefficient diff --git a/core/geometry/src/numerics/Quadrature.ts b/core/geometry/src/numerics/Quadrature.ts index 1fa8d4de2f91..4d79a1fdead6 100644 --- a/core/geometry/src/numerics/Quadrature.ts +++ b/core/geometry/src/numerics/Quadrature.ts @@ -40,9 +40,21 @@ export class Quadrature { public static readonly gaussW4Interval01 = new Float64Array([0.17392742256872692, 0.3260725774312731, 0.3260725774312731, 0.17392742256872692]); /** x value for 5 point gauss rule in 0..1 interval */ - public static readonly gaussX5Interval01 = new Float64Array([0.04691007703066802, 0.23076534494715845, 0.5, 0.7692346550528415, 0.9530899229693319]); + public static readonly gaussX5Interval01 = new Float64Array([ + 0.04691007703066802, + 0.23076534494715845, + 0.5, + 0.7692346550528415, + 0.9530899229693319, + ]); /** weight for 5 point gauss rule in 0..1 interval */ - public static readonly gaussW5Interval01 = new Float64Array([0.11846344252809454, 0.23931433524968324, 0.28444444444444444, 0.23931433524968324, 0.11846344252809454]); + public static readonly gaussW5Interval01 = new Float64Array([ + 0.11846344252809454, + 0.23931433524968324, + 0.28444444444444444, + 0.23931433524968324, + 0.11846344252809454, + ]); /** * Given points and weights in a reference interval (usually 0 to 1): @@ -133,16 +145,17 @@ const w2 = h * (18.0 - r) / 36.0; xMapped[0] = x0 - a2; xMapped[1] = x0 - a1; xMapped[2] = x0 + a1; xMapped[3] = x0 + a2; wMapped[0] = w2; wMapped[1] = w1; wMapped[2] = w1; wMapped[3] = w2; return 4; -*/ + */ } /** Sum function values with given weights and x values. */ public static sum1( xx: Float64Array, ww: Float64Array, n: number, - f: (x: number) => number): number { + f: (x: number) => number, + ): number { let sum = 0; - for (let i = 0; i < n; i++)sum += ww[i] * f(xx[i]); + for (let i = 0; i < n; i++) sum += ww[i] * f(xx[i]); return sum; } /** @@ -161,7 +174,7 @@ return 4; let sum = 0; for (let i = 1; i <= numInterval; i++) { const xA = Geometry.interpolate(x0, (i - 1) * df, x1); - const xB = i === numInterval ? x1 : Geometry.interpolate(x0, (i) * df, x1); + const xB = i === numInterval ? x1 : Geometry.interpolate(x0, i * df, x1); const n = mapper.mapXAndW(xA, xB); for (let k = 0; k < n; k++) { sum += mapper.gaussW[k] * f(mapper.gaussX[k]); @@ -192,20 +205,29 @@ export class GaussMapper { * @param numGauss requested number of gauss points. */ public constructor(numGaussPoints: number) { - const maxGauss = 7; // (As of Nov 2 2018, 7 is a fluffy over-allocation-- the quadrature class only handles up to 5.) + const maxGauss = 7; // (As of Nov 2 2018, 7 is a fluffy over-allocation-- the quadrature class only handles up to 5.) this.gaussX = new Float64Array(maxGauss); this.gaussW = new Float64Array(maxGauss); // This sets the number of gauss points. This integrates exactly for polynomials of (degree 2*numGauss - 1). if (numGaussPoints > 5 || numGaussPoints < 1) numGaussPoints = 5; switch (numGaussPoints) { - case 1: this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss1(xA, xB, xMapped, wMapped); break; - case 2: this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss2(xA, xB, xMapped, wMapped); break; - case 3: this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss3(xA, xB, xMapped, wMapped); break; - case 4: this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss4(xA, xB, xMapped, wMapped); break; - default: this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss5(xA, xB, xMapped, wMapped); break; + case 1: + this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss1(xA, xB, xMapped, wMapped); + break; + case 2: + this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss2(xA, xB, xMapped, wMapped); + break; + case 3: + this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss3(xA, xB, xMapped, wMapped); + break; + case 4: + this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss4(xA, xB, xMapped, wMapped); + break; + default: + this.mapXAndWFunction = (xA, xB, xMapped, wMapped) => Quadrature.setupGauss5(xA, xB, xMapped, wMapped); + break; } - } } // someday .... http://www.holoborodko.com/pavel/numerical-methods/numerical-integration/overlapped-newton-cotes-quadratures/ diff --git a/core/geometry/src/numerics/Range1dArray.ts b/core/geometry/src/numerics/Range1dArray.ts index e8033d0f33be..ccc6c96db721 100644 --- a/core/geometry/src/numerics/Range1dArray.ts +++ b/core/geometry/src/numerics/Range1dArray.ts @@ -186,7 +186,7 @@ export class Range1dArray { data.sort(compareRange1dLexicalLowHigh); - let currentIndex = 0; // last accepted interval + let currentIndex = 0; // last accepted interval for (let i = 1; i < data.length; i++) { if (data[i].low <= data[currentIndex].high) { // extend the current range @@ -283,7 +283,13 @@ export class Range1dArray { * @param sort optionally request immediate sort. * @param compress optionally request removal of duplicates. */ - public static getBreaks(data: Range1d[], result?: GrowableFloat64Array, sort: boolean = false, compress: boolean = false, clear: boolean = true): GrowableFloat64Array { + public static getBreaks( + data: Range1d[], + result?: GrowableFloat64Array, + sort: boolean = false, + compress: boolean = false, + clear: boolean = true, + ): GrowableFloat64Array { if (!result) result = new GrowableFloat64Array(2 * data.length); if (clear) result.clear(); for (const range of data) { @@ -308,9 +314,16 @@ export class Range1dArray { * @param finalRangeFraction fraction coordinate applied only to last range (typically an extrapolation above) * @param result array to receive values */ - public static appendFractionalPoints(data: Range1d[], initialRangeFraction: number | undefined, rangeFraction: number | undefined, includeDegenerateRange: boolean, - gapFraction: number | undefined, includeDegenerateGap: boolean, - finalRangeFraction: number | undefined, result: GrowableFloat64Array | number[]): GrowableFloat64Array | number[] { + public static appendFractionalPoints( + data: Range1d[], + initialRangeFraction: number | undefined, + rangeFraction: number | undefined, + includeDegenerateRange: boolean, + gapFraction: number | undefined, + includeDegenerateGap: boolean, + finalRangeFraction: number | undefined, + result: GrowableFloat64Array | number[], + ): GrowableFloat64Array | number[] { const numRange = data.length; if (numRange > 0) { if (undefined !== initialRangeFraction) diff --git a/core/geometry/src/numerics/TriDiagonalSystem.ts b/core/geometry/src/numerics/TriDiagonalSystem.ts index 896340010132..95e6461927aa 100644 --- a/core/geometry/src/numerics/TriDiagonalSystem.ts +++ b/core/geometry/src/numerics/TriDiagonalSystem.ts @@ -21,7 +21,6 @@ enum DataState { * @internal */ export class TriDiagonalSystem { - // Lower diagonal, indexed by rows private _aLeft: Float64Array; // Upper diagonal, indexed by rows @@ -49,7 +48,12 @@ export class TriDiagonalSystem { this._dataState = DataState.RawMatrix; const n = this._aDiag.length; for (let i = 0; i < n; i++) { - this._aLeft[i] = this._aRight[i] = this._aDiag[i] = this._b[i] = this._x[i] = 0.0; + this._aLeft[i] = + this._aRight[i] = + this._aDiag[i] = + this._b[i] = + this._x[i] = + 0.0; } } /** Install data in a row of the matrix */ @@ -128,7 +132,6 @@ export class TriDiagonalSystem { if (this._dataState === DataState.FactorFailed) { return false; } else if (this._dataState === DataState.FactorOK) { - const n = this._aDiag.length; const nm1 = n - 1; for (let i = 0; i < nm1; i++) { @@ -148,9 +151,14 @@ export class TriDiagonalSystem { let i; for (i = 1; i < nm1; i++) { Point3d.createAdd3Scaled( - pointX[i - 1], this._aLeft[i], pointX[i], this._aDiag[i], - pointX[i + 1], this._aRight[i], - pointB[i]); + pointX[i - 1], + this._aLeft[i], + pointX[i], + this._aDiag[i], + pointX[i + 1], + this._aRight[i], + pointB[i], + ); } Point3d.createAdd2Scaled(pointX[n - 2], this._aLeft[nm1], pointX[nm1], this._aDiag[nm1], pointB[nm1]); return true; @@ -185,7 +193,7 @@ export class TriDiagonalSystem { } this._dataState = DataState.FactorFailed; - const n1 = this._aDiag.length - 1; // Last pivot index + const n1 = this._aDiag.length - 1; // Last pivot index // Eliminate in subdiagonal. for (let i = 0; i < n1; i++) { const r = Geometry.conditionalDivideFraction(this._aLeft[i + 1], this._aDiag[i]); @@ -292,7 +300,8 @@ export class TriDiagonalSystem { for (let i = 0; i < n; i++) { data.push( - [i, [this._aLeft[i], this._aDiag[i], this._aRight[i]], this._x[i], this._b[i]]); + [i, [this._aLeft[i], this._aDiag[i], this._aRight[i]], this._x[i], this._b[i]], + ); } return data; } @@ -304,7 +313,8 @@ export class TriDiagonalSystem { for (let i = 0; i < n; i++) { data.push( - [i, [this._aLeft[i], this._aDiag[i], this._aRight[i]], this._x[i], xyzB[i].toJSON()]); + [i, [this._aLeft[i], this._aDiag[i], this._aRight[i]], this._x[i], xyzB[i].toJSON()], + ); } return data; } diff --git a/core/geometry/src/numerics/UnionFind.ts b/core/geometry/src/numerics/UnionFind.ts index 9f57f4f39f01..e4b8b4a975be 100644 --- a/core/geometry/src/numerics/UnionFind.ts +++ b/core/geometry/src/numerics/UnionFind.ts @@ -22,7 +22,9 @@ export class UnionFindContext { this._parentArray.push(i); } /** Return the number of leaves. */ - public get length(): number { return this._parentArray.length; } + public get length(): number { + return this._parentArray.length; + } /** test if index is within the valid index range. */ public isValidIndex(index: number): boolean { return 0 <= index && index < this._parentArray.length; diff --git a/core/geometry/src/numerics/UsageSums.ts b/core/geometry/src/numerics/UsageSums.ts index c0b2d90952ca..9b7e9853a2c3 100644 --- a/core/geometry/src/numerics/UsageSums.ts +++ b/core/geometry/src/numerics/UsageSums.ts @@ -52,16 +52,24 @@ export class UsageSums { this._origin = origin; } /** Return the number of samples seen */ - public get count(): number { return this._count; } + public get count(): number { + return this._count; + } /** return the mean of all samples. * * Return 0 if no samples */ - public get mean(): number { return this._count > 0 ? this._sumX / this._count : 0.0; } + public get mean(): number { + return this._count > 0 ? this._sumX / this._count : 0.0; + } /** Return the mean of squared samples. * * Return 0 if no samples. */ - public get meanSquare(): number { return this._count > 0 ? this._sumXX / this._count : 0.0; } - public get minMax(): Range1d { return this._minMax.clone(); } + public get meanSquare(): number { + return this._count > 0 ? this._sumXX / this._count : 0.0; + } + public get minMax(): Range1d { + return this._minMax.clone(); + } /** * Return the "biased standard deviation" (https://en.wikipedia.org/wiki/Standard_deviation) @@ -85,7 +93,9 @@ export class UsageSums { /** * return the origin being used in the `accumulate(x)` method. */ - public get origin(): number { return this._origin; } + public get origin(): number { + return this._origin; + } /** * Reset the origin. * * Former sums are unchanged !! diff --git a/core/geometry/src/polyface/AuxData.ts b/core/geometry/src/polyface/AuxData.ts index 703ae68725a8..d7a0a076e94b 100644 --- a/core/geometry/src/polyface/AuxData.ts +++ b/core/geometry/src/polyface/AuxData.ts @@ -9,10 +9,10 @@ // import { Point2d } from "./Geometry2d"; /* eslint-disable @typescript-eslint/naming-convention, no-empty */ -import { Transform } from "../geometry3d/Transform"; import { Matrix3d } from "../geometry3d/Matrix3d"; import { Point3d } from "../geometry3d/Point3dVector3d"; import { NumberArray } from "../geometry3d/PointHelpers"; +import { Transform } from "../geometry3d/Transform"; // import { Geometry } from "./Geometry"; import { Range1d, Range3d } from "../geometry3d/Range"; @@ -41,7 +41,7 @@ export enum AuxChannelDataType { /** Represents the [[AuxChannel]] data at a single input value. * @public -*/ + */ export class AuxChannelData { /** The input value for this data. */ public input: number; @@ -80,7 +80,7 @@ export class AuxChannelData { /** Represents a single [[PolyfaceAuxData]] channel. * @public -*/ + */ export class AuxChannel { /** An array of [[AuxChannelData]] that represents the vertex data at one or more input values. */ public data: AuxChannelData[]; @@ -108,10 +108,12 @@ export class AuxChannel { /** Toleranced comparison of contents. */ public isAlmostEqual(other: AuxChannel, tol?: number): boolean { - if (this.dataType !== other.dataType || + if ( + this.dataType !== other.dataType || this.name !== other.name || this.inputName !== other.inputName || - this.data.length !== other.data.length) + this.data.length !== other.data.length + ) return false; for (let i = 0; i < this.data.length; i++) @@ -271,7 +273,7 @@ export class PolyfaceAuxData { case AuxChannelDataType.Normal: { inverseRot = inverseRot ?? rot.inverse(); if (!inverseRot) - return false; + return false; transformPoints(data.values, (point) => inverseRot!.multiplyTransposeVectorInPlace(point)); break; diff --git a/core/geometry/src/polyface/BoxTopology.ts b/core/geometry/src/polyface/BoxTopology.ts index 1e535ed831a1..202b94bd48ba 100644 --- a/core/geometry/src/polyface/BoxTopology.ts +++ b/core/geometry/src/polyface/BoxTopology.ts @@ -52,17 +52,16 @@ export class BoxTopology { /** IN faceId pair, the first component for bottom and top caps is `primaryCapId` */ public static readonly primaryCapId = -1; /** Indices of vertices around faces, in CCW from the outside. */ - public static readonly cornerIndexCCW = - [ + public static readonly cornerIndexCCW = [ [1, 0, 2, 3], [4, 5, 7, 6], [0, 1, 5, 4], [1, 3, 7, 5], [3, 2, 6, 7], - [2, 0, 4, 6]]; + [2, 0, 4, 6], + ]; /** // [partnerFace[faceIndex][k] = index of k'th adjacent face */ - public static readonly partnerFace = - [ + public static readonly partnerFace = [ [5, 4, 3, 2], [2, 3, 4, 5], [0, 3, 1, 5], @@ -77,25 +76,26 @@ export class BoxTopology { [0, 0], [0, 1], [0, 2], - [0, 3]]; + [0, 3], + ]; /** * Table to look up axis indices of edges and normals in box faces. * faceDirections[faceIndex] =[[edge0AxisIndex, edge1AxisIndex, normalAxisIndex],[direction sign for along the axis] */ - public static readonly faceDirections = - [ + public static readonly faceDirections = [ [[0, 1, 2], [-1, 1, -1]], [[0, 1, 2], [1, 1, 1]], [[0, 2, 1], [1, -1, 1]], [[1, 2, 0], [1, 1, 1]], [[0, 2, 1], [-1, 1, 1]], - [[1, 2, 0], [-1, 1, -1]]]; + [[1, 2, 0], [-1, 1, -1]], + ]; /** There are 4 edges in each axis direction. * * axisEdgeVertex[axisIndex][edgeIndex 0..3][*] = vertex index at end of edge in axisIndex direction. */ - public static readonly axisEdgeVertex = - [ + public static readonly axisEdgeVertex = [ [[0, 1], [2, 3], [4, 5], [6, 7]], [[0, 2], [1, 3], [4, 6], [5, 7]], - [[0, 4], [1, 5], [2, 6], [3, 7]]]; + [[0, 4], [1, 5], [2, 6], [3, 7]], + ]; } diff --git a/core/geometry/src/polyface/FacetFaceData.ts b/core/geometry/src/polyface/FacetFaceData.ts index 44155e94f0fc..85a3a8b1512a 100644 --- a/core/geometry/src/polyface/FacetFaceData.ts +++ b/core/geometry/src/polyface/FacetFaceData.ts @@ -9,8 +9,8 @@ import { Point2d, Vector2d } from "../geometry3d/Point2dVector2d"; import { Point3d } from "../geometry3d/Point3dVector3d"; import { Range2d } from "../geometry3d/Range"; -import { IndexedPolyface } from "./Polyface"; import { IndexedPolyfaceVisitor } from "./IndexedPolyfaceVisitor"; +import { IndexedPolyface } from "./Polyface"; /** * Data for a face in a polyface containing facets. @@ -22,9 +22,13 @@ export class FacetFaceData { private _paramDistanceRange: Range2d; private _paramRange: Range2d; /** (property accessor) Return a reference to the distance-scaled parameter range. */ - public get paramDistanceRange(): Range2d { return this._paramDistanceRange; } + public get paramDistanceRange(): Range2d { + return this._paramDistanceRange; + } /** (property accessor) Return a reference to the parameter range. */ - public get paramRange(): Range2d { return this._paramRange; } + public get paramRange(): Range2d { + return this._paramRange; + } private constructor(distanceRange: Range2d, paramRange: Range2d) { this._paramDistanceRange = distanceRange; this._paramRange = paramRange; @@ -52,9 +56,9 @@ export class FacetFaceData { result = result ? result : Point2d.create(); const paramDelta = this._paramRange.high.minus(this._paramRange.low); result.x = (0 === paramDelta.x) ? x : (this._paramDistanceRange.low.x + (x - this._paramRange.low.x) - * (this._paramDistanceRange.high.x - this._paramDistanceRange.low.x) / paramDelta.x); + * (this._paramDistanceRange.high.x - this._paramDistanceRange.low.x) / paramDelta.x); result.y = (0.0 === paramDelta.y) ? y : (this.paramDistanceRange.low.y + (y - this._paramRange.low.y) - * (this._paramDistanceRange.high.y - this._paramDistanceRange.low.y) / paramDelta.y); + * (this._paramDistanceRange.high.y - this._paramDistanceRange.low.y) / paramDelta.y); return result; } /** Return normalized (0-1) parameter from stored parameter value. */ @@ -110,8 +114,12 @@ export class FacetFaceData { if (k > 1) { visitorParams.vectorIndexIndex(triangleParamIndexes[1], triangleParamIndexes[0], dUV0); visitorParams.vectorIndexIndex(triangleParamIndexes[1], triangleParamIndexes[2], dUV1); - const delta0 = visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[0]).minus(visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[1])); - const delta1 = visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[1]).minus(visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[2])); + const delta0 = visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[0]).minus( + visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[1]), + ); + const delta1 = visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[1]).minus( + visitorPoints.getPoint3dAtUncheckedPointIndex(trianglePointIndexes[2]), + ); const uvCross = Math.abs(dUV0.x * dUV1.y - dUV1.x * dUV0.y); if (uvCross) { const dwDu = Point3d.createFrom(delta0); @@ -136,10 +144,16 @@ export class FacetFaceData { } while (visitor.moveToNextFacet() && visitor.currentReadIndex() < facetEnd); if (aveTotal !== 0) { const dS = Point2d.create(dSTotal.x / aveTotal, dSTotal.y / aveTotal); - const standardDeviation = Point2d.create(Math.sqrt(Math.abs((dSSquaredTotal.x / aveTotal) - dS.x * dS.x)), Math.sqrt(Math.abs((dSSquaredTotal.y / aveTotal) - dS.y * dS.y))); + const standardDeviation = Point2d.create( + Math.sqrt(Math.abs((dSSquaredTotal.x / aveTotal) - dS.x * dS.x)), + Math.sqrt(Math.abs((dSSquaredTotal.y / aveTotal) - dS.y * dS.y)), + ); // TR# 268980 - Add standard deviation to match QV.... this._paramDistanceRange.low.set(0, 0); - this._paramDistanceRange.high.set((dS.x + standardDeviation.x) * (this._paramRange.high.x - this._paramRange.low.x), (dS.y + standardDeviation.y) * (this._paramRange.high.y - this._paramRange.low.y)); + this._paramDistanceRange.high.set( + (dS.x + standardDeviation.x) * (this._paramRange.high.x - this._paramRange.low.x), + (dS.y + standardDeviation.y) * (this._paramRange.high.y - this._paramRange.low.y), + ); } return true; } diff --git a/core/geometry/src/polyface/FacetLocationDetail.ts b/core/geometry/src/polyface/FacetLocationDetail.ts index 5dc1052bbb66..f136a4b063fc 100644 --- a/core/geometry/src/polyface/FacetLocationDetail.ts +++ b/core/geometry/src/polyface/FacetLocationDetail.ts @@ -6,15 +6,15 @@ * @module Polyface */ -import { Point2d } from "../geometry3d/Point2dVector2d"; -import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; -import { TriangleLocationDetail } from "../geometry3d/BarycentricTriangle"; import { Geometry, PolygonLocation } from "../Geometry"; -import { PolyfaceVisitor } from "./Polyface"; -import { PolygonLocationDetail, PolygonOps } from "../geometry3d/PolygonOps"; -import { IndexedXYZCollection } from "../geometry3d/IndexedXYZCollection"; +import { TriangleLocationDetail } from "../geometry3d/BarycentricTriangle"; import { IndexedXYCollection } from "../geometry3d/IndexedXYCollection"; +import { IndexedXYZCollection } from "../geometry3d/IndexedXYZCollection"; +import { Point2d } from "../geometry3d/Point2dVector2d"; +import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; import { NumberArray } from "../geometry3d/PointHelpers"; +import { PolygonLocationDetail, PolygonOps } from "../geometry3d/PolygonOps"; +import { PolyfaceVisitor } from "./Polyface"; /** Callback for processing the detail for an intersected facet. * @param detail reference to the intersection data, with `detail.IsInsideOn === true`. Note that `detail` is owned by the caller; to persist, use `detail.clone`. @@ -137,11 +137,15 @@ export class TriangularFacetLocationDetail implements FacetLocationDetail { * @param detail optional, copied if given * @param result optional pre-allocated object to fill and return */ - public static create(facetIndex: number = -1, detail?: TriangleLocationDetail, result?: TriangularFacetLocationDetail): TriangularFacetLocationDetail { + public static create( + facetIndex: number = -1, + detail?: TriangleLocationDetail, + result?: TriangularFacetLocationDetail, + ): TriangularFacetLocationDetail { if (!result) result = new TriangularFacetLocationDetail(); else - result.invalidate(false); // shallow: detail might be owned by result! + result.invalidate(false); // shallow: detail might be owned by result! result._facetIndex = facetIndex; if (undefined !== detail && result._detail !== detail) result._detail.copyContentsFrom(detail); @@ -245,7 +249,7 @@ export class TriangularFacetLocationDetail implements FacetLocationDetail { } /** Get the barycentric coordinates of this location. * @returns cached barycentric coordinates - */ + */ public getBarycentricCoordinates(): number[] { return [this._detail.local.x, this._detail.local.y, this._detail.local.z]; } @@ -277,11 +281,16 @@ export class NonConvexFacetLocationDetail implements FacetLocationDetail { * @param detail optional, copied if given * @param result optional pre-allocated object to fill and return */ - public static create(facetIndex: number = -1, edgeCount: number = 0, detail?: PolygonLocationDetail, result?: NonConvexFacetLocationDetail): NonConvexFacetLocationDetail { + public static create( + facetIndex: number = -1, + edgeCount: number = 0, + detail?: PolygonLocationDetail, + result?: NonConvexFacetLocationDetail, + ): NonConvexFacetLocationDetail { if (!result) result = new NonConvexFacetLocationDetail(); else - result.invalidate(false); // shallow: detail might be owned by result! + result.invalidate(false); // shallow: detail might be owned by result! result._facetIndex = facetIndex; result._edgeCount = edgeCount; if (undefined !== detail && result._detail !== detail) @@ -348,19 +357,19 @@ export class NonConvexFacetLocationDetail implements FacetLocationDetail { } /** Interpolated data is not defined for a non-convex facet. * @returns undefined - */ + */ public getNormal(): Vector3d | undefined { return undefined; } /** Interpolated data is not defined for a non-convex facet. * @returns undefined - */ + */ public getParam(): Point2d | undefined { return undefined; } /** Interpolated data is not defined for a non-convex facet. * @returns undefined - */ + */ public getColor(): number | undefined { return undefined; } @@ -398,11 +407,16 @@ export class ConvexFacetLocationDetail extends NonConvexFacetLocationDetail { * @param detail optional, copied if given * @param result optional pre-allocated object to fill and return */ - public static override create(facetIndex: number = -1, edgeCount: number = 0, detail?: PolygonLocationDetail, result?: ConvexFacetLocationDetail): ConvexFacetLocationDetail { + public static override create( + facetIndex: number = -1, + edgeCount: number = 0, + detail?: PolygonLocationDetail, + result?: ConvexFacetLocationDetail, + ): ConvexFacetLocationDetail { if (!result) result = new ConvexFacetLocationDetail(); else - result.invalidate(false); // shallow: detail might be owned by result! + result.invalidate(false); // shallow: detail might be owned by result! return super.create(facetIndex, edgeCount, detail, result); } /** Create a detail, capturing inputs. */ @@ -435,7 +449,11 @@ export class ConvexFacetLocationDetail extends NonConvexFacetLocationDetail { * @param distanceTolerance used to compute the barycentric coordinate cache * @returns reference to cached normal */ - public override getNormal(facetNormals?: IndexedXYZCollection, facetVertices?: IndexedXYZCollection, distanceTolerance: number = Geometry.smallMetricDistance): Vector3d | undefined { + public override getNormal( + facetNormals?: IndexedXYZCollection, + facetVertices?: IndexedXYZCollection, + distanceTolerance: number = Geometry.smallMetricDistance, + ): Vector3d | undefined { if (this._detail.isValid && undefined === this._normal && undefined !== facetNormals) { const scales = this.getBarycentricCoordinates(facetVertices, distanceTolerance); if (undefined !== scales) { @@ -451,7 +469,11 @@ export class ConvexFacetLocationDetail extends NonConvexFacetLocationDetail { * @param distanceTolerance used to compute the barycentric coordinate cache * @returns reference to cached uv parameter */ - public override getParam(facetParams?: IndexedXYCollection, facetVertices?: IndexedXYZCollection, distanceTolerance: number = Geometry.smallMetricDistance): Point2d | undefined { + public override getParam( + facetParams?: IndexedXYCollection, + facetVertices?: IndexedXYZCollection, + distanceTolerance: number = Geometry.smallMetricDistance, + ): Point2d | undefined { if (this._detail.isValid && undefined === this._param && undefined !== facetParams) { const scales = this.getBarycentricCoordinates(facetVertices, distanceTolerance); if (undefined !== scales) { @@ -467,7 +489,11 @@ export class ConvexFacetLocationDetail extends NonConvexFacetLocationDetail { * @param distanceTolerance used to compute the barycentric coordinate cache * @returns cached color */ - public override getColor(facetColors?: number[], facetVertices?: IndexedXYZCollection, distanceTolerance: number = Geometry.smallMetricDistance): number | undefined { + public override getColor( + facetColors?: number[], + facetVertices?: IndexedXYZCollection, + distanceTolerance: number = Geometry.smallMetricDistance, + ): number | undefined { if (this._detail.isValid && undefined === this._color && undefined !== facetColors) { const scales = this.getBarycentricCoordinates(facetVertices, distanceTolerance); if (undefined !== scales) @@ -479,8 +505,11 @@ export class ConvexFacetLocationDetail extends NonConvexFacetLocationDetail { * @param facetVertices used to compute the barycentric coordinate cache * @param distanceTolerance used to compute the barycentric coordinate cache * @returns cached barycentric coordinates - */ - public override getBarycentricCoordinates(facetVertices?: IndexedXYZCollection, distanceTolerance: number = Geometry.smallMetricDistance): number[] | undefined { + */ + public override getBarycentricCoordinates( + facetVertices?: IndexedXYZCollection, + distanceTolerance: number = Geometry.smallMetricDistance, + ): number[] | undefined { if (this._detail.isValid && undefined === this._barycentricCoordinates && undefined !== facetVertices) { this._barycentricCoordinates = PolygonOps.convexBarycentricCoordinates(facetVertices, this._detail.point, distanceTolerance); } diff --git a/core/geometry/src/polyface/FacetOrientation.ts b/core/geometry/src/polyface/FacetOrientation.ts index 17e2929db819..41b188641396 100644 --- a/core/geometry/src/polyface/FacetOrientation.ts +++ b/core/geometry/src/polyface/FacetOrientation.ts @@ -145,7 +145,9 @@ export class FacetOrientationFixup { if (neighborOrientation === 0) { // first visit to this facet ! // orientations of baseEdge and neighborEdge tell us how to orient it. - const newOrientation = SortableEdge.areDirectedPartners(edgeArray[baseEdgeIndex], edgeArray[neighborEdgeIndex]) ? baseOrientation : -baseOrientation; + const newOrientation = SortableEdge.areDirectedPartners(edgeArray[baseEdgeIndex], edgeArray[neighborEdgeIndex]) + ? baseOrientation + : -baseOrientation; this.recordFacetInComponent(neighborFacet, newOrientation); this.pushFacetEdgesOnStack(neighborEdgeIndex, edgeStack); FacetOrientationFixup.swapEntries(this._edgeToEdgeInComponent, baseEdgeIndex, neighborEdgeIndex); @@ -192,7 +194,6 @@ export class FacetOrientationFixup { data[j] = q; } /** - * * @param data an array of cyclically linked loops. */ private static extractCyclicIndices(data: number[], index0: number, loopIndices: number[]) { diff --git a/core/geometry/src/polyface/GreedyTriangulationBetweenLineStrings.ts b/core/geometry/src/polyface/GreedyTriangulationBetweenLineStrings.ts index 6b64853d135f..80b90285a818 100644 --- a/core/geometry/src/polyface/GreedyTriangulationBetweenLineStrings.ts +++ b/core/geometry/src/polyface/GreedyTriangulationBetweenLineStrings.ts @@ -19,7 +19,6 @@ import { TriangleCandidate } from "./TriangleCandidate"; * @internal */ export class GreedyTriangulationBetweenLineStrings { - private _vector1: Vector3d; private constructor(turnRadians: number) { this._turnRadians = turnRadians; @@ -37,7 +36,8 @@ export class GreedyTriangulationBetweenLineStrings { private isForwardVector( candidate: Vector3d, forward: Vector3d, - perp: Vector3d): boolean { + perp: Vector3d, + ): boolean { if (candidate.dotProduct(forward) <= 0.0) return false; const theta = candidate.angleFromPerpendicular(perp); @@ -55,7 +55,8 @@ export class GreedyTriangulationBetweenLineStrings { forwardA: Vector3d, xyzB: Point3d, crossB: Vector3d, - forwardB: Vector3d): boolean { + forwardB: Vector3d, + ): boolean { if (baseA + 1 < pointsA.length && baseB + 1 < pointsB.length) { pointsA.getPoint3dAtUncheckedPointIndex(baseA, xyzA); pointsB.getPoint3dAtUncheckedPointIndex(baseB, xyzB); @@ -68,7 +69,6 @@ export class GreedyTriangulationBetweenLineStrings { return true; } return false; - } /** * Starting at start in source, examine points to see how long they are close to being "in plane" @@ -85,8 +85,9 @@ export class GreedyTriangulationBetweenLineStrings { perpA: Vector3d, forwardA: Vector3d, perpB: Vector3d, - forwardB: Vector3d) { - child.setFrom(parent, parent.begin, trialEnd); // initialize as empty interval. + forwardB: Vector3d, + ) { + child.setFrom(parent, parent.begin, trialEnd); // initialize as empty interval. while (child.end < parent.end) { child.points.vectorXYAndZIndex(xyzA, child.end, this._vector1); if (!this.isForwardVector(this._vector1, forwardA, perpA)) @@ -119,20 +120,74 @@ export class GreedyTriangulationBetweenLineStrings { intervalA: IndexedXYZCollectionInterval, intervalB: IndexedXYZCollectionInterval, handler: (triangle: BarycentricTriangle) => void, - addOnly1: boolean = false) { + addOnly1: boolean = false, + ) { intervalA.restrictEnd(); intervalB.restrictEnd(); while (intervalA.length > 1 && intervalB.length > 1) { - // triangles A1 and B1 are always valid. - this._triangleA1 = TriangleCandidate.createFromIndexedXYZ(intervalA.points, intervalA.begin, intervalA.points, intervalA.begin + 1, intervalB.points, intervalB.begin, 1, this._triangleA1); - this._triangleA2 = TriangleCandidate.createFromIndexedXYZ(intervalA.points, intervalA.begin + 1, intervalA.points, intervalA.begin + 2, intervalB.points, intervalB.begin, 2, this._triangleA2); - this._triangleA3 = TriangleCandidate.createFromIndexedXYZ(intervalA.points, intervalA.begin, intervalA.points, intervalA.begin + 1, intervalB.points, intervalB.begin + 1, 3, this._triangleA3); + this._triangleA1 = TriangleCandidate.createFromIndexedXYZ( + intervalA.points, + intervalA.begin, + intervalA.points, + intervalA.begin + 1, + intervalB.points, + intervalB.begin, + 1, + this._triangleA1, + ); + this._triangleA2 = TriangleCandidate.createFromIndexedXYZ( + intervalA.points, + intervalA.begin + 1, + intervalA.points, + intervalA.begin + 2, + intervalB.points, + intervalB.begin, + 2, + this._triangleA2, + ); + this._triangleA3 = TriangleCandidate.createFromIndexedXYZ( + intervalA.points, + intervalA.begin, + intervalA.points, + intervalA.begin + 1, + intervalB.points, + intervalB.begin + 1, + 3, + this._triangleA3, + ); - this._triangleB1 = TriangleCandidate.createFromIndexedXYZ(intervalB.points, intervalB.begin + 1, intervalB.points, intervalB.begin, intervalA.points, intervalA.begin, -1, this._triangleB1); - this._triangleB2 = TriangleCandidate.createFromIndexedXYZ(intervalB.points, intervalB.begin + 2, intervalB.points, intervalB.begin + 1, intervalA.points, intervalA.begin, -2, this._triangleB2); - this._triangleB3 = TriangleCandidate.createFromIndexedXYZ(intervalB.points, intervalB.begin + 1, intervalB.points, intervalB.begin, intervalA.points, intervalA.begin + 1, -3, this._triangleB3); + this._triangleB1 = TriangleCandidate.createFromIndexedXYZ( + intervalB.points, + intervalB.begin + 1, + intervalB.points, + intervalB.begin, + intervalA.points, + intervalA.begin, + -1, + this._triangleB1, + ); + this._triangleB2 = TriangleCandidate.createFromIndexedXYZ( + intervalB.points, + intervalB.begin + 2, + intervalB.points, + intervalB.begin + 1, + intervalA.points, + intervalA.begin, + -2, + this._triangleB2, + ); + this._triangleB3 = TriangleCandidate.createFromIndexedXYZ( + intervalB.points, + intervalB.begin + 1, + intervalB.points, + intervalB.begin, + intervalA.points, + intervalA.begin + 1, + -3, + this._triangleB3, + ); // Look at pairs of 2 triangles. // (each pair begins with 1 or -1) // For each pair find the smallest aspect ratio of its two triangles. (Small is bad) @@ -159,7 +214,16 @@ export class GreedyTriangulationBetweenLineStrings { // sweep in trailing points from either side. At least one of intervalA.begin, intervalB.begin is at its limit, so only one of these will execute any bodies. if (intervalA.isSingleton) { while (intervalB.length >= 2) { - this._workTriangle = TriangleCandidate.createFromIndexedXYZ(intervalB.points, intervalB.begin + 1, intervalB.points, intervalB.begin, intervalA.points, intervalA.begin, 0, this._workTriangle); + this._workTriangle = TriangleCandidate.createFromIndexedXYZ( + intervalB.points, + intervalB.begin + 1, + intervalB.points, + intervalB.begin, + intervalA.points, + intervalA.begin, + 0, + this._workTriangle, + ); // this._workTriangle.scaleFromPointInPlace(this._workTriangle.points[2], 0.95); // crude visualization aid for tracking logic. handler(this._workTriangle); intervalB.advanceBegin(); @@ -169,7 +233,16 @@ export class GreedyTriangulationBetweenLineStrings { // sweep in trailing points from either side. At least one of baseA, baseB is at its limit, so only one of these will execute any bodies. if (intervalB.isSingleton) { while (intervalA.length >= 2) { - this._workTriangle = TriangleCandidate.createFromIndexedXYZ(intervalA.points, intervalA.begin, intervalA.points, intervalA.begin + 1, intervalB.points, intervalB.begin, 0, this._workTriangle); + this._workTriangle = TriangleCandidate.createFromIndexedXYZ( + intervalA.points, + intervalA.begin, + intervalA.points, + intervalA.begin + 1, + intervalB.points, + intervalB.begin, + 0, + this._workTriangle, + ); // this._workTriangle.scaleFromPointInPlace(this._workTriangle.points[2], 0.95); // crude visualization aid for tracking logic. handler(this._workTriangle); intervalA.advanceBegin(); @@ -192,7 +265,8 @@ export class GreedyTriangulationBetweenLineStrings { public emitTriangles( pointsA: IndexedXYZCollection, pointsB: IndexedXYZCollection, - handler: (triangle: BarycentricTriangle) => void) { + handler: (triangle: BarycentricTriangle) => void, + ) { /** Clean up duplicates for the real logic . . . */ this.emitTrianglesGo(resolveToNoDuplicates(pointsA), resolveToNoDuplicates(pointsB), handler); } @@ -205,7 +279,8 @@ export class GreedyTriangulationBetweenLineStrings { private emitTrianglesGo( pointsA: IndexedXYZCollection, pointsB: IndexedXYZCollection, - handler: (triangle: BarycentricTriangle) => void) { + handler: (triangle: BarycentricTriangle) => void, + ) { const intervalA = IndexedXYZCollectionInterval.createComplete(pointsA); const intervalB = IndexedXYZCollectionInterval.createComplete(pointsB); const childA = IndexedXYZCollectionInterval.createComplete(pointsA); @@ -213,19 +288,58 @@ export class GreedyTriangulationBetweenLineStrings { while (intervalA.length > 0 && intervalB.length > 0 && (intervalA.length > 1 || intervalB.length > 1)) { // const lA = intervalA.length; // const lB = intervalB.length; - if (this.isPlanarBase(pointsA, intervalA.begin, pointsB, intervalB.begin, this._xyzA, this._crossA, this._forwardA, this._xyzB, this._crossB, this._forwardB)) { + if ( + this.isPlanarBase( + pointsA, + intervalA.begin, + pointsB, + intervalB.begin, + this._xyzA, + this._crossA, + this._forwardA, + this._xyzB, + this._crossB, + this._forwardB, + ) + ) { this.advanceToPlanarLimit(intervalA, childA, intervalA.begin + 1, this._xyzA, this._crossA, this._forwardA, this._crossB, this._forwardB); this.advanceToPlanarLimit(intervalB, childB, intervalB.begin + 1, this._xyzB, this._crossB, this._forwardB, this._crossA, this._forwardA); this.addGreedy(childA, childB, handler); intervalA.advanceToTail(childA); intervalB.advanceToTail(childB); - } else if (this.isPlanarBase(pointsA, intervalA.begin + 1, pointsB, intervalB.begin, this._xyzA, this._crossA, this._forwardA, this._xyzB, this._crossB, this._forwardB)) { + } else if ( + this.isPlanarBase( + pointsA, + intervalA.begin + 1, + pointsB, + intervalB.begin, + this._xyzA, + this._crossA, + this._forwardA, + this._xyzB, + this._crossB, + this._forwardB, + ) + ) { childA.setFrom(intervalA, intervalA.begin, intervalA.begin + 2); childB.setFrom(intervalB, intervalB.begin, intervalB.begin + 1); this.addGreedy(childA, childB, handler); intervalA.advanceToTail(childA); intervalB.advanceToTail(childB); - } else if (this.isPlanarBase(pointsA, intervalA.begin, pointsB, intervalB.begin + 1, this._xyzA, this._crossA, this._forwardA, this._xyzB, this._crossB, this._forwardB)) { + } else if ( + this.isPlanarBase( + pointsA, + intervalA.begin, + pointsB, + intervalB.begin + 1, + this._xyzA, + this._crossA, + this._forwardA, + this._xyzB, + this._crossB, + this._forwardB, + ) + ) { childA.setFrom(intervalA, intervalA.begin, intervalA.begin + 1); childB.setFrom(intervalB, intervalB.begin, intervalB.begin + 2); this.addGreedy(childA, childB, handler); diff --git a/core/geometry/src/polyface/IndexedEdgeMatcher.ts b/core/geometry/src/polyface/IndexedEdgeMatcher.ts index 1e6740f9943f..6506ef352264 100644 --- a/core/geometry/src/polyface/IndexedEdgeMatcher.ts +++ b/core/geometry/src/polyface/IndexedEdgeMatcher.ts @@ -16,22 +16,36 @@ */ export class SortableEdge extends Float64Array { /** Return the vertex index that appears first in the order stored. */ - public get vertexIndexA(): number { return this[0]; } + public get vertexIndexA(): number { + return this[0]; + } /** Return the vertex index that appears second in the order stored. */ - public get vertexIndexB(): number { return this[1]; } + public get vertexIndexB(): number { + return this[1]; + } /** Return the facet index. */ - public get facetIndex(): number { return this[2]; } + public get facetIndex(): number { + return this[2]; + } /** return true if vertexIndexA is less than vertexIndexB */ - public get isLowHigh(): boolean { return this[0] < this[1]; } + public get isLowHigh(): boolean { + return this[0] < this[1]; + } /** Return the vertex index with lower numeric value */ - public get lowVertexIndex(): number { return this[0] < this[1] ? this[0] : this[1]; } + public get lowVertexIndex(): number { + return this[0] < this[1] ? this[0] : this[1]; + } /** Return the vertex index with higher numeric value */ - public get highVertexIndex(): number { return this[0] > this[1] ? this[0] : this[1]; } + public get highVertexIndex(): number { + return this[0] > this[1] ? this[0] : this[1]; + } /** Return true if the vertices edgeA and edgeB are the same vertex indices in opposite order */ - public static areDirectedPartners(edgeA: SortableEdge, edgeB: SortableEdge): boolean { return edgeA[0] === edgeB[1] && edgeA[1] === edgeB[0]; } + public static areDirectedPartners(edgeA: SortableEdge, edgeB: SortableEdge): boolean { + return edgeA[0] === edgeB[1] && edgeA[1] === edgeB[0]; + } /** Return true if the vertices edgeA and edgeB are the same vertex indices with no consideration of order */ public static areUndirectedPartners(edgeA: SortableEdge, edgeB: SortableEdge): boolean { - return (edgeA[0] === edgeB[0] && edgeA[1] === edgeB[1]) || ((edgeA[0] === edgeB[1] && edgeA[1] === edgeB[0])); + return (edgeA[0] === edgeB[0] && edgeA[1] === edgeB[1]) || (edgeA[0] === edgeB[1] && edgeA[1] === edgeB[0]); } /** Return numeric relationship of edgeA and edgeB: * * 1 if they share start and end in the same order @@ -44,7 +58,9 @@ export class SortableEdge extends Float64Array { return 0; } - public get isNullEdge(): boolean { return this[0] === this[1]; } + public get isNullEdge(): boolean { + return this[0] === this[1]; + } /** * lexical comparison of two edges. * * If the edges have the same vertex pair (in same or opposite order) they will end up adjacent in a sort @@ -75,7 +91,9 @@ export class SortableEdge extends Float64Array { this[1] = vertexB; this[2] = facetIndex; } - public toJSON(): any { return [this[0], this[1], this[2]]; } + public toJSON(): any { + return [this[0], this[1], this[2]]; + } public static clusterToJSON(data: SortableEdgeCluster): any { if (data instanceof SortableEdge) return data.toJSON(); @@ -142,7 +160,6 @@ export class IndexedEdgeMatcher { cluster.push(this.edges[i]); dest.push(cluster); } - } } /** @@ -157,7 +174,12 @@ export class IndexedEdgeMatcher { * @param nullEdges optional array to receive arrays of null edges (same start and end vertex) * @param allOtherClusters optional array to receive arrays in which all the edges are partners in an undirected sense but not a simple directed pair. */ - public sortAndCollectClusters(manifoldPairs: SortableEdgeCluster[] | undefined, singletons?: SortableEdgeCluster[], nullEdges?: SortableEdgeCluster[], allOtherClusters?: SortableEdgeCluster[]) { + public sortAndCollectClusters( + manifoldPairs: SortableEdgeCluster[] | undefined, + singletons?: SortableEdgeCluster[], + nullEdges?: SortableEdgeCluster[], + allOtherClusters?: SortableEdgeCluster[], + ) { this.sort(); if (manifoldPairs) manifoldPairs.length = 0; if (singletons) singletons.length = 0; diff --git a/core/geometry/src/polyface/IndexedPolyfaceVisitor.ts b/core/geometry/src/polyface/IndexedPolyfaceVisitor.ts index 3df830326952..8ba287660b83 100644 --- a/core/geometry/src/polyface/IndexedPolyfaceVisitor.ts +++ b/core/geometry/src/polyface/IndexedPolyfaceVisitor.ts @@ -39,7 +39,6 @@ export class IndexedPolyfaceVisitor extends PolyfaceData implements PolyfaceVisi this._numEdges = 0; this._nextFacetIndex = 0; this._currentFacetIndex = -1; - } /** Return the client polyface object. */ public clientPolyface(): IndexedPolyface { @@ -211,8 +210,8 @@ export class IndexedPolyfaceVisitor extends PolyfaceData implements PolyfaceVisi */ export class IndexedPolyfaceSubsetVisitor extends IndexedPolyfaceVisitor { private _parentFacetIndices?: number[]; // only undefined during super constructor! - private _currentActiveIndex: number; // index within _parentFacetIndices, or -1 after construction - private _nextActiveIndex: number; // index within _parentFacetIndices + private _currentActiveIndex: number; // index within _parentFacetIndices, or -1 after construction + private _nextActiveIndex: number; // index within _parentFacetIndices private constructor(polyface: IndexedPolyface, activeFacetIndices: number[], numWrap: number) { super(polyface, numWrap); @@ -286,14 +285,19 @@ export class IndexedPolyfaceSubsetVisitor extends IndexedPolyfaceVisitor { * The visitor will *not* visit facets whose normals are nearly perpendicular to `compareVector`. * Default is [[Geometry.smallAngleRadians]]. * @param numWrap optional number of entries replicated in visitor arrays. Default is 0. - */ - public static createNormalComparison(mesh: IndexedPolyface | IndexedPolyfaceVisitor, compareVector: Vector3d = Vector3d.unitZ(), sideAngle: Angle = Angle.createSmallAngle(), numWrap: number = 0): IndexedPolyfaceSubsetVisitor { + */ + public static createNormalComparison( + mesh: IndexedPolyface | IndexedPolyfaceVisitor, + compareVector: Vector3d = Vector3d.unitZ(), + sideAngle: Angle = Angle.createSmallAngle(), + numWrap: number = 0, + ): IndexedPolyfaceSubsetVisitor { if (mesh instanceof IndexedPolyface) return this.createNormalComparison(mesh.createVisitor(), compareVector, sideAngle, numWrap); const visitor = mesh; const facets: number[] = []; const facetNormal = Vector3d.createZero(); - for (visitor.reset(); visitor.moveToNextFacet(); ) { + for (visitor.reset(); visitor.moveToNextFacet();) { if (!PolygonOps.unitNormal(visitor.point, facetNormal)) continue; // degenerate facet if (facetNormal.dotProduct(compareVector) < 0.0) diff --git a/core/geometry/src/polyface/PolyfaceBuilder.ts b/core/geometry/src/polyface/PolyfaceBuilder.ts index 2cc73ac3dfae..835c89d09204 100644 --- a/core/geometry/src/polyface/PolyfaceBuilder.ts +++ b/core/geometry/src/polyface/PolyfaceBuilder.ts @@ -235,7 +235,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { super(); this._options = options ? options : StrokeOptions.createForFacets(); this._polyface = IndexedPolyface.create( - this._options.needNormals, this._options.needParams, this._options.needColors, this._options.needTwoSided, + this._options.needNormals, + this._options.needParams, + this._options.needColors, + this._options.needTwoSided, ); this._reversed = false; } @@ -257,7 +260,7 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param range sides become 6 quad polyface facets. * @param faceSelector for each face in the order of `BoxTopology.cornerIndexCCW`, `faceSelector[i] === false` skips * that facet. - */ + */ public addTransformedRangeMesh(transform: Transform, range: Range3d, faceSelector?: boolean[]): void { const pointIndex0 = this._polyface.data.pointCount; // these will have sequential indices starting at pointIndex0 @@ -388,7 +391,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @returns the point index in the polyface. */ public findOrAddPointInLineString( - ls: LineString3d, index: number, transform?: Transform, priorIndex?: number, + ls: LineString3d, + index: number, + transform?: Transform, + priorIndex?: number, ): number | undefined { const q = ls.pointAt(index, PolyfaceBuilder._workPointFindOrAddA); if (q) { @@ -408,7 +414,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @returns the point index in the polyface. */ public findOrAddPointInGrowableXYZArray( - xyz: GrowableXYZArray, index: number, transform?: Transform, priorIndex?: number, + xyz: GrowableXYZArray, + index: number, + transform?: Transform, + priorIndex?: number, ): number | undefined { const q = xyz.getPoint3dAtCheckedPointIndex(index, PolyfaceBuilder._workPointFindOrAddA); if (q) { @@ -428,7 +437,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @returns the normal index in the polyface. */ public findOrAddNormalInGrowableXYZArray( - xyz: GrowableXYZArray, index: number, transform?: Transform, priorIndex?: number, + xyz: GrowableXYZArray, + index: number, + transform?: Transform, + priorIndex?: number, ): number | undefined { const q = xyz.getVector3dAtCheckedVectorIndex(index, PolyfaceBuilder._workVectorFindOrAdd); if (q) { @@ -470,10 +482,15 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @returns the uv parameter index in the polyface. */ public findOrAddParamInLineString( - ls: LineString3d, index: number, v: number, priorIndexA?: number, priorIndexB?: number, + ls: LineString3d, + index: number, + v: number, + priorIndexA?: number, + priorIndexB?: number, ): number | undefined { const u = (ls.fractions && index < ls.fractions.length) ? - ls.fractions.atUncheckedIndex(index) : index / ls.points.length; + ls.fractions.atUncheckedIndex(index) : + index / ls.points.length; return this._polyface.addParamUV(u, v, priorIndexA, priorIndexB); } /** @@ -486,7 +503,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @returns the normal index in the polyface. */ public findOrAddNormalInLineString( - ls: LineString3d, index: number, transform?: Transform, priorIndexA?: number, priorIndexB?: number, + ls: LineString3d, + index: number, + transform?: Transform, + priorIndexA?: number, + priorIndexB?: number, ): number | undefined { const linestringNormals = ls.packedSurfaceNormals; if (linestringNormals) { @@ -537,7 +558,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param colors (optional) array of at least four colors. */ public addQuadFacet( - points: Point3d[] | GrowableXYZArray, params?: Point2d[], normals?: Vector3d[], colors?: number[], + points: Point3d[] | GrowableXYZArray, + params?: Point2d[], + normals?: Vector3d[], + colors?: number[], ): void { if (points instanceof GrowableXYZArray) points = points.getPoint3dArray(); @@ -559,7 +583,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { } else { const paramTransform = this.getUVTransformForTriangleFacet(points[0], points[1], points[2]); if (paramTransform === undefined) { - param0 = param1 = param2 = param3 = Point2d.createZero(); + param0 = + param1 = + param2 = + param3 = + Point2d.createZero(); } else { param0 = Point2d.createFrom(paramTransform.multiplyPoint3d(points[0])); param1 = Point2d.createFrom(paramTransform.multiplyPoint3d(points[1])); @@ -663,7 +691,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { * * This means ccw/cw ordered vertices v[i] should be passed into this function as i=[0,1,3,2]. */ private addIndexedQuadPointIndexes( - indexA0: number, indexA1: number, indexB0: number, indexB1: number, terminate: boolean = true, + indexA0: number, + indexA1: number, + indexB0: number, + indexB1: number, + terminate: boolean = true, ): void { if (this._reversed) { this._polyface.addPointIndex(indexA0); @@ -731,7 +763,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param colors (optional) array of at least three colors. */ public addTriangleFacet( - points: Point3d[] | GrowableXYZArray, params?: Point2d[], normals?: Vector3d[], colors?: number[], + points: Point3d[] | GrowableXYZArray, + params?: Point2d[], + normals?: Vector3d[], + colors?: number[], ): void { if (points.length < 3) return; @@ -774,7 +809,7 @@ export class PolyfaceBuilder extends NullGeometryHandler { idx0 = this._polyface.addNormal(normals[0]); idx1 = this._polyface.addNormal(normals[1]); idx2 = this._polyface.addNormal(normals[2]); - } else { // compute normals + } else { // compute normals const normal = this.getNormalForTriangularFacet(point0, point1, point2); idx0 = this._polyface.addNormal(normal); idx1 = this._polyface.addNormal(normal); @@ -802,7 +837,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * * The added triangle may be reversed based on builder setup. */ private addIndexedTrianglePointIndexes( - indexA: number, indexB: number, indexC: number, terminateFacet: boolean = true, + indexA: number, + indexB: number, + indexC: number, + terminateFacet: boolean = true, ) { if (!this._reversed) { this._polyface.addPointIndex(indexA); @@ -861,9 +899,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { sector.uvIndex = this._polyface.addParam(sector.uv); } private addSectorTriangle(sectorA0: FacetSector, sectorA1: FacetSector, sectorA2: FacetSector): void { - if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) + if ( + sectorA0.xyz.isAlmostEqual(sectorA1.xyz) || sectorA1.xyz.isAlmostEqual(sectorA2.xyz) - || sectorA2.xyz.isAlmostEqual(sectorA0.xyz)) { + || sectorA2.xyz.isAlmostEqual(sectorA0.xyz) + ) { // trivially degenerate triangle; skip!!! } else { if (this._options.needNormals) @@ -874,7 +914,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { } } private addSectorQuadA01B01( - sectorA0: FacetSector, sectorA1: FacetSector, sectorB0: FacetSector, sectorB1: FacetSector, + sectorA0: FacetSector, + sectorA1: FacetSector, + sectorB0: FacetSector, + sectorB1: FacetSector, ): void { if (sectorA0.xyz.isAlmostEqual(sectorA1.xyz) && sectorB0.xyz.isAlmostEqual(sectorB1.xyz)) { // ignore null quad @@ -894,7 +937,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { * * Surface normals are computed from (a) curve tangents in the linestrings and (b) rule line between linestrings. */ public addBetweenLineStringsWithRuleEdgeNormals( - lineStringA: LineString3d, vA: number, lineStringB: LineString3d, vB: number, addClosure: boolean = false, + lineStringA: LineString3d, + vA: number, + lineStringB: LineString3d, + vB: number, + addClosure: boolean = false, ): void { const pointA = lineStringA.packedPoints; const pointB = lineStringB.packedPoints; @@ -959,47 +1006,69 @@ export class PolyfaceBuilder extends NullGeometryHandler { if (this.options.shouldTriangulate) { if (distinctIndices(pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i))) { this.addIndexedTrianglePointIndexes( - pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), pointB.atUncheckedIndex(i), false, + pointA.atUncheckedIndex(i - 1), + pointA.atUncheckedIndex(i), + pointB.atUncheckedIndex(i), + false, ); if (normalA && normalB) this.addIndexedTriangleNormalIndexes( - normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), + normalA.atUncheckedIndex(i - 1), + normalA.atUncheckedIndex(i), + normalB.atUncheckedIndex(i - 1), ); if (paramA && paramB) this.addIndexedTriangleParamIndexes( - paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), + paramA.atUncheckedIndex(i - 1), + paramA.atUncheckedIndex(i), + paramB.atUncheckedIndex(i - 1), ); } if (distinctIndices(pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i - 1))) { this.addIndexedTrianglePointIndexes( - pointA.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), pointB.atUncheckedIndex(i - 1), false, + pointA.atUncheckedIndex(i - 1), + pointB.atUncheckedIndex(i), + pointB.atUncheckedIndex(i - 1), + false, ); if (normalA && normalB) this.addIndexedTriangleNormalIndexes( - normalA.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), normalB.atUncheckedIndex(i - 1), + normalA.atUncheckedIndex(i - 1), + normalB.atUncheckedIndex(i), + normalB.atUncheckedIndex(i - 1), ); if (paramA && paramB) this.addIndexedTriangleParamIndexes( - paramA.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), paramB.atUncheckedIndex(i - 1), + paramA.atUncheckedIndex(i - 1), + paramB.atUncheckedIndex(i), + paramB.atUncheckedIndex(i - 1), ); } } else { - if (pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || - pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i)) { + if ( + pointA.atUncheckedIndex(i - 1) !== pointA.atUncheckedIndex(i) || + pointB.atUncheckedIndex(i - 1) !== pointB.atUncheckedIndex(i) + ) { this.addIndexedQuadPointIndexes( - pointA.atUncheckedIndex(i - 1), pointA.atUncheckedIndex(i), - pointB.atUncheckedIndex(i - 1), pointB.atUncheckedIndex(i), + pointA.atUncheckedIndex(i - 1), + pointA.atUncheckedIndex(i), + pointB.atUncheckedIndex(i - 1), + pointB.atUncheckedIndex(i), false, ); if (normalA && normalB) this.addIndexedQuadNormalIndexes( - normalA.atUncheckedIndex(i - 1), normalA.atUncheckedIndex(i), - normalB.atUncheckedIndex(i - 1), normalB.atUncheckedIndex(i), + normalA.atUncheckedIndex(i - 1), + normalA.atUncheckedIndex(i), + normalB.atUncheckedIndex(i - 1), + normalB.atUncheckedIndex(i), ); if (paramA && paramB) this.addIndexedQuadParamIndexes( - paramA.atUncheckedIndex(i - 1), paramA.atUncheckedIndex(i), - paramB.atUncheckedIndex(i - 1), paramB.atUncheckedIndex(i), + paramA.atUncheckedIndex(i - 1), + paramA.atUncheckedIndex(i), + paramB.atUncheckedIndex(i - 1), + paramB.atUncheckedIndex(i), ); } } @@ -1012,7 +1081,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * * addIndexedQuad is free to apply reversal or triangulation options. */ public addBetweenTransformedLineStrings( - curves: AnyCurve, transformA: Transform, transformB: Transform, addClosure: boolean = false, + curves: AnyCurve, + transformA: Transform, + transformB: Transform, + addClosure: boolean = false, ): void { if (curves instanceof LineString3d) { const pointA = curves.points; @@ -1035,10 +1107,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { } else { const children = curves.children; // just send the children individually; final compress will fix things?? - if (children) + if (children) { for (const c of children) { this.addBetweenTransformedLineStrings(c as AnyCurve, transformA, transformB); } + } } } private addBetweenStrokeSetPair(dataA: AnyCurve, vA: number, dataB: AnyCurve, vB: number) { @@ -1075,7 +1148,8 @@ export class PolyfaceBuilder extends NullGeometryHandler { const lineStringB = cone.strokeConstantVSection(1.0, strokeCount, this._options); if (this._options) { const vDistanceRange = GrowableXYZArray.distanceRangeBetweenCorrespondingPoints( - lineStringA.packedPoints, lineStringB.packedPoints, + lineStringA.packedPoints, + lineStringB.packedPoints, ); axisStrokeCount = this._options.applyMaxEdgeLength(1, vDistanceRange.low); } @@ -1098,7 +1172,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { const thetaFraction = surface.getThetaFraction(); let numU = Geometry.clamp(Geometry.resolveNumber(phiStrokeCount, 8), 4, 64); let numV = Geometry.clamp( - Geometry.resolveNumber(thetaStrokeCount, Math.ceil(16 * thetaFraction)), 2, 64); + Geometry.resolveNumber(thetaStrokeCount, Math.ceil(16 * thetaFraction)), + 2, + 64, + ); if (this._options) { numU = this._options.applyTolerancesToArc(surface.getMinorRadius()); numV = this._options.applyTolerancesToArc(surface.getMajorRadius(), surface.getSweepAngle().radians); @@ -1116,9 +1193,18 @@ export class PolyfaceBuilder extends NullGeometryHandler { const r1 = majorRadius + minorRadius; const z0 = -minorRadius; const cap0ToLocal = Transform.createRowValues( - a, 0, 0, r0, - 0, 0, -1, 0, - 0, a, 0, z0, + a, + 0, + 0, + r0, + 0, + 0, + -1, + 0, + 0, + a, + 0, + z0, ); const cap0ToWorld = centerFrame.multiplyTransformTransform(cap0ToLocal); const worldToCap0 = cap0ToWorld.inverse(); @@ -1131,9 +1217,18 @@ export class PolyfaceBuilder extends NullGeometryHandler { const cc = Math.cos(thetaRadians); const ss = Math.sin(thetaRadians); const cap1ToLocal = Transform.createRowValues( - -cc * a, 0, -ss, r1 * cc, - -ss * a, 0, cc, r1 * ss, - 0, a, 0, z0, + -cc * a, + 0, + -ss, + r1 * cc, + -ss * a, + 0, + cc, + r1 * ss, + 0, + a, + 0, + z0, ); const cap1ToWorld = centerFrame.multiplyTransformTransform(cap1ToLocal); const worldToCap1 = cap1ToWorld.inverse(); @@ -1221,10 +1316,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { data.computeStrokeCountForOptions(options); } else if (data instanceof CurveCollection) { const children = data.children; - if (children) + if (children) { for (const child of children) // eslint-disable-next-line deprecation/deprecation this.applyStrokeCountsToCurvePrimitives(child); + } } } private addBetweenStrokeSetsWithRuledNormals(stroke0: AnyCurve, stroke1: AnyCurve, numVEdge: number): void { @@ -1295,7 +1391,11 @@ export class PolyfaceBuilder extends NullGeometryHandler { } } private addBetweenRotatedStrokeSets( - stroke0: AnyCurve, transformA: Transform, vA: number, transformB: Transform, vB: number, + stroke0: AnyCurve, + transformA: Transform, + vA: number, + transformB: Transform, + vB: number, ): void { if (stroke0 instanceof LineString3d) { const strokeA = stroke0.cloneTransformed(transformA); @@ -1349,8 +1449,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { stroke1 = contours[i].curves.cloneStroked(); if (i > 0 && stroke0 && stroke1) { const distanceRange = Range1d.createNull(); - if (StrokeCountSection.extendDistanceRangeBetweenStrokes(stroke0, stroke1, distanceRange) - && !distanceRange.isNull) { + if ( + StrokeCountSection.extendDistanceRangeBetweenStrokes(stroke0, stroke1, distanceRange) + && !distanceRange.isNull + ) { const numVEdge = this._options.applyMaxEdgeLength(1, distanceRange.high); this.addBetweenStrokeSetsWithRuledNormals(stroke0, stroke1, numVEdge); } @@ -1372,7 +1474,9 @@ export class PolyfaceBuilder extends NullGeometryHandler { if (Geometry.isOdd(numStrokeTheta)) numStrokeTheta += 1; const numStrokePhi = Geometry.clampToStartEnd( - Math.abs(numStrokeTheta * sphere.latitudeSweepFraction), 1, Math.ceil(numStrokeTheta * 0.5), + Math.abs(numStrokeTheta * sphere.latitudeSweepFraction), + 1, + Math.ceil(numStrokeTheta * 0.5), ); const lineStringA = sphere.strokeConstantVSection(0.0, numStrokeTheta, this._options); if (sphere.capped && !Geometry.isSmallMetricDistance(lineStringA.quickLength())) { @@ -1404,19 +1508,35 @@ export class PolyfaceBuilder extends NullGeometryHandler { const uParamRange = Segment1d.create(0, xLength); const vParamRange = Segment1d.create(0, zLength); this.addUVGridBody( - BilinearPatch.create(corners[0], corners[1], corners[4], corners[5]), numX, numZ, uParamRange, vParamRange, + BilinearPatch.create(corners[0], corners[1], corners[4], corners[5]), + numX, + numZ, + uParamRange, + vParamRange, ); uParamRange.shift(xLength); this.addUVGridBody( - BilinearPatch.create(corners[1], corners[3], corners[5], corners[7]), numY, numZ, uParamRange, vParamRange, + BilinearPatch.create(corners[1], corners[3], corners[5], corners[7]), + numY, + numZ, + uParamRange, + vParamRange, ); uParamRange.shift(yLength); this.addUVGridBody( - BilinearPatch.create(corners[3], corners[2], corners[7], corners[6]), numX, numZ, uParamRange, vParamRange, + BilinearPatch.create(corners[3], corners[2], corners[7], corners[6]), + numX, + numZ, + uParamRange, + vParamRange, ); uParamRange.shift(xLength); this.addUVGridBody( - BilinearPatch.create(corners[2], corners[0], corners[6], corners[4]), numY, numZ, uParamRange, vParamRange, + BilinearPatch.create(corners[2], corners[0], corners[6], corners[4]), + numY, + numZ, + uParamRange, + vParamRange, ); // finally end that wraparound face this.endFace(); @@ -1424,13 +1544,21 @@ export class PolyfaceBuilder extends NullGeometryHandler { uParamRange.set(0.0, xLength); vParamRange.set(0.0, yLength); this.addUVGridBody( - BilinearPatch.create(corners[4], corners[5], corners[6], corners[7]), numX, numY, uParamRange, vParamRange, + BilinearPatch.create(corners[4], corners[5], corners[6], corners[7]), + numX, + numY, + uParamRange, + vParamRange, ); this.endFace(); uParamRange.set(0.0, xLength); vParamRange.set(0.0, yLength); this.addUVGridBody( - BilinearPatch.create(corners[2], corners[3], corners[0], corners[1]), numX, numY, uParamRange, vParamRange, + BilinearPatch.create(corners[2], corners[3], corners[0], corners[1]), + numX, + numY, + uParamRange, + vParamRange, ); this.endFace(); } @@ -1591,7 +1719,7 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param visitor data for the currently visited facet. * @param indices local indices into the visitor data arrays. * @returns whether the data was added successfully. Encountering an invalid index returns false. - */ + */ public addFacetFromIndexedVisitor(visitor: PolyfaceVisitor, indices: number[]): boolean { if (indices.length > visitor.pointIndex.length) return false; @@ -1725,7 +1853,8 @@ export class PolyfaceBuilder extends NullGeometryHandler { this._polyface.terminateFacet(); } return true; - }); + }, + ); } /** * Add a graph's faces to the builder. @@ -1810,7 +1939,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param endFace if true, call this.endFace after adding all the facets. */ public addCoordinateFacets( - pointArray: Point3d[][], paramArray?: Point2d[][], normalArray?: Vector3d[][], endFace: boolean = false, + pointArray: Point3d[][], + paramArray?: Point2d[][], + normalArray?: Vector3d[][], + endFace: boolean = false, ): void { for (let i = 0; i < pointArray.length; i++) { const params = paramArray ? paramArray[i] : undefined; @@ -1891,33 +2023,44 @@ export class PolyfaceBuilder extends NullGeometryHandler { for (let u = 0; u < numU; u++) { if (!this._options.shouldTriangulate) { this.addIndexedQuadPointIndexes( - xyzIndex0.atUncheckedIndex(u), xyzIndex0.atUncheckedIndex(u + 1), - xyzIndex1.atUncheckedIndex(u), xyzIndex1.atUncheckedIndex(u + 1), + xyzIndex0.atUncheckedIndex(u), + xyzIndex0.atUncheckedIndex(u + 1), + xyzIndex1.atUncheckedIndex(u), + xyzIndex1.atUncheckedIndex(u + 1), false, ); if (needNormals) this.addIndexedQuadNormalIndexes( - normalIndex0!.atUncheckedIndex(u), normalIndex0!.atUncheckedIndex(u + 1), - normalIndex1!.atUncheckedIndex(u), normalIndex1!.atUncheckedIndex(u + 1), + normalIndex0!.atUncheckedIndex(u), + normalIndex0!.atUncheckedIndex(u + 1), + normalIndex1!.atUncheckedIndex(u), + normalIndex1!.atUncheckedIndex(u + 1), ); if (needParams) this.addIndexedQuadParamIndexes( - paramIndex0!.atUncheckedIndex(u), paramIndex0!.atUncheckedIndex(u + 1), - paramIndex1!.atUncheckedIndex(u), paramIndex1!.atUncheckedIndex(u + 1), + paramIndex0!.atUncheckedIndex(u), + paramIndex0!.atUncheckedIndex(u + 1), + paramIndex1!.atUncheckedIndex(u), + paramIndex1!.atUncheckedIndex(u + 1), ); this._polyface.terminateFacet(); } else { this.addIndexedTrianglePointIndexes( - xyzIndex0.atUncheckedIndex(u), xyzIndex0.atUncheckedIndex(u + 1), - xyzIndex1.atUncheckedIndex(u), false); + xyzIndex0.atUncheckedIndex(u), + xyzIndex0.atUncheckedIndex(u + 1), + xyzIndex1.atUncheckedIndex(u), + false, + ); if (needNormals) this.addIndexedTriangleNormalIndexes( - normalIndex0!.atUncheckedIndex(u), normalIndex0!.atUncheckedIndex(u + 1), + normalIndex0!.atUncheckedIndex(u), + normalIndex0!.atUncheckedIndex(u + 1), normalIndex1!.atUncheckedIndex(u), ); if (needParams) this.addIndexedTriangleParamIndexes( - paramIndex0!.atUncheckedIndex(u), paramIndex0!.atUncheckedIndex(u + 1), + paramIndex0!.atUncheckedIndex(u), + paramIndex0!.atUncheckedIndex(u + 1), paramIndex1!.atUncheckedIndex(u), ); this._polyface.terminateFacet(); @@ -1943,11 +2086,17 @@ export class PolyfaceBuilder extends NullGeometryHandler { } } } - indexSwap = xyzIndex1; xyzIndex1 = xyzIndex0; xyzIndex0 = indexSwap; + indexSwap = xyzIndex1; + xyzIndex1 = xyzIndex0; + xyzIndex0 = indexSwap; if (needParams) - indexSwap = paramIndex1; paramIndex1 = paramIndex0; paramIndex0 = indexSwap; + indexSwap = paramIndex1; + paramIndex1 = paramIndex0; + paramIndex0 = indexSwap; if (needNormals) - indexSwap = normalIndex1; normalIndex1 = normalIndex0; normalIndex0 = indexSwap; + indexSwap = normalIndex1; + normalIndex1 = normalIndex0; + normalIndex0 = indexSwap; } xyzIndex0.clear(); xyzIndex1.clear(); @@ -1982,17 +2131,22 @@ export class PolyfaceBuilder extends NullGeometryHandler { * @param pointsB points of second linestring. */ public addGreedyTriangulationBetweenLineStrings( - pointsA: Point3d[] | LineString3d | IndexedXYZCollection, pointsB: Point3d[] | LineString3d | IndexedXYZCollection, + pointsA: Point3d[] | LineString3d | IndexedXYZCollection, + pointsB: Point3d[] | LineString3d | IndexedXYZCollection, ): void { const context = GreedyTriangulationBetweenLineStrings.createContext(); context.emitTriangles( resolveToIndexedXYZCollectionOrCarrier(pointsA), resolveToIndexedXYZCollectionOrCarrier(pointsB), - (triangle: BarycentricTriangle) => { this.addTriangleFacet(triangle.points); }, + (triangle: BarycentricTriangle) => { + this.addTriangleFacet(triangle.points); + }, ); } private addMiteredPipesFromPoints( - centerline: IndexedXYZCollection, sectionData: number | XAndY | Arc3d, numFacetAround: number = 12, + centerline: IndexedXYZCollection, + sectionData: number | XAndY | Arc3d, + numFacetAround: number = 12, ): void { const sections = CurveFactory.createMiteredPipeSections(centerline, sectionData); const pointA0 = Point3d.create(); @@ -2046,7 +2200,8 @@ export class PolyfaceBuilder extends NullGeometryHandler { } /** Return the polyface index array indices corresponding to the given edge, or `undefined` if error. */ private getEdgeIndices(edge: SortableEdge): { edgeIndexA: number, edgeIndexB: number } | undefined { - let indexA = -1; let indexB = -1; + let indexA = -1; + let indexB = -1; for (let i = this._polyface.facetIndex0(edge.facetIndex); i < this._polyface.facetIndex1(edge.facetIndex); ++i) { if (edge.vertexIndexA === this._polyface.data.pointIndex[i]) indexA = i; @@ -2059,7 +2214,7 @@ export class PolyfaceBuilder extends NullGeometryHandler { * Create a side face between base and swept facets along a base boundary edge. * * Assumes numBaseFacets base facets were added to this builder, immediately followed by the same number of swept * facets with opposite orientation (first index not preserved). - */ + */ private addSweptFace(baseBoundaryEdge: SortableEdge, numBaseFacets: number): boolean { const edge = this.getEdgeIndices(baseBoundaryEdge); if (undefined === edge) @@ -2112,14 +2267,18 @@ export class PolyfaceBuilder extends NullGeometryHandler { * be non-manifold, have inconsistently oriented facets, etc. */ public addSweptIndexedPolyface( - source: IndexedPolyface, sweepVector: Vector3d, triangulateSides: boolean = false, + source: IndexedPolyface, + sweepVector: Vector3d, + triangulateSides: boolean = false, ): boolean { let isSimpleSweep = true; const totalProjectedArea = PolyfaceQuery.sumFacetAreas(source, sweepVector); if (Geometry.isAlmostEqualNumber(0.0, totalProjectedArea)) isSimpleSweep = false; const partitionedIndices = PolyfaceQuery.partitionFacetIndicesByVisibilityVector( - source, sweepVector, Angle.createDegrees(1.0e-3), + source, + sweepVector, + Angle.createDegrees(1.0e-3), ); const numForwardFacets = partitionedIndices[0].length; const numBackwardFacets = partitionedIndices[1].length; @@ -2147,9 +2306,10 @@ export class PolyfaceBuilder extends NullGeometryHandler { for (const edgeOrCluster of baseBoundaryEdges) { if (edgeOrCluster instanceof SortableEdge) this.addSweptFace(edgeOrCluster, numBaseFacets); - else if (Array.isArray(edgeOrCluster)) + else if (Array.isArray(edgeOrCluster)) { for (const edge of edgeOrCluster) this.addSweptFace(edge, numBaseFacets); + } } this._options.shouldTriangulate = oldShouldTriangulate; return isSimpleSweep; diff --git a/core/geometry/src/polyface/PolyfaceClip.ts b/core/geometry/src/polyface/PolyfaceClip.ts index 62aa49fa296d..9d9bec1b8917 100644 --- a/core/geometry/src/polyface/PolyfaceClip.ts +++ b/core/geometry/src/polyface/PolyfaceClip.ts @@ -69,7 +69,11 @@ export class ClippedPolyfaceBuilders { * @param buildSideFaces whether to add side facets to active builders (default false) */ public static create(keepInside: boolean = true, keepOutside: boolean = false, buildSideFaces: boolean = false) { - return new ClippedPolyfaceBuilders(keepInside ? PolyfaceBuilder.create() : undefined, keepOutside ? PolyfaceBuilder.create() : undefined, buildSideFaces); + return new ClippedPolyfaceBuilders( + keepInside ? PolyfaceBuilder.create() : undefined, + keepOutside ? PolyfaceBuilder.create() : undefined, + buildSideFaces, + ); } /** @@ -99,14 +103,24 @@ export class PolyfaceClip { * * Return all surviving clip as a new mesh. * * WARNING: The new mesh is "points only" -- parameters, normals, etc are not interpolated */ - public static clipPolyfaceClipPlaneWithClosureFace(polyface: Polyface, clipper: ClipPlane, insideClip: boolean = true, buildClosureFaces: boolean = true): IndexedPolyface { + public static clipPolyfaceClipPlaneWithClosureFace( + polyface: Polyface, + clipper: ClipPlane, + insideClip: boolean = true, + buildClosureFaces: boolean = true, + ): IndexedPolyface { return this.clipPolyfaceClipPlane(polyface, clipper, insideClip, buildClosureFaces); } /** Clip each facet of polyface to the ClipPlane. * * Return all surviving clip as a new mesh. * * WARNING: The new mesh is "points only" -- parameters, normals, etc are not interpolated */ - public static clipPolyfaceClipPlane(polyface: Polyface, clipper: ClipPlane, insideClip: boolean = true, buildClosureFaces: boolean = false): IndexedPolyface { + public static clipPolyfaceClipPlane( + polyface: Polyface, + clipper: ClipPlane, + insideClip: boolean = true, + buildClosureFaces: boolean = false, + ): IndexedPolyface { const builders = ClippedPolyfaceBuilders.create(insideClip, !insideClip, buildClosureFaces); this.clipPolyfaceInsideOutside(polyface, clipper, builders); return builders.claimPolyface(insideClip ? 0 : 1, true)!; @@ -135,7 +149,12 @@ export class PolyfaceClip { * * 0 outputs all shards -- this may have many interior edges. * * 1 stitches shards together to get cleaner facets. */ - public static clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders(polyface: Polyface | PolyfaceVisitor, allClippers: UnionOfConvexClipPlaneSets, destination: ClippedPolyfaceBuilders, outputSelector: number = 1) { + public static clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders( + polyface: Polyface | PolyfaceVisitor, + allClippers: UnionOfConvexClipPlaneSets, + destination: ClippedPolyfaceBuilders, + outputSelector: number = 1, + ) { if (polyface instanceof Polyface) { this.clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders(polyface.createVisitor(0), allClippers, destination, outputSelector); return; @@ -161,7 +180,7 @@ export class PolyfaceClip { outsideShards.push(candidate.points); } else { const clipper = allClippers.convexSets[convexSetIndex]; - outsideParts.length = 0; // NO NO -- why isn't it empty from prior step cleanup? + outsideParts.length = 0; // NO NO -- why isn't it empty from prior step cleanup? const insidePart = clipper.clipInsidePushOutside(candidate.points, outsideParts, cache); if (insidePart) { if (insidePart.length > 2) @@ -186,8 +205,10 @@ export class PolyfaceClip { } else { const localToWorld = FrameBuilder.createRightHandedFrame(undefined, visitor.point); let worldToLocal: Transform | undefined; - if (outputSelector === 1 && localToWorld !== undefined - && undefined !== (worldToLocal = localToWorld.inverse())) { + if ( + outputSelector === 1 && localToWorld !== undefined + && undefined !== (worldToLocal = localToWorld.inverse()) + ) { this.cleanupAndAddRegion(builderA, insideShards, worldToLocal, localToWorld); this.cleanupAndAddRegion(builderB, outsideShards, worldToLocal, localToWorld); } else { @@ -220,8 +241,12 @@ export class PolyfaceClip { } } // WARNING: shards are transformed into local system, not reverted!!! - private static cleanupAndAddRegion(builder: PolyfaceBuilder | undefined, shards: GrowableXYZArray[], - worldToLocal: Transform | undefined, localToWorld: Transform | undefined) { + private static cleanupAndAddRegion( + builder: PolyfaceBuilder | undefined, + shards: GrowableXYZArray[], + worldToLocal: Transform | undefined, + localToWorld: Transform | undefined, + ) { if (builder !== undefined && shards.length > 0) { if (worldToLocal) GrowableXYZArray.multiplyTransformInPlace(worldToLocal, shards); @@ -234,7 +259,7 @@ export class PolyfaceClip { if (localFacets) { // prefer to add non-convex facets builder.addIndexedPolyface(localFacets, false, localToWorld); - } else { // failsafe; we don't expect to get here + } else { // failsafe; we don't expect to get here if (localToWorld) outsidePieces.tryTransformInPlace(localToWorld); this.addRegion(builder, outsidePieces); // possibly non-convex! @@ -242,14 +267,22 @@ export class PolyfaceClip { } } } - private static addPolygonToBuilderAndDropToCache(polygon: GrowableXYZArray | undefined, builder: PolyfaceBuilder | undefined, cache: GrowableXYZArrayCache) { + private static addPolygonToBuilderAndDropToCache( + polygon: GrowableXYZArray | undefined, + builder: PolyfaceBuilder | undefined, + cache: GrowableXYZArrayCache, + ) { if (polygon) { if (builder) builder.addPolygonGrowableXYZArray(polygon); cache.dropToCache(polygon); } } - private static addPolygonArrayToBuilderAndDropToCache(polygonArray: GrowableXYZArray[], builder: PolyfaceBuilder | undefined, cache: GrowableXYZArrayCache) { + private static addPolygonArrayToBuilderAndDropToCache( + polygonArray: GrowableXYZArray[], + builder: PolyfaceBuilder | undefined, + cache: GrowableXYZArrayCache, + ) { let polygon; while ((polygon = polygonArray.pop()) !== undefined) { this.addPolygonToBuilderAndDropToCache(polygon, builder, cache); @@ -269,10 +302,10 @@ export class PolyfaceClip { } /** Clip each facet of polyface to the the clippers. - * * Add inside, outside fragments to builderA, builderB - * * This does not consider params, normals, colors. Just points. - * @internal - */ + * * Add inside, outside fragments to builderA, builderB + * * This does not consider params, normals, colors. Just points. + * @internal + */ public static clipPolyfaceConvexClipPlaneSetToBuilders(polyface: Polyface, clipper: ConvexClipPlaneSet, destination: ClippedPolyfaceBuilders) { const builderA = destination.builderA; const builderB = destination.builderB; @@ -294,14 +327,17 @@ export class PolyfaceClip { this.buildClosureFacesForConvexSet(visitor, clipper, destination, cache); } /** - * * @param visitor visitor for all facets of interest (entire polyface) * @param clipper ConvexClipPlaneSet to apply * @param destination builders to receive inside, outside parts * @param cache GrowableArray cache. */ - private static buildClosureFacesForConvexSet(visitor: PolyfaceVisitor, clipper: ConvexClipPlaneSet, destination: ClippedPolyfaceBuilders, - cache: GrowableXYZArrayCache) { + private static buildClosureFacesForConvexSet( + visitor: PolyfaceVisitor, + clipper: ConvexClipPlaneSet, + destination: ClippedPolyfaceBuilders, + cache: GrowableXYZArrayCache, + ) { if (destination.buildClosureFaces) { const chainContexts = this.createChainContextsForConvexClipPlaneSet(clipper); const workPoints = cache.grabFromCache(); @@ -324,14 +360,17 @@ export class PolyfaceClip { } /** - * * @param visitor visitor for all facets of interest (entire polyface) * @param clipper ConvexClipPlaneSet to apply * @param destination builders to receive inside, outside parts * @param cache GrowableArray cache. */ - private static buildClosureFacesForPlane(visitor: PolyfaceVisitor, plane: PlaneAltitudeEvaluator, destination: ClippedPolyfaceBuilders, - cache: GrowableXYZArrayCache) { + private static buildClosureFacesForPlane( + visitor: PolyfaceVisitor, + plane: PlaneAltitudeEvaluator, + destination: ClippedPolyfaceBuilders, + cache: GrowableXYZArrayCache, + ) { if (destination.buildClosureFaces) { const chainContext = ChainMergeContext.create(); chainContext.plane = plane; @@ -356,7 +395,12 @@ export class PolyfaceClip { * * Add all the triangles to both builders * * reversed in builderB. */ - private static addClippedContour(contour: SweepContour, clipper: ConvexClipPlaneSet | undefined, destination: ClippedPolyfaceBuilders, cache: GrowableXYZArrayCache) { + private static addClippedContour( + contour: SweepContour, + clipper: ConvexClipPlaneSet | undefined, + destination: ClippedPolyfaceBuilders, + cache: GrowableXYZArrayCache, + ) { const polygonA = cache.grabFromCache(); const polygonB = cache.grabFromCache(); if (destination.builderB) @@ -456,8 +500,12 @@ export class PolyfaceClip { * * WARNING: The new mesh is "points only". * * outputSelect applies only for UnionOfConvexClipPlaneSets -- see [[PolyfaceClip.clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders]] */ - public static clipPolyfaceInsideOutside(polyface: Polyface, clipper: ClipPlane | ConvexClipPlaneSet | UnionOfConvexClipPlaneSets, destination: ClippedPolyfaceBuilders, - outputSelect: number = 0) { + public static clipPolyfaceInsideOutside( + polyface: Polyface, + clipper: ClipPlane | ConvexClipPlaneSet | UnionOfConvexClipPlaneSets, + destination: ClippedPolyfaceBuilders, + outputSelect: number = 0, + ) { if (clipper instanceof ClipPlane) { this.clipPolyfaceClipPlaneToBuilders(polyface, clipper, destination); } else if (clipper instanceof ConvexClipPlaneSet) { @@ -467,10 +515,10 @@ export class PolyfaceClip { } } /** Clip each facet of polyface to the ClipPlane or ConvexClipPlaneSet - * * This method parses the variant input types and calls a more specific method. - * * To get both inside and outside parts, use clipPolyfaceInsideOutside - * * WARNING: The new mesh is "points only". - */ + * * This method parses the variant input types and calls a more specific method. + * * To get both inside and outside parts, use clipPolyfaceInsideOutside + * * WARNING: The new mesh is "points only". + */ public static clipPolyface(polyface: Polyface, clipper: ClipPlane | ConvexClipPlaneSet): Polyface | undefined { if (clipper instanceof ClipPlane) return this.clipPolyfaceClipPlane(polyface, clipper); @@ -488,7 +536,12 @@ export class PolyfaceClip { * @param options how to stroke the region boundary * @returns clipped facets. No other mesh data but vertices appear in output. */ - public static drapeRegion(mesh: Polyface | PolyfaceVisitor, region: AnyRegion, sweepVector?: Vector3d, options?: StrokeOptions): IndexedPolyface | undefined { + public static drapeRegion( + mesh: Polyface | PolyfaceVisitor, + region: AnyRegion, + sweepVector?: Vector3d, + options?: StrokeOptions, + ): IndexedPolyface | undefined { if (mesh instanceof Polyface) return this.drapeRegion(mesh.createVisitor(0), region, sweepVector, options); const contour = SweepContour.createForLinearSweep(region); @@ -500,7 +553,7 @@ export class PolyfaceClip { const clipper = contour.sweepToUnionOfConvexClipPlaneSets(sweep, false, false, options); if (!clipper) return undefined; - const builders = ClippedPolyfaceBuilders.create(true); // we want only the facets inside the clipper + const builders = ClippedPolyfaceBuilders.create(true); // we want only the facets inside the clipper this.clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders(mesh, clipper, builders, 1); return builders.claimPolyface(0, true); } @@ -509,8 +562,14 @@ export class PolyfaceClip { * @param chainContext context receiving edges * @param point0 work point * @param point1 work point - */ - private static collectEdgesOnPlane(points: GrowableXYZArray, clipper: ClipPlane, chainContext: ChainMergeContext, point0: Point3d, point1: Point3d) { + */ + private static collectEdgesOnPlane( + points: GrowableXYZArray, + clipper: ClipPlane, + chainContext: ChainMergeContext, + point0: Point3d, + point1: Point3d, + ) { const n = points.length; if (n > 1) { points.getPoint3dAtUncheckedPointIndex(n - 1, point0); @@ -555,9 +614,12 @@ export class PolyfaceClip { * @param visitorB iterator over polyface that acts as a splitter * @param orientUnderMeshDownward if true, the "meshAUnderB" output is oriented with its normals reversed so it can act as the bottom side of a cut-fill pair. */ - public static clipPolyfaceUnderOverConvexPolyfaceIntoBuilders(visitorA: PolyfaceVisitor, visitorB: PolyfaceVisitor, + public static clipPolyfaceUnderOverConvexPolyfaceIntoBuilders( + visitorA: PolyfaceVisitor, + visitorB: PolyfaceVisitor, builderAUnderB: PolyfaceBuilder | undefined, - builderAOverB: PolyfaceBuilder | undefined) { + builderAOverB: PolyfaceBuilder | undefined, + ) { const rangeDataA = PolyfaceQuery.collectRangeLengthData(visitorA); const searchA = RangeSearch.create2dSearcherForRangeLengthData(rangeDataA); if (!searchA) diff --git a/core/geometry/src/polyface/PolyfaceData.ts b/core/geometry/src/polyface/PolyfaceData.ts index 76fc1c7968b9..b0b344007f19 100644 --- a/core/geometry/src/polyface/PolyfaceData.ts +++ b/core/geometry/src/polyface/PolyfaceData.ts @@ -36,7 +36,7 @@ export class PolyfaceData { /** * Relative tolerance used in tests for planar facets. * @internal - */ + */ public static readonly planarityLocalRelTol = 1.0e-13; /** Coordinate data for points in the facets (packed as numbers in a contiguous array). */ public point: GrowableXYZArray; @@ -92,7 +92,10 @@ export class PolyfaceData { * @param twoSided `true` if the facets are to be considered viewable from the back; `false` (default) if not. */ public constructor( - needNormals: boolean = false, needParams: boolean = false, needColors: boolean = false, twoSided: boolean = false, + needNormals: boolean = false, + needParams: boolean = false, + needColors: boolean = false, + twoSided: boolean = false, ) { this.point = new GrowableXYZArray(); this.pointIndex = []; @@ -393,24 +396,30 @@ export class PolyfaceData { this.point.push(Point3d.create()); while (this.pointIndex.length < length) this.pointIndex.push(-1); - if (this.normal) + if (this.normal) { while (this.normal.length < length) this.normal.push(Vector3d.create()); - if (this.normalIndex) + } + if (this.normalIndex) { while (this.normalIndex.length < length) this.normalIndex.push(-1); - if (this.param) + } + if (this.param) { while (this.param.length < length) this.param.push(Point2d.create()); - if (this.paramIndex) + } + if (this.paramIndex) { while (this.paramIndex.length < length) this.paramIndex.push(-1); - if (this.color) + } + if (this.color) { while (this.color.length < length) this.color.push(0); - if (this.colorIndex) + } + if (this.colorIndex) { while (this.colorIndex.length < length) this.colorIndex.push(-1); + } while (this.edgeVisible.length < length) this.edgeVisible.push(false); if (this.auxData) { @@ -458,12 +467,15 @@ export class PolyfaceData { while (this.point.length < length) this.point.push(Point3d.create()); while (this.pointIndex.length < length) this.pointIndex.push(-1); while (this.edgeVisible.length < length) this.edgeVisible.push(false); - if (this.normal) + if (this.normal) { while (this.normal.length < length) this.normal.push(Vector3d.create()); - if (this.param) + } + if (this.param) { while (this.param.length < length) this.param.push(Point2d.create()); - if (this.color) + } + if (this.color) { while (this.color.length < length) this.color.push(0); + } if (this.auxData) { for (const channel of this.auxData.channels) { for (const channelData of channel.data) { @@ -616,13 +628,18 @@ export class PolyfaceData { * `false` to reverse all indices (e.g., facet [1,2,3,4] becomes [4,3,2,1]). */ public static reverseIndicesSingleFacet( - facetIndex: number, facetStartIndex: number[], indices: T[] | undefined, preserveStart: boolean, + facetIndex: number, + facetStartIndex: number[], + indices: T[] | undefined, + preserveStart: boolean, ): boolean { if (!indices || indices.length === 0) return true; // empty case if (indices.length > 0) { - if (facetStartIndex[facetStartIndex.length - 1] === indices.length - && facetIndex >= 0 && facetIndex + 1 < facetStartIndex.length) { + if ( + facetStartIndex[facetStartIndex.length - 1] === indices.length + && facetIndex >= 0 && facetIndex + 1 < facetStartIndex.length + ) { let index0 = facetStartIndex[facetIndex]; let index1 = facetStartIndex[facetIndex + 1]; if (preserveStart) { // leave "index0" as is so reversed facet starts at same vertex @@ -655,7 +672,7 @@ export class PolyfaceData { * * The indices for facet k are `facetStartIndex[k]` up to (but not including) `facetStartIndex[k + 1]`. * * This implies `facetStartIndex[k + 1]` is both the upper limit of facet k's indices, and the start index of facet k+1. * * For example, passing an IndexedPolyface's _facetStart array into this method reverses every facet. - */ + */ public reverseIndices(facetStartIndex?: number[]): void { if (facetStartIndex && PolyfaceData.isValidFacetStartIndexArray(facetStartIndex)) { PolyfaceData.reverseIndices(facetStartIndex, this.pointIndex, true); diff --git a/core/geometry/src/polyface/PolyfaceQuery.ts b/core/geometry/src/polyface/PolyfaceQuery.ts index 53e9c05f4e8e..8d3e6f5dd7c9 100644 --- a/core/geometry/src/polyface/PolyfaceQuery.ts +++ b/core/geometry/src/polyface/PolyfaceQuery.ts @@ -44,7 +44,11 @@ import { HalfEdgeGraphSearch, HalfEdgeMaskTester } from "../topology/HalfEdgeGra import { HalfEdgeGraphMerge } from "../topology/Merging"; import { SpacePolygonTriangulation } from "../topology/SpaceTriangulation"; import { - ConvexFacetLocationDetail, FacetIntersectOptions, FacetLocationDetail, NonConvexFacetLocationDetail, TriangularFacetLocationDetail, + ConvexFacetLocationDetail, + FacetIntersectOptions, + FacetLocationDetail, + NonConvexFacetLocationDetail, + TriangularFacetLocationDetail, } from "./FacetLocationDetail"; import { FacetOrientationFixup } from "./FacetOrientation"; import { IndexedEdgeMatcher, SortableEdge, SortableEdgeCluster } from "./IndexedEdgeMatcher"; @@ -134,7 +138,7 @@ export class SweepLineStringToFacetsOptions { * * A facet whose facet normal has a positive, zero, or negative dot product with `vectorToEye` is classified * as forward, side, or rear, respectively. * * `undefined` facet normal returns `false`. - */ + */ public collectFromThisFacetNormal(facetNormal: Vector3d | undefined): boolean { if (facetNormal === undefined) return false; @@ -237,7 +241,9 @@ export class OffsetMeshOptions { if (mySmoothAccumulatedRadiansBetweenNormals.degrees < 15.0) mySmoothAccumulatedRadiansBetweenNormals.setDegrees(15.0); return new OffsetMeshOptions( - mySmoothSingleRadiansBetweenNormals, mySmoothAccumulatedRadiansBetweenNormals, myChamferTurnAngleBetweenNormals, + mySmoothSingleRadiansBetweenNormals, + mySmoothAccumulatedRadiansBetweenNormals, + myChamferTurnAngleBetweenNormals, ); } } @@ -282,8 +288,13 @@ export enum DuplicateFacetClusterSelector { * @public */ export type AnnounceDrapePanel = ( - linestring: GrowableXYZArray, segmentIndex: number, polyface: Polyface, - facetIndex: number, points: Point3d[], indexAOnFacet: number, indexBOnFacet: number, + linestring: GrowableXYZArray, + segmentIndex: number, + polyface: Polyface, + facetIndex: number, + points: Point3d[], + indexAOnFacet: number, + indexBOnFacet: number, ) => any; /** @@ -366,7 +377,8 @@ export class PolyfaceQuery { * moments with respect to the centroid. */ public static sumVolumeBetweenFacetsAndPlane( - source: Polyface | PolyfaceVisitor, plane: Plane3dByOriginAndUnitNormal, + source: Polyface | PolyfaceVisitor, + plane: Plane3dByOriginAndUnitNormal, ): FacetProjectedVolumeSums { if (source instanceof Polyface) return PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(source.createVisitor(0), plane); @@ -418,10 +430,12 @@ export class PolyfaceQuery { positiveAreaMomentSums.shiftOriginAndSumsToCentroidOfSums(); negativeAreaMomentSums.shiftOriginAndSumsToCentroidOfSums(); const positiveAreaMoments = MomentData.inertiaProductsToPrincipalAxes( - positiveAreaMomentSums.origin, positiveAreaMomentSums.sums, + positiveAreaMomentSums.origin, + positiveAreaMomentSums.sums, ); const negativeAreaMoments = MomentData.inertiaProductsToPrincipalAxes( - negativeAreaMomentSums.origin, negativeAreaMomentSums.sums, + negativeAreaMomentSums.origin, + negativeAreaMomentSums.sums, ); return { volume: signedVolumeSum / 6.0, @@ -540,7 +554,10 @@ export class PolyfaceQuery { const badClusters: SortableEdgeCluster[] = []; const manifoldClusters: SortableEdgeCluster[] = []; edges.sortAndCollectClusters( - manifoldClusters, ignoreBoundaries ? undefined : badClusters, undefined, badClusters, + manifoldClusters, + ignoreBoundaries ? undefined : badClusters, + undefined, + badClusters, ); if (badClusters.length > 0) return -2; @@ -552,10 +569,13 @@ export class PolyfaceQuery { for (const cluster of manifoldClusters) { const sideA = cluster[0]; const sideB = cluster[1]; - if (sideA instanceof SortableEdge && sideB instanceof SortableEdge - && source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector)) { + if ( + sideA instanceof SortableEdge && sideB instanceof SortableEdge + && source.data.point.vectorIndexIndex(sideA.vertexIndexA, sideA.vertexIndexB, edgeVector) + ) { const dihedralAngle = centroidNormal[sideA.facetIndex].direction.signedAngleTo( - centroidNormal[sideB.facetIndex].direction, edgeVector, + centroidNormal[sideB.facetIndex].direction, + edgeVector, ); if (dihedralAngle.isAlmostZero) numPlanar++; @@ -575,20 +595,20 @@ export class PolyfaceQuery { return -2; } /** - * Test for convex volume by dihedral angle tests on all edges. - * * This tests if all dihedral angles of the mesh are positive. - * * In a closed solid, this is a strong test for overall mesh convexity with outward facing normals. - * * See [[dihedralAngleSummary]] for the definition of "dihedral angle". - * * With `ignoreBoundaries` true, this may be a useful test when all the facets are in a single edge-connected - * component, such as a pyramid with no underside. - * * It is not a correct test if there are multiple, disjoint components. - * * Take the above-mentioned pyramid with no underside. - * * Within the same mesh, have a second pyramid placed to the side, still facing upward. - * * The angles will pass the dihedral convexity test, but the composite thing surely is not convex. - * @param source mesh. - * @param ignoreBoundaries if `true` ignore simple boundary edges, i.e., allow unclosed meshes. Default is `false`. - * @returns true if all dihedral angles of the mesh are positive. - */ + * Test for convex volume by dihedral angle tests on all edges. + * * This tests if all dihedral angles of the mesh are positive. + * * In a closed solid, this is a strong test for overall mesh convexity with outward facing normals. + * * See [[dihedralAngleSummary]] for the definition of "dihedral angle". + * * With `ignoreBoundaries` true, this may be a useful test when all the facets are in a single edge-connected + * component, such as a pyramid with no underside. + * * It is not a correct test if there are multiple, disjoint components. + * * Take the above-mentioned pyramid with no underside. + * * Within the same mesh, have a second pyramid placed to the side, still facing upward. + * * The angles will pass the dihedral convexity test, but the composite thing surely is not convex. + * @param source mesh. + * @param ignoreBoundaries if `true` ignore simple boundary edges, i.e., allow unclosed meshes. Default is `false`. + * @returns true if all dihedral angles of the mesh are positive. + */ public static isConvexByDihedralAngleCount(source: Polyface, ignoreBoundaries: boolean = false): boolean { return this.dihedralAngleSummary(source, ignoreBoundaries) > 0; } @@ -599,7 +619,7 @@ export class PolyfaceQuery { * a boundary, but is still properly matched internally. * * Any edge with 3 or more adjacent facets triggers `false` return. * * Any edge with 2 adjacent facets in the same direction triggers a `false` return. - */ + */ public static isPolyfaceManifold(source: Polyface, allowSimpleBoundaries: boolean = false): boolean { const edges = new IndexedEdgeMatcher(); const visitor = source.createVisitor(1); @@ -648,7 +668,8 @@ export class PolyfaceQuery { } } const boundaryEdges: SortableEdgeCluster[] = []; - edges.sortAndCollectClusters(undefined, + edges.sortAndCollectClusters( + undefined, includeTypical ? boundaryEdges : undefined, includeNull ? boundaryEdges : undefined, includeMismatch ? boundaryEdges : undefined, @@ -716,7 +737,7 @@ export class PolyfaceQuery { /** * Load all half edges from a mesh to an IndexedEdgeMatcher. * @param polyface a mesh or a visitor assumed to have numWrap === 1. - */ + */ public static createIndexedEdges(polyface: Polyface | PolyfaceVisitor): IndexedEdgeMatcher { if (polyface instanceof Polyface) return this.createIndexedEdges(polyface.createVisitor(1)); @@ -782,7 +803,7 @@ export class PolyfaceQuery { announce(pointB, pointA, indexB, indexA, pair[1].facetIndex); continue; } - if (face0.perpAngle * face1.perpAngle < 0.0) { // normals straddle plane + if (face0.perpAngle * face1.perpAngle < 0.0) { // normals straddle plane announce(pointA, pointB, indexA, indexB, pair[0].facetIndex); continue; } @@ -854,7 +875,9 @@ export class PolyfaceQuery { public static awaitBlockCount = 0; /** Execute `context.projectToPolygon` until its work estimates accumulate to workLimit. */ private static async continueAnnounceSweepLinestringToConvexPolyfaceXY( - context: SweepLineStringToFacetContext, visitor: PolyfaceVisitor, announce: AnnounceDrapePanel, + context: SweepLineStringToFacetContext, + visitor: PolyfaceVisitor, + announce: AnnounceDrapePanel, ): Promise { let workCount = 0; while ((workCount < this.asyncWorkLimit) && visitor.moveToNextFacet()) { @@ -871,7 +894,9 @@ export class PolyfaceQuery { * @internal */ public static async asyncAnnounceSweepLinestringToConvexPolyfaceXY( - linestringPoints: GrowableXYZArray, polyface: Polyface, announce: AnnounceDrapePanel, + linestringPoints: GrowableXYZArray, + polyface: Polyface, + announce: AnnounceDrapePanel, ): Promise { const context = SweepLineStringToFacetContext.create(linestringPoints); this.awaitBlockCount = 0; @@ -930,7 +955,9 @@ export class PolyfaceQuery { * * Return array of arrays of facet indices. */ public static partitionFacetIndicesByVisibilityVector( - polyface: Polyface | PolyfaceVisitor, vectorToEye: Vector3d, sideAngleTolerance: Angle, + polyface: Polyface | PolyfaceVisitor, + vectorToEye: Vector3d, + sideAngleTolerance: Angle, ): number[][] { if (polyface instanceof Polyface) { return this.partitionFacetIndicesByVisibilityVector(polyface.createVisitor(0), vectorToEye, sideAngleTolerance); @@ -987,7 +1014,8 @@ export class PolyfaceQuery { * * Emit the chains to the `announceChain` callback. */ public static announceBoundaryChainsAsLineString3d( - mesh: Polyface | PolyfaceVisitor, announceChain: (points: LineString3d) => void, + mesh: Polyface | PolyfaceVisitor, + announceChain: (points: LineString3d) => void, ): void { const collector = new MultiChainCollector(Geometry.smallMetricDistance); // no planarity tolerance needed PolyfaceQuery.announceBoundaryEdges( @@ -1008,7 +1036,8 @@ export class PolyfaceQuery { * uses `Geometry.smallAngleRadians`. */ public static cloneWithMaximalPlanarFacets( - mesh: Polyface | PolyfaceVisitor, maxSmoothEdgeAngle?: Angle, + mesh: Polyface | PolyfaceVisitor, + maxSmoothEdgeAngle?: Angle, ): IndexedPolyface { if (mesh instanceof Polyface) return this.cloneWithMaximalPlanarFacets(mesh.createVisitor(0), maxSmoothEdgeAngle); @@ -1018,7 +1047,7 @@ export class PolyfaceQuery { const builder = PolyfaceBuilder.create(); const visitor = mesh; const planarPartitions: number[][] = []; - const partitionNormals: Ray3d[] = []; // average normal in each nontrivial partition + const partitionNormals: Ray3d[] = []; // average normal in each nontrivial partition const normal = Vector3d.createZero(); for (const partition of partitions) { if (partition.length === 1) { @@ -1030,9 +1059,10 @@ export class PolyfaceQuery { if (visitor.moveToReadIndex(partition[0])) visitor.point.getPoint3dAtCheckedPointIndex(0, point0); for (const facetIndex of partition) { - if (visitor.moveToReadIndex(facetIndex)) + if (visitor.moveToReadIndex(facetIndex)) { if (PolygonOps.areaNormalGo(visitor.point, normal)) averageNormal.addInPlace(normal); + } } partitionNormals.push(Ray3d.createCapture(point0, averageNormal)); planarPartitions.push(partition); @@ -1049,11 +1079,16 @@ export class PolyfaceQuery { const fragment = fragmentPolyfaces[i]; const edges: LineSegment3d[] = []; const edgeStrings: Point3d[][] = []; - PolyfaceQuery.announceBoundaryEdges(fragment, + PolyfaceQuery.announceBoundaryEdges( + fragment, (pointA: Point3d, pointB: Point3d, _indexA: number, _indexB: number) => { edges.push(LineSegment3d.create(pointA, pointB)); edgeStrings.push([pointA.clone(), pointB.clone()]); - }, true, false, false); + }, + true, + false, + false, + ); const chains = CurveOps.collectChains(edges, gapTolerance, planarityTolerance); if (chains) { // avoid FrameBuilder: it can flip the normal of a nonconvex facet! @@ -1066,8 +1101,11 @@ export class PolyfaceQuery { const regularize = !(chains instanceof Loop); const graph = HalfEdgeGraphMerge.formGraphFromChains(edgeStrings, regularize, HalfEdgeMask.BOUNDARY_EDGE); if (graph) { - HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, - new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR); + HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( + graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, + ); // this.purgeNullFaces(HalfEdgeMask.EXTERIOR); const polyface1 = PolyfaceBuilder.graphToPolyface(graph); builder.addIndexedPolyface(polyface1, false, localToWorld); @@ -1093,7 +1131,9 @@ export class PolyfaceQuery { * @param unfilledChains optional array to receive the points around holes that were not filled. */ public static fillSimpleHoles( - mesh: Polyface | PolyfaceVisitor, options: HoleFillOptions, unfilledChains?: LineString3d[], + mesh: Polyface | PolyfaceVisitor, + options: HoleFillOptions, + unfilledChains?: LineString3d[], ): IndexedPolyface | undefined { if (mesh instanceof Polyface) return this.fillSimpleHoles(mesh.createVisitor(0), options, unfilledChains); @@ -1101,7 +1141,10 @@ export class PolyfaceQuery { const chains: LineString3d[] = []; PolyfaceQuery.announceBoundaryChainsAsLineString3d( mesh, - (ls: LineString3d) => { ls.reverseInPlace(); chains.push(ls); }, + (ls: LineString3d) => { + ls.reverseInPlace(); + chains.push(ls); + }, ); for (const c of chains) { const points = c.points; @@ -1114,12 +1157,12 @@ export class PolyfaceQuery { rejected = true; else if (options.upVector !== undefined && PolygonOps.sumTriangleAreasPerpendicularToUpVector(points, options.upVector) <= 0.0) rejected = true; - if (!rejected && SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, - (_loop: Point3d[], triangles: Point3d[][]) => { + if ( + !rejected && SpacePolygonTriangulation.triangulateSimplestSpaceLoop(points, (_loop: Point3d[], triangles: Point3d[][]) => { for (const t of triangles) builder.addPolygon(t); - }, - )) { + }) + ) { } else { rejected = true; } @@ -1157,7 +1200,8 @@ export class PolyfaceQuery { } /** Clone facets that pass a filter function. */ public static cloneFiltered( - source: Polyface | PolyfaceVisitor, filter: (visitor: PolyfaceVisitor) => boolean, + source: Polyface | PolyfaceVisitor, + filter: (visitor: PolyfaceVisitor) => boolean, ): IndexedPolyface { if (source instanceof Polyface) { return this.cloneFiltered(source.createVisitor(0), filter); @@ -1209,8 +1253,8 @@ export class PolyfaceQuery { if (i0 < i1) { indices.splice(i0, palLength - 1); // remove entries [i0,i1) } else if (i0 > i1) { - indices.splice(i0); // remove entries [i0,n) - indices.splice(0, i1); // remove entries [0,i1) + indices.splice(i0); // remove entries [i0,n) + indices.splice(0, i1); // remove entries [0,i1) } return true; } @@ -1221,7 +1265,7 @@ export class PolyfaceQuery { source.reset(); while (source.moveToNextFacet()) { const localIndices = [...Array(source.pointIndex.length).keys()]; // 0, 1, ... n-1; - while (removeFirstOddPalindrome(localIndices, source.pointIndex)) { } + while (removeFirstOddPalindrome(localIndices, source.pointIndex)) {} builder.addFacetFromIndexedVisitor(source, localIndices); } return builder.claimPolyface(true); @@ -1278,7 +1322,8 @@ export class PolyfaceQuery { * @return collection of facet index arrays, one array per connected component. */ private static partitionFacetIndicesBySortableEdgeClusters( - edgeClusters: SortableEdgeCluster[], numFacets: number, + edgeClusters: SortableEdgeCluster[], + numFacets: number, ): number[][] { const context = new UnionFindContext(numFacets); for (const cluster of edgeClusters) { @@ -1315,7 +1360,8 @@ export class PolyfaceQuery { * @return collection of facet index arrays, one per connected component. */ public static partitionFacetIndicesByEdgeConnectedComponent( - polyface: Polyface | PolyfaceVisitor, stopAtVisibleEdges: boolean = false, + polyface: Polyface | PolyfaceVisitor, + stopAtVisibleEdges: boolean = false, ): number[][] { if (polyface instanceof Polyface) { return this.partitionFacetIndicesByEdgeConnectedComponent(polyface.createVisitor(0), stopAtVisibleEdges); @@ -1329,7 +1375,6 @@ export class PolyfaceQuery { numFacets++; for (let i = 0; i < numEdges; i++) { if (stopAtVisibleEdges && polyface.edgeVisible[i]) { - } else { matcher.addEdge(polyface.clientPointIndex(i), polyface.clientPointIndex(i + 1), polyface.currentReadIndex()); } @@ -1398,13 +1443,12 @@ export class PolyfaceQuery { const workNormal = Vector3d.createZero(); for (visitor.reset(); visitor.moveToNextFacet();) { if (options.collectFromThisFacetNormal(PolygonOps.areaNormalGo(visitor.point, workNormal))) { - context.processPolygon(visitor.point.getArray(), - (pointA: Point3d, pointB: Point3d) => { - if (chainContext !== undefined) - chainContext.addSegment(pointA, pointB); - else - result.push(LineSegment3d.create(pointA, pointB)); - }); + context.processPolygon(visitor.point.getArray(), (pointA: Point3d, pointB: Point3d) => { + if (chainContext !== undefined) + chainContext.addSegment(pointA, pointB); + else + result.push(LineSegment3d.create(pointA, pointB)); + }); } } if (chainContext !== undefined) { @@ -1471,16 +1515,22 @@ export class PolyfaceQuery { } /** * Find segments (within the linestring) which project to facets. - * * Return collected line segments. - * * This calls [[sweepLineStringToFacets]] with options created by - * `const options = SweepLineStringToFacetsOptions.create(Vector3d.unitZ(), Angle.createSmallAngle(), false, true, true, true);` - * @deprecated in 4.x. Use [[PolyfaceQuery.sweepLineStringToFacets]] to get further options. - */ + * * Return collected line segments. + * * This calls [[sweepLineStringToFacets]] with options created by + * `const options = SweepLineStringToFacetsOptions.create(Vector3d.unitZ(), Angle.createSmallAngle(), false, true, true, true);` + * @deprecated in 4.x. Use [[PolyfaceQuery.sweepLineStringToFacets]] to get further options. + */ public static sweepLinestringToFacetsXYReturnLines( - linestringPoints: GrowableXYZArray, polyface: Polyface, + linestringPoints: GrowableXYZArray, + polyface: Polyface, ): LineSegment3d[] { const options = SweepLineStringToFacetsOptions.create( - Vector3d.unitZ(), Angle.createSmallAngle(), false, true, true, true, + Vector3d.unitZ(), + Angle.createSmallAngle(), + false, + true, + true, + true, ); const result = PolyfaceQuery.sweepLineStringToFacets(linestringPoints, polyface, options); return result as LineSegment3d[]; @@ -1493,10 +1543,16 @@ export class PolyfaceQuery { * @deprecated in 4.x. Use [[PolyfaceQuery.sweepLineStringToFacets]] to get further options. */ public static sweepLinestringToFacetsXYReturnChains( - linestringPoints: GrowableXYZArray, polyface: Polyface, + linestringPoints: GrowableXYZArray, + polyface: Polyface, ): LineString3d[] { const options = SweepLineStringToFacetsOptions.create( - Vector3d.unitZ(), Angle.createSmallAngle(), true, true, true, true, + Vector3d.unitZ(), + Angle.createSmallAngle(), + true, + true, + true, + true, ); const result = PolyfaceQuery.sweepLineStringToFacets(linestringPoints, polyface, options); return result as LineString3d[]; @@ -1511,15 +1567,23 @@ export class PolyfaceQuery { * * Facets are ASSUMED to be convex and planar, and not overlap in the z direction. */ public static async asyncSweepLinestringToFacetsXYReturnChains( - linestringPoints: GrowableXYZArray, polyface: Polyface, + linestringPoints: GrowableXYZArray, + polyface: Polyface, ): Promise { const chainContext = ChainMergeContext.create(); await Promise.resolve( this.asyncAnnounceSweepLinestringToConvexPolyfaceXY( linestringPoints, polyface, - (_linestring: GrowableXYZArray, _segmentIndex: number, _polyface: Polyface, - _facetIndex: number, points: Point3d[], indexA: number, indexB: number) => { + ( + _linestring: GrowableXYZArray, + _segmentIndex: number, + _polyface: Polyface, + _facetIndex: number, + points: Point3d[], + indexA: number, + indexB: number, + ) => { chainContext.addSegment(points[indexA], points[indexB]); }, ), @@ -1575,8 +1639,10 @@ export class PolyfaceQuery { polyface.data.point.getPoint3dAtUncheckedPointIndex(index, spacePoint); const detail = segment.closestPoint(spacePoint, false); if (undefined !== detail) { - if (detail.fraction > 0.0 && detail.fraction < 1.0 && !detail.point.isAlmostEqual(point0) && - !detail.point.isAlmostEqual(point1) && spacePoint.isAlmostEqual(detail.point)) { + if ( + detail.fraction > 0.0 && detail.fraction < 1.0 && !detail.point.isAlmostEqual(point0) && + !detail.point.isAlmostEqual(point1) && spacePoint.isAlmostEqual(detail.point) + ) { if (detailArray === undefined) detailArray = []; detail.a = index; @@ -1593,7 +1659,11 @@ export class PolyfaceQuery { } } builder.addFacetFromGrowableArrays( - newFacetVisitor.point, newFacetVisitor.normal, newFacetVisitor.param, newFacetVisitor.color, newFacetVisitor.edgeVisible, + newFacetVisitor.point, + newFacetVisitor.normal, + newFacetVisitor.param, + newFacetVisitor.color, + newFacetVisitor.edgeVisible, ); } return builder.claimPolyface(); @@ -1623,7 +1693,8 @@ export class PolyfaceQuery { * indices of a cluster of facets with the same vertex indices. */ public static announceDuplicateFacetIndices( - polyface: Polyface, announceCluster: (clusterFacetIndices: number[]) => void, + polyface: Polyface, + announceCluster: (clusterFacetIndices: number[]) => void, ): void { const visitor = polyface.createVisitor(0); // this is to visit the existing facets const facetIndexAndVertexIndices: number[][] = []; @@ -1690,7 +1761,9 @@ export class PolyfaceQuery { * @param clusterSelector indicates whether to copy 0, 1, or all facets in each cluster of duplicate facets. */ public static cloneByFacetDuplication( - source: Polyface, includeSingletons: boolean, clusterSelector: DuplicateFacetClusterSelector, + source: Polyface, + includeSingletons: boolean, + clusterSelector: DuplicateFacetClusterSelector, ): Polyface { const builder = PolyfaceBuilder.create(); const visitor = source.createVisitor(0); @@ -1758,7 +1831,11 @@ export class PolyfaceQuery { } if (newFacetVisitor.point.length > 2) builder.addFacetFromGrowableArrays( - newFacetVisitor.point, newFacetVisitor.normal, newFacetVisitor.param, newFacetVisitor.color, newFacetVisitor.edgeVisible, + newFacetVisitor.point, + newFacetVisitor.normal, + newFacetVisitor.param, + newFacetVisitor.color, + newFacetVisitor.edgeVisible, ); } return builder.claimPolyface(); @@ -1787,7 +1864,10 @@ export class PolyfaceQuery { * @param value visibility value. */ public static setSingleEdgeVisibility( - polyface: IndexedPolyface, facetIndex: number, vertexIndex: number, value: boolean, + polyface: IndexedPolyface, + facetIndex: number, + vertexIndex: number, + value: boolean, ): void { const data = polyface.data; const index0 = polyface.facetIndex0(facetIndex); @@ -1803,7 +1883,9 @@ export class PolyfaceQuery { * @param vertexIndex vertex index (in vertex array) at which the edge starts. */ public static getSingleEdgeVisibility( - polyface: IndexedPolyface, facetIndex: number, vertexIndex: number, + polyface: IndexedPolyface, + facetIndex: number, + vertexIndex: number, ): boolean | undefined { const data = polyface.data; const index0 = polyface.facetIndex0(facetIndex); @@ -1822,7 +1904,9 @@ export class PolyfaceQuery { * @param sharpEdges true to reverse the angle threshold test and return sharp edges; otherwise return smooth edges (default). */ public static collectEdgesByDihedralAngle( - mesh: Polyface | PolyfaceVisitor, maxSmoothEdgeAngle?: Angle, sharpEdges: boolean = false, + mesh: Polyface | PolyfaceVisitor, + maxSmoothEdgeAngle?: Angle, + sharpEdges: boolean = false, ): SortableEdgeCluster[] { if (mesh instanceof Polyface) return this.collectEdgesByDihedralAngle(mesh.createVisitor(1), maxSmoothEdgeAngle, sharpEdges); @@ -1839,8 +1923,10 @@ export class PolyfaceQuery { if (Array.isArray(pair) && pair.length === 2) { const e0 = pair[0]; const e1 = pair[1]; - if (undefined !== PolyfaceQuery.computeFacetUnitNormal(mesh, e0.facetIndex, normal0) - && undefined !== PolyfaceQuery.computeFacetUnitNormal(mesh, e1.facetIndex, normal1)) { + if ( + undefined !== PolyfaceQuery.computeFacetUnitNormal(mesh, e0.facetIndex, normal0) + && undefined !== PolyfaceQuery.computeFacetUnitNormal(mesh, e1.facetIndex, normal1) + ) { const edgeAngle = normal0.smallerUnorientedAngleTo(normal1); if (sharpEdges) { if (edgeAngle.radians > maxSmoothEdgeAngle.radians) @@ -1856,13 +1942,13 @@ export class PolyfaceQuery { } /** * Make paired edges invisible. - * * Find mated pairs among facet edges. - * * Mated pairs have the same vertex indices appearing in opposite order. - * * Mark all non-mated pairs visible. - * * At mated pairs - * * if angle across the edge is larger than `sharpEdgeAngle`, mark visible - * * otherwise mark invisible. - */ + * * Find mated pairs among facet edges. + * * Mated pairs have the same vertex indices appearing in opposite order. + * * Mark all non-mated pairs visible. + * * At mated pairs + * * if angle across the edge is larger than `sharpEdgeAngle`, mark visible + * * otherwise mark invisible. + */ public static markPairedEdgesInvisible(mesh: IndexedPolyface, sharpEdgeAngle?: Angle) { const visitor = mesh.createVisitor(1); const edges = this.createIndexedEdges(visitor); @@ -1878,8 +1964,10 @@ export class PolyfaceQuery { if (Array.isArray(pair) && pair.length === 2) { const e0 = pair[0]; const e1 = pair[1]; - if (undefined !== PolyfaceQuery.computeFacetUnitNormal(visitor, e0.facetIndex, normal0) - && undefined !== PolyfaceQuery.computeFacetUnitNormal(visitor, e1.facetIndex, normal1)) { + if ( + undefined !== PolyfaceQuery.computeFacetUnitNormal(visitor, e0.facetIndex, normal0) + && undefined !== PolyfaceQuery.computeFacetUnitNormal(visitor, e1.facetIndex, normal1) + ) { const edgeAngle = normal0.smallerUnorientedAngleTo(normal1); if (edgeAngle.radians > sharpEdgeAngle.radians) { this.setSingleEdgeVisibility(mesh, e0.facetIndex, e0.vertexIndexA, true); @@ -1895,7 +1983,9 @@ export class PolyfaceQuery { * * Unit normal is computed by `PolygonOps.unitNormal` with the points around the facet. */ public static computeFacetUnitNormal( - visitor: PolyfaceVisitor, facetIndex: number, result?: Vector3d, + visitor: PolyfaceVisitor, + facetIndex: number, + result?: Vector3d, ): Vector3d | undefined { if (!result) result = Vector3d.create(); @@ -1947,16 +2037,16 @@ export class PolyfaceQuery { BuildAverageNormalsContext.buildPerFaceNormals(polyface); } /** - * * At each vertex of the mesh: - * * Find clusters of almost parallel normals. - * * Compute simple average of those normals. - * * Index to the averages. - * * For typical meshes, this correctly clusters adjacent normals. - * * One can imagine a vertex with multiple "smooth cone-like" sets of adjacent facets such that averaging occurs - * among two nonadjacent cones. But this does not seem to be a problem in practice. - * @param polyface polyface to update. - * @param toleranceAngle averaging is done between normals up to this angle. - */ + * * At each vertex of the mesh: + * * Find clusters of almost parallel normals. + * * Compute simple average of those normals. + * * Index to the averages. + * * For typical meshes, this correctly clusters adjacent normals. + * * One can imagine a vertex with multiple "smooth cone-like" sets of adjacent facets such that averaging occurs + * among two nonadjacent cones. But this does not seem to be a problem in practice. + * @param polyface polyface to update. + * @param toleranceAngle averaging is done between normals up to this angle. + */ public static buildAverageNormals(polyface: IndexedPolyface, toleranceAngle: Angle = Angle.createDegrees(31.0)): void { BuildAverageNormalsContext.buildFastAverageNormals(polyface, toleranceAngle); } @@ -1968,7 +2058,9 @@ export class PolyfaceQuery { * @returns shifted mesh. */ public static cloneOffset( - source: IndexedPolyface, signedOffsetDistance: number, offsetOptions: OffsetMeshOptions = OffsetMeshOptions.create(), + source: IndexedPolyface, + signedOffsetDistance: number, + offsetOptions: OffsetMeshOptions = OffsetMeshOptions.create(), ): IndexedPolyface { const strokeOptions = StrokeOptions.createForFacets(); const offsetBuilder = PolyfaceBuilder.create(strokeOptions); @@ -1998,9 +2090,11 @@ export class PolyfaceQuery { * @return detail for the (accepted) intersection with `detail.IsInsideOrOn === true`, or `undefined` if no * (accepted) intersection. * @see PolygonOps.intersectRay3d - */ + */ public static intersectRay3d( - visitor: Polyface | PolyfaceVisitor, ray: Ray3d, options?: FacetIntersectOptions, + visitor: Polyface | PolyfaceVisitor, + ray: Ray3d, + options?: FacetIntersectOptions, ): FacetLocationDetail | undefined { if (visitor instanceof Polyface) return PolyfaceQuery.intersectRay3d(visitor.createVisitor(0), ray, options); @@ -2019,19 +2113,30 @@ export class PolyfaceQuery { const detail3 = this._workTriDetail = tri.intersectRay3d(ray, this._workTriDetail); tri.snapLocationToEdge(detail3, options?.distanceTolerance, options?.parameterTolerance); detail = this._workFacetDetail3 = TriangularFacetLocationDetail.create( - visitor.currentReadIndex(), detail3, this._workFacetDetail3, + visitor.currentReadIndex(), + detail3, + this._workFacetDetail3, ); } else { const detailN = this._workPolyDetail = PolygonOps.intersectRay3d( - vertices, ray, options?.distanceTolerance, this._workPolyDetail, + vertices, + ray, + options?.distanceTolerance, + this._workPolyDetail, ); if (PolygonOps.isConvex(vertices)) detail = this._workFacetDetailC = ConvexFacetLocationDetail.create( - visitor.currentReadIndex(), numEdges, detailN, this._workFacetDetailC, + visitor.currentReadIndex(), + numEdges, + detailN, + this._workFacetDetailC, ); else detail = this._workFacetDetailNC = NonConvexFacetLocationDetail.create( - visitor.currentReadIndex(), numEdges, detailN, this._workFacetDetailNC, + visitor.currentReadIndex(), + numEdges, + detailN, + this._workFacetDetailNC, ); } if (detail.isInsideOrOn) { // set optional caches, process the intersection diff --git a/core/geometry/src/polyface/RangeTree/LineString3dRangeTreeContext.ts b/core/geometry/src/polyface/RangeTree/LineString3dRangeTreeContext.ts index ae5889ebc433..f003b0a6d1b0 100644 --- a/core/geometry/src/polyface/RangeTree/LineString3dRangeTreeContext.ts +++ b/core/geometry/src/polyface/RangeTree/LineString3dRangeTreeContext.ts @@ -13,7 +13,8 @@ import { Point3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { RangeTreeNode, RangeTreeOps } from "./RangeTreeNode"; import { - SingleTreeSearchHandlerForClosestPointOnLineString3d, TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach, + SingleTreeSearchHandlerForClosestPointOnLineString3d, + TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach, } from "./RangeTreeSearchHandlers"; /** @@ -54,12 +55,20 @@ export class LineString3dRangeTreeContext { * @param maxChildPerNode maximum children per range tree node (default 4) * @param maxAppDataPerLeaf maximum segment indices per leaf node (default 4) */ - public static createCapture(points: Point3d[] | LineString3d, maxChildPerNode: number = 4, maxAppDataPerLeaf: number = 4): LineString3dRangeTreeContext | undefined { + public static createCapture( + points: Point3d[] | LineString3d, + maxChildPerNode: number = 4, + maxAppDataPerLeaf: number = 4, + ): LineString3dRangeTreeContext | undefined { const linestring = points instanceof LineString3d ? points : LineString3d.createPoints(points); const rangeTreeRoot = RangeTreeOps.createByIndexSplits( - ((index: number): Range3d => { return Range3d.create(linestring.pointAt(index)!, linestring.pointAt(index + 1)!); }), - ((index: number): number => { return index; }), - linestring.numPoints() - 1, // number of segments + (index: number): Range3d => { + return Range3d.create(linestring.pointAt(index)!, linestring.pointAt(index + 1)!); + }, + (index: number): number => { + return index; + }, + linestring.numPoints() - 1, // number of segments maxChildPerNode, maxAppDataPerLeaf, ); @@ -90,8 +99,12 @@ export class LineString3dRangeTreeContext { * @param contextB second polyline context * @param maxDist collect close approaches separated by no more than this distance. If undefined, return only the closest approach. * @return closest approach detail pair(s), one per context, with detail.a set to the approach distance - */ - public static searchForClosestApproach(contextA: LineString3dRangeTreeContext, contextB: LineString3dRangeTreeContext, maxDist?: number): CurveLocationDetailPair | CurveLocationDetailPair[] | undefined { + */ + public static searchForClosestApproach( + contextA: LineString3dRangeTreeContext, + contextB: LineString3dRangeTreeContext, + maxDist?: number, + ): CurveLocationDetailPair | CurveLocationDetailPair[] | undefined { const handler = new TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach(contextA, contextB, maxDist); RangeTreeNode.searchTwoTreesTopDown(contextA._rangeTreeRoot, contextB._rangeTreeRoot, handler); return handler.searchState.savedItems.length <= 1 ? handler.getResult() : handler.getSavedItems(); diff --git a/core/geometry/src/polyface/RangeTree/MinimumValueTester.ts b/core/geometry/src/polyface/RangeTree/MinimumValueTester.ts index eabcfba73788..8de6ac941f7d 100644 --- a/core/geometry/src/polyface/RangeTree/MinimumValueTester.ts +++ b/core/geometry/src/polyface/RangeTree/MinimumValueTester.ts @@ -13,7 +13,7 @@ * * When comparing a potential minimum value to an undefined value, the number is always accepted as the new minimum. * @internal */ -export class MinimumValueTester{ +export class MinimumValueTester { public itemAtMinValue: T | undefined; public minValue: number | undefined; public triggerForSavingToArray: number | undefined; diff --git a/core/geometry/src/polyface/RangeTree/Point3dArrayRangeTreeContext.ts b/core/geometry/src/polyface/RangeTree/Point3dArrayRangeTreeContext.ts index 6b444c460548..5cc1e6ddc8b2 100644 --- a/core/geometry/src/polyface/RangeTree/Point3dArrayRangeTreeContext.ts +++ b/core/geometry/src/polyface/RangeTree/Point3dArrayRangeTreeContext.ts @@ -11,7 +11,8 @@ import { Point3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { RangeTreeNode, RangeTreeOps } from "./RangeTreeNode"; import { - SingleTreeSearchHandlerForClosestPointInArray, TwoTreeSearchHandlerForPoint3dArrayPoint3dArrayCloseApproach, + SingleTreeSearchHandlerForClosestPointInArray, + TwoTreeSearchHandlerForPoint3dArrayPoint3dArrayCloseApproach, } from "./RangeTreeSearchHandlers"; /** @@ -52,10 +53,18 @@ export class Point3dArrayRangeTreeContext { * @param maxChildPerNode maximum children per range tree node (default 4) * @param maxAppDataPerLeaf maximum point indices per leaf node (default 4) */ - public static createCapture(points: Point3d[], maxChildPerNode: number = 4, maxAppDataPerLeaf: number = 4): Point3dArrayRangeTreeContext | undefined { + public static createCapture( + points: Point3d[], + maxChildPerNode: number = 4, + maxAppDataPerLeaf: number = 4, + ): Point3dArrayRangeTreeContext | undefined { const rangeTreeRoot = RangeTreeOps.createByIndexSplits( - ((index: number): Range3d => { return Range3d.create(points[index]); }), - ((index: number): number => { return index; }), + (index: number): Range3d => { + return Range3d.create(points[index]); + }, + (index: number): number => { + return index; + }, points.length, maxChildPerNode, maxAppDataPerLeaf, @@ -86,11 +95,14 @@ export class Point3dArrayRangeTreeContext { * * detail.point = the point at closest approach * * detail.fraction = the index of detail.point in the points array * * detail.a = the closest approach distance - */ - public static searchForClosestApproach(contextA: Point3dArrayRangeTreeContext, contextB: Point3dArrayRangeTreeContext, maxDist?: number): CurveLocationDetailPair | CurveLocationDetailPair[] | undefined { + */ + public static searchForClosestApproach( + contextA: Point3dArrayRangeTreeContext, + contextB: Point3dArrayRangeTreeContext, + maxDist?: number, + ): CurveLocationDetailPair | CurveLocationDetailPair[] | undefined { const handler = new TwoTreeSearchHandlerForPoint3dArrayPoint3dArrayCloseApproach(contextA, contextB, maxDist); RangeTreeNode.searchTwoTreesTopDown(contextA._rangeTreeRoot, contextB._rangeTreeRoot, handler); return handler.searchState.savedItems.length <= 1 ? handler.getResult() : handler.getSavedItems(); } } - diff --git a/core/geometry/src/polyface/RangeTree/PolyfaceRangeTreeContext.ts b/core/geometry/src/polyface/RangeTree/PolyfaceRangeTreeContext.ts index 79be260bcdf7..390306ba2907 100644 --- a/core/geometry/src/polyface/RangeTree/PolyfaceRangeTreeContext.ts +++ b/core/geometry/src/polyface/RangeTree/PolyfaceRangeTreeContext.ts @@ -57,13 +57,23 @@ export class PolyfaceRangeTreeContext { * @param maxAppDataPerLeaf maximum facet indices per leaf node (default 4) * @param convexFacets whether all facets are known to be convex (cf. [[PolyfaceQuery.areFacetsConvex]]) (default false) */ - public static createCapture(visitor: Polyface | PolyfaceVisitor, maxChildPerNode: number = 4, maxAppDataPerLeaf: number = 4, convexFacets: boolean = false): PolyfaceRangeTreeContext | undefined { + public static createCapture( + visitor: Polyface | PolyfaceVisitor, + maxChildPerNode: number = 4, + maxAppDataPerLeaf: number = 4, + convexFacets: boolean = false, + ): PolyfaceRangeTreeContext | undefined { if (visitor instanceof Polyface) return this.createCapture(visitor.createVisitor(0), maxChildPerNode, maxAppDataPerLeaf, convexFacets); const numFacet = PolyfaceQuery.visitorClientFacetCount(visitor); const rangeTreeRoot = RangeTreeOps.createByIndexSplits( - (index: number): Range3d => { visitor.moveToReadIndex(index); return visitor.range(); }, - (index: number): number => { return index; }, + (index: number): Range3d => { + visitor.moveToReadIndex(index); + return visitor.range(); + }, + (index: number): number => { + return index; + }, numFacet, maxChildPerNode, maxAppDataPerLeaf, @@ -77,7 +87,11 @@ export class PolyfaceRangeTreeContext { * @param searchFacetInterior whether to include facet interiors in search. Default is false: just consider facet boundaries. * @return closest point detail(s) with detail.a set to the distance from spacePoint to detail.point */ - public searchForClosestPoint(spacePoint: Point3d, maxDist?: number, searchFacetInterior: boolean = false): FacetLocationDetail | FacetLocationDetail[] | undefined { + public searchForClosestPoint( + spacePoint: Point3d, + maxDist?: number, + searchFacetInterior: boolean = false, + ): FacetLocationDetail | FacetLocationDetail[] | undefined { const handler = new SingleTreeSearchHandlerForClosestPointOnPolyface(spacePoint, this, maxDist, searchFacetInterior); this.numSearch++; const numFacet = PolyfaceQuery.visitorClientFacetCount(this.visitor); @@ -98,8 +112,13 @@ export class PolyfaceRangeTreeContext { * @param maxDist collect close approaches separated by no more than this distance. If undefined, return only the closest approach. * @param searchFacetInterior whether to include facet interiors in search (`context.convexFacets` must be true for both contexts). Default is false: just consider facet boundaries. * @return closest approach detail pair(s), one per context, with detail.a set to the approach distance - */ - public static searchForClosestApproach(contextA: PolyfaceRangeTreeContext, contextB: PolyfaceRangeTreeContext, maxDist?: number, searchFacetInterior: boolean = false): FacetLocationDetailPair | FacetLocationDetailPair[] | undefined { + */ + public static searchForClosestApproach( + contextA: PolyfaceRangeTreeContext, + contextB: PolyfaceRangeTreeContext, + maxDist?: number, + searchFacetInterior: boolean = false, + ): FacetLocationDetailPair | FacetLocationDetailPair[] | undefined { const handler = new TwoTreeSearchHandlerForFacetFacetCloseApproach(contextA, contextB, maxDist, searchFacetInterior); RangeTreeNode.searchTwoTreesTopDown(contextA._rangeTreeRoot, contextB._rangeTreeRoot, handler); return handler.searchState.savedItems.length <= 1 ? handler.getResult() : handler.getSavedItems(); diff --git a/core/geometry/src/polyface/RangeTree/RangeTreeNode.ts b/core/geometry/src/polyface/RangeTree/RangeTreeNode.ts index 270a23a63fd6..3f6321152dbd 100644 --- a/core/geometry/src/polyface/RangeTree/RangeTreeNode.ts +++ b/core/geometry/src/polyface/RangeTree/RangeTreeNode.ts @@ -81,7 +81,9 @@ export abstract class SingleTreeSearchHandler { * * Search processes check this after range tests and child processing. */ // eslint-disable-next-line @itwin/prefer-get - public isAborted(): boolean { return false; } + public isAborted(): boolean { + return false; + } } /** * Abstract class for handler objects called during traversal of two range trees. @@ -103,7 +105,9 @@ export abstract class TwoTreeSearchHandler { * * Search processes check this after range tests and child processing. */ // eslint-disable-next-line @itwin/prefer-get - public isAborted(): boolean { return false; } + public isAborted(): boolean { + return false; + } } /** * This class refines the TwoTreeSearchHandler with an implementation of `isRangePairActive` appropriate for computing the minimum distance between trees. @@ -111,7 +115,7 @@ export abstract class TwoTreeSearchHandler { * * The implementation of `isRangePairActive` returns true if the distance between ranges is less than or equal to the `getCurrentDistance()` value. * @internal */ -export abstract class TwoTreeDistanceMinimizationSearchHandler extends TwoTreeSearchHandler{ +export abstract class TwoTreeDistanceMinimizationSearchHandler extends TwoTreeSearchHandler { /** * Provides the allowable distance between ranges. * * Range pairs with more than this distance separation are rejected. @@ -191,7 +195,8 @@ export class RangeTreeNode { public static createCapture( range: Range3d, appData: FlexData, - children: FlexData>): RangeTreeNode { + children: FlexData>, + ): RangeTreeNode { return new RangeTreeNode(range, appData, children); } /** copy (not capture) from given data into the range in this RangeEntry */ @@ -420,11 +425,20 @@ export class RangeTreeNode { this.pushPaths(leftTip, leftStack, leftStackWithAppData); this.pushPaths(rightTip, rightStack, rightStackWithAppData); for (let leftIndex = 0; undefined !== (leftChild = getByIndex>(leftIndex, leftTip._children)); leftIndex++) { - for (let rightIndex = 0; undefined !== (rightChild = getByIndex>(rightIndex, rightTip._children)); rightIndex++) { + for ( + let rightIndex = 0; + undefined !== (rightChild = getByIndex>(rightIndex, rightTip._children)); + rightIndex++ + ) { this.recursivePairSearch( - leftChild, leftStack, leftStackWithAppData, - rightChild, rightStack, rightStackWithAppData, - handler); + leftChild, + leftStack, + leftStackWithAppData, + rightChild, + rightStack, + rightStackWithAppData, + handler, + ); } } this.popPaths(leftTip, leftStack, leftStackWithAppData); @@ -485,14 +499,21 @@ export class RangeTreeOps { /** Count nodes in this tree. */ public static getRecursiveNodeCount(root: RangeTreeNode): number { let count = 0; - root.recurseIntoTree((_node: RangeTreeNode): boolean => { count++; return true; }); + root.recurseIntoTree((_node: RangeTreeNode): boolean => { + count++; + return true; + }); return count; } /** Count appData in this tree. */ public static getRecursiveAppDataCount(root: RangeTreeNode): number { let count = 0; root.recurseIntoTree( - (node: RangeTreeNode): boolean => { count += node.getNumAppData(); return true; }); + (node: RangeTreeNode): boolean => { + count += node.getNumAppData(); + return true; + }, + ); return count; } /** @@ -509,7 +530,8 @@ export class RangeTreeOps { appData: IndexToType, index0: number, index1: number, - arrayLength: number): RangeTreeNode { + arrayLength: number, + ): RangeTreeNode { const appDataBlock: AppDataType[] = []; const range = Range3d.createNull(); index1 = Math.min(index1, arrayLength); @@ -548,7 +570,7 @@ export class RangeTreeOps { const maxChildrenAppData = maxChildPerNode * maxAppDataPerLeaf; // console.log({ name: "createRecursive", index0, index1, maxChildrenAppData }); - if (index1 <= index0 + maxChildrenAppData) { // index range is small enough to hold the appData in leaf children + if (index1 <= index0 + maxChildrenAppData) { // index range is small enough to hold the appData in leaf children // console.log({ case: "LEAF GROUP", index0, index1 }); for (let indexA = index0 + maxAppDataPerLeaf; index0 < index1; index0 = indexA, indexA = Math.min(indexA + maxAppDataPerLeaf, index1)) { const leaf = RangeTreeOps.createLeafInIndexRange(ranges, appData, index0, indexA, arrayLength); @@ -557,7 +579,7 @@ export class RangeTreeOps { children.push(leaf); } } - } else { // split the appData among interior and leaf children + } else { // split the appData among interior and leaf children // console.log({ case: "INTERIOR", index0, index1 }); const numPerGulp = Math.ceil((index1 - index0) / maxChildPerNode); for (let indexA = index0 + numPerGulp; index0 < index1; index0 = indexA, indexA = Math.min(indexA + numPerGulp, index1)) { @@ -591,13 +613,22 @@ export class RangeTreeOps { // console.log(); // const numData = getFlexDataCount(appData); // console.log({ numData }); - if (arrayLength <= 0 + if ( + arrayLength <= 0 || (Array.isArray(ranges) && ranges.length !== arrayLength) - || (Array.isArray(appData) && appData.length !== arrayLength)) + || (Array.isArray(appData) && appData.length !== arrayLength) + ) return undefined; if (maxChildrenPerNode < 2) maxChildrenPerNode = 2; - return RangeTreeOps.createRecursiveByIndexSplits(ranges, appData, 0, arrayLength, arrayLength, maxChildrenPerNode, maxAppDataPerLeaf); + return RangeTreeOps.createRecursiveByIndexSplits( + ranges, + appData, + 0, + arrayLength, + arrayLength, + maxChildrenPerNode, + maxAppDataPerLeaf, + ); } } - diff --git a/core/geometry/src/polyface/RangeTree/RangeTreeSearchHandlers.ts b/core/geometry/src/polyface/RangeTree/RangeTreeSearchHandlers.ts index 11f6cc7b4a7b..27d8591de9ba 100644 --- a/core/geometry/src/polyface/RangeTree/RangeTreeSearchHandlers.ts +++ b/core/geometry/src/polyface/RangeTree/RangeTreeSearchHandlers.ts @@ -276,10 +276,14 @@ export class TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach extend /** Compute and test the closest approach between two segments, given their indices. */ public override processAppDataPair(indexA: number, indexB: number): void { this.contextA.numPointTest++; - const segA = TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentA = - this.contextA.lineString.getIndexedSegment(indexA, TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentA)!; - const segB = TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentB = - this.contextB.lineString.getIndexedSegment(indexB, TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentB)!; + const segA = TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentA = this.contextA.lineString.getIndexedSegment( + indexA, + TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentA, + )!; + const segB = TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentB = this.contextB.lineString.getIndexedSegment( + indexB, + TwoTreeSearchHandlerForLineString3dLineString3dCloseApproach._workSegmentB, + )!; const cldPair = LineSegment3d.closestApproach(segA, false, segB, false); if (cldPair && this.searchState.isNewMinOrTrigger(cldPair.detailA.a)) { LineString3d.convertLocalToGlobalDetail(cldPair.detailA, indexA, this.contextA.lineString.numEdges(), this.contextA.lineString); @@ -388,7 +392,7 @@ export class TwoTreeSearchHandlerForFacetFacetCloseApproach extends TwoTreeDista * @param contextB captured * @param maxDist collect points at no more than this separation distance * @param searchFacetInterior true: search facet interior + boundary; false: just boundary - */ + */ public constructor(contextA: PolyfaceRangeTreeContext, contextB: PolyfaceRangeTreeContext, maxDist?: number, searchFacetInterior: boolean = false) { super(); this.contextA = contextA; @@ -419,7 +423,7 @@ export class TwoTreeSearchHandlerForFacetFacetCloseApproach extends TwoTreeDista } /** Compute and test the closest approach between two facets, given their indices. */ public override processAppDataPair(indexA: number, indexB: number): void { - this.contextA.visitor.setNumWrap(1); // closed polygons are more efficient for PolygonOps.closestApproach + this.contextA.visitor.setNumWrap(1); // closed polygons are more efficient for PolygonOps.closestApproach this.contextB.visitor.setNumWrap(1); if (this.contextA.visitor.moveToReadIndex(indexA) && this.contextB.visitor.moveToReadIndex(indexB)) { // ASSUME: not worth sending in maxDist here... @@ -429,12 +433,15 @@ export class TwoTreeSearchHandlerForFacetFacetCloseApproach extends TwoTreeDista const edgeCountA = this.contextA.visitor.pointCount - 1; const edgeCountB = this.contextB.visitor.pointCount - 1; const fldPair = FacetLocationDetailPair.create( - this.contextA.convexFacets ? ConvexFacetLocationDetail.createCapture(indexA, edgeCountA, pldPair.detailA) : NonConvexFacetLocationDetail.createCapture(indexA, edgeCountA, pldPair.detailA), - this.contextB.convexFacets ? ConvexFacetLocationDetail.createCapture(indexB, edgeCountB, pldPair.detailB) : NonConvexFacetLocationDetail.createCapture(indexB, edgeCountB, pldPair.detailB), + this.contextA.convexFacets + ? ConvexFacetLocationDetail.createCapture(indexA, edgeCountA, pldPair.detailA) + : NonConvexFacetLocationDetail.createCapture(indexA, edgeCountA, pldPair.detailA), + this.contextB.convexFacets + ? ConvexFacetLocationDetail.createCapture(indexB, edgeCountB, pldPair.detailB) + : NonConvexFacetLocationDetail.createCapture(indexB, edgeCountB, pldPair.detailB), ); this.searchState.testAndSave(fldPair, fldPair.detailA.a); } } } } - diff --git a/core/geometry/src/polyface/TaggedNumericData.ts b/core/geometry/src/polyface/TaggedNumericData.ts index 4ed42233d661..a9518d196db8 100644 --- a/core/geometry/src/polyface/TaggedNumericData.ts +++ b/core/geometry/src/polyface/TaggedNumericData.ts @@ -14,34 +14,33 @@ import { Geometry } from "../Geometry"; */ export namespace TaggedNumericConstants { /** Reserved values for the "tagA" member of [[TaggedNumericData]] - * @public - * - */ -export enum TaggedNumericTagType { + * @public + */ + export enum TaggedNumericTagType { /** `tagA` value identifying a subdivision surface*/ - SubdivisionSurface = -1000 + SubdivisionSurface = -1000, } /** * `tagB` values for supported types of subdivision surfaces * @public */ -export enum SubdivisionMethod { + export enum SubdivisionMethod { ChooseBasedOnFacets = 0, CatmullClark = 1, Loop = 2, - DooSabin = 3 + DooSabin = 3, } /** * numeric values for subdivision control. These are entered in the intData array as first of a pair. * @public */ -export enum SubdivisionControlCode { + export enum SubdivisionControlCode { /** pair (FixedDepth, d) indicates subdivision to depth d */ FixedDepth = -100, /** pair (FixedDepth, index) indicates absolute tolerance with value in doubleData[index] */ AbsoluteTolerance = -101, /** pair (FixedDepth, index) indicates tolerance as a fraction of base mesh range is found in doubleData[index] */ - FractionOfRangeBoxTolerance = -102 + FractionOfRangeBoxTolerance = -102, } } /** @@ -55,20 +54,18 @@ export class TaggedNumericData { /** Application specific secondary tag. See reserved values in [[TaggedNumericConstants]] */ public tagB: number; - public constructor(tagA: number = 0, tagB: number = 0, - intData?: number[], doubleData?: number[], - ) { + public constructor(tagA: number = 0, tagB: number = 0, intData?: number[], doubleData?: number[]) { this.tagA = tagA; this.tagB = tagB; if (intData) this.intData = intData; if (doubleData) this.doubleData = doubleData; } -/** Integer data with application-specific meaning */ + /** Integer data with application-specific meaning */ public intData?: number[]; -/** Double data with application-specific meaning */ -public doubleData?: number[]; + /** Double data with application-specific meaning */ + public doubleData?: number[]; -/** + /** * push a pair of int values on the intData array. * @param intA * @param intB @@ -83,12 +80,12 @@ public doubleData?: number[]; * @param intA int to push on the intData array, followed by index of valueB in the doubleData array. * @param valueB value to push on the doubleData array. */ - public pushIndexedDouble(intA: number, valueB: number) { - if (!this.intData) this.intData = []; - if (!this.doubleData) this.doubleData = []; - this.intData.push(intA); - this.intData.push(this.doubleData.length); - this.doubleData.push(valueB); + public pushIndexedDouble(intA: number, valueB: number) { + if (!this.intData) this.intData = []; + if (!this.doubleData) this.doubleData = []; + this.intData.push(intA); + this.intData.push(this.doubleData.length); + this.doubleData.push(valueB); } /** * Search pairs in the intData array for a pair (targetTag, value). Return the value, possibly restricted to (minValue,maxValue) @@ -98,10 +95,10 @@ public doubleData?: number[]; * @param defaultValue */ public tagToInt(targetTag: number, minValue: number, maxValue: number, defaultValue: number): number { - if (this.intData) { - for (let i = 0; i + 1 < this.intData.length; i += 2){ - if (this.intData[i] === targetTag) - return Math.min(Math.max(this.intData[i + 1], minValue), maxValue); + if (this.intData) { + for (let i = 0; i + 1 < this.intData.length; i += 2) { + if (this.intData[i] === targetTag) + return Math.min(Math.max(this.intData[i + 1], minValue), maxValue); } } return defaultValue; @@ -115,10 +112,10 @@ public doubleData?: number[]; * @param defaultValue */ public tagToIndexedDouble(targetTag: number, minValue: number, maxValue: number, defaultValue: number): number { - if (this.intData) { - for (let i = 0; i + 1 < this.intData.length; i += 2){ - if (this.intData[i] === targetTag) { - return Geometry.clamp(this.getDoubleData (this.intData[i + 1], defaultValue), minValue, maxValue); + if (this.intData) { + for (let i = 0; i + 1 < this.intData.length; i += 2) { + if (this.intData[i] === targetTag) { + return Geometry.clamp(this.getDoubleData(this.intData[i + 1], defaultValue), minValue, maxValue); } } } @@ -129,31 +126,31 @@ public doubleData?: number[]; * @param index * @param defaultValue */ - public getDoubleData(index: number, defaultValue: number): number{ + public getDoubleData(index: number, defaultValue: number): number { if (this.doubleData && 0 <= index && index < this.doubleData.length) return this.doubleData[index]; return defaultValue; } /** Apply isAlmostEqual to all members. */ - public isAlmostEqual(other: TaggedNumericData): boolean{ + public isAlmostEqual(other: TaggedNumericData): boolean { if (other === undefined) return false; if (this.tagA !== other.tagA) return false; if (this.tagB !== other.tagB) - return false; + return false; return Geometry.exactEqualNumberArrays(this.intData, other.intData) && Geometry.almostEqualArrays(this.doubleData, other.doubleData, (a, b) => Geometry.isAlmostEqualNumber(a, b)); } - public static areAlmostEqual(dataA: TaggedNumericData | undefined, dataB: TaggedNumericData | undefined): boolean{ + public static areAlmostEqual(dataA: TaggedNumericData | undefined, dataB: TaggedNumericData | undefined): boolean { if (dataA === undefined && dataB === undefined) return true; if (dataA !== undefined && dataB !== undefined) return dataA.isAlmostEqual(dataB); return false; } -/** Return a deep clone. */ + /** Return a deep clone. */ public clone(result?: TaggedNumericData): TaggedNumericData { if (!result) result = new TaggedNumericData(this.tagA, this.tagB); diff --git a/core/geometry/src/polyface/TriangleCandidate.ts b/core/geometry/src/polyface/TriangleCandidate.ts index 10cd7e8df3d6..8de560cfe813 100644 --- a/core/geometry/src/polyface/TriangleCandidate.ts +++ b/core/geometry/src/polyface/TriangleCandidate.ts @@ -44,7 +44,16 @@ export class TriangleCandidate extends BarycentricTriangle { * * Access points from multiple `IndexedXYZCollection` * * mark invalid if any indices are invalid. */ - public static createFromIndexedXYZ(source0: IndexedXYZCollection, index0: number, source1: IndexedXYZCollection, index1: number, source2: IndexedXYZCollection, index2: number, id: number, result?: TriangleCandidate): TriangleCandidate { + public static createFromIndexedXYZ( + source0: IndexedXYZCollection, + index0: number, + source1: IndexedXYZCollection, + index1: number, + source2: IndexedXYZCollection, + index2: number, + id: number, + result?: TriangleCandidate, + ): TriangleCandidate { if (!result) result = new TriangleCandidate(Point3d.create(), Point3d.create(), Point3d.create(), id, 0.0, false); result.id = id; @@ -62,7 +71,9 @@ export class TriangleCandidate extends BarycentricTriangle { return result; } /** (property) return the validity flag. */ - public get isValid(): boolean { return this._isValid; } + public get isValid(): boolean { + return this._isValid; + } /** * * Mark this triangle invalid. * * optionally set aspect ratio. diff --git a/core/geometry/src/polyface/multiclip/BuildAverageNormalsContext.ts b/core/geometry/src/polyface/multiclip/BuildAverageNormalsContext.ts index 7163a4b252a6..37165edcf522 100644 --- a/core/geometry/src/polyface/multiclip/BuildAverageNormalsContext.ts +++ b/core/geometry/src/polyface/multiclip/BuildAverageNormalsContext.ts @@ -6,12 +6,12 @@ * @module Polyface */ +import { Geometry } from "../../Geometry"; +import { Angle } from "../../geometry3d/Angle"; +import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; import { Vector3d } from "../../geometry3d/Point3dVector3d"; import { PolygonOps } from "../../geometry3d/PolygonOps"; import { IndexedPolyface } from "../Polyface"; -import { Geometry } from "../../Geometry"; -import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; -import { Angle } from "../../geometry3d/Angle"; /** * Normal vector with area (or other numeric) and source index @@ -51,8 +51,12 @@ class SectorData { public sectorIndex: number; public vertexIndex: number; public sectorClusterData: IndexedAreaAndNormal | undefined; - public static cbSectorSort(left: SectorData, right: SectorData): number { return left.sectorIndex - right.sectorIndex; } - public static cbVertexSort(left: SectorData, right: SectorData): number { return left.vertexIndex - right.vertexIndex; } + public static cbSectorSort(left: SectorData, right: SectorData): number { + return left.sectorIndex - right.sectorIndex; + } + public static cbVertexSort(left: SectorData, right: SectorData): number { + return left.vertexIndex - right.vertexIndex; + } public static pushToArray(data: SectorData[], facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) { data.push(new SectorData(facetData, sectorIndex, vertexIndex)); } @@ -78,7 +82,7 @@ export class BuildAverageNormalsContext { // We ASSUME that the visitor order matches index order in polyface.data ..... const visitor = polyface.createVisitor(0); const defaultNormal = Vector3d.create(0, 0, 1); - const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE + const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE const sectors: SectorData[] = []; let facetIndex = 0; let sectorIndex = 0; @@ -126,9 +130,7 @@ export class BuildAverageNormalsContext { clusters.push(clusterNormal); // Accumulate with equal weights . . . clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal); - for (let candidateSectorIndex = baseSectorIndex; - candidateSectorIndex < sectors.length; - candidateSectorIndex++) { + for (let candidateSectorIndex = baseSectorIndex; candidateSectorIndex < sectors.length; candidateSectorIndex++) { const candidateSector = sectors[candidateSectorIndex]; if (candidateSector.vertexIndex !== vertexIndex) break; diff --git a/core/geometry/src/polyface/multiclip/LinearSearchRange2dArray.ts b/core/geometry/src/polyface/multiclip/LinearSearchRange2dArray.ts index a0bac6143719..8c3b1db2b5fb 100644 --- a/core/geometry/src/polyface/multiclip/LinearSearchRange2dArray.ts +++ b/core/geometry/src/polyface/multiclip/LinearSearchRange2dArray.ts @@ -57,9 +57,10 @@ export class LinearSearchRange2dArray implements Range2dSearchInterface { this.updateForSearch(); // NEEDS WORK: Linear search here -- do better! for (const candidate of this._rangeArray) { - if (candidate.containsXY(x, y)) + if (candidate.containsXY(x, y)) { if (!handler(candidate, (candidate as any).tag)) return false; + } } return true; } @@ -75,9 +76,10 @@ export class LinearSearchRange2dArray implements Range2dSearchInterface { if (this._isDirty) this.updateForSearch(); for (const candidate of this._rangeArray) { - if (candidate.intersectsRange(testRange)) + if (candidate.intersectsRange(testRange)) { if (!handler(candidate, (candidate as any).tag)) return false; + } } return true; } diff --git a/core/geometry/src/polyface/multiclip/OffsetMeshContext.ts b/core/geometry/src/polyface/multiclip/OffsetMeshContext.ts index fed9de2820d1..7a6fd809975c 100644 --- a/core/geometry/src/polyface/multiclip/OffsetMeshContext.ts +++ b/core/geometry/src/polyface/multiclip/OffsetMeshContext.ts @@ -6,20 +6,20 @@ * @module Polyface */ -import { SmallSystem } from "../../numerics/Polynomials"; +import { Geometry } from "../../Geometry"; +import { Angle } from "../../geometry3d/Angle"; import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { PolygonOps } from "../../geometry3d/PolygonOps"; +import { PolylineCompressionContext } from "../../geometry3d/PolylineCompressionByEdgeOffset"; import { Ray3d } from "../../geometry3d/Ray3d"; +import { XYAndZ } from "../../geometry3d/XYZProps"; +import { SmallSystem } from "../../numerics/Polynomials"; import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "../../topology/Graph"; import { HalfEdgeGraphFromIndexedLoopsContext } from "../../topology/HalfEdgeGraphFromIndexedLoopsContext"; import { IndexedPolyface } from "../Polyface"; import { PolyfaceBuilder } from "../PolyfaceBuilder"; -import { XYAndZ } from "../../geometry3d/XYZProps"; -import { Geometry } from "../../Geometry"; import { OffsetMeshOptions } from "../PolyfaceQuery"; -import { PolylineCompressionContext } from "../../geometry3d/PolylineCompressionByEdgeOffset"; -import { Angle } from "../../geometry3d/Angle"; function isDefinedAndTrue(value: boolean | undefined): boolean { if (value === undefined) @@ -80,14 +80,15 @@ class AverageNormalData { } } /** Return the max deviation as computed on prior calls to recordDeviation */ - public get maxDeviationRadians(): number { return this.maxDeviationRadiansFromAverage; } + public get maxDeviationRadians(): number { + return this.maxDeviationRadiansFromAverage; + } } function emitSector(sector: SectorOffsetProperties) { if (OffsetMeshContext.stringDebugFunction !== undefined) { OffsetMeshContext.stringDebugFunction(` Sector xyz ${sector.xyz.x},${sector.xyz.y},${sector.xyz.z} `); OffsetMeshContext.stringDebugFunction(` normal ${sector.normal.x},${sector.normal.y},${sector.normal.z} `); } - } // facet properties used during offset. @@ -128,11 +129,13 @@ export class SectorOffsetProperties { * @param radiansTolerance tolerance for large angle between normals. * @returns true if this edge has SectorOffsetProperties on both sides and the angle between normals angle exceeds radiansTolerance. */ - public static edgeHasLargeExteriorAngleBetweenNormals(edgeNodeA: HalfEdge, + public static edgeHasLargeExteriorAngleBetweenNormals( + edgeNodeA: HalfEdge, edgeVector: Vector3d, averageNormal: Vector3d, offsetDistance: number, - radiansTolerance: number = Math.PI * 0.5): boolean { + radiansTolerance: number = Math.PI * 0.5, + ): boolean { const propsA = edgeNodeA.edgeTag as SectorOffsetProperties; const edgeNodeB = edgeNodeA.edgeMate; const propsB = edgeNodeB.edgeTag as SectorOffsetProperties; @@ -148,7 +151,11 @@ export class SectorOffsetProperties { return false; } - public static almostEqualNormals(sectorA: SectorOffsetProperties, sectorB: SectorOffsetProperties, radiansTolerance: number = Geometry.smallAngleRadians): boolean { + public static almostEqualNormals( + sectorA: SectorOffsetProperties, + sectorB: SectorOffsetProperties, + radiansTolerance: number = Geometry.smallAngleRadians, + ): boolean { return sectorA.normal.radiansTo(sectorB.normal) <= radiansTolerance; } public static radiansBetweenNormals(sectorA: SectorOffsetProperties, sectorB: SectorOffsetProperties): number { @@ -300,8 +307,7 @@ Important properties during offset construction: 6.3: By vertex: At each vertex, if all vertex coordinates match output nothing. Otherwise output a facet with all the coordinates. */ export class OffsetMeshContext { - private constructor(basePolyface: IndexedPolyface, baseGraph: HalfEdgeGraph, - options: OffsetMeshOptions) { + private constructor(basePolyface: IndexedPolyface, baseGraph: HalfEdgeGraph, options: OffsetMeshOptions) { this._basePolyface = basePolyface; this._baseGraph = baseGraph; this._breakMaskA = baseGraph.grabMask(); @@ -320,34 +326,48 @@ export class OffsetMeshContext { private _basePolyface: IndexedPolyface; private _baseGraph: HalfEdgeGraph; /** "Exterior" side of a bare edge of the mesh */ - public get exteriorMask(): HalfEdgeMask { return this._exteriorMask; } + public get exteriorMask(): HalfEdgeMask { + return this._exteriorMask; + } private _exteriorMask: HalfEdgeMask; /** Mask indicating a a sector's coordinates have been reassigned at offset distance. */ private _offsetCoordinatesReassigned: HalfEdgeMask; /** "First" sector of a smooth sequence. */ - public get breakMaskA(): HalfEdgeMask { return this._breakMaskA; } + public get breakMaskA(): HalfEdgeMask { + return this._breakMaskA; + } private _breakMaskA: HalfEdgeMask; /** "Last" sector of a smooth sequence. */ - public get breakMaskB(): HalfEdgeMask { return this._breakMaskB; } + public get breakMaskB(): HalfEdgeMask { + return this._breakMaskB; + } private _breakMaskB: HalfEdgeMask; /** This edge is on a chamfered face, and along the original edge */ - public get insideOfChamferFace(): HalfEdgeMask { return this._insideOfChamferFace; } + public get insideOfChamferFace(): HalfEdgeMask { + return this._insideOfChamferFace; + } private _insideOfChamferFace: HalfEdgeMask; /** This is the original edge of a chamfer face */ - public get outsideOfChamferFace(): HalfEdgeMask { return this._outsideOfChamferFace; } + public get outsideOfChamferFace(): HalfEdgeMask { + return this._outsideOfChamferFace; + } private _outsideOfChamferFace: HalfEdgeMask; /** This edge is on a chamfered face, and at the end -- other side may be a sling */ - public get insideChamferSling(): HalfEdgeMask { return this._insideChamferSling; } + public get insideChamferSling(): HalfEdgeMask { + return this._insideChamferSling; + } private _insideChamferSling: HalfEdgeMask; /** This is the outside of the end of a chamfer face -- i.e. the inside of a new face-at-vertex */ - public get outsideEndOfChamferFace(): HalfEdgeMask { return this._outsideEndOfChamferFace; } + public get outsideEndOfChamferFace(): HalfEdgeMask { + return this._outsideEndOfChamferFace; + } private _outsideEndOfChamferFace: HalfEdgeMask; // On a CCW vertex loop, the mask sequence at a chamfered edge (which was expanded to a chamfer face) is @@ -386,7 +406,8 @@ export class OffsetMeshContext { basePolyface: IndexedPolyface, builder: PolyfaceBuilder, distance: number, - options: OffsetMeshOptions) { + options: OffsetMeshOptions, + ) { const baseGraph = this.buildBaseGraph(basePolyface); if (baseGraph !== undefined) { const offsetBuilder = new OffsetMeshContext(basePolyface, baseGraph, options); @@ -419,13 +440,13 @@ export class OffsetMeshContext { } /** - * For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet - * @param polyfaceBuilder - */ + * For each face of the graph, shift vertices by offsetDistance and emit to the builder as a facet + * @param polyfaceBuilder + */ public announceSimpleOffsetFromFaces(polyfaceBuilder: PolyfaceBuilder, offsetDistance: number) { const xyzLoop = new GrowableXYZArray(); - const xyz = Point3d.create(); // reused at each point around each facet. - const uvw = Vector3d.create(); // reused once per facet + const xyz = Point3d.create(); // reused at each point around each facet. + const uvw = Vector3d.create(); // reused once per facet const announceNodeAroundFace = (node: HalfEdge): number => { node.getPoint3d(xyz); xyz.addInPlace(uvw); @@ -443,13 +464,14 @@ export class OffsetMeshContext { polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop); } return true; - }); + }, + ); } /** - * For each face of the graph, output the xyz of the sector data - * @param polyfaceBuilder - */ + * For each face of the graph, output the xyz of the sector data + * @param polyfaceBuilder + */ public announceFacetsWithSectorCoordinatesAroundFaces(polyfaceBuilder: PolyfaceBuilder) { const xyzLoop = new GrowableXYZArray(); // For face loop visits .. get the point from the sector data. @@ -469,7 +491,8 @@ export class OffsetMeshContext { polyfaceBuilder.addPolygonGrowableXYZArray(xyzLoop); } return true; - }); + }, + ); } private countBits(mask: HalfEdgeMask): number { let n = 0; @@ -481,12 +504,12 @@ export class OffsetMeshContext { return n; } /** - * For each edge of the graph . . - * * Collect coordinates in 4 sectors going around the edge - * * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point. - * * Emit as a facet. - * @param polyfaceBuilder - */ + * For each edge of the graph . . + * * Collect coordinates in 4 sectors going around the edge + * * Compress with tight tolerance so adjacent sectors with clean point match reduce to a single point. + * * Emit as a facet. + * @param polyfaceBuilder + */ public announceFacetsWithSectorCoordinatesAroundEdges(polyfaceBuilder: PolyfaceBuilder) { const xyzLoop = new GrowableXYZArray(); const primaryCompressionTolerance = Geometry.smallMetricDistance; @@ -500,7 +523,7 @@ export class OffsetMeshContext { // This starts by looking for EXTERIOR on both sides ... if (nodeA.findMaskAroundEdge(this._exteriorMask) !== undefined) { return true; - } else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above + } else if (!nodeA.isMaskSet(allMasksForEdgesToIgnore)) { // By design, we believe that these two test for allMasksForEdgesToIgnore condition would catch the EXTERIOR case above const nodeB = nodeA.faceSuccessor; const nodeC = nodeA.edgeMate; if (!nodeC.isMaskSet(allMasksForEdgesToIgnore)) { @@ -519,7 +542,8 @@ export class OffsetMeshContext { return true; } return true; - }); + }, + ); } private getCoordinateString(node: HalfEdge, showXYZ: boolean = true, showFaceSuccessorXYZ: boolean = false): string { @@ -536,7 +560,6 @@ export class OffsetMeshContext { return ""; } } - } private inspectMasks(node: HalfEdge, showXYZ: boolean = true, showFaceSuccessorXYZ: boolean = false): string { const s = "["; @@ -555,9 +578,9 @@ export class OffsetMeshContext { return v; } /** - * For each face of the graph, output the xyz of the sector data - * @param polyfaceBuilder - */ + * For each face of the graph, output the xyz of the sector data + * @param polyfaceBuilder + */ public announceFacetsWithSectorCoordinatesAroundVertices(polyfaceBuilder: PolyfaceBuilder) { const xyzLoop = new GrowableXYZArray(); const primaryCompressionTolerance = Geometry.smallMetricDistance; @@ -576,18 +599,19 @@ export class OffsetMeshContext { } } return true; - }); + }, + ); } /** - * * Exterior half edges have HalfEdgeMask.EXTERIOR - * * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet. - * * the facetOffsetProperties object has the simple facet normal. - * * Each half edge has edgeTag pointing to to a sectorOffsetProperties object - * * the sectorOffsetProperties has a copy of the facet normal. - * @param polyface - * @returns graph - */ + * * Exterior half edges have HalfEdgeMask.EXTERIOR + * * All interior half edge around a facet have facetTag pointing to a facetProperties object for that facet. + * * the facetOffsetProperties object has the simple facet normal. + * * Each half edge has edgeTag pointing to to a sectorOffsetProperties object + * * the sectorOffsetProperties has a copy of the facet normal. + * @param polyface + * @returns graph + */ public static buildBaseGraph(polyface: IndexedPolyface): HalfEdgeGraph | undefined { const graphBuilder = new HalfEdgeGraphFromIndexedLoopsContext(); const visitor = polyface.createVisitor(); @@ -596,14 +620,13 @@ export class OffsetMeshContext { for (visitor.reset(); visitor.moveToNextFacet();) { const normal = PolygonOps.centroidAreaNormal(visitor.point); if (normal !== undefined) { - const edgeA = graphBuilder.insertLoop(visitor.pointIndex, - (insideHalfEdge: HalfEdge) => { - const mate = insideHalfEdge.edgeMate; - polyface.data.getPoint(insideHalfEdge.i, xyzA); - insideHalfEdge.setXYZ(xyzA); - polyface.data.getPoint(mate.i, xyzB); - mate.setXYZ(xyzB); - }); + const edgeA = graphBuilder.insertLoop(visitor.pointIndex, (insideHalfEdge: HalfEdge) => { + const mate = insideHalfEdge.edgeMate; + polyface.data.getPoint(insideHalfEdge.i, xyzA); + insideHalfEdge.setXYZ(xyzA); + polyface.data.getPoint(mate.i, xyzB); + mate.setXYZ(xyzB); + }); const facetProperties = new FacetOffsetProperties(visitor.currentReadIndex(), normal); if (edgeA !== undefined) { edgeA.sumAroundFace( @@ -611,7 +634,8 @@ export class OffsetMeshContext { edgeB.faceTag = facetProperties; edgeB.edgeTag = new SectorOffsetProperties(normal.direction.clone(), edgeB.getPoint3d()); return 0; - }); + }, + ); } } } @@ -628,8 +652,7 @@ export class OffsetMeshContext { } } return 0.0; - }, - ); + }); } private setOffsetXYAndZAroundVertex(vertexSeed: HalfEdge, xyz: XYAndZ) { @@ -640,21 +663,23 @@ export class OffsetMeshContext { nodeAroundVertex.setMask(this._offsetCoordinatesReassigned); } return 0.0; - }, - ); + }); } /** - * * start at vertexSeed. - * * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask - * * - * @param vertexSeed first node to mark. - * @param f function to call to announce each node and its sector properties. - * @returns number of nodes marked. - */ - private announceNodeAndSectorPropertiesInSmoothSector(vertexSeed: HalfEdge, f: (node: HalfEdge, properties: SectorOffsetProperties) => void): number { + * * start at vertexSeed. + * * set the offset point at up to (and including) one with (a) this._breakMaskB or (b) this._exteriorMask + * * + * @param vertexSeed first node to mark. + * @param f function to call to announce each node and its sector properties. + * @returns number of nodes marked. + */ + private announceNodeAndSectorPropertiesInSmoothSector( + vertexSeed: HalfEdge, + f: (node: HalfEdge, properties: SectorOffsetProperties) => void, + ): number { let n = 0; - for (let currentNode = vertexSeed; ; currentNode = currentNode.vertexSuccessor) { + for (let currentNode = vertexSeed;; currentNode = currentNode.vertexSuccessor) { const props = currentNode.edgeTag as SectorOffsetProperties; if (props !== undefined) { f(currentNode, props); @@ -678,8 +703,7 @@ export class OffsetMeshContext { if (sectorData) data.accumulateNormal(node, sectorData.normal, inactiveNodeMask); return 0.0; - }, - ); + }); if (!data.finishNormalAveraging()) { return undefined; } @@ -688,19 +712,24 @@ export class OffsetMeshContext { if (sectorData) data.recordDeviation(sectorData.normal, !node.isMaskSet(inactiveNodeMask)); return 0.0; - }, - ); + }); return data.maxDeviationRadians; } - private assignOffsetByAverageNormalAroundVertex(vertexSeed: HalfEdge, + private assignOffsetByAverageNormalAroundVertex( + vertexSeed: HalfEdge, maxAllowedDeviationRadians: number, data: AverageNormalData, - distance: number): boolean { + distance: number, + ): boolean { const maxDeviationRadians = this.computeAverageNormalAndMaxDeviationAroundVertex(vertexSeed, data); if (OffsetMeshContext.stringDebugFunction) { - OffsetMeshContext.stringDebugFunction(`XYZ ${HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${JSON.stringify(data.averageNormal.toJSON())}`); - OffsetMeshContext.stringDebugFunction(` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`); + OffsetMeshContext.stringDebugFunction( + `XYZ ${HalfEdge.nodeToIdXYZString(vertexSeed)} Average Normal ${JSON.stringify(data.averageNormal.toJSON())}`, + ); + OffsetMeshContext.stringDebugFunction( + ` angle ratio ${data.radiansSum / (2 * Math.PI)} maxDeviation ${data.maxDeviationRadiansFromAverage}`, + ); } if (maxDeviationRadians !== undefined && maxDeviationRadians <= maxAllowedDeviationRadians) { vertexSeed.sumAroundVertex((node: HalfEdge) => { @@ -714,7 +743,7 @@ export class OffsetMeshContext { /** Search around a vertex for a sector which has a different normal from its vertexPredecessor. * * The seed will be the first candidate considered - */ + */ private markBreakEdgesAndSaveAverageNormalsAroundVertex(vertexSeed: HalfEdge) { vertexSeed.clearMaskAroundVertex(this._breakMaskA); vertexSeed.clearMaskAroundVertex(this._breakMaskB); @@ -728,7 +757,7 @@ export class OffsetMeshContext { let _numSmooth = 0; do { const nodeQ = nodeP.edgeMate; - const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor + const nodeR = nodeQ.faceSuccessor; // same as nodeA.vertexPredecessor if (nodeP.isMaskSet(this._exteriorMask)) { if (!nodeQ.isMaskSet(this._exteriorMask)) { nodeR.setMask(this._breakMaskB); @@ -749,10 +778,13 @@ export class OffsetMeshContext { } else if (nodeQ.isMaskSet(this._exteriorMask)) { numBreaks++; nodeP.setMask(this._breakMaskA); - } else if (!SectorOffsetProperties.almostEqualNormals( - nodeP.edgeTag as SectorOffsetProperties, - nodeR.edgeTag as SectorOffsetProperties, - smoothSingleSmoothRadiansBetweenNormals)) { + } else if ( + !SectorOffsetProperties.almostEqualNormals( + nodeP.edgeTag as SectorOffsetProperties, + nodeR.edgeTag as SectorOffsetProperties, + smoothSingleSmoothRadiansBetweenNormals, + ) + ) { nodeP.setMask(this._breakMaskA); numBreaks++; nodeR.setMask(this._breakMaskB); @@ -809,7 +841,7 @@ export class OffsetMeshContext { if (nodeP.isMaskSet(this._breakMaskA) && !nodeP.isMaskSet(this._breakMaskB)) { let nodeQ = nodeP; averageNormal.setZero(); - for (; ;) { + for (;;) { nodeQ.vectorToFaceSuccessor(edgeVectorU); nodeQ.vectorToFacePredecessor(edgeVectorV); let singleSectorRadians = edgeVectorU.signedRadiansTo(edgeVectorV, (nodeQ.faceTag as FacetOffsetProperties).facetNormal.direction); @@ -822,7 +854,7 @@ export class OffsetMeshContext { } if (averageNormal.normalizeInPlace()) { nodeQ = nodeP; - for (; ;) { + for (;;) { SectorOffsetProperties.setNormalAtHalfEdge(nodeQ, averageNormal); if (nodeQ.isMaskSet(this._breakMaskB)) break; @@ -832,7 +864,6 @@ export class OffsetMeshContext { } nodeP = nodeP.vertexSuccessor; } while (nodeP !== nodeAStart); - } } @@ -842,10 +873,14 @@ export class OffsetMeshContext { const sectorB = nodeB.edgeTag as SectorOffsetProperties; const sectorC = nodeC.edgeTag as SectorOffsetProperties; const vector = SmallSystem.intersect3Planes( - sectorA.xyz, sectorA.normal, - sectorB.xyz, sectorB.normal, - sectorC.xyz, sectorC.normal, - result); + sectorA.xyz, + sectorA.normal, + sectorB.xyz, + sectorB.normal, + sectorC.xyz, + sectorC.normal, + result, + ); return vector; } /** Compute the point of intersection of the planes in the sectors of 3 half edges */ @@ -860,10 +895,14 @@ export class OffsetMeshContext { } const vector = SmallSystem.intersect3Planes( - sectorA.xyz, sectorA.normal, - sectorB.xyz, sectorB.normal, - sectorC.xyz, sectorC.normal, - result); + sectorA.xyz, + sectorA.normal, + sectorB.xyz, + sectorB.normal, + sectorC.xyz, + sectorC.normal, + result, + ); if (OffsetMeshContext.stringDebugFunction !== undefined) { if (vector === undefined) @@ -880,10 +919,14 @@ export class OffsetMeshContext { const sectorB = nodeB.edgeTag as SectorOffsetProperties; const normalC = sectorA.normal.crossProduct(sectorB.normal); return SmallSystem.intersect3Planes( - sectorA.xyz, sectorA.normal, - sectorB.xyz, sectorB.normal, - sectorB.xyz, normalC, - result); + sectorA.xyz, + sectorA.normal, + sectorB.xyz, + sectorB.normal, + sectorB.xyz, + normalC, + result, + ); } /** * * at input, graph has all original faces and edges @@ -910,21 +953,20 @@ export class OffsetMeshContext { private addChamferTopologyToAllEdges(options: OffsetMeshOptions, distance: number) { const edgesToChamfer: HalfEdge[] = []; const chamferRadians = options.chamferAngleBetweenNormals.radians; - const vertexXYZ = Point3d.create(); // reuse - const edgeVector = Vector3d.create(); // reuse + const vertexXYZ = Point3d.create(); // reuse + const edgeVector = Vector3d.create(); // reuse const outwardEdgeVector = Vector3d.create(); // reuse const averageNormal = Vector3d.create(); // reuse // collect all the edges with sharp turn angle. this._baseGraph.announceEdges( (_graph: HalfEdgeGraph, edgeNode: HalfEdge) => { - if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, - distance, - chamferRadians)) { + if (SectorOffsetProperties.edgeHasLargeExteriorAngleBetweenNormals(edgeNode, edgeVector, averageNormal, distance, chamferRadians)) { edgesToChamfer.push(edgeNode); return true; } return true; - }); + }, + ); // Create sliver faces. // Sliver face gets an average normal from its neighbors. // outsideA is the HalfEdge labeled A in the diagram. @@ -957,7 +999,7 @@ export class OffsetMeshContext { slingB.faceTag = facetProperties; slingC.setMask(this._insideChamferSling); HalfEdge.pinch(sliverD, slingB); - const endNormal = Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs + const endNormal = Ray3d.create(vertexXYZ, outwardEdgeVector); // clones the inputs const slingFaceProperties = new FacetOffsetProperties(-1, endNormal); slingC.faceTag = slingFaceProperties; // initialize sectors with existing vertex point. @@ -1007,7 +1049,11 @@ export class OffsetMeshContext { OffsetMeshContext.stringDebugFunction(""); OffsetMeshContext.stringDebugFunction(` VERTEX LOOP ${JSON.stringify(vertexSeed.getPoint3d().toJSON())} `); vertexSeed.sumAroundVertex( - (node: HalfEdge) => { OffsetMeshContext.stringDebugFunction!(this.inspectMasks(node, false, true)); return 0; }); + (node: HalfEdge) => { + OffsetMeshContext.stringDebugFunction!(this.inspectMasks(node, false, true)); + return 0; + }, + ); } // Take care of the easiest vertices directly . . . note that this returns from the lambda, not computeOffsetFacetIntersections if (this.assignOffsetByAverageNormalAroundVertex(vertexSeed, maxAllowedNormalDeviationRadians, averageNormalData, distance)) @@ -1049,20 +1095,25 @@ export class OffsetMeshContext { const i1 = (i0 + 1) % breakEdges.length; const i2 = (i1 + 1) % breakEdges.length; - if (breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace) + if ( + breakEdges[i0].isMaskSet(this._outsideEndOfChamferFace) && breakEdges[i1].isMaskSet(this._outsideOfChamferFace) - && breakEdges[i2].isMaskSet(this._insideOfChamferFace)) { + && breakEdges[i2].isMaskSet(this._insideOfChamferFace) + ) { if (OffsetMeshContext.stringDebugFunction !== undefined) - OffsetMeshContext.stringDebugFunction(` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `); + OffsetMeshContext.stringDebugFunction( + ` ChamferChamfer Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${ + this.inspectMasks(breakEdges[i2]) + } `, + ); const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]); if (vectorFromOrigin !== undefined) { // Treat all 3 spots as possibly compound sequences for (const iOutput of [i0, i1, i2]) { - this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], - (node: HalfEdge, properties: SectorOffsetProperties) => { - properties.setXYAndZ(vectorFromOrigin); - node.setMask(this._offsetCoordinatesReassigned); - }); + this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[iOutput], (node: HalfEdge, properties: SectorOffsetProperties) => { + properties.setXYAndZ(vectorFromOrigin); + node.setMask(this._offsetCoordinatesReassigned); + }); } // Since all three were reset, skip past. This is done on the acyclic integer that controls the loop. i += 2; @@ -1077,14 +1128,17 @@ export class OffsetMeshContext { const i1 = (i0 + 1) % breakEdges.length; if (this.isInsideSling(breakEdges[i0], breakEdges[i1])) continue; - if (!this.isOffsetAssigned(breakEdges[i0]) - && breakEdges[i1].isMaskSet(this.insideOfChamferFace)) { + if ( + !this.isOffsetAssigned(breakEdges[i0]) + && breakEdges[i1].isMaskSet(this.insideOfChamferFace) + ) { this.transferXYZFromNodeToSmoothSector(breakEdges[i1], breakEdges[i0], "push left from chamfer", chamferXYZ); - } else if (!this.isOffsetAssigned(breakEdges[i1]) - && breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace)) { + } else if ( + !this.isOffsetAssigned(breakEdges[i1]) + && breakEdges[i0].isMaskSet(this.outsideEndOfChamferFace) + ) { this.transferXYZFromNodeToSmoothSector(breakEdges[i0], breakEdges[i1], "push right from chamfer", chamferXYZ); } - } // Pass 3 -- look for unassigned nodes as middle of 3-face intersections @@ -1097,15 +1151,18 @@ export class OffsetMeshContext { if (this.isOffsetAssigned(breakEdges[i1])) continue; if (OffsetMeshContext.stringDebugFunction !== undefined) - OffsetMeshContext.stringDebugFunction(` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${this.inspectMasks(breakEdges[i2])} `); + OffsetMeshContext.stringDebugFunction( + ` Intersection Fixup ${this.inspectMasks(breakEdges[i0])} ${this.inspectMasks(breakEdges[i1])} ${ + this.inspectMasks(breakEdges[i2]) + } `, + ); const vectorFromOrigin = this.compute3SectorIntersection(breakEdges[i0], breakEdges[i1], breakEdges[i2]); if (vectorFromOrigin !== undefined) { if (vertexXYZ.distance(vectorFromOrigin) < maxVertexMove) { - this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], - (node: HalfEdge, properties: SectorOffsetProperties) => { - properties.setXYAndZ(vectorFromOrigin); - node.setMask(this._offsetCoordinatesReassigned); - }); + this.announceNodeAndSectorPropertiesInSmoothSector(breakEdges[i1], (node: HalfEdge, properties: SectorOffsetProperties) => { + properties.setXYAndZ(vectorFromOrigin); + node.setMask(this._offsetCoordinatesReassigned); + }); } } } @@ -1120,9 +1177,7 @@ export class OffsetMeshContext { }); } // return true if any of these nodes is "inside" the sling at the end of a chamfer. - private isInsideSling(node0: HalfEdge, - node1?: HalfEdge, - node2?: HalfEdge): boolean { + private isInsideSling(node0: HalfEdge, node1?: HalfEdge, node2?: HalfEdge): boolean { return node0.isMaskSet(this._insideChamferSling) || (node1 !== undefined && node1.isMaskSet(this._insideChamferSling)) || (node2 !== undefined && node2.isMaskSet(this._insideChamferSling)); @@ -1133,16 +1188,13 @@ export class OffsetMeshContext { || node0.isMaskSet(this._insideOfChamferFace) || node0.isMaskSet(this._outsideEndOfChamferFace); } - private isOffsetAssigned(node0: HalfEdge, - node1?: HalfEdge, - node2?: HalfEdge): boolean { + private isOffsetAssigned(node0: HalfEdge, node1?: HalfEdge, node2?: HalfEdge): boolean { return node0.isMaskSet(this._offsetCoordinatesReassigned) || (node1 !== undefined && node1.isMaskSet(this._offsetCoordinatesReassigned)) || (node2 !== undefined && node2.isMaskSet(this._offsetCoordinatesReassigned)); } /** - * * @param sourceNode node with good xyz * @param destinationStartNode first of a sequence of nodes to set (delimited by masks) * @param description string for debug @@ -1157,10 +1209,9 @@ export class OffsetMeshContext { if (OffsetMeshContext.stringDebugFunction !== undefined) OffsetMeshContext.stringDebugFunction(` ${description} ${this.inspectMasks(sourceNode)} to ${this.inspectMasks(destinationStartNode)}} `); SectorOffsetProperties.getSectorPointAtHalfEdge(sourceNode, workPoint, undefined); - this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, - (node: HalfEdge, properties: SectorOffsetProperties) => { - properties.setXYAndZ(workPoint); - node.setMask(this._offsetCoordinatesReassigned); - }); + this.announceNodeAndSectorPropertiesInSmoothSector(destinationStartNode, (node: HalfEdge, properties: SectorOffsetProperties) => { + properties.setXYAndZ(workPoint); + node.setMask(this._offsetCoordinatesReassigned); + }); } } diff --git a/core/geometry/src/polyface/multiclip/RangeSearch.ts b/core/geometry/src/polyface/multiclip/RangeSearch.ts index 8c7a3473d460..98d96223fe0f 100644 --- a/core/geometry/src/polyface/multiclip/RangeSearch.ts +++ b/core/geometry/src/polyface/multiclip/RangeSearch.ts @@ -22,12 +22,26 @@ export class RangeSearch { /** the "representative range size"is the mean range size plus this number of standard deviations */ public static readonly defaultStandardDeviationAdjustment = 1.0; /** Based on range count and distribution, return an object which can answer 2d range queries */ - public static create2dSearcherForRangeLengthData(rangeLengthData: RangeLengthData, rangesPerBlockEdge: number = RangeSearch.defaultRangesPerBlockEdge, standardDeviationAdjustment: number = RangeSearch.defaultStandardDeviationAdjustment): Range2dSearchInterface | undefined { + public static create2dSearcherForRangeLengthData( + rangeLengthData: RangeLengthData, + rangesPerBlockEdge: number = RangeSearch.defaultRangesPerBlockEdge, + standardDeviationAdjustment: number = RangeSearch.defaultStandardDeviationAdjustment, + ): Range2dSearchInterface | undefined { // for smallish sets, just linear search . . .. if (rangeLengthData.xSums.count < RangeSearch.smallCountLimit) return new LinearSearchRange2dArray(); - const numXBlock = this.estimateGridBlockCount(rangeLengthData.range.xLength(), rangeLengthData.xSums, rangesPerBlockEdge, standardDeviationAdjustment); - const numYBlock = this.estimateGridBlockCount(rangeLengthData.range.yLength(), rangeLengthData.ySums, rangesPerBlockEdge, standardDeviationAdjustment); + const numXBlock = this.estimateGridBlockCount( + rangeLengthData.range.xLength(), + rangeLengthData.xSums, + rangesPerBlockEdge, + standardDeviationAdjustment, + ); + const numYBlock = this.estimateGridBlockCount( + rangeLengthData.range.yLength(), + rangeLengthData.ySums, + rangesPerBlockEdge, + standardDeviationAdjustment, + ); if (numXBlock < 2 && numYBlock < 2) return new LinearSearchRange2dArray(); return GriddedRaggedRange2dSetWithOverflow.create(Range2d.createFrom(rangeLengthData.range), numXBlock, numYBlock); @@ -41,7 +55,12 @@ export class RangeSearch { * @param standardDeviationAdjustment the number of standard deviations above the mean to be applied to convert mean to representative length. Typically 0 to 1. * @returns number of blocks in grid. */ - public static estimateGridBlockCount(totalLength: number, sums: UsageSums, rangesPerBlockEdge: number = RangeSearch.defaultRangesPerBlockEdge, standardDeviationAdjustment: number = RangeSearch.defaultStandardDeviationAdjustment): number { + public static estimateGridBlockCount( + totalLength: number, + sums: UsageSums, + rangesPerBlockEdge: number = RangeSearch.defaultRangesPerBlockEdge, + standardDeviationAdjustment: number = RangeSearch.defaultStandardDeviationAdjustment, + ): number { if (sums.count < 1) return 1; const representativeRangeLength = rangesPerBlockEdge * (sums.mean + standardDeviationAdjustment * sums.standardDeviation); diff --git a/core/geometry/src/polyface/multiclip/SweepLineStringToFacetContext.ts b/core/geometry/src/polyface/multiclip/SweepLineStringToFacetContext.ts index 9309b9cd5f83..7eccbac932a8 100644 --- a/core/geometry/src/polyface/multiclip/SweepLineStringToFacetContext.ts +++ b/core/geometry/src/polyface/multiclip/SweepLineStringToFacetContext.ts @@ -6,18 +6,18 @@ * @module Polyface */ -import { Transform } from "../../geometry3d/Transform"; +import { ClipPlane } from "../../clipping/ClipPlane"; +import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; +import { Geometry } from "../../Geometry"; import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; +import { Matrix3d } from "../../geometry3d/Matrix3d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { Segment1d } from "../../geometry3d/Segment1d"; -import { AnnounceDrapePanel } from "../PolyfaceQuery"; +import { IndexedXYZCollectionPolygonOps, Point3dArrayPolygonOps } from "../../geometry3d/PolygonOps"; import { Range3d } from "../../geometry3d/Range"; -import { Geometry } from "../../Geometry"; +import { Segment1d } from "../../geometry3d/Segment1d"; +import { Transform } from "../../geometry3d/Transform"; import { Polyface } from "../Polyface"; -import { ClipPlane } from "../../clipping/ClipPlane"; -import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; -import { IndexedXYZCollectionPolygonOps, Point3dArrayPolygonOps } from "../../geometry3d/PolygonOps"; -import { Matrix3d } from "../../geometry3d/Matrix3d"; +import { AnnounceDrapePanel } from "../PolyfaceQuery"; export class SweepLineStringToFacetContext { private _spacePoints: GrowableXYZArray; @@ -69,11 +69,14 @@ export class SweepLineStringToFacetContext { frame.multiplyInversePoint3d(this._segmentPoint1, this._localSegmentPoint1); this._clipFractions.set(0, 1); /** (x,y,1-x-y) are barycentric coordinates in the triangle !!! */ - if (this._clipFractions.clipBy01FunctionValuesPositive(this._localSegmentPoint0.x, this._localSegmentPoint1.x) + if ( + this._clipFractions.clipBy01FunctionValuesPositive(this._localSegmentPoint0.x, this._localSegmentPoint1.x) && this._clipFractions.clipBy01FunctionValuesPositive(this._localSegmentPoint0.y, this._localSegmentPoint1.y) && this._clipFractions.clipBy01FunctionValuesPositive( 1 - this._localSegmentPoint0.x - this._localSegmentPoint0.y, - 1 - this._localSegmentPoint1.x - this._localSegmentPoint1.y)) { + 1 - this._localSegmentPoint1.x - this._localSegmentPoint1.y, + ) + ) { /* project the local segment point to the plane. */ workCounter++; const localClippedPointA = this._localSegmentPoint0.interpolate(this._clipFractions.x0, this._localSegmentPoint1); @@ -87,12 +90,14 @@ export class SweepLineStringToFacetContext { if (splitParameter !== undefined && splitParameter > this._clipFractions.x0 && splitParameter < this._clipFractions.x1) { workCounter++; const piercePointX = this._segmentPoint0.interpolate(splitParameter, this._segmentPoint1); - const piercePointY = piercePointX.clone(); // so points are distinct for the two triangle announcements. + const piercePointY = piercePointX.clone(); // so points are distinct for the two triangle announcements. announce(this._spacePoints, i1 - 1, polyface, readIndex, [worldClippedPointA, piercePointX, planePointA], 2, 1); announce(this._spacePoints, i1 - 1, polyface, readIndex, [worldClippedPointB, piercePointY, planePointB], 1, 2); - } else if (this._localSegmentPoint0.z > 0) { // segment is entirely above + } else if (this._localSegmentPoint0.z > 0) { // segment is entirely above announce(this._spacePoints, i1 - 1, polyface, readIndex, [worldClippedPointA, worldClippedPointB, planePointB, planePointA], 3, 2); - } else // segment is entirely under + } + // segment is entirely under + else announce(this._spacePoints, i1 - 1, polyface, readIndex, [worldClippedPointB, worldClippedPointA, planePointA, planePointB], 2, 3); } } @@ -147,12 +152,12 @@ export class EdgeClipData { IndexedXYZCollectionPolygonOps.polygonPlaneCrossings(this.edgePlane, polygon, this._crossingPoints); if (this._crossingPoints.length === 2) { // use the end planes to clip the [0,1] swept edge to [f0,f1] - this.clip.announceClippedSegmentIntervals(0, 1, this._crossingPoints[0], this._crossingPoints[1], - (f0: number, f1: number) => { - announceEdge(this._crossingPoints[0].interpolate(f0, this._crossingPoints[1]), - this._crossingPoints[0].interpolate(f1, this._crossingPoints[1])); - }, - ); + this.clip.announceClippedSegmentIntervals(0, 1, this._crossingPoints[0], this._crossingPoints[1], (f0: number, f1: number) => { + announceEdge( + this._crossingPoints[0].interpolate(f0, this._crossingPoints[1]), + this._crossingPoints[0].interpolate(f1, this._crossingPoints[1]), + ); + }); } } } diff --git a/core/geometry/src/polyface/multiclip/XYPointBuckets.ts b/core/geometry/src/polyface/multiclip/XYPointBuckets.ts index dc17726f0e96..f02afb0bef78 100644 --- a/core/geometry/src/polyface/multiclip/XYPointBuckets.ts +++ b/core/geometry/src/polyface/multiclip/XYPointBuckets.ts @@ -39,9 +39,13 @@ export class XYIndexGrid { } } /** Return the number of x edges in the grid */ - public get numXEdge(): number { return this._numXEdge; } + public get numXEdge(): number { + return this._numXEdge; + } /** Return the number of y edges in the grid */ - public get numYEdge(): number { return this._numYEdge; } + public get numYEdge(): number { + return this._numYEdge; + } /** Return the `i` index of cells containing x coordinate */ public xIndex(x: number): number { @@ -154,7 +158,9 @@ export class XYPointBuckets { private _points: IndexedXYZCollection; private _buckets: XYIndexGrid; /** Return the underlying grid with indices recorded by block */ - public get indexGrid(): XYIndexGrid { return this._buckets; } + public get indexGrid(): XYIndexGrid { + return this._buckets; + } private constructor(points: IndexedXYZCollection, buckets: XYIndexGrid) { this._points = points; this._buckets = buckets; @@ -196,9 +202,10 @@ export class XYPointBuckets { const x = this._points.getXAtUncheckedPointIndex(k); const y = this._points.getYAtUncheckedPointIndex(k); const z = this._points.getZAtUncheckedPointIndex(k); - if (range.containsXY(x, y)) + if (range.containsXY(x, y)) { if (!announce(k, x, y, z)) return; + } } } } diff --git a/core/geometry/src/serialization/BGFBAccessors.ts b/core/geometry/src/serialization/BGFBAccessors.ts index f7ba05b167f1..b42c7a070240 100644 --- a/core/geometry/src/serialization/BGFBAccessors.ts +++ b/core/geometry/src/serialization/BGFBAccessors.ts @@ -24,7 +24,7 @@ export namespace BGFBAccessors { */ export enum LoopTypeEnum { Parity = 1, - InteriorToLeft = 2 + InteriorToLeft = 2, } /** @@ -52,7 +52,7 @@ export namespace BGFBAccessors { tagPointString = 18, tagAkimaCurve = 19, tagCatenaryCurve = 20, - tagPartialCurve = 21 + tagPartialCurve = 21, } /** @@ -108,7 +108,6 @@ export namespace BGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** * @constructor @@ -190,7 +189,6 @@ export namespace BGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** * @constructor @@ -236,7 +234,6 @@ export namespace BGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** * @constructor @@ -291,7 +288,6 @@ export namespace BGFBAccessors { builder.writeFloat64(x); return builder.offset(); } - } /** * @constructor @@ -328,7 +324,6 @@ export namespace BGFBAccessors { builder.writeFloat64(degrees); return builder.offset(); } - } /** * @constructor @@ -440,7 +435,20 @@ export namespace BGFBAccessors { * @param number sweepRadians * @returns flatbuffers.Offset */ - static createDEllipse3d(builder: flatbuffers.Builder, centerX: number, centerY: number, centerZ: number, vector0X: number, vector0Y: number, vector0Z: number, vector90X: number, vector90Y: number, vector90Z: number, startRadians: number, sweepRadians: number): flatbuffers.Offset { + static createDEllipse3d( + builder: flatbuffers.Builder, + centerX: number, + centerY: number, + centerZ: number, + vector0X: number, + vector0Y: number, + vector0Z: number, + vector90X: number, + vector90Y: number, + vector90Z: number, + startRadians: number, + sweepRadians: number, + ): flatbuffers.Offset { builder.prep(8, 88); builder.writeFloat64(sweepRadians); builder.writeFloat64(startRadians); @@ -455,7 +463,6 @@ export namespace BGFBAccessors { builder.writeFloat64(centerX); return builder.offset(); } - } /** * @constructor @@ -527,7 +534,15 @@ export namespace BGFBAccessors { * @param number point1Z * @returns flatbuffers.Offset */ - static createDSegment3d(builder: flatbuffers.Builder, point0X: number, point0Y: number, point0Z: number, point1X: number, point1Y: number, point1Z: number): flatbuffers.Offset { + static createDSegment3d( + builder: flatbuffers.Builder, + point0X: number, + point0Y: number, + point0Z: number, + point1X: number, + point1Y: number, + point1Z: number, + ): flatbuffers.Offset { builder.prep(8, 48); builder.writeFloat64(point1Z); builder.writeFloat64(point1Y); @@ -537,7 +552,6 @@ export namespace BGFBAccessors { builder.writeFloat64(point0X); return builder.offset(); } - } /** * @constructor @@ -657,7 +671,21 @@ export namespace BGFBAccessors { * @param number azw * @returns flatbuffers.Offset */ - static createDTransform3d(builder: flatbuffers.Builder, axx: number, axy: number, axz: number, axw: number, ayx: number, ayy: number, ayz: number, ayw: number, azx: number, azy: number, azz: number, azw: number): flatbuffers.Offset { + static createDTransform3d( + builder: flatbuffers.Builder, + axx: number, + axy: number, + axz: number, + axw: number, + ayx: number, + ayy: number, + ayz: number, + ayw: number, + azx: number, + azy: number, + azz: number, + azw: number, + ): flatbuffers.Offset { builder.prep(8, 96); builder.writeFloat64(azw); builder.writeFloat64(azz); @@ -673,7 +701,6 @@ export namespace BGFBAccessors { builder.writeFloat64(axx); return builder.offset(); } - } /** * @constructor @@ -833,7 +860,26 @@ export namespace BGFBAccessors { * @param boolean capped * @returns flatbuffers.Offset */ - static createDgnBoxDetail(builder: flatbuffers.Builder, baseOriginX: number, baseOriginY: number, baseOriginZ: number, topOriginX: number, topOriginY: number, topOriginZ: number, vectorXX: number, vectorXY: number, vectorXZ: number, vectorYX: number, vectorYY: number, vectorYZ: number, baseX: number, baseY: number, topX: number, topY: number, capped: boolean): flatbuffers.Offset { + static createDgnBoxDetail( + builder: flatbuffers.Builder, + baseOriginX: number, + baseOriginY: number, + baseOriginZ: number, + topOriginX: number, + topOriginY: number, + topOriginZ: number, + vectorXX: number, + vectorXY: number, + vectorXZ: number, + vectorYX: number, + vectorYY: number, + vectorYZ: number, + baseX: number, + baseY: number, + topX: number, + topY: number, + capped: boolean, + ): flatbuffers.Offset { builder.prep(8, 136); builder.pad(7); builder.writeInt8(+capped); @@ -855,7 +901,6 @@ export namespace BGFBAccessors { builder.writeFloat64(baseOriginX); return builder.offset(); } - } /** * @constructor @@ -923,7 +968,24 @@ export namespace BGFBAccessors { * @param boolean capped * @returns flatbuffers.Offset */ - static createDgnSphereDetail(builder: flatbuffers.Builder, localToWorld_axx: number, localToWorld_axy: number, localToWorld_axz: number, localToWorld_axw: number, localToWorld_ayx: number, localToWorld_ayy: number, localToWorld_ayz: number, localToWorld_ayw: number, localToWorld_azx: number, localToWorld_azy: number, localToWorld_azz: number, localToWorld_azw: number, startLatitudeRadians: number, latitudeSweepRadians: number, capped: boolean): flatbuffers.Offset { + static createDgnSphereDetail( + builder: flatbuffers.Builder, + localToWorld_axx: number, + localToWorld_axy: number, + localToWorld_axz: number, + localToWorld_axw: number, + localToWorld_ayx: number, + localToWorld_ayy: number, + localToWorld_ayz: number, + localToWorld_ayw: number, + localToWorld_azx: number, + localToWorld_azy: number, + localToWorld_azz: number, + localToWorld_azw: number, + startLatitudeRadians: number, + latitudeSweepRadians: number, + capped: boolean, + ): flatbuffers.Offset { builder.prep(8, 120); builder.pad(7); builder.writeInt8(+capped); @@ -944,7 +1006,6 @@ export namespace BGFBAccessors { builder.writeFloat64(localToWorld_axx); return builder.offset(); } - } /** * @constructor @@ -1088,7 +1149,24 @@ export namespace BGFBAccessors { * @param boolean capped * @returns flatbuffers.Offset */ - static createDgnConeDetail(builder: flatbuffers.Builder, centerAX: number, centerAY: number, centerAZ: number, centerBX: number, centerBY: number, centerBZ: number, vector0X: number, vector0Y: number, vector0Z: number, vector90X: number, vector90Y: number, vector90Z: number, radiusA: number, radiusB: number, capped: boolean): flatbuffers.Offset { + static createDgnConeDetail( + builder: flatbuffers.Builder, + centerAX: number, + centerAY: number, + centerAZ: number, + centerBX: number, + centerBY: number, + centerBZ: number, + vector0X: number, + vector0Y: number, + vector0Z: number, + vector90X: number, + vector90Y: number, + vector90Z: number, + radiusA: number, + radiusB: number, + capped: boolean, + ): flatbuffers.Offset { builder.prep(8, 120); builder.pad(7); builder.writeInt8(+capped); @@ -1108,7 +1186,6 @@ export namespace BGFBAccessors { builder.writeFloat64(centerAX); return builder.offset(); } - } /** * @constructor @@ -1236,7 +1313,22 @@ export namespace BGFBAccessors { * @param boolean capped * @returns flatbuffers.Offset */ - static createDgnTorusPipeDetail(builder: flatbuffers.Builder, centerX: number, centerY: number, centerZ: number, vectorXX: number, vectorXY: number, vectorXZ: number, vectorYX: number, vectorYY: number, vectorYZ: number, majorRadius: number, minorRadius: number, sweepRadians: number, capped: boolean): flatbuffers.Offset { + static createDgnTorusPipeDetail( + builder: flatbuffers.Builder, + centerX: number, + centerY: number, + centerZ: number, + vectorXX: number, + vectorXY: number, + vectorXZ: number, + vectorYX: number, + vectorYY: number, + vectorYZ: number, + majorRadius: number, + minorRadius: number, + sweepRadians: number, + capped: boolean, + ): flatbuffers.Offset { builder.prep(8, 104); builder.pad(7); builder.writeInt8(+capped); @@ -1254,7 +1346,6 @@ export namespace BGFBAccessors { builder.writeFloat64(centerX); return builder.offset(); } - } /** * @constructor @@ -1391,7 +1482,13 @@ export namespace BGFBAccessors { */ pointsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1504,7 +1601,13 @@ export namespace BGFBAccessors { */ pointsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1709,7 +1812,13 @@ export namespace BGFBAccessors { */ polesArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1734,7 +1843,13 @@ export namespace BGFBAccessors { */ weightsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1759,7 +1874,13 @@ export namespace BGFBAccessors { */ knotsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 12); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -1881,7 +2002,14 @@ export namespace BGFBAccessors { return offset; } - static createBsplineCurve(builder: flatbuffers.Builder, order: number, closed: boolean, polesOffset: flatbuffers.Offset, weightsOffset: flatbuffers.Offset, knotsOffset: flatbuffers.Offset): flatbuffers.Offset { + static createBsplineCurve( + builder: flatbuffers.Builder, + order: number, + closed: boolean, + polesOffset: flatbuffers.Offset, + weightsOffset: flatbuffers.Offset, + knotsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { BsplineCurve.startBsplineCurve(builder); BsplineCurve.addOrder(builder, order); BsplineCurve.addClosed(builder, closed); @@ -2016,7 +2144,13 @@ export namespace BGFBAccessors { */ fitPointsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 20); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2041,7 +2175,13 @@ export namespace BGFBAccessors { */ knotsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 22); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2182,7 +2322,19 @@ export namespace BGFBAccessors { return offset; } - static createInterpolationCurve(builder: flatbuffers.Builder, order: number, closed: boolean, isChordLenKnots: number, isColinearTangents: number, isChordLenTangents: number, isNaturalTangents: number, startTangentOffset: flatbuffers.Offset, endTangentOffset: flatbuffers.Offset, fitPointsOffset: flatbuffers.Offset, knotsOffset: flatbuffers.Offset): flatbuffers.Offset { + static createInterpolationCurve( + builder: flatbuffers.Builder, + order: number, + closed: boolean, + isChordLenKnots: number, + isColinearTangents: number, + isChordLenTangents: number, + isNaturalTangents: number, + startTangentOffset: flatbuffers.Offset, + endTangentOffset: flatbuffers.Offset, + fitPointsOffset: flatbuffers.Offset, + knotsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { InterpolationCurve.startInterpolationCurve(builder); InterpolationCurve.addOrder(builder, order); InterpolationCurve.addClosed(builder, closed); @@ -2256,7 +2408,13 @@ export namespace BGFBAccessors { */ pointsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2462,7 +2620,15 @@ export namespace BGFBAccessors { return offset; } - static createCatenaryCurve(builder: flatbuffers.Builder, a: number, originOffset: flatbuffers.Offset, vectorUOffset: flatbuffers.Offset, vectorVOffset: flatbuffers.Offset, x0: number, x1: number): flatbuffers.Offset { + static createCatenaryCurve( + builder: flatbuffers.Builder, + a: number, + originOffset: flatbuffers.Offset, + vectorUOffset: flatbuffers.Offset, + vectorVOffset: flatbuffers.Offset, + x0: number, + x1: number, + ): flatbuffers.Offset { CatenaryCurve.startCatenaryCurve(builder); CatenaryCurve.addA(builder, a); CatenaryCurve.addOrigin(builder, originOffset); @@ -2575,7 +2741,12 @@ export namespace BGFBAccessors { return offset; } - static createPartialCurve(builder: flatbuffers.Builder, fraction0: number, fraction1: number, targetOffset: flatbuffers.Offset): flatbuffers.Offset { + static createPartialCurve( + builder: flatbuffers.Builder, + fraction0: number, + fraction1: number, + targetOffset: flatbuffers.Offset, + ): flatbuffers.Offset { PartialCurve.startPartialCurve(builder); PartialCurve.addFraction0(builder, fraction0); PartialCurve.addFraction1(builder, fraction1); @@ -2666,7 +2837,13 @@ export namespace BGFBAccessors { */ bytesArray(): Uint8Array | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Uint8Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint8Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -2738,7 +2915,13 @@ export namespace BGFBAccessors { return offset; } - static createCurvePrimitiveId(builder: flatbuffers.Builder, type: number, geomIndex: number, partIndex: number, bytesOffset: flatbuffers.Offset): flatbuffers.Offset { + static createCurvePrimitiveId( + builder: flatbuffers.Builder, + type: number, + geomIndex: number, + partIndex: number, + bytesOffset: flatbuffers.Offset, + ): flatbuffers.Offset { CurvePrimitiveId.startCurvePrimitiveId(builder); CurvePrimitiveId.addType(builder, type); CurvePrimitiveId.addGeomIndex(builder, geomIndex); @@ -2799,7 +2982,9 @@ export namespace BGFBAccessors { */ curves(index: number, obj?: VariantGeometry): VariantGeometry | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new VariantGeometry()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; + return offset + ? (obj || new VariantGeometry()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) + : null; } /** @@ -2914,7 +3099,9 @@ export namespace BGFBAccessors { */ members(index: number, obj?: VariantGeometry): VariantGeometry | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? (obj || new VariantGeometry()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; + return offset + ? (obj || new VariantGeometry()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) + : null; } /** @@ -3035,7 +3222,13 @@ export namespace BGFBAccessors { */ polesArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -3060,7 +3253,13 @@ export namespace BGFBAccessors { */ weightsArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -3085,7 +3284,13 @@ export namespace BGFBAccessors { */ knotsUArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -3110,7 +3315,13 @@ export namespace BGFBAccessors { */ knotsVArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -3406,7 +3617,23 @@ export namespace BGFBAccessors { return offset; } - static createBsplineSurface(builder: flatbuffers.Builder, polesOffset: flatbuffers.Offset, weightsOffset: flatbuffers.Offset, knotsUOffset: flatbuffers.Offset, knotsVOffset: flatbuffers.Offset, numPolesU: number, numPolesV: number, orderU: number, orderV: number, numRulesU: number, numRulesV: number, holeOrigin: number, boundariesOffset: flatbuffers.Offset, closedU: boolean, closedV: boolean): flatbuffers.Offset { + static createBsplineSurface( + builder: flatbuffers.Builder, + polesOffset: flatbuffers.Offset, + weightsOffset: flatbuffers.Offset, + knotsUOffset: flatbuffers.Offset, + knotsVOffset: flatbuffers.Offset, + numPolesU: number, + numPolesV: number, + orderU: number, + orderV: number, + numRulesU: number, + numRulesV: number, + holeOrigin: number, + boundariesOffset: flatbuffers.Offset, + closedU: boolean, + closedV: boolean, + ): flatbuffers.Offset { BsplineSurface.startBsplineSurface(builder); BsplineSurface.addPoles(builder, polesOffset); BsplineSurface.addWeights(builder, weightsOffset); @@ -3832,7 +4059,12 @@ export namespace BGFBAccessors { return offset; } - static createDgnExtrusion(builder: flatbuffers.Builder, baseCurveOffset: flatbuffers.Offset, extrusionVectorOffset: flatbuffers.Offset, capped: boolean): flatbuffers.Offset { + static createDgnExtrusion( + builder: flatbuffers.Builder, + baseCurveOffset: flatbuffers.Offset, + extrusionVectorOffset: flatbuffers.Offset, + capped: boolean, + ): flatbuffers.Offset { DgnExtrusion.startDgnExtrusion(builder); DgnExtrusion.addBaseCurve(builder, baseCurveOffset); DgnExtrusion.addExtrusionVector(builder, extrusionVectorOffset); @@ -3975,7 +4207,14 @@ export namespace BGFBAccessors { return offset; } - static createDgnRotationalSweep(builder: flatbuffers.Builder, baseCurveOffset: flatbuffers.Offset, axisOffset: flatbuffers.Offset, sweepRadians: number, numVRules: number, capped: boolean): flatbuffers.Offset { + static createDgnRotationalSweep( + builder: flatbuffers.Builder, + baseCurveOffset: flatbuffers.Offset, + axisOffset: flatbuffers.Offset, + sweepRadians: number, + numVRules: number, + capped: boolean, + ): flatbuffers.Offset { DgnRotationalSweep.startDgnRotationalSweep(builder); DgnRotationalSweep.addBaseCurve(builder, baseCurveOffset); DgnRotationalSweep.addAxis(builder, axisOffset); @@ -4175,7 +4414,13 @@ export namespace BGFBAccessors { */ valuesArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4312,7 +4557,9 @@ export namespace BGFBAccessors { */ data(index: number, obj?: PolyfaceAuxChannelData): PolyfaceAuxChannelData | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? (obj || new PolyfaceAuxChannelData()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; + return offset + ? (obj || new PolyfaceAuxChannelData()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) + : null; } /** @@ -4392,7 +4639,13 @@ export namespace BGFBAccessors { return offset; } - static createPolyfaceAuxChannel(builder: flatbuffers.Builder, dataType: number, nameOffset: flatbuffers.Offset, inputNameOffset: flatbuffers.Offset, dataOffset: flatbuffers.Offset): flatbuffers.Offset { + static createPolyfaceAuxChannel( + builder: flatbuffers.Builder, + dataType: number, + nameOffset: flatbuffers.Offset, + inputNameOffset: flatbuffers.Offset, + dataOffset: flatbuffers.Offset, + ): flatbuffers.Offset { PolyfaceAuxChannel.startPolyfaceAuxChannel(builder); PolyfaceAuxChannel.addDataType(builder, dataType); PolyfaceAuxChannel.addName(builder, nameOffset); @@ -4460,7 +4713,13 @@ export namespace BGFBAccessors { */ indicesArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4470,7 +4729,9 @@ export namespace BGFBAccessors { */ channels(index: number, obj?: PolyfaceAuxChannel): PolyfaceAuxChannel | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? (obj || new PolyfaceAuxChannel()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null; + return offset + ? (obj || new PolyfaceAuxChannel()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) + : null; } /** @@ -4555,7 +4816,11 @@ export namespace BGFBAccessors { return offset; } - static createPolyfaceAuxData(builder: flatbuffers.Builder, indicesOffset: flatbuffers.Offset, channelsOffset: flatbuffers.Offset): flatbuffers.Offset { + static createPolyfaceAuxData( + builder: flatbuffers.Builder, + indicesOffset: flatbuffers.Offset, + channelsOffset: flatbuffers.Offset, + ): flatbuffers.Offset { PolyfaceAuxData.startPolyfaceAuxData(builder); PolyfaceAuxData.addIndices(builder, indicesOffset); PolyfaceAuxData.addChannels(builder, channelsOffset); @@ -4637,7 +4902,13 @@ export namespace BGFBAccessors { */ intDataArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4662,7 +4933,13 @@ export namespace BGFBAccessors { */ doubleDataArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4755,7 +5032,13 @@ export namespace BGFBAccessors { return offset; } - static createTaggedNumericData(builder: flatbuffers.Builder, tagA: number, tagB: number, intDataOffset: flatbuffers.Offset, doubleDataOffset: flatbuffers.Offset): flatbuffers.Offset { + static createTaggedNumericData( + builder: flatbuffers.Builder, + tagA: number, + tagB: number, + intDataOffset: flatbuffers.Offset, + doubleDataOffset: flatbuffers.Offset, + ): flatbuffers.Offset { TaggedNumericData.startTaggedNumericData(builder); TaggedNumericData.addTagA(builder, tagA); TaggedNumericData.addTagB(builder, tagB); @@ -4823,7 +5106,13 @@ export namespace BGFBAccessors { */ pointArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4848,7 +5137,13 @@ export namespace BGFBAccessors { */ paramArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4873,7 +5168,13 @@ export namespace BGFBAccessors { */ normalArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 8); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4898,7 +5199,13 @@ export namespace BGFBAccessors { */ doubleColorArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 10); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4923,7 +5230,13 @@ export namespace BGFBAccessors { */ intColorArray(): Uint32Array | null { const offset = this.bb!.__offset(this.bb_pos, 12); - return offset ? new Uint32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Uint32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4948,7 +5261,13 @@ export namespace BGFBAccessors { */ pointIndexArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 14); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4973,7 +5292,13 @@ export namespace BGFBAccessors { */ paramIndexArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 16); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -4998,7 +5323,13 @@ export namespace BGFBAccessors { */ normalIndexArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5023,7 +5354,13 @@ export namespace BGFBAccessors { */ colorIndexArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 20); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5048,7 +5385,13 @@ export namespace BGFBAccessors { */ colorTableArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 22); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5105,7 +5448,13 @@ export namespace BGFBAccessors { */ faceIndexArray(): Int32Array | null { const offset = this.bb!.__offset(this.bb_pos, 32); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Int32Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5130,7 +5479,13 @@ export namespace BGFBAccessors { */ faceDataArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 34); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5579,7 +5934,28 @@ export namespace BGFBAccessors { return offset; } - static createPolyface(builder: flatbuffers.Builder, pointOffset: flatbuffers.Offset, paramOffset: flatbuffers.Offset, normalOffset: flatbuffers.Offset, doubleColorOffset: flatbuffers.Offset, intColorOffset: flatbuffers.Offset, pointIndexOffset: flatbuffers.Offset, paramIndexOffset: flatbuffers.Offset, normalIndexOffset: flatbuffers.Offset, colorIndexOffset: flatbuffers.Offset, colorTableOffset: flatbuffers.Offset, numPerFace: number, numPerRow: number, meshStyle: number, twoSided: boolean, faceIndexOffset: flatbuffers.Offset, faceDataOffset: flatbuffers.Offset, auxDataOffset: flatbuffers.Offset, expectedClosure: number, taggedNumericDataOffset: flatbuffers.Offset): flatbuffers.Offset { + static createPolyface( + builder: flatbuffers.Builder, + pointOffset: flatbuffers.Offset, + paramOffset: flatbuffers.Offset, + normalOffset: flatbuffers.Offset, + doubleColorOffset: flatbuffers.Offset, + intColorOffset: flatbuffers.Offset, + pointIndexOffset: flatbuffers.Offset, + paramIndexOffset: flatbuffers.Offset, + normalIndexOffset: flatbuffers.Offset, + colorIndexOffset: flatbuffers.Offset, + colorTableOffset: flatbuffers.Offset, + numPerFace: number, + numPerRow: number, + meshStyle: number, + twoSided: boolean, + faceIndexOffset: flatbuffers.Offset, + faceDataOffset: flatbuffers.Offset, + auxDataOffset: flatbuffers.Offset, + expectedClosure: number, + taggedNumericDataOffset: flatbuffers.Offset, + ): flatbuffers.Offset { Polyface.startPolyface(builder); Polyface.addPoint(builder, pointOffset); Polyface.addParam(builder, paramOffset); @@ -5709,7 +6085,29 @@ export namespace BGFBAccessors { * @param number constructionHint * @returns flatbuffers.Offset */ - static createTransitionSpiralDetail(builder: flatbuffers.Builder, transform_axx: number, transform_axy: number, transform_axz: number, transform_axw: number, transform_ayx: number, transform_ayy: number, transform_ayz: number, transform_ayw: number, transform_azx: number, transform_azy: number, transform_azz: number, transform_azw: number, fractionA: number, fractionB: number, bearing0Radians: number, bearing1Radians: number, curvature0: number, curvature1: number, spiralType: number, constructionHint: number): flatbuffers.Offset { + static createTransitionSpiralDetail( + builder: flatbuffers.Builder, + transform_axx: number, + transform_axy: number, + transform_axz: number, + transform_axw: number, + transform_ayx: number, + transform_ayy: number, + transform_ayz: number, + transform_ayw: number, + transform_azx: number, + transform_azy: number, + transform_azz: number, + transform_azw: number, + fractionA: number, + fractionB: number, + bearing0Radians: number, + bearing1Radians: number, + curvature0: number, + curvature1: number, + spiralType: number, + constructionHint: number, + ): flatbuffers.Offset { builder.prep(8, 152); builder.writeInt32(constructionHint); builder.writeInt32(spiralType); @@ -5734,7 +6132,6 @@ export namespace BGFBAccessors { builder.writeFloat64(transform_axx); return builder.offset(); } - } /** * @constructor @@ -5806,7 +6203,15 @@ export namespace BGFBAccessors { * @param number intTag1 * @returns flatbuffers.Offset */ - static createDirectSpiralDetail(builder: flatbuffers.Builder, nominalLength: number, trueLength: number, doubleTag0: number, doubleTag1: number, intTag0: number, intTag1: number): flatbuffers.Offset { + static createDirectSpiralDetail( + builder: flatbuffers.Builder, + nominalLength: number, + trueLength: number, + doubleTag0: number, + doubleTag1: number, + intTag0: number, + intTag1: number, + ): flatbuffers.Offset { builder.prep(8, 48); builder.writeFloat64(intTag1); builder.writeFloat64(intTag0); @@ -5816,7 +6221,6 @@ export namespace BGFBAccessors { builder.writeFloat64(nominalLength); return builder.offset(); } - } /** * @constructor @@ -5886,7 +6290,13 @@ export namespace BGFBAccessors { */ extraDataArray(): Float64Array | null { const offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset + ? new Float64Array( + this.bb!.bytes().buffer, + this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), + this.bb!.__vector_len(this.bb_pos + offset), + ) + : null; } /** @@ -5959,7 +6369,12 @@ export namespace BGFBAccessors { return offset; } - static createTransitionSpiral(builder: flatbuffers.Builder, detailOffset: flatbuffers.Offset, extraDataOffset: flatbuffers.Offset, directDetailOffset: flatbuffers.Offset): flatbuffers.Offset { + static createTransitionSpiral( + builder: flatbuffers.Builder, + detailOffset: flatbuffers.Offset, + extraDataOffset: flatbuffers.Offset, + directDetailOffset: flatbuffers.Offset, + ): flatbuffers.Offset { TransitionSpiral.startTransitionSpiral(builder); TransitionSpiral.addDetail(builder, detailOffset); TransitionSpiral.addExtraData(builder, extraDataOffset); @@ -6070,7 +6485,12 @@ export namespace BGFBAccessors { return offset; } - static createVariantGeometry(builder: flatbuffers.Builder, geometryType: VariantGeometryUnion, geometryOffset: flatbuffers.Offset, tagOffset: flatbuffers.Offset): flatbuffers.Offset { + static createVariantGeometry( + builder: flatbuffers.Builder, + geometryType: VariantGeometryUnion, + geometryOffset: flatbuffers.Offset, + tagOffset: flatbuffers.Offset, + ): flatbuffers.Offset { VariantGeometry.startVariantGeometry(builder); VariantGeometry.addGeometryType(builder, geometryType); VariantGeometry.addGeometry(builder, geometryOffset); diff --git a/core/geometry/src/serialization/BGFBReader.ts b/core/geometry/src/serialization/BGFBReader.ts index 171dc1d32b85..87ff189f39dc 100644 --- a/core/geometry/src/serialization/BGFBReader.ts +++ b/core/geometry/src/serialization/BGFBReader.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { flatbuffers } from "flatbuffers"; import { assert } from "@itwin/core-bentley"; +import { flatbuffers } from "flatbuffers"; import { AkimaCurve3d, AkimaCurve3dOptions } from "../bspline/AkimaCurve3d"; import { BSplineCurve3d } from "../bspline/BSplineCurve"; import { BSplineCurve3dH } from "../bspline/BSplineCurve3dH"; @@ -83,11 +83,28 @@ export class BGFBReader { if (closedV) myData.vParams.closed = true; - if (SerializationHelpers.Import.prepareBSplineSurfaceData(myData, {jsonPoles: false})) { + if (SerializationHelpers.Import.prepareBSplineSurfaceData(myData, { jsonPoles: false })) { if (undefined === myData.weights) - newSurface = BSplineSurface3d.create(myData.poles as Float64Array, myData.uParams.numPoles, myData.uParams.order, myData.uParams.knots, myData.vParams.numPoles, myData.vParams.order, myData.vParams.knots); + newSurface = BSplineSurface3d.create( + myData.poles as Float64Array, + myData.uParams.numPoles, + myData.uParams.order, + myData.uParams.knots, + myData.vParams.numPoles, + myData.vParams.order, + myData.vParams.knots, + ); else - newSurface = BSplineSurface3dH.create(myData.poles as Float64Array, myData.weights as Float64Array, myData.uParams.numPoles, myData.uParams.order, myData.uParams.knots, myData.vParams.numPoles, myData.vParams.order, myData.vParams.knots); + newSurface = BSplineSurface3dH.create( + myData.poles as Float64Array, + myData.weights as Float64Array, + myData.uParams.numPoles, + myData.uParams.order, + myData.uParams.knots, + myData.vParams.numPoles, + myData.vParams.order, + myData.vParams.knots, + ); if (undefined !== newSurface) { if (undefined !== myData.uParams.wrapMode) @@ -102,13 +119,13 @@ export class BGFBReader { return newSurface; } - /** - * Extract an interpolating curve - * @param variant read position in the flat buffer. - */ + /** + * Extract an interpolating curve + * @param variant read position in the flat buffer. + */ public readInterpolationCurve3d(header: BGFBAccessors.InterpolationCurve): InterpolationCurve3d | undefined { const xyzArray = header.fitPointsArray(); - if (xyzArray instanceof Float64Array){ + if (xyzArray instanceof Float64Array) { const knots = header.knotsArray(); const options = new InterpolationCurve3dOptions(Point3dArray.clonePoint3dArray(xyzArray), knots ? NumberArray.create(knots) : undefined); const startTangent = header.startTangent(); @@ -119,27 +136,28 @@ export class BGFBReader { header.isChordLenKnots(), header.isColinearTangents(), header.isChordLenTangents(), - header.isNaturalTangents (), + header.isNaturalTangents(), startTangent !== null ? Vector3d.create(startTangent.x(), startTangent.y(), startTangent.z()) : undefined, - endTangent !== null ? Vector3d.create(endTangent.x(), endTangent.y(), endTangent.z()) : undefined); + endTangent !== null ? Vector3d.create(endTangent.x(), endTangent.y(), endTangent.z()) : undefined, + ); return InterpolationCurve3d.createCapture(options); } - return undefined; -} + return undefined; + } -/** - * Extract an akima curve - * @param variant read position in the flat buffer. - */ - public readAkimaCurve3d(header: BGFBAccessors.AkimaCurve): AkimaCurve3d | undefined { - const xyzArray = header.pointsArray(); - if (xyzArray instanceof Float64Array){ - const options = new AkimaCurve3dOptions(Point3dArray.clonePoint3dArray(xyzArray)); - return AkimaCurve3d.createCapture(options); + /** + * Extract an akima curve + * @param variant read position in the flat buffer. + */ + public readAkimaCurve3d(header: BGFBAccessors.AkimaCurve): AkimaCurve3d | undefined { + const xyzArray = header.pointsArray(); + if (xyzArray instanceof Float64Array) { + const options = new AkimaCurve3dOptions(Point3dArray.clonePoint3dArray(xyzArray)); + return AkimaCurve3d.createCapture(options); + } + return undefined; } -return undefined; -} -/** + /** * Extract a bspline curve * @param variant read position in the flat buffer. */ @@ -162,7 +180,7 @@ return undefined; newCurve = BSplineCurve3d.create(myData.poles, myData.params.knots, myData.params.order); } else { myData.weights = weightsArray; - if (SerializationHelpers.Import.prepareBSplineCurveData(myData, {jsonPoles: false})) + if (SerializationHelpers.Import.prepareBSplineCurveData(myData, { jsonPoles: false })) newCurve = BSplineCurve3dH.create({ xyz: myData.poles as Float64Array, weights: myData.weights }, myData.params.knots, myData.params.order); } @@ -188,33 +206,47 @@ return undefined; const bearing0Radians = detailHeader.bearing0Radians(); const bearing1Radians = detailHeader.bearing1Radians(); const fbTransform = detailHeader.transform(); - const localToWorld = fbTransform ? Transform.createRowValues( - fbTransform.axx(), fbTransform.axy(), fbTransform.axz(), fbTransform.axw(), - fbTransform.ayx(), fbTransform.ayy(), fbTransform.ayz(), fbTransform.ayw(), - fbTransform.azx(), fbTransform.azy(), fbTransform.azz(), fbTransform.azw()) : + const localToWorld = fbTransform ? + Transform.createRowValues( + fbTransform.axx(), + fbTransform.axy(), + fbTransform.axz(), + fbTransform.axw(), + fbTransform.ayx(), + fbTransform.ayy(), + fbTransform.ayz(), + fbTransform.ayw(), + fbTransform.azx(), + fbTransform.azy(), + fbTransform.azz(), + fbTransform.azw(), + ) : Transform.createIdentity(); - const activeFractionInterval = Segment1d.create(detailHeader.fractionA(), - detailHeader.fractionB()); + const activeFractionInterval = Segment1d.create(detailHeader.fractionA(), detailHeader.fractionB()); if (!directDetailHeader) { const integratedSpiral = IntegratedSpiral3d.createRadiusRadiusBearingBearing( Segment1d.create(IntegratedSpiral3d.curvatureToRadius(curvature0), IntegratedSpiral3d.curvatureToRadius(curvature1)), AngleSweep.createStartEndRadians(bearing0Radians, bearing1Radians), - activeFractionInterval, localToWorld, spiralTypeName); + activeFractionInterval, + localToWorld, + spiralTypeName, + ); if (integratedSpiral) return integratedSpiral; const radius0 = TransitionSpiral3d.curvatureToRadius(curvature0); const radius1 = TransitionSpiral3d.curvatureToRadius(curvature1); - const arcLength = TransitionSpiral3d.radiusRadiusSweepRadiansToArcLength(radius0, radius1, - bearing1Radians - bearing0Radians); + const arcLength = TransitionSpiral3d.radiusRadiusSweepRadiansToArcLength(radius0, radius1, bearing1Radians - bearing0Radians); const directSpiral = DirectSpiral3d.createFromLengthAndRadius( spiralTypeName!, - radius0, radius1, + radius0, + radius1, Angle.createRadians(bearing0Radians), - Angle.createRadians (bearing1Radians), + Angle.createRadians(bearing1Radians), arcLength, activeFractionInterval, - localToWorld); + localToWorld, + ); if (directSpiral) return directSpiral; } @@ -231,16 +263,28 @@ return undefined; const offsetToLineSegment = variant.geometry(new BGFBAccessors.LineSegment()); const offsetToCoordinates = offsetToLineSegment!.segment(); return LineSegment3d.createXYZXYZ( - offsetToCoordinates!.point0X(), offsetToCoordinates!.point0Y(), offsetToCoordinates!.point0Z(), - offsetToCoordinates!.point1X(), offsetToCoordinates!.point1Y(), offsetToCoordinates!.point1Z()); + offsetToCoordinates!.point0X(), + offsetToCoordinates!.point0Y(), + offsetToCoordinates!.point0Z(), + offsetToCoordinates!.point1X(), + offsetToCoordinates!.point1Y(), + offsetToCoordinates!.point1Z(), + ); } else if (geometryType === BGFBAccessors.VariantGeometryUnion.tagEllipticArc) { const offsetToEllipticArc = variant.geometry(new BGFBAccessors.EllipticArc()); const offsetToCoordinates = offsetToEllipticArc!.arc()!; return Arc3d.createXYZXYZXYZ( - offsetToCoordinates.centerX(), offsetToCoordinates.centerY(), offsetToCoordinates.centerZ(), - offsetToCoordinates.vector0X(), offsetToCoordinates.vector0Y(), offsetToCoordinates.vector0Z(), - offsetToCoordinates.vector90X(), offsetToCoordinates.vector90Y(), offsetToCoordinates.vector90Z(), - AngleSweep.createStartSweepRadians(offsetToCoordinates.startRadians(), offsetToCoordinates?.sweepRadians())); + offsetToCoordinates.centerX(), + offsetToCoordinates.centerY(), + offsetToCoordinates.centerZ(), + offsetToCoordinates.vector0X(), + offsetToCoordinates.vector0Y(), + offsetToCoordinates.vector0Z(), + offsetToCoordinates.vector90X(), + offsetToCoordinates.vector90Y(), + offsetToCoordinates.vector90Z(), + AngleSweep.createStartSweepRadians(offsetToCoordinates.startRadians(), offsetToCoordinates?.sweepRadians()), + ); } else if (geometryType === BGFBAccessors.VariantGeometryUnion.tagLineString) { const offsetToLineString = variant.geometry(new BGFBAccessors.LineString())!; const numCoordinates = offsetToLineString.pointsLength(); @@ -351,7 +395,7 @@ return undefined; if (0 === i) ++numZeroes; } - return {min, max, numZeroes}; + return { min, max, numZeroes }; } /** @@ -361,7 +405,10 @@ return undefined; * Typescript API previously wrote FlatBuffer PolyfaceAuxData indices as 0-based, unterminated; * heuristics are used herein to identify this legacy format so it can still be read. */ - public readPolyfaceAuxData(fbPolyface: BGFBAccessors.Polyface | null, fbAuxData: BGFBAccessors.PolyfaceAuxData | null): PolyfaceAuxData | undefined { + public readPolyfaceAuxData( + fbPolyface: BGFBAccessors.Polyface | null, + fbAuxData: BGFBAccessors.PolyfaceAuxData | null, + ): PolyfaceAuxData | undefined { if (!fbPolyface || !fbAuxData) return undefined; @@ -397,9 +444,13 @@ return undefined; const indices: number[] = []; if (isLegacy) - SerializationHelpers.announceZeroBasedIndicesWithExternalBlocking(fbAuxIndices, fbPointIndices, numPerFace, (i0: number) => { indices.push(i0); }); + SerializationHelpers.announceZeroBasedIndicesWithExternalBlocking(fbAuxIndices, fbPointIndices, numPerFace, (i0: number) => { + indices.push(i0); + }); else - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(fbAuxIndices, numPerFace, (i0: number) => { indices.push(i0); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(fbAuxIndices, numPerFace, (i0: number) => { + indices.push(i0); + }); if (indices.length + pointIndicesPadCount !== fbPointIndices.length) return undefined; const maxIndex = Math.max(...indices); @@ -430,7 +481,6 @@ return undefined; taggedNumericData.intData = []; for (const c of intDataArray) taggedNumericData.intData.push(c); - } if (doubleDataArray) { taggedNumericData.doubleData = []; @@ -479,27 +529,32 @@ return undefined; if (normalF64 && normalIndexI32) { for (let i = 0; i + 2 < normalF64.length; i += 3) polyface.addNormalXYZ(normalF64[i], normalF64[i + 1], normalF64[i + 2]); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(normalIndexI32, numPerFace, - (i: number) => { polyface.addNormalIndex(i); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(normalIndexI32, numPerFace, (i: number) => { + polyface.addNormalIndex(i); + }); } if (paramF64 && paramIndexI32) { for (let i = 0; i + 1 < paramF64.length; i += 2) polyface.addParamUV(paramF64[i], paramF64[i + 1]); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(paramIndexI32, numPerFace, - (i: number) => { polyface.addParamIndex(i); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(paramIndexI32, numPerFace, (i: number) => { + polyface.addParamIndex(i); + }); } if (intColorU32 && colorIndexI32) { for (const c of intColorU32) polyface.addColor(c); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(colorIndexI32, numPerFace, - (i: number) => { polyface.addColorIndex(i); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(colorIndexI32, numPerFace, (i: number) => { + polyface.addColorIndex(i); + }); } for (let i = 0; i + 2 < pointF64.length; i += 3) polyface.addPointXYZ(pointF64[i], pointF64[i + 1], pointF64[i + 2]); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(pointIndexI32, numPerFace, - (i: number, v?: boolean) => { polyface.addPointIndex(i, v); }, - () => { polyface.terminateFacet(false); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(pointIndexI32, numPerFace, (i: number, v?: boolean) => { + polyface.addPointIndex(i, v); + }, () => { + polyface.terminateFacet(false); + }); if (!polyface.validateAllIndices()) return undefined; @@ -507,11 +562,11 @@ return undefined; polyface.data.auxData = this.readPolyfaceAuxData(polyfaceHeader, polyfaceHeader.auxData()); if (taggedNumericDataOffset) { - const taggedNumericDataAccessor = nullToUndefined(taggedNumericDataOffset); - if (taggedNumericDataAccessor !== undefined) { - const taggedNumericData = this.readTaggedNumericData(taggedNumericDataAccessor); - if (taggedNumericData !== undefined) - polyface.data.setTaggedNumericData(taggedNumericData); + const taggedNumericDataAccessor = nullToUndefined(taggedNumericDataOffset); + if (taggedNumericDataAccessor !== undefined) { + const taggedNumericData = this.readTaggedNumericData(taggedNumericDataAccessor); + if (taggedNumericData !== undefined) + polyface.data.setTaggedNumericData(taggedNumericData); } } return polyface; @@ -541,9 +596,9 @@ return undefined; return collection; } /** - * Extract a curve collection - * @param variant read position in the flat buffer. - */ + * Extract a curve collection + * @param variant read position in the flat buffer. + */ public readCurveCollectionFromVariantGeometry(variant: BGFBAccessors.VariantGeometry): CurveCollection | undefined { const geometryType = variant.geometryType(); if (geometryType === BGFBAccessors.VariantGeometryUnion.tagCurveVector) { @@ -553,9 +608,9 @@ return undefined; return undefined; } /** - * Extract a curve collection - * @param variant read position in the flat buffer. - */ + * Extract a curve collection + * @param variant read position in the flat buffer. + */ public readSolidPrimitiveFromVariant(variant: BGFBAccessors.VariantGeometry): SolidPrimitive | undefined { const geometryType = variant.geometryType(); if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnBox) { @@ -566,20 +621,38 @@ return undefined; Vector3d.create(detail.vectorXX(), detail.vectorXY(), detail.vectorXZ()), Vector3d.create(detail.vectorYX(), detail.vectorYY(), detail.vectorYZ()), Point3d.create(detail.topOriginX(), detail.topOriginY(), detail.topOriginZ()), - detail.baseX(), detail.baseY(), detail.topX(), detail.topY(), - detail.capped()); - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnSphere) { + detail.baseX(), + detail.baseY(), + detail.topX(), + detail.topY(), + detail.capped(), + ); + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnSphere) { const header = variant.geometry(new BGFBAccessors.DgnSphere()); const detail = header!.detail()!; const lToWDetail = detail.localToWorld()!; const localToWorld = Transform.createRowValues( - lToWDetail.axx(), lToWDetail.axy(), lToWDetail.axz(), lToWDetail.axw(), - lToWDetail.ayx(), lToWDetail.ayy(), lToWDetail.ayz(), lToWDetail.ayw(), - lToWDetail.azx(), lToWDetail.azy(), lToWDetail.azz(), lToWDetail.azw()); - return Sphere.createEllipsoid(localToWorld, + lToWDetail.axx(), + lToWDetail.axy(), + lToWDetail.axz(), + lToWDetail.axw(), + lToWDetail.ayx(), + lToWDetail.ayy(), + lToWDetail.ayz(), + lToWDetail.ayw(), + lToWDetail.azx(), + lToWDetail.azy(), + lToWDetail.azz(), + lToWDetail.azw(), + ); + return Sphere.createEllipsoid( + localToWorld, AngleSweep.createStartSweepRadians(detail.startLatitudeRadians(), detail.latitudeSweepRadians()), - detail.capped()); - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnCone) { + detail.capped(), + ); + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnCone) { const header = variant.geometry(new BGFBAccessors.DgnCone()); const detail = header!.detail()!; const centerA = Point3d.create(detail.centerAX(), detail.centerAY(), detail.centerAZ()); @@ -589,7 +662,8 @@ return undefined; const radiusA = detail.radiusA(); const radiusB = detail.radiusB(); return Cone.createBaseAndTarget(centerA, centerB, vector0, vector90, radiusA, radiusB, detail.capped()); - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnTorusPipe) { + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnTorusPipe) { const header = variant.geometry(new BGFBAccessors.DgnTorusPipe())!; const detail = header.detail()!; const center = Point3d.create(detail.centerX(), detail.centerY(), detail.centerZ()); @@ -599,7 +673,8 @@ return undefined; const majorRadius = detail.majorRadius(); const minorRadius = detail.minorRadius(); return TorusPipe.createDgnTorusPipe(center, vectorX, vectorY, majorRadius, minorRadius, Angle.createRadians(sweepRadians), detail.capped()); - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnExtrusion) { + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnExtrusion) { const header = variant.geometry(new BGFBAccessors.DgnExtrusion())!; const dVector = new BGFBAccessors.DVector3d(); header.extrusionVector(dVector); @@ -609,7 +684,8 @@ return undefined; const contour = this.readCurveCollectionFromCurveVectorTable(baseCurve); return LinearSweep.create(contour, extrusionVector, header.capped()); } - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnRotationalSweep) { + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnRotationalSweep) { const header = variant.geometry(new BGFBAccessors.DgnRotationalSweep())!; const dAxis = new BGFBAccessors.DRay3d(); header.axis(dAxis); @@ -621,7 +697,8 @@ return undefined; const contour = this.readCurveCollectionFromCurveVectorTable(baseCurve); return RotationalSweep.create(contour, axis, sweepAngle, header.capped()); } - } if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep) { + } + if (geometryType === BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep) { const header = variant.geometry(new BGFBAccessors.DgnRuledSweep())!; const numCurves = header.curvesLength(); const contours: CurveCollection[] = []; @@ -652,52 +729,46 @@ return undefined; case BGFBAccessors.VariantGeometryUnion.tagBsplineCurve: case BGFBAccessors.VariantGeometryUnion.tagTransitionSpiral: case BGFBAccessors.VariantGeometryUnion.tagInterpolationCurve: - case BGFBAccessors.VariantGeometryUnion.tagAkimaCurve: - { - return this.readCurvePrimitiveFromVariant(variant); - } - case BGFBAccessors.VariantGeometryUnion.tagCurveVector: - { - return this.readCurveCollectionFromVariantGeometry(variant); - } - case BGFBAccessors.VariantGeometryUnion.tagPolyface: - { - return this.readPolyfaceFromVariant(variant); - } + case BGFBAccessors.VariantGeometryUnion.tagAkimaCurve: { + return this.readCurvePrimitiveFromVariant(variant); + } + case BGFBAccessors.VariantGeometryUnion.tagCurveVector: { + return this.readCurveCollectionFromVariantGeometry(variant); + } + case BGFBAccessors.VariantGeometryUnion.tagPolyface: { + return this.readPolyfaceFromVariant(variant); + } case BGFBAccessors.VariantGeometryUnion.tagDgnBox: case BGFBAccessors.VariantGeometryUnion.tagDgnCone: case BGFBAccessors.VariantGeometryUnion.tagDgnTorusPipe: case BGFBAccessors.VariantGeometryUnion.tagDgnSphere: case BGFBAccessors.VariantGeometryUnion.tagDgnExtrusion: case BGFBAccessors.VariantGeometryUnion.tagDgnRotationalSweep: - case BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep: - { - return this.readSolidPrimitiveFromVariant(variant); - } - case BGFBAccessors.VariantGeometryUnion.tagVectorOfVariantGeometry: - { - const geometry: GeometryQuery[] = []; - const offsetToVectorOfVariantGeometry = variant.geometry(new BGFBAccessors.VectorOfVariantGeometry()); - for (let i = 0; i < offsetToVectorOfVariantGeometry!.membersLength(); i++) { - const child = offsetToVectorOfVariantGeometry!.members(i); - if (child !== null) { - const childGeometry = this.readGeometryQueryFromVariant(child); - if (childGeometry instanceof GeometryQuery) { - geometry.push(childGeometry); - } else if (Array.isArray(childGeometry)) { - geometry.push(...childGeometry); - } + case BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep: { + return this.readSolidPrimitiveFromVariant(variant); + } + case BGFBAccessors.VariantGeometryUnion.tagVectorOfVariantGeometry: { + const geometry: GeometryQuery[] = []; + const offsetToVectorOfVariantGeometry = variant.geometry(new BGFBAccessors.VectorOfVariantGeometry()); + for (let i = 0; i < offsetToVectorOfVariantGeometry!.membersLength(); i++) { + const child = offsetToVectorOfVariantGeometry!.members(i); + if (child !== null) { + const childGeometry = this.readGeometryQueryFromVariant(child); + if (childGeometry instanceof GeometryQuery) { + geometry.push(childGeometry); + } else if (Array.isArray(childGeometry)) { + geometry.push(...childGeometry); } } - return geometry; } + return geometry; + } case BGFBAccessors.VariantGeometryUnion.tagBsplineSurface: { return this.readBSplineSurfaceFromVariant(variant); } - case BGFBAccessors.VariantGeometryUnion.tagPointString: - { - return this.readPointStringFromVariant(variant); - } + case BGFBAccessors.VariantGeometryUnion.tagPointString: { + return this.readPointStringFromVariant(variant); + } } return undefined; } @@ -719,7 +790,6 @@ return undefined; const reader = new BGFBReader(); return reader.readGeometryQueryFromVariant(root); } - } /** * if data is "null" (the deprecated javascript idiom!) return undefined. Otherwise return the data as its own type. diff --git a/core/geometry/src/serialization/BGFBWriter.ts b/core/geometry/src/serialization/BGFBWriter.ts index 3e59289a528e..709a29d34953 100644 --- a/core/geometry/src/serialization/BGFBWriter.ts +++ b/core/geometry/src/serialization/BGFBWriter.ts @@ -55,7 +55,6 @@ export class BGFBWriter { this.builder = new flatbuffers.Builder(defaultSize); } /** - * * @param data data source, as Float64Array or number[]. * @param count optional count, used only if less than .length numbers are to be written. */ @@ -75,11 +74,10 @@ export class BGFBWriter { } /** - * * @param data data source, as Float64Array or number[]. * @param count optional count, used only if less than .length numbers are to be written. */ - public writeIntArray(data: Int32Array | number[] | undefined): number { + public writeIntArray(data: Int32Array | number[] | undefined): number { if (data === undefined) return 0; const numInt = data.length; @@ -93,18 +91,17 @@ export class BGFBWriter { } /** - * * @param data data source, as array derived from XYZ. * The data is output as a flat array of 3*data.length numbers. */ - public writePackedYZArray(data: XYZ[] | undefined): number { + public writePackedYZArray(data: XYZ[] | undefined): number { if (data === undefined) return 0; const numFloats = data.length * 3; if (numFloats === 0) return 0; - this.builder.startVector(8, numFloats, 8); - // write in reverse index order, and zyx within each XYZ + this.builder.startVector(8, numFloats, 8); + // write in reverse index order, and zyx within each XYZ for (let i = data.length - 1; i >= 0; i--) { this.builder.addFloat64(data[i].z); this.builder.addFloat64(data[i].y); @@ -166,19 +163,32 @@ export class BGFBWriter { BGFBAccessors.InterpolationCurve.addIsNaturalTangents(this.builder, props.isNaturalTangents); // REMARK: some native or flatbuffer quirk made startTangent a point and endTangent a vector. if (props.startTangent !== undefined) { - const startTangentOffset = BGFBAccessors.DPoint3d.createDPoint3d(this.builder, - XYZ.x(props.startTangent), XYZ.y(props.startTangent), XYZ.z(props.startTangent)); - BGFBAccessors.InterpolationCurve.addStartTangent(this.builder, startTangentOffset); + const startTangentOffset = BGFBAccessors.DPoint3d.createDPoint3d( + this.builder, + XYZ.x(props.startTangent), + XYZ.y(props.startTangent), + XYZ.z(props.startTangent), + ); + BGFBAccessors.InterpolationCurve.addStartTangent(this.builder, startTangentOffset); } if (props.endTangent !== undefined) { - const endTangentOffset = BGFBAccessors.DVector3d.createDVector3d(this.builder, - XYZ.x(props.endTangent), XYZ.y(props.endTangent), XYZ.z(props.endTangent)); - BGFBAccessors.InterpolationCurve.addEndTangent(this.builder, endTangentOffset); + const endTangentOffset = BGFBAccessors.DVector3d.createDVector3d( + this.builder, + XYZ.x(props.endTangent), + XYZ.y(props.endTangent), + XYZ.z(props.endTangent), + ); + BGFBAccessors.InterpolationCurve.addEndTangent(this.builder, endTangentOffset); } if (knotOffset !== 0) BGFBAccessors.InterpolationCurve.addKnots(this.builder, knotOffset); const headerOffset = BGFBAccessors.InterpolationCurve.endInterpolationCurve(this.builder); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagInterpolationCurve, headerOffset, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagInterpolationCurve, + headerOffset, + 0, + ); } public writeAkimaCurve3dAsFBVariantGeometry(curve: AkimaCurve3d): number | undefined { @@ -195,14 +205,21 @@ export class BGFBWriter { if (BSplineWrapMode.None !== wrapMode) data.params.wrapMode = wrapMode; - if (!SerializationHelpers.Export.prepareBSplineCurveData(data, {jsonPoles: false})) + if (!SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonPoles: false })) return undefined; const closed = !!data.params.closed; const polesOffset = this.writeDoubleArray(data.poles as Float64Array); const weightsOffset = 0; const knotsOffset = this.writeDoubleArray(data.params.knots); - const headerOffset = BGFBAccessors.BsplineCurve.createBsplineCurve(this.builder, data.params.order, closed, polesOffset, weightsOffset, knotsOffset); + const headerOffset = BGFBAccessors.BsplineCurve.createBsplineCurve( + this.builder, + data.params.order, + closed, + polesOffset, + weightsOffset, + knotsOffset, + ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagBsplineCurve, headerOffset, 0); } @@ -216,9 +233,16 @@ export class BGFBWriter { dim = 3; } - const data = SerializationHelpers.createBSplineSurfaceData(poles, dim, - bsurf.knots[UVSelect.uDirection].knots, bsurf.numPolesUV(UVSelect.uDirection), bsurf.orderUV(UVSelect.uDirection), - bsurf.knots[UVSelect.vDirection].knots, bsurf.numPolesUV(UVSelect.vDirection), bsurf.orderUV(UVSelect.vDirection)); + const data = SerializationHelpers.createBSplineSurfaceData( + poles, + dim, + bsurf.knots[UVSelect.uDirection].knots, + bsurf.numPolesUV(UVSelect.uDirection), + bsurf.orderUV(UVSelect.uDirection), + bsurf.knots[UVSelect.vDirection].knots, + bsurf.numPolesUV(UVSelect.vDirection), + bsurf.orderUV(UVSelect.vDirection), + ); if (weights) data.weights = weights; @@ -229,7 +253,7 @@ export class BGFBWriter { if (BSplineWrapMode.None !== wrapModeV) data.vParams.wrapMode = wrapModeV; - if (!SerializationHelpers.Export.prepareBSplineSurfaceData(data, {jsonPoles: false})) + if (!SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonPoles: false })) return undefined; // TypeScript B-spline surfaces do not support trim curves or isoline counts @@ -244,9 +268,23 @@ export class BGFBWriter { const weightsOffset = data.weights ? this.writeDoubleArray(data.weights as Float64Array) : 0; const uKnotsOffset = this.writeDoubleArray(data.uParams.knots); const vKnotsOffset = this.writeDoubleArray(data.vParams.knots); - const headerOffset = BGFBAccessors.BsplineSurface.createBsplineSurface(this.builder, polesOffset, weightsOffset, - uKnotsOffset, vKnotsOffset, data.uParams.numPoles, data.vParams.numPoles, data.uParams.order, data.vParams.order, - numRulesU, numRulesV, holeOrigin, boundariesOffset, closedU, closedV); + const headerOffset = BGFBAccessors.BsplineSurface.createBsplineSurface( + this.builder, + polesOffset, + weightsOffset, + uKnotsOffset, + vKnotsOffset, + data.uParams.numPoles, + data.vParams.numPoles, + data.uParams.order, + data.vParams.order, + numRulesU, + numRulesV, + holeOrigin, + boundariesOffset, + closedU, + closedV, + ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagBsplineSurface, headerOffset, 0); } @@ -262,42 +300,66 @@ export class BGFBWriter { if (BSplineWrapMode.None !== wrapMode) data.params.wrapMode = wrapMode; - if (!SerializationHelpers.Export.prepareBSplineCurveData(data, {jsonPoles: false})) + if (!SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonPoles: false })) return undefined; const closed = !!data.params.closed; const polesOffset = this.writeDoubleArray(data.poles as Float64Array); const weightsOffset = this.writeDoubleArray(data.weights); const knotsOffset = this.writeDoubleArray(data.params.knots); - const headerOffset = BGFBAccessors.BsplineCurve.createBsplineCurve(this.builder, data.params.order, closed, polesOffset, weightsOffset, knotsOffset); + const headerOffset = BGFBAccessors.BsplineCurve.createBsplineCurve( + this.builder, + data.params.order, + closed, + polesOffset, + weightsOffset, + knotsOffset, + ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagBsplineCurve, headerOffset, 0); } public writeCurvePrimitiveAsFBVariantGeometry(curvePrimitive: CurvePrimitive): number | undefined { if (curvePrimitive instanceof LineSegment3d) { - const segmentDataOffset = BGFBAccessors.DSegment3d.createDSegment3d(this.builder, + const segmentDataOffset = BGFBAccessors.DSegment3d.createDSegment3d( + this.builder, curvePrimitive.point0Ref.x, curvePrimitive.point0Ref.y, curvePrimitive.point0Ref.z, curvePrimitive.point1Ref.x, curvePrimitive.point1Ref.y, - curvePrimitive.point1Ref.z); + curvePrimitive.point1Ref.z, + ); const lineSegmentOffset = BGFBAccessors.LineSegment.createLineSegment(this.builder, segmentDataOffset); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagLineSegment, lineSegmentOffset, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagLineSegment, + lineSegmentOffset, + 0, + ); } else if (curvePrimitive instanceof Arc3d) { const data = curvePrimitive.toVectors(); - const arcDataOffset = BGFBAccessors.DEllipse3d.createDEllipse3d(this.builder, - data.center.x, data.center.y, data.center.z, - data.vector0.x, data.vector0.y, data.vector0.z, - data.vector90.x, data.vector90.y, data.vector90.z, + const arcDataOffset = BGFBAccessors.DEllipse3d.createDEllipse3d( + this.builder, + data.center.x, + data.center.y, + data.center.z, + data.vector0.x, + data.vector0.y, + data.vector0.z, + data.vector90.x, + data.vector90.y, + data.vector90.z, data.sweep.startRadians, - data.sweep.sweepRadians); + data.sweep.sweepRadians, + ); const arcOffset = BGFBAccessors.EllipticArc.createEllipticArc(this.builder, arcDataOffset); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagEllipticArc, arcOffset, 0); } else if (curvePrimitive instanceof LineString3d) { const coordinates = extractNumberArray(curvePrimitive.packedPoints); - const lineStringOffset = BGFBAccessors.LineString.createLineString(this.builder, - BGFBAccessors.LineString.createPointsVector(this.builder, coordinates)); + const lineStringOffset = BGFBAccessors.LineString.createLineString( + this.builder, + BGFBAccessors.LineString.createPointsVector(this.builder, coordinates), + ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagLineString, lineStringOffset, 0); } else if (curvePrimitive instanceof BSplineCurve3d) { return this.writeBsplineCurve3dAsFBVariantGeometry(curvePrimitive); @@ -310,21 +372,37 @@ export class BGFBWriter { } else if (curvePrimitive instanceof IntegratedSpiral3d) { const placement = curvePrimitive.localToWorld; const typeCode = DgnSpiralTypeQueries.stringToTypeCode(curvePrimitive.spiralType, true)!; - const spiralDetailOffset = BGFBAccessors.TransitionSpiralDetail.createTransitionSpiralDetail(this.builder, - placement.matrix.coffs[0], placement.matrix.coffs[1], placement.matrix.coffs[2], placement.origin.x, - placement.matrix.coffs[3], placement.matrix.coffs[4], placement.matrix.coffs[5], placement.origin.y, - placement.matrix.coffs[6], placement.matrix.coffs[5], placement.matrix.coffs[8], placement.origin.z, - curvePrimitive.activeFractionInterval.x0, curvePrimitive.activeFractionInterval.x1, - curvePrimitive.bearing01.startRadians, curvePrimitive.bearing01.endRadians, + const spiralDetailOffset = BGFBAccessors.TransitionSpiralDetail.createTransitionSpiralDetail( + this.builder, + placement.matrix.coffs[0], + placement.matrix.coffs[1], + placement.matrix.coffs[2], + placement.origin.x, + placement.matrix.coffs[3], + placement.matrix.coffs[4], + placement.matrix.coffs[5], + placement.origin.y, + placement.matrix.coffs[6], + placement.matrix.coffs[5], + placement.matrix.coffs[8], + placement.origin.z, + curvePrimitive.activeFractionInterval.x0, + curvePrimitive.activeFractionInterval.x1, + curvePrimitive.bearing01.startRadians, + curvePrimitive.bearing01.endRadians, TransitionSpiral3d.radiusToCurvature(curvePrimitive.radius01.x0), TransitionSpiral3d.radiusToCurvature(curvePrimitive.radius01.x1), typeCode, - 0); - const transitionTableOffset = BGFBAccessors.TransitionSpiral.createTransitionSpiral(this.builder, - spiralDetailOffset, 0, 0); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, - BGFBAccessors.VariantGeometryUnion.tagTransitionSpiral, transitionTableOffset, 0); - } else if (curvePrimitive instanceof DirectSpiral3d) { + 0, + ); + const transitionTableOffset = BGFBAccessors.TransitionSpiral.createTransitionSpiral(this.builder, spiralDetailOffset, 0, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagTransitionSpiral, + transitionTableOffset, + 0, + ); + } else if (curvePrimitive instanceof DirectSpiral3d) { const placement = curvePrimitive.localToWorld; // direct spirals always inflect at the origin of the local frame .. // spiral @@ -335,30 +413,48 @@ export class BGFBWriter { const nominalLength = curvePrimitive.nominalL1; const bearing0Radians = 0.0; const bearing1Radians = TransitionSpiral3d.radiusRadiusLengthToSweepRadians(radius0, radius1, nominalLength); - const typeCode = DgnSpiralTypeQueries.stringToTypeCode(curvePrimitive.spiralType, true)!; - const spiralDetailOffset = BGFBAccessors.TransitionSpiralDetail.createTransitionSpiralDetail(this.builder, - placement.matrix.coffs[0], placement.matrix.coffs[1], placement.matrix.coffs[2], placement.origin.x, - placement.matrix.coffs[3], placement.matrix.coffs[4], placement.matrix.coffs[5], placement.origin.y, - placement.matrix.coffs[6], placement.matrix.coffs[5], placement.matrix.coffs[8], placement.origin.z, - curvePrimitive.activeFractionInterval.x0, curvePrimitive.activeFractionInterval.x1, - bearing0Radians, bearing1Radians, - curvature0, curvature1, - typeCode, - 0); - const transitionTableOffset = BGFBAccessors.TransitionSpiral.createTransitionSpiral(this.builder, - spiralDetailOffset, 0, 0); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, - BGFBAccessors.VariantGeometryUnion.tagTransitionSpiral, transitionTableOffset, 0); - } - return undefined; + const typeCode = DgnSpiralTypeQueries.stringToTypeCode(curvePrimitive.spiralType, true)!; + const spiralDetailOffset = BGFBAccessors.TransitionSpiralDetail.createTransitionSpiralDetail( + this.builder, + placement.matrix.coffs[0], + placement.matrix.coffs[1], + placement.matrix.coffs[2], + placement.origin.x, + placement.matrix.coffs[3], + placement.matrix.coffs[4], + placement.matrix.coffs[5], + placement.origin.y, + placement.matrix.coffs[6], + placement.matrix.coffs[5], + placement.matrix.coffs[8], + placement.origin.z, + curvePrimitive.activeFractionInterval.x0, + curvePrimitive.activeFractionInterval.x1, + bearing0Radians, + bearing1Radians, + curvature0, + curvature1, + typeCode, + 0, + ); + const transitionTableOffset = BGFBAccessors.TransitionSpiral.createTransitionSpiral(this.builder, spiralDetailOffset, 0, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagTransitionSpiral, + transitionTableOffset, + 0, + ); + } + return undefined; } public writePointString3dAsFBVariantGeometry(pointString: PointString3d): number | undefined { if (pointString instanceof PointString3d) { const coordinates = extractNumberArray(pointString.points); - const headerOffset = BGFBAccessors.PointString.createPointString(this.builder, - BGFBAccessors.PointString.createPointsVector(this.builder, coordinates)); + const headerOffset = BGFBAccessors.PointString.createPointString( + this.builder, + BGFBAccessors.PointString.createPointsVector(this.builder, coordinates), + ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagPointString, headerOffset, 0); - } return undefined; } @@ -376,23 +472,49 @@ export class BGFBWriter { const baseY = solid.getBaseY(); const topX = solid.getTopX(); const topY = solid.getTopY(); - const detailOffset = BGFBAccessors.DgnBoxDetail.createDgnBoxDetail(this.builder, - originA.x, originA.y, originA.z, - originB.x, originB.y, originB.z, - vectorX.x, vectorX.y, vectorX.z, - vectorY.x, vectorY.y, vectorY.z, - baseX, baseY, topX, topY, solid.capped); + const detailOffset = BGFBAccessors.DgnBoxDetail.createDgnBoxDetail( + this.builder, + originA.x, + originA.y, + originA.z, + originB.x, + originB.y, + originB.z, + vectorX.x, + vectorX.y, + vectorX.z, + vectorY.x, + vectorY.y, + vectorY.z, + baseX, + baseY, + topX, + topY, + solid.capped, + ); const carrierOffset = BGFBAccessors.DgnBox.createDgnBox(this.builder, detailOffset); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnBox, carrierOffset, 0); } else if (solid instanceof Sphere) { const localToWorld = solid.cloneLocalToWorld(); const sweep = solid.cloneLatitudeSweep(); - const detailOffset = BGFBAccessors.DgnSphereDetail.createDgnSphereDetail(this.builder, - localToWorld.matrix.coffs[0], localToWorld.matrix.coffs[1], localToWorld.matrix.coffs[2], localToWorld.origin.x, - localToWorld.matrix.coffs[3], localToWorld.matrix.coffs[4], localToWorld.matrix.coffs[5], localToWorld.origin.y, - localToWorld.matrix.coffs[6], localToWorld.matrix.coffs[7], localToWorld.matrix.coffs[8], localToWorld.origin.z, - sweep.startRadians, sweep.sweepRadians, - solid.capped); + const detailOffset = BGFBAccessors.DgnSphereDetail.createDgnSphereDetail( + this.builder, + localToWorld.matrix.coffs[0], + localToWorld.matrix.coffs[1], + localToWorld.matrix.coffs[2], + localToWorld.origin.x, + localToWorld.matrix.coffs[3], + localToWorld.matrix.coffs[4], + localToWorld.matrix.coffs[5], + localToWorld.origin.y, + localToWorld.matrix.coffs[6], + localToWorld.matrix.coffs[7], + localToWorld.matrix.coffs[8], + localToWorld.origin.z, + sweep.startRadians, + sweep.sweepRadians, + solid.capped, + ); const carrierOffset = BGFBAccessors.DgnSphere.createDgnSphere(this.builder, detailOffset); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnSphere, carrierOffset, 0); } else if (solid instanceof Cone) { @@ -402,11 +524,24 @@ export class BGFBWriter { const vectorY = solid.getVectorY(); const radiusA = solid.getRadiusA(); const radiusB = solid.getRadiusB(); - const detailOffset = BGFBAccessors.DgnConeDetail.createDgnConeDetail(this.builder, - centerA.x, centerA.y, centerA.z, - centerB.x, centerB.y, centerB.z, - vectorX.x, vectorX.y, vectorX.z, - vectorY.x, vectorY.y, vectorY.z, radiusA, radiusB, solid.capped); + const detailOffset = BGFBAccessors.DgnConeDetail.createDgnConeDetail( + this.builder, + centerA.x, + centerA.y, + centerA.z, + centerB.x, + centerB.y, + centerB.z, + vectorX.x, + vectorX.y, + vectorX.z, + vectorY.x, + vectorY.y, + vectorY.z, + radiusA, + radiusB, + solid.capped, + ); const carrierOffset = BGFBAccessors.DgnCone.createDgnCone(this.builder, detailOffset); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnCone, carrierOffset, 0); } else if (solid instanceof TorusPipe) { @@ -416,10 +551,22 @@ export class BGFBWriter { const minorRadius = solid.getMinorRadius(); const majorRadius = solid.getMajorRadius(); const sweepRadians = solid.getSweepAngle().radians; - const detailOffset = BGFBAccessors.DgnTorusPipeDetail.createDgnTorusPipeDetail(this.builder, - center.x, center.y, center.z, - vectorX.x, vectorX.y, vectorX.z, - vectorY.x, vectorY.y, vectorY.z, majorRadius, minorRadius, sweepRadians, solid.capped); + const detailOffset = BGFBAccessors.DgnTorusPipeDetail.createDgnTorusPipeDetail( + this.builder, + center.x, + center.y, + center.z, + vectorX.x, + vectorX.y, + vectorX.z, + vectorY.x, + vectorY.y, + vectorY.z, + majorRadius, + minorRadius, + sweepRadians, + solid.capped, + ); const carrierOffset = BGFBAccessors.DgnTorusPipe.createDgnTorusPipe(this.builder, detailOffset); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnTorusPipe, carrierOffset, 0); } else if (solid instanceof LinearSweep) { @@ -437,7 +584,12 @@ export class BGFBWriter { BGFBAccessors.DgnExtrusion.addCapped(this.builder, solid.capped); const dgnExtrusionOffset = BGFBAccessors.DgnExtrusion.endDgnExtrusion(this.builder); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnExtrusion, dgnExtrusionOffset, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagDgnExtrusion, + dgnExtrusionOffset, + 0, + ); } else if (solid instanceof RotationalSweep) { const baseCurveOffset = this.writeCurveCollectionAsFBCurveVector(solid.getSweepContourRef().getCurves())!; const axis = solid.cloneAxisRay(); @@ -449,14 +601,25 @@ export class BGFBWriter { // chokes trying to add it. BGFBAccessors.DgnRotationalSweep.startDgnRotationalSweep(this.builder); BGFBAccessors.DgnRotationalSweep.addBaseCurve(this.builder, baseCurveOffset); - const axisRayOffset = BGFBAccessors.DRay3d.createDRay3d(this.builder, - axis.origin.x, axis.origin.y, axis.origin.z, axis.direction.x, axis.direction.y, axis.direction.z); + const axisRayOffset = BGFBAccessors.DRay3d.createDRay3d( + this.builder, + axis.origin.x, + axis.origin.y, + axis.origin.z, + axis.direction.x, + axis.direction.y, + axis.direction.z, + ); BGFBAccessors.DgnRotationalSweep.addAxis(this.builder, axisRayOffset); BGFBAccessors.DgnRotationalSweep.addSweepRadians(this.builder, sweepAngle.radians); BGFBAccessors.DgnRotationalSweep.addCapped(this.builder, solid.capped); const dgnRotationalSweepOffset = BGFBAccessors.DgnRotationalSweep.endDgnRotationalSweep(this.builder); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnRotationalSweep, dgnRotationalSweepOffset, 0); - + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagDgnRotationalSweep, + dgnRotationalSweepOffset, + 0, + ); } else if (solid instanceof RuledSweep) { const contours = solid.sweepContoursRef(); const contourOffsets: flatbuffers.Offset[] = []; @@ -467,17 +630,19 @@ export class BGFBWriter { } const contoursVectorOffset = BGFBAccessors.DgnRuledSweep.createCurvesVector(this.builder, contourOffsets); const ruledSweepTable = BGFBAccessors.DgnRuledSweep.createDgnRuledSweep(this.builder, contoursVectorOffset, solid.capped); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep, ruledSweepTable, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagDgnRuledSweep, + ruledSweepTable, + 0, + ); } return undefined; } public writePolyfaceAuxChannelDataAsFBVariantGeometry(channelData: AuxChannelData): number | undefined { if (channelData instanceof AuxChannelData) { const valuesOffset = BGFBAccessors.PolyfaceAuxChannelData.createValuesVector(this.builder, channelData.values); - return BGFBAccessors.PolyfaceAuxChannelData.createPolyfaceAuxChannelData(this.builder, - channelData.input, - valuesOffset, - ); + return BGFBAccessors.PolyfaceAuxChannelData.createPolyfaceAuxChannelData(this.builder, channelData.input, valuesOffset); } return undefined; } @@ -491,11 +656,7 @@ export class BGFBWriter { const valuesOffset = BGFBAccessors.PolyfaceAuxChannel.createDataVector(this.builder, channelDataOffsets); const nameOffset = channel.name ? this.builder.createString(channel.name) : 0; const inputNameOffset = channel.inputName ? this.builder.createString(channel.inputName) : 0; - return BGFBAccessors.PolyfaceAuxChannel.createPolyfaceAuxChannel(this.builder, - channel.dataType, - nameOffset, - inputNameOffset, valuesOffset, - ); + return BGFBAccessors.PolyfaceAuxChannel.createPolyfaceAuxChannel(this.builder, channel.dataType, nameOffset, inputNameOffset, valuesOffset); } return undefined; } @@ -516,11 +677,10 @@ export class BGFBWriter { return undefined; } public writeTaggedNumericDataArray(data: TaggedNumericData | undefined): number { - if (data){ - const intDataOffset = this.writeIntArray(data.intData); - const doubleDataOffset = this.writeDoubleArray(data.doubleData); - return BGFBAccessors.TaggedNumericData.createTaggedNumericData(this.builder, - data.tagA, data.tagB, intDataOffset, doubleDataOffset); + if (data) { + const intDataOffset = this.writeIntArray(data.intData); + const doubleDataOffset = this.writeDoubleArray(data.doubleData); + return BGFBAccessors.TaggedNumericData.createTaggedNumericData(this.builder, data.tagA, data.tagB, intDataOffset, doubleDataOffset); } return 0; } @@ -528,7 +688,7 @@ export class BGFBWriter { public writePolyfaceAsFBVariantGeometry(mesh: IndexedPolyface): number | undefined { if (mesh instanceof IndexedPolyface) { // WE KNOW . . . . the polyface has blocks of zero-based indices. - const indexArray: number[] = []; // and this will really be integers. + const indexArray: number[] = []; // and this will really be integers. const numberArray: number[] = []; // and this will really be doubles. copyToPackedNumberArray(numberArray, mesh.data.point.float64Data(), mesh.data.point.float64Length); @@ -541,7 +701,7 @@ export class BGFBWriter { let paramOffset = 0; let auxDataOffset = 0; let taggedNumericDataOffset = 0; - const meshStyle = 1; // That is . . . MESH_ELM_STYLE_INDEXED_FACE_LOOPS + const meshStyle = 1; // That is . . . MESH_ELM_STYLE_INDEXED_FACE_LOOPS const numPerFace = 0; // specifically, variable size with 0 terminators this.fillOneBasedIndexArray(mesh, mesh.data.pointIndex, mesh.data.edgeVisible, 0, indexArray); @@ -587,18 +747,40 @@ export class BGFBWriter { // NOTE: mesh.data.face is not persistent const polyfaceOffset = BGFBAccessors.Polyface.createPolyface( - this.builder, pointOffset, paramOffset, normalOffset, 0, intColorOffset, pointIndexOffset, paramIndexOffset, - normalIndexOffset, colorIndexOffset, 0, 0, 0, meshStyle, twoSided, numPerFace, 0, auxDataOffset, - expectedClosure, taggedNumericDataOffset, + this.builder, + pointOffset, + paramOffset, + normalOffset, + 0, + intColorOffset, + pointIndexOffset, + paramIndexOffset, + normalIndexOffset, + colorIndexOffset, + 0, + 0, + 0, + meshStyle, + twoSided, + numPerFace, + 0, + auxDataOffset, + expectedClosure, + taggedNumericDataOffset, ); return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagPolyface, polyfaceOffset, 0); - } return undefined; } - public fillOneBasedIndexArray(mesh: IndexedPolyface, sourceIndex: number[], visible: boolean[] | undefined, facetTerminator: number | undefined, destIndex: number[]) { + public fillOneBasedIndexArray( + mesh: IndexedPolyface, + sourceIndex: number[], + visible: boolean[] | undefined, + facetTerminator: number | undefined, + destIndex: number[], + ) { destIndex.length = 0; const numFacet = mesh.facetCount; for (let facetIndex = 0; facetIndex < numFacet; facetIndex++) { @@ -634,7 +816,7 @@ export class BGFBWriter { return undefined; } - public writeGeometryQueryArrayAsFBVariantGeometry(allGeometry: GeometryQuery | GeometryQuery[] | undefined): number | undefined{ + public writeGeometryQueryArrayAsFBVariantGeometry(allGeometry: GeometryQuery | GeometryQuery[] | undefined): number | undefined { if (Array.isArray(allGeometry)) { const allOffsets: number[] = []; for (const g of allGeometry) { @@ -645,7 +827,12 @@ export class BGFBWriter { if (allOffsets.length > 0) { const membersOffset = BGFBAccessors.VectorOfVariantGeometry.createMembersVector(this.builder, allOffsets); const vectorOffset = BGFBAccessors.VectorOfVariantGeometry.createVectorOfVariantGeometry(this.builder, membersOffset); - return BGFBAccessors.VariantGeometry.createVariantGeometry(this.builder, BGFBAccessors.VariantGeometryUnion.tagVectorOfVariantGeometry, vectorOffset, 0); + return BGFBAccessors.VariantGeometry.createVariantGeometry( + this.builder, + BGFBAccessors.VariantGeometryUnion.tagVectorOfVariantGeometry, + vectorOffset, + 0, + ); } } else if (allGeometry instanceof GeometryQuery) return this.writeGeometryQueryAsFBVariantGeometry(allGeometry); @@ -707,4 +894,3 @@ function copyToPackedNumberArray(dest: number[], source: Float64Array, count: nu for (let i = 0; i < count; i++) dest.push(source[i]); } - diff --git a/core/geometry/src/serialization/BentleyGeometryFlatBuffer.ts b/core/geometry/src/serialization/BentleyGeometryFlatBuffer.ts index d55fee5f81ee..f1f7ec9994f8 100644 --- a/core/geometry/src/serialization/BentleyGeometryFlatBuffer.ts +++ b/core/geometry/src/serialization/BentleyGeometryFlatBuffer.ts @@ -14,7 +14,7 @@ import { BGFBWriter } from "./BGFBWriter"; * @public */ export class BentleyGeometryFlatBuffer { - private constructor() { } + private constructor() {} /** * Serialize bytes to a flatbuffer. * @public diff --git a/core/geometry/src/serialization/DeepCompare.ts b/core/geometry/src/serialization/DeepCompare.ts index 4b5dd8853efe..08d2fafa3812 100644 --- a/core/geometry/src/serialization/DeepCompare.ts +++ b/core/geometry/src/serialization/DeepCompare.ts @@ -31,7 +31,9 @@ export class DeepCompare { /** relative tolerance for declaring numeric values equal. */ public numberRelTol: number; /** Construct comparison object with relative tolerance. */ - public constructor(numberRelTol = 1.0e-12) { this.numberRelTol = numberRelTol; } + public constructor(numberRelTol = 1.0e-12) { + this.numberRelTol = numberRelTol; + } /** Test if a and b are within tolerance. * * If not, push error message to errorTracker. @@ -146,7 +148,14 @@ export class DeepCompare { if (tolerance !== undefined) this.numberRelTol = tolerance; this.errorTracker.length = 0; - this.typeCounts.numbers = this.typeCounts.arrays = this.typeCounts.functions = this.typeCounts.objects = this.typeCounts.strings = this.typeCounts.booleans = this.typeCounts.undefined = 0; + this.typeCounts.numbers = + this.typeCounts.arrays = + this.typeCounts.functions = + this.typeCounts.objects = + this.typeCounts.strings = + this.typeCounts.booleans = + this.typeCounts.undefined = + 0; this.propertyCounts = {}; return this.compareInternal(a, b); } diff --git a/core/geometry/src/serialization/GeometrySamples.ts b/core/geometry/src/serialization/GeometrySamples.ts index 2b55607efcdd..5b5ef259a3d0 100644 --- a/core/geometry/src/serialization/GeometrySamples.ts +++ b/core/geometry/src/serialization/GeometrySamples.ts @@ -187,7 +187,8 @@ export class Sample { Point2d.create(0, 0), Point2d.create(1, 0), Point2d.create(0, 1), - Point2d.create(2, 3)]; + Point2d.create(2, 3), + ]; /** Array with assorted Point3d samples */ public static readonly point3d: Point3d[] = [ Point3d.create(0, 0, 0), @@ -198,7 +199,8 @@ export class Sample { Point3d.create(2, 3, 0), Point3d.create(0, 2, 5), Point3d.create(-3, 0, 5), - Point3d.create(4, 3, -2)]; + Point3d.create(4, 3, -2), + ]; /** * Return an array of Point3d, with x,y,z all stepping through a range of values. * x varies fastest, then y then z @@ -234,7 +236,8 @@ export class Sample { Point4d.create(-3, 0, 5, 1), Point4d.create(-3, 0, 5, 0.3), Point4d.create(-3, 0, 5, -0.2), - Point4d.create(4, 3, -2, 1)]; + Point4d.create(4, 3, -2, 1), + ]; /** Array with assorted nonzero vector samples. */ public static createNonZeroVectors(): Vector3d[] { return [ @@ -332,7 +335,9 @@ export class Sample { const plane2 = plane1.clone(); plane2.setFlags(true, true); return [ - plane0, plane1, plane2, + plane0, + plane1, + plane2, ClipPlane.createNormalAndDistance(Vector3d.create(3, 4, 0), 2.0)!, ClipPlane.createEdgeXY(Point3d.create(1, 0, 0), Point3d.create(24, 32, 0))!, ]; @@ -487,11 +492,21 @@ export class Sample { const axisTrig = [1, 0, -1, 0, 1]; for (let i = 0; i < 4; i++) { Matrix3d.xyzPlusMatrixTimesCoordinates( - center, axes, radius0 * cornerTrig[i + 1], radius90 * cornerTrig[i], 0, xyz, + center, + axes, + radius0 * cornerTrig[i + 1], + radius90 * cornerTrig[i], + 0, + xyz, ); controlPoints.push([xyz.x, xyz.y, xyz.z, a]); Matrix3d.xyzPlusMatrixTimesCoordinates( - center, axes, radius0 * axisTrig[i + 1], radius90 * axisTrig[i], 0, xyz, + center, + axes, + radius0 * axisTrig[i + 1], + radius90 * axisTrig[i], + 0, + xyz, ); controlPoints.push([xyz.x, xyz.y, xyz.z, 1.0]); } @@ -630,13 +645,16 @@ export class Sample { return [ Matrix3d.createIdentity(), Matrix3d.createRotationAroundVector( - Vector3d.create(1, 0, 0), Angle.createDegrees(10), + Vector3d.create(1, 0, 0), + Angle.createDegrees(10), ) as Matrix3d, Matrix3d.createRotationAroundVector( - Vector3d.create(1, -2, 5), Angle.createDegrees(-6.0), + Vector3d.create(1, -2, 5), + Angle.createDegrees(-6.0), ) as Matrix3d, Matrix3d.createRotationAroundVector( - Vector3d.create(1, 2, 3), Angle.createDegrees(49.0), + Vector3d.create(1, 2, 3), + Angle.createDegrees(49.0), ) as Matrix3d, Matrix3d.createUniformScale(2.0), Matrix3d.createScale(1, 1, -1), @@ -656,7 +674,8 @@ export class Sample { Transform.createFixedPointAndMatrix( Point3d.create(4, 1, -2), Matrix3d.createRotationAroundVector( - Vector3d.create(1, 2, 3), Angle.createRadians(10), + Vector3d.create(1, 2, 3), + Angle.createRadians(10), ) as Matrix3d, ), ]; @@ -671,49 +690,103 @@ export class Sample { public static createScaleSkewMatrix3d(): Matrix3d[] { return [ Matrix3d.createRowValues( - 1, 0, 0, - 0, 1, 0, - 0, 0, 1, + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1, ), Matrix3d.createRowValues( - 5, 0, 0, - 0, 6, 0, - 0, 0, 7, + 5, + 0, + 0, + 0, + 6, + 0, + 0, + 0, + 7, ), Matrix3d.createRowValues( - 5, 2, 0, - 0, 6, 0, - 0, 0, 7, + 5, + 2, + 0, + 0, + 6, + 0, + 0, + 0, + 7, ), Matrix3d.createRowValues( - 5, 0, 2, - 0, 6, 0, - 0, 0, 7, + 5, + 0, + 2, + 0, + 6, + 0, + 0, + 0, + 7, ), Matrix3d.createRowValues( - 5, 0, 0, - 1, 6, 0, - 0, 0, 7, + 5, + 0, + 0, + 1, + 6, + 0, + 0, + 0, + 7, ), Matrix3d.createRowValues( - 5, 0, 0, - 0, 6, 1, - 0, 0, 7, + 5, + 0, + 0, + 0, + 6, + 1, + 0, + 0, + 7, ), Matrix3d.createRowValues( - 5, 0, 0, - 0, 6, 0, - 1, 0, 7, + 5, + 0, + 0, + 0, + 6, + 0, + 1, + 0, + 7, ), Matrix3d.createRowValues( - 5, 0, 0, - 0, 6, 0, - 0, 1, 7, + 5, + 0, + 0, + 0, + 6, + 0, + 0, + 1, + 7, ), Matrix3d.createRowValues( - 5, 2, 3, - 2, 6, 1, - -1, 2, 7, + 5, + 2, + 3, + 2, + 6, + 1, + -1, + 2, + 7, ), ]; } @@ -771,17 +844,23 @@ export class Sample { Transform.createFixedPointAndMatrix( Point3d.create(0, 0, 0), Matrix3d.createRotationAroundVector( - Vector3d.unitY(), Angle.createDegrees(10)) as Matrix3d, + Vector3d.unitY(), + Angle.createDegrees(10), + ) as Matrix3d, ), Transform.createFixedPointAndMatrix( Point3d.create(distanceScale4 * 4, distanceScale4 * 1, -distanceScale4 * 2), Matrix3d.createRotationAroundVector( - Vector3d.create(1, 2, 3), Angle.createDegrees(10)) as Matrix3d, + Vector3d.create(1, 2, 3), + Angle.createDegrees(10), + ) as Matrix3d, ), Transform.createFixedPointAndMatrix( Point3d.create(distanceScale4 * 4, distanceScale4 * 1, -distanceScale4 * 2), Matrix3d.createRotationAroundVector( - Vector3d.create(-2, 1, 4), Angle.createDegrees(35)) as Matrix3d, + Vector3d.create(-2, 1, 4), + Angle.createDegrees(35), + ) as Matrix3d, ), ]; } @@ -789,7 +868,8 @@ export class Sample { public static createMessyRigidTransform(fixedPoint?: Point3d): Transform { return Transform.createFixedPointAndMatrix( fixedPoint ? fixedPoint : Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!); + Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!, + ); } /** * Return various rigid matrices: @@ -801,16 +881,20 @@ export class Sample { return [ Matrix3d.createIdentity(), Matrix3d.createRotationAroundVector( - Vector3d.unitX(), Angle.createDegrees(10), + Vector3d.unitX(), + Angle.createDegrees(10), ) as Matrix3d, Matrix3d.createRotationAroundVector( - Vector3d.unitY(), Angle.createDegrees(10), + Vector3d.unitY(), + Angle.createDegrees(10), ) as Matrix3d, Matrix3d.createRotationAroundVector( - Vector3d.unitZ(), Angle.createDegrees(10), + Vector3d.unitZ(), + Angle.createDegrees(10), ) as Matrix3d, Matrix3d.createRotationAroundVector( - Vector3d.create(1, 2, 3), Angle.createDegrees(10), + Vector3d.create(1, 2, 3), + Angle.createDegrees(10), ) as Matrix3d, ]; } @@ -819,7 +903,8 @@ export class Sample { * * Simple promotion of each Sample.createInvertibleTransforms () * * optional nasty [1,2,3,4...15] row order * @param includeIrregular if true, include [1,2,..15] row major - */ // promote each transform[] to a Matrix4d. + */ + // promote each transform[] to a Matrix4d. public static createMatrix4ds(includeIrregular: boolean = false): Matrix4d[] { const result = []; let transform; @@ -828,10 +913,22 @@ export class Sample { if (includeIrregular) { result.push( Matrix4d.createRowValues( - 1, 2, 3, 4, - 5, 6, 7, 8, - 9, 10, 11, 12, - 13, 14, 15, 16, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, ), ); } @@ -857,7 +954,8 @@ export class Sample { const point1 = Point3d.create(10, 0, 0); const p1 = [ - point1, Point3d.create(0, 10, 0), + point1, + Point3d.create(0, 10, 0), Point3d.create(6, 10, 0), Point3d.create(6, 10, 0), Point3d.create(0, 10, 0), @@ -871,7 +969,8 @@ export class Sample { Path.create(segment1, arc2), Path.create( LineSegment3d.create(point0, point1), - LineString3d.create(p1)), + LineString3d.create(p1), + ), Sample.createCappedArcPath(4, 0, 180), ]; if (withGaps) @@ -894,7 +993,6 @@ export class Sample { const y3 = 10.0; for (const y0 of [0, -1, 1]) { for (const x2 of [15, 11, 20, 9, 7]) { - const point0 = Point3d.create(0, y0, 0); const point1 = Point3d.create(x1, 0, 0); const point2 = Point3d.create(x2, y2, 0); @@ -984,7 +1082,14 @@ export class Sample { * @param index0 optional index of first point. Default is 0. * @param index1 optional index of final point. Default is numPoints */ - public static createInterpolatedPoints(point0: Point3d, point1: Point3d, numPoints: number, result?: Point3d[], index0?: number, index1?: number): Point3d[] { + public static createInterpolatedPoints( + point0: Point3d, + point1: Point3d, + numPoints: number, + result?: Point3d[], + index0?: number, + index1?: number, + ): Point3d[] { if (numPoints < 2) numPoints = 2; if (result === undefined) @@ -1019,7 +1124,15 @@ export class Sample { return points; } /** Append sawtooth with x distances successively scaled by xFactor */ - public static appendVariableSawTooth(points: Point3d[], dxLow: number, riseX: number, riseY: number, dxHigh: number, numPhase: number, xFactor: number): Point3d[] { + public static appendVariableSawTooth( + points: Point3d[], + dxLow: number, + riseX: number, + riseY: number, + dxHigh: number, + numPhase: number, + xFactor: number, + ): Point3d[] { let factor = 1.0; for (let i = 0; i < numPhase; i++) { this.appendSawTooth(points, factor * dxLow, factor * riseX, riseY, factor * dxHigh, 1); @@ -1043,9 +1156,19 @@ export class Sample { * @param riseYReturn rise y part of return * @param dxHighReturn dwell at return high */ - public static createBidirectionalSawtooth(origin: Point3d, dxLow: number, riseX: number, riseY: number, dxHigh: number, numPhaseOutbound: number, + public static createBidirectionalSawtooth( + origin: Point3d, + dxLow: number, + riseX: number, + riseY: number, + dxHigh: number, + numPhaseOutbound: number, dyFinal: number, - dxLowReturn: number, riseXReturn: number, riseYReturn: number, dxHighReturn: number): Point3d[] { + dxLowReturn: number, + riseXReturn: number, + riseYReturn: number, + dxHighReturn: number, + ): Point3d[] { const data = [origin.clone()]; const x0 = data[0].x; this.appendSawTooth(data, dxLow, riseX, riseY, dxHigh, numPhaseOutbound); @@ -1090,12 +1213,14 @@ export class Sample { public static createArcRegions(): Loop[] { const result = []; const center = Point3d.create(0, 0, 0); - for (const sweep of [ - AngleSweep.createStartEndDegrees(0, 360), - AngleSweep.createStartEndDegrees(-20, 20), - AngleSweep.createStartEndDegrees(0, 90), - AngleSweep.createStartEndDegrees(0, 180), - ]) { + for ( + const sweep of [ + AngleSweep.createStartEndDegrees(0, 360), + AngleSweep.createStartEndDegrees(-20, 20), + AngleSweep.createStartEndDegrees(0, 90), + AngleSweep.createStartEndDegrees(0, 180), + ] + ) { const arc0 = Arc3d.createXY(Point3d.create(0, 0), 2.0, sweep); if (arc0.sweep.isFullCircle) { result.push(Loop.create(arc0)); @@ -1190,7 +1315,8 @@ export class Sample { Point3d.create(ax + 1, 4 * ey), pointB, ], - 3)!, + 3, + )!, Arc3d.createCircularStartMiddleEnd(pointB, pointC1, point0), ), ), @@ -1280,27 +1406,52 @@ export class Sample { Point3d.create(), Vector3d.unitX(), Vector3d.unitY(), - gridMultiplier * 3, 2 * gridMultiplier, false, false, false), + gridMultiplier * 3, + 2 * gridMultiplier, + false, + false, + false, + ), Sample.createTriangularUnitGridPolyface( Point3d.create(), Vector3d.unitX(), Vector3d.unitY(), - 3 * gridMultiplier, 2 * gridMultiplier, true, false, false), + 3 * gridMultiplier, + 2 * gridMultiplier, + true, + false, + false, + ), Sample.createTriangularUnitGridPolyface( Point3d.create(), Vector3d.unitX(), Vector3d.unitY(), - 3 * gridMultiplier, 2 * gridMultiplier, false, true, false), + 3 * gridMultiplier, + 2 * gridMultiplier, + false, + true, + false, + ), Sample.createTriangularUnitGridPolyface( Point3d.create(), Vector3d.unitX(), Vector3d.unitY(), - 3 * gridMultiplier, 2 * gridMultiplier, false, false, true), + 3 * gridMultiplier, + 2 * gridMultiplier, + false, + false, + true, + ), Sample.createTriangularUnitGridPolyface( Point3d.create(), Vector3d.unitX(), Vector3d.unitY(), - 3 * gridMultiplier, 2 * gridMultiplier, true, true, true), + 3 * gridMultiplier, + 2 * gridMultiplier, + true, + true, + true, + ), ]; for (const m of meshes) m.expectedClosure = 1; @@ -1319,15 +1470,21 @@ export class Sample { * @note edgeVisible is false only on the diagonals */ public static createTriangularUnitGridPolyface( - origin: Point3d, vectorX: Vector3d, vectorY: Vector3d, - numXVertices: number, numYVertices: number, createParams: boolean = false, createNormals: boolean = false, - createColors: boolean = false, triangulate: boolean = true, + origin: Point3d, + vectorX: Vector3d, + vectorY: Vector3d, + numXVertices: number, + numYVertices: number, + createParams: boolean = false, + createNormals: boolean = false, + createColors: boolean = false, + triangulate: boolean = true, ): IndexedPolyface { const mesh = IndexedPolyface.create(createNormals, createParams, createColors); const normal = vectorX.crossProduct(vectorY); if (createNormals) { normal.normalizeInPlace(); - mesh.addNormalXYZ(normal.x, normal.y, normal.z); // use XYZ to help coverage count!! + mesh.addNormalXYZ(normal.x, normal.y, normal.z); // use XYZ to help coverage count!! } // Push to coordinate arrays for (let j = 0; j < numYVertices; j++) { @@ -1439,7 +1596,14 @@ export class Sample { /** Create simple bspline surface on xy plane grid. */ public static createXYGridBsplineSurface(numU: number, numV: number, orderU: number, orderV: number): BSplineSurface3d | undefined { return BSplineSurface3d.create( - Sample.createXYGrid(numU, numV, 1.0, 1.0), numU, orderU, undefined, numV, orderV, undefined); + Sample.createXYGrid(numU, numV, 1.0, 1.0), + numU, + orderU, + undefined, + numV, + orderV, + undefined, + ); } /** * Create a bspline surface whose poles area on circular paths. @@ -1451,10 +1615,17 @@ export class Sample { * @param orderU major hoop order * @param orderV minor hoop order */ - public static createPseudoTorusBsplineSurface(radiusU: number, radiusV: number, numU: number, numV: number, orderU: number, orderV: number): BSplineSurface3d | undefined { + public static createPseudoTorusBsplineSurface( + radiusU: number, + radiusV: number, + numU: number, + numV: number, + orderU: number, + orderV: number, + ): BSplineSurface3d | undefined { const points = []; - const numUPole = numU + orderU - 1; // degreeU wrap-around poles - const numVPole = numV + orderV - 1; // degreeV wrap-around poles + const numUPole = numU + orderU - 1; // degreeU wrap-around poles + const numVPole = numV + orderV - 1; // degreeV wrap-around poles const uKnots = KnotVector.createUniformWrapped(numU, orderU - 1, 0, 1); const vKnots = KnotVector.createUniformWrapped(numV, orderV - 1, 0, 1); const dURadians = 2.0 * Math.PI / numU; @@ -1490,7 +1661,8 @@ export class Sample { centerB: Point3d, radiusA: number, radiusB: number, - numSection: number): BSplineSurface3dH | undefined { + numSection: number, + ): BSplineSurface3dH | undefined { if (numSection < 2) numSection = 2; const controlPoints: number[][][] = []; @@ -1514,20 +1686,22 @@ export class Sample { r0 = r90 = Geometry.interpolate(radiusA, v, radiusB); controlPoints.push(Sample.createBsplineArc90SectionToXYZWArrays(center, axes, r0, r90, false)); } - const result = BSplineSurface3dH.createGrid(controlPoints, - WeightStyle.WeightsSeparateFromCoordinates, - 3, uKnots, 2, vKnots); + const result = BSplineSurface3dH.createGrid(controlPoints, WeightStyle.WeightsSeparateFromCoordinates, 3, uKnots, 2, vKnots); if (result) result.setWrappable(UVSelect.uDirection, BSplineWrapMode.OpenByRemovingKnots); return result; } /** Create bspline surface on xy grid with weights. */ public static createWeightedXYGridBsplineSurface( - numU: number, numV: number, orderU: number, orderV: number, + numU: number, + numV: number, + orderU: number, + orderV: number, weight00: number = 1.0, weight10: number = 1.0, weight01: number = 1.0, - weight11: number = 1.0): BSplineSurface3dH | undefined { + weight11: number = 1.0, + ): BSplineSurface3dH | undefined { const xyzPoles = Sample.createXYGrid(numU, numV, 1.0, 1.0); const weights = []; for (let i = 0; i < numU; i++) @@ -1539,8 +1713,12 @@ export class Sample { return BSplineSurface3dH.create( xyzPoles, weights, - numU, orderU, undefined, - numV, orderV, undefined, + numU, + orderU, + undefined, + numV, + orderV, + undefined, ); } /** Assorted linear sweeps */ @@ -1608,11 +1786,13 @@ export class Sample { // rectangle in xy plane const base = Loop.create(LineString3d.createRectangleXY(Point3d.create(1, 0, 0), 2, 3)); // rotate around the y axis - for (const axis of [ - Ray3d.createXYZUVW(0, 0, 0, 0, 1, 0), - Ray3d.createXYZUVW(5, 0, 0, 0, 1, 0), - Ray3d.createXYZUVW(-1, 0, 0, -1, 1, 0), - ]) { + for ( + const axis of [ + Ray3d.createXYZUVW(0, 0, 0, 0, 1, 0), + Ray3d.createXYZUVW(5, 0, 0, 0, 1, 0), + Ray3d.createXYZUVW(-1, 0, 0, -1, 1, 0), + ] + ) { result.push(RotationalSweep.create(base, axis, Angle.createDegrees(45.0), false)!); result.push(RotationalSweep.create(base, axis, Angle.createDegrees(150.0), true)!); } @@ -1624,7 +1804,8 @@ export class Sample { result.push(Sphere.createCenterRadius(Point3d.create(0, 0, 0), 1.0)); result.push(Sphere.createCenterRadius(Point3d.create(1, 2, 3), 3.0)); const s1 = Sphere.createCenterRadius( - Point3d.create(1, 2, 3), 2.0, + Point3d.create(1, 2, 3), + 2.0, AngleSweep.createStartEndDegrees(-45, 80), ); s1.capped = true; @@ -1633,11 +1814,19 @@ export class Sample { const s2 = Sphere.createFromAxesAndScales( Point3d.create(1, 2, 3), Matrix3d.createRowValues( - 0, 1, 0, - 0, 0, 1, - 1, 0, 0, + 0, + 1, + 0, + 0, + 0, + 1, + 1, + 0, + 0, ), - 4, 4, 4, + 4, + 4, + 4, AngleSweep.createStartEndDegrees(-45, 45), true, )!; @@ -1650,7 +1839,8 @@ export class Sample { Vector3d.unitZ(), 3, 2, - AngleSweep.createFullLatitude(), false, + AngleSweep.createFullLatitude(), + false, )!, ); return result; @@ -1662,9 +1852,16 @@ export class Sample { Transform.createOriginAndMatrix( Point3d.create(0, 0, 0), Matrix3d.createRowValues( - 4, 1, 1, - 1, 4, 1, - 0.5, 0.2, 5), + 4, + 1, + 1, + 1, + 4, + 1, + 0.5, + 0.2, + 5, + ), ), AngleSweep.createFullLatitude(), true, @@ -1688,12 +1885,22 @@ export class Sample { } /** Return a TorusPipe with swept circle in xz plane rotating through an angle range around the Z axis. */ public static createPartialTorusAroundZ( - majorRadius: number, majorSweep: Angle, minorRadius: number, minorStart: Angle, minorEnd: Angle, + majorRadius: number, + majorSweep: Angle, + minorRadius: number, + minorStart: Angle, + minorEnd: Angle, ): RotationalSweep { const arc = Arc3d.createXYZXYZXYZ( - majorRadius, 0, 0, - minorRadius, 0, 0, - 0, minorRadius, 0, + majorRadius, + 0, + 0, + minorRadius, + 0, + 0, + 0, + minorRadius, + 0, AngleSweep.createStartEnd(minorStart, minorEnd), ); const contour = Path.create(arc); @@ -1704,7 +1911,8 @@ export class Sample { const result: TorusPipe[] = []; const center = Point3d.create(1, 2, 3); const frame = Matrix3d.createRotationAroundVector( - Vector3d.create(1, 2, 3), Angle.createRadians(10), + Vector3d.create(1, 2, 3), + Angle.createRadians(10), ) as Matrix3d; const vectorX = frame.columnX(); const vectorY = frame.columnY(); @@ -1725,24 +1933,49 @@ export class Sample { const bY = 1.0; const h = 5.0; const frame = Matrix3d.createRotationAroundVector( - Vector3d.create(0, 0, 1), Angle.createDegrees(10), + Vector3d.create(0, 0, 1), + Angle.createDegrees(10), ) as Matrix3d; const vectorX = frame.columnX(); const vectorY = frame.columnY(); const cornerB = Matrix3d.xyzPlusMatrixTimesCoordinates(cornerA, frame, 0, 0, h); result.push( Box.createDgnBox( - cornerA, Vector3d.unitX(), Vector3d.unitY(), cornerB, aX, aY, aX, aY, capped, + cornerA, + Vector3d.unitX(), + Vector3d.unitY(), + cornerB, + aX, + aY, + aX, + aY, + capped, ) as Box, ); result.push( Box.createDgnBox( - cornerA, Vector3d.unitX(), Vector3d.unitY(), cornerB, aX, aY, bX, bY, capped, + cornerA, + Vector3d.unitX(), + Vector3d.unitY(), + cornerB, + aX, + aY, + bX, + bY, + capped, ) as Box, ); result.push( Box.createDgnBox( - cornerA, vectorX, vectorY, cornerB, aX, aY, bX, bY, capped, + cornerA, + vectorX, + vectorY, + cornerB, + aX, + aY, + bX, + bY, + capped, ) as Box, ); const frameY = Matrix3d.createRotationAroundVector( @@ -1751,15 +1984,27 @@ export class Sample { ) as Matrix3d; result.push( Box.createDgnBox( - cornerA, frameY.columnX(), frameY.columnY(), - cornerA.plusScaled(frameY.columnZ(), h), aX, aY, bX, bY, capped, + cornerA, + frameY.columnX(), + frameY.columnY(), + cornerA.plusScaled(frameY.columnZ(), h), + aX, + aY, + bX, + bY, + capped, ) as Box, ); return result; } /** Create an array of points for a rectangle with corners (x0,y0,z) and (x1,y1,z) */ public static createRectangle( - x0: number, y0: number, x1: number, y1: number, z: number = 0.0, closed: boolean = false, + x0: number, + y0: number, + x1: number, + y1: number, + z: number = 0.0, + closed: boolean = false, ): Point3d[] { const points = [ Point3d.create(x0, y0, z), @@ -1781,7 +2026,8 @@ export class Sample { } /** Create assorted ruled sweeps */ public static createRuledSweeps( - includeParityRegion: boolean = false, includeBagOfCurves: boolean = false, + includeParityRegion: boolean = false, + includeBagOfCurves: boolean = false, ): RuledSweep[] { const allSweeps = []; const contour0 = Loop.create(LineString3d.create(this.createRectangleXY(0, 0, 3, 2, 0))); @@ -1836,8 +2082,14 @@ export class Sample { * @param numEdge number of edges of chorded circle. Angle step is 2PI/numEdge (whether or not closed) * @param closed true to include final point (i.e. return numEdge+1 points) */ - public static createGrowableArrayCirclePoints(radius: number, numEdge: number, closed: boolean = false, - centerX: number = 0, centerY: number = 0, data?: GrowableXYZArray): GrowableXYZArray { + public static createGrowableArrayCirclePoints( + radius: number, + numEdge: number, + closed: boolean = false, + centerX: number = 0, + centerY: number = 0, + data?: GrowableXYZArray, + ): GrowableXYZArray { if (!data) data = new GrowableXYZArray(); data.ensureCapacity(numEdge + (closed ? 1 : 0)); const delta = 2.0 * Math.PI / numEdge; @@ -1851,7 +2103,14 @@ export class Sample { if (points.length === 0 || points[points.length - 1].distanceXY(xyz) > tol) points.push(xyz); } - private static appendToFractalEval(points: Point3d[], pointA: Point3d, pointB: Point3d, pattern: Point2d[], numRecursion: number, perpendicularFactor: number) { + private static appendToFractalEval( + points: Point3d[], + pointA: Point3d, + pointB: Point3d, + pattern: Point2d[], + numRecursion: number, + perpendicularFactor: number, + ) { const point0 = pointA.clone(); Sample.pushIfDistinct(points, pointA); for (const uv of pattern) { @@ -1873,7 +2132,10 @@ export class Sample { * @param perpendicularFactor factor to apply to perpendicular sizing. */ public static createRecursiveFractalPolygon( - poles: Point3d[], pattern: Point2d[], numRecursion: number, perpendicularFactor: number, + poles: Point3d[], + pattern: Point2d[], + numRecursion: number, + perpendicularFactor: number, ): Point3d[] { const points: Point3d[] = []; Sample.pushIfDistinct(points, poles[0]); @@ -2025,7 +2287,8 @@ export class Sample { wrap: boolean = true, xyzA: Point3d = Point3d.create(0, 0, 0), xyzB: Point3d = Point3d.create(1, 0, 0), - xyzC: Point3d = Point3d.create(0, 1, 0)): Point3d[] { + xyzC: Point3d = Point3d.create(0, 1, 0), + ): Point3d[] { const result = [xyzA.clone()]; Sample.appendSplits(result, xyzB, numSplitAB, true); Sample.appendSplits(result, xyzC, numSplitBC, true); @@ -2033,8 +2296,15 @@ export class Sample { return result; } /** Create a box (xyz) from half-lengths and center. */ - public static createCenteredBoxEdges(ax: number = 1, ay: number = 1, az: number = 0, cx: number = 0, cy: number = 0, cz: number = 0, - geometry?: GeometryQuery[]): GeometryQuery[] { + public static createCenteredBoxEdges( + ax: number = 1, + ay: number = 1, + az: number = 0, + cx: number = 0, + cy: number = 0, + cz: number = 0, + geometry?: GeometryQuery[], + ): GeometryQuery[] { if (!geometry) geometry = []; const x0 = cx - ax; @@ -2073,7 +2343,9 @@ export class Sample { const dThetaRadians = arcLength * averageCurvature; return [ IntegratedSpiral3d.createFrom4OutOf5( - "clothoid", r0, r1, + "clothoid", + r0, + r1, Angle.createDegrees(0), Angle.createRadians(dThetaRadians), undefined, @@ -2081,7 +2353,9 @@ export class Sample { Transform.createIdentity(), )!, IntegratedSpiral3d.createFrom4OutOf5( - "bloss", r0, r1, + "bloss", + r0, + r1, Angle.createDegrees(0), undefined, arcLength, @@ -2089,7 +2363,9 @@ export class Sample { Transform.createIdentity(), )!, IntegratedSpiral3d.createFrom4OutOf5( - "clothoid", r0, r1, + "clothoid", + r0, + r1, undefined, Angle.createRadians(dThetaRadians), arcLength, @@ -2097,7 +2373,9 @@ export class Sample { Transform.createIdentity(), )!, IntegratedSpiral3d.createFrom4OutOf5( - "biquadratic", r0, undefined, + "biquadratic", + r0, + undefined, Angle.createDegrees(0), Angle.createRadians(dThetaRadians), arcLength, @@ -2105,7 +2383,9 @@ export class Sample { Transform.createIdentity(), )!, IntegratedSpiral3d.createFrom4OutOf5( - "sine", undefined, r1, + "sine", + undefined, + r1, Angle.createDegrees(0), Angle.createRadians(dThetaRadians), arcLength, @@ -2113,7 +2393,9 @@ export class Sample { Transform.createIdentity(), )!, IntegratedSpiral3d.createFrom4OutOf5( - "cosine", r0, r1, + "cosine", + r0, + r1, Angle.createDegrees(0), Angle.createRadians(dThetaRadians), undefined, @@ -2124,7 +2406,9 @@ export class Sample { ), )!, DirectSpiral3d.createFromLengthAndRadius( - "Arema", r0, r1, + "Arema", + r0, + r1, Angle.createDegrees(0), undefined, arcLength, @@ -2135,7 +2419,9 @@ export class Sample { ), )!, DirectSpiral3d.createFromLengthAndRadius( - "ChineseCubic", r0, r1, + "ChineseCubic", + r0, + r1, Angle.createDegrees(0), undefined, arcLength, @@ -2146,7 +2432,9 @@ export class Sample { ), )!, DirectSpiral3d.createFromLengthAndRadius( - "JapaneseCubic", r0, r1, + "JapaneseCubic", + r0, + r1, Angle.createDegrees(0), undefined, arcLength, @@ -2157,7 +2445,9 @@ export class Sample { ), )!, DirectSpiral3d.createFromLengthAndRadius( - "DirectHalfCosine", r0, r1, + "DirectHalfCosine", + r0, + r1, Angle.createDegrees(0), undefined, arcLength, @@ -2175,7 +2465,8 @@ export class Sample { * * r and theta are circle in xy plane at steps in thetaStepper * * z varies with sin(phi) at steps in phiStepper. */ - public static createTwistingBezier(order: number, + public static createTwistingBezier( + order: number, x0: number, y0: number, r: number, @@ -2193,7 +2484,8 @@ export class Sample { Point4d.create( weight * (x0 + r * Math.cos(theta)), weight * (y0 + r * Math.sin(theta)), - weight * Math.sin(phi), weight, + weight * Math.sin(phi), + weight, ), ); } @@ -2243,7 +2535,9 @@ export class Sample { CurveChainWithDistanceIndex.createCapture( Path.create( Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, 0, 0), Point3d.create(3, 3, 0), Point3d.create(6, 0, 0), + Point3d.create(0, 0, 0), + Point3d.create(3, 3, 0), + Point3d.create(6, 0, 0), ), ), ), @@ -2331,7 +2625,8 @@ export class Sample { AngleSweep.createStartEndDegrees(10, 75), Segment1d.create(0, 1), Transform.createOriginAndMatrix( - Point3d.createZero(), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(30)), + Point3d.createZero(), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(30)), ), "bloss", )!, @@ -2343,7 +2638,8 @@ export class Sample { Path.create( DirectSpiral3d.createDirectHalfCosine( Transform.createOriginAndMatrix( - Point3d.createZero(), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(110)), + Point3d.createZero(), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(110)), ), 50, 350, @@ -2364,7 +2660,12 @@ export class Sample { * @param structure 1 for line segments, 2 for one linestring per tooth, 0 for single linestring */ public static createSquareWavePath( - numTooth: number, dxA: number, dxB: number, yA: number, yB: number, structure: number, + numTooth: number, + dxA: number, + dxB: number, + yA: number, + yB: number, + structure: number, ): Path { const dxAB = dxA + dxB; const path = Path.create(); @@ -2431,10 +2732,14 @@ export class Sample { const result: Arc3d[] = []; const sweep1 = AngleSweep.createStartEndDegrees(-10, 75); const sweep2 = AngleSweep.createStartEndDegrees(160.0, 380.0); - for (const arcs of [ - Sample.createArcs(1.0), Sample.createArcs(0.5), - Sample.createArcs(1.0, sweep1), Sample.createArcs(0.3, sweep2), - ]) { + for ( + const arcs of [ + Sample.createArcs(1.0), + Sample.createArcs(0.5), + Sample.createArcs(1.0, sweep1), + Sample.createArcs(0.3, sweep2), + ] + ) { for (const arc of arcs) result.push(arc); } @@ -2442,7 +2747,9 @@ export class Sample { for (const skewFactor of skewFactors) { for (let i = 0; i < numBase; i++) { const originalArc = result[i]; - result.push(Arc3d.create(originalArc.center, originalArc.vector0, originalArc.vector90.plusScaled(originalArc.vector0, skewFactor), originalArc.sweep)); + result.push( + Arc3d.create(originalArc.center, originalArc.vector0, originalArc.vector90.plusScaled(originalArc.vector0, skewFactor), originalArc.sweep), + ); } } return result; @@ -2535,7 +2842,13 @@ export class Sample { * @param addClosure true to repeat center as closure point */ public static createCutPie( - x0: number, y0: number, radius: number, sweep: AngleSweep, numRadialEdges: number, numArcEdges: number, addClosure = false, + x0: number, + y0: number, + radius: number, + sweep: AngleSweep, + numRadialEdges: number, + numArcEdges: number, + addClosure = false, ): Point3d[] { const points = []; const center = Point3d.create(x0, y0); @@ -2569,7 +2882,14 @@ export class Sample { * @param dy4 */ public static createVerticalStaggerPolygon( - dy1: number, dy2: number, dy3: number, dy4: number, ax: number, ay: number, dx1: number, dx4: number, + dy1: number, + dy2: number, + dy3: number, + dy4: number, + ax: number, + ay: number, + dx1: number, + dx4: number, ): Point3d[] { const points = []; points.push(Point3d.create(0, 0)); @@ -2585,7 +2905,14 @@ export class Sample { // cspell:word creat /** @deprecated in 4.x. Use createVerticalStaggerPolygon instead. */ public static creatVerticalStaggerPolygon( - dy1: number, dy2: number, dy3: number, dy4: number, ax: number, ay: number, dx1: number, dx4: number, + dy1: number, + dy2: number, + dy3: number, + dy4: number, + ax: number, + ay: number, + dx1: number, + dx4: number, ): Point3d[] { return this.createVerticalStaggerPolygon(dy1, dy2, dy3, dy4, ax, ay, dx1, dx4); } @@ -2612,7 +2939,13 @@ export class Sample { * @param close true to add closure edge. */ public static createRegularPolygon( - cx: number, cy: number, cz: number, angle0: Angle, r: number, numPoint: number, close: boolean, + cx: number, + cy: number, + cz: number, + angle0: Angle, + r: number, + numPoint: number, + close: boolean, ): Point3d[] { const points = []; const angleStepRadians = 2.0 * Math.PI / numPoint; @@ -2633,7 +2966,14 @@ export class Sample { * @param close true to add closure edge. */ public static createStar( - cx: number, cy: number, cz: number, r0: number, r1: number | undefined, numPoint: number, close: boolean, theta0?: Angle, + cx: number, + cy: number, + cz: number, + r0: number, + r1: number | undefined, + numPoint: number, + close: boolean, + theta0?: Angle, ): Point3d[] { const points = []; const angleStepRadians = Math.PI / numPoint; @@ -2663,7 +3003,17 @@ export class Sample { * @param rC radius for inner star centers * @param numC number of inner stars */ - public static createStarsInStars(rA0: number, rA1: number, numAPoint: number, rB0: number, rB1: number, numBPoint: number, rC: number, numC: number, close: boolean): Point3d[][] { + public static createStarsInStars( + rA0: number, + rA1: number, + numAPoint: number, + rB0: number, + rB1: number, + numBPoint: number, + rC: number, + numC: number, + close: boolean, + ): Point3d[][] { const loops: Point3d[][] = []; loops.push(this.createStar(0, 0, 0, rA0, rA1, numAPoint, close)); if (numC > 0) { @@ -2715,7 +3065,15 @@ export class Sample { result.push(this.createTriangularUnitGridPolyface(pointA, Vector3d.unitX(), Vector3d.unitY(), 4, 5)); result.push( this.createTriangularUnitGridPolyface( - pointA, Vector3d.unitX(), Vector3d.unitY(), 4, 5, true, true, true, false, + pointA, + Vector3d.unitX(), + Vector3d.unitY(), + 4, + 5, + true, + true, + true, + false, ), ); this.appendGeometry(this.createSimpleParityRegions(), result); @@ -2730,12 +3088,18 @@ export class Sample { * * If the dTheta and dBeta are equal, it is a sine wave in a tilted plane. * * If dTheta and dBeta are different it is a non-planar curve */ - public static createPointSineWave(origin: XYAndZ | undefined, numInterval: number = 24, + public static createPointSineWave( + origin: XYAndZ | undefined, + numInterval: number = 24, xStep: number = Math.PI / 12, - a: number = 1, thetaSweep: AngleSweep = AngleSweep.createStartEndDegrees(0, 360), - b: number = 0, betaSweep: AngleSweep = AngleSweep.createStartEndDegrees(0, 180)): Point3d[] { + a: number = 1, + thetaSweep: AngleSweep = AngleSweep.createStartEndDegrees(0, 360), + b: number = 0, + betaSweep: AngleSweep = AngleSweep.createStartEndDegrees(0, 180), + ): Point3d[] { return this.createPointsByIndexFunctions( - numInterval, SteppedIndexFunctionFactory.createLinear(xStep, origin ? origin.x : 0), + numInterval, + SteppedIndexFunctionFactory.createLinear(xStep, origin ? origin.x : 0), SteppedIndexFunctionFactory.createCosine(a, thetaSweep, origin ? origin.y : 0), SteppedIndexFunctionFactory.createCosine(b, betaSweep, origin ? origin.z : 0), ); @@ -2745,7 +3109,10 @@ export class Sample { * Point3d.create (fx(i,numInterval), fy(i,numInterval), fz(i, numInterval)); */ public static createPointsByIndexFunctions( - numInterval: number, fx: SteppedIndexFunction, fy: SteppedIndexFunction, fz?: SteppedIndexFunction, + numInterval: number, + fx: SteppedIndexFunction, + fy: SteppedIndexFunction, + fz?: SteppedIndexFunction, ): Point3d[] { const points = []; if (numInterval > 0) { @@ -2772,7 +3139,9 @@ export class Sample { channelIndex: number, name: string | undefined, inputName: string | undefined, - input0: number, inputStep: number, numInput: number, + input0: number, + inputStep: number, + numInput: number, dataType: AuxChannelDataType, scalarFunction: (input: number, xyz: Point3d) => number, ): void { @@ -2806,7 +3175,12 @@ export class Sample { * @returns */ public static createMeshInAnnulus( - edgesPerQuadrant: number, center: Point3d, r0: number, r1: number, theta0: Angle, theta1: Angle, + edgesPerQuadrant: number, + center: Point3d, + r0: number, + r1: number, + theta0: Angle, + theta1: Angle, ): IndexedPolyface | undefined { const point0 = []; const point1 = []; @@ -2827,7 +3201,13 @@ export class Sample { } /** Create strokes on an arc at radius r0, then returning at radius r1. */ public static createAnnulusPolyline( - edgesPerQuadrant: number, center: Point3d, r0: number, r1: number, theta0: Angle, theta1: Angle, addClosure: boolean, + edgesPerQuadrant: number, + center: Point3d, + r0: number, + r1: number, + theta0: Angle, + theta1: Angle, + addClosure: boolean, ): Point3d[] { const point0: Point3d[] = []; const point1: Point3d[] = []; @@ -2848,11 +3228,11 @@ export class Sample { return point0; } /** - * Create a grid of lat-long points on a sphere. - * * If pole latitudes appear in the evaluation, a single point (not a circle) is evaluated. - * * Circles at various latitudes proceed south to north. - * * If first and last angles of longitudeSweep match, that meridian is not duplicated. - * * Longitudes can wrap freely. + * Create a grid of lat-long points on a sphere. + * * If pole latitudes appear in the evaluation, a single point (not a circle) is evaluated. + * * Circles at various latitudes proceed south to north. + * * If first and last angles of longitudeSweep match, that meridian is not duplicated. + * * Longitudes can wrap freely. * @param transform local to world * @param numLatitudeStep number of latitude steps (poles count if they are in the sweeps) * @param numLongitudeStep number of longitude steps @@ -2898,7 +3278,13 @@ export class Sample { * @returns */ public static createArcStrokes( - edgesPerQuadrant: number, center: Point3d, r0: number, theta0: Angle, theta1: Angle, addClosure: boolean = true, z: number = 0, + edgesPerQuadrant: number, + center: Point3d, + r0: number, + theta0: Angle, + theta1: Angle, + addClosure: boolean = true, + z: number = 0, ): Point3d[] { const point0: Point3d[] = []; if (edgesPerQuadrant < 1) @@ -2923,7 +3309,9 @@ export class Sample { * @param acceptFunction (x0: number, y0: number)=> boolean */ public static sweepXZLineStringToMeshWithHoles( - xzPoints: number[][], ySweep: number, acceptFunction: (x0: number, y0: number) => boolean, + xzPoints: number[][], + ySweep: number, + acceptFunction: (x0: number, y0: number) => boolean, ): IndexedPolyface { const builder = PolyfaceBuilder.create(); for (let i0 = 0; i0 + 1 < xzPoints.length; i0++) { @@ -2972,7 +3360,7 @@ export class Sample { result = [start.clone()]; } let numAdded = 0; - for (; ;) { + for (;;) { for (const step of steps) { if (++numAdded > numStroke) return result; @@ -2984,7 +3372,7 @@ export class Sample { * @param theta angle * @param a period multiplier. If odd, this is the petal count; if even, twice the number of petals. * @param z z-coordinate for output - */ + */ public static createRosePoint3d(theta: number, a: number, z: number = 0): Point3d { const r = Math.cos(a * theta); return Point3d.create(r * Math.cos(theta), r * Math.sin(theta), z); @@ -2992,7 +3380,7 @@ export class Sample { /** Create a point on the polar parametric curve r = cos(a * theta), aka "rose". * @param theta angle * @param a period multiplier. If odd, this is the petal count; if even, twice the number of petals. - */ + */ public static createRosePoint2d(theta: number, a: number): Point2d { return Point2d.createFrom(Sample.createRosePoint3d(theta, a)); } @@ -3005,7 +3393,8 @@ export class Sample { public static createMeshFromFrankeSurface( size: number, options?: StrokeOptions, - scales?: number[]): IndexedPolyface | undefined { + scales?: number[], + ): IndexedPolyface | undefined { const builder = PolyfaceBuilder.create(options); builder.addUVGridBody(new FrankeSurface(scales), size, size); return builder.claimPolyface(true); @@ -3034,5 +3423,4 @@ export class Sample { placement.multiplyPoint3dArrayInPlace(points); return points; } - } diff --git a/core/geometry/src/serialization/IModelJsonSchema.ts b/core/geometry/src/serialization/IModelJsonSchema.ts index 8bcfa088687c..21e1d73ce6b2 100644 --- a/core/geometry/src/serialization/IModelJsonSchema.ts +++ b/core/geometry/src/serialization/IModelJsonSchema.ts @@ -115,7 +115,7 @@ export namespace IModelJson { /** polynomial order (one more than degree) in the v parameter direction */ orderV: number; /** Square grid of control points (aka poles) in row major order (row is along the u direction) */ - points: [[[number]]]; // each inner array is xyz or xyzw for a single control point. each middle array is a row of control points. + points: [[[number]]]; // each inner array is xyz or xyzw for a single control point. each middle array is a row of control points. /** Array of knots for the u direction bspline */ uKnots: [number]; /** Array of knots for the v direction bspline */ @@ -325,7 +325,6 @@ export namespace IModelJson { * @public */ export interface TransitionSpiralProps extends AxesProps { - /** origin of the coordinate system. */ origin: XYZProps; /** angle at departure from origin. */ @@ -410,7 +409,7 @@ export namespace IModelJson { topOrigin?: XYZProps; /** optional height. This is only used if `topOrigin` is omitted. * * If omitted, `baseX` is used. - */ + */ height?: number; /** x size on top section. * * If omitted, `baseX` is used. @@ -493,10 +492,10 @@ export namespace IModelJson { * @public */ export interface AuxChannelDataProps { - /** The input value for this data. */ - input: number; - /** The vertex values for this data. A single value per vertex for scalar and distance types and 3 values (x,y,z) for normal or vector channels. */ - values: number[]; + /** The input value for this data. */ + input: number; + /** The vertex values for this data. A single value per vertex for scalar and distance types and 3 values (x,y,z) for normal or vector channels. */ + values: number[]; } /** * Interface for a channel of analytical mesh data. @@ -504,25 +503,25 @@ export namespace IModelJson { * @public */ export interface AuxChannelProps { - /** An array of analytical data at one or more input values. */ - data: AuxChannelDataProps[]; - /** The type of data stored in this channel. */ - dataType: AuxChannelDataType; - /** Optional channel name. */ - name?: string; - /** Optional input name. */ - inputName?: string; + /** An array of analytical data at one or more input values. */ + data: AuxChannelDataProps[]; + /** The type of data stored in this channel. */ + dataType: AuxChannelDataType; + /** Optional channel name. */ + name?: string; + /** Optional input name. */ + inputName?: string; } /** * Interface for analytical mesh data. * See `PolyfaceAuxData` for further information. * @public - */ + */ export interface AuxDataProps { - /** Array with one or more channels of auxiliary data. */ - channels: AuxChannelProps[]; - /** Indices mapping channel data to the mesh facets (must be parallel to mesh indices). */ - indices: number[]; + /** Array with one or more channels of auxiliary data. */ + channels: AuxChannelProps[]; + /** Indices mapping channel data to the mesh facets (must be parallel to mesh indices). */ + indices: number[]; } /** * Interface for extra data attached to an indexed mesh. @@ -589,7 +588,6 @@ export namespace IModelJson { * @public */ export class Reader { - public constructor() { // empty ctor } @@ -653,11 +651,19 @@ export namespace IModelJson { return undefined; } - private static parseNumberArrayProperty(json: any, propertyName: string, minValues: number, maxValues: number | undefined, defaultValue?: number[] | undefined): number[] | undefined { + private static parseNumberArrayProperty( + json: any, + propertyName: string, + minValues: number, + maxValues: number | undefined, + defaultValue?: number[] | undefined, + ): number[] | undefined { if (json.hasOwnProperty(propertyName)) { const value = json[propertyName]; - if (Array.isArray(value) - && value.length >= minValues && (undefined === maxValues || value.length <= maxValues)) { + if ( + Array.isArray(value) + && value.length >= minValues && (undefined === maxValues || value.length <= maxValues) + ) { const result = []; for (const a of value) { result.push(a); @@ -763,7 +769,8 @@ export namespace IModelJson { } private static parseArcByVectorProps(data?: ArcByVectorProps): Arc3d | undefined { - if (data + if ( + data && data.center !== undefined && data.vectorX !== undefined && data.vectorY !== undefined @@ -773,7 +780,8 @@ export namespace IModelJson { Point3d.fromJSON(data.center), Vector3d.fromJSON(data.vectorX), Vector3d.fromJSON(data.vectorY), - AngleSweep.fromJSON(data.sweepStartEnd)); + AngleSweep.fromJSON(data.sweepStartEnd), + ); } return undefined; } @@ -826,20 +834,26 @@ export namespace IModelJson { let candidate: TransitionSpiral3d | undefined; candidate = IntegratedSpiral3d.createFrom4OutOf5( spiralType, - startRadius, endRadius, - startBearing, endBearing, + startRadius, + endRadius, + startBearing, + endBearing, length, interval, - Transform.createOriginAndMatrix(origin, axes)); + Transform.createOriginAndMatrix(origin, axes), + ); if (candidate) return candidate; candidate = DirectSpiral3d.createFromLengthAndRadius( spiralType, - startRadius, endRadius, - startBearing, endBearing, + startRadius, + endRadius, + startBearing, + endBearing, length, interval, - Transform.createOriginAndMatrix(origin, axes)); + Transform.createOriginAndMatrix(origin, axes), + ); if (candidate) return candidate; } @@ -850,7 +864,8 @@ export namespace IModelJson { public static parseBcurve(data?: any): BSplineCurve3d | BSplineCurve3dH | undefined { let newCurve: BSplineCurve3d | BSplineCurve3dH | undefined; let dim: number; - if (data !== undefined + if ( + data !== undefined && data.hasOwnProperty("knots") && Array.isArray(data.knots) && data.hasOwnProperty("order") && Number.isFinite(data.order) && data.hasOwnProperty("points") && Array.isArray(data.points) && Array.isArray(data.points[0]) @@ -904,7 +919,6 @@ export namespace IModelJson { /** parse polyface aux data content to PolyfaceAuxData instance */ public static parsePolyfaceAuxData(data: any = undefined, numPerFace: number = 0): PolyfaceAuxData | undefined { - if (!Array.isArray(data.channels) || !Array.isArray(data.indices)) return undefined; @@ -921,7 +935,9 @@ export namespace IModelJson { } const auxData = new PolyfaceAuxData(outChannels, []); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.indices, numPerFace, (x: number) => { auxData.indices.push(x); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.indices, numPerFace, (x: number) => { + auxData.indices.push(x); + }); return auxData; } @@ -930,8 +946,10 @@ export namespace IModelJson { public static parseIndexedMesh(data?: any): IndexedPolyface | undefined { // {Coord:[[x,y,z],. . . ], -- simple xyz for each point // CoordIndex[1,2,3,0] -- zero-terminated, one based !!! - if (data.hasOwnProperty("point") && Array.isArray(data.point) - && data.hasOwnProperty("pointIndex") && Array.isArray(data.pointIndex)) { + if ( + data.hasOwnProperty("point") && Array.isArray(data.point) + && data.hasOwnProperty("pointIndex") && Array.isArray(data.pointIndex) + ) { const polyface = IndexedPolyface.create(); const numPerFace = data.hasOwnProperty("numPerFace") ? data.numPerFace : 0; if (data.hasOwnProperty("twoSided")) { @@ -954,29 +972,34 @@ export namespace IModelJson { if (Geometry.isNumberArray(uvw, 3)) polyface.addNormalXYZ(uvw[0], uvw[1], uvw[2]); } - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.normalIndex, numPerFace, - (x: number) => { polyface.addNormalIndex(x); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.normalIndex, numPerFace, (x: number) => { + polyface.addNormalIndex(x); + }); } if (data.hasOwnProperty("param") && Array.isArray(data.param) && data.hasOwnProperty("paramIndex")) { for (const uv of data.param) { if (Geometry.isNumberArray(uv, 2)) polyface.addParamUV(uv[0], uv[1]); } - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.paramIndex, numPerFace, - (x: number) => { polyface.addParamIndex(x); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.paramIndex, numPerFace, (x: number) => { + polyface.addParamIndex(x); + }); } if (data.hasOwnProperty("color") && Array.isArray(data.color) && data.hasOwnProperty("colorIndex")) { for (const c of data.color) polyface.addColor(c); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.colorIndex, numPerFace, - (x: number) => { polyface.addColorIndex(x); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.colorIndex, numPerFace, (x: number) => { + polyface.addColorIndex(x); + }); } for (const p of data.point) polyface.addPointXYZ(p[0], p[1], p[2]); - SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.pointIndex, numPerFace, - (i: number, v?: boolean) => { polyface.addPointIndex(i, v); }, - () => { polyface.terminateFacet(false); }); + SerializationHelpers.announceZeroBasedIndicesFromSignedOneBasedIndices(data.pointIndex, numPerFace, (i: number, v?: boolean) => { + polyface.addPointIndex(i, v); + }, () => { + polyface.terminateFacet(false); + }); if (!polyface.validateAllIndices()) return undefined; @@ -1008,7 +1031,8 @@ export namespace IModelJson { public static parseBsurf(data?: any): BSplineSurface3d | BSplineSurface3dH | undefined { let newSurface: BSplineSurface3d | BSplineSurface3dH | undefined; let dim: number; - if (data !== undefined + if ( + data !== undefined && data.hasOwnProperty("uKnots") && Array.isArray(data.uKnots) && data.hasOwnProperty("vKnots") && Array.isArray(data.vKnots) && data.hasOwnProperty("orderU") && Number.isFinite(data.orderU) @@ -1016,16 +1040,38 @@ export namespace IModelJson { && data.hasOwnProperty("points") && Array.isArray(data.points) && Array.isArray(data.points[0]) && Array.isArray(data.points[0][0]) && (dim = data.points[0][0].length) >= 3 && dim <= 4 ) { - const myData = SerializationHelpers.createBSplineSurfaceData(data.points, dim, data.uKnots, data.points[0].length, data.orderU, data.vKnots, data.points.length, data.orderV); + const myData = SerializationHelpers.createBSplineSurfaceData( + data.points, + dim, + data.uKnots, + data.points[0].length, + data.orderU, + data.vKnots, + data.points.length, + data.orderV, + ); if (data.hasOwnProperty("closedU") && true === data.closedU) myData.uParams.closed = true; if (data.hasOwnProperty("closedV") && true === data.closedV) myData.vParams.closed = true; if (SerializationHelpers.Import.prepareBSplineSurfaceData(myData, { jsonPoles: true })) { if (dim === 3) - newSurface = BSplineSurface3d.createGrid(myData.poles as number[][][], myData.uParams.order, myData.uParams.knots, myData.vParams.order, myData.vParams.knots); + newSurface = BSplineSurface3d.createGrid( + myData.poles as number[][][], + myData.uParams.order, + myData.uParams.knots, + myData.vParams.order, + myData.vParams.knots, + ); else - newSurface = BSplineSurface3dH.createGrid(myData.poles as number[][][], WeightStyle.WeightsAlreadyAppliedToCoordinates, myData.uParams.order, myData.uParams.knots, myData.vParams.order, myData.vParams.knots); + newSurface = BSplineSurface3dH.createGrid( + myData.poles as number[][][], + WeightStyle.WeightsAlreadyAppliedToCoordinates, + myData.uParams.order, + myData.uParams.knots, + myData.vParams.order, + myData.vParams.knots, + ); if (undefined !== newSurface) { if (undefined !== myData.uParams.wrapMode) newSurface.setWrappable(UVSelect.uDirection, myData.uParams.wrapMode); @@ -1048,10 +1094,12 @@ export namespace IModelJson { const capped = Reader.parseBooleanProperty(json, "capped", false) as boolean; - if (start + if ( + start && end && startRadius !== undefined - && endRadius !== undefined) { + && endRadius !== undefined + ) { if (axes === undefined) { const axisVector = Vector3d.createStartEnd(start, end); const frame = Matrix3d.createRigidHeadsUp(axisVector, AxisOrder.ZXY); @@ -1073,9 +1121,11 @@ export namespace IModelJson { const capped = Reader.parseBooleanProperty(json, "capped", false) as boolean; - if (start + if ( + start && end - && radius !== undefined) { + && radius !== undefined + ) { return Cone.createAxisPoints(start, end, radius, radius, capped); } return undefined; @@ -1092,7 +1142,8 @@ export namespace IModelJson { const contour = Reader.parse(json.contour); const capped = Reader.parseBooleanProperty(json, "capped"); const extrusionVector = Reader.parseVector3dProperty(json, "vector"); - if (contour instanceof GeometryQuery + if ( + contour instanceof GeometryQuery && "curveCollection" === contour.geometryCategory && capped !== undefined && extrusionVector @@ -1110,7 +1161,8 @@ export namespace IModelJson { const axisVector = Reader.parseVector3dProperty(json, "axis"); const center = Reader.parsePoint3dProperty(json, "center"); const sweepDegrees = Reader.parseNumberProperty(json, "sweepAngle"); - if (contour instanceof GeometryQuery + if ( + contour instanceof GeometryQuery && "curveCollection" === contour.geometryCategory && sweepDegrees !== undefined && capped !== undefined @@ -1121,7 +1173,8 @@ export namespace IModelJson { contour, Ray3d.createCapture(center, axisVector), Angle.createDegrees(sweepDegrees), - capped); + capped, + ); } return undefined; } @@ -1143,7 +1196,8 @@ export namespace IModelJson { if (origin && !topOrigin && height) topOrigin = Matrix3d.xyzPlusMatrixTimesXYZ(origin, axes, Vector3d.create(0, 0, height)); - if (capped !== undefined + if ( + capped !== undefined && baseX !== undefined && baseY !== undefined && topY !== undefined @@ -1172,11 +1226,13 @@ export namespace IModelJson { const capped = Reader.parseBooleanProperty(json, "capped", false); - if (center !== undefined + if ( + center !== undefined && radiusX !== undefined && radiusY !== undefined && radiusZ !== undefined - && capped !== undefined) { + && capped !== undefined + ) { return Sphere.createFromAxesAndScales(center, axes, radiusX, radiusY, radiusZ, latitudeStartEnd, capped); } return undefined; @@ -1185,26 +1241,36 @@ export namespace IModelJson { public static parseRuledSweep(json?: RuledSweepProps): RuledSweep | undefined { const capped = Reader.parseBooleanProperty(json, "capped", false); const contours = this.loadContourArray(json, "contour"); - if (contours !== undefined - && capped !== undefined) { + if ( + contours !== undefined + && capped !== undefined + ) { return RuledSweep.create(contours, capped); } return undefined; } /** Parse TorusPipe props to TorusPipe instance. */ public static parseTorusPipe(json?: TorusPipeProps): TorusPipe | undefined { - const axes = Reader.parseOrientation(json, true)!; // force frame to be pure rotation (no scale or mirror)! + const axes = Reader.parseOrientation(json, true)!; // force frame to be pure rotation (no scale or mirror)! const center = Reader.parsePoint3dProperty(json, "center"); const radiusA = Reader.parseNumberProperty(json, "majorRadius"); const radiusB = Reader.parseNumberProperty(json, "minorRadius"); const sweepAngle = Reader.parseAngleProperty(json, "sweepAngle", undefined); const capped = Reader.parseBooleanProperty(json, "capped", false)!; - if (center + if ( + center && radiusA !== undefined - && radiusB !== undefined) { - return TorusPipe.createDgnTorusPipe(center, axes.columnX(), axes.columnY(), - radiusA, radiusB, - sweepAngle ? sweepAngle : Angle.createDegrees(360), capped); + && radiusB !== undefined + ) { + return TorusPipe.createDgnTorusPipe( + center, + axes.columnX(), + axes.columnY(), + radiusA, + radiusB, + sweepAngle ? sweepAngle : Angle.createDegrees(360), + capped, + ); } return undefined; } @@ -1233,7 +1299,6 @@ export namespace IModelJson { return Reader.parseArcObject(json.arc); } else if (json.hasOwnProperty("point")) { return Reader.parseCoordinate(json.point); - } else if (json.hasOwnProperty("bcurve")) { return Reader.parseBcurve(json.bcurve); } else if (json.hasOwnProperty("interpolationCurve")) { @@ -1290,7 +1355,6 @@ export namespace IModelJson { * @public */ export class Writer extends GeometryHandler { - public handleTaggedNumericData(data: TaggedNumericData): TaggedNumericDataProps { const result: TaggedNumericDataProps = { tagA: data.tagA, tagB: data.tagB }; if (data.intData !== undefined && data.intData.length > 0) @@ -1387,7 +1451,6 @@ export namespace IModelJson { value.endRadius = data.nominalR1; value.length = data.nominalL1; return { transitionSpiral: value }; - } else if (data instanceof IntegratedSpiral3d) { // TODO: HANDLE NONRIGID TRANSFORM !! // the spiral may have indication of how it was defined. If so, use defined/undefined state of the original data @@ -1435,7 +1498,6 @@ export namespace IModelJson { /** Convert strongly typed instance to tagged json */ public handleCone(data: Cone): any { - const radiusA = data.getRadiusA(); const radiusB = data.getRadiusB(); const centerA = data.getCenterA(); @@ -1444,11 +1506,13 @@ export namespace IModelJson { const vectorY = data.getVectorY(); const axisVector = Vector3d.createStartEnd(centerA, centerB); - if (Geometry.isSameCoordinate(radiusA, radiusB) + if ( + Geometry.isSameCoordinate(radiusA, radiusB) && vectorX.isPerpendicularTo(axisVector) && vectorY.isPerpendicularTo(axisVector) && Geometry.isSameCoordinate(vectorX.magnitude(), 1.0) - && Geometry.isSameCoordinate(vectorY.magnitude(), 1.0)) { + && Geometry.isSameCoordinate(vectorY.magnitude(), 1.0) + ) { return { cylinder: { capped: data.capped, @@ -1534,8 +1598,9 @@ export namespace IModelJson { public handleLineString3d(data: LineString3d): any { const pointsA = data.points; const pointsB = []; - if (pointsA) + if (pointsA) { for (const p of pointsA) pointsB.push(p.toJSON()); + } return { lineString: pointsB }; } @@ -1543,8 +1608,9 @@ export namespace IModelJson { public handlePointString3d(data: PointString3d): any { const pointsA = data.points; const pointsB = []; - if (pointsA) + if (pointsA) { for (const p of pointsA) pointsB.push(p.toJSON()); + } return { pointString: pointsB }; } @@ -1589,9 +1655,11 @@ export namespace IModelJson { const extrusionVector = data.cloneSweepVector(); const curves = data.getCurvesRef(); const capped = data.capped; - if (extrusionVector + if ( + extrusionVector && curves - && capped !== undefined) { + && capped !== undefined + ) { return { linearSweep: { contour: curves.dispatchToGeometryHandler(this), @@ -1607,9 +1675,11 @@ export namespace IModelJson { public handleRuledSweep(data: RuledSweep): any { const contours = data.cloneContours(); const capped = data.capped; - if (contours + if ( + contours && contours.length > 1 - && capped !== undefined) { + && capped !== undefined + ) { const jsonContours = []; for (const c of contours) { jsonContours.push(this.emit(c)); @@ -1671,7 +1741,7 @@ export namespace IModelJson { while (visitor.moveToNextFacet()) { for (let i = 0; i < visitor.indexCount; i++) contents.indices.push(visitor.auxData!.indices[i] + 1); - contents.indices.push(0); // facet terminator. + contents.indices.push(0); // facet terminator. } for (const inChannel of auxData.channels) { const outChannel: AuxChannelProps = { data: [], dataType: inChannel.dataType, name: inChannel.name, inputName: inChannel.inputName }; @@ -1703,7 +1773,6 @@ export namespace IModelJson { pf.data.normal.getVector3dAtCheckedVectorIndex(i, normal); normals.push(normal.toJSON()); } - } if (pf.data.param) { @@ -1729,10 +1798,10 @@ export namespace IModelJson { // All meshes have point and point index ... for (let i = 0; i < n; i++) { // Change sign of value to be pushed based on whether or not the edge was originally visible or not - const toPush = pf.data.edgeVisible[indexCounter + i] ? visitor.pointIndex[i] + 1 : - (visitor.clientPointIndex(i) + 1); + const toPush = pf.data.edgeVisible[indexCounter + i] ? visitor.pointIndex[i] + 1 : -(visitor.clientPointIndex(i) + 1); pointIndex.push(toPush); } - pointIndex.push(0); // facet terminator. + pointIndex.push(0); // facet terminator. indexCounter += visitor.indexCount; if (visitor.normalIndex) { @@ -1857,9 +1926,16 @@ export namespace IModelJson { /** Convert strongly typed instance to tagged json */ private handleBSplineSurface(surface: BSplineSurface3d | BSplineSurface3dH): any { - const data = SerializationHelpers.createBSplineSurfaceData(surface.coffs, surface.poleDimension, - surface.knots[UVSelect.uDirection].knots, surface.numPolesUV(UVSelect.uDirection), surface.orderUV(UVSelect.uDirection), - surface.knots[UVSelect.vDirection].knots, surface.numPolesUV(UVSelect.vDirection), surface.orderUV(UVSelect.vDirection)); + const data = SerializationHelpers.createBSplineSurfaceData( + surface.coffs, + surface.poleDimension, + surface.knots[UVSelect.uDirection].knots, + surface.numPolesUV(UVSelect.uDirection), + surface.orderUV(UVSelect.uDirection), + surface.knots[UVSelect.vDirection].knots, + surface.numPolesUV(UVSelect.vDirection), + surface.orderUV(UVSelect.vDirection), + ); const wrapModeU = surface.getWrappable(UVSelect.uDirection); const wrapModeV = surface.getWrappable(UVSelect.vDirection); diff --git a/core/geometry/src/serialization/SerializationHelpers.ts b/core/geometry/src/serialization/SerializationHelpers.ts index f15f904e5379..1be7be75ba39 100644 --- a/core/geometry/src/serialization/SerializationHelpers.ts +++ b/core/geometry/src/serialization/SerializationHelpers.ts @@ -62,13 +62,33 @@ export namespace SerializationHelpers { } /** Constructor for BSplineCurveData that populates the required data. Inputs are captured, not copied. */ - export function createBSplineCurveData(poles: number[][] | Float64Array, dim: number, knots: number[] | Float64Array, numPoles: number, order: number): BSplineCurveData { + export function createBSplineCurveData( + poles: number[][] | Float64Array, + dim: number, + knots: number[] | Float64Array, + numPoles: number, + order: number, + ): BSplineCurveData { return { poles, dim, params: { numPoles, order, knots } }; } /** Constructor for BSplineSurfaceData that populates the required data. Inputs are captured, not copied. */ - export function createBSplineSurfaceData(poles: number[][][] | Float64Array, dim: number, uKnots: number[] | Float64Array, uNumPoles: number, uOrder: number, vKnots: number[] | Float64Array, vNumPoles: number, vOrder: number): BSplineSurfaceData { - return { poles, dim, uParams: { numPoles: uNumPoles, order: uOrder, knots: uKnots }, vParams: { numPoles: vNumPoles, order: vOrder, knots: vKnots } }; + export function createBSplineSurfaceData( + poles: number[][][] | Float64Array, + dim: number, + uKnots: number[] | Float64Array, + uNumPoles: number, + uOrder: number, + vKnots: number[] | Float64Array, + vNumPoles: number, + vOrder: number, + ): BSplineSurfaceData { + return { + poles, + dim, + uParams: { numPoles: uNumPoles, order: uOrder, knots: uKnots }, + vParams: { numPoles: vNumPoles, order: vOrder, knots: vKnots }, + }; } /** Clone B-spline curve data */ @@ -111,7 +131,7 @@ export namespace SerializationHelpers { } /** Copy B-spline curve data from source to dest */ - function copyBSplineCurveDataPoles(source: BSplineCurveData): {poles?: number[][], weights?: number[]} { + function copyBSplineCurveDataPoles(source: BSplineCurveData): { poles?: number[][], weights?: number[] } { let nPole = 0; let nCoordPerPole = 0; let nPoleCoords = 0; @@ -155,11 +175,11 @@ export namespace SerializationHelpers { poles = NumberArray.copy2d(source.poles); if (poles && source.weights) weights = NumberArray.create(source.weights); - return {poles, weights}; + return { poles, weights }; } /** Copy B-spline surface data from source to dest */ - function copyBSplineSurfaceDataPoles(source: BSplineSurfaceData): {poles?: number[][][], weights?: number[][]} { + function copyBSplineSurfaceDataPoles(source: BSplineSurfaceData): { poles?: number[][][], weights?: number[][] } { let nPoleRow = 0; let nPolePerRow = 0; let nCoordPerPole = 0; @@ -215,7 +235,7 @@ export namespace SerializationHelpers { else weights = NumberArray.copy2d(source.weights); } - return {poles, weights}; + return { poles, weights }; } /** Convert B-spline curve data arrays to the types specified by options. */ @@ -282,7 +302,7 @@ export namespace SerializationHelpers { * @param numPerBlock index blocking: fixed blocks of size numPerBlock > 1, possibly 0-padded; otherwise, variable-sized blocks terminated by 0 * @param announceZeroBasedIndex callback to receive a 0-based index and optional flag indicating whether the sign of the source index is positive * @param terminateBlock optional callback called after each index block has been announced - */ + */ export function announceZeroBasedIndicesFromSignedOneBasedIndices( sourceIndices: Int32Array, numPerBlock: number, @@ -296,7 +316,7 @@ export namespace SerializationHelpers { numIndices -= sourceIndices.length % numPerBlock; for (let i = 0; i < numIndices; i++) { const p = sourceIndices[i]; - if (p !== 0) // skip padding + if (p !== 0) // skip padding announceZeroBasedIndex(Math.abs(p) - 1, p > 0); if (terminateBlock && ((i + 1) % numPerBlock) === 0) terminateBlock(); @@ -304,14 +324,14 @@ export namespace SerializationHelpers { } else { for (let i = 0; i < numIndices; i++) { const p = sourceIndices[i]; - if (p !== 0) // skip terminator + if (p !== 0) // skip terminator announceZeroBasedIndex(Math.abs(p) - 1, p > 0); if (terminateBlock) { if (p === 0) { - if (i + 1 === numIndices || sourceIndices[i + 1] !== 0) // skip extra terminators + if (i + 1 === numIndices || sourceIndices[i + 1] !== 0) // skip extra terminators terminateBlock(); } else { - if (i + 1 === numIndices) // missing last terminator + if (i + 1 === numIndices) // missing last terminator terminateBlock(); } } @@ -326,7 +346,7 @@ export namespace SerializationHelpers { * @param numPerBlock index blocking: fixed blocks of size numPerBlock > 1, possibly 0-padded; otherwise, variable-sized blocks terminated by 0 * @param announceZeroBasedIndex callback to receive a 0-based index * @param terminateBlock optional callback called after each index block has been announced - */ + */ export function announceZeroBasedIndicesWithExternalBlocking( sourceIndices: Int32Array, blockingIndices: Int32Array, @@ -345,7 +365,7 @@ export namespace SerializationHelpers { numBlocking -= blockingIndices.length % numPerBlock; for (let iBlocking = 0; iBlocking < numBlocking && iSource < sourceIndices.length; iBlocking++) { const p = blockingIndices[iBlocking]; - if (p !== 0) // skip padding + if (p !== 0) // skip padding announceZeroBasedIndex(sourceIndices[iSource++]); if (terminateBlock && ((iBlocking + 1) % numPerBlock) === 0) terminateBlock(); @@ -353,14 +373,14 @@ export namespace SerializationHelpers { } else { for (let iBlocking = 0; iBlocking < numBlocking && iSource < sourceIndices.length; iBlocking++) { const p = blockingIndices[iBlocking]; - if (p !== 0) // skip terminator + if (p !== 0) // skip terminator announceZeroBasedIndex(sourceIndices[iSource++]); if (terminateBlock) { if (p === 0) { - if (iBlocking + 1 === numBlocking || blockingIndices[iBlocking + 1] !== 0) // skip extra terminators + if (iBlocking + 1 === numBlocking || blockingIndices[iBlocking + 1] !== 0) // skip extra terminators terminateBlock(); } else { - if (iBlocking + 1 === numBlocking) // missing last terminator + if (iBlocking + 1 === numBlocking) // missing last terminator terminateBlock(); } } @@ -371,14 +391,14 @@ export namespace SerializationHelpers { /** Helper class for preparing geometry data for import. */ export class Import { /** copy knots, with options to control destination type and extraneous knot removal */ - private static copyKnots(knots: Float64Array | number[], options?: BSplineDataOptions, iStart?: number, iEnd?: number): Float64Array| number[] { + private static copyKnots(knots: Float64Array | number[], options?: BSplineDataOptions, iStart?: number, iEnd?: number): Float64Array | number[] { if (undefined === iStart) iStart = 0; if (undefined === iEnd) iEnd = knots.length; if (options?.removeExtraKnots) { ++iStart; // ignore start knot - --iEnd; // ignore end knot + --iEnd; // ignore end knot } let newNumKnots = iEnd - iStart; if (newNumKnots < 0) @@ -403,21 +423,26 @@ export namespace SerializationHelpers { * @returns open knots if legacy periodic B-spline input data is recognized; otherwise, undefined * @see Export.closeLegacyPeriodicKnots */ - private static openLegacyPeriodicKnots(knots: Float64Array | number[], numPoles: number, order: number, options?: BSplineDataOptions): Float64Array | number[] | undefined { + private static openLegacyPeriodicKnots( + knots: Float64Array | number[], + numPoles: number, + order: number, + options?: BSplineDataOptions, + ): Float64Array | number[] | undefined { const numKnots = knots.length; if (order < 2 || numPoles + 2 * order - 1 !== numKnots) - return undefined; // not legacy periodic knots + return undefined; // not legacy periodic knots const startKnot = knots[order - 1]; const endKnot = knots[numKnots - order]; - const iStart0 = Math.floor(order / 2); // index of first expected multiple of the start knot - const iEnd0 = iStart0 + numPoles; // index of first expected multiple of the end knot - const iEnd1 = iEnd0 + order; // one past index of last expected multiple of the end knot + const iStart0 = Math.floor(order / 2); // index of first expected multiple of the start knot + const iEnd0 = iStart0 + numPoles; // index of first expected multiple of the end knot + const iEnd1 = iEnd0 + order; // one past index of last expected multiple of the end knot for (let i = 0; i < order; ++i) { if (Math.abs(knots[iStart0 + i] - startKnot) >= KnotVector.knotTolerance) - return undefined; // start knot multiplicity too small + return undefined; // start knot multiplicity too small if (Math.abs(knots[iEnd0 + i] - endKnot) >= KnotVector.knotTolerance) - return undefined; // end knot multiplicity too small + return undefined; // end knot multiplicity too small } return this.copyKnots(knots, options, iStart0, iEnd1); } @@ -454,7 +479,7 @@ export namespace SerializationHelpers { const wraparoundPt = []; for (let j = 0; j < data.dim; ++j) wraparoundPt.push(polesExpanded[i][j]); - polesExpanded.push(wraparoundPt); // append degree wraparound poles + polesExpanded.push(wraparoundPt); // append degree wraparound poles } if (weightsExpanded) { for (let i = 0; i < data.params.order - 1; ++i) @@ -470,7 +495,7 @@ export namespace SerializationHelpers { data.params.knots = this.copyKnots(data.params.knots, options); } - data.params.closed = undefined; // we are open + data.params.closed = undefined; // we are open convertBSplineCurveDataArrays(data, options); return true; @@ -505,16 +530,16 @@ export namespace SerializationHelpers { data.poles = polesExpanded = arrays.poles; data.weights = weightsExpanded = arrays.weights; } - for (let i = 0; i < data.vParams.numPoles; ++i) { // #rows + for (let i = 0; i < data.vParams.numPoles; ++i) { // #rows for (let j = 0; j < data.uParams.order - 1; ++j) { const wraparoundPt = []; for (let k = 0; k < data.dim; ++k) wraparoundPt.push(polesExpanded[i][j][k]); - polesExpanded[i].push(wraparoundPt); // append degreeU wraparound poles to each row + polesExpanded[i].push(wraparoundPt); // append degreeU wraparound poles to each row } } if (weightsExpanded) { - for (let i = 0; i < data.vParams.numPoles; ++i) // #rows + for (let i = 0; i < data.vParams.numPoles; ++i) // #rows for (let j = 0; j < data.uParams.order - 1; ++j) weightsExpanded[i].push(weightsExpanded[i][j]); // append degreeU wraparound weights to each row } @@ -540,20 +565,20 @@ export namespace SerializationHelpers { } for (let i = 0; i < data.vParams.order - 1; ++i) { const wrapAroundRow = []; - for (let j = 0; j < data.uParams.numPoles; ++j) { // #cols + for (let j = 0; j < data.uParams.numPoles; ++j) { // #cols const wrapAroundPt = []; for (let k = 0; k < data.dim; ++k) wrapAroundPt.push(polesExpanded[i][j][k]); wrapAroundRow.push(wrapAroundPt); } - polesExpanded.push(wrapAroundRow); // append degreeV wraparound rows of poles + polesExpanded.push(wrapAroundRow); // append degreeV wraparound rows of poles } if (weightsExpanded) { for (let i = 0; i < data.vParams.order - 1; ++i) { const wrapAroundRow = []; - for (let j = 0; j < data.uParams.numPoles; ++j) // #cols + for (let j = 0; j < data.uParams.numPoles; ++j) // #cols wrapAroundRow.push(weightsExpanded[i][j]); - weightsExpanded.push(wrapAroundRow); // append degreeV wraparound rows of weights + weightsExpanded.push(wrapAroundRow); // append degreeV wraparound rows of weights } } data.vParams.numPoles += data.vParams.order - 1; @@ -568,7 +593,7 @@ export namespace SerializationHelpers { data.vParams.knots = this.copyKnots(data.vParams.knots, options); } - data.uParams.closed = data.vParams.closed = undefined; // we are open + data.uParams.closed = data.vParams.closed = undefined; // we are open convertBSplineSurfaceDataArrays(data, options); return true; @@ -586,7 +611,12 @@ export namespace SerializationHelpers { * @returns legacy periodic knots (with classic extraneous start/end knot) if wrapMode recognized; otherwise, undefined * @see Import.openLegacyPeriodicKnots */ - private static closeLegacyPeriodicKnots(knots: Float64Array | number[], order: number, options?: BSplineDataOptions, wrapMode?: BSplineWrapMode): Float64Array | number[] | undefined { + private static closeLegacyPeriodicKnots( + knots: Float64Array | number[], + order: number, + options?: BSplineDataOptions, + wrapMode?: BSplineWrapMode, + ): Float64Array | number[] | undefined { if (wrapMode === undefined || wrapMode !== BSplineWrapMode.OpenByRemovingKnots) return undefined; @@ -602,10 +632,10 @@ export namespace SerializationHelpers { let k = 0; for (let i = Math.floor(order / 2); i > 0; --i) newKnots[k++] = knots[rightIndex - i] - knotPeriod; - newKnots[k++] = leftKnot; // extraneous start knot + newKnots[k++] = leftKnot; // extraneous start knot for (const knot of knots) newKnots[k++] = knot; - newKnots[k++] = rightKnot; // extraneous end knot + newKnots[k++] = rightKnot; // extraneous end knot for (let i = 1; i <= Math.floor(degree / 2); ++i) newKnots[k++] = knots[leftIndex + i] + knotPeriod; @@ -699,11 +729,11 @@ export namespace SerializationHelpers { data.poles = polesTrimmed = arrays.poles; data.weights = weightsTrimmed = arrays.weights; } - for (let i = 0; i < data.vParams.numPoles; ++i) // #rows + for (let i = 0; i < data.vParams.numPoles; ++i) // #rows for (let j = 0; j < data.uParams.order - 1; ++j) polesTrimmed[i].pop(); // remove last degreeU poles from each row if (weightsTrimmed) { - for (let i = 0; i < data.vParams.numPoles; ++i) // #rows + for (let i = 0; i < data.vParams.numPoles; ++i) // #rows for (let j = 0; j < data.uParams.order - 1; ++j) weightsTrimmed[i].pop(); // remove last degreeU weights from each row } @@ -733,7 +763,7 @@ export namespace SerializationHelpers { data.weights = weightsTrimmed = arrays.weights; } for (let i = 0; i < data.vParams.order - 1; ++i) - polesTrimmed.pop(); // remove last degreeV rows of poles + polesTrimmed.pop(); // remove last degreeV rows of poles if (weightsTrimmed) { for (let i = 0; i < data.vParams.order - 1; ++i) weightsTrimmed.pop(); // remove last degreeV rows of weights diff --git a/core/geometry/src/solid/Box.ts b/core/geometry/src/solid/Box.ts index 50da1dc22a10..1bc563e20a0f 100644 --- a/core/geometry/src/solid/Box.ts +++ b/core/geometry/src/solid/Box.ts @@ -39,8 +39,7 @@ export class Box extends SolidPrimitive { private _topX: number; private _topY: number; - protected constructor(map: Transform, - baseX: number, baseY: number, topX: number, topY: number, capped: boolean) { + protected constructor(map: Transform, baseX: number, baseY: number, topX: number, topY: number, capped: boolean) { super(capped); this._localToWorld = map; this._baseX = baseX; @@ -90,10 +89,17 @@ export class Box extends SolidPrimitive { * @param topY size factor for top rectangle (multiplies vectorY) * @param capped true to define top and bottom closure caps */ - public static createDgnBox(origin: Point3d, vectorX: Vector3d, vectorY: Vector3d, + public static createDgnBox( + origin: Point3d, + vectorX: Vector3d, + vectorY: Vector3d, topOrigin: Point3d, - baseX: number, baseY: number, topX: number, topY: number, - capped: boolean): Box | undefined { + baseX: number, + baseY: number, + topX: number, + topY: number, + capped: boolean, + ): Box | undefined { const vectorZ = origin.vectorTo(topOrigin); const localToWorld = Transform.createOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ); return new Box(localToWorld, baseX, baseY, topX, topY, capped); @@ -110,12 +116,17 @@ export class Box extends SolidPrimitive { * @param topY size factor for top rectangle (multiplies vectorY) * @param capped true to define top and bottom closure caps */ - public static createDgnBoxWithAxes(origin: Point3d, axes: Matrix3d, + public static createDgnBoxWithAxes( + origin: Point3d, + axes: Matrix3d, topOrigin: Point3d, - baseX: number, baseY: number, topX: number, topY: number, - capped: boolean): Box | undefined { - return Box.createDgnBox(origin, axes.columnX(), axes.columnY(), topOrigin, - baseX, baseY, topX, topY, capped); + baseX: number, + baseY: number, + topX: number, + topY: number, + capped: boolean, + ): Box | undefined { + return Box.createDgnBox(origin, axes.columnX(), axes.columnY(), topOrigin, baseX, baseY, topX, topY, capped); } /** @@ -132,32 +143,58 @@ export class Box extends SolidPrimitive { zPoint.z = zPoint.z + range.zLength(); return Box.createDgnBox( lowPoint, - Vector3d.unitX(), Vector3d.unitY(), + Vector3d.unitX(), + Vector3d.unitY(), zPoint, - xSize, ySize, xSize, ySize, capped); + xSize, + ySize, + xSize, + ySize, + capped, + ); } return undefined; } /** (property accessor) return the x length at z = 0 */ - public getBaseX(): number { return this._baseX; } + public getBaseX(): number { + return this._baseX; + } /** (property accessor) return the y length at z = 0 */ - public getBaseY(): number { return this._baseY; } + public getBaseY(): number { + return this._baseY; + } /** (property accessor) return the x length at z = 1 */ - public getTopX(): number { return this._topX; } + public getTopX(): number { + return this._topX; + } /** (property accessor) return the x length at z = 1 */ - public getTopY(): number { return this._topY; } + public getTopY(): number { + return this._topY; + } /** (property accessor) return the local coordinates point (0,0,0) to world */ - public getBaseOrigin(): Point3d { return this._localToWorld.multiplyXYZ(0, 0, 0); } + public getBaseOrigin(): Point3d { + return this._localToWorld.multiplyXYZ(0, 0, 0); + } /** (property accessor) return the local coordinates point (0,0,1) to world */ - public getTopOrigin(): Point3d { return this._localToWorld.multiplyXYZ(0, 0, 1); } + public getTopOrigin(): Point3d { + return this._localToWorld.multiplyXYZ(0, 0, 1); + } /** (property accessor) return the local coordinate frame x vector */ - public getVectorX(): Vector3d { return this._localToWorld.matrix.columnX(); } + public getVectorX(): Vector3d { + return this._localToWorld.matrix.columnX(); + } /** (property accessor) return the local coordinate frame y vector */ - public getVectorY(): Vector3d { return this._localToWorld.matrix.columnY(); } + public getVectorY(): Vector3d { + return this._localToWorld.matrix.columnY(); + } /** (property accessor) return the local coordinate frame z vector */ - public getVectorZ(): Vector3d { return this._localToWorld.matrix.columnZ(); } + public getVectorZ(): Vector3d { + return this._localToWorld.matrix.columnZ(); + } /** Test of `other` is also of class `Box` */ - public isSameGeometryClass(other: any): boolean { return other instanceof Box; } + public isSameGeometryClass(other: any): boolean { + return other instanceof Box; + } /** test for near equality */ public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof Box) { diff --git a/core/geometry/src/solid/Cone.ts b/core/geometry/src/solid/Cone.ts index 2e34965ca693..bee66b2a57b2 100644 --- a/core/geometry/src/solid/Cone.ts +++ b/core/geometry/src/solid/Cone.ts @@ -35,16 +35,16 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam /** String name for schema properties */ public readonly solidPrimitiveType = "cone"; - private _localToWorld: Transform; // Transform from local to global. - private _radiusA: number; // nominal radius at z=0. skewed axes may make it an ellipse - private _radiusB: number; // radius at z=1. skewed axes may make it an ellipse + private _localToWorld: Transform; // Transform from local to global. + private _radiusA: number; // nominal radius at z=0. skewed axes may make it an ellipse + private _radiusB: number; // radius at z=1. skewed axes may make it an ellipse private _maxRadius: number; // maximum radius anywhere on the cone. protected constructor(map: Transform, radiusA: number, radiusB: number, capped: boolean) { super(capped); this._localToWorld = map; this._radiusA = radiusA; this._radiusB = radiusB; - this._maxRadius = Math.max(this._radiusA, this._radiusB); // um... should resolve elliptical sections + this._maxRadius = Math.max(this._radiusA, this._radiusB); // um... should resolve elliptical sections } /** Return a clone of this Cone. */ public clone(): Cone { @@ -100,7 +100,15 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam /** create a cylinder or cone from axis start and end with cross section defined by vectors that do not need to be perpendicular to each other or * to the axis. */ - public static createBaseAndTarget(centerA: Point3d, centerB: Point3d, vectorX: Vector3d, vectorY: Vector3d, radiusA: number, radiusB: number, capped: boolean) { + public static createBaseAndTarget( + centerA: Point3d, + centerB: Point3d, + vectorX: Vector3d, + vectorY: Vector3d, + radiusA: number, + radiusB: number, + capped: boolean, + ) { radiusA = Math.abs(Geometry.correctSmallMetricDistance(radiusA)); radiusB = Math.abs(Geometry.correctSmallMetricDistance(radiusB)); const vectorZ = centerA.vectorTo(centerB); @@ -108,23 +116,41 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam return new Cone(localToWorld, radiusA, radiusB, capped); } /** (Property accessor) Return the center point at the base plane */ - public getCenterA(): Point3d { return this._localToWorld.multiplyXYZ(0, 0, 0); } + public getCenterA(): Point3d { + return this._localToWorld.multiplyXYZ(0, 0, 0); + } /** (Property accessor) */ - public getCenterB(): Point3d { return this._localToWorld.multiplyXYZ(0, 0, 1); } + public getCenterB(): Point3d { + return this._localToWorld.multiplyXYZ(0, 0, 1); + } /** (Property accessor) Return the x vector in the local frame */ - public getVectorX(): Vector3d { return this._localToWorld.matrix.columnX(); } + public getVectorX(): Vector3d { + return this._localToWorld.matrix.columnX(); + } /** (Property accessor) Return the y vector in the local frame */ - public getVectorY(): Vector3d { return this._localToWorld.matrix.columnY(); } + public getVectorY(): Vector3d { + return this._localToWorld.matrix.columnY(); + } /** (Property accessor) return the radius at the base plane */ - public getRadiusA(): number { return this._radiusA; } + public getRadiusA(): number { + return this._radiusA; + } /** (Property accessor) return the radius at the top plane */ - public getRadiusB(): number { return this._radiusB; } + public getRadiusB(): number { + return this._radiusB; + } /** (Property accessor) return the larger of the base and top plane radii */ - public getMaxRadius(): number { return this._maxRadius; } + public getMaxRadius(): number { + return this._maxRadius; + } /** (Property accessor) return the radius at fraction `v` along the axis */ - public vFractionToRadius(v: number): number { return Geometry.interpolate(this._radiusA, v, this._radiusB); } + public vFractionToRadius(v: number): number { + return Geometry.interpolate(this._radiusA, v, this._radiusB); + } /** (Property accessor) test if `other` is an instance of `Cone` */ - public isSameGeometryClass(other: any): boolean { return other instanceof Cone; } + public isSameGeometryClass(other: any): boolean { + return other instanceof Cone; + } /** (Property accessor) Test for nearly equal coordinate data. */ public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof Cone) { @@ -156,7 +182,7 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam if (fixedStrokeCount !== undefined) strokeCount = fixedStrokeCount; else if (options !== undefined) - strokeCount = options.defaultCircleStrokes; // NEEDS WORK -- get circle stroke count with this.maxRadius !!! + strokeCount = options.defaultCircleStrokes; // NEEDS WORK -- get circle stroke count with this.maxRadius !!! else { // accept the local default } @@ -166,7 +192,7 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam const twoPi = Math.PI * 2.0; const deltaRadians = twoPi / strokeCount; let radians = 0; - const fractions = result.fractions; // possibly undefined !!! + const fractions = result.fractions; // possibly undefined !!! const derivatives = result.packedDerivatives; // possibly undefined !!! const uvParams = result.packedUVParams; // possibly undefined !! const surfaceNormals = result.packedSurfaceNormals; @@ -254,7 +280,8 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam this._localToWorld.multiplyXYZ(r * cosTheta, r * sinTheta, vFraction), this._localToWorld.multiplyVectorXYZ(-r * sinTheta * fTheta, r * cosTheta * fTheta, 0), this._localToWorld.multiplyVectorXYZ(drdv * cosTheta, drdv * sinTheta, 1.0), - result); + result, + ); } /** * @return true if this is a closed volume. @@ -276,7 +303,9 @@ export class Cone extends SolidPrimitive implements UVSurface, UVSurfaceIsoParam const hZ = xyNormal.dotProduct(columnZ); const zSkewVector = columnZ.plusScaled(xyNormal, hZ); const zSkewDistance = zSkewVector.magnitudeXY(); - return Vector2d.create(Math.PI * 2 * Math.max(this._radiusA, this._radiusB), - Geometry.hypotenuseXY(Math.abs(this._radiusB - this._radiusA) + zSkewDistance, hZ)); + return Vector2d.create( + Math.PI * 2 * Math.max(this._radiusA, this._radiusB), + Geometry.hypotenuseXY(Math.abs(this._radiusB - this._radiusA) + zSkewDistance, hZ), + ); } } diff --git a/core/geometry/src/solid/LinearSweep.ts b/core/geometry/src/solid/LinearSweep.ts index d41216292108..083e187da6fc 100644 --- a/core/geometry/src/solid/LinearSweep.ts +++ b/core/geometry/src/solid/LinearSweep.ts @@ -7,8 +7,8 @@ * @module Solid */ -import { AnyCurve } from "../curve/CurveTypes"; import { CurveCollection } from "../curve/CurveCollection"; +import { AnyCurve } from "../curve/CurveTypes"; import { GeometryQuery } from "../curve/GeometryQuery"; import { LineString3d } from "../curve/LineString3d"; import { Loop } from "../curve/Loop"; @@ -76,13 +76,21 @@ export class LinearSweep extends SolidPrimitive { return LinearSweep.create(contour, Vector3d.create(0, 0, zSweep), capped); } /** get a reference to the swept curves */ - public getCurvesRef(): CurveCollection { return this._contour.curves; } + public getCurvesRef(): CurveCollection { + return this._contour.curves; + } /** Get a reference to the `SweepContour` carrying the plane of the curves */ - public getSweepContourRef(): SweepContour { return this._contour; } + public getSweepContourRef(): SweepContour { + return this._contour; + } /** return a clone of the sweep vector */ - public cloneSweepVector(): Vector3d { return this._direction.clone(); } + public cloneSweepVector(): Vector3d { + return this._direction.clone(); + } /** Test if `other` is also an instance of `LinearSweep` */ - public isSameGeometryClass(other: any): boolean { return other instanceof LinearSweep; } + public isSameGeometryClass(other: any): boolean { + return other instanceof LinearSweep; + } /** Return a deep clone */ public clone(): LinearSweep { return new LinearSweep(this._contour.clone(), this._direction.clone(), this.capped); diff --git a/core/geometry/src/solid/RotationalSweep.ts b/core/geometry/src/solid/RotationalSweep.ts index dac07d39f8ed..989ded79f954 100644 --- a/core/geometry/src/solid/RotationalSweep.ts +++ b/core/geometry/src/solid/RotationalSweep.ts @@ -7,8 +7,8 @@ * @module Solid */ -import { AnyCurve } from "../curve/CurveTypes"; import { CurveCollection } from "../curve/CurveCollection"; +import { AnyCurve } from "../curve/CurveTypes"; import { GeometryQuery } from "../curve/GeometryQuery"; import { StrokeOptions } from "../curve/StrokeOptions"; import { AxisOrder, Geometry } from "../Geometry"; @@ -68,15 +68,25 @@ export class RotationalSweep extends SolidPrimitive { return undefined; } /** return clone of (not reference to) the axis vector. */ - public cloneAxisRay(): Ray3d { return this._normalizedAxis.clone(); } + public cloneAxisRay(): Ray3d { + return this._normalizedAxis.clone(); + } /** Return (REFERENCE TO) the swept curves. */ - public getCurves(): CurveCollection { return this._contour.curves; } + public getCurves(): CurveCollection { + return this._contour.curves; + } /** Return (REFERENCE TO) the swept curves with containing plane markup. */ - public getSweepContourRef(): SweepContour { return this._contour; } + public getSweepContourRef(): SweepContour { + return this._contour; + } /** Return the sweep angle. */ - public getSweep(): Angle { return this._sweepAngle.clone(); } + public getSweep(): Angle { + return this._sweepAngle.clone(); + } /** Test if `other` is a `RotationalSweep` */ - public isSameGeometryClass(other: any): boolean { return other instanceof RotationalSweep; } + public isSameGeometryClass(other: any): boolean { + return other instanceof RotationalSweep; + } /** Test for same axis, capping, and swept geometry. */ public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof RotationalSweep) { @@ -92,8 +102,10 @@ export class RotationalSweep extends SolidPrimitive { } /** Transform the contour and axis */ public tryTransformInPlace(transform: Transform): boolean { - if (!transform.matrix.isSingular() - && this._contour.tryTransformInPlace(transform)) { + if ( + !transform.matrix.isSingular() + && this._contour.tryTransformInPlace(transform) + ) { this._normalizedAxis.transformInPlace(transform); return this._normalizedAxis.direction.normalizeInPlace(); } @@ -112,9 +124,14 @@ export class RotationalSweep extends SolidPrimitive { /** Return a transform that rotates around the rotational axis by a fraction of the total sweep. */ public getFractionalRotationTransform(vFraction: number, result?: Transform): Transform { const radians = this._sweepAngle.radians * vFraction; - const rotation = Transform.createFixedPointAndMatrix(this._normalizedAxis.origin, - Matrix3d.createRotationAroundVector(this._normalizedAxis.direction, Angle.createRadians(radians), - result ? result.matrix : undefined) as Matrix3d); + const rotation = Transform.createFixedPointAndMatrix( + this._normalizedAxis.origin, + Matrix3d.createRotationAroundVector( + this._normalizedAxis.direction, + Angle.createRadians(radians), + result ? result.matrix : undefined, + ) as Matrix3d, + ); return rotation; } /** @@ -142,7 +159,6 @@ export class RotationalSweep extends SolidPrimitive { transform.multiplyTransformTransform(this.getFractionalRotationTransform(i / numStep, stepTransform), compositeTransform); strokes.extendRange(range, compositeTransform); } - } else { for (let i = 0; i <= numStep; i++) strokes.extendRange(range, this.getFractionalRotationTransform(i / numStep, stepTransform)); diff --git a/core/geometry/src/solid/RuledSweep.ts b/core/geometry/src/solid/RuledSweep.ts index 445ff9e6fef6..f8306518a6e1 100644 --- a/core/geometry/src/solid/RuledSweep.ts +++ b/core/geometry/src/solid/RuledSweep.ts @@ -8,9 +8,9 @@ */ import { ConstructCurveBetweenCurves } from "../curve/ConstructCurveBetweenCurves"; -import { AnyCurve } from "../curve/CurveTypes"; import { CurveChain, CurveCollection } from "../curve/CurveCollection"; import { CurvePrimitive } from "../curve/CurvePrimitive"; +import { AnyCurve } from "../curve/CurveTypes"; import { GeometryQuery } from "../curve/GeometryQuery"; import { Geometry } from "../Geometry"; import { GeometryHandler } from "../geometry3d/GeometryHandler"; @@ -53,7 +53,9 @@ export class RuledSweep extends SolidPrimitive { return new RuledSweep(sweepContours, capped); } /** Return a reference to the array of SweepContour. */ - public sweepContoursRef(): SweepContour[] { return this._contours; } + public sweepContoursRef(): SweepContour[] { + return this._contours; + } /** Return clones of all the sweep contours * * See also cloneContours, which returns the spatial contours without their local coordinate system definitions) */ @@ -103,7 +105,9 @@ export class RuledSweep extends SolidPrimitive { return this._contours[0].localToWorld.cloneRigid(); } /** Test if `other` is an instance of a `RuledSweep` */ - public isSameGeometryClass(other: any): boolean { return other instanceof RuledSweep; } + public isSameGeometryClass(other: any): boolean { + return other instanceof RuledSweep; + } /** test same contour geometry and capping. */ public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof RuledSweep) { @@ -139,12 +143,15 @@ export class RuledSweep extends SolidPrimitive { section0 = numSection - 2; const section1 = section0 + 1; const localFraction = Geometry.clampToStartEnd(q - section0, 0, 1); - return RuledSweep.mutatePartners(this._contours[section0].curves, this._contours[section1].curves, + return RuledSweep.mutatePartners( + this._contours[section0].curves, + this._contours[section1].curves, (primitive0: CurvePrimitive, primitive1: CurvePrimitive): CurvePrimitive | undefined => { const newPrimitive = ConstructCurveBetweenCurves.interpolateBetween(primitive0, localFraction, primitive1); if (newPrimitive instanceof CurvePrimitive) return newPrimitive; return undefined; - }); + }, + ); } /** Pass each contour to `extendRange` */ public extendRange(rangeToExtend: Range3d, transform?: Transform): void { @@ -155,7 +162,11 @@ export class RuledSweep extends SolidPrimitive { /** Construct a CurveCollection with the same structure as collectionA and collectionB, with primitives constructed by the caller-supplied primitiveMutator function. * @returns Returns undefined if there is any type mismatch between the two collections. */ - public static mutatePartners(collectionA: CurveCollection, collectionB: CurveCollection, primitiveMutator: CurvePrimitiveMutator): CurveCollection | undefined { + public static mutatePartners( + collectionA: CurveCollection, + collectionB: CurveCollection, + primitiveMutator: CurvePrimitiveMutator, + ): CurveCollection | undefined { if (!collectionA.isSameGeometryClass(collectionB)) return undefined; if (collectionA instanceof CurveChain && collectionB instanceof CurveChain) { @@ -209,5 +220,4 @@ export class RuledSweep extends SolidPrimitive { const n = this._contours.length; return n > 1 && (this.capped || this._contours[0].isAlmostEqual(this._contours[n - 1])); } - } diff --git a/core/geometry/src/solid/SolidPrimitive.ts b/core/geometry/src/solid/SolidPrimitive.ts index 0e756ab8eff0..d0d4c3859f18 100644 --- a/core/geometry/src/solid/SolidPrimitive.ts +++ b/core/geometry/src/solid/SolidPrimitive.ts @@ -51,10 +51,17 @@ export abstract class SolidPrimitive extends GeometryQuery { /** flag indicating whether cap region is considered closed (i.e. a planar region, rather than just a wire in space) */ protected _capped: boolean; - protected constructor(capped: boolean) { super(); this._capped = capped; } + protected constructor(capped: boolean) { + super(); + this._capped = capped; + } /** Whether this is a capped solid */ - public get capped(): boolean { return this._capped; } - public set capped(capped: boolean) { this._capped = capped; } + public get capped(): boolean { + return this._capped; + } + public set capped(capped: boolean) { + this._capped = capped; + } /** Return a cross section at specified vFraction. */ public abstract constantVSection(_vFraction: number): CurveCollection | undefined; /** Return a Transform from the local system of the solid to world. diff --git a/core/geometry/src/solid/Sphere.ts b/core/geometry/src/solid/Sphere.ts index 7375aea4146f..264f94982950 100644 --- a/core/geometry/src/solid/Sphere.ts +++ b/core/geometry/src/solid/Sphere.ts @@ -36,7 +36,7 @@ export class Sphere extends SolidPrimitive implements UVSurface { /** String name for schema properties */ public readonly solidPrimitiveType = "sphere"; - private _localToWorld: Transform; // unit sphere maps to world through the transform0 part of this map. + private _localToWorld: Transform; // unit sphere maps to world through the transform0 part of this map. private _latitudeSweep: AngleSweep; /** Return the latitude (in radians) all fractional v. */ public vFractionToRadians(v: number): number { @@ -87,7 +87,9 @@ export class Sphere extends SolidPrimitive implements UVSurface { return this._localToWorld.cloneRigid(); } /** Return the latitude sweep as fraction of south pole to north pole. */ - public get latitudeSweepFraction(): number { return this._latitudeSweep.sweepRadians / Math.PI; } + public get latitudeSweepFraction(): number { + return this._latitudeSweep.sweepRadians / Math.PI; + } /** Create from center and radius, with optional restricted latitudes. */ public static createCenterRadius(center: Point3d, radius: number, latitudeSweep?: AngleSweep): Sphere { const localToWorld = Transform.createOriginAndMatrix(center, Matrix3d.createUniformScale(radius)); @@ -99,9 +101,15 @@ export class Sphere extends SolidPrimitive implements UVSurface { } /** Create a sphere from the typical parameters of the Dgn file */ - public static createDgnSphere(center: Point3d, vectorX: Vector3d, vectorZ: Vector3d, radiusXY: number, radiusZ: number, + public static createDgnSphere( + center: Point3d, + vectorX: Vector3d, + vectorZ: Vector3d, + radiusXY: number, + radiusZ: number, latitudeSweep: AngleSweep, - capped: boolean): Sphere | undefined { + capped: boolean, + ): Sphere | undefined { const vectorY = vectorX.rotate90Around(vectorZ); if (vectorY && !vectorX.isParallelTo(vectorZ)) { const matrix = Matrix3d.createColumns(vectorX, vectorY, vectorZ); @@ -113,29 +121,45 @@ export class Sphere extends SolidPrimitive implements UVSurface { } /** Create a sphere from the typical parameters of the Dgn file */ - public static createFromAxesAndScales(center: Point3d, axes: undefined | Matrix3d, radiusX: number, radiusY: number, radiusZ: number, + public static createFromAxesAndScales( + center: Point3d, + axes: undefined | Matrix3d, + radiusX: number, + radiusY: number, + radiusZ: number, latitudeSweep: AngleSweep | undefined, - capped: boolean): Sphere | undefined { + capped: boolean, + ): Sphere | undefined { const localToWorld = Transform.createOriginAndMatrix(center, axes); localToWorld.matrix.scaleColumnsInPlace(radiusX, radiusY, radiusZ); return new Sphere(localToWorld, latitudeSweep ? latitudeSweep.clone() : AngleSweep.createFullLatitude(), capped); } /** return (copy of) sphere center */ - public cloneCenter(): Point3d { return this._localToWorld.getOrigin(); } + public cloneCenter(): Point3d { + return this._localToWorld.getOrigin(); + } /** return the (full length, i.e. scaled by radius) X vector from the sphere transform */ - public cloneVectorX(): Vector3d { return this._localToWorld.matrix.columnX(); } + public cloneVectorX(): Vector3d { + return this._localToWorld.matrix.columnX(); + } /** return the (full length, i.e. scaled by radius) Y vector from the sphere transform */ - public cloneVectorY(): Vector3d { return this._localToWorld.matrix.columnY(); } + public cloneVectorY(): Vector3d { + return this._localToWorld.matrix.columnY(); + } /** return the (full length, i.e. scaled by radius) Z vector from the sphere transform */ - public cloneVectorZ(): Vector3d { return this._localToWorld.matrix.columnZ(); } + public cloneVectorZ(): Vector3d { + return this._localToWorld.matrix.columnZ(); + } /** return (a copy of) the sphere's angle sweep. */ - public cloneLatitudeSweep(): AngleSweep { return this._latitudeSweep.clone(); } + public cloneLatitudeSweep(): AngleSweep { + return this._latitudeSweep.clone(); + } /** Test if the geometry is a true sphere taking the transform (which might have nonuniform scaling) is applied. */ public trueSphereRadius(): number | undefined { const factors = this._localToWorld.matrix.factorRigidWithSignedScale(); if (!factors) return undefined; - if (factors && factors.scale > 0) // why do we rule out mirror? + if (factors && factors.scale > 0) // why do we rule out mirror? return factors.scale; return undefined; } @@ -149,9 +173,13 @@ export class Sphere extends SolidPrimitive implements UVSurface { /** * Return a (clone of) the sphere's local to world transformation. */ - public cloneLocalToWorld(): Transform { return this._localToWorld.clone(); } + public cloneLocalToWorld(): Transform { + return this._localToWorld.clone(); + } /** Test if `other` is a `Sphere` */ - public isSameGeometryClass(other: any): boolean { return other instanceof Sphere; } + public isSameGeometryClass(other: any): boolean { + return other instanceof Sphere; + } /** Test for same geometry in `other` */ public override isAlmostEqual(other: GeometryQuery): boolean { if (other instanceof Sphere) { @@ -167,13 +195,14 @@ export class Sphere extends SolidPrimitive implements UVSurface { * @param v fractional position along the cone axis * @param strokes stroke count or options. */ - public strokeConstantVSection(v: number, fixedStrokeCount: number | undefined, - options?: StrokeOptions): LineString3d { + public strokeConstantVSection(v: number, fixedStrokeCount: number | undefined, options?: StrokeOptions): LineString3d { let strokeCount = 16; if (fixedStrokeCount !== undefined && Number.isFinite(fixedStrokeCount)) { strokeCount = fixedStrokeCount; } else if (options instanceof StrokeOptions) { - strokeCount = options.applyTolerancesToArc(Geometry.maxXY(this._localToWorld.matrix.columnXMagnitude(), this._localToWorld.matrix.columnYMagnitude())); + strokeCount = options.applyTolerancesToArc( + Geometry.maxXY(this._localToWorld.matrix.columnXMagnitude(), this._localToWorld.matrix.columnYMagnitude()), + ); } strokeCount = Geometry.clampToStartEnd(strokeCount, 4, 64); const transform = this._localToWorld; @@ -183,7 +212,7 @@ export class Sphere extends SolidPrimitive implements UVSurface { let c0, s0; const result = LineString3d.createForStrokes(fixedStrokeCount, options); const deltaRadians = Math.PI * 2.0 / strokeCount; - const fractions = result.fractions; // possibly undefined !!! + const fractions = result.fractions; // possibly undefined !!! const derivatives = result.packedDerivatives; // possibly undefined !!! const uvParams = result.packedUVParams; // possibly undefined !! const surfaceNormals = result.packedSurfaceNormals; @@ -255,7 +284,6 @@ export class Sphere extends SolidPrimitive implements UVSurface { range.extendTransformedXYZ(placement, 1, -1, 1); range.extendTransformedXYZ(placement, -1, 1, 1); range.extendTransformedXYZ(placement, 1, 1, 1); - } /** Evaluate as a uv surface * @param uFraction fractional position on minor arc (theta, longitude) @@ -286,9 +314,10 @@ export class Sphere extends SolidPrimitive implements UVSurface { const cosPhi = Math.cos(phiRadians); return Plane3dByOriginAndVectors.createOriginAndVectors( this._localToWorld.multiplyXYZ(cosTheta * cosPhi, sinTheta * cosPhi, sinPhi), - this._localToWorld.matrix.multiplyXYZ(-fTheta * sinTheta, fTheta * cosTheta, 0), // !!! note cosTheta term is omitted -- scale is wrong, but remains non-zero at poles. + this._localToWorld.matrix.multiplyXYZ(-fTheta * sinTheta, fTheta * cosTheta, 0), // !!! note cosTheta term is omitted -- scale is wrong, but remains non-zero at poles. this._localToWorld.matrix.multiplyXYZ(-fPhi * cosTheta * sinPhi, -fPhi * sinTheta * sinPhi, fPhi * cosPhi), - result); + result, + ); } /** * * A sphere is can be closed two ways: diff --git a/core/geometry/src/solid/SweepContour.ts b/core/geometry/src/solid/SweepContour.ts index a48ed7b52075..95a4462e6d09 100644 --- a/core/geometry/src/solid/SweepContour.ts +++ b/core/geometry/src/solid/SweepContour.ts @@ -103,7 +103,9 @@ export class SweepContour { return undefined; } /** Return (Reference to) the curves */ - public getCurves(): CurveCollection { return this.curves; } + public getCurves(): CurveCollection { + return this.curves; + } /** * Apply `transform` to the curves, axis. * * The local to world frame is reconstructed for the transformed curves. @@ -137,7 +139,7 @@ export class SweepContour { } /** Test for near equality of curves, frame, and axis. */ public isAlmostEqual(other: any): boolean { - if (! (other instanceof SweepContour)) + if (!(other instanceof SweepContour)) return false; if (!this.curves.isAlmostEqual(other.curves)) return false; @@ -220,14 +222,19 @@ export class SweepContour { * @param options how to stroke the contour * @returns clipper defined by faceting then sweeping the contour region */ - public sweepToUnionOfConvexClipPlaneSets(sweepVector?: Vector3d, cap0: boolean = false, cap1: boolean = false, options?: StrokeOptions): UnionOfConvexClipPlaneSets | undefined { + public sweepToUnionOfConvexClipPlaneSets( + sweepVector?: Vector3d, + cap0: boolean = false, + cap1: boolean = false, + options?: StrokeOptions, + ): UnionOfConvexClipPlaneSets | undefined { if (!options) options = StrokeOptions.createForFacets(); if (!sweepVector) { cap0 = cap1 = false; sweepVector = this.localToWorld.matrix.columnZ(); } - options.maximizeConvexFacets = true; // produce fewer ConvexClipPlaneSets + options.maximizeConvexFacets = true; // produce fewer ConvexClipPlaneSets // It's a trip around the barn, but it's easy to make a polyface and scan it . . . this.buildFacets(options); const facets = this._facets; diff --git a/core/geometry/src/solid/TorusPipe.ts b/core/geometry/src/solid/TorusPipe.ts index c784b6f95c31..40ba4fbdb2e3 100644 --- a/core/geometry/src/solid/TorusPipe.ts +++ b/core/geometry/src/solid/TorusPipe.ts @@ -52,8 +52,8 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso public readonly solidPrimitiveType = "torusPipe"; private _localToWorld: Transform; // nominally rigid, but x,z column scales contribute to radiusA,radiusB - private _radiusA: number; // radius of (large) circle in xy plane - private _radiusB: number; // radius of (small) circle in xz plane. + private _radiusA: number; // radius of (large) circle in xy plane + private _radiusB: number; // radius of (small) circle in xz plane. private _sweep: Angle; private _isReversed: boolean; @@ -128,7 +128,15 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso } /** Create a TorusPipe from the typical parameters of the Dgn file */ - public static createDgnTorusPipe(center: Point3d, vectorX: Vector3d, vectorY: Vector3d, majorRadius: number, minorRadius: number, sweep: Angle, capped: boolean) { + public static createDgnTorusPipe( + center: Point3d, + vectorX: Vector3d, + vectorY: Vector3d, + majorRadius: number, + minorRadius: number, + sweep: Angle, + capped: boolean, + ) { const vectorZ = vectorX.unitCrossProductWithDefault(vectorY, 0, 0, 1); const frame = Transform.createOriginAndMatrixColumns(center, vectorX, vectorY, vectorZ); return TorusPipe.createInFrame(frame, majorRadius, minorRadius, sweep, capped); @@ -160,7 +168,9 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso return this._localToWorld.cloneRigid(); } /** Return the center of the torus pipe (inside the donut hole) */ - public cloneCenter(): Point3d { return this._localToWorld.getOrigin(); } + public cloneCenter(): Point3d { + return this._localToWorld.getOrigin(); + } /** return unit vector along the x axis (in the major hoop plane) */ public cloneVectorX(): Vector3d { const xAxis = this._localToWorld.matrix.columnX(); @@ -177,19 +187,33 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso return zAxis.normalizeWithDefault(0, 0, 1, zAxis); } /** get the major hoop radius (`radiusA`) in world coordinates */ - public getMajorRadius(): number { return this._radiusA * this._localToWorld.matrix.columnXMagnitude(); } + public getMajorRadius(): number { + return this._radiusA * this._localToWorld.matrix.columnXMagnitude(); + } /** get the minor hoop radius (`radiusB`) in world coordinates */ - public getMinorRadius(): number { return this._radiusB * this._localToWorld.matrix.columnZMagnitude(); } + public getMinorRadius(): number { + return this._radiusB * this._localToWorld.matrix.columnZMagnitude(); + } /** get the sweep angle along the major circle. */ - public getSweepAngle(): Angle { return this._sweep.clone(); } + public getSweepAngle(): Angle { + return this._sweep.clone(); + } /** Ask if this TorusPipe is labeled as reversed */ - public getIsReversed(): boolean { return this._isReversed; } + public getIsReversed(): boolean { + return this._isReversed; + } /** Return the sweep angle as a fraction of full 360 degrees (2PI radians) */ - public getThetaFraction(): number { return this._sweep.radians / (Math.PI * 2.0); } + public getThetaFraction(): number { + return this._sweep.radians / (Math.PI * 2.0); + } /** Return a (clone of) the TorusPipe's local to world transformation. */ - public cloneLocalToWorld(): Transform { return this._localToWorld.clone(); } + public cloneLocalToWorld(): Transform { + return this._localToWorld.clone(); + } /** ask if `other` is an instance of `TorusPipe` */ - public isSameGeometryClass(other: any): boolean { return other instanceof TorusPipe; } + public isSameGeometryClass(other: any): boolean { + return other instanceof TorusPipe; + } /** test if `this` and `other` have nearly equal geometry */ public override isAlmostEqual(other: GeometryQuery): boolean { @@ -219,7 +243,9 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso } /** Return the angle (in radians) for given fractional position around the major hoop. */ - public vFractionToRadians(v: number): number { return this._sweep.radians * v; } + public vFractionToRadians(v: number): number { + return this._sweep.radians * v; + } /** Second step of double dispatch: call `handler.handleTorusPipe(this)` */ public dispatchToGeometryHandler(handler: GeometryHandler): any { return handler.handleTorusPipe(this); @@ -291,17 +317,13 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso for (j = 0; j <= numPhiSample; j++) { phi = phi0 + j * dPhi; rxy = majorRadius + minorRadius * Math.cos(phi); - rangeToExtend.extendTransformTransformedXYZ(transform, transform0, - cosTheta * rxy, sinTheta * rxy, - Math.sin(phi) * minorRadius); + rangeToExtend.extendTransformTransformedXYZ(transform, transform0, cosTheta * rxy, sinTheta * rxy, Math.sin(phi) * minorRadius); } } else { for (j = 0; j <= numPhiSample; j++) { phi = phi0 + j * dPhi; rxy = majorRadius + minorRadius * Math.cos(phi); - rangeToExtend.extendTransformedXYZ(transform0, - cosTheta * rxy, sinTheta * rxy, - Math.sin(phi) * minorRadius); + rangeToExtend.extendTransformedXYZ(transform0, cosTheta * rxy, sinTheta * rxy, Math.sin(phi) * minorRadius); } } } @@ -337,12 +359,13 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso const minorRadius = this._radiusB; const rxy = majorRadius + Math.cos(phiRadians) * minorRadius; const rSinPhi = minorRadius * sinPhi; - const rCosPhi = minorRadius * cosPhi; // appears only as derivative of rSinPhi. + const rCosPhi = minorRadius * cosPhi; // appears only as derivative of rSinPhi. return Plane3dByOriginAndVectors.createOriginAndVectors( this._localToWorld.multiplyXYZ(cosTheta * rxy, sinTheta * rxy, rSinPhi), this._localToWorld.multiplyVectorXYZ(-cosTheta * rSinPhi * fPhi, -sinTheta * rSinPhi * fPhi, rCosPhi * fPhi), this._localToWorld.multiplyVectorXYZ(-rxy * sinTheta * fTheta, rxy * cosTheta * fTheta, 0), - result); + result, + ); } /** * Directional distance query @@ -360,5 +383,4 @@ export class TorusPipe extends SolidPrimitive implements UVSurface, UVSurfaceIso public get isClosedVolume(): boolean { return this.capped || this._sweep.isFullCircle; } - } diff --git a/core/geometry/src/test/Checker.ts b/core/geometry/src/test/Checker.ts index 1a3030499dd2..f44eb8d397cd 100644 --- a/core/geometry/src/test/Checker.ts +++ b/core/geometry/src/test/Checker.ts @@ -101,7 +101,9 @@ export class Checker { public getNumErrors(): number { return this._savedErrors + this._numErrors; } - public getNumOK(): number { return this._numOK + this._savedOK; } + public getNumOK(): number { + return this._numOK + this._savedOK; + } // =================================================================================== // Tests @@ -138,8 +140,11 @@ export class Checker { const dataA1 = transformAToB.multiplyPoint3d(dataA); if (Geometry.isSamePoint3d(dataA1, dataB)) return this.announceOK(); - this.announceError("expect same transformed Point3d", - `${prettyPrint(transformAToB)} * ${prettyPrint(dataA)} ==> ${prettyPrint(dataA1)} =?= ${prettyPrint(dataB)}`, params); + this.announceError( + "expect same transformed Point3d", + `${prettyPrint(transformAToB)} * ${prettyPrint(dataA)} ==> ${prettyPrint(dataA1)} =?= ${prettyPrint(dataB)}`, + params, + ); return false; } public testPoint3dArray(dataA: Point3d[], dataB: Point3d[], ...params: any[]): boolean { @@ -152,7 +157,12 @@ export class Checker { return this.announceOK(); } /** Test if number arrays match with tolerance. */ - public testNumberArrayWithTol(dataA: number[] | GrowableFloat64Array | Float64Array | undefined, dataB: number[] | GrowableFloat64Array | Float64Array | undefined, tol: number = Geometry.smallMetricDistance, ...params: any[]): boolean { + public testNumberArrayWithTol( + dataA: number[] | GrowableFloat64Array | Float64Array | undefined, + dataB: number[] | GrowableFloat64Array | Float64Array | undefined, + tol: number = Geometry.smallMetricDistance, + ...params: any[] + ): boolean { const numA = dataA === undefined ? 0 : dataA.length; const numB = dataB === undefined ? 0 : dataB.length; if (numA !== numB) @@ -351,8 +361,10 @@ export class Checker { return this.announceError("expect same Matrix3d", dataA, dataB, params); } public testTransform(dataA: Transform, dataB: Transform, ...params: any[]): boolean { - if (dataA.matrix.maxDiff(dataB.matrix) < Geometry.smallMetricDistance - && dataA.origin.maxDiff(dataB.origin) < Geometry.smallMetricDistance) + if ( + dataA.matrix.maxDiff(dataB.matrix) < Geometry.smallMetricDistance + && dataA.origin.maxDiff(dataB.origin) < Geometry.smallMetricDistance + ) return this.announceOK(); return this.announceError("expect same Transform", dataA, dataB, params); } @@ -538,8 +550,12 @@ export class Checker { private static _cache: GeometryQuery[] = []; private static _transform: Transform = Transform.createIdentity(); - public static setTransform(transform: Transform) { Checker._transform = transform; } - public static getTransform(): Transform { return Checker._transform; } + public static setTransform(transform: Transform) { + Checker._transform = transform; + } + public static getTransform(): Transform { + return Checker._transform; + } public static saveTransformed(g: GeometryQuery, maxCoordinate: number = 1.0e12) { const range = g.range(); diff --git a/core/geometry/src/test/Geometry.test.ts b/core/geometry/src/test/Geometry.test.ts index 78bafefd6407..c66b8cf56fea 100644 --- a/core/geometry/src/test/Geometry.test.ts +++ b/core/geometry/src/test/Geometry.test.ts @@ -89,7 +89,7 @@ describe("Geometry.almostEqualNumberArrays", () => { assert.isTrue(Geometry.almostEqualNumberArrays(arr1, arr2, (a, b) => Geometry.isAlmostEqualNumber(a, b))); arr1 = [1]; arr2 = [1, 2]; - assert.isTrue(!Geometry.almostEqualNumberArrays(arr1, arr2, (a, b) => Geometry.isAlmostEqualNumber(a,b))); + assert.isTrue(!Geometry.almostEqualNumberArrays(arr1, arr2, (a, b) => Geometry.isAlmostEqualNumber(a, b))); arr1 = [1]; arr2 = [2]; assert.isTrue(!Geometry.almostEqualNumberArrays(arr1, arr2, (a, b) => Geometry.isAlmostEqualNumber(a, b))); diff --git a/core/geometry/src/test/GeometryCoreTestIO.ts b/core/geometry/src/test/GeometryCoreTestIO.ts index bf0c263769a6..a65730332481 100644 --- a/core/geometry/src/test/GeometryCoreTestIO.ts +++ b/core/geometry/src/test/GeometryCoreTestIO.ts @@ -48,7 +48,7 @@ export class GeometryCoreTestIO { public static consoleTime(label?: string): void { if (!this.enableConsole) return; - console.time(label); // eslint-disable-line no-console + console.time(label); // eslint-disable-line no-console } /** Wrapper for console.timeEnd */ public static consoleTimeEnd(label?: string): void { @@ -74,7 +74,7 @@ export class GeometryCoreTestIO { const path = this.makeOutputDir(directoryName); let fullPath = `${path}/${fileName}`; - if (fileName.search(`\\.imjs$`) === -1) // tricky: escape the escape char for the regex + if (fileName.search(`\\.imjs$`) === -1) // tricky: escape the escape char for the regex fullPath = `${fullPath}.imjs`; this.consoleLog(`saveGeometry:: ${fullPath}`); @@ -410,7 +410,11 @@ export class GeometryCoreTestIO { * @param dz z shift */ public static captureRangeEdges( - collection: GeometryQuery[], range?: Range2d | Range3d | Range2d[] | Range3d[], dx: number = 0, dy: number = 0, dz: number = 0, + collection: GeometryQuery[], + range?: Range2d | Range3d | Range2d[] | Range3d[], + dx: number = 0, + dy: number = 0, + dz: number = 0, ) { if (Array.isArray(range)) { for (const r of range) @@ -435,13 +439,19 @@ export class GeometryCoreTestIO { const rx = momentData1.radiusOfGyration.x; const ry = momentData1.radiusOfGyration.y; const rz = momentData1.radiusOfGyration.z; - this.captureGeometry(collection, + this.captureGeometry( + collection, LineString3d.create([ momentData1.origin, momentData1.origin.plusScaled(unitX, 2.0 * rz), momentData1.origin.plusScaled(unitY, rz), momentData1.origin, - momentData1.origin.plusScaled(unitZ, 3.0 * rz)]), dx, dy, dz); + momentData1.origin.plusScaled(unitZ, 3.0 * rz), + ]), + dx, + dy, + dz, + ); this.captureGeometry( collection, Arc3d.create(momentData1.origin, unitX.scale(rz), unitY.scale(rz), AngleSweep.createStartEndDegrees(0, 355)), @@ -499,11 +509,28 @@ export class GeometryCoreTestIO { } } /** Draw the scaled columns and origin to depict e.g., a Frenet frame. */ - public static captureTransformAsFrame(collection: GeometryQuery[], frame: Transform, radius: number, axisLength: number = 1, x?: number, y?: number, z?: number): void { + public static captureTransformAsFrame( + collection: GeometryQuery[], + frame: Transform, + radius: number, + axisLength: number = 1, + x?: number, + y?: number, + z?: number, + ): void { const origin = Arc3d.createCenterNormalRadius(frame.getOrigin(), frame.matrix.columnZ(), radius); - const xAxis = LineSegment3d.create(frame.getOrigin(), frame.getOrigin().plusScaled(frame.matrix.columnX().normalizeWithDefault(0, 0, 0), axisLength)); - const yAxis = LineSegment3d.create(frame.getOrigin(), frame.getOrigin().plusScaled(frame.matrix.columnY().normalizeWithDefault(0, 0, 0), axisLength)); - const zAxis = LineSegment3d.create(frame.getOrigin(), frame.getOrigin().plusScaled(frame.matrix.columnZ().normalizeWithDefault(0, 0, 0), axisLength)); + const xAxis = LineSegment3d.create( + frame.getOrigin(), + frame.getOrigin().plusScaled(frame.matrix.columnX().normalizeWithDefault(0, 0, 0), axisLength), + ); + const yAxis = LineSegment3d.create( + frame.getOrigin(), + frame.getOrigin().plusScaled(frame.matrix.columnY().normalizeWithDefault(0, 0, 0), axisLength), + ); + const zAxis = LineSegment3d.create( + frame.getOrigin(), + frame.getOrigin().plusScaled(frame.matrix.columnZ().normalizeWithDefault(0, 0, 0), axisLength), + ); this.captureGeometry(collection, [origin, xAxis, yAxis, zAxis], x, y, z); } diff --git a/core/geometry/src/test/SimpleFactory.ts b/core/geometry/src/test/SimpleFactory.ts index 0a8f767e11cd..39537bae9627 100644 --- a/core/geometry/src/test/SimpleFactory.ts +++ b/core/geometry/src/test/SimpleFactory.ts @@ -17,29 +17,37 @@ import * as g from "../core-geometry"; * * higher selects should have increasing complexity */ export class SimpleFactory { - // an arc whose coordinates will all be "select == 2" compatible. - private static _arc2 = g.Arc3d.create(g.Point3d.create(0.2, 0.5, 0.3), g.Vector3d.create(0.9, 0.1, 0.01), g.Vector3d.create(-0.2, 0.5, -0.2), g.AngleSweep.createStartEndDegrees(20.5, 345.2)); + private static _arc2 = g.Arc3d.create( + g.Point3d.create(0.2, 0.5, 0.3), + g.Vector3d.create(0.9, 0.1, 0.01), + g.Vector3d.create(-0.2, 0.5, -0.2), + g.AngleSweep.createStartEndDegrees(20.5, 345.2), + ); // _point1 has integer coordinates private static _point1 = [ g.Point3d.create(1, 2, 3), g.Point3d.create(-2, 3, 1), - g.Point3d.create(-1, -2, 3)]; + g.Point3d.create(-1, -2, 3), + ]; // _vector1 has integer coordinates private static _vector1 = [ g.Vector3d.create(0, 1, 0), g.Vector3d.create(1, 0, 0), - g.Vector3d.create(1, 2, 4)]; + g.Vector3d.create(1, 2, 4), + ]; // _point2 has messy coordinates private static _point2 = [ g.Point3d.create(0.234, -0.1, 0.52), g.Point3d.create(Math.sqrt(2.0), 3.234204809, -2.3), - g.Point3d.create(-2.90089, 0.32481216727, -2.789798787)]; + g.Point3d.create(-2.90089, 0.32481216727, -2.789798787), + ]; // _vector1 has messy coordinates private static _vector2 = [ g.Vector3d.create(3 / 27, 4 / 27, 5 / 27), g.Vector3d.create(3, 5, 10).normalize()!, - g.Vector3d.create(-2.90089, 0.32481216727, -2.789798787)]; + g.Vector3d.create(-2.90089, 0.32481216727, -2.789798787), + ]; public static createDefaultLineSegment3d(select: number): g.LineSegment3d | undefined { if (select === 0) @@ -57,7 +65,12 @@ export class SimpleFactory { if (select === 1) return g.LineString3d.create(SimpleFactory._point1[0], SimpleFactory._point1[1]); if (select === 2) - return g.LineString3d.create(SimpleFactory._arc2.fractionToPoint(0.0), SimpleFactory._arc2.fractionToPoint(0.5), SimpleFactory._arc2.fractionToPoint(0.75), SimpleFactory._arc2.fractionToPoint(1.0)); + return g.LineString3d.create( + SimpleFactory._arc2.fractionToPoint(0.0), + SimpleFactory._arc2.fractionToPoint(0.5), + SimpleFactory._arc2.fractionToPoint(0.75), + SimpleFactory._arc2.fractionToPoint(1.0), + ); return undefined; } @@ -67,7 +80,12 @@ export class SimpleFactory { if (select === 1) return g.PointString3d.create(SimpleFactory._point1[0], SimpleFactory._point1[1]); if (select === 2) - return g.PointString3d.create(SimpleFactory._arc2.fractionToPoint(0.0), SimpleFactory._arc2.fractionToPoint(0.5), SimpleFactory._arc2.fractionToPoint(0.75), SimpleFactory._arc2.fractionToPoint(1.0)); + return g.PointString3d.create( + SimpleFactory._arc2.fractionToPoint(0.0), + SimpleFactory._arc2.fractionToPoint(0.5), + SimpleFactory._arc2.fractionToPoint(0.75), + SimpleFactory._arc2.fractionToPoint(1.0), + ); return undefined; } @@ -171,7 +189,10 @@ export class SimpleFactory { if (select === 2) return g.Transform.createOriginAndMatrix(g.Point3d.create(-1, 2, 3), g.Matrix3d.createRotationAroundAxisIndex(2, g.Angle.createDegrees(30))); if (select === 3) - return g.Transform.createOriginAndMatrix(g.Point3d.create(-1, 2, 3), g.Matrix3d.createRotationAroundVector(g.Vector3d.create(4, 2, -1), g.Angle.createDegrees(30))); + return g.Transform.createOriginAndMatrix( + g.Point3d.create(-1, 2, 3), + g.Matrix3d.createRotationAroundVector(g.Vector3d.create(4, 2, -1), g.Angle.createDegrees(30)), + ); return undefined; } @@ -208,17 +229,30 @@ export class SimpleFactory { public static createDefaultMatrix4d(select: number): g.Matrix4d | undefined { switch (select) { case 0: - return g.Matrix4d.createZero(); // and that is singular!!! + return g.Matrix4d.createZero(); // and that is singular!!! case 1: return g.Matrix4d.createIdentity(); case 2: return g.Matrix4d.createTranslationAndScaleXYZ(1, 3, 2, 3, 2, 4); case 2: return g.Matrix4d.createRowValues( - 12, 1, 0.2, 0.1, - 0.13, 10, 1.1, 2, - -0.3, 0.9, 12, 0.8, - 0.2, -0.23, 0.26, 15); + 12, + 1, + 0.2, + 0.1, + 0.13, + 10, + 1.1, + 2, + -0.3, + 0.9, + 12, + 0.8, + 0.2, + -0.23, + 0.26, + 15, + ); } return undefined; } diff --git a/core/geometry/src/test/bspline/AkimaCurve3d.test.ts b/core/geometry/src/test/bspline/AkimaCurve3d.test.ts index 1f3d7eb4ee46..7263a2bd7de8 100644 --- a/core/geometry/src/test/bspline/AkimaCurve3d.test.ts +++ b/core/geometry/src/test/bspline/AkimaCurve3d.test.ts @@ -4,11 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { Checker } from "../Checker"; -import { Sample } from "../../serialization/GeometrySamples"; import { AkimaCurve3d } from "../../bspline/AkimaCurve3d"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; import { GeometryQuery } from "../../curve/GeometryQuery"; +import { Sample } from "../../serialization/GeometrySamples"; +import { Checker } from "../Checker"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; import { testGeometryQueryRoundTrip } from "../serialization/FlatBuffer.test"; describe("AkimaCurve3d", () => { diff --git a/core/geometry/src/test/bspline/BSplineSurface.test.ts b/core/geometry/src/test/bspline/BSplineSurface.test.ts index 82291b8f7694..0f56ca44c8f5 100644 --- a/core/geometry/src/test/bspline/BSplineSurface.test.ts +++ b/core/geometry/src/test/bspline/BSplineSurface.test.ts @@ -2,28 +2,29 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BSplineSurface3d, BSplineSurface3dH, BSplineSurface3dQuery, UVSelect, WeightStyle } from "../../bspline/BSplineSurface"; import { BSplineWrapMode } from "../../bspline/KnotVector"; -import { Geometry } from "../../Geometry"; import { GeometryQuery } from "../../curve/GeometryQuery"; +import { StrokeOptions } from "../../curve/StrokeOptions"; +import { Geometry } from "../../Geometry"; import { Plane3dByOriginAndUnitNormal } from "../../geometry3d/Plane3dByOriginAndUnitNormal"; import { Point3d } from "../../geometry3d/Point3dVector3d"; +import { NumberArray, Point3dArray, Point4dArray } from "../../geometry3d/PointHelpers"; import { Range3d } from "../../geometry3d/Range"; import { Transform } from "../../geometry3d/Transform"; +import { Point4d } from "../../geometry4d/Point4d"; +import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; import { Sample } from "../../serialization/GeometrySamples"; +import { IModelJson } from "../../serialization/IModelJsonSchema"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { IModelJson } from "../../serialization/IModelJsonSchema"; import { testGeometryQueryRoundTrip } from "../serialization/FlatBuffer.test"; -import { StrokeOptions } from "../../curve/StrokeOptions"; -import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; -import { NumberArray, Point3dArray, Point4dArray } from "../../geometry3d/PointHelpers"; -import { Point4d } from "../../geometry4d/Point4d"; function testBasisValues(ck: Checker, data: Float64Array, expectedValue: number = 1) { - let s = 0.0; for (const a of data) s += a; + let s = 0.0; + for (const a of data) s += a; ck.testCoordinate(expectedValue, s, "basis sum"); } function testBSplineSurface(ck: Checker, surfaceA: BSplineSurface3dQuery) { @@ -43,10 +44,12 @@ function testBSplineSurface(ck: Checker, surfaceA: BSplineSurface3dQuery) { const pointB1 = surfaceB.fractionToPoint(u1, v1); const frameA0 = surfaceA.fractionToRigidFrame(u0, v0); const frameB0 = surfaceB.fractionToRigidFrame(u0, v0); - if (ck.testPointer(frameA0) + if ( + ck.testPointer(frameA0) && ck.testPointer(frameB0) && frameA0 - && frameB0) { + && frameB0 + ) { ck.testTransform(frameA0, frameB0); const frameA0Inverse = frameA0.inverse(); if (ck.testPointer(frameA0Inverse)) { @@ -54,10 +57,9 @@ function testBSplineSurface(ck: Checker, surfaceA: BSplineSurface3dQuery) { surfaceA.extendRange(rangeA2, frameA0Inverse); const planeA2 = Plane3dByOriginAndUnitNormal.create( Point3d.createFrom(frameA0.origin), - frameA0.matrix.columnZ()); - ck.testBoolean(surfaceA.isInPlane(planeA2!), - Geometry.isSmallMetricDistance(rangeA2.zLength()), - "Surface planarity test versus range in frame"); + frameA0.matrix.columnZ(), + ); + ck.testBoolean(surfaceA.isInPlane(planeA2!), Geometry.isSmallMetricDistance(rangeA2.zLength()), "Surface planarity test versus range in frame"); } } @@ -136,7 +138,6 @@ function testBSplineSurface(ck: Checker, surfaceA: BSplineSurface3dQuery) { } } } - } } @@ -174,9 +175,13 @@ describe("BSplineSurface", () => { dy = 0.0; for (const orderV of [2, 3, 4, 5]) { const bsurf = Sample.createPseudoTorusBsplineSurface( - 4.0, 1.0, // radii - Math.max(12, orderU + 1), Math.max(6, orderV + 1), // grid edges - orderU, orderV); + 4.0, + 1.0, // radii + Math.max(12, orderU + 1), + Math.max(6, orderV + 1), // grid edges + orderU, + orderV, + ); if (ck.testPointer(bsurf)) { if (ck.testTrue(bsurf.isClosable(UVSelect.uDirection))) ck.testExactNumber(BSplineWrapMode.OpenByAddingControlPoints, bsurf.isClosableSurface(UVSelect.uDirection)); @@ -198,11 +203,21 @@ describe("BSplineSurface", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const surfaceA = Sample.createPseudoTorusBsplineSurface( - 4.0, 1.0, // radii - 12, 6, 4, 4)!; // bicubic + 4.0, + 1.0, // radii + 12, + 6, + 4, + 4, + )!; // bicubic const surfaceB = Sample.createPseudoTorusBsplineSurface( - 4.0, 1.0, // radii - 12, 6, 5, 3)!; + 4.0, + 1.0, // radii + 12, + 6, + 5, + 3, + )!; surfaceB.tryTranslateInPlace(10, 0, 0); const options = StrokeOptions.createForFacets(); @@ -231,15 +246,24 @@ describe("BSplineSurface", () => { const allGeometry = []; let dx = 0.0; const dy = 0.0; - for (const bsurf of [Sample.createConeBsplineSurface( - Point3d.create(0, 0, 0), - Point3d.create(0, 0, 1), - 4.0, 1.0, 2), - Sample.createConeBsplineSurface( - Point3d.create(0, 0, 0), - Point3d.create(1, 3, 1), - 4.0, 1.0, - 3)]) { + for ( + const bsurf of [ + Sample.createConeBsplineSurface( + Point3d.create(0, 0, 0), + Point3d.create(0, 0, 1), + 4.0, + 1.0, + 2, + ), + Sample.createConeBsplineSurface( + Point3d.create(0, 0, 0), + Point3d.create(1, 3, 1), + 4.0, + 1.0, + 3, + ), + ] + ) { if (ck.testPointer(bsurf)) { bsurf.tryTranslateInPlace(dx, dy); allGeometry.push(bsurf); @@ -261,11 +285,26 @@ describe("BSplineSurface", () => { let surface2: BSplineSurface3d | BSplineSurface3dH | undefined; if (surface instanceof BSplineSurface3dH) { const poles = surface.copyXYZToFloat64Array(true); - surface2 = BSplineSurface3d.create(poles, surface.numPolesUV(UVSelect.uDirection), surface.orderUV(UVSelect.uDirection), surface.knots[UVSelect.uDirection].knots, - surface.numPolesUV(UVSelect.vDirection), surface.orderUV(UVSelect.vDirection), surface.knots[UVSelect.vDirection].knots); + surface2 = BSplineSurface3d.create( + poles, + surface.numPolesUV(UVSelect.uDirection), + surface.orderUV(UVSelect.uDirection), + surface.knots[UVSelect.uDirection].knots, + surface.numPolesUV(UVSelect.vDirection), + surface.orderUV(UVSelect.vDirection), + surface.knots[UVSelect.vDirection].knots, + ); } else { - surface2 = BSplineSurface3dH.create(surface.coffs, undefined, surface.numPolesUV(UVSelect.uDirection), surface.orderUV(UVSelect.uDirection), surface.knots[UVSelect.uDirection].knots, - surface.numPolesUV(UVSelect.vDirection), surface.orderUV(UVSelect.vDirection), surface.knots[UVSelect.vDirection].knots); // unit weights + surface2 = BSplineSurface3dH.create( + surface.coffs, + undefined, + surface.numPolesUV(UVSelect.uDirection), + surface.orderUV(UVSelect.uDirection), + surface.knots[UVSelect.uDirection].knots, + surface.numPolesUV(UVSelect.vDirection), + surface.orderUV(UVSelect.vDirection), + surface.knots[UVSelect.vDirection].knots, + ); // unit weights } if (ck.testDefined(surface2, "surface has valid pole dimension")) testGeometryQueryRoundTrip(ck, surface2); @@ -276,10 +315,14 @@ describe("BSplineSurface", () => { const options = StrokeOptions.createForFacets(); options.needNormals = options.needParams = options.shouldTriangulate = true; const allGeometry: GeometryQuery[] = []; - for (const filename of ["./src/test/data/BSplineSurface/torus3_open_closed.imjs", - "./src/test/data/BSplineSurface/torus6_open_closed.imjs", - "./src/test/data/BSplineSurface/nonrational_toroid_open.imjs", - "./src/test/data/BSplineSurface/nonrational_toroid_legacy_closed.imjs"]) { + for ( + const filename of [ + "./src/test/data/BSplineSurface/torus3_open_closed.imjs", + "./src/test/data/BSplineSurface/torus6_open_closed.imjs", + "./src/test/data/BSplineSurface/nonrational_toroid_open.imjs", + "./src/test/data/BSplineSurface/nonrational_toroid_legacy_closed.imjs", + ] + ) { const json = fs.readFileSync(filename, "utf8"); const inputs = IModelJson.Reader.parse(JSON.parse(json)); if (ck.testDefined(inputs)) { @@ -327,23 +370,65 @@ describe("BSplineSurface", () => { ck.testExactNumber(polesGrid.weightStyle!, WeightStyle.UnWeighted, "getPointGridJSON returns expected weightStyle"); ck.testExactNumber(polesGrid.numCartesianDimensions, 3, "getPointGridJSON returns expected dim"); ck.testTrue(NumberArray.isExactEqual(bsurf.copyPointsFloat64Array(), poles), "copyPointsFloat64Array returns expected points"); - ck.testTrue(NumberArray.isExactEqual(bsurf.knots[UVSelect.uDirection].knots, bsurf.copyKnots(UVSelect.uDirection, false)), "copyKnots returns expected uKnots"); - ck.testTrue(NumberArray.isExactEqual(bsurf.knots[UVSelect.vDirection].knots, bsurf.copyKnots(UVSelect.vDirection, false)), "copyKnots returns expected vKnots"); + ck.testTrue( + NumberArray.isExactEqual(bsurf.knots[UVSelect.uDirection].knots, bsurf.copyKnots(UVSelect.uDirection, false)), + "copyKnots returns expected uKnots", + ); + ck.testTrue( + NumberArray.isExactEqual(bsurf.knots[UVSelect.vDirection].knots, bsurf.copyKnots(UVSelect.vDirection, false)), + "copyKnots returns expected vKnots", + ); ck.testFalse(bsurf.testClosableGrid(UVSelect.uDirection), "testClosableGrid returns false with undefined mode in u-direction on open surface"); - ck.testFalse(bsurf.testClosableGrid(UVSelect.vDirection, BSplineWrapMode.None), "testClosableGrid returns false with mode None in v-direction on open surface"); + ck.testFalse( + bsurf.testClosableGrid(UVSelect.vDirection, BSplineWrapMode.None), + "testClosableGrid returns false with mode None in v-direction on open surface", + ); ck.testPoint3d(bsurf.uvFractionToPoint(1, 1), bsurf.getPole(uNumPoles - 1, vNumPoles - 1)!, "uvFractionToPoint returns expected point"); } - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles, 1, undefined, vNumPoles, vOrder, undefined), "create with uOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles, uNumPoles + 1, undefined, vNumPoles, vOrder, undefined), "create with uOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles, 1, undefined), "create with vOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles, vNumPoles + 1, undefined), "create with vOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles + 1, uOrder, undefined, vNumPoles, vOrder, undefined), "create with invalid uPole count yields undefined surface"); - ck.testUndefined(BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles + 1, vOrder, undefined), "create with invalid vPole count yields undefined surface"); - ck.testUndefined(BSplineSurface3d.createGrid([[[]]], uOrder, undefined, vOrder, undefined), "createGrid with invalid poles inner dimension yields undefined surface"); - ck.testUndefined(BSplineSurface3d.createGrid(polesFlat, 1, undefined, vOrder, undefined), "createGrid with uOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3d.createGrid(polesFlat, uNumPoles + 1, undefined, vOrder, undefined), "createGrid with uOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3d.createGrid(polesFlat, uOrder, undefined, 1, undefined), "createGrid with vOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3d.createGrid(polesFlat, uOrder, undefined, vNumPoles + 1, undefined), "createGrid with vOrder too large yields undefined surface"); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles, 1, undefined, vNumPoles, vOrder, undefined), + "create with uOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles, uNumPoles + 1, undefined, vNumPoles, vOrder, undefined), + "create with uOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles, 1, undefined), + "create with vOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles, vNumPoles + 1, undefined), + "create with vOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles + 1, uOrder, undefined, vNumPoles, vOrder, undefined), + "create with invalid uPole count yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.create(poles, uNumPoles, uOrder, undefined, vNumPoles + 1, vOrder, undefined), + "create with invalid vPole count yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.createGrid([[[]]], uOrder, undefined, vOrder, undefined), + "createGrid with invalid poles inner dimension yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.createGrid(polesFlat, 1, undefined, vOrder, undefined), + "createGrid with uOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.createGrid(polesFlat, uNumPoles + 1, undefined, vOrder, undefined), + "createGrid with uOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.createGrid(polesFlat, uOrder, undefined, 1, undefined), + "createGrid with vOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3d.createGrid(polesFlat, uOrder, undefined, vNumPoles + 1, undefined), + "createGrid with vOrder too large yields undefined surface", + ); GeometryCoreTestIO.saveGeometry(allGeometry, "BSplineSurface", "BSplineSurface3dCoverage"); expect(ck.getNumErrors()).toBe(0); @@ -383,30 +468,86 @@ describe("BSplineSurface", () => { bsurf.copyPointsAndWeights(myPoles, myWeights); ck.testTrue(Point3dArray.isAlmostEqual(myPoles, polesPoint3d), "copyPointsAndWeights returns expected points"); ck.testTrue(NumberArray.isExactEqual(myWeights, weights), "copyPointsAndWeights returns expected weights"); - ck.testTrue(NumberArray.isExactEqual(bsurf.knots[UVSelect.uDirection].knots, bsurf.copyKnots(UVSelect.uDirection, false)), "copyKnots returns expected uKnots"); - ck.testTrue(NumberArray.isExactEqual(bsurf.knots[UVSelect.vDirection].knots, bsurf.copyKnots(UVSelect.vDirection, false)), "copyKnots returns expected vKnots"); + ck.testTrue( + NumberArray.isExactEqual(bsurf.knots[UVSelect.uDirection].knots, bsurf.copyKnots(UVSelect.uDirection, false)), + "copyKnots returns expected uKnots", + ); + ck.testTrue( + NumberArray.isExactEqual(bsurf.knots[UVSelect.vDirection].knots, bsurf.copyKnots(UVSelect.vDirection, false)), + "copyKnots returns expected vKnots", + ); ck.testFalse(bsurf.testClosableGrid(UVSelect.uDirection), "testClosableGrid returns false with undefined mode in u-direction on open surface"); - ck.testFalse(bsurf.testClosableGrid(UVSelect.vDirection, BSplineWrapMode.None), "testClosableGrid returns false with mode None in v-direction on open surface"); + ck.testFalse( + bsurf.testClosableGrid(UVSelect.vDirection, BSplineWrapMode.None), + "testClosableGrid returns false with mode None in v-direction on open surface", + ); ck.testPoint3d(bsurf.uvFractionToPoint(1, 1), bsurf.getPole(uNumPoles - 1, vNumPoles - 1)!, "uvFractionToPoint returns expected point"); - let bsurfGrid = BSplineSurface3dH.createGrid(polesFlatUnweighted, WeightStyle.WeightsSeparateFromCoordinates, uOrder, undefined, vOrder, undefined); + let bsurfGrid = BSplineSurface3dH.createGrid( + polesFlatUnweighted, + WeightStyle.WeightsSeparateFromCoordinates, + uOrder, + undefined, + vOrder, + undefined, + ); if (ck.testType(bsurfGrid, BSplineSurface3dH, "createGrid returns expected type")) ck.testNumberArray(bsurfGrid.coffs, bsurf.coffs, "createGrid with separate weights input yields expected poles"); bsurfGrid = BSplineSurface3dH.createGrid(polesFlatUnweighted, WeightStyle.UnWeighted, uOrder, undefined, vOrder, undefined); if (ck.testType(bsurfGrid, BSplineSurface3dH, "createGrid returns expected type")) - ck.testNumberArray(bsurfGrid.copyXYZToFloat64Array(false), bsurf.copyXYZToFloat64Array(true), "createGrid with unweighted input yields expected poles"); + ck.testNumberArray( + bsurfGrid.copyXYZToFloat64Array(false), + bsurf.copyXYZToFloat64Array(true), + "createGrid with unweighted input yields expected poles", + ); } - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, 1, undefined, vNumPoles, vOrder, undefined), "create with uOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uNumPoles + 1, undefined, vNumPoles, vOrder, undefined), "create with uOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles, 1, undefined), "create with vOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles, vNumPoles + 1, undefined), "create with vOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles + 1, uOrder, undefined, vNumPoles, vOrder, undefined), "create with invalid uPole count yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles + 1, vOrder, undefined), "create with invalid vPole count yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.create(polesPoint3d, [1, 1], uNumPoles, uOrder, undefined, vNumPoles, vOrder, undefined), "create with different counts for poles and weights yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.createGrid([[[]]], WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, vOrder, undefined), "createGrid with invalid poles inner dimension yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, 1, undefined, vOrder, undefined), "createGrid with uOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uNumPoles + 1, undefined, vOrder, undefined), "createGrid with uOrder too large yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, 1, undefined), "createGrid with vOrder too small yields undefined surface"); - ck.testUndefined(BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, vNumPoles + 1, undefined), "createGrid with vOrder too large yields undefined surface"); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, 1, undefined, vNumPoles, vOrder, undefined), + "create with uOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uNumPoles + 1, undefined, vNumPoles, vOrder, undefined), + "create with uOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles, 1, undefined), + "create with vOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles, vNumPoles + 1, undefined), + "create with vOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles + 1, uOrder, undefined, vNumPoles, vOrder, undefined), + "create with invalid uPole count yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, weights, uNumPoles, uOrder, undefined, vNumPoles + 1, vOrder, undefined), + "create with invalid vPole count yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.create(polesPoint3d, [1, 1], uNumPoles, uOrder, undefined, vNumPoles, vOrder, undefined), + "create with different counts for poles and weights yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.createGrid([[[]]], WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, vOrder, undefined), + "createGrid with invalid poles inner dimension yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, 1, undefined, vOrder, undefined), + "createGrid with uOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uNumPoles + 1, undefined, vOrder, undefined), + "createGrid with uOrder too large yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, 1, undefined), + "createGrid with vOrder too small yields undefined surface", + ); + ck.testUndefined( + BSplineSurface3dH.createGrid(polesFlat, WeightStyle.WeightsAlreadyAppliedToCoordinates, uOrder, undefined, vNumPoles + 1, undefined), + "createGrid with vOrder too large yields undefined surface", + ); GeometryCoreTestIO.saveGeometry(allGeometry, "BSplineSurface", "BSplineSurface3dHCoverage"); expect(ck.getNumErrors()).toBe(0); diff --git a/core/geometry/src/test/bspline/BezierCurve.test.ts b/core/geometry/src/test/bspline/BezierCurve.test.ts index 46a7740736e9..f1df180561d7 100644 --- a/core/geometry/src/test/bspline/BezierCurve.test.ts +++ b/core/geometry/src/test/bspline/BezierCurve.test.ts @@ -31,7 +31,6 @@ function exercise1dNdBase(ck: Checker, curve: Bezier1dNd) { ck.testTrue(pointA === pointB, "reuse buffer"); } describe("BsplineCurve", () => { - it("PoleQueries", () => { const ck = new Checker(); const allPoints: Point3d[] = [ @@ -40,7 +39,8 @@ describe("BsplineCurve", () => { Point3d.create(10, 10, 0), Point3d.create(10, 0, 0), Point3d.create(20, 0, 0), - Point3d.create(20, 10, 0)]; + Point3d.create(20, 10, 0), + ]; ck.testUndefined(BezierCurve3d.create([])); const bezierCurves = [BezierCurve3d.create(allPoints)!, BezierCurve3dH.create(allPoints)!]; @@ -113,9 +113,9 @@ describe("BsplineCurve", () => { const basis1 = new Float64Array(3); basis[0] = 10.0; basis1[0] = 11.0; - zeroDegreeKnots.evaluateBasisFunctions(0, 0, basis); // nothing happens ! + zeroDegreeKnots.evaluateBasisFunctions(0, 0, basis); // nothing happens ! ck.testExactNumber(1.0, basis[0]); - zeroDegreeKnots.evaluateBasisFunctions1(0, 0, basis, basis1); // nothing happens ! + zeroDegreeKnots.evaluateBasisFunctions1(0, 0, basis, basis1); // nothing happens ! ck.testExactNumber(1.0, basis[0]); ck.testExactNumber(0.0, basis1[0]); ck.testFalse(knotVector1.isIndexOfRealSpan(-1)); @@ -146,7 +146,8 @@ describe("BsplineCurve", () => { Point3d.create(10, 10, 0), Point3d.create(10, 0, 0), Point3d.create(20, 0, 0), - Point3d.create(20, 10, 0)]; + Point3d.create(20, 10, 0), + ]; const livePoints = []; const uniformKnots = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; const yShift = 20.0; @@ -204,7 +205,8 @@ describe("BsplineCurve", () => { Point3d.create(10 + a, 0, 0), Point3d.create(20, 0, 0), Point3d.create(20 + a, 10, 0), - Point3d.create(10, 20, 0)]; + Point3d.create(10, 20, 0), + ]; const dx = 100.0; let x0 = 0.0; let y0 = 0.0; @@ -228,10 +230,15 @@ describe("BsplineCurve", () => { if (order > 2) { for (const u of knots) { if (u > 0.0 && u < 1.0) { - const curvePoint = bcurve.knotToPointAndDerivative(u); // evaluate the knot point + const curvePoint = bcurve.knotToPointAndDerivative(u); // evaluate the knot point const perp = curvePoint.direction.rotate90CCWXY(); perp.normalizeInPlace(); - GeometryCoreTestIO.captureGeometry(geometry, LineSegment3d.create(curvePoint.origin, curvePoint.origin.plusScaled(perp, tickLength)), x0, y0); + GeometryCoreTestIO.captureGeometry( + geometry, + LineSegment3d.create(curvePoint.origin, curvePoint.origin.plusScaled(perp, tickLength)), + x0, + y0, + ); } } } @@ -254,9 +261,9 @@ describe("BsplineCurve", () => { GeometryCoreTestIO.captureGeometry(geometry, bezier.clone(), x0, y3); const bezier4 = bezier.clonePartialCurve(g0, 1.0); - const bezier5 = bezier4.clonePartialCurve(0.0, (g1 - g0) / (1 - g0)); // Remark: This uses the opposite left/right order of what happen in clone partial. (Same result expected) + const bezier5 = bezier4.clonePartialCurve(0.0, (g1 - g0) / (1 - g0)); // Remark: This uses the opposite left/right order of what happen in clone partial. (Same result expected) const bezier6 = bezier.clonePartialCurve(g0, g1); - ck.testTrue(bezier5.isAlmostEqual(bezier6), "bezier subdivision"); // wow, math is right. + ck.testTrue(bezier5.isAlmostEqual(bezier6), "bezier subdivision"); // wow, math is right. GeometryCoreTestIO.captureGeometry(geometry, bezier4, x0, y4); GeometryCoreTestIO.captureGeometry(geometry, bezier5, x0, y4); GeometryCoreTestIO.captureGeometry(geometry, bezier6, x0, y4); diff --git a/core/geometry/src/test/bspline/BsplineCurve.test.ts b/core/geometry/src/test/bspline/BsplineCurve.test.ts index fdc7ea6332eb..d2c9cbddfe57 100644 --- a/core/geometry/src/test/bspline/BsplineCurve.test.ts +++ b/core/geometry/src/test/bspline/BsplineCurve.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BezierCurve3d } from "../../bspline/BezierCurve3d"; import { BezierCurveBase } from "../../bspline/BezierCurveBase"; import { BSplineCurve3d, BSplineCurve3dBase } from "../../bspline/BSplineCurve"; @@ -64,7 +64,7 @@ function buildClampedSteppedKnots(numPoints: number, order: number, step: number */ function buildWrappableSteppedKnots(numInterval: number, order: number, step: number): number[] { const knots = []; - const knot0 = - step * (order - 2); + const knot0 = -step * (order - 2); for (let i = 0; i < numInterval + order - 2; i++) knots.push(knot0 + i * step); return knots; @@ -79,15 +79,15 @@ function translateAndPush(allGeometry: GeometryQuery[], g: GeometryQuery | undef function showPlane(allGeometry: GeometryQuery[], plane: Plane3dByOriginAndUnitNormal, a: number, dx: number, dy: number) { const origin = plane.getOriginRef(); const normal = plane.getNormalRef(); - const frame = Transform.createOriginAndMatrix(origin, - Matrix3d.createRigidViewAxesZTowardsEye(normal.x, normal.y, normal.z)); + const frame = Transform.createOriginAndMatrix(origin, Matrix3d.createRigidViewAxesZTowardsEye(normal.x, normal.y, normal.z)); const g = LineString3d.create( frame.multiplyXYZ(-0.5 * a, 0, 0), frame.multiplyXYZ(a, 0, 0), frame.multiplyXYZ(a, a, 0), frame.multiplyXYZ(0, a, 0), origin, - frame.multiplyXYZ(0, 0, 2 * a)); + frame.multiplyXYZ(0, 0, 2 * a), + ); if (g) { g.tryTranslateInPlace(dx, dy, 0); allGeometry.push(g); @@ -100,7 +100,8 @@ function showPoint(allGeometry: GeometryQuery[], point: Point3d, a: number, dx: Point3d.create(point.x - a, point.y, point.z), Point3d.create(point.x + a, point.y, point.z), Point3d.create(point.x, point.y + a, point.z), - Point3d.create(point.x, point.y, point.z)); + Point3d.create(point.x, point.y, point.z), + ); if (g) { g.tryTranslateInPlace(dx, dy, 0); allGeometry.push(g); @@ -121,8 +122,14 @@ function ellipsePoints(a: number, b: number, sweep: AngleSweep, numStep: number) * @param edgeLengthFactor factor to apply to edgeLength conditions * @param angleFactor factor to apply to angle conditions */ -function checkStrokeProperties(ck: Checker, curve: CurvePrimitive, linestring: LineString3d, options: StrokeOptions, - angleFactor: number = 1.1, edgeLengthFactor: number = 1.1): boolean { +function checkStrokeProperties( + ck: Checker, + curve: CurvePrimitive, + linestring: LineString3d, + options: StrokeOptions, + angleFactor: number = 1.1, + edgeLengthFactor: number = 1.1, +): boolean { const numPoints = linestring.numPoints(); let ok = true; if (ck.testLE(3, numPoints, "Expect 3 or more strokes")) { @@ -136,17 +143,18 @@ function checkStrokeProperties(ck: Checker, curve: CurvePrimitive, linestring: L maxRadians = Geometry.maxXY(maxRadians, vector0.angleTo(vector1).radians); vector0.setFromVector3d(vector1); } - if (options.maxEdgeLength) + if (options.maxEdgeLength) { if (!ck.testLE(maxRadians, edgeLengthFactor * options.maxEdgeLength, "strokeProperties edge length", curve)) ok = false; - if (options.angleTol) + } + if (options.angleTol) { if (!ck.testLE(maxRadians, angleFactor * options.angleTol.radians, "stroke properties angle", curve)) ok = false; + } } return ok; } describe("BsplineCurve", () => { - it("HelloWorld", () => { const ck = new Checker(); for (const rational of [false, true]) { @@ -191,7 +199,6 @@ describe("BsplineCurve", () => { const knotPoint = curve.knotToPoint(knot); ck.testCoordinate(knot, knotPoint.x, "x == knot"); ck.testPoint3d(spanPoint, knotPoint, "spanPoint, knotPoint", order, span, spanFraction); - } ck.testCoordinate(b, p1.y, "constant bspline y"); if (Checker.noisy.bsplineEvaluation) GeometryCoreTestIO.consoleLog("span", span, p0, p1, p2); @@ -225,7 +232,7 @@ describe("BsplineCurve", () => { for (const options of allOptions) { const linestring = LineString3d.create(); curve.emitStrokes(linestring, options); - const angleFactor = curve.order <= 2 ? 1000 : 1.6; // suppress angle test on linear case. Be fluffy on others. + const angleFactor = curve.order <= 2 ? 1000 : 1.6; // suppress angle test on linear case. Be fluffy on others. translateAndPush(allGeometry, linestring, xShift, yShift); if (!checkStrokeProperties(ck, curve, linestring, options, angleFactor, 1.1)) { linestring.clear(); @@ -266,13 +273,17 @@ describe("BsplineCurve", () => { // Be sure the curve is all in one quadrant so 00 is NOT in the stroke range. const ck = new Checker(); const bcurve = BSplineCurve3d.create( - [Point3d.create(1, 0), - Point3d.create(2, 0, 0), - Point3d.create(2, 1, 0), - Point3d.create(3, 1, 0), - Point3d.create(4, 0, 0), - Point3d.create(5, 1, 0)], - [0, 0, 0.5, 0.5, 0.75, 1, 1], 3)!; + [ + Point3d.create(1, 0), + Point3d.create(2, 0, 0), + Point3d.create(2, 1, 0), + Point3d.create(3, 1, 0), + Point3d.create(4, 0, 0), + Point3d.create(5, 1, 0), + ], + [0, 0, 0.5, 0.5, 0.75, 1, 1], + 3, + )!; const path = Path.create(bcurve); const strokes = path.getPackedStrokes()!; // GeometryCoreTestIO.consoleLog(prettyPrint(strokes)); @@ -310,23 +321,31 @@ describe("BsplineCurve", () => { const microstationStyleArc = { bcurve: { closed: true, - knots: [-0.33333333333333337, 0.0, 0.0, 0.0, 0.33333333333333331, 0.33333333333333331, 0.66666666666666663, 0.66666666666666663, + knots: [ + -0.33333333333333337, + 0.0, + 0.0, + 0.0, + 0.33333333333333331, + 0.33333333333333331, + 0.66666666666666663, + 0.66666666666666663, 1.0, 1.0, 1.0, - 1.3333333333333333], + 1.3333333333333333, + ], order: 3, points: [ - [1.0, 0.0, 0.0, 1.0], [0.50000000000000011, 0.86602540378443860, 0.0, 0.50000000000000011], - [-0.49999999999999978, 0.86602540378443871, 0.0, 1.0], [-0.99999999999999989, 7.2674717409587315e-17, 0.0, - 0.50000000000000011], + [-0.49999999999999978, 0.86602540378443871, 0.0, 1.0], + [-0.99999999999999989, 7.2674717409587315e-17, 0.0, 0.50000000000000011], [-0.50000000000000044, -0.86602540378443849, 0.0, 1.0], - [0.49999999999999922, -0.86602540378443904, 0.0, 0.50000000000000011], [1.0, - -2.4492935982947064e-16, 0.0, - 1.0]], + [0.49999999999999922, -0.86602540378443904, 0.0, 0.50000000000000011], + [1.0, -2.4492935982947064e-16, 0.0, 1.0], + ], }, }; const g1 = IModelJson.Reader.parse(microstationStyleArc); @@ -343,22 +362,27 @@ describe("BsplineCurve", () => { const allGeometry: GeometryQuery[] = []; for (const factor of [0.5, 1, 3]) { const transform = Transform.createScaleAboutPoint(Point3d.create(0, 0, 0), factor); - for (const allPoints of [ - [Point3d.create(0, 0, 0), - Point3d.create(0, 10, 0), - Point3d.create(10, 10, 0), - Point3d.create(10, 0, 0), - Point3d.create(20, 0, 0), - Point3d.create(20, 10, 0), - Point3d.create(25, 5, 0), - Point3d.create(30, 5, 0), - Point3d.create(35, 10, 0)], - ellipsePoints(35, 20, AngleSweep.createStartEndDegrees(-45, 110), 9)]) { + for ( + const allPoints of [ + [ + Point3d.create(0, 0, 0), + Point3d.create(0, 10, 0), + Point3d.create(10, 10, 0), + Point3d.create(10, 0, 0), + Point3d.create(20, 0, 0), + Point3d.create(20, 10, 0), + Point3d.create(25, 5, 0), + Point3d.create(30, 5, 0), + Point3d.create(35, 10, 0), + ], + ellipsePoints(35, 20, AngleSweep.createStartEndDegrees(-45, 110), 9), + ] + ) { transform.multiplyPoint3dArrayInPlace(allPoints); for (let degree = 1; degree < 6; degree++) { const bcurve = BSplineCurve3d.createUniformKnots(allPoints, degree + 1)!; let cp: BezierCurveBase | undefined; - for (let spanIndex = 0; ; spanIndex++) { + for (let spanIndex = 0;; spanIndex++) { cp = bcurve.getSaturatedBezierSpan3d(spanIndex, cp); if (!cp) break; const bezier = cp as BezierCurve3d; @@ -397,7 +421,7 @@ describe("BsplineCurve", () => { // Alter the ray z so it is not perpendicular .. // tangentRay.direction.z += 0.02; const intersections: CurveLocationDetail[] = []; - const plane = Plane3dByOriginAndUnitNormal.create(tangentRay.origin, tangentRay.direction)!; // This normalizes. + const plane = Plane3dByOriginAndUnitNormal.create(tangentRay.origin, tangentRay.direction)!; // This normalizes. curve.appendPlaneIntersectionPoints(plane, intersections); if (intersections.length > 1) curve.appendPlaneIntersectionPoints(plane, intersections); @@ -419,11 +443,27 @@ describe("BsplineCurve", () => { it("BsplineCurve3dHCoverage", () => { const ck = new Checker(); const poleBuffer = new Float64Array([ - 0, 0, 0, 1, - 1, 0, 0, 1, - 1, 1, 0, 2, // weights vary !! - 0, 1, 1, 1, // non planar - 0, 2, 2, 1]); + 0, + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 1, + 1, + 0, + 2, // weights vary !! + 0, + 1, + 1, + 1, // non planar + 0, + 2, + 2, + 1, + ]); const myKnots = [0, 0, 0, 1, 2, 2, 2]; const bcurve = BSplineCurve3dH.create(poleBuffer, myKnots, 4)!; const bcurveB = BSplineCurve3dH.createUniformKnots(poleBuffer, 4); @@ -463,11 +503,22 @@ describe("BsplineCurve", () => { it("BsplineCurve3dCoverage", () => { const ck = new Checker(); const poleBuffer = new Float64Array([ - 0, 0, 0, - 1, 0, 0, - 1, 1, 0, - 0, 1, 1, - 0, 2, 2]); + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 1, + 0, + 0, + 1, + 1, + 0, + 2, + 2, + ]); const myKnots = [0, 0, 0, 1, 2, 2, 2]; const myKnotsClassic = [0, ...myKnots, 2]; const bcurve = BSplineCurve3d.create(poleBuffer, myKnots, 4)!; @@ -477,7 +528,10 @@ describe("BsplineCurve", () => { ck.testUndefined(BSplineCurve3d.create(poleBuffer, myKnots, 10), "create with order too large returns undefined"); ck.testUndefined(BSplineCurve3d.create(poleBuffer, myKnots, 1), "create with order too small returns undefined"); ck.testUndefined(BSplineCurve3d.create(poleBuffer, [], 4), "create with empty knots returns undefined"); - ck.testUndefined(BSplineCurve3d.create([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], myKnots, 4), "create with pole input as 2D number array of invalid dimension returns undefined"); + ck.testUndefined( + BSplineCurve3d.create([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], myKnots, 4), + "create with pole input as 2D number array of invalid dimension returns undefined", + ); ck.testDefined(BSplineCurve3d.create(poleBuffer, myKnotsClassic, 4)); ck.testPointer(bcurveB); const poleBufferA = bcurve.copyPointsFloat64Array(); @@ -524,7 +578,8 @@ describe("BsplineCurve", () => { Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 1), - Point3d.create(0, 2, 2)]; + Point3d.create(0, 2, 2), + ]; for (const order of [3, 4, 5]) { const myKnots = buildClampedSteppedKnots(poleArray.length, order, 1.0); const bcurve3d = BSplineCurve3d.create(poleArray, myKnots, order)!; @@ -538,7 +593,6 @@ describe("BsplineCurve", () => { bcurve3d.fractionToPoint(u); bcurve4d.fractionToPoint(u); } - } } GeometryCoreTestIO.saveGeometry(allGeometry, "BSplineCurve", "WeightedCurveMatch"); @@ -554,7 +608,8 @@ describe("BsplineCurve", () => { Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 1), - Point3d.create(0, 2, 2)]; + Point3d.create(0, 2, 2), + ]; for (const order of [2, 3, 4, 5]) { // wrap the points const wrappedPoleArray = []; @@ -623,18 +678,34 @@ describe("BsplineCurve", () => { const path = IModelJson.Reader.parse({ path: [{ bcurve: { - points: [[562203.9888586091, 4184365.4828894683, 13.075188058999167], - [562203.8776459384, 4184365.258953491, 13.075185855086009], - [562203.7664332676, 4184365.035017514, 13.075183688796626], - [562203.6552205969, 4184364.811081537, 13.07518155809684], - [562203.5440079262, 4184364.58714556, 13.075179427397055], - [562203.4327952556, 4184364.3632095824, 13.07517733228783], - [562203.3215825849, 4184364.1392736053, 13.075175270883584], - [562203.0991924296, 4184363.691472501, 13.075171148727286], - [562202.8768022744, 4184363.2436713967, 13.075167161227737], - [562202.6544121193, 4184362.7958702925, 13.075163294885328]], - knots: [0, 0, 0, 0, 0.2500197756132385, 0.2500197756132385, 0.2500197756132385, - 0.500039551226476, 0.500039551226476, 0.500039551226476, 1, 1, 1, 1], + points: [ + [562203.9888586091, 4184365.4828894683, 13.075188058999167], + [562203.8776459384, 4184365.258953491, 13.075185855086009], + [562203.7664332676, 4184365.035017514, 13.075183688796626], + [562203.6552205969, 4184364.811081537, 13.07518155809684], + [562203.5440079262, 4184364.58714556, 13.075179427397055], + [562203.4327952556, 4184364.3632095824, 13.07517733228783], + [562203.3215825849, 4184364.1392736053, 13.075175270883584], + [562203.0991924296, 4184363.691472501, 13.075171148727286], + [562202.8768022744, 4184363.2436713967, 13.075167161227737], + [562202.6544121193, 4184362.7958702925, 13.075163294885328], + ], + knots: [ + 0, + 0, + 0, + 0, + 0.2500197756132385, + 0.2500197756132385, + 0.2500197756132385, + 0.500039551226476, + 0.500039551226476, + 0.500039551226476, + 1, + 1, + 1, + 1, + ], closed: false, order: 4, }, @@ -654,7 +725,7 @@ describe("BsplineCurve", () => { const x2 = 100.0; const allGeometry: GeometryQuery[] = []; let x0Out = 0.0; - for (let i = 0; ; i++) { + for (let i = 0;; i++) { let options; if (i === 0) { options = undefined; @@ -727,8 +798,7 @@ describe("BsplineCurve", () => { it("LegacyClosureRoundTrip", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - for (const filename of ["./src/test/data/curve/openAndClosedCurves.imjs", - "./src/test/data/curve/openAndClosedCurves2.imjs"]) { + for (const filename of ["./src/test/data/curve/openAndClosedCurves.imjs", "./src/test/data/curve/openAndClosedCurves2.imjs"]) { const json = fs.readFileSync(filename, "utf8"); const inputs = IModelJson.Reader.parse(JSON.parse(json)); if (ck.testDefined(inputs)) { @@ -739,7 +809,7 @@ describe("BsplineCurve", () => { for (const input of inputs) { let curve = input; if (input instanceof CurveChain && input.children.length === 1) - curve = input.children[0]; // assume input chains have only one child + curve = input.children[0]; // assume input chains have only one child if (curve instanceof BSplineCurve3dBase) { const strokes = LineString3d.create(); curve.emitStrokes(strokes, options); @@ -767,17 +837,31 @@ describe("BsplineCurve", () => { const endKnot = 10; const wrappedKnots = KnotVector.createUniformWrapped(numKnotIntervals, degree, startKnot, endKnot); - ck.testTrue(wrappedKnots.testClosable(BSplineWrapMode.OpenByAddingControlPoints), "wrapped knots are closable with wrap mode OpenByAddingControlPoints"); + ck.testTrue( + wrappedKnots.testClosable(BSplineWrapMode.OpenByAddingControlPoints), + "wrapped knots are closable with wrap mode OpenByAddingControlPoints", + ); ck.testFalse(wrappedKnots.testClosable(BSplineWrapMode.OpenByRemovingKnots), "wrapped knots are not closable with wrap mode OpenByRemovingKnots"); wrappedKnots.wrappable = BSplineWrapMode.OpenByAddingControlPoints; // simulate B-spline imported from legacy data closed with full continuity const wrappedKnotsLegacy = wrappedKnots.copyKnots(true); ck.testExactNumber(numKnots + 2, wrappedKnotsLegacy.length, "copyKnots with wrapMode OpenByAddingControlPoints added two extra knots"); - ck.testLT(wrappedKnotsLegacy[0], wrappedKnotsLegacy[1], "copyKnots with wrapMode OpenByAddingControlPoints prepended first knot less than second"); - ck.testLT(wrappedKnotsLegacy[wrappedKnotsLegacy.length - 2], wrappedKnotsLegacy[wrappedKnotsLegacy.length - 1], "copyKnots appended last knot greater than penultimate"); + ck.testLT( + wrappedKnotsLegacy[0], + wrappedKnotsLegacy[1], + "copyKnots with wrapMode OpenByAddingControlPoints prepended first knot less than second", + ); + ck.testLT( + wrappedKnotsLegacy[wrappedKnotsLegacy.length - 2], + wrappedKnotsLegacy[wrappedKnotsLegacy.length - 1], + "copyKnots appended last knot greater than penultimate", + ); const clampedKnots = KnotVector.createUniformClamped(numPoles, degree, startKnot, endKnot); ck.testTrue(clampedKnots.testClosable(BSplineWrapMode.OpenByRemovingKnots), "clamped knots are closable with wrap mode OpenByRemovingKnots"); - ck.testFalse(clampedKnots.testClosable(BSplineWrapMode.OpenByAddingControlPoints), "clamped knots are not closable with wrap mode OpenByAddingControlPoints"); + ck.testFalse( + clampedKnots.testClosable(BSplineWrapMode.OpenByAddingControlPoints), + "clamped knots are not closable with wrap mode OpenByAddingControlPoints", + ); let clampedKnotsLegacy = clampedKnots.copyKnots(true); ck.testExactNumber(numKnots + 2, clampedKnotsLegacy.length, "copyKnots without wrapMode added two extra knots"); ck.testExactNumber(clampedKnotsLegacy[0], startKnot, "copyKnots without wrapMode prepended start knot"); @@ -794,8 +878,14 @@ describe("BsplineCurve", () => { ck.testTrue(NumberArray.isExactEqual(clampedKnotsLegacy, clampedKnotsCopy), "cloneWithStartAndEndMultiplicity adds knots"); // related array coverage - ck.testTrue(NumberArray.cloneWithStartAndEndMultiplicity(undefined, degree, degree).length === 0, "cover cloneWithStartAndEndMultiplicity on undefined input"); - ck.testTrue(NumberArray.cloneWithStartAndEndMultiplicity([], degree, degree).length === 0, "cover cloneWithStartAndEndMultiplicity on empty input"); + ck.testTrue( + NumberArray.cloneWithStartAndEndMultiplicity(undefined, degree, degree).length === 0, + "cover cloneWithStartAndEndMultiplicity on undefined input", + ); + ck.testTrue( + NumberArray.cloneWithStartAndEndMultiplicity([], degree, degree).length === 0, + "cover cloneWithStartAndEndMultiplicity on empty input", + ); ck.testUndefined(NumberArray.unpack2d(wrappedKnots.knots, 0), "unpack2d on invalid numPerBlock"); ck.testUndefined(NumberArray.unpack3d(wrappedKnots.knots, 0, 1), "unpack3d on invalid numPerRow"); ck.testUndefined(NumberArray.unpack3d(wrappedKnots.knots, 1, 0), "unpack3d on invalid numPerBlock"); diff --git a/core/geometry/src/test/bspline/ConvexClipPlaneSet.test.ts b/core/geometry/src/test/bspline/ConvexClipPlaneSet.test.ts index 2ecf25c84247..3a7b33a3b1cd 100644 --- a/core/geometry/src/test/bspline/ConvexClipPlaneSet.test.ts +++ b/core/geometry/src/test/bspline/ConvexClipPlaneSet.test.ts @@ -27,13 +27,17 @@ describe("ConvexClipPlaneSet", () => { const ay = -2; const bx = 1; const by = 4; - const boxA = ConvexClipPlaneSet.createXYPolyLine([ - Point3d.create(ax, ay, 0), - Point3d.create(bx, ay, 0), - Point3d.create(bx, by, 0), - Point3d.create(ax, by, 0), - Point3d.create(ax, ay, 0)], - [true, true, true, true, true], true); + const boxA = ConvexClipPlaneSet.createXYPolyLine( + [ + Point3d.create(ax, ay, 0), + Point3d.create(bx, ay, 0), + Point3d.create(bx, by, 0), + Point3d.create(ax, by, 0), + Point3d.create(ax, ay, 0), + ], + [true, true, true, true, true], + true, + ); const boxA1 = boxA.clone(); ck.testFalse(errorSet1.isAlmostEqual(boxA)); ConvexClipPlaneSet.createEmpty(boxA1); @@ -41,18 +45,26 @@ describe("ConvexClipPlaneSet", () => { const boxB = ConvexClipPlaneSet.createXYBox(ax, ay, bx, by); const boxC = boxB.clone(); const segmentM = LineSegment3d.createXYXY( - Geometry.interpolate(ax, 0.3, bx), ay, - bx, Geometry.interpolate(ay, 0.9, by), 0); - - for (const transform of [ - Transform.createTranslationXYZ(10, 0, 0), - Transform.createFixedPointAndMatrix( - Point3d.create(ax, ay, 0), - Matrix3d.createRotationAroundVector(Vector3d.create(0, 0, 1), Angle.createDegrees(90))!), - Transform.createFixedPointAndMatrix( - Point3d.create(3, 2, 5), - Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 9), Angle.createDegrees(23))!)]) { + Geometry.interpolate(ax, 0.3, bx), + ay, + bx, + Geometry.interpolate(ay, 0.9, by), + 0, + ); + for ( + const transform of [ + Transform.createTranslationXYZ(10, 0, 0), + Transform.createFixedPointAndMatrix( + Point3d.create(ax, ay, 0), + Matrix3d.createRotationAroundVector(Vector3d.create(0, 0, 1), Angle.createDegrees(90))!, + ), + Transform.createFixedPointAndMatrix( + Point3d.create(3, 2, 5), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 9), Angle.createDegrees(23))!, + ), + ] + ) { const segmentN = segmentM.cloneTransformed(transform); const boxD = boxA.clone(); boxD.transformInPlace(transform); diff --git a/core/geometry/src/test/bspline/ConvexPolygon2d.test.ts b/core/geometry/src/test/bspline/ConvexPolygon2d.test.ts index eb7801ce6597..10462006caec 100644 --- a/core/geometry/src/test/bspline/ConvexPolygon2d.test.ts +++ b/core/geometry/src/test/bspline/ConvexPolygon2d.test.ts @@ -54,7 +54,8 @@ function checkHullChords(hull: ConvexPolygon2d, step: number, ck: Checker) { const range = hull.rangeAlongRay(ray); const ray1 = Ray2d.createOriginAndDirectionCapture( ray.fractionToPoint(range.low), - ray.direction.scale(range.high - range.low)); + ray.direction.scale(range.high - range.low), + ); const range1 = hull.rangeAlongRay(ray1); ck.testCoordinate(range1.low, 0.0, "Vertex chord extent low"); @@ -74,7 +75,6 @@ function countPointsInHull(hull: ConvexPolygon2d, points: Point2d[]): number { } describe("ConvexPolygon2d", () => { - it("ConvexHullQueries", () => { const ck = new Checker(); const points: Point2d[] = [ @@ -127,7 +127,6 @@ describe("ConvexPolygon2d", () => { range = hull.clipRay(rayC1M); ck.testFalse(range.isNull, "Clip mixed segment"); ck.testCoordinate(range.length(), pointA.distance(pointB), "Clipped segment length"); - } // Construct known exterior rays @@ -248,7 +247,11 @@ describe("ConvexPolygon2d", () => { ck.testCoordinate(offsetDistance1, detail.a, "hull2 has expected offsetDistance1 from hull1"); } const allGeometry: GeometryQuery[] = []; - GeometryCoreTestIO.captureCloneGeometry(allGeometry, [GrowableXYZArray.create(hull.points), GrowableXYZArray.create(hull1.points), GrowableXYZArray.create(hull2.points)]); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, [ + GrowableXYZArray.create(hull.points), + GrowableXYZArray.create(hull1.points), + GrowableXYZArray.create(hull2.points), + ]); GeometryCoreTestIO.saveGeometry(allGeometry, "ConvexPolygon2d", "OffsetInPlace"); expect(ck.getNumErrors()).toBe(0); diff --git a/core/geometry/src/test/bspline/InterpolationCurve3d.test.ts b/core/geometry/src/test/bspline/InterpolationCurve3d.test.ts index 19cdb04c50ee..9e4cdd05c130 100644 --- a/core/geometry/src/test/bspline/InterpolationCurve3d.test.ts +++ b/core/geometry/src/test/bspline/InterpolationCurve3d.test.ts @@ -23,39 +23,137 @@ describe("InterpolationCurve3d", () => { const circlePoints = Sample.createUnitCircle(8); for (const pt of circlePoints) { pt.y *= 1.4; } // perturb const arcPoints = Sample.createArcStrokes(3, Point3d.create(0, 0, 0), 1.0, Angle.createDegrees(-20.0), Angle.createDegrees(200.0), false); - for (const pt of arcPoints) { pt.y *= 1.5; } // perturb + for (const pt of arcPoints) { pt.y *= 1.5; } // perturb const startTan = Vector3d.create(1, 1, 0); const endTan = Vector3d.create(1, -1, 0); let x0 = 0; const delta = 3.0 * circleRadius; const y0 = 0; let count = 0; - for (const options of [ // we don't test input fitParams since they are not preserved in roundtrip: DGN ignores them! - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 0, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 0, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 1, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 1, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 0, isChordLenTangents: 0, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 0, isChordLenTangents: 0, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 0, isChordLenTangents: 1, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 0, isChordLenTangents: 1, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 1, isChordLenTangents: 0, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 1, isChordLenTangents: 0, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 1, isChordLenTangents: 1, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, isColinearTangents: 1, isChordLenTangents: 1, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 0, isChordLenTangents: 0, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 0, isChordLenTangents: 0, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 0, isChordLenTangents: 1, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 0, isChordLenTangents: 1, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 1, isChordLenTangents: 0, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 1, isChordLenTangents: 0, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 1, isChordLenTangents: 1, isNaturalTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, endTangent: endTan, isColinearTangents: 1, isChordLenTangents: 1, isNaturalTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, endTangent: endTan, isChordLenTangents: 0 }), - InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, endTangent: endTan, isChordLenTangents: 1 }), - InterpolationCurve3dOptions.create({ fitPoints: circlePoints, closed: true, isChordLenKnots: 0 }), // the only interpolant with uniform knots - InterpolationCurve3dOptions.create({ fitPoints: circlePoints, closed: true, isChordLenKnots: 1 }), - ]) { + for ( + const options of [ // we don't test input fitParams since they are not preserved in roundtrip: DGN ignores them! + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 0, isNaturalTangents: 0 }), + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 0, isNaturalTangents: 1 }), + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 1, isNaturalTangents: 0 }), + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, isColinearTangents: 1, isNaturalTangents: 1 }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 0, + isChordLenTangents: 0, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 0, + isChordLenTangents: 0, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 0, + isChordLenTangents: 1, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 0, + isChordLenTangents: 1, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 1, + isChordLenTangents: 0, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 1, + isChordLenTangents: 0, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 1, + isChordLenTangents: 1, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + startTangent: startTan, + isColinearTangents: 1, + isChordLenTangents: 1, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 0, + isChordLenTangents: 0, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 0, + isChordLenTangents: 0, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 0, + isChordLenTangents: 1, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 0, + isChordLenTangents: 1, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 1, + isChordLenTangents: 0, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 1, + isChordLenTangents: 0, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 1, + isChordLenTangents: 1, + isNaturalTangents: 0, + }), + InterpolationCurve3dOptions.create({ + fitPoints: arcPoints, + endTangent: endTan, + isColinearTangents: 1, + isChordLenTangents: 1, + isNaturalTangents: 1, + }), + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, endTangent: endTan, isChordLenTangents: 0 }), + InterpolationCurve3dOptions.create({ fitPoints: arcPoints, startTangent: startTan, endTangent: endTan, isChordLenTangents: 1 }), + InterpolationCurve3dOptions.create({ fitPoints: circlePoints, closed: true, isChordLenKnots: 0 }), // the only interpolant with uniform knots + InterpolationCurve3dOptions.create({ fitPoints: circlePoints, closed: true, isChordLenKnots: 1 }), + ] + ) { if (noisy) GeometryCoreTestIO.consoleLog(`InterpolationCurve index ${count}`); count++; @@ -74,10 +172,17 @@ describe("InterpolationCurve3d", () => { Point3d.create(53.44488806143417, -28.649852653892122, 1.0000000000000036), Point3d.create(52.155105205956495, -31.11087513966227, 1.000000000000007), Point3d.create(51.81089204818833, -31.38045503480483, 1.000000000000007), - Point3d.create(51.616695380910535, -31.499726679972767, 1.000000000000007)]; + Point3d.create(51.616695380910535, -31.499726679972767, 1.000000000000007), + ]; const startTan = Vector3d.create(0, -1, 0); const endTan = Vector3d.create(1, 0, 0); - const options = InterpolationCurve3dOptions.create({ fitPoints: points, startTangent: startTan, endTangent: endTan, isChordLenKnots: 1, isColinearTangents: 1 }); + const options = InterpolationCurve3dOptions.create({ + fitPoints: points, + startTangent: startTan, + endTangent: endTan, + isChordLenKnots: 1, + isColinearTangents: 1, + }); testInterpolationCurveConstruction(ck, allGeometry, options); GeometryCoreTestIO.saveGeometry(allGeometry, "InterpolationCurve3d", "BrienCurve"); expect(ck.getNumErrors()).toBe(0); @@ -117,10 +222,16 @@ describe("InterpolationCurve3d", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "InterpolationCurve3d", "ExercisePointSpacing"); expect(ck.getNumErrors()).toBe(0); }); - }); -function testInterpolationCurveConstruction(ck: Checker, allGeometry: GeometryQuery[], options: InterpolationCurve3dOptions, x0: number = 0, y0: number = 0, delta: number = 0) { +function testInterpolationCurveConstruction( + ck: Checker, + allGeometry: GeometryQuery[], + options: InterpolationCurve3dOptions, + x0: number = 0, + y0: number = 0, + delta: number = 0, +) { const curve = InterpolationCurve3d.create(options); if (ck.testType(curve, InterpolationCurve3d, `Expect interpolation curve for options ${JSON.stringify(options)}`)) { if (ck.testType(curve.options, InterpolationCurve3dOptions)) { @@ -149,19 +260,18 @@ function testInterpolationCurveConstruction(ck: Checker, allGeometry: GeometryQu } const ls = LineString3d.create(); curve.proxyCurve.emitStrokes(ls); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, ls, x0, y2, 0); // top row is stroked proxy curve - GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve.proxyCurve, x0, y1, 0); // middle row is MSBsplineCurve proxy + GeometryCoreTestIO.captureCloneGeometry(allGeometry, ls, x0, y2, 0); // top row is stroked proxy curve + GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve.proxyCurve, x0, y1, 0); // middle row is MSBsplineCurve proxy GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve.options.fitPoints, x0, y1, 0); // ... and fit points - GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve, x0, y0, 0); // bottom row is MSInterpolationCurve + GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve, x0, y0, 0); // bottom row is MSInterpolationCurve testGeometryQueryRoundTrip(ck, curve); } } /** push points interpolated at fractions (index0/count)<= i <= (index1/count) * Note that the range is INCLUSIVE -*/ -function pushInterpolatedInteriorPoints(points: Point3d[], point0: Point3d, point1: Point3d, - index0: number, index1: number, count: number) { + */ +function pushInterpolatedInteriorPoints(points: Point3d[], point0: Point3d, point1: Point3d, index0: number, index1: number, count: number) { for (let i = index0; i <= index1; i++) { points.push(point0.interpolate(i / count, point1)); } diff --git a/core/geometry/src/test/clipping/AlternatingConvexClipTree.test.ts b/core/geometry/src/test/clipping/AlternatingConvexClipTree.test.ts index 3fd9036da0ee..32faaf192c63 100644 --- a/core/geometry/src/test/clipping/AlternatingConvexClipTree.test.ts +++ b/core/geometry/src/test/clipping/AlternatingConvexClipTree.test.ts @@ -46,7 +46,10 @@ function saveTree(root: AlternatingCCTreeNode, shiftX: number = 0, shiftY: numbe Checker.saveTransformedLineString(root.points); else { const centroid = Point3dArray.centroid(root.points); - const transform = Transform.createFixedPointAndMatrix(centroid, Matrix3d.createScale(scaleAroundCentroidFactor, scaleAroundCentroidFactor, scaleAroundCentroidFactor)); + const transform = Transform.createFixedPointAndMatrix( + centroid, + Matrix3d.createScale(scaleAroundCentroidFactor, scaleAroundCentroidFactor, scaleAroundCentroidFactor), + ); const scaledPoints = transform.multiplyPoint3dArray(root.points); scaledPoints.push(scaledPoints[0].clone()); Checker.saveTransformedLineString(scaledPoints); @@ -127,7 +130,6 @@ function testClipper(points: Point3d[], root: AlternatingCCTreeNode, outputLevel } describe("RecursiveClipSets", () => { - it("Test1", () => { const ck = new Checker(); for (const numPoints of [5, 8, 12, 15, 23, 37, 67]) { @@ -169,11 +171,14 @@ describe("RecursiveClipSets", () => { it("Test2", () => { const ck = new Checker(); for (const perpendicularFactor of [-1.0, 1.0]) { - for (const generatorFunction of [ - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor), + ] + ) { const shifterA = new SaveAndRestoreCheckTransform(0, 20, 0); for (let numRecursion = 0; numRecursion < 4; numRecursion++) { const shifterB = new SaveAndRestoreCheckTransform(10, 0, 0); @@ -216,7 +221,6 @@ describe("RecursiveClipSets", () => { Point3d.create(1, -2, 0), Point3d.create(2, -1, 0), - // Point3d.create(5, 0, 0), ]; @@ -247,8 +251,10 @@ describe("RecursiveClipSets", () => { x0 += 100; for (const degrees of [0, 45, 90, 180, 270]) { x0 += 100; - const transform = Transform.createFixedPointAndMatrix(Point3d.create(0, 0), - Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); const rotatedPoints = transform.multiplyPoint3dArray(pointsA); testHullAndInlets(rotatedPoints, x0, 10); } @@ -281,13 +287,16 @@ describe("RecursiveClipSets", () => { const linesToClip: Point3d[] = []; const baseShift = Vector3d.create(-0.1, -0.1, 0); for (const perpendicularFactor of [-1.0, 1.0]) { - for (const generatorFunction of [ - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.nonConvexQuadSimpleFractal(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.nonConvexQuadSimpleFractal(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor), + ] + ) { const shifterA = new SaveAndRestoreCheckTransform(50, 0, 0); for (const depth of [0, 1, 2]) { const shifterB = new SaveAndRestoreCheckTransform(5, 0, 0); @@ -365,7 +374,8 @@ describe("RecursiveClipSets", () => { Point3d.create(-0.3, 0.1), Point3d.create(0, 0.8), Point3d.create(0.5, 1.3), - ]); + ], + ); Checker.saveTransformed(linestring); Checker.shift(0, 4, 0); Checker.saveTransformedLineString(polygon); @@ -375,7 +385,8 @@ describe("RecursiveClipSets", () => { Checker.saveTransformedLineString(polygon); const segmentB = LineSegment3d.create( Point3d.create(1, 0.3), - Point3d.create(1.2, 0.8)); + Point3d.create(1.2, 0.8), + ); Checker.saveTransformed(segmentB); Checker.shift(0, 4, 0); Checker.saveTransformedLineString(polygon); @@ -396,7 +407,14 @@ describe("RecursiveClipSets", () => { it("PolygonClipA", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const polygon = [Point3d.create(0, 0), Point3d.create(4, 0), Point3d.create(4, 2), Point3d.create(2, 2), Point3d.create(2, 3), Point3d.create(0, 4)]; + const polygon = [ + Point3d.create(0, 0), + Point3d.create(4, 0), + Point3d.create(4, 2), + Point3d.create(2, 2), + Point3d.create(2, 3), + Point3d.create(0, 4), + ]; const root = AlternatingCCTreeNode.createTreeForPolygon(polygon); let x0 = 0; const dx = 10.0; @@ -437,13 +455,16 @@ describe("RecursiveClipSets", () => { for (const polygonUV of [polygonUVB, polygonUVA]) { for (const perpendicularFactor of [-1.0, 1.0]) { const y0 = 0; - for (const generatorFunction of [ - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.nonConvexQuadSimpleFractal(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), - (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.nonConvexQuadSimpleFractal(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(numRecursion, _perpendicularFactor), + (numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(numRecursion, _perpendicularFactor), + ] + ) { for (const depth of [0, 1, 2]) { const polygon = generatorFunction(depth, perpendicularFactor); const range = Range3d.createArray(polygon); diff --git a/core/geometry/src/test/clipping/ClipNode.test.ts b/core/geometry/src/test/clipping/ClipNode.test.ts index 1b4d610b3862..904f8ad7f71f 100644 --- a/core/geometry/src/test/clipping/ClipNode.test.ts +++ b/core/geometry/src/test/clipping/ClipNode.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BooleanClipFactory } from "../../clipping/BooleanClipFactory"; import { BooleanClipNode } from "../../clipping/BooleanClipNode"; import { ClipPlane } from "../../clipping/ClipPlane"; @@ -16,19 +16,18 @@ import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; import { Loop } from "../../curve/Loop"; +import { RegionBinaryOpType, RegionOps } from "../../curve/RegionOps"; import { Geometry } from "../../Geometry"; import { AngleSweep } from "../../geometry3d/AngleSweep"; +import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; +import { GrowableXYZArrayCache } from "../../geometry3d/ReusableObjectCache"; import { Sample } from "../../serialization/GeometrySamples"; +import { IModelJson } from "../../serialization/IModelJsonSchema"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { IModelJson } from "../../serialization/IModelJsonSchema"; -import { RegionBinaryOpType, RegionOps } from "../../curve/RegionOps"; -import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; -import { GrowableXYZArrayCache } from "../../geometry3d/ReusableObjectCache"; /** - * * @param origin * @param vectorA * @param vectorB @@ -43,7 +42,6 @@ function makePanel(origin: Point3d, vectorA: Vector3d, a0: number, a1: number, v // cspell:word NXOR describe("ClipNodes", () => { - it("ClipManyBooleans", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -67,7 +65,13 @@ describe("ClipNodes", () => { const x0 = 0; let y0 = 0; let z0 = 0; - const points = [Point3d.create(-1, -1, 0), Point3d.create(2, -1, 0), Point3d.create(2, 2, 0), Point3d.create(-1, 2, 0), Point3d.create(-1, -1, 0)]; + const points = [ + Point3d.create(-1, -1, 0), + Point3d.create(2, -1, 0), + Point3d.create(2, 2, 0), + Point3d.create(-1, 2, 0), + Point3d.create(-1, -1, 0), + ]; const segments = []; for (let i = 0; i + 1 < points.length; i++) { const segment = LineSegment3d.create(points[i], points[i + 1]); @@ -94,10 +98,18 @@ describe("ClipNodes", () => { const arc = Arc3d.createXY(sharedOrigin, radius, AngleSweep.createStartSweepDegrees(startDegrees, sweepDegrees)); arcs.push(arc); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc, x0, y0, z0); - const arc1 = Arc3d.createXY(sharedOrigin, radius + radiusStep * 0.25, AngleSweep.createStartSweepDegrees(startDegrees + sweepDegrees, -sweepDegrees)); + const arc1 = Arc3d.createXY( + sharedOrigin, + radius + radiusStep * 0.25, + AngleSweep.createStartSweepDegrees(startDegrees + sweepDegrees, -sweepDegrees), + ); arcs.push(arc1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc1, x0, y0, z0); - const arc2 = Arc3d.createXY(sharedOrigin, radius + radiusStep * 0.5, AngleSweep.createStartSweepDegrees(startDegrees + sweepDegrees - 360, -sweepDegrees)); + const arc2 = Arc3d.createXY( + sharedOrigin, + radius + radiusStep * 0.5, + AngleSweep.createStartSweepDegrees(startDegrees + sweepDegrees - 360, -sweepDegrees), + ); arcs.push(arc2); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc2, x0, y0, z0); const arc3 = Arc3d.createXY(sharedOrigin, radius + radiusStep * 0.75, AngleSweep.createStartSweepDegrees(startDegrees - 360, sweepDegrees)); @@ -138,40 +150,36 @@ describe("ClipNodes", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, wallY, x0, y0, z0); for (const segment of segments) { - clipper.announceClippedSegmentIntervals(0, 1, segment.startPoint(), segment.endPoint(), - (a0: number, a1: number) => { - const midPoint = segment.fractionToPoint(Geometry.interpolate(a0, 0.5, a1)); - if (!ck.testTrue(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) + clipper.announceClippedSegmentIntervals(0, 1, segment.startPoint(), segment.endPoint(), (a0: number, a1: number) => { + const midPoint = segment.fractionToPoint(Geometry.interpolate(a0, 0.5, a1)); + if (!ck.testTrue(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) + clipper.isPointOnOrInside(midPoint); + if (clipper instanceof BooleanClipNode) { + clipper.toggleResult(); + if (!ck.testFalse(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) clipper.isPointOnOrInside(midPoint); - if (clipper instanceof BooleanClipNode) { - clipper.toggleResult(); - if (!ck.testFalse(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) - clipper.isPointOnOrInside(midPoint); - clipper.toggleResult(); - } - GeometryCoreTestIO.captureGeometry(allGeometry, segment.clonePartialCurve(a0, a1), x0, y0, z0); - }); + clipper.toggleResult(); + } + GeometryCoreTestIO.captureGeometry(allGeometry, segment.clonePartialCurve(a0, a1), x0, y0, z0); + }); } for (const arc of arcs) { - clipper.announceClippedArcIntervals(arc, - (a0: number, a1: number) => { - const midPoint = arc.fractionToPoint(Geometry.interpolate(a0, 0.5, a1)); - if (!ck.testTrue(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) - clipper.isPointOnOrInside(midPoint); - GeometryCoreTestIO.captureGeometry(allGeometry, arc.clonePartialCurve(a0, a1), x0, y0, z0); - }); + clipper.announceClippedArcIntervals(arc, (a0: number, a1: number) => { + const midPoint = arc.fractionToPoint(Geometry.interpolate(a0, 0.5, a1)); + if (!ck.testTrue(clipper.isPointOnOrInside(midPoint), "clipped midpoint", midPoint, clipperName.get(clipper))) + clipper.isPointOnOrInside(midPoint); + GeometryCoreTestIO.captureGeometry(allGeometry, arc.clonePartialCurve(a0, a1), x0, y0, z0); + }); } - } z0 = 0; y0 += 100; for (const clipper of allClippers) { z0 += 4; for (const segment of segments) { - clipper.announceClippedSegmentIntervals(0, 1, segment.startPoint(), segment.endPoint(), - (a0: number, a1: number) => { - GeometryCoreTestIO.captureGeometry(allGeometry, segment.clonePartialCurve(a0, a1), x0, y0, z0 + 0.1); - }); + clipper.announceClippedSegmentIntervals(0, 1, segment.startPoint(), segment.endPoint(), (a0: number, a1: number) => { + GeometryCoreTestIO.captureGeometry(allGeometry, segment.clonePartialCurve(a0, a1), x0, y0, z0 + 0.1); + }); } if (clipper.appendPolygonClip) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, wallX, x0, y0, z0); @@ -198,7 +206,13 @@ describe("ClipNodes", () => { const captureClip = (a0: number, a1: number, cp: CurvePrimitive) => { GeometryCoreTestIO.captureGeometry(allGeometry, cp.clonePartialCurve(a0, a1), x0, yOut); }; - const unitBoxPoints = [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 0)]; + const unitBoxPoints = [ + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 0), + ]; const clipperA = createTranslatedClipperUnion(allGeometry, 8, unitBoxPoints, Point3d.create(0, 0, 0), Point3d.create(20, 8, 0), 1.0, 7.0, x0, y0); const ls = LineString3d.create(Sample.createBidirectionalSawtooth(Point3d.create(-1, 0.5, 0), 3, 2, 5, 3, 3, 7, 1, 2, -1, 2)); ls.announceClipIntervals(clipperA, captureClip); @@ -210,7 +224,6 @@ describe("ClipNodes", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "ClipNode", "ClipManyBoxes"); expect(ck.getNumErrors()).toBe(0); }); - }); function createTranslatedClipper(origin: Point3d, polygonPoints: Point3d[], scale: number): { clipper: Clipper, points: Point3d[] } { @@ -221,7 +234,17 @@ function createTranslatedClipper(origin: Point3d, polygonPoints: Point3d[], scal return { clipper: convexClip, points: myPoints }; } -function createTranslatedClipperUnion(allGeometry: GeometryQuery[], count: number, points: Point3d[], origin0: Point3d, origin1: Point3d, scale0: number, scale1: number, x0: number, y0: number): Clipper { +function createTranslatedClipperUnion( + allGeometry: GeometryQuery[], + count: number, + points: Point3d[], + origin0: Point3d, + origin1: Point3d, + scale0: number, + scale1: number, + x0: number, + y0: number, +): Clipper { const clippers = []; for (let i = 0; i < count; i++) { const f = i / (count - 1); @@ -238,20 +261,27 @@ it("MichaelBCover", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const shape0 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/base_shape.imjs", "utf8"))); + "./src/test/data/clipping/base_shape.imjs", + "utf8", + ))); const shape1 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/shape1.imjs", "utf8"))); + "./src/test/data/clipping/shape1.imjs", + "utf8", + ))); const shape2 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/shape2.imjs", "utf8"))); + "./src/test/data/clipping/shape2.imjs", + "utf8", + ))); const shape3 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/shape3.imjs", "utf8"))); + "./src/test/data/clipping/shape3.imjs", + "utf8", + ))); // we expect 3 loops let x0 = -10; const dy = 100; const dx = 100.0; const offset = 1.0; if (shape0 instanceof Loop && shape1 instanceof Loop && shape2 instanceof Loop && shape3 instanceof Loop) { - const area = RegionOps.computeXYArea(shape0)!; const smallShape0 = RegionOps.constructCurveXYOffset(shape0, area > 0 ? offset : -offset); const smallArea = RegionOps.computeXYArea(smallShape0 as Loop)!; @@ -337,11 +367,10 @@ it("MichaelBCover", () => { } if (currentFragments.length === 0) GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYXY(x0, yy, x0 + dx, yy + dy)); -*/ + */ x0 += 100.0; } } GeometryCoreTestIO.saveGeometry(allGeometry, "clipping", "MichaelBCover"); expect(ck.getNumErrors()).toBe(0); - }); diff --git a/core/geometry/src/test/clipping/ClipPlanes.test.ts b/core/geometry/src/test/clipping/ClipPlanes.test.ts index c02a609007dc..6d6dd77bce25 100644 --- a/core/geometry/src/test/clipping/ClipPlanes.test.ts +++ b/core/geometry/src/test/clipping/ClipPlanes.test.ts @@ -76,7 +76,7 @@ function testConvexClipXY(x0: number, y0: number, ux: number, uy: number, xyz: P const plane1 = Plane3dByOriginAndUnitNormal.create(Point3d.create(x0, y0, 0.0), Vector3d.create(-ux, -uy, 0.0)); const clip0 = ClipPlane.createPlane(plane0!); const clip1 = ClipPlane.createPlane(plane1!); - if (clip0 && clip1) { // Since constructor could return undefined + if (clip0 && clip1) { // Since constructor could return undefined const xyz0: Point3d[] = xyz.slice(0); const xyz1: Point3d[] = xyz.slice(0); const normal: Vector3d = PolygonOps.areaNormal(xyz); @@ -93,14 +93,12 @@ function testConvexClipXY(x0: number, y0: number, ux: number, uy: number, xyz: P } describe("ClipPlane", () => { - // --------------------------------------------------------------------------------------------------- it("BoundedSegmentIntersection", () => { const ck = new Checker(); // XY plane with upward (+z) facing normal - const clip = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), - Point3d.create(0, 0, 0), false, false); + const clip = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), Point3d.create(0, 0, 0), false, false); if (clip) { // Should never fail // Move segment through plane, testing fractional value each time @@ -132,8 +130,7 @@ describe("ClipPlane", () => { it("Offset", () => { const ck = new Checker(); // XY plane with upward (+z) facing normal - const clip = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), - Point3d.create(0, 0, 0), false, false)!; + const clip = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), Point3d.create(0, 0, 0), false, false)!; const h0 = 5.0; const testPoint = Point3d.create(2, 3, h0); ck.testCoordinate(h0, clip.dotProductPlaneNormalPoint(testPoint)); @@ -161,15 +158,14 @@ describe("ClipPlane", () => { ck.testCoordinate(clipPlane.altitude(pointA), plane.altitude(pointA)); ck.testCoordinate(clipPlane.altitude(pointB), plane.altitude(pointB)); // announced fractions are strictly increasing pair within what we send as start end fractions, so relation to ends is known ... - clipPlane.announceClippedSegmentIntervals(0.2, 0.9, pointA, pointB, - (f0: number, f1: number) => { - const segmentPoint = pointA.interpolate((f0 + f1) * 0.5, pointB); - ck.testTrue(clipPlane.isPointInside(segmentPoint)); - const point0 = pointA.interpolate(f0, pointB); - const point1 = pointA.interpolate(f1, pointB); - ck.testBoolean(clipPlane.isPointInside(pointA), clipPlane.isPointInside(pointA.interpolate(0.5, point0))); - ck.testBoolean(clipPlane.isPointInside(pointB), clipPlane.isPointInside(point1.interpolate(0.5, pointB))); - }); + clipPlane.announceClippedSegmentIntervals(0.2, 0.9, pointA, pointB, (f0: number, f1: number) => { + const segmentPoint = pointA.interpolate((f0 + f1) * 0.5, pointB); + ck.testTrue(clipPlane.isPointInside(segmentPoint)); + const point0 = pointA.interpolate(f0, pointB); + const point1 = pointA.interpolate(f1, pointB); + ck.testBoolean(clipPlane.isPointInside(pointA), clipPlane.isPointInside(pointA.interpolate(0.5, point0))); + ck.testBoolean(clipPlane.isPointInside(pointB), clipPlane.isPointInside(point1.interpolate(0.5, pointB))); + }); ck.checkpoint("Offset"); expect(ck.getNumErrors()).toBe(0); @@ -198,7 +194,8 @@ describe("ClipPlane", () => { Point3d.create(0, 0, 0), Point3d.create(0, 1, 0), Vector3d.create(0, 0, 1), - Angle.createDegrees(45))!; + Angle.createDegrees(45), + )!; ck.testTrue(tiltPlane.isPointInside(Point3d.create(1, 0, 0))); ck.testFalse(tiltPlane.isPointInside(Point3d.create(1, 0, 10))); expect(ck.getNumErrors()).toBe(0); @@ -216,7 +213,6 @@ describe("ClipPlane", () => { const crossings: Point3d[] = []; if (clip) { // Should never fail - for (let i = 2; i < 15; i++) { let z: number; const rand = Math.random(); @@ -224,8 +220,14 @@ describe("ClipPlane", () => { let didCross = false; let toReduce = false; if (rand >= .5) { z = i; } else { z = -i; } - if (z * lastSign < 0) { numExpectedCrossings++; didCross = true; } - if (z * array[0].z < 0) { numExpectedCrossings++; toReduce = true; } + if (z * lastSign < 0) { + numExpectedCrossings++; + didCross = true; + } + if (z * array[0].z < 0) { + numExpectedCrossings++; + toReduce = true; + } lastSign = z; array.push(Point3d.create(x, 0, z)); @@ -243,7 +245,7 @@ describe("ClipPlane", () => { if (didCross) { const m = (z - array[array.length - 2].z) / (x - array[array.length - 2].x); const b = z - m * x; - const xCross = - b / m; + const xCross = -b / m; ck.testCoordinate(xCross, crossings[crossings.length - 1].x, "Expected and actual x location of crossing match"); } else { const subArray: Point3d[] = array.slice(array.length - 2); @@ -355,7 +357,6 @@ describe("ConvexClipPlaneSet", () => { }); describe("ClipPlaneSet", () => { - it("GetRayIntersections", () => { const ck = new Checker(); const sideLength = 1; @@ -386,7 +387,7 @@ describe("ClipPlaneSet", () => { // Ray origins below box, inside, and above box for (let i = -0.5; i < 2; i++) { // Rotate rays 360 degrees around x and y axis - for (let theta = 0; theta < 2 * Math.PI; theta += (Math.PI / 4)) { + for (let theta = 0; theta < 2 * Math.PI; theta += Math.PI / 4) { const xAlignedRay = Ray3d.create(Point3d.create(xyMiddleOfCube, xyMiddleOfCube, i), Vector3d.create(Math.cos(theta), 0, Math.sin(theta))); const yAlignedRay = Ray3d.create(Point3d.create(xyMiddleOfCube, xyMiddleOfCube, i), Vector3d.create(0, Math.cos(theta), Math.sin(theta))); const xAlignedRange = Range1d.createNull(); @@ -426,8 +427,8 @@ describe("ClipPlaneSet", () => { const edgePoint01 = triangle[0].interpolate(0.4, triangle[1]); const edgePoint12 = triangle[1].interpolate(0.4, triangle[2]); - const linePointA = edgePoint01.interpolate(0.1, edgePoint12); // a little inside along edge01 - const linePointB = edgePoint01.interpolate(0.5, edgePoint12); // a little inside along edge01 + const linePointA = edgePoint01.interpolate(0.1, edgePoint12); // a little inside along edge01 + const linePointB = edgePoint01.interpolate(0.5, edgePoint12); // a little inside along edge01 const sweepDirection = Vector3d.create(0, 0, 1); convexSetA.reloadSweptPolygon(triangle, sweepDirection, 1); @@ -436,11 +437,10 @@ describe("ClipPlaneSet", () => { convexSetA1.reloadSweptPolygon(triangleWithDuplicate, sweepDirection, 1); convexSetB.reloadSweptPolygon(triangle, sweepDirection, -1); convexSet0.reloadSweptPolygon(triangle, sweepDirection, 0); - convexSetA.clipUnboundedSegment(linePointA, linePointB, - (fA: number, fB: number) => { - ck.testPoint3d(edgePoint01, linePointA.interpolate(fA, linePointB), fA, "unboundedLine clip pointA"); - ck.testPoint3d(edgePoint12, linePointA.interpolate(fB, linePointB), fB, "unboundedLine clip pointB"); - }); + convexSetA.clipUnboundedSegment(linePointA, linePointB, (fA: number, fB: number) => { + ck.testPoint3d(edgePoint01, linePointA.interpolate(fA, linePointB), fA, "unboundedLine clip pointA"); + ck.testPoint3d(edgePoint12, linePointA.interpolate(fB, linePointB), fB, "unboundedLine clip pointB"); + }); const tolerance = 1.0e-10; const values: number[] = [-0.5, 0.3, 0.5, 0.8, 1.1]; for (const u of values) { @@ -481,7 +481,7 @@ describe("ClipPlaneSet", () => { const convexSet = ConvexClipPlaneSet.createXYBox(0, 0, 1, 1); const clipZ0 = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), Point3d.create(0, 0, 0), false, false); const clipZ1 = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, -1), Point3d.create(0, 0, 1), false, false); - if (clipZ0 && clipZ1) { // Should never fail + if (clipZ0 && clipZ1) { // Should never fail convexSet.addPlaneToConvexSet(clipZ0); convexSet.addPlaneToConvexSet(clipZ1); } @@ -560,7 +560,7 @@ describe("ClipPlaneSet", () => { const convexSet1 = ConvexClipPlaneSet.createXYBox(0, 0, 1, 1); const clipZ0 = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, 1), Point3d.create(0, 0, 0), false, true); const clipZ1 = ClipPlane.createNormalAndPoint(Vector3d.create(0, 0, -1), Point3d.create(0, 0, 1), false, true); - if (clipZ0 && clipZ1) { // Should never fail + if (clipZ0 && clipZ1) { // Should never fail convexSet1.addPlaneToConvexSet(clipZ0); convexSet1.addPlaneToConvexSet(clipZ1); } @@ -576,8 +576,16 @@ describe("ClipPlaneSet", () => { ck.testExactNumber(set.classifyPointContainment(array, false), ClipPlaneContainment.StronglyInside, "All points inside one region"); ck.testExactNumber(set.classifyPointContainment(array, true), ClipPlaneContainment.StronglyInside, "All points inside one region"); array.push(Point3d.create(0, 0, 0)); - ck.testExactNumber(set.classifyPointContainment(array, true), ClipPlaneContainment.Ambiguous, "All points inside one region with exception of one on border"); - ck.testExactNumber(set.classifyPointContainment(array, false), ClipPlaneContainment.Ambiguous, "All points inside one region with exception of one on border"); + ck.testExactNumber( + set.classifyPointContainment(array, true), + ClipPlaneContainment.Ambiguous, + "All points inside one region with exception of one on border", + ); + ck.testExactNumber( + set.classifyPointContainment(array, false), + ClipPlaneContainment.Ambiguous, + "All points inside one region with exception of one on border", + ); array.pop(); array.push(Point3d.create(0.0000001, 0.0000001, 0.0000001)); ck.testExactNumber(set.classifyPointContainment(array, true), ClipPlaneContainment.StronglyInside, "All points inside one region"); @@ -589,8 +597,16 @@ describe("ClipPlaneSet", () => { Point3d.create(0, 0, 0), ]; - ck.testExactNumber(set.classifyPointContainment(array, false), ClipPlaneContainment.StronglyOutside, "All points outside except for one on border (not counting)"); - ck.testExactNumber(set.classifyPointContainment(array, true), ClipPlaneContainment.StronglyOutside, "All points outside except for one on border (not counting)"); + ck.testExactNumber( + set.classifyPointContainment(array, false), + ClipPlaneContainment.StronglyOutside, + "All points outside except for one on border (not counting)", + ); + ck.testExactNumber( + set.classifyPointContainment(array, true), + ClipPlaneContainment.StronglyOutside, + "All points outside except for one on border (not counting)", + ); ck.checkpoint("ClassifyPointContainment"); expect(ck.getNumErrors()).toBe(0); @@ -634,7 +650,8 @@ function clipMovingCurve( curve: CurvePrimitive, traceCurve: CurvePrimitive, numTrace: number, - announceCurve: AnnounceNumberNumberCurvePrimitive) { + announceCurve: AnnounceNumberNumberCurvePrimitive, +) { for (let i = 0; i + 1 < numTrace; i++) { const shift = traceCurve.fractionToPoint(i / numTrace); const curve1 = curve.cloneTransformed(Transform.createTranslation(shift)) as CurvePrimitive; @@ -652,8 +669,9 @@ describe("ClipPlaneUtilities", () => { for (const low of [1, 4, 9]) intervals.push(Range1d.createXX(low, low + intervalSize)); const cp = LineSegment3d.create(Point3d.create(1, 1, 2), Point3d.create(4, 2, 1)); - ClipUtilities.announceNNC(intervals, cp, - (a: number, b: number, _cp: CurvePrimitive) => { sum += b - a; }); + ClipUtilities.announceNNC(intervals, cp, (a: number, b: number, _cp: CurvePrimitive) => { + sum += b - a; + }); ck.testExactNumber(intervalSize * intervals.length, sum, "summed data from announceNNC"); expect(ck.getNumErrors()).toBe(0); @@ -662,7 +680,8 @@ describe("ClipPlaneUtilities", () => { describe("CurveClips", () => { it("CurvePrimitiveClips", () => { - const ck = new Checker(); expect(ck.getNumErrors()).toBe(0); + const ck = new Checker(); + expect(ck.getNumErrors()).toBe(0); const traceCurve = Arc3d.createXY(Point3d.create(0, 0.2, 0), 1.0); const curves = Sample.createSmoothCurvePrimitives(2.0); const output: GeometryQuery[] = []; @@ -682,37 +701,37 @@ describe("CurveClips", () => { output.push(clipGeometry); output.push(clipGeometry.cloneTransformed(transform0)); output.push(clipGeometry.cloneTransformed(transform1)); - clipMovingCurve(clipper, curve, traceCurve, 5, - (group: number, _index: number, cp: CurvePrimitive) => { - output.push(cp.cloneTransformed(group === 0 ? transform0 : transform1)!); - }); + clipMovingCurve(clipper, curve, traceCurve, 5, (group: number, _index: number, cp: CurvePrimitive) => { + output.push(cp.cloneTransformed(group === 0 ? transform0 : transform1)!); + }); } GeometryCoreTestIO.saveGeometry(output, "ClipPlane", "CurvePrimitiveClips"); expect(ck.getNumErrors()).toBe(0); }); it("PlaneArcClips", () => { - const ck = new Checker(); expect(ck.getNumErrors()).toBe(0); + const ck = new Checker(); + expect(ck.getNumErrors()).toBe(0); const arc = Arc3d.createXY(Point3d.create(0, 0.2, 0), 2.0, AngleSweep.createStartEndDegrees(0, 270.0)); const plane = ClipPlane.createEdgeXY(Point3d.create(3, 1, 0), Point3d.create(3, -10, 0))!; - plane.announceClippedArcIntervals(arc, - (fraction0: number, fraction1: number, _cp: CurvePrimitive) => { - const point0 = arc.fractionToPoint(fraction0); - const point1 = arc.fractionToPoint(Geometry.interpolate(fraction0, 0.5, fraction1)); - const point2 = arc.fractionToPoint(fraction1); - - ck.testTrue(plane.isPointOn(point0), "interval start point is ON"); - ck.testFalse(plane.isPointOn(point1), "interval midpoint is not ON"); - ck.testTrue(plane.isPointOnOrInside(point1), "interval midpoint is IN"); - ck.testTrue(plane.isPointOn(point2), "interval end point is ON"); - }); + plane.announceClippedArcIntervals(arc, (fraction0: number, fraction1: number, _cp: CurvePrimitive) => { + const point0 = arc.fractionToPoint(fraction0); + const point1 = arc.fractionToPoint(Geometry.interpolate(fraction0, 0.5, fraction1)); + const point2 = arc.fractionToPoint(fraction1); + + ck.testTrue(plane.isPointOn(point0), "interval start point is ON"); + ck.testFalse(plane.isPointOn(point1), "interval midpoint is not ON"); + ck.testTrue(plane.isPointOnOrInside(point1), "interval midpoint is IN"); + ck.testTrue(plane.isPointOn(point2), "interval end point is ON"); + }); ck.checkpoint("PlaneArcClips"); expect(ck.getNumErrors()).toBe(0); }); it("PlaneSetArcClips", () => { - const ck = new Checker(); expect(ck.getNumErrors()).toBe(0); + const ck = new Checker(); + expect(ck.getNumErrors()).toBe(0); const arc = Arc3d.createXYEllipse(Point3d.create(0, 0.2, 0), 3.0, 0.5, AngleSweep.createStartEndDegrees(0, 270.0)); const pointA = Point3d.create(-1.5, 1); const pointB = Point3d.create(2, -0.5); @@ -722,11 +741,11 @@ describe("CurveClips", () => { const transform = Transform.createFixedPointAndMatrix( Point3d.create(1, 0.5), - Matrix3d.createRotationAroundVector(Vector3d.create(1, 1, 9), Angle.createDegrees(60))!); + Matrix3d.createRotationAroundVector(Vector3d.create(1, 1, 9), Angle.createDegrees(60))!, + ); const arc1 = arc.clone(); arc1.tryTransformInPlace(transform); for (const clipper of clippers) { - const clipper1 = clipper.clone(); clipper1.transformInPlace(transform); let activeClipper = clipper; @@ -779,15 +798,18 @@ describe("CurveClips", () => { const positiveOctant = ConvexClipPlaneSet.createRange3dPlanes(rangeA, true, false, true, false, true, false); const negativeOctant = positiveOctant.clone(); negativeOctant.negateAllPlanes(); - for (const data of [ - [1, 1, 1, true, false], - [-1, -1, -1, false, true], - [-1, 1, 1, false, false], - [1, -1, 1, false, false], - [-1, 1, -1, false, false], - [-1, -1, 1, false, false], - [-1, 1, -1, false, false], - [-1, 1, -1, false, false]]) { + for ( + const data of [ + [1, 1, 1, true, false], + [-1, -1, -1, false, true], + [-1, 1, 1, false, false], + [1, -1, 1, false, false], + [-1, 1, -1, false, false], + [-1, -1, 1, false, false], + [-1, 1, -1, false, false], + [-1, 1, -1, false, false], + ] + ) { const point = Point3d.create(data[0] as number, data[1] as number, data[2] as number); ck.testBoolean(data[3] as boolean, positiveOctant.isPointInside(point), "unbounded clip planes A"); ck.testBoolean(data[4] as boolean, negativeOctant.isPointInside(point), "unbounded clip planes B"); @@ -804,7 +826,7 @@ describe("CurveClips", () => { const planeB = planeA.cloneNegated(); ck.testTrue(planeA.isPointOn(origin), "origin on plane"); ck.testTrue(planeB.isPointOn(origin), "origin on negated plane"); - for (const x of [-10.0, 10.0]) { // These x values are big enough to be sure we get points far from origin. + for (const x of [-10.0, 10.0]) { // These x values are big enough to be sure we get points far from origin. const point = Point3d.create(x, 5, 3); ck.testBoolean(planeA.isPointInside(point), !planeB.isPointInside(point), "negated plane isPointInside"); ck.testFalse(planeA.isPointOn(point), "off-plane point test"); @@ -822,9 +844,10 @@ describe("CurveClips", () => { const plane = ClipPlane.createNormalAndPoint(Vector3d.create(1, 0, 0), Point3d.create(1, 1, 0))!; const rectangle0 = [ Point3d.create(-1, -1, 0), - Point3d.create(10, - 1, 0), + Point3d.create(10, -1, 0), Point3d.create(10, 2, 0), - Point3d.create(-1, 2, 0)]; + Point3d.create(-1, 2, 0), + ]; const splitA: Point3d[] = []; const splitB: Point3d[] = []; const altitudeRange = Range1d.createNull(); @@ -847,9 +870,10 @@ describe("CurveClips", () => { const convexA = ConvexClipPlaneSet.createRange3dPlanes(range, true, false, true, false, false); const rectangle0 = [ Point3d.create(-1, -1, 0), - Point3d.create(bx, - 1, 0), + Point3d.create(bx, -1, 0), Point3d.create(bx, by, 0), - Point3d.create(-1, by, 0)]; + Point3d.create(-1, by, 0), + ]; // const area0 = PolygonOps.sumTriangleAreas(rectangle0); const splitA = new GrowableXYZArray(); @@ -868,7 +892,8 @@ describe("CurveClips", () => { Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0), - Point3d.create(0, 0, 0)]; + Point3d.create(0, 0, 0), + ]; const area0 = PolygonOps.sumTriangleAreas(triangle0); const rectangle0 = Sample.createRectangle(-2, -1, 2, 2, 0, false); // const rectangle1 = Sample.createRectangle(-2, -1, 2, 2, 1, false); @@ -907,10 +932,13 @@ describe("CurveClips", () => { ck.testExactNumber(ClipStatus.ClipRequired, ClipUtilities.pointSetSingleClipStatus(boundaryB, clipAB, 0.0)); const spreadQ = GrowableXYZArray.create( - [Point3d.create(1, 8), Point3d.create(2, 8)]); + [Point3d.create(1, 8), Point3d.create(2, 8)], + ); ck.testExactNumber(ClipStatus.TrivialReject, ClipUtilities.pointSetSingleClipStatus(spreadQ, clipAB, 0.0)); - ck.testExactNumber(ClipStatus.TrivialAccept, ClipUtilities.pointSetSingleClipStatus(spreadQ, - UnionOfConvexClipPlaneSets.createConvexSets([]), 0.0)); + ck.testExactNumber( + ClipStatus.TrivialAccept, + ClipUtilities.pointSetSingleClipStatus(spreadQ, UnionOfConvexClipPlaneSets.createConvexSets([]), 0.0), + ); ck.checkpoint("QuickClipStatus"); expect(ck.getNumErrors()).toBe(0); }); @@ -964,14 +992,17 @@ describe("CurveClips", () => { const allGeometry: GeometryQuery[] = []; let dy = 0.0; // obviously inside ... - for (const clipPlane of [ - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(1, 0, 0, 0, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0.1)!, - ClipPlane.createNormalAndPointXYZXYZ(-2, 4, 1, 0.3, 0.2, 1.1)!, - ClipPlane.createNormalAndPointXYZXYZ(1, 1, 1.1, 0.3, 0.2, 1.1)!, - ClipPlane.createNormalAndPointXYZXYZ(-2, 6, 3, 0.3, 0.2, 1.1)!, - ClipPlane.createNormalAndPointXYZXYZ(0.2, 0, 1, 0, 0, 0)!]) { + for ( + const clipPlane of [ + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(1, 0, 0, 0, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0.1)!, + ClipPlane.createNormalAndPointXYZXYZ(-2, 4, 1, 0.3, 0.2, 1.1)!, + ClipPlane.createNormalAndPointXYZXYZ(1, 1, 1.1, 0.3, 0.2, 1.1)!, + ClipPlane.createNormalAndPointXYZXYZ(-2, 6, 3, 0.3, 0.2, 1.1)!, + ClipPlane.createNormalAndPointXYZXYZ(0.2, 0, 1, 0, 0, 0)!, + ] + ) { const clipped = clipPlane.intersectRange(range, true); GeometryCoreTestIO.captureRangeEdges(allGeometry, range, 0, dy, 0); if (ck.testPointer(clipped)) { @@ -982,11 +1013,14 @@ describe("CurveClips", () => { } // obviously outside const big = 20.0; - for (const clipPlane of [ - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, big)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 1, 0, 0, big, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(1, 0, 0, big, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(1, 1, 1, big, big, big)!]) { + for ( + const clipPlane of [ + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, big)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 1, 0, 0, big, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(1, 0, 0, big, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(1, 1, 1, big, big, big)!, + ] + ) { const clipped = clipPlane.intersectRange(range, true); ck.testUndefined(clipped, prettyPrint(clipPlane), prettyPrint(range)); } @@ -1074,7 +1108,6 @@ describe("CurveClips", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "ClipPlane", "ClipConvexSetToRange"); expect(ck.getNumErrors()).toBe(0); - }); it("ClipConvexPolygonToRangeCoverage", () => { @@ -1110,7 +1143,6 @@ describe("CurveClips", () => { ck.testUndefined(IndexedXYZCollectionPolygonOps.intersectRangeConvexPolygonInPlace(Range3d.createNull(), polygon), "null range clips to nothing"); GeometryCoreTestIO.saveGeometry(allGeometry, "ClipPlane", "ClipConvexPolygonToRangeCoverage"); expect(ck.getNumErrors()).toBe(0); - }); it("StairwellClipViaSweptPolyline", () => { const ck = new Checker(); @@ -1121,8 +1153,8 @@ describe("CurveClips", () => { const y0 = 0.0; // Outline a rectangle in xz plane at the bottom of the stairwell - const a = 1.0; // stair clearance width. - const b = 2.5; // stair clearance height + const a = 1.0; // stair clearance width. + const b = 2.5; // stair clearance height const baseRectangle = [Point3d.create(0, 0), Point3d.create(a, 0), Point3d.create(a, 0, b), Point3d.create(0, 0, b), Point3d.create(0, 0)]; const sweepVector = Vector3d.create(0, 1, 0.8); // create uncapped sweep @@ -1137,8 +1169,7 @@ describe("CurveClips", () => { PolyfaceClip.clipPolyfaceInsideOutside(target, clipper, clipBuilders); GeometryCoreTestIO.captureCloneGeometry(allGeometry, target, x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, baseRectangle, x0, y0); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineSegment3d.create(baseRectangle[0], baseRectangle[0].plusScaled(sweepVector, 5.0)), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(baseRectangle[0], baseRectangle[0].plusScaled(sweepVector, 5.0)), x0, y0); const clip0 = clipBuilders.claimPolyface(0, false); const clip1 = clipBuilders.claimPolyface(1, true); GeometryCoreTestIO.captureCloneGeometry(allGeometry, clip0, x1, y0); @@ -1146,7 +1177,6 @@ describe("CurveClips", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "clipping", "StairwellClip"); expect(ck.getNumErrors()).toBe(0); - }); it("StairwellClipViaLinearSweep", () => { const ck = new Checker(); @@ -1158,8 +1188,8 @@ describe("CurveClips", () => { let y0 = 0.0; // Outline a rectangle in xz plane at the bottom of the stairwell - const a = 1.0; // stair clearance width. - const b = 2.0; // stair clearance height + const a = 1.0; // stair clearance width. + const b = 2.0; // stair clearance height const baseRectangle = [Point3d.create(0, 0), Point3d.create(a, 0), Point3d.create(a, 0, b), Point3d.create(0, 0, b), Point3d.create(0, 0)]; const sweepVector = Vector3d.create(0, 3, 2.4); for (const capped of [false, true]) { @@ -1182,8 +1212,7 @@ describe("CurveClips", () => { PolyfaceClip.clipPolyfaceInsideOutside(target, clipper, clipBuilders); GeometryCoreTestIO.captureCloneGeometry(allGeometry, target, x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, baseRectangle, x0, y0); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineSegment3d.create(baseRectangle[0], baseRectangle[0].plusScaled(sweepVector, 5.0)), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(baseRectangle[0], baseRectangle[0].plusScaled(sweepVector, 5.0)), x0, y0); const clip0 = clipBuilders.claimPolyface(0, false); const clip1 = clipBuilders.claimPolyface(1, true); GeometryCoreTestIO.captureCloneGeometry(allGeometry, clip0, x1, y0); @@ -1192,9 +1221,7 @@ describe("CurveClips", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "clipping", "StairwellClipViaLinearSweep"); expect(ck.getNumErrors()).toBe(0); - }); - }); /* Tests for various levels of appendPolygonClip implementation */ @@ -1221,7 +1248,6 @@ describe("PolygonClipper", () => { GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(pointA, pointB)); x0 += dx; for (const clipper of [unionBoth, planeAB, planeBA, convexSetAB, convexSetBA, unionAB, unionBoth]) { - const insideFragments: GrowableXYZArray[] = []; const outsideFragments: GrowableXYZArray[] = []; const cache = new GrowableXYZArrayCache(); @@ -1278,27 +1304,19 @@ export class OutputManager { } public drawMinus(xyz: Point3d, radius: number = 0.1) { - GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, - [xyz.plusXYZ(-radius, 0, 0), xyz.plusXYZ(radius, 0, 0)], - this.x0, this.y0, this.z0); + GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, [xyz.plusXYZ(-radius, 0, 0), xyz.plusXYZ(radius, 0, 0)], this.x0, this.y0, this.z0); } public drawPlus(xyz: Point3d, radius: number = 0.1) { - GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, - [xyz.plusXYZ(-radius, 0, 0), xyz.plusXYZ(radius, 0, 0)], - this.x0, this.y0, this.z0); - GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, - [xyz.plusXYZ(0, -radius, 0), xyz.plusXYZ(0, radius, 0)], - this.x0, this.y0, this.z0); + GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, [xyz.plusXYZ(-radius, 0, 0), xyz.plusXYZ(radius, 0, 0)], this.x0, this.y0, this.z0); + GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, [xyz.plusXYZ(0, -radius, 0), xyz.plusXYZ(0, radius, 0)], this.x0, this.y0, this.z0); } public drawLines(xyz: Point3d[]) { - GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, xyz, - this.x0, this.y0, this.z0); + GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, xyz, this.x0, this.y0, this.z0); } public drawCircle(xyz: Point3d, radius: number = 0.1) { - GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, - Arc3d.createXY(xyz, radius)); + GeometryCoreTestIO.captureCloneGeometry(this.allGeometry, Arc3d.createXY(xyz, radius)); } public captureClone(data: GeometryQuery | undefined) { @@ -1316,15 +1334,25 @@ export class OutputManager { this.x0 += dx; this.y0 += dy; } - public setX0(x0: number): number { const a = this.x0; this.x0 = x0; return a; } - public setY0(y0: number): number { const a = this.y0; this.y0 = y0; return a; } - public setZ0(z0: number): number { const a = this.z0; this.z0 = z0; return a; } + public setX0(x0: number): number { + const a = this.x0; + this.x0 = x0; + return a; + } + public setY0(y0: number): number { + const a = this.y0; + this.y0 = y0; + return a; + } + public setZ0(z0: number): number { + const a = this.z0; + this.z0 = z0; + return a; + } public drawGraph(graph: HalfEdgeGraph | undefined) { if (graph) - GeometryCoreTestIO.captureGeometry(this.allGeometry, PolyfaceBuilder.graphToPolyface(graph), - this.x0, this.y0, 0); + GeometryCoreTestIO.captureGeometry(this.allGeometry, PolyfaceBuilder.graphToPolyface(graph), this.x0, this.y0, 0); } - } /** * Create planes with (inward) normal computed as cross product of sweepVector edge vectors. @@ -1355,12 +1383,17 @@ function createSweptConvexClipperForPolygon(points: Point3d[], invisibleBits: bo * * If point counts are different, use the smaller count. * * "interior" edges are marked */ -function createUnionOfConvexClipPlaneSetsBetweenCompatibleLineStringSweeps(pointA: Point3d[], pointB: Point3d[], sweepVector: Vector3d, hideInteriorPlanes: boolean): UnionOfConvexClipPlaneSets { +function createUnionOfConvexClipPlaneSetsBetweenCompatibleLineStringSweeps( + pointA: Point3d[], + pointB: Point3d[], + sweepVector: Vector3d, + hideInteriorPlanes: boolean, +): UnionOfConvexClipPlaneSets { const n = Math.min(pointA.length, pointB.length); const allClippers = UnionOfConvexClipPlaneSets.createEmpty(); for (let i = 0; i + 1 < n; i++) { - const hide0 = (i !== 0); - const hide1 = (i + 1 !== n); + const hide0 = i !== 0; + const hide1 = i + 1 !== n; const pA0 = pointA[i]; const pA1 = pointA[i + 1]; const pB0 = pointB[i]; @@ -1382,7 +1415,7 @@ function createUnionOfConvexClipPlaneSetsBetweenCompatibleLineStringSweeps(point } else { const loopPoints = [pA0, pA1, pB1, pB0]; if (a0 < 0) - loopPoints.reverse(); // reversal preserves 01 sequencing used in visibility check + loopPoints.reverse(); // reversal preserves 01 sequencing used in visibility check allClippers.addConvexSet(createSweptConvexClipperForPolygon(loopPoints, [false, hide1, false, hide0], sweepVector)); } } @@ -1393,9 +1426,9 @@ describe("ClipPlaneDocs", () => { it("Quadrants", () => { const ck = new Checker(); const out = new OutputManager(); - const a = 5.0; // clipped polygon extent + const a = 5.0; // clipped polygon extent const b = 7.0 * a; // step between origins of successive snips - const c = 3.0; // length of arrows for planes + const c = 3.0; // length of arrows for planes const c1 = c / 10.0; const axisLength = 2.0 * a; const axisArrowLength = 1.0; @@ -1419,13 +1452,14 @@ describe("ClipPlaneDocs", () => { out.drawAxes(axisLength, axisArrowLength); const ax = 2 * Geometry.split3WaySign(xSign, -c, c, c); const cx = Geometry.split3WaySign(xSign, -c1, c1, c1); - const xPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(cx, ay, 0, xSign, 0, 0); // undefined is expected in 0 case! - const yPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(ax, cy, 0, 0, ySign, 0); // undefined is expected in 0 case! + const xPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(cx, ay, 0, xSign, 0, 0); // undefined is expected in 0 case! + const yPlane = Plane3dByOriginAndUnitNormal.createXYZUVW(ax, cy, 0, 0, ySign, 0); // undefined is expected in 0 case! const clipper = ConvexClipPlaneSet.createEmpty(); applyConditionalPlane1(clipper, xPlane); applyConditionalPlane1(clipper, yPlane); - const polygonToClip = GrowableXYZArray.create(Sample.createArcStrokes(3, Point3d.create(0, 0), a, Angle.createDegrees(15), - Angle.createDegrees(375), true, -0.04)); + const polygonToClip = GrowableXYZArray.create( + Sample.createArcStrokes(3, Point3d.create(0, 0), a, Angle.createDegrees(15), Angle.createDegrees(375), true, -0.04), + ); clipper.clipConvexPolygonInPlace(polygonToClip, work); out.drawPolygon(polygonToClip, true); out.shift(0, b); @@ -1460,7 +1494,8 @@ describe("ClipPlaneDocs", () => { const planes = [ Plane3dByOriginAndUnitNormal.createXYZUVW(8, 9, 0, -1, -3, 0)!, Plane3dByOriginAndUnitNormal.createXYZUVW(5, 8, 0, 4, 1.5, 0)!, - Plane3dByOriginAndUnitNormal.createXYZUVW(9, 4, 0, -4, 1.5, 0)!]; + Plane3dByOriginAndUnitNormal.createXYZUVW(9, 4, 0, -4, 1.5, 0)!, + ]; for (const plane of planes) { const clipPlane = ClipPlane.createPlane(plane); @@ -1489,7 +1524,8 @@ describe("ClipPlaneDocs", () => { const planesForUnboundedConvexSet = [ Plane3dByOriginAndUnitNormal.createXYZUVW(4.1, 2.1, 0, 1, 3, 0)!, Plane3dByOriginAndUnitNormal.createXYZUVW(2.5, 6.5, 0, 1, 0, 0)!, - Plane3dByOriginAndUnitNormal.createXYZUVW(4.1, 12.1, 0, 1, -2, 0)!]; + Plane3dByOriginAndUnitNormal.createXYZUVW(4.1, 12.1, 0, 1, -2, 0)!, + ]; showClipPlaneEffects(planesForUnboundedConvexSet, grid); out.shift(30, 0); @@ -1514,9 +1550,13 @@ describe("ClipPlaneDocs", () => { const polygonQ = Sample.createArcStrokes(3, Point3d.create(1, 0, 0), 4, Angle.createDegrees(0), Angle.createDegrees(360), true, -0.01); - for (const clipData of [{ clipper: clipperA, polygon: polygonA, doPolyface: true }, - { clipper: clipperB, polygon: polygonB, doPolyface: true }, - { clipper: clipperC, polygon: polygonC, doPolyface: false }]) { + for ( + const clipData of [{ clipper: clipperA, polygon: polygonA, doPolyface: true }, { clipper: clipperB, polygon: polygonB, doPolyface: true }, { + clipper: clipperC, + polygon: polygonC, + doPolyface: false, + }] + ) { for (const polygon of [polygonQ]) { out.drawPolygon(clipData.polygon, true); out.drawPolygon(polygon, false); @@ -1545,5 +1585,4 @@ describe("ClipPlaneDocs", () => { out.saveToFile("ClipPlaneDocs", "UnionOfConvexClipPlaneSets"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/clipping/ClipPrimitives.test.ts b/core/geometry/src/test/clipping/ClipPrimitives.test.ts index 3a256e0d7dc4..d0dab49c696c 100644 --- a/core/geometry/src/test/clipping/ClipPrimitives.test.ts +++ b/core/geometry/src/test/clipping/ClipPrimitives.test.ts @@ -78,7 +78,7 @@ export function clipShapesAreEqual(clip0: ClipShape, clip1: ClipShape): boolean return false; if (clip0.invisible !== clip1.invisible) return false; - for (let i = 0; i < clip0.polygon.length; i++) // Polygon points should be in the same order + for (let i = 0; i < clip0.polygon.length; i++) // Polygon points should be in the same order if (!clip0.polygon[i].isAlmostEqual(clip1.polygon[i])) return false; if (clip0.isMask !== clip1.isMask) @@ -87,7 +87,10 @@ export function clipShapesAreEqual(clip0: ClipShape, clip1: ClipShape): boolean return false; if ((clip0.zLow !== clip1.zLow) || (clip0.zHigh !== clip1.zHigh)) return false; - if (clip0.transformValid && (!clip0.transformFromClip!.isAlmostEqual(clip1.transformFromClip!) || !clip1.transformToClip!.isAlmostEqual(clip1.transformToClip!))) + if ( + clip0.transformValid && + (!clip0.transformFromClip!.isAlmostEqual(clip1.transformFromClip!) || !clip1.transformToClip!.isAlmostEqual(clip1.transformToClip!)) + ) return false; return true; } @@ -106,11 +109,10 @@ function compareXYSector1(a: ClipPlane, b: ClipPlane): number { return -1; else if (a.inwardNormalRef.x > b.inwardNormalRef.x) return 1; - else - if (a.inwardNormalRef.y < a.inwardNormalRef.y) - return -1; - else if (a.inwardNormalRef.y > b.inwardNormalRef.y) - return 1; + else if (a.inwardNormalRef.y < a.inwardNormalRef.y) + return -1; + else if (a.inwardNormalRef.y > b.inwardNormalRef.y) + return 1; return 0; } @@ -120,11 +122,10 @@ function compareXYSector2(a: ClipPlane, b: ClipPlane): number { return -1; else if (a.inwardNormalRef.x < b.inwardNormalRef.x) return 1; - else - if (a.inwardNormalRef.y < a.inwardNormalRef.y) - return -1; - else if (a.inwardNormalRef.y > b.inwardNormalRef.y) - return 1; + else if (a.inwardNormalRef.y < a.inwardNormalRef.y) + return -1; + else if (a.inwardNormalRef.y > b.inwardNormalRef.y) + return 1; return 0; } @@ -134,11 +135,10 @@ function compareXYSector3(a: ClipPlane, b: ClipPlane): number { return -1; else if (a.inwardNormalRef.x < b.inwardNormalRef.x) return 1; - else - if (a.inwardNormalRef.y > a.inwardNormalRef.y) - return -1; - else if (a.inwardNormalRef.y < b.inwardNormalRef.y) - return 1; + else if (a.inwardNormalRef.y > a.inwardNormalRef.y) + return -1; + else if (a.inwardNormalRef.y < b.inwardNormalRef.y) + return 1; return 0; } @@ -148,11 +148,10 @@ function compareXYSector4(a: ClipPlane, b: ClipPlane): number { return -1; else if (a.inwardNormalRef.x > b.inwardNormalRef.x) return 1; - else - if (a.inwardNormalRef.y > a.inwardNormalRef.y) - return -1; - else if (a.inwardNormalRef.y < b.inwardNormalRef.y) - return 1; + else if (a.inwardNormalRef.y > a.inwardNormalRef.y) + return -1; + else if (a.inwardNormalRef.y < b.inwardNormalRef.y) + return 1; return 0; } @@ -220,7 +219,7 @@ function sortConvexSetPlanesToBoundary(convexSet: ConvexClipPlaneSet) { if (plane.inwardNormalRef.x < 0 && plane.inwardNormalRef.y > 0) tempSortedPlanes.push(plane); } - tempSortedPlanes.sort(compareXYSector3); // more negative values less than others + tempSortedPlanes.sort(compareXYSector3); // more negative values less than others for (const plane of tempSortedPlanes) newPlanes.push(plane); @@ -241,7 +240,7 @@ function sortConvexSetPlanesToBoundary(convexSet: ConvexClipPlaneSet) { if (plane.inwardNormalRef.x < 0 && plane.inwardNormalRef.y < 0) tempSortedPlanes.push(plane); } - tempSortedPlanes.sort(compareXYSector4); // more negative values less than others + tempSortedPlanes.sort(compareXYSector4); // more negative values less than others for (const plane of tempSortedPlanes) newPlanes.push(plane); @@ -262,9 +261,15 @@ function getPointIntersectionsOfConvexSetPlanes(convexSet: ConvexClipPlaneSet, c // Intersection of plane 0 with plane 1 const planeMatrix = Matrix3d.createRowValues( - planeA0.inwardNormalRef.x, planeA0.inwardNormalRef.y, planeA0.inwardNormalRef.z, - planeA1.inwardNormalRef.x, planeA1.inwardNormalRef.y, planeA1.inwardNormalRef.z, - 0, 0, 1, + planeA0.inwardNormalRef.x, + planeA0.inwardNormalRef.y, + planeA0.inwardNormalRef.z, + planeA1.inwardNormalRef.x, + planeA1.inwardNormalRef.y, + planeA1.inwardNormalRef.z, + 0, + 0, + 1, ).inverse()!; ck.testTrue(planeMatrix !== undefined); const planeDistanceVec = Vector3d.create(planeA0.distance, planeA1.distance, 0); @@ -277,9 +282,15 @@ function getPointIntersectionsOfConvexSetPlanes(convexSet: ConvexClipPlaneSet, c // Intersection of plane 0 with plane 1 const plane01Matrix = Matrix3d.createRowValues( - plane0.inwardNormalRef.x, plane0.inwardNormalRef.y, plane0.inwardNormalRef.z, - plane1.inwardNormalRef.x, plane1.inwardNormalRef.y, plane1.inwardNormalRef.z, - 0, 0, 1, + plane0.inwardNormalRef.x, + plane0.inwardNormalRef.y, + plane0.inwardNormalRef.z, + plane1.inwardNormalRef.x, + plane1.inwardNormalRef.y, + plane1.inwardNormalRef.z, + 0, + 0, + 1, ).inverse()!; ck.testTrue(plane01Matrix !== undefined); const plane01DistanceVec = Vector3d.create(plane0.distance, plane1.distance, 0); @@ -393,7 +404,15 @@ describe("ClipPrimitive", () => { // Exercise check for z-clips ck.testTrue(clipPrimitive.containsZClip(), "Expected clip primitive to contain a normal along the z-axis"); - ClipShape.createShape([Point3d.create(1, 2), Point3d.create(50, 50), Point3d.create(100, -1)], undefined, undefined, undefined, false, false, clipPrimitive); + ClipShape.createShape( + [Point3d.create(1, 2), Point3d.create(50, 50), Point3d.create(100, -1)], + undefined, + undefined, + undefined, + false, + false, + clipPrimitive, + ); ck.testFalse(clipPrimitive.containsZClip(), "Expected clip primitive of box with open top and bottom to not contain z-clip"); // Exercise invisibility switch @@ -424,7 +443,11 @@ describe("ClipPrimitive", () => { const translation = new Point3d(0, -1, 1); clipShape = ClipShape.createEmpty(false, false, Transform.createTranslation(translation)); clipShape.performTransformFromClip(testPoint); - ck.testPoint3d(testPoint, originalPoint.plus(translation), "Point should be translated when transformed with ClipShape containing translation transform"); + ck.testPoint3d( + testPoint, + originalPoint.plus(translation), + "Point should be translated when transformed with ClipShape containing translation transform", + ); clipShape.performTransformToClip(testPoint); ck.testPoint3d(testPoint, originalPoint, "Point should be translated when transformed with ClipShape containing translation transform"); @@ -435,14 +458,36 @@ describe("ClipPrimitive", () => { it("ClipShape creation (linear) and point classification", () => { const ck = new Checker(); // Create a ClipShape from 3 colinear points (degenerate!) - const clipShape = ClipShape.createShape([Point3d.create(-5, 0, 0), Point3d.create(5, 0, 0), Point3d.create(-5, 0, 0)], - -3, 3, undefined, false, false)!; + const clipShape = ClipShape.createShape( + [Point3d.create(-5, 0, 0), Point3d.create(5, 0, 0), Point3d.create(-5, 0, 0)], + -3, + 3, + undefined, + false, + false, + )!; ck.testPointer(clipShape, "Can create ClipShape that will be parsed into a linear set of planes"); clipShape.fetchClipPlanesRef(); - ck.testExactNumber(clipShape.classifyPointContainment([Point3d.create(-5.00001, 0, 0)], true), 3, "Point does not fall on line outside of sides - strongly outside"); - ck.testExactNumber(clipShape.classifyPointContainment([Point3d.create(0, 3, 0), Point3d.create(2, -5, 0)], true), 2, "Points cross line and within sides - ambiguous"); - ck.testExactNumber(clipShape.classifyPointContainment([Point3d.create(0, -0.00001, 0), Point3d.create(0, 0.00001, 0)], true), 2, "Points cross line and within sides - ambiguous"); - ck.testExactNumber(clipShape.classifyPointContainment([Point3d.create(4.999, 0, 2.999), Point3d.create(0, 0, 0)], true), 1, "Points fall on line and is within sides - strongly inside"); + ck.testExactNumber( + clipShape.classifyPointContainment([Point3d.create(-5.00001, 0, 0)], true), + 3, + "Point does not fall on line outside of sides - strongly outside", + ); + ck.testExactNumber( + clipShape.classifyPointContainment([Point3d.create(0, 3, 0), Point3d.create(2, -5, 0)], true), + 2, + "Points cross line and within sides - ambiguous", + ); + ck.testExactNumber( + clipShape.classifyPointContainment([Point3d.create(0, -0.00001, 0), Point3d.create(0, 0.00001, 0)], true), + 2, + "Points cross line and within sides - ambiguous", + ); + ck.testExactNumber( + clipShape.classifyPointContainment([Point3d.create(4.999, 0, 2.999), Point3d.create(0, 0, 0)], true), + 1, + "Points fall on line and is within sides - strongly inside", + ); ck.checkpoint(); expect(ck.getNumErrors()).toBe(0); @@ -451,7 +496,7 @@ describe("ClipPrimitive", () => { it("ClipShapePointTests", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const minZ = undefined; // EDL Sept 2021 z clip combined with hole is not clear. + const minZ = undefined; // EDL Sept 2021 z clip combined with hole is not clear. const maxZ = undefined; // Test point location const clipShape0 = ClipShape.createEmpty(true); @@ -502,7 +547,10 @@ describe("ClipPrimitive", () => { // Test clone method const clipShape2 = clipShape1Copy.clone(); ck.testTrue(clipShapesAreEqual(clipShape2, clipShape1), "clone method produces a copy of ClipShape"); - const generalTransform = Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 1), Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(24))); + const generalTransform = Transform.createFixedPointAndMatrix( + Point3d.create(3, 2, 1), + Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(24)), + ); clipShape2.transformInPlace(generalTransform); ck.testFalse(clipShape2.isXYPolygon); @@ -528,7 +576,10 @@ describe("ClipPrimitive", () => { const trianglePoints = getPointIntersectionsOfConvexSetPlanes(convexSet, ck); ck.testExactNumber(trianglePoints.length, 3); unionRange.extendArray(trianglePoints); - ck.testTrue(pointArrayIsSubsetOfOther(trianglePoints, clipShape.polygon), "All points of triangulated convex area of polygon should fall on boundary"); + ck.testTrue( + pointArrayIsSubsetOfOther(trianglePoints, clipShape.polygon), + "All points of triangulated convex area of polygon should fall on boundary", + ); unionArea += triangleAreaXY(trianglePoints[0], trianglePoints[1], trianglePoints[2]); } ck.testRange3d(originalRange, unionRange, "Range extended by all convex regions should match range of entire concave region."); @@ -577,7 +628,11 @@ describe("ClipPrimitive", () => { return true; }); } - ck.testCoordinate(clippedPolygonArea, clipShapeArea, "Polygon that completely encompasses clipShape should have same area as clipShape after clipping."); + ck.testCoordinate( + clippedPolygonArea, + clipShapeArea, + "Polygon that completely encompasses clipShape should have same area as clipShape after clipping.", + ); } ck.checkpoint(); expect(ck.getNumErrors()).toBe(0); @@ -614,7 +669,7 @@ describe("ClipPrimitive", () => { it("ClipPrimitive base class", () => { const ck = new Checker(); - for (const invert of [false]) { // EDL sept 2021 invert bit on simple plane set has no effect. Don't test with true. + for (const invert of [false]) { // EDL sept 2021 invert bit on simple plane set has no effect. Don't test with true. const clipper = ConvexClipPlaneSet.createXYBox(1, 1, 10, 8); const prim0 = ClipPrimitive.createCapture(clipper, invert); const prim1 = prim0.clone(); @@ -628,7 +683,6 @@ describe("ClipPrimitive", () => { ck.testBoolean(!invert, prim.pointInside(Point3d.create(7, 2, 0))); ck.testBoolean(invert, prim.pointInside(Point3d.create(-2, 0, 0))); } - } ck.checkpoint(); expect(ck.getNumErrors()).toBe(0); @@ -679,7 +733,8 @@ describe("ClipPrimitive", () => { { dist: -0.09250245365197413, normal: [0.9999999999999999, 0, 0] }, { dist: -4.620474647250288, normal: [-0.9999999999999999, 0, 0] }, { dist: -6.984123210872675, normal: [0, -0.9999999999999999, 6.123233995736765e-17] }, - { dist: -0.09250245365197496, normal: [0, 0.9999999999999999, -6.123233995736765e-17] }]], + { dist: -0.09250245365197496, normal: [0, 0.9999999999999999, -6.123233995736765e-17] }, + ]], }, }]; const clipper = ClipVector.fromJSON(json); @@ -738,7 +793,7 @@ describe("ClipPrimitive", () => { const outerClip = ClipShape.createBlock(outerRange, ClipMaskXYZRangePlanes.XAndY); ck.testFalse(outerClip.isMask); const holeRange = outerRange.clone(); - holeRange.expandInPlace(-4); // hole xy range corners (3,2), (4,6) + holeRange.expandInPlace(-4); // hole xy range corners (3,2), (4,6) const holeClip = ClipShape.createBlock(holeRange, ClipMaskXYZRangePlanes.XAndY, true); ck.testTrue(holeClip.isMask); @@ -797,7 +852,7 @@ describe("ClipPrimitive", () => { const uncappedBoxSetA = ConvexClipPlaneSet.createRange3dPlanes(clipRange, true, true, true, true, false, false); const uncappedBoxSetB = ConvexClipPlaneSet.createRange3dPlanes(clipRange); // clip all sides const boxPrimitiveA = ClipPrimitive.createCapture(uncappedBoxSetA, false); - const boxPrimitiveB = ClipPrimitive.createCapture(uncappedBoxSetB, true); // invisible flag does nothing + const boxPrimitiveB = ClipPrimitive.createCapture(uncappedBoxSetB, true); // invisible flag does nothing const builder = PolyfaceBuilder.create(); const mesh = builder.claimPolyface(); { @@ -818,13 +873,18 @@ describe("ClipPrimitive", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "ClipPrimitive", "ClipPrimitiveMasking"); expect(ck.getNumErrors()).toBe(0); }); - }); -function clipAndOutput(allGeometry: GeometryQuery[], clipper: ClipPrimitive, +function clipAndOutput( + allGeometry: GeometryQuery[], + clipper: ClipPrimitive, mesh: IndexedPolyface, clipRange: Range3d | undefined, - x0: number, y0: number, yStep: number, buildClosureFaces: boolean = true) { + x0: number, + y0: number, + yStep: number, + buildClosureFaces: boolean = true, +) { const unionOfConvexSets = clipper.fetchClipPlanesRef(); if (unionOfConvexSets) { const builders = ClippedPolyfaceBuilders.create(true, true, buildClosureFaces); @@ -838,8 +898,7 @@ function clipAndOutput(allGeometry: GeometryQuery[], clipper: ClipPrimitive, } } -function addCone(builder: PolyfaceBuilder, x0: number, y0: number, z0: number, - x1: number, y1: number, z1: number, radius0: number, radius1: number) { +function addCone(builder: PolyfaceBuilder, x0: number, y0: number, z0: number, x1: number, y1: number, z1: number, radius0: number, radius1: number) { const cone = Cone.createAxisPoints(Point3d.create(x0, y0, z0), Point3d.create(x1, y1, z1), radius0, radius1, true); builder.addCone(cone!); } diff --git a/core/geometry/src/test/clipping/ClipUtilities.test.ts b/core/geometry/src/test/clipping/ClipUtilities.test.ts index fc90a6159eb9..35583aa9ce8f 100644 --- a/core/geometry/src/test/clipping/ClipUtilities.test.ts +++ b/core/geometry/src/test/clipping/ClipUtilities.test.ts @@ -10,8 +10,8 @@ import { ClipVector } from "../../clipping/ClipVector"; import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; import { UnionOfConvexClipPlaneSets } from "../../clipping/UnionOfConvexClipPlaneSets"; import { Arc3d } from "../../curve/Arc3d"; -import { AnyRegion } from "../../curve/CurveTypes"; import { BagOfCurves } from "../../curve/CurveCollection"; +import { AnyRegion } from "../../curve/CurveTypes"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; @@ -28,9 +28,9 @@ import { Point2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Range1d, Range3d } from "../../geometry3d/Range"; import { Transform } from "../../geometry3d/Transform"; +import { YawPitchRollAngles } from "../../geometry3d/YawPitchRollAngles"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { YawPitchRollAngles } from "../../geometry3d/YawPitchRollAngles"; describe("ParityRegionSweep", () => { it("TriangleClip", () => { @@ -42,9 +42,13 @@ describe("ParityRegionSweep", () => { const vector01 = Vector3d.create(1, 7); const dxA = 1.5; const intervals = [ - Range1d.createXX(0, 1), Range1d.createXX(0.3, 1.0), - Range1d.createXX(0.6, 1.0), Range1d.createXX(0, 0.5), - Range1d.createXX(0.5, 1.0), Range1d.createXX(0.2, 0.8)]; + Range1d.createXX(0, 1), + Range1d.createXX(0.3, 1.0), + Range1d.createXX(0.6, 1.0), + Range1d.createXX(0, 0.5), + Range1d.createXX(0.5, 1.0), + Range1d.createXX(0.2, 0.8), + ]; const xOut = 0; const yOut0 = 0; const yOut1 = 10.0; @@ -68,21 +72,26 @@ describe("ParityRegionSweep", () => { ck.testTightNumber(resultABC.length(), resultBCA.length(), "clip fraction length with rotated triangle order"); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [segment2, segment3], xOut, yOut0); if (!resultABC.isNull) { - GeometryCoreTestIO.captureCloneGeometry(allGeometry, + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, [segment2.interpolate(resultABC.low, segment3), segment2.interpolate(resultABC.high, segment3)], - xOut, yOut1); + xOut, + yOut1, + ); } if (!resultBCA.isNull) { - GeometryCoreTestIO.captureCloneGeometry(allGeometry, + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, [segment2.interpolate(resultABC.low, segment3), segment2.interpolate(resultABC.high, segment3)], - xOut, yOut2); + xOut, + yOut2, + ); } } } GeometryCoreTestIO.saveGeometry(allGeometry, "ParityRegionSweep", "TriangleClip"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("ClipUtilities", () => { @@ -113,8 +122,10 @@ describe("ClipUtilities", () => { const clipper = ConvexClipPlaneSet.createRange3dPlanes(range, true, true, true, true, true, true); unionClip.addConvexSet(clipper); exerciseClipper(ck, allGeometry, unitRange, clipper, xy0); - const rotation = Transform.createFixedPointAndMatrix(range.fractionToPoint(0.5, 0.5, 0.5), - Matrix3d.createRotationAroundVector(Vector3d.create(1, 0.4, 0.3), Angle.createDegrees(20))!); + const rotation = Transform.createFixedPointAndMatrix( + range.fractionToPoint(0.5, 0.5, 0.5), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 0.4, 0.3), Angle.createDegrees(20))!, + ); clipper.transformInPlace(rotation); xy0.x += 5.0; xy0.y = 0.0; @@ -156,8 +167,7 @@ function rangeOfGeometry(geometry: GeometryQuery[]): Range3d { return range; } -function exerciseClipper(ck: Checker, allGeometry: GeometryQuery[], outerRange: Range3d, clipper: ConvexClipPlaneSet, - xy0: Point2d) { +function exerciseClipper(ck: Checker, allGeometry: GeometryQuery[], outerRange: Range3d, clipper: ConvexClipPlaneSet, xy0: Point2d) { const clipperLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipper, outerRange, true, false, true); const rangeLoops = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipper, outerRange, false, true, true); @@ -360,7 +370,7 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range, shift); // sanity tests expect(clippedCurve.length).toBe(1); - const area = RegionOps.computeXYArea((clippedCurve[0] as AnyRegion))!; + const area = RegionOps.computeXYArea(clippedCurve[0] as AnyRegion)!; const expectedArea = (6 * 16) + (8 * 8 * Math.PI / 2); ck.testCoordinate(area, expectedArea); // save all geometries @@ -373,22 +383,52 @@ describe("ClipUtilities", () => { interface TestCase { data: { localRange: Range3d, localToWorld: Transform, worldClashRange?: Range3d }[]; expectedClash: boolean; // each entry is a set of mutually clashing or mutually non-clashing local ranges - clashRange?: (undefined | Range3d)[][]; // clashRange[i][j] is world range of intersection of data[i] and data[j], defined only for i < j + clashRange?: (undefined | Range3d)[][]; // clashRange[i][j] is world range of intersection of data[i] and data[j], defined only for i < j } const testCases: TestCase[] = [ // from user iModel { data: [ { - localRange: Range3d.createXYZXYZ(-0.023434012896785816, -5.00413553129377, -9.650393591767262, 20.02343401289663, 5.03613553129378, 9.68239359176722), - localToWorld: Transform.createRefs(Point3d.create(-108.12092516312605, 80.97820829881688, 67.15651552186583), YawPitchRollAngles.createDegrees(-47.95656913000159, 15.000000000006024, 90).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + -0.023434012896785816, + -5.00413553129377, + -9.650393591767262, + 20.02343401289663, + 5.03613553129378, + 9.68239359176722, + ), + localToWorld: Transform.createRefs( + Point3d.create(-108.12092516312605, 80.97820829881688, 67.15651552186583), + YawPitchRollAngles.createDegrees(-47.95656913000159, 15.000000000006024, 90).toMatrix3d(), + ), }, { - localRange: Range3d.createXYZXYZ(-0.024019658687571166, -0.020559836132079568, -0.047579717945438915, 0.10484869637410554, 0.09055983613204432, 0.0975797179454645), - localToWorld: Transform.createRefs(Point3d.create(-95.29966304738043, 66.6762028551563, 72.28348554781851), YawPitchRollAngles.createDegrees(42.04343086998508, -4.9775680764904035e-11, 74.99999999999397).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + -0.024019658687571166, + -0.020559836132079568, + -0.047579717945438915, + 0.10484869637410554, + 0.09055983613204432, + 0.0975797179454645, + ), + localToWorld: Transform.createRefs( + Point3d.create(-95.29966304738043, 66.6762028551563, 72.28348554781851), + YawPitchRollAngles.createDegrees(42.04343086998508, -4.9775680764904035e-11, 74.99999999999397).toMatrix3d(), + ), }, { - localRange: Range3d.createXYZXYZ(-0.041116288886769325, -0.04342022062438389, -0.21911795212515983, 0.3411162888867949, 0.3434202206242212, 0.22911795212515074), - localToWorld: Transform.createRefs(Point3d.create(-95.14478995681672, 66.78879158941069, 72.16981588733208), YawPitchRollAngles.createDegrees(132.0434308699035, 75.00000000001432, 8.799644912641437e-11).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + -0.041116288886769325, + -0.04342022062438389, + -0.21911795212515983, + 0.3411162888867949, + 0.3434202206242212, + 0.22911795212515074, + ), + localToWorld: Transform.createRefs( + Point3d.create(-95.14478995681672, 66.78879158941069, 72.16981588733208), + YawPitchRollAngles.createDegrees(132.0434308699035, 75.00000000001432, 8.799644912641437e-11).toMatrix3d(), + ), }, ], expectedClash: true, @@ -408,16 +448,39 @@ describe("ClipUtilities", () => { { data: [ { - localRange: Range3d.createXYZXYZ(1.1546319456101628e-14, -1.4328815911568427e-14, -5.1535165024318985e-14, 11.999999999999943, 0.03199999999999116, 0.031999999999948535), - localToWorld: Transform.createRefs(Point3d.create(-119.10528623043024, 43.39951280844136, 68.47662261522927), YawPitchRollAngles.createDegrees(-6.448039711171915, 15.000000000002194, 1.6754791257296069).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + 1.1546319456101628e-14, + -1.4328815911568427e-14, + -5.1535165024318985e-14, + 11.999999999999943, + 0.03199999999999116, + 0.031999999999948535, + ), + localToWorld: Transform.createRefs( + Point3d.create(-119.10528623043024, 43.39951280844136, 68.47662261522927), + YawPitchRollAngles.createDegrees(-6.448039711171915, 15.000000000002194, 1.6754791257296069).toMatrix3d(), + ), }, { localRange: Range3d.createXYZXYZ(0, 0, -1.4210854715202004e-14, 11.999999999999986, 0, -1.4210854715202004e-14), - localToWorld: Transform.createRefs(Point3d.create(-107.5899903512084, 42.11371219204531, 71.59835123713896), YawPitchRollAngles.createDegrees(173.55196028882585, -14.99999999999978, 2.0579703138818464e-16).toMatrix3d()), + localToWorld: Transform.createRefs( + Point3d.create(-107.5899903512084, 42.11371219204531, 71.59835123713896), + YawPitchRollAngles.createDegrees(173.55196028882585, -14.99999999999978, 2.0579703138818464e-16).toMatrix3d(), + ), }, { - localRange: Range3d.createXYZXYZ(-0.02213513258379224, -0.018579865396888717, -0.19678412188787828, 0.5721351325838432, 0.5685798653970273, 0.22178412188785057), - localToWorld: Transform.createRefs(Point3d.create(-107.61315829094143, 42.393081259141205, 71.29907515904608), YawPitchRollAngles.createDegrees(173.5519602888134, 74.99999999996545, 5.981534282323202e-12).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + -0.02213513258379224, + -0.018579865396888717, + -0.19678412188787828, + 0.5721351325838432, + 0.5685798653970273, + 0.22178412188785057, + ), + localToWorld: Transform.createRefs( + Point3d.create(-107.61315829094143, 42.393081259141205, 71.29907515904608), + YawPitchRollAngles.createDegrees(173.5519602888134, 74.99999999996545, 5.981534282323202e-12).toMatrix3d(), + ), }, ], expectedClash: true, @@ -438,15 +501,24 @@ describe("ClipUtilities", () => { data: [ { localRange: Range3d.createXYZXYZ(-5, -5, -5, 5, 5, 5), - localToWorld: Transform.createOriginAndMatrix(Point3d.create(-3, -6, -9), Matrix3d.createRotationAroundVector(Vector3d.create(1, 1, 1), Angle.createDegrees(33))), + localToWorld: Transform.createOriginAndMatrix( + Point3d.create(-3, -6, -9), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 1, 1), Angle.createDegrees(33)), + ), }, { localRange: Range3d.createXYZXYZ(-2, -2, -2, 2, 2, 2), - localToWorld: Transform.createOriginAndMatrix(Point3d.create(5, 5, 5), Matrix3d.createRotationAroundVector(Vector3d.create(-1, 1, -1), Angle.createDegrees(-115))), + localToWorld: Transform.createOriginAndMatrix( + Point3d.create(5, 5, 5), + Matrix3d.createRotationAroundVector(Vector3d.create(-1, 1, -1), Angle.createDegrees(-115)), + ), }, { localRange: Range3d.createXYZXYZ(-1, -1, -1, 1, 1, 1), - localToWorld: Transform.createOriginAndMatrix(Point3d.create(-10, 4, 3), Matrix3d.createRotationAroundVector(Vector3d.create(0, 1, -1), Angle.createDegrees(245))), + localToWorld: Transform.createOriginAndMatrix( + Point3d.create(-10, 4, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(0, 1, -1), Angle.createDegrees(245)), + ), }, ], expectedClash: false, @@ -454,12 +526,32 @@ describe("ClipUtilities", () => { { data: [ { - localRange: Range3d.createXYZXYZ(7.993605777301127e-15, 1.1483869410966463e-15, -8.895661984809067e-15, 11.999999999999961, 0.03200000000001247, 0.03200000000001958), - localToWorld: Transform.createRefs(Point3d.create(-118.75022305842617, 45.954529463039, 68.47641991136159), YawPitchRollAngles.createDegrees(-9.408029798593397, 15.000000000007361, 2.455595252575587).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + 7.993605777301127e-15, + 1.1483869410966463e-15, + -8.895661984809067e-15, + 11.999999999999961, + 0.03200000000001247, + 0.03200000000001958, + ), + localToWorld: Transform.createRefs( + Point3d.create(-118.75022305842617, 45.954529463039, 68.47641991136159), + YawPitchRollAngles.createDegrees(-9.408029798593397, 15.000000000007361, 2.455595252575587).toMatrix3d(), + ), }, { - localRange: Range3d.createXYZXYZ(-0.03474118660066772, -3.3591167872492598, -1.714177531529474, 11.744741186600766, 3.4591167872486275, 1.8141775315289306), - localToWorld: Transform.createRefs(Point3d.create(-118.82046236854137, 46.0485514387863, 68.44465610136753), YawPitchRollAngles.createDegrees(-9.40802979863332, 15.000000000003949, 113.91380925648686).toMatrix3d()), + localRange: Range3d.createXYZXYZ( + -0.03474118660066772, + -3.3591167872492598, + -1.714177531529474, + 11.744741186600766, + 3.4591167872486275, + 1.8141775315289306, + ), + localToWorld: Transform.createRefs( + Point3d.create(-118.82046236854137, 46.0485514387863, 68.44465610136753), + YawPitchRollAngles.createDegrees(-9.40802979863332, 15.000000000003949, 113.91380925648686).toMatrix3d(), + ), }, ], expectedClash: true, @@ -475,7 +567,11 @@ describe("ClipUtilities", () => { for (const testCase of testCases) { const maxRange = Point3d.createZero(); for (const datum of testCase.data) - maxRange.set(Math.max(maxRange.x, datum.localRange.xLength()), Math.max(maxRange.y, datum.localRange.yLength()), Math.max(maxRange.z, datum.localRange.zLength())); + maxRange.set( + Math.max(maxRange.x, datum.localRange.xLength()), + Math.max(maxRange.y, datum.localRange.yLength()), + Math.max(maxRange.z, datum.localRange.zLength()), + ); const delta = maxRange.maxAbs(); const delta10 = 10 * delta; let x = 0; @@ -483,23 +579,64 @@ describe("ClipUtilities", () => { for (let j = i + 1; j < testCase.data.length; ++j) { let y = 0; // lambda to exercise local range clash methods - const clashDetect = (index0: number, index1: number, captureLocal: boolean = false, captureWorld: boolean = true, captureIntersection: boolean = true): boolean => { + const clashDetect = ( + index0: number, + index1: number, + captureLocal: boolean = false, + captureWorld: boolean = true, + captureIntersection: boolean = true, + ): boolean => { if (captureLocal) { // doLocalRangesIntersect converts range0 to a polyface transformed into range1's local coordinates - GeometryCoreTestIO.captureTransformedRangeEdges(allGeometry, testCase.data[index0].localRange, testCase.data[index1].localToWorld.inverse()?.multiplyTransformTransform(testCase.data[index0].localToWorld), x, y, z); + GeometryCoreTestIO.captureTransformedRangeEdges( + allGeometry, + testCase.data[index0].localRange, + testCase.data[index1].localToWorld.inverse()?.multiplyTransformTransform(testCase.data[index0].localToWorld), + x, + y, + z, + ); GeometryCoreTestIO.captureRangeEdges(allGeometry, testCase.data[index1].localRange, x, y, z); } if (captureWorld) { - GeometryCoreTestIO.captureTransformedRangeEdges(allGeometry, testCase.data[index0].localRange, testCase.data[index0].localToWorld, x, y, z); - GeometryCoreTestIO.captureTransformedRangeEdges(allGeometry, testCase.data[index1].localRange, testCase.data[index1].localToWorld, x, y, z); + GeometryCoreTestIO.captureTransformedRangeEdges( + allGeometry, + testCase.data[index0].localRange, + testCase.data[index0].localToWorld, + x, + y, + z, + ); + GeometryCoreTestIO.captureTransformedRangeEdges( + allGeometry, + testCase.data[index1].localRange, + testCase.data[index1].localToWorld, + x, + y, + z, + ); } - const isClash = ClipUtilities.doLocalRangesIntersect(testCase.data[index0].localRange, testCase.data[index0].localToWorld, testCase.data[index1].localRange, testCase.data[index1].localToWorld); + const isClash = ClipUtilities.doLocalRangesIntersect( + testCase.data[index0].localRange, + testCase.data[index0].localToWorld, + testCase.data[index1].localRange, + testCase.data[index1].localToWorld, + ); ck.testBoolean(isClash, testCase.expectedClash, `ranges clash as expected: i=${index0} j=${index1}`); - const clashRange = ClipUtilities.rangeOfIntersectionOfLocalRanges(testCase.data[index0].localRange, testCase.data[index0].localToWorld, testCase.data[index1].localRange, testCase.data[index1].localToWorld); + const clashRange = ClipUtilities.rangeOfIntersectionOfLocalRanges( + testCase.data[index0].localRange, + testCase.data[index0].localToWorld, + testCase.data[index1].localRange, + testCase.data[index1].localToWorld, + ); if (captureIntersection) GeometryCoreTestIO.captureRangeEdges(allGeometry, clashRange, x, y, z); if (ck.testTrue(isClash === !clashRange.isNull, "intersection range is non-null iff ranges clash") && isClash) - ck.testRange3d(clashRange, testCase.clashRange![Math.min(index0, index1)][Math.max(index0, index1)]!, "intersection has expected world range"); + ck.testRange3d( + clashRange, + testCase.clashRange![Math.min(index0, index1)][Math.max(index0, index1)]!, + "intersection has expected world range", + ); return isClash; }; @@ -509,7 +646,13 @@ describe("ClipUtilities", () => { ck.testBoolean(clashIJ, clashJI, `symmetric arguments: i=${i} j=${j}`); // cover the margin case, no output or test - ClipUtilities.doLocalRangesIntersect(testCase.data[i].localRange, testCase.data[i].localToWorld, testCase.data[j].localRange, testCase.data[j].localToWorld, 1.0); + ClipUtilities.doLocalRangesIntersect( + testCase.data[i].localRange, + testCase.data[i].localToWorld, + testCase.data[j].localRange, + testCase.data[j].localToWorld, + 1.0, + ); x += delta10; } } @@ -573,7 +716,7 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range, shift); // sanity tests expect(clippedCurve.length).toBe(1); - const area = RegionOps.computeXYArea((clippedCurve[0] as AnyRegion))!; + const area = RegionOps.computeXYArea(clippedCurve[0] as AnyRegion)!; const expectedArea = (4 * 10) + (6 * 4) + (4 * 10); ck.testCoordinate(area, expectedArea); // save all geometries @@ -632,7 +775,7 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range, shift); // sanity tests expect(clippedCurve.length).toBe(1); - const area = RegionOps.computeXYArea((clippedCurve[0] as AnyRegion))!; + const area = RegionOps.computeXYArea(clippedCurve[0] as AnyRegion)!; const expectedArea = (14 * 10) - 8; ck.testCoordinate(area, expectedArea); // save all geometries @@ -698,8 +841,8 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range, shift); // sanity tests expect(clippedCurve.length).toBe(2); - const area = RegionOps.computeXYArea((clippedCurve[1] as AnyRegion))!; - const expectedArea = (14 * 7 / 2); + const area = RegionOps.computeXYArea(clippedCurve[1] as AnyRegion)!; + const expectedArea = 14 * 7 / 2; ck.testCoordinate(area, expectedArea); // save all geometries GeometryCoreTestIO.saveGeometry(allGeometry, "ClipUtilities", "ClipBagOfCurves2"); @@ -761,7 +904,7 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range, shift); // sanity tests expect(clippedCurve.length).toBe(2); - const area = RegionOps.computeXYArea((clippedCurve[1] as AnyRegion))!; + const area = RegionOps.computeXYArea(clippedCurve[1] as AnyRegion)!; const expectedArea = 14 * 7; ck.testCoordinate(area, expectedArea); // save all geometries @@ -904,7 +1047,7 @@ describe("ClipUtilities", () => { GeometryCoreTestIO.captureRangeEdges(allGeometry, range2, shift); // sanity tests expect(clippedCurve.length).toBe(2); - const area = RegionOps.computeXYArea((clippedCurve[0] as AnyRegion))!; + const area = RegionOps.computeXYArea(clippedCurve[0] as AnyRegion)!; const expectedArea = (2 * 10) + (6 * 10); ck.testCoordinate(area, expectedArea); // save all geometries diff --git a/core/geometry/src/test/clipping/ClipVector.test.ts b/core/geometry/src/test/clipping/ClipVector.test.ts index cb2fc27c8242..e580ab93abcc 100644 --- a/core/geometry/src/test/clipping/ClipVector.test.ts +++ b/core/geometry/src/test/clipping/ClipVector.test.ts @@ -78,7 +78,13 @@ function makePointAdjustments(point: Point3d, adjustment: PointAdjustment): Arra * edge of a ClipVector ClipShape. */ -function checkPointProximity(clipVector: ClipVector, pointOnEdge: Point3d, pointInside: Point3d | undefined, pointOutside: Point3d | undefined, ck: Checker) { +function checkPointProximity( + clipVector: ClipVector, + pointOnEdge: Point3d, + pointInside: Point3d | undefined, + pointOutside: Point3d | undefined, + ck: Checker, +) { ck.testTrue(clipVector.pointInside(pointOnEdge), "Point on ClipShape edge is inside ClipVector"); if (pointInside) ck.testTrue(clipVector.pointInside(pointInside), "Point within ClipShape bounds is inside ClipVector"); @@ -126,24 +132,36 @@ describe("ClipVector", () => { beforeAll(() => { clipShape0 = ClipShape.createBlock(Range3d.createXYZXYZ(-5, -4, -50, -3, -2, 50), ClipMaskXYZRangePlanes.All); clipShape1 = ClipShape.createShape([Point3d.create(4.5, 1), Point3d.create(6, 3), Point3d.create(3, 3)])!; - clipShape2 = ClipShape.createShape([ - Point3d.create(6, 1), - Point3d.create(8, 1), - Point3d.create(10, -3), - Point3d.create(10, -5), - Point3d.create(6, -5), - ], -.2, -.1)!; - clipShape3 = ClipShape.createShape([ - Point3d.create(2, -7), - Point3d.create(6.5, -7), - Point3d.create(6.5, -4), - Point3d.create(3, -4), - ], -5, 5)!; - clipShape4 = ClipShape.createShape([ - Point3d.create(7, -8), - Point3d.create(7.7, -4.5), - Point3d.create(6.3, -4.5), - ], -5, 5)!; + clipShape2 = ClipShape.createShape( + [ + Point3d.create(6, 1), + Point3d.create(8, 1), + Point3d.create(10, -3), + Point3d.create(10, -5), + Point3d.create(6, -5), + ], + -.2, + -.1, + )!; + clipShape3 = ClipShape.createShape( + [ + Point3d.create(2, -7), + Point3d.create(6.5, -7), + Point3d.create(6.5, -4), + Point3d.create(3, -4), + ], + -5, + 5, + )!; + clipShape4 = ClipShape.createShape( + [ + Point3d.create(7, -8), + Point3d.create(7.7, -4.5), + Point3d.create(6.3, -4.5), + ], + -5, + 5, + )!; clipVector012 = ClipVector.createCapture([clipShape0, clipShape1, clipShape2]); // clipVector234 = ClipVector.createCapture([clipShape2, clipShape3, clipShape4]); }); @@ -171,13 +189,19 @@ describe("ClipVector", () => { const arrLen = clipVector012.clips.length; for (let i = 0; i < arrLen; i++) { ck.testTrue(clipVector012.clips[i] !== clipVectorTester0.clips[i], "ClipVector created with clones should have deep copies of each ClipShape"); - ck.testTrue(clipPrimitivesAreEqual(clipVector012.clips[i], clipVectorTester0.clips[i]), "ClipShape members of copied vector and cloned vector should be equivalent"); + ck.testTrue( + clipPrimitivesAreEqual(clipVector012.clips[i], clipVectorTester0.clips[i]), + "ClipShape members of copied vector and cloned vector should be equivalent", + ); clipVectorTester1.appendReference(clipVector012.clips[i]); ck.testTrue(clipVector012.clips[i] === clipVectorTester1.clips[0], "ClipShapes appended by reference should be shallow copies of each other"); clipVectorTester1.clear(); clipVectorTester1.appendClone(clipVector012.clips[i]); ck.testTrue(clipVector012.clips[i] !== clipVectorTester1.clips[0], "ClipVector with appended clone should have deep copy of ClipShape"); - ck.testTrue(clipPrimitivesAreEqual(clipVector012.clips[i], clipVectorTester1.clips[0]), "ClipVector with shallow copied ClipShape should be equivalent"); + ck.testTrue( + clipPrimitivesAreEqual(clipVector012.clips[i], clipVectorTester1.clips[0]), + "ClipVector with shallow copied ClipShape should be equivalent", + ); clipVectorTester1.clear(); } @@ -190,7 +214,10 @@ describe("ClipVector", () => { ck.testTrue(clipJSON.length === clipVector012.clips.length, "Converted clipVector to a JSON representation as an array of ClipShapes"); for (const primitive of clipJSON) { const shape = primitive as ClipPrimitiveShapeProps; - ck.testTrue(shape.shape !== undefined && shape.shape.points !== undefined && shape.shape.points.length > 0, "Each ClipShape was stored successfully, with its member points"); + ck.testTrue( + shape.shape !== undefined && shape.shape.points !== undefined && shape.shape.points.length > 0, + "Each ClipShape was stored successfully, with its member points", + ); } const parsedClipVector = ClipVector.fromJSON(clipJSON); ck.testTrue(clipVectorsAreEqual(clipVector012, parsedClipVector), "ClipVector is the same after roundtrip to and from JSON"); @@ -223,8 +250,12 @@ describe("ClipVector", () => { Point3d.create(7, -3, -.1), ]; const shape2PointAdj: PointAdjustment[] = [ - PointAdjustment.SubY, PointAdjustment.SubX, PointAdjustment.SubX, - PointAdjustment.AddX, PointAdjustment.AddZ, PointAdjustment.SubZ, + PointAdjustment.SubY, + PointAdjustment.SubX, + PointAdjustment.SubX, + PointAdjustment.AddX, + PointAdjustment.AddZ, + PointAdjustment.SubZ, ]; const shapeExtremities: Point3d[][] = [shape0Extremities, shape1Extremities, shape2Extremities]; const shapePointAdjustments: PointAdjustment[][] = [shape0PointAdj, shape1PointAdj, shape2PointAdj]; @@ -242,13 +273,29 @@ describe("ClipVector", () => { const pointOnEdge = shapeExtremities[i][j]; const pointAdjustments = makePointAdjustments(pointOnEdge, shapePointAdjustments[i][j]); checkPointProximity(clipVectorSingleShape, pointOnEdge, pointAdjustments[0], pointAdjustments[1], ck); - ck.testExactNumber(clipVectorSingleShape.classifyPointContainment([pointOnEdge]), 1, "Edge point should be classified as strongly inside for a single ClipShape"); + ck.testExactNumber( + clipVectorSingleShape.classifyPointContainment([pointOnEdge]), + 1, + "Edge point should be classified as strongly inside for a single ClipShape", + ); if (pointAdjustments[0]) - ck.testExactNumber(clipVectorSingleShape.classifyPointContainment([pointAdjustments[0]]), 1, "Inner point should be classified as strongly inside for a single ClipShape"); + ck.testExactNumber( + clipVectorSingleShape.classifyPointContainment([pointAdjustments[0]]), + 1, + "Inner point should be classified as strongly inside for a single ClipShape", + ); if (pointAdjustments[1]) - ck.testExactNumber(clipVectorSingleShape.classifyPointContainment([pointAdjustments[1]]), 3, "Outer point should be strongly outside for single ClipShape, given it is the only point."); + ck.testExactNumber( + clipVectorSingleShape.classifyPointContainment([pointAdjustments[1]]), + 3, + "Outer point should be strongly outside for single ClipShape, given it is the only point.", + ); if (pointAdjustments[0] && pointAdjustments[1]) - ck.testExactNumber(clipVectorSingleShape.classifyPointContainment([pointAdjustments[0], pointAdjustments[1]]), 2, "Array of outer AND inner points should return ambiguous for single ClipShape"); + ck.testExactNumber( + clipVectorSingleShape.classifyPointContainment([pointAdjustments[0], pointAdjustments[1]]), + 2, + "Array of outer AND inner points should return ambiguous for single ClipShape", + ); } } // Ensure that pointInside check only passes for points within intersecting ClipShapes @@ -287,7 +334,8 @@ describe("ClipVector", () => { const ck = new Checker(); const vectorLen = clipVector012.clips.length; const lastShape = clipVector012.clips[vectorLen - 1] as ClipShape; - const expClipMask = ClipMaskXYZRangePlanes.XAndY | (lastShape.zLowValid ? ClipMaskXYZRangePlanes.ZLow : 0) | (lastShape.zHighValid ? ClipMaskXYZRangePlanes.ZHigh : 0); + const expClipMask = ClipMaskXYZRangePlanes.XAndY | (lastShape.zLowValid ? ClipMaskXYZRangePlanes.ZLow : 0) | + (lastShape.zHighValid ? ClipMaskXYZRangePlanes.ZHigh : 0); let expZLow = -Number.MAX_VALUE; let expZHigh = Number.MAX_VALUE; let zLowFound = false; @@ -312,9 +360,15 @@ describe("ClipVector", () => { ck.testExactNumber(expZLow, retVal[1], "zLow returned matches expected"); ck.testExactNumber(expZHigh, retVal[2], "zHigh returned matches expected"); for (let loopNum = 0; loopNum < loopPoints.length; loopNum++) { - ck.testTrue(loopPoints[loopNum].length === (clipVector012.clips[loopNum] as ClipShape).polygon.length, "Extracted point array is of same length as ClipShape polygon"); + ck.testTrue( + loopPoints[loopNum].length === (clipVector012.clips[loopNum] as ClipShape).polygon.length, + "Extracted point array is of same length as ClipShape polygon", + ); for (let pointNum = 0; pointNum < loopPoints[loopNum].length; pointNum++) - ck.testTrue(loopPoints[loopNum][pointNum].isAlmostEqual((clipVector012.clips[loopNum] as ClipShape).polygon[pointNum]), "Extracted point matches point in ClipShape polygon array"); + ck.testTrue( + loopPoints[loopNum][pointNum].isAlmostEqual((clipVector012.clips[loopNum] as ClipShape).polygon[pointNum]), + "Extracted point matches point in ClipShape polygon array", + ); } // TODO: Attempt the same check, with member transforms in each of the ClipShapes s.t. the points are transformed as they are extracted @@ -378,10 +432,26 @@ describe("StringifiedClipVector", () => { // const innerCircle = Sample.createArcStrokes(2, Point3d.create(5, 4), 12.0, Angle.createDegrees(12), Angle.createDegrees(372)); const innerCircle = Sample.createArcStrokes(2, Point3d.create(0, 0), 5.0, Angle.createDegrees(0), Angle.createDegrees(360)); const innerU = [[2, 1], [4, 2], [4, 5], [5, 6], [5, 2], [8, 1], [9, 8], [3, 7], [2, 1]]; - const twoInletsWithWhisker = [[2, 1], [4, 2], [4, 5], [5, 6], [5, 2], [8, 1], - [10, 8], [5, 8], [5, 9], [9, 9], [9, 12], - [10, 13], [12, 13], [10, 13], [9, 12], - [7, 11], [3, 12], [2, 1]]; + const twoInletsWithWhisker = [ + [2, 1], + [4, 2], + [4, 5], + [5, 6], + [5, 2], + [8, 1], + [10, 8], + [5, 8], + [5, 9], + [9, 9], + [9, 12], + [10, 13], + [12, 13], + [10, 13], + [9, 12], + [7, 11], + [3, 12], + [2, 1], + ]; const innerDart = [ [0, 0], [-6, -8], @@ -420,7 +490,23 @@ describe("StringifiedClipVector", () => { // const polygonToClip = Sample.createArcStrokes(3, Point3d.create(5, 5), 6.0, Angle.createDegrees(0), Angle.createDegrees(360)); const polygonToClip = Sample.createRectangleXY(-5, -10, 30, 30); const y0 = 0; - const allJson = [jsonTriangle, jsonOutsideCircle, jsonCircle, jsonTriangleTrans, jsonDart1Trans, jsonTwoInlets, jsonTwoInletsReversed, jsonDart, jsonDart1, jsonDart, jsonTriangle, jsonC, jsonCircle, jsonD, jsonDart]; + const allJson = [ + jsonTriangle, + jsonOutsideCircle, + jsonCircle, + jsonTriangleTrans, + jsonDart1Trans, + jsonTwoInlets, + jsonTwoInletsReversed, + jsonDart, + jsonDart1, + jsonDart, + jsonTriangle, + jsonC, + jsonCircle, + jsonD, + jsonDart, + ]; const shortJson = [jsonOuter, jsonTriangle]; const activeJson = doLongTest ? allJson : shortJson; for (const json of activeJson) { @@ -443,35 +529,34 @@ describe("StringifiedClipVector", () => { it("OuterAndMaskLargeCoordinateAndTransform", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const clip1 = - [ - { - shape: { - points: [[0, 0], [97.608056, 0], [-11.108483, 98.118449], [0, 0]], - transA: [ - [-0.704754, 0.709452, 0, 99560.076989], - [-0.709452, -0.704754, 0, 80175.346101], - [0, 0, 1, 0], - ], - }, + const clip1 = [ + { + shape: { + points: [[0, 0], [97.608056, 0], [-11.108483, 98.118449], [0, 0]], + transA: [ + [-0.704754, 0.709452, 0, 99560.076989], + [-0.709452, -0.704754, 0, 80175.346101], + [0, 0, 1, 0], + ], }, - { - shape: { - mask: true, - points: [ - [28.449347, 15.11684], - [5.096967, 59.735151], - [83.292234, 6.542878], - [28.449347, 15.11684], - ], - transA: [ - [-0.704754, 0.709452, 0, 99560.076989], - [-0.709452, -0.704754, 0, 80175.346101], - [0, 0, 1, 0], - ], - }, + }, + { + shape: { + mask: true, + points: [ + [28.449347, 15.11684], + [5.096967, 59.735151], + [83.292234, 6.542878], + [28.449347, 15.11684], + ], + transA: [ + [-0.704754, 0.709452, 0, 99560.076989], + [-0.709452, -0.704754, 0, 80175.346101], + [0, 0, 1, 0], + ], }, - ]; + }, + ]; const _extraClipper = ClipPrimitive.fromJSON( { shape: { @@ -485,7 +570,8 @@ describe("StringifiedClipVector", () => { zhigh: 5.001e-4, zlow: -5.0005e-4, }, - }); + }, + ); let x0 = 0; const y0 = 0; @@ -517,10 +603,26 @@ describe("StringifiedClipVector", () => { // const innerCircle = Sample.createArcStrokes(2, Point3d.create(5, 4), 12.0, Angle.createDegrees(12), Angle.createDegrees(372)); const innerCircle = Sample.createArcStrokes(2, Point3d.create(0, 0), 5.0, Angle.createDegrees(0), Angle.createDegrees(360)); const innerU = [[2, 1], [4, 2], [4, 5], [5, 6], [5, 2], [8, 1], [9, 8], [3, 7], [2, 1]]; - const twoInletsWithWhisker = [[2, 1], [4, 2], [4, 5], [5, 6], [5, 2], [8, 1], - [10, 8], [5, 8], [5, 9], [9, 9], [9, 12], - [10, 13], [12, 13], [10, 13], [9, 12], - [7, 11], [3, 12], [2, 1]]; + const twoInletsWithWhisker = [ + [2, 1], + [4, 2], + [4, 5], + [5, 6], + [5, 2], + [8, 1], + [10, 8], + [5, 8], + [5, 9], + [9, 9], + [9, 12], + [10, 13], + [12, 13], + [10, 13], + [9, 12], + [7, 11], + [3, 12], + [2, 1], + ]; const innerDart = [ [0, 0], [-6, -8], @@ -557,7 +659,25 @@ describe("StringifiedClipVector", () => { // const polygonToClip = Sample.createArcStrokes(3, Point3d.create(5, 5), 6.0, Angle.createDegrees(0), Angle.createDegrees(360)); const polygonToClip = Sample.createRectangleXY(-10, -10, 30, 30); const y0 = 0; - for (const json of [jsonOutsideCircle, jsonCircle, jsonTriangle, jsonTriangleTrans, jsonDart1Trans, jsonTwoInlets, jsonTwoInletsReversed, jsonDart, jsonDart1, jsonDart, jsonTriangle, jsonC, jsonCircle, jsonD, jsonDart]) { + for ( + const json of [ + jsonOutsideCircle, + jsonCircle, + jsonTriangle, + jsonTriangleTrans, + jsonDart1Trans, + jsonTwoInlets, + jsonTwoInletsReversed, + jsonDart, + jsonDart1, + jsonDart, + jsonTriangle, + jsonC, + jsonCircle, + jsonD, + jsonDart, + ] + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, GrowableXYZArray.create(outer), x0, y0); const primitive = ClipPrimitive.fromJSON(json[json.length - 1]); const clipVector = ClipVector.fromJSON(json); @@ -582,10 +702,8 @@ describe("StringifiedClipVector", () => { ck.testLT(2 * b, a, "Confirm diamonds will fit well within outer rectangle -- needed for test conditions."); const outerPoints = Sample.createCenteredRectangleXY(0, 0, 2 * a, a); const outerRange = Range3d.createArray(outerPoints); - const leftHolePoints = Sample.createArcStrokes(1, Point3d.create(-a, 0, 0), 2 * b, - Angle.createDegrees(0), Angle.createDegrees(360), true, 0); - const rightHolePoints = Sample.createArcStrokes(1, Point3d.create(a, 0, 0), b, - Angle.createDegrees(0), Angle.createDegrees(360), true, 0); + const leftHolePoints = Sample.createArcStrokes(1, Point3d.create(-a, 0, 0), 2 * b, Angle.createDegrees(0), Angle.createDegrees(360), true, 0); + const rightHolePoints = Sample.createArcStrokes(1, Point3d.create(a, 0, 0), b, Angle.createDegrees(0), Angle.createDegrees(360), true, 0); const leftRange = Range3d.createArray(leftHolePoints); const rightRange = Range3d.createArray(rightHolePoints); const outerPrimitive = ClipShape.createShape(outerPoints, undefined, undefined, undefined, false)!; @@ -601,7 +719,8 @@ describe("StringifiedClipVector", () => { const outPoints = [ Point3d.create(-a, 0), Point3d.create(a, 0), - outerRange.fractionToPoint(e0, e1)]; + outerRange.fractionToPoint(e0, e1), + ]; GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 2, inPoints, 0.4, x0, y0); GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, outPoints, 0.4, x0, y0); for (const point of inPoints) @@ -619,23 +738,25 @@ describe("StringifiedClipVector", () => { drawTheBoundaries(x0, y1); drawTheBoundaries(x0, y2); - for (const testCase of [ - { range: outerRange, isHole: false }, - { range: leftRange, isHole: true }, - { range: rightRange, isHole: true }]) { + for ( + const testCase of [ + { range: outerRange, isHole: false }, + { range: leftRange, isHole: true }, + { range: rightRange, isHole: true }, + ] + ) { // do some clips for display ... const fractionYA = 0.5; const fractionYC = 1.4; const pointA = testCase.range.fractionToPoint(0.5, fractionYA); const pointB = testCase.range.fractionToPoint(0.55, 0.6); const fractionInRange = (1.0 - fractionYA) / (fractionYC - fractionYA); - const pointC = testCase.range.fractionToPoint(0.5, fractionYC); // One half of this is in the range + const pointC = testCase.range.fractionToPoint(0.5, fractionYC); // One half of this is in the range const lengthAC = pointA.distance(pointC); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [pointA, pointB, pointC, pointA], x0, y1); - ClipUtilities.announcePolylineClip(clipVector, [pointA, pointB, pointC, pointA], - (clippedPoint0: Point3d, clippedPoint1: Point3d) => { - GeometryCoreTestIO.captureCloneGeometry(allGeometry, [clippedPoint0, clippedPoint1], x0, y2); - }); + ClipUtilities.announcePolylineClip(clipVector, [pointA, pointB, pointC, pointA], (clippedPoint0: Point3d, clippedPoint1: Point3d) => { + GeometryCoreTestIO.captureCloneGeometry(allGeometry, [clippedPoint0, clippedPoint1], x0, y2); + }); // Test some clipped lengths .. // We know the holes are symmetric in their ranges and deeply buried, strokes from center have predictable clip lengths .. const clippedLength = ClipUtilities.sumPolylineClipLength(clipVector, [pointA, pointC]); @@ -660,7 +781,15 @@ describe("StringifiedClipVector", () => { }); }); -function exerciseClipVector(ck: Checker, allGeometry: GeometryQuery[], cv: ClipVector, polygonToClip: Point3d[], testDensity: number, x0: number, y0: number) { +function exerciseClipVector( + ck: Checker, + allGeometry: GeometryQuery[], + cv: ClipVector, + polygonToClip: Point3d[], + testDensity: number, + x0: number, + y0: number, +) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, polygonToClip, x0, y0); const range = Range3d.createArray(polygonToClip); // const a = 2 * range.yLength(); @@ -695,9 +824,15 @@ function exerciseClipVector(ck: Checker, allGeometry: GeometryQuery[], cv: ClipV } } } -export function exerciseClipPrimitive(ck: Checker, allGeometry: GeometryQuery[], primitive: ClipPrimitive, polygonToClip: Point3d[], +export function exerciseClipPrimitive( + ck: Checker, + allGeometry: GeometryQuery[], + primitive: ClipPrimitive, + polygonToClip: Point3d[], expectContainment: boolean, // true if caller expects that the primitive shape is contained in the polygonToClip - x0: number, y0: number) { + x0: number, + y0: number, +) { const range2 = Range3d.createArray(polygonToClip); GeometryCoreTestIO.captureCloneGeometry(allGeometry, polygonToClip, x0, y0); if (primitive instanceof ClipShape) { diff --git a/core/geometry/src/test/clipping/CutFill.test.ts b/core/geometry/src/test/clipping/CutFill.test.ts index 5e69d55881b3..c671ac97591f 100644 --- a/core/geometry/src/test/clipping/CutFill.test.ts +++ b/core/geometry/src/test/clipping/CutFill.test.ts @@ -4,18 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; +import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; import { GeometryQuery } from "../../curve/GeometryQuery"; -import { Checker } from "../Checker"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { ClippedPolyfaceBuilders, PolyfaceClip } from "../../polyface/PolyfaceClip"; +import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; +import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { IndexedPolyface, Polyface } from "../../polyface/Polyface"; -import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; -import { Sample } from "../../serialization/GeometrySamples"; -import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; +import { ClippedPolyfaceBuilders, PolyfaceClip } from "../../polyface/PolyfaceClip"; import { PolyfaceQuery } from "../../polyface/PolyfaceQuery"; -import { GrowableXYZArray } from "../../geometry3d/GrowableXYZArray"; +import { Sample } from "../../serialization/GeometrySamples"; +import { Checker } from "../Checker"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function clipMeshToRange(range: Range3d, mesh: Polyface): { inside: Polyface | undefined, outside: Polyface | undefined } { const clipper = ConvexClipPlaneSet.createRange3dPlanes(range); @@ -88,7 +88,17 @@ function createVolumeBelowSurfaceMeshInRange(mesh: IndexedPolyface, clipRange: R } function createSampleUndulatingSurface(numX: number, numY: number): IndexedPolyface { - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 1), Vector3d.create(1, 0.1, 0.3), Vector3d.create(-0.2, 1, 0.5), numX, numY, false, false, false, true); + const mesh = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 1), + Vector3d.create(1, 0.1, 0.3), + Vector3d.create(-0.2, 1, 0.5), + numX, + numY, + false, + false, + false, + true, + ); PolyfaceQuery.markAllEdgeVisibility(mesh, true); // introduce some wobble in the z direction to make the surface more interesting ... const workPoint = Point3d.create(); @@ -124,7 +134,6 @@ describe("CutFill", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CutFill", "RangeBoxClipA"); expect(ck.getNumErrors()).toBe(0); } - }); it("RangeBoxClipB", () => { const ck = new Checker(); @@ -135,10 +144,12 @@ describe("CutFill", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, x0, y0); y0 += 12.0; const allRanges = []; - allRanges.push(Range3d.createXYZXYZ(-2, -2, -1, 10, 10, 5), + allRanges.push( + Range3d.createXYZXYZ(-2, -2, -1, 10, 10, 5), Range3d.createXYZXYZ(1, 2, -3, 5, 10, 10), Range3d.createXYZXYZ(0.5, 0.5, -1, 5.2, 5.8, 10), - Range3d.createXYZXYZ(-1, -1, 1, 10, 8, 3.0)); + Range3d.createXYZXYZ(-1, -1, 1, 10, 8, 3.0), + ); for (const clipRange of allRanges) { x0 += 20.0; GeometryCoreTestIO.captureRangeEdges(allGeometry, clipRange, x0, y0); @@ -152,5 +163,4 @@ describe("CutFill", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CutFill", "RangeBoxClipB"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/clipping/PolyfaceClip.test.ts b/core/geometry/src/test/clipping/PolyfaceClip.test.ts index 70dc7da4e4b0..a635f9840e4a 100644 --- a/core/geometry/src/test/clipping/PolyfaceClip.test.ts +++ b/core/geometry/src/test/clipping/PolyfaceClip.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; -import * as fs from "fs"; import { compareWithTolerance, OrderedSet } from "@itwin/core-bentley"; +import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { ClipPlane } from "../../clipping/ClipPlane"; import { ClipUtilities } from "../../clipping/ClipUtils"; import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; @@ -64,7 +64,14 @@ function raggedVolume(mesh: Polyface): { volume: number, volumeDifferenceRelativ return { volume: volume0.volume, volumeDifferenceRelativeError: Geometry.safeDivideFraction(volumeDifference, Math.abs(volume0.volume), 1000.0) }; } -function shiftZInXYFractionRange(mesh: Polyface, lowXFraction: number, lowYFraction: number, highXFraction: number, highYFraction: number, deltaZ: number) { +function shiftZInXYFractionRange( + mesh: Polyface, + lowXFraction: number, + lowYFraction: number, + highXFraction: number, + highYFraction: number, + deltaZ: number, +) { const points = mesh.data.point; const rangeA = mesh.range(); const lowPoint = rangeA.localXYZToWorld(lowXFraction, lowYFraction, 0)!; @@ -98,7 +105,6 @@ describe("PolyfaceClip", () => { ck.testCoordinate(area, areaLeft + areaRight); GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "ClipPlane"); expect(ck.getNumErrors()).toBe(0); - }); it("EdgeInClipPlane", () => { @@ -118,7 +124,6 @@ describe("PolyfaceClip", () => { ck.testCoordinate(area, areaLeft + areaRight); GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "EdgeInClipPlane"); expect(ck.getNumErrors()).toBe(0); - }); it("ConvexClipPlaneSet", () => { @@ -164,9 +169,29 @@ describe("PolyfaceClip", () => { const xEdges = 4; const yEdges = 5; const polyfaceP3 = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), vectorU, vectorV, xEdges + 1, yEdges + 1); - const polyfaceP4 = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), vectorU, vectorV, xEdges + 1, yEdges + 1, false, false, false, false); + const polyfaceP4 = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + vectorU, + vectorV, + xEdges + 1, + yEdges + 1, + false, + false, + false, + false, + ); const polyfaceQ3 = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), vectorU.scale(xEdges), vectorV.scale(yEdges), 2, 2); - const polyfaceQ4 = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), vectorU.scale(xEdges), vectorV.scale(yEdges), 2, 2, false, false, false, false); + const polyfaceQ4 = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + vectorU.scale(xEdges), + vectorV.scale(yEdges), + 2, + 2, + false, + false, + false, + false, + ); for (const polyface of [polyfaceQ4, polyfaceP3, polyfaceQ3, polyfaceP4]) { const range = polyface.range(); const dY = range.yLength() * 1.5; @@ -208,12 +233,10 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyfaceB1, x0, y0 + 3 * dY, 0); const boundaryB1 = PolyfaceQuery.boundaryEdges(polyfaceB1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, boundaryB1, x0, y0 + 3 * dY, dZ); - } if (!ck.testCoordinate(area, areaA + areaB, " sum of inside and outside clip areas")) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface, x0, y0 + 5 * dY, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, clipperEdges, x0, y0 + 5 * dY, 0); - } x0 += dX; @@ -267,7 +290,6 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.captureGeometry(allGeometry, polyfaceP, 5, 0, 0); GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "addPolygon"); expect(ck.getNumErrors()).toBe(0); - }); it("Section", () => { @@ -277,12 +299,17 @@ describe("PolyfaceClip", () => { const zShift = 0.01; for (const multiplier of [1, 3]) { x0 += multiplier * 10; - const polyface = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.unitX(), Vector3d.unitY(), 3 * multiplier, 4 * multiplier); + const polyface = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.unitX(), + Vector3d.unitY(), + 3 * multiplier, + 4 * multiplier, + ); if (multiplier > 1) - polyface.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 8.0); - }); + polyface.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 8.0); + }); for (let q = 1; q <= multiplier + 1.5; q++) { const clipper = ClipPlane.createNormalAndPointXYZXYZ(q, 1, 0, q, q, 1)!; const section = PolyfaceClip.sectionPolyfaceClipPlane(polyface, clipper); @@ -295,7 +322,6 @@ describe("PolyfaceClip", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "Section"); expect(ck.getNumErrors()).toBe(0); - }); it("ClosedSection", () => { @@ -316,11 +342,14 @@ describe("PolyfaceClip", () => { const facets = builder.claimPolyface(true); const range = facets.range(); range.expandInPlace(0.5); - for (const clipPlane of [ - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 1, 1, 3)!, - ClipPlane.createNormalAndPointXYZXYZ(1, 0.5, 0.2, 0, 1, 1)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 1, 1, 1, 1, 2)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 2)!]) { + for ( + const clipPlane of [ + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 1, 1, 3)!, + ClipPlane.createNormalAndPointXYZXYZ(1, 0.5, 0.2, 0, 1, 1)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 1, 1, 1, 1, 2)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 2)!, + ] + ) { for (const insideClip of [true, false]) { const clipPlanePoints = clipPlane.intersectRange(range)!; const frame = clipPlane.getFrame(); @@ -341,8 +370,12 @@ describe("PolyfaceClip", () => { } x0 += 30.0; } - ck.testUndefined(PolyfaceBuilder.polygonToTriangulatedPolyface( - [Point3d.create(0, 0), Point3d.create(0, 1)]), "should fail triangulating less than 3 points"); + ck.testUndefined( + PolyfaceBuilder.polygonToTriangulatedPolyface( + [Point3d.create(0, 0), Point3d.create(0, 1)], + ), + "should fail triangulating less than 3 points", + ); GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "ClosedSection"); expect(ck.getNumErrors()).toBe(0); }); @@ -356,11 +389,14 @@ describe("PolyfaceClip", () => { const allGeometry: GeometryQuery[] = []; let x0 = 0; const y0 = 0; - for (const clipPlane of [ - ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 0, -1, 0, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 2, 1, 0, 0, 0)!, - ClipPlane.createNormalAndPointXYZXYZ(0, 2, -1, 0, 0, 0)!]) { + for ( + const clipPlane of [ + ClipPlane.createNormalAndPointXYZXYZ(0, 0, 1, 0, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 0, -1, 0, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 2, 1, 0, 0, 0)!, + ClipPlane.createNormalAndPointXYZXYZ(0, 2, -1, 0, 0, 0)!, + ] + ) { const clipPlanePoints = clipPlane.intersectRange(range)!; const frame = clipPlane.getFrame(); const dy = 2.0 * range.yLength(); @@ -459,86 +495,996 @@ describe("PolyfaceClip", () => { const meshJSON = { indexedMesh: { point: [ - [-1314.6730196637218, -57.10471794754267, -5.490003639162751], [-1314.896312748082, -56.537848295643926, -5.510317207634216], [-1314.8979232803686, -56.533829868771136, -5.3803893105941825], - [-1314.6956910152803, -57.04815019853413, -3.662215652904706], [-1314.9189832430566, -56.48128271847963, -3.6825291425338946], [-1314.7091404076782, -57.0142579190433, -3.1975819905346725], - [-1314.9231749525643, -56.47075137402862, -3.478972522978438], [-1314.9421641827794, -56.42276875022799, -3.0638822874461766], [-1314.7390657665092, -56.93854473717511, -2.7227602402563207], - [-1314.976242534176, -56.336483863182366, -2.6424124827608466], [-1314.7866303779301, -56.81805418152362, -2.2439098892791662], [-1315.0262713459088, -56.209706934168935, -2.220409367873799], - [-1314.834356342326, -56.69708855636418, -1.88633862361894], [-1314.8925853258697, -56.549456998705864, -1.5336732444993686], [-1315.0927135171369, -56.04125931020826, -1.8044034888444003], - [-1314.961282182252, -56.37524692341685, -1.1892659660661593], [-1315.1755565702333, -55.831168909557164, -1.4013555171550252], [-1315.0402223932906, -56.17502646334469, -0.856507872173097], - [-1315.274262645049, -55.58079734817147, -1.0183311252039857], [-1315.1289869659813, -55.949857488274574, -0.5387295018008444], [-1315.3580743367784, -55.368176135234535, -0.7483150090265553], - [-1315.226965778158, -55.70128717646003, -0.2390975789166987], [-1315.4495686356095, -55.13604204170406, -0.4960487415373791], [-1315.333369733533, -55.431317169219255, 0.03948582641896792], - [-1315.5479536699713, -54.88640406168997, -0.2638915148272645], [-1315.652313624567, -54.621586034074426, -0.05384081805823371], [-1315.4472513569053, -55.142351396381855, 0.2944752340845298], - [-1319.4383521693526, -45.007064340636134, -5.923518669005716], [-1319.439963756071, -45.00304323993623, -5.793590867804596], [-1315.5675327406498, -54.83712511882186, 0.5237587880692445], - [-1315.7989962851861, -54.249344075098634, 0.18917484689154662], [-1319.6616452540038, -44.440194689668715, -5.9438322374771815], [-1315.6930391303613, -54.518619729205966, 0.7257155363040511], - [-1315.951936306432, -53.8611929519102, 0.3876608006248716], [-1315.8225359838107, -54.18996868748218, 0.8992497764993459], [-1316.1085139245843, -53.46378275100142, 0.5406269291997887], - [-1315.9547671198961, -53.854360677301884, 1.043801223830087], [-1316.266183029511, -53.063577332533896, 0.6485063915024512], [-1316.0884916253272, -53.5149458842352, 1.1593317580409348], - [-1316.4225866948836, -52.66656098328531, 0.7129976582655217], [-1319.4610235207947, -44.95049659349024, -4.095730682747671], [-1316.2225174400955, -53.17475076112896, 1.2462912875053007], - [-1316.5756449538749, -52.27801544778049, 0.7368380023690406], [-1319.6843166055623, -44.38362694066018, -4.1160442512482405], [-1319.4593420174788, -44.95498723257333, -3.6845272506179754], - [-1316.3997749281116, -52.72479889634997, 1.3193813897960354], [-1319.6824109015288, -44.388716329820454, -3.650013694772497], [-1319.4433784229914, -44.99574109353125, -3.2617125234392006], - [-1316.5732409551856, -52.284447288140655, 1.3464004472771194], [-1319.411973949289, -45.07569708675146, -2.8325225476583], [-1319.6643188276794, -44.43490403983742, -3.1708236702834256], - [-1317.2765918981167, -50.49853556416929, 0.6730709861731157], [-1319.3643031304819, -45.196947483345866, -2.4030360869364813], [-1319.6287270910107, -44.52552083041519, -2.6844083640899044], - [-1319.2999650278944, -45.36050648894161, -1.979977705545025], [-1319.5899691355298, -44.62411019485444, -2.3189694250759203], [-1319.2190551686217, -45.56612777058035, -1.5704381284012925], - [-1317.9176058679004, -48.871206316165626, 0.6147562326223124], [-1319.540610271506, -44.74960973486304, -1.9565164920932148], [-1319.1222068965435, -45.81219966430217, -1.1815293378895149], - [-1318.0697283439804, -48.48499567061663, 0.5631527817167807], [-1319.039797498146, -46.02155460137874, -0.9074735297763254], [-1319.4806025013677, -44.90213949885219, -1.6004006100120023], - [-1318.2241813773871, -48.09284638334066, 0.47038205052376725], [-1318.9497548320796, -46.250277870334685, -0.6514305796881672], [-1318.3788218617556, -47.70019774045795, 0.3340909504913725], - [-1318.8192631817656, -46.58171500824392, -0.34194668068084866], [-1319.4100858065067, -45.08134227246046, -1.2540460220188834], [-1318.5312560963794, -47.3131257770583, 0.1530131880135741], - [-1318.6789329773746, -46.93810682557523, -0.07282068848144263], [-1317.9351099316264, -48.82709795888513, 1.2225075878959615], [-1319.3293957076385, -45.286364460363984, -0.920851907460019], - [-1318.1075154047576, -48.38939256221056, 1.164023675955832], [-1319.2390624813852, -45.51585812214762, -0.6040887353592552], [-1318.282562176406, -47.944956701248884, 1.0588835139351431], - [-1319.139801532845, -45.76800546422601, -0.3067954441939946], [-1318.414131053025, -47.61089193448424, 0.9477621258411091], [-1319.032495127176, -46.040565280243754, -0.0316839705046732], - [-1318.5446913255146, -47.2793722813949, 0.8081888991291635], [-1318.9181664104108, -46.330938938073814, 0.2189426910772454], [-1318.6730424726848, -46.95344530697912, 0.6399315853777807], - [-1318.7979473226587, -46.63625187240541, 0.44325374250183813], [-1306.8970196380978, -54.03787715174258, -5.383082429820206], [-1307.1203127235058, -53.471007496118546, -5.403395998291671], - [-1307.123446831596, -53.46758996602148, -5.273489050625358], [-1306.9411242355127, -53.98976263590157, -3.5555891540134326], [-1307.164416463871, -53.42289515584707, -3.575902643526206], - [-1306.960030266142, -53.958022441715, -3.091030521376524], [-1307.1709969213116, -53.41330592986196, -3.372378869680688], [-1307.1948683849187, -53.36724884994328, -2.9573557656549383], - [-1306.9955491531873, -53.884515340439975, -2.6162856828595977], [-1307.2339197730762, -53.282925319857895, -2.535954341001343], [-1307.0487732768524, -53.76625688839704, -2.137513151013991], - [-1307.288944863947, -53.158118915744126, -2.1140199257060885], [-1307.100738369627, -53.64696316886693, -1.7800001740106381], [-1307.1631602107664, -53.50098526477814, -1.4273924473382067], - [-1307.3603305587312, -52.991621006280184, -1.6980820209137164], [-1307.2359643492382, -53.32839509379119, -1.0830416447133757], [-1307.4479828339536, -52.783427353948355, -1.2951001767651178], - [-1307.3188863100368, -53.129745027050376, -0.7503383005096111], [-1307.5512804948376, -52.53486670553684, -0.9121389198116958], [-1307.4114676423487, -52.90608137752861, -0.4326124111539684], - [-1307.6383442233782, -52.32352809049189, -0.6421675197198056], [-1307.5130604805308, -52.65893642697483, -0.133030181779759], [-1307.7328908390482, -52.092597825452685, -0.3899432220205199], - [-1307.6228408953757, -52.39029809460044, 0.1455067968054209], [-1307.834099994041, -51.84407367184758, -0.15782482747454196], [-1307.9410314990673, -51.58026986103505, 0.052190510177752], - [-1307.7398305887473, -52.10255813319236, 0.4004534680279903], [-1311.6623521425645, -41.94022354390472, -5.816597459604964], [-1311.665487305203, -41.9368033381179, -5.686690607864875], - [-1307.862925764406, -51.798441612161696, 0.6296983319043647], [-1308.090716930572, -51.209212188608944, 0.29516488648368977], [-1311.8856452268665, -41.373353890143335, -5.836911028047325], - [-1307.9909314328688, -51.48092193715274, 0.8316207147436216], [-1308.2461448091199, -50.82204227428883, 0.4936166317493189], [-1308.1225989012164, -51.1531269820407, 1.0051251085824333], - [-1308.4046809814172, -50.425404525361955, 0.6465558299678378], [-1308.2566640858422, -50.818242316134274, 1.1496513374440838], [-1308.5637816990493, -50.025763732381165, 0.7544156073709019], - [-1308.3918843068532, -50.47941743209958, 1.2651613053458277], [-1308.7211074174847, -49.62911103852093, 0.8188941958360374], [-1311.7064567398047, -41.89210902992636, -3.98910418379819], - [-1308.5270715028164, -50.13968035392463, 1.3521048656548373], [-1308.874608016049, -49.24073995836079, 0.8427284576755483], [-1311.9297498240485, -41.32523937523365, -4.009417752240552], - [-1311.7095899169217, -41.89849856868386, -3.5779669542971533], [-1308.7053739842377, -49.69014063291252, 1.4251805990934372], [-1308.8793413292733, -49.249986744485795, 1.452192763419589], - [-1311.6985617888859, -41.94119896925986, -3.1552200905571226], [-1311.933300757897, -41.3324808543548, -3.5434622254688293], [-1311.6721510011703, -42.023124465718865, -2.726098778686719], - [-1309.575554959767, -47.461260076612234, 0.7789614414214157], [-1311.920802212495, -41.38087464310229, -3.0643491127702873], [-1311.6294600100373, -42.14633889589459, -2.296680791361723], - [-1311.8908699883032, -41.473723533563316, -2.578011625824729], [-1311.5700086812722, -42.31182523816824, -1.873689603904495], [-1311.8563511604443, -41.57398480270058, -2.21263097555493], - [-1311.4938095906982, -42.51930443570018, -1.464214800595073], [-1310.2165689287358, -45.83393083047122, 0.7206466880161315], [-1311.8111851541325, -41.70113799907267, -1.8502356949611567], - [-1311.4014134522877, -42.76713224314153, -1.0753672275459394], [-1310.3682490662322, -45.447545723989606, 0.6690493192581926], [-1311.3221262866864, -42.97771858703345, -0.801354350609472], - [-1311.755284666433, -41.85528766736388, -1.494176288601011], [-1310.5217800466344, -45.05503278132528, 0.5762912663631141], [-1311.2349867338198, -43.207586833275855, -0.5453513188112993], - [-1310.6749889180646, -44.66181951202452, 0.44001985117211007], [-1311.1079810556257, -43.54039883520454, -0.23591535238665529], [-1310.8254645981942, -44.27397509943694, 0.2589690191671252], - [-1310.9706536214217, -43.89797494281083, 0.03316935116890818], [-1311.6887497214484, -42.03606083616614, -1.1478764503262937], [-1310.2412103049573, -45.79263741709292, 1.3282999040384311], - [-1311.6118763824343, -42.24258834775537, -0.814734816813143], [-1310.413114460418, -45.35473429784179, 1.2698228852823377], [-1311.5251571819535, -42.47350737452507, -0.4980213381059002], - [-1310.5871162380208, -44.90988629497588, 1.1646970921137836], [-1311.42927269364, -42.72698638681322, -0.200774473749334], [-1310.7175237335614, -44.575363480485976, 1.053591673146002], - [-1311.3250743568642, -43.00077202171087, 0.07429426346789114], [-1310.8465882905875, -44.24325392302126, 0.9140390128304716], [-1311.2135594324209, -43.29225543513894, 0.3248822349414695], - [-1310.9731053883443, -43.91660360060632, 0.7458069174608681], [-1311.0958396244678, -43.59855407383293, 0.5491589208832011]], - pointIndex: [84, 83, 1, 2, 0, 83, 86, 4, 1, 0, 86, 88, 6, 4, 0, 88, 91, 9, 6, 0, 91, 93, 11, 9, 0, 93, 95, 13, 11, 0, 95, 96, 14, 13, 0, 96, 98, 16, 14, 0, 98, 100, 18, 16, 0, 100, 102, 20, 18, 0, - 102, 104, 22, 20, 0, 104, 106, 24, 22, 0, 106, 109, 27, 24, 0, 109, 112, 30, 27, 0, 112, 115, 33, 30, 0, 115, 117, 35, 33, 0, 117, 119, 37, 35, 0, 119, 121, 39, 37, 0, 121, 124, 42, 39, 0, - 124, 128, 46, 42, 0, 128, 129, 49, 46, 0, 129, 153, 71, 49, 0, 153, 155, 73, 71, 0, 155, 157, 75, 73, 0, 157, 159, 77, 75, 0, 159, 161, 79, 77, 0, 161, 163, 81, 79, 0, 163, 164, 82, 81, 0, - 164, 162, 80, 82, 0, 162, 160, 78, 80, 0, 160, 158, 76, 78, 0, 158, 156, 74, 76, 0, 156, 154, 72, 74, 0, 154, 152, 68, 72, 0, 152, 145, 63, 68, 0, 145, 141, 59, 63, 0, 141, 138, 56, 59, 0, - 138, 136, 54, 56, 0, 136, 134, 51, 54, 0, 134, 131, 47, 51, 0, 131, 126, 44, 47, 0, 126, 114, 32, 44, 0, 114, 110, 28, 32, 0, 110, 111, 29, 28, 0, 111, 123, 41, 29, 0, 123, 127, 45, 41, 0, - 127, 130, 48, 45, 0, 130, 132, 50, 48, 0, 132, 135, 53, 50, 0, 135, 137, 55, 53, 0, 137, 139, 57, 55, 0, 139, 142, 60, 57, 0, 142, 144, 62, 60, 0, 144, 147, 65, 62, 0, 147, 149, 67, 65, 0, - 149, 151, 70, 67, 0, 151, 150, 69, 70, 0, 150, 148, 66, 69, 0, 148, 146, 64, 66, 0, 146, 143, 61, 64, 0, 143, 140, 58, 61, 0, 140, 133, 52, 58, 0, 133, 125, 43, 52, 0, 125, 122, 40, 43, 0, - 122, 120, 38, 40, 0, 120, 118, 36, 38, 0, 118, 116, 34, 36, 0, 116, 113, 31, 34, 0, 113, 108, 26, 31, 0, 108, 107, 25, 26, 0, 107, 105, 23, 25, 0, 105, 103, 21, 23, 0, 103, 101, 19, 21, 0, - 101, 99, 17, 19, 0, 99, 97, 15, 17, 0, 97, 94, 12, 15, 0, 94, 92, 10, 12, 0, 92, 90, 8, 10, 0, 90, 89, 7, 8, 0, 89, 87, 5, 7, 0, 87, 85, 3, 5, 0, 85, 84, 2, 3, 0, - 2, 1, 4, 6, 9, 11, 13, 14, 16, 18, 20, 22, 24, 27, 30, 33, 35, 37, 39, 42, 46, 49, 71, 73, 75, 77, 79, 81, 82, 80, 78, 76, 74, 72, 68, 63, 59, 56, 54, 51, 47, 44, 32, 28, 29, 41, 45, 48, 50, 53, 55, 57, 60, 62, 65, 67, 70, 69, 66, 64, 61, 58, 52, 43, 40, 38, 36, 34, 31, 26, 25, 23, 21, 19, 17, 15, 12, 10, 8, 7, 5, 3, 0, + [-1314.6730196637218, -57.10471794754267, -5.490003639162751], + [-1314.896312748082, -56.537848295643926, -5.510317207634216], + [-1314.8979232803686, -56.533829868771136, -5.3803893105941825], + [-1314.6956910152803, -57.04815019853413, -3.662215652904706], + [-1314.9189832430566, -56.48128271847963, -3.6825291425338946], + [-1314.7091404076782, -57.0142579190433, -3.1975819905346725], + [-1314.9231749525643, -56.47075137402862, -3.478972522978438], + [-1314.9421641827794, -56.42276875022799, -3.0638822874461766], + [-1314.7390657665092, -56.93854473717511, -2.7227602402563207], + [-1314.976242534176, -56.336483863182366, -2.6424124827608466], + [-1314.7866303779301, -56.81805418152362, -2.2439098892791662], + [-1315.0262713459088, -56.209706934168935, -2.220409367873799], + [-1314.834356342326, -56.69708855636418, -1.88633862361894], + [-1314.8925853258697, -56.549456998705864, -1.5336732444993686], + [-1315.0927135171369, -56.04125931020826, -1.8044034888444003], + [-1314.961282182252, -56.37524692341685, -1.1892659660661593], + [-1315.1755565702333, -55.831168909557164, -1.4013555171550252], + [-1315.0402223932906, -56.17502646334469, -0.856507872173097], + [-1315.274262645049, -55.58079734817147, -1.0183311252039857], + [-1315.1289869659813, -55.949857488274574, -0.5387295018008444], + [-1315.3580743367784, -55.368176135234535, -0.7483150090265553], + [-1315.226965778158, -55.70128717646003, -0.2390975789166987], + [-1315.4495686356095, -55.13604204170406, -0.4960487415373791], + [-1315.333369733533, -55.431317169219255, 0.03948582641896792], + [-1315.5479536699713, -54.88640406168997, -0.2638915148272645], + [-1315.652313624567, -54.621586034074426, -0.05384081805823371], + [-1315.4472513569053, -55.142351396381855, 0.2944752340845298], + [-1319.4383521693526, -45.007064340636134, -5.923518669005716], + [-1319.439963756071, -45.00304323993623, -5.793590867804596], + [-1315.5675327406498, -54.83712511882186, 0.5237587880692445], + [-1315.7989962851861, -54.249344075098634, 0.18917484689154662], + [-1319.6616452540038, -44.440194689668715, -5.9438322374771815], + [-1315.6930391303613, -54.518619729205966, 0.7257155363040511], + [-1315.951936306432, -53.8611929519102, 0.3876608006248716], + [-1315.8225359838107, -54.18996868748218, 0.8992497764993459], + [-1316.1085139245843, -53.46378275100142, 0.5406269291997887], + [-1315.9547671198961, -53.854360677301884, 1.043801223830087], + [-1316.266183029511, -53.063577332533896, 0.6485063915024512], + [-1316.0884916253272, -53.5149458842352, 1.1593317580409348], + [-1316.4225866948836, -52.66656098328531, 0.7129976582655217], + [-1319.4610235207947, -44.95049659349024, -4.095730682747671], + [-1316.2225174400955, -53.17475076112896, 1.2462912875053007], + [-1316.5756449538749, -52.27801544778049, 0.7368380023690406], + [-1319.6843166055623, -44.38362694066018, -4.1160442512482405], + [-1319.4593420174788, -44.95498723257333, -3.6845272506179754], + [-1316.3997749281116, -52.72479889634997, 1.3193813897960354], + [-1319.6824109015288, -44.388716329820454, -3.650013694772497], + [-1319.4433784229914, -44.99574109353125, -3.2617125234392006], + [-1316.5732409551856, -52.284447288140655, 1.3464004472771194], + [-1319.411973949289, -45.07569708675146, -2.8325225476583], + [-1319.6643188276794, -44.43490403983742, -3.1708236702834256], + [-1317.2765918981167, -50.49853556416929, 0.6730709861731157], + [-1319.3643031304819, -45.196947483345866, -2.4030360869364813], + [-1319.6287270910107, -44.52552083041519, -2.6844083640899044], + [-1319.2999650278944, -45.36050648894161, -1.979977705545025], + [-1319.5899691355298, -44.62411019485444, -2.3189694250759203], + [-1319.2190551686217, -45.56612777058035, -1.5704381284012925], + [-1317.9176058679004, -48.871206316165626, 0.6147562326223124], + [-1319.540610271506, -44.74960973486304, -1.9565164920932148], + [-1319.1222068965435, -45.81219966430217, -1.1815293378895149], + [-1318.0697283439804, -48.48499567061663, 0.5631527817167807], + [-1319.039797498146, -46.02155460137874, -0.9074735297763254], + [-1319.4806025013677, -44.90213949885219, -1.6004006100120023], + [-1318.2241813773871, -48.09284638334066, 0.47038205052376725], + [-1318.9497548320796, -46.250277870334685, -0.6514305796881672], + [-1318.3788218617556, -47.70019774045795, 0.3340909504913725], + [-1318.8192631817656, -46.58171500824392, -0.34194668068084866], + [-1319.4100858065067, -45.08134227246046, -1.2540460220188834], + [-1318.5312560963794, -47.3131257770583, 0.1530131880135741], + [-1318.6789329773746, -46.93810682557523, -0.07282068848144263], + [-1317.9351099316264, -48.82709795888513, 1.2225075878959615], + [-1319.3293957076385, -45.286364460363984, -0.920851907460019], + [-1318.1075154047576, -48.38939256221056, 1.164023675955832], + [-1319.2390624813852, -45.51585812214762, -0.6040887353592552], + [-1318.282562176406, -47.944956701248884, 1.0588835139351431], + [-1319.139801532845, -45.76800546422601, -0.3067954441939946], + [-1318.414131053025, -47.61089193448424, 0.9477621258411091], + [-1319.032495127176, -46.040565280243754, -0.0316839705046732], + [-1318.5446913255146, -47.2793722813949, 0.8081888991291635], + [-1318.9181664104108, -46.330938938073814, 0.2189426910772454], + [-1318.6730424726848, -46.95344530697912, 0.6399315853777807], + [-1318.7979473226587, -46.63625187240541, 0.44325374250183813], + [-1306.8970196380978, -54.03787715174258, -5.383082429820206], + [-1307.1203127235058, -53.471007496118546, -5.403395998291671], + [-1307.123446831596, -53.46758996602148, -5.273489050625358], + [-1306.9411242355127, -53.98976263590157, -3.5555891540134326], + [-1307.164416463871, -53.42289515584707, -3.575902643526206], + [-1306.960030266142, -53.958022441715, -3.091030521376524], + [-1307.1709969213116, -53.41330592986196, -3.372378869680688], + [-1307.1948683849187, -53.36724884994328, -2.9573557656549383], + [-1306.9955491531873, -53.884515340439975, -2.6162856828595977], + [-1307.2339197730762, -53.282925319857895, -2.535954341001343], + [-1307.0487732768524, -53.76625688839704, -2.137513151013991], + [-1307.288944863947, -53.158118915744126, -2.1140199257060885], + [-1307.100738369627, -53.64696316886693, -1.7800001740106381], + [-1307.1631602107664, -53.50098526477814, -1.4273924473382067], + [-1307.3603305587312, -52.991621006280184, -1.6980820209137164], + [-1307.2359643492382, -53.32839509379119, -1.0830416447133757], + [-1307.4479828339536, -52.783427353948355, -1.2951001767651178], + [-1307.3188863100368, -53.129745027050376, -0.7503383005096111], + [-1307.5512804948376, -52.53486670553684, -0.9121389198116958], + [-1307.4114676423487, -52.90608137752861, -0.4326124111539684], + [-1307.6383442233782, -52.32352809049189, -0.6421675197198056], + [-1307.5130604805308, -52.65893642697483, -0.133030181779759], + [-1307.7328908390482, -52.092597825452685, -0.3899432220205199], + [-1307.6228408953757, -52.39029809460044, 0.1455067968054209], + [-1307.834099994041, -51.84407367184758, -0.15782482747454196], + [-1307.9410314990673, -51.58026986103505, 0.052190510177752], + [-1307.7398305887473, -52.10255813319236, 0.4004534680279903], + [-1311.6623521425645, -41.94022354390472, -5.816597459604964], + [-1311.665487305203, -41.9368033381179, -5.686690607864875], + [-1307.862925764406, -51.798441612161696, 0.6296983319043647], + [-1308.090716930572, -51.209212188608944, 0.29516488648368977], + [-1311.8856452268665, -41.373353890143335, -5.836911028047325], + [-1307.9909314328688, -51.48092193715274, 0.8316207147436216], + [-1308.2461448091199, -50.82204227428883, 0.4936166317493189], + [-1308.1225989012164, -51.1531269820407, 1.0051251085824333], + [-1308.4046809814172, -50.425404525361955, 0.6465558299678378], + [-1308.2566640858422, -50.818242316134274, 1.1496513374440838], + [-1308.5637816990493, -50.025763732381165, 0.7544156073709019], + [-1308.3918843068532, -50.47941743209958, 1.2651613053458277], + [-1308.7211074174847, -49.62911103852093, 0.8188941958360374], + [-1311.7064567398047, -41.89210902992636, -3.98910418379819], + [-1308.5270715028164, -50.13968035392463, 1.3521048656548373], + [-1308.874608016049, -49.24073995836079, 0.8427284576755483], + [-1311.9297498240485, -41.32523937523365, -4.009417752240552], + [-1311.7095899169217, -41.89849856868386, -3.5779669542971533], + [-1308.7053739842377, -49.69014063291252, 1.4251805990934372], + [-1308.8793413292733, -49.249986744485795, 1.452192763419589], + [-1311.6985617888859, -41.94119896925986, -3.1552200905571226], + [-1311.933300757897, -41.3324808543548, -3.5434622254688293], + [-1311.6721510011703, -42.023124465718865, -2.726098778686719], + [-1309.575554959767, -47.461260076612234, 0.7789614414214157], + [-1311.920802212495, -41.38087464310229, -3.0643491127702873], + [-1311.6294600100373, -42.14633889589459, -2.296680791361723], + [-1311.8908699883032, -41.473723533563316, -2.578011625824729], + [-1311.5700086812722, -42.31182523816824, -1.873689603904495], + [-1311.8563511604443, -41.57398480270058, -2.21263097555493], + [-1311.4938095906982, -42.51930443570018, -1.464214800595073], + [-1310.2165689287358, -45.83393083047122, 0.7206466880161315], + [-1311.8111851541325, -41.70113799907267, -1.8502356949611567], + [-1311.4014134522877, -42.76713224314153, -1.0753672275459394], + [-1310.3682490662322, -45.447545723989606, 0.6690493192581926], + [-1311.3221262866864, -42.97771858703345, -0.801354350609472], + [-1311.755284666433, -41.85528766736388, -1.494176288601011], + [-1310.5217800466344, -45.05503278132528, 0.5762912663631141], + [-1311.2349867338198, -43.207586833275855, -0.5453513188112993], + [-1310.6749889180646, -44.66181951202452, 0.44001985117211007], + [-1311.1079810556257, -43.54039883520454, -0.23591535238665529], + [-1310.8254645981942, -44.27397509943694, 0.2589690191671252], + [-1310.9706536214217, -43.89797494281083, 0.03316935116890818], + [-1311.6887497214484, -42.03606083616614, -1.1478764503262937], + [-1310.2412103049573, -45.79263741709292, 1.3282999040384311], + [-1311.6118763824343, -42.24258834775537, -0.814734816813143], + [-1310.413114460418, -45.35473429784179, 1.2698228852823377], + [-1311.5251571819535, -42.47350737452507, -0.4980213381059002], + [-1310.5871162380208, -44.90988629497588, 1.1646970921137836], + [-1311.42927269364, -42.72698638681322, -0.200774473749334], + [-1310.7175237335614, -44.575363480485976, 1.053591673146002], + [-1311.3250743568642, -43.00077202171087, 0.07429426346789114], + [-1310.8465882905875, -44.24325392302126, 0.9140390128304716], + [-1311.2135594324209, -43.29225543513894, 0.3248822349414695], + [-1310.9731053883443, -43.91660360060632, 0.7458069174608681], + [-1311.0958396244678, -43.59855407383293, 0.5491589208832011], + ], + pointIndex: [ + 84, + 83, + 1, + 2, + 0, + 83, + 86, + 4, + 1, + 0, + 86, + 88, + 6, + 4, + 0, + 88, + 91, + 9, + 6, + 0, + 91, + 93, + 11, + 9, + 0, + 93, + 95, + 13, + 11, + 0, + 95, + 96, + 14, + 13, + 0, + 96, + 98, + 16, + 14, + 0, + 98, + 100, + 18, + 16, + 0, + 100, + 102, + 20, + 18, + 0, + 102, + 104, + 22, + 20, + 0, + 104, + 106, + 24, + 22, + 0, + 106, + 109, + 27, + 24, + 0, + 109, + 112, + 30, + 27, + 0, + 112, + 115, + 33, + 30, + 0, + 115, + 117, + 35, + 33, + 0, + 117, + 119, + 37, + 35, + 0, + 119, + 121, + 39, + 37, + 0, + 121, + 124, + 42, + 39, + 0, + 124, + 128, + 46, + 42, + 0, + 128, + 129, + 49, + 46, + 0, + 129, + 153, + 71, + 49, + 0, + 153, + 155, + 73, + 71, + 0, + 155, + 157, + 75, + 73, + 0, + 157, + 159, + 77, + 75, + 0, + 159, + 161, + 79, + 77, + 0, + 161, + 163, + 81, + 79, + 0, + 163, + 164, + 82, + 81, + 0, + 164, + 162, + 80, + 82, + 0, + 162, + 160, + 78, + 80, + 0, + 160, + 158, + 76, + 78, + 0, + 158, + 156, + 74, + 76, + 0, + 156, + 154, + 72, + 74, + 0, + 154, + 152, + 68, + 72, + 0, + 152, + 145, + 63, + 68, + 0, + 145, + 141, + 59, + 63, + 0, + 141, + 138, + 56, + 59, + 0, + 138, + 136, + 54, + 56, + 0, + 136, + 134, + 51, + 54, + 0, + 134, + 131, + 47, + 51, + 0, + 131, + 126, + 44, + 47, + 0, + 126, + 114, + 32, + 44, + 0, + 114, + 110, + 28, + 32, + 0, + 110, + 111, + 29, + 28, + 0, + 111, + 123, + 41, + 29, + 0, + 123, + 127, + 45, + 41, + 0, + 127, + 130, + 48, + 45, + 0, + 130, + 132, + 50, + 48, + 0, + 132, + 135, + 53, + 50, + 0, + 135, + 137, + 55, + 53, + 0, + 137, + 139, + 57, + 55, + 0, + 139, + 142, + 60, + 57, + 0, + 142, + 144, + 62, + 60, + 0, + 144, + 147, + 65, + 62, + 0, + 147, + 149, + 67, + 65, + 0, + 149, + 151, + 70, + 67, + 0, + 151, + 150, + 69, + 70, + 0, + 150, + 148, + 66, + 69, + 0, + 148, + 146, + 64, + 66, + 0, + 146, + 143, + 61, + 64, + 0, + 143, + 140, + 58, + 61, + 0, + 140, + 133, + 52, + 58, + 0, + 133, + 125, + 43, + 52, + 0, + 125, + 122, + 40, + 43, + 0, + 122, + 120, + 38, + 40, + 0, + 120, + 118, + 36, + 38, + 0, + 118, + 116, + 34, + 36, + 0, + 116, + 113, + 31, + 34, + 0, + 113, + 108, + 26, + 31, + 0, + 108, + 107, + 25, + 26, + 0, + 107, + 105, + 23, + 25, + 0, + 105, + 103, + 21, + 23, + 0, + 103, + 101, + 19, + 21, + 0, + 101, + 99, + 17, + 19, + 0, + 99, + 97, + 15, + 17, + 0, + 97, + 94, + 12, + 15, + 0, + 94, + 92, + 10, + 12, + 0, + 92, + 90, + 8, + 10, + 0, + 90, + 89, + 7, + 8, + 0, + 89, + 87, + 5, + 7, + 0, + 87, + 85, + 3, + 5, + 0, + 85, + 84, + 2, + 3, + 0, + 2, + 1, + 4, + 6, + 9, + 11, + 13, + 14, + 16, + 18, + 20, + 22, + 24, + 27, + 30, + 33, + 35, + 37, + 39, + 42, + 46, + 49, + 71, + 73, + 75, + 77, + 79, + 81, + 82, + 80, + 78, + 76, + 74, + 72, + 68, + 63, + 59, + 56, + 54, + 51, + 47, + 44, + 32, + 28, + 29, + 41, + 45, + 48, + 50, + 53, + 55, + 57, + 60, + 62, + 65, + 67, + 70, + 69, + 66, + 64, + 61, + 58, + 52, + 43, + 40, + 38, + 36, + 34, + 31, + 26, + 25, + 23, + 21, + 19, + 17, + 15, + 12, + 10, + 8, + 7, + 5, + 3, + 0, // start split face // 73, 75, 77, 79, 81, 82, 80, 78, 76, 74, 72, 68, 63, 59, 56, 54, 51, 47, 44, 32, 28, 29, 41, 45, 48, 50, 53, 55, 57, 60, 62, 65, 67, 70, 69, 66, 64, 61, 58, 0, // 58, 52, 43, 40, 38, 36, 34, 31, 26, 25, 23, 21, 19, 17, 15, 12, 10, 8, 7, 5, 3, 2, 1, 4, 6, 9, 11, 13, 14, 16, 18, 20, 22, 24, 27, 30, 33, 35, 37, 39, 42, 46, 49, 71, 73, 0, // end split face - 85, 83, 84, 0, 85, 86, 83, 0, 89, 88, 86, 0, 90, 91, 88, 0, 92, 93, 91, 0, 94, 95, 93, 0, 97, 96, 95, 0, 97, 98, 96, 0, 99, 100, 98, 0, 101, 102, 100, 0, 103, 104, 102, 0, - 105, 106, 104, 0, 107, 109, 106, 0, 108, 112, 109, 0, 113, 115, 112, 0, 113, 117, 115, 0, 116, 119, 117, 0, 118, 121, 119, 0, 120, 124, 121, 0, 120, 128, 124, 0, 122, 129, 128, 0, - 133, 153, 129, 0, 143, 155, 153, 0, 146, 157, 155, 0, 146, 159, 157, 0, 148, 161, 159, 0, 150, 163, 161, 0, 151, 164, 163, 0, 151, 162, 164, 0, 149, 160, 162, 0, 147, 158, 160, 0, - 144, 156, 158, 0, 142, 154, 156, 0, 139, 152, 154, 0, 139, 145, 152, 0, 137, 141, 145, 0, 135, 138, 141, 0, 132, 136, 138, 0, 130, 134, 136, 0, 127, 131, 134, 0, 123, 126, 131, 0, - 111, 114, 126, 0, 111, 110, 114, 0, 126, 123, 111, 0, 131, 127, 123, 0, 134, 130, 127, 0, 136, 132, 130, 0, 138, 135, 132, 0, 141, 137, 135, 0, 145, 139, 137, 0, 154, 142, 139, 0, - 156, 144, 142, 0, 158, 147, 144, 0, 160, 149, 147, 0, 162, 151, 149, 0, 163, 150, 151, 0, 161, 148, 150, 0, 159, 146, 148, 0, 155, 143, 146, 0, 153, 140, 143, 0, 153, 133, 140, 0, - 129, 125, 133, 0, 129, 122, 125, 0, 128, 120, 122, 0, 121, 118, 120, 0, 119, 116, 118, 0, 117, 113, 116, 0, 112, 108, 113, 0, 109, 107, 108, 0, 106, 105, 107, 0, 104, 103, 105, 0, - 102, 101, 103, 0, 100, 99, 101, 0, 98, 97, 99, 0, 95, 94, 97, 0, 93, 92, 94, 0, 91, 90, 92, 0, 88, 89, 90, 0, 86, 87, 89, 0, 86, 85, 87, 0], + 85, + 83, + 84, + 0, + 85, + 86, + 83, + 0, + 89, + 88, + 86, + 0, + 90, + 91, + 88, + 0, + 92, + 93, + 91, + 0, + 94, + 95, + 93, + 0, + 97, + 96, + 95, + 0, + 97, + 98, + 96, + 0, + 99, + 100, + 98, + 0, + 101, + 102, + 100, + 0, + 103, + 104, + 102, + 0, + 105, + 106, + 104, + 0, + 107, + 109, + 106, + 0, + 108, + 112, + 109, + 0, + 113, + 115, + 112, + 0, + 113, + 117, + 115, + 0, + 116, + 119, + 117, + 0, + 118, + 121, + 119, + 0, + 120, + 124, + 121, + 0, + 120, + 128, + 124, + 0, + 122, + 129, + 128, + 0, + 133, + 153, + 129, + 0, + 143, + 155, + 153, + 0, + 146, + 157, + 155, + 0, + 146, + 159, + 157, + 0, + 148, + 161, + 159, + 0, + 150, + 163, + 161, + 0, + 151, + 164, + 163, + 0, + 151, + 162, + 164, + 0, + 149, + 160, + 162, + 0, + 147, + 158, + 160, + 0, + 144, + 156, + 158, + 0, + 142, + 154, + 156, + 0, + 139, + 152, + 154, + 0, + 139, + 145, + 152, + 0, + 137, + 141, + 145, + 0, + 135, + 138, + 141, + 0, + 132, + 136, + 138, + 0, + 130, + 134, + 136, + 0, + 127, + 131, + 134, + 0, + 123, + 126, + 131, + 0, + 111, + 114, + 126, + 0, + 111, + 110, + 114, + 0, + 126, + 123, + 111, + 0, + 131, + 127, + 123, + 0, + 134, + 130, + 127, + 0, + 136, + 132, + 130, + 0, + 138, + 135, + 132, + 0, + 141, + 137, + 135, + 0, + 145, + 139, + 137, + 0, + 154, + 142, + 139, + 0, + 156, + 144, + 142, + 0, + 158, + 147, + 144, + 0, + 160, + 149, + 147, + 0, + 162, + 151, + 149, + 0, + 163, + 150, + 151, + 0, + 161, + 148, + 150, + 0, + 159, + 146, + 148, + 0, + 155, + 143, + 146, + 0, + 153, + 140, + 143, + 0, + 153, + 133, + 140, + 0, + 129, + 125, + 133, + 0, + 129, + 122, + 125, + 0, + 128, + 120, + 122, + 0, + 121, + 118, + 120, + 0, + 119, + 116, + 118, + 0, + 117, + 113, + 116, + 0, + 112, + 108, + 113, + 0, + 109, + 107, + 108, + 0, + 106, + 105, + 107, + 0, + 104, + 103, + 105, + 0, + 102, + 101, + 103, + 0, + 100, + 99, + 101, + 0, + 98, + 97, + 99, + 0, + 95, + 94, + 97, + 0, + 93, + 92, + 94, + 0, + 91, + 90, + 92, + 0, + 88, + 89, + 90, + 0, + 86, + 87, + 89, + 0, + 86, + 85, + 87, + 0, + ], }, }; - const clipPlane = ClipPlane.createNormalAndDistance(Vector3d.create(-0.012396820892038292, 0.030931559524568275, 0.9994446245076056), 13.05715711957438)!; + const clipPlane = ClipPlane.createNormalAndDistance( + Vector3d.create(-0.012396820892038292, 0.030931559524568275, 0.9994446245076056), + 13.05715711957438, + )!; const polyface = IModelJson.Reader.parse(meshJSON); if (ck.testDefined(polyface) && polyface instanceof Polyface) { @@ -571,12 +1517,17 @@ describe("PolyfaceClip", () => { const yStep = numY + 1; GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(Point3d.create(x0, y0), Point3d.create(x0, y0 + yStep))); GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(Point3d.create(x0, y0 + yStep), Point3d.create(x0, y0 + 2 * yStep))); - const meshX = Sample.createTriangularUnitGridPolyface(Point3d.create(0.1, 0.2, -0.5), Vector3d.create(0.5, 0, 0.3), Vector3d.create(0, 0.6, 0), numX, numY); + const meshX = Sample.createTriangularUnitGridPolyface( + Point3d.create(0.1, 0.2, -0.5), + Vector3d.create(0.5, 0, 0.3), + Vector3d.create(0, 0.6, 0), + numX, + numY, + ); if (mapY) - meshX.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 8.0); - }); + meshX.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 8.0); + }); const meshY = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.unitX(), Vector3d.unitY(), numX, numY); /* let z0 = 0.125; @@ -585,10 +1536,9 @@ describe("PolyfaceClip", () => { const meshY = builderY.claimPolyface(); */ if (mapY) - meshY.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 3.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 5.0); - }); + meshY.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 3.0) * RFunctions.cosineOfMappedAngle(y, -1.0, 5.0); + }); GeometryCoreTestIO.captureCloneGeometry(allGeometry, meshX, x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, meshY, x0, y0); const visitorX = meshX.createVisitor(); @@ -632,7 +1582,6 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "UnderAndOver"); expect(ck.getNumErrors()).toBe(0); - }); it("NonConvexClip", () => { @@ -647,7 +1596,10 @@ describe("PolyfaceClip", () => { const shape1 = GrowableXYZArray.create([[0, 0], [0, 6], [4, 4], [2, 1]]); const shape2 = GrowableXYZArray.create([[0, 0], [0, 6], [4, 6], [4, 0]]); const shape3 = GrowableXYZArray.create([[0, 0], [0, 6], [4, 4], [4, 0], [3, 0], [3, 2], [1, 3], [1, 0]]); - const shape4 = GrowableXYZArray.create([[0, 0], [0, 6], [4, 4], [4, 0], [3, 0], [3, 2], [1, 2], [1, 0], [0.5, 0], [0.5, 2], [0.25, 2], [0.25, 0]]); + const shape4 = GrowableXYZArray.create([[0, 0], [0, 6], [4, 4], [4, 0], [3, 0], [3, 2], [1, 2], [1, 0], [0.5, 0], [0.5, 2], [0.25, 2], [ + 0.25, + 0, + ]]); const shape5 = GrowableXYZArray.create(Sample.createSquareWave(Point3d.create(0, 0, 0), 0.5, 3, 0.75, 3, 4)); for (const points of [shape5, shape0, shape1, shape2, shape3, shape4, shape5]) { const range = Range3d.createFromVariantData(points); @@ -681,7 +1633,7 @@ describe("PolyfaceClip", () => { for (const loop of loopsB.outputLoops) GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loop.xyz, x0 + 20.0, y0 + gapDelta); - if (((numCrossingsB !== 0 && numCrossingsB !== 2)) || (numCrossingsA !== 0 && numCrossingsA !== 2)) + if ((numCrossingsB !== 0 && numCrossingsB !== 2) || (numCrossingsA !== 0 && numCrossingsA !== 2)) GeometryCoreTestIO.captureRangeEdges(allGeometry, range, x0, y0); ck.testExactNumber(numCrossingsA, numCrossingsB, "crossing counts with inside flip"); x0 += 40.0; @@ -702,19 +1654,37 @@ describe("PolyfaceClip", () => { const numYA = 5; const numXB = 12; const numYB = 12; - const meshA = Sample.createTriangularUnitGridPolyface(Point3d.create(2, 2, 0), Vector3d.unitX(), Vector3d.unitY(), numXA, numYA, false, false, false, true); + const meshA = Sample.createTriangularUnitGridPolyface( + Point3d.create(2, 2, 0), + Vector3d.unitX(), + Vector3d.unitY(), + numXA, + numYA, + false, + false, + false, + true, + ); const amplitudeA = 0.45; const amplitudeB = -0.35; - meshA.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return amplitudeA * RFunctions.cosineOfMappedAngle(x, 0.0, numXA) * RFunctions.cosineOfMappedAngle(y, 0, numYA); - }); - - const meshB = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.unitX(0.7), Vector3d.unitY(0.8), numXB, numYB, false, false, false, true); - meshB.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return amplitudeB * RFunctions.cosineOfMappedAngle(x, 0.0, 3.0) * RFunctions.cosineOfMappedAngle(y, 1, 5.0); - }); + meshA.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return amplitudeA * RFunctions.cosineOfMappedAngle(x, 0.0, numXA) * RFunctions.cosineOfMappedAngle(y, 0, numYA); + }); + + const meshB = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.unitX(0.7), + Vector3d.unitY(0.8), + numXB, + numYB, + false, + false, + false, + true, + ); + meshB.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return amplitudeB * RFunctions.cosineOfMappedAngle(x, 0.0, 3.0) * RFunctions.cosineOfMappedAngle(y, 1, 5.0); + }); // spin meshB so its grids do not align with mesh A const rangeB = meshB.range(); const centerB = rangeB.localXYZToWorld(0.5, 0.5, 0); @@ -737,7 +1707,6 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "CutFillUndulating"); expect(ck.getNumErrors()).toBe(0); - }); it("CutFillCoincident", () => { const ck = new Checker(); @@ -746,8 +1715,28 @@ describe("PolyfaceClip", () => { let y0 = 0; const numXA = 14; const numYA = 9; - const meshA = Sample.createTriangularUnitGridPolyface(Point3d.create(2, 2, 0), Vector3d.unitX(), Vector3d.unitY(), numXA, numYA, false, false, false, true); - const meshB = Sample.createTriangularUnitGridPolyface(Point3d.create(2, 2, 0), Vector3d.unitX(), Vector3d.unitY(), numXA, numYA, false, false, false, true); + const meshA = Sample.createTriangularUnitGridPolyface( + Point3d.create(2, 2, 0), + Vector3d.unitX(), + Vector3d.unitY(), + numXA, + numYA, + false, + false, + false, + true, + ); + const meshB = Sample.createTriangularUnitGridPolyface( + Point3d.create(2, 2, 0), + Vector3d.unitX(), + Vector3d.unitY(), + numXA, + numYA, + false, + false, + false, + true, + ); const rangeB1 = meshB.range(); shiftZInXYFractionRange(meshA, 0.1, 0.1, 0.5, 0.3, 0.5); shiftZInXYFractionRange(meshB, 0.3, 0.2, 0.6, 0.6, -0.5); @@ -767,7 +1756,6 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "CutFillCoincident"); expect(ck.getNumErrors()).toBe(0); - }); it("CutFillJonas", () => { @@ -807,7 +1795,8 @@ describe("PolyfaceClip", () => { indexedMesh: { point: [ [0, 0, 0.4999999999723128], - [0, 0, 1], [2.3283064365386963e-10, 0.6889561647549272, 0.49999999998019096], + [0, 0, 1], + [2.3283064365386963e-10, 0.6889561647549272, 0.49999999998019096], [0.8495529009960592, 9.313225746154785e-10, 0.5000000000207994], [0.3110438375733793, 0.6889561647549272, 0.499999999997943], @@ -817,16 +1806,64 @@ describe("PolyfaceClip", () => { [0.8495529012288898, 0.6889561638236046, 0.5000000000286775], [0.8495529012288898, 0.6889561638236046, 0.8908151873411514], - [0.8495529012288898, 0.6889561638236046, 1]], - pointIndex: [1, 4, 8, 2, 0, 3, 1, 2, - 7, 0, 11, 7, 2, 8, 0, 3, - 5, 6, 4, 1, 0, 6, 5, 9, + [0.8495529012288898, 0.6889561638236046, 1], + ], + pointIndex: [ + 1, + 4, + 8, + 2, + 0, + 3, + 1, + 2, + 7, + 0, + 11, + 7, + 2, + 8, + 0, + 3, + 5, + 6, + 4, + 1, + 0, + 6, + 5, + 9, + 0, + 9, + 5, + 10, + 0, + 5, + 3, + 7, 0, - 9, 5, 10, 0, 5, 3, 7, 0, - 7, 11, 10, 5, 0, 4, 6, 8, + 7, + 11, + 10, + 5, 0, - 6, 9, 10, 0, 10, 11, 8, 0, - 8, 6, 10, 0], + 4, + 6, + 8, + 0, + 6, + 9, + 10, + 0, + 10, + 11, + 8, + 0, + 8, + 6, + 10, + 0, + ], }, }; let x0 = 0; @@ -839,10 +1876,14 @@ describe("PolyfaceClip", () => { if (ck.testType(polyface, Polyface)) { for (const transform of Sample.createRigidTransforms(1.0)) { y0 = 0.0; - for (const clipPlane of [ClipPlane.createNormalAndDistance(Vector3d.create(0, 0, -1), -0.8221099398657934)!, - /* */ ClipPlane.createNormalAndDistance(Vector3d.create(0, -1, 0), -0.4221099398657934)!, - /* */ ClipPlane.createNormalAndDistance(Vector3d.create(-1, 0, 0), -0.8221099398657934)!, - /* */ ClipPlane.createNormalAndDistance(vectorA, -0.8221099398657934)!]) { + for ( + const clipPlane of [ + ClipPlane.createNormalAndDistance(Vector3d.create(0, 0, -1), -0.8221099398657934)!, + /* */ ClipPlane.createNormalAndDistance(Vector3d.create(0, -1, 0), -0.4221099398657934)!, + /* */ ClipPlane.createNormalAndDistance(Vector3d.create(-1, 0, 0), -0.8221099398657934)!, + /* */ ClipPlane.createNormalAndDistance(vectorA, -0.8221099398657934)!, + ] + ) { const clipPlaneA = clipPlane.clone(); clipPlaneA.transformInPlace(transform); const polyfaceA = polyface.cloneTransformed(transform) as Polyface; @@ -861,14 +1902,15 @@ describe("PolyfaceClip", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceClip", "ArnoldasBox"); expect(ck.getNumErrors()).toBe(0); - }); it("CutFill", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const sideAngle = Angle.createDegrees(0.001); - const meshA = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/data/iModelJsonSamples/polyface/ArnoldasEarthWorks/meshA.imjs", "utf8"))); + const meshA = IModelJson.Reader.parse( + JSON.parse(fs.readFileSync("./src/test/data/iModelJsonSamples/polyface/ArnoldasEarthWorks/meshA.imjs", "utf8")), + ); if (ck.testTrue(meshA instanceof IndexedPolyface, "Expected one indexed polyface in meshA") && meshA instanceof IndexedPolyface) { ck.testFalse(PolyfaceQuery.isPolyfaceClosedByEdgePairing(meshA), " expect this input to have boundary issue"); const boundaries = PolyfaceQuery.boundaryEdges(meshA, true, true, true); @@ -910,7 +1952,6 @@ describe("PolyfaceClip", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "ArnoldasEarthWorks", "meshA"); } expect(ck.getNumErrors()).toBe(0); - }); it("BoxClosure", () => { const ck = new Checker(); @@ -958,19 +1999,39 @@ describe("PolyfaceClip", () => { const yD = 0.4; const clipData = []; const contourP0 = SweepContour.createForPolygon( - [Point3d.create(xA, yA), Point3d.create(xB, yA), Point3d.create(xA, yB), Point3d.create(xA, yA)])!; + [Point3d.create(xA, yA), Point3d.create(xB, yA), Point3d.create(xA, yB), Point3d.create(xA, yA)], + )!; const clipperP0 = contourP0.sweepToUnionOfConvexClipPlaneSets()!; const contourP1 = SweepContour.createForPolygon( - [Point3d.create(xA, yA), Point3d.create(xC, yA), Point3d.create(xA, yC), Point3d.create(xA, yA)])!; + [Point3d.create(xA, yA), Point3d.create(xC, yA), Point3d.create(xA, yC), Point3d.create(xA, yA)], + )!; const clipperP1 = contourP1.sweepToUnionOfConvexClipPlaneSets()!; const dxB = 0.3; const contourQ0 = SweepContour.createForPolygon( - [Point3d.create(xA, yA), Point3d.create(xC, yA), Point3d.create(xC, yB), Point3d.create(xB + dxB, yB), Point3d.create(xB, yC), Point3d.create(xA, yC), Point3d.create(xA, yA)])!; + [ + Point3d.create(xA, yA), + Point3d.create(xC, yA), + Point3d.create(xC, yB), + Point3d.create(xB + dxB, yB), + Point3d.create(xB, yC), + Point3d.create(xA, yC), + Point3d.create(xA, yA), + ], + )!; const clipperQ0 = contourQ0.sweepToUnionOfConvexClipPlaneSets()!; const contourQ1 = SweepContour.createForPolygon( - [Point3d.create(xA, yA), Point3d.create(xC, yA), Point3d.create(xC, yB), Point3d.create(xB + dxB, yB), Point3d.create(xB, yD), Point3d.create(xA, yD), Point3d.create(xA, yA)])!; + [ + Point3d.create(xA, yA), + Point3d.create(xC, yA), + Point3d.create(xC, yB), + Point3d.create(xB + dxB, yB), + Point3d.create(xB, yD), + Point3d.create(xA, yD), + Point3d.create(xA, yA), + ], + )!; const clipperQ1 = contourQ1.sweepToUnionOfConvexClipPlaneSets()!; let x0 = 0; @@ -1039,15 +2100,203 @@ describe("PolyfaceClip", () => { [-43.36655237781815, -471.5515877753496, -0.1686169594322564], [-43.37025829101913, -471.5522910640575, -0.13070406735641882], [-43.239302208178145, -469.36335787194645, -0.15128906038398932], - [-43.2430081212604, -469.36406116061477, -0.11337616830783828]], - pointIndex: [39, 40, 38, 37, 0, 40, 36, 32, 38, 0, 36, 35, 31, 32, 0, 35, 39, 37, 31, 0, 37, 38, 34, 33, 0, - 38, 32, 26, 34, 0, 32, 31, 25, 26, 0, 31, 37, 33, 25, 0, 33, 34, 30, 29, 0, 34, 26, 24, 30, 0, - 26, 25, 23, 24, 0, 25, 33, 29, 23, 0, 29, 30, 28, 27, 0, 30, 24, 20, 28, 0, 24, 23, 19, 20, 0, - 23, 29, 27, 19, 0, 27, 28, 22, 21, 0, 28, 20, 16, 22, 0, 20, 19, 15, 16, 0, 19, 27, 21, 15, 0, - 21, 22, 18, 17, 0, 22, 16, 14, 18, 0, 16, 15, 13, 14, 0, 15, 21, 17, 13, 0, 17, 18, 12, 11, 0, - 18, 14, 8, 12, 0, 14, 13, 7, 8, 0, 13, 17, 11, 7, 0, 11, 12, 10, 9, 0, 12, 8, 4, 10, 0, - 8, 7, 3, 4, 0, 7, 11, 9, 3, 0, 9, 10, 6, 5, 0, 10, 4, 2, 6, 0, 4, 3, 1, 2, 0, - 3, 9, 5, 1, 0, 5, 6, 2, 1, 0, 35, 40, 39, 0, 35, 36, 40, 0], + [-43.2430081212604, -469.36406116061477, -0.11337616830783828], + ], + pointIndex: [ + 39, + 40, + 38, + 37, + 0, + 40, + 36, + 32, + 38, + 0, + 36, + 35, + 31, + 32, + 0, + 35, + 39, + 37, + 31, + 0, + 37, + 38, + 34, + 33, + 0, + 38, + 32, + 26, + 34, + 0, + 32, + 31, + 25, + 26, + 0, + 31, + 37, + 33, + 25, + 0, + 33, + 34, + 30, + 29, + 0, + 34, + 26, + 24, + 30, + 0, + 26, + 25, + 23, + 24, + 0, + 25, + 33, + 29, + 23, + 0, + 29, + 30, + 28, + 27, + 0, + 30, + 24, + 20, + 28, + 0, + 24, + 23, + 19, + 20, + 0, + 23, + 29, + 27, + 19, + 0, + 27, + 28, + 22, + 21, + 0, + 28, + 20, + 16, + 22, + 0, + 20, + 19, + 15, + 16, + 0, + 19, + 27, + 21, + 15, + 0, + 21, + 22, + 18, + 17, + 0, + 22, + 16, + 14, + 18, + 0, + 16, + 15, + 13, + 14, + 0, + 15, + 21, + 17, + 13, + 0, + 17, + 18, + 12, + 11, + 0, + 18, + 14, + 8, + 12, + 0, + 14, + 13, + 7, + 8, + 0, + 13, + 17, + 11, + 7, + 0, + 11, + 12, + 10, + 9, + 0, + 12, + 8, + 4, + 10, + 0, + 8, + 7, + 3, + 4, + 0, + 7, + 11, + 9, + 3, + 0, + 9, + 10, + 6, + 5, + 0, + 10, + 4, + 2, + 6, + 0, + 4, + 3, + 1, + 2, + 0, + 3, + 9, + 5, + 1, + 0, + 5, + 6, + 2, + 1, + 0, + 35, + 40, + 39, + 0, + 35, + 36, + 40, + 0, + ], }, }; if (Checker.noisy.isolateFacetsOnClipPlane) { @@ -1074,7 +2323,6 @@ describe("PolyfaceClip", () => { } const polyface = IModelJson.Reader.parse(meshData) as Polyface; if (ck.testDefined(polyface)) { - const pointA = polyface.data.point.getPoint3dAtUncheckedPointIndex(33); const pointB = polyface.data.point.getPoint3dAtUncheckedPointIndex(25); const edgeVector = Vector3d.createStartEnd(pointA, pointB); @@ -1082,7 +2330,10 @@ describe("PolyfaceClip", () => { const basePoint = pointA.clone(); GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface, basePoint.x, basePoint.y, basePoint.z); for (const shiftDistance of [0, 0.1, -0.01]) { - const plane = ClipPlane.createNormalAndDistance(Vector3d.create(0.040888310883825336, 0.998909753725443, 0.022526649667507826), -475.2718707964355 + shiftDistance); + const plane = ClipPlane.createNormalAndDistance( + Vector3d.create(0.040888310883825336, 0.998909753725443, 0.022526649667507826), + -475.2718707964355 + shiftDistance, + ); if (ck.testDefined(plane)) { const inside = PolyfaceClip.clipPolyfaceClipPlaneWithClosureFace(polyface, plane, true, true); const outside = PolyfaceClip.clipPolyfaceClipPlaneWithClosureFace(polyface, plane, false, true); @@ -1095,7 +2346,13 @@ describe("PolyfaceClip", () => { const arc2 = Arc3d.createCenterNormalRadius(centerB, plane1.getNormalRef(), 0.2); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc1, basePoint.x, basePoint.y, basePoint.z); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc2, basePoint.x, basePoint.y, basePoint.z); - GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(arc1.fractionToPoint(0.8), arc2.fractionToPoint(0.2)), basePoint.x, basePoint.y, basePoint.z); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineString3d.create(arc1.fractionToPoint(0.8), arc2.fractionToPoint(0.2)), + basePoint.x, + basePoint.y, + basePoint.z, + ); } GeometryCoreTestIO.captureCloneGeometry(allGeometry, inside, basePoint.x, basePoint.y, basePoint.z); GeometryCoreTestIO.captureCloneGeometry(allGeometry, outside, basePoint.x, basePoint.y, basePoint.z); @@ -1113,7 +2370,10 @@ describe("PolyfaceClip", () => { const clipperFile = `./src/test/data/clipping/arnoldasInOut/${caseDirectory}/clipper.json`; const meshA = IModelJson.Reader.parse(JSON.parse(fs.readFileSync(meshFile, "utf8"))); const clipper = UnionOfConvexClipPlaneSets.fromJSON(JSON.parse(fs.readFileSync(clipperFile, "utf8"))); - if (ck.testType(meshA as IndexedPolyface, IndexedPolyface, "Expect mesh") && meshA instanceof IndexedPolyface && ck.testType(clipper, UnionOfConvexClipPlaneSets, "expect clipper")) { + if ( + ck.testType(meshA as IndexedPolyface, IndexedPolyface, "Expect mesh") && meshA instanceof IndexedPolyface && + ck.testType(clipper, UnionOfConvexClipPlaneSets, "expect clipper") + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, meshA, 0, 0); const range = meshA.range(); const dx = 0.2 * range.xLength(); @@ -1124,7 +2384,7 @@ describe("PolyfaceClip", () => { const clipperLoopsA = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipper, range, true, false, true); const clipperLoopsB = ClipUtilities.loopsOfConvexClipPlaneIntersectionWithRange(clipper, range, true, false, false); GeometryCoreTestIO.captureCloneGeometry(allGeometry, clipperLoopsA, 0, 0); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, clipperLoopsB, 0, - dy); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, clipperLoopsB, 0, -dy); const builders = ClippedPolyfaceBuilders.create(true, true, true); PolyfaceClip.clipPolyfaceInsideOutside(meshA, clipper, builders); const inside = builders.builderA?.claimPolyface(); @@ -1225,7 +2485,10 @@ describe("PolyfaceClip", () => { // verify that all facets have the correct orientation, with normal pointing outward const compareWithTol = (a: number, b: number) => compareWithTolerance(a, b, Geometry.smallMetricDistance); const rayHits = new OrderedSet(compareWithTol); - const addRayHit = (d: FacetLocationDetail) => { if (d.a > 0.1 * thickness) rayHits.add(d.a); return false; }; + const addRayHit = (d: FacetLocationDetail) => { + if (d.a > 0.1 * thickness) rayHits.add(d.a); + return false; + }; const intersectOptions = new FacetIntersectOptions(); intersectOptions.acceptIntersection = addRayHit; // record ray param if beyond ray.origin for (const visitor = clampMesh.createVisitor(); visitor.moveToNextFacet();) { @@ -1258,16 +2521,25 @@ describe("PolyfaceClip", () => { let drapeMesh: IndexedPolyface | undefined; const contour = SweepContour.createForLinearSweep(regionXY); if (ck.testType(contour, SweepContour, `${label}: created contour from region`)) { - contour.announceFacets((facets: IndexedPolyface) => { regionFacets = facets; }, regionOptions); + contour.announceFacets((facets: IndexedPolyface) => { + regionFacets = facets; + }, regionOptions); const regionNormal = contour.localToWorld.matrix.columnZ(); ck.testTrue(regionNormal.isParallelTo(Vector3d.unitZ(), true), `${label}: we are only testing input regions parallel to the xy-plane`); drapeMesh = PolyfaceClip.drapeRegion(mesh, regionXY, sweepDir, regionOptions); - if (ck.testType(drapeMesh, IndexedPolyface, `${label}: draped mesh is created`) && - ck.testFalse(drapeMesh.isEmpty, `${label}: draped mesh is nonempty`)) { + if ( + ck.testType(drapeMesh, IndexedPolyface, `${label}: draped mesh is created`) && + ck.testFalse(drapeMesh.isEmpty, `${label}: draped mesh is nonempty`) + ) { const area = knownAreaXY ? knownAreaXY : RegionOps.computeXYArea(regionXY); if (ck.testDefined(area, `${label}: region area computed`)) { const projectedArea = PolyfaceQuery.sumFacetAreas(drapeMesh, sweepDir ? sweepDir : regionNormal); - ck.testCoordinateWithToleranceFactor(Math.abs(area), Math.abs(projectedArea), 1000, `${label}: projected area of draped mesh agrees with tool region area`); + ck.testCoordinateWithToleranceFactor( + Math.abs(area), + Math.abs(projectedArea), + 1000, + `${label}: projected area of draped mesh agrees with tool region area`, + ); } } } @@ -1281,18 +2553,35 @@ describe("PolyfaceClip", () => { if (true) { // nonconvex polygon const polygon = [ - Point3d.create(0.3, 0.3), Point3d.create(0.3, 0.1), Point3d.create(0.5, 0.2), Point3d.create(0.6, 0.1), - Point3d.create(0.8, 0.3), Point3d.create(0.5, 0.4), Point3d.create(0.5, 0.5), Point3d.create(0.9, 0.5), - Point3d.create(0.7, 0.7), Point3d.create(0.8, 0.8), Point3d.create(0.7, 0.9), Point3d.create(0.6, 0.7), - Point3d.create(0.5, 0.8), Point3d.create(0.4, 0.6), Point3d.create(0.2, 0.9), Point3d.create(0.1, 0.8), - Point3d.create(0.2, 0.7), Point3d.create(0.2, 0.5), Point3d.create(0.1, 0.4), Point3d.create(0.3, 0.3), + Point3d.create(0.3, 0.3), + Point3d.create(0.3, 0.1), + Point3d.create(0.5, 0.2), + Point3d.create(0.6, 0.1), + Point3d.create(0.8, 0.3), + Point3d.create(0.5, 0.4), + Point3d.create(0.5, 0.5), + Point3d.create(0.9, 0.5), + Point3d.create(0.7, 0.7), + Point3d.create(0.8, 0.8), + Point3d.create(0.7, 0.9), + Point3d.create(0.6, 0.7), + Point3d.create(0.5, 0.8), + Point3d.create(0.4, 0.6), + Point3d.create(0.2, 0.9), + Point3d.create(0.1, 0.8), + Point3d.create(0.2, 0.7), + Point3d.create(0.2, 0.5), + Point3d.create(0.1, 0.4), + Point3d.create(0.3, 0.3), ]; const loopCCW = Loop.createPolygon(polygon); const subMesh0 = facetAndDrapeRegion("nonconvexPolygon", loopCCW, 0.31); const loopCW = Loop.createPolygon(polygon.reverse()); const subMesh1 = PolyfaceClip.drapeRegion(mesh, loopCW, undefined, regionOptions); GeometryCoreTestIO.captureCloneGeometry(allGeometry, subMesh1, x); - if (ck.testType(subMesh0, IndexedPolyface, "draped mesh #0 is created") && ck.testType(subMesh1, IndexedPolyface, "draped mesh #1 is created")) { + if ( + ck.testType(subMesh0, IndexedPolyface, "draped mesh #0 is created") && ck.testType(subMesh1, IndexedPolyface, "draped mesh #1 is created") + ) { const area0 = PolyfaceQuery.sumFacetAreas(subMesh0); const area1 = PolyfaceQuery.sumFacetAreas(subMesh1); ck.testCoordinate(area0, area1, "loop orientation has no effect on (absolute) area of the draped facets"); @@ -1300,7 +2589,13 @@ describe("PolyfaceClip", () => { } if (x += 2) { // cw polygon - const squareCW = [Point3d.create(0.2, 0.2), Point3d.create(0.2, 0.8), Point3d.create(0.8, 0.8), Point3d.create(0.8, 0.2), Point3d.create(0.2, 0.2)]; + const squareCW = [ + Point3d.create(0.2, 0.2), + Point3d.create(0.2, 0.8), + Point3d.create(0.8, 0.8), + Point3d.create(0.8, 0.2), + Point3d.create(0.2, 0.2), + ]; const loopCW = Loop.createPolygon(squareCW); const subMesh0 = facetAndDrapeRegion("cwPolygon", loopCW, 0.36); const subMesh1 = facetAndDrapeRegion("cwPolygonOppositeSweep", loopCW, 0.36, Vector3d.unitZ()); @@ -1309,9 +2604,19 @@ describe("PolyfaceClip", () => { } if (x += 2) { // triangle with hole bridge - const outerTriangle = LineString3d.create(Point3d.create(0.1, 0.5), Point3d.create(0.9, 0.1), Point3d.create(0.9, 0.9), Point3d.create(0.1, 0.5)); + const outerTriangle = LineString3d.create( + Point3d.create(0.1, 0.5), + Point3d.create(0.9, 0.1), + Point3d.create(0.9, 0.9), + Point3d.create(0.1, 0.5), + ); const bridgeForward = LineSegment3d.createXYXY(0.1, 0.5, 0.4, 0.5); - const innerTriangle = LineString3d.create(Point3d.create(0.4, 0.5), Point3d.create(0.6, 0.6), Point3d.create(0.6, 0.4), Point3d.create(0.4, 0.5)); + const innerTriangle = LineString3d.create( + Point3d.create(0.4, 0.5), + Point3d.create(0.6, 0.6), + Point3d.create(0.6, 0.4), + Point3d.create(0.4, 0.5), + ); const bridgeBackward = bridgeForward.clone(); bridgeBackward.reverseInPlace(); const splitTriangle = Loop.create(outerTriangle, bridgeForward, innerTriangle, bridgeBackward); @@ -1319,13 +2624,21 @@ describe("PolyfaceClip", () => { } if (x += 2) { // split washer with hole - const outerArc = Arc3d.createRefs(Point3d.create(0.5, 0.5), Matrix3d.createIdentity().scale(0.4), AngleSweep.createStartEndDegrees(-180, 180)); // CCW + const outerArc = Arc3d.createRefs( + Point3d.create(0.5, 0.5), + Matrix3d.createIdentity().scale(0.4), + AngleSweep.createStartEndDegrees(-180, 180), + ); // CCW const bridgeForward = LineSegment3d.createXYXY(0.1, 0.5, 0.4, 0.5); - const innerArc = Arc3d.createRefs(Point3d.create(0.5, 0.5), Matrix3d.createIdentity().scale(0.1), AngleSweep.createStartEndDegrees(180, -180)); + const innerArc = Arc3d.createRefs( + Point3d.create(0.5, 0.5), + Matrix3d.createIdentity().scale(0.1), + AngleSweep.createStartEndDegrees(180, -180), + ); const bridgeBackward = bridgeForward.clone(); bridgeBackward.reverseInPlace(); const splitWasher = Loop.create(outerArc, bridgeForward, innerArc, bridgeBackward); - const hole = Loop.create(Arc3d.createCenterNormalRadius(Point3d.create(0.75, 0.5), Vector3d.unitZ().negate(), 0.1)); // CW + const hole = Loop.create(Arc3d.createCenterNormalRadius(Point3d.create(0.75, 0.5), Vector3d.unitZ().negate(), 0.1)); // CW const splitWasherWithHole = ParityRegion.create(splitWasher, hole); facetAndDrapeRegion("splitWasherWithHole", splitWasherWithHole, Math.PI * 0.14); } @@ -1393,7 +2706,7 @@ describe("PolyfaceClip", () => { const sweptArea = Vector3d.unitZ(circleArea).dotProduct(sweepDir); facetAndDrapeRegion("nonOrthogonalSweep", loop, sweptArea, sweepDir); const cylinder = LinearSweep.create(arc, sweepDir.scale(3), false); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, cylinder, x); // visual check + GeometryCoreTestIO.captureCloneGeometry(allGeometry, cylinder, x); // visual check } } @@ -1454,7 +2767,7 @@ describe("PolyfaceClip", () => { if (y > 0.0) profilePoints.push(Point3d.create(x)); const profileNormal = PolygonOps.areaNormal(profilePoints); - const xyProfile = Loop.createPolygon(profilePoints); // close the profile + const xyProfile = Loop.createPolygon(profilePoints); // close the profile GeometryCoreTestIO.captureCloneGeometry(allGeometry, xyProfile, xDelta); // sweep profile into a square deck @@ -1465,13 +2778,17 @@ describe("PolyfaceClip", () => { const builder = PolyfaceBuilder.create(); builder.addLinearSweep(deck); deckPolyface = builder.claimPolyface(); - deckPolyface.tryTransformInPlace(Transform.createFixedPointAndMatrix(profilePoints[0], Matrix3d.createRotationAroundAxisIndex(AxisIndex.X, Angle.createDegrees(90)))); + deckPolyface.tryTransformInPlace( + Transform.createFixedPointAndMatrix(profilePoints[0], Matrix3d.createRotationAroundAxisIndex(AxisIndex.X, Angle.createDegrees(90))), + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, deckPolyface, xDelta += sweepLength); } // create a clipper let clipper: UnionOfConvexClipPlaneSets | undefined; - if (ck.testType(deckPolyface, IndexedPolyface, "builder created a mesh") && ck.testFalse(deckPolyface.isEmpty, "builder created a *nonempty* mesh")) { + if ( + ck.testType(deckPolyface, IndexedPolyface, "builder created a mesh") && ck.testFalse(deckPolyface.isEmpty, "builder created a *nonempty* mesh") + ) { const clipShape = Arc3d.createXY(deckPolyface.range().center, sweepLength / 4); GeometryCoreTestIO.captureCloneGeometry(allGeometry, clipShape, xDelta += sweepLength); const clipShapeNormal = clipShape.matrixRef.columnZ(); diff --git a/core/geometry/src/test/clipping/XYOffsetAsClipper.test.ts b/core/geometry/src/test/clipping/XYOffsetAsClipper.test.ts index f657e218d588..c642629f1a13 100644 --- a/core/geometry/src/test/clipping/XYOffsetAsClipper.test.ts +++ b/core/geometry/src/test/clipping/XYOffsetAsClipper.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { ClipUtilities } from "../../clipping/ClipUtils"; import { UnionOfConvexClipPlaneSets } from "../../clipping/UnionOfConvexClipPlaneSets"; import { Arc3d } from "../../curve/Arc3d"; @@ -34,9 +34,7 @@ import { HalfEdgeGraphMerge, VertexNeighborhoodSortData } from "../../topology/M import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -function captureClippedPolygon(allGeometry: GeometryQuery[], points: Point3d[], clipper: UnionOfConvexClipPlaneSets, - x0: number, - y0: number) { +function captureClippedPolygon(allGeometry: GeometryQuery[], points: Point3d[], clipper: UnionOfConvexClipPlaneSets, x0: number, y0: number) { const clipShapes: GrowableXYZArray[] = []; clipper.polygonClip(points, clipShapes); for (const shape of clipShapes) { @@ -82,10 +80,9 @@ describe("OffsetByClip", () => { const offsetClipper = ClipUtilities.createXYOffsetClipFromLineString(points, leftSign * rightOffset, rightOffset, -0.1, -0.02); if (ck.testType(offsetClipper, UnionOfConvexClipPlaneSets)) { for (const c of offsetClipper.convexSets) { - ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, range, - (loopPoints: GrowableXYZArray) => { - GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0); - }); + ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, range, (loopPoints: GrowableXYZArray) => { + GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0); + }); } } y0 += 10.0; @@ -133,10 +130,9 @@ describe("OffsetByClip", () => { const offsetClipper = ClipUtilities.createXYOffsetClipFromLineString(points, leftOffset, 0, -9999, 9999); if (ck.testType(offsetClipper, UnionOfConvexClipPlaneSets)) { for (const c of offsetClipper.convexSets) { - ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, range, - (loopPoints: GrowableXYZArray) => { - GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0); - }); + ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, range, (loopPoints: GrowableXYZArray) => { + GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0); + }); } y0 += 30.0; } @@ -159,9 +155,13 @@ describe("OffsetByClip", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const shape1 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/DiegoTrickyBuilding/case1.imjs", "utf8"))) as CurveCollection; + "./src/test/data/clipping/DiegoTrickyBuilding/case1.imjs", + "utf8", + ))) as CurveCollection; const shape2 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/DiegoTrickyBuilding/case2.imjs", "utf8"))) as CurveCollection; + "./src/test/data/clipping/DiegoTrickyBuilding/case2.imjs", + "utf8", + ))) as CurveCollection; // const shape3 = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( // "./src/test/data/clipping/DiegoTrickyBuilding/case3.imjs", "utf8"))) as CurveCollection; let x00 = 0; @@ -179,13 +179,18 @@ describe("OffsetByClip", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, shape, x0, y0, z0 + zShape); if (shape instanceof CurveChain) { const points = shape.getPackedStrokes()!; - const offsetClipper = ClipUtilities.createXYOffsetClipFromLineString(points, offsetDistance, offsetDistance, range.low.z - 0.1, range.low.z - 0.02); + const offsetClipper = ClipUtilities.createXYOffsetClipFromLineString( + points, + offsetDistance, + offsetDistance, + range.low.z - 0.1, + range.low.z - 0.02, + ); if (ck.testType(offsetClipper, UnionOfConvexClipPlaneSets)) { for (const c of offsetClipper.convexSets) { - ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, clipRange, - (loopPoints: GrowableXYZArray) => { - GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0, z0); - }); + ClipUtilities.announceLoopsOfConvexClipPlaneSetIntersectRange(c, clipRange, (loopPoints: GrowableXYZArray) => { + GeometryCoreTestIO.createAndCaptureLoop(allGeometry, loopPoints, x0, y0, z0); + }); } } x00 += range.xLength() * 2; @@ -199,15 +204,16 @@ describe("OffsetByClip", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const fullRoadMesh = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/clipping/arnoldasLaneClipper/fullRoadMesh.imjs", "utf8"))); + "./src/test/data/clipping/arnoldasLaneClipper/fullRoadMesh.imjs", + "utf8", + ))); // const largeClipRegion = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( // "./src/test/data/clipping/arnoldasLaneClipper/largeClipRegion.imjs", "utf8"))); if (fullRoadMesh instanceof IndexedPolyface) { const meshRangeA = fullRoadMesh.range(); fullRoadMesh.tryTranslateInPlace(-meshRangeA.low.x, -meshRangeA.low.y, -meshRangeA.low.z); const meshRange = fullRoadMesh.range(); - const rangeRectangle = Sample.createRectangleXY(meshRange.low.x, meshRange.low.y, - meshRange.xLength(), meshRange.yLength(), meshRange.low.z); + const rangeRectangle = Sample.createRectangleXY(meshRange.low.x, meshRange.low.y, meshRange.xLength(), meshRange.yLength(), meshRange.low.z); let x0 = -meshRange.low.x; const y0 = -meshRange.low.y; const dx = meshRange.xLength(); @@ -227,14 +233,20 @@ describe("OffsetByClip", () => { const rightSideChains: LineString3d[] = []; for (const primitive of chainsA.children) { if (primitive instanceof LineString3d) - filterSegments(primitive, - (pointA: Point3d, pointB: Point3d) => { return pointB.x - pointA.x >= 0.0 && pointB.y - pointA.y >= 0.0; }, - (ls: LineString3d) => rightSideChains.push(ls)); + filterSegments(primitive, (pointA: Point3d, pointB: Point3d) => { + return pointB.x - pointA.x >= 0.0 && pointB.y - pointA.y >= 0.0; + }, (ls: LineString3d) => rightSideChains.push(ls)); } const offsetA = 3.0; - for (const offsetB of [0.0, -1.0]) { // we expect only one right side chain .. + for (const offsetB of [0.0, -1.0]) { // we expect only one right side chain .. for (const ls of rightSideChains) { - const clipper = ClipUtilities.createXYOffsetClipFromLineString(ls.packedPoints, offsetA, offsetB, meshRange.low.z - 1, meshRange.high.z + 1); + const clipper = ClipUtilities.createXYOffsetClipFromLineString( + ls.packedPoints, + offsetA, + offsetB, + meshRange.low.z - 1, + meshRange.high.z + 1, + ); const builders = ClippedPolyfaceBuilders.create(true, true, true); // first method: clip the whole polyface at once .... PolyfaceClip.clipPolyfaceUnionOfConvexClipPlaneSetsToBuilders(fullRoadMesh, clipper, builders); @@ -285,38 +297,72 @@ describe("OffsetByClip", () => { let y0 = 0; const clipper = UnionOfConvexClipPlaneSets.createEmpty(); const allClipPolygons = []; - for (const annulusA of - [ - Sample.createAnnulusPolyline(4, Point3d.create(4, 1.1, 0), 2, 2.6, - Angle.createDegrees(100), Angle.createDegrees(170), true), - Sample.createAnnulusPolyline(4, Point3d.create(6, 6, 0), 2, 2.6, - Angle.createDegrees(-80), Angle.createDegrees(45), true), - ]) { + for ( + const annulusA of [ + Sample.createAnnulusPolyline(4, Point3d.create(4, 1.1, 0), 2, 2.6, Angle.createDegrees(100), Angle.createDegrees(170), true), + Sample.createAnnulusPolyline(4, Point3d.create(6, 6, 0), 2, 2.6, Angle.createDegrees(-80), Angle.createDegrees(45), true), + ] + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, annulusA, x0, y0); const contourA = SweepContour.createForPolygon(annulusA); const clipperA = contourA!.sweepToUnionOfConvexClipPlaneSets()!; clipper.takeConvexSets(clipperA); allClipPolygons.push(annulusA); - const grid0 = Sample.createTriangularUnitGridPolyface(Point3d.create(1, 2, 0), + const grid0 = Sample.createTriangularUnitGridPolyface( + Point3d.create(1, 2, 0), Vector3d.create(1.0, 0, 0), Vector3d.create(0, 2.0, 0), - 3, 2, false, false, false, false); - const grid0A = Sample.createTriangularUnitGridPolyface(Point3d.create(2, 0, 0), + 3, + 2, + false, + false, + false, + false, + ); + const grid0A = Sample.createTriangularUnitGridPolyface( + Point3d.create(2, 0, 0), Vector3d.create(1.0, 0, 0), Vector3d.create(0, 2.0, 0), - 2, 2, false, false, false, false); - const grid1 = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), + 2, + 2, + false, + false, + false, + false, + ); + const grid1 = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), Vector3d.create(1.0, 0, 0), Vector3d.create(0, 2.0, 0), - 11, 6, false, false, false, false); - const grid2 = Sample.createTriangularUnitGridPolyface(Point3d.create(1, 2, 0), + 11, + 6, + false, + false, + false, + false, + ); + const grid2 = Sample.createTriangularUnitGridPolyface( + Point3d.create(1, 2, 0), Vector3d.create(1.0, 0, 0), Vector3d.create(0, 2.0, 0), - 4, 3, false, false, false, false); - const grid3 = Sample.createTriangularUnitGridPolyface(Point3d.create(7, 4, 0), + 4, + 3, + false, + false, + false, + false, + ); + const grid3 = Sample.createTriangularUnitGridPolyface( + Point3d.create(7, 4, 0), Vector3d.create(1.0, 0, 0), Vector3d.create(0, 2.0, 0), - 3, 2, false, false, false, false); + 3, + 2, + false, + false, + false, + false, + ); x0 += 20.0; for (const grid of [grid0A, grid0, grid1, grid2, grid3]) { y0 = 0.0; @@ -361,13 +407,22 @@ describe("OffsetByClip", () => { const clipRectangle = SweepContour.createForPolygon(Sample.createRectangleXY(1, 1, 2, 3, 0)); const rectangleClipper = clipRectangle!.sweepToUnionOfConvexClipPlaneSets()!; - const grid0 = Sample.createTriangularUnitGridPolyface(Point3d.create(2, 0, 0), + const grid0 = Sample.createTriangularUnitGridPolyface( + Point3d.create(2, 0, 0), Vector3d.create(2.0, 0, 0), Vector3d.create(0, 3.0, 0), - 2, 2, false, false, false, false); + 2, + 2, + false, + false, + false, + false, + ); for (const degrees of [0, 10, 20, 45, 90, 125]) { - const rotation = Transform.createFixedPointAndMatrix(Point3d.create(0, 0, 0), - Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(degrees))); + const rotation = Transform.createFixedPointAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(degrees)), + ); const grid1 = grid0.cloneTransformed(rotation); const clipper1 = rectangleClipper.clone(); clipper1.transformInPlace(rotation); @@ -410,23 +465,26 @@ describe("OffsetByClip", () => { paths.push(quirkyArcPath(0, 0, 0, 1)); paths.push(quirkyArcPath(0, 0, 0, -1)); - for (const radius0 of [1.0, 2.0]) { // nominally possible to have undefined return -- but it will get tossed later . .. + for (const radius0 of [1.0, 2.0]) { // nominally possible to have undefined return -- but it will get tossed later . .. paths.push(CurveFactory.createRectangleXY(aa, aa, bb, bb, 0, radius0)); } - paths.push(CurveFactory.createFilletsInLineString(LineString3d.create([ - [0, 0, 0], - [5, 0, 0], - [5, 5, 0], - [10, 5, 0], - [10, 10, 0], - [0, 8, 0], - ]), 1.0)); + paths.push(CurveFactory.createFilletsInLineString( + LineString3d.create([ + [0, 0, 0], + [5, 0, 0], + [5, 5, 0], + [10, 5, 0], + [10, 10, 0], + [0, 8, 0], + ]), + 1.0, + )); for (const path of paths) { const y0 = y00; if (path) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, path, x0, y0, 0.01); - for (const offsetDistance of [2.0, 3.0, 0.9, 1.0, 1.1]) { // 7.0 makes bow ties + for (const offsetDistance of [2.0, 3.0, 0.9, 1.0, 1.1]) { // 7.0 makes bow ties const options1 = new JointOptions(offsetDistance); const options2 = new JointOptions(-offsetDistance); const offset1 = RegionOps.constructCurveXYOffset(path, options1); @@ -458,10 +516,11 @@ describe("OffsetByClip", () => { Point3d.create(22.0, 22.141134101103496, 0.0), Point3d.create(21.693771833736626, 22.300546394411093, 0.0), ], - [Point3d.create(21.693771833736626, 22.300546394411093, 0.0), - Point3d.create(21.591750080167749, 22.0, 0.0), - Point3d.create(21.812339330618727, 22.0, 0.0), - Point3d.create(21.693771833736626, 22.300546394411093, 0.0), + [ + Point3d.create(21.693771833736626, 22.300546394411093, 0.0), + Point3d.create(21.591750080167749, 22.0, 0.0), + Point3d.create(21.812339330618727, 22.0, 0.0), + Point3d.create(21.693771833736626, 22.300546394411093, 0.0), ], [ Point3d.create(21.693771833736626, 22.300546394411093, 0.0), @@ -478,18 +537,20 @@ describe("OffsetByClip", () => { ], ]; let x0 = -21; - for (const candidates of [ - [polygonsToPaste[1], polygonsToPaste[2]], - [polygonsToPaste[0], polygonsToPaste[1]], - [polygonsToPaste[0], polygonsToPaste[2]], - [polygonsToPaste[0], polygonsToPaste[3]], - [polygonsToPaste[0], polygonsToPaste[4]], - [polygonsToPaste[1], polygonsToPaste[2]], - [polygonsToPaste[1], polygonsToPaste[3]], - [polygonsToPaste[1], polygonsToPaste[4]], - [polygonsToPaste[2], polygonsToPaste[3]], - [polygonsToPaste[2], polygonsToPaste[4]], // 4 is a sliver !!! - ]) { + for ( + const candidates of [ + [polygonsToPaste[1], polygonsToPaste[2]], + [polygonsToPaste[0], polygonsToPaste[1]], + [polygonsToPaste[0], polygonsToPaste[2]], + [polygonsToPaste[0], polygonsToPaste[3]], + [polygonsToPaste[0], polygonsToPaste[4]], + [polygonsToPaste[1], polygonsToPaste[2]], + [polygonsToPaste[1], polygonsToPaste[3]], + [polygonsToPaste[1], polygonsToPaste[4]], + [polygonsToPaste[2], polygonsToPaste[3]], + [polygonsToPaste[2], polygonsToPaste[4]], // 4 is a sliver !!! + ] + ) { let y0 = -21; GeometryCoreTestIO.captureCloneGeometry(allGeometry, candidates, x0, y0); const insidePieces = RegionOps.polygonBooleanXYToLoops(candidates, RegionBinaryOpType.Union, []); @@ -541,17 +602,21 @@ describe("OffsetByClip", () => { const vertexNeighborhoodFunction = (edgeData: VertexNeighborhoodSortData[]) => { GeometryCoreTestIO.consoleLog({ nodeCount: edgeData.length }); for (const data of edgeData) { - GeometryCoreTestIO.consoleLog(` id: ${data.node.id} x: ${data.node.x}, y: ${data.node.y}, theta: ${data.radians}, curvature: ${data.radiusOfCurvature} `); + GeometryCoreTestIO.consoleLog( + ` id: ${data.node.id} x: ${data.node.x}, y: ${data.node.y}, theta: ${data.radians}, curvature: ${data.radiusOfCurvature} `, + ); } }; - for (const candidates of [ - [shard0, shard1], - [shard0A, shard1], - [shard0B, shard1], - [shard0C, shard1], - [shard0A, shard1A], - [shard0, shard1A], - ]) { + for ( + const candidates of [ + [shard0, shard1], + [shard0A, shard1], + [shard0B, shard1], + [shard0C, shard1], + [shard0A, shard1A], + [shard0, shard1A], + ] + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, candidates, x0, y0); if (showVertexNeighborhoods) HalfEdgeGraphMerge.announceVertexNeighborhoodFunction = vertexNeighborhoodFunction; @@ -566,14 +631,15 @@ describe("OffsetByClip", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "OffsetByClip", "IncompletePasteWithDoublePoint"); expect(ck.getNumErrors()).toBe(0); }); - }); // Pass each segment to a test function. // Collect sequences of accepted segments into linestrings. -function filterSegments(linestring: LineString3d, +function filterSegments( + linestring: LineString3d, segmentTestFunction: (pointA: Point3d, pointB: Point3d) => boolean, - linestringAcceptFunction: (ls: LineString3d) => void): void { + linestringAcceptFunction: (ls: LineString3d) => void, +): void { const pointA = Point3d.create(); const pointB = Point3d.create(); let currentLineString: LineString3d | undefined; diff --git a/core/geometry/src/test/curve/Arc3d.test.ts b/core/geometry/src/test/curve/Arc3d.test.ts index ba53972fdc38..f0b71ca1740d 100644 --- a/core/geometry/src/test/curve/Arc3d.test.ts +++ b/core/geometry/src/test/curve/Arc3d.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, describe, expect, it } from "vitest"; import { compareNumbers, OrderedSet } from "@itwin/core-bentley"; +import { assert, describe, expect, it } from "vitest"; import { Constant } from "../../Constant"; import { CurveFactory } from "../../core-geometry"; import { Arc3d, EllipticalArcApproximationOptions, EllipticalArcSampleMethod, FractionMapper } from "../../curve/Arc3d"; @@ -35,13 +35,37 @@ import { BuildingCodeOffsetOps } from "./BuildingCodeOffsetOps"; describe("Arc3d", () => { function sampleSweeps(): AngleSweep[] { - return [AngleSweep.create360(), AngleSweep.createStartEndDegrees(0, 40), AngleSweep.createStartEndDegrees(0, 2), AngleSweep.createStartEndDegrees(-1, 3), AngleSweep.createStartEndDegrees(88, 91), - /* */ AngleSweep.createStartEndDegrees(0, 18), AngleSweep.createStartEndDegrees(-10, 10), AngleSweep.createStartEndDegrees(80, 100), AngleSweep.createStartEndDegrees(90, 108), AngleSweep.createStartEndDegrees(30, 45), - /* */ AngleSweep.createStartEndDegrees(80, 110), AngleSweep.createStartEndDegrees(-10, 110), AngleSweep.createStartEndDegrees(-10, 320), AngleSweep.createStartEndDegrees(0, 88), AngleSweep.createStartEndDegrees(45, 132), - /* */ AngleSweep.createStartEndDegrees(-10, 278), AngleSweep.createStartEndDegrees(30, 80), - /* */ AngleSweep.createStartEndDegrees(0, -18), AngleSweep.createStartEndDegrees(-10, -20), AngleSweep.createStartEndDegrees(80, -100), AngleSweep.createStartEndDegrees(90, -108), AngleSweep.createStartEndDegrees(30, -45), - /* */ AngleSweep.createStartEndDegrees(80, -110), AngleSweep.createStartEndDegrees(-10, -110), AngleSweep.createStartEndDegrees(-10, -320), AngleSweep.createStartEndDegrees(0, -88), AngleSweep.createStartEndDegrees(45, -132), - /* */ AngleSweep.createStartEndDegrees(-10, -278), AngleSweep.createStartEndDegrees(30, -80)]; + return [ + AngleSweep.create360(), + AngleSweep.createStartEndDegrees(0, 40), + AngleSweep.createStartEndDegrees(0, 2), + AngleSweep.createStartEndDegrees(-1, 3), + AngleSweep.createStartEndDegrees(88, 91), + /* */ AngleSweep.createStartEndDegrees(0, 18), + AngleSweep.createStartEndDegrees(-10, 10), + AngleSweep.createStartEndDegrees(80, 100), + AngleSweep.createStartEndDegrees(90, 108), + AngleSweep.createStartEndDegrees(30, 45), + /* */ AngleSweep.createStartEndDegrees(80, 110), + AngleSweep.createStartEndDegrees(-10, 110), + AngleSweep.createStartEndDegrees(-10, 320), + AngleSweep.createStartEndDegrees(0, 88), + AngleSweep.createStartEndDegrees(45, 132), + /* */ AngleSweep.createStartEndDegrees(-10, 278), + AngleSweep.createStartEndDegrees(30, 80), + /* */ AngleSweep.createStartEndDegrees(0, -18), + AngleSweep.createStartEndDegrees(-10, -20), + AngleSweep.createStartEndDegrees(80, -100), + AngleSweep.createStartEndDegrees(90, -108), + AngleSweep.createStartEndDegrees(30, -45), + /* */ AngleSweep.createStartEndDegrees(80, -110), + AngleSweep.createStartEndDegrees(-10, -110), + AngleSweep.createStartEndDegrees(-10, -320), + AngleSweep.createStartEndDegrees(0, -88), + AngleSweep.createStartEndDegrees(45, -132), + /* */ AngleSweep.createStartEndDegrees(-10, -278), + AngleSweep.createStartEndDegrees(30, -80), + ]; } function exerciseArcSet(ck: Checker, arcA: Arc3d) { const arcB = Arc3d.createXY(Point3d.create(6, 5, 4), 1232.9, AngleSweep.createStartEndDegrees(1, 92)); @@ -49,9 +73,11 @@ describe("Arc3d", () => { ck.testFalse(arcA.isAlmostEqual(arcC), "Verify distinct arcs before using set to match."); ck.testTrue(arcB.isAlmostEqual(arcC), "same arc after clone"); arcC.setFrom(arcA); - ck.testTrue(arcC.isAlmostEqual(arcA), "same after setFrom"); // but still not to confirm members where cloned. - const transform = Transform.createOriginAndMatrix(Point3d.create(4, 23, 2), - Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 2), Angle.createDegrees(12))); + ck.testTrue(arcC.isAlmostEqual(arcA), "same after setFrom"); // but still not to confirm members where cloned. + const transform = Transform.createOriginAndMatrix( + Point3d.create(4, 23, 2), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 2), Angle.createDegrees(12)), + ); arcC.tryTransformInPlace(transform); ck.testFalse(arcC.isAlmostEqual(arcA), "confirm cloned arc does not share pointers."); @@ -73,10 +99,16 @@ describe("Arc3d", () => { const arcF = arcC.cloneAtZ(); ck.testFalse(arcF.isAlmostEqual(arcC), "cloneAtZ of non-xy-arc is not the same arc"); ck.testPoint3d(arcF.center, arcC.center, "cloneAtZ of non-xy-arc with undefined param doesn't change center"); - ck.testTrue(arcF.isInPlane(Plane3dByOriginAndUnitNormal.createXYPlane(arcF.center)), "cloneAtZ of non-xy-arc with undefined param is in the horizontal plane at its center"); + ck.testTrue( + arcF.isInPlane(Plane3dByOriginAndUnitNormal.createXYPlane(arcF.center)), + "cloneAtZ of non-xy-arc with undefined param is in the horizontal plane at its center", + ); const arcG = arcC.cloneAtZ(100); ck.testExactNumber(arcG.center.z, 100, "cloneAtZ sets new center to param"); - ck.testTrue(arcG.isInPlane(Plane3dByOriginAndUnitNormal.createXYPlane(Point3d.create(arcC.center.x, arcC.center.y, 100))), "cloneAtZ of non-xy-arc is in the horizontal plane at the new center"); + ck.testTrue( + arcG.isInPlane(Plane3dByOriginAndUnitNormal.createXYPlane(Point3d.create(arcC.center.x, arcC.center.y, 100))), + "cloneAtZ of non-xy-arc is in the horizontal plane at the new center", + ); } function exerciseArc3d(ck: Checker, arc: Arc3d) { const vector0 = arc.vector0; @@ -85,8 +117,7 @@ describe("Arc3d", () => { ck.testVector3d(vector0, vectorData.vector0); ck.testVector3d(vector90, vectorData.vector90); const a = 4.2; - const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), - Matrix3d.createScale(a, a, a)); + const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), Matrix3d.createScale(a, a, a)); const arc1 = arc.cloneTransformed(scaleTransform); ck.testFalse(arc.isAlmostEqual(arc1), "scale changes arc"); ck.testPointer(arc1); @@ -94,15 +125,14 @@ describe("Arc3d", () => { ck.testBoolean( arc.sweep.isFullCircle, arc.startPoint().isAlmostEqual(arc.endPoint()), - "full circle start, end condition"); + "full circle start, end condition", + ); const json = arc1.toJSON(); const arc2 = Arc3d.createUnitCircle(); arc2.setFromJSON(json); ck.testTrue(arc1.isAlmostEqual(arc2), "Tight json round trip"); - ck.testLE(arc.curveLength(), - arc.sweep.sweepRadians * arc.maxVectorLength(), - "arc length smaller than circle on max radius"); + ck.testLE(arc.curveLength(), arc.sweep.sweepRadians * arc.maxVectorLength(), "arc length smaller than circle on max radius"); const fA = 0.35; const fB = 0.51; const arc3A = arc.clonePartialCurve(fA, fB); @@ -119,13 +149,19 @@ describe("Arc3d", () => { const arcA = Arc3d.createUnitCircle(); ck.testTrue(arcA.isCircular); exerciseArc3d(ck, arcA); - exerciseArc3d(ck, + exerciseArc3d( + ck, Arc3d.create( Point3d.create(1, 2, 5), Vector3d.create(1, 0, 0), - Vector3d.create(0, 2, 0), AngleSweep.createStartEndDegrees(0, 90))); + Vector3d.create(0, 2, 0), + AngleSweep.createStartEndDegrees(0, 90), + ), + ); - ck.testTrue(Arc3d.createCircularStartMiddleEnd(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(4, 0, 0)) instanceof LineString3d); + ck.testTrue( + Arc3d.createCircularStartMiddleEnd(Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(4, 0, 0)) instanceof LineString3d, + ); ck.checkpoint("Arc3d.HelloWorld"); const arcB = Arc3d.createUnitCircle(); @@ -150,16 +186,17 @@ describe("Arc3d", () => { const factorRange = Range1d.createNull(); for (const sweep of sampleSweeps()) { const factorRange1 = Range1d.createNull(); - for (const arc of [ - Arc3d.createXY(origin, 4.0, sweep), - Arc3d.createXYEllipse(origin, 4, 2, sweep), - Arc3d.createXYEllipse(origin, 8, 2, sweep), - Arc3d.createXYEllipse(origin, 5, 4, sweep), - Arc3d.createXYEllipse(origin, 20, 2, sweep), - Arc3d.create(origin, - Vector3d.create(4, 0, 0), Vector3d.create(1, 2, 0), sweep), - Arc3d.create(origin, - Vector3d.create(8, 7, 0), Vector3d.create(7, 8, 0), sweep)]) { + for ( + const arc of [ + Arc3d.createXY(origin, 4.0, sweep), + Arc3d.createXYEllipse(origin, 4, 2, sweep), + Arc3d.createXYEllipse(origin, 8, 2, sweep), + Arc3d.createXYEllipse(origin, 5, 4, sweep), + Arc3d.createXYEllipse(origin, 20, 2, sweep), + Arc3d.create(origin, Vector3d.create(4, 0, 0), Vector3d.create(1, 2, 0), sweep), + Arc3d.create(origin, Vector3d.create(8, 7, 0), Vector3d.create(7, 8, 0), sweep), + ] + ) { const arcLength = arc.curveLength(); const quickLength = arc.quickLength(); if (arc.isCircular) { @@ -196,9 +233,7 @@ describe("Arc3d", () => { GeometryCoreTestIO.consoleLog(`\n\n ******************* numGauss ${numGauss}`); for (let e2 = 1.0; e2 < 1000.0; e2 *= 2.0) { const e = Math.sqrt(e2); - const arc = Arc3d.create(Point3d.createZero(), - Vector3d.create(e, 0, 0), - Vector3d.create(0, 1, 0), AngleSweep.createStartEndDegrees(0, 90)); + const arc = Arc3d.create(Point3d.createZero(), Vector3d.create(e, 0, 0), Vector3d.create(0, 1, 0), AngleSweep.createStartEndDegrees(0, 90)); const lengths = []; const deltas = []; const counts = []; @@ -213,7 +248,10 @@ describe("Arc3d", () => { if (k >= 1) { const q = (lengths[k] - lengths[k - 1]) / lengths[k]; deltas.push(q); - if (Math.abs(q) < 4.0e-15) { done = true; break; } + if (Math.abs(q) < 4.0e-15) { + done = true; + break; + } } } if (done) @@ -246,9 +284,12 @@ describe("Arc3d", () => { for (const sweepDegrees of [30, 90, 135, 180, 239, 360]) { for (let e2 = 1.0; e2 < 1000.0; e2 *= 2.0) { const e = Math.sqrt(e2); - const arc = Arc3d.create(Point3d.createZero(), + const arc = Arc3d.create( + Point3d.createZero(), Vector3d.create(e, 0, 0), - Vector3d.create(0, 1, 0), AngleSweep.createStartEndDegrees(0, sweepDegrees)); + Vector3d.create(0, 1, 0), + AngleSweep.createStartEndDegrees(0, sweepDegrees), + ); const numA = Math.ceil(arc.sweep.sweepDegrees * e / degreesInterval); const lengthA = arc.curveLengthWithFixedIntervalCountQuadrature(0.0, 1.0, numA, numGauss); const lengthB = arc.curveLengthWithFixedIntervalCountQuadrature(0.0, 1.0, 2 * numA, numGauss); @@ -271,7 +312,8 @@ describe("Arc3d", () => { scaledForm.axes, scaledForm.r0, scaledForm.r90, - scaledForm.sweep); + scaledForm.sweep, + ); for (const fraction of [0.0, 0.2, 0.4, 0.6, 0.8]) { ck.testPoint3d(arc.fractionToPoint(fraction), arc1.fractionToPoint(fraction)); } @@ -339,10 +381,24 @@ describe("Arc3d", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc, x0, y0); GeometryCoreTestIO.captureRangeEdges(allGeometry, range, x0, y0); range1.expandInPlace(tolerancePullBack); - if (!ck.testTrue(range.containsRange(range1), "precise range contains stroke range", prettyPrint(arc.sweep), prettyPrint(range.toJSON()), prettyPrint(range1.toJSON()))) + if ( + !ck.testTrue( + range.containsRange(range1), + "precise range contains stroke range", + prettyPrint(arc.sweep), + prettyPrint(range.toJSON()), + prettyPrint(range1.toJSON()), + ) + ) GeometryCoreTestIO.captureCloneGeometry(allGeometry, linestring, x0, y0); range1.expandInPlace(chordTol2); - ck.testTrue(range1.containsRange(range), "stroking is close to true range", prettyPrint(arc.sweep), prettyPrint(range.toJSON()), prettyPrint(range1.toJSON())); + ck.testTrue( + range1.containsRange(range), + "stroking is close to true range", + prettyPrint(arc.sweep), + prettyPrint(range.toJSON()), + prettyPrint(range1.toJSON()), + ); } x0 = 0; y0 += dx; @@ -361,9 +417,7 @@ describe("Arc3d", () => { const point0 = Point3d.create(0, 0, 0); const point1 = Point3d.create(0, 0, 1); const point2 = Point3d.create(1, 0, 1); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineString3d.create(point0, point1, point2), - x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(point0, point1, point2), x0, y0); const arc = Arc3d.createCircularStartMiddleEnd(point0, point1, point2) as Arc3d; GeometryCoreTestIO.captureGeometry(allGeometry, arc, x0, y0); GeometryCoreTestIO.saveGeometry(allGeometry, "Arc3d", "ArnoldasFailureLinearSys3d"); @@ -391,27 +445,26 @@ describe("Arc3d", () => { Point3d.create(0, 0, 0), Point3d.create(2, e, 0), Point3d.create(2, 2 - e, 0), - Point3d.create(-e, 2, 0)]; + Point3d.create(-e, 2, 0), + ]; GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(points), x0, y0); GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(points[points.length - 1], points[0]), x0, y0); let point0: Point3d | undefined; let point1: Point3d | undefined; for (let i = 0; i <= points.length; i++) { - const i0 = (i % points.length); + const i0 = i % points.length; const i1 = (i + 1) % points.length; const i2 = (i + 2) % points.length; const joint = BuildingCodeOffsetOps.createJointWithRadiusChange(points[i0], points[i1], points[i2], offset[i0], offset[i1]); if (joint instanceof Arc3d) { point1 = joint.startPoint(); if (point0) - GeometryCoreTestIO.captureGeometry(allGeometry, - LineSegment3d.create(point0, point1), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(point0, point1), x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, joint, x0, y0); point0 = joint.endPoint(point0); } else if (joint instanceof Point3d) { if (point0) - GeometryCoreTestIO.captureGeometry(allGeometry, - LineSegment3d.create(point0, joint), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(point0, joint), x0, y0); point0?.setFromPoint3d(joint); } else { point0 = undefined; @@ -475,7 +528,12 @@ describe("Arc3d", () => { for (const x of offsets) reverseOffsets.push(-x); const theta = Angle.createDegrees(degrees); - const points = [Point3d.create(a - c * theta.cos(), c * theta.sin()), Point3d.create(a, 0, 0), Point3d.create(b, 0, 0), Point3d.create(b + c * theta.cos(), c * theta.sin())]; + const points = [ + Point3d.create(a - c * theta.cos(), c * theta.sin()), + Point3d.create(a, 0, 0), + Point3d.create(b, 0, 0), + Point3d.create(b + c * theta.cos(), c * theta.sin()), + ]; GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(points), x0, y0); const fullOffsetA = BuildingCodeOffsetOps.edgeByEdgeOffsetFromPoints(points, offsets, false); GeometryCoreTestIO.captureCloneGeometry(allGeometry, fullOffsetA, x0, y0); @@ -664,7 +722,10 @@ describe("Arc3d", () => { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, end1, 0.1, dx); const circularArc1 = Arc3d.createCircularStartTangentEnd(start1, tangent1, end1) as Arc3d; const circle1 = Arc3d.create( - circularArc1.center, circularArc1.vector0, circularArc1.vector90, AngleSweep.createStartEndDegrees(0, 360), + circularArc1.center, + circularArc1.vector0, + circularArc1.vector90, + AngleSweep.createStartEndDegrees(0, 360), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circularArc1, dx); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circle1, dx); @@ -693,7 +754,10 @@ describe("Arc3d", () => { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, end3, 0.1, dx); const circularArc3 = Arc3d.createCircularStartTangentEnd(start3, tangent3, end3) as Arc3d; const circle3 = Arc3d.create( - circularArc3.center, circularArc3.vector0, circularArc3.vector90, AngleSweep.createStartEndDegrees(0, 360), + circularArc3.center, + circularArc3.vector0, + circularArc3.vector90, + AngleSweep.createStartEndDegrees(0, 360), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circularArc3, dx); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circle3, dx); @@ -709,7 +773,10 @@ describe("Arc3d", () => { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, end4, 0.1, dx); const circularArc4 = Arc3d.createCircularStartTangentEnd(start4, tangent4, end4) as Arc3d; const circle4 = Arc3d.create( - circularArc4.center, circularArc4.vector0, circularArc4.vector90, AngleSweep.createStartEndDegrees(0, 360), + circularArc4.center, + circularArc4.vector0, + circularArc4.vector90, + AngleSweep.createStartEndDegrees(0, 360), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circularArc4, dx); GeometryCoreTestIO.captureCloneGeometry(allGeometry, circle4, dx); @@ -745,7 +812,11 @@ describe("Arc3d", () => { ck.testPoint3d(start, arc0.startPoint(), "constructed arc has expected start point"); ck.testPoint3d(end, arc0.endPoint(), "constructed arc has expected end point"); ck.testCoordinate(radius, arc0.circularRadius() ?? 0, "constructed arc has expected radius"); - ck.testCoordinate(0, arc0.matrixRef.dotColumnZ(Vector3d.createStartEnd(arc0.center, helperPoint)), "helperPoint is in plane of constructed arc"); + ck.testCoordinate( + 0, + arc0.matrixRef.dotColumnZ(Vector3d.createStartEnd(arc0.center, helperPoint)), + "helperPoint is in plane of constructed arc", + ); const intersectFractions = Vector2d.createZero(); SmallSystem.lineSegment3dClosestApproachUnbounded(arc0.center, helperPoint, start, end, intersectFractions); ck.testTrue(0 < intersectFractions.x && intersectFractions.x < 1, "center and helperPoint on opposite sides of chord"); @@ -780,37 +851,49 @@ describe("Arc3d", () => { describe("ApproximateArc3d", () => { const remaps: FractionMapper[] = []; - remaps.push((x: number) => x); // identity - remaps.push((x: number) => { // piecewise linear (under) + remaps.push((x: number) => x); // identity + remaps.push((x: number) => { // piecewise linear (under) const f = 0.6; // could be improved by dependence on eccentricity const slope = (1 - f) / f; return (x <= f) ? slope * x : slope * f + ((1 - slope * f) / (1 - f)) * (x - f); }); remaps.push((x: number) => Math.pow(x, 1.5)); // sqrt cubed - remaps.push((x: number) => x * x); // quadratic - remaps.push((x: number) => x * x * x); // cubic - remaps.push((x: number) => x * x * x * x); // quartic - remaps.push((x: number) => Math.sqrt(x)); // sqrt + remaps.push((x: number) => x * x); // quadratic + remaps.push((x: number) => x * x * x); // cubic + remaps.push((x: number) => x * x * x * x); // quartic + remaps.push((x: number) => Math.sqrt(x)); // sqrt function iMethodToString(iMethod: number | undefined): string { switch (iMethod) { - case -1: return "Naive"; - case 0: return "Identity"; - case 1: return "PwLinear"; - case 2: return "SqrtCubed"; - case 3: return "Quadratic"; - case 4: return "Cubic"; - case 5: return "Quartic"; - case 6: return "Sqrt"; - case 7: return "Subdivision"; + case -1: + return "Naive"; + case 0: + return "Identity"; + case 1: + return "PwLinear"; + case 2: + return "SqrtCubed"; + case 3: + return "Quadratic"; + case 4: + return "Cubic"; + case 5: + return "Quartic"; + case 6: + return "Sqrt"; + case 7: + return "Subdivision"; case undefined: - default: return "Undefined"; + default: + return "Undefined"; } } function displaySamples( allGeometry: GeometryQuery[], arc: Arc3d, samples: QuadrantFractions[] | number[], - x?: number, y?: number, z?: number, + x?: number, + y?: number, + z?: number, ): void { if (!GeometryCoreTestIO.enableSave) return; @@ -819,11 +902,21 @@ describe("ApproximateArc3d", () => { const quadrant = samples[i] as QuadrantFractions; for (let j = 0; j < quadrant.fractions.length - 1; ++j) // skip last fraction... GeometryCoreTestIO.createAndCaptureXYCircle( - allGeometry, arc.fractionToPoint(quadrant.fractions[j]), 0.1, x, y, z, + allGeometry, + arc.fractionToPoint(quadrant.fractions[j]), + 0.1, + x, + y, + z, ); if (i === samples.length - 1 && !arc.sweep.isFullCircle) // ...unless last fraction of last quadrant of open arc GeometryCoreTestIO.createAndCaptureXYCircle( - allGeometry, arc.fractionToPoint(quadrant.fractions[quadrant.fractions.length - 1]), 0.1, x, y, z, + allGeometry, + arc.fractionToPoint(quadrant.fractions[quadrant.fractions.length - 1]), + 0.1, + x, + y, + z, ); } } else { @@ -889,28 +982,28 @@ describe("ApproximateArc3d", () => { const arcs: Arc3d[] = []; // xy-plane, perp-axis arcs - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b)); // ccw full - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(0, 90))); // ccw Q1 - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(-100, 32))); // ccw contains seam - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(147, -100))); // cw contains seam - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(100, 120))); // ccw tiny sweep in one quadrant - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, a - 2, AngleSweep.createStartEndDegrees(90, 0))); // cw Q1 - arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, 1, AngleSweep.createStartEndDegrees(90, 270))); // ccw Q2+Q3 + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b)); // ccw full + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(0, 90))); // ccw Q1 + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(-100, 32))); // ccw contains seam + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(147, -100))); // cw contains seam + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, b, AngleSweep.createStartEndDegrees(100, 120))); // ccw tiny sweep in one quadrant + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, a - 2, AngleSweep.createStartEndDegrees(90, 0))); // cw Q1 + arcs.push(Arc3d.createXYEllipse(Point3d.createZero(), a, 1, AngleSweep.createStartEndDegrees(90, 270))); // ccw Q2+Q3 if (GeometryCoreTestIO.enableLongTests) { // general arcs const arc0 = Arc3d.create(Point3d.createZero(), Vector3d.create(2, 4, -1), Vector3d.create(3, 2, -3)); - arcs.push(arc0); // random #1 + arcs.push(arc0); // random #1 const perpData0 = arc0.toScaledMatrix3d(); const arc1 = Arc3d.createScaledXYColumns(perpData0.center, perpData0.axes, perpData0.r0, perpData0.r90); - arcs.push(arc1); // different start + arcs.push(arc1); // different start const arc2 = arc0.clone(); arc2.sweep = AngleSweep.createStartEndDegrees(345, -15); - arcs.push(arc2); // cw full, different start + arcs.push(arc2); // cw full, different start const arc3 = arc0.clone(); arc3.sweep = AngleSweep.createStartEndDegrees(100, 80); - arcs.push(arc3); // cw tiny sweep across 2 quadrants + arcs.push(arc3); // cw tiny sweep across 2 quadrants const arc4 = Arc3d.createStartMiddleEnd(Point3d.create(-1, -1, -2), Point3d.create(0.5, 0.5, 1.7), Point3d.create(1, 1, 2)); if (ck.testDefined(arc4, "use 3pt elliptical arc ctor")) - arcs.push(arc4); // random #2 + arcs.push(arc4); // random #2 } const convertToFlatArray = (array: QuadrantFractions[] | number[]): number[] => { @@ -949,8 +1042,14 @@ describe("ApproximateArc3d", () => { break; } } - const rotateY180 = Transform.createOriginAndMatrix(undefined, Matrix3d.createRotationAroundVector(arc.matrixRef.columnY(), Angle.createDegrees(180))); - const rotateX180 = Transform.createOriginAndMatrix(undefined, Matrix3d.createRotationAroundVector(arc.matrixRef.columnX(), Angle.createDegrees(180))); + const rotateY180 = Transform.createOriginAndMatrix( + undefined, + Matrix3d.createRotationAroundVector(arc.matrixRef.columnY(), Angle.createDegrees(180)), + ); + const rotateX180 = Transform.createOriginAndMatrix( + undefined, + Matrix3d.createRotationAroundVector(arc.matrixRef.columnX(), Angle.createDegrees(180)), + ); for (const q of structured) { // compare to reflections of other quadrants if (q.quadrant > 1) { const pts: Point3d[] = []; @@ -1002,8 +1101,10 @@ describe("ApproximateArc3d", () => { // test error computation const chainError = context.computeApproximationError(samples); - if (ck.testDefined(chainError, "cover arc chain approximation error computation") && - ck.testTrue(chainError.detailA.a > Geometry.smallFraction, "computed a nonzero arc chain approximation error")) { + if ( + ck.testDefined(chainError, "cover arc chain approximation error computation") && + ck.testTrue(chainError.detailA.a > Geometry.smallFraction, "computed a nonzero arc chain approximation error") + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, [chainError.detailA.point, chainError.detailB.point], x, y); } return { err: chainError ? chainError.detailA.a : undefined, nSeg: chain ? chain.children.length : 0 }; @@ -1071,7 +1172,9 @@ describe("ApproximateArc3d", () => { ck.testDefined(iMin, "Have best approx method id") && ck.testDefined(nMin, "Have best approx segment count") ) { - GeometryCoreTestIO.consoleLog(`Arc ${iArc} min error is ${eMin} using ${iMethodToString(iMin)} on ${n} Q1 samples with chain count ${nMin}.`); + GeometryCoreTestIO.consoleLog( + `Arc ${iArc} min error is ${eMin} using ${iMethodToString(iMin)} on ${n} Q1 samples with chain count ${nMin}.`, + ); const numWins = methodWins.get(iMin) ?? 0; methodWins.set(iMin, numWins + 1); } @@ -1148,7 +1251,10 @@ describe("ApproximateArc3d", () => { } else if (ellipticalArc.isCircular) { if (options.forcePath && ellipticalArc.sweep.isFullCircle) { if (ck.testType(approx, Path, "nearly circular full elliptical arc approximation with forcePath is a Path")) - ck.testTrue(approx.children.length === 1 && ellipticalArc === approx.children[0], "nearly circular elliptical arc Path approximation has the input arc as only child"); + ck.testTrue( + approx.children.length === 1 && ellipticalArc === approx.children[0], + "nearly circular elliptical arc Path approximation has the input arc as only child", + ); } else { if (ck.testType(approx, Arc3d, "nearly circular elliptical arc approximation with !forcePath is an Arc3d")) ck.testTrue(ellipticalArc === approx, "nearly circular elliptical arc Arc3d approximation is the input arc"); @@ -1157,7 +1263,14 @@ describe("ApproximateArc3d", () => { return { approx, error, errorSegment, nSamplesQ1, isValidArc: context.isValidEllipticalArc }; }; - const compareToSubdivision = (ellipticalArc: Arc3d, e: number, swapped: boolean, iMethod: number, options: EllipticalArcApproximationOptions, subdivisionResult: Approximation): boolean => { + const compareToSubdivision = ( + ellipticalArc: Arc3d, + e: number, + swapped: boolean, + iMethod: number, + options: EllipticalArcApproximationOptions, + subdivisionResult: Approximation, + ): boolean => { const result = analyzeQ1Approximation(ellipticalArc, options); ck.testTrue(result.isValidArc, `${iMethodToString(iMethod)} approximation is valid`); ck.testExactNumber(subdivisionResult.nSamplesQ1, result.nSamplesQ1, `${iMethodToString(iMethod)} approximation has expected sample count`); @@ -1166,7 +1279,13 @@ describe("ApproximateArc3d", () => { ++nSubdivisionComparisonWins; } else { // subdivision has worse error; we expect this to happen some of the time. Report only unexpectedly large error. Observed as much as 68% overshoot. const overshootPct = 100 * (subdivisionResult.error - result.error) / result.error; - ck.testLE(overshootPct, 70, `subdivision came within 70% of beating ${iMethodToString(iMethod)} on ${subdivisionResult.nSamplesQ1} samples of eccentricity ${e} ellipse ${swapped ? "(swapped)" : ""}`); + ck.testLE( + overshootPct, + 70, + `subdivision came within 70% of beating ${ + iMethodToString(iMethod) + } on ${subdivisionResult.nSamplesQ1} samples of eccentricity ${e} ellipse ${swapped ? "(swapped)" : ""}`, + ); if (!swapped) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, ellipticalArc, x, y, -delta); GeometryCoreTestIO.captureCloneGeometry(allGeometry, result.approx, x, y); @@ -1248,7 +1367,11 @@ describe("ApproximateArc3d", () => { const winOverallPct = 100 * Geometry.safeDivideFraction(nEllipses - nSubdivisionLosses, nEllipses, 0); GeometryCoreTestIO.consoleLog(`Subdivision wins overall for ${nEllipses - nSubdivisionLosses} of ${nEllipses} ellipses (${winOverallPct}%).`); const targetNSampleWinPct = GeometryCoreTestIO.enableLongTests ? 80 : 60; - ck.testLE(targetNSampleWinPct, winOverallPct, `Subdivision is more accurate than all other n-sample methods over ${targetNSampleWinPct}% of the time.`); + ck.testLE( + targetNSampleWinPct, + winOverallPct, + `Subdivision is more accurate than all other n-sample methods over ${targetNSampleWinPct}% of the time.`, + ); // test forcePath behavior on closed input const fullEllipse = Arc3d.createXYEllipse(center, a, a / 2); @@ -1260,12 +1383,27 @@ describe("ApproximateArc3d", () => { analyzeQ1Approximation(fullCircle, optionsA); // previously, these arcs' approximations exceeded the desired max error - interface AnomalousArc { arc: Arc3d, maxError: number }; + interface AnomalousArc { + arc: Arc3d; + maxError: number; + } const anomalousArcs: AnomalousArc[] = []; - anomalousArcs.push({ arc: Arc3d.create(Point3d.createZero(), Vector3d.create(5, 0), Vector3d.create(0, 8), AngleSweep.createStartEndDegrees(0, -63)), maxError: 0.01 }); - anomalousArcs.push({ arc: Arc3d.createXYEllipse(Point3d.createZero(), 10, 8, AngleSweep.createStartEndDegrees(90, 0)), maxError: 0.001836772806889095 }); - anomalousArcs.push({ arc: Arc3d.create(Point3d.createZero(), Vector3d.create(2, 4, -1), Vector3d.create(3, 2, -3)), maxError: 0.004891996419172132 }); - anomalousArcs.push({ arc: Arc3d.create(Point3d.createZero(), Vector3d.create(2, 4, -1), Vector3d.create(3, 2, -3), AngleSweep.createStartEndDegrees(-15, 345)), maxError: 0.0005076837030701749 }); + anomalousArcs.push({ + arc: Arc3d.create(Point3d.createZero(), Vector3d.create(5, 0), Vector3d.create(0, 8), AngleSweep.createStartEndDegrees(0, -63)), + maxError: 0.01, + }); + anomalousArcs.push({ + arc: Arc3d.createXYEllipse(Point3d.createZero(), 10, 8, AngleSweep.createStartEndDegrees(90, 0)), + maxError: 0.001836772806889095, + }); + anomalousArcs.push({ + arc: Arc3d.create(Point3d.createZero(), Vector3d.create(2, 4, -1), Vector3d.create(3, 2, -3)), + maxError: 0.004891996419172132, + }); + anomalousArcs.push({ + arc: Arc3d.create(Point3d.createZero(), Vector3d.create(2, 4, -1), Vector3d.create(3, 2, -3), AngleSweep.createStartEndDegrees(-15, 345)), + maxError: 0.0005076837030701749, + }); const optionsB = EllipticalArcApproximationOptions.create(EllipticalArcSampleMethod.AdaptiveSubdivision); for (const anomalousArc of anomalousArcs) { optionsB.maxError = anomalousArc.maxError; diff --git a/core/geometry/src/test/curve/AustralianRailCorpSpiral.test.ts b/core/geometry/src/test/curve/AustralianRailCorpSpiral.test.ts index 4ff5c39ae275..2ac3d5411133 100644 --- a/core/geometry/src/test/curve/AustralianRailCorpSpiral.test.ts +++ b/core/geometry/src/test/curve/AustralianRailCorpSpiral.test.ts @@ -41,7 +41,6 @@ describe("AustralianRailCorpSpiral", () => { ck.testTightNumber(y1 * scaleFactor, yA, " y from scaled construction"); ck.testTightNumber(x1 * scaleFactor, xB, "x from scaled clone"); ck.testTightNumber(y1 * scaleFactor, yB, "y from scaled clone"); - } } diff --git a/core/geometry/src/test/curve/BuildingCodeOffsetOps.ts b/core/geometry/src/test/curve/BuildingCodeOffsetOps.ts index b9fe74dd4ccc..033caf23d554 100644 --- a/core/geometry/src/test/curve/BuildingCodeOffsetOps.ts +++ b/core/geometry/src/test/curve/BuildingCodeOffsetOps.ts @@ -4,21 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { Arc3d } from "../../curve/Arc3d"; +import { CurvePrimitive } from "../../curve/CurvePrimitive"; +import { LineSegment3d } from "../../curve/LineSegment3d"; +import { Loop } from "../../curve/Loop"; +import { Path } from "../../curve/Path"; import { Geometry } from "../../Geometry"; import { AngleSweep } from "../../geometry3d/AngleSweep"; +import { GrowableFloat64Array } from "../../geometry3d/GrowableFloat64Array"; +import { Vector2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { LineSegment3d } from "../../curve/LineSegment3d"; import { AnalyticRoots, SmallSystem } from "../../numerics/Polynomials"; -import { Vector2d } from "../../geometry3d/Point2dVector2d"; -import { Path } from "../../curve/Path"; -import { Loop } from "../../curve/Loop"; -import { CurvePrimitive } from "../../curve/CurvePrimitive"; -import { GrowableFloat64Array } from "../../geometry3d/GrowableFloat64Array"; /** * Assorted static methods for constructing fragmentary and complete curves for offsets from linestrings. * * Primary method is the static edgeByEdgeOffsetFromPoints * * - * */ export class BuildingCodeOffsetOps { /** @@ -33,7 +32,13 @@ export class BuildingCodeOffsetOps { * @param offsetAB offset along edge from pointA to pointB. Positive is to the right (outside of a CCW turn) * @param offsetBC offset along edge from pointB to pointC. Positive is tot he right (outside of a CCW turn) */ - public static createJointWithRadiusChange(pointA: Point3d, pointB: Point3d, pointC: Point3d, offsetAB: number, offsetBC: number): CurvePrimitive | Point3d | undefined { + public static createJointWithRadiusChange( + pointA: Point3d, + pointB: Point3d, + pointC: Point3d, + offsetAB: number, + offsetBC: number, + ): CurvePrimitive | Point3d | undefined { // enforce same-sign: if (offsetAB * offsetBC < 0.0) return undefined; diff --git a/core/geometry/src/test/curve/CoincidentGeometryQuery.test.ts b/core/geometry/src/test/curve/CoincidentGeometryQuery.test.ts index b4b5c9586ac6..392396e5d475 100644 --- a/core/geometry/src/test/curve/CoincidentGeometryQuery.test.ts +++ b/core/geometry/src/test/curve/CoincidentGeometryQuery.test.ts @@ -16,7 +16,6 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; import { prettyPrint } from "../testFunctions"; describe("CoincidentGeometryQuery", () => { - it("SegmentSegment", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -36,7 +35,7 @@ describe("CoincidentGeometryQuery", () => { for (const fA0 of fractionsOnA) { let y0 = 0.0; for (const fA1 of fractionsOnA) { - if (fA1 === fA0) // only do non trivial + if (fA1 === fA0) // only do non trivial continue; const rangeA = Range1d.createXX(fA0, fA1); const rangeA01 = rangeA.intersect(range01); @@ -109,7 +108,7 @@ describe("CoincidentGeometryQuery", () => { for (const fA0 of fractionsOnA) { let y0 = 0.0; for (const fA1 of fractionsOnA) { - if (fA1 === fA0) // only do non trivial + if (fA1 === fA0) // only do non trivial continue; const arcB = arcA.clone(); arcB.sweep.setStartEndRadians(arcA.sweep.fractionToRadians(fA0), arcA.sweep.fractionToRadians(fA1)); @@ -150,5 +149,4 @@ describe("CoincidentGeometryQuery", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CoincidentGeometryQuery", "ArcArc"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/curve/Curve.test.ts b/core/geometry/src/test/curve/Curve.test.ts index a0639bb3494b..b45ad6894062 100644 --- a/core/geometry/src/test/curve/Curve.test.ts +++ b/core/geometry/src/test/curve/Curve.test.ts @@ -63,13 +63,27 @@ class StrokeCountSearch extends NullGeometryHandler { return this.emitPackedStrokeCountMap(g.strokeData); return undefined; } - public override handleLineString3d(g: LineString3d) { return { numLineString3d: this.emitCountData(g) }; } - public override handleArc3d(g: Arc3d) { return { numArc3d: this.emitCountData(g) }; } - public override handleLineSegment3d(g: LineSegment3d) { return { numLineSegment3d: this.emitCountData(g) }; } - public override handleBSplineCurve3d(g: BSplineCurve3d) { return { numBSplineCurve3d: this.emitCountData(g) }; } - public override handleBSplineCurve3dH(g: BSplineCurve3dH) { return { numBSplineCurve3dH: this.emitCountData(g) }; } - public override handleBezierCurve3d(g: BezierCurve3d) { return { numBezierCurve3d: this.emitCountData(g) }; } - public override handleBezierCurve3dH(g: BezierCurve3dH) { return { numBezierCurve3dH: this.emitCountData(g) }; } + public override handleLineString3d(g: LineString3d) { + return { numLineString3d: this.emitCountData(g) }; + } + public override handleArc3d(g: Arc3d) { + return { numArc3d: this.emitCountData(g) }; + } + public override handleLineSegment3d(g: LineSegment3d) { + return { numLineSegment3d: this.emitCountData(g) }; + } + public override handleBSplineCurve3d(g: BSplineCurve3d) { + return { numBSplineCurve3d: this.emitCountData(g) }; + } + public override handleBSplineCurve3dH(g: BSplineCurve3dH) { + return { numBSplineCurve3dH: this.emitCountData(g) }; + } + public override handleBezierCurve3d(g: BezierCurve3d) { + return { numBezierCurve3d: this.emitCountData(g) }; + } + public override handleBezierCurve3dH(g: BezierCurve3dH) { + return { numBezierCurve3dH: this.emitCountData(g) }; + } public override handleCurveChainWithDistanceIndex(g: CurveChainWithDistanceIndex) { const data = { numCurveVectorWithDistanceIndex: this.emitCountData(g) }; const children = g.children; @@ -113,7 +127,6 @@ function curvePrimitiveHasInstanceOf(cp: CurvePrimitive, cla } class ExerciseCurve { public static exerciseStrokeData(ck: Checker, curve: CurvePrimitive) { - const curveA = curve.clone(); const count0 = curveA.computeStrokeCountForOptions(); curveA.computeAndAttachRecursiveStrokeCounts(); @@ -146,11 +159,13 @@ class ExerciseCurve { ck.testCoordinate(scaleFactor * pointA0.distance(pointA1), pointB0.distance(pointB1)); const frameA0 = curveA.fractionToFrenetFrame(u0); const frameB0 = curveB.fractionToFrenetFrame(u0); - if (frameA0 && frameB0 + if ( + frameA0 && frameB0 /* ck.testPointer(frameA0) && ck.testPointer(frameB0) && frameA0 - && frameB0*/ ) { + && frameB0*/ + ) { ck.testTransform(frameA0, frameB0); const frameA0Inverse = frameA0.inverse(); if (ck.testPointer(frameA0Inverse)) { @@ -158,14 +173,17 @@ class ExerciseCurve { curveA.extendRange(rangeA2, frameA0Inverse); const planeA2 = Plane3dByOriginAndUnitNormal.create( Point3d.createFrom(frameA0.origin), - frameA0.matrix.columnZ()); - ck.testBoolean(curveA.isInPlane(planeA2!), + frameA0.matrix.columnZ(), + ); + ck.testBoolean( + curveA.isInPlane(planeA2!), Geometry.isSmallMetricDistance(rangeA2.zLength()), - "Surface planarity test versus range in frame"); + "Surface planarity test versus range in frame", + ); } } } - const upperFractions = [0.3, 0.5, 0.912312, 1.0]; // do NOT include 0.0 ... + const upperFractions = [0.3, 0.5, 0.912312, 1.0]; // do NOT include 0.0 ... let fraction0 = 0; const totalLength = curveA.curveLength(); const totalRange = curveA.range(); @@ -194,8 +212,10 @@ class ExerciseCurve { if (curvePrimitiveHasInstanceOf(curveA, InterpolationCurve3d)) { // just skip it -- ranges are wonky. // bug in interpolation curve? distance index confused by proxy? - } else if (curvePrimitiveHasInstanceOf(curveA, BSplineCurve3dBase) - || curvePrimitiveHasInstanceOf(curveA, TransitionSpiral3d)) { + } else if ( + curvePrimitiveHasInstanceOf(curveA, BSplineCurve3dBase) + || curvePrimitiveHasInstanceOf(curveA, TransitionSpiral3d) + ) { // ugh. bspline are pole boundaries that are not tight ck.testTrue(totalRange1.containsPoint(summedRange.low), "range low by parts"); ck.testTrue(totalRange1.containsPoint(summedRange.high), "range high by parts"); @@ -220,7 +240,7 @@ class ExerciseCurve { } } public static exerciseCurvePlaneIntersections(ck: Checker, curve: CurvePrimitive) { - if (curve instanceof BSplineCurve3d) return; // TODO + if (curve instanceof BSplineCurve3d) return; // TODO // if (curve instanceof TransitionSpiral3d) return; // TODO for (const fractionA of [0.421, 0.421, 0.45, 0.45]) { const tangentA = curve.fractionToPointAndDerivative(fractionA); @@ -234,22 +254,26 @@ class ExerciseCurve { return Geometry.isAlmostEqualNumber(detail.fraction, fractionA); // Different curve -- maybe a constituent? accept based on points return plane.getOriginRef().isAlmostEqual(detail.point); - }); + }, + ); ck.testTrue(foundAt.length >= 1, "planeCurveIntersections", curve, plane, fractionA); } } } public static exerciseMoveSignedDistance(ck: Checker, curve: CurvePrimitive) { - for (const segment of [ - Segment1d.create(0.0, 0.5), - Segment1d.create(0.5, 1.0), - Segment1d.create(0.1, 0.35), - Segment1d.create(0.38, 0.92), - Segment1d.create(-0.1, 0.2), - Segment1d.create(-0.1, 0.2), - Segment1d.create(0.9, 1.2), - Segment1d.create(0.9, 1.2)]) { + for ( + const segment of [ + Segment1d.create(0.0, 0.5), + Segment1d.create(0.5, 1.0), + Segment1d.create(0.1, 0.35), + Segment1d.create(0.38, 0.92), + Segment1d.create(-0.1, 0.2), + Segment1d.create(-0.1, 0.2), + Segment1d.create(0.9, 1.2), + Segment1d.create(0.9, 1.2), + ] + ) { const a = segment.x0; const b = segment.x1; const distanceAB = curve.curveLengthBetweenFractions(a, b); @@ -260,14 +284,18 @@ class ExerciseCurve { } let detailAtoB = curve.moveSignedDistanceFromFraction(a, distanceAB, true); let detailBtoA = curve.moveSignedDistanceFromFraction(b, -distanceAB, true); - if (!segment.isIn01 && + if ( + !segment.isIn01 && (detailAtoB.curveSearchStatus === CurveSearchStatus.stoppedAtBoundary - || detailBtoA.curveSearchStatus === CurveSearchStatus.stoppedAtBoundary)) { + || detailBtoA.curveSearchStatus === CurveSearchStatus.stoppedAtBoundary) + ) { // um .. not sure what to test for - } else if (detailAtoB.curveSearchStatus === undefined + } else if ( + detailAtoB.curveSearchStatus === undefined || detailBtoA.curveSearchStatus === undefined || detailAtoB.curveSearchStatus !== CurveSearchStatus.success - || detailBtoA.curveSearchStatus !== CurveSearchStatus.success) { + || detailBtoA.curveSearchStatus !== CurveSearchStatus.success + ) { detailAtoB = curve.moveSignedDistanceFromFraction(a, distanceAB, true); detailBtoA = curve.moveSignedDistanceFromFraction(b, -distanceAB, true); ck.announceError("Incomplete moveSignedDistanceFromFraction", a, b, curve); @@ -276,13 +304,17 @@ class ExerciseCurve { ck.testCoordinate(b, detailAtoB.fraction); ck.testCoordinate(a, detailBtoA.fraction); } else { - } } } } - public static exerciseFractionToPoint(ck: Checker, curve: CurvePrimitive | undefined, expectProportionalDistance: boolean, expectEqualChordLength: boolean) { + public static exerciseFractionToPoint( + ck: Checker, + curve: CurvePrimitive | undefined, + expectProportionalDistance: boolean, + expectEqualChordLength: boolean, + ) { if (!curve) { ck.announceError("Null CurvePrimitive provided to exerciseFractionAndPoint"); return; @@ -332,8 +364,14 @@ class ExerciseCurve { ck.testPoint3d(pointA1, derivativeRay.origin); const approximateDerivative = delta02.scale(0.5 / derivativeIncrement); const approximateDerivative2 = delta012.scale(1.0 / (derivativeIncrement * derivativeIncrement)); - ck.testTrue(approximateDerivative.distance(derivativeRay.direction) < derivativeTolerance * (1 + derivativeRay.direction.magnitude()), - "approximate derivative", derivativeRay.direction, approximateDerivative, curve, fraction); + ck.testTrue( + approximateDerivative.distance(derivativeRay.direction) < derivativeTolerance * (1 + derivativeRay.direction.magnitude()), + "approximate derivative", + derivativeRay.direction, + approximateDerivative, + curve, + fraction, + ); if (plane1) { // curve instanceof TransitionSpiral3d ck.testPoint3d(derivativeRay.origin, plane1.origin, "points with derivatives"); if (!(curve instanceof TransitionSpiral3d) && !plane1.vectorV.isAlmostZero) { @@ -345,12 +383,14 @@ class ExerciseCurve { curve.fractionToPointAnd2Derivatives(fraction); const q = approximateDerivative2.distance(plane1.vectorV); if (!ck.testTrue(q < derivative2Tolerance * (1 + plane1.vectorV.magnitude()))) { - curve.fractionToPointAnd2Derivatives(fraction); // for debug + curve.fractionToPointAnd2Derivatives(fraction); // for debug const magU = plane1.vectorU.magnitude(); const magV = plane1.vectorV.magnitude(); const magV2 = approximateDerivative2.magnitude(); const ratio = magV / magV2; - GeometryCoreTestIO.consoleLog(` (magU ${magU} (magV ${magV} (magV2 ${magV2} (magV/magV2 ${ratio} (L ${curve.curveLength()} (radians ${radians}`); + GeometryCoreTestIO.consoleLog( + ` (magU ${magU} (magV ${magV} (magV2 ${magV2} (magV/magV2 ${ratio} (L ${curve.curveLength()} (radians ${radians}`, + ); curve.fractionToPointAnd2Derivatives(fraction); } } @@ -383,12 +423,21 @@ class ExerciseCurve { } } - public static exerciseClosestPointDetail(ck: Checker, detail: CurveLocationDetail | undefined, curve: CurvePrimitive, resultPt: Point3d, testPt: Point3d, testFraction: number): boolean { + public static exerciseClosestPointDetail( + ck: Checker, + detail: CurveLocationDetail | undefined, + curve: CurvePrimitive, + resultPt: Point3d, + testPt: Point3d, + testFraction: number, + ): boolean { let succeeded = true; if (ck.testPointer(detail) && ck.testPointer(detail.curve)) { if (detail.curve === curve) { - if (!ck.testCoordinate(testFraction, detail.fraction, "fraction round trip", curve) - || !ck.testPoint3d(resultPt, detail.point, "round trip point")) { + if ( + !ck.testCoordinate(testFraction, detail.fraction, "fraction round trip", curve) + || !ck.testPoint3d(resultPt, detail.point, "round trip point") + ) { succeeded = false; detail = curve.closestPoint(testPt, false); } @@ -402,7 +451,15 @@ class ExerciseCurve { return succeeded; } - public static exerciseClosestPoint(ck: Checker, curve: CurvePrimitive, fractionA: number, allGeometry?: GeometryQuery[], x0: number = 0, y0: number = 0, z0: number = 0): boolean { + public static exerciseClosestPoint( + ck: Checker, + curve: CurvePrimitive, + fractionA: number, + allGeometry?: GeometryQuery[], + x0: number = 0, + y0: number = 0, + z0: number = 0, + ): boolean { // test point on curve projects to itself const pointA = curve.fractionToPoint(fractionA); let detail = curve.closestPoint(pointA, false); @@ -451,8 +508,10 @@ class ExerciseCurve { curve.emitStrokes(strokesB, options); // add slop to pass CurveChainWithDistanceIndex with 2-pt InterpolationCurve3d inside, for which quickLength is smaller by 9.0e-16 ck.testLE(strokeLength, curveLength + Geometry.smallMetricDistanceSquared, "strokeLength cannot exceed curveLength"); - if (!ck.testLE(chordFraction * curveLength, strokeLength, "strokes appear accurate") - || Checker.noisy.stroke) { + if ( + !ck.testLE(chordFraction * curveLength, strokeLength, "strokes appear accurate") + || Checker.noisy.stroke + ) { GeometryCoreTestIO.consoleLog(" CURVE", curve); const curveLength1 = curve.curveLength(); GeometryCoreTestIO.consoleLog("computed length", curveLength1); @@ -475,10 +534,7 @@ class ExerciseCurve { } { // a circular arc . . . - const arc = Arc3d.create(Point3d.create(1, 2, 3), - Vector3d.create(2, 0, 0), - Vector3d.create(0, 2, 0), - AngleSweep.createStartEndDegrees(0, 180)); + const arc = Arc3d.create(Point3d.create(1, 2, 3), Vector3d.create(2, 0, 0), Vector3d.create(0, 2, 0), AngleSweep.createStartEndDegrees(0, 180)); if (arc) { ExerciseCurve.exerciseFractionToPoint(ck, arc, false, true); ExerciseCurve.exerciseMoveSignedDistance(ck, arc); @@ -491,10 +547,7 @@ class ExerciseCurve { } { // a non-circular arc . . . (much harder computations!!) - const arc = Arc3d.create(Point3d.create(1, 2, 3), - Vector3d.create(3, 0, 0), - Vector3d.create(0, 2, 0), - AngleSweep.createStartEndDegrees(0, 180)); + const arc = Arc3d.create(Point3d.create(1, 2, 3), Vector3d.create(3, 0, 0), Vector3d.create(0, 2, 0), AngleSweep.createStartEndDegrees(0, 180)); if (arc) { ExerciseCurve.exerciseFractionToPoint(ck, arc, false, false); ExerciseCurve.exerciseMoveSignedDistance(ck, arc); @@ -510,7 +563,8 @@ class ExerciseCurve { const linestring = LineString3d.createPoints([ Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), - Point3d.create(1, 1, 0)]); + Point3d.create(1, 1, 0), + ]); ExerciseCurve.exerciseFractionToPoint(ck, linestring, false, false); ExerciseCurve.exerciseMoveSignedDistance(ck, linestring); ExerciseCurve.exerciseStroke(ck, linestring); @@ -523,7 +577,8 @@ class ExerciseCurve { const linestring = LineString3d.create( Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), - Point3d.create(2, 1, 0)); + Point3d.create(2, 1, 0), + ); ExerciseCurve.exerciseFractionToPoint(ck, linestring, false, false); ExerciseCurve.exerciseMoveSignedDistance(ck, linestring); ExerciseCurve.exerciseStroke(ck, linestring); @@ -588,7 +643,8 @@ class ExerciseCurve { Point4d.create(5, 0, 0, 0.8), Point4d.create(10, 4, 0, 1), Point4d.create(15, 4, 0, 1), - Point4d.create(20, 0, 0, 1)]; + Point4d.create(20, 0, 0, 1), + ]; for (let order = 3; order <= poles4d.length; order++) { const bcurveH = BSplineCurve3dH.createUniformKnots(poles4d, order); GeometryCoreTestIO.captureCloneGeometry(allGeometry, bcurveH, dx); @@ -657,7 +713,11 @@ class ExerciseCurve { { const bezierCurve3d = BezierCurve3dH.create([ - Point3d.create(0, 0), Point3d.create(0.5, 0.0), Point3d.create(1, 1), Point3d.create(2, 1, 1)])!; + Point3d.create(0, 0), + Point3d.create(0.5, 0.0), + Point3d.create(1, 1), + Point3d.create(2, 1, 1), + ])!; ExerciseCurve.exerciseFractionToPoint(ck, bezierCurve3d, false, false); ExerciseCurve.exerciseMoveSignedDistance(ck, bezierCurve3d); ExerciseCurve.exerciseStroke(ck, bezierCurve3d); @@ -668,15 +728,22 @@ class ExerciseCurve { { if (Checker.noisy.testTransitionSpiral) { - for (const spiral of [ - IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 10), Segment1d.create(0, 1), Transform.createIdentity()), - DirectSpiral3d.createDirectHalfCosine(Transform.createIdentity(), 100, 300, undefined), - DirectSpiral3d.createJapaneseCubic(Transform.createIdentity(), 100, 300, undefined), - DirectSpiral3d.createArema(Transform.createIdentity(), 100, 300, undefined), - ]) { + for ( + const spiral of [ + IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 10), + Segment1d.create(0, 1), + Transform.createIdentity(), + ), + DirectSpiral3d.createDirectHalfCosine(Transform.createIdentity(), 100, 300, undefined), + DirectSpiral3d.createJapaneseCubic(Transform.createIdentity(), 100, 300, undefined), + DirectSpiral3d.createArema(Transform.createIdentity(), 100, 300, undefined), + ] + ) { if (ck.testPointer(spiral)) { ExerciseCurve.exerciseCurvePlaneIntersections(ck, spiral); - ExerciseCurve.exerciseFractionToPoint(ck, spiral, (spiral instanceof IntegratedSpiral3d), false); + ExerciseCurve.exerciseFractionToPoint(ck, spiral, spiral instanceof IntegratedSpiral3d, false); ExerciseCurve.exerciseStroke(ck, spiral); ExerciseCurve.exerciseClosestPoint(ck, spiral, 0.3, allGeometry, dx); GeometryCoreTestIO.captureGeometry(allGeometry, spiral, dx); @@ -781,7 +848,7 @@ describe("Curves", () => { } const c0x = p.closestPoint(p0, CurveExtendMode.OnCurve); const c1x = p.closestPoint(p1, CurveExtendMode.OnCurve); - const proximityFactor = 0.01; // WE TRUST THAT THE CURVE DOES NOT BEND MUCH IN SMALL EXTRAPOLATION -- projected point should be closer than extension distance. + const proximityFactor = 0.01; // WE TRUST THAT THE CURVE DOES NOT BEND MUCH IN SMALL EXTRAPOLATION -- projected point should be closer than extension distance. if (ck.testPointer(c0x)) { if (c0x.childDetail && c0x.childDetail.curve!.isExtensibleFractionSpace) ck.testLT(p0.distance(c0x.point), proximityFactor * e, "small distance from curve"); @@ -804,10 +871,10 @@ describe("Curves", () => { it("DistanceIndexMismatches", () => { const ck = new Checker(); - const pathA = Sample.createSquareWavePath(4, 1, 1, 0, 1, 0); // 4 waves as one linestring - const pathB = Sample.createSquareWavePath(1, 1, 1, 0, 1, 0); // 1 wave as one linestring - const pathC = Sample.createSquareWavePath(1, 1, 1, 0, 0, 1); // 1 wave as 4 line segments - const pathD = Sample.createSquareWavePath(4, 1, 1, 0, 0, 2); // 4 wave as 4 linestrings + const pathA = Sample.createSquareWavePath(4, 1, 1, 0, 1, 0); // 4 waves as one linestring + const pathB = Sample.createSquareWavePath(1, 1, 1, 0, 1, 0); // 1 wave as one linestring + const pathC = Sample.createSquareWavePath(1, 1, 1, 0, 0, 1); // 1 wave as 4 line segments + const pathD = Sample.createSquareWavePath(4, 1, 1, 0, 0, 2); // 4 wave as 4 linestrings const emptyBag = BagOfCurves.create(); const bag1 = BagOfCurves.create(); const bagWithPath = BagOfCurves.create(pathA.clone()); @@ -836,9 +903,18 @@ describe("Curves", () => { ck.testUndefined(RuledSweep.mutatePartners(bag1, bag1, returnUndefined), "mutatePartners notices failed mutator"); ck.testUndefined(emptyBag.getChild(0)); ck.testUndefined(bag1.getChild(4)); - ck.testUndefined(RuledSweep.mutatePartners(pathA, (lineSegment as any) as CurveCollection, returnUndefined), "mutatePartners rejects non-collection"); - ck.testUndefined(RuledSweep.mutatePartners((lineSegment as any) as CurveCollection, (lineSegment as any) as CurveCollection, returnUndefined), "mutatePartners rejects non-collection"); - ck.testUndefined(RuledSweep.mutatePartners(bagWithPath, bagWithPath, returnUndefined), "mutatePartners sees undefined step for collection in bag"); + ck.testUndefined( + RuledSweep.mutatePartners(pathA, (lineSegment as any) as CurveCollection, returnUndefined), + "mutatePartners rejects non-collection", + ); + ck.testUndefined( + RuledSweep.mutatePartners((lineSegment as any) as CurveCollection, (lineSegment as any) as CurveCollection, returnUndefined), + "mutatePartners rejects non-collection", + ); + ck.testUndefined( + RuledSweep.mutatePartners(bagWithPath, bagWithPath, returnUndefined), + "mutatePartners sees undefined step for collection in bag", + ); ck.checkpoint("CurvePrimitive.DistanceIndexMismatches"); GeometryCoreTestIO.saveGeometry(allGeometry, "CurvePrimitive", "CurveChainWithDistanceIndex"); @@ -871,10 +947,12 @@ describe("Curves", () => { if (ck.testDefined(detail)) { const unitTangent = indexedPath.fractionToPointAndUnitTangent(detail.fraction); // strokes .. space point to new evaluation to short step on tangent back to nearby point on line from space point to detail point - GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(spacePoint, unitTangent.origin, - unitTangent.fractionToPoint(0.05), - spacePoint.interpolate(0.95, detail.point)), x0, y0); - + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineString3d.create(spacePoint, unitTangent.origin, unitTangent.fractionToPoint(0.05), spacePoint.interpolate(0.95, detail.point)), + x0, + y0, + ); } } } @@ -887,7 +965,6 @@ describe("Curves", () => { expect(ck.getNumErrors()).toBe(0); }); - }); class NewtonEvaluatorClosestPointOnCurve extends NewtonEvaluatorRtoR { @@ -911,7 +988,6 @@ class NewtonEvaluatorClosestPointOnCurve extends NewtonEvaluatorRtoR { // GeometryCoreTestIO.consoleLog("evaluate ", this.lastFraction, this.lastEvaluationA, this.currentF); return true; } - } describe("CurvePrimitive.Newton", () => { it("CurvePrimitive.Newton", () => { @@ -923,7 +999,7 @@ describe("CurvePrimitive.Newton", () => { const xyz = c.fractionToPoint(f); const evaluator = new NewtonEvaluatorClosestPointOnCurve(c, xyz); const searcher = new Newton1dUnboundedApproximateDerivative(evaluator); - searcher.setX(f + initialShift); // start searching from a fraction close to the known result. + searcher.setX(f + initialShift); // start searching from a fraction close to the known result. // the step cannot be too big for nasty curves !!! // GeometryCoreTestIO.consoleLog("search at fraction " + f); if (ck.testBoolean(true, searcher.runIterations(), "Newton finish")) { @@ -943,7 +1019,8 @@ describe("CurvePrimitive.TransitionSpiral", () => { Segment1d.create(0, 100), AngleSweep.createStartEndDegrees(0, 5), Segment1d.create(0, 1), - Transform.createIdentity())!; + Transform.createIdentity(), + )!; const point0 = c.fractionToPointAndDerivative(0); const point1 = Ray3d.createZero(); const numStroke = 50; @@ -1047,7 +1124,8 @@ function findPointInCLDArray(point: Point3d, data: CurveLocationDetail[], startI function testCurveIntervalRole( ck: Checker, cld: CurveLocationDetail, - values: CurveIntervalRole[]): boolean { + values: CurveIntervalRole[], +): boolean { const value = cld.intervalRole; for (const v of values) if (v === value) return true; @@ -1062,25 +1140,33 @@ describe("Linestring3dSpecials", () => { const ay = a; const az = a; const geometry = []; - for (const linestring of [ - LineString3d.create( - Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), // pure X - Point3d.create(1, 1, 0), // pure Y - Point3d.create(4, 2, 1), // everything tilts - Point3d.create(8, 1, 0)), // dive down - LineString3d.createRegularPolygonXY(Point3d.create(0, 10, 0), 7, 3.0, true)]) { + for ( + const linestring of [ + LineString3d.create( + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), // pure X + Point3d.create(1, 1, 0), // pure Y + Point3d.create(4, 2, 1), // everything tilts + Point3d.create(8, 1, 0), + ), // dive down + LineString3d.createRegularPolygonXY(Point3d.create(0, 10, 0), 7, 3.0, true), + ] + ) { geometry.push(linestring); const df = 0.125 / (linestring.numPoints() - 1); for (let fraction = 0; fraction <= 1.0000001; fraction += df) { const frame0 = linestring.fractionToFrenetFrame(fraction); - geometry.push(LineString3d.create(frame0.origin, - frame0.multiplyXYZ(ax, 0, 0), - frame0.multiplyXYZ(0, ay, 0), - frame0.multiplyXYZ(0, -ay, 0), - frame0.multiplyXYZ(ax, 0, 0), - frame0.multiplyXYZ(0, 0, az), - frame0.origin)); + geometry.push( + LineString3d.create( + frame0.origin, + frame0.multiplyXYZ(ax, 0, 0), + frame0.multiplyXYZ(0, ay, 0), + frame0.multiplyXYZ(0, -ay, 0), + frame0.multiplyXYZ(ax, 0, 0), + frame0.multiplyXYZ(0, 0, az), + frame0.origin, + ), + ); const tangent = linestring.fractionToPointAndUnitTangent(fraction); ck.testPerpendicular(tangent.direction, frame0.matrix.columnZ()); } @@ -1104,9 +1190,11 @@ describe("Linestring3dSpecials", () => { const plane = Plane3dByOriginAndUnitNormal.create(pointOnSegment.origin, pointOnSegment.direction); const intersections = new Array(); linestring.appendPlaneIntersectionPoints(plane!, intersections); - if (ck.testExactNumber(1, intersections.length, `Expect single intersection ${i}`) + if ( + ck.testExactNumber(1, intersections.length, `Expect single intersection ${i}`) && ck.testCoordinate(globalFraction, intersections[0].fraction, `intersection fraction on segment ${i}`) - && ck.testPoint3d(plane!.getOriginRef(), intersections[0].point, `intersection point on segment ${i}`)) { + && ck.testPoint3d(plane!.getOriginRef(), intersections[0].point, `intersection point on segment ${i}`) + ) { // all ok!! } else { intersections.length = 0; @@ -1128,8 +1216,10 @@ describe("Linestring3dSpecials", () => { const index0 = findPointInCLDArray(point0, intersections, 0); const index1 = findPointInCLDArray(point1, intersections, index0); const index2 = findPointInCLDArray(point2, intersections, index1); - if (ck.testExactNumber(index0 + 1, index1, "consecutive points in intersection list.") - && ck.testExactNumber(index1 + 1, index2, "consecutive points in intersection list.")) { + if ( + ck.testExactNumber(index0 + 1, index1, "consecutive points in intersection list.") + && ck.testExactNumber(index1 + 1, index2, "consecutive points in intersection list.") + ) { // when inspecting the intervalRole, allow for ends to be subsumed by larger intervals. testCurveIntervalRole(ck, intersections[index0], [CurveIntervalRole.intervalStart, CurveIntervalRole.intervalInterior]); testCurveIntervalRole(ck, intersections[index1], [CurveIntervalRole.intervalInterior]); @@ -1202,7 +1292,8 @@ describe("IsomorphicCurves", () => { Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(2, 0, 0), - Point3d.create(2, 1, 0)]; + Point3d.create(2, 1, 0), + ]; for (let numPoints = 2; numPoints <= allPoints.length; numPoints++) { // GeometryCoreTestIO.consoleLog("Isomorphic LineString (" + numPoints + ")"); // assemble leading numPoints part of allPoints ... @@ -1221,7 +1312,6 @@ describe("IsomorphicCurves", () => { } ck.checkpoint("IsomorphicCurves.Hello"); expect(ck.getNumErrors()).toBe(0); - }); }); @@ -1233,9 +1323,12 @@ describe("CylindricalRange", () => { const curves = Sample.createSimplePaths(false); for (const c of curves) { const strokes = c.cloneStroked(); - for (const ray of [ - Ray3d.createXYZUVW(0, 0, 0, 1, 0, 0), - Ray3d.createXYZUVW(1, 2, 4, 3, 1, 5)]) { + for ( + const ray of [ + Ray3d.createXYZUVW(0, 0, 0, 1, 0, 0), + Ray3d.createXYZUVW(1, 2, 4, 3, 1, 5), + ] + ) { const vector1 = CylindricalRangeQuery.computeMaxVectorFromRay(ray, c); ck.testPointer(vector1); const vector2 = CylindricalRangeQuery.computeMaxVectorFromRay(ray, strokes); @@ -1258,7 +1351,7 @@ describe("GeometryQuery", () => { ck.testUndefined(ls.children, "linestring has no children -- expected undefined from base class"); const pathA = Path.create(sg); const pathB = Path.create(ls, sg); - const pathC = Path.create(); // empty !!! + const pathC = Path.create(); // empty !!! ck.testFalse(pathA.isAlmostEqual(pathB)); ck.testFalse(pathA.isAlmostEqual(ls)); ck.testFalse(pathA.isAlmostEqual(pathC)); diff --git a/core/geometry/src/test/curve/CurveChainWithDistanceIndex.test.ts b/core/geometry/src/test/curve/CurveChainWithDistanceIndex.test.ts index 521fc96be0fd..d6f2a3b5cc4b 100644 --- a/core/geometry/src/test/curve/CurveChainWithDistanceIndex.test.ts +++ b/core/geometry/src/test/curve/CurveChainWithDistanceIndex.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { Arc3d } from "../../curve/Arc3d"; import { CurveChainWithDistanceIndex } from "../../curve/CurveChainWithDistanceIndex"; import { CurveCurve } from "../../curve/CurveCurve"; @@ -130,9 +130,17 @@ describe("CurveChainWithDistanceIndex", () => { ck.testLE(detail0.fraction, 1, "Point off path start has projection fraction <= 0"); ck.testLE(1, detail1.fraction, "Point off path end has projection fraction >= 1"); ck.testPoint3d(detail0.point, path0.startPoint(), "Point projected off path start equals start of clonedPartialCurve at projection fraction"); - ck.testPoint3d(detail0.point, path.fractionToPoint(detail0.fraction), "Point projected off path start equals fractionToPoint at projection fraction"); + ck.testPoint3d( + detail0.point, + path.fractionToPoint(detail0.fraction), + "Point projected off path start equals fractionToPoint at projection fraction", + ); ck.testPoint3d(detail1.point, path1.endPoint(), "Point projected off path end equals end of clonedPartialCurve at projection fraction"); - ck.testPoint3d(detail1.point, path.fractionToPoint(detail1.fraction), "Point projected off path end equals fractionToPoint at projection fraction"); + ck.testPoint3d( + detail1.point, + path.fractionToPoint(detail1.fraction), + "Point projected off path end equals fractionToPoint at projection fraction", + ); x0 += path.range().xLength() + 2; } @@ -231,14 +239,18 @@ describe("CurveChainWithDistanceIndex", () => { const arcDerivC = LineSegment3d.create(planeC.origin, Point3d.createAdd2Scaled(planeC.origin, 1, planeC.vectorU, 1)); const arcDeriv2C = LineSegment3d.create(planeC.origin, Point3d.createAdd2Scaled(planeC.origin, 1, planeC.vectorV, 1)); const pathC = new Path(); - pathC.children.push(arcC); // ellipse, not arc length parameterized + pathC.children.push(arcC); // ellipse, not arc length parameterized const indexedC = CurveChainWithDistanceIndex.createCapture(pathC); const pathFracC = indexedC.chainDistanceToChainFraction(distanceAlongArcC); const pathPlaneC = indexedC.fractionToPointAnd2Derivatives(pathFracC)!; const pathDerivC = LineSegment3d.create(pathPlaneC.origin, Point3d.createAdd2Scaled(pathPlaneC.origin, 1, pathPlaneC.vectorU, 1)); const pathDeriv2C = LineSegment3d.create(pathPlaneC.origin, Point3d.createAdd2Scaled(pathPlaneC.origin, 1, pathPlaneC.vectorV, 1)); ck.testPoint3d(planeC.origin, pathPlaneC?.origin, "comparing same points along arc and path containing the arc"); - ck.testAngleNoShift(Angle.createRadians(0), planeC.vectorU.angleTo(pathPlaneC.vectorU), "arc and path containing the arc have same 1st derivative direction"); + ck.testAngleNoShift( + Angle.createRadians(0), + planeC.vectorU.angleTo(pathPlaneC.vectorU), + "arc and path containing the arc have same 1st derivative direction", + ); ck.testFalse(planeC.vectorV.angleTo(pathPlaneC.vectorV).isAlmostZero, "arc and path containing the arc have different 2nd derivative directions"); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [arcC, arcDerivC, arcDeriv2C]); @@ -261,7 +273,8 @@ describe("CurveChainWithDistanceIndex", () => { // AB ck.testDefined(closestApproachAB); const closestApproachSegmentAB = LineSegment3d.create( - closestApproachAB!.detailA.point, closestApproachAB!.detailB.point, + closestApproachAB!.detailA.point, + closestApproachAB!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentAB); ck.testCoordinate(closestApproachAB!.detailA.fraction, 0.2, "AB detailA"); @@ -269,7 +282,8 @@ describe("CurveChainWithDistanceIndex", () => { // BA ck.testDefined(closestApproachAB); const closestApproachSegmentBA = LineSegment3d.create( - closestApproachBA!.detailA.point, closestApproachBA!.detailB.point, + closestApproachBA!.detailA.point, + closestApproachBA!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentBA); ck.testCoordinate(closestApproachBA!.detailA.fraction, 0, "BA detailA"); @@ -294,7 +308,8 @@ describe("CurveChainWithDistanceIndex", () => { // AB ck.testDefined(closestApproachAB); const closestApproachSegmentAB = LineSegment3d.create( - closestApproachAB!.detailA.point, closestApproachAB!.detailB.point, + closestApproachAB!.detailA.point, + closestApproachAB!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentAB); ck.testCoordinate(closestApproachAB!.detailA.fraction, 1 / 3, "AB detailA"); @@ -302,7 +317,8 @@ describe("CurveChainWithDistanceIndex", () => { // BA ck.testDefined(closestApproachAB); const closestApproachSegmentBA = LineSegment3d.create( - closestApproachBA!.detailA.point, closestApproachBA!.detailB.point, + closestApproachBA!.detailA.point, + closestApproachBA!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentBA); ck.testCoordinate(closestApproachBA!.detailA.fraction, 1 / 4, "BA detailA"); @@ -324,7 +340,9 @@ describe("CurveChainWithDistanceIndex", () => { path.tryAddChild(lineString2); const geometryA = CurveChainWithDistanceIndex.createCapture(path); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(4, 0), Point3d.create(6, 2), Point3d.create(8, 0), + Point3d.create(4, 0), + Point3d.create(6, 2), + Point3d.create(8, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); @@ -334,7 +352,8 @@ describe("CurveChainWithDistanceIndex", () => { // AB ck.testDefined(closestApproachAB); const closestApproachSegmentAB = LineSegment3d.create( - closestApproachAB!.detailA.point, closestApproachAB!.detailB.point, + closestApproachAB!.detailA.point, + closestApproachAB!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentAB); ck.testCoordinate(closestApproachAB!.detailA.fraction, 0.4, "AB detailA"); @@ -342,7 +361,8 @@ describe("CurveChainWithDistanceIndex", () => { // BA ck.testDefined(closestApproachAB); const closestApproachSegmentBA = LineSegment3d.create( - closestApproachBA!.detailA.point, closestApproachBA!.detailB.point, + closestApproachBA!.detailA.point, + closestApproachBA!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentBA); ck.testCoordinate(closestApproachBA!.detailA.fraction, 0.5, "BA detailA"); @@ -381,7 +401,8 @@ describe("CurveChainWithDistanceIndex", () => { // AB ck.testDefined(closestApproachAB); const closestApproachSegmentAB = LineSegment3d.create( - closestApproachAB!.detailA.point, closestApproachAB!.detailB.point, + closestApproachAB!.detailA.point, + closestApproachAB!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentAB); ck.testCoordinate(closestApproachAB!.detailA.fraction, 0.4, "AB detailA"); @@ -389,7 +410,8 @@ describe("CurveChainWithDistanceIndex", () => { // BA ck.testDefined(closestApproachAB); const closestApproachSegmentBA = LineSegment3d.create( - closestApproachBA!.detailA.point, closestApproachBA!.detailB.point, + closestApproachBA!.detailA.point, + closestApproachBA!.detailB.point, ); GeometryCoreTestIO.captureGeometry(allGeometry, closestApproachSegmentBA); ck.testCoordinate(closestApproachBA!.detailA.fraction, 1 / 3, "BA detailA"); @@ -431,7 +453,12 @@ describe("CurveChainWithDistanceIndex", () => { else ck.announceError("unexpected close approach"); } - GeometryCoreTestIO.captureGeometry(allGeometry, [chainA, chainB, LineSegment3d.create(pairs[0].detailA.point, pairs[0].detailB.point), LineSegment3d.create(pairs[1].detailA.point, pairs[1].detailB.point)]); + GeometryCoreTestIO.captureGeometry(allGeometry, [ + chainA, + chainB, + LineSegment3d.create(pairs[0].detailA.point, pairs[0].detailB.point), + LineSegment3d.create(pairs[1].detailA.point, pairs[1].detailB.point), + ]); } GeometryCoreTestIO.saveGeometry(allGeometry, "CurveChainWithDistanceIndex", "closestApproachChainLoops"); expect(ck.getNumErrors()).toBe(0); @@ -502,7 +529,9 @@ describe("CurveChainWithDistanceIndex", () => { path.tryAddChild(lineString2); const geometryA = CurveChainWithDistanceIndex.createCapture(path); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(4, 0), Point3d.create(6, 2), Point3d.create(8, 0), + Point3d.create(4, 0), + Point3d.create(6, 2), + Point3d.create(8, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); @@ -639,7 +668,9 @@ describe("CurveChainWithDistanceIndex", () => { path.tryAddChild(lineString2); const geometryA = CurveChainWithDistanceIndex.createCapture(path); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(4, 2, 1), Point3d.create(6, 2, -1), Point3d.create(8, 2, 1), + Point3d.create(4, 2, 1), + Point3d.create(6, 2, -1), + Point3d.create(8, 2, 1), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); @@ -712,7 +743,9 @@ describe("CurveChainWithDistanceIndex", () => { }); it("recursionAvoidance", () => { const ck = new Checker(); - const pts: Point3d[] = Array(7).fill(null).map((_v: Point3d, i: number) => { return Point3d.create(i, i, i); }); + const pts: Point3d[] = Array(7).fill(null).map((_v: Point3d, i: number) => { + return Point3d.create(i, i, i); + }); const childChain0 = CurveChainWithDistanceIndex.createCapture(Path.create([pts[1], pts[2], pts[3]])); const childChain1 = CurveChainWithDistanceIndex.createCapture(Path.create([pts[4], pts[5], pts[6]])); const path = Path.create(LineSegment3d.create(pts[0], pts[1]), childChain0, LineSegment3d.create(pts[3], pts[4]), childChain1); diff --git a/core/geometry/src/test/curve/CurveCollection.test.ts b/core/geometry/src/test/curve/CurveCollection.test.ts index 853ae850444a..4a6cdac12de1 100644 --- a/core/geometry/src/test/curve/CurveCollection.test.ts +++ b/core/geometry/src/test/curve/CurveCollection.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BezierCurve3d } from "../../bspline/BezierCurve3d"; import { Arc3d } from "../../curve/Arc3d"; import { BagOfCurves, CurveCollection } from "../../curve/CurveCollection"; @@ -75,7 +75,6 @@ function verifyCurveCollection(ck: Checker, collection: CurveCollection) { ck.testCoordinate(length1, length3, "length of clone(transform), transformInPlace"); const path5 = collection.cloneTransformed(scaleTransform)!; path5.sumLengths(); - } ck.testCoordinate(length0 * scaleFactor, length1, "scaled length"); @@ -95,7 +94,6 @@ function verifyCurveCollection(ck: Checker, collection: CurveCollection) { ck.testTrue(child === child1, "collection.getChild matches iterator "); } } - } describe("CurveCollection", () => { it("HelloWorld", () => { @@ -151,7 +149,6 @@ describe("CurveCollection", () => { }); describe("ConsolidateAdjacentPrimitives", () => { - it("Lines", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -200,10 +197,9 @@ describe("ConsolidateAdjacentPrimitives", () => { const chain0 = CurveFactory.createFilletsInLineString(points, 0.2, false)!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, chain0, x0, y0); x0 += 10; - chain0.tryAddChild(BezierCurve3d.create([tail, - tail.plus(Vector3d.create(1, 1, 0)), - tail.plus(Vector3d.create(2, 0, -1)), - tail.plus(Vector3d.create(-2, 3, 0))])); + chain0.tryAddChild( + BezierCurve3d.create([tail, tail.plus(Vector3d.create(1, 1, 0)), tail.plus(Vector3d.create(2, 0, -1)), tail.plus(Vector3d.create(-2, 3, 0))]), + ); const chain1 = Path.create(); const breakFractionRadius = 0.4; let radians = 0.3; @@ -344,7 +340,6 @@ describe("ConsolidateAdjacentPrimitives", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCollection", "ClosestPoint"); expect(ck.getNumErrors()).toBe(0); }); - }); /** * Capture markers at shiftFraction and (1-shiftFraction) on each primitive of curves. @@ -355,7 +350,15 @@ describe("ConsolidateAdjacentPrimitives", () => { * @param x0 * @param y0 */ -function markLimits(allGeometry: GeometryQuery[], primitives: CurvePrimitive[], shiftFraction: number, markerSize0: number, markerSize1: number, x0: number, y0: number) { +function markLimits( + allGeometry: GeometryQuery[], + primitives: CurvePrimitive[], + shiftFraction: number, + markerSize0: number, + markerSize1: number, + x0: number, + y0: number, +) { for (const p of primitives) { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, p.fractionToPoint(shiftFraction), markerSize0, x0, y0); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, p.fractionToPoint(1.0 - shiftFraction), markerSize1, x0, y0); diff --git a/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts b/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts index 78b22230e1bf..bf8e0a59cded 100644 --- a/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts +++ b/core/geometry/src/test/curve/CurveCurveCloseApproachXY.test.ts @@ -56,27 +56,38 @@ function testVaryingLineSegments( const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); _ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment, x0, y0); } } - } else { // no intersection and no closest approach between geometries + } else { // no intersection and no closest approach between geometries const circleA0 = Arc3d.createXY(geometryAStart, maxDistance); const circleA1 = Arc3d.createXY(geometryAEnd, maxDistance); const circleB0 = Arc3d.createXY(lineB.startPoint(), maxDistance); const circleB1 = Arc3d.createXY(lineB.endPoint(), maxDistance); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleA0, false, lineB, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleA0, false, lineB, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleA1, false, lineB, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleA1, false, lineB, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleB0, false, geometryA, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleB0, false, geometryA, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleB1, false, geometryA, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleB1, false, geometryA, false).length, + "expect no intersection", ); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, geometryAStart, maxDistance, x0, y0); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, geometryAEnd, maxDistance, x0, y0); @@ -118,9 +129,13 @@ function testVaryingSubsets( for (const p of approaches) if (p.detailA.point.isAlmostEqual(p.detailB.point)) // intersection between geometries GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, p.detailA.point, 0.0625, x0, y0); - else // closest approach between geometries + // closest approach between geometries + else GeometryCoreTestIO.captureGeometry( - allGeometry, LineSegment3d.create(p.detailA.point, p.detailB.point), x0, y0, + allGeometry, + LineSegment3d.create(p.detailA.point, p.detailB.point), + x0, + y0, ); } else { const circleA0 = Arc3d.createXY(geometryA.startPoint(), maxDistance); @@ -128,16 +143,24 @@ function testVaryingSubsets( const circleB0 = Arc3d.createXY(partialB.startPoint(), maxDistance); const circleB1 = Arc3d.createXY(partialB.endPoint(), maxDistance); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleA0, false, partialB, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleA0, false, partialB, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleA1, false, partialB, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleA1, false, partialB, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleB0, false, geometryA, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleB0, false, geometryA, false).length, + "expect no intersection", ); _ck.testCoordinate( - 0, CurveCurve.intersectionXYPairs(circleB1, false, geometryA, false).length, "expect no intersection", + 0, + CurveCurve.intersectionXYPairs(circleB1, false, geometryA, false).length, + "expect no intersection", ); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, geometryA.startPoint(), maxDistance, x0, y0); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, geometryA.endPoint(), maxDistance, x0, y0); @@ -157,7 +180,12 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const geometryA = LineSegment3d.createXYXY(1, 2, 5, 2); testVaryingLineSegments( - ck, allGeometry, geometryA, geometryA.startPoint(), geometryA.fractionToPoint(0.5), geometryA.endPoint(), + ck, + allGeometry, + geometryA, + geometryA.startPoint(), + geometryA.fractionToPoint(0.5), + geometryA.endPoint(), ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LineLine"); expect(ck.getNumErrors()).toBe(0); @@ -178,7 +206,10 @@ describe("CurveCurveCloseApproachXY", () => { const lenSqr = start.distanceSquaredXY(end); const expectedLenSqr = 0; ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); ck.testCoordinate(lenSqr, expectedLenSqr); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); @@ -188,7 +219,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); const expectedMinLenSqr = 0; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineLine1"); @@ -209,7 +243,10 @@ describe("CurveCurveCloseApproachXY", () => { const lenSqr = start.distanceSquaredXY(end); const expectedLenSqr = 0.5; // (sqrt(2)/2)*(sqrt(2)/2) ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); ck.testCoordinate(lenSqr, expectedLenSqr, "closest approach has expected length"); ck.testCoordinate(approaches[0].detailA.fraction, 1.0, "closest approach has expected fraction on curveA"); @@ -225,7 +262,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 0.5; // (sqrt(2)/2)*(sqrt(2)/2) ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineLine2"); @@ -236,7 +276,12 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const geometryA = LineString3d.create([1, 2], [3, 4], [4, 3]); testVaryingLineSegments( - ck, allGeometry, geometryA, geometryA.startPoint(), geometryA.fractionToPoint(0.5), geometryA.endPoint(), + ck, + allGeometry, + geometryA, + geometryA.startPoint(), + geometryA.fractionToPoint(0.5), + geometryA.endPoint(), ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LineLineString"); expect(ck.getNumErrors()).toBe(0); @@ -261,7 +306,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -277,7 +325,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -304,7 +355,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -320,7 +374,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 0.5; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineLineString2"); @@ -330,10 +387,17 @@ describe("CurveCurveCloseApproachXY", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 2), Point3d.create(3, 3.5), Point3d.create(5, 2), + Point3d.create(1, 2), + Point3d.create(3, 3.5), + Point3d.create(5, 2), ); testVaryingLineSegments( - ck, allGeometry, geometryA, geometryA.startPoint(), geometryA.fractionToPoint(0.5), geometryA.endPoint(), + ck, + allGeometry, + geometryA, + geometryA.startPoint(), + geometryA.fractionToPoint(0.5), + geometryA.endPoint(), ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LineArc"); expect(ck.getNumErrors()).toBe(0); @@ -343,7 +407,9 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2.5; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-2, 0), Point3d.create(0, 2), Point3d.create(2, 0), + Point3d.create(-2, 0), + Point3d.create(0, 2), + Point3d.create(2, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = LineSegment3d.createXYXY(-5, 4, 5, 4); @@ -354,7 +420,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); // test the convenience method @@ -367,7 +436,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 4; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineArc1"); @@ -378,7 +450,9 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 4; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-2, 0, 0), Point3d.create(0, 2, -2), Point3d.create(2, 0, -4), + Point3d.create(-2, 0, 0), + Point3d.create(0, 2, -2), + Point3d.create(2, 0, -4), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = LineSegment3d.createXYZXYZ(0, 3, -3, 0, 6, 3); @@ -394,7 +468,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -405,7 +482,10 @@ describe("CurveCurveCloseApproachXY", () => { ck.testDefined(closestApproach); const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); const expectedMinLenSqr = 1; ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -417,7 +497,10 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2.5; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(2, 0), Vector3d.create(0, 3), AngleSweep.createStartEndRadians(0, Math.PI), + Point3d.create(0, 0), + Vector3d.create(2, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndRadians(0, Math.PI), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = LineSegment3d.createXYXY(-5, 3, 5, 3); @@ -431,7 +514,10 @@ describe("CurveCurveCloseApproachXY", () => { else { // closest approach between geometries const approachSegment = LineSegment3d.create(start, end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -447,7 +533,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 0; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineArc3"); @@ -475,7 +564,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -486,7 +578,10 @@ describe("CurveCurveCloseApproachXY", () => { ck.testDefined(closestApproach); const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); const expectedMinLenSqr = 0.25; // 0.5 * 0.5 ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -504,7 +599,12 @@ describe("CurveCurveCloseApproachXY", () => { geometryA.tryAddChild(lineString); geometryA.tryAddChild(lineSegment); testVaryingLineSegments( - ck, allGeometry, geometryA, Point3d.create(1, 2), Point3d.create(5, 2), Point3d.create(10, 0), + ck, + allGeometry, + geometryA, + Point3d.create(1, 2), + Point3d.create(5, 2), + Point3d.create(10, 0), ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LinePath1"); expect(ck.getNumErrors()).toBe(0); @@ -550,7 +650,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -568,7 +671,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment, shift, 0); } @@ -590,15 +696,21 @@ describe("CurveCurveCloseApproachXY", () => { ck.testCoordinate(detailA1.fraction, 2 / 3); ck.testCoordinate(detailB1.fraction, 5 / 6); // fraction on line string ck.testCoordinate(detailA2.fraction, 2 / 3); - ck.testCoordinate(detailB2.fraction, 1); // fraction on line segment + ck.testCoordinate(detailB2.fraction, 1); // fraction on line segment const minLenSqr1 = detailA1.point.distanceSquaredXY(detailB1.point); const minLenSqr2 = detailA2.point.distanceSquaredXY(detailB2.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr1), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr1), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testLE( - Math.sqrt(minLenSqr2), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr2), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr1, expectedMinLenSqr); ck.testCoordinate(minLenSqr2, expectedMinLenSqr); @@ -618,7 +730,12 @@ describe("CurveCurveCloseApproachXY", () => { geometryA.tryAddChild(lineSegment1); geometryA.tryAddChild(lineSegment2); testVaryingLineSegments( - ck, allGeometry, geometryA, Point3d.create(1, 2), Point3d.create(5, 2), Point3d.create(10, 0), + ck, + allGeometry, + geometryA, + Point3d.create(1, 2), + Point3d.create(5, 2), + Point3d.create(10, 0), ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LineLoop1"); expect(ck.getNumErrors()).toBe(0); @@ -633,7 +750,14 @@ describe("CurveCurveCloseApproachXY", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA, shift, 0); // line string const geometryB1 = LineString3d.create([ - [1, 0], [2, 3], [3, 0], [4, 2], [5, 0], [6, 3], [7, -2], [1, 0], + [1, 0], + [2, 3], + [3, 0], + [4, 2], + [5, 0], + [6, 3], + [7, -2], + [1, 0], ]); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB1); // same line string create as loop of line segments @@ -668,7 +792,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -686,7 +813,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment, shift, 0); } @@ -705,10 +835,16 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr2 = closestApproach2!.detailA.point.distanceSquaredXY(closestApproach2!.detailB.point); const expectedMinLenSqr = 4; ck.testLE( - Math.sqrt(minLenSqr1), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr1), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testLE( - Math.sqrt(minLenSqr2), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr2), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr1, expectedMinLenSqr); ck.testCoordinate(minLenSqr2, expectedMinLenSqr); @@ -748,11 +884,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(1, 0), Vector3d.create(1, 0), Vector3d.create(0, 3), + Point3d.create(1, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 3), ); // non-circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -771,7 +911,11 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -786,11 +930,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(6, 0), Vector3d.create(2, 0), Vector3d.create(0, 3), + Point3d.create(6, 0), + Vector3d.create(2, 0), + Vector3d.create(0, 3), ); // non-circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -803,11 +951,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 5; const geometryA = Arc3d.create( - Point3d.create(-1, 0), Vector3d.create(2, 0), Vector3d.create(0, 1), + Point3d.create(-1, 0), + Vector3d.create(2, 0), + Vector3d.create(0, 1), ); // non-circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(4, 0), Vector3d.create(2, 0), Vector3d.create(0, 2), + Point3d.create(4, 0), + Vector3d.create(2, 0), + Vector3d.create(0, 2), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -816,7 +968,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); // test the convenience method @@ -829,7 +984,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleArcArc3"); @@ -866,7 +1024,11 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -882,7 +1044,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleArcArc4"); @@ -903,13 +1068,18 @@ describe("CurveCurveCloseApproachXY", () => { return false; }; const existsInApproachSetWithTolerance = ( - set: Set<[Point3d, Point3d]>, point0: Point3d, point1: Point3d, tolerance: number = 1e-6, + set: Set<[Point3d, Point3d]>, + point0: Point3d, + point1: Point3d, + tolerance: number = 1e-6, ): boolean => { for (const startEnd of set) { const start = startEnd[0]; const end = startEnd[1]; - if ((start.isAlmostEqual(point0, tolerance) && end.isAlmostEqual(point1, tolerance)) || - (start.isAlmostEqual(point1, tolerance) && end.isAlmostEqual(point0, tolerance))) + if ( + (start.isAlmostEqual(point0, tolerance) && end.isAlmostEqual(point1, tolerance)) || + (start.isAlmostEqual(point1, tolerance) && end.isAlmostEqual(point0, tolerance)) + ) return true; } return false; @@ -944,14 +1114,20 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + undefined, + "approach length must be smaller than maxDistance", ); const vec1 = Vector3d.createStartEnd(start, end); const vec2 = geometryA.fractionToPointAndDerivative(ap.detailA.fraction).direction; const vec3 = geometryB.fractionToPointAndDerivative(ap.detailB.fraction).direction; GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment, 0, dy); - if (vec1.isPerpendicularTo(vec2) && vec1.isPerpendicularTo(vec3) && - !existsInApproachSetWithTolerance(approachSet, start, end, 1e-6)) { + if ( + vec1.isPerpendicularTo(vec2) && vec1.isPerpendicularTo(vec3) && + !existsInApproachSetWithTolerance(approachSet, start, end, 1e-6) + ) { approachSet.add([start, end]); // add unique close approach to set numUniquePerpCloseApproach++; } @@ -1001,11 +1177,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(1, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(1, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(4, 0), Vector3d.create(2, 0), Vector3d.create(0, 4), + Point3d.create(4, 0), + Vector3d.create(2, 0), + Vector3d.create(0, 4), ); // non-circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -1030,11 +1210,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(-0.75, 0), Vector3d.create(1.25, 0), Vector3d.create(0, 1.25), + Point3d.create(-0.75, 0), + Vector3d.create(1.25, 0), + Vector3d.create(0, 1.25), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -1061,11 +1245,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(-1, 0, 2), Vector3d.create(0, 1, 0), Vector3d.create(0, 0, 2), + Point3d.create(-1, 0, 2), + Vector3d.create(0, 1, 0), + Vector3d.create(0, 0, 2), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -1090,11 +1278,15 @@ describe("CurveCurveCloseApproachXY", () => { const allGeometry: GeometryQuery[] = []; const maxDistance = 2; const geometryA = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.create( - Point3d.create(0, 0, 0), Vector3d.create(0, 1, 0), Vector3d.create(0, 0, 2), + Point3d.create(0, 0, 0), + Vector3d.create(0, 1, 0), + Vector3d.create(0, 0, 2), ); // circular arc GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); const approaches = CurveCurve.closeApproachProjectedXYPairs(geometryA, geometryB, maxDistance); @@ -1166,7 +1358,11 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1182,7 +1378,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = detailA.point.distanceSquaredXY(detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "SingleLineStringLineString"); @@ -1219,7 +1418,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1230,7 +1432,10 @@ describe("CurveCurveCloseApproachXY", () => { ck.testDefined(closestApproach); const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); const expectedMinLenSqr = 0.25; // 0.5 * 0.5 ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -1272,7 +1477,9 @@ describe("CurveCurveCloseApproachXY", () => { 4, )!; const cpB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 3), Point3d.create(4, 2.5), Point3d.create(6, 2), + Point3d.create(1, 3), + Point3d.create(4, 2.5), + Point3d.create(6, 2), ); testVaryingSubsets(ck, allGeometry, cpA, cpB, 2, [0, 1]); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "BsplineArc"); @@ -1281,7 +1488,9 @@ describe("CurveCurveCloseApproachXY", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "ArcBspline"); allGeometry.length = 0; const cpB1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, -1), Point3d.create(4, 0), Point3d.create(6, -1), + Point3d.create(1, -1), + Point3d.create(4, 0), + Point3d.create(6, -1), ); testVaryingSubsets(ck, allGeometry, cpA, cpB1, 2, [0, 1]); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "BsplineArcB"); @@ -1341,7 +1550,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1353,7 +1565,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "PathPath"); @@ -1436,7 +1651,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1447,7 +1665,10 @@ describe("CurveCurveCloseApproachXY", () => { ck.testDefined(closestApproach); const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); const expectedMinLenSqr = 36; // 6 * 6 ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -1484,7 +1705,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1495,7 +1719,10 @@ describe("CurveCurveCloseApproachXY", () => { ck.testDefined(closestApproach); const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); const expectedMinLenSqr = 36; // 6 * 6 ck.testCoordinate(minLenSqr, expectedMinLenSqr); @@ -1530,7 +1757,10 @@ describe("CurveCurveCloseApproachXY", () => { const approachSegment = LineSegment3d.create(start, end); const lenSqr = start.distanceSquaredXY(end); ck.testLE( - Math.sqrt(lenSqr), maxDistance, undefined, "approach length must be smaller than maxDistance", + Math.sqrt(lenSqr), + maxDistance, + undefined, + "approach length must be smaller than maxDistance", ); GeometryCoreTestIO.captureGeometry(allGeometry, approachSegment); } @@ -1542,7 +1772,10 @@ describe("CurveCurveCloseApproachXY", () => { const minLenSqr = closestApproach!.detailA.point.distanceSquaredXY(closestApproach!.detailB.point); const expectedMinLenSqr = 1; ck.testLE( - Math.sqrt(minLenSqr), maxDistance, undefined, "closest approach length must be smaller than maxDistance", + Math.sqrt(minLenSqr), + maxDistance, + undefined, + "closest approach length must be smaller than maxDistance", ); ck.testCoordinate(minLenSqr, expectedMinLenSqr); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveCloseApproachXY", "LineBagOfCurves"); diff --git a/core/geometry/src/test/curve/CurveCurveIntersectXY.test.ts b/core/geometry/src/test/curve/CurveCurveIntersectXY.test.ts index 7ed7fd58a984..6926b9ce522d 100644 --- a/core/geometry/src/test/curve/CurveCurveIntersectXY.test.ts +++ b/core/geometry/src/test/curve/CurveCurveIntersectXY.test.ts @@ -59,7 +59,13 @@ function createSamplePerspectiveMaps(): Map4d[] { * Save in allGeometry */ function captureEyeStroke( - allGeometry: GeometryQuery[], map: Map4d, pointA: Point3d, pointB: Point3d, dzNpc: number, dx: number, dy: number, + allGeometry: GeometryQuery[], + map: Map4d, + pointA: Point3d, + pointB: Point3d, + dzNpc: number, + dx: number, + dy: number, ): void { for (const point0 of [pointA, pointB]) { const npcPoint0 = map.transform0.multiplyPoint3d(point0, 1); @@ -114,7 +120,10 @@ function testIntersectionsXY( * * mixed ==> ck.announceError and return false. */ function verifyTypedPair( - ck: Checker, valueA: T | undefined, valueB: T | undefined, defaultUndefinedValue: boolean = false, + ck: Checker, + valueA: T | undefined, + valueB: T | undefined, + defaultUndefinedValue: boolean = false, ): boolean { if (valueA !== undefined && valueB !== undefined) return true; @@ -124,7 +133,10 @@ function verifyTypedPair( return false; } function verifyLocalPointXY( - ck: Checker, pointAWorld: Point3d | undefined, pointBWorld: Point3d | undefined, worldToLocal: Matrix4d | undefined, + ck: Checker, + pointAWorld: Point3d | undefined, + pointBWorld: Point3d | undefined, + worldToLocal: Matrix4d | undefined, ) { if (verifyTypedPair(ck, pointAWorld, pointBWorld) && pointAWorld && pointBWorld) { if (worldToLocal) { @@ -265,10 +277,14 @@ describe("CurveCurveIntersectXY", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const arc0 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(0, 2, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 1, 0), + Point3d.create(0, 2, 0), ); const arc1 = Arc3d.createCircularStartMiddleEnd( - arc0.fractionToPoint(0.25), arc0.fractionToPoint(0.5), arc0.fractionToPoint(1.5), + arc0.fractionToPoint(0.25), + arc0.fractionToPoint(0.5), + arc0.fractionToPoint(1.5), ); const intersectionsAB = CurveCurve.intersectionXYPairs(arc0, false, arc1, false); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [arc0, arc1]); @@ -478,7 +494,7 @@ describe("CurveCurveIntersectXY", () => { let dx = 0, dy = 0; for (const map of createSamplePerspectiveMaps()) { const worldToLocal = map.transform0; // That's world to local. The perspective frustum forced that. Seems backwards. - const z = 0.1; // Raise the arc a little so various view directions produce different intersections. + const z = 0.1; // Raise the arc a little so various view directions produce different intersections. const arc = Arc3d.create(Point3d.create(0, 0, z), Vector3d.create(2, 0, 0), Vector3d.create(0, 2, 1)); for (const order of [2, 3, 4]) { const bspline = BSplineCurve3d.createUniformKnots( @@ -521,7 +537,7 @@ describe("CurveCurveIntersectXY", () => { const worldToLocal = map.transform0; // That's world to local. The perspective frustum forced that. Seems backwards. dx = 0.0; for (const order0 of [2, 3, 4]) { - const z0 = 0.3; // Raise the arc a little so various view directions produce different intersections. + const z0 = 0.3; // Raise the arc a little so various view directions produce different intersections. // bspline0 sweeps from high on y axis to low in 4 quadrant const bspline0 = BSplineCurve3d.createUniformKnots( [ @@ -548,12 +564,14 @@ describe("CurveCurveIntersectXY", () => { GeometryCoreTestIO.captureGeometry(allGeometry, bspline0.clone(), dx, dy); // Inner loop moves bspline1 around to have specific intersections. // bspline1 and the computed intersections are drawn at each placement. - for (const fraction0fraction1 of [ - Point2d.create(0.1, 0.45), - Point2d.create(0.35, 0.521), - Point2d.create(0.5, 0.672), - Point2d.create(0.82, 0.1), - ]) { + for ( + const fraction0fraction1 of [ + Point2d.create(0.1, 0.45), + Point2d.create(0.35, 0.521), + Point2d.create(0.5, 0.672), + Point2d.create(0.82, 0.1), + ] + ) { const fraction0 = fraction0fraction1.x; const fraction1 = fraction0fraction1.y; const point0 = bspline0.fractionToPoint(fraction0); @@ -580,8 +598,14 @@ describe("CurveCurveIntersectXY", () => { expect(ck.getNumErrors()).toBe(0); }); function captureAndTestIntersection( - allGeometry: GeometryQuery[], ck: Checker, dx: number, dy: number, - curveA: any, curveB: any, extendA: boolean, extendB: boolean, + allGeometry: GeometryQuery[], + ck: Checker, + dx: number, + dy: number, + curveA: any, + curveB: any, + extendA: boolean, + extendB: boolean, expectedIntersections: number, ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, curveA, dx, dy); @@ -597,22 +621,28 @@ describe("CurveCurveIntersectXY", () => { const path = Path.create( LineSegment3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), LineSegment3d.create( - Point3d.create(95.24913755203208, 12.748564710980762), Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(89.42790013152023, 12.74856471098076), ), LineSegment3d.create( - Point3d.create(89.42790013152023, 12.74856471098076), Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(89.42790013152023, 7.375114784355288), ), LineSegment3d.create( - Point3d.create(89.42790013152023, 7.375114784355288), Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(97.67998394741026, 7.3751147843552864), ), LineSegment3d.create( - Point3d.create(97.67998394741026, 7.3751147843552864), Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(97.67998394741026, 2.961209487484229), ), LineSegment3d.create( - Point3d.create(97.67998394741026, 2.961209487484229), Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(102.60564638015066, 2.961209487484229), ), ); @@ -672,56 +702,80 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(0, 180), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(93, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(93, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(95, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(95, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc8, true, true, 0); dx += 20; @@ -730,35 +784,40 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const bspline1 = BSplineCurve3d.createUniformKnots( - [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], 4, + [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, false, true, 0); dx += 20; const bspline2 = BSplineCurve3d.createUniformKnots( - [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], 4, + [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, true, true, 1); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, false, true, 0); dx += 20; const bspline3 = BSplineCurve3d.createUniformKnots( - [Point3d.create(91, 20), Point3d.create(92, 20.5), Point3d.create(93, 20), Point3d.create(94, 22), Point3d.create(95, 20)], 4, + [Point3d.create(91, 20), Point3d.create(92, 20.5), Point3d.create(93, 20), Point3d.create(94, 22), Point3d.create(95, 20)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, false, true, 0); dx += 20; const bspline4 = BSplineCurve3d.createUniformKnots( - [Point3d.create(104, 2), Point3d.create(105, 2.5), Point3d.create(106, 2), Point3d.create(107, 4), Point3d.create(108, 2)], 4, + [Point3d.create(104, 2), Point3d.create(105, 2.5), Point3d.create(106, 2), Point3d.create(107, 4), Point3d.create(108, 2)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, false, true, 0); dx += 20; const bspline5 = BSplineCurve3d.createUniformKnots( - [Point3d.create(99, 7), Point3d.create(100, 7.5), Point3d.create(101, 7), Point3d.create(102, 9), Point3d.create(103, 7)], 4, + [Point3d.create(99, 7), Point3d.create(100, 7.5), Point3d.create(101, 7), Point3d.create(102, 9), Point3d.create(103, 7)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline5, true, true, 0); dx += 20; @@ -851,56 +910,80 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(0, 180), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(93, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(93, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(95, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(95, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc8, true, true, 0); dx += 20; @@ -909,35 +992,40 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const bspline1 = BSplineCurve3d.createUniformKnots( - [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], 4, + [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, false, true, 0); dx += 20; const bspline2 = BSplineCurve3d.createUniformKnots( - [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], 4, + [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, true, true, 1); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, false, true, 0); dx += 20; const bspline3 = BSplineCurve3d.createUniformKnots( - [Point3d.create(91, 20), Point3d.create(92, 20.5), Point3d.create(93, 20), Point3d.create(94, 22), Point3d.create(95, 20)], 4, + [Point3d.create(91, 20), Point3d.create(92, 20.5), Point3d.create(93, 20), Point3d.create(94, 22), Point3d.create(95, 20)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, false, true, 0); dx += 20; const bspline4 = BSplineCurve3d.createUniformKnots( - [Point3d.create(104, 2), Point3d.create(105, 2.5), Point3d.create(106, 2), Point3d.create(107, 4), Point3d.create(108, 2)], 4, + [Point3d.create(104, 2), Point3d.create(105, 2.5), Point3d.create(106, 2), Point3d.create(107, 4), Point3d.create(108, 2)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, false, true, 0); dx += 20; const bspline5 = BSplineCurve3d.createUniformKnots( - [Point3d.create(99, 7), Point3d.create(100, 7.5), Point3d.create(101, 7), Point3d.create(102, 9), Point3d.create(103, 7)], 4, + [Point3d.create(99, 7), Point3d.create(100, 7.5), Point3d.create(101, 7), Point3d.create(102, 9), Point3d.create(103, 7)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline5, true, true, 0); dx += 20; @@ -952,22 +1040,40 @@ describe("CurveCurveIntersectXY", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(100, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(100, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), ); @@ -1027,56 +1133,80 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc1, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(0, 180), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc2, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, true, true, 2); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc3, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(96, 15), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(96, 15), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, true, true, 4); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc4, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc5, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(91, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(91, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc6, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(96, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(96, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc7, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, arc8, true, true, 0); dx += 20; @@ -1085,35 +1215,40 @@ describe("CurveCurveIntersectXY", () => { dx = 0; dy += 30; const bspline1 = BSplineCurve3d.createUniformKnots( - [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], 4, + [Point3d.create(95, 0), Point3d.create(96, 0.5), Point3d.create(97, 0), Point3d.create(98, 2), Point3d.create(99, 0)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline1, false, true, 0); dx += 20; const bspline2 = BSplineCurve3d.createUniformKnots( - [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], 4, + [Point3d.create(93, 23), Point3d.create(94, 23.5), Point3d.create(95, 23), Point3d.create(96, 25), Point3d.create(97, 23)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, true, true, 0); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline2, false, true, 0); dx += 20; const bspline3 = BSplineCurve3d.createUniformKnots( - [Point3d.create(91, 17), Point3d.create(92, 17.5), Point3d.create(93, 17), Point3d.create(94, 19), Point3d.create(95, 17)], 4, + [Point3d.create(91, 17), Point3d.create(92, 17.5), Point3d.create(93, 17), Point3d.create(94, 19), Point3d.create(95, 17)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, true, true, 1); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline3, false, true, 0); dx += 20; const bspline4 = BSplineCurve3d.createUniformKnots( - [Point3d.create(102, 3), Point3d.create(103, 3.5), Point3d.create(104, 3), Point3d.create(105, 5), Point3d.create(106, 3)], 4, + [Point3d.create(102, 3), Point3d.create(103, 3.5), Point3d.create(104, 3), Point3d.create(105, 5), Point3d.create(106, 3)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, true, true, 1); dx += 20; captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline4, false, true, 0); dx += 20; const bspline5 = BSplineCurve3d.createUniformKnots( - [Point3d.create(96, 7), Point3d.create(97, 7.5), Point3d.create(98, 7), Point3d.create(99, 9), Point3d.create(100, 7)], 4, + [Point3d.create(96, 7), Point3d.create(97, 7.5), Point3d.create(98, 7), Point3d.create(99, 9), Point3d.create(100, 7)], + 4, ); captureAndTestIntersection(allGeometry, ck, dx, dy, path, bspline5, true, true, 0); dx += 20; @@ -1128,28 +1263,36 @@ describe("CurveCurveIntersectXY", () => { const loop = Loop.create( LineString3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), LineString3d.create( - Point3d.create(95.24913755203208, 12.748564710980762), Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(89.42790013152023, 12.74856471098076), ), LineString3d.create( - Point3d.create(89.42790013152023, 12.74856471098076), Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(89.42790013152023, 7.375114784355288), ), LineString3d.create( - Point3d.create(89.42790013152023, 7.375114784355288), Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(97.67998394741026, 7.3751147843552864), ), LineString3d.create( - Point3d.create(97.67998394741026, 7.3751147843552864), Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(97.67998394741026, 2.961209487484229), ), LineString3d.create( - Point3d.create(97.67998394741026, 2.961209487484229), Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(102.60564638015066, 2.961209487484229), ), LineString3d.create( - Point3d.create(102.60564638015066, 2.961209487484229), Point3d.create(102.60564638015066, 20.36095210703357), + Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(102.60564638015066, 20.36095210703357), ), LineString3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), ); @@ -1223,19 +1366,34 @@ describe("CurveCurveIntersectXY", () => { const path1 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1244,7 +1402,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), ); @@ -1267,19 +1428,34 @@ describe("CurveCurveIntersectXY", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1288,7 +1464,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1320,19 +1499,34 @@ describe("CurveCurveIntersectXY", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1341,7 +1535,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1406,7 +1603,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), ); const curveChain2 = CurveChainWithDistanceIndex.createCapture(path2); @@ -1438,7 +1638,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1473,7 +1676,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1487,19 +1693,34 @@ describe("CurveCurveIntersectXY", () => { ); const path1 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1516,7 +1737,10 @@ describe("CurveCurveIntersectXY", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(81, 10), Vector3d.create(5, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 180), + Point3d.create(81, 10), + Vector3d.create(5, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 180), ), LineSegment3d.create(Point3d.create(75, 10), Point3d.create(80, 10)), LineSegment3d.create(Point3d.create(80, 10), Point3d.create(80, 5)), @@ -1546,7 +1770,10 @@ describe("CurveCurveIntersectXY", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1558,19 +1785,34 @@ describe("CurveCurveIntersectXY", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1594,10 +1836,16 @@ describe("CurveCurveIntersectXY", () => { const allGeometry: GeometryQuery[] = []; const arc1 = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(-90, 90), ); const arc2 = Arc3d.create( - Point3d.create(0, 10), Vector3d.create(5, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(0, 10), + Vector3d.create(5, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, 0, 0, arc1, arc2, false, false, 0); @@ -1609,10 +1857,16 @@ describe("CurveCurveIntersectXY", () => { const allGeometry: GeometryQuery[] = []; const arc1 = Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ); const arc2 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, 0, 0, arc1, arc2, false, false, 0); @@ -1770,7 +2024,9 @@ describe("CurveCurveIntersectXY", () => { const geometryA = LineSegment3d.createXYZXYZ(0, 0, 0, 0, 3, -4); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-2, 0), Point3d.create(0, 2), Point3d.create(2, 0), + Point3d.create(-2, 0), + Point3d.create(0, 2), + Point3d.create(2, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); // find intersections @@ -1793,7 +2049,9 @@ describe("CurveCurveIntersectXY", () => { const geometryA = LineSegment3d.createXYZXYZ(0, 0, 0, 10, 2, -1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const arc = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 2), Point3d.create(3, 3.5), Point3d.create(5, 2), + Point3d.create(1, 2), + Point3d.create(3, 3.5), + Point3d.create(5, 2), ); const lineString = LineString3d.create([5, 2], [6, 0], [7, 2]); const lineSegment = LineSegment3d.create(Point3d.create(7, 2), Point3d.create(10, 0)); @@ -1821,7 +2079,9 @@ describe("CurveCurveIntersectXY", () => { const geometryA = LineSegment3d.createXYZXYZ(0, 5, 1, 8, -1, -1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const arc = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 2), Point3d.create(3, 3.5), Point3d.create(5, 2), + Point3d.create(1, 2), + Point3d.create(3, 3.5), + Point3d.create(5, 2), ); const lineString = LineString3d.create([5, 2], [6, 0], [7, 2]); const lineSegment1 = LineSegment3d.create(Point3d.create(7, 2), Point3d.create(10, 0)); @@ -1849,11 +2109,15 @@ describe("CurveCurveIntersectXY", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-1, 2), Point3d.create(3, 4), Point3d.create(7, 2), + Point3d.create(-1, 2), + Point3d.create(3, 4), + Point3d.create(7, 2), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 4), Point3d.create(1, 3), + Point3d.create(1, 5), + Point3d.create(3, 4), + Point3d.create(1, 3), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); // find intersections @@ -1894,7 +2158,9 @@ describe("CurveCurveIntersectXY", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 2), Point3d.create(3, 4), Point3d.create(5, 2), + Point3d.create(1, 2), + Point3d.create(3, 4), + Point3d.create(5, 2), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = LineString3d.create([3, 5], [3, 1], [6, 1]); @@ -1986,7 +2252,9 @@ describe("CurveCurveIntersectXY", () => { )!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 0), Point3d.create(2, 1), Point3d.create(3, 0), + Point3d.create(1, 0), + Point3d.create(2, 1), + Point3d.create(3, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); // find intersections @@ -2045,7 +2313,9 @@ describe("CurveCurveIntersectXY", () => { const allGeometry: GeometryQuery[] = []; // path1 const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 6.5), Point3d.create(5, 5), + Point3d.create(1, 5), + Point3d.create(3, 6.5), + Point3d.create(5, 5), ); const lineString1 = LineString3d.create([5, 5], [6, 3], [7, 5], [10, 3]); const lineSegment1 = LineSegment3d.create(Point3d.create(10, 3), Point3d.create(1, 5)); @@ -2056,7 +2326,9 @@ describe("CurveCurveIntersectXY", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // path2 const arc2 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, -2), Point3d.create(2, -3.5), Point3d.create(4, -2), + Point3d.create(0, -2), + Point3d.create(2, -3.5), + Point3d.create(4, -2), ); const lineString2 = LineString3d.create([4, -2], [6, -1], [8, -2], [9, 6]); const lineSegment2 = LineSegment3d.create(Point3d.create(9, 6), Point3d.create(0, -2)); @@ -2083,7 +2355,9 @@ describe("CurveCurveIntersectXY", () => { const allGeometry: GeometryQuery[] = []; // loop1 const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 6.5), Point3d.create(5, 5), + Point3d.create(1, 5), + Point3d.create(3, 6.5), + Point3d.create(5, 5), ); const lineString1 = LineString3d.create([5, 5], [6, 3], [7, 5], [10, 3]); const lineSegment1 = LineSegment3d.create(Point3d.create(10, 3), Point3d.create(1, 5)); @@ -2094,7 +2368,9 @@ describe("CurveCurveIntersectXY", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // loop2 const arc2 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, -2), Point3d.create(2, -3.5), Point3d.create(4, -2), + Point3d.create(0, -2), + Point3d.create(2, -3.5), + Point3d.create(4, -2), ); const lineString2 = LineString3d.create([4, -2], [6, -1], [8, -2], [9, 6]); const lineSegment2 = LineSegment3d.create(Point3d.create(9, 6), Point3d.create(0, -2)); @@ -2212,7 +2488,9 @@ describe("CurveCurveIntersectXY", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // bag of curves const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 6.5), Point3d.create(5, 5), + Point3d.create(1, 5), + Point3d.create(3, 6.5), + Point3d.create(5, 5), ); const lineString1 = LineString3d.create([5, 5], [6, 3], [7, 5], [10, 3]); const path = Path.create(); @@ -2240,12 +2518,23 @@ describe("CurveCurveIntersectXY", () => { const allGeometry: GeometryQuery[] = []; const bezier = BSplineCurve3d.createUniformKnots([Point3d.createZero(), Point3d.create(1, 1), Point3d.create(2), Point3d.create(3, 1)], 4); if (ck.testDefined(bezier)) { - const arc = Arc3d.createStartMiddleEnd(bezier.endPoint(), Point3d.create(4.5, 0.5), Point3d.create(5, -1), AngleSweep.createStartEndDegrees(0, 60)); + const arc = Arc3d.createStartMiddleEnd( + bezier.endPoint(), + Point3d.create(4.5, 0.5), + Point3d.create(5, -1), + AngleSweep.createStartEndDegrees(0, 60), + ); if (ck.testDefined(arc)) { const options = new StrokeOptions(); options.angleTol = Angle.createDegrees(0.0001); - const testChainIntersection = (chainA: CurveChainWithDistanceIndex, intersectAAtStart: boolean, chainB: CurveChainWithDistanceIndex, intersectBAtStart: boolean, x0: number): number => { + const testChainIntersection = ( + chainA: CurveChainWithDistanceIndex, + intersectAAtStart: boolean, + chainB: CurveChainWithDistanceIndex, + intersectBAtStart: boolean, + x0: number, + ): number => { let numIntersects = 0; const primA = chainA.path.getChild(intersectAAtStart ? 0 : chainA.path.children.length - 1)!; @@ -2261,8 +2550,16 @@ describe("CurveCurveIntersectXY", () => { if (ck.testExactNumber(globalIntersections.length, localIntersections.length, "same # chain-chain and arc-arc extended intersections")) { numIntersects = globalIntersections.length; for (let i = 0; i < numIntersects; ++i) { - ck.testPoint3d(globalIntersections[i].detailA.point, localIntersections[i].detailA.point, "global and local intersections same for detailA"); - ck.testPoint3d(globalIntersections[i].detailB.point, localIntersections[i].detailB.point, "global and local intersections same for detailB"); + ck.testPoint3d( + globalIntersections[i].detailA.point, + localIntersections[i].detailA.point, + "global and local intersections same for detailA", + ); + ck.testPoint3d( + globalIntersections[i].detailB.point, + localIntersections[i].detailB.point, + "global and local intersections same for detailB", + ); const globalFracA = globalIntersections[i].detailA.fraction; const globalFracB = globalIntersections[i].detailB.fraction; if (!Geometry.isIn01(globalFracA)) { @@ -2309,8 +2606,16 @@ describe("CurveCurveIntersectXY", () => { const extArcB = intersectBAtStart ? primB.clonePartialCurve(localFracB, 1) : primB.clonePartialCurve(0, localFracB); if (ck.testDefined(extPathA) && ck.testDefined(extPathB) && ck.testDefined(extArcA) && ck.testDefined(extArcB)) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, [extPathA, extPathB, extArcA, extArcB], x0, 0, i + 1); - ck.testPoint3d(extPathA.endPoint(), intersectBAtStart ? extPathB.startPoint() : extPathB.endPoint(), "extended paths to the intersection"); - ck.testPoint3d(extArcA.endPoint(), intersectBAtStart ? extArcB.startPoint() : extArcB.endPoint(), "extended arcs to the intersection"); + ck.testPoint3d( + extPathA.endPoint(), + intersectBAtStart ? extPathB.startPoint() : extPathB.endPoint(), + "extended paths to the intersection", + ); + ck.testPoint3d( + extArcA.endPoint(), + intersectBAtStart ? extArcB.startPoint() : extArcB.endPoint(), + "extended arcs to the intersection", + ); } } } @@ -2320,16 +2625,25 @@ describe("CurveCurveIntersectXY", () => { const pathA = CurveChainWithDistanceIndex.createCapture(Path.createArray([bezier, arc]), options); // intersect extended chains - let pathB = pathA.cloneTransformed(Transform.createFixedPointAndMatrix(Point3d.create(4), Matrix3d.createDirectionalScale(Vector3d.unitX(-1), -1)), options); + let pathB = pathA.cloneTransformed( + Transform.createFixedPointAndMatrix(Point3d.create(4), Matrix3d.createDirectionalScale(Vector3d.unitX(-1), -1)), + options, + ); if (ck.testDefined(pathB)) { pathB.reverseInPlace(); // mirrored and reversed ck.testExactNumber(4, testChainIntersection(pathA, false, pathB, true, 0), "chains have expected # arc-arc intersections"); } // test arc-bsp intersection - pathB = pathA.cloneTransformed(Transform.createOriginAndMatrix(Point3d.create(4, -1), Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(90))), options); + pathB = pathA.cloneTransformed( + Transform.createOriginAndMatrix(Point3d.create(4, -1), Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(90))), + options, + ); if (ck.testDefined(pathB)) ck.testExactNumber(2, testChainIntersection(pathA, false, pathB, true, 10), "chains have expected # arc-bspline intersections"); - pathB = pathA.cloneTransformed(Transform.createOriginAndMatrix(Point3d.create(2, -3), Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(90))), options); + pathB = pathA.cloneTransformed( + Transform.createOriginAndMatrix(Point3d.create(2, -3), Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, Angle.createDegrees(90))), + options, + ); if (ck.testDefined(pathB)) ck.testExactNumber(2, testChainIntersection(pathA, true, pathB, false, 15), "chains have expected # bspline-arc intersections"); } diff --git a/core/geometry/src/test/curve/CurveCurveIntersectXYZ.test.ts b/core/geometry/src/test/curve/CurveCurveIntersectXYZ.test.ts index 9342ee3f09e0..faea3c4300f9 100644 --- a/core/geometry/src/test/curve/CurveCurveIntersectXYZ.test.ts +++ b/core/geometry/src/test/curve/CurveCurveIntersectXYZ.test.ts @@ -108,14 +108,18 @@ describe("CurveCurveIntersectXYZ", () => { const allGeometry: GeometryQuery[] = []; const origPt = Point3d.create(0, 5); const origSeg = LineSegment3d.create( - Point3d.create(origPt.x, origPt.y, 1), Point3d.create(origPt.x, origPt.y, -1), + Point3d.create(origPt.x, origPt.y, 1), + Point3d.create(origPt.x, origPt.y, -1), ); const origArc = Arc3d.create( - Point3d.createZero(), Vector3d.create(3, 4), Vector3d.create(-4, 3), AngleSweep.createStartSweepDegrees(0, 90), + Point3d.createZero(), + Vector3d.create(3, 4), + Vector3d.create(-4, 3), + AngleSweep.createStartSweepDegrees(0, 90), ); let dx = 0; - for (const trans of - [ + for ( + const trans of [ Transform.identity, Transform.createRefs(undefined, Matrix3d.create90DegreeRotationAroundAxis(0)), Transform.createRefs(undefined, Matrix3d.create90DegreeRotationAroundAxis(1)), @@ -190,7 +194,9 @@ describe("CurveCurveIntersectXYZ", () => { const allGeometry: GeometryQuery[] = []; const dx = 8; const arc = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 4, 1), Point3d.create(4, 2, 1), Point3d.create(7, 4, 1), + Point3d.create(1, 4, 1), + Point3d.create(4, 2, 1), + Point3d.create(7, 4, 1), ) as Arc3d; const linestring = LineString3d.create([2, 4, 1], [4, 1, 1], [5, 5, 1]); const intersectionsX = CurveCurve.intersectionXYZPairs(arc, false, linestring, false); @@ -311,7 +317,9 @@ describe("CurveCurveIntersectXYZ", () => { const geometryA = LineSegment3d.createXYZXYZ(1, 2, -3, -1, 2, 3); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-2, 0), Point3d.create(0, 2), Point3d.create(2, 0), + Point3d.create(-2, 0), + Point3d.create(0, 2), + Point3d.create(2, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); // find intersections @@ -387,11 +395,15 @@ describe("CurveCurveIntersectXYZ", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const geometryA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(-1, 2, 0), Point3d.create(3, 4, 0), Point3d.create(7, 2, 0), + Point3d.create(-1, 2, 0), + Point3d.create(3, 4, 0), + Point3d.create(7, 2, 0), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); const geometryB = Arc3d.createCircularStartMiddleEnd( - Point3d.create(3, 3, -2), Point3d.create(3, 4, 0), Point3d.create(3, 5, -2), + Point3d.create(3, 3, -2), + Point3d.create(3, 4, 0), + Point3d.create(3, 5, -2), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryB); // find intersections @@ -486,7 +498,9 @@ describe("CurveCurveIntersectXYZ", () => { const allGeometry: GeometryQuery[] = []; // path1 const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5, 0), Point3d.create(3, 6.5, 0), Point3d.create(5, 5, 0), + Point3d.create(1, 5, 0), + Point3d.create(3, 6.5, 0), + Point3d.create(5, 5, 0), ); const lineString1 = LineString3d.create([5, 5, 0], [6, 3, -1], [7, 5, 0], [10, 3, 0]); const lineSegment1 = LineSegment3d.create(Point3d.create(10, 3, 0), Point3d.create(1, 5, 0)); @@ -497,7 +511,9 @@ describe("CurveCurveIntersectXYZ", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // path2 const arc2 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, -2), Point3d.create(2, -3.5), Point3d.create(4, -2), + Point3d.create(0, -2), + Point3d.create(2, -3.5), + Point3d.create(4, -2), ); const lineString2 = LineString3d.create([4, -2, 0], [6, -1, 1], [8, -2, -1], [9, 6, 0]); const lineSegment2 = LineSegment3d.create(Point3d.create(9, 6), Point3d.create(0, -2)); @@ -524,7 +540,9 @@ describe("CurveCurveIntersectXYZ", () => { const allGeometry: GeometryQuery[] = []; // loop1 const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 6.5), Point3d.create(5, 5), + Point3d.create(1, 5), + Point3d.create(3, 6.5), + Point3d.create(5, 5), ); const lineString1 = LineString3d.create([5, 5], [6, 3], [7, 5], [10, 3]); const lineSegment1 = LineSegment3d.create(Point3d.create(10, 3), Point3d.create(1, 5)); @@ -535,7 +553,9 @@ describe("CurveCurveIntersectXYZ", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // loop2 const arc2 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, -2), Point3d.create(2, -3.5), Point3d.create(4, -2), + Point3d.create(0, -2), + Point3d.create(2, -3.5), + Point3d.create(4, -2), ); const lineString2 = LineString3d.create([4, -2], [6, -1], [8, -2], [9, 6]); const lineSegment2 = LineSegment3d.create(Point3d.create(9, 6), Point3d.create(0, -2)); @@ -653,7 +673,9 @@ describe("CurveCurveIntersectXYZ", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geometryA); // bag of curves const arc1 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(1, 5), Point3d.create(3, 6.5), Point3d.create(5, 5), + Point3d.create(1, 5), + Point3d.create(3, 6.5), + Point3d.create(5, 5), ); const lineString1 = LineString3d.create([5, 5, 0], [6, 3, 1], [7, 5, -1], [10, 3, 0]); const path = Path.create(); @@ -679,8 +701,14 @@ describe("CurveCurveIntersectXYZ", () => { describe("CurveCurveIntersectXYZChains", () => { function captureAndTestIntersection( - allGeometry: GeometryQuery[], ck: Checker, dx: number, dy: number, - curveA: any, curveB: any, extendA: boolean, extendB: boolean, + allGeometry: GeometryQuery[], + ck: Checker, + dx: number, + dy: number, + curveA: any, + curveB: any, + extendA: boolean, + extendB: boolean, expectedIntersections: number, ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, curveA, dx, dy); @@ -691,9 +719,16 @@ describe("CurveCurveIntersectXYZChains", () => { ck.testExactNumber(expectedIntersections, intersectionDetails.length, `${expectedIntersections} intersection(s) expected`); } function captureTestAndCompareIntersection( - allGeometry: GeometryQuery[], ck: Checker, dx: number, dy: number, - curveA: any, curveB: any, extendA: boolean, extendB: boolean, - expectedIntersectionsXy: number, expectedIntersectionsXyz: number, + allGeometry: GeometryQuery[], + ck: Checker, + dx: number, + dy: number, + curveA: any, + curveB: any, + extendA: boolean, + extendB: boolean, + expectedIntersectionsXy: number, + expectedIntersectionsXyz: number, ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, curveA, dx, dy); GeometryCoreTestIO.captureCloneGeometry(allGeometry, curveB, dx, dy); @@ -740,22 +775,28 @@ describe("CurveCurveIntersectXYZChains", () => { const path = Path.create( LineSegment3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), LineSegment3d.create( - Point3d.create(95.24913755203208, 12.748564710980762), Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(89.42790013152023, 12.74856471098076), ), LineSegment3d.create( - Point3d.create(89.42790013152023, 12.74856471098076), Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(89.42790013152023, 7.375114784355288), ), LineSegment3d.create( - Point3d.create(89.42790013152023, 7.375114784355288), Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(97.67998394741026, 7.3751147843552864), ), LineSegment3d.create( - Point3d.create(97.67998394741026, 7.3751147843552864), Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(97.67998394741026, 2.961209487484229), ), LineSegment3d.create( - Point3d.create(97.67998394741026, 2.961209487484229), Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(102.60564638015066, 2.961209487484229), ), ); @@ -831,7 +872,10 @@ describe("CurveCurveIntersectXYZChains", () => { degrees = -40; rotatedPath = getRotationCurve(path, Angle.createDegrees(degrees)); const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); let rotatedArc = getRotationCurve(arc1, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -839,7 +883,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(0, 180), ); rotatedArc = getRotationCurve(arc2, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -847,7 +894,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc3, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -855,7 +905,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc4, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -863,7 +916,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc5, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -871,7 +927,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(93, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(93, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc6, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -879,7 +938,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(95, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(95, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc7, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -887,7 +949,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc8, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1037,7 +1102,10 @@ describe("CurveCurveIntersectXYZChains", () => { degrees = 90; rotatedPath = getRotationCurve(path, Angle.createDegrees(degrees)); const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); let rotatedArc = getRotationCurve(arc1, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1045,7 +1113,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(0, 180), ); rotatedArc = getRotationCurve(arc2, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1053,7 +1124,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc3, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1061,7 +1135,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc4, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1069,7 +1146,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc5, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1077,7 +1157,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(93, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(93, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc6, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1085,7 +1168,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(95, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(95, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc7, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1093,7 +1179,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc8, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1149,22 +1238,40 @@ describe("CurveCurveIntersectXYZChains", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(100, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(100, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), ); @@ -1240,7 +1347,10 @@ describe("CurveCurveIntersectXYZChains", () => { degrees = -330; rotatedPath = getRotationCurve(path, Angle.createDegrees(degrees)); const arc1 = Arc3d.create( - Point3d.create(87, 10), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(87, 10), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); let rotatedArc = getRotationCurve(arc1, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1248,7 +1358,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc2 = Arc3d.create( - Point3d.create(95, 20), Vector3d.create(3, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(0, 180), + Point3d.create(95, 20), + Vector3d.create(3, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(0, 180), ); rotatedArc = getRotationCurve(arc2, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1256,7 +1369,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc3 = Arc3d.create( - Point3d.create(104, 3), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(104, 3), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc3, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 2); @@ -1264,7 +1380,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 1); dx += 20; const arc4 = Arc3d.create( - Point3d.create(96, 15), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(96, 15), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); rotatedArc = getRotationCurve(arc4, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 4); @@ -1272,7 +1391,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 2); dx += 20; const arc5 = Arc3d.create( - Point3d.create(90, 15), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 15), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc5, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1280,7 +1402,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc6 = Arc3d.create( - Point3d.create(91, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(91, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc6, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1288,7 +1413,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc7 = Arc3d.create( - Point3d.create(96, 11), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(96, 11), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc7, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1296,7 +1424,10 @@ describe("CurveCurveIntersectXYZChains", () => { captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, false, true, 0); dx += 20; const arc8 = Arc3d.create( - Point3d.create(90, 5), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(90, 5), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(90, 270), ); rotatedArc = getRotationCurve(arc8, Angle.createDegrees(degrees)); captureAndTestIntersection(allGeometry, ck, dx, dy, rotatedPath, rotatedArc, true, true, 0); @@ -1352,28 +1483,36 @@ describe("CurveCurveIntersectXYZChains", () => { const loop = Loop.create( LineString3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), LineString3d.create( - Point3d.create(95.24913755203208, 12.748564710980762), Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(89.42790013152023, 12.74856471098076), ), LineString3d.create( - Point3d.create(89.42790013152023, 12.74856471098076), Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(89.42790013152023, 12.74856471098076), + Point3d.create(89.42790013152023, 7.375114784355288), ), LineString3d.create( - Point3d.create(89.42790013152023, 7.375114784355288), Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(89.42790013152023, 7.375114784355288), + Point3d.create(97.67998394741026, 7.3751147843552864), ), LineString3d.create( - Point3d.create(97.67998394741026, 7.3751147843552864), Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(97.67998394741026, 7.3751147843552864), + Point3d.create(97.67998394741026, 2.961209487484229), ), LineString3d.create( - Point3d.create(97.67998394741026, 2.961209487484229), Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(97.67998394741026, 2.961209487484229), + Point3d.create(102.60564638015066, 2.961209487484229), ), LineString3d.create( - Point3d.create(102.60564638015066, 2.961209487484229), Point3d.create(102.60564638015066, 20.36095210703357), + Point3d.create(102.60564638015066, 2.961209487484229), + Point3d.create(102.60564638015066, 20.36095210703357), ), LineString3d.create( - Point3d.create(95.24913755203208, 20.36095210703357), Point3d.create(95.24913755203208, 12.748564710980762), + Point3d.create(95.24913755203208, 20.36095210703357), + Point3d.create(95.24913755203208, 12.748564710980762), ), ); @@ -1461,19 +1600,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path1 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1482,7 +1636,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), ); @@ -1508,19 +1665,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1529,7 +1701,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1564,19 +1739,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1585,7 +1775,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1659,7 +1852,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), ); const curveChain2 = CurveChainWithDistanceIndex.createCapture(path2); @@ -1694,7 +1890,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1732,7 +1931,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1746,19 +1948,34 @@ describe("CurveCurveIntersectXYZChains", () => { ); const path1 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1778,7 +1995,10 @@ describe("CurveCurveIntersectXYZChains", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(81, 10), Vector3d.create(5, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 180), + Point3d.create(81, 10), + Vector3d.create(5, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 180), ), LineSegment3d.create(Point3d.create(75, 10), Point3d.create(80, 10)), LineSegment3d.create(Point3d.create(80, 10), Point3d.create(80, 5)), @@ -1811,7 +2031,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16), Point3d.create(91, 21)), LineString3d.create(Point3d.create(91, 21), Point3d.create(99, 21), Point3d.create(99, 7)), Arc3d.create( - Point3d.create(99, 4), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4), @@ -1823,19 +2046,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(103, 3)), ); @@ -1907,7 +2145,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16, 10), Point3d.create(91, 21, 10)), LineString3d.create(Point3d.create(91, 21, 10), Point3d.create(99, 21, 10), Point3d.create(99, 7, 10)), Arc3d.create( - Point3d.create(99, 4, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4, 10), @@ -1919,19 +2160,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(110, 3)), ); @@ -1961,7 +2217,10 @@ describe("CurveCurveIntersectXYZChains", () => { LineSegment3d.create(Point3d.create(91, 16, 10), Point3d.create(91, 21, 10)), LineString3d.create(Point3d.create(91, 21, 10), Point3d.create(99, 21, 10), Point3d.create(99, 7, 10)), Arc3d.create( - Point3d.create(99, 4, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 0), + Point3d.create(99, 4, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 0), ), LineString3d.create( Point3d.create(100, 4, 10), @@ -1974,19 +2233,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(110, 3)), ); @@ -1995,19 +2269,55 @@ describe("CurveCurveIntersectXYZChains", () => { let dx = 0; const dy = 0; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, true, true, 4, 1, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + true, + true, + 4, + 1, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, true, false, 3, 1, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + true, + false, + 3, + 1, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, false, true, 4, 0, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + false, + true, + 4, + 0, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, false, false, 3, 0, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + false, + false, + 3, + 0, ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveIntersectXYZChains", "intersectionXyzCurveChainCoPlanarVsCurveChainPlanar1"); @@ -2026,19 +2336,34 @@ describe("CurveCurveIntersectXYZChains", () => { const path2 = Path.create( Arc3d.create( - Point3d.create(95, 16), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(95, 16), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, -90), ), Arc3d.create( - Point3d.create(92, 13), Vector3d.create(3, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(360, 180), + Point3d.create(92, 13), + Vector3d.create(3, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(360, 180), ), Arc3d.create( - Point3d.create(89, 10), Vector3d.create(1, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(90, 270), + Point3d.create(89, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(90, 270), ), Arc3d.create( - Point3d.create(93, 7), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(180, 360), + Point3d.create(93, 7), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(180, 360), ), Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ), LineString3d.create(Point3d.create(97, 3), Point3d.create(110, 3)), ); @@ -2047,19 +2372,55 @@ describe("CurveCurveIntersectXYZChains", () => { let dx = 0; const dy = 0; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, true, true, 3, 1, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + true, + true, + 3, + 1, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, true, false, 3, 1, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + true, + false, + 3, + 1, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, false, true, 0, 0, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + false, + true, + 0, + 0, ); dx += 40; captureTestAndCompareIntersection( - allGeometry, ck, dx, dy, curveChain1, curveChain2, false, false, 0, 0, + allGeometry, + ck, + dx, + dy, + curveChain1, + curveChain2, + false, + false, + 0, + 0, ); GeometryCoreTestIO.saveGeometry(allGeometry, "CurveCurveIntersectXYZChains", "intersectionXyzCurveChainCoPlanarVsCurveChainPlanar2"); @@ -2070,10 +2431,16 @@ describe("CurveCurveIntersectXYZChains", () => { const allGeometry: GeometryQuery[] = []; const arc1 = Arc3d.create( - Point3d.create(77, 10), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(77, 10), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(-90, 90), ); const arc2 = Arc3d.create( - Point3d.create(77, 20), Vector3d.create(5, 0), Vector3d.create(0, 3), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(77, 20), + Vector3d.create(5, 0), + Vector3d.create(0, 3), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, 0, 0, arc2, arc1, false, false, 0); @@ -2085,10 +2452,16 @@ describe("CurveCurveIntersectXYZChains", () => { const allGeometry: GeometryQuery[] = []; const arc1 = Arc3d.create( - Point3d.create(97, 5), Vector3d.create(1, 0), Vector3d.create(0, 2), AngleSweep.createStartEndDegrees(90, -90), + Point3d.create(97, 5), + Vector3d.create(1, 0), + Vector3d.create(0, 2), + AngleSweep.createStartEndDegrees(90, -90), ); const arc2 = Arc3d.create( - Point3d.create(97, 15), Vector3d.create(4, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(-90, 90), + Point3d.create(97, 15), + Vector3d.create(4, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(-90, 90), ); captureAndTestIntersection(allGeometry, ck, 0, 0, arc1, arc2, false, false, 0); diff --git a/core/geometry/src/test/curve/CurveExtendMode.test.ts b/core/geometry/src/test/curve/CurveExtendMode.test.ts index fb3983a3b61a..bd1e8e20563f 100644 --- a/core/geometry/src/test/curve/CurveExtendMode.test.ts +++ b/core/geometry/src/test/curve/CurveExtendMode.test.ts @@ -9,7 +9,6 @@ import { AngleSweep } from "../../geometry3d/AngleSweep"; import { Checker } from "../Checker"; describe("CurveExtendMode", () => { - it("HelloWorld", () => { const ck = new Checker(); ck.testExactNumber(CurveExtendMode.None, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(false, 0)); @@ -17,8 +16,14 @@ describe("CurveExtendMode", () => { ck.testExactNumber(CurveExtendMode.None, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.None, 0)); ck.testExactNumber(CurveExtendMode.None, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.None, 1)); - ck.testExactNumber(CurveExtendMode.OnTangent, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.OnTangent, 0)); - ck.testExactNumber(CurveExtendMode.OnTangent, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.OnTangent, 1)); + ck.testExactNumber( + CurveExtendMode.OnTangent, + CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.OnTangent, 0), + ); + ck.testExactNumber( + CurveExtendMode.OnTangent, + CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(CurveExtendMode.OnTangent, 1), + ); const qTangentNone: [CurveExtendMode, CurveExtendMode] = [CurveExtendMode.OnTangent, CurveExtendMode.None]; ck.testExactNumber(CurveExtendMode.OnTangent, CurveExtendOptions.resolveVariantCurveExtendParameterToCurveExtendMode(qTangentNone, 0)); diff --git a/core/geometry/src/test/curve/CurveFactory.test.ts b/core/geometry/src/test/curve/CurveFactory.test.ts index 627ff9c901d7..002eb42ab06a 100644 --- a/core/geometry/src/test/curve/CurveFactory.test.ts +++ b/core/geometry/src/test/curve/CurveFactory.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BSplineCurve3d } from "../../bspline/BSplineCurve"; import { Arc3d } from "../../curve/Arc3d"; import { CurveCollection } from "../../curve/CurveCollection"; @@ -51,7 +51,8 @@ describe("CurveFactory", () => { Point3d.create(8, 3), Point3d.create(13, 5), Point3d.create(12, 8), - Point3d.create(5, 8)]; + Point3d.create(5, 8), + ]; const points2 = [ Point3d.create(1, 1), @@ -62,7 +63,8 @@ describe("CurveFactory", () => { Point3d.create(-1, 1), Point3d.create(-1, 8), Point3d.create(4, 12), - Point3d.create(8, 14)]; + Point3d.create(8, 14), + ]; let x0 = 0.0; const xStep = 30; const yStep = 20; @@ -103,10 +105,13 @@ describe("CurveFactory", () => { let x0 = 0.0; const xStep = 3.0; const yStep = 3.0; - for (const arcA0 of [ - Arc3d.createXYZXYZXYZ(0, 0, 0, 2, 0, 0, 0, 2, 0, AngleSweep.createStartEndDegrees(0, 90)), - Arc3d.createCircularStartMiddleEnd(Point3d.create(1, 0, 0), Point3d.create(1.5, 1, 0), Point3d.create(1, 2, 0)) as Arc3d, - Arc3d.createXYZXYZXYZ(0, 0, 0, 2, 0, 0, 0.5, 1, 0, AngleSweep.createStartEndDegrees(-10, 50))]) { + for ( + const arcA0 of [ + Arc3d.createXYZXYZXYZ(0, 0, 0, 2, 0, 0, 0, 2, 0, AngleSweep.createStartEndDegrees(0, 90)), + Arc3d.createCircularStartMiddleEnd(Point3d.create(1, 0, 0), Point3d.create(1.5, 1, 0), Point3d.create(1, 2, 0)) as Arc3d, + Arc3d.createXYZXYZXYZ(0, 0, 0, 2, 0, 0, 0.5, 1, 0, AngleSweep.createStartEndDegrees(-10, 50)), + ] + ) { for (const reverse of [false, true]) { const arcA = arcA0.clone(); if (reverse) @@ -147,7 +152,14 @@ describe("CurveFactory", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; let x0 = 0.0; - const points = [Point3d.create(0, 0, 0), Point3d.create(2, 0, 0), Point3d.create(2, 5, 1), Point3d.create(4, 5, 1), Point3d.create(6, 2, 1), Point3d.create(6, 5, 1)]; + const points = [ + Point3d.create(0, 0, 0), + Point3d.create(2, 0, 0), + Point3d.create(2, 5, 1), + Point3d.create(4, 5, 1), + Point3d.create(6, 2, 1), + Point3d.create(6, 5, 1), + ]; const lineString0 = LineString3d.create(points); points.reverse(); const lineString1 = LineString3d.create(points); @@ -175,7 +187,6 @@ describe("CurveFactory", () => { }); }); /** - * * @param allGeometry * @param arc * @param radialFraction draw arc at this fraction of radius @@ -190,9 +201,16 @@ function markArcData(allGeometry: GeometryQuery[], arc: Arc3d, radialFraction: n const point0 = arc.angleToPointAndDerivative(Angle.createDegrees(0)); const point90 = arc.angleToPointAndDerivative(Angle.createDegrees(90)); arc1.matrixRef.scaleColumnsInPlace(radialFraction, radialFraction, 1.0); - GeometryCoreTestIO.captureGeometry(allGeometry, [arc1, - LineSegment3d.create(center.interpolate(radialFraction, start), center.interpolate(radialFraction + tickFraction, start)), - LineString3d.create(point0.origin, center, point90.origin)], x0, y0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + [ + arc1, + LineSegment3d.create(center.interpolate(radialFraction, start), center.interpolate(radialFraction + tickFraction, start)), + LineString3d.create(point0.origin, center, point90.origin), + ], + x0, + y0, + ); } const ppePathInputDirector = "./src/test/data/pipeConnections/"; describe("PipeConnections", () => { @@ -250,9 +268,16 @@ describe("PipeConnections", () => { for (const numPoints of [8, 20, 40]) { const path = new Point3dArrayCarrier( - Sample.createPointSineWave(undefined, numPoints, 10.0 / numPoints, - 5.0, AngleSweep.createStartEndDegrees(0, 520), - 3.0, AngleSweep.createStartEndDegrees(0, 100))); + Sample.createPointSineWave( + undefined, + numPoints, + 10.0 / numPoints, + 5.0, + AngleSweep.createStartEndDegrees(0, 520), + 3.0, + AngleSweep.createStartEndDegrees(0, 100), + ), + ); allPaths.push(path); } @@ -279,14 +304,14 @@ describe("PipeConnections", () => { startPoint.setFrom(startRay.origin); startTangent.setFrom(startRay.direction); } - const startFrame = Matrix3d.createRotationAroundVector(startTangent, v0Angle)!.multiplyMatrixMatrix(Matrix3d.createRigidHeadsUp(startTangent, AxisOrder.ZXY)); + const startFrame = Matrix3d.createRotationAroundVector(startTangent, v0Angle)!.multiplyMatrixMatrix( + Matrix3d.createRigidHeadsUp(startTangent, AxisOrder.ZXY), + ); const v0 = startFrame.columnX().scaleToLength(radius)!; const v90 = startFrame.columnY().scaleToLength(radius * minorFraction)!; for (const angleTol of [Angle.createDegrees(22), Angle.createDegrees(15), Angle.createDegrees(5)]) { - for (const sectionData of [radius, - { x: radius, y: radius * minorFraction }, - Arc3d.create(startPoint, v0, v90, AngleSweep.create360())]) { + for (const sectionData of [radius, { x: radius, y: radius * minorFraction }, Arc3d.create(startPoint, v0, v90, AngleSweep.create360())]) { y0 += 10.0; const builder = PolyfaceBuilder.create(); builder.options.angleTol = angleTol; @@ -384,18 +409,25 @@ describe("PipeConnections", () => { centerlines.push([Point3d.create(0, 0, 0), Point3d.create(0, 0, 10), Point3d.create(0, 12, 10)]); // closed planar centerlines.push( - [Point3d.create(0, 0, 0), Point3d.create(0, 0, a), Point3d.create(0, a, a), Point3d.create(0, a, 0), Point3d.create(0, 0, 0)]); + [Point3d.create(0, 0, 0), Point3d.create(0, 0, a), Point3d.create(0, a, a), Point3d.create(0, a, 0), Point3d.create(0, 0, 0)], + ); // closed non-planar centerlines.push( - [Point3d.create(0, 0, 0), Point3d.create(0, 0, a), Point3d.create(0, a, a), Point3d.create(4, a, 0), Point3d.create(0, 0, 0)]); + [Point3d.create(0, 0, 0), Point3d.create(0, 0, a), Point3d.create(0, a, a), Point3d.create(4, a, 0), Point3d.create(0, 0, 0)], + ); // with duplicate points. centerlines.push( - [Point3d.create(0, 0, 0), - Point3d.create(0, 0, a), Point3d.create(0, 0, a), - Point3d.create(0, a, a), - Point3d.create(4, a, 0), - Point3d.create(0, 0, 0), Point3d.create(0, 0, 0)]); + [ + Point3d.create(0, 0, 0), + Point3d.create(0, 0, a), + Point3d.create(0, 0, a), + Point3d.create(0, a, a), + Point3d.create(4, a, 0), + Point3d.create(0, 0, 0), + Point3d.create(0, 0, 0), + ], + ); const numDuplicates: number[] = []; for (const centerline of centerlines) { @@ -408,7 +440,7 @@ describe("PipeConnections", () => { } const wrapIfClosed = [false, false, true, false]; let x0Out = 0; - const z0Out = -3.0; // for input section + const z0Out = -3.0; // for input section const outDelta = 20.0; // sections with various corner conditions . . for (const radiusA of [undefined, 0.0, 3.0]) { @@ -422,14 +454,21 @@ describe("PipeConnections", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, centerline, x0Out, y0Out); GeometryCoreTestIO.captureCloneGeometry(allGeometry, rectangleA, x0Out, y0Out, z0Out); if (sweeps !== undefined) { - if (ck.testDefined(sweeps.sections) && ck.testDefined(sweeps.planes) && ck.testExactNumber(sweeps.planes.length, sweeps.sections.length, "Same number of planes and sections")) { - + if ( + ck.testDefined(sweeps.sections) && ck.testDefined(sweeps.planes) && + ck.testExactNumber(sweeps.planes.length, sweeps.sections.length, "Same number of planes and sections") + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, sweeps.sections, x0Out, y0Out); ck.testExactNumber(centerline.length - numDuplicates[centerlineIndex], sweeps.sections.length, "confirm section count"); for (const plane of sweeps.planes) { GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, plane.getAnyPointOnPlane(), 0.25, x0Out, y0Out); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, [plane.getOriginRef(), plane.getOriginRef().plus(plane.getNormalRef())], x0Out, y0Out); + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, + [plane.getOriginRef(), plane.getOriginRef().plus(plane.getNormalRef())], + x0Out, + y0Out, + ); } for (let i = 0; i < sweeps.sections.length; i++) @@ -495,13 +534,18 @@ describe("PipeConnections", () => { ck.announceError("expect primitive or collection for section ", section); break; } - const sections = CurveFactory.createMiteredSweepSections(strokePoints, section, { wrapIfPhysicallyClosed: true, outputSelect: MiteredSweepOutputSelect.AlsoMesh })!; + const sections = CurveFactory.createMiteredSweepSections(strokePoints, section, { + wrapIfPhysicallyClosed: true, + outputSelect: MiteredSweepOutputSelect.AlsoMesh, + })!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, strokePoints, x0, y0, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, section, x0, y1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, strokePoints, x0, y1); GeometryCoreTestIO.captureCloneGeometry(allGeometry, sections.sections, x0, y0); - if (ck.testType(sections.ruledSweep, RuledSweep, "output ruled sweep") && - ck.testType(sections.mesh, IndexedPolyface, "output mesh")) { + if ( + ck.testType(sections.ruledSweep, RuledSweep, "output ruled sweep") && + ck.testType(sections.mesh, IndexedPolyface, "output mesh") + ) { const sweptSurface = sections.ruledSweep; const mesh = sections.mesh; GeometryCoreTestIO.captureCloneGeometry(allGeometry, sweptSurface, x0, ySurface); @@ -523,7 +567,6 @@ describe("PipeConnections", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CurveFactory", "createMiteredSweepStadiumExample"); expect(ck.getNumErrors()).toBe(0); }); - }); function isGeometryInPlane(geometry: GeometryQuery, plane: Plane3dByOriginAndUnitNormal): boolean { diff --git a/core/geometry/src/test/curve/CurveLocationDetail.test.ts b/core/geometry/src/test/curve/CurveLocationDetail.test.ts index 191e4c410dbe..a7818b55c501 100644 --- a/core/geometry/src/test/curve/CurveLocationDetail.test.ts +++ b/core/geometry/src/test/curve/CurveLocationDetail.test.ts @@ -7,8 +7,8 @@ import { describe, expect, it } from "vitest"; import { CurveLocationDetail, CurveLocationDetailPair } from "../../curve/CurveLocationDetail"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { Geometry } from "../../Geometry"; -import { Checker } from "../Checker"; import { Point3d } from "../../geometry3d/Point3dVector3d"; +import { Checker } from "../Checker"; describe("CurveLocationDetail", () => { it("HelloWorld", () => { @@ -27,7 +27,7 @@ describe("CurveLocationDetail", () => { const detailB0 = detailA0.clone(); detailA0.fraction += 0.5; - const detailB1 = detailB0.clone(detailB0); // nothing happens, but a return gets reached. + const detailB1 = detailB0.clone(detailB0); // nothing happens, but a return gets reached. ck.testPointer(detailB0, detailB1); ck.checkpoint("CurveLocationDetail.HelloWorld"); @@ -46,7 +46,7 @@ describe("CurveLocationDetail", () => { const g1 = detailA0.inverseInterpolateFraction(f, g0); ck.testExactNumber(g, g1, "inverse interpolation in simple interval."); // a degenerate two-point detail - const detailA2 = CurveLocationDetail.createCurveEvaluatedFractionFraction(segmentA, f0, f0); // degenerate ! + const detailA2 = CurveLocationDetail.createCurveEvaluatedFractionFraction(segmentA, f0, f0); // degenerate ! const g2 = detailA2.inverseInterpolateFraction(f0, g0); ck.testExactNumber(g0, g2, "inverse interpolate in degenerate interval"); @@ -67,8 +67,10 @@ describe("CurveLocationDetail", () => { copy.collapseToEnd(); ck.testExactNumber(copy.fraction, detail.fraction1!, "CurveLocationDetail.collapseToEnd moves fraction1 to fraction"); ck.testPoint3d(copy.point, detail.point1!, "CurveLocationDetail.collapseToEnd moves point1 to point"); - if (ck.testUndefined(copy.fraction1, "CurveLocationDetail.collapseToEnd nullifies fraction1") && - ck.testUndefined(copy.point1, "CurveLocationDetail.collapseToEnd nullifies point1")) { + if ( + ck.testUndefined(copy.fraction1, "CurveLocationDetail.collapseToEnd nullifies fraction1") && + ck.testUndefined(copy.point1, "CurveLocationDetail.collapseToEnd nullifies point1") + ) { const copy1 = copy.clone(); copy1.collapseToEnd(); ck.testExactNumber(copy1.fraction, copy.fraction, "CurveLocationDetail.collapseToEnd preserves fraction if fraction1 undefined"); diff --git a/core/geometry/src/test/curve/EmitStrokableParts.test.ts b/core/geometry/src/test/curve/EmitStrokableParts.test.ts index bce6e4c28125..07eb669e5d2b 100644 --- a/core/geometry/src/test/curve/EmitStrokableParts.test.ts +++ b/core/geometry/src/test/curve/EmitStrokableParts.test.ts @@ -34,7 +34,9 @@ class StrokeVerifier implements IStrokeHandler { this._myCP = undefined; this.frameBuilder = new FrameBuilder(); } - public startCurvePrimitive(cp: CurvePrimitive): void { this._myCP = cp; } + public startCurvePrimitive(cp: CurvePrimitive): void { + this._myCP = cp; + } public announcePointTangent(xyz: Point3d, fraction: number, tangent: Vector3d): void { this.frameBuilder.announcePoint(xyz); this._ck.testTrue(this.frameBuilder.hasOrigin, "frameBuilder.hasOrigin after a point is announced"); @@ -51,7 +53,8 @@ class StrokeVerifier implements IStrokeHandler { _cp: CurvePrimitive, _numStrokes: number, _fraction0: number, - _fraction1: number): void { + _fraction1: number, + ): void { // } /** Announce numPoints interpolated between point0 and point1, with associated fractions */ @@ -61,16 +64,20 @@ class StrokeVerifier implements IStrokeHandler { _point1: Point3d, _numStrokes: number, _fraction0: number, - _fraction1: number): void { + _fraction1: number, + ): void { // } - public endCurvePrimitive(_cp: CurvePrimitive): void { this._myCP = undefined; } + public endCurvePrimitive(_cp: CurvePrimitive): void { + this._myCP = undefined; + } public startParentCurvePrimitive(_cp: CurvePrimitive): void { this._ck.testUndefined(this._myParent, "Stroker parentCurve cannot be recursive"); this._myParent = _cp; } - public endParentCurvePrimitive(_cp: CurvePrimitive): void { this._myParent = undefined; } - + public endParentCurvePrimitive(_cp: CurvePrimitive): void { + this._myParent = undefined; + } } describe("EmitStrokableParts", () => { diff --git a/core/geometry/src/test/curve/GeometryQuery.test.ts b/core/geometry/src/test/curve/GeometryQuery.test.ts index 0f1767ace4cc..625d6cb015e7 100644 --- a/core/geometry/src/test/curve/GeometryQuery.test.ts +++ b/core/geometry/src/test/curve/GeometryQuery.test.ts @@ -4,24 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; +import { AkimaCurve3d } from "../../bspline/AkimaCurve3d"; import { BezierCurve3d } from "../../bspline/BezierCurve3d"; import { BezierCurve3dH } from "../../bspline/BezierCurve3dH"; import { BSplineCurve3d } from "../../bspline/BSplineCurve"; import { BSplineCurve3dH } from "../../bspline/BSplineCurve3dH"; import { BSplineSurface3d, BSplineSurface3dH } from "../../bspline/BSplineSurface"; +import { InterpolationCurve3d } from "../../bspline/InterpolationCurve3d"; import { Arc3d } from "../../curve/Arc3d"; import { CoordinateXYZ } from "../../curve/CoordinateXYZ"; import { CurveCollection } from "../../curve/CurveCollection"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; +import { Loop } from "../../curve/Loop"; +import { ParityRegion } from "../../curve/ParityRegion"; import { Path } from "../../curve/Path"; import { PointString3d } from "../../curve/PointString3d"; import { CylindricalRangeQuery } from "../../curve/Query/CylindricalRange"; import { StrokeCountSection } from "../../curve/Query/StrokeCountChain"; -import { StrokeOptions } from "../../curve/StrokeOptions"; import { TransitionSpiral3d } from "../../curve/spiral/TransitionSpiral3d"; +import { StrokeOptions } from "../../curve/StrokeOptions"; import { GeometryHandler, NullGeometryHandler, RecurseToCurvesGeometryHandler } from "../../geometry3d/GeometryHandler"; import { Vector3d } from "../../geometry3d/Point3dVector3d"; +import { Range1d } from "../../geometry3d/Range"; import { Ray3d } from "../../geometry3d/Ray3d"; import { IndexedPolyface } from "../../polyface/Polyface"; import { Sample } from "../../serialization/GeometrySamples"; @@ -33,43 +38,62 @@ import { RuledSweep } from "../../solid/RuledSweep"; import { Sphere } from "../../solid/Sphere"; import { TorusPipe } from "../../solid/TorusPipe"; import { Checker } from "../Checker"; -import { Range1d } from "../../geometry3d/Range"; -import { ParityRegion } from "../../curve/ParityRegion"; -import { Loop } from "../../curve/Loop"; -import { InterpolationCurve3d } from "../../bspline/InterpolationCurve3d"; -import { AkimaCurve3d } from "../../bspline/AkimaCurve3d"; /** Like NullGeometryHandler, but allow various CurveCollections to flow to base class, where they reach handleCurveCollection. */ export class MinimalGeometryHandler extends GeometryHandler { /** no-action implementation */ - public handleLineSegment3d(_g: LineSegment3d): any { return undefined; } + public handleLineSegment3d(_g: LineSegment3d): any { + return undefined; + } /** no-action implementation */ - public handleLineString3d(_g: LineString3d): any { return undefined; } + public handleLineString3d(_g: LineString3d): any { + return undefined; + } /** no-action implementation */ - public handleArc3d(_g: Arc3d): any { return undefined; } + public handleArc3d(_g: Arc3d): any { + return undefined; + } /** no-action implementation */ // public handleCurveCollection(_g: CurveCollection): any { return undefined; } /** no-action implementation */ - public handleBSplineCurve3d(_g: BSplineCurve3d): any { return undefined; } + public handleBSplineCurve3d(_g: BSplineCurve3d): any { + return undefined; + } /** no-action implementation */ - public handleInterpolationCurve3d(_g: InterpolationCurve3d): any { return undefined; } + public handleInterpolationCurve3d(_g: InterpolationCurve3d): any { + return undefined; + } /** no-action implementation */ - public handleAkimaCurve3d(_g: AkimaCurve3d): any { return undefined; } + public handleAkimaCurve3d(_g: AkimaCurve3d): any { + return undefined; + } /** no-action implementation */ - public handleBSplineCurve3dH(_g: BSplineCurve3dH): any { return undefined; } + public handleBSplineCurve3dH(_g: BSplineCurve3dH): any { + return undefined; + } /** no-action implementation */ - public handleBSplineSurface3d(_g: BSplineSurface3d): any { return undefined; } + public handleBSplineSurface3d(_g: BSplineSurface3d): any { + return undefined; + } /** no-action implementation */ - public handleCoordinateXYZ(_g: CoordinateXYZ): any { return undefined; } + public handleCoordinateXYZ(_g: CoordinateXYZ): any { + return undefined; + } /** no-action implementation */ - public handleBSplineSurface3dH(_g: BSplineSurface3dH): any { return undefined; } + public handleBSplineSurface3dH(_g: BSplineSurface3dH): any { + return undefined; + } /** no-action implementation */ - public handleIndexedPolyface(_g: IndexedPolyface): any { return undefined; } + public handleIndexedPolyface(_g: IndexedPolyface): any { + return undefined; + } /** no-action implementation * @alpha */ - public handleTransitionSpiral(_g: TransitionSpiral3d): any { return undefined; } + public handleTransitionSpiral(_g: TransitionSpiral3d): any { + return undefined; + } /** no-action implementation */ // public handlePath(_g: Path): any { return undefined; } @@ -83,25 +107,45 @@ export class MinimalGeometryHandler extends GeometryHandler { // public handleBagOfCurves(_g: BagOfCurves): any { return undefined; } /** no-action implementation */ - public handleSphere(_g: Sphere): any { return undefined; } + public handleSphere(_g: Sphere): any { + return undefined; + } /** no-action implementation */ - public handleCone(_g: Cone): any { return undefined; } + public handleCone(_g: Cone): any { + return undefined; + } /** no-action implementation */ - public handleBox(_g: Box): any { return undefined; } + public handleBox(_g: Box): any { + return undefined; + } /** no-action implementation */ - public handleTorusPipe(_g: TorusPipe): any { return undefined; } + public handleTorusPipe(_g: TorusPipe): any { + return undefined; + } /** no-action implementation */ - public handleLinearSweep(_g: LinearSweep): any { return undefined; } + public handleLinearSweep(_g: LinearSweep): any { + return undefined; + } /** no-action implementation */ - public handleRotationalSweep(_g: RotationalSweep): any { return undefined; } + public handleRotationalSweep(_g: RotationalSweep): any { + return undefined; + } /** no-action implementation */ - public handleRuledSweep(_g: RuledSweep): any { return undefined; } + public handleRuledSweep(_g: RuledSweep): any { + return undefined; + } /** no-action implementation */ - public handlePointString3d(_g: PointString3d): any { return undefined; } + public handlePointString3d(_g: PointString3d): any { + return undefined; + } /** no-action implementation */ - public handleBezierCurve3d(_g: BezierCurve3d): any { return undefined; } + public handleBezierCurve3d(_g: BezierCurve3d): any { + return undefined; + } /** no-action implementation */ - public handleBezierCurve3dH(_g: BezierCurve3dH): any { return undefined; } + public handleBezierCurve3dH(_g: BezierCurve3dH): any { + return undefined; + } } describe("GeometryQuery", () => { @@ -117,7 +161,6 @@ describe("GeometryQuery", () => { g.dispatchToGeometryHandler(recurseHandler); if (g instanceof CurveCollection) recurseHandler.handleCurveCollection(g); - } const minimalHandler = new MinimalGeometryHandler(); @@ -125,7 +168,6 @@ describe("GeometryQuery", () => { g.dispatchToGeometryHandler(minimalHandler); expect(ck.getNumErrors()).toBe(0); }); - }); describe("CylindricalRangeQuery", () => { diff --git a/core/geometry/src/test/curve/LineSegment3d.test.ts b/core/geometry/src/test/curve/LineSegment3d.test.ts index 240d2c4fd774..cf058a6ce076 100644 --- a/core/geometry/src/test/curve/LineSegment3d.test.ts +++ b/core/geometry/src/test/curve/LineSegment3d.test.ts @@ -20,8 +20,7 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function exerciseLineSegment3d(ck: Checker, segmentA: LineSegment3d) { const a = 4.2; - const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), - Matrix3d.createScale(a, a, a)); + const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), Matrix3d.createScale(a, a, a)); const segment0 = LineSegment3d.create(Point3d.create(), Point3d.create()); const segmentB = segment0.clone(); // zeros!! @@ -67,7 +66,7 @@ function exerciseLineSegment3d(ck: Checker, segmentA: LineSegment3d) { describe("LineSegment3d", () => { it("HelloWorld", () => { const ck = new Checker(); - const result = LineSegment3d.createXYXY(0, 0, 0, 0); // cover result arg in next line + const result = LineSegment3d.createXYXY(0, 0, 0, 0); // cover result arg in next line const segmentA = LineSegment3d.createXYXY(1, 2, 6, 3, 1, result); exerciseLineSegment3d(ck, segmentA); @@ -81,19 +80,28 @@ describe("LineSegment3d", () => { ck.testFalse(coordinate.isAlmostEqual(segmentB)); const segmentD = LineSegment3d.createXYZXYZ(1, 2, 3, 4, 5, 6); - const segmentE = LineSegment3d.createXYZXYZ(1, 2, 3, 4, 5, 6, segmentC); // overwrite the default segmentC. + const segmentE = LineSegment3d.createXYZXYZ(1, 2, 3, 4, 5, 6, segmentC); // overwrite the default segmentC. ck.testPointer(segmentE, segmentC, "reuse of optional arg"); ck.testTrue(segmentD.isAlmostEqual(segmentE)); - const segmentF = LineSegment3d.create(segmentA.endPoint(), segmentA.startPoint(), segmentD); // another optional + const segmentF = LineSegment3d.create(segmentA.endPoint(), segmentA.startPoint(), segmentD); // another optional ck.testFalse(segmentF.isAlmostEqual(segmentA)); segmentF.reverseInPlace(); ck.testTrue(segmentF.isAlmostEqual(segmentA)); const fraction = 0.27; - const worldToLocal = Transform.createRigidFromOriginAndColumns(segmentA.point0Ref, Vector3d.createStartEnd(segmentA.point0Ref, segmentA.point1Ref), Vector3d.createFrom([0, 1, 0]), AxisOrder.XYZ); + const worldToLocal = Transform.createRigidFromOriginAndColumns( + segmentA.point0Ref, + Vector3d.createStartEnd(segmentA.point0Ref, segmentA.point1Ref), + Vector3d.createFrom([0, 1, 0]), + AxisOrder.XYZ, + ); const localRangeFirstHalf = segmentA.rangeBetweenFractions(0, fraction, worldToLocal?.inverse()); - ck.testRange3d(localRangeFirstHalf, Range3d.createXYZXYZ(0, 0, 0, fraction * segmentA.curveLength(), 0, 0), "rangeBetweenFractions with Transform"); + ck.testRange3d( + localRangeFirstHalf, + Range3d.createXYZXYZ(0, 0, 0, fraction * segmentA.curveLength(), 0, 0), + "rangeBetweenFractions with Transform", + ); const xRange = segmentA.projectedParameterRange(Vector3d.create(1, 0, 0)); if (ck.testType(xRange, Range1d, "projectedParameterRange returns a range")) @@ -227,8 +235,10 @@ describe("LineSegment3d", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, segmentB, x0, y0); if (approach) { numNonParallel++; - if (Math.abs(approach.detailA.fraction - 0.5) < interiorFractionTrigger - && Math.abs(approach.detailB.fraction - 0.5) < interiorFractionTrigger) + if ( + Math.abs(approach.detailA.fraction - 0.5) < interiorFractionTrigger + && Math.abs(approach.detailB.fraction - 0.5) < interiorFractionTrigger + ) numSimple++; verifyAVectorsAtA(ck, approach.detailA, approach.detailB); verifyAVectorsAtA(ck, approach.detailB, approach.detailA); @@ -289,6 +299,5 @@ function verifyAVectorsAtA(ck: Checker, detailA: CurveLocationDetail, detailB: C ck.testLE(d, curveA.fractionToPoint(fractionA).distance(detailB.curve!.fractionToPoint(fractionB))); } } - } } diff --git a/core/geometry/src/test/curve/LineString3d.test.ts b/core/geometry/src/test/curve/LineString3d.test.ts index 423dcfa50b93..a9a3c7c631e2 100644 --- a/core/geometry/src/test/curve/LineString3d.test.ts +++ b/core/geometry/src/test/curve/LineString3d.test.ts @@ -34,13 +34,13 @@ function exerciseClonePartialLineString3d(ck: Checker, allGeometry: GeometryQuer delta.x += 1.2 * lsA.range().xLength(); GeometryCoreTestIO.captureCloneGeometry(allGeometry, lsA, delta.x, delta.y = 0); for (const extendFraction of [0.05, 0.721, 1.4, 3.96]) { - const cee0 = lsA.clonePartialCurve(-extendFraction, -extendFraction / 2); // does not contain [0,1] - const ce0 = lsA.clonePartialCurve(-extendFraction, 0); // contains [0] - const ce01 = lsA.clonePartialCurve(-extendFraction, 1); // contains [0,1] - const ce01e = lsA.clonePartialCurve(-extendFraction, 1 + extendFraction); // contains [0,1] - const c01e = lsA.clonePartialCurve(0, 1 + extendFraction); // contains [0,1] - const c1e = lsA.clonePartialCurve(1, 1 + extendFraction); // contains [1] - const c1ee = lsA.clonePartialCurve(1 + extendFraction / 2, 1 + extendFraction); // does not contain [0,1] + const cee0 = lsA.clonePartialCurve(-extendFraction, -extendFraction / 2); // does not contain [0,1] + const ce0 = lsA.clonePartialCurve(-extendFraction, 0); // contains [0] + const ce01 = lsA.clonePartialCurve(-extendFraction, 1); // contains [0,1] + const ce01e = lsA.clonePartialCurve(-extendFraction, 1 + extendFraction); // contains [0,1] + const c01e = lsA.clonePartialCurve(0, 1 + extendFraction); // contains [0,1] + const c1e = lsA.clonePartialCurve(1, 1 + extendFraction); // contains [1] + const c1ee = lsA.clonePartialCurve(1 + extendFraction / 2, 1 + extendFraction); // does not contain [0,1] // first segment distance multipliers const preLocal = lsA.globalFractionToSegmentIndexAndLocalFraction(-extendFraction); @@ -56,43 +56,72 @@ function exerciseClonePartialLineString3d(ck: Checker, allGeometry: GeometryQuer if (ck.testPointer(cee0) && expectValidResults) { ck.testExactNumber(cee0.numPoints(), 2, "isolated pre-extension is a segment"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(cee0.curveLength(), preLocalFractionHalf * lsA.points[0].distance(lsA.points[1]), "isolated pre-extension length is fraction of first segment"); + ck.testCoordinate( + cee0.curveLength(), + preLocalFractionHalf * lsA.points[0].distance(lsA.points[1]), + "isolated pre-extension length is fraction of first segment", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, cee0, delta.x, delta.y += yInc); } if (ck.testPointer(ce0) && expectValidResults) { ck.testExactNumber(ce0.numPoints(), 2, "pre-extension is a segment"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(ce0.curveLength(), preLocalFraction * lsA.points[0].distance(lsA.points[1]), "pre-extension length is fraction of first segment"); + ck.testCoordinate( + ce0.curveLength(), + preLocalFraction * lsA.points[0].distance(lsA.points[1]), + "pre-extension length is fraction of first segment", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce0, delta.x, delta.y += yInc); } if (ck.testPointer(ce01) && expectValidResults) { ck.testExactNumber(ce01.numPoints(), lsA.numPoints(), "pre-extended linestring has same point count"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(ce01.curveLength(), lsA.curveLength() + preLocalFraction * lsA.points[0].distance(lsA.points[1]), "pre-extended linestring has expected length"); + ck.testCoordinate( + ce01.curveLength(), + lsA.curveLength() + preLocalFraction * lsA.points[0].distance(lsA.points[1]), + "pre-extended linestring has expected length", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce01, delta.x, delta.y += yInc); } if (ck.testPointer(ce01e) && expectValidResults) { ck.testExactNumber(ce01e.numPoints(), lsA.numPoints(), "bi-extended linestring has same point count"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(ce01e.curveLength(), preLocalFraction * lsA.points[0].distance(lsA.points[1]) + lsA.curveLength() + postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "bi-extended linestring has expected length"); + ck.testCoordinate( + ce01e.curveLength(), + preLocalFraction * lsA.points[0].distance(lsA.points[1]) + lsA.curveLength() + + postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), + "bi-extended linestring has expected length", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, ce01e, delta.x, delta.y += yInc); } if (ck.testPointer(c01e) && expectValidResults) { ck.testExactNumber(c01e.numPoints(), lsA.numPoints(), "post-extended linestring has same point count"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(c01e.curveLength(), lsA.curveLength() + postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "post-extended linestring has expected length"); + ck.testCoordinate( + c01e.curveLength(), + lsA.curveLength() + postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), + "post-extended linestring has expected length", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, c01e, delta.x, delta.y += yInc); } if (ck.testPointer(c1e) && expectValidResults) { ck.testExactNumber(c1e.numPoints(), 2, "post-extension is a segment"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(c1e.curveLength(), postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "post-extension length is fraction of last segment"); + ck.testCoordinate( + c1e.curveLength(), + postLocalFraction * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), + "post-extension length is fraction of last segment", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, c1e, delta.x, delta.y += yInc); } if (ck.testPointer(c1ee) && expectValidResults) { ck.testExactNumber(c1ee.numPoints(), 2, "isolated post-extension is a segment"); if (!lsA.isPhysicallyClosed) - ck.testCoordinate(c1ee.curveLength(), postLocalFractionHalf * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), "isolated post-extension length is fraction of last segment"); + ck.testCoordinate( + c1ee.curveLength(), + postLocalFractionHalf * lsA.points[lsA.numPoints() - 2].distance(lsA.points[lsA.numPoints() - 1]), + "isolated post-extension length is fraction of last segment", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, c1ee, delta.x, delta.y += yInc); } } @@ -101,8 +130,7 @@ function exerciseClonePartialLineString3d(ck: Checker, allGeometry: GeometryQuer function exerciseLineString3d(ck: Checker, lsA: LineString3d) { const expectValidResults = lsA.numPoints() > 1; const a = 4.2; - const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), - Matrix3d.createScale(a, a, a)); + const scaleTransform = Transform.createFixedPointAndMatrix(Point3d.create(4, 3), Matrix3d.createScale(a, a, a)); const lsB = lsA.clone(); lsB.reverseInPlace(); const lsC = lsA.clone(); @@ -127,7 +155,7 @@ function exerciseLineString3d(ck: Checker, lsA: LineString3d) { const splitFraction = 0.4203; const partA = lsA.clonePartialCurve(0.0, splitFraction); - const partB = lsA.clonePartialCurve(1.0, splitFraction); // reversed to exercise more code. But length is absolute so it will add. + const partB = lsA.clonePartialCurve(1.0, splitFraction); // reversed to exercise more code. But length is absolute so it will add. if (ck.testPointer(partA, "forward partial") && ck.testPointer(partB, "backward partial")) ck.testCoordinate(lsA.curveLength(), partA.curveLength() + partB.curveLength(), "Partial curves sum to length", lsA, partA, partB); } @@ -225,9 +253,17 @@ describe("LineString3d", () => { ck.testLT(detail0.fraction, 1, "Point projected off curve start has projection fraction < 0"); ck.testLT(1, detail1.fraction, "Point projected off curve end has projection fraction > 1"); ck.testPoint3d(detail0.point, ls0.startPoint(), "Point projected off curve start equals start of clonedPartialCurve at projection fraction < 0"); - ck.testPoint3d(detail0.point, ls.fractionToPoint(detail0.fraction), "Point projected off curve start equals fractionToPoint at projection fraction < 0"); + ck.testPoint3d( + detail0.point, + ls.fractionToPoint(detail0.fraction), + "Point projected off curve start equals fractionToPoint at projection fraction < 0", + ); ck.testPoint3d(detail1.point, ls1.endPoint(), "Point projected off curve end equals end of clonedPartialCurve at projection fraction > 1"); - ck.testPoint3d(detail1.point, ls.fractionToPoint(detail1.fraction), "Point projected off curve end equals fractionToPoint at projection fraction > 1"); + ck.testPoint3d( + detail1.point, + ls.fractionToPoint(detail1.fraction), + "Point projected off curve end equals fractionToPoint at projection fraction > 1", + ); GeometryCoreTestIO.saveGeometry(allGeometry, "LineString3d", "ClonePartialFromExtendedClosestPointDetailFraction"); expect(ck.getNumErrors()).toBe(0); @@ -305,10 +341,9 @@ describe("LineString3d", () => { const clipper = ClipPlane.createEdgeXY(Point3d.create(2, 0, 0), Point3d.create(0, 5, 0))!; // The linestring starts in, goes out, and comes back. Verify 2 segments announced. let numAnnounce = 0; - ls.announceClipIntervals(clipper, - (_a0: number, _a1: number, _cp: CurvePrimitive) => { - numAnnounce++; - }); + ls.announceClipIntervals(clipper, (_a0: number, _a1: number, _cp: CurvePrimitive) => { + numAnnounce++; + }); ck.testExactNumber(numAnnounce, 2); expect(ck.getNumErrors()).toBe(0); }); @@ -323,7 +358,7 @@ describe("LineString3d", () => { ]); const rotation = Matrix3d.createRotationAroundVector(Vector3d.create(1, 1, 1), Angle.createDegrees(31)); const transform = Transform.createOriginAndMatrix(ls.startPoint(), rotation); - ls.tryTransformInPlace(transform); // make things interesting + ls.tryTransformInPlace(transform); // make things interesting GeometryCoreTestIO.captureCloneGeometry(allGeometry, ls); // With a change in concavity before and after the segment AND fraction 0.5, we used to return identity incorrectly @@ -397,7 +432,9 @@ class IterableLineStringPoint3dIterator implements Iterator { return { done: false, value: point }; return { done: true, value: undefined } as any as IteratorResult; } - public [Symbol.iterator](): IterableIterator { return this; } + public [Symbol.iterator](): IterableIterator { + return this; + } } /** * This is a linestring class which @@ -415,7 +452,9 @@ class LineStringWithIterator { this._data[i++] = p.z; } } - public [Symbol.iterator](): IterableIterator { return new IterableLineStringPoint3dIterator(this); } + public [Symbol.iterator](): IterableIterator { + return new IterableLineStringPoint3dIterator(this); + } /** * access a point by index. The point coordinates are returned as a first class point object. * @param index index of point to access @@ -428,7 +467,6 @@ class LineStringWithIterator { } } describe("LineStringIterator", () => { - it("HelloWorld", () => { const ck = new Checker(); const allPoints: Point3d[] = [ @@ -437,7 +475,8 @@ describe("LineStringIterator", () => { Point3d.create(10, 10, 0), Point3d.create(10, 0, 0), Point3d.create(20, 0, 0), - Point3d.create(20, 10, 0)]; + Point3d.create(20, 10, 0), + ]; const ls = new LineStringWithIterator(allPoints); let i = 0; for (const p of ls) { @@ -447,7 +486,6 @@ describe("LineStringIterator", () => { } expect(ck.getNumErrors()).toBe(0); }); - }); describe("LineStringAnnotation", () => { @@ -489,9 +527,9 @@ describe("LineStringAnnotation", () => { ls0.appendStrokePoint(p0, 0.0); ls0.appendStrokePoint(p1, 1.0); ck.testExactNumber(2, ls0.numPoints()); - ls0.appendStrokePoint(p1, 1.0); // this is a duplicate + ls0.appendStrokePoint(p1, 1.0); // this is a duplicate ck.testExactNumber(2, ls0.numPoints()); - ls0.appendStrokePoint(p1, 0.0); // this is xyz dup but fraction different + ls0.appendStrokePoint(p1, 0.0); // this is xyz dup but fraction different ck.testExactNumber(2, ls0.numPoints()); const line = LineSegment3d.createXYZXYZ(1, 2, 3, 2, 5, 1); @@ -552,7 +590,8 @@ describe("LineStringAnnotation", () => { Point3d.create(10, 10, 0), Point3d.create(10, 0, 0), Point3d.create(20, 0, 0), - Point3d.create(20, 10, 0)]; + Point3d.create(20, 10, 0), + ]; const ls = LineString3d.create(allPoints); const normalIndices = ls.ensureEmptyNormalIndices(); @@ -632,9 +671,21 @@ describe("LineStringAnnotation", () => { ck.testRange3d(partialSegment.range(), segment.rangeBetweenFractions(f0, f1), { title: "segment rangeBetweenFractions", f0, f1 }); ck.testRange3d(partialString.range(), linestring.rangeBetweenFractions(f0, f1), { title: "Linestring rangeBetweenFractions", f0, f1 }); ck.testRange3d(partialSegment.range(), partialString.range(), { title: "partial linestring, partial segment range", f0, f1 }); - ck.testCoordinate(partialSegment.curveLength(), segment.curveLengthBetweenFractions(f0, f1), { title: "segment length between fractions", f0, f1 }); - ck.testCoordinate(partialString.curveLength(), linestring.curveLengthBetweenFractions(f0, f1), { title: "linestring length between fractions", f0, f1 }); - ck.testCoordinate(partialSegment.curveLength(), partialString.curveLength(), { title: "partial linestring, partial segment length", f0, f1 }); + ck.testCoordinate(partialSegment.curveLength(), segment.curveLengthBetweenFractions(f0, f1), { + title: "segment length between fractions", + f0, + f1, + }); + ck.testCoordinate(partialString.curveLength(), linestring.curveLengthBetweenFractions(f0, f1), { + title: "linestring length between fractions", + f0, + f1, + }); + ck.testCoordinate(partialSegment.curveLength(), partialString.curveLength(), { + title: "partial linestring, partial segment length", + f0, + f1, + }); } } } @@ -651,7 +702,9 @@ describe("LineString3dOps", () => { const fragments: AnyCurve[] = []; if (includeDangler) fragments.push(LineSegment3d.create(Point3d.create(4, 4, 0), Point3d.create(3, 2, 0))); - fragments.push(Arc3d.create(Point3d.create(1, 0, 0), Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), AngleSweep.createStartEndDegrees(0, 180))); + fragments.push( + Arc3d.create(Point3d.create(1, 0, 0), Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), AngleSweep.createStartEndDegrees(0, 180)), + ); fragments.push(LineString3d.create(Point3d.createZero(), Point3d.create(0, 2, 0), Point3d.create(3, 2, 0))); fragments.push(LineSegment3d.create(Point3d.create(2, 0, 0), Point3d.create(3, 0, 0))); fragments.push(LineSegment3d.create(Point3d.create(3, 2, 0), Point3d.create(3, 0, 0))); diff --git a/core/geometry/src/test/curve/RegionBoolean.test.ts b/core/geometry/src/test/curve/RegionBoolean.test.ts index 4f1917e4aba2..e3b2596e9517 100644 --- a/core/geometry/src/test/curve/RegionBoolean.test.ts +++ b/core/geometry/src/test/curve/RegionBoolean.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BSplineCurve3d } from "../../bspline/BSplineCurve"; import { InterpolationCurve3d, InterpolationCurve3dOptions } from "../../bspline/InterpolationCurve3d"; import { Arc3d } from "../../curve/Arc3d"; @@ -59,15 +59,17 @@ describe("RegionBoolean", () => { candidates.push(Arc3d.createCircularStartMiddleEnd(Point3d.create(0.1, -0.1), Point3d.create(0.5, 0.6), Point3d.create(1.1, 0.8))); for (const c of candidates) GeometryCoreTestIO.consoleLog(" geometry: ", IModelJson.Writer.toIModelJson(c)); - const linestringStartY = 0.5; // making this 0.5 creates partial overlap -- problem? - for (const stepData of [ - { geometry: LineSegment3d.createXYXY(0, 0.5, 1, 0.5), expectedFaces: 3 }, - { geometry: LineSegment3d.createXYXY(0.8, -0.1, 1.1, 0.2), expectedFaces: 4 }, - { geometry: LineSegment3d.createXYXY(0.5, 0, 0.4, -0.2), expectedFaces: 4 }, - { geometry: LineSegment3d.createXYXY(0.4, 0.0, 0.4, -0.2), expectedFaces: 5 }, - { geometry: LineSegment3d.createXYXY(0.4, 0.0, 1.6, 1), expectedFaces: 6 }, - { geometry: LineString3d.create([0, linestringStartY], [0.2, 0.5], [0.8, 0.3], [1.2, 0.4]), expectedFaces: -1, expectedIntersections: -1 }, - ]) { + const linestringStartY = 0.5; // making this 0.5 creates partial overlap -- problem? + for ( + const stepData of [ + { geometry: LineSegment3d.createXYXY(0, 0.5, 1, 0.5), expectedFaces: 3 }, + { geometry: LineSegment3d.createXYXY(0.8, -0.1, 1.1, 0.2), expectedFaces: 4 }, + { geometry: LineSegment3d.createXYXY(0.5, 0, 0.4, -0.2), expectedFaces: 4 }, + { geometry: LineSegment3d.createXYXY(0.4, 0.0, 0.4, -0.2), expectedFaces: 5 }, + { geometry: LineSegment3d.createXYXY(0.4, 0.0, 1.6, 1), expectedFaces: 6 }, + { geometry: LineString3d.create([0, linestringStartY], [0.2, 0.5], [0.8, 0.3], [1.2, 0.4]), expectedFaces: -1, expectedIntersections: -1 }, + ] + ) { candidates.push(stepData.geometry); GeometryCoreTestIO.consoleLog(" add geometry: ", IModelJson.Writer.toIModelJson(stepData.geometry)); for (const c of candidates) @@ -76,7 +78,11 @@ describe("RegionBoolean", () => { y0 += 0.75; saveShiftedLoops(allGeometry, loops, x0, y0, 1.0); if (stepData.expectedFaces >= 0 && loops.length === 1) - ck.testExactNumber(stepData.expectedFaces, loops[0].positiveAreaLoops.length + loops[0].negativeAreaLoops.length + loops[0].slivers.length, "Face loop count"); + ck.testExactNumber( + stepData.expectedFaces, + loops[0].positiveAreaLoops.length + loops[0].negativeAreaLoops.length + loops[0].slivers.length, + "Face loop count", + ); x0 += 5.0; y0 = 0.0; } @@ -136,8 +142,10 @@ describe("RegionBoolean", () => { const c = 1.0; const c1 = 2.5; for (const degrees of [0, 180, 0.012123389324234, 42.123213]) { - const transform = Transform.createFixedPointAndMatrix(Point3d.create(0, 0, 0), - Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); x0 = 0.0; for (const ab of [0.6 /* , 1.1, 3.1 */]) { for (const numCut of [1, 4, 7, 9]) { @@ -147,7 +155,8 @@ describe("RegionBoolean", () => { Point3d.create(xMax, 0), Point3d.create(xMax, 2), Point3d.create(0, 2), - Point3d.create(0, 0)])); + Point3d.create(0, 0), + ])); const a0 = 0.5; const b0 = a0 + ab; @@ -177,8 +186,10 @@ describe("RegionBoolean", () => { const dy = 3.0; saveShiftedLoops(allGeometry, loops, x0, y0 + dy, dy); const stepData = { rotateDegrees: degrees, numCutout: numCut, cutoutStep: ab }; - if (!ck.testExactNumber(1, loops.length, stepData) - || !ck.testExactNumber(1, loops[0].negativeAreaLoops.length, stepData)) { + if ( + !ck.testExactNumber(1, loops.length, stepData) + || !ck.testExactNumber(1, loops[0].negativeAreaLoops.length, stepData) + ) { saveShiftedLoops(badGeometry, loops, x0, y0 + dy, dy); } @@ -192,7 +203,6 @@ describe("RegionBoolean", () => { GeometryCoreTestIO.saveGeometry(badGeometry, "RegionBoolean", "Overlaps.BAD"); GeometryCoreTestIO.saveGeometry(allGeometry, "RegionBoolean", "Overlaps"); expect(ck.getNumErrors()).toBe(0); - }); it("ParityRegionWithCoincidentEdges", () => { const ck = new Checker(); @@ -205,8 +215,7 @@ describe("RegionBoolean", () => { const b0 = 4 - q; const b1 = 8 + q; for (const q1 of [0, -1, 1]) { - const pointArrayA = [[8, +q1], [4, 0], [a0, a0], [0, 4], [0, 8], [a0, 12], - [4, 11], [8, 11], [a1, 12], [12, 8], [12, 4], [a1, a0], [8, 0]]; + const pointArrayA = [[8, +q1], [4, 0], [a0, a0], [0, 4], [0, 8], [a0, 12], [4, 11], [8, 11], [a1, 12], [12, 8], [12, 4], [a1, a0], [8, 0]]; const pointArrayB = [[8, 0], [4, 0], [b0, 4], [4, 8], [8, 8], [b1, 4], [8, 0]]; // loopB.reverseChildrenInPlace(); runRegionTest(allGeometry, pointArrayA, pointArrayB, xBase, yBase); @@ -241,11 +250,12 @@ describe("RegionBoolean", () => { let z0 = props.z0 ?? 0; const delta = props.delta ?? 0; - if (Array.isArray(curvesAndRegions)) + if (Array.isArray(curvesAndRegions)) { for (const geom of curvesAndRegions) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, geom, x0, y0, z0); y0 += delta; } + } else GeometryCoreTestIO.captureCloneGeometry(allGeometry, curvesAndRegions, x0, y0, z0); @@ -416,8 +426,7 @@ describe("RegionBoolean", () => { const b1 = 8 + q; const q1 = q1q2[0]; const q2 = q1q2[1]; - const pointArrayA = [[8, 0], [4, 0], [a0, a0], [0, 4], [0, 8], [a0, 12], - [4, 11], [8, 11], [a1, 12], [12, 8], [12, 4], [a1, a0], [8, 0]]; + const pointArrayA = [[8, 0], [4, 0], [a0, a0], [0, 4], [0, 8], [a0, 12], [4, 11], [8, 11], [a1, 12], [12, 8], [12, 4], [a1, a0], [8, 0]]; const pointArrayB = [[8, q2], [4, q1], [b0, 4], [4, 7], [8, 7], [b1, 4], [8, q2]]; for (const data of [pointArrayA, pointArrayB]) { for (const xy of data) { @@ -450,7 +459,7 @@ describe("RegionBoolean", () => { allLines.push(LineString3d.create([[0, 0], [ax, ay1], [ax, ay2], [0, ay1]])); for (const fraction of [0.0, 0.25, 0.5, 0.9]) { const x = fraction * ax; - const y = fraction * ay1; // "on" the lower line + const y = fraction * ay1; // "on" the lower line allLines.push(LineSegment3d.createXYXY(x, y - by, x, y + dy + by)); } { @@ -463,8 +472,7 @@ describe("RegionBoolean", () => { { // repeat with a mirrored set of polygons const n = allLines.length; - const transform = Transform.createFixedPointAndMatrix(Point3d.create(ax1, 0, 0), - Matrix3d.createScale(-1, 1.4, 1)); + const transform = Transform.createFixedPointAndMatrix(Point3d.create(ax1, 0, 0), Matrix3d.createScale(-1, 1.4, 1)); for (let i = 0; i < n; i++) allLines.push(allLines[i].cloneTransformed(transform) as CurvePrimitive); @@ -503,7 +511,6 @@ describe("RegionBoolean", () => { } } } - } GeometryCoreTestIO.captureCloneGeometry(allGeometry, section, x0, y0); const regions = RegionOps.constructAllXYRegionLoops(section as AnyRegion[]); @@ -570,7 +577,7 @@ describe("RegionBoolean", () => { } if (numOverlap > 0) GeometryCoreTestIO.consoleLog({ numOverlap, i, j }); - if (shortestPair && numPoint === 0) + if (shortestPair && numPoint === 0) { for (const p of pairs) { if (p.detailA.point.isAlmostEqual(p.detailB.point)) { } else { @@ -582,6 +589,7 @@ describe("RegionBoolean", () => { } } } + } } } x0 += 100.0; @@ -624,21 +632,19 @@ describe("RegionBoolean", () => { it("NearTangencyUnion", () => { testSelectedTangencySubsets(true, 0, [-1], [], "Base"); - testSelectedTangencySubsets(false, 0, [], - [ - [0, 13], - [7, 20], - [8, 21], - ], "ArcSubsetsA"); - testSelectedTangencySubsets(false, 0, [], - [ - [11, 12], - [12, 13], - [11, 13], - [11, 15], - [11, 16], - [11, 17], - ], "ArcSubsets"); + testSelectedTangencySubsets(false, 0, [], [ + [0, 13], + [7, 20], + [8, 21], + ], "ArcSubsetsA"); + testSelectedTangencySubsets(false, 0, [], [ + [11, 12], + [12, 13], + [11, 13], + [11, 15], + [11, 16], + [11, 17], + ], "ArcSubsets"); const allShuffles = []; const n = 13; for (let i0 = 0; i0 < n; i0 += 1) { @@ -691,22 +697,24 @@ describe("RegionBoolean", () => { { jsonFilePath: "./src/test/data/curve/laurynasLoopsSimplified.imjs", expectedNumComponents: 1 }, { jsonFilePath: "./src/test/data/curve/laurynasLoopsSimplified.imjs", expectedNumComponents: 1, tolerance: 0.0001 }, { jsonFilePath: "./src/test/data/curve/laurynasLoopsInRectangle.imjs", expectedNumComponents: 1 }, - { jsonFilePath: "./src/test/data/curve/laurynasLoopsWithDanglers.imjs", expectedNumComponents: 1 }, // has doglegs of length 0.0001 + { jsonFilePath: "./src/test/data/curve/laurynasLoopsWithDanglers.imjs", expectedNumComponents: 1 }, // has doglegs of length 0.0001 { jsonFilePath: "./src/test/data/curve/laurynasLoopsWithoutDanglers.imjs", expectedNumComponents: 1 }, - { jsonFilePath: "./src/test/data/curve/michelParityRegion.imjs", expectedNumComponents: 2 }, // has a small island in a hole! + { jsonFilePath: "./src/test/data/curve/michelParityRegion.imjs", expectedNumComponents: 2 }, // has a small island in a hole! { jsonFilePath: "./src/test/data/curve/laurynasCircularHole.imjs", expectedNumComponents: 1 }, - { jsonFilePath: "./src/test/data/curve/laurynasCircularHole2.imjs", expectedNumComponents: 4, skipBoolean: true }, // without merge, 4 separate loops + { jsonFilePath: "./src/test/data/curve/laurynasCircularHole2.imjs", expectedNumComponents: 4, skipBoolean: true }, // without merge, 4 separate loops { jsonFilePath: "./src/test/data/curve/dovydasLoops.imjs", expectedNumComponents: 1 }, // union makes bridges to three holes along the bridge ray ]; if (GeometryCoreTestIO.enableLongTests) { - testCases.push({ jsonFilePath: "./src/test/data/curve/michelLoops2.imjs", expectedNumComponents: 206 }); // 2 minutes + testCases.push({ jsonFilePath: "./src/test/data/curve/michelLoops2.imjs", expectedNumComponents: 206 }); // 2 minutes testCases.push({ jsonFilePath: "./src/test/data/curve/michelLoops2.imjs", expectedNumComponents: 338, skipBoolean: true }); // 10 seconds } for (const testCase of testCases) { const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync(testCase.jsonFilePath, "utf8"))) as Loop[]; if (ck.testDefined(inputs, "inputs successfully parsed")) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, inputs, x0, y0); - const range: Range3d = Range3d.createFromVariantData(inputs.map((loop: Loop) => { return [loop.range().low, loop.range().high]; })); + const range: Range3d = Range3d.createFromVariantData(inputs.map((loop: Loop) => { + return [loop.range().low, loop.range().high]; + })); xDelta = 1.5 * range.xLength(); yDelta = 1.5 * range.yLength(); let merged: Loop[] | AnyRegion | undefined = inputs; @@ -720,7 +728,11 @@ describe("RegionBoolean", () => { } if (merged) { const signedLoops = RegionOps.constructAllXYRegionLoops(merged); - ck.testExactNumber(testCase.expectedNumComponents, signedLoops.length, `UnionRegion has expected number of connected components: ${testCase.jsonFilePath}`); + ck.testExactNumber( + testCase.expectedNumComponents, + signedLoops.length, + `UnionRegion has expected number of connected components: ${testCase.jsonFilePath}`, + ); x0 += xDelta; for (const signedLoop of signedLoops) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, signedLoop.negativeAreaLoops, x0, y0); @@ -767,7 +779,7 @@ describe("RegionBoolean", () => { { sweepStartA: 0, sweepEndA: 90, sweepStartB: 90, sweepEndB: 360, reverseB: false, numLoop: 1, numOverlap: 0 }, { sweepStartA: 0, sweepEndA: 90, sweepStartB: 0, sweepEndB: -270, reverseB: false, numLoop: 1, numOverlap: 0 }, { sweepStartA: 90, sweepEndA: 0, sweepStartB: 0, sweepEndB: -270, reverseB: false, numLoop: 1, numOverlap: 0 }, - { sweepStartA: 180, sweepEndA: 0, sweepStartB: 0, sweepEndB: 180, reverseB: true, numLoop: 1, numOverlap: 0 }, // Laurynas' original 2-arc circle + { sweepStartA: 180, sweepEndA: 0, sweepStartB: 0, sweepEndB: 180, reverseB: true, numLoop: 1, numOverlap: 0 }, // Laurynas' original 2-arc circle { sweepStartA: 190, sweepEndA: -10, sweepStartB: 0, sweepEndB: 180, reverseB: true, numLoop: 1, numOverlap: 2 }, { sweepStartA: 180, sweepEndA: 0, sweepStartB: -10, sweepEndB: 190, reverseB: true, numLoop: 1, numOverlap: 2 }, { sweepStartA: 190, sweepEndA: 0, sweepStartB: 0, sweepEndB: 180, reverseB: true, numLoop: 1, numOverlap: 1 }, @@ -830,8 +842,8 @@ describe("PlaneAltitudeRangeContext", () => { const lsLoop = Loop.create(linestring); let lowHigh: Range1d | undefined; interface RayParam { - ray: Vector3d | Ray3d; // defines 0-altitude plane - param: number; // expected fractional projection parameter (for xy-plane geometry) + ray: Vector3d | Ray3d; // defines 0-altitude plane + param: number; // expected fractional projection parameter (for xy-plane geometry) } const rayParams: RayParam[] = [ { ray: Vector3d.unitZ(), param: 0.0 }, @@ -857,7 +869,10 @@ describe("PlaneAltitudeRangeContext", () => { const zero = Vector3d.createZero(); ck.testUndefined(lsLoop.projectedParameterRange(zero), "CurveCollection projection range is undefined for undefined plane"); ck.testUndefined(linestring.projectedParameterRange(zero), "CurvePrimitive projection range is undefined for undefined plane"); - ck.testUndefined(PlaneAltitudeRangeContext.findExtremeFractionsAlongDirection(linestring.points, zero), "points projection range is undefined for undefined plane"); + ck.testUndefined( + PlaneAltitudeRangeContext.findExtremeFractionsAlongDirection(linestring.points, zero), + "points projection range is undefined for undefined plane", + ); expect(ck.getNumErrors()).toBe(0); }); @@ -891,9 +906,15 @@ describe("PlaneAltitudeRangeContext", () => { { geom: fitCurveLoop, ray: xyRay, minParam: -2.7265388486929107, maxParam: 4.6879835021011536, label: "fitCurveLoop" }, { geom: bCurve!, ray: xyRay, minParam: -1.3355667912298879, maxParam: 3.4568871347895316, label: "bCurve" }, { geom: bCurveLoop, ray: xyRay, minParam: -3.5945409474105596, maxParam: 3.5804340252875075, label: "bCurveLoop" }, - { geom: lsLoop, ray: xyRay, minParam: - 1.5 * Math.sqrt(2), maxParam: 3 * Math.sqrt(2), label: "rectangle" }, + { geom: lsLoop, ray: xyRay, minParam: -1.5 * Math.sqrt(2), maxParam: 3 * Math.sqrt(2), label: "rectangle" }, { geom: circle, ray: xyRay, minParam: -1, maxParam: 1, label: "circle-xy" }, - { geom: circle, ray: Ray3d.create(Point3d.create(2, 0), minusDiag), minParam: Math.sqrt(2) - 1, maxParam: Math.sqrt(2) + 1, label: "circle-xy2" }, + { + geom: circle, + ray: Ray3d.create(Point3d.create(2, 0), minusDiag), + minParam: Math.sqrt(2) - 1, + maxParam: Math.sqrt(2) + 1, + label: "circle-xy2", + }, { geom: circle, ray: Ray3d.create(Point3d.create(1, -1), minusDiag), minParam: -1, maxParam: 1, label: "circle-xy3" }, { geom: circle, ray: Ray3d.create(Point3d.create(0.5, -0.5), minusDiag), minParam: -1, maxParam: 1, label: "circle-xy4" }, { geom: circle, ray: Ray3d.create(Point3d.createZero(), Vector3d.unitY()), minParam: -1, maxParam: 1, label: "circle-y" }, @@ -923,10 +944,13 @@ function testSelectedTangencySubsets( linestringSimplification: number | number[], arcSimplificationIndices: number[], arcCyclicIndexRanges: number[][], // POSITIVE indices for (k = first; k < last; k++) loop. Will be modulo'ed into range for access - outputFileSuffix: string) { + outputFileSuffix: string, +) { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/data/curve/areaBoolean/AreaBoolean.716145.Inputs.imjs", "utf8"))) as AnyRegion[]; + const inputs = IModelJson.Reader.parse( + JSON.parse(fs.readFileSync("./src/test/data/curve/areaBoolean/AreaBoolean.716145.Inputs.imjs", "utf8")), + ) as AnyRegion[]; // const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/data/curve/areaBoolean/AreaBoolean.716145.RemoveShortSegment.imjs", "utf8"))) as AnyRegion[]; let x0 = 0; let y0 = 0; @@ -1021,16 +1045,22 @@ function testSelectedTangencySubsets( } /** -* -* @param allGeometry array to receive (cloned) geometry -* @param components geometry to output -* @param x0 x shift for positive area loops -* @param y0 y shift for positive area loops -* @param dy additional y shift for (1 step) negative loops, (2 steps) non-loop geometry, (3 step) inward offsets of positive area geometry. -* @param y1 y shift for negative loops and stray geometry -*/ -function saveShiftedLoops(allGeometry: GeometryQuery[], components: SignedLoops | SignedLoops[], x0: number, y0: number, dy: number, positiveLoopOffset: number = 0.02, - doTriangulation: boolean = true) { + * @param allGeometry array to receive (cloned) geometry + * @param components geometry to output + * @param x0 x shift for positive area loops + * @param y0 y shift for positive area loops + * @param dy additional y shift for (1 step) negative loops, (2 steps) non-loop geometry, (3 step) inward offsets of positive area geometry. + * @param y1 y shift for negative loops and stray geometry + */ +function saveShiftedLoops( + allGeometry: GeometryQuery[], + components: SignedLoops | SignedLoops[], + x0: number, + y0: number, + dy: number, + positiveLoopOffset: number = 0.02, + doTriangulation: boolean = true, +) { if (Array.isArray(components)) { const allNegativeAreaLoops: Loop[] = []; for (const member of components) { @@ -1068,7 +1098,7 @@ function saveShiftedLoops(allGeometry: GeometryQuery[], components: SignedLoops GeometryCoreTestIO.captureCloneGeometry(allGeometry, components.slivers, x0, y0 + 4 * dy); if (positiveLoopOffset !== 0.0) { const yy = y0 + dy; - const zz = 0.01; // raise the tic marks above the faces + const zz = 0.01; // raise the tic marks above the faces for (const loop of components.positiveAreaLoops) { const offsetLoop = RegionOps.constructCurveXYOffset(loop, positiveLoopOffset); GeometryCoreTestIO.captureCloneGeometry(allGeometry, offsetLoop, x0, yy); @@ -1078,17 +1108,22 @@ function saveShiftedLoops(allGeometry: GeometryQuery[], components: SignedLoops if (curve) { const curveLength = curve.quickLength(); let ticMultiplier = 3.0; - if (loop !== undefined + if ( + loop !== undefined && (loop as any).computedAreaInPlanarSubdivision !== undefined - && (loop as any).computedAreaInPlanarSubdivision < 0.0) + && (loop as any).computedAreaInPlanarSubdivision < 0.0 + ) ticMultiplier = 6.0; const ticLength = Math.min(0.2 * curveLength, ticMultiplier * positiveLoopOffset); const tangentRayAtTicMark = curve.fractionToPointAndUnitTangent(fraction); const midPoint = curve.fractionToPoint(0.5); const perp = tangentRayAtTicMark.direction.unitPerpendicularXY(); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, [midPoint, tangentRayAtTicMark.origin, tangentRayAtTicMark.origin.plusScaled(perp, ticLength)], - x0, yy, zz, + x0, + yy, + zz, ); } }; @@ -1144,10 +1179,15 @@ function runRegionTest(allGeometry: GeometryQuery[], pointArrayA: number[][], po (name: string, graph: HalfEdgeGraph, _properties: string, _extraData?: any) => { GraphChecker.captureAnnotatedGraph(allGeometry, graph, x0, y1 += 15); const euler = graph.countVertexLoops() - graph.countNodes() / 2.0 + graph.countFaceLoops(); - GeometryCoreTestIO.consoleLog(` Checkpoint ${name}.${_properties}`, - { v: graph.countVertexLoops(), e: graph.countNodes(), f: graph.countFaceLoops(), eulerCharacteristic: euler }); + GeometryCoreTestIO.consoleLog(` Checkpoint ${name}.${_properties}`, { + v: graph.countVertexLoops(), + e: graph.countNodes(), + f: graph.countFaceLoops(), + eulerCharacteristic: euler, + }); GraphChecker.dumpGraph(graph); - }); + }, + ); } const unionRegion = RegionOps.polygonXYAreaUnionLoopsToPolyface(pointArrayA, pointArrayB); RegionOps.setCheckPointFunction(); @@ -1246,15 +1286,19 @@ describe("GeneralSweepBooleans", () => { const rectangle1B = Loop.create(LineString3d.create(Sample.createRectangle(-2, -2, 8, 7, 0, true))); const rectangle2 = Loop.create(LineString3d.create(Sample.createRectangle(1, 1, 6, 2, 0, true))); const area3 = Loop.create( - LineSegment3d.createXYXY(2, 1.5, 5, 2.5), LineSegment3d.createXYXY(5, 2.5, 5, 3), + LineSegment3d.createXYXY(2, 1.5, 5, 2.5), + LineSegment3d.createXYXY(5, 2.5, 5, 3), Arc3d.createCircularStartMiddleEnd(Point3d.create(5, 3, 0), Point3d.create(4, 4, 0), Point3d.create(2, 3, 0)), - LineSegment3d.createXYXY(2, 3, 2, 1.5)); + LineSegment3d.createXYXY(2, 3, 2, 1.5), + ); const area4 = Loop.create( LineSegment3d.createXYXY(-1, -1, -1, 9), - Arc3d.createCircularStartMiddleEnd(Point3d.create(-1, 9), Point3d.create(4, 4, 0), Point3d.create(-1, -1))); + Arc3d.createCircularStartMiddleEnd(Point3d.create(-1, 9), Point3d.create(4, 4, 0), Point3d.create(-1, -1)), + ); const area5 = Loop.create( LineSegment3d.createXYXY(-1, 1, -1, 6), - Arc3d.createCircularStartMiddleEnd(Point3d.create(-1, 6), Point3d.create(1, 3.5), Point3d.create(-1, 1))); + Arc3d.createCircularStartMiddleEnd(Point3d.create(-1, 6), Point3d.create(1, 3.5), Point3d.create(-1, 1)), + ); const xStep = 20.0; let y0 = 0; for (const rectangle1 of [rectangle1B, rectangle1A, rectangle1B]) { @@ -1273,8 +1317,58 @@ describe("GeneralSweepBooleans", () => { it("HighParityRectangles", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const outerLoop = [[0, 0, 1], [0, 4, 1], [0, 4, 1], [0, 8, 1], [0, 8, 1], [0, 12, 1], [0, 12, 1], [0, 16, 1], [0, 16, 1], [0, 20, 1], [0, 20, 1], [0, 24, 1], [0, 24, 1], [4, 24, 1], [4, 24, 1], [4, 20, 1], [4, 20, 1], [4, 16, 1], [4, 16, 1], [4, 12, 1], [4, 12, 1], [4, 8, 1], [4, 8, 1], [4, 4, 1], [4, 4, 1], [4, 0, 1], [4, 0, 1], [0, 0, 1]]; - const inner1 = [[0, 4, 1], [4, 4, 1], [4, 4, 1], [4, 8, 1], [4, 8, 1], [4, 12, 1], [4, 12, 1], [4, 16, 1], [4, 16, 1], [4, 20, 1], [4, 20, 1], [0, 20, 1], [0, 20, 1], [0, 16, 1], [0, 16, 1], [0, 12, 1], [0, 12, 1], [0, 8, 1], [0, 8, 1], [0, 4, 1]]; + const outerLoop = [ + [0, 0, 1], + [0, 4, 1], + [0, 4, 1], + [0, 8, 1], + [0, 8, 1], + [0, 12, 1], + [0, 12, 1], + [0, 16, 1], + [0, 16, 1], + [0, 20, 1], + [0, 20, 1], + [0, 24, 1], + [0, 24, 1], + [4, 24, 1], + [4, 24, 1], + [4, 20, 1], + [4, 20, 1], + [4, 16, 1], + [4, 16, 1], + [4, 12, 1], + [4, 12, 1], + [4, 8, 1], + [4, 8, 1], + [4, 4, 1], + [4, 4, 1], + [4, 0, 1], + [4, 0, 1], + [0, 0, 1], + ]; + const inner1 = [ + [0, 4, 1], + [4, 4, 1], + [4, 4, 1], + [4, 8, 1], + [4, 8, 1], + [4, 12, 1], + [4, 12, 1], + [4, 16, 1], + [4, 16, 1], + [4, 20, 1], + [4, 20, 1], + [0, 20, 1], + [0, 20, 1], + [0, 16, 1], + [0, 16, 1], + [0, 12, 1], + [0, 12, 1], + [0, 8, 1], + [0, 8, 1], + [0, 4, 1], + ]; const inner2 = [[0, 8, 1], [4, 8, 1], [4, 8, 1], [4, 12, 1], [4, 12, 1], [0, 12, 1], [0, 12, 1], [0, 8, 1]]; // const inner3 = [[0, 12, 1], [4, 12, 1], [4, 12, 1], [4, 16, 1], [4, 16, 1], [0, 16, 1], [0, 16, 1], [0, 12, 1]]; const inner3 = [[0, 12, 1], [3, 12, 1], [3, 12, 1], [3, 16, 1], [3, 16, 1], [0, 16, 1], [0, 16, 1], [0, 12, 1]]; @@ -1313,9 +1407,13 @@ describe("GeneralSweepBooleans", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const outer = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/outer.imjs", "utf8"))) as AnyRegion[]; + "./src/test/data/intersections/MBContainmentBoolean/outer.imjs", + "utf8", + ))) as AnyRegion[]; const inner = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/inner.imjs", "utf8"))) as AnyRegion[]; + "./src/test/data/intersections/MBContainmentBoolean/inner.imjs", + "utf8", + ))) as AnyRegion[]; let x0 = 0; const dy = 50; // for (const entry of outer) { @@ -1324,7 +1422,7 @@ describe("GeneralSweepBooleans", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, outer, x0, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, inner, x0, 50); const dx = 100.0; - exerciseAreaBooleans(outer, inner, ck, allGeometry, (x0 += dx), -dy, false); + exerciseAreaBooleans(outer, inner, ck, allGeometry, x0 += dx, -dy, false); for (const a of outer) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, a, x0 += 2 * dx, 0); for (const b of inner) { @@ -1436,7 +1534,9 @@ describe("GeneralSweepBooleans", () => { manyRoundedRectangles.push(CurveFactory.createRectangleXY(a, a, a + 4, a + 1.75, 0, 0.5)); } const splitterB0 = CurveFactory.createRectangleXY(0.5, 0.4, 6, 2.1, 0, 0); - const splitterB1 = splitterB0.cloneTransformed(Transform.createFixedPointAndMatrix({ x: 1, y: 2, z: 0 }, Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(40)))) as Loop; + const splitterB1 = splitterB0.cloneTransformed( + Transform.createFixedPointAndMatrix({ x: 1, y: 2, z: 0 }, Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(40))), + ) as Loop; const splitterB = [splitterB0, splitterB1]; const unionB = RegionOps.regionBooleanXY(manyRoundedRectangles, splitterB, RegionBinaryOpType.Union); const intersectionB = RegionOps.regionBooleanXY(manyRoundedRectangles, splitterB, RegionBinaryOpType.Intersection); @@ -1456,8 +1556,8 @@ describe("GeneralSweepBooleans", () => { it("FacetPasting", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const loopA = GrowableXYZArray.create([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]); // Missing closure !!! - const loopB = GrowableXYZArray.create([[1, 0, 0], [2, 0, 0], [2, 1, 0], [1, 1, 0]]); // Missing closure !!! + const loopA = GrowableXYZArray.create([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]]); // Missing closure !!! + const loopB = GrowableXYZArray.create([[1, 0, 0], [2, 0, 0], [2, 1, 0], [1, 1, 0]]); // Missing closure !!! const loop = RegionOps.polygonBooleanXYToLoops([loopA, loopB], RegionBinaryOpType.Union, []); GeometryCoreTestIO.captureCloneGeometry(allGeometry, loopA, 0, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, loopB, 0, 0); @@ -1467,8 +1567,15 @@ describe("GeneralSweepBooleans", () => { }); }); -function exerciseAreaBooleans(dataA: AnyRegion[], dataB: AnyRegion[], - ck: Checker, allGeometry: GeometryQuery[], x0: number, y0Start: number, showVertexNeighborhoods: boolean) { +function exerciseAreaBooleans( + dataA: AnyRegion[], + dataB: AnyRegion[], + ck: Checker, + allGeometry: GeometryQuery[], + x0: number, + y0Start: number, + showVertexNeighborhoods: boolean, +) { const areas = []; const range = RegionOps.curveArrayRange(dataA.concat(dataB)); const yStep = Math.max(15.0, 2.0 * range.yLength()); @@ -1479,7 +1586,9 @@ function exerciseAreaBooleans(dataA: AnyRegion[], dataB: AnyRegion[], const vertexNeighborhoodFunction = (edgeData: VertexNeighborhoodSortData[]) => { GeometryCoreTestIO.consoleLog({ nodeCount: edgeData.length }); for (const data of edgeData) { - GeometryCoreTestIO.consoleLog(` id: ${data.node.id} x: ${data.node.x}, y: ${data.node.y}, theta: ${data.radians}, curvature: ${data.radiusOfCurvature} `); + GeometryCoreTestIO.consoleLog( + ` id: ${data.node.id} x: ${data.node.x}, y: ${data.node.y}, theta: ${data.radians}, curvature: ${data.radiusOfCurvature} `, + ); } }; for (const opType of [RegionBinaryOpType.Union, RegionBinaryOpType.Intersection, RegionBinaryOpType.AMinusB, RegionBinaryOpType.BMinusA]) { @@ -1511,7 +1620,6 @@ function constructEllipseAroundSegment(pointA: Point3d, pointB: Point3d, fractio } class SectionDataParser extends PointStreamXYZHandlerBase { - public allChains: Point3d[][] = []; private _currentChain?: Point3d[]; public override startChain(_chainData: MultiLineStringDataVariant, _isLeaf: boolean): void { @@ -1546,11 +1654,11 @@ class SectionDataParser extends PointStreamXYZHandlerBase { if (Number.isFinite(data.distanceAlong)) { if (Array.isArray(data.elements)) GeometryCoreTestIO.consoleLog({ - distanceAlong: data.distanceAlong, direction: data.direction, + distanceAlong: data.distanceAlong, + direction: data.direction, numElements: data.elements.length, }); this.parseElements(data.elements); - } } } @@ -1563,7 +1671,6 @@ function captureShiftedClones(allGeometry: GeometryQuery[], newGeometry: Geometr y0 += dy; GeometryCoreTestIO.captureCloneGeometry(allGeometry, g, x0, y0); } - } function simplifyLineString(ls: LineString3d, select: number | number[]): LineString3d { if (Array.isArray(select)) { diff --git a/core/geometry/src/test/curve/StrokeOptions.test.ts b/core/geometry/src/test/curve/StrokeOptions.test.ts index 45acc6ce5186..2fdb7524400c 100644 --- a/core/geometry/src/test/curve/StrokeOptions.test.ts +++ b/core/geometry/src/test/curve/StrokeOptions.test.ts @@ -13,7 +13,6 @@ import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; describe("StrokeOptions", () => { - it("HelloWorld", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; diff --git a/core/geometry/src/test/curve/TransitionSpiral3d.test.ts b/core/geometry/src/test/curve/TransitionSpiral3d.test.ts index b49f36a4d671..28409c7e6d28 100644 --- a/core/geometry/src/test/curve/TransitionSpiral3d.test.ts +++ b/core/geometry/src/test/curve/TransitionSpiral3d.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { CurveChainWithDistanceIndex } from "../../curve/CurveChainWithDistanceIndex"; import { CurveCollection } from "../../curve/CurveCollection"; import { CurveFactory } from "../../curve/CurveFactory"; @@ -21,7 +21,11 @@ import { DirectHalfCosineSpiralEvaluator } from "../../curve/spiral/DirectHalfCo import { DirectSpiral3d } from "../../curve/spiral/DirectSpiral3d"; import { IntegratedSpiral3d } from "../../curve/spiral/IntegratedSpiral3d"; import { - NormalizedBiQuadraticTransition, NormalizedBlossTransition, NormalizedClothoidTransition, NormalizedCosineTransition, NormalizedSineTransition, + NormalizedBiQuadraticTransition, + NormalizedBlossTransition, + NormalizedClothoidTransition, + NormalizedCosineTransition, + NormalizedSineTransition, } from "../../curve/spiral/NormalizedTransition"; import { PolishCubicEvaluator } from "../../curve/spiral/PolishCubicSpiralEvaluator"; import { TransitionConditionalProperties } from "../../curve/spiral/TransitionConditionalProperties"; @@ -108,8 +112,18 @@ describe("TransitionSpiral3d", () => { }); it("CreateAndPokeTransitionProperties", () => { const ck = new Checker(); - const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(0, 1), Transform.createIdentity()); - const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(1000, 0), AngleSweep.createStartEndDegrees(10, 3), Segment1d.create(0, 1), Transform.createIdentity()); + const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + ); + const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(1000, 0), + AngleSweep.createStartEndDegrees(10, 3), + Segment1d.create(0, 1), + Transform.createIdentity(), + ); if (ck.testType(spiralA, IntegratedSpiral3d) && ck.testType(spiralB, IntegratedSpiral3d)) { ck.testFalse(spiralB.isAlmostEqual(spiralA)); ck.testFalse(spiralA.isAlmostEqual(undefined)); @@ -118,13 +132,40 @@ describe("TransitionSpiral3d", () => { if (Checker.noisy.spirals) GeometryCoreTestIO.consoleLog(TransitionSpiral3d.radiusRadiusLengthToSweepRadians(0, 10, 50)); } - const spiralD = IntegratedSpiral3d.createFrom4OutOf5("badTypeName", 0, 300.0, Angle.createDegrees(0), undefined, 100.0, undefined, Transform.createIdentity())!; + const spiralD = IntegratedSpiral3d.createFrom4OutOf5( + "badTypeName", + 0, + 300.0, + Angle.createDegrees(0), + undefined, + 100.0, + undefined, + Transform.createIdentity(), + )!; ck.testUndefined(spiralD); // default to clothoid ... - const spiralD1 = IntegratedSpiral3d.createFrom4OutOf5("clothoid", 0, 300.0, Angle.createDegrees(0), undefined, 100.0, undefined, Transform.createIdentity())!; + const spiralD1 = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + 0, + 300.0, + Angle.createDegrees(0), + undefined, + 100.0, + undefined, + Transform.createIdentity(), + )!; ck.testType(spiralD1, TransitionSpiral3d); - const spiralD2 = IntegratedSpiral3d.createFrom4OutOf5("clothoid", 0, undefined, Angle.createDegrees(0), undefined, 100.0, undefined, Transform.createIdentity())!; + const spiralD2 = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + 0, + undefined, + Angle.createDegrees(0), + undefined, + 100.0, + undefined, + Transform.createIdentity(), + )!; ck.testUndefined(spiralD2); expect(ck.getNumErrors()).toBe(0); @@ -133,12 +174,20 @@ describe("TransitionSpiral3d", () => { it("CreateAndTransform", () => { const ck = new Checker(); // spiral transform is not as easy as you expect -- regenerated data has been wrong at times. - const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(0, 1), Transform.createIdentity())!; - for (const transform of [ - Transform.createTranslationXYZ(2, 3, 1), - Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(10))), - Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createUniformScale(2.0)), - Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(10)))]) { + const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + )!; + for ( + const transform of [ + Transform.createTranslationXYZ(2, 3, 1), + Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(10))), + Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createUniformScale(2.0)), + Transform.createFixedPointAndMatrix(Point3d.create(3, 2, 5), Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(10))), + ] + ) { const spiralB = spiralA.cloneTransformed(transform); ck.testTransformedPoint3d(transform, spiralA.startPoint(), spiralB.startPoint(), "spiral.startPoint ()"); ck.testTransformedPoint3d(transform, spiralA.endPoint(), spiralB.endPoint(), "spiral.endPoint ()"); @@ -169,7 +218,7 @@ describe("TransitionSpiral3d", () => { Transform.createOriginAndMatrix(undefined, Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(85.5))), )!; // the start angle is chosen to make the true max x appear near the middle. - const numEvalA = 4; // a pretty crude count for the range, so as to show the properties of the extrapolation. + const numEvalA = 4; // a pretty crude count for the range, so as to show the properties of the extrapolation. const numEvalB = numEvalA * 2 - 1; const ls = LineString3d.create(); const lsB = LineString3d.create(); @@ -228,10 +277,20 @@ describe("TransitionSpiral3d", () => { it("PartialSpiralPoints", () => { const ck = new Checker(); - const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(0, 1), Transform.createIdentity())!; + const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + )!; const f0 = 0.3; const f1 = 0.9; - const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(f0, f1), Transform.createIdentity())!; + const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(f0, f1), + Transform.createIdentity(), + )!; for (const f of [0.25, 0.35, 0.98]) { const pointA = spiralA.fractionToPoint(Geometry.interpolate(f0, f, f1)); const pointB = spiralB.fractionToPoint(f); @@ -249,22 +308,40 @@ describe("TransitionSpiral3d", () => { }); it("PartialSpiralDerivatives", () => { const ck = new Checker(); - const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(0, 1), Transform.createIdentity())!; + const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + )!; const f0 = 0.3; const f1 = 0.9; const delta = f1 - f0; - const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(f0, f1), Transform.createIdentity())!; + const spiralB = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(f0, f1), + Transform.createIdentity(), + )!; for (const f of [0.25, 0.35, 0.98]) { const tangentA = spiralA.fractionToPointAndDerivative(Geometry.interpolate(f0, f, f1)); const tangentB = spiralB.fractionToPointAndDerivative(f); ck.testPoint3d(tangentA.origin, tangentB.origin, `spiral.fractionToPoint () in partial spiral at partial fraction ${f}`); - ck.testVector3d(tangentA.direction.scale(delta), tangentB.direction, "spiral.fractionToPointAndDerivatives in partial spiral at partial fraction"); + ck.testVector3d( + tangentA.direction.scale(delta), + tangentB.direction, + "spiral.fractionToPointAndDerivatives in partial spiral at partial fraction", + ); const planeA = spiralA.fractionToPointAnd2Derivatives(Geometry.interpolate(f0, f, f1))!; const planeB = spiralB.fractionToPointAnd2Derivatives(f)!; ck.testPoint3d(planeA.origin, planeB.origin, `spiral.fractionToPoint () in partial spiral at partial fraction ${f}`); ck.testVector3d(planeA.vectorU.scale(delta), planeB.vectorU, "spiral.fractionToPointAnd2Derivatives in partial spiral at partial fraction"); - ck.testVector3d(planeA.vectorV.scale(delta * delta), planeB.vectorV, "spiral.fractionToPointAnd2Derivatives in partial spiral at partial fraction"); + ck.testVector3d( + planeA.vectorV.scale(delta * delta), + planeB.vectorV, + "spiral.fractionToPointAnd2Derivatives in partial spiral at partial fraction", + ); } expect(ck.getNumErrors()).toBe(0); }); @@ -274,8 +351,16 @@ describe("TransitionSpiral3d", () => { const distance1 = 100; for (const radius1 of [200, -200, 400, 1000]) { for (const numTerm of [1, 2, 3]) { - const spiral3 = DirectSpiral3d.createTruncatedClothoid(`ClothoidSeries${numTerm}`, - Transform.createIdentity(), 3, 3, undefined, distance1, radius1, undefined)!; + const spiral3 = DirectSpiral3d.createTruncatedClothoid( + `ClothoidSeries${numTerm}`, + Transform.createIdentity(), + 3, + 3, + undefined, + distance1, + radius1, + undefined, + )!; for (const fraction0 of [0.0, 0.1, 0.5, 0.8, 0.941234763476189]) { const targetX = spiral3.evaluator.fractionToX(fraction0); const fraction1 = spiral3.evaluator.xToFraction(targetX); @@ -303,7 +388,16 @@ describe("TransitionSpiral3d", () => { if (Checker.noisy.spirals) GeometryCoreTestIO.consoleLog(` R/L = ${radius1 / distance1}`); let y0 = 0; - const spiral = IntegratedSpiral3d.createFrom4OutOf5("clothoid", 0, radius1, Angle.createDegrees(0), undefined, distance1, undefined, Transform.createIdentity())!; + const spiral = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + 0, + radius1, + Angle.createDegrees(0), + undefined, + distance1, + undefined, + Transform.createIdentity(), + )!; const linestring0 = LineString3d.create(); for (const d of [0, 10, 20, 30, 40, 50, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 80, 90, 100]) { distances.push(d); @@ -332,7 +426,9 @@ describe("TransitionSpiral3d", () => { const vy = seriesEvaluator.fractionToDDY(f); const curvature = Geometry.curvatureMagnitude(ux, uy, 0, vx, vy, 0); if (Checker.noisy.spirals) { - GeometryCoreTestIO.consoleLog(` f ${f} ${xyString("D,R", d, Geometry.safeDivideFraction(1, curvature, 0))} ${xyString("DU", ux, uy)} ${xyString("DV", vx, vy)}`); + GeometryCoreTestIO.consoleLog( + ` f ${f} ${xyString("D,R", d, Geometry.safeDivideFraction(1, curvature, 0))} ${xyString("DU", ux, uy)} ${xyString("DV", vx, vy)}`, + ); } const beta = d * d / (2.0 * radius1 * distance1); const wx = Math.cos(beta); @@ -384,28 +480,74 @@ describe("TransitionSpiral3d", () => { let y0 = 0; const dY0 = 10.0; const createPlacement = (degrees: number) => { - return Transform.createOriginAndMatrix(Point3d.create(1, 2, 0), - Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + return Transform.createOriginAndMatrix(Point3d.create(1, 2, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); }; const simpleCubic = DirectSpiral3d.createJapaneseCubic(createPlacement(0), nominalL1, nominalR1)!; const simpleCubicRotated = DirectSpiral3d.createJapaneseCubic(createPlacement(15), nominalL1, nominalR1)!; const aremaSpiral = DirectSpiral3d.createArema(createPlacement(45), nominalL1, nominalR1)!; const directHalfCosine = DirectSpiral3d.createDirectHalfCosine(createPlacement(90.0), nominalL1, nominalR1)!; - const spiral3 = DirectSpiral3d.createTruncatedClothoid("ClothoidSeriesX3Y3", - Transform.createIdentity(), 3, 3, undefined, nominalL1, nominalR1, undefined)!; - const westernAustralianSpiral = DirectSpiral3d.createTruncatedClothoid("WesternAustralian", - Transform.createIdentity(), 2, 1, undefined, nominalL1, nominalR1, undefined)!; - const spiral4 = DirectSpiral3d.createTruncatedClothoid("ClothoidSeriesX4Y4", - Transform.createIdentity(), 4, 4, undefined, nominalL1, nominalR1, undefined)!; - const spiral23 = DirectSpiral3d.createTruncatedClothoid("ClothoidSeriesX2Y3", - Transform.createIdentity(), 2, 3, undefined, nominalL1, nominalR1, undefined)!; + const spiral3 = DirectSpiral3d.createTruncatedClothoid( + "ClothoidSeriesX3Y3", + Transform.createIdentity(), + 3, + 3, + undefined, + nominalL1, + nominalR1, + undefined, + )!; + const westernAustralianSpiral = DirectSpiral3d.createTruncatedClothoid( + "WesternAustralian", + Transform.createIdentity(), + 2, + 1, + undefined, + nominalL1, + nominalR1, + undefined, + )!; + const spiral4 = DirectSpiral3d.createTruncatedClothoid( + "ClothoidSeriesX4Y4", + Transform.createIdentity(), + 4, + 4, + undefined, + nominalL1, + nominalR1, + undefined, + )!; + const spiral23 = DirectSpiral3d.createTruncatedClothoid( + "ClothoidSeriesX2Y3", + Transform.createIdentity(), + 2, + 3, + undefined, + nominalL1, + nominalR1, + undefined, + )!; const y4 = spiral4.evaluator.fractionToY(1.0); const x4 = spiral4.evaluator.fractionToX(1.0); const czechSpiral = DirectSpiral3d.createCzechCubic(Transform.createIdentity(), nominalL1, nominalR1)!; const mxCubicAlongArc = DirectSpiral3d.createMXCubicAlongArc(Transform.createIdentity(), nominalL1, nominalR1)!; const australianRailSpiral = DirectSpiral3d.createAustralianRail(Transform.createIdentity(), nominalL1, nominalR1)!; GeometryCoreTestIO.consoleLog(`Czech gamma factor ${CzechSpiralEvaluator.gammaConstant(nominalL1, nominalR1)}`); - for (const spiral of [mxCubicAlongArc, australianRailSpiral, westernAustralianSpiral, spiral23, simpleCubic, simpleCubicRotated, czechSpiral, directHalfCosine, westernAustralianSpiral, aremaSpiral, spiral3, spiral4]) { + for ( + const spiral of [ + mxCubicAlongArc, + australianRailSpiral, + westernAustralianSpiral, + spiral23, + simpleCubic, + simpleCubicRotated, + czechSpiral, + directHalfCosine, + westernAustralianSpiral, + aremaSpiral, + spiral3, + spiral4, + ] + ) { const strokes = spiral.activeStrokes; const range = spiral.range(); @@ -468,8 +610,7 @@ describe("TransitionSpiral3d", () => { const numA = spiral.computeStrokeCountForOptions(optionsA); optionsA.maxEdgeLength = 2; const numB = spiral.computeStrokeCountForOptions(optionsA); - ck.testTrue(numB > 2 * numA); // expect near 2.5 multiple, assuming first call was dominated by maxEdgeLength rather than internal angle setup? - + ck.testTrue(numB > 2 * numA); // expect near 2.5 multiple, assuming first call was dominated by maxEdgeLength rather than internal angle setup? } const directHalfCosine2L = DirectSpiral3d.createDirectHalfCosine(Transform.createIdentity(), 2 * nominalL1, nominalR1)!; @@ -496,7 +637,8 @@ describe("TransitionSpiral3d", () => { new NormalizedBiQuadraticTransition(), new NormalizedBlossTransition(), new NormalizedCosineTransition(), - new NormalizedSineTransition()]; + new NormalizedSineTransition(), + ]; for (const snap of snapFunctions) { if (Checker.noisy.spirals) GeometryCoreTestIO.consoleLog(" Snap Function ", snap); @@ -515,7 +657,7 @@ describe("TransitionSpiral3d", () => { let trueDerivative; for (let f = 0.0; f <= 1.0; f += df) { lsF.packedPoints.pushXYZ(f, snap.fractionToCurvatureFraction(f), 0); - lsDF.packedPoints.pushXYZ(f, (trueDerivative = snap.fractionToCurvatureFractionDerivative(f)), 0); + lsDF.packedPoints.pushXYZ(f, trueDerivative = snap.fractionToCurvatureFractionDerivative(f), 0); lsIF.packedPoints.pushXYZ(f, snap.fractionToArea(f), 0); // if cleanly inside the interval and NOT bracketing 0.5, do a central-difference derivative check ... if (f - e >= 0 && f + e <= 1.0 && (f + e - 0.5) * (f - e - 0.5) > 0) { @@ -603,31 +745,43 @@ describe("TransitionSpiral3d", () => { const length = bearingChange.radians / Geometry.meanCurvatureOfRadii(0, bigRadius); const dxB = length; const spirals: TransitionSpiral3d[] = []; - for (const spiralType of ["clothoid", "bloss", "biquadratic", "sine", "cosine", - "Czech", "Arema", "AustralianRailCorp"]) { + for (const spiralType of ["clothoid", "bloss", "biquadratic", "sine", "cosine", "Czech", "Arema", "AustralianRailCorp"]) { for (const activeInterval of [Segment1d.create(0, 1), Segment1d.create(0.35, 0.75)]) { for (const radiusSign of [1.0, -1.0]) { for (const reverseRadii of [false, true]) { let r0, r1; if (reverseRadii) { - r0 = bigRadius; r1 = 0; + r0 = bigRadius; + r1 = 0; } else { - r0 = 0; r1 = bigRadius; + r0 = 0; + r1 = bigRadius; } r0 *= radiusSign; r1 *= radiusSign; for (const reverseAfterCreate of [false, true]) { const spiralA = IntegratedSpiral3d.createRadiusRadiusBearingBearing( - Segment1d.create(r0, r1), AngleSweep.createStartEndDegrees(0, 8), - activeInterval, Transform.createIdentity(), spiralType); + Segment1d.create(r0, r1), + AngleSweep.createStartEndDegrees(0, 8), + activeInterval, + Transform.createIdentity(), + spiralType, + ); if (spiralA) { if (reverseAfterCreate) spiralA.reverseInPlace(); spirals.push(spiralA); } else { - const spiralB = DirectSpiral3d.createFromLengthAndRadius(spiralType, r0, r1, - undefined, undefined, length, - activeInterval, Transform.createIdentity()); + const spiralB = DirectSpiral3d.createFromLengthAndRadius( + spiralType, + r0, + r1, + undefined, + undefined, + length, + activeInterval, + Transform.createIdentity(), + ); if (spiralB) { if (reverseAfterCreate) spiralB.reverseInPlace(); @@ -641,7 +795,7 @@ describe("TransitionSpiral3d", () => { } let spiralType0 = ""; const optionsB = StrokeOptions.createForCurves(); - optionsB.maxEdgeLength = 2.0; // force a lot of strokes ! + optionsB.maxEdgeLength = 2.0; // force a lot of strokes ! for (const spiral of spirals) { const spiralType1 = spiral.spiralType; @@ -693,14 +847,17 @@ describe("TransitionSpiral3d", () => { const dxA = 0.1 * length1; const dyA = 1.5 * length1; const dyB = length1; - for (const evaluator of [ - new DirectHalfCosineSpiralEvaluator(length1, radius1), - new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 1, 1), - new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 2, 2), - new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 3, 3), - new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 4, 4), - AustralianRailCorpXYEvaluator.create(length1, radius1)!, - CzechSpiralEvaluator.create(length1, radius1)!]) { + for ( + const evaluator of [ + new DirectHalfCosineSpiralEvaluator(length1, radius1), + new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 1, 1), + new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 2, 2), + new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 3, 3), + new ClothoidSeriesRLEvaluator(length1, 1.0 / (2.0 * radius1 * length1), 4, 4), + AustralianRailCorpXYEvaluator.create(length1, radius1)!, + CzechSpiralEvaluator.create(length1, radius1)!, + ] + ) { const lsY = LineString3d.create(); const lsD1Y = LineString3d.create(); const lsD2Y = LineString3d.create(); @@ -763,7 +920,16 @@ describe("TransitionSpiral3d", () => { const length1 = 100; // smooth transition from the line to an arc of radius 300 const lineIn = LineSegment3d.createXYXY(-length1, 0, 0, 0); - const spiral = IntegratedSpiral3d.createFrom4OutOf5("clothoid", 0, radius1, Angle.createDegrees(0), undefined, length1, undefined, Transform.createIdentity())!; + const spiral = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + 0, + radius1, + Angle.createDegrees(0), + undefined, + length1, + undefined, + Transform.createIdentity(), + )!; const tangent1 = spiral.fractionToPointAndDerivative(1.0); const arcOut = CurveFactory.createArcPointTangentRadius(tangent1.origin, tangent1.direction, radius1, undefined, Angle.createDegrees(90)); GeometryCoreTestIO.captureCloneGeometry(allGeometry, lineIn, x0, y0); @@ -794,7 +960,6 @@ describe("TransitionSpiral3d", () => { { GeometryCoreTestIO.captureCloneGeometry(allGeometry, spiral.activeStrokes, x0, y0); } - } } } @@ -828,7 +993,6 @@ describe("TransitionSpiral3d", () => { ck.testCoordinate(lengthArray[spiralCounter], spiral.curveLength(), " confirm spiralLength"); spiralCounter++; } - } } } @@ -865,11 +1029,27 @@ describe("TransitionSpiral3d", () => { const simpleCubic = DirectSpiral3d.createJapaneseCubic(Transform.createIdentity(), nominalL1, nominalR1)!; const aremaSpiral = DirectSpiral3d.createArema(Transform.createIdentity(), nominalL1, nominalR1)!; const directHalfCosine = DirectSpiral3d.createDirectHalfCosine(Transform.createIdentity(), nominalL1, nominalR1)!; - const spiral3 = DirectSpiral3d.createTruncatedClothoid("ClothoidSeriesX3Y3", - Transform.createIdentity(), 3, 3, undefined, nominalL1, nominalR1, undefined)!; + const spiral3 = DirectSpiral3d.createTruncatedClothoid( + "ClothoidSeriesX3Y3", + Transform.createIdentity(), + 3, + 3, + undefined, + nominalL1, + nominalR1, + undefined, + )!; const westernAustralianSpiral = DirectSpiral3d.createWesternAustralian(Transform.createIdentity(), nominalL1, nominalR1, undefined)!; - const spiral4 = DirectSpiral3d.createTruncatedClothoid("ClothoidSeriesX3Y3", - Transform.createIdentity(), 4, 4, undefined, nominalL1, nominalR1, undefined)!; + const spiral4 = DirectSpiral3d.createTruncatedClothoid( + "ClothoidSeriesX3Y3", + Transform.createIdentity(), + 4, + 4, + undefined, + nominalL1, + nominalR1, + undefined, + )!; const czechSpiral = DirectSpiral3d.createCzechCubic(Transform.createIdentity(), nominalL1, nominalR1)!; for (const spiral of [simpleCubic, czechSpiral, directHalfCosine, westernAustralianSpiral, aremaSpiral, spiral3, spiral4]) { const actualL1 = spiral.curveLength(); @@ -881,7 +1061,9 @@ describe("TransitionSpiral3d", () => { const inverseFraction = spiral.moveSignedDistanceFromFraction(0, distanceFromStart, true); if (Checker.noisy.directSpiralDistanceAlong) GeometryCoreTestIO.consoleLog({ - fraction0: fraction, distance0: distanceFromStart, fraction1: inverseFraction.fraction, + fraction0: fraction, + distance0: distanceFromStart, + fraction1: inverseFraction.fraction, fraction01: (inverseFraction.fraction - fraction), }); ck.testCoordinate(fraction, inverseFraction.fraction); @@ -932,7 +1114,7 @@ describe("TransitionSpiral3d", () => { if (curve instanceof TransitionSpiral3d) { numSpiral++; const points = []; - for (let fraction = 0.0; fraction <= 1.0; fraction += 1.0 / 16.0) { // stay strictly less to allow debug break at 1.0 + for (let fraction = 0.0; fraction <= 1.0; fraction += 1.0 / 16.0) { // stay strictly less to allow debug break at 1.0 points.push(curve.fractionToPoint(fraction)); } // throw away for debugging... @@ -974,8 +1156,26 @@ describe("TransitionSpiral3d", () => { const x0 = 0; let y0 = 0; for (const radiusA of [200, 400]) { - const spiralA = IntegratedSpiral3d.createFrom4OutOf5("clothoid", 0, radiusA, Angle.createDegrees(0), Angle.createDegrees(exitDegrees), undefined, undefined, Transform.createIdentity()); - const spiralB = IntegratedSpiral3d.createFrom4OutOf5("clothoid", radiusA, 0, Angle.createDegrees(0), Angle.createDegrees(exitDegrees), undefined, undefined, Transform.createIdentity()); + const spiralA = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + 0, + radiusA, + Angle.createDegrees(0), + Angle.createDegrees(exitDegrees), + undefined, + undefined, + Transform.createIdentity(), + ); + const spiralB = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + radiusA, + 0, + Angle.createDegrees(0), + Angle.createDegrees(exitDegrees), + undefined, + undefined, + Transform.createIdentity(), + ); captureStroked(allGeometry, spiralB, x0, y0, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, spiralB, x0, y0, 0); @@ -998,7 +1198,12 @@ describe("TransitionSpiral3d", () => { const simpleCubicReversed = simpleCubic.clone(); simpleCubicReversed.reverseInPlace(); - const integratedSpiral = IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1000), AngleSweep.createStartEndDegrees(0, 8), Segment1d.create(0, 1), Transform.createIdentity())!; + const integratedSpiral = IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1000), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + )!; ck.testType(integratedSpiral, IntegratedSpiral3d); const integratedSpiralReversed = integratedSpiral.clone(); integratedSpiralReversed.reverseInPlace(); @@ -1064,7 +1269,16 @@ describe("TransitionSpiral3d", () => { const startAngle = Angle.createRadians(1.0877954002626353); const spiralToWorld = Transform.createOriginAndMatrix(startPoint, Matrix3d.createRotationAroundAxisIndex(AxisIndex.Z, startAngle)); - const clothoid = IntegratedSpiral3d.createFrom4OutOf5("clothoid", startRadius, endRadius, startBearing, endBearing, length, undefined, spiralToWorld); + const clothoid = IntegratedSpiral3d.createFrom4OutOf5( + "clothoid", + startRadius, + endRadius, + startBearing, + endBearing, + length, + undefined, + spiralToWorld, + ); if (ck.testPointer(clothoid)) { GeometryCoreTestIO.captureGeometry(allGeometry, clothoid); @@ -1091,8 +1305,12 @@ describe("TransitionSpiral3d", () => { const dy = 20.0; const radius1 = 300; const spiral01 = IntegratedSpiral3d.createRadiusRadiusBearingBearing( - Segment1d.create(0.0, radius1), AngleSweep.createStartEndDegrees(0, 8), - Segment1d.create(0, 1), Transform.createIdentity(), "clothoid")!; + Segment1d.create(0.0, radius1), + AngleSweep.createStartEndDegrees(0, 8), + Segment1d.create(0, 1), + Transform.createIdentity(), + "clothoid", + )!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, spiral01, x0, y0); const length01 = spiral01.curveLength(); for (const u of [0.0, 1.0]) { @@ -1100,13 +1318,15 @@ describe("TransitionSpiral3d", () => { const pointB = pointA.plusXYZ(0, 10 * dy, 0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [pointA, pointB], x0, y0); } - for (const activeInterval of [Segment1d.create(0, 1), - Segment1d.create(0.35, 0.75), - Segment1d.create(0.35, 1.1), Segment1d.create(-0.1, 1.1)]) { + for (const activeInterval of [Segment1d.create(0, 1), Segment1d.create(0.35, 0.75), Segment1d.create(0.35, 1.1), Segment1d.create(-0.1, 1.1)]) { y0 += dy; const spiral = IntegratedSpiral3d.createRadiusRadiusBearingBearing( - Segment1d.create(0.0, radius1), AngleSweep.createStartEndDegrees(0, 8), - activeInterval, Transform.createIdentity(), "clothoid")!; + Segment1d.create(0.0, radius1), + AngleSweep.createStartEndDegrees(0, 8), + activeInterval, + Transform.createIdentity(), + "clothoid", + )!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, spiral, x0, y0); const fractionLength = activeInterval.absoluteDelta(); const spiralLength = spiral.curveLength(); @@ -1130,7 +1350,6 @@ describe("TransitionSpiral3d", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, [spacePoint, curvePointDetail.point], x0, y0); ck.testCoordinate(u0, curvePointDetail.fraction, { u0, curvePointDetail, msg: "projected point fraction" }); } - } } expect(ck.getNumErrors()).toBe(0); @@ -1161,7 +1380,6 @@ it("AlexGProjectPointToChain", () => { if (curvePoint) { GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(spacePoint, curvePoint.point)); } - } } const counters = CurveChainWithDistanceIndex.getClosestPointTestCounts(true); @@ -1169,7 +1387,6 @@ it("AlexGProjectPointToChain", () => { ck.testTrue(counters.numTested > counters.numCalls, "more than one test per call"); ck.testTrue(counters.numCandidate >= counters.numCalls * alignment.children.length, "candidates"); GeometryCoreTestIO.consoleLog(counters); - } GeometryCoreTestIO.saveGeometry(allGeometry, "TransitionSpiral3d", "AlexGProjectToChain"); @@ -1192,8 +1409,13 @@ function captureStroked(allGeometry: GeometryQuery[], data: any, dx: number = 0, for (const fraction of [0.0, 0.10, 0.5, 0.75, 1.0]) { const frame = data.fractionToFrenetFrame(fraction); if (frame) - GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(frame.multiplyXYZ(2, 0, 0), frame.getOrigin(), frame.multiplyXYZ(0, 1, 0), frame.multiplyXYZ(0, 0, 1)), - dx, dy, dz); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineString3d.create(frame.multiplyXYZ(2, 0, 0), frame.getOrigin(), frame.multiplyXYZ(0, 1, 0), frame.multiplyXYZ(0, 0, 1)), + dx, + dy, + dz, + ); } } numStroked++; diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/MadhavInput.json b/core/geometry/src/test/data/ChainCollector/sectionData00/MadhavInput.json index 5bb6cdc6d8fc..f8032840d6ca 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/MadhavInput.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/MadhavInput.json @@ -1 +1,1970 @@ -[{"sourceId":"0x20000000f71","distanceAlong":0,"ray":{"origin":[508065.00303496333,6645747.0143687865,5.68931356159401],"direction":[0.17828222297866367,0.9839793945859772,0]},"elements":[{"elementId":"0x2000000251f","categoryId":"0x20000000325","modelId":"0x200000003b4","geometries":[[[-21.309597260551527,11.920265698326453,-9.313225746154785e-10],[-21.33814022457227,12.089129285321263,-1.862645149230957e-9],[-24.999999999650754,11.929871822407076,-1.862645149230957e-9]],[[-24.999999999650754,11.70139930111667,0],[-21.31668586714659,11.860715112107197,-9.313225746154785e-10],[-21.309597260551527,11.920265698326453,-9.313225746154785e-10]]]},{"elementId":"0x20000000ff7","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[24.999999999883585,-0.43631041904140133,0],[22.056361284456216,-0.40630544087528264,9.313225746154785e-10],[16.147139406879432,-0.3219719019683067,-9.313225746154785e-10],[15.132645385456271,-0.3056930230513286,0],[12.055327196256258,-0.253085721444374,0],[2.0542931078234687,-0.04858841566853389,9.313225746154785e-10],[7.695052772760391e-8,0.0039498092831484755,0],[7.695052772760391e-8,-0.03605019071685156,0],[2.0542931078234687,-0.08858841566853393,9.313225746154785e-10],[12.055327196256258,-0.29308572144437317,0],[15.132645385456271,-0.34569302305132865,0],[16.147139406879432,-0.36197190196830764,-9.313225746154785e-10],[22.056361284456216,-0.4463054408752827,9.313225746154785e-10],[24.999999999883585,-0.47631041904140137,0]]]},{"elementId":"0x20000000ff9","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[24.999999999883585,-0.47631041904140137,0],[22.056361284456216,-0.4463054408752827,9.313225746154785e-10],[16.147139406879432,-0.36197190196830764,-9.313225746154785e-10],[15.132645385456271,-0.34569302305132954,0],[12.055327196256258,-0.29308572144437317,0],[2.0542931078234687,-0.08858841566853481,9.313225746154785e-10],[7.695052772760391e-8,-0.036050190716853336,0],[7.695052772760391e-8,-0.1860501907168537,0],[2.0542931078234687,-0.23858841566853606,9.313225746154785e-10],[12.055327196256258,-0.4430857214443753,0],[15.132645385456271,-0.4956930230513299,0],[16.147139406879432,-0.5119719019683071,-9.313225746154785e-10],[22.056361284456216,-0.596305440875283,9.313225746154785e-10],[24.999999999883585,-0.6263104190414026,0]]]},{"elementId":"0x20000000ffb","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[24.999999999883585,-0.6263104190414017,0],[22.056361284456216,-0.596305440875283,9.313225746154785e-10],[16.147139406879432,-0.5119719019683071,-9.313225746154785e-10],[15.132645385456271,-0.4956930230513299,0],[12.055327196256258,-0.4430857214443753,0],[2.0542931078234687,-0.23858841566853606,9.313225746154785e-10],[7.695052772760391e-8,-0.1860501907168537,0],[7.695052772760391e-8,-0.386050190716853,0],[2.0542931078234687,-0.43858841566853535,9.313225746154785e-10],[12.055327196256258,-0.6430857214443746,0],[15.132645385456271,-0.6956930230513292,0],[16.147139406879432,-0.7119719019683073,-9.313225746154785e-10],[22.056361284456216,-0.7963054408752841,9.313225746154785e-10],[24.999999999883585,-0.8263104190414028,0]]]},{"elementId":"0x20000000fff","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-15.859479100327007,0.24273002498905605,0],[-17.947775068460032,0.31198164748942947,-9.313225746154785e-10],[-24.999999999883585,0.5677002788677514,0]],[[-25,0.7489401965574727,-9.313225746154785e-10],[-17.947775068343617,0.5013344678828959,-9.313225746154785e-10],[-15.859479100327007,0.43448522791356137,0]]]},{"elementId":"0x20000002525","categoryId":"0x2000000032b","modelId":"0x200000003b4","geometries":[[[-21.780904921120964,12.861791405043807,-9.313225746154785e-10],[-21.789858330157585,12.86956032503004,-1.862645149230957e-9],[-21.802550818421878,12.88066022244428,0],[-21.954314876929857,12.879165069859074,-9.313225746154785e-10],[-22.0804018083727,12.878036511133136,0],[-22.092661482281983,12.866303068942944,-9.313225746154785e-10],[-22.102102481527254,12.859073650031558,0],[-22.122556253219955,12.691610429392252,9.313225746154785e-10],[-22.159407244995236,12.385707666906114,0],[-22.17524986958597,12.35070784902479,-9.313225746154785e-10],[-22.196215688600205,12.330766938884697,-9.313225746154785e-10],[-22.194328614044935,12.30820463059127,0],[-22.214426882448606,12.263424855605749,-9.313225746154785e-10],[-22.250542386667803,12.217219808593622,0],[-22.310210896888748,12.13960101119519,0],[-22.305738903814927,12.080095888556123,-9.313225746154785e-10],[-22.305362391169183,12.046420798394731,0],[-22.016940460540354,12.058755775962776,-9.313225746154785e-10],[-21.810020496021025,12.067788405595405,-9.313225746154785e-10],[-21.812365179648623,12.263115616705043,0],[-21.816983875934966,12.54396206488616,0],[-21.799688460538164,12.557083743688562,0],[-21.77341440867167,12.576102172924184,-9.313225746154785e-10],[-21.775930330040865,12.693170305172938,-9.313225746154785e-10],[-21.780904921120964,12.861791405043807,-9.313225746154785e-10]]]},{"elementId":"0x200000025c2","categoryId":"0x20000000329","modelId":"0x200000003b4","geometries":[[[-21.61189473886043,11.848987561140202,-1.862645149230957e-9],[-22.193277208018117,11.82371376758709,0],[-22.192129198578186,11.798743681702902,0],[-22.225849510519765,11.797277796091816,-9.313225746154785e-10],[-22.29781346663367,10.648233753169766,0],[-22.589239793014713,10.585524916534677,0],[-22.885258157271892,10.622696423379715,0],[-23.062379766604863,11.760912246496144,0],[-23.096100079012103,11.759446360862054,-9.313225746154785e-10],[-23.097248088102788,11.784416446746484,-9.313225746154785e-10],[-23.678630557027645,11.759142653185911,0],[-23.675186529173516,11.684232395572554,0],[-23.27663874591235,11.701558020134758,-1.862645149230957e-9],[-23.15837606182322,11.631639146276054,0],[-22.949542722548358,10.289637957472351,-9.313225746154785e-10],[-22.203221454867162,10.322081952008123,-9.313225746154785e-10],[-22.118373121949844,11.676850037567103,-9.313225746154785e-10],[-22.006998493918218,11.756751678947065,-9.313225746154785e-10],[-21.608450710773468,11.774077303520965,-9.313225746154785e-10],[-21.61189473886043,11.848987561140202,-1.862645149230957e-9]]]},{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[-13.560657557449304,0.36501718623917956,0],[-13.965304459095933,0.3773465961386817,0],[-13.965304459095933,0.33734659613868256,0],[-13.560657557449304,0.32501718623917863,0],[-13.21495238353964,0.31453340329701174,0],[-12.749161509796977,0.3004772233202271,0],[-11.556745232548565,0.26536794189919544,0],[-11.317022527451627,0.2581691636677146,0],[-10.523360020597465,0.23481056174965165,0],[-10.412220384343527,0.23137165663719106,-9.313225746154785e-10],[-8.93376574816648,0.18978392633499386,-9.313225746154785e-10],[-8.900657587801106,0.1887610140821181,-9.313225746154785e-10],[-8.864327007555403,0.1877605621898768,-9.313225746154785e-10],[-7.993680467130616,0.16327686679037523,0],[-7.954276460572146,0.16256610885502543,-9.313225746154785e-10],[-5.506849944475107,0.0967532445200332,0],[-5.480727260117419,0.0964170635489463,0],[-3.898698852164671,0.05541856261882838,0],[-3.8841997728450224,0.055307173701409695,-9.313225746154785e-10],[-3.77053390792571,0.05476232726746133,0],[-2.8965330155333504,0.03206737034783469,0],[-0.4447324851062149,-0.029418677682011563,-9.313225746154785e-10],[-1.1641532182693481e-10,-0.040000000000000036,9.313225746154785e-10],[-1.1641532182693481e-10,0,9.313225746154785e-10],[-0.4447324851062149,0.010581322317988473,-9.313225746154785e-10],[-2.8965330155333504,0.07206737034783561,0],[-3.77053390792571,0.09476232726746137,0],[-3.8841997728450224,0.09530717370141062,-9.313225746154785e-10],[-3.898698852164671,0.09541856261882753,0],[-5.480727260233834,0.13641706354894634,0],[-5.506849944475107,0.13675324452003323,0],[-7.954276460572146,0.20256610885502546,-9.313225746154785e-10],[-7.993680467130616,0.20327686679037527,0],[-8.864327007555403,0.22776056218987684,-9.313225746154785e-10],[-8.900657587801106,0.22876101408211724,-9.313225746154785e-10],[-8.93376574816648,0.2297839263349939,-9.313225746154785e-10],[-10.412220384576358,0.2713716566371911,0],[-10.523360020597465,0.2748105617496517,0],[-11.317022527451627,0.2981691636677155,0],[-11.556745232548565,0.30536794189919547,0],[-12.749161509796977,0.340477223320228,0],[-13.21495238353964,0.3545334032970109,0],[-13.560657557449304,0.36501718623917956,0]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[-13.560657557449304,0.32501718623917863,0],[-13.965304459095933,0.33734659613868256,0],[-13.965304459095933,0.1873465961386822,0],[-13.560657557449304,0.17501718623918006,0],[-13.21495238353964,0.16453340329701138,0],[-12.749161509796977,0.15047722332022762,0],[-11.556745232548565,0.11536794189919597,0],[-11.317022527451627,0.10816916366771512,0],[-10.523360020597465,0.08481056174965129,0],[-10.412220384343527,0.08137165663718982,-9.313225746154785e-10],[-8.93376574816648,0.039783926334992614,-9.313225746154785e-10],[-8.900657587801106,0.03876101408211685,-9.313225746154785e-10],[-8.864327007555403,0.03776056218987467,-9.313225746154785e-10],[-7.993680467130616,0.013276866790373987,0],[-7.954276460572146,0.012566108855024183,-9.313225746154785e-10],[-5.506849944475107,-0.053246755479968044,0],[-5.480727260117419,-0.05358293645105494,0],[-3.898698852164671,-0.09458143738117109,0],[-3.8841997728450224,-0.09469282629858888,-9.313225746154785e-10],[-3.77053390792571,-0.09523767273253814,0],[-2.8965330155333504,-0.11793262965216389,0],[-0.4447324851062149,-0.1794186776820128,-9.313225746154785e-10],[-1.1641532182693481e-10,-0.1899999999999995,9.313225746154785e-10],[-1.1641532182693481e-10,-0.040000000000000036,9.313225746154785e-10],[-0.4447324851062149,-0.029418677682011563,-9.313225746154785e-10],[-2.8965330155333504,0.03206737034783469,0],[-3.77053390792571,0.05476232726746133,0],[-3.8841997728450224,0.055307173701409695,-9.313225746154785e-10],[-3.898698852164671,0.05541856261882838,0],[-5.480727260233834,0.0964170635489463,0],[-5.506849944475107,0.0967532445200332,0],[-7.954276460572146,0.16256610885502543,-9.313225746154785e-10],[-7.993680467130616,0.16327686679037523,0],[-8.864327007555403,0.1877605621898768,-9.313225746154785e-10],[-8.900657587801106,0.1887610140821181,-9.313225746154785e-10],[-8.93376574816648,0.18978392633499386,-9.313225746154785e-10],[-10.412220384576358,0.23137165663719106,0],[-10.523360020597465,0.23481056174965165,0],[-11.317022527451627,0.2581691636677146,0],[-11.556745232548565,0.26536794189919544,0],[-12.749161509796977,0.3004772233202271,0],[-13.21495238353964,0.31453340329701174,0],[-13.560657557449304,0.32501718623917863,0]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[-13.560657557449304,0.17501718623918006,0],[-13.965304459095933,0.1873465961386822,0],[-13.965304459095933,-0.012653403861317969,0],[-13.560657557449304,-0.02498281376082101,0],[-13.21495238353964,-0.03546659670298968,0],[-12.749161509796977,-0.04952277667977345,0],[-11.556745232548565,-0.08463205810080421,0],[-11.317022527451627,-0.09183083633228506,0],[-10.523360020597465,-0.11518943825034889,0],[-10.412220384343527,-0.11862834336280859,-9.313225746154785e-10],[-8.93376574816648,-0.16021607366500756,-9.313225746154785e-10],[-8.900657587801106,-0.16123898591788244,-9.313225746154785e-10],[-8.864327007555403,-0.1622394378101255,-9.313225746154785e-10],[-7.993680467130616,-0.18672313320962708,0],[-7.954276460572146,-0.187433891144976,-9.313225746154785e-10],[-5.506849944475107,-0.2532467554799682,0],[-5.480727260117419,-0.2535829364510551,0],[-3.898698852164671,-0.29458143738117215,0],[-3.8841997728450224,-0.29469282629858995,-9.313225746154785e-10],[-3.77053390792571,-0.2952376727325392,0],[-2.8965330155333504,-0.31793262965216584,0],[-0.4447324851062149,-0.379418677682013,-9.313225746154785e-10],[-1.1641532182693481e-10,-0.39000000000000057,9.313225746154785e-10],[-1.1641532182693481e-10,-0.1899999999999995,9.313225746154785e-10],[-0.4447324851062149,-0.1794186776820128,-9.313225746154785e-10],[-2.8965330155333504,-0.11793262965216389,0],[-3.77053390792571,-0.09523767273253814,0],[-3.8841997728450224,-0.09469282629858888,-9.313225746154785e-10],[-3.898698852164671,-0.09458143738117109,0],[-5.480727260233834,-0.05358293645105494,0],[-5.506849944475107,-0.053246755479968044,0],[-7.954276460572146,0.012566108855024183,-9.313225746154785e-10],[-7.993680467130616,0.013276866790373987,0],[-8.864327007555403,0.03776056218987467,-9.313225746154785e-10],[-8.900657587801106,0.03876101408211685,-9.313225746154785e-10],[-8.93376574816648,0.039783926334992614,-9.313225746154785e-10],[-10.412220384576358,0.0813716566371907,0],[-10.523360020597465,0.08481056174965129,0],[-11.317022527451627,0.10816916366771512,0],[-11.556745232548565,0.11536794189919597,0],[-12.749161509796977,0.15047722332022762,0],[-13.21495238353964,0.16453340329701138,0],[-13.560657557449304,0.17501718623918006,0]]]},{"elementId":"0x20000001047","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-14.629234474035911,0.39593035363518947,-1.862645149230957e-9],[-15.020279791089706,0.40860511585720527,-9.313225746154785e-10],[-15.859479100327007,0.434485227954001,0],[-15.859479100443423,0.24273002499550778,0],[-15.515034026349895,0.229057381444421,-9.313225746154785e-10],[-14.629234474268742,0.19660126485857976,-9.313225746154785e-10],[-13.965304456767626,0.16734659604119706,0],[-13.965304456884041,0.377346596041197,0],[-14.629234474035911,0.39593035363518947,-1.862645149230957e-9]]]},{"elementId":"0x200000025bf","categoryId":"0x20000000329","modelId":"0x200000003b4","geometries":[[[-23.717762321117334,11.757671543662408,0],[-24.301593580050394,11.732228036294664,0],[-24.300440740655176,11.707258285300973,-9.313225746154785e-10],[-24.334303083014674,11.705782556229131,-9.313225746154785e-10],[-24.406570418039337,10.556717494419264,0],[-24.69922424782999,10.493923585774699,-9.313225746154785e-10],[-24.996489433106035,10.531008681171187,-9.313225746154785e-10],[-24.999999999650754,10.553472614613835,0]],[[-24.999999999650754,10.20059179534578,0],[-24.311580060399137,10.230593302678546,-1.862645149230957e-9],[-24.226374032441527,11.585386170316227,0],[-24.11453027499374,11.665320324314234,-9.313225746154785e-10],[-23.714303803630173,11.682762290660467,-9.313225746154785e-10],[-23.717762321117334,11.757671543662408,0]]]}]},{"sourceId":"0x20000000f71","distanceAlong":10,"ray":{"origin":[508066.7858571931,6645756.854162732,5.483521231404236],"direction":[0.17828222297866367,0.9839793945859772,0]},"elements":[{"elementId":"0x20000000a16","categoryId":"0x20000000183","modelId":"0x200000003c3","geometries":[[[-24.712078254204243,12.229065306170728,-1.862645149230957e-9],[-24.712078254204243,9.439300229625651,-1.862645149230957e-9],[-24.712078254204243,-0.04962572769248297,-1.862645149230957e-9],[-24.999999999883585,-0.05862859917218266,-9.313225746154785e-10]],[[-24.99999999976717,-0.6086964001481494,-9.313225746154785e-10],[-24.905035979347304,-0.6057454895855674,-9.313225746154785e-10],[-23.677354383165948,-0.5673994461203868,-9.313225746154785e-10],[-23.677354383165948,-0.16739944612038382,-9.313225746154785e-10],[-23.931223444873467,-0.17532892392315524,-3.725290298461914e-9],[-24.200328385224566,-0.18367852391556472,-9.313225746154785e-10],[-24.274962203926407,6.2351032033325335,-1.862645149230957e-9],[-24.35399462026544,13.032284360849353,-1.862645149230957e-9],[-24.70277738769073,13.029148948575045,-1.862645149230957e-9],[-24.712078254204243,12.229065306170728,-1.862645149230957e-9]]]},{"elementId":"0x20000000a1e","categoryId":"0x20000000187","modelId":"0x200000003c3","geometries":[[[-24.71207825327292,12.229065306219276,-9.313225746154785e-10],[-24.99999999976717,12.216575559213922,-9.313225746154785e-10]]]},{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[0,0,0],[-6.000000000232831,-0.12000000000499345,-9.313225746154785e-10],[-6.000000000232831,-0.16000000000499348,-9.313225746154785e-10],[0,-0.040000000000000036,0],[6.0098497840808704,-0.1602517443488738,-1.862645149230957e-9],[6.0098497840808704,-0.12025174434887376,-1.862645149230957e-9],[0,0,0]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[0,-0.040000000000000036,0],[-6.000000000232831,-0.16000000000499348,-9.313225746154785e-10],[-6.000000000232831,-0.31000000000499295,-9.313225746154785e-10],[0,-0.1899999999999995,0],[6.0098497840808704,-0.31025174434887504,-1.862645149230957e-9],[6.0098497840808704,-0.1602517443488738,-1.862645149230957e-9],[0,-0.040000000000000036,0]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[0,-0.1899999999999995,0],[-6.000000000232831,-0.31000000000499295,-9.313225746154785e-10],[-6.000000000232831,-0.510000000004994,-9.313225746154785e-10],[0,-0.39000000000000057,0],[6.0098497840808704,-0.5102517443488743,-1.862645149230957e-9],[6.0098497840808704,-0.31025174434887504,-1.862645149230957e-9],[0,-0.1899999999999995,0]]]},{"elementId":"0x20000000f9f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.380000000237487,-0.08400000000499297,0],[-11.052264821715653,0.1400860329075968,0],[-11.052264821715653,0.04008603290759538,0],[-10.380000000237487,-0.1840000000049944,0],[-10.380000000237487,-0.08400000000499297,0]]]},{"elementId":"0x20000000f9d","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[-11.052264821715653,0.1400860329075968,0],[-10.380000000237487,-0.08400000000499297,0]]]},{"elementId":"0x20000000f81","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-8.680000000284053,-0.05000000000499227,9.313225746154785e-10],[-9.880000000121072,-0.0740000000049923,-9.313225746154785e-10],[-9.880000000121072,-0.17400000000499372,-9.313225746154785e-10],[-8.680000000284053,-0.1500000000049937,9.313225746154785e-10],[-8.680000000284053,-0.05000000000499227,9.313225746154785e-10]]]},{"elementId":"0x20000000f82","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-8.680000000284053,-0.05000000000499227,0],[-6.680000000284053,-0.010000000004992238,9.313225746154785e-10]]]},{"elementId":"0x20000000f83","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-10.380000000237487,-0.08400000000499297,0],[-9.880000000353903,-0.0740000000049923,0]]]},{"elementId":"0x20000000f85","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-6,-0.12000000000499433,-9.313225746154785e-10],[-6.500000000349246,-0.16000000000499437,0],[-6.53000000002794,-0.010000000004994014,-9.313225746154785e-10],[-6.680000000167638,-0.010000000004994014,9.313225746154785e-10],[-6.680000000167638,-0.3300000000049934,9.313225746154785e-10],[-6,-0.3300000000049934,-9.313225746154785e-10],[-6,-0.12000000000499433,-9.313225746154785e-10]]]},{"elementId":"0x2000000102d","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[6.009849783964455,-0.3302517155538194,-1.862645149230957e-9],[6.5050995904020965,-0.3302517155538194,-1.862645149230957e-9],[6.689849783782847,-0.32992302906745863,-9.313225746154785e-10],[6.689849783782847,-0.009923029067459233,-9.313225746154785e-10],[6.6468152336310595,-0.009999591230094751,-1.862645149230957e-9],[6.539849783643149,-0.009999591243764705,0],[6.5098497837316245,-0.1600146135503513,-9.313225746154785e-10],[6.152845289441757,-0.13145425399504784,-9.313225746154785e-10],[6.009849783964455,-0.12025171555381853,-1.862645149230957e-9],[6.009849783964455,-0.3302517155538194,-1.862645149230957e-9]]]},{"elementId":"0x20000001029","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[6.689849783782847,-0.009923029067458344,-9.313225746154785e-10],[7.432176180649549,-0.023448894482823057,-1.862645149230957e-9],[8.689849783666432,-0.048602366564344024,0]]]},{"elementId":"0x20000001027","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[9.222578136483207,-0.15805021063472324,-1.862645149230957e-9],[9.889849783852696,-0.1713956435702162,-9.313225746154785e-10],[9.889849783852696,-0.07139564357021566,-9.313225746154785e-10],[9.222578136483207,-0.05805021063472271,-1.862645149230957e-9],[8.689849783899263,-0.04860236656434491,0],[8.689849783899263,-0.14860236656434544,0],[9.222578136483207,-0.15805021063472324,-1.862645149230957e-9]]]},{"elementId":"0x2000000102b","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[9.889849783736281,-0.0713956435570493,-9.313225746154785e-10],[10.131568165728822,-0.07557511702494502,-9.313225746154785e-10],[10.389849783852696,-0.08074074936673448,-9.313225746154785e-10]]]},{"elementId":"0x20000001025","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[10.389849783852696,-0.08074074938234865,-9.313225746154785e-10],[10.631802612915635,0.0006232376989618871,-9.313225746154785e-10],[10.860269933007658,0.07677824947917156,-9.313225746154785e-10]]]},{"elementId":"0x2000000102f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.631802612915635,-0.09937676230103598,-9.313225746154785e-10],[10.860269933007658,-0.0232217505208272,-9.313225746154785e-10],[10.860269933007658,0.07677824947917156,-9.313225746154785e-10],[10.631802612915635,0.0006232376989618871,-9.313225746154785e-10],[10.389849783852696,-0.08074074938234865,-9.313225746154785e-10],[10.389849783852696,-0.18074074938234652,-9.313225746154785e-10],[10.631802612915635,-0.09937676230103598,-9.313225746154785e-10]]]}]},{"sourceId":"0x20000000f71","distanceAlong":20,"ray":{"origin":[508068.5686794229,6645766.693956678,5.277728901214461],"direction":[0.17828222297866367,0.9839793945859772,0]},"elements":[{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[0,0,0],[-6.000000000349246,-0.12000000000384681,9.313225746154785e-10],[-6.000000000349246,-0.16000000000384684,9.313225746154785e-10],[0,-0.040000000000000036,0],[5.999999999650754,-0.15999999999926562,1.862645149230957e-9],[5.999999999650754,-0.11999999999926558,1.862645149230957e-9],[0,0,0]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[0,-0.040000000000000036,0],[-6.000000000349246,-0.16000000000384684,9.313225746154785e-10],[-6.000000000349246,-0.3100000000038481,9.313225746154785e-10],[0,-0.1900000000000004,0],[5.999999999650754,-0.309999999999266,1.862645149230957e-9],[5.999999999650754,-0.15999999999926562,1.862645149230957e-9],[0,-0.040000000000000036,0]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[0,-0.1900000000000004,0],[-6.000000000349246,-0.3100000000038481,9.313225746154785e-10],[-6.000000000349246,-0.5100000000038483,9.313225746154785e-10],[0,-0.39000000000000057,0],[5.999999999650754,-0.5099999999992653,1.862645149230957e-9],[5.999999999650754,-0.309999999999266,1.862645149230957e-9],[0,-0.1900000000000004,0]]]},{"elementId":"0x20000000f98","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[5.999999999767169,-0.32999999999926555,2.7939677238464355e-9],[6.679999999701977,-0.32999999999926555,1.862645149230957e-9],[6.679999999701977,-0.009999999999265263,1.862645149230957e-9],[6.529999999795109,-0.009999999999265263,1.862645149230957e-9],[6.499999999767169,-0.15999999999926562,2.7939677238464355e-9],[5.999999999767169,-0.11999999999926558,2.7939677238464355e-9],[5.999999999767169,-0.32999999999926555,2.7939677238464355e-9]]]},{"elementId":"0x20000000f92","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.14999999999926583,0],[9.879999999888241,-0.17399999999926585,1.862645149230957e-9],[9.879999999888241,-0.07399999999926443,1.862645149230957e-9],[8.680000000051223,-0.04999999999926441,0],[8.680000000051223,-0.14999999999926583,0]]]},{"elementId":"0x20000000fa5","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.379999999771826,-0.18399999999926564,9.313225746154785e-10],[10.85427225427702,-0.025910829392767454,1.862645149230957e-9],[10.85427225427702,0.07408917060723219,1.862645149230957e-9],[10.379999999771826,-0.083999999999266,9.313225746154785e-10],[10.379999999771826,-0.18399999999926564,9.313225746154785e-10]]]},{"elementId":"0x20000000fa3","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[10.85427225427702,0.07408917060723219,1.862645149230957e-9],[10.379999999771826,-0.083999999999266,9.313225746154785e-10]]]},{"elementId":"0x20000000f96","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[10.379999999771826,-0.083999999999266,9.313225746154785e-10],[9.879999999888241,-0.07399999999926443,9.313225746154785e-10]]]},{"elementId":"0x20000000f94","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.04999999999926441,0],[6.679999999701977,-0.009999999999265263,1.862645149230957e-9]]]},{"elementId":"0x20000000f9f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.380000000470318,-0.08400000000384811,2.7939677238464355e-9],[-10.452001590980217,-0.059999709788664646,1.862645149230957e-9],[-10.452001590980217,-0.1599997097886634,1.862645149230957e-9],[-10.380000000470318,-0.18400000000384864,2.7939677238464355e-9],[-10.380000000470318,-0.08400000000384811,2.7939677238464355e-9]]]},{"elementId":"0x20000000f9d","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[-10.452001590980217,-0.059999709788664646,1.862645149230957e-9],[-10.380000000470318,-0.08400000000384811,2.7939677238464355e-9]]]},{"elementId":"0x20000000f81","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-8.680000000284053,-0.05000000000384741,1.862645149230957e-9],[-9.880000000353903,-0.07400000000384743,9.313225746154785e-10],[-9.880000000353903,-0.17400000000384797,9.313225746154785e-10],[-8.680000000284053,-0.15000000000384794,1.862645149230957e-9],[-8.680000000284053,-0.05000000000384741,1.862645149230957e-9]]]},{"elementId":"0x20000000f82","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-8.680000000167638,-0.05000000000384652,1.862645149230957e-9],[-6.680000000167638,-0.010000000003847376,0]]]},{"elementId":"0x20000000f83","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-10.380000000237487,-0.08400000000384722,9.313225746154785e-10],[-9.880000000353903,-0.07400000000384743,9.313225746154785e-10]]]},{"elementId":"0x20000000f85","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-6.000000000232831,-0.12000000000384681,1.862645149230957e-9],[-6.500000000116415,-0.16000000000384684,9.313225746154785e-10],[-6.530000000377186,-0.010000000003847376,1.862645149230957e-9],[-6.680000000284053,-0.010000000003847376,9.313225746154785e-10],[-6.680000000284053,-0.33000000000384766,9.313225746154785e-10],[-6.000000000232831,-0.33000000000384766,1.862645149230957e-9],[-6.000000000232831,-0.12000000000384681,1.862645149230957e-9]]]}]},{"sourceId":"0x20000000f71","distanceAlong":30,"ray":{"origin":[508070.3515016527,6645776.533750624,5.071936571024687],"direction":[0.17828222297866367,0.9839793945859772,0]},"elements":[{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[0,0,0],[-6.000000000232831,-0.11999999999926558,1.862645149230957e-9],[-6.000000000232831,-0.15999999999926562,1.862645149230957e-9],[0,-0.040000000000000036,0],[6.000000000465661,-0.16000000000270198,0],[6.000000000465661,-0.12000000000270195,0],[0,0,0]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[0,-0.040000000000000036,0],[-6.000000000232831,-0.15999999999926562,1.862645149230957e-9],[-6.000000000232831,-0.309999999999266,1.862645149230957e-9],[0,-0.1900000000000004,0],[6.000000000465661,-0.31000000000270234,0],[6.000000000465661,-0.16000000000270198,0],[0,-0.040000000000000036,0]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[0,-0.1900000000000004,0],[-6.000000000232831,-0.309999999999266,1.862645149230957e-9],[-6.000000000232831,-0.5099999999992653,1.862645149230957e-9],[0,-0.39000000000000057,0],[6.000000000465661,-0.5100000000027016,0],[6.000000000465661,-0.31000000000270234,0],[0,-0.1900000000000004,0]]]},{"elementId":"0x20000000f98","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[6.000000000116415,-0.3300000000027019,1.862645149230957e-9],[6.680000000284053,-0.3300000000027019,0],[6.680000000284053,-0.010000000002701626,0],[6.529999999795109,-0.010000000002701626,2.7939677238464355e-9],[6.500000000232831,-0.16000000000270198,1.862645149230957e-9],[6.000000000116415,-0.12000000000270195,1.862645149230957e-9],[6.000000000116415,-0.3300000000027019,1.862645149230957e-9]]]},{"elementId":"0x20000000f92","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[8.680000000167638,-0.1500000000027022,0],[9.880000000004657,-0.17400000000270222,1.862645149230957e-9],[9.880000000004657,-0.07400000000270168,1.862645149230957e-9],[8.680000000167638,-0.05000000000270166,0],[8.680000000167638,-0.1500000000027022,0]]]},{"elementId":"0x20000000fa5","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.379999999888241,-0.184000000002702,9.313225746154785e-10],[10.788921954343095,-0.04769404485953377,1.862645149230957e-9],[10.788921954343095,0.052305955140465876,1.862645149230957e-9],[10.379999999888241,-0.08400000000270236,9.313225746154785e-10],[10.379999999888241,-0.184000000002702,9.313225746154785e-10]]]},{"elementId":"0x20000000fa3","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[10.788921954343095,0.052305955140465876,1.862645149230957e-9],[10.379999999888241,-0.08400000000270236,9.313225746154785e-10]]]},{"elementId":"0x20000000f96","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[10.379999999888241,-0.08400000000270236,9.313225746154785e-10],[9.880000000004657,-0.07400000000270168,1.862645149230957e-9]]]},{"elementId":"0x20000000f94","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[8.680000000167638,-0.05000000000270166,0],[6.680000000167638,-0.010000000002701626,9.313225746154785e-10]]]},{"elementId":"0x20000000f9f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.380000000121072,-0.083999999999266,1.862645149230957e-9],[-10.684205847093835,0.017400935047763078,1.862645149230957e-9],[-10.684205847093835,-0.08259906495223479,1.862645149230957e-9],[-10.380000000121072,-0.18399999999926564,1.862645149230957e-9],[-10.380000000121072,-0.083999999999266,1.862645149230957e-9]]]},{"elementId":"0x20000000f9d","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[-10.684205847093835,0.017400935047763966,1.862645149230957e-9],[-10.380000000121072,-0.083999999999266,1.862645149230957e-9]]]},{"elementId":"0x20000000f81","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-8.680000000051223,-0.04999999999926441,1.862645149230957e-9],[-9.880000000121072,-0.07399999999926443,1.862645149230957e-9],[-9.880000000121072,-0.17399999999926585,1.862645149230957e-9],[-8.680000000051223,-0.14999999999926583,1.862645149230957e-9],[-8.680000000051223,-0.04999999999926441,1.862645149230957e-9]]]},{"elementId":"0x20000000f82","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-8.680000000051223,-0.04999999999926441,2.7939677238464355e-9],[-6.679999999934807,-0.009999999999265263,9.313225746154785e-10]]]},{"elementId":"0x20000000f83","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-10.379999999771826,-0.08399999999926511,9.313225746154785e-10],[-9.879999999888241,-0.07399999999926443,9.313225746154785e-10]]]},{"elementId":"0x20000000f85","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-6.000000000232831,-0.11999999999926558,1.862645149230957e-9],[-6.5,-0.15999999999926562,1.862645149230957e-9],[-6.529999999678694,-0.009999999999265263,0],[-6.679999999934807,-0.009999999999265263,9.313225746154785e-10],[-6.679999999934807,-0.32999999999926644,9.313225746154785e-10],[-6.000000000232831,-0.32999999999926644,1.862645149230957e-9],[-6.000000000232831,-0.11999999999926558,1.862645149230957e-9]]]}]},{"sourceId":"0x20000000f71","distanceAlong":40,"ray":{"origin":[508071.60238111287,6645786.443305271,4.866144240834913],"direction":[0.03269890991174909,0.9994652476652619,0]},"elements":[{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,0,-9.313225746154785e-10],[-6.000000000058208,-0.11999999999991129,9.313225746154785e-10],[-6.000000000058208,-0.15999999999991132,9.313225746154785e-10],[1.1641532182693481e-10,-0.040000000000000036,-9.313225746154785e-10],[6,-0.15999999999991132,-9.313225746154785e-10],[6,-0.11999999999991129,-9.313225746154785e-10],[1.1641532182693481e-10,0,-9.313225746154785e-10]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,-0.040000000000000036,-9.313225746154785e-10],[-6.000000000058208,-0.15999999999991132,9.313225746154785e-10],[-6.000000000058208,-0.30999999999991257,9.313225746154785e-10],[1.1641532182693481e-10,-0.1900000000000004,-9.313225746154785e-10],[6,-0.30999999999991257,-9.313225746154785e-10],[6,-0.15999999999991132,-9.313225746154785e-10],[1.1641532182693481e-10,-0.040000000000000036,-9.313225746154785e-10]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,-0.1900000000000004,-9.313225746154785e-10],[-6.000000000058208,-0.30999999999991257,9.313225746154785e-10],[-6.000000000058208,-0.5099999999999127,9.313225746154785e-10],[1.1641532182693481e-10,-0.39000000000000057,-9.313225746154785e-10],[6,-0.5099999999999127,-9.313225746154785e-10],[6,-0.30999999999991257,-9.313225746154785e-10],[1.1641532182693481e-10,-0.1900000000000004,-9.313225746154785e-10]]]},{"elementId":"0x20000000f98","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[6.000000000058208,-0.32999999999991125,9.313225746154785e-10],[6.680000000051223,-0.32999999999991125,9.313225746154785e-10],[6.680000000051223,-0.009999999999911857,9.313225746154785e-10],[6.53000000002794,-0.009999999999911857,9.313225746154785e-10],[6.5,-0.15999999999991132,-9.313225746154785e-10],[6.000000000058208,-0.11999999999991129,9.313225746154785e-10],[6.000000000058208,-0.32999999999991125,9.313225746154785e-10]]]},{"elementId":"0x20000000f92","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.14999999999991243,0],[9.879999999830034,-0.17399999999991245,1.862645149230957e-9],[9.879999999830034,-0.07399999999991191,1.862645149230957e-9],[8.680000000051223,-0.04999999999991189,0],[8.680000000051223,-0.14999999999991243,0]]]},{"elementId":"0x20000000fa5","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.380000000004657,-0.18399999999991135,9.313225746154785e-10],[10.96782595908735,0.011940026961439365,2.7939677238464355e-9],[10.96782595908735,0.11194002696143812,2.7939677238464355e-9],[10.380000000004657,-0.08399999999991259,9.313225746154785e-10],[10.380000000004657,-0.18399999999991135,9.313225746154785e-10]]]},{"elementId":"0x20000000fa3","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[10.96782595908735,0.11194002696143812,2.7939677238464355e-9],[10.380000000004657,-0.08399999999991259,9.313225746154785e-10]]]},{"elementId":"0x20000000f96","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[10.380000000004657,-0.08399999999991259,9.313225746154785e-10],[9.879999999946449,-0.07399999999991191,1.862645149230957e-9]]]},{"elementId":"0x20000000f94","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.04999999999991189,0],[6.679999999934807,-0.009999999999911857,2.7939677238464355e-9]]]},{"elementId":"0x20000000f9f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.380000000121072,-0.08399999999991348,1.862645149230957e-9],[-11.18704475602135,0.18501222850247867,-9.313225746154785e-10],[-11.18704475602135,0.08501222850247814,-9.313225746154785e-10],[-10.380000000121072,-0.18399999999991135,1.862645149230957e-9],[-10.380000000121072,-0.08399999999991348,1.862645149230957e-9]]]},{"elementId":"0x20000000f9d","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[-11.18704475602135,0.18501222850247867,-9.313225746154785e-10],[-10.380000000121072,-0.08399999999991259,1.862645149230957e-9]]]},{"elementId":"0x20000000f81","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-8.679999999993015,-0.04999999999991189,1.862645149230957e-9],[-9.880000000121072,-0.07399999999991191,1.862645149230957e-9],[-9.880000000121072,-0.17399999999991245,1.862645149230957e-9],[-8.679999999993015,-0.14999999999991243,1.862645149230957e-9],[-8.679999999993015,-0.04999999999991189,1.862645149230957e-9]]]},{"elementId":"0x20000000f82","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-8.679999999993015,-0.04999999999991189,1.862645149230957e-9],[-6.679999999934807,-0.009999999999911857,0]]]},{"elementId":"0x20000000f83","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-10.380000000004657,-0.08399999999991259,0],[-9.880000000121072,-0.07399999999991191,0]]]},{"elementId":"0x20000000f85","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-6,-0.11999999999991307,-9.313225746154785e-10],[-6.5,-0.15999999999991132,1.862645149230957e-9],[-6.53000000002794,-0.009999999999911857,0],[-6.679999999934807,-0.009999999999911857,0],[-6.679999999934807,-0.32999999999991125,0],[-6,-0.32999999999991125,-9.313225746154785e-10],[-6,-0.11999999999991307,-9.313225746154785e-10]]]}]},{"sourceId":"0x20000000f71","distanceAlong":42.64596001776388,"ray":{"origin":[508071.618903467,6645789.088904963,4.8116924130704515],"direction":[-0.020213083931456988,0.9997956947486721,0]},"elements":[{"elementId":"0x20000000f3a","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.379999999771826,-0.18497774903659003,9.313225746154785e-10],[-10.379999999771826,-0.08497774903659039,9.313225746154785e-10],[-11.218174668611027,0.19441101331197608,-9.313225746154785e-10]],[[-11.218174668611027,0.19441101331197608,-9.313225746154785e-10],[-10.379999999771826,-0.18497774903659003,9.313225746154785e-10]],[[-10.379999999771826,-0.18497774903659003,9.313225746154785e-10],[-11.218174668611027,0.09441101331197643,-9.313225746154785e-10],[-11.218174668611027,0.19441101331197608,-9.313225746154785e-10]],[[-10.379999999771826,-0.18497774903659003,9.313225746154785e-10],[-11.218174668611027,0.19441101331197608,-9.313225746154785e-10]]]},{"elementId":"0x20000000f32","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-9.880000000004657,-0.17497774903658936,-1.862645149230957e-9],[-8.679999999934807,-0.05097774903658969,-1.862645149230957e-9]],[[-8.679999999934807,-0.05097774903658969,-1.862645149230957e-9],[-9.880000000004657,-0.07497774903658971,-1.862645149230957e-9],[-9.880000000004657,-0.17497774903658936,-1.862645149230957e-9]],[[-8.679999999934807,-0.05097774903658969,-1.862645149230957e-9],[-8.679999999934807,-0.15097774903658934,-1.862645149230957e-9],[-9.880000000004657,-0.17497774903658936,-1.862645149230957e-9]],[[-8.679999999934807,-0.05097774903658969,-1.862645149230957e-9],[-9.880000000004657,-0.17497774903658936,-1.862645149230957e-9]]]},{"elementId":"0x20000001087","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[0,0,0],[-5.999999999883585,-0.11999999999890498,0]],[[6.000000000116415,-0.1199999999960717,1.862645149230957e-9],[0,0,0]],[[-5.999999999883585,-0.15999999999890502,0],[0,-0.040000000000000036,0]],[[0,-0.040000000000000036,0],[6.000000000116415,-0.15999999999607173,1.862645149230957e-9]],[[-5.999999999883585,-0.11999999999890498,0],[-5.999999999883585,-0.15999999999890502,0]],[[-5.999999999883585,-0.11999999999890498,0],[0,0,0]],[[0,0,0],[0,-0.040000000000000036,0]],[[0,-0.040000000000000036,0],[-5.999999999883585,-0.11999999999890498,0]],[[-5.999999999883585,-0.15999999999890502,0],[-5.999999999883585,-0.11999999999890498,0]],[[-5.999999999883585,-0.11999999999890498,0],[0,-0.040000000000000036,0]],[[0,-0.040000000000000036,0],[-5.999999999883585,-0.15999999999890502,0]],[[0,0,0],[6.000000000116415,-0.1199999999960717,1.862645149230957e-9]],[[6.000000000116415,-0.1199999999960717,1.862645149230957e-9],[6.000000000116415,-0.15999999999607173,1.862645149230957e-9]],[[6.000000000116415,-0.15999999999607173,1.862645149230957e-9],[0,0,0]],[[0,-0.040000000000000036,0],[0,0,0]],[[0,0,0],[6.000000000116415,-0.15999999999607173,1.862645149230957e-9]],[[6.000000000116415,-0.15999999999607173,1.862645149230957e-9],[0,-0.040000000000000036,0]],[[6.000000000116415,-0.15999999999607173,1.862645149230957e-9],[6.000000000116415,-0.1199999999960717,1.862645149230957e-9]]]},{"elementId":"0x20000001089","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[0,-0.040000000000000036,0],[-5.999999999883585,-0.15999999999890502,0]],[[6.000000000116415,-0.15999999999607173,1.862645149230957e-9],[0,-0.040000000000000036,0]],[[-5.999999999883585,-0.30999999999890626,0],[0,-0.1900000000000004,0]],[[0,-0.1900000000000004,0],[6.000000000116415,-0.309999999996073,1.862645149230957e-9]],[[-5.999999999883585,-0.15999999999890502,0],[-5.999999999883585,-0.30999999999890626,0]],[[-5.999999999883585,-0.15999999999890502,0],[0,-0.040000000000000036,0]],[[0,-0.040000000000000036,0],[0,-0.1900000000000004,0]],[[0,-0.1900000000000004,0],[-5.999999999883585,-0.15999999999890502,0]],[[-5.999999999883585,-0.30999999999890626,0],[-5.999999999883585,-0.15999999999890502,0]],[[-5.999999999883585,-0.15999999999890502,0],[0,-0.1900000000000004,0]],[[0,-0.1900000000000004,0],[-5.999999999883585,-0.30999999999890626,0]],[[0,-0.040000000000000036,0],[6.000000000116415,-0.15999999999607173,1.862645149230957e-9]],[[6.000000000116415,-0.15999999999607173,1.862645149230957e-9],[6.000000000116415,-0.309999999996073,1.862645149230957e-9]],[[6.000000000116415,-0.309999999996073,1.862645149230957e-9],[0,-0.040000000000000036,0]],[[0,-0.1900000000000004,0],[0,-0.040000000000000036,0]],[[0,-0.040000000000000036,0],[6.000000000116415,-0.309999999996073,1.862645149230957e-9]],[[6.000000000116415,-0.309999999996073,1.862645149230957e-9],[0,-0.1900000000000004,0]],[[6.000000000116415,-0.309999999996073,1.862645149230957e-9],[6.000000000116415,-0.15999999999607173,1.862645149230957e-9]]]},{"elementId":"0x2000000108b","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[0,-0.1900000000000004,0],[-5.999999999883585,-0.30999999999890626,0]],[[6.000000000116415,-0.309999999996073,1.862645149230957e-9],[0,-0.1900000000000004,0]],[[-5.999999999883585,-0.5099999999989064,0],[0,-0.39000000000000057,0]],[[0,-0.39000000000000057,0],[6.000000000116415,-0.5099999999960732,1.862645149230957e-9]],[[-5.999999999883585,-0.30999999999890626,0],[-5.999999999883585,-0.5099999999989064,0]],[[-5.999999999883585,-0.30999999999890626,0],[0,-0.1900000000000004,0]],[[0,-0.1900000000000004,0],[0,-0.39000000000000057,0]],[[0,-0.39000000000000057,0],[-5.999999999883585,-0.30999999999890626,0]],[[-5.999999999883585,-0.5099999999989064,0],[-5.999999999883585,-0.30999999999890626,0]],[[-5.999999999883585,-0.30999999999890626,0],[0,-0.39000000000000057,0]],[[0,-0.39000000000000057,0],[-5.999999999883585,-0.5099999999989064,0]],[[0,-0.1900000000000004,0],[6.000000000116415,-0.309999999996073,1.862645149230957e-9]],[[6.000000000116415,-0.309999999996073,1.862645149230957e-9],[6.000000000116415,-0.5099999999960732,1.862645149230957e-9]],[[6.000000000116415,-0.5099999999960732,1.862645149230957e-9],[0,-0.1900000000000004,0]],[[0,-0.39000000000000057,0],[0,-0.1900000000000004,0]],[[0,-0.1900000000000004,0],[6.000000000116415,-0.5099999999960732,1.862645149230957e-9]],[[6.000000000116415,-0.5099999999960732,1.862645149230957e-9],[0,-0.39000000000000057,0]],[[6.000000000116415,-0.5099999999960732,1.862645149230957e-9],[6.000000000116415,-0.309999999996073,1.862645149230957e-9]]]},{"elementId":"0x20000000f98","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[6.000000000116415,-0.32999999999609386,1.862645149230957e-9],[6.680000000051223,-0.32999999999609386,0]],[[6.680000000051223,-0.32999999999609386,0],[6.680000000051223,-0.009999999996093578,0]],[[6.680000000051223,-0.009999999996093578,0],[6.530000000144355,-0.009999999996093578,1.862645149230957e-9]],[[6.530000000144355,-0.009999999996093578,1.862645149230957e-9],[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9]],[[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9],[6.000000000116415,-0.1199999999960939,1.862645149230957e-9]],[[6.000000000116415,-0.1199999999960939,1.862645149230957e-9],[6.000000000116415,-0.32999999999609386,1.862645149230957e-9]],[[6.000000000116415,-0.1199999999960939,1.862645149230957e-9],[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9]],[[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9],[6.000000000116415,-0.32999999999609386,1.862645149230957e-9]],[[6.000000000116415,-0.32999999999609386,1.862645149230957e-9],[6.000000000116415,-0.1199999999960939,1.862645149230957e-9]],[[6.680000000051223,-0.32999999999609386,0],[6.000000000116415,-0.32999999999609386,1.862645149230957e-9]],[[6.000000000116415,-0.32999999999609386,1.862645149230957e-9],[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9]],[[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9],[6.680000000051223,-0.32999999999609386,0]],[[6.530000000144355,-0.009999999996093578,1.862645149230957e-9],[6.680000000051223,-0.009999999996093578,0]],[[6.680000000051223,-0.009999999996093578,0],[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9]],[[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9],[6.530000000144355,-0.009999999996093578,1.862645149230957e-9]],[[6.680000000051223,-0.32999999999609386,0],[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9]],[[6.500000000232831,-0.15999999999609393,2.7939677238464355e-9],[6.680000000051223,-0.009999999996093578,0]],[[6.680000000051223,-0.009999999996093578,0],[6.680000000051223,-0.32999999999609386,0]]]},{"elementId":"0x20000000e98","categoryId":"0x2000000014b","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,-0.19097774901887465,0],[-5.999999999883585,-0.3109777490295773,0],[-5.999999999883585,-0.5109777490295775,0]],[[-5.999999999883585,-0.5109777490295775,0],[1.1641532182693481e-10,-0.19097774901887465,0]],[[1.1641532182693481e-10,-0.39097774901887394,0],[1.1641532182693481e-10,-0.19097774901887465,0]],[[1.1641532182693481e-10,-0.19097774901887465,0],[-5.999999999883585,-0.5109777490295775,0]],[[-5.999999999883585,-0.5109777490295775,0],[1.1641532182693481e-10,-0.39097774901887394,0]],[[6.000000000116415,-0.31097774903400577,9.313225746154785e-10],[1.1641532182693481e-10,-0.19097774901887465,0]],[[1.1641532182693481e-10,-0.19097774901887465,0],[1.1641532182693481e-10,-0.39097774901887394,0]],[[1.1641532182693481e-10,-0.39097774901887394,0],[6.000000000116415,-0.31097774903400577,9.313225746154785e-10]],[[6.000000000116415,-0.31097774903400577,9.313225746154785e-10],[6.000000000116415,-0.5109777490340068,9.313225746154785e-10],[1.1641532182693481e-10,-0.39097774901887394,0]],[[6.000000000116415,-0.31097774903400577,9.313225746154785e-10],[1.1641532182693481e-10,-0.39097774901887394,0]]]},{"elementId":"0x20000000e96","categoryId":"0x2000000014d","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,-0.0409777490188743,0],[-5.999999999883585,-0.16097774902957607,0],[-5.999999999883585,-0.3109777490295773,0]],[[-5.999999999883585,-0.3109777490295773,0],[1.1641532182693481e-10,-0.0409777490188743,0]],[[1.1641532182693481e-10,-0.19097774901887465,0],[1.1641532182693481e-10,-0.0409777490188743,0]],[[1.1641532182693481e-10,-0.0409777490188743,0],[-5.999999999883585,-0.3109777490295773,0]],[[-5.999999999883585,-0.3109777490295773,0],[1.1641532182693481e-10,-0.19097774901887465,0]],[[6.000000000116415,-0.1609777490340063,9.313225746154785e-10],[1.1641532182693481e-10,-0.0409777490188743,0]],[[1.1641532182693481e-10,-0.0409777490188743,0],[1.1641532182693481e-10,-0.19097774901887465,0]],[[1.1641532182693481e-10,-0.19097774901887465,0],[6.000000000116415,-0.1609777490340063,9.313225746154785e-10]],[[6.000000000116415,-0.1609777490340063,9.313225746154785e-10],[6.000000000116415,-0.31097774903400577,9.313225746154785e-10],[1.1641532182693481e-10,-0.19097774901887465,0]],[[6.000000000116415,-0.1609777490340063,9.313225746154785e-10],[1.1641532182693481e-10,-0.19097774901887465,0]]]},{"elementId":"0x20000000e94","categoryId":"0x20000000255","modelId":"0x200000003c7","geometries":[[[1.1641532182693481e-10,-0.0009777490188742632,0],[-5.999999999883585,-0.12097774902957692,0],[-5.999999999883585,-0.16097774902957607,0]],[[-5.999999999883585,-0.16097774902957607,0],[1.1641532182693481e-10,-0.0009777490188742632,0]],[[1.1641532182693481e-10,-0.0409777490188743,0],[1.1641532182693481e-10,-0.0009777490188742632,0]],[[1.1641532182693481e-10,-0.0009777490188742632,0],[-5.999999999883585,-0.16097774902957607,0]],[[-5.999999999883585,-0.16097774902957607,0],[1.1641532182693481e-10,-0.0409777490188743,0]],[[6.000000000116415,-0.12097774903400627,9.313225746154785e-10],[1.1641532182693481e-10,-0.0009777490188742632,0]],[[1.1641532182693481e-10,-0.0009777490188742632,0],[1.1641532182693481e-10,-0.0409777490188743,0]],[[1.1641532182693481e-10,-0.0409777490188743,0],[6.000000000116415,-0.12097774903400627,9.313225746154785e-10]],[[6.000000000116415,-0.12097774903400627,9.313225746154785e-10],[6.000000000116415,-0.1609777490340063,9.313225746154785e-10],[1.1641532182693481e-10,-0.0409777490188743,0]],[[6.000000000116415,-0.12097774903400627,9.313225746154785e-10],[1.1641532182693481e-10,-0.0409777490188743,0]]]},{"elementId":"0x20000000f1b","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[6.500000000116415,-0.1609777490340063,0],[6.530000000144355,-0.010977749034005946,-9.313225746154785e-10],[6.680000000051223,-0.010977749034005946,-9.313225746154785e-10]],[[6.500000000116415,-0.1609777490340063,0],[6.680000000051223,-0.010977749034005946,-9.313225746154785e-10]],[[6.680000000051223,-0.33097774903400623,-9.313225746154785e-10],[6.680000000051223,-0.010977749034005946,-9.313225746154785e-10]],[[6.680000000051223,-0.010977749034005946,-9.313225746154785e-10],[6.500000000116415,-0.1609777490340063,0]],[[6.500000000116415,-0.1609777490340063,0],[6.680000000051223,-0.33097774903400623,-9.313225746154785e-10]],[[6.680000000051223,-0.33097774903400623,-9.313225746154785e-10],[6.500000000116415,-0.1609777490340063,0]],[[6.500000000116415,-0.1609777490340063,0],[6.000000000232831,-0.33097774903400623,-9.313225746154785e-10]],[[6.000000000232831,-0.33097774903400623,-9.313225746154785e-10],[6.680000000051223,-0.33097774903400623,-9.313225746154785e-10]],[[6.000000000232831,-0.33097774903400623,-9.313225746154785e-10],[6.000000000232831,-0.12097774903400715,-9.313225746154785e-10],[6.500000000116415,-0.1609777490340063,0]],[[6.000000000232831,-0.33097774903400623,-9.313225746154785e-10],[6.500000000116415,-0.1609777490340063,0]]]},{"elementId":"0x20000000f38","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-6.5,-0.1609777490365909,-1.862645149230957e-9],[-6,-0.12097774903658998,0],[-6,-0.33097774903658994,0]],[[-6.5,-0.1609777490365909,-1.862645149230957e-9],[-6,-0.33097774903658994,0]],[[-6.679999999818392,-0.33097774903658994,0],[-6,-0.33097774903658994,0]],[[-6,-0.33097774903658994,0],[-6.5,-0.1609777490365909,-1.862645149230957e-9]],[[-6.5,-0.1609777490365909,-1.862645149230957e-9],[-6.679999999818392,-0.33097774903658994,0]],[[-6.679999999818392,-0.010977749036589657,0],[-6.529999999911524,-0.010977749036589657,0],[-6.5,-0.1609777490365909,-1.862645149230957e-9]],[[-6.679999999818392,-0.010977749036589657,0],[-6.5,-0.1609777490365909,-1.862645149230957e-9]],[[-6.679999999818392,-0.33097774903658994,0],[-6.5,-0.1609777490365909,-1.862645149230957e-9]],[[-6.5,-0.1609777490365909,-1.862645149230957e-9],[-6.679999999818392,-0.010977749036589657,0]],[[-6.679999999818392,-0.010977749036589657,0],[-6.679999999818392,-0.33097774903658994,0]]]},{"elementId":"0x20000000f1d","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.380000000004657,-0.08497774903400668,-1.862645149230957e-9],[10.380000000004657,-0.18497774903400632,-1.862645149230957e-9],[10.888796739047393,-0.01538053204497114,-9.313225746154785e-10]],[[10.888796739047393,-0.01538053204497114,-9.313225746154785e-10],[10.380000000004657,-0.08497774903400668,-1.862645149230957e-9]],[[10.380000000004657,-0.08497774903400668,-1.862645149230957e-9],[10.888796739047393,0.08461946795502762,-9.313225746154785e-10],[10.888796739047393,-0.01538053204497114,-9.313225746154785e-10]],[[10.380000000004657,-0.08497774903400668,-1.862645149230957e-9],[10.888796739047393,-0.01538053204497114,-9.313225746154785e-10]]]},{"elementId":"0x20000000f92","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.14999999999609415,9.313225746154785e-10],[9.880000000004657,-0.17399999999609417,-9.313225746154785e-10]],[[9.880000000004657,-0.17399999999609417,-9.313225746154785e-10],[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10]],[[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10],[8.680000000051223,-0.049999999996093614,9.313225746154785e-10]],[[8.680000000051223,-0.049999999996093614,9.313225746154785e-10],[8.680000000051223,-0.14999999999609415,9.313225746154785e-10]],[[8.680000000051223,-0.14999999999609415,9.313225746154785e-10],[8.680000000051223,-0.049999999996093614,9.313225746154785e-10]],[[8.680000000051223,-0.049999999996093614,9.313225746154785e-10],[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10]],[[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10],[8.680000000051223,-0.14999999999609415,9.313225746154785e-10]],[[9.880000000004657,-0.17399999999609417,-9.313225746154785e-10],[8.680000000051223,-0.14999999999609415,9.313225746154785e-10]],[[8.680000000051223,-0.14999999999609415,9.313225746154785e-10],[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10]],[[9.880000000004657,-0.07399999999609363,-9.313225746154785e-10],[9.880000000004657,-0.17399999999609417,-9.313225746154785e-10]]]},{"elementId":"0x20000000fa5","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[10.380000000004657,-0.18399999999609395,0],[10.885664732661098,-0.015446774683195663,9.313225746154785e-10]],[[10.885664732661098,-0.015446774683195663,9.313225746154785e-10],[10.885664732661098,0.0845532253168031,9.313225746154785e-10]],[[10.885664732661098,0.0845532253168031,9.313225746154785e-10],[10.380000000004657,-0.08399999999609431,0]],[[10.380000000004657,-0.08399999999609431,0],[10.380000000004657,-0.18399999999609395,0]],[[10.380000000004657,-0.18399999999609395,0],[10.380000000004657,-0.08399999999609431,0]],[[10.380000000004657,-0.08399999999609431,0],[10.885664732661098,0.0845532253168031,9.313225746154785e-10]],[[10.885664732661098,0.0845532253168031,9.313225746154785e-10],[10.380000000004657,-0.18399999999609395,0]],[[10.885664732661098,-0.015446774683195663,9.313225746154785e-10],[10.380000000004657,-0.18399999999609395,0]],[[10.380000000004657,-0.18399999999609395,0],[10.885664732661098,0.0845532253168031,9.313225746154785e-10]],[[10.885664732661098,0.0845532253168031,9.313225746154785e-10],[10.885664732661098,-0.015446774683195663,9.313225746154785e-10]]]},{"elementId":"0x20000000fa3","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[10.885664732661098,0.0845532253168031,9.313225746154785e-10],[10.380000000004657,-0.08399999999609431,0]]]},{"elementId":"0x20000000f96","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[10.380000000004657,-0.08399999999609431,0],[9.880000000004657,-0.07399999999609363,9.313225746154785e-10]]]},{"elementId":"0x20000000f94","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[8.680000000167638,-0.049999999996093614,9.313225746154785e-10],[6.680000000284053,-0.009999999996093578,0]]]},{"elementId":"0x20000000f9f","categoryId":"0x20000000199","modelId":"0x200000003c7","geometries":[[[-10.379999999888241,-0.08399999999890717,0],[-11.214947268133983,0.19431297293451877,-9.313225746154785e-10]],[[-11.214947268133983,0.19431297293451877,-9.313225746154785e-10],[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10]],[[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10],[-10.379999999888241,-0.18399999999890504,0]],[[-10.379999999888241,-0.18399999999890504,0],[-10.379999999888241,-0.08399999999890717,0]],[[-10.379999999888241,-0.08399999999890717,0],[-10.379999999888241,-0.18399999999890504,0]],[[-10.379999999888241,-0.18399999999890504,0],[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10]],[[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10],[-10.379999999888241,-0.08399999999890717,0]],[[-11.214947268133983,0.19431297293451877,-9.313225746154785e-10],[-10.379999999888241,-0.08399999999890717,0]],[[-10.379999999888241,-0.08399999999890717,0],[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10]],[[-11.214947268133983,0.09431297293452001,-9.313225746154785e-10],[-11.214947268133983,0.19431297293451877,-9.313225746154785e-10]]]},{"elementId":"0x20000000f9d","categoryId":"0x20000000147","modelId":"0x200000003c7","geometries":[[[-11.214947268133983,0.19431297293451877,-9.313225746154785e-10],[-10.379999999888241,-0.08399999999890628,0]]]},{"elementId":"0x20000000f81","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[-8.679999999818392,-0.04999999999890559,0],[-9.879999999888241,-0.07399999999890561,0]],[[-9.879999999888241,-0.07399999999890561,0],[-9.879999999888241,-0.17399999999890614,0]],[[-9.879999999888241,-0.17399999999890614,0],[-8.679999999818392,-0.14999999999890612,0]],[[-8.679999999818392,-0.14999999999890612,0],[-8.679999999818392,-0.04999999999890559,0]],[[-8.679999999818392,-0.04999999999890559,0],[-8.679999999818392,-0.14999999999890612,0]],[[-8.679999999818392,-0.14999999999890612,0],[-9.879999999888241,-0.17399999999890614,0]],[[-9.879999999888241,-0.17399999999890614,0],[-8.679999999818392,-0.04999999999890559,0]],[[-9.879999999888241,-0.07399999999890561,0],[-8.679999999818392,-0.04999999999890559,0]],[[-8.679999999818392,-0.04999999999890559,0],[-9.879999999888241,-0.17399999999890614,0]],[[-9.879999999888241,-0.17399999999890614,0],[-9.879999999888241,-0.07399999999890561,0]]]},{"elementId":"0x20000000f82","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-8.679999999934807,-0.04999999999890559,-9.313225746154785e-10],[-6.679999999818392,-0.009999999998905551,-1.862645149230957e-9]]]},{"elementId":"0x20000000f83","categoryId":"0x20000000253","modelId":"0x200000003c7","geometries":[[[-10.379999999888241,-0.08399999999890628,0],[-9.880000000004657,-0.07399999999890561,0]]]},{"elementId":"0x20000000f85","categoryId":"0x20000000153","modelId":"0x200000003c7","geometries":[[[-5.999999999883585,-0.11999999999890676,0],[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10]],[[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10],[-6.529999999911524,-0.009999999998905551,0]],[[-6.529999999911524,-0.009999999998905551,0],[-6.679999999818392,-0.009999999998905551,0]],[[-6.679999999818392,-0.009999999998905551,0],[-6.679999999818392,-0.32999999999890495,0]],[[-6.679999999818392,-0.32999999999890495,0],[-5.999999999883585,-0.32999999999890495,0]],[[-5.999999999883585,-0.32999999999890495,0],[-5.999999999883585,-0.11999999999890676,0]],[[-6.529999999911524,-0.009999999998905551,0],[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10]],[[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10],[-6.679999999818392,-0.009999999998905551,0]],[[-6.679999999818392,-0.009999999998905551,0],[-6.529999999911524,-0.009999999998905551,0]],[[-6.679999999818392,-0.32999999999890495,0],[-6.679999999818392,-0.009999999998905551,0]],[[-6.679999999818392,-0.009999999998905551,0],[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10]],[[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10],[-6.679999999818392,-0.32999999999890495,0]],[[-6.679999999818392,-0.32999999999890495,0],[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10]],[[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10],[-5.999999999883585,-0.32999999999890495,0]],[[-5.999999999883585,-0.32999999999890495,0],[-6.679999999818392,-0.32999999999890495,0]],[[-5.999999999883585,-0.11999999999890676,0],[-5.999999999883585,-0.32999999999890495,0]],[[-5.999999999883585,-0.32999999999890495,0],[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10]],[[-6.499999999883585,-0.15999999999890502,-9.313225746154785e-10],[-5.999999999883585,-0.11999999999890676,0]]]},{"elementId":"0x20000000f17","categoryId":"0x20000000183","modelId":"0x200000003c7","geometries":[[[8.680000000051223,-0.05097774903400598,-1.862645149230957e-9],[8.680000000051223,-0.15097774903400651,-1.862645149230957e-9],[9.880000000004657,-0.17497774903400565,-1.862645149230957e-9]],[[9.880000000004657,-0.17497774903400565,-1.862645149230957e-9],[8.680000000051223,-0.05097774903400598,-1.862645149230957e-9]],[[8.680000000051223,-0.05097774903400598,-1.862645149230957e-9],[9.880000000004657,-0.074977749034006,-1.862645149230957e-9],[9.880000000004657,-0.17497774903400565,-1.862645149230957e-9]],[[8.680000000051223,-0.05097774903400598,-1.862645149230957e-9],[9.880000000004657,-0.17497774903400565,-1.862645149230957e-9]]]}]}] \ No newline at end of file +[ + { + "sourceId": "0x20000000f71", + "distanceAlong": 0, + "ray": { + "origin": [508065.00303496333, 6645747.0143687865, 5.68931356159401], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x2000000251f", + "categoryId": "0x20000000325", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.309597260551527, 11.920265698326453, -9.313225746154785e-10], + [-21.33814022457227, 12.089129285321263, -1.862645149230957e-9], + [-24.999999999650754, 11.929871822407076, -1.862645149230957e-9] + ], + [ + [-24.999999999650754, 11.70139930111667, 0], + [-21.31668586714659, 11.860715112107197, -9.313225746154785e-10], + [-21.309597260551527, 11.920265698326453, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000ff7", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.43631041904140133, 0], + [22.056361284456216, -0.40630544087528264, 9.313225746154785e-10], + [16.147139406879432, -0.3219719019683067, -9.313225746154785e-10], + [15.132645385456271, -0.3056930230513286, 0], + [12.055327196256258, -0.253085721444374, 0], + [2.0542931078234687, -0.04858841566853389, 9.313225746154785e-10], + [7.695052772760391e-8, 0.0039498092831484755, 0], + [7.695052772760391e-8, -0.03605019071685156, 0], + [2.0542931078234687, -0.08858841566853393, 9.313225746154785e-10], + [12.055327196256258, -0.29308572144437317, 0], + [15.132645385456271, -0.34569302305132865, 0], + [16.147139406879432, -0.36197190196830764, -9.313225746154785e-10], + [22.056361284456216, -0.4463054408752827, 9.313225746154785e-10], + [24.999999999883585, -0.47631041904140137, 0] + ] + ] + }, + { + "elementId": "0x20000000ff9", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.47631041904140137, 0], + [22.056361284456216, -0.4463054408752827, 9.313225746154785e-10], + [16.147139406879432, -0.36197190196830764, -9.313225746154785e-10], + [15.132645385456271, -0.34569302305132954, 0], + [12.055327196256258, -0.29308572144437317, 0], + [2.0542931078234687, -0.08858841566853481, 9.313225746154785e-10], + [7.695052772760391e-8, -0.036050190716853336, 0], + [7.695052772760391e-8, -0.1860501907168537, 0], + [2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10], + [12.055327196256258, -0.4430857214443753, 0], + [15.132645385456271, -0.4956930230513299, 0], + [16.147139406879432, -0.5119719019683071, -9.313225746154785e-10], + [22.056361284456216, -0.596305440875283, 9.313225746154785e-10], + [24.999999999883585, -0.6263104190414026, 0] + ] + ] + }, + { + "elementId": "0x20000000ffb", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.6263104190414017, 0], + [22.056361284456216, -0.596305440875283, 9.313225746154785e-10], + [16.147139406879432, -0.5119719019683071, -9.313225746154785e-10], + [15.132645385456271, -0.4956930230513299, 0], + [12.055327196256258, -0.4430857214443753, 0], + [2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10], + [7.695052772760391e-8, -0.1860501907168537, 0], + [7.695052772760391e-8, -0.386050190716853, 0], + [2.0542931078234687, -0.43858841566853535, 9.313225746154785e-10], + [12.055327196256258, -0.6430857214443746, 0], + [15.132645385456271, -0.6956930230513292, 0], + [16.147139406879432, -0.7119719019683073, -9.313225746154785e-10], + [22.056361284456216, -0.7963054408752841, 9.313225746154785e-10], + [24.999999999883585, -0.8263104190414028, 0] + ] + ] + }, + { + "elementId": "0x20000000fff", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-15.859479100327007, 0.24273002498905605, 0], + [-17.947775068460032, 0.31198164748942947, -9.313225746154785e-10], + [-24.999999999883585, 0.5677002788677514, 0] + ], + [ + [-25, 0.7489401965574727, -9.313225746154785e-10], + [-17.947775068343617, 0.5013344678828959, -9.313225746154785e-10], + [-15.859479100327007, 0.43448522791356137, 0] + ] + ] + }, + { + "elementId": "0x20000002525", + "categoryId": "0x2000000032b", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.780904921120964, 12.861791405043807, -9.313225746154785e-10], + [-21.789858330157585, 12.86956032503004, -1.862645149230957e-9], + [-21.802550818421878, 12.88066022244428, 0], + [-21.954314876929857, 12.879165069859074, -9.313225746154785e-10], + [-22.0804018083727, 12.878036511133136, 0], + [-22.092661482281983, 12.866303068942944, -9.313225746154785e-10], + [-22.102102481527254, 12.859073650031558, 0], + [-22.122556253219955, 12.691610429392252, 9.313225746154785e-10], + [-22.159407244995236, 12.385707666906114, 0], + [-22.17524986958597, 12.35070784902479, -9.313225746154785e-10], + [-22.196215688600205, 12.330766938884697, -9.313225746154785e-10], + [-22.194328614044935, 12.30820463059127, 0], + [-22.214426882448606, 12.263424855605749, -9.313225746154785e-10], + [-22.250542386667803, 12.217219808593622, 0], + [-22.310210896888748, 12.13960101119519, 0], + [-22.305738903814927, 12.080095888556123, -9.313225746154785e-10], + [-22.305362391169183, 12.046420798394731, 0], + [-22.016940460540354, 12.058755775962776, -9.313225746154785e-10], + [-21.810020496021025, 12.067788405595405, -9.313225746154785e-10], + [-21.812365179648623, 12.263115616705043, 0], + [-21.816983875934966, 12.54396206488616, 0], + [-21.799688460538164, 12.557083743688562, 0], + [-21.77341440867167, 12.576102172924184, -9.313225746154785e-10], + [-21.775930330040865, 12.693170305172938, -9.313225746154785e-10], + [-21.780904921120964, 12.861791405043807, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x200000025c2", + "categoryId": "0x20000000329", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.61189473886043, 11.848987561140202, -1.862645149230957e-9], + [-22.193277208018117, 11.82371376758709, 0], + [-22.192129198578186, 11.798743681702902, 0], + [-22.225849510519765, 11.797277796091816, -9.313225746154785e-10], + [-22.29781346663367, 10.648233753169766, 0], + [-22.589239793014713, 10.585524916534677, 0], + [-22.885258157271892, 10.622696423379715, 0], + [-23.062379766604863, 11.760912246496144, 0], + [-23.096100079012103, 11.759446360862054, -9.313225746154785e-10], + [-23.097248088102788, 11.784416446746484, -9.313225746154785e-10], + [-23.678630557027645, 11.759142653185911, 0], + [-23.675186529173516, 11.684232395572554, 0], + [-23.27663874591235, 11.701558020134758, -1.862645149230957e-9], + [-23.15837606182322, 11.631639146276054, 0], + [-22.949542722548358, 10.289637957472351, -9.313225746154785e-10], + [-22.203221454867162, 10.322081952008123, -9.313225746154785e-10], + [-22.118373121949844, 11.676850037567103, -9.313225746154785e-10], + [-22.006998493918218, 11.756751678947065, -9.313225746154785e-10], + [-21.608450710773468, 11.774077303520965, -9.313225746154785e-10], + [-21.61189473886043, 11.848987561140202, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.36501718623917956, 0], + [-13.965304459095933, 0.3773465961386817, 0], + [-13.965304459095933, 0.33734659613868256, 0], + [-13.560657557449304, 0.32501718623917863, 0], + [-13.21495238353964, 0.31453340329701174, 0], + [-12.749161509796977, 0.3004772233202271, 0], + [-11.556745232548565, 0.26536794189919544, 0], + [-11.317022527451627, 0.2581691636677146, 0], + [-10.523360020597465, 0.23481056174965165, 0], + [-10.412220384343527, 0.23137165663719106, -9.313225746154785e-10], + [-8.93376574816648, 0.18978392633499386, -9.313225746154785e-10], + [-8.900657587801106, 0.1887610140821181, -9.313225746154785e-10], + [-8.864327007555403, 0.1877605621898768, -9.313225746154785e-10], + [-7.993680467130616, 0.16327686679037523, 0], + [-7.954276460572146, 0.16256610885502543, -9.313225746154785e-10], + [-5.506849944475107, 0.0967532445200332, 0], + [-5.480727260117419, 0.0964170635489463, 0], + [-3.898698852164671, 0.05541856261882838, 0], + [-3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10], + [-3.77053390792571, 0.05476232726746133, 0], + [-2.8965330155333504, 0.03206737034783469, 0], + [-0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10], + [-1.1641532182693481e-10, 0, 9.313225746154785e-10], + [-0.4447324851062149, 0.010581322317988473, -9.313225746154785e-10], + [-2.8965330155333504, 0.07206737034783561, 0], + [-3.77053390792571, 0.09476232726746137, 0], + [-3.8841997728450224, 0.09530717370141062, -9.313225746154785e-10], + [-3.898698852164671, 0.09541856261882753, 0], + [-5.480727260233834, 0.13641706354894634, 0], + [-5.506849944475107, 0.13675324452003323, 0], + [-7.954276460572146, 0.20256610885502546, -9.313225746154785e-10], + [-7.993680467130616, 0.20327686679037527, 0], + [-8.864327007555403, 0.22776056218987684, -9.313225746154785e-10], + [-8.900657587801106, 0.22876101408211724, -9.313225746154785e-10], + [-8.93376574816648, 0.2297839263349939, -9.313225746154785e-10], + [-10.412220384576358, 0.2713716566371911, 0], + [-10.523360020597465, 0.2748105617496517, 0], + [-11.317022527451627, 0.2981691636677155, 0], + [-11.556745232548565, 0.30536794189919547, 0], + [-12.749161509796977, 0.340477223320228, 0], + [-13.21495238353964, 0.3545334032970109, 0], + [-13.560657557449304, 0.36501718623917956, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.32501718623917863, 0], + [-13.965304459095933, 0.33734659613868256, 0], + [-13.965304459095933, 0.1873465961386822, 0], + [-13.560657557449304, 0.17501718623918006, 0], + [-13.21495238353964, 0.16453340329701138, 0], + [-12.749161509796977, 0.15047722332022762, 0], + [-11.556745232548565, 0.11536794189919597, 0], + [-11.317022527451627, 0.10816916366771512, 0], + [-10.523360020597465, 0.08481056174965129, 0], + [-10.412220384343527, 0.08137165663718982, -9.313225746154785e-10], + [-8.93376574816648, 0.039783926334992614, -9.313225746154785e-10], + [-8.900657587801106, 0.03876101408211685, -9.313225746154785e-10], + [-8.864327007555403, 0.03776056218987467, -9.313225746154785e-10], + [-7.993680467130616, 0.013276866790373987, 0], + [-7.954276460572146, 0.012566108855024183, -9.313225746154785e-10], + [-5.506849944475107, -0.053246755479968044, 0], + [-5.480727260117419, -0.05358293645105494, 0], + [-3.898698852164671, -0.09458143738117109, 0], + [-3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10], + [-3.77053390792571, -0.09523767273253814, 0], + [-2.8965330155333504, -0.11793262965216389, 0], + [-0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10], + [-1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10], + [-0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10], + [-2.8965330155333504, 0.03206737034783469, 0], + [-3.77053390792571, 0.05476232726746133, 0], + [-3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10], + [-3.898698852164671, 0.05541856261882838, 0], + [-5.480727260233834, 0.0964170635489463, 0], + [-5.506849944475107, 0.0967532445200332, 0], + [-7.954276460572146, 0.16256610885502543, -9.313225746154785e-10], + [-7.993680467130616, 0.16327686679037523, 0], + [-8.864327007555403, 0.1877605621898768, -9.313225746154785e-10], + [-8.900657587801106, 0.1887610140821181, -9.313225746154785e-10], + [-8.93376574816648, 0.18978392633499386, -9.313225746154785e-10], + [-10.412220384576358, 0.23137165663719106, 0], + [-10.523360020597465, 0.23481056174965165, 0], + [-11.317022527451627, 0.2581691636677146, 0], + [-11.556745232548565, 0.26536794189919544, 0], + [-12.749161509796977, 0.3004772233202271, 0], + [-13.21495238353964, 0.31453340329701174, 0], + [-13.560657557449304, 0.32501718623917863, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.17501718623918006, 0], + [-13.965304459095933, 0.1873465961386822, 0], + [-13.965304459095933, -0.012653403861317969, 0], + [-13.560657557449304, -0.02498281376082101, 0], + [-13.21495238353964, -0.03546659670298968, 0], + [-12.749161509796977, -0.04952277667977345, 0], + [-11.556745232548565, -0.08463205810080421, 0], + [-11.317022527451627, -0.09183083633228506, 0], + [-10.523360020597465, -0.11518943825034889, 0], + [-10.412220384343527, -0.11862834336280859, -9.313225746154785e-10], + [-8.93376574816648, -0.16021607366500756, -9.313225746154785e-10], + [-8.900657587801106, -0.16123898591788244, -9.313225746154785e-10], + [-8.864327007555403, -0.1622394378101255, -9.313225746154785e-10], + [-7.993680467130616, -0.18672313320962708, 0], + [-7.954276460572146, -0.187433891144976, -9.313225746154785e-10], + [-5.506849944475107, -0.2532467554799682, 0], + [-5.480727260117419, -0.2535829364510551, 0], + [-3.898698852164671, -0.29458143738117215, 0], + [-3.8841997728450224, -0.29469282629858995, -9.313225746154785e-10], + [-3.77053390792571, -0.2952376727325392, 0], + [-2.8965330155333504, -0.31793262965216584, 0], + [-0.4447324851062149, -0.379418677682013, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.39000000000000057, 9.313225746154785e-10], + [-1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10], + [-0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10], + [-2.8965330155333504, -0.11793262965216389, 0], + [-3.77053390792571, -0.09523767273253814, 0], + [-3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10], + [-3.898698852164671, -0.09458143738117109, 0], + [-5.480727260233834, -0.05358293645105494, 0], + [-5.506849944475107, -0.053246755479968044, 0], + [-7.954276460572146, 0.012566108855024183, -9.313225746154785e-10], + [-7.993680467130616, 0.013276866790373987, 0], + [-8.864327007555403, 0.03776056218987467, -9.313225746154785e-10], + [-8.900657587801106, 0.03876101408211685, -9.313225746154785e-10], + [-8.93376574816648, 0.039783926334992614, -9.313225746154785e-10], + [-10.412220384576358, 0.0813716566371907, 0], + [-10.523360020597465, 0.08481056174965129, 0], + [-11.317022527451627, 0.10816916366771512, 0], + [-11.556745232548565, 0.11536794189919597, 0], + [-12.749161509796977, 0.15047722332022762, 0], + [-13.21495238353964, 0.16453340329701138, 0], + [-13.560657557449304, 0.17501718623918006, 0] + ] + ] + }, + { + "elementId": "0x20000001047", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-14.629234474035911, 0.39593035363518947, -1.862645149230957e-9], + [-15.020279791089706, 0.40860511585720527, -9.313225746154785e-10], + [-15.859479100327007, 0.434485227954001, 0], + [-15.859479100443423, 0.24273002499550778, 0], + [-15.515034026349895, 0.229057381444421, -9.313225746154785e-10], + [-14.629234474268742, 0.19660126485857976, -9.313225746154785e-10], + [-13.965304456767626, 0.16734659604119706, 0], + [-13.965304456884041, 0.377346596041197, 0], + [-14.629234474035911, 0.39593035363518947, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x200000025bf", + "categoryId": "0x20000000329", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-23.717762321117334, 11.757671543662408, 0], + [-24.301593580050394, 11.732228036294664, 0], + [-24.300440740655176, 11.707258285300973, -9.313225746154785e-10], + [-24.334303083014674, 11.705782556229131, -9.313225746154785e-10], + [-24.406570418039337, 10.556717494419264, 0], + [-24.69922424782999, 10.493923585774699, -9.313225746154785e-10], + [-24.996489433106035, 10.531008681171187, -9.313225746154785e-10], + [-24.999999999650754, 10.553472614613835, 0] + ], + [ + [-24.999999999650754, 10.20059179534578, 0], + [-24.311580060399137, 10.230593302678546, -1.862645149230957e-9], + [-24.226374032441527, 11.585386170316227, 0], + [-24.11453027499374, 11.665320324314234, -9.313225746154785e-10], + [-23.714303803630173, 11.682762290660467, -9.313225746154785e-10], + [-23.717762321117334, 11.757671543662408, 0] + ] + ] + } + ] + }, + { + "sourceId": "0x20000000f71", + "distanceAlong": 10, + "ray": { + "origin": [508066.7858571931, 6645756.854162732, 5.483521231404236], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000000a16", + "categoryId": "0x20000000183", + "modelId": "0x200000003c3", + "geometries": [ + [ + [-24.712078254204243, 12.229065306170728, -1.862645149230957e-9], + [-24.712078254204243, 9.439300229625651, -1.862645149230957e-9], + [-24.712078254204243, -0.04962572769248297, -1.862645149230957e-9], + [-24.999999999883585, -0.05862859917218266, -9.313225746154785e-10] + ], + [ + [-24.99999999976717, -0.6086964001481494, -9.313225746154785e-10], + [-24.905035979347304, -0.6057454895855674, -9.313225746154785e-10], + [-23.677354383165948, -0.5673994461203868, -9.313225746154785e-10], + [-23.677354383165948, -0.16739944612038382, -9.313225746154785e-10], + [-23.931223444873467, -0.17532892392315524, -3.725290298461914e-9], + [-24.200328385224566, -0.18367852391556472, -9.313225746154785e-10], + [-24.274962203926407, 6.2351032033325335, -1.862645149230957e-9], + [-24.35399462026544, 13.032284360849353, -1.862645149230957e-9], + [-24.70277738769073, 13.029148948575045, -1.862645149230957e-9], + [-24.712078254204243, 12.229065306170728, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000a1e", + "categoryId": "0x20000000187", + "modelId": "0x200000003c3", + "geometries": [ + [ + [-24.71207825327292, 12.229065306219276, -9.313225746154785e-10], + [-24.99999999976717, 12.216575559213922, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000232831, -0.12000000000499345, -9.313225746154785e-10], + [-6.000000000232831, -0.16000000000499348, -9.313225746154785e-10], + [0, -0.040000000000000036, 0], + [6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9], + [6.0098497840808704, -0.12025174434887376, -1.862645149230957e-9], + [0, 0, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000232831, -0.16000000000499348, -9.313225746154785e-10], + [-6.000000000232831, -0.31000000000499295, -9.313225746154785e-10], + [0, -0.1899999999999995, 0], + [6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9], + [6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1899999999999995, 0], + [-6.000000000232831, -0.31000000000499295, -9.313225746154785e-10], + [-6.000000000232831, -0.510000000004994, -9.313225746154785e-10], + [0, -0.39000000000000057, 0], + [6.0098497840808704, -0.5102517443488743, -1.862645149230957e-9], + [6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9], + [0, -0.1899999999999995, 0] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000237487, -0.08400000000499297, 0], + [-11.052264821715653, 0.1400860329075968, 0], + [-11.052264821715653, 0.04008603290759538, 0], + [-10.380000000237487, -0.1840000000049944, 0], + [-10.380000000237487, -0.08400000000499297, 0] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [[[-11.052264821715653, 0.1400860329075968, 0], [-10.380000000237487, -0.08400000000499297, 0]]] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000499227, 9.313225746154785e-10], + [-9.880000000121072, -0.0740000000049923, -9.313225746154785e-10], + [-9.880000000121072, -0.17400000000499372, -9.313225746154785e-10], + [-8.680000000284053, -0.1500000000049937, 9.313225746154785e-10], + [-8.680000000284053, -0.05000000000499227, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000499227, 0], + [-6.680000000284053, -0.010000000004992238, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [[[-10.380000000237487, -0.08400000000499297, 0], [-9.880000000353903, -0.0740000000049923, 0]]] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6, -0.12000000000499433, -9.313225746154785e-10], + [-6.500000000349246, -0.16000000000499437, 0], + [-6.53000000002794, -0.010000000004994014, -9.313225746154785e-10], + [-6.680000000167638, -0.010000000004994014, 9.313225746154785e-10], + [-6.680000000167638, -0.3300000000049934, 9.313225746154785e-10], + [-6, -0.3300000000049934, -9.313225746154785e-10], + [-6, -0.12000000000499433, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000102d", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.009849783964455, -0.3302517155538194, -1.862645149230957e-9], + [6.5050995904020965, -0.3302517155538194, -1.862645149230957e-9], + [6.689849783782847, -0.32992302906745863, -9.313225746154785e-10], + [6.689849783782847, -0.009923029067459233, -9.313225746154785e-10], + [6.6468152336310595, -0.009999591230094751, -1.862645149230957e-9], + [6.539849783643149, -0.009999591243764705, 0], + [6.5098497837316245, -0.1600146135503513, -9.313225746154785e-10], + [6.152845289441757, -0.13145425399504784, -9.313225746154785e-10], + [6.009849783964455, -0.12025171555381853, -1.862645149230957e-9], + [6.009849783964455, -0.3302517155538194, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001029", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.689849783782847, -0.009923029067458344, -9.313225746154785e-10], + [7.432176180649549, -0.023448894482823057, -1.862645149230957e-9], + [8.689849783666432, -0.048602366564344024, 0] + ] + ] + }, + { + "elementId": "0x20000001027", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [9.222578136483207, -0.15805021063472324, -1.862645149230957e-9], + [9.889849783852696, -0.1713956435702162, -9.313225746154785e-10], + [9.889849783852696, -0.07139564357021566, -9.313225746154785e-10], + [9.222578136483207, -0.05805021063472271, -1.862645149230957e-9], + [8.689849783899263, -0.04860236656434491, 0], + [8.689849783899263, -0.14860236656434544, 0], + [9.222578136483207, -0.15805021063472324, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x2000000102b", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [9.889849783736281, -0.0713956435570493, -9.313225746154785e-10], + [10.131568165728822, -0.07557511702494502, -9.313225746154785e-10], + [10.389849783852696, -0.08074074936673448, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000001025", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.389849783852696, -0.08074074938234865, -9.313225746154785e-10], + [10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10], + [10.860269933007658, 0.07677824947917156, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000102f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.631802612915635, -0.09937676230103598, -9.313225746154785e-10], + [10.860269933007658, -0.0232217505208272, -9.313225746154785e-10], + [10.860269933007658, 0.07677824947917156, -9.313225746154785e-10], + [10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10], + [10.389849783852696, -0.08074074938234865, -9.313225746154785e-10], + [10.389849783852696, -0.18074074938234652, -9.313225746154785e-10], + [10.631802612915635, -0.09937676230103598, -9.313225746154785e-10] + ] + ] + } + ] + }, + { + "sourceId": "0x20000000f71", + "distanceAlong": 20, + "ray": { + "origin": [508068.5686794229, 6645766.693956678, 5.277728901214461], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000349246, -0.12000000000384681, 9.313225746154785e-10], + [-6.000000000349246, -0.16000000000384684, 9.313225746154785e-10], + [0, -0.040000000000000036, 0], + [5.999999999650754, -0.15999999999926562, 1.862645149230957e-9], + [5.999999999650754, -0.11999999999926558, 1.862645149230957e-9], + [0, 0, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000349246, -0.16000000000384684, 9.313225746154785e-10], + [-6.000000000349246, -0.3100000000038481, 9.313225746154785e-10], + [0, -0.1900000000000004, 0], + [5.999999999650754, -0.309999999999266, 1.862645149230957e-9], + [5.999999999650754, -0.15999999999926562, 1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1900000000000004, 0], + [-6.000000000349246, -0.3100000000038481, 9.313225746154785e-10], + [-6.000000000349246, -0.5100000000038483, 9.313225746154785e-10], + [0, -0.39000000000000057, 0], + [5.999999999650754, -0.5099999999992653, 1.862645149230957e-9], + [5.999999999650754, -0.309999999999266, 1.862645149230957e-9], + [0, -0.1900000000000004, 0] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9], + [6.679999999701977, -0.32999999999926555, 1.862645149230957e-9], + [6.679999999701977, -0.009999999999265263, 1.862645149230957e-9], + [6.529999999795109, -0.009999999999265263, 1.862645149230957e-9], + [6.499999999767169, -0.15999999999926562, 2.7939677238464355e-9], + [5.999999999767169, -0.11999999999926558, 2.7939677238464355e-9], + [5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999926583, 0], + [9.879999999888241, -0.17399999999926585, 1.862645149230957e-9], + [9.879999999888241, -0.07399999999926443, 1.862645149230957e-9], + [8.680000000051223, -0.04999999999926441, 0], + [8.680000000051223, -0.14999999999926583, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999771826, -0.18399999999926564, 9.313225746154785e-10], + [10.85427225427702, -0.025910829392767454, 1.862645149230957e-9], + [10.85427225427702, 0.07408917060723219, 1.862645149230957e-9], + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10], + [10.379999999771826, -0.18399999999926564, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.85427225427702, 0.07408917060723219, 1.862645149230957e-9], + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10], + [9.879999999888241, -0.07399999999926443, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.04999999999926441, 0], + [6.679999999701977, -0.009999999999265263, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9], + [-10.452001590980217, -0.059999709788664646, 1.862645149230957e-9], + [-10.452001590980217, -0.1599997097886634, 1.862645149230957e-9], + [-10.380000000470318, -0.18400000000384864, 2.7939677238464355e-9], + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.452001590980217, -0.059999709788664646, 1.862645149230957e-9], + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000384741, 1.862645149230957e-9], + [-9.880000000353903, -0.07400000000384743, 9.313225746154785e-10], + [-9.880000000353903, -0.17400000000384797, 9.313225746154785e-10], + [-8.680000000284053, -0.15000000000384794, 1.862645149230957e-9], + [-8.680000000284053, -0.05000000000384741, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000167638, -0.05000000000384652, 1.862645149230957e-9], + [-6.680000000167638, -0.010000000003847376, 0] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000237487, -0.08400000000384722, 9.313225746154785e-10], + [-9.880000000353903, -0.07400000000384743, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.000000000232831, -0.12000000000384681, 1.862645149230957e-9], + [-6.500000000116415, -0.16000000000384684, 9.313225746154785e-10], + [-6.530000000377186, -0.010000000003847376, 1.862645149230957e-9], + [-6.680000000284053, -0.010000000003847376, 9.313225746154785e-10], + [-6.680000000284053, -0.33000000000384766, 9.313225746154785e-10], + [-6.000000000232831, -0.33000000000384766, 1.862645149230957e-9], + [-6.000000000232831, -0.12000000000384681, 1.862645149230957e-9] + ] + ] + } + ] + }, + { + "sourceId": "0x20000000f71", + "distanceAlong": 30, + "ray": { + "origin": [508070.3515016527, 6645776.533750624, 5.071936571024687], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9], + [-6.000000000232831, -0.15999999999926562, 1.862645149230957e-9], + [0, -0.040000000000000036, 0], + [6.000000000465661, -0.16000000000270198, 0], + [6.000000000465661, -0.12000000000270195, 0], + [0, 0, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000232831, -0.15999999999926562, 1.862645149230957e-9], + [-6.000000000232831, -0.309999999999266, 1.862645149230957e-9], + [0, -0.1900000000000004, 0], + [6.000000000465661, -0.31000000000270234, 0], + [6.000000000465661, -0.16000000000270198, 0], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1900000000000004, 0], + [-6.000000000232831, -0.309999999999266, 1.862645149230957e-9], + [-6.000000000232831, -0.5099999999992653, 1.862645149230957e-9], + [0, -0.39000000000000057, 0], + [6.000000000465661, -0.5100000000027016, 0], + [6.000000000465661, -0.31000000000270234, 0], + [0, -0.1900000000000004, 0] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000116415, -0.3300000000027019, 1.862645149230957e-9], + [6.680000000284053, -0.3300000000027019, 0], + [6.680000000284053, -0.010000000002701626, 0], + [6.529999999795109, -0.010000000002701626, 2.7939677238464355e-9], + [6.500000000232831, -0.16000000000270198, 1.862645149230957e-9], + [6.000000000116415, -0.12000000000270195, 1.862645149230957e-9], + [6.000000000116415, -0.3300000000027019, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.1500000000027022, 0], + [9.880000000004657, -0.17400000000270222, 1.862645149230957e-9], + [9.880000000004657, -0.07400000000270168, 1.862645149230957e-9], + [8.680000000167638, -0.05000000000270166, 0], + [8.680000000167638, -0.1500000000027022, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999888241, -0.184000000002702, 9.313225746154785e-10], + [10.788921954343095, -0.04769404485953377, 1.862645149230957e-9], + [10.788921954343095, 0.052305955140465876, 1.862645149230957e-9], + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10], + [10.379999999888241, -0.184000000002702, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.788921954343095, 0.052305955140465876, 1.862645149230957e-9], + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10], + [9.880000000004657, -0.07400000000270168, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.05000000000270166, 0], + [6.680000000167638, -0.010000000002701626, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9], + [-10.684205847093835, 0.017400935047763078, 1.862645149230957e-9], + [-10.684205847093835, -0.08259906495223479, 1.862645149230957e-9], + [-10.380000000121072, -0.18399999999926564, 1.862645149230957e-9], + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.684205847093835, 0.017400935047763966, 1.862645149230957e-9], + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000051223, -0.04999999999926441, 1.862645149230957e-9], + [-9.880000000121072, -0.07399999999926443, 1.862645149230957e-9], + [-9.880000000121072, -0.17399999999926585, 1.862645149230957e-9], + [-8.680000000051223, -0.14999999999926583, 1.862645149230957e-9], + [-8.680000000051223, -0.04999999999926441, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000051223, -0.04999999999926441, 2.7939677238464355e-9], + [-6.679999999934807, -0.009999999999265263, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999771826, -0.08399999999926511, 9.313225746154785e-10], + [-9.879999999888241, -0.07399999999926443, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9], + [-6.5, -0.15999999999926562, 1.862645149230957e-9], + [-6.529999999678694, -0.009999999999265263, 0], + [-6.679999999934807, -0.009999999999265263, 9.313225746154785e-10], + [-6.679999999934807, -0.32999999999926644, 9.313225746154785e-10], + [-6.000000000232831, -0.32999999999926644, 1.862645149230957e-9], + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9] + ] + ] + } + ] + }, + { + "sourceId": "0x20000000f71", + "distanceAlong": 40, + "ray": { + "origin": [508071.60238111287, 6645786.443305271, 4.866144240834913], + "direction": [0.03269890991174909, 0.9994652476652619, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, 0, -9.313225746154785e-10], + [-6.000000000058208, -0.11999999999991129, 9.313225746154785e-10], + [-6.000000000058208, -0.15999999999991132, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10], + [6, -0.15999999999991132, -9.313225746154785e-10], + [6, -0.11999999999991129, -9.313225746154785e-10], + [1.1641532182693481e-10, 0, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10], + [-6.000000000058208, -0.15999999999991132, 9.313225746154785e-10], + [-6.000000000058208, -0.30999999999991257, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10], + [6, -0.30999999999991257, -9.313225746154785e-10], + [6, -0.15999999999991132, -9.313225746154785e-10], + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10], + [-6.000000000058208, -0.30999999999991257, 9.313225746154785e-10], + [-6.000000000058208, -0.5099999999999127, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39000000000000057, -9.313225746154785e-10], + [6, -0.5099999999999127, -9.313225746154785e-10], + [6, -0.30999999999991257, -9.313225746154785e-10], + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000058208, -0.32999999999991125, 9.313225746154785e-10], + [6.680000000051223, -0.32999999999991125, 9.313225746154785e-10], + [6.680000000051223, -0.009999999999911857, 9.313225746154785e-10], + [6.53000000002794, -0.009999999999911857, 9.313225746154785e-10], + [6.5, -0.15999999999991132, -9.313225746154785e-10], + [6.000000000058208, -0.11999999999991129, 9.313225746154785e-10], + [6.000000000058208, -0.32999999999991125, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999991243, 0], + [9.879999999830034, -0.17399999999991245, 1.862645149230957e-9], + [9.879999999830034, -0.07399999999991191, 1.862645149230957e-9], + [8.680000000051223, -0.04999999999991189, 0], + [8.680000000051223, -0.14999999999991243, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.18399999999991135, 9.313225746154785e-10], + [10.96782595908735, 0.011940026961439365, 2.7939677238464355e-9], + [10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9], + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999991135, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9], + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10], + [9.879999999946449, -0.07399999999991191, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.04999999999991189, 0], + [6.679999999934807, -0.009999999999911857, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000121072, -0.08399999999991348, 1.862645149230957e-9], + [-11.18704475602135, 0.18501222850247867, -9.313225746154785e-10], + [-11.18704475602135, 0.08501222850247814, -9.313225746154785e-10], + [-10.380000000121072, -0.18399999999991135, 1.862645149230957e-9], + [-10.380000000121072, -0.08399999999991348, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-11.18704475602135, 0.18501222850247867, -9.313225746154785e-10], + [-10.380000000121072, -0.08399999999991259, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9], + [-9.880000000121072, -0.07399999999991191, 1.862645149230957e-9], + [-9.880000000121072, -0.17399999999991245, 1.862645149230957e-9], + [-8.679999999993015, -0.14999999999991243, 1.862645149230957e-9], + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9], + [-6.679999999934807, -0.009999999999911857, 0] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [[[-10.380000000004657, -0.08399999999991259, 0], [-9.880000000121072, -0.07399999999991191, 0]]] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6, -0.11999999999991307, -9.313225746154785e-10], + [-6.5, -0.15999999999991132, 1.862645149230957e-9], + [-6.53000000002794, -0.009999999999911857, 0], + [-6.679999999934807, -0.009999999999911857, 0], + [-6.679999999934807, -0.32999999999991125, 0], + [-6, -0.32999999999991125, -9.313225746154785e-10], + [-6, -0.11999999999991307, -9.313225746154785e-10] + ] + ] + } + ] + }, + { + "sourceId": "0x20000000f71", + "distanceAlong": 42.64596001776388, + "ray": { + "origin": [508071.618903467, 6645789.088904963, 4.8116924130704515], + "direction": [-0.020213083931456988, 0.9997956947486721, 0] + }, + "elements": [ + { + "elementId": "0x20000000f3a", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-10.379999999771826, -0.08497774903659039, 9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ], + [ + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10], + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10] + ], + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-11.218174668611027, 0.09441101331197643, -9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ], + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f32", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9], + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-9.880000000004657, -0.07497774903658971, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-8.679999999934807, -0.15097774903658934, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [[0, 0, 0], [-5.999999999883585, -0.11999999999890498, 0]], + [[6.000000000116415, -0.1199999999960717, 1.862645149230957e-9], [0, 0, 0]], + [[-5.999999999883585, -0.15999999999890502, 0], [0, -0.040000000000000036, 0]], + [[0, -0.040000000000000036, 0], [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9]], + [[-5.999999999883585, -0.11999999999890498, 0], [-5.999999999883585, -0.15999999999890502, 0]], + [[-5.999999999883585, -0.11999999999890498, 0], [0, 0, 0]], + [[0, 0, 0], [0, -0.040000000000000036, 0]], + [[0, -0.040000000000000036, 0], [-5.999999999883585, -0.11999999999890498, 0]], + [[-5.999999999883585, -0.15999999999890502, 0], [-5.999999999883585, -0.11999999999890498, 0]], + [[-5.999999999883585, -0.11999999999890498, 0], [0, -0.040000000000000036, 0]], + [[0, -0.040000000000000036, 0], [-5.999999999883585, -0.15999999999890502, 0]], + [[0, 0, 0], [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9]], + [ + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ], + [[6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], [0, 0, 0]], + [[0, -0.040000000000000036, 0], [0, 0, 0]], + [[0, 0, 0], [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9]], + [[6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], [0, -0.040000000000000036, 0]], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [[0, -0.040000000000000036, 0], [-5.999999999883585, -0.15999999999890502, 0]], + [[6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], [0, -0.040000000000000036, 0]], + [[-5.999999999883585, -0.30999999999890626, 0], [0, -0.1900000000000004, 0]], + [[0, -0.1900000000000004, 0], [6.000000000116415, -0.309999999996073, 1.862645149230957e-9]], + [[-5.999999999883585, -0.15999999999890502, 0], [-5.999999999883585, -0.30999999999890626, 0]], + [[-5.999999999883585, -0.15999999999890502, 0], [0, -0.040000000000000036, 0]], + [[0, -0.040000000000000036, 0], [0, -0.1900000000000004, 0]], + [[0, -0.1900000000000004, 0], [-5.999999999883585, -0.15999999999890502, 0]], + [[-5.999999999883585, -0.30999999999890626, 0], [-5.999999999883585, -0.15999999999890502, 0]], + [[-5.999999999883585, -0.15999999999890502, 0], [0, -0.1900000000000004, 0]], + [[0, -0.1900000000000004, 0], [-5.999999999883585, -0.30999999999890626, 0]], + [[0, -0.040000000000000036, 0], [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9]], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ], + [[6.000000000116415, -0.309999999996073, 1.862645149230957e-9], [0, -0.040000000000000036, 0]], + [[0, -0.1900000000000004, 0], [0, -0.040000000000000036, 0]], + [[0, -0.040000000000000036, 0], [6.000000000116415, -0.309999999996073, 1.862645149230957e-9]], + [[6.000000000116415, -0.309999999996073, 1.862645149230957e-9], [0, -0.1900000000000004, 0]], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [[0, -0.1900000000000004, 0], [-5.999999999883585, -0.30999999999890626, 0]], + [[6.000000000116415, -0.309999999996073, 1.862645149230957e-9], [0, -0.1900000000000004, 0]], + [[-5.999999999883585, -0.5099999999989064, 0], [0, -0.39000000000000057, 0]], + [[0, -0.39000000000000057, 0], [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9]], + [[-5.999999999883585, -0.30999999999890626, 0], [-5.999999999883585, -0.5099999999989064, 0]], + [[-5.999999999883585, -0.30999999999890626, 0], [0, -0.1900000000000004, 0]], + [[0, -0.1900000000000004, 0], [0, -0.39000000000000057, 0]], + [[0, -0.39000000000000057, 0], [-5.999999999883585, -0.30999999999890626, 0]], + [[-5.999999999883585, -0.5099999999989064, 0], [-5.999999999883585, -0.30999999999890626, 0]], + [[-5.999999999883585, -0.30999999999890626, 0], [0, -0.39000000000000057, 0]], + [[0, -0.39000000000000057, 0], [-5.999999999883585, -0.5099999999989064, 0]], + [[0, -0.1900000000000004, 0], [6.000000000116415, -0.309999999996073, 1.862645149230957e-9]], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9] + ], + [[6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], [0, -0.1900000000000004, 0]], + [[0, -0.39000000000000057, 0], [0, -0.1900000000000004, 0]], + [[0, -0.1900000000000004, 0], [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9]], + [[6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], [0, -0.39000000000000057, 0]], + [ + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.680000000051223, -0.32999999999609386, 0] + ], + [[6.680000000051223, -0.32999999999609386, 0], [6.680000000051223, -0.009999999996093578, 0]], + [ + [6.680000000051223, -0.009999999996093578, 0], + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9] + ], + [ + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9] + ], + [ + [6.680000000051223, -0.32999999999609386, 0], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.680000000051223, -0.32999999999609386, 0] + ], + [ + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9], + [6.680000000051223, -0.009999999996093578, 0] + ], + [ + [6.680000000051223, -0.009999999996093578, 0], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9] + ], + [ + [6.680000000051223, -0.32999999999609386, 0], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.680000000051223, -0.009999999996093578, 0] + ], + [[6.680000000051223, -0.009999999996093578, 0], [6.680000000051223, -0.32999999999609386, 0]] + ] + }, + { + "elementId": "0x20000000e98", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [-5.999999999883585, -0.3109777490295773, 0], + [-5.999999999883585, -0.5109777490295775, 0] + ], + [[-5.999999999883585, -0.5109777490295775, 0], [1.1641532182693481e-10, -0.19097774901887465, 0]], + [[1.1641532182693481e-10, -0.39097774901887394, 0], [1.1641532182693481e-10, -0.19097774901887465, 0]], + [[1.1641532182693481e-10, -0.19097774901887465, 0], [-5.999999999883585, -0.5109777490295775, 0]], + [[-5.999999999883585, -0.5109777490295775, 0], [1.1641532182693481e-10, -0.39097774901887394, 0]], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [[1.1641532182693481e-10, -0.19097774901887465, 0], [1.1641532182693481e-10, -0.39097774901887394, 0]], + [ + [1.1641532182693481e-10, -0.39097774901887394, 0], + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [6.000000000116415, -0.5109777490340068, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ] + ] + }, + { + "elementId": "0x20000000e96", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [-5.999999999883585, -0.16097774902957607, 0], + [-5.999999999883585, -0.3109777490295773, 0] + ], + [[-5.999999999883585, -0.3109777490295773, 0], [1.1641532182693481e-10, -0.0409777490188743, 0]], + [[1.1641532182693481e-10, -0.19097774901887465, 0], [1.1641532182693481e-10, -0.0409777490188743, 0]], + [[1.1641532182693481e-10, -0.0409777490188743, 0], [-5.999999999883585, -0.3109777490295773, 0]], + [[-5.999999999883585, -0.3109777490295773, 0], [1.1641532182693481e-10, -0.19097774901887465, 0]], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [[1.1641532182693481e-10, -0.0409777490188743, 0], [1.1641532182693481e-10, -0.19097774901887465, 0]], + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ] + ] + }, + { + "elementId": "0x20000000e94", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.0009777490188742632, 0], + [-5.999999999883585, -0.12097774902957692, 0], + [-5.999999999883585, -0.16097774902957607, 0] + ], + [[-5.999999999883585, -0.16097774902957607, 0], [1.1641532182693481e-10, -0.0009777490188742632, 0]], + [[1.1641532182693481e-10, -0.0409777490188743, 0], [1.1641532182693481e-10, -0.0009777490188742632, 0]], + [[1.1641532182693481e-10, -0.0009777490188742632, 0], [-5.999999999883585, -0.16097774902957607, 0]], + [[-5.999999999883585, -0.16097774902957607, 0], [1.1641532182693481e-10, -0.0409777490188743, 0]], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0009777490188742632, 0] + ], + [[1.1641532182693481e-10, -0.0009777490188742632, 0], [1.1641532182693481e-10, -0.0409777490188743, 0]], + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ] + ] + }, + { + "elementId": "0x20000000f1b", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.530000000144355, -0.010977749034005946, -9.313225746154785e-10], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.000000000232831, -0.12097774903400715, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ] + ] + }, + { + "elementId": "0x20000000f38", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.5, -0.1609777490365909, -1.862645149230957e-9], + [-6, -0.12097774903658998, 0], + [-6, -0.33097774903658994, 0] + ], + [[-6.5, -0.1609777490365909, -1.862645149230957e-9], [-6, -0.33097774903658994, 0]], + [[-6.679999999818392, -0.33097774903658994, 0], [-6, -0.33097774903658994, 0]], + [[-6, -0.33097774903658994, 0], [-6.5, -0.1609777490365909, -1.862645149230957e-9]], + [[-6.5, -0.1609777490365909, -1.862645149230957e-9], [-6.679999999818392, -0.33097774903658994, 0]], + [ + [-6.679999999818392, -0.010977749036589657, 0], + [-6.529999999911524, -0.010977749036589657, 0], + [-6.5, -0.1609777490365909, -1.862645149230957e-9] + ], + [[-6.679999999818392, -0.010977749036589657, 0], [-6.5, -0.1609777490365909, -1.862645149230957e-9]], + [[-6.679999999818392, -0.33097774903658994, 0], [-6.5, -0.1609777490365909, -1.862645149230957e-9]], + [[-6.5, -0.1609777490365909, -1.862645149230957e-9], [-6.679999999818392, -0.010977749036589657, 0]], + [[-6.679999999818392, -0.010977749036589657, 0], [-6.679999999818392, -0.33097774903658994, 0]] + ] + }, + { + "elementId": "0x20000000f1d", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.380000000004657, -0.18497774903400632, -1.862645149230957e-9], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ], + [ + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10], + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9] + ], + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.888796739047393, 0.08461946795502762, -9.313225746154785e-10], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ], + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.18399999999609395, 0], + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10] + ], + [ + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.08399999999609431, 0] + ], + [[10.380000000004657, -0.08399999999609431, 0], [10.380000000004657, -0.18399999999609395, 0]], + [[10.380000000004657, -0.18399999999609395, 0], [10.380000000004657, -0.08399999999609431, 0]], + [ + [10.380000000004657, -0.08399999999609431, 0], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999609395, 0] + ], + [ + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999609395, 0] + ], + [ + [10.380000000004657, -0.18399999999609395, 0], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.08399999999609431, 0] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08399999999609431, 0], + [9.880000000004657, -0.07399999999609363, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.049999999996093614, 9.313225746154785e-10], + [6.680000000284053, -0.009999999996093578, 0] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999888241, -0.08399999999890717, 0], + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-10.379999999888241, -0.18399999999890504, 0] + ], + [[-10.379999999888241, -0.18399999999890504, 0], [-10.379999999888241, -0.08399999999890717, 0]], + [[-10.379999999888241, -0.08399999999890717, 0], [-10.379999999888241, -0.18399999999890504, 0]], + [ + [-10.379999999888241, -0.18399999999890504, 0], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890717, 0] + ], + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890717, 0] + ], + [ + [-10.379999999888241, -0.08399999999890717, 0], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890628, 0] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [[-8.679999999818392, -0.04999999999890559, 0], [-9.879999999888241, -0.07399999999890561, 0]], + [[-9.879999999888241, -0.07399999999890561, 0], [-9.879999999888241, -0.17399999999890614, 0]], + [[-9.879999999888241, -0.17399999999890614, 0], [-8.679999999818392, -0.14999999999890612, 0]], + [[-8.679999999818392, -0.14999999999890612, 0], [-8.679999999818392, -0.04999999999890559, 0]], + [[-8.679999999818392, -0.04999999999890559, 0], [-8.679999999818392, -0.14999999999890612, 0]], + [[-8.679999999818392, -0.14999999999890612, 0], [-9.879999999888241, -0.17399999999890614, 0]], + [[-9.879999999888241, -0.17399999999890614, 0], [-8.679999999818392, -0.04999999999890559, 0]], + [[-9.879999999888241, -0.07399999999890561, 0], [-8.679999999818392, -0.04999999999890559, 0]], + [[-8.679999999818392, -0.04999999999890559, 0], [-9.879999999888241, -0.17399999999890614, 0]], + [[-9.879999999888241, -0.17399999999890614, 0], [-9.879999999888241, -0.07399999999890561, 0]] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999934807, -0.04999999999890559, -9.313225746154785e-10], + [-6.679999999818392, -0.009999999998905551, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [[[-10.379999999888241, -0.08399999999890628, 0], [-9.880000000004657, -0.07399999999890561, 0]]] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-5.999999999883585, -0.11999999999890676, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.529999999911524, -0.009999999998905551, 0] + ], + [[-6.529999999911524, -0.009999999998905551, 0], [-6.679999999818392, -0.009999999998905551, 0]], + [[-6.679999999818392, -0.009999999998905551, 0], [-6.679999999818392, -0.32999999999890495, 0]], + [[-6.679999999818392, -0.32999999999890495, 0], [-5.999999999883585, -0.32999999999890495, 0]], + [[-5.999999999883585, -0.32999999999890495, 0], [-5.999999999883585, -0.11999999999890676, 0]], + [ + [-6.529999999911524, -0.009999999998905551, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.679999999818392, -0.009999999998905551, 0] + ], + [[-6.679999999818392, -0.009999999998905551, 0], [-6.529999999911524, -0.009999999998905551, 0]], + [[-6.679999999818392, -0.32999999999890495, 0], [-6.679999999818392, -0.009999999998905551, 0]], + [ + [-6.679999999818392, -0.009999999998905551, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.679999999818392, -0.32999999999890495, 0] + ], + [ + [-6.679999999818392, -0.32999999999890495, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-5.999999999883585, -0.32999999999890495, 0] + ], + [[-5.999999999883585, -0.32999999999890495, 0], [-6.679999999818392, -0.32999999999890495, 0]], + [[-5.999999999883585, -0.11999999999890676, 0], [-5.999999999883585, -0.32999999999890495, 0]], + [ + [-5.999999999883585, -0.32999999999890495, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-5.999999999883585, -0.11999999999890676, 0] + ] + ] + }, + { + "elementId": "0x20000000f17", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [8.680000000051223, -0.15097774903400651, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ], + [ + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9], + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9] + ], + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [9.880000000004657, -0.074977749034006, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ], + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ] + ] + } + ] + } +] diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionA.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionA.json index 673b2c89533f..d8caac97e31d 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionA.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionA.json @@ -1,391 +1,375 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 0, - "ray": { - - "origin": [ 508065.00303496333, 6645747.0143687865, 5.68931356159401 ], - "direction": [ 0.17828222297866367, 0.9839793945859772, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 0, + "ray": { + "origin": [508065.00303496333, 6645747.0143687865, 5.68931356159401], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x2000000251f", + "categoryId": "0x20000000325", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.309597260551527, 11.920265698326453, -9.313225746154785e-10], + [-21.33814022457227, 12.089129285321263, -1.862645149230957e-9], + [-24.999999999650754, 11.929871822407076, -1.862645149230957e-9] + ], + [ + [-24.999999999650754, 11.70139930111667, 0], + [-21.31668586714659, 11.860715112107197, -9.313225746154785e-10], + [-21.309597260551527, 11.920265698326453, -9.313225746154785e-10] + ] + ] }, - "elements": [ - { - "elementId": "0x2000000251f", - "categoryId": "0x20000000325", - "modelId": "0x200000003b4", - "geometries": [ - [ - - [ -21.309597260551527, 11.920265698326453, -9.313225746154785e-10 ], - [ -21.33814022457227, 12.089129285321263, -1.862645149230957e-9 ], - [ -24.999999999650754, 11.929871822407076, -1.862645149230957e-9 ] - ], - [ - - [ -24.999999999650754, 11.70139930111667, 0 ], - [ -21.31668586714659, 11.860715112107197, -9.313225746154785e-10 ], - [ -21.309597260551527, 11.920265698326453, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000ff7", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 24.999999999883585, -0.43631041904140133, 0 ], - [ 22.056361284456216, -0.40630544087528264, 9.313225746154785e-10 ], - [ 16.147139406879432, -0.3219719019683067, -9.313225746154785e-10 ], - [ 15.132645385456271, -0.3056930230513286, 0 ], - [ 12.055327196256258, -0.253085721444374, 0 ], - [ 2.0542931078234687, -0.04858841566853389, 9.313225746154785e-10 ], - [ 7.695052772760391e-8, 0.0039498092831484755, 0 ], - [ 7.695052772760391e-8, -0.03605019071685156, 0 ], - [ 2.0542931078234687, -0.08858841566853393, 9.313225746154785e-10 ], - [ 12.055327196256258, -0.29308572144437317, 0 ], - [ 15.132645385456271, -0.34569302305132865, 0 ], - [ 16.147139406879432, -0.36197190196830764, -9.313225746154785e-10 ], - [ 22.056361284456216, -0.4463054408752827, 9.313225746154785e-10 ], - [ 24.999999999883585, -0.47631041904140137, 0 ] - ] - ] - }, - { - "elementId": "0x20000000ff9", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 24.999999999883585, -0.47631041904140137, 0 ], - [ 22.056361284456216, -0.4463054408752827, 9.313225746154785e-10 ], - [ 16.147139406879432, -0.36197190196830764, -9.313225746154785e-10 ], - [ 15.132645385456271, -0.34569302305132954, 0 ], - [ 12.055327196256258, -0.29308572144437317, 0 ], - [ 2.0542931078234687, -0.08858841566853481, 9.313225746154785e-10 ], - [ 7.695052772760391e-8, -0.036050190716853336, 0 ], - [ 7.695052772760391e-8, -0.1860501907168537, 0 ], - [ 2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10 ], - [ 12.055327196256258, -0.4430857214443753, 0 ], - [ 15.132645385456271, -0.4956930230513299, 0 ], - [ 16.147139406879432, -0.5119719019683071, -9.313225746154785e-10 ], - [ 22.056361284456216, -0.596305440875283, 9.313225746154785e-10 ], - [ 24.999999999883585, -0.6263104190414026, 0 ] - ] - ] - }, - { - "elementId": "0x20000000ffb", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 24.999999999883585, -0.6263104190414017, 0 ], - [ 22.056361284456216, -0.596305440875283, 9.313225746154785e-10 ], - [ 16.147139406879432, -0.5119719019683071, -9.313225746154785e-10 ], - [ 15.132645385456271, -0.4956930230513299, 0 ], - [ 12.055327196256258, -0.4430857214443753, 0 ], - [ 2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10 ], - [ 7.695052772760391e-8, -0.1860501907168537, 0 ], - [ 7.695052772760391e-8, -0.386050190716853, 0 ], - [ 2.0542931078234687, -0.43858841566853535, 9.313225746154785e-10 ], - [ 12.055327196256258, -0.6430857214443746, 0 ], - [ 15.132645385456271, -0.6956930230513292, 0 ], - [ 16.147139406879432, -0.7119719019683073, -9.313225746154785e-10 ], - [ 22.056361284456216, -0.7963054408752841, 9.313225746154785e-10 ], - [ 24.999999999883585, -0.8263104190414028, 0 ] - ] - ] - }, - { - "elementId": "0x20000000fff", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -15.859479100327007, 0.24273002498905605, 0 ], - [ -17.947775068460032, 0.31198164748942947, -9.313225746154785e-10 ], - [ -24.999999999883585, 0.5677002788677514, 0 ] - ], - [ - - [ -25, 0.7489401965574727, -9.313225746154785e-10 ], - [ -17.947775068343617, 0.5013344678828959, -9.313225746154785e-10 ], - [ -15.859479100327007, 0.43448522791356137, 0 ] - ] - ] - }, - { - "elementId": "0x20000002525", - "categoryId": "0x2000000032b", - "modelId": "0x200000003b4", - "geometries": [ - [ - - [ -21.780904921120964, 12.861791405043807, -9.313225746154785e-10 ], - [ -21.789858330157585, 12.86956032503004, -1.862645149230957e-9 ], - [ -21.802550818421878, 12.88066022244428, 0 ], - [ -21.954314876929857, 12.879165069859074, -9.313225746154785e-10 ], - [ -22.0804018083727, 12.878036511133136, 0 ], - [ -22.092661482281983, 12.866303068942944, -9.313225746154785e-10 ], - [ -22.102102481527254, 12.859073650031558, 0 ], - [ -22.122556253219955, 12.691610429392252, 9.313225746154785e-10 ], - [ -22.159407244995236, 12.385707666906114, 0 ], - [ -22.17524986958597, 12.35070784902479, -9.313225746154785e-10 ], - [ -22.196215688600205, 12.330766938884697, -9.313225746154785e-10 ], - [ -22.194328614044935, 12.30820463059127, 0 ], - [ -22.214426882448606, 12.263424855605749, -9.313225746154785e-10 ], - [ -22.250542386667803, 12.217219808593622, 0 ], - [ -22.310210896888748, 12.13960101119519, 0 ], - [ -22.305738903814927, 12.080095888556123, -9.313225746154785e-10 ], - [ -22.305362391169183, 12.046420798394731, 0 ], - [ -22.016940460540354, 12.058755775962776, -9.313225746154785e-10 ], - [ -21.810020496021025, 12.067788405595405, -9.313225746154785e-10 ], - [ -21.812365179648623, 12.263115616705043, 0 ], - [ -21.816983875934966, 12.54396206488616, 0 ], - [ -21.799688460538164, 12.557083743688562, 0 ], - [ -21.77341440867167, 12.576102172924184, -9.313225746154785e-10 ], - [ -21.775930330040865, 12.693170305172938, -9.313225746154785e-10 ], - [ -21.780904921120964, 12.861791405043807, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x200000025c2", - "categoryId": "0x20000000329", - "modelId": "0x200000003b4", - "geometries": [ - [ - - [ -21.61189473886043, 11.848987561140202, -1.862645149230957e-9 ], - [ -22.193277208018117, 11.82371376758709, 0 ], - [ -22.192129198578186, 11.798743681702902, 0 ], - [ -22.225849510519765, 11.797277796091816, -9.313225746154785e-10 ], - [ -22.29781346663367, 10.648233753169766, 0 ], - [ -22.589239793014713, 10.585524916534677, 0 ], - [ -22.885258157271892, 10.622696423379715, 0 ], - [ -23.062379766604863, 11.760912246496144, 0 ], - [ -23.096100079012103, 11.759446360862054, -9.313225746154785e-10 ], - [ -23.097248088102788, 11.784416446746484, -9.313225746154785e-10 ], - [ -23.678630557027645, 11.759142653185911, 0 ], - [ -23.675186529173516, 11.684232395572554, 0 ], - [ -23.27663874591235, 11.701558020134758, -1.862645149230957e-9 ], - [ -23.15837606182322, 11.631639146276054, 0 ], - [ -22.949542722548358, 10.289637957472351, -9.313225746154785e-10 ], - [ -22.203221454867162, 10.322081952008123, -9.313225746154785e-10 ], - [ -22.118373121949844, 11.676850037567103, -9.313225746154785e-10 ], - [ -22.006998493918218, 11.756751678947065, -9.313225746154785e-10 ], - [ -21.608450710773468, 11.774077303520965, -9.313225746154785e-10 ], - [ -21.61189473886043, 11.848987561140202, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -13.560657557449304, 0.36501718623917956, 0 ], - [ -13.965304459095933, 0.3773465961386817, 0 ], - [ -13.965304459095933, 0.33734659613868256, 0 ], - [ -13.560657557449304, 0.32501718623917863, 0 ], - [ -13.21495238353964, 0.31453340329701174, 0 ], - [ -12.749161509796977, 0.3004772233202271, 0 ], - [ -11.556745232548565, 0.26536794189919544, 0 ], - [ -11.317022527451627, 0.2581691636677146, 0 ], - [ -10.523360020597465, 0.23481056174965165, 0 ], - [ -10.412220384343527, 0.23137165663719106, -9.313225746154785e-10 ], - [ -8.93376574816648, 0.18978392633499386, -9.313225746154785e-10 ], - [ -8.900657587801106, 0.1887610140821181, -9.313225746154785e-10 ], - [ -8.864327007555403, 0.1877605621898768, -9.313225746154785e-10 ], - [ -7.993680467130616, 0.16327686679037523, 0 ], - [ -7.954276460572146, 0.16256610885502543, -9.313225746154785e-10 ], - [ -5.506849944475107, 0.0967532445200332, 0 ], - [ -5.480727260117419, 0.0964170635489463, 0 ], - [ -3.898698852164671, 0.05541856261882838, 0 ], - [ -3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10 ], - [ -3.77053390792571, 0.05476232726746133, 0 ], - [ -2.8965330155333504, 0.03206737034783469, 0 ], - [ -0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10 ], - [ -1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10 ], - [ -1.1641532182693481e-10, 0, 9.313225746154785e-10 ], - [ -0.4447324851062149, 0.010581322317988473, -9.313225746154785e-10 ], - [ -2.8965330155333504, 0.07206737034783561, 0 ], - [ -3.77053390792571, 0.09476232726746137, 0 ], - [ -3.8841997728450224, 0.09530717370141062, -9.313225746154785e-10 ], - [ -3.898698852164671, 0.09541856261882753, 0 ], - [ -5.480727260233834, 0.13641706354894634, 0 ], - [ -5.506849944475107, 0.13675324452003323, 0 ], - [ -7.954276460572146, 0.20256610885502546, -9.313225746154785e-10 ], - [ -7.993680467130616, 0.20327686679037527, 0 ], - [ -8.864327007555403, 0.22776056218987684, -9.313225746154785e-10 ], - [ -8.900657587801106, 0.22876101408211724, -9.313225746154785e-10 ], - [ -8.93376574816648, 0.2297839263349939, -9.313225746154785e-10 ], - [ -10.412220384576358, 0.2713716566371911, 0 ], - [ -10.523360020597465, 0.2748105617496517, 0 ], - [ -11.317022527451627, 0.2981691636677155, 0 ], - [ -11.556745232548565, 0.30536794189919547, 0 ], - [ -12.749161509796977, 0.340477223320228, 0 ], - [ -13.21495238353964, 0.3545334032970109, 0 ], - [ -13.560657557449304, 0.36501718623917956, 0 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -13.560657557449304, 0.32501718623917863, 0 ], - [ -13.965304459095933, 0.33734659613868256, 0 ], - [ -13.965304459095933, 0.1873465961386822, 0 ], - [ -13.560657557449304, 0.17501718623918006, 0 ], - [ -13.21495238353964, 0.16453340329701138, 0 ], - [ -12.749161509796977, 0.15047722332022762, 0 ], - [ -11.556745232548565, 0.11536794189919597, 0 ], - [ -11.317022527451627, 0.10816916366771512, 0 ], - [ -10.523360020597465, 0.08481056174965129, 0 ], - [ -10.412220384343527, 0.08137165663718982, -9.313225746154785e-10 ], - [ -8.93376574816648, 0.039783926334992614, -9.313225746154785e-10 ], - [ -8.900657587801106, 0.03876101408211685, -9.313225746154785e-10 ], - [ -8.864327007555403, 0.03776056218987467, -9.313225746154785e-10 ], - [ -7.993680467130616, 0.013276866790373987, 0 ], - [ -7.954276460572146, 0.012566108855024183, -9.313225746154785e-10 ], - [ -5.506849944475107, -0.053246755479968044, 0 ], - [ -5.480727260117419, -0.05358293645105494, 0 ], - [ -3.898698852164671, -0.09458143738117109, 0 ], - [ -3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10 ], - [ -3.77053390792571, -0.09523767273253814, 0 ], - [ -2.8965330155333504, -0.11793262965216389, 0 ], - [ -0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10 ], - [ -1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10 ], - [ -1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10 ], - [ -0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10 ], - [ -2.8965330155333504, 0.03206737034783469, 0 ], - [ -3.77053390792571, 0.05476232726746133, 0 ], - [ -3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10 ], - [ -3.898698852164671, 0.05541856261882838, 0 ], - [ -5.480727260233834, 0.0964170635489463, 0 ], - [ -5.506849944475107, 0.0967532445200332, 0 ], - [ -7.954276460572146, 0.16256610885502543, -9.313225746154785e-10 ], - [ -7.993680467130616, 0.16327686679037523, 0 ], - [ -8.864327007555403, 0.1877605621898768, -9.313225746154785e-10 ], - [ -8.900657587801106, 0.1887610140821181, -9.313225746154785e-10 ], - [ -8.93376574816648, 0.18978392633499386, -9.313225746154785e-10 ], - [ -10.412220384576358, 0.23137165663719106, 0 ], - [ -10.523360020597465, 0.23481056174965165, 0 ], - [ -11.317022527451627, 0.2581691636677146, 0 ], - [ -11.556745232548565, 0.26536794189919544, 0 ], - [ -12.749161509796977, 0.3004772233202271, 0 ], - [ -13.21495238353964, 0.31453340329701174, 0 ], - [ -13.560657557449304, 0.32501718623917863, 0 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -13.560657557449304, 0.17501718623918006, 0 ], - [ -13.965304459095933, 0.1873465961386822, 0 ], - [ -13.965304459095933, -0.012653403861317969, 0 ], - [ -13.560657557449304, -0.02498281376082101, 0 ], - [ -13.21495238353964, -0.03546659670298968, 0 ], - [ -12.749161509796977, -0.04952277667977345, 0 ], - [ -11.556745232548565, -0.08463205810080421, 0 ], - [ -11.317022527451627, -0.09183083633228506, 0 ], - [ -10.523360020597465, -0.11518943825034889, 0 ], - [ -10.412220384343527, -0.11862834336280859, -9.313225746154785e-10 ], - [ -8.93376574816648, -0.16021607366500756, -9.313225746154785e-10 ], - [ -8.900657587801106, -0.16123898591788244, -9.313225746154785e-10 ], - [ -8.864327007555403, -0.1622394378101255, -9.313225746154785e-10 ], - [ -7.993680467130616, -0.18672313320962708, 0 ], - [ -7.954276460572146, -0.187433891144976, -9.313225746154785e-10 ], - [ -5.506849944475107, -0.2532467554799682, 0 ], - [ -5.480727260117419, -0.2535829364510551, 0 ], - [ -3.898698852164671, -0.29458143738117215, 0 ], - [ -3.8841997728450224, -0.29469282629858995, -9.313225746154785e-10 ], - [ -3.77053390792571, -0.2952376727325392, 0 ], - [ -2.8965330155333504, -0.31793262965216584, 0 ], - [ -0.4447324851062149, -0.379418677682013, -9.313225746154785e-10 ], - [ -1.1641532182693481e-10, -0.39000000000000057, 9.313225746154785e-10 ], - [ -1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10 ], - [ -0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10 ], - [ -2.8965330155333504, -0.11793262965216389, 0 ], - [ -3.77053390792571, -0.09523767273253814, 0 ], - [ -3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10 ], - [ -3.898698852164671, -0.09458143738117109, 0 ], - [ -5.480727260233834, -0.05358293645105494, 0 ], - [ -5.506849944475107, -0.053246755479968044, 0 ], - [ -7.954276460572146, 0.012566108855024183, -9.313225746154785e-10 ], - [ -7.993680467130616, 0.013276866790373987, 0 ], - [ -8.864327007555403, 0.03776056218987467, -9.313225746154785e-10 ], - [ -8.900657587801106, 0.03876101408211685, -9.313225746154785e-10 ], - [ -8.93376574816648, 0.039783926334992614, -9.313225746154785e-10 ], - [ -10.412220384576358, 0.0813716566371907, 0 ], - [ -10.523360020597465, 0.08481056174965129, 0 ], - [ -11.317022527451627, 0.10816916366771512, 0 ], - [ -11.556745232548565, 0.11536794189919597, 0 ], - [ -12.749161509796977, 0.15047722332022762, 0 ], - [ -13.21495238353964, 0.16453340329701138, 0 ], - [ -13.560657557449304, 0.17501718623918006, 0 ] - ] - ] - }, - { - "elementId": "0x20000001047", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -14.629234474035911, 0.39593035363518947, -1.862645149230957e-9 ], - [ -15.020279791089706, 0.40860511585720527, -9.313225746154785e-10 ], - [ -15.859479100327007, 0.434485227954001, 0 ], - [ -15.859479100443423, 0.24273002499550778, 0 ], - [ -15.515034026349895, 0.229057381444421, -9.313225746154785e-10 ], - [ -14.629234474268742, 0.19660126485857976, -9.313225746154785e-10 ], - [ -13.965304456767626, 0.16734659604119706, 0 ], - [ -13.965304456884041, 0.377346596041197, 0 ], - [ -14.629234474035911, 0.39593035363518947, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x200000025bf", - "categoryId": "0x20000000329", - "modelId": "0x200000003b4", - "geometries": [ - [ - - [ -23.717762321117334, 11.757671543662408, 0 ], - [ -24.301593580050394, 11.732228036294664, 0 ], - [ -24.300440740655176, 11.707258285300973, -9.313225746154785e-10 ], - [ -24.334303083014674, 11.705782556229131, -9.313225746154785e-10 ], - [ -24.406570418039337, 10.556717494419264, 0 ], - [ -24.69922424782999, 10.493923585774699, -9.313225746154785e-10 ], - [ -24.996489433106035, 10.531008681171187, -9.313225746154785e-10 ], - [ -24.999999999650754, 10.553472614613835, 0 ] - ], - [ - - [ -24.999999999650754, 10.20059179534578, 0 ], - [ -24.311580060399137, 10.230593302678546, -1.862645149230957e-9 ], - [ -24.226374032441527, 11.585386170316227, 0 ], - [ -24.11453027499374, 11.665320324314234, -9.313225746154785e-10 ], - [ -23.714303803630173, 11.682762290660467, -9.313225746154785e-10 ], - [ -23.717762321117334, 11.757671543662408, 0 ] - ] - ] - } - ] -} \ No newline at end of file + { + "elementId": "0x20000000ff7", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.43631041904140133, 0], + [22.056361284456216, -0.40630544087528264, 9.313225746154785e-10], + [16.147139406879432, -0.3219719019683067, -9.313225746154785e-10], + [15.132645385456271, -0.3056930230513286, 0], + [12.055327196256258, -0.253085721444374, 0], + [2.0542931078234687, -0.04858841566853389, 9.313225746154785e-10], + [7.695052772760391e-8, 0.0039498092831484755, 0], + [7.695052772760391e-8, -0.03605019071685156, 0], + [2.0542931078234687, -0.08858841566853393, 9.313225746154785e-10], + [12.055327196256258, -0.29308572144437317, 0], + [15.132645385456271, -0.34569302305132865, 0], + [16.147139406879432, -0.36197190196830764, -9.313225746154785e-10], + [22.056361284456216, -0.4463054408752827, 9.313225746154785e-10], + [24.999999999883585, -0.47631041904140137, 0] + ] + ] + }, + { + "elementId": "0x20000000ff9", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.47631041904140137, 0], + [22.056361284456216, -0.4463054408752827, 9.313225746154785e-10], + [16.147139406879432, -0.36197190196830764, -9.313225746154785e-10], + [15.132645385456271, -0.34569302305132954, 0], + [12.055327196256258, -0.29308572144437317, 0], + [2.0542931078234687, -0.08858841566853481, 9.313225746154785e-10], + [7.695052772760391e-8, -0.036050190716853336, 0], + [7.695052772760391e-8, -0.1860501907168537, 0], + [2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10], + [12.055327196256258, -0.4430857214443753, 0], + [15.132645385456271, -0.4956930230513299, 0], + [16.147139406879432, -0.5119719019683071, -9.313225746154785e-10], + [22.056361284456216, -0.596305440875283, 9.313225746154785e-10], + [24.999999999883585, -0.6263104190414026, 0] + ] + ] + }, + { + "elementId": "0x20000000ffb", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [24.999999999883585, -0.6263104190414017, 0], + [22.056361284456216, -0.596305440875283, 9.313225746154785e-10], + [16.147139406879432, -0.5119719019683071, -9.313225746154785e-10], + [15.132645385456271, -0.4956930230513299, 0], + [12.055327196256258, -0.4430857214443753, 0], + [2.0542931078234687, -0.23858841566853606, 9.313225746154785e-10], + [7.695052772760391e-8, -0.1860501907168537, 0], + [7.695052772760391e-8, -0.386050190716853, 0], + [2.0542931078234687, -0.43858841566853535, 9.313225746154785e-10], + [12.055327196256258, -0.6430857214443746, 0], + [15.132645385456271, -0.6956930230513292, 0], + [16.147139406879432, -0.7119719019683073, -9.313225746154785e-10], + [22.056361284456216, -0.7963054408752841, 9.313225746154785e-10], + [24.999999999883585, -0.8263104190414028, 0] + ] + ] + }, + { + "elementId": "0x20000000fff", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-15.859479100327007, 0.24273002498905605, 0], + [-17.947775068460032, 0.31198164748942947, -9.313225746154785e-10], + [-24.999999999883585, 0.5677002788677514, 0] + ], + [ + [-25, 0.7489401965574727, -9.313225746154785e-10], + [-17.947775068343617, 0.5013344678828959, -9.313225746154785e-10], + [-15.859479100327007, 0.43448522791356137, 0] + ] + ] + }, + { + "elementId": "0x20000002525", + "categoryId": "0x2000000032b", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.780904921120964, 12.861791405043807, -9.313225746154785e-10], + [-21.789858330157585, 12.86956032503004, -1.862645149230957e-9], + [-21.802550818421878, 12.88066022244428, 0], + [-21.954314876929857, 12.879165069859074, -9.313225746154785e-10], + [-22.0804018083727, 12.878036511133136, 0], + [-22.092661482281983, 12.866303068942944, -9.313225746154785e-10], + [-22.102102481527254, 12.859073650031558, 0], + [-22.122556253219955, 12.691610429392252, 9.313225746154785e-10], + [-22.159407244995236, 12.385707666906114, 0], + [-22.17524986958597, 12.35070784902479, -9.313225746154785e-10], + [-22.196215688600205, 12.330766938884697, -9.313225746154785e-10], + [-22.194328614044935, 12.30820463059127, 0], + [-22.214426882448606, 12.263424855605749, -9.313225746154785e-10], + [-22.250542386667803, 12.217219808593622, 0], + [-22.310210896888748, 12.13960101119519, 0], + [-22.305738903814927, 12.080095888556123, -9.313225746154785e-10], + [-22.305362391169183, 12.046420798394731, 0], + [-22.016940460540354, 12.058755775962776, -9.313225746154785e-10], + [-21.810020496021025, 12.067788405595405, -9.313225746154785e-10], + [-21.812365179648623, 12.263115616705043, 0], + [-21.816983875934966, 12.54396206488616, 0], + [-21.799688460538164, 12.557083743688562, 0], + [-21.77341440867167, 12.576102172924184, -9.313225746154785e-10], + [-21.775930330040865, 12.693170305172938, -9.313225746154785e-10], + [-21.780904921120964, 12.861791405043807, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x200000025c2", + "categoryId": "0x20000000329", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-21.61189473886043, 11.848987561140202, -1.862645149230957e-9], + [-22.193277208018117, 11.82371376758709, 0], + [-22.192129198578186, 11.798743681702902, 0], + [-22.225849510519765, 11.797277796091816, -9.313225746154785e-10], + [-22.29781346663367, 10.648233753169766, 0], + [-22.589239793014713, 10.585524916534677, 0], + [-22.885258157271892, 10.622696423379715, 0], + [-23.062379766604863, 11.760912246496144, 0], + [-23.096100079012103, 11.759446360862054, -9.313225746154785e-10], + [-23.097248088102788, 11.784416446746484, -9.313225746154785e-10], + [-23.678630557027645, 11.759142653185911, 0], + [-23.675186529173516, 11.684232395572554, 0], + [-23.27663874591235, 11.701558020134758, -1.862645149230957e-9], + [-23.15837606182322, 11.631639146276054, 0], + [-22.949542722548358, 10.289637957472351, -9.313225746154785e-10], + [-22.203221454867162, 10.322081952008123, -9.313225746154785e-10], + [-22.118373121949844, 11.676850037567103, -9.313225746154785e-10], + [-22.006998493918218, 11.756751678947065, -9.313225746154785e-10], + [-21.608450710773468, 11.774077303520965, -9.313225746154785e-10], + [-21.61189473886043, 11.848987561140202, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.36501718623917956, 0], + [-13.965304459095933, 0.3773465961386817, 0], + [-13.965304459095933, 0.33734659613868256, 0], + [-13.560657557449304, 0.32501718623917863, 0], + [-13.21495238353964, 0.31453340329701174, 0], + [-12.749161509796977, 0.3004772233202271, 0], + [-11.556745232548565, 0.26536794189919544, 0], + [-11.317022527451627, 0.2581691636677146, 0], + [-10.523360020597465, 0.23481056174965165, 0], + [-10.412220384343527, 0.23137165663719106, -9.313225746154785e-10], + [-8.93376574816648, 0.18978392633499386, -9.313225746154785e-10], + [-8.900657587801106, 0.1887610140821181, -9.313225746154785e-10], + [-8.864327007555403, 0.1877605621898768, -9.313225746154785e-10], + [-7.993680467130616, 0.16327686679037523, 0], + [-7.954276460572146, 0.16256610885502543, -9.313225746154785e-10], + [-5.506849944475107, 0.0967532445200332, 0], + [-5.480727260117419, 0.0964170635489463, 0], + [-3.898698852164671, 0.05541856261882838, 0], + [-3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10], + [-3.77053390792571, 0.05476232726746133, 0], + [-2.8965330155333504, 0.03206737034783469, 0], + [-0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10], + [-1.1641532182693481e-10, 0, 9.313225746154785e-10], + [-0.4447324851062149, 0.010581322317988473, -9.313225746154785e-10], + [-2.8965330155333504, 0.07206737034783561, 0], + [-3.77053390792571, 0.09476232726746137, 0], + [-3.8841997728450224, 0.09530717370141062, -9.313225746154785e-10], + [-3.898698852164671, 0.09541856261882753, 0], + [-5.480727260233834, 0.13641706354894634, 0], + [-5.506849944475107, 0.13675324452003323, 0], + [-7.954276460572146, 0.20256610885502546, -9.313225746154785e-10], + [-7.993680467130616, 0.20327686679037527, 0], + [-8.864327007555403, 0.22776056218987684, -9.313225746154785e-10], + [-8.900657587801106, 0.22876101408211724, -9.313225746154785e-10], + [-8.93376574816648, 0.2297839263349939, -9.313225746154785e-10], + [-10.412220384576358, 0.2713716566371911, 0], + [-10.523360020597465, 0.2748105617496517, 0], + [-11.317022527451627, 0.2981691636677155, 0], + [-11.556745232548565, 0.30536794189919547, 0], + [-12.749161509796977, 0.340477223320228, 0], + [-13.21495238353964, 0.3545334032970109, 0], + [-13.560657557449304, 0.36501718623917956, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.32501718623917863, 0], + [-13.965304459095933, 0.33734659613868256, 0], + [-13.965304459095933, 0.1873465961386822, 0], + [-13.560657557449304, 0.17501718623918006, 0], + [-13.21495238353964, 0.16453340329701138, 0], + [-12.749161509796977, 0.15047722332022762, 0], + [-11.556745232548565, 0.11536794189919597, 0], + [-11.317022527451627, 0.10816916366771512, 0], + [-10.523360020597465, 0.08481056174965129, 0], + [-10.412220384343527, 0.08137165663718982, -9.313225746154785e-10], + [-8.93376574816648, 0.039783926334992614, -9.313225746154785e-10], + [-8.900657587801106, 0.03876101408211685, -9.313225746154785e-10], + [-8.864327007555403, 0.03776056218987467, -9.313225746154785e-10], + [-7.993680467130616, 0.013276866790373987, 0], + [-7.954276460572146, 0.012566108855024183, -9.313225746154785e-10], + [-5.506849944475107, -0.053246755479968044, 0], + [-5.480727260117419, -0.05358293645105494, 0], + [-3.898698852164671, -0.09458143738117109, 0], + [-3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10], + [-3.77053390792571, -0.09523767273253814, 0], + [-2.8965330155333504, -0.11793262965216389, 0], + [-0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10], + [-1.1641532182693481e-10, -0.040000000000000036, 9.313225746154785e-10], + [-0.4447324851062149, -0.029418677682011563, -9.313225746154785e-10], + [-2.8965330155333504, 0.03206737034783469, 0], + [-3.77053390792571, 0.05476232726746133, 0], + [-3.8841997728450224, 0.055307173701409695, -9.313225746154785e-10], + [-3.898698852164671, 0.05541856261882838, 0], + [-5.480727260233834, 0.0964170635489463, 0], + [-5.506849944475107, 0.0967532445200332, 0], + [-7.954276460572146, 0.16256610885502543, -9.313225746154785e-10], + [-7.993680467130616, 0.16327686679037523, 0], + [-8.864327007555403, 0.1877605621898768, -9.313225746154785e-10], + [-8.900657587801106, 0.1887610140821181, -9.313225746154785e-10], + [-8.93376574816648, 0.18978392633499386, -9.313225746154785e-10], + [-10.412220384576358, 0.23137165663719106, 0], + [-10.523360020597465, 0.23481056174965165, 0], + [-11.317022527451627, 0.2581691636677146, 0], + [-11.556745232548565, 0.26536794189919544, 0], + [-12.749161509796977, 0.3004772233202271, 0], + [-13.21495238353964, 0.31453340329701174, 0], + [-13.560657557449304, 0.32501718623917863, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-13.560657557449304, 0.17501718623918006, 0], + [-13.965304459095933, 0.1873465961386822, 0], + [-13.965304459095933, -0.012653403861317969, 0], + [-13.560657557449304, -0.02498281376082101, 0], + [-13.21495238353964, -0.03546659670298968, 0], + [-12.749161509796977, -0.04952277667977345, 0], + [-11.556745232548565, -0.08463205810080421, 0], + [-11.317022527451627, -0.09183083633228506, 0], + [-10.523360020597465, -0.11518943825034889, 0], + [-10.412220384343527, -0.11862834336280859, -9.313225746154785e-10], + [-8.93376574816648, -0.16021607366500756, -9.313225746154785e-10], + [-8.900657587801106, -0.16123898591788244, -9.313225746154785e-10], + [-8.864327007555403, -0.1622394378101255, -9.313225746154785e-10], + [-7.993680467130616, -0.18672313320962708, 0], + [-7.954276460572146, -0.187433891144976, -9.313225746154785e-10], + [-5.506849944475107, -0.2532467554799682, 0], + [-5.480727260117419, -0.2535829364510551, 0], + [-3.898698852164671, -0.29458143738117215, 0], + [-3.8841997728450224, -0.29469282629858995, -9.313225746154785e-10], + [-3.77053390792571, -0.2952376727325392, 0], + [-2.8965330155333504, -0.31793262965216584, 0], + [-0.4447324851062149, -0.379418677682013, -9.313225746154785e-10], + [-1.1641532182693481e-10, -0.39000000000000057, 9.313225746154785e-10], + [-1.1641532182693481e-10, -0.1899999999999995, 9.313225746154785e-10], + [-0.4447324851062149, -0.1794186776820128, -9.313225746154785e-10], + [-2.8965330155333504, -0.11793262965216389, 0], + [-3.77053390792571, -0.09523767273253814, 0], + [-3.8841997728450224, -0.09469282629858888, -9.313225746154785e-10], + [-3.898698852164671, -0.09458143738117109, 0], + [-5.480727260233834, -0.05358293645105494, 0], + [-5.506849944475107, -0.053246755479968044, 0], + [-7.954276460572146, 0.012566108855024183, -9.313225746154785e-10], + [-7.993680467130616, 0.013276866790373987, 0], + [-8.864327007555403, 0.03776056218987467, -9.313225746154785e-10], + [-8.900657587801106, 0.03876101408211685, -9.313225746154785e-10], + [-8.93376574816648, 0.039783926334992614, -9.313225746154785e-10], + [-10.412220384576358, 0.0813716566371907, 0], + [-10.523360020597465, 0.08481056174965129, 0], + [-11.317022527451627, 0.10816916366771512, 0], + [-11.556745232548565, 0.11536794189919597, 0], + [-12.749161509796977, 0.15047722332022762, 0], + [-13.21495238353964, 0.16453340329701138, 0], + [-13.560657557449304, 0.17501718623918006, 0] + ] + ] + }, + { + "elementId": "0x20000001047", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-14.629234474035911, 0.39593035363518947, -1.862645149230957e-9], + [-15.020279791089706, 0.40860511585720527, -9.313225746154785e-10], + [-15.859479100327007, 0.434485227954001, 0], + [-15.859479100443423, 0.24273002499550778, 0], + [-15.515034026349895, 0.229057381444421, -9.313225746154785e-10], + [-14.629234474268742, 0.19660126485857976, -9.313225746154785e-10], + [-13.965304456767626, 0.16734659604119706, 0], + [-13.965304456884041, 0.377346596041197, 0], + [-14.629234474035911, 0.39593035363518947, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x200000025bf", + "categoryId": "0x20000000329", + "modelId": "0x200000003b4", + "geometries": [ + [ + [-23.717762321117334, 11.757671543662408, 0], + [-24.301593580050394, 11.732228036294664, 0], + [-24.300440740655176, 11.707258285300973, -9.313225746154785e-10], + [-24.334303083014674, 11.705782556229131, -9.313225746154785e-10], + [-24.406570418039337, 10.556717494419264, 0], + [-24.69922424782999, 10.493923585774699, -9.313225746154785e-10], + [-24.996489433106035, 10.531008681171187, -9.313225746154785e-10], + [-24.999999999650754, 10.553472614613835, 0] + ], + [ + [-24.999999999650754, 10.20059179534578, 0], + [-24.311580060399137, 10.230593302678546, -1.862645149230957e-9], + [-24.226374032441527, 11.585386170316227, 0], + [-24.11453027499374, 11.665320324314234, -9.313225746154785e-10], + [-23.714303803630173, 11.682762290660467, -9.313225746154785e-10], + [-23.717762321117334, 11.757671543662408, 0] + ] + ] + } + ] +} diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionB.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionB.json index 394e3d717787..b3e05acb03ad 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionB.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionB.json @@ -1,276 +1,258 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 10, - "ray": { - "origin": [ 508066.7858571931, 6645756.854162732, 5.483521231404236 ], - "direction": [ 0.17828222297866367, 0.9839793945859772, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 10, + "ray": { + "origin": [508066.7858571931, 6645756.854162732, 5.483521231404236], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000000a16", + "categoryId": "0x20000000183", + "modelId": "0x200000003c3", + "geometries": [ + [ + [-24.712078254204243, 12.229065306170728, -1.862645149230957e-9], + [-24.712078254204243, 9.439300229625651, -1.862645149230957e-9], + [-24.712078254204243, -0.04962572769248297, -1.862645149230957e-9], + [-24.999999999883585, -0.05862859917218266, -9.313225746154785e-10] + ], + [ + [-24.99999999976717, -0.6086964001481494, -9.313225746154785e-10], + [-24.905035979347304, -0.6057454895855674, -9.313225746154785e-10], + [-23.677354383165948, -0.5673994461203868, -9.313225746154785e-10], + [-23.677354383165948, -0.16739944612038382, -9.313225746154785e-10], + [-23.931223444873467, -0.17532892392315524, -3.725290298461914e-9], + [-24.200328385224566, -0.18367852391556472, -9.313225746154785e-10], + [-24.274962203926407, 6.2351032033325335, -1.862645149230957e-9], + [-24.35399462026544, 13.032284360849353, -1.862645149230957e-9], + [-24.70277738769073, 13.029148948575045, -1.862645149230957e-9], + [-24.712078254204243, 12.229065306170728, -1.862645149230957e-9] + ] + ] }, - "elements": [ - { - "elementId": "0x20000000a16", - "categoryId": "0x20000000183", - "modelId": "0x200000003c3", - "geometries": [ - [ - - [ -24.712078254204243, 12.229065306170728, -1.862645149230957e-9 ], - [ -24.712078254204243, 9.439300229625651, -1.862645149230957e-9 ], - [ -24.712078254204243, -0.04962572769248297, -1.862645149230957e-9 ], - [ -24.999999999883585, -0.05862859917218266, -9.313225746154785e-10 ] - ], - [ - - [ -24.99999999976717, -0.6086964001481494, -9.313225746154785e-10 ], - [ -24.905035979347304, -0.6057454895855674, -9.313225746154785e-10 ], - [ -23.677354383165948, -0.5673994461203868, -9.313225746154785e-10 ], - [ -23.677354383165948, -0.16739944612038382, -9.313225746154785e-10 ], - [ -23.931223444873467, -0.17532892392315524, -3.725290298461914e-9 ], - [ -24.200328385224566, -0.18367852391556472, -9.313225746154785e-10 ], - [ -24.274962203926407, 6.2351032033325335, -1.862645149230957e-9 ], - [ -24.35399462026544, 13.032284360849353, -1.862645149230957e-9 ], - [ -24.70277738769073, 13.029148948575045, -1.862645149230957e-9 ], - [ -24.712078254204243, 12.229065306170728, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000a1e", - "categoryId": "0x20000000187", - "modelId": "0x200000003c3", - "geometries": [ - [ - - [ -24.71207825327292, 12.229065306219276, -9.313225746154785e-10 ], - [ -24.99999999976717, 12.216575559213922, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, 0, 0 ], - [ -6.000000000232831, -0.12000000000499345, -9.313225746154785e-10 ], - [ -6.000000000232831, -0.16000000000499348, -9.313225746154785e-10 ], - [ 0, -0.040000000000000036, 0 ], - [ 6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9 ], - [ 6.0098497840808704, -0.12025174434887376, -1.862645149230957e-9 ], - [ 0, 0, 0 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.040000000000000036, 0 ], - [ -6.000000000232831, -0.16000000000499348, -9.313225746154785e-10 ], - [ -6.000000000232831, -0.31000000000499295, -9.313225746154785e-10 ], - [ 0, -0.1899999999999995, 0 ], - [ 6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9 ], - [ 6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.1899999999999995, 0 ], - [ -6.000000000232831, -0.31000000000499295, -9.313225746154785e-10 ], - [ -6.000000000232831, -0.510000000004994, -9.313225746154785e-10 ], - [ 0, -0.39000000000000057, 0 ], - [ 6.0098497840808704, -0.5102517443488743, -1.862645149230957e-9 ], - [ 6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9 ], - [ 0, -0.1899999999999995, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f9f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000237487, -0.08400000000499297, 0 ], - [ -11.052264821715653, 0.1400860329075968, 0 ], - [ -11.052264821715653, 0.04008603290759538, 0 ], - [ -10.380000000237487, -0.1840000000049944, 0 ], - [ -10.380000000237487, -0.08400000000499297, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f9d", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -11.052264821715653, 0.1400860329075968, 0 ], - [ -10.380000000237487, -0.08400000000499297, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f81", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000284053, -0.05000000000499227, 9.313225746154785e-10 ], - [ -9.880000000121072, -0.0740000000049923, -9.313225746154785e-10 ], - [ -9.880000000121072, -0.17400000000499372, -9.313225746154785e-10 ], - [ -8.680000000284053, -0.1500000000049937, 9.313225746154785e-10 ], - [ -8.680000000284053, -0.05000000000499227, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f82", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000284053, -0.05000000000499227, 0 ], - [ -6.680000000284053, -0.010000000004992238, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f83", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000237487, -0.08400000000499297, 0 ], - [ -9.880000000353903, -0.0740000000049923, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f85", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -6, -0.12000000000499433, -9.313225746154785e-10 ], - [ -6.500000000349246, -0.16000000000499437, 0 ], - [ -6.53000000002794, -0.010000000004994014, -9.313225746154785e-10 ], - [ -6.680000000167638, -0.010000000004994014, 9.313225746154785e-10 ], - [ -6.680000000167638, -0.3300000000049934, 9.313225746154785e-10 ], - [ -6, -0.3300000000049934, -9.313225746154785e-10 ], - [ -6, -0.12000000000499433, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x2000000102d", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.009849783964455, -0.3302517155538194, -1.862645149230957e-9 ], - [ 6.5050995904020965, -0.3302517155538194, -1.862645149230957e-9 ], - [ 6.689849783782847, -0.32992302906745863, -9.313225746154785e-10 ], - [ 6.689849783782847, -0.009923029067459233, -9.313225746154785e-10 ], - [ 6.6468152336310595, -0.009999591230094751, -1.862645149230957e-9 ], - [ 6.539849783643149, -0.009999591243764705, 0 ], - [ 6.5098497837316245, -0.1600146135503513, -9.313225746154785e-10 ], - [ 6.152845289441757, -0.13145425399504784, -9.313225746154785e-10 ], - [ 6.009849783964455, -0.12025171555381853, -1.862645149230957e-9 ], - [ 6.009849783964455, -0.3302517155538194, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000001029", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.689849783782847, -0.009923029067458344, -9.313225746154785e-10 ], - [ 7.432176180649549, -0.023448894482823057, -1.862645149230957e-9 ], - [ 8.689849783666432, -0.048602366564344024, 0 ] - ] - ] - }, - { - "elementId": "0x20000001027", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 9.222578136483207, -0.15805021063472324, -1.862645149230957e-9 ], - [ 9.889849783852696, -0.1713956435702162, -9.313225746154785e-10 ], - [ 9.889849783852696, -0.07139564357021566, -9.313225746154785e-10 ], - [ 9.222578136483207, -0.05805021063472271, -1.862645149230957e-9 ], - [ 8.689849783899263, -0.04860236656434491, 0 ], - [ 8.689849783899263, -0.14860236656434544, 0 ], - [ 9.222578136483207, -0.15805021063472324, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x2000000102b", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 9.889849783736281, -0.0713956435570493, -9.313225746154785e-10 ], - [ 10.131568165728822, -0.07557511702494502, -9.313225746154785e-10 ], - [ 10.389849783852696, -0.08074074936673448, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000001025", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.389849783852696, -0.08074074938234865, -9.313225746154785e-10 ], - [ 10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10 ], - [ 10.860269933007658, 0.07677824947917156, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x2000000102f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.631802612915635, -0.09937676230103598, -9.313225746154785e-10 ], - [ 10.860269933007658, -0.0232217505208272, -9.313225746154785e-10 ], - [ 10.860269933007658, 0.07677824947917156, -9.313225746154785e-10 ], - [ 10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10 ], - [ 10.389849783852696, -0.08074074938234865, -9.313225746154785e-10 ], - [ 10.389849783852696, -0.18074074938234652, -9.313225746154785e-10 ], - [ 10.631802612915635, -0.09937676230103598, -9.313225746154785e-10 ] - ] - ] - } - ] -} \ No newline at end of file + { + "elementId": "0x20000000a1e", + "categoryId": "0x20000000187", + "modelId": "0x200000003c3", + "geometries": [ + [ + [-24.71207825327292, 12.229065306219276, -9.313225746154785e-10], + [-24.99999999976717, 12.216575559213922, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000232831, -0.12000000000499345, -9.313225746154785e-10], + [-6.000000000232831, -0.16000000000499348, -9.313225746154785e-10], + [0, -0.040000000000000036, 0], + [6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9], + [6.0098497840808704, -0.12025174434887376, -1.862645149230957e-9], + [0, 0, 0] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000232831, -0.16000000000499348, -9.313225746154785e-10], + [-6.000000000232831, -0.31000000000499295, -9.313225746154785e-10], + [0, -0.1899999999999995, 0], + [6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9], + [6.0098497840808704, -0.1602517443488738, -1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1899999999999995, 0], + [-6.000000000232831, -0.31000000000499295, -9.313225746154785e-10], + [-6.000000000232831, -0.510000000004994, -9.313225746154785e-10], + [0, -0.39000000000000057, 0], + [6.0098497840808704, -0.5102517443488743, -1.862645149230957e-9], + [6.0098497840808704, -0.31025174434887504, -1.862645149230957e-9], + [0, -0.1899999999999995, 0] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000237487, -0.08400000000499297, 0], + [-11.052264821715653, 0.1400860329075968, 0], + [-11.052264821715653, 0.04008603290759538, 0], + [-10.380000000237487, -0.1840000000049944, 0], + [-10.380000000237487, -0.08400000000499297, 0] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-11.052264821715653, 0.1400860329075968, 0], + [-10.380000000237487, -0.08400000000499297, 0] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000499227, 9.313225746154785e-10], + [-9.880000000121072, -0.0740000000049923, -9.313225746154785e-10], + [-9.880000000121072, -0.17400000000499372, -9.313225746154785e-10], + [-8.680000000284053, -0.1500000000049937, 9.313225746154785e-10], + [-8.680000000284053, -0.05000000000499227, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000499227, 0], + [-6.680000000284053, -0.010000000004992238, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000237487, -0.08400000000499297, 0], + [-9.880000000353903, -0.0740000000049923, 0] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6, -0.12000000000499433, -9.313225746154785e-10], + [-6.500000000349246, -0.16000000000499437, 0], + [-6.53000000002794, -0.010000000004994014, -9.313225746154785e-10], + [-6.680000000167638, -0.010000000004994014, 9.313225746154785e-10], + [-6.680000000167638, -0.3300000000049934, 9.313225746154785e-10], + [-6, -0.3300000000049934, -9.313225746154785e-10], + [-6, -0.12000000000499433, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000102d", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.009849783964455, -0.3302517155538194, -1.862645149230957e-9], + [6.5050995904020965, -0.3302517155538194, -1.862645149230957e-9], + [6.689849783782847, -0.32992302906745863, -9.313225746154785e-10], + [6.689849783782847, -0.009923029067459233, -9.313225746154785e-10], + [6.6468152336310595, -0.009999591230094751, -1.862645149230957e-9], + [6.539849783643149, -0.009999591243764705, 0], + [6.5098497837316245, -0.1600146135503513, -9.313225746154785e-10], + [6.152845289441757, -0.13145425399504784, -9.313225746154785e-10], + [6.009849783964455, -0.12025171555381853, -1.862645149230957e-9], + [6.009849783964455, -0.3302517155538194, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001029", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.689849783782847, -0.009923029067458344, -9.313225746154785e-10], + [7.432176180649549, -0.023448894482823057, -1.862645149230957e-9], + [8.689849783666432, -0.048602366564344024, 0] + ] + ] + }, + { + "elementId": "0x20000001027", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [9.222578136483207, -0.15805021063472324, -1.862645149230957e-9], + [9.889849783852696, -0.1713956435702162, -9.313225746154785e-10], + [9.889849783852696, -0.07139564357021566, -9.313225746154785e-10], + [9.222578136483207, -0.05805021063472271, -1.862645149230957e-9], + [8.689849783899263, -0.04860236656434491, 0], + [8.689849783899263, -0.14860236656434544, 0], + [9.222578136483207, -0.15805021063472324, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x2000000102b", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [9.889849783736281, -0.0713956435570493, -9.313225746154785e-10], + [10.131568165728822, -0.07557511702494502, -9.313225746154785e-10], + [10.389849783852696, -0.08074074936673448, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000001025", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.389849783852696, -0.08074074938234865, -9.313225746154785e-10], + [10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10], + [10.860269933007658, 0.07677824947917156, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000102f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.631802612915635, -0.09937676230103598, -9.313225746154785e-10], + [10.860269933007658, -0.0232217505208272, -9.313225746154785e-10], + [10.860269933007658, 0.07677824947917156, -9.313225746154785e-10], + [10.631802612915635, 0.0006232376989618871, -9.313225746154785e-10], + [10.389849783852696, -0.08074074938234865, -9.313225746154785e-10], + [10.389849783852696, -0.18074074938234652, -9.313225746154785e-10], + [10.631802612915635, -0.09937676230103598, -9.313225746154785e-10] + ] + ] + } + ] +} diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionC.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionC.json index 8d02e0f7edbf..79a136802f0b 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionC.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionC.json @@ -1,227 +1,212 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 20, - "ray": { - "origin": [ 508068.5686794229, 6645766.693956678, 5.277728901214461 ], - "direction": [ 0.17828222297866367, 0.9839793945859772, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 20, + "ray": { + "origin": [508068.5686794229, 6645766.693956678, 5.277728901214461], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000349246, -0.12000000000384681, 9.313225746154785e-10], + [-6.000000000349246, -0.16000000000384684, 9.313225746154785e-10], + [0, -0.040000000000000036, 0], + [5.999999999650754, -0.15999999999926562, 1.862645149230957e-9], + [5.999999999650754, -0.11999999999926558, 1.862645149230957e-9], + [0, 0, 0] + ] + ] }, - "elements": [ - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, 0, 0 ], - [ -6.000000000349246, -0.12000000000384681, 9.313225746154785e-10 ], - [ -6.000000000349246, -0.16000000000384684, 9.313225746154785e-10 ], - [ 0, -0.040000000000000036, 0 ], - [ 5.999999999650754, -0.15999999999926562, 1.862645149230957e-9 ], - [ 5.999999999650754, -0.11999999999926558, 1.862645149230957e-9 ], - [ 0, 0, 0 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.040000000000000036, 0 ], - [ -6.000000000349246, -0.16000000000384684, 9.313225746154785e-10 ], - [ -6.000000000349246, -0.3100000000038481, 9.313225746154785e-10 ], - [ 0, -0.1900000000000004, 0 ], - [ 5.999999999650754, -0.309999999999266, 1.862645149230957e-9 ], - [ 5.999999999650754, -0.15999999999926562, 1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.1900000000000004, 0 ], - [ -6.000000000349246, -0.3100000000038481, 9.313225746154785e-10 ], - [ -6.000000000349246, -0.5100000000038483, 9.313225746154785e-10 ], - [ 0, -0.39000000000000057, 0 ], - [ 5.999999999650754, -0.5099999999992653, 1.862645149230957e-9 ], - [ 5.999999999650754, -0.309999999999266, 1.862645149230957e-9 ], - [ 0, -0.1900000000000004, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f98", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9 ], - [ 6.679999999701977, -0.32999999999926555, 1.862645149230957e-9 ], - [ 6.679999999701977, -0.009999999999265263, 1.862645149230957e-9 ], - [ 6.529999999795109, -0.009999999999265263, 1.862645149230957e-9 ], - [ 6.499999999767169, -0.15999999999926562, 2.7939677238464355e-9 ], - [ 5.999999999767169, -0.11999999999926558, 2.7939677238464355e-9 ], - [ 5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f92", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.14999999999926583, 0 ], - [ 9.879999999888241, -0.17399999999926585, 1.862645149230957e-9 ], - [ 9.879999999888241, -0.07399999999926443, 1.862645149230957e-9 ], - [ 8.680000000051223, -0.04999999999926441, 0 ], - [ 8.680000000051223, -0.14999999999926583, 0 ] - ] - ] - }, - { - "elementId": "0x20000000fa5", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.379999999771826, -0.18399999999926564, 9.313225746154785e-10 ], - [ 10.85427225427702, -0.025910829392767454, 1.862645149230957e-9 ], - [ 10.85427225427702, 0.07408917060723219, 1.862645149230957e-9 ], - [ 10.379999999771826, -0.083999999999266, 9.313225746154785e-10 ], - [ 10.379999999771826, -0.18399999999926564, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000fa3", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.85427225427702, 0.07408917060723219, 1.862645149230957e-9 ], - [ 10.379999999771826, -0.083999999999266, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f96", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.379999999771826, -0.083999999999266, 9.313225746154785e-10 ], - [ 9.879999999888241, -0.07399999999926443, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f94", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.04999999999926441, 0 ], - [ 6.679999999701977, -0.009999999999265263, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f9f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9 ], - [ -10.452001590980217, -0.059999709788664646, 1.862645149230957e-9 ], - [ -10.452001590980217, -0.1599997097886634, 1.862645149230957e-9 ], - [ -10.380000000470318, -0.18400000000384864, 2.7939677238464355e-9 ], - [ -10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f9d", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.452001590980217, -0.059999709788664646, 1.862645149230957e-9 ], - [ -10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f81", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000284053, -0.05000000000384741, 1.862645149230957e-9 ], - [ -9.880000000353903, -0.07400000000384743, 9.313225746154785e-10 ], - [ -9.880000000353903, -0.17400000000384797, 9.313225746154785e-10 ], - [ -8.680000000284053, -0.15000000000384794, 1.862645149230957e-9 ], - [ -8.680000000284053, -0.05000000000384741, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f82", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000167638, -0.05000000000384652, 1.862645149230957e-9 ], - [ -6.680000000167638, -0.010000000003847376, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f83", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000237487, -0.08400000000384722, 9.313225746154785e-10 ], - [ -9.880000000353903, -0.07400000000384743, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f85", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -6.000000000232831, -0.12000000000384681, 1.862645149230957e-9 ], - [ -6.500000000116415, -0.16000000000384684, 9.313225746154785e-10 ], - [ -6.530000000377186, -0.010000000003847376, 1.862645149230957e-9 ], - [ -6.680000000284053, -0.010000000003847376, 9.313225746154785e-10 ], - [ -6.680000000284053, -0.33000000000384766, 9.313225746154785e-10 ], - [ -6.000000000232831, -0.33000000000384766, 1.862645149230957e-9 ], - [ -6.000000000232831, -0.12000000000384681, 1.862645149230957e-9 ] - ] - ] - } - ] -} \ No newline at end of file + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000349246, -0.16000000000384684, 9.313225746154785e-10], + [-6.000000000349246, -0.3100000000038481, 9.313225746154785e-10], + [0, -0.1900000000000004, 0], + [5.999999999650754, -0.309999999999266, 1.862645149230957e-9], + [5.999999999650754, -0.15999999999926562, 1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1900000000000004, 0], + [-6.000000000349246, -0.3100000000038481, 9.313225746154785e-10], + [-6.000000000349246, -0.5100000000038483, 9.313225746154785e-10], + [0, -0.39000000000000057, 0], + [5.999999999650754, -0.5099999999992653, 1.862645149230957e-9], + [5.999999999650754, -0.309999999999266, 1.862645149230957e-9], + [0, -0.1900000000000004, 0] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9], + [6.679999999701977, -0.32999999999926555, 1.862645149230957e-9], + [6.679999999701977, -0.009999999999265263, 1.862645149230957e-9], + [6.529999999795109, -0.009999999999265263, 1.862645149230957e-9], + [6.499999999767169, -0.15999999999926562, 2.7939677238464355e-9], + [5.999999999767169, -0.11999999999926558, 2.7939677238464355e-9], + [5.999999999767169, -0.32999999999926555, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999926583, 0], + [9.879999999888241, -0.17399999999926585, 1.862645149230957e-9], + [9.879999999888241, -0.07399999999926443, 1.862645149230957e-9], + [8.680000000051223, -0.04999999999926441, 0], + [8.680000000051223, -0.14999999999926583, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999771826, -0.18399999999926564, 9.313225746154785e-10], + [10.85427225427702, -0.025910829392767454, 1.862645149230957e-9], + [10.85427225427702, 0.07408917060723219, 1.862645149230957e-9], + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10], + [10.379999999771826, -0.18399999999926564, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.85427225427702, 0.07408917060723219, 1.862645149230957e-9], + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999771826, -0.083999999999266, 9.313225746154785e-10], + [9.879999999888241, -0.07399999999926443, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.04999999999926441, 0], + [6.679999999701977, -0.009999999999265263, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9], + [-10.452001590980217, -0.059999709788664646, 1.862645149230957e-9], + [-10.452001590980217, -0.1599997097886634, 1.862645149230957e-9], + [-10.380000000470318, -0.18400000000384864, 2.7939677238464355e-9], + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.452001590980217, -0.059999709788664646, 1.862645149230957e-9], + [-10.380000000470318, -0.08400000000384811, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000284053, -0.05000000000384741, 1.862645149230957e-9], + [-9.880000000353903, -0.07400000000384743, 9.313225746154785e-10], + [-9.880000000353903, -0.17400000000384797, 9.313225746154785e-10], + [-8.680000000284053, -0.15000000000384794, 1.862645149230957e-9], + [-8.680000000284053, -0.05000000000384741, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000167638, -0.05000000000384652, 1.862645149230957e-9], + [-6.680000000167638, -0.010000000003847376, 0] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000237487, -0.08400000000384722, 9.313225746154785e-10], + [-9.880000000353903, -0.07400000000384743, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.000000000232831, -0.12000000000384681, 1.862645149230957e-9], + [-6.500000000116415, -0.16000000000384684, 9.313225746154785e-10], + [-6.530000000377186, -0.010000000003847376, 1.862645149230957e-9], + [-6.680000000284053, -0.010000000003847376, 9.313225746154785e-10], + [-6.680000000284053, -0.33000000000384766, 9.313225746154785e-10], + [-6.000000000232831, -0.33000000000384766, 1.862645149230957e-9], + [-6.000000000232831, -0.12000000000384681, 1.862645149230957e-9] + ] + ] + } + ] +} diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionD.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionD.json index b533442cd60d..7992f2394e2a 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionD.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionD.json @@ -1,227 +1,212 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 30, - "ray": { - "origin": [ 508070.3515016527, 6645776.533750624, 5.071936571024687 ], - "direction": [ 0.17828222297866367, 0.9839793945859772, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 30, + "ray": { + "origin": [508070.3515016527, 6645776.533750624, 5.071936571024687], + "direction": [0.17828222297866367, 0.9839793945859772, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9], + [-6.000000000232831, -0.15999999999926562, 1.862645149230957e-9], + [0, -0.040000000000000036, 0], + [6.000000000465661, -0.16000000000270198, 0], + [6.000000000465661, -0.12000000000270195, 0], + [0, 0, 0] + ] + ] }, - "elements": [ - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, 0, 0 ], - [ -6.000000000232831, -0.11999999999926558, 1.862645149230957e-9 ], - [ -6.000000000232831, -0.15999999999926562, 1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ], - [ 6.000000000465661, -0.16000000000270198, 0 ], - [ 6.000000000465661, -0.12000000000270195, 0 ], - [ 0, 0, 0 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.040000000000000036, 0 ], - [ -6.000000000232831, -0.15999999999926562, 1.862645149230957e-9 ], - [ -6.000000000232831, -0.309999999999266, 1.862645149230957e-9 ], - [ 0, -0.1900000000000004, 0 ], - [ 6.000000000465661, -0.31000000000270234, 0 ], - [ 6.000000000465661, -0.16000000000270198, 0 ], - [ 0, -0.040000000000000036, 0 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.1900000000000004, 0 ], - [ -6.000000000232831, -0.309999999999266, 1.862645149230957e-9 ], - [ -6.000000000232831, -0.5099999999992653, 1.862645149230957e-9 ], - [ 0, -0.39000000000000057, 0 ], - [ 6.000000000465661, -0.5100000000027016, 0 ], - [ 6.000000000465661, -0.31000000000270234, 0 ], - [ 0, -0.1900000000000004, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f98", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.000000000116415, -0.3300000000027019, 1.862645149230957e-9 ], - [ 6.680000000284053, -0.3300000000027019, 0 ], - [ 6.680000000284053, -0.010000000002701626, 0 ], - [ 6.529999999795109, -0.010000000002701626, 2.7939677238464355e-9 ], - [ 6.500000000232831, -0.16000000000270198, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.12000000000270195, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.3300000000027019, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f92", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000167638, -0.1500000000027022, 0 ], - [ 9.880000000004657, -0.17400000000270222, 1.862645149230957e-9 ], - [ 9.880000000004657, -0.07400000000270168, 1.862645149230957e-9 ], - [ 8.680000000167638, -0.05000000000270166, 0 ], - [ 8.680000000167638, -0.1500000000027022, 0 ] - ] - ] - }, - { - "elementId": "0x20000000fa5", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.379999999888241, -0.184000000002702, 9.313225746154785e-10 ], - [ 10.788921954343095, -0.04769404485953377, 1.862645149230957e-9 ], - [ 10.788921954343095, 0.052305955140465876, 1.862645149230957e-9 ], - [ 10.379999999888241, -0.08400000000270236, 9.313225746154785e-10 ], - [ 10.379999999888241, -0.184000000002702, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000fa3", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.788921954343095, 0.052305955140465876, 1.862645149230957e-9 ], - [ 10.379999999888241, -0.08400000000270236, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f96", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.379999999888241, -0.08400000000270236, 9.313225746154785e-10 ], - [ 9.880000000004657, -0.07400000000270168, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f94", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000167638, -0.05000000000270166, 0 ], - [ 6.680000000167638, -0.010000000002701626, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f9f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000121072, -0.083999999999266, 1.862645149230957e-9 ], - [ -10.684205847093835, 0.017400935047763078, 1.862645149230957e-9 ], - [ -10.684205847093835, -0.08259906495223479, 1.862645149230957e-9 ], - [ -10.380000000121072, -0.18399999999926564, 1.862645149230957e-9 ], - [ -10.380000000121072, -0.083999999999266, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f9d", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.684205847093835, 0.017400935047763966, 1.862645149230957e-9 ], - [ -10.380000000121072, -0.083999999999266, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f81", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000051223, -0.04999999999926441, 1.862645149230957e-9 ], - [ -9.880000000121072, -0.07399999999926443, 1.862645149230957e-9 ], - [ -9.880000000121072, -0.17399999999926585, 1.862645149230957e-9 ], - [ -8.680000000051223, -0.14999999999926583, 1.862645149230957e-9 ], - [ -8.680000000051223, -0.04999999999926441, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f82", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.680000000051223, -0.04999999999926441, 2.7939677238464355e-9 ], - [ -6.679999999934807, -0.009999999999265263, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f83", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.379999999771826, -0.08399999999926511, 9.313225746154785e-10 ], - [ -9.879999999888241, -0.07399999999926443, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f85", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -6.000000000232831, -0.11999999999926558, 1.862645149230957e-9 ], - [ -6.5, -0.15999999999926562, 1.862645149230957e-9 ], - [ -6.529999999678694, -0.009999999999265263, 0 ], - [ -6.679999999934807, -0.009999999999265263, 9.313225746154785e-10 ], - [ -6.679999999934807, -0.32999999999926644, 9.313225746154785e-10 ], - [ -6.000000000232831, -0.32999999999926644, 1.862645149230957e-9 ], - [ -6.000000000232831, -0.11999999999926558, 1.862645149230957e-9 ] - ] - ] - } - ] -} \ No newline at end of file + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-6.000000000232831, -0.15999999999926562, 1.862645149230957e-9], + [-6.000000000232831, -0.309999999999266, 1.862645149230957e-9], + [0, -0.1900000000000004, 0], + [6.000000000465661, -0.31000000000270234, 0], + [6.000000000465661, -0.16000000000270198, 0], + [0, -0.040000000000000036, 0] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1900000000000004, 0], + [-6.000000000232831, -0.309999999999266, 1.862645149230957e-9], + [-6.000000000232831, -0.5099999999992653, 1.862645149230957e-9], + [0, -0.39000000000000057, 0], + [6.000000000465661, -0.5100000000027016, 0], + [6.000000000465661, -0.31000000000270234, 0], + [0, -0.1900000000000004, 0] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000116415, -0.3300000000027019, 1.862645149230957e-9], + [6.680000000284053, -0.3300000000027019, 0], + [6.680000000284053, -0.010000000002701626, 0], + [6.529999999795109, -0.010000000002701626, 2.7939677238464355e-9], + [6.500000000232831, -0.16000000000270198, 1.862645149230957e-9], + [6.000000000116415, -0.12000000000270195, 1.862645149230957e-9], + [6.000000000116415, -0.3300000000027019, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.1500000000027022, 0], + [9.880000000004657, -0.17400000000270222, 1.862645149230957e-9], + [9.880000000004657, -0.07400000000270168, 1.862645149230957e-9], + [8.680000000167638, -0.05000000000270166, 0], + [8.680000000167638, -0.1500000000027022, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999888241, -0.184000000002702, 9.313225746154785e-10], + [10.788921954343095, -0.04769404485953377, 1.862645149230957e-9], + [10.788921954343095, 0.052305955140465876, 1.862645149230957e-9], + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10], + [10.379999999888241, -0.184000000002702, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.788921954343095, 0.052305955140465876, 1.862645149230957e-9], + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.379999999888241, -0.08400000000270236, 9.313225746154785e-10], + [9.880000000004657, -0.07400000000270168, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.05000000000270166, 0], + [6.680000000167638, -0.010000000002701626, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9], + [-10.684205847093835, 0.017400935047763078, 1.862645149230957e-9], + [-10.684205847093835, -0.08259906495223479, 1.862645149230957e-9], + [-10.380000000121072, -0.18399999999926564, 1.862645149230957e-9], + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.684205847093835, 0.017400935047763966, 1.862645149230957e-9], + [-10.380000000121072, -0.083999999999266, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000051223, -0.04999999999926441, 1.862645149230957e-9], + [-9.880000000121072, -0.07399999999926443, 1.862645149230957e-9], + [-9.880000000121072, -0.17399999999926585, 1.862645149230957e-9], + [-8.680000000051223, -0.14999999999926583, 1.862645149230957e-9], + [-8.680000000051223, -0.04999999999926441, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.680000000051223, -0.04999999999926441, 2.7939677238464355e-9], + [-6.679999999934807, -0.009999999999265263, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999771826, -0.08399999999926511, 9.313225746154785e-10], + [-9.879999999888241, -0.07399999999926443, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9], + [-6.5, -0.15999999999926562, 1.862645149230957e-9], + [-6.529999999678694, -0.009999999999265263, 0], + [-6.679999999934807, -0.009999999999265263, 9.313225746154785e-10], + [-6.679999999934807, -0.32999999999926644, 9.313225746154785e-10], + [-6.000000000232831, -0.32999999999926644, 1.862645149230957e-9], + [-6.000000000232831, -0.11999999999926558, 1.862645149230957e-9] + ] + ] + } + ] +} diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionE.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionE.json index 15d143b91268..1851f2433d64 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionE.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionE.json @@ -1,227 +1,212 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 40, - "ray": { - "origin": [ 508071.60238111287, 6645786.443305271, 4.866144240834913 ], - "direction": [ 0.03269890991174909, 0.9994652476652619, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 40, + "ray": { + "origin": [508071.60238111287, 6645786.443305271, 4.866144240834913], + "direction": [0.03269890991174909, 0.9994652476652619, 0] + }, + "elements": [ + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, 0, -9.313225746154785e-10], + [-6.000000000058208, -0.11999999999991129, 9.313225746154785e-10], + [-6.000000000058208, -0.15999999999991132, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10], + [6, -0.15999999999991132, -9.313225746154785e-10], + [6, -0.11999999999991129, -9.313225746154785e-10], + [1.1641532182693481e-10, 0, -9.313225746154785e-10] + ] + ] }, - "elements": [ - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, 0, -9.313225746154785e-10 ], - [ -6.000000000058208, -0.11999999999991129, 9.313225746154785e-10 ], - [ -6.000000000058208, -0.15999999999991132, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10 ], - [ 6, -0.15999999999991132, -9.313225746154785e-10 ], - [ 6, -0.11999999999991129, -9.313225746154785e-10 ], - [ 1.1641532182693481e-10, 0, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10 ], - [ -6.000000000058208, -0.15999999999991132, 9.313225746154785e-10 ], - [ -6.000000000058208, -0.30999999999991257, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10 ], - [ 6, -0.30999999999991257, -9.313225746154785e-10 ], - [ 6, -0.15999999999991132, -9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10 ], - [ -6.000000000058208, -0.30999999999991257, 9.313225746154785e-10 ], - [ -6.000000000058208, -0.5099999999999127, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.39000000000000057, -9.313225746154785e-10 ], - [ 6, -0.5099999999999127, -9.313225746154785e-10 ], - [ 6, -0.30999999999991257, -9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f98", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.000000000058208, -0.32999999999991125, 9.313225746154785e-10 ], - [ 6.680000000051223, -0.32999999999991125, 9.313225746154785e-10 ], - [ 6.680000000051223, -0.009999999999911857, 9.313225746154785e-10 ], - [ 6.53000000002794, -0.009999999999911857, 9.313225746154785e-10 ], - [ 6.5, -0.15999999999991132, -9.313225746154785e-10 ], - [ 6.000000000058208, -0.11999999999991129, 9.313225746154785e-10 ], - [ 6.000000000058208, -0.32999999999991125, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f92", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.14999999999991243, 0 ], - [ 9.879999999830034, -0.17399999999991245, 1.862645149230957e-9 ], - [ 9.879999999830034, -0.07399999999991191, 1.862645149230957e-9 ], - [ 8.680000000051223, -0.04999999999991189, 0 ], - [ 8.680000000051223, -0.14999999999991243, 0 ] - ] - ] - }, - { - "elementId": "0x20000000fa5", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.380000000004657, -0.18399999999991135, 9.313225746154785e-10 ], - [ 10.96782595908735, 0.011940026961439365, 2.7939677238464355e-9 ], - [ 10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9 ], - [ 10.380000000004657, -0.08399999999991259, 9.313225746154785e-10 ], - [ 10.380000000004657, -0.18399999999991135, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000fa3", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9 ], - [ 10.380000000004657, -0.08399999999991259, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f96", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.380000000004657, -0.08399999999991259, 9.313225746154785e-10 ], - [ 9.879999999946449, -0.07399999999991191, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f94", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.04999999999991189, 0 ], - [ 6.679999999934807, -0.009999999999911857, 2.7939677238464355e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f9f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000121072, -0.08399999999991348, 1.862645149230957e-9 ], - [ -11.18704475602135, 0.18501222850247867, -9.313225746154785e-10 ], - [ -11.18704475602135, 0.08501222850247814, -9.313225746154785e-10 ], - [ -10.380000000121072, -0.18399999999991135, 1.862645149230957e-9 ], - [ -10.380000000121072, -0.08399999999991348, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f9d", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -11.18704475602135, 0.18501222850247867, -9.313225746154785e-10 ], - [ -10.380000000121072, -0.08399999999991259, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f81", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.679999999993015, -0.04999999999991189, 1.862645149230957e-9 ], - [ -9.880000000121072, -0.07399999999991191, 1.862645149230957e-9 ], - [ -9.880000000121072, -0.17399999999991245, 1.862645149230957e-9 ], - [ -8.679999999993015, -0.14999999999991243, 1.862645149230957e-9 ], - [ -8.679999999993015, -0.04999999999991189, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f82", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.679999999993015, -0.04999999999991189, 1.862645149230957e-9 ], - [ -6.679999999934807, -0.009999999999911857, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f83", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.380000000004657, -0.08399999999991259, 0 ], - [ -9.880000000121072, -0.07399999999991191, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f85", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -6, -0.11999999999991307, -9.313225746154785e-10 ], - [ -6.5, -0.15999999999991132, 1.862645149230957e-9 ], - [ -6.53000000002794, -0.009999999999911857, 0 ], - [ -6.679999999934807, -0.009999999999911857, 0 ], - [ -6.679999999934807, -0.32999999999991125, 0 ], - [ -6, -0.32999999999991125, -9.313225746154785e-10 ], - [ -6, -0.11999999999991307, -9.313225746154785e-10 ] - ] - ] - } - ] -} \ No newline at end of file + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10], + [-6.000000000058208, -0.15999999999991132, 9.313225746154785e-10], + [-6.000000000058208, -0.30999999999991257, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10], + [6, -0.30999999999991257, -9.313225746154785e-10], + [6, -0.15999999999991132, -9.313225746154785e-10], + [1.1641532182693481e-10, -0.040000000000000036, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10], + [-6.000000000058208, -0.30999999999991257, 9.313225746154785e-10], + [-6.000000000058208, -0.5099999999999127, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39000000000000057, -9.313225746154785e-10], + [6, -0.5099999999999127, -9.313225746154785e-10], + [6, -0.30999999999991257, -9.313225746154785e-10], + [1.1641532182693481e-10, -0.1900000000000004, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000058208, -0.32999999999991125, 9.313225746154785e-10], + [6.680000000051223, -0.32999999999991125, 9.313225746154785e-10], + [6.680000000051223, -0.009999999999911857, 9.313225746154785e-10], + [6.53000000002794, -0.009999999999911857, 9.313225746154785e-10], + [6.5, -0.15999999999991132, -9.313225746154785e-10], + [6.000000000058208, -0.11999999999991129, 9.313225746154785e-10], + [6.000000000058208, -0.32999999999991125, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999991243, 0], + [9.879999999830034, -0.17399999999991245, 1.862645149230957e-9], + [9.879999999830034, -0.07399999999991191, 1.862645149230957e-9], + [8.680000000051223, -0.04999999999991189, 0], + [8.680000000051223, -0.14999999999991243, 0] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.18399999999991135, 9.313225746154785e-10], + [10.96782595908735, 0.011940026961439365, 2.7939677238464355e-9], + [10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9], + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999991135, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.96782595908735, 0.11194002696143812, 2.7939677238464355e-9], + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08399999999991259, 9.313225746154785e-10], + [9.879999999946449, -0.07399999999991191, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.04999999999991189, 0], + [6.679999999934807, -0.009999999999911857, 2.7939677238464355e-9] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000121072, -0.08399999999991348, 1.862645149230957e-9], + [-11.18704475602135, 0.18501222850247867, -9.313225746154785e-10], + [-11.18704475602135, 0.08501222850247814, -9.313225746154785e-10], + [-10.380000000121072, -0.18399999999991135, 1.862645149230957e-9], + [-10.380000000121072, -0.08399999999991348, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-11.18704475602135, 0.18501222850247867, -9.313225746154785e-10], + [-10.380000000121072, -0.08399999999991259, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9], + [-9.880000000121072, -0.07399999999991191, 1.862645149230957e-9], + [-9.880000000121072, -0.17399999999991245, 1.862645149230957e-9], + [-8.679999999993015, -0.14999999999991243, 1.862645149230957e-9], + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999993015, -0.04999999999991189, 1.862645149230957e-9], + [-6.679999999934807, -0.009999999999911857, 0] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.380000000004657, -0.08399999999991259, 0], + [-9.880000000121072, -0.07399999999991191, 0] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6, -0.11999999999991307, -9.313225746154785e-10], + [-6.5, -0.15999999999991132, 1.862645149230957e-9], + [-6.53000000002794, -0.009999999999911857, 0], + [-6.679999999934807, -0.009999999999911857, 0], + [-6.679999999934807, -0.32999999999991125, 0], + [-6, -0.32999999999991125, -9.313225746154785e-10], + [-6, -0.11999999999991307, -9.313225746154785e-10] + ] + ] + } + ] +} diff --git a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionF.json b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionF.json index aadb1673cea5..8c5963bc4e25 100644 --- a/core/geometry/src/test/data/ChainCollector/sectionData00/sectionF.json +++ b/core/geometry/src/test/data/ChainCollector/sectionData00/sectionF.json @@ -1,1206 +1,1004 @@ { - "sourceId": "0x20000000f71", - "distanceAlong": 42.64596001776388, - "ray": { - "origin": [ 508071.618903467, 6645789.088904963, 4.8116924130704515 ], - "direction": [ -0.020213083931456988, 0.9997956947486721, 0 ] + "sourceId": "0x20000000f71", + "distanceAlong": 42.64596001776388, + "ray": { + "origin": [508071.618903467, 6645789.088904963, 4.8116924130704515], + "direction": [-0.020213083931456988, 0.9997956947486721, 0] + }, + "elements": [ + { + "elementId": "0x20000000f3a", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-10.379999999771826, -0.08497774903659039, 9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ], + [ + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10], + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10] + ], + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-11.218174668611027, 0.09441101331197643, -9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ], + [ + [-10.379999999771826, -0.18497774903659003, 9.313225746154785e-10], + [-11.218174668611027, 0.19441101331197608, -9.313225746154785e-10] + ] + ] }, - "elements": [ - { - "elementId": "0x20000000f3a", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.379999999771826, -0.18497774903659003, 9.313225746154785e-10 ], - [ -10.379999999771826, -0.08497774903659039, 9.313225746154785e-10 ], - [ -11.218174668611027, 0.19441101331197608, -9.313225746154785e-10 ] - ], - [ - - [ -11.218174668611027, 0.19441101331197608, -9.313225746154785e-10 ], - [ -10.379999999771826, -0.18497774903659003, 9.313225746154785e-10 ] - ], - [ - - [ -10.379999999771826, -0.18497774903659003, 9.313225746154785e-10 ], - [ -11.218174668611027, 0.09441101331197643, -9.313225746154785e-10 ], - [ -11.218174668611027, 0.19441101331197608, -9.313225746154785e-10 ] - ], - [ - - [ -10.379999999771826, -0.18497774903659003, 9.313225746154785e-10 ], - [ -11.218174668611027, 0.19441101331197608, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f32", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -9.880000000004657, -0.17497774903658936, -1.862645149230957e-9 ], - [ -8.679999999934807, -0.05097774903658969, -1.862645149230957e-9 ] - ], - [ - - [ -8.679999999934807, -0.05097774903658969, -1.862645149230957e-9 ], - [ -9.880000000004657, -0.07497774903658971, -1.862645149230957e-9 ], - [ -9.880000000004657, -0.17497774903658936, -1.862645149230957e-9 ] - ], - [ - - [ -8.679999999934807, -0.05097774903658969, -1.862645149230957e-9 ], - [ -8.679999999934807, -0.15097774903658934, -1.862645149230957e-9 ], - [ -9.880000000004657, -0.17497774903658936, -1.862645149230957e-9 ] - ], - [ - - [ -8.679999999934807, -0.05097774903658969, -1.862645149230957e-9 ], - [ -9.880000000004657, -0.17497774903658936, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000001087", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, 0, 0 ], - [ -5.999999999883585, -0.11999999999890498, 0 ] - ], - [ - - [ 6.000000000116415, -0.1199999999960717, 1.862645149230957e-9 ], - [ 0, 0, 0 ] - ], - [ - - [ -5.999999999883585, -0.15999999999890502, 0 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ] - ], - [ - - [ -5.999999999883585, -0.11999999999890498, 0 ], - [ -5.999999999883585, -0.15999999999890502, 0 ] - ], - [ - - [ -5.999999999883585, -0.11999999999890498, 0 ], - [ 0, 0, 0 ] - ], - [ - - [ 0, 0, 0 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ -5.999999999883585, -0.11999999999890498, 0 ] - ], - [ - - [ -5.999999999883585, -0.15999999999890502, 0 ], - [ -5.999999999883585, -0.11999999999890498, 0 ] - ], - [ - - [ -5.999999999883585, -0.11999999999890498, 0 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ -5.999999999883585, -0.15999999999890502, 0 ] - ], - [ - - [ 0, 0, 0 ], - [ 6.000000000116415, -0.1199999999960717, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.1199999999960717, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ], - [ 0, 0, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ 0, 0, 0 ] - ], - [ - - [ 0, 0, 0 ], - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.1199999999960717, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000001089", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.040000000000000036, 0 ], - [ -5.999999999883585, -0.15999999999890502, 0 ] - ], - [ - - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ -5.999999999883585, -0.30999999999890626, 0 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ] - ], - [ - - [ -5.999999999883585, -0.15999999999890502, 0 ], - [ -5.999999999883585, -0.30999999999890626, 0 ] - ], - [ - - [ -5.999999999883585, -0.15999999999890502, 0 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ -5.999999999883585, -0.15999999999890502, 0 ] - ], - [ - - [ -5.999999999883585, -0.30999999999890626, 0 ], - [ -5.999999999883585, -0.15999999999890502, 0 ] - ], - [ - - [ -5.999999999883585, -0.15999999999890502, 0 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ -5.999999999883585, -0.30999999999890626, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ 0, -0.040000000000000036, 0 ] - ], - [ - - [ 0, -0.040000000000000036, 0 ], - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.15999999999607173, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x2000000108b", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 0, -0.1900000000000004, 0 ], - [ -5.999999999883585, -0.30999999999890626, 0 ] - ], - [ - - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ -5.999999999883585, -0.5099999999989064, 0 ], - [ 0, -0.39000000000000057, 0 ] - ], - [ - - [ 0, -0.39000000000000057, 0 ], - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ] - ], - [ - - [ -5.999999999883585, -0.30999999999890626, 0 ], - [ -5.999999999883585, -0.5099999999989064, 0 ] - ], - [ - - [ -5.999999999883585, -0.30999999999890626, 0 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ 0, -0.39000000000000057, 0 ] - ], - [ - - [ 0, -0.39000000000000057, 0 ], - [ -5.999999999883585, -0.30999999999890626, 0 ] - ], - [ - - [ -5.999999999883585, -0.5099999999989064, 0 ], - [ -5.999999999883585, -0.30999999999890626, 0 ] - ], - [ - - [ -5.999999999883585, -0.30999999999890626, 0 ], - [ 0, -0.39000000000000057, 0 ] - ], - [ - - [ 0, -0.39000000000000057, 0 ], - [ -5.999999999883585, -0.5099999999989064, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.39000000000000057, 0 ], - [ 0, -0.1900000000000004, 0 ] - ], - [ - - [ 0, -0.1900000000000004, 0 ], - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ], - [ 0, -0.39000000000000057, 0 ] - ], - [ - - [ 6.000000000116415, -0.5099999999960732, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.309999999996073, 1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f98", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ], - [ 6.680000000051223, -0.32999999999609386, 0 ] - ], - [ - - [ 6.680000000051223, -0.32999999999609386, 0 ], - [ 6.680000000051223, -0.009999999996093578, 0 ] - ], - [ - - [ 6.680000000051223, -0.009999999996093578, 0 ], - [ 6.530000000144355, -0.009999999996093578, 1.862645149230957e-9 ] - ], - [ - - [ 6.530000000144355, -0.009999999996093578, 1.862645149230957e-9 ], - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ] - ], - [ - - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ], - [ 6.000000000116415, -0.1199999999960939, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.1199999999960939, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.1199999999960939, 1.862645149230957e-9 ], - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ] - ], - [ - - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ], - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ], - [ 6.000000000116415, -0.1199999999960939, 1.862645149230957e-9 ] - ], - [ - - [ 6.680000000051223, -0.32999999999609386, 0 ], - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ] - ], - [ - - [ 6.000000000116415, -0.32999999999609386, 1.862645149230957e-9 ], - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ] - ], - [ - - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ], - [ 6.680000000051223, -0.32999999999609386, 0 ] - ], - [ - - [ 6.530000000144355, -0.009999999996093578, 1.862645149230957e-9 ], - [ 6.680000000051223, -0.009999999996093578, 0 ] - ], - [ - - [ 6.680000000051223, -0.009999999996093578, 0 ], - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ] - ], - [ - - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ], - [ 6.530000000144355, -0.009999999996093578, 1.862645149230957e-9 ] - ], - [ - - [ 6.680000000051223, -0.32999999999609386, 0 ], - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ] - ], - [ - - [ 6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9 ], - [ 6.680000000051223, -0.009999999996093578, 0 ] - ], - [ - - [ 6.680000000051223, -0.009999999996093578, 0 ], - [ 6.680000000051223, -0.32999999999609386, 0 ] - ] - ] - }, - { - "elementId": "0x20000000e98", - "categoryId": "0x2000000014b", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ], - [ -5.999999999883585, -0.3109777490295773, 0 ], - [ -5.999999999883585, -0.5109777490295775, 0 ] - ], - [ - - [ -5.999999999883585, -0.5109777490295775, 0 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ], - [ -5.999999999883585, -0.5109777490295775, 0 ] - ], - [ - - [ -5.999999999883585, -0.5109777490295775, 0 ], - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ] - ], - [ - - [ 6.000000000116415, -0.31097774903400577, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ], - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ], - [ 6.000000000116415, -0.31097774903400577, 9.313225746154785e-10 ] - ], - [ - - [ 6.000000000116415, -0.31097774903400577, 9.313225746154785e-10 ], - [ 6.000000000116415, -0.5109777490340068, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ] - ], - [ - - [ 6.000000000116415, -0.31097774903400577, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.39097774901887394, 0 ] - ] - ] - }, - { - "elementId": "0x20000000e96", - "categoryId": "0x2000000014d", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ], - [ -5.999999999883585, -0.16097774902957607, 0 ], - [ -5.999999999883585, -0.3109777490295773, 0 ] - ], - [ - - [ -5.999999999883585, -0.3109777490295773, 0 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ], - [ -5.999999999883585, -0.3109777490295773, 0 ] - ], - [ - - [ -5.999999999883585, -0.3109777490295773, 0 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 6.000000000116415, -0.1609777490340063, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ], - [ 6.000000000116415, -0.1609777490340063, 9.313225746154785e-10 ] - ], - [ - - [ 6.000000000116415, -0.1609777490340063, 9.313225746154785e-10 ], - [ 6.000000000116415, -0.31097774903400577, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ], - [ - - [ 6.000000000116415, -0.1609777490340063, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.19097774901887465, 0 ] - ] - ] - }, - { - "elementId": "0x20000000e94", - "categoryId": "0x20000000255", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ], - [ -5.999999999883585, -0.12097774902957692, 0 ], - [ -5.999999999883585, -0.16097774902957607, 0 ] - ], - [ - - [ -5.999999999883585, -0.16097774902957607, 0 ], - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ], - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ], - [ -5.999999999883585, -0.16097774902957607, 0 ] - ], - [ - - [ -5.999999999883585, -0.16097774902957607, 0 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 6.000000000116415, -0.12097774903400627, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0009777490188742632, 0 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ], - [ 6.000000000116415, -0.12097774903400627, 9.313225746154785e-10 ] - ], - [ - - [ 6.000000000116415, -0.12097774903400627, 9.313225746154785e-10 ], - [ 6.000000000116415, -0.1609777490340063, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ], - [ - - [ 6.000000000116415, -0.12097774903400627, 9.313225746154785e-10 ], - [ 1.1641532182693481e-10, -0.0409777490188743, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f1b", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 6.500000000116415, -0.1609777490340063, 0 ], - [ 6.530000000144355, -0.010977749034005946, -9.313225746154785e-10 ], - [ 6.680000000051223, -0.010977749034005946, -9.313225746154785e-10 ] - ], - [ - - [ 6.500000000116415, -0.1609777490340063, 0 ], - [ 6.680000000051223, -0.010977749034005946, -9.313225746154785e-10 ] - ], - [ - - [ 6.680000000051223, -0.33097774903400623, -9.313225746154785e-10 ], - [ 6.680000000051223, -0.010977749034005946, -9.313225746154785e-10 ] - ], - [ - - [ 6.680000000051223, -0.010977749034005946, -9.313225746154785e-10 ], - [ 6.500000000116415, -0.1609777490340063, 0 ] - ], - [ - - [ 6.500000000116415, -0.1609777490340063, 0 ], - [ 6.680000000051223, -0.33097774903400623, -9.313225746154785e-10 ] - ], - [ - - [ 6.680000000051223, -0.33097774903400623, -9.313225746154785e-10 ], - [ 6.500000000116415, -0.1609777490340063, 0 ] - ], - [ - - [ 6.500000000116415, -0.1609777490340063, 0 ], - [ 6.000000000232831, -0.33097774903400623, -9.313225746154785e-10 ] - ], - [ - - [ 6.000000000232831, -0.33097774903400623, -9.313225746154785e-10 ], - [ 6.680000000051223, -0.33097774903400623, -9.313225746154785e-10 ] - ], - [ - - [ 6.000000000232831, -0.33097774903400623, -9.313225746154785e-10 ], - [ 6.000000000232831, -0.12097774903400715, -9.313225746154785e-10 ], - [ 6.500000000116415, -0.1609777490340063, 0 ] - ], - [ - - [ 6.000000000232831, -0.33097774903400623, -9.313225746154785e-10 ], - [ 6.500000000116415, -0.1609777490340063, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f38", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ], - [ -6, -0.12097774903658998, 0 ], - [ -6, -0.33097774903658994, 0 ] - ], - [ - - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ], - [ -6, -0.33097774903658994, 0 ] - ], - [ - - [ -6.679999999818392, -0.33097774903658994, 0 ], - [ -6, -0.33097774903658994, 0 ] - ], - [ - - [ -6, -0.33097774903658994, 0 ], - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ] - ], - [ - - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ], - [ -6.679999999818392, -0.33097774903658994, 0 ] - ], - [ - - [ -6.679999999818392, -0.010977749036589657, 0 ], - [ -6.529999999911524, -0.010977749036589657, 0 ], - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ] - ], - [ - - [ -6.679999999818392, -0.010977749036589657, 0 ], - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ] - ], - [ - - [ -6.679999999818392, -0.33097774903658994, 0 ], - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ] - ], - [ - - [ -6.5, -0.1609777490365909, -1.862645149230957e-9 ], - [ -6.679999999818392, -0.010977749036589657, 0 ] - ], - [ - - [ -6.679999999818392, -0.010977749036589657, 0 ], - [ -6.679999999818392, -0.33097774903658994, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f1d", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.380000000004657, -0.08497774903400668, -1.862645149230957e-9 ], - [ 10.380000000004657, -0.18497774903400632, -1.862645149230957e-9 ], - [ 10.888796739047393, -0.01538053204497114, -9.313225746154785e-10 ] - ], - [ - - [ 10.888796739047393, -0.01538053204497114, -9.313225746154785e-10 ], - [ 10.380000000004657, -0.08497774903400668, -1.862645149230957e-9 ] - ], - [ - - [ 10.380000000004657, -0.08497774903400668, -1.862645149230957e-9 ], - [ 10.888796739047393, 0.08461946795502762, -9.313225746154785e-10 ], - [ 10.888796739047393, -0.01538053204497114, -9.313225746154785e-10 ] - ], - [ - - [ 10.380000000004657, -0.08497774903400668, -1.862645149230957e-9 ], - [ 10.888796739047393, -0.01538053204497114, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f92", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ], - [ 9.880000000004657, -0.17399999999609417, -9.313225746154785e-10 ] - ], - [ - - [ 9.880000000004657, -0.17399999999609417, -9.313225746154785e-10 ], - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ] - ], - [ - - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ], - [ 8.680000000051223, -0.049999999996093614, 9.313225746154785e-10 ] - ], - [ - - [ 8.680000000051223, -0.049999999996093614, 9.313225746154785e-10 ], - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ] - ], - [ - - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ], - [ 8.680000000051223, -0.049999999996093614, 9.313225746154785e-10 ] - ], - [ - - [ 8.680000000051223, -0.049999999996093614, 9.313225746154785e-10 ], - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ] - ], - [ - - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ], - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ] - ], - [ - - [ 9.880000000004657, -0.17399999999609417, -9.313225746154785e-10 ], - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ] - ], - [ - - [ 8.680000000051223, -0.14999999999609415, 9.313225746154785e-10 ], - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ] - ], - [ - - [ 9.880000000004657, -0.07399999999609363, -9.313225746154785e-10 ], - [ 9.880000000004657, -0.17399999999609417, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000fa5", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.380000000004657, -0.18399999999609395, 0 ], - [ 10.885664732661098, -0.015446774683195663, 9.313225746154785e-10 ] - ], - [ - - [ 10.885664732661098, -0.015446774683195663, 9.313225746154785e-10 ], - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ] - ], - [ - - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ], - [ 10.380000000004657, -0.08399999999609431, 0 ] - ], - [ - - [ 10.380000000004657, -0.08399999999609431, 0 ], - [ 10.380000000004657, -0.18399999999609395, 0 ] - ], - [ - - [ 10.380000000004657, -0.18399999999609395, 0 ], - [ 10.380000000004657, -0.08399999999609431, 0 ] - ], - [ - - [ 10.380000000004657, -0.08399999999609431, 0 ], - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ] - ], - [ - - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ], - [ 10.380000000004657, -0.18399999999609395, 0 ] - ], - [ - - [ 10.885664732661098, -0.015446774683195663, 9.313225746154785e-10 ], - [ 10.380000000004657, -0.18399999999609395, 0 ] - ], - [ - - [ 10.380000000004657, -0.18399999999609395, 0 ], - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ] - ], - [ - - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ], - [ 10.885664732661098, -0.015446774683195663, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000fa3", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.885664732661098, 0.0845532253168031, 9.313225746154785e-10 ], - [ 10.380000000004657, -0.08399999999609431, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f96", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 10.380000000004657, -0.08399999999609431, 0 ], - [ 9.880000000004657, -0.07399999999609363, 9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f94", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000167638, -0.049999999996093614, 9.313225746154785e-10 ], - [ 6.680000000284053, -0.009999999996093578, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f9f", - "categoryId": "0x20000000199", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.379999999888241, -0.08399999999890717, 0 ], - [ -11.214947268133983, 0.19431297293451877, -9.313225746154785e-10 ] - ], - [ - - [ -11.214947268133983, 0.19431297293451877, -9.313225746154785e-10 ], - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ] - ], - [ - - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ], - [ -10.379999999888241, -0.18399999999890504, 0 ] - ], - [ - - [ -10.379999999888241, -0.18399999999890504, 0 ], - [ -10.379999999888241, -0.08399999999890717, 0 ] - ], - [ - - [ -10.379999999888241, -0.08399999999890717, 0 ], - [ -10.379999999888241, -0.18399999999890504, 0 ] - ], - [ - - [ -10.379999999888241, -0.18399999999890504, 0 ], - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ] - ], - [ - - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ], - [ -10.379999999888241, -0.08399999999890717, 0 ] - ], - [ - - [ -11.214947268133983, 0.19431297293451877, -9.313225746154785e-10 ], - [ -10.379999999888241, -0.08399999999890717, 0 ] - ], - [ - - [ -10.379999999888241, -0.08399999999890717, 0 ], - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ] - ], - [ - - [ -11.214947268133983, 0.09431297293452001, -9.313225746154785e-10 ], - [ -11.214947268133983, 0.19431297293451877, -9.313225746154785e-10 ] - ] - ] - }, - { - "elementId": "0x20000000f9d", - "categoryId": "0x20000000147", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -11.214947268133983, 0.19431297293451877, -9.313225746154785e-10 ], - [ -10.379999999888241, -0.08399999999890628, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f81", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.679999999818392, -0.04999999999890559, 0 ], - [ -9.879999999888241, -0.07399999999890561, 0 ] - ], - [ - - [ -9.879999999888241, -0.07399999999890561, 0 ], - [ -9.879999999888241, -0.17399999999890614, 0 ] - ], - [ - - [ -9.879999999888241, -0.17399999999890614, 0 ], - [ -8.679999999818392, -0.14999999999890612, 0 ] - ], - [ - - [ -8.679999999818392, -0.14999999999890612, 0 ], - [ -8.679999999818392, -0.04999999999890559, 0 ] - ], - [ - - [ -8.679999999818392, -0.04999999999890559, 0 ], - [ -8.679999999818392, -0.14999999999890612, 0 ] - ], - [ - - [ -8.679999999818392, -0.14999999999890612, 0 ], - [ -9.879999999888241, -0.17399999999890614, 0 ] - ], - [ - - [ -9.879999999888241, -0.17399999999890614, 0 ], - [ -8.679999999818392, -0.04999999999890559, 0 ] - ], - [ - - [ -9.879999999888241, -0.07399999999890561, 0 ], - [ -8.679999999818392, -0.04999999999890559, 0 ] - ], - [ - - [ -8.679999999818392, -0.04999999999890559, 0 ], - [ -9.879999999888241, -0.17399999999890614, 0 ] - ], - [ - - [ -9.879999999888241, -0.17399999999890614, 0 ], - [ -9.879999999888241, -0.07399999999890561, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f82", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -8.679999999934807, -0.04999999999890559, -9.313225746154785e-10 ], - [ -6.679999999818392, -0.009999999998905551, -1.862645149230957e-9 ] - ] - ] - }, - { - "elementId": "0x20000000f83", - "categoryId": "0x20000000253", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -10.379999999888241, -0.08399999999890628, 0 ], - [ -9.880000000004657, -0.07399999999890561, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f85", - "categoryId": "0x20000000153", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ -5.999999999883585, -0.11999999999890676, 0 ], - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ] - ], - [ - - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ], - [ -6.529999999911524, -0.009999999998905551, 0 ] - ], - [ - - [ -6.529999999911524, -0.009999999998905551, 0 ], - [ -6.679999999818392, -0.009999999998905551, 0 ] - ], - [ - - [ -6.679999999818392, -0.009999999998905551, 0 ], - [ -6.679999999818392, -0.32999999999890495, 0 ] - ], - [ - - [ -6.679999999818392, -0.32999999999890495, 0 ], - [ -5.999999999883585, -0.32999999999890495, 0 ] - ], - [ - - [ -5.999999999883585, -0.32999999999890495, 0 ], - [ -5.999999999883585, -0.11999999999890676, 0 ] - ], - [ - - [ -6.529999999911524, -0.009999999998905551, 0 ], - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ] - ], - [ - - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ], - [ -6.679999999818392, -0.009999999998905551, 0 ] - ], - [ - - [ -6.679999999818392, -0.009999999998905551, 0 ], - [ -6.529999999911524, -0.009999999998905551, 0 ] - ], - [ - - [ -6.679999999818392, -0.32999999999890495, 0 ], - [ -6.679999999818392, -0.009999999998905551, 0 ] - ], - [ - - [ -6.679999999818392, -0.009999999998905551, 0 ], - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ] - ], - [ - - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ], - [ -6.679999999818392, -0.32999999999890495, 0 ] - ], - [ - - [ -6.679999999818392, -0.32999999999890495, 0 ], - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ] - ], - [ - - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ], - [ -5.999999999883585, -0.32999999999890495, 0 ] - ], - [ - - [ -5.999999999883585, -0.32999999999890495, 0 ], - [ -6.679999999818392, -0.32999999999890495, 0 ] - ], - [ - - [ -5.999999999883585, -0.11999999999890676, 0 ], - [ -5.999999999883585, -0.32999999999890495, 0 ] - ], - [ - - [ -5.999999999883585, -0.32999999999890495, 0 ], - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ] - ], - [ - - [ -6.499999999883585, -0.15999999999890502, -9.313225746154785e-10 ], - [ -5.999999999883585, -0.11999999999890676, 0 ] - ] - ] - }, - { - "elementId": "0x20000000f17", - "categoryId": "0x20000000183", - "modelId": "0x200000003c7", - "geometries": [ - [ - - [ 8.680000000051223, -0.05097774903400598, -1.862645149230957e-9 ], - [ 8.680000000051223, -0.15097774903400651, -1.862645149230957e-9 ], - [ 9.880000000004657, -0.17497774903400565, -1.862645149230957e-9 ] - ], - [ - - [ 9.880000000004657, -0.17497774903400565, -1.862645149230957e-9 ], - [ 8.680000000051223, -0.05097774903400598, -1.862645149230957e-9 ] - ], - [ - - [ 8.680000000051223, -0.05097774903400598, -1.862645149230957e-9 ], - [ 9.880000000004657, -0.074977749034006, -1.862645149230957e-9 ], - [ 9.880000000004657, -0.17497774903400565, -1.862645149230957e-9 ] - ], - [ - - [ 8.680000000051223, -0.05097774903400598, -1.862645149230957e-9 ], - [ 9.880000000004657, -0.17497774903400565, -1.862645149230957e-9 ] - ] - ] - } - ] + { + "elementId": "0x20000000f32", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9], + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-9.880000000004657, -0.07497774903658971, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-8.679999999934807, -0.15097774903658934, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ], + [ + [-8.679999999934807, -0.05097774903658969, -1.862645149230957e-9], + [-9.880000000004657, -0.17497774903658936, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001087", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, 0, 0], + [-5.999999999883585, -0.11999999999890498, 0] + ], + [ + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9], + [0, 0, 0] + ], + [ + [-5.999999999883585, -0.15999999999890502, 0], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.040000000000000036, 0], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ], + [ + [-5.999999999883585, -0.11999999999890498, 0], + [-5.999999999883585, -0.15999999999890502, 0] + ], + [ + [-5.999999999883585, -0.11999999999890498, 0], + [0, 0, 0] + ], + [ + [0, 0, 0], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.040000000000000036, 0], + [-5.999999999883585, -0.11999999999890498, 0] + ], + [ + [-5.999999999883585, -0.15999999999890502, 0], + [-5.999999999883585, -0.11999999999890498, 0] + ], + [ + [-5.999999999883585, -0.11999999999890498, 0], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.040000000000000036, 0], + [-5.999999999883585, -0.15999999999890502, 0] + ], + [ + [0, 0, 0], + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [0, 0, 0] + ], + [ + [0, -0.040000000000000036, 0], + [0, 0, 0] + ], + [ + [0, 0, 0], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [6.000000000116415, -0.1199999999960717, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000001089", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.040000000000000036, 0], + [-5.999999999883585, -0.15999999999890502, 0] + ], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ], + [ + [-5.999999999883585, -0.30999999999890626, 0], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.1900000000000004, 0], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ], + [ + [-5.999999999883585, -0.15999999999890502, 0], + [-5.999999999883585, -0.30999999999890626, 0] + ], + [ + [-5.999999999883585, -0.15999999999890502, 0], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.040000000000000036, 0], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.1900000000000004, 0], + [-5.999999999883585, -0.15999999999890502, 0] + ], + [ + [-5.999999999883585, -0.30999999999890626, 0], + [-5.999999999883585, -0.15999999999890502, 0] + ], + [ + [-5.999999999883585, -0.15999999999890502, 0], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.1900000000000004, 0], + [-5.999999999883585, -0.30999999999890626, 0] + ], + [ + [0, -0.040000000000000036, 0], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.1900000000000004, 0], + [0, -0.040000000000000036, 0] + ], + [ + [0, -0.040000000000000036, 0], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [0, -0.1900000000000004, 0] + ], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [6.000000000116415, -0.15999999999607173, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x2000000108b", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [0, -0.1900000000000004, 0], + [-5.999999999883585, -0.30999999999890626, 0] + ], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [0, -0.1900000000000004, 0] + ], + [ + [-5.999999999883585, -0.5099999999989064, 0], + [0, -0.39000000000000057, 0] + ], + [ + [0, -0.39000000000000057, 0], + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9] + ], + [ + [-5.999999999883585, -0.30999999999890626, 0], + [-5.999999999883585, -0.5099999999989064, 0] + ], + [ + [-5.999999999883585, -0.30999999999890626, 0], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.1900000000000004, 0], + [0, -0.39000000000000057, 0] + ], + [ + [0, -0.39000000000000057, 0], + [-5.999999999883585, -0.30999999999890626, 0] + ], + [ + [-5.999999999883585, -0.5099999999989064, 0], + [-5.999999999883585, -0.30999999999890626, 0] + ], + [ + [-5.999999999883585, -0.30999999999890626, 0], + [0, -0.39000000000000057, 0] + ], + [ + [0, -0.39000000000000057, 0], + [-5.999999999883585, -0.5099999999989064, 0] + ], + [ + [0, -0.1900000000000004, 0], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9], + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.39000000000000057, 0], + [0, -0.1900000000000004, 0] + ], + [ + [0, -0.1900000000000004, 0], + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], + [0, -0.39000000000000057, 0] + ], + [ + [6.000000000116415, -0.5099999999960732, 1.862645149230957e-9], + [6.000000000116415, -0.309999999996073, 1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f98", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.680000000051223, -0.32999999999609386, 0] + ], + [ + [6.680000000051223, -0.32999999999609386, 0], + [6.680000000051223, -0.009999999996093578, 0] + ], + [ + [6.680000000051223, -0.009999999996093578, 0], + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9] + ], + [ + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.000000000116415, -0.1199999999960939, 1.862645149230957e-9] + ], + [ + [6.680000000051223, -0.32999999999609386, 0], + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9] + ], + [ + [6.000000000116415, -0.32999999999609386, 1.862645149230957e-9], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.680000000051223, -0.32999999999609386, 0] + ], + [ + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9], + [6.680000000051223, -0.009999999996093578, 0] + ], + [ + [6.680000000051223, -0.009999999996093578, 0], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.530000000144355, -0.009999999996093578, 1.862645149230957e-9] + ], + [ + [6.680000000051223, -0.32999999999609386, 0], + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9] + ], + [ + [6.500000000232831, -0.15999999999609393, 2.7939677238464355e-9], + [6.680000000051223, -0.009999999996093578, 0] + ], + [ + [6.680000000051223, -0.009999999996093578, 0], + [6.680000000051223, -0.32999999999609386, 0] + ] + ] + }, + { + "elementId": "0x20000000e98", + "categoryId": "0x2000000014b", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [-5.999999999883585, -0.3109777490295773, 0], + [-5.999999999883585, -0.5109777490295775, 0] + ], + [ + [-5.999999999883585, -0.5109777490295775, 0], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [1.1641532182693481e-10, -0.39097774901887394, 0], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [-5.999999999883585, -0.5109777490295775, 0] + ], + [ + [-5.999999999883585, -0.5109777490295775, 0], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ], + [ + [1.1641532182693481e-10, -0.39097774901887394, 0], + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [6.000000000116415, -0.5109777490340068, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ], + [ + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.39097774901887394, 0] + ] + ] + }, + { + "elementId": "0x20000000e96", + "categoryId": "0x2000000014d", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [-5.999999999883585, -0.16097774902957607, 0], + [-5.999999999883585, -0.3109777490295773, 0] + ], + [ + [-5.999999999883585, -0.3109777490295773, 0], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [-5.999999999883585, -0.3109777490295773, 0] + ], + [ + [-5.999999999883585, -0.3109777490295773, 0], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [1.1641532182693481e-10, -0.19097774901887465, 0], + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [6.000000000116415, -0.31097774903400577, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ], + [ + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.19097774901887465, 0] + ] + ] + }, + { + "elementId": "0x20000000e94", + "categoryId": "0x20000000255", + "modelId": "0x200000003c7", + "geometries": [ + [ + [1.1641532182693481e-10, -0.0009777490188742632, 0], + [-5.999999999883585, -0.12097774902957692, 0], + [-5.999999999883585, -0.16097774902957607, 0] + ], + [ + [-5.999999999883585, -0.16097774902957607, 0], + [1.1641532182693481e-10, -0.0009777490188742632, 0] + ], + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [1.1641532182693481e-10, -0.0009777490188742632, 0] + ], + [ + [1.1641532182693481e-10, -0.0009777490188742632, 0], + [-5.999999999883585, -0.16097774902957607, 0] + ], + [ + [-5.999999999883585, -0.16097774902957607, 0], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0009777490188742632, 0] + ], + [ + [1.1641532182693481e-10, -0.0009777490188742632, 0], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [1.1641532182693481e-10, -0.0409777490188743, 0], + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10] + ], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [6.000000000116415, -0.1609777490340063, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ], + [ + [6.000000000116415, -0.12097774903400627, 9.313225746154785e-10], + [1.1641532182693481e-10, -0.0409777490188743, 0] + ] + ] + }, + { + "elementId": "0x20000000f1b", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.530000000144355, -0.010977749034005946, -9.313225746154785e-10], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10], + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.010977749034005946, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.500000000116415, -0.1609777490340063, 0], + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.680000000051223, -0.33097774903400623, -9.313225746154785e-10] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.000000000232831, -0.12097774903400715, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ], + [ + [6.000000000232831, -0.33097774903400623, -9.313225746154785e-10], + [6.500000000116415, -0.1609777490340063, 0] + ] + ] + }, + { + "elementId": "0x20000000f38", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-6.5, -0.1609777490365909, -1.862645149230957e-9], + [-6, -0.12097774903658998, 0], + [-6, -0.33097774903658994, 0] + ], + [ + [-6.5, -0.1609777490365909, -1.862645149230957e-9], + [-6, -0.33097774903658994, 0] + ], + [ + [-6.679999999818392, -0.33097774903658994, 0], + [-6, -0.33097774903658994, 0] + ], + [ + [-6, -0.33097774903658994, 0], + [-6.5, -0.1609777490365909, -1.862645149230957e-9] + ], + [ + [-6.5, -0.1609777490365909, -1.862645149230957e-9], + [-6.679999999818392, -0.33097774903658994, 0] + ], + [ + [-6.679999999818392, -0.010977749036589657, 0], + [-6.529999999911524, -0.010977749036589657, 0], + [-6.5, -0.1609777490365909, -1.862645149230957e-9] + ], + [ + [-6.679999999818392, -0.010977749036589657, 0], + [-6.5, -0.1609777490365909, -1.862645149230957e-9] + ], + [ + [-6.679999999818392, -0.33097774903658994, 0], + [-6.5, -0.1609777490365909, -1.862645149230957e-9] + ], + [ + [-6.5, -0.1609777490365909, -1.862645149230957e-9], + [-6.679999999818392, -0.010977749036589657, 0] + ], + [ + [-6.679999999818392, -0.010977749036589657, 0], + [-6.679999999818392, -0.33097774903658994, 0] + ] + ] + }, + { + "elementId": "0x20000000f1d", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.380000000004657, -0.18497774903400632, -1.862645149230957e-9], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ], + [ + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10], + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9] + ], + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.888796739047393, 0.08461946795502762, -9.313225746154785e-10], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ], + [ + [10.380000000004657, -0.08497774903400668, -1.862645149230957e-9], + [10.888796739047393, -0.01538053204497114, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f92", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.049999999996093614, 9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10], + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10] + ], + [ + [8.680000000051223, -0.14999999999609415, 9.313225746154785e-10], + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10] + ], + [ + [9.880000000004657, -0.07399999999609363, -9.313225746154785e-10], + [9.880000000004657, -0.17399999999609417, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa5", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.18399999999609395, 0], + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10] + ], + [ + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.08399999999609431, 0] + ], + [ + [10.380000000004657, -0.08399999999609431, 0], + [10.380000000004657, -0.18399999999609395, 0] + ], + [ + [10.380000000004657, -0.18399999999609395, 0], + [10.380000000004657, -0.08399999999609431, 0] + ], + [ + [10.380000000004657, -0.08399999999609431, 0], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999609395, 0] + ], + [ + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10], + [10.380000000004657, -0.18399999999609395, 0] + ], + [ + [10.380000000004657, -0.18399999999609395, 0], + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10] + ], + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.885664732661098, -0.015446774683195663, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000fa3", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.885664732661098, 0.0845532253168031, 9.313225746154785e-10], + [10.380000000004657, -0.08399999999609431, 0] + ] + ] + }, + { + "elementId": "0x20000000f96", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [10.380000000004657, -0.08399999999609431, 0], + [9.880000000004657, -0.07399999999609363, 9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f94", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000167638, -0.049999999996093614, 9.313225746154785e-10], + [6.680000000284053, -0.009999999996093578, 0] + ] + ] + }, + { + "elementId": "0x20000000f9f", + "categoryId": "0x20000000199", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999888241, -0.08399999999890717, 0], + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-10.379999999888241, -0.18399999999890504, 0] + ], + [ + [-10.379999999888241, -0.18399999999890504, 0], + [-10.379999999888241, -0.08399999999890717, 0] + ], + [ + [-10.379999999888241, -0.08399999999890717, 0], + [-10.379999999888241, -0.18399999999890504, 0] + ], + [ + [-10.379999999888241, -0.18399999999890504, 0], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890717, 0] + ], + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890717, 0] + ], + [ + [-10.379999999888241, -0.08399999999890717, 0], + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10] + ], + [ + [-11.214947268133983, 0.09431297293452001, -9.313225746154785e-10], + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10] + ] + ] + }, + { + "elementId": "0x20000000f9d", + "categoryId": "0x20000000147", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-11.214947268133983, 0.19431297293451877, -9.313225746154785e-10], + [-10.379999999888241, -0.08399999999890628, 0] + ] + ] + }, + { + "elementId": "0x20000000f81", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999818392, -0.04999999999890559, 0], + [-9.879999999888241, -0.07399999999890561, 0] + ], + [ + [-9.879999999888241, -0.07399999999890561, 0], + [-9.879999999888241, -0.17399999999890614, 0] + ], + [ + [-9.879999999888241, -0.17399999999890614, 0], + [-8.679999999818392, -0.14999999999890612, 0] + ], + [ + [-8.679999999818392, -0.14999999999890612, 0], + [-8.679999999818392, -0.04999999999890559, 0] + ], + [ + [-8.679999999818392, -0.04999999999890559, 0], + [-8.679999999818392, -0.14999999999890612, 0] + ], + [ + [-8.679999999818392, -0.14999999999890612, 0], + [-9.879999999888241, -0.17399999999890614, 0] + ], + [ + [-9.879999999888241, -0.17399999999890614, 0], + [-8.679999999818392, -0.04999999999890559, 0] + ], + [ + [-9.879999999888241, -0.07399999999890561, 0], + [-8.679999999818392, -0.04999999999890559, 0] + ], + [ + [-8.679999999818392, -0.04999999999890559, 0], + [-9.879999999888241, -0.17399999999890614, 0] + ], + [ + [-9.879999999888241, -0.17399999999890614, 0], + [-9.879999999888241, -0.07399999999890561, 0] + ] + ] + }, + { + "elementId": "0x20000000f82", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-8.679999999934807, -0.04999999999890559, -9.313225746154785e-10], + [-6.679999999818392, -0.009999999998905551, -1.862645149230957e-9] + ] + ] + }, + { + "elementId": "0x20000000f83", + "categoryId": "0x20000000253", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-10.379999999888241, -0.08399999999890628, 0], + [-9.880000000004657, -0.07399999999890561, 0] + ] + ] + }, + { + "elementId": "0x20000000f85", + "categoryId": "0x20000000153", + "modelId": "0x200000003c7", + "geometries": [ + [ + [-5.999999999883585, -0.11999999999890676, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.529999999911524, -0.009999999998905551, 0] + ], + [ + [-6.529999999911524, -0.009999999998905551, 0], + [-6.679999999818392, -0.009999999998905551, 0] + ], + [ + [-6.679999999818392, -0.009999999998905551, 0], + [-6.679999999818392, -0.32999999999890495, 0] + ], + [ + [-6.679999999818392, -0.32999999999890495, 0], + [-5.999999999883585, -0.32999999999890495, 0] + ], + [ + [-5.999999999883585, -0.32999999999890495, 0], + [-5.999999999883585, -0.11999999999890676, 0] + ], + [ + [-6.529999999911524, -0.009999999998905551, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.679999999818392, -0.009999999998905551, 0] + ], + [ + [-6.679999999818392, -0.009999999998905551, 0], + [-6.529999999911524, -0.009999999998905551, 0] + ], + [ + [-6.679999999818392, -0.32999999999890495, 0], + [-6.679999999818392, -0.009999999998905551, 0] + ], + [ + [-6.679999999818392, -0.009999999998905551, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-6.679999999818392, -0.32999999999890495, 0] + ], + [ + [-6.679999999818392, -0.32999999999890495, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-5.999999999883585, -0.32999999999890495, 0] + ], + [ + [-5.999999999883585, -0.32999999999890495, 0], + [-6.679999999818392, -0.32999999999890495, 0] + ], + [ + [-5.999999999883585, -0.11999999999890676, 0], + [-5.999999999883585, -0.32999999999890495, 0] + ], + [ + [-5.999999999883585, -0.32999999999890495, 0], + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10] + ], + [ + [-6.499999999883585, -0.15999999999890502, -9.313225746154785e-10], + [-5.999999999883585, -0.11999999999890676, 0] + ] + ] + }, + { + "elementId": "0x20000000f17", + "categoryId": "0x20000000183", + "modelId": "0x200000003c7", + "geometries": [ + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [8.680000000051223, -0.15097774903400651, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ], + [ + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9], + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9] + ], + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [9.880000000004657, -0.074977749034006, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ], + [ + [8.680000000051223, -0.05097774903400598, -1.862645149230957e-9], + [9.880000000004657, -0.17497774903400565, -1.862645149230957e-9] + ] + ] + } + ] } diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/clipper.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/clipper.json index ccb62f02c406..ac9e832e208a 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/clipper.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/clipper.json @@ -1 +1,22 @@ -[[{"normal":[-0.0038817298517902217,0.9999924660582987,0],"dist":3968844.4369143066},{"normal":[-0.7586867190525952,-0.6514556487844808,0],"dist":-2761900.976754894,"interior":true,"invisible":true},{"normal":[0.999992466058308,0.003881729849387539,0],"dist":246998.6554596908}],[{"normal":[-0.999992466058308,-0.003881729849387539,0],"dist":-247083.84954713186},{"normal":[0.0038817298517902217,-0.9999924660582987,0],"dist":-3968944.4369143066},{"normal":[0.7586867190525952,0.6514556487844808,0],"dist":2761900.9767548945,"interior":true,"invisible":true}]] \ No newline at end of file +[ + [ + { "normal": [-0.0038817298517902217, 0.9999924660582987, 0], "dist": 3968844.4369143066 }, + { + "normal": [-0.7586867190525952, -0.6514556487844808, 0], + "dist": -2761900.976754894, + "interior": true, + "invisible": true + }, + { "normal": [0.999992466058308, 0.003881729849387539, 0], "dist": 246998.6554596908 } + ], + [ + { "normal": [-0.999992466058308, -0.003881729849387539, 0], "dist": -247083.84954713186 }, + { "normal": [0.0038817298517902217, -0.9999924660582987, 0], "dist": -3968944.4369143066 }, + { + "normal": [0.7586867190525952, 0.6514556487844808, 0], + "dist": 2761900.9767548945, + "interior": true, + "invisible": true + } + ] +] diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/inside.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/inside.json index 687d969416ee..32ecdad8a055 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/inside.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/inside.json @@ -1 +1,496 @@ -{"indexedMesh":{"point":[[231590.61858138186,3969823.3175492873,47.141290796769226],[231590.61858138186,3969823.3175492873,47.17939087276923],[231592.68924458895,3969823.3255871036,47.104293753334794],[231592.68924458895,3969823.3255871036,47.142393829334786],[231590.60441306792,3969826.9675217886,47.068290796769745],[231590.60441306792,3969826.9675217886,47.10639087276975],[231592.67507627502,3969826.975559605,47.031293753334786],[231592.67507627502,3969826.975559605,47.0693938293348],[231597.68920691925,3969823.344995752,47.016168650076736],[231597.68920691925,3969823.344995752,47.05426872607673],[231597.67503860532,3969826.9949682537,46.943168650076736],[231597.67503860532,3969826.9949682537,46.98126872607673],[231602.68916924956,3969823.364404402,46.92925398729971],[231602.68916924956,3969823.364404402,46.96735406329972],[231602.67500093562,3969827.014376903,46.85625398729971],[231602.67500093562,3969827.014376903,46.89435406329971],[231607.6891315799,3969823.383813051,46.84354976500373],[231607.6891315799,3969823.383813051,46.881649841003735],[231607.67496326592,3969827.0337855523,46.770549765003736],[231607.67496326592,3969827.0337855523,46.80864984100373],[231612.68909391013,3969823.4032217003,46.759055983188794],[231612.68909391013,3969823.4032217003,46.79715605918881],[231612.6749255962,3969827.053194201,46.686055983188794],[231612.6749255962,3969827.053194201,46.72415605918879],[231617.68905624043,3969823.42263035,46.6757726418549],[231617.68905624043,3969823.42263035,46.7138727178549],[231617.6748879265,3969827.0726028513,46.60277264185491],[231617.6748879265,3969827.0726028513,46.640872717854904],[231622.68901857073,3969823.4420389994,46.593699741002055],[231622.68901857073,3969823.4420389994,46.63179981700204],[231622.6748502568,3969827.0920115,46.52069974100204],[231622.6748502568,3969827.0920115,46.55879981700205],[231627.68898090097,3969823.4614476482,46.51283728063022],[231627.68898090097,3969823.4614476482,46.55093735663023],[231627.67481258704,3969827.1114201494,46.43983728063023],[231627.67481258704,3969827.1114201494,46.47793735663023],[231632.6889432313,3969823.4808562975,46.43318526073946],[231632.6889432313,3969823.4808562975,46.47128533673945],[231633.21530417824,3969823.482899504,46.424927481722136],[231632.6865449353,3969824.0986937117,46.42082841935846],[231633.21530417824,3969823.482899504,46.46302755772213],[231632.6865449353,3969824.0986937117,46.45892849535845],[231630.09157510012,3969827.120801439,46.40133698741877],[231630.09157510012,3969827.120801439,46.43943706341877],[231632.67477491734,3969827.1308287983,46.360185260739456],[231632.67477491734,3969827.1308287983,46.398285336739455],[231637.6889055616,3969823.500264947,46.35474368132972],[231637.6889055616,3969823.500264947,46.392843757329715],[231637.67473724767,3969827.1502374476,46.281743681329715],[231637.67473724767,3969827.1502374476,46.31984375732973],[231642.68886789185,3969823.5196735957,46.27751254240103],[231642.68886789185,3969823.5196735957,46.31561261840104],[231642.6746995779,3969827.169646098,46.20451254240103],[231642.6746995779,3969827.169646098,46.242612618401026],[231647.68883022218,3969823.539082245,46.20149184395337],[231647.68883022218,3969823.539082245,46.23959191995337],[231647.6746619082,3969827.1890547466,46.128491843953384],[231647.6746619082,3969827.1890547466,46.16659191995337],[231652.68879255248,3969823.5584908947,46.12668158598677],[231652.68879255248,3969823.5584908947,46.164781661986765],[231652.6746242385,3969827.208463396,46.053681585986766],[231652.6746242385,3969827.208463396,46.09178166198678],[231657.68875488272,3969823.577899543,46.053081768501194],[231657.68875488272,3969823.577899543,46.09118184450119],[231657.67458656884,3969827.2278720452,45.9800817685012],[231657.67458656884,3969827.2278720452,46.01818184450119],[231662.68871721302,3969823.5973081933,45.980692391496675],[231662.68871721302,3969823.5973081933,46.018792467496674],[231662.6745488991,3969827.247280694,45.90769239149668],[231662.6745488991,3969827.247280694,45.945792467496666],[231667.68867954332,3969823.616716842,45.90951345497319],[231667.68867954332,3969823.616716842,45.94761353097318],[231667.6745112294,3969827.2666893434,45.83651345497318],[231667.6745112294,3969827.2666893434,45.87461353097319],[231672.6886418736,3969823.6361254915,45.83954495893073],[231672.6886418736,3969823.6361254915,45.877645034930744],[231675.81202697562,3969823.6482497198,45.796593058056665],[231672.6744735597,3969827.286097992,45.76654495893073],[231675.81202697562,3969823.6482497198,45.834693134056664],[231672.6744735597,3969827.286097992,45.80464503493073],[231675.79785866168,3969827.298222221,45.72359305805681],[231675.79785866168,3969827.298222221,45.76169313405681]],"pointIndex":[5,6,8,7,0,6,2,4,8,0,2,1,3,4,0,1,5,7,3,0,7,8,12,11,0,8,4,10,12,0,4,3,9,10,0,3,7,11,9,0,11,12,16,15,0,12,10,14,16,0,10,9,13,14,0,9,11,15,13,0,15,16,20,19,0,16,14,18,20,0,14,13,17,18,0,13,15,19,17,0,19,20,24,23,0,20,18,22,24,0,18,17,21,22,0,17,19,23,21,0,23,24,28,27,0,24,22,26,28,0,22,21,25,26,0,21,23,27,25,0,27,28,32,31,0,28,26,30,32,0,26,25,29,30,0,25,27,31,29,0,31,32,36,35,0,32,30,34,36,0,30,29,33,34,0,29,31,35,33,0,43,35,36,44,0,43,44,46,45,0,44,36,34,38,42,0,44,42,46,0,34,33,37,38,0,33,35,43,40,37,0,43,45,40,0,45,46,50,49,0,42,38,41,0,46,42,41,48,50,0,41,38,37,39,0,41,39,47,48,0,39,37,40,0,39,40,45,49,47,0,49,50,54,53,0,50,48,52,54,0,48,47,51,52,0,47,49,53,51,0,53,54,58,57,0,54,52,56,58,0,52,51,55,56,0,51,53,57,55,0,57,58,62,61,0,58,56,60,62,0,56,55,59,60,0,55,57,61,59,0,61,62,66,65,0,62,60,64,66,0,60,59,63,64,0,59,61,65,63,0,65,66,70,69,0,66,64,68,70,0,64,63,67,68,0,63,65,69,67,0,69,70,74,73,0,70,68,72,74,0,68,67,71,72,0,67,69,73,71,0,73,74,80,78,0,74,72,76,80,0,72,71,75,76,0,71,73,78,75,0,81,78,80,82,0,82,80,76,79,0,79,76,75,77,0,77,75,78,81,0,5,6,1,0,6,2,1,0,82,81,77,0,77,79,82,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [231590.61858138186, 3969823.3175492873, 47.141290796769226], + [231590.61858138186, 3969823.3175492873, 47.17939087276923], + [231592.68924458895, 3969823.3255871036, 47.104293753334794], + [231592.68924458895, 3969823.3255871036, 47.142393829334786], + [231590.60441306792, 3969826.9675217886, 47.068290796769745], + [231590.60441306792, 3969826.9675217886, 47.10639087276975], + [231592.67507627502, 3969826.975559605, 47.031293753334786], + [231592.67507627502, 3969826.975559605, 47.0693938293348], + [231597.68920691925, 3969823.344995752, 47.016168650076736], + [231597.68920691925, 3969823.344995752, 47.05426872607673], + [231597.67503860532, 3969826.9949682537, 46.943168650076736], + [231597.67503860532, 3969826.9949682537, 46.98126872607673], + [231602.68916924956, 3969823.364404402, 46.92925398729971], + [231602.68916924956, 3969823.364404402, 46.96735406329972], + [231602.67500093562, 3969827.014376903, 46.85625398729971], + [231602.67500093562, 3969827.014376903, 46.89435406329971], + [231607.6891315799, 3969823.383813051, 46.84354976500373], + [231607.6891315799, 3969823.383813051, 46.881649841003735], + [231607.67496326592, 3969827.0337855523, 46.770549765003736], + [231607.67496326592, 3969827.0337855523, 46.80864984100373], + [231612.68909391013, 3969823.4032217003, 46.759055983188794], + [231612.68909391013, 3969823.4032217003, 46.79715605918881], + [231612.6749255962, 3969827.053194201, 46.686055983188794], + [231612.6749255962, 3969827.053194201, 46.72415605918879], + [231617.68905624043, 3969823.42263035, 46.6757726418549], + [231617.68905624043, 3969823.42263035, 46.7138727178549], + [231617.6748879265, 3969827.0726028513, 46.60277264185491], + [231617.6748879265, 3969827.0726028513, 46.640872717854904], + [231622.68901857073, 3969823.4420389994, 46.593699741002055], + [231622.68901857073, 3969823.4420389994, 46.63179981700204], + [231622.6748502568, 3969827.0920115, 46.52069974100204], + [231622.6748502568, 3969827.0920115, 46.55879981700205], + [231627.68898090097, 3969823.4614476482, 46.51283728063022], + [231627.68898090097, 3969823.4614476482, 46.55093735663023], + [231627.67481258704, 3969827.1114201494, 46.43983728063023], + [231627.67481258704, 3969827.1114201494, 46.47793735663023], + [231632.6889432313, 3969823.4808562975, 46.43318526073946], + [231632.6889432313, 3969823.4808562975, 46.47128533673945], + [231633.21530417824, 3969823.482899504, 46.424927481722136], + [231632.6865449353, 3969824.0986937117, 46.42082841935846], + [231633.21530417824, 3969823.482899504, 46.46302755772213], + [231632.6865449353, 3969824.0986937117, 46.45892849535845], + [231630.09157510012, 3969827.120801439, 46.40133698741877], + [231630.09157510012, 3969827.120801439, 46.43943706341877], + [231632.67477491734, 3969827.1308287983, 46.360185260739456], + [231632.67477491734, 3969827.1308287983, 46.398285336739455], + [231637.6889055616, 3969823.500264947, 46.35474368132972], + [231637.6889055616, 3969823.500264947, 46.392843757329715], + [231637.67473724767, 3969827.1502374476, 46.281743681329715], + [231637.67473724767, 3969827.1502374476, 46.31984375732973], + [231642.68886789185, 3969823.5196735957, 46.27751254240103], + [231642.68886789185, 3969823.5196735957, 46.31561261840104], + [231642.6746995779, 3969827.169646098, 46.20451254240103], + [231642.6746995779, 3969827.169646098, 46.242612618401026], + [231647.68883022218, 3969823.539082245, 46.20149184395337], + [231647.68883022218, 3969823.539082245, 46.23959191995337], + [231647.6746619082, 3969827.1890547466, 46.128491843953384], + [231647.6746619082, 3969827.1890547466, 46.16659191995337], + [231652.68879255248, 3969823.5584908947, 46.12668158598677], + [231652.68879255248, 3969823.5584908947, 46.164781661986765], + [231652.6746242385, 3969827.208463396, 46.053681585986766], + [231652.6746242385, 3969827.208463396, 46.09178166198678], + [231657.68875488272, 3969823.577899543, 46.053081768501194], + [231657.68875488272, 3969823.577899543, 46.09118184450119], + [231657.67458656884, 3969827.2278720452, 45.9800817685012], + [231657.67458656884, 3969827.2278720452, 46.01818184450119], + [231662.68871721302, 3969823.5973081933, 45.980692391496675], + [231662.68871721302, 3969823.5973081933, 46.018792467496674], + [231662.6745488991, 3969827.247280694, 45.90769239149668], + [231662.6745488991, 3969827.247280694, 45.945792467496666], + [231667.68867954332, 3969823.616716842, 45.90951345497319], + [231667.68867954332, 3969823.616716842, 45.94761353097318], + [231667.6745112294, 3969827.2666893434, 45.83651345497318], + [231667.6745112294, 3969827.2666893434, 45.87461353097319], + [231672.6886418736, 3969823.6361254915, 45.83954495893073], + [231672.6886418736, 3969823.6361254915, 45.877645034930744], + [231675.81202697562, 3969823.6482497198, 45.796593058056665], + [231672.6744735597, 3969827.286097992, 45.76654495893073], + [231675.81202697562, 3969823.6482497198, 45.834693134056664], + [231672.6744735597, 3969827.286097992, 45.80464503493073], + [231675.79785866168, 3969827.298222221, 45.72359305805681], + [231675.79785866168, 3969827.298222221, 45.76169313405681] + ], + "pointIndex": [ + 5, + 6, + 8, + 7, + 0, + 6, + 2, + 4, + 8, + 0, + 2, + 1, + 3, + 4, + 0, + 1, + 5, + 7, + 3, + 0, + 7, + 8, + 12, + 11, + 0, + 8, + 4, + 10, + 12, + 0, + 4, + 3, + 9, + 10, + 0, + 3, + 7, + 11, + 9, + 0, + 11, + 12, + 16, + 15, + 0, + 12, + 10, + 14, + 16, + 0, + 10, + 9, + 13, + 14, + 0, + 9, + 11, + 15, + 13, + 0, + 15, + 16, + 20, + 19, + 0, + 16, + 14, + 18, + 20, + 0, + 14, + 13, + 17, + 18, + 0, + 13, + 15, + 19, + 17, + 0, + 19, + 20, + 24, + 23, + 0, + 20, + 18, + 22, + 24, + 0, + 18, + 17, + 21, + 22, + 0, + 17, + 19, + 23, + 21, + 0, + 23, + 24, + 28, + 27, + 0, + 24, + 22, + 26, + 28, + 0, + 22, + 21, + 25, + 26, + 0, + 21, + 23, + 27, + 25, + 0, + 27, + 28, + 32, + 31, + 0, + 28, + 26, + 30, + 32, + 0, + 26, + 25, + 29, + 30, + 0, + 25, + 27, + 31, + 29, + 0, + 31, + 32, + 36, + 35, + 0, + 32, + 30, + 34, + 36, + 0, + 30, + 29, + 33, + 34, + 0, + 29, + 31, + 35, + 33, + 0, + 43, + 35, + 36, + 44, + 0, + 43, + 44, + 46, + 45, + 0, + 44, + 36, + 34, + 38, + 42, + 0, + 44, + 42, + 46, + 0, + 34, + 33, + 37, + 38, + 0, + 33, + 35, + 43, + 40, + 37, + 0, + 43, + 45, + 40, + 0, + 45, + 46, + 50, + 49, + 0, + 42, + 38, + 41, + 0, + 46, + 42, + 41, + 48, + 50, + 0, + 41, + 38, + 37, + 39, + 0, + 41, + 39, + 47, + 48, + 0, + 39, + 37, + 40, + 0, + 39, + 40, + 45, + 49, + 47, + 0, + 49, + 50, + 54, + 53, + 0, + 50, + 48, + 52, + 54, + 0, + 48, + 47, + 51, + 52, + 0, + 47, + 49, + 53, + 51, + 0, + 53, + 54, + 58, + 57, + 0, + 54, + 52, + 56, + 58, + 0, + 52, + 51, + 55, + 56, + 0, + 51, + 53, + 57, + 55, + 0, + 57, + 58, + 62, + 61, + 0, + 58, + 56, + 60, + 62, + 0, + 56, + 55, + 59, + 60, + 0, + 55, + 57, + 61, + 59, + 0, + 61, + 62, + 66, + 65, + 0, + 62, + 60, + 64, + 66, + 0, + 60, + 59, + 63, + 64, + 0, + 59, + 61, + 65, + 63, + 0, + 65, + 66, + 70, + 69, + 0, + 66, + 64, + 68, + 70, + 0, + 64, + 63, + 67, + 68, + 0, + 63, + 65, + 69, + 67, + 0, + 69, + 70, + 74, + 73, + 0, + 70, + 68, + 72, + 74, + 0, + 68, + 67, + 71, + 72, + 0, + 67, + 69, + 73, + 71, + 0, + 73, + 74, + 80, + 78, + 0, + 74, + 72, + 76, + 80, + 0, + 72, + 71, + 75, + 76, + 0, + 71, + 73, + 78, + 75, + 0, + 81, + 78, + 80, + 82, + 0, + 82, + 80, + 76, + 79, + 0, + 79, + 76, + 75, + 77, + 0, + 77, + 75, + 78, + 81, + 0, + 5, + 6, + 1, + 0, + 6, + 2, + 1, + 0, + 82, + 81, + 77, + 0, + 77, + 79, + 82, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/outside.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/outside.json index 3867a79d7ced..b94cbe75c55e 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/outside.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/outside.json @@ -1 +1,5454 @@ -{"indexedMesh":{"point":[[231318.71862147184,3969833.794423595,52.34198669098813],[231318.71862147184,3969833.794423595,52.38008676698812],[231319.0552437973,3969833.699915871,52.33530277647533],[231319.0552437973,3969833.699915871,52.37340285247532],[231323.5427737373,3969832.480278922,52.24640317426871],[231323.5427737373,3969832.480278922,52.28450325026871],[231319.70727180273,3969837.3079788485,52.04998669098812],[231319.70727180273,3969837.3079788485,52.08808676698813],[231320.03979855657,3969837.214620969,52.043302776475315],[231320.03979855657,3969837.214620969,52.081402852475314],[231325.74466138077,3969831.909049104,52.20291682334428],[231325.74466138077,3969831.909049104,52.241016899344274],[231328.38815739428,3969831.24671558,52.1508196575493],[231328.38815739428,3969831.24671558,52.1889197335493],[231324.4727302156,3969836.009822936,51.95440317426871],[231324.4727302156,3969836.009822936,51.99250325026871],[231326.6478282261,3969835.44554308,51.91091682334427],[231326.6478282261,3969835.44554308,51.94901689934428],[231332.473633145,3969830.2730630464,52.07053087021323],[231332.473633145,3969830.2730630464,52.10863094621324],[231329.2591617048,3969834.791267948,51.85881965754929],[231329.2591617048,3969834.791267948,51.89691973354929],[231333.25342653418,3969830.0940762185,52.055236140829884],[231333.25342653418,3969830.0940762185,52.09333621682988],[231333.29493083383,3969833.8294615205,51.77853087021324],[231333.29493083383,3969833.8294615205,51.81663094621323],[231334.0652367368,3969833.652652365,51.76323614082989],[231334.0652367368,3969833.652652365,51.801336216829874],[231338.13722972453,3969829.022681006,51.959652624110475],[231338.13722972453,3969829.022681006,51.99775270011046],[231339.2385736313,3969828.7928294153,51.938144917082184],[231339.2385736313,3969828.7928294153,51.97624499308219],[231338.88962032163,3969832.5942924623,51.66765262411046],[231338.88962032163,3969832.5942924623,51.705752700110466],[231343.03821038472,3969828.0328275478,51.864069107391046],[231343.03821038472,3969828.0328275478,51.90216918339105],[231343.0886612497,3969828.0230792924,51.86308681418512],[231343.0886612497,3969828.0230792924,51.90118689018512],[231339.9775645442,3969832.367237399,51.64614491708219],[231339.9775645442,3969832.367237399,51.68424499308219],[231346.03587821542,3969827.469136938,51.80575896395115],[231346.03587821542,3969827.469136938,51.84385903995114],[231343.73097238384,3969831.6164822197,51.57206910739105],[231343.73097238384,3969831.6164822197,51.610169183391044],[231343.78080942994,3969831.606852569,51.57108681418512],[231343.78080942994,3969831.606852569,51.609186890185114],[231347.95500716282,3969827.1247907947,51.76848559067164],[231347.95500716282,3969827.1247907947,51.80658566667163],[231346.69216858927,3969831.059649846,51.52836998096813],[231346.69216858927,3969831.059649846,51.566470056968136],[231348.5879481345,3969830.7194932476,51.5005963864009],[231348.5879481345,3969830.7194932476,51.538696462400914],[231352.8619250283,3969826.302690928,51.6733730108201],[231352.88625431352,3969826.298822975,51.67290207395222],[231352.8619250283,3969826.302690928,51.7114730868201],[231352.88625431352,3969826.298822975,51.71100214995222],[231353.43516516592,3969829.9073955966,51.4297249304896],[231353.45919844485,3969829.903574703,51.42937402021529],[231353.43516516592,3969829.9073955966,51.46782500648959],[231353.45919844485,3969829.903574703,51.46747409621529],[231357.8305820777,3969825.5551535166,51.57731855723279],[231357.8305820777,3969825.5551535166,51.61541863323281],[231359.7130768859,3969825.294112915,51.54098705768906],[231359.7130768859,3969825.294112915,51.579087133689065],[231358.3433702212,3969829.1689532236,51.35815165402976],[231358.3433702212,3969829.1689532236,51.39625173002977],[231362.78661706272,3969824.8939889916,51.481735040513385],[231362.78661706272,3969824.8939889916,51.5198351165134],[231360.20296134258,3969828.9110886157,51.3310798800107],[231360.20296134258,3969828.9110886157,51.36917995601071],[231366.58568322717,3969824.443940307,51.40860110455801],[231366.58568322717,3969824.443940307,51.44670118055802],[231363.23910678053,3969828.515832867,51.28692928784427],[231363.23910678053,3969828.515832867,51.32502936384429],[231367.75298262408,3969824.3155130525,51.38615152379398],[231367.75298262408,3969824.3155130525,51.42425159979397],[231366.99195097337,3969828.071259775,51.232434829531854],[231366.99195097337,3969828.071259775,51.27053490553187],[231368.14504822757,3969827.9443950504,51.21570692165858],[231368.14504822757,3969827.9443950504,51.25380699765858],[231372.7282992477,3969823.8198863817,51.29056800707455],[231372.7282992477,3969823.8198863817,51.328668083074554],[231373.47608205935,3969823.752626111,51.276215151426975],[231373.47608205935,3969823.752626111,51.31431522742697],[231373.05983183227,3969827.4547985056,51.14448455547303],[231373.05983183227,3969827.4547985056,51.18258463147302],[231373.79851661975,3969827.3883565674,51.1337897790531],[231373.79851661975,3969827.3883565674,51.171889855053095],[231377.7111849332,3969823.4072466516,51.19498449035515],[231377.7111849332,3969823.4072466516,51.23308456635514],[231380.38060190907,3969823.220538685,51.143829198295926],[231380.38060190907,3969823.220538685,51.18192927429592],[231377.9820924086,3969827.0471792254,51.07326218928752],[231377.9820924086,3969827.0471792254,51.111362265287525],[231382.7002555777,3969823.077708482,51.09940097363573],[231382.7002555777,3969823.077708482,51.13750104963573],[231380.61903147798,3969826.862742872,51.03514472857434],[231380.61903147798,3969826.862742872,51.073244804574344],[231382.91046269366,3969826.7216504365,51.00203982310191],[231382.91046269366,3969826.7216504365,51.040139899101916],[231387.29556377884,3969822.847961545,51.01144324516488],[231387.29556377884,3969822.847961545,51.04954332116488],[231387.6941253603,3969822.8313634074,51.00381745691726],[231387.6941253603,3969822.8313634074,51.041917532917275],[231387.44986131164,3969826.494698755,50.936499678095664],[231387.44986131164,3969826.494698755,50.97459975409567],[231387.84357372724,3969826.47830256,50.93081745691726],[231387.84357372724,3969826.47830256,50.96891753291726],[231392.6914071272,3969822.6682798564,50.908233940196894],[231392.6914071272,3969822.6682798564,50.94633401619691],[231394.2172831071,3969822.635093217,50.87905729203383],[231394.2172831071,3969822.635093217,50.917157368033834],[231392.78005523258,3969826.317203193,50.8352339401969],[231392.78005523258,3969826.317203193,50.8733340161969],[231394.28736638805,3969826.2844203236,50.80605729203384],[231394.28736638805,3969826.2844203236,50.84415736803383],[231397.69071277653,3969822.58850313,50.812650423477486],[231397.69071277653,3969822.58850313,50.85075049947748],[231397.7185359965,3969826.238397083,50.739650423477485],[231397.7185359965,3969826.238397083,50.777750499477484],[231401.1420717323,3969822.582047123,50.746671338902765],[231401.1420717323,3969822.582047123,50.78477141490276],[231402.6906760379,3969822.588058432,50.71706690675807],[231402.6906760379,3969822.588058432,50.75516698275806],[231401.12790341835,3969826.2320196237,50.67367133890276],[231401.12790341835,3969826.2320196237,50.71177141490277],[231402.67650772393,3969826.238030933,50.644066906758056],[231402.67650772393,3969826.238030933,50.68216698275806],[231407.6906383682,3969822.607467081,50.621483390038655],[231407.6906383682,3969822.607467081,50.659583466038654],[231407.67647005426,3969826.2574395817,50.54848339003865],[231407.67647005426,3969826.2574395817,50.586583466038654],[231412.69060069844,3969822.62687573,50.52589987331923],[231412.69060069844,3969822.62687573,50.56399994931923],[231412.6764323845,3969826.2768482324,50.45289987331924],[231412.6764323845,3969826.2768482324,50.49099994931923],[231417.69056302874,3969822.64628438,50.43031635659981],[231417.69056302874,3969822.64628438,50.46841643259982],[231417.67639471486,3969826.296256881,50.35731635659981],[231417.67639471486,3969826.296256881,50.395416432599816],[231422.69052535907,3969822.6656930293,50.3347328398804],[231422.69052535907,3969822.6656930293,50.37283291588041],[231422.6763570451,3969826.3156655305,50.26173283988041],[231422.6763570451,3969826.3156655305,50.29983291588041],[231427.69048768937,3969822.6851016777,50.239149323160994],[231427.69048768937,3969822.6851016777,50.277249399160986],[231427.67631937537,3969826.3350741793,50.16614932316099],[231427.67631937537,3969826.3350741793,50.204249399160986],[231432.6904500196,3969822.7045103274,50.14356580644158],[231432.6904500196,3969822.7045103274,50.181665882441564],[231432.67628170567,3969826.3544828286,50.070565806441564],[231432.67628170567,3969826.3544828286,50.10866588244157],[231437.6904123499,3969822.7239189767,50.04798228972217],[231437.6904123499,3969822.7239189767,50.086082365722156],[231437.67624403597,3969826.373891478,49.974982289722156],[231437.67624403597,3969826.373891478,50.01308236572216],[231442.69037468018,3969822.743327626,49.95239877300274],[231442.69037468018,3969822.743327626,49.99049884900275],[231442.67620636628,3969826.393300127,49.87939877300275],[231442.67620636628,3969826.393300127,49.91749884900274],[231447.69033701048,3969822.762736275,49.856815256283326],[231447.69033701048,3969822.762736275,49.894915332283325],[231447.67616869655,3969826.412708776,49.78381525628332],[231447.67616869655,3969826.412708776,49.82191533228332],[231452.69029934084,3969822.7821449237,49.76123173956391],[231452.69029934084,3969822.7821449237,49.79933181556391],[231452.67613102685,3969826.432117426,49.688231739563925],[231452.67613102685,3969826.432117426,49.72633181556391],[231457.6902616711,3969822.801553574,49.66564822284449],[231457.6902616711,3969822.801553574,49.7037482988445],[231457.67609335715,3969826.451526075,49.592648222844495],[231457.67609335715,3969826.451526075,49.63074829884449],[231462.69022400136,3969822.820962223,49.57006470612508],[231462.69022400136,3969822.820962223,49.60816478212507],[231462.67605568745,3969826.470934724,49.49706470612508],[231462.67605568745,3969826.470934724,49.53516478212508],[231467.69018633166,3969822.840370872,49.47448118940567],[231467.69018633166,3969822.840370872,49.51258126540567],[231467.67601801772,3969826.4903433733,49.401481189405665],[231467.67601801772,3969826.4903433733,49.439581265405664],[231472.69014866196,3969822.8597795214,49.37889767268625],[231472.69014866196,3969822.8597795214,49.41699774868624],[231472.67598034802,3969826.5097520235,49.30589767268624],[231472.67598034802,3969826.5097520235,49.343997748686256],[231477.69011099226,3969822.8791881707,49.283314155966835],[231477.69011099226,3969822.8791881707,49.321414231966834],[231477.67594267832,3969826.5291606723,49.210314155966834],[231477.67594267832,3969826.5291606723,49.24841423196683],[231482.69007332253,3969822.8985968204,49.18773063924743],[231482.69007332253,3969822.8985968204,49.22583071524742],[231482.67590500863,3969826.5485693216,49.114730639247426],[231482.67590500863,3969826.5485693216,49.15283071524742],[231487.69003565283,3969822.918005469,49.092147122528],[231487.69003565283,3969822.918005469,49.13024719852801],[231487.67586733887,3969826.5679779705,49.019147122528004],[231487.67586733887,3969826.5679779705,49.057247198528],[231492.68999798314,3969822.9374141186,48.99656360580859],[231492.68999798314,3969822.9374141186,49.03466368180858],[231492.6758296692,3969826.587386619,48.92356360580859],[231492.6758296692,3969826.587386619,48.96166368180859],[231497.68996031344,3969822.956822768,48.90098008908918],[231497.68996031344,3969822.956822768,48.93908016508918],[231497.6757919995,3969826.606795269,48.82798008908918],[231497.6757919995,3969826.606795269,48.86608016508917],[231502.68992264368,3969822.9762314167,48.80539657236976],[231502.68992264368,3969822.9762314167,48.84349664836976],[231502.6757543298,3969826.626203918,48.73239657236975],[231502.6757543298,3969826.626203918,48.77049664836976],[231507.689884974,3969822.995640066,48.709813055650336],[231507.689884974,3969822.995640066,48.74791313165035],[231507.67571666007,3969826.645612567,48.63681305565034],[231507.67571666007,3969826.645612567,48.674913131650335],[231512.6898473043,3969823.015048715,48.61422953893093],[231512.6898473043,3969823.015048715,48.65232961493093],[231512.67567899037,3969826.665021217,48.541229538930935],[231512.67567899037,3969826.665021217,48.579329614930934],[231517.68980963455,3969823.0344573655,48.518646022211506],[231517.68980963455,3969823.0344573655,48.55674609821151],[231517.67564132062,3969826.6844298663,48.44564602221151],[231517.67564132062,3969826.6844298663,48.48374609821151],[231522.68977196486,3969823.0538660144,48.4230625054921],[231522.68977196486,3969823.0538660144,48.46116258149209],[231522.67560365092,3969826.7038385156,48.35006250549209],[231522.67560365092,3969826.7038385156,48.388162581492104],[231527.68973429519,3969823.0732746636,48.32747898877268],[231527.68973429519,3969823.0732746636,48.365579064772696],[231527.67556598125,3969826.7232471644,48.25447898877268],[231527.67556598125,3969826.7232471644,48.29257906477268],[231532.68969662543,3969823.0926833125,48.231895472053274],[231532.68969662543,3969823.0926833125,48.26999554805326],[231532.6755283115,3969826.7426558146,48.15889547205326],[231532.6755283115,3969826.7426558146,48.196995548053266],[231537.6896589558,3969823.1120919613,48.136311955333845],[231537.6896589558,3969823.1120919613,48.17441203133386],[231537.6754906418,3969826.7620644625,48.06331195533385],[231537.6754906418,3969826.7620644625,48.101412031333844],[231542.68962128603,3969823.131500611,48.040728438614444],[231542.68962128603,3969823.131500611,48.078828514614436],[231542.6754529721,3969826.781473112,47.96772843861444],[231542.6754529721,3969826.781473112,48.00582851461445],[231547.6895836163,3969823.15090926,47.945144921895015],[231547.6895836163,3969823.15090926,47.983244997895014],[231547.6754153024,3969826.8008817616,47.87214492189503],[231547.6754153024,3969826.8008817616,47.91024499789501],[231552.6895459466,3969823.170317909,47.849561405175606],[231552.6895459466,3969823.170317909,47.887661481175606],[231552.67537763267,3969826.82029041,47.7765614051756],[231552.67537763267,3969826.82029041,47.81466148117561],[231557.6895082769,3969823.189726559,47.753977888456184],[231557.6895082769,3969823.189726559,47.79207796445618],[231557.67533996297,3969826.83969906,47.68097788845619],[231557.67533996297,3969826.83969906,47.71907796445618],[231562.6894706072,3969823.2091352083,47.65839437173678],[231562.6894706072,3969823.2091352083,47.69649444773677],[231564.38078293134,3969823.2157004746,47.626061812182925],[231564.38078293134,3969823.2157004746,47.66416188818293],[231562.67530229327,3969826.859107709,47.58539437173677],[231562.67530229327,3969826.859107709,47.623494447736775],[231564.3666146174,3969826.8656729762,47.553061812182925],[231564.3666146174,3969826.8656729762,47.59116188818293],[231567.68943293748,3969823.228543857,47.56307587684072],[231567.68943293748,3969823.228543857,47.60117595284071],[231567.67526462357,3969826.8785163583,47.490075876840706],[231567.67526462357,3969826.8785163583,47.52817595284071],[231572.68939526778,3969823.2479525064,47.468898571177455],[231572.68939526778,3969823.2479525064,47.50699864717744],[231572.6752269539,3969826.8979250076,47.39589857117744],[231572.6752269539,3969826.8979250076,47.43399864717745],[231577.68935759808,3969823.2673611557,47.37593170599522],[231577.68935759808,3969823.2673611557,47.41403178199523],[231577.67518928414,3969826.9173336574,47.30293170599522],[231577.67518928414,3969826.9173336574,47.34103178199522],[231582.68931992838,3969823.2867698045,47.28417528129403],[231582.68931992838,3969823.2867698045,47.32227535729403],[231582.67515161444,3969826.9367423067,47.21117528129404],[231582.67515161444,3969826.9367423067,47.24927535729403],[231587.68928225865,3969823.306178454,47.19362929707389],[231587.68928225865,3969823.306178454,47.2317293730739],[231590.61858138186,3969823.3175492873,47.141290796769226],[231590.61858138186,3969823.3175492873,47.17939087276923],[231587.67511394474,3969826.9561509555,47.12062929707389],[231587.67511394474,3969826.9561509555,47.15872937307389],[231590.60441306792,3969826.9675217886,47.068290796769745],[231590.60441306792,3969826.9675217886,47.10639087276975],[231633.21530417824,3969823.482899504,46.424927481722136],[231632.6865449353,3969824.0986937117,46.42082841935846],[231633.21530417824,3969823.482899504,46.46302755772213],[231632.6865449353,3969824.0986937117,46.45892849535845],[231630.09157510012,3969827.120801439,46.40133698741877],[231630.09157510012,3969827.120801439,46.43943706341877],[231675.81202697562,3969823.6482497198,45.796593058056665],[231675.81202697562,3969823.6482497198,45.834693134056664],[231677.6886042039,3969823.6555341403,45.770786903369334],[231677.6886042039,3969823.6555341403,45.808886979369326],[231675.79785866168,3969827.298222221,45.72359305805681],[231675.79785866168,3969827.298222221,45.76169313405681],[231677.67443588996,3969827.3055066415,45.69778690336933],[231677.67443588996,3969827.3055066415,45.73588697936933],[231682.6885665342,3969823.6749427896,45.70323928828896],[231682.6885665342,3969823.6749427896,45.74133936428896],[231682.67439822032,3969827.324915291,45.630239288288976],[231682.67439822032,3969827.324915291,45.66833936428897],[231687.6885288645,3969823.69435144,45.63690211368964],[231687.6885288645,3969823.69435144,45.675002189689636],[231687.67436055056,3969827.3443239406,45.56390211368965],[231687.67436055056,3969827.3443239406,45.602002189689635],[231692.68849119483,3969823.7137600887,45.571775379571356],[231692.68849119483,3969823.7137600887,45.60987545557136],[231692.67432288086,3969827.36373259,45.498775379571356],[231692.67432288086,3969827.36373259,45.536875455571355],[231697.68845352507,3969823.733168738,45.507859085934115],[231697.68845352507,3969823.733168738,45.54595916193413],[231697.67428521113,3969827.3831412387,45.43485908593412],[231697.67428521113,3969827.3831412387,45.472959161934114],[231702.68841585537,3969823.752577387,45.44515323277791],[231702.68841585537,3969823.752577387,45.48325330877792],[231702.67424754144,3969827.402549889,45.37215323277792],[231702.67424754144,3969827.402549889,45.41025330877792],[231707.68837818567,3969823.771986036,45.38365782010277],[231707.68837818567,3969823.771986036,45.421757896102754],[231707.67420987174,3969827.4219585373,45.310657820102755],[231707.67420987174,3969827.4219585373,45.34875789610276],[231712.688340516,3969823.7913946854,45.323372847908644],[231712.688340516,3969823.7913946854,45.361472923908636],[231712.67417220204,3969827.441367187,45.250372847908636],[231712.67417220204,3969827.441367187,45.28847292390865],[231717.68830284625,3969823.810803334,45.26429831619556],[231717.68830284625,3969823.810803334,45.302398392195556],[231717.67413453228,3969827.4607758354,45.19129831619557],[231717.67413453228,3969827.4607758354,45.22939839219556],[231722.68826517655,3969823.8302119835,45.20643422496353],[231722.68826517655,3969823.8302119835,45.24453430096352],[231722.6740968626,3969827.480184485,45.13343422496352],[231722.6740968626,3969827.480184485,45.17153430096353],[231727.68822750685,3969823.8496206333,45.14978057421254],[231727.68822750685,3969823.8496206333,45.18788065021253],[231727.6740591929,3969827.4995931336,45.07678057421253],[231727.6740591929,3969827.4995931336,45.114880650212534],[231732.68818983712,3969823.8690292826,45.09433736394257],[231732.68818983712,3969823.8690292826,45.13243743994258],[231732.67402152315,3969827.5190017833,45.02133736394258],[231732.67402152315,3969827.5190017833,45.05943743994257],[231737.68815216742,3969823.8884379314,45.040104594153654],[231737.68815216742,3969823.8884379314,45.07820467015365],[231737.67398385346,3969827.5384104326,44.96710459415366],[231737.67398385346,3969827.5384104326,45.00520467015366],[231742.68811449772,3969823.9078465807,44.98708226484579],[231742.68811449772,3969823.9078465807,45.02518234084579],[231742.6739461838,3969827.557819082,44.91408226484579],[231742.6739461838,3969827.557819082,44.95218234084578],[231747.68807682797,3969823.927255231,44.935270376018956],[231747.68807682797,3969823.927255231,44.973370452018955],[231747.67390851403,3969827.5772277317,44.86227037601895],[231747.67390851403,3969827.5772277317,44.900370452018954],[231752.68803915827,3969823.94666388,44.88466892767317],[231752.68803915827,3969823.94666388,44.92276900367316],[231752.67387084433,3969827.596636381,44.81166892767317],[231752.67387084433,3969827.596636381,44.84976900367317],[231757.6880014886,3969823.966072529,44.83527791980842],[231757.6880014886,3969823.966072529,44.87337799580842],[231757.67383317463,3969827.61604503,44.76227791980842],[231757.67383317463,3969827.61604503,44.80037799580841],[231762.68796381884,3969823.985481178,44.7870973524247],[231762.68796381884,3969823.985481178,44.82519742842471],[231762.6737955049,3969827.635453679,44.71409735242471],[231762.6737955049,3969827.635453679,44.75219742842471],[231767.68792614914,3969824.004889827,44.74012722552204],[231767.68792614914,3969824.004889827,44.77822730152203],[231767.67375783526,3969827.6548623284,44.667127225522044],[231767.67375783526,3969827.6548623284,44.70522730152203],[231772.68788847944,3969824.0242984765,44.69436753910041],[231772.68788847944,3969824.0242984765,44.732467615100404],[231772.6737201655,3969827.6742709773,44.62136753910041],[231772.6737201655,3969827.6742709773,44.65946761510041],[231777.68785080977,3969824.0437071254,44.64981829315983],[231777.68785080977,3969824.0437071254,44.687918369159824],[231777.6736824958,3969827.6936796266,44.57681829315982],[231777.6736824958,3969827.6936796266,44.614918369159824],[231782.68781314002,3969824.0631157747,44.60647948770028],[231782.68781314002,3969824.0631157747,44.644579563700276],[231782.67364482608,3969827.7130882763,44.533479487700276],[231782.67364482608,3969827.7130882763,44.57157956370029],[231787.68777547032,3969824.082524424,44.56435112272177],[231787.68777547032,3969824.082524424,44.60245119872178],[231787.67360715638,3969827.7324969256,44.49135112272177],[231787.67360715638,3969827.7324969256,44.529451198721766],[231792.68773780062,3969824.1019330737,44.52343319822431],[231792.68773780062,3969824.1019330737,44.56153327422431],[231792.67356948668,3969827.751905575,44.45043319822431],[231792.67356948668,3969827.751905575,44.4885332742243],[231797.68770013095,3969824.121341723,44.483725714207885],[231797.68770013095,3969824.121341723,44.521825790207885],[231797.67353181698,3969827.7713142238,44.4107257142079],[231797.67353181698,3969827.7713142238,44.448825790207884],[231802.68766246125,3969824.140750372,44.44522867067251],[231802.68766246125,3969824.140750372,44.4833287466725],[231802.67349414725,3969827.790722873,44.3722286706725],[231802.67349414725,3969827.790722873,44.410328746672505],[231807.6876247915,3969824.160159021,44.40794206761816],[231807.6876247915,3969824.160159021,44.44604214361816],[231807.67345647755,3969827.810131522,44.33494206761817],[231807.67345647755,3969827.810131522,44.37304214361816],[231812.6875871218,3969824.17956767,44.37186590504487],[231812.6875871218,3969824.17956767,44.40996598104487],[231812.67341880786,3969827.829540171,44.29886590504486],[231812.67341880786,3969827.829540171,44.33696598104487],[231817.68754945206,3969824.1989763193,44.337000182952615],[231817.68754945206,3969824.1989763193,44.3751002589526],[231817.67338113816,3969827.8489488205,44.2640001829526],[231817.67338113816,3969827.8489488205,44.302100258952606],[231822.68751178237,3969824.2183849686,44.30334490134138],[231822.68751178237,3969824.2183849686,44.34144497734138],[231822.6733434684,3969827.8683574703,44.2303449013414],[231822.6733434684,3969827.8683574703,44.26844497734138],[231827.68747411267,3969824.2377936174,44.27090006021121],[231827.68747411267,3969824.2377936174,44.30900013621121],[231827.67330579873,3969827.8877661196,44.19790006021122],[231827.67330579873,3969827.8877661196,44.23600013621122],[231832.68743644297,3969824.2572022676,44.23966565956208],[231832.68743644297,3969824.2572022676,44.27776573556207],[231832.67326812903,3969827.9071747684,44.16666565956208],[231832.67326812903,3969827.9071747684,44.20476573556207],[231837.6873987732,3969824.2766109165,44.209641699393984],[231837.6873987732,3969824.2766109165,44.247741775393976],[231837.67323045927,3969827.9265834177,44.136641699393984],[231837.67323045927,3969827.9265834177,44.17474177539398],[231842.68736110354,3969824.296019566,44.180828179706936],[231842.68736110354,3969824.296019566,44.21892825570693],[231842.67319278957,3969827.9459920665,44.10782817970692],[231842.67319278957,3969827.9459920665,44.14592825570692],[231847.68732343384,3969824.315428215,44.15322510050091],[231847.68732343384,3969824.315428215,44.19132517650092],[231847.6731551199,3969827.9654007168,44.08022510050092],[231847.6731551199,3969827.9654007168,44.11832517650092],[231852.68728576408,3969824.334836864,44.126832461775955],[231852.68728576408,3969824.334836864,44.16493253777594],[231852.6731174502,3969827.984809365,44.05383246177594],[231852.6731174502,3969827.984809365,44.091932537775946],[231857.6872480944,3969824.3542455127,44.101650263532015],[231857.6872480944,3969824.3542455127,44.139750339532014],[231857.67307978045,3969828.004218015,44.02865026353201],[231857.67307978045,3969828.004218015,44.066750339532014],[231862.68721042472,3969824.373654163,44.07767850576912],[231862.68721042472,3969824.373654163,44.115778581769135],[231862.67304211075,3969828.023626664,44.00467850576912],[231862.67304211075,3969828.023626664,44.04277858176912],[231867.68717275502,3969824.3930628123,44.054917188487266],[231867.68717275502,3969824.3930628123,44.09301726448727],[231867.67300444108,3969828.043035313,43.98191718848727],[231867.67300444108,3969828.043035313,44.020017264487265],[231872.68713508526,3969824.4124714616,44.033366311686464],[231872.68713508526,3969824.4124714616,44.07146638768647],[231872.67296677132,3969828.0624439623,43.960366311686464],[231872.67296677132,3969828.0624439623,43.99846638768647],[231877.68709741556,3969824.4318801104,44.013025875366694],[231877.68709741556,3969824.4318801104,44.05112595136669],[231879.78155222532,3969824.4400102794,44.00486510881276],[231879.78155222532,3969824.4400102794,44.042965184812765],[231877.67292910168,3969828.0818526116,43.9400258753667],[231877.67292910168,3969828.0818526116,43.97812595136669],[231882.6870597459,3969824.4512887597,43.99389587952797],[231882.6870597459,3969824.4512887597,44.031995955527975],[231879.76738391138,3969828.0899827806,43.93186510881276],[231879.76738391138,3969828.0899827806,43.969965184812764],[231882.67289143192,3969828.1012612614,43.93542352658119],[231882.67289143192,3969828.1012612614,43.97352360258118],[231887.6870220762,3969824.4706974085,43.9759763241703],[231887.6870220762,3969824.4706974085,44.01407640017029],[231887.6728537622,3969828.1206699107,43.942503971223395],[231887.6728537622,3969828.1206699107,43.98060404722341],[231892.68698440643,3969824.490106059,43.95926720929364],[231892.68698440643,3969824.490106059,43.99736728529365],[231894.38144222982,3969824.496683535,43.953879203201055],[231894.38144222982,3969824.496683535,43.99197927920104],[231892.6728160925,3969828.14007856,43.95079485634681],[231892.6728160925,3969828.14007856,43.98889493234681],[231894.36727391588,3969828.1466560364,43.953879203201055],[231894.36727391588,3969828.1466560364,43.99197927920104],[231897.6869568894,3969824.50639286,43.94376853489804],[231897.6869568894,3969824.50639286,43.98186861089804],[231897.67968293463,3969828.1563856127,43.960296181951236],[231897.67968293463,3969828.1563856127,43.99839625795123],[231902.68695439264,3969824.5092143305,43.92948030098347],[231902.68695439264,3969824.5092143305,43.96758037698347],[231902.6901090041,3969828.159212967,43.971007948036636],[231902.6901090041,3969828.159212967,44.00910802403662],[231907.68693954908,3969824.4977501007,43.916402507549954],[231907.68693954908,3969824.4977501007,43.95450258354995],[231908.98139927528,3969824.4924540888,43.91321399730674],[231908.98139927528,3969824.4924540888,43.95131407330675],[231910.3813826965,3969824.4856485515,43.90985687133767],[231910.3813826965,3969824.4856485515,43.947956947337666],[231907.70052270102,3969828.1477248264,43.982930154603075],[231907.70052270102,3969828.1477248264,44.02103023060307],[231908.99768230034,3969828.142417769,43.98621399730685],[231908.99768230034,3969828.142417769,44.024314073306854],[231912.68687154257,3969824.4720002664,43.90453515459749],[231912.68687154257,3969824.4720002664,43.942635230597475],[231910.400585687,3969828.1355980365,43.98985687133703],[231910.400585687,3969828.1355980365,44.02795694733703],[231912.71088312403,3969828.1219212846,43.99606280165058],[231912.71088312403,3969828.1219212846,44.03416287765059],[231917.6867095573,3969824.4319650354,43.89387824212604],[231917.6867095573,3969824.4319650354,43.93197831812604],[231917.72114937234,3969828.081802552,44.010405889179225],[231917.72114937234,3969828.081802552,44.04850596517924],[231922.6864127783,3969824.377644737,43.88443177013564],[231922.6864127783,3969824.377644737,43.92253184613564],[231922.73128054582,3969828.027368957,44.02595941718883],[231922.73128054582,3969828.027368957,44.06405949318883],[231926.38055354578,3969824.3283308963,43.878229449999964],[231926.38055354578,3969824.3283308963,43.91632952599996],[231927.6859403918,3969824.309039812,43.87619573862628],[231927.6859403918,3969824.309039812,43.91429581462628],[231926.43312623544,3969827.9779522615,44.03822944999877],[231926.43312623544,3969827.9779522615,44.07632952599877],[231927.7412357454,3969827.958620942,44.04272338567941],[231927.7412357454,3969827.958620942,44.0808234616794],[231932.68525158515,3969824.226150823,43.86917014759797],[231932.68525158515,3969824.226150823,43.90727022359796],[231935.05473618413,3969824.181873632,43.86626298906988],[231935.05473618413,3969824.181873632,43.90436306506987],[231932.7509740736,3969827.87555907,44.06069779465106],[231932.7509740736,3969827.87555907,44.09879787065106],[231937.6843055479,3969824.1289784457,43.86335499705069],[231937.6843055479,3969824.1289784457,43.901455073050684],[231935.12540074045,3969827.8311895295,44.0696401282989],[231935.12540074045,3969827.8311895295,44.107740204298906],[231937.76045463458,3969827.778184018,44.06673213627971],[231937.76045463458,3969827.778184018,44.104832212279725],[231942.37761738684,3969824.0247437214,43.85899693918792],[231942.37761738684,3969824.0247437214,43.89709701518792],[231942.68306147133,3969824.017523472,43.85875028698446],[231942.68306147133,3969824.017523472,43.89685036298445],[231942.4635553811,3969827.6737318896,44.06237407841695],[231942.4635553811,3969827.6737318896,44.100474154416936],[231942.7696365347,3969827.6664965823,44.06212742621348],[231942.7696365347,3969827.6664965823,44.100227502213485],[231947.68147854935,3969823.8917868137,43.85535601739927],[231947.68147854935,3969823.8917868137,43.89345609339926],[231947.7784788826,3969827.540497673,44.058733156628286],[231947.7784788826,3969827.540497673,44.09683323262829],[231952.67951597858,3969823.7517694957,43.853172188295105],[231952.67951597858,3969823.7517694957,43.89127226429511],[231952.7869407899,3969827.400188319,44.056549327524145],[231952.7869407899,3969827.400188319,44.09464940352413],[231957.67713295875,3969823.5974726626,43.852198799671996],[231957.67713295875,3969823.5974726626,43.890298875672],[231958.3712370051,3969823.574912402,43.85215933890154],[231958.3712370051,3969823.574912402,43.89025941490154],[231957.79498137117,3969827.2455696664,44.055575938901036],[231957.79498137117,3969827.2455696664,44.09367601490102],[231958.49053312026,3969827.222962352,44.05553647813056],[231958.49053312026,3969827.222962352,44.09363655413057],[231962.67428869297,3969823.4288975727,43.85243585152993],[231962.67428869297,3969823.4288975727,43.89053592752993],[231962.80255974457,3969827.0766429775,44.05581299075896],[231962.80255974457,3969827.0766429775,44.09391306675895],[231967.6709423882,3969823.246045602,43.853883343868894],[231967.6709423882,3969823.246045602,43.89198341986889],[231967.80963503176,3969826.89340963,44.05726048309792],[231967.80963503176,3969826.89340963,44.09536055909793],[231972.66705325549,3969823.0489182444,43.85654127668891],[231972.66705325549,3969823.0489182444,43.8946413526889],[231974.36007547379,3969822.978874542,43.85771664914085],[231974.36007547379,3969822.978874542,43.89581672514083],[231972.81616635883,3969826.695871121,44.05991841591793],[231972.81616635883,3969826.695871121,44.09801849191794],[231977.6625805102,3969822.8375171074,43.860409649989954],[231977.6625805102,3969822.8375171074,43.89850972598996],[231974.51271973774,3969826.625681328,44.06109378836987],[231974.51271973774,3969826.625681328,44.099193864369866],[231977.8221128561,3969826.484029061,44.06378678921899],[231977.8221128561,3969826.484029061,44.10188686521898],[231981.6775772967,3969822.6572443377,43.86439660047098],[231981.6775772967,3969822.6572443377,43.90249667647098],[231982.6574833726,3969822.611843919,43.86548846377205],[231982.6574833726,3969822.611843919,43.903588539772045],[231981.84548377877,3969826.3033802942,44.06777373970001],[231981.84548377877,3969826.3033802942,44.105873815700015],[231982.82743365876,3969826.2578851823,44.063960816714015],[231982.82743365876,3969826.2578851823,44.102060892714015],[231987.65172106802,3969822.371900519,43.87177771803518],[231987.65172106802,3969822.371900519,43.90987779403519],[231990.34279626585,3969822.2366799647,43.8756688699058],[231990.34279626585,3969822.2366799647,43.913768945905794],[231987.8320879071,3969826.0174413295,44.04525007097714],[231987.8320879071,3969826.0174413295,44.083350146977146],[231992.64525282718,3969822.1176888673,43.879277412779366],[231992.64525282718,3969822.1176888673,43.91737748877936],[231990.52877591894,3969825.8819387443,44.035668869904626],[231990.52877591894,3969825.8819387443,44.07376894590464],[231992.83603474675,3969825.7626994653,44.02774976572125],[231992.83603474675,3969825.7626994653,44.06584984172125],[231997.63803788653,3969821.8492110386,43.88798754800458],[231997.63803788653,3969821.8492110386,43.92608762400457],[231997.83923332926,3969825.4936616695,44.01145990094651],[231997.83923332926,3969825.4936616695,44.0495599769465],[232002.63003548872,3969821.566469226,43.89790812371083],[232002.63003548872,3969821.566469226,43.93600819971083],[232002.84164281213,3969825.210330137,43.99638047665281],[232002.84164281213,3969825.210330137,44.03448055265281],[232006.31806336567,3969821.3483907105,43.90601600119643],[232006.31806336567,3969821.3483907105,43.94411607719644],[232007.62120488277,3969821.2694657366,43.909039139898134],[232007.62120488277,3969821.2694657366,43.947139215898126],[232007.7155003888,3969821.2637168565,43.90926110178639],[232007.7155003888,3969821.2637168565,43.9473611777864],[232006.53736286156,3969824.991796773,43.986016001195814],[232006.53736286156,3969824.991796773,44.0241160771958],[232007.84322235952,3969824.912707183,43.98251149283999],[232007.84322235952,3969824.912707183,44.02061156883998],[232007.93771453897,3969824.906946313,43.982261101786506],[232007.93771453897,3969824.906946313,44.02036117778651],[232012.61150532452,3969820.958202994,43.92138059656648],[232012.61150532452,3969820.958202994,43.959480672566464],[232012.84393114215,3969824.600795235,43.96985294950832],[232012.84393114215,3969824.600795235,44.00795302550832],[232017.60089607674,3969820.6326835407,43.93493249371585],[232017.60089607674,3969820.6326835407,43.973032569715855],[232017.84372833796,3969824.2745968415,43.95840484665774],[232017.84372833796,3969824.2745968415,43.996504922657756],[232022.28454138056,3969820.3140810337,43.94875804301272],[232022.28454138056,3969820.3140810337,43.98685811901272],[232022.5893382642,3969820.2929366403,43.94969483134627],[232022.5893382642,3969820.2929366403,43.98779490734628],[232022.53714238774,3969823.9553298205,43.94875804301272],[232022.53714238774,3969823.9553298205,43.98685811901272],[232022.84193927137,3969823.934185427,43.94816718428813],[232022.84193927137,3969823.934185427,43.98626726028814],[232027.5773503016,3969819.946907863,43.965667609457746],[232027.5773503016,3969819.946907863,44.00376768545774],[232027.82995130878,3969823.588156651,43.9391399623997],[232027.82995130878,3969823.588156651,43.97724003839971],[232032.56536233908,3969819.6008790866,43.98285082805024],[232032.56536233908,3969819.6008790866,44.02095090405023],[232032.8179633462,3969823.2421278735,43.93132318099216],[232032.8179633462,3969823.2421278735,43.969423256992165],[232036.84953653693,3969819.303677005,43.998575683956545],[232036.84953653693,3969819.303677005,44.036675759956545],[232037.5533743765,3969819.2548503093,44.001244487123785],[232037.5533743765,3969819.2548503093,44.03934456312378],[232037.10213754408,3969822.944925793,43.92557568395655],[232037.10213754408,3969822.944925793,43.96367575995655],[232037.80597538367,3969822.896099097,43.928244487123784],[232037.80597538367,3969822.896099097,43.966344563123776],[232042.5413864139,3969818.9088215325,44.020848586678376],[232042.5413864139,3969818.9088215325,44.05894866267837],[232042.79398742106,3969822.5500703203,43.94784858667836],[232042.79398742106,3969822.5500703203,43.98594866267837],[232047.52939845138,3969818.562792756,44.041663126713985],[232047.52939845138,3969818.562792756,44.07976320271399],[232047.7819994585,3969822.204041543,43.96866312671399],[232047.7819994585,3969822.204041543,44.006763202713984],[232052.51741048877,3969818.216763979,44.06368810723066],[232052.51741048877,3969818.216763979,44.10178818323067],[232052.77001149594,3969821.8580127656,43.99068810723065],[232052.77001149594,3969821.8580127656,44.02878818323065],[232057.5054225262,3969817.8707352015,44.08692352822836],[232057.5054225262,3969817.8707352015,44.12502360422836],[232057.75802353336,3969821.5119839893,44.01392352822837],[232057.75802353336,3969821.5119839893,44.05202360422836],[232062.49343456366,3969817.5247064247,44.11136938970711],[232062.49343456366,3969817.5247064247,44.149469465707114],[232062.74603557083,3969821.165955212,44.038369389707114],[232062.74603557083,3969821.165955212,44.07646946570711],[232067.48144660107,3969817.1786776483,44.1370256916669],[232067.48144660107,3969817.1786776483,44.175125767666906],[232067.73404760825,3969820.819926435,44.0640256916669],[232067.73404760825,3969820.819926435,44.1021257676669],[232072.46945863854,3969816.832648871,44.16389243410773],[232072.46945863854,3969816.832648871,44.20199251010773],[232072.72205964566,3969820.4738976588,44.090892434107744],[232072.72205964566,3969820.4738976588,44.12899251010773],[232077.45747067596,3969816.4866200946,44.1919696170296],[232077.45747067596,3969816.4866200946,44.23006969302961],[232077.71007168313,3969820.1278688814,44.118969617029606],[232077.71007168313,3969820.1278688814,44.1570696930296],[232082.44548271337,3969816.1405913173,44.22125724043253],[232082.44548271337,3969816.1405913173,44.259357316432514],[232082.69808372055,3969819.781840105,44.148257240432514],[232082.69808372055,3969819.781840105,44.18635731643252],[232087.43349475085,3969815.7945625405,44.25175530431648],[232087.43349475085,3969815.7945625405,44.28985538031647],[232087.68609575796,3969819.4358113282,44.17875530431647],[232087.68609575796,3969819.4358113282,44.216855380316474],[232092.42150678826,3969815.448533763,44.28346380868147],[232092.42150678826,3969815.448533763,44.32156388468146],[232092.6741077954,3969819.089782551,44.21046380868146],[232092.6741077954,3969819.089782551,44.248563884681474],[232097.40951882568,3969815.102504987,44.31638275352751],[232097.40951882568,3969815.102504987,44.3544828295275],[232099.09678878385,3969814.985455558,44.327792056924444],[232099.09678878385,3969814.985455558,44.36589213292445],[232097.66211983282,3969818.7437537746,44.2433827535275],[232097.66211983282,3969818.7437537746,44.281482829527505],[232102.39753086315,3969814.7564762104,44.3502471170312],[232102.39753086315,3969814.7564762104,44.388347193031215],[232099.34938979102,3969818.626704345,44.25479205692446],[232099.34938979102,3969818.626704345,44.29289213292445],[232102.6501318703,3969818.3977249963,44.2772471170312],[232102.6501318703,3969818.3977249963,44.3153471930312],[232107.38554290053,3969814.410447432,44.38418073178317],[232107.38554290053,3969814.410447432,44.422280807783174],[232107.6381439077,3969818.05169622,44.311180731783175],[232107.6381439077,3969818.05169622,44.349280807783174],[232112.373554938,3969814.0644186554,44.418114346535134],[232112.373554938,3969814.0644186554,44.45621442253513],[232112.62615594512,3969817.705667443,44.34511434653515],[232112.62615594512,3969817.705667443,44.38321442253513],[232117.36156697542,3969813.718389879,44.45204796128711],[232117.36156697542,3969813.718389879,44.490148037287106],[232117.6141679826,3969817.3596386667,44.379047961287114],[232117.6141679826,3969817.3596386667,44.417148037287106],[232122.34957901284,3969813.3723611026,44.48598157603907],[232122.34957901284,3969813.3723611026,44.52408165203908],[232122.60218002,3969817.0136098894,44.41298157603907],[232122.60218002,3969817.0136098894,44.45108165203908],[232127.3375910503,3969813.0263323253,44.51991519079105],[232127.3375910503,3969813.0263323253,44.55801526679104],[232127.59019205743,3969816.667581113,44.44691519079104],[232127.59019205743,3969816.667581113,44.485015266791045],[232131.43967678156,3969812.7417621,44.54782181889087],[232131.43967678156,3969812.7417621,44.585921894890866],[232132.32560308767,3969812.680303548,44.5538618857791],[232132.32560308767,3969812.680303548,44.591961961779106],[232131.6922777887,3969816.3830108875,44.47482181889088],[232131.6922777887,3969816.3830108875,44.51292189489087],[232132.5782040948,3969816.3215523358,44.480861885779106],[232132.5782040948,3969816.3215523358,44.5189619617791],[232137.31361512514,3969812.334274771,44.588357435269955],[232137.31361512514,3969812.334274771,44.626457511269955],[232137.5662161323,3969815.975523559,44.515357435269955],[232137.5662161323,3969815.975523559,44.55345751126995],[232142.3016271626,3969811.988245995,44.62368227273833],[232142.3016271626,3969811.988245995,44.66178234873831],[232142.55422816973,3969815.6294947816,44.550682272738314],[232142.55422816973,3969815.6294947816,44.58878234873832],[232147.2896392,3969811.6422172175,44.6598363981842],[232147.2896392,3969811.6422172175,44.697936474184196],[232147.54224020717,3969815.283466005,44.58683639818419],[232147.54224020717,3969815.283466005,44.624936474184196],[232152.27765123744,3969811.296188441,44.69681981160758],[232152.27765123744,3969811.296188441,44.734919887607575],[232152.53025224459,3969814.937437228,44.62381981160758],[232152.53025224459,3969814.937437228,44.661919887607574],[232157.26566327483,3969810.9501596643,44.73463251300848],[232157.26566327483,3969810.9501596643,44.772732589008484],[232157.518264282,3969814.591408452,44.661632513008485],[232157.518264282,3969814.591408452,44.699732589008484],[232162.2536753123,3969810.604130888,44.773274502386904],[232162.2536753123,3969810.604130888,44.811374578386896],[232162.50627631947,3969814.245379674,44.7002745023869],[232162.50627631947,3969814.245379674,44.7383745783869],[232167.2416873497,3969810.2581021097,44.81274577974284],[232167.2416873497,3969810.2581021097,44.850845855742826],[232167.49428835683,3969813.8993508974,44.73974577974283],[232167.49428835683,3969813.8993508974,44.77784585574283],[232172.22969938713,3969809.9120733333,44.85304634507627],[232172.22969938713,3969809.9120733333,44.89114642107627],[232172.4823003943,3969813.553322121,44.78004634507627],[232172.4823003943,3969813.553322121,44.818146421076264],[232177.2177114246,3969809.566044556,44.89417619838723],[232177.2177114246,3969809.566044556,44.93227627438722],[232177.47031243177,3969813.207293343,44.82117619838722],[232177.47031243177,3969813.207293343,44.859276274387234],[232182.20572346202,3969809.2200157787,44.936135339675694],[232182.20572346202,3969809.2200157787,44.9742354156757],[232182.45832446916,3969812.861264567,44.863135339675694],[232182.45832446916,3969812.861264567,44.9012354156757],[232187.19373549943,3969808.8739870028,44.97892376894169],[232187.19373549943,3969808.8739870028,45.017023844941676],[232187.44633650657,3969812.5152357896,44.905923768941676],[232187.44633650657,3969812.5152357896,44.94402384494168],[232192.18174753687,3969808.5279582255,45.02254148618517],[232192.18174753687,3969808.5279582255,45.060641562185175],[232192.434348544,3969812.169207013,44.94954148618517],[232192.434348544,3969812.169207013,44.98764156218517],[232197.1697595743,3969808.181929449,45.06698849140619],[232197.1697595743,3969808.181929449,45.105088567406185],[232197.42236058146,3969811.823178236,44.99398849140619],[232197.42236058146,3969811.823178236,45.03208856740619],[232202.1577716117,3969807.8359006722,45.11226478460471],[232202.1577716117,3969807.8359006722,45.150364860604704],[232202.41037261888,3969811.477149459,45.03926478460471],[232202.41037261888,3969811.477149459,45.07736486060471],[232207.14578364918,3969807.489871895,45.15837036578075],[232207.14578364918,3969807.489871895,45.19647044178074],[232207.3983846563,3969811.1311206827,45.085370365780754],[232207.3983846563,3969811.1311206827,45.12347044178074],[232212.1337956866,3969807.1438431176,45.20530523493429],[232212.1337956866,3969807.1438431176,45.2434053109343],[232212.38639669376,3969810.7850919054,45.13230523493431],[232212.38639669376,3969810.7850919054,45.17040531093429],[232217.121807724,3969806.7978143413,45.25306939206536],[232217.121807724,3969806.7978143413,45.29116946806536],[232217.37440873115,3969810.439063128,45.180069392065356],[232217.37440873115,3969810.439063128,45.21816946806536],[232222.10981976148,3969806.451785564,45.30166283717394],[232222.10981976148,3969806.451785564,45.33976291317394],[232222.3624207686,3969810.0930343517,45.228662837173935],[232222.3624207686,3969810.0930343517,45.26676291317395],[232227.09783179886,3969806.105756787,45.35108557026003],[232227.09783179886,3969806.105756787,45.38918564626003],[232227.35043280604,3969809.7470055744,45.27808557026003],[232227.35043280604,3969809.7470055744,45.316185646260024],[232232.0858438363,3969805.7597280107,45.401337591323625],[232232.0858438363,3969805.7597280107,45.43943766732363],[232232.33844484345,3969809.4009767985,45.328337591323624],[232232.33844484345,3969809.4009767985,45.36643766732363],[232237.07385587375,3969805.4136992334,45.45241890036475],[232237.07385587375,3969805.4136992334,45.49051897636476],[232237.32645688087,3969809.0549480203,45.37941890036475],[232237.32645688087,3969809.0549480203,45.41751897636475],[232242.06186791116,3969805.067670456,45.504329497383374],[232242.06186791116,3969805.067670456,45.54242957338338],[232242.31446891834,3969808.708919244,45.43132949738337],[232242.31446891834,3969808.708919244,45.46942957338338],[232247.04987994864,3969804.7216416798,45.557069382379524],[232247.04987994864,3969804.7216416798,45.59516945837954],[232247.30248095575,3969808.362890467,45.48406938237952],[232247.30248095575,3969808.362890467,45.52216945837952],[232252.03789198605,3969804.3756129025,45.610638555353184],[232252.03789198605,3969804.3756129025,45.64873863135318],[232252.29049299317,3969808.0168616897,45.537638555353176],[232252.29049299317,3969808.0168616897,45.57573863135319],[232257.02590402347,3969804.0295841256,45.665037016304346],[232257.02590402347,3969804.0295841256,45.70313709230435],[232257.27850503064,3969807.6708329134,45.592037016304346],[232257.27850503064,3969807.6708329134,45.630137092304345],[232262.01391606088,3969803.6835553492,45.72026476523304],[232262.01391606088,3969803.6835553492,45.75836484123303],[232262.26651706803,3969807.324804136,45.64726476523304],[232262.26651706803,3969807.324804136,45.68536484123304],[232267.00192809835,3969803.337526572,45.776321802139236],[232267.00192809835,3969803.337526572,45.81442187813923],[232267.25452910547,3969806.9787753597,45.70332180213923],[232267.25452910547,3969806.9787753597,45.741421878139235],[232271.98994013574,3969802.991497795,45.83320812702294],[232271.98994013574,3969802.991497795,45.871308203022956],[232272.2425411429,3969806.6327465824,45.76020812702294],[232272.2425411429,3969806.6327465824,45.79830820302294],[232276.97795217318,3969802.6454690187,45.890923739884165],[232276.97795217318,3969802.6454690187,45.92902381588418],[232277.23055318033,3969806.2867178055,45.817923739884165],[232277.23055318033,3969806.2867178055,45.856023815884164],[232281.96596421063,3969802.2994402414,45.949468640722905],[232281.96596421063,3969802.2994402414,45.98756871672291],[232282.2185652178,3969805.940689029,45.87646864072291],[232282.2185652178,3969805.940689029,45.914568716722904],[232286.95397624804,3969801.953411465,46.00884282953916],[232286.95397624804,3969801.953411465,46.04694290553917],[232287.20657725522,3969805.594660252,45.93584282953916],[232287.20657725522,3969805.594660252,45.97394290553917],[232291.9419882855,3969801.6073826877,46.06904630633293],[232291.9419882855,3969801.6073826877,46.10714638233292],[232292.19458929263,3969805.2486314746,45.99604630633293],[232292.19458929263,3969805.2486314746,46.03414638233293],[232296.93000032293,3969801.2613539104,46.130079071104205],[232296.93000032293,3969801.2613539104,46.16817914710422],[232297.18260133005,3969804.9026026977,46.05707907110421],[232297.18260133005,3969804.9026026977,46.095179147104204],[232301.91801236034,3969800.9153251336,46.191941123853006],[232301.91801236034,3969800.9153251336,46.23004119985299],[232302.17061336752,3969804.5565739213,46.11894112385299],[232302.17061336752,3969804.5565739213,46.157041199853],[232306.90602439776,3969800.569296357,46.2546324645793],[232306.90602439776,3969800.569296357,46.29273254057931],[232307.1586254049,3969804.210545144,46.1816324645793],[232307.1586254049,3969804.210545144,46.21973254057931],[232311.89403643523,3969800.22326758,46.31815309328312],[232311.89403643523,3969800.22326758,46.356253169283136],[232312.14663744235,3969803.8645163677,46.24515309328313],[232312.14663744235,3969803.8645163677,46.28325316928312],[232316.88204847265,3969799.877238803,46.382503009964466],[232316.88204847265,3969799.877238803,46.42060308596445],[232317.1346494798,3969803.5184875904,46.30950300996445],[232317.1346494798,3969803.5184875904,46.34760308596446],[232321.87006051006,3969799.5312100267,46.447682214623306],[232321.87006051006,3969799.5312100267,46.4857822906233],[232322.1226615172,3969803.1724588135,46.3746822146233],[232322.1226615172,3969803.1724588135,46.4127822906233],[232326.8580725475,3969799.1851812494,46.513690707259656],[232326.8580725475,3969799.1851812494,46.55179078325966],[232327.11067355468,3969802.826430037,46.44069070725966],[232327.11067355468,3969802.826430037,46.47879078325966],[232331.84608458492,3969798.839152472,46.580528487873536],[232331.84608458492,3969798.839152472,46.61862856387353],[232332.0986855921,3969802.48040126,46.507528487873536],[232332.0986855921,3969802.48040126,46.54562856387353],[232336.51620828634,3969798.515176272,46.64385836124185],[232336.51620828634,3969798.515176272,46.681958437241846],[232336.8340966224,3969798.4931236957,46.64819387235834],[232336.8340966224,3969798.4931236957,46.68629394835834],[232336.76880929348,3969802.1564250584,46.57085836124184],[232336.76880929348,3969802.1564250584,46.608958437241846],[232337.0866976295,3969802.1343724825,46.57519387235835],[232337.0866976295,3969802.1343724825,46.61329394835834],[232341.8221086598,3969798.1470949184,46.716222734028484],[232341.8221086598,3969798.1470949184,46.754322810028484],[232342.07470966692,3969801.788343706,46.643222734028484],[232342.07470966692,3969801.788343706,46.681322810028476],[232346.81012069722,3969797.8010661416,46.78425159569863],[232346.81012069722,3969797.8010661416,46.82235167169862],[232347.01132511083,3969797.7871081727,46.786995716426084],[232347.01132511083,3969797.7871081727,46.825095792426076],[232347.0627217044,3969801.4423149293,46.71125159569862],[232347.0627217044,3969801.4423149293,46.749351671698626],[232347.263926118,3969801.4283569604,46.71399571642609],[232347.263926118,3969801.4283569604,46.752095792426076]],"pointIndex":[7,8,10,9,0,8,2,4,10,0,2,1,3,4,0,1,7,9,3,0,9,10,16,15,0,10,4,6,16,0,4,3,5,6,0,3,9,15,5,0,15,16,18,17,0,16,6,12,18,0,6,5,11,12,0,5,15,17,11,0,17,18,22,21,0,18,12,14,22,0,12,11,13,14,0,11,17,21,13,0,21,22,26,25,0,22,14,20,26,0,14,13,19,20,0,13,21,25,19,0,25,26,28,27,0,26,20,24,28,0,20,19,23,24,0,19,25,27,23,0,27,28,34,33,0,28,24,30,34,0,24,23,29,30,0,23,27,33,29,0,33,34,40,39,0,34,30,32,40,0,30,29,31,32,0,29,33,39,31,0,39,40,44,43,0,40,32,36,44,0,32,31,35,36,0,31,39,43,35,0,43,44,46,45,0,44,36,38,46,0,36,35,37,38,0,35,43,45,37,0,45,46,50,49,0,46,38,42,50,0,38,37,41,42,0,37,45,49,41,0,49,50,52,51,0,50,42,48,52,0,42,41,47,48,0,41,49,51,47,0,51,52,59,57,0,52,48,55,59,0,48,47,53,55,0,47,51,57,53,0,57,59,60,58,0,59,55,56,60,0,55,53,54,56,0,53,57,58,54,0,58,60,66,65,0,60,56,62,66,0,56,54,61,62,0,54,58,65,61,0,65,66,70,69,0,66,62,64,70,0,62,61,63,64,0,61,65,69,63,0,69,70,74,73,0,70,64,68,74,0,64,63,67,68,0,63,69,73,67,0,73,74,78,77,0,74,68,72,78,0,68,67,71,72,0,67,73,77,71,0,77,78,80,79,0,78,72,76,80,0,72,71,75,76,0,71,77,79,75,0,79,80,86,85,0,80,76,82,86,0,76,75,81,82,0,75,79,85,81,0,85,86,88,87,0,86,82,84,88,0,82,81,83,84,0,81,85,87,83,0,87,88,94,93,0,88,84,90,94,0,84,83,89,90,0,83,87,93,89,0,93,94,98,97,0,94,90,92,98,0,90,89,91,92,0,89,93,97,91,0,97,98,100,99,0,98,92,96,100,0,92,91,95,96,0,91,97,99,95,0,99,100,106,105,0,100,96,102,106,0,96,95,101,102,0,95,99,105,101,0,105,106,108,107,0,106,102,104,108,0,102,101,103,104,0,101,105,107,103,0,107,108,114,113,0,108,104,110,114,0,104,103,109,110,0,103,107,113,109,0,113,114,116,115,0,114,110,112,116,0,110,109,111,112,0,109,113,115,111,0,115,116,120,119,0,116,112,118,120,0,112,111,117,118,0,111,115,119,117,0,119,120,126,125,0,120,118,122,126,0,118,117,121,122,0,117,119,125,121,0,125,126,128,127,0,126,122,124,128,0,122,121,123,124,0,121,125,127,123,0,127,128,132,131,0,128,124,130,132,0,124,123,129,130,0,123,127,131,129,0,131,132,136,135,0,132,130,134,136,0,130,129,133,134,0,129,131,135,133,0,135,136,140,139,0,136,134,138,140,0,134,133,137,138,0,133,135,139,137,0,139,140,144,143,0,140,138,142,144,0,138,137,141,142,0,137,139,143,141,0,143,144,148,147,0,144,142,146,148,0,142,141,145,146,0,141,143,147,145,0,147,148,152,151,0,148,146,150,152,0,146,145,149,150,0,145,147,151,149,0,151,152,156,155,0,152,150,154,156,0,150,149,153,154,0,149,151,155,153,0,155,156,160,159,0,156,154,158,160,0,154,153,157,158,0,153,155,159,157,0,159,160,164,163,0,160,158,162,164,0,158,157,161,162,0,157,159,163,161,0,163,164,168,167,0,164,162,166,168,0,162,161,165,166,0,161,163,167,165,0,167,168,172,171,0,168,166,170,172,0,166,165,169,170,0,165,167,171,169,0,171,172,176,175,0,172,170,174,176,0,170,169,173,174,0,169,171,175,173,0,175,176,180,179,0,176,174,178,180,0,174,173,177,178,0,173,175,179,177,0,179,180,184,183,0,180,178,182,184,0,178,177,181,182,0,177,179,183,181,0,183,184,188,187,0,184,182,186,188,0,182,181,185,186,0,181,183,187,185,0,187,188,192,191,0,188,186,190,192,0,186,185,189,190,0,185,187,191,189,0,191,192,196,195,0,192,190,194,196,0,190,189,193,194,0,189,191,195,193,0,195,196,200,199,0,196,194,198,200,0,194,193,197,198,0,193,195,199,197,0,199,200,204,203,0,200,198,202,204,0,198,197,201,202,0,197,199,203,201,0,203,204,208,207,0,204,202,206,208,0,202,201,205,206,0,201,203,207,205,0,207,208,212,211,0,208,206,210,212,0,206,205,209,210,0,205,207,211,209,0,211,212,216,215,0,212,210,214,216,0,210,209,213,214,0,209,211,215,213,0,215,216,220,219,0,216,214,218,220,0,214,213,217,218,0,213,215,219,217,0,219,220,224,223,0,220,218,222,224,0,218,217,221,222,0,217,219,223,221,0,223,224,228,227,0,224,222,226,228,0,222,221,225,226,0,221,223,227,225,0,227,228,232,231,0,228,226,230,232,0,226,225,229,230,0,225,227,231,229,0,231,232,236,235,0,232,230,234,236,0,230,229,233,234,0,229,231,235,233,0,235,236,240,239,0,236,234,238,240,0,234,233,237,238,0,233,235,239,237,0,239,240,244,243,0,240,238,242,244,0,238,237,241,242,0,237,239,243,241,0,243,244,248,247,0,244,242,246,248,0,242,241,245,246,0,241,243,247,245,0,247,248,252,251,0,248,246,250,252,0,246,245,249,250,0,245,247,251,249,0,251,252,258,257,0,252,250,254,258,0,250,249,253,254,0,249,251,257,253,0,257,258,260,259,0,258,254,256,260,0,254,253,255,256,0,253,257,259,255,0,259,260,264,263,0,260,256,262,264,0,256,255,261,262,0,255,259,263,261,0,263,264,268,267,0,264,262,266,268,0,262,261,265,266,0,261,263,267,265,0,267,268,272,271,0,268,266,270,272,0,266,265,269,270,0,265,267,271,269,0,271,272,276,275,0,272,270,274,276,0,270,269,273,274,0,269,271,275,273,0,275,276,282,281,0,276,274,278,282,0,274,273,277,278,0,273,275,281,277,0,283,281,282,284,0,284,282,278,280,0,280,278,277,279,0,279,277,281,283,0,289,289,290,290,0,290,290,288,288,0,289,289,286,286,0,288,288,287,287,0,287,287,285,285,0,285,285,286,286,0,295,296,298,297,0,296,292,294,298,0,292,291,293,294,0,291,295,297,293,0,297,298,302,301,0,298,294,300,302,0,294,293,299,300,0,293,297,301,299,0,301,302,306,305,0,302,300,304,306,0,300,299,303,304,0,299,301,305,303,0,305,306,310,309,0,306,304,308,310,0,304,303,307,308,0,303,305,309,307,0,309,310,314,313,0,310,308,312,314,0,308,307,311,312,0,307,309,313,311,0,313,314,318,317,0,314,312,316,318,0,312,311,315,316,0,311,313,317,315,0,317,318,322,321,0,318,316,320,322,0,316,315,319,320,0,315,317,321,319,0,321,322,326,325,0,322,320,324,326,0,320,319,323,324,0,319,321,325,323,0,325,326,330,329,0,326,324,328,330,0,324,323,327,328,0,323,325,329,327,0,329,330,334,333,0,330,328,332,334,0,328,327,331,332,0,327,329,333,331,0,333,334,338,337,0,334,332,336,338,0,332,331,335,336,0,331,333,337,335,0,337,338,342,341,0,338,336,340,342,0,336,335,339,340,0,335,337,341,339,0,341,342,346,345,0,342,340,344,346,0,340,339,343,344,0,339,341,345,343,0,345,346,350,349,0,346,344,348,350,0,344,343,347,348,0,343,345,349,347,0,349,350,354,353,0,350,348,352,354,0,348,347,351,352,0,347,349,353,351,0,353,354,358,357,0,354,352,356,358,0,352,351,355,356,0,351,353,357,355,0,357,358,362,361,0,358,356,360,362,0,356,355,359,360,0,355,357,361,359,0,361,362,366,365,0,362,360,364,366,0,360,359,363,364,0,359,361,365,363,0,365,366,370,369,0,366,364,368,370,0,364,363,367,368,0,363,365,369,367,0,369,370,374,373,0,370,368,372,374,0,368,367,371,372,0,367,369,373,371,0,373,374,378,377,0,374,372,376,378,0,372,371,375,376,0,371,373,377,375,0,377,378,382,381,0,378,376,380,382,0,376,375,379,380,0,375,377,381,379,0,381,382,386,385,0,382,380,384,386,0,380,379,383,384,0,379,381,385,383,0,385,386,390,389,0,386,384,388,390,0,384,383,387,388,0,383,385,389,387,0,389,390,394,393,0,390,388,392,394,0,388,387,391,392,0,387,389,393,391,0,393,394,398,397,0,394,392,396,398,0,392,391,395,396,0,391,393,397,395,0,397,398,402,401,0,398,396,400,402,0,396,395,399,400,0,395,397,401,399,0,401,402,406,405,0,402,400,404,406,0,400,399,403,404,0,399,401,405,403,0,405,406,410,409,0,406,404,408,410,0,404,403,407,408,0,403,405,409,407,0,409,410,414,413,0,410,408,412,414,0,408,407,411,412,0,407,409,413,411,0,413,414,418,417,0,414,412,416,418,0,412,411,415,416,0,411,413,417,415,0,417,418,422,421,0,418,416,420,422,0,416,415,419,420,0,415,417,421,419,0,421,422,426,425,0,422,420,424,426,0,420,419,423,424,0,419,421,425,423,0,425,426,430,429,0,426,424,428,430,0,424,423,427,428,0,423,425,429,427,0,429,430,434,433,0,430,428,432,434,0,428,427,431,432,0,427,429,433,431,0,433,434,438,437,0,434,432,436,438,0,432,431,435,436,0,431,433,437,435,0,437,438,442,441,0,438,436,440,442,0,436,435,439,440,0,435,437,441,439,0,441,442,446,445,0,442,440,444,446,0,440,439,443,444,0,439,441,445,443,0,445,446,450,449,0,446,444,448,450,0,444,443,447,448,0,443,445,449,447,0,449,450,454,453,0,450,448,452,454,0,448,447,451,452,0,447,449,453,451,0,453,454,460,459,0,454,452,456,460,0,452,451,455,456,0,451,453,459,455,0,459,460,464,463,0,460,456,458,464,0,456,455,457,458,0,455,459,463,457,0,463,464,466,465,0,464,458,462,466,0,458,457,461,462,0,457,463,465,461,0,465,466,470,469,0,466,462,468,470,0,462,461,467,468,0,461,465,469,467,0,469,470,476,475,0,470,468,472,476,0,468,467,471,472,0,467,469,475,471,0,475,476,478,477,0,476,472,474,478,0,472,471,473,474,0,471,475,477,473,0,477,478,482,481,0,478,474,480,482,0,474,473,479,480,0,473,477,481,479,0,481,482,486,485,0,482,480,484,486,0,480,479,483,484,0,479,481,485,483,0,485,486,494,493,0,486,484,488,494,0,484,483,487,488,0,483,485,493,487,0,493,494,496,495,0,494,488,490,496,0,488,487,489,490,0,487,493,495,489,0,495,496,500,499,0,496,490,492,500,0,490,489,491,492,0,489,495,499,491,0,499,500,502,501,0,500,492,498,502,0,492,491,497,498,0,491,499,501,497,0,501,502,506,505,0,502,498,504,506,0,498,497,503,504,0,497,501,505,503,0,505,506,510,509,0,506,504,508,510,0,504,503,507,508,0,503,505,509,507,0,509,510,516,515,0,510,508,512,516,0,508,507,511,512,0,507,509,515,511,0,515,516,518,517,0,516,512,514,518,0,512,511,513,514,0,511,515,517,513,0,517,518,524,523,0,518,514,520,524,0,514,513,519,520,0,513,517,523,519,0,523,524,528,527,0,524,520,522,528,0,520,519,521,522,0,519,523,527,521,0,527,528,530,529,0,528,522,526,530,0,522,521,525,526,0,521,527,529,525,0,529,530,536,535,0,530,526,532,536,0,526,525,531,532,0,525,529,535,531,0,535,536,538,537,0,536,532,534,538,0,532,531,533,534,0,531,535,537,533,0,537,538,542,541,0,538,534,540,542,0,534,533,539,540,0,533,537,541,539,0,541,542,546,545,0,542,540,544,546,0,540,539,543,544,0,539,541,545,543,0,545,546,552,551,0,546,544,548,552,0,544,543,547,548,0,543,545,551,547,0,551,552,554,553,0,552,548,550,554,0,548,547,549,550,0,547,551,553,549,0,553,554,558,557,0,554,550,556,558,0,550,549,555,556,0,549,553,557,555,0,557,558,562,561,0,558,556,560,562,0,556,555,559,560,0,555,557,561,559,0,561,562,568,567,0,562,560,564,568,0,560,559,563,564,0,559,561,567,563,0,567,568,572,571,0,568,564,566,572,0,564,563,565,566,0,563,567,571,565,0,571,572,574,573,0,572,566,570,574,0,566,565,569,570,0,565,571,573,569,0,573,574,580,579,0,574,570,576,580,0,570,569,575,576,0,569,573,579,575,0,579,580,582,581,0,580,576,578,582,0,576,575,577,578,0,575,579,581,577,0,581,582,588,587,0,582,578,584,588,0,578,577,583,584,0,577,581,587,583,0,587,588,592,591,0,588,584,586,592,0,584,583,585,586,0,583,587,591,585,0,591,592,594,593,0,592,586,590,594,0,586,585,589,590,0,585,591,593,589,0,593,594,598,597,0,594,590,596,598,0,590,589,595,596,0,589,593,597,595,0,597,598,602,601,0,598,596,600,602,0,596,595,599,600,0,595,597,601,599,0,601,602,610,609,0,602,600,604,610,0,600,599,603,604,0,599,601,609,603,0,609,610,612,611,0,610,604,606,612,0,604,603,605,606,0,603,609,611,605,0,611,612,614,613,0,612,606,608,614,0,606,605,607,608,0,605,611,613,607,0,613,614,618,617,0,614,608,616,618,0,608,607,615,616,0,607,613,617,615,0,617,618,622,621,0,618,616,620,622,0,616,615,619,620,0,615,617,621,619,0,621,622,628,627,0,622,620,624,628,0,620,619,623,624,0,619,621,627,623,0,627,628,630,629,0,628,624,626,630,0,624,623,625,626,0,623,627,629,625,0,629,630,634,633,0,630,626,632,634,0,626,625,631,632,0,625,629,633,631,0,633,634,638,637,0,634,632,636,638,0,632,631,635,636,0,631,633,637,635,0,637,638,644,643,0,638,636,640,644,0,636,635,639,640,0,635,637,643,639,0,643,644,646,645,0,644,640,642,646,0,640,639,641,642,0,639,643,645,641,0,645,646,650,649,0,646,642,648,650,0,642,641,647,648,0,641,645,649,647,0,649,650,654,653,0,650,648,652,654,0,648,647,651,652,0,647,649,653,651,0,653,654,658,657,0,654,652,656,658,0,652,651,655,656,0,651,653,657,655,0,657,658,662,661,0,658,656,660,662,0,656,655,659,660,0,655,657,661,659,0,661,662,666,665,0,662,660,664,666,0,660,659,663,664,0,659,661,665,663,0,665,666,670,669,0,666,664,668,670,0,664,663,667,668,0,663,665,669,667,0,669,670,674,673,0,670,668,672,674,0,668,667,671,672,0,667,669,673,671,0,673,674,678,677,0,674,672,676,678,0,672,671,675,676,0,671,673,677,675,0,677,678,682,681,0,678,676,680,682,0,676,675,679,680,0,675,677,681,679,0,681,682,686,685,0,682,680,684,686,0,680,679,683,684,0,679,681,685,683,0,685,686,690,689,0,686,684,688,690,0,684,683,687,688,0,683,685,689,687,0,689,690,696,695,0,690,688,692,696,0,688,687,691,692,0,687,689,695,691,0,695,696,700,699,0,696,692,694,700,0,692,691,693,694,0,691,695,699,693,0,699,700,702,701,0,700,694,698,702,0,694,693,697,698,0,693,699,701,697,0,701,702,706,705,0,702,698,704,706,0,698,697,703,704,0,697,701,705,703,0,705,706,710,709,0,706,704,708,710,0,704,703,707,708,0,703,705,709,707,0,709,710,714,713,0,710,708,712,714,0,708,707,711,712,0,707,709,713,711,0,713,714,718,717,0,714,712,716,718,0,712,711,715,716,0,711,713,717,715,0,717,718,722,721,0,718,716,720,722,0,716,715,719,720,0,715,717,721,719,0,721,722,728,727,0,722,720,724,728,0,720,719,723,724,0,719,721,727,723,0,727,728,730,729,0,728,724,726,730,0,724,723,725,726,0,723,727,729,725,0,729,730,734,733,0,730,726,732,734,0,726,725,731,732,0,725,729,733,731,0,733,734,738,737,0,734,732,736,738,0,732,731,735,736,0,731,733,737,735,0,737,738,742,741,0,738,736,740,742,0,736,735,739,740,0,735,737,741,739,0,741,742,746,745,0,742,740,744,746,0,740,739,743,744,0,739,741,745,743,0,745,746,750,749,0,746,744,748,750,0,744,743,747,748,0,743,745,749,747,0,749,750,754,753,0,750,748,752,754,0,748,747,751,752,0,747,749,753,751,0,753,754,758,757,0,754,752,756,758,0,752,751,755,756,0,751,753,757,755,0,757,758,762,761,0,758,756,760,762,0,756,755,759,760,0,755,757,761,759,0,761,762,766,765,0,762,760,764,766,0,760,759,763,764,0,759,761,765,763,0,765,766,770,769,0,766,764,768,770,0,764,763,767,768,0,763,765,769,767,0,769,770,774,773,0,770,768,772,774,0,768,767,771,772,0,767,769,773,771,0,773,774,778,777,0,774,772,776,778,0,772,771,775,776,0,771,773,777,775,0,777,778,782,781,0,778,776,780,782,0,776,775,779,780,0,775,777,781,779,0,781,782,786,785,0,782,780,784,786,0,780,779,783,784,0,779,781,785,783,0,785,786,790,789,0,786,784,788,790,0,784,783,787,788,0,783,785,789,787,0,789,790,794,793,0,790,788,792,794,0,788,787,791,792,0,787,789,793,791,0,793,794,798,797,0,794,792,796,798,0,792,791,795,796,0,791,793,797,795,0,797,798,802,801,0,798,796,800,802,0,796,795,799,800,0,795,797,801,799,0,801,802,806,805,0,802,800,804,806,0,800,799,803,804,0,799,801,805,803,0,805,806,810,809,0,806,804,808,810,0,804,803,807,808,0,803,805,809,807,0,809,810,814,813,0,810,808,812,814,0,808,807,811,812,0,807,809,813,811,0,813,814,818,817,0,814,812,816,818,0,812,811,815,816,0,811,813,817,815,0,817,818,822,821,0,818,816,820,822,0,816,815,819,820,0,815,817,821,819,0,821,822,826,825,0,822,820,824,826,0,820,819,823,824,0,819,821,825,823,0,825,826,830,829,0,826,824,828,830,0,824,823,827,828,0,823,825,829,827,0,829,830,834,833,0,830,828,832,834,0,828,827,831,832,0,827,829,833,831,0,833,834,838,837,0,834,832,836,838,0,832,831,835,836,0,831,833,837,835,0,837,838,842,841,0,838,836,840,842,0,836,835,839,840,0,835,837,841,839,0,841,842,846,845,0,842,840,844,846,0,840,839,843,844,0,839,841,845,843,0,845,846,850,849,0,846,844,848,850,0,844,843,847,848,0,843,845,849,847,0,849,850,854,853,0,850,848,852,854,0,848,847,851,852,0,847,849,853,851,0,853,854,858,857,0,854,852,856,858,0,852,851,855,856,0,851,853,857,855,0,857,858,862,861,0,858,856,860,862,0,856,855,859,860,0,855,857,861,859,0,861,862,866,865,0,862,860,864,866,0,860,859,863,864,0,859,861,865,863,0,865,866,870,869,0,866,864,868,870,0,864,863,867,868,0,863,865,869,867,0,869,870,874,873,0,870,868,872,874,0,868,867,871,872,0,867,869,873,871,0,873,874,878,877,0,874,872,876,878,0,872,871,875,876,0,871,873,877,875,0,877,878,882,881,0,878,876,880,882,0,876,875,879,880,0,875,877,881,879,0,881,882,886,885,0,882,880,884,886,0,880,879,883,884,0,879,881,885,883,0,885,886,890,889,0,886,884,888,890,0,884,883,887,888,0,883,885,889,887,0,889,890,896,895,0,890,888,892,896,0,888,887,891,892,0,887,889,895,891,0,895,896,898,897,0,896,892,894,898,0,892,891,893,894,0,891,895,897,893,0,897,898,902,901,0,898,894,900,902,0,894,893,899,900,0,893,897,901,899,0,901,902,908,907,0,902,900,904,908,0,900,899,903,904,0,899,901,907,903,0,907,908,910,909,0,908,904,906,910,0,904,903,905,906,0,903,907,909,905,0,7,1,2,8,0,909,910,906,905,0,279,284,283,0,279,280,284,0,291,295,296,0,296,292,291,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [231318.71862147184, 3969833.794423595, 52.34198669098813], + [231318.71862147184, 3969833.794423595, 52.38008676698812], + [231319.0552437973, 3969833.699915871, 52.33530277647533], + [231319.0552437973, 3969833.699915871, 52.37340285247532], + [231323.5427737373, 3969832.480278922, 52.24640317426871], + [231323.5427737373, 3969832.480278922, 52.28450325026871], + [231319.70727180273, 3969837.3079788485, 52.04998669098812], + [231319.70727180273, 3969837.3079788485, 52.08808676698813], + [231320.03979855657, 3969837.214620969, 52.043302776475315], + [231320.03979855657, 3969837.214620969, 52.081402852475314], + [231325.74466138077, 3969831.909049104, 52.20291682334428], + [231325.74466138077, 3969831.909049104, 52.241016899344274], + [231328.38815739428, 3969831.24671558, 52.1508196575493], + [231328.38815739428, 3969831.24671558, 52.1889197335493], + [231324.4727302156, 3969836.009822936, 51.95440317426871], + [231324.4727302156, 3969836.009822936, 51.99250325026871], + [231326.6478282261, 3969835.44554308, 51.91091682334427], + [231326.6478282261, 3969835.44554308, 51.94901689934428], + [231332.473633145, 3969830.2730630464, 52.07053087021323], + [231332.473633145, 3969830.2730630464, 52.10863094621324], + [231329.2591617048, 3969834.791267948, 51.85881965754929], + [231329.2591617048, 3969834.791267948, 51.89691973354929], + [231333.25342653418, 3969830.0940762185, 52.055236140829884], + [231333.25342653418, 3969830.0940762185, 52.09333621682988], + [231333.29493083383, 3969833.8294615205, 51.77853087021324], + [231333.29493083383, 3969833.8294615205, 51.81663094621323], + [231334.0652367368, 3969833.652652365, 51.76323614082989], + [231334.0652367368, 3969833.652652365, 51.801336216829874], + [231338.13722972453, 3969829.022681006, 51.959652624110475], + [231338.13722972453, 3969829.022681006, 51.99775270011046], + [231339.2385736313, 3969828.7928294153, 51.938144917082184], + [231339.2385736313, 3969828.7928294153, 51.97624499308219], + [231338.88962032163, 3969832.5942924623, 51.66765262411046], + [231338.88962032163, 3969832.5942924623, 51.705752700110466], + [231343.03821038472, 3969828.0328275478, 51.864069107391046], + [231343.03821038472, 3969828.0328275478, 51.90216918339105], + [231343.0886612497, 3969828.0230792924, 51.86308681418512], + [231343.0886612497, 3969828.0230792924, 51.90118689018512], + [231339.9775645442, 3969832.367237399, 51.64614491708219], + [231339.9775645442, 3969832.367237399, 51.68424499308219], + [231346.03587821542, 3969827.469136938, 51.80575896395115], + [231346.03587821542, 3969827.469136938, 51.84385903995114], + [231343.73097238384, 3969831.6164822197, 51.57206910739105], + [231343.73097238384, 3969831.6164822197, 51.610169183391044], + [231343.78080942994, 3969831.606852569, 51.57108681418512], + [231343.78080942994, 3969831.606852569, 51.609186890185114], + [231347.95500716282, 3969827.1247907947, 51.76848559067164], + [231347.95500716282, 3969827.1247907947, 51.80658566667163], + [231346.69216858927, 3969831.059649846, 51.52836998096813], + [231346.69216858927, 3969831.059649846, 51.566470056968136], + [231348.5879481345, 3969830.7194932476, 51.5005963864009], + [231348.5879481345, 3969830.7194932476, 51.538696462400914], + [231352.8619250283, 3969826.302690928, 51.6733730108201], + [231352.88625431352, 3969826.298822975, 51.67290207395222], + [231352.8619250283, 3969826.302690928, 51.7114730868201], + [231352.88625431352, 3969826.298822975, 51.71100214995222], + [231353.43516516592, 3969829.9073955966, 51.4297249304896], + [231353.45919844485, 3969829.903574703, 51.42937402021529], + [231353.43516516592, 3969829.9073955966, 51.46782500648959], + [231353.45919844485, 3969829.903574703, 51.46747409621529], + [231357.8305820777, 3969825.5551535166, 51.57731855723279], + [231357.8305820777, 3969825.5551535166, 51.61541863323281], + [231359.7130768859, 3969825.294112915, 51.54098705768906], + [231359.7130768859, 3969825.294112915, 51.579087133689065], + [231358.3433702212, 3969829.1689532236, 51.35815165402976], + [231358.3433702212, 3969829.1689532236, 51.39625173002977], + [231362.78661706272, 3969824.8939889916, 51.481735040513385], + [231362.78661706272, 3969824.8939889916, 51.5198351165134], + [231360.20296134258, 3969828.9110886157, 51.3310798800107], + [231360.20296134258, 3969828.9110886157, 51.36917995601071], + [231366.58568322717, 3969824.443940307, 51.40860110455801], + [231366.58568322717, 3969824.443940307, 51.44670118055802], + [231363.23910678053, 3969828.515832867, 51.28692928784427], + [231363.23910678053, 3969828.515832867, 51.32502936384429], + [231367.75298262408, 3969824.3155130525, 51.38615152379398], + [231367.75298262408, 3969824.3155130525, 51.42425159979397], + [231366.99195097337, 3969828.071259775, 51.232434829531854], + [231366.99195097337, 3969828.071259775, 51.27053490553187], + [231368.14504822757, 3969827.9443950504, 51.21570692165858], + [231368.14504822757, 3969827.9443950504, 51.25380699765858], + [231372.7282992477, 3969823.8198863817, 51.29056800707455], + [231372.7282992477, 3969823.8198863817, 51.328668083074554], + [231373.47608205935, 3969823.752626111, 51.276215151426975], + [231373.47608205935, 3969823.752626111, 51.31431522742697], + [231373.05983183227, 3969827.4547985056, 51.14448455547303], + [231373.05983183227, 3969827.4547985056, 51.18258463147302], + [231373.79851661975, 3969827.3883565674, 51.1337897790531], + [231373.79851661975, 3969827.3883565674, 51.171889855053095], + [231377.7111849332, 3969823.4072466516, 51.19498449035515], + [231377.7111849332, 3969823.4072466516, 51.23308456635514], + [231380.38060190907, 3969823.220538685, 51.143829198295926], + [231380.38060190907, 3969823.220538685, 51.18192927429592], + [231377.9820924086, 3969827.0471792254, 51.07326218928752], + [231377.9820924086, 3969827.0471792254, 51.111362265287525], + [231382.7002555777, 3969823.077708482, 51.09940097363573], + [231382.7002555777, 3969823.077708482, 51.13750104963573], + [231380.61903147798, 3969826.862742872, 51.03514472857434], + [231380.61903147798, 3969826.862742872, 51.073244804574344], + [231382.91046269366, 3969826.7216504365, 51.00203982310191], + [231382.91046269366, 3969826.7216504365, 51.040139899101916], + [231387.29556377884, 3969822.847961545, 51.01144324516488], + [231387.29556377884, 3969822.847961545, 51.04954332116488], + [231387.6941253603, 3969822.8313634074, 51.00381745691726], + [231387.6941253603, 3969822.8313634074, 51.041917532917275], + [231387.44986131164, 3969826.494698755, 50.936499678095664], + [231387.44986131164, 3969826.494698755, 50.97459975409567], + [231387.84357372724, 3969826.47830256, 50.93081745691726], + [231387.84357372724, 3969826.47830256, 50.96891753291726], + [231392.6914071272, 3969822.6682798564, 50.908233940196894], + [231392.6914071272, 3969822.6682798564, 50.94633401619691], + [231394.2172831071, 3969822.635093217, 50.87905729203383], + [231394.2172831071, 3969822.635093217, 50.917157368033834], + [231392.78005523258, 3969826.317203193, 50.8352339401969], + [231392.78005523258, 3969826.317203193, 50.8733340161969], + [231394.28736638805, 3969826.2844203236, 50.80605729203384], + [231394.28736638805, 3969826.2844203236, 50.84415736803383], + [231397.69071277653, 3969822.58850313, 50.812650423477486], + [231397.69071277653, 3969822.58850313, 50.85075049947748], + [231397.7185359965, 3969826.238397083, 50.739650423477485], + [231397.7185359965, 3969826.238397083, 50.777750499477484], + [231401.1420717323, 3969822.582047123, 50.746671338902765], + [231401.1420717323, 3969822.582047123, 50.78477141490276], + [231402.6906760379, 3969822.588058432, 50.71706690675807], + [231402.6906760379, 3969822.588058432, 50.75516698275806], + [231401.12790341835, 3969826.2320196237, 50.67367133890276], + [231401.12790341835, 3969826.2320196237, 50.71177141490277], + [231402.67650772393, 3969826.238030933, 50.644066906758056], + [231402.67650772393, 3969826.238030933, 50.68216698275806], + [231407.6906383682, 3969822.607467081, 50.621483390038655], + [231407.6906383682, 3969822.607467081, 50.659583466038654], + [231407.67647005426, 3969826.2574395817, 50.54848339003865], + [231407.67647005426, 3969826.2574395817, 50.586583466038654], + [231412.69060069844, 3969822.62687573, 50.52589987331923], + [231412.69060069844, 3969822.62687573, 50.56399994931923], + [231412.6764323845, 3969826.2768482324, 50.45289987331924], + [231412.6764323845, 3969826.2768482324, 50.49099994931923], + [231417.69056302874, 3969822.64628438, 50.43031635659981], + [231417.69056302874, 3969822.64628438, 50.46841643259982], + [231417.67639471486, 3969826.296256881, 50.35731635659981], + [231417.67639471486, 3969826.296256881, 50.395416432599816], + [231422.69052535907, 3969822.6656930293, 50.3347328398804], + [231422.69052535907, 3969822.6656930293, 50.37283291588041], + [231422.6763570451, 3969826.3156655305, 50.26173283988041], + [231422.6763570451, 3969826.3156655305, 50.29983291588041], + [231427.69048768937, 3969822.6851016777, 50.239149323160994], + [231427.69048768937, 3969822.6851016777, 50.277249399160986], + [231427.67631937537, 3969826.3350741793, 50.16614932316099], + [231427.67631937537, 3969826.3350741793, 50.204249399160986], + [231432.6904500196, 3969822.7045103274, 50.14356580644158], + [231432.6904500196, 3969822.7045103274, 50.181665882441564], + [231432.67628170567, 3969826.3544828286, 50.070565806441564], + [231432.67628170567, 3969826.3544828286, 50.10866588244157], + [231437.6904123499, 3969822.7239189767, 50.04798228972217], + [231437.6904123499, 3969822.7239189767, 50.086082365722156], + [231437.67624403597, 3969826.373891478, 49.974982289722156], + [231437.67624403597, 3969826.373891478, 50.01308236572216], + [231442.69037468018, 3969822.743327626, 49.95239877300274], + [231442.69037468018, 3969822.743327626, 49.99049884900275], + [231442.67620636628, 3969826.393300127, 49.87939877300275], + [231442.67620636628, 3969826.393300127, 49.91749884900274], + [231447.69033701048, 3969822.762736275, 49.856815256283326], + [231447.69033701048, 3969822.762736275, 49.894915332283325], + [231447.67616869655, 3969826.412708776, 49.78381525628332], + [231447.67616869655, 3969826.412708776, 49.82191533228332], + [231452.69029934084, 3969822.7821449237, 49.76123173956391], + [231452.69029934084, 3969822.7821449237, 49.79933181556391], + [231452.67613102685, 3969826.432117426, 49.688231739563925], + [231452.67613102685, 3969826.432117426, 49.72633181556391], + [231457.6902616711, 3969822.801553574, 49.66564822284449], + [231457.6902616711, 3969822.801553574, 49.7037482988445], + [231457.67609335715, 3969826.451526075, 49.592648222844495], + [231457.67609335715, 3969826.451526075, 49.63074829884449], + [231462.69022400136, 3969822.820962223, 49.57006470612508], + [231462.69022400136, 3969822.820962223, 49.60816478212507], + [231462.67605568745, 3969826.470934724, 49.49706470612508], + [231462.67605568745, 3969826.470934724, 49.53516478212508], + [231467.69018633166, 3969822.840370872, 49.47448118940567], + [231467.69018633166, 3969822.840370872, 49.51258126540567], + [231467.67601801772, 3969826.4903433733, 49.401481189405665], + [231467.67601801772, 3969826.4903433733, 49.439581265405664], + [231472.69014866196, 3969822.8597795214, 49.37889767268625], + [231472.69014866196, 3969822.8597795214, 49.41699774868624], + [231472.67598034802, 3969826.5097520235, 49.30589767268624], + [231472.67598034802, 3969826.5097520235, 49.343997748686256], + [231477.69011099226, 3969822.8791881707, 49.283314155966835], + [231477.69011099226, 3969822.8791881707, 49.321414231966834], + [231477.67594267832, 3969826.5291606723, 49.210314155966834], + [231477.67594267832, 3969826.5291606723, 49.24841423196683], + [231482.69007332253, 3969822.8985968204, 49.18773063924743], + [231482.69007332253, 3969822.8985968204, 49.22583071524742], + [231482.67590500863, 3969826.5485693216, 49.114730639247426], + [231482.67590500863, 3969826.5485693216, 49.15283071524742], + [231487.69003565283, 3969822.918005469, 49.092147122528], + [231487.69003565283, 3969822.918005469, 49.13024719852801], + [231487.67586733887, 3969826.5679779705, 49.019147122528004], + [231487.67586733887, 3969826.5679779705, 49.057247198528], + [231492.68999798314, 3969822.9374141186, 48.99656360580859], + [231492.68999798314, 3969822.9374141186, 49.03466368180858], + [231492.6758296692, 3969826.587386619, 48.92356360580859], + [231492.6758296692, 3969826.587386619, 48.96166368180859], + [231497.68996031344, 3969822.956822768, 48.90098008908918], + [231497.68996031344, 3969822.956822768, 48.93908016508918], + [231497.6757919995, 3969826.606795269, 48.82798008908918], + [231497.6757919995, 3969826.606795269, 48.86608016508917], + [231502.68992264368, 3969822.9762314167, 48.80539657236976], + [231502.68992264368, 3969822.9762314167, 48.84349664836976], + [231502.6757543298, 3969826.626203918, 48.73239657236975], + [231502.6757543298, 3969826.626203918, 48.77049664836976], + [231507.689884974, 3969822.995640066, 48.709813055650336], + [231507.689884974, 3969822.995640066, 48.74791313165035], + [231507.67571666007, 3969826.645612567, 48.63681305565034], + [231507.67571666007, 3969826.645612567, 48.674913131650335], + [231512.6898473043, 3969823.015048715, 48.61422953893093], + [231512.6898473043, 3969823.015048715, 48.65232961493093], + [231512.67567899037, 3969826.665021217, 48.541229538930935], + [231512.67567899037, 3969826.665021217, 48.579329614930934], + [231517.68980963455, 3969823.0344573655, 48.518646022211506], + [231517.68980963455, 3969823.0344573655, 48.55674609821151], + [231517.67564132062, 3969826.6844298663, 48.44564602221151], + [231517.67564132062, 3969826.6844298663, 48.48374609821151], + [231522.68977196486, 3969823.0538660144, 48.4230625054921], + [231522.68977196486, 3969823.0538660144, 48.46116258149209], + [231522.67560365092, 3969826.7038385156, 48.35006250549209], + [231522.67560365092, 3969826.7038385156, 48.388162581492104], + [231527.68973429519, 3969823.0732746636, 48.32747898877268], + [231527.68973429519, 3969823.0732746636, 48.365579064772696], + [231527.67556598125, 3969826.7232471644, 48.25447898877268], + [231527.67556598125, 3969826.7232471644, 48.29257906477268], + [231532.68969662543, 3969823.0926833125, 48.231895472053274], + [231532.68969662543, 3969823.0926833125, 48.26999554805326], + [231532.6755283115, 3969826.7426558146, 48.15889547205326], + [231532.6755283115, 3969826.7426558146, 48.196995548053266], + [231537.6896589558, 3969823.1120919613, 48.136311955333845], + [231537.6896589558, 3969823.1120919613, 48.17441203133386], + [231537.6754906418, 3969826.7620644625, 48.06331195533385], + [231537.6754906418, 3969826.7620644625, 48.101412031333844], + [231542.68962128603, 3969823.131500611, 48.040728438614444], + [231542.68962128603, 3969823.131500611, 48.078828514614436], + [231542.6754529721, 3969826.781473112, 47.96772843861444], + [231542.6754529721, 3969826.781473112, 48.00582851461445], + [231547.6895836163, 3969823.15090926, 47.945144921895015], + [231547.6895836163, 3969823.15090926, 47.983244997895014], + [231547.6754153024, 3969826.8008817616, 47.87214492189503], + [231547.6754153024, 3969826.8008817616, 47.91024499789501], + [231552.6895459466, 3969823.170317909, 47.849561405175606], + [231552.6895459466, 3969823.170317909, 47.887661481175606], + [231552.67537763267, 3969826.82029041, 47.7765614051756], + [231552.67537763267, 3969826.82029041, 47.81466148117561], + [231557.6895082769, 3969823.189726559, 47.753977888456184], + [231557.6895082769, 3969823.189726559, 47.79207796445618], + [231557.67533996297, 3969826.83969906, 47.68097788845619], + [231557.67533996297, 3969826.83969906, 47.71907796445618], + [231562.6894706072, 3969823.2091352083, 47.65839437173678], + [231562.6894706072, 3969823.2091352083, 47.69649444773677], + [231564.38078293134, 3969823.2157004746, 47.626061812182925], + [231564.38078293134, 3969823.2157004746, 47.66416188818293], + [231562.67530229327, 3969826.859107709, 47.58539437173677], + [231562.67530229327, 3969826.859107709, 47.623494447736775], + [231564.3666146174, 3969826.8656729762, 47.553061812182925], + [231564.3666146174, 3969826.8656729762, 47.59116188818293], + [231567.68943293748, 3969823.228543857, 47.56307587684072], + [231567.68943293748, 3969823.228543857, 47.60117595284071], + [231567.67526462357, 3969826.8785163583, 47.490075876840706], + [231567.67526462357, 3969826.8785163583, 47.52817595284071], + [231572.68939526778, 3969823.2479525064, 47.468898571177455], + [231572.68939526778, 3969823.2479525064, 47.50699864717744], + [231572.6752269539, 3969826.8979250076, 47.39589857117744], + [231572.6752269539, 3969826.8979250076, 47.43399864717745], + [231577.68935759808, 3969823.2673611557, 47.37593170599522], + [231577.68935759808, 3969823.2673611557, 47.41403178199523], + [231577.67518928414, 3969826.9173336574, 47.30293170599522], + [231577.67518928414, 3969826.9173336574, 47.34103178199522], + [231582.68931992838, 3969823.2867698045, 47.28417528129403], + [231582.68931992838, 3969823.2867698045, 47.32227535729403], + [231582.67515161444, 3969826.9367423067, 47.21117528129404], + [231582.67515161444, 3969826.9367423067, 47.24927535729403], + [231587.68928225865, 3969823.306178454, 47.19362929707389], + [231587.68928225865, 3969823.306178454, 47.2317293730739], + [231590.61858138186, 3969823.3175492873, 47.141290796769226], + [231590.61858138186, 3969823.3175492873, 47.17939087276923], + [231587.67511394474, 3969826.9561509555, 47.12062929707389], + [231587.67511394474, 3969826.9561509555, 47.15872937307389], + [231590.60441306792, 3969826.9675217886, 47.068290796769745], + [231590.60441306792, 3969826.9675217886, 47.10639087276975], + [231633.21530417824, 3969823.482899504, 46.424927481722136], + [231632.6865449353, 3969824.0986937117, 46.42082841935846], + [231633.21530417824, 3969823.482899504, 46.46302755772213], + [231632.6865449353, 3969824.0986937117, 46.45892849535845], + [231630.09157510012, 3969827.120801439, 46.40133698741877], + [231630.09157510012, 3969827.120801439, 46.43943706341877], + [231675.81202697562, 3969823.6482497198, 45.796593058056665], + [231675.81202697562, 3969823.6482497198, 45.834693134056664], + [231677.6886042039, 3969823.6555341403, 45.770786903369334], + [231677.6886042039, 3969823.6555341403, 45.808886979369326], + [231675.79785866168, 3969827.298222221, 45.72359305805681], + [231675.79785866168, 3969827.298222221, 45.76169313405681], + [231677.67443588996, 3969827.3055066415, 45.69778690336933], + [231677.67443588996, 3969827.3055066415, 45.73588697936933], + [231682.6885665342, 3969823.6749427896, 45.70323928828896], + [231682.6885665342, 3969823.6749427896, 45.74133936428896], + [231682.67439822032, 3969827.324915291, 45.630239288288976], + [231682.67439822032, 3969827.324915291, 45.66833936428897], + [231687.6885288645, 3969823.69435144, 45.63690211368964], + [231687.6885288645, 3969823.69435144, 45.675002189689636], + [231687.67436055056, 3969827.3443239406, 45.56390211368965], + [231687.67436055056, 3969827.3443239406, 45.602002189689635], + [231692.68849119483, 3969823.7137600887, 45.571775379571356], + [231692.68849119483, 3969823.7137600887, 45.60987545557136], + [231692.67432288086, 3969827.36373259, 45.498775379571356], + [231692.67432288086, 3969827.36373259, 45.536875455571355], + [231697.68845352507, 3969823.733168738, 45.507859085934115], + [231697.68845352507, 3969823.733168738, 45.54595916193413], + [231697.67428521113, 3969827.3831412387, 45.43485908593412], + [231697.67428521113, 3969827.3831412387, 45.472959161934114], + [231702.68841585537, 3969823.752577387, 45.44515323277791], + [231702.68841585537, 3969823.752577387, 45.48325330877792], + [231702.67424754144, 3969827.402549889, 45.37215323277792], + [231702.67424754144, 3969827.402549889, 45.41025330877792], + [231707.68837818567, 3969823.771986036, 45.38365782010277], + [231707.68837818567, 3969823.771986036, 45.421757896102754], + [231707.67420987174, 3969827.4219585373, 45.310657820102755], + [231707.67420987174, 3969827.4219585373, 45.34875789610276], + [231712.688340516, 3969823.7913946854, 45.323372847908644], + [231712.688340516, 3969823.7913946854, 45.361472923908636], + [231712.67417220204, 3969827.441367187, 45.250372847908636], + [231712.67417220204, 3969827.441367187, 45.28847292390865], + [231717.68830284625, 3969823.810803334, 45.26429831619556], + [231717.68830284625, 3969823.810803334, 45.302398392195556], + [231717.67413453228, 3969827.4607758354, 45.19129831619557], + [231717.67413453228, 3969827.4607758354, 45.22939839219556], + [231722.68826517655, 3969823.8302119835, 45.20643422496353], + [231722.68826517655, 3969823.8302119835, 45.24453430096352], + [231722.6740968626, 3969827.480184485, 45.13343422496352], + [231722.6740968626, 3969827.480184485, 45.17153430096353], + [231727.68822750685, 3969823.8496206333, 45.14978057421254], + [231727.68822750685, 3969823.8496206333, 45.18788065021253], + [231727.6740591929, 3969827.4995931336, 45.07678057421253], + [231727.6740591929, 3969827.4995931336, 45.114880650212534], + [231732.68818983712, 3969823.8690292826, 45.09433736394257], + [231732.68818983712, 3969823.8690292826, 45.13243743994258], + [231732.67402152315, 3969827.5190017833, 45.02133736394258], + [231732.67402152315, 3969827.5190017833, 45.05943743994257], + [231737.68815216742, 3969823.8884379314, 45.040104594153654], + [231737.68815216742, 3969823.8884379314, 45.07820467015365], + [231737.67398385346, 3969827.5384104326, 44.96710459415366], + [231737.67398385346, 3969827.5384104326, 45.00520467015366], + [231742.68811449772, 3969823.9078465807, 44.98708226484579], + [231742.68811449772, 3969823.9078465807, 45.02518234084579], + [231742.6739461838, 3969827.557819082, 44.91408226484579], + [231742.6739461838, 3969827.557819082, 44.95218234084578], + [231747.68807682797, 3969823.927255231, 44.935270376018956], + [231747.68807682797, 3969823.927255231, 44.973370452018955], + [231747.67390851403, 3969827.5772277317, 44.86227037601895], + [231747.67390851403, 3969827.5772277317, 44.900370452018954], + [231752.68803915827, 3969823.94666388, 44.88466892767317], + [231752.68803915827, 3969823.94666388, 44.92276900367316], + [231752.67387084433, 3969827.596636381, 44.81166892767317], + [231752.67387084433, 3969827.596636381, 44.84976900367317], + [231757.6880014886, 3969823.966072529, 44.83527791980842], + [231757.6880014886, 3969823.966072529, 44.87337799580842], + [231757.67383317463, 3969827.61604503, 44.76227791980842], + [231757.67383317463, 3969827.61604503, 44.80037799580841], + [231762.68796381884, 3969823.985481178, 44.7870973524247], + [231762.68796381884, 3969823.985481178, 44.82519742842471], + [231762.6737955049, 3969827.635453679, 44.71409735242471], + [231762.6737955049, 3969827.635453679, 44.75219742842471], + [231767.68792614914, 3969824.004889827, 44.74012722552204], + [231767.68792614914, 3969824.004889827, 44.77822730152203], + [231767.67375783526, 3969827.6548623284, 44.667127225522044], + [231767.67375783526, 3969827.6548623284, 44.70522730152203], + [231772.68788847944, 3969824.0242984765, 44.69436753910041], + [231772.68788847944, 3969824.0242984765, 44.732467615100404], + [231772.6737201655, 3969827.6742709773, 44.62136753910041], + [231772.6737201655, 3969827.6742709773, 44.65946761510041], + [231777.68785080977, 3969824.0437071254, 44.64981829315983], + [231777.68785080977, 3969824.0437071254, 44.687918369159824], + [231777.6736824958, 3969827.6936796266, 44.57681829315982], + [231777.6736824958, 3969827.6936796266, 44.614918369159824], + [231782.68781314002, 3969824.0631157747, 44.60647948770028], + [231782.68781314002, 3969824.0631157747, 44.644579563700276], + [231782.67364482608, 3969827.7130882763, 44.533479487700276], + [231782.67364482608, 3969827.7130882763, 44.57157956370029], + [231787.68777547032, 3969824.082524424, 44.56435112272177], + [231787.68777547032, 3969824.082524424, 44.60245119872178], + [231787.67360715638, 3969827.7324969256, 44.49135112272177], + [231787.67360715638, 3969827.7324969256, 44.529451198721766], + [231792.68773780062, 3969824.1019330737, 44.52343319822431], + [231792.68773780062, 3969824.1019330737, 44.56153327422431], + [231792.67356948668, 3969827.751905575, 44.45043319822431], + [231792.67356948668, 3969827.751905575, 44.4885332742243], + [231797.68770013095, 3969824.121341723, 44.483725714207885], + [231797.68770013095, 3969824.121341723, 44.521825790207885], + [231797.67353181698, 3969827.7713142238, 44.4107257142079], + [231797.67353181698, 3969827.7713142238, 44.448825790207884], + [231802.68766246125, 3969824.140750372, 44.44522867067251], + [231802.68766246125, 3969824.140750372, 44.4833287466725], + [231802.67349414725, 3969827.790722873, 44.3722286706725], + [231802.67349414725, 3969827.790722873, 44.410328746672505], + [231807.6876247915, 3969824.160159021, 44.40794206761816], + [231807.6876247915, 3969824.160159021, 44.44604214361816], + [231807.67345647755, 3969827.810131522, 44.33494206761817], + [231807.67345647755, 3969827.810131522, 44.37304214361816], + [231812.6875871218, 3969824.17956767, 44.37186590504487], + [231812.6875871218, 3969824.17956767, 44.40996598104487], + [231812.67341880786, 3969827.829540171, 44.29886590504486], + [231812.67341880786, 3969827.829540171, 44.33696598104487], + [231817.68754945206, 3969824.1989763193, 44.337000182952615], + [231817.68754945206, 3969824.1989763193, 44.3751002589526], + [231817.67338113816, 3969827.8489488205, 44.2640001829526], + [231817.67338113816, 3969827.8489488205, 44.302100258952606], + [231822.68751178237, 3969824.2183849686, 44.30334490134138], + [231822.68751178237, 3969824.2183849686, 44.34144497734138], + [231822.6733434684, 3969827.8683574703, 44.2303449013414], + [231822.6733434684, 3969827.8683574703, 44.26844497734138], + [231827.68747411267, 3969824.2377936174, 44.27090006021121], + [231827.68747411267, 3969824.2377936174, 44.30900013621121], + [231827.67330579873, 3969827.8877661196, 44.19790006021122], + [231827.67330579873, 3969827.8877661196, 44.23600013621122], + [231832.68743644297, 3969824.2572022676, 44.23966565956208], + [231832.68743644297, 3969824.2572022676, 44.27776573556207], + [231832.67326812903, 3969827.9071747684, 44.16666565956208], + [231832.67326812903, 3969827.9071747684, 44.20476573556207], + [231837.6873987732, 3969824.2766109165, 44.209641699393984], + [231837.6873987732, 3969824.2766109165, 44.247741775393976], + [231837.67323045927, 3969827.9265834177, 44.136641699393984], + [231837.67323045927, 3969827.9265834177, 44.17474177539398], + [231842.68736110354, 3969824.296019566, 44.180828179706936], + [231842.68736110354, 3969824.296019566, 44.21892825570693], + [231842.67319278957, 3969827.9459920665, 44.10782817970692], + [231842.67319278957, 3969827.9459920665, 44.14592825570692], + [231847.68732343384, 3969824.315428215, 44.15322510050091], + [231847.68732343384, 3969824.315428215, 44.19132517650092], + [231847.6731551199, 3969827.9654007168, 44.08022510050092], + [231847.6731551199, 3969827.9654007168, 44.11832517650092], + [231852.68728576408, 3969824.334836864, 44.126832461775955], + [231852.68728576408, 3969824.334836864, 44.16493253777594], + [231852.6731174502, 3969827.984809365, 44.05383246177594], + [231852.6731174502, 3969827.984809365, 44.091932537775946], + [231857.6872480944, 3969824.3542455127, 44.101650263532015], + [231857.6872480944, 3969824.3542455127, 44.139750339532014], + [231857.67307978045, 3969828.004218015, 44.02865026353201], + [231857.67307978045, 3969828.004218015, 44.066750339532014], + [231862.68721042472, 3969824.373654163, 44.07767850576912], + [231862.68721042472, 3969824.373654163, 44.115778581769135], + [231862.67304211075, 3969828.023626664, 44.00467850576912], + [231862.67304211075, 3969828.023626664, 44.04277858176912], + [231867.68717275502, 3969824.3930628123, 44.054917188487266], + [231867.68717275502, 3969824.3930628123, 44.09301726448727], + [231867.67300444108, 3969828.043035313, 43.98191718848727], + [231867.67300444108, 3969828.043035313, 44.020017264487265], + [231872.68713508526, 3969824.4124714616, 44.033366311686464], + [231872.68713508526, 3969824.4124714616, 44.07146638768647], + [231872.67296677132, 3969828.0624439623, 43.960366311686464], + [231872.67296677132, 3969828.0624439623, 43.99846638768647], + [231877.68709741556, 3969824.4318801104, 44.013025875366694], + [231877.68709741556, 3969824.4318801104, 44.05112595136669], + [231879.78155222532, 3969824.4400102794, 44.00486510881276], + [231879.78155222532, 3969824.4400102794, 44.042965184812765], + [231877.67292910168, 3969828.0818526116, 43.9400258753667], + [231877.67292910168, 3969828.0818526116, 43.97812595136669], + [231882.6870597459, 3969824.4512887597, 43.99389587952797], + [231882.6870597459, 3969824.4512887597, 44.031995955527975], + [231879.76738391138, 3969828.0899827806, 43.93186510881276], + [231879.76738391138, 3969828.0899827806, 43.969965184812764], + [231882.67289143192, 3969828.1012612614, 43.93542352658119], + [231882.67289143192, 3969828.1012612614, 43.97352360258118], + [231887.6870220762, 3969824.4706974085, 43.9759763241703], + [231887.6870220762, 3969824.4706974085, 44.01407640017029], + [231887.6728537622, 3969828.1206699107, 43.942503971223395], + [231887.6728537622, 3969828.1206699107, 43.98060404722341], + [231892.68698440643, 3969824.490106059, 43.95926720929364], + [231892.68698440643, 3969824.490106059, 43.99736728529365], + [231894.38144222982, 3969824.496683535, 43.953879203201055], + [231894.38144222982, 3969824.496683535, 43.99197927920104], + [231892.6728160925, 3969828.14007856, 43.95079485634681], + [231892.6728160925, 3969828.14007856, 43.98889493234681], + [231894.36727391588, 3969828.1466560364, 43.953879203201055], + [231894.36727391588, 3969828.1466560364, 43.99197927920104], + [231897.6869568894, 3969824.50639286, 43.94376853489804], + [231897.6869568894, 3969824.50639286, 43.98186861089804], + [231897.67968293463, 3969828.1563856127, 43.960296181951236], + [231897.67968293463, 3969828.1563856127, 43.99839625795123], + [231902.68695439264, 3969824.5092143305, 43.92948030098347], + [231902.68695439264, 3969824.5092143305, 43.96758037698347], + [231902.6901090041, 3969828.159212967, 43.971007948036636], + [231902.6901090041, 3969828.159212967, 44.00910802403662], + [231907.68693954908, 3969824.4977501007, 43.916402507549954], + [231907.68693954908, 3969824.4977501007, 43.95450258354995], + [231908.98139927528, 3969824.4924540888, 43.91321399730674], + [231908.98139927528, 3969824.4924540888, 43.95131407330675], + [231910.3813826965, 3969824.4856485515, 43.90985687133767], + [231910.3813826965, 3969824.4856485515, 43.947956947337666], + [231907.70052270102, 3969828.1477248264, 43.982930154603075], + [231907.70052270102, 3969828.1477248264, 44.02103023060307], + [231908.99768230034, 3969828.142417769, 43.98621399730685], + [231908.99768230034, 3969828.142417769, 44.024314073306854], + [231912.68687154257, 3969824.4720002664, 43.90453515459749], + [231912.68687154257, 3969824.4720002664, 43.942635230597475], + [231910.400585687, 3969828.1355980365, 43.98985687133703], + [231910.400585687, 3969828.1355980365, 44.02795694733703], + [231912.71088312403, 3969828.1219212846, 43.99606280165058], + [231912.71088312403, 3969828.1219212846, 44.03416287765059], + [231917.6867095573, 3969824.4319650354, 43.89387824212604], + [231917.6867095573, 3969824.4319650354, 43.93197831812604], + [231917.72114937234, 3969828.081802552, 44.010405889179225], + [231917.72114937234, 3969828.081802552, 44.04850596517924], + [231922.6864127783, 3969824.377644737, 43.88443177013564], + [231922.6864127783, 3969824.377644737, 43.92253184613564], + [231922.73128054582, 3969828.027368957, 44.02595941718883], + [231922.73128054582, 3969828.027368957, 44.06405949318883], + [231926.38055354578, 3969824.3283308963, 43.878229449999964], + [231926.38055354578, 3969824.3283308963, 43.91632952599996], + [231927.6859403918, 3969824.309039812, 43.87619573862628], + [231927.6859403918, 3969824.309039812, 43.91429581462628], + [231926.43312623544, 3969827.9779522615, 44.03822944999877], + [231926.43312623544, 3969827.9779522615, 44.07632952599877], + [231927.7412357454, 3969827.958620942, 44.04272338567941], + [231927.7412357454, 3969827.958620942, 44.0808234616794], + [231932.68525158515, 3969824.226150823, 43.86917014759797], + [231932.68525158515, 3969824.226150823, 43.90727022359796], + [231935.05473618413, 3969824.181873632, 43.86626298906988], + [231935.05473618413, 3969824.181873632, 43.90436306506987], + [231932.7509740736, 3969827.87555907, 44.06069779465106], + [231932.7509740736, 3969827.87555907, 44.09879787065106], + [231937.6843055479, 3969824.1289784457, 43.86335499705069], + [231937.6843055479, 3969824.1289784457, 43.901455073050684], + [231935.12540074045, 3969827.8311895295, 44.0696401282989], + [231935.12540074045, 3969827.8311895295, 44.107740204298906], + [231937.76045463458, 3969827.778184018, 44.06673213627971], + [231937.76045463458, 3969827.778184018, 44.104832212279725], + [231942.37761738684, 3969824.0247437214, 43.85899693918792], + [231942.37761738684, 3969824.0247437214, 43.89709701518792], + [231942.68306147133, 3969824.017523472, 43.85875028698446], + [231942.68306147133, 3969824.017523472, 43.89685036298445], + [231942.4635553811, 3969827.6737318896, 44.06237407841695], + [231942.4635553811, 3969827.6737318896, 44.100474154416936], + [231942.7696365347, 3969827.6664965823, 44.06212742621348], + [231942.7696365347, 3969827.6664965823, 44.100227502213485], + [231947.68147854935, 3969823.8917868137, 43.85535601739927], + [231947.68147854935, 3969823.8917868137, 43.89345609339926], + [231947.7784788826, 3969827.540497673, 44.058733156628286], + [231947.7784788826, 3969827.540497673, 44.09683323262829], + [231952.67951597858, 3969823.7517694957, 43.853172188295105], + [231952.67951597858, 3969823.7517694957, 43.89127226429511], + [231952.7869407899, 3969827.400188319, 44.056549327524145], + [231952.7869407899, 3969827.400188319, 44.09464940352413], + [231957.67713295875, 3969823.5974726626, 43.852198799671996], + [231957.67713295875, 3969823.5974726626, 43.890298875672], + [231958.3712370051, 3969823.574912402, 43.85215933890154], + [231958.3712370051, 3969823.574912402, 43.89025941490154], + [231957.79498137117, 3969827.2455696664, 44.055575938901036], + [231957.79498137117, 3969827.2455696664, 44.09367601490102], + [231958.49053312026, 3969827.222962352, 44.05553647813056], + [231958.49053312026, 3969827.222962352, 44.09363655413057], + [231962.67428869297, 3969823.4288975727, 43.85243585152993], + [231962.67428869297, 3969823.4288975727, 43.89053592752993], + [231962.80255974457, 3969827.0766429775, 44.05581299075896], + [231962.80255974457, 3969827.0766429775, 44.09391306675895], + [231967.6709423882, 3969823.246045602, 43.853883343868894], + [231967.6709423882, 3969823.246045602, 43.89198341986889], + [231967.80963503176, 3969826.89340963, 44.05726048309792], + [231967.80963503176, 3969826.89340963, 44.09536055909793], + [231972.66705325549, 3969823.0489182444, 43.85654127668891], + [231972.66705325549, 3969823.0489182444, 43.8946413526889], + [231974.36007547379, 3969822.978874542, 43.85771664914085], + [231974.36007547379, 3969822.978874542, 43.89581672514083], + [231972.81616635883, 3969826.695871121, 44.05991841591793], + [231972.81616635883, 3969826.695871121, 44.09801849191794], + [231977.6625805102, 3969822.8375171074, 43.860409649989954], + [231977.6625805102, 3969822.8375171074, 43.89850972598996], + [231974.51271973774, 3969826.625681328, 44.06109378836987], + [231974.51271973774, 3969826.625681328, 44.099193864369866], + [231977.8221128561, 3969826.484029061, 44.06378678921899], + [231977.8221128561, 3969826.484029061, 44.10188686521898], + [231981.6775772967, 3969822.6572443377, 43.86439660047098], + [231981.6775772967, 3969822.6572443377, 43.90249667647098], + [231982.6574833726, 3969822.611843919, 43.86548846377205], + [231982.6574833726, 3969822.611843919, 43.903588539772045], + [231981.84548377877, 3969826.3033802942, 44.06777373970001], + [231981.84548377877, 3969826.3033802942, 44.105873815700015], + [231982.82743365876, 3969826.2578851823, 44.063960816714015], + [231982.82743365876, 3969826.2578851823, 44.102060892714015], + [231987.65172106802, 3969822.371900519, 43.87177771803518], + [231987.65172106802, 3969822.371900519, 43.90987779403519], + [231990.34279626585, 3969822.2366799647, 43.8756688699058], + [231990.34279626585, 3969822.2366799647, 43.913768945905794], + [231987.8320879071, 3969826.0174413295, 44.04525007097714], + [231987.8320879071, 3969826.0174413295, 44.083350146977146], + [231992.64525282718, 3969822.1176888673, 43.879277412779366], + [231992.64525282718, 3969822.1176888673, 43.91737748877936], + [231990.52877591894, 3969825.8819387443, 44.035668869904626], + [231990.52877591894, 3969825.8819387443, 44.07376894590464], + [231992.83603474675, 3969825.7626994653, 44.02774976572125], + [231992.83603474675, 3969825.7626994653, 44.06584984172125], + [231997.63803788653, 3969821.8492110386, 43.88798754800458], + [231997.63803788653, 3969821.8492110386, 43.92608762400457], + [231997.83923332926, 3969825.4936616695, 44.01145990094651], + [231997.83923332926, 3969825.4936616695, 44.0495599769465], + [232002.63003548872, 3969821.566469226, 43.89790812371083], + [232002.63003548872, 3969821.566469226, 43.93600819971083], + [232002.84164281213, 3969825.210330137, 43.99638047665281], + [232002.84164281213, 3969825.210330137, 44.03448055265281], + [232006.31806336567, 3969821.3483907105, 43.90601600119643], + [232006.31806336567, 3969821.3483907105, 43.94411607719644], + [232007.62120488277, 3969821.2694657366, 43.909039139898134], + [232007.62120488277, 3969821.2694657366, 43.947139215898126], + [232007.7155003888, 3969821.2637168565, 43.90926110178639], + [232007.7155003888, 3969821.2637168565, 43.9473611777864], + [232006.53736286156, 3969824.991796773, 43.986016001195814], + [232006.53736286156, 3969824.991796773, 44.0241160771958], + [232007.84322235952, 3969824.912707183, 43.98251149283999], + [232007.84322235952, 3969824.912707183, 44.02061156883998], + [232007.93771453897, 3969824.906946313, 43.982261101786506], + [232007.93771453897, 3969824.906946313, 44.02036117778651], + [232012.61150532452, 3969820.958202994, 43.92138059656648], + [232012.61150532452, 3969820.958202994, 43.959480672566464], + [232012.84393114215, 3969824.600795235, 43.96985294950832], + [232012.84393114215, 3969824.600795235, 44.00795302550832], + [232017.60089607674, 3969820.6326835407, 43.93493249371585], + [232017.60089607674, 3969820.6326835407, 43.973032569715855], + [232017.84372833796, 3969824.2745968415, 43.95840484665774], + [232017.84372833796, 3969824.2745968415, 43.996504922657756], + [232022.28454138056, 3969820.3140810337, 43.94875804301272], + [232022.28454138056, 3969820.3140810337, 43.98685811901272], + [232022.5893382642, 3969820.2929366403, 43.94969483134627], + [232022.5893382642, 3969820.2929366403, 43.98779490734628], + [232022.53714238774, 3969823.9553298205, 43.94875804301272], + [232022.53714238774, 3969823.9553298205, 43.98685811901272], + [232022.84193927137, 3969823.934185427, 43.94816718428813], + [232022.84193927137, 3969823.934185427, 43.98626726028814], + [232027.5773503016, 3969819.946907863, 43.965667609457746], + [232027.5773503016, 3969819.946907863, 44.00376768545774], + [232027.82995130878, 3969823.588156651, 43.9391399623997], + [232027.82995130878, 3969823.588156651, 43.97724003839971], + [232032.56536233908, 3969819.6008790866, 43.98285082805024], + [232032.56536233908, 3969819.6008790866, 44.02095090405023], + [232032.8179633462, 3969823.2421278735, 43.93132318099216], + [232032.8179633462, 3969823.2421278735, 43.969423256992165], + [232036.84953653693, 3969819.303677005, 43.998575683956545], + [232036.84953653693, 3969819.303677005, 44.036675759956545], + [232037.5533743765, 3969819.2548503093, 44.001244487123785], + [232037.5533743765, 3969819.2548503093, 44.03934456312378], + [232037.10213754408, 3969822.944925793, 43.92557568395655], + [232037.10213754408, 3969822.944925793, 43.96367575995655], + [232037.80597538367, 3969822.896099097, 43.928244487123784], + [232037.80597538367, 3969822.896099097, 43.966344563123776], + [232042.5413864139, 3969818.9088215325, 44.020848586678376], + [232042.5413864139, 3969818.9088215325, 44.05894866267837], + [232042.79398742106, 3969822.5500703203, 43.94784858667836], + [232042.79398742106, 3969822.5500703203, 43.98594866267837], + [232047.52939845138, 3969818.562792756, 44.041663126713985], + [232047.52939845138, 3969818.562792756, 44.07976320271399], + [232047.7819994585, 3969822.204041543, 43.96866312671399], + [232047.7819994585, 3969822.204041543, 44.006763202713984], + [232052.51741048877, 3969818.216763979, 44.06368810723066], + [232052.51741048877, 3969818.216763979, 44.10178818323067], + [232052.77001149594, 3969821.8580127656, 43.99068810723065], + [232052.77001149594, 3969821.8580127656, 44.02878818323065], + [232057.5054225262, 3969817.8707352015, 44.08692352822836], + [232057.5054225262, 3969817.8707352015, 44.12502360422836], + [232057.75802353336, 3969821.5119839893, 44.01392352822837], + [232057.75802353336, 3969821.5119839893, 44.05202360422836], + [232062.49343456366, 3969817.5247064247, 44.11136938970711], + [232062.49343456366, 3969817.5247064247, 44.149469465707114], + [232062.74603557083, 3969821.165955212, 44.038369389707114], + [232062.74603557083, 3969821.165955212, 44.07646946570711], + [232067.48144660107, 3969817.1786776483, 44.1370256916669], + [232067.48144660107, 3969817.1786776483, 44.175125767666906], + [232067.73404760825, 3969820.819926435, 44.0640256916669], + [232067.73404760825, 3969820.819926435, 44.1021257676669], + [232072.46945863854, 3969816.832648871, 44.16389243410773], + [232072.46945863854, 3969816.832648871, 44.20199251010773], + [232072.72205964566, 3969820.4738976588, 44.090892434107744], + [232072.72205964566, 3969820.4738976588, 44.12899251010773], + [232077.45747067596, 3969816.4866200946, 44.1919696170296], + [232077.45747067596, 3969816.4866200946, 44.23006969302961], + [232077.71007168313, 3969820.1278688814, 44.118969617029606], + [232077.71007168313, 3969820.1278688814, 44.1570696930296], + [232082.44548271337, 3969816.1405913173, 44.22125724043253], + [232082.44548271337, 3969816.1405913173, 44.259357316432514], + [232082.69808372055, 3969819.781840105, 44.148257240432514], + [232082.69808372055, 3969819.781840105, 44.18635731643252], + [232087.43349475085, 3969815.7945625405, 44.25175530431648], + [232087.43349475085, 3969815.7945625405, 44.28985538031647], + [232087.68609575796, 3969819.4358113282, 44.17875530431647], + [232087.68609575796, 3969819.4358113282, 44.216855380316474], + [232092.42150678826, 3969815.448533763, 44.28346380868147], + [232092.42150678826, 3969815.448533763, 44.32156388468146], + [232092.6741077954, 3969819.089782551, 44.21046380868146], + [232092.6741077954, 3969819.089782551, 44.248563884681474], + [232097.40951882568, 3969815.102504987, 44.31638275352751], + [232097.40951882568, 3969815.102504987, 44.3544828295275], + [232099.09678878385, 3969814.985455558, 44.327792056924444], + [232099.09678878385, 3969814.985455558, 44.36589213292445], + [232097.66211983282, 3969818.7437537746, 44.2433827535275], + [232097.66211983282, 3969818.7437537746, 44.281482829527505], + [232102.39753086315, 3969814.7564762104, 44.3502471170312], + [232102.39753086315, 3969814.7564762104, 44.388347193031215], + [232099.34938979102, 3969818.626704345, 44.25479205692446], + [232099.34938979102, 3969818.626704345, 44.29289213292445], + [232102.6501318703, 3969818.3977249963, 44.2772471170312], + [232102.6501318703, 3969818.3977249963, 44.3153471930312], + [232107.38554290053, 3969814.410447432, 44.38418073178317], + [232107.38554290053, 3969814.410447432, 44.422280807783174], + [232107.6381439077, 3969818.05169622, 44.311180731783175], + [232107.6381439077, 3969818.05169622, 44.349280807783174], + [232112.373554938, 3969814.0644186554, 44.418114346535134], + [232112.373554938, 3969814.0644186554, 44.45621442253513], + [232112.62615594512, 3969817.705667443, 44.34511434653515], + [232112.62615594512, 3969817.705667443, 44.38321442253513], + [232117.36156697542, 3969813.718389879, 44.45204796128711], + [232117.36156697542, 3969813.718389879, 44.490148037287106], + [232117.6141679826, 3969817.3596386667, 44.379047961287114], + [232117.6141679826, 3969817.3596386667, 44.417148037287106], + [232122.34957901284, 3969813.3723611026, 44.48598157603907], + [232122.34957901284, 3969813.3723611026, 44.52408165203908], + [232122.60218002, 3969817.0136098894, 44.41298157603907], + [232122.60218002, 3969817.0136098894, 44.45108165203908], + [232127.3375910503, 3969813.0263323253, 44.51991519079105], + [232127.3375910503, 3969813.0263323253, 44.55801526679104], + [232127.59019205743, 3969816.667581113, 44.44691519079104], + [232127.59019205743, 3969816.667581113, 44.485015266791045], + [232131.43967678156, 3969812.7417621, 44.54782181889087], + [232131.43967678156, 3969812.7417621, 44.585921894890866], + [232132.32560308767, 3969812.680303548, 44.5538618857791], + [232132.32560308767, 3969812.680303548, 44.591961961779106], + [232131.6922777887, 3969816.3830108875, 44.47482181889088], + [232131.6922777887, 3969816.3830108875, 44.51292189489087], + [232132.5782040948, 3969816.3215523358, 44.480861885779106], + [232132.5782040948, 3969816.3215523358, 44.5189619617791], + [232137.31361512514, 3969812.334274771, 44.588357435269955], + [232137.31361512514, 3969812.334274771, 44.626457511269955], + [232137.5662161323, 3969815.975523559, 44.515357435269955], + [232137.5662161323, 3969815.975523559, 44.55345751126995], + [232142.3016271626, 3969811.988245995, 44.62368227273833], + [232142.3016271626, 3969811.988245995, 44.66178234873831], + [232142.55422816973, 3969815.6294947816, 44.550682272738314], + [232142.55422816973, 3969815.6294947816, 44.58878234873832], + [232147.2896392, 3969811.6422172175, 44.6598363981842], + [232147.2896392, 3969811.6422172175, 44.697936474184196], + [232147.54224020717, 3969815.283466005, 44.58683639818419], + [232147.54224020717, 3969815.283466005, 44.624936474184196], + [232152.27765123744, 3969811.296188441, 44.69681981160758], + [232152.27765123744, 3969811.296188441, 44.734919887607575], + [232152.53025224459, 3969814.937437228, 44.62381981160758], + [232152.53025224459, 3969814.937437228, 44.661919887607574], + [232157.26566327483, 3969810.9501596643, 44.73463251300848], + [232157.26566327483, 3969810.9501596643, 44.772732589008484], + [232157.518264282, 3969814.591408452, 44.661632513008485], + [232157.518264282, 3969814.591408452, 44.699732589008484], + [232162.2536753123, 3969810.604130888, 44.773274502386904], + [232162.2536753123, 3969810.604130888, 44.811374578386896], + [232162.50627631947, 3969814.245379674, 44.7002745023869], + [232162.50627631947, 3969814.245379674, 44.7383745783869], + [232167.2416873497, 3969810.2581021097, 44.81274577974284], + [232167.2416873497, 3969810.2581021097, 44.850845855742826], + [232167.49428835683, 3969813.8993508974, 44.73974577974283], + [232167.49428835683, 3969813.8993508974, 44.77784585574283], + [232172.22969938713, 3969809.9120733333, 44.85304634507627], + [232172.22969938713, 3969809.9120733333, 44.89114642107627], + [232172.4823003943, 3969813.553322121, 44.78004634507627], + [232172.4823003943, 3969813.553322121, 44.818146421076264], + [232177.2177114246, 3969809.566044556, 44.89417619838723], + [232177.2177114246, 3969809.566044556, 44.93227627438722], + [232177.47031243177, 3969813.207293343, 44.82117619838722], + [232177.47031243177, 3969813.207293343, 44.859276274387234], + [232182.20572346202, 3969809.2200157787, 44.936135339675694], + [232182.20572346202, 3969809.2200157787, 44.9742354156757], + [232182.45832446916, 3969812.861264567, 44.863135339675694], + [232182.45832446916, 3969812.861264567, 44.9012354156757], + [232187.19373549943, 3969808.8739870028, 44.97892376894169], + [232187.19373549943, 3969808.8739870028, 45.017023844941676], + [232187.44633650657, 3969812.5152357896, 44.905923768941676], + [232187.44633650657, 3969812.5152357896, 44.94402384494168], + [232192.18174753687, 3969808.5279582255, 45.02254148618517], + [232192.18174753687, 3969808.5279582255, 45.060641562185175], + [232192.434348544, 3969812.169207013, 44.94954148618517], + [232192.434348544, 3969812.169207013, 44.98764156218517], + [232197.1697595743, 3969808.181929449, 45.06698849140619], + [232197.1697595743, 3969808.181929449, 45.105088567406185], + [232197.42236058146, 3969811.823178236, 44.99398849140619], + [232197.42236058146, 3969811.823178236, 45.03208856740619], + [232202.1577716117, 3969807.8359006722, 45.11226478460471], + [232202.1577716117, 3969807.8359006722, 45.150364860604704], + [232202.41037261888, 3969811.477149459, 45.03926478460471], + [232202.41037261888, 3969811.477149459, 45.07736486060471], + [232207.14578364918, 3969807.489871895, 45.15837036578075], + [232207.14578364918, 3969807.489871895, 45.19647044178074], + [232207.3983846563, 3969811.1311206827, 45.085370365780754], + [232207.3983846563, 3969811.1311206827, 45.12347044178074], + [232212.1337956866, 3969807.1438431176, 45.20530523493429], + [232212.1337956866, 3969807.1438431176, 45.2434053109343], + [232212.38639669376, 3969810.7850919054, 45.13230523493431], + [232212.38639669376, 3969810.7850919054, 45.17040531093429], + [232217.121807724, 3969806.7978143413, 45.25306939206536], + [232217.121807724, 3969806.7978143413, 45.29116946806536], + [232217.37440873115, 3969810.439063128, 45.180069392065356], + [232217.37440873115, 3969810.439063128, 45.21816946806536], + [232222.10981976148, 3969806.451785564, 45.30166283717394], + [232222.10981976148, 3969806.451785564, 45.33976291317394], + [232222.3624207686, 3969810.0930343517, 45.228662837173935], + [232222.3624207686, 3969810.0930343517, 45.26676291317395], + [232227.09783179886, 3969806.105756787, 45.35108557026003], + [232227.09783179886, 3969806.105756787, 45.38918564626003], + [232227.35043280604, 3969809.7470055744, 45.27808557026003], + [232227.35043280604, 3969809.7470055744, 45.316185646260024], + [232232.0858438363, 3969805.7597280107, 45.401337591323625], + [232232.0858438363, 3969805.7597280107, 45.43943766732363], + [232232.33844484345, 3969809.4009767985, 45.328337591323624], + [232232.33844484345, 3969809.4009767985, 45.36643766732363], + [232237.07385587375, 3969805.4136992334, 45.45241890036475], + [232237.07385587375, 3969805.4136992334, 45.49051897636476], + [232237.32645688087, 3969809.0549480203, 45.37941890036475], + [232237.32645688087, 3969809.0549480203, 45.41751897636475], + [232242.06186791116, 3969805.067670456, 45.504329497383374], + [232242.06186791116, 3969805.067670456, 45.54242957338338], + [232242.31446891834, 3969808.708919244, 45.43132949738337], + [232242.31446891834, 3969808.708919244, 45.46942957338338], + [232247.04987994864, 3969804.7216416798, 45.557069382379524], + [232247.04987994864, 3969804.7216416798, 45.59516945837954], + [232247.30248095575, 3969808.362890467, 45.48406938237952], + [232247.30248095575, 3969808.362890467, 45.52216945837952], + [232252.03789198605, 3969804.3756129025, 45.610638555353184], + [232252.03789198605, 3969804.3756129025, 45.64873863135318], + [232252.29049299317, 3969808.0168616897, 45.537638555353176], + [232252.29049299317, 3969808.0168616897, 45.57573863135319], + [232257.02590402347, 3969804.0295841256, 45.665037016304346], + [232257.02590402347, 3969804.0295841256, 45.70313709230435], + [232257.27850503064, 3969807.6708329134, 45.592037016304346], + [232257.27850503064, 3969807.6708329134, 45.630137092304345], + [232262.01391606088, 3969803.6835553492, 45.72026476523304], + [232262.01391606088, 3969803.6835553492, 45.75836484123303], + [232262.26651706803, 3969807.324804136, 45.64726476523304], + [232262.26651706803, 3969807.324804136, 45.68536484123304], + [232267.00192809835, 3969803.337526572, 45.776321802139236], + [232267.00192809835, 3969803.337526572, 45.81442187813923], + [232267.25452910547, 3969806.9787753597, 45.70332180213923], + [232267.25452910547, 3969806.9787753597, 45.741421878139235], + [232271.98994013574, 3969802.991497795, 45.83320812702294], + [232271.98994013574, 3969802.991497795, 45.871308203022956], + [232272.2425411429, 3969806.6327465824, 45.76020812702294], + [232272.2425411429, 3969806.6327465824, 45.79830820302294], + [232276.97795217318, 3969802.6454690187, 45.890923739884165], + [232276.97795217318, 3969802.6454690187, 45.92902381588418], + [232277.23055318033, 3969806.2867178055, 45.817923739884165], + [232277.23055318033, 3969806.2867178055, 45.856023815884164], + [232281.96596421063, 3969802.2994402414, 45.949468640722905], + [232281.96596421063, 3969802.2994402414, 45.98756871672291], + [232282.2185652178, 3969805.940689029, 45.87646864072291], + [232282.2185652178, 3969805.940689029, 45.914568716722904], + [232286.95397624804, 3969801.953411465, 46.00884282953916], + [232286.95397624804, 3969801.953411465, 46.04694290553917], + [232287.20657725522, 3969805.594660252, 45.93584282953916], + [232287.20657725522, 3969805.594660252, 45.97394290553917], + [232291.9419882855, 3969801.6073826877, 46.06904630633293], + [232291.9419882855, 3969801.6073826877, 46.10714638233292], + [232292.19458929263, 3969805.2486314746, 45.99604630633293], + [232292.19458929263, 3969805.2486314746, 46.03414638233293], + [232296.93000032293, 3969801.2613539104, 46.130079071104205], + [232296.93000032293, 3969801.2613539104, 46.16817914710422], + [232297.18260133005, 3969804.9026026977, 46.05707907110421], + [232297.18260133005, 3969804.9026026977, 46.095179147104204], + [232301.91801236034, 3969800.9153251336, 46.191941123853006], + [232301.91801236034, 3969800.9153251336, 46.23004119985299], + [232302.17061336752, 3969804.5565739213, 46.11894112385299], + [232302.17061336752, 3969804.5565739213, 46.157041199853], + [232306.90602439776, 3969800.569296357, 46.2546324645793], + [232306.90602439776, 3969800.569296357, 46.29273254057931], + [232307.1586254049, 3969804.210545144, 46.1816324645793], + [232307.1586254049, 3969804.210545144, 46.21973254057931], + [232311.89403643523, 3969800.22326758, 46.31815309328312], + [232311.89403643523, 3969800.22326758, 46.356253169283136], + [232312.14663744235, 3969803.8645163677, 46.24515309328313], + [232312.14663744235, 3969803.8645163677, 46.28325316928312], + [232316.88204847265, 3969799.877238803, 46.382503009964466], + [232316.88204847265, 3969799.877238803, 46.42060308596445], + [232317.1346494798, 3969803.5184875904, 46.30950300996445], + [232317.1346494798, 3969803.5184875904, 46.34760308596446], + [232321.87006051006, 3969799.5312100267, 46.447682214623306], + [232321.87006051006, 3969799.5312100267, 46.4857822906233], + [232322.1226615172, 3969803.1724588135, 46.3746822146233], + [232322.1226615172, 3969803.1724588135, 46.4127822906233], + [232326.8580725475, 3969799.1851812494, 46.513690707259656], + [232326.8580725475, 3969799.1851812494, 46.55179078325966], + [232327.11067355468, 3969802.826430037, 46.44069070725966], + [232327.11067355468, 3969802.826430037, 46.47879078325966], + [232331.84608458492, 3969798.839152472, 46.580528487873536], + [232331.84608458492, 3969798.839152472, 46.61862856387353], + [232332.0986855921, 3969802.48040126, 46.507528487873536], + [232332.0986855921, 3969802.48040126, 46.54562856387353], + [232336.51620828634, 3969798.515176272, 46.64385836124185], + [232336.51620828634, 3969798.515176272, 46.681958437241846], + [232336.8340966224, 3969798.4931236957, 46.64819387235834], + [232336.8340966224, 3969798.4931236957, 46.68629394835834], + [232336.76880929348, 3969802.1564250584, 46.57085836124184], + [232336.76880929348, 3969802.1564250584, 46.608958437241846], + [232337.0866976295, 3969802.1343724825, 46.57519387235835], + [232337.0866976295, 3969802.1343724825, 46.61329394835834], + [232341.8221086598, 3969798.1470949184, 46.716222734028484], + [232341.8221086598, 3969798.1470949184, 46.754322810028484], + [232342.07470966692, 3969801.788343706, 46.643222734028484], + [232342.07470966692, 3969801.788343706, 46.681322810028476], + [232346.81012069722, 3969797.8010661416, 46.78425159569863], + [232346.81012069722, 3969797.8010661416, 46.82235167169862], + [232347.01132511083, 3969797.7871081727, 46.786995716426084], + [232347.01132511083, 3969797.7871081727, 46.825095792426076], + [232347.0627217044, 3969801.4423149293, 46.71125159569862], + [232347.0627217044, 3969801.4423149293, 46.749351671698626], + [232347.263926118, 3969801.4283569604, 46.71399571642609], + [232347.263926118, 3969801.4283569604, 46.752095792426076] + ], + "pointIndex": [ + 7, + 8, + 10, + 9, + 0, + 8, + 2, + 4, + 10, + 0, + 2, + 1, + 3, + 4, + 0, + 1, + 7, + 9, + 3, + 0, + 9, + 10, + 16, + 15, + 0, + 10, + 4, + 6, + 16, + 0, + 4, + 3, + 5, + 6, + 0, + 3, + 9, + 15, + 5, + 0, + 15, + 16, + 18, + 17, + 0, + 16, + 6, + 12, + 18, + 0, + 6, + 5, + 11, + 12, + 0, + 5, + 15, + 17, + 11, + 0, + 17, + 18, + 22, + 21, + 0, + 18, + 12, + 14, + 22, + 0, + 12, + 11, + 13, + 14, + 0, + 11, + 17, + 21, + 13, + 0, + 21, + 22, + 26, + 25, + 0, + 22, + 14, + 20, + 26, + 0, + 14, + 13, + 19, + 20, + 0, + 13, + 21, + 25, + 19, + 0, + 25, + 26, + 28, + 27, + 0, + 26, + 20, + 24, + 28, + 0, + 20, + 19, + 23, + 24, + 0, + 19, + 25, + 27, + 23, + 0, + 27, + 28, + 34, + 33, + 0, + 28, + 24, + 30, + 34, + 0, + 24, + 23, + 29, + 30, + 0, + 23, + 27, + 33, + 29, + 0, + 33, + 34, + 40, + 39, + 0, + 34, + 30, + 32, + 40, + 0, + 30, + 29, + 31, + 32, + 0, + 29, + 33, + 39, + 31, + 0, + 39, + 40, + 44, + 43, + 0, + 40, + 32, + 36, + 44, + 0, + 32, + 31, + 35, + 36, + 0, + 31, + 39, + 43, + 35, + 0, + 43, + 44, + 46, + 45, + 0, + 44, + 36, + 38, + 46, + 0, + 36, + 35, + 37, + 38, + 0, + 35, + 43, + 45, + 37, + 0, + 45, + 46, + 50, + 49, + 0, + 46, + 38, + 42, + 50, + 0, + 38, + 37, + 41, + 42, + 0, + 37, + 45, + 49, + 41, + 0, + 49, + 50, + 52, + 51, + 0, + 50, + 42, + 48, + 52, + 0, + 42, + 41, + 47, + 48, + 0, + 41, + 49, + 51, + 47, + 0, + 51, + 52, + 59, + 57, + 0, + 52, + 48, + 55, + 59, + 0, + 48, + 47, + 53, + 55, + 0, + 47, + 51, + 57, + 53, + 0, + 57, + 59, + 60, + 58, + 0, + 59, + 55, + 56, + 60, + 0, + 55, + 53, + 54, + 56, + 0, + 53, + 57, + 58, + 54, + 0, + 58, + 60, + 66, + 65, + 0, + 60, + 56, + 62, + 66, + 0, + 56, + 54, + 61, + 62, + 0, + 54, + 58, + 65, + 61, + 0, + 65, + 66, + 70, + 69, + 0, + 66, + 62, + 64, + 70, + 0, + 62, + 61, + 63, + 64, + 0, + 61, + 65, + 69, + 63, + 0, + 69, + 70, + 74, + 73, + 0, + 70, + 64, + 68, + 74, + 0, + 64, + 63, + 67, + 68, + 0, + 63, + 69, + 73, + 67, + 0, + 73, + 74, + 78, + 77, + 0, + 74, + 68, + 72, + 78, + 0, + 68, + 67, + 71, + 72, + 0, + 67, + 73, + 77, + 71, + 0, + 77, + 78, + 80, + 79, + 0, + 78, + 72, + 76, + 80, + 0, + 72, + 71, + 75, + 76, + 0, + 71, + 77, + 79, + 75, + 0, + 79, + 80, + 86, + 85, + 0, + 80, + 76, + 82, + 86, + 0, + 76, + 75, + 81, + 82, + 0, + 75, + 79, + 85, + 81, + 0, + 85, + 86, + 88, + 87, + 0, + 86, + 82, + 84, + 88, + 0, + 82, + 81, + 83, + 84, + 0, + 81, + 85, + 87, + 83, + 0, + 87, + 88, + 94, + 93, + 0, + 88, + 84, + 90, + 94, + 0, + 84, + 83, + 89, + 90, + 0, + 83, + 87, + 93, + 89, + 0, + 93, + 94, + 98, + 97, + 0, + 94, + 90, + 92, + 98, + 0, + 90, + 89, + 91, + 92, + 0, + 89, + 93, + 97, + 91, + 0, + 97, + 98, + 100, + 99, + 0, + 98, + 92, + 96, + 100, + 0, + 92, + 91, + 95, + 96, + 0, + 91, + 97, + 99, + 95, + 0, + 99, + 100, + 106, + 105, + 0, + 100, + 96, + 102, + 106, + 0, + 96, + 95, + 101, + 102, + 0, + 95, + 99, + 105, + 101, + 0, + 105, + 106, + 108, + 107, + 0, + 106, + 102, + 104, + 108, + 0, + 102, + 101, + 103, + 104, + 0, + 101, + 105, + 107, + 103, + 0, + 107, + 108, + 114, + 113, + 0, + 108, + 104, + 110, + 114, + 0, + 104, + 103, + 109, + 110, + 0, + 103, + 107, + 113, + 109, + 0, + 113, + 114, + 116, + 115, + 0, + 114, + 110, + 112, + 116, + 0, + 110, + 109, + 111, + 112, + 0, + 109, + 113, + 115, + 111, + 0, + 115, + 116, + 120, + 119, + 0, + 116, + 112, + 118, + 120, + 0, + 112, + 111, + 117, + 118, + 0, + 111, + 115, + 119, + 117, + 0, + 119, + 120, + 126, + 125, + 0, + 120, + 118, + 122, + 126, + 0, + 118, + 117, + 121, + 122, + 0, + 117, + 119, + 125, + 121, + 0, + 125, + 126, + 128, + 127, + 0, + 126, + 122, + 124, + 128, + 0, + 122, + 121, + 123, + 124, + 0, + 121, + 125, + 127, + 123, + 0, + 127, + 128, + 132, + 131, + 0, + 128, + 124, + 130, + 132, + 0, + 124, + 123, + 129, + 130, + 0, + 123, + 127, + 131, + 129, + 0, + 131, + 132, + 136, + 135, + 0, + 132, + 130, + 134, + 136, + 0, + 130, + 129, + 133, + 134, + 0, + 129, + 131, + 135, + 133, + 0, + 135, + 136, + 140, + 139, + 0, + 136, + 134, + 138, + 140, + 0, + 134, + 133, + 137, + 138, + 0, + 133, + 135, + 139, + 137, + 0, + 139, + 140, + 144, + 143, + 0, + 140, + 138, + 142, + 144, + 0, + 138, + 137, + 141, + 142, + 0, + 137, + 139, + 143, + 141, + 0, + 143, + 144, + 148, + 147, + 0, + 144, + 142, + 146, + 148, + 0, + 142, + 141, + 145, + 146, + 0, + 141, + 143, + 147, + 145, + 0, + 147, + 148, + 152, + 151, + 0, + 148, + 146, + 150, + 152, + 0, + 146, + 145, + 149, + 150, + 0, + 145, + 147, + 151, + 149, + 0, + 151, + 152, + 156, + 155, + 0, + 152, + 150, + 154, + 156, + 0, + 150, + 149, + 153, + 154, + 0, + 149, + 151, + 155, + 153, + 0, + 155, + 156, + 160, + 159, + 0, + 156, + 154, + 158, + 160, + 0, + 154, + 153, + 157, + 158, + 0, + 153, + 155, + 159, + 157, + 0, + 159, + 160, + 164, + 163, + 0, + 160, + 158, + 162, + 164, + 0, + 158, + 157, + 161, + 162, + 0, + 157, + 159, + 163, + 161, + 0, + 163, + 164, + 168, + 167, + 0, + 164, + 162, + 166, + 168, + 0, + 162, + 161, + 165, + 166, + 0, + 161, + 163, + 167, + 165, + 0, + 167, + 168, + 172, + 171, + 0, + 168, + 166, + 170, + 172, + 0, + 166, + 165, + 169, + 170, + 0, + 165, + 167, + 171, + 169, + 0, + 171, + 172, + 176, + 175, + 0, + 172, + 170, + 174, + 176, + 0, + 170, + 169, + 173, + 174, + 0, + 169, + 171, + 175, + 173, + 0, + 175, + 176, + 180, + 179, + 0, + 176, + 174, + 178, + 180, + 0, + 174, + 173, + 177, + 178, + 0, + 173, + 175, + 179, + 177, + 0, + 179, + 180, + 184, + 183, + 0, + 180, + 178, + 182, + 184, + 0, + 178, + 177, + 181, + 182, + 0, + 177, + 179, + 183, + 181, + 0, + 183, + 184, + 188, + 187, + 0, + 184, + 182, + 186, + 188, + 0, + 182, + 181, + 185, + 186, + 0, + 181, + 183, + 187, + 185, + 0, + 187, + 188, + 192, + 191, + 0, + 188, + 186, + 190, + 192, + 0, + 186, + 185, + 189, + 190, + 0, + 185, + 187, + 191, + 189, + 0, + 191, + 192, + 196, + 195, + 0, + 192, + 190, + 194, + 196, + 0, + 190, + 189, + 193, + 194, + 0, + 189, + 191, + 195, + 193, + 0, + 195, + 196, + 200, + 199, + 0, + 196, + 194, + 198, + 200, + 0, + 194, + 193, + 197, + 198, + 0, + 193, + 195, + 199, + 197, + 0, + 199, + 200, + 204, + 203, + 0, + 200, + 198, + 202, + 204, + 0, + 198, + 197, + 201, + 202, + 0, + 197, + 199, + 203, + 201, + 0, + 203, + 204, + 208, + 207, + 0, + 204, + 202, + 206, + 208, + 0, + 202, + 201, + 205, + 206, + 0, + 201, + 203, + 207, + 205, + 0, + 207, + 208, + 212, + 211, + 0, + 208, + 206, + 210, + 212, + 0, + 206, + 205, + 209, + 210, + 0, + 205, + 207, + 211, + 209, + 0, + 211, + 212, + 216, + 215, + 0, + 212, + 210, + 214, + 216, + 0, + 210, + 209, + 213, + 214, + 0, + 209, + 211, + 215, + 213, + 0, + 215, + 216, + 220, + 219, + 0, + 216, + 214, + 218, + 220, + 0, + 214, + 213, + 217, + 218, + 0, + 213, + 215, + 219, + 217, + 0, + 219, + 220, + 224, + 223, + 0, + 220, + 218, + 222, + 224, + 0, + 218, + 217, + 221, + 222, + 0, + 217, + 219, + 223, + 221, + 0, + 223, + 224, + 228, + 227, + 0, + 224, + 222, + 226, + 228, + 0, + 222, + 221, + 225, + 226, + 0, + 221, + 223, + 227, + 225, + 0, + 227, + 228, + 232, + 231, + 0, + 228, + 226, + 230, + 232, + 0, + 226, + 225, + 229, + 230, + 0, + 225, + 227, + 231, + 229, + 0, + 231, + 232, + 236, + 235, + 0, + 232, + 230, + 234, + 236, + 0, + 230, + 229, + 233, + 234, + 0, + 229, + 231, + 235, + 233, + 0, + 235, + 236, + 240, + 239, + 0, + 236, + 234, + 238, + 240, + 0, + 234, + 233, + 237, + 238, + 0, + 233, + 235, + 239, + 237, + 0, + 239, + 240, + 244, + 243, + 0, + 240, + 238, + 242, + 244, + 0, + 238, + 237, + 241, + 242, + 0, + 237, + 239, + 243, + 241, + 0, + 243, + 244, + 248, + 247, + 0, + 244, + 242, + 246, + 248, + 0, + 242, + 241, + 245, + 246, + 0, + 241, + 243, + 247, + 245, + 0, + 247, + 248, + 252, + 251, + 0, + 248, + 246, + 250, + 252, + 0, + 246, + 245, + 249, + 250, + 0, + 245, + 247, + 251, + 249, + 0, + 251, + 252, + 258, + 257, + 0, + 252, + 250, + 254, + 258, + 0, + 250, + 249, + 253, + 254, + 0, + 249, + 251, + 257, + 253, + 0, + 257, + 258, + 260, + 259, + 0, + 258, + 254, + 256, + 260, + 0, + 254, + 253, + 255, + 256, + 0, + 253, + 257, + 259, + 255, + 0, + 259, + 260, + 264, + 263, + 0, + 260, + 256, + 262, + 264, + 0, + 256, + 255, + 261, + 262, + 0, + 255, + 259, + 263, + 261, + 0, + 263, + 264, + 268, + 267, + 0, + 264, + 262, + 266, + 268, + 0, + 262, + 261, + 265, + 266, + 0, + 261, + 263, + 267, + 265, + 0, + 267, + 268, + 272, + 271, + 0, + 268, + 266, + 270, + 272, + 0, + 266, + 265, + 269, + 270, + 0, + 265, + 267, + 271, + 269, + 0, + 271, + 272, + 276, + 275, + 0, + 272, + 270, + 274, + 276, + 0, + 270, + 269, + 273, + 274, + 0, + 269, + 271, + 275, + 273, + 0, + 275, + 276, + 282, + 281, + 0, + 276, + 274, + 278, + 282, + 0, + 274, + 273, + 277, + 278, + 0, + 273, + 275, + 281, + 277, + 0, + 283, + 281, + 282, + 284, + 0, + 284, + 282, + 278, + 280, + 0, + 280, + 278, + 277, + 279, + 0, + 279, + 277, + 281, + 283, + 0, + 289, + 289, + 290, + 290, + 0, + 290, + 290, + 288, + 288, + 0, + 289, + 289, + 286, + 286, + 0, + 288, + 288, + 287, + 287, + 0, + 287, + 287, + 285, + 285, + 0, + 285, + 285, + 286, + 286, + 0, + 295, + 296, + 298, + 297, + 0, + 296, + 292, + 294, + 298, + 0, + 292, + 291, + 293, + 294, + 0, + 291, + 295, + 297, + 293, + 0, + 297, + 298, + 302, + 301, + 0, + 298, + 294, + 300, + 302, + 0, + 294, + 293, + 299, + 300, + 0, + 293, + 297, + 301, + 299, + 0, + 301, + 302, + 306, + 305, + 0, + 302, + 300, + 304, + 306, + 0, + 300, + 299, + 303, + 304, + 0, + 299, + 301, + 305, + 303, + 0, + 305, + 306, + 310, + 309, + 0, + 306, + 304, + 308, + 310, + 0, + 304, + 303, + 307, + 308, + 0, + 303, + 305, + 309, + 307, + 0, + 309, + 310, + 314, + 313, + 0, + 310, + 308, + 312, + 314, + 0, + 308, + 307, + 311, + 312, + 0, + 307, + 309, + 313, + 311, + 0, + 313, + 314, + 318, + 317, + 0, + 314, + 312, + 316, + 318, + 0, + 312, + 311, + 315, + 316, + 0, + 311, + 313, + 317, + 315, + 0, + 317, + 318, + 322, + 321, + 0, + 318, + 316, + 320, + 322, + 0, + 316, + 315, + 319, + 320, + 0, + 315, + 317, + 321, + 319, + 0, + 321, + 322, + 326, + 325, + 0, + 322, + 320, + 324, + 326, + 0, + 320, + 319, + 323, + 324, + 0, + 319, + 321, + 325, + 323, + 0, + 325, + 326, + 330, + 329, + 0, + 326, + 324, + 328, + 330, + 0, + 324, + 323, + 327, + 328, + 0, + 323, + 325, + 329, + 327, + 0, + 329, + 330, + 334, + 333, + 0, + 330, + 328, + 332, + 334, + 0, + 328, + 327, + 331, + 332, + 0, + 327, + 329, + 333, + 331, + 0, + 333, + 334, + 338, + 337, + 0, + 334, + 332, + 336, + 338, + 0, + 332, + 331, + 335, + 336, + 0, + 331, + 333, + 337, + 335, + 0, + 337, + 338, + 342, + 341, + 0, + 338, + 336, + 340, + 342, + 0, + 336, + 335, + 339, + 340, + 0, + 335, + 337, + 341, + 339, + 0, + 341, + 342, + 346, + 345, + 0, + 342, + 340, + 344, + 346, + 0, + 340, + 339, + 343, + 344, + 0, + 339, + 341, + 345, + 343, + 0, + 345, + 346, + 350, + 349, + 0, + 346, + 344, + 348, + 350, + 0, + 344, + 343, + 347, + 348, + 0, + 343, + 345, + 349, + 347, + 0, + 349, + 350, + 354, + 353, + 0, + 350, + 348, + 352, + 354, + 0, + 348, + 347, + 351, + 352, + 0, + 347, + 349, + 353, + 351, + 0, + 353, + 354, + 358, + 357, + 0, + 354, + 352, + 356, + 358, + 0, + 352, + 351, + 355, + 356, + 0, + 351, + 353, + 357, + 355, + 0, + 357, + 358, + 362, + 361, + 0, + 358, + 356, + 360, + 362, + 0, + 356, + 355, + 359, + 360, + 0, + 355, + 357, + 361, + 359, + 0, + 361, + 362, + 366, + 365, + 0, + 362, + 360, + 364, + 366, + 0, + 360, + 359, + 363, + 364, + 0, + 359, + 361, + 365, + 363, + 0, + 365, + 366, + 370, + 369, + 0, + 366, + 364, + 368, + 370, + 0, + 364, + 363, + 367, + 368, + 0, + 363, + 365, + 369, + 367, + 0, + 369, + 370, + 374, + 373, + 0, + 370, + 368, + 372, + 374, + 0, + 368, + 367, + 371, + 372, + 0, + 367, + 369, + 373, + 371, + 0, + 373, + 374, + 378, + 377, + 0, + 374, + 372, + 376, + 378, + 0, + 372, + 371, + 375, + 376, + 0, + 371, + 373, + 377, + 375, + 0, + 377, + 378, + 382, + 381, + 0, + 378, + 376, + 380, + 382, + 0, + 376, + 375, + 379, + 380, + 0, + 375, + 377, + 381, + 379, + 0, + 381, + 382, + 386, + 385, + 0, + 382, + 380, + 384, + 386, + 0, + 380, + 379, + 383, + 384, + 0, + 379, + 381, + 385, + 383, + 0, + 385, + 386, + 390, + 389, + 0, + 386, + 384, + 388, + 390, + 0, + 384, + 383, + 387, + 388, + 0, + 383, + 385, + 389, + 387, + 0, + 389, + 390, + 394, + 393, + 0, + 390, + 388, + 392, + 394, + 0, + 388, + 387, + 391, + 392, + 0, + 387, + 389, + 393, + 391, + 0, + 393, + 394, + 398, + 397, + 0, + 394, + 392, + 396, + 398, + 0, + 392, + 391, + 395, + 396, + 0, + 391, + 393, + 397, + 395, + 0, + 397, + 398, + 402, + 401, + 0, + 398, + 396, + 400, + 402, + 0, + 396, + 395, + 399, + 400, + 0, + 395, + 397, + 401, + 399, + 0, + 401, + 402, + 406, + 405, + 0, + 402, + 400, + 404, + 406, + 0, + 400, + 399, + 403, + 404, + 0, + 399, + 401, + 405, + 403, + 0, + 405, + 406, + 410, + 409, + 0, + 406, + 404, + 408, + 410, + 0, + 404, + 403, + 407, + 408, + 0, + 403, + 405, + 409, + 407, + 0, + 409, + 410, + 414, + 413, + 0, + 410, + 408, + 412, + 414, + 0, + 408, + 407, + 411, + 412, + 0, + 407, + 409, + 413, + 411, + 0, + 413, + 414, + 418, + 417, + 0, + 414, + 412, + 416, + 418, + 0, + 412, + 411, + 415, + 416, + 0, + 411, + 413, + 417, + 415, + 0, + 417, + 418, + 422, + 421, + 0, + 418, + 416, + 420, + 422, + 0, + 416, + 415, + 419, + 420, + 0, + 415, + 417, + 421, + 419, + 0, + 421, + 422, + 426, + 425, + 0, + 422, + 420, + 424, + 426, + 0, + 420, + 419, + 423, + 424, + 0, + 419, + 421, + 425, + 423, + 0, + 425, + 426, + 430, + 429, + 0, + 426, + 424, + 428, + 430, + 0, + 424, + 423, + 427, + 428, + 0, + 423, + 425, + 429, + 427, + 0, + 429, + 430, + 434, + 433, + 0, + 430, + 428, + 432, + 434, + 0, + 428, + 427, + 431, + 432, + 0, + 427, + 429, + 433, + 431, + 0, + 433, + 434, + 438, + 437, + 0, + 434, + 432, + 436, + 438, + 0, + 432, + 431, + 435, + 436, + 0, + 431, + 433, + 437, + 435, + 0, + 437, + 438, + 442, + 441, + 0, + 438, + 436, + 440, + 442, + 0, + 436, + 435, + 439, + 440, + 0, + 435, + 437, + 441, + 439, + 0, + 441, + 442, + 446, + 445, + 0, + 442, + 440, + 444, + 446, + 0, + 440, + 439, + 443, + 444, + 0, + 439, + 441, + 445, + 443, + 0, + 445, + 446, + 450, + 449, + 0, + 446, + 444, + 448, + 450, + 0, + 444, + 443, + 447, + 448, + 0, + 443, + 445, + 449, + 447, + 0, + 449, + 450, + 454, + 453, + 0, + 450, + 448, + 452, + 454, + 0, + 448, + 447, + 451, + 452, + 0, + 447, + 449, + 453, + 451, + 0, + 453, + 454, + 460, + 459, + 0, + 454, + 452, + 456, + 460, + 0, + 452, + 451, + 455, + 456, + 0, + 451, + 453, + 459, + 455, + 0, + 459, + 460, + 464, + 463, + 0, + 460, + 456, + 458, + 464, + 0, + 456, + 455, + 457, + 458, + 0, + 455, + 459, + 463, + 457, + 0, + 463, + 464, + 466, + 465, + 0, + 464, + 458, + 462, + 466, + 0, + 458, + 457, + 461, + 462, + 0, + 457, + 463, + 465, + 461, + 0, + 465, + 466, + 470, + 469, + 0, + 466, + 462, + 468, + 470, + 0, + 462, + 461, + 467, + 468, + 0, + 461, + 465, + 469, + 467, + 0, + 469, + 470, + 476, + 475, + 0, + 470, + 468, + 472, + 476, + 0, + 468, + 467, + 471, + 472, + 0, + 467, + 469, + 475, + 471, + 0, + 475, + 476, + 478, + 477, + 0, + 476, + 472, + 474, + 478, + 0, + 472, + 471, + 473, + 474, + 0, + 471, + 475, + 477, + 473, + 0, + 477, + 478, + 482, + 481, + 0, + 478, + 474, + 480, + 482, + 0, + 474, + 473, + 479, + 480, + 0, + 473, + 477, + 481, + 479, + 0, + 481, + 482, + 486, + 485, + 0, + 482, + 480, + 484, + 486, + 0, + 480, + 479, + 483, + 484, + 0, + 479, + 481, + 485, + 483, + 0, + 485, + 486, + 494, + 493, + 0, + 486, + 484, + 488, + 494, + 0, + 484, + 483, + 487, + 488, + 0, + 483, + 485, + 493, + 487, + 0, + 493, + 494, + 496, + 495, + 0, + 494, + 488, + 490, + 496, + 0, + 488, + 487, + 489, + 490, + 0, + 487, + 493, + 495, + 489, + 0, + 495, + 496, + 500, + 499, + 0, + 496, + 490, + 492, + 500, + 0, + 490, + 489, + 491, + 492, + 0, + 489, + 495, + 499, + 491, + 0, + 499, + 500, + 502, + 501, + 0, + 500, + 492, + 498, + 502, + 0, + 492, + 491, + 497, + 498, + 0, + 491, + 499, + 501, + 497, + 0, + 501, + 502, + 506, + 505, + 0, + 502, + 498, + 504, + 506, + 0, + 498, + 497, + 503, + 504, + 0, + 497, + 501, + 505, + 503, + 0, + 505, + 506, + 510, + 509, + 0, + 506, + 504, + 508, + 510, + 0, + 504, + 503, + 507, + 508, + 0, + 503, + 505, + 509, + 507, + 0, + 509, + 510, + 516, + 515, + 0, + 510, + 508, + 512, + 516, + 0, + 508, + 507, + 511, + 512, + 0, + 507, + 509, + 515, + 511, + 0, + 515, + 516, + 518, + 517, + 0, + 516, + 512, + 514, + 518, + 0, + 512, + 511, + 513, + 514, + 0, + 511, + 515, + 517, + 513, + 0, + 517, + 518, + 524, + 523, + 0, + 518, + 514, + 520, + 524, + 0, + 514, + 513, + 519, + 520, + 0, + 513, + 517, + 523, + 519, + 0, + 523, + 524, + 528, + 527, + 0, + 524, + 520, + 522, + 528, + 0, + 520, + 519, + 521, + 522, + 0, + 519, + 523, + 527, + 521, + 0, + 527, + 528, + 530, + 529, + 0, + 528, + 522, + 526, + 530, + 0, + 522, + 521, + 525, + 526, + 0, + 521, + 527, + 529, + 525, + 0, + 529, + 530, + 536, + 535, + 0, + 530, + 526, + 532, + 536, + 0, + 526, + 525, + 531, + 532, + 0, + 525, + 529, + 535, + 531, + 0, + 535, + 536, + 538, + 537, + 0, + 536, + 532, + 534, + 538, + 0, + 532, + 531, + 533, + 534, + 0, + 531, + 535, + 537, + 533, + 0, + 537, + 538, + 542, + 541, + 0, + 538, + 534, + 540, + 542, + 0, + 534, + 533, + 539, + 540, + 0, + 533, + 537, + 541, + 539, + 0, + 541, + 542, + 546, + 545, + 0, + 542, + 540, + 544, + 546, + 0, + 540, + 539, + 543, + 544, + 0, + 539, + 541, + 545, + 543, + 0, + 545, + 546, + 552, + 551, + 0, + 546, + 544, + 548, + 552, + 0, + 544, + 543, + 547, + 548, + 0, + 543, + 545, + 551, + 547, + 0, + 551, + 552, + 554, + 553, + 0, + 552, + 548, + 550, + 554, + 0, + 548, + 547, + 549, + 550, + 0, + 547, + 551, + 553, + 549, + 0, + 553, + 554, + 558, + 557, + 0, + 554, + 550, + 556, + 558, + 0, + 550, + 549, + 555, + 556, + 0, + 549, + 553, + 557, + 555, + 0, + 557, + 558, + 562, + 561, + 0, + 558, + 556, + 560, + 562, + 0, + 556, + 555, + 559, + 560, + 0, + 555, + 557, + 561, + 559, + 0, + 561, + 562, + 568, + 567, + 0, + 562, + 560, + 564, + 568, + 0, + 560, + 559, + 563, + 564, + 0, + 559, + 561, + 567, + 563, + 0, + 567, + 568, + 572, + 571, + 0, + 568, + 564, + 566, + 572, + 0, + 564, + 563, + 565, + 566, + 0, + 563, + 567, + 571, + 565, + 0, + 571, + 572, + 574, + 573, + 0, + 572, + 566, + 570, + 574, + 0, + 566, + 565, + 569, + 570, + 0, + 565, + 571, + 573, + 569, + 0, + 573, + 574, + 580, + 579, + 0, + 574, + 570, + 576, + 580, + 0, + 570, + 569, + 575, + 576, + 0, + 569, + 573, + 579, + 575, + 0, + 579, + 580, + 582, + 581, + 0, + 580, + 576, + 578, + 582, + 0, + 576, + 575, + 577, + 578, + 0, + 575, + 579, + 581, + 577, + 0, + 581, + 582, + 588, + 587, + 0, + 582, + 578, + 584, + 588, + 0, + 578, + 577, + 583, + 584, + 0, + 577, + 581, + 587, + 583, + 0, + 587, + 588, + 592, + 591, + 0, + 588, + 584, + 586, + 592, + 0, + 584, + 583, + 585, + 586, + 0, + 583, + 587, + 591, + 585, + 0, + 591, + 592, + 594, + 593, + 0, + 592, + 586, + 590, + 594, + 0, + 586, + 585, + 589, + 590, + 0, + 585, + 591, + 593, + 589, + 0, + 593, + 594, + 598, + 597, + 0, + 594, + 590, + 596, + 598, + 0, + 590, + 589, + 595, + 596, + 0, + 589, + 593, + 597, + 595, + 0, + 597, + 598, + 602, + 601, + 0, + 598, + 596, + 600, + 602, + 0, + 596, + 595, + 599, + 600, + 0, + 595, + 597, + 601, + 599, + 0, + 601, + 602, + 610, + 609, + 0, + 602, + 600, + 604, + 610, + 0, + 600, + 599, + 603, + 604, + 0, + 599, + 601, + 609, + 603, + 0, + 609, + 610, + 612, + 611, + 0, + 610, + 604, + 606, + 612, + 0, + 604, + 603, + 605, + 606, + 0, + 603, + 609, + 611, + 605, + 0, + 611, + 612, + 614, + 613, + 0, + 612, + 606, + 608, + 614, + 0, + 606, + 605, + 607, + 608, + 0, + 605, + 611, + 613, + 607, + 0, + 613, + 614, + 618, + 617, + 0, + 614, + 608, + 616, + 618, + 0, + 608, + 607, + 615, + 616, + 0, + 607, + 613, + 617, + 615, + 0, + 617, + 618, + 622, + 621, + 0, + 618, + 616, + 620, + 622, + 0, + 616, + 615, + 619, + 620, + 0, + 615, + 617, + 621, + 619, + 0, + 621, + 622, + 628, + 627, + 0, + 622, + 620, + 624, + 628, + 0, + 620, + 619, + 623, + 624, + 0, + 619, + 621, + 627, + 623, + 0, + 627, + 628, + 630, + 629, + 0, + 628, + 624, + 626, + 630, + 0, + 624, + 623, + 625, + 626, + 0, + 623, + 627, + 629, + 625, + 0, + 629, + 630, + 634, + 633, + 0, + 630, + 626, + 632, + 634, + 0, + 626, + 625, + 631, + 632, + 0, + 625, + 629, + 633, + 631, + 0, + 633, + 634, + 638, + 637, + 0, + 634, + 632, + 636, + 638, + 0, + 632, + 631, + 635, + 636, + 0, + 631, + 633, + 637, + 635, + 0, + 637, + 638, + 644, + 643, + 0, + 638, + 636, + 640, + 644, + 0, + 636, + 635, + 639, + 640, + 0, + 635, + 637, + 643, + 639, + 0, + 643, + 644, + 646, + 645, + 0, + 644, + 640, + 642, + 646, + 0, + 640, + 639, + 641, + 642, + 0, + 639, + 643, + 645, + 641, + 0, + 645, + 646, + 650, + 649, + 0, + 646, + 642, + 648, + 650, + 0, + 642, + 641, + 647, + 648, + 0, + 641, + 645, + 649, + 647, + 0, + 649, + 650, + 654, + 653, + 0, + 650, + 648, + 652, + 654, + 0, + 648, + 647, + 651, + 652, + 0, + 647, + 649, + 653, + 651, + 0, + 653, + 654, + 658, + 657, + 0, + 654, + 652, + 656, + 658, + 0, + 652, + 651, + 655, + 656, + 0, + 651, + 653, + 657, + 655, + 0, + 657, + 658, + 662, + 661, + 0, + 658, + 656, + 660, + 662, + 0, + 656, + 655, + 659, + 660, + 0, + 655, + 657, + 661, + 659, + 0, + 661, + 662, + 666, + 665, + 0, + 662, + 660, + 664, + 666, + 0, + 660, + 659, + 663, + 664, + 0, + 659, + 661, + 665, + 663, + 0, + 665, + 666, + 670, + 669, + 0, + 666, + 664, + 668, + 670, + 0, + 664, + 663, + 667, + 668, + 0, + 663, + 665, + 669, + 667, + 0, + 669, + 670, + 674, + 673, + 0, + 670, + 668, + 672, + 674, + 0, + 668, + 667, + 671, + 672, + 0, + 667, + 669, + 673, + 671, + 0, + 673, + 674, + 678, + 677, + 0, + 674, + 672, + 676, + 678, + 0, + 672, + 671, + 675, + 676, + 0, + 671, + 673, + 677, + 675, + 0, + 677, + 678, + 682, + 681, + 0, + 678, + 676, + 680, + 682, + 0, + 676, + 675, + 679, + 680, + 0, + 675, + 677, + 681, + 679, + 0, + 681, + 682, + 686, + 685, + 0, + 682, + 680, + 684, + 686, + 0, + 680, + 679, + 683, + 684, + 0, + 679, + 681, + 685, + 683, + 0, + 685, + 686, + 690, + 689, + 0, + 686, + 684, + 688, + 690, + 0, + 684, + 683, + 687, + 688, + 0, + 683, + 685, + 689, + 687, + 0, + 689, + 690, + 696, + 695, + 0, + 690, + 688, + 692, + 696, + 0, + 688, + 687, + 691, + 692, + 0, + 687, + 689, + 695, + 691, + 0, + 695, + 696, + 700, + 699, + 0, + 696, + 692, + 694, + 700, + 0, + 692, + 691, + 693, + 694, + 0, + 691, + 695, + 699, + 693, + 0, + 699, + 700, + 702, + 701, + 0, + 700, + 694, + 698, + 702, + 0, + 694, + 693, + 697, + 698, + 0, + 693, + 699, + 701, + 697, + 0, + 701, + 702, + 706, + 705, + 0, + 702, + 698, + 704, + 706, + 0, + 698, + 697, + 703, + 704, + 0, + 697, + 701, + 705, + 703, + 0, + 705, + 706, + 710, + 709, + 0, + 706, + 704, + 708, + 710, + 0, + 704, + 703, + 707, + 708, + 0, + 703, + 705, + 709, + 707, + 0, + 709, + 710, + 714, + 713, + 0, + 710, + 708, + 712, + 714, + 0, + 708, + 707, + 711, + 712, + 0, + 707, + 709, + 713, + 711, + 0, + 713, + 714, + 718, + 717, + 0, + 714, + 712, + 716, + 718, + 0, + 712, + 711, + 715, + 716, + 0, + 711, + 713, + 717, + 715, + 0, + 717, + 718, + 722, + 721, + 0, + 718, + 716, + 720, + 722, + 0, + 716, + 715, + 719, + 720, + 0, + 715, + 717, + 721, + 719, + 0, + 721, + 722, + 728, + 727, + 0, + 722, + 720, + 724, + 728, + 0, + 720, + 719, + 723, + 724, + 0, + 719, + 721, + 727, + 723, + 0, + 727, + 728, + 730, + 729, + 0, + 728, + 724, + 726, + 730, + 0, + 724, + 723, + 725, + 726, + 0, + 723, + 727, + 729, + 725, + 0, + 729, + 730, + 734, + 733, + 0, + 730, + 726, + 732, + 734, + 0, + 726, + 725, + 731, + 732, + 0, + 725, + 729, + 733, + 731, + 0, + 733, + 734, + 738, + 737, + 0, + 734, + 732, + 736, + 738, + 0, + 732, + 731, + 735, + 736, + 0, + 731, + 733, + 737, + 735, + 0, + 737, + 738, + 742, + 741, + 0, + 738, + 736, + 740, + 742, + 0, + 736, + 735, + 739, + 740, + 0, + 735, + 737, + 741, + 739, + 0, + 741, + 742, + 746, + 745, + 0, + 742, + 740, + 744, + 746, + 0, + 740, + 739, + 743, + 744, + 0, + 739, + 741, + 745, + 743, + 0, + 745, + 746, + 750, + 749, + 0, + 746, + 744, + 748, + 750, + 0, + 744, + 743, + 747, + 748, + 0, + 743, + 745, + 749, + 747, + 0, + 749, + 750, + 754, + 753, + 0, + 750, + 748, + 752, + 754, + 0, + 748, + 747, + 751, + 752, + 0, + 747, + 749, + 753, + 751, + 0, + 753, + 754, + 758, + 757, + 0, + 754, + 752, + 756, + 758, + 0, + 752, + 751, + 755, + 756, + 0, + 751, + 753, + 757, + 755, + 0, + 757, + 758, + 762, + 761, + 0, + 758, + 756, + 760, + 762, + 0, + 756, + 755, + 759, + 760, + 0, + 755, + 757, + 761, + 759, + 0, + 761, + 762, + 766, + 765, + 0, + 762, + 760, + 764, + 766, + 0, + 760, + 759, + 763, + 764, + 0, + 759, + 761, + 765, + 763, + 0, + 765, + 766, + 770, + 769, + 0, + 766, + 764, + 768, + 770, + 0, + 764, + 763, + 767, + 768, + 0, + 763, + 765, + 769, + 767, + 0, + 769, + 770, + 774, + 773, + 0, + 770, + 768, + 772, + 774, + 0, + 768, + 767, + 771, + 772, + 0, + 767, + 769, + 773, + 771, + 0, + 773, + 774, + 778, + 777, + 0, + 774, + 772, + 776, + 778, + 0, + 772, + 771, + 775, + 776, + 0, + 771, + 773, + 777, + 775, + 0, + 777, + 778, + 782, + 781, + 0, + 778, + 776, + 780, + 782, + 0, + 776, + 775, + 779, + 780, + 0, + 775, + 777, + 781, + 779, + 0, + 781, + 782, + 786, + 785, + 0, + 782, + 780, + 784, + 786, + 0, + 780, + 779, + 783, + 784, + 0, + 779, + 781, + 785, + 783, + 0, + 785, + 786, + 790, + 789, + 0, + 786, + 784, + 788, + 790, + 0, + 784, + 783, + 787, + 788, + 0, + 783, + 785, + 789, + 787, + 0, + 789, + 790, + 794, + 793, + 0, + 790, + 788, + 792, + 794, + 0, + 788, + 787, + 791, + 792, + 0, + 787, + 789, + 793, + 791, + 0, + 793, + 794, + 798, + 797, + 0, + 794, + 792, + 796, + 798, + 0, + 792, + 791, + 795, + 796, + 0, + 791, + 793, + 797, + 795, + 0, + 797, + 798, + 802, + 801, + 0, + 798, + 796, + 800, + 802, + 0, + 796, + 795, + 799, + 800, + 0, + 795, + 797, + 801, + 799, + 0, + 801, + 802, + 806, + 805, + 0, + 802, + 800, + 804, + 806, + 0, + 800, + 799, + 803, + 804, + 0, + 799, + 801, + 805, + 803, + 0, + 805, + 806, + 810, + 809, + 0, + 806, + 804, + 808, + 810, + 0, + 804, + 803, + 807, + 808, + 0, + 803, + 805, + 809, + 807, + 0, + 809, + 810, + 814, + 813, + 0, + 810, + 808, + 812, + 814, + 0, + 808, + 807, + 811, + 812, + 0, + 807, + 809, + 813, + 811, + 0, + 813, + 814, + 818, + 817, + 0, + 814, + 812, + 816, + 818, + 0, + 812, + 811, + 815, + 816, + 0, + 811, + 813, + 817, + 815, + 0, + 817, + 818, + 822, + 821, + 0, + 818, + 816, + 820, + 822, + 0, + 816, + 815, + 819, + 820, + 0, + 815, + 817, + 821, + 819, + 0, + 821, + 822, + 826, + 825, + 0, + 822, + 820, + 824, + 826, + 0, + 820, + 819, + 823, + 824, + 0, + 819, + 821, + 825, + 823, + 0, + 825, + 826, + 830, + 829, + 0, + 826, + 824, + 828, + 830, + 0, + 824, + 823, + 827, + 828, + 0, + 823, + 825, + 829, + 827, + 0, + 829, + 830, + 834, + 833, + 0, + 830, + 828, + 832, + 834, + 0, + 828, + 827, + 831, + 832, + 0, + 827, + 829, + 833, + 831, + 0, + 833, + 834, + 838, + 837, + 0, + 834, + 832, + 836, + 838, + 0, + 832, + 831, + 835, + 836, + 0, + 831, + 833, + 837, + 835, + 0, + 837, + 838, + 842, + 841, + 0, + 838, + 836, + 840, + 842, + 0, + 836, + 835, + 839, + 840, + 0, + 835, + 837, + 841, + 839, + 0, + 841, + 842, + 846, + 845, + 0, + 842, + 840, + 844, + 846, + 0, + 840, + 839, + 843, + 844, + 0, + 839, + 841, + 845, + 843, + 0, + 845, + 846, + 850, + 849, + 0, + 846, + 844, + 848, + 850, + 0, + 844, + 843, + 847, + 848, + 0, + 843, + 845, + 849, + 847, + 0, + 849, + 850, + 854, + 853, + 0, + 850, + 848, + 852, + 854, + 0, + 848, + 847, + 851, + 852, + 0, + 847, + 849, + 853, + 851, + 0, + 853, + 854, + 858, + 857, + 0, + 854, + 852, + 856, + 858, + 0, + 852, + 851, + 855, + 856, + 0, + 851, + 853, + 857, + 855, + 0, + 857, + 858, + 862, + 861, + 0, + 858, + 856, + 860, + 862, + 0, + 856, + 855, + 859, + 860, + 0, + 855, + 857, + 861, + 859, + 0, + 861, + 862, + 866, + 865, + 0, + 862, + 860, + 864, + 866, + 0, + 860, + 859, + 863, + 864, + 0, + 859, + 861, + 865, + 863, + 0, + 865, + 866, + 870, + 869, + 0, + 866, + 864, + 868, + 870, + 0, + 864, + 863, + 867, + 868, + 0, + 863, + 865, + 869, + 867, + 0, + 869, + 870, + 874, + 873, + 0, + 870, + 868, + 872, + 874, + 0, + 868, + 867, + 871, + 872, + 0, + 867, + 869, + 873, + 871, + 0, + 873, + 874, + 878, + 877, + 0, + 874, + 872, + 876, + 878, + 0, + 872, + 871, + 875, + 876, + 0, + 871, + 873, + 877, + 875, + 0, + 877, + 878, + 882, + 881, + 0, + 878, + 876, + 880, + 882, + 0, + 876, + 875, + 879, + 880, + 0, + 875, + 877, + 881, + 879, + 0, + 881, + 882, + 886, + 885, + 0, + 882, + 880, + 884, + 886, + 0, + 880, + 879, + 883, + 884, + 0, + 879, + 881, + 885, + 883, + 0, + 885, + 886, + 890, + 889, + 0, + 886, + 884, + 888, + 890, + 0, + 884, + 883, + 887, + 888, + 0, + 883, + 885, + 889, + 887, + 0, + 889, + 890, + 896, + 895, + 0, + 890, + 888, + 892, + 896, + 0, + 888, + 887, + 891, + 892, + 0, + 887, + 889, + 895, + 891, + 0, + 895, + 896, + 898, + 897, + 0, + 896, + 892, + 894, + 898, + 0, + 892, + 891, + 893, + 894, + 0, + 891, + 895, + 897, + 893, + 0, + 897, + 898, + 902, + 901, + 0, + 898, + 894, + 900, + 902, + 0, + 894, + 893, + 899, + 900, + 0, + 893, + 897, + 901, + 899, + 0, + 901, + 902, + 908, + 907, + 0, + 902, + 900, + 904, + 908, + 0, + 900, + 899, + 903, + 904, + 0, + 899, + 901, + 907, + 903, + 0, + 907, + 908, + 910, + 909, + 0, + 908, + 904, + 906, + 910, + 0, + 904, + 903, + 905, + 906, + 0, + 903, + 907, + 909, + 905, + 0, + 7, + 1, + 2, + 8, + 0, + 909, + 910, + 906, + 905, + 0, + 279, + 284, + 283, + 0, + 279, + 280, + 284, + 0, + 291, + 295, + 296, + 0, + 296, + 292, + 291, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/source.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/source.json index 9c55b2f69d2a..e492db09a0d8 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case1/source.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case1/source.json @@ -1 +1,5782 @@ -{"indexedMesh":{"point":[[232347.01132511083,3969797.7871081727,46.825095792426076],[232347.01132511083,3969797.7871081727,46.786995716426084],[232347.263926118,3969801.4283569604,46.752095792426076],[232347.263926118,3969801.4283569604,46.71399571642609],[232346.81012069722,3969797.8010661416,46.82235167169862],[232346.81012069722,3969797.8010661416,46.78425159569863],[232347.0627217044,3969801.4423149293,46.749351671698626],[232347.0627217044,3969801.4423149293,46.71125159569862],[232341.8221086598,3969798.1470949184,46.754322810028484],[232341.8221086598,3969798.1470949184,46.716222734028484],[232342.07470966692,3969801.788343706,46.681322810028476],[232342.07470966692,3969801.788343706,46.643222734028484],[232336.8340966224,3969798.4931236957,46.68629394835834],[232336.8340966224,3969798.4931236957,46.64819387235834],[232337.0866976295,3969802.1343724825,46.61329394835834],[232337.0866976295,3969802.1343724825,46.57519387235835],[232336.51620828634,3969798.515176272,46.681958437241846],[232336.51620828634,3969798.515176272,46.64385836124185],[232336.76880929348,3969802.1564250584,46.608958437241846],[232336.76880929348,3969802.1564250584,46.57085836124184],[232331.84608458492,3969798.839152472,46.61862856387353],[232331.84608458492,3969798.839152472,46.580528487873536],[232332.0986855921,3969802.48040126,46.54562856387353],[232332.0986855921,3969802.48040126,46.507528487873536],[232326.8580725475,3969799.1851812494,46.55179078325966],[232326.8580725475,3969799.1851812494,46.513690707259656],[232327.11067355468,3969802.826430037,46.47879078325966],[232327.11067355468,3969802.826430037,46.44069070725966],[232321.87006051006,3969799.5312100267,46.4857822906233],[232321.87006051006,3969799.5312100267,46.447682214623306],[232322.1226615172,3969803.1724588135,46.4127822906233],[232322.1226615172,3969803.1724588135,46.3746822146233],[232316.88204847265,3969799.877238803,46.42060308596445],[232316.88204847265,3969799.877238803,46.382503009964466],[232317.1346494798,3969803.5184875904,46.34760308596446],[232317.1346494798,3969803.5184875904,46.30950300996445],[232311.89403643523,3969800.22326758,46.356253169283136],[232311.89403643523,3969800.22326758,46.31815309328312],[232312.14663744235,3969803.8645163677,46.28325316928312],[232312.14663744235,3969803.8645163677,46.24515309328313],[232306.90602439776,3969800.569296357,46.29273254057931],[232306.90602439776,3969800.569296357,46.2546324645793],[232307.1586254049,3969804.210545144,46.21973254057931],[232307.1586254049,3969804.210545144,46.1816324645793],[232301.91801236034,3969800.9153251336,46.23004119985299],[232301.91801236034,3969800.9153251336,46.191941123853006],[232302.17061336752,3969804.5565739213,46.157041199853],[232302.17061336752,3969804.5565739213,46.11894112385299],[232296.93000032293,3969801.2613539104,46.16817914710422],[232296.93000032293,3969801.2613539104,46.130079071104205],[232297.18260133005,3969804.9026026977,46.095179147104204],[232297.18260133005,3969804.9026026977,46.05707907110421],[232291.9419882855,3969801.6073826877,46.10714638233292],[232291.9419882855,3969801.6073826877,46.06904630633293],[232292.19458929263,3969805.2486314746,46.03414638233293],[232292.19458929263,3969805.2486314746,45.99604630633293],[232286.95397624804,3969801.953411465,46.04694290553917],[232286.95397624804,3969801.953411465,46.00884282953916],[232287.20657725522,3969805.594660252,45.97394290553917],[232287.20657725522,3969805.594660252,45.93584282953916],[232281.96596421063,3969802.2994402414,45.98756871672291],[232281.96596421063,3969802.2994402414,45.949468640722905],[232282.2185652178,3969805.940689029,45.914568716722904],[232282.2185652178,3969805.940689029,45.87646864072291],[232276.97795217318,3969802.6454690187,45.92902381588418],[232276.97795217318,3969802.6454690187,45.890923739884165],[232277.23055318033,3969806.2867178055,45.856023815884164],[232277.23055318033,3969806.2867178055,45.817923739884165],[232271.98994013574,3969802.991497795,45.871308203022956],[232271.98994013574,3969802.991497795,45.83320812702294],[232272.2425411429,3969806.6327465824,45.79830820302294],[232272.2425411429,3969806.6327465824,45.76020812702294],[232267.00192809835,3969803.337526572,45.81442187813923],[232267.00192809835,3969803.337526572,45.776321802139236],[232267.25452910547,3969806.9787753597,45.741421878139235],[232267.25452910547,3969806.9787753597,45.70332180213923],[232262.01391606088,3969803.6835553492,45.75836484123303],[232262.01391606088,3969803.6835553492,45.72026476523304],[232262.26651706803,3969807.324804136,45.68536484123304],[232262.26651706803,3969807.324804136,45.64726476523304],[232257.02590402347,3969804.0295841256,45.70313709230435],[232257.02590402347,3969804.0295841256,45.665037016304346],[232257.27850503064,3969807.6708329134,45.630137092304345],[232257.27850503064,3969807.6708329134,45.592037016304346],[232252.03789198605,3969804.3756129025,45.64873863135318],[232252.03789198605,3969804.3756129025,45.610638555353184],[232252.29049299317,3969808.0168616897,45.57573863135319],[232252.29049299317,3969808.0168616897,45.537638555353176],[232247.04987994864,3969804.7216416798,45.59516945837954],[232247.04987994864,3969804.7216416798,45.557069382379524],[232247.30248095575,3969808.362890467,45.52216945837952],[232247.30248095575,3969808.362890467,45.48406938237952],[232242.06186791116,3969805.067670456,45.54242957338338],[232242.06186791116,3969805.067670456,45.504329497383374],[232242.31446891834,3969808.708919244,45.46942957338338],[232242.31446891834,3969808.708919244,45.43132949738337],[232237.07385587375,3969805.4136992334,45.49051897636476],[232237.07385587375,3969805.4136992334,45.45241890036475],[232237.32645688087,3969809.0549480203,45.41751897636475],[232237.32645688087,3969809.0549480203,45.37941890036475],[232232.0858438363,3969805.7597280107,45.43943766732363],[232232.0858438363,3969805.7597280107,45.401337591323625],[232232.33844484345,3969809.4009767985,45.36643766732363],[232232.33844484345,3969809.4009767985,45.328337591323624],[232227.09783179886,3969806.105756787,45.38918564626003],[232227.09783179886,3969806.105756787,45.35108557026003],[232227.35043280604,3969809.7470055744,45.316185646260024],[232227.35043280604,3969809.7470055744,45.27808557026003],[232222.10981976148,3969806.451785564,45.33976291317394],[232222.10981976148,3969806.451785564,45.30166283717394],[232222.3624207686,3969810.0930343517,45.26676291317395],[232222.3624207686,3969810.0930343517,45.228662837173935],[232217.121807724,3969806.7978143413,45.29116946806536],[232217.121807724,3969806.7978143413,45.25306939206536],[232217.37440873115,3969810.439063128,45.21816946806536],[232217.37440873115,3969810.439063128,45.180069392065356],[232212.1337956866,3969807.1438431176,45.2434053109343],[232212.1337956866,3969807.1438431176,45.20530523493429],[232212.38639669376,3969810.7850919054,45.17040531093429],[232212.38639669376,3969810.7850919054,45.13230523493431],[232207.14578364918,3969807.489871895,45.19647044178074],[232207.14578364918,3969807.489871895,45.15837036578075],[232207.3983846563,3969811.1311206827,45.12347044178074],[232207.3983846563,3969811.1311206827,45.085370365780754],[232202.1577716117,3969807.8359006722,45.150364860604704],[232202.1577716117,3969807.8359006722,45.11226478460471],[232202.41037261888,3969811.477149459,45.07736486060471],[232202.41037261888,3969811.477149459,45.03926478460471],[232197.1697595743,3969808.181929449,45.105088567406185],[232197.1697595743,3969808.181929449,45.06698849140619],[232197.42236058146,3969811.823178236,45.03208856740619],[232197.42236058146,3969811.823178236,44.99398849140619],[232192.18174753687,3969808.5279582255,45.060641562185175],[232192.18174753687,3969808.5279582255,45.02254148618517],[232192.434348544,3969812.169207013,44.98764156218517],[232192.434348544,3969812.169207013,44.94954148618517],[232187.19373549943,3969808.8739870028,45.017023844941676],[232187.19373549943,3969808.8739870028,44.97892376894169],[232187.44633650657,3969812.5152357896,44.94402384494168],[232187.44633650657,3969812.5152357896,44.905923768941676],[232182.20572346202,3969809.2200157787,44.9742354156757],[232182.20572346202,3969809.2200157787,44.936135339675694],[232182.45832446916,3969812.861264567,44.9012354156757],[232182.45832446916,3969812.861264567,44.863135339675694],[232177.2177114246,3969809.566044556,44.93227627438722],[232177.2177114246,3969809.566044556,44.89417619838723],[232177.47031243177,3969813.207293343,44.859276274387234],[232177.47031243177,3969813.207293343,44.82117619838722],[232172.22969938713,3969809.9120733333,44.89114642107627],[232172.22969938713,3969809.9120733333,44.85304634507627],[232172.4823003943,3969813.553322121,44.818146421076264],[232172.4823003943,3969813.553322121,44.78004634507627],[232167.2416873497,3969810.2581021097,44.850845855742826],[232167.2416873497,3969810.2581021097,44.81274577974284],[232167.49428835683,3969813.8993508974,44.77784585574283],[232167.49428835683,3969813.8993508974,44.73974577974283],[232162.2536753123,3969810.604130888,44.811374578386896],[232162.2536753123,3969810.604130888,44.773274502386904],[232162.50627631947,3969814.245379674,44.7383745783869],[232162.50627631947,3969814.245379674,44.7002745023869],[232157.26566327483,3969810.9501596643,44.772732589008484],[232157.26566327483,3969810.9501596643,44.73463251300848],[232157.518264282,3969814.591408452,44.699732589008484],[232157.518264282,3969814.591408452,44.661632513008485],[232152.27765123744,3969811.296188441,44.734919887607575],[232152.27765123744,3969811.296188441,44.69681981160758],[232152.53025224459,3969814.937437228,44.661919887607574],[232152.53025224459,3969814.937437228,44.62381981160758],[232147.2896392,3969811.6422172175,44.697936474184196],[232147.2896392,3969811.6422172175,44.6598363981842],[232147.54224020717,3969815.283466005,44.624936474184196],[232147.54224020717,3969815.283466005,44.58683639818419],[232142.3016271626,3969811.988245995,44.66178234873831],[232142.3016271626,3969811.988245995,44.62368227273833],[232142.55422816973,3969815.6294947816,44.58878234873832],[232142.55422816973,3969815.6294947816,44.550682272738314],[232137.31361512514,3969812.334274771,44.626457511269955],[232137.31361512514,3969812.334274771,44.588357435269955],[232137.5662161323,3969815.975523559,44.55345751126995],[232137.5662161323,3969815.975523559,44.515357435269955],[232132.32560308767,3969812.680303548,44.591961961779106],[232132.32560308767,3969812.680303548,44.5538618857791],[232132.5782040948,3969816.3215523358,44.5189619617791],[232132.5782040948,3969816.3215523358,44.480861885779106],[232131.43967678156,3969812.7417621,44.585921894890866],[232131.43967678156,3969812.7417621,44.54782181889087],[232131.6922777887,3969816.3830108875,44.51292189489087],[232131.6922777887,3969816.3830108875,44.47482181889088],[232127.3375910503,3969813.0263323253,44.55801526679104],[232127.3375910503,3969813.0263323253,44.51991519079105],[232127.59019205743,3969816.667581113,44.485015266791045],[232127.59019205743,3969816.667581113,44.44691519079104],[232122.34957901284,3969813.3723611026,44.52408165203908],[232122.34957901284,3969813.3723611026,44.48598157603907],[232122.60218002,3969817.0136098894,44.45108165203908],[232122.60218002,3969817.0136098894,44.41298157603907],[232117.36156697542,3969813.718389879,44.490148037287106],[232117.36156697542,3969813.718389879,44.45204796128711],[232117.6141679826,3969817.3596386667,44.417148037287106],[232117.6141679826,3969817.3596386667,44.379047961287114],[232112.373554938,3969814.0644186554,44.45621442253513],[232112.373554938,3969814.0644186554,44.418114346535134],[232112.62615594512,3969817.705667443,44.38321442253513],[232112.62615594512,3969817.705667443,44.34511434653515],[232107.38554290053,3969814.410447432,44.422280807783174],[232107.38554290053,3969814.410447432,44.38418073178317],[232107.6381439077,3969818.05169622,44.349280807783174],[232107.6381439077,3969818.05169622,44.311180731783175],[232102.39753086315,3969814.7564762104,44.388347193031215],[232102.39753086315,3969814.7564762104,44.3502471170312],[232102.6501318703,3969818.3977249963,44.3153471930312],[232102.6501318703,3969818.3977249963,44.2772471170312],[232099.09678878385,3969814.985455558,44.36589213292445],[232099.09678878385,3969814.985455558,44.327792056924444],[232099.34938979102,3969818.626704345,44.29289213292445],[232099.34938979102,3969818.626704345,44.25479205692446],[232097.40951882568,3969815.102504987,44.3544828295275],[232097.40951882568,3969815.102504987,44.31638275352751],[232097.66211983282,3969818.7437537746,44.281482829527505],[232097.66211983282,3969818.7437537746,44.2433827535275],[232092.42150678826,3969815.448533763,44.32156388468146],[232092.42150678826,3969815.448533763,44.28346380868147],[232092.6741077954,3969819.089782551,44.248563884681474],[232092.6741077954,3969819.089782551,44.21046380868146],[232087.43349475085,3969815.7945625405,44.28985538031647],[232087.43349475085,3969815.7945625405,44.25175530431648],[232087.68609575796,3969819.4358113282,44.216855380316474],[232087.68609575796,3969819.4358113282,44.17875530431647],[232082.44548271337,3969816.1405913173,44.259357316432514],[232082.44548271337,3969816.1405913173,44.22125724043253],[232082.69808372055,3969819.781840105,44.18635731643252],[232082.69808372055,3969819.781840105,44.148257240432514],[232077.45747067596,3969816.4866200946,44.23006969302961],[232077.45747067596,3969816.4866200946,44.1919696170296],[232077.71007168313,3969820.1278688814,44.1570696930296],[232077.71007168313,3969820.1278688814,44.118969617029606],[232072.46945863854,3969816.832648871,44.20199251010773],[232072.46945863854,3969816.832648871,44.16389243410773],[232072.72205964566,3969820.4738976588,44.12899251010773],[232072.72205964566,3969820.4738976588,44.090892434107744],[232067.48144660107,3969817.1786776483,44.175125767666906],[232067.48144660107,3969817.1786776483,44.1370256916669],[232067.73404760825,3969820.819926435,44.1021257676669],[232067.73404760825,3969820.819926435,44.0640256916669],[232062.49343456366,3969817.5247064247,44.149469465707114],[232062.49343456366,3969817.5247064247,44.11136938970711],[232062.74603557083,3969821.165955212,44.07646946570711],[232062.74603557083,3969821.165955212,44.038369389707114],[232057.5054225262,3969817.8707352015,44.12502360422836],[232057.5054225262,3969817.8707352015,44.08692352822836],[232057.75802353336,3969821.5119839893,44.05202360422836],[232057.75802353336,3969821.5119839893,44.01392352822837],[232052.51741048877,3969818.216763979,44.10178818323067],[232052.51741048877,3969818.216763979,44.06368810723066],[232052.77001149594,3969821.8580127656,44.02878818323065],[232052.77001149594,3969821.8580127656,43.99068810723065],[232047.52939845138,3969818.562792756,44.07976320271399],[232047.52939845138,3969818.562792756,44.041663126713985],[232047.7819994585,3969822.204041543,44.006763202713984],[232047.7819994585,3969822.204041543,43.96866312671399],[232042.5413864139,3969818.9088215325,44.05894866267837],[232042.5413864139,3969818.9088215325,44.020848586678376],[232042.79398742106,3969822.5500703203,43.98594866267837],[232042.79398742106,3969822.5500703203,43.94784858667836],[232037.5533743765,3969819.2548503093,44.03934456312378],[232037.5533743765,3969819.2548503093,44.001244487123785],[232037.80597538367,3969822.896099097,43.966344563123776],[232037.80597538367,3969822.896099097,43.928244487123784],[232036.84953653693,3969819.303677005,44.036675759956545],[232036.84953653693,3969819.303677005,43.998575683956545],[232037.10213754408,3969822.944925793,43.96367575995655],[232037.10213754408,3969822.944925793,43.92557568395655],[232032.56536233908,3969819.6008790866,44.02095090405023],[232032.56536233908,3969819.6008790866,43.98285082805024],[232032.8179633462,3969823.2421278735,43.969423256992165],[232032.8179633462,3969823.2421278735,43.93132318099216],[232027.5773503016,3969819.946907863,44.00376768545774],[232027.5773503016,3969819.946907863,43.965667609457746],[232027.82995130878,3969823.588156651,43.97724003839971],[232027.82995130878,3969823.588156651,43.9391399623997],[232022.5893382642,3969820.2929366403,43.98779490734628],[232022.5893382642,3969820.2929366403,43.94969483134627],[232022.84193927137,3969823.934185427,43.98626726028814],[232022.84193927137,3969823.934185427,43.94816718428813],[232022.28454138056,3969820.3140810337,43.98685811901272],[232022.28454138056,3969820.3140810337,43.94875804301272],[232022.53714238774,3969823.9553298205,43.98685811901272],[232022.53714238774,3969823.9553298205,43.94875804301272],[232017.60089607674,3969820.6326835407,43.973032569715855],[232017.60089607674,3969820.6326835407,43.93493249371585],[232017.84372833796,3969824.2745968415,43.996504922657756],[232017.84372833796,3969824.2745968415,43.95840484665774],[232012.61150532452,3969820.958202994,43.959480672566464],[232012.61150532452,3969820.958202994,43.92138059656648],[232012.84393114215,3969824.600795235,44.00795302550832],[232012.84393114215,3969824.600795235,43.96985294950832],[232007.7155003888,3969821.2637168565,43.9473611777864],[232007.7155003888,3969821.2637168565,43.90926110178639],[232007.93771453897,3969824.906946313,44.02036117778651],[232007.62120488277,3969821.2694657366,43.947139215898126],[232007.93771453897,3969824.906946313,43.982261101786506],[232007.62120488277,3969821.2694657366,43.909039139898134],[232007.84322235952,3969824.912707183,44.02061156883998],[232007.84322235952,3969824.912707183,43.98251149283999],[232006.31806336567,3969821.3483907105,43.94411607719644],[232006.31806336567,3969821.3483907105,43.90601600119643],[232006.53736286156,3969824.991796773,44.0241160771958],[232006.53736286156,3969824.991796773,43.986016001195814],[232002.63003548872,3969821.566469226,43.93600819971083],[232002.63003548872,3969821.566469226,43.89790812371083],[232002.84164281213,3969825.210330137,44.03448055265281],[232002.84164281213,3969825.210330137,43.99638047665281],[231997.63803788653,3969821.8492110386,43.92608762400457],[231997.63803788653,3969821.8492110386,43.88798754800458],[231997.83923332926,3969825.4936616695,44.0495599769465],[231997.83923332926,3969825.4936616695,44.01145990094651],[231992.64525282718,3969822.1176888673,43.91737748877936],[231992.64525282718,3969822.1176888673,43.879277412779366],[231992.83603474675,3969825.7626994653,44.06584984172125],[231992.83603474675,3969825.7626994653,44.02774976572125],[231990.34279626585,3969822.2366799647,43.913768945905794],[231990.34279626585,3969822.2366799647,43.8756688699058],[231990.52877591894,3969825.8819387443,44.07376894590464],[231990.52877591894,3969825.8819387443,44.035668869904626],[231987.65172106802,3969822.371900519,43.90987779403519],[231987.65172106802,3969822.371900519,43.87177771803518],[231987.8320879071,3969826.0174413295,44.083350146977146],[231987.8320879071,3969826.0174413295,44.04525007097714],[231982.6574833726,3969822.611843919,43.903588539772045],[231982.6574833726,3969822.611843919,43.86548846377205],[231982.82743365876,3969826.2578851823,44.102060892714015],[231982.82743365876,3969826.2578851823,44.063960816714015],[231981.6775772967,3969822.6572443377,43.90249667647098],[231981.6775772967,3969822.6572443377,43.86439660047098],[231981.84548377877,3969826.3033802942,44.105873815700015],[231981.84548377877,3969826.3033802942,44.06777373970001],[231977.6625805102,3969822.8375171074,43.89850972598996],[231977.6625805102,3969822.8375171074,43.860409649989954],[231977.8221128561,3969826.484029061,44.10188686521898],[231977.8221128561,3969826.484029061,44.06378678921899],[231974.36007547379,3969822.978874542,43.89581672514083],[231974.36007547379,3969822.978874542,43.85771664914085],[231974.51271973774,3969826.625681328,44.099193864369866],[231974.51271973774,3969826.625681328,44.06109378836987],[231972.66705325549,3969823.0489182444,43.8946413526889],[231972.66705325549,3969823.0489182444,43.85654127668891],[231972.81616635883,3969826.695871121,44.09801849191794],[231972.81616635883,3969826.695871121,44.05991841591793],[231967.6709423882,3969823.246045602,43.89198341986889],[231967.6709423882,3969823.246045602,43.853883343868894],[231967.80963503176,3969826.89340963,44.09536055909793],[231967.80963503176,3969826.89340963,44.05726048309792],[231962.67428869297,3969823.4288975727,43.89053592752993],[231962.67428869297,3969823.4288975727,43.85243585152993],[231962.80255974457,3969827.0766429775,44.09391306675895],[231962.80255974457,3969827.0766429775,44.05581299075896],[231958.3712370051,3969823.574912402,43.89025941490154],[231958.3712370051,3969823.574912402,43.85215933890154],[231958.49053312026,3969827.222962352,44.09363655413057],[231958.49053312026,3969827.222962352,44.05553647813056],[231957.67713295875,3969823.5974726626,43.890298875672],[231957.67713295875,3969823.5974726626,43.852198799671996],[231957.79498137117,3969827.2455696664,44.09367601490102],[231957.79498137117,3969827.2455696664,44.055575938901036],[231952.67951597858,3969823.7517694957,43.89127226429511],[231952.67951597858,3969823.7517694957,43.853172188295105],[231952.7869407899,3969827.400188319,44.09464940352413],[231952.7869407899,3969827.400188319,44.056549327524145],[231947.68147854935,3969823.8917868137,43.89345609339926],[231947.68147854935,3969823.8917868137,43.85535601739927],[231947.7784788826,3969827.540497673,44.09683323262829],[231947.7784788826,3969827.540497673,44.058733156628286],[231942.68306147133,3969824.017523472,43.89685036298445],[231942.68306147133,3969824.017523472,43.85875028698446],[231942.7696365347,3969827.6664965823,44.100227502213485],[231942.7696365347,3969827.6664965823,44.06212742621348],[231942.37761738684,3969824.0247437214,43.89709701518792],[231942.37761738684,3969824.0247437214,43.85899693918792],[231942.4635553811,3969827.6737318896,44.100474154416936],[231942.4635553811,3969827.6737318896,44.06237407841695],[231937.6843055479,3969824.1289784457,43.901455073050684],[231937.6843055479,3969824.1289784457,43.86335499705069],[231937.76045463458,3969827.778184018,44.104832212279725],[231937.76045463458,3969827.778184018,44.06673213627971],[231935.05473618413,3969824.181873632,43.90436306506987],[231935.05473618413,3969824.181873632,43.86626298906988],[231935.12540074045,3969827.8311895295,44.107740204298906],[231935.12540074045,3969827.8311895295,44.0696401282989],[231932.68525158515,3969824.226150823,43.90727022359796],[231932.68525158515,3969824.226150823,43.86917014759797],[231932.7509740736,3969827.87555907,44.09879787065106],[231932.7509740736,3969827.87555907,44.06069779465106],[231927.6859403918,3969824.309039812,43.91429581462628],[231927.6859403918,3969824.309039812,43.87619573862628],[231927.7412357454,3969827.958620942,44.0808234616794],[231927.7412357454,3969827.958620942,44.04272338567941],[231926.38055354578,3969824.3283308963,43.91632952599996],[231926.38055354578,3969824.3283308963,43.878229449999964],[231926.43312623544,3969827.9779522615,44.07632952599877],[231926.43312623544,3969827.9779522615,44.03822944999877],[231922.6864127783,3969824.377644737,43.92253184613564],[231922.6864127783,3969824.377644737,43.88443177013564],[231922.73128054582,3969828.027368957,44.06405949318883],[231922.73128054582,3969828.027368957,44.02595941718883],[231917.6867095573,3969824.4319650354,43.93197831812604],[231917.6867095573,3969824.4319650354,43.89387824212604],[231917.72114937234,3969828.081802552,44.04850596517924],[231917.72114937234,3969828.081802552,44.010405889179225],[231912.68687154257,3969824.4720002664,43.942635230597475],[231912.68687154257,3969824.4720002664,43.90453515459749],[231912.71088312403,3969828.1219212846,44.03416287765059],[231912.71088312403,3969828.1219212846,43.99606280165058],[231910.3813826965,3969824.4856485515,43.947956947337666],[231910.3813826965,3969824.4856485515,43.90985687133767],[231910.400585687,3969828.1355980365,44.02795694733703],[231910.400585687,3969828.1355980365,43.98985687133703],[231908.98139927528,3969824.4924540888,43.95131407330675],[231908.98139927528,3969824.4924540888,43.91321399730674],[231908.99768230034,3969828.142417769,44.024314073306854],[231908.99768230034,3969828.142417769,43.98621399730685],[231907.68693954908,3969824.4977501007,43.95450258354995],[231907.68693954908,3969824.4977501007,43.916402507549954],[231907.70052270102,3969828.1477248264,44.02103023060307],[231907.70052270102,3969828.1477248264,43.982930154603075],[231902.68695439264,3969824.5092143305,43.96758037698347],[231902.68695439264,3969824.5092143305,43.92948030098347],[231902.6901090041,3969828.159212967,44.00910802403662],[231902.6901090041,3969828.159212967,43.971007948036636],[231897.6869568894,3969824.50639286,43.98186861089804],[231897.6869568894,3969824.50639286,43.94376853489804],[231897.67968293463,3969828.1563856127,43.99839625795123],[231897.67968293463,3969828.1563856127,43.960296181951236],[231894.38144222982,3969824.496683535,43.99197927920104],[231894.38144222982,3969824.496683535,43.953879203201055],[231894.36727391588,3969828.1466560364,43.99197927920104],[231894.36727391588,3969828.1466560364,43.953879203201055],[231892.68698440643,3969824.490106059,43.99736728529365],[231892.68698440643,3969824.490106059,43.95926720929364],[231892.6728160925,3969828.14007856,43.98889493234681],[231892.6728160925,3969828.14007856,43.95079485634681],[231887.6870220762,3969824.4706974085,44.01407640017029],[231887.6870220762,3969824.4706974085,43.9759763241703],[231887.6728537622,3969828.1206699107,43.98060404722341],[231887.6728537622,3969828.1206699107,43.942503971223395],[231882.6870597459,3969824.4512887597,44.031995955527975],[231882.6870597459,3969824.4512887597,43.99389587952797],[231882.67289143192,3969828.1012612614,43.97352360258118],[231882.67289143192,3969828.1012612614,43.93542352658119],[231879.78155222532,3969824.4400102794,44.042965184812765],[231879.78155222532,3969824.4400102794,44.00486510881276],[231879.76738391138,3969828.0899827806,43.969965184812764],[231879.76738391138,3969828.0899827806,43.93186510881276],[231877.68709741556,3969824.4318801104,44.05112595136669],[231877.68709741556,3969824.4318801104,44.013025875366694],[231877.67292910168,3969828.0818526116,43.97812595136669],[231877.67292910168,3969828.0818526116,43.9400258753667],[231872.68713508526,3969824.4124714616,44.07146638768647],[231872.68713508526,3969824.4124714616,44.033366311686464],[231872.67296677132,3969828.0624439623,43.99846638768647],[231872.67296677132,3969828.0624439623,43.960366311686464],[231867.68717275502,3969824.3930628123,44.09301726448727],[231867.68717275502,3969824.3930628123,44.054917188487266],[231867.67300444108,3969828.043035313,44.020017264487265],[231867.67300444108,3969828.043035313,43.98191718848727],[231862.68721042472,3969824.373654163,44.115778581769135],[231862.68721042472,3969824.373654163,44.07767850576912],[231862.67304211075,3969828.023626664,44.04277858176912],[231862.67304211075,3969828.023626664,44.00467850576912],[231857.6872480944,3969824.3542455127,44.139750339532014],[231857.6872480944,3969824.3542455127,44.101650263532015],[231857.67307978045,3969828.004218015,44.066750339532014],[231857.67307978045,3969828.004218015,44.02865026353201],[231852.68728576408,3969824.334836864,44.16493253777594],[231852.68728576408,3969824.334836864,44.126832461775955],[231852.6731174502,3969827.984809365,44.091932537775946],[231852.6731174502,3969827.984809365,44.05383246177594],[231847.68732343384,3969824.315428215,44.19132517650092],[231847.68732343384,3969824.315428215,44.15322510050091],[231847.6731551199,3969827.9654007168,44.11832517650092],[231847.6731551199,3969827.9654007168,44.08022510050092],[231842.68736110354,3969824.296019566,44.21892825570693],[231842.68736110354,3969824.296019566,44.180828179706936],[231842.67319278957,3969827.9459920665,44.14592825570692],[231842.67319278957,3969827.9459920665,44.10782817970692],[231837.6873987732,3969824.2766109165,44.247741775393976],[231837.6873987732,3969824.2766109165,44.209641699393984],[231837.67323045927,3969827.9265834177,44.17474177539398],[231837.67323045927,3969827.9265834177,44.136641699393984],[231832.68743644297,3969824.2572022676,44.27776573556207],[231832.68743644297,3969824.2572022676,44.23966565956208],[231832.67326812903,3969827.9071747684,44.20476573556207],[231832.67326812903,3969827.9071747684,44.16666565956208],[231827.68747411267,3969824.2377936174,44.30900013621121],[231827.68747411267,3969824.2377936174,44.27090006021121],[231827.67330579873,3969827.8877661196,44.23600013621122],[231827.67330579873,3969827.8877661196,44.19790006021122],[231822.68751178237,3969824.2183849686,44.34144497734138],[231822.68751178237,3969824.2183849686,44.30334490134138],[231822.6733434684,3969827.8683574703,44.26844497734138],[231822.6733434684,3969827.8683574703,44.2303449013414],[231817.68754945206,3969824.1989763193,44.3751002589526],[231817.68754945206,3969824.1989763193,44.337000182952615],[231817.67338113816,3969827.8489488205,44.302100258952606],[231817.67338113816,3969827.8489488205,44.2640001829526],[231812.6875871218,3969824.17956767,44.40996598104487],[231812.6875871218,3969824.17956767,44.37186590504487],[231812.67341880786,3969827.829540171,44.33696598104487],[231812.67341880786,3969827.829540171,44.29886590504486],[231807.6876247915,3969824.160159021,44.44604214361816],[231807.6876247915,3969824.160159021,44.40794206761816],[231807.67345647755,3969827.810131522,44.37304214361816],[231807.67345647755,3969827.810131522,44.33494206761817],[231802.68766246125,3969824.140750372,44.4833287466725],[231802.68766246125,3969824.140750372,44.44522867067251],[231802.67349414725,3969827.790722873,44.410328746672505],[231802.67349414725,3969827.790722873,44.3722286706725],[231797.68770013095,3969824.121341723,44.521825790207885],[231797.68770013095,3969824.121341723,44.483725714207885],[231797.67353181698,3969827.7713142238,44.448825790207884],[231797.67353181698,3969827.7713142238,44.4107257142079],[231792.68773780062,3969824.1019330737,44.56153327422431],[231792.68773780062,3969824.1019330737,44.52343319822431],[231792.67356948668,3969827.751905575,44.4885332742243],[231792.67356948668,3969827.751905575,44.45043319822431],[231787.68777547032,3969824.082524424,44.60245119872178],[231787.68777547032,3969824.082524424,44.56435112272177],[231787.67360715638,3969827.7324969256,44.529451198721766],[231787.67360715638,3969827.7324969256,44.49135112272177],[231782.68781314002,3969824.0631157747,44.644579563700276],[231782.68781314002,3969824.0631157747,44.60647948770028],[231782.67364482608,3969827.7130882763,44.57157956370029],[231782.67364482608,3969827.7130882763,44.533479487700276],[231777.68785080977,3969824.0437071254,44.687918369159824],[231777.68785080977,3969824.0437071254,44.64981829315983],[231777.6736824958,3969827.6936796266,44.614918369159824],[231777.6736824958,3969827.6936796266,44.57681829315982],[231772.68788847944,3969824.0242984765,44.732467615100404],[231772.68788847944,3969824.0242984765,44.69436753910041],[231772.6737201655,3969827.6742709773,44.65946761510041],[231772.6737201655,3969827.6742709773,44.62136753910041],[231767.68792614914,3969824.004889827,44.77822730152203],[231767.68792614914,3969824.004889827,44.74012722552204],[231767.67375783526,3969827.6548623284,44.70522730152203],[231767.67375783526,3969827.6548623284,44.667127225522044],[231762.68796381884,3969823.985481178,44.82519742842471],[231762.68796381884,3969823.985481178,44.7870973524247],[231762.6737955049,3969827.635453679,44.75219742842471],[231762.6737955049,3969827.635453679,44.71409735242471],[231757.6880014886,3969823.966072529,44.87337799580842],[231757.6880014886,3969823.966072529,44.83527791980842],[231757.67383317463,3969827.61604503,44.80037799580841],[231757.67383317463,3969827.61604503,44.76227791980842],[231752.68803915827,3969823.94666388,44.92276900367316],[231752.68803915827,3969823.94666388,44.88466892767317],[231752.67387084433,3969827.596636381,44.84976900367317],[231752.67387084433,3969827.596636381,44.81166892767317],[231747.68807682797,3969823.927255231,44.973370452018955],[231747.68807682797,3969823.927255231,44.935270376018956],[231747.67390851403,3969827.5772277317,44.900370452018954],[231747.67390851403,3969827.5772277317,44.86227037601895],[231742.68811449772,3969823.9078465807,45.02518234084579],[231742.68811449772,3969823.9078465807,44.98708226484579],[231742.6739461838,3969827.557819082,44.95218234084578],[231742.6739461838,3969827.557819082,44.91408226484579],[231737.68815216742,3969823.8884379314,45.07820467015365],[231737.68815216742,3969823.8884379314,45.040104594153654],[231737.67398385346,3969827.5384104326,45.00520467015366],[231737.67398385346,3969827.5384104326,44.96710459415366],[231732.68818983712,3969823.8690292826,45.13243743994258],[231732.68818983712,3969823.8690292826,45.09433736394257],[231732.67402152315,3969827.5190017833,45.05943743994257],[231732.67402152315,3969827.5190017833,45.02133736394258],[231727.68822750685,3969823.8496206333,45.18788065021253],[231727.68822750685,3969823.8496206333,45.14978057421254],[231727.6740591929,3969827.4995931336,45.114880650212534],[231727.6740591929,3969827.4995931336,45.07678057421253],[231722.68826517655,3969823.8302119835,45.24453430096352],[231722.68826517655,3969823.8302119835,45.20643422496353],[231722.6740968626,3969827.480184485,45.17153430096353],[231722.6740968626,3969827.480184485,45.13343422496352],[231717.68830284625,3969823.810803334,45.302398392195556],[231717.68830284625,3969823.810803334,45.26429831619556],[231717.67413453228,3969827.4607758354,45.22939839219556],[231717.67413453228,3969827.4607758354,45.19129831619557],[231712.688340516,3969823.7913946854,45.361472923908636],[231712.688340516,3969823.7913946854,45.323372847908644],[231712.67417220204,3969827.441367187,45.28847292390865],[231712.67417220204,3969827.441367187,45.250372847908636],[231707.68837818567,3969823.771986036,45.421757896102754],[231707.68837818567,3969823.771986036,45.38365782010277],[231707.67420987174,3969827.4219585373,45.34875789610276],[231707.67420987174,3969827.4219585373,45.310657820102755],[231702.68841585537,3969823.752577387,45.48325330877792],[231702.68841585537,3969823.752577387,45.44515323277791],[231702.67424754144,3969827.402549889,45.41025330877792],[231702.67424754144,3969827.402549889,45.37215323277792],[231697.68845352507,3969823.733168738,45.54595916193413],[231697.68845352507,3969823.733168738,45.507859085934115],[231697.67428521113,3969827.3831412387,45.472959161934114],[231697.67428521113,3969827.3831412387,45.43485908593412],[231692.68849119483,3969823.7137600887,45.60987545557136],[231692.68849119483,3969823.7137600887,45.571775379571356],[231692.67432288086,3969827.36373259,45.536875455571355],[231692.67432288086,3969827.36373259,45.498775379571356],[231687.6885288645,3969823.69435144,45.675002189689636],[231687.6885288645,3969823.69435144,45.63690211368964],[231687.67436055056,3969827.3443239406,45.602002189689635],[231687.67436055056,3969827.3443239406,45.56390211368965],[231682.6885665342,3969823.6749427896,45.74133936428896],[231682.6885665342,3969823.6749427896,45.70323928828896],[231682.67439822032,3969827.324915291,45.66833936428897],[231682.67439822032,3969827.324915291,45.630239288288976],[231677.6886042039,3969823.6555341403,45.808886979369326],[231677.6886042039,3969823.6555341403,45.770786903369334],[231677.67443588996,3969827.3055066415,45.73588697936933],[231677.67443588996,3969827.3055066415,45.69778690336933],[231672.6886418736,3969823.6361254915,45.877645034930744],[231672.6886418736,3969823.6361254915,45.83954495893073],[231672.6744735597,3969827.286097992,45.80464503493073],[231672.6744735597,3969827.286097992,45.76654495893073],[231667.68867954332,3969823.616716842,45.94761353097318],[231667.68867954332,3969823.616716842,45.90951345497319],[231667.6745112294,3969827.2666893434,45.87461353097319],[231667.6745112294,3969827.2666893434,45.83651345497318],[231662.68871721302,3969823.5973081933,46.018792467496674],[231662.68871721302,3969823.5973081933,45.980692391496675],[231662.6745488991,3969827.247280694,45.945792467496666],[231662.6745488991,3969827.247280694,45.90769239149668],[231657.68875488272,3969823.577899543,46.09118184450119],[231657.68875488272,3969823.577899543,46.053081768501194],[231657.67458656884,3969827.2278720452,46.01818184450119],[231657.67458656884,3969827.2278720452,45.9800817685012],[231652.68879255248,3969823.5584908947,46.164781661986765],[231652.68879255248,3969823.5584908947,46.12668158598677],[231652.6746242385,3969827.208463396,46.09178166198678],[231652.6746242385,3969827.208463396,46.053681585986766],[231647.68883022218,3969823.539082245,46.23959191995337],[231647.68883022218,3969823.539082245,46.20149184395337],[231647.6746619082,3969827.1890547466,46.16659191995337],[231647.6746619082,3969827.1890547466,46.128491843953384],[231642.68886789185,3969823.5196735957,46.31561261840104],[231642.68886789185,3969823.5196735957,46.27751254240103],[231642.6746995779,3969827.169646098,46.242612618401026],[231642.6746995779,3969827.169646098,46.20451254240103],[231637.6889055616,3969823.500264947,46.392843757329715],[231637.6889055616,3969823.500264947,46.35474368132972],[231637.67473724767,3969827.1502374476,46.31984375732973],[231637.67473724767,3969827.1502374476,46.281743681329715],[231632.6889432313,3969823.4808562975,46.47128533673945],[231632.6889432313,3969823.4808562975,46.43318526073946],[231632.67477491734,3969827.1308287983,46.398285336739455],[231632.67477491734,3969827.1308287983,46.360185260739456],[231627.68898090097,3969823.4614476482,46.55093735663023],[231627.68898090097,3969823.4614476482,46.51283728063022],[231627.67481258704,3969827.1114201494,46.47793735663023],[231627.67481258704,3969827.1114201494,46.43983728063023],[231622.68901857073,3969823.4420389994,46.63179981700204],[231622.68901857073,3969823.4420389994,46.593699741002055],[231622.6748502568,3969827.0920115,46.55879981700205],[231622.6748502568,3969827.0920115,46.52069974100204],[231617.68905624043,3969823.42263035,46.7138727178549],[231617.68905624043,3969823.42263035,46.6757726418549],[231617.6748879265,3969827.0726028513,46.640872717854904],[231617.6748879265,3969827.0726028513,46.60277264185491],[231612.68909391013,3969823.4032217003,46.79715605918881],[231612.68909391013,3969823.4032217003,46.759055983188794],[231612.6749255962,3969827.053194201,46.72415605918879],[231612.6749255962,3969827.053194201,46.686055983188794],[231607.6891315799,3969823.383813051,46.881649841003735],[231607.6891315799,3969823.383813051,46.84354976500373],[231607.67496326592,3969827.0337855523,46.80864984100373],[231607.67496326592,3969827.0337855523,46.770549765003736],[231602.68916924956,3969823.364404402,46.96735406329972],[231602.68916924956,3969823.364404402,46.92925398729971],[231602.67500093562,3969827.014376903,46.89435406329971],[231602.67500093562,3969827.014376903,46.85625398729971],[231597.68920691925,3969823.344995752,47.05426872607673],[231597.68920691925,3969823.344995752,47.016168650076736],[231597.67503860532,3969826.9949682537,46.98126872607673],[231597.67503860532,3969826.9949682537,46.943168650076736],[231592.68924458895,3969823.3255871036,47.142393829334786],[231592.68924458895,3969823.3255871036,47.104293753334794],[231592.67507627502,3969826.975559605,47.0693938293348],[231592.67507627502,3969826.975559605,47.031293753334786],[231587.68928225865,3969823.306178454,47.2317293730739],[231587.68928225865,3969823.306178454,47.19362929707389],[231587.67511394474,3969826.9561509555,47.15872937307389],[231587.67511394474,3969826.9561509555,47.12062929707389],[231582.68931992838,3969823.2867698045,47.32227535729403],[231582.68931992838,3969823.2867698045,47.28417528129403],[231582.67515161444,3969826.9367423067,47.24927535729403],[231582.67515161444,3969826.9367423067,47.21117528129404],[231577.68935759808,3969823.2673611557,47.41403178199523],[231577.68935759808,3969823.2673611557,47.37593170599522],[231577.67518928414,3969826.9173336574,47.34103178199522],[231577.67518928414,3969826.9173336574,47.30293170599522],[231572.68939526778,3969823.2479525064,47.50699864717744],[231572.68939526778,3969823.2479525064,47.468898571177455],[231572.6752269539,3969826.8979250076,47.43399864717745],[231572.6752269539,3969826.8979250076,47.39589857117744],[231567.68943293748,3969823.228543857,47.60117595284071],[231567.68943293748,3969823.228543857,47.56307587684072],[231567.67526462357,3969826.8785163583,47.52817595284071],[231567.67526462357,3969826.8785163583,47.490075876840706],[231564.38078293134,3969823.2157004746,47.66416188818293],[231564.38078293134,3969823.2157004746,47.626061812182925],[231564.3666146174,3969826.8656729762,47.59116188818293],[231564.3666146174,3969826.8656729762,47.553061812182925],[231562.6894706072,3969823.2091352083,47.69649444773677],[231562.6894706072,3969823.2091352083,47.65839437173678],[231562.67530229327,3969826.859107709,47.623494447736775],[231562.67530229327,3969826.859107709,47.58539437173677],[231557.6895082769,3969823.189726559,47.79207796445618],[231557.6895082769,3969823.189726559,47.753977888456184],[231557.67533996297,3969826.83969906,47.71907796445618],[231557.67533996297,3969826.83969906,47.68097788845619],[231552.6895459466,3969823.170317909,47.887661481175606],[231552.6895459466,3969823.170317909,47.849561405175606],[231552.67537763267,3969826.82029041,47.81466148117561],[231552.67537763267,3969826.82029041,47.7765614051756],[231547.6895836163,3969823.15090926,47.983244997895014],[231547.6895836163,3969823.15090926,47.945144921895015],[231547.6754153024,3969826.8008817616,47.91024499789501],[231547.6754153024,3969826.8008817616,47.87214492189503],[231542.68962128603,3969823.131500611,48.078828514614436],[231542.68962128603,3969823.131500611,48.040728438614444],[231542.6754529721,3969826.781473112,48.00582851461445],[231542.6754529721,3969826.781473112,47.96772843861444],[231537.6896589558,3969823.1120919613,48.17441203133386],[231537.6896589558,3969823.1120919613,48.136311955333845],[231537.6754906418,3969826.7620644625,48.101412031333844],[231537.6754906418,3969826.7620644625,48.06331195533385],[231532.68969662543,3969823.0926833125,48.26999554805326],[231532.68969662543,3969823.0926833125,48.231895472053274],[231532.6755283115,3969826.7426558146,48.196995548053266],[231532.6755283115,3969826.7426558146,48.15889547205326],[231527.68973429519,3969823.0732746636,48.365579064772696],[231527.68973429519,3969823.0732746636,48.32747898877268],[231527.67556598125,3969826.7232471644,48.29257906477268],[231527.67556598125,3969826.7232471644,48.25447898877268],[231522.68977196486,3969823.0538660144,48.46116258149209],[231522.68977196486,3969823.0538660144,48.4230625054921],[231522.67560365092,3969826.7038385156,48.388162581492104],[231522.67560365092,3969826.7038385156,48.35006250549209],[231517.68980963455,3969823.0344573655,48.55674609821151],[231517.68980963455,3969823.0344573655,48.518646022211506],[231517.67564132062,3969826.6844298663,48.48374609821151],[231517.67564132062,3969826.6844298663,48.44564602221151],[231512.6898473043,3969823.015048715,48.65232961493093],[231512.6898473043,3969823.015048715,48.61422953893093],[231512.67567899037,3969826.665021217,48.579329614930934],[231512.67567899037,3969826.665021217,48.541229538930935],[231507.689884974,3969822.995640066,48.74791313165035],[231507.689884974,3969822.995640066,48.709813055650336],[231507.67571666007,3969826.645612567,48.674913131650335],[231507.67571666007,3969826.645612567,48.63681305565034],[231502.68992264368,3969822.9762314167,48.84349664836976],[231502.68992264368,3969822.9762314167,48.80539657236976],[231502.6757543298,3969826.626203918,48.77049664836976],[231502.6757543298,3969826.626203918,48.73239657236975],[231497.68996031344,3969822.956822768,48.93908016508918],[231497.68996031344,3969822.956822768,48.90098008908918],[231497.6757919995,3969826.606795269,48.86608016508917],[231497.6757919995,3969826.606795269,48.82798008908918],[231492.68999798314,3969822.9374141186,49.03466368180858],[231492.68999798314,3969822.9374141186,48.99656360580859],[231492.6758296692,3969826.587386619,48.96166368180859],[231492.6758296692,3969826.587386619,48.92356360580859],[231487.69003565283,3969822.918005469,49.13024719852801],[231487.69003565283,3969822.918005469,49.092147122528],[231487.67586733887,3969826.5679779705,49.057247198528],[231487.67586733887,3969826.5679779705,49.019147122528004],[231482.69007332253,3969822.8985968204,49.22583071524742],[231482.69007332253,3969822.8985968204,49.18773063924743],[231482.67590500863,3969826.5485693216,49.15283071524742],[231482.67590500863,3969826.5485693216,49.114730639247426],[231477.69011099226,3969822.8791881707,49.321414231966834],[231477.69011099226,3969822.8791881707,49.283314155966835],[231477.67594267832,3969826.5291606723,49.24841423196683],[231477.67594267832,3969826.5291606723,49.210314155966834],[231472.69014866196,3969822.8597795214,49.41699774868624],[231472.69014866196,3969822.8597795214,49.37889767268625],[231472.67598034802,3969826.5097520235,49.343997748686256],[231472.67598034802,3969826.5097520235,49.30589767268624],[231467.69018633166,3969822.840370872,49.51258126540567],[231467.69018633166,3969822.840370872,49.47448118940567],[231467.67601801772,3969826.4903433733,49.439581265405664],[231467.67601801772,3969826.4903433733,49.401481189405665],[231462.69022400136,3969822.820962223,49.60816478212507],[231462.69022400136,3969822.820962223,49.57006470612508],[231462.67605568745,3969826.470934724,49.53516478212508],[231462.67605568745,3969826.470934724,49.49706470612508],[231457.6902616711,3969822.801553574,49.7037482988445],[231457.6902616711,3969822.801553574,49.66564822284449],[231457.67609335715,3969826.451526075,49.63074829884449],[231457.67609335715,3969826.451526075,49.592648222844495],[231452.69029934084,3969822.7821449237,49.79933181556391],[231452.69029934084,3969822.7821449237,49.76123173956391],[231452.67613102685,3969826.432117426,49.72633181556391],[231452.67613102685,3969826.432117426,49.688231739563925],[231447.69033701048,3969822.762736275,49.894915332283325],[231447.69033701048,3969822.762736275,49.856815256283326],[231447.67616869655,3969826.412708776,49.82191533228332],[231447.67616869655,3969826.412708776,49.78381525628332],[231442.69037468018,3969822.743327626,49.99049884900275],[231442.69037468018,3969822.743327626,49.95239877300274],[231442.67620636628,3969826.393300127,49.91749884900274],[231442.67620636628,3969826.393300127,49.87939877300275],[231437.6904123499,3969822.7239189767,50.086082365722156],[231437.6904123499,3969822.7239189767,50.04798228972217],[231437.67624403597,3969826.373891478,50.01308236572216],[231437.67624403597,3969826.373891478,49.974982289722156],[231432.6904500196,3969822.7045103274,50.181665882441564],[231432.6904500196,3969822.7045103274,50.14356580644158],[231432.67628170567,3969826.3544828286,50.10866588244157],[231432.67628170567,3969826.3544828286,50.070565806441564],[231427.69048768937,3969822.6851016777,50.277249399160986],[231427.69048768937,3969822.6851016777,50.239149323160994],[231427.67631937537,3969826.3350741793,50.204249399160986],[231427.67631937537,3969826.3350741793,50.16614932316099],[231422.69052535907,3969822.6656930293,50.37283291588041],[231422.69052535907,3969822.6656930293,50.3347328398804],[231422.6763570451,3969826.3156655305,50.29983291588041],[231422.6763570451,3969826.3156655305,50.26173283988041],[231417.69056302874,3969822.64628438,50.46841643259982],[231417.69056302874,3969822.64628438,50.43031635659981],[231417.67639471486,3969826.296256881,50.395416432599816],[231417.67639471486,3969826.296256881,50.35731635659981],[231412.69060069844,3969822.62687573,50.56399994931923],[231412.69060069844,3969822.62687573,50.52589987331923],[231412.6764323845,3969826.2768482324,50.49099994931923],[231412.6764323845,3969826.2768482324,50.45289987331924],[231407.6906383682,3969822.607467081,50.659583466038654],[231407.6906383682,3969822.607467081,50.621483390038655],[231407.67647005426,3969826.2574395817,50.586583466038654],[231407.67647005426,3969826.2574395817,50.54848339003865],[231402.6906760379,3969822.588058432,50.75516698275806],[231402.6906760379,3969822.588058432,50.71706690675807],[231402.67650772393,3969826.238030933,50.68216698275806],[231402.67650772393,3969826.238030933,50.644066906758056],[231401.1420717323,3969822.582047123,50.78477141490276],[231401.1420717323,3969822.582047123,50.746671338902765],[231401.12790341835,3969826.2320196237,50.71177141490277],[231401.12790341835,3969826.2320196237,50.67367133890276],[231397.69071277653,3969822.58850313,50.85075049947748],[231397.69071277653,3969822.58850313,50.812650423477486],[231397.7185359965,3969826.238397083,50.777750499477484],[231397.7185359965,3969826.238397083,50.739650423477485],[231394.2172831071,3969822.635093217,50.917157368033834],[231394.2172831071,3969822.635093217,50.87905729203383],[231394.28736638805,3969826.2844203236,50.84415736803383],[231394.28736638805,3969826.2844203236,50.80605729203384],[231392.6914071272,3969822.6682798564,50.94633401619691],[231392.6914071272,3969822.6682798564,50.908233940196894],[231392.78005523258,3969826.317203193,50.8733340161969],[231392.78005523258,3969826.317203193,50.8352339401969],[231387.6941253603,3969822.8313634074,51.041917532917275],[231387.6941253603,3969822.8313634074,51.00381745691726],[231387.84357372724,3969826.47830256,50.96891753291726],[231387.84357372724,3969826.47830256,50.93081745691726],[231387.29556377884,3969822.847961545,51.04954332116488],[231387.29556377884,3969822.847961545,51.01144324516488],[231387.44986131164,3969826.494698755,50.97459975409567],[231387.44986131164,3969826.494698755,50.936499678095664],[231382.7002555777,3969823.077708482,51.13750104963573],[231382.7002555777,3969823.077708482,51.09940097363573],[231382.91046269366,3969826.7216504365,51.040139899101916],[231382.91046269366,3969826.7216504365,51.00203982310191],[231380.38060190907,3969823.220538685,51.18192927429592],[231380.38060190907,3969823.220538685,51.143829198295926],[231380.61903147798,3969826.862742872,51.073244804574344],[231380.61903147798,3969826.862742872,51.03514472857434],[231377.7111849332,3969823.4072466516,51.23308456635514],[231377.7111849332,3969823.4072466516,51.19498449035515],[231377.9820924086,3969827.0471792254,51.111362265287525],[231377.9820924086,3969827.0471792254,51.07326218928752],[231373.47608205935,3969823.752626111,51.31431522742697],[231373.47608205935,3969823.752626111,51.276215151426975],[231373.79851661975,3969827.3883565674,51.171889855053095],[231373.79851661975,3969827.3883565674,51.1337897790531],[231372.7282992477,3969823.8198863817,51.328668083074554],[231372.7282992477,3969823.8198863817,51.29056800707455],[231373.05983183227,3969827.4547985056,51.18258463147302],[231373.05983183227,3969827.4547985056,51.14448455547303],[231368.14504822757,3969827.9443950504,51.25380699765858],[231368.14504822757,3969827.9443950504,51.21570692165858],[231367.75298262408,3969824.3155130525,51.42425159979397],[231367.75298262408,3969824.3155130525,51.38615152379398],[231366.99195097337,3969828.071259775,51.27053490553187],[231366.99195097337,3969828.071259775,51.232434829531854],[231366.58568322717,3969824.443940307,51.44670118055802],[231366.58568322717,3969824.443940307,51.40860110455801],[231363.23910678053,3969828.515832867,51.32502936384429],[231363.23910678053,3969828.515832867,51.28692928784427],[231362.78661706272,3969824.8939889916,51.5198351165134],[231362.78661706272,3969824.8939889916,51.481735040513385],[231360.20296134258,3969828.9110886157,51.36917995601071],[231360.20296134258,3969828.9110886157,51.3310798800107],[231359.7130768859,3969825.294112915,51.579087133689065],[231359.7130768859,3969825.294112915,51.54098705768906],[231358.3433702212,3969829.1689532236,51.39625173002977],[231358.3433702212,3969829.1689532236,51.35815165402976],[231357.8305820777,3969825.5551535166,51.61541863323281],[231357.8305820777,3969825.5551535166,51.57731855723279],[231353.45919844485,3969829.903574703,51.46747409621529],[231353.45919844485,3969829.903574703,51.42937402021529],[231353.43516516592,3969829.9073955966,51.46782500648959],[231353.43516516592,3969829.9073955966,51.4297249304896],[231352.88625431352,3969826.298822975,51.71100214995222],[231352.88625431352,3969826.298822975,51.67290207395222],[231352.8619250283,3969826.302690928,51.7114730868201],[231352.8619250283,3969826.302690928,51.6733730108201],[231348.5879481345,3969830.7194932476,51.538696462400914],[231348.5879481345,3969830.7194932476,51.5005963864009],[231347.95500716282,3969827.1247907947,51.80658566667163],[231347.95500716282,3969827.1247907947,51.76848559067164],[231346.69216858927,3969831.059649846,51.566470056968136],[231346.69216858927,3969831.059649846,51.52836998096813],[231346.03587821542,3969827.469136938,51.84385903995114],[231346.03587821542,3969827.469136938,51.80575896395115],[231343.78080942994,3969831.606852569,51.609186890185114],[231343.78080942994,3969831.606852569,51.57108681418512],[231343.73097238384,3969831.6164822197,51.610169183391044],[231343.73097238384,3969831.6164822197,51.57206910739105],[231343.0886612497,3969828.0230792924,51.90118689018512],[231343.0886612497,3969828.0230792924,51.86308681418512],[231343.03821038472,3969828.0328275478,51.90216918339105],[231343.03821038472,3969828.0328275478,51.864069107391046],[231339.9775645442,3969832.367237399,51.68424499308219],[231339.9775645442,3969832.367237399,51.64614491708219],[231339.2385736313,3969828.7928294153,51.97624499308219],[231339.2385736313,3969828.7928294153,51.938144917082184],[231338.88962032163,3969832.5942924623,51.705752700110466],[231338.88962032163,3969832.5942924623,51.66765262411046],[231338.13722972453,3969829.022681006,51.99775270011046],[231338.13722972453,3969829.022681006,51.959652624110475],[231334.0652367368,3969833.652652365,51.801336216829874],[231334.0652367368,3969833.652652365,51.76323614082989],[231333.25342653418,3969830.0940762185,52.09333621682988],[231333.25342653418,3969830.0940762185,52.055236140829884],[231333.29493083383,3969833.8294615205,51.81663094621323],[231333.29493083383,3969833.8294615205,51.77853087021324],[231332.473633145,3969830.2730630464,52.10863094621324],[231332.473633145,3969830.2730630464,52.07053087021323],[231329.2591617048,3969834.791267948,51.89691973354929],[231329.2591617048,3969834.791267948,51.85881965754929],[231328.38815739428,3969831.24671558,52.1889197335493],[231328.38815739428,3969831.24671558,52.1508196575493],[231326.6478282261,3969835.44554308,51.94901689934428],[231326.6478282261,3969835.44554308,51.91091682334427],[231325.74466138077,3969831.909049104,52.241016899344274],[231325.74466138077,3969831.909049104,52.20291682334428],[231324.4727302156,3969836.009822936,51.99250325026871],[231324.4727302156,3969836.009822936,51.95440317426871],[231323.5427737373,3969832.480278922,52.28450325026871],[231323.5427737373,3969832.480278922,52.24640317426871],[231320.03979855657,3969837.214620969,52.081402852475314],[231320.03979855657,3969837.214620969,52.043302776475315],[231319.70727180273,3969837.3079788485,52.08808676698813],[231319.70727180273,3969837.3079788485,52.04998669098812],[231319.0552437973,3969833.699915871,52.37340285247532],[231319.0552437973,3969833.699915871,52.33530277647533],[231318.71862147184,3969833.794423595,52.38008676698812],[231318.71862147184,3969833.794423595,52.34198669098813]],"pointIndex":[960,959,957,958,0,959,963,961,957,0,963,964,962,961,0,964,960,958,962,0,958,957,953,954,0,957,961,955,953,0,961,962,956,955,0,962,958,954,956,0,954,953,949,950,0,953,955,951,949,0,955,956,952,951,0,956,954,950,952,0,950,949,945,946,0,949,951,947,945,0,951,952,948,947,0,952,950,946,948,0,946,945,941,942,0,945,947,943,941,0,947,948,944,943,0,948,946,942,944,0,942,941,937,938,0,941,943,939,937,0,943,944,940,939,0,944,942,938,940,0,938,937,933,934,0,937,939,935,933,0,939,940,936,935,0,940,938,934,936,0,934,933,929,930,0,933,935,931,929,0,935,936,932,931,0,936,934,930,932,0,930,929,923,924,0,929,931,927,923,0,931,932,928,927,0,932,930,924,928,0,924,923,921,922,0,923,927,925,921,0,927,928,926,925,0,928,924,922,926,0,922,921,917,918,0,921,925,919,917,0,925,926,920,919,0,926,922,918,920,0,918,917,913,914,0,917,919,915,913,0,919,920,916,915,0,920,918,914,916,0,914,913,907,908,0,913,915,911,907,0,915,916,912,911,0,916,914,908,912,0,908,907,905,906,0,907,911,909,905,0,911,912,910,909,0,912,908,906,910,0,906,905,901,902,0,905,909,903,901,0,909,910,904,903,0,910,906,902,904,0,902,901,897,898,0,901,903,899,897,0,903,904,900,899,0,904,902,898,900,0,898,897,893,894,0,897,899,895,893,0,899,900,896,895,0,900,898,894,896,0,894,893,889,890,0,893,895,891,889,0,895,896,892,891,0,896,894,890,892,0,890,889,885,886,0,889,891,887,885,0,891,892,888,887,0,892,890,886,888,0,886,885,883,884,0,885,887,881,883,0,887,888,882,881,0,888,886,884,882,0,884,883,879,880,0,883,881,877,879,0,881,882,878,877,0,882,884,880,878,0,880,879,875,876,0,879,877,873,875,0,877,878,874,873,0,878,880,876,874,0,876,875,871,872,0,875,873,869,871,0,873,874,870,869,0,874,876,872,870,0,872,871,867,868,0,871,869,865,867,0,869,870,866,865,0,870,872,868,866,0,868,867,863,864,0,867,865,861,863,0,865,866,862,861,0,866,868,864,862,0,864,863,859,860,0,863,861,857,859,0,861,862,858,857,0,862,864,860,858,0,860,859,855,856,0,859,857,853,855,0,857,858,854,853,0,858,860,856,854,0,856,855,851,852,0,855,853,849,851,0,853,854,850,849,0,854,856,852,850,0,852,851,847,848,0,851,849,845,847,0,849,850,846,845,0,850,852,848,846,0,848,847,843,844,0,847,845,841,843,0,845,846,842,841,0,846,848,844,842,0,844,843,839,840,0,843,841,837,839,0,841,842,838,837,0,842,844,840,838,0,840,839,835,836,0,839,837,833,835,0,837,838,834,833,0,838,840,836,834,0,836,835,831,832,0,835,833,829,831,0,833,834,830,829,0,834,836,832,830,0,832,831,827,828,0,831,829,825,827,0,829,830,826,825,0,830,832,828,826,0,828,827,823,824,0,827,825,821,823,0,825,826,822,821,0,826,828,824,822,0,824,823,819,820,0,823,821,817,819,0,821,822,818,817,0,822,824,820,818,0,820,819,815,816,0,819,817,813,815,0,817,818,814,813,0,818,820,816,814,0,816,815,811,812,0,815,813,809,811,0,813,814,810,809,0,814,816,812,810,0,812,811,807,808,0,811,809,805,807,0,809,810,806,805,0,810,812,808,806,0,808,807,803,804,0,807,805,801,803,0,805,806,802,801,0,806,808,804,802,0,804,803,799,800,0,803,801,797,799,0,801,802,798,797,0,802,804,800,798,0,800,799,795,796,0,799,797,793,795,0,797,798,794,793,0,798,800,796,794,0,796,795,791,792,0,795,793,789,791,0,793,794,790,789,0,794,796,792,790,0,792,791,787,788,0,791,789,785,787,0,789,790,786,785,0,790,792,788,786,0,788,787,783,784,0,787,785,781,783,0,785,786,782,781,0,786,788,784,782,0,784,783,779,780,0,783,781,777,779,0,781,782,778,777,0,782,784,780,778,0,780,779,775,776,0,779,777,773,775,0,777,778,774,773,0,778,780,776,774,0,776,775,771,772,0,775,773,769,771,0,773,774,770,769,0,774,776,772,770,0,772,771,767,768,0,771,769,765,767,0,769,770,766,765,0,770,772,768,766,0,768,767,763,764,0,767,765,761,763,0,765,766,762,761,0,766,768,764,762,0,764,763,759,760,0,763,761,757,759,0,761,762,758,757,0,762,764,760,758,0,760,759,755,756,0,759,757,753,755,0,757,758,754,753,0,758,760,756,754,0,756,755,751,752,0,755,753,749,751,0,753,754,750,749,0,754,756,752,750,0,752,751,747,748,0,751,749,745,747,0,749,750,746,745,0,750,752,748,746,0,748,747,743,744,0,747,745,741,743,0,745,746,742,741,0,746,748,744,742,0,744,743,739,740,0,743,741,737,739,0,741,742,738,737,0,742,744,740,738,0,740,739,735,736,0,739,737,733,735,0,737,738,734,733,0,738,740,736,734,0,736,735,731,732,0,735,733,729,731,0,733,734,730,729,0,734,736,732,730,0,732,731,727,728,0,731,729,725,727,0,729,730,726,725,0,730,732,728,726,0,728,727,723,724,0,727,725,721,723,0,725,726,722,721,0,726,728,724,722,0,724,723,719,720,0,723,721,717,719,0,721,722,718,717,0,722,724,720,718,0,720,719,715,716,0,719,717,713,715,0,717,718,714,713,0,718,720,716,714,0,716,715,711,712,0,715,713,709,711,0,713,714,710,709,0,714,716,712,710,0,712,711,707,708,0,711,709,705,707,0,709,710,706,705,0,710,712,708,706,0,708,707,703,704,0,707,705,701,703,0,705,706,702,701,0,706,708,704,702,0,704,703,699,700,0,703,701,697,699,0,701,702,698,697,0,702,704,700,698,0,700,699,695,696,0,699,697,693,695,0,697,698,694,693,0,698,700,696,694,0,696,695,691,692,0,695,693,689,691,0,693,694,690,689,0,694,696,692,690,0,692,691,687,688,0,691,689,685,687,0,689,690,686,685,0,690,692,688,686,0,688,687,683,684,0,687,685,681,683,0,685,686,682,681,0,686,688,684,682,0,684,683,679,680,0,683,681,677,679,0,681,682,678,677,0,682,684,680,678,0,680,679,675,676,0,679,677,673,675,0,677,678,674,673,0,678,680,676,674,0,676,675,671,672,0,675,673,669,671,0,673,674,670,669,0,674,676,672,670,0,672,671,667,668,0,671,669,665,667,0,669,670,666,665,0,670,672,668,666,0,668,667,663,664,0,667,665,661,663,0,665,666,662,661,0,666,668,664,662,0,664,663,659,660,0,663,661,657,659,0,661,662,658,657,0,662,664,660,658,0,660,659,655,656,0,659,657,653,655,0,657,658,654,653,0,658,660,656,654,0,656,655,651,652,0,655,653,649,651,0,653,654,650,649,0,654,656,652,650,0,652,651,647,648,0,651,649,645,647,0,649,650,646,645,0,650,652,648,646,0,648,647,643,644,0,647,645,641,643,0,645,646,642,641,0,646,648,644,642,0,644,643,639,640,0,643,641,637,639,0,641,642,638,637,0,642,644,640,638,0,640,639,635,636,0,639,637,633,635,0,637,638,634,633,0,638,640,636,634,0,636,635,631,632,0,635,633,629,631,0,633,634,630,629,0,634,636,632,630,0,632,631,627,628,0,631,629,625,627,0,629,630,626,625,0,630,632,628,626,0,628,627,623,624,0,627,625,621,623,0,625,626,622,621,0,626,628,624,622,0,624,623,619,620,0,623,621,617,619,0,621,622,618,617,0,622,624,620,618,0,620,619,615,616,0,619,617,613,615,0,617,618,614,613,0,618,620,616,614,0,616,615,611,612,0,615,613,609,611,0,613,614,610,609,0,614,616,612,610,0,612,611,607,608,0,611,609,605,607,0,609,610,606,605,0,610,612,608,606,0,608,607,603,604,0,607,605,601,603,0,605,606,602,601,0,606,608,604,602,0,604,603,599,600,0,603,601,597,599,0,601,602,598,597,0,602,604,600,598,0,600,599,595,596,0,599,597,593,595,0,597,598,594,593,0,598,600,596,594,0,596,595,591,592,0,595,593,589,591,0,593,594,590,589,0,594,596,592,590,0,592,591,587,588,0,591,589,585,587,0,589,590,586,585,0,590,592,588,586,0,588,587,583,584,0,587,585,581,583,0,585,586,582,581,0,586,588,584,582,0,584,583,579,580,0,583,581,577,579,0,581,582,578,577,0,582,584,580,578,0,580,579,575,576,0,579,577,573,575,0,577,578,574,573,0,578,580,576,574,0,576,575,571,572,0,575,573,569,571,0,573,574,570,569,0,574,576,572,570,0,572,571,567,568,0,571,569,565,567,0,569,570,566,565,0,570,572,568,566,0,568,567,563,564,0,567,565,561,563,0,565,566,562,561,0,566,568,564,562,0,564,563,559,560,0,563,561,557,559,0,561,562,558,557,0,562,564,560,558,0,560,559,555,556,0,559,557,553,555,0,557,558,554,553,0,558,560,556,554,0,556,555,551,552,0,555,553,549,551,0,553,554,550,549,0,554,556,552,550,0,552,551,547,548,0,551,549,545,547,0,549,550,546,545,0,550,552,548,546,0,548,547,543,544,0,547,545,541,543,0,545,546,542,541,0,546,548,544,542,0,544,543,539,540,0,543,541,537,539,0,541,542,538,537,0,542,544,540,538,0,540,539,535,536,0,539,537,533,535,0,537,538,534,533,0,538,540,536,534,0,536,535,531,532,0,535,533,529,531,0,533,534,530,529,0,534,536,532,530,0,532,531,527,528,0,531,529,525,527,0,529,530,526,525,0,530,532,528,526,0,528,527,523,524,0,527,525,521,523,0,525,526,522,521,0,526,528,524,522,0,524,523,519,520,0,523,521,517,519,0,521,522,518,517,0,522,524,520,518,0,520,519,515,516,0,519,517,513,515,0,517,518,514,513,0,518,520,516,514,0,516,515,511,512,0,515,513,509,511,0,513,514,510,509,0,514,516,512,510,0,512,511,507,508,0,511,509,505,507,0,509,510,506,505,0,510,512,508,506,0,508,507,503,504,0,507,505,501,503,0,505,506,502,501,0,506,508,504,502,0,504,503,499,500,0,503,501,497,499,0,501,502,498,497,0,502,504,500,498,0,500,499,495,496,0,499,497,493,495,0,497,498,494,493,0,498,500,496,494,0,496,495,491,492,0,495,493,489,491,0,493,494,490,489,0,494,496,492,490,0,492,491,487,488,0,491,489,485,487,0,489,490,486,485,0,490,492,488,486,0,488,487,483,484,0,487,485,481,483,0,485,486,482,481,0,486,488,484,482,0,484,483,479,480,0,483,481,477,479,0,481,482,478,477,0,482,484,480,478,0,480,479,475,476,0,479,477,473,475,0,477,478,474,473,0,478,480,476,474,0,476,475,471,472,0,475,473,469,471,0,473,474,470,469,0,474,476,472,470,0,472,471,467,468,0,471,469,465,467,0,469,470,466,465,0,470,472,468,466,0,468,467,463,464,0,467,465,461,463,0,465,466,462,461,0,466,468,464,462,0,464,463,459,460,0,463,461,457,459,0,461,462,458,457,0,462,464,460,458,0,460,459,455,456,0,459,457,453,455,0,457,458,454,453,0,458,460,456,454,0,456,455,451,452,0,455,453,449,451,0,453,454,450,449,0,454,456,452,450,0,452,451,447,448,0,451,449,445,447,0,449,450,446,445,0,450,452,448,446,0,448,447,443,444,0,447,445,441,443,0,445,446,442,441,0,446,448,444,442,0,444,443,439,440,0,443,441,437,439,0,441,442,438,437,0,442,444,440,438,0,440,439,435,436,0,439,437,433,435,0,437,438,434,433,0,438,440,436,434,0,436,435,431,432,0,435,433,429,431,0,433,434,430,429,0,434,436,432,430,0,432,431,427,428,0,431,429,425,427,0,429,430,426,425,0,430,432,428,426,0,428,427,423,424,0,427,425,421,423,0,425,426,422,421,0,426,428,424,422,0,424,423,419,420,0,423,421,417,419,0,421,422,418,417,0,422,424,420,418,0,420,419,415,416,0,419,417,413,415,0,417,418,414,413,0,418,420,416,414,0,416,415,411,412,0,415,413,409,411,0,413,414,410,409,0,414,416,412,410,0,412,411,407,408,0,411,409,405,407,0,409,410,406,405,0,410,412,408,406,0,408,407,403,404,0,407,405,401,403,0,405,406,402,401,0,406,408,404,402,0,404,403,399,400,0,403,401,397,399,0,401,402,398,397,0,402,404,400,398,0,400,399,395,396,0,399,397,393,395,0,397,398,394,393,0,398,400,396,394,0,396,395,391,392,0,395,393,389,391,0,393,394,390,389,0,394,396,392,390,0,392,391,387,388,0,391,389,385,387,0,389,390,386,385,0,390,392,388,386,0,388,387,383,384,0,387,385,381,383,0,385,386,382,381,0,386,388,384,382,0,384,383,379,380,0,383,381,377,379,0,381,382,378,377,0,382,384,380,378,0,380,379,375,376,0,379,377,373,375,0,377,378,374,373,0,378,380,376,374,0,376,375,371,372,0,375,373,369,371,0,373,374,370,369,0,374,376,372,370,0,372,371,367,368,0,371,369,365,367,0,369,370,366,365,0,370,372,368,366,0,368,367,363,364,0,367,365,361,363,0,365,366,362,361,0,366,368,364,362,0,364,363,359,360,0,363,361,357,359,0,361,362,358,357,0,362,364,360,358,0,360,359,355,356,0,359,357,353,355,0,357,358,354,353,0,358,360,356,354,0,356,355,351,352,0,355,353,349,351,0,353,354,350,349,0,354,356,352,350,0,352,351,347,348,0,351,349,345,347,0,349,350,346,345,0,350,352,348,346,0,348,347,343,344,0,347,345,341,343,0,345,346,342,341,0,346,348,344,342,0,344,343,339,340,0,343,341,337,339,0,341,342,338,337,0,342,344,340,338,0,340,339,335,336,0,339,337,333,335,0,337,338,334,333,0,338,340,336,334,0,336,335,331,332,0,335,333,329,331,0,333,334,330,329,0,334,336,332,330,0,332,331,327,328,0,331,329,325,327,0,329,330,326,325,0,330,332,328,326,0,328,327,323,324,0,327,325,321,323,0,325,326,322,321,0,326,328,324,322,0,324,323,319,320,0,323,321,317,319,0,321,322,318,317,0,322,324,320,318,0,320,319,315,316,0,319,317,313,315,0,317,318,314,313,0,318,320,316,314,0,316,315,311,312,0,315,313,309,311,0,313,314,310,309,0,314,316,312,310,0,312,311,307,308,0,311,309,305,307,0,309,310,306,305,0,310,312,308,306,0,308,307,303,304,0,307,305,300,303,0,305,306,302,300,0,306,308,304,302,0,304,303,299,301,0,303,300,297,299,0,300,302,298,297,0,302,304,301,298,0,301,299,295,296,0,299,297,293,295,0,297,298,294,293,0,298,301,296,294,0,296,295,291,292,0,295,293,289,291,0,293,294,290,289,0,294,296,292,290,0,292,291,287,288,0,291,289,285,287,0,289,290,286,285,0,290,292,288,286,0,288,287,283,284,0,287,285,281,283,0,285,286,282,281,0,286,288,284,282,0,284,283,279,280,0,283,281,277,279,0,281,282,278,277,0,282,284,280,278,0,280,279,275,276,0,279,277,273,275,0,277,278,274,273,0,278,280,276,274,0,276,275,271,272,0,275,273,269,271,0,273,274,270,269,0,274,276,272,270,0,272,271,267,268,0,271,269,265,267,0,269,270,266,265,0,270,272,268,266,0,268,267,263,264,0,267,265,261,263,0,265,266,262,261,0,266,268,264,262,0,264,263,259,260,0,263,261,257,259,0,261,262,258,257,0,262,264,260,258,0,260,259,255,256,0,259,257,253,255,0,257,258,254,253,0,258,260,256,254,0,256,255,251,252,0,255,253,249,251,0,253,254,250,249,0,254,256,252,250,0,252,251,247,248,0,251,249,245,247,0,249,250,246,245,0,250,252,248,246,0,248,247,243,244,0,247,245,241,243,0,245,246,242,241,0,246,248,244,242,0,244,243,239,240,0,243,241,237,239,0,241,242,238,237,0,242,244,240,238,0,240,239,235,236,0,239,237,233,235,0,237,238,234,233,0,238,240,236,234,0,236,235,231,232,0,235,233,229,231,0,233,234,230,229,0,234,236,232,230,0,232,231,227,228,0,231,229,225,227,0,229,230,226,225,0,230,232,228,226,0,228,227,223,224,0,227,225,221,223,0,225,226,222,221,0,226,228,224,222,0,224,223,219,220,0,223,221,217,219,0,221,222,218,217,0,222,224,220,218,0,220,219,215,216,0,219,217,213,215,0,217,218,214,213,0,218,220,216,214,0,216,215,211,212,0,215,213,209,211,0,213,214,210,209,0,214,216,212,210,0,212,211,207,208,0,211,209,205,207,0,209,210,206,205,0,210,212,208,206,0,208,207,203,204,0,207,205,201,203,0,205,206,202,201,0,206,208,204,202,0,204,203,199,200,0,203,201,197,199,0,201,202,198,197,0,202,204,200,198,0,200,199,195,196,0,199,197,193,195,0,197,198,194,193,0,198,200,196,194,0,196,195,191,192,0,195,193,189,191,0,193,194,190,189,0,194,196,192,190,0,192,191,187,188,0,191,189,185,187,0,189,190,186,185,0,190,192,188,186,0,188,187,183,184,0,187,185,181,183,0,185,186,182,181,0,186,188,184,182,0,184,183,179,180,0,183,181,177,179,0,181,182,178,177,0,182,184,180,178,0,180,179,175,176,0,179,177,173,175,0,177,178,174,173,0,178,180,176,174,0,176,175,171,172,0,175,173,169,171,0,173,174,170,169,0,174,176,172,170,0,172,171,167,168,0,171,169,165,167,0,169,170,166,165,0,170,172,168,166,0,168,167,163,164,0,167,165,161,163,0,165,166,162,161,0,166,168,164,162,0,164,163,159,160,0,163,161,157,159,0,161,162,158,157,0,162,164,160,158,0,160,159,155,156,0,159,157,153,155,0,157,158,154,153,0,158,160,156,154,0,156,155,151,152,0,155,153,149,151,0,153,154,150,149,0,154,156,152,150,0,152,151,147,148,0,151,149,145,147,0,149,150,146,145,0,150,152,148,146,0,148,147,143,144,0,147,145,141,143,0,145,146,142,141,0,146,148,144,142,0,144,143,139,140,0,143,141,137,139,0,141,142,138,137,0,142,144,140,138,0,140,139,135,136,0,139,137,133,135,0,137,138,134,133,0,138,140,136,134,0,136,135,131,132,0,135,133,129,131,0,133,134,130,129,0,134,136,132,130,0,132,131,127,128,0,131,129,125,127,0,129,130,126,125,0,130,132,128,126,0,128,127,123,124,0,127,125,121,123,0,125,126,122,121,0,126,128,124,122,0,124,123,119,120,0,123,121,117,119,0,121,122,118,117,0,122,124,120,118,0,120,119,115,116,0,119,117,113,115,0,117,118,114,113,0,118,120,116,114,0,116,115,111,112,0,115,113,109,111,0,113,114,110,109,0,114,116,112,110,0,112,111,107,108,0,111,109,105,107,0,109,110,106,105,0,110,112,108,106,0,108,107,103,104,0,107,105,101,103,0,105,106,102,101,0,106,108,104,102,0,104,103,99,100,0,103,101,97,99,0,101,102,98,97,0,102,104,100,98,0,100,99,95,96,0,99,97,93,95,0,97,98,94,93,0,98,100,96,94,0,96,95,91,92,0,95,93,89,91,0,93,94,90,89,0,94,96,92,90,0,92,91,87,88,0,91,89,85,87,0,89,90,86,85,0,90,92,88,86,0,88,87,83,84,0,87,85,81,83,0,85,86,82,81,0,86,88,84,82,0,84,83,79,80,0,83,81,77,79,0,81,82,78,77,0,82,84,80,78,0,80,79,75,76,0,79,77,73,75,0,77,78,74,73,0,78,80,76,74,0,76,75,71,72,0,75,73,69,71,0,73,74,70,69,0,74,76,72,70,0,72,71,67,68,0,71,69,65,67,0,69,70,66,65,0,70,72,68,66,0,68,67,63,64,0,67,65,61,63,0,65,66,62,61,0,66,68,64,62,0,64,63,59,60,0,63,61,57,59,0,61,62,58,57,0,62,64,60,58,0,60,59,55,56,0,59,57,53,55,0,57,58,54,53,0,58,60,56,54,0,56,55,51,52,0,55,53,49,51,0,53,54,50,49,0,54,56,52,50,0,52,51,47,48,0,51,49,45,47,0,49,50,46,45,0,50,52,48,46,0,48,47,43,44,0,47,45,41,43,0,45,46,42,41,0,46,48,44,42,0,44,43,39,40,0,43,41,37,39,0,41,42,38,37,0,42,44,40,38,0,40,39,35,36,0,39,37,33,35,0,37,38,34,33,0,38,40,36,34,0,36,35,31,32,0,35,33,29,31,0,33,34,30,29,0,34,36,32,30,0,32,31,27,28,0,31,29,25,27,0,29,30,26,25,0,30,32,28,26,0,28,27,23,24,0,27,25,21,23,0,25,26,22,21,0,26,28,24,22,0,24,23,19,20,0,23,21,17,19,0,21,22,18,17,0,22,24,20,18,0,20,19,15,16,0,19,17,13,15,0,17,18,14,13,0,18,20,16,14,0,16,15,11,12,0,15,13,9,11,0,13,14,10,9,0,14,16,12,10,0,12,11,7,8,0,11,9,5,7,0,9,10,6,5,0,10,12,8,6,0,8,7,3,4,0,7,5,1,3,0,5,6,2,1,0,6,8,4,2,0,960,964,963,959,0,4,3,1,2,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [232347.01132511083, 3969797.7871081727, 46.825095792426076], + [232347.01132511083, 3969797.7871081727, 46.786995716426084], + [232347.263926118, 3969801.4283569604, 46.752095792426076], + [232347.263926118, 3969801.4283569604, 46.71399571642609], + [232346.81012069722, 3969797.8010661416, 46.82235167169862], + [232346.81012069722, 3969797.8010661416, 46.78425159569863], + [232347.0627217044, 3969801.4423149293, 46.749351671698626], + [232347.0627217044, 3969801.4423149293, 46.71125159569862], + [232341.8221086598, 3969798.1470949184, 46.754322810028484], + [232341.8221086598, 3969798.1470949184, 46.716222734028484], + [232342.07470966692, 3969801.788343706, 46.681322810028476], + [232342.07470966692, 3969801.788343706, 46.643222734028484], + [232336.8340966224, 3969798.4931236957, 46.68629394835834], + [232336.8340966224, 3969798.4931236957, 46.64819387235834], + [232337.0866976295, 3969802.1343724825, 46.61329394835834], + [232337.0866976295, 3969802.1343724825, 46.57519387235835], + [232336.51620828634, 3969798.515176272, 46.681958437241846], + [232336.51620828634, 3969798.515176272, 46.64385836124185], + [232336.76880929348, 3969802.1564250584, 46.608958437241846], + [232336.76880929348, 3969802.1564250584, 46.57085836124184], + [232331.84608458492, 3969798.839152472, 46.61862856387353], + [232331.84608458492, 3969798.839152472, 46.580528487873536], + [232332.0986855921, 3969802.48040126, 46.54562856387353], + [232332.0986855921, 3969802.48040126, 46.507528487873536], + [232326.8580725475, 3969799.1851812494, 46.55179078325966], + [232326.8580725475, 3969799.1851812494, 46.513690707259656], + [232327.11067355468, 3969802.826430037, 46.47879078325966], + [232327.11067355468, 3969802.826430037, 46.44069070725966], + [232321.87006051006, 3969799.5312100267, 46.4857822906233], + [232321.87006051006, 3969799.5312100267, 46.447682214623306], + [232322.1226615172, 3969803.1724588135, 46.4127822906233], + [232322.1226615172, 3969803.1724588135, 46.3746822146233], + [232316.88204847265, 3969799.877238803, 46.42060308596445], + [232316.88204847265, 3969799.877238803, 46.382503009964466], + [232317.1346494798, 3969803.5184875904, 46.34760308596446], + [232317.1346494798, 3969803.5184875904, 46.30950300996445], + [232311.89403643523, 3969800.22326758, 46.356253169283136], + [232311.89403643523, 3969800.22326758, 46.31815309328312], + [232312.14663744235, 3969803.8645163677, 46.28325316928312], + [232312.14663744235, 3969803.8645163677, 46.24515309328313], + [232306.90602439776, 3969800.569296357, 46.29273254057931], + [232306.90602439776, 3969800.569296357, 46.2546324645793], + [232307.1586254049, 3969804.210545144, 46.21973254057931], + [232307.1586254049, 3969804.210545144, 46.1816324645793], + [232301.91801236034, 3969800.9153251336, 46.23004119985299], + [232301.91801236034, 3969800.9153251336, 46.191941123853006], + [232302.17061336752, 3969804.5565739213, 46.157041199853], + [232302.17061336752, 3969804.5565739213, 46.11894112385299], + [232296.93000032293, 3969801.2613539104, 46.16817914710422], + [232296.93000032293, 3969801.2613539104, 46.130079071104205], + [232297.18260133005, 3969804.9026026977, 46.095179147104204], + [232297.18260133005, 3969804.9026026977, 46.05707907110421], + [232291.9419882855, 3969801.6073826877, 46.10714638233292], + [232291.9419882855, 3969801.6073826877, 46.06904630633293], + [232292.19458929263, 3969805.2486314746, 46.03414638233293], + [232292.19458929263, 3969805.2486314746, 45.99604630633293], + [232286.95397624804, 3969801.953411465, 46.04694290553917], + [232286.95397624804, 3969801.953411465, 46.00884282953916], + [232287.20657725522, 3969805.594660252, 45.97394290553917], + [232287.20657725522, 3969805.594660252, 45.93584282953916], + [232281.96596421063, 3969802.2994402414, 45.98756871672291], + [232281.96596421063, 3969802.2994402414, 45.949468640722905], + [232282.2185652178, 3969805.940689029, 45.914568716722904], + [232282.2185652178, 3969805.940689029, 45.87646864072291], + [232276.97795217318, 3969802.6454690187, 45.92902381588418], + [232276.97795217318, 3969802.6454690187, 45.890923739884165], + [232277.23055318033, 3969806.2867178055, 45.856023815884164], + [232277.23055318033, 3969806.2867178055, 45.817923739884165], + [232271.98994013574, 3969802.991497795, 45.871308203022956], + [232271.98994013574, 3969802.991497795, 45.83320812702294], + [232272.2425411429, 3969806.6327465824, 45.79830820302294], + [232272.2425411429, 3969806.6327465824, 45.76020812702294], + [232267.00192809835, 3969803.337526572, 45.81442187813923], + [232267.00192809835, 3969803.337526572, 45.776321802139236], + [232267.25452910547, 3969806.9787753597, 45.741421878139235], + [232267.25452910547, 3969806.9787753597, 45.70332180213923], + [232262.01391606088, 3969803.6835553492, 45.75836484123303], + [232262.01391606088, 3969803.6835553492, 45.72026476523304], + [232262.26651706803, 3969807.324804136, 45.68536484123304], + [232262.26651706803, 3969807.324804136, 45.64726476523304], + [232257.02590402347, 3969804.0295841256, 45.70313709230435], + [232257.02590402347, 3969804.0295841256, 45.665037016304346], + [232257.27850503064, 3969807.6708329134, 45.630137092304345], + [232257.27850503064, 3969807.6708329134, 45.592037016304346], + [232252.03789198605, 3969804.3756129025, 45.64873863135318], + [232252.03789198605, 3969804.3756129025, 45.610638555353184], + [232252.29049299317, 3969808.0168616897, 45.57573863135319], + [232252.29049299317, 3969808.0168616897, 45.537638555353176], + [232247.04987994864, 3969804.7216416798, 45.59516945837954], + [232247.04987994864, 3969804.7216416798, 45.557069382379524], + [232247.30248095575, 3969808.362890467, 45.52216945837952], + [232247.30248095575, 3969808.362890467, 45.48406938237952], + [232242.06186791116, 3969805.067670456, 45.54242957338338], + [232242.06186791116, 3969805.067670456, 45.504329497383374], + [232242.31446891834, 3969808.708919244, 45.46942957338338], + [232242.31446891834, 3969808.708919244, 45.43132949738337], + [232237.07385587375, 3969805.4136992334, 45.49051897636476], + [232237.07385587375, 3969805.4136992334, 45.45241890036475], + [232237.32645688087, 3969809.0549480203, 45.41751897636475], + [232237.32645688087, 3969809.0549480203, 45.37941890036475], + [232232.0858438363, 3969805.7597280107, 45.43943766732363], + [232232.0858438363, 3969805.7597280107, 45.401337591323625], + [232232.33844484345, 3969809.4009767985, 45.36643766732363], + [232232.33844484345, 3969809.4009767985, 45.328337591323624], + [232227.09783179886, 3969806.105756787, 45.38918564626003], + [232227.09783179886, 3969806.105756787, 45.35108557026003], + [232227.35043280604, 3969809.7470055744, 45.316185646260024], + [232227.35043280604, 3969809.7470055744, 45.27808557026003], + [232222.10981976148, 3969806.451785564, 45.33976291317394], + [232222.10981976148, 3969806.451785564, 45.30166283717394], + [232222.3624207686, 3969810.0930343517, 45.26676291317395], + [232222.3624207686, 3969810.0930343517, 45.228662837173935], + [232217.121807724, 3969806.7978143413, 45.29116946806536], + [232217.121807724, 3969806.7978143413, 45.25306939206536], + [232217.37440873115, 3969810.439063128, 45.21816946806536], + [232217.37440873115, 3969810.439063128, 45.180069392065356], + [232212.1337956866, 3969807.1438431176, 45.2434053109343], + [232212.1337956866, 3969807.1438431176, 45.20530523493429], + [232212.38639669376, 3969810.7850919054, 45.17040531093429], + [232212.38639669376, 3969810.7850919054, 45.13230523493431], + [232207.14578364918, 3969807.489871895, 45.19647044178074], + [232207.14578364918, 3969807.489871895, 45.15837036578075], + [232207.3983846563, 3969811.1311206827, 45.12347044178074], + [232207.3983846563, 3969811.1311206827, 45.085370365780754], + [232202.1577716117, 3969807.8359006722, 45.150364860604704], + [232202.1577716117, 3969807.8359006722, 45.11226478460471], + [232202.41037261888, 3969811.477149459, 45.07736486060471], + [232202.41037261888, 3969811.477149459, 45.03926478460471], + [232197.1697595743, 3969808.181929449, 45.105088567406185], + [232197.1697595743, 3969808.181929449, 45.06698849140619], + [232197.42236058146, 3969811.823178236, 45.03208856740619], + [232197.42236058146, 3969811.823178236, 44.99398849140619], + [232192.18174753687, 3969808.5279582255, 45.060641562185175], + [232192.18174753687, 3969808.5279582255, 45.02254148618517], + [232192.434348544, 3969812.169207013, 44.98764156218517], + [232192.434348544, 3969812.169207013, 44.94954148618517], + [232187.19373549943, 3969808.8739870028, 45.017023844941676], + [232187.19373549943, 3969808.8739870028, 44.97892376894169], + [232187.44633650657, 3969812.5152357896, 44.94402384494168], + [232187.44633650657, 3969812.5152357896, 44.905923768941676], + [232182.20572346202, 3969809.2200157787, 44.9742354156757], + [232182.20572346202, 3969809.2200157787, 44.936135339675694], + [232182.45832446916, 3969812.861264567, 44.9012354156757], + [232182.45832446916, 3969812.861264567, 44.863135339675694], + [232177.2177114246, 3969809.566044556, 44.93227627438722], + [232177.2177114246, 3969809.566044556, 44.89417619838723], + [232177.47031243177, 3969813.207293343, 44.859276274387234], + [232177.47031243177, 3969813.207293343, 44.82117619838722], + [232172.22969938713, 3969809.9120733333, 44.89114642107627], + [232172.22969938713, 3969809.9120733333, 44.85304634507627], + [232172.4823003943, 3969813.553322121, 44.818146421076264], + [232172.4823003943, 3969813.553322121, 44.78004634507627], + [232167.2416873497, 3969810.2581021097, 44.850845855742826], + [232167.2416873497, 3969810.2581021097, 44.81274577974284], + [232167.49428835683, 3969813.8993508974, 44.77784585574283], + [232167.49428835683, 3969813.8993508974, 44.73974577974283], + [232162.2536753123, 3969810.604130888, 44.811374578386896], + [232162.2536753123, 3969810.604130888, 44.773274502386904], + [232162.50627631947, 3969814.245379674, 44.7383745783869], + [232162.50627631947, 3969814.245379674, 44.7002745023869], + [232157.26566327483, 3969810.9501596643, 44.772732589008484], + [232157.26566327483, 3969810.9501596643, 44.73463251300848], + [232157.518264282, 3969814.591408452, 44.699732589008484], + [232157.518264282, 3969814.591408452, 44.661632513008485], + [232152.27765123744, 3969811.296188441, 44.734919887607575], + [232152.27765123744, 3969811.296188441, 44.69681981160758], + [232152.53025224459, 3969814.937437228, 44.661919887607574], + [232152.53025224459, 3969814.937437228, 44.62381981160758], + [232147.2896392, 3969811.6422172175, 44.697936474184196], + [232147.2896392, 3969811.6422172175, 44.6598363981842], + [232147.54224020717, 3969815.283466005, 44.624936474184196], + [232147.54224020717, 3969815.283466005, 44.58683639818419], + [232142.3016271626, 3969811.988245995, 44.66178234873831], + [232142.3016271626, 3969811.988245995, 44.62368227273833], + [232142.55422816973, 3969815.6294947816, 44.58878234873832], + [232142.55422816973, 3969815.6294947816, 44.550682272738314], + [232137.31361512514, 3969812.334274771, 44.626457511269955], + [232137.31361512514, 3969812.334274771, 44.588357435269955], + [232137.5662161323, 3969815.975523559, 44.55345751126995], + [232137.5662161323, 3969815.975523559, 44.515357435269955], + [232132.32560308767, 3969812.680303548, 44.591961961779106], + [232132.32560308767, 3969812.680303548, 44.5538618857791], + [232132.5782040948, 3969816.3215523358, 44.5189619617791], + [232132.5782040948, 3969816.3215523358, 44.480861885779106], + [232131.43967678156, 3969812.7417621, 44.585921894890866], + [232131.43967678156, 3969812.7417621, 44.54782181889087], + [232131.6922777887, 3969816.3830108875, 44.51292189489087], + [232131.6922777887, 3969816.3830108875, 44.47482181889088], + [232127.3375910503, 3969813.0263323253, 44.55801526679104], + [232127.3375910503, 3969813.0263323253, 44.51991519079105], + [232127.59019205743, 3969816.667581113, 44.485015266791045], + [232127.59019205743, 3969816.667581113, 44.44691519079104], + [232122.34957901284, 3969813.3723611026, 44.52408165203908], + [232122.34957901284, 3969813.3723611026, 44.48598157603907], + [232122.60218002, 3969817.0136098894, 44.45108165203908], + [232122.60218002, 3969817.0136098894, 44.41298157603907], + [232117.36156697542, 3969813.718389879, 44.490148037287106], + [232117.36156697542, 3969813.718389879, 44.45204796128711], + [232117.6141679826, 3969817.3596386667, 44.417148037287106], + [232117.6141679826, 3969817.3596386667, 44.379047961287114], + [232112.373554938, 3969814.0644186554, 44.45621442253513], + [232112.373554938, 3969814.0644186554, 44.418114346535134], + [232112.62615594512, 3969817.705667443, 44.38321442253513], + [232112.62615594512, 3969817.705667443, 44.34511434653515], + [232107.38554290053, 3969814.410447432, 44.422280807783174], + [232107.38554290053, 3969814.410447432, 44.38418073178317], + [232107.6381439077, 3969818.05169622, 44.349280807783174], + [232107.6381439077, 3969818.05169622, 44.311180731783175], + [232102.39753086315, 3969814.7564762104, 44.388347193031215], + [232102.39753086315, 3969814.7564762104, 44.3502471170312], + [232102.6501318703, 3969818.3977249963, 44.3153471930312], + [232102.6501318703, 3969818.3977249963, 44.2772471170312], + [232099.09678878385, 3969814.985455558, 44.36589213292445], + [232099.09678878385, 3969814.985455558, 44.327792056924444], + [232099.34938979102, 3969818.626704345, 44.29289213292445], + [232099.34938979102, 3969818.626704345, 44.25479205692446], + [232097.40951882568, 3969815.102504987, 44.3544828295275], + [232097.40951882568, 3969815.102504987, 44.31638275352751], + [232097.66211983282, 3969818.7437537746, 44.281482829527505], + [232097.66211983282, 3969818.7437537746, 44.2433827535275], + [232092.42150678826, 3969815.448533763, 44.32156388468146], + [232092.42150678826, 3969815.448533763, 44.28346380868147], + [232092.6741077954, 3969819.089782551, 44.248563884681474], + [232092.6741077954, 3969819.089782551, 44.21046380868146], + [232087.43349475085, 3969815.7945625405, 44.28985538031647], + [232087.43349475085, 3969815.7945625405, 44.25175530431648], + [232087.68609575796, 3969819.4358113282, 44.216855380316474], + [232087.68609575796, 3969819.4358113282, 44.17875530431647], + [232082.44548271337, 3969816.1405913173, 44.259357316432514], + [232082.44548271337, 3969816.1405913173, 44.22125724043253], + [232082.69808372055, 3969819.781840105, 44.18635731643252], + [232082.69808372055, 3969819.781840105, 44.148257240432514], + [232077.45747067596, 3969816.4866200946, 44.23006969302961], + [232077.45747067596, 3969816.4866200946, 44.1919696170296], + [232077.71007168313, 3969820.1278688814, 44.1570696930296], + [232077.71007168313, 3969820.1278688814, 44.118969617029606], + [232072.46945863854, 3969816.832648871, 44.20199251010773], + [232072.46945863854, 3969816.832648871, 44.16389243410773], + [232072.72205964566, 3969820.4738976588, 44.12899251010773], + [232072.72205964566, 3969820.4738976588, 44.090892434107744], + [232067.48144660107, 3969817.1786776483, 44.175125767666906], + [232067.48144660107, 3969817.1786776483, 44.1370256916669], + [232067.73404760825, 3969820.819926435, 44.1021257676669], + [232067.73404760825, 3969820.819926435, 44.0640256916669], + [232062.49343456366, 3969817.5247064247, 44.149469465707114], + [232062.49343456366, 3969817.5247064247, 44.11136938970711], + [232062.74603557083, 3969821.165955212, 44.07646946570711], + [232062.74603557083, 3969821.165955212, 44.038369389707114], + [232057.5054225262, 3969817.8707352015, 44.12502360422836], + [232057.5054225262, 3969817.8707352015, 44.08692352822836], + [232057.75802353336, 3969821.5119839893, 44.05202360422836], + [232057.75802353336, 3969821.5119839893, 44.01392352822837], + [232052.51741048877, 3969818.216763979, 44.10178818323067], + [232052.51741048877, 3969818.216763979, 44.06368810723066], + [232052.77001149594, 3969821.8580127656, 44.02878818323065], + [232052.77001149594, 3969821.8580127656, 43.99068810723065], + [232047.52939845138, 3969818.562792756, 44.07976320271399], + [232047.52939845138, 3969818.562792756, 44.041663126713985], + [232047.7819994585, 3969822.204041543, 44.006763202713984], + [232047.7819994585, 3969822.204041543, 43.96866312671399], + [232042.5413864139, 3969818.9088215325, 44.05894866267837], + [232042.5413864139, 3969818.9088215325, 44.020848586678376], + [232042.79398742106, 3969822.5500703203, 43.98594866267837], + [232042.79398742106, 3969822.5500703203, 43.94784858667836], + [232037.5533743765, 3969819.2548503093, 44.03934456312378], + [232037.5533743765, 3969819.2548503093, 44.001244487123785], + [232037.80597538367, 3969822.896099097, 43.966344563123776], + [232037.80597538367, 3969822.896099097, 43.928244487123784], + [232036.84953653693, 3969819.303677005, 44.036675759956545], + [232036.84953653693, 3969819.303677005, 43.998575683956545], + [232037.10213754408, 3969822.944925793, 43.96367575995655], + [232037.10213754408, 3969822.944925793, 43.92557568395655], + [232032.56536233908, 3969819.6008790866, 44.02095090405023], + [232032.56536233908, 3969819.6008790866, 43.98285082805024], + [232032.8179633462, 3969823.2421278735, 43.969423256992165], + [232032.8179633462, 3969823.2421278735, 43.93132318099216], + [232027.5773503016, 3969819.946907863, 44.00376768545774], + [232027.5773503016, 3969819.946907863, 43.965667609457746], + [232027.82995130878, 3969823.588156651, 43.97724003839971], + [232027.82995130878, 3969823.588156651, 43.9391399623997], + [232022.5893382642, 3969820.2929366403, 43.98779490734628], + [232022.5893382642, 3969820.2929366403, 43.94969483134627], + [232022.84193927137, 3969823.934185427, 43.98626726028814], + [232022.84193927137, 3969823.934185427, 43.94816718428813], + [232022.28454138056, 3969820.3140810337, 43.98685811901272], + [232022.28454138056, 3969820.3140810337, 43.94875804301272], + [232022.53714238774, 3969823.9553298205, 43.98685811901272], + [232022.53714238774, 3969823.9553298205, 43.94875804301272], + [232017.60089607674, 3969820.6326835407, 43.973032569715855], + [232017.60089607674, 3969820.6326835407, 43.93493249371585], + [232017.84372833796, 3969824.2745968415, 43.996504922657756], + [232017.84372833796, 3969824.2745968415, 43.95840484665774], + [232012.61150532452, 3969820.958202994, 43.959480672566464], + [232012.61150532452, 3969820.958202994, 43.92138059656648], + [232012.84393114215, 3969824.600795235, 44.00795302550832], + [232012.84393114215, 3969824.600795235, 43.96985294950832], + [232007.7155003888, 3969821.2637168565, 43.9473611777864], + [232007.7155003888, 3969821.2637168565, 43.90926110178639], + [232007.93771453897, 3969824.906946313, 44.02036117778651], + [232007.62120488277, 3969821.2694657366, 43.947139215898126], + [232007.93771453897, 3969824.906946313, 43.982261101786506], + [232007.62120488277, 3969821.2694657366, 43.909039139898134], + [232007.84322235952, 3969824.912707183, 44.02061156883998], + [232007.84322235952, 3969824.912707183, 43.98251149283999], + [232006.31806336567, 3969821.3483907105, 43.94411607719644], + [232006.31806336567, 3969821.3483907105, 43.90601600119643], + [232006.53736286156, 3969824.991796773, 44.0241160771958], + [232006.53736286156, 3969824.991796773, 43.986016001195814], + [232002.63003548872, 3969821.566469226, 43.93600819971083], + [232002.63003548872, 3969821.566469226, 43.89790812371083], + [232002.84164281213, 3969825.210330137, 44.03448055265281], + [232002.84164281213, 3969825.210330137, 43.99638047665281], + [231997.63803788653, 3969821.8492110386, 43.92608762400457], + [231997.63803788653, 3969821.8492110386, 43.88798754800458], + [231997.83923332926, 3969825.4936616695, 44.0495599769465], + [231997.83923332926, 3969825.4936616695, 44.01145990094651], + [231992.64525282718, 3969822.1176888673, 43.91737748877936], + [231992.64525282718, 3969822.1176888673, 43.879277412779366], + [231992.83603474675, 3969825.7626994653, 44.06584984172125], + [231992.83603474675, 3969825.7626994653, 44.02774976572125], + [231990.34279626585, 3969822.2366799647, 43.913768945905794], + [231990.34279626585, 3969822.2366799647, 43.8756688699058], + [231990.52877591894, 3969825.8819387443, 44.07376894590464], + [231990.52877591894, 3969825.8819387443, 44.035668869904626], + [231987.65172106802, 3969822.371900519, 43.90987779403519], + [231987.65172106802, 3969822.371900519, 43.87177771803518], + [231987.8320879071, 3969826.0174413295, 44.083350146977146], + [231987.8320879071, 3969826.0174413295, 44.04525007097714], + [231982.6574833726, 3969822.611843919, 43.903588539772045], + [231982.6574833726, 3969822.611843919, 43.86548846377205], + [231982.82743365876, 3969826.2578851823, 44.102060892714015], + [231982.82743365876, 3969826.2578851823, 44.063960816714015], + [231981.6775772967, 3969822.6572443377, 43.90249667647098], + [231981.6775772967, 3969822.6572443377, 43.86439660047098], + [231981.84548377877, 3969826.3033802942, 44.105873815700015], + [231981.84548377877, 3969826.3033802942, 44.06777373970001], + [231977.6625805102, 3969822.8375171074, 43.89850972598996], + [231977.6625805102, 3969822.8375171074, 43.860409649989954], + [231977.8221128561, 3969826.484029061, 44.10188686521898], + [231977.8221128561, 3969826.484029061, 44.06378678921899], + [231974.36007547379, 3969822.978874542, 43.89581672514083], + [231974.36007547379, 3969822.978874542, 43.85771664914085], + [231974.51271973774, 3969826.625681328, 44.099193864369866], + [231974.51271973774, 3969826.625681328, 44.06109378836987], + [231972.66705325549, 3969823.0489182444, 43.8946413526889], + [231972.66705325549, 3969823.0489182444, 43.85654127668891], + [231972.81616635883, 3969826.695871121, 44.09801849191794], + [231972.81616635883, 3969826.695871121, 44.05991841591793], + [231967.6709423882, 3969823.246045602, 43.89198341986889], + [231967.6709423882, 3969823.246045602, 43.853883343868894], + [231967.80963503176, 3969826.89340963, 44.09536055909793], + [231967.80963503176, 3969826.89340963, 44.05726048309792], + [231962.67428869297, 3969823.4288975727, 43.89053592752993], + [231962.67428869297, 3969823.4288975727, 43.85243585152993], + [231962.80255974457, 3969827.0766429775, 44.09391306675895], + [231962.80255974457, 3969827.0766429775, 44.05581299075896], + [231958.3712370051, 3969823.574912402, 43.89025941490154], + [231958.3712370051, 3969823.574912402, 43.85215933890154], + [231958.49053312026, 3969827.222962352, 44.09363655413057], + [231958.49053312026, 3969827.222962352, 44.05553647813056], + [231957.67713295875, 3969823.5974726626, 43.890298875672], + [231957.67713295875, 3969823.5974726626, 43.852198799671996], + [231957.79498137117, 3969827.2455696664, 44.09367601490102], + [231957.79498137117, 3969827.2455696664, 44.055575938901036], + [231952.67951597858, 3969823.7517694957, 43.89127226429511], + [231952.67951597858, 3969823.7517694957, 43.853172188295105], + [231952.7869407899, 3969827.400188319, 44.09464940352413], + [231952.7869407899, 3969827.400188319, 44.056549327524145], + [231947.68147854935, 3969823.8917868137, 43.89345609339926], + [231947.68147854935, 3969823.8917868137, 43.85535601739927], + [231947.7784788826, 3969827.540497673, 44.09683323262829], + [231947.7784788826, 3969827.540497673, 44.058733156628286], + [231942.68306147133, 3969824.017523472, 43.89685036298445], + [231942.68306147133, 3969824.017523472, 43.85875028698446], + [231942.7696365347, 3969827.6664965823, 44.100227502213485], + [231942.7696365347, 3969827.6664965823, 44.06212742621348], + [231942.37761738684, 3969824.0247437214, 43.89709701518792], + [231942.37761738684, 3969824.0247437214, 43.85899693918792], + [231942.4635553811, 3969827.6737318896, 44.100474154416936], + [231942.4635553811, 3969827.6737318896, 44.06237407841695], + [231937.6843055479, 3969824.1289784457, 43.901455073050684], + [231937.6843055479, 3969824.1289784457, 43.86335499705069], + [231937.76045463458, 3969827.778184018, 44.104832212279725], + [231937.76045463458, 3969827.778184018, 44.06673213627971], + [231935.05473618413, 3969824.181873632, 43.90436306506987], + [231935.05473618413, 3969824.181873632, 43.86626298906988], + [231935.12540074045, 3969827.8311895295, 44.107740204298906], + [231935.12540074045, 3969827.8311895295, 44.0696401282989], + [231932.68525158515, 3969824.226150823, 43.90727022359796], + [231932.68525158515, 3969824.226150823, 43.86917014759797], + [231932.7509740736, 3969827.87555907, 44.09879787065106], + [231932.7509740736, 3969827.87555907, 44.06069779465106], + [231927.6859403918, 3969824.309039812, 43.91429581462628], + [231927.6859403918, 3969824.309039812, 43.87619573862628], + [231927.7412357454, 3969827.958620942, 44.0808234616794], + [231927.7412357454, 3969827.958620942, 44.04272338567941], + [231926.38055354578, 3969824.3283308963, 43.91632952599996], + [231926.38055354578, 3969824.3283308963, 43.878229449999964], + [231926.43312623544, 3969827.9779522615, 44.07632952599877], + [231926.43312623544, 3969827.9779522615, 44.03822944999877], + [231922.6864127783, 3969824.377644737, 43.92253184613564], + [231922.6864127783, 3969824.377644737, 43.88443177013564], + [231922.73128054582, 3969828.027368957, 44.06405949318883], + [231922.73128054582, 3969828.027368957, 44.02595941718883], + [231917.6867095573, 3969824.4319650354, 43.93197831812604], + [231917.6867095573, 3969824.4319650354, 43.89387824212604], + [231917.72114937234, 3969828.081802552, 44.04850596517924], + [231917.72114937234, 3969828.081802552, 44.010405889179225], + [231912.68687154257, 3969824.4720002664, 43.942635230597475], + [231912.68687154257, 3969824.4720002664, 43.90453515459749], + [231912.71088312403, 3969828.1219212846, 44.03416287765059], + [231912.71088312403, 3969828.1219212846, 43.99606280165058], + [231910.3813826965, 3969824.4856485515, 43.947956947337666], + [231910.3813826965, 3969824.4856485515, 43.90985687133767], + [231910.400585687, 3969828.1355980365, 44.02795694733703], + [231910.400585687, 3969828.1355980365, 43.98985687133703], + [231908.98139927528, 3969824.4924540888, 43.95131407330675], + [231908.98139927528, 3969824.4924540888, 43.91321399730674], + [231908.99768230034, 3969828.142417769, 44.024314073306854], + [231908.99768230034, 3969828.142417769, 43.98621399730685], + [231907.68693954908, 3969824.4977501007, 43.95450258354995], + [231907.68693954908, 3969824.4977501007, 43.916402507549954], + [231907.70052270102, 3969828.1477248264, 44.02103023060307], + [231907.70052270102, 3969828.1477248264, 43.982930154603075], + [231902.68695439264, 3969824.5092143305, 43.96758037698347], + [231902.68695439264, 3969824.5092143305, 43.92948030098347], + [231902.6901090041, 3969828.159212967, 44.00910802403662], + [231902.6901090041, 3969828.159212967, 43.971007948036636], + [231897.6869568894, 3969824.50639286, 43.98186861089804], + [231897.6869568894, 3969824.50639286, 43.94376853489804], + [231897.67968293463, 3969828.1563856127, 43.99839625795123], + [231897.67968293463, 3969828.1563856127, 43.960296181951236], + [231894.38144222982, 3969824.496683535, 43.99197927920104], + [231894.38144222982, 3969824.496683535, 43.953879203201055], + [231894.36727391588, 3969828.1466560364, 43.99197927920104], + [231894.36727391588, 3969828.1466560364, 43.953879203201055], + [231892.68698440643, 3969824.490106059, 43.99736728529365], + [231892.68698440643, 3969824.490106059, 43.95926720929364], + [231892.6728160925, 3969828.14007856, 43.98889493234681], + [231892.6728160925, 3969828.14007856, 43.95079485634681], + [231887.6870220762, 3969824.4706974085, 44.01407640017029], + [231887.6870220762, 3969824.4706974085, 43.9759763241703], + [231887.6728537622, 3969828.1206699107, 43.98060404722341], + [231887.6728537622, 3969828.1206699107, 43.942503971223395], + [231882.6870597459, 3969824.4512887597, 44.031995955527975], + [231882.6870597459, 3969824.4512887597, 43.99389587952797], + [231882.67289143192, 3969828.1012612614, 43.97352360258118], + [231882.67289143192, 3969828.1012612614, 43.93542352658119], + [231879.78155222532, 3969824.4400102794, 44.042965184812765], + [231879.78155222532, 3969824.4400102794, 44.00486510881276], + [231879.76738391138, 3969828.0899827806, 43.969965184812764], + [231879.76738391138, 3969828.0899827806, 43.93186510881276], + [231877.68709741556, 3969824.4318801104, 44.05112595136669], + [231877.68709741556, 3969824.4318801104, 44.013025875366694], + [231877.67292910168, 3969828.0818526116, 43.97812595136669], + [231877.67292910168, 3969828.0818526116, 43.9400258753667], + [231872.68713508526, 3969824.4124714616, 44.07146638768647], + [231872.68713508526, 3969824.4124714616, 44.033366311686464], + [231872.67296677132, 3969828.0624439623, 43.99846638768647], + [231872.67296677132, 3969828.0624439623, 43.960366311686464], + [231867.68717275502, 3969824.3930628123, 44.09301726448727], + [231867.68717275502, 3969824.3930628123, 44.054917188487266], + [231867.67300444108, 3969828.043035313, 44.020017264487265], + [231867.67300444108, 3969828.043035313, 43.98191718848727], + [231862.68721042472, 3969824.373654163, 44.115778581769135], + [231862.68721042472, 3969824.373654163, 44.07767850576912], + [231862.67304211075, 3969828.023626664, 44.04277858176912], + [231862.67304211075, 3969828.023626664, 44.00467850576912], + [231857.6872480944, 3969824.3542455127, 44.139750339532014], + [231857.6872480944, 3969824.3542455127, 44.101650263532015], + [231857.67307978045, 3969828.004218015, 44.066750339532014], + [231857.67307978045, 3969828.004218015, 44.02865026353201], + [231852.68728576408, 3969824.334836864, 44.16493253777594], + [231852.68728576408, 3969824.334836864, 44.126832461775955], + [231852.6731174502, 3969827.984809365, 44.091932537775946], + [231852.6731174502, 3969827.984809365, 44.05383246177594], + [231847.68732343384, 3969824.315428215, 44.19132517650092], + [231847.68732343384, 3969824.315428215, 44.15322510050091], + [231847.6731551199, 3969827.9654007168, 44.11832517650092], + [231847.6731551199, 3969827.9654007168, 44.08022510050092], + [231842.68736110354, 3969824.296019566, 44.21892825570693], + [231842.68736110354, 3969824.296019566, 44.180828179706936], + [231842.67319278957, 3969827.9459920665, 44.14592825570692], + [231842.67319278957, 3969827.9459920665, 44.10782817970692], + [231837.6873987732, 3969824.2766109165, 44.247741775393976], + [231837.6873987732, 3969824.2766109165, 44.209641699393984], + [231837.67323045927, 3969827.9265834177, 44.17474177539398], + [231837.67323045927, 3969827.9265834177, 44.136641699393984], + [231832.68743644297, 3969824.2572022676, 44.27776573556207], + [231832.68743644297, 3969824.2572022676, 44.23966565956208], + [231832.67326812903, 3969827.9071747684, 44.20476573556207], + [231832.67326812903, 3969827.9071747684, 44.16666565956208], + [231827.68747411267, 3969824.2377936174, 44.30900013621121], + [231827.68747411267, 3969824.2377936174, 44.27090006021121], + [231827.67330579873, 3969827.8877661196, 44.23600013621122], + [231827.67330579873, 3969827.8877661196, 44.19790006021122], + [231822.68751178237, 3969824.2183849686, 44.34144497734138], + [231822.68751178237, 3969824.2183849686, 44.30334490134138], + [231822.6733434684, 3969827.8683574703, 44.26844497734138], + [231822.6733434684, 3969827.8683574703, 44.2303449013414], + [231817.68754945206, 3969824.1989763193, 44.3751002589526], + [231817.68754945206, 3969824.1989763193, 44.337000182952615], + [231817.67338113816, 3969827.8489488205, 44.302100258952606], + [231817.67338113816, 3969827.8489488205, 44.2640001829526], + [231812.6875871218, 3969824.17956767, 44.40996598104487], + [231812.6875871218, 3969824.17956767, 44.37186590504487], + [231812.67341880786, 3969827.829540171, 44.33696598104487], + [231812.67341880786, 3969827.829540171, 44.29886590504486], + [231807.6876247915, 3969824.160159021, 44.44604214361816], + [231807.6876247915, 3969824.160159021, 44.40794206761816], + [231807.67345647755, 3969827.810131522, 44.37304214361816], + [231807.67345647755, 3969827.810131522, 44.33494206761817], + [231802.68766246125, 3969824.140750372, 44.4833287466725], + [231802.68766246125, 3969824.140750372, 44.44522867067251], + [231802.67349414725, 3969827.790722873, 44.410328746672505], + [231802.67349414725, 3969827.790722873, 44.3722286706725], + [231797.68770013095, 3969824.121341723, 44.521825790207885], + [231797.68770013095, 3969824.121341723, 44.483725714207885], + [231797.67353181698, 3969827.7713142238, 44.448825790207884], + [231797.67353181698, 3969827.7713142238, 44.4107257142079], + [231792.68773780062, 3969824.1019330737, 44.56153327422431], + [231792.68773780062, 3969824.1019330737, 44.52343319822431], + [231792.67356948668, 3969827.751905575, 44.4885332742243], + [231792.67356948668, 3969827.751905575, 44.45043319822431], + [231787.68777547032, 3969824.082524424, 44.60245119872178], + [231787.68777547032, 3969824.082524424, 44.56435112272177], + [231787.67360715638, 3969827.7324969256, 44.529451198721766], + [231787.67360715638, 3969827.7324969256, 44.49135112272177], + [231782.68781314002, 3969824.0631157747, 44.644579563700276], + [231782.68781314002, 3969824.0631157747, 44.60647948770028], + [231782.67364482608, 3969827.7130882763, 44.57157956370029], + [231782.67364482608, 3969827.7130882763, 44.533479487700276], + [231777.68785080977, 3969824.0437071254, 44.687918369159824], + [231777.68785080977, 3969824.0437071254, 44.64981829315983], + [231777.6736824958, 3969827.6936796266, 44.614918369159824], + [231777.6736824958, 3969827.6936796266, 44.57681829315982], + [231772.68788847944, 3969824.0242984765, 44.732467615100404], + [231772.68788847944, 3969824.0242984765, 44.69436753910041], + [231772.6737201655, 3969827.6742709773, 44.65946761510041], + [231772.6737201655, 3969827.6742709773, 44.62136753910041], + [231767.68792614914, 3969824.004889827, 44.77822730152203], + [231767.68792614914, 3969824.004889827, 44.74012722552204], + [231767.67375783526, 3969827.6548623284, 44.70522730152203], + [231767.67375783526, 3969827.6548623284, 44.667127225522044], + [231762.68796381884, 3969823.985481178, 44.82519742842471], + [231762.68796381884, 3969823.985481178, 44.7870973524247], + [231762.6737955049, 3969827.635453679, 44.75219742842471], + [231762.6737955049, 3969827.635453679, 44.71409735242471], + [231757.6880014886, 3969823.966072529, 44.87337799580842], + [231757.6880014886, 3969823.966072529, 44.83527791980842], + [231757.67383317463, 3969827.61604503, 44.80037799580841], + [231757.67383317463, 3969827.61604503, 44.76227791980842], + [231752.68803915827, 3969823.94666388, 44.92276900367316], + [231752.68803915827, 3969823.94666388, 44.88466892767317], + [231752.67387084433, 3969827.596636381, 44.84976900367317], + [231752.67387084433, 3969827.596636381, 44.81166892767317], + [231747.68807682797, 3969823.927255231, 44.973370452018955], + [231747.68807682797, 3969823.927255231, 44.935270376018956], + [231747.67390851403, 3969827.5772277317, 44.900370452018954], + [231747.67390851403, 3969827.5772277317, 44.86227037601895], + [231742.68811449772, 3969823.9078465807, 45.02518234084579], + [231742.68811449772, 3969823.9078465807, 44.98708226484579], + [231742.6739461838, 3969827.557819082, 44.95218234084578], + [231742.6739461838, 3969827.557819082, 44.91408226484579], + [231737.68815216742, 3969823.8884379314, 45.07820467015365], + [231737.68815216742, 3969823.8884379314, 45.040104594153654], + [231737.67398385346, 3969827.5384104326, 45.00520467015366], + [231737.67398385346, 3969827.5384104326, 44.96710459415366], + [231732.68818983712, 3969823.8690292826, 45.13243743994258], + [231732.68818983712, 3969823.8690292826, 45.09433736394257], + [231732.67402152315, 3969827.5190017833, 45.05943743994257], + [231732.67402152315, 3969827.5190017833, 45.02133736394258], + [231727.68822750685, 3969823.8496206333, 45.18788065021253], + [231727.68822750685, 3969823.8496206333, 45.14978057421254], + [231727.6740591929, 3969827.4995931336, 45.114880650212534], + [231727.6740591929, 3969827.4995931336, 45.07678057421253], + [231722.68826517655, 3969823.8302119835, 45.24453430096352], + [231722.68826517655, 3969823.8302119835, 45.20643422496353], + [231722.6740968626, 3969827.480184485, 45.17153430096353], + [231722.6740968626, 3969827.480184485, 45.13343422496352], + [231717.68830284625, 3969823.810803334, 45.302398392195556], + [231717.68830284625, 3969823.810803334, 45.26429831619556], + [231717.67413453228, 3969827.4607758354, 45.22939839219556], + [231717.67413453228, 3969827.4607758354, 45.19129831619557], + [231712.688340516, 3969823.7913946854, 45.361472923908636], + [231712.688340516, 3969823.7913946854, 45.323372847908644], + [231712.67417220204, 3969827.441367187, 45.28847292390865], + [231712.67417220204, 3969827.441367187, 45.250372847908636], + [231707.68837818567, 3969823.771986036, 45.421757896102754], + [231707.68837818567, 3969823.771986036, 45.38365782010277], + [231707.67420987174, 3969827.4219585373, 45.34875789610276], + [231707.67420987174, 3969827.4219585373, 45.310657820102755], + [231702.68841585537, 3969823.752577387, 45.48325330877792], + [231702.68841585537, 3969823.752577387, 45.44515323277791], + [231702.67424754144, 3969827.402549889, 45.41025330877792], + [231702.67424754144, 3969827.402549889, 45.37215323277792], + [231697.68845352507, 3969823.733168738, 45.54595916193413], + [231697.68845352507, 3969823.733168738, 45.507859085934115], + [231697.67428521113, 3969827.3831412387, 45.472959161934114], + [231697.67428521113, 3969827.3831412387, 45.43485908593412], + [231692.68849119483, 3969823.7137600887, 45.60987545557136], + [231692.68849119483, 3969823.7137600887, 45.571775379571356], + [231692.67432288086, 3969827.36373259, 45.536875455571355], + [231692.67432288086, 3969827.36373259, 45.498775379571356], + [231687.6885288645, 3969823.69435144, 45.675002189689636], + [231687.6885288645, 3969823.69435144, 45.63690211368964], + [231687.67436055056, 3969827.3443239406, 45.602002189689635], + [231687.67436055056, 3969827.3443239406, 45.56390211368965], + [231682.6885665342, 3969823.6749427896, 45.74133936428896], + [231682.6885665342, 3969823.6749427896, 45.70323928828896], + [231682.67439822032, 3969827.324915291, 45.66833936428897], + [231682.67439822032, 3969827.324915291, 45.630239288288976], + [231677.6886042039, 3969823.6555341403, 45.808886979369326], + [231677.6886042039, 3969823.6555341403, 45.770786903369334], + [231677.67443588996, 3969827.3055066415, 45.73588697936933], + [231677.67443588996, 3969827.3055066415, 45.69778690336933], + [231672.6886418736, 3969823.6361254915, 45.877645034930744], + [231672.6886418736, 3969823.6361254915, 45.83954495893073], + [231672.6744735597, 3969827.286097992, 45.80464503493073], + [231672.6744735597, 3969827.286097992, 45.76654495893073], + [231667.68867954332, 3969823.616716842, 45.94761353097318], + [231667.68867954332, 3969823.616716842, 45.90951345497319], + [231667.6745112294, 3969827.2666893434, 45.87461353097319], + [231667.6745112294, 3969827.2666893434, 45.83651345497318], + [231662.68871721302, 3969823.5973081933, 46.018792467496674], + [231662.68871721302, 3969823.5973081933, 45.980692391496675], + [231662.6745488991, 3969827.247280694, 45.945792467496666], + [231662.6745488991, 3969827.247280694, 45.90769239149668], + [231657.68875488272, 3969823.577899543, 46.09118184450119], + [231657.68875488272, 3969823.577899543, 46.053081768501194], + [231657.67458656884, 3969827.2278720452, 46.01818184450119], + [231657.67458656884, 3969827.2278720452, 45.9800817685012], + [231652.68879255248, 3969823.5584908947, 46.164781661986765], + [231652.68879255248, 3969823.5584908947, 46.12668158598677], + [231652.6746242385, 3969827.208463396, 46.09178166198678], + [231652.6746242385, 3969827.208463396, 46.053681585986766], + [231647.68883022218, 3969823.539082245, 46.23959191995337], + [231647.68883022218, 3969823.539082245, 46.20149184395337], + [231647.6746619082, 3969827.1890547466, 46.16659191995337], + [231647.6746619082, 3969827.1890547466, 46.128491843953384], + [231642.68886789185, 3969823.5196735957, 46.31561261840104], + [231642.68886789185, 3969823.5196735957, 46.27751254240103], + [231642.6746995779, 3969827.169646098, 46.242612618401026], + [231642.6746995779, 3969827.169646098, 46.20451254240103], + [231637.6889055616, 3969823.500264947, 46.392843757329715], + [231637.6889055616, 3969823.500264947, 46.35474368132972], + [231637.67473724767, 3969827.1502374476, 46.31984375732973], + [231637.67473724767, 3969827.1502374476, 46.281743681329715], + [231632.6889432313, 3969823.4808562975, 46.47128533673945], + [231632.6889432313, 3969823.4808562975, 46.43318526073946], + [231632.67477491734, 3969827.1308287983, 46.398285336739455], + [231632.67477491734, 3969827.1308287983, 46.360185260739456], + [231627.68898090097, 3969823.4614476482, 46.55093735663023], + [231627.68898090097, 3969823.4614476482, 46.51283728063022], + [231627.67481258704, 3969827.1114201494, 46.47793735663023], + [231627.67481258704, 3969827.1114201494, 46.43983728063023], + [231622.68901857073, 3969823.4420389994, 46.63179981700204], + [231622.68901857073, 3969823.4420389994, 46.593699741002055], + [231622.6748502568, 3969827.0920115, 46.55879981700205], + [231622.6748502568, 3969827.0920115, 46.52069974100204], + [231617.68905624043, 3969823.42263035, 46.7138727178549], + [231617.68905624043, 3969823.42263035, 46.6757726418549], + [231617.6748879265, 3969827.0726028513, 46.640872717854904], + [231617.6748879265, 3969827.0726028513, 46.60277264185491], + [231612.68909391013, 3969823.4032217003, 46.79715605918881], + [231612.68909391013, 3969823.4032217003, 46.759055983188794], + [231612.6749255962, 3969827.053194201, 46.72415605918879], + [231612.6749255962, 3969827.053194201, 46.686055983188794], + [231607.6891315799, 3969823.383813051, 46.881649841003735], + [231607.6891315799, 3969823.383813051, 46.84354976500373], + [231607.67496326592, 3969827.0337855523, 46.80864984100373], + [231607.67496326592, 3969827.0337855523, 46.770549765003736], + [231602.68916924956, 3969823.364404402, 46.96735406329972], + [231602.68916924956, 3969823.364404402, 46.92925398729971], + [231602.67500093562, 3969827.014376903, 46.89435406329971], + [231602.67500093562, 3969827.014376903, 46.85625398729971], + [231597.68920691925, 3969823.344995752, 47.05426872607673], + [231597.68920691925, 3969823.344995752, 47.016168650076736], + [231597.67503860532, 3969826.9949682537, 46.98126872607673], + [231597.67503860532, 3969826.9949682537, 46.943168650076736], + [231592.68924458895, 3969823.3255871036, 47.142393829334786], + [231592.68924458895, 3969823.3255871036, 47.104293753334794], + [231592.67507627502, 3969826.975559605, 47.0693938293348], + [231592.67507627502, 3969826.975559605, 47.031293753334786], + [231587.68928225865, 3969823.306178454, 47.2317293730739], + [231587.68928225865, 3969823.306178454, 47.19362929707389], + [231587.67511394474, 3969826.9561509555, 47.15872937307389], + [231587.67511394474, 3969826.9561509555, 47.12062929707389], + [231582.68931992838, 3969823.2867698045, 47.32227535729403], + [231582.68931992838, 3969823.2867698045, 47.28417528129403], + [231582.67515161444, 3969826.9367423067, 47.24927535729403], + [231582.67515161444, 3969826.9367423067, 47.21117528129404], + [231577.68935759808, 3969823.2673611557, 47.41403178199523], + [231577.68935759808, 3969823.2673611557, 47.37593170599522], + [231577.67518928414, 3969826.9173336574, 47.34103178199522], + [231577.67518928414, 3969826.9173336574, 47.30293170599522], + [231572.68939526778, 3969823.2479525064, 47.50699864717744], + [231572.68939526778, 3969823.2479525064, 47.468898571177455], + [231572.6752269539, 3969826.8979250076, 47.43399864717745], + [231572.6752269539, 3969826.8979250076, 47.39589857117744], + [231567.68943293748, 3969823.228543857, 47.60117595284071], + [231567.68943293748, 3969823.228543857, 47.56307587684072], + [231567.67526462357, 3969826.8785163583, 47.52817595284071], + [231567.67526462357, 3969826.8785163583, 47.490075876840706], + [231564.38078293134, 3969823.2157004746, 47.66416188818293], + [231564.38078293134, 3969823.2157004746, 47.626061812182925], + [231564.3666146174, 3969826.8656729762, 47.59116188818293], + [231564.3666146174, 3969826.8656729762, 47.553061812182925], + [231562.6894706072, 3969823.2091352083, 47.69649444773677], + [231562.6894706072, 3969823.2091352083, 47.65839437173678], + [231562.67530229327, 3969826.859107709, 47.623494447736775], + [231562.67530229327, 3969826.859107709, 47.58539437173677], + [231557.6895082769, 3969823.189726559, 47.79207796445618], + [231557.6895082769, 3969823.189726559, 47.753977888456184], + [231557.67533996297, 3969826.83969906, 47.71907796445618], + [231557.67533996297, 3969826.83969906, 47.68097788845619], + [231552.6895459466, 3969823.170317909, 47.887661481175606], + [231552.6895459466, 3969823.170317909, 47.849561405175606], + [231552.67537763267, 3969826.82029041, 47.81466148117561], + [231552.67537763267, 3969826.82029041, 47.7765614051756], + [231547.6895836163, 3969823.15090926, 47.983244997895014], + [231547.6895836163, 3969823.15090926, 47.945144921895015], + [231547.6754153024, 3969826.8008817616, 47.91024499789501], + [231547.6754153024, 3969826.8008817616, 47.87214492189503], + [231542.68962128603, 3969823.131500611, 48.078828514614436], + [231542.68962128603, 3969823.131500611, 48.040728438614444], + [231542.6754529721, 3969826.781473112, 48.00582851461445], + [231542.6754529721, 3969826.781473112, 47.96772843861444], + [231537.6896589558, 3969823.1120919613, 48.17441203133386], + [231537.6896589558, 3969823.1120919613, 48.136311955333845], + [231537.6754906418, 3969826.7620644625, 48.101412031333844], + [231537.6754906418, 3969826.7620644625, 48.06331195533385], + [231532.68969662543, 3969823.0926833125, 48.26999554805326], + [231532.68969662543, 3969823.0926833125, 48.231895472053274], + [231532.6755283115, 3969826.7426558146, 48.196995548053266], + [231532.6755283115, 3969826.7426558146, 48.15889547205326], + [231527.68973429519, 3969823.0732746636, 48.365579064772696], + [231527.68973429519, 3969823.0732746636, 48.32747898877268], + [231527.67556598125, 3969826.7232471644, 48.29257906477268], + [231527.67556598125, 3969826.7232471644, 48.25447898877268], + [231522.68977196486, 3969823.0538660144, 48.46116258149209], + [231522.68977196486, 3969823.0538660144, 48.4230625054921], + [231522.67560365092, 3969826.7038385156, 48.388162581492104], + [231522.67560365092, 3969826.7038385156, 48.35006250549209], + [231517.68980963455, 3969823.0344573655, 48.55674609821151], + [231517.68980963455, 3969823.0344573655, 48.518646022211506], + [231517.67564132062, 3969826.6844298663, 48.48374609821151], + [231517.67564132062, 3969826.6844298663, 48.44564602221151], + [231512.6898473043, 3969823.015048715, 48.65232961493093], + [231512.6898473043, 3969823.015048715, 48.61422953893093], + [231512.67567899037, 3969826.665021217, 48.579329614930934], + [231512.67567899037, 3969826.665021217, 48.541229538930935], + [231507.689884974, 3969822.995640066, 48.74791313165035], + [231507.689884974, 3969822.995640066, 48.709813055650336], + [231507.67571666007, 3969826.645612567, 48.674913131650335], + [231507.67571666007, 3969826.645612567, 48.63681305565034], + [231502.68992264368, 3969822.9762314167, 48.84349664836976], + [231502.68992264368, 3969822.9762314167, 48.80539657236976], + [231502.6757543298, 3969826.626203918, 48.77049664836976], + [231502.6757543298, 3969826.626203918, 48.73239657236975], + [231497.68996031344, 3969822.956822768, 48.93908016508918], + [231497.68996031344, 3969822.956822768, 48.90098008908918], + [231497.6757919995, 3969826.606795269, 48.86608016508917], + [231497.6757919995, 3969826.606795269, 48.82798008908918], + [231492.68999798314, 3969822.9374141186, 49.03466368180858], + [231492.68999798314, 3969822.9374141186, 48.99656360580859], + [231492.6758296692, 3969826.587386619, 48.96166368180859], + [231492.6758296692, 3969826.587386619, 48.92356360580859], + [231487.69003565283, 3969822.918005469, 49.13024719852801], + [231487.69003565283, 3969822.918005469, 49.092147122528], + [231487.67586733887, 3969826.5679779705, 49.057247198528], + [231487.67586733887, 3969826.5679779705, 49.019147122528004], + [231482.69007332253, 3969822.8985968204, 49.22583071524742], + [231482.69007332253, 3969822.8985968204, 49.18773063924743], + [231482.67590500863, 3969826.5485693216, 49.15283071524742], + [231482.67590500863, 3969826.5485693216, 49.114730639247426], + [231477.69011099226, 3969822.8791881707, 49.321414231966834], + [231477.69011099226, 3969822.8791881707, 49.283314155966835], + [231477.67594267832, 3969826.5291606723, 49.24841423196683], + [231477.67594267832, 3969826.5291606723, 49.210314155966834], + [231472.69014866196, 3969822.8597795214, 49.41699774868624], + [231472.69014866196, 3969822.8597795214, 49.37889767268625], + [231472.67598034802, 3969826.5097520235, 49.343997748686256], + [231472.67598034802, 3969826.5097520235, 49.30589767268624], + [231467.69018633166, 3969822.840370872, 49.51258126540567], + [231467.69018633166, 3969822.840370872, 49.47448118940567], + [231467.67601801772, 3969826.4903433733, 49.439581265405664], + [231467.67601801772, 3969826.4903433733, 49.401481189405665], + [231462.69022400136, 3969822.820962223, 49.60816478212507], + [231462.69022400136, 3969822.820962223, 49.57006470612508], + [231462.67605568745, 3969826.470934724, 49.53516478212508], + [231462.67605568745, 3969826.470934724, 49.49706470612508], + [231457.6902616711, 3969822.801553574, 49.7037482988445], + [231457.6902616711, 3969822.801553574, 49.66564822284449], + [231457.67609335715, 3969826.451526075, 49.63074829884449], + [231457.67609335715, 3969826.451526075, 49.592648222844495], + [231452.69029934084, 3969822.7821449237, 49.79933181556391], + [231452.69029934084, 3969822.7821449237, 49.76123173956391], + [231452.67613102685, 3969826.432117426, 49.72633181556391], + [231452.67613102685, 3969826.432117426, 49.688231739563925], + [231447.69033701048, 3969822.762736275, 49.894915332283325], + [231447.69033701048, 3969822.762736275, 49.856815256283326], + [231447.67616869655, 3969826.412708776, 49.82191533228332], + [231447.67616869655, 3969826.412708776, 49.78381525628332], + [231442.69037468018, 3969822.743327626, 49.99049884900275], + [231442.69037468018, 3969822.743327626, 49.95239877300274], + [231442.67620636628, 3969826.393300127, 49.91749884900274], + [231442.67620636628, 3969826.393300127, 49.87939877300275], + [231437.6904123499, 3969822.7239189767, 50.086082365722156], + [231437.6904123499, 3969822.7239189767, 50.04798228972217], + [231437.67624403597, 3969826.373891478, 50.01308236572216], + [231437.67624403597, 3969826.373891478, 49.974982289722156], + [231432.6904500196, 3969822.7045103274, 50.181665882441564], + [231432.6904500196, 3969822.7045103274, 50.14356580644158], + [231432.67628170567, 3969826.3544828286, 50.10866588244157], + [231432.67628170567, 3969826.3544828286, 50.070565806441564], + [231427.69048768937, 3969822.6851016777, 50.277249399160986], + [231427.69048768937, 3969822.6851016777, 50.239149323160994], + [231427.67631937537, 3969826.3350741793, 50.204249399160986], + [231427.67631937537, 3969826.3350741793, 50.16614932316099], + [231422.69052535907, 3969822.6656930293, 50.37283291588041], + [231422.69052535907, 3969822.6656930293, 50.3347328398804], + [231422.6763570451, 3969826.3156655305, 50.29983291588041], + [231422.6763570451, 3969826.3156655305, 50.26173283988041], + [231417.69056302874, 3969822.64628438, 50.46841643259982], + [231417.69056302874, 3969822.64628438, 50.43031635659981], + [231417.67639471486, 3969826.296256881, 50.395416432599816], + [231417.67639471486, 3969826.296256881, 50.35731635659981], + [231412.69060069844, 3969822.62687573, 50.56399994931923], + [231412.69060069844, 3969822.62687573, 50.52589987331923], + [231412.6764323845, 3969826.2768482324, 50.49099994931923], + [231412.6764323845, 3969826.2768482324, 50.45289987331924], + [231407.6906383682, 3969822.607467081, 50.659583466038654], + [231407.6906383682, 3969822.607467081, 50.621483390038655], + [231407.67647005426, 3969826.2574395817, 50.586583466038654], + [231407.67647005426, 3969826.2574395817, 50.54848339003865], + [231402.6906760379, 3969822.588058432, 50.75516698275806], + [231402.6906760379, 3969822.588058432, 50.71706690675807], + [231402.67650772393, 3969826.238030933, 50.68216698275806], + [231402.67650772393, 3969826.238030933, 50.644066906758056], + [231401.1420717323, 3969822.582047123, 50.78477141490276], + [231401.1420717323, 3969822.582047123, 50.746671338902765], + [231401.12790341835, 3969826.2320196237, 50.71177141490277], + [231401.12790341835, 3969826.2320196237, 50.67367133890276], + [231397.69071277653, 3969822.58850313, 50.85075049947748], + [231397.69071277653, 3969822.58850313, 50.812650423477486], + [231397.7185359965, 3969826.238397083, 50.777750499477484], + [231397.7185359965, 3969826.238397083, 50.739650423477485], + [231394.2172831071, 3969822.635093217, 50.917157368033834], + [231394.2172831071, 3969822.635093217, 50.87905729203383], + [231394.28736638805, 3969826.2844203236, 50.84415736803383], + [231394.28736638805, 3969826.2844203236, 50.80605729203384], + [231392.6914071272, 3969822.6682798564, 50.94633401619691], + [231392.6914071272, 3969822.6682798564, 50.908233940196894], + [231392.78005523258, 3969826.317203193, 50.8733340161969], + [231392.78005523258, 3969826.317203193, 50.8352339401969], + [231387.6941253603, 3969822.8313634074, 51.041917532917275], + [231387.6941253603, 3969822.8313634074, 51.00381745691726], + [231387.84357372724, 3969826.47830256, 50.96891753291726], + [231387.84357372724, 3969826.47830256, 50.93081745691726], + [231387.29556377884, 3969822.847961545, 51.04954332116488], + [231387.29556377884, 3969822.847961545, 51.01144324516488], + [231387.44986131164, 3969826.494698755, 50.97459975409567], + [231387.44986131164, 3969826.494698755, 50.936499678095664], + [231382.7002555777, 3969823.077708482, 51.13750104963573], + [231382.7002555777, 3969823.077708482, 51.09940097363573], + [231382.91046269366, 3969826.7216504365, 51.040139899101916], + [231382.91046269366, 3969826.7216504365, 51.00203982310191], + [231380.38060190907, 3969823.220538685, 51.18192927429592], + [231380.38060190907, 3969823.220538685, 51.143829198295926], + [231380.61903147798, 3969826.862742872, 51.073244804574344], + [231380.61903147798, 3969826.862742872, 51.03514472857434], + [231377.7111849332, 3969823.4072466516, 51.23308456635514], + [231377.7111849332, 3969823.4072466516, 51.19498449035515], + [231377.9820924086, 3969827.0471792254, 51.111362265287525], + [231377.9820924086, 3969827.0471792254, 51.07326218928752], + [231373.47608205935, 3969823.752626111, 51.31431522742697], + [231373.47608205935, 3969823.752626111, 51.276215151426975], + [231373.79851661975, 3969827.3883565674, 51.171889855053095], + [231373.79851661975, 3969827.3883565674, 51.1337897790531], + [231372.7282992477, 3969823.8198863817, 51.328668083074554], + [231372.7282992477, 3969823.8198863817, 51.29056800707455], + [231373.05983183227, 3969827.4547985056, 51.18258463147302], + [231373.05983183227, 3969827.4547985056, 51.14448455547303], + [231368.14504822757, 3969827.9443950504, 51.25380699765858], + [231368.14504822757, 3969827.9443950504, 51.21570692165858], + [231367.75298262408, 3969824.3155130525, 51.42425159979397], + [231367.75298262408, 3969824.3155130525, 51.38615152379398], + [231366.99195097337, 3969828.071259775, 51.27053490553187], + [231366.99195097337, 3969828.071259775, 51.232434829531854], + [231366.58568322717, 3969824.443940307, 51.44670118055802], + [231366.58568322717, 3969824.443940307, 51.40860110455801], + [231363.23910678053, 3969828.515832867, 51.32502936384429], + [231363.23910678053, 3969828.515832867, 51.28692928784427], + [231362.78661706272, 3969824.8939889916, 51.5198351165134], + [231362.78661706272, 3969824.8939889916, 51.481735040513385], + [231360.20296134258, 3969828.9110886157, 51.36917995601071], + [231360.20296134258, 3969828.9110886157, 51.3310798800107], + [231359.7130768859, 3969825.294112915, 51.579087133689065], + [231359.7130768859, 3969825.294112915, 51.54098705768906], + [231358.3433702212, 3969829.1689532236, 51.39625173002977], + [231358.3433702212, 3969829.1689532236, 51.35815165402976], + [231357.8305820777, 3969825.5551535166, 51.61541863323281], + [231357.8305820777, 3969825.5551535166, 51.57731855723279], + [231353.45919844485, 3969829.903574703, 51.46747409621529], + [231353.45919844485, 3969829.903574703, 51.42937402021529], + [231353.43516516592, 3969829.9073955966, 51.46782500648959], + [231353.43516516592, 3969829.9073955966, 51.4297249304896], + [231352.88625431352, 3969826.298822975, 51.71100214995222], + [231352.88625431352, 3969826.298822975, 51.67290207395222], + [231352.8619250283, 3969826.302690928, 51.7114730868201], + [231352.8619250283, 3969826.302690928, 51.6733730108201], + [231348.5879481345, 3969830.7194932476, 51.538696462400914], + [231348.5879481345, 3969830.7194932476, 51.5005963864009], + [231347.95500716282, 3969827.1247907947, 51.80658566667163], + [231347.95500716282, 3969827.1247907947, 51.76848559067164], + [231346.69216858927, 3969831.059649846, 51.566470056968136], + [231346.69216858927, 3969831.059649846, 51.52836998096813], + [231346.03587821542, 3969827.469136938, 51.84385903995114], + [231346.03587821542, 3969827.469136938, 51.80575896395115], + [231343.78080942994, 3969831.606852569, 51.609186890185114], + [231343.78080942994, 3969831.606852569, 51.57108681418512], + [231343.73097238384, 3969831.6164822197, 51.610169183391044], + [231343.73097238384, 3969831.6164822197, 51.57206910739105], + [231343.0886612497, 3969828.0230792924, 51.90118689018512], + [231343.0886612497, 3969828.0230792924, 51.86308681418512], + [231343.03821038472, 3969828.0328275478, 51.90216918339105], + [231343.03821038472, 3969828.0328275478, 51.864069107391046], + [231339.9775645442, 3969832.367237399, 51.68424499308219], + [231339.9775645442, 3969832.367237399, 51.64614491708219], + [231339.2385736313, 3969828.7928294153, 51.97624499308219], + [231339.2385736313, 3969828.7928294153, 51.938144917082184], + [231338.88962032163, 3969832.5942924623, 51.705752700110466], + [231338.88962032163, 3969832.5942924623, 51.66765262411046], + [231338.13722972453, 3969829.022681006, 51.99775270011046], + [231338.13722972453, 3969829.022681006, 51.959652624110475], + [231334.0652367368, 3969833.652652365, 51.801336216829874], + [231334.0652367368, 3969833.652652365, 51.76323614082989], + [231333.25342653418, 3969830.0940762185, 52.09333621682988], + [231333.25342653418, 3969830.0940762185, 52.055236140829884], + [231333.29493083383, 3969833.8294615205, 51.81663094621323], + [231333.29493083383, 3969833.8294615205, 51.77853087021324], + [231332.473633145, 3969830.2730630464, 52.10863094621324], + [231332.473633145, 3969830.2730630464, 52.07053087021323], + [231329.2591617048, 3969834.791267948, 51.89691973354929], + [231329.2591617048, 3969834.791267948, 51.85881965754929], + [231328.38815739428, 3969831.24671558, 52.1889197335493], + [231328.38815739428, 3969831.24671558, 52.1508196575493], + [231326.6478282261, 3969835.44554308, 51.94901689934428], + [231326.6478282261, 3969835.44554308, 51.91091682334427], + [231325.74466138077, 3969831.909049104, 52.241016899344274], + [231325.74466138077, 3969831.909049104, 52.20291682334428], + [231324.4727302156, 3969836.009822936, 51.99250325026871], + [231324.4727302156, 3969836.009822936, 51.95440317426871], + [231323.5427737373, 3969832.480278922, 52.28450325026871], + [231323.5427737373, 3969832.480278922, 52.24640317426871], + [231320.03979855657, 3969837.214620969, 52.081402852475314], + [231320.03979855657, 3969837.214620969, 52.043302776475315], + [231319.70727180273, 3969837.3079788485, 52.08808676698813], + [231319.70727180273, 3969837.3079788485, 52.04998669098812], + [231319.0552437973, 3969833.699915871, 52.37340285247532], + [231319.0552437973, 3969833.699915871, 52.33530277647533], + [231318.71862147184, 3969833.794423595, 52.38008676698812], + [231318.71862147184, 3969833.794423595, 52.34198669098813] + ], + "pointIndex": [ + 960, + 959, + 957, + 958, + 0, + 959, + 963, + 961, + 957, + 0, + 963, + 964, + 962, + 961, + 0, + 964, + 960, + 958, + 962, + 0, + 958, + 957, + 953, + 954, + 0, + 957, + 961, + 955, + 953, + 0, + 961, + 962, + 956, + 955, + 0, + 962, + 958, + 954, + 956, + 0, + 954, + 953, + 949, + 950, + 0, + 953, + 955, + 951, + 949, + 0, + 955, + 956, + 952, + 951, + 0, + 956, + 954, + 950, + 952, + 0, + 950, + 949, + 945, + 946, + 0, + 949, + 951, + 947, + 945, + 0, + 951, + 952, + 948, + 947, + 0, + 952, + 950, + 946, + 948, + 0, + 946, + 945, + 941, + 942, + 0, + 945, + 947, + 943, + 941, + 0, + 947, + 948, + 944, + 943, + 0, + 948, + 946, + 942, + 944, + 0, + 942, + 941, + 937, + 938, + 0, + 941, + 943, + 939, + 937, + 0, + 943, + 944, + 940, + 939, + 0, + 944, + 942, + 938, + 940, + 0, + 938, + 937, + 933, + 934, + 0, + 937, + 939, + 935, + 933, + 0, + 939, + 940, + 936, + 935, + 0, + 940, + 938, + 934, + 936, + 0, + 934, + 933, + 929, + 930, + 0, + 933, + 935, + 931, + 929, + 0, + 935, + 936, + 932, + 931, + 0, + 936, + 934, + 930, + 932, + 0, + 930, + 929, + 923, + 924, + 0, + 929, + 931, + 927, + 923, + 0, + 931, + 932, + 928, + 927, + 0, + 932, + 930, + 924, + 928, + 0, + 924, + 923, + 921, + 922, + 0, + 923, + 927, + 925, + 921, + 0, + 927, + 928, + 926, + 925, + 0, + 928, + 924, + 922, + 926, + 0, + 922, + 921, + 917, + 918, + 0, + 921, + 925, + 919, + 917, + 0, + 925, + 926, + 920, + 919, + 0, + 926, + 922, + 918, + 920, + 0, + 918, + 917, + 913, + 914, + 0, + 917, + 919, + 915, + 913, + 0, + 919, + 920, + 916, + 915, + 0, + 920, + 918, + 914, + 916, + 0, + 914, + 913, + 907, + 908, + 0, + 913, + 915, + 911, + 907, + 0, + 915, + 916, + 912, + 911, + 0, + 916, + 914, + 908, + 912, + 0, + 908, + 907, + 905, + 906, + 0, + 907, + 911, + 909, + 905, + 0, + 911, + 912, + 910, + 909, + 0, + 912, + 908, + 906, + 910, + 0, + 906, + 905, + 901, + 902, + 0, + 905, + 909, + 903, + 901, + 0, + 909, + 910, + 904, + 903, + 0, + 910, + 906, + 902, + 904, + 0, + 902, + 901, + 897, + 898, + 0, + 901, + 903, + 899, + 897, + 0, + 903, + 904, + 900, + 899, + 0, + 904, + 902, + 898, + 900, + 0, + 898, + 897, + 893, + 894, + 0, + 897, + 899, + 895, + 893, + 0, + 899, + 900, + 896, + 895, + 0, + 900, + 898, + 894, + 896, + 0, + 894, + 893, + 889, + 890, + 0, + 893, + 895, + 891, + 889, + 0, + 895, + 896, + 892, + 891, + 0, + 896, + 894, + 890, + 892, + 0, + 890, + 889, + 885, + 886, + 0, + 889, + 891, + 887, + 885, + 0, + 891, + 892, + 888, + 887, + 0, + 892, + 890, + 886, + 888, + 0, + 886, + 885, + 883, + 884, + 0, + 885, + 887, + 881, + 883, + 0, + 887, + 888, + 882, + 881, + 0, + 888, + 886, + 884, + 882, + 0, + 884, + 883, + 879, + 880, + 0, + 883, + 881, + 877, + 879, + 0, + 881, + 882, + 878, + 877, + 0, + 882, + 884, + 880, + 878, + 0, + 880, + 879, + 875, + 876, + 0, + 879, + 877, + 873, + 875, + 0, + 877, + 878, + 874, + 873, + 0, + 878, + 880, + 876, + 874, + 0, + 876, + 875, + 871, + 872, + 0, + 875, + 873, + 869, + 871, + 0, + 873, + 874, + 870, + 869, + 0, + 874, + 876, + 872, + 870, + 0, + 872, + 871, + 867, + 868, + 0, + 871, + 869, + 865, + 867, + 0, + 869, + 870, + 866, + 865, + 0, + 870, + 872, + 868, + 866, + 0, + 868, + 867, + 863, + 864, + 0, + 867, + 865, + 861, + 863, + 0, + 865, + 866, + 862, + 861, + 0, + 866, + 868, + 864, + 862, + 0, + 864, + 863, + 859, + 860, + 0, + 863, + 861, + 857, + 859, + 0, + 861, + 862, + 858, + 857, + 0, + 862, + 864, + 860, + 858, + 0, + 860, + 859, + 855, + 856, + 0, + 859, + 857, + 853, + 855, + 0, + 857, + 858, + 854, + 853, + 0, + 858, + 860, + 856, + 854, + 0, + 856, + 855, + 851, + 852, + 0, + 855, + 853, + 849, + 851, + 0, + 853, + 854, + 850, + 849, + 0, + 854, + 856, + 852, + 850, + 0, + 852, + 851, + 847, + 848, + 0, + 851, + 849, + 845, + 847, + 0, + 849, + 850, + 846, + 845, + 0, + 850, + 852, + 848, + 846, + 0, + 848, + 847, + 843, + 844, + 0, + 847, + 845, + 841, + 843, + 0, + 845, + 846, + 842, + 841, + 0, + 846, + 848, + 844, + 842, + 0, + 844, + 843, + 839, + 840, + 0, + 843, + 841, + 837, + 839, + 0, + 841, + 842, + 838, + 837, + 0, + 842, + 844, + 840, + 838, + 0, + 840, + 839, + 835, + 836, + 0, + 839, + 837, + 833, + 835, + 0, + 837, + 838, + 834, + 833, + 0, + 838, + 840, + 836, + 834, + 0, + 836, + 835, + 831, + 832, + 0, + 835, + 833, + 829, + 831, + 0, + 833, + 834, + 830, + 829, + 0, + 834, + 836, + 832, + 830, + 0, + 832, + 831, + 827, + 828, + 0, + 831, + 829, + 825, + 827, + 0, + 829, + 830, + 826, + 825, + 0, + 830, + 832, + 828, + 826, + 0, + 828, + 827, + 823, + 824, + 0, + 827, + 825, + 821, + 823, + 0, + 825, + 826, + 822, + 821, + 0, + 826, + 828, + 824, + 822, + 0, + 824, + 823, + 819, + 820, + 0, + 823, + 821, + 817, + 819, + 0, + 821, + 822, + 818, + 817, + 0, + 822, + 824, + 820, + 818, + 0, + 820, + 819, + 815, + 816, + 0, + 819, + 817, + 813, + 815, + 0, + 817, + 818, + 814, + 813, + 0, + 818, + 820, + 816, + 814, + 0, + 816, + 815, + 811, + 812, + 0, + 815, + 813, + 809, + 811, + 0, + 813, + 814, + 810, + 809, + 0, + 814, + 816, + 812, + 810, + 0, + 812, + 811, + 807, + 808, + 0, + 811, + 809, + 805, + 807, + 0, + 809, + 810, + 806, + 805, + 0, + 810, + 812, + 808, + 806, + 0, + 808, + 807, + 803, + 804, + 0, + 807, + 805, + 801, + 803, + 0, + 805, + 806, + 802, + 801, + 0, + 806, + 808, + 804, + 802, + 0, + 804, + 803, + 799, + 800, + 0, + 803, + 801, + 797, + 799, + 0, + 801, + 802, + 798, + 797, + 0, + 802, + 804, + 800, + 798, + 0, + 800, + 799, + 795, + 796, + 0, + 799, + 797, + 793, + 795, + 0, + 797, + 798, + 794, + 793, + 0, + 798, + 800, + 796, + 794, + 0, + 796, + 795, + 791, + 792, + 0, + 795, + 793, + 789, + 791, + 0, + 793, + 794, + 790, + 789, + 0, + 794, + 796, + 792, + 790, + 0, + 792, + 791, + 787, + 788, + 0, + 791, + 789, + 785, + 787, + 0, + 789, + 790, + 786, + 785, + 0, + 790, + 792, + 788, + 786, + 0, + 788, + 787, + 783, + 784, + 0, + 787, + 785, + 781, + 783, + 0, + 785, + 786, + 782, + 781, + 0, + 786, + 788, + 784, + 782, + 0, + 784, + 783, + 779, + 780, + 0, + 783, + 781, + 777, + 779, + 0, + 781, + 782, + 778, + 777, + 0, + 782, + 784, + 780, + 778, + 0, + 780, + 779, + 775, + 776, + 0, + 779, + 777, + 773, + 775, + 0, + 777, + 778, + 774, + 773, + 0, + 778, + 780, + 776, + 774, + 0, + 776, + 775, + 771, + 772, + 0, + 775, + 773, + 769, + 771, + 0, + 773, + 774, + 770, + 769, + 0, + 774, + 776, + 772, + 770, + 0, + 772, + 771, + 767, + 768, + 0, + 771, + 769, + 765, + 767, + 0, + 769, + 770, + 766, + 765, + 0, + 770, + 772, + 768, + 766, + 0, + 768, + 767, + 763, + 764, + 0, + 767, + 765, + 761, + 763, + 0, + 765, + 766, + 762, + 761, + 0, + 766, + 768, + 764, + 762, + 0, + 764, + 763, + 759, + 760, + 0, + 763, + 761, + 757, + 759, + 0, + 761, + 762, + 758, + 757, + 0, + 762, + 764, + 760, + 758, + 0, + 760, + 759, + 755, + 756, + 0, + 759, + 757, + 753, + 755, + 0, + 757, + 758, + 754, + 753, + 0, + 758, + 760, + 756, + 754, + 0, + 756, + 755, + 751, + 752, + 0, + 755, + 753, + 749, + 751, + 0, + 753, + 754, + 750, + 749, + 0, + 754, + 756, + 752, + 750, + 0, + 752, + 751, + 747, + 748, + 0, + 751, + 749, + 745, + 747, + 0, + 749, + 750, + 746, + 745, + 0, + 750, + 752, + 748, + 746, + 0, + 748, + 747, + 743, + 744, + 0, + 747, + 745, + 741, + 743, + 0, + 745, + 746, + 742, + 741, + 0, + 746, + 748, + 744, + 742, + 0, + 744, + 743, + 739, + 740, + 0, + 743, + 741, + 737, + 739, + 0, + 741, + 742, + 738, + 737, + 0, + 742, + 744, + 740, + 738, + 0, + 740, + 739, + 735, + 736, + 0, + 739, + 737, + 733, + 735, + 0, + 737, + 738, + 734, + 733, + 0, + 738, + 740, + 736, + 734, + 0, + 736, + 735, + 731, + 732, + 0, + 735, + 733, + 729, + 731, + 0, + 733, + 734, + 730, + 729, + 0, + 734, + 736, + 732, + 730, + 0, + 732, + 731, + 727, + 728, + 0, + 731, + 729, + 725, + 727, + 0, + 729, + 730, + 726, + 725, + 0, + 730, + 732, + 728, + 726, + 0, + 728, + 727, + 723, + 724, + 0, + 727, + 725, + 721, + 723, + 0, + 725, + 726, + 722, + 721, + 0, + 726, + 728, + 724, + 722, + 0, + 724, + 723, + 719, + 720, + 0, + 723, + 721, + 717, + 719, + 0, + 721, + 722, + 718, + 717, + 0, + 722, + 724, + 720, + 718, + 0, + 720, + 719, + 715, + 716, + 0, + 719, + 717, + 713, + 715, + 0, + 717, + 718, + 714, + 713, + 0, + 718, + 720, + 716, + 714, + 0, + 716, + 715, + 711, + 712, + 0, + 715, + 713, + 709, + 711, + 0, + 713, + 714, + 710, + 709, + 0, + 714, + 716, + 712, + 710, + 0, + 712, + 711, + 707, + 708, + 0, + 711, + 709, + 705, + 707, + 0, + 709, + 710, + 706, + 705, + 0, + 710, + 712, + 708, + 706, + 0, + 708, + 707, + 703, + 704, + 0, + 707, + 705, + 701, + 703, + 0, + 705, + 706, + 702, + 701, + 0, + 706, + 708, + 704, + 702, + 0, + 704, + 703, + 699, + 700, + 0, + 703, + 701, + 697, + 699, + 0, + 701, + 702, + 698, + 697, + 0, + 702, + 704, + 700, + 698, + 0, + 700, + 699, + 695, + 696, + 0, + 699, + 697, + 693, + 695, + 0, + 697, + 698, + 694, + 693, + 0, + 698, + 700, + 696, + 694, + 0, + 696, + 695, + 691, + 692, + 0, + 695, + 693, + 689, + 691, + 0, + 693, + 694, + 690, + 689, + 0, + 694, + 696, + 692, + 690, + 0, + 692, + 691, + 687, + 688, + 0, + 691, + 689, + 685, + 687, + 0, + 689, + 690, + 686, + 685, + 0, + 690, + 692, + 688, + 686, + 0, + 688, + 687, + 683, + 684, + 0, + 687, + 685, + 681, + 683, + 0, + 685, + 686, + 682, + 681, + 0, + 686, + 688, + 684, + 682, + 0, + 684, + 683, + 679, + 680, + 0, + 683, + 681, + 677, + 679, + 0, + 681, + 682, + 678, + 677, + 0, + 682, + 684, + 680, + 678, + 0, + 680, + 679, + 675, + 676, + 0, + 679, + 677, + 673, + 675, + 0, + 677, + 678, + 674, + 673, + 0, + 678, + 680, + 676, + 674, + 0, + 676, + 675, + 671, + 672, + 0, + 675, + 673, + 669, + 671, + 0, + 673, + 674, + 670, + 669, + 0, + 674, + 676, + 672, + 670, + 0, + 672, + 671, + 667, + 668, + 0, + 671, + 669, + 665, + 667, + 0, + 669, + 670, + 666, + 665, + 0, + 670, + 672, + 668, + 666, + 0, + 668, + 667, + 663, + 664, + 0, + 667, + 665, + 661, + 663, + 0, + 665, + 666, + 662, + 661, + 0, + 666, + 668, + 664, + 662, + 0, + 664, + 663, + 659, + 660, + 0, + 663, + 661, + 657, + 659, + 0, + 661, + 662, + 658, + 657, + 0, + 662, + 664, + 660, + 658, + 0, + 660, + 659, + 655, + 656, + 0, + 659, + 657, + 653, + 655, + 0, + 657, + 658, + 654, + 653, + 0, + 658, + 660, + 656, + 654, + 0, + 656, + 655, + 651, + 652, + 0, + 655, + 653, + 649, + 651, + 0, + 653, + 654, + 650, + 649, + 0, + 654, + 656, + 652, + 650, + 0, + 652, + 651, + 647, + 648, + 0, + 651, + 649, + 645, + 647, + 0, + 649, + 650, + 646, + 645, + 0, + 650, + 652, + 648, + 646, + 0, + 648, + 647, + 643, + 644, + 0, + 647, + 645, + 641, + 643, + 0, + 645, + 646, + 642, + 641, + 0, + 646, + 648, + 644, + 642, + 0, + 644, + 643, + 639, + 640, + 0, + 643, + 641, + 637, + 639, + 0, + 641, + 642, + 638, + 637, + 0, + 642, + 644, + 640, + 638, + 0, + 640, + 639, + 635, + 636, + 0, + 639, + 637, + 633, + 635, + 0, + 637, + 638, + 634, + 633, + 0, + 638, + 640, + 636, + 634, + 0, + 636, + 635, + 631, + 632, + 0, + 635, + 633, + 629, + 631, + 0, + 633, + 634, + 630, + 629, + 0, + 634, + 636, + 632, + 630, + 0, + 632, + 631, + 627, + 628, + 0, + 631, + 629, + 625, + 627, + 0, + 629, + 630, + 626, + 625, + 0, + 630, + 632, + 628, + 626, + 0, + 628, + 627, + 623, + 624, + 0, + 627, + 625, + 621, + 623, + 0, + 625, + 626, + 622, + 621, + 0, + 626, + 628, + 624, + 622, + 0, + 624, + 623, + 619, + 620, + 0, + 623, + 621, + 617, + 619, + 0, + 621, + 622, + 618, + 617, + 0, + 622, + 624, + 620, + 618, + 0, + 620, + 619, + 615, + 616, + 0, + 619, + 617, + 613, + 615, + 0, + 617, + 618, + 614, + 613, + 0, + 618, + 620, + 616, + 614, + 0, + 616, + 615, + 611, + 612, + 0, + 615, + 613, + 609, + 611, + 0, + 613, + 614, + 610, + 609, + 0, + 614, + 616, + 612, + 610, + 0, + 612, + 611, + 607, + 608, + 0, + 611, + 609, + 605, + 607, + 0, + 609, + 610, + 606, + 605, + 0, + 610, + 612, + 608, + 606, + 0, + 608, + 607, + 603, + 604, + 0, + 607, + 605, + 601, + 603, + 0, + 605, + 606, + 602, + 601, + 0, + 606, + 608, + 604, + 602, + 0, + 604, + 603, + 599, + 600, + 0, + 603, + 601, + 597, + 599, + 0, + 601, + 602, + 598, + 597, + 0, + 602, + 604, + 600, + 598, + 0, + 600, + 599, + 595, + 596, + 0, + 599, + 597, + 593, + 595, + 0, + 597, + 598, + 594, + 593, + 0, + 598, + 600, + 596, + 594, + 0, + 596, + 595, + 591, + 592, + 0, + 595, + 593, + 589, + 591, + 0, + 593, + 594, + 590, + 589, + 0, + 594, + 596, + 592, + 590, + 0, + 592, + 591, + 587, + 588, + 0, + 591, + 589, + 585, + 587, + 0, + 589, + 590, + 586, + 585, + 0, + 590, + 592, + 588, + 586, + 0, + 588, + 587, + 583, + 584, + 0, + 587, + 585, + 581, + 583, + 0, + 585, + 586, + 582, + 581, + 0, + 586, + 588, + 584, + 582, + 0, + 584, + 583, + 579, + 580, + 0, + 583, + 581, + 577, + 579, + 0, + 581, + 582, + 578, + 577, + 0, + 582, + 584, + 580, + 578, + 0, + 580, + 579, + 575, + 576, + 0, + 579, + 577, + 573, + 575, + 0, + 577, + 578, + 574, + 573, + 0, + 578, + 580, + 576, + 574, + 0, + 576, + 575, + 571, + 572, + 0, + 575, + 573, + 569, + 571, + 0, + 573, + 574, + 570, + 569, + 0, + 574, + 576, + 572, + 570, + 0, + 572, + 571, + 567, + 568, + 0, + 571, + 569, + 565, + 567, + 0, + 569, + 570, + 566, + 565, + 0, + 570, + 572, + 568, + 566, + 0, + 568, + 567, + 563, + 564, + 0, + 567, + 565, + 561, + 563, + 0, + 565, + 566, + 562, + 561, + 0, + 566, + 568, + 564, + 562, + 0, + 564, + 563, + 559, + 560, + 0, + 563, + 561, + 557, + 559, + 0, + 561, + 562, + 558, + 557, + 0, + 562, + 564, + 560, + 558, + 0, + 560, + 559, + 555, + 556, + 0, + 559, + 557, + 553, + 555, + 0, + 557, + 558, + 554, + 553, + 0, + 558, + 560, + 556, + 554, + 0, + 556, + 555, + 551, + 552, + 0, + 555, + 553, + 549, + 551, + 0, + 553, + 554, + 550, + 549, + 0, + 554, + 556, + 552, + 550, + 0, + 552, + 551, + 547, + 548, + 0, + 551, + 549, + 545, + 547, + 0, + 549, + 550, + 546, + 545, + 0, + 550, + 552, + 548, + 546, + 0, + 548, + 547, + 543, + 544, + 0, + 547, + 545, + 541, + 543, + 0, + 545, + 546, + 542, + 541, + 0, + 546, + 548, + 544, + 542, + 0, + 544, + 543, + 539, + 540, + 0, + 543, + 541, + 537, + 539, + 0, + 541, + 542, + 538, + 537, + 0, + 542, + 544, + 540, + 538, + 0, + 540, + 539, + 535, + 536, + 0, + 539, + 537, + 533, + 535, + 0, + 537, + 538, + 534, + 533, + 0, + 538, + 540, + 536, + 534, + 0, + 536, + 535, + 531, + 532, + 0, + 535, + 533, + 529, + 531, + 0, + 533, + 534, + 530, + 529, + 0, + 534, + 536, + 532, + 530, + 0, + 532, + 531, + 527, + 528, + 0, + 531, + 529, + 525, + 527, + 0, + 529, + 530, + 526, + 525, + 0, + 530, + 532, + 528, + 526, + 0, + 528, + 527, + 523, + 524, + 0, + 527, + 525, + 521, + 523, + 0, + 525, + 526, + 522, + 521, + 0, + 526, + 528, + 524, + 522, + 0, + 524, + 523, + 519, + 520, + 0, + 523, + 521, + 517, + 519, + 0, + 521, + 522, + 518, + 517, + 0, + 522, + 524, + 520, + 518, + 0, + 520, + 519, + 515, + 516, + 0, + 519, + 517, + 513, + 515, + 0, + 517, + 518, + 514, + 513, + 0, + 518, + 520, + 516, + 514, + 0, + 516, + 515, + 511, + 512, + 0, + 515, + 513, + 509, + 511, + 0, + 513, + 514, + 510, + 509, + 0, + 514, + 516, + 512, + 510, + 0, + 512, + 511, + 507, + 508, + 0, + 511, + 509, + 505, + 507, + 0, + 509, + 510, + 506, + 505, + 0, + 510, + 512, + 508, + 506, + 0, + 508, + 507, + 503, + 504, + 0, + 507, + 505, + 501, + 503, + 0, + 505, + 506, + 502, + 501, + 0, + 506, + 508, + 504, + 502, + 0, + 504, + 503, + 499, + 500, + 0, + 503, + 501, + 497, + 499, + 0, + 501, + 502, + 498, + 497, + 0, + 502, + 504, + 500, + 498, + 0, + 500, + 499, + 495, + 496, + 0, + 499, + 497, + 493, + 495, + 0, + 497, + 498, + 494, + 493, + 0, + 498, + 500, + 496, + 494, + 0, + 496, + 495, + 491, + 492, + 0, + 495, + 493, + 489, + 491, + 0, + 493, + 494, + 490, + 489, + 0, + 494, + 496, + 492, + 490, + 0, + 492, + 491, + 487, + 488, + 0, + 491, + 489, + 485, + 487, + 0, + 489, + 490, + 486, + 485, + 0, + 490, + 492, + 488, + 486, + 0, + 488, + 487, + 483, + 484, + 0, + 487, + 485, + 481, + 483, + 0, + 485, + 486, + 482, + 481, + 0, + 486, + 488, + 484, + 482, + 0, + 484, + 483, + 479, + 480, + 0, + 483, + 481, + 477, + 479, + 0, + 481, + 482, + 478, + 477, + 0, + 482, + 484, + 480, + 478, + 0, + 480, + 479, + 475, + 476, + 0, + 479, + 477, + 473, + 475, + 0, + 477, + 478, + 474, + 473, + 0, + 478, + 480, + 476, + 474, + 0, + 476, + 475, + 471, + 472, + 0, + 475, + 473, + 469, + 471, + 0, + 473, + 474, + 470, + 469, + 0, + 474, + 476, + 472, + 470, + 0, + 472, + 471, + 467, + 468, + 0, + 471, + 469, + 465, + 467, + 0, + 469, + 470, + 466, + 465, + 0, + 470, + 472, + 468, + 466, + 0, + 468, + 467, + 463, + 464, + 0, + 467, + 465, + 461, + 463, + 0, + 465, + 466, + 462, + 461, + 0, + 466, + 468, + 464, + 462, + 0, + 464, + 463, + 459, + 460, + 0, + 463, + 461, + 457, + 459, + 0, + 461, + 462, + 458, + 457, + 0, + 462, + 464, + 460, + 458, + 0, + 460, + 459, + 455, + 456, + 0, + 459, + 457, + 453, + 455, + 0, + 457, + 458, + 454, + 453, + 0, + 458, + 460, + 456, + 454, + 0, + 456, + 455, + 451, + 452, + 0, + 455, + 453, + 449, + 451, + 0, + 453, + 454, + 450, + 449, + 0, + 454, + 456, + 452, + 450, + 0, + 452, + 451, + 447, + 448, + 0, + 451, + 449, + 445, + 447, + 0, + 449, + 450, + 446, + 445, + 0, + 450, + 452, + 448, + 446, + 0, + 448, + 447, + 443, + 444, + 0, + 447, + 445, + 441, + 443, + 0, + 445, + 446, + 442, + 441, + 0, + 446, + 448, + 444, + 442, + 0, + 444, + 443, + 439, + 440, + 0, + 443, + 441, + 437, + 439, + 0, + 441, + 442, + 438, + 437, + 0, + 442, + 444, + 440, + 438, + 0, + 440, + 439, + 435, + 436, + 0, + 439, + 437, + 433, + 435, + 0, + 437, + 438, + 434, + 433, + 0, + 438, + 440, + 436, + 434, + 0, + 436, + 435, + 431, + 432, + 0, + 435, + 433, + 429, + 431, + 0, + 433, + 434, + 430, + 429, + 0, + 434, + 436, + 432, + 430, + 0, + 432, + 431, + 427, + 428, + 0, + 431, + 429, + 425, + 427, + 0, + 429, + 430, + 426, + 425, + 0, + 430, + 432, + 428, + 426, + 0, + 428, + 427, + 423, + 424, + 0, + 427, + 425, + 421, + 423, + 0, + 425, + 426, + 422, + 421, + 0, + 426, + 428, + 424, + 422, + 0, + 424, + 423, + 419, + 420, + 0, + 423, + 421, + 417, + 419, + 0, + 421, + 422, + 418, + 417, + 0, + 422, + 424, + 420, + 418, + 0, + 420, + 419, + 415, + 416, + 0, + 419, + 417, + 413, + 415, + 0, + 417, + 418, + 414, + 413, + 0, + 418, + 420, + 416, + 414, + 0, + 416, + 415, + 411, + 412, + 0, + 415, + 413, + 409, + 411, + 0, + 413, + 414, + 410, + 409, + 0, + 414, + 416, + 412, + 410, + 0, + 412, + 411, + 407, + 408, + 0, + 411, + 409, + 405, + 407, + 0, + 409, + 410, + 406, + 405, + 0, + 410, + 412, + 408, + 406, + 0, + 408, + 407, + 403, + 404, + 0, + 407, + 405, + 401, + 403, + 0, + 405, + 406, + 402, + 401, + 0, + 406, + 408, + 404, + 402, + 0, + 404, + 403, + 399, + 400, + 0, + 403, + 401, + 397, + 399, + 0, + 401, + 402, + 398, + 397, + 0, + 402, + 404, + 400, + 398, + 0, + 400, + 399, + 395, + 396, + 0, + 399, + 397, + 393, + 395, + 0, + 397, + 398, + 394, + 393, + 0, + 398, + 400, + 396, + 394, + 0, + 396, + 395, + 391, + 392, + 0, + 395, + 393, + 389, + 391, + 0, + 393, + 394, + 390, + 389, + 0, + 394, + 396, + 392, + 390, + 0, + 392, + 391, + 387, + 388, + 0, + 391, + 389, + 385, + 387, + 0, + 389, + 390, + 386, + 385, + 0, + 390, + 392, + 388, + 386, + 0, + 388, + 387, + 383, + 384, + 0, + 387, + 385, + 381, + 383, + 0, + 385, + 386, + 382, + 381, + 0, + 386, + 388, + 384, + 382, + 0, + 384, + 383, + 379, + 380, + 0, + 383, + 381, + 377, + 379, + 0, + 381, + 382, + 378, + 377, + 0, + 382, + 384, + 380, + 378, + 0, + 380, + 379, + 375, + 376, + 0, + 379, + 377, + 373, + 375, + 0, + 377, + 378, + 374, + 373, + 0, + 378, + 380, + 376, + 374, + 0, + 376, + 375, + 371, + 372, + 0, + 375, + 373, + 369, + 371, + 0, + 373, + 374, + 370, + 369, + 0, + 374, + 376, + 372, + 370, + 0, + 372, + 371, + 367, + 368, + 0, + 371, + 369, + 365, + 367, + 0, + 369, + 370, + 366, + 365, + 0, + 370, + 372, + 368, + 366, + 0, + 368, + 367, + 363, + 364, + 0, + 367, + 365, + 361, + 363, + 0, + 365, + 366, + 362, + 361, + 0, + 366, + 368, + 364, + 362, + 0, + 364, + 363, + 359, + 360, + 0, + 363, + 361, + 357, + 359, + 0, + 361, + 362, + 358, + 357, + 0, + 362, + 364, + 360, + 358, + 0, + 360, + 359, + 355, + 356, + 0, + 359, + 357, + 353, + 355, + 0, + 357, + 358, + 354, + 353, + 0, + 358, + 360, + 356, + 354, + 0, + 356, + 355, + 351, + 352, + 0, + 355, + 353, + 349, + 351, + 0, + 353, + 354, + 350, + 349, + 0, + 354, + 356, + 352, + 350, + 0, + 352, + 351, + 347, + 348, + 0, + 351, + 349, + 345, + 347, + 0, + 349, + 350, + 346, + 345, + 0, + 350, + 352, + 348, + 346, + 0, + 348, + 347, + 343, + 344, + 0, + 347, + 345, + 341, + 343, + 0, + 345, + 346, + 342, + 341, + 0, + 346, + 348, + 344, + 342, + 0, + 344, + 343, + 339, + 340, + 0, + 343, + 341, + 337, + 339, + 0, + 341, + 342, + 338, + 337, + 0, + 342, + 344, + 340, + 338, + 0, + 340, + 339, + 335, + 336, + 0, + 339, + 337, + 333, + 335, + 0, + 337, + 338, + 334, + 333, + 0, + 338, + 340, + 336, + 334, + 0, + 336, + 335, + 331, + 332, + 0, + 335, + 333, + 329, + 331, + 0, + 333, + 334, + 330, + 329, + 0, + 334, + 336, + 332, + 330, + 0, + 332, + 331, + 327, + 328, + 0, + 331, + 329, + 325, + 327, + 0, + 329, + 330, + 326, + 325, + 0, + 330, + 332, + 328, + 326, + 0, + 328, + 327, + 323, + 324, + 0, + 327, + 325, + 321, + 323, + 0, + 325, + 326, + 322, + 321, + 0, + 326, + 328, + 324, + 322, + 0, + 324, + 323, + 319, + 320, + 0, + 323, + 321, + 317, + 319, + 0, + 321, + 322, + 318, + 317, + 0, + 322, + 324, + 320, + 318, + 0, + 320, + 319, + 315, + 316, + 0, + 319, + 317, + 313, + 315, + 0, + 317, + 318, + 314, + 313, + 0, + 318, + 320, + 316, + 314, + 0, + 316, + 315, + 311, + 312, + 0, + 315, + 313, + 309, + 311, + 0, + 313, + 314, + 310, + 309, + 0, + 314, + 316, + 312, + 310, + 0, + 312, + 311, + 307, + 308, + 0, + 311, + 309, + 305, + 307, + 0, + 309, + 310, + 306, + 305, + 0, + 310, + 312, + 308, + 306, + 0, + 308, + 307, + 303, + 304, + 0, + 307, + 305, + 300, + 303, + 0, + 305, + 306, + 302, + 300, + 0, + 306, + 308, + 304, + 302, + 0, + 304, + 303, + 299, + 301, + 0, + 303, + 300, + 297, + 299, + 0, + 300, + 302, + 298, + 297, + 0, + 302, + 304, + 301, + 298, + 0, + 301, + 299, + 295, + 296, + 0, + 299, + 297, + 293, + 295, + 0, + 297, + 298, + 294, + 293, + 0, + 298, + 301, + 296, + 294, + 0, + 296, + 295, + 291, + 292, + 0, + 295, + 293, + 289, + 291, + 0, + 293, + 294, + 290, + 289, + 0, + 294, + 296, + 292, + 290, + 0, + 292, + 291, + 287, + 288, + 0, + 291, + 289, + 285, + 287, + 0, + 289, + 290, + 286, + 285, + 0, + 290, + 292, + 288, + 286, + 0, + 288, + 287, + 283, + 284, + 0, + 287, + 285, + 281, + 283, + 0, + 285, + 286, + 282, + 281, + 0, + 286, + 288, + 284, + 282, + 0, + 284, + 283, + 279, + 280, + 0, + 283, + 281, + 277, + 279, + 0, + 281, + 282, + 278, + 277, + 0, + 282, + 284, + 280, + 278, + 0, + 280, + 279, + 275, + 276, + 0, + 279, + 277, + 273, + 275, + 0, + 277, + 278, + 274, + 273, + 0, + 278, + 280, + 276, + 274, + 0, + 276, + 275, + 271, + 272, + 0, + 275, + 273, + 269, + 271, + 0, + 273, + 274, + 270, + 269, + 0, + 274, + 276, + 272, + 270, + 0, + 272, + 271, + 267, + 268, + 0, + 271, + 269, + 265, + 267, + 0, + 269, + 270, + 266, + 265, + 0, + 270, + 272, + 268, + 266, + 0, + 268, + 267, + 263, + 264, + 0, + 267, + 265, + 261, + 263, + 0, + 265, + 266, + 262, + 261, + 0, + 266, + 268, + 264, + 262, + 0, + 264, + 263, + 259, + 260, + 0, + 263, + 261, + 257, + 259, + 0, + 261, + 262, + 258, + 257, + 0, + 262, + 264, + 260, + 258, + 0, + 260, + 259, + 255, + 256, + 0, + 259, + 257, + 253, + 255, + 0, + 257, + 258, + 254, + 253, + 0, + 258, + 260, + 256, + 254, + 0, + 256, + 255, + 251, + 252, + 0, + 255, + 253, + 249, + 251, + 0, + 253, + 254, + 250, + 249, + 0, + 254, + 256, + 252, + 250, + 0, + 252, + 251, + 247, + 248, + 0, + 251, + 249, + 245, + 247, + 0, + 249, + 250, + 246, + 245, + 0, + 250, + 252, + 248, + 246, + 0, + 248, + 247, + 243, + 244, + 0, + 247, + 245, + 241, + 243, + 0, + 245, + 246, + 242, + 241, + 0, + 246, + 248, + 244, + 242, + 0, + 244, + 243, + 239, + 240, + 0, + 243, + 241, + 237, + 239, + 0, + 241, + 242, + 238, + 237, + 0, + 242, + 244, + 240, + 238, + 0, + 240, + 239, + 235, + 236, + 0, + 239, + 237, + 233, + 235, + 0, + 237, + 238, + 234, + 233, + 0, + 238, + 240, + 236, + 234, + 0, + 236, + 235, + 231, + 232, + 0, + 235, + 233, + 229, + 231, + 0, + 233, + 234, + 230, + 229, + 0, + 234, + 236, + 232, + 230, + 0, + 232, + 231, + 227, + 228, + 0, + 231, + 229, + 225, + 227, + 0, + 229, + 230, + 226, + 225, + 0, + 230, + 232, + 228, + 226, + 0, + 228, + 227, + 223, + 224, + 0, + 227, + 225, + 221, + 223, + 0, + 225, + 226, + 222, + 221, + 0, + 226, + 228, + 224, + 222, + 0, + 224, + 223, + 219, + 220, + 0, + 223, + 221, + 217, + 219, + 0, + 221, + 222, + 218, + 217, + 0, + 222, + 224, + 220, + 218, + 0, + 220, + 219, + 215, + 216, + 0, + 219, + 217, + 213, + 215, + 0, + 217, + 218, + 214, + 213, + 0, + 218, + 220, + 216, + 214, + 0, + 216, + 215, + 211, + 212, + 0, + 215, + 213, + 209, + 211, + 0, + 213, + 214, + 210, + 209, + 0, + 214, + 216, + 212, + 210, + 0, + 212, + 211, + 207, + 208, + 0, + 211, + 209, + 205, + 207, + 0, + 209, + 210, + 206, + 205, + 0, + 210, + 212, + 208, + 206, + 0, + 208, + 207, + 203, + 204, + 0, + 207, + 205, + 201, + 203, + 0, + 205, + 206, + 202, + 201, + 0, + 206, + 208, + 204, + 202, + 0, + 204, + 203, + 199, + 200, + 0, + 203, + 201, + 197, + 199, + 0, + 201, + 202, + 198, + 197, + 0, + 202, + 204, + 200, + 198, + 0, + 200, + 199, + 195, + 196, + 0, + 199, + 197, + 193, + 195, + 0, + 197, + 198, + 194, + 193, + 0, + 198, + 200, + 196, + 194, + 0, + 196, + 195, + 191, + 192, + 0, + 195, + 193, + 189, + 191, + 0, + 193, + 194, + 190, + 189, + 0, + 194, + 196, + 192, + 190, + 0, + 192, + 191, + 187, + 188, + 0, + 191, + 189, + 185, + 187, + 0, + 189, + 190, + 186, + 185, + 0, + 190, + 192, + 188, + 186, + 0, + 188, + 187, + 183, + 184, + 0, + 187, + 185, + 181, + 183, + 0, + 185, + 186, + 182, + 181, + 0, + 186, + 188, + 184, + 182, + 0, + 184, + 183, + 179, + 180, + 0, + 183, + 181, + 177, + 179, + 0, + 181, + 182, + 178, + 177, + 0, + 182, + 184, + 180, + 178, + 0, + 180, + 179, + 175, + 176, + 0, + 179, + 177, + 173, + 175, + 0, + 177, + 178, + 174, + 173, + 0, + 178, + 180, + 176, + 174, + 0, + 176, + 175, + 171, + 172, + 0, + 175, + 173, + 169, + 171, + 0, + 173, + 174, + 170, + 169, + 0, + 174, + 176, + 172, + 170, + 0, + 172, + 171, + 167, + 168, + 0, + 171, + 169, + 165, + 167, + 0, + 169, + 170, + 166, + 165, + 0, + 170, + 172, + 168, + 166, + 0, + 168, + 167, + 163, + 164, + 0, + 167, + 165, + 161, + 163, + 0, + 165, + 166, + 162, + 161, + 0, + 166, + 168, + 164, + 162, + 0, + 164, + 163, + 159, + 160, + 0, + 163, + 161, + 157, + 159, + 0, + 161, + 162, + 158, + 157, + 0, + 162, + 164, + 160, + 158, + 0, + 160, + 159, + 155, + 156, + 0, + 159, + 157, + 153, + 155, + 0, + 157, + 158, + 154, + 153, + 0, + 158, + 160, + 156, + 154, + 0, + 156, + 155, + 151, + 152, + 0, + 155, + 153, + 149, + 151, + 0, + 153, + 154, + 150, + 149, + 0, + 154, + 156, + 152, + 150, + 0, + 152, + 151, + 147, + 148, + 0, + 151, + 149, + 145, + 147, + 0, + 149, + 150, + 146, + 145, + 0, + 150, + 152, + 148, + 146, + 0, + 148, + 147, + 143, + 144, + 0, + 147, + 145, + 141, + 143, + 0, + 145, + 146, + 142, + 141, + 0, + 146, + 148, + 144, + 142, + 0, + 144, + 143, + 139, + 140, + 0, + 143, + 141, + 137, + 139, + 0, + 141, + 142, + 138, + 137, + 0, + 142, + 144, + 140, + 138, + 0, + 140, + 139, + 135, + 136, + 0, + 139, + 137, + 133, + 135, + 0, + 137, + 138, + 134, + 133, + 0, + 138, + 140, + 136, + 134, + 0, + 136, + 135, + 131, + 132, + 0, + 135, + 133, + 129, + 131, + 0, + 133, + 134, + 130, + 129, + 0, + 134, + 136, + 132, + 130, + 0, + 132, + 131, + 127, + 128, + 0, + 131, + 129, + 125, + 127, + 0, + 129, + 130, + 126, + 125, + 0, + 130, + 132, + 128, + 126, + 0, + 128, + 127, + 123, + 124, + 0, + 127, + 125, + 121, + 123, + 0, + 125, + 126, + 122, + 121, + 0, + 126, + 128, + 124, + 122, + 0, + 124, + 123, + 119, + 120, + 0, + 123, + 121, + 117, + 119, + 0, + 121, + 122, + 118, + 117, + 0, + 122, + 124, + 120, + 118, + 0, + 120, + 119, + 115, + 116, + 0, + 119, + 117, + 113, + 115, + 0, + 117, + 118, + 114, + 113, + 0, + 118, + 120, + 116, + 114, + 0, + 116, + 115, + 111, + 112, + 0, + 115, + 113, + 109, + 111, + 0, + 113, + 114, + 110, + 109, + 0, + 114, + 116, + 112, + 110, + 0, + 112, + 111, + 107, + 108, + 0, + 111, + 109, + 105, + 107, + 0, + 109, + 110, + 106, + 105, + 0, + 110, + 112, + 108, + 106, + 0, + 108, + 107, + 103, + 104, + 0, + 107, + 105, + 101, + 103, + 0, + 105, + 106, + 102, + 101, + 0, + 106, + 108, + 104, + 102, + 0, + 104, + 103, + 99, + 100, + 0, + 103, + 101, + 97, + 99, + 0, + 101, + 102, + 98, + 97, + 0, + 102, + 104, + 100, + 98, + 0, + 100, + 99, + 95, + 96, + 0, + 99, + 97, + 93, + 95, + 0, + 97, + 98, + 94, + 93, + 0, + 98, + 100, + 96, + 94, + 0, + 96, + 95, + 91, + 92, + 0, + 95, + 93, + 89, + 91, + 0, + 93, + 94, + 90, + 89, + 0, + 94, + 96, + 92, + 90, + 0, + 92, + 91, + 87, + 88, + 0, + 91, + 89, + 85, + 87, + 0, + 89, + 90, + 86, + 85, + 0, + 90, + 92, + 88, + 86, + 0, + 88, + 87, + 83, + 84, + 0, + 87, + 85, + 81, + 83, + 0, + 85, + 86, + 82, + 81, + 0, + 86, + 88, + 84, + 82, + 0, + 84, + 83, + 79, + 80, + 0, + 83, + 81, + 77, + 79, + 0, + 81, + 82, + 78, + 77, + 0, + 82, + 84, + 80, + 78, + 0, + 80, + 79, + 75, + 76, + 0, + 79, + 77, + 73, + 75, + 0, + 77, + 78, + 74, + 73, + 0, + 78, + 80, + 76, + 74, + 0, + 76, + 75, + 71, + 72, + 0, + 75, + 73, + 69, + 71, + 0, + 73, + 74, + 70, + 69, + 0, + 74, + 76, + 72, + 70, + 0, + 72, + 71, + 67, + 68, + 0, + 71, + 69, + 65, + 67, + 0, + 69, + 70, + 66, + 65, + 0, + 70, + 72, + 68, + 66, + 0, + 68, + 67, + 63, + 64, + 0, + 67, + 65, + 61, + 63, + 0, + 65, + 66, + 62, + 61, + 0, + 66, + 68, + 64, + 62, + 0, + 64, + 63, + 59, + 60, + 0, + 63, + 61, + 57, + 59, + 0, + 61, + 62, + 58, + 57, + 0, + 62, + 64, + 60, + 58, + 0, + 60, + 59, + 55, + 56, + 0, + 59, + 57, + 53, + 55, + 0, + 57, + 58, + 54, + 53, + 0, + 58, + 60, + 56, + 54, + 0, + 56, + 55, + 51, + 52, + 0, + 55, + 53, + 49, + 51, + 0, + 53, + 54, + 50, + 49, + 0, + 54, + 56, + 52, + 50, + 0, + 52, + 51, + 47, + 48, + 0, + 51, + 49, + 45, + 47, + 0, + 49, + 50, + 46, + 45, + 0, + 50, + 52, + 48, + 46, + 0, + 48, + 47, + 43, + 44, + 0, + 47, + 45, + 41, + 43, + 0, + 45, + 46, + 42, + 41, + 0, + 46, + 48, + 44, + 42, + 0, + 44, + 43, + 39, + 40, + 0, + 43, + 41, + 37, + 39, + 0, + 41, + 42, + 38, + 37, + 0, + 42, + 44, + 40, + 38, + 0, + 40, + 39, + 35, + 36, + 0, + 39, + 37, + 33, + 35, + 0, + 37, + 38, + 34, + 33, + 0, + 38, + 40, + 36, + 34, + 0, + 36, + 35, + 31, + 32, + 0, + 35, + 33, + 29, + 31, + 0, + 33, + 34, + 30, + 29, + 0, + 34, + 36, + 32, + 30, + 0, + 32, + 31, + 27, + 28, + 0, + 31, + 29, + 25, + 27, + 0, + 29, + 30, + 26, + 25, + 0, + 30, + 32, + 28, + 26, + 0, + 28, + 27, + 23, + 24, + 0, + 27, + 25, + 21, + 23, + 0, + 25, + 26, + 22, + 21, + 0, + 26, + 28, + 24, + 22, + 0, + 24, + 23, + 19, + 20, + 0, + 23, + 21, + 17, + 19, + 0, + 21, + 22, + 18, + 17, + 0, + 22, + 24, + 20, + 18, + 0, + 20, + 19, + 15, + 16, + 0, + 19, + 17, + 13, + 15, + 0, + 17, + 18, + 14, + 13, + 0, + 18, + 20, + 16, + 14, + 0, + 16, + 15, + 11, + 12, + 0, + 15, + 13, + 9, + 11, + 0, + 13, + 14, + 10, + 9, + 0, + 14, + 16, + 12, + 10, + 0, + 12, + 11, + 7, + 8, + 0, + 11, + 9, + 5, + 7, + 0, + 9, + 10, + 6, + 5, + 0, + 10, + 12, + 8, + 6, + 0, + 8, + 7, + 3, + 4, + 0, + 7, + 5, + 1, + 3, + 0, + 5, + 6, + 2, + 1, + 0, + 6, + 8, + 4, + 2, + 0, + 960, + 964, + 963, + 959, + 0, + 4, + 3, + 1, + 2, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/clipper.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/clipper.json index 42618e2646d5..b489fad2023b 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/clipper.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/clipper.json @@ -1 +1,42 @@ -[[{"normal":[-0.3083386359491782,0.951276660904177,0],"dist":6170181.464168096},{"normal":[-0.6966989213774921,-0.7173636546072286,0],"dist":-5125771.987808087,"interior":true,"invisible":true},{"normal":[0.9470427902682248,0.3211073860891014,0],"dist":2617545.405920379}],[{"normal":[-0.9553383821970284,-0.2955140868066438,0],"dist":-2451593.4016264486},{"normal":[0.3083386359685791,-0.9512766608978883,0],"dist":-6170281.455068067},{"normal":[0.6966989213774921,0.7173636546072286,0],"dist":5125771.987808087,"interior":true,"invisible":true}],[{"normal":[-0.2808949109572395,0.9597385315794739,0],"dist":6240426.253356652},{"normal":[-0.9639149835530603,-0.26621026366746936,0],"dist":-2261112.138611255},{"normal":[0.9674228811456469,-0.25316589232330605,0],"dist":-1191601.8774178803,"interior":true,"invisible":true}],[{"normal":[0.28089491095155456,-0.9597385315811378,0],"dist":-6240526.241716532},{"normal":[0.9553383821970284,0.2955140868066438,0],"dist":2451593.4016264486},{"normal":[-0.9674228811456469,0.25316589232330605,0],"dist":1191601.8774178806,"interior":true,"invisible":true}]] \ No newline at end of file +[ + [ + { "normal": [-0.3083386359491782, 0.951276660904177, 0], "dist": 6170181.464168096 }, + { + "normal": [-0.6966989213774921, -0.7173636546072286, 0], + "dist": -5125771.987808087, + "interior": true, + "invisible": true + }, + { "normal": [0.9470427902682248, 0.3211073860891014, 0], "dist": 2617545.405920379 } + ], + [ + { "normal": [-0.9553383821970284, -0.2955140868066438, 0], "dist": -2451593.4016264486 }, + { "normal": [0.3083386359685791, -0.9512766608978883, 0], "dist": -6170281.455068067 }, + { + "normal": [0.6966989213774921, 0.7173636546072286, 0], + "dist": 5125771.987808087, + "interior": true, + "invisible": true + } + ], + [ + { "normal": [-0.2808949109572395, 0.9597385315794739, 0], "dist": 6240426.253356652 }, + { "normal": [-0.9639149835530603, -0.26621026366746936, 0], "dist": -2261112.138611255 }, + { + "normal": [0.9674228811456469, -0.25316589232330605, 0], + "dist": -1191601.8774178803, + "interior": true, + "invisible": true + } + ], + [ + { "normal": [0.28089491095155456, -0.9597385315811378, 0], "dist": -6240526.241716532 }, + { "normal": [0.9553383821970284, 0.2955140868066438, 0], "dist": 2451593.4016264486 }, + { + "normal": [-0.9674228811456469, 0.25316589232330605, 0], + "dist": 1191601.8774178806, + "interior": true, + "invisible": true + } + ] +] diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/inside.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/inside.json index 87300b700215..05af55c79b6f 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/inside.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/inside.json @@ -1 +1,9262 @@ -{"indexedMesh":{"point":[[508756.28394181497,6651143.909274647,91.3199669126467],[508756.088194514,6651144.4865926355,91.31996691264918],[508756.088194514,6651144.4865926355,91.44996691264919],[508756.28394181497,6651143.909274647,93.14877057164671],[508757.5568140733,6651144.341973173,91.33631063381246],[508756.088194514,6651144.4865926355,93.14877057164918],[508756.2772113811,6651143.929124732,93.61436125864583],[508757.3614660662,6651144.919426898,91.33631063381246],[508756.0822558954,6651144.504107417,93.55958588364068],[508757.3614660662,6651144.919426898,91.46631063381247],[508756.25616441696,6651143.991198594,94.09163221063858],[508756.06368504517,6651144.55887847,93.98070731164123],[508756.21971539175,6651144.098697793,94.5745332306442],[508756.0315241402,6651144.653730705,94.40679644664426],[508756.1818078276,6651144.210498664,94.93623921564632],[508757.5568140733,6651144.341973173,93.16511429281246],[508755.9851163838,6651144.790601213,94.83170295064227],[508756.13465000596,6651144.34958134,95.29399706164321],[508757.3614660662,6651144.919426898,93.16511429281246],[508757.55009736854,6651144.361827926,93.63070497981245],[508755.92418373236,6651144.9703100305,95.24866965264734],[508756.0782362944,6651144.515962435,95.64445327664261],[508757.3555395622,6651144.936945797,93.57592960481244],[508757.5290933375,6651144.423916382,94.10797593181246],[508756.0127264599,6651144.709170749,95.98419830364112],[508755.8488868478,6651145.192383314,95.65061856964533],[508757.33700659353,6651144.991729728,93.99705103281245],[508757.4927186622,6651144.531440855,94.59087695181246],[508755.9384512209,6651144.928230892,96.30986541364487],[508757.30491129163,6651145.086604264,94.42314016781245],[508755.7598575632,6651145.454957597,96.03049937163823],[508757.45488842344,6651144.6432680115,94.95258293681245],[508755.85591043497,6651145.171668631,96.61823422164382],[508755.6847191385,6651145.676563536,96.29690568664412],[508757.2585982,6651145.223506953,94.84804667181247],[508757.40782679664,6651144.782383389,95.31034078281245],[508755.6030922834,6651145.917305817,96.54461542664565],[508755.7657635549,6651145.437539043,96.90633257264452],[508757.1977898413,6651145.403258021,95.26501337381245],[508757.35152816033,6651144.948803603,95.66079699781247],[508755.6688125905,6651145.723476756,97.17153029764322],[508755.4854658217,6651146.264221824,96.84205789664404],[508757.2861519559,6651145.142057342,96.00054202481246],[508757.1226465509,6651145.625383517,95.66696229081245],[508755.56597847457,6651146.026765663,97.41161874464638],[508755.3596625666,6651146.635253669,97.09827101964285],[508757.2120282266,6651145.361168989,96.32620913481244],[508757.0337988728,6651145.888019536,96.04684309281245],[508755.45827227476,6651146.344423818,97.62487107964382],[508755.22789640026,6651147.023871941,97.31054882863958],[508757.1296558111,6651145.604663963,96.63457794281246],[508756.95881371835,6651146.109677576,96.31324940781246],[508755.34676311864,6651146.673298042,97.81007998164468],[508752.170689591,6651156.040499378,91.3199669126459],[508755.0924505664,6651147.4233426675,97.4776635856434],[508752.170689591,6651156.040499378,91.4499669126459],[508756.87735336926,6651146.35047646,96.56095914781245],[508755.2325448955,6651147.0101621235,97.96657127364296],[508757.0396928167,6651145.870596886,96.92267629381246],[508751.97494228964,6651156.6178173665,91.31996691264403],[508754.9555592707,6651147.827076497,97.59981670763861],[508755.11670379795,6651147.351812553,98.09419403264249],[508756.94293961726,6651146.156601827,97.18787401881245],[508756.7599668474,6651146.697474032,96.85840161781245],[508754.81930480513,6651148.228932121,97.67849140064006],[508755.00028854015,6651147.695156354,98.19328952664557],[508754.6855382233,6651148.623450224,97.71623425963736],[508756.84031526675,6651146.459962042,97.42796246581246],[508756.63442021154,6651147.068593111,97.11461474081246],[508754.845866812,6651148.15059273,98.28245417864466],[508756.7328287711,6651146.777694883,97.64121480081245],[508754.69426468585,6651148.597713247,98.32522941964449],[508752.17068883986,6651156.040501593,93.14877057264447],[508756.502922828,6651147.457302753,97.32689254981246],[508752.1721484198,6651156.03619685,93.3525918566441],[508756.6215470763,6651147.106646429,97.82642370281246],[508753.45195224613,6651156.4760501245,91.33631063381246],[508751.97494228964,6651156.6178173665,93.14877057164405],[508756.36775328236,6651147.856867401,97.49400730681245],[508753.45195224613,6651156.4760501245,91.46631063381247],[508754.12360073806,6651150.28077381,97.71623425964779],[508752.18426792085,6651156.000452776,93.76917114464099],[508756.50756184076,6651147.4435897125,97.98291499481245],[508753.2566042391,6651157.053503849,91.33631063381246],[508751.98167272296,6651156.597967282,93.6143612586376],[508756.23114122404,6651148.260696153,97.61616042881245],[508752.20953092584,6651155.925944533,94.19349826463878],[508756.3919570411,6651147.785320468,98.11053775381247],[508756.09516469634,6651148.662646259,97.69483512181246],[508752.002719687,6651156.535893422,94.09163221064352],[508752.24875516497,6651155.810260391,94.61980861563926],[508756.2757792522,6651148.128744994,98.20963324781246],[508755.9616709778,6651149.05725712,97.73257798081245],[508752.30241690605,6651155.651995689,95.04161747464255],[508753.57334512926,6651151.903644007,97.7162342596433],[508752.0391687129,6651156.428394222,94.57453323064652],[508756.1216725205,6651148.58428845,98.29879789981247],[508752.3705808253,6651155.450959677,95.45196701764566],[508753.4395785479,6651152.298162109,97.67849140064625],[508752.0770762764,6651156.316593351,94.93623921563581],[508753.303324082,6651152.700017734,97.59981670764505],[508752.4528526866,6651155.208315077,95.84374671163808],[508755.9703796392,6651149.031514091,98.34157314081246],[508753.45195149665,6651156.47605234,93.16511429381245],[508752.1242340985,6651156.177510674,95.2939970616445],[508752.5233096953,6651155.000516051,96.12122857164316],[508753.1664327865,6651153.1037515635,97.47766358564292],[508753.5646194184,6651151.929378766,98.32522941964064],[508752.60068676784,6651154.772307663,96.38166924464245],[508753.0309869522,6651153.5032222895,97.3105488286411],[508753.4534080993,6651156.471746585,93.36893557781245],[508752.68431612616,6651154.525659394,96.62263889064258],[508752.8992207858,6651153.891840562,97.09827101963653],[508752.77341753116,6651154.262872405,96.84205789664227],[508752.1806478098,6651156.011129578,95.64445327664251],[508753.41301729245,6651152.376499283,98.2824541786431],[508753.2566042391,6651157.053503849,93.16511429281246],[508752.2461576441,6651155.817921266,95.98419830364098],[508755.40087975713,6651150.714970364,97.73257798081245],[508753.4655028787,6651156.435994107,93.78551486581246],[508753.2585955643,6651152.831935659,98.19328952664218],[508752.32043288345,6651155.5988611225,96.30986541364155],[508753.14218030643,6651153.175279461,98.09419403264394],[508752.4029736697,6651155.355423383,96.61823422164692],[508753.02633920853,6651153.516929891,97.96657127363913],[508753.26332094386,6651157.033649098,93.63070497981245],[508752.4931205494,6651155.0895529725,96.90633257264192],[508752.9121209858,6651153.853793971,97.81007998164307],[508752.59007151355,6651154.803615258,97.17153029763888],[508753.4907143513,6651156.361468348,94.20984198581245],[508752.8006118293,6651154.182668196,97.6248710796396],[508752.6929056298,6651154.500326351,97.41161874464137],[508753.2843249749,6651156.971560642,94.10797593181246],[508753.529858579,6651156.245757005,94.63615233681244],[508753.5834108582,6651156.087455093,95.05796119581247],[508754.8517465848,6651152.338222121,97.73257798081245],[508753.3206996502,6651156.864036168,94.59087695181246],[508753.65143573337,6651155.886371815,95.46831073881245],[508754.7182528663,6651152.73283298,97.69483512181246],[508753.358529889,6651156.752209012,94.95258293681245],[508754.5822763385,6651153.134783087,97.61616042881245],[508753.7335397734,6651155.643670166,95.86009043281247],[508753.40559151577,6651156.613093634,95.31034078281245],[508753.80385306035,6651155.435822284,96.13757229281245],[508754.44566428015,6651153.5386118395,97.49400730681245],[508754.8430386732,6651152.363962931,98.34157314081246],[508753.8810722957,6651155.20756024,96.39801296581246],[508754.3104947345,6651153.938176488,97.32689254981246],[508753.9645310631,6651154.960853982,96.63898261181245],[508754.17899735103,6651154.32688613,97.11461474081246],[508754.0534507151,6651154.698005208,96.85840161781245],[508753.461890152,6651156.446673419,95.66079699781247],[508754.69174579193,6651152.811188572,98.29879789981247],[508753.5272663565,6651156.253419681,96.00054202481246],[508754.53763906023,6651153.266732028,98.20963324781246],[508753.6013900858,6651156.034308034,96.32620913481244],[508754.4214612713,6651153.610156555,98.11053775381247],[508753.6837625013,6651155.790813059,96.63457794281246],[508754.30585647165,6651153.951887311,97.98291499481245],[508753.77372549573,6651155.524880138,96.92267629381246],[508754.1918712361,6651154.288830593,97.82642370281246],[508753.87047869514,6651155.238875196,97.18787401881245],[508754.0805895413,6651154.617782141,97.64121480081245],[508753.9731030456,6651154.935514982,97.42796246581246],[508768.5865013963,6651148.036477735,91.46976384454798],[508768.39461335127,6651148.615090409,91.46976384454798],[508768.39461335127,6651148.615090409,91.599763844548],[508768.5865013963,6651148.036477735,93.29856750354799],[508768.39461335127,6651148.615090409,93.29856750354799],[508768.5799036564,6651148.056372336,93.76415819054799],[508768.3887918162,6651148.632644468,93.709382815548],[508768.5592716442,6651148.118585402,94.24142914254799],[508768.3705870994,6651148.68753835,94.130504243548],[508768.52354122937,6651148.226325678,94.72433016254799],[508768.3390602627,6651148.782603299,94.55659337854799],[508768.48638103175,6651148.338377273,95.086036147548],[508768.2935674586,6651148.919780752,94.981499882548],[508768.4401529504,6651148.477771853,95.443793993548],[508768.2338361244,6651149.099892582,95.398466584548],[508768.38485146343,6651148.644526073,95.794250208548],[508768.32063318836,6651148.838167672,96.13399523554799],[508768.16002375586,6651149.322463883,95.80041550154799],[508768.2478223225,6651149.057719076,96.459662345548],[508768.0727497287,6651149.585627011,96.18029630354799],[508768.1669088696,6651149.301702744,96.768031153548],[508767.99909269536,6651149.807729919,96.44670261854799],[508767.9190751544,6651150.049012086,96.69441235854799],[508768.07853928034,6651149.5681693945,97.05612950454798],[508767.9834997528,6651149.854748346,97.32132722954799],[508767.80376775743,6651150.396706083,96.991854828548],[508767.8826930628,6651150.158717405,97.561415676548],[508767.68044477655,6651150.768569997,97.248067951548],[508767.7771103449,6651150.477087936,97.77466801154799],[508767.55127644655,6651151.158059778,97.46034576054801],[508767.66779964755,6651150.806699689,97.95987691354799],[508764.5543440002,6651160.194907766,91.46976384454798],[508767.4185009948,6651151.558426351,97.62746051754799],[508764.5543440002,6651160.194907766,91.599763844548],[508767.55583329406,6651151.144319215,98.11636820554799],[508764.36245595507,6651160.77352044,91.46976384454798],[508767.28430857987,6651151.963065587,97.74961363954799],[508767.44227606175,6651151.4867358245,98.24399096454799],[508767.15074043913,6651152.365822407,97.82828833254798],[508767.3281559888,6651151.830849605,98.34308645854799],[508767.01961113274,6651152.761225251,97.866031191548],[508767.17677876254,6651152.287307334,98.432251110548],[508767.02816554817,6651152.735430557,98.475026351548],[508764.5543432639,6651160.194909986,93.29856750454799],[508764.5557740675,6651160.19059559,93.50238878854799],[508764.36245595507,6651160.77352044,93.29856750354799],[508766.46875252575,6651154.422265525,97.866031191548],[508764.5676546268,6651160.154771357,93.91896807654798],[508764.36905369506,6651160.75362584,93.76415819054799],[508764.5924195593,6651160.080096022,94.343295196548],[508764.3896857072,6651160.691412774,94.24142914254799],[508764.63087047276,6651159.964152448,94.76960554754798],[508764.6834742455,6651159.805532824,95.19141440654799],[508765.9293454822,6651156.048775146,97.866031191548],[508764.4254161221,6651160.583672497,94.72433016254799],[508765.7982161757,6651156.44417799,97.82828833254798],[508764.75029427867,6651159.604045973,95.60176394954799],[508764.4625763197,6651160.471620903,95.086036147548],[508765.66464803496,6651156.846934809,97.74961363954799],[508764.83094410953,6651159.36085722,95.993543643548],[508764.9000120227,6651159.15259219,96.27102550354799],[508765.53045562014,6651157.251574045,97.62746051754799],[508764.50880440115,6651160.332226322,95.443793993548],[508765.9207918033,6651156.074567618,98.475026351548],[508764.97586356755,6651158.923872025,96.531466176548],[508765.3976801684,6651157.65194062,97.46034576054801],[508765.0578441312,6651158.676670627,96.772435822548],[508765.2685118383,6651158.041430401,97.248067951548],[508765.1451888574,6651158.413294315,96.991854828548],[508764.564105888,6651160.165472102,95.794250208548],[508765.7721785889,6651156.522690841,98.432251110548],[508776.31516765006,6651150.581623798,91.55678584387401],[508764.62832416315,6651159.971830503,96.13399523554799],[508765.62080136256,6651156.979148571,98.34308645854799],[508764.70113502897,6651159.7522791,96.459662345548],[508765.5066812897,6651157.323262351,98.24399096454799],[508764.78204848187,6651159.50829543,96.768031153548],[508765.3931240574,6651157.665678961,98.11636820554799],[508764.8704180711,6651159.2418287825,97.05612950454798],[508776.1257040518,6651151.161034873,91.55678584387401],[508765.2811577039,6651158.003298488,97.95987691354799],[508764.9654575986,6651158.955249829,97.32132722954799],[508765.17184700654,6651158.33291024,97.77466801154799],[508765.0662642886,6651158.65128077,97.561415676548],[508776.1257040518,6651151.161034873,91.686785843874],[508776.31516765006,6651150.581623798,93.385589502874],[508776.1257040518,6651151.161034873,93.385589502874],[508776.3086532705,6651150.601545851,93.851180189874],[508776.11995607,6651151.178613153,93.796404814874],[508776.28828193754,6651150.663844762,94.32845114187401],[508776.10198136437,6651151.233582781,94.21752624287402],[508776.2530029656,6651150.771733703,94.811352161874],[508776.0708528595,6651151.328778906,94.643615377874],[508776.2163122756,6651150.883939912,95.17305814687401],[508776.0259348432,6651151.466145642,95.06852188187402],[508776.17066827195,6651151.023526837,95.53081599287401],[508775.9669581962,6651151.646506001,95.485488583874],[508776.11606550246,6651151.190511154,95.881272207874],[508776.0526586056,6651151.384419949,96.221017234874],[508775.8940784244,6651151.869384417,95.887437500874],[508775.98076768295,6651151.604274302,96.546684344874],[508775.8079070779,6651152.132910673,96.267318302874],[508775.9008765468,6651151.848594632,96.855053152874],[508775.7351806786,6651152.355320049,96.53372461787401],[508775.6561741349,6651152.59693515,96.781434357874],[508775.8136234803,6651152.1154289665,97.143151503874],[508775.7197847482,6651152.402403356,97.408349228874],[508775.54232361173,6651152.945108913,97.078876827874],[508775.62025171996,6651152.706791848,97.648437675874],[508775.4205587791,6651153.317485945,97.335089950874],[508775.5160030074,6651153.025601682,97.861690010874],[508775.2930224514,6651153.707513166,97.547367759874],[508775.4080734175,6651153.35566825,98.04689891287401],[508775.1619245771,6651154.108432187,97.714482516874],[508772.33395533194,6651162.756830677,91.55678584387401],[508772.33395533194,6651162.756830677,91.686785843874],[508775.29752172454,6651153.693753643,98.203390204874],[508775.0294276423,6651154.513629765,97.836635638874],[508772.1444917337,6651163.336241752,91.55678584387401],[508775.1853992532,6651154.036642737,98.331012963874],[508774.89754709427,6651154.91694233,97.915310331874],[508775.0727210527,6651154.381231342,98.430108457874],[508774.7680745667,6651155.312890771,97.95305319087402],[508774.9232564314,6651154.838318918,98.519273109874],[508774.77652089973,6651155.287060485,98.56204835087401],[508772.3339546049,6651162.7568329,93.385589503874],[508772.33536733076,6651162.752512552,93.58941078787402],[508772.1444917337,6651163.336241752,93.385589502874],[508774.22417589,6651156.976223038,97.95305319087402],[508772.3470977828,6651162.716638885,94.005990075874],[508772.1510061133,6651163.316319699,93.851180189874],[508772.37154981797,6651162.641860511,94.430317195874],[508772.1713774462,6651163.254020788,94.32845114187401],[508772.4095149159,6651162.525756951,94.856627546874],[508773.6915840899,6651158.604977004,97.95305319087402],[508772.461454056,6651162.366918456,95.27843640587402],[508772.20665641816,6651163.146131848,94.811352161874],[508773.5621115622,6651159.000925444,97.915310331874],[508772.5274298385,6651162.165153583,95.688785948874],[508772.24334710813,6651163.0339256385,95.17305814687401],[508773.4302310141,6651159.40423801,97.836635638874],[508772.60706068337,6651161.921629265,96.080565642874],[508773.2977340795,6651159.809435588,97.714482516874],[508773.683138484,6651158.630805066,98.56204835087401],[508772.6752559445,6651161.713076858,96.358047502874],[508772.2889911118,6651162.894338713,95.53081599287401],[508772.75014912826,6651161.484041093,96.618488175874],[508773.16663620505,6651160.2103546085,97.547367759874],[508772.8310938925,6651161.236498593,96.85945782187402],[508773.0390998774,6651160.60038183,97.335089950874],[508772.9173350447,6651160.972758862,97.078876827874],[508772.34359388123,6651162.727354397,95.881272207874],[508773.53640295233,6651159.079546632,98.519273109874],[508772.4070007781,6651162.533445602,96.221017234874],[508773.38693833107,6651159.536634209,98.430108457874],[508772.47889170086,6651162.313591248,96.546684344874],[508773.27426013054,6651159.881222813,98.331012963874],[508772.55878283695,6651162.069270918,96.855053152874],[508773.1621376592,6651160.224111907,98.203390204874],[508772.64603590337,6651161.802436585,97.143151503874],[508773.0515859663,6651160.562197301,98.04689891287401],[508772.73987463553,6651161.5154621955,97.408349228874],[508772.9436563763,6651160.892263868,97.861690010874],[508772.83940766373,6651161.211073703,97.648437675874],[508785.09937079577,6651153.430914629,91.64923286031915],[508784.9126627614,6651154.011219511,91.64923286031915],[508784.9126627614,6651154.011219511,91.77923286031915],[508785.09937079577,6651153.430914629,93.47803651931915],[508784.9126627614,6651154.011219511,93.47803651931915],[508785.0929511615,6651153.450867412,93.94362720631915],[508784.9069983784,6651154.028824909,93.88885183131916],[508785.07287610974,6651153.513262427,94.42089815831915],[508784.8892850974,6651154.083879335,94.30997325931916],[508785.0381102361,6651153.6213178,94.90379917831915],[508784.8586093265,6651154.17922231,94.73606239431915],[508785.0019531767,6651153.7336971,95.26550516331916],[508784.8143445989,6651154.31680095,95.16096889831915],[508784.9569730207,6651153.873499355,95.62326300931916],[508784.75622571004,6651154.497439536,95.57793560031917],[508784.9031643955,6651154.040741263,95.97371922431915],[508784.8406796903,6651154.2349491855,96.31346425131915],[508784.6844059036,6651154.720661768,95.97988451731915],[508784.7698343512,6651154.455142689,96.63913136131916],[508784.5994878357,6651154.984594543,96.35976531931915],[508784.691105154,6651154.699839912,96.94750016931917],[508784.52781917126,6651155.207347013,96.62617163431915],[508784.44996170094,6651155.449334833,96.87388137431915],[508784.60512109863,6651154.967085869,97.23559852031914],[508784.5126471597,6651155.25450295,97.50079624531915],[508784.337767023,6651155.798045695,97.17132384431916],[508784.4145617426,6651155.559360998,97.74088469231916],[508784.2177731415,6651156.170997163,97.42753696731916],[508784.3118292263,6651155.878662633,97.95413702731915],[508784.0920917058,6651156.561626046,97.63981477631917],[508784.2054693673,6651156.209238368,98.13934592931915],[508783.96290052263,6651156.9631635295,97.80692953331916],[508781.1760613422,6651165.624903189,91.64923286031915],[508784.09652554145,6651156.547845297,98.29583722131915],[508781.1760613422,6651165.624903189,91.77923286031915],[508780.9085904975,6651166.179011417,91.64838872264654],[508783.8323306271,6651157.3689861735,97.92908265531916],[508781.03831829067,6651166.053020627,91.64923286031915],[508781.4042431351,6651165.697636796,91.65142950527056],[508780.98935330793,6651166.2052080715,91.64923286031915],[508783.9860337824,6651156.891263337,98.42345998031915],[508781.4042431351,6651165.697636796,91.78142950527057],[508783.7023681535,6651157.772920896,98.00775734831915],[508783.8749943768,6651157.236383512,98.52255547431915],[508783.5747786779,6651158.169480134,98.04550020731915],[508783.72770357324,6651157.694176198,98.61172012631916],[508783.58310216723,6651158.143610002,98.65449536731917],[508781.17606062576,6651165.624905415,93.47803652031915],[508781.17745280487,6651165.620578401,93.68185780431915],[508780.9085904975,6651166.179011417,93.47719238164655],[508783.038790479,6651159.835378285,98.04550020731915],[508781.40424123115,6651165.697638644,93.48023315383543],[508780.98935330793,6651166.2052080715,93.47803651931915],[508781.40793966077,6651165.694046753,93.6840766446469],[508781.1890126489,6651165.584649395,94.09843709231914],[508791.3308076835,6651156.057021789,91.7114063908341],[508791.8268117102,6651155.5753059,91.71442303084955],[508791.3308076835,6651156.057021789,91.84140639083411],[508780.92559867207,6651166.162493188,93.9428937328404],[508780.9957729421,6651166.185255287,93.94362720631915],[508781.21310905286,6651165.509755666,94.52276421231916],[508781.438649262,6651165.664221789,94.10084032902482],[508780.9787855011,6651166.110838485,94.42051076182501],[508781.0158479939,6651166.122860272,94.42089815831915],[508781.25052198535,6651165.393473004,94.94907456331914],[508781.5026631831,6651165.602051884,94.52555184468987],[508782.51394470903,6651161.466644794,98.04550020731915],[508781.03831829043,6651166.053020627,94.73301253991784],[508781.3017057211,6651165.234389482,95.37088342231915],[508781.0506138674,6651166.0148049,94.90379917831915],[508781.0709824218,6651166.021297435,94.90399521988304],[508782.3863552335,6651161.863204031,98.00775734831915],[508781.36672195,6651165.032313361,95.78123296531915],[508781.60205347085,6651165.505524683,94.95245908333906],[508781.0867709269,6651165.902425601,95.26550516331916],[508782.2563927599,6651162.267138755,97.92908265531916],[508781.4451946417,6651164.78841338,96.17301265931916],[508781.1670363865,6651165.928010449,95.26627774223853],[508782.50562193635,6651161.492512698,98.65449536731917],[508782.12582286436,6651162.672961397,97.80692953331916],[508781.512398069,6651164.579539256,96.45049451931915],[508781.1317510829,6651165.7626233455,95.62326300931916],[508781.58620200417,6651164.350150177,96.71093519231916],[508781.9966316811,6651163.074498882,97.63981477631917],[508781.73802693875,6651165.373468134,95.37508465078702],[508781.66596950544,6651164.102225814,96.95190483831915],[508781.8709502454,6651163.465127764,97.42753696731916],[508781.750956364,6651163.838079233,97.17132384431916],[508791.3308076835,6651156.057021789,93.5402100498341],[508782.36102053046,6651161.941946502,98.61172012631916],[508781.18555970816,6651165.595381437,95.97371922431915],[508781.2865295777,6651165.811959439,95.62475291020371],[508791.8268117102,6651155.5753059,93.54322668984955],[508781.2480444133,6651165.401173515,96.31346425131915],[508782.21372972673,6651162.399739189,98.52255547431915],[508781.9107474735,6651165.2057230715,95.786471820401],[508791.3157598206,6651156.071636176,93.95093387201312],[508781.3188897525,6651165.180980011,96.63913136131916],[508782.1026903211,6651162.744859362,98.42345998031915],[508781.429476264,6651165.673130546,95.97606738084248],[508781.39761894965,6651164.936282787,96.94750016931917],[508781.9921985622,6651163.088277403,98.29583722131915],[508791.8097574663,6651155.591868871,94.00871362346382],[508781.48360300495,6651164.669036831,97.23559852031914],[508781.88325473625,6651163.426884332,98.13934592931915],[508781.5760769439,6651164.381619749,97.50079624531915],[508781.77689487726,6651163.757460066,97.95413702731915],[508781.6741623611,6651164.076761703,97.74088469231916],[508782.1192161192,6651165.003259677,96.17950419952633],[508791.26870314847,6651156.117337311,94.37176921039583],[508781.59547161206,6651165.511916941,96.31680924172528],[508791.75642657146,6651155.643663489,94.48566013922657],[508782.2977471118,6651164.829871537,96.45805911072323],[508781.7836776189,6651165.329132489,96.64360681646063],[508791.18721064064,6651156.196482304,94.79736293709999],[508782.4938128534,6651164.639453763,96.71967850416095],[508791.6640683957,6651155.733361149,94.9679993539432],[508781.9928276921,6651165.126007297,96.95323220408682],[508791.06961804087,6651156.310687473,95.22155466351614],[508782.7057212588,6651164.433649696,96.96192244134859],[508782.8186082703,6651164.324014563,97.0723109665908],[508791.5680144301,6651155.826648137,95.32912112216707],[508782.22125084494,6651164.904164216,97.2427033054233],[508782.9314952818,6651164.214379431,97.18269949183302],[508790.915220813,6651156.460637058,95.6375830351749],[508791.44852124096,6651155.942699146,95.68615228904439],[508782.4669148643,6651164.665576915,97.50937783292844],[508783.2502681133,6651163.904789329,97.44083070961177],[508790.7244260601,6651156.645935682,96.03837267327464],[508791.3055745548,6651156.08152804,96.03573934039045],[508782.7274861998,6651164.412511727,97.75103319599748],[508783.5841503607,6651163.580525057,97.6551183535247],[508790.4988347842,6651156.865028464,96.41688313154079],[508783.00040290714,6651164.147456793,97.96592723521465],[508791.1395792051,6651156.242741645,96.37447525727447],[508783.9273565201,6651163.247205466,97.82429995188103],[508790.30844155047,6651157.049937135,96.6821332156547],[508784.2742253312,6651162.91032873,97.9485428796279],[508783.28295592504,6651163.8730431385,98.15283640162367],[508790.95137319824,6651156.425526096,96.6989984914695],[508790.1016072871,6651157.250813229,96.92858719596532],[508784.61948048195,6651162.5750191705,98.02929856282987],[508783.57237344515,6651163.591962722,98.31106989193187],[508784.95843158313,6651162.245832063,98.06908529524047],[508790.74222312565,6651156.628651287,97.00609644935226],[508789.8035536311,6651157.540281003,97.22422066004887],[508783.86590316804,6651163.306888563,98.44046025153582],[508786.3527241049,6651160.891704223,98.07750205646393],[508789.48478080117,6651157.8498711055,97.47849977789618],[508784.1608877546,6651163.020401448,98.54133276512589],[508790.51379997365,6651156.85049437,97.29280722579055],[508789.15089855244,6651158.174135376,97.68875274712765],[508784.55217692594,6651162.640383948,98.63285560452938],[508790.2681359536,6651157.089081669,97.55651309220755],[508788.80769239395,6651158.507454967,97.8537870088007],[508787.77661733126,6651159.508828371,98.08611278570439],[508795.13602509245,6651156.630127247,91.7464899322843],[508788.46082358254,6651158.844331705,97.97383834843298],[508784.9363215073,6651162.267305225,98.67794710499602],[508788.11556843144,6651159.179641264,98.05042195029993],[508790.0075646181,6651157.342146859,97.79501965812733],[508789.73464791116,6651157.607201791,98.00661572382455],[508789.45209489367,6651157.881615446,98.19011047744299],[508794.9524655103,6651157.211435708,91.7464899322843],[508789.1626773728,6651158.162695862,98.34484661064175],[508794.9524655103,6651157.211435708,91.87648993228431],[508788.86914764997,6651158.447770022,98.47068992764929],[508787.79872931115,6651159.48735336,98.69524178576452],[508788.5741630632,6651158.734257137,98.56799782418399],[508788.18287389237,6651159.114274638,98.65479230272302],[508795.13602509245,6651156.630127247,93.57529359128431],[508794.9524655103,6651157.211435708,93.57529359128431],[508795.1297137123,6651156.650114537,94.0408842782843],[508794.9468966456,6651157.229071553,93.98610890328429],[508795.10997718555,6651156.712617458,94.51815523028431],[508794.92948206305,6651157.284221189,94.4072303312843],[508795.07579756796,6651156.820859702,95.00105625028431],[508794.89932357677,6651157.379729051,94.8333194662843],[508795.0402502238,6651156.93343335,95.3627622352843],[508794.85580528405,6651157.51754562,95.25822597028431],[508794.99602856697,6651157.073477378,95.72052008128429],[508794.79866645223,6651157.6984966,95.6751926722843],[508794.94312731485,6651157.241008515,96.07097629628431],[508794.8816962875,6651157.435552301,96.4107213232843],[508794.7280577411,6651157.922104873,96.0771415892843],[508794.8120456112,6651157.656126606,96.73638843328429],[508794.644571644,6651158.186494092,96.4570223912843],[508794.73464402213,6651157.901247009,97.0447572412843],[508794.57411152613,6651158.4096317915,96.72342870628431],[508794.49756696407,6651158.652038105,96.9711384462843],[508794.6501099134,6651158.16895514,97.3328555922843],[508794.5591953598,6651158.456869281,97.5980533172843],[508794.3872642216,6651159.001352027,97.2685809162843],[508794.4627639542,6651158.762254546,97.8381417642843],[508794.2692937934,6651159.3749484755,97.5247940392843],[508794.36176381324,6651159.082108383,98.0513940992843],[508794.1457317201,6651159.766252911,97.7370718482843],[508794.2571974974,6651159.413255814,98.23660300128431],[508794.018719084,6651160.168484814,97.9041866052843],[508794.150090788,6651159.752448331,98.39309429328429],[508791.2788742904,6651168.845204068,91.7464899322843],[508791.2788742904,6651168.845204068,91.87648993228431],[508793.8903509847,6651160.575009286,98.0263397272843],[508794.04146224837,6651160.096460278,98.52071705228431],[508791.0953147082,6651169.42651253,91.7464899322843],[508793.76258006453,6651160.979642573,98.1050144202843],[508793.932295297,6651160.442177301,98.61981254628431],[508793.6371421265,6651161.376887619,98.1427572792843],[508793.7874882538,6651160.900761694,98.70897719828432],[508793.64532525715,6651161.3509727465,98.7517524392843],[508791.2788735861,6651168.845206299,93.5752935922843],[508801.65980245115,6651158.677523874,91.80494108921562],[508791.2802422889,6651168.8408718025,93.7791148762843],[508793.1101922808,6651163.045666771,98.1427572792843],[508791.0953147082,6651169.42651253,93.57529359128431],[508791.2916071996,6651168.804880661,94.1956941642843],[508801.4782893478,6651159.259474593,91.80494108921562],[508801.4782893478,6651159.259474593,91.93494108921564],[508791.10162608826,6651169.40652524,94.0408842782843],[508791.3152972667,6651168.729857411,94.62002128428429],[508791.352079306,6651168.61337365,95.04633163528429],[508791.121362615,6651169.34402232,94.51815523028431],[508792.5941969695,6651164.679754389,98.1427572792843],[508791.40239993186,6651168.454015007,95.46814049428431],[508791.15554223274,6651169.235780076,95.00105625028431],[508792.4687590315,6651165.076999436,98.1050144202843],[508791.466319794,6651168.251589417,95.8784900372843],[508791.19108957675,6651169.123206427,95.3627622352843],[508792.3409881112,6651165.481632723,98.0263397272843],[508801.65980245115,6651158.677523874,93.63374474821562],[508791.54346920294,6651168.007267636,96.27026973128432],[508792.5860145435,6651164.705667031,98.7517524392843],[508792.212620012,6651165.8881571945,97.9041866052843],[508791.6095393809,6651167.798032286,96.5477515912843],[508791.23531123373,6651168.983162398,95.72052008128429],[508792.08560737595,6651166.290389098,97.7370718482843],[508791.68209876254,6651167.5682465015,96.8081922642843],[508791.7605211467,6651167.319893379,97.0491619102843],[508791.9620453025,6651166.681693533,97.5247940392843],[508791.8440748743,6651167.055289983,97.2685809162843],[508792.4438515468,6651165.155878084,98.70897719828432],[508801.4782893478,6651159.259474593,93.63374474821562],[508791.2882124857,6651168.815631263,96.07097629628431],[508801.6535614357,6651158.697533246,94.09933543521562],[508791.34964351315,6651168.621087477,96.4107213232843],[508792.2990445036,6651165.614462476,98.61981254628431],[508791.41929418937,6651168.400513171,96.73638843328429],[508792.1898775523,6651165.960179501,98.52071705228431],[508801.47278256953,6651159.277129922,94.04456006021562],[508792.0812490126,6651166.304191447,98.39309429328429],[508791.4966957784,6651168.155392769,97.0447572412843],[508801.6340449486,6651158.760105223,94.57660638721562],[508791.9741423031,6651166.643383963,98.23660300128431],[508791.5812298872,6651167.887684638,97.3328555922843],[508791.8695759873,6651166.974531394,98.0513940992843],[508791.67214444076,6651167.599770498,97.5980533172843],[508791.7685758464,6651167.29438523,97.8381417642843],[508801.4555621396,6651159.33234049,94.46568148821562],[508801.60024639446,6651158.868467058,95.05950740721562],[508801.42573988595,6651159.427953876,94.89177062321563],[508801.5650953625,6651158.981165084,95.42121339221562],[508801.38270677225,6651159.565922711,95.31667712721563],[508801.5213667263,6651159.12136384,95.77897123821562],[508801.32620497287,6651159.747073614,95.73364382921562],[508801.46905526257,6651159.289080073,96.12942745321564],[508801.4083091207,6651159.4838388,96.46917248021562],[508801.2563834678,6651159.970928941,96.13559274621562],[508801.33943496953,6651159.704656808,96.79483959021562],[508801.173828145,6651160.235610271,96.51547354821564],[508801.2628963195,6651159.950048032,97.10320839821563],[508801.1041535766,6651160.458994503,96.78187986321562],[508801.0284623986,6651160.70166864,97.02958960321564],[508801.179304669,6651160.21805194,97.39130674921562],[508801.0894037084,6651160.506284182,97.65650447421564],[508800.9193894053,6651161.0513685,97.32703207321562],[508806.02157038066,6651160.022071428,91.84040728419325],[508800.9940474024,6651160.812006854,97.89659292121564],[508805.84142554365,6651160.604443926,91.84040728419237],[508800.802734212,6651161.425377718,97.58324519621564],[508805.84142554365,6651160.604443926,91.97040728419239],[508800.8941732972,6651161.1322140815,98.10984525621564],[508800.68054971413,6651161.817114487,97.79552300521563],[508800.7907727759,6651161.463727381,98.29505415821562],[508800.5549531232,6651162.219790796,97.96263776221562],[508800.68486018345,6651161.803294654,98.45154545021563],[508797.8456544565,6651170.906096526,91.80494108921562],[508806.02157038066,6651160.022071428,93.66921094319325],[508797.8456544565,6651170.906096526,91.93494108921564],[508800.428016181,6651162.626764416,98.08479088421562],[508800.5774427274,6651162.147686682,98.57916820921564],[508797.66414135316,6651171.488047247,91.80494108921562],[508805.84142554365,6651160.604443926,93.66921094319237],[508800.30166975997,6651163.031844763,98.16346557721562],[508806.01537641056,6651160.042095303,94.13480163019182],[508800.46949286223,6651162.493785672,98.67826370321563],[508800.1776303111,6651163.429528705,98.20120843621562],[508805.83596027637,6651160.622112051,94.08002625519457],[508800.32630025153,6651162.952876732,98.76742835521563],[508805.99600704084,6651160.10471263,94.61207258219072],[508805.8188696561,6651160.677362634,94.50114768319555],[508800.1857222093,6651163.403585201,98.81020359621563],[508805.9624632644,6651160.213153002,95.09497360219407],[508797.8456537601,6651170.90609876,93.63374474921562],[508805.78927220526,6651160.773045316,94.92723681818944],[508797.8470072035,6651170.901759473,93.83756603321562],[508799.65655535174,6651165.10015161,98.20120843621562],[508805.9275772049,6651160.325932708,95.45667958719376],[508797.66414135316,6651171.488047247,93.63374474821562],[508797.85824540845,6651170.865728568,94.25414532121562],[508805.7465634801,6651160.911114147,95.35214332219047],[508805.8841782,6651160.466233075,95.81443743319278],[508797.6703823686,6651171.468037874,94.09933543521562],[508797.8816713584,6651170.790622428,94.67847244121562],[508805.69048759807,6651161.092396343,95.76911002419283],[508805.8322610662,6651160.634070863,96.1648936481941],[508797.9180433202,6651170.674009969,95.10478279221563],[508797.6898988557,6651171.405465897,94.57660638721562],[508799.1463127965,6651166.736044649,98.20120843621562],[508797.96780292894,6651170.514475261,95.52659165121563],[508797.72369740985,6651171.2971040625,95.05950740721562],[508805.7719728354,6651160.828970745,96.50463867519221],[508799.0222733476,6651167.133728593,98.16346557721562],[508805.6211924154,6651161.316413912,96.17105894119219],[508798.0310101579,6651170.311826021,95.93694119421562],[508798.8959269265,6651167.538808937,98.08479088421562],[508797.7588484418,6651171.1844060365,95.42121339221562],[508798.1072994394,6651170.0672343,96.32872088821563],[508799.13822159515,6651166.7619859185,98.81020359621563],[508798.76898998435,6651167.945782559,97.96263776221562],[508798.1726330106,6651169.857767776,96.60620274821562],[508805.7036178657,6651161.049948793,96.83030578519424],[508797.802577078,6651171.044207281,95.77897123821562],[508798.64339339343,6651168.3484588675,97.79552300521563],[508798.2443834383,6651169.627728113,96.86664342121563],[508805.53925940424,6651161.581287075,96.55093974319398],[508798.32193150296,6651169.3791005965,97.10761306721562],[508798.52120889554,6651168.740195637,97.58324519621564],[508798.4045537023,6651169.114204854,97.32703207321562],[508798.9976435527,6651167.212694388,98.76742835521563],[508797.85488854174,6651170.8764910465,96.12942745321564],[508798.8544509421,6651167.671785448,98.67826370321563],[508797.9156346836,6651170.68173232,96.46917248021562],[508805.6276561724,6651161.295517869,97.13867459319158],[508805.47011005046,6651161.804833207,96.81734605819234],[508798.7465010769,6651168.017884438,98.57916820921564],[508797.9845088348,6651170.460914312,96.79483959021562],[508798.63908362086,6651168.362276467,98.45154545021563],[508798.0610474849,6651170.215523088,97.10320839821563],[508798.5331710284,6651168.701843739,98.29505415821562],[508798.1446391353,6651169.947519179,97.39130674921562],[508798.4297705071,6651169.033357039,98.10984525621564],[508798.23454009584,6651169.659286938,97.65650447421564],[508798.3298964019,6651169.353564266,97.89659292121564],[508805.3949894412,6651162.047683226,97.065055798192],[508805.54469464545,6651161.563716018,97.42677294419249],[508805.45547136874,6651161.852157161,97.69197066919432],[508805.2867386526,6651162.397636537,97.36249826819326],[508805.3608338692,6651162.158101411,97.93205911619278],[508805.17096281936,6651162.771916824,97.61871139119184],[508805.26171262615,6651162.478540713,98.14531145119072],[508805.04969936213,6651163.163937511,97.83098920019165],[508805.1590915499,6651162.810294283,98.33052035319271],[508804.9250495327,6651163.566905666,97.99810395719315],[508805.05397733854,6651163.150107662,98.48701164519102],[508802.2361738679,6651172.259506941,91.84040728419299],[508802.2361738679,6651172.259506941,91.97040728419302],[508804.79906945553,6651163.974174247,98.12025707919231],[508804.94736960786,6651163.494749295,98.61463440419426],[508802.0560290307,6651172.841879439,91.84040728419106],[508804.6736754481,6651164.379548183,98.1989317721914],[508804.8402334811,6651163.841099124,98.71372989819434],[508804.55057102285,6651164.777520353,98.23667463119219],[508804.6981202724,6651164.300522918,98.80289455019278],[508804.55860192346,6651164.751558046,98.84566979119329],[508802.23617317685,6651172.259509175,93.66921094419426],[508802.2375164178,6651172.255166743,93.87303222819412],[508804.0334239857,6651166.449354069,98.23667463119065],[508802.0560290307,6651172.841879439,93.66921094319106],[508802.2486699077,6651172.219109724,94.2896115161922],[508802.0622230007,6651172.821855564,94.13480163019142],[508802.2719192703,6651172.14394915,94.71393863619335],[508802.3080170559,6651172.027252174,95.1402489871918],[508802.0815923706,6651172.759238237,94.61207258219358],[508803.52702769707,6651168.0864327485,98.23667463119213],[508802.35740157095,6651171.867601841,95.56205784619114],[508802.1151361473,6651172.650797865,95.09497360219257],[508803.4039232714,6651168.484404921,98.19893177219056],[508802.42013233656,6651171.664805727,95.97240738919054],[508803.27852926427,6651168.889778854,98.120257079192],[508802.15002220694,6651172.53801816,95.45667958719415],[508802.4958465408,6651171.420036733,96.3641870831913],[508803.51899748814,6651168.11239282,98.84566979119231],[508803.1525491875,6651169.297047436,97.99810395719369],[508802.56068762037,6651171.210418396,96.64166894319322],[508802.1934212113,6651172.397717793,95.81443743319153],[508803.02789935796,6651169.700015591,97.83098920019393],[508802.631897185,6651170.980212009,96.9021096161917],[508802.70886068366,6651170.731404295,97.14307926219281],[508802.90663590055,6651170.092036278,97.61871139119249],[508802.79086006735,6651170.466316564,97.3624982681923],[508803.3794791392,6651168.563427947,98.8028945501939],[508802.24533834547,6651172.229880003,96.16489364819257],[508814.0174386713,6651162.486857572,91.90542289905302],[508803.3084225346,6651168.793139845,98.75831222403362],[508803.2373659306,6651169.022851741,98.7137298981923],[508802.3056265758,6651172.034980122,96.5046386751908],[508803.13022980397,6651169.369201573,98.61463440419368],[508802.3739815461,6651171.814002072,96.83030578519366],[508813.83980210137,6651163.070003264,91.90542289905302],[508803.0236220729,6651169.713843205,98.48701164519329],[508802.4499432392,6651171.568432997,97.138674593194],[508802.9185078617,6651170.053656584,98.33052035319393],[508802.5329047661,6651171.300234849,97.42677294419308],[508813.83980210137,6651163.070003264,92.03542289905302],[508802.8158867849,6651170.385410154,98.14531145119105],[508802.62212804286,6651171.011793706,97.69197066919236],[508802.71676554205,6651170.705849456,97.93205911619029],[508814.0174386713,6651162.486857572,93.73422655805301],[508813.83980210137,6651163.070003264,93.73422655805301],[508814.0113309439,6651162.506908032,94.19981724505301],[508813.8344129301,6651163.087694844,94.145041870053],[508813.9922312659,6651162.569608494,94.67708819705302],[508813.81756027293,6651163.143018781,94.56616329805301],[508813.9591545395,6651162.678192838,95.15998921705301],[508813.7883749262,6651163.238828498,94.99225243305301],[508813.9247542201,6651162.791122275,95.52169520205301],[508813.74626086076,6651163.377080636,95.41715893705303],[508813.8819594862,6651162.931608914,95.87945304805302],[508813.6909657572,6651163.558603514,95.83412563905301],[508813.8307652264,6651163.099669534,96.22990926305302],[508813.7713164258,6651163.294828177,96.56965429005301],[508813.62263541395,6651163.782918502,96.23607455605301],[508813.703913204,6651163.5160996085,96.895321400053],[508813.54184320604,6651164.048143325,96.61595535805301],[508813.6290091721,6651163.761994716,97.20369020805302],[508813.47365666134,6651164.271986252,96.88236167305303],[508813.39958200237,6651164.515158691,97.13007141305302],[508813.5472027692,6651164.03054894,97.49178855905302],[508818.26647299883,6651163.77588621,91.93688853122363],[508813.45922180265,6651164.319373035,97.75698628405301],[508813.2928384557,6651164.865576622,97.42751388305301],[508818.0901693312,6651164.359436262,91.93688853122363],[508818.0901693312,6651164.359436262,92.06688853122364],[508813.36590199923,6651164.625723476,97.99707473105302],[508813.1786746405,6651165.2403538255,97.68372700605302],[508813.26816088223,6651164.946588212,98.21032706605301],[508813.05909960857,6651165.632894982,97.89600481505302],[508813.1669686618,6651165.278782236,98.39553596805303],[508812.936185355,6651166.036398141,98.06311957205301],[508818.26647299883,6651163.77588621,93.76569219022363],[508813.0633180202,6651165.619046772,98.55202726005301],[508810.2847485534,6651174.740540226,91.90542289905302],[508812.8119593757,6651166.444207436,98.18527269405301],[508810.2847485534,6651174.740540226,92.03542289905302],[508818.0901693312,6651164.359436262,93.76569219022363],[508812.9581946539,6651165.9641459705,98.67965001905301],[508818.2604111008,6651163.795950573,94.23128287722363],[508810.1071119834,6651175.323685916,91.90542289905302],[508812.68831130594,6651166.850119569,98.26394738705301],[508812.852550249,6651166.310955635,98.77874551305301],[508818.0848205978,6651164.377140112,94.17650750222364],[508818.2414547379,6651163.8586945115,94.70855382922363],[508812.5669209389,6651167.248620112,98.30169024605303],[508812.7124157698,6651166.770989386,98.86791016505303],[508818.06809439516,6651164.432502412,94.59762893022365],[508818.20862620405,6651163.96735415,95.19145484922363],[508812.5748400202,6651167.222623335,98.91068540605302],[508818.03912804177,6651164.528378562,95.02371806522363],[508818.1744840087,6651164.080361894,95.55316083422365],[508810.2847478718,6651174.740542462,93.73422655905301],[508810.28607240994,6651174.736194265,93.93804784305303],[508812.056974457,6651168.922673453,98.30169024605303],[508817.99732998066,6651164.666726568,95.44862456922364],[508818.1320103867,6651164.220945949,95.91091868022365],[508810.1071119834,6651175.323685916,93.73422655805301],[508810.2970706032,6651174.700089375,94.35462713105301],[508817.942449786,6651164.848375316,95.86559127122365],[508810.1132197108,6651175.303635455,94.19981724505301],[508818.08120026474,6651164.389123105,96.26137489522364],[508810.31999625056,6651174.624829014,94.77895425105301],[508810.3555914248,6651174.507977105,95.205264602053],[508810.1323193889,6651175.240934993,94.67708819705302],[508818.0221975404,6651164.584417073,96.60111992222363],[508817.8746321619,6651165.072845848,96.26754018822363],[508811.55762903386,6651170.561925614,98.30169024605303],[508810.40428832907,6651174.348114808,95.62707346105303],[508811.4362386668,6651170.960426157,98.26394738705301],[508810.1653961152,6651175.132350651,95.15998921705301],[508810.46614565584,6651174.145049451,96.03742300405301],[508817.9553000812,6651164.8058419395,96.92678703222364],[508811.3125905971,6651171.36633829,98.18527269405301],[508817.79444618133,6651165.338254582,96.64742099022364],[508810.1997964346,6651175.019421211,95.52169520205301],[508810.5408056448,6651173.899955488,96.42920269805303],[508811.54971063446,6651170.587920152,98.91068540605302],[508811.1883646179,6651171.774147584,98.06311957205301],[508810.60474390205,6651173.690058848,96.70668455805301],[508810.24259116844,6651174.878934573,95.87945304805302],[508811.0654503643,6651172.177650744,97.89600481505302],[508810.67496197246,6651173.459546825,96.96712523105302],[508810.9458753324,6651172.5701919,97.68372700605302],[508810.750853861,6651173.21040878,97.20809487705303],[508810.8317115172,6651172.944969103,97.42751388305301],[508817.8809580943,6651165.051907552,97.23515584022365],[508811.41213488486,6651171.039554101,98.86791016505303],[508817.7267712768,6651165.562252725,96.91382730522363],[508810.29378542834,6651174.710873954,96.22990926305302],[508822.1918849311,6651164.9449669225,91.9627256389017],[508811.27200040565,6651171.499587852,98.77874551305301],[508810.3532342289,6651174.515715311,96.56965429005301],[508811.1663560008,6651171.846397517,98.67965001905301],[508810.4206374507,6651174.294443878,96.895321400053],[508817.7997655288,6651165.320647997,97.52325419122363],[508817.65325243963,6651165.805593786,97.16153704522364],[508811.0612326346,6651172.191496716,98.55202726005301],[508810.4955414826,6651174.048548771,97.20369020805302],[508810.95758199284,6651172.531761251,98.39553596805303],[508810.5773478855,6651173.779994546,97.49178855905302],[508810.85638977255,6651172.863955278,98.21032706605301],[508810.665328852,6651173.491170452,97.75698628405301],[508810.75864865555,6651173.184820014,97.99707473105302],[508817.71244473057,6651165.609672367,97.78845191622364],[508817.5473098471,6651166.1562547,97.45897951522365],[508822.372404784,6651165.634787478,91.96506541656744],[508822.372404784,6651165.634787478,92.09506541656745],[508817.6198251556,6651165.9162352355,98.02854036322364],[508817.4340026641,6651166.53129178,97.71519263822364],[508817.52281744266,6651166.237322463,98.24179269822363],[508822.1918849311,6651164.9449669225,93.7915292979017],[508817.31532486784,6651166.92410513,97.92747044722366],[508817.4223845218,6651166.569746836,98.42700160022363],[508817.1933329059,6651167.327888085,98.09458520422365],[508822.1980917954,6651164.968685214,94.25720045849617],[508817.31951162644,6651166.9102473175,98.58349289222363],[508814.5617912562,6651176.038065758,91.93688853122363],[508817.0700390607,6651167.7359801615,98.21673832622365],[508814.5617912562,6651176.038065758,92.06688853122364],[508822.372404784,6651165.634787478,93.79386907556744],[508817.2151770572,6651167.255585814,98.71111565122364],[508822.2175014869,6651165.042855473,94.73472305094654],[508814.38548758865,6651176.62161581,91.93688853122363],[508816.94731878873,6651168.142173761,98.29541301922363],[508817.110325359,6651167.602635962,98.81021114522363],[508822.37788142887,6651165.655715382,94.20475534924105],[508816.82683927874,6651168.540950629,98.33315587822364],[508822.25111509353,6651165.171303156,95.21805982046632],[508816.9712423839,6651168.062988708,98.89937579722364],[508822.39500762743,6651165.721159728,94.62609867514391],[508816.8346989389,6651168.514935827,98.94215103822366],[508822.2860737768,6651165.30489078,95.5802189378769],[508822.4246666921,6651165.834495918,95.0525720605858],[508814.5617905797,6651176.038067996,93.76569219122364],[508814.56310517923,6651176.033716784,93.96951347522364],[508816.3207191986,6651170.216164784,98.33315587822364],[508822.32956312713,6651165.471076645,95.93854041346947],[508814.38548758865,6651176.62161581,93.76569219022363],[508822.4674643263,6651165.998038527,95.47803296306158],[508814.57402084715,6651175.9975868575,94.38609276322363],[508814.39154948655,6651176.601551446,94.23128287722363],[508822.38158834004,6651165.669880602,96.2896707724538],[508814.5967744711,6651175.92227431,94.81041988322364],[508814.6321025556,6651175.805341372,95.23673023422363],[508814.41050584946,6651176.538807507,94.70855382922363],[508822.52365694434,6651166.212767391,95.89572745636704],[508815.825120632,6651171.85655363,98.33315587822364],[508822.4420020749,6651165.900739621,96.63019848922737],[508814.6804340608,6651175.645368226,95.65853909322364],[508815.7046411219,6651172.255330498,98.29541301922363],[508814.4433343833,6651176.430147869,95.19145484922363],[508814.741827239,6651175.442162061,96.06888863622363],[508815.58192085003,6651172.661524097,98.21673832622365],[508814.47747657873,6651176.317140124,95.55316083422365],[508815.8172616486,6651171.882566192,98.94215103822366],[508814.815927014,6651175.196898146,96.46066833022364],[508815.4586270048,6651173.069616174,98.09458520422365],[508822.59309638164,6651166.47811633,96.29857553761954],[508814.8793855082,6651174.9868559595,96.73815019022364],[508815.33663504286,6651173.473399128,97.92747044722366],[508814.51995020075,6651176.176556069,95.91091868022365],[508814.9490766948,6651174.756184096,96.99859086322364],[508822.51049934304,6651166.162488246,96.95675281647692],[508815.2179572465,6651173.866212479,97.71519263822364],[508815.0243991258,6651174.506873295,97.23956050922365],[508815.1046500636,6651174.241249558,97.45897951522365],[508815.68071820354,6651172.33451331,98.89937579722364],[508814.5707603226,6651176.008378915,96.26137489522364],[508815.5416352285,6651172.794866056,98.81021114522363],[508814.62976304704,6651175.813084945,96.60111992222363],[508815.4367835303,6651173.141916205,98.71111565122364],[508814.69666050636,6651175.59166008,96.92678703222364],[508815.332448961,6651173.487254701,98.58349289222363],[508814.77100249304,6651175.345594465,97.23515584022365],[508822.6751999569,6651166.791858739,96.67951921077417],[508815.22957606567,6651173.827755182,98.42700160022363],[508814.85219505866,6651175.076854022,97.52325419122363],[508822.5866191689,6651166.453364954,97.26610732601614],[508815.1291431448,6651174.160179555,98.24179269822363],[508814.93951585685,6651174.7878296515,97.78845191622364],[508815.0321354318,6651174.4812667845,98.02854036322364],[508822.7444932617,6651167.056649261,96.94682232590775],[508822.6697534008,6651166.771045813,97.55528191281114],[508822.81977025385,6651167.344305247,97.19550606296447],[508822.75916241796,6651167.112704511,97.82163675876285],[508822.9282463929,6651167.758825142,97.49435164092193],[508822.8539969291,6651167.475095649,98.06295215031385],[508823.04426324216,6651168.202160354,97.75206482426465],[508822.9533245171,6651167.854656183,98.27748912713014],[508823.0561592244,6651168.247618474,98.46402756333227],[508823.16577913926,6651168.666509079,97.96591314708884],[508823.1614922571,6651168.650127616,98.62188019819675],[508823.2906884579,6651169.143825087,98.13464158568678],[508823.2683219183,6651169.058355824,98.75088313467333],[508823.41693079384,6651169.626234953,98.25842490002799],[508823.37568107556,6651169.468607395,98.85136513173755],[508823.5425858402,6651170.106400609,98.33872149297953],[508823.51809012797,6651170.012795139,98.94236814657671],[508823.6659465378,6651170.577798871,98.37805595023299],[508823.6578989189,6651170.547046503,98.9869473007037],[508824.18417014414,6651172.558086854,98.38473463639099],[508832.95745439094,6651168.151208672,92.03358474417486],[508832.78575921635,6651168.736131243,92.03358474417486],[508832.78575921635,6651168.736131243,92.16358474417487],[508832.95745439094,6651168.151208672,93.86238840317486],[508832.78575921635,6651168.736131243,93.86238840317486],[508832.9515509481,6651168.171320227,94.32797909017485],[508832.78055029624,6651168.753876733,94.27320371517484],[508824.6916206219,6651174.49720748,98.3912628763363],[508832.93309009535,6651168.23421174,94.80525004217485],[508832.7642613085,6651168.809369245,94.69432514317485],[508834.91805535817,6651168.725594205,92.04507518621509],[508832.9011196836,6651168.343126947,95.28815106217486],[508824.6996675483,6651174.5279572,99.000361465957],[508824.81498131994,6651174.968605742,98.35510529410794],[508832.73605212156,6651168.905470898,95.12041427817485],[508834.746975215,6651169.310696958,92.04507518621509],[508825.9851616828,6651179.440216226,92.01158491380276],[508834.746975215,6651169.310696958,92.1750751862151],[508832.8678699487,6651168.4564004885,95.64985704717485],[508825.9851616828,6651179.440216226,92.14158491380277],[508824.94063636544,6651175.448771397,98.27804466653393],[508832.69534664176,6651169.044144301,95.54532078217485],[508824.83947633876,6651175.062208563,98.95938277082355],[508832.8265065667,6651168.597315199,96.00761489317485],[508825.06687870115,6651175.931181262,98.15751244752472],[508832.6419009889,6651169.22622029,95.96228748417485],[508826.16568153584,6651180.130036781,92.01389415230373],[508832.777024597,6651168.76588791,96.35807110817487],[508824.9818853913,6651175.606396307,98.87204718498923],[508834.91805535817,6651168.725594205,93.87387884521509],[508825.1917880205,6651176.408497271,97.99200078177701],[508832.71956417535,6651168.961641212,96.69781613517486],[508832.5758560848,6651169.451218779,96.36423640117485],[508825.08924454823,6651176.016647878,98.77432998960177],[508834.746975215,6651169.310696958,93.87387884521509],[508834.91217306204,6651168.745711955,94.3394695322151],[508825.98516237503,6651179.440218871,93.84038858266251],[508825.3133039177,6651176.872845997,97.7812818484891],[508832.65441538347,6651169.183586872,97.02348324517484],[508825.983816338,6651179.43507526,94.04419264253698],[508832.4977661271,6651169.717251758,96.74411720317487],[508825.1960742097,6651176.424876087,98.6480782236168],[508834.7417849538,6651169.328447915,94.28469415721509],[508834.8937783383,6651168.808622842,94.81674048421509],[508825.42932076653,6651177.316181207,97.52655644535326],[508825.9726396292,6651179.3923657,94.46062890832961],[508832.5820166604,6651169.430231238,97.33185205317486],[508832.43186021206,6651169.941776749,97.01052351817485],[508825.3014072421,6651176.827385227,98.49293822201905],[508825.51149085234,6651177.6301777745,97.30819077092062],[508834.72555431514,6651169.383957521,94.70581558521509],[508825.9493418676,6651179.303337958,94.8846578819189],[508825.5886145694,6651177.924890652,97.06820949544128],[508826.16568153584,6651180.130036781,93.84269781130374],[508834.8619224481,6651168.9175716,95.29964150421509],[508825.91316893493,6651179.165110323,95.31050527267823],[508825.6599723748,6651178.197570249,96.8086830660119],[508825.40424195013,6651177.22034752,98.30904808548469],[508832.5029464295,6651169.699603763,97.61995040417486],[508832.3602631219,6651170.18569015,97.25823325817485],[508825.8636816144,6651178.976004412,95.73168067320069],[508825.72494843695,6651178.44586329,96.5320334900092],[508825.80082025914,6651178.735792302,96.14122540835535],[508834.69744617667,6651169.480088778,95.13190472021509],[508826.1594746717,6651180.106318489,94.30820912300204],[508834.8287918175,6651169.030880034,95.66134748921509],[508825.503569538,6651177.599908054,98.09706909526902],[508832.4179081549,6651169.989307922,97.88514812917485],[508832.25708981766,6651170.537175825,97.55567572817485],[508825.5984040485,6651177.962299191,97.85819598559807],[508826.1400649798,6651180.032148229,94.78523184687617],[508834.6568865084,6651169.618804897,95.5568112242151],[508834.7875766038,6651169.171838152,96.01910533521509],[508825.68781306606,6651178.303957889,97.59414370370696],[508826.106451373,6651179.903700546,95.26770294731547],[508832.327709611,6651170.29659183,98.12523657617486],[508825.770947298,6651178.621638748,97.30711009047509],[508826.07149269,6651179.770112922,95.62896175624135],[508832.1467444299,6651170.913094997,97.81188885117486],[508825.8470671244,6651178.912515458,96.99971591547958],[508826.02800333954,6651179.603927057,95.98616323029663],[508834.60363230394,6651169.800936973,95.97377792621509],[508825.91556439176,6651179.174264081,96.67492562078117],[508834.738271884,6651169.340462791,96.3695615502151],[508825.9759781274,6651179.4051231025,96.33595376183395],[508832.23323763296,6651170.618434261,98.33848891117486],[508832.0311688141,6651171.30683225,98.02416666017486],[508834.68101729214,6651169.536276395,96.70930657721509],[508834.53782398015,6651170.026004774,96.3757268432151],[508832.1354299803,6651170.951640502,98.52369781317485],[508831.91236566316,6651171.711564909,98.19128141717485],[508834.61610187055,6651169.758290425,97.0349736872151],[508832.0352461329,6651171.292941844,98.68018910517485],[508834.46001374954,6651170.292119702,96.7556076452151],[508831.7922946598,6651172.120616824,98.31343453917485],[508829.349611245,6651180.442229048,92.03358474417486],[508831.93363881897,6651171.639092581,98.80781186417487],[508829.349611245,6651180.442229048,92.16358474417487],[508834.5439624879,6651170.005010765,97.34334249521511],[508834.39434391685,6651170.516713856,97.02201396021509],[508831.6727822367,6651172.5277657965,98.39210923217486],[508829.1779160704,6651181.02715162,92.03358474417486],[508831.83152789366,6651171.986958997,98.90690735817486],[508834.46517549537,6651170.27446627,97.63144084621509],[508834.3230032955,6651170.760702394,97.2697237002151],[508831.555452003,6651172.927480595,98.42985209117485],[508831.6960804805,6651172.448394501,98.99607201017487],[508834.38044183754,6651170.564259672,97.8966385712151],[508834.22019956965,6651171.112296342,97.56716617021509],[508831.5631062154,6651172.901404604,99.03884725117486],[508834.2905663949,6651170.871638236,98.1367270182151],[508834.1102494516,6651171.488331314,97.82337929321511],[508829.3496105863,6651180.442231293,93.86238840417485],[508831.06256165804,6651174.606634879,98.42985209117485],[508829.3508908227,6651180.437869848,94.06620968817485],[508834.19643282617,6651171.193579809,98.34997935321509],[508829.1779160704,6651181.02715162,93.86238840317486],[508833.9950878406,6651171.882189856,98.0356571022151],[508829.36152116035,6651180.401654943,94.48278897617486],[508834.0989755315,6651171.526888691,98.53518825521509],[508829.18381951324,6651181.007040066,94.32797909017485],[508833.87671025604,6651172.28704719,98.2027718592151],[508829.3836800155,6651180.326165258,94.90711609617485],[508833.9991505539,6651171.868295171,98.69167954721509],[508829.4180846409,6651180.208957293,95.33342644717486],[508829.202280366,6651180.944148551,94.80525004217485],[508833.75706936046,6651172.696225111,98.3249249812151],[508830.57991779933,6651176.250881943,98.42985209117485],[508831.32313591294,6651181.020400761,92.04507518621509],[508833.89790720894,6651172.214552538,98.81930230621509],[508831.32313591294,6651181.020400761,92.1750751862151],[508829.4651527839,6651180.048607889,95.75523530617485],[508830.46258756565,6651176.650596741,98.39210923217486],[508829.23425077775,6651180.835233344,95.28815106217486],[508833.63798504433,6651173.103499503,98.40359967421509],[508829.52494117385,6651179.844923778,96.16558484917485],[508833.7961620564,6651172.5625261115,98.91839780021509],[508830.3430751425,6651177.057745712,98.31343453917485],[508831.15205576975,6651181.605503514,92.04507518621509],[508829.26750051265,6651180.721959803,95.64985704717485],[508830.57226424594,6651176.276955688,99.03884725117486],[508829.5971040165,6651179.599082999,96.55736454317487],[508830.2230041391,6651177.4667976275,98.19128141717485],[508833.52107510075,6651173.503337431,98.44134253321509],[508829.6589037362,6651179.388546792,96.83484640317485],[508830.1042009882,6651177.871530287,98.02416666017486],[508829.3088638946,6651180.581045093,96.00761489317485],[508829.7267732288,6651179.157332383,97.09528707617486],[508829.98862537235,6651178.265267541,97.81188885117486],[508833.66119983123,6651173.024103756,99.0075624522151],[508829.80012676766,6651178.907435199,97.33625672217485],[508830.4392899808,6651176.729965792,98.99607201017487],[508829.8782799847,6651178.641186711,97.55567572817485],[508829.35834586434,6651180.412472383,96.35807110817487],[508830.30384256766,6651177.191401295,98.90690735817486],[508829.415806286,6651180.216719079,96.69781613517486],[508833.528701895,6651173.477253408,99.05033769321511],[508830.20173164236,6651177.53926771,98.80781186417487],[508829.48095507786,6651179.9947734205,97.02348324517484],[508830.1001243285,6651177.885418449,98.68018910517485],[508829.5533538009,6651179.748129055,97.33185205317486],[508829.9999404811,6651178.22671979,98.52369781317485],[508829.63242403185,6651179.478756529,97.61995040417486],[508829.9021328284,6651178.559926032,98.33848891117486],[508829.71746230655,6651179.18905237,97.88514812917485],[508829.80766085035,6651178.881768462,98.12523657617486],[508831.32313525653,6651181.020403006,93.8738788462151],[508833.0299503446,6651175.183008968,98.44134253321509],[508831.324410907,6651181.016040216,94.07770013021509],[508831.15205576975,6651181.605503514,93.87387884521509],[508831.3350031655,6651180.979814156,94.49427941821509],[508831.1579380658,6651181.585385765,94.3394695322151],[508831.3570826452,6651180.904301217,94.91860653821509],[508831.3913640293,6651180.787057147,95.34491688921509],[508831.17633278965,6651181.522474877,94.81674048421509],[508832.54903537047,6651176.827762534,98.44134253321509],[508831.4382635689,6651180.6266583465,95.7667257482151],[508832.4321254269,6651177.227600462,98.40359967421509],[508831.2081886798,6651181.413526119,95.29964150421509],[508831.49783779023,6651180.422911493,96.1770752912151],[508832.31304111076,6651177.634874854,98.3249249812151],[508831.2413193104,6651181.300217684,95.66134748921509],[508832.54140923294,6651176.85384431,99.05033769321511],[508831.56974213733,6651180.176994984,96.5688549852151],[508832.1934002152,6651178.044052775,98.2027718592151],[508831.6313204835,6651179.966393922,96.8463368452151],[508832.0750226306,6651178.44891011,98.0356571022151],[508831.2825345241,6651181.159259568,96.01910533521509],[508831.69894685986,6651179.735108291,97.10677751821511],[508831.9598610196,6651178.842768651,97.82337929321511],[508831.77203763823,6651179.485134127,97.3477471642151],[508832.4089112967,6651177.306993962,99.0075624522151],[508831.84991090157,6651179.218803623,97.56716617021509],[508831.33183924394,6651180.990634928,96.3695615502151],[508832.27394907153,6651177.768571609,98.91839780021509],[508831.3890938358,6651180.794821326,96.70930657721509],[508832.172203919,6651178.116545183,98.81930230621509],[508831.4540092573,6651180.572807295,97.0349736872151],[508832.07096057397,6651178.462802549,98.69167954721509],[508831.52614863997,6651180.326086953,97.34334249521511],[508831.9711355964,6651178.804209027,98.53518825521509],[508831.60493563255,6651180.056631449,97.63144084621509],[508831.87367830175,6651179.137517911,98.34997935321509],[508831.6896692904,6651179.766838048,97.8966385712151],[508831.779544733,6651179.459459483,98.1367270182151],[508851.61321885866,6651173.526252328,92.12950105420167],[508851.44737591106,6651174.112861025,92.12950105420167],[508851.95411219,6651173.622594357,92.13097546765042],[508851.44737591106,6651174.112861025,92.25950105420169],[508851.7883761792,6651174.209233276,92.13097546765042],[508851.7883761792,6651174.209233276,92.26097546765041],[508851.61321885866,6651173.526252328,93.95830471320168],[508851.44737591106,6651174.112861025,93.95830471320168],[508851.6075166345,6651173.546421858,94.42389540020167],[508851.95411219,6651173.622594357,93.9597791266504],[508851.442344537,6651174.130657669,94.36912002520167],[508851.58968501963,6651173.609494666,94.90116635220167],[508851.7883761792,6651174.209233276,93.9597791266504],[508851.9484136427,6651173.642764926,94.4253698136504],[508851.4266107591,6651174.186310148,94.79024145320167],[508851.78334804927,6651174.227030836,94.3705944386504],[508851.9305935258,6651173.705840983,94.90264076565042],[508851.55880431883,6651173.718723837,95.38406737220168],[508851.3993630818,6651174.282688828,95.21633058820167],[508851.7676244167,6651174.282686182,94.7917158666504],[508851.5266879006,6651173.832323905,95.74577335720167],[508851.8997327371,6651173.815075781,95.3855417856504],[508851.3600450476,6651174.421761977,95.64123709220168],[508851.7403943089,6651174.3790698275,95.2178050016504],[508851.48673438875,6651173.973644823,96.10353120320167],[508851.86763702775,6651173.928681702,95.7472477706504],[508851.3084210889,6651174.604362826,96.05820379420167],[508851.7011016271,6651174.5181501405,95.64271150565042],[508851.43893901113,6651174.14270347,96.45398741820169],[508851.8277092782,6651174.070009902,96.1050056166504],[508851.38343712705,6651174.339021062,96.79373244520168],[508851.6495109559,6651174.700760398,96.0596782076504],[508851.24462732434,6651174.8300099075,96.46015271120167],[508851.77994471934,6651174.239077259,96.45546183165041],[508851.3205089306,6651174.561606512,97.11939955520167],[508851.72447862325,6651174.435404963,96.7952068586504],[508851.585758326,6651174.926419106,96.4616271246504],[508851.1691990614,6651175.096809767,96.84003351320169],[508851.25057791674,6651174.808961867,97.42776836320168],[508851.66159100324,6651174.658001883,97.1208739686504],[508851.1055395483,6651175.321981983,97.10643982820167],[508851.5103786998,6651175.1932327105,96.84150792665041],[508851.1742027932,6651175.079110898,97.71586671420168],[508851.0363828438,6651175.566598503,97.35414956820169],[508851.59170508146,6651174.905369979,97.42924277665041],[508851.4467602348,6651175.418416529,97.10791424165042],[508851.09206304676,6651175.369650174,97.98106443920167],[508851.5153792052,6651175.17553293,97.71734112765041],[508851.3776481229,6651175.6630456485,97.35562398165041],[508850.93672619987,6651175.919097387,97.65159203820167],[508851.0049389187,6651175.677819872,98.22115288620168],[508851.43329242297,6651175.466087173,97.9825388526504],[508850.8301419328,6651176.296100203,97.90780516120168],[508851.2780557383,6651176.0155626945,97.6530664516504],[508850.9136870164,6651176.000590063,98.43440522120169],[508851.3462244732,6651175.774272749,98.22262729965041],[508850.7185057098,6651176.690972462,98.12008297020168],[508851.1715401975,6651176.392584933,97.90927957465041],[508850.8192131359,6651176.334756819,98.61961412320167],[508851.2550314107,6651176.097059567,98.4358796346504],[508850.6037519623,6651177.096871823,98.28719772720167],[508851.0599759584,6651176.787477536,98.12155738365041],[508850.7224440532,6651176.677042015,98.77610541520167],[508851.16061844764,6651176.431243542,98.62108853665042],[508850.48777357704,6651177.50710289,98.40935084920167],[508850.9452962049,6651177.193397809,98.2886721406504],[508850.6243000229,6651177.024190582,98.90372817420169],[508848.12834898476,6651185.8527034,92.12950105420167],[508851.06391176226,6651176.773546371,98.7775798286504],[508848.12834898476,6651185.8527034,92.25950105420169],[508850.37233473273,6651177.91542553,98.48802554220168],[508850.52566954674,6651177.373059775,99.00282366820169],[508850.82939260313,6651177.603650013,98.4108252626504],[508847.96250603726,6651186.439312099,92.12950105420167],[508850.9658310159,6651177.120712824,98.90520258765041],[508850.25900369807,6651178.316292565,98.52576840120167],[508848.4714893839,6651185.949680488,92.13097546765042],[508848.4714893839,6651185.949680488,92.26097546765041],[508850.39483885636,6651177.835825434,99.0919883202017],[508850.71402819466,6651178.0119936885,98.48949995565042],[508850.8672641373,6651177.46959999,99.0042980816504],[508848.3057533731,6651186.536319407,92.13097546765042],[508850.60077023663,6651178.412881376,98.52724281465042],[508850.2663970168,6651178.290141408,99.13476356120168],[508850.7365178075,6651177.932389491,99.09346273365043],[508850.6081587881,6651178.386728871,99.13623797465041],[508848.1283483484,6651185.852705651,93.95830471420167],[508849.78291351214,6651180.000287262,98.52576840120167],[508848.129584948,6651185.848331632,94.16212599820167],[508847.96250603726,6651186.439312099,93.95830471320168],[508848.471488748,6651185.949682738,93.9597791276504],[508848.1398529508,6651185.8120123325,94.57870528620168],[508850.1249870369,6651180.096962831,98.52724281465042],[508848.4727245503,6651185.945308494,94.16360041165042],[508847.9682082613,6651186.419142568,94.42389540020167],[508848.1612565217,6651185.736305038,95.00303240620167],[508848.3057533731,6651186.536319407,93.9597791266504],[508848.4829859321,6651185.908987324,94.5801796996504],[508848.194488466,6651185.618759204,95.42934275720168],[508849.3167205611,6651181.649274113,98.52576840120167],[508847.9860398761,6651186.35606976,94.90116635220167],[508848.31145192037,6651186.516148837,94.4253698136504],[508848.50437570194,6651185.833276128,95.0045068196504],[508849.2033895264,6651182.050141148,98.48802554220168],[508848.2399522922,6651185.457947567,95.85115161620168],[508848.016920577,6651186.246840589,95.38406737220168],[508849.0879506822,6651182.458463787,98.40935084920167],[508848.2977027959,6651185.253676308,96.26150115920167],[508848.5375862181,6651185.715724237,95.4308171706504],[508849.6590946902,6651181.746034639,98.52724281465042],[508848.32927203726,6651186.45307278,94.90264076565042],[508849.309327879,6651181.675423019,99.13476356120168],[508848.0490369952,6651186.13324052,95.74577335720167],[508848.97197229695,6651182.868694855,98.28719772720167],[508848.36740596924,6651185.007126857,96.6532808532017],[508849.5458367322,6651182.146922327,98.48949995565042],[508848.5830207288,6651185.554904317,95.85262602965042],[508848.42709924665,6651184.795983747,96.93076271320167],[508848.85721854947,6651183.274594216,98.12008297020168],[508848.4926554087,6651184.5641028285,97.19120338620168],[508849.1808860394,6651182.129738993,99.0919883202017],[508848.08899050707,6651185.991919602,96.10353120320167],[508848.74558232643,6651183.669466475,97.90780516120168],[508848.56350869354,6651184.31348528,97.43217303220167],[508848.3601328261,6651186.343837982,95.3855417856504],[508848.6389980594,6651184.046469292,97.65159203820167],[508849.43047232373,6651182.555266002,98.4108252626504],[508848.6407339946,6651185.350622532,96.2629755726504],[508848.1367858848,6651185.822860955,96.45398741820169],[508849.65170677495,6651181.772184892,99.13623797465041],[508849.0500553491,6651182.592504652,99.00282366820169],[508848.3922285353,6651186.230232061,95.7472477706504],[508849.3145687221,6651182.965518205,98.2886721406504],[508848.7103922229,6651185.10406038,96.65475526665043],[508848.1922877689,6651185.626543365,96.79373244520168],[508848.9514248729,6651182.941373844,98.90372817420169],[508848.7700470097,6651184.892906391,96.9322371266504],[508849.1998889686,6651183.371438478,98.12155738365041],[508848.8355609006,6651184.661013527,97.19267779965041],[508849.52334775554,6651182.226524273,99.09346273365043],[508848.25521596527,6651185.403957913,97.11939955520167],[508848.4321562849,6651186.088903861,96.1050056166504],[508849.08832472935,6651183.766331081,97.90927957465041],[508848.85328084254,6651183.288522412,98.77610541520167],[508848.90636849875,6651184.410383065,97.43364744565042],[508848.98180918855,6651184.14335332,97.6530664516504],[508848.32514697907,6651185.15660256,97.42776836320168],[508848.7565117599,6651183.6308076065,98.61961412320167],[508848.4015221026,6651184.886453527,97.71586671420168],[508848.6620378794,6651183.964974364,98.43440522120169],[508848.47992084373,6651185.919836504,96.45546183165041],[508848.48366184905,6651184.595914254,97.98106443920167],[508848.5707859771,6651184.287744553,98.22115288620168],[508849.39260142576,6651182.689313772,99.0042980816504],[508848.53538693994,6651185.7235088,96.7952068586504],[508849.2940345472,6651183.038200939,98.90520258765041],[508848.59827455983,6651185.500911881,97.1208739686504],[508849.1959538008,6651183.385367393,98.7775798286504],[508848.66816048155,6651185.253543783,97.42924277665041],[508849.09924711543,6651183.727670222,98.62108853665042],[508848.7444863579,6651184.983380833,97.71734112765041],[508849.00483415235,6651184.061854195,98.4358796346504],[508848.82657314016,6651184.69282659,97.9825388526504],[508848.91364108986,6651184.384641014,98.22262729965041],[508862.9688786647,6651176.682449538,92.17073826452479],[508862.8065979349,6651177.270048321,92.17073826452386],[508862.8065979349,6651177.270048321,92.30073826452386],[508862.9688786647,6651176.682449538,93.99954192352479],[508862.8065979349,6651177.270048321,93.99954192352385],[508862.96329892095,6651176.702653111,94.46513261052354],[508862.8016746321,6651177.287875001,94.41035723552457],[508862.94585031964,6651176.765832375,94.94240356252364],[508862.7862788074,6651177.34362141,94.83147866352425],[508862.91563292,6651176.875245904,95.42530458252438],[508862.7596163956,6651177.440162759,95.25756779852415],[508862.88420634513,6651176.989037707,95.78701056752352],[508862.7211428919,6651177.579470636,95.68247430252461],[508862.8451110138,6651177.130597148,96.14476841352497],[508862.6706277882,6651177.762379683,96.0994410045242],[508862.79834225506,6651177.299941134,96.49522462852435],[508862.74403252196,6651177.496590071,96.83496965552457],[508862.60820427974,6651177.988407616,96.5013899215247],[508862.6824559892,6651177.719551206,97.1606367655234],[508862.5343961757,6651178.255657782,96.88127072352452],[508862.61402705655,6651177.967324047,97.46900557352438],[508862.4721040347,6651178.481210046,97.14767703852353],[508862.5392924299,6651178.237929041,97.75710392452419],[508862.40443277935,6651178.726239431,97.39538677852407],[508862.4589170015,6651178.52895869,98.02230164952486],[508862.3069167071,6651179.079333268,97.69282924852448],[508862.373664253,6651178.837648522,98.26239009652396],[508862.20262181305,6651179.456972391,97.94904237152416],[508862.2843723933,6651179.160963486,98.47564243152547],[508862.0933834768,6651179.852511121,98.16132018052465],[508862.19192776096,6651179.495694254,98.6608513335243],[508861.9810945786,6651180.259095563,98.32843493752496],[508862.0972372265,6651179.83855716,98.81734262552403],[508861.86760734697,6651180.670019024,98.45058805952459],[508862.0012012777,6651180.186291651,98.94496538452462],[508859.55886193557,6651189.029705328,92.17073826452425],[508859.55886193557,6651189.029705328,92.30073826452426],[508861.7546480673,6651181.079030836,98.52926275252398],[508861.90468933166,6651180.535749668,99.04406087852502],[508859.3965812058,6651189.617304111,92.17073826452334],[508861.6437513231,6651181.480574457,98.56700561152488],[508861.77666881424,6651180.999296389,99.1332255305231],[508861.6509858372,6651181.454379161,99.17600077152467],[508861.1778873002,6651183.167411417,98.56700561152469],[508859.5588613128,6651189.029707583,93.99954192452388],[508859.560071351,6651189.025326181,94.20336320852385],[508859.3965812058,6651189.617304111,93.99954192352334],[508859.5701188026,6651188.988945583,94.61994249652426],[508859.4021609492,6651189.597100538,94.4651326105235],[508859.5910626361,6651188.913110508,95.0442696165235],[508860.72170792485,6651184.819181446,98.56700561152454],[508859.62358077615,6651188.795366278,95.47057996752416],[508859.41960955085,6651189.533921274,94.9424035625245],[508860.61081118044,6651185.220725069,98.52926275252486],[508859.6680680638,6651188.634283222,95.89238882652492],[508859.44982695085,6651189.424507746,95.42530458252482],[508860.49785190076,6651185.62973688,98.45058805952424],[508859.7245781173,6651188.429667191,96.30273836952409],[508860.7144740336,6651184.845374487,99.17600077152454],[508860.38436466956,6651186.04066034,98.32843493752495],[508859.48125352524,6651189.310715942,95.78701056752408],[508859.7927841038,6651188.182701611,96.69451806352455],[508860.272075771,6651186.447244784,98.16132018052417],[508859.8511952015,6651187.971202131,96.9719999235248],[508860.5887910561,6651185.300457261,99.1332255305245],[508859.915343252,6651187.738929843,97.23244059652424],[508860.1628374343,6651186.842783513,97.94904237152357],[508859.52034885704,6651189.169156501,96.14476841352425],[508859.98467464594,6651187.487889298,97.47341024252378],[508860.05854254065,6651187.220422637,97.69282924852436],[508859.5671176157,6651188.9998125145,96.49522462852485],[508860.4607705393,6651185.76400398,99.0440608785247],[508859.62142734893,6651188.803163578,96.83496965552462],[508860.36425859306,6651186.113461998,98.94496538452458],[508860.2682226441,6651186.461196488,98.81734262552462],[508859.68300388084,6651188.5802024435,97.1606367655231],[508860.1735321096,6651186.804059395,98.66085133352439],[508859.75143281405,6651188.332429601,97.46900557352427],[508860.0810874778,6651187.138790161,98.4756424315248],[508859.82616744086,6651188.061824608,97.75710392452501],[508859.99179561756,6651187.462105127,98.26239009652473],[508859.9065428696,6651187.770794958,98.02230164952542]],"pointIndex":[54,60,84,77,0,60,78,117,84,0,78,85,126,117,0,85,90,133,126,0,90,96,137,133,0,96,100,140,137,0,100,105,143,140,0,105,115,152,143,0,115,118,154,152,0,118,122,156,154,0,122,124,158,156,0,124,127,160,158,0,127,129,162,160,0,129,132,164,162,0,132,131,163,164,0,131,128,161,163,0,128,125,159,161,0,125,123,157,159,0,123,121,155,157,0,121,116,153,155,0,116,108,146,153,0,108,72,103,146,0,72,70,97,103,0,70,66,92,97,0,66,62,88,92,0,62,58,83,88,0,58,53,76,83,0,53,49,71,76,0,49,45,68,71,0,45,41,63,68,0,41,38,59,63,0,38,33,51,59,0,33,29,47,51,0,29,25,43,47,0,25,22,40,43,0,22,18,36,40,0,18,15,32,36,0,15,13,28,32,0,13,11,24,28,0,11,7,20,24,0,7,4,16,20,0,4,1,5,16,0,1,2,8,5,0,2,3,10,8,0,3,6,19,10,0,6,9,23,19,0,9,12,27,23,0,12,14,30,27,0,14,17,35,30,0,17,21,39,35,0,21,26,44,39,0,26,31,48,44,0,31,34,52,48,0,34,37,57,52,0,37,42,64,57,0,42,46,69,64,0,46,50,74,69,0,50,55,79,74,0,55,61,86,79,0,61,65,89,86,0,65,67,93,89,0,67,81,119,93,0,81,95,136,119,0,95,99,139,136,0,99,101,141,139,0,101,107,145,141,0,107,110,148,145,0,110,113,150,148,0,113,114,151,150,0,114,112,149,151,0,112,109,147,149,0,109,106,144,147,0,106,102,142,144,0,102,98,138,142,0,98,94,135,138,0,94,91,134,135,0,91,87,130,134,0,87,82,120,130,0,82,75,111,120,0,75,73,104,111,0,73,56,80,104,0,56,54,77,80,0,77,84,200,196,0,84,117,210,200,0,117,126,213,210,0,126,133,215,213,0,133,137,219,215,0,137,140,222,219,0,140,143,227,222,0,143,152,234,227,0,152,154,237,234,0,154,156,239,237,0,156,158,241,239,0,158,160,243,241,0,160,162,246,243,0,162,164,248,246,0,164,163,247,248,0,163,161,245,247,0,161,159,242,245,0,159,157,240,242,0,157,155,238,240,0,155,153,235,238,0,153,146,228,235,0,146,103,207,228,0,103,97,206,207,0,97,92,204,206,0,92,88,202,204,0,88,83,199,202,0,83,76,195,199,0,76,71,193,195,0,71,68,191,193,0,68,63,189,191,0,63,59,188,189,0,59,51,185,188,0,51,47,183,185,0,47,43,181,183,0,43,40,180,181,0,40,36,178,180,0,36,32,176,178,0,32,28,174,176,0,28,24,172,174,0,24,20,170,172,0,20,16,168,170,0,16,5,165,168,0,5,8,166,165,0,8,10,167,166,0,10,19,169,167,0,19,23,171,169,0,23,27,173,171,0,27,30,175,173,0,30,35,177,175,0,35,39,179,177,0,39,44,182,179,0,44,48,184,182,0,48,52,186,184,0,52,57,187,186,0,57,64,190,187,0,64,69,192,190,0,69,74,194,192,0,74,79,197,194,0,79,86,201,197,0,86,89,203,201,0,89,93,205,203,0,93,119,211,205,0,119,136,218,211,0,136,139,220,218,0,139,141,223,220,0,141,145,226,223,0,145,148,230,226,0,148,150,232,230,0,150,151,233,232,0,151,149,231,233,0,149,147,229,231,0,147,144,225,229,0,144,142,224,225,0,142,138,221,224,0,138,135,217,221,0,135,134,216,217,0,134,130,214,216,0,130,120,212,214,0,120,111,209,212,0,111,104,208,209,0,104,80,198,208,0,80,77,196,198,0,196,200,283,279,0,200,210,292,283,0,210,213,295,292,0,213,215,297,295,0,215,219,301,297,0,219,222,304,301,0,222,227,310,304,0,227,234,316,310,0,234,237,318,316,0,237,239,320,318,0,239,241,322,320,0,241,243,324,322,0,243,246,326,324,0,246,248,328,326,0,248,247,327,328,0,247,245,325,327,0,245,242,323,325,0,242,240,321,323,0,240,238,319,321,0,238,235,317,319,0,235,228,308,317,0,228,207,289,308,0,207,206,288,289,0,206,204,286,288,0,204,202,284,286,0,202,199,281,284,0,199,195,277,281,0,195,193,275,277,0,193,191,273,275,0,191,189,271,273,0,189,188,270,271,0,188,185,267,270,0,185,183,265,267,0,183,181,263,265,0,181,180,262,263,0,180,178,260,262,0,178,176,258,260,0,176,174,256,258,0,174,172,254,256,0,172,170,252,254,0,170,168,250,252,0,168,165,236,250,0,165,166,244,236,0,166,167,249,244,0,167,169,251,249,0,169,171,253,251,0,171,173,255,253,0,173,175,257,255,0,175,177,259,257,0,177,179,261,259,0,179,182,264,261,0,182,184,266,264,0,184,186,268,266,0,186,187,269,268,0,187,190,272,269,0,190,192,274,272,0,192,194,276,274,0,194,197,278,276,0,197,201,282,278,0,201,203,285,282,0,203,205,287,285,0,205,211,293,287,0,211,218,299,293,0,218,220,302,299,0,220,223,305,302,0,223,226,307,305,0,226,230,312,307,0,230,232,314,312,0,232,233,315,314,0,233,231,313,315,0,231,229,311,313,0,229,225,309,311,0,225,224,306,309,0,224,221,303,306,0,221,217,300,303,0,217,216,298,300,0,216,214,296,298,0,214,212,294,296,0,212,209,291,294,0,209,208,290,291,0,208,198,280,290,0,198,196,279,280,0,279,283,364,366,361,0,364,368,366,0,364,283,292,378,0,364,378,381,368,0,378,292,295,387,0,378,387,388,381,0,387,295,297,391,0,387,391,392,388,0,391,297,301,398,396,0,391,396,392,0,301,304,403,398,0,304,310,410,403,0,310,316,419,410,0,316,318,422,419,0,318,320,426,422,0,320,322,429,426,0,322,324,432,429,0,324,326,434,432,0,326,328,436,434,0,328,327,435,436,0,327,325,433,435,0,325,323,430,433,0,323,321,427,430,0,321,319,423,427,0,319,317,418,423,0,317,308,407,418,0,308,289,375,407,0,289,288,374,375,0,288,286,372,374,0,286,284,369,372,0,284,281,362,369,0,281,277,359,362,0,277,275,357,359,0,275,273,355,357,0,273,271,353,355,0,271,270,352,353,0,270,267,349,352,0,267,265,347,349,0,265,263,345,347,0,263,262,344,345,0,262,260,342,344,0,260,258,340,342,0,258,256,338,340,0,256,254,336,338,0,254,252,334,336,0,252,250,332,334,0,250,236,329,332,0,236,244,330,329,0,244,249,331,330,0,249,251,333,331,0,251,253,335,333,0,253,255,337,335,0,255,257,339,337,0,257,259,341,339,0,259,261,343,341,0,261,264,346,343,0,264,266,348,346,0,266,268,350,348,0,268,269,351,350,0,269,272,354,351,0,272,274,356,354,0,274,276,358,356,0,276,278,360,358,0,278,282,365,360,0,282,285,371,365,0,285,287,373,371,0,287,293,379,373,0,293,299,395,379,0,299,302,400,395,0,302,305,404,400,0,305,307,408,404,0,307,312,412,408,0,312,314,415,412,0,314,315,416,415,0,315,313,414,416,0,313,311,411,414,0,311,309,409,411,0,309,306,405,409,0,306,303,401,405,0,303,300,397,401,0,300,298,393,397,0,298,296,389,393,0,296,294,383,389,0,294,291,377,383,0,291,290,376,377,0,290,280,363,376,0,280,279,361,363,0,367,361,366,0,367,366,368,533,529,0,368,381,543,533,0,381,388,547,543,0,388,392,550,547,0,396,398,399,0,392,396,399,553,550,0,399,398,403,406,0,399,406,556,553,0,406,403,410,420,0,406,420,563,556,0,420,410,419,428,0,420,428,571,563,0,428,419,422,439,0,428,439,573,571,0,439,422,426,442,0,439,442,575,573,0,442,426,429,446,0,442,446,579,575,0,446,429,432,451,0,446,451,582,579,0,451,432,434,455,0,451,455,584,582,0,455,434,436,459,0,455,459,585,584,0,459,436,435,462,0,459,462,583,585,0,462,435,433,467,0,462,467,581,583,0,467,433,430,471,0,467,471,578,581,0,471,430,427,475,0,471,475,576,578,0,475,427,423,478,0,475,478,574,576,0,478,423,418,481,0,478,481,569,574,0,481,418,407,487,0,481,487,560,569,0,487,407,375,496,0,487,496,538,560,0,496,375,374,498,0,496,498,537,538,0,498,374,372,497,0,498,497,535,537,0,497,372,369,495,0,497,495,532,535,0,495,369,362,493,0,495,493,528,532,0,493,362,359,491,0,493,491,526,528,0,491,359,357,490,0,491,490,524,526,0,490,357,355,489,0,490,489,522,524,0,489,355,353,482,0,489,482,520,522,0,482,353,352,479,0,482,479,519,520,0,479,352,349,473,0,479,473,516,519,0,473,349,347,468,0,473,468,514,516,0,468,347,345,463,0,468,463,512,514,0,463,345,344,458,0,463,458,511,512,0,458,344,342,454,0,458,454,509,511,0,454,342,340,450,0,454,450,507,509,0,450,340,338,445,0,450,445,505,507,0,445,338,336,440,0,445,440,503,505,0,440,336,334,431,0,440,431,501,503,0,431,334,332,421,0,431,421,499,501,0,421,332,329,385,0,421,385,485,499,0,385,329,330,384,0,385,384,492,485,0,384,330,331,386,0,384,386,494,492,0,386,331,333,417,0,386,417,500,494,0,417,333,335,425,0,417,425,502,500,0,425,335,337,438,0,425,438,504,502,0,438,337,339,443,0,438,443,506,504,0,443,339,341,447,0,443,447,508,506,0,447,341,343,453,0,447,453,510,508,0,453,343,346,457,0,453,457,513,510,0,457,346,348,461,0,457,461,515,513,0,461,348,350,465,0,461,465,517,515,0,465,350,351,469,0,465,469,518,517,0,469,351,354,474,0,469,474,521,518,0,474,354,356,477,0,474,477,523,521,0,477,356,358,480,0,477,480,525,523,0,480,358,360,483,0,480,483,527,525,0,483,360,365,486,0,483,486,531,527,0,486,365,371,488,0,486,488,534,531,0,488,371,373,484,0,488,484,536,534,0,484,373,379,476,0,484,476,542,536,0,476,379,395,472,0,476,472,551,542,0,472,395,400,470,0,472,470,554,551,0,470,400,404,466,0,470,466,557,554,0,466,404,408,464,0,466,464,561,557,0,464,408,412,460,0,464,460,564,561,0,460,412,415,456,0,460,456,567,564,0,456,415,416,452,0,456,452,568,567,0,452,416,414,448,449,0,452,449,448,566,568,0,448,414,411,444,0,448,444,565,566,0,444,411,409,441,0,444,441,562,565,0,441,409,405,437,0,441,437,559,562,0,437,405,401,424,0,437,424,555,559,0,424,401,397,413,0,424,413,552,555,0,413,397,393,402,0,413,402,549,552,0,402,393,389,394,0,402,394,548,549,0,394,389,383,390,0,394,390,544,548,0,390,383,377,382,0,390,382,541,544,0,382,377,376,380,0,382,380,539,541,0,380,376,363,370,0,380,370,530,539,0,370,363,361,367,0,370,367,529,530,0,529,533,619,614,0,533,543,636,619,0,543,547,640,636,0,547,550,645,640,0,550,553,648,645,0,553,556,654,648,0,556,563,660,654,0,563,571,668,660,0,571,573,670,668,0,573,575,674,670,0,575,579,676,674,0,579,582,678,676,0,582,584,680,678,0,584,585,681,680,0,585,583,679,681,0,583,581,677,679,0,581,578,675,677,0,578,576,673,675,0,576,574,669,673,0,574,569,667,669,0,569,560,656,667,0,560,538,629,656,0,538,537,626,629,0,537,535,623,626,0,535,532,618,623,0,532,528,613,618,0,528,526,611,613,0,526,524,609,611,0,524,522,605,609,0,522,520,602,605,0,520,519,601,602,0,519,516,598,601,0,516,514,596,598,0,514,512,594,596,0,512,511,593,594,0,511,509,591,593,0,509,507,589,591,0,507,505,587,589,0,505,503,580,587,0,503,501,572,580,0,501,499,558,572,0,499,485,540,558,0,485,492,545,540,0,492,494,546,545,0,494,500,570,546,0,500,502,577,570,0,502,504,586,577,0,504,506,588,586,0,506,508,590,588,0,508,510,592,590,0,510,513,595,592,0,513,515,597,595,0,515,517,599,597,0,517,518,600,599,0,518,521,603,600,0,521,523,607,603,0,523,525,610,607,0,525,527,612,610,0,527,531,617,612,0,531,534,621,617,0,534,536,624,621,0,536,542,634,624,0,542,551,646,634,0,551,554,650,646,0,554,557,653,650,0,557,561,657,653,0,561,564,661,657,0,564,567,665,661,0,567,568,666,665,0,568,566,664,666,0,566,565,662,664,0,565,562,658,662,0,562,559,655,658,0,559,555,652,655,0,555,552,647,652,0,552,549,644,647,0,549,548,641,644,0,548,544,637,641,0,544,541,633,637,0,541,539,631,633,0,539,530,616,631,0,530,529,614,616,0,693,614,619,697,0,693,697,786,780,0,697,619,636,706,0,697,706,803,786,0,706,636,640,708,0,706,708,806,803,0,708,640,645,711,0,708,711,810,806,0,711,645,648,714,0,711,714,816,810,0,714,648,654,718,0,714,718,821,816,0,718,654,660,723,0,718,723,826,821,0,723,660,668,730,0,723,730,835,826,0,730,668,670,734,0,730,734,838,835,0,734,670,674,736,0,734,736,840,838,0,736,674,676,739,0,736,739,844,840,0,739,676,678,741,0,739,741,846,844,0,741,678,680,744,0,741,744,848,846,0,744,680,681,745,0,744,745,849,848,0,745,681,679,743,0,745,743,847,849,0,743,679,677,740,0,743,740,845,847,0,740,677,675,738,0,740,738,843,845,0,738,675,673,735,0,738,735,839,843,0,735,673,669,733,0,735,733,837,839,0,733,669,667,729,732,0,733,732,729,833,837,0,729,667,656,720,0,729,720,823,833,0,720,656,629,702,0,720,702,795,823,0,702,629,626,701,0,702,701,792,795,0,701,626,623,699,0,701,699,788,792,0,699,623,618,696,0,699,696,784,788,0,696,618,613,692,0,696,692,779,784,0,692,613,611,690,0,692,690,776,779,0,690,611,609,688,0,690,688,774,776,0,688,609,605,686,0,688,686,772,774,0,686,605,602,684,0,686,684,768,772,0,684,602,601,683,0,684,683,766,768,0,683,601,598,671,0,683,671,763,766,0,671,598,596,659,0,671,659,761,763,0,659,596,594,649,0,659,649,759,761,0,649,594,593,643,0,649,643,758,759,0,643,593,591,639,0,643,639,756,758,0,639,591,589,635,0,639,635,754,756,0,635,589,587,630,0,635,630,752,754,0,630,587,580,627,0,630,627,750,752,0,627,580,572,622,0,627,622,748,750,0,622,572,558,615,0,622,615,746,748,0,615,558,540,604,0,615,604,731,746,0,604,540,545,606,0,604,606,737,731,0,606,545,546,608,0,606,608,742,737,0,608,546,570,620,0,608,620,747,742,0,620,570,577,625,0,620,625,749,747,0,625,577,586,628,0,625,628,751,749,0,628,586,588,632,0,628,632,753,751,0,632,588,590,638,0,632,638,755,753,0,638,590,592,642,0,638,642,757,755,0,642,592,595,651,0,642,651,760,757,0,651,595,597,663,0,651,663,762,760,0,663,597,599,672,0,663,672,764,762,0,672,599,600,682,0,672,682,765,764,0,682,600,603,685,0,682,685,769,765,0,685,603,607,687,0,685,687,773,769,0,687,607,610,689,0,687,689,775,773,0,689,610,612,691,0,689,691,777,775,0,691,612,617,695,0,691,695,781,777,0,695,617,621,698,0,695,698,787,781,0,698,621,624,700,0,698,700,791,787,0,700,624,634,705,0,700,705,800,791,0,705,634,646,712,0,705,712,813,800,0,712,646,650,715,0,712,715,815,813,0,715,650,653,717,0,715,717,819,815,0,717,653,657,721,0,717,721,824,819,0,721,657,661,724,0,721,724,827,824,0,724,661,665,727,0,724,727,829,827,0,727,665,666,728,0,727,728,831,829,0,728,666,664,726,0,728,726,830,831,0,726,664,662,725,0,726,725,828,830,0,725,662,658,722,0,725,722,825,828,0,722,658,655,719,0,722,719,822,825,0,719,655,652,716,0,719,716,817,822,0,716,652,647,713,0,716,713,814,817,0,713,647,644,710,0,713,710,809,814,0,710,644,641,709,0,710,709,808,809,0,709,641,637,707,0,709,707,804,808,0,707,637,633,704,0,707,704,799,804,0,704,633,631,703,0,704,703,798,799,0,703,631,616,694,0,703,694,782,798,0,694,616,614,693,0,694,693,780,782,0,780,786,869,863,0,786,803,884,869,0,803,806,887,884,0,806,810,891,887,0,810,816,897,891,0,816,821,900,897,0,821,826,907,900,0,826,835,914,907,0,835,838,916,914,0,838,840,918,916,0,840,844,920,918,0,844,846,923,920,0,846,848,926,923,0,848,849,927,926,0,849,847,925,927,0,847,845,922,925,0,845,843,919,922,0,843,839,917,919,0,839,837,915,917,0,837,833,913,915,0,833,823,901,913,0,823,795,877,901,0,795,792,875,877,0,792,788,871,875,0,788,784,867,871,0,784,779,862,867,0,779,776,859,862,0,776,774,856,859,0,774,772,854,856,0,772,768,850,854,0,768,766,841,850,0,766,763,832,841,0,763,761,818,832,0,761,759,811,818,0,759,758,807,811,0,758,756,802,807,0,756,754,797,802,0,754,752,794,797,0,752,750,790,794,0,750,748,785,790,0,748,746,778,785,0,746,731,767,778,0,731,737,770,767,0,737,742,771,770,0,742,747,783,771,0,747,749,789,783,0,749,751,793,789,0,751,753,796,793,0,753,755,801,796,0,755,757,805,801,0,757,760,812,805,0,760,762,820,812,0,762,764,834,820,0,764,765,842,834,0,765,769,851,842,0,769,773,855,851,0,773,775,858,855,0,775,777,860,858,0,777,781,864,860,0,781,787,870,864,0,787,791,873,870,0,791,800,882,873,0,800,813,893,882,0,813,815,896,893,0,815,819,899,896,0,819,824,903,899,0,824,827,906,903,0,827,829,910,906,0,829,831,912,910,0,831,830,911,912,0,830,828,908,911,0,828,825,905,908,0,825,822,902,905,0,822,817,898,902,0,817,814,895,898,0,814,809,890,895,0,809,808,889,890,0,808,804,886,889,0,804,799,881,886,0,799,798,880,881,0,798,782,865,880,0,782,780,863,865,0,964,974,1049,1043,0,964,863,869,974,0,974,1001,1064,1049,0,974,869,884,1001,0,1001,1012,1068,1064,0,1001,884,887,1012,0,1012,1018,1073,1068,0,1012,887,891,1018,0,1018,1022,1081,1073,0,1018,891,897,1022,0,1022,1025,1087,1081,0,1022,897,900,1025,0,1025,1028,1094,1087,0,1025,900,907,1028,0,1028,1032,1101,1094,0,1028,907,914,1032,0,1032,1030,1103,1101,0,1032,914,916,1030,0,1030,1027,1106,1103,0,1030,916,918,1027,0,1027,1024,1108,1106,0,1027,918,920,1024,0,1024,1021,1110,1108,0,1024,920,923,1021,0,1021,1017,1112,1110,0,1021,923,926,1017,0,1017,1014,1113,1112,0,1017,926,927,1014,0,1014,1005,1111,1113,0,1014,927,925,1005,0,1005,996,1109,1111,0,1005,925,922,996,0,996,989,1107,1109,0,996,922,919,989,0,989,981,1105,1107,0,989,919,917,981,0,981,976,1102,1105,0,981,917,915,976,0,976,970,1099,1102,0,976,915,913,970,0,970,960,1088,1099,0,970,913,901,960,0,960,946,1057,1088,0,960,901,877,946,0,946,944,1054,1057,0,946,877,875,944,0,944,942,1050,1054,0,944,875,871,942,0,942,940,1044,1050,0,942,871,867,940,0,940,938,1040,1044,0,940,867,862,938,0,938,936,1037,1040,0,938,862,859,936,0,936,935,1033,1037,0,936,859,856,935,0,935,933,1023,1033,0,935,856,854,933,0,933,931,1015,1023,0,933,854,850,931,0,931,929,1006,1015,0,931,850,841,929,0,929,924,994,1006,0,929,841,832,924,0,924,909,986,994,0,924,832,818,909,0,909,894,979,986,0,909,818,811,894,0,894,888,975,979,0,894,811,807,888,0,888,883,971,975,0,888,807,802,883,0,883,878,966,971,0,883,802,797,878,0,878,874,959,966,0,878,797,794,874,0,874,868,956,959,0,874,794,790,868,0,868,861,953,956,0,868,790,785,861,0,861,857,951,953,0,861,785,778,857,0,857,836,948,951,0,857,778,767,836,0,836,852,949,948,0,836,767,770,852,0,852,853,950,949,0,852,770,771,853,0,853,866,952,950,0,853,771,783,866,0,866,872,954,952,0,866,783,789,872,0,872,876,957,954,0,872,789,793,876,0,876,879,962,957,0,876,793,796,879,0,879,885,969,962,0,879,796,801,885,0,885,892,973,969,0,885,801,805,892,0,892,904,980,973,0,892,805,812,904,0,904,921,988,980,0,904,812,820,921,0,921,928,995,988,0,921,820,834,928,0,928,930,1007,995,0,928,834,842,930,0,930,932,1016,1007,0,930,842,851,932,0,932,934,1026,1016,0,932,851,855,934,0,934,937,1034,1026,0,934,855,858,937,0,937,939,1038,1034,0,937,858,860,939,0,939,941,1042,1038,0,939,860,864,941,0,941,943,1048,1042,0,941,864,870,943,0,943,945,1053,1048,0,943,870,873,945,0,945,947,1061,1053,0,945,873,882,947,0,947,955,1075,1061,0,947,882,893,955,0,955,961,1080,1075,0,955,893,896,961,0,961,968,1085,1080,0,961,896,899,968,0,968,972,1090,1085,0,968,899,903,972,0,972,978,1093,1090,0,972,903,906,978,0,978,985,1096,1093,0,978,906,910,985,0,985,992,1100,1096,0,985,910,912,992,0,992,997,1098,1100,0,992,912,911,997,0,997,1000,1095,1098,0,997,911,908,1000,0,1000,1004,1092,1095,0,1000,908,905,1004,0,1004,1009,1089,1092,0,1004,905,902,1009,0,1009,1010,1083,1089,0,1009,902,898,1010,0,1010,1008,1079,1083,0,1010,898,895,1008,0,1008,1003,1072,1079,0,1008,895,890,1003,0,1003,999,1070,1072,0,1003,890,889,999,0,999,993,1066,1070,0,999,889,886,993,0,993,987,1062,1066,0,993,886,881,987,0,987,984,1060,1062,0,987,881,880,984,0,984,967,1045,1060,0,984,880,865,967,0,967,964,1043,1045,0,967,865,863,964,0,1043,1049,1086,1076,0,1049,1064,1117,1086,0,1064,1068,1119,1117,0,1068,1073,1122,1119,0,1073,1081,1126,1122,0,1081,1087,1129,1126,0,1087,1094,1135,1129,0,1094,1101,1141,1135,0,1101,1103,1143,1141,0,1103,1106,1145,1143,0,1106,1108,1147,1145,0,1108,1110,1149,1147,0,1110,1112,1151,1149,0,1112,1113,1152,1151,0,1113,1111,1150,1152,0,1111,1109,1148,1150,0,1109,1107,1146,1148,0,1107,1105,1144,1146,0,1105,1102,1142,1144,0,1102,1099,1139,1142,0,1099,1088,1130,1139,0,1088,1057,1104,1130,0,1057,1054,1097,1104,0,1054,1050,1084,1097,0,1050,1044,1077,1084,0,1044,1040,1071,1077,0,1040,1037,1067,1071,0,1037,1033,1063,1067,0,1033,1023,1058,1063,0,1023,1015,1055,1058,0,1015,1006,1051,1055,0,1006,994,1046,1051,0,994,986,1039,1046,0,986,979,1035,1039,0,979,975,1031,1035,0,975,971,1020,1031,0,971,966,1013,1020,0,966,959,1002,1013,0,959,956,991,1002,0,956,953,983,991,0,953,951,977,983,0,951,948,958,977,0,948,949,963,958,0,949,950,965,963,0,950,952,982,965,0,952,954,990,982,0,954,957,998,990,0,957,962,1011,998,0,962,969,1019,1011,0,969,973,1029,1019,0,973,980,1036,1029,0,980,988,1041,1036,0,988,995,1047,1041,0,995,1007,1052,1047,0,1007,1016,1056,1052,0,1016,1026,1059,1056,0,1026,1034,1065,1059,0,1034,1038,1069,1065,0,1038,1042,1074,1069,0,1042,1048,1082,1074,0,1048,1053,1091,1082,0,1053,1061,1115,1091,0,1061,1075,1123,1115,0,1075,1080,1125,1123,0,1080,1085,1128,1125,0,1085,1090,1132,1128,0,1090,1093,1134,1132,0,1093,1096,1137,1134,0,1096,1100,1140,1137,0,1100,1098,1138,1140,0,1098,1095,1136,1138,0,1095,1092,1133,1136,0,1092,1089,1131,1133,0,1089,1083,1127,1131,0,1083,1079,1124,1127,0,1079,1072,1121,1124,0,1072,1070,1120,1121,0,1070,1066,1118,1120,0,1066,1062,1116,1118,0,1062,1060,1114,1116,0,1060,1045,1078,1114,0,1045,1043,1076,1078,0,1076,1086,1226,1220,0,1086,1117,1242,1226,0,1117,1119,1247,1242,0,1119,1122,1253,1247,0,1122,1126,1258,1253,0,1126,1129,1265,1258,0,1129,1135,1274,1265,0,1135,1141,1281,1274,0,1141,1143,1287,1281,0,1143,1145,1293,1287,0,1145,1147,1299,1293,0,1147,1149,1301,1299,0,1149,1151,1304,1301,0,1151,1152,1305,1304,0,1152,1150,1302,1305,0,1150,1148,1300,1302,0,1148,1146,1296,1300,0,1146,1144,1288,1296,0,1144,1142,1283,1288,0,1142,1139,1273,1283,0,1139,1130,1264,1273,0,1130,1104,1236,1264,0,1104,1097,1231,1236,0,1097,1084,1224,1231,0,1084,1077,1219,1224,0,1077,1071,1215,1219,0,1071,1067,1211,1215,0,1067,1063,1207,1211,0,1063,1058,1203,1207,0,1058,1055,1199,1203,0,1055,1051,1195,1199,0,1051,1046,1191,1195,0,1046,1039,1187,1191,0,1039,1035,1183,1187,0,1035,1031,1181,1183,0,1031,1020,1177,1181,0,1020,1013,1173,1177,0,1013,1002,1170,1173,0,1002,991,1164,1170,0,991,983,1161,1164,0,983,977,1159,1161,0,977,958,1153,1159,0,958,963,1154,1153,0,963,965,1156,1154,0,965,982,1160,1156,0,982,990,1163,1160,0,990,998,1167,1163,0,998,1011,1171,1167,0,1011,1019,1175,1171,0,1019,1029,1179,1175,0,1029,1036,1185,1179,0,1036,1041,1190,1185,0,1041,1047,1193,1190,0,1047,1052,1196,1193,0,1052,1056,1202,1196,0,1056,1059,1205,1202,0,1059,1065,1209,1205,0,1065,1069,1213,1209,0,1069,1074,1217,1213,0,1074,1082,1223,1217,0,1082,1091,1228,1223,0,1091,1115,1240,1228,0,1115,1123,1252,1240,0,1123,1125,1256,1252,0,1125,1128,1259,1256,0,1128,1132,1266,1259,0,1132,1134,1271,1266,0,1134,1137,1275,1271,0,1137,1140,1278,1275,0,1140,1138,1276,1278,0,1138,1136,1272,1276,0,1136,1133,1270,1272,0,1133,1131,1267,1270,0,1131,1127,1260,1267,0,1127,1124,1257,1260,0,1124,1121,1251,1257,0,1121,1120,1248,1251,0,1120,1118,1244,1248,0,1118,1116,1241,1244,0,1116,1114,1239,1241,0,1114,1078,1222,1239,0,1078,1076,1220,1222,0,1220,1226,1234,1229,0,1226,1242,1249,1234,0,1242,1247,1254,1249,0,1247,1253,1263,1254,0,1253,1258,1277,1263,0,1258,1265,1284,1277,0,1265,1274,1294,1284,0,1274,1281,1303,1294,0,1281,1287,1307,1303,0,1287,1293,1309,1307,0,1293,1299,1311,1309,0,1299,1301,1313,1311,0,1301,1304,1315,1313,0,1304,1305,1316,1315,0,1305,1302,1314,1316,0,1302,1300,1312,1314,0,1300,1296,1310,1312,0,1296,1288,1308,1310,0,1288,1283,1306,1308,0,1283,1273,1292,1306,0,1273,1264,1282,1292,0,1264,1236,1238,1282,0,1236,1231,1237,1238,0,1231,1224,1233,1237,0,1224,1219,1227,1233,0,1219,1215,1221,1227,0,1215,1211,1216,1221,0,1211,1207,1212,1216,0,1207,1203,1208,1212,0,1203,1199,1204,1208,0,1199,1195,1200,1204,0,1195,1191,1197,1200,0,1191,1187,1192,1197,0,1187,1183,1188,1192,0,1183,1181,1186,1188,0,1181,1177,1182,1186,0,1177,1173,1178,1182,0,1173,1170,1174,1178,0,1170,1164,1169,1174,0,1164,1161,1166,1169,0,1161,1159,1162,1166,0,1159,1153,1155,1162,0,1153,1154,1157,1155,0,1154,1156,1158,1157,0,1156,1160,1165,1158,0,1160,1163,1168,1165,0,1163,1167,1172,1168,0,1167,1171,1176,1172,0,1171,1175,1180,1176,0,1175,1179,1184,1180,0,1179,1185,1189,1184,0,1185,1190,1194,1189,0,1190,1193,1198,1194,0,1193,1196,1201,1198,0,1196,1202,1206,1201,0,1202,1205,1210,1206,0,1205,1209,1214,1210,0,1209,1213,1218,1214,0,1213,1217,1225,1218,0,1217,1223,1232,1225,0,1223,1228,1235,1232,0,1228,1240,1245,1235,0,1240,1252,1262,1245,0,1252,1256,1268,1262,0,1256,1259,1279,1268,0,1259,1266,1285,1279,0,1266,1271,1290,1285,0,1271,1275,1295,1290,0,1275,1278,1298,1295,0,1278,1276,1297,1298,0,1276,1272,1291,1297,0,1272,1270,1289,1291,0,1270,1267,1286,1289,0,1267,1260,1280,1286,0,1260,1257,1269,1280,0,1257,1251,1261,1269,0,1251,1248,1255,1261,0,1248,1244,1250,1255,0,1244,1241,1246,1250,0,1241,1239,1243,1246,0,1239,1222,1230,1243,0,1222,1220,1229,1230,0,1352,1229,1234,1356,0,1356,1234,1249,1363,0,1363,1249,1254,1365,0,1365,1254,1263,1369,0,1369,1263,1277,1372,0,1372,1277,1284,1377,0,1377,1284,1294,1384,0,1384,1294,1303,1387,0,1387,1303,1307,1389,0,1389,1307,1309,1392,0,1392,1309,1311,1394,0,1394,1311,1313,1396,0,1396,1313,1315,1398,0,1398,1315,1316,1397,0,1397,1316,1314,1395,0,1395,1314,1312,1393,0,1393,1312,1310,1391,0,1391,1310,1308,1390,0,1390,1308,1306,1388,0,1388,1306,1292,1381,0,1381,1292,1282,1375,0,1375,1282,1238,1359,0,1359,1238,1237,1358,0,1358,1237,1233,1355,0,1355,1233,1227,1351,0,1351,1227,1221,1349,0,1349,1221,1216,1347,0,1347,1216,1212,1345,0,1345,1212,1208,1343,0,1343,1208,1204,1341,0,1341,1204,1200,1339,0,1339,1200,1197,1337,0,1337,1197,1192,1335,0,1335,1192,1188,1333,0,1333,1188,1186,1332,0,1332,1186,1182,1330,0,1330,1182,1178,1328,0,1328,1178,1174,1326,0,1326,1174,1169,1324,0,1324,1169,1166,1322,0,1322,1166,1162,1320,0,1320,1162,1155,1317,0,1317,1155,1157,1318,0,1318,1157,1158,1319,0,1319,1158,1165,1321,0,1321,1165,1168,1323,0,1323,1168,1172,1325,0,1325,1172,1176,1327,0,1327,1176,1180,1329,0,1329,1180,1184,1331,0,1331,1184,1189,1334,0,1334,1189,1194,1336,0,1336,1194,1198,1338,0,1338,1198,1201,1340,0,1340,1201,1206,1342,0,1342,1206,1210,1344,0,1344,1210,1214,1346,0,1346,1214,1218,1348,0,1348,1218,1225,1350,0,1350,1225,1232,1354,0,1354,1232,1235,1357,0,1357,1235,1245,1360,0,1360,1245,1262,1367,0,1367,1262,1268,1370,0,1370,1268,1279,1373,0,1373,1279,1285,1376,0,1376,1285,1290,1379,0,1379,1290,1295,1383,0,1383,1295,1298,1386,0,1386,1298,1297,1385,0,1385,1297,1291,1382,0,1382,1291,1289,1380,0,1380,1289,1286,1378,0,1378,1286,1280,1374,0,1374,1280,1269,1371,0,1371,1269,1261,1368,0,1368,1261,1255,1366,0,1366,1255,1250,1364,0,1364,1250,1246,1362,0,1362,1246,1243,1361,0,1361,1243,1230,1353,0,1353,1230,1229,1352,0,54,60,56,0,60,78,56,0,78,85,75,0,85,90,82,0,90,96,87,0,96,100,91,0,100,105,94,0,105,115,94,0,115,118,98,0,118,122,102,0,122,124,106,0,124,127,109,0,127,129,112,0,129,132,114,0,132,131,113,0,131,128,113,0,128,125,110,0,125,123,107,0,123,121,101,0,121,116,99,0,116,108,95,0,108,72,81,0,72,70,67,0,70,66,65,0,66,62,61,0,62,58,55,0,58,53,50,0,53,49,46,0,49,45,46,0,45,41,42,0,41,38,37,0,38,33,34,0,33,29,31,0,29,25,26,0,25,22,26,0,22,18,21,0,18,15,17,0,15,13,14,0,13,11,14,0,11,7,12,0,7,4,9,0,4,1,3,0,1,2,3,0,3,6,4,0,6,9,4,0,9,12,7,0,12,14,11,0,14,17,15,0,17,21,18,0,21,26,22,0,26,31,29,0,31,34,33,0,34,37,38,0,37,42,41,0,42,46,45,0,46,50,53,0,50,55,58,0,55,61,62,0,61,65,66,0,65,67,70,0,67,81,72,0,81,95,108,0,95,99,116,0,99,101,121,0,101,107,123,0,107,110,125,0,110,113,128,0,113,114,132,0,114,112,129,0,112,109,127,0,109,106,124,0,106,102,122,0,102,98,118,0,98,94,115,0,94,91,100,0,91,87,96,0,87,82,90,0,82,75,85,0,75,73,78,0,73,56,78,0,697,693,694,0,694,703,706,0,703,704,706,0,704,707,708,0,707,709,711,0,709,710,714,0,710,713,718,0,713,716,730,0,716,719,734,0,719,722,736,0,722,725,739,0,725,726,741,0,726,728,744,0,728,727,745,0,727,724,740,0,724,721,738,0,721,717,735,0,717,715,733,0,715,712,729,0,712,705,720,0,705,700,702,0,700,698,701,0,698,695,699,0,695,691,696,0,691,689,692,0,689,687,690,0,687,685,686,0,685,682,684,0,682,672,683,0,672,663,671,0,663,651,659,0,651,642,643,0,642,638,639,0,638,632,635,0,632,628,627,0,628,625,622,0,625,620,615,0,620,608,615,0,608,606,604,0,604,615,608,0,615,622,625,0,622,627,628,0,627,630,632,0,630,635,632,0,635,639,638,0,639,643,642,0,643,649,651,0,649,659,651,0,659,671,663,0,671,683,672,0,683,684,682,0,684,686,685,0,686,688,687,0,688,690,687,0,690,692,689,0,692,696,691,0,696,699,695,0,699,701,698,0,701,702,700,0,702,720,705,0,720,729,712,0,729,732,733,715,0,733,735,717,0,735,738,721,0,738,740,724,0,740,743,727,0,743,745,727,0,745,744,728,0,744,741,726,0,741,739,725,0,739,736,722,0,736,734,719,0,734,730,716,0,730,723,713,0,723,718,713,0,718,714,710,0,714,711,709,0,711,708,707,0,708,706,704,0,706,697,694,0,1356,1352,1353,0,1353,1361,1363,0,1361,1362,1363,0,1362,1364,1365,0,1364,1366,1369,0,1366,1368,1372,0,1368,1371,1377,0,1371,1374,1387,0,1374,1378,1389,0,1378,1380,1392,0,1380,1382,1394,0,1382,1385,1396,0,1385,1386,1398,0,1386,1383,1397,0,1383,1379,1393,0,1379,1376,1391,0,1376,1373,1390,0,1373,1370,1388,0,1370,1367,1381,0,1367,1360,1375,0,1360,1357,1359,0,1357,1354,1358,0,1354,1350,1355,0,1350,1348,1351,0,1348,1346,1349,0,1346,1344,1347,0,1344,1342,1343,0,1342,1340,1341,0,1340,1338,1339,0,1338,1336,1337,0,1336,1334,1335,0,1334,1331,1332,0,1331,1329,1330,0,1329,1327,1328,0,1327,1325,1324,0,1325,1323,1322,0,1323,1321,1320,0,1321,1319,1320,0,1319,1318,1317,0,1317,1320,1319,0,1320,1322,1323,0,1322,1324,1325,0,1324,1326,1327,0,1326,1328,1327,0,1328,1330,1329,0,1330,1332,1331,0,1332,1333,1334,0,1333,1335,1334,0,1335,1337,1336,0,1337,1339,1338,0,1339,1341,1340,0,1341,1343,1342,0,1343,1345,1344,0,1345,1347,1344,0,1347,1349,1346,0,1349,1351,1348,0,1351,1355,1350,0,1355,1358,1354,0,1358,1359,1357,0,1359,1375,1360,0,1375,1381,1367,0,1381,1388,1370,0,1388,1390,1373,0,1390,1391,1376,0,1391,1393,1379,0,1393,1395,1383,0,1395,1397,1383,0,1397,1398,1386,0,1398,1396,1385,0,1396,1394,1382,0,1394,1392,1380,0,1392,1389,1378,0,1389,1387,1374,0,1387,1384,1371,0,1384,1377,1371,0,1377,1372,1368,0,1372,1369,1366,0,1369,1365,1364,0,1365,1363,1362,0,1363,1356,1353,0,693,697,694,0,697,706,694,0,706,708,704,0,708,711,707,0,711,714,709,0,714,718,710,0,718,723,713,0,723,730,713,0,730,734,716,0,734,736,719,0,736,739,722,0,739,741,725,0,741,744,726,0,744,745,728,0,745,743,727,0,743,740,727,0,740,738,724,0,738,735,721,0,735,733,717,0,733,732,729,715,0,729,720,712,0,720,702,705,0,702,701,700,0,701,699,698,0,699,696,695,0,696,692,691,0,692,690,689,0,690,688,687,0,688,686,687,0,686,684,685,0,684,683,682,0,683,671,672,0,671,659,663,0,659,649,651,0,649,643,651,0,643,639,642,0,639,635,638,0,635,630,632,0,630,627,632,0,627,622,628,0,622,615,625,0,615,604,608,0,604,606,608,0,608,620,615,0,620,625,615,0,625,628,622,0,628,632,627,0,632,638,635,0,638,642,639,0,642,651,643,0,651,663,659,0,663,672,671,0,672,682,683,0,682,685,684,0,685,687,686,0,687,689,690,0,689,691,692,0,691,695,696,0,695,698,699,0,698,700,701,0,700,705,702,0,705,712,720,0,712,715,729,0,715,717,733,0,717,721,735,0,721,724,738,0,724,727,740,0,727,728,745,0,728,726,744,0,726,725,741,0,725,722,739,0,722,719,736,0,719,716,734,0,716,713,730,0,713,710,718,0,710,709,714,0,709,707,711,0,707,704,708,0,704,703,706,0,703,694,706,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [508756.28394181497, 6651143.909274647, 91.3199669126467], + [508756.088194514, 6651144.4865926355, 91.31996691264918], + [508756.088194514, 6651144.4865926355, 91.44996691264919], + [508756.28394181497, 6651143.909274647, 93.14877057164671], + [508757.5568140733, 6651144.341973173, 91.33631063381246], + [508756.088194514, 6651144.4865926355, 93.14877057164918], + [508756.2772113811, 6651143.929124732, 93.61436125864583], + [508757.3614660662, 6651144.919426898, 91.33631063381246], + [508756.0822558954, 6651144.504107417, 93.55958588364068], + [508757.3614660662, 6651144.919426898, 91.46631063381247], + [508756.25616441696, 6651143.991198594, 94.09163221063858], + [508756.06368504517, 6651144.55887847, 93.98070731164123], + [508756.21971539175, 6651144.098697793, 94.5745332306442], + [508756.0315241402, 6651144.653730705, 94.40679644664426], + [508756.1818078276, 6651144.210498664, 94.93623921564632], + [508757.5568140733, 6651144.341973173, 93.16511429281246], + [508755.9851163838, 6651144.790601213, 94.83170295064227], + [508756.13465000596, 6651144.34958134, 95.29399706164321], + [508757.3614660662, 6651144.919426898, 93.16511429281246], + [508757.55009736854, 6651144.361827926, 93.63070497981245], + [508755.92418373236, 6651144.9703100305, 95.24866965264734], + [508756.0782362944, 6651144.515962435, 95.64445327664261], + [508757.3555395622, 6651144.936945797, 93.57592960481244], + [508757.5290933375, 6651144.423916382, 94.10797593181246], + [508756.0127264599, 6651144.709170749, 95.98419830364112], + [508755.8488868478, 6651145.192383314, 95.65061856964533], + [508757.33700659353, 6651144.991729728, 93.99705103281245], + [508757.4927186622, 6651144.531440855, 94.59087695181246], + [508755.9384512209, 6651144.928230892, 96.30986541364487], + [508757.30491129163, 6651145.086604264, 94.42314016781245], + [508755.7598575632, 6651145.454957597, 96.03049937163823], + [508757.45488842344, 6651144.6432680115, 94.95258293681245], + [508755.85591043497, 6651145.171668631, 96.61823422164382], + [508755.6847191385, 6651145.676563536, 96.29690568664412], + [508757.2585982, 6651145.223506953, 94.84804667181247], + [508757.40782679664, 6651144.782383389, 95.31034078281245], + [508755.6030922834, 6651145.917305817, 96.54461542664565], + [508755.7657635549, 6651145.437539043, 96.90633257264452], + [508757.1977898413, 6651145.403258021, 95.26501337381245], + [508757.35152816033, 6651144.948803603, 95.66079699781247], + [508755.6688125905, 6651145.723476756, 97.17153029764322], + [508755.4854658217, 6651146.264221824, 96.84205789664404], + [508757.2861519559, 6651145.142057342, 96.00054202481246], + [508757.1226465509, 6651145.625383517, 95.66696229081245], + [508755.56597847457, 6651146.026765663, 97.41161874464638], + [508755.3596625666, 6651146.635253669, 97.09827101964285], + [508757.2120282266, 6651145.361168989, 96.32620913481244], + [508757.0337988728, 6651145.888019536, 96.04684309281245], + [508755.45827227476, 6651146.344423818, 97.62487107964382], + [508755.22789640026, 6651147.023871941, 97.31054882863958], + [508757.1296558111, 6651145.604663963, 96.63457794281246], + [508756.95881371835, 6651146.109677576, 96.31324940781246], + [508755.34676311864, 6651146.673298042, 97.81007998164468], + [508752.170689591, 6651156.040499378, 91.3199669126459], + [508755.0924505664, 6651147.4233426675, 97.4776635856434], + [508752.170689591, 6651156.040499378, 91.4499669126459], + [508756.87735336926, 6651146.35047646, 96.56095914781245], + [508755.2325448955, 6651147.0101621235, 97.96657127364296], + [508757.0396928167, 6651145.870596886, 96.92267629381246], + [508751.97494228964, 6651156.6178173665, 91.31996691264403], + [508754.9555592707, 6651147.827076497, 97.59981670763861], + [508755.11670379795, 6651147.351812553, 98.09419403264249], + [508756.94293961726, 6651146.156601827, 97.18787401881245], + [508756.7599668474, 6651146.697474032, 96.85840161781245], + [508754.81930480513, 6651148.228932121, 97.67849140064006], + [508755.00028854015, 6651147.695156354, 98.19328952664557], + [508754.6855382233, 6651148.623450224, 97.71623425963736], + [508756.84031526675, 6651146.459962042, 97.42796246581246], + [508756.63442021154, 6651147.068593111, 97.11461474081246], + [508754.845866812, 6651148.15059273, 98.28245417864466], + [508756.7328287711, 6651146.777694883, 97.64121480081245], + [508754.69426468585, 6651148.597713247, 98.32522941964449], + [508752.17068883986, 6651156.040501593, 93.14877057264447], + [508756.502922828, 6651147.457302753, 97.32689254981246], + [508752.1721484198, 6651156.03619685, 93.3525918566441], + [508756.6215470763, 6651147.106646429, 97.82642370281246], + [508753.45195224613, 6651156.4760501245, 91.33631063381246], + [508751.97494228964, 6651156.6178173665, 93.14877057164405], + [508756.36775328236, 6651147.856867401, 97.49400730681245], + [508753.45195224613, 6651156.4760501245, 91.46631063381247], + [508754.12360073806, 6651150.28077381, 97.71623425964779], + [508752.18426792085, 6651156.000452776, 93.76917114464099], + [508756.50756184076, 6651147.4435897125, 97.98291499481245], + [508753.2566042391, 6651157.053503849, 91.33631063381246], + [508751.98167272296, 6651156.597967282, 93.6143612586376], + [508756.23114122404, 6651148.260696153, 97.61616042881245], + [508752.20953092584, 6651155.925944533, 94.19349826463878], + [508756.3919570411, 6651147.785320468, 98.11053775381247], + [508756.09516469634, 6651148.662646259, 97.69483512181246], + [508752.002719687, 6651156.535893422, 94.09163221064352], + [508752.24875516497, 6651155.810260391, 94.61980861563926], + [508756.2757792522, 6651148.128744994, 98.20963324781246], + [508755.9616709778, 6651149.05725712, 97.73257798081245], + [508752.30241690605, 6651155.651995689, 95.04161747464255], + [508753.57334512926, 6651151.903644007, 97.7162342596433], + [508752.0391687129, 6651156.428394222, 94.57453323064652], + [508756.1216725205, 6651148.58428845, 98.29879789981247], + [508752.3705808253, 6651155.450959677, 95.45196701764566], + [508753.4395785479, 6651152.298162109, 97.67849140064625], + [508752.0770762764, 6651156.316593351, 94.93623921563581], + [508753.303324082, 6651152.700017734, 97.59981670764505], + [508752.4528526866, 6651155.208315077, 95.84374671163808], + [508755.9703796392, 6651149.031514091, 98.34157314081246], + [508753.45195149665, 6651156.47605234, 93.16511429381245], + [508752.1242340985, 6651156.177510674, 95.2939970616445], + [508752.5233096953, 6651155.000516051, 96.12122857164316], + [508753.1664327865, 6651153.1037515635, 97.47766358564292], + [508753.5646194184, 6651151.929378766, 98.32522941964064], + [508752.60068676784, 6651154.772307663, 96.38166924464245], + [508753.0309869522, 6651153.5032222895, 97.3105488286411], + [508753.4534080993, 6651156.471746585, 93.36893557781245], + [508752.68431612616, 6651154.525659394, 96.62263889064258], + [508752.8992207858, 6651153.891840562, 97.09827101963653], + [508752.77341753116, 6651154.262872405, 96.84205789664227], + [508752.1806478098, 6651156.011129578, 95.64445327664251], + [508753.41301729245, 6651152.376499283, 98.2824541786431], + [508753.2566042391, 6651157.053503849, 93.16511429281246], + [508752.2461576441, 6651155.817921266, 95.98419830364098], + [508755.40087975713, 6651150.714970364, 97.73257798081245], + [508753.4655028787, 6651156.435994107, 93.78551486581246], + [508753.2585955643, 6651152.831935659, 98.19328952664218], + [508752.32043288345, 6651155.5988611225, 96.30986541364155], + [508753.14218030643, 6651153.175279461, 98.09419403264394], + [508752.4029736697, 6651155.355423383, 96.61823422164692], + [508753.02633920853, 6651153.516929891, 97.96657127363913], + [508753.26332094386, 6651157.033649098, 93.63070497981245], + [508752.4931205494, 6651155.0895529725, 96.90633257264192], + [508752.9121209858, 6651153.853793971, 97.81007998164307], + [508752.59007151355, 6651154.803615258, 97.17153029763888], + [508753.4907143513, 6651156.361468348, 94.20984198581245], + [508752.8006118293, 6651154.182668196, 97.6248710796396], + [508752.6929056298, 6651154.500326351, 97.41161874464137], + [508753.2843249749, 6651156.971560642, 94.10797593181246], + [508753.529858579, 6651156.245757005, 94.63615233681244], + [508753.5834108582, 6651156.087455093, 95.05796119581247], + [508754.8517465848, 6651152.338222121, 97.73257798081245], + [508753.3206996502, 6651156.864036168, 94.59087695181246], + [508753.65143573337, 6651155.886371815, 95.46831073881245], + [508754.7182528663, 6651152.73283298, 97.69483512181246], + [508753.358529889, 6651156.752209012, 94.95258293681245], + [508754.5822763385, 6651153.134783087, 97.61616042881245], + [508753.7335397734, 6651155.643670166, 95.86009043281247], + [508753.40559151577, 6651156.613093634, 95.31034078281245], + [508753.80385306035, 6651155.435822284, 96.13757229281245], + [508754.44566428015, 6651153.5386118395, 97.49400730681245], + [508754.8430386732, 6651152.363962931, 98.34157314081246], + [508753.8810722957, 6651155.20756024, 96.39801296581246], + [508754.3104947345, 6651153.938176488, 97.32689254981246], + [508753.9645310631, 6651154.960853982, 96.63898261181245], + [508754.17899735103, 6651154.32688613, 97.11461474081246], + [508754.0534507151, 6651154.698005208, 96.85840161781245], + [508753.461890152, 6651156.446673419, 95.66079699781247], + [508754.69174579193, 6651152.811188572, 98.29879789981247], + [508753.5272663565, 6651156.253419681, 96.00054202481246], + [508754.53763906023, 6651153.266732028, 98.20963324781246], + [508753.6013900858, 6651156.034308034, 96.32620913481244], + [508754.4214612713, 6651153.610156555, 98.11053775381247], + [508753.6837625013, 6651155.790813059, 96.63457794281246], + [508754.30585647165, 6651153.951887311, 97.98291499481245], + [508753.77372549573, 6651155.524880138, 96.92267629381246], + [508754.1918712361, 6651154.288830593, 97.82642370281246], + [508753.87047869514, 6651155.238875196, 97.18787401881245], + [508754.0805895413, 6651154.617782141, 97.64121480081245], + [508753.9731030456, 6651154.935514982, 97.42796246581246], + [508768.5865013963, 6651148.036477735, 91.46976384454798], + [508768.39461335127, 6651148.615090409, 91.46976384454798], + [508768.39461335127, 6651148.615090409, 91.599763844548], + [508768.5865013963, 6651148.036477735, 93.29856750354799], + [508768.39461335127, 6651148.615090409, 93.29856750354799], + [508768.5799036564, 6651148.056372336, 93.76415819054799], + [508768.3887918162, 6651148.632644468, 93.709382815548], + [508768.5592716442, 6651148.118585402, 94.24142914254799], + [508768.3705870994, 6651148.68753835, 94.130504243548], + [508768.52354122937, 6651148.226325678, 94.72433016254799], + [508768.3390602627, 6651148.782603299, 94.55659337854799], + [508768.48638103175, 6651148.338377273, 95.086036147548], + [508768.2935674586, 6651148.919780752, 94.981499882548], + [508768.4401529504, 6651148.477771853, 95.443793993548], + [508768.2338361244, 6651149.099892582, 95.398466584548], + [508768.38485146343, 6651148.644526073, 95.794250208548], + [508768.32063318836, 6651148.838167672, 96.13399523554799], + [508768.16002375586, 6651149.322463883, 95.80041550154799], + [508768.2478223225, 6651149.057719076, 96.459662345548], + [508768.0727497287, 6651149.585627011, 96.18029630354799], + [508768.1669088696, 6651149.301702744, 96.768031153548], + [508767.99909269536, 6651149.807729919, 96.44670261854799], + [508767.9190751544, 6651150.049012086, 96.69441235854799], + [508768.07853928034, 6651149.5681693945, 97.05612950454798], + [508767.9834997528, 6651149.854748346, 97.32132722954799], + [508767.80376775743, 6651150.396706083, 96.991854828548], + [508767.8826930628, 6651150.158717405, 97.561415676548], + [508767.68044477655, 6651150.768569997, 97.248067951548], + [508767.7771103449, 6651150.477087936, 97.77466801154799], + [508767.55127644655, 6651151.158059778, 97.46034576054801], + [508767.66779964755, 6651150.806699689, 97.95987691354799], + [508764.5543440002, 6651160.194907766, 91.46976384454798], + [508767.4185009948, 6651151.558426351, 97.62746051754799], + [508764.5543440002, 6651160.194907766, 91.599763844548], + [508767.55583329406, 6651151.144319215, 98.11636820554799], + [508764.36245595507, 6651160.77352044, 91.46976384454798], + [508767.28430857987, 6651151.963065587, 97.74961363954799], + [508767.44227606175, 6651151.4867358245, 98.24399096454799], + [508767.15074043913, 6651152.365822407, 97.82828833254798], + [508767.3281559888, 6651151.830849605, 98.34308645854799], + [508767.01961113274, 6651152.761225251, 97.866031191548], + [508767.17677876254, 6651152.287307334, 98.432251110548], + [508767.02816554817, 6651152.735430557, 98.475026351548], + [508764.5543432639, 6651160.194909986, 93.29856750454799], + [508764.5557740675, 6651160.19059559, 93.50238878854799], + [508764.36245595507, 6651160.77352044, 93.29856750354799], + [508766.46875252575, 6651154.422265525, 97.866031191548], + [508764.5676546268, 6651160.154771357, 93.91896807654798], + [508764.36905369506, 6651160.75362584, 93.76415819054799], + [508764.5924195593, 6651160.080096022, 94.343295196548], + [508764.3896857072, 6651160.691412774, 94.24142914254799], + [508764.63087047276, 6651159.964152448, 94.76960554754798], + [508764.6834742455, 6651159.805532824, 95.19141440654799], + [508765.9293454822, 6651156.048775146, 97.866031191548], + [508764.4254161221, 6651160.583672497, 94.72433016254799], + [508765.7982161757, 6651156.44417799, 97.82828833254798], + [508764.75029427867, 6651159.604045973, 95.60176394954799], + [508764.4625763197, 6651160.471620903, 95.086036147548], + [508765.66464803496, 6651156.846934809, 97.74961363954799], + [508764.83094410953, 6651159.36085722, 95.993543643548], + [508764.9000120227, 6651159.15259219, 96.27102550354799], + [508765.53045562014, 6651157.251574045, 97.62746051754799], + [508764.50880440115, 6651160.332226322, 95.443793993548], + [508765.9207918033, 6651156.074567618, 98.475026351548], + [508764.97586356755, 6651158.923872025, 96.531466176548], + [508765.3976801684, 6651157.65194062, 97.46034576054801], + [508765.0578441312, 6651158.676670627, 96.772435822548], + [508765.2685118383, 6651158.041430401, 97.248067951548], + [508765.1451888574, 6651158.413294315, 96.991854828548], + [508764.564105888, 6651160.165472102, 95.794250208548], + [508765.7721785889, 6651156.522690841, 98.432251110548], + [508776.31516765006, 6651150.581623798, 91.55678584387401], + [508764.62832416315, 6651159.971830503, 96.13399523554799], + [508765.62080136256, 6651156.979148571, 98.34308645854799], + [508764.70113502897, 6651159.7522791, 96.459662345548], + [508765.5066812897, 6651157.323262351, 98.24399096454799], + [508764.78204848187, 6651159.50829543, 96.768031153548], + [508765.3931240574, 6651157.665678961, 98.11636820554799], + [508764.8704180711, 6651159.2418287825, 97.05612950454798], + [508776.1257040518, 6651151.161034873, 91.55678584387401], + [508765.2811577039, 6651158.003298488, 97.95987691354799], + [508764.9654575986, 6651158.955249829, 97.32132722954799], + [508765.17184700654, 6651158.33291024, 97.77466801154799], + [508765.0662642886, 6651158.65128077, 97.561415676548], + [508776.1257040518, 6651151.161034873, 91.686785843874], + [508776.31516765006, 6651150.581623798, 93.385589502874], + [508776.1257040518, 6651151.161034873, 93.385589502874], + [508776.3086532705, 6651150.601545851, 93.851180189874], + [508776.11995607, 6651151.178613153, 93.796404814874], + [508776.28828193754, 6651150.663844762, 94.32845114187401], + [508776.10198136437, 6651151.233582781, 94.21752624287402], + [508776.2530029656, 6651150.771733703, 94.811352161874], + [508776.0708528595, 6651151.328778906, 94.643615377874], + [508776.2163122756, 6651150.883939912, 95.17305814687401], + [508776.0259348432, 6651151.466145642, 95.06852188187402], + [508776.17066827195, 6651151.023526837, 95.53081599287401], + [508775.9669581962, 6651151.646506001, 95.485488583874], + [508776.11606550246, 6651151.190511154, 95.881272207874], + [508776.0526586056, 6651151.384419949, 96.221017234874], + [508775.8940784244, 6651151.869384417, 95.887437500874], + [508775.98076768295, 6651151.604274302, 96.546684344874], + [508775.8079070779, 6651152.132910673, 96.267318302874], + [508775.9008765468, 6651151.848594632, 96.855053152874], + [508775.7351806786, 6651152.355320049, 96.53372461787401], + [508775.6561741349, 6651152.59693515, 96.781434357874], + [508775.8136234803, 6651152.1154289665, 97.143151503874], + [508775.7197847482, 6651152.402403356, 97.408349228874], + [508775.54232361173, 6651152.945108913, 97.078876827874], + [508775.62025171996, 6651152.706791848, 97.648437675874], + [508775.4205587791, 6651153.317485945, 97.335089950874], + [508775.5160030074, 6651153.025601682, 97.861690010874], + [508775.2930224514, 6651153.707513166, 97.547367759874], + [508775.4080734175, 6651153.35566825, 98.04689891287401], + [508775.1619245771, 6651154.108432187, 97.714482516874], + [508772.33395533194, 6651162.756830677, 91.55678584387401], + [508772.33395533194, 6651162.756830677, 91.686785843874], + [508775.29752172454, 6651153.693753643, 98.203390204874], + [508775.0294276423, 6651154.513629765, 97.836635638874], + [508772.1444917337, 6651163.336241752, 91.55678584387401], + [508775.1853992532, 6651154.036642737, 98.331012963874], + [508774.89754709427, 6651154.91694233, 97.915310331874], + [508775.0727210527, 6651154.381231342, 98.430108457874], + [508774.7680745667, 6651155.312890771, 97.95305319087402], + [508774.9232564314, 6651154.838318918, 98.519273109874], + [508774.77652089973, 6651155.287060485, 98.56204835087401], + [508772.3339546049, 6651162.7568329, 93.385589503874], + [508772.33536733076, 6651162.752512552, 93.58941078787402], + [508772.1444917337, 6651163.336241752, 93.385589502874], + [508774.22417589, 6651156.976223038, 97.95305319087402], + [508772.3470977828, 6651162.716638885, 94.005990075874], + [508772.1510061133, 6651163.316319699, 93.851180189874], + [508772.37154981797, 6651162.641860511, 94.430317195874], + [508772.1713774462, 6651163.254020788, 94.32845114187401], + [508772.4095149159, 6651162.525756951, 94.856627546874], + [508773.6915840899, 6651158.604977004, 97.95305319087402], + [508772.461454056, 6651162.366918456, 95.27843640587402], + [508772.20665641816, 6651163.146131848, 94.811352161874], + [508773.5621115622, 6651159.000925444, 97.915310331874], + [508772.5274298385, 6651162.165153583, 95.688785948874], + [508772.24334710813, 6651163.0339256385, 95.17305814687401], + [508773.4302310141, 6651159.40423801, 97.836635638874], + [508772.60706068337, 6651161.921629265, 96.080565642874], + [508773.2977340795, 6651159.809435588, 97.714482516874], + [508773.683138484, 6651158.630805066, 98.56204835087401], + [508772.6752559445, 6651161.713076858, 96.358047502874], + [508772.2889911118, 6651162.894338713, 95.53081599287401], + [508772.75014912826, 6651161.484041093, 96.618488175874], + [508773.16663620505, 6651160.2103546085, 97.547367759874], + [508772.8310938925, 6651161.236498593, 96.85945782187402], + [508773.0390998774, 6651160.60038183, 97.335089950874], + [508772.9173350447, 6651160.972758862, 97.078876827874], + [508772.34359388123, 6651162.727354397, 95.881272207874], + [508773.53640295233, 6651159.079546632, 98.519273109874], + [508772.4070007781, 6651162.533445602, 96.221017234874], + [508773.38693833107, 6651159.536634209, 98.430108457874], + [508772.47889170086, 6651162.313591248, 96.546684344874], + [508773.27426013054, 6651159.881222813, 98.331012963874], + [508772.55878283695, 6651162.069270918, 96.855053152874], + [508773.1621376592, 6651160.224111907, 98.203390204874], + [508772.64603590337, 6651161.802436585, 97.143151503874], + [508773.0515859663, 6651160.562197301, 98.04689891287401], + [508772.73987463553, 6651161.5154621955, 97.408349228874], + [508772.9436563763, 6651160.892263868, 97.861690010874], + [508772.83940766373, 6651161.211073703, 97.648437675874], + [508785.09937079577, 6651153.430914629, 91.64923286031915], + [508784.9126627614, 6651154.011219511, 91.64923286031915], + [508784.9126627614, 6651154.011219511, 91.77923286031915], + [508785.09937079577, 6651153.430914629, 93.47803651931915], + [508784.9126627614, 6651154.011219511, 93.47803651931915], + [508785.0929511615, 6651153.450867412, 93.94362720631915], + [508784.9069983784, 6651154.028824909, 93.88885183131916], + [508785.07287610974, 6651153.513262427, 94.42089815831915], + [508784.8892850974, 6651154.083879335, 94.30997325931916], + [508785.0381102361, 6651153.6213178, 94.90379917831915], + [508784.8586093265, 6651154.17922231, 94.73606239431915], + [508785.0019531767, 6651153.7336971, 95.26550516331916], + [508784.8143445989, 6651154.31680095, 95.16096889831915], + [508784.9569730207, 6651153.873499355, 95.62326300931916], + [508784.75622571004, 6651154.497439536, 95.57793560031917], + [508784.9031643955, 6651154.040741263, 95.97371922431915], + [508784.8406796903, 6651154.2349491855, 96.31346425131915], + [508784.6844059036, 6651154.720661768, 95.97988451731915], + [508784.7698343512, 6651154.455142689, 96.63913136131916], + [508784.5994878357, 6651154.984594543, 96.35976531931915], + [508784.691105154, 6651154.699839912, 96.94750016931917], + [508784.52781917126, 6651155.207347013, 96.62617163431915], + [508784.44996170094, 6651155.449334833, 96.87388137431915], + [508784.60512109863, 6651154.967085869, 97.23559852031914], + [508784.5126471597, 6651155.25450295, 97.50079624531915], + [508784.337767023, 6651155.798045695, 97.17132384431916], + [508784.4145617426, 6651155.559360998, 97.74088469231916], + [508784.2177731415, 6651156.170997163, 97.42753696731916], + [508784.3118292263, 6651155.878662633, 97.95413702731915], + [508784.0920917058, 6651156.561626046, 97.63981477631917], + [508784.2054693673, 6651156.209238368, 98.13934592931915], + [508783.96290052263, 6651156.9631635295, 97.80692953331916], + [508781.1760613422, 6651165.624903189, 91.64923286031915], + [508784.09652554145, 6651156.547845297, 98.29583722131915], + [508781.1760613422, 6651165.624903189, 91.77923286031915], + [508780.9085904975, 6651166.179011417, 91.64838872264654], + [508783.8323306271, 6651157.3689861735, 97.92908265531916], + [508781.03831829067, 6651166.053020627, 91.64923286031915], + [508781.4042431351, 6651165.697636796, 91.65142950527056], + [508780.98935330793, 6651166.2052080715, 91.64923286031915], + [508783.9860337824, 6651156.891263337, 98.42345998031915], + [508781.4042431351, 6651165.697636796, 91.78142950527057], + [508783.7023681535, 6651157.772920896, 98.00775734831915], + [508783.8749943768, 6651157.236383512, 98.52255547431915], + [508783.5747786779, 6651158.169480134, 98.04550020731915], + [508783.72770357324, 6651157.694176198, 98.61172012631916], + [508783.58310216723, 6651158.143610002, 98.65449536731917], + [508781.17606062576, 6651165.624905415, 93.47803652031915], + [508781.17745280487, 6651165.620578401, 93.68185780431915], + [508780.9085904975, 6651166.179011417, 93.47719238164655], + [508783.038790479, 6651159.835378285, 98.04550020731915], + [508781.40424123115, 6651165.697638644, 93.48023315383543], + [508780.98935330793, 6651166.2052080715, 93.47803651931915], + [508781.40793966077, 6651165.694046753, 93.6840766446469], + [508781.1890126489, 6651165.584649395, 94.09843709231914], + [508791.3308076835, 6651156.057021789, 91.7114063908341], + [508791.8268117102, 6651155.5753059, 91.71442303084955], + [508791.3308076835, 6651156.057021789, 91.84140639083411], + [508780.92559867207, 6651166.162493188, 93.9428937328404], + [508780.9957729421, 6651166.185255287, 93.94362720631915], + [508781.21310905286, 6651165.509755666, 94.52276421231916], + [508781.438649262, 6651165.664221789, 94.10084032902482], + [508780.9787855011, 6651166.110838485, 94.42051076182501], + [508781.0158479939, 6651166.122860272, 94.42089815831915], + [508781.25052198535, 6651165.393473004, 94.94907456331914], + [508781.5026631831, 6651165.602051884, 94.52555184468987], + [508782.51394470903, 6651161.466644794, 98.04550020731915], + [508781.03831829043, 6651166.053020627, 94.73301253991784], + [508781.3017057211, 6651165.234389482, 95.37088342231915], + [508781.0506138674, 6651166.0148049, 94.90379917831915], + [508781.0709824218, 6651166.021297435, 94.90399521988304], + [508782.3863552335, 6651161.863204031, 98.00775734831915], + [508781.36672195, 6651165.032313361, 95.78123296531915], + [508781.60205347085, 6651165.505524683, 94.95245908333906], + [508781.0867709269, 6651165.902425601, 95.26550516331916], + [508782.2563927599, 6651162.267138755, 97.92908265531916], + [508781.4451946417, 6651164.78841338, 96.17301265931916], + [508781.1670363865, 6651165.928010449, 95.26627774223853], + [508782.50562193635, 6651161.492512698, 98.65449536731917], + [508782.12582286436, 6651162.672961397, 97.80692953331916], + [508781.512398069, 6651164.579539256, 96.45049451931915], + [508781.1317510829, 6651165.7626233455, 95.62326300931916], + [508781.58620200417, 6651164.350150177, 96.71093519231916], + [508781.9966316811, 6651163.074498882, 97.63981477631917], + [508781.73802693875, 6651165.373468134, 95.37508465078702], + [508781.66596950544, 6651164.102225814, 96.95190483831915], + [508781.8709502454, 6651163.465127764, 97.42753696731916], + [508781.750956364, 6651163.838079233, 97.17132384431916], + [508791.3308076835, 6651156.057021789, 93.5402100498341], + [508782.36102053046, 6651161.941946502, 98.61172012631916], + [508781.18555970816, 6651165.595381437, 95.97371922431915], + [508781.2865295777, 6651165.811959439, 95.62475291020371], + [508791.8268117102, 6651155.5753059, 93.54322668984955], + [508781.2480444133, 6651165.401173515, 96.31346425131915], + [508782.21372972673, 6651162.399739189, 98.52255547431915], + [508781.9107474735, 6651165.2057230715, 95.786471820401], + [508791.3157598206, 6651156.071636176, 93.95093387201312], + [508781.3188897525, 6651165.180980011, 96.63913136131916], + [508782.1026903211, 6651162.744859362, 98.42345998031915], + [508781.429476264, 6651165.673130546, 95.97606738084248], + [508781.39761894965, 6651164.936282787, 96.94750016931917], + [508781.9921985622, 6651163.088277403, 98.29583722131915], + [508791.8097574663, 6651155.591868871, 94.00871362346382], + [508781.48360300495, 6651164.669036831, 97.23559852031914], + [508781.88325473625, 6651163.426884332, 98.13934592931915], + [508781.5760769439, 6651164.381619749, 97.50079624531915], + [508781.77689487726, 6651163.757460066, 97.95413702731915], + [508781.6741623611, 6651164.076761703, 97.74088469231916], + [508782.1192161192, 6651165.003259677, 96.17950419952633], + [508791.26870314847, 6651156.117337311, 94.37176921039583], + [508781.59547161206, 6651165.511916941, 96.31680924172528], + [508791.75642657146, 6651155.643663489, 94.48566013922657], + [508782.2977471118, 6651164.829871537, 96.45805911072323], + [508781.7836776189, 6651165.329132489, 96.64360681646063], + [508791.18721064064, 6651156.196482304, 94.79736293709999], + [508782.4938128534, 6651164.639453763, 96.71967850416095], + [508791.6640683957, 6651155.733361149, 94.9679993539432], + [508781.9928276921, 6651165.126007297, 96.95323220408682], + [508791.06961804087, 6651156.310687473, 95.22155466351614], + [508782.7057212588, 6651164.433649696, 96.96192244134859], + [508782.8186082703, 6651164.324014563, 97.0723109665908], + [508791.5680144301, 6651155.826648137, 95.32912112216707], + [508782.22125084494, 6651164.904164216, 97.2427033054233], + [508782.9314952818, 6651164.214379431, 97.18269949183302], + [508790.915220813, 6651156.460637058, 95.6375830351749], + [508791.44852124096, 6651155.942699146, 95.68615228904439], + [508782.4669148643, 6651164.665576915, 97.50937783292844], + [508783.2502681133, 6651163.904789329, 97.44083070961177], + [508790.7244260601, 6651156.645935682, 96.03837267327464], + [508791.3055745548, 6651156.08152804, 96.03573934039045], + [508782.7274861998, 6651164.412511727, 97.75103319599748], + [508783.5841503607, 6651163.580525057, 97.6551183535247], + [508790.4988347842, 6651156.865028464, 96.41688313154079], + [508783.00040290714, 6651164.147456793, 97.96592723521465], + [508791.1395792051, 6651156.242741645, 96.37447525727447], + [508783.9273565201, 6651163.247205466, 97.82429995188103], + [508790.30844155047, 6651157.049937135, 96.6821332156547], + [508784.2742253312, 6651162.91032873, 97.9485428796279], + [508783.28295592504, 6651163.8730431385, 98.15283640162367], + [508790.95137319824, 6651156.425526096, 96.6989984914695], + [508790.1016072871, 6651157.250813229, 96.92858719596532], + [508784.61948048195, 6651162.5750191705, 98.02929856282987], + [508783.57237344515, 6651163.591962722, 98.31106989193187], + [508784.95843158313, 6651162.245832063, 98.06908529524047], + [508790.74222312565, 6651156.628651287, 97.00609644935226], + [508789.8035536311, 6651157.540281003, 97.22422066004887], + [508783.86590316804, 6651163.306888563, 98.44046025153582], + [508786.3527241049, 6651160.891704223, 98.07750205646393], + [508789.48478080117, 6651157.8498711055, 97.47849977789618], + [508784.1608877546, 6651163.020401448, 98.54133276512589], + [508790.51379997365, 6651156.85049437, 97.29280722579055], + [508789.15089855244, 6651158.174135376, 97.68875274712765], + [508784.55217692594, 6651162.640383948, 98.63285560452938], + [508790.2681359536, 6651157.089081669, 97.55651309220755], + [508788.80769239395, 6651158.507454967, 97.8537870088007], + [508787.77661733126, 6651159.508828371, 98.08611278570439], + [508795.13602509245, 6651156.630127247, 91.7464899322843], + [508788.46082358254, 6651158.844331705, 97.97383834843298], + [508784.9363215073, 6651162.267305225, 98.67794710499602], + [508788.11556843144, 6651159.179641264, 98.05042195029993], + [508790.0075646181, 6651157.342146859, 97.79501965812733], + [508789.73464791116, 6651157.607201791, 98.00661572382455], + [508789.45209489367, 6651157.881615446, 98.19011047744299], + [508794.9524655103, 6651157.211435708, 91.7464899322843], + [508789.1626773728, 6651158.162695862, 98.34484661064175], + [508794.9524655103, 6651157.211435708, 91.87648993228431], + [508788.86914764997, 6651158.447770022, 98.47068992764929], + [508787.79872931115, 6651159.48735336, 98.69524178576452], + [508788.5741630632, 6651158.734257137, 98.56799782418399], + [508788.18287389237, 6651159.114274638, 98.65479230272302], + [508795.13602509245, 6651156.630127247, 93.57529359128431], + [508794.9524655103, 6651157.211435708, 93.57529359128431], + [508795.1297137123, 6651156.650114537, 94.0408842782843], + [508794.9468966456, 6651157.229071553, 93.98610890328429], + [508795.10997718555, 6651156.712617458, 94.51815523028431], + [508794.92948206305, 6651157.284221189, 94.4072303312843], + [508795.07579756796, 6651156.820859702, 95.00105625028431], + [508794.89932357677, 6651157.379729051, 94.8333194662843], + [508795.0402502238, 6651156.93343335, 95.3627622352843], + [508794.85580528405, 6651157.51754562, 95.25822597028431], + [508794.99602856697, 6651157.073477378, 95.72052008128429], + [508794.79866645223, 6651157.6984966, 95.6751926722843], + [508794.94312731485, 6651157.241008515, 96.07097629628431], + [508794.8816962875, 6651157.435552301, 96.4107213232843], + [508794.7280577411, 6651157.922104873, 96.0771415892843], + [508794.8120456112, 6651157.656126606, 96.73638843328429], + [508794.644571644, 6651158.186494092, 96.4570223912843], + [508794.73464402213, 6651157.901247009, 97.0447572412843], + [508794.57411152613, 6651158.4096317915, 96.72342870628431], + [508794.49756696407, 6651158.652038105, 96.9711384462843], + [508794.6501099134, 6651158.16895514, 97.3328555922843], + [508794.5591953598, 6651158.456869281, 97.5980533172843], + [508794.3872642216, 6651159.001352027, 97.2685809162843], + [508794.4627639542, 6651158.762254546, 97.8381417642843], + [508794.2692937934, 6651159.3749484755, 97.5247940392843], + [508794.36176381324, 6651159.082108383, 98.0513940992843], + [508794.1457317201, 6651159.766252911, 97.7370718482843], + [508794.2571974974, 6651159.413255814, 98.23660300128431], + [508794.018719084, 6651160.168484814, 97.9041866052843], + [508794.150090788, 6651159.752448331, 98.39309429328429], + [508791.2788742904, 6651168.845204068, 91.7464899322843], + [508791.2788742904, 6651168.845204068, 91.87648993228431], + [508793.8903509847, 6651160.575009286, 98.0263397272843], + [508794.04146224837, 6651160.096460278, 98.52071705228431], + [508791.0953147082, 6651169.42651253, 91.7464899322843], + [508793.76258006453, 6651160.979642573, 98.1050144202843], + [508793.932295297, 6651160.442177301, 98.61981254628431], + [508793.6371421265, 6651161.376887619, 98.1427572792843], + [508793.7874882538, 6651160.900761694, 98.70897719828432], + [508793.64532525715, 6651161.3509727465, 98.7517524392843], + [508791.2788735861, 6651168.845206299, 93.5752935922843], + [508801.65980245115, 6651158.677523874, 91.80494108921562], + [508791.2802422889, 6651168.8408718025, 93.7791148762843], + [508793.1101922808, 6651163.045666771, 98.1427572792843], + [508791.0953147082, 6651169.42651253, 93.57529359128431], + [508791.2916071996, 6651168.804880661, 94.1956941642843], + [508801.4782893478, 6651159.259474593, 91.80494108921562], + [508801.4782893478, 6651159.259474593, 91.93494108921564], + [508791.10162608826, 6651169.40652524, 94.0408842782843], + [508791.3152972667, 6651168.729857411, 94.62002128428429], + [508791.352079306, 6651168.61337365, 95.04633163528429], + [508791.121362615, 6651169.34402232, 94.51815523028431], + [508792.5941969695, 6651164.679754389, 98.1427572792843], + [508791.40239993186, 6651168.454015007, 95.46814049428431], + [508791.15554223274, 6651169.235780076, 95.00105625028431], + [508792.4687590315, 6651165.076999436, 98.1050144202843], + [508791.466319794, 6651168.251589417, 95.8784900372843], + [508791.19108957675, 6651169.123206427, 95.3627622352843], + [508792.3409881112, 6651165.481632723, 98.0263397272843], + [508801.65980245115, 6651158.677523874, 93.63374474821562], + [508791.54346920294, 6651168.007267636, 96.27026973128432], + [508792.5860145435, 6651164.705667031, 98.7517524392843], + [508792.212620012, 6651165.8881571945, 97.9041866052843], + [508791.6095393809, 6651167.798032286, 96.5477515912843], + [508791.23531123373, 6651168.983162398, 95.72052008128429], + [508792.08560737595, 6651166.290389098, 97.7370718482843], + [508791.68209876254, 6651167.5682465015, 96.8081922642843], + [508791.7605211467, 6651167.319893379, 97.0491619102843], + [508791.9620453025, 6651166.681693533, 97.5247940392843], + [508791.8440748743, 6651167.055289983, 97.2685809162843], + [508792.4438515468, 6651165.155878084, 98.70897719828432], + [508801.4782893478, 6651159.259474593, 93.63374474821562], + [508791.2882124857, 6651168.815631263, 96.07097629628431], + [508801.6535614357, 6651158.697533246, 94.09933543521562], + [508791.34964351315, 6651168.621087477, 96.4107213232843], + [508792.2990445036, 6651165.614462476, 98.61981254628431], + [508791.41929418937, 6651168.400513171, 96.73638843328429], + [508792.1898775523, 6651165.960179501, 98.52071705228431], + [508801.47278256953, 6651159.277129922, 94.04456006021562], + [508792.0812490126, 6651166.304191447, 98.39309429328429], + [508791.4966957784, 6651168.155392769, 97.0447572412843], + [508801.6340449486, 6651158.760105223, 94.57660638721562], + [508791.9741423031, 6651166.643383963, 98.23660300128431], + [508791.5812298872, 6651167.887684638, 97.3328555922843], + [508791.8695759873, 6651166.974531394, 98.0513940992843], + [508791.67214444076, 6651167.599770498, 97.5980533172843], + [508791.7685758464, 6651167.29438523, 97.8381417642843], + [508801.4555621396, 6651159.33234049, 94.46568148821562], + [508801.60024639446, 6651158.868467058, 95.05950740721562], + [508801.42573988595, 6651159.427953876, 94.89177062321563], + [508801.5650953625, 6651158.981165084, 95.42121339221562], + [508801.38270677225, 6651159.565922711, 95.31667712721563], + [508801.5213667263, 6651159.12136384, 95.77897123821562], + [508801.32620497287, 6651159.747073614, 95.73364382921562], + [508801.46905526257, 6651159.289080073, 96.12942745321564], + [508801.4083091207, 6651159.4838388, 96.46917248021562], + [508801.2563834678, 6651159.970928941, 96.13559274621562], + [508801.33943496953, 6651159.704656808, 96.79483959021562], + [508801.173828145, 6651160.235610271, 96.51547354821564], + [508801.2628963195, 6651159.950048032, 97.10320839821563], + [508801.1041535766, 6651160.458994503, 96.78187986321562], + [508801.0284623986, 6651160.70166864, 97.02958960321564], + [508801.179304669, 6651160.21805194, 97.39130674921562], + [508801.0894037084, 6651160.506284182, 97.65650447421564], + [508800.9193894053, 6651161.0513685, 97.32703207321562], + [508806.02157038066, 6651160.022071428, 91.84040728419325], + [508800.9940474024, 6651160.812006854, 97.89659292121564], + [508805.84142554365, 6651160.604443926, 91.84040728419237], + [508800.802734212, 6651161.425377718, 97.58324519621564], + [508805.84142554365, 6651160.604443926, 91.97040728419239], + [508800.8941732972, 6651161.1322140815, 98.10984525621564], + [508800.68054971413, 6651161.817114487, 97.79552300521563], + [508800.7907727759, 6651161.463727381, 98.29505415821562], + [508800.5549531232, 6651162.219790796, 97.96263776221562], + [508800.68486018345, 6651161.803294654, 98.45154545021563], + [508797.8456544565, 6651170.906096526, 91.80494108921562], + [508806.02157038066, 6651160.022071428, 93.66921094319325], + [508797.8456544565, 6651170.906096526, 91.93494108921564], + [508800.428016181, 6651162.626764416, 98.08479088421562], + [508800.5774427274, 6651162.147686682, 98.57916820921564], + [508797.66414135316, 6651171.488047247, 91.80494108921562], + [508805.84142554365, 6651160.604443926, 93.66921094319237], + [508800.30166975997, 6651163.031844763, 98.16346557721562], + [508806.01537641056, 6651160.042095303, 94.13480163019182], + [508800.46949286223, 6651162.493785672, 98.67826370321563], + [508800.1776303111, 6651163.429528705, 98.20120843621562], + [508805.83596027637, 6651160.622112051, 94.08002625519457], + [508800.32630025153, 6651162.952876732, 98.76742835521563], + [508805.99600704084, 6651160.10471263, 94.61207258219072], + [508805.8188696561, 6651160.677362634, 94.50114768319555], + [508800.1857222093, 6651163.403585201, 98.81020359621563], + [508805.9624632644, 6651160.213153002, 95.09497360219407], + [508797.8456537601, 6651170.90609876, 93.63374474921562], + [508805.78927220526, 6651160.773045316, 94.92723681818944], + [508797.8470072035, 6651170.901759473, 93.83756603321562], + [508799.65655535174, 6651165.10015161, 98.20120843621562], + [508805.9275772049, 6651160.325932708, 95.45667958719376], + [508797.66414135316, 6651171.488047247, 93.63374474821562], + [508797.85824540845, 6651170.865728568, 94.25414532121562], + [508805.7465634801, 6651160.911114147, 95.35214332219047], + [508805.8841782, 6651160.466233075, 95.81443743319278], + [508797.6703823686, 6651171.468037874, 94.09933543521562], + [508797.8816713584, 6651170.790622428, 94.67847244121562], + [508805.69048759807, 6651161.092396343, 95.76911002419283], + [508805.8322610662, 6651160.634070863, 96.1648936481941], + [508797.9180433202, 6651170.674009969, 95.10478279221563], + [508797.6898988557, 6651171.405465897, 94.57660638721562], + [508799.1463127965, 6651166.736044649, 98.20120843621562], + [508797.96780292894, 6651170.514475261, 95.52659165121563], + [508797.72369740985, 6651171.2971040625, 95.05950740721562], + [508805.7719728354, 6651160.828970745, 96.50463867519221], + [508799.0222733476, 6651167.133728593, 98.16346557721562], + [508805.6211924154, 6651161.316413912, 96.17105894119219], + [508798.0310101579, 6651170.311826021, 95.93694119421562], + [508798.8959269265, 6651167.538808937, 98.08479088421562], + [508797.7588484418, 6651171.1844060365, 95.42121339221562], + [508798.1072994394, 6651170.0672343, 96.32872088821563], + [508799.13822159515, 6651166.7619859185, 98.81020359621563], + [508798.76898998435, 6651167.945782559, 97.96263776221562], + [508798.1726330106, 6651169.857767776, 96.60620274821562], + [508805.7036178657, 6651161.049948793, 96.83030578519424], + [508797.802577078, 6651171.044207281, 95.77897123821562], + [508798.64339339343, 6651168.3484588675, 97.79552300521563], + [508798.2443834383, 6651169.627728113, 96.86664342121563], + [508805.53925940424, 6651161.581287075, 96.55093974319398], + [508798.32193150296, 6651169.3791005965, 97.10761306721562], + [508798.52120889554, 6651168.740195637, 97.58324519621564], + [508798.4045537023, 6651169.114204854, 97.32703207321562], + [508798.9976435527, 6651167.212694388, 98.76742835521563], + [508797.85488854174, 6651170.8764910465, 96.12942745321564], + [508798.8544509421, 6651167.671785448, 98.67826370321563], + [508797.9156346836, 6651170.68173232, 96.46917248021562], + [508805.6276561724, 6651161.295517869, 97.13867459319158], + [508805.47011005046, 6651161.804833207, 96.81734605819234], + [508798.7465010769, 6651168.017884438, 98.57916820921564], + [508797.9845088348, 6651170.460914312, 96.79483959021562], + [508798.63908362086, 6651168.362276467, 98.45154545021563], + [508798.0610474849, 6651170.215523088, 97.10320839821563], + [508798.5331710284, 6651168.701843739, 98.29505415821562], + [508798.1446391353, 6651169.947519179, 97.39130674921562], + [508798.4297705071, 6651169.033357039, 98.10984525621564], + [508798.23454009584, 6651169.659286938, 97.65650447421564], + [508798.3298964019, 6651169.353564266, 97.89659292121564], + [508805.3949894412, 6651162.047683226, 97.065055798192], + [508805.54469464545, 6651161.563716018, 97.42677294419249], + [508805.45547136874, 6651161.852157161, 97.69197066919432], + [508805.2867386526, 6651162.397636537, 97.36249826819326], + [508805.3608338692, 6651162.158101411, 97.93205911619278], + [508805.17096281936, 6651162.771916824, 97.61871139119184], + [508805.26171262615, 6651162.478540713, 98.14531145119072], + [508805.04969936213, 6651163.163937511, 97.83098920019165], + [508805.1590915499, 6651162.810294283, 98.33052035319271], + [508804.9250495327, 6651163.566905666, 97.99810395719315], + [508805.05397733854, 6651163.150107662, 98.48701164519102], + [508802.2361738679, 6651172.259506941, 91.84040728419299], + [508802.2361738679, 6651172.259506941, 91.97040728419302], + [508804.79906945553, 6651163.974174247, 98.12025707919231], + [508804.94736960786, 6651163.494749295, 98.61463440419426], + [508802.0560290307, 6651172.841879439, 91.84040728419106], + [508804.6736754481, 6651164.379548183, 98.1989317721914], + [508804.8402334811, 6651163.841099124, 98.71372989819434], + [508804.55057102285, 6651164.777520353, 98.23667463119219], + [508804.6981202724, 6651164.300522918, 98.80289455019278], + [508804.55860192346, 6651164.751558046, 98.84566979119329], + [508802.23617317685, 6651172.259509175, 93.66921094419426], + [508802.2375164178, 6651172.255166743, 93.87303222819412], + [508804.0334239857, 6651166.449354069, 98.23667463119065], + [508802.0560290307, 6651172.841879439, 93.66921094319106], + [508802.2486699077, 6651172.219109724, 94.2896115161922], + [508802.0622230007, 6651172.821855564, 94.13480163019142], + [508802.2719192703, 6651172.14394915, 94.71393863619335], + [508802.3080170559, 6651172.027252174, 95.1402489871918], + [508802.0815923706, 6651172.759238237, 94.61207258219358], + [508803.52702769707, 6651168.0864327485, 98.23667463119213], + [508802.35740157095, 6651171.867601841, 95.56205784619114], + [508802.1151361473, 6651172.650797865, 95.09497360219257], + [508803.4039232714, 6651168.484404921, 98.19893177219056], + [508802.42013233656, 6651171.664805727, 95.97240738919054], + [508803.27852926427, 6651168.889778854, 98.120257079192], + [508802.15002220694, 6651172.53801816, 95.45667958719415], + [508802.4958465408, 6651171.420036733, 96.3641870831913], + [508803.51899748814, 6651168.11239282, 98.84566979119231], + [508803.1525491875, 6651169.297047436, 97.99810395719369], + [508802.56068762037, 6651171.210418396, 96.64166894319322], + [508802.1934212113, 6651172.397717793, 95.81443743319153], + [508803.02789935796, 6651169.700015591, 97.83098920019393], + [508802.631897185, 6651170.980212009, 96.9021096161917], + [508802.70886068366, 6651170.731404295, 97.14307926219281], + [508802.90663590055, 6651170.092036278, 97.61871139119249], + [508802.79086006735, 6651170.466316564, 97.3624982681923], + [508803.3794791392, 6651168.563427947, 98.8028945501939], + [508802.24533834547, 6651172.229880003, 96.16489364819257], + [508814.0174386713, 6651162.486857572, 91.90542289905302], + [508803.3084225346, 6651168.793139845, 98.75831222403362], + [508803.2373659306, 6651169.022851741, 98.7137298981923], + [508802.3056265758, 6651172.034980122, 96.5046386751908], + [508803.13022980397, 6651169.369201573, 98.61463440419368], + [508802.3739815461, 6651171.814002072, 96.83030578519366], + [508813.83980210137, 6651163.070003264, 91.90542289905302], + [508803.0236220729, 6651169.713843205, 98.48701164519329], + [508802.4499432392, 6651171.568432997, 97.138674593194], + [508802.9185078617, 6651170.053656584, 98.33052035319393], + [508802.5329047661, 6651171.300234849, 97.42677294419308], + [508813.83980210137, 6651163.070003264, 92.03542289905302], + [508802.8158867849, 6651170.385410154, 98.14531145119105], + [508802.62212804286, 6651171.011793706, 97.69197066919236], + [508802.71676554205, 6651170.705849456, 97.93205911619029], + [508814.0174386713, 6651162.486857572, 93.73422655805301], + [508813.83980210137, 6651163.070003264, 93.73422655805301], + [508814.0113309439, 6651162.506908032, 94.19981724505301], + [508813.8344129301, 6651163.087694844, 94.145041870053], + [508813.9922312659, 6651162.569608494, 94.67708819705302], + [508813.81756027293, 6651163.143018781, 94.56616329805301], + [508813.9591545395, 6651162.678192838, 95.15998921705301], + [508813.7883749262, 6651163.238828498, 94.99225243305301], + [508813.9247542201, 6651162.791122275, 95.52169520205301], + [508813.74626086076, 6651163.377080636, 95.41715893705303], + [508813.8819594862, 6651162.931608914, 95.87945304805302], + [508813.6909657572, 6651163.558603514, 95.83412563905301], + [508813.8307652264, 6651163.099669534, 96.22990926305302], + [508813.7713164258, 6651163.294828177, 96.56965429005301], + [508813.62263541395, 6651163.782918502, 96.23607455605301], + [508813.703913204, 6651163.5160996085, 96.895321400053], + [508813.54184320604, 6651164.048143325, 96.61595535805301], + [508813.6290091721, 6651163.761994716, 97.20369020805302], + [508813.47365666134, 6651164.271986252, 96.88236167305303], + [508813.39958200237, 6651164.515158691, 97.13007141305302], + [508813.5472027692, 6651164.03054894, 97.49178855905302], + [508818.26647299883, 6651163.77588621, 91.93688853122363], + [508813.45922180265, 6651164.319373035, 97.75698628405301], + [508813.2928384557, 6651164.865576622, 97.42751388305301], + [508818.0901693312, 6651164.359436262, 91.93688853122363], + [508818.0901693312, 6651164.359436262, 92.06688853122364], + [508813.36590199923, 6651164.625723476, 97.99707473105302], + [508813.1786746405, 6651165.2403538255, 97.68372700605302], + [508813.26816088223, 6651164.946588212, 98.21032706605301], + [508813.05909960857, 6651165.632894982, 97.89600481505302], + [508813.1669686618, 6651165.278782236, 98.39553596805303], + [508812.936185355, 6651166.036398141, 98.06311957205301], + [508818.26647299883, 6651163.77588621, 93.76569219022363], + [508813.0633180202, 6651165.619046772, 98.55202726005301], + [508810.2847485534, 6651174.740540226, 91.90542289905302], + [508812.8119593757, 6651166.444207436, 98.18527269405301], + [508810.2847485534, 6651174.740540226, 92.03542289905302], + [508818.0901693312, 6651164.359436262, 93.76569219022363], + [508812.9581946539, 6651165.9641459705, 98.67965001905301], + [508818.2604111008, 6651163.795950573, 94.23128287722363], + [508810.1071119834, 6651175.323685916, 91.90542289905302], + [508812.68831130594, 6651166.850119569, 98.26394738705301], + [508812.852550249, 6651166.310955635, 98.77874551305301], + [508818.0848205978, 6651164.377140112, 94.17650750222364], + [508818.2414547379, 6651163.8586945115, 94.70855382922363], + [508812.5669209389, 6651167.248620112, 98.30169024605303], + [508812.7124157698, 6651166.770989386, 98.86791016505303], + [508818.06809439516, 6651164.432502412, 94.59762893022365], + [508818.20862620405, 6651163.96735415, 95.19145484922363], + [508812.5748400202, 6651167.222623335, 98.91068540605302], + [508818.03912804177, 6651164.528378562, 95.02371806522363], + [508818.1744840087, 6651164.080361894, 95.55316083422365], + [508810.2847478718, 6651174.740542462, 93.73422655905301], + [508810.28607240994, 6651174.736194265, 93.93804784305303], + [508812.056974457, 6651168.922673453, 98.30169024605303], + [508817.99732998066, 6651164.666726568, 95.44862456922364], + [508818.1320103867, 6651164.220945949, 95.91091868022365], + [508810.1071119834, 6651175.323685916, 93.73422655805301], + [508810.2970706032, 6651174.700089375, 94.35462713105301], + [508817.942449786, 6651164.848375316, 95.86559127122365], + [508810.1132197108, 6651175.303635455, 94.19981724505301], + [508818.08120026474, 6651164.389123105, 96.26137489522364], + [508810.31999625056, 6651174.624829014, 94.77895425105301], + [508810.3555914248, 6651174.507977105, 95.205264602053], + [508810.1323193889, 6651175.240934993, 94.67708819705302], + [508818.0221975404, 6651164.584417073, 96.60111992222363], + [508817.8746321619, 6651165.072845848, 96.26754018822363], + [508811.55762903386, 6651170.561925614, 98.30169024605303], + [508810.40428832907, 6651174.348114808, 95.62707346105303], + [508811.4362386668, 6651170.960426157, 98.26394738705301], + [508810.1653961152, 6651175.132350651, 95.15998921705301], + [508810.46614565584, 6651174.145049451, 96.03742300405301], + [508817.9553000812, 6651164.8058419395, 96.92678703222364], + [508811.3125905971, 6651171.36633829, 98.18527269405301], + [508817.79444618133, 6651165.338254582, 96.64742099022364], + [508810.1997964346, 6651175.019421211, 95.52169520205301], + [508810.5408056448, 6651173.899955488, 96.42920269805303], + [508811.54971063446, 6651170.587920152, 98.91068540605302], + [508811.1883646179, 6651171.774147584, 98.06311957205301], + [508810.60474390205, 6651173.690058848, 96.70668455805301], + [508810.24259116844, 6651174.878934573, 95.87945304805302], + [508811.0654503643, 6651172.177650744, 97.89600481505302], + [508810.67496197246, 6651173.459546825, 96.96712523105302], + [508810.9458753324, 6651172.5701919, 97.68372700605302], + [508810.750853861, 6651173.21040878, 97.20809487705303], + [508810.8317115172, 6651172.944969103, 97.42751388305301], + [508817.8809580943, 6651165.051907552, 97.23515584022365], + [508811.41213488486, 6651171.039554101, 98.86791016505303], + [508817.7267712768, 6651165.562252725, 96.91382730522363], + [508810.29378542834, 6651174.710873954, 96.22990926305302], + [508822.1918849311, 6651164.9449669225, 91.9627256389017], + [508811.27200040565, 6651171.499587852, 98.77874551305301], + [508810.3532342289, 6651174.515715311, 96.56965429005301], + [508811.1663560008, 6651171.846397517, 98.67965001905301], + [508810.4206374507, 6651174.294443878, 96.895321400053], + [508817.7997655288, 6651165.320647997, 97.52325419122363], + [508817.65325243963, 6651165.805593786, 97.16153704522364], + [508811.0612326346, 6651172.191496716, 98.55202726005301], + [508810.4955414826, 6651174.048548771, 97.20369020805302], + [508810.95758199284, 6651172.531761251, 98.39553596805303], + [508810.5773478855, 6651173.779994546, 97.49178855905302], + [508810.85638977255, 6651172.863955278, 98.21032706605301], + [508810.665328852, 6651173.491170452, 97.75698628405301], + [508810.75864865555, 6651173.184820014, 97.99707473105302], + [508817.71244473057, 6651165.609672367, 97.78845191622364], + [508817.5473098471, 6651166.1562547, 97.45897951522365], + [508822.372404784, 6651165.634787478, 91.96506541656744], + [508822.372404784, 6651165.634787478, 92.09506541656745], + [508817.6198251556, 6651165.9162352355, 98.02854036322364], + [508817.4340026641, 6651166.53129178, 97.71519263822364], + [508817.52281744266, 6651166.237322463, 98.24179269822363], + [508822.1918849311, 6651164.9449669225, 93.7915292979017], + [508817.31532486784, 6651166.92410513, 97.92747044722366], + [508817.4223845218, 6651166.569746836, 98.42700160022363], + [508817.1933329059, 6651167.327888085, 98.09458520422365], + [508822.1980917954, 6651164.968685214, 94.25720045849617], + [508817.31951162644, 6651166.9102473175, 98.58349289222363], + [508814.5617912562, 6651176.038065758, 91.93688853122363], + [508817.0700390607, 6651167.7359801615, 98.21673832622365], + [508814.5617912562, 6651176.038065758, 92.06688853122364], + [508822.372404784, 6651165.634787478, 93.79386907556744], + [508817.2151770572, 6651167.255585814, 98.71111565122364], + [508822.2175014869, 6651165.042855473, 94.73472305094654], + [508814.38548758865, 6651176.62161581, 91.93688853122363], + [508816.94731878873, 6651168.142173761, 98.29541301922363], + [508817.110325359, 6651167.602635962, 98.81021114522363], + [508822.37788142887, 6651165.655715382, 94.20475534924105], + [508816.82683927874, 6651168.540950629, 98.33315587822364], + [508822.25111509353, 6651165.171303156, 95.21805982046632], + [508816.9712423839, 6651168.062988708, 98.89937579722364], + [508822.39500762743, 6651165.721159728, 94.62609867514391], + [508816.8346989389, 6651168.514935827, 98.94215103822366], + [508822.2860737768, 6651165.30489078, 95.5802189378769], + [508822.4246666921, 6651165.834495918, 95.0525720605858], + [508814.5617905797, 6651176.038067996, 93.76569219122364], + [508814.56310517923, 6651176.033716784, 93.96951347522364], + [508816.3207191986, 6651170.216164784, 98.33315587822364], + [508822.32956312713, 6651165.471076645, 95.93854041346947], + [508814.38548758865, 6651176.62161581, 93.76569219022363], + [508822.4674643263, 6651165.998038527, 95.47803296306158], + [508814.57402084715, 6651175.9975868575, 94.38609276322363], + [508814.39154948655, 6651176.601551446, 94.23128287722363], + [508822.38158834004, 6651165.669880602, 96.2896707724538], + [508814.5967744711, 6651175.92227431, 94.81041988322364], + [508814.6321025556, 6651175.805341372, 95.23673023422363], + [508814.41050584946, 6651176.538807507, 94.70855382922363], + [508822.52365694434, 6651166.212767391, 95.89572745636704], + [508815.825120632, 6651171.85655363, 98.33315587822364], + [508822.4420020749, 6651165.900739621, 96.63019848922737], + [508814.6804340608, 6651175.645368226, 95.65853909322364], + [508815.7046411219, 6651172.255330498, 98.29541301922363], + [508814.4433343833, 6651176.430147869, 95.19145484922363], + [508814.741827239, 6651175.442162061, 96.06888863622363], + [508815.58192085003, 6651172.661524097, 98.21673832622365], + [508814.47747657873, 6651176.317140124, 95.55316083422365], + [508815.8172616486, 6651171.882566192, 98.94215103822366], + [508814.815927014, 6651175.196898146, 96.46066833022364], + [508815.4586270048, 6651173.069616174, 98.09458520422365], + [508822.59309638164, 6651166.47811633, 96.29857553761954], + [508814.8793855082, 6651174.9868559595, 96.73815019022364], + [508815.33663504286, 6651173.473399128, 97.92747044722366], + [508814.51995020075, 6651176.176556069, 95.91091868022365], + [508814.9490766948, 6651174.756184096, 96.99859086322364], + [508822.51049934304, 6651166.162488246, 96.95675281647692], + [508815.2179572465, 6651173.866212479, 97.71519263822364], + [508815.0243991258, 6651174.506873295, 97.23956050922365], + [508815.1046500636, 6651174.241249558, 97.45897951522365], + [508815.68071820354, 6651172.33451331, 98.89937579722364], + [508814.5707603226, 6651176.008378915, 96.26137489522364], + [508815.5416352285, 6651172.794866056, 98.81021114522363], + [508814.62976304704, 6651175.813084945, 96.60111992222363], + [508815.4367835303, 6651173.141916205, 98.71111565122364], + [508814.69666050636, 6651175.59166008, 96.92678703222364], + [508815.332448961, 6651173.487254701, 98.58349289222363], + [508814.77100249304, 6651175.345594465, 97.23515584022365], + [508822.6751999569, 6651166.791858739, 96.67951921077417], + [508815.22957606567, 6651173.827755182, 98.42700160022363], + [508814.85219505866, 6651175.076854022, 97.52325419122363], + [508822.5866191689, 6651166.453364954, 97.26610732601614], + [508815.1291431448, 6651174.160179555, 98.24179269822363], + [508814.93951585685, 6651174.7878296515, 97.78845191622364], + [508815.0321354318, 6651174.4812667845, 98.02854036322364], + [508822.7444932617, 6651167.056649261, 96.94682232590775], + [508822.6697534008, 6651166.771045813, 97.55528191281114], + [508822.81977025385, 6651167.344305247, 97.19550606296447], + [508822.75916241796, 6651167.112704511, 97.82163675876285], + [508822.9282463929, 6651167.758825142, 97.49435164092193], + [508822.8539969291, 6651167.475095649, 98.06295215031385], + [508823.04426324216, 6651168.202160354, 97.75206482426465], + [508822.9533245171, 6651167.854656183, 98.27748912713014], + [508823.0561592244, 6651168.247618474, 98.46402756333227], + [508823.16577913926, 6651168.666509079, 97.96591314708884], + [508823.1614922571, 6651168.650127616, 98.62188019819675], + [508823.2906884579, 6651169.143825087, 98.13464158568678], + [508823.2683219183, 6651169.058355824, 98.75088313467333], + [508823.41693079384, 6651169.626234953, 98.25842490002799], + [508823.37568107556, 6651169.468607395, 98.85136513173755], + [508823.5425858402, 6651170.106400609, 98.33872149297953], + [508823.51809012797, 6651170.012795139, 98.94236814657671], + [508823.6659465378, 6651170.577798871, 98.37805595023299], + [508823.6578989189, 6651170.547046503, 98.9869473007037], + [508824.18417014414, 6651172.558086854, 98.38473463639099], + [508832.95745439094, 6651168.151208672, 92.03358474417486], + [508832.78575921635, 6651168.736131243, 92.03358474417486], + [508832.78575921635, 6651168.736131243, 92.16358474417487], + [508832.95745439094, 6651168.151208672, 93.86238840317486], + [508832.78575921635, 6651168.736131243, 93.86238840317486], + [508832.9515509481, 6651168.171320227, 94.32797909017485], + [508832.78055029624, 6651168.753876733, 94.27320371517484], + [508824.6916206219, 6651174.49720748, 98.3912628763363], + [508832.93309009535, 6651168.23421174, 94.80525004217485], + [508832.7642613085, 6651168.809369245, 94.69432514317485], + [508834.91805535817, 6651168.725594205, 92.04507518621509], + [508832.9011196836, 6651168.343126947, 95.28815106217486], + [508824.6996675483, 6651174.5279572, 99.000361465957], + [508824.81498131994, 6651174.968605742, 98.35510529410794], + [508832.73605212156, 6651168.905470898, 95.12041427817485], + [508834.746975215, 6651169.310696958, 92.04507518621509], + [508825.9851616828, 6651179.440216226, 92.01158491380276], + [508834.746975215, 6651169.310696958, 92.1750751862151], + [508832.8678699487, 6651168.4564004885, 95.64985704717485], + [508825.9851616828, 6651179.440216226, 92.14158491380277], + [508824.94063636544, 6651175.448771397, 98.27804466653393], + [508832.69534664176, 6651169.044144301, 95.54532078217485], + [508824.83947633876, 6651175.062208563, 98.95938277082355], + [508832.8265065667, 6651168.597315199, 96.00761489317485], + [508825.06687870115, 6651175.931181262, 98.15751244752472], + [508832.6419009889, 6651169.22622029, 95.96228748417485], + [508826.16568153584, 6651180.130036781, 92.01389415230373], + [508832.777024597, 6651168.76588791, 96.35807110817487], + [508824.9818853913, 6651175.606396307, 98.87204718498923], + [508834.91805535817, 6651168.725594205, 93.87387884521509], + [508825.1917880205, 6651176.408497271, 97.99200078177701], + [508832.71956417535, 6651168.961641212, 96.69781613517486], + [508832.5758560848, 6651169.451218779, 96.36423640117485], + [508825.08924454823, 6651176.016647878, 98.77432998960177], + [508834.746975215, 6651169.310696958, 93.87387884521509], + [508834.91217306204, 6651168.745711955, 94.3394695322151], + [508825.98516237503, 6651179.440218871, 93.84038858266251], + [508825.3133039177, 6651176.872845997, 97.7812818484891], + [508832.65441538347, 6651169.183586872, 97.02348324517484], + [508825.983816338, 6651179.43507526, 94.04419264253698], + [508832.4977661271, 6651169.717251758, 96.74411720317487], + [508825.1960742097, 6651176.424876087, 98.6480782236168], + [508834.7417849538, 6651169.328447915, 94.28469415721509], + [508834.8937783383, 6651168.808622842, 94.81674048421509], + [508825.42932076653, 6651177.316181207, 97.52655644535326], + [508825.9726396292, 6651179.3923657, 94.46062890832961], + [508832.5820166604, 6651169.430231238, 97.33185205317486], + [508832.43186021206, 6651169.941776749, 97.01052351817485], + [508825.3014072421, 6651176.827385227, 98.49293822201905], + [508825.51149085234, 6651177.6301777745, 97.30819077092062], + [508834.72555431514, 6651169.383957521, 94.70581558521509], + [508825.9493418676, 6651179.303337958, 94.8846578819189], + [508825.5886145694, 6651177.924890652, 97.06820949544128], + [508826.16568153584, 6651180.130036781, 93.84269781130374], + [508834.8619224481, 6651168.9175716, 95.29964150421509], + [508825.91316893493, 6651179.165110323, 95.31050527267823], + [508825.6599723748, 6651178.197570249, 96.8086830660119], + [508825.40424195013, 6651177.22034752, 98.30904808548469], + [508832.5029464295, 6651169.699603763, 97.61995040417486], + [508832.3602631219, 6651170.18569015, 97.25823325817485], + [508825.8636816144, 6651178.976004412, 95.73168067320069], + [508825.72494843695, 6651178.44586329, 96.5320334900092], + [508825.80082025914, 6651178.735792302, 96.14122540835535], + [508834.69744617667, 6651169.480088778, 95.13190472021509], + [508826.1594746717, 6651180.106318489, 94.30820912300204], + [508834.8287918175, 6651169.030880034, 95.66134748921509], + [508825.503569538, 6651177.599908054, 98.09706909526902], + [508832.4179081549, 6651169.989307922, 97.88514812917485], + [508832.25708981766, 6651170.537175825, 97.55567572817485], + [508825.5984040485, 6651177.962299191, 97.85819598559807], + [508826.1400649798, 6651180.032148229, 94.78523184687617], + [508834.6568865084, 6651169.618804897, 95.5568112242151], + [508834.7875766038, 6651169.171838152, 96.01910533521509], + [508825.68781306606, 6651178.303957889, 97.59414370370696], + [508826.106451373, 6651179.903700546, 95.26770294731547], + [508832.327709611, 6651170.29659183, 98.12523657617486], + [508825.770947298, 6651178.621638748, 97.30711009047509], + [508826.07149269, 6651179.770112922, 95.62896175624135], + [508832.1467444299, 6651170.913094997, 97.81188885117486], + [508825.8470671244, 6651178.912515458, 96.99971591547958], + [508826.02800333954, 6651179.603927057, 95.98616323029663], + [508834.60363230394, 6651169.800936973, 95.97377792621509], + [508825.91556439176, 6651179.174264081, 96.67492562078117], + [508834.738271884, 6651169.340462791, 96.3695615502151], + [508825.9759781274, 6651179.4051231025, 96.33595376183395], + [508832.23323763296, 6651170.618434261, 98.33848891117486], + [508832.0311688141, 6651171.30683225, 98.02416666017486], + [508834.68101729214, 6651169.536276395, 96.70930657721509], + [508834.53782398015, 6651170.026004774, 96.3757268432151], + [508832.1354299803, 6651170.951640502, 98.52369781317485], + [508831.91236566316, 6651171.711564909, 98.19128141717485], + [508834.61610187055, 6651169.758290425, 97.0349736872151], + [508832.0352461329, 6651171.292941844, 98.68018910517485], + [508834.46001374954, 6651170.292119702, 96.7556076452151], + [508831.7922946598, 6651172.120616824, 98.31343453917485], + [508829.349611245, 6651180.442229048, 92.03358474417486], + [508831.93363881897, 6651171.639092581, 98.80781186417487], + [508829.349611245, 6651180.442229048, 92.16358474417487], + [508834.5439624879, 6651170.005010765, 97.34334249521511], + [508834.39434391685, 6651170.516713856, 97.02201396021509], + [508831.6727822367, 6651172.5277657965, 98.39210923217486], + [508829.1779160704, 6651181.02715162, 92.03358474417486], + [508831.83152789366, 6651171.986958997, 98.90690735817486], + [508834.46517549537, 6651170.27446627, 97.63144084621509], + [508834.3230032955, 6651170.760702394, 97.2697237002151], + [508831.555452003, 6651172.927480595, 98.42985209117485], + [508831.6960804805, 6651172.448394501, 98.99607201017487], + [508834.38044183754, 6651170.564259672, 97.8966385712151], + [508834.22019956965, 6651171.112296342, 97.56716617021509], + [508831.5631062154, 6651172.901404604, 99.03884725117486], + [508834.2905663949, 6651170.871638236, 98.1367270182151], + [508834.1102494516, 6651171.488331314, 97.82337929321511], + [508829.3496105863, 6651180.442231293, 93.86238840417485], + [508831.06256165804, 6651174.606634879, 98.42985209117485], + [508829.3508908227, 6651180.437869848, 94.06620968817485], + [508834.19643282617, 6651171.193579809, 98.34997935321509], + [508829.1779160704, 6651181.02715162, 93.86238840317486], + [508833.9950878406, 6651171.882189856, 98.0356571022151], + [508829.36152116035, 6651180.401654943, 94.48278897617486], + [508834.0989755315, 6651171.526888691, 98.53518825521509], + [508829.18381951324, 6651181.007040066, 94.32797909017485], + [508833.87671025604, 6651172.28704719, 98.2027718592151], + [508829.3836800155, 6651180.326165258, 94.90711609617485], + [508833.9991505539, 6651171.868295171, 98.69167954721509], + [508829.4180846409, 6651180.208957293, 95.33342644717486], + [508829.202280366, 6651180.944148551, 94.80525004217485], + [508833.75706936046, 6651172.696225111, 98.3249249812151], + [508830.57991779933, 6651176.250881943, 98.42985209117485], + [508831.32313591294, 6651181.020400761, 92.04507518621509], + [508833.89790720894, 6651172.214552538, 98.81930230621509], + [508831.32313591294, 6651181.020400761, 92.1750751862151], + [508829.4651527839, 6651180.048607889, 95.75523530617485], + [508830.46258756565, 6651176.650596741, 98.39210923217486], + [508829.23425077775, 6651180.835233344, 95.28815106217486], + [508833.63798504433, 6651173.103499503, 98.40359967421509], + [508829.52494117385, 6651179.844923778, 96.16558484917485], + [508833.7961620564, 6651172.5625261115, 98.91839780021509], + [508830.3430751425, 6651177.057745712, 98.31343453917485], + [508831.15205576975, 6651181.605503514, 92.04507518621509], + [508829.26750051265, 6651180.721959803, 95.64985704717485], + [508830.57226424594, 6651176.276955688, 99.03884725117486], + [508829.5971040165, 6651179.599082999, 96.55736454317487], + [508830.2230041391, 6651177.4667976275, 98.19128141717485], + [508833.52107510075, 6651173.503337431, 98.44134253321509], + [508829.6589037362, 6651179.388546792, 96.83484640317485], + [508830.1042009882, 6651177.871530287, 98.02416666017486], + [508829.3088638946, 6651180.581045093, 96.00761489317485], + [508829.7267732288, 6651179.157332383, 97.09528707617486], + [508829.98862537235, 6651178.265267541, 97.81188885117486], + [508833.66119983123, 6651173.024103756, 99.0075624522151], + [508829.80012676766, 6651178.907435199, 97.33625672217485], + [508830.4392899808, 6651176.729965792, 98.99607201017487], + [508829.8782799847, 6651178.641186711, 97.55567572817485], + [508829.35834586434, 6651180.412472383, 96.35807110817487], + [508830.30384256766, 6651177.191401295, 98.90690735817486], + [508829.415806286, 6651180.216719079, 96.69781613517486], + [508833.528701895, 6651173.477253408, 99.05033769321511], + [508830.20173164236, 6651177.53926771, 98.80781186417487], + [508829.48095507786, 6651179.9947734205, 97.02348324517484], + [508830.1001243285, 6651177.885418449, 98.68018910517485], + [508829.5533538009, 6651179.748129055, 97.33185205317486], + [508829.9999404811, 6651178.22671979, 98.52369781317485], + [508829.63242403185, 6651179.478756529, 97.61995040417486], + [508829.9021328284, 6651178.559926032, 98.33848891117486], + [508829.71746230655, 6651179.18905237, 97.88514812917485], + [508829.80766085035, 6651178.881768462, 98.12523657617486], + [508831.32313525653, 6651181.020403006, 93.8738788462151], + [508833.0299503446, 6651175.183008968, 98.44134253321509], + [508831.324410907, 6651181.016040216, 94.07770013021509], + [508831.15205576975, 6651181.605503514, 93.87387884521509], + [508831.3350031655, 6651180.979814156, 94.49427941821509], + [508831.1579380658, 6651181.585385765, 94.3394695322151], + [508831.3570826452, 6651180.904301217, 94.91860653821509], + [508831.3913640293, 6651180.787057147, 95.34491688921509], + [508831.17633278965, 6651181.522474877, 94.81674048421509], + [508832.54903537047, 6651176.827762534, 98.44134253321509], + [508831.4382635689, 6651180.6266583465, 95.7667257482151], + [508832.4321254269, 6651177.227600462, 98.40359967421509], + [508831.2081886798, 6651181.413526119, 95.29964150421509], + [508831.49783779023, 6651180.422911493, 96.1770752912151], + [508832.31304111076, 6651177.634874854, 98.3249249812151], + [508831.2413193104, 6651181.300217684, 95.66134748921509], + [508832.54140923294, 6651176.85384431, 99.05033769321511], + [508831.56974213733, 6651180.176994984, 96.5688549852151], + [508832.1934002152, 6651178.044052775, 98.2027718592151], + [508831.6313204835, 6651179.966393922, 96.8463368452151], + [508832.0750226306, 6651178.44891011, 98.0356571022151], + [508831.2825345241, 6651181.159259568, 96.01910533521509], + [508831.69894685986, 6651179.735108291, 97.10677751821511], + [508831.9598610196, 6651178.842768651, 97.82337929321511], + [508831.77203763823, 6651179.485134127, 97.3477471642151], + [508832.4089112967, 6651177.306993962, 99.0075624522151], + [508831.84991090157, 6651179.218803623, 97.56716617021509], + [508831.33183924394, 6651180.990634928, 96.3695615502151], + [508832.27394907153, 6651177.768571609, 98.91839780021509], + [508831.3890938358, 6651180.794821326, 96.70930657721509], + [508832.172203919, 6651178.116545183, 98.81930230621509], + [508831.4540092573, 6651180.572807295, 97.0349736872151], + [508832.07096057397, 6651178.462802549, 98.69167954721509], + [508831.52614863997, 6651180.326086953, 97.34334249521511], + [508831.9711355964, 6651178.804209027, 98.53518825521509], + [508831.60493563255, 6651180.056631449, 97.63144084621509], + [508831.87367830175, 6651179.137517911, 98.34997935321509], + [508831.6896692904, 6651179.766838048, 97.8966385712151], + [508831.779544733, 6651179.459459483, 98.1367270182151], + [508851.61321885866, 6651173.526252328, 92.12950105420167], + [508851.44737591106, 6651174.112861025, 92.12950105420167], + [508851.95411219, 6651173.622594357, 92.13097546765042], + [508851.44737591106, 6651174.112861025, 92.25950105420169], + [508851.7883761792, 6651174.209233276, 92.13097546765042], + [508851.7883761792, 6651174.209233276, 92.26097546765041], + [508851.61321885866, 6651173.526252328, 93.95830471320168], + [508851.44737591106, 6651174.112861025, 93.95830471320168], + [508851.6075166345, 6651173.546421858, 94.42389540020167], + [508851.95411219, 6651173.622594357, 93.9597791266504], + [508851.442344537, 6651174.130657669, 94.36912002520167], + [508851.58968501963, 6651173.609494666, 94.90116635220167], + [508851.7883761792, 6651174.209233276, 93.9597791266504], + [508851.9484136427, 6651173.642764926, 94.4253698136504], + [508851.4266107591, 6651174.186310148, 94.79024145320167], + [508851.78334804927, 6651174.227030836, 94.3705944386504], + [508851.9305935258, 6651173.705840983, 94.90264076565042], + [508851.55880431883, 6651173.718723837, 95.38406737220168], + [508851.3993630818, 6651174.282688828, 95.21633058820167], + [508851.7676244167, 6651174.282686182, 94.7917158666504], + [508851.5266879006, 6651173.832323905, 95.74577335720167], + [508851.8997327371, 6651173.815075781, 95.3855417856504], + [508851.3600450476, 6651174.421761977, 95.64123709220168], + [508851.7403943089, 6651174.3790698275, 95.2178050016504], + [508851.48673438875, 6651173.973644823, 96.10353120320167], + [508851.86763702775, 6651173.928681702, 95.7472477706504], + [508851.3084210889, 6651174.604362826, 96.05820379420167], + [508851.7011016271, 6651174.5181501405, 95.64271150565042], + [508851.43893901113, 6651174.14270347, 96.45398741820169], + [508851.8277092782, 6651174.070009902, 96.1050056166504], + [508851.38343712705, 6651174.339021062, 96.79373244520168], + [508851.6495109559, 6651174.700760398, 96.0596782076504], + [508851.24462732434, 6651174.8300099075, 96.46015271120167], + [508851.77994471934, 6651174.239077259, 96.45546183165041], + [508851.3205089306, 6651174.561606512, 97.11939955520167], + [508851.72447862325, 6651174.435404963, 96.7952068586504], + [508851.585758326, 6651174.926419106, 96.4616271246504], + [508851.1691990614, 6651175.096809767, 96.84003351320169], + [508851.25057791674, 6651174.808961867, 97.42776836320168], + [508851.66159100324, 6651174.658001883, 97.1208739686504], + [508851.1055395483, 6651175.321981983, 97.10643982820167], + [508851.5103786998, 6651175.1932327105, 96.84150792665041], + [508851.1742027932, 6651175.079110898, 97.71586671420168], + [508851.0363828438, 6651175.566598503, 97.35414956820169], + [508851.59170508146, 6651174.905369979, 97.42924277665041], + [508851.4467602348, 6651175.418416529, 97.10791424165042], + [508851.09206304676, 6651175.369650174, 97.98106443920167], + [508851.5153792052, 6651175.17553293, 97.71734112765041], + [508851.3776481229, 6651175.6630456485, 97.35562398165041], + [508850.93672619987, 6651175.919097387, 97.65159203820167], + [508851.0049389187, 6651175.677819872, 98.22115288620168], + [508851.43329242297, 6651175.466087173, 97.9825388526504], + [508850.8301419328, 6651176.296100203, 97.90780516120168], + [508851.2780557383, 6651176.0155626945, 97.6530664516504], + [508850.9136870164, 6651176.000590063, 98.43440522120169], + [508851.3462244732, 6651175.774272749, 98.22262729965041], + [508850.7185057098, 6651176.690972462, 98.12008297020168], + [508851.1715401975, 6651176.392584933, 97.90927957465041], + [508850.8192131359, 6651176.334756819, 98.61961412320167], + [508851.2550314107, 6651176.097059567, 98.4358796346504], + [508850.6037519623, 6651177.096871823, 98.28719772720167], + [508851.0599759584, 6651176.787477536, 98.12155738365041], + [508850.7224440532, 6651176.677042015, 98.77610541520167], + [508851.16061844764, 6651176.431243542, 98.62108853665042], + [508850.48777357704, 6651177.50710289, 98.40935084920167], + [508850.9452962049, 6651177.193397809, 98.2886721406504], + [508850.6243000229, 6651177.024190582, 98.90372817420169], + [508848.12834898476, 6651185.8527034, 92.12950105420167], + [508851.06391176226, 6651176.773546371, 98.7775798286504], + [508848.12834898476, 6651185.8527034, 92.25950105420169], + [508850.37233473273, 6651177.91542553, 98.48802554220168], + [508850.52566954674, 6651177.373059775, 99.00282366820169], + [508850.82939260313, 6651177.603650013, 98.4108252626504], + [508847.96250603726, 6651186.439312099, 92.12950105420167], + [508850.9658310159, 6651177.120712824, 98.90520258765041], + [508850.25900369807, 6651178.316292565, 98.52576840120167], + [508848.4714893839, 6651185.949680488, 92.13097546765042], + [508848.4714893839, 6651185.949680488, 92.26097546765041], + [508850.39483885636, 6651177.835825434, 99.0919883202017], + [508850.71402819466, 6651178.0119936885, 98.48949995565042], + [508850.8672641373, 6651177.46959999, 99.0042980816504], + [508848.3057533731, 6651186.536319407, 92.13097546765042], + [508850.60077023663, 6651178.412881376, 98.52724281465042], + [508850.2663970168, 6651178.290141408, 99.13476356120168], + [508850.7365178075, 6651177.932389491, 99.09346273365043], + [508850.6081587881, 6651178.386728871, 99.13623797465041], + [508848.1283483484, 6651185.852705651, 93.95830471420167], + [508849.78291351214, 6651180.000287262, 98.52576840120167], + [508848.129584948, 6651185.848331632, 94.16212599820167], + [508847.96250603726, 6651186.439312099, 93.95830471320168], + [508848.471488748, 6651185.949682738, 93.9597791276504], + [508848.1398529508, 6651185.8120123325, 94.57870528620168], + [508850.1249870369, 6651180.096962831, 98.52724281465042], + [508848.4727245503, 6651185.945308494, 94.16360041165042], + [508847.9682082613, 6651186.419142568, 94.42389540020167], + [508848.1612565217, 6651185.736305038, 95.00303240620167], + [508848.3057533731, 6651186.536319407, 93.9597791266504], + [508848.4829859321, 6651185.908987324, 94.5801796996504], + [508848.194488466, 6651185.618759204, 95.42934275720168], + [508849.3167205611, 6651181.649274113, 98.52576840120167], + [508847.9860398761, 6651186.35606976, 94.90116635220167], + [508848.31145192037, 6651186.516148837, 94.4253698136504], + [508848.50437570194, 6651185.833276128, 95.0045068196504], + [508849.2033895264, 6651182.050141148, 98.48802554220168], + [508848.2399522922, 6651185.457947567, 95.85115161620168], + [508848.016920577, 6651186.246840589, 95.38406737220168], + [508849.0879506822, 6651182.458463787, 98.40935084920167], + [508848.2977027959, 6651185.253676308, 96.26150115920167], + [508848.5375862181, 6651185.715724237, 95.4308171706504], + [508849.6590946902, 6651181.746034639, 98.52724281465042], + [508848.32927203726, 6651186.45307278, 94.90264076565042], + [508849.309327879, 6651181.675423019, 99.13476356120168], + [508848.0490369952, 6651186.13324052, 95.74577335720167], + [508848.97197229695, 6651182.868694855, 98.28719772720167], + [508848.36740596924, 6651185.007126857, 96.6532808532017], + [508849.5458367322, 6651182.146922327, 98.48949995565042], + [508848.5830207288, 6651185.554904317, 95.85262602965042], + [508848.42709924665, 6651184.795983747, 96.93076271320167], + [508848.85721854947, 6651183.274594216, 98.12008297020168], + [508848.4926554087, 6651184.5641028285, 97.19120338620168], + [508849.1808860394, 6651182.129738993, 99.0919883202017], + [508848.08899050707, 6651185.991919602, 96.10353120320167], + [508848.74558232643, 6651183.669466475, 97.90780516120168], + [508848.56350869354, 6651184.31348528, 97.43217303220167], + [508848.3601328261, 6651186.343837982, 95.3855417856504], + [508848.6389980594, 6651184.046469292, 97.65159203820167], + [508849.43047232373, 6651182.555266002, 98.4108252626504], + [508848.6407339946, 6651185.350622532, 96.2629755726504], + [508848.1367858848, 6651185.822860955, 96.45398741820169], + [508849.65170677495, 6651181.772184892, 99.13623797465041], + [508849.0500553491, 6651182.592504652, 99.00282366820169], + [508848.3922285353, 6651186.230232061, 95.7472477706504], + [508849.3145687221, 6651182.965518205, 98.2886721406504], + [508848.7103922229, 6651185.10406038, 96.65475526665043], + [508848.1922877689, 6651185.626543365, 96.79373244520168], + [508848.9514248729, 6651182.941373844, 98.90372817420169], + [508848.7700470097, 6651184.892906391, 96.9322371266504], + [508849.1998889686, 6651183.371438478, 98.12155738365041], + [508848.8355609006, 6651184.661013527, 97.19267779965041], + [508849.52334775554, 6651182.226524273, 99.09346273365043], + [508848.25521596527, 6651185.403957913, 97.11939955520167], + [508848.4321562849, 6651186.088903861, 96.1050056166504], + [508849.08832472935, 6651183.766331081, 97.90927957465041], + [508848.85328084254, 6651183.288522412, 98.77610541520167], + [508848.90636849875, 6651184.410383065, 97.43364744565042], + [508848.98180918855, 6651184.14335332, 97.6530664516504], + [508848.32514697907, 6651185.15660256, 97.42776836320168], + [508848.7565117599, 6651183.6308076065, 98.61961412320167], + [508848.4015221026, 6651184.886453527, 97.71586671420168], + [508848.6620378794, 6651183.964974364, 98.43440522120169], + [508848.47992084373, 6651185.919836504, 96.45546183165041], + [508848.48366184905, 6651184.595914254, 97.98106443920167], + [508848.5707859771, 6651184.287744553, 98.22115288620168], + [508849.39260142576, 6651182.689313772, 99.0042980816504], + [508848.53538693994, 6651185.7235088, 96.7952068586504], + [508849.2940345472, 6651183.038200939, 98.90520258765041], + [508848.59827455983, 6651185.500911881, 97.1208739686504], + [508849.1959538008, 6651183.385367393, 98.7775798286504], + [508848.66816048155, 6651185.253543783, 97.42924277665041], + [508849.09924711543, 6651183.727670222, 98.62108853665042], + [508848.7444863579, 6651184.983380833, 97.71734112765041], + [508849.00483415235, 6651184.061854195, 98.4358796346504], + [508848.82657314016, 6651184.69282659, 97.9825388526504], + [508848.91364108986, 6651184.384641014, 98.22262729965041], + [508862.9688786647, 6651176.682449538, 92.17073826452479], + [508862.8065979349, 6651177.270048321, 92.17073826452386], + [508862.8065979349, 6651177.270048321, 92.30073826452386], + [508862.9688786647, 6651176.682449538, 93.99954192352479], + [508862.8065979349, 6651177.270048321, 93.99954192352385], + [508862.96329892095, 6651176.702653111, 94.46513261052354], + [508862.8016746321, 6651177.287875001, 94.41035723552457], + [508862.94585031964, 6651176.765832375, 94.94240356252364], + [508862.7862788074, 6651177.34362141, 94.83147866352425], + [508862.91563292, 6651176.875245904, 95.42530458252438], + [508862.7596163956, 6651177.440162759, 95.25756779852415], + [508862.88420634513, 6651176.989037707, 95.78701056752352], + [508862.7211428919, 6651177.579470636, 95.68247430252461], + [508862.8451110138, 6651177.130597148, 96.14476841352497], + [508862.6706277882, 6651177.762379683, 96.0994410045242], + [508862.79834225506, 6651177.299941134, 96.49522462852435], + [508862.74403252196, 6651177.496590071, 96.83496965552457], + [508862.60820427974, 6651177.988407616, 96.5013899215247], + [508862.6824559892, 6651177.719551206, 97.1606367655234], + [508862.5343961757, 6651178.255657782, 96.88127072352452], + [508862.61402705655, 6651177.967324047, 97.46900557352438], + [508862.4721040347, 6651178.481210046, 97.14767703852353], + [508862.5392924299, 6651178.237929041, 97.75710392452419], + [508862.40443277935, 6651178.726239431, 97.39538677852407], + [508862.4589170015, 6651178.52895869, 98.02230164952486], + [508862.3069167071, 6651179.079333268, 97.69282924852448], + [508862.373664253, 6651178.837648522, 98.26239009652396], + [508862.20262181305, 6651179.456972391, 97.94904237152416], + [508862.2843723933, 6651179.160963486, 98.47564243152547], + [508862.0933834768, 6651179.852511121, 98.16132018052465], + [508862.19192776096, 6651179.495694254, 98.6608513335243], + [508861.9810945786, 6651180.259095563, 98.32843493752496], + [508862.0972372265, 6651179.83855716, 98.81734262552403], + [508861.86760734697, 6651180.670019024, 98.45058805952459], + [508862.0012012777, 6651180.186291651, 98.94496538452462], + [508859.55886193557, 6651189.029705328, 92.17073826452425], + [508859.55886193557, 6651189.029705328, 92.30073826452426], + [508861.7546480673, 6651181.079030836, 98.52926275252398], + [508861.90468933166, 6651180.535749668, 99.04406087852502], + [508859.3965812058, 6651189.617304111, 92.17073826452334], + [508861.6437513231, 6651181.480574457, 98.56700561152488], + [508861.77666881424, 6651180.999296389, 99.1332255305231], + [508861.6509858372, 6651181.454379161, 99.17600077152467], + [508861.1778873002, 6651183.167411417, 98.56700561152469], + [508859.5588613128, 6651189.029707583, 93.99954192452388], + [508859.560071351, 6651189.025326181, 94.20336320852385], + [508859.3965812058, 6651189.617304111, 93.99954192352334], + [508859.5701188026, 6651188.988945583, 94.61994249652426], + [508859.4021609492, 6651189.597100538, 94.4651326105235], + [508859.5910626361, 6651188.913110508, 95.0442696165235], + [508860.72170792485, 6651184.819181446, 98.56700561152454], + [508859.62358077615, 6651188.795366278, 95.47057996752416], + [508859.41960955085, 6651189.533921274, 94.9424035625245], + [508860.61081118044, 6651185.220725069, 98.52926275252486], + [508859.6680680638, 6651188.634283222, 95.89238882652492], + [508859.44982695085, 6651189.424507746, 95.42530458252482], + [508860.49785190076, 6651185.62973688, 98.45058805952424], + [508859.7245781173, 6651188.429667191, 96.30273836952409], + [508860.7144740336, 6651184.845374487, 99.17600077152454], + [508860.38436466956, 6651186.04066034, 98.32843493752495], + [508859.48125352524, 6651189.310715942, 95.78701056752408], + [508859.7927841038, 6651188.182701611, 96.69451806352455], + [508860.272075771, 6651186.447244784, 98.16132018052417], + [508859.8511952015, 6651187.971202131, 96.9719999235248], + [508860.5887910561, 6651185.300457261, 99.1332255305245], + [508859.915343252, 6651187.738929843, 97.23244059652424], + [508860.1628374343, 6651186.842783513, 97.94904237152357], + [508859.52034885704, 6651189.169156501, 96.14476841352425], + [508859.98467464594, 6651187.487889298, 97.47341024252378], + [508860.05854254065, 6651187.220422637, 97.69282924852436], + [508859.5671176157, 6651188.9998125145, 96.49522462852485], + [508860.4607705393, 6651185.76400398, 99.0440608785247], + [508859.62142734893, 6651188.803163578, 96.83496965552462], + [508860.36425859306, 6651186.113461998, 98.94496538452458], + [508860.2682226441, 6651186.461196488, 98.81734262552462], + [508859.68300388084, 6651188.5802024435, 97.1606367655231], + [508860.1735321096, 6651186.804059395, 98.66085133352439], + [508859.75143281405, 6651188.332429601, 97.46900557352427], + [508860.0810874778, 6651187.138790161, 98.4756424315248], + [508859.82616744086, 6651188.061824608, 97.75710392452501], + [508859.99179561756, 6651187.462105127, 98.26239009652473], + [508859.9065428696, 6651187.770794958, 98.02230164952542] + ], + "pointIndex": [ + 54, + 60, + 84, + 77, + 0, + 60, + 78, + 117, + 84, + 0, + 78, + 85, + 126, + 117, + 0, + 85, + 90, + 133, + 126, + 0, + 90, + 96, + 137, + 133, + 0, + 96, + 100, + 140, + 137, + 0, + 100, + 105, + 143, + 140, + 0, + 105, + 115, + 152, + 143, + 0, + 115, + 118, + 154, + 152, + 0, + 118, + 122, + 156, + 154, + 0, + 122, + 124, + 158, + 156, + 0, + 124, + 127, + 160, + 158, + 0, + 127, + 129, + 162, + 160, + 0, + 129, + 132, + 164, + 162, + 0, + 132, + 131, + 163, + 164, + 0, + 131, + 128, + 161, + 163, + 0, + 128, + 125, + 159, + 161, + 0, + 125, + 123, + 157, + 159, + 0, + 123, + 121, + 155, + 157, + 0, + 121, + 116, + 153, + 155, + 0, + 116, + 108, + 146, + 153, + 0, + 108, + 72, + 103, + 146, + 0, + 72, + 70, + 97, + 103, + 0, + 70, + 66, + 92, + 97, + 0, + 66, + 62, + 88, + 92, + 0, + 62, + 58, + 83, + 88, + 0, + 58, + 53, + 76, + 83, + 0, + 53, + 49, + 71, + 76, + 0, + 49, + 45, + 68, + 71, + 0, + 45, + 41, + 63, + 68, + 0, + 41, + 38, + 59, + 63, + 0, + 38, + 33, + 51, + 59, + 0, + 33, + 29, + 47, + 51, + 0, + 29, + 25, + 43, + 47, + 0, + 25, + 22, + 40, + 43, + 0, + 22, + 18, + 36, + 40, + 0, + 18, + 15, + 32, + 36, + 0, + 15, + 13, + 28, + 32, + 0, + 13, + 11, + 24, + 28, + 0, + 11, + 7, + 20, + 24, + 0, + 7, + 4, + 16, + 20, + 0, + 4, + 1, + 5, + 16, + 0, + 1, + 2, + 8, + 5, + 0, + 2, + 3, + 10, + 8, + 0, + 3, + 6, + 19, + 10, + 0, + 6, + 9, + 23, + 19, + 0, + 9, + 12, + 27, + 23, + 0, + 12, + 14, + 30, + 27, + 0, + 14, + 17, + 35, + 30, + 0, + 17, + 21, + 39, + 35, + 0, + 21, + 26, + 44, + 39, + 0, + 26, + 31, + 48, + 44, + 0, + 31, + 34, + 52, + 48, + 0, + 34, + 37, + 57, + 52, + 0, + 37, + 42, + 64, + 57, + 0, + 42, + 46, + 69, + 64, + 0, + 46, + 50, + 74, + 69, + 0, + 50, + 55, + 79, + 74, + 0, + 55, + 61, + 86, + 79, + 0, + 61, + 65, + 89, + 86, + 0, + 65, + 67, + 93, + 89, + 0, + 67, + 81, + 119, + 93, + 0, + 81, + 95, + 136, + 119, + 0, + 95, + 99, + 139, + 136, + 0, + 99, + 101, + 141, + 139, + 0, + 101, + 107, + 145, + 141, + 0, + 107, + 110, + 148, + 145, + 0, + 110, + 113, + 150, + 148, + 0, + 113, + 114, + 151, + 150, + 0, + 114, + 112, + 149, + 151, + 0, + 112, + 109, + 147, + 149, + 0, + 109, + 106, + 144, + 147, + 0, + 106, + 102, + 142, + 144, + 0, + 102, + 98, + 138, + 142, + 0, + 98, + 94, + 135, + 138, + 0, + 94, + 91, + 134, + 135, + 0, + 91, + 87, + 130, + 134, + 0, + 87, + 82, + 120, + 130, + 0, + 82, + 75, + 111, + 120, + 0, + 75, + 73, + 104, + 111, + 0, + 73, + 56, + 80, + 104, + 0, + 56, + 54, + 77, + 80, + 0, + 77, + 84, + 200, + 196, + 0, + 84, + 117, + 210, + 200, + 0, + 117, + 126, + 213, + 210, + 0, + 126, + 133, + 215, + 213, + 0, + 133, + 137, + 219, + 215, + 0, + 137, + 140, + 222, + 219, + 0, + 140, + 143, + 227, + 222, + 0, + 143, + 152, + 234, + 227, + 0, + 152, + 154, + 237, + 234, + 0, + 154, + 156, + 239, + 237, + 0, + 156, + 158, + 241, + 239, + 0, + 158, + 160, + 243, + 241, + 0, + 160, + 162, + 246, + 243, + 0, + 162, + 164, + 248, + 246, + 0, + 164, + 163, + 247, + 248, + 0, + 163, + 161, + 245, + 247, + 0, + 161, + 159, + 242, + 245, + 0, + 159, + 157, + 240, + 242, + 0, + 157, + 155, + 238, + 240, + 0, + 155, + 153, + 235, + 238, + 0, + 153, + 146, + 228, + 235, + 0, + 146, + 103, + 207, + 228, + 0, + 103, + 97, + 206, + 207, + 0, + 97, + 92, + 204, + 206, + 0, + 92, + 88, + 202, + 204, + 0, + 88, + 83, + 199, + 202, + 0, + 83, + 76, + 195, + 199, + 0, + 76, + 71, + 193, + 195, + 0, + 71, + 68, + 191, + 193, + 0, + 68, + 63, + 189, + 191, + 0, + 63, + 59, + 188, + 189, + 0, + 59, + 51, + 185, + 188, + 0, + 51, + 47, + 183, + 185, + 0, + 47, + 43, + 181, + 183, + 0, + 43, + 40, + 180, + 181, + 0, + 40, + 36, + 178, + 180, + 0, + 36, + 32, + 176, + 178, + 0, + 32, + 28, + 174, + 176, + 0, + 28, + 24, + 172, + 174, + 0, + 24, + 20, + 170, + 172, + 0, + 20, + 16, + 168, + 170, + 0, + 16, + 5, + 165, + 168, + 0, + 5, + 8, + 166, + 165, + 0, + 8, + 10, + 167, + 166, + 0, + 10, + 19, + 169, + 167, + 0, + 19, + 23, + 171, + 169, + 0, + 23, + 27, + 173, + 171, + 0, + 27, + 30, + 175, + 173, + 0, + 30, + 35, + 177, + 175, + 0, + 35, + 39, + 179, + 177, + 0, + 39, + 44, + 182, + 179, + 0, + 44, + 48, + 184, + 182, + 0, + 48, + 52, + 186, + 184, + 0, + 52, + 57, + 187, + 186, + 0, + 57, + 64, + 190, + 187, + 0, + 64, + 69, + 192, + 190, + 0, + 69, + 74, + 194, + 192, + 0, + 74, + 79, + 197, + 194, + 0, + 79, + 86, + 201, + 197, + 0, + 86, + 89, + 203, + 201, + 0, + 89, + 93, + 205, + 203, + 0, + 93, + 119, + 211, + 205, + 0, + 119, + 136, + 218, + 211, + 0, + 136, + 139, + 220, + 218, + 0, + 139, + 141, + 223, + 220, + 0, + 141, + 145, + 226, + 223, + 0, + 145, + 148, + 230, + 226, + 0, + 148, + 150, + 232, + 230, + 0, + 150, + 151, + 233, + 232, + 0, + 151, + 149, + 231, + 233, + 0, + 149, + 147, + 229, + 231, + 0, + 147, + 144, + 225, + 229, + 0, + 144, + 142, + 224, + 225, + 0, + 142, + 138, + 221, + 224, + 0, + 138, + 135, + 217, + 221, + 0, + 135, + 134, + 216, + 217, + 0, + 134, + 130, + 214, + 216, + 0, + 130, + 120, + 212, + 214, + 0, + 120, + 111, + 209, + 212, + 0, + 111, + 104, + 208, + 209, + 0, + 104, + 80, + 198, + 208, + 0, + 80, + 77, + 196, + 198, + 0, + 196, + 200, + 283, + 279, + 0, + 200, + 210, + 292, + 283, + 0, + 210, + 213, + 295, + 292, + 0, + 213, + 215, + 297, + 295, + 0, + 215, + 219, + 301, + 297, + 0, + 219, + 222, + 304, + 301, + 0, + 222, + 227, + 310, + 304, + 0, + 227, + 234, + 316, + 310, + 0, + 234, + 237, + 318, + 316, + 0, + 237, + 239, + 320, + 318, + 0, + 239, + 241, + 322, + 320, + 0, + 241, + 243, + 324, + 322, + 0, + 243, + 246, + 326, + 324, + 0, + 246, + 248, + 328, + 326, + 0, + 248, + 247, + 327, + 328, + 0, + 247, + 245, + 325, + 327, + 0, + 245, + 242, + 323, + 325, + 0, + 242, + 240, + 321, + 323, + 0, + 240, + 238, + 319, + 321, + 0, + 238, + 235, + 317, + 319, + 0, + 235, + 228, + 308, + 317, + 0, + 228, + 207, + 289, + 308, + 0, + 207, + 206, + 288, + 289, + 0, + 206, + 204, + 286, + 288, + 0, + 204, + 202, + 284, + 286, + 0, + 202, + 199, + 281, + 284, + 0, + 199, + 195, + 277, + 281, + 0, + 195, + 193, + 275, + 277, + 0, + 193, + 191, + 273, + 275, + 0, + 191, + 189, + 271, + 273, + 0, + 189, + 188, + 270, + 271, + 0, + 188, + 185, + 267, + 270, + 0, + 185, + 183, + 265, + 267, + 0, + 183, + 181, + 263, + 265, + 0, + 181, + 180, + 262, + 263, + 0, + 180, + 178, + 260, + 262, + 0, + 178, + 176, + 258, + 260, + 0, + 176, + 174, + 256, + 258, + 0, + 174, + 172, + 254, + 256, + 0, + 172, + 170, + 252, + 254, + 0, + 170, + 168, + 250, + 252, + 0, + 168, + 165, + 236, + 250, + 0, + 165, + 166, + 244, + 236, + 0, + 166, + 167, + 249, + 244, + 0, + 167, + 169, + 251, + 249, + 0, + 169, + 171, + 253, + 251, + 0, + 171, + 173, + 255, + 253, + 0, + 173, + 175, + 257, + 255, + 0, + 175, + 177, + 259, + 257, + 0, + 177, + 179, + 261, + 259, + 0, + 179, + 182, + 264, + 261, + 0, + 182, + 184, + 266, + 264, + 0, + 184, + 186, + 268, + 266, + 0, + 186, + 187, + 269, + 268, + 0, + 187, + 190, + 272, + 269, + 0, + 190, + 192, + 274, + 272, + 0, + 192, + 194, + 276, + 274, + 0, + 194, + 197, + 278, + 276, + 0, + 197, + 201, + 282, + 278, + 0, + 201, + 203, + 285, + 282, + 0, + 203, + 205, + 287, + 285, + 0, + 205, + 211, + 293, + 287, + 0, + 211, + 218, + 299, + 293, + 0, + 218, + 220, + 302, + 299, + 0, + 220, + 223, + 305, + 302, + 0, + 223, + 226, + 307, + 305, + 0, + 226, + 230, + 312, + 307, + 0, + 230, + 232, + 314, + 312, + 0, + 232, + 233, + 315, + 314, + 0, + 233, + 231, + 313, + 315, + 0, + 231, + 229, + 311, + 313, + 0, + 229, + 225, + 309, + 311, + 0, + 225, + 224, + 306, + 309, + 0, + 224, + 221, + 303, + 306, + 0, + 221, + 217, + 300, + 303, + 0, + 217, + 216, + 298, + 300, + 0, + 216, + 214, + 296, + 298, + 0, + 214, + 212, + 294, + 296, + 0, + 212, + 209, + 291, + 294, + 0, + 209, + 208, + 290, + 291, + 0, + 208, + 198, + 280, + 290, + 0, + 198, + 196, + 279, + 280, + 0, + 279, + 283, + 364, + 366, + 361, + 0, + 364, + 368, + 366, + 0, + 364, + 283, + 292, + 378, + 0, + 364, + 378, + 381, + 368, + 0, + 378, + 292, + 295, + 387, + 0, + 378, + 387, + 388, + 381, + 0, + 387, + 295, + 297, + 391, + 0, + 387, + 391, + 392, + 388, + 0, + 391, + 297, + 301, + 398, + 396, + 0, + 391, + 396, + 392, + 0, + 301, + 304, + 403, + 398, + 0, + 304, + 310, + 410, + 403, + 0, + 310, + 316, + 419, + 410, + 0, + 316, + 318, + 422, + 419, + 0, + 318, + 320, + 426, + 422, + 0, + 320, + 322, + 429, + 426, + 0, + 322, + 324, + 432, + 429, + 0, + 324, + 326, + 434, + 432, + 0, + 326, + 328, + 436, + 434, + 0, + 328, + 327, + 435, + 436, + 0, + 327, + 325, + 433, + 435, + 0, + 325, + 323, + 430, + 433, + 0, + 323, + 321, + 427, + 430, + 0, + 321, + 319, + 423, + 427, + 0, + 319, + 317, + 418, + 423, + 0, + 317, + 308, + 407, + 418, + 0, + 308, + 289, + 375, + 407, + 0, + 289, + 288, + 374, + 375, + 0, + 288, + 286, + 372, + 374, + 0, + 286, + 284, + 369, + 372, + 0, + 284, + 281, + 362, + 369, + 0, + 281, + 277, + 359, + 362, + 0, + 277, + 275, + 357, + 359, + 0, + 275, + 273, + 355, + 357, + 0, + 273, + 271, + 353, + 355, + 0, + 271, + 270, + 352, + 353, + 0, + 270, + 267, + 349, + 352, + 0, + 267, + 265, + 347, + 349, + 0, + 265, + 263, + 345, + 347, + 0, + 263, + 262, + 344, + 345, + 0, + 262, + 260, + 342, + 344, + 0, + 260, + 258, + 340, + 342, + 0, + 258, + 256, + 338, + 340, + 0, + 256, + 254, + 336, + 338, + 0, + 254, + 252, + 334, + 336, + 0, + 252, + 250, + 332, + 334, + 0, + 250, + 236, + 329, + 332, + 0, + 236, + 244, + 330, + 329, + 0, + 244, + 249, + 331, + 330, + 0, + 249, + 251, + 333, + 331, + 0, + 251, + 253, + 335, + 333, + 0, + 253, + 255, + 337, + 335, + 0, + 255, + 257, + 339, + 337, + 0, + 257, + 259, + 341, + 339, + 0, + 259, + 261, + 343, + 341, + 0, + 261, + 264, + 346, + 343, + 0, + 264, + 266, + 348, + 346, + 0, + 266, + 268, + 350, + 348, + 0, + 268, + 269, + 351, + 350, + 0, + 269, + 272, + 354, + 351, + 0, + 272, + 274, + 356, + 354, + 0, + 274, + 276, + 358, + 356, + 0, + 276, + 278, + 360, + 358, + 0, + 278, + 282, + 365, + 360, + 0, + 282, + 285, + 371, + 365, + 0, + 285, + 287, + 373, + 371, + 0, + 287, + 293, + 379, + 373, + 0, + 293, + 299, + 395, + 379, + 0, + 299, + 302, + 400, + 395, + 0, + 302, + 305, + 404, + 400, + 0, + 305, + 307, + 408, + 404, + 0, + 307, + 312, + 412, + 408, + 0, + 312, + 314, + 415, + 412, + 0, + 314, + 315, + 416, + 415, + 0, + 315, + 313, + 414, + 416, + 0, + 313, + 311, + 411, + 414, + 0, + 311, + 309, + 409, + 411, + 0, + 309, + 306, + 405, + 409, + 0, + 306, + 303, + 401, + 405, + 0, + 303, + 300, + 397, + 401, + 0, + 300, + 298, + 393, + 397, + 0, + 298, + 296, + 389, + 393, + 0, + 296, + 294, + 383, + 389, + 0, + 294, + 291, + 377, + 383, + 0, + 291, + 290, + 376, + 377, + 0, + 290, + 280, + 363, + 376, + 0, + 280, + 279, + 361, + 363, + 0, + 367, + 361, + 366, + 0, + 367, + 366, + 368, + 533, + 529, + 0, + 368, + 381, + 543, + 533, + 0, + 381, + 388, + 547, + 543, + 0, + 388, + 392, + 550, + 547, + 0, + 396, + 398, + 399, + 0, + 392, + 396, + 399, + 553, + 550, + 0, + 399, + 398, + 403, + 406, + 0, + 399, + 406, + 556, + 553, + 0, + 406, + 403, + 410, + 420, + 0, + 406, + 420, + 563, + 556, + 0, + 420, + 410, + 419, + 428, + 0, + 420, + 428, + 571, + 563, + 0, + 428, + 419, + 422, + 439, + 0, + 428, + 439, + 573, + 571, + 0, + 439, + 422, + 426, + 442, + 0, + 439, + 442, + 575, + 573, + 0, + 442, + 426, + 429, + 446, + 0, + 442, + 446, + 579, + 575, + 0, + 446, + 429, + 432, + 451, + 0, + 446, + 451, + 582, + 579, + 0, + 451, + 432, + 434, + 455, + 0, + 451, + 455, + 584, + 582, + 0, + 455, + 434, + 436, + 459, + 0, + 455, + 459, + 585, + 584, + 0, + 459, + 436, + 435, + 462, + 0, + 459, + 462, + 583, + 585, + 0, + 462, + 435, + 433, + 467, + 0, + 462, + 467, + 581, + 583, + 0, + 467, + 433, + 430, + 471, + 0, + 467, + 471, + 578, + 581, + 0, + 471, + 430, + 427, + 475, + 0, + 471, + 475, + 576, + 578, + 0, + 475, + 427, + 423, + 478, + 0, + 475, + 478, + 574, + 576, + 0, + 478, + 423, + 418, + 481, + 0, + 478, + 481, + 569, + 574, + 0, + 481, + 418, + 407, + 487, + 0, + 481, + 487, + 560, + 569, + 0, + 487, + 407, + 375, + 496, + 0, + 487, + 496, + 538, + 560, + 0, + 496, + 375, + 374, + 498, + 0, + 496, + 498, + 537, + 538, + 0, + 498, + 374, + 372, + 497, + 0, + 498, + 497, + 535, + 537, + 0, + 497, + 372, + 369, + 495, + 0, + 497, + 495, + 532, + 535, + 0, + 495, + 369, + 362, + 493, + 0, + 495, + 493, + 528, + 532, + 0, + 493, + 362, + 359, + 491, + 0, + 493, + 491, + 526, + 528, + 0, + 491, + 359, + 357, + 490, + 0, + 491, + 490, + 524, + 526, + 0, + 490, + 357, + 355, + 489, + 0, + 490, + 489, + 522, + 524, + 0, + 489, + 355, + 353, + 482, + 0, + 489, + 482, + 520, + 522, + 0, + 482, + 353, + 352, + 479, + 0, + 482, + 479, + 519, + 520, + 0, + 479, + 352, + 349, + 473, + 0, + 479, + 473, + 516, + 519, + 0, + 473, + 349, + 347, + 468, + 0, + 473, + 468, + 514, + 516, + 0, + 468, + 347, + 345, + 463, + 0, + 468, + 463, + 512, + 514, + 0, + 463, + 345, + 344, + 458, + 0, + 463, + 458, + 511, + 512, + 0, + 458, + 344, + 342, + 454, + 0, + 458, + 454, + 509, + 511, + 0, + 454, + 342, + 340, + 450, + 0, + 454, + 450, + 507, + 509, + 0, + 450, + 340, + 338, + 445, + 0, + 450, + 445, + 505, + 507, + 0, + 445, + 338, + 336, + 440, + 0, + 445, + 440, + 503, + 505, + 0, + 440, + 336, + 334, + 431, + 0, + 440, + 431, + 501, + 503, + 0, + 431, + 334, + 332, + 421, + 0, + 431, + 421, + 499, + 501, + 0, + 421, + 332, + 329, + 385, + 0, + 421, + 385, + 485, + 499, + 0, + 385, + 329, + 330, + 384, + 0, + 385, + 384, + 492, + 485, + 0, + 384, + 330, + 331, + 386, + 0, + 384, + 386, + 494, + 492, + 0, + 386, + 331, + 333, + 417, + 0, + 386, + 417, + 500, + 494, + 0, + 417, + 333, + 335, + 425, + 0, + 417, + 425, + 502, + 500, + 0, + 425, + 335, + 337, + 438, + 0, + 425, + 438, + 504, + 502, + 0, + 438, + 337, + 339, + 443, + 0, + 438, + 443, + 506, + 504, + 0, + 443, + 339, + 341, + 447, + 0, + 443, + 447, + 508, + 506, + 0, + 447, + 341, + 343, + 453, + 0, + 447, + 453, + 510, + 508, + 0, + 453, + 343, + 346, + 457, + 0, + 453, + 457, + 513, + 510, + 0, + 457, + 346, + 348, + 461, + 0, + 457, + 461, + 515, + 513, + 0, + 461, + 348, + 350, + 465, + 0, + 461, + 465, + 517, + 515, + 0, + 465, + 350, + 351, + 469, + 0, + 465, + 469, + 518, + 517, + 0, + 469, + 351, + 354, + 474, + 0, + 469, + 474, + 521, + 518, + 0, + 474, + 354, + 356, + 477, + 0, + 474, + 477, + 523, + 521, + 0, + 477, + 356, + 358, + 480, + 0, + 477, + 480, + 525, + 523, + 0, + 480, + 358, + 360, + 483, + 0, + 480, + 483, + 527, + 525, + 0, + 483, + 360, + 365, + 486, + 0, + 483, + 486, + 531, + 527, + 0, + 486, + 365, + 371, + 488, + 0, + 486, + 488, + 534, + 531, + 0, + 488, + 371, + 373, + 484, + 0, + 488, + 484, + 536, + 534, + 0, + 484, + 373, + 379, + 476, + 0, + 484, + 476, + 542, + 536, + 0, + 476, + 379, + 395, + 472, + 0, + 476, + 472, + 551, + 542, + 0, + 472, + 395, + 400, + 470, + 0, + 472, + 470, + 554, + 551, + 0, + 470, + 400, + 404, + 466, + 0, + 470, + 466, + 557, + 554, + 0, + 466, + 404, + 408, + 464, + 0, + 466, + 464, + 561, + 557, + 0, + 464, + 408, + 412, + 460, + 0, + 464, + 460, + 564, + 561, + 0, + 460, + 412, + 415, + 456, + 0, + 460, + 456, + 567, + 564, + 0, + 456, + 415, + 416, + 452, + 0, + 456, + 452, + 568, + 567, + 0, + 452, + 416, + 414, + 448, + 449, + 0, + 452, + 449, + 448, + 566, + 568, + 0, + 448, + 414, + 411, + 444, + 0, + 448, + 444, + 565, + 566, + 0, + 444, + 411, + 409, + 441, + 0, + 444, + 441, + 562, + 565, + 0, + 441, + 409, + 405, + 437, + 0, + 441, + 437, + 559, + 562, + 0, + 437, + 405, + 401, + 424, + 0, + 437, + 424, + 555, + 559, + 0, + 424, + 401, + 397, + 413, + 0, + 424, + 413, + 552, + 555, + 0, + 413, + 397, + 393, + 402, + 0, + 413, + 402, + 549, + 552, + 0, + 402, + 393, + 389, + 394, + 0, + 402, + 394, + 548, + 549, + 0, + 394, + 389, + 383, + 390, + 0, + 394, + 390, + 544, + 548, + 0, + 390, + 383, + 377, + 382, + 0, + 390, + 382, + 541, + 544, + 0, + 382, + 377, + 376, + 380, + 0, + 382, + 380, + 539, + 541, + 0, + 380, + 376, + 363, + 370, + 0, + 380, + 370, + 530, + 539, + 0, + 370, + 363, + 361, + 367, + 0, + 370, + 367, + 529, + 530, + 0, + 529, + 533, + 619, + 614, + 0, + 533, + 543, + 636, + 619, + 0, + 543, + 547, + 640, + 636, + 0, + 547, + 550, + 645, + 640, + 0, + 550, + 553, + 648, + 645, + 0, + 553, + 556, + 654, + 648, + 0, + 556, + 563, + 660, + 654, + 0, + 563, + 571, + 668, + 660, + 0, + 571, + 573, + 670, + 668, + 0, + 573, + 575, + 674, + 670, + 0, + 575, + 579, + 676, + 674, + 0, + 579, + 582, + 678, + 676, + 0, + 582, + 584, + 680, + 678, + 0, + 584, + 585, + 681, + 680, + 0, + 585, + 583, + 679, + 681, + 0, + 583, + 581, + 677, + 679, + 0, + 581, + 578, + 675, + 677, + 0, + 578, + 576, + 673, + 675, + 0, + 576, + 574, + 669, + 673, + 0, + 574, + 569, + 667, + 669, + 0, + 569, + 560, + 656, + 667, + 0, + 560, + 538, + 629, + 656, + 0, + 538, + 537, + 626, + 629, + 0, + 537, + 535, + 623, + 626, + 0, + 535, + 532, + 618, + 623, + 0, + 532, + 528, + 613, + 618, + 0, + 528, + 526, + 611, + 613, + 0, + 526, + 524, + 609, + 611, + 0, + 524, + 522, + 605, + 609, + 0, + 522, + 520, + 602, + 605, + 0, + 520, + 519, + 601, + 602, + 0, + 519, + 516, + 598, + 601, + 0, + 516, + 514, + 596, + 598, + 0, + 514, + 512, + 594, + 596, + 0, + 512, + 511, + 593, + 594, + 0, + 511, + 509, + 591, + 593, + 0, + 509, + 507, + 589, + 591, + 0, + 507, + 505, + 587, + 589, + 0, + 505, + 503, + 580, + 587, + 0, + 503, + 501, + 572, + 580, + 0, + 501, + 499, + 558, + 572, + 0, + 499, + 485, + 540, + 558, + 0, + 485, + 492, + 545, + 540, + 0, + 492, + 494, + 546, + 545, + 0, + 494, + 500, + 570, + 546, + 0, + 500, + 502, + 577, + 570, + 0, + 502, + 504, + 586, + 577, + 0, + 504, + 506, + 588, + 586, + 0, + 506, + 508, + 590, + 588, + 0, + 508, + 510, + 592, + 590, + 0, + 510, + 513, + 595, + 592, + 0, + 513, + 515, + 597, + 595, + 0, + 515, + 517, + 599, + 597, + 0, + 517, + 518, + 600, + 599, + 0, + 518, + 521, + 603, + 600, + 0, + 521, + 523, + 607, + 603, + 0, + 523, + 525, + 610, + 607, + 0, + 525, + 527, + 612, + 610, + 0, + 527, + 531, + 617, + 612, + 0, + 531, + 534, + 621, + 617, + 0, + 534, + 536, + 624, + 621, + 0, + 536, + 542, + 634, + 624, + 0, + 542, + 551, + 646, + 634, + 0, + 551, + 554, + 650, + 646, + 0, + 554, + 557, + 653, + 650, + 0, + 557, + 561, + 657, + 653, + 0, + 561, + 564, + 661, + 657, + 0, + 564, + 567, + 665, + 661, + 0, + 567, + 568, + 666, + 665, + 0, + 568, + 566, + 664, + 666, + 0, + 566, + 565, + 662, + 664, + 0, + 565, + 562, + 658, + 662, + 0, + 562, + 559, + 655, + 658, + 0, + 559, + 555, + 652, + 655, + 0, + 555, + 552, + 647, + 652, + 0, + 552, + 549, + 644, + 647, + 0, + 549, + 548, + 641, + 644, + 0, + 548, + 544, + 637, + 641, + 0, + 544, + 541, + 633, + 637, + 0, + 541, + 539, + 631, + 633, + 0, + 539, + 530, + 616, + 631, + 0, + 530, + 529, + 614, + 616, + 0, + 693, + 614, + 619, + 697, + 0, + 693, + 697, + 786, + 780, + 0, + 697, + 619, + 636, + 706, + 0, + 697, + 706, + 803, + 786, + 0, + 706, + 636, + 640, + 708, + 0, + 706, + 708, + 806, + 803, + 0, + 708, + 640, + 645, + 711, + 0, + 708, + 711, + 810, + 806, + 0, + 711, + 645, + 648, + 714, + 0, + 711, + 714, + 816, + 810, + 0, + 714, + 648, + 654, + 718, + 0, + 714, + 718, + 821, + 816, + 0, + 718, + 654, + 660, + 723, + 0, + 718, + 723, + 826, + 821, + 0, + 723, + 660, + 668, + 730, + 0, + 723, + 730, + 835, + 826, + 0, + 730, + 668, + 670, + 734, + 0, + 730, + 734, + 838, + 835, + 0, + 734, + 670, + 674, + 736, + 0, + 734, + 736, + 840, + 838, + 0, + 736, + 674, + 676, + 739, + 0, + 736, + 739, + 844, + 840, + 0, + 739, + 676, + 678, + 741, + 0, + 739, + 741, + 846, + 844, + 0, + 741, + 678, + 680, + 744, + 0, + 741, + 744, + 848, + 846, + 0, + 744, + 680, + 681, + 745, + 0, + 744, + 745, + 849, + 848, + 0, + 745, + 681, + 679, + 743, + 0, + 745, + 743, + 847, + 849, + 0, + 743, + 679, + 677, + 740, + 0, + 743, + 740, + 845, + 847, + 0, + 740, + 677, + 675, + 738, + 0, + 740, + 738, + 843, + 845, + 0, + 738, + 675, + 673, + 735, + 0, + 738, + 735, + 839, + 843, + 0, + 735, + 673, + 669, + 733, + 0, + 735, + 733, + 837, + 839, + 0, + 733, + 669, + 667, + 729, + 732, + 0, + 733, + 732, + 729, + 833, + 837, + 0, + 729, + 667, + 656, + 720, + 0, + 729, + 720, + 823, + 833, + 0, + 720, + 656, + 629, + 702, + 0, + 720, + 702, + 795, + 823, + 0, + 702, + 629, + 626, + 701, + 0, + 702, + 701, + 792, + 795, + 0, + 701, + 626, + 623, + 699, + 0, + 701, + 699, + 788, + 792, + 0, + 699, + 623, + 618, + 696, + 0, + 699, + 696, + 784, + 788, + 0, + 696, + 618, + 613, + 692, + 0, + 696, + 692, + 779, + 784, + 0, + 692, + 613, + 611, + 690, + 0, + 692, + 690, + 776, + 779, + 0, + 690, + 611, + 609, + 688, + 0, + 690, + 688, + 774, + 776, + 0, + 688, + 609, + 605, + 686, + 0, + 688, + 686, + 772, + 774, + 0, + 686, + 605, + 602, + 684, + 0, + 686, + 684, + 768, + 772, + 0, + 684, + 602, + 601, + 683, + 0, + 684, + 683, + 766, + 768, + 0, + 683, + 601, + 598, + 671, + 0, + 683, + 671, + 763, + 766, + 0, + 671, + 598, + 596, + 659, + 0, + 671, + 659, + 761, + 763, + 0, + 659, + 596, + 594, + 649, + 0, + 659, + 649, + 759, + 761, + 0, + 649, + 594, + 593, + 643, + 0, + 649, + 643, + 758, + 759, + 0, + 643, + 593, + 591, + 639, + 0, + 643, + 639, + 756, + 758, + 0, + 639, + 591, + 589, + 635, + 0, + 639, + 635, + 754, + 756, + 0, + 635, + 589, + 587, + 630, + 0, + 635, + 630, + 752, + 754, + 0, + 630, + 587, + 580, + 627, + 0, + 630, + 627, + 750, + 752, + 0, + 627, + 580, + 572, + 622, + 0, + 627, + 622, + 748, + 750, + 0, + 622, + 572, + 558, + 615, + 0, + 622, + 615, + 746, + 748, + 0, + 615, + 558, + 540, + 604, + 0, + 615, + 604, + 731, + 746, + 0, + 604, + 540, + 545, + 606, + 0, + 604, + 606, + 737, + 731, + 0, + 606, + 545, + 546, + 608, + 0, + 606, + 608, + 742, + 737, + 0, + 608, + 546, + 570, + 620, + 0, + 608, + 620, + 747, + 742, + 0, + 620, + 570, + 577, + 625, + 0, + 620, + 625, + 749, + 747, + 0, + 625, + 577, + 586, + 628, + 0, + 625, + 628, + 751, + 749, + 0, + 628, + 586, + 588, + 632, + 0, + 628, + 632, + 753, + 751, + 0, + 632, + 588, + 590, + 638, + 0, + 632, + 638, + 755, + 753, + 0, + 638, + 590, + 592, + 642, + 0, + 638, + 642, + 757, + 755, + 0, + 642, + 592, + 595, + 651, + 0, + 642, + 651, + 760, + 757, + 0, + 651, + 595, + 597, + 663, + 0, + 651, + 663, + 762, + 760, + 0, + 663, + 597, + 599, + 672, + 0, + 663, + 672, + 764, + 762, + 0, + 672, + 599, + 600, + 682, + 0, + 672, + 682, + 765, + 764, + 0, + 682, + 600, + 603, + 685, + 0, + 682, + 685, + 769, + 765, + 0, + 685, + 603, + 607, + 687, + 0, + 685, + 687, + 773, + 769, + 0, + 687, + 607, + 610, + 689, + 0, + 687, + 689, + 775, + 773, + 0, + 689, + 610, + 612, + 691, + 0, + 689, + 691, + 777, + 775, + 0, + 691, + 612, + 617, + 695, + 0, + 691, + 695, + 781, + 777, + 0, + 695, + 617, + 621, + 698, + 0, + 695, + 698, + 787, + 781, + 0, + 698, + 621, + 624, + 700, + 0, + 698, + 700, + 791, + 787, + 0, + 700, + 624, + 634, + 705, + 0, + 700, + 705, + 800, + 791, + 0, + 705, + 634, + 646, + 712, + 0, + 705, + 712, + 813, + 800, + 0, + 712, + 646, + 650, + 715, + 0, + 712, + 715, + 815, + 813, + 0, + 715, + 650, + 653, + 717, + 0, + 715, + 717, + 819, + 815, + 0, + 717, + 653, + 657, + 721, + 0, + 717, + 721, + 824, + 819, + 0, + 721, + 657, + 661, + 724, + 0, + 721, + 724, + 827, + 824, + 0, + 724, + 661, + 665, + 727, + 0, + 724, + 727, + 829, + 827, + 0, + 727, + 665, + 666, + 728, + 0, + 727, + 728, + 831, + 829, + 0, + 728, + 666, + 664, + 726, + 0, + 728, + 726, + 830, + 831, + 0, + 726, + 664, + 662, + 725, + 0, + 726, + 725, + 828, + 830, + 0, + 725, + 662, + 658, + 722, + 0, + 725, + 722, + 825, + 828, + 0, + 722, + 658, + 655, + 719, + 0, + 722, + 719, + 822, + 825, + 0, + 719, + 655, + 652, + 716, + 0, + 719, + 716, + 817, + 822, + 0, + 716, + 652, + 647, + 713, + 0, + 716, + 713, + 814, + 817, + 0, + 713, + 647, + 644, + 710, + 0, + 713, + 710, + 809, + 814, + 0, + 710, + 644, + 641, + 709, + 0, + 710, + 709, + 808, + 809, + 0, + 709, + 641, + 637, + 707, + 0, + 709, + 707, + 804, + 808, + 0, + 707, + 637, + 633, + 704, + 0, + 707, + 704, + 799, + 804, + 0, + 704, + 633, + 631, + 703, + 0, + 704, + 703, + 798, + 799, + 0, + 703, + 631, + 616, + 694, + 0, + 703, + 694, + 782, + 798, + 0, + 694, + 616, + 614, + 693, + 0, + 694, + 693, + 780, + 782, + 0, + 780, + 786, + 869, + 863, + 0, + 786, + 803, + 884, + 869, + 0, + 803, + 806, + 887, + 884, + 0, + 806, + 810, + 891, + 887, + 0, + 810, + 816, + 897, + 891, + 0, + 816, + 821, + 900, + 897, + 0, + 821, + 826, + 907, + 900, + 0, + 826, + 835, + 914, + 907, + 0, + 835, + 838, + 916, + 914, + 0, + 838, + 840, + 918, + 916, + 0, + 840, + 844, + 920, + 918, + 0, + 844, + 846, + 923, + 920, + 0, + 846, + 848, + 926, + 923, + 0, + 848, + 849, + 927, + 926, + 0, + 849, + 847, + 925, + 927, + 0, + 847, + 845, + 922, + 925, + 0, + 845, + 843, + 919, + 922, + 0, + 843, + 839, + 917, + 919, + 0, + 839, + 837, + 915, + 917, + 0, + 837, + 833, + 913, + 915, + 0, + 833, + 823, + 901, + 913, + 0, + 823, + 795, + 877, + 901, + 0, + 795, + 792, + 875, + 877, + 0, + 792, + 788, + 871, + 875, + 0, + 788, + 784, + 867, + 871, + 0, + 784, + 779, + 862, + 867, + 0, + 779, + 776, + 859, + 862, + 0, + 776, + 774, + 856, + 859, + 0, + 774, + 772, + 854, + 856, + 0, + 772, + 768, + 850, + 854, + 0, + 768, + 766, + 841, + 850, + 0, + 766, + 763, + 832, + 841, + 0, + 763, + 761, + 818, + 832, + 0, + 761, + 759, + 811, + 818, + 0, + 759, + 758, + 807, + 811, + 0, + 758, + 756, + 802, + 807, + 0, + 756, + 754, + 797, + 802, + 0, + 754, + 752, + 794, + 797, + 0, + 752, + 750, + 790, + 794, + 0, + 750, + 748, + 785, + 790, + 0, + 748, + 746, + 778, + 785, + 0, + 746, + 731, + 767, + 778, + 0, + 731, + 737, + 770, + 767, + 0, + 737, + 742, + 771, + 770, + 0, + 742, + 747, + 783, + 771, + 0, + 747, + 749, + 789, + 783, + 0, + 749, + 751, + 793, + 789, + 0, + 751, + 753, + 796, + 793, + 0, + 753, + 755, + 801, + 796, + 0, + 755, + 757, + 805, + 801, + 0, + 757, + 760, + 812, + 805, + 0, + 760, + 762, + 820, + 812, + 0, + 762, + 764, + 834, + 820, + 0, + 764, + 765, + 842, + 834, + 0, + 765, + 769, + 851, + 842, + 0, + 769, + 773, + 855, + 851, + 0, + 773, + 775, + 858, + 855, + 0, + 775, + 777, + 860, + 858, + 0, + 777, + 781, + 864, + 860, + 0, + 781, + 787, + 870, + 864, + 0, + 787, + 791, + 873, + 870, + 0, + 791, + 800, + 882, + 873, + 0, + 800, + 813, + 893, + 882, + 0, + 813, + 815, + 896, + 893, + 0, + 815, + 819, + 899, + 896, + 0, + 819, + 824, + 903, + 899, + 0, + 824, + 827, + 906, + 903, + 0, + 827, + 829, + 910, + 906, + 0, + 829, + 831, + 912, + 910, + 0, + 831, + 830, + 911, + 912, + 0, + 830, + 828, + 908, + 911, + 0, + 828, + 825, + 905, + 908, + 0, + 825, + 822, + 902, + 905, + 0, + 822, + 817, + 898, + 902, + 0, + 817, + 814, + 895, + 898, + 0, + 814, + 809, + 890, + 895, + 0, + 809, + 808, + 889, + 890, + 0, + 808, + 804, + 886, + 889, + 0, + 804, + 799, + 881, + 886, + 0, + 799, + 798, + 880, + 881, + 0, + 798, + 782, + 865, + 880, + 0, + 782, + 780, + 863, + 865, + 0, + 964, + 974, + 1049, + 1043, + 0, + 964, + 863, + 869, + 974, + 0, + 974, + 1001, + 1064, + 1049, + 0, + 974, + 869, + 884, + 1001, + 0, + 1001, + 1012, + 1068, + 1064, + 0, + 1001, + 884, + 887, + 1012, + 0, + 1012, + 1018, + 1073, + 1068, + 0, + 1012, + 887, + 891, + 1018, + 0, + 1018, + 1022, + 1081, + 1073, + 0, + 1018, + 891, + 897, + 1022, + 0, + 1022, + 1025, + 1087, + 1081, + 0, + 1022, + 897, + 900, + 1025, + 0, + 1025, + 1028, + 1094, + 1087, + 0, + 1025, + 900, + 907, + 1028, + 0, + 1028, + 1032, + 1101, + 1094, + 0, + 1028, + 907, + 914, + 1032, + 0, + 1032, + 1030, + 1103, + 1101, + 0, + 1032, + 914, + 916, + 1030, + 0, + 1030, + 1027, + 1106, + 1103, + 0, + 1030, + 916, + 918, + 1027, + 0, + 1027, + 1024, + 1108, + 1106, + 0, + 1027, + 918, + 920, + 1024, + 0, + 1024, + 1021, + 1110, + 1108, + 0, + 1024, + 920, + 923, + 1021, + 0, + 1021, + 1017, + 1112, + 1110, + 0, + 1021, + 923, + 926, + 1017, + 0, + 1017, + 1014, + 1113, + 1112, + 0, + 1017, + 926, + 927, + 1014, + 0, + 1014, + 1005, + 1111, + 1113, + 0, + 1014, + 927, + 925, + 1005, + 0, + 1005, + 996, + 1109, + 1111, + 0, + 1005, + 925, + 922, + 996, + 0, + 996, + 989, + 1107, + 1109, + 0, + 996, + 922, + 919, + 989, + 0, + 989, + 981, + 1105, + 1107, + 0, + 989, + 919, + 917, + 981, + 0, + 981, + 976, + 1102, + 1105, + 0, + 981, + 917, + 915, + 976, + 0, + 976, + 970, + 1099, + 1102, + 0, + 976, + 915, + 913, + 970, + 0, + 970, + 960, + 1088, + 1099, + 0, + 970, + 913, + 901, + 960, + 0, + 960, + 946, + 1057, + 1088, + 0, + 960, + 901, + 877, + 946, + 0, + 946, + 944, + 1054, + 1057, + 0, + 946, + 877, + 875, + 944, + 0, + 944, + 942, + 1050, + 1054, + 0, + 944, + 875, + 871, + 942, + 0, + 942, + 940, + 1044, + 1050, + 0, + 942, + 871, + 867, + 940, + 0, + 940, + 938, + 1040, + 1044, + 0, + 940, + 867, + 862, + 938, + 0, + 938, + 936, + 1037, + 1040, + 0, + 938, + 862, + 859, + 936, + 0, + 936, + 935, + 1033, + 1037, + 0, + 936, + 859, + 856, + 935, + 0, + 935, + 933, + 1023, + 1033, + 0, + 935, + 856, + 854, + 933, + 0, + 933, + 931, + 1015, + 1023, + 0, + 933, + 854, + 850, + 931, + 0, + 931, + 929, + 1006, + 1015, + 0, + 931, + 850, + 841, + 929, + 0, + 929, + 924, + 994, + 1006, + 0, + 929, + 841, + 832, + 924, + 0, + 924, + 909, + 986, + 994, + 0, + 924, + 832, + 818, + 909, + 0, + 909, + 894, + 979, + 986, + 0, + 909, + 818, + 811, + 894, + 0, + 894, + 888, + 975, + 979, + 0, + 894, + 811, + 807, + 888, + 0, + 888, + 883, + 971, + 975, + 0, + 888, + 807, + 802, + 883, + 0, + 883, + 878, + 966, + 971, + 0, + 883, + 802, + 797, + 878, + 0, + 878, + 874, + 959, + 966, + 0, + 878, + 797, + 794, + 874, + 0, + 874, + 868, + 956, + 959, + 0, + 874, + 794, + 790, + 868, + 0, + 868, + 861, + 953, + 956, + 0, + 868, + 790, + 785, + 861, + 0, + 861, + 857, + 951, + 953, + 0, + 861, + 785, + 778, + 857, + 0, + 857, + 836, + 948, + 951, + 0, + 857, + 778, + 767, + 836, + 0, + 836, + 852, + 949, + 948, + 0, + 836, + 767, + 770, + 852, + 0, + 852, + 853, + 950, + 949, + 0, + 852, + 770, + 771, + 853, + 0, + 853, + 866, + 952, + 950, + 0, + 853, + 771, + 783, + 866, + 0, + 866, + 872, + 954, + 952, + 0, + 866, + 783, + 789, + 872, + 0, + 872, + 876, + 957, + 954, + 0, + 872, + 789, + 793, + 876, + 0, + 876, + 879, + 962, + 957, + 0, + 876, + 793, + 796, + 879, + 0, + 879, + 885, + 969, + 962, + 0, + 879, + 796, + 801, + 885, + 0, + 885, + 892, + 973, + 969, + 0, + 885, + 801, + 805, + 892, + 0, + 892, + 904, + 980, + 973, + 0, + 892, + 805, + 812, + 904, + 0, + 904, + 921, + 988, + 980, + 0, + 904, + 812, + 820, + 921, + 0, + 921, + 928, + 995, + 988, + 0, + 921, + 820, + 834, + 928, + 0, + 928, + 930, + 1007, + 995, + 0, + 928, + 834, + 842, + 930, + 0, + 930, + 932, + 1016, + 1007, + 0, + 930, + 842, + 851, + 932, + 0, + 932, + 934, + 1026, + 1016, + 0, + 932, + 851, + 855, + 934, + 0, + 934, + 937, + 1034, + 1026, + 0, + 934, + 855, + 858, + 937, + 0, + 937, + 939, + 1038, + 1034, + 0, + 937, + 858, + 860, + 939, + 0, + 939, + 941, + 1042, + 1038, + 0, + 939, + 860, + 864, + 941, + 0, + 941, + 943, + 1048, + 1042, + 0, + 941, + 864, + 870, + 943, + 0, + 943, + 945, + 1053, + 1048, + 0, + 943, + 870, + 873, + 945, + 0, + 945, + 947, + 1061, + 1053, + 0, + 945, + 873, + 882, + 947, + 0, + 947, + 955, + 1075, + 1061, + 0, + 947, + 882, + 893, + 955, + 0, + 955, + 961, + 1080, + 1075, + 0, + 955, + 893, + 896, + 961, + 0, + 961, + 968, + 1085, + 1080, + 0, + 961, + 896, + 899, + 968, + 0, + 968, + 972, + 1090, + 1085, + 0, + 968, + 899, + 903, + 972, + 0, + 972, + 978, + 1093, + 1090, + 0, + 972, + 903, + 906, + 978, + 0, + 978, + 985, + 1096, + 1093, + 0, + 978, + 906, + 910, + 985, + 0, + 985, + 992, + 1100, + 1096, + 0, + 985, + 910, + 912, + 992, + 0, + 992, + 997, + 1098, + 1100, + 0, + 992, + 912, + 911, + 997, + 0, + 997, + 1000, + 1095, + 1098, + 0, + 997, + 911, + 908, + 1000, + 0, + 1000, + 1004, + 1092, + 1095, + 0, + 1000, + 908, + 905, + 1004, + 0, + 1004, + 1009, + 1089, + 1092, + 0, + 1004, + 905, + 902, + 1009, + 0, + 1009, + 1010, + 1083, + 1089, + 0, + 1009, + 902, + 898, + 1010, + 0, + 1010, + 1008, + 1079, + 1083, + 0, + 1010, + 898, + 895, + 1008, + 0, + 1008, + 1003, + 1072, + 1079, + 0, + 1008, + 895, + 890, + 1003, + 0, + 1003, + 999, + 1070, + 1072, + 0, + 1003, + 890, + 889, + 999, + 0, + 999, + 993, + 1066, + 1070, + 0, + 999, + 889, + 886, + 993, + 0, + 993, + 987, + 1062, + 1066, + 0, + 993, + 886, + 881, + 987, + 0, + 987, + 984, + 1060, + 1062, + 0, + 987, + 881, + 880, + 984, + 0, + 984, + 967, + 1045, + 1060, + 0, + 984, + 880, + 865, + 967, + 0, + 967, + 964, + 1043, + 1045, + 0, + 967, + 865, + 863, + 964, + 0, + 1043, + 1049, + 1086, + 1076, + 0, + 1049, + 1064, + 1117, + 1086, + 0, + 1064, + 1068, + 1119, + 1117, + 0, + 1068, + 1073, + 1122, + 1119, + 0, + 1073, + 1081, + 1126, + 1122, + 0, + 1081, + 1087, + 1129, + 1126, + 0, + 1087, + 1094, + 1135, + 1129, + 0, + 1094, + 1101, + 1141, + 1135, + 0, + 1101, + 1103, + 1143, + 1141, + 0, + 1103, + 1106, + 1145, + 1143, + 0, + 1106, + 1108, + 1147, + 1145, + 0, + 1108, + 1110, + 1149, + 1147, + 0, + 1110, + 1112, + 1151, + 1149, + 0, + 1112, + 1113, + 1152, + 1151, + 0, + 1113, + 1111, + 1150, + 1152, + 0, + 1111, + 1109, + 1148, + 1150, + 0, + 1109, + 1107, + 1146, + 1148, + 0, + 1107, + 1105, + 1144, + 1146, + 0, + 1105, + 1102, + 1142, + 1144, + 0, + 1102, + 1099, + 1139, + 1142, + 0, + 1099, + 1088, + 1130, + 1139, + 0, + 1088, + 1057, + 1104, + 1130, + 0, + 1057, + 1054, + 1097, + 1104, + 0, + 1054, + 1050, + 1084, + 1097, + 0, + 1050, + 1044, + 1077, + 1084, + 0, + 1044, + 1040, + 1071, + 1077, + 0, + 1040, + 1037, + 1067, + 1071, + 0, + 1037, + 1033, + 1063, + 1067, + 0, + 1033, + 1023, + 1058, + 1063, + 0, + 1023, + 1015, + 1055, + 1058, + 0, + 1015, + 1006, + 1051, + 1055, + 0, + 1006, + 994, + 1046, + 1051, + 0, + 994, + 986, + 1039, + 1046, + 0, + 986, + 979, + 1035, + 1039, + 0, + 979, + 975, + 1031, + 1035, + 0, + 975, + 971, + 1020, + 1031, + 0, + 971, + 966, + 1013, + 1020, + 0, + 966, + 959, + 1002, + 1013, + 0, + 959, + 956, + 991, + 1002, + 0, + 956, + 953, + 983, + 991, + 0, + 953, + 951, + 977, + 983, + 0, + 951, + 948, + 958, + 977, + 0, + 948, + 949, + 963, + 958, + 0, + 949, + 950, + 965, + 963, + 0, + 950, + 952, + 982, + 965, + 0, + 952, + 954, + 990, + 982, + 0, + 954, + 957, + 998, + 990, + 0, + 957, + 962, + 1011, + 998, + 0, + 962, + 969, + 1019, + 1011, + 0, + 969, + 973, + 1029, + 1019, + 0, + 973, + 980, + 1036, + 1029, + 0, + 980, + 988, + 1041, + 1036, + 0, + 988, + 995, + 1047, + 1041, + 0, + 995, + 1007, + 1052, + 1047, + 0, + 1007, + 1016, + 1056, + 1052, + 0, + 1016, + 1026, + 1059, + 1056, + 0, + 1026, + 1034, + 1065, + 1059, + 0, + 1034, + 1038, + 1069, + 1065, + 0, + 1038, + 1042, + 1074, + 1069, + 0, + 1042, + 1048, + 1082, + 1074, + 0, + 1048, + 1053, + 1091, + 1082, + 0, + 1053, + 1061, + 1115, + 1091, + 0, + 1061, + 1075, + 1123, + 1115, + 0, + 1075, + 1080, + 1125, + 1123, + 0, + 1080, + 1085, + 1128, + 1125, + 0, + 1085, + 1090, + 1132, + 1128, + 0, + 1090, + 1093, + 1134, + 1132, + 0, + 1093, + 1096, + 1137, + 1134, + 0, + 1096, + 1100, + 1140, + 1137, + 0, + 1100, + 1098, + 1138, + 1140, + 0, + 1098, + 1095, + 1136, + 1138, + 0, + 1095, + 1092, + 1133, + 1136, + 0, + 1092, + 1089, + 1131, + 1133, + 0, + 1089, + 1083, + 1127, + 1131, + 0, + 1083, + 1079, + 1124, + 1127, + 0, + 1079, + 1072, + 1121, + 1124, + 0, + 1072, + 1070, + 1120, + 1121, + 0, + 1070, + 1066, + 1118, + 1120, + 0, + 1066, + 1062, + 1116, + 1118, + 0, + 1062, + 1060, + 1114, + 1116, + 0, + 1060, + 1045, + 1078, + 1114, + 0, + 1045, + 1043, + 1076, + 1078, + 0, + 1076, + 1086, + 1226, + 1220, + 0, + 1086, + 1117, + 1242, + 1226, + 0, + 1117, + 1119, + 1247, + 1242, + 0, + 1119, + 1122, + 1253, + 1247, + 0, + 1122, + 1126, + 1258, + 1253, + 0, + 1126, + 1129, + 1265, + 1258, + 0, + 1129, + 1135, + 1274, + 1265, + 0, + 1135, + 1141, + 1281, + 1274, + 0, + 1141, + 1143, + 1287, + 1281, + 0, + 1143, + 1145, + 1293, + 1287, + 0, + 1145, + 1147, + 1299, + 1293, + 0, + 1147, + 1149, + 1301, + 1299, + 0, + 1149, + 1151, + 1304, + 1301, + 0, + 1151, + 1152, + 1305, + 1304, + 0, + 1152, + 1150, + 1302, + 1305, + 0, + 1150, + 1148, + 1300, + 1302, + 0, + 1148, + 1146, + 1296, + 1300, + 0, + 1146, + 1144, + 1288, + 1296, + 0, + 1144, + 1142, + 1283, + 1288, + 0, + 1142, + 1139, + 1273, + 1283, + 0, + 1139, + 1130, + 1264, + 1273, + 0, + 1130, + 1104, + 1236, + 1264, + 0, + 1104, + 1097, + 1231, + 1236, + 0, + 1097, + 1084, + 1224, + 1231, + 0, + 1084, + 1077, + 1219, + 1224, + 0, + 1077, + 1071, + 1215, + 1219, + 0, + 1071, + 1067, + 1211, + 1215, + 0, + 1067, + 1063, + 1207, + 1211, + 0, + 1063, + 1058, + 1203, + 1207, + 0, + 1058, + 1055, + 1199, + 1203, + 0, + 1055, + 1051, + 1195, + 1199, + 0, + 1051, + 1046, + 1191, + 1195, + 0, + 1046, + 1039, + 1187, + 1191, + 0, + 1039, + 1035, + 1183, + 1187, + 0, + 1035, + 1031, + 1181, + 1183, + 0, + 1031, + 1020, + 1177, + 1181, + 0, + 1020, + 1013, + 1173, + 1177, + 0, + 1013, + 1002, + 1170, + 1173, + 0, + 1002, + 991, + 1164, + 1170, + 0, + 991, + 983, + 1161, + 1164, + 0, + 983, + 977, + 1159, + 1161, + 0, + 977, + 958, + 1153, + 1159, + 0, + 958, + 963, + 1154, + 1153, + 0, + 963, + 965, + 1156, + 1154, + 0, + 965, + 982, + 1160, + 1156, + 0, + 982, + 990, + 1163, + 1160, + 0, + 990, + 998, + 1167, + 1163, + 0, + 998, + 1011, + 1171, + 1167, + 0, + 1011, + 1019, + 1175, + 1171, + 0, + 1019, + 1029, + 1179, + 1175, + 0, + 1029, + 1036, + 1185, + 1179, + 0, + 1036, + 1041, + 1190, + 1185, + 0, + 1041, + 1047, + 1193, + 1190, + 0, + 1047, + 1052, + 1196, + 1193, + 0, + 1052, + 1056, + 1202, + 1196, + 0, + 1056, + 1059, + 1205, + 1202, + 0, + 1059, + 1065, + 1209, + 1205, + 0, + 1065, + 1069, + 1213, + 1209, + 0, + 1069, + 1074, + 1217, + 1213, + 0, + 1074, + 1082, + 1223, + 1217, + 0, + 1082, + 1091, + 1228, + 1223, + 0, + 1091, + 1115, + 1240, + 1228, + 0, + 1115, + 1123, + 1252, + 1240, + 0, + 1123, + 1125, + 1256, + 1252, + 0, + 1125, + 1128, + 1259, + 1256, + 0, + 1128, + 1132, + 1266, + 1259, + 0, + 1132, + 1134, + 1271, + 1266, + 0, + 1134, + 1137, + 1275, + 1271, + 0, + 1137, + 1140, + 1278, + 1275, + 0, + 1140, + 1138, + 1276, + 1278, + 0, + 1138, + 1136, + 1272, + 1276, + 0, + 1136, + 1133, + 1270, + 1272, + 0, + 1133, + 1131, + 1267, + 1270, + 0, + 1131, + 1127, + 1260, + 1267, + 0, + 1127, + 1124, + 1257, + 1260, + 0, + 1124, + 1121, + 1251, + 1257, + 0, + 1121, + 1120, + 1248, + 1251, + 0, + 1120, + 1118, + 1244, + 1248, + 0, + 1118, + 1116, + 1241, + 1244, + 0, + 1116, + 1114, + 1239, + 1241, + 0, + 1114, + 1078, + 1222, + 1239, + 0, + 1078, + 1076, + 1220, + 1222, + 0, + 1220, + 1226, + 1234, + 1229, + 0, + 1226, + 1242, + 1249, + 1234, + 0, + 1242, + 1247, + 1254, + 1249, + 0, + 1247, + 1253, + 1263, + 1254, + 0, + 1253, + 1258, + 1277, + 1263, + 0, + 1258, + 1265, + 1284, + 1277, + 0, + 1265, + 1274, + 1294, + 1284, + 0, + 1274, + 1281, + 1303, + 1294, + 0, + 1281, + 1287, + 1307, + 1303, + 0, + 1287, + 1293, + 1309, + 1307, + 0, + 1293, + 1299, + 1311, + 1309, + 0, + 1299, + 1301, + 1313, + 1311, + 0, + 1301, + 1304, + 1315, + 1313, + 0, + 1304, + 1305, + 1316, + 1315, + 0, + 1305, + 1302, + 1314, + 1316, + 0, + 1302, + 1300, + 1312, + 1314, + 0, + 1300, + 1296, + 1310, + 1312, + 0, + 1296, + 1288, + 1308, + 1310, + 0, + 1288, + 1283, + 1306, + 1308, + 0, + 1283, + 1273, + 1292, + 1306, + 0, + 1273, + 1264, + 1282, + 1292, + 0, + 1264, + 1236, + 1238, + 1282, + 0, + 1236, + 1231, + 1237, + 1238, + 0, + 1231, + 1224, + 1233, + 1237, + 0, + 1224, + 1219, + 1227, + 1233, + 0, + 1219, + 1215, + 1221, + 1227, + 0, + 1215, + 1211, + 1216, + 1221, + 0, + 1211, + 1207, + 1212, + 1216, + 0, + 1207, + 1203, + 1208, + 1212, + 0, + 1203, + 1199, + 1204, + 1208, + 0, + 1199, + 1195, + 1200, + 1204, + 0, + 1195, + 1191, + 1197, + 1200, + 0, + 1191, + 1187, + 1192, + 1197, + 0, + 1187, + 1183, + 1188, + 1192, + 0, + 1183, + 1181, + 1186, + 1188, + 0, + 1181, + 1177, + 1182, + 1186, + 0, + 1177, + 1173, + 1178, + 1182, + 0, + 1173, + 1170, + 1174, + 1178, + 0, + 1170, + 1164, + 1169, + 1174, + 0, + 1164, + 1161, + 1166, + 1169, + 0, + 1161, + 1159, + 1162, + 1166, + 0, + 1159, + 1153, + 1155, + 1162, + 0, + 1153, + 1154, + 1157, + 1155, + 0, + 1154, + 1156, + 1158, + 1157, + 0, + 1156, + 1160, + 1165, + 1158, + 0, + 1160, + 1163, + 1168, + 1165, + 0, + 1163, + 1167, + 1172, + 1168, + 0, + 1167, + 1171, + 1176, + 1172, + 0, + 1171, + 1175, + 1180, + 1176, + 0, + 1175, + 1179, + 1184, + 1180, + 0, + 1179, + 1185, + 1189, + 1184, + 0, + 1185, + 1190, + 1194, + 1189, + 0, + 1190, + 1193, + 1198, + 1194, + 0, + 1193, + 1196, + 1201, + 1198, + 0, + 1196, + 1202, + 1206, + 1201, + 0, + 1202, + 1205, + 1210, + 1206, + 0, + 1205, + 1209, + 1214, + 1210, + 0, + 1209, + 1213, + 1218, + 1214, + 0, + 1213, + 1217, + 1225, + 1218, + 0, + 1217, + 1223, + 1232, + 1225, + 0, + 1223, + 1228, + 1235, + 1232, + 0, + 1228, + 1240, + 1245, + 1235, + 0, + 1240, + 1252, + 1262, + 1245, + 0, + 1252, + 1256, + 1268, + 1262, + 0, + 1256, + 1259, + 1279, + 1268, + 0, + 1259, + 1266, + 1285, + 1279, + 0, + 1266, + 1271, + 1290, + 1285, + 0, + 1271, + 1275, + 1295, + 1290, + 0, + 1275, + 1278, + 1298, + 1295, + 0, + 1278, + 1276, + 1297, + 1298, + 0, + 1276, + 1272, + 1291, + 1297, + 0, + 1272, + 1270, + 1289, + 1291, + 0, + 1270, + 1267, + 1286, + 1289, + 0, + 1267, + 1260, + 1280, + 1286, + 0, + 1260, + 1257, + 1269, + 1280, + 0, + 1257, + 1251, + 1261, + 1269, + 0, + 1251, + 1248, + 1255, + 1261, + 0, + 1248, + 1244, + 1250, + 1255, + 0, + 1244, + 1241, + 1246, + 1250, + 0, + 1241, + 1239, + 1243, + 1246, + 0, + 1239, + 1222, + 1230, + 1243, + 0, + 1222, + 1220, + 1229, + 1230, + 0, + 1352, + 1229, + 1234, + 1356, + 0, + 1356, + 1234, + 1249, + 1363, + 0, + 1363, + 1249, + 1254, + 1365, + 0, + 1365, + 1254, + 1263, + 1369, + 0, + 1369, + 1263, + 1277, + 1372, + 0, + 1372, + 1277, + 1284, + 1377, + 0, + 1377, + 1284, + 1294, + 1384, + 0, + 1384, + 1294, + 1303, + 1387, + 0, + 1387, + 1303, + 1307, + 1389, + 0, + 1389, + 1307, + 1309, + 1392, + 0, + 1392, + 1309, + 1311, + 1394, + 0, + 1394, + 1311, + 1313, + 1396, + 0, + 1396, + 1313, + 1315, + 1398, + 0, + 1398, + 1315, + 1316, + 1397, + 0, + 1397, + 1316, + 1314, + 1395, + 0, + 1395, + 1314, + 1312, + 1393, + 0, + 1393, + 1312, + 1310, + 1391, + 0, + 1391, + 1310, + 1308, + 1390, + 0, + 1390, + 1308, + 1306, + 1388, + 0, + 1388, + 1306, + 1292, + 1381, + 0, + 1381, + 1292, + 1282, + 1375, + 0, + 1375, + 1282, + 1238, + 1359, + 0, + 1359, + 1238, + 1237, + 1358, + 0, + 1358, + 1237, + 1233, + 1355, + 0, + 1355, + 1233, + 1227, + 1351, + 0, + 1351, + 1227, + 1221, + 1349, + 0, + 1349, + 1221, + 1216, + 1347, + 0, + 1347, + 1216, + 1212, + 1345, + 0, + 1345, + 1212, + 1208, + 1343, + 0, + 1343, + 1208, + 1204, + 1341, + 0, + 1341, + 1204, + 1200, + 1339, + 0, + 1339, + 1200, + 1197, + 1337, + 0, + 1337, + 1197, + 1192, + 1335, + 0, + 1335, + 1192, + 1188, + 1333, + 0, + 1333, + 1188, + 1186, + 1332, + 0, + 1332, + 1186, + 1182, + 1330, + 0, + 1330, + 1182, + 1178, + 1328, + 0, + 1328, + 1178, + 1174, + 1326, + 0, + 1326, + 1174, + 1169, + 1324, + 0, + 1324, + 1169, + 1166, + 1322, + 0, + 1322, + 1166, + 1162, + 1320, + 0, + 1320, + 1162, + 1155, + 1317, + 0, + 1317, + 1155, + 1157, + 1318, + 0, + 1318, + 1157, + 1158, + 1319, + 0, + 1319, + 1158, + 1165, + 1321, + 0, + 1321, + 1165, + 1168, + 1323, + 0, + 1323, + 1168, + 1172, + 1325, + 0, + 1325, + 1172, + 1176, + 1327, + 0, + 1327, + 1176, + 1180, + 1329, + 0, + 1329, + 1180, + 1184, + 1331, + 0, + 1331, + 1184, + 1189, + 1334, + 0, + 1334, + 1189, + 1194, + 1336, + 0, + 1336, + 1194, + 1198, + 1338, + 0, + 1338, + 1198, + 1201, + 1340, + 0, + 1340, + 1201, + 1206, + 1342, + 0, + 1342, + 1206, + 1210, + 1344, + 0, + 1344, + 1210, + 1214, + 1346, + 0, + 1346, + 1214, + 1218, + 1348, + 0, + 1348, + 1218, + 1225, + 1350, + 0, + 1350, + 1225, + 1232, + 1354, + 0, + 1354, + 1232, + 1235, + 1357, + 0, + 1357, + 1235, + 1245, + 1360, + 0, + 1360, + 1245, + 1262, + 1367, + 0, + 1367, + 1262, + 1268, + 1370, + 0, + 1370, + 1268, + 1279, + 1373, + 0, + 1373, + 1279, + 1285, + 1376, + 0, + 1376, + 1285, + 1290, + 1379, + 0, + 1379, + 1290, + 1295, + 1383, + 0, + 1383, + 1295, + 1298, + 1386, + 0, + 1386, + 1298, + 1297, + 1385, + 0, + 1385, + 1297, + 1291, + 1382, + 0, + 1382, + 1291, + 1289, + 1380, + 0, + 1380, + 1289, + 1286, + 1378, + 0, + 1378, + 1286, + 1280, + 1374, + 0, + 1374, + 1280, + 1269, + 1371, + 0, + 1371, + 1269, + 1261, + 1368, + 0, + 1368, + 1261, + 1255, + 1366, + 0, + 1366, + 1255, + 1250, + 1364, + 0, + 1364, + 1250, + 1246, + 1362, + 0, + 1362, + 1246, + 1243, + 1361, + 0, + 1361, + 1243, + 1230, + 1353, + 0, + 1353, + 1230, + 1229, + 1352, + 0, + 54, + 60, + 56, + 0, + 60, + 78, + 56, + 0, + 78, + 85, + 75, + 0, + 85, + 90, + 82, + 0, + 90, + 96, + 87, + 0, + 96, + 100, + 91, + 0, + 100, + 105, + 94, + 0, + 105, + 115, + 94, + 0, + 115, + 118, + 98, + 0, + 118, + 122, + 102, + 0, + 122, + 124, + 106, + 0, + 124, + 127, + 109, + 0, + 127, + 129, + 112, + 0, + 129, + 132, + 114, + 0, + 132, + 131, + 113, + 0, + 131, + 128, + 113, + 0, + 128, + 125, + 110, + 0, + 125, + 123, + 107, + 0, + 123, + 121, + 101, + 0, + 121, + 116, + 99, + 0, + 116, + 108, + 95, + 0, + 108, + 72, + 81, + 0, + 72, + 70, + 67, + 0, + 70, + 66, + 65, + 0, + 66, + 62, + 61, + 0, + 62, + 58, + 55, + 0, + 58, + 53, + 50, + 0, + 53, + 49, + 46, + 0, + 49, + 45, + 46, + 0, + 45, + 41, + 42, + 0, + 41, + 38, + 37, + 0, + 38, + 33, + 34, + 0, + 33, + 29, + 31, + 0, + 29, + 25, + 26, + 0, + 25, + 22, + 26, + 0, + 22, + 18, + 21, + 0, + 18, + 15, + 17, + 0, + 15, + 13, + 14, + 0, + 13, + 11, + 14, + 0, + 11, + 7, + 12, + 0, + 7, + 4, + 9, + 0, + 4, + 1, + 3, + 0, + 1, + 2, + 3, + 0, + 3, + 6, + 4, + 0, + 6, + 9, + 4, + 0, + 9, + 12, + 7, + 0, + 12, + 14, + 11, + 0, + 14, + 17, + 15, + 0, + 17, + 21, + 18, + 0, + 21, + 26, + 22, + 0, + 26, + 31, + 29, + 0, + 31, + 34, + 33, + 0, + 34, + 37, + 38, + 0, + 37, + 42, + 41, + 0, + 42, + 46, + 45, + 0, + 46, + 50, + 53, + 0, + 50, + 55, + 58, + 0, + 55, + 61, + 62, + 0, + 61, + 65, + 66, + 0, + 65, + 67, + 70, + 0, + 67, + 81, + 72, + 0, + 81, + 95, + 108, + 0, + 95, + 99, + 116, + 0, + 99, + 101, + 121, + 0, + 101, + 107, + 123, + 0, + 107, + 110, + 125, + 0, + 110, + 113, + 128, + 0, + 113, + 114, + 132, + 0, + 114, + 112, + 129, + 0, + 112, + 109, + 127, + 0, + 109, + 106, + 124, + 0, + 106, + 102, + 122, + 0, + 102, + 98, + 118, + 0, + 98, + 94, + 115, + 0, + 94, + 91, + 100, + 0, + 91, + 87, + 96, + 0, + 87, + 82, + 90, + 0, + 82, + 75, + 85, + 0, + 75, + 73, + 78, + 0, + 73, + 56, + 78, + 0, + 697, + 693, + 694, + 0, + 694, + 703, + 706, + 0, + 703, + 704, + 706, + 0, + 704, + 707, + 708, + 0, + 707, + 709, + 711, + 0, + 709, + 710, + 714, + 0, + 710, + 713, + 718, + 0, + 713, + 716, + 730, + 0, + 716, + 719, + 734, + 0, + 719, + 722, + 736, + 0, + 722, + 725, + 739, + 0, + 725, + 726, + 741, + 0, + 726, + 728, + 744, + 0, + 728, + 727, + 745, + 0, + 727, + 724, + 740, + 0, + 724, + 721, + 738, + 0, + 721, + 717, + 735, + 0, + 717, + 715, + 733, + 0, + 715, + 712, + 729, + 0, + 712, + 705, + 720, + 0, + 705, + 700, + 702, + 0, + 700, + 698, + 701, + 0, + 698, + 695, + 699, + 0, + 695, + 691, + 696, + 0, + 691, + 689, + 692, + 0, + 689, + 687, + 690, + 0, + 687, + 685, + 686, + 0, + 685, + 682, + 684, + 0, + 682, + 672, + 683, + 0, + 672, + 663, + 671, + 0, + 663, + 651, + 659, + 0, + 651, + 642, + 643, + 0, + 642, + 638, + 639, + 0, + 638, + 632, + 635, + 0, + 632, + 628, + 627, + 0, + 628, + 625, + 622, + 0, + 625, + 620, + 615, + 0, + 620, + 608, + 615, + 0, + 608, + 606, + 604, + 0, + 604, + 615, + 608, + 0, + 615, + 622, + 625, + 0, + 622, + 627, + 628, + 0, + 627, + 630, + 632, + 0, + 630, + 635, + 632, + 0, + 635, + 639, + 638, + 0, + 639, + 643, + 642, + 0, + 643, + 649, + 651, + 0, + 649, + 659, + 651, + 0, + 659, + 671, + 663, + 0, + 671, + 683, + 672, + 0, + 683, + 684, + 682, + 0, + 684, + 686, + 685, + 0, + 686, + 688, + 687, + 0, + 688, + 690, + 687, + 0, + 690, + 692, + 689, + 0, + 692, + 696, + 691, + 0, + 696, + 699, + 695, + 0, + 699, + 701, + 698, + 0, + 701, + 702, + 700, + 0, + 702, + 720, + 705, + 0, + 720, + 729, + 712, + 0, + 729, + 732, + 733, + 715, + 0, + 733, + 735, + 717, + 0, + 735, + 738, + 721, + 0, + 738, + 740, + 724, + 0, + 740, + 743, + 727, + 0, + 743, + 745, + 727, + 0, + 745, + 744, + 728, + 0, + 744, + 741, + 726, + 0, + 741, + 739, + 725, + 0, + 739, + 736, + 722, + 0, + 736, + 734, + 719, + 0, + 734, + 730, + 716, + 0, + 730, + 723, + 713, + 0, + 723, + 718, + 713, + 0, + 718, + 714, + 710, + 0, + 714, + 711, + 709, + 0, + 711, + 708, + 707, + 0, + 708, + 706, + 704, + 0, + 706, + 697, + 694, + 0, + 1356, + 1352, + 1353, + 0, + 1353, + 1361, + 1363, + 0, + 1361, + 1362, + 1363, + 0, + 1362, + 1364, + 1365, + 0, + 1364, + 1366, + 1369, + 0, + 1366, + 1368, + 1372, + 0, + 1368, + 1371, + 1377, + 0, + 1371, + 1374, + 1387, + 0, + 1374, + 1378, + 1389, + 0, + 1378, + 1380, + 1392, + 0, + 1380, + 1382, + 1394, + 0, + 1382, + 1385, + 1396, + 0, + 1385, + 1386, + 1398, + 0, + 1386, + 1383, + 1397, + 0, + 1383, + 1379, + 1393, + 0, + 1379, + 1376, + 1391, + 0, + 1376, + 1373, + 1390, + 0, + 1373, + 1370, + 1388, + 0, + 1370, + 1367, + 1381, + 0, + 1367, + 1360, + 1375, + 0, + 1360, + 1357, + 1359, + 0, + 1357, + 1354, + 1358, + 0, + 1354, + 1350, + 1355, + 0, + 1350, + 1348, + 1351, + 0, + 1348, + 1346, + 1349, + 0, + 1346, + 1344, + 1347, + 0, + 1344, + 1342, + 1343, + 0, + 1342, + 1340, + 1341, + 0, + 1340, + 1338, + 1339, + 0, + 1338, + 1336, + 1337, + 0, + 1336, + 1334, + 1335, + 0, + 1334, + 1331, + 1332, + 0, + 1331, + 1329, + 1330, + 0, + 1329, + 1327, + 1328, + 0, + 1327, + 1325, + 1324, + 0, + 1325, + 1323, + 1322, + 0, + 1323, + 1321, + 1320, + 0, + 1321, + 1319, + 1320, + 0, + 1319, + 1318, + 1317, + 0, + 1317, + 1320, + 1319, + 0, + 1320, + 1322, + 1323, + 0, + 1322, + 1324, + 1325, + 0, + 1324, + 1326, + 1327, + 0, + 1326, + 1328, + 1327, + 0, + 1328, + 1330, + 1329, + 0, + 1330, + 1332, + 1331, + 0, + 1332, + 1333, + 1334, + 0, + 1333, + 1335, + 1334, + 0, + 1335, + 1337, + 1336, + 0, + 1337, + 1339, + 1338, + 0, + 1339, + 1341, + 1340, + 0, + 1341, + 1343, + 1342, + 0, + 1343, + 1345, + 1344, + 0, + 1345, + 1347, + 1344, + 0, + 1347, + 1349, + 1346, + 0, + 1349, + 1351, + 1348, + 0, + 1351, + 1355, + 1350, + 0, + 1355, + 1358, + 1354, + 0, + 1358, + 1359, + 1357, + 0, + 1359, + 1375, + 1360, + 0, + 1375, + 1381, + 1367, + 0, + 1381, + 1388, + 1370, + 0, + 1388, + 1390, + 1373, + 0, + 1390, + 1391, + 1376, + 0, + 1391, + 1393, + 1379, + 0, + 1393, + 1395, + 1383, + 0, + 1395, + 1397, + 1383, + 0, + 1397, + 1398, + 1386, + 0, + 1398, + 1396, + 1385, + 0, + 1396, + 1394, + 1382, + 0, + 1394, + 1392, + 1380, + 0, + 1392, + 1389, + 1378, + 0, + 1389, + 1387, + 1374, + 0, + 1387, + 1384, + 1371, + 0, + 1384, + 1377, + 1371, + 0, + 1377, + 1372, + 1368, + 0, + 1372, + 1369, + 1366, + 0, + 1369, + 1365, + 1364, + 0, + 1365, + 1363, + 1362, + 0, + 1363, + 1356, + 1353, + 0, + 693, + 697, + 694, + 0, + 697, + 706, + 694, + 0, + 706, + 708, + 704, + 0, + 708, + 711, + 707, + 0, + 711, + 714, + 709, + 0, + 714, + 718, + 710, + 0, + 718, + 723, + 713, + 0, + 723, + 730, + 713, + 0, + 730, + 734, + 716, + 0, + 734, + 736, + 719, + 0, + 736, + 739, + 722, + 0, + 739, + 741, + 725, + 0, + 741, + 744, + 726, + 0, + 744, + 745, + 728, + 0, + 745, + 743, + 727, + 0, + 743, + 740, + 727, + 0, + 740, + 738, + 724, + 0, + 738, + 735, + 721, + 0, + 735, + 733, + 717, + 0, + 733, + 732, + 729, + 715, + 0, + 729, + 720, + 712, + 0, + 720, + 702, + 705, + 0, + 702, + 701, + 700, + 0, + 701, + 699, + 698, + 0, + 699, + 696, + 695, + 0, + 696, + 692, + 691, + 0, + 692, + 690, + 689, + 0, + 690, + 688, + 687, + 0, + 688, + 686, + 687, + 0, + 686, + 684, + 685, + 0, + 684, + 683, + 682, + 0, + 683, + 671, + 672, + 0, + 671, + 659, + 663, + 0, + 659, + 649, + 651, + 0, + 649, + 643, + 651, + 0, + 643, + 639, + 642, + 0, + 639, + 635, + 638, + 0, + 635, + 630, + 632, + 0, + 630, + 627, + 632, + 0, + 627, + 622, + 628, + 0, + 622, + 615, + 625, + 0, + 615, + 604, + 608, + 0, + 604, + 606, + 608, + 0, + 608, + 620, + 615, + 0, + 620, + 625, + 615, + 0, + 625, + 628, + 622, + 0, + 628, + 632, + 627, + 0, + 632, + 638, + 635, + 0, + 638, + 642, + 639, + 0, + 642, + 651, + 643, + 0, + 651, + 663, + 659, + 0, + 663, + 672, + 671, + 0, + 672, + 682, + 683, + 0, + 682, + 685, + 684, + 0, + 685, + 687, + 686, + 0, + 687, + 689, + 690, + 0, + 689, + 691, + 692, + 0, + 691, + 695, + 696, + 0, + 695, + 698, + 699, + 0, + 698, + 700, + 701, + 0, + 700, + 705, + 702, + 0, + 705, + 712, + 720, + 0, + 712, + 715, + 729, + 0, + 715, + 717, + 733, + 0, + 717, + 721, + 735, + 0, + 721, + 724, + 738, + 0, + 724, + 727, + 740, + 0, + 727, + 728, + 745, + 0, + 728, + 726, + 744, + 0, + 726, + 725, + 741, + 0, + 725, + 722, + 739, + 0, + 722, + 719, + 736, + 0, + 719, + 716, + 734, + 0, + 716, + 713, + 730, + 0, + 713, + 710, + 718, + 0, + 710, + 709, + 714, + 0, + 709, + 707, + 711, + 0, + 707, + 704, + 708, + 0, + 704, + 703, + 706, + 0, + 703, + 694, + 706, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/outside.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/outside.json index 9ef9805da7d6..c28bfb57aa4a 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/outside.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/outside.json @@ -1 +1,59678 @@ -{"indexedMesh":{"point":[[508710.84184697916,6651127.894657594,90.64963022028905],[508710.63451255544,6651128.467916771,90.64963022028905],[508710.63451255544,6651128.467916771,90.77963022028906],[508710.84184697916,6651127.894657594,92.47843387928906],[508710.63451255544,6651128.467916771,92.47843387928906],[508710.83471814217,6651127.914368123,92.94402456628906],[508710.62822240515,6651128.485308414,92.88924919128907],[508710.81242531847,6651127.976005576,93.42129551828906],[508710.6085522666,6651128.539694401,93.31037061928907],[508710.77381871856,6651128.082749007,93.90419653828906],[508710.5744876195,6651128.633879782,93.73645975428906],[508710.7336672429,6651128.193763865,94.26590252328907],[508710.52533278905,6651128.769788027,94.16136625828906],[508710.6837179477,6651128.331868728,94.62366036928907],[508710.46079327207,6651128.94823341,94.57833296028907],[508710.6239648667,6651128.497080087,94.97411658428906],[508710.381039242,6651129.168745415,94.98028187728906],[508710.5545772241,6651128.688930056,95.31386161128906],[508710.47590531467,6651128.906450105,95.63952872128907],[508710.28673993266,6651129.429473679,95.36016267928906],[508710.3884785856,6651129.1481763655,95.94789752928908],[508710.2071537418,6651129.649521626,95.62656899428906],[508710.12069504283,6651129.888571378,95.87427873428906],[508710.2929955248,6651129.412177585,96.23599588028905],[508710.190305617,6651129.696105025,96.50119360528906],[508709.9961057662,6651130.233048406,96.17172120428907],[508710.0813843083,6651129.997261671,96.74128205228907],[508709.86285567685,6651130.601471727,96.42793432728907],[508709.96730251657,6651130.312686544,96.95453438728906],[508709.723289706,6651130.9873578325,96.64021213628908],[508706.4851137081,6651139.940594222,90.64963022028905],[508706.4851137081,6651139.940594222,90.77963022028906],[508709.849192655,6651130.639248629,97.13974328928906],[508706.2777792843,6651140.513853399,90.64963022028905],[508709.57982625184,6651131.384020096,96.80732689328907],[508709.7282133653,6651130.973744401,97.29623458128906],[508709.4348317733,6651131.784915489,96.92948001528907],[508709.60551513615,6651131.31299287,97.42385734028906],[508709.2905118211,6651132.183945884,97.00815470828906],[508709.4822087595,6651131.653922807,97.52295283428906],[508709.14882702165,6651132.575690342,97.04589756728906],[508709.3186461469,6651132.106157256,97.61211748628907],[508706.4851129126,6651139.940596422,92.47843388028906],[508706.4866588913,6651139.936321944,92.68225516428906],[508709.15807004046,6651132.55013431,97.65489272728908],[508706.2777792843,6651140.513853399,92.47843387928906],[508706.49949579797,6651139.900829167,93.09883445228905],[508708.55362604477,6651134.221362181,97.04589756728906],[508706.28490812134,6651140.49414287,92.94402456628906],[508706.5262542289,6651139.826844751,93.52316157228907],[508706.30720094504,6651140.432505418,93.42129551828906],[508706.5678003188,6651139.711973921,93.94947192328905],[508706.6246385284,6651139.554821893,94.37128078228906],[508706.34580754495,6651140.325761987,93.90419653828906],[508707.97079844604,6651135.832822851,97.04589756728906],[508706.6968373622,6651139.355199258,94.78163032528906],[508706.3859590205,6651140.214747127,94.26590252328907],[508707.8291136465,6651136.224567309,97.00815470828906],[508706.78397924855,6651139.11426056,95.17341001928907],[508707.68479369435,6651136.623597706,96.92948001528907],[508706.43590831576,6651140.076642266,94.62366036928907],[508706.8586069096,6651138.907922458,95.45089187928906],[508707.5397992159,6651137.024493099,96.80732689328907],[508706.9405642631,6651138.681318481,95.71133255228906],[508707.96155622305,6651135.858376684,97.65489272728908],[508707.0291440019,6651138.436404263,95.95230219828906],[508707.3963357616,6651137.4211553605,96.64021213628908],[508706.4956613969,6651139.9114309065,94.97411658428906],[508707.1235197014,6651138.175464787,96.17172120428907],[508707.25676979084,6651137.807041467,96.42793432728907],[508706.5650490394,6651139.719580937,95.31386161128906],[508707.8009801167,6651136.302353737,97.61211748628907],[508706.64372094884,6651139.502060887,95.63952872128907],[508707.637417504,6651136.754588186,97.52295283428906],[508706.7311476779,6651139.260334628,95.94789752928908],[508707.5141111274,6651137.095518122,97.42385734028906],[508706.8266307387,6651138.996333408,96.23599588028905],[508707.3914128982,6651137.4347665915,97.29623458128906],[508706.9293206465,6651138.712405968,96.50119360528906],[508707.27043360844,6651137.769262364,97.13974328928906],[508707.0382419553,6651138.411249321,96.74128205228907],[508707.1523237469,6651138.095824449,96.95453438728906],[508719.34644272923,6651130.970570781,90.78879207594775],[508719.1391083054,6651131.543829958,90.78879207594775],[508719.1391083054,6651131.543829958,90.91879207594776],[508720.23537689366,6651131.291833014,90.80304684876648],[508719.34644272923,6651130.970570781,92.61759573494776],[508720.02832132427,6651131.86519297,90.80304684876648],[508720.02832132427,6651131.86519297,90.9330468487665],[508719.1391083054,6651131.543829958,92.61759573494776],[508719.3393138921,6651130.990281312,93.08318642194777],[508719.1328181552,6651131.561221601,93.02841104694775],[508719.3170210684,6651131.051918764,93.56045737394776],[508719.11314801656,6651131.61560759,93.44953247494776],[508720.23537689366,6651131.291833014,92.63185050776649],[508719.2784144686,6651131.158662194,94.04335839394776],[508719.07908336946,6651131.70979297,93.87562160994777],[508720.02832132427,6651131.86519297,92.63185050776649],[508719.238262993,6651131.269677053,94.40506437894776],[508720.2282576446,6651131.311547009,93.0974411947665],[508719.029928539,6651131.845701215,94.30052811394776],[508720.02203963394,6651131.882587671,93.0426658197665],[508719.18831369776,6651131.407781915,94.76282222494775],[508720.2059948036,6651131.373195298,93.57471214676649],[508718.9653890221,6651132.024146597,94.71749481594776],[508720.0023959507,6651131.93698322,93.46378724776649],[508719.12856061663,6651131.572993275,95.11327843994776],[508720.1674401276,6651131.479957494,94.05761316676649],[508719.9683771189,6651132.0311851585,93.88987638276649],[508718.88563499204,6651132.244658602,95.11944373294777],[508719.05917297414,6651131.764843244,95.45302346694776],[508720.1273426537,6651131.59099187,94.41931915176649],[508719.91928839916,6651132.167117296,94.3147828867665],[508718.9805010646,6651131.982363293,95.77869057694775],[508718.7913356826,6651132.505386867,95.49932453494776],[508720.07746053784,6651131.72912101,94.77707699776649],[508718.8930743356,6651132.224089553,96.08705938494776],[508718.7117494918,6651132.725434814,95.76573084994776],[508719.8548356846,6651132.345594048,94.7317495887665],[508720.0177878216,6651131.894361413,95.1275332127665],[508718.6252907928,6651132.964484566,96.01344058994778],[508718.7975912748,6651132.488090773,96.37515773594775],[508719.7751889197,6651132.56614482,95.1336985057665],[508719.948493502,6651132.08624511,95.46727823976649],[508718.694901367,6651132.772018213,96.64035546094777],[508718.5007015163,6651133.3089615945,96.31088305994776],[508719.86992740224,6651132.303803399,95.7929453497665],[508719.68101643823,6651132.82691892,95.51357930776649],[508718.58598005824,6651133.07317486,96.88044390794778],[508718.3674514268,6651133.677384914,96.56709618294778],[508719.78261825774,6651132.545572154,96.10131415776651],[508719.60153728677,6651133.047005552,95.77998562276649],[508718.4718982665,6651133.388599731,97.09369624294777],[508718.227885456,6651134.063271021,96.77937399194776],[508714.9897094581,6651143.01650741,90.78879207594775],[508719.5151948704,6651133.286097328,96.0276953627665],[508719.68726361694,6651132.809619785,96.38941250876648],[508714.9897094581,6651143.01650741,90.91879207594776],[508718.3537884051,6651133.715161817,97.27890514494776],[508714.78237503424,6651143.589766587,90.78879207594775],[508718.0844220018,6651134.459933283,96.94648874894776],[508719.58471182187,6651133.093597139,96.65461023376649],[508719.3907731602,6651133.630634915,96.3251378327665],[508718.23280911526,6651134.049657589,97.43539643694777],[508717.93942752335,6651134.860828677,97.06864187094776],[508719.4759370069,6651133.394806729,96.8946986807665],[508718.1101108861,6651134.388906058,97.56301919594776],[508719.2577022854,6651133.999123003,96.5813509557665],[508717.7951075712,6651135.259859072,97.14731656394775],[508717.9868045096,6651134.7298359955,97.66211468994776],[508719.36200864945,6651133.710287051,97.10795101576649],[508717.65342277166,6651135.65160353,97.18505942294776],[508719.11832402385,6651134.385076948,96.79362876476651],[508715.8845032102,6651143.339887308,90.80304684876648],[508715.8845032102,6651143.339887308,90.9330468487665],[508717.82324189687,6651135.182070444,97.75127934194776],[508719.24405763973,6651134.036906548,97.29315991776649],[508714.98970866256,6651143.01650961,92.61759573594777],[508715.6774476409,6651143.913247264,90.80304684876648],[508718.9750535208,6651134.7818089435,96.9607435217665],[508714.99125464127,6651143.012235131,92.82141701994776],[508717.6626657904,6651135.626047498,97.79405458294777],[508719.12324106105,6651134.371461123,97.44965120976649],[508714.78237503424,6651143.589766587,92.61759573494776],[508718.8302540526,6651135.182774814,97.0828966437665],[508715.0040915479,6651142.976742355,93.23799630794775],[508719.00070785487,6651134.710769232,97.57727396876649],[508717.05822179484,6651137.297275369,97.18505942294776],[508714.78950387135,6651143.5700560585,93.08318642194777],[508718.6861282035,6651135.581875358,97.16157133676649],[508715.03084997885,6651142.90275794,93.66232342794775],[508718.8775673192,6651135.051759104,97.67636946276649],[508718.544633963,6651135.973688684,97.19931419576649],[508714.81179669505,6651143.508418606,93.56045737394776],[508715.0723960689,6651142.787887109,94.08863377894775],[508718.71422469,6651135.5040730545,97.7655341147665],[508715.8845024158,6651143.339889509,92.6318505087665],[508715.12923427834,6651142.630735081,94.51044263794776],[508714.85040329496,6651143.401675175,94.04335839394776],[508715.8860463153,6651143.335614278,92.83567179276649],[508718.5538645504,6651135.94812816,97.80830935576651],[508716.47539419605,6651138.908736039,97.18505942294776],[508715.20143311226,6651142.431112445,94.92079218094777],[508715.6774476409,6651143.913247264,92.63185050776649],[508714.8905547706,6651143.290660315,94.40506437894776],[508716.3337093965,6651139.300480497,97.14731656394775],[508715.2885749985,6651142.190173748,95.31257187494776],[508715.89886595693,6651143.300115261,93.25225108076648],[508716.18938944436,6651139.699510893,97.06864187094776],[508714.94050406583,6651143.152555454,94.76282222494775],[508715.36320265953,6651141.983835646,95.59005373494777],[508717.9502335017,6651137.619649831,97.19931419576649],[508716.04439496587,6651140.100406287,96.94648874894776],[508715.44516001304,6651141.7572316695,95.85049440794778],[508715.68456689,6651143.893533269,93.0974411947665],[508716.46615197306,6651138.934289873,97.79405458294777],[508715.53373975185,6651141.512317451,96.09146405394776],[508715.9009315116,6651140.497068549,96.77937399194776],[508715.00025714684,6651142.987344094,95.11327843994776],[508715.62811545137,6651141.251377975,96.31088305994776],[508715.7613655408,6651140.882954656,96.56709618294778],[508715.92558839906,6651143.22611784,93.6765782007665],[508715.06964478944,6651142.795494125,95.45302346694776],[508716.3055758666,6651139.378266925,97.75127934194776],[508715.706829731,6651143.83188498,93.57471214676649],[508715.1483166988,6651142.577974075,95.77869057694775],[508715.96707861166,6651143.111226816,94.10288855176648],[508716.142013254,6651139.830501375,97.66211468994776],[508715.23574342794,6651142.336247816,96.08705938494776],[508716.01870687737,6651140.1714313105,97.56301919594776],[508715.33122648863,6651142.072246595,96.37515773594775],[508715.89600864815,6651140.5106797805,97.43539643694777],[508716.0238403766,6651142.95404716,94.52469741076649],[508715.4339163965,6651141.7883191565,96.64035546094777],[508715.7750293585,6651140.845175552,97.27890514494776],[508715.54283770523,6651141.48716251,96.88044390794778],[508715.65691949695,6651141.171737637,97.09369624294777],[508715.7453844069,6651143.725122785,94.05761316676649],[508717.3681897767,6651139.2313937945,97.19931419576649],[508716.09594210674,6651142.754389431,94.93504695376649],[508715.78548188077,6651143.614088409,94.41931915176649],[508717.22669553617,6651139.623207121,97.16157133676649],[508716.18296679156,6651142.513408378,95.3268266477665],[508717.0825696871,6651140.022307666,97.0828966437665],[508715.83536399674,6651143.475959268,94.77707699776649],[508716.2574940821,6651142.307034001,95.6043085077665],[508716.9377702189,6651140.423273537,96.9607435217665],[508716.33934120706,6651142.080390187,95.86474918076651],[508717.35895998415,6651139.256952119,97.80830935576651],[508716.42780181055,6651141.835432913,96.10571882676649],[508716.79449971585,6651140.820005531,96.79362876476651],[508715.89503671293,6651143.310718865,95.1275332127665],[508716.5220505795,6651141.574447565,96.3251378327665],[508716.65512145427,6651141.2059594765,96.5813509557665],[508715.9643310326,6651143.11883517,95.46727823976649],[508717.1985998445,6651139.701007224,97.7655341147665],[508716.0428971322,6651142.901276879,95.7929453497665],[508717.0352572153,6651140.153321175,97.67636946276649],[508716.13020627684,6651142.659508124,96.10131415776651],[508716.9121166796,6651140.494311047,97.57727396876649],[508716.2255609175,6651142.395460493,96.38941250876648],[508716.7895834734,6651140.833619155,97.44965120976649],[508716.3281127127,6651142.11148314,96.65461023376649],[508716.6687668947,6651141.168173731,97.29315991776649],[508716.4368875277,6651141.8102735495,96.8946986807665],[508716.550815885,6651141.494793227,97.10795101576649],[508729.8143226638,6651134.722724985,90.95204076656832],[508729.8786742204,6651134.745582613,90.9530132307946],[508729.61027196544,6651135.2971611945,90.95204076656832],[508729.6746437088,6651135.320025993,90.9530132307946],[508729.61027196544,6651135.2971611945,91.08204076656834],[508729.6746437088,6651135.320025993,91.08301323079462],[508729.8143226638,6651134.722724985,92.78084442556833],[508729.8786742204,6651134.745582613,92.78181688979461],[508729.61027196544,6651135.2971611945,92.78084442556833],[508729.807306732,6651134.742475984,93.24643511256832],[508729.6746437088,6651135.320025993,92.78181688979461],[508729.8716589827,6651134.765333859,93.2474075767946],[508729.6040814375,6651135.314588548,93.19165973756832],[508729.6684537933,6651135.337453564,93.1926322017946],[508729.7853669781,6651134.804239994,93.72370606456832],[508729.84972139925,6651134.827098639,93.7246785287946],[508729.584722831,6651135.369086202,93.61278116556832],[508729.649097102,6651135.391951898,93.6137536297946],[508729.7473718226,6651134.911202593,94.20660708456833],[508729.81173000264,6651134.934062573,94.20757954879461],[508729.55119769374,6651135.463464968,94.03887030056832],[508729.6155752814,6651135.486331842,94.0398427647946],[508729.7078562588,6651135.022445392,94.56831306956832],[508729.77221834817,6651135.04530676,94.5692855337946],[508729.50282136863,6651135.599652262,94.46377680456833],[508729.56720374216,6651135.622520837,94.4647492687946],[508729.6586980516,6651135.160833814,94.92607091556832],[508729.72306500416,6651135.183696911,94.9270433797946],[508729.439304017,6651135.778464034,94.88074350656832],[508729.599891329,6651135.326384392,95.27652713056834],[508729.5036926743,6651135.801334841,94.8817159707946],[508729.66426409944,6651135.349249553,95.27749959479462],[508729.36081311695,6651135.999428803,95.28269242356832],[508729.5316026356,6651135.518628272,95.61627215756833],[508729.42520953936,6651136.022302366,95.2836648877946],[508729.59598216176,6651135.5414958345,95.61724462179461],[508729.45417671767,6651135.73659494,95.94193926756832],[508729.26800730306,6651136.260692402,95.66257322556834],[508729.51856390364,6651135.759465223,95.9429117317946],[508729.33241290686,6651136.283569227,95.66354568979462],[508729.3681346375,6651135.97881752,96.25030807556833],[508729.189681584,6651136.481192158,95.92897954056832],[508729.43253033556,6651136.001690826,96.2512805397946],[508729.2540949366,6651136.504071737,95.9299520047946],[508729.1045922024,6651136.720732735,96.17668928056834],[508729.2741638204,6651136.243360795,96.53840642656833],[508729.1690139728,6651136.743615302,96.17766174479462],[508729.338568815,6651136.266237404,96.5393788907946],[508729.1731002968,6651136.527871204,96.80360415156832],[508728.98197614856,6651137.065917053,96.47413175056832],[508729.2375152897,6651136.550751365,96.8045766157946],[508729.04641004937,6651137.088803929,96.4751042147946],[508729.0659040642,6651136.829646194,97.04369259856833],[508728.8508364501,6651137.435096831,96.73034487356833],[508729.13032966206,6651136.852530121,97.0446650627946],[508728.91528332455,6651137.457988316,96.73131733779461],[508728.95362907957,6651137.145718706,97.25694493356833],[508729.01806578477,6651137.168606578,97.25791739779461],[508728.7134809001,6651137.821775251,96.94262268256833],[508725.52659055294,6651146.793394702,90.95204076656832],[508728.7779413633,6651137.844671562,96.9435951467946],[508725.59136629594,6651146.816403001,90.9530132307946],[508725.52659055294,6651146.793394702,91.08204076656834],[508728.8373898208,6651137.4729512995,97.44215383556832],[508725.59136629594,6651146.816403001,91.08301323079462],[508728.9018380256,6651137.495843258,97.4431262997946],[508728.5722895944,6651138.219251953,97.10973743956832],[508725.32253985456,6651147.367830913,90.95204076656832],[508728.6367640256,6651138.242153226,97.1107099037946],[508725.38733578427,6651147.390846381,90.9530132307946],[508728.7183265793,6651137.8081338685,97.59864512756832],[508728.78278656316,6651137.831030009,97.5996175917946],[508728.4295915124,6651138.620970477,97.23189056156832],[508728.4940800608,6651138.643876764,97.2328630257946],[508728.59757162275,6651138.148078892,97.72626788656834],[508728.6620435529,6651138.170979277,97.72724035079462],[508728.2875572738,6651139.020820174,97.31056525456833],[508728.3520598737,6651139.043731453,97.31153771879461],[508728.47621815046,6651138.489708837,97.82536338056833],[508728.5407020861,6651138.5126134865,97.82633584479461],[508728.14811645274,6651139.413368974,97.34830811356832],[508728.21263284754,6651139.436285153,97.3492805777946],[508728.3152460131,6651138.942871828,97.91452803256834],[508728.3797458737,6651138.965782133,97.9155004967946],[508725.52658977,6651146.793396905,92.78084442656832],[508725.591365513,6651146.816405204,92.7818168907946],[508728.15721308225,6651139.38776047,97.95730327356833],[508735.7087237135,6651136.805857087,91.03954345236868],[508725.52811126376,6651146.789113652,92.98466571056832],[508728.22172857705,6651139.4106763275,97.95827573779461],[508725.5928868563,6651146.812121895,92.9856381747946],[508725.32253985456,6651147.367830913,92.78084442556833],[508725.38733578427,6651147.390846381,92.78181688979461],[508735.5065220615,6651137.380946767,91.03954345236868],[508725.5407448617,6651146.753547998,93.40124499856833],[508727.56234216224,6651141.062419756,97.34830811356832],[508735.5065220615,6651137.380946767,91.16954345236869],[508725.60551920446,6651146.7765558,93.40221746279461],[508727.62691650784,6651141.085356518,97.3492805777946],[508725.32955578633,6651147.348079913,93.24643511256832],[508725.3943510221,6651147.371095134,93.2474075767946],[508725.56707949744,6651146.679411677,93.82557211856832],[508725.6318512348,6651146.702418552,93.8265445827946],[508725.35149554035,6651147.286315903,93.72370606456832],[508725.60796758794,6651146.56430499,94.25188246956833],[508725.41628860554,6651147.309330354,93.7246785287946],[508725.67273528024,6651146.587310429,94.25285493379461],[508725.6639056041,6651146.406830293,94.67369132856832],[508725.3894906958,6651147.179353304,94.20660708456833],[508725.7286677624,6651146.429833766,94.6746637927946],[508726.9887452824,6651142.677189128,97.34830811356832],[508725.45428000204,6651147.20236642,94.20757954879461],[508727.05337637407,6651142.7001460465,97.3492805777946],[508725.73496096575,6651146.206797785,95.08404087156832],[508725.4290062595,6651147.068110505,94.56831306956832],[508726.8493044613,6651143.069737928,97.31056525456833],[508735.7087237135,6651136.805857087,92.86834711136868],[508725.7997160946,6651146.229798762,95.0850133357946],[508725.4937916565,6651147.091122234,94.5692855337946],[508726.9139493479,6651143.092699747,97.31153771879461],[508725.82072271453,6651145.965364385,95.47582056556834],[508726.7072702227,6651143.469587625,97.23189056156832],[508725.4781644668,6651146.929722083,94.92607091556832],[508725.88546935894,6651145.988362348,95.47679302979462],[508725.894168436,6651145.758602623,95.75330242556832],[508726.7719291607,6651143.492554434,97.2328630257946],[508726.5645721407,6651143.871306149,97.10973743956832],[508725.5429450006,6651146.952732083,94.9270433797946],[508725.9748277637,6651145.531533376,96.01374309856833],[508725.9589078144,6651145.7815980045,95.7542748897946],[508735.5065220615,6651137.380946767,92.86834711136868],[508726.97964943614,6651142.702795427,97.95730327356833],[508726.423380835,6651144.268782851,96.94262268256833],[508726.06200459244,6651145.286116293,96.25471274456832],[508726.629245196,6651143.894277973,97.1107099037946],[508725.53697118926,6651146.764171507,95.27652713056834],[508735.70177135797,6651136.825630555,93.33393779836867],[508726.03955916245,6651145.554525924,96.0147155627946],[508726.1548855866,6651145.024641049,96.47413175056832],[508726.28602528496,6651144.65546127,96.73034487356833],[508727.0442814277,6651142.725752666,97.95827573779461],[508726.4880678583,6651144.291759636,96.9435951467946],[508726.1267273669,6651145.309105776,96.2556852087946],[508725.60174590535,6651146.78717944,95.27749959479462],[508726.21959917224,6651145.047627268,96.4751042147946],[508726.35072589695,6651144.678442883,96.73131733779461],[508726.8216165053,6651143.147684069,97.91452803256834],[508725.60525988275,6651146.571927624,95.61627215756833],[508726.886264131,6651143.170646861,97.9155004967946],[508725.67002784304,6651146.59493316,95.61724462179461],[508735.5003876302,6651137.398393943,93.27916242336866],[508725.6826858006,6651146.353960956,95.94193926756832],[508726.6606443679,6651143.600847059,97.82536338056833],[508725.74744610104,6651146.376963769,95.9429117317946],[508726.7253079187,6651143.623815507,97.82633584479461],[508735.6800304155,6651136.887464826,93.81120875036866],[508725.7687278809,6651146.111738377,96.25030807556833],[508726.53929089557,6651143.942477004,97.72626788656834],[508726.41853593895,6651144.2824220285,97.59864512756832],[508725.86269869795,6651145.847195102,96.53840642656833],[508725.8334796691,6651146.134738167,96.2512805397946],[508726.60396645183,6651143.965449717,97.72724035079462],[508726.2994726975,6651144.6176045975,97.44215383556832],[508725.96376222157,6651145.562684693,96.80360415156832],[508726.1832334388,6651144.94483719,97.25694493356833],[508726.07095845405,6651145.260909703,97.04369259856833],[508726.48322344164,6651144.305398984,97.5996175917946],[508725.9274411897,6651145.87019159,96.5393788907946],[508735.4812044456,6651137.452953594,93.70028385136867],[508726.3641719791,6651144.640585736,97.4431262997946],[508726.02849471505,6651145.585677629,96.8045766157946],[508726.2479442199,6651144.967822416,97.25791739779461],[508726.1356803426,6651145.283898872,97.0446650627946],[508735.6423795607,6651136.994549103,94.29410977036868],[508735.4479831031,6651137.547439722,94.12637298636866],[508735.6032220752,6651137.105918449,94.65581575536866],[508735.40004514984,6651137.683781942,94.55127949036867],[508735.55450932495,6651137.244464301,95.01357360136866],[508735.3371033734,6651137.862797127,94.96824619236867],[508735.4962354913,6651137.4102032045,95.36402981636869],[508735.2593237343,6651138.08401326,95.37019510936867],[508735.4285656095,6651137.60266578,95.70377484336868],[508738.8629056248,6651137.911821096,91.08506430210429],[508735.3518413021,6651137.820880404,96.02944195336866],[508735.167358899,6651138.34557407,95.75007591136868],[508738.66169342503,6651138.487257712,91.08506430210429],[508738.66169342503,6651138.487257712,91.2150643021043],[508735.26657890953,6651138.0633785315,96.33781076136867],[508735.0897429443,6651138.566324663,96.01648222636868],[508735.00542461715,6651138.806137736,96.26419196636867],[508735.17345962784,6651138.328222747,96.62590911236867],[508735.0733119117,6651138.613056809,96.89110683736867],[508734.8839196733,6651139.151714731,96.56163443636866],[508738.8629056248,6651137.911821096,92.91386796110429],[508734.96708705934,6651138.915175093,97.13119528436867],[508734.75396832346,6651139.521314481,96.81784755936867],[508738.66169342503,6651138.487257712,92.91386796110429],[508738.85598728986,6651137.931606493,93.37945864810429],[508734.85582947696,6651139.231607164,97.34444761936867],[508738.6555890119,6651138.504715414,93.3246832731043],[508734.6178574484,6651139.90843278,97.03012536836867],[508731.4598457478,6651148.890258194,91.03954345236868],[508738.8343527343,6651137.993478066,93.85672960010429],[508734.74064354354,6651139.559212013,97.52965652136866],[508731.4598457478,6651148.890258194,91.16954345236869],[508734.477945576,6651140.306361645,97.19724012536867],[508738.6364996983,6651138.559307979,93.7458047011043],[508731.2576440958,6651149.465347872,91.03954345236868],[508734.62265921757,6651139.89477588,97.68614781336866],[508738.79688612005,6651138.1006269455,94.33963062010429],[508734.33654058137,6651140.708537157,97.31939324736867],[508738.60344092076,6651138.653851108,94.17189383610429],[508734.5029985063,6651140.23510762,97.81377057236868],[508738.7579202475,6651138.212063477,94.7013366051043],[508734.19579341455,6651141.108841715,97.39806794036868],[508734.38274470274,6651140.577126197,97.91286606636868],[508738.55573754676,6651138.790275581,94.5968003401043],[508734.05761616444,6651141.501837073,97.43581079936867],[508738.70944586786,6651138.35069291,95.0590944511043],[508734.22323124675,6651141.030804697,98.00203071836869],[508731.45984497207,6651148.8902604,92.86834711236867],[508738.49310376926,6651138.96939876,95.0137670421043],[508738.65145719104,6651138.516531801,95.4095506661043],[508734.066630363,6651141.476199437,98.04480595936867],[508731.46135267854,6651148.885972272,93.07216839636867],[508731.2576440958,6651149.465347872,92.86834711136868],[508738.41570473666,6651139.190748346,95.41571595910429],[508738.58411844465,6651138.7091104835,95.74929569310429],[508731.47387179465,6651148.850366161,93.48874768436868],[508733.47714998526,6651143.152763788,97.43581079936867],[508731.2645964514,6651149.445574404,93.33393779836867],[508731.4999677937,6651148.776145502,93.91307480436866],[508738.50776957953,6651138.92745675,96.07496280310428],[508738.3241899215,6651139.452466948,95.79559676110429],[508731.28633739386,6651149.383740134,93.81120875036866],[508731.5404853686,6651148.660907873,94.33938515536866],[508738.42292440933,6651139.1701011695,96.3833316111043],[508738.2469537721,6651139.673350713,96.06200307610429],[508731.5959164912,6651148.503254035,94.76119401436867],[508731.32398824865,6651149.276655856,94.29410977036868],[508732.90875086875,6651144.769370093,97.43581079936867],[508731.66632797045,6651148.302993974,95.17154355736866],[508738.16304804775,6651139.91330846,96.3097128161043],[508731.3631457341,6651149.165286509,94.65581575536866],[508732.77057361865,6651145.16236545,97.39806794036868],[508738.33026079694,6651139.435105157,96.67142996210428],[508731.7513125718,6651148.061285923,95.56332325136869],[508732.6298264518,6651145.562670009,97.31939324736867],[508731.4118584844,6651149.026740658,95.01357360136866],[508731.8240927502,6651147.854288953,95.84080511136867],[508732.4884214571,6651145.964845522,97.19724012536867],[508731.9040211672,6651147.626961395,96.10124578436867],[508732.89973744634,6651144.795005524,98.04480595936867],[508732.3485095847,6651146.362774386,97.03012536836867],[508731.9904080257,6651147.38126513,96.34221543036867],[508738.23060314305,6651139.720111053,96.93662768710429],[508731.47013231803,6651148.861001753,95.36402981636869],[508732.08244736,6651147.119492435,96.56163443636866],[508732.21239870973,6651146.749892686,96.81784755936867],[508738.0421376754,6651140.259093932,96.6071552861043],[508732.7431365626,6651145.240400261,98.00203071836869],[508731.5378021998,6651148.668539179,95.70377484336868],[508732.5836231066,6651145.694078762,97.91286606636868],[508731.6145265072,6651148.450324556,96.02944195336866],[508738.12489809067,6651140.022411597,97.1767161341043],[508732.46336930303,6651146.03609734,97.81377057236868],[508737.91282222874,6651140.628916651,96.8633684091043],[508731.6997888998,6651148.207826428,96.33781076136867],[508732.34370859177,6651146.37642908,97.68614781336866],[508731.7929081815,6651147.942982213,96.62590911236867],[508732.2257242658,6651146.711992947,97.52965652136866],[508731.8930558976,6651147.65814815,96.89110683736867],[508732.1105383324,6651147.039597794,97.34444761936867],[508731.99928075,6651147.356029864,97.13119528436867],[508738.0141849354,6651140.339034562,97.38996846910429],[508737.77737739775,6651141.016268489,97.07564621810431],[508734.6348190917,6651150.003512391,91.08506430210429],[508737.8995626522,6651140.666837046,97.5751773711043],[508734.6348190917,6651150.003512391,91.2150643021043],[508737.6381501692,6651141.414437412,97.24276097510429],[508734.433606892,6651150.578949004,91.08506430210429],[508737.78215567,6651141.002603349,97.73166866310429],[508737.49743712496,6651141.816855546,97.36491409710429],[508737.6630805057,6651141.343140403,97.85929142210429],[508737.3573786894,6651142.217401598,97.44358879010429],[508737.5434151514,6651141.685365309,97.95838691610429],[508737.21987759497,6651142.610634039,97.4813316491043],[508737.3846822575,6651142.139317501,98.0475515681043],[508734.63481831976,6651150.003514597,92.91386796210429],[508737.2288476835,6651142.584980935,98.0903268091043],[508734.63631864847,6651149.999223883,93.1176892461043],[508734.433606892,6651150.578949004,92.91386796110429],[508734.6487765035,6651149.963596293,93.53426853410429],[508736.6422518653,6651144.262556712,97.4813316491043],[508734.440525227,6651150.559163608,93.37945864810429],[508734.6747448047,6651149.889330859,93.9585956541043],[508734.4621597824,6651150.497292034,93.85672960010429],[508734.71506411105,6651149.77402371,94.38490600510428],[508734.7702239873,6651149.616274762,94.8067148641043],[508734.4996263967,6651150.390143155,94.33963062010429],[508736.0766341495,6651145.8801382715,97.4813316491043],[508734.8402909155,6651149.415893892,95.21706440710429],[508735.93913305504,6651146.273370711,97.44358879010429],[508734.53859226924,6651150.278706622,94.7013366051043],[508734.92485965387,6651149.174040023,95.6088441011043],[508735.7990746194,6651146.673916763,97.36491409710429],[508734.5870666489,6651150.1400771905,95.0590944511043],[508734.9972836901,6651148.966918178,95.88632596110429],[508735.65836157516,6651147.076334898,97.24276097510429],[508736.0676648333,6651145.905789166,98.0903268091043],[508735.0768209858,6651148.73945348,96.1467666341043],[508735.5191343467,6651147.474503822,97.07564621810431],[508735.1627851194,6651148.4936089935,96.3877362801043],[508734.64505532564,6651149.974238301,95.4095506661043],[508735.25437406905,6651148.231678378,96.6071552861043],[508735.3836895157,6651147.861855659,96.8633684091043],[508735.91183025925,6651146.351452599,98.0475515681043],[508734.7123940721,6651149.781659619,95.74929569310429],[508735.7530973654,6651146.805404792,97.95838691610429],[508734.7887429372,6651149.563313353,96.07496280310428],[508735.6334320112,6651147.1476297,97.85929142210429],[508734.8735881074,6651149.320668933,96.3833316111043],[508735.51435684675,6651147.488166753,97.73166866310429],[508734.9662517198,6651149.055664944,96.67142996210428],[508735.3969498646,6651147.823933057,97.5751773711043],[508735.0659093737,6651148.770659049,96.93662768710429],[508735.2823275813,6651148.151735539,97.38996846910429],[508735.1716144261,6651148.468358504,97.1767161341043],[508752.12251381646,6651142.494644271,91.26653404189648],[508751.9254610946,6651143.071518497,91.26653404189648],[508751.9254610946,6651143.071518497,91.39653404189649],[508752.12251381646,6651142.494644271,93.09533770089648],[508751.9254610946,6651143.071518497,93.09533770089648],[508752.11573849805,6651142.514479098,93.56092838789648],[508751.91948287253,6651143.0890198145,93.50615301289649],[508752.0945511742,6651142.576505245,94.03819933989648],[508751.90078817494,6651143.143748769,93.9272744408965],[508752.0578590733,6651142.683921814,94.52110035989648],[508751.86841279175,6651143.238528093,94.35336357589648],[508752.01969870704,6651142.795636747,94.8828063448965],[508751.8216955464,6651143.375293394,94.77827007989649],[508751.9722263944,6651142.934612516,95.24056419089648],[508751.7603565403,6651143.554864077,95.1952367818965],[508751.9154364651,6651143.100865722,95.59102040589649],[508751.8494897516,6651143.293925522,95.93076543289648],[508751.6845575079,6651143.77676666,95.59718569889648],[508751.77471917757,6651143.512817281,96.25643254289649],[508751.59493449575,6651144.039139111,95.97706650089648],[508751.69162793487,6651143.7560679,96.5648013508965],[508751.5192949794,6651144.26057471,96.24347281589648],[508751.43712376215,6651144.501131942,96.49118255589649],[508751.6008798735,6651144.021733946,96.85289970189648],[508751.5032823521,6651144.307451869,97.11809742689648],[508756.28394181497,6651143.909274647,91.3199669126467],[508751.31871286064,6651144.8477812875,96.7886250258965],[508756.088194514,6651144.4865926355,91.31996691264918],[508751.3997624447,6651144.61050765,97.35818587389649],[508756.088194514,6651144.4865926355,91.44996691264919],[508751.19207063527,6651145.218527934,97.04483814889649],[508751.2913379624,6651144.927921632,97.57143820889648],[508751.05942573276,6651145.606847488,97.2571159578965],[508751.1790851619,6651145.256543064,97.75664711089648],[508747.9818306922,6651154.616544179,91.26653404189648],[508747.9818306922,6651154.616544179,91.39653404189649],[508750.92307662277,6651146.006011156,97.4242307148965],[508751.06410522806,6651145.59314821,97.91313840289648],[508747.7847779702,6651155.193418403,91.26653404189648],[508756.28394181497,6651143.909274647,93.14877057164671],[508750.78527241194,6651146.409434651,97.5463838368965],[508750.9474915969,6651145.934536026,98.04076116189648],[508756.088194514,6651144.4865926355,93.14877057164918],[508750.64810927777,6651146.810981384,97.62505852989648],[508756.2772113811,6651143.929124732,93.61436125864583],[508750.8302999763,6651146.277615911,98.13985665589648],[508750.51345061907,6651147.205196234,97.66280138889648],[508756.0822558954,6651144.504107417,93.55958588364068],[508750.67484842386,6651146.73270221,98.22902130789649],[508756.25616441696,6651143.991198594,94.09163221063858],[508756.06368504517,6651144.55887847,93.98070731164123],[508750.5222352771,6651147.179479042,98.2717965488965],[508747.98182993603,6651154.616546391,93.09533770189648],[508747.98329924984,6651154.612244957,93.29915898589648],[508756.21971539175,6651144.098697793,94.5745332306442],[508747.7847779702,6651155.193418403,93.09533770089648],[508756.0315241402,6651144.653730705,94.40679644664426],[508749.9477656237,6651148.861245898,97.66280138889648],[508747.995499575,6651154.576528358,93.71573827389648],[508756.1818078276,6651144.210498664,94.93623921564632],[508747.7915532887,6651155.173583576,93.56092838789648],[508748.02093105693,6651154.502077387,94.14006539389649],[508755.9851163838,6651144.790601213,94.83170295064227],[508756.13465000596,6651144.34958134,95.29399706164321],[508747.8127406126,6651155.11155743,94.03819933989648],[508748.0604168787,6651154.386482167,94.56637574489648],[508755.92418373236,6651144.9703100305,95.24866965264734],[508756.0782362944,6651144.515962435,95.64445327664261],[508748.11443648476,6651154.228339116,94.98818460389649],[508749.3938404113,6651150.482868655,97.66280138889648],[508747.8494327134,6651155.004140861,94.52110035989648],[508748.1830549827,6651154.027457634,95.39853414689648],[508749.2591817526,6651150.877083505,97.62505852989648],[508747.88759307977,6651154.892425927,94.8828063448965],[508756.0127264599,6651144.709170749,95.98419830364112],[508755.8488868478,6651145.192383314,95.65061856964533],[508748.265875508,6651153.784999545,95.79031384089649],[508749.1220186184,6651151.27863024,97.5463838368965],[508747.93506539235,6651154.753450158,95.24056419089648],[508748.3368023877,6651153.577360247,96.06779570089648],[508748.98421440757,6651151.682053732,97.4242307148965],[508749.38505650964,6651150.508583633,98.2717965488965],[508748.41469548084,6651153.349327276,96.32823637389649],[508748.84786529763,6651152.0812174,97.2571159578965],[508748.4988825557,6651153.102868596,96.56920601989648],[508748.7152203951,6651152.4695369555,97.04483814889649],[508748.58857816976,6651152.840283602,96.7886250258965],[508747.99185532174,6651154.587196954,95.59102040589649],[508755.9384512209,6651144.928230892,96.30986541364487],[508749.23244336294,6651150.955360464,98.22902130789649],[508755.7598575632,6651145.454957597,96.03049937163823],[508748.05780203507,6651154.3941371525,95.93076543289648],[508749.0769918105,6651151.410446763,98.13985665589648],[508748.1325726092,6651154.175245394,96.25643254289649],[508748.9598001899,6651151.753526649,98.04076116189648],[508748.21566385194,6651153.931994775,96.5648013508965],[508755.85591043497,6651145.171668631,96.61823422164382],[508748.84318655875,6651152.094914465,97.91313840289648],[508755.6847191385,6651145.676563536,96.29690568664412],[508748.30641191325,6651153.666328729,96.85289970189648],[508748.7282066249,6651152.431519611,97.75664711089648],[508748.4040094346,6651153.380610805,97.11809742689648],[508748.61595382437,6651152.760141041,97.57143820889648],[508748.5075293421,6651153.077555024,97.35818587389649],[508755.6030922834,6651145.917305817,96.54461542664565],[508755.7657635549,6651145.437539043,96.90633257264452],[508755.6688125905,6651145.723476756,97.17153029764322],[508755.4854658217,6651146.264221824,96.84205789664404],[508755.56597847457,6651146.026765663,97.41161874464638],[508755.3596625666,6651146.635253669,97.09827101964285],[508755.45827227476,6651146.344423818,97.62487107964382],[508755.22789640026,6651147.023871941,97.31054882863958],[508755.34676311864,6651146.673298042,97.81007998164468],[508752.170689591,6651156.040499378,91.3199669126459],[508755.0924505664,6651147.4233426675,97.4776635856434],[508752.170689591,6651156.040499378,91.4499669126459],[508755.2325448955,6651147.0101621235,97.96657127364296],[508751.97494228964,6651156.6178173665,91.31996691264403],[508754.9555592707,6651147.827076497,97.59981670763861],[508755.11670379795,6651147.351812553,98.09419403264249],[508754.81930480513,6651148.228932121,97.67849140064006],[508755.00028854015,6651147.695156354,98.19328952664557],[508754.6855382233,6651148.623450224,97.71623425963736],[508754.845866812,6651148.15059273,98.28245417864466],[508754.69426468585,6651148.597713247,98.32522941964449],[508752.17068883986,6651156.040501593,93.14877057264447],[508752.1721484198,6651156.03619685,93.3525918566441],[508751.97494228964,6651156.6178173665,93.14877057164405],[508754.12360073806,6651150.28077381,97.71623425964779],[508752.18426792085,6651156.000452776,93.76917114464099],[508751.98167272296,6651156.597967282,93.6143612586376],[508752.20953092584,6651155.925944533,94.19349826463878],[508752.002719687,6651156.535893422,94.09163221064352],[508752.24875516497,6651155.810260391,94.61980861563926],[508752.30241690605,6651155.651995689,95.04161747464255],[508753.57334512926,6651151.903644007,97.7162342596433],[508752.0391687129,6651156.428394222,94.57453323064652],[508752.3705808253,6651155.450959677,95.45196701764566],[508753.4395785479,6651152.298162109,97.67849140064625],[508752.0770762764,6651156.316593351,94.93623921563581],[508753.303324082,6651152.700017734,97.59981670764505],[508752.4528526866,6651155.208315077,95.84374671163808],[508752.1242340985,6651156.177510674,95.2939970616445],[508752.5233096953,6651155.000516051,96.12122857164316],[508753.1664327865,6651153.1037515635,97.47766358564292],[508753.5646194184,6651151.929378766,98.32522941964064],[508752.60068676784,6651154.772307663,96.38166924464245],[508753.0309869522,6651153.5032222895,97.3105488286411],[508752.68431612616,6651154.525659394,96.62263889064258],[508752.8992207858,6651153.891840562,97.09827101963653],[508752.77341753116,6651154.262872405,96.84205789664227],[508752.1806478098,6651156.011129578,95.64445327664251],[508753.41301729245,6651152.376499283,98.2824541786431],[508752.2461576441,6651155.817921266,95.98419830364098],[508753.2585955643,6651152.831935659,98.19328952664218],[508752.32043288345,6651155.5988611225,96.30986541364155],[508753.14218030643,6651153.175279461,98.09419403264394],[508752.4029736697,6651155.355423383,96.61823422164692],[508753.02633920853,6651153.516929891,97.96657127363913],[508752.4931205494,6651155.0895529725,96.90633257264192],[508752.9121209858,6651153.853793971,97.81007998164307],[508752.59007151355,6651154.803615258,97.17153029763888],[508752.8006118293,6651154.182668196,97.6248710796396],[508752.6929056298,6651154.500326351,97.41161874464137],[508780.9085904975,6651166.179011417,93.47719238164655],[508781.40424123115,6651165.697638644,93.48023315383543],[508781.40793966077,6651165.694046753,93.6840766446469],[508780.92559867207,6651166.162493188,93.9428937328404],[508781.438649262,6651165.664221789,94.10084032902482],[508780.9787855011,6651166.110838485,94.42051076182501],[508781.03831829043,6651166.053020627,94.73301253991784],[508791.8097574663,6651155.591868871,94.00871362346382],[508782.1192161192,6651165.003259677,96.17950419952633],[508781.59547161206,6651165.511916941,96.31680924172528],[508791.75642657146,6651155.643663489,94.48566013922657],[508782.2977471118,6651164.829871537,96.45805911072323],[508781.7836776189,6651165.329132489,96.64360681646063],[508782.4938128534,6651164.639453763,96.71967850416095],[508791.6640683957,6651155.733361149,94.9679993539432],[508781.9928276921,6651165.126007297,96.95323220408682],[508782.8186082703,6651164.324014563,97.0723109665908],[508791.5680144301,6651155.826648137,95.32912112216707],[508782.9314952818,6651164.214379431,97.18269949183302],[508791.44852124096,6651155.942699146,95.68615228904439],[508783.2502681133,6651163.904789329,97.44083070961177],[508783.5841503607,6651163.580525057,97.6551183535247],[508790.4988347842,6651156.865028464,96.41688313154079],[508783.9273565201,6651163.247205466,97.82429995188103],[508790.30844155047,6651157.049937135,96.6821332156547],[508790.95137319824,6651156.425526096,96.6989984914695],[508790.1016072871,6651157.250813229,96.92858719596532],[508790.74222312565,6651156.628651287,97.00609644935226],[508789.48478080117,6651157.8498711055,97.47849977789618],[508790.51379997365,6651156.85049437,97.29280722579055],[508789.15089855244,6651158.174135376,97.68875274712765],[508788.80769239395,6651158.507454967,97.8537870088007],[508787.77661733126,6651159.508828371,98.08611278570439],[508788.46082358254,6651158.844331705,97.97383834843298],[508788.11556843144,6651159.179641264,98.05042195029993],[508789.1626773728,6651158.162695862,98.34484661064175],[508788.86914764997,6651158.447770022,98.47068992764929],[508788.5741630632,6651158.734257137,98.56799782418399],[508806.02157038066,6651160.022071429,91.84040728419325],[508805.84142554365,6651160.604443926,91.84040728419237],[508805.84142554365,6651160.604443926,91.97040728419239],[508806.02157038066,6651160.022071429,93.66921094319325],[508805.84142554365,6651160.604443926,93.66921094319237],[508806.01537641056,6651160.042095303,94.13480163019182],[508805.83596027637,6651160.622112051,94.08002625519457],[508805.99600704084,6651160.10471263,94.61207258219072],[508805.8188696562,6651160.677362634,94.50114768319555],[508805.9624632644,6651160.213153002,95.09497360219407],[508805.7892722053,6651160.773045316,94.92723681818944],[508805.9275772049,6651160.325932708,95.45667958719376],[508805.7465634801,6651160.911114147,95.35214332219047],[508805.8841782,6651160.466233075,95.81443743319278],[508805.69048759807,6651161.092396343,95.76911002419283],[508805.8322610662,6651160.634070863,96.1648936481941],[508805.7719728354,6651160.828970745,96.50463867519221],[508805.6211924154,6651161.316413912,96.17105894119219],[508805.7036178657,6651161.049948793,96.83030578519424],[508805.53925940424,6651161.581287075,96.55093974319398],[508805.6276561724,6651161.295517869,97.13867459319158],[508805.47011005046,6651161.804833207,96.81734605819234],[508805.3949894412,6651162.047683226,97.065055798192],[508805.54469464545,6651161.563716018,97.42677294419249],[508805.45547136874,6651161.852157161,97.69197066919432],[508805.2867386526,6651162.397636537,97.36249826819326],[508805.3608338692,6651162.158101411,97.93205911619278],[508805.17096281936,6651162.771916824,97.61871139119184],[508805.26171262615,6651162.478540713,98.14531145119072],[508805.04969936213,6651163.163937511,97.83098920019165],[508805.1590915499,6651162.810294283,98.33052035319271],[508804.9250495327,6651163.566905666,97.99810395719315],[508805.0539773385,6651163.150107663,98.48701164519102],[508802.2361738679,6651172.259506941,91.84040728419299],[508802.2361738679,6651172.259506941,91.97040728419302],[508804.79906945553,6651163.974174247,98.12025707919231],[508804.94736960786,6651163.494749295,98.61463440419426],[508802.0560290307,6651172.841879439,91.84040728419106],[508804.6736754481,6651164.379548183,98.1989317721914],[508804.8402334811,6651163.841099124,98.71372989819434],[508804.5505710229,6651164.777520353,98.23667463119219],[508804.6981202724,6651164.300522918,98.80289455019278],[508804.5586019235,6651164.751558046,98.84566979119329],[508802.23617317685,6651172.259509175,93.66921094419426],[508802.2375164178,6651172.255166743,93.87303222819412],[508804.0334239857,6651166.449354069,98.23667463119065],[508802.0560290307,6651172.841879439,93.66921094319106],[508802.2486699077,6651172.219109724,94.2896115161922],[508802.0622230007,6651172.821855564,94.13480163019142],[508802.2719192703,6651172.14394915,94.71393863619335],[508802.3080170559,6651172.027252174,95.1402489871918],[508802.08159237064,6651172.7592382375,94.61207258219358],[508803.52702769707,6651168.0864327485,98.23667463119213],[508802.35740157095,6651171.867601841,95.56205784619114],[508802.1151361473,6651172.650797865,95.09497360219257],[508803.4039232714,6651168.484404921,98.19893177219056],[508802.42013233656,6651171.664805727,95.97240738919054],[508803.27852926427,6651168.889778854,98.120257079192],[508802.15002220694,6651172.53801816,95.45667958719415],[508802.4958465408,6651171.420036733,96.3641870831913],[508803.51899748814,6651168.11239282,98.84566979119231],[508803.1525491875,6651169.297047436,97.99810395719369],[508802.56068762037,6651171.210418396,96.64166894319322],[508802.1934212113,6651172.397717793,95.81443743319153],[508803.027899358,6651169.700015591,97.83098920019393],[508802.631897185,6651170.980212009,96.9021096161917],[508802.70886068366,6651170.731404295,97.14307926219281],[508802.9066359006,6651170.092036279,97.6187113911925],[508802.79086006735,6651170.466316564,97.3624982681923],[508803.3794791392,6651168.563427947,98.8028945501939],[508802.2453383455,6651172.229880003,96.16489364819259],[508803.3084225346,6651168.793139845,98.75831222403362],[508803.2373659306,6651169.022851741,98.7137298981923],[508802.30562657584,6651172.034980122,96.50463867519082],[508803.13022980397,6651169.369201573,98.61463440419368],[508802.37398154614,6651171.814002072,96.83030578519366],[508803.0236220729,6651169.713843205,98.48701164519329],[508802.4499432392,6651171.568432997,97.138674593194],[508802.9185078617,6651170.053656584,98.33052035319393],[508802.53290476615,6651171.300234849,97.42677294419308],[508802.8158867849,6651170.385410154,98.14531145119105],[508802.62212804286,6651171.011793706,97.69197066919236],[508802.71676554205,6651170.705849456,97.93205911619029],[508822.1918849311,6651164.9449669225,91.9627256389017],[508822.372404784,6651165.634787478,91.96506541656744],[508822.372404784,6651165.634787478,92.09506541656745],[508822.1918849311,6651164.9449669225,93.7915292979017],[508822.1980917954,6651164.968685214,94.25720045849617],[508822.372404784,6651165.634787478,93.79386907556744],[508822.2175014869,6651165.042855473,94.73472305094654],[508822.37788142887,6651165.655715382,94.20475534924105],[508822.25111509353,6651165.171303156,95.21805982046632],[508822.39500762743,6651165.721159728,94.62609867514391],[508822.2860737768,6651165.30489078,95.5802189378769],[508822.4246666921,6651165.834495918,95.0525720605858],[508822.32956312713,6651165.471076645,95.93854041346947],[508822.38158834004,6651165.669880602,96.2896707724538],[508822.52365694434,6651166.212767391,95.89572745636704],[508822.4420020749,6651165.900739621,96.63019848922737],[508822.59309638164,6651166.47811633,96.29857553761954],[508822.51049934304,6651166.162488246,96.95675281647692],[508822.6751999569,6651166.791858739,96.67951921077417],[508822.5866191689,6651166.453364954,97.26610732601614],[508822.7444932617,6651167.056649261,96.94682232590775],[508822.6697534008,6651166.771045813,97.55528191281114],[508822.81977025385,6651167.344305247,97.19550606296447],[508822.75916241796,6651167.112704511,97.82163675876285],[508822.9282463929,6651167.758825142,97.49435164092193],[508822.8539969291,6651167.475095649,98.06295215031385],[508823.04426324216,6651168.202160354,97.75206482426465],[508822.9533245171,6651167.854656183,98.27748912713014],[508823.0561592244,6651168.247618474,98.46402756333227],[508823.16577913926,6651168.666509079,97.96591314708884],[508823.1614922571,6651168.650127616,98.62188019819675],[508823.2906884579,6651169.143825087,98.13464158568678],[508823.2683219183,6651169.058355824,98.75088313467333],[508823.41693079384,6651169.626234953,98.25842490002799],[508823.37568107556,6651169.468607395,98.85136513173755],[508823.5425858402,6651170.106400609,98.33872149297953],[508823.51809012797,6651170.012795139,98.94236814657671],[508823.6659465378,6651170.577798871,98.37805595023299],[508823.6578989189,6651170.547046503,98.9869473007037],[508824.18417014414,6651172.558086854,98.38473463639099],[508824.6916206219,6651174.49720748,98.3912628763363],[508824.6996675483,6651174.5279572,99.000361465957],[508824.81498131994,6651174.968605742,98.35510529410794],[508825.9851616828,6651179.440216226,92.01158491380276],[508825.9851616828,6651179.440216226,92.14158491380277],[508824.94063636544,6651175.448771397,98.27804466653393],[508824.83947633876,6651175.062208563,98.95938277082355],[508825.06687870115,6651175.931181262,98.15751244752472],[508826.16568153584,6651180.130036781,92.01389415230373],[508824.9818853913,6651175.606396307,98.87204718498923],[508825.1917880205,6651176.408497271,97.99200078177701],[508825.08924454823,6651176.016647878,98.77432998960177],[508825.98516237503,6651179.440218871,93.84038858266251],[508825.3133039177,6651176.872845997,97.7812818484891],[508825.983816338,6651179.43507526,94.04419264253698],[508825.1960742097,6651176.424876087,98.6480782236168],[508825.42932076653,6651177.316181207,97.52655644535326],[508825.9726396292,6651179.3923657,94.46062890832961],[508825.3014072421,6651176.827385227,98.49293822201905],[508825.51149085234,6651177.6301777745,97.30819077092062],[508825.9493418676,6651179.303337958,94.8846578819189],[508825.5886145694,6651177.924890652,97.06820949544128],[508826.16568153584,6651180.130036781,93.84269781130374],[508825.91316893493,6651179.165110323,95.31050527267823],[508825.6599723748,6651178.197570249,96.8086830660119],[508825.40424195013,6651177.22034752,98.30904808548469],[508825.8636816144,6651178.976004412,95.73168067320069],[508825.72494843695,6651178.44586329,96.5320334900092],[508825.80082025914,6651178.735792302,96.14122540835535],[508826.1594746717,6651180.106318489,94.30820912300204],[508825.503569538,6651177.599908054,98.09706909526902],[508825.5984040485,6651177.962299191,97.85819598559807],[508826.1400649798,6651180.032148229,94.78523184687617],[508825.68781306606,6651178.303957889,97.59414370370696],[508826.106451373,6651179.903700546,95.26770294731547],[508825.770947298,6651178.621638748,97.30711009047509],[508826.07149269,6651179.770112922,95.62896175624135],[508825.8470671244,6651178.912515458,96.99971591547958],[508826.02800333954,6651179.603927057,95.98616323029663],[508825.91556439176,6651179.174264081,96.67492562078117],[508862.9688786647,6651176.682449538,92.17073826452479],[508862.8065979349,6651177.270048321,92.17073826452386],[508862.8065979349,6651177.270048321,92.30073826452386],[508862.9688786647,6651176.682449538,93.99954192352479],[508862.8065979349,6651177.270048321,93.99954192352385],[508862.96329892095,6651176.702653111,94.46513261052354],[508862.8016746321,6651177.287875001,94.41035723552457],[508862.94585031964,6651176.765832375,94.94240356252364],[508862.7862788074,6651177.34362141,94.83147866352425],[508862.91563292,6651176.875245904,95.42530458252438],[508862.7596163956,6651177.440162759,95.25756779852415],[508862.88420634513,6651176.989037707,95.78701056752352],[508862.7211428919,6651177.579470636,95.68247430252461],[508862.8451110138,6651177.130597148,96.14476841352497],[508862.6706277882,6651177.762379683,96.0994410045242],[508862.79834225506,6651177.299941134,96.49522462852435],[508862.74403252196,6651177.496590071,96.83496965552457],[508862.60820427974,6651177.988407616,96.5013899215247],[508862.6824559892,6651177.719551206,97.1606367655234],[508862.5343961757,6651178.255657782,96.88127072352452],[508862.61402705655,6651177.967324047,97.46900557352438],[508862.4721040347,6651178.481210046,97.14767703852353],[508862.5392924299,6651178.237929041,97.75710392452419],[508862.40443277935,6651178.726239431,97.39538677852407],[508862.4589170015,6651178.52895869,98.02230164952486],[508862.3069167071,6651179.079333268,97.69282924852448],[508862.373664253,6651178.837648522,98.26239009652396],[508862.20262181305,6651179.456972391,97.94904237152416],[508862.2843723933,6651179.160963486,98.47564243152547],[508862.0933834768,6651179.852511121,98.16132018052465],[508862.19192776096,6651179.495694254,98.6608513335243],[508868.35062941536,6651178.17747696,92.19016613550315],[508861.9810945786,6651180.259095563,98.32843493752496],[508862.0972372265,6651179.83855716,98.81734262552403],[508868.1900369162,6651178.7655447265,92.19016613550315],[508868.1900369162,6651178.7655447265,92.32016613550316],[508861.86760734697,6651180.670019024,98.45058805952459],[508862.0012012777,6651180.186291651,98.94496538452462],[508859.55886193557,6651189.029705328,92.17073826452425],[508859.55886193557,6651189.029705328,92.30073826452426],[508861.7546480673,6651181.079030836,98.52926275252398],[508861.90468933166,6651180.535749668,99.04406087852502],[508859.3965812058,6651189.617304111,92.17073826452334],[508861.6437513231,6651181.480574457,98.56700561152488],[508861.77666881424,6651180.999296389,99.1332255305231],[508868.35062941536,6651178.17747696,94.01896979450315],[508861.6509858372,6651181.454379161,99.17600077152467],[508868.1900369162,6651178.7655447265,94.01896979450315],[508868.3451077189,6651178.197696658,94.48456048150315],[508861.1778873002,6651183.167411417,98.56700561152469],[508859.5588613128,6651189.029707583,93.99954192452388],[508868.1851648311,6651178.783385635,94.42978510650315],[508868.3278406379,6651178.260926347,94.96183143350316],[508859.560071351,6651189.025326181,94.20336320852385],[508859.3965812058,6651189.617304111,93.99954192352334],[508868.1699291714,6651178.839176537,94.85090653450317],[508859.5701188026,6651188.988945583,94.61994249652426],[508868.29793759406,6651178.370427203,95.44473245350315],[508859.4021609492,6651189.597100538,94.4651326105235],[508859.5910626361,6651188.913110508,95.0442696165235],[508868.14354413265,6651178.935794939,95.27699566950315],[508868.26683795475,6651178.484309829,95.80643843850316],[508860.72170792485,6651184.819181446,98.56700561152454],[508859.62358077615,6651188.795366278,95.47057996752416],[508859.41960955085,6651189.533921274,94.9424035625245],[508868.10547087435,6651179.075214003,95.70190217350317],[508860.61081118044,6651185.220725069,98.52926275252486],[508859.6680680638,6651188.634283222,95.89238882652492],[508871.0054461452,6651178.900448406,92.19759506947767],[508868.2281493375,6651178.625982252,96.16419628450316],[508859.44982695085,6651189.424507746,95.42530458252482],[508860.49785190076,6651185.62973688,98.45058805952424],[508859.7245781173,6651188.429667191,96.30273836952409],[508860.7144740336,6651184.845374487,99.17600077152454],[508860.38436466956,6651186.04066034,98.32843493752495],[508859.48125352524,6651189.310715942,95.78701056752408],[508859.7927841038,6651188.182701611,96.69451806352455],[508868.05548128684,6651179.258269035,96.11886887550315],[508870.8456864497,6651179.488742964,92.19759506947767],[508868.18186712125,6651178.795461397,96.51465249950316],[508860.272075771,6651186.447244784,98.16132018052417],[508859.8511952015,6651187.971202131,96.9719999235248],[508870.8456864497,6651179.488742964,92.3275950694777],[508860.5887910561,6651185.300457261,99.1332255305245],[508859.915343252,6651187.738929843,97.23244059652424],[508860.1628374343,6651186.842783513,97.94904237152357],[508859.52034885704,6651189.169156501,96.14476841352425],[508859.98467464594,6651187.487889298,97.47341024252378],[508860.05854254065,6651187.220422637,97.69282924852436],[508859.5671176157,6651188.9998125145,96.49522462852485],[508860.4607705393,6651185.76400398,99.0440608785247],[508868.1281223802,6651178.992267287,96.85439752650315],[508867.9937071792,6651179.484477368,96.52081779250315],[508859.62142734893,6651188.803163578,96.83496965552462],[508860.36425859306,6651186.113461998,98.94496538452458],[508860.2682226441,6651186.461196488,98.81734262552462],[508859.68300388084,6651188.5802024435,97.1606367655231],[508860.1735321096,6651186.804059395,98.66085133352439],[508859.75143281405,6651188.332429601,97.46900557352427],[508860.0810874778,6651187.138790161,98.4756424315248],[508859.82616744086,6651188.061824608,97.75710392452501],[508859.99179561756,6651187.462105127,98.26239009652473],[508859.9065428696,6651187.770794958,98.02230164952542],[508868.06718643755,6651179.215406375,97.18006463650315],[508867.9206669118,6651179.751940836,96.90069859450315],[508871.0054461452,6651178.900448406,94.02639872847767],[508867.9994693809,6651179.463376973,97.48843344450316],[508867.85902280535,6651179.977673122,97.16710490950317],[508870.8456864497,6651179.488742964,94.02639872847767],[508870.9999530832,6651178.920675902,94.49198941547768],[508867.9255122297,6651179.734197945,97.77653179550315],[508867.7920555439,6651180.2228980735,97.41481464950316],[508870.84083963046,6651179.506590754,94.43721404047767],[508870.98277554626,6651178.983929976,94.96926036747767],[508867.8459729585,6651180.025459875,98.04172952050315],[508867.69555394555,6651180.576273727,97.71225711950315],[508870.8256829802,6651179.562403172,94.85833546847768],[508870.9530275743,6651179.093473061,95.45216138747767],[508867.76160710707,6651180.334396084,98.28181796750316],[508867.5923440468,6651180.954214257,97.96847024250314],[508870.7994347695,6651179.659058836,95.28442460347769],[508870.922089212,6651179.207399606,95.81386737247767],[508867.67324416334,6651180.657969097,98.49507030250315],[508867.48424213286,6651181.35006868,98.18074805150316],[508870.76155895216,6651179.798531668,95.70933110747768],[508870.883601227,6651179.349126668,96.17162521847767],[508867.5817612465,6651180.992967024,98.68027920450317],[508867.37312139256,6651181.756977631,98.34786280850315],[508870.71182860166,6651179.981657297,96.12629780947768],[508870.83755902195,6651179.5186711745,96.5220814334777],[508867.4880557917,6651181.336103583,98.83677049650315],[508867.2608147855,6651182.168229065,98.47001593050315],[508867.3930189188,6651181.684115612,98.96439325550315],[508870.7840929915,6651179.715552963,96.86182646047767],[508870.65037484345,6651180.207952868,96.52824672647768],[508864.97608759283,6651190.534587528,92.19016613550315],[508867.14903063804,6651182.577567323,98.54869062350315],[508864.97608759283,6651190.534587528,92.32016613550316],[508867.29751100065,6651182.033852544,99.06348874950315],[508870.72347305156,6651179.938778105,97.18749357047767],[508867.0392875687,6651182.979431431,98.58643348250317],[508864.81549509364,6651191.122655294,92.19016613550315],[508870.57771334966,6651180.475519486,96.90812752847769],[508867.1708223001,6651182.4977692375,99.15265340150316],[508870.65610716335,6651180.186844336,97.49586237847768],[508870.51638891845,6651180.701338827,97.17453384347768],[508867.0464468211,6651182.953215227,99.19542864250316],[508870.58253354055,6651180.4577697525,97.78396072947767],[508870.44976893713,6651180.9466583505,97.4222435834777],[508866.5782699979,6651184.667614714,98.58643348250317],[508864.97608697665,6651190.534589784,94.01896979550315],[508870.50340674573,6651180.74914401,98.04915845447769],[508870.3537677787,6651181.300170287,97.71968605347767],[508864.9772844266,6651190.530204887,94.22279107950317],[508864.81549509364,6651191.122655294,94.01896979450315],[508870.41947840044,6651181.058199363,98.2892469014777],[508864.98722735303,6651190.493795251,94.63937036750315],[508870.2510931079,6651181.678256574,97.97589917647767],[508864.8210167901,6651191.102435596,94.48456048150315],[508865.0079533049,6651190.417899649,95.06369748750315],[508870.3315736909,6651181.381897164,98.50249923647769],[508866.1268363239,6651186.32070308,98.58643348250317],[508870.1435517909,6651182.074263661,98.18817698547767],[508865.04013315385,6651190.300061445,95.49000783850315],[508864.8382838711,6651191.039205907,94.96183143350316],[508870.24056518805,6651181.717024285,98.68770813847767],[508866.0170932545,6651186.722567189,98.54869062350315],[508865.0841576334,6651190.138849821,95.91181669750317],[508864.86818691494,6651190.929705051,95.44473245350315],[508870.0330073028,6651182.481329539,98.35529174247768],[508865.90530910704,6651187.131905446,98.47001593050315],[508865.14007980475,6651189.934070479,96.32216624050315],[508866.1196776879,6651186.346917026,99.19542864250316],[508870.1473456728,6651182.060293177,98.84419943047769],[508865.79300249997,6651187.543156879,98.34786280850315],[508864.89928655425,6651190.815822425,95.80643843850316],[508865.2075762342,6651189.686907787,96.71394593450316],[508865.68188175966,6651187.950065832,98.18074805150316],[508865.2653796726,6651189.475239502,96.99142779450315],[508869.9212830975,6651182.892739574,98.47744486447768],[508865.99530220893,6651186.802363017,99.15265340150316],[508865.3288603816,6651189.242781829,97.25186846750316],[508865.5737798457,6651188.345920254,97.96847024250314],[508864.9379751715,6651190.674150002,96.16419628450316],[508865.397470511,6651188.991540921,97.49283811350317],[508865.470569947,6651188.723860784,97.71225711950315],[508870.0528016441,6651182.40843942,98.97182218947768],[508864.98425738775,6651190.504670856,96.51465249950316],[508865.86861350836,6651187.2662797095,99.06348874950315],[508867.64840408805,6651191.2623245865,92.19759506947767],[508869.8100786425,6651183.302235696,98.55611955747767],[508867.64840408805,6651191.2623245865,92.3275950694777],[508865.7731055902,6651187.616016641,98.96439325550315],[508865.03800212883,6651190.307864966,96.85439752650315],[508869.95778901275,6651182.758311231,99.07091768347767],[508865.6780687173,6651187.96402867,98.83677049650315],[508865.09893807146,6651190.084725879,97.18006463650315],[508865.58436326246,6651188.307165228,98.68027920450317],[508865.1666551281,6651189.83675528,97.48843344450316],[508869.7009046808,6651183.704254787,98.59386241647768],[508867.48864439264,6651191.850619145,92.19759506947767],[508865.4928803457,6651188.642163156,98.49507030250315],[508865.24061227933,6651189.565934308,97.77653179550315],[508865.4045174018,6651188.965736169,98.28181796750316],[508865.3201515505,6651189.274672377,98.04172952050315],[508869.83175729687,6651183.222406836,99.16008233547768],[508869.70802680677,6651183.678028474,99.20285757647768],[508869.2422778641,6651185.393089131,98.59386241647768],[508867.648403475,6651191.262326844,94.02639872947768],[508867.6495947152,6651191.257940255,94.23022001347768],[508867.48864439264,6651191.850619145,94.02639872847767],[508867.65948607936,6651191.221516577,94.64679930147767],[508867.49413745455,6651191.830391649,94.49198941547768],[508867.6801045502,6651191.145591706,95.07112642147767],[508868.79318524373,6651187.046815022,98.59386241647768],[508867.7121175203,6651191.027708057,95.49743677247768],[508867.5113149915,6651191.767137576,94.96926036747767],[508868.6840112821,6651187.448834113,98.55611955747767],[508867.7559136969,6651190.866434261,95.91924563147768],[508867.5410629635,6651191.657594491,95.45216138747767],[508868.5728068271,6651187.858330235,98.47744486447768],[508867.81154586584,6651190.661575945,96.32959517447769],[508868.786063731,6651187.073039079,99.20285757647768],[508868.46108262177,6651188.26974027,98.35529174247768],[508867.57200132584,6651191.543667945,95.81386737247767],[508867.8786922711,6651190.414317933,96.72137486847768],[508868.35053813364,6651188.67680615,98.18817698547767],[508867.9361959512,6651190.202568016,96.99885672847768],[508868.662333241,6651187.528660715,99.16008233547768],[508867.9993474607,6651189.970020695,97.25929740147768],[508868.24299681664,6651189.072813236,97.97589917647767],[508867.6104893109,6651191.401940885,96.17162521847767],[508868.06760179036,6651189.718682893,97.50026704747768],[508868.1403221459,6651189.450899523,97.71968605347767],[508868.53630152514,6651187.99275632,99.07091768347767],[508867.6565315158,6651191.232396378,96.5220814334777],[508868.44128889375,6651188.342628133,98.97182218947768],[508867.70999754634,6651191.035514588,96.86182646047767],[508868.34674486506,6651188.690774374,98.84419943047769],[508867.7706174862,6651190.812289446,97.18749357047767],[508868.2535253497,6651189.0340432655,98.68770813847767],[508867.8379833744,6651190.564223215,97.49586237847768],[508868.1625168468,6651189.369170387,98.50249923647769],[508867.9115569972,6651190.2932978,97.78396072947767],[508868.07461213734,6651189.69286819,98.2892469014777],[508867.99068379204,6651190.001923541,98.04915845447769],[508885.1289495216,6651182.678896419,92.22707043011843],[508884.97362030385,6651183.268376259,92.22707043011843],[508884.97362030385,6651183.268376259,92.35707043011844],[508885.1289495216,6651182.678896419,94.05587408911843],[508884.97362030385,6651183.268376259,94.05587408911843],[508885.12360879395,6651182.699164669,94.52146477611844],[508884.9689078972,6651183.286260009,94.46668940111844],[508885.10690762685,6651182.7625461845,94.99873572811843],[508884.95417157316,6651183.342184876,94.88781082911845],[508885.07798462966,6651182.872309975,95.48163674811843],[508884.92865128146,6651183.43903528,95.31389996411843],[508885.04790425417,6651182.986466058,95.84334273311845],[508884.89182584157,6651183.578789118,95.73880646811844],[508885.01048362325,6651183.128478666,96.20110057911843],[508884.8434746199,6651183.762283704,96.15577317011845],[508884.9657182671,6651183.298364766,96.55155679411844],[508884.91373496375,6651183.495643229,96.89130182111843],[508884.7837251057,6651183.98903521,96.55772208711844],[508884.8547961444,6651183.71931812,97.21696893111844],[508884.71307867044,6651184.257140915,96.93760288911844],[508884.7892984562,6651183.967884148,97.52533773911846],[508884.65345489676,6651184.48341523,97.20400920411844],[508884.7177651871,6651184.239355418,97.81343609011843],[508884.5886824299,6651184.729229019,97.45171894411844],[508884.6408327474,6651184.531316731,98.07863381511844],[508884.49534358876,6651185.083453201,97.74916141411845],[508884.55923191446,6651184.8409947585,98.31872226211844],[508884.39551630587,6651185.462301247,98.00537453711844],[508890.1094846779,6651183.98422462,92.23344354966014],[508884.47376499046,6651185.16534474,98.53197459711843],[508889.955717831,6651184.574113935,92.23344354966014],[508884.2909573395,6651185.859106199,98.21765234611843],[508889.955717831,6651184.574113935,92.36344354966016],[508884.38528034784,6651185.501147067,98.71718349911843],[508884.1834784862,6651186.266992224,98.38476710311845],[508884.2946460089,6651185.845107568,98.87367479111843],[508884.0748526319,6651186.679231158,98.50692022511845],[508884.20272388804,6651186.193955248,99.00129755011844],[508890.1094846779,6651183.98422462,94.06224720866015],[508883.966732114,6651187.089552323,98.58559491811843],[508881.8650054141,6651195.06567901,92.22707043011843],[508884.1103461601,6651186.544531973,99.10039304411843],[508881.8650054141,6651195.06567901,92.35707043011844],[508883.8605857796,6651187.492381393,98.62333777711844],[508889.955717831,6651184.574113935,94.06224720866015],[508890.1041976697,6651184.004506948,94.52783789566014],[508881.7096761964,6651195.6551588485,92.22707043011843],[508883.9878095729,6651187.009562627,99.18955769611844],[508889.95105282386,6651184.592010107,94.47306252066014],[508883.8675103937,6651187.466102239,99.23233293711846],[508890.08766449033,6651184.067932491,95.00510884766014],[508889.93646472436,6651184.6479738215,94.89418394866014],[508890.0590324136,6651184.177772529,95.48800986766015],[508883.4146776646,6651189.184618359,98.62333777711844],[508889.91120112716,6651184.744891502,95.32027308366015],[508881.8650048182,6651195.065681271,94.05587409011844],[508890.0292546002,6651184.292007907,95.84971585266014],[508881.86616302264,6651195.061285845,94.25969537411844],[508881.7096761964,6651195.6551588485,94.05587408911843],[508889.87474609405,6651184.88474242,95.74517958766015],[508881.87578007823,6651195.02478878,94.67627466211843],[508889.99221036263,6651184.434119165,96.20747369866014],[508881.715016924,6651195.6348906,94.52146477611844],[508881.8958267548,6651194.948710939,95.10060178211845],[508889.8268812106,6651185.0683644675,96.16214628966014],[508889.94789527636,6651184.604123275,96.55792991366016],[508882.97803934215,6651190.841676137,98.62333777711844],[508881.92695193674,6651194.83058978,95.52691213311843],[508881.73171809124,6651195.571509084,94.99873572811843],[508882.8718930078,6651191.244505207,98.58559491811843],[508881.9695335517,6651194.668991054,95.94872099211844],[508889.89643484453,6651184.801538775,96.89767494066015],[508889.76773268386,6651185.295273483,96.56409520666014],[508882.76377248985,6651191.654826372,98.50692022511845],[508881.7606410884,6651195.461745293,95.48163674811843],[508882.97111532424,6651190.86795303,99.23233293711846],[508882.0236229219,6651194.463719993,96.35907053511843],[508882.65514663554,6651192.067065306,98.38476710311845],[508881.7907214638,6651195.347589212,95.84334273311845],[508882.0889072137,6651194.215963812,96.75085022911844],[508882.54766778223,6651192.4749513315,98.21765234611843],[508882.1448161939,6651194.003787266,97.02833208911844],[508889.8380888582,6651185.025369038,97.22334205066014],[508882.8508161451,6651191.324492642,99.18955769611844],[508882.4431088159,6651192.871756284,98.00537453711844],[508882.2062163772,6651193.770771414,97.28877276211844],[508882.27257786837,6651193.518927223,97.52974240811844],[508882.343281533,6651193.25060433,97.74916141411845],[508881.82814209466,6651195.205576601,96.20110057911843],[508889.697796842,6651185.563565425,96.94397600866016],[508882.728279558,6651191.789523297,99.10039304411843],[508881.872907451,6651195.035690501,96.55155679411844],[508882.6359018299,6651192.14010002,99.00129755011844],[508889.77324997506,6651185.27410773,97.53171085866015],[508881.9248907542,6651194.83841204,96.89130182111843],[508889.638772791,6651185.789996919,97.21038232366014],[508882.5439797091,6651192.488947699,98.87367479111843],[508881.98382957355,6651194.614737148,97.21696893111844],[508882.45334537025,6651192.8329082,98.71718349911843],[508882.04932726175,6651194.36617112,97.52533773911846],[508882.3648607275,6651193.168710529,98.53197459711843],[508882.1208605309,6651194.09469985,97.81343609011843],[508882.27939380344,6651193.493060509,98.31872226211844],[508882.1977929706,6651193.802738537,98.07863381511844],[508889.7024362197,6651185.545767575,97.81980920966014],[508889.5746518346,6651186.0359814605,97.45809206366016],[508889.6262776009,6651185.8379316935,98.08500693466014],[508889.4822518374,6651186.3904517,97.75553453366014],[508889.54549754574,6651186.147824837,98.32509538166015],[508889.383428662,6651186.769562908,98.01174765666013],[508889.46089028625,6651186.472400124,98.53834771666016],[508889.2799213966,6651187.166643497,98.22402546566013],[508889.37329566176,6651186.808435714,98.72355661866014],[508889.1735236138,6651187.574812855,98.39114022266014],[508889.28357296373,6651187.152635143,98.88004791066015],[508889.065990367,6651187.987338146,98.51329334466014],[508889.1925754367,6651187.501725144,99.00767066966016],[508888.95895737363,6651188.397944337,98.59196803766015],[508886.8783707826,6651196.379611547,92.23344354966014],[508889.10112688533,6651187.852545393,99.10676616366015],[508886.8783707826,6651196.379611547,92.36344354966016],[508888.85387870675,6651188.801053226,98.62971089666014],[508886.72460393567,6651196.969500862,92.23344354966014],[508888.97982282605,6651188.317899075,99.19593081566015],[508888.86073366995,6651188.774755819,99.23870605666015],[508888.41245573515,6651190.494465686,98.62971089666014],[508886.87837019254,6651196.37961381,94.06224720966014],[508886.8795167473,6651196.375215331,94.26606849366014],[508886.72460393567,6651196.969500862,94.06224720866015],[508886.8890370702,6651196.338692915,94.68264778166015],[508886.72989094385,6651196.949218535,94.52783789566014],[508886.90888210834,6651196.262562226,95.10697490166014],[508887.98020931665,6651192.15267452,98.62971089666014],[508886.9396942192,6651196.144359015,95.53328525266015],[508886.74642412324,6651196.88579299,95.00510884766014],[508887.8751306496,6651192.555783411,98.59196803766015],[508886.98184752936,6651195.982648036,95.95509411166015],[508887.7680976564,6651192.966389601,98.51329334466014],[508886.77505619987,6651196.775952955,95.48800986766015],[508887.97335494356,6651192.178969665,99.23870605666015],[508887.0353928443,6651195.777234387,96.36544365466014],[508887.66056440957,6651193.378914892,98.39114022266014],[508887.1000204775,6651195.529306104,96.75722334866015],[508886.8048340134,6651196.661717575,95.84971585266014],[508887.55416662677,6651193.787084251,98.22402546566013],[508887.15536710015,6651195.316982173,97.03470520866014],[508887.8542657875,6651192.635826407,99.19593081566015],[508887.4506593612,6651194.184164838,98.01174765666013],[508887.21614969283,6651195.083804459,97.29514588166015],[508887.28184369043,6651194.831785328,97.53611552766014],[508887.35183618596,6651194.563276047,97.75553453366014],[508886.8418782509,6651196.519606319,96.20747369866014],[508887.73296172824,6651193.10118009,99.10676616366015],[508886.8861933371,6651196.349602209,96.55792991366016],[508887.64151317684,6651193.452000339,99.00767066966016],[508886.93765376904,6651196.152186709,96.89767494066015],[508887.55051564984,6651193.801090341,98.88004791066015],[508886.9959997554,6651195.928356444,97.22334205066014],[508887.4607929517,6651194.14528977,98.72355661866014],[508887.0608386385,6651195.679617752,97.53171085866015],[508887.37319832726,6651194.48132536,98.53834771666016],[508887.13165239384,6651195.407957908,97.81980920966014],[508887.28859106783,6651194.805900645,98.32509538166015],[508887.2078110126,6651195.115793789,98.08500693466014],[508901.9468384022,6651187.030150988,92.24021393804705],[508901.7967848785,6651187.620995796,92.24021393804705],[508901.7967848785,6651187.620995796,92.37021393804707],[508901.9468384022,6651187.030150988,94.06901759704706],[508901.7967848785,6651187.620995796,94.06901759704706],[508901.94167907024,6651187.05046617,94.53460828404705],[508901.7922325268,6651187.638920956,94.47983290904705],[508901.92554515146,6651187.113994448,95.01187923604705],[508901.77799671615,6651187.694975321,94.90095433704705],[508901.8976045122,6651187.224012404,95.49478025604706],[508901.7533432108,6651187.792049986,95.32704347204707],[508901.8685458045,6651187.338432819,95.85648624104705],[508901.717768532,6651187.932127431,95.75194997604706],[508901.83239615016,6651187.480774265,96.21424408704705],[508901.67105954,6651188.116046907,96.16891667804705],[508901.7891512311,6651187.651053744,96.56470030204707],[508901.7389335197,6651187.848789014,96.90444532904706],[508901.6133393939,6651188.343323467,96.57086559504705],[508901.68199653353,6651188.072981834,97.23011243904705],[508901.54509243625,6651188.612049984,96.95074639704707],[508901.61872344784,6651188.32212343,97.53848124704706],[508901.48749375984,6651188.838848249,97.21715271204705],[508901.54961977724,6651188.594223305,97.82657959804705],[508901.4249212637,6651189.08523123,97.46486245204707],[508901.47530031676,6651188.886860667,98.09177732304707],[508901.3347526385,6651189.440275635,97.76230492204705],[508901.3964710231,6651189.197255771,98.33186577004707],[508901.23831594887,6651189.820000922,98.01851804504705],[508901.3139069485,6651189.522356797,98.54511810504707],[508901.13730828546,6651190.217724695,98.23079585404705],[508901.22842765093,6651189.858936692,98.73032700704705],[508901.0334799079,6651190.626555199,98.39791061104705],[508901.1408716707,6651190.203693651,98.88681829904706],[508900.9285434868,6651191.039748694,98.52006373304705],[508901.0520716475,6651190.553349102,99.01444105804707],[508900.8240952385,6651191.451019975,98.59873842604705],[508900.9628314916,6651190.904737604,99.11353655204707],[508898.7937528355,6651199.44561576,92.24021393804705],[508898.7937528355,6651199.44561576,92.37021393804707],[508900.7215541214,6651191.854781814,98.63648128504705],[508900.8444568101,6651191.370845058,99.20270120404706],[508898.64369931177,6651200.036460568,92.24021393804705],[508900.7282435438,6651191.82844181,99.24547644504706],[508900.290791095,6651193.550937236,98.63648128504705],[508909.26425075,6651188.873396899,92.23852090819406],[508898.79375225975,6651199.445618027,94.06901759804705],[508898.7948711263,6651199.441212422,94.27283888204705],[508909.11649266473,6651189.464819925,92.23852090819406],[508909.11649266473,6651189.464819925,92.36852090819407],[508898.64369931177,6651200.036460568,94.06901759704706],[508898.80416154244,6651199.404630847,94.68941817004705],[508898.6488586437,6651200.016145387,94.53460828404705],[508898.82352734177,6651199.328376844,95.11374529004705],[508899.8689830165,6651195.21183201,98.63648128504705],[508898.85359536944,6651199.209982169,95.54005564104706],[508898.66499256244,6651199.952617109,95.01187923604705],[508899.7664418994,6651195.615593849,98.59873842604705],[508898.8947307171,6651199.048009254,95.96186450004706],[508909.26425075,6651188.873396899,94.06732456719406],[508899.66199365124,6651196.026865132,98.52006373304705],[508898.69293320173,6651199.8425991535,95.49478025604706],[508899.86229417,6651195.2381697465,99.24547644504706],[508898.94698296377,6651198.84226288,96.37221404304705],[508899.55705723003,6651196.440058625,98.39791061104705],[508899.01004990103,6651198.593933006,96.76399373704706],[508898.72199190944,6651199.728178738,95.85648624104705],[508899.4532288525,6651196.848889129,98.23079585404705],[508899.74608090386,6651195.695766499,99.20270120404706],[508909.25917034276,6651188.893731961,94.53291525419407],[508909.11649266473,6651189.464819925,94.06732456719406],[508899.06405995536,6651198.381265156,97.04147559704705],[508899.35222118907,6651197.246612903,98.01851804504705],[508899.1233747062,6651198.147709745,97.30191627004706],[508899.18748225627,6651197.895282396,97.54288591604706],[508899.2557844996,6651197.62633819,97.76230492204705],[508898.75814156374,6651199.5858372925,96.21424408704705],[508899.6277062223,6651196.1618739525,99.11353655204707],[508898.80138648284,6651199.415557812,96.56470030204707],[508909.1120099525,6651189.482762627,94.47813987919407],[508899.5384660665,6651196.513262454,99.01444105804707],[508909.24328323203,6651188.957322411,95.01018620619406],[508898.8516041942,6651199.217822542,96.90444532904706],[508899.4496660433,6651196.862917906,98.88681829904706],[508898.90854118037,6651198.993629721,97.23011243904705],[508899.362110063,6651197.207674866,98.73032700704705],[508898.9718142661,6651198.744488127,97.53848124704706],[508899.27663076547,6651197.544254758,98.54511810504707],[508899.04091793665,6651198.472388252,97.82657959804705],[508899.19406669086,6651197.8693557875,98.33186577004707],[508899.11523739714,6651198.17975089,98.09177732304707],[508909.0979919136,6651189.538871847,94.89926130719408],[508909.21577001363,6651189.067448033,95.49308722619406],[508909.07371554436,6651189.636041514,95.32535044219406],[508909.1871558306,6651189.181980424,95.85479321119408],[508909.0386850681,6651189.776256042,95.75025694619407],[508909.1515591743,6651189.324461169,96.21255105719406],[508908.99269060517,6651189.960355506,96.16722364819408],[508909.1089757928,6651189.494907288,96.56300727219407],[508909.0595262851,6651189.692836069,96.90275229919406],[508908.9358534309,6651190.187854486,96.56917256519407],[508909.0034602904,6651189.917248291,97.22841940919407],[508908.86865047866,6651190.456843985,96.94905336719407],[508908.9411551224,6651190.166633703,97.53678821719409],[508908.811932916,6651190.683864202,97.21545968219407],[508908.8731085629,6651190.438999861,97.82488656819406],[508908.7503176203,6651190.9304883005,97.46316942219407],[508908.7999260017,6651190.731923607,98.09008429319407],[508908.6615283465,6651191.285880164,97.76061189219408],[508908.7223025963,6651191.042622471,98.33017274019407],[508908.5665668937,6651191.66597706,98.01682501519407],[508908.6410015427,6651191.368041652,98.54342507519407],[508908.4671043914,6651192.064090057,98.22910282419406],[508908.55682986166,6651191.704950933,98.72863397719406],[508908.3648643248,6651192.473320655,98.39621758119408],[508908.4706132658,6651192.050045281,98.88512526919406],[508908.2615331648,6651192.88691851,98.51837070319408],[508908.38317165786,6651192.400042916,99.01274802819407],[508908.1586827099,6651193.298592276,98.59704539619406],[508908.29529665015,6651192.751775297,99.11184352219406],[508906.1593993975,6651201.301011802,92.23852090819406],[508906.1593993975,6651201.301011802,92.36852090819407],[508908.05771021196,6651193.702749248,98.63478825519407],[508908.17873280105,6651193.2183388965,99.20100817419407],[508906.01164131216,6651201.892434828,92.23852090819406],[508908.06429730315,6651193.6763834655,99.24378341519409],[508907.6335367675,6651195.400564576,98.63478825519407],[508906.15939883055,6651201.30101407,94.06732456819407],[508906.16050058126,6651201.296604154,94.27114585219407],[508906.01164131216,6651201.892434828,94.06732456719406],[508906.1696488776,6651201.25998678,94.68772514019406],[508906.01672171947,6651201.872099766,94.53291525419407],[508906.1887184293,6651201.183658152,95.11205226019408],[508907.21818128304,6651197.0630847495,98.63478825519407],[508906.2183264924,6651201.065147614,95.53836261119406],[508906.0326088302,6651201.808509315,95.01018620619406],[508907.1172087851,6651197.467241721,98.59704539619406],[508906.25883257366,6651200.903016187,95.96017147019407],[508907.0143583303,6651197.878915487,98.51837070319408],[508907.211594759,6651197.089448261,99.24378341519409],[508906.0601220485,6651201.6983836945,95.49308722619406],[508906.3102854933,6651200.697068463,96.37052101319406],[508906.9110271703,6651198.292513342,98.39621758119408],[508906.3723876664,6651200.448495566,96.76230070719407],[508906.08873623156,6651201.583851304,95.85479321119408],[508906.8087871037,6651198.70174394,98.22910282419406],[508907.0971592612,6651197.547492829,99.20100817419407],[508906.4255715039,6651200.235619593,97.03978256719408],[508906.7093246013,6651199.099856937,98.01682501519407],[508906.4839788894,6651200.001835617,97.30022324019407],[508906.61436314863,6651199.479953834,97.76061189219408],[508906.5471057564,6651199.749161236,97.54119288619407],[508906.1243328879,6651201.441370559,96.21255105719406],[508906.9805954121,6651198.01405643,99.11184352219406],[508906.16691626934,6651201.270924438,96.56300727219407],[508906.89272040426,6651198.36578881,99.01274802819407],[508906.21636577713,6651201.072995658,96.90275229919406],[508906.8052787963,6651198.715786445,98.88512526919406],[508906.2724317718,6651200.848583437,97.22841940919407],[508906.7190622006,6651199.060880792,98.72863397719406],[508906.33473693975,6651200.599198025,97.53678821719409],[508906.63489051955,6651199.397790073,98.54342507519407],[508906.40278349933,6651200.326831865,97.82488656819406],[508906.55358946585,6651199.723209255,98.33017274019407],[508906.4759660606,6651200.033908119,98.09008429319407],[508918.8029521197,6651191.230892957,92.22959665928788],[508918.6581862809,6651191.823055518,92.22959665928788],[508918.6581862809,6651191.823055518,92.35959665928787],[508918.8029521197,6651191.230892957,94.05840031828788],[508918.7979745957,6651191.251253446,94.52399100528787],[508918.6581862809,6651191.823055518,94.05840031828788],[508918.65379434807,6651191.841020656,94.46921563028786],[508918.78240921453,6651191.314923412,95.00126195728788],[508918.64006018825,6651191.897200037,94.89033705828787],[508918.75545316585,6651191.4251867365,95.48416297728788],[508918.6162754394,6651191.9944912065,95.31642619328787],[508918.7274184482,6651191.539862342,95.84586896228787],[508918.5819543646,6651192.134881065,95.74133269728789],[508918.6925426591,6651191.682521251,96.20362680828786],[508918.53689133486,6651192.319210733,96.15829939928787],[508918.65082163305,6651191.853180503,96.55408302328787],[508918.6023735265,6651192.051356779,96.89382805028788],[508918.4812051692,6651192.546994185,96.56024831628787],[508918.5474429233,6651192.276049614,97.21949516028786],[508918.4153631428,6651192.816320039,96.94012911828787],[508918.48639949627,6651192.525746866,97.52786396828787],[508918.3597941666,6651193.04362413,97.20653543328788],[508918.4197309465,6651192.798453601,97.81596231928788],[508918.2994266412,6651193.290556616,97.45424517328787],[508918.348030404,6651193.091743629,98.08116004428787],[508918.2124354374,6651193.646392873,97.75168764328787],[508918.271978949,6651193.402831002,98.32124849128788],[508918.11939704756,6651194.026965055,98.00790076628786],[508918.1923243218,6651193.7286570985,98.53450082628787],[508918.02194875875,6651194.425575865,98.22017857528787],[508918.1098572,6651194.065987662,98.71970972828788],[508917.92177915404,6651194.835318179,98.38729333228787],[508918.025386575,6651194.411513528,98.87620102028787],[508917.8205405517,6651195.249433213,98.50944645428787],[508917.9397157457,6651194.761948813,99.00382377928788],[508917.7197729196,6651195.6616217485,98.58812114728788],[508917.85362029314,6651195.1141210105,99.10291927328788],[508915.76097706036,6651203.674047774,92.22959665928788],[508917.620845214,6651196.066284092,98.62586400628788],[508915.76097706036,6651203.674047774,92.35959665928787],[508917.73941697675,6651195.581268019,99.19208392528789],[508915.6162112216,6651204.266210336,92.22959665928788],[508917.62729891017,6651196.039885341,99.23485916628788],[508917.20526169904,6651197.766222427,98.62586400628788],[508915.76097650494,6651203.674050045,94.05840031928787],[508915.7620559442,6651203.669634616,94.26222160328788],[508915.6162112216,6651204.266210336,94.05840031828788],[508915.77101897844,6651203.632971454,94.67880089128788],[508915.6211887457,6651204.245849845,94.52399100528787],[508915.78970235295,6651203.556547381,95.10312801128786],[508916.7983175716,6651199.430821473,98.62586400628788],[508915.8187108238,6651203.437888652,95.52943836228786],[508915.63675412675,6651204.18217988,95.00126195728788],[508916.699389866,6651199.835483816,98.58812114728788],[508915.85839661694,6651203.275554492,95.95124722128789],[508916.598622234,6651200.247672351,98.50944645428787],[508916.7918644311,6651199.45721795,99.23485916628788],[508915.66371017543,6651204.071916554,95.48416297728788],[508915.90880756435,6651203.069349243,96.36159676428787],[508916.49738363165,6651200.661787384,98.38729333228787],[508915.96965210733,6651202.820465523,96.75337645828789],[508916.39721402683,6651201.071529699,98.22017857528787],[508915.6917448931,6651203.957240948,95.84586896228787],[508916.6797463646,6651199.9158352725,99.19208392528789],[508916.0217589198,6651202.607323363,97.03085831828787],[508916.299765738,6651201.470140509,98.00790076628786],[508916.0789834984,6651202.373247055,97.29129899128787],[508916.20672734815,6651201.850712692,97.75168764328787],[508916.14083198435,6651202.120256723,97.53226863728787],[508915.72662068217,6651203.81458204,96.20362680828786],[508916.56554304814,6651200.382982281,99.10291927328788],[508915.76834170823,6651203.643922789,96.55408302328787],[508916.4794475957,6651200.735154479,99.00382377928788],[508915.8167898148,6651203.445746511,96.89382805028788],[508916.3937767663,6651201.085589763,98.87620102028787],[508915.871720418,6651203.221053677,97.21949516028786],[508916.3093061413,6651201.431115628,98.71970972828788],[508915.932763845,6651202.971356425,97.52786396828787],[508916.2268390196,6651201.768446192,98.53450082628787],[508915.9994323948,6651202.69864969,97.81596231928788],[508916.14718439226,6651202.094272289,98.32124849128788],[508916.0711329373,6651202.405359662,98.08116004428787],[508928.4677620787,6651193.567459267,92.21282714508105],[508928.32602804626,6651194.160354798,92.21282714508105],[508928.32602804626,6651194.160354798,92.34282714508106],[508928.4677620787,6651193.567459267,94.04163080408105],[508928.46288879815,6651193.587844958,94.50722149108107],[508928.32602804626,6651194.160354798,94.04163080408105],[508928.3217280928,6651194.178342173,94.45244611608105],[508928.44764940016,6651193.651593733,94.98449244308105],[508928.3082815652,6651194.234591092,94.87356754408106],[508928.4212578874,6651193.76199354,95.46739346308105],[508928.2849949362,6651194.332002687,95.29965667908105],[508928.39381029597,6651193.876811091,95.82909944808105],[508928.25139264186,6651194.472566318,95.72456318308106],[508928.3596649047,6651194.019646581,96.18685729408105],[508928.2072733594,6651194.657124148,96.14152988508106],[508928.3188176349,6651194.190517071,96.53731350908106],[508928.27138416877,6651194.388938648,96.87705853608105],[508928.1527534197,6651194.885189546,96.54347880208107],[508928.21760396776,6651194.613909604,97.20272564608106],[508928.08829031157,6651195.154848767,96.92335960408106],[508928.15783896286,6651194.863915928,97.51109445408107],[508928.03388510685,6651195.382434212,97.18976591908105],[508928.09256664105,6651195.136960215,97.79919280508105],[508927.9747818484,6651195.629672347,97.43747565908106],[508928.0223677109,6651195.430613273,98.06439053008107],[508927.88961248647,6651195.985949052,97.73491812908105],[508927.9479089884,6651195.7420857055,98.30447897708106],[508927.7985225836,6651196.366992301,97.99113125208108],[508927.8699225544,6651196.068315105,98.51773131208105],[508927.7031151377,6651196.766096507,98.20340906108106],[508927.78918252746,6651196.406063211,98.70294021408105],[508927.6050433679,6651197.176345994,98.37052381808107],[508927.7064809564,6651196.752016763,98.85943150608105],[508927.5059249883,6651197.590973613,98.49267694008107],[508927.62260431657,6651197.102885812,98.98705426508106],[508927.4072677155,6651198.00367235,98.57135163308105],[508927.53831194644,6651197.455493922,99.08614975908105],[508925.48949458316,6651206.026016037,92.21282714508105],[508927.3104118359,6651198.408835579,98.60909449208106],[508925.48949458316,6651206.026016037,92.34282714508106],[508927.42650037055,6651197.923219158,99.17531441108106],[508925.34776055074,6651206.618911569,92.21282714508105],[508927.3167303734,6651198.382404151,99.21808965208108],[508935.69594368146,6651195.280786637,92.19521859384106],[508926.90353181545,6651200.110878071,98.60909449208106],[508935.5564770961,6651195.874219633,92.19521859384106],[508935.5564770961,6651195.874219633,92.32521859384107],[508925.4894940394,6651206.026018311,94.04163080508107],[508925.49055087205,6651206.021597415,94.24545208908106],[508925.34776055074,6651206.618911569,94.04163080408105],[508925.4993261951,6651205.984888872,94.66203137708105],[508925.3526338313,6651206.598525876,94.50722149108107],[508925.51761828695,6651205.908370203,95.08635849708105],[508926.50511024933,6651201.777537532,98.60909449208106],[508935.69594368146,6651195.280786637,94.02402225284106],[508925.5460192382,6651205.789564601,95.51266884808105],[508926.40825436986,6651202.182700761,98.57135163308105],[508925.36787322926,6651206.534777101,94.98449244308105],[508935.6911483631,6651195.301190808,94.48961293984107],[508935.5564770961,6651195.874219633,94.02402225284106],[508925.58487389865,6651205.6270295065,95.93447770708106],[508926.30959709705,6651202.595399497,98.49267694008107],[508926.498792256,6651201.803966682,99.21808965208108],[508925.3942647419,6651206.424377293,95.46739346308105],[508925.6342290983,6651205.420569018,96.34482725008107],[508926.21047871746,6651203.010027117,98.37052381808107],[508925.69379938435,6651205.171377234,96.73660694408106],[508935.552245933,6651195.892223312,94.43483756484108],[508926.11240694765,6651203.420276604,98.20340906108106],[508926.38902225887,6651202.263151676,99.17531441108106],[508925.42171233334,6651206.309559744,95.82909944808105],[508935.6761527636,6651195.364997372,94.96688389184106],[508925.74481493275,6651204.957971252,97.01408880408107],[508926.0169995016,6651203.819380809,97.99113125208108],[508925.80084106675,6651204.723605206,97.27452947708107],[508925.9259095988,6651204.200424059,97.73491812908105],[508925.8613942703,6651204.470301725,97.51549912308106],[508925.4558577247,6651206.166724255,96.18685729408105],[508926.277210683,6651202.730876911,99.08614975908105],[508935.5390145215,6651195.948523222,94.85595899284108],[508925.4967049945,6651205.995853763,96.53731350908106],[508926.19291831285,6651203.083485024,98.98705426508106],[508925.54413846065,6651205.797432187,96.87705853608105],[508935.6501834597,6651195.475497258,95.44978491184106],[508926.109041673,6651203.434354072,98.85943150608105],[508925.59791866154,6651205.572461231,97.20272564608106],[508926.02634010196,6651203.780307623,98.70294021408105],[508925.65768366656,6651205.322454908,97.51109445408107],[508925.94560007507,6651204.118055731,98.51773131208105],[508925.7229559883,6651205.049410619,97.79919280508105],[508925.867613641,6651204.44428513,98.30447897708106],[508935.51610042976,6651196.046023121,95.28204812784107],[508925.7931549186,6651204.755757561,98.06439053008107],[508935.6231749722,6651195.590418891,95.81149089684108],[508935.4830357017,6651196.186714173,95.70695463184107],[508935.58957583545,6651195.733383862,96.16924874284108],[508935.43962223514,6651196.371439305,96.12392133384108],[508935.5493820363,6651195.904409247,96.51970495784107],[508935.50270740606,6651196.103010694,96.85944998484106],[508935.3859745001,6651196.599711447,96.52587025084107],[508935.44978757546,6651196.328185587,97.18511709484108],[508935.32254266646,6651196.869615115,96.90575105284107],[508935.39097868523,6651196.578418543,97.49348590284107],[508935.26900783094,6651197.097406866,97.17215736784107],[508935.3267505836,6651196.8517103465,97.78158425384106],[508935.21085010056,6651197.344869125,97.41986710784107],[508935.2576746891,6651197.145629603,98.04678197884107],[508935.12704326975,6651197.7014687965,97.71730957784108],[508935.18440715,6651197.457384387,98.28687042584107],[508935.0374106143,6651198.082857464,97.97352270084107],[508935.10766833526,6651197.783909515,98.50012276084107],[508934.94352948724,6651198.482323458,98.18580050984109],[508935.02821997943,6651198.121963792,98.68533166284107],[508934.84702666,6651198.892944839,98.35291526684107],[508934.94684145995,6651198.468230952,98.84182295484106],[508934.7494939665,6651199.30794832,98.47506838884107],[508934.8643066703,6651198.819418063,98.96944571384107],[508934.6524150032,6651199.721021171,98.55374308184106],[508934.78136280127,6651199.172345817,99.06854120784106],[508932.7653222175,6651207.750637153,92.19521859384106],[508934.5571086145,6651200.126551682,98.59148594084108],[508932.7653222175,6651207.750637153,92.32521859384107],[508934.6713399761,6651199.640495048,99.15770585984107],[508932.6258556321,6651208.344070148,92.19521859384106],[508934.56332606863,6651200.100096295,99.20048110084107],[508934.15673782077,6651201.830137085,98.59148594084108],[508932.7653216824,6651207.75063943,94.02402225384107],[508932.76636160794,6651207.746214527,94.22784353784107],[508932.6258556321,6651208.344070148,94.02402225284106],[508932.7749965442,6651207.7094727075,94.64442282584106],[508932.6306509505,6651208.323665977,94.48961293984107],[508932.7929960009,6651207.632884675,95.06874994584108],[508933.76469016384,6651203.498307382,98.59148594084108],[508932.82094259665,6651207.513971374,95.49506029684106],[508933.66938377515,6651203.903837893,98.55374308184106],[508932.6456465501,6651208.259859414,94.96688389184106],[508932.85917566397,6651207.351288939,95.91686915584107],[508933.5723048118,6651204.316910744,98.47506838884107],[508933.75847324496,6651203.52476049,99.20048110084107],[508932.6716158539,6651208.149359527,95.44978491184106],[508932.90774128394,6651207.144641295,96.32721869884107],[508933.4747721182,6651204.731914224,98.35291526684107],[508933.37826929096,6651205.142535604,98.18580050984109],[508932.9663585705,6651206.895223618,96.71899839284107],[508933.65045933763,6651203.984361737,99.15770585984107],[508932.6986243415,6651208.034437896,95.81149089684108],[508933.0165579771,6651206.68162418,96.99648025284107],[508933.284388164,6651205.542001599,97.97352270084107],[508933.07168781053,6651206.447045681,97.25692092584107],[508933.19475550856,6651205.9233902665,97.71730957784108],[508933.13127228996,6651206.193512579,97.49789057184108],[508932.73222347815,6651207.891472924,96.16924874284108],[508933.5404365123,6651204.452510969,99.06854120784106],[508932.7724172773,6651207.7204475375,96.51970495784107],[508933.45749264327,6651204.805438722,98.96944571384107],[508932.8190919075,6651207.521846091,96.85944998484106],[508933.37495785364,6651205.156625833,98.84182295484106],[508933.2935793343,6651205.502892993,98.68533166284107],[508932.87201173813,6651207.296671198,97.18511709484108],[508933.21413097833,6651205.840947271,98.50012276084107],[508932.93082062836,6651207.046438242,97.49348590284107],[508933.1373921637,6651206.1674724,98.28687042584107],[508932.99504872994,6651206.773146439,97.78158425384106],[508933.06412462454,6651206.479227183,98.04678197884107],[508947.7180313342,6651198.065925944,92.15636226031798],[508947.5823360222,6651198.660232624,92.15636226031798],[508947.5823360222,6651198.660232624,92.28636226031799],[508947.7180313342,6651198.065925944,93.98516591931798],[508947.7133656846,6651198.086360155,94.45075660631797],[508947.5823360222,6651198.660232624,93.98516591931798],[508947.5782192727,6651198.678262811,94.39598123131796],[508947.69877557654,6651198.150260659,94.92802755831796],[508947.56534564774,6651198.734645607,94.81710265931797],[508947.6735085006,6651198.260923229,95.41092857831798],[508947.54305116896,6651198.832289051,95.24319179431797],[508947.6472303414,6651198.376014055,95.77263456331796],[508947.510880534,6651198.973187237,95.66809829831797],[508947.6145397487,6651198.519189507,96.13039240931796],[508947.4686409979,6651199.158184332,96.08506500031797],[508947.57543281774,6651198.690466686,96.48084862431799],[508947.5300203019,6651198.889360525,96.82059365131798],[508947.41644393484,6651199.386792549,96.48701391731797],[508947.4785314604,6651199.114866933,97.14626076131796],[508947.3547273421,6651199.657093584,96.86689471931798],[508947.4213128033,6651199.365468296,97.45462956931797],[508947.3026401257,6651199.885220703,97.13330103431797],[508947.3588214742,6651199.639162456,97.74272792031798],[508947.24605502066,6651200.133047289,97.38101077431797],[508947.2916134398,6651199.933514435,98.00792564531797],[508947.16451438476,6651200.490171966,97.67845324431796],[508952.6244631494,6651199.179508398,92.13707974170651],[508947.22032710584,6651200.245728201,98.24801409231797],[508947.07730545854,6651200.872122136,97.93466636731796],[508952.49030696234,6651199.774164403,92.13707974170651],[508952.49030696234,6651199.774164403,92.26707974170652],[508947.14566336205,6651200.572734058,98.46126642731798],[508946.9859629424,6651201.272176248,98.14694417631796],[508947.0683633449,6651200.911286038,98.64647532931797],[508946.89206961874,6651201.683402168,98.31405893331797],[508946.9891853571,6651201.258062992,98.80296662131796],[508952.6244631494,6651199.179508398,93.96588340070652],[508946.79717427696,6651202.09901664,98.43621205531797],[508946.90888236556,6651201.609767142,98.93058938031798],[508952.6198504199,6651199.19995462,94.43147408770653],[508952.49030696234,6651199.774164403,93.96588340070652],[508946.70272039616,6651202.512697639,98.51488674831798],[508946.82818135637,6651201.963214495,99.02968487431798],[508952.486236907,6651199.792205187,94.37669871270653],[508946.6099911584,6651202.918825195,98.55262960731797],[508952.60542580014,6651199.263892684,94.90874503970652],[508944.86665591015,6651210.554135273,92.15636226031798],[508946.72113362467,6651202.4320529625,99.11884952631799],[508944.86665591015,6651210.554135273,92.28636226031799],[508952.4735093013,6651199.848621125,94.79782014070652],[508944.7309605982,6651211.148441953,92.15636226031798],[508946.61604048836,6651202.892330859,99.16162476731797],[508952.58044531633,6651199.374620299,95.39164605970652],[508952.45146769786,6651199.946321964,95.22390927570652],[508952.5544652172,6651199.489778774,95.75335204470652],[508946.22044666903,6651204.624918713,98.55262960731797],[508952.4196619585,6651200.087302967,95.64881577970652],[508952.5221454178,6651199.633038383,96.11110989070652],[508944.86665538955,6651210.554137555,93.98516592031797],[508952.4834820575,6651199.8044162365,96.46156610570652],[508952.3779015246,6651200.272408801,96.06578248170652],[508944.86766719486,6651210.549706136,94.18898720431797],[508944.7309605982,6651211.148441953,93.98516591931798],[508944.87606863637,6651210.512910223,94.60556649231798],[508952.43858463346,6651200.003426982,96.80131113270652],[508952.3262965071,6651200.501151389,96.46773139870653],[508944.89358137525,6651210.436209433,95.02989361231796],[508944.7356262477,6651211.128007742,94.45075660631797],[508945.839000253,6651206.295544983,98.55262960731797],[508952.38767980435,6651200.229065941,97.12697824270653],[508944.92077227565,6651210.3171210615,95.45620396331798],[508945.74627101526,6651206.701672539,98.51488674831798],[508952.2652799351,6651200.771611306,96.84761220070652],[508944.7502163559,6651211.064107238,94.92802755831796],[508945.6518171345,6651207.115353539,98.43621205531797],[508944.95797149424,6651210.154199116,95.87801282231797],[508945.8329514441,6651206.322037038,99.16162476731797],[508952.3311101504,6651200.479814603,97.43534705070654],[508944.77548343176,6651210.953444668,95.41092857831798],[508945.5569217928,6651207.530968011,98.31405893331797],[508945.0052238661,6651209.947247235,96.28836236531797],[508952.21378351835,6651200.999872515,97.11401851570652],[508945.7278583078,6651206.782314935,99.11884952631799],[508945.463028469,6651207.94219393,98.14694417631796],[508945.0622561005,6651209.697462349,96.68014205931799],[508944.801761591,6651210.838353842,95.77263456331796],[508945.1110980803,6651209.483548438,96.95762391931797],[508945.3716859529,6651208.342248043,97.93466636731796],[508945.1647371648,6651209.248624582,97.21806459231797],[508945.28447702667,6651208.724198211,97.67845324431796],[508945.2227104385,6651208.994718214,97.45903423831797],[508952.2693276296,6651200.753669637,97.72344540170651],[508945.6208105761,6651207.251153402,99.02968487431798],[508944.83445218374,6651210.6951783905,96.13039240931796],[508952.1578402302,6651201.24784477,97.36172825570652],[508945.5401095668,6651207.604600755,98.93058938031798],[508944.8735591147,6651210.523901211,96.48084862431799],[508945.4598065753,6651207.956304904,98.80296662131796],[508944.9189716305,6651210.325007372,96.82059365131798],[508952.20288190275,6651201.048194633,97.98864312670652],[508945.38062858756,6651208.303081859,98.64647532931797],[508944.97046047205,6651210.099500963,97.14626076131796],[508945.3033285704,6651208.641633839,98.46126642731798],[508945.02767912904,6651209.848899601,97.45462956931797],[508952.07722446957,6651201.60517936,97.65917072570653],[508945.2286648265,6651208.968639695,98.24801409231797],[508945.09017045813,6651209.575205442,97.74272792031798],[508945.1573784926,6651209.2808534615,98.00792564531797],[508952.1324041345,6651201.3605919145,98.22873157370653],[508951.9910047112,6651201.987354035,97.91538384870653],[508952.0585872647,6651201.68778998,98.44198390870652],[508951.90069824824,6651202.387643293,98.12766165770651],[508951.98216402344,6651202.026540956,98.62719281070652],[508951.8078699101,6651202.799110927,98.29477641470653],[508951.9038841126,6651202.373521742,98.78368410270652],[508951.71405091946,6651203.214969691,98.41692953670653],[508951.82449195825,6651202.725432619,98.91130686170652],[508951.6206683824,6651203.628893848,98.49560422970652],[508951.7447063008,6651203.079087725,99.01040235570652],[508951.5289909267,6651204.0352601195,98.53334708870652],[508949.8054294701,6651211.675058132,92.13707974170651],[508951.6388727587,6651203.548201768,99.09956700770653],[508949.8054294701,6651211.675058132,92.26707974170652],[508951.53497164196,6651204.0087502105,99.14234224870654],[508949.67127328314,6651212.269714138,92.13707974170651],[508951.14386484824,6651205.742356456,98.53334708870652],[508949.8054289554,6651211.675060415,93.96588340170653],[508949.8064292842,6651211.670626392,94.16970468570652],[508949.67127328314,6651212.269714138,93.96588340070652],[508949.81473543245,6651211.63380885,94.58628397370651],[508949.832049533,6651211.557062976,95.01061109370652],[508950.7667449908,6651207.413964699,98.53334708870652],[508949.6758860125,6651212.249267915,94.43147408770653],[508950.675067535,6651207.820330971,98.49560422970652],[508949.8589320203,6651211.437904607,95.43692144470651],[508949.6903106322,6651212.185329852,94.90874503970652],[508950.58168499806,6651208.234255128,98.41692953670653],[508949.89570930664,6651211.274886899,95.85873030370652],[508950.76076479047,6651207.440472324,99.14234224870654],[508950.4878660074,6651208.650113892,98.29477641470653],[508949.71529111615,6651212.074602236,95.39164605970652],[508949.94242571807,6651211.067813372,96.26907984670653],[508950.6568636737,6651207.901020768,99.09956700770653],[508950.3950376692,6651209.061581525,98.12766165770651],[508949.998811064,6651210.817881668,96.66085954070653],[508949.7412712152,6651211.959443761,95.75335204470652],[508950.04709905334,6651210.603842022,96.93834140070653],[508950.30473120627,6651209.461870784,97.91538384870653],[508950.10012973606,6651210.368780077,97.19878207370654],[508950.21851144783,6651209.844045457,97.65917072570653],[508950.1574454476,6651210.114724467,97.43975171970652],[508950.55103013164,6651208.370134811,99.01040235570652],[508949.7735910147,6651211.816184153,96.11110989070652],[508950.47124447423,6651208.723789916,98.91130686170652],[508949.8122543749,6651211.644806298,96.46156610570652],[508950.3918523198,6651209.075700793,98.78368410270652],[508949.85715179896,6651211.445795553,96.80131113270652],[508950.313572409,6651209.422681578,98.62719281070652],[508949.9080566281,6651211.220156594,97.12697824270653],[508950.23714916775,6651209.761432555,98.44198390870652],[508949.96462628205,6651210.969407933,97.43534705070654],[508950.16333229793,6651210.088630621,98.22873157370653],[508950.02640880283,6651210.695552899,97.72344540170651],[508950.0928545297,6651210.401027903,97.98864312670652],[508967.01306634734,6651202.3683314,92.06912625390798],[508966.8834237986,6651202.963987725,92.06912625390798],[508966.8834237986,6651202.963987725,92.19912625390799],[508967.01306634734,6651202.3683314,93.89792991290798],[508967.0086088116,6651202.388812016,94.36352059990799],[508966.8834237986,6651202.963987725,93.89792991290798],[508966.8794906789,6651202.982058856,94.30874522490798],[508966.9946695031,6651202.452857635,94.840791551908],[508966.8671912891,6651203.038569696,94.729866652908],[508966.970529479,6651202.563771514,95.32369257190798],[508966.8458912677,6651203.136434885,95.15595578790798],[508966.9454234713,6651202.679123707,95.685398556908],[508969.5871577454,6651202.926746684,92.05518010288448],[508966.8151556214,6651203.277653044,95.580862291908],[508966.9141910603,6651202.822624304,96.043156402908],[508969.45832267724,6651203.522578181,92.05518010288448],[508969.45832267724,6651203.522578181,92.18518010288449],[508966.8768285154,6651202.994290448,96.39361261790799],[508966.77480020275,6651203.463070259,95.997828993908],[508966.83344164956,6651203.193635966,96.73335764490798],[508966.72493141814,6651203.692197635,96.39977791090799],[508969.5871577454,6651202.926746684,93.88398376188448],[508966.78424949583,6651203.419654489,97.05902475490798],[508966.6659677276,6651203.963112514,96.77965871290799],[508969.58272797347,6651202.947233324,94.34957444888448],[508969.45832267724,6651203.522578181,93.88398376188448],[508966.72958310816,6651203.670824957,97.36739356290799],[508966.6162038899,6651204.1917576995,97.046065027908],[508969.4544140551,6651203.540654628,94.29479907388448],[508969.5688754862,6651203.011297778,94.82684540088448],[508966.6698792388,6651203.945140663,97.65549191390798],[508966.56214279425,6651204.440147088,97.29377476790799],[508969.44219127216,6651203.597182088,94.71592050188448],[508969.5448858186,6651203.122244275,95.30974642088448],[508966.6056690553,6651204.240161103,97.92068963890799],[508966.4842393229,6651204.798082781,97.59121723790798],[508969.42102391826,6651203.695076056,95.1420096368845],[508969.51993618405,6651203.2376303915,95.67145240588448],[508966.5375624871,6651204.553083894,98.16077808590799],[508966.40092039836,6651205.180900342,97.84743036090799],[508969.3904797095,6651203.836335745,95.56691614088449],[508969.4888983046,6651203.381173189,96.02921025188448],[508966.46622916026,6651204.880832368,98.37403042090799],[508966.3136522649,6651205.58186296,98.059708169908],[508969.4517684728,6651203.5528898155,96.3796664668845],[508969.3503756451,6651204.021807489,95.98388284288448],[508966.39237715246,6651205.220153184,98.559239322908],[508966.223947104,6651205.994022755,98.22682292690799],[508969.40865184274,6651203.752293957,96.71941149388448],[508966.316730942,6651205.567717653,98.71573061490798],[508969.30081746896,6651204.251002246,96.3858317598845],[508966.1332846207,6651206.41058107,98.34897604890799],[508966.2400099091,6651205.920220507,98.84335337390799],[508969.3597660831,6651203.97837895,97.04507860388448],[508969.24222103466,6651204.521996795,96.7657125618845],[508966.0430439068,6651206.825201521,98.42765074190798],[508966.16290861234,6651206.274470524,98.94244886790798],[508969.3054401859,6651204.229623281,97.35344741188449],[508969.19276715175,6651204.750709222,97.03211887688448],[508965.9544509072,6651207.232251374,98.465393600908],[508966.06063580315,6651206.744373702,99.03161351990799],[508964.28887807723,6651214.884900912,92.06912625390798],[508964.28887807723,6651214.884900912,92.19912625390799],[508969.24610818294,6651204.504019661,97.64154576288448],[508969.1390427766,6651204.9991716575,97.2798286168845],[508965.96023040335,6651207.2056968715,99.074388760908],[508964.1592355286,6651215.480557236,92.06912625390798],[508969.1822979336,6651204.799126862,97.9067434878845],[508969.06162452814,6651205.357212614,97.57727108688448],[508969.1146155682,6651205.112141677,98.1468319348845],[508965.58228226186,6651208.942219356,98.465393600908],[508968.97882455675,6651205.740142754,97.8334842098845],[508969.04372654203,6651205.439986534,98.3600842698845],[508964.2888775799,6651214.884903196,93.89792991390799],[508968.89209997427,6651206.141223288,98.04576201888449],[508964.289844253,6651214.880461715,94.101751197908],[508968.97033452266,6651205.77940714,98.54529317188448],[508964.1592355286,6651215.480557236,93.89792991290798],[508964.2978709437,6651214.843582242,94.51833048590798],[508968.8029535432,6651206.553504294,98.21287677588448],[508968.89515947574,6651206.1270738235,98.7017844638845],[508965.21785047103,6651210.616639547,98.465393600908],[508964.31460251735,6651214.766707266,94.94265760590798],[508964.16369306436,6651215.460076619,94.36352059990799],[508968.7128557526,6651206.97018511,98.33502989788448],[508965.1292574715,6651211.023689401,98.42765074190798],[508968.8189163009,6651206.479680342,98.82940722288448],[508964.3405805528,6651214.64734845,95.36896795690798],[508964.17763237277,6651215.396031001,94.840791551908],[508965.0390167575,6651211.438309852,98.34897604890799],[508965.2120714725,6651210.643191763,99.074388760908],[508964.37612048,6651214.484056517,95.790776815908],[508968.6231771042,6651207.384927495,98.41370459088448],[508968.7422952308,6651206.834034539,98.92850271688448],[508964.9483542742,6651211.854868167,98.22682292690799],[508964.201772397,6651215.2851171205,95.32369257190798],[508964.42126513406,6651214.276634655,96.20112635890798],[508965.1116660728,6651211.104514932,99.03161351990799],[508964.8586491133,6651212.267027964,98.059708169908],[508964.47575341456,6651214.026282521,96.59290605290799],[508968.5351359076,6651207.792097054,98.45144744988448],[508964.2268784046,6651215.169764928,95.685398556908],[508964.77138097986,6651212.66799058,97.84743036090799],[508964.52241677133,6651213.811882821,96.87038791290799],[508964.57366325514,6651213.57642546,97.13082858590799],[508964.6880620553,6651213.050808142,97.59121723790798],[508964.6290505994,6651213.321942482,97.371798231908],[508968.6406594292,6651207.304075907,99.01766736888449],[508965.00939326355,6651211.574418111,98.94244886790798],[508966.8799371232,6651215.446997104,92.05518010288448],[508964.25811081566,6651215.02626433,96.043156402908],[508966.8799371232,6651215.446997104,92.18518010288449],[508964.93229196675,6651211.928668127,98.84335337390799],[508964.2954733606,6651214.854598189,96.39361261790799],[508964.85557093384,6651212.281170982,98.71573061490798],[508968.5408794061,6651207.765534743,99.06044260988449],[508964.3388602264,6651214.655252671,96.73335764490798],[508966.7511020551,6651216.042828602,92.05518010288448],[508964.7799247234,6651212.628735453,98.559239322908],[508964.3880523801,6651214.429234146,97.05902475490798],[508964.7060727157,6651212.968056269,98.37403042090799],[508964.44271876774,6651214.1780636795,97.36739356290799],[508964.63473938877,6651213.295804741,98.16077808590799],[508964.5024226372,6651213.903747972,97.65549191390798],[508964.5666328205,6651213.6087275315,97.92068963890799],[508968.1652853203,6651209.502567909,98.45144744988448],[508966.87993662886,6651215.446999391,93.88398376288448],[508966.8808972811,6651215.442556604,94.08780504688448],[508966.7511020551,6651216.042828602,93.88398376188448],[508966.8888739774,6651215.405666283,94.50438433488448],[508967.80312339845,6651211.177480518,98.45144744988448],[508966.90550133825,6651215.3287687,94.92871145488448],[508966.755531827,6651216.022341961,94.34957444888448],[508967.7150822017,6651211.584650078,98.41370459088448],[508966.931317569,6651215.209374783,95.35502180588449],[508966.7693843142,6651215.958277508,94.82684540088448],[508967.6254035534,6651211.999392463,98.33502989788448],[508967.79738039436,6651211.204040544,99.06044260988449],[508966.9666361353,6651215.046034829,95.77683066488449],[508967.5353057627,6651212.416073279,98.21287677588448],[508966.7933739819,6651215.84733101,95.30974642088448],[508967.0114996052,6651214.838551968,96.1871802078845],[508967.6976003712,6651211.665499379,99.01766736888449],[508967.4461593317,6651212.828354284,98.04576201888449],[508967.06564850465,6651214.588126208,96.57895990188449],[508966.81832361646,6651215.731944894,95.67145240588448],[508967.35943474923,6651213.229434817,97.8334842098845],[508967.11202121794,6651214.373663458,96.85644176188448],[508967.1629485123,6651214.138136854,97.1168824348845],[508967.2766347778,6651213.612364959,97.57727108688448],[508967.21799087565,6651213.883579036,97.35785208088448],[508967.5959645697,6651212.135540748,98.92850271688448],[508966.84936149593,6651215.588402097,96.02921025188448],[508967.5193434995,6651212.489894943,98.82940722288448],[508966.88649132766,6651215.41668547,96.3796664668845],[508967.4431003248,6651212.842501462,98.7017844638845],[508966.9296079578,6651215.2172813285,96.71941149388448],[508967.36792527785,6651213.190168145,98.54529317188448],[508966.9784937174,6651214.991196336,97.04507860388448],[508967.2945332585,6651213.529588751,98.3600842698845],[508967.03281961463,6651214.739952004,97.35344741188449],[508967.2236442322,6651213.857433608,98.1468319348845],[508967.0921516176,6651214.465555625,97.64154576288448],[508967.1559618669,6651214.170448423,97.9067434878845],[508986.3508703175,6651206.474230385,91.95111912584724],[508986.5826719601,6651206.522202054,91.94951967737245],[508986.22729394847,6651207.071174711,91.95111912584724],[508986.22729394847,6651207.071174711,92.08111912584725],[508986.4591683062,6651207.119161429,91.94951967737245],[508986.4591683062,6651207.119161429,92.07951967737247],[508986.3508703175,6651206.474230385,93.77992278484724],[508986.5826719601,6651206.522202054,93.77832333637247],[508986.3466213569,6651206.494755287,94.24551347184725],[508986.22729394847,6651207.071174711,93.77992278484724],[508986.57842549967,6651206.542727474,94.24391402337245],[508986.4591683062,6651207.119161429,93.77832333637247],[508986.22354486573,6651207.089284918,94.19073809684726],[508986.3333342907,6651206.558939394,94.72278442384724],[508986.4554214295,6651207.137272093,94.18913864837245],[508986.5651462519,6651206.606913199,94.72118497537245],[508986.21182098374,6651207.145917953,94.61185952484726],[508986.31032381643,6651206.670093105,95.20568544384724],[508986.44370444614,6651207.193906556,94.61026007637246],[508986.191517624,6651207.243994758,95.03794865984725],[508986.54214931745,6651206.718069713,95.20408599537247],[508986.2863925585,6651206.785694726,95.56739142884726],[508986.4234130333,6651207.291985833,95.03634921137247],[508986.51823214133,6651206.833674248,95.56579198037245],[508986.16222014715,6651207.385518276,95.46285516384725],[508986.25662156136,6651206.929505618,95.92514927484724],[508986.39413279586,6651207.43351292,95.46125571537246],[508986.48847866204,6651206.977488765,95.92354982637245],[508986.22100726893,6651207.101542958,96.27560548984725],[508986.1237530224,6651207.571336425,95.87982186584726],[508986.45288532594,6651207.1495304415,96.27400604137247],[508986.35568830586,6651207.619335752,95.87822241737246],[508986.17965054314,6651207.3013195265,96.61535051684724],[508986.07621767704,6651207.800959247,96.28177078284725],[508986.4115529353,6651207.349312046,96.61375106837247],[508986.3081809314,6651207.848964362,96.28017133437245],[508986.132760168,6651207.527826774,96.94101762684726],[508986.0200129907,6651208.07245993,96.66165158484725],[508986.36469015153,6651207.575825005,96.93941817837245],[508986.080651707,6651207.779540353,97.24938643484727],[508986.2520093172,6651208.120471891,96.66005213637247],[508985.9725776816,6651208.301599521,96.92805789984725],[508986.3126123523,6651207.827544929,97.24778698637246],[508986.20460192004,6651208.349617258,96.92645845137245],[508986.02374147606,6651208.05444922,97.53748478584724],[508985.9210461901,6651208.550526008,97.17576763984725],[508986.2557356087,6651208.102460726,97.53588533737245],[508986.1531007509,6651208.59855002,97.17416819137247],[508985.96253578865,6651208.35010759,97.80268251084725],[508985.8467879453,6651208.909235673,97.47321010984726],[508986.19456593593,6651208.398126549,97.80108306237247],[508985.89761603443,6651208.663707021,98.04277095784725],[508986.0788862013,6651208.957268728,97.47161066137245],[508985.76736764493,6651209.292881011,97.72942323284725],[508986.129684382,6651208.711733885,98.04117150937248],[508985.8296205066,6651208.992164191,98.25602329284725],[508985.99951263354,6651209.340923736,97.72782378437245],[508985.68418292527,6651209.694710638,97.94170104184724],[508986.0617288643,6651209.040199336,98.25442384437247],[508985.75922415097,6651209.332218729,98.44123219484725],[508985.9163768618,6651209.742763494,97.94010159337245],[508985.5986752106,6651210.107761657,98.10881579884726],[508985.9913739314,6651209.380262447,98.43963274637245],[508985.6871175462,6651209.6805347465,98.59772348684724],[508985.8309194617,6651210.155824927,98.10721635037245],[508985.91930975585,6651209.728587244,98.59612403837247],[508985.51225496817,6651210.525220706,98.23096892084726],[508985.6139864117,6651210.033799825,98.72534624584725],[508985.7445500709,6651210.573294497,98.22936947237245],[508985.8462216534,6651210.08186123,98.72374679737247],[508985.4262367599,6651210.9407377,98.30964361384724],[508985.54049280647,6651210.388815845,98.82444173984725],[508985.6585824776,6651210.988821967,98.30804416537245],[508985.77277129336,6651210.4368862,98.82284229137247],[508985.34178916673,6651211.348667727,98.34738647284725],[508985.44300550356,6651210.859735106,98.91360639184725],[508983.7541511217,6651219.0178647665,91.95111912584724],[508985.5741845753,6651211.396762278,98.34578702437246],[508983.7541511217,6651219.0178647665,92.08111912584725],[508985.6753413542,6651210.907817331,98.91200694337246],[508985.34729823115,6651211.322055805,98.95638163284727],[508983.9874807321,6651219.066152652,91.94951967737245],[508983.9874807321,6651219.066152652,92.07951967737247],[508983.63057475275,6651219.614809092,91.95111912584724],[508985.5796903981,6651211.370149684,98.95478218437246],[508983.8639770783,6651219.663112026,91.94951967737245],[508984.98703488056,6651213.062333213,98.34738647284725],[508985.2196390345,6651213.110470964,98.34578702437246],[508983.75415064755,6651219.017867057,93.77992278584725],[508983.75507208856,6651219.013415971,93.98374406984725],[508983.9874802582,6651219.066154941,93.77832333737246],[508983.63057475275,6651219.614809092,93.77992278484724],[508983.988401157,6651219.061703744,93.98214462137246],[508983.76272319775,6651218.976456751,94.40032335784724],[508984.6396554291,6651214.740374042,98.34738647284725],[508983.8639770783,6651219.663112026,93.77832333637247],[508983.77867187466,6651218.899415548,94.82465047784726],[508983.99604776414,6651219.024743592,94.39872390937245],[508983.6348237134,6651219.59428419,94.24551347184725],[508984.555207836,6651215.148304069,98.30964361384724],[508984.872463989,6651214.788554094,98.34578702437246],[508983.8034343567,6651218.77979864,95.25096082884724],[508984.01198705647,6651218.9477004465,94.82305102937245],[508983.8682235387,6651219.642586607,94.24391402337245],[508983.6481107796,6651219.530100084,94.72278442384724],[508984.4691896277,6651215.563821062,98.23096892084726],[508984.6341468391,6651214.766983673,98.95638163284727],[508984.7880660867,6651215.196494405,98.30804416537245],[508983.8373113146,6651218.6161536155,95.67276968784725],[508984.0367349677,6651218.828080523,95.24936138037246],[508984.3827693853,6651215.981280112,98.10881579884726],[508983.8815027865,6651219.578400882,94.72118497537245],[508983.88034357893,6651218.408283242,96.08311923084725],[508983.6711212539,6651219.418946372,95.20568544384724],[508984.7020984934,6651215.612021874,98.22936947237245],[508984.8669586402,6651214.815164397,98.95478218437246],[508984.5384395666,6651215.2293043705,98.91360639184725],[508984.29726167064,6651216.39433113,97.94170104184724],[508984.07059199165,6651218.664431374,95.67117023937246],[508983.93228226673,6651218.157389765,96.47489892484725],[508984.21407695103,6651216.796160758,97.72942323284725],[508983.9767621712,6651217.9425264625,96.75238078484726],[508984.6157291025,6651216.029491446,98.10721635037245],[508983.6950525118,6651219.303344752,95.56739142884726],[508984.02561075106,6651217.706559968,97.01282145784725],[508984.13465665065,6651217.179806095,97.47321010984726],[508984.078406434,6651217.451526715,97.25379110384725],[508984.11359893484,6651218.4565557595,96.08151978237245],[508983.9044997209,6651219.467244368,95.20408599537247],[508984.4409522638,6651215.700223631,98.82444173984725],[508984.77130768413,6651215.277496749,98.91200694337246],[508984.5302717025,6651216.4425528785,97.94010159337245],[508983.7248235089,6651219.159533859,95.92514927484724],[508984.16550706077,6651218.2056559585,96.47329947637246],[508984.3674586585,6651216.055239651,98.72534624584725],[508984.44713593076,6651216.844392635,97.72782378437245],[508984.2099607923,6651217.99078724,96.75078133637246],[508983.92841689714,6651219.351639832,95.56579198037245],[508984.2587806285,6651217.754814797,97.01122200937246],[508984.367762363,6651217.228047645,97.47161066137245],[508984.3115452453,6651217.4997751145,97.25219165537246],[508983.7604378013,6651218.987496519,96.27560548984725],[508984.673877745,6651215.748427881,98.82284229137247],[508984.294327524,6651216.408504731,98.59772348684724],[508983.95817037625,6651219.207825315,95.92354982637245],[508983.8017945271,6651218.787719951,96.61535051684724],[508984.22222091927,6651216.756820748,98.44123219484725],[508984.60042738507,6651216.103452851,98.72374679737247],[508983.8486849023,6651218.561212704,96.94101762684726],[508984.1518245636,6651217.096875287,98.25602329284725],[508983.9937637125,6651219.035783638,96.27400604137247],[508983.9007933632,6651218.309499124,97.24938643484727],[508984.08382903587,6651217.425332457,98.04277095784725],[508984.52733928256,6651216.456726837,98.59612403837247],[508983.95770359423,6651218.034590257,97.53748478584724],[508984.01890928164,6651217.738931888,97.80268251084725],[508984.03509610303,6651218.836002034,96.61375106837247],[508984.45527510694,6651216.805051634,98.43963274637245],[508984.0819588868,6651218.609489076,96.93941817837245],[508984.38492017414,6651217.145114744,98.25442384437247],[508984.134036686,6651218.357769151,97.24778698637246],[508984.3169646564,6651217.473580196,98.04117150937248],[508984.1909134298,6651218.0828533545,97.53588533737245],[508984.25208310236,6651217.787187531,97.80108306237247],[509003.609647662,6651209.965587189,91.82009846517153],[509003.4914852917,6651210.563626738,91.82009846517153],[509003.4914852917,6651210.563626738,91.95009846517154],[509003.609647662,6651209.965587189,93.64890212417153],[509003.60558485246,6651209.98614975,94.11449281117152],[509003.4914852917,6651210.563626738,93.64890212417153],[509003.4879004598,6651210.581770174,94.05971743617151],[509003.59287990525,6651210.050451616,94.59176376317151],[509005.7294420178,6651210.383197987,91.80234087613896],[509003.47669021226,6651210.638507114,94.48083886417152],[509003.57087754185,6651210.161809263,95.07466478317153],[509003.45727636217,6651210.736763861,94.90692799917151],[509005.6119446172,6651210.981368539,91.80234087613896],[509003.5479947352,6651210.277622979,95.43637076817151],[509005.6119446172,6651210.981368539,91.93234087613897],[509003.42926243576,6651210.878547035,95.33183450317152],[509003.51952803385,6651210.421697723,95.79412861417151],[509003.4854740376,6651210.594050703,96.14458482917154],[509003.39248059236,6651211.064706106,95.74880120517152],[509005.7294420178,6651210.383197987,93.63114453513896],[509003.44592918945,6651210.794193803,96.48432985617153],[509003.34702781594,6651211.294750222,96.15075012217152],[509005.7254020721,6651210.403765052,94.09673522213897],[509005.6119446172,6651210.981368539,93.63114453513896],[509003.4010931264,6651211.021116628,96.80999696617151],[509005.60837995925,6651210.999515948,94.04195984713895],[509005.7127686232,6651210.468081003,94.57400617413896],[509003.29328551056,6651211.56674903,96.53063092417153],[509003.3512675868,6651211.27329203,97.11836577417152],[509005.5972327985,6651211.056265317,94.46308127513896],[509003.24792838754,6651211.796309028,96.79703723917152],[509005.6908900801,6651210.579463043,95.05690719413896],[509003.2968506475,6651211.548705275,97.40646412517152],[509005.5779282015,6651211.154543589,94.88917041013897],[509003.19865454,6651212.045692224,97.04474697917152],[509005.66813604854,6651210.69530213,95.41861317913896],[509003.2383264395,6651211.8449060945,97.67166185017152],[509005.55007192615,6651211.296357821,95.31407691413897],[509005.6398295462,6651210.839408435,95.77637102513896],[509003.1276496197,6651212.405060018,97.34218944917151],[509003.1762508817,6651212.15908089,97.91175029717152],[509005.605967192,6651211.011799168,96.12682724013897],[509005.51349707606,6651211.482557669,95.73104361613896],[509003.0517087985,6651212.789409236,97.59840257217152],[509003.1112343029,6651212.488140686,98.12500263217153],[509005.56664488616,6651211.211986111,96.46657226713896],[509005.4683000892,6651211.712652177,96.13299253313897],[509002.9721684809,6651213.191976106,97.81068038117152],[509003.0439220788,6651212.828819128,98.31021153417151],[509005.5220611422,6651211.438958645,96.79223937713896],[509005.4148602237,6651211.984710569,96.51287333513896],[509002.8904069409,6651213.605784956,97.97779513817152],[509002.9749745333,6651213.177774205,98.46670282617151],[509005.4725160005,6651211.691189285,97.10060818513897],[509005.3697583521,6651212.214320851,96.77927965013896],[509002.8077728518,6651214.024009922,98.09994826017152],[509002.9050473436,6651213.5316874245,98.59432558517153],[509005.4184052974,6651211.9666628605,97.38870653613895],[509005.32076179766,6651212.463758675,97.02698939013897],[509002.7255231832,6651214.440289271,98.17862295317153],[509002.83477356343,6651213.887354798,98.69342107917153],[509002.6447753198,6651214.848967734,98.21636581217152],[509005.36021044,6651212.262928563,97.65390426113898],[509002.74155727227,6651214.35913806,98.78258573117154],[509005.25015646423,6651212.823205192,97.32443186013896],[509001.1266932131,6651222.532235561,91.82009846517153],[509001.1266932131,6651222.532235561,91.95009846517154],[509005.29848421813,6651212.577172182,97.89399270813898],[509002.65004302684,6651214.822306987,98.82536097217152],[509005.174643007,6651213.207638601,97.58064498313898],[509001.0085308428,6651223.13027511,91.82009846517153],[509005.2338335261,6651212.90630406,98.10724504313896],[509005.09555030987,6651213.610293655,97.79292279213897],[509002.3055631575,6651216.565777306,98.21636581217152],[509005.1669001078,6651213.247057126,98.29245394513896],[509005.0142488905,6651214.024193152,97.96003754913897],[509005.0983405709,6651213.596088643,98.44894523713897],[509001.12669275975,6651222.532237856,93.64890212517152],[509004.93207983236,6651214.442509731,98.08219067113896],[509001.1275738315,6651222.527778604,93.85272340917152],[509005.028806903,6651213.95007939,98.57656799613896],[509001.0085308428,6651223.13027511,93.64890212417153],[509001.1348897383,6651222.490751574,94.26930269717153],[509004.85029303154,6651214.858880268,98.16086536413896],[509004.958928595,6651214.305824672,98.67566349013896],[509001.9734027315,6651218.246896861,98.21636581217152],[509001.1501396884,6651222.413569022,94.69362981717151],[509001.0125936525,6651223.1097125495,94.11449281117152],[509004.7699995841,6651215.267648254,98.19860822313896],[509001.8926548681,6651218.655575323,98.17862295317153],[509004.8662368872,6651214.777711282,98.76482814213897],[509001.17381730245,6651222.2937326515,95.11994016817152],[509001.8104051995,6651219.071854672,98.09994826017152],[509001.02529859956,6651223.045410684,94.59176376317151],[509001.96813547803,6651218.273555313,98.82536097217152],[509003.2604606253,6651222.952599125,91.80234087613896],[509001.20621007856,6651222.129787385,95.54174902717152],[509003.2604606253,6651222.952599125,91.93234087613897],[509004.7752376467,6651215.2409816645,98.80760338313898],[509001.72777111037,6651219.4900796395,97.97779513817152],[509001.2473570583,6651221.921535629,95.95209857017151],[509001.87662123254,6651218.736724238,98.78258573117154],[509001.04730096296,6651222.934053037,95.07466478317153],[509001.64600957034,6651219.903888489,97.81068038117152],[509001.2970202626,6651221.670181833,96.34387826417154],[509003.1429632246,6651223.550769676,91.80234087613896],[509001.5664692527,6651220.30645536,97.59840257217152],[509001.33955146,6651221.454924319,96.62136012417152],[509001.0701837696,6651222.818239321,95.43637076817151],[509001.49052843155,6651220.690804577,97.34218944917151],[509001.3862599369,6651221.218524894,96.88180079717152],[509001.43674259057,6651220.963023727,97.12277044317152],[509001.7834049415,6651219.2085075015,98.69342107917153],[509001.09865047096,6651222.6741645755,95.79412861417151],[509001.71313116123,6651219.564174876,98.59432558517153],[509001.1327044672,6651222.501811597,96.14458482917154],[509001.6432039715,6651219.918088094,98.46670282617151],[509004.43269636977,6651216.984833899,98.19860822313896],[509001.17224931536,6651222.301668496,96.48432985617153],[509001.57425642596,6651220.267043172,98.31021153417151],[509001.2170853785,6651222.074745672,96.80999696617151],[509001.5069442019,6651220.607721613,98.12500263217153],[509001.266910918,6651221.822570269,97.11836577417152],[509001.4419276231,6651220.936781408,97.91175029717152],[509001.32132785744,6651221.547157025,97.40646412517152],[509001.3798520653,6651221.250956206,97.67166185017152],[509003.2604601744,6651222.952601421,93.63114453613898],[509003.2613362879,6651222.948141192,93.83496582013896],[509003.1429632246,6651223.550769676,93.63114453513896],[509003.2686110237,6651222.911106051,94.25154510813896],[509004.1024052073,6651218.666321708,98.19860822313896],[509003.2837751533,6651222.833906592,94.67587222813896],[509003.1470031704,6651223.530202612,94.09673522213897],[509004.02211176,6651219.075089693,98.16086536413896],[509003.30731951946,6651222.714043971,95.10218257913895],[509003.9403249591,6651219.49146023,98.08219067113896],[509004.0971675958,6651218.692985999,98.80760338313898],[509003.1596366192,6651223.465886662,94.57400617413896],[509003.33953000215,6651222.550062792,95.52399143813896],[509003.8581559009,6651219.90977681,97.96003754913897],[509003.3804454234,6651222.341765418,95.93434098113897],[509004.0061683553,6651219.156256384,98.76482814213897],[509003.1815151624,6651223.3545046225,95.05690719413896],[509003.77685448155,6651220.323676307,97.79292279213897],[509003.42982914345,6651222.090356562,96.32612067513897],[509003.6977617845,6651220.726331361,97.58064498313898],[509003.4721209926,6651221.875051895,96.60360253513898],[509003.20426919387,6651223.238665534,95.41861317913896],[509003.6222483272,6651221.11076477,97.32443186013896],[509003.5185666132,6651221.638600685,96.86404320813898],[509003.56876517105,6651221.383043551,97.10501285413896],[509003.9134766474,6651219.628142994,98.67566349013896],[509003.2325756962,6651223.094559231,95.77637102513896],[509003.8435983395,6651219.983888276,98.57656799613896],[509003.2664380505,6651222.922168497,96.12682724013897],[509003.77406467154,6651220.337879022,98.44894523713897],[509003.30576035636,6651222.721981554,96.46657226713896],[509003.7055051346,6651220.686910538,98.29245394513896],[509003.3503441003,6651222.495009021,96.79223937713896],[509003.6385717163,6651221.027663606,98.10724504313896],[509003.399889242,6651222.24277838,97.10060818513897],[509003.57392102433,6651221.356795484,97.89399270813898],[509003.4539999451,6651221.967304803,97.38870653613895],[509003.5121948025,6651221.671039101,97.65390426113898],[509020.666724205,6651213.256626926,91.66691646628368],[509020.55391256086,6651213.855698859,91.66691646628368],[509020.55391256086,6651213.855698859,91.7969164662837],[509020.666724205,6651213.256626926,93.49572012528368],[509020.662845371,6651213.277224983,93.96131081228368],[509020.55391256086,6651213.855698859,93.49572012528368],[509020.55049006024,6651213.873873615,93.90653543728368],[509020.65071573976,6651213.341637852,94.43858176428368],[509020.5397874445,6651213.930708499,94.32765686528369],[509020.6297097055,6651213.453187733,94.92148278428368],[509020.5212527083,6651214.029134865,94.7537460002837],[509020.60786309704,6651213.569201377,95.28318876928368],[509020.4945073317,6651214.171162796,95.17865250428369],[509020.58068544837,6651213.713524835,95.64094661528368],[509020.5481735133,6651213.886175345,95.9914028302837],[509020.4593910742,6651214.35764323,95.59561920628369],[509020.51041936764,6651214.086663947,96.3311478572837],[509020.41599652776,6651214.588084466,95.99756812328368],[509020.4676136083,6651214.313978504,96.65681496728368],[509020.364687826,6651214.860552821,96.3774489252837],[509020.4200443099,6651214.5665892325,96.96518377528369],[509020.3213846017,6651215.090509103,96.64385524028368],[509025.1467760023,6651214.094829679,91.62279150477926],[509020.3680915234,6651214.842477918,97.25328212628368],[509020.2743420132,6651215.340322805,96.8915649802837],[509025.03536972974,6651214.694164551,91.62279150477926],[509025.03536972974,6651214.694164551,91.75279150477925],[509020.31221745705,6651215.139190063,97.5184798512837],[509020.2065523964,6651215.70031097,97.18900745028368],[509020.2529528559,6651215.453907212,97.7585682982837],[509020.13405039016,6651216.08532368,97.44522057328368],[509020.1908804115,6651215.783535059,97.9718206332837],[509025.1467760023,6651214.094829679,93.45159516377925],[509020.058111883,6651216.488585494,97.65749838228368],[509020.1266162752,6651216.124801606,98.15702953528368],[509025.14294548956,6651214.115436777,93.91718585077925],[509025.03536972974,6651214.694164551,93.45159516377925],[509019.9800527366,6651216.903108694,97.82461313928368],[509020.06079086935,6651216.474359077,98.3135208272837],[509025.0319898655,6651214.712347284,93.86241047577924],[509025.1309669654,6651214.179877915,94.39445680277926],[509019.9011605525,6651217.322055635,97.94676626128368],[509019.9940301805,6651216.828883251,98.4411435862837],[509025.02142057946,6651214.769207114,94.28353190377925],[509025.11022261763,6651214.291476759,94.87735782277925],[509019.8226353814,6651217.7390536,98.02544095428368],[509019.9269385956,6651217.185164605,98.5402390802837],[509025.0031167431,6651214.86767668,94.70962103877925],[509025.08864816726,6651214.4075413225,95.23906380777925],[509019.74554400943,6651218.148437555,98.06318381328369],[509019.83794340165,6651217.657762299,98.62940373228369],[509024.9767045519,6651215.009766949,95.13452754277927],[509025.0618090891,6651214.551928124,95.59682165377924],[509018.296204951,6651225.844968856,91.66691646628368],[509019.75057317986,6651218.121730783,98.67217897328369],[509018.296204951,6651225.844968856,91.7969164662837],[509025.02970217733,6651214.724654413,95.94727786877925],[509024.9420257615,6651215.196329231,95.55149424477925],[509018.18339330686,6651226.444040789,91.66691646628368],[509024.99241836084,6651214.925231013,96.28702289577924],[509024.89917181066,6651215.426871612,95.95344316177925],[509019.4216923326,6651219.868210822,98.06318381328369],[509024.95014586195,6651215.152645342,96.61269000577924],[509024.84850229626,6651215.6994595565,96.33332396377925],[509018.29620451824,6651225.844971155,93.49572012628369],[509024.90316916676,6651215.405366943,96.92105881377925],[509018.29704569257,6651225.840504205,93.69954141028369],[509024.80573852983,6651215.929516769,96.59973027877926],[509018.18339330686,6651226.444040789,93.49572012528368],[509018.3040303144,6651225.803413256,94.11612069828368],[509024.8518635915,6651215.68137672,97.20915716477926],[509019.1045730695,6651221.55223246,98.06318381328369],[509024.75928198284,6651216.179440118,96.84744001877925],[509018.3185897037,6651225.7260974655,94.54044781828368],[509018.18727214093,6651226.423442733,93.96131081228368],[509019.0274816975,6651221.961616416,98.02544095428368],[509024.79668558645,6651215.978219096,97.47435488977925],[509018.34119512845,6651225.606054223,94.9667581692837],[509018.9489565264,6651222.378614381,97.94676626128368],[509019.0995443321,6651221.578936933,98.67217897328369],[509024.69233686756,6651216.539586286,97.14488248877925],[509018.1994017721,6651226.359029864,94.43858176428368],[509018.3721210681,6651225.441825942,95.38856702828369],[509018.87006434234,6651222.7975613205,97.82461313928368],[509019.01217411034,6651222.042905418,98.62940373228369],[509024.7381592849,6651216.29307438,97.71444333677925],[509018.41140479635,6651225.233214686,95.79891657128368],[509018.2204078064,6651226.247479983,94.92148278428368],[509018.7920051959,6651223.212084521,97.65749838228368],[509018.4588191103,6651224.981426982,96.19069626528369],[509018.71606668865,6651223.615346335,97.44522057328368],[509024.62073806825,6651216.924767983,97.40109561177925],[509018.4994243749,6651224.765797873,96.46817812528369],[509018.6435646825,6651224.000359045,97.18900745028368],[509018.2422544149,6651226.131466338,95.28318876928368],[509018.54401776,6651224.528990356,96.72861879828369],[509018.9231789163,6651222.51550311,98.5402390802837],[509018.5922144164,6651224.273048123,96.96958844428369],[509024.6768601193,6651216.622846902,97.92769567177925],[509018.2694320635,6651225.98714288,95.64094661528368],[509018.8560873314,6651222.871784465,98.4411435862837],[509018.7893266425,6651223.226308638,98.3135208272837],[509018.30194399855,6651225.814492373,95.9914028302837],[509024.54574557877,6651217.328206794,97.61337342077925],[509018.72350123676,6651223.57586611,98.15702953528368],[509018.3396981443,6651225.614003768,96.3311478572837],[509024.6133965651,6651216.964263236,98.11290457377926],[509018.65923710045,6651223.917132658,97.9718206332837],[509018.3825039037,6651225.386689211,96.65681496728368],[509018.597164656,6651224.246760503,97.7585682982837],[509018.43007320195,6651225.134078483,96.96518377528369],[509018.53790005494,6651224.561477653,97.5184798512837],[509018.4820259885,6651224.858189798,97.25328212628368],[509024.46865886834,6651217.742911933,97.78048817777925],[509024.54839119123,6651217.313974132,98.26939586577925],[509024.39074949804,6651218.162042755,97.90264129977925],[509024.48246218567,6651217.668653911,98.39701862477925],[509024.31320256856,6651218.579223745,97.98131599277926],[509024.41620640643,6651218.025091642,98.49611411877925],[509024.23707157624,6651218.988787385,98.01905885177926],[509024.32831988623,6651218.497896764,98.58527877077927],[509022.8057879224,6651226.688696793,91.62279150477926],[509024.2420380949,6651218.962068891,98.62805401177926],[509022.8057879224,6651226.688696793,91.75279150477925],[509022.6943816497,6651227.288031666,91.62279150477926],[509023.9172543405,6651220.7093154825,98.01905885177926],[509022.805787495,6651226.688699093,93.45159516477925],[509022.8066181902,6651226.684230181,93.65541644877926],[509022.6943816497,6651227.288031666,93.45159516377925],[509022.8135157998,6651226.647122953,94.07199573677924],[509023.6040856482,6651222.394076259,98.01905885177926],[509022.82789381297,6651226.569773227,94.49632285677924],[509022.69821216253,6651227.267424568,93.91718585077925],[509023.5279546559,6651222.803639899,97.98131599277926],[509022.8502176265,6651226.449677298,94.92263320777924],[509023.4504077264,6651223.220820889,97.90264129977925],[509023.5991195571,6651222.420792453,98.62805401177926],[509022.71019068663,6651227.202983428,94.39445680277926],[509034.8693510464,6651215.876523727,91.52147764848303],[509022.8807583006,6651226.285376933,95.34444206677927],[509023.3724983561,6651223.639951711,97.78048817777925],[509023.5128377658,6651222.88496458,98.58527877077927],[509022.91955264466,6651226.076674115,95.75479160977925],[509023.2954116456,6651224.054656851,97.61337342077925],[509022.7309350344,6651227.091384585,94.87735782277925],[509022.96637628623,6651225.824775898,96.14657130377927],[509023.2204191562,6651224.45809566,97.40109561177925],[509023.0064757034,6651225.609052147,96.42405316377925],[509023.1488203569,6651224.843277358,97.14488248877925],[509023.4249512456,6651223.357769702,98.49611411877925],[509022.7525094849,6651226.975320023,95.23906380777925],[509023.0505135583,6651225.372140692,96.68449383677925],[509034.76099470054,6651216.476417507,91.52147764848303],[509023.09810979606,6651225.1160861235,96.92546348277926],[509034.76099470054,6651216.476417507,91.65147764848305],[509023.35869546636,6651223.714207433,98.39701862477925],[509022.77934856294,6651226.83093322,95.59682165377924],[509023.2927664609,6651224.068887212,98.26939586577925],[509022.8114554747,6651226.658206931,95.94727786877925],[509023.22776108695,6651224.418598108,98.11290457377926],[509022.8487392913,6651226.457630331,96.28702289577924],[509023.1642975329,6651224.760014442,97.92769567177925],[509022.8910117901,6651226.230216002,96.61269000577924],[509023.10299836716,6651225.0897869645,97.71444333677925],[509022.93798848527,6651225.977494401,96.92105881377925],[509023.0444720656,6651225.4046422485,97.47435488977925],[509022.9892940606,6651225.701484624,97.20915716477926],[509034.8693510464,6651215.876523727,93.35028130748304],[509034.8656254,6651215.89715004,93.81587199448303],[509034.76099470054,6651216.476417507,93.35028130748304],[509034.7577073656,6651216.494617197,93.76109661948303],[509034.85397480737,6651215.961651274,94.29314294648303],[509034.74742743094,6651216.551530052,94.18221804748303],[509034.8337983696,6651216.073354189,94.77604396648304],[509034.7296246917,6651216.650091445,94.60830718248303],[509034.8128145547,6651216.189526988,95.13774995148303],[509034.70393557695,6651216.792314221,95.03321368648304],[509034.7867102397,6651216.33404844,95.49550779748303],[509034.7554823066,6651216.506935802,95.84596401248305],[509034.6702061745,6651216.979050481,95.45018038848303],[509034.7192191949,6651216.707699451,96.18570903948304],[509034.62852541974,6651217.209807852,95.85212930548303],[509034.678103974,6651216.935325854,96.51137614948303],[509034.57924306527,6651217.482650001,96.23201010748305],[509034.63241334184,6651217.1882831305,96.81974495748304],[509034.53765002603,6651217.712921752,96.49841642248303],[509034.58251233964,6651217.4645503005,97.10784330848304],[509034.49246530223,6651217.963078165,96.74612616248305],[509034.52884492173,6651217.761669496,97.37304103348303],[509034.4273529177,6651218.323560188,97.04356863248303],[509034.47192087234,6651218.076818396,97.61312948048304],[509034.35771425127,6651218.7091010865,97.29978175548302],[509034.4122998704,6651218.406898449,97.82638181548305],[509034.2847748025,6651219.112916124,97.51205956448302],[509034.3505737336,6651218.7486331705,98.01159071748303],[509034.20979846537,6651219.528007996,97.67917432148303],[509034.287347987,6651219.098670189,98.16808200948303],[509034.13402199006,6651219.947529678,97.80132744348303],[509034.2232238946,6651219.453680726,98.29570476848305],[509034.05859803315,6651220.3650997095,97.88000213648304],[509034.1587819745,6651219.810450851,98.39480026248305],[509033.98455125,6651220.775045289,97.91774499548303],[509034.0733014899,6651220.283696888,98.48396491448305],[509033.9893818021,6651220.748301878,98.52674015548304],[509032.5924513005,6651228.482135238,91.52147764848303],[509032.5924513005,6651228.482135238,91.65147764848305],[509032.4840949547,6651229.082029021,91.52147764848303],[509033.6734895281,6651222.497177863,97.91774499548303],[509032.59245088475,6651228.48213754,93.35028130848303],[509032.5932588384,6651228.477664462,93.55410259248303],[509032.4840949547,6651229.082029021,93.35028130748304],[509032.59996761486,6651228.44052263,93.97068188048304],[509033.3688943351,6651224.183509762,97.91774499548303],[509032.61395200656,6651228.363100773,94.39500900048303],[509032.48782060103,6651229.061402706,93.81587199448303],[509033.29484755197,6651224.59345534,97.88000213648304],[509032.6356646696,6651228.2428928455,94.82131935148304],[509033.3640641989,6651224.210250868,98.52674015548304],[509033.21942359506,6651225.011025371,97.80132744348303],[509032.49947119365,6651228.996901471,94.29314294648303],[509032.66536924336,6651228.078439265,95.24312821048304],[509033.14364711975,6651225.430547052,97.67917432148303],[509033.28014451114,6651224.674855858,98.48396491448305],[509032.7031015295,6651227.869541819,95.65347775348303],[509033.0686707826,6651225.845638924,97.51205956448302],[509032.5196476314,6651228.885198559,94.77604396648304],[509032.74864329817,6651227.617408697,96.04525744748305],[509032.99573133385,6651226.249453962,97.29978175548302],[509032.78764492896,6651227.401483771,96.32273930748303],[509032.9260926674,6651226.634994861,97.04356863248303],[509033.19466402655,6651225.148101895,98.39480026248305],[509032.8304771764,6651227.164351385,96.58317998048304],[509032.87677039014,6651226.908058032,96.82414962648303],[509032.5406314463,6651228.769025758,95.13774995148303],[509033.13022210647,6651225.504872022,98.29570476848305],[509032.5667357613,6651228.624504308,95.49550779748303],[509033.066098014,6651225.859882557,98.16808200948303],[509032.5979636944,6651228.451616945,95.84596401248305],[509033.0028722674,6651226.209919576,98.01159071748303],[509032.63422680617,6651228.250853297,96.18570903948304],[509032.9411461307,6651226.551654297,97.82638181548305],[509032.67534202704,6651228.0232268935,96.51137614948303],[509032.8815251288,6651226.88173435,97.61312948048304],[509032.7210326592,6651227.7702696165,96.81974495748304],[509032.8246010793,6651227.19688325,97.37304103348303],[509032.7709336614,6651227.494002446,97.10784330848304],[510538.3475552979,6651106.192133014,67.73428539412009],[510538.3807739694,6651106.800828477,67.73428539412009],[510538.3807739694,6651106.800828477,67.86428539412009],[510538.3475552979,6651106.192133014,69.5630890531201],[510538.3486974647,6651106.213061959,70.02867974012008],[510538.3807739694,6651106.800828477,69.5630890531201],[510538.3522691726,6651106.278509561,70.5059506921201],[510538.3817817637,6651106.819295193,69.97390436512009],[510538.3849332706,6651106.877043078,70.39502579312008],[510538.3584546382,6651106.391851387,70.9888517121201],[510538.36488762056,6651106.509728681,71.35055769712011],[510538.3903910344,6651106.977050571,70.8211149281201],[510541.804904192,6651106.006721421,67.77395593323926],[510538.37289038824,6651106.65637056,71.70831554312011],[510538.3982665147,6651107.121360049,71.24602143212009],[510541.83697537443,6651106.6154784225,67.77395593323926],[510538.38246389723,6651106.831794538,72.05877175812009],[510541.83697537443,6651106.6154784225,67.90395593323927],[510538.4086068961,6651107.310836116,71.66298813412008],[510538.3935810348,6651107.035503805,72.3985167851201],[510538.42138491385,6651107.544979176,72.0649370511201],[510541.804904192,6651106.006721421,69.60275959223927],[510538.40618567745,6651107.266469957,72.72418389512009],[510541.80600690434,6651106.0276524825,70.06835027923925],[510538.4364933446,6651107.82182448,72.44481785312009],[510538.4201929983,6651107.52313864,73.0325527031201],[510541.83697537443,6651106.6154784225,69.60275959223927],[510541.8094552329,6651106.0931067,70.54562123123927],[510538.4492444714,6651108.055474795,72.71122416812008],[510541.837948356,6651106.6339470055,70.01357490423926],[510538.43549108715,6651107.80345922,73.32065105412009],[510538.4630966966,6651108.30930152,72.95893390812009],[510541.8409909988,6651106.691700729,70.43469633223926],[510541.81542703096,6651106.206459986,71.02852225123927],[510538.4519438414,6651108.104937769,73.58584877912008],[510541.82163779554,6651106.324349198,71.39022823623927],[510541.8462602324,6651106.791718332,70.86078546723928],[510545.0497702439,6651105.838649935,67.8111848015487],[510538.4830581202,6651108.675072559,73.2563763781201],[510538.4693949772,6651108.424710556,73.82593722612009],[510541.82936411974,6651106.471005901,71.74798608223927],[510541.85386366607,6651106.936042399,71.28569197123926],[510545.0807644602,6651106.447462719,67.8111848015487],[510538.5044071604,6651109.066270138,73.51258950112009],[510545.0807644602,6651106.447462719,67.94118480154869],[510538.48767291434,6651108.759633563,74.0391895611201],[510541.83860692626,6651106.646447614,72.09844229723927],[510541.86384685454,6651107.125537623,71.70265867323926],[510538.52676811744,6651109.476009977,73.72486731012009],[510538.50659622013,6651109.10638224,74.2243984631201],[510541.849340039,6651106.850177474,72.43818732423927],[510545.0497702439,6651105.838649935,69.6399884605487],[510541.87618347484,6651107.359704352,72.10460759023925],[510538.5259792594,6651109.461555026,74.3808897551201],[510541.8615092733,6651107.081166978,72.76385443423926],[510538.5497535208,6651109.897192105,73.8919820671201],[510545.05083592667,6651105.859582913,70.10557914754868],[510545.0807644602,6651106.447462719,69.6399884605487],[510541.8907700076,6651107.636577646,72.48448839223927],[510538.54563770344,6651109.821774298,74.50851251412008],[510541.8750327323,6651107.33786161,73.07222324223926],[510538.57298422157,6651110.322869036,74.0141351891201],[510545.0541684587,6651105.925043128,70.58285009954871],[510545.0817047684,6651106.465932993,70.05080377254869],[510541.9030806659,6651107.870251583,72.75089470723927],[510538.5653935836,6651110.18377898,74.6076080081201],[510538.59610685124,6651110.746565684,74.0928098821201],[510541.8898023716,6651107.61821053,73.36032159323926],[510545.08464523783,6651106.523692008,70.4719252005487],[510545.0599397207,6651106.038406801,71.0657511195487],[510541.91645438684,6651108.124103969,72.99860444723927],[510538.5915992306,6651110.663968514,74.69677266012009],[510538.61880728236,6651111.16252601,74.13055274112008],[510545.0659419248,6651106.156306815,71.4274571045487],[510545.08973752795,6651106.623718777,70.8980143355487],[510541.9056867903,6651107.919719556,73.62551931823926],[510548.45917139295,6651105.66825618,67.85029779767426],[510541.9357262731,6651108.4899119865,73.29604691723927],[510545.0734087951,6651106.302976958,71.78521495054869],[510538.6173263859,6651111.135390218,74.7395479011201],[510545.09708563454,6651106.768056069,71.32292083954869],[510541.9225351029,6651108.239524672,73.86560776523926],[510548.48903403396,6651106.277125518,67.85029779767426],[510545.08234122366,6651106.478434748,72.13567116554869],[510541.95633784286,6651108.881149115,73.55226004023926],[510548.48903403396,6651106.277125518,67.98029779767425],[510545.1067335826,6651106.957568655,71.7398875415487],[510541.9401816561,6651108.574481541,74.07886010023927],[510545.09271391307,6651106.682183276,72.47541619254869],[510541.9779263743,6651109.290930377,73.76453784923926],[510541.95845128474,6651108.921265272,74.26406900223927],[510545.11865593295,6651107.191756844,72.14183645854868],[510538.71416909155,6651112.909925829,74.13055274112008],[510548.45917139295,6651105.66825618,69.67910145667426],[510545.10447449837,6651106.913193947,72.80108330254869],[510541.9771647662,6651109.276473965,74.42056029423928],[510542.00011778146,6651109.712155086,73.93165260623927],[510548.4601981684,6651105.689191103,70.14469214367426],[510545.1327526427,6651107.468655508,72.52171726054868],[510548.48903403396,6651106.277125518,69.67910145667426],[510545.117543833,6651107.169912099,73.10945211054869],[510541.99614413886,6651109.636729655,74.54818305323927],[510539.0455816504,6651118.982694897,67.73428539412009],[510548.46340903227,6651105.754657399,70.62196309567426],[510542.0225460126,6651110.137875052,74.05380572823927],[510539.0455816504,6651118.982694897,67.86428539412009],[510545.14464990306,6651107.702350857,72.78812357554871],[510548.4899400123,6651106.295597508,70.08991676867427],[510545.1318175005,6651107.450286709,73.3975504615487],[510542.0152175819,6651109.9987709345,74.64727854723927],[510542.0448699058,6651110.561614534,74.13248042123926],[510545.15757452766,6651107.956226505,73.03583331554869],[510548.4927731274,6651106.353361887,70.51103819667425],[510548.4689695899,6651105.868031602,71.10486411567426],[510539.0788003219,6651119.59139036,67.73428539412009],[510545.1471685124,6651107.751823364,73.66274818654868],[510538.8075484649,6651114.6209997,74.13055274112008],[510542.04051799414,6651110.4790090155,74.73644319923926],[510548.4747526581,6651105.985942568,71.46657010067428],[510542.06678618473,6651110.977616914,74.17022328023926],[510548.49767950195,6651106.453397949,70.93712733167426],[510545.17619925446,6651108.322068042,73.3332757855487],[510538.83024889615,6651115.036960028,74.0928098821201],[510545.16345105023,6651108.071657784,73.90283663354869],[510538.8090292339,6651114.648133156,74.7395479011201],[510548.4819469187,6651106.132626335,71.82432794667427],[510542.06535644364,6651110.950478381,74.77921844023926],[510539.0455817779,6651118.982697234,69.56308905412008],[510548.50475933467,6651106.597748647,71.36203383567425],[510538.8533715257,6651115.4606566755,74.0141351891201],[510539.0453340844,6651118.978158525,69.76691033812008],[510545.19611867744,6651108.713341023,73.58948890854869],[510538.83475638926,6651115.119554861,74.69677266012009],[510548.490553231,6651106.308100423,72.17478416167425],[510545.1805050235,6651108.406645346,74.1160889685487],[510538.8766022266,6651115.886333606,73.8919820671201],[510539.0432773831,6651118.940471746,70.18348962612009],[510548.51405504346,6651106.787278838,71.77900053767425],[510539.0788003219,6651119.59139036,69.5630890531201],[510539.0389902054,6651118.861913948,70.6078167461201],[510538.8995876299,6651116.307515735,73.72486731012009],[510538.86096203624,6651115.599744395,74.6076080081201],[510545.2169822552,6651109.123159834,73.8017667175487],[510548.5005472215,6651106.511867878,72.51452918867426],[510545.1981611489,6651108.753460854,74.30129787054871],[510539.03233378095,6651118.739942323,71.03412709712009],[510539.07765815506,6651119.570461417,70.02867974012008],[510538.92194858694,6651116.717255572,73.51258950112009],[510538.8807179163,6651115.961749077,74.50851251412008],[510548.525542118,6651107.02148878,72.18094945467426],[510539.02322728635,6651118.573075869,71.45593595612009],[510538.9432976272,6651117.108453153,73.2563763781201],[510542.1588538637,6651112.725193391,74.17022328023926],[510538.95841829706,6651117.385522725,73.03695737212009],[510539.0116597458,6651118.361113467,71.8662854991201],[510539.07408644725,6651119.505013815,70.5059506921201],[510538.90037636046,6651116.321968349,74.3808897551201],[510538.97261035064,6651117.6455764305,72.79598772612009],[510538.99769806187,6651118.105281029,72.25806519312009],[510538.98574137996,6651117.88618804,72.5355470531201],[510548.5118784368,6651106.742900008,72.84019629867427],[510545.2162462223,6651109.108702098,74.45778916254869],[510545.23842846387,6651109.5444231415,73.9688814745487],[510538.9197593997,6651116.677141135,74.2243984631201],[510539.06790098164,6651119.391671988,70.9888517121201],[510548.5391241676,6651107.298413167,72.56083025667425],[510538.9386827055,6651117.023889812,74.0391895611201],[510539.0614679993,6651119.273794693,71.35055769712011],[510545.2345882582,6651109.468990799,74.58541192154868],[510538.95696064265,6651117.358812819,73.82593722612009],[510548.5244706198,6651106.999642007,73.14856510667427],[510539.05346523155,6651119.1271528145,71.70831554312011],[510545.2601035439,6651109.970182119,74.0910345965487],[510538.9744117784,6651117.678585607,73.58584877912008],[510539.0438917225,6651118.951728838,72.05877175812009],[510542.47881827434,6651118.798576403,67.77395593323926],[510538.9908645327,6651117.9800641555,73.32065105412009],[510539.032774585,6651118.7480195705,72.3985167851201],[510539.00616262155,6651118.260384735,73.0325527031201],[510539.0201699424,6651118.517053418,72.72418389512009],[510548.5505870679,6651107.532130225,72.82723657167426],[510542.47881827434,6651118.798576403,67.90395593323927],[510545.2530212054,6651109.831065253,74.6845074155487],[510548.5382231666,6651107.28004266,73.43666345767426],[510545.28167778964,6651110.393960429,74.1697092895487],[510548.5630398244,6651107.786029454,73.07494631167425],[510542.51088945684,6651119.407333405,67.77395593323926],[510545.27747201733,6651110.311347341,74.77367206754869],[510545.30285810895,6651110.810000929,74.2074521485487],[510548.55301372486,6651107.581607326,73.70186118267425],[510542.24900758715,6651114.436440249,74.17022328023926],[510548.58098457655,6651108.151904975,73.37238878167427],[510545.30147637933,6651110.7828599075,74.81644730854869],[510542.27092386613,6651114.852442629,74.13248042123926],[510548.5687017996,6651107.9014714565,73.94194962967426],[510542.25043720513,6651114.463576447,74.77921844023926],[510542.47881839745,6651118.798578739,69.60275959323926],[510542.2932477593,6651115.276182111,74.05380572823927],[510542.4785792602,6651118.794039574,69.80658087723926],[510548.6001767565,6651108.543214302,73.62860190467426],[510542.2752756546,6651114.935045811,74.73644319923926],[510548.5851331453,6651108.236490136,74.15520196467426],[510542.3156759904,6651115.7019020775,73.93165260623927],[510542.4765936046,6651118.756348984,70.22316016523926],[510542.51088945684,6651119.407333405,69.60275959223927],[510542.47245452093,6651118.677783244,70.64748728523927],[510542.33786739764,6651116.123126786,73.76453784923926],[510542.300576067,6651115.415283892,74.64727854723927],[510548.62027862103,6651108.953071182,73.84087971367425],[510548.602144659,6651108.58333786,74.34041086667426],[510542.4660280327,6651118.55579929,71.07379763623926],[510542.50978674454,6651119.386402345,70.06835027923925],[510542.359455929,6651116.532908048,73.55226004023926],[510542.3196495099,6651115.777325171,74.54818305323927],[510545.39183410944,6651112.557737542,74.2074521485487],[510542.45723610825,6651118.388915964,71.49560649523926],[510542.3800674989,6651116.924145179,73.29604691723927],[510542.3946658478,6651117.201242763,73.07662791123926],[510542.4460681509,6651118.176932132,71.90595603823928],[510542.50633841596,6651119.320948128,70.54562123123927],[510542.3386288826,6651116.137580863,74.42056029423928],[510542.40836765827,6651117.461322758,72.83565826523926],[510542.4325887524,6651117.921073833,72.29773573223926],[510542.42104509607,6651117.701958692,72.57521759223926],[510548.61956946005,6651108.938612102,74.49690215867426],[510548.64094184496,6651109.374373621,74.00799447067426],[510542.35734236403,6651116.492789555,74.26406900223927],[510542.5003666178,6651119.207594842,71.02852225123927],[510542.37561199267,6651116.8395732865,74.07886010023927],[510542.4941558532,6651119.089705629,71.39022823623927],[510548.6372418422,6651109.298934272,74.62452491767425],[510545.70105395577,6651118.631677083,67.8111848015487],[510542.393258546,6651117.174530156,73.86560776523926],[510542.48642952903,6651118.943048925,71.74798608223927],[510548.66182558425,6651109.800172147,74.13014759267426],[510545.70105395577,6651118.631677083,67.94118480154869],[510542.4101068586,6651117.494335271,73.62551931823926],[510542.4771867225,6651118.767607212,72.09844229723927],[510542.42599127715,6651117.795844297,73.36032159323926],[510542.46645360976,6651118.5638773525,72.43818732423927],[510542.44076091656,6651118.076193218,73.07222324223926],[510542.4542843756,6651118.332887848,72.76385443423926],[510548.6550018166,6651109.661042361,74.72362041167426],[510548.68261217064,6651110.223989824,74.20882228567426],[510545.73204817204,6651119.240489867,67.8111848015487],[510545.4789604259,6651114.269141209,74.2074521485487],[510548.6785599479,6651110.14136906,74.81278506367426],[510548.70301921276,6651110.64006897,74.24656514467425],[510545.5001407453,6651114.685181708,74.1697092895487],[510545.4803420366,6651114.296279894,74.81644730854869],[510558.6812516685,6651105.195443709,67.96754571538673],[510548.701687929,6651110.612925427,74.85556030467427],[510545.7010540747,6651118.631679418,69.63998846154868],[510545.521714991,6651115.1089600185,74.0910345965487],[510545.70082296786,6651118.627139836,69.84380974554868],[510545.5043463986,6651114.7677924605,74.77367206754869],[510545.69890399143,6651118.589445793,70.26038903354869],[510545.54339007096,6651115.534718996,73.9688814745487],[510558.707721616,6651105.804469973,67.96754571538673],[510545.73204817204,6651119.240489867,69.6399884605487],[510558.707721616,6651105.804469973,68.09754571538674],[510545.6949039004,6651118.510872854,70.68471615354869],[510545.5648362797,6651115.955982302,73.8017667175487],[510545.5287972104,6651115.248074547,74.6845074155487],[510545.6886932168,6651118.388877721,71.11102650454869],[510545.73098248924,6651119.219556888,70.10557914754868],[510545.58569985745,6651116.365801115,73.58948890854869],[510545.54723015777,6651115.610149001,74.58541192154868],[510545.6801965295,6651118.221979103,71.53283536354868],[510545.6056192805,6651116.757074094,73.3332757855487],[510548.78874676715,6651112.387967932,74.24656514467425],[510545.6197274097,6651117.03419707,73.1138567795487],[510545.6694035978,6651118.009975847,71.9431849065487],[510545.7276499573,6651119.154096671,70.58285009954871],[510545.56557219365,6651115.970437704,74.45778916254869],[510545.6329691065,6651117.294300898,72.87288713354869],[510545.65637684416,6651117.754094101,72.33496460054869],[510545.6452208295,6651117.534958883,72.61244646054868],[510558.6812516685,6651105.195443709,69.79634937438674],[510545.58365726704,6651116.325678945,74.30129787054871],[510545.7218786951,6651119.040732999,71.0657511195487],[510545.6013133924,6651116.672494453,74.1160889685487],[510545.7158764911,6651118.9228329845,71.4274571045487],[510558.682161792,6651105.216384027,70.26194006138672],[510545.6183673657,6651117.0074820155,73.90283663354869],[510545.7084096208,6651118.776162843,71.78521495054869],[510545.6346499035,6651117.327316436,73.66274818654868],[510549.0866772323,6651118.462471688,67.85029779767426],[510545.69947719225,6651118.600705054,72.13567116554869],[510558.707721616,6651105.804469973,69.79634937438674],[510545.65000091546,6651117.628853091,73.3975504615487],[510545.6891045028,6651118.396956524,72.47541619254869],[510549.0866772323,6651118.462471688,67.98029779767425],[510545.664274583,6651117.9092277,73.10945211054869],[510545.6773439175,6651118.165945854,72.80108330254869],[510558.6850078697,6651105.281867197,70.73921101338674],[510558.70852466614,6651105.822946724,70.20716468638673],[510549.11653987324,6651119.071341026,67.85029779767426],[510558.7110359112,6651105.880725991,70.62828611438673],[510558.68993669265,6651105.39527062,71.22211203338674],[510548.87269216817,6651114.099530574,74.24656514467425],[510558.69506274664,6651105.513211976,71.58381801838674],[510558.71538487263,6651105.980787834,71.05437524938675],[510548.89309921017,6651114.51560972,74.20882228567426],[510548.87402333727,6651114.126671779,74.85556030467427],[510549.08667734684,6651118.462474025,69.67910145767426],[510548.91388579656,6651114.939427396,74.13014759267426],[510549.0864546775,6651118.457934021,69.88292274167425],[510558.70143966755,6651105.6599335475,71.94157586438673],[510562.25216679554,6651105.043722797,68.00849746456501],[510558.721660366,6651106.125175738,71.47928175338673],[510548.89715131826,6651114.598228146,74.81278506367426],[510549.08460576157,6651118.420236477,70.29950202967426],[510548.93476953596,6651115.365225922,74.00799447067426],[510549.11653987324,6651119.071341026,69.67910145667426],[510558.70906821714,6651105.835452861,72.29203207938674],[510549.08075171075,6651118.341656239,70.72382914967427],[510548.9554327599,6651115.78652836,73.84087971367425],[510548.9207094496,6651115.078554845,74.72362041167426],[510558.7298999896,6651106.314754777,71.89624845538673],[510562.2774515616,6651105.652799416,68.00849746456501],[510562.2774515616,6651105.652799416,68.138497464565],[510549.1155130978,6651119.050406102,70.14469214367426],[510549.07476777444,6651118.219649774,71.15013950067426],[510548.9755346243,6651116.19638524,73.62860190467426],[510548.93846942397,6651115.4406629335,74.62452491767425],[510558.71792679076,6651106.039272834,72.63177710638674],[510549.06658129476,6651118.052735654,71.57194835967425],[510548.9947268044,6651116.587694567,73.37238878167427],[510549.0083198565,6651116.864843285,73.15296977567425],[510549.0561824048,6651117.840712703,71.98229790267426],[510549.112302234,6651118.984939807,70.62196309567426],[510548.95614180615,6651115.8009851035,74.49690215867426],[510549.021078109,6651117.124971275,72.91200012967427],[510549.043631248,6651117.584807188,72.37407759667425],[510558.740082018,6651106.549025084,72.29819737238674],[510549.032882531,6651117.365651615,72.65155945667426],[510548.9735666072,6651116.156259344,74.34041086667426],[510549.1067416763,6651118.871565604,71.10486411567426],[510558.7279706671,6651106.270364508,72.95744421638673],[510562.25216679554,6651105.043722797,69.83730112356503],[510548.99057812104,6651116.50310707,74.15520196467426],[510549.1009586081,6651118.753654637,71.46657010067428],[510549.00700946664,6651116.838125749,73.94194962967426],[510549.0937643476,6651118.606970871,71.82432794667427],[510558.7521210115,6651106.8260208415,72.67807817438674],[510549.02269754146,6651117.157989879,73.70186118267425],[510549.0851580352,6651118.431496782,72.17478416167425],[510549.0374880996,6651117.459554546,73.43666345767426],[510562.2530361687,6651105.064664846,70.302891810565],[510549.0751640447,6651118.227729328,72.51452918867426],[510558.7391322528,6651106.527172679,73.26581302438673],[510549.0512406464,6651117.739955198,73.14856510667427],[510549.0638328294,6651117.996697198,72.84019629867427],[510562.2774515616,6651105.652799416,69.83730112356503],[510558.7622816122,6651107.0597981345,72.94448448938672],[510562.25575481437,6651105.13015343,70.78016276256501],[510558.7513223732,6651106.8076456,73.55391137538673],[510562.2782186556,6651105.671277695,70.24811643556501],[510558.7733196115,6651107.3137628045,73.19219422938673],[510562.28061746055,6651105.7290617395,70.669237863565],[510562.2604629512,6651105.24356623,71.26306378256501],[510558.76443257666,6651107.109287989,73.81910910038673],[510558.78922566114,6651107.679732623,73.48963669938674],[510562.2653594882,6651105.361517337,71.62476976756501],[510562.284771699,6651105.829131857,71.09532699856501],[510558.7783383299,6651107.42923456,74.05919754738673],[510562.27145088505,6651105.50825104,71.98252761356501],[510562.29076620954,6651105.973531698,71.52023350256502],[510558.8062374183,6651108.071142804,73.74584982238673],[510558.792902911,6651107.764339584,74.27244988238674],[510562.2787378692,6651105.683784867,72.332983828565],[510562.2986369073,6651106.163126413,71.937200204565],[510558.82405551075,6651108.481105316,73.95812763138673],[510558.8079817474,6651108.111276703,74.45765878438674],[510562.28719980374,6651105.887621691,72.67272885556503],[510562.3083630394,6651106.397416089,72.33914912156501],[510558.8234269176,6651108.46664251,74.61415007638675],[510558.84237118665,6651108.902516339,74.12524238838674],[510562.29679396946,6651106.118732473,72.99839596556501],[510558.839091541,6651108.827057547,74.74177283538674],[510562.31986299163,6651106.67443475,72.719029923565],[510558.8608823251,6651109.328424607,74.24739551038674],[510562.3074557995,6651106.375561878,73.306764773565],[510558.85483380547,6651109.189258963,74.84086832938674],[510562.3295686555,6651106.908231372,72.98543623856501],[510558.8793073483,6651109.752351516,74.32607020338673],[510562.3191001122,6651106.65605799,73.59486312456501],[510562.3401124328,6651107.162217041,73.233145978565],[510558.87571549846,6651109.669709458,74.93003298138673],[510558.8973959472,6651110.168537899,74.36381306238673],[510562.33162331133,6651106.957725319,73.860060849565],[510568.6902991316,6651104.7877660515,68.0823226047824],[510558.89621591044,6651110.141387361,74.97280822238673],[510562.35530629515,6651107.528217118,73.53058844856501],[510562.34490644,6651107.277698344,74.10014929656501],[510568.71344709094,6651105.396927622,68.0823226047824],[510568.71344709094,6651105.396927622,68.2123226047824],[510562.3715563576,6651107.919659661,73.78680157156501],[510562.35881889774,6651107.612831075,74.31340163156503],[510558.97338399757,6651111.916887354,74.36381306238673],[510562.388576652,6651108.329656073,73.99907938056501],[510562.3732225851,6651107.959796879,74.49861053356501],[510568.6902991316,6651104.7877660515,69.9111262637824],[510568.69109503424,6651104.808711022,70.37671695078241],[510562.38797620387,6651108.31519207,74.65510182556501],[510562.4060722507,6651108.751101937,74.16619413756501],[510568.71344709094,6651105.396927622,69.9111262637824],[510559.23746659444,6651117.99295671,67.96754571538673],[510559.23746659444,6651117.99295671,68.09754571538674],[510568.6935839281,6651104.874208739,70.8539879027824],[510562.40293945,6651108.675636907,74.782724584565],[510568.714149358,6651105.415408478,70.32194157578242],[510562.4237545603,6651109.177045421,74.28834725956501],[510559.263936542,6651118.6019829735,67.96754571538673],[510562.41797686066,6651109.037868269,74.88182007856503],[510568.7163454409,6651105.473200583,70.7430630037824],[510568.69789418206,6651104.987637357,71.3368889227824],[510562.44135461026,6651109.601007381,74.36702195256501],[510559.0477923649,6651113.628891122,74.36381306238673],[510568.7023769143,6651105.105604916,71.69859490778242],[510568.72014860605,6651105.573284656,71.16915213878241],[510562.437923584,6651109.518358491,74.97098473056502],[510562.45863329916,6651110.017228177,74.404764811565],[510559.06588096364,6651114.045077505,74.32607020338673],[510559.0489722999,6651113.656039322,74.97280822238673],[510559.237466696,6651117.992959048,69.79634937538673],[510568.7079535294,6651105.252359086,72.0563527537824],[510568.7256365227,6651105.717704638,71.5940586427824],[510559.23726932413,6651117.988417874,70.00017065938673],[510559.0843059868,6651114.469004412,74.24739551038674],[510562.4575060982,6651109.990075394,75.01375997156501],[510559.06947271194,6651114.127717225,74.93003298138673],[510559.23563046346,6651117.950710612,70.41674994738673],[510559.10281712544,6651114.894912682,74.12524238838674],[510568.71462469315,6651105.427917394,72.4068089687824],[510559.263936542,6651118.6019829735,69.79634937438674],[510568.7328420705,6651105.907325796,72.0110253447824],[510559.2322142711,6651117.872110123,70.84107706738673],[510559.1211328013,6651115.316323703,73.95812763138673],[510559.09035440494,6651114.60816772,74.84086832938674],[510559.2630264184,6651118.581042654,70.26194006138672],[510559.22691016964,6651117.750072213,71.26738741838673],[510559.1389508937,6651115.726286217,73.74584982238673],[510568.72237151256,6651105.631782649,72.7465539957824],[510559.10609666933,6651114.970369136,74.74177283538674],[510559.2196537556,6651117.583115072,71.68919627738673],[510559.1559626509,6651116.117696397,73.48963669938674],[510568.74174625066,6651106.14164815,72.41297426178241],[510559.168011397,6651116.394916545,73.27021769338673],[510559.21043628315,6651117.371037477,72.09954582038675],[510559.2601803408,6651118.515559485,70.73921101338674],[510559.12176129286,6651115.330784173,74.61415007638675],[510559.1793201849,6651116.655111578,73.02924804738673],[510559.19931106275,6651117.115066006,72.49132551438674],[510559.18978350697,6651116.89585395,72.76880737438674],[510562.5312190145,6651111.765722188,74.404764811565],[510568.7311548786,6651105.862925665,73.07222110578242],[510559.13720646297,6651115.686149979,74.45765878438674],[510559.2552515178,6651118.402156062,71.22211203338674],[510559.1522852993,6651116.033087098,74.27244988238674],[510559.2501254637,6651118.284214707,71.58381801838674],[510568.7522743459,6651106.41870545,72.7928550637824],[510559.16684988054,6651116.368192124,74.05919754738673],[510559.2437485428,6651118.1374931345,71.94157586438673],[510568.7409156812,6651106.119790891,73.3805899137824],[510559.1807556337,6651116.688138693,73.81910910038673],[510559.2361199933,6651117.961973821,72.29203207938674],[510559.1938658371,6651116.989781082,73.55391137538673],[510559.2272614197,6651117.758153848,72.63177710638674],[510559.20605595765,6651117.270254004,73.26581302438673],[510559.21721754334,6651117.527062175,72.95744421638673],[510562.783477417,6651117.842293931,68.00849746456501],[510568.7611597876,6651106.65253468,73.0592613787824],[510562.783477417,6651117.842293931,68.138497464565],[510568.7515759371,6651106.400326126,73.6686882647824],[510568.77081251383,6651106.906555775,73.3069711187824],[510562.808762183,6651118.451370551,68.00849746456501],[510568.7630408052,6651106.7020355305,73.93388598978241],[510562.6022957765,6651113.47786751,74.404764811565],[510568.7847223483,6651107.2726069,73.60441358878242],[510562.6195744654,6651113.894088304,74.36702195256501],[510568.77520138124,6651107.022053183,74.17397443678242],[510575.56434793817,6651104.539443691,68.16113549753591],[510562.6034228804,6651113.505017955,75.01375997156501],[510562.783477514,6651117.842296268,69.837301124565],[510562.7832889794,6651117.837754719,70.04112240856502],[510562.63717451534,6651114.318050263,74.28834725956501],[510568.7995991237,6651107.66410404,73.86062671178242],[510568.7879381021,6651107.357232659,74.38722677178241],[510562.6230053946,6651113.976734857,74.97098473056502],[510562.78172349796,6651117.80004434,70.45770169656501],[510575.5852144108,6651105.148687679,68.16113549753591],[510562.654856825,6651114.743993747,74.16619413756501],[510575.5852144108,6651105.148687679,68.2911354975359],[510562.808762183,6651118.451370551,69.83730112356503],[510562.7784602643,6651117.721437353,70.88202881656501],[510562.6723524237,6651115.165439613,73.99907938056501],[510568.815181039,6651108.074157636,74.0729045207824],[510562.64295211795,6651114.457225078,74.88182007856503],[510568.80112453894,6651107.704246856,74.57243567378241],[510562.8078928099,6651118.4304285,70.302891810565],[510562.773393652,6651117.59938935,71.30833916756502],[510562.689372718,6651115.575436023,73.78680157156501],[510562.65798952867,6651114.819456441,74.782724584565],[510562.76646214095,6651117.432418406,71.73014802656502],[510562.70562278054,6651115.966878566,73.53058844856501],[510562.7171320486,6651116.244121635,73.311169442565],[510562.75765737717,6651117.220323276,72.14049756956501],[510562.80517416424,6651118.364939917,70.78016276256501],[510568.8146313345,6651108.0596916145,74.7289269657824],[510562.67295277474,6651115.179901279,74.65510182556501],[510562.72793449013,6651116.504338183,73.070199796565],[510568.83119809086,6651108.495662283,74.24001927778241],[510562.74703028414,6651116.964330641,72.53227726356502],[510562.737929321,6651116.745100459,72.80975912356502],[510575.56434793817,6651104.539443691,69.98993915653591],[510562.68770639354,6651115.535296467,74.49861053356501],[510562.8004660274,6651118.2515271185,71.26306378256501],[510562.7021100809,6651115.882262272,74.31340163156503],[510562.79556949035,6651118.133576009,71.62476976756501],[510568.828330042,6651108.420186726,74.8565497247824],[510575.56506539584,6651104.560391497,70.4555298435359],[510568.84738607466,6651108.921665175,74.36217239978242],[510562.7160225386,6651116.217395004,74.10014929656501],[510562.78947809356,6651117.986842307,71.98252761356501],[510575.5852144108,6651105.148687679,69.98993915653591],[510562.7293056672,6651116.5373680275,73.860060849565],[510562.7821911093,6651117.811308481,72.332983828565],[510562.7737291749,6651117.607471656,72.67272885556503],[510562.7418288664,6651116.839035358,73.59486312456501],[510562.76413500914,6651117.376360874,72.99839596556501],[510562.75347317907,6651117.11953147,73.306764773565],[510568.84209664643,6651108.782468611,74.95564521878241],[510575.56730898184,6651104.625898075,70.93280079553591],[510575.5858474617,6651105.167171037,70.40075446853591],[510568.8634987506,6651109.345686267,74.4408470927824],[510575.5878270964,6651105.22497096,70.8218758965359],[510575.57119441265,6651104.739342039,71.41570181553591],[510568.8603576792,6651109.263025849,75.0448098707824],[510568.8793172237,6651109.761965115,74.4785899517824],[510575.57523532223,6651104.8573255595,71.77740780053593],[510575.5912554177,6651105.325068575,71.24796503153591],[510568.87828528194,6651109.734808546,75.0875851117824],[510575.5802623003,6651105.004099584,72.13516564653592],[510575.5962024395,6651105.469508097,71.6728715355359],[510579.46126029454,6651104.410116288,68.20581012757597],[510575.5862759473,6651105.179681645,72.4856218615359],[510575.60269780125,6651105.65915491,72.0898382375359],[510568.94576874573,6651111.510703002,74.4785899517824],[510575.5932592322,6651105.383574483,72.82536688853591],[510579.4808333877,6651105.0194032,68.20581012757597],[510579.4808333877,6651105.0194032,68.33581012757597],[510575.6107243761,6651105.893508967,72.4917871545359],[510575.6011769008,6651105.614748772,73.15103399853591],[510569.1767088793,6651117.58812228,68.0823226047824],[510569.1767088793,6651117.58812228,68.2123226047824],[510575.6202148115,6651106.170603752,72.8716679565359],[510579.46126029454,6651104.410116288,70.03461378657599],[510575.60997566854,6651105.871648751,73.45940280653592],[510575.62822449487,6651106.40446462,73.13807427153591],[510569.19985683874,6651118.197283852,68.0823226047824],[510579.46193328174,6651104.431065568,70.50020447357596],[510575.6195852386,6651106.152221941,73.74750115753591],[510579.4808333877,6651105.0194032,70.03461378657599],[510569.01083883556,6651113.223087125,74.4785899517824],[510575.6369258386,6651106.65852008,73.3857840115359],[510579.46403780207,6651104.496576762,70.97747542557597],[510579.48142719985,6651105.037887859,70.44542909857597],[510569.0266573085,6651113.639365973,74.4408470927824],[510575.6299201175,6651106.453972166,74.0126988825359],[510569.0118706883,6651113.250241357,75.0875851117824],[510569.1767089682,6651117.588124618,69.91112626478241],[510575.6494647054,6651107.024620732,73.68322648153591],[510579.48328412964,6651105.095691853,70.86655052657596],[510579.4676823998,6651104.610028719,71.46037644557599],[510569.1765363666,6651117.583582436,70.1149475487824],[510569.04276998446,6651114.063387065,74.36217239978242],[510575.64088213467,6651106.774033116,74.2527873295359],[510569.02979829104,6651113.722024052,75.0448098707824],[510569.1751031835,6651117.545866797,70.5315268367824],[510569.05895796826,6651114.489389959,74.24001927778241],[510579.4714728392,6651104.728020551,71.82208243057597],[510579.4864999512,6651105.195796522,71.29263966157598],[510569.19985683874,6651118.197283852,69.9111262637824],[510575.6628752105,6651107.416170841,73.9394396045359],[510569.1721157246,6651117.467248845,70.95585395678242],[510569.07497502014,6651114.910894604,74.0729045207824],[510569.0480593238,6651114.202581291,74.95564521878241],[510575.6523635112,6651107.10925794,74.46603966453591],[510569.199060936,6651118.17633888,70.37671695078241],[510569.1674772898,6651117.34518382,71.3821643077824],[510579.476188227,6651104.874804918,72.17984027657597],[510569.09055693535,6651115.3209482,73.86062671178242],[510579.4911403387,6651105.340246219,71.71754616557598],[510569.06182592834,6651114.564863176,74.8565497247824],[510569.16113155836,6651117.178189588,71.8039731667824],[510569.1054337108,6651115.71244534,73.60441358878242],[510569.1530708821,6651116.966064875,72.21432270978241],[510569.11597033474,6651115.989727079,73.3849945827824],[510569.1965720421,6651118.110841163,70.8539879027824],[510575.6769213561,6651107.826279915,74.1517174135359],[510569.1258598657,6651116.249979919,73.14402493678242],[510569.07552463573,6651114.925358287,74.7289269657824],[510575.66425027914,6651107.456319088,74.65124856653591],[510569.14334188093,6651116.710036535,72.6061024037824],[510569.135010037,6651116.490775776,72.88358426378241],[510579.48182912637,6651105.050399349,72.53029649157597],[510569.0890314314,6651115.280803045,74.57243567378241],[510569.1922617883,6651117.997412547,71.3368889227824],[510579.49723309436,6651105.529906395,72.13451286757596],[510569.10221786815,6651115.627817243,74.38722677178241],[510569.1877790559,6651117.879444987,71.69859490778242],[510575.67642583116,6651107.811811938,74.80773985853591],[510575.69135975087,6651108.247841591,74.31883217053591],[510569.18220244086,6651117.732690817,72.0563527537824],[510569.114954589,6651115.9629967185,74.17397443678242],[510579.48837956204,6651105.254306552,72.87004151857599],[510569.1755312772,6651117.557132508,72.4068089687824],[510569.12711516506,6651116.283014371,73.93388598978241],[510569.1677844578,6651117.353267252,72.7465539957824],[510569.13858003315,6651116.584723776,73.6686882647824],[510569.1590010916,6651117.122124237,73.07222110578242],[510569.14924028906,6651116.86525901,73.3805899137824],[510579.5047621531,6651105.764276962,72.53646178457598],[510575.68877437984,6651108.172355822,74.9353626175359],[510575.7059522304,6651108.67390212,74.44098529253591],[510579.4958064648,6651105.485497128,73.19570862857597],[510575.70118413365,6651108.534686725,75.03445811153591],[510579.513664337,6651106.041391268,72.91634258657596],[510575.7204768243,6651109.097980581,74.51965998553591],[510579.5040598531,6651105.742415206,73.50407743657597],[510579.5211775512,6651106.275268613,73.18274890157598],[510575.7176453402,6651109.01530898,75.1236227635359],[510575.73473621235,6651109.51431575,74.5574028445359],[510579.5130737873,6651106.023008165,73.79217578757597],[510579.52933955414,6651106.529341973,73.43045864157597],[510585.5625478138,6651104.224263366,68.27574991362977],[510575.73380597995,6651109.487155505,75.16639800453592],[510579.5227680729,6651106.324779649,74.05737351257596],[510579.54110121663,6651106.8954684185,73.72790111157597],[510585.58009589853,6651104.833611962,68.27574991362977],[510585.58009589853,6651104.833611962,68.40574991362976],[510579.5330506246,6651106.644863147,74.29746195957597],[510579.55368049006,6651107.287046113,73.98411423457597],[510579.5438203439,6651106.980111591,74.51071429457599],[510575.7946382039,6651111.263290236,74.5574028445359],[510585.5625478138,6651104.224263366,70.10455357262977],[510579.56685600476,6651107.697184081,74.19639204357597],[510579.554970327,6651107.327197189,74.69592319657598],[510585.56315117446,6651104.24521477,70.57014425962976],[510576.0028166402,6651117.341531774,68.16113549753591],[510576.0028166402,6651117.341531774,68.2911354975359],[510585.58009589853,6651104.833611962,70.10455357262977],[510579.5663911942,6651107.682715084,74.85241448857597],[510579.5803994555,6651108.118775458,74.36350680057598],[510585.5650379637,6651104.310732596,71.04741521162978],[510585.58062827564,6651104.852098494,70.51536888462977],[510576.02368311293,6651117.950775762,68.16113549753591],[510579.5779743351,6651108.043284371,74.98003724757596],[510579.59408744023,6651108.544866005,74.48565992257598],[510585.5822930897,6651104.909908341,70.93649031262976],[510585.5683054958,6651104.424196037,71.53031623162977],[510575.8532949188,6651112.9759060405,74.5574028445359],[510579.5896148874,6651108.4056408005,75.07913274157599],[510579.6077117474,6651108.968974344,74.56433461557597],[510585.57170378097,6651104.542199816,71.89202221662977],[510585.58517620625,6651105.010023143,71.36257944762977],[510575.86755430675,6651113.39224121,74.51965998553591],[510576.00281672034,6651117.341534112,69.9899391575359],[510575.8542250711,6651113.003063948,75.16639800453592],[510588.92990477174,6651104.130380348,68.31382165648704],[510576.00266113045,6651117.336991314,70.1937604415359],[510579.6050557689,6651108.886296918,75.16829739357598],[510579.62108728697,6651109.385338846,74.60207747457596],[510575.88207890076,6651113.816319671,74.44098529253591],[510585.5759313205,6651104.688999041,72.24978006262978],[510585.589336505,6651105.154487466,71.78748595162976],[510575.87038571085,6651113.474910473,75.1236227635359],[510576.0013692033,6651117.299270572,70.61033972953591],[510575.89667138027,6651114.242380201,74.31883217053591],[510576.02368311293,6651117.950775762,69.98993915653591],[510579.6202147137,6651109.358176687,75.21107263457597],[510588.9463352356,6651104.739760105,68.31382165648704],[510585.58098861936,6651104.86461125,72.60023627762976],[510575.99867619155,6651117.220641984,71.03466684953591],[510575.9111097749,6651114.663941877,74.1517174135359],[510588.9463352356,6651104.739760105,68.44382165648703],[510575.8868469174,6651113.955532729,75.03445811153591],[510585.5947989115,6651105.344166841,72.20445265362977],[510576.02296565514,6651117.9298279565,70.4555298435359],[510575.9944949256,6651117.098560444,71.46097720053591],[510575.9251559206,6651115.074050951,73.9394396045359],[510575.8992566711,6651114.31786363,74.9353626175359],[510575.988774636,6651116.9315436175,71.8827860595359],[510575.93856642576,6651115.46560106,73.68322648153591],[510585.58686135476,6651105.068539097,72.93998130462977],[510575.9815084283,6651116.719390206,72.29313560253591],[510576.0207220692,6651117.864321377,70.93280079553591],[510575.9480645492,6651115.742920312,73.4638074755359],[510575.95697935775,6651116.003208364,73.2228378295359],[510575.9116052199,6651114.6784075145,74.80773985853591],[510575.9727383275,6651116.463327226,72.6849152965359],[510575.9652276787,6651116.244036801,72.96239715653591],[510585.601549023,6651105.578561137,72.60640157062977],[510576.0168366384,6651117.750877414,71.41570181553591],[510575.92378077185,6651115.033900364,74.65124856653591],[510588.92990477174,6651104.130380348,70.14262531548704],[510585.5935198793,6651105.299753079,73.26564841462977],[510576.0127957288,6651117.632893895,71.77740780053593],[510575.93566753983,6651115.380961512,74.46603966453591],[510576.0077687507,6651117.486119869,72.13516564653592],[510579.67727633624,6651111.134436552,74.60207747457596],[510575.94714891637,6651115.716186337,74.2527873295359],[510585.60953019786,6651105.855703498,72.98628237262976],[510576.0017551037,6651117.310537808,72.4856218615359],[510588.93046970497,6651104.151332822,70.60821600248704],[510575.95811093354,6651116.036247287,74.0126988825359],[510575.99477181886,6651117.106644969,72.82536688853591],[510575.96844581235,6651116.337997512,73.74750115753591],[510575.9868541503,6651116.875470681,73.15103399853591],[510575.97805538244,6651116.618570702,73.45940280653592],[510585.6009193821,6651105.556697167,73.57401722262978],[510588.9463352356,6651104.739760105,70.14262531548704],[510585.61626610404,6651106.089604521,73.25268868762976],[510588.93223632633,6651104.216853999,71.08548695448704],[510588.9468337061,6651104.758247582,70.55344062748705],[510579.87255111965,6651117.213106325,68.20581012757597],[510579.87255111965,6651117.213106325,68.33581012757597],[510585.6090007456,6651105.837318534,73.86211557362977],[510585.623583676,6651106.343703603,73.50039842762976],[510588.94839248975,6651104.816060384,70.97456205548703],[510588.9352957525,6651104.330323244,71.56838797448704],[510579.89212421275,6651117.822393238,68.20581012757597],[510585.6176920723,6651106.139120569,74.12731329862976],[510588.9384776041,6651104.448333057,71.93009395948705],[510588.95109198336,6651104.916180306,71.40065119048704],[510585.6341284912,6651106.709867116,73.79784089762977],[510579.7322972956,6651112.847173017,74.60207747457596],[510585.6269108037,6651106.459236474,74.36740174562976],[510588.94243589556,6651104.595139789,72.28785180548705],[510592.45276433567,6651104.0387768755,68.35252413432214],[510588.9549873166,6651105.060652016,71.82555769448703],[510579.7456728351,6651113.263537521,74.56433461557597],[510579.8725511947,6651117.213108663,70.03461378757596],[510585.64540632843,6651107.101484454,74.05405402062976],[510579.73316979373,6651112.874332837,75.21107263457597],[510585.6365663009,6651106.794518856,74.58065408062977],[510579.8724052489,6651117.208565545,70.23843507157598],[510588.9471710999,6651104.770760979,72.63830802048703],[510579.7592971423,6651113.687645858,74.48565992257598],[510588.96010182763,6651105.25034109,72.24252439648703],[510592.46802556765,6651104.648187035,68.35252413432214],[510579.7483287385,6651113.346212606,75.16829739357598],[510579.8711934001,6651117.1708421465,70.65501435957597],[510592.46802556765,6651104.648187035,68.48252413432213],[510579.772985127,6651114.113736405,74.36350680057598],[510585.65721872036,6651107.511663944,74.26633182962978],[510579.89212421275,6651117.822393238,70.03461378657599],[510585.6465627204,6651107.141639595,74.76586298262978],[510588.95266980643,6651104.974699252,72.97805304748704],[510579.8686673109,6651117.092208018,71.07934147957597],[510579.78652857774,6651114.535327782,74.19639204357597],[510579.76376962,6651113.826868724,75.07913274157599],[510588.96642203105,6651105.484747373,72.64447331348704],[510579.8914512257,6651117.801443957,70.50020447357596],[510579.86474521505,6651116.970117877,71.50565183057599],[510579.79970409244,6651114.94546575,73.98411423457597],[510585.65680199856,6651107.497193484,74.92235427462977],[510579.7754101722,6651114.189225154,74.98003724757596],[510585.66936098225,6651107.933298003,74.43344658662977],[510579.8593794896,6651116.803089285,71.92746068957598],[510588.9589042558,6651105.205925057,73.30372015748704],[510579.8122833659,6651115.337043445,73.72790111157597],[510592.45276433567,6651104.0387768755,70.18132779332214],[510579.8893467053,6651117.735932763,70.97747542557597],[510579.8525636678,6651116.590920925,72.33781023257598],[510579.82119276136,6651115.614382235,73.50848210557596],[510579.82955499773,6651115.874688626,73.26751245957597],[510579.84433716966,6651116.334839905,72.72958992657598],[510579.78699331323,6651114.549794439,74.85241448857597],[510579.8372920579,6651116.115534031,73.00707178657598],[510588.9738948923,6651105.761903906,73.02435411548703],[510585.66718676186,6651107.857799273,75.04997703362976],[510579.88570210757,6651117.622480806,71.46037644557599],[510579.7984141804,6651114.905312335,74.69592319657598],[510585.6816328247,6651108.359431689,74.55559970862977],[510588.96583249135,6651105.462882286,73.61208896548705],[510592.4532890668,6651104.059730395,70.64691848032213],[510579.8819116681,6651117.504488974,71.82208243057597],[510579.8095641635,6651115.252397935,74.51071429457599],[510592.46802556765,6651104.648187035,70.18132779332214],[510579.8771962804,6651117.357704608,72.17984027657597],[510579.82033388276,6651115.587646376,74.29746195957597],[510588.9802017951,6651105.995816889,73.29076043048704],[510585.67762299674,6651108.220192387,75.14907252762977],[510579.87155538093,6651117.182110176,72.53029649157597],[510579.8306164344,6651115.907729876,74.05737351257596],[510579.8650049454,6651116.978202973,72.87004151857599],[510579.8403107201,6651116.209501361,73.79217578757597],[510585.69384757767,6651108.783582963,74.63427440162977],[510592.45492997114,6651104.1252548415,71.12418943232214],[510579.85757804255,6651116.747012397,73.19570862857597],[510579.8493246542,6651116.490094319,73.50407743657597],[510588.9733991605,6651105.743518001,73.90018731648703],[510592.46848856576,6651104.6666754335,70.59214310532214],[510588.98705331795,6651106.249928965,73.53847017048703],[510585.6914663834,6651108.7008971665,75.23823717962976],[510585.7058393002,6651109.199989618,74.67201726062976],[510592.46993642254,6651104.724491121,71.01326453332213],[510592.4577716811,6651104.238729747,71.60709045232214],[510588.9815369448,6651106.04533547,74.16538504148703],[510588.9969265438,6651106.616111202,73.83591264048705],[510585.70505700225,6651109.17282471,75.28101242062978],[510592.4607271044,6651104.356745446,71.96879643732214],[510592.47244381363,6651104.824616039,71.43935366832216],[510588.99016854394,6651106.365467743,74.40547348848703],[510592.4644037142,6651104.503559503,72.32655428332214],[510592.4760619455,6651104.969094955,71.86426017232213],[510589.00748610625,6651107.007748566,74.09212576348703],[510588.99920909177,6651106.700767272,74.61872582348704],[510592.4688019497,6651104.679189454,72.67701049832213],[510592.48081249546,6651105.158793495,72.28122687432213],[510589.0185461783,6651107.417949031,74.30440357248703],[510589.0085688487,6651107.047905761,74.80393472548704],[510585.7562150989,6651110.949264403,74.67201726062976],[510596.67553794186,6651103.937886111,68.39739721245486],[510592.4739093549,6651104.883137903,73.01675552532214],[510592.48668293766,6651105.393211472,72.68317579132213],[510589.01815599704,6651107.403477829,74.96042601748704],[510589.029915111,6651107.83960465,74.47151832948704],[510596.6893976416,6651104.5473297555,68.39739721245486],[510585.93128699105,6651117.028549582,68.27574991362977],[510592.47970014566,6651105.114375245,73.34242263532214],[510596.6893976416,6651104.5473297555,68.52739721245487],[510585.93128699105,6651117.028549582,68.40574991362976],[510589.02787936473,6651107.764102059,75.08804877648703],[510589.0414053715,6651108.265760126,74.59367145148704],[510592.4936240119,6651105.670381833,73.06305659332213],[510592.4861353511,6651105.371345293,73.65079144332213],[510585.9488350758,6651117.637898179,68.27574991362977],[510589.03765092575,6651108.126513705,75.18714427048704],[510592.4994821,6651105.904306487,73.32946290832214],[510589.05284217844,6651108.6899330905,74.67234614448704],[510596.67553794186,6651103.937886111,70.22620087145486],[510585.80554365675,6651112.662174267,74.67201726062976],[510592.49316355755,6651105.65199501,73.93888979432214],[510589.0506126402,6651108.607243066,75.27630892248703],[510589.06407015957,6651109.106361039,74.71008900348703],[510592.5058460518,6651106.158431242,73.57717264832213],[510596.67601448385,6651103.958840781,70.69179155845485],[510585.81753537926,6651113.078580921,74.63427440162977],[510596.6893976416,6651104.5473297555,70.22620087145486],[510585.9312870584,6651117.02855192,70.10455357362976],[510592.50072223734,6651105.953827537,74.20408751932213],[510585.80632588733,6651112.689336835,75.28101242062978],[510585.9311562119,6651117.024008343,70.30837485762976],[510589.06333768554,6651109.079194741,75.31908416348705],[510596.6775046939,6651104.024368827,71.16906251045486],[510585.8297501322,6651113.502732197,74.55559970862977],[510596.68981811975,6651104.56581917,70.63701618345486],[510592.51501667494,6651106.524631746,73.87461511832214],[510585.8199165061,6651113.161264378,75.23823717962976],[510585.9300697396,6651116.986281125,70.72495414562977],[510592.50873959076,6651106.273975783,74.44417596632213],[510585.8420219748,6651113.928865881,74.43344658662977],[510585.9488350758,6651117.637898179,70.10455357262977],[510596.6911330109,6651104.623638035,71.05813761145485],[510596.6800854321,6651104.137849968,71.65196353045486],[510585.92780499643,6651116.907639035,71.14928126562977],[510585.8541642366,6651114.350499939,74.26633182962978],[510585.8337598928,6651113.641969157,75.14907252762977],[510592.52482479316,6651106.91628865,74.13082824132213],[510585.9482317151,6651117.616946777,70.57014425962976],[510585.92428867583,6651116.785536534,71.57559161662977],[510592.51713679114,6651106.609292039,74.65742830132216],[510585.8659766286,6651114.76067943,74.05405402062976],[510585.8441961277,6651114.004362272,75.04997703362976],[510596.68276944075,6651104.255872153,72.01366951545486],[510596.6934101329,6651104.723768453,71.48422674645488],[510585.9194780818,6651116.61849103,71.99740047562976],[510585.8772544657,6651115.152296768,73.79784089762977],[510585.9463449259,6651117.55142895,71.04741521162978],[510585.9133674166,6651116.406301191,72.40775001862977],[510585.88524210587,6651115.429663638,73.57842189162976],[510585.89273919555,6651115.689996381,73.33745224562976],[510585.90599202196,6651116.150194245,72.79952971262976],[510585.8545808911,6651114.364968063,74.92235427462977],[510585.899675789,6651115.930866169,73.07701157262977],[510589.11123757163,6651110.855725275,74.71008900348703],[510592.53509780334,6651107.326509581,74.34310605032213],[510592.525830485,6651106.956447848,74.84263720332214],[510585.94307739375,6651117.437965508,71.53031623162977],[510596.68610840506,6651104.4026942765,72.37142736145486],[510585.86482016917,6651114.720521951,74.76586298262978],[510596.6966959895,6651104.868255309,71.90913325045486],[510585.93967910856,6651117.319961729,71.89202221662977],[510585.8748165887,6651115.067642689,74.58065408062977],[510585.9354515691,6651117.173162503,72.24978006262978],[510585.88447208586,6651115.402925071,74.36740174562976],[510592.5347353884,6651107.312037658,74.99912849532215],[510592.54565769504,6651107.748186238,74.51022080732214],[510585.93039427034,6651116.997550295,72.60023627762976],[510596.6901027237,6651104.578333879,72.72188357645487],[510585.8936908173,6651115.723040977,74.12731329862976],[510589.2751593013,6651116.935321324,68.31382165648704],[510585.92452153476,6651116.793622448,72.93998130462977],[510585.902382144,6651116.024843013,73.86211557362977],[510585.91786301025,6651116.562408468,73.26564841462977],[510585.9104635074,6651116.305464378,73.57401722262978],[510589.2751593013,6651116.935321324,68.44382165648703],[510596.7010102675,6651105.057964272,72.32609995245485],[510592.5437668175,6651107.67267988,75.12675125432214],[510596.6947410846,6651104.782293535,73.06162860345486],[510592.5563302806,6651108.174362975,74.63237392932214],[510589.2915897653,6651117.54470108,68.31382165648704],[510596.706341591,6651105.292395129,72.72804886945485],[510592.55284301034,6651108.0351096075,75.22584674832214],[510596.70000007167,6651105.013543581,73.38729571345486],[510592.5669532165,6651108.598557102,74.71104862232214],[510589.1574244405,6651112.56872273,74.71008900348703],[510596.71264522395,6651105.56958072,73.10792967145487],[510592.5648823376,6651108.515862952,75.31501140032215],[510589.1686524216,6651112.985150678,74.67234614448704],[510592.577382187,6651109.015005826,74.74879148132213],[510596.70584429265,6651105.27052775,73.69566452145486],[510589.27515936433,6651116.935323662,70.14262531648704],[510589.1581568515,6651112.595886688,75.31908416348705],[510589.2750368514,6651116.930779853,70.34644660048703],[510596.71796532796,6651105.803518227,73.37433598645487],[510589.18008922855,6651113.409323642,74.59367145148704],[510592.57670183765,6651108.987838173,75.35778664132214],[510596.712227056,6651105.551192887,73.98376287245486],[510589.1708818968,6651113.067838362,75.27630892248703],[510589.27401957544,6651116.893050705,70.76302588848704],[510589.19157948904,6651113.835479118,74.47151832948704],[510589.2915897653,6651117.54470108,70.14262531548704],[510596.72374483914,6651106.057656946,73.62204572645486],[510589.27189907164,6651116.814404594,71.18735300848705],[510589.20294842176,6651114.2571347365,74.30440357248703],[510589.1838436113,6651113.548567724,75.18714427048704],[510589.29102483205,6651117.523748606,70.60821600248704],[510596.7190915758,6651105.853041999,74.24896059745485],[510589.26860670216,6651116.69229585,71.61366335948703],[510589.21400849376,6651114.667335203,74.09212576348703],[510589.1936151723,6651113.910979369,75.08804877648703],[510589.2641024903,6651116.525241805,72.03547221848703],[510589.22456805623,6651115.058972565,73.83591264048705],[510596.7320732677,6651106.423877573,73.91948819645486],[510589.2892582107,6651117.45822743,71.08548695448704],[510589.2583810076,6651116.313041114,72.44582176148704],[510589.23204697116,6651115.336353619,73.61649363448703],[510589.23906657833,6651115.5966996765,73.37552398848705],[510589.25147534476,6651116.056921072,72.83760145548703],[510589.2033385399,6651114.2716036,74.96042601748704],[510589.2455613867,6651115.837581779,73.11508331548704],[510596.72637264675,6651106.173207836,74.48904904445486],[510589.28619878454,6651117.344758186,71.56838797448704],[510592.6211930509,6651110.764457343,74.74879148132213],[510589.2129256882,6651114.627175668,74.80393472548704],[510589.2830169329,6651117.226748373,71.93009395948705],[510589.22228544526,6651114.974314158,74.61872582348704],[510596.74098064634,6651106.815555996,74.17570131945486],[510589.27905864135,6651117.079941641,72.28785180548705],[510589.23132599297,6651115.309613685,74.40547348848703],[510596.7339986807,6651106.508542517,74.70230137945487],[510589.27432343713,6651116.904320451,72.63830802048703],[510589.23995759216,6651115.62974596,74.16538504148703],[510589.26882473053,6651116.700382178,72.97805304748704],[510589.24809537653,6651115.931563429,73.90018731648703],[510589.26259028114,6651116.469156371,73.30372015748704],[510589.2556620456,6651116.212199143,73.61208896548705],[510592.7734497102,6651116.844356714,68.35252413432214],[510592.7734497102,6651116.844356714,68.48252413432213],[510596.7503102232,6651107.225799468,74.38797912845486],[510596.7418939794,6651106.855717401,74.88751028145487],[510592.7887109422,6651117.453766873,68.35252413432214],[510596.74998109107,6651107.21132675,75.04400157345488],[510596.75990033546,6651107.647499295,74.55509388545487],[510592.6640931494,6651112.477540261,74.74879148132213],[510596.75818310864,6651107.571988788,75.17162433245487],[510596.76959279214,6651108.073699448,74.67724700745487],[510592.67452212004,6651112.893988985,74.71104862232214],[510592.7734497688,6651116.844359051,70.18132779432213],[510592.6647734403,6651112.504705574,75.35778664132214],[510596.76642577926,6651107.934438431,75.27071982645487],[510592.77333597414,6651116.839815014,70.38514907832213],[510596.7792401587,6651108.497916885,74.75592170045486],[510592.6851450558,6651113.318183114,74.63237392932214],[510592.77239108994,6651116.802083986,70.80172836632214],[510592.67659294023,6651112.976680796,75.31501140032215],[510592.6958176414,6651113.744359851,74.51022080732214],[510592.7887109422,6651117.453766873,70.18132779332214],[510596.77735946135,6651108.415218192,75.35988447845486],[510596.78871137305,6651108.914388492,74.79366455945485],[510592.7704214864,6651116.72343395,71.22605548632214],[510592.7063775331,6651114.166036505,74.34310605032213],[510592.6886322676,6651113.457434141,75.22584674832214],[510592.788186211,6651117.432813353,70.64691848032213],[510592.7673634099,6651116.601319114,71.65236583732215],[510592.7166505433,6651114.5762574375,74.13082824132213],[510596.78809350426,6651108.887219346,75.40265971945486],[510592.69770846044,6651113.819863868,75.12675125432214],[510592.7631797288,6651116.434256734,72.07417469632213],[510592.7264586615,6651114.96791434,73.87461511832214],[510592.78654530674,6651117.367288907,71.12418943232214],[510592.7578654008,6651116.222045456,72.48452423932214],[510592.7334053586,6651115.245309232,73.65519611232213],[510592.7399254335,6651115.505668278,73.41422646632213],[510592.7514511618,6651115.965912636,72.87630393332215],[510592.7459580553,6651115.7465624,73.15378579332213],[510592.70673988946,6651114.180506091,74.99912849532215],[510592.7837035968,6651117.253814002,71.60709045232214],[510592.7156447929,6651114.5360958995,74.84263720332214],[510592.78074817354,6651117.1357983025,71.96879643732214],[510592.7243384867,6651114.883251709,74.65742830132216],[510592.77707156364,6651116.988984244,72.32655428332214],[510592.7327356871,6651115.218567966,74.44417596632213],[510592.7726733281,6651116.813354294,72.67701049832213],[510592.74075304053,6651115.538716211,74.20408751932213],[510592.7675659229,6651116.609405844,73.01675552532214],[510592.7483117203,6651115.840548739,73.93888979432214],[510592.7617751322,6651116.378168503,73.34242263532214],[510592.75533992675,6651116.121198455,73.65079144332213],[510596.8284988171,6651110.663936135,74.79366455945485],[510596.96677281527,6651116.744169581,68.39739721245486],[510596.96677281527,6651116.744169581,68.52739721245487],[510596.98063251487,6651117.353613226,68.39739721245486],[510609.1755280418,6651103.696178987,68.52052626257824],[510596.867459137,6651112.377113184,74.79366455945485],[510609.3450717457,6651103.693485635,68.52209666841532],[510596.8769303513,6651112.793584791,74.75592170045486],[510596.9667728685,6651116.744171919,70.22620087245485],[510609.18523901305,6651104.305702854,68.52052626257824],[510596.8680769526,6651112.404279989,75.40265971945486],[510596.9666695243,6651116.739627633,70.43002215645485],[510609.18523901305,6651104.305702854,68.65052626257824],[510609.3547264457,6651104.303010396,68.52209666841532],[510596.8865777179,6651113.217802227,74.67724700745487],[510609.3547264457,6651104.303010396,68.65209666841531],[510596.96581141464,6651116.70189453,70.84660144445486],[510596.87881099543,6651112.876281145,75.35988447845486],[510596.89627017465,6651113.644002382,74.55509388545487],[510596.98063251487,6651117.353613226,70.22620087145486],[510596.96402269177,6651116.623240175,71.27092856445486],[510596.90586028685,6651114.065702207,74.38797912845486],[510596.8897446776,6651113.3570609065,75.27071982645487],[510596.980155973,6651117.332658556,70.69179155845485],[510596.9612454572,6651116.501118627,71.69723891545486],[510609.1755280418,6651103.696178987,70.34932992157825],[510596.9151898636,6651114.4759456795,74.17570131945486],[510596.8979873482,6651113.719510548,75.17162433245487],[510596.95744598925,6651116.334047068,72.11904777445486],[510609.3450717457,6651103.693485635,70.35090032741533],[510596.9240972423,6651114.867624102,73.91948819645486],[510596.97866576293,6651117.26713051,71.16906251045486],[510596.9526197084,6651116.1218241295,72.52939731745488],[510596.93040598166,6651115.145034237,73.70006919045485],[510596.93632727815,6651115.405407589,73.45909954445486],[510596.9467945282,6651115.865677235,72.92117701145486],[510609.17586193676,6651103.717136416,70.81492060857825],[510596.94180588744,6651115.646314947,73.19865887145485],[510596.9061893658,6651114.080172587,75.04400157345488],[510609.18523901305,6651104.305702854,70.34932992157825],[510609.3454037059,6651103.714443094,70.8164910144153],[510596.97608502477,6651117.153649368,71.65196353045486],[510596.91427647736,6651114.435781935,74.88751028145487],[510609.3547264457,6651104.303010396,70.35090032741533],[510596.973401016,6651117.0356271835,72.01366951545486],[510596.9221717761,6651114.782956819,74.70230137945487],[510609.176906071,6651103.782673088,71.29219156057825],[510596.9700620517,6651116.88880506,72.37142736145486],[510609.1855336263,6651104.324194701,70.76014523357826],[510596.9297978101,6651115.1182915,74.48904904445486],[510609.3464417898,6651103.779979862,71.29376196641532],[510596.9660677331,6651116.713165458,72.72188357645487],[510596.937078881,6651115.438457337,74.24896059745485],[510609.3550193518,6651104.321502272,70.76171563941531],[510596.96142937226,6651116.509205802,73.06162860345486],[510596.94394340087,6651115.740306449,73.98376287245486],[510596.9561703852,6651116.277955756,73.38729571345486],[510596.9503261642,6651116.020971587,73.69566452145486],[510609.18645492126,6651104.382021178,71.18126666157823],[510609.1787142974,6651103.896169165,71.77509258057825],[510609.3559353081,6651104.379328833,71.1828370674153],[510609.3482395383,6651103.893476107,71.77666298641533],[510609.18059488165,6651104.014206886,72.13679856557826],[510609.18805041513,6651104.482164776,71.60735579657825],[510609.3501092252,6651104.011514001,72.13836897141532],[510609.3575215568,6651104.479472578,71.60892620241532],[510609.18293436855,6651104.161048336,72.49455641157826],[510609.19035269157,6651104.626670651,72.03226230057824],[510609.3524351556,6651104.158355666,72.49612681741532],[510609.3598104924,6651104.623978665,72.03383270641532],[510609.1857330377,6651104.336711057,72.84501262657824],[510609.1933755441,6651104.816404587,72.44922900257824],[510609.35521760763,6651104.334018646,72.84658303241531],[510609.36281582864,6651104.813712877,72.4507994084153],[510609.18898296304,6651104.540697562,73.18475765357825],[510609.3584487009,6651104.538005449,73.18632805941533],[510609.19711100246,6651105.050866302,72.85117791957825],[510609.36652964144,6651105.048174938,72.85274832541532],[510613.89348648244,6651103.627073775,68.5632313089762],[510609.1926677378,6651104.771978049,73.51042476357824],[510609.3621121238,6651104.769286274,73.51199516941531],[510609.2015277214,6651105.32808838,73.23105872157824],[510609.37092076725,6651105.325397422,73.23262912741531],[510609.1967625641,6651105.028996043,73.81879357157825],[510613.9016315702,6651104.236620578,68.5632313089762],[510613.9016315702,6651104.236620578,68.69323130897621],[510609.3661832222,6651105.026304646,73.82036397741531],[510609.20525531855,6651105.56205668,73.49746503657823],[510609.3746267645,6651105.559366065,73.49903544241532],[510609.20123472676,6651105.309698125,74.10689192257824],[510609.3706294704,6651105.3070071405,74.10846232841533],[510609.20930480503,6651105.816228851,73.74517477657824],[510609.37865278573,6651105.81353861,73.74674518241531],[510613.89348648244,6651103.627073775,70.3920349679762],[510609.2060444381,6651105.611586971,74.37208964757824],[510609.37541131146,6651105.608896428,74.3736600534153],[510609.2151402224,6651106.182497685,74.04261724657826],[510613.8937665372,6651103.648031992,70.85762565497619],[510609.38445438904,6651106.17980798,74.04418765241532],[510613.9016315702,6651104.236620578,70.3920349679762],[510609.2111460112,6651105.931794952,74.61217809457824],[510609.38048332284,6651105.92910488,74.61374850041531],[510613.89464230597,6651103.71357113,71.3348966069762],[510613.90187867737,6651104.255113122,70.8028502799762],[510609.22138128825,6651106.5742276665,74.29883036957824],[510609.2164892869,6651106.267173775,74.82543042957825],[510609.39065929037,6651106.571538536,74.30040077541531],[510609.3857956364,6651106.264484194,74.82700083541532],[510613.9026514145,6651104.312941775,71.22397170797619],[510613.8961589578,6651103.82707148,71.8177976269762],[510609.2279181725,6651106.984525139,74.51110817857824],[510609.2220212264,6651106.6143943565,75.01063933157825],[510609.39715829596,6651106.98183661,74.51267858441531],[510609.39129552036,6651106.611705286,75.01220973741532],[510613.89773629984,6651103.945113642,72.1795036119762],[510613.90398963675,6651104.413089141,71.65006084297622],[510609.22768756194,6651106.970050516,75.16713062357825],[510609.23463760415,6651107.406280475,74.67822293557825],[510613.89969854703,6651104.091960617,72.5372614579762],[510609.3969290217,6651106.967361964,75.16870102941532],[510609.403838791,6651107.403592563,74.67979334141532],[510613.90592067357,6651104.5576004535,72.0749673469762],[510609.23343440774,6651107.330760027,75.29475338257824],[510609.24142874463,6651107.832536731,74.80037605757825],[510613.9020459338,6651104.267629948,72.88771767297621],[510609.4026425668,6651107.328072008,75.29632378841531],[510609.4105905796,6651107.829849445,74.80194646341532],[510613.9084560945,6651104.747341528,72.49193404897619],[510609.2392097376,6651107.693257379,75.39384887657825],[510609.24818829226,6651108.256810007,74.87905075057824],[510609.4083844308,6651107.69056989,75.39541928241533],[510613.90477181226,6651104.471624129,73.2274626999762],[510609.4173109583,6651108.254123345,74.88062115641533],[510613.9115892142,6651104.981812067,72.89388296597619],[510609.2468705583,6651108.174100428,75.48301352857824],[510609.25482441665,6651108.673336434,74.91679360957824],[510613.9078624212,6651104.702913318,73.5531298099762],[510609.41600086004,6651108.171413644,75.48458393441531],[510609.4239086289,6651108.6706503825,74.91836401541532],[510613.9152937421,6651105.2590445755,73.2737637679762],[510609.25439149915,6651108.646163712,75.52578876957826],[510609.42347822,6651108.643477621,75.52735917541531],[510613.91129696125,6651104.959940986,73.8614986179762],[510613.9184202683,6651105.49302168,73.5401700829762],[510613.91504799254,6651105.240653629,74.1495969689762],[510613.92181677953,6651105.747203415,73.7878798229762],[510613.9190821432,6651105.542553835,74.41479469397619],[510609.2827019851,6651110.423114375,74.91679360957824],[510609.45162465767,6651110.420430889,74.91836401541532],[510613.92671124224,6651106.113486032,74.0853222929762],[510613.92336109316,6651105.862773865,74.6548831409762],[510609.3795853851,6651116.504148172,68.52052626257824],[510609.3795853851,6651116.504148172,68.65052626257824],[510609.5479466559,6651116.501473606,68.52209666841532],[510613.931945943,6651106.505230753,74.3415354159762],[510609.5479466559,6651116.501473606,68.65209666841531],[510613.9278427716,6651106.198165307,74.8681354759762],[510609.3892963563,6651117.11367204,68.52052626257824],[510609.5576013559,6651117.110998366,68.52209666841532],[510613.9374287619,6651106.915543665,74.5538132249762],[510613.9324826919,6651106.545398956,75.0533443779762],[510609.3100000188,6651112.1365169315,74.91679360957824],[510609.4787645098,6651112.13383596,74.91836401541532],[510613.937235337,6651106.901068497,75.20983566997621],[510613.94306469255,6651107.337314871,74.7209279819762],[510609.31663614314,6651112.553043359,74.87905075057824],[510609.37958542234,6651116.504150511,70.34932992257825],[510609.3104328989,6651112.163687313,75.52578876957826],[510609.48536218033,6651112.550362998,74.88062115641533],[510609.3795130129,6651116.499605627,70.55315120657824],[510609.54794669297,6651116.501475945,70.3509003284153],[510609.47919488157,6651112.161006381,75.52735917541531],[510609.32339569076,6651112.977316637,74.80037605757825],[510613.94205551024,6651107.261791583,75.3374584289762],[510609.54787470313,6651116.496931053,70.55472161241532],[510613.9487607691,6651107.763587167,74.8430811039762],[510609.49208255904,6651112.9746368965,74.80194646341532],[510609.3789117677,6651116.461867557,70.96973049457824],[510609.3179538399,6651112.635750599,75.48301352857824],[510609.3892963563,6651117.11367204,70.34932992157825],[510609.3301868313,6651113.403572893,74.67822293557825],[510609.5472769419,6651116.459192928,70.97130090041533],[510609.4866722416,6651112.633070359,75.48458393441531],[510609.37765847676,6651116.383202848,71.39405761457826],[510613.9468995745,6651107.624302576,75.4365539229762],[510609.5576013559,6651117.110998366,70.35090032741533],[510609.49883434764,6651113.400893778,74.67979334141532],[510609.3369062629,6651113.825328227,74.51110817857824],[510613.9544303471,6651108.187876408,74.9217557969762],[510609.32561466057,6651113.116593648,75.39384887657825],[510609.5460309133,6651116.380528104,71.39562802041532],[510609.3889624613,6651117.092714612,70.81492060857825],[510609.3757125727,6651116.261065225,71.82036796557824],[510609.50551484275,6651113.822649731,74.51267858441531],[510609.3434431472,6651114.235625701,74.29883036957824],[510609.4942886708,6651113.113914112,75.39541928241533],[510609.5572693957,6651117.090040907,70.8164910144153],[510609.54409628507,6651116.258390302,71.82193837141531],[510609.3730504281,6651116.093971674,72.24217682457824],[510609.33138999034,6651113.479090998,75.29475338257824],[510609.349684213,6651114.627355681,74.04261724657826],[510609.51201384823,6651114.232947806,74.30040077541531],[510609.38791832706,6651117.027177939,71.29219156057825],[510613.95332509617,6651108.105163718,75.5257185749762],[510613.9599964036,6651108.60441851,74.95949865597619],[510609.3696688343,6651115.881720801,72.65252636757825],[510609.35410450987,6651114.904802331,73.82319824057824],[510609.5414495666,6651116.091296505,72.24374723041532],[510609.50003053475,6651113.476411995,75.29632378841531],[510609.3655873492,6651115.625540189,73.04430606157824],[510609.35825334,6651115.1652099565,73.58222859457825],[510609.36209199595,6651115.406149025,73.32178792157825],[510609.33713683626,6651113.8398005115,75.16713062357825],[510609.51821874955,6651114.624678362,74.04418765241532],[510609.5562313118,6651117.024504139,71.29376196641532],[510609.5380875677,6651115.879045322,72.65409677341532],[510609.52261343255,6651114.902125418,73.82476864641532],[510609.5340297333,6651115.622864335,73.04587646741531],[510609.5267382219,6651115.162533427,73.58379900041531],[510609.38611010066,6651116.913681861,71.77509258057825],[510609.5305546342,6651115.403472849,73.32335832741532],[510609.50574408,6651113.837122037,75.16870102941532],[510609.3428031718,6651114.195456669,75.01063933157825],[510609.5544335634,6651116.911007894,71.77666298641533],[510609.38422951655,6651116.795644141,72.13679856557826],[510613.9596332937,6651108.577244766,75.5684938159762],[510609.5113775812,6651114.192778716,75.01220973741532],[510609.34833511116,6651114.542677253,74.82543042957825],[510609.38189002965,6651116.64880269,72.49455641157826],[510609.55256387644,6651116.792970001,72.13836897141532],[510609.3536783869,6651114.8780560745,74.61217809457824],[510609.5168774652,6651114.539999809,74.82700083541532],[510609.3790913605,6651116.47313997,72.84501262657824],[510609.3587799599,6651115.198264056,74.37208964757824],[510609.550237946,6651116.646128335,72.49612681741532],[510609.3758414351,6651116.269153465,73.18475765357825],[510609.52218977874,6651114.875379123,74.61374850041531],[510609.3635896713,6651115.500152901,74.10689192257824],[510609.3721566603,6651116.0378729785,73.51042476357824],[510609.36806183396,6651115.780854982,73.81879357157825],[510609.54745549406,6651116.4704653565,72.84658303241531],[510609.5272617901,6651115.195587574,74.3736600534153],[510609.54422440066,6651116.266478554,73.18632805941533],[510609.5320436312,6651115.497476861,74.10846232841533],[510609.54056097777,6651116.035197727,73.51199516941531],[510609.53648987936,6651115.778179355,73.82036397741531],[510613.98337874474,6651110.354262293,74.95949865597619],[510614.0646398025,6651116.435524915,68.5632313089762],[510614.0646398025,6651116.435524915,68.69323130897621],[510614.0727848903,6651117.045071719,68.5632313089762],[510626.23984072346,6651103.503599185,68.66521709454246],[510614.0062750003,6651112.067729325,74.95949865597619],[510614.01184105687,6651112.484271425,74.9217557969762],[510614.06463983376,6651116.435527254,70.39203496897619],[510614.006638079,6651112.094900728,75.5684938159762],[510626.2438880744,6651104.11318697,68.66521709454246],[510614.06457910023,6651116.4309822,70.59585625297619],[510626.2438880744,6651104.11318697,68.79521709454245],[510614.01751063485,6651112.908560668,74.8430811039762],[510614.0640748052,6651116.393242709,71.0124355409762],[510614.0129462765,6651112.566981778,75.5257185749762],[510614.0727848903,6651117.045071719,70.3920349679762],[510614.0232067114,6651113.3348329635,74.7209279819762],[510614.063023606,6651116.314575039,71.4367626609762],[510614.02884264203,6651113.756604169,74.5538132249762],[510614.01937179815,6651113.04784292,75.4365539229762],[510614.07250483544,6651117.024113502,70.85762565497619],[510614.06139147695,6651116.192432822,71.8630730119762],[510626.23984072346,6651103.503599185,70.49402075354247],[510614.03432546085,6651114.166917081,74.3415354159762],[510614.05915860017,6651116.025332983,72.28488187097619],[510614.0242158624,6651113.41035391,75.3374584289762],[510614.0395601617,6651114.558661803,74.0853222929762],[510614.07162906666,6651116.958574363,71.3348966069762],[510614.05632228474,6651115.813074122,72.69523141397622],[510614.0432676906,6651114.836118892,73.86590328697619],[510614.0528989346,6651115.556883871,73.08701110797621],[510614.0467475264,6651115.096536316,73.6249336409762],[510614.0499672032,6651115.337484452,73.36449296797619],[510614.02903603564,6651113.771076997,75.20983566997621],[510626.23997988465,6651103.524558811,70.95961144054245],[510614.0701124148,6651116.845074014,71.8177976269762],[510626.2438880744,6651104.11318697,70.49402075354247],[510614.0337886808,6651114.126746538,75.0533443779762],[510614.06853507285,6651116.727031852,72.1795036119762],[510614.038428601,6651114.4739801865,74.8681354759762],[510626.24041506025,6651103.590102356,71.43688239254246],[510614.06657282566,6651116.580184877,72.5372614579762],[510614.0429102794,6651114.809371629,74.6548831409762],[510626.2440108637,6651104.131680758,70.90483606554245],[510614.0642254388,6651116.404515545,72.88771767297621],[510614.04718922934,6651115.12959166,74.41479469397619],[510614.06149956037,6651116.200521367,73.2274626999762],[510614.05122338014,6651115.431491864,74.1495969689762],[510614.0584089515,6651115.9692321755,73.5531298099762],[510614.05497441144,6651115.7122045085,73.8614986179762],[510626.2443948422,6651104.189513296,71.32595749354245],[510626.2411686951,6651103.7036103355,71.91978341254247],[510626.2419524874,6651103.821660434,72.28148939754246],[510626.2450598141,6651104.289667396,71.75204662854246],[510629.4247079386,6651103.4852147475,68.68923256011365],[510626.24292754167,6651103.968517283,72.63924724354246],[510626.2460193598,6651104.434188425,72.17695313254247],[510629.4276982368,6651104.094808633,68.68923256011365],[510629.4276982368,6651104.094808633,68.81923256011363],[510626.2440939746,6651104.144198425,72.98970345854245],[510626.2472792281,6651104.623942256,72.59391983454245],[510626.24544848263,6651104.348206319,73.32944848554247],[510626.2488360972,6651104.858428558,72.99586875154245],[510629.4247079386,6651103.4852147475,70.51803621911364],[510626.2469842277,6651104.579511059,73.65511559554245],[510631.1135923384,6651103.4777066065,68.7015861260573],[510629.4248107548,6651103.506174582,70.98362690611363],[510626.2506769029,6651105.135679706,73.37574955354245],[510629.4276982368,6651104.094808633,70.51803621911364],[510626.2486908746,6651104.836556006,73.96348440354245],[510629.4251322749,6651103.571718783,71.46089785811365],[510631.1160220983,6651104.087302984,68.7015861260573],[510626.25223049556,6651105.369672542,73.64215586854246],[510629.42778895696,6651104.113302606,70.92885153111364],[510631.1160220983,6651104.087302984,68.83158612605729],[510626.2505547882,6651105.117287523,74.25158275454245],[510629.4280726512,6651104.171135723,71.34997295911364],[510629.4256890819,6651103.6852279,71.94379887811364],[510626.2539182457,6651105.623871366,73.88986560854245],[510626.2525593859,6651105.419208026,74.51678047954245],[510629.4262681699,6651103.80327918,72.30550486311364],[510629.4285639514,6651104.271290826,71.77606209411364],[510631.1135923384,6651103.4777066065,70.5303897850573],[510626.2563503383,6651105.990178609,74.18730807854246],[510626.25468562596,6651105.739449585,74.75686892654245],[510629.42698856787,6651103.950137498,72.66326270911364],[510631.1136758815,6651103.498666528,70.99598047205728],[510629.4292728911,6651104.415813303,72.20096859811363],[510631.1160220983,6651104.087302984,70.5303897850573],[510626.2589514977,6651106.381949667,74.44352120154245],[510629.4278503617,6651104.125820398,73.01371892411363],[510631.1139371319,6651103.564210997,71.4732514240573],[510626.2569126032,6651106.074863577,74.97012126154247],[510631.1160958128,6651104.105797033,70.9412050970573],[510629.4302037177,6651104.605569031,72.61793530011364],[510626.26167594857,6651106.792290165,74.65579901054245],[510629.42885111074,6651104.3298303345,73.35346395111364],[510631.11632632784,6651104.163630388,71.36232652505728],[510626.25921821187,6651106.422120571,75.15533016354246],[510631.11438956414,6651103.6777205765,71.9561524440573],[510629.43135397695,6651104.840057681,73.01988421711363],[510631.1148601008,6651103.795772339,72.3178584290573],[510631.11672553275,6651104.2637859,71.7884156600573],[510629.429985763,6651104.561137389,73.67913106111364],[510626.2615798344,6651106.777814023,75.31182145554246],[510626.2644764818,6651107.214089728,74.82291376754246],[510629.43271401664,6651105.117311604,73.39976501911363],[510631.11544545845,6651103.942631259,72.6756162750573],[510626.2639750121,6651107.138561362,75.43944421454245],[510631.1173015801,6651104.408308966,72.21332216405729],[510629.43124668236,6651104.818184911,73.98749986911363],[510626.26730690204,6651107.640390683,74.94506688954246],[510629.43386185524,6651105.351306782,73.66617133411366],[510631.1161457071,6651104.118314878,73.02607249005729],[510626.2663820614,6651107.501096726,75.53853970854247],[510631.11805792106,6651104.598065472,72.63028886605728],[510626.2701241548,6651108.06470845,75.02374158254247],[510629.4326237949,6651105.098919239,74.27559822011365],[510629.4351088131,6651105.6055081505,73.91388107411363],[510631.1169588634,6651104.322325647,73.3658175170573],[510626.26957494795,6651107.981990198,75.62770436054247],[510626.2728899672,6651108.481278556,75.06148444154246],[510629.4341048487,6651105.400842763,74.54079594511363],[510631.11899256153,6651104.832555079,73.0322377830573],[510629.43690571235,6651105.971819059,74.21132354411364],[510631.1178808225,6651104.553633648,73.6914846270573],[510626.27270953526,6651108.454102986,75.67047960154245],[510629.43567577546,6651105.721087527,74.78088439211363],[510631.1200976588,6651105.109810137,73.41211858505729],[510631.1189053796,6651104.81068222,73.99985343505729],[510629.438827523,6651106.363594039,74.46753666711363],[510629.4373211297,6651106.056504875,74.99413672711364],[510631.1210303323,6651105.3438062705,73.67852490005728],[510631.12002434925,6651105.091417694,74.28795178605729],[510629.440840425,6651106.773938647,74.67981447611365],[510629.4390245791,6651106.403765346,75.17934562911366],[510631.12204354507,6651105.598008678,73.9262346400573],[510626.2845088155,6651110.231239986,75.06148444154246],[510631.12122777617,6651105.393342453,74.5531495110573],[510629.44076941314,6651106.75946236,75.33583692111364],[510629.4429095387,6651107.19574243,74.84692923311364],[510626.32488800184,6651116.312911464,68.66521709454246],[510631.1235036115,6651105.964321085,74.22367711005731],[510626.32488800184,6651116.312911464,68.79521709454245],[510631.122504229,6651105.7135885265,74.7932379580573],[510629.4425390386,6651107.120213309,75.46345968011363],[510629.4450007338,6651107.622047652,74.96908235511364],[510626.32893535285,6651116.922499247,68.66521709454246],[510631.12506517424,6651106.356097667,74.4798902330573],[510629.4443174352,6651107.482752302,75.56255517411364],[510631.1238411578,6651106.049007246,75.0064902930573],[510629.44708220044,6651108.046369667,75.04775704811364],[510626.29588612466,6651111.9448222155,75.06148444154246],[510631.1267007531,6651106.766443949,74.69216804205729],[510631.12522529176,6651106.396269136,75.1916991950573],[510629.4466764307,6651107.963650586,75.65171982611363],[510629.4491256614,6651108.462943942,75.08549990711363],[510626.29865193693,6651112.361392322,75.02374158254247],[510626.3248880174,6651116.3129138015,70.49402075454245],[510626.29606654093,6651111.971995447,75.67047960154245],[510626.32485783857,6651116.308368442,70.69784203854246],[510631.1266430526,6651106.751967603,75.3481904870573],[510631.1283820068,6651107.188249458,74.85928279905731],[510629.44899235317,6651108.4357680995,75.69449506711364],[510626.30146918976,6651112.78571009,74.94506688954246],[510626.3246072508,6651116.270626414,71.11442132654247],[510626.2992011283,6651112.444108235,75.62770436054247],[510626.32893535285,6651116.922499247,70.49402075354247],[510631.12808095774,6651107.1127200285,75.47581324605729],[510626.30429960997,6651113.212011044,74.82291376754246],[510631.13008120254,6651107.614556422,74.98143592105731],[510626.3240849026,6651116.191953456,71.53874844654246],[510626.30710014317,6651113.633810608,74.65579901054245],[510626.3023940148,6651112.925001705,75.53853970854247],[510626.3287961916,6651116.901539621,70.95961144054245],[510626.3232738862,6651116.0698030265,71.96505879754247],[510631.1295259898,6651107.475260503,75.5749087400573],[510626.3098245941,6651114.044151105,74.44352120154245],[510631.1317724935,6651108.038880172,75.0601106140573],[510626.32216435426,6651115.902691952,72.38686765654246],[510626.30480106414,6651113.28753707,75.43944421454245],[510626.3124257535,6651114.435922164,74.18730807854246],[510626.328361016,6651116.835996076,71.43688239254246],[510626.32075496926,6651115.690418822,72.79721719954246],[510626.3142680504,6651114.713397908,73.96788907254245],[510626.31905388273,6651115.434211346,73.18899689354245],[510626.3159972051,6651114.973832841,73.72691942654245],[510626.3175970849,6651115.2147971755,73.46647875354245],[510629.4577099976,6651110.212922889,75.08549990711363],[510626.3071962418,6651113.648284409,75.31182145554246],[510626.3276073811,6651116.722488096,71.91978341254247],[510631.13144278625,6651107.956160753,75.66407339205729],[510631.13343290304,6651108.455456151,75.09785347305728],[510626.3095578643,6651114.003977861,75.15533016354246],[510626.32682358887,6651116.6044379985,72.28148939754246],[510626.31186347303,6651114.351234855,74.97012126154247],[510626.3258485345,6651116.457581149,72.63924724354246],[510629.48754329083,6651116.294655242,68.68923256011365],[510626.3140904503,6651114.686648847,74.75686892654245],[510629.48754329083,6651116.294655242,68.81923256011363],[510626.32468210167,6651116.281900008,72.98970345854245],[510631.13332458364,6651108.428280197,75.70684863305729],[510626.31621669047,6651115.006890406,74.51678047954245],[510626.3233275936,6651116.0778921135,73.32944848554247],[510626.31822128803,6651115.308810909,74.25158275454245],[510626.3217918486,6651115.846587373,73.65511559554245],[510626.32008520165,6651115.589542426,73.96348440354245],[510629.4905335889,6651116.904249128,68.68923256011365],[510629.4661158777,6651111.926522272,75.08549990711363],[510631.14040808566,6651110.205442251,75.09785347305728],[510629.4681593386,6651112.343096547,75.04775704811364],[510629.4875433023,6651116.294657581,70.51803622011363],[510629.46624917444,6651111.953695774,75.69449506711364],[510629.48752100527,6651116.290112174,70.72185750411363],[510631.1646490596,6651116.287199465,68.7015861260573],[510629.47024080524,6651112.767418562,74.96908235511364],[510631.1646490596,6651116.287199465,68.83158612605729],[510629.4873358639,6651116.25236977,71.13843679211364],[510629.4685650968,6651112.425813288,75.65171982611363],[510629.4905335889,6651116.904249128,70.51803621911364],[510629.47233200027,6651113.193723784,74.84692923311364],[510629.4869499381,6651116.173696023,71.56276391211364],[510631.1670788195,6651116.896795843,68.7015861260573],[510629.4744011141,6651113.615527568,74.67981447611365],[510629.47092409234,6651112.906711572,75.56255517411364],[510629.4904307727,6651116.8832892915,70.98362690611363],[510629.4863507362,6651116.05154437,71.98907426311364],[510629.476414016,6651114.025872175,74.46753666711363],[510629.4855309823,6651115.884431624,72.41088312211363],[510629.47270248894,6651113.269250565,75.46345968011363],[510643.1356416159,6651103.469133594,68.78188541270163],[510629.4783358266,6651114.417647155,74.21132354411364],[510629.49010925257,6651116.817745091,71.46089785811365],[510629.48448968853,6651115.672156369,72.82123266511364],[510629.4796969681,6651114.695125677,73.99190453811364],[510629.4832328774,6651115.415946329,73.21301235911363],[510629.4809745169,6651114.955563216,73.75093489211363],[510629.48215655365,6651115.196529962,73.49049421911363],[510631.1472382642,6651111.919048638,75.09785347305728],[510629.4744721144,6651113.630001515,75.33583692111364],[510629.4895524457,6651116.704235976,71.94379887811364],[510629.4762169484,6651113.985698529,75.17934562911366],[510629.4889733576,6651116.586184695,72.30550486311364],[510643.1340812753,6651104.0787328165,68.78188541270163],[510631.14889867377,6651112.335624617,75.0601106140573],[510631.16464906896,6651116.287201805,70.53038978605728],[510629.4779203979,6651114.332958998,74.99413672711364],[510643.1340812753,6651104.0787328165,68.91188541270164],[510629.4882529597,6651116.439326376,72.66326270911364],[510631.14734657423,6651111.946222252,75.70684863305729],[510629.47956575215,6651114.668376348,74.78088439211363],[510631.16463095153,6651116.282656379,70.73421107005728],[510629.48739116587,6651116.263643475,73.01371892411363],[510629.48113667883,6651114.988621112,74.54079594511363],[510629.48639041674,6651116.059633539,73.35346395111364],[510631.1505899647,6651112.759948367,74.98143592105731],[510629.48261773266,6651115.290544637,74.27559822011365],[510629.4852557645,6651115.828326484,73.67913106111364],[510629.4839948451,6651115.571278964,73.98749986911363],[510631.1644805153,6651116.244913819,71.1507903580573],[510631.14922837156,6651112.418341696,75.66407339205729],[510631.1670788195,6651116.896795843,70.5303897850573],[510631.15228916047,6651113.186255332,74.85928279905731],[510631.16416693234,6651116.1662397515,71.5751174780573],[510631.153970414,6651113.6080608405,74.69216804205729],[510643.1356416159,6651103.469133594,70.61068907170163],[510631.16699527646,6651116.875835921,70.99598047205728],[510631.15114516806,6651112.899241946,75.5749087400573],[510631.1636800521,6651116.0440876,72.00142782905729],[510631.15560599294,6651114.018407123,74.4798902330573],[510631.16301396297,6651115.87697417,72.42323668805729],[510631.1525902001,6651113.261782422,75.47581324605729],[510631.15716755576,6651114.410183704,74.22367711005731],[510631.166734026,6651116.810291452,71.4732514240573],[510631.1621678622,6651115.664698048,72.8335862310573],[510643.1355879663,6651103.490093613,71.07627975870162],[510631.15827354806,6651114.6876633605,74.00425810405729],[510631.1611466431,6651115.40848696,73.22536592505729],[510631.1593116174,6651114.948101965,73.76328845805729],[510631.1602720787,6651115.189069697,73.50284778505731],[510631.15402810526,6651113.622534845,75.3481904870573],[510643.1340812753,6651104.0787328165,70.61068907170163],[510631.16628159373,6651116.696781872,71.9561524440573],[510631.1554458661,6651113.978233313,75.1916991950573],[510631.16581105714,6651116.57873011,72.3178584290573],[510643.13542019675,6651103.555638387,71.55355071070163],[510631.15683000005,6651114.325495202,75.0064902930573],[510643.13403393736,6651104.097226952,71.02150438370163],[510631.1652256994,6651116.431871191,72.6756162750573],[510631.1581669288,6651114.660913923,74.7932379580573],[510631.16452545085,6651116.256187573,73.02607249005729],[510631.1594433817,6651114.981159996,74.5531495110573],[510631.1637122944,6651116.0521768015,73.3658175170573],[510631.1606468086,6651115.283084755,74.28795178605729],[510631.16279033537,6651115.820868801,73.6914846270573],[510631.1617657782,6651115.563820231,73.99985343505729],[510643.1338859055,6651104.155060575,71.44262581170162],[510643.1351296543,6651103.669148497,72.03645173070163],[510643.1348274856,6651103.78720081,72.39815771570163],[510643.13362954446,6651104.255216556,71.86871494670164],[510643.1344515812,6651103.934060415,72.75591556170163],[510643.13325961906,6651104.399740296,72.29362145070162],[510643.1340018963,6651104.109744854,73.10637177670164],[510643.13277391274,6651104.589497688,72.71058815270162],[510643.1334797045,6651104.313756577,73.44611680370163],[510643.13217370637,6651104.823988391,73.11253706970165],[510643.13288764184,6651104.545065657,73.77178391370163],[510643.1314640363,6651105.101244741,73.49241787170163],[510643.13222969277,6651104.802115428,74.08015272170162],[510648.33434174245,6651103.489797736,68.81246166369984],[510643.130865093,6651105.335241968,73.75882418670162],[510643.1315111141,6651105.082852214,74.36825107270163],[510648.33105596085,6651104.099390101,68.81246166369984],[510643.1302144291,6651105.589445562,74.00653392670162],[510648.33105596085,6651104.099390101,68.94246166369982],[510643.1307382987,6651105.384778381,74.63344879770162],[510643.1292768052,6651105.955759678,74.30397639670163],[510643.1299185876,6651105.705025951,74.87353724470162],[510649.6749830265,6651103.497513266,68.81994054909241],[510648.33434174245,6651103.489797736,70.64126532269984],[510643.12827400246,6651106.347538088,74.56018951970162],[510648.33422876644,6651103.510757518,71.10685600969981],[510643.1290600401,6651106.040446236,75.08678957970163],[510649.6712522881,6651104.10710307,68.81994054909241],[510648.33105596085,6651104.099390101,70.64126532269984],[510649.6712522881,6651104.10710307,68.9499405490924],[510648.3338754756,6651103.576301555,71.58412696169982],[510643.1272236682,6651106.757886288,74.77246732870162],[510643.12817117845,6651106.387709746,75.27199848170163],[510648.3309562763,6651104.117884026,71.05208063469982],[510648.330644549,6651104.175717,71.47320206269981],[510648.33326364844,6651103.689810388,72.06702798169984],[510643.1272607223,6651106.743409874,75.42848977370164],[510643.12614400254,6651107.179693764,74.93958208570163],[510649.6749830265,6651103.497513266,70.64874420809241],[510648.33262733836,6651103.807861374,72.42873396669982],[510648.33010470145,6651104.275871852,71.89929119769982],[510643.12633733,6651107.104163982,75.55611253270163],[510649.67485475144,6651103.518472962,71.1143348950924],[510643.1250528149,6651107.606002719,75.06173520770163],[510649.6712522881,6651104.10710307,70.64874420809241],[510648.331835755,6651103.9547193255,72.78649181269982],[510643.12540936074,6651107.466706149,75.65520802670163],[510648.3293257086,6651104.420393968,72.32419770169982],[510649.67445361835,6651103.584016724,71.59160584709242],[510643.12396670354,6651108.030328449,75.14040990070163],[510649.6711391042,6651104.12559692,71.0595595200924],[510648.3308888039,6651104.130401788,73.13694802769982],[510648.3283029032,6651104.610149223,72.74116440369981],[510643.1241784345,6651107.947608644,75.74437267870162],[510643.1229004235,6651108.446906372,75.17815275970162],[510649.67078516324,6651104.18342965,71.48068094809241],[510649.67375893815,6651103.697525079,72.07450686709241],[510648.3297891667,6651104.334411216,73.47669305469984],[510649.67303645966,6651103.81557557,72.43621285209241],[510649.67017221014,6651104.283584083,71.90677008309241],[510643.1229699839,6651108.419730292,75.78714791970162],[510648.3270389823,6651104.844637289,73.14311332069983],[510648.328542395,6651104.565717693,73.80236016469982],[510649.67213768105,6651103.962432904,72.79397069809241],[510649.6692877269,6651104.42810559,72.3316765870924],[510648.3255445516,6651105.12189052,73.52299412269981],[510648.32715687907,6651104.822764572,74.11072897269982],[510649.67106249486,6651104.138114629,73.1444269130924],[510649.6681264144,6651104.617860049,72.74864328909241],[510648.3242832905,6651105.355885114,73.78940043769981],[510643.1184211083,6651110.19690064,75.17815275970162],[510649.669813946,6651104.3421232,73.48417194009241],[510648.3256436886,6651105.103498199,74.39882732369983],[510648.3229131157,6651105.610085848,74.03711017769982],[510649.66669133474,6651104.852347129,73.1505922060924],[510643.1028540657,6651116.278686242,68.78188541270163],[510643.1028540657,6651116.278686242,68.91188541270164],[510649.6683983378,6651104.573428706,73.8098390500924],[510648.3240162858,6651105.40542097,74.66402504869981],[510649.66499452986,6651105.129599195,73.5304730080924],[510648.3209386576,6651105.976395843,74.33455264769982],[510643.10129372514,6651116.888285465,68.78188541270163],[510649.6668251969,6651104.830474504,74.1182078580924],[510648.3222901295,6651105.725664936,74.90411349569982],[510649.6635624702,6651105.363592806,73.79687932309243],[510648.31882694515,6651106.368169847,74.59076577069982],[510643.11403491156,6651111.910515026,75.17815275970162],[510649.66510709183,6651105.1112069525,74.4063062090924],[510648.3204821912,6651106.061081448,75.11736583069982],[510649.66200674785,6651105.617792473,74.0445890630924],[510643.1028540597,6651116.278688582,70.61068907270162],[510643.1129686315,6651112.32709295,75.14040990070163],[510648.3166151402,6651106.778513428,74.80304357969982],[510643.1028656944,6651116.274143135,70.81451035670162],[510643.11396535713,6651111.937688768,75.78714791970162],[510649.6632593081,6651105.413128455,74.6715039340924],[510648.3186104172,6651106.408341051,75.30257473269982],[510643.11188252014,6651112.75141868,75.06173520770163],[510649.6597649108,6651105.9841009285,74.34203153309241],[510643.1029623013,6651116.236400399,71.23108964470163],[510643.10129372514,6651116.888285465,70.61068907170163],[510643.11275690654,6651112.4098104155,75.74437267870162],[510643.11079133244,6651113.177727635,74.93958208570163],[510648.31669316906,6651106.764037178,75.45906602469982],[510648.3143415691,6651107.200316159,74.97015833669982],[510649.6612993976,6651105.733371076,74.9115923810924],[510643.10316367773,6651116.157725964,71.65541676470163],[510643.1097116668,6651113.599535111,74.77246732870162],[510643.10134737473,6651116.867325446,71.07627975870162],[510643.11152598023,6651112.89071291,75.65520802670163],[510643.10347634193,6651116.035573242,72.08172711570163],[510649.65736723255,6651106.375873286,74.5982446560924],[510648.31474867975,6651107.124787226,75.58668878369981],[510643.1086613325,6651114.009883311,74.56018951970162],[510648.3120437346,6651107.626620318,75.09231145869983],[510649.6592466303,6651106.068786178,75.12484471609241],[510643.10390409036,6651115.868459034,72.50353597470162],[510643.11059801106,6651113.253255077,75.55611253270163],[510643.1015151443,6651116.801780672,71.55355071070163],[510643.10765852977,6651114.401661721,74.30397639670163],[510643.10444743844,6651115.656181919,72.91388551770164],[510643.10694828484,6651114.679142673,74.08455739070162],[510643.10510324384,6651115.399969636,73.30566521170162],[510643.1062816586,6651114.939582491,73.84358774470162],[510643.1056648706,6651115.180551348,73.58314707170163],[510643.10967461875,6651113.614009186,75.42848977370164],[510648.31279455265,6651107.487325315,75.68578427769984],[510643.1018056867,6651116.688270561,72.03645173070163],[510649.65485590755,6651106.786215144,74.81052246509242],[510648.3097565898,6651108.050941274,75.17098615169984],[510649.65712138265,6651106.416044324,75.31005361809243],[510643.1087641626,6651113.969709313,75.27199848170163],[510643.10210785543,6651116.570218248,72.39815771570163],[510643.1078753009,6651114.316972823,75.08678957970163],[510643.1024837598,6651116.423358643,72.75591556170163],[510643.1070167535,6651114.652393108,74.87353724470162],[510643.1029334447,6651116.247674204,73.10637177670164],[510648.31020245526,6651107.968222399,75.77494892969982],[510648.30751120637,6651108.46751451,75.20872901069983],[510643.1061970423,6651114.972640678,74.63344879770162],[510649.65494450304,6651106.771738955,75.46654491009241],[510643.10345563653,6651116.043662482,73.44611680370163],[510649.65227445186,6651107.208016104,74.97763722209241],[510643.1054242269,6651115.274566845,74.36825107270163],[510643.1040476992,6651115.812353401,73.77178391370163],[510643.10470564826,6651115.55530363,74.08015272170162],[510648.3076576872,6651108.440338735,75.81772417069982],[510649.65273669304,6651107.132487488,75.5941676690924],[510649.64966544724,6651107.634318471,75.09979034409241],[510649.6505179403,6651107.495024054,75.69326316309241],[510649.64706858,6651108.058637645,75.17846503709241],[510649.647574824,6651107.975919119,75.7824278150924],[510649.644519129,6651108.475209132,75.2162078960924],[510648.29807861743,6651110.21748909,75.20872901069983],[510649.6446854463,6651108.448033472,75.8252030560924],[510648.26529737655,6651116.299206267,68.81246166369984],[510648.26529737655,6651116.299206267,68.94246166369982],[510648.26201159507,6651116.908798631,68.81246166369984],[510660.03104468284,6651103.590091781,68.87210162289652],[510649.6338091894,6651110.2251763595,75.2162078960924],[510648.2888421186,6651111.931084196,75.20872901069983],[510660.02387678274,6651104.199650858,68.87210162289652],[510660.02387678274,6651104.199650858,69.0021016228965],[510649.5965887496,6651116.306867989,68.81994054909241],[510648.265297364,6651116.299208607,70.64126532369981],[510648.28659673495,6651112.347657433,75.17098615169984],[510649.5965887496,6651116.306867989,68.9499405490924],[510648.2653218642,6651116.294663211,70.84508660769983],[510648.28869565023,6651111.958257632,75.81772417069982],[510648.2843095903,6651112.771978389,75.09231145869983],[510648.26552530023,6651116.2569209,71.26166589569984],[510649.5928580111,6651116.916457793,68.81994054909241],[510648.26201159507,6651116.908798631,70.64126532269984],[510648.2861508822,6651112.430373968,75.77494892969982],[510648.28201175586,6651113.198282547,74.97015833669982],[510648.2659493608,6651116.17824735,71.68599301569982],[510660.03104468284,6651103.590091781,70.70090528189651],[510648.2797381846,6651113.6200852785,74.80304357969982],[510648.26212457096,6651116.887838849,71.10685600969981],[510648.2835587848,6651112.911271052,75.68578427769984],[510648.26660777227,6651116.056096002,72.11230336669982],[510649.6233218942,6651111.938764268,75.2162078960924],[510648.2775263798,6651114.03042886,74.59076577069982],[510660.03079822694,6651103.6110504195,71.1664959688965],[510648.2675085293,6651115.888983673,72.53411222569983],[510648.28160465776,6651113.27380914,75.58668878369981],[510648.26247786183,6651116.822294813,71.58412696169982],[510648.27541466727,6651114.422202865,74.33455264769982],[510648.2686527175,6651115.676708948,72.94446176869982],[510660.02387678274,6651104.199650858,70.70090528189651],[510648.2739190259,6651114.6996806925,74.11513364169983],[510648.27003371925,6651115.420499547,73.33624146269982],[510648.27251523745,6651114.960117582,73.87416399569982],[510648.27121639886,6651115.201083728,73.61372332269983],[510649.59658873524,6651116.306870329,70.6487442090924],[510648.2796601684,6651113.634559189,75.45906602469982],[510649.6207724433,6651112.355335754,75.17846503709241],[510648.2630896891,6651116.708785978,72.06702798169984],[510649.5966165533,6651116.302324953,70.8525654930924],[510660.0300275265,6651103.676590877,71.64376692089652],[510649.6231555913,6651111.965937588,75.8252030560924],[510648.2777429203,6651113.990255317,75.30257473269982],[510660.0236593216,6651104.218143773,71.11172059389651],[510648.2637259991,6651116.590734993,72.42873396669982],[510649.61817557603,6651112.7796549285,75.09979034409241],[510648.27587114624,6651114.337514919,75.11736583069982],[510648.26451758243,6651116.44387704,72.78649181269982],[510649.5968475383,6651116.2645828,71.26914478109241],[510648.27406320797,6651114.67293143,74.90411349569982],[510649.5928580111,6651116.916457793,70.64874420809241],[510648.26546453364,6651116.268194579,73.13694802769982],[510649.6202662136,6651112.438051941,75.7824278150924],[510648.27233705163,6651114.993175397,74.66402504869981],[510660.02297929185,6651104.27597359,71.53284202189651],[510649.61556657136,6651113.205957295,74.97763722209241],[510648.2665641708,6651116.064185151,73.47669305469984],[510660.02869283134,6651103.790093511,72.12666794089651],[510648.27070964884,6651115.295098167,74.39882732369983],[510648.2678109425,6651115.832878673,73.80236016469982],[510648.26919645845,6651115.575831794,74.11072897269982],[510649.59732902475,6651116.18590958,71.69347190109241],[510649.61298511573,6651113.627758255,74.81052246509242],[510649.5929862861,6651116.895498098,71.1143348950924],[510649.61732309737,6651112.918947006,75.69326316309241],[510649.5980765976,6651116.063758746,72.1197822520924],[510660.0218016197,6651104.376122974,71.95893115689651],[510660.0273047272,6651103.908138051,72.48837392589651],[510649.6104737907,6651114.038100113,74.5982446560924],[510649.5990993341,6651115.896647119,72.5415911110924],[510649.6151043445,6651113.281483571,75.5941676690924],[510649.59338741924,6651116.829954336,71.59160584709242],[510649.60807611246,6651114.42987247,74.34203153309241],[510649.600398467,6651115.684373286,72.95194065409241],[510649.60637793306,6651114.707349134,74.1226125270924],[510649.60196648247,6651115.42816496,73.3437203480924],[510649.60478404514,6651114.96778493,73.8816428810924],[510649.60330931924,6651115.208750063,73.6212022080924],[510649.61289653456,6651113.642232105,75.46654491009241],[510660.0255778959,6651104.054987984,72.84613177189651],[510649.59408209944,6651116.71644598,72.07450686709241],[510660.0201022544,6651104.5206371965,72.3838376608965],[510649.61071965494,6651113.997926737,75.31005361809243],[510649.59480457794,6651116.598395491,72.43621285209241],[510649.60859440727,6651114.345184882,75.12484471609241],[510649.59570335655,6651116.451538155,72.79397069809241],[510660.0235121314,6651104.230660852,73.1965879868965],[510649.60654164,6651114.680599985,74.9115923810924],[510649.59677854273,6651116.275856432,73.1444269130924],[510649.6045817295,6651115.000842605,74.6715039340924],[510660.0178710146,6651104.710382091,72.80080436289651],[510649.59802709153,6651116.071847861,73.48417194009241],[510649.60273394577,6651115.3027641075,74.4063062090924],[510649.59944269975,6651115.840542354,73.8098390500924],[510649.60101584066,6651115.583496555,74.1182078580924],[510660.02111328376,6651104.434659139,73.53633301389651],[510660.0151137835,6651104.944857352,73.20275327989651],[510660.01839346334,6651104.665952987,73.86200012389651],[510660.0118536976,6651105.222095443,73.5826340818965],[510660.0153709742,6651104.922985829,74.1703689318965],[510660.009102269,6651105.456077259,73.8490403968965],[510665.5542208707,6651103.663346096,68.89585792190336],[510660.01206996397,6651105.203704126,74.45846728289652],[510660.0061132462,6651105.710264113,74.0967501368965],[510660.00851980096,6651105.505610411,74.7236650078965],[510665.54521983647,6651104.272880859,68.89585792190336],[510665.54521983647,6651104.272880859,69.02585792190335],[510660.0018059852,6651106.076554105,74.39419260689651],[510660.0047542079,6651105.82583689,74.9637534548965],[510659.9971993053,6651106.468306715,74.6504057298965],[510665.5542208707,6651103.663346096,70.72466158090337],[510660.0008102083,6651106.161235085,75.17700578989651],[510665.55391138565,6651103.684303897,71.19025226790335],[510659.99237427465,6651106.878627889,74.86268353889652],[510659.9967269516,6651106.5084757265,75.36221469189653],[510665.54521983647,6651104.272880859,70.72466158090337],[510665.55294358457,6651103.749841741,71.66752321990336],[510665.54494676145,6651104.291373038,71.13547689290336],[510659.9925444938,6651106.864152429,75.51870598389651],[510659.9874145015,6651107.300407588,75.02979829589651],[510665.5440928193,6651104.349200548,71.55659832090335],[510665.55126755167,6651103.86333985,72.15042423990337],[510659.9883026095,6651107.22488278,75.6463287428965],[510659.98240179825,6651107.726688467,75.15195141789651],[510665.5426139668,6651104.449345936,71.98268745590336],[510665.5495244508,6651103.981379679,72.51213022490336],[510659.9840397004,6651107.587401071,75.74542423689651],[510659.97741241456,6651108.150986253,75.23062611089651],[510665.54735599604,6651104.128223756,72.86988807090336],[510665.54048000224,6651104.593854395,72.40759395990337],[510659.97251413245,6651108.5675367415,75.2683689698965],[510659.97838506557,6651108.068271895,75.8345888888965],[510665.5447619284,6651104.303889617,73.22034428590335],[510665.5376781404,6651104.783591721,72.82456066190335],[510659.97283367923,6651108.54036245,75.8773641298965],[510665.54174959444,6651104.507879768,73.56008931290337],[510669.92389173683,6651103.733073057,68.91265022951784],[510665.5342157692,6651105.0180576295,73.22650957890335],[510665.5383342014,6651104.73916439,73.88575642290336],[510669.9134404153,6651104.342584677,68.91265022951784],[510665.530121942,6651105.295284663,73.60639038090335],[510669.9134404153,6651104.342584677,69.04265022951783],[510659.95193703263,6651110.317415762,75.2683689698965],[510665.5345387343,6651104.99618698,74.19412523090335],[510665.52666685707,6651105.529257147,73.87279669590336],[510659.8804250786,6651116.3988008415,68.87210162289652],[510659.8804250786,6651116.3988008415,69.0021016228965],[510665.53039351676,6651105.27689408,74.48222358190336],[510665.5229134153,6651105.783433863,74.12050643590335],[510669.92389173683,6651103.733073057,70.74145388851784],[510659.8732571785,6651117.008359918,68.87210162289652],[510665.5259354275,6651105.578788322,74.74742130690335],[510669.92353238614,6651103.754030063,71.20704457551783],[510665.5175046061,6651106.149709243,74.41794890590336],[510669.9134404153,6651104.342584677,70.74145388851784],[510659.93178770127,6651112.030917296,75.2683689698965],[510665.52120681363,6651105.899002029,74.98750975390335],[510669.9224086487,6651103.819565418,71.68431552751784],[510669.9131233412,6651104.361076154,71.15226920051784],[510659.88042505103,6651116.39880318,70.7009052828965],[510659.9268894192,6651112.447467786,75.23062611089651],[510665.511719804,6651106.541446228,74.67416202890335],[510659.8804784981,6651116.394258033,70.9047265668965],[510665.5162541672,6651106.234386846,75.20076208890337],[510659.9314681821,6651112.058089248,75.8773641298965],[510669.9121318081,6651104.418901469,71.57339062851783],[510669.92046256573,6651103.9330592165,72.16721654751784],[510659.9219000355,6651112.871765571,75.15195141789651],[510659.8809222916,6651116.356517783,71.32130585489651],[510659.8732571785,6651117.008359918,70.70090528189651],[510665.50566080975,6651106.9517510375,74.88643983790335],[510659.9259167957,6651112.530179803,75.8345888888965],[510659.9168873323,6651113.29804645,75.02979829589651],[510665.51112664957,6651106.5816136375,75.38597099090336],[510669.910414676,6651104.519043056,71.99947976351784],[510669.9184386086,6651104.051094566,72.52892253251784],[510659.8818473756,6651116.27784853,71.74563297489651],[510659.87350363436,6651116.987401279,71.1664959688965],[510659.9119275591,6651113.71982615,74.86268353889652],[510659.8832836939,6651116.155703852,72.1719433258965],[510659.9202621609,6651113.011050627,75.74542423689651],[510669.9159207626,6651104.197933067,72.88668037851784],[510665.50587456115,6651106.937276154,75.54246228290336],[510665.4994326136,6651107.373513913,75.05355459490336],[510659.9071025285,6651114.130147324,74.6504057298965],[510659.88524868654,6651115.988600648,72.5937521848965],[510669.90793687745,6651104.663546028,72.42438626751783],[510659.91599925177,6651113.373568919,75.6463287428965],[510659.8742743348,6651116.921860822,71.64376692089652],[510659.9024958486,6651114.521899933,74.39419260689651],[510659.8877447217,6651115.776337514,73.00410172789651],[510659.8992331217,6651114.79936261,74.17477360089651],[510659.8907573635,6651115.520142104,73.3958814218965],[510659.89617077104,6651115.0597852785,73.9338039548965],[510659.8933373674,6651115.300738267,73.67336328189651],[510659.91175736743,6651113.73429927,75.51870598389651],[510659.87560902996,6651116.808358188,72.12666794089651],[510665.50054784823,6651107.297992116,75.67008504190335],[510669.912908727,6651104.373592258,73.23713659351785],[510665.493137951,6651107.79977779,75.17570771690336],[510659.90757490974,6651114.089975973,75.36221469189653],[510669.90468356706,6651104.853276151,72.84135296951783],[510659.8769971341,6651116.6903136475,72.48837392589651],[510659.903491653,6651114.4372166125,75.17700578989651],[510659.8787239654,6651116.543463715,72.84613177189651],[510665.4951947337,6651107.660495948,75.76918053590337],[510659.89954765333,6651114.772614809,74.9637534548965],[510659.8807897299,6651116.367790846,73.1965879868965],[510669.90941103204,6651104.577574664,73.57688162051784],[510665.4868725716,6651108.22405865,75.25438240990336],[510659.8957820603,6651115.092841287,74.7236650078965],[510659.8831885776,6651116.163792559,73.53633301389651],[510659.8922318973,6651115.394747573,74.45846728289652],[510659.8859083979,6651115.932498712,73.86200012389651],[510659.88893088716,6651115.67546587,74.1703689318965],[510669.9006633228,6651105.087733156,73.24330188651783],[510665.48072159244,6651108.640592525,75.29212526890335],[510665.4880939705,6651108.141347594,75.85834518790337],[510669.90544533543,6651104.808850504,73.90254873051784],[510669.8959098797,6651105.364949665,73.62318268851784],[510665.48112286074,6651108.613419318,75.90112042890335],[510669.9010383256,6651105.065863336,74.21091753851783],[510669.891898096,6651105.598913264,73.88958900351784],[510669.89622521185,6651105.34655978,74.49901588951784],[510669.88753988256,6651105.8530803295,74.13729874351785],[510669.8910488151,6651105.64844256,74.76421361451783],[510665.4548820611,6651110.390401749,75.29212526890335],[510669.8812595816,6651106.219341805,74.43474121351784],[510665.3650814872,6651116.471544266,68.89585792190336],[510669.8855583056,6651105.968644109,75.00430206151785],[510665.3650814872,6651116.471544266,69.02585792190335],[510669.87454270595,6651106.611063915,74.69095433651783],[510669.87980766624,6651106.304016193,75.21755439651784],[510665.356080453,6651117.081079029,68.89585792190336],[510676.9246202175,6651103.866463508,68.93586572512353],[510669.8675074592,6651107.021353147,74.90323214551783],[510669.8738539799,6651106.651229801,75.40276329851784],[510676.9118453645,6651104.475930858,68.93586572512353],[510665.4295796968,6651112.103834938,75.29212526890335],[510676.9118453645,6651104.475930858,69.06586572512353],[510669.86775565124,6651107.006878814,75.55925459051784],[510669.860275748,6651107.443100009,75.07034690251785],[510665.36508145276,6651116.471546603,70.72466158190335],[510665.42342871753,6651112.520368813,75.25438240990336],[510665.36514856847,6651116.467001638,70.92848286590336],[510665.429178463,6651112.131005806,75.90112042890335],[510669.86157067417,6651107.367581081,75.68687734951783],[510665.4171633382,6651112.944649675,75.17570771690336],[510669.8529668608,6651107.869347701,75.19250002451786],[510665.3657058586,6651116.429262893,71.34506215390337],[510665.356080453,6651117.081079029,70.72466158090337],[510676.9246202175,6651103.866463508,70.76466938412354],[510665.42220735323,6651112.603077531,75.85834518790337],[510665.41086867556,6651113.370913551,75.05355459490336],[510665.3668675256,6651116.350596778,71.76938927390336],[510669.85535504174,6651107.730071149,75.78597284351784],[510669.84569197515,6651108.293612454,75.27117471751784],[510665.3563899381,6651117.060121227,71.19025226790335],[510665.4046404794,6651113.792676427,74.88643983790335],[510665.368671171,6651116.228456973,72.19569962490337],[510665.41510659,6651113.0839291755,75.76918053590337],[510676.9241809761,6651103.887418992,71.23026007112352],[510665.3985814852,6651114.202981235,74.67416202890335],[510665.371138695,6651116.061360433,72.61750848390336],[510676.9118453645,6651104.475930858,70.76466938412354],[510665.3573577392,6651116.994583382,71.66752321990336],[510665.4097534755,6651113.446433008,75.67008504190335],[510669.8385499224,6651108.710130515,75.30891757651783],[510669.84711017134,6651108.210904537,75.87513749551783],[510665.39279668307,6651114.59471822,74.41794890590336],[510665.3742730716,6651115.849105765,73.02785802690336],[510665.3886995396,6651114.87216983,74.19852989990335],[510665.3780561728,6651115.592920573,73.41963772090337],[510665.3848540167,6651115.132582111,73.95756025390335],[510665.3812959923,6651115.373525488,73.69711958090335],[510676.92280740995,6651103.952949587,71.70753102312354],[510665.4044267626,6651113.807148971,75.54246228290336],[510676.9114577986,6651104.49442099,71.17548469612353],[510665.35903377214,6651116.881085275,72.15042423990337],[510665.3991746742,6651114.162811486,75.38597099090336],[510665.36077687296,6651116.763045445,72.51213022490336],[510669.83901584474,6651108.682958338,75.91791273651783],[510665.39404715656,6651114.510038278,75.20076208890337],[510665.3629453277,6651116.616201368,72.86988807090336],[510676.9102458284,6651104.552242105,71.59660612412353],[510676.920428675,6651104.066435142,72.19043204312354],[510665.3890945101,6651114.845423095,74.98750975390335],[510665.36553939537,6651116.440535507,73.22034428590335],[510665.3843658962,6651115.165636801,74.74742130690335],[510665.3685517293,6651116.236545356,73.56008931290337],[510665.379907807,6651115.467531043,74.48222358190336],[510665.37196712237,6651116.005260734,73.88575642290336],[510665.37576258945,6651115.7482381435,74.19412523090335],[510676.90814694465,6651104.652376419,72.02269525912354],[510676.91795475304,6651104.184461919,72.55213802812354],[510676.914877141,6651104.331289752,72.90989587412354],[510676.9051182834,6651104.796868893,72.44760176312353],[510669.80854700884,6651110.459873303,75.30891757651783],[510669.7042773602,6651116.540784936,68.91265022951784],[510676.9111954715,6651104.506936187,73.26035208912353],[510669.7042773602,6651116.540784936,69.04265022951783],[510676.90114169894,6651104.986585236,72.86456846512353],[510676.9069201711,6651104.710903775,73.60009711612354],[510669.6938260387,6651117.150296558,68.91265022951784],[510676.89622767654,6651105.221025213,73.26651738212355],[510676.90207282326,6651104.942162817,73.92576422612353],[510669.779167813,6651112.173241438,75.30891757651783],[510676.89041745075,6651105.498221584,73.64639818412354],[510676.8966860496,6651105.199156981,74.23413303412353],[510669.7042773201,6651116.540787275,70.74145388951783],[510669.7720257603,6651112.589759498,75.27117471751784],[510669.7043552498,6651116.536242481,70.94527517351783],[510676.88551376964,6651105.73216819,73.91280449912352],[510669.7787019307,6651112.200411274,75.91791273651783],[510669.76475087466,6651113.014024251,75.19250002451786],[510676.89080288727,6651105.479833035,74.52223138512353],[510669.7050023331,6651116.49850517,71.36185446151784],[510669.6938260387,6651117.150296558,70.74145388851784],[510676.8801866408,6651105.9863167945,74.16051423912354],[510669.77060760424,6651112.672465077,75.87513749551783],[510669.75744198746,6651113.440271944,75.07034690251785],[510669.7063511731,6651116.41984204,71.78618158151784],[510682.7717159758,6651103.998336429,68.95177490066979],[510669.6941853894,6651117.129339551,71.20704457551783],[510676.88447567704,6651105.781693889,74.78742911012354],[510669.75021027616,6651113.862018806,74.90323214551783],[510669.70844543003,6651116.297706873,72.21249193251784],[510669.7623627338,6651113.153298464,75.78597284351784],[510669.7431750294,6651114.272308037,74.69095433651783],[510669.7113105327,6651116.130616677,72.63430079151783],[510676.87251010706,6651106.352551666,74.45795670912354],[510669.69530912687,6651117.063804195,71.68431552751784],[510669.75614710135,6651113.515788534,75.68687734951783],[510669.7364581539,6651114.664030148,74.43474121351784],[510669.7149499342,6651115.918370069,73.04465033451785],[510682.7570004802,6651104.607760011,68.95177490066979],[510669.73170085996,6651114.941471224,74.21532220751783],[510669.71934258577,6651115.662194603,73.43643002851783],[510669.72723572917,6651115.201873618,73.97435256151783],[510676.8777645209,6651106.101872179,75.02751755712355],[510669.7231044197,6651115.442807847,73.71391188851783],[510682.7570004802,6651104.607760011,69.0817749006698],[510669.7499621243,6651113.8764908,75.55925459051784],[510669.69725520985,6651116.950310396,72.16721654751784],[510669.7438637956,6651114.232139813,75.40276329851784],[510669.69927916693,6651116.832275048,72.52892253251784],[510676.86429993977,6651106.744245323,74.71416983212355],[510669.7379101093,6651114.579353421,75.21755439651784],[510669.70179701294,6651116.685436548,72.88668037851784],[510676.8707354028,6651106.437219903,75.24076989212354],[510669.7321594699,6651114.914725506,75.00430206151785],[510669.7048090485,6651116.509777355,73.23713659351785],[510669.7266689604,6651115.2349270545,74.76421361451783],[510669.7083067435,6651116.305794949,73.57688162051784],[510669.72149256367,6651115.536809834,74.49901588951784],[510669.7122724401,6651116.074519108,73.90254873051784],[510669.7166794499,6651115.817506276,74.21091753851783],[510682.7717159758,6651103.998336429,70.78057855966979],[510676.85570062115,6651107.154504753,74.92644764112353],[510676.8634580965,6651106.784408291,75.42597879412354],[510682.77121000877,6651104.019290409,71.24616924666978],[510676.8468611602,6651107.576220981,75.09356239812355],[510676.85600399104,6651107.140031472,75.58247008612354],[510682.7570004802,6651104.607760011,70.78057855966979],[510682.7696277826,6651104.084816299,71.72344019866979],[510682.75655403873,6651104.626248816,71.19139387166979],[510676.84844397375,6651107.500707538,75.71009284512353],[510676.8379273656,6651108.002437714,75.21571552012355],[510682.7551579568,6651104.684065778,71.61251529966978],[510682.76688769134,6651104.198293704,72.20634121866979],[510676.84084648546,6651107.863171278,75.80918833912354],[510676.8290351318,6651108.426671649,75.29439021312353],[510682.75274022925,6651104.7841929,72.03860443466981],[510682.76403795293,6651104.316312004,72.56804720366979],[510676.8203052621,6651108.843159456,75.33213307212353],[510676.8307686204,6651108.343969739,75.89835299112353],[510682.76049281744,6651104.463129293,72.92580504966979],[510682.7492514806,6651104.928675001,72.46351093866978],[510676.8208747682,6651108.815989254,75.94112823212353],[510682.7562518612,6651104.638763113,73.2762612646698],[510682.7446708086,6651105.118377716,72.88047764066978],[510682.75132709515,6651104.842716054,73.61600629166979],[510682.7390102914,6651105.352800856,73.2824265576698],[510676.7836321189,6651110.592775151,75.33213307212353],[510682.74574338115,6651105.073958489,73.94167340166979],[510676.6561813048,6651116.673245096,68.93586572512353],[510682.7323174276,6651105.629977323,73.66230735966978],[510676.6561813048,6651116.673245096,69.06586572512353],[510682.73953829653,6651105.330934196,74.25004220966979],[510682.7266688227,6651105.863907128,73.92871367466978],[510676.64340645174,6651117.282712445,68.93586572512353],[510682.7327614163,6651105.611590094,74.53814056066979],[510682.7205324437,6651106.118037479,74.17642341466978],[510682.7254730324,6651105.913429269,74.80333828566978],[510676.747721358,6651112.306018835,75.33213307212353],[510682.711689759,6651106.484246051,74.47386588466979],[510676.65618125576,6651116.673247434,70.76466938512353],[510676.7389914884,6651112.722506641,75.29439021312353],[510676.65627651074,6651116.66870297,70.96849066912353],[510682.7177423767,6651106.233584566,75.04342673266979],[510676.74715190096,6651112.333186698,75.94112823212353],[510676.73009925446,6651113.146740579,75.21571552012355],[510676.6570674532,6651116.630968399,71.38506995712353],[510682.70223237574,6651106.8759115795,74.73007900766979],[510676.64340645174,6651117.282712445,70.76466938412354],[510676.73725804867,6651112.805206212,75.89835299112353],[510682.7096454574,6651106.568908208,75.25667906766981],[510676.72116545995,6651113.57295731,75.09356239812355],[510676.6587161665,6651116.552310984,71.80939707712353],[510676.64384569303,6651117.26175696,71.23026007112352],[510676.712325999,6651113.994673539,74.92644764112353],[510676.6612760173,6651116.430184687,72.23570742812353],[510676.72718018363,6651113.286004675,75.80918833912354],[510682.69232672494,6651107.286141547,74.94235681666979],[510676.7037266803,6651114.404932967,74.71416983212355],[510682.70126264717,6651106.916071664,75.44188796966979],[510676.6647780878,6651116.263106628,72.65751628712353],[510676.6452192592,6651117.196226364,71.70753102312354],[510676.7195826955,6651113.648468414,75.71009284512353],[510676.6955165131,6651114.7966266265,74.45795670912354],[510676.66922659904,6651116.0508754365,73.06786583012355],[510690.1689726671,6651104.19186548,68.96736160139059],[510676.68970158044,6651115.07404755,74.23853770312353],[510676.6745958222,6651115.794718578,73.45964552412353],[510676.68424376444,6651115.334431029,73.99756805712353],[510676.67919398483,6651115.575347758,73.73712738412355],[510676.7120226781,6651114.009144481,75.58247008612354],[510676.6475979941,6651117.082740809,72.19043204312354],[510682.68214445136,6651107.70782749,75.1094715736698],[510682.6926761801,6651107.271669304,75.5983792616698],[510676.70456857275,6651114.364767661,75.42597879412354],[510676.6500719161,6651116.9647140335,72.55213802812354],[510676.6972912663,6651114.711956049,75.24076989212354],[510690.1518020329,6651104.801224829,68.96736160139059],[510676.65314952814,6651116.8178862,72.90989587412354],[510690.1518020329,6651104.801224829,69.09736160139059],[510676.69026214833,6651115.047303773,75.02751755712355],[510676.6568311977,6651116.642239766,73.26035208912353],[510682.68396771187,6651107.632319469,75.7260020206698],[510676.6835509921,6651115.367482063,74.78742911012354],[510676.661106498,6651116.438272176,73.60009711612354],[510682.67185351375,6651108.134013615,75.2316246956698],[510676.6772237819,6651115.669342916,74.52223138512353],[510676.6659538459,6651116.207013135,73.92576422612353],[510676.67134061956,6651115.950018971,74.23413303412353],[510682.6752160805,6651107.994757179,75.82509751466979],[510682.6616104506,6651108.558217084,75.31029938866979],[510690.1689726671,6651104.19186548,70.79616526039061],[510682.6515544164,6651108.97467498,75.34804224766978],[510682.6636072755,6651108.475521113,75.9142621666698],[510690.16838228446,6651104.212817251,71.26175594739058],[510690.1518020329,6651104.801224829,70.79616526039061],[510682.65221043676,6651108.94750673,75.95703740766979],[510690.16653607914,6651104.278336233,71.7390268993906],[510690.15128110704,6651104.819711686,71.20698057239059],[510690.1496521023,6651104.877522553,71.62810200039058],[510690.16333882994,6651104.391801679,72.22192791939061],[510682.6093102142,6651110.724165028,75.34804224766978],[510690.14683100017,6651104.977639122,72.0541911353906],[510690.16001364024,6651104.509807539,72.5836339043906],[510682.4624982014,6651116.804198307,68.95177490066979],[510682.4624982014,6651116.804198307,69.0817749006698],[510690.15587703296,6651104.6566093555,72.9413917503906],[510690.1427601874,6651105.122105994,72.4790976393906],[510693.8149386678,6651104.298225386,68.97317771938432],[510682.4477827058,6651117.413621889,68.95177490066979],[510690.15092851414,6651104.832224664,73.29184796539059],[510690.13741527445,6651105.311788716,72.89606434139058],[510693.7965579429,6651104.907549433,68.97317771938432],[510690.1451820983,6651105.0361561095,73.63159299239061],[510693.7965579429,6651104.907549433,69.1031777193843],[510690.13081035455,6651105.546187148,73.2980132583906],[510682.56794420857,6651112.437285677,75.34804224766978],[510682.46249814495,6651116.804200646,70.78057856066978],[510690.1386667954,6651105.26737417,73.95726010239059],[510682.55788817455,6651112.853743574,75.31029938866979],[510682.4626078702,6651116.799656509,70.98439984466978],[510682.5672882447,6651112.464451589,75.95703740766979],[510690.1230008509,6651105.823334401,73.67789406039059],[510682.5476451112,6651113.277947045,75.2316246956698],[510682.46351896564,6651116.761924649,71.40097913266979],[510693.8149386678,6651104.298225386,70.80198137838431],[510690.1314264522,6651105.524322793,74.26562891039059],[510682.4477827058,6651117.413621889,70.78057855966979],[510682.5558914061,6651112.936437205,75.9142621666698],[510682.5373541738,6651113.704133168,75.1094715736698],[510690.1164098307,6651106.057239551,73.9443003753906],[510682.4654181369,6651116.683272881,71.82530625266979],[510693.8143066783,6651104.319175944,71.2675720653843],[510682.4482886728,6651117.392667909,71.24616924666978],[510682.5271719002,6651114.12581911,74.94235681666979],[510682.46836685756,6651116.561155355,72.2516166036698],[510690.12351891474,6651105.80494911,74.5537272613906],[510693.7965579429,6651104.907549433,70.80198137838431],[510682.5442826011,6651113.417201139,75.82509751466979],[510690.10924965603,6651106.311343118,74.19201011539059],[510682.5172662492,6651114.536049078,74.73007900766979],[510682.4724009316,6651116.3940892955,72.67342546266978],[510682.4498708989,6651117.327142019,71.72344019866979],[510682.53553096973,6651113.779638848,75.7260020206698],[510682.50780886604,6651114.927714606,74.47386588466979],[510682.4775252212,6651116.181873344,73.08377500566979],[510693.8123303626,6651104.38469113,71.74484301738433],[510682.50111058046,6651115.205115609,74.25444687866978],[510693.796000305,6651104.92603522,71.21279669038431],[510682.4837100891,6651115.925734882,73.4755546996698],[510682.49482366134,6651115.465480388,74.01347723266979],[510682.48900676396,6651115.706379815,73.7530365596698],[510690.1150145342,6651106.106756472,74.81892498639058],[510682.5268225015,6651114.140289015,75.5983792616698],[510682.45261099027,6651117.2136646155,72.20634121866979],[510682.51823603443,6651114.4958866555,75.44188796966979],[510682.45546072855,6651117.095646315,72.56804720366979],[510690.0989316545,6651106.677513091,74.4894525853906],[510693.7942564971,6651104.983842739,71.63391811838432],[510693.8089077892,6651104.498150002,72.22774403738431],[510682.5098532241,6651114.84305011,75.25667906766981],[510682.45900586416,6651116.948829024,72.92580504966979],[510690.1059940932,6651106.426878026,75.05901343339059],[510682.5017563049,6651115.178373751,75.04342673266979],[510682.46324682026,6651116.773195205,73.2762612646698],[510682.4940256492,6651115.49852905,74.80333828566978],[510682.46817158634,6651116.569242263,73.61600629166979],[510682.48673726525,6651115.800368224,74.53814056066979],[510682.47375530045,6651116.337999829,73.94167340166979],[510682.47996038507,6651116.081024122,74.25004220966979],[510693.79123657936,6651105.083953507,72.06000725338431],[510693.8053482585,6651104.616149026,72.58945002238431],[510690.087896398,6651107.06913734,74.74566570839059],[510690.0965462809,6651106.762166326,75.2722657683906],[510693.80092012626,6651104.762942339,72.94720786838431],[510693.7868788784,6651105.22841201,72.4849137573843],[510690.0763380847,6651107.479324068,74.95794351739059],[510690.0867648795,6651107.10929319,75.4574746703906],[510693.7956228634,6651104.9385474725,73.2976640833843],[510693.78115728573,6651105.418083744,72.90188045938432],[510690.06445699686,6651107.900965568,75.1250582743906],[510690.07674584317,6651107.464853351,75.6139659623906],[510693.7894714721,6651105.142467104,73.63740911038431],[510693.7740868878,6651105.6524685975,73.3038293763843],[510690.06658445083,6651107.825465506,75.74158872139058],[510690.0524491156,6651108.327106771,75.2472113963906],[510693.7824970068,6651105.37367177,73.96307622038431],[510690.05637269415,6651108.187865014,75.84068421539061],[510690.0404970959,6651108.751265531,75.32588608939061],[510693.7657270137,6651105.9295997955,73.6837101783843],[510693.7747464045,6651105.630605509,74.2714450283843],[510690.0287633094,6651109.167679534,75.3636289483906],[510690.04282707185,6651108.668578276,75.92984886739059],[510693.7586714951,6651106.163491393,73.95011649338433],[510693.7662815879,6651105.911215569,74.55954337938432],[510693.7510067111,6651106.417580241,74.1978262333843],[510690.0295287805,6651109.140514147,75.97262410839059],[510693.7571778659,6651106.213005447,74.8247411043843],[510693.73996155435,6651106.783729001,74.49526870338431],[510699.9853135196,6651104.494739295,68.98021260000013],[510693.7475217143,6651106.533108455,75.0648295513843],[510689.9794710692,6651110.9169851905,75.3636289483906],[510693.7281485943,6651107.1753305625,74.7514818263843],[510699.96488485625,6651105.103998121,68.98021260000013],[510699.96488485625,6651105.103998121,69.11021260000012],[510693.7374080728,6651106.868377331,75.27808188638431],[510689.8081648865,6651116.996377645,68.96736160139059],[510689.8081648865,6651116.996377645,69.09736160139059],[510693.7157757155,6651107.58549353,74.96375963538432],[510693.72693733266,6651107.215484087,75.46329078838433],[510689.7909942523,6651117.605736995,68.96736160139059],[510699.9853135196,6651104.494739295,70.80901625900015],[510693.7030573146,6651108.007110601,75.13087439238431],[510693.7162122104,6651107.5710236505,75.61978208038431],[510699.9846111152,6651104.51568761,71.27460694600012],[510693.7053346998,6651107.931614913,75.7474048393843],[510699.96488485625,6651105.103998121,70.80901625900015],[510689.9312035441,6651112.62992528,75.3636289483906],[510693.6902031847,6651108.433227119,75.25302751438431],[510689.8081648206,6651116.996379984,70.79616526139058],[510699.98241460306,6651104.581195785,71.75187789800013],[510699.96426508774,6651105.122481928,71.21983157100013],[510689.9194697576,6651113.046339281,75.32588608939061],[510693.6944032752,6651108.293993428,75.84650033338431],[510689.80829285254,6651116.991836326,70.9999865453906],[510693.6774088532,6651108.857361308,75.33170220738431],[510689.9304381389,6651112.657088327,75.97262410839059],[510689.9075177379,6651113.470498042,75.2472113963906],[510689.80935595545,6651116.954108442,71.4165658333906],[510699.9623269887,6651105.18028326,71.64095299900012],[510689.7909942523,6651117.605736995,70.79616526039061],[510699.97861069423,6651104.694642511,72.23477891800015],[510693.66484813474,6651109.273751187,75.3694450663843],[510693.6799030329,6651108.774678842,75.9356649853843],[510689.9171398475,6651113.129024197,75.92984886739059],[510689.89550985664,6651113.8966392465,75.1250582743906],[510689.8115719851,6651116.875464965,71.8408929533906],[510689.7915846349,6651117.584785224,71.26175594739058],[510699.95897059864,6651105.280383312,72.06704213400013],[510699.9746545689,6651104.812628905,72.59648490300013],[510689.88362876873,6651114.318280744,74.95794351739059],[510689.8150126714,6651116.75336031,72.26720330439059],[510689.90359422524,6651113.60973746,75.84068421539061],[510693.6656675519,6651109.246587373,75.97844022638431],[510689.87207045546,6651114.728467474,74.74566570839059],[510689.8197197918,6651116.586311859,72.6890121633906],[510689.7934308403,6651117.51926624,71.7390268993906],[510689.89338246855,6651113.97213697,75.74158872139058],[510689.82569901977,6651116.374118274,73.0993617063906],[510689.861035199,6651115.120091722,74.4894525853906],[510699.9697330642,6651104.9594065035,72.95424274900013],[510689.85321936896,6651115.397463486,74.2700335793906],[510689.8329157733,6651116.118006809,73.49114140039059],[510689.84588353796,6651115.657800825,74.02906393339059],[510699.9541273726,6651105.424826352,72.49194863800014],[510689.8390961473,6651115.898674862,73.7686232603906],[510689.88322107634,6651114.332749123,75.6139659623906],[510689.79662808945,6651117.405800796,72.22192791939061],[510689.8732020399,6651114.688309285,75.4574746703906],[510689.79995327914,6651117.2877949355,72.5836339043906],[510699.96384559234,6651105.134992841,73.30469896400012],[510689.8634206385,6651115.035436149,75.2722657683906],[510689.8040898864,6651117.140993119,72.9413917503906],[510699.9477682932,6651105.6144777825,72.90891534000012],[510689.8539728262,6651115.37072445,75.05901343339059],[510689.80903840525,6651116.965377811,73.29184796539059],[510689.81478482106,6651116.761446366,73.63159299239061],[510689.8449523852,6651115.690846002,74.81892498639058],[510689.821300124,6651116.530228306,73.95726010239059],[510689.83644800464,6651115.992653363,74.5537272613906],[510689.8285404672,6651116.273279681,74.26562891039059],[510693.6120820515,6651111.022955503,75.3694450663843],[510699.9570088271,6651105.338890645,73.64444399100014],[510699.93991012766,6651105.848837548,73.31086425700013],[510693.42870316224,6651117.1019957755,68.97317771938432],[510693.42870316224,6651117.1019957755,69.1031777193843],[510699.94925728295,6651105.570070563,73.97011110100013],[510693.41032243724,6651117.711319824,68.97317771938432],[510699.93061881553,6651106.12593908,73.69074505900012],[510699.9406431262,6651105.8269767985,74.27847990900013],[510699.9227771871,6651106.359805644,73.95715137400013],[510699.9312351791,6651106.107556822,74.56657826000014],[510693.5604128998,6651112.735796362,75.3694450663843],[510699.9142584104,6651106.613867291,74.20486111400012],[510693.42870309163,6651117.101998114,70.8019813793843],[510693.54785218136,6651113.152186241,75.33170220738431],[510693.4288401466,6651117.09745472,71.0058026633843],[510699.9211171412,6651106.409314396,74.83177598500012],[510693.5595935532,6651112.762957836,75.97844022638431],[510693.53505784983,6651113.576320428,75.25302751438431],[510693.4299781711,6651117.059729021,71.42238195138431],[510699.9019826275,6651106.979976861,74.50230358400013],[510693.41032243724,6651117.711319824,70.80198137838431],[510693.5453580722,6651113.234866366,75.9356649853843],[510699.9103851233,6651106.729383141,75.07186443200013],[510693.5222037198,6651114.002436946,75.13087439238431],[510693.43235037423,6651116.9810901,71.84670907138431],[510693.4109544268,6651117.690369266,71.2675720653843],[510693.5094853191,6651114.424054019,74.96375963538432],[510693.43603354093,6651116.858992517,72.27301942238431],[510699.8888534946,6651107.371536504,74.75851670700013],[510693.5308578298,6651113.7155517815,75.84650033338431],[510693.441072393,6651116.691953744,72.6948282813843],[510693.4971124401,6651114.834216987,74.7514818263843],[510699.8991446429,6651107.064616129,75.28511676700013],[510693.4129307424,6651117.624854079,71.74484301738433],[510693.51992640534,6651114.077930296,75.7474048393843],[510693.4474730036,6651116.479772453,73.10517782438431],[510693.48529948015,6651115.2258185465,74.49526870338431],[510693.4769328339,6651115.503174243,74.27584969738432],[510693.4551983539,6651116.223675824,73.4969575183843],[510693.46908001445,6651115.7634964995,74.0348800513843],[510693.4618142862,6651116.004356583,73.7744393783843],[510693.5090488947,6651114.438521558,75.61978208038431],[510693.4163533159,6651117.511395209,72.22774403738431],[510699.87510205776,6651107.781655566,74.97079451600013],[510699.88750727684,6651107.411685729,75.47032566900013],[510693.49832377234,6651114.794061122,75.46329078838433],[510693.41991284647,6651117.393396183,72.58945002238431],[510693.42434097873,6651117.2466028705,72.94720786838431],[510693.48785303225,6651115.141167878,75.27808188638431],[510693.4296382417,6651117.070997736,73.2976640833843],[510693.4777393907,6651115.476436754,75.0648295513843],[510693.435789633,6651116.867078106,73.63740911038431],[510693.4680832391,6651115.796539762,74.8247411043843],[510699.86096660176,6651108.203227508,75.13790927300013],[510699.8755871859,6651107.767187236,75.62681696100013],[510693.4427640982,6651116.63587344,73.96307622038431],[510693.4589795171,6651116.098329641,74.55954337938432],[510693.45051470055,6651116.3789397,74.2714450283843],[510699.8634977279,6651108.127739902,75.75443972000012],[510699.8466802941,6651108.629298414,75.26006239500013],[510699.8513483491,6651108.490079626,75.85353521400015],[510699.83246044745,6651109.053387202,75.33873708800014],[510699.81850024237,6651109.469732512,75.37647994700013],[510699.8352325228,6651108.9707135875,75.94269986600013],[510699.81941095716,6651109.442571606,75.98547510700013],[510699.7598550827,6651111.218749591,75.37647994700013],[510699.5560445367,6651117.297139156,68.98021260000013],[510710.4077648801,6651104.8738347655,68.98407466471348],[510699.5560445367,6651117.297139156,69.11021260000012],[510710.7005707575,6651104.885340882,68.9840376056788],[510699.53561587346,6651117.906397982,68.98021260000013],[510710.3838770205,6651105.48296777,68.98407466471348],[510710.3838770205,6651105.48296777,69.11407466471347],[510710.6765857161,6651105.494470069,68.9840376056788],[510710.6765857161,6651105.494470069,69.11403760567879],[510699.70242907223,6651112.931407105,75.37647994700013],[510699.5560444584,6651117.297141493,70.80901626000012],[510710.4077648801,6651104.8738347655,70.81287832371348],[510699.6884688672,6651113.347752413,75.33873708800014],[510699.55619678367,6651117.292598586,71.01283754400013],[510699.7015184359,6651112.958565671,75.98547510700013],[510710.7005707575,6651104.885340882,70.8128412646788],[510710.4069435372,6651104.894778755,71.27846901071347],[510699.6742490205,6651113.771841201,75.26006239500013],[510699.55746160424,6651117.254876926,71.42941683200014],[510699.53561587346,6651117.906397982,70.80901625900015],[510710.3838770205,6651105.48296777,70.81287832371348],[510699.68569687015,6651113.430423689,75.94269986600013],[510710.69974607317,6651104.906284741,71.2784319516788],[510699.5600981128,6651117.176246421,71.85374395200013],[510699.6599627128,6651114.197912107,75.13790927300013],[510710.4043750885,6651104.960273401,71.75573996271348],[510710.6765857161,6651105.494470069,70.8128412646788],[510710.3831523062,6651105.501447761,71.22369363571347],[510699.53631827777,6651117.8854496665,71.27460694600012],[510699.56419164955,6651117.054161909,72.28005430300013],[510699.6458272569,6651114.619484049,74.97079451600013],[510699.66958104394,6651113.91105765,75.85353521400015],[510699.56979191897,6651116.887141016,72.70186316200014],[510710.6971671753,6651104.971778976,71.7557029036788],[510699.63207582006,6651115.029603112,74.75851670700013],[510710.67585805344,6651105.512949944,71.2236565766788],[510699.53851479,6651117.819941492,71.75187789800013],[510710.3808860278,6651105.559237155,71.64481506371347],[510699.65743166517,6651114.273397376,75.75443972000012],[510699.57690567104,6651116.674982437,73.11221270500013],[510699.61894668714,6651115.421162756,74.50230358400013],[510710.39992706187,6651105.073696698,72.23864098271348],[510699.60964784835,6651115.698488763,74.28288457800014],[510699.5854917621,6651116.418913221,73.50399239900013],[510699.60092008556,6651115.958783154,74.04191493200013],[510699.5928448265,6651116.199617455,73.78147425900013],[510699.54231869883,6651117.706494765,72.23477891800015],[510699.64534220716,6651114.633950041,75.62681696100013],[510710.6735825553,6651105.570738974,71.64477800467878],[510710.692701053,6651105.085201563,72.2386039236788],[510699.5462748242,6651117.588508373,72.59648490300013],[510699.6334221162,6651114.989451547,75.47032566900013],[510710.3769612984,6651105.659316535,72.07090419871348],[510710.39530104364,6651105.191658726,72.60034696771348],[510699.55119632883,6651117.441730773,72.95424274900013],[510699.6217847501,6651115.336521149,75.28511676700013],[510699.5570838006,6651117.266144436,73.30469896400012],[510699.6105442698,6651115.671754136,75.07186443200013],[510710.6696418591,6651105.670817729,72.0708671396788],[510710.688056215,6651105.203162851,72.6003099086788],[510699.56392056594,6651117.062246632,73.64444399100014],[510699.59981225186,6651115.99182288,74.83177598500012],[510699.5716721101,6651116.831066714,73.97011110100013],[510699.589694214,6651116.293580454,74.56657826000014],[510710.389546178,6651105.338406014,72.95810481371348],[510699.5802862668,6651116.574160478,74.27847990900013],[510710.3712979664,6651105.803729745,72.49581070271348],[510710.68227793707,6651105.349909219,72.9580677546788],[510710.6639554872,6651105.815230032,72.49577364367879],[510710.38266177743,6651105.51395609,73.30856102871347],[510710.3638621007,6651105.993342011,72.91277740471347],[510710.6753655291,6651105.525458194,73.30852396967879],[510710.65648937057,6651106.00484111,72.91274034567878],[510710.3746673391,6651105.717811785,73.64830605571348],[510710.3546733078,6651106.227653377,73.31472632171347],[510710.6673385674,6651105.729312612,73.6482689966788],[510710.3656032218,6651105.948943961,73.97397316571347],[510710.64726319537,6651106.239151007,73.3146892626788],[510710.34380869294,6651106.504697682,73.69460712371347],[510710.658237575,6651105.96044334,73.9739361066788],[510710.3555304255,6651106.205797142,74.28234197371347],[510710.63635438046,6651106.516193576,73.69457006467879],[510710.3346392375,6651106.73851595,73.96101343871348],[510710.64812379994,6651106.217294909,74.28230491467879],[510710.34452942567,6651106.486319222,74.57044032471347],[510710.62714762136,6651106.750010377,73.96097637967878],[510710.32467797195,6651106.9925251305,74.20872317871347],[510710.6370780453,6651106.49781523,74.57040326567879],[510710.61714583077,6651107.004017965,74.20868611967879],[510710.33269809507,6651106.788014479,74.83563804971347],[510710.3103235241,6651107.358559091,74.50616564871348],[510710.62519858184,6651106.799508596,74.8356009906788],[510710.320148819,6651107.108017123,75.07572649671347],[510710.6027329855,6651107.370049632,74.50612858967881],[510710.29497122817,6651107.750037872,74.76237877171347],[510710.61259825213,6651107.119509234,75.0756894376788],[510710.3070049822,6651107.443180881,75.2889788317135],[510717.1935003072,6651105.152511052,68.98117101989592],[510710.5873182326,6651107.761525957,74.7623417126788],[510710.5994009429,6651107.45467089,75.2889417726788],[510710.2788912533,6651108.160072238,74.97465658071347],[510710.2933970547,6651107.790178806,75.47418773371348],[510717.16736027185,6651105.7615515655,68.98117101989592],[510710.57117284025,6651108.171557753,74.97461952167879],[510717.16736027185,6651105.7615515655,69.11117101989592],[510710.585737655,6651107.80166664,75.4741506746788],[510710.2623622332,6651108.581557119,75.14177133771348],[510710.27945852856,6651108.145606897,75.63067902571348],[510710.554576576,6651108.593039993,75.14173427867881],[510710.5717424233,6651108.157092503,75.6306419666788],[510710.2653219562,6651108.5060851015,75.75830178471347],[510710.24565681745,6651109.007540036,75.26392445971348],[510717.1935003072,6651105.152511052,70.80997467889593],[510710.5575483399,6651108.517568449,75.75826472567879],[510710.5378031984,6651109.019020237,75.26388740067881],[510710.2511153167,6651108.868349999,75.85739727871349],[510710.2290291166,6651109.431541244,75.34259915271348],[510717.19260152715,6651105.173451861,71.27556536589593],[510710.5432839042,6651108.879831074,75.8573602196788],[510717.16736027185,6651105.7615515655,70.80997467889593],[510710.52110785194,6651109.443018787,75.3425620936788],[510710.2127050227,6651109.847800571,75.38034201171347],[510710.2322705891,6651109.348884702,75.94656193071349],[510717.1897909219,6651105.238936563,71.75283631789593],[510717.16656723066,6651105.780028748,71.22078999089594],[510710.50471734744,6651109.859275505,75.38030495267878],[510710.52436251147,6651109.3603627635,75.94652487167879],[510710.2137699493,6651109.820645273,75.98933717171347],[510717.1640872849,6651105.837809368,71.64191141889592],[510717.18492353015,6651105.352342638,72.23573733789593],[510710.50578660634,6651109.832120378,75.98930011267879],[510717.15979252744,6651105.937873553,72.06800055389593],[510717.1798613654,6651105.470286753,72.59744332289593],[510717.1735639243,6651105.6170117585,72.95520116889593],[510717.1535952497,6651106.082264833,72.49290705789592],[510710.1441294474,6651111.596456451,75.38034201171347],[510709.90580755426,6651117.6735907355,68.98407466471348],[510709.90580755426,6651117.6735907355,69.11407466471347],[510710.4358627894,6651111.607920422,75.38030495267878],[510717.1660304544,6651105.792535178,73.30565738389592],[510717.1454583218,6651106.271848308,72.90987375989592],[510710.1965713426,6651117.685016608,68.9840376056788],[510710.1965713426,6651117.685016608,69.11403760567879],[510709.88191969466,6651118.282723741,68.98407466471348],[510717.15728229086,6651105.996359921,73.64540241089593],[510717.13540319866,6651106.506124095,73.31182267689593],[510710.17258630117,6651118.294145795,68.9840376056788],[510717.147363598,6651106.227457001,73.97106952089594],[510710.07697946037,6651113.308760275,75.38034201171347],[510717.12351425504,6651106.783126335,73.69170347889592],[510709.90580746264,6651117.673593073,70.81287832471347],[510717.13634112646,6651106.48427118,74.27943832889592],[510710.3684396192,6651113.320213512,75.38030495267878],[510709.9059855812,6651117.669051103,71.01669960871347],[510710.06065536645,6651113.725019602,75.34259915271348],[510717.11348029255,6651107.016909098,73.95810979389591],[510710.19657125056,6651117.685018945,70.8128412656788],[510710.0759146255,6651113.3359132325,75.98933717171347],[510709.90746457456,6651117.631337234,71.43327889671347],[510710.1967500939,6651117.680477004,71.01666254967878],[510710.04402766563,6651114.149020809,75.26392445971348],[510710.3520491147,6651113.736470228,75.3425620936788],[510709.88191969466,6651118.282723741,70.81287832371348],[510717.12430293934,6651106.764750664,74.56753667989592],[510710.3673704523,6651113.347366299,75.98930011267879],[510710.05741398566,6651113.807673804,75.94656193071349],[510709.91054752446,6651117.552722968,71.85760601671348],[510717.102579867,6651107.270879709,74.20581953389592],[510710.02732224984,6651114.575003725,75.14177133771348],[510710.19823510404,6651117.64276337,71.43324183767879],[510710.3353537682,6651114.160468778,75.26388740067881],[510710.17258630117,6651118.294145795,70.8128412646788],[510709.8827410376,6651118.261779752,71.27846901071347],[510709.91533422197,6651117.430663668,72.28391636771349],[510710.0107932298,6651114.996488606,74.97465658071347],[510710.3487945472,6651113.8191239135,75.94652487167879],[510710.2013305962,6651117.564149599,71.85756895767881],[510717.1113561369,6651107.066400111,74.83273440489593],[510710.3185803906,6651114.586449023,75.14173427867881],[510710.03856925806,6651114.288208507,75.85739727871349],[510709.921882788,6651117.263677267,72.70572522671348],[510709.99471325486,6651115.406522973,74.76237877171347],[510710.1734109855,6651118.273201936,71.2784319516788],[510709.8853094863,6651118.196285105,71.75573996271348],[510710.2061367672,6651117.442091064,72.28387930867879],[510717.086872065,6651107.636858092,74.50326200389594],[510709.93020111544,6651117.051562501,73.11607476971348],[510710.30198412633,6651115.007931261,74.97461952167879],[510710.02436261857,6651114.650473405,75.75830178471347],[510709.97936095897,6651115.798001753,74.50616564871348],[510709.9684875428,6651116.075270488,74.28674664271347],[510709.94024109386,6651116.795546168,73.50785446371349],[510710.32987315446,6651114.299655603,75.8573602196788],[510709.9582819034,6651116.335511125,74.04577699671347],[510709.9488392565,6651116.57629569,73.78533632371347],[510710.21271197445,6651117.275105708,72.70568816767879],[510710.28583873407,6651115.417963057,74.7623417126788],[510709.88975751295,6651118.082861807,72.23864098271348],[510710.0102260462,6651115.010951609,75.63067902571348],[510710.17598988337,6651118.2077077,71.7557029036788],[510717.0976237003,6651107.386354167,75.07282285189594],[510710.22106414294,6651117.062992273,73.1160377106788],[510710.3156087188,6651114.6619182285,75.75826472567879],[510710.2704239811,6651115.809439384,74.50612858967881],[510709.8943835311,6651117.96489978,72.60034696771348],[510710.2595063292,6651116.08670638,74.28670958367879],[510710.23114496656,6651116.806977544,73.50781740467879],[510709.99628752004,6651115.3663797,75.47418773371348],[510710.24925917067,6651116.346945386,74.0457399376788],[510710.2397781086,6651116.587728441,73.7852992646788],[510710.1804560056,6651118.094285113,72.2386039236788],[510717.0700723364,6651108.02827743,74.75947512689594],[510710.3014146353,6651115.022394176,75.6306419666788],[510709.90013839677,6651117.818152492,72.95810481371348],[510709.9826795926,6651115.713377625,75.2889788317135],[510709.9070227973,6651117.642602418,73.30856102871347],[510709.96953575587,6651116.048541383,75.07572649671347],[510717.08324064704,6651107.721467031,75.28607518689593],[510710.18510084366,6651117.976323825,72.6003099086788],[510710.28741940367,6651115.377820036,75.4741506746788],[510709.9150172357,6651117.4387467215,73.64830605571348],[510709.9569864797,6651116.368544029,74.83563804971347],[510709.92408135295,6651117.207614545,73.97397316571347],[510709.9451551491,6651116.670239285,74.57044032471347],[510709.93415414926,6651116.950761364,74.28234197371347],[510710.19087912154,6651117.829577458,72.9580677546788],[510710.27375611576,6651115.724815786,75.2889417726788],[510710.1977915296,6651117.654028483,73.30852396967879],[510710.26055880653,6651116.059977442,75.0756894376788],[510717.05247632257,6651108.438249534,74.97175293589592],[510710.2058184913,6651117.450174065,73.6482689966788],[510710.2479584768,6651116.379978082,74.8356009906788],[510710.2149194837,6651117.219043339,73.9739361066788],[510717.06834974803,6651108.068412268,75.47128408889593],[510710.2360790134,6651116.681671446,74.57040326567879],[510710.2250332587,6651116.962191767,74.28230491467879],[510717.0343889269,6651108.859670416,75.13886769289594],[510717.0530970812,6651108.423786389,75.62777538089593],[510717.03762769606,6651108.784209859,75.75539813989592],[510717.0161085048,6651109.28558865,75.26102081489594],[510717.0220816379,6651109.146419749,75.85449363389593],[510716.9979131247,6651109.709525476,75.33969550789593],[510716.9800499759,6651110.125721598,75.37743836689592],[510717.001460207,6651109.626881486,75.94365828589592],[510716.98121530504,6651110.098570424,75.98643352689592],[510716.90500901436,6651111.874111958,75.37743836689592],[510716.64421785146,6651117.950323476,68.98117101989592],[510716.64421785146,6651117.950323476,69.11117101989592],[510727.58008760674,6651105.627760315,68.96844538400684],[510716.6180778162,6651118.559363989,68.98117101989592],[510727.5505002783,6651106.236643095,68.96844538400684],[510727.5505002783,6651106.236643095,69.09844538400685],[510716.8315280471,6651113.5861557815,75.37743836689592],[510716.64421775116,6651117.950325814,70.80997467989593],[510716.6444126631,6651117.945784534,71.01379596389592],[510727.58008760674,6651105.627760315,70.79724904300684],[510716.81366489833,6651114.002351903,75.33969550789593],[510716.8303628184,6651113.613304617,75.98643352689592],[510716.6460310976,6651117.90807639,71.43037525189592],[510716.7954695182,6651114.426288729,75.26102081489594],[510716.6180778162,6651118.559363989,70.80997467889593],[510727.57907029736,6651105.648695701,71.26283973000683],[510727.5505002783,6651106.236643095,70.79724904300684],[510716.6494047117,6651117.829474061,71.85470237189594],[510716.8101179163,6651114.084993556,75.94365828589592],[510716.7771890962,6651114.852206962,75.13886769289594],[510716.6189765963,6651118.53842318,71.27556536589593],[510716.6546427047,6651117.707433295,72.28101272289592],[510716.7591017005,6651115.273627844,74.97175293589592],[510727.57588903554,6651105.714163442,71.74011068200684],[510727.5496026525,6651106.255115492,71.20806435500684],[510716.78949648555,6651114.565455293,75.85449363389593],[510716.6618086773,6651117.5404722495,72.70282158189592],[510716.7415056866,6651115.68359995,74.75947512689594],[510716.62178720144,6651118.472938479,71.75283631789593],[510716.67091126635,6651117.328389692,73.11317112489593],[510716.7247059581,6651116.075019288,74.50326200389594],[510716.77395042736,6651114.927665182,75.75539813989592],[510716.7128073834,6651116.352245921,74.28384299789592],[510716.68189782585,6651117.072412233,73.50495081889592],[510716.7016395442,6651116.612447043,74.04287335189593],[510716.6913066334,6651116.853195047,73.78243267889593],[510727.54679565673,6651106.312881147,71.62918578300683],[510727.57037974225,6651105.827540148,72.22301170200684],[510716.6266545933,6651118.359532403,72.23573733789593],[510716.7584810422,6651115.288088651,75.62777538089593],[510716.6317167579,6651118.241588288,72.59744332289593],[510716.7432283754,6651115.6434627725,75.47128408889593],[510716.6380141991,6651118.094863282,72.95520116889593],[510727.5419345156,6651106.412919416,72.05527491800686],[510716.7283374764,6651115.990408009,75.28607518689593],[510727.5646499899,6651105.945453716,72.58471768700684],[510716.64554766903,6651117.919339863,73.30565738389592],[510716.71395442315,6651116.325520874,75.07282285189594],[510730.6378082029,6651105.778898019,68.96278941948812],[510716.65429583244,6651117.71551512,73.64540241089593],[510716.7002219864,6651116.645474929,74.83273440489593],[510716.66421452543,6651117.484418041,73.97106952089594],[510716.6872751841,6651116.947124376,74.56753667989592],[510716.67523699696,6651117.227603861,74.27943832889592],[510727.55752205546,6651106.092140722,72.94247553300684],[510727.53491995385,6651106.557273301,72.48018142200684],[510730.60720602155,6651106.387730636,68.96278941948812],[510730.60720602155,6651106.387730636,69.0927894194881],[510727.5489950873,6651106.267618683,73.29293174800685],[510727.52570994495,6651106.746807677,72.89714812400683],[510727.5390932343,6651106.471390637,73.63267677500684],[510727.51432877325,6651106.981022789,73.29909704100683],[510730.6378082029,6651105.778898019,70.7915930784881],[510727.52786648495,6651106.702427866,73.95834388500684],[510727.50087194075,6651107.257953289,73.67897784300683],[510730.6367559996,6651105.799831681,71.2571837654881],[510730.60720602155,6651106.387730636,70.7915930784881],[510727.5153903929,6651106.959175534,74.26671269300684],[510727.48951472016,6651107.491675504,73.94538415800685],[510730.6334656197,6651105.865294028,71.73445471748812],[510730.6062776069,6651106.406201512,71.2024083904881],[510727.50176463503,6651107.2395823775,74.55481104400684],[510727.47717676946,6651107.74558034,74.19309389800684],[510730.60337433044,6651106.463962407,71.62352981848811],[510730.6277673562,6651105.978661393,72.21735573748812],[510727.48711043544,6651107.5411537,74.82000876900683],[510730.59834645095,6651106.563992436,72.0496189534881],[510730.62184107193,6651106.0965652475,72.5790617224881],[510727.4593974553,6651108.111463937,74.49053636800684],[510727.47156699374,6651107.86102489,75.06009721600684],[510730.6144686474,6651106.243240168,72.9368195684881],[510730.5910912879,6651106.708334429,72.4745254574881],[510727.4403822138,6651108.5027819015,74.74674949100684],[510727.4552871335,6651108.196050965,75.27334955100686],[510730.605649202,6651106.418703673,73.2872757834881],[510730.58156537334,6651106.897853188,72.8914921594881],[510734.3947636187,6651105.971593879,68.95465016035759],[510727.4204656744,6651108.912647829,74.95902730000684],[510727.438432454,6651108.542906347,75.45855845300684],[510730.595407713,6651106.622458839,73.6270208104881],[510730.5697938245,6651107.1320490055,73.29344107648811],[510734.3629145093,6651106.58036254,68.95465016035759],[510734.3629145093,6651106.58036254,69.08465016035757],[510727.39999295096,6651109.333959568,75.12614205700685],[510727.4211682974,6651108.89818843,75.61504974500686],[510730.5837958832,6651106.853477035,73.9526879204881],[510730.5558754192,6651107.40895669,73.6733218784881],[510727.4036588422,6651109.258518553,75.74267250400685],[510727.37930174504,6651109.759767494,75.24829517900685],[510730.570891858,6651107.110203549,74.2610567284881],[510734.3947636187,6651105.971593879,70.78345381935759],[510730.54412864306,6651107.642659651,73.9397281934881],[510727.38606260234,6651109.620634636,75.84176799800684],[510727.35870679637,6651110.183594526,75.32696987200684],[510730.5567987331,6651107.390587292,74.54915507948812],[510734.3936685419,6651105.992525341,71.24904450635756],[510730.5313674974,6651107.89654357,74.1874379334881],[510727.33848789294,6651110.599682856,75.36471273100683],[510727.36272166047,6651110.100971939,75.93093265000685],[510734.3629145093,6651106.58036254,70.78345381935759],[510730.54164189065,6651107.692133769,74.8143528044881],[510734.3902440909,6651106.057980813,71.72631545835758],[510734.3619482651,6651106.598831477,71.19426913135757],[510727.3398069032,6651110.572538715,75.97370789100684],[510730.5129783483,6651108.262397023,74.4848804034881],[510730.52556530497,6651108.011978609,75.0544412514881],[510734.3589266907,6651106.656586305,71.61539055935756],[510734.38431364385,6651106.171336268,72.20921647835759],[510730.493310879,6651108.653682749,74.7410935264881],[510734.35369394324,6651106.756605824,72.04147969435758],[510730.50872704136,6651108.346977082,75.26769358648811],[510734.3781458849,6651106.289227738,72.57092246335758],[510727.2535506866,6651112.347620404,75.36471273100683],[510730.4727111972,6651109.06351491,74.95337133548811],[510734.3704730608,6651106.435887252,72.92868030935757],[510730.49129424203,6651108.693803888,75.4529024884881],[510734.34614315873,6651106.900932655,72.46638619835758],[510726.9583669315,6651118.422258254,68.96844538400684],[510726.9583669315,6651118.422258254,69.09844538400685],[510734.361294255,6651106.611332324,73.27913652435757],[510730.451536254,6651109.484791939,75.12048609248811],[510730.47343792033,6651109.049056702,75.6093937804881],[510734.3362290977,6651107.090431508,72.88335290035756],[510726.9287796031,6651119.0311410315,68.96844538400684],[510730.45532788633,6651109.40935714,75.7370165394881],[510734.3506354625,6651106.815066086,73.61888155135759],[510730.4301353345,6651109.910564785,75.24263921448811],[510734.3239779009,6651107.324602722,73.28530181735758],[510730.4371280909,6651109.771443389,75.8361120334881],[510730.4088339738,6651110.3343569,75.32131390748812],[510734.3385504927,6651107.046060014,73.94454866135757],[510727.17037920334,6651114.059220828,75.36471273100683],[510726.95836681797,6651118.422260589,70.79724904400683],[510734.3094923709,6651107.601481319,73.66518261935757],[510726.95858743443,6651118.417720486,71.00107032800683],[510727.1501602999,6651114.475309158,75.32696987200684],[510730.3879215568,6651110.750410953,75.35905676648811],[510730.41298654873,6651110.25174112,75.9252766854881],[510734.3251206753,6651107.302759563,74.25291746935757],[510727.1690603067,6651114.086362632,75.97370789100684],[510726.96041930467,6651118.380022108,71.41764961600684],[510734.29726695624,6651107.835159731,73.93158893435758],[510727.12956535124,6651114.89913619,75.24829517900685],[510726.9287796031,6651119.0311410315,70.79724904300684],[510730.3892858094,6651110.723269046,75.9680519264881],[510726.9642378239,6651118.301440137,71.84197673600684],[510727.1461455494,6651114.557929408,75.93093265000685],[510734.3104533066,6651107.583113851,74.54101582035759],[510727.1088741453,6651115.324944116,75.12614205700685],[510726.9297969124,6651119.010205645,71.26283973000683],[510734.28398584016,6651108.089016979,74.17929867435757],[510726.97016659245,6651118.179430978,72.26828708700685],[510727.08840142185,6651115.746255854,74.95902730000684],[510727.1228046075,6651115.038266711,75.84176799800684],[510726.9782775985,6651118.012513173,72.69009594600683],[510727.0684848825,6651116.156121782,74.74674949100684],[510726.93297817436,6651118.944737904,71.74011068200684],[510734.29467887775,6651107.884628652,74.80621354535756],[510726.988580618,6651117.800485543,73.10044548900684],[510727.04946964094,6651116.5474397475,74.49053636800684],[510727.10520836763,6651115.400382793,75.74267250400685],[510727.001016062,6651117.544574378,73.49222518300685],[510727.0360019072,6651116.8245945815,74.27111736200683],[510727.0116656833,6651117.325413967,73.76970704300683],[510727.02336127684,6651117.084728314,74.03014771600684],[510734.26484739984,6651108.454832002,74.47674114435758],[510726.9384874676,6651118.831361199,72.22301170200684],[510727.0876989125,6651115.760712918,75.61504974500686],[510726.94421721995,6651118.7134476295,72.58471768700684],[510734.27794722933,6651108.204439892,75.04630199235757],[510730.3000709823,6651112.498204497,75.35905676648811],[510727.0704347558,6651116.115995001,75.45855845300684],[510726.9513451545,6651118.566760625,72.94247553300684],[510729.9947623485,6651118.572341891,68.96278941948812],[510727.0535800763,6651116.462850382,75.27334955100686],[510729.9947623485,6651118.572341891,69.0927894194881],[510726.9598721226,6651118.391282664,73.29293174800685],[510727.03730021615,6651116.797876457,75.06009721600684],[510734.2443785525,6651108.8460766245,74.73295426735757],[510726.9697739755,6651118.187510709,73.63267677500684],[510727.02175677445,6651117.117747648,74.82000876900683],[510726.9810007249,6651117.956473481,73.95834388500684],[510727.00710257486,6651117.41931897,74.55481104400684],[510726.993476817,6651117.699725813,74.26671269300684],[510734.2604228676,6651108.539403177,75.25955432735758],[510729.96416016715,6651119.181174506,68.96278941948812],[510734.2229395084,6651109.255865734,74.94523207635757],[510734.2422797448,6651108.886193549,75.44476322935758],[510734.200901763,6651109.67709851,75.11234683335758],[510734.2236958428,6651109.241409045,75.60125452135757],[510730.21404669574,6651114.209663911,75.35905676648811],[510729.994762231,6651118.572344227,70.7915930794881],[510734.2048478906,6651109.601671636,75.72887728035757],[510729.99499041465,6651118.567804497,70.9954143634881],[510734.1786288335,6651110.10282663,75.23449995535758],[510730.1931342788,6651114.625717964,75.32131390748812],[510730.21268256055,6651114.23680348,75.9680519264881],[510729.9968851186,6651118.530109226,71.41199365148812],[510730.171832918,6651115.049510078,75.24263921448811],[510729.96416016715,6651119.181174506,70.7915930784881],[510734.18590651936,6651109.963719849,75.82797277435759],[510734.1564595195,6651110.526574227,75.31317464835759],[510730.00083461404,6651118.451533728,71.8363207714881],[510730.1889818213,6651114.708331407,75.9252766854881],[510730.1504319985,6651115.475282923,75.12048609248811],[510729.96521237044,6651119.160240846,71.2571837654881],[510730.0069667408,6651118.32953462,72.2626311224881],[510734.13469499734,6651110.942584574,75.35091750735758],[510730.12925705523,6651115.896559953,74.95337133548811],[510734.16078129684,6651110.443967126,75.91713742635757],[510730.16484027903,6651115.188629137,75.8361120334881],[510730.0153559565,6651118.162630567,72.6844399814881],[510730.10865737346,6651116.306392115,74.7410935264881],[510729.96850275033,6651119.094778499,71.73445471748812],[510730.0260123722,6651117.950620405,73.0947895244881],[510730.0889899043,6651116.6976778405,74.4848804034881],[510730.1466404837,6651115.550715387,75.7370165394881],[510730.038874355,6651117.694730324,73.4865692184881],[510730.0750602238,6651116.974809842,74.26546139748811],[510730.0498892612,6651117.475587968,73.76405107848811],[510730.0619860166,6651117.234922144,74.0244917514881],[510734.13611483824,6651110.91544552,75.95991266735757],[510729.9742010138,6651118.981411134,72.21735573748812],[510730.1285304497,6651115.911015824,75.6093937804881],[510729.9801272981,6651118.863507279,72.5790617224881],[510730.110674128,6651116.266268638,75.4529024884881],[510729.9874997227,6651118.716832358,72.9368195684881],[510730.09324132866,6651116.613095444,75.26769358648811],[510729.996319168,6651118.541368853,73.2872757834881],[510730.07640306506,6651116.948093918,75.0544412514881],[510730.00656065706,6651118.337613688,73.6270208104881],[510730.0603264794,6651117.267938757,74.8143528044881],[510730.0181724868,6651118.106595492,73.9526879204881],[510730.04516963696,6651117.569485234,74.54915507948812],[510730.031076512,6651117.8498689765,74.2610567284881],[510734.04326483025,6651112.69019452,75.35091750735758],[510733.72551597597,6651118.763693851,68.95465016035759],[510744.45206085313,6651106.525420858,68.92640105436793],[510733.72551597597,6651118.763693851,69.08465016035757],[510733.69366686663,6651119.372462511,68.95465016035759],[510744.41687374155,6651107.134005704,68.92640105436793],[510744.41687374155,6651107.134005704,69.05640105436792],[510733.9537353658,6651114.401474153,75.35091750735758],[510733.72551585373,6651118.763696186,70.78345382035756],[510744.45206085313,6651106.525420858,70.75520471336793],[510733.7257533351,6651118.759156933,70.98727510435758],[510733.9319708435,6651114.817484501,75.31317464835759],[510733.952315647,6651114.428610871,75.95991266735757],[510744.4508510049,6651106.546345999,71.22079540036792],[510733.7277252413,6651118.721465621,71.40385439235759],[510733.69366686663,6651119.372462511,70.78345381935759],[510733.90980152955,6651115.241232097,75.23449995535758],[510744.41687374155,6651107.134005704,70.75520471336793],[510733.7318356643,6651118.642898378,71.82818151235757],[510733.92764918844,6651114.900089264,75.91713742635757],[510733.88752860005,6651115.666960218,75.11234683335758],[510744.44706764823,6651106.611781707,71.69806635236795],[510733.69476194336,6651119.351531049,71.24904450635756],[510744.41580622847,6651107.152469065,71.16602002536793],[510733.7382176531,6651118.520912086,72.25449186335757],[510733.8654908548,6651116.088192994,74.94523207635757],[510733.902523966,6651115.380336542,75.82797277435759],[510733.74694869894,6651118.354025566,72.67630072235758],[510733.6981863944,6651119.286075577,71.72631545835758],[510733.84405181056,6651116.497982102,74.73295426735757],[510744.4124679726,6651107.210206454,71.58714145336793],[510733.7580393249,6651118.142037674,73.08665026535758],[510744.4405156502,6651106.725102936,72.18096737236793],[510733.8235829632,6651116.889226725,74.47674114435758],[510733.8835825948,6651115.742384755,75.72887728035757],[510733.77142538695,6651117.886174472,73.47842995935757],[510733.80908569874,6651117.166329616,74.25732213835758],[510733.7828891107,6651117.667055137,73.75591181935758],[510733.79547876486,6651117.426414593,74.01635249235757],[510733.7041168414,6651119.172720123,72.20921647835759],[510733.86473464256,6651116.102647346,75.60125452135757],[510733.7102846004,6651119.054828652,72.57092246335758],[510744.40668679785,6651107.310195773,72.01323058836793],[510744.4337014684,6651106.842958809,72.54267335736793],[510733.84615074046,6651116.457862841,75.44476322935758],[510733.71795742447,6651118.908169139,72.92868030935757],[510733.8280076178,6651116.804653214,75.25955432735758],[510733.7271362303,6651118.732724067,73.27913652435757],[510733.8104832559,6651117.139616499,75.04630199235757],[510733.7377950229,6651118.528990304,73.61888155135759],[510733.79375160753,6651117.459427739,74.80621354535756],[510733.7498799926,6651118.297996378,73.94454866135757],[510744.42522448045,6651106.989574039,72.90043120336794],[510733.7779771788,6651117.76094254,74.54101582035759],[510733.7633098101,6651118.041296829,74.25291746935757],[510744.3983446399,6651107.454479025,72.43813709236792],[510744.4150836736,6651107.164966137,73.25088741836792],[510744.38739151816,6651107.643920658,72.85510379436793],[510744.4033077675,6651107.368638382,73.59063244536793],[510744.37385631306,6651107.878021168,73.25705271136792],[510744.38995621103,6651107.599562564,73.91629955536793],[510744.35785260145,6651108.154816163,73.63693351336792],[510744.3751188579,6651107.856184602,74.22466836336794],[510744.3443458806,6651108.388424016,73.90333982836795],[510744.35891424963,6651108.1364542395,74.51276671436793],[510744.32967281365,6651108.642204613,74.15104956836792],[510744.34148655395,6651108.437878001,74.77796443936792],[510744.3085285353,6651109.00790918,74.44849203836793],[510744.3230013157,6651108.757592674,75.01805288636793],[510750.856643526,6651106.906945225,68.9035058657163],[510744.2859144142,6651109.399035669,74.70470516136793],[510744.3036402822,6651109.092454818,75.23130522136793],[510750.8193307429,6651107.515403444,68.9035058657163],[510744.26222841314,6651109.808701046,74.91698297036794],[510750.8193307429,6651107.515403444,69.0335058657163],[510744.28359563736,6651109.43914048,75.41651412336795],[510751.5875913436,6651106.951915768,68.90065002138758],[510744.23788096296,6651110.229806632,75.08409772736793],[510744.26306401653,6651109.794248721,75.57300541536793],[510751.5500359599,6651107.560359061,68.90065002138758],[510751.5500359599,6651107.560359061,69.03065002138757],[510750.856643526,6651106.906945225,70.7323095247163],[510744.24224067136,6651110.154402531,75.70062817436792],[510744.21327367966,6651110.655406205,75.20625084936793],[510750.8553605902,6651106.927866013,71.1979002117163],[510744.2213141163,6651110.5163414255,75.79972366836793],[510744.1887808716,6651111.079025854,75.28492554236793],[510750.8193307429,6651107.515403444,70.7323095247163],[510751.5875913436,6651106.951915768,70.72945368038758],[510750.851348679,6651106.993288105,71.6751711637163],[510744.16473528015,6651111.49491059,75.32266840136792],[510750.8181987407,6651107.533862962,71.14312483671631],[510744.1935556005,6651110.996443695,75.88888832036793],[510751.5863000664,6651106.972836043,71.19504436738757],[510750.81465881906,6651107.591588338,71.56424626471629],[510750.84440087137,6651107.106585755,72.1580721837163],[510744.1663039301,6651111.4677797295,75.93166356136794],[510751.5500359599,6651107.560359061,70.72945368038758],[510751.5822620705,6651107.038256531,71.67231531938758],[510751.5488965977,6651107.578818127,71.14026899238758],[510750.80852840055,6651107.691556854,71.9903353997163],[510750.8371750413,6651107.224417107,72.51977816871631],[510751.54533366015,6651107.636542086,71.56139042038757],[510750.82818595413,6651107.37100183,72.87753601471631],[510751.5752690896,6651107.1515514,72.15521633938758],[510750.7996822885,6651107.835810084,72.41524190371629],[510744.06372261286,6651113.2419928545,75.32266840136792],[510743.7126715283,6651119.313658325,68.92640105436793],[510751.53916338284,6651107.73650815,71.9874795553876],[510751.5679962787,6651107.269379862,72.51692232438758],[510743.7126715283,6651119.313658325,69.05640105436792],[510750.817432536,6651107.546357435,73.22799222971629],[510750.78806748305,6651108.025212301,72.83220860571629],[510751.5589487461,6651107.415960989,72.87468017038758],[510751.53025975515,6651107.880757842,72.41238605938757],[510743.6774844167,6651119.92224317,68.92640105436793],[510750.8049452412,6651107.749987303,73.5677372567163],[510750.77371460927,6651108.259264101,73.2341575227163],[510751.54812541127,6651107.591312292,73.22513638538757],[510751.5185694325,6651108.070155413,72.82935276138757],[510750.79078711045,6651107.980863436,73.8934043667163],[510750.7567441052,6651108.536001503,73.61403832471629],[510751.53555692657,6651107.794937166,73.56488141238758],[510743.96480985463,6651114.952755776,75.32266840136792],[510743.71267139324,6651119.31366066,70.75520471436792],[510750.77505342505,6651108.237432078,74.20177317471631],[510751.5041232391,6651108.304201472,73.23130167838758],[510743.7129337642,6651119.309122778,70.95902599836792],[510750.74242143636,6651108.769560751,73.8804446397163],[510743.94076426316,6651115.36864051,75.28492554236793],[510751.52130674233,6651108.025807634,73.89054852238758],[510743.9632413397,6651114.979884299,75.93166356136794],[510743.71511233953,6651119.271442845,71.37560528636793],[510750.75786988804,6651108.5176434005,74.4898715257163],[510743.6774844167,6651119.92224317,70.75520471336793],[510743.9162714551,6651115.792260159,75.20625084936793],[510751.487042396,6651108.580932085,73.61118248038757],[510750.72686196177,6651109.023288545,74.12815437971629],[510743.71965356276,6651119.192899325,71.79993240636793],[510743.93598966935,6651115.451220333,75.88888832036793],[510743.8916641718,6651116.217859733,75.08409772736793],[510751.5054707596,6651108.282369984,74.19891733038757],[510743.6786942649,6651119.901318029,71.22079540036792],[510750.7393893763,6651108.819004444,74.75506925071629],[510743.72670442716,6651119.070949866,72.22624275736793],[510751.472626604,6651108.814485602,73.87758879538757],[510743.86731672165,6651116.63896532,74.91698297036794],[510743.9082311535,6651115.9313226035,75.79972366836793],[510743.7363505456,6651118.904113736,72.64805161636792],[510750.7044403466,6651109.38891702,74.42559684971631],[510743.6824776216,6651119.835882322,71.69806635236795],[510743.84363072057,6651117.048630697,74.70470516136793],[510751.4881754986,6651108.562574432,74.48701568138758],[510743.74860354426,6651118.692189854,73.05840115936793],[510743.8210165995,6651117.439757184,74.44849203836793],[510743.88730459847,6651116.293261498,75.70062817436792],[510743.7633925562,6651118.436403908,73.45018085336793],[510743.8049999236,6651117.716776405,74.22907303236792],[510750.7197874351,6651109.1386525985,74.9951576977163],[510751.4569659648,6651109.068207172,74.12529853538757],[510743.7760577557,6651118.217350735,73.72766271336792],[510743.78996689094,6651117.976782853,73.98810338636792],[510743.6890296196,6651119.722561093,72.18096737236793],[510743.8664812533,6651116.653415308,75.57300541536793],[510743.6958438014,6651119.604705219,72.54267335736793],[510750.6804600949,6651109.779962127,74.6818099727163],[510743.84594963246,6651117.008523548,75.41651412336795],[510751.4695748301,6651108.863928085,74.75221340638757],[510743.7043207894,6651119.45808999,72.90043120336794],[510750.6992567916,6651109.473445066,75.2084100327163],[510743.82590498775,6651117.355209211,75.23130522136793],[510743.7144615962,6651119.282697892,73.25088741836792],[510751.43439856864,6651109.433826678,74.42274100538758],[510743.8065439542,6651117.690071355,75.01805288636793],[510743.7262375024,6651119.079025646,73.59063244536793],[510743.7880587159,6651118.009786028,74.77796443936792],[510743.7395890588,6651118.848101465,73.91629955536793],[510743.7706310202,6651118.3112097895,74.51276671436793],[510743.75442641194,6651118.591479427,74.22466836336794],[510751.44984544086,6651109.183568395,74.99230185338757],[510750.65534321027,6651110.189542265,74.8940877817163],[510750.67800123943,6651109.820058594,75.3936189347163],[510751.4102624018,6651109.824862193,74.67895412838757],[510751.42918131105,6651109.518352652,75.2055541883876],[510750.6295249179,6651110.610560233,75.0612025387163],[510750.6562292928,6651110.175092947,75.5501102267163],[510751.3849822121,6651110.234432285,74.89123193738757],[510751.40778755944,6651109.864957676,75.39076309038758],[510750.63414799864,6651110.535171822,75.67773298571629],[510750.603431096,6651111.036071253,75.1833556607163],[510751.3589960542,6651110.655439925,75.05834669438758],[510750.6119572596,6651110.897035409,75.7768284797163],[510751.3858740558,6651110.219983321,75.54725438238759],[510750.5774586647,6651111.45960276,75.2620303537163],[510751.3636491933,6651110.580053363,75.67487714138758],[510751.33273257525,6651111.080940507,75.18049981638758],[510750.5519604666,6651111.875400962,75.29977321271629],[510750.58252183744,6651111.377037784,75.8659931317163],[510751.3413141743,6651110.941908073,75.77397263538758],[510751.3065912763,6651111.504461624,75.25917450938758],[510750.55362387956,6651111.848275747,75.90876837271631],[510751.2809272938,6651111.920249627,75.29691736838757],[510751.3116873687,6651111.421898673,75.86313728738759],[510751.282601522,6651111.893125078,75.90591252838757],[510750.44484557194,6651113.6221197145,75.29977321271629],[510750.07258730987,6651119.692521863,68.9035058657163],[510750.07258730987,6651119.692521863,69.0335058657163],[510750.03527452674,6651120.30098008,68.9035058657163],[510761.3150627726,6651107.578246551,68.8579046167634],[510751.1731159588,6651113.666925532,75.29691736838757],[510750.7984373454,6651119.73717877,68.90065002138758],[510750.7984373454,6651119.73717877,69.03065002138757],[510761.2742788554,6651108.186481965,68.8579046167634],[510761.2742788554,6651108.186481965,68.98790461676339],[510750.7608819617,6651120.345622063,68.90065002138758],[510750.3399574428,6651115.332526679,75.29977321271629],[510750.0725871666,6651119.692524197,70.7323095257163],[510750.07286538754,6651119.687987258,70.93613080971629],[510750.3144592448,6651115.748324881,75.2620303537163],[510750.33829417307,6651115.359649558,75.90876837271631],[510750.07517557184,6651119.650315166,71.3527100977163],[510750.03527452674,6651120.30098008,70.7323095247163],[510750.2884868135,6651116.171856388,75.1833556607163],[510761.3150627726,6651107.578246551,70.68670827576341],[510750.07999113266,6651119.57178799,71.77703721771631],[510751.0675458673,6651115.377290539,75.29691736838757],[510750.79843720124,6651119.737181106,70.72945368138757],[510750.30939621525,6651115.830887522,75.8659931317163],[510750.2623929916,6651116.597367409,75.0612025387163],[510750.0365574624,6651120.280059292,71.1979002117163],[510750.7987172311,6651119.732644279,70.93327496538757],[510750.0874679433,6651119.449863903,72.2033475687163],[510761.3136604879,6651107.599159678,71.15229896276338],[510750.2365746992,6651117.018385376,74.8940877817163],[510751.0418818849,6651115.793078542,75.25917450938758],[510750.27996079304,6651116.310889898,75.7768284797163],[510750.0976967889,6651119.283062487,72.62515642771629],[510761.2742788554,6651108.186481965,70.68670827576341],[510750.04056937364,6651120.214637199,71.6751711637163],[510750.2114578146,6651117.427965514,74.6818099727163],[510751.06587178336,6651115.404412754,75.90591252838757],[510750.8010424357,6651119.69497311,71.34985425338758],[510750.1106899975,6651119.071182698,73.0355059707163],[510750.7608819617,6651120.345622063,70.72945368038758],[510750.18747756275,6651117.819010622,74.42559684971631],[510751.0157405858,6651116.21659966,75.18049981638758],[510750.2577700541,6651116.672753485,75.67773298571629],[510750.1263724214,6651118.815449975,73.4272856647163],[510750.17049331125,6651118.095972205,74.20617784371629],[510750.1398027321,6651118.596442379,73.7047675247163],[510750.1545521254,6651118.355924551,73.96520819771631],[510761.3092753565,6651107.664557815,71.6295699147634],[510750.0475171813,6651120.101339551,72.1580721837163],[510761.2730415454,6651108.204934724,71.09752358776339],[510750.80588930636,6651119.6164478585,71.77418137338758],[510750.2356887598,6651117.032832358,75.5501102267163],[510751.03678593657,6651115.875639157,75.86313728738759],[510750.9894771069,6651116.642100242,75.05834669438758],[510750.76217323885,6651120.324701788,71.19504436738757],[510750.0547430113,6651119.9835081985,72.51977816871631],[510750.2139168132,6651117.387866712,75.3936189347163],[510750.8134147299,6651119.494526765,72.20049172438759],[510750.0637320985,6651119.836923476,72.87753601471631],[510750.96349094907,6651117.063107883,74.89123193738757],[510761.2691723118,6651108.262638962,71.5186450157634],[510750.1926612611,6651117.7344802385,75.2084100327163],[510751.007159131,6651116.355629758,75.77397263538758],[510750.8237100814,6651119.32772944,72.62230058338757],[510761.30168120813,6651107.777813977,72.11247093476341],[510750.07448551664,6651119.6615678705,73.22799222971629],[510750.7662112348,6651120.259281302,71.67231531938758],[510750.17213061755,6651118.069272708,74.9951576977163],[510750.93821075937,6651117.472677973,74.67895412838757],[510750.08697281143,6651119.457938003,73.5677372567163],[510750.15252867644,6651118.38892086,74.75506925071629],[510750.83678776934,6651119.115854849,73.03265012638758],[510750.1011309423,6651119.2270618705,73.8934043667163],[510750.1340481646,6651118.690281905,74.4898715257163],[510750.9140745925,6651117.863713488,74.42274100538758],[510750.1168646276,6651118.970493227,74.20177317471631],[510750.984824112,6651116.717484468,75.67487714138758],[510750.85257215734,6651118.860128398,73.42442982038759],[510750.8969799127,6651118.140668276,74.20332199938757],[510750.8660897893,6651118.6411261745,73.70191168038758],[510750.8809350803,6651118.400614246,73.96235235338757],[510750.77320421574,6651120.14598643,72.15521633938758],[510761.26247159275,6651108.362570872,71.9447341507634],[510761.2937831736,6651107.895602181,72.4741769197634],[510750.9625992495,6651117.077554509,75.54725438238759],[510750.78047702665,6651120.028157969,72.51692232438758],[510750.94068574585,6651117.432580154,75.39076309038758],[510750.7895245592,6651119.881576842,72.87468017038758],[510750.9192919943,6651117.779185179,75.2055541883876],[510761.28395784943,6651108.042133229,72.83193476576339],[510750.800347894,6651119.706225539,73.22513638538757],[510761.2528025445,6651108.5067712795,72.36964065476339],[510750.8986278645,6651118.113969435,74.99230185338757],[510750.8129163787,6651119.502600665,73.56488141238758],[510750.8788984752,6651118.433609747,74.75221340638757],[510750.82716656296,6651119.271730197,73.89054852238758],[510750.86029780674,6651118.734963399,74.48701568138758],[510750.84300254576,6651119.015167847,74.19891733038757],[510761.2722040622,6651108.217424622,73.18239098076339],[510761.2401072368,6651108.696104142,72.78660735676338],[510761.25855509925,6651108.420979925,73.52213600776341],[510761.2244191437,6651108.930070237,73.1885562737634],[510761.24307986564,6651108.651771516,73.84780311776339],[510761.2058699073,6651109.206706304,73.56843707576338],[510761.2258825069,6651108.908246209,74.15617192576339],[510761.19021482917,6651109.440180027,73.83484339076338],[510761.20710041956,6651109.188354924,74.4442702767634],[510761.1732078877,6651109.693814911,74.08255313076339],[510761.1869007026,6651109.489605617,74.70946800176338],[510761.14870043425,6651110.059309501,74.3799956007634],[510761.16547523177,6651109.80913672,74.94955644876339],[510761.1224893473,6651110.450211417,74.63620872376339],[510761.14303466334,6651110.143806596,75.1628087837634],[510761.0950358888,6651110.859641577,74.84848653276339],[510761.1198017494,6651110.490293201,75.3480176857634],[510761.0668157721,6651111.280505376,75.0156012897634],[510761.0960044019,6651110.84519755,75.5045089777634],[510768.77047211194,6651108.093390549,68.81917060298551],[510761.07186892885,6651111.20514457,75.63213173676338],[510761.0382944938,6651111.705860583,75.1377544117634],[510768.72721375537,6651108.701454987,68.81917060298551],[510761.04761382943,6651111.5668756515,75.73122723076341],[510768.72721375537,6651108.701454987,68.9491706029855],[510761.0099058989,6651112.129237003,75.2164291047634],[510760.9820356542,6651112.5448829485,75.2541719637634],[510761.01544008846,6651112.04670226,75.82039188276339],[510768.77047211194,6651108.093390549,70.64797426198551],[510760.9838538111,6651112.517767667,75.86316712376339],[510768.76898474793,6651108.114297796,71.1135649489855],[510768.72721375537,6651108.701454987,70.64797426198551],[510768.7643335621,6651108.17967755,71.59083590098551],[510768.7259013753,6651108.719902559,71.05878957398552],[510760.86495607387,6651114.290962093,75.2541719637634],[510771.06181310286,6651108.257839253,68.80622400340143],[510760.45806736604,6651120.359141392,68.8579046167634],[510760.45806736604,6651120.359141392,68.98790461676339],[510768.72179738793,6651108.777590576,71.4799110019855],[510768.7562786621,6651108.292901875,72.07373692098551],[510771.01779425354,6651108.865849112,68.80622400340143],[510760.4172834488,6651120.967376806,68.8579046167634],[510768.7146901231,6651108.877494394,71.90600013698551],[510771.01779425354,6651108.865849112,68.93622400340142],[510768.7479014383,6651108.410656969,72.43544290598551],[510768.7374799928,6651108.557146828,72.79320075198551],[510768.704434435,6651109.021654268,72.3309066409855],[510760.7503104106,6651116.000742743,75.2541719637634],[510768.72501308034,6651108.732388945,73.1436569669855],[510771.06181310286,6651108.257839253,70.63502766240143],[510760.45806720946,6651120.359143726,70.68670827676338],[510768.6909688783,6651109.210933909,72.7478733429855],[510760.45837131276,6651120.354608448,70.8905295607634],[510760.72244016593,6651116.416388689,75.2164291047634],[510771.0602995905,6651108.278744626,71.10061834940143],[510768.7105360084,6651108.935887029,73.48340199398551],[510760.46089640877,6651120.316950152,71.3071088487634],[510760.7484924103,6651116.027855691,75.86316712376339],[510771.01779425354,6651108.865849112,70.63502766240143],[510760.4172834488,6651120.967376806,70.68670827576341],[510760.694051571,6651116.839765109,75.1377544117634],[510768.67432895803,6651109.444834236,73.1498222599855],[510760.4661599517,6651120.2384517295,71.73143596876339],[510771.0555666358,6651108.34411851,71.57788930140143],[510760.71690613293,6651116.498921096,75.82039188276339],[510760.6655302927,6651117.265120316,75.0156012897634],[510771.0164588016,6651108.884295029,71.04584297440144],[510760.41868573363,6651120.946463679,71.15229896276338],[510768.69412186235,6651109.166613744,73.80906910398552],[510760.47433231527,6651120.116572291,72.15774631976339],[510760.6373101761,6651117.685984117,74.84848653276339],[510768.65465430357,6651109.721392539,73.5297030619855],[510760.48551272985,6651119.949831951,72.57955517876339],[510760.68473239196,6651116.978747706,75.73122723076341],[510760.42307086487,6651120.881065543,71.6295699147634],[510771.012282665,6651108.941977868,71.46696440240142],[510760.60985671764,6651118.095414275,74.63620872376339],[510771.04737012857,6651108.4573326735,72.06079032140143],[510760.4997146709,6651119.73802975,72.9899047217634],[510768.6758811064,6651109.423016342,74.1174379119855],[510760.5836456307,6651118.486316191,74.3799956007634],[510760.66047729267,6651117.340478787,75.63213173676338],[510760.5168559994,6651119.482390669,73.38168441576339],[510760.5650813679,6651118.763176355,74.1605765947634],[510760.5315357052,6651119.263463269,73.6591662757634],[510760.5476572053,6651119.023033513,73.91960694876339],[510760.43066501326,6651120.76780938,72.11247093476341],[510768.6380494014,6651109.954800633,73.7961093769855],[510760.6363418195,6651117.700425807,75.5045089777634],[510771.0050504527,6651109.041872717,71.89305353740141],[510760.4385630479,6651120.650021177,72.4741769197634],[510771.03884563124,6651108.575077197,72.42249630640144],[510760.61254447204,6651118.055330155,75.3480176857634],[510768.65595947346,6651109.703046319,74.4055362629855],[510760.44838837197,6651120.503490129,72.83193476576339],[510760.5893115582,6651118.40181676,75.1628087837634],[510768.62001061573,6651110.20836422,74.04381911698552],[510760.4601421593,6651120.328198736,73.18239098076339],[510760.5668709896,6651118.736486637,74.94955644876339],[510760.4737911222,6651120.124643432,73.52213600776341],[510771.028240974,6651108.721553905,72.78025415240143],[510760.5454455189,6651119.056017741,74.70946800176338],[510770.9946144671,6651109.1860196525,72.31796004140142],[510760.4892663558,6651119.893851841,73.84780311776339],[510760.5252458018,6651119.357268432,74.4442702767634],[510760.5064637145,6651119.637377148,74.15617192576339],[510768.6345342003,6651110.004212329,74.67073398798551],[510768.5940162476,6651110.57375607,74.34126158698552],[510771.01555489015,6651108.896780294,73.13071036740142],[510770.98091218254,6651109.375282303,72.73492674340142],[510768.61180880474,6651110.323653613,74.91082243498552],[510771.0008233076,6651109.1002601115,73.47045539440143],[510768.56621488306,6651110.964548103,74.59747470998552],[510770.96397972835,6651109.609161634,73.13687566040143],[510768.5880067233,6651110.658229413,75.12407476998551],[510770.98412059684,6651109.330966116,73.79612250440144],[510768.53709577,6651111.37386317,74.8097525189855],[510768.5633642235,6651111.00461862,75.30928367198551],[510770.9439591885,6651109.885695116,73.51675646240142],[510770.9655591638,6651109.587345701,74.10449131240142],[510768.5071634841,6651111.794608666,74.97686727598553],[510768.5381230447,6651111.359423203,75.46577496398551],[510770.92706236796,6651110.119082257,73.78316277740142],[510770.9452873036,6651109.86735054,74.39258966340142],[510768.5125232256,6651111.719269044,75.5933977229855],[510768.4769117645,6651112.219844305,75.0990203979855],[510770.908706456,6651110.372623084,74.03087251740142],[510770.92348536884,6651110.168489519,74.65778738840143],[510768.4867965223,6651112.08089844,75.69249321698551],[510768.4468007783,6651112.643101713,75.17769509098551],[510770.8822551003,6651110.737982137,74.32831498740144],[510770.900360455,6651110.487902128,74.89787583540142],[510768.4172395918,6651113.05863082,75.2154379499855],[510768.452670738,6651112.56059017,75.7816578689855],[510770.8539649809,6651111.128739091,74.58452811040144],[510770.87613992713,6651110.822447896,75.11112817040143],[510768.4191680598,6651113.031523161,75.8244331099855],[510770.8243339465,6651111.538017418,74.79680591940142],[510770.851064206,6651111.168806013,75.29633707240143],[510778.1676664001,6651108.786148307,68.76295607119135],[510770.7938754436,6651111.958725148,74.96392067640143],[510770.82537928096,6651111.523578749,75.45282836440143],[510767.86148113036,6651120.870692668,68.81917060298551],[510768.293056566,6651114.804219138,75.2154379499855],[510767.86148113036,6651120.870692668,68.9491706029855],[510778.12128912844,6651109.39398282,68.76295607119135],[510770.7993294106,6651111.883392287,75.58045112340142],[510770.76309189113,6651112.383922617,75.08607379840143],[510778.12128912844,6651109.39398282,68.89295607119135],[510767.8182227738,6651121.478757107,68.81917060298551],[510770.77315042546,6651112.244989226,75.67954661740143],[510770.7324515464,6651112.807142033,75.16474849140143],[510770.7023706667,6651113.222633842,75.20249135040142],[510770.7384247013,6651112.724637897,75.76871126940142],[510778.1676664001,6651108.786148307,70.59175973019136],[510768.17145512794,6651116.513519169,75.2154379499855],[510767.8614809644,6651120.870695001,70.6479742629855],[510770.7043330378,6651113.195528616,75.81148651040142],[510778.1660717975,6651108.807047649,71.05735041719136],[510767.86180351814,6651120.866161,70.8517955469855],[510778.12128912844,6651109.39398282,70.59175973019136],[510768.14189394144,6651116.9290482765,75.17769509098551],[510767.8644818167,6651120.828513289,71.26837483498551],[510768.16952682595,6651116.540624496,75.8244331099855],[510767.8182227738,6651121.478757107,70.64797426198551],[510778.1610852626,6651108.87240268,71.53462136919136],[510778.11988212616,6651109.412423416,71.00257504219137],[510768.1117829553,6651117.352305684,75.0990203979855],[510767.8700647089,6651120.750036932,71.69270195498551],[510768.1360241478,6651117.011557484,75.7816578689855],[510768.0815312357,6651117.7775413245,74.97686727598553],[510767.81971013796,6651121.457849858,71.1135649489855],[510778.1154822424,6651109.470089621,71.42369647019135],[510767.8787329057,6651120.628191753,72.1190123059855],[510778.1524496065,6651108.985584193,72.01752238919136],[510770.1368418328,6651121.0339944735,68.80622400340143],[510768.05159894977,6651118.19828682,74.8097525189855],[510770.5760044724,6651114.968065476,75.20249135040142],[510770.1368418328,6651121.0339944735,68.93622400340142],[510767.8905916578,6651120.461498286,72.5408211649855],[510768.1018983635,6651117.491249215,75.69249321698551],[510767.82436132367,6651121.3924701065,71.59083590098551],[510768.0224798366,6651118.607601887,74.59747470998552],[510767.9056552582,6651120.24975562,72.95117070798551],[510778.1078625459,6651109.569955662,71.84978560519136],[510767.99467847217,6651118.998393919,74.34126158698552],[510778.1434683874,6651109.103294761,72.37922837419137],[510768.07617166016,6651117.8528786125,75.5933977229855],[510767.9238365844,6651119.994188401,73.3429504019855],[510767.97498787957,6651119.275176259,74.1218425809855],[510767.9394069364,6651119.7753225425,73.6204322619855],[510767.9565065591,6651119.5349603705,73.8808729349855],[510767.83241622377,6651121.279245781,72.07373692098551],[510770.09282298345,6651121.642004333,68.80622400340143],[510768.0505718411,6651118.212724451,75.46577496398551],[510767.84079344745,6651121.161490685,72.43544290598551],[510768.02533066226,6651118.567529035,75.30928367198551],[510778.1322955586,6651109.249729227,72.73698622019135],[510778.09686742566,6651109.7140610255,72.27469210919135],[510767.8512148931,6651121.015000829,72.79320075198551],[510768.00068816246,6651118.913918243,75.12407476998551],[510767.86368180544,6651120.839758709,73.1436569669855],[510767.97688608104,6651119.248494042,74.91082243498552],[510767.87815887737,6651120.636260627,73.48340199398551],[510767.9541606855,6651119.567935327,74.67073398798551],[510767.8945730234,6651120.405533911,73.80906910398552],[510767.9327354123,6651119.869101336,74.4055362629855],[510767.9128137794,6651120.149131312,74.1174379119855],[510778.1189297854,6651109.424905081,73.08744243519135],[510778.0824310062,6651109.903269094,72.69165881119135],[510770.4522652506,6651116.677212078,75.20249135040142],[510770.13684166386,6651121.0339968065,70.63502766340143],[510778.1034089207,6651109.628326218,73.42718746219136],[510770.13716988824,6651121.029463212,70.83884894740142],[510778.0645913526,6651110.137080977,73.09360772819136],[510770.42218437104,6651117.092703887,75.16474849140143],[510770.1398952719,6651120.991818881,71.25542823540142],[510770.45030304865,6651116.70431497,75.81148651040142],[510770.09282298345,6651121.642004333,70.63502766240143],[510778.08581131947,6651109.858965688,73.75285457219137],[510770.3915440263,6651117.515923304,75.08607379840143],[510770.14557631285,6651120.913349567,71.67975535540144],[510778.04349816113,6651110.413534708,73.47348853019135],[510770.36076047394,6651117.941120773,74.96392067640143],[510770.416211385,6651117.17520569,75.76871126940142],[510770.0943364958,6651121.621098961,71.10061834940143],[510770.1543968986,6651120.791515325,72.10606570640142],[510778.0662554103,6651110.1152713355,74.06122338019135],[510770.3303019709,6651118.361828502,74.79680591940142],[510770.1664641305,6651120.624836821,72.52787456540142],[510770.0990694505,6651121.555725077,71.57788930140143],[510770.38148566097,6651117.654854361,75.67954661740143],[510778.0256960504,6651110.646854544,73.73989484519134],[510770.3006709365,6651118.771106829,74.58452811040144],[510770.18179255276,6651120.413113163,72.93822410840143],[510770.27238081716,6651119.161863784,74.32831498740144],[510770.2002935112,6651120.157568882,73.33000380240142],[510770.3553066757,6651118.016451299,75.58045112340142],[510770.252344059,6651119.43862128,74.10889598140142],[510770.21613759396,6651119.938722669,73.60748566240143],[510770.2335378323,6651119.698382073,73.86792633540144],[510770.10726595775,6651121.442510913,72.06079032140143],[510778.0448974334,6651110.395195425,74.34932173119135],[510770.32925680536,6651118.3762648385,75.45282836440143],[510778.00635667343,6651110.900322251,73.98760458519135],[510770.1157904552,6651121.32476639,72.42249630640144],[510770.3035718804,6651118.731037575,75.29633707240143],[510770.1263951124,6651121.178289681,72.78025415240143],[510770.2784961593,6651119.07739569,75.11112817040143],[510770.13908119616,6651121.003063292,73.13071036740142],[510778.02192740433,6651110.696247556,74.61451945619136],[510770.25427563133,6651119.411941458,74.89787583540142],[510770.15381277876,6651120.799583474,73.47045539440143],[510770.2311507176,6651119.731354068,74.65778738840143],[510770.1705154896,6651120.56887747,73.79612250440144],[510770.20934878284,6651120.0324930465,74.39258966340142],[510770.18907692254,6651120.312497886,74.10449131240142],[510777.97848811885,6651111.265575936,74.28504705519137],[510777.99756351416,6651111.01556805,74.85460790319135],[510777.948682284,6651111.6562202,74.54126017819137],[510777.97204530967,6651111.350017337,75.06786023819136],[510777.9174636914,6651112.065380495,74.75353798719135],[510777.94562609267,6651111.696275567,75.25306914019136],[510777.8853732962,6651112.485966895,74.92065274419136],[510777.91856503225,6651112.05094599,75.40956043219136],[510777.8911194735,6651112.410655761,75.53718319119135],[510777.8529404364,6651112.911041741,75.04280586619134],[510785.94189542916,6651109.395917872,68.71021190515403],[510777.86353788234,6651112.772148418,75.63627868519136],[510777.8206584568,6651113.334139104,75.12148055919135],[510785.8929379023,6651110.003550005,68.71021190515403],[510777.7889659173,6651113.74951109,75.15922341819135],[510785.8929379023,6651110.003550005,68.84021190515402],[510777.8269516389,6651113.251658762,75.72544333719135],[510777.79103342735,6651113.72241368,75.76821857819135],[510785.94189542916,6651109.395917872,70.53901556415403],[510785.94021210884,6651109.416810256,71.00460625115402],[510785.8929379023,6651110.003550005,70.53901556415403],[510777.1931374316,6651121.55861899,68.76295607119135],[510777.6558293313,6651115.494439354,75.15922341819135],[510777.1931374316,6651121.55861899,68.89295607119135],[510785.9349481421,6651109.482143528,71.48187720315403],[510785.89145261975,6651110.021984461,70.94983087615402],[510777.14676016,6651122.166453505,68.76295607119135],[510785.88680794317,6651110.079631464,71.37095230415402],[510785.925832031,6651109.5952873565,71.96477822315403],[510785.87876431574,6651110.179464255,71.79704143915401],[510785.916351131,6651109.712958732,72.32648420815403],[510777.1931372536,6651121.558621322,70.59175973119136],[510777.5254604647,6651117.203093054,75.15922341819135],[510785.9045566883,6651109.8593444405,72.68424205415403],[510785.86715746875,6651110.323521638,72.22194794315402],[510777.1934830634,6651121.554089035,70.79558101519135],[510777.4937679251,6651117.618465039,75.12148055919135],[510777.1963544665,6651121.516455559,71.21216030319135],[510777.14676016,6651122.166453505,70.59175973019136],[510785.89044729434,6651110.03446197,73.03469826915402],[510777.5233931327,6651117.23018813,75.76821857819135],[510785.8519178618,6651110.51266671,72.63891464515402],[510777.4614859456,6651118.041562402,75.04280586619134],[510777.20233988366,6651121.438008877,71.63648742319137],[510777.1483547626,6651122.145554162,71.05735041719136],[510777.42905308574,6651118.466637248,74.92065274419136],[510777.48747492116,6651117.700943048,75.72544333719135],[510785.8740629077,6651110.237815375,73.37444329615403],[510777.21163305483,6651121.316209772,72.06279777419135],[510777.3969626907,6651118.887223649,74.75353798719135],[510785.8330856775,6651110.746400744,73.04086356215402],[510777.2243468195,6651121.149579335,72.48460663319135],[510777.15334129747,6651122.080199131,71.53462136919136],[510777.4508886776,6651118.180453393,75.63627868519136],[510777.3657440979,6651119.296383943,74.54126017819137],[510777.2404965012,6651120.937916735,72.89495617619136],[510777.33593826316,6651119.687028207,74.28504705519137],[510785.8554862428,6651110.468378054,73.70011040615402],[510777.25998869573,6651120.682446152,73.28673587019135],[510777.4233070865,6651118.541946049,75.53718319119135],[510777.31482798455,6651119.963705887,74.06562804919135],[510777.2766816656,6651120.463663052,73.56421773019136],[510777.2950141663,6651120.2233917685,73.82465840319136],[510777.16197695344,6651121.967017616,72.01752238919136],[510777.39586152777,6651118.901655821,75.40956043219136],[510785.81081894116,6651111.022762426,73.42074436415402],[510777.17095817265,6651121.849307049,72.37922837419137],[510777.36880046735,6651119.256326244,75.25306914019136],[510777.1821310015,6651121.702872584,72.73698622019135],[510785.83484231716,6651110.724598361,74.00847921415402],[510777.3423812504,6651119.602584473,75.06786023819136],[510777.1954967746,6651121.527696728,73.08744243519135],[510777.3168630458,6651119.93703376,74.85460790319135],[510785.79202638846,6651111.2560045775,73.68715067915402],[510777.21101763926,6651121.324275592,73.42718746219136],[510777.29249915574,6651120.256354256,74.61451945619136],[510777.2286152405,6651121.093636122,73.75285457219137],[510777.2695291266,6651120.557406387,74.34932173119135],[510777.24817114964,6651120.837330476,74.06122338019135],[510785.81229606346,6651111.004429248,74.29657756515402],[510785.77161104215,6651111.509387892,73.93486041915402],[510791.2508608473,6651109.831415902,68.67094383254415],[510785.7880480692,6651111.305381143,74.56177529015402],[510791.2001412827,6651110.438903492,68.67094383254415],[510785.742191987,6651111.874519964,74.23230288915403],[510791.2001412827,6651110.438903492,68.80094383254415],[510785.7623286649,6651111.624595318,74.80186373715402],[510785.7107278688,6651112.265034161,74.48851601215402],[510785.7353907243,6651111.958933249,75.01511607215404],[510791.2508608473,6651109.831415902,70.49974749154416],[510785.6777723921,6651112.674058223,74.70079382115402],[510785.7075016425,6651112.305076189,75.20032497415403],[510791.2491169424,6651109.852303315,70.96533817854414],[510791.2001412827,6651110.438903492,70.49974749154416],[510785.6438966093,6651113.094504588,74.86790857815402],[510785.6789350074,6651112.659628523,75.35681626615404],[510791.2436635195,6651109.917621044,71.44260913054416],[510791.1986025431,6651110.457333564,70.91056280354415],[510785.6499624821,6651113.019218529,75.48443902515403],[510785.60965930833,6651113.519437904,74.99006170015403],[510791.19379069924,6651110.514966855,71.33168423154414],[510791.234219309,6651110.030737959,71.92551015054416],[510785.62084635603,6651113.3805908235,75.58353451915403],[510785.57558128214,6651113.942394393,75.06873639315403],[510791.1854575724,6651110.614775898,71.75777336654414],[510791.2243971805,6651110.148381343,72.28721613554416],[510785.54212549014,6651114.357628079,75.10647925215402],[510785.5822245929,6651113.859941513,75.67269917115404],[510791.2121782422,6651110.294732231,72.64497398154415],[510791.17343298154,6651110.758799013,72.18267987054416],[510785.54430802853,6651114.33053969,75.71547441215402],[510791.1975610349,6651110.469808105,72.99543019654415],[510791.15764488355,6651110.947899089,72.59964657254415],[510795.0084456514,6651110.149023901,68.64155541765334],[510791.1805869553,6651110.673113138,73.33517522354416],[510791.1381349073,6651111.181577524,73.00159548954414],[510784.91314737085,6651122.164135896,68.71021190515403],[510794.95647894987,6651110.756406079,68.64155541765334],[510785.40158169024,6651116.101975361,75.10647925215402],[510784.91314737085,6651122.164135896,68.84021190515402],[510794.95647894987,6651110.756406079,68.77155541765335],[510791.16134169477,6651110.90362097,73.66084233354415],[510791.1150667654,6651111.457873467,73.38147629154415],[510784.86418984405,6651122.771768029,68.71021190515403],[510791.1399547704,6651111.159780329,73.96921114154415],[510791.09559784713,6651111.691060135,73.64788260654416],[510795.0084456514,6651110.149023901,70.47035907665334],[510791.1165970511,6651111.439544652,74.25730949254415],[510791.07444772887,6651111.944383178,73.89559234654415],[510795.0066588658,6651110.169907692,70.93594976365333],[510784.91314718296,6651122.164138228,70.53901556515402],[510794.95647894987,6651110.756406079,70.47035907665334],[510785.2639595951,6651117.810060155,75.10647925215402],[510791.0914763436,6651111.740424957,74.52250721754415],[510784.9135122323,6651122.159607449,70.74283684915402],[510791.0439698481,6651112.309428392,74.19303481654416],[510785.230503803,6651118.225293839,75.06873639315403],[510795.00107134925,6651110.235214085,71.41322071565334],[510794.95490237436,6651110.774832951,70.88117438865333],[510784.9165433893,6651122.121986504,71.15941613715403],[510784.86418984405,6651122.771768029,70.53901556415403],[510785.26177724457,6651117.8371462105,75.71547441215402],[510791.06483126816,6651112.059563198,74.76259566454415],[510785.1964257768,6651118.64825033,74.99006170015403],[510784.9228618124,6651122.04356594,71.58374325715403],[510794.9499722127,6651110.832456242,71.30229581665333],[510794.9913949164,6651110.348311373,71.89612173565334],[510791.01137329993,6651112.699849695,74.44924793954415],[510784.8658731642,6651122.750875643,71.00460625115402],[510785.16218847584,6651119.0731836455,74.86790857815402],[510785.22386068024,6651118.307744387,75.67269917115404],[510784.93267202034,6651121.921807388,72.01005360815404],[510791.03692380013,6651112.393821598,74.97584799954417],[510785.12831269304,6651119.493630009,74.70079382115402],[510784.9460931306,6651121.755232432,72.43186246715402],[510794.9414341836,6651110.932247965,71.72838495165335],[510784.87113713106,6651122.685542373,71.48187720315403],[510794.98133127275,6651110.465934342,72.25782772065334],[510785.18523891707,6651118.787095077,75.58353451915403],[510785.0953572165,6651119.902654071,74.48851601215402],[510784.9631413191,6651121.543640307,72.84221201015403],[510790.9772317177,6651113.108776461,74.66152574854415],[510785.0638930982,6651120.293168268,74.23230288915403],[510784.9837179854,6651121.288254784,73.23399170415404],[510785.15612279094,6651119.148467371,75.48443902515403],[510785.04160832387,6651120.5697538275,74.01288388315402],[510791.0080309581,6651112.739882199,75.16105690154416],[510785.0013396887,6651121.06954453,73.51147356415402],[510785.02069214004,6651120.829353245,73.77191423715402],[510784.88025324215,6651122.572398544,71.96477822315403],[510794.96881188464,6651110.612259835,72.61558556665334],[510794.92911392177,6651111.076246088,72.15329145565333],[510785.1271502656,6651119.508057376,75.35681626615404],[510784.8897341422,6651122.454727169,72.32648420815403],[510785.0985836306,6651119.8626097115,75.20032497415403],[510784.9015285847,6651122.30834146,72.68424205415403],[510790.9421367065,6651113.529122812,74.82864050554414],[510790.9784361769,6651113.094350194,75.31754819354417],[510785.0706945487,6651120.20875265,75.01511607215404],[510784.91563797876,6651122.13322393,73.03469826915402],[510794.9538352567,6651110.787305329,72.96604178165335],[510785.0437566082,6651120.543090581,74.80186373715402],[510784.9320223654,6651121.929870525,73.37444329615403],[510794.91293761216,6651111.265313352,72.57025815765333],[510785.0180372038,6651120.862304756,74.56177529015402],[510784.9505990303,6651121.699307847,73.70011040615402],[510784.9937892096,6651121.163256651,74.29657756515402],[510784.971242956,6651121.44308754,74.00847921415402],[510790.948420897,6651113.453854661,75.44517095254415],[510790.9066671655,6651113.953955046,74.95079362754416],[510794.93644380354,6651110.990575083,73.30578680865334],[510794.8929479077,6651111.498951239,72.97220707465333],[510790.9182568479,6651113.815140994,75.54426644654416],[510790.8713626319,6651114.376810925,75.02946832054415],[510794.91672532377,6651111.221042917,73.63145391865334],[510790.83670272736,6651114.791945835,75.06721117954415],[510790.8782450431,6651114.294377658,75.63343109854416],[510794.8693125461,6651111.775199239,73.35208787665334],[510794.8948125191,6651111.477157826,73.93982272665333],[510790.8389638178,6651114.7648638915,75.67620633954415],[510794.8493649091,6651112.008345443,73.61849419165333],[510794.8708804599,6651111.756873603,74.22792107765333],[510794.8276947333,6651112.261624526,73.86620393165335],[510794.8451420624,6651112.057701698,74.49311880265333],[510790.18508696026,6651122.596596671,68.67094383254415],[510790.69110059395,6651116.535878179,75.06721117954415],[510794.7964674358,6651112.626606397,74.16364640165334],[510790.18508696026,6651122.596596671,68.80094383254415],[510794.81784181466,6651112.376784561,74.73320724965333],[510790.1343673957,6651123.204084262,68.67094383254415],[510794.76306937524,6651113.016959954,74.41985952465333],[510794.7892481335,6651112.710984959,74.94645958465334],[510794.72808829,6651113.42581576,74.63213733365333],[510794.75964484905,6651113.0569855105,75.13166848665334],[510790.1850867657,6651122.596599001,70.49974749254415],[510790.54852532095,6651118.24355666,75.06721117954415],[510794.6921303321,6651113.846089169,74.79925209065334],[510790.18546495354,6651122.592069301,70.70356877654415],[510794.7293223656,6651113.411391997,75.28815977865335],[510790.51386541646,6651118.65869157,75.02946832054415],[510790.18860520545,6651122.554457305,71.12014806454415],[510790.1343673957,6651123.204084262,70.49974749154416],[510790.5462644252,6651118.270636272,75.67620633954415],[510794.6985690438,6651113.770834081,75.41578253765334],[510794.6557886352,6651114.270847687,74.92140521265333],[510790.4785608828,6651119.08154745,74.95079362754416],[510790.1951510358,6651122.476055396,71.54447518454415],[510790.1361113005,6651123.183196848,70.96533817854414],[510790.4430913418,6651119.506379684,74.82864050554414],[510790.5069831999,6651118.741122505,75.63343109854416],[510794.6676632947,6651114.132057722,75.51487803165334],[510790.20531432447,6651122.354325807,71.97078553554417],[510794.6196160029,6651114.693630189,75.00007990565334],[510790.4079963306,6651119.926726034,74.66152574854415],[510790.21921847604,6651122.187790476,72.39259439454416],[510790.1415647235,6651123.117879118,71.44260913054416],[510790.466971395,6651119.220359169,75.54426644654416],[510803.10035180685,6651110.859383242,68.5737739278946],[510790.3738547484,6651120.335652799,74.44924793954415],[510790.23688024847,6651121.976248683,72.80294393754416],[510794.5841038503,6651115.108693064,75.03782276465333],[510790.3412582002,6651120.726074102,74.19303481654416],[510794.6266676447,6651114.611211228,75.60404268365333],[510790.2581974926,6651121.720923911,73.19472363154416],[510790.436807346,6651119.581645502,75.44517095254415],[510790.3181713712,6651121.002593868,73.97361581054415],[510790.27645342145,6651121.5022656815,73.47220549154414],[510790.15100893396,6651123.004762203,71.92551015054416],[510790.29650238977,6651121.262131533,73.73264616454415],[510790.4067920661,6651119.94114997,75.31754819354417],[510790.16083106253,6651122.88711882,72.28721613554416],[510803.0456994135,6651111.4665296525,68.5737739278946],[510790.37719728483,6651120.295617964,75.16105690154416],[510790.1730500008,6651122.740767932,72.64497398154415],[510794.5864205384,6651115.08161582,75.64681792465333],[510803.0456994135,6651111.4665296525,68.70377392789462],[510790.3483044428,6651120.641678565,74.97584799954417],[510790.187667208,6651122.565692058,72.99543019654415],[510790.3203969748,6651120.975936965,74.76259566454415],[510790.20464128774,6651122.362387026,73.33517522354416],[510790.2937518994,6651121.295075206,74.52250721754415],[510790.22388654825,6651122.131879194,73.66084233354415],[510790.26863119187,6651121.595955512,74.25730949254415],[510790.2452734725,6651121.875719834,73.96921114154415],[510793.9164655865,6651122.911989608,68.64155541765334],[510803.10035180685,6651110.859383242,70.40257758689461],[510793.9164655865,6651122.911989608,68.77155541765335],[510794.4349215247,6651116.852322794,75.03782276465333],[510803.0984726784,6651110.880258927,70.8681682738946],[510803.0456994135,6651111.4665296525,70.40257758689461],[510793.864498885,6651123.519371784,68.64155541765334],[510803.0925963934,6651110.945539972,71.34543922589461],[510803.04404135904,6651111.484949374,70.8133928988946],[510803.03885640175,6651111.542550296,71.2345143268946],[510803.0824198726,6651111.058593357,71.82834024589461],[510793.91646538716,6651122.911991938,70.47035907765333],[510794.28884048655,6651118.559704953,75.03782276465333],[510793.91685287433,6651122.9074630225,70.67418036165333],[510803.0298771186,6651111.642303282,71.6606034618946],[510803.0718361297,6651111.1761706695,72.19004623089461],[510794.2533283341,6651118.974767827,75.00007990565334],[510793.92007034144,6651122.869857553,71.09075964965334],[510793.864498885,6651123.519371784,70.47035907665334],[510794.2865239979,6651118.5867798645,75.64681792465333],[510803.0586697269,6651111.322439362,72.54780407689461],[510803.016920133,6651111.786245511,72.0855099658946],[510794.2171557018,6651119.3975503305,74.92140521265333],[510793.9267771263,6651122.791469249,71.51508676965334],[510793.8662856706,6651123.498487995,70.93594976365333],[510794.18081400485,6651119.822308846,74.79925209065334],[510794.2462768916,6651119.057184458,75.60404268365333],[510793.9371903188,6651122.669760783,71.94139712065333],[510803.04291909165,6651111.497416909,72.89826029189462],[510794.1448560469,6651120.242582257,74.63213733365333],[510802.9999078155,6651111.975239386,72.5024766678946],[510793.9514363577,6651122.503254349,72.36320597965333],[510793.8718731871,6651123.433181599,71.41322071565334],[510794.2052812416,6651119.536337962,75.51487803165334],[510794.1098749616,6651120.651438063,74.41985952465333],[510793.96953241323,6651122.291749264,72.77355552265335],[510794.0764769012,6651121.041791618,74.16364640165334],[510793.9913738244,6651122.036468796,73.16533521665333],[510794.0528223931,6651121.318263401,73.94422739565333],[510794.1743754926,6651119.897561604,75.41578253765334],[510794.0100786459,6651121.817848509,73.44281707665333],[510793.88154962007,6651123.320084312,71.89612173565334],[510794.0306205958,6651121.5777560305,73.70325774965333],[510803.02462883067,6651111.70060776,73.23800531889461],[510802.97888502275,6651112.20878658,72.9044255848946],[510794.14362217084,6651120.257003688,75.28815977865335],[510793.89161326364,6651123.202461343,72.25782772065334],[510794.11329968733,6651120.6114101745,75.13166848665334],[510793.90413265175,6651123.05613585,72.61558556665334],[510803.0038912799,6651111.930986134,73.5636724288946],[510794.08369640284,6651120.957410725,74.94645958465334],[510793.91910927976,6651122.881090356,72.96604178165335],[510794.05510272173,6651121.291611123,74.73320724965333],[510793.93650073285,6651122.677820602,73.30578680865334],[510794.02780247387,6651121.6106939865,74.49311880265333],[510793.95621921256,6651122.447352768,73.63145391865334],[510794.00206407654,6651121.911522082,74.22792107765333],[510793.97813201725,6651122.1912378585,73.93982272665333],[510802.9540281618,6651112.484927348,73.28430638689461],[510802.98084599926,6651112.187001626,73.8720412368946],[510802.93304961064,6651112.717983052,73.5507127018946],[510802.95567710686,6651112.466608825,74.1601395878946],[510802.9102594982,6651112.971163821,73.7984224418946],[510802.9286085231,6651112.767320149,74.4253373128946],[510802.87741834234,6651113.336004017,74.09586491189461],[510802.89989737084,6651113.086279154,74.6654257598946],[510802.8422942363,6651113.726206049,74.3520780348946],[510802.8698259392,6651113.420349826,74.87867809489461],[510802.80550529313,6651114.1349031525,74.5643558438946],[510802.83869272703,6651113.766216071,75.06388699689461],[510802.7676889914,6651114.555013424,74.7314706008946],[510802.80680314684,6651114.120484985,75.22037828889462],[510802.7744604622,6651114.479787547,75.34800104789461],[510802.7294691188,6651114.979607061,74.85362372289461],[510802.7419574728,6651114.840870972,75.44709654189461],[510802.6914270481,6651115.402225453,74.9322984158946],[510802.65407959156,6651115.817127215,74.9700412748946],[510802.698843126,6651115.319838485,75.5362611938946],[510811.421332634,6651111.627483879,68.49766535314345],[510802.6565160085,6651115.790060479,75.5790364348946],[510811.8359754414,6651111.666758015,68.49370265615114],[510811.36391851935,6651112.234375359,68.49766535314345],[510811.36391851935,6651112.234375359,68.62766535314343],[510811.7784237074,6651112.273636458,68.49370265615114],[510811.7784237074,6651112.273636458,68.62370265615114],[510801.951937106,6651123.617394755,68.5737739278946],[510801.951937106,6651123.617394755,68.70377392789462],[510802.49718737236,6651117.560080119,74.9700412748946],[510811.421332634,6651111.627483879,70.32646901214345],[510801.89728471264,6651124.224541166,68.5737739278946],[510811.4193585485,6651111.648350798,70.79205969914342],[510811.8359754414,6651111.666758015,70.32250631515114],[510811.36391851935,6651112.234375359,70.32646901214345],[510811.4131853202,6651111.713604433,71.26933065114343],[510811.36217667925,6651112.252787345,70.73728432414343],[510811.8339966241,6651111.687624484,70.78809700215113],[510811.7784237074,6651112.273636458,70.32250631515114],[510801.95193689625,6651123.617397084,70.4025775878946],[510802.3435567181,6651119.2667995235,74.9700412748946],[510811.3567297131,6651112.3103640815,71.15840575214342],[510801.95234440913,6651123.612869927,70.6063988718946],[510811.8278085988,6651111.752876718,71.26536795415115],[510811.40249455447,6651111.826610349,71.75223167114345],[510811.77667769225,6651112.292048049,70.73332162715114],[510802.30620926153,6651119.681701284,74.9322984158946],[510801.95572815824,6651123.575279055,71.0229781598946],[510801.89728471264,6651124.224541166,70.40257758689461],[510811.34729668446,6651112.410075184,71.58449488714342],[510811.3913759888,6651111.944138291,72.11393765614343],[510811.7712176699,6651112.349623549,71.15444305515113],[510802.341120511,6651119.293863927,75.5790364348946],[510811.8170922077,6651111.865880206,71.74826897415115],[510802.26816719095,6651120.104319678,74.85362372289461],[510801.96278155665,6651123.496921178,71.44730527989461],[510801.8991638411,6651124.203665481,70.8681682738946],[510802.2299473184,6651120.5289133135,74.7314706008946],[510802.2987933934,6651119.764085923,75.5362611938946],[510801.97373291344,6651123.375259956,71.8736156308946],[510811.3775442549,6651112.090345569,72.47169550214343],[510811.3336849502,6651112.553956972,72.00940139114343],[510811.7617620306,6651112.449332511,71.58053219015113],[510811.8059469912,6651111.983405625,72.10997495915115],[510802.1921310166,6651120.949023586,74.5643558438946],[510801.9887152021,6651123.208818156,72.2954244898946],[510801.90504012606,6651124.138384436,71.34543922589461],[510802.2556790467,6651120.243053436,75.44709654189461],[510802.15534207347,6651121.357720688,74.3520780348946],[510802.0077464801,6651122.99739517,72.70577403289462],[510811.36099770083,6651112.265249644,72.82215171714343],[510802.12021796743,6651121.747922719,74.09586491189461],[510802.0307166775,6651122.742213795,73.09755372689462],[510811.79208210326,6651112.129609763,72.46773280515114],[510811.7481176696,6651112.5932112085,72.00543869415114],[510802.0953409703,6651122.024287186,73.8764459058946],[510801.915216647,6651124.02533105,71.82834024589461],[510802.05038818304,6651122.52367837,73.3750355868946],[510802.2231760573,6651120.60413686,75.34800104789461],[510811.315812958,6651112.742871491,72.42636809314342],[510802.0719917616,6651122.283679088,73.6354762598946],[510801.9258003898,6651123.907753739,72.19004623089461],[510802.19083337265,6651120.963439422,75.22037828889462],[510801.9389667926,6651123.761485045,72.54780407689461],[510802.15894379246,6651121.317708337,75.06388699689461],[510811.3417831874,6651112.468355179,73.16189674414345],[510811.7754958878,6651112.304510082,72.81818902015114],[510811.73020283884,6651112.78212167,72.42240539615113],[510801.95471742784,6651123.586507498,72.89826029189462],[510802.12781058036,6651121.663574581,74.87867809489461],[510811.2937278312,6651112.9763206225,72.82831701014342],[510801.97300768894,6651123.383316647,73.23800531889461],[510802.09773914865,6651121.997645252,74.6654257598946],[510801.9937452397,6651123.152938274,73.5636724288946],[510802.06902799645,6651122.316604258,74.4253373128946],[510802.0167905203,6651122.89692278,73.8720412368946],[510802.04195941257,6651122.617315581,74.1601395878946],[510811.31999771675,6651112.698636821,73.48756385414343],[510811.756235318,6651112.507611254,73.15793404715114],[510811.70806477504,6651113.015565787,72.82435431315113],[510811.2676148913,6651113.252345445,73.20819781214342],[510811.29578790074,6651112.954544818,73.79593266214343],[510811.73439762834,6651112.73788795,73.48360115715114],[510811.2455762418,6651113.485303292,73.47460412714342],[510811.6818892434,6651113.291584682,73.20423511515114],[510811.2693471617,6651113.234034614,74.08403101314344],[510811.71012978244,6651112.99379045,73.79196996515114],[510811.2216344883,6651113.738377754,73.72231386714343],[510811.65979776817,6651113.524537525,73.47064143015113],[510811.240910735,6651113.534619673,74.34922873814342],[510811.68362566596,6651113.273274244,74.08006831615114],[510811.6357986272,6651113.777606551,73.71835117015114],[510811.1871337872,6651114.103064761,74.01975633714343],[510811.2107487368,6651113.853444751,74.58931718514343],[510811.65512107825,6651113.573852846,74.34526604115113],[510811.60121522925,6651114.142285723,74.01579364015114],[510811.1502347726,6651114.493102952,74.27596946014343],[510811.17915772105,6651114.1873751525,74.80256952014344],[510811.6248867831,6651113.892671078,74.58535448815114],[510811.5642277693,6651114.532315538,74.27200676315114],[510811.1115867927,6651114.901628448,74.48824726914343],[510811.14645127015,6651114.533096174,74.98777842214344],[510811.5932200448,6651114.226594306,74.79860682315116],[510811.52548715175,6651114.94083226,74.48428457215114],[510811.07185953925,6651115.321562323,74.65536202614342],[510811.11295023025,6651114.887216336,75.14426971414343],[510811.56043519796,6651114.5723079005,74.98381572515115],[510811.0789731894,6651115.246368032,75.27189247314342],[510811.0317083214,6651115.74597768,74.77751514814344],[510811.48566467356,6651115.360757115,74.65139932915113],[510811.52685385733,6651114.926420458,75.14030701715116],[510811.0448277431,6651115.607299843,75.37098796714345],[510810.9917438904,6651116.168418622,74.85618984114345],[510811.4927953749,6651115.285564439,75.26792977615115],[510811.4454172149,6651115.785163356,74.77355245115115],[510810.952509174,6651116.583146171,74.89393270014344],[510810.9995347212,6651116.086066245,75.46015261914343],[510811.4585680833,6651115.646488498,75.36702527015115],[510811.40535699076,6651116.207595225,74.85222714415114],[510810.9550687091,6651116.556090802,75.50292786014343],[510811.36602823023,6651116.622313866,74.88997000315113],[510811.41316649574,6651116.125244617,75.45618992215115],[510820.24433289777,6651112.483658005,68.40985667120633],[510811.3685939005,6651116.595259079,75.49896516315114],[510810.2148856826,6651124.380138498,68.49766535314345],[510820.1839904423,6651113.09026532,68.40985667120633],[510810.2148856826,6651124.380138498,68.62766535314343],[510820.1839904423,6651113.09026532,68.53985667120634],[510810.7876888007,6651118.3253672365,74.89393270014344],[510810.6266366848,6651124.419138728,68.49370265615114],[510810.1574715679,6651124.987029978,68.49766535314345],[510810.6266366848,6651124.419138728,68.62370265615114],[510811.2008127892,6651118.3644975135,74.88997000315113],[510810.56908495084,6651125.026017172,68.49370265615114],[510820.24433289777,6651112.483658005,70.23866033020633],[510820.2422581264,6651112.5045151515,70.70425101720632],[510810.2148854623,6651124.380140827,70.32646901314342],[510820.1839904423,6651113.09026532,70.23866033020633],[510810.62629480753,6651120.031370016,74.89393270014344],[510810.2153135678,6651124.375615571,70.53029029714344],[510820.23577003967,6651112.5697382325,71.18152196920633],[510820.18215976167,6651113.108668686,70.64947564220633],[510810.58706009114,6651120.446097565,74.85618984114345],[510810.2188683061,6651124.338040482,70.94686958514345],[510810.626636464,6651124.419141056,70.32250631615113],[510810.1574715679,6651124.987029978,70.32646901214345],[510811.03903194104,6651120.07046365,74.88997000315113],[510810.6237354928,6651120.058423055,75.50292786014343],[510810.62706559565,6651124.414615897,70.52632760015113],[510810.54709566006,6651120.868538506,74.77751514814344],[510810.22627813026,6651124.259715507,71.37119670514343],[510820.17643497925,6651113.166218462,71.07059707020632],[510810.1594456534,6651124.966163059,70.79205969914342],[510820.22453400376,6651112.682691237,71.66442298920633],[510810.9997031806,6651120.485182291,74.85222714415114],[510810.6306288545,6651124.377041617,70.94290688815114],[510810.5069444423,6651121.292953864,74.65536202614342],[510810.56908495084,6651125.026017172,70.32250631515114],[510810.57926948083,6651120.528447612,75.46015261914343],[510810.2377828864,6651124.138105368,71.79750705614343],[510811.0364664917,6651120.097516108,75.49896516315114],[510810.46721718885,6651121.712887738,74.48824726914343],[510810.9596429564,6651120.907614159,74.77355245115115],[510810.1656188817,6651124.900909424,71.26933065114343],[510810.2535222673,6651123.971733454,72.21931591514344],[510820.1665208299,6651113.2658828795,71.49668620520632],[510810.6380564398,6651124.298718323,71.36723400815114],[510820.21284834837,6651112.800164151,72.02612897420633],[510810.53397645894,6651121.007214014,75.37098796714345],[510810.42856920895,6651122.121413235,74.27596946014343],[510810.5710637681,6651125.005150702,70.78809700215113],[510810.2735152431,6651123.760399242,72.62966545814344],[510810.9193954977,6651121.3320204,74.65139932915113],[510810.9918938964,6651120.56753057,75.45618992215115],[510810.39167019434,6651122.511451426,74.01975633714343],[510810.2976461817,6651123.505325014,73.02144515214343],[510810.6495887723,6651124.177110796,71.79354435915116],[510810.1763096474,6651124.787903508,71.75223167114345],[510810.3655361008,6651122.787699851,73.80033733114344],[510810.3183117374,6651123.286881349,73.29892701214342],[510810.49983101257,6651121.368145825,75.27189247314342],[510810.34100699855,6651123.046982837,73.55936768514343],[510810.8795730196,6651121.751945255,74.48428457215114],[510810.5772517934,6651124.939898468,71.26536795415115],[510820.19831114286,6651112.946302971,72.38388682020633],[510810.66536587983,6651124.010742455,72.21535321815114],[510820.1522148448,6651113.409697298,71.92159270920632],[510810.18742821325,6651124.670375564,72.11393765614343],[510810.4658539716,6651121.72729752,75.14426971414343],[510810.9464923089,6651121.046286688,75.36702527015115],[510810.84083240206,6651122.160461978,74.27200676315114],[510810.68540677807,6651123.799412782,72.62570276115115],[510810.20125994703,6651124.524168288,72.47169550214343],[510810.4323529317,6651122.0814176835,74.98777842214344],[510810.803844942,6651122.550491793,74.01579364015114],[510810.7095955576,6651123.544344032,73.01748245515115],[510810.5879681845,6651124.826894979,71.74826897415115],[510810.77764820616,6651122.826734283,73.79637463415114],[510810.7303106478,6651123.3259050585,73.29496431515113],[510810.91226501734,6651121.407210747,75.26792977615115],[510810.7530603086,6651123.0860117,73.55540498815114],[510810.217806501,6651124.349264212,72.82215171714343],[510810.399646481,6651122.427138704,74.80256952014344],[510820.1809206509,6651113.1211251505,72.73434303520634],[510810.23702101444,6651124.1461586775,73.16189674414345],[510810.36805546505,6651122.761069104,74.58931718514343],[510810.59911340097,6651124.70936956,72.10997495915115],[510820.1334313121,6651113.598523363,72.33855941120632],[510810.2588064852,6651123.915877035,73.48756385414343],[510810.8782065349,6651121.7663547285,75.14030701715116],[510810.337893467,6651123.079894183,74.34922873814342],[510810.28301630117,6651123.659969039,73.79593266214343],[510810.3094570402,6651123.380479243,74.08403101314344],[510810.61297828896,6651124.563165423,72.46773280515114],[510810.84462519427,6651122.120467287,74.98381572515115],[510810.6295645044,6651124.388265104,72.81818902015114],[510810.8118403474,6651122.466180881,74.79860682315116],[510820.16072612326,6651113.324135586,73.07408806220633],[510810.6488250742,6651124.185163932,73.15793404715114],[510810.7801736092,6651122.800104109,74.58535448815114],[510810.6706627638,6651123.954887237,73.48360115715114],[510810.7499393139,6651123.11892234,74.34526604115113],[510820.11021975894,6651113.831863187,72.74050832820632],[510810.69493060984,6651123.698984737,73.79196996515114],[510810.72143472626,6651123.419500943,74.08006831615114],[510820.1378295097,6651113.554309403,73.39975517220633],[510820.08277495846,6651114.107758766,73.12038913020633],[510820.1123848999,6651113.810097576,73.70812398020632],[510820.05961225304,6651114.340607535,73.38679544520632],[510820.08459558134,6651114.089456508,73.99622233120633],[510820.034449378,6651114.593563502,73.63450518520634],[510820.0547087875,6651114.389900825,74.26142005620632],[510819.99818900827,6651114.958079752,73.93194765520633],[510820.02300841134,6651114.7085766215,74.50150850320632],[510819.95940800203,6651115.347935317,74.18816077820632],[510819.98980613204,6651115.0423506675,74.71476083820633],[510819.9187888264,6651115.75626953,74.40043858720632],[510819.9554315264,6651115.387909813,74.89996974020633],[510819.87703533005,6651116.176006781,74.56755334420632],[510819.92022180447,6651115.741864166,75.05646103220633],[510819.88451180374,6651116.100847697,75.18408379120633],[510819.8348362456,6651116.600223415,74.68970646620633],[510819.84862480813,6651116.461610511,75.28317928520633],[510819.79283347464,6651117.022466558,74.76838115920633],[510819.7515976367,6651117.43699992,74.80612401820632],[510819.8010216678,6651116.940152741,75.37234393720632],[510828.64883180737,6651113.339222212,68.31939778668155],[510819.75428771804,6651117.409957219,75.41511917820633],[510828.58569991105,6651113.945545568,68.31939778668155],[510828.58569991105,6651113.945545568,68.44939778668154],[510818.976352508,6651125.230341487,68.40985667120633],[510818.976352508,6651125.230341487,68.53985667120634],[510819.57837078994,6651119.178405232,74.80612401820632],[510818.91601005243,6651125.836948804,68.40985667120633],[510828.64883180737,6651113.339222212,70.14820144568156],[510828.6466611259,6651113.360069597,70.61379213268154],[510828.58569991105,6651113.945545568,70.14820144568156],[510818.97635227646,6651125.230343814,70.23866033120632],[510828.63987311535,6651113.425262147,71.09106308468155],[510828.5837846038,6651113.963940319,70.55901675768155],[510819.4087450819,6651120.883609215,74.80612401820632],[510818.97680221696,6651125.225820677,70.44248161520632],[510828.5777951828,6651114.021463157,70.98013818568154],[510819.3675092439,6651121.2981425775,74.76838115920633],[510818.9805382606,6651125.188263183,70.85906090320633],[510828.62811767304,6651113.538162275,71.57396410468156],[510818.91601005243,6651125.836948804,70.23866033020633],[510819.4060552323,6651120.910649587,75.41511917820633],[510819.3255064731,6651121.720385721,74.68970646620633],[510818.98832601437,6651125.109974882,71.28338802320633],[510828.5674227337,6651114.121080917,71.40622732068155],[510818.91808482393,6651125.816091655,70.70425101720632],[510828.61589182675,6651113.655580199,71.93567008968155],[510819.2833073886,6651122.144602355,74.56755334420632],[510819.00041755725,6651124.988421684,71.70969837420633],[510819.3593212824,6651121.380454067,75.37234393720632],[510831.5707765937,6651113.645824876,68.28638856520544],[510819.24155389227,6651122.564339605,74.40043858720632],[510818.92457291065,6651125.750868574,71.18152196920633],[510819.0169597072,6651124.822127669,72.13150723320632],[510828.6006826123,6651113.801650608,72.29342793568155],[510828.5524554282,6651114.264828015,71.83113382468156],[510819.31171814207,6651121.858996295,75.28317928520633],[510819.2009347166,6651122.9726738185,74.18816077820632],[510819.0379724018,6651124.610892409,72.54185677620634],[510819.1621537104,6651123.362529384,73.93194765520633],[510819.0633341111,6651124.355937613,72.93363647020632],[510818.93580894655,6651125.637915569,71.66442298920633],[510819.1346866775,6651123.6386484625,73.71252864920632],[510819.0850536898,6651124.137596229,73.21111833020632],[510819.10890649655,6651123.897810046,73.47155900320632],[510819.2758311466,6651122.219759109,75.18408379120633],[510831.50667490816,6651114.2520464705,68.28638856520544],[510831.50667490816,6651114.2520464705,68.41638856520542],[510818.94749460195,6651125.520442656,72.02612897420633],[510828.5824882128,6651113.976390952,72.64388415068154],[510819.24012114585,6651122.57874264,75.05646103220633],[510828.53280359216,6651114.453565687,72.24810052668154],[510818.96203180746,6651125.374303838,72.38388682020633],[510819.2049114239,6651122.932696994,74.89996974020633],[510818.9794222994,6651125.199481656,72.73434303520634],[510819.17053681816,6651123.278256139,74.71476083820633],[510818.99961682694,6651124.996471221,73.07408806220633],[510819.137334539,6651123.612030185,74.50150850320632],[510828.5613601561,6651114.179306355,72.98362917768156],[510819.02251344064,6651124.766297404,73.39975517220633],[510819.10563416284,6651123.930705981,74.26142005620632],[510819.0479580504,6651124.51050923,73.70812398020632],[510819.07574736886,6651124.231150298,73.99622233120633],[510828.5085190422,6651114.686796282,72.65004944368154],[510831.5707765937,6651113.645824876,70.11519222420543],[510828.5374051045,6651114.409372427,73.30929628768155],[510828.4798055555,6651114.962562713,73.02993024568154],[510831.56857256766,6651113.666668761,70.58078291120542],[510831.50667490816,6651114.2520464705,70.11519222420543],[510828.5107842709,6651114.665040862,73.61766509568155],[510828.45557211153,6651115.195302483,73.29633656068155],[510831.56168028445,6651113.73185037,71.05805386320544],[510831.5047301793,6651114.270438133,70.52600753620543],[510828.4817103401,6651114.944269022,73.90576344668155],[510828.42924603634,6651115.448140036,73.54404630068154],[510831.4986487529,6651114.327951317,70.94712896420543],[510831.549744263,6651113.84473155,71.54095488320543],[510828.4504419742,6651115.244572698,74.17096117168154],[510828.3913094644,6651115.812485652,73.84148877068155],[510831.4881169693,6651114.427552359,71.37321809920542],[510831.53733061155,6651113.962129766,71.90266086820543],[510828.41727618984,6651115.563099318,74.41104961868155],[510831.5218877635,6651114.108175661,72.26041871420543],[510831.47291974624,6651114.571275331,71.79812460320542],[510828.35073573486,6651116.202158721,74.09770189368155],[510828.38253907434,6651115.89671712,74.62430195368155],[510831.5034138741,6651114.282886677,72.61087492920542],[510831.45296603214,6651114.759981328,72.21509130520543],[510828.30823886313,6651116.610301789,74.30997970268155],[510828.34657543927,6651116.242114503,74.80951085568155],[510831.48196126265,6651114.485768025,72.95061995620543],[510831.42830843956,6651114.99317278,72.61704022220542],[510828.26455523475,6651117.029842554,74.47709445968155],[510828.3097380833,6651116.595903168,74.96600214768155],[510831.45763822977,6651114.7157954825,73.27628706620543],[510828.27237732214,6651116.954718653,75.09362490668154],[510828.22040542006,6651117.453860608,74.59924758168154],[510831.39915387577,6651115.268892925,72.99692102420542],[510831.43060846505,6651114.971421009,73.58465587420542],[510828.2348313843,6651117.3153125895,75.19272040068157],[510828.176460994,6651117.875906092,74.67792227468156],[510831.37454817403,6651115.501593635,73.26332733920542],[510831.4010879203,6651115.250602305,73.87275422520543],[510828.1333189536,6651118.290245407,74.71566513368155],[510828.1850277013,6651117.793630808,75.28188505268155],[510831.34781769564,6651115.754388754,73.51103707920542],[510831.36933923105,6651115.550855581,74.13795195020542],[510828.13613338885,6651118.263215365,75.32466029368155],[510831.3092983679,6651116.118673219,73.80847954920543],[510837.37233162613,6651114.268599376,68.21846013508599],[510831.3356639766,6651115.869328741,74.37804039720542],[510831.26810137235,6651116.508280889,74.06469267220542],[510827.32223669457,6651126.079938812,68.31939778668155],[510827.32223669457,6651126.079938812,68.44939778668154],[510837.30630441307,6651114.874614272,68.21846013508599],[510831.30039325304,6651116.202890552,74.59129273220543],[510837.30630441307,6651114.874614272,68.34846013508599],[510827.9520843777,6651120.030835545,74.71566513368155],[510831.2249516927,6651116.916355457,74.27697048120544],[510827.25910479826,6651126.686262168,68.31939778668155],[510831.2638771692,6651116.548229965,74.77650163420545],[510831.1805970262,6651117.33582581,74.44408523820542],[510831.22647394286,6651116.901959253,74.93299292620543],[510837.37233162613,6651114.268599376,70.04726379408599],[510831.1885392712,6651117.260714518,75.06061568520542],[510831.1357690121,6651117.759772698,74.56623836020543],[510827.3222364523,6651126.079941139,70.14820144668154],[510837.3700613941,6651114.289436154,70.51285448108598],[510837.30630441307,6651114.874614272,70.04726379408599],[510827.7746174096,6651121.7352413,74.71566513368155],[510827.32270719216,6651126.075420119,70.35202273068155],[510831.1504165782,6651117.621247934,75.15971117920543],[510831.09114954167,6651118.181747352,74.64491305320543],[510827.7314753693,6651122.149580615,74.67792227468156],[510827.32661594136,6651126.037880206,70.76860201868156],[510837.36296207603,6651114.354595538,70.990125433086],[510837.3043012672,6651114.892999666,70.45807910608599],[510827.25910479826,6651126.686262168,70.14820144568156],[510827.7718032168,6651121.762269015,75.32466029368155],[510831.0473447827,6651118.596017126,74.68265591220542],[510827.68753094313,6651122.571626102,74.59924758168154],[510831.0998478449,6651118.099485875,75.24887583120542],[510827.3347636982,6651125.959628552,71.19292913868155],[510827.26127547974,6651126.665414784,70.61379213268154],[510837.2980371629,6651114.950493239,70.87920053408598],[510837.35066751274,6651114.46743823,71.47302645308599],[510827.64338112855,6651122.995644155,74.47709445968155],[510827.347414195,6651125.838132255,71.61923948968155],[510827.7229089042,6651122.231853574,75.28188505268155],[510831.05020245136,6651118.56899162,75.29165107220543],[510827.2680634902,6651126.600222234,71.09106308468155],[510827.59969750006,6651123.41518492,74.30997970268155],[510827.36472103617,6651125.671916084,72.04104834868156],[510837.28718901885,6651115.050060321,71.305289669086],[510827.6731052213,6651122.710171792,75.19272040068157],[510837.33788097213,6651114.584796419,71.834732438086],[510827.5572006284,6651123.8233279865,74.09770189368155],[510827.3867050812,6651125.460779707,72.45139789168155],[510827.5166268989,6651124.213001057,73.84148877068155],[510827.4132391822,6651125.20594426,72.84317758568154],[510827.2798189326,6651126.487322106,71.57396410468156],[510827.4878901519,6651124.48899088,73.62206976468156],[510827.4359627881,6651124.987705083,73.12065944568154],[510827.46091823484,6651124.748031147,73.38110011868154],[510827.6355592835,6651123.070765727,75.09362490668154],[510827.2920447788,6651126.369904182,71.93567008968155],[510827.5981985223,6651123.429581213,74.96600214768155],[510837.3219742419,6651114.730792518,72.192490284086],[510837.2715352918,6651115.193734289,71.73019617308599],[510827.30725399335,6651126.223833772,72.29342793568155],[510830.2238032305,6651126.384403165,68.28638856520544],[510827.5613611663,6651123.783369876,74.80951085568155],[510830.2238032305,6651126.384403165,68.41638856520542],[510827.3254483928,6651126.049093428,72.64388415068154],[510827.52539753134,6651124.12876726,74.62430195368155],[510827.3465764494,6651125.846178025,72.98362917768156],[510830.8633262046,6651120.3363151355,74.68265591220542],[510827.4906604157,6651124.462385063,74.41104961868155],[510837.30294542183,6651114.9054439645,72.54294649908599],[510827.37053150113,6651125.616111954,73.30929628768155],[510827.4574946314,6651124.780911683,74.17096117168154],[510827.3971523348,6651125.360443519,73.61766509568155],[510827.42622626555,6651125.081215358,73.90576344668155],[510837.2509821952,6651115.382375944,72.147162875086],[510830.15970154497,6651126.99062476,68.28638856520544],[510837.280848403,6651115.108256138,72.88269152608599],[510837.22558392194,6651115.615487886,72.54911179208598],[510837.2557947393,6651115.338205164,73.20835863608599],[510837.19555359473,6651115.8911140235,72.92899259408598],[510830.22380298446,6651126.384405491,70.11519222520542],[510830.6831331099,6651122.040434836,74.68265591220542],[510830.2242809555,6651126.37988523,70.31901350920542],[510837.2279530372,6651115.593743532,73.516727444086],[510837.17020877113,6651116.12373539,73.19539890908598],[510830.63932835095,6651122.454704611,74.64491305320543],[510830.2282497482,6651126.342351617,70.73559279720543],[510830.15970154497,6651126.99062476,70.11519222420543],[510837.1975457353,6651115.872829639,73.80482579508599],[510830.68027568725,6651122.067458014,75.29165107220543],[510830.59470888047,6651122.876679264,74.56623836020543],[510830.2365226654,6651126.2641130965,71.15991991720543],[510837.14267534553,6651116.376444316,73.44310864908599],[510830.161905571,6651126.969780874,70.58078291120542],[510830.54988086637,6651123.300626152,74.44408523820542],[510830.2493674905,6651126.14263719,71.58623026820543],[510830.6306302937,6651122.53696376,75.24887583120542],[510837.1648433586,6651116.1729805395,74.07002352008598],[510830.16879785416,6651126.904599266,71.05805386320544],[510830.50552619994,6651123.720096505,74.27697048120544],[510830.26694018755,6651125.976448917,72.00803912720542],[510837.1029989495,6651116.740604575,73.74055111908599],[510830.58006156044,6651123.015201701,75.15971117920543],[510830.46237652027,6651124.128171072,74.06469267220542],[510830.2892619365,6651125.765347974,72.41838867020543],[510830.4211795246,6651124.517778742,73.80847954920543],[510830.3162036363,6651125.510555296,72.81016836420542],[510830.1807338756,6651126.791718086,71.54095488320543],[510830.39200134337,6651124.793722245,73.58906054320542],[510830.33927630686,6651125.292352748,73.08765022420542],[510830.364615102,6651125.052719036,73.34809089720542],[510830.5419388675,6651123.375735118,75.06061568520542],[510837.1301565452,6651116.491345114,74.31011196708599],[510830.19314752705,6651126.67431987,71.90266086820543],[510830.5040041958,6651123.734490382,74.93299292620543],[510837.060564452,6651117.130079404,73.99676424208599],[510830.20859037514,6651126.528273975,72.26041871420543],[510830.46660096943,6651124.088219669,74.77650163420545],[510830.22706426453,6651126.353562958,72.61087492920542],[510837.0938263371,6651116.824793192,74.523364302086],[510830.4300848855,6651124.433559084,74.59129273220543],[510830.2485168761,6651126.150681609,72.95061995620543],[510830.3948141621,6651124.767120893,74.37804039720542],[510830.2728399089,6651125.9206541525,73.27628706620543],[510830.36113890755,6651125.085594055,74.13795195020542],[510830.2998696737,6651125.665028627,73.58465587420542],[510830.32939021837,6651125.385847329,73.87275422520543],[510837.0161186146,6651117.538014834,74.209042051086],[510837.0562133596,6651117.170014859,74.70857320408601],[510836.9704315941,6651117.957342164,74.376156808086],[510837.0176865911,6651117.523623538,74.86506449608599],[510836.97861241334,6651117.882256482,74.99268725508598],[510836.9242570073,6651118.381144502,74.498309930086],[510836.9393445665,6651118.24266697,75.091782749086],[510836.87829722866,6651118.802975278,74.57698462308599],[510836.83317663416,6651119.2171038035,74.61472748208598],[510836.8872568171,6651118.72074185,75.18094740108599],[510845.4455920274,6651115.166274973,68.11864080924303],[510836.83612014324,6651119.190087512,75.223722642086],[510845.376885311,6651115.771991932,68.11864080924303],[510845.376885311,6651115.771991932,68.24864080924304],[510835.9848970118,6651127.002834307,68.21846013508599],[510835.9848970118,6651127.002834307,68.34846013508599],[510836.6436303878,6651120.95680844,74.61472748208598],[510845.4455920274,6651115.166274973,69.94744446824303],[510835.9188697986,6651127.608849202,68.21846013508599],[510845.4432296652,6651115.187101508,70.41303515524302],[510845.376885311,6651115.771991932,69.94744446824303],[510845.4358422441,6651115.252228856,70.89030610724303],[510845.3748008738,6651115.790368287,70.35825978024303],[510835.9848967584,6651127.002836633,70.04726379508598],[510835.98538908706,6651126.998317912,70.25108507908598],[510836.45802453713,6651122.660347102,74.61472748208598],[510845.36828256096,6651115.847833594,70.77938120824302],[510845.4230487452,6651115.365016072,71.37320712724303],[510835.9894770969,6651126.960797097,70.66766436708599],[510836.4129039427,6651123.074475626,74.57698462308599],[510835.9188697986,6651127.608849202,70.04726379408599],[510845.35699417966,6651115.947351726,71.20547034324305],[510836.4550812815,6651122.687361067,75.223722642086],[510845.4097433037,6651115.482316563,71.73491311224304],[510835.99799852126,6651126.882585252,71.09199148708599],[510836.3669441639,6651123.496306403,74.498309930086],[510835.9211400306,6651127.588012425,70.51285448108598],[510836.0112291874,6651126.761150765,71.51830183808599],[510836.3207695772,6651123.920108741,74.376156808086],[510836.4039446076,6651123.156706729,75.18094740108599],[510845.34070519614,6651116.090955059,71.63037684724303],[510845.3931910496,6651115.628240884,72.09267095824303],[510835.92823934864,6651127.522853041,70.990125433086],[510836.02932974446,6651126.595019154,71.94011069708598],[510836.27508255665,6651124.339436072,74.209042051086],[510836.3518568583,6651123.634781609,75.091782749086],[510836.0523220085,6651126.38399019,72.350460240086],[510836.23063671927,6651124.747371501,73.99676424208599],[510836.0800730003,6651126.129284386,72.74223993408599],[510836.1882022218,6651125.136846331,73.74055111908599],[510835.9405339119,6651127.410010348,71.47302645308599],[510836.1038387426,6651125.911156236,73.01972179408598],[510836.1581475676,6651125.412695746,73.52113211308598],[510845.3733900059,6651115.802806468,72.44312717324304],[510836.1299386808,6651125.67160423,73.28016246708599],[510836.3125890114,6651123.9951920975,74.99268725508598],[510845.3193180178,6651116.27950397,72.04734354924302],[510835.9533204526,6651127.29265216,71.834732438086],[510836.27351483365,6651124.353825041,74.86506449608599],[510835.9692271829,6651127.1466560615,72.192490284086],[510836.23498806515,6651124.707433719,74.70857320408601],[510845.3503962502,6651116.005518931,72.78287220024303],[510835.98825600295,6651126.972004614,72.54294649908599],[510836.19737508777,6651125.052655388,74.523364302086],[510845.2928890369,6651116.512501308,72.44929246624302],[510836.01035302173,6651126.769192442,72.88269152608599],[510836.1610448796,6651125.386103465,74.31011196708599],[510836.0354066855,6651126.539243415,73.20835863608599],[510836.1263580662,6651125.70446804,74.07002352008598],[510836.06324838765,6651126.283705046,73.516727444086],[510836.09365568944,6651126.00461894,73.80482579508599],[510845.3243258637,6651116.235354909,73.10853931024303],[510845.2616400249,6651116.787991937,72.82917326824304],[510845.295354295,6651116.490767644,73.41690811824303],[510845.2352666627,6651117.02049894,73.09557958324302],[510845.26371301006,6651116.769716543,73.70500646924303],[510845.206615881,6651117.273083625,73.34328932324304],[510845.22968351207,6651117.069719879,73.97020419424302],[510845.16532934527,6651117.637064851,73.64073179324303],[510845.19358904526,6651117.3879279345,74.21029264124303],[510845.1211727796,6651118.026348202,73.89694491624303],[510845.15578449174,6651117.721212079,74.42354497624304],[510851.69674341613,6651115.8861935325,68.03711346873332],[510845.07492324995,6651118.434083077,74.10922272524303],[510845.1166451119,6651118.066264023,74.60875387824304],[510851.6259619517,6651116.491671551,68.03711346873332],[510851.6259619517,6651116.491671551,68.16711346873333],[510845.02738216775,6651118.85320425,74.27633748224304],[510845.0765548578,6651118.419698858,74.76524517024305],[510845.03589497943,6651118.778155483,74.89286792924304],[510844.9793337331,6651119.276798235,74.39849060424302],[510851.69674341613,6651115.8861935325,69.86591712773333],[510844.9950335726,6651119.138388783,74.99196342324304],[510844.9315088237,6651119.698421625,74.47716529724303],[510851.6943097174,6651115.907011851,70.33150781473331],[510844.8845571542,6651120.112346551,74.51490815624302],[510851.6259619517,6651116.491671551,69.86591712773333],[510844.9408320085,6651119.616228626,75.08112807524303],[510851.68669921707,6651115.972113509,70.80877876673333],[510851.62381457054,6651116.510040656,70.27673243973332],[510844.88762011623,6651120.085343542,75.12390331624303],[510851.61709942314,6651116.567483295,70.69785386773331],[510851.6735193908,6651116.084856232,71.29167978673333],[510844.00185281615,6651127.894249328,68.11864080924303],[510851.6054701646,6651116.666962169,71.12394300273331],[510844.00185281615,6651127.894249328,68.24864080924304],[510851.6598121627,6651116.202110451,71.65338577173333],[510854.48284232145,6651116.214050449,67.99958431955216],[510844.6873187797,6651121.851195889,74.51490815624302],[510843.9331460998,6651128.499966287,68.11864080924303],[510851.58868930006,6651116.810508855,71.54884950673332],[510851.6427600775,6651116.34797721,72.01114361773332],[510854.4111361548,6651116.819419654,67.99958431955216],[510854.4111361548,6651116.819419654,68.12958431955215],[510851.6223610983,6651116.522473931,72.36159983273332],[510851.5666562896,6651116.998983389,71.96581620873332],[510851.59867299645,6651116.725106429,72.70134485973333],[510844.0018525525,6651127.894251651,69.94744446924302],[510851.5394292285,6651117.231888814,72.36776512573331],[510844.00236486073,6651127.889735154,70.15126575324302],[510844.4941807091,6651123.553897034,74.51490815624302],[510854.48284232145,6651116.214050449,69.82838797855216],[510851.5718153582,6651116.954851742,73.02701196973332],[510844.0066187695,6651127.852232785,70.56784504124303],[510843.9331460998,6651128.499966287,69.94744446824303],[510844.4472290397,6651123.96782196,74.47716529724303],[510854.4803768284,6651116.2348650275,70.29397866555215],[510851.5072365849,6651117.50727077,72.74764592773332],[510854.4111361548,6651116.819419654,69.82838797855216],[510844.49111801083,6651123.580897719,75.12390331624303],[510844.01548600866,6651127.7740593925,70.99217216124303],[510844.3994041303,6651124.3894453505,74.39849060424302],[510851.54196893034,6651117.210163725,73.33538077773332],[510843.9355084619,6651128.479139752,70.41303515524302],[510844.029253599,6651127.652684605,71.41848251224303],[510851.48006682197,6651117.739686054,73.01405224273331],[510844.3513556956,6651124.813039334,74.27633748224304],[510854.47266690305,6651116.299954985,70.77124961755217],[510854.4089607199,6651116.837785458,70.23920329055215],[510844.43790611863,6651124.050012634,75.08112807524303],[510843.9428958831,6651128.414012403,70.89030610724303],[510844.0480887093,6651127.486634672,71.84029137124303],[510844.30381461343,6651125.232160509,74.10922272524303],[510851.5093721684,6651117.489002585,73.62347912873332],[510844.0720140408,6651127.275709456,72.25064091424305],[510844.3837045546,6651124.527852477,74.99196342324304],[510844.2575650838,6651125.639895384,73.89694491624303],[510851.4505508679,6651117.992171102,73.26176198273332],[510854.40215784457,6651116.895217773,70.66032471855216],[510844.1008912178,6651127.021128873,72.64242060824303],[510843.9556893819,6651128.301225187,71.37320712724303],[510844.21340851806,6651126.029178733,73.64073179324303],[510854.45931489306,6651116.412677447,71.25415063755216],[510844.1256214168,6651126.803107962,72.91990246824302],[510844.1821341918,6651126.3048925325,73.42131278724302],[510844.15278053755,6651126.563673728,73.18034314124303],[510844.3428431477,6651124.888085776,74.89286792924304],[510843.9689948234,6651128.183924696,71.73491311224304],[510851.4743150759,6651117.788887577,73.88867685373332],[510844.3021832694,6651125.246542403,74.76524517024305],[510854.3903766592,6651116.994678769,71.08641385355216],[510843.9855470775,6651128.038000376,72.09267095824303],[510854.4454285913,6651116.529910593,71.61585662255216],[510844.2620930152,6651125.599977236,74.60875387824304],[510851.4080175959,6651118.356008747,73.55920445273333],[510844.0053481213,6651127.863434792,72.44312717324304],[510844.2229536353,6651125.945029182,74.42354497624304],[510844.0283418769,6651127.660722328,72.78287220024303],[510844.1851490819,6651126.278313325,74.21029264124303],[510844.0544122635,6651127.430886352,73.10853931024303],[510851.43713065865,6651118.106970107,74.12876530073332],[510844.1490546151,6651126.596521381,73.97020419424302],[510844.08338383207,6651127.1754736155,73.41690811824303],[510844.11502511706,6651126.896524716,73.70500646924303],[510854.37337656633,6651117.138199658,71.51132035755215],[510854.4281537344,6651116.675751138,71.97361446855217],[510851.3625276271,6651118.745138534,73.81541757573332],[510851.39818451484,6651118.440122779,74.34201763573334],[510854.40748825925,6651116.850216498,72.32407068355215],[510854.3510557126,6651117.326640319,71.92828705955216],[510851.3148814928,6651119.152712569,74.02769538473332],[510851.35786323674,6651118.78503861,74.52722653773333],[510854.3834906916,6651117.05281258,72.66381571055216],[510854.3234729521,6651117.559503888,72.33023597655215],[510851.2659048049,6651119.57166841,74.19481014173331],[510851.31656237063,6651119.138334022,74.68371782973334],[510854.35628218023,6651117.282516602,72.98948282055215],[510854.2908597379,6651117.834836352,72.71011677855215],[510851.2746746793,6651119.4966492485,74.81134058873333],[510851.2164054438,6651119.995095297,74.31696326373333],[510854.3260458331,6651117.537782702,73.29785162855217],[510854.2633350242,6651118.067209868,72.97652309355215],[510851.23257937375,6651119.856740445,74.91043608273333],[510851.1671363577,6651120.416552367,74.39563795673332],[510854.29302322096,6651117.81657145,73.58594997955215],[510851.118766881,6651120.830314009,74.43338081573332],[510854.23343346815,6651118.319649538,73.22423283355215],[510851.1767410762,6651120.334391791,74.99960073473333],[510854.2575081362,6651118.116402546,73.85114770455215],[510851.12192233576,6651120.803321653,75.04237597573332],[510854.19034453365,6651118.683421794,73.52167530355216],[510854.2198379348,6651118.434427912,74.09123615155215],[510854.14426027547,6651119.072481649,73.77788842655215],[510850.20940737537,6651128.609147025,68.03711346873332],[510850.20940737537,6651128.609147025,68.16711346873333],[510854.18038299144,6651118.767520711,74.30448848655216],[510850.91557246685,6651122.568477416,74.43338081573332],[510854.0959916833,6651119.479982435,73.99016623555217],[510850.138625911,6651129.214625044,68.03711346873332],[510854.13953494874,6651119.112374554,74.48969738855217],[510854.0463751548,6651119.898862982,74.15728099255216],[510854.0976945203,6651119.465606473,74.64618868055216],[510853.99622912495,6651120.322213772,74.27943411455216],[510854.05525960046,6651119.823857303,74.77381143955215],[510850.2094071038,6651128.609149347,69.86591712873332],[510850.2099348822,6651128.6046346305,70.06973841273332],[510850.7166021744,6651124.27050689,74.43338081573332],[510854.01261435414,6651120.183883784,74.87290693355216],[510853.9463163784,6651120.743595098,74.35810880755216],[510850.21431724686,6651128.567147057,70.48631770073332],[510850.138625911,6651129.214625044,69.86591712773333],[510850.6682326976,6651124.684268533,74.39563795673332],[510862.22483474266,6651117.147761682,67.89143172384466],[510853.8973149939,6651121.157282381,74.39585166655215],[510850.7134469913,6651124.297496922,75.04237597573332],[510853.9560465748,6651120.661449288,74.96207158555215],[510850.22345225146,6651128.489004501,70.91064482073332],[510850.6189636116,6651125.105725602,74.31696326373333],[510850.1410596097,6651129.193806725,70.33150781473331],[510850.2376355841,6651128.367677594,71.33695517173334],[510862.15055902017,6651117.752820987,67.89143172384466],[510850.56946425047,6651125.52915249,74.19481014173331],[510850.6586282508,6651124.766426786,74.99960073473333],[510862.15055902017,6651117.752820987,68.02143172384466],[510853.90051167214,6651121.130294875,75.00484682655217],[510850.14867011004,6651129.128705067,70.80877876673333],[510850.25703946134,6651128.201693161,71.75876403073332],[510850.52048756246,6651125.948108331,74.02769538473332],[510850.2816872699,6651127.990851151,72.16911357373333],[510850.60278995323,6651125.244078131,74.91043608273333],[510850.4728414283,6651126.355682366,73.81541757573332],[510850.3114364559,6651127.736370994,72.56089326773333],[510850.16184993624,6651129.015962344,71.29167978673333],[510850.42735145945,6651126.744812154,73.55920445273333],[510850.33691343665,6651127.518436086,72.83837512773331],[510850.3951327372,6651127.02041719,73.33978544673332],[510850.36489268584,6651127.2790963035,73.09881580073332],[510850.56069464784,6651125.604169328,74.81134058873333],[510850.1755571644,6651128.898708125,71.65338577173333],[510852.9760754476,6651128.934717401,67.99958431955216],[510850.51880695653,6651125.962484553,74.68371782973334],[510852.9760754476,6651128.934717401,68.12958431955215],[510850.1926092496,6651128.752841366,72.01114361773332],[510850.4775060903,6651126.315779965,74.52722653773333],[510850.2130082287,6651128.578344644,72.36159983273332],[510862.22483474266,6651117.147761682,69.72023538284466],[510850.4371848122,6651126.660695797,74.34201763573334],[510853.6914660104,6651122.895133409,74.39585166655215],[510850.2366963306,6651128.375712145,72.70134485973333],[510850.3982386684,6651126.993848467,74.12876530073332],[510850.2635539689,6651128.145966833,73.02701196973332],[510852.904369281,6651129.540086604,67.99958431955216],[510850.36105425115,6651127.311930998,73.88867685373332],[510850.29340039677,6651127.890654851,73.33538077773332],[510850.32599715865,6651127.611815992,73.62347912873332],[510862.22228089994,6651117.168565603,70.18582606984465],[510862.15055902017,6651117.752820987,69.72023538284466],[510862.14830562955,6651117.77117739,70.13105069484466],[510862.21429469314,6651117.233622242,70.66309702184468],[510852.97607517237,6651128.934719723,69.82838797955215],[510862.1412589765,6651117.828580305,70.55217212284467],[510862.20046422037,6651117.346286998,71.14599804184466],[510852.9766098459,6651128.930205817,70.03220926355215],[510853.48989633325,6651124.596856996,74.39585166655215],[510862.12905561813,6651117.927990385,70.97826125784465],[510852.98104946245,6651128.89272498,70.44878855155216],[510852.904369281,6651129.540086604,69.82838797855216],[510862.1860803095,6651117.463460131,71.50770402684466],[510853.4408949487,6651125.010544279,74.35810880755216],[510853.4866999302,6651124.62384218,75.00484682655217],[510852.99030380853,6651128.814596468,70.87311567155216],[510853.3909822022,6651125.431925606,74.27943411455216],[510852.90683477395,6651129.519272028,70.29397866555215],[510862.11144633504,6651118.071437803,71.40316776184466],[510862.16818641656,6651117.609226017,71.86546187284466],[510853.0046724348,6651128.693291365,71.29942602255215],[510853.3408361722,6651125.855276396,74.15728099255216],[510853.43116502755,6651125.092687767,74.96207158555215],[510852.9145446993,6651129.454182069,70.77124961755217],[510853.0243298079,6651128.527336765,71.72123488155215],[510853.2912196437,6651126.274156943,73.99016623555217],[510862.14678040403,6651117.783602066,72.21591808784466],[510853.04929962,6651128.316532645,72.13158442455216],[510853.3745972482,6651125.570253271,74.87290693355216],[510862.0883256243,6651118.259781999,71.82013446384467],[510853.24295105156,6651126.681657729,73.77788842655215],[510852.9278967093,6651129.341459608,71.25415063755216],[510853.0794374548,6651128.062098224,72.52336411855215],[510853.19686679344,6651127.070717583,73.52167530355216],[510853.10524727154,6651127.844202482,72.80084597855215],[510853.1642271598,6651127.346273089,73.30225629755215],[510853.13359204686,6651127.604905712,73.06128665155215],[510853.3319520019,6651125.930279752,74.77381143955215],[510852.9417830112,6651129.224226462,71.61585662255216],[510862.1219228952,6651117.986094437,72.55566311484466],[510853.28951708204,6651126.288530582,74.64618868055216],[510852.95905786793,6651129.0783859175,71.97361446855217],[510862.0597544488,6651118.492526362,72.22208338084465],[510853.2476766537,6651126.641762501,74.48969738855217],[510852.9797233431,6651128.9039205555,72.32407068355215],[510853.2068286109,6651126.986616343,74.30448848655216],[510853.00372091075,6651128.701324473,72.66381571055216],[510853.16737366753,6651127.319709142,74.09123615155215],[510853.0309294221,6651128.471620451,72.98948282055215],[510862.09373937984,6651118.21568087,72.88133022484466],[510853.12970346614,6651127.637734507,73.85114770455215],[510853.06116576924,6651128.216354353,73.29785162855217],[510853.09418838134,6651127.937565605,73.58594997955215],[510862.02597255574,6651118.767717878,72.60196418284465],[510862.06241952785,6651118.470816296,73.18969903284466],[510861.99746150716,6651118.999972439,72.86837049784465],[510862.02821356634,6651118.749462327,73.47779738384466],[510861.9664884434,6651119.252282882,73.11608023784466],[510861.9914258156,6651119.0491399355,73.74299510884465],[510861.9218554377,6651119.615868919,73.41352270784466],[510861.95240572066,6651119.3670025,73.98308355584466],[510861.8741197723,6651120.004729606,73.66973583084466],[510861.9115369284,6651119.699924783,74.19633589084467],[510861.82412149844,6651120.412021788,73.88201363984467],[510861.8692251157,6651120.0446020905,74.38154479284468],[510861.77272698557,6651120.830687904,74.04912839684465],[510861.82588535576,6651120.397653185,74.53803608484466],[510861.7207839968,6651121.253821974,74.17128151884467],[510861.781929801,6651120.75572062,74.66565884384465],[510861.7377563828,6651121.115562798,74.76475433784466],[510861.6690826511,6651121.67498759,74.24995621184466],[510861.6183253255,6651122.0884631,74.28769907084465],[510861.67916152434,6651121.592883831,74.85391898984466],[510861.62163655524,6651122.061489409,74.89669423084466],[510860.66407360387,6651129.861916736,67.89143172384466],[510860.66407360387,6651129.861916736,68.02143172384466],[510861.4050998429,6651123.825424497,74.28769907084465],[510860.58979788143,6651130.466976043,67.89143172384466],[510871.57436085044,6651118.319840205,67.75322922458413],[510871.7967866418,6651118.348317526,67.74984006371746],[510871.49698203395,6651118.9245105,67.75322922458413],[510871.49698203395,6651118.9245105,67.88322922458413],[510860.6640733189,6651129.861919057,69.72023538384465],[510871.7193340025,6651118.95297837,67.74984006371746],[510871.7193340025,6651118.95297837,67.87984006371745],[510860.6646271521,6651129.857407464,69.92405666784465],[510861.19630701345,6651125.526276947,74.28769907084465],[510860.6692258602,6651129.819945812,70.34063595584466],[510860.58979788143,6651130.466976043,69.72023538284466],[510861.1455496879,6651125.939752456,74.24995621184466],[510860.6788118313,6651129.741857296,70.76496307584466],[510861.1929960688,6651125.553248314,74.89669423084466],[510871.57436085044,6651118.319840205,69.58203288358415],[510861.09384834213,6651126.360918071,74.17128151884467],[510860.59235172416,6651130.44617212,70.18582606984465],[510860.6936953504,6651129.62061429,71.19127342684466],[510871.7967866418,6651118.348317526,69.57864372271747],[510861.04190535337,6651126.784052142,74.04912839684465],[510861.13547109975,6651126.021853894,74.85391898984466],[510871.5717003131,6651118.340630752,70.04762357058412],[510860.600337931,6651130.381115482,70.66309702184468],[510860.714057136,6651129.4547446435,71.61308228584465],[510871.49698203395,6651118.9245105,69.58203288358415],[510860.99051084055,6651127.202718259,73.88201363984467],[510860.7399217293,6651129.244048439,72.02343182884466],[510860.9405125666,6651127.610010439,73.66973583084466],[510861.07687624125,6651126.499174925,74.76475433784466],[510871.7941235662,6651118.369107748,70.04423440971745],[510860.61416840367,6651130.268450725,71.14599804184466],[510860.7711395389,6651128.989744266,72.41521152284466],[510860.89277690125,6651127.998871128,73.41352270784466],[510871.7193340025,6651118.95297837,69.57864372271747],[510860.79787423793,6651128.7719600685,72.69269338284465],[510860.8589676421,6651128.2742855735,73.19410370184465],[510860.82723473455,6651128.532785799,72.95313405584466],[510871.494634501,6651118.9428551,69.99284819558413],[510871.5633804583,6651118.405645562,70.52489452258413],[510861.032702823,6651126.859017103,74.66565884384465],[510860.6285523146,6651130.151277592,71.50770402684466],[510860.98874726833,6651127.217084538,74.53803608484466],[510860.64644620754,6651130.005511706,71.86546187284466],[510871.71698423,6651118.971322684,69.98945903471746],[510871.7857957739,6651118.434121542,70.52150536171746],[510860.9454075084,6651127.5701356325,74.38154479284468],[510871.48729345266,6651119.00022111,70.41396962358412],[510860.66785222,6651129.831135657,72.21591808784466],[510860.9030956957,6651127.91481294,74.19633589084467],[510871.5489721755,6651118.518237885,71.00779554258415],[510860.69270972896,6651129.628643286,72.55566311484466],[510860.8622269034,6651128.247735223,73.98308355584466],[510860.7208932442,6651129.399056852,72.88133022484466],[510860.8232068085,6651128.565597787,73.74299510884465],[510860.75221309625,6651129.143921429,73.18969903284466],[510871.70963617787,6651119.028687796,70.41058046271745],[510860.78641905775,6651128.865275396,73.47779738384466],[510871.771373745,6651118.546712104,71.00440638171747],[510871.4745802619,6651119.099567277,70.84005875858412],[510871.533987333,6651118.635335683,71.36950152758413],[510871.69691085815,6651119.12803241,70.83666959771745],[510871.75637460634,6651118.663808072,71.36611236671746],[510871.4562352976,6651119.242922467,71.26496526258414],[510871.5153458683,6651118.7810078515,71.72725937358413],[510871.678548392,6651119.2713853605,71.26157610171747],[510871.73771535687,6651118.8094779635,71.72387021271746],[510871.49304555455,6651118.95527179,72.07771558858413],[510871.4321486488,6651119.431145571,71.68193196458412],[510871.7153937676,6651118.983739178,72.07432642771745],[510871.65443876345,6651119.4596055215,71.67854280371745],[510871.4671495477,6651119.157633971,72.41746061558415],[510871.4023838256,6651119.663740294,72.08388088158412],[510871.68947305484,6651119.186098197,72.41407145471747],[510871.6246455434,6651119.692196609,72.08049172071745],[510871.43778858037,6651119.387072797,72.74312772558413],[510871.36719059135,6651119.938754884,72.46376168358412],[510871.6600840759,6651119.415533436,72.73973856471746],[510871.4051602464,6651119.642044187,73.05149653358413],[510871.58941873326,6651119.967206899,72.46037252271745],[510871.33748840715,6651120.170860121,72.73016799858414],[510871.62742461305,6651119.67050084,73.04810737271745],[510871.55968821177,6651120.199308507,72.72677883771746],[510871.369525227,6651119.920511069,73.33959488458414],[510871.30522134947,6651120.423008345,72.97787773858413],[510871.5917555961,6651119.948963369,73.33620572371747],[510871.5273903699,6651120.451452792,72.97448857771745],[510871.33120055613,6651120.219996005,73.60479260958412],[510871.25872366433,6651120.786360621,73.27532020858413],[510871.5533943619,6651120.248443625,73.60140344871745],[510871.48084832396,6651120.814799389,73.27193104771746],[510871.2905502782,6651120.537654206,73.84488105658413],[510871.20899369643,6651121.174971298,73.53153333158413],[510871.5127053018,6651120.56609686,73.84149189571745],[510871.2479740679,6651120.870362443,74.05813339158414],[510871.4310709115,6651121.203403992,73.52814417071745],[510871.470088472,6651120.898799897,74.05474423071746],[510871.1569065928,6651121.582001618,73.74381114058413],[510871.20389455074,6651121.214818148,74.24334229358413],[510871.3789341145,6651121.610427949,73.74042197971745],[510871.42596690095,6651121.243250218,74.23995313271746],[510871.103364918,6651122.000398563,73.91092589758412],[510871.15874414064,6651121.567642254,74.39983358558413],[510871.3253413585,6651122.028818353,73.90753673671745],[510871.3807734153,6651121.596068809,74.39644442471746],[510871.049251853,6651122.423260587,74.03307901958414],[510871.112952209,6651121.925479477,74.52745634458412],[510871.27117666724,6651122.451673767,74.02968985871746],[510871.33493779623,6651121.953900439,74.52406718371745],[510878.9851400758,6651119.283514667,67.63777053046715],[510871.06693331205,6651122.285090303,74.62655183858415],[510870.9953905264,6651122.8441554215,74.11175371258415],[510871.28887499525,6651122.313505642,74.62316267771747],[510871.21726395475,6651122.872562024,74.10836455171747],[510870.94251265936,6651123.257365095,74.14949657158414],[510878.90530163253,6651119.887865121,67.63777053046715],[510871.0058904752,6651122.762104449,74.71571649058413],[510878.90530163253,6651119.887865121,67.76777053046715],[510871.1643356398,6651123.285765238,74.14610741071746],[510871.22777392087,6651122.790512334,74.71232732971745],[510870.9459622257,6651123.230408748,74.75849173158413],[510871.1677884973,6651123.258809312,74.75510257071745],[510869.9483941724,6651131.02582094,67.75322922458413],[510878.9851400758,6651119.283514667,69.46657418946717],[510869.9483941724,6651131.02582094,67.88322922458413],[510870.1692687201,6651131.054099654,67.74984006371746],[510870.1692687201,6651131.054099654,67.87984006371745],[510870.72037903435,6651124.993209746,74.14949657158414],[510869.871015356,6651131.630491235,67.75322922458413],[510878.98239496845,6651119.3042942155,69.93216487646714],[510878.90530163253,6651119.887865121,69.46657418946717],[510870.94199008954,6651125.021582756,74.14610741071746],[510870.0918160808,6651131.658760498,67.74984006371746],[510878.90287947905,6651119.906200016,69.87738950146715],[510878.9738106518,6651119.369274637,70.40943582846715],[510878.89530508197,6651119.963535681,70.29851092946714],[510878.95894437557,6651119.481807402,70.89233684846717],[510869.9483938755,6651131.02582326,69.58203288458412],[510869.9489708468,6651131.021314566,69.78585416858414],[510878.88218777935,6651120.0628293,70.72460006446715],[510870.16926842293,6651131.054101975,69.57864372371745],[510870.5028632499,6651126.6929686675,74.14949657158414],[510878.9434832126,6651119.598843262,71.25404283346715],[510870.1698459446,6651131.049593351,69.78246500771746],[510869.95376168005,6651130.983877,70.20243345658415],[510869.871015356,6651131.630491235,69.58203288358415],[510870.72426678555,6651126.721315107,74.14610741071746],[510870.44998538285,6651127.1061783405,74.11175371258415],[510878.86325968686,6651120.206108662,71.14950656846716],[510878.9242491949,6651119.744438377,71.61180067946715],[510870.1746413485,6651131.01215637,70.19904429571747],[510870.0918160808,6651131.658760498,69.57864372271747],[510869.96374813415,6651130.905838689,70.62676057658413],[510870.4994139806,6651126.719922694,74.75849173158413],[510870.6713384706,6651127.1345183235,74.10836455171747],[510870.39612405637,6651127.527073177,74.03307901958414],[510869.87367589324,6651131.609700689,70.04762357058412],[510869.97925345745,6651130.784673636,71.05307092758413],[510870.1846373302,6651130.9341192795,70.62337141571746],[510870.72081422544,6651126.748268713,74.75510257071745],[510870.3420109914,6651127.9499352,73.91092589758412],[510870.6174257581,6651127.555406579,74.02968985871746],[510870.0944791564,6651131.637970276,70.04423440971745],[510870.4394857311,6651127.188226991,74.71571649058413],[510878.90124002506,6651119.918610138,71.96225689446715],[510869.88199574815,6651131.544685878,70.52489452258413],[510878.83840740006,6651120.394232205,71.56647327046714],[510870.00046591845,6651130.618910633,71.47487978658414],[510870.2001574462,6651130.812956119,71.04968176671746],[510870.2884693166,6651128.368332145,73.74381114058413],[510870.56326106685,6651127.978261993,73.90753673671745],[510870.0274110838,6651130.408349889,71.88522932958413],[510870.66082880175,6651127.216565691,74.71232732971745],[510870.23638221284,6651128.775362463,73.53153333158413],[510870.3784428944,6651127.66524114,74.62655183858415],[510870.10280694877,6651131.572956482,70.52150536171746],[510870.22139014484,6651130.647195706,71.47149062571746],[510869.8964040309,6651131.432093557,71.00779554258415],[510870.0599331122,6651130.154209216,72.27700902358413],[510870.18665224506,6651129.163973141,73.27532020858413],[510870.5096683109,6651128.396652397,73.74042197971745],[510870.0877847347,6651129.93656504,72.55449088358412],[510870.15143050137,6651129.439210514,73.05590120258414],[510870.1183718552,6651129.697544542,72.81493155658413],[510878.87452086643,6651120.120865279,72.30200192146717],[510870.33242399734,6651128.024851964,74.52745634458412],[510870.2483610171,6651130.436638256,71.88184016871746],[510870.4575315138,6651128.803676354,73.52814417071745],[510869.9113888733,6651131.314995757,71.36950152758413],[510870.5997277274,6651127.6935723815,74.62316267771747],[510878.80769644777,6651120.626703896,71.96842218746714],[510870.11722897773,6651131.46036592,71.00440638171747],[510870.28091407294,6651130.182501554,72.27361986271745],[510870.4077541014,6651129.192280958,73.27193104771746],[510870.30879226705,6651129.964860781,72.55110172271745],[510870.2866320657,6651128.382689186,74.39983358558413],[510870.37249875464,6651129.467514029,73.05251204171746],[510870.3394085691,6651129.725844018,72.81154239571745],[510869.930030338,6651131.16932359,71.72725937358413],[510870.5536649264,6651128.053177586,74.52406718371745],[510870.1322281163,6651131.343269952,71.36611236671746],[510870.24148165574,6651128.735513294,74.24334229358413],[510869.9523306518,6651130.995059651,72.07771558858413],[510878.84422660724,6651120.350182742,72.62766903146715],[510870.5078293073,6651128.411009216,74.39644442471746],[510870.19740213844,6651129.079968997,74.05813339158414],[510870.15088736586,6651131.19760006,71.72387021271746],[510869.97822665866,6651130.79269747,72.41746061558415],[510870.15482592816,6651129.412677235,73.84488105658413],[510870.007587626,6651130.563258644,72.74312772558413],[510870.46263582166,6651128.763827808,74.23995313271746],[510878.7713845324,6651120.901573014,72.34830298946714],[510870.11417565023,6651129.730335435,73.60479260958412],[510870.04021595995,6651130.308287255,73.05149653358413],[510870.0758509794,6651130.029820372,73.33959488458414],[510870.17320895504,6651131.023338846,72.07432642771745],[510870.41851425066,6651129.108278127,74.05474423071746],[510870.1991296678,6651130.820979828,72.41407145471747],[510870.3758974208,6651129.440981164,73.84149189571745],[510870.22851864673,6651130.591544589,72.73973856471746],[510878.8105611221,6651120.605019265,72.93603783946715],[510870.3352083607,6651129.758634399,73.60140344871745],[510870.2611781097,6651130.3365771845,73.04810737271745],[510870.2968471265,6651130.058114655,73.33620572371747],[510878.74073821004,6651121.133555479,72.61470930446715],[510878.77379337855,6651120.88333885,73.22413619046716],[510878.70744548517,6651121.38557033,72.86241904446715],[510878.7342504882,6651121.182665374,73.48933391546714],[510878.6594697863,6651121.74873041,73.15986151446715],[510878.69230806705,6651121.500155548,73.72942236246715],[510878.6081590607,6651122.137135531,73.41607463746715],[510878.64837849437,6651121.832687799,73.94267469746715],[510878.55441627343,6651122.543950549,73.62835244646715],[510878.6028978294,6651122.176961301,74.12788359946715],[510878.49917267886,6651122.9621261805,73.79546720346715],[510878.5563122312,6651122.529598781,74.28437489146715],[510878.44333953154,6651123.384764532,73.91762032546714],[510878.50906471943,6651122.887246726,74.41199765046714],[510878.46158302797,6651123.246667332,74.51109314446717],[510878.38776612456,6651123.805436733,73.99629501846717],[510878.333207438,6651124.218427839,74.03403787746716],[510878.3985998333,6651123.723429161,74.60025779646715],[510878.3367666552,6651124.191485749,74.64303303746715],[510877.30748908257,6651131.982774536,67.63777053046715],[510877.30748908257,6651131.982774536,67.76777053046715],[510878.10401289066,6651125.953354308,74.03403787746716],[510877.22765063925,6651132.587124988,67.63777053046715],[510888.6453847495,6651120.58578353,67.4793948502016],[510877.3074887762,6651131.982776854,69.46657419046714],[510877.30808408756,6651131.9782705465,69.67039547446716],[510877.87958297064,6651127.652214138,74.03403787746716],[510888.56234008534,6651121.189701763,67.4793948502016],[510888.56234008534,6651121.189701763,67.60939485020158],[510877.31302720617,6651131.940852782,70.08697476246716],[510877.22765063925,6651132.587124988,69.46657418946717],[510877.8250242841,6651128.065205242,73.99629501846717],[510877.3233310979,6651131.86285575,70.51130188246715],[510877.8760240599,6651127.679153906,74.64303303746715],[510877.23039574665,6651132.566345439,69.93216487646714],[510877.7694508771,6651128.485877444,73.91762032546714],[510877.33932928625,6651131.741754786,70.93761223346715],[510877.7136177298,6651128.908515794,73.79546720346715],[510877.81419088185,6651128.147210494,74.60025779646715],[510877.2389800633,6651132.501365018,70.40943582846715],[510877.36121602403,6651131.5760794645,71.35942109246716],[510877.65837413515,6651129.326691425,73.62835244646715],[510888.6453847495,6651120.58578353,69.3081985092016],[510877.3890176905,6651131.365630099,71.76977063546715],[510877.6046313479,6651129.733506445,73.41607463746715],[510877.75120768714,6651128.623972323,74.51109314446717],[510877.25384633965,6651132.3888322525,70.89233684846717],[510877.42257349094,6651131.1116238525,72.16155032946715],[510877.55332062236,6651130.121911566,73.15986151446715],[510877.45131042786,6651130.894094801,72.43903218946714],[510877.5169792914,6651130.397003351,72.94044250846716],[510877.48286981584,6651130.655200734,72.69947286246715],[510877.70372599567,6651128.983392931,74.41199765046714],[510877.2693075025,6651132.271796394,71.25404283346715],[510888.6425294018,6651120.606548218,69.77378919620158],[510888.56234008534,6651121.189701763,69.3081985092016],[510877.656478484,6651129.341040874,74.28437489146715],[510877.28854152025,6651132.126201279,71.61180067946715],[510877.6098928858,6651129.693678354,74.12788359946715],[510877.3115506901,6651131.952029519,71.96225689446715],[510877.5644122208,6651130.037951857,73.94267469746715],[510877.33826984867,6651131.749774376,72.30200192146717],[510888.5598206608,6651121.208023545,69.71901382120159],[510888.6336003488,6651120.671482166,70.25106014820159],[510877.520482648,6651130.370484107,73.72942236246715],[510877.3685641079,6651131.520456913,72.62766903146715],[510877.4785402269,6651130.687974281,73.48933391546714],[510877.402229593,6651131.265620392,72.93603783946715],[510877.4389973365,6651130.987300805,73.22413619046716],[510888.5519420846,6651121.265318206,70.14013524920158],[510888.61813705973,6651120.78393445,70.7339611682016],[510888.538298006,6651121.36454081,70.56622438420158],[510888.60205499415,6651120.900886607,71.09566715320159],[510888.5186097829,6651121.507717702,70.9911308882016],[510888.58204856014,6651121.0463775955,71.45342499920159],[510891.86846296454,6651121.0318975635,67.42456835018152],[510888.5581153682,6651121.220424791,71.80388121420158],[510888.49275945657,6651121.695706701,71.40809759020158],[510891.7843485653,6651121.635667731,67.42456835018152],[510891.7843485653,6651121.635667731,67.5545683501815],[510888.53032319853,6651121.422535284,72.1436262412016],[510888.4608151873,6651121.928012133,71.81004650720158],[510888.4988123564,6651121.651688743,72.46929335120159],[510888.4230450267,6651122.20268467,72.18992730920158],[510891.86846296454,6651121.0318975635,69.2533720091815],[510888.4637949038,6651121.906343009,72.77766215920158],[510888.3911679829,6651122.434501225,72.45633362420159],[510891.8655708358,6651121.052657161,69.71896269618149],[510891.7843485653,6651121.635667731,69.2533720091815],[510888.4255506094,6651122.184463547,73.0657605102016],[510888.3565382601,6651122.686335838,72.70404336420158],[510891.78179668705,6651121.6539850235,69.6641873211815],[510891.85652676376,6651121.117575189,70.19623364818152],[510888.3844197216,6651122.483575998,73.33095823520158],[510888.3066359117,6651123.049236191,73.00148583420159],[510891.77381662343,6651121.711265636,70.08530874918151],[510891.8408642853,6651121.229999903,70.6791346681815],[510888.3407929405,6651122.8008391075,73.57104668220158],[510891.7599967895,6651121.810463914,70.51139788418149],[510888.2532646058,6651123.437363532,73.25769895720158],[510891.82457505947,6651121.346923387,71.0408406531815],[510888.2950992062,6651123.133133537,73.78429901720159],[510891.7400549536,6651121.953605702,70.9363043881815],[510891.8043109138,6651121.492378703,71.3985984991815],[510888.1973635694,6651123.843887605,73.46997676620158],[510888.2477920894,6651123.477160821,73.96950791920159],[510891.7800694279,6651121.666383228,71.7490547141815],[510891.7138716378,6651122.141548612,71.35327109018151],[510888.13990145497,6651124.261764164,73.63709152320158],[510888.1993356666,6651123.829546101,74.12599921120159],[510891.751919255,6651121.868444168,72.0887997411815],[510888.0818261118,6651124.684100252,73.75924464520159],[510888.1501907486,6651124.186938261,74.25362197020158],[510895.7250897525,6651121.573353198,67.35765722912942],[510891.6815158804,6651122.373797089,71.75522000718149],[510888.1008022464,6651124.546101817,74.3527174642016],[510891.72000250773,6651122.097541446,72.4144668511815],[510888.02402094007,6651125.104471595,73.8379193382016],[510895.6396953445,6651122.176943657,67.35765722912942],[510891.6432591857,6651122.648402283,72.1351008091815],[510895.6396953445,6651122.176943657,67.48765722912941],[510887.96727123886,6651125.517167335,73.87566219720159],[510888.03528971836,6651125.022522674,74.44188211620158],[510891.6845339799,6651122.352133278,72.7228356591815],[510891.61097151967,6651122.8801620025,72.40150712418149],[510887.97097339004,6651125.490244515,74.48465735720158],[510891.6457970439,6651122.630185626,73.01093401018151],[510891.57589571615,6651123.131934875,72.6492168641815],[510895.7250897525,6651121.573353198,69.18646088812942],[510886.9003612012,6651133.275961105,67.4793948502016],[510891.604136331,6651122.9292247435,73.2761317351815],[510886.9003612012,6651133.275961105,67.60939485020158],[510891.5253505536,6651123.494746254,72.9466593341815],[510895.72215361294,6651121.594106616,69.6520515751294],[510895.6396953445,6651122.176943657,69.18646088812942],[510886.817316537,6651133.879879337,67.4793948502016],[510887.7288724993,6651127.250853017,73.87566219720159],[510891.55994757416,6651123.24641007,73.5162201821815],[510895.6371046331,6651122.195255497,69.59727620012941],[510895.7129719129,6651121.659005322,70.12932252712942],[510891.47129174846,6651123.882778435,73.2028724571815],[510891.5136652387,6651123.5786230285,73.7294725171815],[510895.62900313304,6651122.252519061,70.0183976281294],[510895.697071091,6651121.771396574,70.61222354712942],[510891.4146706261,6651124.289202839,73.41515026618151],[510891.46574873803,6651123.922565967,73.91468141918152],[510886.9003608826,6651133.275963422,69.30819851020158],[510895.61497299606,6651122.351687812,70.44448676312942],[510895.6805339843,6651121.888285257,70.97392953212943],[510886.900980101,6651133.271460336,69.51201979420159],[510891.35646831675,6651124.706976946,73.58226502318149],[510891.4166681267,6651124.274864851,74.0711727111815],[510887.49542972894,6651128.9484978495,73.87566219720159],[510886.9061217296,6651133.234069334,69.9285990822016],[510886.817316537,6651133.879879337,69.3081985092016],[510895.59472769586,6651122.494786996,70.86939326712941],[510895.6599614695,6651122.03369728,71.33168737812943],[510887.4386800276,6651129.36119359,73.8379193382016],[510891.29764487955,6651125.129209487,73.7044181451815],[510891.36689015134,6651124.632169387,74.1987954701815],[510886.9168394139,6651133.156128082,70.35292620220159],[510887.49172789644,6651128.9754183525,74.48465735720158],[510886.82017188467,6651133.859114649,69.77378919620158],[510887.38087485585,6651129.781564935,73.75924464520159],[510895.6353510894,6651122.207650012,71.68214359312941],[510895.5681459361,6651122.682673966,71.2863599691294],[510886.9334800713,6651133.0351137305,70.77923655320159],[510891.31686545414,6651124.991244887,74.2978909641815],[510891.2390950939,6651125.549477767,73.7830928381815],[510887.3227995129,6651130.203901021,73.63709152320158],[510887.4274115682,6651129.443140194,74.44188211620158],[510886.8291009377,6651133.794180701,70.25106014820159],[510886.9562457555,6651132.869556895,71.2010454122016],[510887.26533739833,6651130.62177758,73.46997676620158],[510895.60677254194,6651122.409650811,72.02188862012942],[510886.98516390525,6651132.65925804,71.61139495520159],[510891.18161437474,6651125.962072326,73.8208356971815],[510887.2094363619,6651131.0283016525,73.25769895720158],[510887.3618990402,6651129.91956105,74.3527174642016],[510886.84456422675,6651133.681728418,70.7339611682016],[510895.53529780573,6651122.914853315,71.6883088861294],[510891.2505090302,6651125.467548939,74.3870556161815],[510887.0200672685,6651132.4054334555,72.00317464920158],[510887.15606505604,6651131.416428993,73.00148583420159],[510887.04995824816,6651132.188059975,72.28065650920158],[510887.1182642985,6651131.6913240375,72.7820668282016],[510887.08278502524,6651131.949336761,72.54109718220158],[510887.3125105379,6651130.278724607,74.25362197020158],[510886.86064629245,6651133.5647762595,71.09566715320159],[510895.57437010243,6651122.638679897,72.34755573012941],[510887.26336562,6651130.636116766,74.12599921120159],[510886.8806527264,6651133.419285271,71.45342499920159],[510891.185364215,6651125.935156106,74.4298308571815],[510887.2149091972,6651130.988502046,73.96950791920159],[510886.90458591835,6651133.245238076,71.80388121420158],[510895.49645894073,6651123.189376776,72.06818968812941],[510887.1676020804,6651131.332529331,73.78429901720159],[510886.93237808795,6651133.043127583,72.1436262412016],[510887.121908346,6651131.664823759,73.57104668220158],[510886.96388893016,6651132.813974124,72.46929335120159],[510887.0782815649,6651131.98208687,73.33095823520158],[510886.99890638277,6651132.559319858,72.77766215920158],[510895.53836183314,6651122.893195953,72.65592453812943],[510887.03715067706,6651132.28119932,73.0657605102016],[510890.10096099856,6651133.718963847,67.42456835018152],[510890.10096099856,6651133.718963847,67.5545683501815],[510895.46367993794,6651123.421067513,72.3345960031294],[510895.49903541885,6651123.171165542,72.94402288912941],[510890.0168465994,6651134.322734014,67.42456835018152],[510890.9401447159,6651127.695332954,73.8208356971815],[510895.4280703693,6651123.672765445,72.58230574312941],[510895.4567407351,6651123.47011565,73.2092206141294],[510895.37675603695,6651124.035468836,72.87974821312942],[510895.41187953687,6651123.787206569,73.44930906112941],[510890.1009606759,6651133.718966164,69.2533720101815],[510895.32187459327,6651124.423385523,73.13596133612941],[510890.1015878706,6651133.714464181,69.4571932941815],[510895.36489290104,6651124.119320646,73.66256139612942],[510890.7036948663,6651129.392561571,73.8208356971815],[510890.1067957308,6651133.677082348,69.8737725821815],[510890.0168465994,6651134.322734014,69.2533720091815],[510895.2643918404,6651124.829688958,73.34823914512941],[510890.6462141471,6651129.805156129,73.7830928381815],[510895.31624723226,6651124.463161212,73.84777029812942],[510890.11765147443,6651133.599160205,70.2980997021815],[510890.0197387282,6651134.301974417,69.71896269618149],[510890.69994534896,6651129.4194754725,74.4298308571815],[510890.5876643615,6651130.225424409,73.7044181451815],[510890.1345064874,6651133.478175522,70.7244100531815],[510895.20530383894,6651125.247338717,73.51535390212942],[510895.26641973795,6651124.815355238,74.00426159012942],[510890.5288409244,6651130.64765695,73.58226502318149],[510890.02878280025,6651134.23705639,70.19623364818152],[510890.6348005337,6651129.88708264,74.3870556161815],[510890.1575654265,6651133.312659276,71.1462189121815],[510890.4706386151,6651131.065431057,73.41515026618151],[510890.18685608363,6651133.10241198,71.5565684551815],[510895.14558525756,6651125.669445583,73.63750702412942],[510890.4140174926,6651131.471855461,73.2028724571815],[510895.21588426747,6651125.172553425,74.13188434912941],[510890.56844410993,6651130.363386692,74.2978909641815],[510890.04444527865,6651134.124631675,70.6791346681815],[510890.2222090524,6651132.8486496275,71.9483481491815],[510890.35995868745,6651131.859887643,72.9466593341815],[510890.252485071,6651132.6313294405,72.2258300091815],[510890.3216710017,6651132.134715291,72.72724032818151],[510890.28573470435,6651132.392664757,72.4862706821815],[510890.51841941255,6651130.72246219,74.1987954701815],[510890.06073450454,6651134.007708192,71.0408406531815],[510895.1650983207,6651125.531522047,74.23097984312942],[510895.086144492,6651126.0895887725,73.71618171712942],[510890.46864143724,6651131.079766729,74.0711727111815],[510890.0809986501,6651133.862252874,71.3985984991815],[510890.4195608259,6651131.432065613,73.91468141918152],[510890.1052401361,6651133.688248351,71.7490547141815],[510890.37164432526,6651131.776008551,73.7294725171815],[510890.1333903089,6651133.486187411,72.0887997411815],[510895.02778906137,6651126.502060527,73.7539245761294],[510890.32536198973,6651132.1082215095,73.5162201821815],[510890.16530705616,6651133.257090134,72.4144668511815],[510890.2811732329,6651132.425406835,73.2761317351815],[510890.20077558403,6651133.002498302,72.7228356591815],[510895.0977321196,6651126.0076843295,74.32014449512941],[510890.23951251997,6651132.724445951,73.01093401018151],[510895.03159596474,6651126.4751523165,74.36291973612943],[510893.93069086946,6651134.256643257,67.35765722912942],[510893.93069086946,6651134.256643257,67.48765722912941],[510893.8452964614,6651134.860233717,67.35765722912942],[510894.7826448441,6651128.23480526,73.7539245761294],[510893.93069054175,6651134.256645573,69.1864608891294],[510893.93132728094,6651134.252144931,69.3902821731294],[510894.54259682476,6651129.931528707,73.7539245761294],[510905.6944133563,6651123.011681235,67.17808119638813],[510893.8452964614,6651134.860233717,69.18646088812942],[510893.93661439157,6651134.214774222,69.80686146112942],[510894.48424139415,6651130.344000459,73.71618171712942],[510893.9476353321,6651134.136875275,70.23118858112942],[510893.848232601,6651134.839480299,69.6520515751294],[510894.5387902491,6651129.9584345985,74.36291973612943],[510894.42480062856,6651130.764143649,73.63750702412942],[510905.60571014445,6651123.614794314,67.17808119638813],[510893.9647468358,6651134.015926601,70.65749893212941],[510905.60571014445,6651123.614794314,67.30808119638813],[510894.3650820473,6651131.186250514,73.51535390212942],[510893.857414301,6651134.7745815925,70.12932252712942],[510894.47265409434,6651130.4259025855,74.32014449512941],[510893.98815667373,6651133.850459621,71.07930779112941],[510894.30599404575,6651131.603900274,73.34823914512941],[510894.0178930608,6651133.640274904,71.48965733412942],[510894.24851129286,6651132.010203708,73.13596133612941],[510893.8733151229,6651134.662190341,70.61222354712942],[510894.4052878933,6651130.902064868,74.23097984312942],[510894.05378401256,6651133.38658808,71.88143702812941],[510894.1936298492,6651132.398120395,72.87974821312942],[510894.0845207557,6651133.16933258,72.15891888812942],[510894.15475952154,6651132.672866243,72.66032920712941],[510894.11827636434,6651132.93073893,72.41935956112941],[510893.8898522296,6651134.54530166,70.97392953212943],[510894.35450194636,6651131.26103349,74.13188434912941],[510893.9104247444,6651134.399889637,71.33168737812943],[510894.303966476,6651131.618231678,74.00426159012942],[510905.6944133563,6651123.011681235,69.00688485538814],[510893.93503512454,6651134.225936903,71.68214359312941],[510894.25413898163,6651131.970425703,73.84777029812942],[510894.20549331285,6651132.314266268,73.66256139612942],[510893.963613672,6651134.023936105,72.02188862012942],[510894.1585066771,6651132.646380346,73.44930906112941],[510893.9960161115,6651133.794907017,72.34755573012941],[510894.11364547885,6651132.963471265,73.2092206141294],[510894.0320243808,6651133.540390962,72.65592453812943],[510894.0713507951,6651133.262421373,72.94402288912941],[510905.6913634492,6651123.032418239,69.47247554238812],[510905.60571014445,6651123.614794314,69.00688485538814],[510905.60301905,6651123.633091672,69.41770016738813],[510905.681825983,6651123.097265616,69.94974649438814],[510905.5946036386,6651123.690309946,69.83882159538813],[510905.665309047,6651123.209567977,70.43264751438814],[510905.5800298714,6651123.789400265,70.26491073038812],[510905.6481311718,6651123.326364213,70.79435349938814],[510905.5590001202,6651123.932386272,70.68981723438813],[510905.6267615274,6651123.47166123,71.15211134538814],[510905.601197561,6651123.645476383,71.50256756038813],[510905.53138838866,6651124.120124641,71.10678393638813],[510905.57151167176,6651123.847317419,71.84231258738814],[510905.4972674815,6651124.352120361,71.50873285338812],[510905.5378537247,6651124.076165368,72.16797969738813],[510905.45692371484,6651124.6264267005,71.88861365538813],[510905.50045023166,6651124.330480128,72.47634850538813],[510905.4228746138,6651124.857934194,72.15501997038814],[510905.4596000245,6651124.608229869,72.76444685638813],[510905.38588526996,6651125.10943306,72.40272971038813],[510905.4156665354,6651124.90694354,73.02964458138813],[510905.3325826452,6651125.471849589,72.70017218038814],[510905.36906708626,6651125.22378367,73.26973302838813],[510905.27557469293,6651125.859459472,72.95638530338813],[510905.32025984454,6651125.555635081,73.48298536338815],[510905.21586463787,6651126.265441561,73.16866311238813],[510911.9093325254,6651123.936607438,67.0612983281163],[510905.2697292868,6651125.899203703,73.66819426538814],[510905.15448713506,6651126.682761002,73.33577786938812],[510911.818566591,6651124.539413537,67.0612983281163],[510905.21797111095,6651126.251119177,73.82468555738815],[510911.818566591,6651124.539413537,67.19129832811629],[510912.4432672205,6651124.017083507,67.0510918198317],[510905.09245461907,6651127.104534024,73.45793099138814],[510905.1654775269,6651126.608034858,73.95230831638814],[510912.3523240739,6651124.619862897,67.0510918198317],[510912.3523240739,6651124.619862897,67.18109181983169],[510905.112723761,6651126.966719572,74.05140381038814],[510905.03071068355,6651127.524344925,73.53660568438814],[510911.9093325254,6651123.936607438,68.8901019871163],[510904.97009413684,6651127.936490453,73.57434854338813],[510905.04274730064,6651127.442505258,74.14056846238815],[510911.9062116951,6651123.957333889,69.3556926741163],[510911.818566591,6651124.539413537,68.8901019871163],[510904.9740485475,6651127.909603526,74.18334370338813],[510912.4432672205,6651124.017083507,68.8798954788317],[510911.81581291725,6651124.55770158,69.3009172991163],[510911.8964524427,6651124.022148259,69.8329636261163],[510903.8304863374,6651135.684940094,67.17808119638813],[510912.44014029705,6651124.037809039,69.3454861658317],[510903.8304863374,6651135.684940094,67.30808119638813],[510912.3523240739,6651124.619862897,68.8798954788317],[510911.8072018121,6651124.614890731,69.72203872711628],[510911.87955141853,6651124.134393457,70.3158646461163],[510903.7417831255,6651136.2880531745,67.17808119638813],[510912.34956502385,6651124.638150129,69.29071079083171],[510912.4303619906,6651124.102620537,69.8227571178317],[510904.7154512396,6651129.667864761,73.57434854338813],[510911.79228914366,6651124.713930614,70.1481278621163],[510911.86197408556,6651124.251130244,70.6775706311163],[510912.34093710635,6651124.695336746,69.71183221883169],[510912.4134279686,6651124.214860763,70.3056581378317],[510911.7707703624,6651124.85684384,70.57303436611629],[510911.8401075071,6651124.396353305,71.0353284771163],[510912.32599532226,6651124.794372239,70.1379213538317],[510912.3958163176,6651124.331592378,70.66736412283171],[510903.830485997,6651135.684942409,69.00688485638813],[510911.81394907105,6651124.570079989,71.38578469211629],[510911.74251654197,6651125.044486653,70.99000106811629],[510903.8311474081,6651135.680445326,69.21070614038813],[510912.3044345275,6651124.937279135,70.56282785783169],[510912.3739070466,6651124.476809003,71.0251219688317],[510904.4661020046,6651131.363246271,73.57434854338813],[510903.7417831255,6651136.2880531745,69.00688485538814],[510903.8366393801,6651135.643104174,69.62728542838813],[510911.78357286006,6651124.771818289,71.7255297191163],[510911.7076021803,6651125.276364288,71.3919499851163],[510904.4054854578,6651131.775391801,73.53660568438814],[510912.3476975387,6651124.6505279895,71.37557818383169],[510903.8480873526,6651135.565266836,70.05161254838814],[510912.2761255442,6651125.124913633,70.97979455983169],[510903.7448330327,6651136.26731617,69.47247554238812],[510904.46214793436,6651131.390130883,74.18334370338813],[510904.3437415222,6651132.195202701,73.45793099138814],[510911.7491322243,6651125.000549755,72.05119682911631],[510903.8658618811,6651135.444413821,70.47792289938815],[510904.28170900635,6651132.616975722,73.33577786938812],[510912.3172620209,6651124.8522573495,71.7153232108317],[510911.6663202515,6651125.550531007,71.77183078711629],[510903.754370499,6651136.202468793,69.94974649438814],[510904.3934491813,6651131.857229152,74.14056846238815],[510903.89017878723,6651135.279077708,70.89973175838813],[510912.2411430154,6651125.356780993,71.3817434768317],[510904.2203315035,6651133.034295163,73.16866311238813],[510903.9210673794,6651135.069059225,71.31008130138814],[510911.7108589428,6651125.254735068,72.35956563711629],[510903.7708874349,6651136.090166433,70.43264751438814],[510904.16062144836,6651133.440277252,72.95638530338813],[510904.3234727209,6651132.333014838,74.05140381038814],[510903.95834900916,6651134.815573043,71.70186099538815],[510911.63147936563,6651125.781920664,72.03823710211628],[510904.10361349623,6651133.827887136,72.70017218038814],[510903.99027671845,6651134.598489368,71.97934285538813],[510904.0632370478,6651134.102415687,72.48075317438813],[510904.02534026635,6651134.360084424,72.23978352838813],[510912.282754143,6651125.080978681,72.04099032083171],[510903.7880653101,6651135.973370197,70.79435349938814],[510904.2707189551,6651132.691699551,73.95230831638814],[510912.1997804874,6651125.630935564,71.76162427883169],[510903.8094349546,6651135.82807318,71.15211134538814],[510911.66905879654,6651125.532343438,72.64766398811629],[510904.2182253709,6651133.048615232,73.82468555738815],[510911.59362986404,6651126.033291517,72.28594684211629],[510903.83499892085,6651135.654258027,71.50256756038813],[510904.1664671951,6651133.400530706,73.66819426538814],[510912.24440613645,6651125.335152732,72.3493591288317],[510903.8646848101,6651135.45241699,71.84231258738814],[510904.11593663733,6651133.74409933,73.48298536338815],[510912.16487157793,6651125.862314968,72.02803059383169],[510903.89834275714,6651135.223569042,72.16797969738813],[510904.0671293956,6651134.07595074,73.26973302838813],[510903.93574625015,6651134.969254282,72.47634850538813],[510904.02052994655,6651134.39279087,73.02964458138813],[510903.9765964573,6651134.691504541,72.76444685638813],[510911.6241036692,6651125.830905064,72.9128617131163],[510911.5390877292,6651126.395523578,72.58338931211631],[510912.2025243793,6651125.612748801,72.6374574798317],[510912.1269481787,6651126.1136746835,72.27574033383169],[510911.57642058696,6651126.147583925,73.1529501601163],[510912.1574814811,6651125.911297198,72.9026552048317],[510911.48075410246,6651126.782936172,72.8396024351163],[510912.07229955535,6651126.475890695,72.57318280383171],[510911.52647837176,6651126.479266424,73.3662024951163],[510912.109705302,6651126.227962027,73.1427436518317],[510911.4196555375,6651127.188711617,73.05188024411629],[510911.47477276606,6651126.822660171,73.5514113971163],[510912.01385203755,6651126.863286121,72.82939592683171],[510912.0596655792,6651126.55962983,73.3559959868317],[510911.3568507498,6651127.605818644,73.21899500111631],[510911.42181099503,6651127.174396523,73.7079026891163],[510911.95263418334,6651127.269043588,73.0416737358317],[510912.0078590231,6651126.903008361,73.5412048888317],[510911.2933757172,6651128.027376986,73.34114812311628],[510911.36809671443,6651127.531130535,73.83552544811629],[510911.889706775,6651127.686132133,73.2087884928317],[510911.9547938491,6651127.2547291275,73.6976961808317],[510911.3141162017,6651127.88963268,73.9346209421163],[510911.2301959755,6651128.446974205,73.4198228161163],[510911.8261078131,6651128.107671796,73.33094161483169],[510911.90097469627,6651127.611447334,73.82531893983169],[510911.1681698393,6651128.858909952,73.45756567511629],[510911.2425124945,6651128.365176194,74.02378559411629],[510911.8468887916,6651127.969933594,73.9244144338317],[510911.7628047189,6651128.527250421,73.4096163078317],[510911.17221620656,6651128.832036711,74.06656083511629],[510911.70065748226,6651128.939167919,73.44735916683169],[510911.7751452848,6651128.445456036,74.0135790858317],[510910.0020613679,6651136.603415671,67.0612983281163],[510910.0020613679,6651136.603415671,67.19129832811629],[510911.70471174974,6651128.912295869,74.0563543268317],[510909.9112954335,6651137.2062217705,67.0612983281163],[510910.90760542435,6651130.589403001,73.45756567511629],[510910.53227229137,6651136.683330483,67.0510918198317],[510910.53227229137,6651136.683330483,67.18109181983169],[510910.4413291449,6651137.286109873,67.0510918198317],[510911.43958433927,6651130.669584288,73.44735916683169],[510910.00206101965,6651136.603417983,68.8901019881163],[510910.0027378113,6651136.5989231905,69.09392327211629],[510910.65245777124,6651132.283921569,73.45756567511629],[510909.9112954335,6651137.2062217705,68.8901019871163],[510910.0083574948,6651136.561601045,69.5105025601163],[510910.5322719425,6651136.683332797,68.8798954798317],[510910.59043163504,6651132.695857318,73.4198228161163],[510910.02007168066,6651136.483803324,69.93482968011631],[510910.53295005544,6651136.678838202,69.08371676383169],[510909.9144162638,6651137.185495321,69.3556926741163],[510910.64841175237,6651132.310792496,74.06656083511629],[510910.5272518934,6651133.115454536,73.34114812311628],[510910.03825954173,6651136.363011824,70.36114003111629],[510911.1839385339,6651132.364027774,73.44735916683169],[510910.4413291449,6651137.286109873,68.8798954788317],[510910.5385807108,6651136.64151771,69.5002960518317],[510910.46377686074,6651133.537012877,73.21899500111631],[510909.92417551624,6651137.12068095,69.8329636261163],[510910.5781154644,6651132.777653014,74.02378559411629],[510910.0631419182,6651136.197759866,70.78294889011629],[510911.1217912973,6651132.775945271,73.4096163078317],[510910.400972073,6651133.954119906,73.05188024411629],[510910.55031776766,6651136.5637234375,69.92462317183171],[510910.09474880004,6651135.987848282,71.1932984331163],[510910.4444560683,6651137.265384341,69.3454861658317],[510909.9410765405,6651137.00843575,70.3158646461163],[510910.3398735081,6651134.359895351,72.8396024351163],[510910.5065117572,6651133.253196527,73.9346209421163],[510910.1328973843,6651135.734491124,71.58507812711629],[510911.1798846155,6651132.3908975115,74.0563543268317],[510911.0584882031,6651133.195523898,73.33094161483169],[510910.28153988137,6651134.747307943,72.58338931211631],[510910.1655675471,6651135.517517943,71.86255998711628],[510910.2402245108,6651135.021696761,72.36397030611629],[510910.2014464698,6651135.279234346,72.1230006601163],[510910.5685411388,6651136.4429372875,70.3509335228317],[510922.71994794323,6651125.597320058,66.84928826316256],[510909.9586538735,6651136.891698964,70.6775706311163],[510910.4525312445,6651133.611698673,73.83552544811629],[510910.99488924124,6651133.61706356,73.2087884928317],[510910.45423437475,6651137.200572843,69.8227571178317],[510909.98052045197,6651136.746475902,71.0353284771163],[510910.5934720958,6651136.277692652,70.77274238183169],[510911.10945108056,6651132.857737343,74.0135790858317],[510910.3988169639,6651133.968432685,73.7079026891163],[510910.9319618329,6651134.034152106,73.0416737358317],[510910.0066788879,6651136.572749219,71.38578469211629],[510910.6251406871,6651136.0677903695,71.1830919248317],[510910.34585519286,6651134.320169036,73.5514113971163],[510910.4711683966,6651137.088332616,70.3056581378317],[510922.6255939815,6651126.199574968,66.84928826316256],[510910.8707439787,6651134.439909572,72.82939592683171],[510910.03705509886,6651136.371010919,71.7255297191163],[510910.2941495873,6651134.663562784,73.3662024951163],[510911.0377075736,6651133.333259786,73.9244144338317],[510910.66336375306,6651135.814444437,71.5748716188317],[510910.81229646085,6651134.827304999,72.57318280383171],[510910.69609770126,6651135.597480871,71.8523534788317],[510910.07149573474,6651136.142279453,72.05119682911631],[510922.6255939815,6651126.199574968,66.97928826316257],[510910.244207372,6651134.9952452835,73.1529501601163],[510910.77090042585,6651135.101681658,72.35376379783169],[510910.73204667435,6651135.35920783,72.11279415183171],[510910.1097690162,6651135.888094139,72.35956563711629],[510910.19652428984,6651135.311924145,72.9128617131163],[510910.1515691624,6651135.61048577,72.64766398811629],[510910.48878004774,6651136.971601002,70.66736412283171],[510910.98362166894,6651133.691746046,73.82531893983169],[510910.5106893187,6651136.826384375,71.0251219688317],[510910.9298025161,6651134.048464252,73.6976961808317],[510910.5368988266,6651136.652665391,71.37557818383169],[510910.8767373421,6651134.400185017,73.5412048888317],[510910.56733434444,6651136.450936031,71.7153232108317],[510910.82493078604,6651134.7435635505,73.3559959868317],[510910.6018422223,6651136.222214699,72.04099032083171],[510910.7748910632,6651135.075231353,73.1427436518317],[510910.6401902289,6651135.968040647,72.3493591288317],[510910.7271148843,6651135.391896181,72.9026552048317],[510910.682071986,6651135.690444578,72.6374574798317],[510922.71994794323,6651125.597320058,68.67809192216257],[510922.71670374484,6651125.618027556,69.14368260916255],[510922.6255939815,6651126.199574968,68.67809192216257],[510922.62273145345,6651126.217846289,69.08890723416256],[510922.70655870374,6651125.682782662,69.62095356116257],[510922.61377994664,6651126.274983148,69.51002866216255],[510922.68898957275,6651125.794925229,70.10385458116257],[510922.59827777214,6651126.3739324715,69.93611779716255],[510922.6707173981,6651125.911555273,70.46556056616257],[510922.5759083416,6651126.516715024,70.36102430116256],[510922.6479864217,6651126.056645547,70.82331841216256],[510922.62079392845,6651126.23021338,71.17377462716257],[510922.5465376321,6651126.70418626,70.77799100316255],[510922.589216929,6651126.431767216,71.51351965416256],[510922.51024308644,6651126.935851873,71.17993992016255],[510922.55341483594,6651126.660289537,71.83918676416256],[510922.4673292602,6651127.209767902,71.55982072216257],[510922.5136285905,6651126.9142424315,72.14755557216256],[510922.43111109495,6651127.440945984,71.82622703716255],[510922.47017606156,6651127.191596963,72.43565392316256],[510922.39176538173,6651127.692086992,72.07393677716257],[510922.4234438331,6651127.489885594,72.70085164816255],[510922.33506716625,6651128.053987837,72.37137924716257],[510922.37387581245,6651127.806274893,72.94094009516256],[510922.27442757913,6651128.441046191,72.62759237016256],[510922.32195935387,6651128.137654111,73.15419243016257],[510922.2109137543,6651128.846450608,72.83987017916256],[510922.2682097972,6651128.4807338705,73.33940133216257],[510929.1382577701,6651126.614498805,66.71807430255812],[510922.14562625857,6651129.263176247,73.00698493616255],[510922.2131544181,6651128.832148603,73.49589262416256],[510929.0417735806,6651127.216416116,66.71807430255812],[510922.0796420229,6651129.684349127,73.12913805816257],[510929.0417735806,6651127.216416116,66.8480743025581],[510922.1573167824,6651129.188556428,73.62351538316257],[510922.10120239033,6651129.546730771,73.72261087716257],[510922.0139647514,6651130.103562677,73.20781275116256],[510921.94948668766,6651130.5151217645,73.24555561016255],[510922.0267681491,6651130.021839462,73.81177552916256],[510929.1382577701,6651126.614498805,68.54687796155812],[510921.95369301015,6651130.488273094,73.85455077016256],[510929.1349403274,6651126.635194695,69.0124686485581],[510929.0417735806,6651127.216416116,68.54687796155812],[510920.737281306,6651138.252546136,66.84928826316256],[510920.737281306,6651138.252546136,66.97928826316257],[510929.03884642536,6651127.234677196,68.9576932735581],[510929.124566242,6651126.699913502,69.48973960055811],[510920.64292734413,6651138.854801047,66.84928826316256],[510921.6786220178,6651132.2440325,73.24555561016255],[510929.02969282056,6651127.291782024,69.3788147015581],[510929.10660045303,6651126.811993206,69.97264062055812],[510929.0138406538,6651127.390675882,69.80490383655811],[510929.08791574783,6651126.928557873,70.33434660555811],[510931.9169592113,6651127.062094056,66.66002999750813],[510920.7372809439,6651138.252548446,68.67809192316255],[510928.99096618895,6651127.533378394,70.22981034055812],[510929.0646715746,6651127.073566816,70.69210445155811],[510920.73798448953,6651138.248057762,68.88191320716255],[510931.81955277483,6651127.6638628105,66.66002999750813],[510921.4133882375,6651133.937001651,73.24555561016255],[510931.81955277483,6651127.6638628105,66.79002999750811],[510920.64292734413,6651138.854801047,68.67809192216257],[510920.7438263221,6651138.210769743,69.29849249516256],[510929.03686515684,6651127.247037352,71.0425606665581],[510928.96093237755,6651127.720744543,70.6467770425581],[510921.3489101739,6651134.348560738,73.20781275116256],[510920.75600357633,6651138.13304316,69.72281961516256],[510920.6461715426,6651138.834093549,69.14368260916255],[510921.4091822772,6651133.963848009,73.85455077016256],[510929.00457524415,6651127.448478205,71.38230569355812],[510921.28323290235,6651134.767774289,73.12913805816257],[510920.7749104135,6651138.012362106,70.14912996616256],[510928.9238184106,6651127.952280293,71.0487259595581],[510920.6563165837,6651138.769338443,69.62095356116257],[510921.2172486666,6651135.188947171,73.00698493616255],[510920.80077640404,6651137.847261251,70.57093882516256],[510921.33610713837,6651134.430281643,73.81177552916256],[510931.9169592113,6651127.062094056,68.48883365650812],[510921.151961171,6651135.6056728065,72.83987017916256],[510928.96796484786,6651127.676872426,71.7079728035581],[510920.83363272325,6651137.637541602,70.98128836816258],[510920.67388571467,6651138.657195876,70.10385458116257],[510921.08844734606,6651136.011077224,72.62759237016256],[510920.87328934215,6651137.384416107,71.37306806216256],[510921.2616728971,6651134.905390334,73.72261087716257],[510928.8799357197,6651128.226042776,71.4286067615581],[510921.02780775895,6651136.398135577,72.37137924716257],[510920.9072509745,6651137.16764132,71.65054992216255],[510920.98485916905,6651136.672273502,72.15196024116256],[510920.9445482108,6651136.9295756025,71.91099059516256],[510920.6921578893,6651138.54056583,70.46556056616257],[510921.20555850497,6651135.263564675,73.62351538316257],[510931.9136100587,6651127.082784838,68.95442434350811],[510931.81955277483,6651127.6638628105,68.48883365650812],[510928.9272803492,6651127.930682964,72.0163416115581],[510920.7148888657,6651138.395475556,70.82331841216256],[510921.1497208692,6651135.6199725,73.49589262416256],[510928.84289985773,6651128.457091268,71.69501307655811],[510920.742081359,6651138.221907725,71.17377462716257],[510921.09466549027,6651135.9713872345,73.33940133216257],[510920.77365835843,6651138.020353888,71.51351965416256],[510931.81659764034,6651127.682119383,68.89964896850812],[510921.04091593355,6651136.314466992,73.15419243016257],[510931.9031368123,6651127.147487671,69.43169529550813],[510920.80946045154,6651137.791831567,71.83918676416256],[510920.988999475,6651136.64584621,72.94094009516256],[510920.84924669686,6651137.5378786735,72.14755557216256],[510928.8828467932,6651128.207882023,72.30443996255812],[510920.9394314543,6651136.962235509,72.70085164816255],[510920.8926992259,6651137.26052414,72.43565392316256],[510928.80266583705,6651128.708091495,71.9427228165581],[510931.8073565405,6651127.739210118,69.32077039650812],[510931.8849992968,6651127.259539713,69.91459631550813],[510928.83505949215,6651128.506003444,72.5696376875581],[510928.7446875469,6651129.069789475,72.24016528655811],[510931.7913528504,6651127.838079567,69.74685953150811],[510931.86613599333,6651127.376075613,70.27630230050812],[510928.78437237523,6651128.822215388,72.8097261345581],[510928.682678901,6651129.456630859,72.4963784095581],[510931.7682597393,6651127.980746861,70.17176603550811],[510931.84266963997,6651127.521048766,70.63406014650812],[510928.73128379975,6651129.153408848,73.02297846955811],[510931.8145974338,6651127.69447649,70.98451636150811],[510928.6177311257,6651129.8618080225,72.7086562185581],[510931.7379388489,6651128.168066767,70.58873273750811],[510928.6763207404,6651129.496296291,73.20818737155811],[510931.78199887706,6651127.895867626,71.32426138850812],[510928.5509696356,6651130.278300061,72.87577097555811],[510928.62002237706,6651129.847514034,73.36467866355811],[510931.70047012705,6651128.3995453715,70.99068165450811],[510931.74503853923,6651128.1242054785,71.64992849850812],[510928.483495675,6651130.699236848,72.9979240975581],[510928.5629240961,6651130.203722072,73.4923014225581],[510931.65616798215,6651128.67324029,71.37056245650811],[510928.50554281037,6651130.561695635,73.59139691655812],[510928.41633560887,6651131.118215404,73.07659879055812],[510931.7039651566,6651128.377953374,71.95829730650811],[510931.61877811176,6651128.904231757,71.63696877150811],[510928.3504018253,6651131.529543788,73.11434164955811],[510928.42942806875,6651131.036537999,73.6805615685581],[510931.6591068812,6651128.655084019,72.24639565750813],[510931.578159513,6651129.1551700365,71.88467851150811],[510928.3547031138,6651131.502710169,73.7233368095581],[510931.6108628039,6651128.953131862,72.51159338250811],[510927.1108285054,6651139.262630868,66.71807430255812],[510931.5196270357,6651129.516778748,72.18212098150812],[510927.1108285054,6651139.262630868,66.8480743025581],[510931.55969119264,6651129.269265763,72.75168182950812],[510927.01434431603,6651139.864548177,66.71807430255812],[510931.45702567836,6651129.903524657,72.43833410450812],[510928.0734218488,6651133.257485365,73.11434164955811],[510931.5060951684,6651129.600377483,72.96493416450812],[510931.39145709784,6651130.308601822,72.65061191350811],[510931.450606743,6651129.943180299,73.15014306650812],[510927.1108281352,6651139.2626331765,68.5468779625581],[510931.32405746606,6651130.724991065,72.81772667050811],[510931.39377025014,6651130.294311362,73.30663435850812],[510927.11154756474,6651139.258145011,68.75069924655811],[510931.25593855366,6651131.145823965,72.93987979250812],[510927.8021998904,6651134.949505504,73.11434164955811],[510927.01434431603,6651139.864548177,68.54687796155812],[510931.33612619364,6651130.650431485,73.43425711750811],[510927.11752128834,6651139.220877892,69.16727853455812],[510927.73626610683,6651135.360833889,73.07659879055812],[510927.129973468,6651139.143194879,69.59160565455811],[510931.2781964273,6651131.008316698,73.53335261150812],[510931.18813653616,6651131.564699115,73.01855448550813],[510927.01766175864,6651139.843852287,69.0124686485581],[510927.79789897223,6651134.9763368135,73.7233368095581],[510927.6691060406,6651135.779812445,72.9979240975581],[510927.1493071646,6651139.022581476,70.0179160055581],[510931.12157252245,6651131.975925981,73.05629734450812],[510927.02803584404,6651139.77913348,69.48973960055811],[510927.6016320801,6651136.200749233,72.87577097555811],[510927.17575713113,6651138.857573168,70.43972486455812],[510931.2013541406,6651131.483041869,73.62251726350812],[510927.7231740173,6651135.442508983,73.6805615685581],[510927.53487058997,6651136.61724127,72.7086562185581],[510927.20935524686,6651138.647971082,70.85007440755811],[510927.046001633,6651139.667053777,69.97264062055812],[510927.4699228147,6651137.022418435,72.4963784095581],[510927.2499071924,6651138.394987477,71.2418541015581],[510927.64705927565,6651135.917351346,73.59139691655812],[510927.2846355759,6651138.178334206,71.5193359615581],[510927.40791416867,6651137.409259818,72.24016528655811],[510939.7204918468,6651128.342472709,66.49301605051268],[510927.32277487125,6651137.940401938,71.7797766345581],[510927.36399592925,6651137.683244072,72.02074628055811],[510931.12591492495,6651131.949098984,73.66529250450812],[510927.0646863382,6651139.550489109,70.33434660555811],[510927.5896779899,6651136.275324911,73.4923014225581],[510929.870150705,6651139.707104495,66.66002999750813],[510927.0879305114,6651139.405480167,70.69210445155811],[510927.53257970896,6651136.6315329475,73.36467866355811],[510929.870150705,6651139.707104495,66.79002999750811],[510927.1157369292,6651139.23200963,71.0425606665581],[510927.4762813457,6651136.982750693,73.20818737155811],[510939.62049542944,6651128.943816506,66.49301605051268],[510927.14802684187,6651139.030568777,71.38230569355812],[510927.4213182863,6651137.325638134,73.02297846955811],[510939.62049542944,6651128.943816506,66.62301605051267],[510927.18463723816,6651138.802174556,71.7079728035581],[510927.3682297108,6651137.656831594,72.8097261345581],[510927.2253217368,6651138.548364019,72.0163416115581],[510929.77274426864,6651140.308873249,66.66002999750813],[510927.3175425938,6651137.973043539,72.5696376875581],[510927.2697552928,6651138.271164959,72.30443996255812],[510930.8419450249,6651133.703441093,73.05629734450812],[510939.7204918468,6651128.342472709,68.32181970951268],[510929.87015033123,6651139.7071068045,68.48883365750811],[510929.87087663746,6651139.702619746,68.69265494150811],[510939.7170536422,6651128.363148879,68.78741039651267],[510939.62049542944,6651128.943816506,68.32181970951268],[510930.5681305835,6651135.395043635,73.05629734450812],[510929.77274426864,6651140.308873249,68.48883365650812],[510929.8769074611,6651139.665361826,69.10923422950813],[510939.61746171955,6651128.962060186,68.73263502151268],[510939.70630191825,6651128.427806021,69.26468134851268],[510930.50156656984,6651135.8062705,73.01855448550813],[510929.88947866537,6651139.587697985,69.53356134950812],[510929.7760934212,6651140.288182467,68.95442434350811],[510930.56378855486,6651135.421868321,73.66529250450812],[510939.6079749042,6651129.019110605,69.15375644951267],[510930.43376455235,6651136.22514565,72.93987979250812],[510929.9089971635,6651139.467114348,69.95987170050812],[510939.68768213666,6651128.539778934,69.74758236851268],[510929.7865666676,6651140.223479633,69.43169529550813],[510930.36564563995,6651136.645978549,72.81772667050811],[510929.9356999528,6651139.302146767,70.38168055950811],[510930.48834933934,6651135.887925437,73.62251726350812],[510930.2982460081,6651137.062367794,72.65061191350811],[510939.59154568514,6651129.117910235,69.57984558451267],[510929.96961921715,6651139.092596412,70.79203010250812],[510929.804704183,6651140.111427591,69.91459631550813],[510939.6683172688,6651128.656232538,70.10928835351268],[510930.2326774276,6651137.467444957,72.43833410450812],[510930.01055877964,6651138.839675245,71.18380979650811],[510930.41150705266,6651136.362650607,73.53335261150812],[510930.04561911547,6651138.623075444,71.46129165650811],[510930.17007607024,6651137.854190868,72.18212098150812],[510930.08412296633,6651138.385201898,71.72173232950811],[510930.12573803705,6651138.1281075,71.96270197550812],[510929.8235674865,6651139.994891694,70.27630230050812],[510930.3535772863,6651136.720535822,73.43425711750811],[510939.5678385415,6651129.26047678,70.00475208851269],[510929.8470338399,6651139.84991854,70.63406014650812],[510939.6442269587,6651128.801103313,70.46704619951268],[510930.2959332297,6651137.076655945,73.30663435850812],[510929.87510604603,6651139.676490816,70.98451636150811],[510930.2390967368,6651137.427787006,73.15014306650812],[510929.9077046028,6651139.475099679,71.32426138850812],[510930.1836083114,6651137.770589822,72.96493416450812],[510929.9446649406,6651139.246761828,71.64992849850812],[510930.13001228723,6651138.101701542,72.75168182950812],[510929.9857383233,6651138.993013931,71.95829730650811],[510939.61540832865,6651128.974408567,70.81750241451267],[510930.07884067605,6651138.417835443,72.51159338250811],[510930.03059659875,6651138.715883288,72.24639565750813],[510939.5367114361,6651129.447664404,70.42171879051267],[510939.581942995,6651129.175657485,71.15724744151268],[510939.4982464425,6651129.678979545,70.82366770751267],[510939.54399990314,6651129.40383409,71.48291455151268],[510939.45276632905,6651129.952481185,71.20354850951267],[510939.50183440285,6651129.657402795,71.79128335951268],[510939.4143822835,6651130.183309532,71.46995482451268],[510939.45578337176,6651129.934337736,72.07938171051268],[510939.37268365966,6651130.434070605,71.71766456451267],[510939.4062565123,6651130.232175105,72.34457943551267],[510939.31259483757,6651130.795423956,72.01510703451268],[510939.35372427735,6651130.54808576,72.58466788251268],[510939.2483289461,6651131.181896754,72.27132015751268],[510939.2987031657,6651130.878963656,72.7979202175127],[510939.1810169349,6651131.586687861,72.48359796651268],[510945.8086486536,6651129.365379294,66.35860467732431],[510939.241739335,6651131.221524391,72.98312911951268],[510939.1118251857,6651132.002783062,72.65071272351267],[510945.70663158584,6651129.966383592,66.35860467732431],[510939.18339159264,6651131.572407492,73.1396204115127],[510945.70663158584,6651129.966383592,66.4886046773243],[510939.0418950307,6651132.423318778,72.77286584551268],[510939.12421481375,6651131.928276133,73.26724317051267],[510939.0647447283,6651132.285908615,73.36633866451268],[510938.9722901965,6651132.8418981265,72.85154053851268],[510945.8086486536,6651129.365379294,68.18740833632432],[510938.90395628416,6651133.252834594,72.88928339751267],[510938.98585924954,6651132.760298545,73.45550331651269],[510945.80514097237,6651129.386043793,68.6529990233243],[510945.70663158584,6651129.966383592,68.18740833632432],[510938.90841414867,6651133.2260265425,73.49827855751268],[510937.6192598813,6651140.9785535205,66.49301605051268],[510945.70353657304,6651129.984616972,68.5982236483243],[510937.6192598813,6651140.9785535205,66.62301605051267],[510945.7941719858,6651129.450664431,69.13026997532431],[510937.5192634639,6651141.579897319,66.49301605051268],[510945.6938580555,6651130.041635182,69.0193450763243],[510945.7751759502,6651129.562574126,69.61317099532432],[510938.6168936525,6651134.979129774,72.88928339751267],[510945.67709684744,6651130.140379032,69.44543421132431],[510945.755419772,6651129.678961985,69.97487698032431],[510945.65291064826,6651130.2828650875,69.87034071532432],[510945.7308426635,6651129.82375097,70.33263482632431],[510937.6192594977,6651140.978555827,68.32181971051267],[510937.6200051159,6651140.974071938,68.52564099451267],[510945.70144168887,6651129.9969583815,70.6830910413243],[510945.6211545503,6651130.469947032,70.2873074173243],[510937.5192634639,6651141.579897319,68.32181970951268],[510938.3357986428,6651136.669537742,72.88928339751267],[510937.62619629566,6651140.936840328,68.94222028251268],[510945.6673001137,6651130.19809368,71.02283606832432],[510938.2674647303,6651137.080474208,72.85154053851268],[510937.639101761,6651140.859231332,69.36654740251268],[510937.5227016685,6651141.5592211485,68.78741039651267],[510945.58191228594,6651130.7011315795,70.6892563343243],[510938.33134116215,6651136.696343485,73.49827855751268],[510938.19785989623,6651137.499053558,72.77286584551268],[510937.65913924476,6651140.738732849,69.79285775351269],[510937.5334533925,6651141.494564006,69.26468134851268],[510945.62859029707,6651130.426141462,71.34850317832431],[510938.1279297412,6651137.919589275,72.65071272351267],[510937.68655204587,6651140.573881765,70.21466661251267],[510938.2538960613,6651137.162071481,73.45550331651269],[510945.53551314556,6651130.974478807,71.0691371363243],[510938.058737992,6651138.335684474,72.48359796651268],[510937.72137320385,6651140.364479389,70.62501615551268],[510937.55207317404,6651141.382591093,69.74758236851268],[510937.9914259807,6651138.740475582,72.27132015751268],[510937.76340132585,6651140.111736829,71.01679584951269],[510938.1750105824,6651137.636461412,73.36633866451268],[510937.79939389566,6651139.895289987,71.29427770951267],[510937.92716008925,6651139.126948379,72.01510703451268],[510945.58557274897,6651130.679567009,71.6568719863243],[510937.8389215418,6651139.657584422,71.55471838251268],[510937.8816431333,6651139.400671579,71.79568802851267],[510937.5714380419,6651141.26613749,70.10928835351268],[510945.49635346484,6651131.205176835,71.33554345132431],[510938.11554049695,6651137.994093895,73.26724317051267],[510937.595528352,6651141.121266712,70.46704619951268],[510938.05636371806,6651138.349962533,73.1396204115127],[510937.62434698205,6651140.947961461,70.81750241451267],[510945.5385911543,6651130.956345601,71.9449703373243],[510937.9980159757,6651138.7008456355,72.98312911951268],[510937.6578123157,6651140.746712541,71.15724744151268],[510945.45381222747,6651131.455796335,71.5832531913243],[510937.9410521449,6651139.043406372,72.7979202175127],[510937.69575540756,6651140.518535936,71.48291455151268],[510937.88603103335,6651139.374284267,72.58466788251268],[510937.7379209078,6651140.264967231,71.79128335951268],[510937.8334987985,6651139.6901949225,72.34457943551267],[510937.78397193894,6651139.988032291,72.07938171051268],[510945.48806349415,6651131.254014821,72.2101680623243],[510945.39250917686,6651131.816945677,71.88069566132431],[510945.4344697285,6651131.56974712,72.4502565093243],[510945.3269446499,6651132.203200284,72.1369087843243],[510945.37833679287,6651131.900438213,72.66350884432433],[510945.2582724496,6651132.607762857,72.3491865933243],[510951.88891094783,6651130.4079775,66.2207633583812],[510945.32022188103,6651132.242805549,72.84871774632431],[510945.187682527,6651133.023623142,72.51630135032431],[510951.78487584996,6651131.008635759,66.2207633583812],[510945.2606950926,6651132.593490551,73.00520903832431],[510951.78487584996,6651131.008635759,66.3507633583812],[510945.1163392775,6651133.443921437,72.6384544723243],[510945.20032251516,6651132.949158277,73.1328317973243],[510945.04532792256,6651133.862264468,72.71712916532432],[510945.1396507041,6651133.306588852,73.23192729132433],[510951.88891094783,6651130.4079775,68.04956701738121],[510944.9756131713,6651134.272968933,72.75487202432431],[510945.05917116854,6651133.780710955,73.32109194332432],[510951.88533388014,6651130.428630099,68.5151577043812],[510951.78487584996,6651131.008635759,68.04956701738121],[510944.9801611169,6651134.246176015,73.3638671843243],[510943.6649566165,6651141.9943261435,66.35860467732431],[510943.6649566165,6651141.9943261435,66.4886046773243],[510951.7817196139,6651131.026858642,68.4603823293812],[510951.87414791284,6651130.493213531,68.99242865638121],[510943.5629395488,6651142.59533044,66.35860467732431],[510951.77184964257,6651131.083844024,68.8815037573812],[510951.85477611085,6651130.605058793,69.47532967638121],[510944.68274979986,6651135.998289496,72.75487202432431],[510951.7547568761,6651131.18253102,69.30759289238121],[510951.8346291299,6651130.721379639,69.83703566138121],[510951.7300922425,6651131.324935039,69.7324993963812],[510951.8095658542,6651130.866085261,70.1947935073812],[510943.66495622514,6651141.994328449,68.1874083373243],[510943.66571691027,6651141.98984709,68.39122962132431],[510951.7795832901,6651131.039192946,70.5452497223812],[510951.6977079677,6651131.511909266,70.1494660983812],[510943.5629395488,6651142.59533044,68.18740833632432],[510943.67203319655,6651141.952636503,68.80780890932432],[510944.39597463945,6651137.687743109,72.75487202432431],[510943.6851994456,6651141.875071323,69.23213602932431],[510944.3262598882,6651138.098447572,72.71712916532432],[510951.7447663502,6651131.240212437,70.8849947493812],[510943.56644723,6651142.574665943,68.6529990233243],[510951.6576894403,6651131.742960705,70.5514150153812],[510944.39142708544,6651137.714533719,73.3638671843243],[510944.2552485334,6651138.516790605,72.6384544723243],[510943.70564183145,6651141.754640868,69.65844638032432],[510943.5774162165,6651142.510045304,69.13026997532431],[510944.18390528375,6651138.937088898,72.51630135032431],[510951.70529080316,6651131.468128918,71.2106618593812],[510943.73360856925,6651141.5898828525,70.08025523932432],[510944.3124170339,6651138.179998779,73.32109194332432],[510944.11331536114,6651139.352949184,72.3491865933243],[510943.76913336624,6651141.380598699,70.49060478232431],[510951.6103724646,6651132.01615055,70.93129581738121],[510943.5964122523,6651142.398135608,69.61317099532432],[510944.04464316077,6651139.757511758,72.1369087843243],[510943.81201075995,6651141.127998831,70.8823844763243],[510944.2319374983,6651138.654120883,73.23192729132433],[510943.84873063985,6651140.911674188,71.1598663363243],[510943.9790786339,6651140.143766365,71.88069566132431],[510943.88905703014,6651140.674102826,71.4203070093243],[510943.9326419065,6651140.417335027,71.6612766553243],[510943.61616843037,6651142.28174775,69.97487698032431],[510951.6614223121,6651131.7214085525,71.5190306673812],[510944.1712656873,6651139.0115514565,73.1328317973243],[510951.5704381546,6651132.2467157515,71.1977021323812],[510943.6407455389,6651142.136958764,70.33263482632431],[510944.1108931098,6651139.367219183,73.00520903832431],[510943.6701465135,6651141.963751353,70.6830910413243],[510944.0513663213,6651139.717904185,72.84871774632431],[510951.61351136037,6651131.998027785,71.8071290183812],[510943.7042880887,6651141.762616056,71.02283606832432],[510943.99325140956,6651140.060271521,72.66350884432433],[510951.5270553962,6651132.497190952,71.44541187238121],[510956.69455060066,6651131.246897866,66.10926455844026],[510943.7429979053,6651141.534568272,71.34850317832431],[510943.9371184739,6651140.390962614,72.4502565093243],[510943.78601545334,6651141.281142725,71.6568719863243],[510943.8835247082,6651140.706694915,72.2101680623243],[510943.8329970481,6651141.004364133,71.9449703373243],[510951.5619841975,6651132.295525616,72.07232674338121],[510956.58892051806,6651131.847277692,66.10926455844026],[510951.4645396917,6651132.858132358,71.74285434238121],[510956.58892051806,6651131.847277692,66.23926455844025],[510951.50733027747,6651132.611076129,72.31241519038122],[510951.39767821325,6651133.244164573,71.99906746538122],[510951.45008695946,6651132.941576822,72.52566752538121],[510951.3276475875,6651133.648494214,72.2113452743812],[510956.69455060066,6651131.246897866,67.93806821744026],[510951.39082245925,6651133.283747035,72.71087642738121],[510956.69091869215,6651131.2675408935,68.40365890444025],[510951.2556613045,6651134.064115061,72.3784600313812],[510956.58892051806,6651131.847277692,67.93806821744026],[510951.3301181535,6651133.634230126,72.8673677193812],[510956.5857158929,6651131.865492125,68.34888352944026],[510956.6795612303,6651131.332094387,68.88092985644026],[510951.18290679285,6651134.484171363,72.50061315338122],[510951.2685513281,6651133.98969307,72.9949904783812],[510956.5756946031,6651131.922451091,68.77000495744025],[510951.1104907411,6651134.902273528,72.5792878463812],[510951.2066793498,6651134.346917849,73.09408597238121],[510956.659892435,6651131.443887804,69.36383087644026],[510951.0393969415,6651135.312741524,72.6170307053812],[510956.5583397836,6651132.021092342,69.19609409244028],[510951.12460782443,6651134.82076697,73.1832506243812],[510956.6394365763,6651131.560154729,69.72553686144026],[510951.0440348513,6651135.285964033,73.2260258653812],[510956.5332970111,6651132.163430348,69.62100059644025],[510956.61398905015,6651131.704793272,70.08329470744026],[510949.70281389734,6651143.029653051,66.2207633583812],[510949.70281389734,6651143.029653051,66.3507633583812],[510956.58354681684,6651131.877820711,70.43375092244025],[510956.50041624595,6651132.350317904,70.03796729844025],[510949.59877879947,6651143.630311312,66.2207633583812],[510950.7407403521,6651137.037068709,72.6170307053812],[510956.54819609073,6651132.07874702,70.77349594944026],[510956.45978418575,6651132.581262238,70.43991621544025],[510956.5081153355,6651132.30655785,71.09916305944026],[510956.41174178326,6651132.854325446,70.81979701744025],[510949.70281349815,6651143.029655356,68.0495670183812],[510949.70358923066,6651143.025176579,68.2533883023812],[510956.4635742871,6651132.559720077,71.40753186744026],[510956.37119523156,6651133.084783768,71.08620333244025],[510949.59877879947,6651143.630311312,68.04956701738121],[510949.71003046125,6651142.987987413,68.6699675903812],[510950.4482924064,6651138.725549594,72.6170307053812],[510956.41492880206,6651132.836211082,71.69563021844026],[510956.32714736264,6651133.335142861,71.33391307244025],[510949.72345715575,6651142.910466894,69.0942947103812],[510950.37719860673,6651139.136017589,72.5792878463812],[510949.60235586704,6651143.609658713,68.5151577043812],[510950.4436548959,6651138.7523247795,73.2260258653812],[510949.7443039185,6651142.790105779,69.5206050613812],[510950.30478255503,6651139.554119755,72.50061315338122],[510956.3626116651,6651133.133571006,71.96082794344025],[510949.61354183446,6651143.545075281,68.99242865638121],[510956.2636732163,6651133.695916952,71.63135554244026],[510949.7728238748,6651142.625442625,69.9424139203812],[510950.23202804336,6651139.974176056,72.3784600313812],[510950.3630819228,6651139.217521841,73.1832506243812],[510950.16004176036,6651140.389796902,72.2113452743812],[510949.8090513985,6651142.4162789695,70.35276346338122],[510949.63291363645,6651143.433230017,69.47532967638121],[510956.3071198339,6651133.448975246,72.20091639044026],[510950.09001113474,6651140.794126544,71.99906746538122],[510949.8527769627,6651142.163824541,70.7445431573812],[510949.8902232096,6651141.947624451,71.0220250173812],[510950.2810103975,6651139.691370961,73.09408597238121],[510950.0231496563,6651141.180158759,71.74285434238121],[510949.9313473083,6651141.7101898715,71.2824656903812],[510949.97579435,6651141.4535699105,71.5234353363812],[510949.6530606174,6651143.316909172,69.83703566138121],[510956.19578666997,6651134.081770221,71.88756866544026],[510950.2191384192,6651140.04859574,72.9949904783812],[510949.6781238931,6651143.172203549,70.1947935073812],[510962.45302920556,6651132.269492191,65.97268294412484],[510956.24899890606,6651133.779322733,72.41416872544028],[510950.1575715937,6651140.4040586855,72.8673677193812],[510949.7081064571,6651142.999095866,70.5452497223812],[510950.09686728806,6651140.754541776,72.71087642738121],[510949.7429233971,6651142.7980763735,70.8849947493812],[510956.1246823895,6651134.485912433,72.09984647444026],[510950.0376027878,6651141.0967119895,72.52566752538121],[510949.78239894414,6651142.570159893,71.2106618593812],[510949.9803594697,6651141.427212682,72.31241519038122],[510949.8262674352,6651142.316880259,71.5190306673812],[510949.9257055497,6651141.742763194,72.07232674338121],[510949.8741783869,6651142.040261026,71.8071290183812],[510956.18882580893,6651134.121334333,72.59937762744026],[510962.3454878923,6651132.869532619,65.97268294412484],[510962.3454878923,6651132.869532619,66.10268294412484],[510956.05159246904,6651134.90134062,72.26696123144026],[510956.1271908323,6651134.471654956,72.75586891944027],[510955.9777225421,6651135.321202202,72.38911435344025],[510956.0646801124,6651134.826953126,72.88349167844027],[510962.45302920556,6651132.269492191,67.80148660312486],[510955.9041962641,6651135.739110555,72.46778904644026],[510956.00185956137,6651135.184012312,72.98258717244026],[510955.8320125099,6651136.149388276,72.50553190544025],[510962.44933158264,6651132.290123547,68.26707729012483],[510962.3454878923,6651132.869532619,67.80148660312486],[510955.9185297795,6651135.65764178,73.07175182444027],[510962.3422252839,6651132.887736755,68.21230191512484],[510962.4377686233,6651132.354640549,68.74434824212484],[510955.83672152465,6651136.122623199,73.11452706544026],[510954.4749380199,6651143.862722614,66.10926455844026],[510954.4749380199,6651143.862722614,66.23926455844025],[510962.3320226727,6651132.944663522,68.63342334312483],[510962.4177439483,6651132.466370769,69.22724926212486],[510954.3693079373,6651144.463102438,66.10926455844026],[510962.3143538417,6651133.043249011,69.05951247812484],[510955.5287771513,6651137.872916145,72.50553190544025],[510962.396917969,6651132.5825719675,69.58895524712484],[510962.2888579548,6651133.1855065515,69.48441898212485],[510962.37101000483,6651132.727128746,69.94671309312484],[510954.4749376146,6651143.862724918,67.93806821844025],[510962.34001696133,6651132.900058372,70.29716930812484],[510962.2553822575,6651133.37228846,69.90138568412483],[510954.4757252401,6651143.858248216,68.14188950244025],[510954.3693079373,6651144.463102438,67.93806821744026],[510954.4822652226,6651143.821076291,68.55846879044026],[510955.2318456225,6651139.560614333,72.50553190544025],[510962.3040266128,6651133.100871096,70.63691433512486],[510962.2140150162,6651133.603102241,70.30333460112483],[510954.4958977647,6651143.743591704,68.98279591044026],[510955.1596618683,6651139.970892055,72.46778904644026],[510954.3729398458,6651144.442459412,68.40365890444025],[510962.2632206515,6651133.328553145,70.96258144512484],[510954.51706413366,6651143.623286384,69.40910626144027],[510955.2271370133,6651139.587377106,73.11452706544026],[510955.0861355904,6651140.388800407,72.38911435344025],[510962.16510335275,6651133.876011085,70.68321540312483],[510954.38429730764,6651144.377905917,68.88092985644026],[510954.5460213355,6651143.458699561,69.83091512044025],[510955.01226566336,6651140.808661992,72.26696123144026],[510955.14532875834,6651140.052358526,73.07175182444027],[510962.21787369426,6651133.581572256,71.27095025312484],[510954.58280427137,6651143.249632864,70.24126466344026],[510954.939175743,6651141.224090176,72.09984647444026],[510954.4039661029,6651144.266112501,69.36383087644026],[510962.1238231672,6651134.106339126,70.94962171812485],[510954.62720020174,6651142.99729546,70.63304435744027],[510954.86807146255,6651141.62823239,71.88756866544026],[510954.66522054514,6651142.781195589,70.91052621744025],[510955.0619989766,6651140.525987992,72.98258717244026],[510954.80018491624,6651142.01408566,71.63135554244026],[510954.7069751263,6651142.543871074,71.17096689044025],[510954.75210359547,6651142.28737007,71.41193653644025],[510954.4244219616,6651144.149845576,69.72553686144026],[510954.9991784255,6651140.883047179,72.88349167844027],[510962.1683480363,6651133.857906959,71.55904860412484],[510954.4498694878,6651144.005207032,70.08329470744026],[510962.0789783129,6651134.356556691,71.19733145812484],[510954.93666770565,6651141.238345348,72.75586891944027],[510954.48031172116,6651143.832179594,70.43375092244025],[510954.875032729,6651141.5886659715,72.59937762744026],[510954.5156624472,6651143.631253284,70.77349594944026],[510954.8148596318,6651141.930677571,72.41416872544028],[510954.55574320245,6651143.4034424545,71.09916305944026],[510962.1150842929,6651134.155098786,71.82424632912483],[510954.75673870405,6651142.261025059,72.20091639044026],[510954.60028425086,6651143.150280228,71.40753186744026],[510954.70124687284,6651142.576429299,71.96082794344025],[510954.6489297359,6651142.873789223,71.69563021844026],[510962.01435568935,6651134.717126833,71.49477392812484],[510962.05858841364,6651134.470324727,72.06433477612484],[510961.94524082966,6651135.102761977,71.75098705112484],[510961.99941586785,6651134.800485467,72.27758711112486],[510961.8728500153,6651135.506675729,71.96326486012484],[510961.9381540214,6651135.142303725,72.46279601312484],[510961.7984376337,6651135.92186907,72.13037961712485],[510961.87540384487,6651135.492426311,72.61928730512484],[510961.72323113226,6651136.341493303,72.25253273912483],[510961.81176207983,6651135.84752363,72.74691006412483],[510961.64837449783,6651136.75916541,72.33120743212484],[510961.7478048776,6651136.204380968,72.84600555812486],[510961.5748846781,6651137.1692111995,72.36895029112483],[510961.6629673583,6651136.67774269,72.93517021012485],[510961.579678896,6651137.142461253,72.97794545112484],[510960.1932557976,6651144.878185154,65.97268294412484],[510960.1932557976,6651144.878185154,66.10268294412484],[510960.08571448433,6651145.47822558,65.97268294412484],[510961.266162694,6651138.891764751,72.36895029112483],[510960.19325538503,6651144.878187455,67.80148660412483],[510960.1940572614,6651144.873713284,68.00530788812485],[510960.08571448433,6651145.47822558,67.80148660312486],[510960.20071557583,6651144.836562372,68.42188717612486],[510960.9638585989,6651140.578508874,72.36895029112483],[510971.8227599998,6651133.973851045,65.74349841073101],[510960.21459478,6651144.759121588,68.84621429612484],[510960.8903687793,6651140.988554664,72.33120743212484],[510960.0894121072,6651145.457594223,68.26707729012483],[510971.7121088866,6651134.573325796,65.74349841073101],[510960.2361441253,6651144.638884278,69.27252464712485],[510960.959064794,6651140.605256519,72.97794545112484],[510960.81551214476,6651141.406226771,72.25253273912483],[510971.7121088866,6651134.573325796,65.87349841073102],[510960.1009750667,6651145.393077222,68.74434824212484],[510960.2656252678,6651144.474390496,69.69433350612485],[510960.7403056434,6651141.8258510055,72.13037961712485],[510960.8757763315,6651141.069975081,72.93517021012485],[510960.30307374004,6651144.265441985,70.10468304912484],[510960.6658932617,6651142.241044347,71.96326486012484],[510960.1209997416,6651145.281347002,69.22724926212486],[510960.34827295353,6651144.013247228,70.49646274312485],[510960.5935024474,6651142.644958097,71.75098705112484],[510960.38698122266,6651143.797269521,70.77394460312483],[510960.79093881237,6651141.543336804,72.84600555812486],[510960.5243875877,6651143.030593241,71.49477392812484],[510960.42949129536,6651143.560079167,71.03438527612484],[510960.47543630184,6651143.303723163,71.27535492212483],[510960.1418257209,6651145.165145803,69.58895524712484],[510960.7269816101,6651141.900194142,72.74691006412483],[510960.16773368506,6651145.020589026,69.94671309312484],[510960.663339845,6651142.255291461,72.61928730512484],[510960.19872672856,6651144.847659399,70.29716930812484],[510971.8227599998,6651133.973851045,67.57230206973101],[510960.6005896685,6651142.605414046,72.46279601312484],[510960.2347170771,6651144.646846673,70.63691433512486],[510960.53932782204,6651142.947232305,72.27758711112486],[510960.2755230384,6651144.419164628,70.96258144512484],[510960.4801552763,6651143.277393045,72.06433477612484],[510960.32086999563,6651144.166145515,71.27095025312484],[510960.42365939694,6651143.592618984,71.82424632912483],[510960.37039565353,6651143.889810811,71.55904860412484],[510971.8189554519,6651133.994462951,68.037892756731],[510971.7121088866,6651134.573325796,67.57230206973101],[510973.640632066,6651134.310340218,65.69803378696157],[510971.70875193266,6651134.591512773,67.983117381731],[510971.80705812335,6651134.058919131,68.51516370873101],[510973.5293776037,6651134.90970329,65.69803378696157],[510971.69825428975,6651134.648385874,68.404238809731],[510973.5293776037,6651134.90970329,65.82803378696157],[510971.78645438957,6651134.170544021,68.99806472873101],[510971.6800745247,6651134.746878422,68.83032794473101],[510971.7650261801,6651134.286635673,69.35977071373101],[510971.6538413666,6651134.889001855,69.255234448731],[510971.7383690288,6651134.431056174,69.71752855973101],[510973.640632066,6651134.310340218,67.52683744596158],[510971.70647975145,6651134.603822773,70.06798477473102],[510971.6193976439,6651135.075607677,69.672201150731],[510973.63680677285,6651134.330948285,67.99242813296156],[510973.5293776037,6651134.90970329,67.52683744596158],[510971.6694486605,6651134.804446187,70.40772980173101],[510973.5260023452,6651134.927886878,67.93765275796157],[510971.5768341755,6651135.306203864,70.074150067731],[510973.62484457163,6651134.395392457,68.46969908496158],[510971.62746270286,6651135.0319135925,70.733396911731],[510973.5154474616,6651134.984749384,68.35877418596156],[510973.6041284916,6651134.5069965515,68.95260010496158],[510971.52650812076,6651135.57885543,70.45403086973101],[510971.5808044358,6651135.284694177,71.041765719731],[510973.4971685675,6651135.083223583,68.78486332096156],[510973.5825834401,6651134.623066576,69.31430608996158],[510971.48403422546,6651135.808966334,70.720437184731],[510971.52984663175,6651135.560768371,71.329864070731],[510973.4707923675,6651135.225320538,69.20976982496158],[510971.4378925809,6651136.058948012,70.96814692473102],[510973.5557809349,6651134.767460172,69.67206393596157],[510971.4750426469,6651135.857680027,71.595061795731],[510973.5237177744,6651134.940194585,70.02252015096157],[510973.436160833,6651135.411891597,69.62673652696157],[510971.3714012484,6651136.419178236,71.26558939473101],[510971.41691306175,6651136.172608795,71.835150242731],[510973.48648476356,6651135.140780623,70.36226517796158],[510973.3933652781,6651135.642444826,70.02868544396156],[510971.3002877764,6651136.804449832,71.521802517731],[510971.3560294081,6651136.502458286,72.04840257773101],[510973.4442698683,6651135.368205653,70.68793228796157],[510973.3427648097,6651135.915045596,70.40856624596157],[510971.22580361826,6651137.207982802,71.734080326731],[510971.2929960371,6651136.843954301,72.23361147973101],[510973.3973571871,6651135.620939145,70.99630109596157],[510973.3000593163,6651136.145113632,70.67497256096158],[510971.14923943457,6651137.622784729,71.90119508373101],[510971.2284312975,6651137.193746817,72.39010277173101],[510973.3461215246,6651135.896961908,71.28439944696157],[510973.2536660745,6651136.39504874,70.92268230096157],[510971.0718581673,6651138.042013371,72.023348205731],[510971.1629491871,6651137.548509375,72.51772553073101],[510973.2910187092,6651136.19381825,71.54959717196157],[510970.99483688414,6651138.459291728,72.10202289873101],[510971.097142518,6651137.905030296,72.61682102473101],[510973.1868121835,6651136.7552118525,71.22012477096158],[510973.2325721599,6651136.508688348,71.78968561896157],[510970.91922194045,6651138.868950957,72.139765757731],[510979.0699909608,6651135.326591749,65.56030910294606],[510971.00985173025,6651138.377945767,72.705985676731],[510973.11531095003,6651137.140411674,71.47633789396157],[510973.171356525,6651136.838476388,72.00293795396159],[510969.49764014105,6651146.5706574535,65.74349841073101],[510970.92415479396,6651138.842226227,72.748760917731],[510978.95693450235,6651135.925617528,65.56030910294606],[510969.49764014105,6651146.5706574535,65.87349841073102],[510978.95693450235,6651135.925617528,65.69030910294606],[510973.0404206509,6651137.5438694665,71.68861570296157],[510973.107979451,6651137.179908785,72.18814685596158],[510969.3869890279,6651147.170132206,65.74349841073101],[510972.9634389844,6651137.958594119,71.85573045996156],[510973.04306265817,6651137.529636135,72.34463814796158],[510970.6015725631,6651140.58988061,72.139765757731],[510972.88563577924,6651138.37774466,71.97788358196158],[510979.0699909608,6651135.326591749,67.38911276194607],[510972.97722349246,6651137.884332602,72.47226090696157],[510972.8081945209,6651138.794945278,72.05655827496157],[510972.9110579982,6651138.240787105,72.57135640096159],[510979.06610370916,6651135.347188219,67.85470344894605],[510969.4976397165,6651146.570659755,67.572302070731],[510978.95693450235,6651135.925617528,67.38911276194607],[510969.4984647809,6651146.5661898,67.776123354731],[510972.7321672704,6651139.204528188,72.09430113396157],[510972.82329123863,6651138.713614472,72.66052105296158],[510978.9535045745,6651135.943790884,67.79992807394606],[510979.05394775525,6651135.411596125,68.33197440094607],[510969.3869890279,6651147.170132206,67.57230206973101],[510969.5053156356,6651146.529073913,68.192702642731],[510970.2905266624,6651142.275034595,72.139765757731],[510971.3028339894,6651146.904799883,65.69803378696157],[510972.73712702125,6651139.1778084375,72.70329629396157],[510978.9427787328,6651136.00062139,68.22104950194606],[510969.5195961883,6651146.451706133,68.61702976273101],[510969.3907935758,6651147.149520299,68.037892756731],[510971.3028339894,6651146.904799883,65.82803378696157],[510970.2149117187,6651142.684693824,72.10202289873101],[510979.0328961355,6651135.523137413,68.81487542094607],[510969.54176868155,6651146.331582173,69.043340113731],[510970.13789043564,6651143.1019721795,72.023348205731],[510970.2855942337,6651142.301757024,72.748760917731],[510969.40269090433,6651147.08506412,68.51516370873101],[510971.1915795272,6651147.504162954,65.69803378696157],[510978.9242037741,6651136.099040172,68.64713863694608],[510969.57210233784,6651146.167243464,69.465148972731],[510979.01100211736,6651135.639142118,69.17658140594607],[510970.06050916837,6651143.521200823,71.90119508373101],[510970.1998972974,6651142.766037483,72.705985676731],[510969.61063371715,6651145.958491934,69.87549851573102],[510969.98394498473,6651143.93600275,71.734080326731],[510969.423294638,6651146.973439231,68.99806472873101],[510972.4127858412,6651140.925137239,72.09430113396157],[510969.657139968,6651145.70653493,70.267278209731],[510969.90946082654,6651144.339535721,71.521802517731],[510969.6969675741,6651145.490760829,70.544760069731],[510978.897400357,6651136.241057161,69.07204514094606],[510969.83834735455,6651144.724807316,71.26558939473101],[510970.1126065097,6651143.238952954,72.61682102473101],[510969.7407069216,6651145.253794081,70.805200742731],[510969.4447228476,6651146.857347578,69.35977071373101],[510978.98376549006,6651135.783454456,69.53433925194607],[510969.78798053163,6651144.99767975,71.046170388731],[510970.0467998406,6651143.595473875,72.51772553073101],[510969.4713799989,6651146.712927077,69.71752855973101],[510969.98131773015,6651143.950236432,72.39010277173101],[510969.5032692763,6651146.540160476,70.06798477473102],[510978.9511830004,6651135.956091666,69.88479546694606],[510978.8622078931,6651136.427523228,69.48901184294606],[510969.91675299057,6651144.300028948,72.23361147973101],[510969.5403003671,6651146.339537064,70.40772980173101],[510971.3028335625,6651146.904802183,67.52683744696157],[510969.8537196195,6651144.641524966,72.04840257773101],[510969.5822863248,6651146.112069658,70.733396911731],[510969.7928359659,6651144.971374456,71.835150242731],[510969.62894459174,6651145.859289073,71.041765719731],[510969.7347063807,6651145.286303224,71.595061795731],[510969.67990239593,6651145.583214878,71.329864070731],[510971.30366312584,6651146.900333062,67.73065873096157],[510978.91334692383,6651136.156564822,70.22454049394607],[510978.8187191755,6651136.657946712,69.89096075994605],[510971.1915795272,6651147.504162954,67.52683744596158],[510971.3105513363,6651146.863224088,68.14723801896157],[510972.10004389565,6651142.609977284,72.09430113396157],[510978.870448271,6651136.383861868,70.55020760394606],[510971.3249097568,6651146.785870722,68.57156513896157],[510971.1954048202,6651147.483554888,67.99242813296156],[510972.02401664515,6651143.019560195,72.05655827496157],[510978.7672991279,6651136.930394076,70.27084156194606],[510971.3472031503,6651146.66576914,68.99787548996159],[510971.94657538686,6651143.436760813,71.97788358196158],[510972.09508457186,6651142.636694735,72.70329629396157],[510971.2073670216,6651147.419110715,68.46969908496158],[510978.8227757418,6651136.636453134,70.85857641194606],[510971.3777022074,6651146.501461048,69.41968434896158],[510971.8687721816,6651143.855911355,71.85573045996156],[510978.7239019306,6651137.160332642,70.53724787694605],[510972.0089203545,6651143.1008887,72.66052105296158],[510971.41644368746,6651146.292748408,69.83003389196158],[510971.7917905152,6651144.270636006,71.68861570296157],[510971.2280831015,6651147.307506622,68.95260010496158],[510971.46320352366,6651146.04083834,70.22181358596158],[510971.716900216,6651144.6740938,71.47633789396157],[510978.7707102118,6651136.9123205645,71.14667476294606],[510971.50324829837,6651145.825104439,70.49929544596156],[510971.64539898257,6651145.05929362,71.22012477096158],[510971.9211535949,6651143.573716069,72.57135640096159],[510971.54722614406,6651145.588181837,70.75973611896157],[510971.249628153,6651147.191436598,69.31430608996158],[510971.5947575237,6651145.33211522,71.00070576496157],[510978.67675725423,6651137.410127097,70.78495761694606],[510971.85498810076,6651143.9301705705,72.47226090696157],[510971.2764306582,6651147.047043002,69.67206393596157],[510971.78914893494,6651144.284867037,72.34463814796158],[510971.3084938187,6651146.874308587,70.02252015096157],[510978.7147148922,6651137.20900985,71.41187248794606],[510971.7242321422,6651144.634594389,72.18814685596158],[510971.34572682955,6651146.673722549,70.36226517796158],[510978.60882052616,6651137.770087529,71.08240008694607],[510971.6608550681,6651144.976026786,72.00293795396159],[510971.3879417248,6651146.44629752,70.68793228796157],[510971.5996394333,6651145.305814825,71.78968561896157],[510971.434854406,6651146.193564028,70.99630109596157],[510971.5411928839,6651145.620684923,71.54959717196157],[510971.48609006853,6651145.917541265,71.28439944696157],[510978.65532168,6651137.523702754,71.65196093494606],[510978.5361611822,6651138.155070577,71.33861320994606],[510978.59311453137,6651137.853305205,71.86521326994608],[510978.4600578797,6651138.558301324,71.55089101894606],[510978.5287109344,6651138.194545461,72.05042217194607],[510978.3818293359,6651138.972792588,71.71800577594607],[510978.4627426798,6651138.544076003,72.20691346394608],[510978.3027659467,6651139.391707253,71.84015889794605],[510978.39583711256,6651138.898572863,72.33453622294607],[510978.224070367,6651139.808673091,71.91883359094606],[510978.32859993115,6651139.254826769,72.43363171694607],[510978.1468116978,6651140.218025507,71.95657644994606],[510978.2394116074,6651139.727388053,72.52279636894608],[510976.69432740635,6651147.913963863,65.56030910294606],[510978.15185178217,6651140.191320795,72.56557160994606],[510976.69432740635,6651147.913963863,65.69030910294606],[510976.5812709479,6651148.512989643,65.56030910294606],[510977.82225722546,6651141.937666283,71.95657644994606],[510976.69432697253,6651147.913966162,67.38911276294606],[510976.69516997243,6651147.909499556,67.59293404694606],[510976.5812709479,6651148.512989643,67.38911276194607],[510976.7021697517,6651147.872411465,68.00951333494606],[510977.50444977684,6651143.621558183,71.95657644994606],[510976.7167607365,6651147.7951016305,68.43384045494606],[510976.58515819954,6651148.492393172,67.85470344894605],[510977.42719110777,6651144.030910599,71.91883359094606],[510976.7394152177,6651147.675067636,68.86015080594608],[510977.348495528,6651144.447876438,71.84015889794605],[510977.49941012653,6651143.648260597,72.56557160994606],[510976.59731415333,6651148.427985267,68.33197440094607],[510976.7704082701,6651147.510852007,69.28195966494606],[510977.26943213877,6651144.866791102,71.71800577594607],[510977.4118503014,6651144.112193339,72.52279636894608],[510976.8097772486,6651147.302256822,69.69230920794607],[510976.6183657731,6651148.316443979,68.81487542094607],[510977.191203595,6651145.281282366,71.55089101894606],[510976.8572944571,6651147.050488518,70.08408890194607],[510977.11510029243,6651145.684513113,71.33861320994606],[510976.8979878398,6651146.8348760195,70.36157076194606],[510977.0424409485,6651146.069496163,71.08240008694607],[510976.6402597913,6651148.200439272,69.17658140594607],[510976.9426779977,6651146.598086746,70.62201143494606],[510977.3226619775,6651144.584754623,72.43363171694607],[510976.99097924645,6651146.342164231,70.86298108094606],[510976.6674964185,6651148.056126935,69.53433925194607],[510977.25542479614,6651144.941008529,72.33453622294607],[510977.1885192289,6651145.295505389,72.20691346394608],[510976.7000789083,6651147.883489726,69.88479546694606],[510977.1225509743,6651145.64503593,72.05042217194607],[510976.7379149848,6651147.683016569,70.22454049394607],[510977.05814737733,6651145.986276187,71.86521326994608],[510976.78081363766,6651147.455719523,70.55020760394606],[510976.9959402286,6651146.315878637,71.65196093494606],[510976.8284861669,6651147.203128258,70.85857641194606],[510976.93654701643,6651146.63057154,71.41187248794606],[510976.880551697,6651146.927260826,71.14667476294606],[510990.5572465645,6651137.532530463,65.25932373606133],[510990.44037750276,6651138.130824095,65.25932373606133],[510990.44037750276,6651138.130824095,65.38932373606133],[510991.7160832611,6651137.75928124,65.22823515455318],[510990.5572465645,6651137.532530463,67.08812739506133],[510991.5988295832,6651138.357499615,65.22823515455318],[510990.55322822306,6651137.5531017585,67.55371808206134],[510990.44037750276,6651138.130824095,67.08812739506133],[510991.5988295832,6651138.357499615,65.35823515455317],[510990.4368319075,6651138.148975237,67.49894270706135],[510990.5406623339,6651137.617430944,68.03098903406134],[510990.4257443581,6651138.205736283,67.92006413506132],[510990.5189007903,6651137.728835903,68.51389005406133],[510991.7160832611,6651137.75928124,67.05703881355318],[510990.40654299606,6651138.304034777,68.34615327006134],[510990.4962684401,6651137.844698825,68.87559603906134],[510991.7120516954,6651137.77984995,67.52262950055317],[510991.5988295832,6651138.357499615,67.05703881355318],[510990.3788356872,6651138.445878189,68.77105977406133],[510990.468113312,6651137.988834779,69.23335388506133],[510991.59527231933,6651138.375648474,67.46785412555317],[510991.69944445184,6651137.844171043,67.99990045255318],[510990.4344320428,6651138.161260985,69.58381010006133],[510990.3424564278,6651138.632116351,69.18802647606132],[510991.5841482809,6651138.43240238,67.88897555355317],[510991.67761129106,6651137.955561988,68.48280147255318],[510990.3953200202,6651138.361489118,69.92355512706133],[510990.29750114004,6651138.862258202,69.58997539306134],[510991.5648837271,6651138.530688509,68.31506468855319],[510991.6549044578,6651138.071410335,68.84450745755318],[510990.350974696,6651138.588508354,70.24922223706135],[510991.53708523355,6651138.672514077,68.73997119255317],[510991.626656671,6651138.215528159,69.20226530355318],[510990.24434705405,6651139.134372573,69.96985619506133],[510990.301694506,6651138.840790896,70.55759104506133],[510990.199486373,6651139.3640301,70.23626251006132],[510991.5928645568,6651138.387932676,69.55272151855317],[510991.50058624987,6651138.858728814,69.15693789455317],[510990.24787316984,6651139.116321152,70.84568939606133],[510990.15075183654,6651139.61351925,70.48397225006133],[510991.5536238165,6651138.588135622,69.89246654555318],[510991.45548301435,6651139.088841717,69.55888681155317],[510990.18998952,6651139.4126478145,71.11088712106134],[510991.5091325518,6651138.815126302,70.21813365555317],[510990.08052407793,6651139.973039726,70.78141472006135],[510995.6581277741,6651138.536419273,65.12148315381185],[510991.40215399803,6651139.360921859,69.93876761355317],[510990.1285933904,6651139.726956091,71.35097556806134],[510991.4596901806,6651139.067377109,70.52650246355317],[510995.53956573736,6651139.134379716,65.12148315381185],[510990.00541444274,6651140.357552237,71.03762784306134],[510991.35714568046,6651139.590550498,70.20517392855317],[510995.53956573736,6651139.134379716,65.25148315381185],[510990.06428842974,6651140.056155692,71.56422790306134],[510991.40569171833,6651139.342872708,70.81460081455317],[510991.30825075856,6651139.840008264,70.45288366855317],[510989.92674470827,6651140.760290142,71.24990565206133],[510989.99771295016,6651140.396978874,71.74943680506134],[510991.3476175734,6651139.639162097,71.07979853955317],[510989.8458780631,6651141.174274803,71.41702040906135],[510991.23779188044,6651140.199483517,70.75032613855318],[510989.92952004797,6651140.746082208,71.90592809706133],[510995.6581277741,6651138.536419273,66.95028681281185],[510991.286019389,6651139.953430836,71.31988698655317],[510989.764148419,6651141.592677458,71.53917353106132],[510989.86035822396,6651141.100145792,72.03355085606132],[510995.65405122266,6651138.556979113,67.41587749981184],[510991.1624350594,6651140.583947662,71.00653926155317],[510995.53956573736,6651139.134379716,66.95028681281185],[510991.2215028007,6651140.282589028,71.5331393215532],[510989.682798988,6651142.009133668,71.61784822406133],[510989.7908536029,6651141.455964274,72.13264635006134],[510995.5359687803,6651139.152520751,67.36110212481185],[510995.64130330295,6651138.621272473,67.89314845181185],[510991.08350642276,6651140.986634906,71.21881707055317],[510989.60293492454,6651142.417985761,71.65559108306132],[510991.1547082211,6651140.623369339,71.71834822355318],[510989.69865758106,6651141.9279479785,72.22181100206133],[510995.52472061577,6651139.209250186,67.78222355281184],[510995.6192265198,6651138.732615391,68.37604947181185],[510991.00237364526,6651141.400567493,71.38593182755318],[510988.1014685009,6651150.104517902,65.25932373606133],[510991.08629089594,6651140.97242876,71.87483951555319],[510988.1014685009,6651150.104517902,65.38932373606133],[510989.6081449755,6651142.391313687,72.26458624306133],[510995.5052411012,6651139.307493936,68.20831268781185],[510995.5962663155,6651138.848413788,68.73775545681185],[510990.9203750289,6651141.818917517,71.50808494955317],[510991.01690146036,6651141.326447805,72.00246227455318],[510987.9845994391,6651150.702811534,65.25932373606133],[510995.4771324219,6651139.449258356,68.63321919181186],[510995.5677033298,6651138.992469475,69.09551330281185],[510990.83875787683,6651142.235321341,71.58675964255318],[510990.94716809964,6651141.68222153,72.10155776855318],[510989.26743550063,6651144.135524738,71.65559108306132],[510990.7586309806,6651142.644122006,71.62450250155317],[510995.533534151,6651139.164799656,69.44596951781185],[510995.4402261694,6651139.635392802,69.05018589381184],[510990.8546686605,6651142.154145865,72.19072242055319],[510989.25222322944,6651150.329687274,65.22823515455318],[510988.1014680524,6651150.104520198,67.08812739606134],[510989.25222322944,6651150.329687274,65.35823515455317],[510990.763858178,6651142.617453287,72.23349766155317],[510995.4938555483,6651139.364916282,69.78571454481185],[510988.1023394807,6651150.100059051,67.29194868006132],[510995.39461965574,6651139.865406488,69.45213481081184],[510989.13496955147,6651150.927905647,65.22823515455318],[510987.9845994391,6651150.702811534,67.08812739506133],[510988.1095753136,6651150.06301629,67.70852796806133],[510995.4488678341,6651139.591809091,70.11138165481185],[510988.93891063053,6651145.817358532,71.65559108306132],[510995.34069557517,6651140.13736932,69.83201561281184],[510988.1246583503,6651149.985800946,68.13285508806135],[510987.9886177805,6651150.6822402375,67.55371808206134],[510990.4220274278,6651144.361444937,71.62450250155317],[510988.859046567,6651146.226210627,71.61784822406133],[510995.3988737671,6651139.843951136,70.41975046281185],[510988.14807680855,6651149.865913662,68.55916543906133],[510995.29518503847,6651140.36689895,70.09842192781186],[510988.77769713604,6651146.642666837,71.53917353106132],[510988.93370102806,6651145.844028312,72.26458624306133],[510988.00118366966,6651150.617911053,68.03098903406134],[510988.18011503987,6651149.701898743,68.98097429806133],[510988.69596749195,6651147.061069489,71.41702040906135],[510995.3442727705,6651140.11932795,70.70784881381185],[510989.25222277956,6651150.329689568,67.05703881455317],[510988.8431884226,6651146.307394018,72.22181100206133],[510988.2208116584,6651149.493558507,69.39132384106134],[510995.2457445295,6651140.61624916,70.34613166781185],[510988.02294521325,6651150.506506095,68.51389005406133],[510988.6151008467,6651147.47505415,71.24990565206133],[510988.26993129,6651149.242097922,69.78310353506133],[510989.2530970758,6651150.325228983,67.26086009855317],[510988.5364311122,6651147.877792056,71.03762784306134],[510988.31199697574,6651149.026748953,70.06058539506134],[510988.0455775635,6651150.390643174,68.87559603906134],[510988.4613214771,6651148.262304568,70.78141472006135],[510988.35819422,6651148.790249091,70.32102606806134],[510988.4081243318,6651148.5346393725,70.56199571406133],[510988.7509924007,6651146.779377723,72.13264635006134],[510995.2855506133,6651140.41548959,70.97304653881184],[510989.13496955147,6651150.927905647,67.05703881355318],[510988.0737326916,6651150.246507218,69.23335388506133],[510988.68148777966,6651147.135196205,72.03355085606132],[510989.2603567217,6651150.288190882,67.67743938655317],[510995.17449944577,6651140.975569419,70.64357413781185],[510988.1074139608,6651150.074081012,69.58381010006133],[510988.6123259557,6651147.489259789,71.90592809706133],[510990.09242138197,6651146.043067177,71.62450250155317],[510988.14652598335,6651149.873852879,69.92355512706133],[510988.5441330535,6651147.838363124,71.74943680506134],[510989.2754893967,6651150.210985251,68.10176650655318],[510989.13900111726,6651150.907336939,67.52262950055317],[510995.2232650942,6651140.729622828,71.21313498581185],[510988.19087130757,6651149.646833643,70.24922223706135],[510988.4775575738,6651148.179186306,71.56422790306134],[510990.01229448576,6651146.451867842,71.58675964255318],[510988.2401514976,6651149.394551103,70.55759104506133],[510988.4132526133,6651148.508385905,71.35097556806134],[510988.29397283384,6651149.119020846,70.84568939606133],[510988.35185648367,6651148.822694182,71.11088712106134],[510995.09830176615,6651141.359867796,70.89978726081185],[510989.2989849252,6651150.091113046,68.52807685755319],[510989.9306773337,6651146.868271667,71.50808494955317],[510990.0871946348,6651146.069733602,72.23349766155317],[510989.1516083608,6651150.843015845,67.99990045255318],[510995.1580286066,6651141.058639097,71.42638732081187],[510989.33112859423,6651149.927118758,68.94988571655317],[510989.8486787173,6651147.286621691,71.38593182755318],[510989.3719591455,6651149.71880473,69.36023525955318],[510989.99638415215,6651146.533041022,72.19072242055319],[510989.1734415216,6651150.7316249,68.48280147255318],[510995.0184924154,6651141.762381416,71.11206506981185],[510989.76754593983,6651147.700554278,71.21881707055317],[510989.4212404298,6651149.467375776,69.75201495355319],[510989.6886173032,6651148.103241523,71.00653926155317],[510995.090488709,6651141.399272475,71.61159622281185],[510989.4634445538,6651149.252053895,70.02949681355317],[510989.1961483549,6651150.615776552,68.84450745755318],[510989.61326048215,6651148.487705667,70.75032613855318],[510989.5097938332,6651149.0155837815,70.28993748655317],[510989.55988826504,6651148.760006216,70.53090713255317],[510989.903884713,6651147.0049653575,72.10155776855318],[510989.22439614165,6651150.471658727,69.20226530355318],[510989.83415135223,6651147.360739081,72.00246227455318],[510994.93645432906,6651142.176135529,71.27917982681186],[510995.0213079587,6651141.748181393,71.76808751481185],[510989.25818825583,6651150.299254212,69.55272151855317],[510989.76476191665,6651147.714758128,71.87483951555319],[510989.2974289962,6651150.099051264,69.89246654555318],[510989.69634459156,6651148.0638175495,71.71834822355318],[510989.3419202609,6651149.872060586,70.21813365555317],[510989.62955001194,6651148.40459786,71.5331393215532],[510994.85354074254,6651142.594305174,71.40133294881184],[510989.3913626321,6651149.619809779,70.52650246355317],[510989.56503342366,6651148.7337560505,71.31988698655317],[510989.4453610943,6651149.344314179,70.81460081455317],[510989.5034352393,6651149.04802479,71.07979853955317],[510994.9511442508,6651142.102047801,71.89571027381184],[510994.77101287694,6651143.01052946,71.48000764181185],[510994.88063278,6651142.457668127,71.99480576781185],[510994.68999189587,6651143.419153865,71.51775050081184],[510994.7871011988,6651142.929388984,72.08397041981186],[510993.1667751042,6651151.101405384,65.12148315381185],[510993.1667751042,6651151.101405384,65.25148315381185],[510994.69527742016,6651143.3924966445,72.12674566081185],[510993.04821306746,6651151.699365826,65.12148315381185],[510994.3496323994,6651145.135736346,71.51775050081184],[510993.16677464935,6651151.101407679,66.95028681381184],[510993.16765870125,6651151.096949016,67.15410809781184],[510993.04821306746,6651151.699365826,66.95028681281185],[510993.17499935295,6651151.059926884,67.57068738581185],[510994.01634849055,6651146.816633529,71.51775050081184],[510993.1903008838,6651150.982754541,67.99501450581185],[510993.0522896189,6651151.6788059855,67.41587749981184],[510993.93532750953,6651147.225257933,71.48000764181185],[510993.2140585838,6651150.862934021,68.42132485681186],[510993.85279964394,6651147.641482219,71.40133294881184],[510993.06503753865,6651151.614512626,67.89314845181185],[510994.0110634214,6651146.843288455,72.12674566081185],[510993.2465609235,6651150.699010443,68.84313371581186],[510993.7698860573,6651148.059651865,71.27917982681186],[510993.28784707683,6651150.490786231,69.25348325881185],[510993.91923964274,6651147.306396114,72.08397041981186],[510993.0871143217,6651151.503169709,68.37604947181185],[510993.6878479711,6651148.473405978,71.11206506981185],[510993.3376782594,6651150.239465684,69.64526295281186],[510993.6080386203,6651148.875919599,70.89978726081185],[510993.38035331224,6651150.024236643,69.92274481281184],[510993.11007452605,6651151.387371312,68.73775545681185],[510993.5318409407,6651149.260217975,70.64357413781185],[510993.4272197735,6651149.787868488,70.18318548581185],[510993.47787317715,6651149.532401118,70.42415513181184],[510993.82570806146,6651147.778116973,71.99480576781185],[510993.13863751176,6651151.243315625,69.09551330281185],[510993.75519659073,6651148.133737299,71.89571027381184],[510993.1728066905,6651151.070985444,69.44596951781185],[510993.6850328828,6651148.487603704,71.76808751481185],[510993.2124852932,6651150.870868818,69.78571454481185],[510993.61585213256,6651148.836512624,71.61159622281185],[510993.2574730075,6651150.6439760085,70.11138165481185],[510993.5483122349,6651149.177146002,71.42638732081187],[510993.30746707454,6651150.391833963,70.41975046281185],[510993.4830757473,6651149.506162272,71.21313498581185],[510993.36206807103,6651150.116457149,70.70784881381185],[510993.4207902283,6651149.820295509,70.97304653881184],[511007.4429070083,6651140.913185345,64.79313440574904],[511007.3204336206,6651141.510356942,64.79313440574904],[511007.3204336206,6651141.510356942,64.92313440574902],[511007.4429070083,6651140.913185345,66.62193806474903],[511007.4386959718,6651140.933718062,67.08752875174902],[511007.3204336206,6651141.510356942,66.62193806474903],[511007.31671800016,6651141.528474045,67.03275337674903],[511007.4255274994,6651140.997926604,67.56479970374905],[511007.30509875977,6651141.585128642,67.45387480474903],[511007.4027224051,6651141.109122635,68.04770072374903],[511007.2849766177,6651141.683242787,67.87996393974902],[511007.3790047457,6651141.224768269,68.40940670874903],[511007.25594063563,6651141.824820186,68.30487044374902],[511007.3494994697,6651141.368633913,68.76716455474903],[511007.3142030527,6651141.540736752,69.11762076974902],[511007.21781684924,6651142.010709079,68.72183714574903],[511007.2732154565,6651141.740589378,69.45736579674903],[511007.17070578074,6651142.240419325,69.12378606274902],[511007.22674360155,6651141.967182864,69.78303290674903],[511007.11500274955,6651142.512023376,69.50366686474902],[511011.56646255543,6651141.763807931,64.67497358985594],[511007.1751002348,6651142.218992277,70.09140171474903],[511007.06799082446,6651142.741250206,69.77007317974902],[511011.44262056565,6651142.360697208,64.67497358985594],[511011.44262056565,6651142.360697208,64.80497358985593],[511007.1186979563,6651142.494005808,70.37950006574903],[511007.0169192775,6651142.990271466,70.01778291974902],[511012.21603594173,6651141.898703137,64.65620509671923],[511007.05803856044,6651142.789776742,70.64469779074902],[511006.9433238248,6651143.349117701,70.31522538974903],[511012.09197835956,6651142.495547644,64.65620509671923],[511012.09197835956,6651142.495547644,64.78620509671923],[511006.99369824765,6651143.103495568,70.88478623774903],[511011.56646255543,6651141.763807931,66.50377724885594],[511006.8646123905,6651143.7329091,70.57143851274903],[511006.9263096141,6651143.432077792,71.09803857274903],[511011.5622044619,6651141.784330942,66.96936793585593],[511011.44262056565,6651142.360697208,66.50377724885594],[511006.7821701364,6651144.134891714,70.78371632174904],[511006.85654158145,6651143.7722617965,71.28324747474905],[511011.4388634244,6651142.378805746,66.91459256085594],[511012.21603594173,6651141.898703137,66.48500875571924],[511011.54888883594,6651141.848509127,67.44663888785594],[511006.69742562115,6651144.548099992,70.95083107874902],[511006.78507856437,6651144.120710424,71.43973876674903],[511011.42711434263,6651142.435433558,67.33571398885593],[511012.21177043545,6651141.919224608,66.95059944271922],[511012.09197835956,6651142.495547644,66.48500875571924],[511011.5258289018,6651141.959652589,67.92953990785594],[511006.6117767228,6651144.965717978,71.07298420074903],[511006.7126001621,6651144.474110001,71.56736152574902],[511011.40676734183,6651142.533501318,67.76180312385594],[511012.0882146775,6651142.5136548225,66.89582406771923],[511012.19843162876,6651141.983397981,67.42787039471925],[511011.501846205,6651142.075243549,68.29124589285595],[511006.5265262703,6651145.381393168,71.15165889374903],[511006.63976252417,6651144.829261185,71.66645701974903],[511012.0764451422,6651142.5702783875,67.31694549571924],[511011.3774068917,6651142.675011787,68.18670962785593],[511011.4720112167,6651142.21904118,68.64900373885595],[511006.44283241435,6651145.789478505,71.18940175274902],[511012.17533155036,6651142.094533105,67.91077141471924],[511006.5431453445,6651145.300359735,71.75562167174903],[511004.8693648376,6651153.461595396,64.79313440574904],[511012.05606272,6651142.668338792,67.74303463071922],[511004.8693648376,6651153.461595396,64.92313440574902],[511011.43632037326,6651142.3910626555,68.99945995385593],[511012.1513071028,6651142.210115396,68.27247739971924],[511011.33885708393,6651142.860812798,68.60367632985593],[511006.4482923077,6651145.762856451,71.79839691274903],[511004.74689144985,6651154.058766993,64.79313440574904],[511012.02665115724,6651142.809838645,68.16794113471923],[511012.12142017577,6651142.35390224,68.63023524571923],[511011.39487475343,6651142.590820799,69.33920498085594],[511011.2912195638,6651143.090414445,69.00562524685593],[511012.08566719934,6651142.525910812,68.98069146071923],[511011.98803423933,6651142.995625719,68.58490783671924],[511006.09124448866,6651147.503796426,71.18940175274902],[511011.34788358986,6651142.81730716,69.66487209085594],[511011.23489406856,6651143.361890092,69.38550604885593],[511012.0441494281,6651142.725653973,69.32043648771923],[511011.2956631246,6651143.068997527,69.97324089885595],[511011.94031378865,6651143.225210145,68.98685675371922],[511004.8693643676,6651153.461597687,66.62193806574902],[511011.18735679984,6651143.5910085505,69.65191236385593],[511004.8702775843,6651153.457144906,66.82575934974902],[511011.9970764592,6651142.952123346,69.64610359771923],[511011.23863056814,6651143.343881041,70.26133924985594],[511011.13571454416,6651143.839912082,69.89962210385593],[511004.74689144985,6651154.058766993,66.62193806474903],[511011.8838902381,6651143.496665428,69.36673755571923],[511004.87786040345,6651153.420171615,67.24233863774903],[511005.74696557363,6651149.182476124,71.18940175274902],[511011.94476508506,6651143.203794833,69.95447240571923],[511011.1772933223,6651143.639512146,70.52653697485593],[511004.89366673044,6651153.34310108,67.66666575774903],[511004.75110248633,6651154.038234276,67.08752875174902],[511011.83627021336,6651143.725766703,69.63314387071922],[511011.06129668525,6651144.198588668,70.19706457385594],[511005.66327171767,6651149.590561462,71.15165889374903],[511004.91820819484,6651153.22343863,68.09297610874903],[511004.7642709587,6651153.974025734,67.56479970374905],[511011.8876332425,6651143.478657731,70.24257075671923],[511005.57802126516,6651150.006236652,71.07298420074903],[511011.11223402654,6651143.953082658,70.76662542185593],[511005.74150615046,6651149.209095887,71.79839691274903],[511011.78453805536,6651143.974651565,69.88085361071923],[511004.9517827839,6651153.059731303,68.51478496774902],[511005.49237236683,6651150.423854638,70.95083107874902],[511010.9817056751,6651144.582198625,70.45327769685593],[511004.99443096365,6651152.851781787,68.92513451074903],[511004.787076053,6651153.862829702,68.04770072374903],[511005.6466531136,6651149.6715926025,71.75562167174903],[511005.4076278515,6651150.837062916,70.78371632174904],[511011.82618921663,6651143.77426666,70.50776848171922],[511005.0459060724,6651152.600792789,69.31691420474903],[511011.04409234604,6651144.281509538,70.97987775685594],[511005.32518559747,6651151.239045531,70.57143851274903],[511005.08998897136,6651152.385847684,69.59439606474902],[511004.81079371244,6651153.747184069,68.40940670874903],[511011.70999064477,6651144.333301246,70.17829608071924],[511005.2464741632,6651151.622836931,70.31522538974903],[511005.1384015531,6651152.149791351,69.85483673774903],[511005.190726008,6651151.894661001,70.09580638374902],[511005.5500359339,6651150.142691153,71.66645701974903],[511010.89834215445,6651144.983991197,70.66555550585593],[511004.84029898845,6651153.603318425,68.76716455474903],[511005.4771982961,6651150.497842337,71.56736152574902],[511010.9735446772,6651144.621532718,71.16508665885596],[511011.7610166613,6651144.087813651,70.74785692871923],[511004.8755954053,6651153.431215585,69.11762076974902],[511005.40471989376,6651150.851241913,71.43973876674903],[511004.91658300156,6651153.231362958,69.45736579674903],[511011.6302610773,6651144.716882431,70.43450920371923],[511005.3332568767,6651151.199690541,71.28324747474905],[511004.9630548565,6651153.004769472,69.78303290674903],[511010.81265064556,6651145.397004127,70.83267026285594],[511005.2634888439,6651151.539874546,71.09803857274903],[511005.0146982233,6651152.752960061,70.09140171474903],[511005.1961002104,6651151.868456769,70.88478623774903],[511010.9012830832,6651144.969816613,71.32157795085594],[511005.07110050175,6651152.47794653,70.37950006574903],[511005.13175989775,6651152.182175594,70.64469779074902],[511011.6927563552,6651144.416215898,70.96110926371924],[511011.5467524319,6651145.118644866,70.64678701271924],[511010.72604464745,6651145.814424677,70.95482338485594],[511010.8279947572,6651145.323049115,71.44920070985593],[511011.6220858723,6651144.756213572,71.14631816571925],[511010.6398415475,6651146.229903353,71.03349807785594],[511010.75434318144,6651145.678032395,71.54829620385594],[511011.4609117454,6651145.531626815,70.81390176971922],[511011.54969848035,6651145.104471343,71.30280945771923],[511010.5552124388,6651146.637795762,71.07124093685593],[511010.65664633474,6651146.1489082305,71.63746085585593],[511011.37415497773,6651145.949016056,70.93605489171924],[511011.4762825692,6651145.457677349,71.43043221671923],[511008.964161851,6651154.306285562,64.67497358985594],[511008.964161851,6651154.306285562,64.80497358985593],[511010.5607333447,6651146.611186294,71.68023609685595],[511011.2878018097,6651146.364463567,71.01472958471923],[511011.4025027757,6651145.812634004,71.52952771071924],[511008.84031986113,6651154.903174839,64.67497358985594],[511011.203025373,6651146.772325381,71.05247244371922],[511011.3046358519,6651146.283474518,71.61869236271923],[511009.60920497734,6651154.440239982,64.65620509671923],[511009.60920497734,6651154.440239982,64.78620509671923],[511010.1996956273,6651148.351303216,71.07124093685593],[511011.20855589,6651146.745717907,71.66146760371923],[511009.4851473952,6651155.037084486,64.65620509671923],[511008.9641613757,6651154.306287853,66.50377724985593],[511008.9650847973,6651154.301837178,66.70759853385593],[511010.8468896539,6651148.485704308,71.05247244371922],[511008.84031986113,6651154.903174839,66.50377724885594],[511008.9727523522,6651154.264881366,67.12417782185594],[511009.8515695024,6651150.0291893,71.07124093685593],[511008.9887353098,6651154.187847268,67.54850494185594],[511008.8445779547,6651154.88265183,66.96936793585593],[511009.6092045014,6651154.440242271,66.48500875671922],[511009.76694039366,6651150.437081708,71.03349807785594],[511009.61012953054,6651154.435791931,66.68883004071922],[511009.0135510175,6651154.0682413895,67.97481529285594],[511008.85789358075,6651154.818473643,67.44663888785594],[511009.68073729385,6651150.852560385,70.95482338485594],[511009.84604907193,6651150.055796476,71.68023609685595],[511009.4851473952,6651155.037084486,66.48500875571924],[511009.04750079213,6651153.904611457,68.39662415185593],[511009.6178104335,6651154.398838891,67.10540932871923],[511009.5941312957,6651151.269980936,70.83267026285594],[511009.090625552,6651153.696760253,68.80697369485594],[511008.8809535148,6651154.70733018,67.92953990785594],[511010.4981574877,6651150.163464535,71.05247244371922],[511009.7501360818,6651150.518074541,71.63746085585593],[511009.50843978673,6651151.682993863,70.66555550585593],[511009.63382121536,6651154.321810571,67.52973644871923],[511009.14267587924,6651153.445889912,69.19875338885593],[511009.4894129014,6651155.016563016,66.95059944271922],[511009.4250762661,6651152.084786436,70.45327769685593],[511009.18725139095,6651153.231046424,69.47623524885593],[511008.9049362116,6651154.59173922,68.29124589285595],[511009.2362049682,6651152.995101691,69.73667592185593],[511009.34548525605,6651152.468396394,70.19706457385594],[511009.2891141325,6651152.740091956,69.97764556785593],[511010.413381051,6651150.571326349,71.01472958471923],[511009.65243923524,6651150.988950375,71.54829620385594],[511009.6586801239,6651154.202213665,67.95604679971923],[511008.93477119994,6651154.44794159,68.64900373885595],[511009.5787876594,6651151.343933655,71.44920070985593],[511009.50275170815,6651154.952389644,67.42787039471925],[511010.327027883,6651150.986773862,70.93605489171924],[511010.4926274468,6651150.190069717,71.66146760371923],[511008.9704620434,6651154.275920116,68.99945995385593],[511009.6926890006,6651154.038596005,68.37785565871923],[511009.5054993335,6651151.697166157,71.32157795085594],[511009.0119076632,6651154.07616197,69.33920498085594],[511010.2402711152,6651151.404163103,70.81390176971922],[511009.4332377394,6651152.045450052,71.16508665885596],[511009.735888835,6651153.830760391,68.78820520171924],[511009.52585178654,6651154.841254518,67.91077141471924],[511009.0588988267,6651153.84967561,69.66487209085594],[511009.36269007064,6651152.385473231,70.97987775685594],[511010.39654748497,6651150.652313107,71.61869236271923],[511009.1111192921,6651153.597985243,69.97324089885595],[511010.1544304288,6651151.817145051,70.64678701271924],[511009.29454839,6651152.7139001135,70.76662542185593],[511009.1681518484,6651153.323101728,70.26133924985594],[511009.2294890943,6651153.027470623,70.52653697485593],[511009.7880297749,6651153.579908868,69.17998489571923],[511010.0709217833,6651152.218907485,70.43450920371923],[511009.8326828866,6651153.365081496,69.45746675571922],[511009.5498762341,6651154.725672228,68.27247739971924],[511009.8817216855,6651153.12915446,69.71790742871923],[511009.9911922158,6651152.60248867,70.17829608071924],[511009.9347229577,6651152.874163853,69.95887707471923],[511010.29868056107,6651151.12315362,71.52952771071924],[511009.5797631612,6651154.581885384,68.63023524571923],[511010.22490076773,6651151.478110275,71.43043221671923],[511009.6155161376,6651154.409876812,68.98069146071923],[511010.15148485656,6651151.831316282,71.30280945771923],[511009.65703390876,6651154.210133651,69.32043648771923],[511010.0790974647,6651152.179574053,71.14631816571925],[511009.7041068776,6651153.98366428,69.64610359771923],[511010.0084269817,6651152.519571727,70.96110926371924],[511009.75641825184,6651153.731992792,69.95447240571923],[511009.9401666756,6651152.847973974,70.74785692871923],[511009.81355009443,6651153.457129896,70.24257075671923],[511009.87499412015,6651153.161520965,70.50776848171922],[511024.2961290296,6651144.452007684,64.29946579601143],[511024.1680620823,6651145.048004751,64.29946579601143],[511024.1680620823,6651145.048004751,64.42946579601143],[511024.2961290296,6651144.452007684,66.12826945501143],[511024.2917256682,6651144.472500016,66.59386014201144],[511024.1680620823,6651145.048004751,66.12826945501143],[511024.16417676344,6651145.066086221,66.53908476701145],[511024.27795577014,6651144.536582272,67.07113109401143],[511024.1520268534,6651145.122629388,66.96020619501142],[511024.25410913,6651144.6475596,67.55403211401143],[511024.1309857002,6651145.220550559,67.38629533001144],[511024.22930824646,6651144.762977779,67.91573809901143],[511024.10062359745,6651145.361849502,67.81120183401143],[511024.19845541625,6651144.906560465,68.27349594501143],[511024.1615469543,6651145.078324808,68.62395216001143],[511024.06075863546,6651145.547372784,68.22816853601142],[511024.1186873876,6651145.2777843615,68.96369718701143],[511024.01149592747,6651145.776631232,68.63011745301144],[511024.07009308715,6651145.503932178,69.28936429701145],[511023.9532488478,6651146.047701085,69.00999825501142],[511024.01609108347,6651145.755246326,69.59773310501143],[511023.90408981126,6651146.276477067,69.27640457001142],[511028.7423143146,6651145.413158831,64.16447493163774],[511023.95711282076,6651146.029718955,69.88583145601143],[511023.8506857434,6651146.525008547,69.52411431001143],[511028.6127716849,6651146.008836894,64.16447493163774],[511028.6127716849,6651146.008836894,64.29447493163774],[511023.8936830112,6651146.324908161,70.15102918101144],[511023.77372906613,6651146.883148995,69.82155678001145],[511023.8264041712,6651146.638009957,70.39111762801144],[511023.69142275205,6651147.266185545,70.07776990301144],[511023.7559377887,6651146.965945918,70.60436996301144],[511028.7423143146,6651145.413158831,65.99327859063776],[511023.60521522554,6651147.6673775315,70.29004771201143],[511023.6829833359,6651147.305460841,70.78957886501144],[511028.7378602144,6651145.433640195,66.45886927763773],[511028.6127716849,6651146.008836894,65.99327859063776],[511023.51660028985,6651148.079773102,70.45716246901142],[511023.60825648624,6651147.653224135,70.94607015701143],[511028.6088415965,6651146.026908685,66.40409390263774],[511028.72393164935,6651145.497688151,66.93614022963774],[511023.4270396664,6651148.496569707,70.57931559101145],[511023.53246787685,6651148.0059286365,71.07369291601142],[511028.5965516861,6651146.083421589,66.82521533063773],[511023.33789568645,6651148.91142734,70.65799028401143],[511028.69981023046,6651145.608606079,67.41904124963776],[511023.45630362513,6651148.3603813,71.17278841001144],[511028.5752680812,6651146.181290348,67.25130446563773],[511023.2503793955,6651149.318710045,70.69573314301142],[511028.6747235727,6651145.723962481,67.78074723463774],[511023.35527378094,6651148.830553286,71.26195306201143],[511021.6050489842,6651156.97573725,64.29946579601143],[511031.37148492254,6651145.986944344,64.08371371663779],[511021.6050489842,6651156.97573725,64.42946579601143],[511028.54455612367,6651146.322513661,67.67621096963775],[511028.64351523336,6651145.867468315,68.13850508063774],[511023.256088651,6651149.292140353,71.30472830301143],[511021.4769820368,6651157.5717343185,64.29946579601143],[511031.2410696749,6651146.582431968,64.08371371663779],[511031.2410696749,6651146.582431968,64.21371371663778],[511028.60618148465,6651146.039140723,68.48896129563774],[511028.504231808,6651146.507937643,68.09317767163773],[511022.88273387484,6651151.029656208,70.69573314301142],[511028.56282805826,6651146.238493515,68.82870632263776],[511028.4544014587,6651146.7370733805,68.49512658863773],[511021.60504849284,6651156.975739538,66.12826945601144],[511031.37148492254,6651145.986944344,65.91251737563779],[511028.5136738182,6651146.464520288,69.15437343263774],[511021.60600341763,6651156.971295516,66.33209074001142],[511028.3954832129,6651147.007998145,68.87500739063773],[511031.36700081883,6651146.007419161,66.37810806263779],[511021.4769820368,6651157.5717343185,66.12826945501143],[511031.2410696749,6651146.582431968,65.91251737563779],[511028.45904956345,6651146.715699921,69.46274224063774],[511021.6139325565,6651156.9343949435,66.74867002801143],[511028.34575772955,6651147.236651676,69.14141370563775],[511022.5227311794,6651152.705034244,70.69573314301142],[511021.6304607842,6651156.857475993,67.17299714801145],[511031.2371131129,6651146.600497983,66.3233326876378],[511021.48138539825,6651157.551241985,66.59386014201144],[511031.35297842906,6651146.071446641,66.85537901463779],[511028.39939170936,6651146.9900256395,69.75084059163775],[511028.29173830024,6651147.48505013,69.38912344563774],[511022.4352148884,6651153.11231695,70.65799028401143],[511021.65612309735,6651156.738048899,67.59930749901143],[511021.49515529623,6651157.487159729,67.07113109401143],[511031.224740416,6651146.656992819,66.74445411563778],[511022.3460709085,6651153.527174582,70.57931559101145],[511022.5170224155,6651152.731601651,71.30472830301143],[511021.6912310927,6651156.574663554,68.02111635801143],[511031.3286945249,6651146.182329107,67.33828003463779],[511028.33523101447,6651147.285056848,70.01603831663773],[511022.256510285,6651153.943971187,70.45716246901142],[511028.2138948712,6651147.842998885,69.68656591563774],[511021.5190019365,6651157.376182402,67.55403211401143],[511021.73582708446,6651156.3671230385,68.43146590101144],[511022.41783728544,6651153.193188718,71.26195306201143],[511022.16789534927,6651154.356366758,70.29004771201143],[511031.2033134416,6651146.75483029,67.17054325063779],[511021.78965314565,6651156.116627689,68.82324559501143],[511021.54380282003,6651157.260764223,67.91573809901143],[511022.08168782276,6651154.757558744,70.07776990301144],[511021.8357493826,6651155.9021053435,69.10072745501142],[511031.3034388796,6651146.29764863,67.6999860196378],[511021.886373046,6651155.666513291,69.36116812801144],[511021.9993815087,6651155.140595295,69.82155678001145],[511021.94108724425,6651155.411884738,69.60213777401142],[511028.2671769378,6651147.597991058,70.25612676363774],[511022.31680744136,6651153.663360701,71.17278841001144],[511021.5746556502,6651157.117181537,68.27349594501143],[511028.1306401627,6651148.225830417,69.94277903863774],[511022.24064318964,6651154.017813366,71.07369291601142],[511021.6115641121,6651156.945417193,68.62395216001143],[511031.17239460396,6651146.896008453,67.59544975463778],[511031.27202031645,6651146.441108585,68.05774386563779],[511022.16485458025,6651154.370517868,70.94607015701143],[511028.19589858945,6651147.925751491,70.46937909863775],[511021.6544236788,6651156.74595764,68.96369718701143],[511022.0901277305,6651154.71828116,70.78957886501144],[511021.70301797934,6651156.5198098235,69.28936429701145],[511022.0171732778,6651155.057796085,70.60436996301144],[511021.757019983,6651156.268495674,69.59773310501143],[511021.9467068953,6651155.385732044,70.39111762801144],[511028.0434392891,6651148.626807668,70.15505684763774],[511021.81599824573,6651155.994023046,69.88583145601143],[511021.8794280553,6651155.698833841,70.15102918101144],[511031.2344350823,6651146.61272611,68.40820008063778],[511031.1317986578,6651147.081373155,68.01241645663778],[511028.12210350134,6651148.265084692,70.65458800063774],[511027.9538032663,6651149.038982505,70.32217160463773],[511031.1907896209,6651146.812015168,68.74794510763779],[511028.04651559336,6651148.612661846,70.81107929263774],[511031.08163264394,6651147.310435638,68.41436537363779],[511027.86321065895,6651149.455556022,70.44432472663775],[511027.9698536914,6651148.965177565,70.93870205163773],[511031.1413042708,6651147.037969681,69.0736122176378],[511031.02231751644,6651147.581273788,68.79424617563778],[511027.773039496,6651149.870191604,70.52299941963776],[511027.89281181875,6651149.319440509,71.03779754563776],[511031.08631205914,6651147.289069012,69.38198102563778],[511030.9722570751,6651147.809854217,69.06065249063778],[511027.6845147774,6651150.277256313,70.56074227863775],[511027.7906178337,6651149.789360836,71.12696219763774],[511026.0202256484,6651157.93018513,64.16447493163774],[511026.0202256484,6651157.93018513,64.29447493163774],[511031.0262523412,6651147.563307027,69.67007937663779],[511030.91787376313,6651148.058173259,69.30836223063778],[511027.6902898191,6651150.250700841,71.16973743863774],[511025.8906830187,6651158.525863193,64.16447493163774],[511030.96165945055,6651147.858243913,69.9352771016378],[511030.8395059694,6651148.416007577,69.6058047006378],[511030.8931469518,6651148.171078078,70.17536554863779],[511027.31263297226,6651151.9872867,70.56074227863775],[511030.75569044525,6651148.798716717,69.8620178236378],[511030.8213884621,6651148.498733727,70.38861788363779],[511026.0202251514,6651157.930187415,65.99327859163773],[511030.66790217394,6651149.199565775,70.07429563263779],[511026.02119107946,6651157.925745773,66.19709987563775],[511030.74709627964,6651148.837958442,70.57382678563779],[511025.8906830187,6651158.525863193,65.99327859063776],[511026.02921158384,6651157.888864951,66.61367916363776],[511030.5776623499,6651149.6116088405,70.24141038963779],[511030.67099920067,6651149.185424476,70.73031807763779],[511026.94848205865,6651153.661767998,70.56074227863775],[511026.045930262,6651157.811987172,67.03800628363774],[511025.89513711893,6651158.505381828,66.45886927763773],[511030.48645949777,6651150.028049178,70.36356351163778],[511026.85995734,6651154.068832707,70.52299941963776],[511030.59382089303,6651149.5378274955,70.85794083663778],[511026.07188827544,6651157.692623999,67.46431663463774],[511025.90906568395,6651158.441333872,66.93614022963774],[511026.76978617697,6651154.483468289,70.44432472663775],[511026.9427075141,6651153.688321184,71.16973743863774],[511026.1074008111,6651157.529326106,67.88612549363775],[511030.3956809287,6651150.442552201,70.44223820463779],[511030.51626005507,6651149.891977183,70.95703633063779],[511026.6791935697,6651154.900041806,70.32217160463773],[511025.9331871027,6651158.330415945,67.41904124963776],[511026.15251067106,6651157.321896676,68.29647503663774],[511026.84237949946,6651154.149661188,71.12696219763774],[511026.58955754683,6651155.312216644,70.15505684763774],[511026.20695695595,6651157.071535405,68.68825473063774],[511030.30655989476,6651150.849486773,70.47998106363778],[511025.9582737605,6651158.215059542,67.78074723463774],[511026.50235667324,6651155.713193893,69.94277903863774],[511026.25358434796,6651156.857127881,68.96573659063773],[511026.30479133484,6651156.621661927,69.22617726363774],[511026.4191019648,6651156.096025426,69.68656591563774],[511026.36013599054,6651156.367169662,69.46714690963775],[511030.4133776768,6651150.361747275,71.04620098263779],[511028.6310598739,6651158.499968944,64.08371371663779],[511026.74018551456,6651154.619581515,71.03779754563776],[511025.98948209995,6651158.071553708,68.13850508063774],[511028.6310598739,6651158.499968944,64.21371371663778],[511026.6631436418,6651154.97384446,70.93870205163773],[511026.02681584854,6651157.899881301,68.48896129563774],[511026.5864817398,6651155.326360179,70.81107929263774],[511030.31237383815,6651150.822939789,71.08897622363779],[511026.0701692749,6651157.700528508,68.82870632263776],[511028.50064462627,6651159.095456568,64.08371371663779],[511026.51089383196,6651155.673937333,70.65458800063774],[511026.119323515,6651157.474501736,69.15437343263774],[511026.43709874386,6651156.013270534,70.46937909863775],[511026.17394776986,6651157.223322102,69.46274224063774],[511026.3658203954,6651156.3410309665,70.25612676363774],[511026.2336056238,6651156.948996385,69.75084059163775],[511026.29776631884,6651156.653965177,70.01603831663773],[511029.9321730401,6651152.558970461,70.47998106363778],[511028.6310593735,6651158.499971229,65.9125173766378],[511028.6320318082,6651158.495531006,66.11633866063778],[511028.50064462627,6651159.095456568,65.91251737563779],[511028.6401063399,6651158.458661975,66.53291794863779],[511029.56556915335,6651154.232916427,70.47998106363778],[511028.6569376374,6651158.381808774,66.9572450686378],[511028.5051287299,6651159.074981753,66.37810806263779],[511029.4764481195,6651154.639850996,70.44223820463779],[511028.68307050783,6651158.262483762,67.38355541963779],[511028.51915111975,6651159.010954272,66.85537901463779],[511029.38566955045,6651155.054354019,70.36356351163778],[511029.5597557107,6651154.2594611235,71.08897622363779],[511028.7188222611,6651158.099238075,67.80536427863778],[511029.2944666982,6651155.470794357,70.24141038963779],[511028.5434350239,6651158.900071804,67.33828003463779],[511028.7642359875,6651157.89187496,68.21571382163779],[511029.458751872,6651154.720653636,71.04620098263779],[511029.2042268743,6651155.882837423,70.07429563263779],[511028.81904903054,6651157.641593728,68.60749351563778],[511028.5686906691,6651158.784752281,67.6999860196378],[511029.11643860297,6651156.283686481,69.8620178236378],[511028.8659905114,6651157.42725475,68.8849753756378],[511028.91754243587,6651157.191864077,69.1454160486378],[511029.03262307873,6651156.666395621,69.6058047006378],[511028.97325990116,6651156.937453172,69.38638569463778],[511029.3558694937,6651155.19042373,70.95703633063779],[511028.60010923236,6651158.641292327,68.05774386563779],[511041.115431113,6651148.148686391,63.77831790688605],[511029.2783086558,6651155.544573417,70.85794083663778],[511028.6376944665,6651158.469674803,68.40820008063778],[511029.20113034814,6651155.8969764365,70.73031807763779],[511028.6813399279,6651158.270385743,68.74794510763779],[511029.12503326917,6651156.244442471,70.57382678563779],[511028.73082527803,6651158.044431232,69.0736122176378],[511029.0507410867,6651156.583667185,70.38861788363779],[511028.78581748967,6651157.793331902,69.38198102563778],[511040.981781864,6651148.743456536,63.77831790688605],[511028.978982597,6651156.911322834,70.17536554863779],[511028.8458772076,6651157.519093884,69.67007937663779],[511028.9104700983,6651157.224157,69.9352771016378],[511040.981781864,6651148.743456536,63.90831790688606],[511041.115431113,6651148.148686391,65.60712156588606],[511041.11083581386,6651148.169136538,66.07271225288605],[511040.981781864,6651148.743456536,65.60712156588606],[511040.9777271882,6651148.761500784,66.01793687788606],[511041.09646570054,6651148.233086874,66.54998320488606],[511040.9650476766,6651148.8179275505,66.43905830588605],[511041.07157961087,6651148.343835743,67.03288422488606],[511040.943089362,6651148.915647141,66.86514744088608],[511041.04569768306,6651148.459016323,67.39459020988606],[511040.91140380746,6651149.056655205,67.29005394488605],[511041.013500011,6651148.602303429,67.75234805588606],[511040.97498274845,6651148.773714176,68.10280427088607],[511040.86980117427,6651149.241796569,67.70702064688605],[511040.93025497894,6651148.972763121,68.44254929788606],[511040.8183911574,6651149.470583063,68.10896956388605],[511040.8795425047,6651149.198445389,68.76821640788606],[511040.7576051497,6651149.74109489,68.48885036588607],[511045.23556442215,6651149.079488954,63.646292658619146],[511040.8231866113,6651149.449242182,69.07658521588606],[511040.7063033231,6651149.969399913,68.75525668088605],[511045.10054770694,6651149.673950167,63.646292658619146],[511040.76163754903,6651149.723149778,69.36468356688606],[511045.10054770694,6651149.673950167,63.776292658619155],[511040.6505714288,6651150.217419764,69.00296642088605],[511040.69544290163,6651150.017731307,69.62988129188605],[511040.5702602921,6651150.574822943,69.30040889088606],[511040.62523144885,6651150.33018855,69.86996973888606],[511045.23556442215,6651149.079488954,65.47509631761915],[511040.4843663336,6651150.957070973,69.55662201388606],[511040.5516935118,6651150.65744942,70.08322207388606],[511045.23092210497,6651149.09992848,65.94068700461915],[511045.10054770694,6651149.673950167,65.47509631761915],[511040.39440111286,6651151.357437064,69.76889982288606],[511040.4755590523,6651150.996265417,70.26843097588606],[511045.0964515448,6651149.691985042,65.88591162961914],[511045.21640496026,6651149.163845598,66.41795795661916],[511040.30192354653,6651151.768983676,69.93601457988606],[511040.3975749388,6651151.343312804,70.42492226788607],[511045.0836422994,6651149.7483825,66.30703305761915],[511040.2084590711,6651152.184922261,70.05816770188605],[511045.1912642422,6651149.274536943,66.90085897661915],[511040.3184827848,6651151.695291226,70.55254502688607],[511045.06145931274,6651149.8460513335,66.73312219261915],[511040.11542940006,6651152.598925866,70.13684239488606],[511040.23899861454,6651152.049014212,70.65164052088606],[511045.1651174969,6651149.389657696,67.26256496161915],[511040.02409836726,6651153.005370137,70.17458525388605],[511045.0294495594,6651149.986986156,67.15802869661917],[511038.3070497575,6651160.646634553,63.77831790688605],[511040.1335649872,6651152.518218298,70.74080517288606],[511045.13259038614,6651149.5328703765,67.62032280761915],[511038.3070497575,6651160.646634553,63.90831790688606],[511040.0300564831,6651152.978855141,70.78358041388606],[511038.1734005084,6651161.241404697,63.77831790688605],[511045.09367902455,6651149.704192091,67.97077902261915],[511044.98742125835,6651150.172031355,67.57499539861915],[511045.04849361157,6651149.903137647,68.31052404961915],[511044.93548522686,6651150.400699014,67.97694431561915],[511039.6404275704,6651154.712794139,70.17458525388605],[511044.9972622597,6651150.128702692,68.63619115961914],[511044.87407727167,6651150.6710703345,68.35682511761915],[511038.3070492447,6651160.646636833,65.60712156688605],[511038.3080457937,6651160.64220196,65.81094285088605],[511044.94032974663,6651150.379369217,68.94455996761916],[511044.8222505375,6651150.899256771,68.62323143261916],[511038.1734005084,6651161.241404697,65.60712156588606],[511038.3163205552,6651160.605377353,66.22752213888606],[511044.8781509296,6651150.653134543,69.23265831861914],[511044.76594840817,6651151.147147799,68.87094117261915],[511039.26473274117,6651156.384723234,70.17458525388605],[511038.33356923074,6651160.528616747,66.65184925888606],[511038.17799580767,6651161.2209545495,66.07271225288605],[511039.1734017084,6651156.791167505,70.13684239488606],[511038.3603501369,6651160.409435506,67.07815960988606],[511044.8112789948,6651150.9475630615,69.49785604361915],[511038.19236592087,6651161.157004214,66.54998320488606],[511044.6848155476,6651151.504365336,69.16838364261915],[511039.0803720374,6651157.20517111,70.05816770188605],[511038.3969884523,6651160.2463865075,67.49996846888605],[511039.2587751383,6651156.411235948,70.78358041388606],[511038.9869075619,6651157.621109696,69.93601457988606],[511038.21725201065,6651161.0462553445,67.03288422488606],[511038.4435283358,6651160.039273236,67.91031801188608],[511044.74034915573,6651151.25985801,69.73794449061916],[511039.1552666343,6651156.871872789,70.74080517288606],[511038.89442999556,6651158.032656307,69.76889982288606],[511038.4997006175,6651159.789293559,68.30209770588606],[511038.24313393835,6651160.931074766,67.39459020988606],[511044.59804274334,6651151.886414822,69.42459676561916],[511038.5478061403,6651159.575212829,68.57957956588605],[511038.80446477485,6651158.433022398,69.55662201388606],[511038.60063643527,6651159.340105767,68.84002023888605],[511038.71857081633,6651158.815270428,69.30040889088606],[511038.657735567,6651159.086001392,69.08098988488605],[511039.049833007,6651157.341076876,70.65164052088606],[511038.2753316105,6651160.787787661,67.75234805588606],[511044.66605879663,6651151.586948897,69.95119682561915],[511038.97034883674,6651157.694799862,70.55254502688607],[511038.31384887296,6651160.616376911,68.10280427088607],[511044.5071570207,6651152.286572957,69.63687457461916],[511038.89125668263,6651158.046778286,70.42492226788607],[511038.3585766425,6651160.417327967,68.44254929788606],[511038.8132725692,6651158.393825671,70.26843097588606],[511038.4092891167,6651160.191645699,68.76821640788606],[511044.589145348,6651151.925588907,70.13640572761916],[511038.73713810963,6651158.732641668,70.08322207388606],[511038.4656450101,6651159.940848907,69.07658521588606],[511038.66360017273,6651159.059902538,69.86996973888606],[511038.52719407243,6651159.666941309,69.36468356688606],[511038.5933887199,6651159.3723597815,69.62988129188605],[511051.1287429177,6651150.428177127,63.45445553490367],[511044.4137332466,6651152.697905804,69.80398933161915],[511044.51036332035,6651152.272456031,70.29289701961915],[511050.99177026504,6651151.022190713,63.45445553490367],[511044.3193124656,6651153.113628346,69.92614245361915],[511050.99177026504,6651151.022190713,63.584455534903675],[511044.43046191486,6651152.624251632,70.42051977861915],[511044.225330938,6651153.527416913,70.00481714661915],[511044.35016448214,6651152.977790889,70.51961527261915],[511044.13306542847,6651153.933650071,70.04256000561917],[511042.39844840026,6651161.570945504,63.646292658619146],[511044.2436520839,6651153.446751265,70.60877992461916],[511042.39844840026,6651161.570945504,63.776292658619155],[511051.1287429177,6651150.428177127,65.28325919390367],[511042.263431685,6651162.165406717,63.646292658619146],[511044.1390845064,6651153.907148846,70.65155516561916],[511051.12403334887,6651150.448601262,65.74884988090368],[511050.99177026504,6651151.022190713,65.28325919390367],[511050.9876147634,6651151.040212006,65.69407450590369],[511051.10930589976,6651150.51247025,66.22612083290367],[511043.7454690065,6651155.640187212,70.04256000561917],[511050.9746199552,6651151.0965669975,66.11519593390366],[511042.3984478822,6651161.570947786,65.47509631861915],[511051.08380097727,6651150.623078245,66.70902185290367],[511042.39945462754,6651161.566515215,65.67891760261917],[511050.95211561176,6651151.194162289,66.54128506890368],[511042.263431685,6651162.165406717,65.47509631761915],[511051.0572754539,6651150.738112312,67.07072783790368],[511042.4078140545,6651161.529709735,66.09549689061915],[511050.919642145,6651151.334990987,66.96619157290367],[511042.42523921415,6651161.452989,66.51982401061915],[511042.2680740021,6651162.144967193,65.94068700461915],[511043.36593016033,6651157.311247882,70.04256000561917],[511051.0242771348,6651150.881217155,67.42848568390367],[511043.2736646509,6651157.717481041,70.00481714661915],[511042.452294136,6651161.333869664,66.94613436161914],[511042.2825911469,6651162.081050075,66.41795795661916],[511050.8770049955,6651151.519896845,67.38315827490366],[511050.98480207863,6651151.052409864,67.77894189890367],[511043.17968312325,6651158.131269607,69.92614245361915],[511042.48930732557,6651161.170905354,67.36794322061917],[511043.3599116008,6651157.337746827,70.65155516561916],[511042.307731865,6651161.970358729,66.90085897661915],[511043.0852623423,6651158.546992149,69.80398933161915],[511042.53632339375,6651160.96389966,67.77829276361915],[511043.2553440232,6651157.798144408,70.60877992461916],[511042.99183856824,6651158.958324998,69.63687457461916],[511042.5930704165,6651160.714049825,68.17007245761916],[511050.9389620813,6651151.251205615,68.11868692590367],[511042.33387861017,6651161.855237977,67.26256496161915],[511042.6416681431,6651160.500080292,68.44755431761915],[511042.9009528455,6651159.358483133,69.42459676561916],[511050.82431658584,6651151.74839232,67.78510719190368],[511042.69503898453,6651160.265095349,68.70799499061916],[511042.81418004126,6651159.740532617,69.16838364261915],[511042.75272234064,6651160.011122961,68.94896463661917],[511043.148831625,6651158.267104781,70.51961527261915],[511042.36640572094,6651161.712025296,67.62032280761915],[511043.0685341923,6651158.620644039,70.42051977861915],[511042.40531708254,6651161.54070358,67.97077902261915],[511050.88698855985,6651151.476600811,68.44435403590369],[511042.9886327868,6651158.972439639,70.29289701961915],[511042.4505024956,6651161.341758025,68.31052404961915],[511050.7620190362,6651152.018560051,68.16498799390367],[511042.90985075914,6651159.319306764,70.13640572761916],[511042.50173384737,6651161.116192979,68.63619115961914],[511042.83293731045,6651159.657946776,69.95119682561915],[511042.5586663605,6651160.8655264545,68.94455996761916],[511042.7586469514,6651159.985037661,69.73794449061916],[511042.62084517756,6651160.591761129,69.23265831861914],[511042.68771711236,6651160.297332611,69.49785604361915],[511050.8292312865,6651151.727078585,68.75272284390367],[511050.70944150735,6651152.2465746645,68.43139430890366],[511050.7661517078,6651152.000637765,69.04082119490367],[511050.65232374985,6651152.49427903,68.67910404890367],[511050.69831102394,6651152.294844581,69.30601891990368],[511050.5700155475,6651152.851227584,68.97654651890369],[511050.6263536504,6651152.606904372,69.54610736690368],[511050.4819856976,6651153.232989387,69.23275964190368],[511050.5509870744,6651152.933748959,69.75935970190368],[511050.3897833471,6651153.632846204,69.44503745090367],[511050.47295940906,6651153.272133974,69.94456860390368],[511050.2950061773,6651154.043869319,69.61215220790369],[511050.39303609525,6651153.6187399095,70.10105989590367],[511050.1992175574,6651154.459278824,69.73430532990369],[511050.3119771876,6651153.970270609,70.22868265490368],[511050.103874554,6651154.872755808,69.81298002290367],[511050.2305165157,6651154.323543652,70.32777814890368],[511050.01027242816,6651155.278683073,69.85072288190366],[511048.2505266435,6651162.910227645,63.45445553490367],[511050.1224611116,6651154.792150903,70.41694280090367],[511048.2505266435,6651162.910227645,63.584455534903675],[511048.11355399096,6651163.504241231,63.45445553490367],[511050.0163787022,6651155.252201804,70.45971804190367],[511049.61706103984,6651156.983935197,69.85072288190366],[511048.2505261179,6651162.910229924,65.28325919490368],[511048.2515474477,6651162.905800693,65.48708047890366],[511048.11355399096,6651163.504241231,65.28325919390367],[511048.26002797455,6651162.869022926,65.90365976690367],[511048.277705566,6651162.792359963,66.32798688690369],[511048.11826355965,6651163.483817097,65.74884988090368],[511049.2320239546,6651158.6537375655,69.85072288190366],[511048.30515242246,6651162.673330323,66.75429723790367],[511049.13842182886,6651159.0596648315,69.81298002290367],[511048.13299100887,6651163.4199481085,66.22612083290367],[511049.0430788254,6651159.473141815,69.73430532990369],[511048.3427018085,6651162.510488725,67.17610609690367],[511049.22591820644,6651158.680216554,70.45971804190367],[511048.15849593125,6651163.309340114,66.70902185290367],[511048.9472902055,6651159.888551319,69.61215220790369],[511048.3903989811,6651162.303638905,67.58645563990368],[511049.11983579694,6651159.140267456,70.41694280090367],[511048.8525130357,6651160.299574434,69.44503745090367],[511048.4479680769,6651162.053977206,67.97823533390367],[511048.18502145476,6651163.194306046,67.07072783790368],[511048.497269821,6651161.840168792,68.25571719390368],[511048.7603106852,6651160.699431251,69.23275964190368],[511048.5514138261,6651161.605360792,68.51615786690368],[511048.6722808353,6651161.081193054,68.97654651890369],[511048.60993281956,6651161.351579643,68.75712751290366],[511049.01178039296,6651159.608874706,70.32777814890368],[511048.2180197737,6651163.051201204,67.42848568390367],[511048.93031972094,6651159.96214775,70.22868265490368],[511048.2574948299,6651162.8800084945,67.77894189890367],[511048.8492608134,6651160.313678448,70.10105989590367],[511048.30333482736,6651162.681212743,68.11868692590367],[511048.76933749946,6651160.660284384,69.94456860390368],[511048.3553083488,6651162.455817548,68.44435403590369],[511048.69130983413,6651160.9986694,69.75935970190368],[511048.41306562215,6651162.2053397745,68.75272284390367],[511048.6159432581,6651161.325513987,69.54610736690368],[511048.47614520084,6651161.931780593,69.04082119490367],[511048.5439858846,6651161.637573778,69.30601891990368]],"pointIndex":[31,34,140,135,0,34,46,164,140,0,46,49,169,164,0,49,51,174,169,0,51,54,179,174,0,54,57,185,179,0,57,61,190,185,0,61,68,199,190,0,68,71,203,199,0,71,73,206,203,0,73,75,209,206,0,75,77,211,209,0,77,79,214,211,0,79,81,216,214,0,81,82,217,216,0,82,80,215,217,0,80,78,212,215,0,78,76,210,212,0,76,74,208,210,0,74,72,204,208,0,72,65,196,204,0,65,45,162,196,0,45,42,156,162,0,42,40,150,156,0,40,38,147,150,0,38,36,144,147,0,36,33,139,144,0,33,29,133,139,0,29,27,129,133,0,27,25,125,129,0,25,24,122,125,0,24,21,117,122,0,21,19,114,117,0,19,18,111,114,0,18,16,107,111,0,16,14,103,107,0,14,12,99,103,0,12,10,96,99,0,10,8,93,96,0,8,6,91,93,0,6,4,87,91,0,4,1,83,87,0,1,2,84,83,0,2,3,85,84,0,3,5,90,85,0,5,7,92,90,0,7,9,94,92,0,9,11,97,94,0,11,13,101,97,0,13,15,105,101,0,15,17,110,105,0,17,20,115,110,0,20,22,118,115,0,22,23,121,118,0,23,26,126,121,0,26,28,130,126,0,28,30,134,130,0,30,35,141,134,0,35,37,145,141,0,37,39,149,145,0,39,41,152,149,0,41,48,168,152,0,48,55,182,168,0,55,58,186,182,0,58,60,189,186,0,60,63,193,189,0,63,67,198,193,0,67,70,201,198,0,70,69,200,201,0,69,66,197,200,0,66,64,194,197,0,64,62,191,194,0,62,59,187,191,0,59,56,183,187,0,56,53,178,183,0,53,52,175,178,0,52,50,171,175,0,50,47,166,171,0,47,44,161,166,0,44,43,158,161,0,43,32,138,158,0,32,31,135,138,0,135,140,159,154,0,140,164,184,159,0,164,169,195,184,0,169,174,205,195,0,174,179,218,205,0,179,185,221,218,0,185,190,225,221,0,190,199,232,225,0,199,203,235,232,0,203,206,237,235,0,206,209,239,237,0,209,211,241,239,0,211,214,243,241,0,214,216,245,243,0,216,217,246,245,0,217,215,244,246,0,215,212,242,244,0,212,210,240,242,0,210,208,238,240,0,208,204,236,238,0,204,196,229,236,0,196,162,181,229,0,162,156,176,181,0,156,150,172,176,0,150,147,167,172,0,147,144,163,167,0,144,139,157,163,0,139,133,151,157,0,133,129,146,151,0,129,125,142,146,0,125,122,137,142,0,122,117,131,137,0,117,114,127,131,0,114,111,124,127,0,111,107,120,124,0,107,103,116,120,0,103,99,112,116,0,99,96,108,112,0,96,93,104,108,0,93,91,100,104,0,91,87,95,100,0,87,83,86,95,0,83,84,88,86,0,84,85,89,88,0,85,90,98,89,0,90,92,102,98,0,92,94,106,102,0,94,97,109,106,0,97,101,113,109,0,101,105,119,113,0,105,110,123,119,0,110,115,128,123,0,115,118,132,128,0,118,121,136,132,0,121,126,143,136,0,126,130,148,143,0,130,134,153,148,0,134,141,160,153,0,141,145,165,160,0,145,149,170,165,0,149,152,173,170,0,152,168,192,173,0,168,182,219,192,0,182,186,222,219,0,186,189,224,222,0,189,193,227,224,0,193,198,231,227,0,198,201,234,231,0,201,200,233,234,0,200,197,230,233,0,197,194,228,230,0,194,191,226,228,0,191,187,223,226,0,187,183,220,223,0,183,178,213,220,0,178,175,207,213,0,175,171,202,207,0,171,166,188,202,0,166,161,180,188,0,161,158,177,180,0,158,138,155,177,0,138,135,154,155,0,154,159,314,306,0,159,184,338,314,0,184,195,346,338,0,195,205,350,346,0,205,218,355,350,0,218,221,361,355,0,221,225,369,361,0,225,232,382,369,0,232,235,394,382,0,235,237,398,394,0,237,239,403,398,0,239,241,406,403,0,241,243,410,406,0,243,245,412,410,0,245,246,411,412,0,246,244,409,411,0,244,242,405,409,0,242,240,404,405,0,240,238,399,404,0,238,236,393,399,0,236,229,378,393,0,229,181,333,378,0,181,176,329,333,0,176,172,325,329,0,172,167,321,325,0,167,163,317,321,0,163,157,310,317,0,157,151,303,310,0,151,146,299,303,0,146,142,295,299,0,142,137,292,295,0,137,131,287,292,0,131,127,283,287,0,127,124,280,283,0,124,120,276,280,0,120,116,273,276,0,116,112,269,273,0,112,108,265,269,0,108,104,261,265,0,104,100,256,261,0,100,95,253,256,0,95,86,247,253,0,86,88,249,247,0,88,89,251,249,0,89,98,255,251,0,98,102,259,255,0,102,106,263,259,0,106,109,267,263,0,109,113,271,267,0,113,119,275,271,0,119,123,279,275,0,123,128,284,279,0,128,132,288,284,0,132,136,291,288,0,136,143,296,291,0,143,148,300,296,0,148,153,305,300,0,153,160,313,305,0,160,165,319,313,0,165,170,323,319,0,170,173,327,323,0,173,192,342,327,0,192,219,357,342,0,219,222,362,357,0,222,224,368,362,0,224,227,373,368,0,227,231,379,373,0,231,234,386,379,0,234,233,385,386,0,233,230,380,385,0,230,228,375,380,0,228,226,371,375,0,226,223,367,371,0,223,220,360,367,0,220,213,354,360,0,213,207,351,354,0,207,202,348,351,0,202,188,341,348,0,188,180,335,341,0,180,177,331,335,0,177,155,309,331,0,155,154,306,309,0,306,314,316,308,0,314,338,339,316,0,338,346,347,339,0,346,350,352,347,0,350,355,358,352,0,355,361,365,358,0,361,369,374,365,0,369,382,390,374,0,382,394,396,390,0,394,398,400,396,0,398,403,407,400,0,403,406,414,407,0,406,410,417,414,0,410,412,419,417,0,412,411,418,419,0,411,409,416,418,0,409,405,413,416,0,405,404,408,413,0,404,399,401,408,0,399,393,395,401,0,393,378,387,395,0,378,333,336,387,0,333,329,330,336,0,329,325,326,330,0,325,321,322,326,0,321,317,318,322,0,317,310,312,318,0,310,303,304,312,0,303,299,301,304,0,299,295,297,301,0,295,292,294,297,0,292,287,289,294,0,287,283,285,289,0,283,280,282,285,0,280,276,278,282,0,276,273,274,278,0,273,269,270,274,0,269,265,266,270,0,265,261,262,266,0,261,256,258,262,0,256,253,254,258,0,253,247,248,254,0,247,249,250,248,0,249,251,252,250,0,251,255,257,252,0,255,259,260,257,0,259,263,264,260,0,263,267,268,264,0,267,271,272,268,0,271,275,277,272,0,275,279,281,277,0,279,284,286,281,0,284,288,290,286,0,288,291,293,290,0,291,296,298,293,0,296,300,302,298,0,300,305,307,302,0,305,313,315,307,0,313,319,320,315,0,319,323,324,320,0,323,327,328,324,0,327,342,345,328,0,342,357,359,345,0,357,362,366,359,0,362,368,372,366,0,368,373,381,372,0,373,379,388,381,0,379,386,392,388,0,386,385,391,392,0,385,380,389,391,0,380,375,384,389,0,375,371,376,384,0,371,367,370,376,0,367,360,364,370,0,360,354,356,364,0,354,351,353,356,0,351,348,349,353,0,348,341,344,349,0,341,335,337,344,0,335,331,332,337,0,331,309,311,332,0,309,306,308,311,0,308,316,454,448,0,316,339,472,454,0,339,347,477,472,0,347,352,481,477,0,352,358,486,481,0,358,365,490,486,0,365,374,495,490,0,374,390,503,495,0,390,396,508,503,0,396,400,510,508,0,400,407,514,510,0,407,414,516,514,0,414,417,518,516,0,417,419,520,518,0,419,418,519,520,0,418,416,517,519,0,416,413,515,517,0,413,408,512,515,0,408,401,509,512,0,401,395,507,509,0,395,387,499,507,0,387,336,470,499,0,336,330,466,470,0,330,326,462,466,0,326,322,459,462,0,322,318,455,459,0,318,312,450,455,0,312,304,445,450,0,304,301,441,445,0,301,297,438,441,0,297,294,437,438,0,294,289,434,437,0,289,285,430,434,0,285,282,428,430,0,282,278,426,428,0,278,274,424,426,0,274,270,422,424,0,270,266,420,422,0,266,262,402,420,0,262,258,383,402,0,258,254,363,383,0,254,248,334,363,0,248,250,340,334,0,250,252,343,340,0,252,257,377,343,0,257,260,397,377,0,260,264,415,397,0,264,268,421,415,0,268,272,423,421,0,272,277,425,423,0,277,281,427,425,0,281,286,431,427,0,286,290,435,431,0,290,293,436,435,0,293,298,439,436,0,298,302,442,439,0,302,307,447,442,0,307,315,452,447,0,315,320,457,452,0,320,324,461,457,0,324,328,464,461,0,328,345,476,464,0,345,359,487,476,0,359,366,491,487,0,366,372,494,491,0,372,381,497,494,0,381,388,500,497,0,388,392,505,500,0,392,391,504,505,0,391,389,501,504,0,389,384,498,501,0,384,376,496,498,0,376,370,493,496,0,370,364,488,493,0,364,356,485,488,0,356,353,482,485,0,353,349,478,482,0,349,344,475,478,0,344,337,471,475,0,337,332,467,471,0,332,311,451,467,0,311,308,448,451,0,448,454,527,523,0,454,472,538,527,0,472,477,541,538,0,477,481,543,541,0,481,486,546,543,0,486,490,550,546,0,490,495,553,550,0,495,503,560,553,0,503,508,564,560,0,508,510,566,564,0,510,514,568,566,0,514,516,570,568,0,516,518,572,570,0,518,520,574,572,0,520,519,573,574,0,519,517,571,573,0,517,515,569,571,0,515,512,567,569,0,512,509,565,567,0,509,507,563,565,0,507,499,556,563,0,499,470,536,556,0,470,466,534,536,0,466,462,532,534,0,462,459,530,532,0,459,455,528,530,0,455,450,524,528,0,450,445,521,524,0,445,441,511,521,0,441,438,502,511,0,438,437,492,502,0,437,434,483,492,0,434,430,479,483,0,430,428,474,479,0,428,426,469,474,0,426,424,465,469,0,424,422,460,465,0,422,420,456,460,0,420,402,449,456,0,402,383,444,449,0,383,363,440,444,0,363,334,429,440,0,334,340,432,429,0,340,343,433,432,0,343,377,443,433,0,377,397,446,443,0,397,415,453,446,0,415,421,458,453,0,421,423,463,458,0,423,425,468,463,0,425,427,473,468,0,427,431,480,473,0,431,435,484,480,0,435,436,489,484,0,436,439,506,489,0,439,442,513,506,0,442,447,522,513,0,447,452,526,522,0,452,457,529,526,0,457,461,531,529,0,461,464,533,531,0,464,476,540,533,0,476,487,547,540,0,487,491,549,547,0,491,494,552,549,0,494,497,555,552,0,497,500,558,555,0,500,505,562,558,0,505,504,561,562,0,504,501,559,561,0,501,498,557,559,0,498,496,554,557,0,496,493,551,554,0,493,488,548,551,0,488,485,545,548,0,485,482,544,545,0,482,478,542,544,0,478,475,539,542,0,475,471,537,539,0,471,467,535,537,0,467,451,525,535,0,451,448,523,525,0,523,527,613,609,0,527,538,630,613,0,538,541,635,630,0,541,543,639,635,0,543,546,645,639,0,546,550,648,645,0,550,553,653,648,0,553,560,662,653,0,560,564,666,662,0,564,566,668,666,0,566,568,670,668,0,568,570,674,670,0,570,572,676,674,0,572,574,678,676,0,574,573,677,678,0,573,571,675,677,0,571,569,672,675,0,569,567,669,672,0,567,565,667,669,0,565,563,664,667,0,563,556,656,664,0,556,536,626,656,0,536,534,623,626,0,534,532,620,623,0,532,530,616,620,0,530,528,612,616,0,528,524,608,612,0,524,521,606,608,0,521,511,603,606,0,511,502,599,603,0,502,492,598,599,0,492,483,595,598,0,483,479,593,595,0,479,474,591,593,0,474,469,590,591,0,469,465,588,590,0,465,460,586,588,0,460,456,584,586,0,456,449,582,584,0,449,444,580,582,0,444,440,578,580,0,440,429,575,578,0,429,432,576,575,0,432,433,577,576,0,433,443,579,577,0,443,446,581,579,0,446,453,583,581,0,453,458,585,583,0,458,463,587,585,0,463,468,589,587,0,468,473,592,589,0,473,480,594,592,0,480,484,596,594,0,484,489,597,596,0,489,506,601,597,0,506,513,605,601,0,513,522,607,605,0,522,526,611,607,0,526,529,615,611,0,529,531,618,615,0,531,533,621,618,0,533,540,632,621,0,540,547,644,632,0,547,549,647,644,0,549,552,652,647,0,552,555,655,652,0,555,558,658,655,0,558,562,660,658,0,562,561,661,660,0,561,559,659,661,0,559,557,657,659,0,557,554,654,657,0,554,551,651,654,0,551,548,646,651,0,548,545,643,646,0,545,544,640,643,0,544,542,636,640,0,542,539,633,636,0,539,537,628,633,0,537,535,627,628,0,535,525,610,627,0,525,523,609,610,0,688,609,613,692,0,692,613,630,702,0,702,630,635,705,0,705,635,639,707,0,707,639,645,711,0,711,645,648,714,0,714,648,653,717,0,717,653,662,726,0,726,662,666,728,0,728,666,668,730,0,730,668,670,732,0,732,670,674,734,0,734,674,676,736,0,736,676,678,738,0,738,678,677,737,0,737,677,675,735,0,735,675,672,733,0,733,672,669,731,0,731,669,667,729,0,729,667,664,727,0,727,664,656,720,0,720,656,626,699,0,699,626,623,698,0,698,623,620,696,0,696,620,616,694,0,694,616,612,691,0,691,612,608,687,0,687,608,606,685,0,685,606,603,683,0,683,603,599,681,0,681,599,598,680,0,680,598,595,671,0,671,595,593,663,0,663,593,591,649,0,649,591,590,642,0,642,590,588,638,0,638,588,586,634,0,634,586,584,629,0,629,584,582,624,0,624,582,580,619,0,619,580,578,614,0,614,578,575,600,0,600,575,576,602,0,602,576,577,604,0,604,577,579,617,0,617,579,581,622,0,622,581,583,625,0,625,583,585,631,0,631,585,587,637,0,637,587,589,641,0,641,589,592,650,0,650,592,594,665,0,665,594,596,673,0,673,596,597,679,0,679,597,601,682,0,682,601,605,684,0,684,605,607,686,0,686,607,611,689,0,689,611,615,693,0,693,615,618,695,0,695,618,621,697,0,697,621,632,703,0,703,632,644,710,0,710,644,647,713,0,713,647,652,715,0,715,652,655,719,0,719,655,658,722,0,722,658,660,724,0,724,660,661,725,0,725,661,659,723,0,723,659,657,721,0,721,657,654,718,0,718,654,651,716,0,716,651,646,712,0,712,646,643,709,0,709,643,640,708,0,708,640,636,706,0,706,636,633,704,0,704,633,628,701,0,701,628,627,700,0,700,627,610,690,0,690,610,609,688,0,739,742,742,0,742,742,744,744,0,744,744,745,0,748,751,751,0,751,751,754,0,776,775,775,0,775,775,774,0,768,766,766,0,766,766,764,0,758,756,756,0,756,756,753,753,0,753,753,749,749,0,749,749,746,0,761,763,763,0,763,763,765,0,767,769,769,0,769,769,770,770,0,770,770,772,0,772,773,773,0,773,773,771,0,762,760,760,0,760,760,759,0,759,757,757,0,757,757,755,0,752,750,750,0,750,750,747,0,743,741,741,0,741,741,740,0,851,849,849,0,849,849,848,0,807,805,805,0,805,805,803,0,801,800,800,0,800,800,797,0,786,784,784,0,784,784,782,0,791,794,794,0,794,794,796,0,798,799,799,0,799,799,802,0,808,812,812,0,812,812,815,0,843,842,842,0,842,842,839,0,836,833,833,0,833,833,830,0,903,908,908,0,908,908,922,922,0,922,922,929,929,0,929,929,932,932,0,932,932,934,934,0,934,934,936,936,0,936,936,938,0,939,937,937,0,937,937,935,0,933,931,931,0,931,931,930,930,0,930,930,925,0,925,918,918,0,918,918,915,915,0,915,915,911,911,0,911,911,909,909,0,909,909,906,906,0,906,906,901,0,901,898,898,0,898,898,896,896,0,896,896,894,894,0,894,894,892,892,0,892,892,890,890,0,890,890,888,888,0,888,888,887,0,887,885,885,0,885,885,883,883,0,883,883,881,881,0,881,881,879,879,0,879,879,877,0,877,875,875,0,875,875,873,873,0,873,873,872,872,0,872,872,870,870,0,870,870,868,868,0,868,868,866,866,0,866,866,864,0,864,863,863,0,863,863,860,860,0,860,860,861,861,0,861,861,862,862,0,862,862,865,865,0,865,865,867,867,0,867,867,869,869,0,869,869,871,0,874,876,876,0,876,876,878,878,0,878,878,880,880,0,880,880,882,0,882,884,884,0,884,884,886,886,0,886,886,889,889,0,889,889,891,891,0,891,891,893,893,0,893,893,895,0,895,897,897,0,897,897,899,899,0,899,899,900,900,0,900,900,902,0,902,905,905,0,905,905,907,907,0,907,907,910,910,0,910,910,913,913,0,913,913,916,916,0,916,916,919,919,0,919,919,921,921,0,921,921,924,924,0,924,924,927,0,928,926,926,0,926,926,923,923,0,923,923,920,920,0,920,920,917,917,0,917,917,914,914,0,914,914,912,912,0,912,912,904,0,978,982,1081,1075,0,982,994,1094,1081,0,994,998,1098,1094,0,998,1004,1104,1098,0,1004,1010,1108,1104,0,1010,1015,1115,1108,0,1015,1026,1123,1115,0,1026,1029,1127,1123,0,1029,1033,1133,1127,0,1033,1036,1136,1133,0,1036,1038,1138,1136,0,1038,1040,1142,1138,0,1040,1042,1144,1142,0,1042,1041,1143,1144,0,1041,1039,1141,1143,0,1039,1037,1137,1141,0,1037,1035,1135,1137,0,1035,1034,1132,1135,0,1034,1030,1128,1132,0,1030,1023,1120,1128,0,1023,1013,1112,1120,0,1013,986,1086,1112,0,986,984,1083,1086,0,984,981,1078,1083,0,981,977,1072,1078,0,977,973,1070,1072,0,973,970,1066,1070,0,970,968,1062,1066,0,968,966,1058,1062,0,966,964,1054,1058,0,964,962,1050,1054,0,962,960,1046,1050,0,960,958,1043,1046,0,958,956,1031,1043,0,956,955,1019,1031,0,955,953,1009,1019,0,953,951,1001,1009,0,951,949,997,1001,0,949,947,992,997,0,947,945,988,992,0,945,943,985,988,0,943,940,971,985,0,940,941,974,971,0,941,942,975,974,0,942,944,987,975,0,944,946,991,987,0,946,948,995,991,0,948,950,1000,995,0,950,952,1005,1000,0,952,954,1017,1005,0,954,957,1032,1017,0,957,959,1044,1032,0,959,961,1047,1044,0,961,963,1051,1047,0,963,965,1055,1051,0,965,967,1059,1055,0,967,969,1063,1059,0,969,972,1067,1063,0,972,976,1071,1067,0,976,980,1076,1071,0,980,983,1080,1076,0,983,989,1089,1080,0,989,1002,1101,1089,0,1002,1006,1106,1101,0,1006,1011,1110,1106,0,1011,1014,1114,1110,0,1014,1020,1117,1114,0,1020,1025,1122,1117,0,1025,1028,1125,1122,0,1028,1027,1124,1125,0,1027,1024,1121,1124,0,1024,1021,1118,1121,0,1021,1016,1116,1118,0,1016,1012,1111,1116,0,1012,1007,1107,1111,0,1007,1003,1103,1107,0,1003,999,1099,1103,0,999,996,1096,1099,0,996,993,1093,1096,0,993,990,1090,1093,0,990,979,1077,1090,0,979,978,1075,1077,0,1075,1081,1140,1129,0,1081,1094,1150,1140,0,1094,1098,1152,1150,0,1098,1104,1156,1152,0,1104,1108,1159,1156,0,1108,1115,1164,1159,0,1115,1123,1171,1164,0,1123,1127,1175,1171,0,1127,1133,1177,1175,0,1133,1136,1179,1177,0,1136,1138,1181,1179,0,1138,1142,1183,1181,0,1142,1144,1185,1183,0,1144,1143,1184,1185,0,1143,1141,1182,1184,0,1141,1137,1180,1182,0,1137,1135,1178,1180,0,1135,1132,1176,1178,0,1132,1128,1174,1176,0,1128,1120,1168,1174,0,1120,1112,1162,1168,0,1112,1086,1146,1162,0,1086,1083,1145,1146,0,1083,1078,1134,1145,0,1078,1072,1126,1134,0,1072,1070,1113,1126,0,1070,1066,1105,1113,0,1066,1062,1100,1105,0,1062,1058,1095,1100,0,1058,1054,1091,1095,0,1054,1050,1087,1091,0,1050,1046,1084,1087,0,1046,1043,1079,1084,0,1043,1031,1073,1079,0,1031,1019,1069,1073,0,1019,1009,1065,1069,0,1009,1001,1061,1065,0,1001,997,1057,1061,0,997,992,1053,1057,0,992,988,1049,1053,0,988,985,1045,1049,0,985,971,1008,1045,0,971,974,1018,1008,0,974,975,1022,1018,0,975,987,1048,1022,0,987,991,1052,1048,0,991,995,1056,1052,0,995,1000,1060,1056,0,1000,1005,1064,1060,0,1005,1017,1068,1064,0,1017,1032,1074,1068,0,1032,1044,1082,1074,0,1044,1047,1085,1082,0,1047,1051,1088,1085,0,1051,1055,1092,1088,0,1055,1059,1097,1092,0,1059,1063,1102,1097,0,1063,1067,1109,1102,0,1067,1071,1119,1109,0,1071,1076,1130,1119,0,1076,1080,1139,1130,0,1080,1089,1147,1139,0,1089,1101,1154,1147,0,1101,1106,1157,1154,0,1106,1110,1160,1157,0,1110,1114,1163,1160,0,1114,1117,1166,1163,0,1117,1122,1170,1166,0,1122,1125,1173,1170,0,1125,1124,1172,1173,0,1124,1121,1169,1172,0,1121,1118,1167,1169,0,1118,1116,1165,1167,0,1116,1111,1161,1165,0,1111,1107,1158,1161,0,1107,1103,1155,1158,0,1103,1099,1153,1155,0,1099,1096,1151,1153,0,1096,1093,1149,1151,0,1093,1090,1148,1149,0,1090,1077,1131,1148,0,1077,1075,1129,1131,0,1129,1140,1232,1226,0,1140,1150,1244,1232,0,1150,1152,1248,1244,0,1152,1156,1254,1248,0,1156,1159,1260,1254,0,1159,1164,1264,1260,0,1164,1171,1274,1264,0,1171,1175,1277,1274,0,1175,1177,1280,1277,0,1177,1179,1283,1280,0,1179,1181,1285,1283,0,1181,1183,1287,1285,0,1183,1185,1289,1287,0,1185,1184,1288,1289,0,1184,1182,1286,1288,0,1182,1180,1284,1286,0,1180,1178,1282,1284,0,1178,1176,1278,1282,0,1176,1174,1276,1278,0,1174,1168,1269,1276,0,1168,1162,1261,1269,0,1162,1146,1235,1261,0,1146,1145,1233,1235,0,1145,1134,1227,1233,0,1134,1126,1223,1227,0,1126,1113,1221,1223,0,1113,1105,1219,1221,0,1105,1100,1215,1219,0,1100,1095,1212,1215,0,1095,1091,1210,1212,0,1091,1087,1208,1210,0,1087,1084,1206,1208,0,1084,1079,1204,1206,0,1079,1073,1202,1204,0,1073,1069,1201,1202,0,1069,1065,1199,1201,0,1065,1061,1197,1199,0,1061,1057,1195,1197,0,1057,1053,1193,1195,0,1053,1049,1191,1193,0,1049,1045,1189,1191,0,1045,1008,1186,1189,0,1008,1018,1187,1186,0,1018,1022,1188,1187,0,1022,1048,1190,1188,0,1048,1052,1192,1190,0,1052,1056,1194,1192,0,1056,1060,1196,1194,0,1060,1064,1198,1196,0,1064,1068,1200,1198,0,1068,1074,1203,1200,0,1074,1082,1205,1203,0,1082,1085,1207,1205,0,1085,1088,1209,1207,0,1088,1092,1211,1209,0,1092,1097,1213,1211,0,1097,1102,1217,1213,0,1102,1109,1220,1217,0,1109,1119,1222,1220,0,1119,1130,1225,1222,0,1130,1139,1229,1225,0,1139,1147,1239,1229,0,1147,1154,1252,1239,0,1154,1157,1255,1252,0,1157,1160,1259,1255,0,1160,1163,1263,1259,0,1163,1166,1266,1263,0,1166,1170,1270,1266,0,1170,1173,1273,1270,0,1173,1172,1272,1273,0,1172,1169,1271,1272,0,1169,1167,1267,1271,0,1167,1165,1265,1267,0,1165,1161,1262,1265,0,1161,1158,1256,1262,0,1158,1155,1253,1256,0,1155,1153,1249,1253,0,1153,1151,1246,1249,0,1151,1149,1243,1246,0,1149,1148,1241,1243,0,1148,1131,1228,1241,0,1131,1129,1226,1228,0,1226,1232,1308,1304,0,1232,1244,1314,1308,0,1244,1248,1316,1314,0,1248,1254,1320,1316,0,1254,1260,1324,1320,0,1260,1264,1329,1324,0,1264,1274,1337,1329,0,1274,1277,1339,1337,0,1277,1280,1341,1339,0,1280,1283,1343,1341,0,1283,1285,1345,1343,0,1285,1287,1347,1345,0,1287,1289,1349,1347,0,1289,1288,1348,1349,0,1288,1286,1346,1348,0,1286,1284,1344,1346,0,1284,1282,1342,1344,0,1282,1278,1340,1342,0,1278,1276,1338,1340,0,1276,1269,1332,1338,0,1269,1261,1325,1332,0,1261,1235,1310,1325,0,1235,1233,1309,1310,0,1233,1227,1305,1309,0,1227,1223,1302,1305,0,1223,1221,1300,1302,0,1221,1219,1298,1300,0,1219,1215,1296,1298,0,1215,1212,1294,1296,0,1212,1210,1292,1294,0,1210,1208,1290,1292,0,1208,1206,1279,1290,0,1206,1204,1268,1279,0,1204,1202,1257,1268,0,1202,1201,1251,1257,0,1201,1199,1247,1251,0,1199,1197,1242,1247,0,1197,1195,1238,1242,0,1195,1193,1236,1238,0,1193,1191,1231,1236,0,1191,1189,1224,1231,0,1189,1186,1214,1224,0,1186,1187,1216,1214,0,1187,1188,1218,1216,0,1188,1190,1230,1218,0,1190,1192,1234,1230,0,1192,1194,1237,1234,0,1194,1196,1240,1237,0,1196,1198,1245,1240,0,1198,1200,1250,1245,0,1200,1203,1258,1250,0,1203,1205,1275,1258,0,1205,1207,1281,1275,0,1207,1209,1291,1281,0,1209,1211,1293,1291,0,1211,1213,1295,1293,0,1213,1217,1297,1295,0,1217,1220,1299,1297,0,1220,1222,1301,1299,0,1222,1225,1303,1301,0,1225,1229,1307,1303,0,1229,1239,1311,1307,0,1239,1252,1318,1311,0,1252,1255,1321,1318,0,1255,1259,1323,1321,0,1259,1263,1327,1323,0,1263,1266,1330,1327,0,1266,1270,1333,1330,0,1270,1273,1336,1333,0,1273,1272,1335,1336,0,1272,1271,1334,1335,0,1271,1267,1331,1334,0,1267,1265,1328,1331,0,1265,1262,1326,1328,0,1262,1256,1322,1326,0,1256,1253,1319,1322,0,1253,1249,1317,1319,0,1249,1246,1315,1317,0,1246,1243,1313,1315,0,1243,1241,1312,1313,0,1241,1228,1306,1312,0,1228,1226,1304,1306,0,1304,1308,1391,1387,0,1308,1314,1399,1391,0,1314,1316,1401,1399,0,1316,1320,1405,1401,0,1320,1324,1410,1405,0,1324,1329,1415,1410,0,1329,1337,1425,1415,0,1337,1339,1427,1425,0,1339,1341,1431,1427,0,1341,1343,1433,1431,0,1343,1345,1435,1433,0,1345,1347,1437,1435,0,1347,1349,1439,1437,0,1349,1348,1438,1439,0,1348,1346,1436,1438,0,1346,1344,1434,1436,0,1344,1342,1432,1434,0,1342,1340,1429,1432,0,1340,1338,1426,1429,0,1338,1332,1417,1426,0,1332,1325,1411,1417,0,1325,1310,1392,1411,0,1310,1309,1390,1392,0,1309,1305,1386,1390,0,1305,1302,1384,1386,0,1302,1300,1382,1384,0,1300,1298,1380,1382,0,1298,1296,1378,1380,0,1296,1294,1376,1378,0,1294,1292,1374,1376,0,1292,1290,1372,1374,0,1290,1279,1370,1372,0,1279,1268,1368,1370,0,1268,1257,1366,1368,0,1257,1251,1365,1366,0,1251,1247,1363,1365,0,1247,1242,1361,1363,0,1242,1238,1359,1361,0,1238,1236,1357,1359,0,1236,1231,1355,1357,0,1231,1224,1353,1355,0,1224,1214,1350,1353,0,1214,1216,1351,1350,0,1216,1218,1352,1351,0,1218,1230,1354,1352,0,1230,1234,1356,1354,0,1234,1237,1358,1356,0,1237,1240,1360,1358,0,1240,1245,1362,1360,0,1245,1250,1364,1362,0,1250,1258,1367,1364,0,1258,1275,1369,1367,0,1275,1281,1371,1369,0,1281,1291,1373,1371,0,1291,1293,1375,1373,0,1293,1295,1377,1375,0,1295,1297,1379,1377,0,1297,1299,1381,1379,0,1299,1301,1383,1381,0,1301,1303,1385,1383,0,1303,1307,1389,1385,0,1307,1311,1393,1389,0,1311,1318,1403,1393,0,1318,1321,1406,1403,0,1321,1323,1409,1406,0,1323,1327,1413,1409,0,1327,1330,1416,1413,0,1330,1333,1421,1416,0,1333,1336,1424,1421,0,1336,1335,1423,1424,0,1335,1334,1422,1423,0,1334,1331,1420,1422,0,1331,1328,1414,1420,0,1328,1326,1412,1414,0,1326,1322,1407,1412,0,1322,1319,1404,1407,0,1319,1317,1402,1404,0,1317,1315,1400,1402,0,1315,1313,1396,1400,0,1313,1312,1395,1396,0,1312,1306,1388,1395,0,1306,1304,1387,1388,0,1387,1391,1473,1469,0,1391,1399,1478,1473,0,1399,1401,1480,1478,0,1401,1405,1484,1480,0,1405,1410,1489,1484,0,1410,1415,1493,1489,0,1415,1425,1501,1493,0,1425,1427,1503,1501,0,1427,1431,1505,1503,0,1431,1433,1507,1505,0,1433,1435,1509,1507,0,1435,1437,1511,1509,0,1437,1439,1513,1511,0,1439,1438,1512,1513,0,1438,1436,1510,1512,0,1436,1434,1508,1510,0,1434,1432,1506,1508,0,1432,1429,1504,1506,0,1429,1426,1502,1504,0,1426,1417,1495,1502,0,1417,1411,1488,1495,0,1411,1392,1474,1488,0,1392,1390,1472,1474,0,1390,1386,1468,1472,0,1386,1384,1466,1468,0,1384,1382,1464,1466,0,1382,1380,1462,1464,0,1380,1378,1460,1462,0,1378,1376,1458,1460,0,1376,1374,1456,1458,0,1374,1372,1454,1456,0,1372,1370,1452,1454,0,1370,1368,1450,1452,0,1368,1366,1448,1450,0,1366,1365,1447,1448,0,1365,1363,1445,1447,0,1363,1361,1443,1445,0,1361,1359,1441,1443,0,1359,1357,1430,1441,0,1357,1355,1418,1430,0,1355,1353,1408,1418,0,1353,1350,1394,1408,0,1350,1351,1397,1394,0,1351,1352,1398,1397,0,1352,1354,1419,1398,0,1354,1356,1428,1419,0,1356,1358,1440,1428,0,1358,1360,1442,1440,0,1360,1362,1444,1442,0,1362,1364,1446,1444,0,1364,1367,1449,1446,0,1367,1369,1451,1449,0,1369,1371,1453,1451,0,1371,1373,1455,1453,0,1373,1375,1457,1455,0,1375,1377,1459,1457,0,1377,1379,1461,1459,0,1379,1381,1463,1461,0,1381,1383,1465,1463,0,1383,1385,1467,1465,0,1385,1389,1471,1467,0,1389,1393,1475,1471,0,1393,1403,1482,1475,0,1403,1406,1485,1482,0,1406,1409,1487,1485,0,1409,1413,1491,1487,0,1413,1416,1494,1491,0,1416,1421,1497,1494,0,1421,1424,1499,1497,0,1424,1423,1500,1499,0,1423,1422,1498,1500,0,1422,1420,1496,1498,0,1420,1414,1492,1496,0,1414,1412,1490,1492,0,1412,1407,1486,1490,0,1407,1404,1483,1486,0,1404,1402,1481,1483,0,1402,1400,1479,1481,0,1400,1396,1477,1479,0,1396,1395,1476,1477,0,1395,1388,1470,1476,0,1388,1387,1469,1470,0,1469,1473,1555,1551,0,1473,1478,1560,1555,0,1478,1480,1562,1560,0,1480,1484,1566,1562,0,1484,1489,1571,1566,0,1489,1493,1576,1571,0,1493,1501,1583,1576,0,1501,1503,1585,1583,0,1503,1505,1587,1585,0,1505,1507,1589,1587,0,1507,1509,1591,1589,0,1509,1511,1593,1591,0,1511,1513,1595,1593,0,1513,1512,1594,1595,0,1512,1510,1592,1594,0,1510,1508,1590,1592,0,1508,1506,1588,1590,0,1506,1504,1586,1588,0,1504,1502,1584,1586,0,1502,1495,1577,1584,0,1495,1488,1570,1577,0,1488,1474,1556,1570,0,1474,1472,1554,1556,0,1472,1468,1550,1554,0,1468,1466,1548,1550,0,1466,1464,1546,1548,0,1464,1462,1544,1546,0,1462,1460,1542,1544,0,1460,1458,1540,1542,0,1458,1456,1538,1540,0,1456,1454,1536,1538,0,1454,1452,1534,1536,0,1452,1450,1532,1534,0,1450,1448,1530,1532,0,1448,1447,1529,1530,0,1447,1445,1527,1529,0,1445,1443,1525,1527,0,1443,1441,1523,1525,0,1441,1430,1521,1523,0,1430,1418,1518,1521,0,1418,1408,1517,1518,0,1408,1394,1514,1517,0,1394,1397,1515,1514,0,1397,1398,1516,1515,0,1398,1419,1519,1516,0,1419,1428,1520,1519,0,1428,1440,1522,1520,0,1440,1442,1524,1522,0,1442,1444,1526,1524,0,1444,1446,1528,1526,0,1446,1449,1531,1528,0,1449,1451,1533,1531,0,1451,1453,1535,1533,0,1453,1455,1537,1535,0,1455,1457,1539,1537,0,1457,1459,1541,1539,0,1459,1461,1543,1541,0,1461,1463,1545,1543,0,1463,1465,1547,1545,0,1465,1467,1549,1547,0,1467,1471,1552,1549,0,1471,1475,1557,1552,0,1475,1482,1564,1557,0,1482,1485,1567,1564,0,1485,1487,1569,1567,0,1487,1491,1573,1569,0,1491,1494,1575,1573,0,1494,1497,1579,1575,0,1497,1499,1581,1579,0,1499,1500,1582,1581,0,1500,1498,1580,1582,0,1498,1496,1578,1580,0,1496,1492,1574,1578,0,1492,1490,1572,1574,0,1490,1486,1568,1572,0,1486,1483,1565,1568,0,1483,1481,1563,1565,0,1481,1479,1561,1563,0,1479,1477,1559,1561,0,1477,1476,1558,1559,0,1476,1470,1553,1558,0,1470,1469,1551,1553,0,1551,1555,1637,1633,0,1555,1560,1645,1637,0,1560,1562,1647,1645,0,1562,1566,1653,1647,0,1566,1571,1659,1653,0,1571,1576,1666,1659,0,1576,1583,1673,1666,0,1583,1585,1676,1673,0,1585,1587,1678,1676,0,1587,1589,1681,1678,0,1589,1591,1683,1681,0,1591,1593,1685,1683,0,1593,1595,1688,1685,0,1595,1594,1686,1688,0,1594,1592,1684,1686,0,1592,1590,1682,1684,0,1590,1588,1680,1682,0,1588,1586,1677,1680,0,1586,1584,1674,1677,0,1584,1577,1665,1674,0,1577,1570,1658,1665,0,1570,1556,1638,1658,0,1556,1554,1636,1638,0,1554,1550,1632,1636,0,1550,1548,1630,1632,0,1548,1546,1628,1630,0,1546,1544,1626,1628,0,1544,1542,1624,1626,0,1542,1540,1622,1624,0,1540,1538,1620,1622,0,1538,1536,1618,1620,0,1536,1534,1616,1618,0,1534,1532,1614,1616,0,1532,1530,1612,1614,0,1530,1529,1611,1612,0,1529,1527,1609,1611,0,1527,1525,1607,1609,0,1525,1523,1605,1607,0,1523,1521,1603,1605,0,1521,1518,1600,1603,0,1518,1517,1599,1600,0,1517,1514,1596,1599,0,1514,1515,1597,1596,0,1515,1516,1598,1597,0,1516,1519,1601,1598,0,1519,1520,1602,1601,0,1520,1522,1604,1602,0,1522,1524,1606,1604,0,1524,1526,1608,1606,0,1526,1528,1610,1608,0,1528,1531,1613,1610,0,1531,1533,1615,1613,0,1533,1535,1617,1615,0,1535,1537,1619,1617,0,1537,1539,1621,1619,0,1539,1541,1623,1621,0,1541,1543,1625,1623,0,1543,1545,1627,1625,0,1545,1547,1629,1627,0,1547,1549,1631,1629,0,1549,1552,1634,1631,0,1552,1557,1640,1634,0,1557,1564,1649,1640,0,1564,1567,1652,1649,0,1567,1569,1657,1652,0,1569,1573,1661,1657,0,1573,1575,1664,1661,0,1575,1579,1669,1664,0,1579,1581,1671,1669,0,1581,1582,1672,1671,0,1582,1580,1670,1672,0,1580,1578,1668,1670,0,1578,1574,1662,1668,0,1574,1572,1660,1662,0,1572,1568,1656,1660,0,1568,1565,1651,1656,0,1565,1563,1648,1651,0,1563,1561,1646,1648,0,1561,1559,1644,1646,0,1559,1558,1643,1644,0,1558,1553,1635,1643,0,1553,1551,1633,1635,0,1633,1637,1719,1715,0,1637,1645,1724,1719,0,1645,1647,1726,1724,0,1647,1653,1731,1726,0,1653,1659,1735,1731,0,1659,1666,1741,1735,0,1666,1673,1747,1741,0,1673,1676,1749,1747,0,1676,1678,1751,1749,0,1678,1681,1754,1751,0,1681,1683,1756,1754,0,1683,1685,1758,1756,0,1685,1688,1759,1758,0,1688,1686,1757,1759,0,1686,1684,1755,1757,0,1684,1682,1753,1755,0,1682,1680,1752,1753,0,1680,1677,1750,1752,0,1677,1674,1748,1750,0,1674,1665,1740,1748,0,1665,1658,1734,1740,0,1658,1638,1720,1734,0,1638,1636,1718,1720,0,1636,1632,1714,1718,0,1632,1630,1712,1714,0,1630,1628,1710,1712,0,1628,1626,1708,1710,0,1626,1624,1706,1708,0,1624,1622,1704,1706,0,1622,1620,1702,1704,0,1620,1618,1700,1702,0,1618,1616,1698,1700,0,1616,1614,1696,1698,0,1614,1612,1694,1696,0,1612,1611,1693,1694,0,1611,1609,1691,1693,0,1609,1607,1689,1691,0,1607,1605,1679,1689,0,1605,1603,1667,1679,0,1603,1600,1654,1667,0,1600,1599,1650,1654,0,1599,1596,1639,1650,0,1596,1597,1641,1639,0,1597,1598,1642,1641,0,1598,1601,1655,1642,0,1601,1602,1663,1655,0,1602,1604,1675,1663,0,1604,1606,1687,1675,0,1606,1608,1690,1687,0,1608,1610,1692,1690,0,1610,1613,1695,1692,0,1613,1615,1697,1695,0,1615,1617,1699,1697,0,1617,1619,1701,1699,0,1619,1621,1703,1701,0,1621,1623,1705,1703,0,1623,1625,1707,1705,0,1625,1627,1709,1707,0,1627,1629,1711,1709,0,1629,1631,1713,1711,0,1631,1634,1716,1713,0,1634,1640,1721,1716,0,1640,1649,1728,1721,0,1649,1652,1730,1728,0,1652,1657,1733,1730,0,1657,1661,1737,1733,0,1661,1664,1738,1737,0,1664,1669,1743,1738,0,1669,1671,1745,1743,0,1671,1672,1746,1745,0,1672,1670,1744,1746,0,1670,1668,1742,1744,0,1668,1662,1739,1742,0,1662,1660,1736,1739,0,1660,1656,1732,1736,0,1656,1651,1729,1732,0,1651,1648,1727,1729,0,1648,1646,1725,1727,0,1646,1644,1723,1725,0,1644,1643,1722,1723,0,1643,1635,1717,1722,0,1635,1633,1715,1717,0,1715,1719,1810,1806,0,1719,1724,1822,1810,0,1724,1726,1827,1822,0,1726,1731,1833,1827,0,1731,1735,1838,1833,0,1735,1741,1845,1838,0,1741,1747,1853,1845,0,1747,1749,1856,1853,0,1749,1751,1858,1856,0,1751,1754,1861,1858,0,1754,1756,1863,1861,0,1756,1758,1866,1863,0,1758,1759,1867,1866,0,1759,1757,1865,1867,0,1757,1755,1862,1865,0,1755,1753,1860,1862,0,1753,1752,1857,1860,0,1752,1750,1855,1857,0,1750,1748,1852,1855,0,1748,1740,1842,1852,0,1740,1734,1836,1842,0,1734,1720,1811,1836,0,1720,1718,1807,1811,0,1718,1714,1802,1807,0,1714,1712,1798,1802,0,1712,1710,1795,1798,0,1710,1708,1793,1795,0,1708,1706,1791,1793,0,1706,1704,1787,1791,0,1704,1702,1784,1787,0,1702,1700,1782,1784,0,1700,1698,1780,1782,0,1698,1696,1778,1780,0,1696,1694,1776,1778,0,1694,1693,1775,1776,0,1693,1691,1773,1775,0,1691,1689,1771,1773,0,1689,1679,1769,1771,0,1679,1667,1767,1769,0,1667,1654,1764,1767,0,1654,1650,1763,1764,0,1650,1639,1760,1763,0,1639,1641,1761,1760,0,1641,1642,1762,1761,0,1642,1655,1765,1762,0,1655,1663,1766,1765,0,1663,1675,1768,1766,0,1675,1687,1770,1768,0,1687,1690,1772,1770,0,1690,1692,1774,1772,0,1692,1695,1777,1774,0,1695,1697,1779,1777,0,1697,1699,1781,1779,0,1699,1701,1783,1781,0,1701,1703,1785,1783,0,1703,1705,1788,1785,0,1705,1707,1792,1788,0,1707,1709,1794,1792,0,1709,1711,1797,1794,0,1711,1713,1801,1797,0,1713,1716,1804,1801,0,1716,1721,1815,1804,0,1721,1728,1828,1815,0,1728,1730,1831,1828,0,1730,1733,1834,1831,0,1733,1737,1839,1834,0,1737,1738,1843,1839,0,1738,1743,1847,1843,0,1743,1745,1849,1847,0,1745,1746,1850,1849,0,1746,1744,1848,1850,0,1744,1742,1846,1848,0,1742,1739,1844,1846,0,1739,1736,1840,1844,0,1736,1732,1835,1840,0,1732,1729,1830,1835,0,1729,1727,1826,1830,0,1727,1725,1823,1826,0,1725,1723,1821,1823,0,1723,1722,1818,1821,0,1722,1717,1808,1818,0,1717,1715,1806,1808,0,1806,1810,1884,1880,0,1810,1822,1888,1884,0,1822,1827,1892,1888,0,1827,1833,1895,1892,0,1833,1838,1900,1895,0,1838,1845,1905,1900,0,1845,1853,1912,1905,0,1853,1856,1914,1912,0,1856,1858,1916,1914,0,1858,1861,1918,1916,0,1861,1863,1920,1918,0,1863,1866,1922,1920,0,1866,1867,1923,1922,0,1867,1865,1921,1923,0,1865,1862,1919,1921,0,1862,1860,1917,1919,0,1860,1857,1915,1917,0,1857,1855,1913,1915,0,1855,1852,1911,1913,0,1852,1842,1902,1911,0,1842,1836,1898,1902,0,1836,1811,1883,1898,0,1811,1807,1881,1883,0,1807,1802,1878,1881,0,1802,1798,1876,1878,0,1798,1795,1874,1876,0,1795,1793,1872,1874,0,1793,1791,1870,1872,0,1791,1787,1868,1870,0,1787,1784,1859,1868,0,1784,1782,1851,1859,0,1782,1780,1837,1851,0,1780,1778,1829,1837,0,1778,1776,1824,1829,0,1776,1775,1819,1824,0,1775,1773,1817,1819,0,1773,1771,1814,1817,0,1771,1769,1812,1814,0,1769,1767,1805,1812,0,1767,1764,1799,1805,0,1764,1763,1796,1799,0,1763,1760,1786,1796,0,1760,1761,1789,1786,0,1761,1762,1790,1789,0,1762,1765,1800,1790,0,1765,1766,1803,1800,0,1766,1768,1809,1803,0,1768,1770,1813,1809,0,1770,1772,1816,1813,0,1772,1774,1820,1816,0,1774,1777,1825,1820,0,1777,1779,1832,1825,0,1779,1781,1841,1832,0,1781,1783,1854,1841,0,1783,1785,1864,1854,0,1785,1788,1869,1864,0,1788,1792,1871,1869,0,1792,1794,1873,1871,0,1794,1797,1875,1873,0,1797,1801,1877,1875,0,1801,1804,1879,1877,0,1804,1815,1885,1879,0,1815,1828,1891,1885,0,1828,1831,1893,1891,0,1831,1834,1896,1893,0,1834,1839,1899,1896,0,1839,1843,1903,1899,0,1843,1847,1907,1903,0,1847,1849,1909,1907,0,1849,1850,1910,1909,0,1850,1848,1908,1910,0,1848,1846,1906,1908,0,1846,1844,1904,1906,0,1844,1840,1901,1904,0,1840,1835,1897,1901,0,1835,1830,1894,1897,0,1830,1826,1890,1894,0,1826,1823,1889,1890,0,1823,1821,1887,1889,0,1821,1818,1886,1887,0,1818,1808,1882,1886,0,1808,1806,1880,1882,0,1880,1884,1990,1985,0,1884,1888,2001,1990,0,1888,1892,2007,2001,0,1892,1895,2012,2007,0,1895,1900,2019,2012,0,1900,1905,2025,2019,0,1905,1912,2034,2025,0,1912,1914,2037,2034,0,1914,1916,2040,2037,0,1916,1918,2043,2040,0,1918,1920,2045,2043,0,1920,1922,2047,2045,0,1922,1923,2048,2047,0,1923,1921,2046,2048,0,1921,1919,2044,2046,0,1919,1917,2042,2044,0,1917,1915,2038,2042,0,1915,1913,2036,2038,0,1913,1911,2032,2036,0,1911,1902,2021,2032,0,1902,1898,2014,2021,0,1898,1883,1989,2014,0,1883,1881,1984,1989,0,1881,1878,1980,1984,0,1878,1876,1976,1980,0,1876,1874,1973,1976,0,1874,1872,1970,1973,0,1872,1870,1966,1970,0,1870,1868,1962,1966,0,1868,1859,1958,1962,0,1859,1851,1954,1958,0,1851,1837,1950,1954,0,1837,1829,1946,1950,0,1829,1824,1943,1946,0,1824,1819,1941,1943,0,1819,1817,1938,1941,0,1817,1814,1935,1938,0,1814,1812,1933,1935,0,1812,1805,1931,1933,0,1805,1799,1928,1931,0,1799,1796,1927,1928,0,1796,1786,1924,1927,0,1786,1789,1925,1924,0,1789,1790,1926,1925,0,1790,1800,1929,1926,0,1800,1803,1930,1929,0,1803,1809,1932,1930,0,1809,1813,1934,1932,0,1813,1816,1937,1934,0,1816,1820,1942,1937,0,1820,1825,1944,1942,0,1825,1832,1947,1944,0,1832,1841,1951,1947,0,1841,1854,1955,1951,0,1854,1864,1959,1955,0,1864,1869,1963,1959,0,1869,1871,1967,1963,0,1871,1873,1971,1967,0,1873,1875,1975,1971,0,1875,1877,1979,1975,0,1877,1879,1983,1979,0,1879,1885,1994,1983,0,1885,1891,2005,1994,0,1891,1893,2009,2005,0,1893,1896,2013,2009,0,1896,1899,2018,2013,0,1899,1903,2022,2018,0,1903,1907,2026,2022,0,1907,1909,2029,2026,0,1909,1910,2030,2029,0,1910,1908,2028,2030,0,1908,1906,2027,2028,0,1906,1904,2023,2027,0,1904,1901,2020,2023,0,1901,1897,2015,2020,0,1897,1894,2011,2015,0,1894,1890,2006,2011,0,1890,1889,2002,2006,0,1889,1887,1999,2002,0,1887,1886,1997,1999,0,1886,1882,1986,1997,0,1882,1880,1985,1986,0,1985,1990,2041,2033,0,1990,2001,2052,2041,0,2001,2007,2056,2052,0,2007,2012,2059,2056,0,2012,2019,2064,2059,0,2019,2025,2069,2064,0,2025,2034,2076,2069,0,2034,2037,2078,2076,0,2037,2040,2080,2078,0,2040,2043,2082,2080,0,2043,2045,2084,2082,0,2045,2047,2086,2084,0,2047,2048,2087,2086,0,2048,2046,2085,2087,0,2046,2044,2083,2085,0,2044,2042,2081,2083,0,2042,2038,2079,2081,0,2038,2036,2077,2079,0,2036,2032,2075,2077,0,2032,2021,2066,2075,0,2021,2014,2061,2066,0,2014,1989,2039,2061,0,1989,1984,2031,2039,0,1984,1980,2017,2031,0,1980,1976,2010,2017,0,1976,1973,2004,2010,0,1973,1970,2000,2004,0,1970,1966,1996,2000,0,1966,1962,1993,1996,0,1962,1958,1991,1993,0,1958,1954,1987,1991,0,1954,1950,1981,1987,0,1950,1946,1977,1981,0,1946,1943,1972,1977,0,1943,1941,1968,1972,0,1941,1938,1965,1968,0,1938,1935,1961,1965,0,1935,1933,1957,1961,0,1933,1931,1953,1957,0,1931,1928,1948,1953,0,1928,1927,1945,1948,0,1927,1924,1936,1945,0,1924,1925,1939,1936,0,1925,1926,1940,1939,0,1926,1929,1949,1940,0,1929,1930,1952,1949,0,1930,1932,1956,1952,0,1932,1934,1960,1956,0,1934,1937,1964,1960,0,1937,1942,1969,1964,0,1942,1944,1974,1969,0,1944,1947,1978,1974,0,1947,1951,1982,1978,0,1951,1955,1988,1982,0,1955,1959,1992,1988,0,1959,1963,1995,1992,0,1963,1967,1998,1995,0,1967,1971,2003,1998,0,1971,1975,2008,2003,0,1975,1979,2016,2008,0,1979,1983,2024,2016,0,1983,1994,2049,2024,0,1994,2005,2054,2049,0,2005,2009,2057,2054,0,2009,2013,2060,2057,0,2013,2018,2063,2060,0,2018,2022,2067,2063,0,2022,2026,2070,2067,0,2026,2029,2073,2070,0,2029,2030,2074,2073,0,2030,2028,2072,2074,0,2028,2027,2071,2072,0,2027,2023,2068,2071,0,2023,2020,2065,2068,0,2020,2015,2062,2065,0,2015,2011,2058,2062,0,2011,2006,2055,2058,0,2006,2002,2053,2055,0,2002,1999,2051,2053,0,1999,1997,2050,2051,0,1997,1986,2035,2050,0,1986,1985,2033,2035,0,2033,2041,2171,2164,0,2041,2052,2179,2171,0,2052,2056,2186,2179,0,2056,2059,2192,2186,0,2059,2064,2201,2192,0,2064,2069,2211,2201,0,2069,2076,2220,2211,0,2076,2078,2229,2220,0,2078,2080,2233,2229,0,2080,2082,2236,2233,0,2082,2084,2239,2236,0,2084,2086,2242,2239,0,2086,2087,2243,2242,0,2087,2085,2240,2243,0,2085,2083,2237,2240,0,2083,2081,2234,2237,0,2081,2079,2231,2234,0,2079,2077,2222,2231,0,2077,2075,2217,2222,0,2075,2066,2204,2217,0,2066,2061,2194,2204,0,2061,2039,2168,2194,0,2039,2031,2163,2168,0,2031,2017,2159,2163,0,2017,2010,2155,2159,0,2010,2004,2151,2155,0,2004,2000,2147,2151,0,2000,1996,2143,2147,0,1996,1993,2139,2143,0,1993,1991,2136,2139,0,1991,1987,2132,2136,0,1987,1981,2127,2132,0,1981,1977,2124,2127,0,1977,1972,2120,2124,0,1972,1968,2116,2120,0,1968,1965,2113,2116,0,1965,1961,2109,2113,0,1961,1957,2105,2109,0,1957,1953,2101,2105,0,1953,1948,2096,2101,0,1948,1945,2094,2096,0,1945,1936,2088,2094,0,1936,1939,2090,2088,0,1939,1940,2091,2090,0,1940,1949,2097,2091,0,1949,1952,2100,2097,0,1952,1956,2104,2100,0,1956,1960,2107,2104,0,1960,1964,2112,2107,0,1964,1969,2117,2112,0,1969,1974,2121,2117,0,1974,1978,2125,2121,0,1978,1982,2129,2125,0,1982,1988,2133,2129,0,1988,1992,2137,2133,0,1992,1995,2141,2137,0,1995,1998,2145,2141,0,1998,2003,2149,2145,0,2003,2008,2154,2149,0,2008,2016,2158,2154,0,2016,2024,2162,2158,0,2024,2049,2174,2162,0,2049,2054,2182,2174,0,2054,2057,2187,2182,0,2057,2060,2193,2187,0,2060,2063,2198,2193,0,2063,2067,2205,2198,0,2067,2070,2208,2205,0,2070,2073,2213,2208,0,2073,2074,2214,2213,0,2074,2072,2212,2214,0,2072,2071,2209,2212,0,2071,2068,2207,2209,0,2068,2065,2200,2207,0,2065,2062,2196,2200,0,2062,2058,2189,2196,0,2058,2055,2184,2189,0,2055,2053,2181,2184,0,2053,2051,2177,2181,0,2051,2050,2176,2177,0,2050,2035,2166,2176,0,2035,2033,2164,2166,0,2164,2171,2173,2169,0,2171,2179,2183,2173,0,2179,2186,2191,2183,0,2186,2192,2199,2191,0,2192,2201,2216,2199,0,2201,2211,2225,2216,0,2211,2220,2232,2225,0,2220,2229,2238,2232,0,2229,2233,2244,2238,0,2233,2236,2246,2244,0,2236,2239,2248,2246,0,2239,2242,2250,2248,0,2242,2243,2251,2250,0,2243,2240,2249,2251,0,2240,2237,2247,2249,0,2237,2234,2245,2247,0,2234,2231,2241,2245,0,2231,2222,2235,2241,0,2222,2217,2230,2235,0,2217,2204,2218,2230,0,2204,2194,2203,2218,0,2194,2168,2172,2203,0,2168,2163,2167,2172,0,2163,2159,2161,2167,0,2159,2155,2157,2161,0,2155,2151,2153,2157,0,2151,2147,2150,2153,0,2147,2143,2146,2150,0,2143,2139,2142,2146,0,2139,2136,2138,2142,0,2136,2132,2134,2138,0,2132,2127,2130,2134,0,2127,2124,2126,2130,0,2124,2120,2122,2126,0,2120,2116,2118,2122,0,2116,2113,2115,2118,0,2113,2109,2111,2115,0,2109,2105,2108,2111,0,2105,2101,2103,2108,0,2101,2096,2098,2103,0,2096,2094,2095,2098,0,2094,2088,2089,2095,0,2088,2090,2092,2089,0,2090,2091,2093,2092,0,2091,2097,2099,2093,0,2097,2100,2102,2099,0,2100,2104,2106,2102,0,2104,2107,2110,2106,0,2107,2112,2114,2110,0,2112,2117,2119,2114,0,2117,2121,2123,2119,0,2121,2125,2128,2123,0,2125,2129,2131,2128,0,2129,2133,2135,2131,0,2133,2137,2140,2135,0,2137,2141,2144,2140,0,2141,2145,2148,2144,0,2145,2149,2152,2148,0,2149,2154,2156,2152,0,2154,2158,2160,2156,0,2158,2162,2165,2160,0,2162,2174,2175,2165,0,2174,2182,2188,2175,0,2182,2187,2195,2188,0,2187,2193,2202,2195,0,2193,2198,2210,2202,0,2198,2205,2219,2210,0,2205,2208,2223,2219,0,2208,2213,2227,2223,0,2213,2214,2228,2227,0,2214,2212,2226,2228,0,2212,2209,2224,2226,0,2209,2207,2221,2224,0,2207,2200,2215,2221,0,2200,2196,2206,2215,0,2196,2189,2197,2206,0,2189,2184,2190,2197,0,2184,2181,2185,2190,0,2181,2177,2180,2185,0,2177,2176,2178,2180,0,2176,2166,2170,2178,0,2166,2164,2169,2170,0,2169,2173,2322,2317,0,2173,2183,2333,2322,0,2183,2191,2339,2333,0,2191,2199,2345,2339,0,2199,2216,2354,2345,0,2216,2225,2360,2354,0,2225,2232,2365,2360,0,2232,2238,2367,2365,0,2238,2244,2370,2367,0,2244,2246,2372,2370,0,2246,2248,2374,2372,0,2248,2250,2376,2374,0,2250,2251,2377,2376,0,2251,2249,2375,2377,0,2249,2247,2373,2375,0,2247,2245,2371,2373,0,2245,2241,2368,2371,0,2241,2235,2366,2368,0,2235,2230,2364,2366,0,2230,2218,2353,2364,0,2218,2203,2346,2353,0,2203,2172,2320,2346,0,2172,2167,2315,2320,0,2167,2161,2312,2315,0,2161,2157,2308,2312,0,2157,2153,2304,2308,0,2153,2150,2300,2304,0,2150,2146,2296,2300,0,2146,2142,2292,2296,0,2142,2138,2288,2292,0,2138,2134,2284,2288,0,2134,2130,2280,2284,0,2130,2126,2276,2280,0,2126,2122,2272,2276,0,2122,2118,2269,2272,0,2118,2115,2268,2269,0,2115,2111,2265,2268,0,2111,2108,2262,2265,0,2108,2103,2259,2262,0,2103,2098,2256,2259,0,2098,2095,2255,2256,0,2095,2089,2252,2255,0,2089,2092,2253,2252,0,2092,2093,2254,2253,0,2093,2099,2257,2254,0,2099,2102,2258,2257,0,2102,2106,2261,2258,0,2106,2110,2263,2261,0,2110,2114,2267,2263,0,2114,2119,2270,2267,0,2119,2123,2273,2270,0,2123,2128,2279,2273,0,2128,2131,2282,2279,0,2131,2135,2286,2282,0,2135,2140,2291,2286,0,2140,2144,2295,2291,0,2144,2148,2299,2295,0,2148,2152,2303,2299,0,2152,2156,2307,2303,0,2156,2160,2311,2307,0,2160,2165,2313,2311,0,2165,2175,2325,2313,0,2175,2188,2337,2325,0,2188,2195,2341,2337,0,2195,2202,2344,2341,0,2202,2210,2351,2344,0,2210,2219,2355,2351,0,2219,2223,2358,2355,0,2223,2227,2361,2358,0,2227,2228,2363,2361,0,2228,2226,2362,2363,0,2226,2224,2359,2362,0,2224,2221,2356,2359,0,2221,2215,2352,2356,0,2215,2206,2348,2352,0,2206,2197,2343,2348,0,2197,2190,2338,2343,0,2190,2185,2334,2338,0,2185,2180,2331,2334,0,2180,2178,2329,2331,0,2178,2170,2318,2329,0,2170,2169,2317,2318,0,2317,2322,2357,2347,0,2322,2333,2380,2357,0,2333,2339,2384,2380,0,2339,2345,2389,2384,0,2345,2354,2394,2389,0,2354,2360,2399,2394,0,2360,2365,2404,2399,0,2365,2367,2406,2404,0,2367,2370,2408,2406,0,2370,2372,2410,2408,0,2372,2374,2412,2410,0,2374,2376,2414,2412,0,2376,2377,2415,2414,0,2377,2375,2413,2415,0,2375,2373,2411,2413,0,2373,2371,2409,2411,0,2371,2368,2407,2409,0,2368,2366,2405,2407,0,2366,2364,2403,2405,0,2364,2353,2393,2403,0,2353,2346,2388,2393,0,2346,2320,2350,2388,0,2320,2315,2342,2350,0,2315,2312,2336,2342,0,2312,2308,2332,2336,0,2308,2304,2328,2332,0,2304,2300,2326,2328,0,2300,2296,2323,2326,0,2296,2292,2319,2323,0,2292,2288,2314,2319,0,2288,2284,2309,2314,0,2284,2280,2305,2309,0,2280,2276,2301,2305,0,2276,2272,2297,2301,0,2272,2269,2293,2297,0,2269,2268,2290,2293,0,2268,2265,2287,2290,0,2265,2262,2283,2287,0,2262,2259,2278,2283,0,2259,2256,2274,2278,0,2256,2255,2271,2274,0,2255,2252,2260,2271,0,2252,2253,2264,2260,0,2253,2254,2266,2264,0,2254,2257,2275,2266,0,2257,2258,2277,2275,0,2258,2261,2281,2277,0,2261,2263,2285,2281,0,2263,2267,2289,2285,0,2267,2270,2294,2289,0,2270,2273,2298,2294,0,2273,2279,2302,2298,0,2279,2282,2306,2302,0,2282,2286,2310,2306,0,2286,2291,2316,2310,0,2291,2295,2321,2316,0,2295,2299,2324,2321,0,2299,2303,2327,2324,0,2303,2307,2330,2327,0,2307,2311,2335,2330,0,2311,2313,2340,2335,0,2313,2325,2369,2340,0,2325,2337,2382,2369,0,2337,2341,2385,2382,0,2341,2344,2387,2385,0,2344,2351,2391,2387,0,2351,2355,2395,2391,0,2355,2358,2397,2395,0,2358,2361,2400,2397,0,2361,2363,2402,2400,0,2363,2362,2401,2402,0,2362,2359,2398,2401,0,2359,2356,2396,2398,0,2356,2352,2392,2396,0,2352,2348,2390,2392,0,2348,2343,2386,2390,0,2343,2338,2383,2386,0,2338,2334,2381,2383,0,2334,2331,2379,2381,0,2331,2329,2378,2379,0,2329,2318,2349,2378,0,2318,2317,2347,2349,0,2347,2357,2474,2469,0,2357,2380,2484,2474,0,2380,2384,2490,2484,0,2384,2389,2497,2490,0,2389,2394,2503,2497,0,2394,2399,2510,2503,0,2399,2404,2515,2510,0,2404,2406,2518,2515,0,2406,2408,2521,2518,0,2408,2410,2524,2521,0,2410,2412,2526,2524,0,2412,2414,2528,2526,0,2414,2415,2527,2528,0,2415,2413,2525,2527,0,2413,2411,2523,2525,0,2411,2409,2520,2523,0,2409,2407,2517,2520,0,2407,2405,2516,2517,0,2405,2403,2512,2516,0,2403,2393,2500,2512,0,2393,2388,2495,2500,0,2388,2350,2470,2495,0,2350,2342,2466,2470,0,2342,2336,2462,2466,0,2336,2332,2458,2462,0,2332,2328,2454,2458,0,2328,2326,2450,2454,0,2326,2323,2447,2450,0,2323,2319,2445,2447,0,2319,2314,2443,2445,0,2314,2309,2439,2443,0,2309,2305,2436,2439,0,2305,2301,2434,2436,0,2301,2297,2432,2434,0,2297,2293,2430,2432,0,2293,2290,2429,2430,0,2290,2287,2427,2429,0,2287,2283,2425,2427,0,2283,2278,2423,2425,0,2278,2274,2420,2423,0,2274,2271,2419,2420,0,2271,2260,2416,2419,0,2260,2264,2417,2416,0,2264,2266,2418,2417,0,2266,2275,2421,2418,0,2275,2277,2422,2421,0,2277,2281,2424,2422,0,2281,2285,2426,2424,0,2285,2289,2428,2426,0,2289,2294,2431,2428,0,2294,2298,2433,2431,0,2298,2302,2435,2433,0,2302,2306,2437,2435,0,2306,2310,2440,2437,0,2310,2316,2444,2440,0,2316,2321,2446,2444,0,2321,2324,2449,2446,0,2324,2327,2453,2449,0,2327,2330,2457,2453,0,2330,2335,2461,2457,0,2335,2340,2465,2461,0,2340,2369,2477,2465,0,2369,2382,2487,2477,0,2382,2385,2491,2487,0,2385,2387,2494,2491,0,2387,2391,2499,2494,0,2391,2395,2504,2499,0,2395,2397,2506,2504,0,2397,2400,2509,2506,0,2400,2402,2513,2509,0,2402,2401,2511,2513,0,2401,2398,2508,2511,0,2398,2396,2505,2508,0,2396,2392,2502,2505,0,2392,2390,2498,2502,0,2390,2386,2493,2498,0,2386,2383,2489,2493,0,2383,2381,2485,2489,0,2381,2379,2482,2485,0,2379,2378,2480,2482,0,2378,2349,2471,2480,0,2349,2347,2469,2471,0,2469,2474,2540,2537,0,2474,2484,2544,2540,0,2484,2490,2548,2544,0,2490,2497,2553,2548,0,2497,2503,2560,2553,0,2503,2510,2566,2560,0,2510,2515,2572,2566,0,2515,2518,2574,2572,0,2518,2521,2576,2574,0,2521,2524,2578,2576,0,2524,2526,2580,2578,0,2526,2528,2582,2580,0,2528,2527,2581,2582,0,2527,2525,2579,2581,0,2525,2523,2577,2579,0,2523,2520,2575,2577,0,2520,2517,2573,2575,0,2517,2516,2571,2573,0,2516,2512,2565,2571,0,2512,2500,2557,2565,0,2500,2495,2552,2557,0,2495,2470,2538,2552,0,2470,2466,2536,2538,0,2466,2462,2534,2536,0,2462,2458,2532,2534,0,2458,2454,2530,2532,0,2454,2450,2522,2530,0,2450,2447,2514,2522,0,2447,2445,2501,2514,0,2445,2443,2492,2501,0,2443,2439,2486,2492,0,2439,2436,2481,2486,0,2436,2434,2478,2481,0,2434,2432,2475,2478,0,2432,2430,2472,2475,0,2430,2429,2468,2472,0,2429,2427,2464,2468,0,2427,2425,2460,2464,0,2425,2423,2456,2460,0,2423,2420,2451,2456,0,2420,2419,2448,2451,0,2419,2416,2438,2448,0,2416,2417,2441,2438,0,2417,2418,2442,2441,0,2418,2421,2452,2442,0,2421,2422,2455,2452,0,2422,2424,2459,2455,0,2424,2426,2463,2459,0,2426,2428,2467,2463,0,2428,2431,2473,2467,0,2431,2433,2476,2473,0,2433,2435,2479,2476,0,2435,2437,2483,2479,0,2437,2440,2488,2483,0,2440,2444,2496,2488,0,2444,2446,2507,2496,0,2446,2449,2519,2507,0,2449,2453,2529,2519,0,2453,2457,2531,2529,0,2457,2461,2533,2531,0,2461,2465,2535,2533,0,2465,2477,2541,2535,0,2477,2487,2546,2541,0,2487,2491,2549,2546,0,2491,2494,2551,2549,0,2494,2499,2556,2551,0,2499,2504,2559,2556,0,2504,2506,2562,2559,0,2506,2509,2564,2562,0,2509,2513,2569,2564,0,2513,2511,2567,2569,0,2511,2508,2563,2567,0,2508,2505,2561,2563,0,2505,2502,2558,2561,0,2502,2498,2555,2558,0,2498,2493,2550,2555,0,2493,2489,2547,2550,0,2489,2485,2545,2547,0,2485,2482,2543,2545,0,2482,2480,2542,2543,0,2480,2471,2539,2542,0,2471,2469,2537,2539,0,2537,2540,2622,2620,0,2540,2544,2626,2622,0,2544,2548,2630,2626,0,2548,2553,2635,2630,0,2553,2560,2641,2635,0,2560,2566,2649,2641,0,2566,2572,2651,2649,0,2572,2574,2653,2651,0,2574,2576,2655,2653,0,2576,2578,2657,2655,0,2578,2580,2659,2657,0,2580,2582,2661,2659,0,2582,2581,2660,2661,0,2581,2579,2658,2660,0,2579,2577,2656,2658,0,2577,2575,2654,2656,0,2575,2573,2652,2654,0,2573,2571,2650,2652,0,2571,2565,2646,2650,0,2565,2557,2638,2646,0,2557,2552,2633,2638,0,2552,2538,2619,2633,0,2538,2536,2618,2619,0,2536,2534,2616,2618,0,2534,2532,2614,2616,0,2532,2530,2612,2614,0,2530,2522,2610,2612,0,2522,2514,2608,2610,0,2514,2501,2606,2608,0,2501,2492,2604,2606,0,2492,2486,2602,2604,0,2486,2481,2600,2602,0,2481,2478,2598,2600,0,2478,2475,2596,2598,0,2475,2472,2594,2596,0,2472,2468,2593,2594,0,2468,2464,2591,2593,0,2464,2460,2589,2591,0,2460,2456,2587,2589,0,2456,2451,2584,2587,0,2451,2448,2583,2584,0,2448,2438,2554,2583,0,2438,2441,2568,2554,0,2441,2442,2570,2568,0,2442,2452,2585,2570,0,2452,2455,2586,2585,0,2455,2459,2588,2586,0,2459,2463,2590,2588,0,2463,2467,2592,2590,0,2467,2473,2595,2592,0,2473,2476,2597,2595,0,2476,2479,2599,2597,0,2479,2483,2601,2599,0,2483,2488,2603,2601,0,2488,2496,2605,2603,0,2496,2507,2607,2605,0,2507,2519,2609,2607,0,2519,2529,2611,2609,0,2529,2531,2613,2611,0,2531,2533,2615,2613,0,2533,2535,2617,2615,0,2535,2541,2623,2617,0,2541,2546,2628,2623,0,2546,2549,2631,2628,0,2549,2551,2634,2631,0,2551,2556,2637,2634,0,2556,2559,2640,2637,0,2559,2562,2643,2640,0,2562,2564,2645,2643,0,2564,2569,2648,2645,0,2569,2567,2647,2648,0,2567,2563,2644,2647,0,2563,2561,2642,2644,0,2561,2558,2639,2642,0,2558,2555,2636,2639,0,2555,2550,2632,2636,0,2550,2547,2629,2632,0,2547,2545,2627,2629,0,2545,2543,2625,2627,0,2543,2542,2624,2625,0,2542,2539,2621,2624,0,2539,2537,2620,2621,0,32,43,44,47,50,52,53,56,59,62,64,66,69,70,67,63,60,58,55,48,41,39,37,35,30,28,26,23,22,20,17,15,13,11,9,7,5,3,2,1,4,6,8,10,12,14,16,18,19,21,24,25,27,29,33,36,38,40,42,45,65,72,74,76,78,80,82,81,79,77,75,73,71,68,61,57,54,51,49,46,34,31,0,2620,2622,2626,2630,2635,2641,2649,2651,2653,2655,2657,2659,2661,2660,2658,2656,2654,2652,2650,2646,2638,2633,2619,2618,2616,2614,2612,2610,2608,2606,2604,2602,2600,2598,2596,2594,2593,2591,2589,2587,2584,2583,2554,2568,2570,2585,2586,2588,2590,2592,2595,2597,2599,2601,2603,2605,2607,2609,2611,2613,2615,2617,2623,2628,2631,2634,2637,2640,2643,2645,2648,2647,2644,2642,2639,2636,2632,2629,2627,2625,2624,2621,0,2764,2776,2848,2837,0,2776,2800,2866,2848,0,2800,2808,2873,2866,0,2808,2817,2881,2873,0,2817,2826,2889,2881,0,2826,2829,2891,2889,0,2829,2833,2895,2891,0,2833,2836,2899,2895,0,2836,2839,2901,2899,0,2839,2841,2903,2901,0,2841,2840,2902,2903,0,2840,2838,2900,2902,0,2838,2835,2898,2900,0,2835,2831,2894,2898,0,2831,2828,2890,2894,0,2828,2825,2888,2890,0,2825,2818,2882,2888,0,2818,2810,2875,2882,0,2810,2803,2869,2875,0,2803,2794,2862,2869,0,2794,2786,2857,2862,0,2786,2741,2788,2857,0,2741,2733,2779,2788,0,2733,2727,2771,2779,0,2727,2721,2763,2771,0,2721,2715,2757,2763,0,2715,2711,2752,2757,0,2711,2707,2749,2752,0,2707,2701,2743,2749,0,2701,2696,2737,2743,0,2696,2692,2729,2737,0,2692,2687,2722,2729,0,2687,2684,2716,2722,0,2684,2681,2712,2716,0,2681,2678,2708,2712,0,2678,2675,2702,2708,0,2675,2672,2697,2702,0,2672,2671,2695,2697,0,2671,2668,2689,2695,0,2668,2666,2685,2689,0,2666,2665,2683,2685,0,2665,2662,2674,2683,0,2662,2663,2677,2674,0,2663,2664,2679,2677,0,2664,2667,2688,2679,0,2667,2669,2691,2688,0,2669,2670,2694,2691,0,2670,2673,2698,2694,0,2673,2676,2703,2698,0,2676,2680,2709,2703,0,2680,2682,2714,2709,0,2682,2686,2720,2714,0,2686,2690,2726,2720,0,2690,2693,2732,2726,0,2693,2700,2739,2732,0,2700,2705,2746,2739,0,2705,2710,2751,2746,0,2710,2717,2758,2751,0,2717,2723,2766,2758,0,2723,2728,2772,2766,0,2728,2734,2781,2772,0,2734,2754,2814,2781,0,2754,2778,2852,2814,0,2778,2784,2855,2852,0,2784,2791,2859,2855,0,2791,2797,2864,2859,0,2797,2802,2868,2864,0,2802,2809,2874,2868,0,2809,2813,2878,2874,0,2813,2815,2879,2878,0,2815,2819,2883,2879,0,2819,2821,2885,2883,0,2821,2820,2884,2885,0,2820,2816,2880,2884,0,2816,2812,2877,2880,0,2812,2807,2872,2877,0,2807,2801,2867,2872,0,2801,2798,2865,2867,0,2798,2792,2860,2865,0,2792,2789,2858,2860,0,2789,2767,2843,2858,0,2767,2764,2837,2843,0,2837,2848,2906,2893,0,2848,2866,2921,2906,0,2866,2873,2927,2921,0,2873,2881,2935,2927,0,2881,2889,2942,2935,0,2889,2891,2944,2942,0,2891,2895,2947,2944,0,2895,2899,2950,2947,0,2899,2901,2953,2950,0,2901,2903,2956,2953,0,2903,2902,2955,2956,0,2902,2900,2952,2955,0,2900,2898,2948,2952,0,2898,2894,2946,2948,0,2894,2890,2943,2946,0,2890,2888,2941,2943,0,2888,2882,2936,2941,0,2882,2875,2929,2936,0,2875,2869,2925,2929,0,2869,2862,2917,2925,0,2862,2857,2911,2917,0,2857,2788,2854,2911,0,2788,2779,2849,2854,0,2779,2771,2844,2849,0,2771,2763,2830,2844,0,2763,2757,2823,2830,0,2757,2752,2806,2823,0,2752,2749,2796,2806,0,2749,2743,2785,2796,0,2743,2737,2777,2785,0,2737,2729,2770,2777,0,2729,2722,2762,2770,0,2722,2716,2756,2762,0,2716,2712,2750,2756,0,2712,2708,2745,2750,0,2708,2702,2740,2745,0,2702,2697,2735,2740,0,2697,2695,2731,2735,0,2695,2689,2724,2731,0,2689,2685,2718,2724,0,2685,2683,2713,2718,0,2683,2674,2699,2713,0,2674,2677,2704,2699,0,2677,2679,2706,2704,0,2679,2688,2719,2706,0,2688,2691,2725,2719,0,2691,2694,2730,2725,0,2694,2698,2736,2730,0,2698,2703,2742,2736,0,2703,2709,2748,2742,0,2709,2714,2753,2748,0,2714,2720,2760,2753,0,2720,2726,2768,2760,0,2726,2732,2773,2768,0,2732,2739,2783,2773,0,2739,2746,2793,2783,0,2746,2751,2804,2793,0,2751,2758,2824,2804,0,2758,2766,2834,2824,0,2766,2772,2846,2834,0,2772,2781,2850,2846,0,2781,2814,2876,2850,0,2814,2852,2907,2876,0,2852,2855,2910,2907,0,2855,2859,2915,2910,0,2859,2864,2919,2915,0,2864,2868,2924,2919,0,2868,2874,2928,2924,0,2874,2878,2931,2928,0,2878,2879,2933,2931,0,2879,2883,2937,2933,0,2883,2885,2939,2937,0,2885,2884,2938,2939,0,2884,2880,2934,2938,0,2880,2877,2930,2934,0,2877,2872,2926,2930,0,2872,2867,2923,2926,0,2867,2865,2918,2923,0,2865,2860,2916,2918,0,2860,2858,2914,2916,0,2858,2843,2897,2914,0,2843,2837,2893,2897,0,2893,2906,2959,2949,0,2906,2921,2976,2959,0,2921,2927,2984,2976,0,2927,2935,2993,2984,0,2935,2942,3000,2993,0,2942,2944,3004,3000,0,2944,2947,3006,3004,0,2947,2950,3009,3006,0,2950,2953,3012,3009,0,2953,2956,3015,3012,0,2956,2955,3014,3015,0,2955,2952,3010,3014,0,2952,2948,3008,3010,0,2948,2946,3005,3008,0,2946,2943,3003,3005,0,2943,2941,2999,3003,0,2941,2936,2994,2999,0,2936,2929,2987,2994,0,2929,2925,2980,2987,0,2925,2917,2973,2980,0,2917,2911,2966,2973,0,2911,2854,2913,2966,0,2854,2849,2908,2913,0,2849,2844,2904,2908,0,2844,2830,2892,2904,0,2830,2823,2886,2892,0,2823,2806,2871,2886,0,2806,2796,2863,2871,0,2796,2785,2856,2863,0,2785,2777,2851,2856,0,2777,2770,2845,2851,0,2770,2762,2832,2845,0,2762,2756,2822,2832,0,2756,2750,2805,2822,0,2750,2745,2795,2805,0,2745,2740,2787,2795,0,2740,2735,2780,2787,0,2735,2731,2775,2780,0,2731,2724,2765,2775,0,2724,2718,2759,2765,0,2718,2713,2755,2759,0,2713,2699,2738,2755,0,2699,2704,2744,2738,0,2704,2706,2747,2744,0,2706,2719,2761,2747,0,2719,2725,2769,2761,0,2725,2730,2774,2769,0,2730,2736,2782,2774,0,2736,2742,2790,2782,0,2742,2748,2799,2790,0,2748,2753,2811,2799,0,2753,2760,2827,2811,0,2760,2768,2842,2827,0,2768,2773,2847,2842,0,2773,2783,2853,2847,0,2783,2793,2861,2853,0,2793,2804,2870,2861,0,2804,2824,2887,2870,0,2824,2834,2896,2887,0,2834,2846,2905,2896,0,2846,2850,2909,2905,0,2850,2876,2932,2909,0,2876,2907,2962,2932,0,2907,2910,2965,2962,0,2910,2915,2968,2965,0,2915,2919,2975,2968,0,2919,2924,2979,2975,0,2924,2928,2986,2979,0,2928,2931,2990,2986,0,2931,2933,2991,2990,0,2933,2937,2995,2991,0,2937,2939,2998,2995,0,2939,2938,2996,2998,0,2938,2934,2992,2996,0,2934,2930,2989,2992,0,2930,2926,2985,2989,0,2926,2923,2978,2985,0,2923,2918,2974,2978,0,2918,2916,2969,2974,0,2916,2914,2967,2969,0,2914,2897,2954,2967,0,2897,2893,2949,2954,0,2949,2959,3076,3070,0,2959,2976,3098,3076,0,2976,2984,3103,3098,0,2984,2993,3113,3103,0,2993,3000,3121,3113,0,3000,3004,3123,3121,0,3004,3006,3126,3123,0,3006,3009,3129,3126,0,3009,3012,3131,3129,0,3012,3015,3133,3131,0,3015,3014,3132,3133,0,3014,3010,3130,3132,0,3010,3008,3128,3130,0,3008,3005,3125,3128,0,3005,3003,3122,3125,0,3003,2999,3120,3122,0,2999,2994,3114,3120,0,2994,2987,3107,3114,0,2987,2980,3102,3107,0,2980,2973,3094,3102,0,2973,2966,3087,3094,0,2966,2913,3055,3087,0,2913,2908,3051,3055,0,2908,2904,3046,3051,0,2904,2892,3042,3046,0,2892,2886,3039,3042,0,2886,2871,3036,3039,0,2871,2863,3032,3036,0,2863,2856,3028,3032,0,2856,2851,3024,3028,0,2851,2845,3019,3024,0,2845,2832,3013,3019,0,2832,2822,3001,3013,0,2822,2805,2988,3001,0,2805,2795,2977,2988,0,2795,2787,2970,2977,0,2787,2780,2963,2970,0,2780,2775,2961,2963,0,2775,2765,2957,2961,0,2765,2759,2945,2957,0,2759,2755,2940,2945,0,2755,2738,2912,2940,0,2738,2744,2920,2912,0,2744,2747,2922,2920,0,2747,2761,2951,2922,0,2761,2769,2958,2951,0,2769,2774,2960,2958,0,2774,2782,2964,2960,0,2782,2790,2972,2964,0,2790,2799,2981,2972,0,2799,2811,2997,2981,0,2811,2827,3007,2997,0,2827,2842,3017,3007,0,2842,2847,3021,3017,0,2847,2853,3025,3021,0,2853,2861,3031,3025,0,2861,2870,3035,3031,0,2870,2887,3040,3035,0,2887,2896,3044,3040,0,2896,2905,3048,3044,0,2905,2909,3052,3048,0,2909,2932,3062,3052,0,2932,2962,3081,3062,0,2962,2965,3086,3081,0,2965,2968,3092,3086,0,2968,2975,3096,3092,0,2975,2979,3101,3096,0,2979,2986,3105,3101,0,2986,2990,3109,3105,0,2990,2991,3111,3109,0,2991,2995,3115,3111,0,2995,2998,3117,3115,0,2998,2996,3116,3117,0,2996,2992,3112,3116,0,2992,2989,3108,3112,0,2989,2985,3104,3108,0,2985,2978,3100,3104,0,2978,2974,3095,3100,0,2974,2969,3091,3095,0,2969,2967,3088,3091,0,2967,2954,3071,3088,0,2954,2949,3070,3071,0,3070,3076,3139,3134,0,3076,3098,3157,3139,0,3098,3103,3163,3157,0,3103,3113,3171,3163,0,3113,3121,3180,3171,0,3121,3123,3182,3180,0,3123,3126,3187,3182,0,3126,3129,3190,3187,0,3129,3131,3191,3190,0,3131,3133,3193,3191,0,3133,3132,3194,3193,0,3132,3130,3192,3194,0,3130,3128,3189,3192,0,3128,3125,3186,3189,0,3125,3122,3181,3186,0,3122,3120,3179,3181,0,3120,3114,3173,3179,0,3114,3107,3166,3173,0,3107,3102,3161,3166,0,3102,3094,3152,3161,0,3094,3087,3146,3152,0,3087,3055,3093,3146,0,3055,3051,3084,3093,0,3051,3046,3077,3084,0,3046,3042,3073,3077,0,3042,3039,3067,3073,0,3039,3036,3064,3067,0,3036,3032,3061,3064,0,3032,3028,3057,3061,0,3028,3024,3053,3057,0,3024,3019,3049,3053,0,3019,3013,3045,3049,0,3013,3001,3041,3045,0,3001,2988,3037,3041,0,2988,2977,3033,3037,0,2977,2970,3029,3033,0,2970,2963,3026,3029,0,2963,2961,3023,3026,0,2961,2957,3018,3023,0,2957,2945,3011,3018,0,2945,2940,3002,3011,0,2940,2912,2971,3002,0,2912,2920,2982,2971,0,2920,2922,2983,2982,0,2922,2951,3016,2983,0,2951,2958,3020,3016,0,2958,2960,3022,3020,0,2960,2964,3027,3022,0,2964,2972,3030,3027,0,2972,2981,3034,3030,0,2981,2997,3038,3034,0,2997,3007,3043,3038,0,3007,3017,3047,3043,0,3017,3021,3050,3047,0,3021,3025,3056,3050,0,3025,3031,3060,3056,0,3031,3035,3063,3060,0,3035,3040,3068,3063,0,3040,3044,3075,3068,0,3044,3048,3080,3075,0,3048,3052,3085,3080,0,3052,3062,3118,3085,0,3062,3081,3141,3118,0,3081,3086,3143,3141,0,3086,3092,3149,3143,0,3092,3096,3155,3149,0,3096,3101,3159,3155,0,3101,3105,3165,3159,0,3105,3109,3168,3165,0,3109,3111,3169,3168,0,3111,3115,3174,3169,0,3115,3117,3177,3174,0,3117,3116,3176,3177,0,3116,3112,3170,3176,0,3112,3108,3167,3170,0,3108,3104,3164,3167,0,3104,3100,3158,3164,0,3100,3095,3153,3158,0,3095,3091,3148,3153,0,3091,3088,3147,3148,0,3088,3071,3136,3147,0,3071,3070,3134,3136,0,3134,3139,3223,3217,0,3139,3157,3246,3223,0,3157,3163,3252,3246,0,3163,3171,3262,3252,0,3171,3180,3271,3262,0,3180,3182,3274,3271,0,3182,3187,3277,3274,0,3187,3190,3280,3277,0,3190,3191,3282,3280,0,3191,3193,3284,3282,0,3193,3194,3285,3284,0,3194,3192,3283,3285,0,3192,3189,3281,3283,0,3189,3186,3278,3281,0,3186,3181,3273,3278,0,3181,3179,3270,3273,0,3179,3173,3265,3270,0,3173,3166,3257,3265,0,3166,3161,3250,3257,0,3161,3152,3241,3250,0,3152,3146,3233,3241,0,3146,3093,3205,3233,0,3093,3084,3201,3205,0,3084,3077,3195,3201,0,3077,3073,3183,3195,0,3073,3067,3172,3183,0,3067,3064,3162,3172,0,3064,3061,3151,3162,0,3061,3057,3144,3151,0,3057,3053,3140,3144,0,3053,3049,3137,3140,0,3049,3045,3127,3137,0,3045,3041,3119,3127,0,3041,3037,3106,3119,0,3037,3033,3097,3106,0,3033,3029,3089,3097,0,3029,3026,3082,3089,0,3026,3023,3079,3082,0,3023,3018,3072,3079,0,3018,3011,3066,3072,0,3011,3002,3065,3066,0,3002,2971,3054,3065,0,2971,2982,3058,3054,0,2982,2983,3059,3058,0,2983,3016,3069,3059,0,3016,3020,3074,3069,0,3020,3022,3078,3074,0,3022,3027,3083,3078,0,3027,3030,3090,3083,0,3030,3034,3099,3090,0,3034,3038,3110,3099,0,3038,3043,3124,3110,0,3043,3047,3135,3124,0,3047,3050,3138,3135,0,3050,3056,3142,3138,0,3056,3060,3150,3142,0,3060,3063,3160,3150,0,3063,3068,3175,3160,0,3068,3075,3185,3175,0,3075,3080,3198,3185,0,3080,3085,3202,3198,0,3085,3118,3211,3202,0,3118,3141,3227,3211,0,3141,3143,3231,3227,0,3143,3149,3239,3231,0,3149,3155,3243,3239,0,3155,3159,3249,3243,0,3159,3165,3255,3249,0,3165,3168,3259,3255,0,3168,3169,3261,3259,0,3169,3174,3264,3261,0,3174,3177,3268,3264,0,3177,3176,3267,3268,0,3176,3170,3260,3267,0,3170,3167,3258,3260,0,3167,3164,3253,3258,0,3164,3158,3248,3253,0,3158,3153,3242,3248,0,3153,3148,3238,3242,0,3148,3147,3234,3238,0,3147,3136,3218,3234,0,3136,3134,3217,3218,0,3217,3223,3320,3313,0,3223,3246,3343,3320,0,3246,3252,3352,3343,0,3252,3262,3360,3352,0,3262,3271,3367,3360,0,3271,3274,3371,3367,0,3274,3277,3373,3371,0,3277,3280,3377,3373,0,3280,3282,3380,3377,0,3282,3284,3382,3380,0,3284,3285,3383,3382,0,3285,3283,3381,3383,0,3283,3281,3379,3381,0,3281,3278,3375,3379,0,3278,3273,3372,3375,0,3273,3270,3368,3372,0,3270,3265,3363,3368,0,3265,3257,3355,3363,0,3257,3250,3350,3355,0,3250,3241,3340,3350,0,3241,3233,3332,3340,0,3233,3205,3300,3332,0,3205,3201,3295,3300,0,3201,3195,3290,3295,0,3195,3183,3287,3290,0,3183,3172,3275,3287,0,3172,3162,3266,3275,0,3162,3151,3251,3266,0,3151,3144,3240,3251,0,3144,3140,3232,3240,0,3140,3137,3225,3232,0,3137,3127,3221,3225,0,3127,3119,3216,3221,0,3119,3106,3212,3216,0,3106,3097,3209,3212,0,3097,3089,3206,3209,0,3089,3082,3203,3206,0,3082,3079,3200,3203,0,3079,3072,3196,3200,0,3072,3066,3184,3196,0,3066,3065,3178,3184,0,3065,3054,3145,3178,0,3054,3058,3154,3145,0,3058,3059,3156,3154,0,3059,3069,3188,3156,0,3069,3074,3197,3188,0,3074,3078,3199,3197,0,3078,3083,3204,3199,0,3083,3090,3207,3204,0,3090,3099,3210,3207,0,3099,3110,3215,3210,0,3110,3124,3219,3215,0,3124,3135,3222,3219,0,3135,3138,3228,3222,0,3138,3142,3235,3228,0,3142,3150,3247,3235,0,3150,3160,3263,3247,0,3160,3175,3276,3263,0,3175,3185,3288,3276,0,3185,3198,3292,3288,0,3198,3202,3296,3292,0,3202,3211,3308,3296,0,3211,3227,3325,3308,0,3227,3231,3330,3325,0,3231,3239,3337,3330,0,3239,3243,3342,3337,0,3243,3249,3348,3342,0,3249,3255,3354,3348,0,3255,3259,3357,3354,0,3259,3261,3361,3357,0,3261,3264,3362,3361,0,3264,3268,3365,3362,0,3268,3267,3364,3365,0,3267,3260,3359,3364,0,3260,3258,3356,3359,0,3258,3253,3353,3356,0,3253,3248,3347,3353,0,3248,3242,3341,3347,0,3242,3238,3334,3341,0,3238,3234,3331,3334,0,3234,3218,3314,3331,0,3218,3217,3313,3314,0,3313,3320,3395,3389,0,3320,3343,3420,3395,0,3343,3352,3427,3420,0,3352,3360,3437,3427,0,3360,3367,3446,3437,0,3367,3371,3451,3446,0,3371,3373,3454,3451,0,3373,3377,3458,3454,0,3377,3380,3460,3458,0,3380,3382,3464,3460,0,3382,3383,3465,3464,0,3383,3381,3461,3465,0,3381,3379,3459,3461,0,3379,3375,3455,3459,0,3375,3372,3452,3455,0,3372,3368,3447,3452,0,3368,3363,3442,3447,0,3363,3355,3431,3442,0,3355,3350,3425,3431,0,3350,3340,3415,3425,0,3340,3332,3408,3415,0,3332,3300,3344,3408,0,3300,3295,3335,3344,0,3295,3290,3326,3335,0,3290,3287,3321,3326,0,3287,3275,3316,3321,0,3275,3266,3311,3316,0,3266,3251,3307,3311,0,3251,3240,3305,3307,0,3240,3232,3301,3305,0,3232,3225,3297,3301,0,3225,3221,3293,3297,0,3221,3216,3289,3293,0,3216,3212,3279,3289,0,3212,3209,3269,3279,0,3209,3206,3254,3269,0,3206,3203,3244,3254,0,3203,3200,3237,3244,0,3200,3196,3229,3237,0,3196,3184,3224,3229,0,3184,3178,3220,3224,0,3178,3145,3208,3220,0,3145,3154,3213,3208,0,3154,3156,3214,3213,0,3156,3188,3226,3214,0,3188,3197,3230,3226,0,3197,3199,3236,3230,0,3199,3204,3245,3236,0,3204,3207,3256,3245,0,3207,3210,3272,3256,0,3210,3215,3286,3272,0,3215,3219,3291,3286,0,3219,3222,3294,3291,0,3222,3228,3298,3294,0,3228,3235,3302,3298,0,3235,3247,3306,3302,0,3247,3263,3310,3306,0,3263,3276,3317,3310,0,3276,3288,3322,3317,0,3288,3292,3327,3322,0,3292,3296,3336,3327,0,3296,3308,3374,3336,0,3308,3325,3400,3374,0,3325,3330,3405,3400,0,3330,3337,3412,3405,0,3337,3342,3418,3412,0,3342,3348,3424,3418,0,3348,3354,3429,3424,0,3354,3357,3435,3429,0,3357,3361,3439,3435,0,3361,3362,3440,3439,0,3362,3365,3443,3440,0,3365,3364,3441,3443,0,3364,3359,3438,3441,0,3359,3356,3433,3438,0,3356,3353,3428,3433,0,3353,3347,3423,3428,0,3347,3341,3416,3423,0,3341,3334,3410,3416,0,3334,3331,3406,3410,0,3331,3314,3390,3406,0,3314,3313,3389,3390,0,3389,3395,3502,3494,0,3395,3420,3528,3502,0,3420,3427,3535,3528,0,3427,3437,3544,3535,0,3437,3446,3554,3544,0,3446,3451,3558,3554,0,3451,3454,3560,3558,0,3454,3458,3564,3560,0,3458,3460,3568,3564,0,3460,3464,3570,3568,0,3464,3465,3571,3570,0,3465,3461,3569,3571,0,3461,3459,3566,3569,0,3459,3455,3561,3566,0,3455,3452,3559,3561,0,3452,3447,3556,3559,0,3447,3442,3549,3556,0,3442,3431,3539,3549,0,3431,3425,3533,3539,0,3425,3415,3524,3533,0,3415,3408,3517,3524,0,3408,3344,3475,3517,0,3344,3335,3469,3475,0,3335,3326,3457,3469,0,3326,3321,3445,3457,0,3321,3316,3430,3445,0,3316,3311,3421,3430,0,3311,3307,3409,3421,0,3307,3305,3401,3409,0,3305,3301,3396,3401,0,3301,3297,3391,3396,0,3297,3293,3384,3391,0,3293,3289,3370,3384,0,3289,3279,3358,3370,0,3279,3269,3346,3358,0,3269,3254,3338,3346,0,3254,3244,3328,3338,0,3244,3237,3324,3328,0,3237,3229,3318,3324,0,3229,3224,3312,3318,0,3224,3220,3309,3312,0,3220,3208,3299,3309,0,3208,3213,3303,3299,0,3213,3214,3304,3303,0,3214,3226,3315,3304,0,3226,3230,3319,3315,0,3230,3236,3323,3319,0,3236,3245,3329,3323,0,3245,3256,3339,3329,0,3256,3272,3351,3339,0,3272,3286,3366,3351,0,3286,3291,3376,3366,0,3291,3294,3386,3376,0,3294,3298,3392,3386,0,3298,3302,3399,3392,0,3302,3306,3407,3399,0,3306,3310,3419,3407,0,3310,3317,3432,3419,0,3317,3322,3448,3432,0,3322,3327,3462,3448,0,3327,3336,3470,3462,0,3336,3374,3487,3470,0,3374,3400,3507,3487,0,3400,3405,3513,3507,0,3405,3412,3521,3513,0,3412,3418,3527,3521,0,3418,3424,3532,3527,0,3424,3429,3538,3532,0,3429,3435,3543,3538,0,3435,3439,3546,3543,0,3439,3440,3547,3546,0,3440,3443,3550,3547,0,3443,3441,3548,3550,0,3441,3438,3545,3548,0,3438,3433,3542,3545,0,3433,3428,3536,3542,0,3428,3423,3531,3536,0,3423,3416,3525,3531,0,3416,3410,3518,3525,0,3410,3406,3515,3518,0,3406,3390,3497,3515,0,3390,3389,3494,3497,0,3494,3502,3577,3567,0,3502,3528,3598,3577,0,3528,3535,3603,3598,0,3535,3544,3611,3603,0,3544,3554,3619,3611,0,3554,3558,3622,3619,0,3558,3560,3625,3622,0,3560,3564,3628,3625,0,3564,3568,3630,3628,0,3568,3570,3632,3630,0,3570,3571,3633,3632,0,3571,3569,3631,3633,0,3569,3566,3629,3631,0,3566,3561,3626,3629,0,3561,3559,3623,3626,0,3559,3556,3621,3623,0,3556,3549,3616,3621,0,3549,3539,3607,3616,0,3539,3533,3602,3607,0,3533,3524,3595,3602,0,3524,3517,3589,3595,0,3517,3475,3519,3589,0,3475,3469,3509,3519,0,3469,3457,3503,3509,0,3457,3445,3498,3503,0,3445,3430,3491,3498,0,3430,3421,3486,3491,0,3421,3409,3482,3486,0,3409,3401,3478,3482,0,3401,3396,3473,3478,0,3396,3391,3466,3473,0,3391,3384,3449,3466,0,3384,3370,3434,3449,0,3370,3358,3422,3434,0,3358,3346,3411,3422,0,3346,3338,3402,3411,0,3338,3328,3397,3402,0,3328,3324,3394,3397,0,3324,3318,3387,3394,0,3318,3312,3378,3387,0,3312,3309,3369,3378,0,3309,3299,3333,3369,0,3299,3303,3345,3333,0,3303,3304,3349,3345,0,3304,3315,3385,3349,0,3315,3319,3388,3385,0,3319,3323,3393,3388,0,3323,3329,3398,3393,0,3329,3339,3404,3398,0,3339,3351,3413,3404,0,3351,3366,3426,3413,0,3366,3376,3444,3426,0,3376,3386,3456,3444,0,3386,3392,3468,3456,0,3392,3399,3474,3468,0,3399,3407,3481,3474,0,3407,3419,3485,3481,0,3419,3432,3492,3485,0,3432,3448,3499,3492,0,3448,3462,3505,3499,0,3462,3470,3510,3505,0,3470,3487,3551,3510,0,3487,3507,3582,3551,0,3507,3513,3585,3582,0,3513,3521,3592,3585,0,3521,3527,3597,3592,0,3527,3532,3601,3597,0,3532,3538,3606,3601,0,3538,3543,3609,3606,0,3543,3546,3613,3609,0,3546,3547,3614,3613,0,3547,3550,3617,3614,0,3550,3548,3615,3617,0,3548,3545,3612,3615,0,3545,3542,3608,3612,0,3542,3536,3605,3608,0,3536,3531,3600,3605,0,3531,3525,3596,3600,0,3525,3518,3590,3596,0,3518,3515,3588,3590,0,3515,3497,3572,3588,0,3497,3494,3567,3572,0,3567,3577,3638,3634,0,3577,3598,3654,3638,0,3598,3603,3660,3654,0,3603,3611,3667,3660,0,3611,3619,3674,3667,0,3619,3622,3676,3674,0,3622,3625,3678,3676,0,3625,3628,3680,3678,0,3628,3630,3682,3680,0,3630,3632,3684,3682,0,3632,3633,3685,3684,0,3633,3631,3683,3685,0,3631,3629,3681,3683,0,3629,3626,3679,3681,0,3626,3623,3677,3679,0,3623,3621,3675,3677,0,3621,3616,3673,3675,0,3616,3607,3664,3673,0,3607,3602,3659,3664,0,3602,3595,3652,3659,0,3595,3589,3646,3652,0,3589,3519,3593,3646,0,3519,3509,3584,3593,0,3509,3503,3579,3584,0,3503,3498,3574,3579,0,3498,3491,3562,3574,0,3491,3486,3553,3562,0,3486,3482,3537,3553,0,3482,3478,3526,3537,0,3478,3473,3516,3526,0,3473,3466,3508,3516,0,3466,3449,3501,3508,0,3449,3434,3495,3501,0,3434,3422,3489,3495,0,3422,3411,3483,3489,0,3411,3402,3479,3483,0,3402,3397,3476,3479,0,3397,3394,3472,3476,0,3394,3387,3463,3472,0,3387,3378,3450,3463,0,3378,3369,3436,3450,0,3369,3333,3403,3436,0,3333,3345,3414,3403,0,3345,3349,3417,3414,0,3349,3385,3453,3417,0,3385,3388,3467,3453,0,3388,3393,3471,3467,0,3393,3398,3477,3471,0,3398,3404,3480,3477,0,3404,3413,3484,3480,0,3413,3426,3490,3484,0,3426,3444,3500,3490,0,3444,3456,3504,3500,0,3456,3468,3511,3504,0,3468,3474,3523,3511,0,3474,3481,3534,3523,0,3481,3485,3552,3534,0,3485,3492,3563,3552,0,3492,3499,3576,3563,0,3499,3505,3581,3576,0,3505,3510,3586,3581,0,3510,3551,3620,3586,0,3551,3582,3641,3620,0,3582,3585,3644,3641,0,3585,3592,3650,3644,0,3592,3597,3653,3650,0,3597,3601,3658,3653,0,3601,3606,3662,3658,0,3606,3609,3666,3662,0,3609,3613,3669,3666,0,3613,3614,3670,3669,0,3614,3617,3672,3670,0,3617,3615,3671,3672,0,3615,3612,3668,3671,0,3612,3608,3665,3668,0,3608,3605,3661,3665,0,3605,3600,3657,3661,0,3600,3596,3651,3657,0,3596,3590,3648,3651,0,3590,3588,3645,3648,0,3588,3572,3635,3645,0,3572,3567,3634,3635,0,3634,3638,3689,3687,0,3638,3654,3705,3689,0,3654,3660,3709,3705,0,3660,3667,3717,3709,0,3667,3674,3727,3717,0,3674,3676,3730,3727,0,3676,3678,3733,3730,0,3678,3680,3737,3733,0,3680,3682,3740,3737,0,3682,3684,3742,3740,0,3684,3685,3743,3742,0,3685,3683,3741,3743,0,3683,3681,3738,3741,0,3681,3679,3735,3738,0,3679,3677,3731,3735,0,3677,3675,3728,3731,0,3675,3673,3724,3728,0,3673,3664,3713,3724,0,3664,3659,3708,3713,0,3659,3652,3703,3708,0,3652,3646,3696,3703,0,3646,3593,3663,3696,0,3593,3584,3655,3663,0,3584,3579,3647,3655,0,3579,3574,3642,3647,0,3574,3562,3639,3642,0,3562,3553,3637,3639,0,3553,3537,3627,3637,0,3537,3526,3618,3627,0,3526,3516,3604,3618,0,3516,3508,3594,3604,0,3508,3501,3587,3594,0,3501,3495,3580,3587,0,3495,3489,3575,3580,0,3489,3483,3565,3575,0,3483,3479,3555,3565,0,3479,3476,3540,3555,0,3476,3472,3530,3540,0,3472,3463,3520,3530,0,3463,3450,3512,3520,0,3450,3436,3506,3512,0,3436,3403,3488,3506,0,3403,3414,3493,3488,0,3414,3417,3496,3493,0,3417,3453,3514,3496,0,3453,3467,3522,3514,0,3467,3471,3529,3522,0,3471,3477,3541,3529,0,3477,3480,3557,3541,0,3480,3484,3573,3557,0,3484,3490,3578,3573,0,3490,3500,3583,3578,0,3500,3504,3591,3583,0,3504,3511,3599,3591,0,3511,3523,3610,3599,0,3523,3534,3624,3610,0,3534,3552,3636,3624,0,3552,3563,3640,3636,0,3563,3576,3643,3640,0,3576,3581,3649,3643,0,3581,3586,3656,3649,0,3586,3620,3686,3656,0,3620,3641,3691,3686,0,3641,3644,3693,3691,0,3644,3650,3700,3693,0,3650,3653,3704,3700,0,3653,3658,3707,3704,0,3658,3662,3712,3707,0,3662,3666,3716,3712,0,3666,3669,3719,3716,0,3669,3670,3720,3719,0,3670,3672,3723,3720,0,3672,3671,3721,3723,0,3671,3668,3718,3721,0,3668,3665,3714,3718,0,3665,3661,3710,3714,0,3661,3657,3706,3710,0,3657,3651,3702,3706,0,3651,3648,3697,3702,0,3648,3645,3694,3697,0,3645,3635,3688,3694,0,3635,3634,3687,3688,0,3687,3689,3843,3837,0,3689,3705,3865,3843,0,3705,3709,3877,3865,0,3709,3717,3888,3877,0,3717,3727,3905,3888,0,3727,3730,3910,3905,0,3730,3733,3914,3910,0,3733,3737,3918,3914,0,3737,3740,3921,3918,0,3740,3742,3924,3921,0,3742,3743,3925,3924,0,3743,3741,3923,3925,0,3741,3738,3919,3923,0,3738,3735,3916,3919,0,3735,3731,3913,3916,0,3731,3728,3908,3913,0,3728,3724,3898,3908,0,3724,3713,3885,3898,0,3713,3708,3875,3885,0,3708,3703,3864,3875,0,3703,3696,3853,3864,0,3696,3663,3826,3853,0,3663,3655,3820,3826,0,3655,3647,3814,3820,0,3647,3642,3808,3814,0,3642,3639,3802,3808,0,3639,3637,3797,3802,0,3637,3627,3791,3797,0,3627,3618,3786,3791,0,3618,3604,3780,3786,0,3604,3594,3775,3780,0,3594,3587,3769,3775,0,3587,3580,3765,3769,0,3580,3575,3760,3765,0,3575,3565,3756,3760,0,3565,3555,3752,3756,0,3555,3540,3748,3752,0,3540,3530,3745,3748,0,3530,3520,3732,3745,0,3520,3512,3722,3732,0,3512,3506,3711,3722,0,3506,3488,3690,3711,0,3488,3493,3695,3690,0,3493,3496,3698,3695,0,3496,3514,3725,3698,0,3514,3522,3734,3725,0,3522,3529,3744,3734,0,3529,3541,3749,3744,0,3541,3557,3753,3749,0,3557,3573,3757,3753,0,3573,3578,3762,3757,0,3578,3583,3767,3762,0,3583,3591,3773,3767,0,3591,3599,3777,3773,0,3599,3610,3782,3777,0,3610,3624,3790,3782,0,3624,3636,3796,3790,0,3636,3640,3803,3796,0,3640,3643,3809,3803,0,3643,3649,3815,3809,0,3649,3656,3821,3815,0,3656,3686,3833,3821,0,3686,3691,3847,3833,0,3691,3693,3851,3847,0,3693,3700,3858,3851,0,3700,3704,3866,3858,0,3704,3707,3873,3866,0,3707,3712,3880,3873,0,3712,3716,3886,3880,0,3716,3719,3892,3886,0,3719,3720,3896,3892,0,3720,3723,3897,3896,0,3723,3721,3895,3897,0,3721,3718,3891,3895,0,3718,3714,3884,3891,0,3714,3710,3878,3884,0,3710,3706,3869,3878,0,3706,3702,3863,3869,0,3702,3697,3855,3863,0,3697,3694,3852,3855,0,3694,3688,3838,3852,0,3688,3687,3837,3838,0,3837,3843,3844,3839,0,3843,3865,3871,3844,0,3865,3877,3882,3871,0,3877,3888,3900,3882,0,3888,3905,3909,3900,0,3905,3910,3915,3909,0,3910,3914,3920,3915,0,3914,3918,3926,3920,0,3918,3921,3928,3926,0,3921,3924,3930,3928,0,3924,3925,3931,3930,0,3925,3923,3929,3931,0,3923,3919,3927,3929,0,3919,3916,3922,3927,0,3916,3913,3917,3922,0,3913,3908,3912,3917,0,3908,3898,3907,3912,0,3898,3885,3894,3907,0,3885,3875,3881,3894,0,3875,3864,3868,3881,0,3864,3853,3857,3868,0,3853,3826,3827,3857,0,3826,3820,3823,3827,0,3820,3814,3816,3823,0,3814,3808,3811,3816,0,3808,3802,3805,3811,0,3802,3797,3799,3805,0,3797,3791,3793,3799,0,3791,3786,3787,3793,0,3786,3780,3781,3787,0,3780,3775,3776,3781,0,3775,3769,3772,3776,0,3769,3765,3766,3772,0,3765,3760,3761,3766,0,3760,3756,3758,3761,0,3756,3752,3754,3758,0,3752,3748,3750,3754,0,3748,3745,3747,3750,0,3745,3732,3736,3747,0,3732,3722,3726,3736,0,3722,3711,3715,3726,0,3711,3690,3692,3715,0,3690,3695,3699,3692,0,3695,3698,3701,3699,0,3698,3725,3729,3701,0,3725,3734,3739,3729,0,3734,3744,3746,3739,0,3744,3749,3751,3746,0,3749,3753,3755,3751,0,3753,3757,3759,3755,0,3757,3762,3763,3759,0,3762,3767,3768,3763,0,3767,3773,3774,3768,0,3773,3777,3778,3774,0,3777,3782,3784,3778,0,3782,3790,3792,3784,0,3790,3796,3798,3792,0,3796,3803,3806,3798,0,3803,3809,3812,3806,0,3809,3815,3818,3812,0,3815,3821,3824,3818,0,3821,3833,3834,3824,0,3833,3847,3848,3834,0,3847,3851,3854,3848,0,3851,3858,3862,3854,0,3858,3866,3872,3862,0,3866,3873,3879,3872,0,3873,3880,3887,3879,0,3880,3886,3899,3887,0,3886,3892,3902,3899,0,3892,3896,3904,3902,0,3896,3897,3906,3904,0,3897,3895,3903,3906,0,3895,3891,3901,3903,0,3891,3884,3893,3901,0,3884,3878,3883,3893,0,3878,3869,3876,3883,0,3869,3863,3867,3876,0,3863,3855,3860,3867,0,3855,3852,3856,3860,0,3852,3838,3841,3856,0,3838,3837,3839,3841,0,3839,3844,3935,3933,0,3844,3871,3947,3935,0,3871,3882,3952,3947,0,3882,3900,3959,3952,0,3900,3909,3967,3959,0,3909,3915,3970,3967,0,3915,3920,3973,3970,0,3920,3926,3976,3973,0,3926,3928,3978,3976,0,3928,3930,3980,3978,0,3930,3931,3981,3980,0,3931,3929,3979,3981,0,3929,3927,3977,3979,0,3927,3922,3974,3977,0,3922,3917,3971,3974,0,3917,3912,3969,3971,0,3912,3907,3965,3969,0,3907,3894,3957,3965,0,3894,3881,3951,3957,0,3881,3868,3946,3951,0,3868,3857,3940,3946,0,3857,3827,3911,3940,0,3827,3823,3889,3911,0,3823,3816,3870,3889,0,3816,3811,3859,3870,0,3811,3805,3849,3859,0,3805,3799,3846,3849,0,3799,3793,3842,3846,0,3793,3787,3836,3842,0,3787,3781,3832,3836,0,3781,3776,3830,3832,0,3776,3772,3828,3830,0,3772,3766,3822,3828,0,3766,3761,3817,3822,0,3761,3758,3810,3817,0,3758,3754,3804,3810,0,3754,3750,3800,3804,0,3750,3747,3795,3800,0,3747,3736,3788,3795,0,3736,3726,3783,3788,0,3726,3715,3779,3783,0,3715,3692,3764,3779,0,3692,3699,3770,3764,0,3699,3701,3771,3770,0,3701,3729,3785,3771,0,3729,3739,3789,3785,0,3739,3746,3794,3789,0,3746,3751,3801,3794,0,3751,3755,3807,3801,0,3755,3759,3813,3807,0,3759,3763,3819,3813,0,3763,3768,3825,3819,0,3768,3774,3829,3825,0,3774,3778,3831,3829,0,3778,3784,3835,3831,0,3784,3792,3840,3835,0,3792,3798,3845,3840,0,3798,3806,3850,3845,0,3806,3812,3861,3850,0,3812,3818,3874,3861,0,3818,3824,3890,3874,0,3824,3834,3932,3890,0,3834,3848,3937,3932,0,3848,3854,3938,3937,0,3854,3862,3944,3938,0,3862,3872,3948,3944,0,3872,3879,3950,3948,0,3879,3887,3955,3950,0,3887,3899,3958,3955,0,3899,3902,3961,3958,0,3902,3904,3963,3961,0,3904,3906,3964,3963,0,3906,3903,3962,3964,0,3903,3901,3960,3962,0,3901,3893,3956,3960,0,3893,3883,3953,3956,0,3883,3876,3949,3953,0,3876,3867,3945,3949,0,3867,3860,3942,3945,0,3860,3856,3939,3942,0,3856,3841,3934,3939,0,3841,3839,3933,3934,0,3933,3935,4079,4073,0,3935,3947,4099,4079,0,3947,3952,4106,4099,0,3952,3959,4114,4106,0,3959,3967,4122,4114,0,3967,3970,4126,4122,0,3970,3973,4128,4126,0,3973,3976,4132,4128,0,3976,3978,4135,4132,0,3978,3980,4137,4135,0,3980,3981,4138,4137,0,3981,3979,4136,4138,0,3979,3977,4134,4136,0,3977,3974,4130,4134,0,3974,3971,4127,4130,0,3971,3969,4125,4127,0,3969,3965,4121,4125,0,3965,3957,4112,4121,0,3957,3951,4105,4112,0,3951,3946,4098,4105,0,3946,3940,4091,4098,0,3940,3911,4058,4091,0,3911,3889,4052,4058,0,3889,3870,4046,4052,0,3870,3859,4040,4046,0,3859,3849,4036,4040,0,3849,3846,4030,4036,0,3846,3842,4024,4030,0,3842,3836,4016,4024,0,3836,3832,4011,4016,0,3832,3830,4007,4011,0,3830,3828,4001,4007,0,3828,3822,3996,4001,0,3822,3817,3993,3996,0,3817,3810,3991,3993,0,3810,3804,3987,3991,0,3804,3800,3984,3987,0,3800,3795,3983,3984,0,3795,3788,3972,3983,0,3788,3783,3966,3972,0,3783,3779,3954,3966,0,3779,3764,3936,3954,0,3764,3770,3941,3936,0,3770,3771,3943,3941,0,3771,3785,3968,3943,0,3785,3789,3975,3968,0,3789,3794,3982,3975,0,3794,3801,3985,3982,0,3801,3807,3988,3985,0,3807,3813,3992,3988,0,3813,3819,3994,3992,0,3819,3825,3999,3994,0,3825,3829,4004,3999,0,3829,3831,4010,4004,0,3831,3835,4015,4010,0,3835,3840,4021,4015,0,3840,3845,4027,4021,0,3845,3850,4037,4027,0,3850,3861,4043,4037,0,3861,3874,4048,4043,0,3874,3890,4053,4048,0,3890,3932,4069,4053,0,3932,3937,4084,4069,0,3937,3938,4089,4084,0,3938,3944,4096,4089,0,3944,3948,4101,4096,0,3948,3950,4104,4101,0,3950,3955,4109,4104,0,3955,3958,4113,4109,0,3958,3961,4116,4113,0,3961,3963,4118,4116,0,3963,3964,4119,4118,0,3964,3962,4117,4119,0,3962,3960,4115,4117,0,3960,3956,4111,4115,0,3956,3953,4107,4111,0,3953,3949,4103,4107,0,3949,3945,4097,4103,0,3945,3942,4092,4097,0,3942,3939,4090,4092,0,3939,3934,4075,4090,0,3934,3933,4073,4075,0,4073,4079,4139,4129,0,4079,4099,4151,4139,0,4099,4106,4157,4151,0,4106,4114,4164,4157,0,4114,4122,4172,4164,0,4122,4126,4174,4172,0,4126,4128,4180,4174,0,4128,4132,4184,4180,0,4132,4135,4186,4184,0,4135,4137,4189,4186,0,4137,4138,4190,4189,0,4138,4136,4188,4190,0,4136,4134,4185,4188,0,4134,4130,4182,4185,0,4130,4127,4178,4182,0,4127,4125,4173,4178,0,4125,4121,4171,4173,0,4121,4112,4161,4171,0,4112,4105,4156,4161,0,4105,4098,4150,4156,0,4098,4091,4144,4150,0,4091,4058,4095,4144,0,4058,4052,4087,4095,0,4052,4046,4081,4087,0,4046,4040,4077,4081,0,4040,4036,4071,4077,0,4036,4030,4067,4071,0,4030,4024,4063,4067,0,4024,4016,4059,4063,0,4016,4011,4054,4059,0,4011,4007,4049,4054,0,4007,4001,4042,4049,0,4001,3996,4035,4042,0,3996,3993,4028,4035,0,3993,3991,4022,4028,0,3991,3987,4017,4022,0,3987,3984,4012,4017,0,3984,3983,4009,4012,0,3983,3972,4002,4009,0,3972,3966,3998,4002,0,3966,3954,3995,3998,0,3954,3936,3986,3995,0,3936,3941,3989,3986,0,3941,3943,3990,3989,0,3943,3968,4000,3990,0,3968,3975,4005,4000,0,3975,3982,4008,4005,0,3982,3985,4013,4008,0,3985,3988,4019,4013,0,3988,3992,4026,4019,0,3992,3994,4032,4026,0,3994,3999,4038,4032,0,3999,4004,4044,4038,0,4004,4010,4050,4044,0,4010,4015,4056,4050,0,4015,4021,4062,4056,0,4021,4027,4066,4062,0,4027,4037,4072,4066,0,4037,4043,4078,4072,0,4043,4048,4083,4078,0,4048,4053,4088,4083,0,4053,4069,4120,4088,0,4069,4084,4140,4120,0,4084,4089,4142,4140,0,4089,4096,4147,4142,0,4096,4101,4152,4147,0,4101,4104,4155,4152,0,4104,4109,4159,4155,0,4109,4113,4163,4159,0,4113,4116,4166,4163,0,4116,4118,4168,4166,0,4118,4119,4169,4168,0,4119,4117,4167,4169,0,4117,4115,4165,4167,0,4115,4111,4160,4165,0,4111,4107,4158,4160,0,4107,4103,4153,4158,0,4103,4097,4149,4153,0,4097,4092,4145,4149,0,4092,4090,4143,4145,0,4090,4075,4131,4143,0,4075,4073,4129,4131,0,4129,4139,4154,4146,0,4139,4151,4193,4154,0,4151,4157,4198,4193,0,4157,4164,4205,4198,0,4164,4172,4214,4205,0,4172,4174,4216,4214,0,4174,4180,4220,4216,0,4180,4184,4222,4220,0,4184,4186,4224,4222,0,4186,4189,4226,4224,0,4189,4190,4227,4226,0,4190,4188,4225,4227,0,4188,4185,4223,4225,0,4185,4182,4221,4223,0,4182,4178,4218,4221,0,4178,4173,4215,4218,0,4173,4171,4212,4215,0,4171,4161,4203,4212,0,4161,4156,4199,4203,0,4156,4150,4192,4199,0,4150,4144,4181,4192,0,4144,4095,4133,4181,0,4095,4087,4123,4133,0,4087,4081,4108,4123,0,4081,4077,4100,4108,0,4077,4071,4093,4100,0,4071,4067,4086,4093,0,4067,4063,4082,4086,0,4063,4059,4076,4082,0,4059,4054,4070,4076,0,4054,4049,4065,4070,0,4049,4042,4061,4065,0,4042,4035,4057,4061,0,4035,4028,4051,4057,0,4028,4022,4045,4051,0,4022,4017,4039,4045,0,4017,4012,4033,4039,0,4012,4009,4031,4033,0,4009,4002,4023,4031,0,4002,3998,4018,4023,0,3998,3995,4014,4018,0,3995,3986,3997,4014,0,3986,3989,4003,3997,0,3989,3990,4006,4003,0,3990,4000,4020,4006,0,4000,4005,4025,4020,0,4005,4008,4029,4025,0,4008,4013,4034,4029,0,4013,4019,4041,4034,0,4019,4026,4047,4041,0,4026,4032,4055,4047,0,4032,4038,4060,4055,0,4038,4044,4064,4060,0,4044,4050,4068,4064,0,4050,4056,4074,4068,0,4056,4062,4080,4074,0,4062,4066,4085,4080,0,4066,4072,4094,4085,0,4072,4078,4102,4094,0,4078,4083,4110,4102,0,4083,4088,4124,4110,0,4088,4120,4141,4124,0,4120,4140,4170,4141,0,4140,4142,4176,4170,0,4142,4147,4187,4176,0,4147,4152,4194,4187,0,4152,4155,4196,4194,0,4155,4159,4201,4196,0,4159,4163,4204,4201,0,4163,4166,4208,4204,0,4166,4168,4210,4208,0,4168,4169,4211,4210,0,4169,4167,4209,4211,0,4167,4165,4206,4209,0,4165,4160,4202,4206,0,4160,4158,4200,4202,0,4158,4153,4195,4200,0,4153,4149,4191,4195,0,4149,4145,4183,4191,0,4145,4143,4177,4183,0,4143,4131,4148,4177,0,4131,4129,4146,4148,0,4146,4154,4309,4303,0,4154,4193,4328,4309,0,4193,4198,4336,4328,0,4198,4205,4346,4336,0,4205,4214,4355,4346,0,4214,4216,4360,4355,0,4216,4220,4362,4360,0,4220,4222,4364,4362,0,4222,4224,4369,4364,0,4224,4226,4372,4369,0,4226,4227,4373,4372,0,4227,4225,4371,4373,0,4225,4223,4367,4371,0,4223,4221,4363,4367,0,4221,4218,4361,4363,0,4218,4215,4359,4361,0,4215,4212,4353,4359,0,4212,4203,4345,4353,0,4203,4199,4337,4345,0,4199,4192,4329,4337,0,4192,4181,4322,4329,0,4181,4133,4288,4322,0,4133,4123,4281,4288,0,4123,4108,4274,4281,0,4108,4100,4269,4274,0,4100,4093,4264,4269,0,4093,4086,4260,4264,0,4086,4082,4254,4260,0,4082,4076,4249,4254,0,4076,4070,4247,4249,0,4070,4065,4243,4247,0,4065,4061,4240,4243,0,4061,4057,4238,4240,0,4057,4051,4236,4238,0,4051,4045,4234,4236,0,4045,4039,4232,4234,0,4039,4033,4230,4232,0,4033,4031,4229,4230,0,4031,4023,4217,4229,0,4023,4018,4207,4217,0,4018,4014,4197,4207,0,4014,3997,4162,4197,0,3997,4003,4175,4162,0,4003,4006,4179,4175,0,4006,4020,4213,4179,0,4020,4025,4219,4213,0,4025,4029,4228,4219,0,4029,4034,4231,4228,0,4034,4041,4233,4231,0,4041,4047,4235,4233,0,4047,4055,4237,4235,0,4055,4060,4239,4237,0,4060,4064,4242,4239,0,4064,4068,4245,4242,0,4068,4074,4248,4245,0,4074,4080,4252,4248,0,4080,4085,4259,4252,0,4085,4094,4265,4259,0,4094,4102,4271,4265,0,4102,4110,4277,4271,0,4110,4124,4282,4277,0,4124,4141,4298,4282,0,4141,4170,4314,4298,0,4170,4176,4319,4314,0,4176,4187,4325,4319,0,4187,4194,4330,4325,0,4194,4196,4335,4330,0,4196,4201,4341,4335,0,4201,4204,4347,4341,0,4204,4208,4349,4347,0,4208,4210,4351,4349,0,4210,4211,4352,4351,0,4211,4209,4350,4352,0,4209,4206,4348,4350,0,4206,4202,4344,4348,0,4202,4200,4338,4344,0,4200,4195,4334,4338,0,4195,4191,4327,4334,0,4191,4183,4321,4327,0,4183,4177,4318,4321,0,4177,4148,4304,4318,0,4148,4146,4303,4304,0,4303,4309,4385,4383,0,4309,4328,4400,4385,0,4328,4336,4406,4400,0,4336,4346,4414,4406,0,4346,4355,4425,4414,0,4355,4360,4431,4425,0,4360,4362,4434,4431,0,4362,4364,4438,4434,0,4364,4369,4443,4438,0,4369,4372,4446,4443,0,4372,4373,4447,4446,0,4373,4371,4445,4447,0,4371,4367,4440,4445,0,4367,4363,4436,4440,0,4363,4361,4433,4436,0,4361,4359,4429,4433,0,4359,4353,4423,4429,0,4353,4345,4413,4423,0,4345,4337,4407,4413,0,4337,4329,4401,4407,0,4329,4322,4396,4401,0,4322,4288,4374,4396,0,4288,4281,4365,4374,0,4281,4274,4354,4365,0,4274,4269,4340,4354,0,4269,4264,4331,4340,0,4264,4260,4324,4331,0,4260,4254,4316,4324,0,4254,4249,4311,4316,0,4249,4247,4306,4311,0,4247,4243,4300,4306,0,4243,4240,4294,4300,0,4240,4238,4290,4294,0,4238,4236,4285,4290,0,4236,4234,4279,4285,0,4234,4232,4273,4279,0,4232,4230,4267,4273,0,4230,4229,4263,4267,0,4229,4217,4258,4263,0,4217,4207,4253,4258,0,4207,4197,4251,4253,0,4197,4162,4241,4251,0,4162,4175,4244,4241,0,4175,4179,4246,4244,0,4179,4213,4256,4246,0,4213,4219,4261,4256,0,4219,4228,4262,4261,0,4228,4231,4268,4262,0,4231,4233,4275,4268,0,4233,4235,4280,4275,0,4235,4237,4289,4280,0,4237,4239,4293,4289,0,4239,4242,4297,4293,0,4242,4245,4301,4297,0,4245,4248,4308,4301,0,4248,4252,4313,4308,0,4252,4259,4320,4313,0,4259,4265,4332,4320,0,4265,4271,4342,4332,0,4271,4277,4357,4342,0,4277,4282,4366,4357,0,4282,4298,4381,4366,0,4298,4314,4388,4381,0,4314,4319,4393,4388,0,4319,4325,4397,4393,0,4325,4330,4402,4397,0,4330,4335,4405,4402,0,4335,4341,4410,4405,0,4341,4347,4415,4410,0,4347,4349,4418,4415,0,4349,4351,4420,4418,0,4351,4352,4421,4420,0,4352,4350,4419,4421,0,4350,4348,4416,4419,0,4348,4344,4412,4416,0,4344,4338,4408,4412,0,4338,4334,4403,4408,0,4334,4327,4398,4403,0,4327,4321,4395,4398,0,4321,4318,4392,4395,0,4318,4304,4384,4392,0,4304,4303,4383,4384,0,4383,4385,4399,4391,0,4385,4400,4437,4399,0,4400,4406,4450,4437,0,4406,4414,4458,4450,0,4414,4425,4467,4458,0,4425,4431,4470,4467,0,4431,4434,4472,4470,0,4434,4438,4475,4472,0,4438,4443,4478,4475,0,4443,4446,4480,4478,0,4446,4447,4481,4480,0,4447,4445,4479,4481,0,4445,4440,4476,4479,0,4440,4436,4474,4476,0,4436,4433,4471,4474,0,4433,4429,4469,4471,0,4429,4423,4465,4469,0,4423,4413,4457,4465,0,4413,4407,4451,4457,0,4407,4401,4439,4451,0,4401,4396,4428,4439,0,4396,4374,4382,4428,0,4374,4365,4379,4382,0,4365,4354,4377,4379,0,4354,4340,4375,4377,0,4340,4331,4368,4375,0,4331,4324,4358,4368,0,4324,4316,4343,4358,0,4316,4311,4333,4343,0,4311,4306,4323,4333,0,4306,4300,4315,4323,0,4300,4294,4310,4315,0,4294,4290,4305,4310,0,4290,4285,4299,4305,0,4285,4279,4295,4299,0,4279,4273,4291,4295,0,4273,4267,4286,4291,0,4267,4263,4284,4286,0,4263,4258,4276,4284,0,4258,4253,4270,4276,0,4253,4251,4266,4270,0,4251,4241,4250,4266,0,4241,4244,4255,4250,0,4244,4246,4257,4255,0,4246,4256,4272,4257,0,4256,4261,4278,4272,0,4261,4262,4283,4278,0,4262,4268,4287,4283,0,4268,4275,4292,4287,0,4275,4280,4296,4292,0,4280,4289,4302,4296,0,4289,4293,4307,4302,0,4293,4297,4312,4307,0,4297,4301,4317,4312,0,4301,4308,4326,4317,0,4308,4313,4339,4326,0,4313,4320,4356,4339,0,4320,4332,4370,4356,0,4332,4342,4376,4370,0,4342,4357,4378,4376,0,4357,4366,4380,4378,0,4366,4381,4387,4380,0,4381,4388,4409,4387,0,4388,4393,4424,4409,0,4393,4397,4432,4424,0,4397,4402,4442,4432,0,4402,4405,4449,4442,0,4405,4410,4455,4449,0,4410,4415,4459,4455,0,4415,4418,4461,4459,0,4418,4420,4463,4461,0,4420,4421,4464,4463,0,4421,4419,4462,4464,0,4419,4416,4460,4462,0,4416,4412,4456,4460,0,4412,4408,4452,4456,0,4408,4403,4448,4452,0,4403,4398,4435,4448,0,4398,4395,4426,4435,0,4395,4392,4422,4426,0,4392,4384,4394,4422,0,4384,4383,4391,4394,0,4391,4399,4537,4532,0,4399,4437,4556,4537,0,4437,4450,4564,4556,0,4450,4458,4575,4564,0,4458,4467,4583,4575,0,4467,4470,4589,4583,0,4470,4472,4591,4589,0,4472,4475,4594,4591,0,4475,4478,4598,4594,0,4478,4480,4600,4598,0,4480,4481,4601,4600,0,4481,4479,4599,4601,0,4479,4476,4597,4599,0,4476,4474,4593,4597,0,4474,4471,4590,4593,0,4471,4469,4587,4590,0,4469,4465,4582,4587,0,4465,4457,4574,4582,0,4457,4451,4567,4574,0,4451,4439,4558,4567,0,4439,4428,4551,4558,0,4428,4382,4521,4551,0,4382,4379,4518,4521,0,4379,4377,4513,4518,0,4377,4375,4509,4513,0,4375,4368,4505,4509,0,4368,4358,4501,4505,0,4358,4343,4498,4501,0,4343,4333,4495,4498,0,4333,4323,4491,4495,0,4323,4315,4489,4491,0,4315,4310,4486,4489,0,4310,4305,4484,4486,0,4305,4299,4482,4484,0,4299,4295,4473,4482,0,4295,4291,4466,4473,0,4291,4286,4454,4466,0,4286,4284,4444,4454,0,4284,4276,4427,4444,0,4276,4270,4411,4427,0,4270,4266,4404,4411,0,4266,4250,4386,4404,0,4250,4255,4389,4386,0,4255,4257,4390,4389,0,4257,4272,4417,4390,0,4272,4278,4430,4417,0,4278,4283,4441,4430,0,4283,4287,4453,4441,0,4287,4292,4468,4453,0,4292,4296,4477,4468,0,4296,4302,4483,4477,0,4302,4307,4485,4483,0,4307,4312,4487,4485,0,4312,4317,4490,4487,0,4317,4326,4494,4490,0,4326,4339,4496,4494,0,4339,4356,4500,4496,0,4356,4370,4506,4500,0,4370,4376,4510,4506,0,4376,4378,4514,4510,0,4378,4380,4517,4514,0,4380,4387,4529,4517,0,4387,4409,4542,4529,0,4409,4424,4547,4542,0,4424,4432,4554,4547,0,4432,4442,4559,4554,0,4442,4449,4565,4559,0,4449,4455,4571,4565,0,4455,4459,4576,4571,0,4459,4461,4578,4576,0,4461,4463,4580,4578,0,4463,4464,4581,4580,0,4464,4462,4579,4581,0,4462,4460,4577,4579,0,4460,4456,4572,4577,0,4456,4452,4566,4572,0,4452,4448,4563,4566,0,4448,4435,4555,4563,0,4435,4426,4549,4555,0,4426,4422,4546,4549,0,4422,4394,4533,4546,0,4394,4391,4532,4533,0,4532,4537,4620,4615,0,4537,4556,4637,4620,0,4556,4564,4644,4637,0,4564,4575,4652,4644,0,4575,4583,4665,4652,0,4583,4589,4667,4665,0,4589,4591,4670,4667,0,4591,4594,4674,4670,0,4594,4598,4676,4674,0,4598,4600,4678,4676,0,4600,4601,4679,4678,0,4601,4599,4677,4679,0,4599,4597,4675,4677,0,4597,4593,4673,4675,0,4593,4590,4669,4673,0,4590,4587,4666,4669,0,4587,4582,4663,4666,0,4582,4574,4653,4663,0,4574,4567,4647,4653,0,4567,4558,4639,4647,0,4558,4551,4632,4639,0,4551,4521,4607,4632,0,4521,4518,4604,4607,0,4518,4513,4592,4604,0,4513,4509,4584,4592,0,4509,4505,4569,4584,0,4505,4501,4560,4569,0,4501,4498,4550,4560,0,4498,4495,4543,4550,0,4495,4491,4538,4543,0,4491,4489,4534,4538,0,4489,4486,4530,4534,0,4486,4484,4525,4530,0,4484,4482,4522,4525,0,4482,4473,4519,4522,0,4473,4466,4515,4519,0,4466,4454,4512,4515,0,4454,4444,4508,4512,0,4444,4427,4503,4508,0,4427,4411,4499,4503,0,4411,4404,4497,4499,0,4404,4386,4488,4497,0,4386,4389,4492,4488,0,4389,4390,4493,4492,0,4390,4417,4502,4493,0,4417,4430,4504,4502,0,4430,4441,4507,4504,0,4441,4453,4511,4507,0,4453,4468,4516,4511,0,4468,4477,4520,4516,0,4477,4483,4524,4520,0,4483,4485,4527,4524,0,4485,4487,4531,4527,0,4487,4490,4535,4531,0,4490,4494,4540,4535,0,4494,4496,4548,4540,0,4496,4500,4557,4548,0,4500,4506,4570,4557,0,4506,4510,4586,4570,0,4510,4514,4596,4586,0,4514,4517,4603,4596,0,4517,4529,4613,4603,0,4529,4542,4625,4613,0,4542,4547,4630,4625,0,4547,4554,4634,4630,0,4554,4559,4640,4634,0,4559,4565,4645,4640,0,4565,4571,4649,4645,0,4571,4576,4656,4649,0,4576,4578,4658,4656,0,4578,4580,4660,4658,0,4580,4581,4661,4660,0,4581,4579,4659,4661,0,4579,4577,4657,4659,0,4577,4572,4650,4657,0,4572,4566,4646,4650,0,4566,4563,4641,4646,0,4563,4555,4636,4641,0,4555,4549,4631,4636,0,4549,4546,4629,4631,0,4546,4533,4617,4629,0,4533,4532,4615,4617,0,4615,4620,4690,4685,0,4620,4637,4704,4690,0,4637,4644,4710,4704,0,4644,4652,4718,4710,0,4652,4665,4730,4718,0,4665,4667,4732,4730,0,4667,4670,4735,4732,0,4670,4674,4738,4735,0,4674,4676,4740,4738,0,4676,4678,4742,4740,0,4678,4679,4743,4742,0,4679,4677,4741,4743,0,4677,4675,4739,4741,0,4675,4673,4737,4739,0,4673,4669,4734,4737,0,4669,4666,4731,4734,0,4666,4663,4729,4731,0,4663,4653,4719,4729,0,4653,4647,4714,4719,0,4647,4639,4706,4714,0,4639,4632,4700,4706,0,4632,4607,4668,4700,0,4607,4604,4655,4668,0,4604,4592,4642,4655,0,4592,4584,4633,4642,0,4584,4569,4627,4633,0,4569,4560,4623,4627,0,4560,4550,4619,4623,0,4550,4543,4616,4619,0,4543,4538,4612,4616,0,4538,4534,4610,4612,0,4534,4530,4608,4610,0,4530,4525,4605,4608,0,4525,4522,4595,4605,0,4522,4519,4585,4595,0,4519,4515,4568,4585,0,4515,4512,4562,4568,0,4512,4508,4553,4562,0,4508,4503,4544,4553,0,4503,4499,4539,4544,0,4499,4497,4536,4539,0,4497,4488,4523,4536,0,4488,4492,4526,4523,0,4492,4493,4528,4526,0,4493,4502,4541,4528,0,4502,4504,4545,4541,0,4504,4507,4552,4545,0,4507,4511,4561,4552,0,4511,4516,4573,4561,0,4516,4520,4588,4573,0,4520,4524,4602,4588,0,4524,4527,4606,4602,0,4527,4531,4609,4606,0,4531,4535,4611,4609,0,4535,4540,4614,4611,0,4540,4548,4618,4614,0,4548,4557,4622,4618,0,4557,4570,4628,4622,0,4570,4586,4635,4628,0,4586,4596,4643,4635,0,4596,4603,4654,4643,0,4603,4613,4684,4654,0,4613,4625,4693,4684,0,4625,4630,4697,4693,0,4630,4634,4701,4697,0,4634,4640,4707,4701,0,4640,4645,4712,4707,0,4645,4649,4715,4712,0,4649,4656,4720,4715,0,4656,4658,4723,4720,0,4658,4660,4725,4723,0,4660,4661,4727,4725,0,4661,4659,4724,4727,0,4659,4657,4721,4724,0,4657,4650,4716,4721,0,4650,4646,4713,4716,0,4646,4641,4708,4713,0,4641,4636,4703,4708,0,4636,4631,4698,4703,0,4631,4629,4696,4698,0,4629,4617,4687,4696,0,4617,4615,4685,4687,0,4685,4690,4777,4772,0,4690,4704,4791,4777,0,4704,4710,4796,4791,0,4710,4718,4804,4796,0,4718,4730,4814,4804,0,4730,4732,4818,4814,0,4732,4735,4821,4818,0,4735,4738,4824,4821,0,4738,4740,4827,4824,0,4740,4742,4830,4827,0,4742,4743,4831,4830,0,4743,4741,4829,4831,0,4741,4739,4826,4829,0,4739,4737,4823,4826,0,4737,4734,4819,4823,0,4734,4731,4817,4819,0,4731,4729,4813,4817,0,4729,4719,4805,4813,0,4719,4714,4799,4805,0,4714,4706,4792,4799,0,4706,4700,4787,4792,0,4700,4668,4765,4787,0,4668,4655,4762,4765,0,4655,4642,4757,4762,0,4642,4633,4753,4757,0,4633,4627,4749,4753,0,4627,4623,4746,4749,0,4623,4619,4736,4746,0,4619,4616,4726,4736,0,4616,4612,4711,4726,0,4612,4610,4702,4711,0,4610,4608,4695,4702,0,4608,4605,4692,4695,0,4605,4595,4689,4692,0,4595,4585,4686,4689,0,4585,4568,4682,4686,0,4568,4562,4681,4682,0,4562,4553,4672,4681,0,4553,4544,4662,4672,0,4544,4539,4648,4662,0,4539,4536,4638,4648,0,4536,4523,4621,4638,0,4523,4526,4624,4621,0,4526,4528,4626,4624,0,4528,4541,4651,4626,0,4541,4545,4664,4651,0,4545,4552,4671,4664,0,4552,4561,4680,4671,0,4561,4573,4683,4680,0,4573,4588,4688,4683,0,4588,4602,4691,4688,0,4602,4606,4694,4691,0,4606,4609,4699,4694,0,4609,4611,4705,4699,0,4611,4614,4717,4705,0,4614,4618,4733,4717,0,4618,4622,4745,4733,0,4622,4628,4748,4745,0,4628,4635,4754,4748,0,4635,4643,4758,4754,0,4643,4654,4761,4758,0,4654,4684,4770,4761,0,4684,4693,4781,4770,0,4693,4697,4784,4781,0,4697,4701,4788,4784,0,4701,4707,4794,4788,0,4707,4712,4797,4794,0,4712,4715,4801,4797,0,4715,4720,4806,4801,0,4720,4723,4809,4806,0,4723,4725,4811,4809,0,4725,4727,4812,4811,0,4727,4724,4810,4812,0,4724,4721,4807,4810,0,4721,4716,4803,4807,0,4716,4713,4798,4803,0,4713,4708,4795,4798,0,4708,4703,4789,4795,0,4703,4698,4785,4789,0,4698,4696,4783,4785,0,4696,4687,4774,4783,0,4687,4685,4772,4774,0,4772,4777,4852,4847,0,4777,4791,4870,4852,0,4791,4796,4876,4870,0,4796,4804,4885,4876,0,4804,4814,4897,4885,0,4814,4818,4899,4897,0,4818,4821,4904,4899,0,4821,4824,4907,4904,0,4824,4827,4909,4907,0,4827,4830,4911,4909,0,4830,4831,4912,4911,0,4831,4829,4910,4912,0,4829,4826,4908,4910,0,4826,4823,4906,4908,0,4823,4819,4903,4906,0,4819,4817,4898,4903,0,4817,4813,4896,4898,0,4813,4805,4886,4896,0,4805,4799,4881,4886,0,4799,4792,4871,4881,0,4792,4787,4864,4871,0,4787,4765,4839,4864,0,4765,4762,4836,4839,0,4762,4757,4832,4836,0,4757,4753,4825,4832,0,4753,4749,4816,4825,0,4749,4746,4802,4816,0,4746,4736,4793,4802,0,4736,4726,4786,4793,0,4726,4711,4780,4786,0,4711,4702,4778,4780,0,4702,4695,4775,4778,0,4695,4692,4771,4775,0,4692,4689,4768,4771,0,4689,4686,4766,4768,0,4686,4682,4763,4766,0,4682,4681,4760,4763,0,4681,4672,4756,4760,0,4672,4662,4751,4756,0,4662,4648,4747,4751,0,4648,4638,4744,4747,0,4638,4621,4709,4744,0,4621,4624,4722,4709,0,4624,4626,4728,4722,0,4626,4651,4750,4728,0,4651,4664,4752,4750,0,4664,4671,4755,4752,0,4671,4680,4759,4755,0,4680,4683,4764,4759,0,4683,4688,4767,4764,0,4688,4691,4769,4767,0,4691,4694,4773,4769,0,4694,4699,4776,4773,0,4699,4705,4779,4776,0,4705,4717,4782,4779,0,4717,4733,4790,4782,0,4733,4745,4800,4790,0,4745,4748,4815,4800,0,4748,4754,4828,4815,0,4754,4758,4833,4828,0,4758,4761,4835,4833,0,4761,4770,4844,4835,0,4770,4781,4859,4844,0,4781,4784,4862,4859,0,4784,4788,4866,4862,0,4788,4794,4872,4866,0,4794,4797,4877,4872,0,4797,4801,4883,4877,0,4801,4806,4887,4883,0,4806,4809,4890,4887,0,4809,4811,4893,4890,0,4811,4812,4894,4893,0,4812,4810,4892,4894,0,4810,4807,4888,4892,0,4807,4803,4884,4888,0,4803,4798,4878,4884,0,4798,4795,4874,4878,0,4795,4789,4867,4874,0,4789,4785,4863,4867,0,4785,4783,4860,4863,0,4783,4774,4848,4860,0,4774,4772,4847,4848,0,4847,4852,4953,4949,0,4852,4870,4973,4953,0,4870,4876,4980,4973,0,4876,4885,4989,4980,0,4885,4897,5000,4989,0,4897,4899,5002,5000,0,4899,4904,5005,5002,0,4904,4907,5008,5005,0,4907,4909,5009,5008,0,4909,4911,5011,5009,0,4911,4912,5013,5011,0,4912,4910,5012,5013,0,4910,4908,5010,5012,0,4908,4906,5007,5010,0,4906,4903,5004,5007,0,4903,4898,5001,5004,0,4898,4896,4999,5001,0,4896,4886,4990,4999,0,4886,4881,4985,4990,0,4881,4871,4977,4985,0,4871,4864,4969,4977,0,4864,4839,4939,4969,0,4839,4836,4935,4939,0,4836,4832,4930,4935,0,4832,4825,4927,4930,0,4825,4816,4924,4927,0,4816,4802,4920,4924,0,4802,4793,4916,4920,0,4793,4786,4905,4916,0,4786,4780,4895,4905,0,4780,4778,4879,4895,0,4778,4775,4869,4879,0,4775,4771,4861,4869,0,4771,4768,4856,4861,0,4768,4766,4853,4856,0,4766,4763,4849,4853,0,4763,4760,4846,4849,0,4760,4756,4843,4846,0,4756,4751,4840,4843,0,4751,4747,4837,4840,0,4747,4744,4834,4837,0,4744,4709,4808,4834,0,4709,4722,4820,4808,0,4722,4728,4822,4820,0,4728,4750,4838,4822,0,4750,4752,4841,4838,0,4752,4755,4842,4841,0,4755,4759,4845,4842,0,4759,4764,4850,4845,0,4764,4767,4854,4850,0,4767,4769,4858,4854,0,4769,4773,4865,4858,0,4773,4776,4873,4865,0,4776,4779,4882,4873,0,4779,4782,4900,4882,0,4782,4790,4915,4900,0,4790,4800,4919,4915,0,4800,4815,4923,4919,0,4815,4828,4928,4923,0,4828,4833,4931,4928,0,4833,4835,4934,4931,0,4835,4844,4944,4934,0,4844,4859,4960,4944,0,4859,4862,4965,4960,0,4862,4866,4970,4965,0,4866,4872,4978,4970,0,4872,4877,4983,4978,0,4877,4883,4987,4983,0,4883,4887,4992,4987,0,4887,4890,4994,4992,0,4890,4893,4996,4994,0,4893,4894,4998,4996,0,4894,4892,4995,4998,0,4892,4888,4991,4995,0,4888,4884,4988,4991,0,4884,4878,4984,4988,0,4878,4874,4979,4984,0,4874,4867,4971,4979,0,4867,4863,4967,4971,0,4863,4860,4962,4967,0,4860,4848,4950,4962,0,4848,4847,4949,4950,0,4949,4953,5020,5017,0,4953,4973,5035,5020,0,4973,4980,5040,5035,0,4980,4989,5048,5040,0,4989,5000,5057,5048,0,5000,5002,5061,5057,0,5002,5005,5062,5061,0,5005,5008,5064,5062,0,5008,5009,5066,5064,0,5009,5011,5070,5066,0,5011,5013,5072,5070,0,5013,5012,5071,5072,0,5012,5010,5067,5071,0,5010,5007,5065,5067,0,5007,5004,5063,5065,0,5004,5001,5060,5063,0,5001,4999,5056,5060,0,4999,4990,5049,5056,0,4990,4985,5044,5049,0,4985,4977,5036,5044,0,4977,4969,5031,5036,0,4969,4939,4986,5031,0,4939,4935,4976,4986,0,4935,4930,4966,4976,0,4930,4927,4958,4966,0,4927,4924,4956,4958,0,4924,4920,4952,4956,0,4920,4916,4948,4952,0,4916,4905,4943,4948,0,4905,4895,4940,4943,0,4895,4879,4937,4940,0,4879,4869,4933,4937,0,4869,4861,4929,4933,0,4861,4856,4925,4929,0,4856,4853,4921,4925,0,4853,4849,4917,4921,0,4849,4846,4914,4917,0,4846,4843,4902,4914,0,4843,4840,4889,4902,0,4840,4837,4875,4889,0,4837,4834,4868,4875,0,4834,4808,4851,4868,0,4808,4820,4855,4851,0,4820,4822,4857,4855,0,4822,4838,4880,4857,0,4838,4841,4891,4880,0,4841,4842,4901,4891,0,4842,4845,4913,4901,0,4845,4850,4918,4913,0,4850,4854,4922,4918,0,4854,4858,4926,4922,0,4858,4865,4932,4926,0,4865,4873,4936,4932,0,4873,4882,4938,4936,0,4882,4900,4941,4938,0,4900,4915,4945,4941,0,4915,4919,4951,4945,0,4919,4923,4955,4951,0,4923,4928,4961,4955,0,4928,4931,4968,4961,0,4931,4934,4975,4968,0,4934,4944,5014,4975,0,4944,4960,5025,5014,0,4960,4965,5028,5025,0,4965,4970,5032,5028,0,4970,4978,5038,5032,0,4978,4983,5041,5038,0,4983,4987,5046,5041,0,4987,4992,5051,5046,0,4992,4994,5052,5051,0,4994,4996,5054,5052,0,4996,4998,5055,5054,0,4998,4995,5053,5055,0,4995,4991,5050,5053,0,4991,4988,5045,5050,0,4988,4984,5042,5045,0,4984,4979,5039,5042,0,4979,4971,5033,5039,0,4971,4967,5029,5033,0,4967,4962,5027,5029,0,4962,4950,5018,5027,0,4950,4949,5017,5018,0,5017,5020,5085,5081,0,5020,5035,5100,5085,0,5035,5040,5109,5100,0,5040,5048,5117,5109,0,5048,5057,5127,5117,0,5057,5061,5131,5127,0,5061,5062,5135,5131,0,5062,5064,5137,5135,0,5064,5066,5141,5137,0,5066,5070,5143,5141,0,5070,5072,5146,5143,0,5072,5071,5144,5146,0,5071,5067,5142,5144,0,5067,5065,5138,5142,0,5065,5063,5136,5138,0,5063,5060,5132,5136,0,5060,5056,5128,5132,0,5056,5049,5119,5128,0,5049,5044,5112,5119,0,5044,5036,5102,5112,0,5036,5031,5095,5102,0,5031,4986,5079,5095,0,4986,4976,5078,5079,0,4976,4966,5075,5078,0,4966,4958,5073,5075,0,4958,4956,5069,5073,0,4956,4952,5059,5069,0,4952,4948,5047,5059,0,4948,4943,5037,5047,0,4943,4940,5030,5037,0,4940,4937,5024,5030,0,4937,4933,5022,5024,0,4933,4929,5019,5022,0,4929,4925,5015,5019,0,4925,4921,5003,5015,0,4921,4917,4993,5003,0,4917,4914,4982,4993,0,4914,4902,4974,4982,0,4902,4889,4963,4974,0,4889,4875,4957,4963,0,4875,4868,4954,4957,0,4868,4851,4942,4954,0,4851,4855,4946,4942,0,4855,4857,4947,4946,0,4857,4880,4959,4947,0,4880,4891,4964,4959,0,4891,4901,4972,4964,0,4901,4913,4981,4972,0,4913,4918,4997,4981,0,4918,4922,5006,4997,0,4922,4926,5016,5006,0,4926,4932,5021,5016,0,4932,4936,5023,5021,0,4936,4938,5026,5023,0,4938,4941,5034,5026,0,4941,4945,5043,5034,0,4945,4951,5058,5043,0,4951,4955,5068,5058,0,4955,4961,5074,5068,0,4961,4968,5076,5074,0,4968,4975,5077,5076,0,4975,5014,5080,5077,0,5014,5025,5090,5080,0,5025,5028,5093,5090,0,5028,5032,5098,5093,0,5032,5038,5105,5098,0,5038,5041,5111,5105,0,5041,5046,5115,5111,0,5046,5051,5121,5115,0,5051,5052,5123,5121,0,5052,5054,5125,5123,0,5054,5055,5126,5125,0,5055,5053,5124,5126,0,5053,5050,5120,5124,0,5050,5045,5113,5120,0,5045,5042,5110,5113,0,5042,5039,5104,5110,0,5039,5033,5099,5104,0,5033,5029,5094,5099,0,5029,5027,5091,5094,0,5027,5018,5083,5091,0,5018,5017,5081,5083,0,5081,5085,5224,5217,0,5085,5100,5243,5224,0,5100,5109,5253,5243,0,5109,5117,5264,5253,0,5117,5127,5278,5264,0,5127,5131,5285,5278,0,5131,5135,5294,5285,0,5135,5137,5296,5294,0,5137,5141,5301,5296,0,5141,5143,5303,5301,0,5143,5146,5305,5303,0,5146,5144,5304,5305,0,5144,5142,5302,5304,0,5142,5138,5297,5302,0,5138,5136,5295,5297,0,5136,5132,5288,5295,0,5132,5128,5279,5288,0,5128,5119,5269,5279,0,5119,5112,5260,5269,0,5112,5102,5246,5260,0,5102,5095,5238,5246,0,5095,5079,5208,5238,0,5079,5078,5203,5208,0,5078,5075,5196,5203,0,5075,5073,5191,5196,0,5073,5069,5188,5191,0,5069,5059,5182,5188,0,5059,5047,5177,5182,0,5047,5037,5173,5177,0,5037,5030,5170,5173,0,5030,5024,5165,5170,0,5024,5022,5161,5165,0,5022,5019,5157,5161,0,5019,5015,5154,5157,0,5015,5003,5150,5154,0,5003,4993,5145,5150,0,4993,4982,5134,5145,0,4982,4974,5122,5134,0,4974,4963,5106,5122,0,4963,4957,5097,5106,0,4957,4954,5092,5097,0,4954,4942,5082,5092,0,4942,4946,5086,5082,0,4946,4947,5087,5086,0,4947,4959,5101,5087,0,4959,4964,5108,5101,0,4964,4972,5118,5108,0,4972,4981,5133,5118,0,4981,4997,5147,5133,0,4997,5006,5151,5147,0,5006,5016,5155,5151,0,5016,5021,5159,5155,0,5021,5023,5163,5159,0,5023,5026,5167,5163,0,5026,5034,5171,5167,0,5034,5043,5175,5171,0,5043,5058,5181,5175,0,5058,5068,5187,5181,0,5068,5074,5192,5187,0,5074,5076,5197,5192,0,5076,5077,5202,5197,0,5077,5080,5216,5202,0,5080,5090,5229,5216,0,5090,5093,5235,5229,0,5093,5098,5241,5235,0,5098,5105,5249,5241,0,5105,5111,5255,5249,0,5111,5115,5262,5255,0,5115,5121,5270,5262,0,5121,5123,5271,5270,0,5123,5125,5274,5271,0,5125,5126,5275,5274,0,5126,5124,5272,5275,0,5124,5120,5267,5272,0,5120,5113,5261,5267,0,5113,5110,5254,5261,0,5110,5104,5247,5254,0,5104,5099,5239,5247,0,5099,5094,5234,5239,0,5094,5091,5231,5234,0,5091,5083,5218,5231,0,5083,5081,5217,5218,0,5217,5224,5227,5222,0,5224,5243,5252,5227,0,5243,5253,5263,5252,0,5253,5264,5280,5263,0,5264,5278,5291,5280,0,5278,5285,5299,5291,0,5285,5294,5306,5299,0,5294,5296,5308,5306,0,5296,5301,5311,5308,0,5301,5303,5313,5311,0,5303,5305,5316,5313,0,5305,5304,5315,5316,0,5304,5302,5312,5315,0,5302,5297,5309,5312,0,5297,5295,5307,5309,0,5295,5288,5300,5307,0,5288,5279,5293,5300,0,5279,5269,5283,5293,0,5269,5260,5273,5283,0,5260,5246,5256,5273,0,5246,5238,5245,5256,0,5238,5208,5211,5245,0,5208,5203,5207,5211,0,5203,5196,5199,5207,0,5196,5191,5194,5199,0,5191,5188,5190,5194,0,5188,5182,5186,5190,0,5182,5177,5180,5186,0,5177,5173,5176,5180,0,5173,5170,5172,5176,0,5170,5165,5168,5172,0,5165,5161,5164,5168,0,5161,5157,5160,5164,0,5157,5154,5156,5160,0,5154,5150,5152,5156,0,5150,5145,5148,5152,0,5145,5134,5140,5148,0,5134,5122,5130,5140,0,5122,5106,5114,5130,0,5106,5097,5103,5114,0,5097,5092,5096,5103,0,5092,5082,5084,5096,0,5082,5086,5088,5084,0,5086,5087,5089,5088,0,5087,5101,5107,5089,0,5101,5108,5116,5107,0,5108,5118,5129,5116,0,5118,5133,5139,5129,0,5133,5147,5149,5139,0,5147,5151,5153,5149,0,5151,5155,5158,5153,0,5155,5159,5162,5158,0,5159,5163,5166,5162,0,5163,5167,5169,5166,0,5167,5171,5174,5169,0,5171,5175,5179,5174,0,5175,5181,5184,5179,0,5181,5187,5189,5184,0,5187,5192,5195,5189,0,5192,5197,5201,5195,0,5197,5202,5206,5201,0,5202,5216,5219,5206,0,5216,5229,5233,5219,0,5229,5235,5242,5233,0,5235,5241,5251,5242,0,5241,5249,5259,5251,0,5249,5255,5268,5259,0,5255,5262,5277,5268,0,5262,5270,5284,5277,0,5270,5271,5286,5284,0,5271,5274,5289,5286,0,5274,5275,5290,5289,0,5275,5272,5287,5290,0,5272,5267,5282,5287,0,5267,5261,5276,5282,0,5261,5254,5265,5276,0,5254,5247,5257,5265,0,5247,5239,5250,5257,0,5239,5234,5240,5250,0,5234,5231,5237,5240,0,5231,5218,5223,5237,0,5218,5217,5222,5223,0,5222,5227,5330,5327,0,5227,5252,5341,5330,0,5252,5263,5347,5341,0,5263,5280,5355,5347,0,5280,5291,5365,5355,0,5291,5299,5367,5365,0,5299,5306,5369,5367,0,5306,5308,5373,5369,0,5308,5311,5376,5373,0,5311,5313,5378,5376,0,5313,5316,5380,5378,0,5316,5315,5379,5380,0,5315,5312,5377,5379,0,5312,5309,5374,5377,0,5309,5307,5371,5374,0,5307,5300,5368,5371,0,5300,5293,5366,5368,0,5293,5283,5358,5366,0,5283,5273,5352,5358,0,5273,5256,5345,5352,0,5256,5245,5338,5345,0,5245,5211,5325,5338,0,5211,5207,5324,5325,0,5207,5199,5321,5324,0,5199,5194,5319,5321,0,5194,5190,5318,5319,0,5190,5186,5314,5318,0,5186,5180,5298,5314,0,5180,5176,5281,5298,0,5176,5172,5258,5281,0,5172,5168,5244,5258,0,5168,5164,5232,5244,0,5164,5160,5228,5232,0,5160,5156,5225,5228,0,5156,5152,5220,5225,0,5152,5148,5214,5220,0,5148,5140,5213,5214,0,5140,5130,5210,5213,0,5130,5114,5204,5210,0,5114,5103,5198,5204,0,5103,5096,5193,5198,0,5096,5084,5178,5193,0,5084,5088,5183,5178,0,5088,5089,5185,5183,0,5089,5107,5200,5185,0,5107,5116,5205,5200,0,5116,5129,5209,5205,0,5129,5139,5212,5209,0,5139,5149,5215,5212,0,5149,5153,5221,5215,0,5153,5158,5226,5221,0,5158,5162,5230,5226,0,5162,5166,5236,5230,0,5166,5169,5248,5236,0,5169,5174,5266,5248,0,5174,5179,5292,5266,0,5179,5184,5310,5292,0,5184,5189,5317,5310,0,5189,5195,5320,5317,0,5195,5201,5322,5320,0,5201,5206,5323,5322,0,5206,5219,5326,5323,0,5219,5233,5333,5326,0,5233,5242,5337,5333,0,5242,5251,5340,5337,0,5251,5259,5346,5340,0,5259,5268,5349,5346,0,5268,5277,5354,5349,0,5277,5284,5357,5354,0,5284,5286,5359,5357,0,5286,5289,5361,5359,0,5289,5290,5362,5361,0,5290,5287,5360,5362,0,5287,5282,5356,5360,0,5282,5276,5353,5356,0,5276,5265,5348,5353,0,5265,5257,5344,5348,0,5257,5250,5339,5344,0,5250,5240,5335,5339,0,5240,5237,5334,5335,0,5237,5223,5328,5334,0,5223,5222,5327,5328,0,5327,5330,5460,5454,0,5330,5341,5480,5460,0,5341,5347,5486,5480,0,5347,5355,5493,5486,0,5355,5365,5503,5493,0,5365,5367,5505,5503,0,5367,5369,5509,5505,0,5369,5373,5513,5509,0,5373,5376,5516,5513,0,5376,5378,5518,5516,0,5378,5380,5520,5518,0,5380,5379,5519,5520,0,5379,5377,5517,5519,0,5377,5374,5514,5517,0,5374,5371,5511,5514,0,5371,5368,5508,5511,0,5368,5366,5504,5508,0,5366,5358,5497,5504,0,5358,5352,5490,5497,0,5352,5345,5483,5490,0,5345,5338,5476,5483,0,5338,5325,5440,5476,0,5325,5324,5435,5440,0,5324,5321,5429,5435,0,5321,5319,5424,5429,0,5319,5318,5421,5424,0,5318,5314,5415,5421,0,5314,5298,5410,5415,0,5298,5281,5406,5410,0,5281,5258,5402,5406,0,5258,5244,5398,5402,0,5244,5232,5394,5398,0,5232,5228,5390,5394,0,5228,5225,5387,5390,0,5225,5220,5385,5387,0,5220,5214,5381,5385,0,5214,5213,5372,5381,0,5213,5210,5364,5372,0,5210,5204,5350,5364,0,5204,5198,5342,5350,0,5198,5193,5336,5342,0,5193,5178,5329,5336,0,5178,5183,5331,5329,0,5183,5185,5332,5331,0,5185,5200,5343,5332,0,5200,5205,5351,5343,0,5205,5209,5363,5351,0,5209,5212,5370,5363,0,5212,5215,5382,5370,0,5215,5221,5386,5382,0,5221,5226,5388,5386,0,5226,5230,5391,5388,0,5230,5236,5395,5391,0,5236,5248,5399,5395,0,5248,5266,5405,5399,0,5266,5292,5409,5405,0,5292,5310,5414,5409,0,5310,5317,5420,5414,0,5317,5320,5425,5420,0,5320,5322,5430,5425,0,5322,5323,5434,5430,0,5323,5326,5449,5434,0,5326,5333,5468,5449,0,5333,5337,5472,5468,0,5337,5340,5479,5472,0,5340,5346,5485,5479,0,5346,5349,5489,5485,0,5349,5354,5492,5489,0,5354,5357,5496,5492,0,5357,5359,5499,5496,0,5359,5361,5501,5499,0,5361,5362,5500,5501,0,5362,5360,5498,5500,0,5360,5356,5495,5498,0,5356,5353,5491,5495,0,5353,5348,5488,5491,0,5348,5344,5482,5488,0,5344,5339,5477,5482,0,5339,5335,5471,5477,0,5335,5334,5469,5471,0,5334,5328,5455,5469,0,5328,5327,5454,5455,0,5454,5460,5522,5510,0,5460,5480,5536,5522,0,5480,5486,5542,5536,0,5486,5493,5550,5542,0,5493,5503,5559,5550,0,5503,5505,5561,5559,0,5505,5509,5563,5561,0,5509,5513,5565,5563,0,5513,5516,5567,5565,0,5516,5518,5569,5567,0,5518,5520,5571,5569,0,5520,5519,5570,5571,0,5519,5517,5568,5570,0,5517,5514,5566,5568,0,5514,5511,5564,5566,0,5511,5508,5562,5564,0,5508,5504,5560,5562,0,5504,5497,5553,5560,0,5497,5490,5547,5553,0,5490,5483,5540,5547,0,5483,5476,5533,5540,0,5476,5440,5481,5533,0,5440,5435,5474,5481,0,5435,5429,5465,5474,0,5429,5424,5461,5465,0,5424,5421,5458,5461,0,5421,5415,5452,5458,0,5415,5410,5447,5452,0,5410,5406,5442,5447,0,5406,5402,5437,5442,0,5402,5398,5431,5437,0,5398,5394,5426,5431,0,5394,5390,5422,5426,0,5390,5387,5416,5422,0,5387,5385,5411,5416,0,5385,5381,5407,5411,0,5381,5372,5404,5407,0,5372,5364,5401,5404,0,5364,5350,5396,5401,0,5350,5342,5392,5396,0,5342,5336,5389,5392,0,5336,5329,5375,5389,0,5329,5331,5383,5375,0,5331,5332,5384,5383,0,5332,5343,5393,5384,0,5343,5351,5397,5393,0,5351,5363,5400,5397,0,5363,5370,5403,5400,0,5370,5382,5408,5403,0,5382,5386,5412,5408,0,5386,5388,5417,5412,0,5388,5391,5423,5417,0,5391,5395,5428,5423,0,5395,5399,5433,5428,0,5399,5405,5441,5433,0,5405,5409,5445,5441,0,5409,5414,5450,5445,0,5414,5420,5457,5450,0,5420,5425,5463,5457,0,5425,5430,5466,5463,0,5430,5434,5473,5466,0,5434,5449,5507,5473,0,5449,5468,5527,5507,0,5468,5472,5532,5527,0,5472,5479,5535,5532,0,5479,5485,5541,5535,0,5485,5489,5545,5541,0,5489,5492,5549,5545,0,5492,5496,5552,5549,0,5496,5499,5555,5552,0,5499,5501,5557,5555,0,5501,5500,5556,5557,0,5500,5498,5554,5556,0,5498,5495,5551,5554,0,5495,5491,5548,5551,0,5491,5488,5543,5548,0,5488,5482,5539,5543,0,5482,5477,5534,5539,0,5477,5471,5530,5534,0,5471,5469,5528,5530,0,5469,5455,5512,5528,0,5455,5454,5510,5512,0,5510,5522,5576,5573,0,5522,5536,5587,5576,0,5536,5542,5594,5587,0,5542,5550,5600,5594,0,5550,5559,5611,5600,0,5559,5561,5613,5611,0,5561,5563,5617,5613,0,5563,5565,5619,5617,0,5565,5567,5621,5619,0,5567,5569,5623,5621,0,5569,5571,5626,5623,0,5571,5570,5625,5626,0,5570,5568,5622,5625,0,5568,5566,5620,5622,0,5566,5564,5618,5620,0,5564,5562,5616,5618,0,5562,5560,5612,5616,0,5560,5553,5606,5612,0,5553,5547,5598,5606,0,5547,5540,5591,5598,0,5540,5533,5584,5591,0,5533,5481,5558,5584,0,5481,5474,5546,5558,0,5474,5465,5537,5546,0,5465,5461,5529,5537,0,5461,5458,5526,5529,0,5458,5452,5524,5526,0,5452,5447,5521,5524,0,5447,5442,5506,5521,0,5442,5437,5494,5506,0,5437,5431,5484,5494,0,5431,5426,5475,5484,0,5426,5422,5467,5475,0,5422,5416,5462,5467,0,5416,5411,5456,5462,0,5411,5407,5451,5456,0,5407,5404,5448,5451,0,5404,5401,5444,5448,0,5401,5396,5438,5444,0,5396,5392,5432,5438,0,5392,5389,5427,5432,0,5389,5375,5413,5427,0,5375,5383,5418,5413,0,5383,5384,5419,5418,0,5384,5393,5436,5419,0,5393,5397,5439,5436,0,5397,5400,5443,5439,0,5400,5403,5446,5443,0,5403,5408,5453,5446,0,5408,5412,5459,5453,0,5412,5417,5464,5459,0,5417,5423,5470,5464,0,5423,5428,5478,5470,0,5428,5433,5487,5478,0,5433,5441,5502,5487,0,5441,5445,5515,5502,0,5445,5450,5523,5515,0,5450,5457,5525,5523,0,5457,5463,5531,5525,0,5463,5466,5538,5531,0,5466,5473,5544,5538,0,5473,5507,5572,5544,0,5507,5527,5579,5572,0,5527,5532,5583,5579,0,5532,5535,5588,5583,0,5535,5541,5592,5588,0,5541,5545,5597,5592,0,5545,5549,5601,5597,0,5549,5552,5605,5601,0,5552,5555,5608,5605,0,5555,5557,5610,5608,0,5557,5556,5609,5610,0,5556,5554,5607,5609,0,5554,5551,5603,5607,0,5551,5548,5599,5603,0,5548,5543,5596,5599,0,5543,5539,5590,5596,0,5539,5534,5586,5590,0,5534,5530,5582,5586,0,5530,5528,5580,5582,0,5528,5512,5575,5580,0,5512,5510,5573,5575,0,5573,5576,5687,5679,0,5576,5587,5706,5687,0,5587,5594,5714,5706,0,5594,5600,5722,5714,0,5600,5611,5734,5722,0,5611,5613,5736,5734,0,5613,5617,5740,5736,0,5617,5619,5743,5740,0,5619,5621,5746,5743,0,5621,5623,5748,5746,0,5623,5626,5750,5748,0,5626,5625,5749,5750,0,5625,5622,5747,5749,0,5622,5620,5745,5747,0,5620,5618,5742,5745,0,5618,5616,5738,5742,0,5616,5612,5735,5738,0,5612,5606,5727,5735,0,5606,5598,5719,5727,0,5598,5591,5711,5719,0,5591,5584,5703,5711,0,5584,5558,5668,5703,0,5558,5546,5664,5668,0,5546,5537,5657,5664,0,5537,5529,5654,5657,0,5529,5526,5650,5654,0,5526,5524,5647,5650,0,5524,5521,5643,5647,0,5521,5506,5640,5643,0,5506,5494,5638,5640,0,5494,5484,5636,5638,0,5484,5475,5634,5636,0,5475,5467,5632,5634,0,5467,5462,5630,5632,0,5462,5456,5628,5630,0,5456,5451,5624,5628,0,5451,5448,5615,5624,0,5448,5444,5604,5615,0,5444,5438,5593,5604,0,5438,5432,5585,5593,0,5432,5427,5581,5585,0,5427,5413,5574,5581,0,5413,5418,5577,5574,0,5418,5419,5578,5577,0,5419,5436,5589,5578,0,5436,5439,5595,5589,0,5439,5443,5602,5595,0,5443,5446,5614,5602,0,5446,5453,5627,5614,0,5453,5459,5629,5627,0,5459,5464,5631,5629,0,5464,5470,5633,5631,0,5470,5478,5635,5633,0,5478,5487,5637,5635,0,5487,5502,5639,5637,0,5502,5515,5642,5639,0,5515,5523,5645,5642,0,5523,5525,5649,5645,0,5525,5531,5655,5649,0,5531,5538,5658,5655,0,5538,5544,5662,5658,0,5544,5572,5678,5662,0,5572,5579,5695,5678,0,5579,5583,5701,5695,0,5583,5588,5707,5701,0,5588,5592,5712,5707,0,5592,5597,5718,5712,0,5597,5601,5723,5718,0,5601,5605,5726,5723,0,5605,5608,5729,5726,0,5608,5610,5733,5729,0,5610,5609,5732,5733,0,5609,5607,5728,5732,0,5607,5603,5725,5728,0,5603,5599,5720,5725,0,5599,5596,5716,5720,0,5596,5590,5710,5716,0,5590,5586,5704,5710,0,5586,5582,5699,5704,0,5582,5580,5696,5699,0,5580,5575,5682,5696,0,5575,5573,5679,5682,0,5679,5687,5779,5777,0,5687,5706,5793,5779,0,5706,5714,5801,5793,0,5714,5722,5810,5801,0,5722,5734,5824,5810,0,5734,5736,5831,5824,0,5736,5740,5834,5831,0,5740,5743,5841,5834,0,5743,5746,5845,5841,0,5746,5748,5848,5845,0,5748,5750,5851,5848,0,5750,5749,5849,5851,0,5749,5747,5846,5849,0,5747,5745,5843,5846,0,5745,5742,5837,5843,0,5742,5738,5832,5837,0,5738,5735,5827,5832,0,5735,5727,5818,5827,0,5727,5719,5807,5818,0,5719,5711,5799,5807,0,5711,5703,5791,5799,0,5703,5668,5772,5791,0,5668,5664,5769,5772,0,5664,5657,5763,5769,0,5657,5654,5760,5763,0,5654,5650,5757,5760,0,5650,5647,5753,5757,0,5647,5643,5741,5753,0,5643,5640,5730,5741,0,5640,5638,5715,5730,0,5638,5636,5705,5715,0,5636,5634,5697,5705,0,5634,5632,5692,5697,0,5632,5630,5688,5692,0,5630,5628,5683,5688,0,5628,5624,5675,5683,0,5624,5615,5673,5675,0,5615,5604,5667,5673,0,5604,5593,5661,5667,0,5593,5585,5656,5661,0,5585,5581,5653,5656,0,5581,5574,5641,5653,0,5574,5577,5644,5641,0,5577,5578,5646,5644,0,5578,5589,5659,5646,0,5589,5595,5663,5659,0,5595,5602,5666,5663,0,5602,5614,5672,5666,0,5614,5627,5677,5672,0,5627,5629,5684,5677,0,5629,5631,5689,5684,0,5631,5633,5693,5689,0,5633,5635,5700,5693,0,5635,5637,5709,5700,0,5637,5639,5721,5709,0,5639,5642,5737,5721,0,5642,5645,5752,5737,0,5645,5649,5756,5752,0,5649,5655,5761,5756,0,5655,5658,5765,5761,0,5658,5662,5768,5765,0,5662,5678,5776,5768,0,5678,5695,5787,5776,0,5695,5701,5790,5787,0,5701,5707,5794,5790,0,5707,5712,5800,5794,0,5712,5718,5805,5800,0,5718,5723,5811,5805,0,5723,5726,5816,5811,0,5726,5729,5820,5816,0,5729,5733,5822,5820,0,5733,5732,5821,5822,0,5732,5728,5819,5821,0,5728,5725,5814,5819,0,5725,5720,5808,5814,0,5720,5716,5803,5808,0,5716,5710,5796,5803,0,5710,5704,5792,5796,0,5704,5699,5789,5792,0,5699,5696,5788,5789,0,5696,5682,5778,5788,0,5682,5679,5777,5778,0,5777,5779,5786,5782,0,5779,5793,5815,5786,0,5793,5801,5830,5815,0,5801,5810,5842,5830,0,5810,5824,5857,5842,0,5824,5831,5861,5857,0,5831,5834,5863,5861,0,5834,5841,5866,5863,0,5841,5845,5869,5866,0,5845,5848,5871,5869,0,5848,5851,5873,5871,0,5851,5849,5872,5873,0,5849,5846,5870,5872,0,5846,5843,5868,5870,0,5843,5837,5864,5868,0,5837,5832,5862,5864,0,5832,5827,5860,5862,0,5827,5818,5852,5860,0,5818,5807,5838,5852,0,5807,5799,5828,5838,0,5799,5791,5812,5828,0,5791,5772,5775,5812,0,5772,5769,5774,5775,0,5769,5763,5770,5774,0,5763,5760,5766,5770,0,5760,5757,5764,5766,0,5757,5753,5759,5764,0,5753,5741,5755,5759,0,5741,5730,5751,5755,0,5730,5715,5739,5751,0,5715,5705,5724,5739,0,5705,5697,5713,5724,0,5697,5692,5702,5713,0,5692,5688,5694,5702,0,5688,5683,5690,5694,0,5683,5675,5685,5690,0,5675,5673,5681,5685,0,5673,5667,5676,5681,0,5667,5661,5670,5676,0,5661,5656,5665,5670,0,5656,5653,5660,5665,0,5653,5641,5648,5660,0,5641,5644,5651,5648,0,5644,5646,5652,5651,0,5646,5659,5669,5652,0,5659,5663,5671,5669,0,5663,5666,5674,5671,0,5666,5672,5680,5674,0,5672,5677,5686,5680,0,5677,5684,5691,5686,0,5684,5689,5698,5691,0,5689,5693,5708,5698,0,5693,5700,5717,5708,0,5700,5709,5731,5717,0,5709,5721,5744,5731,0,5721,5737,5754,5744,0,5737,5752,5758,5754,0,5752,5756,5762,5758,0,5756,5761,5767,5762,0,5761,5765,5771,5767,0,5765,5768,5773,5771,0,5768,5776,5781,5773,0,5776,5787,5797,5781,0,5787,5790,5806,5797,0,5790,5794,5817,5806,0,5794,5800,5829,5817,0,5800,5805,5835,5829,0,5805,5811,5844,5835,0,5811,5816,5850,5844,0,5816,5820,5854,5850,0,5820,5822,5856,5854,0,5822,5821,5855,5856,0,5821,5819,5853,5855,0,5819,5814,5847,5853,0,5814,5808,5839,5847,0,5808,5803,5833,5839,0,5803,5796,5826,5833,0,5796,5792,5813,5826,0,5792,5789,5802,5813,0,5789,5788,5798,5802,0,5788,5778,5783,5798,0,5778,5777,5782,5783,0,5782,5786,5915,5910,0,5786,5815,5933,5915,0,5815,5830,5941,5933,0,5830,5842,5948,5941,0,5842,5857,5960,5948,0,5857,5861,5964,5960,0,5861,5863,5968,5964,0,5863,5866,5971,5968,0,5866,5869,5973,5971,0,5869,5871,5977,5973,0,5871,5873,5979,5977,0,5873,5872,5978,5979,0,5872,5870,5975,5978,0,5870,5868,5972,5975,0,5868,5864,5969,5972,0,5864,5862,5966,5969,0,5862,5860,5962,5966,0,5860,5852,5955,5962,0,5852,5838,5947,5955,0,5838,5828,5938,5947,0,5828,5812,5931,5938,0,5812,5775,5903,5931,0,5775,5774,5901,5903,0,5774,5770,5897,5901,0,5770,5766,5894,5897,0,5766,5764,5892,5894,0,5764,5759,5890,5892,0,5759,5755,5888,5890,0,5755,5751,5886,5888,0,5751,5739,5884,5886,0,5739,5724,5882,5884,0,5724,5713,5880,5882,0,5713,5702,5878,5880,0,5702,5694,5876,5878,0,5694,5690,5874,5876,0,5690,5685,5865,5874,0,5685,5681,5859,5865,0,5681,5676,5840,5859,0,5676,5670,5823,5840,0,5670,5665,5804,5823,0,5665,5660,5795,5804,0,5660,5648,5780,5795,0,5648,5651,5784,5780,0,5651,5652,5785,5784,0,5652,5669,5809,5785,0,5669,5671,5825,5809,0,5671,5674,5836,5825,0,5674,5680,5858,5836,0,5680,5686,5867,5858,0,5686,5691,5875,5867,0,5691,5698,5877,5875,0,5698,5708,5879,5877,0,5708,5717,5881,5879,0,5717,5731,5883,5881,0,5731,5744,5885,5883,0,5744,5754,5887,5885,0,5754,5758,5889,5887,0,5758,5762,5891,5889,0,5762,5767,5895,5891,0,5767,5771,5899,5895,0,5771,5773,5900,5899,0,5773,5781,5908,5900,0,5781,5797,5921,5908,0,5797,5806,5927,5921,0,5806,5817,5934,5927,0,5817,5829,5939,5934,0,5829,5835,5944,5939,0,5835,5844,5950,5944,0,5844,5850,5954,5950,0,5850,5854,5957,5954,0,5854,5856,5959,5957,0,5856,5855,5958,5959,0,5855,5853,5956,5958,0,5853,5847,5952,5956,0,5847,5839,5946,5952,0,5839,5833,5943,5946,0,5833,5826,5936,5943,0,5826,5813,5930,5936,0,5813,5802,5926,5930,0,5802,5798,5924,5926,0,5798,5783,5911,5924,0,5783,5782,5910,5911,0,5910,5915,6023,6016,0,5915,5933,6038,6023,0,5933,5941,6045,6038,0,5941,5948,6055,6045,0,5948,5960,6066,6055,0,5960,5964,6069,6066,0,5964,5968,6073,6069,0,5968,5971,6075,6073,0,5971,5973,6077,6075,0,5973,5977,6079,6077,0,5977,5979,6081,6079,0,5979,5978,6080,6081,0,5978,5975,6078,6080,0,5975,5972,6076,6078,0,5972,5969,6074,6076,0,5969,5966,6070,6074,0,5966,5962,6068,6070,0,5962,5955,6061,6068,0,5955,5947,6054,6061,0,5947,5938,6043,6054,0,5938,5931,6037,6043,0,5931,5903,6010,6037,0,5903,5901,6007,6010,0,5901,5897,6002,6007,0,5897,5894,5998,6002,0,5894,5892,5995,5998,0,5892,5890,5991,5995,0,5890,5888,5988,5991,0,5888,5886,5984,5988,0,5886,5884,5980,5984,0,5884,5882,5967,5980,0,5882,5880,5953,5967,0,5880,5878,5942,5953,0,5878,5876,5929,5942,0,5876,5874,5922,5929,0,5874,5865,5919,5922,0,5865,5859,5918,5919,0,5859,5840,5913,5918,0,5840,5823,5906,5913,0,5823,5804,5904,5906,0,5804,5795,5902,5904,0,5795,5780,5893,5902,0,5780,5784,5896,5893,0,5784,5785,5898,5896,0,5785,5809,5905,5898,0,5809,5825,5907,5905,0,5825,5836,5912,5907,0,5836,5858,5916,5912,0,5858,5867,5920,5916,0,5867,5875,5925,5920,0,5875,5877,5935,5925,0,5877,5879,5945,5935,0,5879,5881,5961,5945,0,5881,5883,5970,5961,0,5883,5885,5981,5970,0,5885,5887,5986,5981,0,5887,5889,5990,5986,0,5889,5891,5994,5990,0,5891,5895,5999,5994,0,5895,5899,6003,5999,0,5899,5900,6006,6003,0,5900,5908,6017,6006,0,5908,5921,6029,6017,0,5921,5927,6035,6029,0,5927,5934,6041,6035,0,5934,5939,6044,6041,0,5939,5944,6050,6044,0,5944,5950,6056,6050,0,5950,5954,6059,6056,0,5954,5957,6063,6059,0,5957,5959,6065,6063,0,5959,5958,6064,6065,0,5958,5956,6062,6064,0,5956,5952,6057,6062,0,5952,5946,6053,6057,0,5946,5943,6047,6053,0,5943,5936,6042,6047,0,5936,5930,6036,6042,0,5930,5926,6033,6036,0,5926,5924,6030,6033,0,5924,5911,6018,6030,0,5911,5910,6016,6018,0,6016,6023,6067,6049,0,6023,6038,6092,6067,0,6038,6045,6099,6092,0,6045,6055,6104,6099,0,6055,6066,6115,6104,0,6066,6069,6119,6115,0,6069,6073,6121,6119,0,6073,6075,6123,6121,0,6075,6077,6126,6123,0,6077,6079,6128,6126,0,6079,6081,6130,6128,0,6081,6080,6129,6130,0,6080,6078,6127,6129,0,6078,6076,6125,6127,0,6076,6074,6122,6125,0,6074,6070,6120,6122,0,6070,6068,6117,6120,0,6068,6061,6111,6117,0,6061,6054,6105,6111,0,6054,6043,6098,6105,0,6043,6037,6091,6098,0,6037,6010,6031,6091,0,6010,6007,6027,6031,0,6007,6002,6024,6027,0,6002,5998,6020,6024,0,5998,5995,6015,6020,0,5995,5991,6012,6015,0,5991,5988,6009,6012,0,5988,5984,6005,6009,0,5984,5980,6001,6005,0,5980,5967,5997,6001,0,5967,5953,5993,5997,0,5953,5942,5989,5993,0,5942,5929,5985,5989,0,5929,5922,5982,5985,0,5922,5919,5974,5982,0,5919,5918,5965,5974,0,5918,5913,5951,5965,0,5913,5906,5937,5951,0,5906,5904,5928,5937,0,5904,5902,5923,5928,0,5902,5893,5909,5923,0,5893,5896,5914,5909,0,5896,5898,5917,5914,0,5898,5905,5932,5917,0,5905,5907,5940,5932,0,5907,5912,5949,5940,0,5912,5916,5963,5949,0,5916,5920,5976,5963,0,5920,5925,5983,5976,0,5925,5935,5987,5983,0,5935,5945,5992,5987,0,5945,5961,5996,5992,0,5961,5970,6000,5996,0,5970,5981,6004,6000,0,5981,5986,6008,6004,0,5986,5990,6011,6008,0,5990,5994,6014,6011,0,5994,5999,6021,6014,0,5999,6003,6025,6021,0,6003,6006,6026,6025,0,6006,6017,6051,6026,0,6017,6029,6084,6051,0,6029,6035,6089,6084,0,6035,6041,6094,6089,0,6041,6044,6097,6094,0,6044,6050,6102,6097,0,6050,6056,6107,6102,0,6056,6059,6109,6107,0,6059,6063,6112,6109,0,6063,6065,6114,6112,0,6065,6064,6113,6114,0,6064,6062,6110,6113,0,6062,6057,6108,6110,0,6057,6053,6103,6108,0,6053,6047,6100,6103,0,6047,6042,6095,6100,0,6042,6036,6090,6095,0,6036,6033,6087,6090,0,6033,6030,6085,6087,0,6030,6018,6052,6085,0,6018,6016,6049,6052,0,6049,6067,6157,6152,0,6067,6092,6169,6157,0,6092,6099,6175,6169,0,6099,6104,6183,6175,0,6104,6115,6194,6183,0,6115,6119,6197,6194,0,6119,6121,6199,6197,0,6121,6123,6202,6199,0,6123,6126,6205,6202,0,6126,6128,6207,6205,0,6128,6130,6209,6207,0,6130,6129,6208,6209,0,6129,6127,6206,6208,0,6127,6125,6203,6206,0,6125,6122,6201,6203,0,6122,6120,6198,6201,0,6120,6117,6195,6198,0,6117,6111,6190,6195,0,6111,6105,6184,6190,0,6105,6098,6177,6184,0,6098,6091,6171,6177,0,6091,6031,6148,6171,0,6031,6027,6147,6148,0,6027,6024,6142,6147,0,6024,6020,6139,6142,0,6020,6015,6138,6139,0,6015,6012,6136,6138,0,6012,6009,6134,6136,0,6009,6005,6132,6134,0,6005,6001,6124,6132,0,6001,5997,6116,6124,0,5997,5993,6101,6116,0,5993,5989,6093,6101,0,5989,5985,6086,6093,0,5985,5982,6082,6086,0,5982,5974,6071,6082,0,5974,5965,6060,6071,0,5965,5951,6048,6060,0,5951,5937,6039,6048,0,5937,5928,6032,6039,0,5928,5923,6028,6032,0,5923,5909,6013,6028,0,5909,5914,6019,6013,0,5914,5917,6022,6019,0,5917,5932,6034,6022,0,5932,5940,6040,6034,0,5940,5949,6046,6040,0,5949,5963,6058,6046,0,5963,5976,6072,6058,0,5976,5983,6083,6072,0,5983,5987,6088,6083,0,5987,5992,6096,6088,0,5992,5996,6106,6096,0,5996,6000,6118,6106,0,6000,6004,6131,6118,0,6004,6008,6133,6131,0,6008,6011,6135,6133,0,6011,6014,6137,6135,0,6014,6021,6140,6137,0,6021,6025,6143,6140,0,6025,6026,6145,6143,0,6026,6051,6153,6145,0,6051,6084,6163,6153,0,6084,6089,6167,6163,0,6089,6094,6173,6167,0,6094,6097,6176,6173,0,6097,6102,6180,6176,0,6102,6107,6185,6180,0,6107,6109,6187,6185,0,6109,6112,6191,6187,0,6112,6114,6193,6191,0,6114,6113,6192,6193,0,6113,6110,6189,6192,0,6110,6108,6186,6189,0,6108,6103,6182,6186,0,6103,6100,6179,6182,0,6100,6095,6174,6179,0,6095,6090,6168,6174,0,6090,6087,6166,6168,0,6087,6085,6162,6166,0,6085,6052,6154,6162,0,6052,6049,6152,6154,0,6152,6157,6254,6247,0,6157,6169,6271,6254,0,6169,6175,6279,6271,0,6175,6183,6287,6279,0,6183,6194,6300,6287,0,6194,6197,6304,6300,0,6197,6199,6306,6304,0,6199,6202,6310,6306,0,6202,6205,6313,6310,0,6205,6207,6316,6313,0,6207,6209,6318,6316,0,6209,6208,6317,6318,0,6208,6206,6315,6317,0,6206,6203,6312,6315,0,6203,6201,6309,6312,0,6201,6198,6305,6309,0,6198,6195,6303,6305,0,6195,6190,6295,6303,0,6190,6184,6289,6295,0,6184,6177,6281,6289,0,6177,6171,6272,6281,0,6171,6148,6241,6272,0,6148,6147,6238,6241,0,6147,6142,6233,6238,0,6142,6139,6229,6233,0,6139,6138,6226,6229,0,6138,6136,6222,6226,0,6136,6134,6219,6222,0,6134,6132,6217,6219,0,6132,6124,6213,6217,0,6124,6116,6210,6213,0,6116,6101,6200,6210,0,6101,6093,6188,6200,0,6093,6086,6178,6188,0,6086,6082,6170,6178,0,6082,6071,6164,6170,0,6071,6060,6161,6164,0,6060,6048,6159,6161,0,6048,6039,6155,6159,0,6039,6032,6150,6155,0,6032,6028,6149,6150,0,6028,6013,6141,6149,0,6013,6019,6144,6141,0,6019,6022,6146,6144,0,6022,6034,6151,6146,0,6034,6040,6156,6151,0,6040,6046,6158,6156,0,6046,6058,6160,6158,0,6058,6072,6165,6160,0,6072,6083,6172,6165,0,6083,6088,6181,6172,0,6088,6096,6196,6181,0,6096,6106,6204,6196,0,6106,6118,6211,6204,0,6118,6131,6215,6211,0,6131,6133,6218,6215,0,6133,6135,6221,6218,0,6135,6137,6225,6221,0,6137,6140,6230,6225,0,6140,6143,6234,6230,0,6143,6145,6237,6234,0,6145,6153,6249,6237,0,6153,6163,6263,6249,0,6163,6167,6267,6263,0,6167,6173,6274,6267,0,6173,6176,6280,6274,0,6176,6180,6284,6280,0,6180,6185,6290,6284,0,6185,6187,6293,6290,0,6187,6191,6296,6293,0,6191,6193,6299,6296,0,6193,6192,6298,6299,0,6192,6189,6294,6298,0,6189,6186,6291,6294,0,6186,6182,6285,6291,0,6182,6179,6282,6285,0,6179,6174,6275,6282,0,6174,6168,6270,6275,0,6168,6166,6265,6270,0,6166,6162,6261,6265,0,6162,6154,6250,6261,0,6154,6152,6247,6250,0,6247,6254,6340,6335,0,6254,6271,6352,6340,0,6271,6279,6358,6352,0,6279,6287,6366,6358,0,6287,6300,6378,6366,0,6300,6304,6381,6378,0,6304,6306,6384,6381,0,6306,6310,6388,6384,0,6310,6313,6390,6388,0,6313,6316,6392,6390,0,6316,6318,6394,6392,0,6318,6317,6393,6394,0,6317,6315,6391,6393,0,6315,6312,6389,6391,0,6312,6309,6387,6389,0,6309,6305,6383,6387,0,6305,6303,6380,6383,0,6303,6295,6375,6380,0,6295,6289,6367,6375,0,6289,6281,6360,6367,0,6281,6272,6353,6360,0,6272,6241,6330,6353,0,6241,6238,6327,6330,0,6238,6233,6323,6327,0,6233,6229,6319,6323,0,6229,6226,6308,6319,0,6226,6222,6297,6308,0,6222,6219,6283,6297,0,6219,6217,6273,6283,0,6217,6213,6264,6273,0,6213,6210,6258,6264,0,6210,6200,6255,6258,0,6200,6188,6252,6255,0,6188,6178,6245,6252,0,6178,6170,6242,6245,0,6170,6164,6239,6242,0,6164,6161,6236,6239,0,6161,6159,6232,6236,0,6159,6155,6227,6232,0,6155,6150,6223,6227,0,6150,6149,6220,6223,0,6149,6141,6212,6220,0,6141,6144,6214,6212,0,6144,6146,6216,6214,0,6146,6151,6224,6216,0,6151,6156,6228,6224,0,6156,6158,6231,6228,0,6158,6160,6235,6231,0,6160,6165,6240,6235,0,6165,6172,6243,6240,0,6172,6181,6246,6243,0,6181,6196,6253,6246,0,6196,6204,6256,6253,0,6204,6211,6259,6256,0,6211,6215,6266,6259,0,6215,6218,6278,6266,0,6218,6221,6292,6278,0,6221,6225,6307,6292,0,6225,6230,6320,6307,0,6230,6234,6324,6320,0,6234,6237,6326,6324,0,6237,6249,6336,6326,0,6249,6263,6346,6336,0,6263,6267,6350,6346,0,6267,6274,6356,6350,0,6274,6280,6359,6356,0,6280,6284,6364,6359,0,6284,6290,6369,6364,0,6290,6293,6372,6369,0,6293,6296,6376,6372,0,6296,6299,6379,6376,0,6299,6298,6377,6379,0,6298,6294,6374,6377,0,6294,6291,6370,6374,0,6291,6285,6365,6370,0,6285,6282,6362,6365,0,6282,6275,6357,6362,0,6275,6270,6351,6357,0,6270,6265,6348,6351,0,6265,6261,6345,6348,0,6261,6250,6338,6345,0,6250,6247,6335,6338,0,6335,6340,6401,6395,0,6340,6352,6413,6401,0,6352,6358,6419,6413,0,6358,6366,6427,6419,0,6366,6378,6436,6427,0,6378,6381,6441,6436,0,6381,6384,6443,6441,0,6384,6388,6446,6443,0,6388,6390,6448,6446,0,6390,6392,6450,6448,0,6392,6394,6452,6450,0,6394,6393,6451,6452,0,6393,6391,6449,6451,0,6391,6389,6447,6449,0,6389,6387,6445,6447,0,6387,6383,6442,6445,0,6383,6380,6440,6442,0,6380,6375,6434,6440,0,6375,6367,6428,6434,0,6367,6360,6421,6428,0,6360,6353,6414,6421,0,6353,6330,6385,6414,0,6330,6327,6373,6385,0,6327,6323,6361,6373,0,6323,6319,6354,6361,0,6319,6308,6349,6354,0,6308,6297,6344,6349,0,6297,6283,6342,6344,0,6283,6273,6339,6342,0,6273,6264,6334,6339,0,6264,6258,6332,6334,0,6258,6255,6329,6332,0,6255,6252,6325,6329,0,6252,6245,6321,6325,0,6245,6242,6311,6321,0,6242,6239,6301,6311,0,6239,6236,6288,6301,0,6236,6232,6277,6288,0,6232,6227,6268,6277,0,6227,6223,6260,6268,0,6223,6220,6257,6260,0,6220,6212,6244,6257,0,6212,6214,6248,6244,0,6214,6216,6251,6248,0,6216,6224,6262,6251,0,6224,6228,6269,6262,0,6228,6231,6276,6269,0,6231,6235,6286,6276,0,6235,6240,6302,6286,0,6240,6243,6314,6302,0,6243,6246,6322,6314,0,6246,6253,6328,6322,0,6253,6256,6331,6328,0,6256,6259,6333,6331,0,6259,6266,6337,6333,0,6266,6278,6341,6337,0,6278,6292,6343,6341,0,6292,6307,6347,6343,0,6307,6320,6355,6347,0,6320,6324,6363,6355,0,6324,6326,6371,6363,0,6326,6336,6398,6371,0,6336,6346,6407,6398,0,6346,6350,6411,6407,0,6350,6356,6417,6411,0,6356,6359,6420,6417,0,6359,6364,6424,6420,0,6364,6369,6429,6424,0,6369,6372,6431,6429,0,6372,6376,6433,6431,0,6376,6379,6437,6433,0,6379,6377,6435,6437,0,6377,6374,6432,6435,0,6374,6370,6430,6432,0,6370,6365,6426,6430,0,6365,6362,6422,6426,0,6362,6357,6418,6422,0,6357,6351,6412,6418,0,6351,6348,6408,6412,0,6348,6345,6406,6408,0,6345,6338,6397,6406,0,6338,6335,6395,6397,0,6395,6401,6484,6480,0,6401,6413,6501,6484,0,6413,6419,6509,6501,0,6419,6427,6519,6509,0,6427,6436,6529,6519,0,6436,6441,6534,6529,0,6441,6443,6536,6534,0,6443,6446,6541,6536,0,6446,6448,6544,6541,0,6448,6450,6546,6544,0,6450,6452,6548,6546,0,6452,6451,6549,6548,0,6451,6449,6547,6549,0,6449,6447,6545,6547,0,6447,6445,6542,6545,0,6445,6442,6537,6542,0,6442,6440,6535,6537,0,6440,6434,6531,6535,0,6434,6428,6520,6531,0,6428,6421,6511,6520,0,6421,6414,6505,6511,0,6414,6385,6474,6505,0,6385,6373,6472,6474,0,6373,6361,6469,6472,0,6361,6354,6467,6469,0,6354,6349,6466,6467,0,6349,6344,6464,6466,0,6344,6342,6462,6464,0,6342,6339,6460,6462,0,6339,6334,6458,6460,0,6334,6332,6456,6458,0,6332,6329,6454,6456,0,6329,6325,6444,6454,0,6325,6321,6438,6444,0,6321,6311,6423,6438,0,6311,6301,6415,6423,0,6301,6288,6410,6415,0,6288,6277,6405,6410,0,6277,6268,6402,6405,0,6268,6260,6399,6402,0,6260,6257,6396,6399,0,6257,6244,6368,6396,0,6244,6248,6382,6368,0,6248,6251,6386,6382,0,6251,6262,6400,6386,0,6262,6269,6403,6400,0,6269,6276,6404,6403,0,6276,6286,6409,6404,0,6286,6302,6416,6409,0,6302,6314,6425,6416,0,6314,6322,6439,6425,0,6322,6328,6453,6439,0,6328,6331,6455,6453,0,6331,6333,6457,6455,0,6333,6337,6459,6457,0,6337,6341,6461,6459,0,6341,6343,6463,6461,0,6343,6347,6465,6463,0,6347,6355,6468,6465,0,6355,6363,6470,6468,0,6363,6371,6471,6470,0,6371,6398,6482,6471,0,6398,6407,6493,6482,0,6407,6411,6499,6493,0,6411,6417,6507,6499,0,6417,6420,6510,6507,0,6420,6424,6517,6510,0,6424,6429,6521,6517,0,6429,6431,6524,6521,0,6431,6433,6528,6524,0,6433,6437,6533,6528,0,6437,6435,6530,6533,0,6435,6432,6525,6530,0,6432,6430,6522,6525,0,6430,6426,6518,6522,0,6426,6422,6512,6518,0,6422,6418,6508,6512,0,6418,6412,6500,6508,0,6412,6408,6495,6500,0,6408,6406,6492,6495,0,6406,6397,6481,6492,0,6397,6395,6480,6481,0,6480,6484,6603,6597,0,6484,6501,6618,6603,0,6501,6509,6625,6618,0,6509,6519,6636,6625,0,6519,6529,6650,6636,0,6529,6534,6660,6650,0,6534,6536,6665,6660,0,6536,6541,6674,6665,0,6541,6544,6677,6674,0,6544,6546,6681,6677,0,6546,6548,6684,6681,0,6548,6549,6685,6684,0,6549,6547,6683,6685,0,6547,6545,6678,6683,0,6545,6542,6675,6678,0,6542,6537,6666,6675,0,6537,6535,6661,6666,0,6535,6531,6653,6661,0,6531,6520,6641,6653,0,6520,6511,6631,6641,0,6511,6505,6620,6631,0,6505,6474,6592,6620,0,6474,6472,6589,6592,0,6472,6469,6584,6589,0,6469,6467,6580,6584,0,6467,6466,6578,6580,0,6466,6464,6574,6578,0,6464,6462,6570,6574,0,6462,6460,6566,6570,0,6460,6458,6562,6566,0,6458,6456,6558,6562,0,6456,6454,6554,6558,0,6454,6444,6550,6554,0,6444,6438,6538,6550,0,6438,6423,6523,6538,0,6423,6415,6513,6523,0,6415,6410,6503,6513,0,6410,6405,6497,6503,0,6405,6402,6488,6497,0,6402,6399,6485,6488,0,6399,6396,6483,6485,0,6396,6368,6473,6483,0,6368,6382,6476,6473,0,6382,6386,6477,6476,0,6386,6400,6487,6477,0,6400,6403,6489,6487,0,6403,6404,6494,6489,0,6404,6409,6502,6494,0,6409,6416,6514,6502,0,6416,6425,6532,6514,0,6425,6439,6543,6532,0,6439,6453,6553,6543,0,6453,6455,6556,6553,0,6455,6457,6560,6556,0,6457,6459,6565,6560,0,6459,6461,6569,6565,0,6461,6463,6573,6569,0,6463,6465,6577,6573,0,6465,6468,6581,6577,0,6468,6470,6585,6581,0,6470,6471,6588,6585,0,6471,6482,6601,6588,0,6482,6493,6611,6601,0,6493,6499,6615,6611,0,6499,6507,6622,6615,0,6507,6510,6629,6622,0,6510,6517,6634,6629,0,6517,6521,6642,6634,0,6521,6524,6647,6642,0,6524,6528,6651,6647,0,6528,6533,6654,6651,0,6533,6530,6652,6654,0,6530,6525,6648,6652,0,6525,6522,6644,6648,0,6522,6518,6637,6644,0,6518,6512,6632,6637,0,6512,6508,6623,6632,0,6508,6500,6616,6623,0,6500,6495,6612,6616,0,6495,6492,6609,6612,0,6492,6481,6599,6609,0,6481,6480,6597,6599,0,6597,6603,6606,6602,0,6603,6618,6630,6606,0,6618,6625,6643,6630,0,6625,6636,6656,6643,0,6636,6650,6669,6656,0,6650,6660,6679,6669,0,6660,6665,6686,6679,0,6665,6674,6688,6686,0,6674,6677,6691,6688,0,6677,6681,6693,6691,0,6681,6684,6696,6693,0,6684,6685,6697,6696,0,6685,6683,6694,6697,0,6683,6678,6692,6694,0,6678,6675,6689,6692,0,6675,6666,6687,6689,0,6666,6661,6682,6687,0,6661,6653,6672,6682,0,6653,6641,6662,6672,0,6641,6631,6646,6662,0,6631,6620,6633,6646,0,6620,6592,6596,6633,0,6592,6589,6594,6596,0,6589,6584,6590,6594,0,6584,6580,6586,6590,0,6580,6578,6583,6586,0,6578,6574,6579,6583,0,6574,6570,6575,6579,0,6570,6566,6571,6575,0,6566,6562,6567,6571,0,6562,6558,6563,6567,0,6558,6554,6559,6563,0,6554,6550,6555,6559,0,6550,6538,6551,6555,0,6538,6523,6539,6551,0,6523,6513,6526,6539,0,6513,6503,6516,6526,0,6503,6497,6506,6516,0,6497,6488,6496,6506,0,6488,6485,6490,6496,0,6485,6483,6486,6490,0,6483,6473,6475,6486,0,6473,6476,6478,6475,0,6476,6477,6479,6478,0,6477,6487,6491,6479,0,6487,6489,6498,6491,0,6489,6494,6504,6498,0,6494,6502,6515,6504,0,6502,6514,6527,6515,0,6514,6532,6540,6527,0,6532,6543,6552,6540,0,6543,6553,6557,6552,0,6553,6556,6561,6557,0,6556,6560,6564,6561,0,6560,6565,6568,6564,0,6565,6569,6572,6568,0,6569,6573,6576,6572,0,6573,6577,6582,6576,0,6577,6581,6587,6582,0,6581,6585,6591,6587,0,6585,6588,6593,6591,0,6588,6601,6605,6593,0,6601,6611,6619,6605,0,6611,6615,6627,6619,0,6615,6622,6635,6627,0,6622,6629,6645,6635,0,6629,6634,6655,6645,0,6634,6642,6663,6655,0,6642,6647,6667,6663,0,6647,6651,6670,6667,0,6651,6654,6673,6670,0,6654,6652,6671,6673,0,6652,6648,6668,6671,0,6648,6644,6664,6668,0,6644,6637,6658,6664,0,6637,6632,6649,6658,0,6632,6623,6639,6649,0,6623,6616,6628,6639,0,6616,6612,6621,6628,0,6612,6609,6617,6621,0,6609,6599,6604,6617,0,6599,6597,6602,6604,0,6602,6606,6726,6723,0,6606,6630,6739,6726,0,6630,6643,6744,6739,0,6643,6656,6751,6744,0,6656,6669,6760,6751,0,6669,6679,6767,6760,0,6679,6686,6771,6767,0,6686,6688,6773,6771,0,6688,6691,6775,6773,0,6691,6693,6778,6775,0,6693,6696,6780,6778,0,6696,6697,6781,6780,0,6697,6694,6779,6781,0,6694,6692,6776,6779,0,6692,6689,6774,6776,0,6689,6687,6772,6774,0,6687,6682,6769,6772,0,6682,6672,6764,6769,0,6672,6662,6755,6764,0,6662,6646,6748,6755,0,6646,6633,6740,6748,0,6633,6596,6720,6740,0,6596,6594,6718,6720,0,6594,6590,6715,6718,0,6590,6586,6713,6715,0,6586,6583,6712,6713,0,6583,6579,6710,6712,0,6579,6575,6708,6710,0,6575,6571,6706,6708,0,6571,6567,6704,6706,0,6567,6563,6702,6704,0,6563,6559,6700,6702,0,6559,6555,6698,6700,0,6555,6551,6690,6698,0,6551,6539,6676,6690,0,6539,6526,6657,6676,0,6526,6516,6640,6657,0,6516,6506,6626,6640,0,6506,6496,6613,6626,0,6496,6490,6608,6613,0,6490,6486,6607,6608,0,6486,6475,6595,6607,0,6475,6478,6598,6595,0,6478,6479,6600,6598,0,6479,6491,6610,6600,0,6491,6498,6614,6610,0,6498,6504,6624,6614,0,6504,6515,6638,6624,0,6515,6527,6659,6638,0,6527,6540,6680,6659,0,6540,6552,6695,6680,0,6552,6557,6699,6695,0,6557,6561,6701,6699,0,6561,6564,6703,6701,0,6564,6568,6705,6703,0,6568,6572,6707,6705,0,6572,6576,6709,6707,0,6576,6582,6711,6709,0,6582,6587,6714,6711,0,6587,6591,6716,6714,0,6591,6593,6717,6716,0,6593,6605,6725,6717,0,6605,6619,6733,6725,0,6619,6627,6736,6733,0,6627,6635,6741,6736,0,6635,6645,6746,6741,0,6645,6655,6750,6746,0,6655,6663,6756,6750,0,6663,6667,6758,6756,0,6667,6670,6761,6758,0,6670,6673,6763,6761,0,6673,6671,6762,6763,0,6671,6668,6759,6762,0,6668,6664,6757,6759,0,6664,6658,6752,6757,0,6658,6649,6747,6752,0,6649,6639,6742,6747,0,6639,6628,6737,6742,0,6628,6621,6734,6737,0,6621,6617,6730,6734,0,6617,6604,6724,6730,0,6604,6602,6723,6724,0,6723,6726,6838,6831,0,6726,6739,6856,6838,0,6739,6744,6862,6856,0,6744,6751,6869,6862,0,6751,6760,6879,6869,0,6760,6767,6884,6879,0,6767,6771,6888,6884,0,6771,6773,6892,6888,0,6773,6775,6894,6892,0,6775,6778,6898,6894,0,6778,6780,6900,6898,0,6780,6781,6901,6900,0,6781,6779,6899,6901,0,6779,6776,6896,6899,0,6776,6774,6893,6896,0,6774,6772,6890,6893,0,6772,6769,6885,6890,0,6769,6764,6883,6885,0,6764,6755,6873,6883,0,6755,6748,6867,6873,0,6748,6740,6857,6867,0,6740,6720,6826,6857,0,6720,6718,6823,6826,0,6718,6715,6818,6823,0,6715,6713,6814,6818,0,6713,6712,6812,6814,0,6712,6710,6808,6812,0,6710,6708,6804,6808,0,6708,6706,6800,6804,0,6706,6704,6796,6800,0,6704,6702,6792,6796,0,6702,6700,6788,6792,0,6700,6698,6784,6788,0,6698,6690,6777,6784,0,6690,6676,6768,6777,0,6676,6657,6753,6768,0,6657,6640,6745,6753,0,6640,6626,6738,6745,0,6626,6613,6731,6738,0,6613,6608,6728,6731,0,6608,6607,6727,6728,0,6607,6595,6719,6727,0,6595,6598,6721,6719,0,6598,6600,6722,6721,0,6600,6610,6729,6722,0,6610,6614,6732,6729,0,6614,6624,6735,6732,0,6624,6638,6743,6735,0,6638,6659,6754,6743,0,6659,6680,6770,6754,0,6680,6695,6782,6770,0,6695,6699,6785,6782,0,6699,6701,6789,6785,0,6701,6703,6793,6789,0,6703,6705,6797,6793,0,6705,6707,6803,6797,0,6707,6709,6807,6803,0,6709,6711,6811,6807,0,6711,6714,6815,6811,0,6714,6716,6819,6815,0,6716,6717,6822,6819,0,6717,6725,6836,6822,0,6725,6733,6848,6836,0,6733,6736,6852,6848,0,6736,6741,6859,6852,0,6741,6746,6865,6859,0,6746,6750,6870,6865,0,6750,6756,6875,6870,0,6756,6758,6877,6875,0,6758,6761,6880,6877,0,6761,6763,6882,6880,0,6763,6762,6881,6882,0,6762,6759,6878,6881,0,6759,6757,6876,6878,0,6757,6752,6871,6876,0,6752,6747,6866,6871,0,6747,6742,6861,6866,0,6742,6737,6853,6861,0,6737,6734,6849,6853,0,6734,6730,6845,6849,0,6730,6724,6832,6845,0,6724,6723,6831,6832,0,6831,6838,6903,6889,0,6838,6856,6915,6903,0,6856,6862,6921,6915,0,6862,6869,6926,6921,0,6869,6879,6935,6926,0,6879,6884,6941,6935,0,6884,6888,6944,6941,0,6888,6892,6946,6944,0,6892,6894,6949,6946,0,6894,6898,6951,6949,0,6898,6900,6953,6951,0,6900,6901,6954,6953,0,6901,6899,6952,6954,0,6899,6896,6950,6952,0,6896,6893,6948,6950,0,6893,6890,6945,6948,0,6890,6885,6942,6945,0,6885,6883,6939,6942,0,6883,6873,6930,6939,0,6873,6867,6924,6930,0,6867,6857,6917,6924,0,6857,6826,6868,6917,0,6826,6823,6860,6868,0,6823,6818,6850,6860,0,6818,6814,6843,6850,0,6814,6812,6841,6843,0,6812,6808,6839,6841,0,6808,6804,6834,6839,0,6804,6800,6829,6834,0,6800,6796,6825,6829,0,6796,6792,6821,6825,0,6792,6788,6817,6821,0,6788,6784,6813,6817,0,6784,6777,6809,6813,0,6777,6768,6805,6809,0,6768,6753,6801,6805,0,6753,6745,6799,6801,0,6745,6738,6795,6799,0,6738,6731,6790,6795,0,6731,6728,6786,6790,0,6728,6727,6783,6786,0,6727,6719,6749,6783,0,6719,6721,6765,6749,0,6721,6722,6766,6765,0,6722,6729,6787,6766,0,6729,6732,6791,6787,0,6732,6735,6794,6791,0,6735,6743,6798,6794,0,6743,6754,6802,6798,0,6754,6770,6806,6802,0,6770,6782,6810,6806,0,6782,6785,6816,6810,0,6785,6789,6820,6816,0,6789,6793,6824,6820,0,6793,6797,6827,6824,0,6797,6803,6830,6827,0,6803,6807,6837,6830,0,6807,6811,6840,6837,0,6811,6815,6844,6840,0,6815,6819,6851,6844,0,6819,6822,6858,6851,0,6822,6836,6895,6858,0,6836,6848,6909,6895,0,6848,6852,6913,6909,0,6852,6859,6918,6913,0,6859,6865,6922,6918,0,6865,6870,6927,6922,0,6870,6875,6931,6927,0,6875,6877,6933,6931,0,6877,6880,6936,6933,0,6880,6882,6938,6936,0,6882,6881,6937,6938,0,6881,6878,6934,6937,0,6878,6876,6932,6934,0,6876,6871,6928,6932,0,6871,6866,6923,6928,0,6866,6861,6919,6923,0,6861,6853,6914,6919,0,6853,6849,6910,6914,0,6849,6845,6908,6910,0,6845,6832,6891,6908,0,6832,6831,6889,6891,0,6889,6903,6973,6969,0,6903,6915,6985,6973,0,6915,6921,6991,6985,0,6921,6926,6997,6991,0,6926,6935,7005,6997,0,6935,6941,7012,7005,0,6941,6944,7014,7012,0,6944,6946,7017,7014,0,6946,6949,7020,7017,0,6949,6951,7022,7020,0,6951,6953,7024,7022,0,6953,6954,7025,7024,0,6954,6952,7023,7025,0,6952,6950,7021,7023,0,6950,6948,7018,7021,0,6948,6945,7015,7018,0,6945,6942,7013,7015,0,6942,6939,7010,7013,0,6939,6930,7000,7010,0,6930,6924,6994,7000,0,6924,6917,6987,6994,0,6917,6868,6966,6987,0,6868,6860,6964,6966,0,6860,6850,6961,6964,0,6850,6843,6959,6961,0,6843,6841,6958,6959,0,6841,6839,6956,6958,0,6839,6834,6947,6956,0,6834,6829,6940,6947,0,6829,6825,6925,6940,0,6825,6821,6916,6925,0,6821,6817,6911,6916,0,6817,6813,6906,6911,0,6813,6809,6904,6906,0,6809,6805,6897,6904,0,6805,6801,6886,6897,0,6801,6799,6874,6886,0,6799,6795,6864,6874,0,6795,6790,6854,6864,0,6790,6786,6846,6854,0,6786,6783,6842,6846,0,6783,6749,6828,6842,0,6749,6765,6833,6828,0,6765,6766,6835,6833,0,6766,6787,6847,6835,0,6787,6791,6855,6847,0,6791,6794,6863,6855,0,6794,6798,6872,6863,0,6798,6802,6887,6872,0,6802,6806,6902,6887,0,6806,6810,6905,6902,0,6810,6816,6907,6905,0,6816,6820,6912,6907,0,6820,6824,6920,6912,0,6824,6827,6929,6920,0,6827,6830,6943,6929,0,6830,6837,6955,6943,0,6837,6840,6957,6955,0,6840,6844,6960,6957,0,6844,6851,6962,6960,0,6851,6858,6963,6962,0,6858,6895,6971,6963,0,6895,6909,6980,6971,0,6909,6913,6984,6980,0,6913,6918,6990,6984,0,6918,6922,6993,6990,0,6922,6927,6999,6993,0,6927,6931,7002,6999,0,6931,6933,7004,7002,0,6933,6936,7007,7004,0,6936,6938,7009,7007,0,6938,6937,7006,7009,0,6937,6934,7003,7006,0,6934,6932,7001,7003,0,6932,6928,6998,7001,0,6928,6923,6992,6998,0,6923,6919,6989,6992,0,6919,6914,6983,6989,0,6914,6910,6979,6983,0,6910,6908,6978,6979,0,6908,6891,6970,6978,0,6891,6889,6969,6970,0,6969,6973,7064,7058,0,6973,6985,7079,7064,0,6985,6991,7088,7079,0,6991,6997,7095,7088,0,6997,7005,7105,7095,0,7005,7012,7112,7105,0,7012,7014,7116,7112,0,7014,7017,7120,7116,0,7017,7020,7122,7120,0,7020,7022,7124,7122,0,7022,7024,7127,7124,0,7024,7025,7128,7127,0,7025,7023,7126,7128,0,7023,7021,7123,7126,0,7021,7018,7121,7123,0,7018,7015,7118,7121,0,7015,7013,7114,7118,0,7013,7010,7111,7114,0,7010,7000,7100,7111,0,7000,6994,7094,7100,0,6994,6987,7084,7094,0,6987,6966,7055,7084,0,6966,6964,7052,7055,0,6964,6961,7047,7052,0,6961,6959,7044,7047,0,6959,6958,7043,7044,0,6958,6956,7039,7043,0,6956,6947,7036,7039,0,6947,6940,7034,7036,0,6940,6925,7032,7034,0,6925,6916,7030,7032,0,6916,6911,7028,7030,0,6911,6906,7026,7028,0,6906,6904,7016,7026,0,6904,6897,7008,7016,0,6897,6886,6996,7008,0,6886,6874,6988,6996,0,6874,6864,6982,6988,0,6864,6854,6976,6982,0,6854,6846,6974,6976,0,6846,6842,6972,6974,0,6842,6828,6965,6972,0,6828,6833,6967,6965,0,6833,6835,6968,6967,0,6835,6847,6975,6968,0,6847,6855,6977,6975,0,6855,6863,6981,6977,0,6863,6872,6986,6981,0,6872,6887,6995,6986,0,6887,6902,7011,6995,0,6902,6905,7019,7011,0,6905,6907,7027,7019,0,6907,6912,7029,7027,0,6912,6920,7031,7029,0,6920,6929,7033,7031,0,6929,6943,7035,7033,0,6943,6955,7038,7035,0,6955,6957,7042,7038,0,6957,6960,7045,7042,0,6960,6962,7048,7045,0,6962,6963,7050,7048,0,6963,6971,7063,7050,0,6971,6980,7075,7063,0,6980,6984,7080,7075,0,6984,6990,7086,7080,0,6990,6993,7091,7086,0,6993,6999,7097,7091,0,6999,7002,7101,7097,0,7002,7004,7106,7101,0,7004,7007,7109,7106,0,7007,7009,7110,7109,0,7009,7006,7108,7110,0,7006,7003,7104,7108,0,7003,7001,7099,7104,0,7001,6998,7096,7099,0,6998,6992,7089,7096,0,6992,6989,7085,7089,0,6989,6983,7078,7085,0,6983,6979,7074,7078,0,6979,6978,7072,7074,0,6978,6970,7060,7072,0,6970,6969,7058,7060,0,7058,7064,7163,7158,0,7064,7079,7175,7163,0,7079,7088,7183,7175,0,7088,7095,7190,7183,0,7095,7105,7197,7190,0,7105,7112,7203,7197,0,7112,7116,7207,7203,0,7116,7120,7209,7207,0,7120,7122,7213,7209,0,7122,7124,7215,7213,0,7124,7127,7218,7215,0,7127,7128,7219,7218,0,7128,7126,7217,7219,0,7126,7123,7214,7217,0,7123,7121,7211,7214,0,7121,7118,7208,7211,0,7118,7114,7205,7208,0,7114,7111,7202,7205,0,7111,7100,7194,7202,0,7100,7094,7187,7194,0,7094,7084,7179,7187,0,7084,7055,7154,7179,0,7055,7052,7152,7154,0,7052,7047,7147,7152,0,7047,7044,7143,7147,0,7044,7043,7140,7143,0,7043,7039,7136,7140,0,7039,7036,7132,7136,0,7036,7034,7125,7132,0,7034,7032,7113,7125,0,7032,7030,7098,7113,0,7030,7028,7087,7098,0,7028,7026,7077,7087,0,7026,7016,7071,7077,0,7016,7008,7069,7071,0,7008,6996,7066,7069,0,6996,6988,7061,7066,0,6988,6982,7057,7061,0,6982,6976,7053,7057,0,6976,6974,7049,7053,0,6974,6972,7046,7049,0,6972,6965,7037,7046,0,6965,6967,7040,7037,0,6967,6968,7041,7040,0,6968,6975,7051,7041,0,6975,6977,7054,7051,0,6977,6981,7056,7054,0,6981,6986,7059,7056,0,6986,6995,7065,7059,0,6995,7011,7070,7065,0,7011,7019,7073,7070,0,7019,7027,7082,7073,0,7027,7029,7090,7082,0,7029,7031,7102,7090,0,7031,7033,7119,7102,0,7033,7035,7131,7119,0,7035,7038,7135,7131,0,7038,7042,7139,7135,0,7042,7045,7144,7139,0,7045,7048,7148,7144,0,7048,7050,7150,7148,0,7050,7063,7161,7150,0,7063,7075,7171,7161,0,7075,7080,7176,7171,0,7080,7086,7182,7176,0,7086,7091,7186,7182,0,7091,7097,7192,7186,0,7097,7101,7195,7192,0,7101,7106,7198,7195,0,7106,7109,7200,7198,0,7109,7110,7201,7200,0,7110,7108,7199,7201,0,7108,7104,7196,7199,0,7104,7099,7193,7196,0,7099,7096,7191,7193,0,7096,7089,7184,7191,0,7089,7085,7181,7184,0,7085,7078,7174,7181,0,7078,7074,7170,7174,0,7074,7072,7169,7170,0,7072,7060,7159,7169,0,7060,7058,7158,7159,0,7158,7163,7216,7204,0,7163,7175,7231,7216,0,7175,7183,7237,7231,0,7183,7190,7243,7237,0,7190,7197,7251,7243,0,7197,7203,7258,7251,0,7203,7207,7261,7258,0,7207,7209,7264,7261,0,7209,7213,7266,7264,0,7213,7215,7268,7266,0,7215,7218,7271,7268,0,7218,7219,7272,7271,0,7219,7217,7270,7272,0,7217,7214,7267,7270,0,7214,7211,7265,7267,0,7211,7208,7263,7265,0,7208,7205,7260,7263,0,7205,7202,7257,7260,0,7202,7194,7248,7257,0,7194,7187,7242,7248,0,7187,7179,7234,7242,0,7179,7154,7189,7234,0,7154,7152,7180,7189,0,7152,7147,7172,7180,0,7147,7143,7168,7172,0,7143,7140,7166,7168,0,7140,7136,7164,7166,0,7136,7132,7160,7164,0,7132,7125,7156,7160,0,7125,7113,7153,7156,0,7113,7098,7149,7153,0,7098,7087,7145,7149,0,7087,7077,7141,7145,0,7077,7071,7137,7141,0,7071,7069,7133,7137,0,7069,7066,7130,7133,0,7066,7061,7117,7130,0,7061,7057,7107,7117,0,7057,7053,7092,7107,0,7053,7049,7081,7092,0,7049,7046,7076,7081,0,7046,7037,7062,7076,0,7037,7040,7067,7062,0,7040,7041,7068,7067,0,7041,7051,7083,7068,0,7051,7054,7093,7083,0,7054,7056,7103,7093,0,7056,7059,7115,7103,0,7059,7065,7129,7115,0,7065,7070,7134,7129,0,7070,7073,7138,7134,0,7073,7082,7142,7138,0,7082,7090,7146,7142,0,7090,7102,7151,7146,0,7102,7119,7155,7151,0,7119,7131,7157,7155,0,7131,7135,7162,7157,0,7135,7139,7165,7162,0,7139,7144,7167,7165,0,7144,7148,7173,7167,0,7148,7150,7178,7173,0,7150,7161,7212,7178,0,7161,7171,7228,7212,0,7171,7176,7233,7228,0,7176,7182,7236,7233,0,7182,7186,7241,7236,0,7186,7192,7245,7241,0,7192,7195,7250,7245,0,7195,7198,7253,7250,0,7198,7200,7255,7253,0,7200,7201,7256,7255,0,7201,7199,7254,7256,0,7199,7196,7252,7254,0,7196,7193,7247,7252,0,7193,7191,7244,7247,0,7191,7184,7240,7244,0,7184,7181,7235,7240,0,7181,7174,7230,7235,0,7174,7170,7227,7230,0,7170,7169,7224,7227,0,7169,7159,7206,7224,0,7159,7158,7204,7206,0,7204,7216,7297,7294,0,7216,7231,7308,7297,0,7231,7237,7314,7308,0,7237,7243,7320,7314,0,7243,7251,7328,7320,0,7251,7258,7338,7328,0,7258,7261,7340,7338,0,7261,7264,7345,7340,0,7264,7266,7348,7345,0,7266,7268,7350,7348,0,7268,7271,7352,7350,0,7271,7272,7354,7352,0,7272,7270,7351,7354,0,7270,7267,7349,7351,0,7267,7265,7346,7349,0,7265,7263,7343,7346,0,7263,7260,7339,7343,0,7260,7257,7337,7339,0,7257,7248,7326,7337,0,7248,7242,7318,7326,0,7242,7234,7311,7318,0,7234,7189,7293,7311,0,7189,7180,7292,7293,0,7180,7172,7289,7292,0,7172,7168,7288,7289,0,7168,7166,7286,7288,0,7166,7164,7284,7286,0,7164,7160,7282,7284,0,7160,7156,7280,7282,0,7156,7153,7278,7280,0,7153,7149,7276,7278,0,7149,7145,7274,7276,0,7145,7141,7269,7274,0,7141,7137,7259,7269,0,7137,7133,7246,7259,0,7133,7130,7239,7246,0,7130,7117,7232,7239,0,7117,7107,7226,7232,0,7107,7092,7223,7226,0,7092,7081,7220,7223,0,7081,7076,7210,7220,0,7076,7062,7177,7210,0,7062,7067,7185,7177,0,7067,7068,7188,7185,0,7068,7083,7221,7188,0,7083,7093,7222,7221,0,7093,7103,7225,7222,0,7103,7115,7229,7225,0,7115,7129,7238,7229,0,7129,7134,7249,7238,0,7134,7138,7262,7249,0,7138,7142,7273,7262,0,7142,7146,7275,7273,0,7146,7151,7277,7275,0,7151,7155,7279,7277,0,7155,7157,7281,7279,0,7157,7162,7283,7281,0,7162,7165,7285,7283,0,7165,7167,7287,7285,0,7167,7173,7290,7287,0,7173,7178,7291,7290,0,7178,7212,7296,7291,0,7212,7228,7306,7296,0,7228,7233,7309,7306,0,7233,7236,7313,7309,0,7236,7241,7317,7313,0,7241,7245,7323,7317,0,7245,7250,7325,7323,0,7250,7253,7330,7325,0,7253,7255,7333,7330,0,7255,7256,7334,7333,0,7256,7254,7332,7334,0,7254,7252,7329,7332,0,7252,7247,7324,7329,0,7247,7244,7321,7324,0,7244,7240,7315,7321,0,7240,7235,7310,7315,0,7235,7230,7307,7310,0,7230,7227,7305,7307,0,7227,7224,7302,7305,0,7224,7206,7295,7302,0,7206,7204,7294,7295,0,7294,7297,7425,7419,0,7297,7308,7442,7425,0,7308,7314,7453,7442,0,7314,7320,7462,7453,0,7320,7328,7474,7462,0,7328,7338,7485,7474,0,7338,7340,7495,7485,0,7340,7345,7499,7495,0,7345,7348,7504,7499,0,7348,7350,7506,7504,0,7350,7352,7510,7506,0,7352,7354,7511,7510,0,7354,7351,7509,7511,0,7351,7349,7505,7509,0,7349,7346,7502,7505,0,7346,7343,7498,7502,0,7343,7339,7492,7498,0,7339,7337,7482,7492,0,7337,7326,7471,7482,0,7326,7318,7460,7471,0,7318,7311,7450,7460,0,7311,7293,7417,7450,0,7293,7292,7413,7417,0,7292,7289,7407,7413,0,7289,7288,7403,7407,0,7288,7286,7399,7403,0,7286,7284,7395,7399,0,7284,7282,7391,7395,0,7282,7280,7388,7391,0,7280,7278,7384,7388,0,7278,7276,7380,7384,0,7276,7274,7375,7380,0,7274,7269,7372,7375,0,7269,7259,7368,7372,0,7259,7246,7364,7368,0,7246,7239,7361,7364,0,7239,7232,7357,7361,0,7232,7226,7347,7357,0,7226,7223,7336,7347,0,7223,7220,7319,7336,0,7220,7210,7312,7319,0,7210,7177,7298,7312,0,7177,7185,7300,7298,0,7185,7188,7301,7300,0,7188,7221,7322,7301,0,7221,7222,7335,7322,0,7222,7225,7344,7335,0,7225,7229,7356,7344,0,7229,7238,7360,7356,0,7238,7249,7365,7360,0,7249,7262,7369,7365,0,7262,7273,7373,7369,0,7273,7275,7377,7373,0,7275,7277,7381,7377,0,7277,7279,7385,7381,0,7279,7281,7389,7385,0,7281,7283,7394,7389,0,7283,7285,7398,7394,0,7285,7287,7402,7398,0,7287,7290,7408,7402,0,7290,7291,7411,7408,0,7291,7296,7424,7411,0,7296,7306,7438,7424,0,7306,7309,7444,7438,0,7309,7313,7452,7444,0,7313,7317,7457,7452,0,7317,7323,7466,7457,0,7323,7325,7470,7466,0,7325,7330,7476,7470,0,7330,7333,7479,7476,0,7333,7334,7480,7479,0,7334,7332,7478,7480,0,7332,7329,7475,7478,0,7329,7324,7468,7475,0,7324,7321,7464,7468,0,7321,7315,7454,7464,0,7315,7310,7449,7454,0,7310,7307,7441,7449,0,7307,7305,7435,7441,0,7305,7302,7434,7435,0,7302,7295,7421,7434,0,7295,7294,7419,7421,0,7419,7425,7429,7422,0,7425,7442,7448,7429,0,7442,7453,7459,7448,0,7453,7462,7472,7459,0,7462,7474,7488,7472,0,7474,7485,7497,7488,0,7485,7495,7503,7497,0,7495,7499,7512,7503,0,7499,7504,7514,7512,0,7504,7506,7516,7514,0,7506,7510,7519,7516,0,7510,7511,7520,7519,0,7511,7509,7518,7520,0,7509,7505,7515,7518,0,7505,7502,7513,7515,0,7502,7498,7507,7513,0,7498,7492,7501,7507,0,7492,7482,7496,7501,0,7482,7471,7486,7496,0,7471,7460,7469,7486,0,7460,7450,7456,7469,0,7450,7417,7418,7456,0,7417,7413,7416,7418,0,7413,7407,7409,7416,0,7407,7403,7405,7409,0,7403,7399,7401,7405,0,7399,7395,7397,7401,0,7395,7391,7393,7397,0,7391,7388,7390,7393,0,7388,7384,7386,7390,0,7384,7380,7382,7386,0,7380,7375,7378,7382,0,7375,7372,7374,7378,0,7372,7368,7370,7374,0,7368,7364,7366,7370,0,7364,7361,7363,7366,0,7361,7357,7359,7363,0,7357,7347,7355,7359,0,7347,7336,7342,7355,0,7336,7319,7327,7342,0,7319,7312,7316,7327,0,7312,7298,7299,7316,0,7298,7300,7303,7299,0,7300,7301,7304,7303,0,7301,7322,7331,7304,0,7322,7335,7341,7331,0,7335,7344,7353,7341,0,7344,7356,7358,7353,0,7356,7360,7362,7358,0,7360,7365,7367,7362,0,7365,7369,7371,7367,0,7369,7373,7376,7371,0,7373,7377,7379,7376,0,7377,7381,7383,7379,0,7381,7385,7387,7383,0,7385,7389,7392,7387,0,7389,7394,7396,7392,0,7394,7398,7400,7396,0,7398,7402,7404,7400,0,7402,7408,7410,7404,0,7408,7411,7415,7410,0,7411,7424,7428,7415,0,7424,7438,7443,7428,0,7438,7444,7451,7443,0,7444,7452,7458,7451,0,7452,7457,7467,7458,0,7457,7466,7477,7467,0,7466,7470,7484,7477,0,7470,7476,7490,7484,0,7476,7479,7493,7490,0,7479,7480,7494,7493,0,7480,7478,7491,7494,0,7478,7475,7489,7491,0,7475,7468,7483,7489,0,7468,7464,7473,7483,0,7464,7454,7465,7473,0,7454,7449,7455,7465,0,7449,7441,7447,7455,0,7441,7435,7440,7447,0,7435,7434,7437,7440,0,7434,7421,7423,7437,0,7421,7419,7422,7423,0,7422,7429,7543,7540,0,7429,7448,7551,7543,0,7448,7459,7555,7551,0,7459,7472,7560,7555,0,7472,7488,7567,7560,0,7488,7497,7574,7567,0,7497,7503,7578,7574,0,7503,7512,7580,7578,0,7512,7514,7582,7580,0,7514,7516,7586,7582,0,7516,7519,7588,7586,0,7519,7520,7589,7588,0,7520,7518,7587,7589,0,7518,7515,7585,7587,0,7515,7513,7581,7585,0,7513,7507,7579,7581,0,7507,7501,7577,7579,0,7501,7496,7573,7577,0,7496,7486,7566,7573,0,7486,7469,7559,7566,0,7469,7456,7554,7559,0,7456,7418,7539,7554,0,7418,7416,7538,7539,0,7416,7409,7535,7538,0,7409,7405,7534,7535,0,7405,7401,7532,7534,0,7401,7397,7530,7532,0,7397,7393,7528,7530,0,7393,7390,7526,7528,0,7390,7386,7524,7526,0,7386,7382,7522,7524,0,7382,7378,7517,7522,0,7378,7374,7500,7517,0,7374,7370,7481,7500,0,7370,7366,7461,7481,0,7366,7363,7446,7461,0,7363,7359,7439,7446,0,7359,7355,7433,7439,0,7355,7342,7431,7433,0,7342,7327,7426,7431,0,7327,7316,7420,7426,0,7316,7299,7406,7420,0,7299,7303,7412,7406,0,7303,7304,7414,7412,0,7304,7331,7427,7414,0,7331,7341,7430,7427,0,7341,7353,7432,7430,0,7353,7358,7436,7432,0,7358,7362,7445,7436,0,7362,7367,7463,7445,0,7367,7371,7487,7463,0,7371,7376,7508,7487,0,7376,7379,7521,7508,0,7379,7383,7523,7521,0,7383,7387,7525,7523,0,7387,7392,7527,7525,0,7392,7396,7529,7527,0,7396,7400,7531,7529,0,7400,7404,7533,7531,0,7404,7410,7536,7533,0,7410,7415,7537,7536,0,7415,7428,7542,7537,0,7428,7443,7547,7542,0,7443,7451,7552,7547,0,7451,7458,7556,7552,0,7458,7467,7558,7556,0,7467,7477,7562,7558,0,7477,7484,7565,7562,0,7484,7490,7569,7565,0,7490,7493,7571,7569,0,7493,7494,7572,7571,0,7494,7491,7570,7572,0,7491,7489,7568,7570,0,7489,7483,7564,7568,0,7483,7473,7561,7564,0,7473,7465,7557,7561,0,7465,7455,7553,7557,0,7455,7447,7550,7553,0,7447,7440,7546,7550,0,7440,7437,7545,7546,0,7437,7423,7541,7545,0,7423,7422,7540,7541,0,7540,7543,7656,7650,0,7543,7551,7675,7656,0,7551,7555,7683,7675,0,7555,7560,7692,7683,0,7560,7567,7700,7692,0,7567,7574,7709,7700,0,7574,7578,7712,7709,0,7578,7580,7715,7712,0,7580,7582,7718,7715,0,7582,7586,7720,7718,0,7586,7588,7722,7720,0,7588,7589,7724,7722,0,7589,7587,7721,7724,0,7587,7585,7719,7721,0,7585,7581,7717,7719,0,7581,7579,7714,7717,0,7579,7577,7711,7714,0,7577,7573,7708,7711,0,7573,7566,7699,7708,0,7566,7559,7691,7699,0,7559,7554,7682,7691,0,7554,7539,7646,7682,0,7539,7538,7643,7646,0,7538,7535,7636,7643,0,7535,7534,7633,7636,0,7534,7532,7630,7633,0,7532,7530,7626,7630,0,7530,7528,7622,7626,0,7528,7526,7618,7622,0,7526,7524,7614,7618,0,7524,7522,7610,7614,0,7522,7517,7606,7610,0,7517,7500,7603,7606,0,7500,7481,7601,7603,0,7481,7461,7597,7601,0,7461,7446,7595,7597,0,7446,7439,7593,7595,0,7439,7433,7591,7593,0,7433,7431,7584,7591,0,7431,7426,7575,7584,0,7426,7420,7563,7575,0,7420,7406,7544,7563,0,7406,7412,7548,7544,0,7412,7414,7549,7548,0,7414,7427,7576,7549,0,7427,7430,7583,7576,0,7430,7432,7590,7583,0,7432,7436,7592,7590,0,7436,7445,7594,7592,0,7445,7463,7598,7594,0,7463,7487,7602,7598,0,7487,7508,7604,7602,0,7508,7521,7607,7604,0,7521,7523,7611,7607,0,7523,7525,7615,7611,0,7525,7527,7620,7615,0,7527,7529,7625,7620,0,7529,7531,7629,7625,0,7531,7533,7632,7629,0,7533,7536,7638,7632,0,7536,7537,7642,7638,0,7537,7542,7657,7642,0,7542,7547,7673,7657,0,7547,7552,7678,7673,0,7552,7556,7684,7678,0,7556,7558,7690,7684,0,7558,7562,7694,7690,0,7562,7565,7698,7694,0,7565,7569,7704,7698,0,7569,7571,7706,7704,0,7571,7572,7707,7706,0,7572,7570,7705,7707,0,7570,7568,7703,7705,0,7568,7564,7696,7703,0,7564,7561,7693,7696,0,7561,7557,7687,7693,0,7557,7553,7681,7687,0,7553,7550,7674,7681,0,7550,7546,7670,7674,0,7546,7545,7667,7670,0,7545,7541,7652,7667,0,7541,7540,7650,7652,0,7650,7656,7729,7725,0,7656,7675,7741,7729,0,7675,7683,7746,7741,0,7683,7692,7753,7746,0,7692,7700,7762,7753,0,7700,7709,7769,7762,0,7709,7712,7773,7769,0,7712,7715,7775,7773,0,7715,7718,7777,7775,0,7718,7720,7780,7777,0,7720,7722,7782,7780,0,7722,7724,7784,7782,0,7724,7721,7781,7784,0,7721,7719,7779,7781,0,7719,7717,7776,7779,0,7717,7714,7774,7776,0,7714,7711,7772,7774,0,7711,7708,7768,7772,0,7708,7699,7761,7768,0,7699,7691,7754,7761,0,7691,7682,7747,7754,0,7682,7646,7713,7747,0,7646,7643,7702,7713,0,7643,7636,7688,7702,0,7636,7633,7680,7688,0,7633,7630,7672,7680,0,7630,7626,7666,7672,0,7626,7622,7662,7666,0,7622,7618,7658,7662,0,7618,7614,7651,7658,0,7614,7610,7647,7651,0,7610,7606,7644,7647,0,7606,7603,7637,7644,0,7603,7601,7631,7637,0,7601,7597,7627,7631,0,7597,7595,7624,7627,0,7595,7593,7621,7624,0,7593,7591,7617,7621,0,7591,7584,7613,7617,0,7584,7575,7608,7613,0,7575,7563,7605,7608,0,7563,7544,7596,7605,0,7544,7548,7599,7596,0,7548,7549,7600,7599,0,7549,7576,7609,7600,0,7576,7583,7612,7609,0,7583,7590,7616,7612,0,7590,7592,7619,7616,0,7592,7594,7623,7619,0,7594,7598,7628,7623,0,7598,7602,7635,7628,0,7602,7604,7640,7635,0,7604,7607,7645,7640,0,7607,7611,7648,7645,0,7611,7615,7653,7648,0,7615,7620,7661,7653,0,7620,7625,7665,7661,0,7625,7629,7671,7665,0,7629,7632,7679,7671,0,7632,7638,7689,7679,0,7638,7642,7697,7689,0,7642,7657,7730,7697,0,7657,7673,7739,7730,0,7673,7678,7743,7739,0,7678,7684,7748,7743,0,7684,7690,7752,7748,0,7690,7694,7756,7752,0,7694,7698,7759,7756,0,7698,7704,7764,7759,0,7704,7706,7766,7764,0,7706,7707,7767,7766,0,7707,7705,7765,7767,0,7705,7703,7763,7765,0,7703,7696,7757,7763,0,7696,7693,7755,7757,0,7693,7687,7749,7755,0,7687,7681,7745,7749,0,7681,7674,7740,7745,0,7674,7670,7737,7740,0,7670,7667,7735,7737,0,7667,7652,7726,7735,0,7652,7650,7725,7726,0,7725,7729,7788,7786,0,7729,7741,7794,7788,0,7741,7746,7798,7794,0,7746,7753,7805,7798,0,7753,7762,7811,7805,0,7762,7769,7818,7811,0,7769,7773,7820,7818,0,7773,7775,7823,7820,0,7775,7777,7826,7823,0,7777,7780,7828,7826,0,7780,7782,7830,7828,0,7782,7784,7831,7830,0,7784,7781,7829,7831,0,7781,7779,7827,7829,0,7779,7776,7825,7827,0,7776,7774,7824,7825,0,7774,7772,7821,7824,0,7772,7768,7819,7821,0,7768,7761,7812,7819,0,7761,7754,7806,7812,0,7754,7747,7799,7806,0,7747,7713,7785,7799,0,7713,7702,7783,7785,0,7702,7688,7770,7783,0,7688,7680,7760,7770,0,7680,7672,7751,7760,0,7672,7666,7744,7751,0,7666,7662,7738,7744,0,7662,7658,7734,7738,0,7658,7651,7732,7734,0,7651,7647,7728,7732,0,7647,7644,7723,7728,0,7644,7637,7710,7723,0,7637,7631,7695,7710,0,7631,7627,7685,7695,0,7627,7624,7677,7685,0,7624,7621,7669,7677,0,7621,7617,7664,7669,0,7617,7613,7660,7664,0,7613,7608,7654,7660,0,7608,7605,7649,7654,0,7605,7596,7634,7649,0,7596,7599,7639,7634,0,7599,7600,7641,7639,0,7600,7609,7655,7641,0,7609,7612,7659,7655,0,7612,7616,7663,7659,0,7616,7619,7668,7663,0,7619,7623,7676,7668,0,7623,7628,7686,7676,0,7628,7635,7701,7686,0,7635,7640,7716,7701,0,7640,7645,7727,7716,0,7645,7648,7731,7727,0,7648,7653,7733,7731,0,7653,7661,7736,7733,0,7661,7665,7742,7736,0,7665,7671,7750,7742,0,7671,7679,7758,7750,0,7679,7689,7771,7758,0,7689,7697,7778,7771,0,7697,7730,7789,7778,0,7730,7739,7792,7789,0,7739,7743,7796,7792,0,7743,7748,7800,7796,0,7748,7752,7804,7800,0,7752,7756,7808,7804,0,7756,7759,7810,7808,0,7759,7764,7814,7810,0,7764,7766,7816,7814,0,7766,7767,7817,7816,0,7767,7765,7815,7817,0,7765,7763,7813,7815,0,7763,7757,7809,7813,0,7757,7755,7807,7809,0,7755,7749,7802,7807,0,7749,7745,7797,7802,0,7745,7740,7795,7797,0,7740,7737,7791,7795,0,7737,7735,7790,7791,0,7735,7726,7787,7790,0,7726,7725,7786,7787,0,7786,7788,7886,7880,0,7788,7794,7905,7886,0,7794,7798,7913,7905,0,7798,7805,7921,7913,0,7805,7811,7928,7921,0,7811,7818,7938,7928,0,7818,7820,7941,7938,0,7820,7823,7945,7941,0,7823,7826,7948,7945,0,7826,7828,7951,7948,0,7828,7830,7953,7951,0,7830,7831,7955,7953,0,7831,7829,7954,7955,0,7829,7827,7952,7954,0,7827,7825,7949,7952,0,7825,7824,7946,7949,0,7824,7821,7943,7946,0,7821,7819,7939,7943,0,7819,7812,7930,7939,0,7812,7806,7922,7930,0,7806,7799,7914,7922,0,7799,7785,7876,7914,0,7785,7783,7873,7876,0,7783,7770,7869,7873,0,7770,7760,7866,7869,0,7760,7751,7862,7866,0,7751,7744,7859,7862,0,7744,7738,7856,7859,0,7738,7734,7854,7856,0,7734,7732,7852,7854,0,7732,7728,7850,7852,0,7728,7723,7848,7850,0,7723,7710,7846,7848,0,7710,7695,7844,7846,0,7695,7685,7842,7844,0,7685,7677,7841,7842,0,7677,7669,7839,7841,0,7669,7664,7837,7839,0,7664,7660,7835,7837,0,7660,7654,7832,7835,0,7654,7649,7822,7832,0,7649,7634,7793,7822,0,7634,7639,7801,7793,0,7639,7641,7803,7801,0,7641,7655,7833,7803,0,7655,7659,7834,7833,0,7659,7663,7836,7834,0,7663,7668,7838,7836,0,7668,7676,7840,7838,0,7676,7686,7843,7840,0,7686,7701,7845,7843,0,7701,7716,7847,7845,0,7716,7727,7849,7847,0,7727,7731,7851,7849,0,7731,7733,7853,7851,0,7733,7736,7855,7853,0,7736,7742,7857,7855,0,7742,7750,7860,7857,0,7750,7758,7865,7860,0,7758,7771,7870,7865,0,7771,7778,7872,7870,0,7778,7789,7889,7872,0,7789,7792,7904,7889,0,7792,7796,7909,7904,0,7796,7800,7915,7909,0,7800,7804,7918,7915,0,7804,7808,7925,7918,0,7808,7810,7929,7925,0,7810,7814,7933,7929,0,7814,7816,7935,7933,0,7816,7817,7936,7935,0,7817,7815,7934,7936,0,7815,7813,7931,7934,0,7813,7809,7926,7931,0,7809,7807,7923,7926,0,7807,7802,7917,7923,0,7802,7797,7911,7917,0,7797,7795,7906,7911,0,7795,7791,7901,7906,0,7791,7790,7898,7901,0,7790,7787,7882,7898,0,7787,7786,7880,7882,0,7880,7886,7992,7989,0,7886,7905,8001,7992,0,7905,7913,8007,8001,0,7913,7921,8015,8007,0,7921,7928,8023,8015,0,7928,7938,8035,8023,0,7938,7941,8039,8035,0,7941,7945,8044,8039,0,7945,7948,8050,8044,0,7948,7951,8056,8050,0,7951,7953,8061,8056,0,7953,7955,8063,8061,0,7955,7954,8062,8063,0,7954,7952,8058,8062,0,7952,7949,8051,8058,0,7949,7946,8046,8051,0,7946,7943,8042,8046,0,7943,7939,8036,8042,0,7939,7930,8025,8036,0,7930,7922,8016,8025,0,7922,7914,8008,8016,0,7914,7876,7986,8008,0,7876,7873,7983,7986,0,7873,7869,7978,7983,0,7869,7866,7975,7978,0,7866,7862,7971,7975,0,7862,7859,7967,7971,0,7859,7856,7964,7967,0,7856,7854,7960,7964,0,7854,7852,7956,7960,0,7852,7850,7942,7956,0,7850,7848,7927,7942,0,7848,7846,7916,7927,0,7846,7844,7907,7916,0,7844,7842,7899,7907,0,7842,7841,7895,7899,0,7841,7839,7891,7895,0,7839,7837,7885,7891,0,7837,7835,7879,7885,0,7835,7832,7874,7879,0,7832,7822,7871,7874,0,7822,7793,7858,7871,0,7793,7801,7861,7858,0,7801,7803,7863,7861,0,7803,7833,7875,7863,0,7833,7834,7878,7875,0,7834,7836,7884,7878,0,7836,7838,7890,7884,0,7838,7840,7894,7890,0,7840,7843,7900,7894,0,7843,7845,7908,7900,0,7845,7847,7920,7908,0,7847,7849,7932,7920,0,7849,7851,7944,7932,0,7851,7853,7957,7944,0,7853,7855,7962,7957,0,7855,7857,7966,7962,0,7857,7860,7970,7966,0,7860,7865,7974,7970,0,7865,7870,7979,7974,0,7870,7872,7982,7979,0,7872,7889,7993,7982,0,7889,7904,8000,7993,0,7904,7909,8004,8000,0,7909,7915,8009,8004,0,7915,7918,8014,8009,0,7918,7925,8019,8014,0,7925,7929,8024,8019,0,7929,7933,8029,8024,0,7933,7935,8031,8029,0,7935,7936,8032,8031,0,7936,7934,8030,8032,0,7934,7931,8026,8030,0,7931,7926,8021,8026,0,7926,7923,8017,8021,0,7923,7917,8010,8017,0,7917,7911,8005,8010,0,7911,7906,8002,8005,0,7906,7901,7999,8002,0,7901,7898,7998,7999,0,7898,7882,7990,7998,0,7882,7880,7989,7990,0,7989,7992,7996,7994,0,7992,8001,8012,7996,0,8001,8007,8022,8012,0,8007,8015,8038,8022,0,8015,8023,8047,8038,0,8023,8035,8064,8047,0,8035,8039,8066,8064,0,8039,8044,8068,8066,0,8044,8050,8070,8068,0,8050,8056,8072,8070,0,8056,8061,8074,8072,0,8061,8063,8076,8074,0,8063,8062,8075,8076,0,8062,8058,8073,8075,0,8058,8051,8071,8073,0,8051,8046,8069,8071,0,8046,8042,8067,8069,0,8042,8036,8065,8067,0,8036,8025,8052,8065,0,8025,8016,8041,8052,0,8016,8008,8027,8041,0,8008,7986,7991,8027,0,7986,7983,7988,7991,0,7983,7978,7984,7988,0,7978,7975,7981,7984,0,7975,7971,7977,7981,0,7971,7967,7973,7977,0,7967,7964,7969,7973,0,7964,7960,7965,7969,0,7960,7956,7961,7965,0,7956,7942,7958,7961,0,7942,7927,7947,7958,0,7927,7916,7937,7947,0,7916,7907,7919,7937,0,7907,7899,7910,7919,0,7899,7895,7903,7910,0,7895,7891,7897,7903,0,7891,7885,7893,7897,0,7885,7879,7888,7893,0,7879,7874,7881,7888,0,7874,7871,7877,7881,0,7871,7858,7864,7877,0,7858,7861,7867,7864,0,7861,7863,7868,7867,0,7863,7875,7883,7868,0,7875,7878,7887,7883,0,7878,7884,7892,7887,0,7884,7890,7896,7892,0,7890,7894,7902,7896,0,7894,7900,7912,7902,0,7900,7908,7924,7912,0,7908,7920,7940,7924,0,7920,7932,7950,7940,0,7932,7944,7959,7950,0,7944,7957,7963,7959,0,7957,7962,7968,7963,0,7962,7966,7972,7968,0,7966,7970,7976,7972,0,7970,7974,7980,7976,0,7974,7979,7985,7980,0,7979,7982,7987,7985,0,7982,7993,7997,7987,0,7993,8000,8011,7997,0,8000,8004,8018,8011,0,8004,8009,8028,8018,0,8009,8014,8037,8028,0,8014,8019,8043,8037,0,8019,8024,8049,8043,0,8024,8029,8054,8049,0,8029,8031,8059,8054,0,8031,8032,8060,8059,0,8032,8030,8055,8060,0,8030,8026,8053,8055,0,8026,8021,8045,8053,0,8021,8017,8040,8045,0,8017,8010,8033,8040,0,8010,8005,8020,8033,0,8005,8002,8013,8020,0,8002,7999,8006,8013,0,7999,7998,8003,8006,0,7998,7990,7995,8003,0,7990,7989,7994,7995,0,7994,7996,8124,8120,0,7996,8012,8138,8124,0,8012,8022,8144,8138,0,8022,8038,8150,8144,0,8038,8047,8158,8150,0,8047,8064,8167,8158,0,8064,8066,8172,8167,0,8066,8068,8175,8172,0,8068,8070,8177,8175,0,8070,8072,8181,8177,0,8072,8074,8183,8181,0,8074,8076,8186,8183,0,8076,8075,8185,8186,0,8075,8073,8182,8185,0,8073,8071,8179,8182,0,8071,8069,8176,8179,0,8069,8067,8173,8176,0,8067,8065,8168,8173,0,8065,8052,8161,8168,0,8052,8041,8153,8161,0,8041,8027,8145,8153,0,8027,7991,8117,8145,0,7991,7988,8115,8117,0,7988,7984,8112,8115,0,7984,7981,8111,8112,0,7981,7977,8107,8111,0,7977,7973,8104,8107,0,7973,7969,8102,8104,0,7969,7965,8100,8102,0,7965,7961,8098,8100,0,7961,7958,8096,8098,0,7958,7947,8094,8096,0,7947,7937,8092,8094,0,7937,7919,8090,8092,0,7919,7910,8088,8090,0,7910,7903,8087,8088,0,7903,7897,8085,8087,0,7897,7893,8083,8085,0,7893,7888,8081,8083,0,7888,7881,8078,8081,0,7881,7877,8077,8078,0,7877,7864,8034,8077,0,7864,7867,8048,8034,0,7867,7868,8057,8048,0,7868,7883,8079,8057,0,7883,7887,8080,8079,0,7887,7892,8082,8080,0,7892,7896,8084,8082,0,7896,7902,8086,8084,0,7902,7912,8089,8086,0,7912,7924,8091,8089,0,7924,7940,8093,8091,0,7940,7950,8095,8093,0,7950,7959,8097,8095,0,7959,7963,8099,8097,0,7963,7968,8101,8099,0,7968,7972,8103,8101,0,7972,7976,8106,8103,0,7976,7980,8109,8106,0,7980,7985,8113,8109,0,7985,7987,8114,8113,0,7987,7997,8125,8114,0,7997,8011,8136,8125,0,8011,8018,8142,8136,0,8018,8028,8147,8142,0,8028,8037,8151,8147,0,8037,8043,8155,8151,0,8043,8049,8159,8155,0,8049,8054,8163,8159,0,8054,8059,8165,8163,0,8059,8060,8166,8165,0,8060,8055,8164,8166,0,8055,8053,8160,8164,0,8053,8045,8157,8160,0,8045,8040,8152,8157,0,8040,8033,8148,8152,0,8033,8020,8143,8148,0,8020,8013,8139,8143,0,8013,8006,8134,8139,0,8006,8003,8131,8134,0,8003,7995,8121,8131,0,7995,7994,8120,8121,0,8120,8124,8225,8221,0,8124,8138,8237,8225,0,8138,8144,8244,8237,0,8144,8150,8249,8244,0,8150,8158,8256,8249,0,8158,8167,8266,8256,0,8167,8172,8269,8266,0,8172,8175,8272,8269,0,8175,8177,8275,8272,0,8177,8181,8278,8275,0,8181,8183,8280,8278,0,8183,8186,8283,8280,0,8186,8185,8282,8283,0,8185,8182,8279,8282,0,8182,8179,8276,8279,0,8179,8176,8273,8276,0,8176,8173,8270,8273,0,8173,8168,8267,8270,0,8168,8161,8259,8267,0,8161,8153,8253,8259,0,8153,8145,8245,8253,0,8145,8117,8219,8245,0,8117,8115,8216,8219,0,8115,8112,8211,8216,0,8112,8111,8209,8211,0,8111,8107,8205,8209,0,8107,8104,8202,8205,0,8104,8102,8198,8202,0,8102,8100,8194,8198,0,8100,8098,8190,8194,0,8098,8096,8184,8190,0,8096,8094,8171,8184,0,8094,8092,8156,8171,0,8092,8090,8146,8156,0,8090,8088,8140,8146,0,8088,8087,8133,8140,0,8087,8085,8129,8133,0,8085,8083,8127,8129,0,8083,8081,8123,8127,0,8081,8078,8118,8123,0,8078,8077,8116,8118,0,8077,8034,8105,8116,0,8034,8048,8108,8105,0,8048,8057,8110,8108,0,8057,8079,8119,8110,0,8079,8080,8122,8119,0,8080,8082,8126,8122,0,8082,8084,8128,8126,0,8084,8086,8132,8128,0,8086,8089,8141,8132,0,8089,8091,8149,8141,0,8091,8093,8162,8149,0,8093,8095,8174,8162,0,8095,8097,8187,8174,0,8097,8099,8191,8187,0,8099,8101,8195,8191,0,8101,8103,8200,8195,0,8103,8106,8204,8200,0,8106,8109,8208,8204,0,8109,8113,8212,8208,0,8113,8114,8215,8212,0,8114,8125,8227,8215,0,8125,8136,8236,8227,0,8136,8142,8240,8236,0,8142,8147,8246,8240,0,8147,8151,8250,8246,0,8151,8155,8254,8250,0,8155,8159,8257,8254,0,8159,8163,8261,8257,0,8163,8165,8264,8261,0,8165,8166,8263,8264,0,8166,8164,8260,8263,0,8164,8160,8258,8260,0,8160,8157,8255,8258,0,8157,8152,8251,8255,0,8152,8148,8247,8251,0,8148,8143,8241,8247,0,8143,8139,8239,8241,0,8139,8134,8234,8239,0,8134,8131,8231,8234,0,8131,8121,8223,8231,0,8121,8120,8221,8223,0,8221,8225,8281,8268,0,8225,8237,8291,8281,0,8237,8244,8297,8291,0,8244,8249,8303,8297,0,8249,8256,8310,8303,0,8256,8266,8319,8310,0,8266,8269,8322,8319,0,8269,8272,8325,8322,0,8272,8275,8327,8325,0,8275,8278,8329,8327,0,8278,8280,8331,8329,0,8280,8283,8334,8331,0,8283,8282,8333,8334,0,8282,8279,8330,8333,0,8279,8276,8328,8330,0,8276,8273,8326,8328,0,8273,8270,8324,8326,0,8270,8267,8320,8324,0,8267,8259,8314,8320,0,8259,8253,8306,8314,0,8253,8245,8298,8306,0,8245,8219,8265,8298,0,8219,8216,8252,8265,0,8216,8211,8242,8252,0,8211,8209,8238,8242,0,8209,8205,8233,8238,0,8205,8202,8230,8233,0,8202,8198,8228,8230,0,8198,8194,8224,8228,0,8194,8190,8220,8224,0,8190,8184,8217,8220,0,8184,8171,8213,8217,0,8171,8156,8207,8213,0,8156,8146,8203,8207,0,8146,8140,8199,8203,0,8140,8133,8197,8199,0,8133,8129,8193,8197,0,8129,8127,8189,8193,0,8127,8123,8180,8189,0,8123,8118,8169,8180,0,8118,8116,8154,8169,0,8116,8105,8130,8154,0,8105,8108,8135,8130,0,8108,8110,8137,8135,0,8110,8119,8170,8137,0,8119,8122,8178,8170,0,8122,8126,8188,8178,0,8126,8128,8192,8188,0,8128,8132,8196,8192,0,8132,8141,8201,8196,0,8141,8149,8206,8201,0,8149,8162,8210,8206,0,8162,8174,8214,8210,0,8174,8187,8218,8214,0,8187,8191,8222,8218,0,8191,8195,8226,8222,0,8195,8200,8229,8226,0,8200,8204,8232,8229,0,8204,8208,8235,8232,0,8208,8212,8243,8235,0,8212,8215,8248,8243,0,8215,8227,8284,8248,0,8227,8236,8290,8284,0,8236,8240,8295,8290,0,8240,8246,8300,8295,0,8246,8250,8304,8300,0,8250,8254,8307,8304,0,8254,8257,8312,8307,0,8257,8261,8316,8312,0,8261,8264,8318,8316,0,8264,8263,8317,8318,0,8263,8260,8315,8317,0,8260,8258,8313,8315,0,8258,8255,8309,8313,0,8255,8251,8305,8309,0,8251,8247,8301,8305,0,8247,8241,8296,8301,0,8241,8239,8292,8296,0,8239,8234,8287,8292,0,8234,8231,8286,8287,0,8231,8223,8271,8286,0,8223,8221,8268,8271,0,8268,8281,8370,8366,0,8281,8291,8382,8370,0,8291,8297,8388,8382,0,8297,8303,8393,8388,0,8303,8310,8401,8393,0,8310,8319,8410,8401,0,8319,8322,8413,8410,0,8322,8325,8415,8413,0,8325,8327,8418,8415,0,8327,8329,8421,8418,0,8329,8331,8423,8421,0,8331,8334,8425,8423,0,8334,8333,8424,8425,0,8333,8330,8422,8424,0,8330,8328,8420,8422,0,8328,8326,8417,8420,0,8326,8324,8414,8417,0,8324,8320,8412,8414,0,8320,8314,8404,8412,0,8314,8306,8397,8404,0,8306,8298,8390,8397,0,8298,8265,8365,8390,0,8265,8252,8362,8365,0,8252,8242,8358,8362,0,8242,8238,8357,8358,0,8238,8233,8354,8357,0,8233,8230,8351,8354,0,8230,8228,8348,8351,0,8228,8224,8346,8348,0,8224,8220,8344,8346,0,8220,8217,8342,8344,0,8217,8213,8340,8342,0,8213,8207,8338,8340,0,8207,8203,8336,8338,0,8203,8199,8332,8336,0,8199,8197,8323,8332,0,8197,8193,8311,8323,0,8193,8189,8302,8311,0,8189,8180,8294,8302,0,8180,8169,8288,8294,0,8169,8154,8285,8288,0,8154,8130,8262,8285,0,8130,8135,8274,8262,0,8135,8137,8277,8274,0,8137,8170,8289,8277,0,8170,8178,8293,8289,0,8178,8188,8299,8293,0,8188,8192,8308,8299,0,8192,8196,8321,8308,0,8196,8201,8335,8321,0,8201,8206,8337,8335,0,8206,8210,8339,8337,0,8210,8214,8341,8339,0,8214,8218,8343,8341,0,8218,8222,8345,8343,0,8222,8226,8347,8345,0,8226,8229,8349,8347,0,8229,8232,8352,8349,0,8232,8235,8356,8352,0,8235,8243,8359,8356,0,8243,8248,8361,8359,0,8248,8284,8373,8361,0,8284,8290,8383,8373,0,8290,8295,8386,8383,0,8295,8300,8391,8386,0,8300,8304,8395,8391,0,8304,8307,8399,8395,0,8307,8312,8402,8399,0,8312,8316,8406,8402,0,8316,8318,8409,8406,0,8318,8317,8408,8409,0,8317,8315,8405,8408,0,8315,8313,8403,8405,0,8313,8309,8400,8403,0,8309,8305,8396,8400,0,8305,8301,8392,8396,0,8301,8296,8387,8392,0,8296,8292,8384,8387,0,8292,8287,8379,8384,0,8287,8286,8378,8379,0,8286,8271,8368,8378,0,8271,8268,8366,8368,0,8366,8370,8452,8448,0,8370,8382,8464,8452,0,8382,8388,8470,8464,0,8388,8393,8475,8470,0,8393,8401,8483,8475,0,8401,8410,8491,8483,0,8410,8413,8495,8491,0,8413,8415,8497,8495,0,8415,8418,8500,8497,0,8418,8421,8504,8500,0,8421,8423,8506,8504,0,8423,8425,8508,8506,0,8425,8424,8507,8508,0,8424,8422,8505,8507,0,8422,8420,8501,8505,0,8420,8417,8498,8501,0,8417,8414,8496,8498,0,8414,8412,8493,8496,0,8412,8404,8486,8493,0,8404,8397,8479,8486,0,8397,8390,8472,8479,0,8390,8365,8447,8472,0,8365,8362,8444,8447,0,8362,8358,8441,8444,0,8358,8357,8439,8441,0,8357,8354,8436,8439,0,8354,8351,8433,8436,0,8351,8348,8430,8433,0,8348,8346,8428,8430,0,8346,8344,8426,8428,0,8344,8342,8416,8426,0,8342,8340,8407,8416,0,8340,8338,8394,8407,0,8338,8336,8385,8394,0,8336,8332,8380,8385,0,8332,8323,8377,8380,0,8323,8311,8375,8377,0,8311,8302,8372,8375,0,8302,8294,8369,8372,0,8294,8288,8363,8369,0,8288,8285,8360,8363,0,8285,8262,8350,8360,0,8262,8274,8353,8350,0,8274,8277,8355,8353,0,8277,8289,8364,8355,0,8289,8293,8367,8364,0,8293,8299,8371,8367,0,8299,8308,8374,8371,0,8308,8321,8376,8374,0,8321,8335,8381,8376,0,8335,8337,8389,8381,0,8337,8339,8398,8389,0,8339,8341,8411,8398,0,8341,8343,8419,8411,0,8343,8345,8427,8419,0,8345,8347,8429,8427,0,8347,8349,8431,8429,0,8349,8352,8434,8431,0,8352,8356,8438,8434,0,8356,8359,8440,8438,0,8359,8361,8443,8440,0,8361,8373,8455,8443,0,8373,8383,8466,8455,0,8383,8386,8468,8466,0,8386,8391,8473,8468,0,8391,8395,8476,8473,0,8395,8399,8480,8476,0,8399,8402,8484,8480,0,8402,8406,8488,8484,0,8406,8409,8490,8488,0,8409,8408,8489,8490,0,8408,8405,8487,8489,0,8405,8403,8485,8487,0,8403,8400,8481,8485,0,8400,8396,8478,8481,0,8396,8392,8474,8478,0,8392,8387,8467,8474,0,8387,8384,8465,8467,0,8384,8379,8461,8465,0,8379,8378,8460,8461,0,8378,8368,8449,8460,0,8368,8366,8448,8449,0,8448,8452,8542,8538,0,8452,8464,8552,8542,0,8464,8470,8559,8552,0,8470,8475,8564,8559,0,8475,8483,8571,8564,0,8483,8491,8580,8571,0,8491,8495,8583,8580,0,8495,8497,8587,8583,0,8497,8500,8589,8587,0,8500,8504,8592,8589,0,8504,8506,8594,8592,0,8506,8508,8596,8594,0,8508,8507,8595,8596,0,8507,8505,8593,8595,0,8505,8501,8591,8593,0,8501,8498,8588,8591,0,8498,8496,8586,8588,0,8496,8493,8582,8586,0,8493,8486,8576,8582,0,8486,8479,8568,8576,0,8479,8472,8560,8568,0,8472,8447,8535,8560,0,8447,8444,8533,8535,0,8444,8441,8529,8533,0,8441,8439,8526,8529,0,8439,8436,8522,8526,0,8436,8433,8518,8522,0,8433,8430,8515,8518,0,8430,8428,8513,8515,0,8428,8426,8509,8513,0,8426,8416,8499,8509,0,8416,8407,8492,8499,0,8407,8394,8477,8492,0,8394,8385,8469,8477,0,8385,8380,8462,8469,0,8380,8377,8459,8462,0,8377,8375,8457,8459,0,8375,8372,8454,8457,0,8372,8369,8451,8454,0,8369,8363,8445,8451,0,8363,8360,8442,8445,0,8360,8350,8432,8442,0,8350,8353,8435,8432,0,8353,8355,8437,8435,0,8355,8364,8446,8437,0,8364,8367,8450,8446,0,8367,8371,8453,8450,0,8371,8374,8456,8453,0,8374,8376,8458,8456,0,8376,8381,8463,8458,0,8381,8389,8471,8463,0,8389,8398,8482,8471,0,8398,8411,8494,8482,0,8411,8419,8502,8494,0,8419,8427,8511,8502,0,8427,8429,8514,8511,0,8429,8431,8516,8514,0,8431,8434,8520,8516,0,8434,8438,8525,8520,0,8438,8440,8528,8525,0,8440,8443,8531,8528,0,8443,8455,8543,8531,0,8455,8466,8554,8543,0,8466,8468,8558,8554,0,8468,8473,8562,8558,0,8473,8476,8567,8562,0,8476,8480,8569,8567,0,8480,8484,8573,8569,0,8484,8488,8577,8573,0,8488,8490,8579,8577,0,8490,8489,8578,8579,0,8489,8487,8575,8578,0,8487,8485,8574,8575,0,8485,8481,8570,8574,0,8481,8478,8566,8570,0,8478,8474,8561,8566,0,8474,8467,8557,8561,0,8467,8465,8553,8557,0,8465,8461,8549,8553,0,8461,8460,8548,8549,0,8460,8449,8539,8548,0,8449,8448,8538,8539,0,8538,8542,8618,8614,0,8542,8552,8628,8618,0,8552,8559,8635,8628,0,8559,8564,8641,8635,0,8564,8571,8648,8641,0,8571,8580,8657,8648,0,8580,8583,8660,8657,0,8583,8587,8663,8660,0,8587,8589,8665,8663,0,8589,8592,8667,8665,0,8592,8594,8670,8667,0,8594,8596,8672,8670,0,8596,8595,8671,8672,0,8595,8593,8669,8671,0,8593,8591,8666,8669,0,8591,8588,8664,8666,0,8588,8586,8662,8664,0,8586,8582,8658,8662,0,8582,8576,8653,8658,0,8576,8568,8644,8653,0,8568,8560,8638,8644,0,8560,8535,8613,8638,0,8535,8533,8610,8613,0,8533,8529,8606,8610,0,8529,8526,8603,8606,0,8526,8522,8601,8603,0,8522,8518,8597,8601,0,8518,8515,8585,8597,0,8515,8513,8572,8585,0,8513,8509,8563,8572,0,8509,8499,8555,8563,0,8499,8492,8550,8555,0,8492,8477,8546,8550,0,8477,8469,8544,8546,0,8469,8462,8540,8544,0,8462,8459,8537,8540,0,8459,8457,8534,8537,0,8457,8454,8530,8534,0,8454,8451,8524,8530,0,8451,8445,8519,8524,0,8445,8442,8517,8519,0,8442,8432,8503,8517,0,8432,8435,8510,8503,0,8435,8437,8512,8510,0,8437,8446,8521,8512,0,8446,8450,8523,8521,0,8450,8453,8527,8523,0,8453,8456,8532,8527,0,8456,8458,8536,8532,0,8458,8463,8541,8536,0,8463,8471,8545,8541,0,8471,8482,8547,8545,0,8482,8494,8551,8547,0,8494,8502,8556,8551,0,8502,8511,8565,8556,0,8511,8514,8581,8565,0,8514,8516,8590,8581,0,8516,8520,8600,8590,0,8520,8525,8602,8600,0,8525,8528,8605,8602,0,8528,8531,8607,8605,0,8531,8543,8620,8607,0,8543,8554,8630,8620,0,8554,8558,8634,8630,0,8558,8562,8639,8634,0,8562,8567,8643,8639,0,8567,8569,8647,8643,0,8569,8573,8651,8647,0,8573,8577,8654,8651,0,8577,8579,8656,8654,0,8579,8578,8655,8656,0,8578,8575,8652,8655,0,8575,8574,8650,8652,0,8574,8570,8646,8650,0,8570,8566,8642,8646,0,8566,8561,8637,8642,0,8561,8557,8633,8637,0,8557,8553,8629,8633,0,8553,8549,8627,8629,0,8549,8548,8624,8627,0,8548,8539,8615,8624,0,8539,8538,8614,8615,0,8614,8618,8690,8688,0,8618,8628,8694,8690,0,8628,8635,8700,8694,0,8635,8641,8706,8700,0,8641,8648,8712,8706,0,8648,8657,8720,8712,0,8657,8660,8722,8720,0,8660,8663,8724,8722,0,8663,8665,8727,8724,0,8665,8667,8729,8727,0,8667,8670,8731,8729,0,8670,8672,8733,8731,0,8672,8671,8732,8733,0,8671,8669,8730,8732,0,8669,8666,8728,8730,0,8666,8664,8726,8728,0,8664,8662,8723,8726,0,8662,8658,8721,8723,0,8658,8653,8716,8721,0,8653,8644,8709,8716,0,8644,8638,8703,8709,0,8638,8613,8687,8703,0,8613,8610,8686,8687,0,8610,8606,8684,8686,0,8606,8603,8682,8684,0,8603,8601,8680,8682,0,8601,8597,8678,8680,0,8597,8585,8676,8678,0,8585,8572,8674,8676,0,8572,8563,8668,8674,0,8563,8555,8659,8668,0,8555,8550,8645,8659,0,8550,8546,8636,8645,0,8546,8544,8631,8636,0,8544,8540,8625,8631,0,8540,8537,8623,8625,0,8537,8534,8621,8623,0,8534,8530,8617,8621,0,8530,8524,8612,8617,0,8524,8519,8608,8612,0,8519,8517,8604,8608,0,8517,8503,8584,8604,0,8503,8510,8598,8584,0,8510,8512,8599,8598,0,8512,8521,8609,8599,0,8521,8523,8611,8609,0,8523,8527,8616,8611,0,8527,8532,8619,8616,0,8532,8536,8622,8619,0,8536,8541,8626,8622,0,8541,8545,8632,8626,0,8545,8547,8640,8632,0,8547,8551,8649,8640,0,8551,8556,8661,8649,0,8556,8565,8673,8661,0,8565,8581,8675,8673,0,8581,8590,8677,8675,0,8590,8600,8679,8677,0,8600,8602,8681,8679,0,8602,8605,8683,8681,0,8605,8607,8685,8683,0,8607,8620,8691,8685,0,8620,8630,8696,8691,0,8630,8634,8699,8696,0,8634,8639,8704,8699,0,8639,8643,8708,8704,0,8643,8647,8711,8708,0,8647,8651,8714,8711,0,8651,8654,8717,8714,0,8654,8656,8719,8717,0,8656,8655,8718,8719,0,8655,8652,8715,8718,0,8652,8650,8713,8715,0,8650,8646,8710,8713,0,8646,8642,8707,8710,0,8642,8637,8702,8707,0,8637,8633,8698,8702,0,8633,8629,8695,8698,0,8629,8627,8693,8695,0,8627,8624,8692,8693,0,8624,8615,8689,8692,0,8615,8614,8688,8689,0,8688,8690,8806,8799,0,8690,8694,8823,8806,0,8694,8700,8830,8823,0,8700,8706,8837,8830,0,8706,8712,8846,8837,0,8712,8720,8855,8846,0,8720,8722,8859,8855,0,8722,8724,8861,8859,0,8724,8727,8865,8861,0,8727,8729,8868,8865,0,8729,8731,8870,8868,0,8731,8733,8872,8870,0,8733,8732,8871,8872,0,8732,8730,8869,8871,0,8730,8728,8867,8869,0,8728,8726,8864,8867,0,8726,8723,8860,8864,0,8723,8721,8858,8860,0,8721,8716,8853,8858,0,8716,8709,8843,8853,0,8709,8703,8836,8843,0,8703,8687,8800,8836,0,8687,8686,8796,8800,0,8686,8684,8791,8796,0,8684,8682,8788,8791,0,8682,8680,8784,8788,0,8680,8678,8780,8784,0,8678,8676,8776,8780,0,8676,8674,8772,8776,0,8674,8668,8768,8772,0,8668,8659,8764,8768,0,8659,8645,8760,8764,0,8645,8636,8756,8760,0,8636,8631,8752,8756,0,8631,8625,8748,8752,0,8625,8623,8746,8748,0,8623,8621,8744,8746,0,8621,8617,8742,8744,0,8617,8612,8738,8742,0,8612,8608,8734,8738,0,8608,8604,8725,8734,0,8604,8584,8697,8725,0,8584,8598,8701,8697,0,8598,8599,8705,8701,0,8599,8609,8735,8705,0,8609,8611,8737,8735,0,8611,8616,8740,8737,0,8616,8619,8743,8740,0,8619,8622,8745,8743,0,8622,8626,8749,8745,0,8626,8632,8754,8749,0,8632,8640,8759,8754,0,8640,8649,8763,8759,0,8649,8661,8766,8763,0,8661,8673,8771,8766,0,8673,8675,8775,8771,0,8675,8677,8779,8775,0,8677,8679,8783,8779,0,8679,8681,8787,8783,0,8681,8683,8790,8787,0,8683,8685,8794,8790,0,8685,8691,8809,8794,0,8691,8696,8825,8809,0,8696,8699,8832,8825,0,8699,8704,8835,8832,0,8704,8708,8842,8835,0,8708,8711,8845,8842,0,8711,8714,8849,8845,0,8714,8717,8852,8849,0,8717,8719,8857,8852,0,8719,8718,8854,8857,0,8718,8715,8850,8854,0,8715,8713,8848,8850,0,8713,8710,8844,8848,0,8710,8707,8840,8844,0,8707,8702,8834,8840,0,8702,8698,8829,8834,0,8698,8695,8824,8829,0,8695,8693,8818,8824,0,8693,8692,8816,8818,0,8692,8689,8802,8816,0,8689,8688,8799,8802,0,8799,8806,8838,8826,0,8806,8823,8876,8838,0,8823,8830,8881,8876,0,8830,8837,8887,8881,0,8837,8846,8895,8887,0,8846,8855,8903,8895,0,8855,8859,8907,8903,0,8859,8861,8909,8907,0,8861,8865,8912,8909,0,8865,8868,8915,8912,0,8868,8870,8917,8915,0,8870,8872,8919,8917,0,8872,8871,8918,8919,0,8871,8869,8916,8918,0,8869,8867,8914,8916,0,8867,8864,8911,8914,0,8864,8860,8908,8911,0,8860,8858,8906,8908,0,8858,8853,8901,8906,0,8853,8843,8892,8901,0,8843,8836,8886,8892,0,8836,8800,8827,8886,0,8800,8796,8820,8827,0,8796,8791,8814,8820,0,8791,8788,8812,8814,0,8788,8784,8808,8812,0,8784,8780,8805,8808,0,8780,8776,8798,8805,0,8776,8772,8793,8798,0,8772,8768,8789,8793,0,8768,8764,8785,8789,0,8764,8760,8781,8785,0,8760,8756,8777,8781,0,8756,8752,8773,8777,0,8752,8748,8769,8773,0,8748,8746,8767,8769,0,8746,8744,8762,8767,0,8744,8742,8758,8762,0,8742,8738,8755,8758,0,8738,8734,8750,8755,0,8734,8725,8747,8750,0,8725,8697,8736,8747,0,8697,8701,8739,8736,0,8701,8705,8741,8739,0,8705,8735,8751,8741,0,8735,8737,8753,8751,0,8737,8740,8757,8753,0,8740,8743,8761,8757,0,8743,8745,8765,8761,0,8745,8749,8770,8765,0,8749,8754,8774,8770,0,8754,8759,8778,8774,0,8759,8763,8782,8778,0,8763,8766,8786,8782,0,8766,8771,8792,8786,0,8771,8775,8797,8792,0,8775,8779,8804,8797,0,8779,8783,8807,8804,0,8783,8787,8810,8807,0,8787,8790,8813,8810,0,8790,8794,8819,8813,0,8794,8809,8847,8819,0,8809,8825,8878,8847,0,8825,8832,8882,8878,0,8832,8835,8885,8882,0,8835,8842,8890,8885,0,8842,8845,8894,8890,0,8845,8849,8897,8894,0,8849,8852,8900,8897,0,8852,8857,8904,8900,0,8857,8854,8902,8904,0,8854,8850,8899,8902,0,8850,8848,8896,8899,0,8848,8844,8893,8896,0,8844,8840,8889,8893,0,8840,8834,8884,8889,0,8834,8829,8880,8884,0,8829,8824,8877,8880,0,8824,8818,8873,8877,0,8818,8816,8866,8873,0,8816,8802,8831,8866,0,8802,8799,8826,8831,0,8826,8838,8936,8933,0,8838,8876,8940,8936,0,8876,8881,8944,8940,0,8881,8887,8949,8944,0,8887,8895,8954,8949,0,8895,8903,8960,8954,0,8903,8907,8964,8960,0,8907,8909,8967,8964,0,8909,8912,8969,8967,0,8912,8915,8971,8969,0,8915,8917,8973,8971,0,8917,8919,8975,8973,0,8919,8918,8974,8975,0,8918,8916,8972,8974,0,8916,8914,8970,8972,0,8914,8911,8968,8970,0,8911,8908,8966,8968,0,8908,8906,8965,8966,0,8906,8901,8962,8965,0,8901,8892,8952,8962,0,8892,8886,8948,8952,0,8886,8827,8934,8948,0,8827,8820,8932,8934,0,8820,8814,8930,8932,0,8814,8812,8928,8930,0,8812,8808,8926,8928,0,8808,8805,8924,8926,0,8805,8798,8922,8924,0,8798,8793,8920,8922,0,8793,8789,8910,8920,0,8789,8785,8898,8910,0,8785,8781,8888,8898,0,8781,8777,8879,8888,0,8777,8773,8874,8879,0,8773,8769,8862,8874,0,8769,8767,8856,8862,0,8767,8762,8841,8856,0,8762,8758,8833,8841,0,8758,8755,8822,8833,0,8755,8750,8815,8822,0,8750,8747,8811,8815,0,8747,8736,8795,8811,0,8736,8739,8801,8795,0,8739,8741,8803,8801,0,8741,8751,8817,8803,0,8751,8753,8821,8817,0,8753,8757,8828,8821,0,8757,8761,8839,8828,0,8761,8765,8851,8839,0,8765,8770,8863,8851,0,8770,8774,8875,8863,0,8774,8778,8883,8875,0,8778,8782,8891,8883,0,8782,8786,8905,8891,0,8786,8792,8913,8905,0,8792,8797,8921,8913,0,8797,8804,8923,8921,0,8804,8807,8925,8923,0,8807,8810,8927,8925,0,8810,8813,8929,8927,0,8813,8819,8931,8929,0,8819,8847,8937,8931,0,8847,8878,8942,8937,0,8878,8882,8945,8942,0,8882,8885,8947,8945,0,8885,8890,8951,8947,0,8890,8894,8955,8951,0,8894,8897,8957,8955,0,8897,8900,8959,8957,0,8900,8904,8963,8959,0,8904,8902,8961,8963,0,8902,8899,8958,8961,0,8899,8896,8956,8958,0,8896,8893,8953,8956,0,8893,8889,8950,8953,0,8889,8884,8946,8950,0,8884,8880,8943,8946,0,8880,8877,8941,8943,0,8877,8873,8939,8941,0,8873,8866,8938,8939,0,8866,8831,8935,8938,0,8831,8826,8933,8935,0,8933,8936,9065,9057,0,8936,8940,9083,9065,0,8940,8944,9089,9083,0,8944,8949,9097,9089,0,8949,8954,9105,9097,0,8954,8960,9111,9105,0,8960,8964,9118,9111,0,8964,8967,9122,9118,0,8967,8969,9125,9122,0,8969,8971,9130,9125,0,8971,8973,9133,9130,0,8973,8975,9135,9133,0,8975,8974,9136,9135,0,8974,8972,9134,9136,0,8972,8970,9131,9134,0,8970,8968,9126,9131,0,8968,8966,9123,9126,0,8966,8965,9119,9123,0,8965,8962,9115,9119,0,8962,8952,9102,9115,0,8952,8948,9096,9102,0,8948,8934,9060,9096,0,8934,8932,9053,9060,0,8932,8930,9047,9053,0,8930,8928,9041,9047,0,8928,8926,9037,9041,0,8926,8924,9033,9037,0,8924,8922,9029,9033,0,8922,8920,9023,9029,0,8920,8910,9018,9023,0,8910,8898,9014,9018,0,8898,8888,9010,9014,0,8888,8879,9006,9010,0,8879,8874,9002,9006,0,8874,8862,8998,9002,0,8862,8856,8995,8998,0,8856,8841,8991,8995,0,8841,8833,8988,8991,0,8833,8822,8986,8988,0,8822,8815,8982,8986,0,8815,8811,8980,8982,0,8811,8795,8976,8980,0,8795,8801,8977,8976,0,8801,8803,8978,8977,0,8803,8817,8983,8978,0,8817,8821,8985,8983,0,8821,8828,8987,8985,0,8828,8839,8990,8987,0,8839,8851,8994,8990,0,8851,8863,8999,8994,0,8863,8875,9003,8999,0,8875,8883,9009,9003,0,8883,8891,9011,9009,0,8891,8905,9015,9011,0,8905,8913,9020,9015,0,8913,8921,9026,9020,0,8921,8923,9032,9026,0,8923,8925,9035,9032,0,8925,8927,9040,9035,0,8927,8929,9046,9040,0,8929,8931,9051,9046,0,8931,8937,9070,9051,0,8937,8942,9086,9070,0,8942,8945,9091,9086,0,8945,8947,9095,9091,0,8947,8951,9099,9095,0,8951,8955,9106,9099,0,8955,8957,9109,9106,0,8957,8959,9112,9109,0,8959,8963,9114,9112,0,8963,8961,9113,9114,0,8961,8958,9110,9113,0,8958,8956,9107,9110,0,8956,8953,9103,9107,0,8953,8950,9098,9103,0,8950,8946,9093,9098,0,8946,8943,9088,9093,0,8943,8941,9084,9088,0,8941,8939,9080,9084,0,8939,8938,9076,9080,0,8938,8935,9059,9076,0,8935,8933,9057,9059,0,9057,9065,9082,9075,0,9065,9083,9117,9082,0,9083,9089,9128,9117,0,9089,9097,9141,9128,0,9097,9105,9147,9141,0,9105,9111,9154,9147,0,9111,9118,9159,9154,0,9118,9122,9163,9159,0,9122,9125,9165,9163,0,9125,9130,9167,9165,0,9130,9133,9170,9167,0,9133,9135,9172,9170,0,9135,9136,9173,9172,0,9136,9134,9171,9173,0,9134,9131,9168,9171,0,9131,9126,9166,9168,0,9126,9123,9164,9166,0,9123,9119,9160,9164,0,9119,9115,9158,9160,0,9115,9102,9146,9158,0,9102,9096,9140,9146,0,9096,9060,9078,9140,0,9060,9053,9074,9078,0,9053,9047,9069,9074,0,9047,9041,9064,9069,0,9041,9037,9058,9064,0,9037,9033,9052,9058,0,9033,9029,9045,9052,0,9029,9023,9039,9045,0,9023,9018,9034,9039,0,9018,9014,9030,9034,0,9014,9010,9024,9030,0,9010,9006,9019,9024,0,9006,9002,9016,9019,0,9002,8998,9012,9016,0,8998,8995,9008,9012,0,8995,8991,9005,9008,0,8991,8988,9001,9005,0,8988,8986,8997,9001,0,8986,8982,8992,8997,0,8982,8980,8989,8992,0,8980,8976,8979,8989,0,8976,8977,8981,8979,0,8977,8978,8984,8981,0,8978,8983,8993,8984,0,8983,8985,8996,8993,0,8985,8987,9000,8996,0,8987,8990,9004,9000,0,8990,8994,9007,9004,0,8994,8999,9013,9007,0,8999,9003,9017,9013,0,9003,9009,9022,9017,0,9009,9011,9027,9022,0,9011,9015,9031,9027,0,9015,9020,9036,9031,0,9020,9026,9043,9036,0,9026,9032,9050,9043,0,9032,9035,9056,9050,0,9035,9040,9063,9056,0,9040,9046,9068,9063,0,9046,9051,9071,9068,0,9051,9070,9090,9071,0,9070,9086,9124,9090,0,9086,9091,9132,9124,0,9091,9095,9139,9132,0,9095,9099,9144,9139,0,9099,9106,9149,9144,0,9106,9109,9151,9149,0,9109,9112,9155,9151,0,9112,9114,9157,9155,0,9114,9113,9156,9157,0,9113,9110,9153,9156,0,9110,9107,9150,9153,0,9107,9103,9145,9150,0,9103,9098,9143,9145,0,9098,9093,9138,9143,0,9093,9088,9127,9138,0,9088,9084,9120,9127,0,9084,9080,9108,9120,0,9080,9076,9101,9108,0,9076,9059,9077,9101,0,9059,9057,9075,9077,0,9075,9082,9182,9179,0,9082,9117,9186,9182,0,9117,9128,9190,9186,0,9128,9141,9194,9190,0,9141,9147,9200,9194,0,9147,9154,9205,9200,0,9154,9159,9210,9205,0,9159,9163,9212,9210,0,9163,9165,9214,9212,0,9165,9167,9216,9214,0,9167,9170,9218,9216,0,9170,9172,9220,9218,0,9172,9173,9221,9220,0,9173,9171,9219,9221,0,9171,9168,9217,9219,0,9168,9166,9215,9217,0,9166,9164,9213,9215,0,9164,9160,9211,9213,0,9160,9158,9209,9211,0,9158,9146,9199,9209,0,9146,9140,9195,9199,0,9140,9078,9181,9195,0,9078,9074,9178,9181,0,9074,9069,9176,9178,0,9069,9064,9174,9176,0,9064,9058,9162,9174,0,9058,9052,9152,9162,0,9052,9045,9142,9152,0,9045,9039,9129,9142,0,9039,9034,9116,9129,0,9034,9030,9100,9116,0,9030,9024,9092,9100,0,9024,9019,9085,9092,0,9019,9016,9079,9085,0,9016,9012,9072,9079,0,9012,9008,9067,9072,0,9008,9005,9062,9067,0,9005,9001,9055,9062,0,9001,8997,9049,9055,0,8997,8992,9042,9049,0,8992,8989,9038,9042,0,8989,8979,9021,9038,0,8979,8981,9025,9021,0,8981,8984,9028,9025,0,8984,8993,9044,9028,0,8993,8996,9048,9044,0,8996,9000,9054,9048,0,9000,9004,9061,9054,0,9004,9007,9066,9061,0,9007,9013,9073,9066,0,9013,9017,9081,9073,0,9017,9022,9087,9081,0,9022,9027,9094,9087,0,9027,9031,9104,9094,0,9031,9036,9121,9104,0,9036,9043,9137,9121,0,9043,9050,9148,9137,0,9050,9056,9161,9148,0,9056,9063,9169,9161,0,9063,9068,9175,9169,0,9068,9071,9177,9175,0,9071,9090,9183,9177,0,9090,9124,9188,9183,0,9124,9132,9191,9188,0,9132,9139,9193,9191,0,9139,9144,9197,9193,0,9144,9149,9201,9197,0,9149,9151,9203,9201,0,9151,9155,9206,9203,0,9155,9157,9208,9206,0,9157,9156,9207,9208,0,9156,9153,9204,9207,0,9153,9150,9202,9204,0,9150,9145,9198,9202,0,9145,9143,9196,9198,0,9143,9138,9192,9196,0,9138,9127,9189,9192,0,9127,9120,9187,9189,0,9120,9108,9185,9187,0,9108,9101,9184,9185,0,9101,9077,9180,9184,0,9077,9075,9179,9180,0,9179,9182,9292,9285,0,9182,9186,9311,9292,0,9186,9190,9318,9311,0,9190,9194,9323,9318,0,9194,9200,9333,9323,0,9200,9205,9341,9333,0,9205,9210,9348,9341,0,9210,9212,9352,9348,0,9212,9214,9354,9352,0,9214,9216,9357,9354,0,9216,9218,9360,9357,0,9218,9220,9363,9360,0,9220,9221,9364,9363,0,9221,9219,9361,9364,0,9219,9217,9359,9361,0,9217,9215,9356,9359,0,9215,9213,9353,9356,0,9213,9211,9349,9353,0,9211,9209,9346,9349,0,9209,9199,9334,9346,0,9199,9195,9327,9334,0,9195,9181,9291,9327,0,9181,9178,9284,9291,0,9178,9176,9278,9284,0,9176,9174,9272,9278,0,9174,9162,9266,9272,0,9162,9152,9261,9266,0,9152,9142,9257,9261,0,9142,9129,9254,9257,0,9129,9116,9250,9254,0,9116,9100,9247,9250,0,9100,9092,9243,9247,0,9092,9085,9240,9243,0,9085,9079,9238,9240,0,9079,9072,9236,9238,0,9072,9067,9235,9236,0,9067,9062,9233,9235,0,9062,9055,9231,9233,0,9055,9049,9229,9231,0,9049,9042,9226,9229,0,9042,9038,9225,9226,0,9038,9021,9222,9225,0,9021,9025,9223,9222,0,9025,9028,9224,9223,0,9028,9044,9227,9224,0,9044,9048,9228,9227,0,9048,9054,9230,9228,0,9054,9061,9232,9230,0,9061,9066,9234,9232,0,9066,9073,9237,9234,0,9073,9081,9239,9237,0,9081,9087,9241,9239,0,9087,9094,9244,9241,0,9094,9104,9248,9244,0,9104,9121,9251,9248,0,9121,9137,9256,9251,0,9137,9148,9260,9256,0,9148,9161,9265,9260,0,9161,9169,9271,9265,0,9169,9175,9277,9271,0,9175,9177,9282,9277,0,9177,9183,9299,9282,0,9183,9188,9314,9299,0,9188,9191,9321,9314,0,9191,9193,9325,9321,0,9193,9197,9330,9325,0,9197,9201,9335,9330,0,9201,9203,9339,9335,0,9203,9206,9343,9339,0,9206,9208,9345,9343,0,9208,9207,9344,9345,0,9207,9204,9340,9344,0,9204,9202,9337,9340,0,9202,9198,9332,9337,0,9198,9196,9329,9332,0,9196,9192,9322,9329,0,9192,9189,9317,9322,0,9189,9187,9313,9317,0,9187,9185,9307,9313,0,9185,9184,9305,9307,0,9184,9180,9287,9305,0,9180,9179,9285,9287,0,9285,9292,9383,9378,0,9292,9311,9394,9383,0,9311,9318,9398,9394,0,9318,9323,9403,9398,0,9323,9333,9411,9403,0,9333,9341,9420,9411,0,9341,9348,9427,9420,0,9348,9352,9432,9427,0,9352,9354,9435,9432,0,9354,9357,9440,9435,0,9357,9360,9443,9440,0,9360,9363,9446,9443,0,9363,9364,9447,9446,0,9364,9361,9445,9447,0,9361,9359,9441,9445,0,9359,9356,9437,9441,0,9356,9353,9434,9437,0,9353,9349,9428,9434,0,9349,9346,9425,9428,0,9346,9334,9413,9425,0,9334,9327,9405,9413,0,9327,9291,9380,9405,0,9291,9284,9375,9380,0,9284,9278,9371,9375,0,9278,9272,9368,9371,0,9272,9266,9362,9368,0,9266,9261,9350,9362,0,9261,9257,9338,9350,0,9257,9254,9326,9338,0,9254,9250,9316,9326,0,9250,9247,9309,9316,0,9247,9243,9303,9309,0,9243,9240,9300,9303,0,9240,9238,9295,9300,0,9238,9236,9288,9295,0,9236,9235,9281,9288,0,9235,9233,9276,9281,0,9233,9231,9270,9276,0,9231,9229,9264,9270,0,9229,9226,9258,9264,0,9226,9225,9255,9258,0,9225,9222,9242,9255,0,9222,9223,9245,9242,0,9223,9224,9246,9245,0,9224,9227,9259,9246,0,9227,9228,9262,9259,0,9228,9230,9267,9262,0,9230,9232,9273,9267,0,9232,9234,9280,9273,0,9234,9237,9290,9280,0,9237,9239,9296,9290,0,9239,9241,9301,9296,0,9241,9244,9306,9301,0,9244,9248,9310,9306,0,9248,9251,9320,9310,0,9251,9256,9331,9320,0,9256,9260,9347,9331,0,9260,9265,9358,9347,0,9265,9271,9367,9358,0,9271,9277,9370,9367,0,9277,9282,9374,9370,0,9282,9299,9388,9374,0,9299,9314,9396,9388,0,9314,9321,9400,9396,0,9321,9325,9404,9400,0,9325,9330,9409,9404,0,9330,9335,9414,9409,0,9335,9339,9418,9414,0,9339,9343,9422,9418,0,9343,9345,9423,9422,0,9345,9344,9421,9423,0,9344,9340,9419,9421,0,9340,9337,9416,9419,0,9337,9332,9410,9416,0,9332,9329,9407,9410,0,9329,9322,9402,9407,0,9322,9317,9397,9402,0,9317,9313,9395,9397,0,9313,9307,9392,9395,0,9307,9305,9391,9392,0,9305,9287,9379,9391,0,9287,9285,9378,9379,0,9378,9383,9390,9386,0,9383,9394,9406,9390,0,9394,9398,9417,9406,0,9398,9403,9429,9417,0,9403,9411,9439,9429,0,9411,9420,9451,9439,0,9420,9427,9456,9451,0,9427,9432,9458,9456,0,9432,9435,9460,9458,0,9435,9440,9462,9460,0,9440,9443,9464,9462,0,9443,9446,9466,9464,0,9446,9447,9467,9466,0,9447,9445,9465,9467,0,9445,9441,9463,9465,0,9441,9437,9461,9463,0,9437,9434,9459,9461,0,9434,9428,9457,9459,0,9428,9425,9455,9457,0,9425,9413,9442,9455,0,9413,9405,9431,9442,0,9405,9380,9389,9431,0,9380,9375,9385,9389,0,9375,9371,9382,9385,0,9371,9368,9377,9382,0,9368,9362,9373,9377,0,9362,9350,9369,9373,0,9350,9338,9365,9369,0,9338,9326,9351,9365,0,9326,9316,9336,9351,0,9316,9309,9324,9336,0,9309,9303,9315,9324,0,9303,9300,9308,9315,0,9300,9295,9302,9308,0,9295,9288,9297,9302,0,9288,9281,9294,9297,0,9281,9276,9289,9294,0,9276,9270,9283,9289,0,9270,9264,9275,9283,0,9264,9258,9268,9275,0,9258,9255,9263,9268,0,9255,9242,9249,9263,0,9242,9245,9252,9249,0,9245,9246,9253,9252,0,9246,9259,9269,9253,0,9259,9262,9274,9269,0,9262,9267,9279,9274,0,9267,9273,9286,9279,0,9273,9280,9293,9286,0,9280,9290,9298,9293,0,9290,9296,9304,9298,0,9296,9301,9312,9304,0,9301,9306,9319,9312,0,9306,9310,9328,9319,0,9310,9320,9342,9328,0,9320,9331,9355,9342,0,9331,9347,9366,9355,0,9347,9358,9372,9366,0,9358,9367,9376,9372,0,9367,9370,9381,9376,0,9370,9374,9384,9381,0,9374,9388,9393,9384,0,9388,9396,9412,9393,0,9396,9400,9424,9412,0,9400,9404,9430,9424,0,9404,9409,9436,9430,0,9409,9414,9444,9436,0,9414,9418,9449,9444,0,9418,9422,9453,9449,0,9422,9423,9454,9453,0,9423,9421,9452,9454,0,9421,9419,9450,9452,0,9419,9416,9448,9450,0,9416,9410,9438,9448,0,9410,9407,9433,9438,0,9407,9402,9426,9433,0,9402,9397,9415,9426,0,9397,9395,9408,9415,0,9395,9392,9401,9408,0,9392,9391,9399,9401,0,9391,9379,9387,9399,0,9379,9378,9386,9387,0,9386,9390,9525,9519,0,9390,9406,9539,9525,0,9406,9417,9547,9539,0,9417,9429,9553,9547,0,9429,9439,9562,9553,0,9439,9451,9568,9562,0,9451,9456,9577,9568,0,9456,9458,9580,9577,0,9458,9460,9585,9580,0,9460,9462,9587,9585,0,9462,9464,9589,9587,0,9464,9466,9592,9589,0,9466,9467,9593,9592,0,9467,9465,9590,9593,0,9465,9463,9588,9590,0,9463,9461,9586,9588,0,9461,9459,9583,9586,0,9459,9457,9579,9583,0,9457,9455,9576,9579,0,9455,9442,9564,9576,0,9442,9431,9556,9564,0,9431,9389,9524,9556,0,9389,9385,9518,9524,0,9385,9382,9514,9518,0,9382,9377,9510,9514,0,9377,9373,9506,9510,0,9373,9369,9502,9506,0,9369,9365,9499,9502,0,9365,9351,9497,9499,0,9351,9336,9495,9497,0,9336,9324,9491,9495,0,9324,9315,9488,9491,0,9315,9308,9486,9488,0,9308,9302,9484,9486,0,9302,9297,9482,9484,0,9297,9294,9481,9482,0,9294,9289,9479,9481,0,9289,9283,9477,9479,0,9283,9275,9475,9477,0,9275,9268,9472,9475,0,9268,9263,9471,9472,0,9263,9249,9468,9471,0,9249,9252,9469,9468,0,9252,9253,9470,9469,0,9253,9269,9473,9470,0,9269,9274,9474,9473,0,9274,9279,9476,9474,0,9279,9286,9478,9476,0,9286,9293,9480,9478,0,9293,9298,9483,9480,0,9298,9304,9485,9483,0,9304,9312,9487,9485,0,9312,9319,9489,9487,0,9319,9328,9492,9489,0,9328,9342,9496,9492,0,9342,9355,9498,9496,0,9355,9366,9501,9498,0,9366,9372,9505,9501,0,9372,9376,9509,9505,0,9376,9381,9512,9509,0,9381,9384,9516,9512,0,9384,9393,9530,9516,0,9393,9412,9544,9530,0,9412,9424,9551,9544,0,9424,9430,9555,9551,0,9430,9436,9560,9555,0,9436,9444,9565,9560,0,9444,9449,9569,9565,0,9449,9453,9573,9569,0,9453,9454,9574,9573,0,9454,9452,9572,9574,0,9452,9450,9570,9572,0,9450,9448,9567,9570,0,9448,9438,9563,9567,0,9438,9433,9557,9563,0,9433,9426,9552,9557,0,9426,9415,9545,9552,0,9415,9408,9542,9545,0,9408,9401,9536,9542,0,9401,9399,9533,9536,0,9399,9387,9521,9533,0,9387,9386,9519,9521,0,9519,9525,9616,9611,0,9525,9539,9627,9616,0,9539,9547,9633,9627,0,9547,9553,9638,9633,0,9553,9562,9645,9638,0,9562,9568,9651,9645,0,9568,9577,9660,9651,0,9577,9580,9663,9660,0,9580,9585,9666,9663,0,9585,9587,9669,9666,0,9587,9589,9671,9669,0,9589,9592,9673,9671,0,9592,9593,9674,9673,0,9593,9590,9672,9674,0,9590,9588,9670,9672,0,9588,9586,9668,9670,0,9586,9583,9664,9668,0,9583,9579,9662,9664,0,9579,9576,9659,9662,0,9576,9564,9647,9659,0,9564,9556,9640,9647,0,9556,9524,9615,9640,0,9524,9518,9610,9615,0,9518,9514,9606,9610,0,9514,9510,9602,9606,0,9510,9506,9599,9602,0,9506,9502,9596,9599,0,9502,9499,9584,9596,0,9499,9497,9575,9584,0,9497,9495,9559,9575,0,9495,9491,9549,9559,0,9491,9488,9541,9549,0,9488,9486,9535,9541,0,9486,9484,9531,9535,0,9484,9482,9528,9531,0,9482,9481,9523,9528,0,9481,9479,9517,9523,0,9479,9477,9513,9517,0,9477,9475,9508,9513,0,9475,9472,9503,9508,0,9472,9471,9500,9503,0,9471,9468,9490,9500,0,9468,9469,9493,9490,0,9469,9470,9494,9493,0,9470,9473,9504,9494,0,9473,9474,9507,9504,0,9474,9476,9511,9507,0,9476,9478,9515,9511,0,9478,9480,9522,9515,0,9480,9483,9529,9522,0,9483,9485,9532,9529,0,9485,9487,9537,9532,0,9487,9489,9543,9537,0,9489,9492,9550,9543,0,9492,9496,9561,9550,0,9496,9498,9578,9561,0,9498,9501,9591,9578,0,9501,9505,9597,9591,0,9505,9509,9601,9597,0,9509,9512,9605,9601,0,9512,9516,9609,9605,0,9516,9530,9620,9609,0,9530,9544,9631,9620,0,9544,9551,9635,9631,0,9551,9555,9639,9635,0,9555,9560,9644,9639,0,9560,9565,9648,9644,0,9565,9569,9652,9648,0,9569,9573,9655,9652,0,9573,9574,9656,9655,0,9574,9572,9654,9656,0,9572,9570,9653,9654,0,9570,9567,9649,9653,0,9567,9563,9646,9649,0,9563,9557,9641,9646,0,9557,9552,9637,9641,0,9552,9545,9632,9637,0,9545,9542,9628,9632,0,9542,9536,9625,9628,0,9536,9533,9623,9625,0,9533,9521,9612,9623,0,9521,9519,9611,9612,0,9611,9616,9667,9658,0,9616,9627,9678,9667,0,9627,9633,9682,9678,0,9633,9638,9685,9682,0,9638,9645,9690,9685,0,9645,9651,9695,9690,0,9651,9660,9702,9695,0,9660,9663,9705,9702,0,9663,9666,9707,9705,0,9666,9669,9709,9707,0,9669,9671,9711,9709,0,9671,9673,9714,9711,0,9673,9674,9715,9714,0,9674,9672,9713,9715,0,9672,9670,9710,9713,0,9670,9668,9708,9710,0,9668,9664,9706,9708,0,9664,9662,9704,9706,0,9662,9659,9701,9704,0,9659,9647,9692,9701,0,9647,9640,9687,9692,0,9640,9615,9665,9687,0,9615,9610,9657,9665,0,9610,9606,9643,9657,0,9606,9602,9636,9643,0,9602,9599,9630,9636,0,9599,9596,9626,9630,0,9596,9584,9622,9626,0,9584,9575,9619,9622,0,9575,9559,9617,9619,0,9559,9549,9613,9617,0,9549,9541,9607,9613,0,9541,9535,9603,9607,0,9535,9531,9598,9603,0,9531,9528,9594,9598,0,9528,9523,9582,9594,0,9523,9517,9571,9582,0,9517,9513,9558,9571,0,9513,9508,9548,9558,0,9508,9503,9538,9548,0,9503,9500,9534,9538,0,9500,9490,9520,9534,0,9490,9493,9526,9520,0,9493,9494,9527,9526,0,9494,9504,9540,9527,0,9504,9507,9546,9540,0,9507,9511,9554,9546,0,9511,9515,9566,9554,0,9515,9522,9581,9566,0,9522,9529,9595,9581,0,9529,9532,9600,9595,0,9532,9537,9604,9600,0,9537,9543,9608,9604,0,9543,9550,9614,9608,0,9550,9561,9618,9614,0,9561,9578,9621,9618,0,9578,9591,9624,9621,0,9591,9597,9629,9624,0,9597,9601,9634,9629,0,9601,9605,9642,9634,0,9605,9609,9650,9642,0,9609,9620,9675,9650,0,9620,9631,9680,9675,0,9631,9635,9683,9680,0,9635,9639,9686,9683,0,9639,9644,9689,9686,0,9644,9648,9693,9689,0,9648,9652,9696,9693,0,9652,9655,9699,9696,0,9655,9656,9700,9699,0,9656,9654,9698,9700,0,9654,9653,9697,9698,0,9653,9649,9694,9697,0,9649,9646,9691,9694,0,9646,9641,9688,9691,0,9641,9637,9684,9688,0,9637,9632,9681,9684,0,9632,9628,9679,9681,0,9628,9625,9677,9679,0,9625,9623,9676,9677,0,9623,9612,9661,9676,0,9612,9611,9658,9661,0,9658,9667,9770,9765,0,9667,9678,9782,9770,0,9678,9682,9788,9782,0,9682,9685,9792,9788,0,9685,9690,9798,9792,0,9690,9695,9804,9798,0,9695,9702,9812,9804,0,9702,9705,9815,9812,0,9705,9707,9818,9815,0,9707,9709,9820,9818,0,9709,9711,9823,9820,0,9711,9714,9825,9823,0,9714,9715,9826,9825,0,9715,9713,9824,9826,0,9713,9710,9822,9824,0,9710,9708,9819,9822,0,9708,9706,9817,9819,0,9706,9704,9814,9817,0,9704,9701,9811,9814,0,9701,9692,9801,9811,0,9692,9687,9796,9801,0,9687,9665,9769,9796,0,9665,9657,9766,9769,0,9657,9643,9761,9766,0,9643,9636,9758,9761,0,9636,9630,9754,9758,0,9630,9626,9750,9754,0,9626,9622,9746,9750,0,9622,9619,9743,9746,0,9619,9617,9741,9743,0,9617,9613,9738,9741,0,9613,9607,9735,9738,0,9607,9603,9732,9735,0,9603,9598,9730,9732,0,9598,9594,9728,9730,0,9594,9582,9727,9728,0,9582,9571,9725,9727,0,9571,9558,9723,9725,0,9558,9548,9721,9723,0,9548,9538,9718,9721,0,9538,9534,9717,9718,0,9534,9520,9703,9717,0,9520,9526,9712,9703,0,9526,9527,9716,9712,0,9527,9540,9719,9716,0,9540,9546,9720,9719,0,9546,9554,9722,9720,0,9554,9566,9724,9722,0,9566,9581,9726,9724,0,9581,9595,9729,9726,0,9595,9600,9731,9729,0,9600,9604,9733,9731,0,9604,9608,9736,9733,0,9608,9614,9740,9736,0,9614,9618,9742,9740,0,9618,9621,9745,9742,0,9621,9624,9749,9745,0,9624,9629,9753,9749,0,9629,9634,9756,9753,0,9634,9642,9760,9756,0,9642,9650,9763,9760,0,9650,9675,9775,9763,0,9675,9680,9786,9775,0,9680,9683,9789,9786,0,9683,9686,9794,9789,0,9686,9689,9797,9794,0,9689,9693,9802,9797,0,9693,9696,9807,9802,0,9696,9699,9809,9807,0,9699,9700,9810,9809,0,9700,9698,9808,9810,0,9698,9697,9806,9808,0,9697,9694,9803,9806,0,9694,9691,9799,9803,0,9691,9688,9795,9799,0,9688,9684,9790,9795,0,9684,9681,9787,9790,0,9681,9679,9783,9787,0,9679,9677,9779,9783,0,9677,9676,9778,9779,0,9676,9661,9768,9778,0,9661,9658,9765,9768,0,9765,9770,9841,9837,0,9770,9782,9853,9841,0,9782,9788,9858,9853,0,9788,9792,9863,9858,0,9792,9798,9869,9863,0,9798,9804,9876,9869,0,9804,9812,9884,9876,0,9812,9815,9886,9884,0,9815,9818,9889,9886,0,9818,9820,9892,9889,0,9820,9823,9894,9892,0,9823,9825,9896,9894,0,9825,9826,9897,9896,0,9826,9824,9895,9897,0,9824,9822,9893,9895,0,9822,9819,9891,9893,0,9819,9817,9888,9891,0,9817,9814,9885,9888,0,9814,9811,9883,9885,0,9811,9801,9872,9883,0,9801,9796,9868,9872,0,9796,9769,9842,9868,0,9769,9766,9838,9842,0,9766,9761,9835,9838,0,9761,9758,9833,9835,0,9758,9754,9829,9833,0,9754,9750,9821,9829,0,9750,9746,9813,9821,0,9746,9743,9800,9813,0,9743,9741,9791,9800,0,9741,9738,9784,9791,0,9738,9735,9780,9784,0,9735,9732,9776,9780,0,9732,9730,9773,9776,0,9730,9728,9771,9773,0,9728,9727,9767,9771,0,9727,9725,9762,9767,0,9725,9723,9757,9762,0,9723,9721,9752,9757,0,9721,9718,9747,9752,0,9718,9717,9744,9747,0,9717,9703,9734,9744,0,9703,9712,9737,9734,0,9712,9716,9739,9737,0,9716,9719,9748,9739,0,9719,9720,9751,9748,0,9720,9722,9755,9751,0,9722,9724,9759,9755,0,9724,9726,9764,9759,0,9726,9729,9772,9764,0,9729,9731,9774,9772,0,9731,9733,9777,9774,0,9733,9736,9781,9777,0,9736,9740,9785,9781,0,9740,9742,9793,9785,0,9742,9745,9805,9793,0,9745,9749,9816,9805,0,9749,9753,9828,9816,0,9753,9756,9831,9828,0,9756,9760,9834,9831,0,9760,9763,9836,9834,0,9763,9775,9847,9836,0,9775,9786,9859,9847,0,9786,9789,9861,9859,0,9789,9794,9866,9861,0,9794,9797,9870,9866,0,9797,9802,9873,9870,0,9802,9807,9878,9873,0,9807,9809,9881,9878,0,9809,9810,9882,9881,0,9810,9808,9880,9882,0,9808,9806,9877,9880,0,9806,9803,9874,9877,0,9803,9799,9871,9874,0,9799,9795,9867,9871,0,9795,9790,9862,9867,0,9790,9787,9857,9862,0,9787,9783,9855,9857,0,9783,9779,9851,9855,0,9779,9778,9849,9851,0,9778,9768,9839,9849,0,9768,9765,9837,9839,0,9837,9841,9919,9916,0,9841,9853,9924,9919,0,9853,9858,9927,9924,0,9858,9863,9931,9927,0,9863,9869,9935,9931,0,9869,9876,9941,9935,0,9876,9884,9948,9941,0,9884,9886,9950,9948,0,9886,9889,9952,9950,0,9889,9892,9954,9952,0,9892,9894,9956,9954,0,9894,9896,9958,9956,0,9896,9897,9959,9958,0,9897,9895,9957,9959,0,9895,9893,9955,9957,0,9893,9891,9953,9955,0,9891,9888,9951,9953,0,9888,9885,9949,9951,0,9885,9883,9947,9949,0,9883,9872,9938,9947,0,9872,9868,9934,9938,0,9868,9842,9920,9934,0,9842,9838,9917,9920,0,9838,9835,9914,9917,0,9835,9833,9912,9914,0,9833,9829,9910,9912,0,9829,9821,9908,9910,0,9821,9813,9906,9908,0,9813,9800,9904,9906,0,9800,9791,9902,9904,0,9791,9784,9900,9902,0,9784,9780,9898,9900,0,9780,9776,9887,9898,0,9776,9773,9875,9887,0,9773,9771,9865,9875,0,9771,9767,9860,9865,0,9767,9762,9854,9860,0,9762,9757,9850,9854,0,9757,9752,9846,9850,0,9752,9747,9843,9846,0,9747,9744,9840,9843,0,9744,9734,9827,9840,0,9734,9737,9830,9827,0,9737,9739,9832,9830,0,9739,9748,9844,9832,0,9748,9751,9845,9844,0,9751,9755,9848,9845,0,9755,9759,9852,9848,0,9759,9764,9856,9852,0,9764,9772,9864,9856,0,9772,9774,9879,9864,0,9774,9777,9890,9879,0,9777,9781,9899,9890,0,9781,9785,9901,9899,0,9785,9793,9903,9901,0,9793,9805,9905,9903,0,9805,9816,9907,9905,0,9816,9828,9909,9907,0,9828,9831,9911,9909,0,9831,9834,9913,9911,0,9834,9836,9915,9913,0,9836,9847,9921,9915,0,9847,9859,9928,9921,0,9859,9861,9930,9928,0,9861,9866,9932,9930,0,9866,9870,9936,9932,0,9870,9873,9939,9936,0,9873,9878,9943,9939,0,9878,9881,9945,9943,0,9881,9882,9946,9945,0,9882,9880,9944,9946,0,9880,9877,9942,9944,0,9877,9874,9940,9942,0,9874,9871,9937,9940,0,9871,9867,9933,9937,0,9867,9862,9929,9933,0,9862,9857,9926,9929,0,9857,9855,9925,9926,0,9855,9851,9923,9925,0,9851,9849,9922,9923,0,9849,9839,9918,9922,0,9839,9837,9916,9918,0,2767,2789,2792,2798,2801,2807,2812,2816,2820,2821,2819,2815,2813,2809,2802,2797,2791,2784,2778,2754,2734,2728,2723,2717,2710,2705,2700,2693,2690,2686,2682,2680,2676,2673,2670,2669,2667,2664,2663,2662,2665,2666,2668,2671,2672,2675,2678,2681,2684,2687,2692,2696,2701,2707,2711,2715,2721,2727,2733,2741,2786,2794,2803,2810,2818,2825,2828,2831,2835,2838,2840,2841,2839,2836,2833,2829,2826,2817,2808,2800,2776,2764,0,9916,9919,9924,9927,9931,9935,9941,9948,9950,9952,9954,9956,9958,9959,9957,9955,9953,9951,9949,9947,9938,9934,9920,9917,9914,9912,9910,9908,9906,9904,9902,9900,9898,9887,9875,9865,9860,9854,9850,9846,9843,9840,9827,9830,9832,9844,9845,9848,9852,9856,9864,9879,9890,9899,9901,9903,9905,9907,9909,9911,9913,9915,9921,9928,9930,9932,9936,9939,9943,9945,9946,9944,9942,9940,9937,9933,9929,9926,9925,9923,9922,9918,0,690,692,688,0,690,702,692,0,701,705,702,0,704,707,705,0,706,711,707,0,708,714,711,0,709,717,714,0,709,726,717,0,712,728,726,0,716,730,728,0,718,732,730,0,721,734,732,0,723,736,734,0,725,738,736,0,724,737,738,0,724,735,737,0,722,733,735,0,719,731,733,0,715,729,731,0,713,727,729,0,710,720,727,0,703,699,720,0,697,698,699,0,695,696,698,0,693,694,696,0,689,691,694,0,686,687,691,0,684,685,687,0,684,683,685,0,682,681,683,0,679,680,681,0,673,671,680,0,665,663,671,0,650,649,663,0,650,642,649,0,641,638,642,0,637,634,638,0,631,629,634,0,631,624,629,0,625,619,624,0,622,614,619,0,604,600,614,0,604,602,600,0,614,617,604,0,614,622,617,0,619,625,622,0,624,631,625,0,634,637,631,0,638,641,637,0,642,650,641,0,663,665,650,0,671,673,665,0,680,679,673,0,681,682,679,0,683,684,682,0,687,686,684,0,691,689,686,0,694,693,689,0,696,695,693,0,698,697,695,0,699,703,697,0,720,710,703,0,727,713,710,0,729,715,713,0,731,719,715,0,733,722,719,0,735,724,722,0,738,725,724,0,736,723,725,0,734,721,723,0,732,718,721,0,730,716,718,0,728,712,716,0,726,709,712,0,714,708,709,0,711,706,708,0,707,704,706,0,705,701,704,0,702,700,701,0,702,690,700,0,811,810,814,0,823,820,811,0,823,821,820,0,825,824,821,0,828,826,824,0,831,827,826,0,835,830,827,0,847,833,830,0,850,836,833,0,852,839,836,0,854,842,839,0,856,843,842,0,858,845,843,0,859,844,845,0,855,841,844,0,853,838,841,0,851,834,838,0,849,832,834,0,846,829,832,0,837,822,829,0,819,817,822,0,818,815,817,0,816,812,815,0,813,808,812,0,809,806,808,0,807,804,806,0,803,802,804,0,801,799,802,0,800,798,799,0,797,796,798,0,795,794,796,0,792,791,794,0,790,789,791,0,788,787,789,0,784,785,787,0,782,783,785,0,780,781,783,0,780,779,781,0,777,778,779,0,779,780,777,0,783,782,780,0,785,784,782,0,787,786,784,0,787,788,786,0,789,790,788,0,791,792,790,0,794,793,792,0,794,795,793,0,796,797,795,0,798,800,797,0,799,801,800,0,802,803,801,0,804,805,803,0,804,807,805,0,806,809,807,0,808,813,809,0,812,816,813,0,815,818,816,0,817,819,818,0,822,837,819,0,829,846,837,0,832,849,848,846,0,834,851,849,0,838,853,851,0,841,855,853,0,844,857,855,0,844,859,857,0,845,858,859,0,843,856,858,0,842,854,856,0,839,852,854,0,836,850,852,0,833,847,850,0,830,840,847,0,830,835,840,0,827,831,835,0,826,828,831,0,824,825,828,0,821,823,825,0,811,814,823,0,979,978,982,0,994,990,979,0,994,993,990,0,998,996,993,0,1004,999,996,0,1010,1003,999,0,1015,1007,1003,0,1029,1012,1007,0,1033,1016,1012,0,1036,1021,1016,0,1038,1024,1021,0,1040,1027,1024,0,1042,1028,1027,0,1041,1025,1028,0,1037,1020,1025,0,1035,1014,1020,0,1034,1011,1014,0,1030,1006,1011,0,1023,1002,1006,0,1013,989,1002,0,986,983,989,0,984,980,983,0,981,976,980,0,977,972,976,0,973,969,972,0,970,967,969,0,966,965,967,0,964,963,965,0,962,961,963,0,960,959,961,0,958,957,959,0,955,954,957,0,953,952,954,0,951,950,952,0,947,948,950,0,945,946,948,0,943,944,946,0,943,942,944,0,940,941,942,0,942,943,940,0,946,945,943,0,948,947,945,0,950,949,947,0,950,951,949,0,952,953,951,0,954,955,953,0,957,956,955,0,957,958,956,0,959,960,958,0,961,962,960,0,963,964,962,0,965,966,964,0,967,968,966,0,967,970,968,0,969,973,970,0,972,977,973,0,976,981,977,0,980,984,981,0,983,986,984,0,989,1013,986,0,1002,1023,1013,0,1006,1030,1023,0,1011,1034,1030,0,1014,1035,1034,0,1020,1037,1035,0,1025,1039,1037,0,1025,1041,1039,0,1028,1042,1041,0,1027,1040,1042,0,1024,1038,1040,0,1021,1036,1038,0,1016,1033,1036,0,1012,1029,1033,0,1007,1026,1029,0,1007,1015,1026,0,1003,1010,1015,0,999,1004,1010,0,996,998,1004,0,993,994,998,0,979,982,994,0,811,814,810,0,811,823,814,0,821,825,823,0,824,828,825,0,826,831,828,0,827,835,831,0,830,840,835,0,830,847,840,0,833,850,847,0,836,852,850,0,839,854,852,0,842,856,854,0,843,858,856,0,845,859,858,0,844,857,859,0,844,855,857,0,841,853,855,0,838,851,853,0,834,849,851,0,832,846,848,849,0,829,837,846,0,822,819,837,0,817,818,819,0,815,816,818,0,812,813,816,0,808,809,813,0,806,807,809,0,804,805,807,0,804,803,805,0,802,801,803,0,799,800,801,0,798,797,800,0,796,795,797,0,794,793,795,0,794,792,793,0,791,790,792,0,789,788,790,0,787,786,788,0,787,784,786,0,785,782,784,0,783,780,782,0,779,777,780,0,779,778,777,0,780,781,779,0,780,783,781,0,782,785,783,0,784,787,785,0,788,789,787,0,790,791,789,0,792,794,791,0,795,796,794,0,797,798,796,0,800,799,798,0,801,802,799,0,803,804,802,0,807,806,804,0,809,808,806,0,813,812,808,0,816,815,812,0,818,817,815,0,819,822,817,0,837,829,822,0,846,832,829,0,849,834,832,0,851,838,834,0,853,841,838,0,855,844,841,0,859,845,844,0,858,843,845,0,856,842,843,0,854,839,842,0,852,836,839,0,850,833,836,0,847,830,833,0,835,827,830,0,831,826,827,0,828,824,826,0,825,821,824,0,823,820,821,0,823,811,820,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [508710.84184697916, 6651127.894657594, 90.64963022028905], + [508710.63451255544, 6651128.467916771, 90.64963022028905], + [508710.63451255544, 6651128.467916771, 90.77963022028906], + [508710.84184697916, 6651127.894657594, 92.47843387928906], + [508710.63451255544, 6651128.467916771, 92.47843387928906], + [508710.83471814217, 6651127.914368123, 92.94402456628906], + [508710.62822240515, 6651128.485308414, 92.88924919128907], + [508710.81242531847, 6651127.976005576, 93.42129551828906], + [508710.6085522666, 6651128.539694401, 93.31037061928907], + [508710.77381871856, 6651128.082749007, 93.90419653828906], + [508710.5744876195, 6651128.633879782, 93.73645975428906], + [508710.7336672429, 6651128.193763865, 94.26590252328907], + [508710.52533278905, 6651128.769788027, 94.16136625828906], + [508710.6837179477, 6651128.331868728, 94.62366036928907], + [508710.46079327207, 6651128.94823341, 94.57833296028907], + [508710.6239648667, 6651128.497080087, 94.97411658428906], + [508710.381039242, 6651129.168745415, 94.98028187728906], + [508710.5545772241, 6651128.688930056, 95.31386161128906], + [508710.47590531467, 6651128.906450105, 95.63952872128907], + [508710.28673993266, 6651129.429473679, 95.36016267928906], + [508710.3884785856, 6651129.1481763655, 95.94789752928908], + [508710.2071537418, 6651129.649521626, 95.62656899428906], + [508710.12069504283, 6651129.888571378, 95.87427873428906], + [508710.2929955248, 6651129.412177585, 96.23599588028905], + [508710.190305617, 6651129.696105025, 96.50119360528906], + [508709.9961057662, 6651130.233048406, 96.17172120428907], + [508710.0813843083, 6651129.997261671, 96.74128205228907], + [508709.86285567685, 6651130.601471727, 96.42793432728907], + [508709.96730251657, 6651130.312686544, 96.95453438728906], + [508709.723289706, 6651130.9873578325, 96.64021213628908], + [508706.4851137081, 6651139.940594222, 90.64963022028905], + [508706.4851137081, 6651139.940594222, 90.77963022028906], + [508709.849192655, 6651130.639248629, 97.13974328928906], + [508706.2777792843, 6651140.513853399, 90.64963022028905], + [508709.57982625184, 6651131.384020096, 96.80732689328907], + [508709.7282133653, 6651130.973744401, 97.29623458128906], + [508709.4348317733, 6651131.784915489, 96.92948001528907], + [508709.60551513615, 6651131.31299287, 97.42385734028906], + [508709.2905118211, 6651132.183945884, 97.00815470828906], + [508709.4822087595, 6651131.653922807, 97.52295283428906], + [508709.14882702165, 6651132.575690342, 97.04589756728906], + [508709.3186461469, 6651132.106157256, 97.61211748628907], + [508706.4851129126, 6651139.940596422, 92.47843388028906], + [508706.4866588913, 6651139.936321944, 92.68225516428906], + [508709.15807004046, 6651132.55013431, 97.65489272728908], + [508706.2777792843, 6651140.513853399, 92.47843387928906], + [508706.49949579797, 6651139.900829167, 93.09883445228905], + [508708.55362604477, 6651134.221362181, 97.04589756728906], + [508706.28490812134, 6651140.49414287, 92.94402456628906], + [508706.5262542289, 6651139.826844751, 93.52316157228907], + [508706.30720094504, 6651140.432505418, 93.42129551828906], + [508706.5678003188, 6651139.711973921, 93.94947192328905], + [508706.6246385284, 6651139.554821893, 94.37128078228906], + [508706.34580754495, 6651140.325761987, 93.90419653828906], + [508707.97079844604, 6651135.832822851, 97.04589756728906], + [508706.6968373622, 6651139.355199258, 94.78163032528906], + [508706.3859590205, 6651140.214747127, 94.26590252328907], + [508707.8291136465, 6651136.224567309, 97.00815470828906], + [508706.78397924855, 6651139.11426056, 95.17341001928907], + [508707.68479369435, 6651136.623597706, 96.92948001528907], + [508706.43590831576, 6651140.076642266, 94.62366036928907], + [508706.8586069096, 6651138.907922458, 95.45089187928906], + [508707.5397992159, 6651137.024493099, 96.80732689328907], + [508706.9405642631, 6651138.681318481, 95.71133255228906], + [508707.96155622305, 6651135.858376684, 97.65489272728908], + [508707.0291440019, 6651138.436404263, 95.95230219828906], + [508707.3963357616, 6651137.4211553605, 96.64021213628908], + [508706.4956613969, 6651139.9114309065, 94.97411658428906], + [508707.1235197014, 6651138.175464787, 96.17172120428907], + [508707.25676979084, 6651137.807041467, 96.42793432728907], + [508706.5650490394, 6651139.719580937, 95.31386161128906], + [508707.8009801167, 6651136.302353737, 97.61211748628907], + [508706.64372094884, 6651139.502060887, 95.63952872128907], + [508707.637417504, 6651136.754588186, 97.52295283428906], + [508706.7311476779, 6651139.260334628, 95.94789752928908], + [508707.5141111274, 6651137.095518122, 97.42385734028906], + [508706.8266307387, 6651138.996333408, 96.23599588028905], + [508707.3914128982, 6651137.4347665915, 97.29623458128906], + [508706.9293206465, 6651138.712405968, 96.50119360528906], + [508707.27043360844, 6651137.769262364, 97.13974328928906], + [508707.0382419553, 6651138.411249321, 96.74128205228907], + [508707.1523237469, 6651138.095824449, 96.95453438728906], + [508719.34644272923, 6651130.970570781, 90.78879207594775], + [508719.1391083054, 6651131.543829958, 90.78879207594775], + [508719.1391083054, 6651131.543829958, 90.91879207594776], + [508720.23537689366, 6651131.291833014, 90.80304684876648], + [508719.34644272923, 6651130.970570781, 92.61759573494776], + [508720.02832132427, 6651131.86519297, 90.80304684876648], + [508720.02832132427, 6651131.86519297, 90.9330468487665], + [508719.1391083054, 6651131.543829958, 92.61759573494776], + [508719.3393138921, 6651130.990281312, 93.08318642194777], + [508719.1328181552, 6651131.561221601, 93.02841104694775], + [508719.3170210684, 6651131.051918764, 93.56045737394776], + [508719.11314801656, 6651131.61560759, 93.44953247494776], + [508720.23537689366, 6651131.291833014, 92.63185050776649], + [508719.2784144686, 6651131.158662194, 94.04335839394776], + [508719.07908336946, 6651131.70979297, 93.87562160994777], + [508720.02832132427, 6651131.86519297, 92.63185050776649], + [508719.238262993, 6651131.269677053, 94.40506437894776], + [508720.2282576446, 6651131.311547009, 93.0974411947665], + [508719.029928539, 6651131.845701215, 94.30052811394776], + [508720.02203963394, 6651131.882587671, 93.0426658197665], + [508719.18831369776, 6651131.407781915, 94.76282222494775], + [508720.2059948036, 6651131.373195298, 93.57471214676649], + [508718.9653890221, 6651132.024146597, 94.71749481594776], + [508720.0023959507, 6651131.93698322, 93.46378724776649], + [508719.12856061663, 6651131.572993275, 95.11327843994776], + [508720.1674401276, 6651131.479957494, 94.05761316676649], + [508719.9683771189, 6651132.0311851585, 93.88987638276649], + [508718.88563499204, 6651132.244658602, 95.11944373294777], + [508719.05917297414, 6651131.764843244, 95.45302346694776], + [508720.1273426537, 6651131.59099187, 94.41931915176649], + [508719.91928839916, 6651132.167117296, 94.3147828867665], + [508718.9805010646, 6651131.982363293, 95.77869057694775], + [508718.7913356826, 6651132.505386867, 95.49932453494776], + [508720.07746053784, 6651131.72912101, 94.77707699776649], + [508718.8930743356, 6651132.224089553, 96.08705938494776], + [508718.7117494918, 6651132.725434814, 95.76573084994776], + [508719.8548356846, 6651132.345594048, 94.7317495887665], + [508720.0177878216, 6651131.894361413, 95.1275332127665], + [508718.6252907928, 6651132.964484566, 96.01344058994778], + [508718.7975912748, 6651132.488090773, 96.37515773594775], + [508719.7751889197, 6651132.56614482, 95.1336985057665], + [508719.948493502, 6651132.08624511, 95.46727823976649], + [508718.694901367, 6651132.772018213, 96.64035546094777], + [508718.5007015163, 6651133.3089615945, 96.31088305994776], + [508719.86992740224, 6651132.303803399, 95.7929453497665], + [508719.68101643823, 6651132.82691892, 95.51357930776649], + [508718.58598005824, 6651133.07317486, 96.88044390794778], + [508718.3674514268, 6651133.677384914, 96.56709618294778], + [508719.78261825774, 6651132.545572154, 96.10131415776651], + [508719.60153728677, 6651133.047005552, 95.77998562276649], + [508718.4718982665, 6651133.388599731, 97.09369624294777], + [508718.227885456, 6651134.063271021, 96.77937399194776], + [508714.9897094581, 6651143.01650741, 90.78879207594775], + [508719.5151948704, 6651133.286097328, 96.0276953627665], + [508719.68726361694, 6651132.809619785, 96.38941250876648], + [508714.9897094581, 6651143.01650741, 90.91879207594776], + [508718.3537884051, 6651133.715161817, 97.27890514494776], + [508714.78237503424, 6651143.589766587, 90.78879207594775], + [508718.0844220018, 6651134.459933283, 96.94648874894776], + [508719.58471182187, 6651133.093597139, 96.65461023376649], + [508719.3907731602, 6651133.630634915, 96.3251378327665], + [508718.23280911526, 6651134.049657589, 97.43539643694777], + [508717.93942752335, 6651134.860828677, 97.06864187094776], + [508719.4759370069, 6651133.394806729, 96.8946986807665], + [508718.1101108861, 6651134.388906058, 97.56301919594776], + [508719.2577022854, 6651133.999123003, 96.5813509557665], + [508717.7951075712, 6651135.259859072, 97.14731656394775], + [508717.9868045096, 6651134.7298359955, 97.66211468994776], + [508719.36200864945, 6651133.710287051, 97.10795101576649], + [508717.65342277166, 6651135.65160353, 97.18505942294776], + [508719.11832402385, 6651134.385076948, 96.79362876476651], + [508715.8845032102, 6651143.339887308, 90.80304684876648], + [508715.8845032102, 6651143.339887308, 90.9330468487665], + [508717.82324189687, 6651135.182070444, 97.75127934194776], + [508719.24405763973, 6651134.036906548, 97.29315991776649], + [508714.98970866256, 6651143.01650961, 92.61759573594777], + [508715.6774476409, 6651143.913247264, 90.80304684876648], + [508718.9750535208, 6651134.7818089435, 96.9607435217665], + [508714.99125464127, 6651143.012235131, 92.82141701994776], + [508717.6626657904, 6651135.626047498, 97.79405458294777], + [508719.12324106105, 6651134.371461123, 97.44965120976649], + [508714.78237503424, 6651143.589766587, 92.61759573494776], + [508718.8302540526, 6651135.182774814, 97.0828966437665], + [508715.0040915479, 6651142.976742355, 93.23799630794775], + [508719.00070785487, 6651134.710769232, 97.57727396876649], + [508717.05822179484, 6651137.297275369, 97.18505942294776], + [508714.78950387135, 6651143.5700560585, 93.08318642194777], + [508718.6861282035, 6651135.581875358, 97.16157133676649], + [508715.03084997885, 6651142.90275794, 93.66232342794775], + [508718.8775673192, 6651135.051759104, 97.67636946276649], + [508718.544633963, 6651135.973688684, 97.19931419576649], + [508714.81179669505, 6651143.508418606, 93.56045737394776], + [508715.0723960689, 6651142.787887109, 94.08863377894775], + [508718.71422469, 6651135.5040730545, 97.7655341147665], + [508715.8845024158, 6651143.339889509, 92.6318505087665], + [508715.12923427834, 6651142.630735081, 94.51044263794776], + [508714.85040329496, 6651143.401675175, 94.04335839394776], + [508715.8860463153, 6651143.335614278, 92.83567179276649], + [508718.5538645504, 6651135.94812816, 97.80830935576651], + [508716.47539419605, 6651138.908736039, 97.18505942294776], + [508715.20143311226, 6651142.431112445, 94.92079218094777], + [508715.6774476409, 6651143.913247264, 92.63185050776649], + [508714.8905547706, 6651143.290660315, 94.40506437894776], + [508716.3337093965, 6651139.300480497, 97.14731656394775], + [508715.2885749985, 6651142.190173748, 95.31257187494776], + [508715.89886595693, 6651143.300115261, 93.25225108076648], + [508716.18938944436, 6651139.699510893, 97.06864187094776], + [508714.94050406583, 6651143.152555454, 94.76282222494775], + [508715.36320265953, 6651141.983835646, 95.59005373494777], + [508717.9502335017, 6651137.619649831, 97.19931419576649], + [508716.04439496587, 6651140.100406287, 96.94648874894776], + [508715.44516001304, 6651141.7572316695, 95.85049440794778], + [508715.68456689, 6651143.893533269, 93.0974411947665], + [508716.46615197306, 6651138.934289873, 97.79405458294777], + [508715.53373975185, 6651141.512317451, 96.09146405394776], + [508715.9009315116, 6651140.497068549, 96.77937399194776], + [508715.00025714684, 6651142.987344094, 95.11327843994776], + [508715.62811545137, 6651141.251377975, 96.31088305994776], + [508715.7613655408, 6651140.882954656, 96.56709618294778], + [508715.92558839906, 6651143.22611784, 93.6765782007665], + [508715.06964478944, 6651142.795494125, 95.45302346694776], + [508716.3055758666, 6651139.378266925, 97.75127934194776], + [508715.706829731, 6651143.83188498, 93.57471214676649], + [508715.1483166988, 6651142.577974075, 95.77869057694775], + [508715.96707861166, 6651143.111226816, 94.10288855176648], + [508716.142013254, 6651139.830501375, 97.66211468994776], + [508715.23574342794, 6651142.336247816, 96.08705938494776], + [508716.01870687737, 6651140.1714313105, 97.56301919594776], + [508715.33122648863, 6651142.072246595, 96.37515773594775], + [508715.89600864815, 6651140.5106797805, 97.43539643694777], + [508716.0238403766, 6651142.95404716, 94.52469741076649], + [508715.4339163965, 6651141.7883191565, 96.64035546094777], + [508715.7750293585, 6651140.845175552, 97.27890514494776], + [508715.54283770523, 6651141.48716251, 96.88044390794778], + [508715.65691949695, 6651141.171737637, 97.09369624294777], + [508715.7453844069, 6651143.725122785, 94.05761316676649], + [508717.3681897767, 6651139.2313937945, 97.19931419576649], + [508716.09594210674, 6651142.754389431, 94.93504695376649], + [508715.78548188077, 6651143.614088409, 94.41931915176649], + [508717.22669553617, 6651139.623207121, 97.16157133676649], + [508716.18296679156, 6651142.513408378, 95.3268266477665], + [508717.0825696871, 6651140.022307666, 97.0828966437665], + [508715.83536399674, 6651143.475959268, 94.77707699776649], + [508716.2574940821, 6651142.307034001, 95.6043085077665], + [508716.9377702189, 6651140.423273537, 96.9607435217665], + [508716.33934120706, 6651142.080390187, 95.86474918076651], + [508717.35895998415, 6651139.256952119, 97.80830935576651], + [508716.42780181055, 6651141.835432913, 96.10571882676649], + [508716.79449971585, 6651140.820005531, 96.79362876476651], + [508715.89503671293, 6651143.310718865, 95.1275332127665], + [508716.5220505795, 6651141.574447565, 96.3251378327665], + [508716.65512145427, 6651141.2059594765, 96.5813509557665], + [508715.9643310326, 6651143.11883517, 95.46727823976649], + [508717.1985998445, 6651139.701007224, 97.7655341147665], + [508716.0428971322, 6651142.901276879, 95.7929453497665], + [508717.0352572153, 6651140.153321175, 97.67636946276649], + [508716.13020627684, 6651142.659508124, 96.10131415776651], + [508716.9121166796, 6651140.494311047, 97.57727396876649], + [508716.2255609175, 6651142.395460493, 96.38941250876648], + [508716.7895834734, 6651140.833619155, 97.44965120976649], + [508716.3281127127, 6651142.11148314, 96.65461023376649], + [508716.6687668947, 6651141.168173731, 97.29315991776649], + [508716.4368875277, 6651141.8102735495, 96.8946986807665], + [508716.550815885, 6651141.494793227, 97.10795101576649], + [508729.8143226638, 6651134.722724985, 90.95204076656832], + [508729.8786742204, 6651134.745582613, 90.9530132307946], + [508729.61027196544, 6651135.2971611945, 90.95204076656832], + [508729.6746437088, 6651135.320025993, 90.9530132307946], + [508729.61027196544, 6651135.2971611945, 91.08204076656834], + [508729.6746437088, 6651135.320025993, 91.08301323079462], + [508729.8143226638, 6651134.722724985, 92.78084442556833], + [508729.8786742204, 6651134.745582613, 92.78181688979461], + [508729.61027196544, 6651135.2971611945, 92.78084442556833], + [508729.807306732, 6651134.742475984, 93.24643511256832], + [508729.6746437088, 6651135.320025993, 92.78181688979461], + [508729.8716589827, 6651134.765333859, 93.2474075767946], + [508729.6040814375, 6651135.314588548, 93.19165973756832], + [508729.6684537933, 6651135.337453564, 93.1926322017946], + [508729.7853669781, 6651134.804239994, 93.72370606456832], + [508729.84972139925, 6651134.827098639, 93.7246785287946], + [508729.584722831, 6651135.369086202, 93.61278116556832], + [508729.649097102, 6651135.391951898, 93.6137536297946], + [508729.7473718226, 6651134.911202593, 94.20660708456833], + [508729.81173000264, 6651134.934062573, 94.20757954879461], + [508729.55119769374, 6651135.463464968, 94.03887030056832], + [508729.6155752814, 6651135.486331842, 94.0398427647946], + [508729.7078562588, 6651135.022445392, 94.56831306956832], + [508729.77221834817, 6651135.04530676, 94.5692855337946], + [508729.50282136863, 6651135.599652262, 94.46377680456833], + [508729.56720374216, 6651135.622520837, 94.4647492687946], + [508729.6586980516, 6651135.160833814, 94.92607091556832], + [508729.72306500416, 6651135.183696911, 94.9270433797946], + [508729.439304017, 6651135.778464034, 94.88074350656832], + [508729.599891329, 6651135.326384392, 95.27652713056834], + [508729.5036926743, 6651135.801334841, 94.8817159707946], + [508729.66426409944, 6651135.349249553, 95.27749959479462], + [508729.36081311695, 6651135.999428803, 95.28269242356832], + [508729.5316026356, 6651135.518628272, 95.61627215756833], + [508729.42520953936, 6651136.022302366, 95.2836648877946], + [508729.59598216176, 6651135.5414958345, 95.61724462179461], + [508729.45417671767, 6651135.73659494, 95.94193926756832], + [508729.26800730306, 6651136.260692402, 95.66257322556834], + [508729.51856390364, 6651135.759465223, 95.9429117317946], + [508729.33241290686, 6651136.283569227, 95.66354568979462], + [508729.3681346375, 6651135.97881752, 96.25030807556833], + [508729.189681584, 6651136.481192158, 95.92897954056832], + [508729.43253033556, 6651136.001690826, 96.2512805397946], + [508729.2540949366, 6651136.504071737, 95.9299520047946], + [508729.1045922024, 6651136.720732735, 96.17668928056834], + [508729.2741638204, 6651136.243360795, 96.53840642656833], + [508729.1690139728, 6651136.743615302, 96.17766174479462], + [508729.338568815, 6651136.266237404, 96.5393788907946], + [508729.1731002968, 6651136.527871204, 96.80360415156832], + [508728.98197614856, 6651137.065917053, 96.47413175056832], + [508729.2375152897, 6651136.550751365, 96.8045766157946], + [508729.04641004937, 6651137.088803929, 96.4751042147946], + [508729.0659040642, 6651136.829646194, 97.04369259856833], + [508728.8508364501, 6651137.435096831, 96.73034487356833], + [508729.13032966206, 6651136.852530121, 97.0446650627946], + [508728.91528332455, 6651137.457988316, 96.73131733779461], + [508728.95362907957, 6651137.145718706, 97.25694493356833], + [508729.01806578477, 6651137.168606578, 97.25791739779461], + [508728.7134809001, 6651137.821775251, 96.94262268256833], + [508725.52659055294, 6651146.793394702, 90.95204076656832], + [508728.7779413633, 6651137.844671562, 96.9435951467946], + [508725.59136629594, 6651146.816403001, 90.9530132307946], + [508725.52659055294, 6651146.793394702, 91.08204076656834], + [508728.8373898208, 6651137.4729512995, 97.44215383556832], + [508725.59136629594, 6651146.816403001, 91.08301323079462], + [508728.9018380256, 6651137.495843258, 97.4431262997946], + [508728.5722895944, 6651138.219251953, 97.10973743956832], + [508725.32253985456, 6651147.367830913, 90.95204076656832], + [508728.6367640256, 6651138.242153226, 97.1107099037946], + [508725.38733578427, 6651147.390846381, 90.9530132307946], + [508728.7183265793, 6651137.8081338685, 97.59864512756832], + [508728.78278656316, 6651137.831030009, 97.5996175917946], + [508728.4295915124, 6651138.620970477, 97.23189056156832], + [508728.4940800608, 6651138.643876764, 97.2328630257946], + [508728.59757162275, 6651138.148078892, 97.72626788656834], + [508728.6620435529, 6651138.170979277, 97.72724035079462], + [508728.2875572738, 6651139.020820174, 97.31056525456833], + [508728.3520598737, 6651139.043731453, 97.31153771879461], + [508728.47621815046, 6651138.489708837, 97.82536338056833], + [508728.5407020861, 6651138.5126134865, 97.82633584479461], + [508728.14811645274, 6651139.413368974, 97.34830811356832], + [508728.21263284754, 6651139.436285153, 97.3492805777946], + [508728.3152460131, 6651138.942871828, 97.91452803256834], + [508728.3797458737, 6651138.965782133, 97.9155004967946], + [508725.52658977, 6651146.793396905, 92.78084442656832], + [508725.591365513, 6651146.816405204, 92.7818168907946], + [508728.15721308225, 6651139.38776047, 97.95730327356833], + [508735.7087237135, 6651136.805857087, 91.03954345236868], + [508725.52811126376, 6651146.789113652, 92.98466571056832], + [508728.22172857705, 6651139.4106763275, 97.95827573779461], + [508725.5928868563, 6651146.812121895, 92.9856381747946], + [508725.32253985456, 6651147.367830913, 92.78084442556833], + [508725.38733578427, 6651147.390846381, 92.78181688979461], + [508735.5065220615, 6651137.380946767, 91.03954345236868], + [508725.5407448617, 6651146.753547998, 93.40124499856833], + [508727.56234216224, 6651141.062419756, 97.34830811356832], + [508735.5065220615, 6651137.380946767, 91.16954345236869], + [508725.60551920446, 6651146.7765558, 93.40221746279461], + [508727.62691650784, 6651141.085356518, 97.3492805777946], + [508725.32955578633, 6651147.348079913, 93.24643511256832], + [508725.3943510221, 6651147.371095134, 93.2474075767946], + [508725.56707949744, 6651146.679411677, 93.82557211856832], + [508725.6318512348, 6651146.702418552, 93.8265445827946], + [508725.35149554035, 6651147.286315903, 93.72370606456832], + [508725.60796758794, 6651146.56430499, 94.25188246956833], + [508725.41628860554, 6651147.309330354, 93.7246785287946], + [508725.67273528024, 6651146.587310429, 94.25285493379461], + [508725.6639056041, 6651146.406830293, 94.67369132856832], + [508725.3894906958, 6651147.179353304, 94.20660708456833], + [508725.7286677624, 6651146.429833766, 94.6746637927946], + [508726.9887452824, 6651142.677189128, 97.34830811356832], + [508725.45428000204, 6651147.20236642, 94.20757954879461], + [508727.05337637407, 6651142.7001460465, 97.3492805777946], + [508725.73496096575, 6651146.206797785, 95.08404087156832], + [508725.4290062595, 6651147.068110505, 94.56831306956832], + [508726.8493044613, 6651143.069737928, 97.31056525456833], + [508735.7087237135, 6651136.805857087, 92.86834711136868], + [508725.7997160946, 6651146.229798762, 95.0850133357946], + [508725.4937916565, 6651147.091122234, 94.5692855337946], + [508726.9139493479, 6651143.092699747, 97.31153771879461], + [508725.82072271453, 6651145.965364385, 95.47582056556834], + [508726.7072702227, 6651143.469587625, 97.23189056156832], + [508725.4781644668, 6651146.929722083, 94.92607091556832], + [508725.88546935894, 6651145.988362348, 95.47679302979462], + [508725.894168436, 6651145.758602623, 95.75330242556832], + [508726.7719291607, 6651143.492554434, 97.2328630257946], + [508726.5645721407, 6651143.871306149, 97.10973743956832], + [508725.5429450006, 6651146.952732083, 94.9270433797946], + [508725.9748277637, 6651145.531533376, 96.01374309856833], + [508725.9589078144, 6651145.7815980045, 95.7542748897946], + [508735.5065220615, 6651137.380946767, 92.86834711136868], + [508726.97964943614, 6651142.702795427, 97.95730327356833], + [508726.423380835, 6651144.268782851, 96.94262268256833], + [508726.06200459244, 6651145.286116293, 96.25471274456832], + [508726.629245196, 6651143.894277973, 97.1107099037946], + [508725.53697118926, 6651146.764171507, 95.27652713056834], + [508735.70177135797, 6651136.825630555, 93.33393779836867], + [508726.03955916245, 6651145.554525924, 96.0147155627946], + [508726.1548855866, 6651145.024641049, 96.47413175056832], + [508726.28602528496, 6651144.65546127, 96.73034487356833], + [508727.0442814277, 6651142.725752666, 97.95827573779461], + [508726.4880678583, 6651144.291759636, 96.9435951467946], + [508726.1267273669, 6651145.309105776, 96.2556852087946], + [508725.60174590535, 6651146.78717944, 95.27749959479462], + [508726.21959917224, 6651145.047627268, 96.4751042147946], + [508726.35072589695, 6651144.678442883, 96.73131733779461], + [508726.8216165053, 6651143.147684069, 97.91452803256834], + [508725.60525988275, 6651146.571927624, 95.61627215756833], + [508726.886264131, 6651143.170646861, 97.9155004967946], + [508725.67002784304, 6651146.59493316, 95.61724462179461], + [508735.5003876302, 6651137.398393943, 93.27916242336866], + [508725.6826858006, 6651146.353960956, 95.94193926756832], + [508726.6606443679, 6651143.600847059, 97.82536338056833], + [508725.74744610104, 6651146.376963769, 95.9429117317946], + [508726.7253079187, 6651143.623815507, 97.82633584479461], + [508735.6800304155, 6651136.887464826, 93.81120875036866], + [508725.7687278809, 6651146.111738377, 96.25030807556833], + [508726.53929089557, 6651143.942477004, 97.72626788656834], + [508726.41853593895, 6651144.2824220285, 97.59864512756832], + [508725.86269869795, 6651145.847195102, 96.53840642656833], + [508725.8334796691, 6651146.134738167, 96.2512805397946], + [508726.60396645183, 6651143.965449717, 97.72724035079462], + [508726.2994726975, 6651144.6176045975, 97.44215383556832], + [508725.96376222157, 6651145.562684693, 96.80360415156832], + [508726.1832334388, 6651144.94483719, 97.25694493356833], + [508726.07095845405, 6651145.260909703, 97.04369259856833], + [508726.48322344164, 6651144.305398984, 97.5996175917946], + [508725.9274411897, 6651145.87019159, 96.5393788907946], + [508735.4812044456, 6651137.452953594, 93.70028385136867], + [508726.3641719791, 6651144.640585736, 97.4431262997946], + [508726.02849471505, 6651145.585677629, 96.8045766157946], + [508726.2479442199, 6651144.967822416, 97.25791739779461], + [508726.1356803426, 6651145.283898872, 97.0446650627946], + [508735.6423795607, 6651136.994549103, 94.29410977036868], + [508735.4479831031, 6651137.547439722, 94.12637298636866], + [508735.6032220752, 6651137.105918449, 94.65581575536866], + [508735.40004514984, 6651137.683781942, 94.55127949036867], + [508735.55450932495, 6651137.244464301, 95.01357360136866], + [508735.3371033734, 6651137.862797127, 94.96824619236867], + [508735.4962354913, 6651137.4102032045, 95.36402981636869], + [508735.2593237343, 6651138.08401326, 95.37019510936867], + [508735.4285656095, 6651137.60266578, 95.70377484336868], + [508738.8629056248, 6651137.911821096, 91.08506430210429], + [508735.3518413021, 6651137.820880404, 96.02944195336866], + [508735.167358899, 6651138.34557407, 95.75007591136868], + [508738.66169342503, 6651138.487257712, 91.08506430210429], + [508738.66169342503, 6651138.487257712, 91.2150643021043], + [508735.26657890953, 6651138.0633785315, 96.33781076136867], + [508735.0897429443, 6651138.566324663, 96.01648222636868], + [508735.00542461715, 6651138.806137736, 96.26419196636867], + [508735.17345962784, 6651138.328222747, 96.62590911236867], + [508735.0733119117, 6651138.613056809, 96.89110683736867], + [508734.8839196733, 6651139.151714731, 96.56163443636866], + [508738.8629056248, 6651137.911821096, 92.91386796110429], + [508734.96708705934, 6651138.915175093, 97.13119528436867], + [508734.75396832346, 6651139.521314481, 96.81784755936867], + [508738.66169342503, 6651138.487257712, 92.91386796110429], + [508738.85598728986, 6651137.931606493, 93.37945864810429], + [508734.85582947696, 6651139.231607164, 97.34444761936867], + [508738.6555890119, 6651138.504715414, 93.3246832731043], + [508734.6178574484, 6651139.90843278, 97.03012536836867], + [508731.4598457478, 6651148.890258194, 91.03954345236868], + [508738.8343527343, 6651137.993478066, 93.85672960010429], + [508734.74064354354, 6651139.559212013, 97.52965652136866], + [508731.4598457478, 6651148.890258194, 91.16954345236869], + [508734.477945576, 6651140.306361645, 97.19724012536867], + [508738.6364996983, 6651138.559307979, 93.7458047011043], + [508731.2576440958, 6651149.465347872, 91.03954345236868], + [508734.62265921757, 6651139.89477588, 97.68614781336866], + [508738.79688612005, 6651138.1006269455, 94.33963062010429], + [508734.33654058137, 6651140.708537157, 97.31939324736867], + [508738.60344092076, 6651138.653851108, 94.17189383610429], + [508734.5029985063, 6651140.23510762, 97.81377057236868], + [508738.7579202475, 6651138.212063477, 94.7013366051043], + [508734.19579341455, 6651141.108841715, 97.39806794036868], + [508734.38274470274, 6651140.577126197, 97.91286606636868], + [508738.55573754676, 6651138.790275581, 94.5968003401043], + [508734.05761616444, 6651141.501837073, 97.43581079936867], + [508738.70944586786, 6651138.35069291, 95.0590944511043], + [508734.22323124675, 6651141.030804697, 98.00203071836869], + [508731.45984497207, 6651148.8902604, 92.86834711236867], + [508738.49310376926, 6651138.96939876, 95.0137670421043], + [508738.65145719104, 6651138.516531801, 95.4095506661043], + [508734.066630363, 6651141.476199437, 98.04480595936867], + [508731.46135267854, 6651148.885972272, 93.07216839636867], + [508731.2576440958, 6651149.465347872, 92.86834711136868], + [508738.41570473666, 6651139.190748346, 95.41571595910429], + [508738.58411844465, 6651138.7091104835, 95.74929569310429], + [508731.47387179465, 6651148.850366161, 93.48874768436868], + [508733.47714998526, 6651143.152763788, 97.43581079936867], + [508731.2645964514, 6651149.445574404, 93.33393779836867], + [508731.4999677937, 6651148.776145502, 93.91307480436866], + [508738.50776957953, 6651138.92745675, 96.07496280310428], + [508738.3241899215, 6651139.452466948, 95.79559676110429], + [508731.28633739386, 6651149.383740134, 93.81120875036866], + [508731.5404853686, 6651148.660907873, 94.33938515536866], + [508738.42292440933, 6651139.1701011695, 96.3833316111043], + [508738.2469537721, 6651139.673350713, 96.06200307610429], + [508731.5959164912, 6651148.503254035, 94.76119401436867], + [508731.32398824865, 6651149.276655856, 94.29410977036868], + [508732.90875086875, 6651144.769370093, 97.43581079936867], + [508731.66632797045, 6651148.302993974, 95.17154355736866], + [508738.16304804775, 6651139.91330846, 96.3097128161043], + [508731.3631457341, 6651149.165286509, 94.65581575536866], + [508732.77057361865, 6651145.16236545, 97.39806794036868], + [508738.33026079694, 6651139.435105157, 96.67142996210428], + [508731.7513125718, 6651148.061285923, 95.56332325136869], + [508732.6298264518, 6651145.562670009, 97.31939324736867], + [508731.4118584844, 6651149.026740658, 95.01357360136866], + [508731.8240927502, 6651147.854288953, 95.84080511136867], + [508732.4884214571, 6651145.964845522, 97.19724012536867], + [508731.9040211672, 6651147.626961395, 96.10124578436867], + [508732.89973744634, 6651144.795005524, 98.04480595936867], + [508732.3485095847, 6651146.362774386, 97.03012536836867], + [508731.9904080257, 6651147.38126513, 96.34221543036867], + [508738.23060314305, 6651139.720111053, 96.93662768710429], + [508731.47013231803, 6651148.861001753, 95.36402981636869], + [508732.08244736, 6651147.119492435, 96.56163443636866], + [508732.21239870973, 6651146.749892686, 96.81784755936867], + [508738.0421376754, 6651140.259093932, 96.6071552861043], + [508732.7431365626, 6651145.240400261, 98.00203071836869], + [508731.5378021998, 6651148.668539179, 95.70377484336868], + [508732.5836231066, 6651145.694078762, 97.91286606636868], + [508731.6145265072, 6651148.450324556, 96.02944195336866], + [508738.12489809067, 6651140.022411597, 97.1767161341043], + [508732.46336930303, 6651146.03609734, 97.81377057236868], + [508737.91282222874, 6651140.628916651, 96.8633684091043], + [508731.6997888998, 6651148.207826428, 96.33781076136867], + [508732.34370859177, 6651146.37642908, 97.68614781336866], + [508731.7929081815, 6651147.942982213, 96.62590911236867], + [508732.2257242658, 6651146.711992947, 97.52965652136866], + [508731.8930558976, 6651147.65814815, 96.89110683736867], + [508732.1105383324, 6651147.039597794, 97.34444761936867], + [508731.99928075, 6651147.356029864, 97.13119528436867], + [508738.0141849354, 6651140.339034562, 97.38996846910429], + [508737.77737739775, 6651141.016268489, 97.07564621810431], + [508734.6348190917, 6651150.003512391, 91.08506430210429], + [508737.8995626522, 6651140.666837046, 97.5751773711043], + [508734.6348190917, 6651150.003512391, 91.2150643021043], + [508737.6381501692, 6651141.414437412, 97.24276097510429], + [508734.433606892, 6651150.578949004, 91.08506430210429], + [508737.78215567, 6651141.002603349, 97.73166866310429], + [508737.49743712496, 6651141.816855546, 97.36491409710429], + [508737.6630805057, 6651141.343140403, 97.85929142210429], + [508737.3573786894, 6651142.217401598, 97.44358879010429], + [508737.5434151514, 6651141.685365309, 97.95838691610429], + [508737.21987759497, 6651142.610634039, 97.4813316491043], + [508737.3846822575, 6651142.139317501, 98.0475515681043], + [508734.63481831976, 6651150.003514597, 92.91386796210429], + [508737.2288476835, 6651142.584980935, 98.0903268091043], + [508734.63631864847, 6651149.999223883, 93.1176892461043], + [508734.433606892, 6651150.578949004, 92.91386796110429], + [508734.6487765035, 6651149.963596293, 93.53426853410429], + [508736.6422518653, 6651144.262556712, 97.4813316491043], + [508734.440525227, 6651150.559163608, 93.37945864810429], + [508734.6747448047, 6651149.889330859, 93.9585956541043], + [508734.4621597824, 6651150.497292034, 93.85672960010429], + [508734.71506411105, 6651149.77402371, 94.38490600510428], + [508734.7702239873, 6651149.616274762, 94.8067148641043], + [508734.4996263967, 6651150.390143155, 94.33963062010429], + [508736.0766341495, 6651145.8801382715, 97.4813316491043], + [508734.8402909155, 6651149.415893892, 95.21706440710429], + [508735.93913305504, 6651146.273370711, 97.44358879010429], + [508734.53859226924, 6651150.278706622, 94.7013366051043], + [508734.92485965387, 6651149.174040023, 95.6088441011043], + [508735.7990746194, 6651146.673916763, 97.36491409710429], + [508734.5870666489, 6651150.1400771905, 95.0590944511043], + [508734.9972836901, 6651148.966918178, 95.88632596110429], + [508735.65836157516, 6651147.076334898, 97.24276097510429], + [508736.0676648333, 6651145.905789166, 98.0903268091043], + [508735.0768209858, 6651148.73945348, 96.1467666341043], + [508735.5191343467, 6651147.474503822, 97.07564621810431], + [508735.1627851194, 6651148.4936089935, 96.3877362801043], + [508734.64505532564, 6651149.974238301, 95.4095506661043], + [508735.25437406905, 6651148.231678378, 96.6071552861043], + [508735.3836895157, 6651147.861855659, 96.8633684091043], + [508735.91183025925, 6651146.351452599, 98.0475515681043], + [508734.7123940721, 6651149.781659619, 95.74929569310429], + [508735.7530973654, 6651146.805404792, 97.95838691610429], + [508734.7887429372, 6651149.563313353, 96.07496280310428], + [508735.6334320112, 6651147.1476297, 97.85929142210429], + [508734.8735881074, 6651149.320668933, 96.3833316111043], + [508735.51435684675, 6651147.488166753, 97.73166866310429], + [508734.9662517198, 6651149.055664944, 96.67142996210428], + [508735.3969498646, 6651147.823933057, 97.5751773711043], + [508735.0659093737, 6651148.770659049, 96.93662768710429], + [508735.2823275813, 6651148.151735539, 97.38996846910429], + [508735.1716144261, 6651148.468358504, 97.1767161341043], + [508752.12251381646, 6651142.494644271, 91.26653404189648], + [508751.9254610946, 6651143.071518497, 91.26653404189648], + [508751.9254610946, 6651143.071518497, 91.39653404189649], + [508752.12251381646, 6651142.494644271, 93.09533770089648], + [508751.9254610946, 6651143.071518497, 93.09533770089648], + [508752.11573849805, 6651142.514479098, 93.56092838789648], + [508751.91948287253, 6651143.0890198145, 93.50615301289649], + [508752.0945511742, 6651142.576505245, 94.03819933989648], + [508751.90078817494, 6651143.143748769, 93.9272744408965], + [508752.0578590733, 6651142.683921814, 94.52110035989648], + [508751.86841279175, 6651143.238528093, 94.35336357589648], + [508752.01969870704, 6651142.795636747, 94.8828063448965], + [508751.8216955464, 6651143.375293394, 94.77827007989649], + [508751.9722263944, 6651142.934612516, 95.24056419089648], + [508751.7603565403, 6651143.554864077, 95.1952367818965], + [508751.9154364651, 6651143.100865722, 95.59102040589649], + [508751.8494897516, 6651143.293925522, 95.93076543289648], + [508751.6845575079, 6651143.77676666, 95.59718569889648], + [508751.77471917757, 6651143.512817281, 96.25643254289649], + [508751.59493449575, 6651144.039139111, 95.97706650089648], + [508751.69162793487, 6651143.7560679, 96.5648013508965], + [508751.5192949794, 6651144.26057471, 96.24347281589648], + [508751.43712376215, 6651144.501131942, 96.49118255589649], + [508751.6008798735, 6651144.021733946, 96.85289970189648], + [508751.5032823521, 6651144.307451869, 97.11809742689648], + [508756.28394181497, 6651143.909274647, 91.3199669126467], + [508751.31871286064, 6651144.8477812875, 96.7886250258965], + [508756.088194514, 6651144.4865926355, 91.31996691264918], + [508751.3997624447, 6651144.61050765, 97.35818587389649], + [508756.088194514, 6651144.4865926355, 91.44996691264919], + [508751.19207063527, 6651145.218527934, 97.04483814889649], + [508751.2913379624, 6651144.927921632, 97.57143820889648], + [508751.05942573276, 6651145.606847488, 97.2571159578965], + [508751.1790851619, 6651145.256543064, 97.75664711089648], + [508747.9818306922, 6651154.616544179, 91.26653404189648], + [508747.9818306922, 6651154.616544179, 91.39653404189649], + [508750.92307662277, 6651146.006011156, 97.4242307148965], + [508751.06410522806, 6651145.59314821, 97.91313840289648], + [508747.7847779702, 6651155.193418403, 91.26653404189648], + [508756.28394181497, 6651143.909274647, 93.14877057164671], + [508750.78527241194, 6651146.409434651, 97.5463838368965], + [508750.9474915969, 6651145.934536026, 98.04076116189648], + [508756.088194514, 6651144.4865926355, 93.14877057164918], + [508750.64810927777, 6651146.810981384, 97.62505852989648], + [508756.2772113811, 6651143.929124732, 93.61436125864583], + [508750.8302999763, 6651146.277615911, 98.13985665589648], + [508750.51345061907, 6651147.205196234, 97.66280138889648], + [508756.0822558954, 6651144.504107417, 93.55958588364068], + [508750.67484842386, 6651146.73270221, 98.22902130789649], + [508756.25616441696, 6651143.991198594, 94.09163221063858], + [508756.06368504517, 6651144.55887847, 93.98070731164123], + [508750.5222352771, 6651147.179479042, 98.2717965488965], + [508747.98182993603, 6651154.616546391, 93.09533770189648], + [508747.98329924984, 6651154.612244957, 93.29915898589648], + [508756.21971539175, 6651144.098697793, 94.5745332306442], + [508747.7847779702, 6651155.193418403, 93.09533770089648], + [508756.0315241402, 6651144.653730705, 94.40679644664426], + [508749.9477656237, 6651148.861245898, 97.66280138889648], + [508747.995499575, 6651154.576528358, 93.71573827389648], + [508756.1818078276, 6651144.210498664, 94.93623921564632], + [508747.7915532887, 6651155.173583576, 93.56092838789648], + [508748.02093105693, 6651154.502077387, 94.14006539389649], + [508755.9851163838, 6651144.790601213, 94.83170295064227], + [508756.13465000596, 6651144.34958134, 95.29399706164321], + [508747.8127406126, 6651155.11155743, 94.03819933989648], + [508748.0604168787, 6651154.386482167, 94.56637574489648], + [508755.92418373236, 6651144.9703100305, 95.24866965264734], + [508756.0782362944, 6651144.515962435, 95.64445327664261], + [508748.11443648476, 6651154.228339116, 94.98818460389649], + [508749.3938404113, 6651150.482868655, 97.66280138889648], + [508747.8494327134, 6651155.004140861, 94.52110035989648], + [508748.1830549827, 6651154.027457634, 95.39853414689648], + [508749.2591817526, 6651150.877083505, 97.62505852989648], + [508747.88759307977, 6651154.892425927, 94.8828063448965], + [508756.0127264599, 6651144.709170749, 95.98419830364112], + [508755.8488868478, 6651145.192383314, 95.65061856964533], + [508748.265875508, 6651153.784999545, 95.79031384089649], + [508749.1220186184, 6651151.27863024, 97.5463838368965], + [508747.93506539235, 6651154.753450158, 95.24056419089648], + [508748.3368023877, 6651153.577360247, 96.06779570089648], + [508748.98421440757, 6651151.682053732, 97.4242307148965], + [508749.38505650964, 6651150.508583633, 98.2717965488965], + [508748.41469548084, 6651153.349327276, 96.32823637389649], + [508748.84786529763, 6651152.0812174, 97.2571159578965], + [508748.4988825557, 6651153.102868596, 96.56920601989648], + [508748.7152203951, 6651152.4695369555, 97.04483814889649], + [508748.58857816976, 6651152.840283602, 96.7886250258965], + [508747.99185532174, 6651154.587196954, 95.59102040589649], + [508755.9384512209, 6651144.928230892, 96.30986541364487], + [508749.23244336294, 6651150.955360464, 98.22902130789649], + [508755.7598575632, 6651145.454957597, 96.03049937163823], + [508748.05780203507, 6651154.3941371525, 95.93076543289648], + [508749.0769918105, 6651151.410446763, 98.13985665589648], + [508748.1325726092, 6651154.175245394, 96.25643254289649], + [508748.9598001899, 6651151.753526649, 98.04076116189648], + [508748.21566385194, 6651153.931994775, 96.5648013508965], + [508755.85591043497, 6651145.171668631, 96.61823422164382], + [508748.84318655875, 6651152.094914465, 97.91313840289648], + [508755.6847191385, 6651145.676563536, 96.29690568664412], + [508748.30641191325, 6651153.666328729, 96.85289970189648], + [508748.7282066249, 6651152.431519611, 97.75664711089648], + [508748.4040094346, 6651153.380610805, 97.11809742689648], + [508748.61595382437, 6651152.760141041, 97.57143820889648], + [508748.5075293421, 6651153.077555024, 97.35818587389649], + [508755.6030922834, 6651145.917305817, 96.54461542664565], + [508755.7657635549, 6651145.437539043, 96.90633257264452], + [508755.6688125905, 6651145.723476756, 97.17153029764322], + [508755.4854658217, 6651146.264221824, 96.84205789664404], + [508755.56597847457, 6651146.026765663, 97.41161874464638], + [508755.3596625666, 6651146.635253669, 97.09827101964285], + [508755.45827227476, 6651146.344423818, 97.62487107964382], + [508755.22789640026, 6651147.023871941, 97.31054882863958], + [508755.34676311864, 6651146.673298042, 97.81007998164468], + [508752.170689591, 6651156.040499378, 91.3199669126459], + [508755.0924505664, 6651147.4233426675, 97.4776635856434], + [508752.170689591, 6651156.040499378, 91.4499669126459], + [508755.2325448955, 6651147.0101621235, 97.96657127364296], + [508751.97494228964, 6651156.6178173665, 91.31996691264403], + [508754.9555592707, 6651147.827076497, 97.59981670763861], + [508755.11670379795, 6651147.351812553, 98.09419403264249], + [508754.81930480513, 6651148.228932121, 97.67849140064006], + [508755.00028854015, 6651147.695156354, 98.19328952664557], + [508754.6855382233, 6651148.623450224, 97.71623425963736], + [508754.845866812, 6651148.15059273, 98.28245417864466], + [508754.69426468585, 6651148.597713247, 98.32522941964449], + [508752.17068883986, 6651156.040501593, 93.14877057264447], + [508752.1721484198, 6651156.03619685, 93.3525918566441], + [508751.97494228964, 6651156.6178173665, 93.14877057164405], + [508754.12360073806, 6651150.28077381, 97.71623425964779], + [508752.18426792085, 6651156.000452776, 93.76917114464099], + [508751.98167272296, 6651156.597967282, 93.6143612586376], + [508752.20953092584, 6651155.925944533, 94.19349826463878], + [508752.002719687, 6651156.535893422, 94.09163221064352], + [508752.24875516497, 6651155.810260391, 94.61980861563926], + [508752.30241690605, 6651155.651995689, 95.04161747464255], + [508753.57334512926, 6651151.903644007, 97.7162342596433], + [508752.0391687129, 6651156.428394222, 94.57453323064652], + [508752.3705808253, 6651155.450959677, 95.45196701764566], + [508753.4395785479, 6651152.298162109, 97.67849140064625], + [508752.0770762764, 6651156.316593351, 94.93623921563581], + [508753.303324082, 6651152.700017734, 97.59981670764505], + [508752.4528526866, 6651155.208315077, 95.84374671163808], + [508752.1242340985, 6651156.177510674, 95.2939970616445], + [508752.5233096953, 6651155.000516051, 96.12122857164316], + [508753.1664327865, 6651153.1037515635, 97.47766358564292], + [508753.5646194184, 6651151.929378766, 98.32522941964064], + [508752.60068676784, 6651154.772307663, 96.38166924464245], + [508753.0309869522, 6651153.5032222895, 97.3105488286411], + [508752.68431612616, 6651154.525659394, 96.62263889064258], + [508752.8992207858, 6651153.891840562, 97.09827101963653], + [508752.77341753116, 6651154.262872405, 96.84205789664227], + [508752.1806478098, 6651156.011129578, 95.64445327664251], + [508753.41301729245, 6651152.376499283, 98.2824541786431], + [508752.2461576441, 6651155.817921266, 95.98419830364098], + [508753.2585955643, 6651152.831935659, 98.19328952664218], + [508752.32043288345, 6651155.5988611225, 96.30986541364155], + [508753.14218030643, 6651153.175279461, 98.09419403264394], + [508752.4029736697, 6651155.355423383, 96.61823422164692], + [508753.02633920853, 6651153.516929891, 97.96657127363913], + [508752.4931205494, 6651155.0895529725, 96.90633257264192], + [508752.9121209858, 6651153.853793971, 97.81007998164307], + [508752.59007151355, 6651154.803615258, 97.17153029763888], + [508752.8006118293, 6651154.182668196, 97.6248710796396], + [508752.6929056298, 6651154.500326351, 97.41161874464137], + [508780.9085904975, 6651166.179011417, 93.47719238164655], + [508781.40424123115, 6651165.697638644, 93.48023315383543], + [508781.40793966077, 6651165.694046753, 93.6840766446469], + [508780.92559867207, 6651166.162493188, 93.9428937328404], + [508781.438649262, 6651165.664221789, 94.10084032902482], + [508780.9787855011, 6651166.110838485, 94.42051076182501], + [508781.03831829043, 6651166.053020627, 94.73301253991784], + [508791.8097574663, 6651155.591868871, 94.00871362346382], + [508782.1192161192, 6651165.003259677, 96.17950419952633], + [508781.59547161206, 6651165.511916941, 96.31680924172528], + [508791.75642657146, 6651155.643663489, 94.48566013922657], + [508782.2977471118, 6651164.829871537, 96.45805911072323], + [508781.7836776189, 6651165.329132489, 96.64360681646063], + [508782.4938128534, 6651164.639453763, 96.71967850416095], + [508791.6640683957, 6651155.733361149, 94.9679993539432], + [508781.9928276921, 6651165.126007297, 96.95323220408682], + [508782.8186082703, 6651164.324014563, 97.0723109665908], + [508791.5680144301, 6651155.826648137, 95.32912112216707], + [508782.9314952818, 6651164.214379431, 97.18269949183302], + [508791.44852124096, 6651155.942699146, 95.68615228904439], + [508783.2502681133, 6651163.904789329, 97.44083070961177], + [508783.5841503607, 6651163.580525057, 97.6551183535247], + [508790.4988347842, 6651156.865028464, 96.41688313154079], + [508783.9273565201, 6651163.247205466, 97.82429995188103], + [508790.30844155047, 6651157.049937135, 96.6821332156547], + [508790.95137319824, 6651156.425526096, 96.6989984914695], + [508790.1016072871, 6651157.250813229, 96.92858719596532], + [508790.74222312565, 6651156.628651287, 97.00609644935226], + [508789.48478080117, 6651157.8498711055, 97.47849977789618], + [508790.51379997365, 6651156.85049437, 97.29280722579055], + [508789.15089855244, 6651158.174135376, 97.68875274712765], + [508788.80769239395, 6651158.507454967, 97.8537870088007], + [508787.77661733126, 6651159.508828371, 98.08611278570439], + [508788.46082358254, 6651158.844331705, 97.97383834843298], + [508788.11556843144, 6651159.179641264, 98.05042195029993], + [508789.1626773728, 6651158.162695862, 98.34484661064175], + [508788.86914764997, 6651158.447770022, 98.47068992764929], + [508788.5741630632, 6651158.734257137, 98.56799782418399], + [508806.02157038066, 6651160.022071429, 91.84040728419325], + [508805.84142554365, 6651160.604443926, 91.84040728419237], + [508805.84142554365, 6651160.604443926, 91.97040728419239], + [508806.02157038066, 6651160.022071429, 93.66921094319325], + [508805.84142554365, 6651160.604443926, 93.66921094319237], + [508806.01537641056, 6651160.042095303, 94.13480163019182], + [508805.83596027637, 6651160.622112051, 94.08002625519457], + [508805.99600704084, 6651160.10471263, 94.61207258219072], + [508805.8188696562, 6651160.677362634, 94.50114768319555], + [508805.9624632644, 6651160.213153002, 95.09497360219407], + [508805.7892722053, 6651160.773045316, 94.92723681818944], + [508805.9275772049, 6651160.325932708, 95.45667958719376], + [508805.7465634801, 6651160.911114147, 95.35214332219047], + [508805.8841782, 6651160.466233075, 95.81443743319278], + [508805.69048759807, 6651161.092396343, 95.76911002419283], + [508805.8322610662, 6651160.634070863, 96.1648936481941], + [508805.7719728354, 6651160.828970745, 96.50463867519221], + [508805.6211924154, 6651161.316413912, 96.17105894119219], + [508805.7036178657, 6651161.049948793, 96.83030578519424], + [508805.53925940424, 6651161.581287075, 96.55093974319398], + [508805.6276561724, 6651161.295517869, 97.13867459319158], + [508805.47011005046, 6651161.804833207, 96.81734605819234], + [508805.3949894412, 6651162.047683226, 97.065055798192], + [508805.54469464545, 6651161.563716018, 97.42677294419249], + [508805.45547136874, 6651161.852157161, 97.69197066919432], + [508805.2867386526, 6651162.397636537, 97.36249826819326], + [508805.3608338692, 6651162.158101411, 97.93205911619278], + [508805.17096281936, 6651162.771916824, 97.61871139119184], + [508805.26171262615, 6651162.478540713, 98.14531145119072], + [508805.04969936213, 6651163.163937511, 97.83098920019165], + [508805.1590915499, 6651162.810294283, 98.33052035319271], + [508804.9250495327, 6651163.566905666, 97.99810395719315], + [508805.0539773385, 6651163.150107663, 98.48701164519102], + [508802.2361738679, 6651172.259506941, 91.84040728419299], + [508802.2361738679, 6651172.259506941, 91.97040728419302], + [508804.79906945553, 6651163.974174247, 98.12025707919231], + [508804.94736960786, 6651163.494749295, 98.61463440419426], + [508802.0560290307, 6651172.841879439, 91.84040728419106], + [508804.6736754481, 6651164.379548183, 98.1989317721914], + [508804.8402334811, 6651163.841099124, 98.71372989819434], + [508804.5505710229, 6651164.777520353, 98.23667463119219], + [508804.6981202724, 6651164.300522918, 98.80289455019278], + [508804.5586019235, 6651164.751558046, 98.84566979119329], + [508802.23617317685, 6651172.259509175, 93.66921094419426], + [508802.2375164178, 6651172.255166743, 93.87303222819412], + [508804.0334239857, 6651166.449354069, 98.23667463119065], + [508802.0560290307, 6651172.841879439, 93.66921094319106], + [508802.2486699077, 6651172.219109724, 94.2896115161922], + [508802.0622230007, 6651172.821855564, 94.13480163019142], + [508802.2719192703, 6651172.14394915, 94.71393863619335], + [508802.3080170559, 6651172.027252174, 95.1402489871918], + [508802.08159237064, 6651172.7592382375, 94.61207258219358], + [508803.52702769707, 6651168.0864327485, 98.23667463119213], + [508802.35740157095, 6651171.867601841, 95.56205784619114], + [508802.1151361473, 6651172.650797865, 95.09497360219257], + [508803.4039232714, 6651168.484404921, 98.19893177219056], + [508802.42013233656, 6651171.664805727, 95.97240738919054], + [508803.27852926427, 6651168.889778854, 98.120257079192], + [508802.15002220694, 6651172.53801816, 95.45667958719415], + [508802.4958465408, 6651171.420036733, 96.3641870831913], + [508803.51899748814, 6651168.11239282, 98.84566979119231], + [508803.1525491875, 6651169.297047436, 97.99810395719369], + [508802.56068762037, 6651171.210418396, 96.64166894319322], + [508802.1934212113, 6651172.397717793, 95.81443743319153], + [508803.027899358, 6651169.700015591, 97.83098920019393], + [508802.631897185, 6651170.980212009, 96.9021096161917], + [508802.70886068366, 6651170.731404295, 97.14307926219281], + [508802.9066359006, 6651170.092036279, 97.6187113911925], + [508802.79086006735, 6651170.466316564, 97.3624982681923], + [508803.3794791392, 6651168.563427947, 98.8028945501939], + [508802.2453383455, 6651172.229880003, 96.16489364819259], + [508803.3084225346, 6651168.793139845, 98.75831222403362], + [508803.2373659306, 6651169.022851741, 98.7137298981923], + [508802.30562657584, 6651172.034980122, 96.50463867519082], + [508803.13022980397, 6651169.369201573, 98.61463440419368], + [508802.37398154614, 6651171.814002072, 96.83030578519366], + [508803.0236220729, 6651169.713843205, 98.48701164519329], + [508802.4499432392, 6651171.568432997, 97.138674593194], + [508802.9185078617, 6651170.053656584, 98.33052035319393], + [508802.53290476615, 6651171.300234849, 97.42677294419308], + [508802.8158867849, 6651170.385410154, 98.14531145119105], + [508802.62212804286, 6651171.011793706, 97.69197066919236], + [508802.71676554205, 6651170.705849456, 97.93205911619029], + [508822.1918849311, 6651164.9449669225, 91.9627256389017], + [508822.372404784, 6651165.634787478, 91.96506541656744], + [508822.372404784, 6651165.634787478, 92.09506541656745], + [508822.1918849311, 6651164.9449669225, 93.7915292979017], + [508822.1980917954, 6651164.968685214, 94.25720045849617], + [508822.372404784, 6651165.634787478, 93.79386907556744], + [508822.2175014869, 6651165.042855473, 94.73472305094654], + [508822.37788142887, 6651165.655715382, 94.20475534924105], + [508822.25111509353, 6651165.171303156, 95.21805982046632], + [508822.39500762743, 6651165.721159728, 94.62609867514391], + [508822.2860737768, 6651165.30489078, 95.5802189378769], + [508822.4246666921, 6651165.834495918, 95.0525720605858], + [508822.32956312713, 6651165.471076645, 95.93854041346947], + [508822.38158834004, 6651165.669880602, 96.2896707724538], + [508822.52365694434, 6651166.212767391, 95.89572745636704], + [508822.4420020749, 6651165.900739621, 96.63019848922737], + [508822.59309638164, 6651166.47811633, 96.29857553761954], + [508822.51049934304, 6651166.162488246, 96.95675281647692], + [508822.6751999569, 6651166.791858739, 96.67951921077417], + [508822.5866191689, 6651166.453364954, 97.26610732601614], + [508822.7444932617, 6651167.056649261, 96.94682232590775], + [508822.6697534008, 6651166.771045813, 97.55528191281114], + [508822.81977025385, 6651167.344305247, 97.19550606296447], + [508822.75916241796, 6651167.112704511, 97.82163675876285], + [508822.9282463929, 6651167.758825142, 97.49435164092193], + [508822.8539969291, 6651167.475095649, 98.06295215031385], + [508823.04426324216, 6651168.202160354, 97.75206482426465], + [508822.9533245171, 6651167.854656183, 98.27748912713014], + [508823.0561592244, 6651168.247618474, 98.46402756333227], + [508823.16577913926, 6651168.666509079, 97.96591314708884], + [508823.1614922571, 6651168.650127616, 98.62188019819675], + [508823.2906884579, 6651169.143825087, 98.13464158568678], + [508823.2683219183, 6651169.058355824, 98.75088313467333], + [508823.41693079384, 6651169.626234953, 98.25842490002799], + [508823.37568107556, 6651169.468607395, 98.85136513173755], + [508823.5425858402, 6651170.106400609, 98.33872149297953], + [508823.51809012797, 6651170.012795139, 98.94236814657671], + [508823.6659465378, 6651170.577798871, 98.37805595023299], + [508823.6578989189, 6651170.547046503, 98.9869473007037], + [508824.18417014414, 6651172.558086854, 98.38473463639099], + [508824.6916206219, 6651174.49720748, 98.3912628763363], + [508824.6996675483, 6651174.5279572, 99.000361465957], + [508824.81498131994, 6651174.968605742, 98.35510529410794], + [508825.9851616828, 6651179.440216226, 92.01158491380276], + [508825.9851616828, 6651179.440216226, 92.14158491380277], + [508824.94063636544, 6651175.448771397, 98.27804466653393], + [508824.83947633876, 6651175.062208563, 98.95938277082355], + [508825.06687870115, 6651175.931181262, 98.15751244752472], + [508826.16568153584, 6651180.130036781, 92.01389415230373], + [508824.9818853913, 6651175.606396307, 98.87204718498923], + [508825.1917880205, 6651176.408497271, 97.99200078177701], + [508825.08924454823, 6651176.016647878, 98.77432998960177], + [508825.98516237503, 6651179.440218871, 93.84038858266251], + [508825.3133039177, 6651176.872845997, 97.7812818484891], + [508825.983816338, 6651179.43507526, 94.04419264253698], + [508825.1960742097, 6651176.424876087, 98.6480782236168], + [508825.42932076653, 6651177.316181207, 97.52655644535326], + [508825.9726396292, 6651179.3923657, 94.46062890832961], + [508825.3014072421, 6651176.827385227, 98.49293822201905], + [508825.51149085234, 6651177.6301777745, 97.30819077092062], + [508825.9493418676, 6651179.303337958, 94.8846578819189], + [508825.5886145694, 6651177.924890652, 97.06820949544128], + [508826.16568153584, 6651180.130036781, 93.84269781130374], + [508825.91316893493, 6651179.165110323, 95.31050527267823], + [508825.6599723748, 6651178.197570249, 96.8086830660119], + [508825.40424195013, 6651177.22034752, 98.30904808548469], + [508825.8636816144, 6651178.976004412, 95.73168067320069], + [508825.72494843695, 6651178.44586329, 96.5320334900092], + [508825.80082025914, 6651178.735792302, 96.14122540835535], + [508826.1594746717, 6651180.106318489, 94.30820912300204], + [508825.503569538, 6651177.599908054, 98.09706909526902], + [508825.5984040485, 6651177.962299191, 97.85819598559807], + [508826.1400649798, 6651180.032148229, 94.78523184687617], + [508825.68781306606, 6651178.303957889, 97.59414370370696], + [508826.106451373, 6651179.903700546, 95.26770294731547], + [508825.770947298, 6651178.621638748, 97.30711009047509], + [508826.07149269, 6651179.770112922, 95.62896175624135], + [508825.8470671244, 6651178.912515458, 96.99971591547958], + [508826.02800333954, 6651179.603927057, 95.98616323029663], + [508825.91556439176, 6651179.174264081, 96.67492562078117], + [508862.9688786647, 6651176.682449538, 92.17073826452479], + [508862.8065979349, 6651177.270048321, 92.17073826452386], + [508862.8065979349, 6651177.270048321, 92.30073826452386], + [508862.9688786647, 6651176.682449538, 93.99954192352479], + [508862.8065979349, 6651177.270048321, 93.99954192352385], + [508862.96329892095, 6651176.702653111, 94.46513261052354], + [508862.8016746321, 6651177.287875001, 94.41035723552457], + [508862.94585031964, 6651176.765832375, 94.94240356252364], + [508862.7862788074, 6651177.34362141, 94.83147866352425], + [508862.91563292, 6651176.875245904, 95.42530458252438], + [508862.7596163956, 6651177.440162759, 95.25756779852415], + [508862.88420634513, 6651176.989037707, 95.78701056752352], + [508862.7211428919, 6651177.579470636, 95.68247430252461], + [508862.8451110138, 6651177.130597148, 96.14476841352497], + [508862.6706277882, 6651177.762379683, 96.0994410045242], + [508862.79834225506, 6651177.299941134, 96.49522462852435], + [508862.74403252196, 6651177.496590071, 96.83496965552457], + [508862.60820427974, 6651177.988407616, 96.5013899215247], + [508862.6824559892, 6651177.719551206, 97.1606367655234], + [508862.5343961757, 6651178.255657782, 96.88127072352452], + [508862.61402705655, 6651177.967324047, 97.46900557352438], + [508862.4721040347, 6651178.481210046, 97.14767703852353], + [508862.5392924299, 6651178.237929041, 97.75710392452419], + [508862.40443277935, 6651178.726239431, 97.39538677852407], + [508862.4589170015, 6651178.52895869, 98.02230164952486], + [508862.3069167071, 6651179.079333268, 97.69282924852448], + [508862.373664253, 6651178.837648522, 98.26239009652396], + [508862.20262181305, 6651179.456972391, 97.94904237152416], + [508862.2843723933, 6651179.160963486, 98.47564243152547], + [508862.0933834768, 6651179.852511121, 98.16132018052465], + [508862.19192776096, 6651179.495694254, 98.6608513335243], + [508868.35062941536, 6651178.17747696, 92.19016613550315], + [508861.9810945786, 6651180.259095563, 98.32843493752496], + [508862.0972372265, 6651179.83855716, 98.81734262552403], + [508868.1900369162, 6651178.7655447265, 92.19016613550315], + [508868.1900369162, 6651178.7655447265, 92.32016613550316], + [508861.86760734697, 6651180.670019024, 98.45058805952459], + [508862.0012012777, 6651180.186291651, 98.94496538452462], + [508859.55886193557, 6651189.029705328, 92.17073826452425], + [508859.55886193557, 6651189.029705328, 92.30073826452426], + [508861.7546480673, 6651181.079030836, 98.52926275252398], + [508861.90468933166, 6651180.535749668, 99.04406087852502], + [508859.3965812058, 6651189.617304111, 92.17073826452334], + [508861.6437513231, 6651181.480574457, 98.56700561152488], + [508861.77666881424, 6651180.999296389, 99.1332255305231], + [508868.35062941536, 6651178.17747696, 94.01896979450315], + [508861.6509858372, 6651181.454379161, 99.17600077152467], + [508868.1900369162, 6651178.7655447265, 94.01896979450315], + [508868.3451077189, 6651178.197696658, 94.48456048150315], + [508861.1778873002, 6651183.167411417, 98.56700561152469], + [508859.5588613128, 6651189.029707583, 93.99954192452388], + [508868.1851648311, 6651178.783385635, 94.42978510650315], + [508868.3278406379, 6651178.260926347, 94.96183143350316], + [508859.560071351, 6651189.025326181, 94.20336320852385], + [508859.3965812058, 6651189.617304111, 93.99954192352334], + [508868.1699291714, 6651178.839176537, 94.85090653450317], + [508859.5701188026, 6651188.988945583, 94.61994249652426], + [508868.29793759406, 6651178.370427203, 95.44473245350315], + [508859.4021609492, 6651189.597100538, 94.4651326105235], + [508859.5910626361, 6651188.913110508, 95.0442696165235], + [508868.14354413265, 6651178.935794939, 95.27699566950315], + [508868.26683795475, 6651178.484309829, 95.80643843850316], + [508860.72170792485, 6651184.819181446, 98.56700561152454], + [508859.62358077615, 6651188.795366278, 95.47057996752416], + [508859.41960955085, 6651189.533921274, 94.9424035625245], + [508868.10547087435, 6651179.075214003, 95.70190217350317], + [508860.61081118044, 6651185.220725069, 98.52926275252486], + [508859.6680680638, 6651188.634283222, 95.89238882652492], + [508871.0054461452, 6651178.900448406, 92.19759506947767], + [508868.2281493375, 6651178.625982252, 96.16419628450316], + [508859.44982695085, 6651189.424507746, 95.42530458252482], + [508860.49785190076, 6651185.62973688, 98.45058805952424], + [508859.7245781173, 6651188.429667191, 96.30273836952409], + [508860.7144740336, 6651184.845374487, 99.17600077152454], + [508860.38436466956, 6651186.04066034, 98.32843493752495], + [508859.48125352524, 6651189.310715942, 95.78701056752408], + [508859.7927841038, 6651188.182701611, 96.69451806352455], + [508868.05548128684, 6651179.258269035, 96.11886887550315], + [508870.8456864497, 6651179.488742964, 92.19759506947767], + [508868.18186712125, 6651178.795461397, 96.51465249950316], + [508860.272075771, 6651186.447244784, 98.16132018052417], + [508859.8511952015, 6651187.971202131, 96.9719999235248], + [508870.8456864497, 6651179.488742964, 92.3275950694777], + [508860.5887910561, 6651185.300457261, 99.1332255305245], + [508859.915343252, 6651187.738929843, 97.23244059652424], + [508860.1628374343, 6651186.842783513, 97.94904237152357], + [508859.52034885704, 6651189.169156501, 96.14476841352425], + [508859.98467464594, 6651187.487889298, 97.47341024252378], + [508860.05854254065, 6651187.220422637, 97.69282924852436], + [508859.5671176157, 6651188.9998125145, 96.49522462852485], + [508860.4607705393, 6651185.76400398, 99.0440608785247], + [508868.1281223802, 6651178.992267287, 96.85439752650315], + [508867.9937071792, 6651179.484477368, 96.52081779250315], + [508859.62142734893, 6651188.803163578, 96.83496965552462], + [508860.36425859306, 6651186.113461998, 98.94496538452458], + [508860.2682226441, 6651186.461196488, 98.81734262552462], + [508859.68300388084, 6651188.5802024435, 97.1606367655231], + [508860.1735321096, 6651186.804059395, 98.66085133352439], + [508859.75143281405, 6651188.332429601, 97.46900557352427], + [508860.0810874778, 6651187.138790161, 98.4756424315248], + [508859.82616744086, 6651188.061824608, 97.75710392452501], + [508859.99179561756, 6651187.462105127, 98.26239009652473], + [508859.9065428696, 6651187.770794958, 98.02230164952542], + [508868.06718643755, 6651179.215406375, 97.18006463650315], + [508867.9206669118, 6651179.751940836, 96.90069859450315], + [508871.0054461452, 6651178.900448406, 94.02639872847767], + [508867.9994693809, 6651179.463376973, 97.48843344450316], + [508867.85902280535, 6651179.977673122, 97.16710490950317], + [508870.8456864497, 6651179.488742964, 94.02639872847767], + [508870.9999530832, 6651178.920675902, 94.49198941547768], + [508867.9255122297, 6651179.734197945, 97.77653179550315], + [508867.7920555439, 6651180.2228980735, 97.41481464950316], + [508870.84083963046, 6651179.506590754, 94.43721404047767], + [508870.98277554626, 6651178.983929976, 94.96926036747767], + [508867.8459729585, 6651180.025459875, 98.04172952050315], + [508867.69555394555, 6651180.576273727, 97.71225711950315], + [508870.8256829802, 6651179.562403172, 94.85833546847768], + [508870.9530275743, 6651179.093473061, 95.45216138747767], + [508867.76160710707, 6651180.334396084, 98.28181796750316], + [508867.5923440468, 6651180.954214257, 97.96847024250314], + [508870.7994347695, 6651179.659058836, 95.28442460347769], + [508870.922089212, 6651179.207399606, 95.81386737247767], + [508867.67324416334, 6651180.657969097, 98.49507030250315], + [508867.48424213286, 6651181.35006868, 98.18074805150316], + [508870.76155895216, 6651179.798531668, 95.70933110747768], + [508870.883601227, 6651179.349126668, 96.17162521847767], + [508867.5817612465, 6651180.992967024, 98.68027920450317], + [508867.37312139256, 6651181.756977631, 98.34786280850315], + [508870.71182860166, 6651179.981657297, 96.12629780947768], + [508870.83755902195, 6651179.5186711745, 96.5220814334777], + [508867.4880557917, 6651181.336103583, 98.83677049650315], + [508867.2608147855, 6651182.168229065, 98.47001593050315], + [508867.3930189188, 6651181.684115612, 98.96439325550315], + [508870.7840929915, 6651179.715552963, 96.86182646047767], + [508870.65037484345, 6651180.207952868, 96.52824672647768], + [508864.97608759283, 6651190.534587528, 92.19016613550315], + [508867.14903063804, 6651182.577567323, 98.54869062350315], + [508864.97608759283, 6651190.534587528, 92.32016613550316], + [508867.29751100065, 6651182.033852544, 99.06348874950315], + [508870.72347305156, 6651179.938778105, 97.18749357047767], + [508867.0392875687, 6651182.979431431, 98.58643348250317], + [508864.81549509364, 6651191.122655294, 92.19016613550315], + [508870.57771334966, 6651180.475519486, 96.90812752847769], + [508867.1708223001, 6651182.4977692375, 99.15265340150316], + [508870.65610716335, 6651180.186844336, 97.49586237847768], + [508870.51638891845, 6651180.701338827, 97.17453384347768], + [508867.0464468211, 6651182.953215227, 99.19542864250316], + [508870.58253354055, 6651180.4577697525, 97.78396072947767], + [508870.44976893713, 6651180.9466583505, 97.4222435834777], + [508866.5782699979, 6651184.667614714, 98.58643348250317], + [508864.97608697665, 6651190.534589784, 94.01896979550315], + [508870.50340674573, 6651180.74914401, 98.04915845447769], + [508870.3537677787, 6651181.300170287, 97.71968605347767], + [508864.9772844266, 6651190.530204887, 94.22279107950317], + [508864.81549509364, 6651191.122655294, 94.01896979450315], + [508870.41947840044, 6651181.058199363, 98.2892469014777], + [508864.98722735303, 6651190.493795251, 94.63937036750315], + [508870.2510931079, 6651181.678256574, 97.97589917647767], + [508864.8210167901, 6651191.102435596, 94.48456048150315], + [508865.0079533049, 6651190.417899649, 95.06369748750315], + [508870.3315736909, 6651181.381897164, 98.50249923647769], + [508866.1268363239, 6651186.32070308, 98.58643348250317], + [508870.1435517909, 6651182.074263661, 98.18817698547767], + [508865.04013315385, 6651190.300061445, 95.49000783850315], + [508864.8382838711, 6651191.039205907, 94.96183143350316], + [508870.24056518805, 6651181.717024285, 98.68770813847767], + [508866.0170932545, 6651186.722567189, 98.54869062350315], + [508865.0841576334, 6651190.138849821, 95.91181669750317], + [508864.86818691494, 6651190.929705051, 95.44473245350315], + [508870.0330073028, 6651182.481329539, 98.35529174247768], + [508865.90530910704, 6651187.131905446, 98.47001593050315], + [508865.14007980475, 6651189.934070479, 96.32216624050315], + [508866.1196776879, 6651186.346917026, 99.19542864250316], + [508870.1473456728, 6651182.060293177, 98.84419943047769], + [508865.79300249997, 6651187.543156879, 98.34786280850315], + [508864.89928655425, 6651190.815822425, 95.80643843850316], + [508865.2075762342, 6651189.686907787, 96.71394593450316], + [508865.68188175966, 6651187.950065832, 98.18074805150316], + [508865.2653796726, 6651189.475239502, 96.99142779450315], + [508869.9212830975, 6651182.892739574, 98.47744486447768], + [508865.99530220893, 6651186.802363017, 99.15265340150316], + [508865.3288603816, 6651189.242781829, 97.25186846750316], + [508865.5737798457, 6651188.345920254, 97.96847024250314], + [508864.9379751715, 6651190.674150002, 96.16419628450316], + [508865.397470511, 6651188.991540921, 97.49283811350317], + [508865.470569947, 6651188.723860784, 97.71225711950315], + [508870.0528016441, 6651182.40843942, 98.97182218947768], + [508864.98425738775, 6651190.504670856, 96.51465249950316], + [508865.86861350836, 6651187.2662797095, 99.06348874950315], + [508867.64840408805, 6651191.2623245865, 92.19759506947767], + [508869.8100786425, 6651183.302235696, 98.55611955747767], + [508867.64840408805, 6651191.2623245865, 92.3275950694777], + [508865.7731055902, 6651187.616016641, 98.96439325550315], + [508865.03800212883, 6651190.307864966, 96.85439752650315], + [508869.95778901275, 6651182.758311231, 99.07091768347767], + [508865.6780687173, 6651187.96402867, 98.83677049650315], + [508865.09893807146, 6651190.084725879, 97.18006463650315], + [508865.58436326246, 6651188.307165228, 98.68027920450317], + [508865.1666551281, 6651189.83675528, 97.48843344450316], + [508869.7009046808, 6651183.704254787, 98.59386241647768], + [508867.48864439264, 6651191.850619145, 92.19759506947767], + [508865.4928803457, 6651188.642163156, 98.49507030250315], + [508865.24061227933, 6651189.565934308, 97.77653179550315], + [508865.4045174018, 6651188.965736169, 98.28181796750316], + [508865.3201515505, 6651189.274672377, 98.04172952050315], + [508869.83175729687, 6651183.222406836, 99.16008233547768], + [508869.70802680677, 6651183.678028474, 99.20285757647768], + [508869.2422778641, 6651185.393089131, 98.59386241647768], + [508867.648403475, 6651191.262326844, 94.02639872947768], + [508867.6495947152, 6651191.257940255, 94.23022001347768], + [508867.48864439264, 6651191.850619145, 94.02639872847767], + [508867.65948607936, 6651191.221516577, 94.64679930147767], + [508867.49413745455, 6651191.830391649, 94.49198941547768], + [508867.6801045502, 6651191.145591706, 95.07112642147767], + [508868.79318524373, 6651187.046815022, 98.59386241647768], + [508867.7121175203, 6651191.027708057, 95.49743677247768], + [508867.5113149915, 6651191.767137576, 94.96926036747767], + [508868.6840112821, 6651187.448834113, 98.55611955747767], + [508867.7559136969, 6651190.866434261, 95.91924563147768], + [508867.5410629635, 6651191.657594491, 95.45216138747767], + [508868.5728068271, 6651187.858330235, 98.47744486447768], + [508867.81154586584, 6651190.661575945, 96.32959517447769], + [508868.786063731, 6651187.073039079, 99.20285757647768], + [508868.46108262177, 6651188.26974027, 98.35529174247768], + [508867.57200132584, 6651191.543667945, 95.81386737247767], + [508867.8786922711, 6651190.414317933, 96.72137486847768], + [508868.35053813364, 6651188.67680615, 98.18817698547767], + [508867.9361959512, 6651190.202568016, 96.99885672847768], + [508868.662333241, 6651187.528660715, 99.16008233547768], + [508867.9993474607, 6651189.970020695, 97.25929740147768], + [508868.24299681664, 6651189.072813236, 97.97589917647767], + [508867.6104893109, 6651191.401940885, 96.17162521847767], + [508868.06760179036, 6651189.718682893, 97.50026704747768], + [508868.1403221459, 6651189.450899523, 97.71968605347767], + [508868.53630152514, 6651187.99275632, 99.07091768347767], + [508867.6565315158, 6651191.232396378, 96.5220814334777], + [508868.44128889375, 6651188.342628133, 98.97182218947768], + [508867.70999754634, 6651191.035514588, 96.86182646047767], + [508868.34674486506, 6651188.690774374, 98.84419943047769], + [508867.7706174862, 6651190.812289446, 97.18749357047767], + [508868.2535253497, 6651189.0340432655, 98.68770813847767], + [508867.8379833744, 6651190.564223215, 97.49586237847768], + [508868.1625168468, 6651189.369170387, 98.50249923647769], + [508867.9115569972, 6651190.2932978, 97.78396072947767], + [508868.07461213734, 6651189.69286819, 98.2892469014777], + [508867.99068379204, 6651190.001923541, 98.04915845447769], + [508885.1289495216, 6651182.678896419, 92.22707043011843], + [508884.97362030385, 6651183.268376259, 92.22707043011843], + [508884.97362030385, 6651183.268376259, 92.35707043011844], + [508885.1289495216, 6651182.678896419, 94.05587408911843], + [508884.97362030385, 6651183.268376259, 94.05587408911843], + [508885.12360879395, 6651182.699164669, 94.52146477611844], + [508884.9689078972, 6651183.286260009, 94.46668940111844], + [508885.10690762685, 6651182.7625461845, 94.99873572811843], + [508884.95417157316, 6651183.342184876, 94.88781082911845], + [508885.07798462966, 6651182.872309975, 95.48163674811843], + [508884.92865128146, 6651183.43903528, 95.31389996411843], + [508885.04790425417, 6651182.986466058, 95.84334273311845], + [508884.89182584157, 6651183.578789118, 95.73880646811844], + [508885.01048362325, 6651183.128478666, 96.20110057911843], + [508884.8434746199, 6651183.762283704, 96.15577317011845], + [508884.9657182671, 6651183.298364766, 96.55155679411844], + [508884.91373496375, 6651183.495643229, 96.89130182111843], + [508884.7837251057, 6651183.98903521, 96.55772208711844], + [508884.8547961444, 6651183.71931812, 97.21696893111844], + [508884.71307867044, 6651184.257140915, 96.93760288911844], + [508884.7892984562, 6651183.967884148, 97.52533773911846], + [508884.65345489676, 6651184.48341523, 97.20400920411844], + [508884.7177651871, 6651184.239355418, 97.81343609011843], + [508884.5886824299, 6651184.729229019, 97.45171894411844], + [508884.6408327474, 6651184.531316731, 98.07863381511844], + [508884.49534358876, 6651185.083453201, 97.74916141411845], + [508884.55923191446, 6651184.8409947585, 98.31872226211844], + [508884.39551630587, 6651185.462301247, 98.00537453711844], + [508890.1094846779, 6651183.98422462, 92.23344354966014], + [508884.47376499046, 6651185.16534474, 98.53197459711843], + [508889.955717831, 6651184.574113935, 92.23344354966014], + [508884.2909573395, 6651185.859106199, 98.21765234611843], + [508889.955717831, 6651184.574113935, 92.36344354966016], + [508884.38528034784, 6651185.501147067, 98.71718349911843], + [508884.1834784862, 6651186.266992224, 98.38476710311845], + [508884.2946460089, 6651185.845107568, 98.87367479111843], + [508884.0748526319, 6651186.679231158, 98.50692022511845], + [508884.20272388804, 6651186.193955248, 99.00129755011844], + [508890.1094846779, 6651183.98422462, 94.06224720866015], + [508883.966732114, 6651187.089552323, 98.58559491811843], + [508881.8650054141, 6651195.06567901, 92.22707043011843], + [508884.1103461601, 6651186.544531973, 99.10039304411843], + [508881.8650054141, 6651195.06567901, 92.35707043011844], + [508883.8605857796, 6651187.492381393, 98.62333777711844], + [508889.955717831, 6651184.574113935, 94.06224720866015], + [508890.1041976697, 6651184.004506948, 94.52783789566014], + [508881.7096761964, 6651195.6551588485, 92.22707043011843], + [508883.9878095729, 6651187.009562627, 99.18955769611844], + [508889.95105282386, 6651184.592010107, 94.47306252066014], + [508883.8675103937, 6651187.466102239, 99.23233293711846], + [508890.08766449033, 6651184.067932491, 95.00510884766014], + [508889.93646472436, 6651184.6479738215, 94.89418394866014], + [508890.0590324136, 6651184.177772529, 95.48800986766015], + [508883.4146776646, 6651189.184618359, 98.62333777711844], + [508889.91120112716, 6651184.744891502, 95.32027308366015], + [508881.8650048182, 6651195.065681271, 94.05587409011844], + [508890.0292546002, 6651184.292007907, 95.84971585266014], + [508881.86616302264, 6651195.061285845, 94.25969537411844], + [508881.7096761964, 6651195.6551588485, 94.05587408911843], + [508889.87474609405, 6651184.88474242, 95.74517958766015], + [508881.87578007823, 6651195.02478878, 94.67627466211843], + [508889.99221036263, 6651184.434119165, 96.20747369866014], + [508881.715016924, 6651195.6348906, 94.52146477611844], + [508881.8958267548, 6651194.948710939, 95.10060178211845], + [508889.8268812106, 6651185.0683644675, 96.16214628966014], + [508889.94789527636, 6651184.604123275, 96.55792991366016], + [508882.97803934215, 6651190.841676137, 98.62333777711844], + [508881.92695193674, 6651194.83058978, 95.52691213311843], + [508881.73171809124, 6651195.571509084, 94.99873572811843], + [508882.8718930078, 6651191.244505207, 98.58559491811843], + [508881.9695335517, 6651194.668991054, 95.94872099211844], + [508889.89643484453, 6651184.801538775, 96.89767494066015], + [508889.76773268386, 6651185.295273483, 96.56409520666014], + [508882.76377248985, 6651191.654826372, 98.50692022511845], + [508881.7606410884, 6651195.461745293, 95.48163674811843], + [508882.97111532424, 6651190.86795303, 99.23233293711846], + [508882.0236229219, 6651194.463719993, 96.35907053511843], + [508882.65514663554, 6651192.067065306, 98.38476710311845], + [508881.7907214638, 6651195.347589212, 95.84334273311845], + [508882.0889072137, 6651194.215963812, 96.75085022911844], + [508882.54766778223, 6651192.4749513315, 98.21765234611843], + [508882.1448161939, 6651194.003787266, 97.02833208911844], + [508889.8380888582, 6651185.025369038, 97.22334205066014], + [508882.8508161451, 6651191.324492642, 99.18955769611844], + [508882.4431088159, 6651192.871756284, 98.00537453711844], + [508882.2062163772, 6651193.770771414, 97.28877276211844], + [508882.27257786837, 6651193.518927223, 97.52974240811844], + [508882.343281533, 6651193.25060433, 97.74916141411845], + [508881.82814209466, 6651195.205576601, 96.20110057911843], + [508889.697796842, 6651185.563565425, 96.94397600866016], + [508882.728279558, 6651191.789523297, 99.10039304411843], + [508881.872907451, 6651195.035690501, 96.55155679411844], + [508882.6359018299, 6651192.14010002, 99.00129755011844], + [508889.77324997506, 6651185.27410773, 97.53171085866015], + [508881.9248907542, 6651194.83841204, 96.89130182111843], + [508889.638772791, 6651185.789996919, 97.21038232366014], + [508882.5439797091, 6651192.488947699, 98.87367479111843], + [508881.98382957355, 6651194.614737148, 97.21696893111844], + [508882.45334537025, 6651192.8329082, 98.71718349911843], + [508882.04932726175, 6651194.36617112, 97.52533773911846], + [508882.3648607275, 6651193.168710529, 98.53197459711843], + [508882.1208605309, 6651194.09469985, 97.81343609011843], + [508882.27939380344, 6651193.493060509, 98.31872226211844], + [508882.1977929706, 6651193.802738537, 98.07863381511844], + [508889.7024362197, 6651185.545767575, 97.81980920966014], + [508889.5746518346, 6651186.0359814605, 97.45809206366016], + [508889.6262776009, 6651185.8379316935, 98.08500693466014], + [508889.4822518374, 6651186.3904517, 97.75553453366014], + [508889.54549754574, 6651186.147824837, 98.32509538166015], + [508889.383428662, 6651186.769562908, 98.01174765666013], + [508889.46089028625, 6651186.472400124, 98.53834771666016], + [508889.2799213966, 6651187.166643497, 98.22402546566013], + [508889.37329566176, 6651186.808435714, 98.72355661866014], + [508889.1735236138, 6651187.574812855, 98.39114022266014], + [508889.28357296373, 6651187.152635143, 98.88004791066015], + [508889.065990367, 6651187.987338146, 98.51329334466014], + [508889.1925754367, 6651187.501725144, 99.00767066966016], + [508888.95895737363, 6651188.397944337, 98.59196803766015], + [508886.8783707826, 6651196.379611547, 92.23344354966014], + [508889.10112688533, 6651187.852545393, 99.10676616366015], + [508886.8783707826, 6651196.379611547, 92.36344354966016], + [508888.85387870675, 6651188.801053226, 98.62971089666014], + [508886.72460393567, 6651196.969500862, 92.23344354966014], + [508888.97982282605, 6651188.317899075, 99.19593081566015], + [508888.86073366995, 6651188.774755819, 99.23870605666015], + [508888.41245573515, 6651190.494465686, 98.62971089666014], + [508886.87837019254, 6651196.37961381, 94.06224720966014], + [508886.8795167473, 6651196.375215331, 94.26606849366014], + [508886.72460393567, 6651196.969500862, 94.06224720866015], + [508886.8890370702, 6651196.338692915, 94.68264778166015], + [508886.72989094385, 6651196.949218535, 94.52783789566014], + [508886.90888210834, 6651196.262562226, 95.10697490166014], + [508887.98020931665, 6651192.15267452, 98.62971089666014], + [508886.9396942192, 6651196.144359015, 95.53328525266015], + [508886.74642412324, 6651196.88579299, 95.00510884766014], + [508887.8751306496, 6651192.555783411, 98.59196803766015], + [508886.98184752936, 6651195.982648036, 95.95509411166015], + [508887.7680976564, 6651192.966389601, 98.51329334466014], + [508886.77505619987, 6651196.775952955, 95.48800986766015], + [508887.97335494356, 6651192.178969665, 99.23870605666015], + [508887.0353928443, 6651195.777234387, 96.36544365466014], + [508887.66056440957, 6651193.378914892, 98.39114022266014], + [508887.1000204775, 6651195.529306104, 96.75722334866015], + [508886.8048340134, 6651196.661717575, 95.84971585266014], + [508887.55416662677, 6651193.787084251, 98.22402546566013], + [508887.15536710015, 6651195.316982173, 97.03470520866014], + [508887.8542657875, 6651192.635826407, 99.19593081566015], + [508887.4506593612, 6651194.184164838, 98.01174765666013], + [508887.21614969283, 6651195.083804459, 97.29514588166015], + [508887.28184369043, 6651194.831785328, 97.53611552766014], + [508887.35183618596, 6651194.563276047, 97.75553453366014], + [508886.8418782509, 6651196.519606319, 96.20747369866014], + [508887.73296172824, 6651193.10118009, 99.10676616366015], + [508886.8861933371, 6651196.349602209, 96.55792991366016], + [508887.64151317684, 6651193.452000339, 99.00767066966016], + [508886.93765376904, 6651196.152186709, 96.89767494066015], + [508887.55051564984, 6651193.801090341, 98.88004791066015], + [508886.9959997554, 6651195.928356444, 97.22334205066014], + [508887.4607929517, 6651194.14528977, 98.72355661866014], + [508887.0608386385, 6651195.679617752, 97.53171085866015], + [508887.37319832726, 6651194.48132536, 98.53834771666016], + [508887.13165239384, 6651195.407957908, 97.81980920966014], + [508887.28859106783, 6651194.805900645, 98.32509538166015], + [508887.2078110126, 6651195.115793789, 98.08500693466014], + [508901.9468384022, 6651187.030150988, 92.24021393804705], + [508901.7967848785, 6651187.620995796, 92.24021393804705], + [508901.7967848785, 6651187.620995796, 92.37021393804707], + [508901.9468384022, 6651187.030150988, 94.06901759704706], + [508901.7967848785, 6651187.620995796, 94.06901759704706], + [508901.94167907024, 6651187.05046617, 94.53460828404705], + [508901.7922325268, 6651187.638920956, 94.47983290904705], + [508901.92554515146, 6651187.113994448, 95.01187923604705], + [508901.77799671615, 6651187.694975321, 94.90095433704705], + [508901.8976045122, 6651187.224012404, 95.49478025604706], + [508901.7533432108, 6651187.792049986, 95.32704347204707], + [508901.8685458045, 6651187.338432819, 95.85648624104705], + [508901.717768532, 6651187.932127431, 95.75194997604706], + [508901.83239615016, 6651187.480774265, 96.21424408704705], + [508901.67105954, 6651188.116046907, 96.16891667804705], + [508901.7891512311, 6651187.651053744, 96.56470030204707], + [508901.7389335197, 6651187.848789014, 96.90444532904706], + [508901.6133393939, 6651188.343323467, 96.57086559504705], + [508901.68199653353, 6651188.072981834, 97.23011243904705], + [508901.54509243625, 6651188.612049984, 96.95074639704707], + [508901.61872344784, 6651188.32212343, 97.53848124704706], + [508901.48749375984, 6651188.838848249, 97.21715271204705], + [508901.54961977724, 6651188.594223305, 97.82657959804705], + [508901.4249212637, 6651189.08523123, 97.46486245204707], + [508901.47530031676, 6651188.886860667, 98.09177732304707], + [508901.3347526385, 6651189.440275635, 97.76230492204705], + [508901.3964710231, 6651189.197255771, 98.33186577004707], + [508901.23831594887, 6651189.820000922, 98.01851804504705], + [508901.3139069485, 6651189.522356797, 98.54511810504707], + [508901.13730828546, 6651190.217724695, 98.23079585404705], + [508901.22842765093, 6651189.858936692, 98.73032700704705], + [508901.0334799079, 6651190.626555199, 98.39791061104705], + [508901.1408716707, 6651190.203693651, 98.88681829904706], + [508900.9285434868, 6651191.039748694, 98.52006373304705], + [508901.0520716475, 6651190.553349102, 99.01444105804707], + [508900.8240952385, 6651191.451019975, 98.59873842604705], + [508900.9628314916, 6651190.904737604, 99.11353655204707], + [508898.7937528355, 6651199.44561576, 92.24021393804705], + [508898.7937528355, 6651199.44561576, 92.37021393804707], + [508900.7215541214, 6651191.854781814, 98.63648128504705], + [508900.8444568101, 6651191.370845058, 99.20270120404706], + [508898.64369931177, 6651200.036460568, 92.24021393804705], + [508900.7282435438, 6651191.82844181, 99.24547644504706], + [508900.290791095, 6651193.550937236, 98.63648128504705], + [508909.26425075, 6651188.873396899, 92.23852090819406], + [508898.79375225975, 6651199.445618027, 94.06901759804705], + [508898.7948711263, 6651199.441212422, 94.27283888204705], + [508909.11649266473, 6651189.464819925, 92.23852090819406], + [508909.11649266473, 6651189.464819925, 92.36852090819407], + [508898.64369931177, 6651200.036460568, 94.06901759704706], + [508898.80416154244, 6651199.404630847, 94.68941817004705], + [508898.6488586437, 6651200.016145387, 94.53460828404705], + [508898.82352734177, 6651199.328376844, 95.11374529004705], + [508899.8689830165, 6651195.21183201, 98.63648128504705], + [508898.85359536944, 6651199.209982169, 95.54005564104706], + [508898.66499256244, 6651199.952617109, 95.01187923604705], + [508899.7664418994, 6651195.615593849, 98.59873842604705], + [508898.8947307171, 6651199.048009254, 95.96186450004706], + [508909.26425075, 6651188.873396899, 94.06732456719406], + [508899.66199365124, 6651196.026865132, 98.52006373304705], + [508898.69293320173, 6651199.8425991535, 95.49478025604706], + [508899.86229417, 6651195.2381697465, 99.24547644504706], + [508898.94698296377, 6651198.84226288, 96.37221404304705], + [508899.55705723003, 6651196.440058625, 98.39791061104705], + [508899.01004990103, 6651198.593933006, 96.76399373704706], + [508898.72199190944, 6651199.728178738, 95.85648624104705], + [508899.4532288525, 6651196.848889129, 98.23079585404705], + [508899.74608090386, 6651195.695766499, 99.20270120404706], + [508909.25917034276, 6651188.893731961, 94.53291525419407], + [508909.11649266473, 6651189.464819925, 94.06732456719406], + [508899.06405995536, 6651198.381265156, 97.04147559704705], + [508899.35222118907, 6651197.246612903, 98.01851804504705], + [508899.1233747062, 6651198.147709745, 97.30191627004706], + [508899.18748225627, 6651197.895282396, 97.54288591604706], + [508899.2557844996, 6651197.62633819, 97.76230492204705], + [508898.75814156374, 6651199.5858372925, 96.21424408704705], + [508899.6277062223, 6651196.1618739525, 99.11353655204707], + [508898.80138648284, 6651199.415557812, 96.56470030204707], + [508909.1120099525, 6651189.482762627, 94.47813987919407], + [508899.5384660665, 6651196.513262454, 99.01444105804707], + [508909.24328323203, 6651188.957322411, 95.01018620619406], + [508898.8516041942, 6651199.217822542, 96.90444532904706], + [508899.4496660433, 6651196.862917906, 98.88681829904706], + [508898.90854118037, 6651198.993629721, 97.23011243904705], + [508899.362110063, 6651197.207674866, 98.73032700704705], + [508898.9718142661, 6651198.744488127, 97.53848124704706], + [508899.27663076547, 6651197.544254758, 98.54511810504707], + [508899.04091793665, 6651198.472388252, 97.82657959804705], + [508899.19406669086, 6651197.8693557875, 98.33186577004707], + [508899.11523739714, 6651198.17975089, 98.09177732304707], + [508909.0979919136, 6651189.538871847, 94.89926130719408], + [508909.21577001363, 6651189.067448033, 95.49308722619406], + [508909.07371554436, 6651189.636041514, 95.32535044219406], + [508909.1871558306, 6651189.181980424, 95.85479321119408], + [508909.0386850681, 6651189.776256042, 95.75025694619407], + [508909.1515591743, 6651189.324461169, 96.21255105719406], + [508908.99269060517, 6651189.960355506, 96.16722364819408], + [508909.1089757928, 6651189.494907288, 96.56300727219407], + [508909.0595262851, 6651189.692836069, 96.90275229919406], + [508908.9358534309, 6651190.187854486, 96.56917256519407], + [508909.0034602904, 6651189.917248291, 97.22841940919407], + [508908.86865047866, 6651190.456843985, 96.94905336719407], + [508908.9411551224, 6651190.166633703, 97.53678821719409], + [508908.811932916, 6651190.683864202, 97.21545968219407], + [508908.8731085629, 6651190.438999861, 97.82488656819406], + [508908.7503176203, 6651190.9304883005, 97.46316942219407], + [508908.7999260017, 6651190.731923607, 98.09008429319407], + [508908.6615283465, 6651191.285880164, 97.76061189219408], + [508908.7223025963, 6651191.042622471, 98.33017274019407], + [508908.5665668937, 6651191.66597706, 98.01682501519407], + [508908.6410015427, 6651191.368041652, 98.54342507519407], + [508908.4671043914, 6651192.064090057, 98.22910282419406], + [508908.55682986166, 6651191.704950933, 98.72863397719406], + [508908.3648643248, 6651192.473320655, 98.39621758119408], + [508908.4706132658, 6651192.050045281, 98.88512526919406], + [508908.2615331648, 6651192.88691851, 98.51837070319408], + [508908.38317165786, 6651192.400042916, 99.01274802819407], + [508908.1586827099, 6651193.298592276, 98.59704539619406], + [508908.29529665015, 6651192.751775297, 99.11184352219406], + [508906.1593993975, 6651201.301011802, 92.23852090819406], + [508906.1593993975, 6651201.301011802, 92.36852090819407], + [508908.05771021196, 6651193.702749248, 98.63478825519407], + [508908.17873280105, 6651193.2183388965, 99.20100817419407], + [508906.01164131216, 6651201.892434828, 92.23852090819406], + [508908.06429730315, 6651193.6763834655, 99.24378341519409], + [508907.6335367675, 6651195.400564576, 98.63478825519407], + [508906.15939883055, 6651201.30101407, 94.06732456819407], + [508906.16050058126, 6651201.296604154, 94.27114585219407], + [508906.01164131216, 6651201.892434828, 94.06732456719406], + [508906.1696488776, 6651201.25998678, 94.68772514019406], + [508906.01672171947, 6651201.872099766, 94.53291525419407], + [508906.1887184293, 6651201.183658152, 95.11205226019408], + [508907.21818128304, 6651197.0630847495, 98.63478825519407], + [508906.2183264924, 6651201.065147614, 95.53836261119406], + [508906.0326088302, 6651201.808509315, 95.01018620619406], + [508907.1172087851, 6651197.467241721, 98.59704539619406], + [508906.25883257366, 6651200.903016187, 95.96017147019407], + [508907.0143583303, 6651197.878915487, 98.51837070319408], + [508907.211594759, 6651197.089448261, 99.24378341519409], + [508906.0601220485, 6651201.6983836945, 95.49308722619406], + [508906.3102854933, 6651200.697068463, 96.37052101319406], + [508906.9110271703, 6651198.292513342, 98.39621758119408], + [508906.3723876664, 6651200.448495566, 96.76230070719407], + [508906.08873623156, 6651201.583851304, 95.85479321119408], + [508906.8087871037, 6651198.70174394, 98.22910282419406], + [508907.0971592612, 6651197.547492829, 99.20100817419407], + [508906.4255715039, 6651200.235619593, 97.03978256719408], + [508906.7093246013, 6651199.099856937, 98.01682501519407], + [508906.4839788894, 6651200.001835617, 97.30022324019407], + [508906.61436314863, 6651199.479953834, 97.76061189219408], + [508906.5471057564, 6651199.749161236, 97.54119288619407], + [508906.1243328879, 6651201.441370559, 96.21255105719406], + [508906.9805954121, 6651198.01405643, 99.11184352219406], + [508906.16691626934, 6651201.270924438, 96.56300727219407], + [508906.89272040426, 6651198.36578881, 99.01274802819407], + [508906.21636577713, 6651201.072995658, 96.90275229919406], + [508906.8052787963, 6651198.715786445, 98.88512526919406], + [508906.2724317718, 6651200.848583437, 97.22841940919407], + [508906.7190622006, 6651199.060880792, 98.72863397719406], + [508906.33473693975, 6651200.599198025, 97.53678821719409], + [508906.63489051955, 6651199.397790073, 98.54342507519407], + [508906.40278349933, 6651200.326831865, 97.82488656819406], + [508906.55358946585, 6651199.723209255, 98.33017274019407], + [508906.4759660606, 6651200.033908119, 98.09008429319407], + [508918.8029521197, 6651191.230892957, 92.22959665928788], + [508918.6581862809, 6651191.823055518, 92.22959665928788], + [508918.6581862809, 6651191.823055518, 92.35959665928787], + [508918.8029521197, 6651191.230892957, 94.05840031828788], + [508918.7979745957, 6651191.251253446, 94.52399100528787], + [508918.6581862809, 6651191.823055518, 94.05840031828788], + [508918.65379434807, 6651191.841020656, 94.46921563028786], + [508918.78240921453, 6651191.314923412, 95.00126195728788], + [508918.64006018825, 6651191.897200037, 94.89033705828787], + [508918.75545316585, 6651191.4251867365, 95.48416297728788], + [508918.6162754394, 6651191.9944912065, 95.31642619328787], + [508918.7274184482, 6651191.539862342, 95.84586896228787], + [508918.5819543646, 6651192.134881065, 95.74133269728789], + [508918.6925426591, 6651191.682521251, 96.20362680828786], + [508918.53689133486, 6651192.319210733, 96.15829939928787], + [508918.65082163305, 6651191.853180503, 96.55408302328787], + [508918.6023735265, 6651192.051356779, 96.89382805028788], + [508918.4812051692, 6651192.546994185, 96.56024831628787], + [508918.5474429233, 6651192.276049614, 97.21949516028786], + [508918.4153631428, 6651192.816320039, 96.94012911828787], + [508918.48639949627, 6651192.525746866, 97.52786396828787], + [508918.3597941666, 6651193.04362413, 97.20653543328788], + [508918.4197309465, 6651192.798453601, 97.81596231928788], + [508918.2994266412, 6651193.290556616, 97.45424517328787], + [508918.348030404, 6651193.091743629, 98.08116004428787], + [508918.2124354374, 6651193.646392873, 97.75168764328787], + [508918.271978949, 6651193.402831002, 98.32124849128788], + [508918.11939704756, 6651194.026965055, 98.00790076628786], + [508918.1923243218, 6651193.7286570985, 98.53450082628787], + [508918.02194875875, 6651194.425575865, 98.22017857528787], + [508918.1098572, 6651194.065987662, 98.71970972828788], + [508917.92177915404, 6651194.835318179, 98.38729333228787], + [508918.025386575, 6651194.411513528, 98.87620102028787], + [508917.8205405517, 6651195.249433213, 98.50944645428787], + [508917.9397157457, 6651194.761948813, 99.00382377928788], + [508917.7197729196, 6651195.6616217485, 98.58812114728788], + [508917.85362029314, 6651195.1141210105, 99.10291927328788], + [508915.76097706036, 6651203.674047774, 92.22959665928788], + [508917.620845214, 6651196.066284092, 98.62586400628788], + [508915.76097706036, 6651203.674047774, 92.35959665928787], + [508917.73941697675, 6651195.581268019, 99.19208392528789], + [508915.6162112216, 6651204.266210336, 92.22959665928788], + [508917.62729891017, 6651196.039885341, 99.23485916628788], + [508917.20526169904, 6651197.766222427, 98.62586400628788], + [508915.76097650494, 6651203.674050045, 94.05840031928787], + [508915.7620559442, 6651203.669634616, 94.26222160328788], + [508915.6162112216, 6651204.266210336, 94.05840031828788], + [508915.77101897844, 6651203.632971454, 94.67880089128788], + [508915.6211887457, 6651204.245849845, 94.52399100528787], + [508915.78970235295, 6651203.556547381, 95.10312801128786], + [508916.7983175716, 6651199.430821473, 98.62586400628788], + [508915.8187108238, 6651203.437888652, 95.52943836228786], + [508915.63675412675, 6651204.18217988, 95.00126195728788], + [508916.699389866, 6651199.835483816, 98.58812114728788], + [508915.85839661694, 6651203.275554492, 95.95124722128789], + [508916.598622234, 6651200.247672351, 98.50944645428787], + [508916.7918644311, 6651199.45721795, 99.23485916628788], + [508915.66371017543, 6651204.071916554, 95.48416297728788], + [508915.90880756435, 6651203.069349243, 96.36159676428787], + [508916.49738363165, 6651200.661787384, 98.38729333228787], + [508915.96965210733, 6651202.820465523, 96.75337645828789], + [508916.39721402683, 6651201.071529699, 98.22017857528787], + [508915.6917448931, 6651203.957240948, 95.84586896228787], + [508916.6797463646, 6651199.9158352725, 99.19208392528789], + [508916.0217589198, 6651202.607323363, 97.03085831828787], + [508916.299765738, 6651201.470140509, 98.00790076628786], + [508916.0789834984, 6651202.373247055, 97.29129899128787], + [508916.20672734815, 6651201.850712692, 97.75168764328787], + [508916.14083198435, 6651202.120256723, 97.53226863728787], + [508915.72662068217, 6651203.81458204, 96.20362680828786], + [508916.56554304814, 6651200.382982281, 99.10291927328788], + [508915.76834170823, 6651203.643922789, 96.55408302328787], + [508916.4794475957, 6651200.735154479, 99.00382377928788], + [508915.8167898148, 6651203.445746511, 96.89382805028788], + [508916.3937767663, 6651201.085589763, 98.87620102028787], + [508915.871720418, 6651203.221053677, 97.21949516028786], + [508916.3093061413, 6651201.431115628, 98.71970972828788], + [508915.932763845, 6651202.971356425, 97.52786396828787], + [508916.2268390196, 6651201.768446192, 98.53450082628787], + [508915.9994323948, 6651202.69864969, 97.81596231928788], + [508916.14718439226, 6651202.094272289, 98.32124849128788], + [508916.0711329373, 6651202.405359662, 98.08116004428787], + [508928.4677620787, 6651193.567459267, 92.21282714508105], + [508928.32602804626, 6651194.160354798, 92.21282714508105], + [508928.32602804626, 6651194.160354798, 92.34282714508106], + [508928.4677620787, 6651193.567459267, 94.04163080408105], + [508928.46288879815, 6651193.587844958, 94.50722149108107], + [508928.32602804626, 6651194.160354798, 94.04163080408105], + [508928.3217280928, 6651194.178342173, 94.45244611608105], + [508928.44764940016, 6651193.651593733, 94.98449244308105], + [508928.3082815652, 6651194.234591092, 94.87356754408106], + [508928.4212578874, 6651193.76199354, 95.46739346308105], + [508928.2849949362, 6651194.332002687, 95.29965667908105], + [508928.39381029597, 6651193.876811091, 95.82909944808105], + [508928.25139264186, 6651194.472566318, 95.72456318308106], + [508928.3596649047, 6651194.019646581, 96.18685729408105], + [508928.2072733594, 6651194.657124148, 96.14152988508106], + [508928.3188176349, 6651194.190517071, 96.53731350908106], + [508928.27138416877, 6651194.388938648, 96.87705853608105], + [508928.1527534197, 6651194.885189546, 96.54347880208107], + [508928.21760396776, 6651194.613909604, 97.20272564608106], + [508928.08829031157, 6651195.154848767, 96.92335960408106], + [508928.15783896286, 6651194.863915928, 97.51109445408107], + [508928.03388510685, 6651195.382434212, 97.18976591908105], + [508928.09256664105, 6651195.136960215, 97.79919280508105], + [508927.9747818484, 6651195.629672347, 97.43747565908106], + [508928.0223677109, 6651195.430613273, 98.06439053008107], + [508927.88961248647, 6651195.985949052, 97.73491812908105], + [508927.9479089884, 6651195.7420857055, 98.30447897708106], + [508927.7985225836, 6651196.366992301, 97.99113125208108], + [508927.8699225544, 6651196.068315105, 98.51773131208105], + [508927.7031151377, 6651196.766096507, 98.20340906108106], + [508927.78918252746, 6651196.406063211, 98.70294021408105], + [508927.6050433679, 6651197.176345994, 98.37052381808107], + [508927.7064809564, 6651196.752016763, 98.85943150608105], + [508927.5059249883, 6651197.590973613, 98.49267694008107], + [508927.62260431657, 6651197.102885812, 98.98705426508106], + [508927.4072677155, 6651198.00367235, 98.57135163308105], + [508927.53831194644, 6651197.455493922, 99.08614975908105], + [508925.48949458316, 6651206.026016037, 92.21282714508105], + [508927.3104118359, 6651198.408835579, 98.60909449208106], + [508925.48949458316, 6651206.026016037, 92.34282714508106], + [508927.42650037055, 6651197.923219158, 99.17531441108106], + [508925.34776055074, 6651206.618911569, 92.21282714508105], + [508927.3167303734, 6651198.382404151, 99.21808965208108], + [508935.69594368146, 6651195.280786637, 92.19521859384106], + [508926.90353181545, 6651200.110878071, 98.60909449208106], + [508935.5564770961, 6651195.874219633, 92.19521859384106], + [508935.5564770961, 6651195.874219633, 92.32521859384107], + [508925.4894940394, 6651206.026018311, 94.04163080508107], + [508925.49055087205, 6651206.021597415, 94.24545208908106], + [508925.34776055074, 6651206.618911569, 94.04163080408105], + [508925.4993261951, 6651205.984888872, 94.66203137708105], + [508925.3526338313, 6651206.598525876, 94.50722149108107], + [508925.51761828695, 6651205.908370203, 95.08635849708105], + [508926.50511024933, 6651201.777537532, 98.60909449208106], + [508935.69594368146, 6651195.280786637, 94.02402225284106], + [508925.5460192382, 6651205.789564601, 95.51266884808105], + [508926.40825436986, 6651202.182700761, 98.57135163308105], + [508925.36787322926, 6651206.534777101, 94.98449244308105], + [508935.6911483631, 6651195.301190808, 94.48961293984107], + [508935.5564770961, 6651195.874219633, 94.02402225284106], + [508925.58487389865, 6651205.6270295065, 95.93447770708106], + [508926.30959709705, 6651202.595399497, 98.49267694008107], + [508926.498792256, 6651201.803966682, 99.21808965208108], + [508925.3942647419, 6651206.424377293, 95.46739346308105], + [508925.6342290983, 6651205.420569018, 96.34482725008107], + [508926.21047871746, 6651203.010027117, 98.37052381808107], + [508925.69379938435, 6651205.171377234, 96.73660694408106], + [508935.552245933, 6651195.892223312, 94.43483756484108], + [508926.11240694765, 6651203.420276604, 98.20340906108106], + [508926.38902225887, 6651202.263151676, 99.17531441108106], + [508925.42171233334, 6651206.309559744, 95.82909944808105], + [508935.6761527636, 6651195.364997372, 94.96688389184106], + [508925.74481493275, 6651204.957971252, 97.01408880408107], + [508926.0169995016, 6651203.819380809, 97.99113125208108], + [508925.80084106675, 6651204.723605206, 97.27452947708107], + [508925.9259095988, 6651204.200424059, 97.73491812908105], + [508925.8613942703, 6651204.470301725, 97.51549912308106], + [508925.4558577247, 6651206.166724255, 96.18685729408105], + [508926.277210683, 6651202.730876911, 99.08614975908105], + [508935.5390145215, 6651195.948523222, 94.85595899284108], + [508925.4967049945, 6651205.995853763, 96.53731350908106], + [508926.19291831285, 6651203.083485024, 98.98705426508106], + [508925.54413846065, 6651205.797432187, 96.87705853608105], + [508935.6501834597, 6651195.475497258, 95.44978491184106], + [508926.109041673, 6651203.434354072, 98.85943150608105], + [508925.59791866154, 6651205.572461231, 97.20272564608106], + [508926.02634010196, 6651203.780307623, 98.70294021408105], + [508925.65768366656, 6651205.322454908, 97.51109445408107], + [508925.94560007507, 6651204.118055731, 98.51773131208105], + [508925.7229559883, 6651205.049410619, 97.79919280508105], + [508925.867613641, 6651204.44428513, 98.30447897708106], + [508935.51610042976, 6651196.046023121, 95.28204812784107], + [508925.7931549186, 6651204.755757561, 98.06439053008107], + [508935.6231749722, 6651195.590418891, 95.81149089684108], + [508935.4830357017, 6651196.186714173, 95.70695463184107], + [508935.58957583545, 6651195.733383862, 96.16924874284108], + [508935.43962223514, 6651196.371439305, 96.12392133384108], + [508935.5493820363, 6651195.904409247, 96.51970495784107], + [508935.50270740606, 6651196.103010694, 96.85944998484106], + [508935.3859745001, 6651196.599711447, 96.52587025084107], + [508935.44978757546, 6651196.328185587, 97.18511709484108], + [508935.32254266646, 6651196.869615115, 96.90575105284107], + [508935.39097868523, 6651196.578418543, 97.49348590284107], + [508935.26900783094, 6651197.097406866, 97.17215736784107], + [508935.3267505836, 6651196.8517103465, 97.78158425384106], + [508935.21085010056, 6651197.344869125, 97.41986710784107], + [508935.2576746891, 6651197.145629603, 98.04678197884107], + [508935.12704326975, 6651197.7014687965, 97.71730957784108], + [508935.18440715, 6651197.457384387, 98.28687042584107], + [508935.0374106143, 6651198.082857464, 97.97352270084107], + [508935.10766833526, 6651197.783909515, 98.50012276084107], + [508934.94352948724, 6651198.482323458, 98.18580050984109], + [508935.02821997943, 6651198.121963792, 98.68533166284107], + [508934.84702666, 6651198.892944839, 98.35291526684107], + [508934.94684145995, 6651198.468230952, 98.84182295484106], + [508934.7494939665, 6651199.30794832, 98.47506838884107], + [508934.8643066703, 6651198.819418063, 98.96944571384107], + [508934.6524150032, 6651199.721021171, 98.55374308184106], + [508934.78136280127, 6651199.172345817, 99.06854120784106], + [508932.7653222175, 6651207.750637153, 92.19521859384106], + [508934.5571086145, 6651200.126551682, 98.59148594084108], + [508932.7653222175, 6651207.750637153, 92.32521859384107], + [508934.6713399761, 6651199.640495048, 99.15770585984107], + [508932.6258556321, 6651208.344070148, 92.19521859384106], + [508934.56332606863, 6651200.100096295, 99.20048110084107], + [508934.15673782077, 6651201.830137085, 98.59148594084108], + [508932.7653216824, 6651207.75063943, 94.02402225384107], + [508932.76636160794, 6651207.746214527, 94.22784353784107], + [508932.6258556321, 6651208.344070148, 94.02402225284106], + [508932.7749965442, 6651207.7094727075, 94.64442282584106], + [508932.6306509505, 6651208.323665977, 94.48961293984107], + [508932.7929960009, 6651207.632884675, 95.06874994584108], + [508933.76469016384, 6651203.498307382, 98.59148594084108], + [508932.82094259665, 6651207.513971374, 95.49506029684106], + [508933.66938377515, 6651203.903837893, 98.55374308184106], + [508932.6456465501, 6651208.259859414, 94.96688389184106], + [508932.85917566397, 6651207.351288939, 95.91686915584107], + [508933.5723048118, 6651204.316910744, 98.47506838884107], + [508933.75847324496, 6651203.52476049, 99.20048110084107], + [508932.6716158539, 6651208.149359527, 95.44978491184106], + [508932.90774128394, 6651207.144641295, 96.32721869884107], + [508933.4747721182, 6651204.731914224, 98.35291526684107], + [508933.37826929096, 6651205.142535604, 98.18580050984109], + [508932.9663585705, 6651206.895223618, 96.71899839284107], + [508933.65045933763, 6651203.984361737, 99.15770585984107], + [508932.6986243415, 6651208.034437896, 95.81149089684108], + [508933.0165579771, 6651206.68162418, 96.99648025284107], + [508933.284388164, 6651205.542001599, 97.97352270084107], + [508933.07168781053, 6651206.447045681, 97.25692092584107], + [508933.19475550856, 6651205.9233902665, 97.71730957784108], + [508933.13127228996, 6651206.193512579, 97.49789057184108], + [508932.73222347815, 6651207.891472924, 96.16924874284108], + [508933.5404365123, 6651204.452510969, 99.06854120784106], + [508932.7724172773, 6651207.7204475375, 96.51970495784107], + [508933.45749264327, 6651204.805438722, 98.96944571384107], + [508932.8190919075, 6651207.521846091, 96.85944998484106], + [508933.37495785364, 6651205.156625833, 98.84182295484106], + [508933.2935793343, 6651205.502892993, 98.68533166284107], + [508932.87201173813, 6651207.296671198, 97.18511709484108], + [508933.21413097833, 6651205.840947271, 98.50012276084107], + [508932.93082062836, 6651207.046438242, 97.49348590284107], + [508933.1373921637, 6651206.1674724, 98.28687042584107], + [508932.99504872994, 6651206.773146439, 97.78158425384106], + [508933.06412462454, 6651206.479227183, 98.04678197884107], + [508947.7180313342, 6651198.065925944, 92.15636226031798], + [508947.5823360222, 6651198.660232624, 92.15636226031798], + [508947.5823360222, 6651198.660232624, 92.28636226031799], + [508947.7180313342, 6651198.065925944, 93.98516591931798], + [508947.7133656846, 6651198.086360155, 94.45075660631797], + [508947.5823360222, 6651198.660232624, 93.98516591931798], + [508947.5782192727, 6651198.678262811, 94.39598123131796], + [508947.69877557654, 6651198.150260659, 94.92802755831796], + [508947.56534564774, 6651198.734645607, 94.81710265931797], + [508947.6735085006, 6651198.260923229, 95.41092857831798], + [508947.54305116896, 6651198.832289051, 95.24319179431797], + [508947.6472303414, 6651198.376014055, 95.77263456331796], + [508947.510880534, 6651198.973187237, 95.66809829831797], + [508947.6145397487, 6651198.519189507, 96.13039240931796], + [508947.4686409979, 6651199.158184332, 96.08506500031797], + [508947.57543281774, 6651198.690466686, 96.48084862431799], + [508947.5300203019, 6651198.889360525, 96.82059365131798], + [508947.41644393484, 6651199.386792549, 96.48701391731797], + [508947.4785314604, 6651199.114866933, 97.14626076131796], + [508947.3547273421, 6651199.657093584, 96.86689471931798], + [508947.4213128033, 6651199.365468296, 97.45462956931797], + [508947.3026401257, 6651199.885220703, 97.13330103431797], + [508947.3588214742, 6651199.639162456, 97.74272792031798], + [508947.24605502066, 6651200.133047289, 97.38101077431797], + [508947.2916134398, 6651199.933514435, 98.00792564531797], + [508947.16451438476, 6651200.490171966, 97.67845324431796], + [508952.6244631494, 6651199.179508398, 92.13707974170651], + [508947.22032710584, 6651200.245728201, 98.24801409231797], + [508947.07730545854, 6651200.872122136, 97.93466636731796], + [508952.49030696234, 6651199.774164403, 92.13707974170651], + [508952.49030696234, 6651199.774164403, 92.26707974170652], + [508947.14566336205, 6651200.572734058, 98.46126642731798], + [508946.9859629424, 6651201.272176248, 98.14694417631796], + [508947.0683633449, 6651200.911286038, 98.64647532931797], + [508946.89206961874, 6651201.683402168, 98.31405893331797], + [508946.9891853571, 6651201.258062992, 98.80296662131796], + [508952.6244631494, 6651199.179508398, 93.96588340070652], + [508946.79717427696, 6651202.09901664, 98.43621205531797], + [508946.90888236556, 6651201.609767142, 98.93058938031798], + [508952.6198504199, 6651199.19995462, 94.43147408770653], + [508952.49030696234, 6651199.774164403, 93.96588340070652], + [508946.70272039616, 6651202.512697639, 98.51488674831798], + [508946.82818135637, 6651201.963214495, 99.02968487431798], + [508952.486236907, 6651199.792205187, 94.37669871270653], + [508946.6099911584, 6651202.918825195, 98.55262960731797], + [508952.60542580014, 6651199.263892684, 94.90874503970652], + [508944.86665591015, 6651210.554135273, 92.15636226031798], + [508946.72113362467, 6651202.4320529625, 99.11884952631799], + [508944.86665591015, 6651210.554135273, 92.28636226031799], + [508952.4735093013, 6651199.848621125, 94.79782014070652], + [508944.7309605982, 6651211.148441953, 92.15636226031798], + [508946.61604048836, 6651202.892330859, 99.16162476731797], + [508952.58044531633, 6651199.374620299, 95.39164605970652], + [508952.45146769786, 6651199.946321964, 95.22390927570652], + [508952.5544652172, 6651199.489778774, 95.75335204470652], + [508946.22044666903, 6651204.624918713, 98.55262960731797], + [508952.4196619585, 6651200.087302967, 95.64881577970652], + [508952.5221454178, 6651199.633038383, 96.11110989070652], + [508944.86665538955, 6651210.554137555, 93.98516592031797], + [508952.4834820575, 6651199.8044162365, 96.46156610570652], + [508952.3779015246, 6651200.272408801, 96.06578248170652], + [508944.86766719486, 6651210.549706136, 94.18898720431797], + [508944.7309605982, 6651211.148441953, 93.98516591931798], + [508944.87606863637, 6651210.512910223, 94.60556649231798], + [508952.43858463346, 6651200.003426982, 96.80131113270652], + [508952.3262965071, 6651200.501151389, 96.46773139870653], + [508944.89358137525, 6651210.436209433, 95.02989361231796], + [508944.7356262477, 6651211.128007742, 94.45075660631797], + [508945.839000253, 6651206.295544983, 98.55262960731797], + [508952.38767980435, 6651200.229065941, 97.12697824270653], + [508944.92077227565, 6651210.3171210615, 95.45620396331798], + [508945.74627101526, 6651206.701672539, 98.51488674831798], + [508952.2652799351, 6651200.771611306, 96.84761220070652], + [508944.7502163559, 6651211.064107238, 94.92802755831796], + [508945.6518171345, 6651207.115353539, 98.43621205531797], + [508944.95797149424, 6651210.154199116, 95.87801282231797], + [508945.8329514441, 6651206.322037038, 99.16162476731797], + [508952.3311101504, 6651200.479814603, 97.43534705070654], + [508944.77548343176, 6651210.953444668, 95.41092857831798], + [508945.5569217928, 6651207.530968011, 98.31405893331797], + [508945.0052238661, 6651209.947247235, 96.28836236531797], + [508952.21378351835, 6651200.999872515, 97.11401851570652], + [508945.7278583078, 6651206.782314935, 99.11884952631799], + [508945.463028469, 6651207.94219393, 98.14694417631796], + [508945.0622561005, 6651209.697462349, 96.68014205931799], + [508944.801761591, 6651210.838353842, 95.77263456331796], + [508945.1110980803, 6651209.483548438, 96.95762391931797], + [508945.3716859529, 6651208.342248043, 97.93466636731796], + [508945.1647371648, 6651209.248624582, 97.21806459231797], + [508945.28447702667, 6651208.724198211, 97.67845324431796], + [508945.2227104385, 6651208.994718214, 97.45903423831797], + [508952.2693276296, 6651200.753669637, 97.72344540170651], + [508945.6208105761, 6651207.251153402, 99.02968487431798], + [508944.83445218374, 6651210.6951783905, 96.13039240931796], + [508952.1578402302, 6651201.24784477, 97.36172825570652], + [508945.5401095668, 6651207.604600755, 98.93058938031798], + [508944.8735591147, 6651210.523901211, 96.48084862431799], + [508945.4598065753, 6651207.956304904, 98.80296662131796], + [508944.9189716305, 6651210.325007372, 96.82059365131798], + [508952.20288190275, 6651201.048194633, 97.98864312670652], + [508945.38062858756, 6651208.303081859, 98.64647532931797], + [508944.97046047205, 6651210.099500963, 97.14626076131796], + [508945.3033285704, 6651208.641633839, 98.46126642731798], + [508945.02767912904, 6651209.848899601, 97.45462956931797], + [508952.07722446957, 6651201.60517936, 97.65917072570653], + [508945.2286648265, 6651208.968639695, 98.24801409231797], + [508945.09017045813, 6651209.575205442, 97.74272792031798], + [508945.1573784926, 6651209.2808534615, 98.00792564531797], + [508952.1324041345, 6651201.3605919145, 98.22873157370653], + [508951.9910047112, 6651201.987354035, 97.91538384870653], + [508952.0585872647, 6651201.68778998, 98.44198390870652], + [508951.90069824824, 6651202.387643293, 98.12766165770651], + [508951.98216402344, 6651202.026540956, 98.62719281070652], + [508951.8078699101, 6651202.799110927, 98.29477641470653], + [508951.9038841126, 6651202.373521742, 98.78368410270652], + [508951.71405091946, 6651203.214969691, 98.41692953670653], + [508951.82449195825, 6651202.725432619, 98.91130686170652], + [508951.6206683824, 6651203.628893848, 98.49560422970652], + [508951.7447063008, 6651203.079087725, 99.01040235570652], + [508951.5289909267, 6651204.0352601195, 98.53334708870652], + [508949.8054294701, 6651211.675058132, 92.13707974170651], + [508951.6388727587, 6651203.548201768, 99.09956700770653], + [508949.8054294701, 6651211.675058132, 92.26707974170652], + [508951.53497164196, 6651204.0087502105, 99.14234224870654], + [508949.67127328314, 6651212.269714138, 92.13707974170651], + [508951.14386484824, 6651205.742356456, 98.53334708870652], + [508949.8054289554, 6651211.675060415, 93.96588340170653], + [508949.8064292842, 6651211.670626392, 94.16970468570652], + [508949.67127328314, 6651212.269714138, 93.96588340070652], + [508949.81473543245, 6651211.63380885, 94.58628397370651], + [508949.832049533, 6651211.557062976, 95.01061109370652], + [508950.7667449908, 6651207.413964699, 98.53334708870652], + [508949.6758860125, 6651212.249267915, 94.43147408770653], + [508950.675067535, 6651207.820330971, 98.49560422970652], + [508949.8589320203, 6651211.437904607, 95.43692144470651], + [508949.6903106322, 6651212.185329852, 94.90874503970652], + [508950.58168499806, 6651208.234255128, 98.41692953670653], + [508949.89570930664, 6651211.274886899, 95.85873030370652], + [508950.76076479047, 6651207.440472324, 99.14234224870654], + [508950.4878660074, 6651208.650113892, 98.29477641470653], + [508949.71529111615, 6651212.074602236, 95.39164605970652], + [508949.94242571807, 6651211.067813372, 96.26907984670653], + [508950.6568636737, 6651207.901020768, 99.09956700770653], + [508950.3950376692, 6651209.061581525, 98.12766165770651], + [508949.998811064, 6651210.817881668, 96.66085954070653], + [508949.7412712152, 6651211.959443761, 95.75335204470652], + [508950.04709905334, 6651210.603842022, 96.93834140070653], + [508950.30473120627, 6651209.461870784, 97.91538384870653], + [508950.10012973606, 6651210.368780077, 97.19878207370654], + [508950.21851144783, 6651209.844045457, 97.65917072570653], + [508950.1574454476, 6651210.114724467, 97.43975171970652], + [508950.55103013164, 6651208.370134811, 99.01040235570652], + [508949.7735910147, 6651211.816184153, 96.11110989070652], + [508950.47124447423, 6651208.723789916, 98.91130686170652], + [508949.8122543749, 6651211.644806298, 96.46156610570652], + [508950.3918523198, 6651209.075700793, 98.78368410270652], + [508949.85715179896, 6651211.445795553, 96.80131113270652], + [508950.313572409, 6651209.422681578, 98.62719281070652], + [508949.9080566281, 6651211.220156594, 97.12697824270653], + [508950.23714916775, 6651209.761432555, 98.44198390870652], + [508949.96462628205, 6651210.969407933, 97.43534705070654], + [508950.16333229793, 6651210.088630621, 98.22873157370653], + [508950.02640880283, 6651210.695552899, 97.72344540170651], + [508950.0928545297, 6651210.401027903, 97.98864312670652], + [508967.01306634734, 6651202.3683314, 92.06912625390798], + [508966.8834237986, 6651202.963987725, 92.06912625390798], + [508966.8834237986, 6651202.963987725, 92.19912625390799], + [508967.01306634734, 6651202.3683314, 93.89792991290798], + [508967.0086088116, 6651202.388812016, 94.36352059990799], + [508966.8834237986, 6651202.963987725, 93.89792991290798], + [508966.8794906789, 6651202.982058856, 94.30874522490798], + [508966.9946695031, 6651202.452857635, 94.840791551908], + [508966.8671912891, 6651203.038569696, 94.729866652908], + [508966.970529479, 6651202.563771514, 95.32369257190798], + [508966.8458912677, 6651203.136434885, 95.15595578790798], + [508966.9454234713, 6651202.679123707, 95.685398556908], + [508969.5871577454, 6651202.926746684, 92.05518010288448], + [508966.8151556214, 6651203.277653044, 95.580862291908], + [508966.9141910603, 6651202.822624304, 96.043156402908], + [508969.45832267724, 6651203.522578181, 92.05518010288448], + [508969.45832267724, 6651203.522578181, 92.18518010288449], + [508966.8768285154, 6651202.994290448, 96.39361261790799], + [508966.77480020275, 6651203.463070259, 95.997828993908], + [508966.83344164956, 6651203.193635966, 96.73335764490798], + [508966.72493141814, 6651203.692197635, 96.39977791090799], + [508969.5871577454, 6651202.926746684, 93.88398376188448], + [508966.78424949583, 6651203.419654489, 97.05902475490798], + [508966.6659677276, 6651203.963112514, 96.77965871290799], + [508969.58272797347, 6651202.947233324, 94.34957444888448], + [508969.45832267724, 6651203.522578181, 93.88398376188448], + [508966.72958310816, 6651203.670824957, 97.36739356290799], + [508966.6162038899, 6651204.1917576995, 97.046065027908], + [508969.4544140551, 6651203.540654628, 94.29479907388448], + [508969.5688754862, 6651203.011297778, 94.82684540088448], + [508966.6698792388, 6651203.945140663, 97.65549191390798], + [508966.56214279425, 6651204.440147088, 97.29377476790799], + [508969.44219127216, 6651203.597182088, 94.71592050188448], + [508969.5448858186, 6651203.122244275, 95.30974642088448], + [508966.6056690553, 6651204.240161103, 97.92068963890799], + [508966.4842393229, 6651204.798082781, 97.59121723790798], + [508969.42102391826, 6651203.695076056, 95.1420096368845], + [508969.51993618405, 6651203.2376303915, 95.67145240588448], + [508966.5375624871, 6651204.553083894, 98.16077808590799], + [508966.40092039836, 6651205.180900342, 97.84743036090799], + [508969.3904797095, 6651203.836335745, 95.56691614088449], + [508969.4888983046, 6651203.381173189, 96.02921025188448], + [508966.46622916026, 6651204.880832368, 98.37403042090799], + [508966.3136522649, 6651205.58186296, 98.059708169908], + [508969.4517684728, 6651203.5528898155, 96.3796664668845], + [508969.3503756451, 6651204.021807489, 95.98388284288448], + [508966.39237715246, 6651205.220153184, 98.559239322908], + [508966.223947104, 6651205.994022755, 98.22682292690799], + [508969.40865184274, 6651203.752293957, 96.71941149388448], + [508966.316730942, 6651205.567717653, 98.71573061490798], + [508969.30081746896, 6651204.251002246, 96.3858317598845], + [508966.1332846207, 6651206.41058107, 98.34897604890799], + [508966.2400099091, 6651205.920220507, 98.84335337390799], + [508969.3597660831, 6651203.97837895, 97.04507860388448], + [508969.24222103466, 6651204.521996795, 96.7657125618845], + [508966.0430439068, 6651206.825201521, 98.42765074190798], + [508966.16290861234, 6651206.274470524, 98.94244886790798], + [508969.3054401859, 6651204.229623281, 97.35344741188449], + [508969.19276715175, 6651204.750709222, 97.03211887688448], + [508965.9544509072, 6651207.232251374, 98.465393600908], + [508966.06063580315, 6651206.744373702, 99.03161351990799], + [508964.28887807723, 6651214.884900912, 92.06912625390798], + [508964.28887807723, 6651214.884900912, 92.19912625390799], + [508969.24610818294, 6651204.504019661, 97.64154576288448], + [508969.1390427766, 6651204.9991716575, 97.2798286168845], + [508965.96023040335, 6651207.2056968715, 99.074388760908], + [508964.1592355286, 6651215.480557236, 92.06912625390798], + [508969.1822979336, 6651204.799126862, 97.9067434878845], + [508969.06162452814, 6651205.357212614, 97.57727108688448], + [508969.1146155682, 6651205.112141677, 98.1468319348845], + [508965.58228226186, 6651208.942219356, 98.465393600908], + [508968.97882455675, 6651205.740142754, 97.8334842098845], + [508969.04372654203, 6651205.439986534, 98.3600842698845], + [508964.2888775799, 6651214.884903196, 93.89792991390799], + [508968.89209997427, 6651206.141223288, 98.04576201888449], + [508964.289844253, 6651214.880461715, 94.101751197908], + [508968.97033452266, 6651205.77940714, 98.54529317188448], + [508964.1592355286, 6651215.480557236, 93.89792991290798], + [508964.2978709437, 6651214.843582242, 94.51833048590798], + [508968.8029535432, 6651206.553504294, 98.21287677588448], + [508968.89515947574, 6651206.1270738235, 98.7017844638845], + [508965.21785047103, 6651210.616639547, 98.465393600908], + [508964.31460251735, 6651214.766707266, 94.94265760590798], + [508964.16369306436, 6651215.460076619, 94.36352059990799], + [508968.7128557526, 6651206.97018511, 98.33502989788448], + [508965.1292574715, 6651211.023689401, 98.42765074190798], + [508968.8189163009, 6651206.479680342, 98.82940722288448], + [508964.3405805528, 6651214.64734845, 95.36896795690798], + [508964.17763237277, 6651215.396031001, 94.840791551908], + [508965.0390167575, 6651211.438309852, 98.34897604890799], + [508965.2120714725, 6651210.643191763, 99.074388760908], + [508964.37612048, 6651214.484056517, 95.790776815908], + [508968.6231771042, 6651207.384927495, 98.41370459088448], + [508968.7422952308, 6651206.834034539, 98.92850271688448], + [508964.9483542742, 6651211.854868167, 98.22682292690799], + [508964.201772397, 6651215.2851171205, 95.32369257190798], + [508964.42126513406, 6651214.276634655, 96.20112635890798], + [508965.1116660728, 6651211.104514932, 99.03161351990799], + [508964.8586491133, 6651212.267027964, 98.059708169908], + [508964.47575341456, 6651214.026282521, 96.59290605290799], + [508968.5351359076, 6651207.792097054, 98.45144744988448], + [508964.2268784046, 6651215.169764928, 95.685398556908], + [508964.77138097986, 6651212.66799058, 97.84743036090799], + [508964.52241677133, 6651213.811882821, 96.87038791290799], + [508964.57366325514, 6651213.57642546, 97.13082858590799], + [508964.6880620553, 6651213.050808142, 97.59121723790798], + [508964.6290505994, 6651213.321942482, 97.371798231908], + [508968.6406594292, 6651207.304075907, 99.01766736888449], + [508965.00939326355, 6651211.574418111, 98.94244886790798], + [508966.8799371232, 6651215.446997104, 92.05518010288448], + [508964.25811081566, 6651215.02626433, 96.043156402908], + [508966.8799371232, 6651215.446997104, 92.18518010288449], + [508964.93229196675, 6651211.928668127, 98.84335337390799], + [508964.2954733606, 6651214.854598189, 96.39361261790799], + [508964.85557093384, 6651212.281170982, 98.71573061490798], + [508968.5408794061, 6651207.765534743, 99.06044260988449], + [508964.3388602264, 6651214.655252671, 96.73335764490798], + [508966.7511020551, 6651216.042828602, 92.05518010288448], + [508964.7799247234, 6651212.628735453, 98.559239322908], + [508964.3880523801, 6651214.429234146, 97.05902475490798], + [508964.7060727157, 6651212.968056269, 98.37403042090799], + [508964.44271876774, 6651214.1780636795, 97.36739356290799], + [508964.63473938877, 6651213.295804741, 98.16077808590799], + [508964.5024226372, 6651213.903747972, 97.65549191390798], + [508964.5666328205, 6651213.6087275315, 97.92068963890799], + [508968.1652853203, 6651209.502567909, 98.45144744988448], + [508966.87993662886, 6651215.446999391, 93.88398376288448], + [508966.8808972811, 6651215.442556604, 94.08780504688448], + [508966.7511020551, 6651216.042828602, 93.88398376188448], + [508966.8888739774, 6651215.405666283, 94.50438433488448], + [508967.80312339845, 6651211.177480518, 98.45144744988448], + [508966.90550133825, 6651215.3287687, 94.92871145488448], + [508966.755531827, 6651216.022341961, 94.34957444888448], + [508967.7150822017, 6651211.584650078, 98.41370459088448], + [508966.931317569, 6651215.209374783, 95.35502180588449], + [508966.7693843142, 6651215.958277508, 94.82684540088448], + [508967.6254035534, 6651211.999392463, 98.33502989788448], + [508967.79738039436, 6651211.204040544, 99.06044260988449], + [508966.9666361353, 6651215.046034829, 95.77683066488449], + [508967.5353057627, 6651212.416073279, 98.21287677588448], + [508966.7933739819, 6651215.84733101, 95.30974642088448], + [508967.0114996052, 6651214.838551968, 96.1871802078845], + [508967.6976003712, 6651211.665499379, 99.01766736888449], + [508967.4461593317, 6651212.828354284, 98.04576201888449], + [508967.06564850465, 6651214.588126208, 96.57895990188449], + [508966.81832361646, 6651215.731944894, 95.67145240588448], + [508967.35943474923, 6651213.229434817, 97.8334842098845], + [508967.11202121794, 6651214.373663458, 96.85644176188448], + [508967.1629485123, 6651214.138136854, 97.1168824348845], + [508967.2766347778, 6651213.612364959, 97.57727108688448], + [508967.21799087565, 6651213.883579036, 97.35785208088448], + [508967.5959645697, 6651212.135540748, 98.92850271688448], + [508966.84936149593, 6651215.588402097, 96.02921025188448], + [508967.5193434995, 6651212.489894943, 98.82940722288448], + [508966.88649132766, 6651215.41668547, 96.3796664668845], + [508967.4431003248, 6651212.842501462, 98.7017844638845], + [508966.9296079578, 6651215.2172813285, 96.71941149388448], + [508967.36792527785, 6651213.190168145, 98.54529317188448], + [508966.9784937174, 6651214.991196336, 97.04507860388448], + [508967.2945332585, 6651213.529588751, 98.3600842698845], + [508967.03281961463, 6651214.739952004, 97.35344741188449], + [508967.2236442322, 6651213.857433608, 98.1468319348845], + [508967.0921516176, 6651214.465555625, 97.64154576288448], + [508967.1559618669, 6651214.170448423, 97.9067434878845], + [508986.3508703175, 6651206.474230385, 91.95111912584724], + [508986.5826719601, 6651206.522202054, 91.94951967737245], + [508986.22729394847, 6651207.071174711, 91.95111912584724], + [508986.22729394847, 6651207.071174711, 92.08111912584725], + [508986.4591683062, 6651207.119161429, 91.94951967737245], + [508986.4591683062, 6651207.119161429, 92.07951967737247], + [508986.3508703175, 6651206.474230385, 93.77992278484724], + [508986.5826719601, 6651206.522202054, 93.77832333637247], + [508986.3466213569, 6651206.494755287, 94.24551347184725], + [508986.22729394847, 6651207.071174711, 93.77992278484724], + [508986.57842549967, 6651206.542727474, 94.24391402337245], + [508986.4591683062, 6651207.119161429, 93.77832333637247], + [508986.22354486573, 6651207.089284918, 94.19073809684726], + [508986.3333342907, 6651206.558939394, 94.72278442384724], + [508986.4554214295, 6651207.137272093, 94.18913864837245], + [508986.5651462519, 6651206.606913199, 94.72118497537245], + [508986.21182098374, 6651207.145917953, 94.61185952484726], + [508986.31032381643, 6651206.670093105, 95.20568544384724], + [508986.44370444614, 6651207.193906556, 94.61026007637246], + [508986.191517624, 6651207.243994758, 95.03794865984725], + [508986.54214931745, 6651206.718069713, 95.20408599537247], + [508986.2863925585, 6651206.785694726, 95.56739142884726], + [508986.4234130333, 6651207.291985833, 95.03634921137247], + [508986.51823214133, 6651206.833674248, 95.56579198037245], + [508986.16222014715, 6651207.385518276, 95.46285516384725], + [508986.25662156136, 6651206.929505618, 95.92514927484724], + [508986.39413279586, 6651207.43351292, 95.46125571537246], + [508986.48847866204, 6651206.977488765, 95.92354982637245], + [508986.22100726893, 6651207.101542958, 96.27560548984725], + [508986.1237530224, 6651207.571336425, 95.87982186584726], + [508986.45288532594, 6651207.1495304415, 96.27400604137247], + [508986.35568830586, 6651207.619335752, 95.87822241737246], + [508986.17965054314, 6651207.3013195265, 96.61535051684724], + [508986.07621767704, 6651207.800959247, 96.28177078284725], + [508986.4115529353, 6651207.349312046, 96.61375106837247], + [508986.3081809314, 6651207.848964362, 96.28017133437245], + [508986.132760168, 6651207.527826774, 96.94101762684726], + [508986.0200129907, 6651208.07245993, 96.66165158484725], + [508986.36469015153, 6651207.575825005, 96.93941817837245], + [508986.080651707, 6651207.779540353, 97.24938643484727], + [508986.2520093172, 6651208.120471891, 96.66005213637247], + [508985.9725776816, 6651208.301599521, 96.92805789984725], + [508986.3126123523, 6651207.827544929, 97.24778698637246], + [508986.20460192004, 6651208.349617258, 96.92645845137245], + [508986.02374147606, 6651208.05444922, 97.53748478584724], + [508985.9210461901, 6651208.550526008, 97.17576763984725], + [508986.2557356087, 6651208.102460726, 97.53588533737245], + [508986.1531007509, 6651208.59855002, 97.17416819137247], + [508985.96253578865, 6651208.35010759, 97.80268251084725], + [508985.8467879453, 6651208.909235673, 97.47321010984726], + [508986.19456593593, 6651208.398126549, 97.80108306237247], + [508985.89761603443, 6651208.663707021, 98.04277095784725], + [508986.0788862013, 6651208.957268728, 97.47161066137245], + [508985.76736764493, 6651209.292881011, 97.72942323284725], + [508986.129684382, 6651208.711733885, 98.04117150937248], + [508985.8296205066, 6651208.992164191, 98.25602329284725], + [508985.99951263354, 6651209.340923736, 97.72782378437245], + [508985.68418292527, 6651209.694710638, 97.94170104184724], + [508986.0617288643, 6651209.040199336, 98.25442384437247], + [508985.75922415097, 6651209.332218729, 98.44123219484725], + [508985.9163768618, 6651209.742763494, 97.94010159337245], + [508985.5986752106, 6651210.107761657, 98.10881579884726], + [508985.9913739314, 6651209.380262447, 98.43963274637245], + [508985.6871175462, 6651209.6805347465, 98.59772348684724], + [508985.8309194617, 6651210.155824927, 98.10721635037245], + [508985.91930975585, 6651209.728587244, 98.59612403837247], + [508985.51225496817, 6651210.525220706, 98.23096892084726], + [508985.6139864117, 6651210.033799825, 98.72534624584725], + [508985.7445500709, 6651210.573294497, 98.22936947237245], + [508985.8462216534, 6651210.08186123, 98.72374679737247], + [508985.4262367599, 6651210.9407377, 98.30964361384724], + [508985.54049280647, 6651210.388815845, 98.82444173984725], + [508985.6585824776, 6651210.988821967, 98.30804416537245], + [508985.77277129336, 6651210.4368862, 98.82284229137247], + [508985.34178916673, 6651211.348667727, 98.34738647284725], + [508985.44300550356, 6651210.859735106, 98.91360639184725], + [508983.7541511217, 6651219.0178647665, 91.95111912584724], + [508985.5741845753, 6651211.396762278, 98.34578702437246], + [508983.7541511217, 6651219.0178647665, 92.08111912584725], + [508985.6753413542, 6651210.907817331, 98.91200694337246], + [508985.34729823115, 6651211.322055805, 98.95638163284727], + [508983.9874807321, 6651219.066152652, 91.94951967737245], + [508983.9874807321, 6651219.066152652, 92.07951967737247], + [508983.63057475275, 6651219.614809092, 91.95111912584724], + [508985.5796903981, 6651211.370149684, 98.95478218437246], + [508983.8639770783, 6651219.663112026, 91.94951967737245], + [508984.98703488056, 6651213.062333213, 98.34738647284725], + [508985.2196390345, 6651213.110470964, 98.34578702437246], + [508983.75415064755, 6651219.017867057, 93.77992278584725], + [508983.75507208856, 6651219.013415971, 93.98374406984725], + [508983.9874802582, 6651219.066154941, 93.77832333737246], + [508983.63057475275, 6651219.614809092, 93.77992278484724], + [508983.988401157, 6651219.061703744, 93.98214462137246], + [508983.76272319775, 6651218.976456751, 94.40032335784724], + [508984.6396554291, 6651214.740374042, 98.34738647284725], + [508983.8639770783, 6651219.663112026, 93.77832333637247], + [508983.77867187466, 6651218.899415548, 94.82465047784726], + [508983.99604776414, 6651219.024743592, 94.39872390937245], + [508983.6348237134, 6651219.59428419, 94.24551347184725], + [508984.555207836, 6651215.148304069, 98.30964361384724], + [508984.872463989, 6651214.788554094, 98.34578702437246], + [508983.8034343567, 6651218.77979864, 95.25096082884724], + [508984.01198705647, 6651218.9477004465, 94.82305102937245], + [508983.8682235387, 6651219.642586607, 94.24391402337245], + [508983.6481107796, 6651219.530100084, 94.72278442384724], + [508984.4691896277, 6651215.563821062, 98.23096892084726], + [508984.6341468391, 6651214.766983673, 98.95638163284727], + [508984.7880660867, 6651215.196494405, 98.30804416537245], + [508983.8373113146, 6651218.6161536155, 95.67276968784725], + [508984.0367349677, 6651218.828080523, 95.24936138037246], + [508984.3827693853, 6651215.981280112, 98.10881579884726], + [508983.8815027865, 6651219.578400882, 94.72118497537245], + [508983.88034357893, 6651218.408283242, 96.08311923084725], + [508983.6711212539, 6651219.418946372, 95.20568544384724], + [508984.7020984934, 6651215.612021874, 98.22936947237245], + [508984.8669586402, 6651214.815164397, 98.95478218437246], + [508984.5384395666, 6651215.2293043705, 98.91360639184725], + [508984.29726167064, 6651216.39433113, 97.94170104184724], + [508984.07059199165, 6651218.664431374, 95.67117023937246], + [508983.93228226673, 6651218.157389765, 96.47489892484725], + [508984.21407695103, 6651216.796160758, 97.72942323284725], + [508983.9767621712, 6651217.9425264625, 96.75238078484726], + [508984.6157291025, 6651216.029491446, 98.10721635037245], + [508983.6950525118, 6651219.303344752, 95.56739142884726], + [508984.02561075106, 6651217.706559968, 97.01282145784725], + [508984.13465665065, 6651217.179806095, 97.47321010984726], + [508984.078406434, 6651217.451526715, 97.25379110384725], + [508984.11359893484, 6651218.4565557595, 96.08151978237245], + [508983.9044997209, 6651219.467244368, 95.20408599537247], + [508984.4409522638, 6651215.700223631, 98.82444173984725], + [508984.77130768413, 6651215.277496749, 98.91200694337246], + [508984.5302717025, 6651216.4425528785, 97.94010159337245], + [508983.7248235089, 6651219.159533859, 95.92514927484724], + [508984.16550706077, 6651218.2056559585, 96.47329947637246], + [508984.3674586585, 6651216.055239651, 98.72534624584725], + [508984.44713593076, 6651216.844392635, 97.72782378437245], + [508984.2099607923, 6651217.99078724, 96.75078133637246], + [508983.92841689714, 6651219.351639832, 95.56579198037245], + [508984.2587806285, 6651217.754814797, 97.01122200937246], + [508984.367762363, 6651217.228047645, 97.47161066137245], + [508984.3115452453, 6651217.4997751145, 97.25219165537246], + [508983.7604378013, 6651218.987496519, 96.27560548984725], + [508984.673877745, 6651215.748427881, 98.82284229137247], + [508984.294327524, 6651216.408504731, 98.59772348684724], + [508983.95817037625, 6651219.207825315, 95.92354982637245], + [508983.8017945271, 6651218.787719951, 96.61535051684724], + [508984.22222091927, 6651216.756820748, 98.44123219484725], + [508984.60042738507, 6651216.103452851, 98.72374679737247], + [508983.8486849023, 6651218.561212704, 96.94101762684726], + [508984.1518245636, 6651217.096875287, 98.25602329284725], + [508983.9937637125, 6651219.035783638, 96.27400604137247], + [508983.9007933632, 6651218.309499124, 97.24938643484727], + [508984.08382903587, 6651217.425332457, 98.04277095784725], + [508984.52733928256, 6651216.456726837, 98.59612403837247], + [508983.95770359423, 6651218.034590257, 97.53748478584724], + [508984.01890928164, 6651217.738931888, 97.80268251084725], + [508984.03509610303, 6651218.836002034, 96.61375106837247], + [508984.45527510694, 6651216.805051634, 98.43963274637245], + [508984.0819588868, 6651218.609489076, 96.93941817837245], + [508984.38492017414, 6651217.145114744, 98.25442384437247], + [508984.134036686, 6651218.357769151, 97.24778698637246], + [508984.3169646564, 6651217.473580196, 98.04117150937248], + [508984.1909134298, 6651218.0828533545, 97.53588533737245], + [508984.25208310236, 6651217.787187531, 97.80108306237247], + [509003.609647662, 6651209.965587189, 91.82009846517153], + [509003.4914852917, 6651210.563626738, 91.82009846517153], + [509003.4914852917, 6651210.563626738, 91.95009846517154], + [509003.609647662, 6651209.965587189, 93.64890212417153], + [509003.60558485246, 6651209.98614975, 94.11449281117152], + [509003.4914852917, 6651210.563626738, 93.64890212417153], + [509003.4879004598, 6651210.581770174, 94.05971743617151], + [509003.59287990525, 6651210.050451616, 94.59176376317151], + [509005.7294420178, 6651210.383197987, 91.80234087613896], + [509003.47669021226, 6651210.638507114, 94.48083886417152], + [509003.57087754185, 6651210.161809263, 95.07466478317153], + [509003.45727636217, 6651210.736763861, 94.90692799917151], + [509005.6119446172, 6651210.981368539, 91.80234087613896], + [509003.5479947352, 6651210.277622979, 95.43637076817151], + [509005.6119446172, 6651210.981368539, 91.93234087613897], + [509003.42926243576, 6651210.878547035, 95.33183450317152], + [509003.51952803385, 6651210.421697723, 95.79412861417151], + [509003.4854740376, 6651210.594050703, 96.14458482917154], + [509003.39248059236, 6651211.064706106, 95.74880120517152], + [509005.7294420178, 6651210.383197987, 93.63114453513896], + [509003.44592918945, 6651210.794193803, 96.48432985617153], + [509003.34702781594, 6651211.294750222, 96.15075012217152], + [509005.7254020721, 6651210.403765052, 94.09673522213897], + [509005.6119446172, 6651210.981368539, 93.63114453513896], + [509003.4010931264, 6651211.021116628, 96.80999696617151], + [509005.60837995925, 6651210.999515948, 94.04195984713895], + [509005.7127686232, 6651210.468081003, 94.57400617413896], + [509003.29328551056, 6651211.56674903, 96.53063092417153], + [509003.3512675868, 6651211.27329203, 97.11836577417152], + [509005.5972327985, 6651211.056265317, 94.46308127513896], + [509003.24792838754, 6651211.796309028, 96.79703723917152], + [509005.6908900801, 6651210.579463043, 95.05690719413896], + [509003.2968506475, 6651211.548705275, 97.40646412517152], + [509005.5779282015, 6651211.154543589, 94.88917041013897], + [509003.19865454, 6651212.045692224, 97.04474697917152], + [509005.66813604854, 6651210.69530213, 95.41861317913896], + [509003.2383264395, 6651211.8449060945, 97.67166185017152], + [509005.55007192615, 6651211.296357821, 95.31407691413897], + [509005.6398295462, 6651210.839408435, 95.77637102513896], + [509003.1276496197, 6651212.405060018, 97.34218944917151], + [509003.1762508817, 6651212.15908089, 97.91175029717152], + [509005.605967192, 6651211.011799168, 96.12682724013897], + [509005.51349707606, 6651211.482557669, 95.73104361613896], + [509003.0517087985, 6651212.789409236, 97.59840257217152], + [509003.1112343029, 6651212.488140686, 98.12500263217153], + [509005.56664488616, 6651211.211986111, 96.46657226713896], + [509005.4683000892, 6651211.712652177, 96.13299253313897], + [509002.9721684809, 6651213.191976106, 97.81068038117152], + [509003.0439220788, 6651212.828819128, 98.31021153417151], + [509005.5220611422, 6651211.438958645, 96.79223937713896], + [509005.4148602237, 6651211.984710569, 96.51287333513896], + [509002.8904069409, 6651213.605784956, 97.97779513817152], + [509002.9749745333, 6651213.177774205, 98.46670282617151], + [509005.4725160005, 6651211.691189285, 97.10060818513897], + [509005.3697583521, 6651212.214320851, 96.77927965013896], + [509002.8077728518, 6651214.024009922, 98.09994826017152], + [509002.9050473436, 6651213.5316874245, 98.59432558517153], + [509005.4184052974, 6651211.9666628605, 97.38870653613895], + [509005.32076179766, 6651212.463758675, 97.02698939013897], + [509002.7255231832, 6651214.440289271, 98.17862295317153], + [509002.83477356343, 6651213.887354798, 98.69342107917153], + [509002.6447753198, 6651214.848967734, 98.21636581217152], + [509005.36021044, 6651212.262928563, 97.65390426113898], + [509002.74155727227, 6651214.35913806, 98.78258573117154], + [509005.25015646423, 6651212.823205192, 97.32443186013896], + [509001.1266932131, 6651222.532235561, 91.82009846517153], + [509001.1266932131, 6651222.532235561, 91.95009846517154], + [509005.29848421813, 6651212.577172182, 97.89399270813898], + [509002.65004302684, 6651214.822306987, 98.82536097217152], + [509005.174643007, 6651213.207638601, 97.58064498313898], + [509001.0085308428, 6651223.13027511, 91.82009846517153], + [509005.2338335261, 6651212.90630406, 98.10724504313896], + [509005.09555030987, 6651213.610293655, 97.79292279213897], + [509002.3055631575, 6651216.565777306, 98.21636581217152], + [509005.1669001078, 6651213.247057126, 98.29245394513896], + [509005.0142488905, 6651214.024193152, 97.96003754913897], + [509005.0983405709, 6651213.596088643, 98.44894523713897], + [509001.12669275975, 6651222.532237856, 93.64890212517152], + [509004.93207983236, 6651214.442509731, 98.08219067113896], + [509001.1275738315, 6651222.527778604, 93.85272340917152], + [509005.028806903, 6651213.95007939, 98.57656799613896], + [509001.0085308428, 6651223.13027511, 93.64890212417153], + [509001.1348897383, 6651222.490751574, 94.26930269717153], + [509004.85029303154, 6651214.858880268, 98.16086536413896], + [509004.958928595, 6651214.305824672, 98.67566349013896], + [509001.9734027315, 6651218.246896861, 98.21636581217152], + [509001.1501396884, 6651222.413569022, 94.69362981717151], + [509001.0125936525, 6651223.1097125495, 94.11449281117152], + [509004.7699995841, 6651215.267648254, 98.19860822313896], + [509001.8926548681, 6651218.655575323, 98.17862295317153], + [509004.8662368872, 6651214.777711282, 98.76482814213897], + [509001.17381730245, 6651222.2937326515, 95.11994016817152], + [509001.8104051995, 6651219.071854672, 98.09994826017152], + [509001.02529859956, 6651223.045410684, 94.59176376317151], + [509001.96813547803, 6651218.273555313, 98.82536097217152], + [509003.2604606253, 6651222.952599125, 91.80234087613896], + [509001.20621007856, 6651222.129787385, 95.54174902717152], + [509003.2604606253, 6651222.952599125, 91.93234087613897], + [509004.7752376467, 6651215.2409816645, 98.80760338313898], + [509001.72777111037, 6651219.4900796395, 97.97779513817152], + [509001.2473570583, 6651221.921535629, 95.95209857017151], + [509001.87662123254, 6651218.736724238, 98.78258573117154], + [509001.04730096296, 6651222.934053037, 95.07466478317153], + [509001.64600957034, 6651219.903888489, 97.81068038117152], + [509001.2970202626, 6651221.670181833, 96.34387826417154], + [509003.1429632246, 6651223.550769676, 91.80234087613896], + [509001.5664692527, 6651220.30645536, 97.59840257217152], + [509001.33955146, 6651221.454924319, 96.62136012417152], + [509001.0701837696, 6651222.818239321, 95.43637076817151], + [509001.49052843155, 6651220.690804577, 97.34218944917151], + [509001.3862599369, 6651221.218524894, 96.88180079717152], + [509001.43674259057, 6651220.963023727, 97.12277044317152], + [509001.7834049415, 6651219.2085075015, 98.69342107917153], + [509001.09865047096, 6651222.6741645755, 95.79412861417151], + [509001.71313116123, 6651219.564174876, 98.59432558517153], + [509001.1327044672, 6651222.501811597, 96.14458482917154], + [509001.6432039715, 6651219.918088094, 98.46670282617151], + [509004.43269636977, 6651216.984833899, 98.19860822313896], + [509001.17224931536, 6651222.301668496, 96.48432985617153], + [509001.57425642596, 6651220.267043172, 98.31021153417151], + [509001.2170853785, 6651222.074745672, 96.80999696617151], + [509001.5069442019, 6651220.607721613, 98.12500263217153], + [509001.266910918, 6651221.822570269, 97.11836577417152], + [509001.4419276231, 6651220.936781408, 97.91175029717152], + [509001.32132785744, 6651221.547157025, 97.40646412517152], + [509001.3798520653, 6651221.250956206, 97.67166185017152], + [509003.2604601744, 6651222.952601421, 93.63114453613898], + [509003.2613362879, 6651222.948141192, 93.83496582013896], + [509003.1429632246, 6651223.550769676, 93.63114453513896], + [509003.2686110237, 6651222.911106051, 94.25154510813896], + [509004.1024052073, 6651218.666321708, 98.19860822313896], + [509003.2837751533, 6651222.833906592, 94.67587222813896], + [509003.1470031704, 6651223.530202612, 94.09673522213897], + [509004.02211176, 6651219.075089693, 98.16086536413896], + [509003.30731951946, 6651222.714043971, 95.10218257913895], + [509003.9403249591, 6651219.49146023, 98.08219067113896], + [509004.0971675958, 6651218.692985999, 98.80760338313898], + [509003.1596366192, 6651223.465886662, 94.57400617413896], + [509003.33953000215, 6651222.550062792, 95.52399143813896], + [509003.8581559009, 6651219.90977681, 97.96003754913897], + [509003.3804454234, 6651222.341765418, 95.93434098113897], + [509004.0061683553, 6651219.156256384, 98.76482814213897], + [509003.1815151624, 6651223.3545046225, 95.05690719413896], + [509003.77685448155, 6651220.323676307, 97.79292279213897], + [509003.42982914345, 6651222.090356562, 96.32612067513897], + [509003.6977617845, 6651220.726331361, 97.58064498313898], + [509003.4721209926, 6651221.875051895, 96.60360253513898], + [509003.20426919387, 6651223.238665534, 95.41861317913896], + [509003.6222483272, 6651221.11076477, 97.32443186013896], + [509003.5185666132, 6651221.638600685, 96.86404320813898], + [509003.56876517105, 6651221.383043551, 97.10501285413896], + [509003.9134766474, 6651219.628142994, 98.67566349013896], + [509003.2325756962, 6651223.094559231, 95.77637102513896], + [509003.8435983395, 6651219.983888276, 98.57656799613896], + [509003.2664380505, 6651222.922168497, 96.12682724013897], + [509003.77406467154, 6651220.337879022, 98.44894523713897], + [509003.30576035636, 6651222.721981554, 96.46657226713896], + [509003.7055051346, 6651220.686910538, 98.29245394513896], + [509003.3503441003, 6651222.495009021, 96.79223937713896], + [509003.6385717163, 6651221.027663606, 98.10724504313896], + [509003.399889242, 6651222.24277838, 97.10060818513897], + [509003.57392102433, 6651221.356795484, 97.89399270813898], + [509003.4539999451, 6651221.967304803, 97.38870653613895], + [509003.5121948025, 6651221.671039101, 97.65390426113898], + [509020.666724205, 6651213.256626926, 91.66691646628368], + [509020.55391256086, 6651213.855698859, 91.66691646628368], + [509020.55391256086, 6651213.855698859, 91.7969164662837], + [509020.666724205, 6651213.256626926, 93.49572012528368], + [509020.662845371, 6651213.277224983, 93.96131081228368], + [509020.55391256086, 6651213.855698859, 93.49572012528368], + [509020.55049006024, 6651213.873873615, 93.90653543728368], + [509020.65071573976, 6651213.341637852, 94.43858176428368], + [509020.5397874445, 6651213.930708499, 94.32765686528369], + [509020.6297097055, 6651213.453187733, 94.92148278428368], + [509020.5212527083, 6651214.029134865, 94.7537460002837], + [509020.60786309704, 6651213.569201377, 95.28318876928368], + [509020.4945073317, 6651214.171162796, 95.17865250428369], + [509020.58068544837, 6651213.713524835, 95.64094661528368], + [509020.5481735133, 6651213.886175345, 95.9914028302837], + [509020.4593910742, 6651214.35764323, 95.59561920628369], + [509020.51041936764, 6651214.086663947, 96.3311478572837], + [509020.41599652776, 6651214.588084466, 95.99756812328368], + [509020.4676136083, 6651214.313978504, 96.65681496728368], + [509020.364687826, 6651214.860552821, 96.3774489252837], + [509020.4200443099, 6651214.5665892325, 96.96518377528369], + [509020.3213846017, 6651215.090509103, 96.64385524028368], + [509025.1467760023, 6651214.094829679, 91.62279150477926], + [509020.3680915234, 6651214.842477918, 97.25328212628368], + [509020.2743420132, 6651215.340322805, 96.8915649802837], + [509025.03536972974, 6651214.694164551, 91.62279150477926], + [509025.03536972974, 6651214.694164551, 91.75279150477925], + [509020.31221745705, 6651215.139190063, 97.5184798512837], + [509020.2065523964, 6651215.70031097, 97.18900745028368], + [509020.2529528559, 6651215.453907212, 97.7585682982837], + [509020.13405039016, 6651216.08532368, 97.44522057328368], + [509020.1908804115, 6651215.783535059, 97.9718206332837], + [509025.1467760023, 6651214.094829679, 93.45159516377925], + [509020.058111883, 6651216.488585494, 97.65749838228368], + [509020.1266162752, 6651216.124801606, 98.15702953528368], + [509025.14294548956, 6651214.115436777, 93.91718585077925], + [509025.03536972974, 6651214.694164551, 93.45159516377925], + [509019.9800527366, 6651216.903108694, 97.82461313928368], + [509020.06079086935, 6651216.474359077, 98.3135208272837], + [509025.0319898655, 6651214.712347284, 93.86241047577924], + [509025.1309669654, 6651214.179877915, 94.39445680277926], + [509019.9011605525, 6651217.322055635, 97.94676626128368], + [509019.9940301805, 6651216.828883251, 98.4411435862837], + [509025.02142057946, 6651214.769207114, 94.28353190377925], + [509025.11022261763, 6651214.291476759, 94.87735782277925], + [509019.8226353814, 6651217.7390536, 98.02544095428368], + [509019.9269385956, 6651217.185164605, 98.5402390802837], + [509025.0031167431, 6651214.86767668, 94.70962103877925], + [509025.08864816726, 6651214.4075413225, 95.23906380777925], + [509019.74554400943, 6651218.148437555, 98.06318381328369], + [509019.83794340165, 6651217.657762299, 98.62940373228369], + [509024.9767045519, 6651215.009766949, 95.13452754277927], + [509025.0618090891, 6651214.551928124, 95.59682165377924], + [509018.296204951, 6651225.844968856, 91.66691646628368], + [509019.75057317986, 6651218.121730783, 98.67217897328369], + [509018.296204951, 6651225.844968856, 91.7969164662837], + [509025.02970217733, 6651214.724654413, 95.94727786877925], + [509024.9420257615, 6651215.196329231, 95.55149424477925], + [509018.18339330686, 6651226.444040789, 91.66691646628368], + [509024.99241836084, 6651214.925231013, 96.28702289577924], + [509024.89917181066, 6651215.426871612, 95.95344316177925], + [509019.4216923326, 6651219.868210822, 98.06318381328369], + [509024.95014586195, 6651215.152645342, 96.61269000577924], + [509024.84850229626, 6651215.6994595565, 96.33332396377925], + [509018.29620451824, 6651225.844971155, 93.49572012628369], + [509024.90316916676, 6651215.405366943, 96.92105881377925], + [509018.29704569257, 6651225.840504205, 93.69954141028369], + [509024.80573852983, 6651215.929516769, 96.59973027877926], + [509018.18339330686, 6651226.444040789, 93.49572012528368], + [509018.3040303144, 6651225.803413256, 94.11612069828368], + [509024.8518635915, 6651215.68137672, 97.20915716477926], + [509019.1045730695, 6651221.55223246, 98.06318381328369], + [509024.75928198284, 6651216.179440118, 96.84744001877925], + [509018.3185897037, 6651225.7260974655, 94.54044781828368], + [509018.18727214093, 6651226.423442733, 93.96131081228368], + [509019.0274816975, 6651221.961616416, 98.02544095428368], + [509024.79668558645, 6651215.978219096, 97.47435488977925], + [509018.34119512845, 6651225.606054223, 94.9667581692837], + [509018.9489565264, 6651222.378614381, 97.94676626128368], + [509019.0995443321, 6651221.578936933, 98.67217897328369], + [509024.69233686756, 6651216.539586286, 97.14488248877925], + [509018.1994017721, 6651226.359029864, 94.43858176428368], + [509018.3721210681, 6651225.441825942, 95.38856702828369], + [509018.87006434234, 6651222.7975613205, 97.82461313928368], + [509019.01217411034, 6651222.042905418, 98.62940373228369], + [509024.7381592849, 6651216.29307438, 97.71444333677925], + [509018.41140479635, 6651225.233214686, 95.79891657128368], + [509018.2204078064, 6651226.247479983, 94.92148278428368], + [509018.7920051959, 6651223.212084521, 97.65749838228368], + [509018.4588191103, 6651224.981426982, 96.19069626528369], + [509018.71606668865, 6651223.615346335, 97.44522057328368], + [509024.62073806825, 6651216.924767983, 97.40109561177925], + [509018.4994243749, 6651224.765797873, 96.46817812528369], + [509018.6435646825, 6651224.000359045, 97.18900745028368], + [509018.2422544149, 6651226.131466338, 95.28318876928368], + [509018.54401776, 6651224.528990356, 96.72861879828369], + [509018.9231789163, 6651222.51550311, 98.5402390802837], + [509018.5922144164, 6651224.273048123, 96.96958844428369], + [509024.6768601193, 6651216.622846902, 97.92769567177925], + [509018.2694320635, 6651225.98714288, 95.64094661528368], + [509018.8560873314, 6651222.871784465, 98.4411435862837], + [509018.7893266425, 6651223.226308638, 98.3135208272837], + [509018.30194399855, 6651225.814492373, 95.9914028302837], + [509024.54574557877, 6651217.328206794, 97.61337342077925], + [509018.72350123676, 6651223.57586611, 98.15702953528368], + [509018.3396981443, 6651225.614003768, 96.3311478572837], + [509024.6133965651, 6651216.964263236, 98.11290457377926], + [509018.65923710045, 6651223.917132658, 97.9718206332837], + [509018.3825039037, 6651225.386689211, 96.65681496728368], + [509018.597164656, 6651224.246760503, 97.7585682982837], + [509018.43007320195, 6651225.134078483, 96.96518377528369], + [509018.53790005494, 6651224.561477653, 97.5184798512837], + [509018.4820259885, 6651224.858189798, 97.25328212628368], + [509024.46865886834, 6651217.742911933, 97.78048817777925], + [509024.54839119123, 6651217.313974132, 98.26939586577925], + [509024.39074949804, 6651218.162042755, 97.90264129977925], + [509024.48246218567, 6651217.668653911, 98.39701862477925], + [509024.31320256856, 6651218.579223745, 97.98131599277926], + [509024.41620640643, 6651218.025091642, 98.49611411877925], + [509024.23707157624, 6651218.988787385, 98.01905885177926], + [509024.32831988623, 6651218.497896764, 98.58527877077927], + [509022.8057879224, 6651226.688696793, 91.62279150477926], + [509024.2420380949, 6651218.962068891, 98.62805401177926], + [509022.8057879224, 6651226.688696793, 91.75279150477925], + [509022.6943816497, 6651227.288031666, 91.62279150477926], + [509023.9172543405, 6651220.7093154825, 98.01905885177926], + [509022.805787495, 6651226.688699093, 93.45159516477925], + [509022.8066181902, 6651226.684230181, 93.65541644877926], + [509022.6943816497, 6651227.288031666, 93.45159516377925], + [509022.8135157998, 6651226.647122953, 94.07199573677924], + [509023.6040856482, 6651222.394076259, 98.01905885177926], + [509022.82789381297, 6651226.569773227, 94.49632285677924], + [509022.69821216253, 6651227.267424568, 93.91718585077925], + [509023.5279546559, 6651222.803639899, 97.98131599277926], + [509022.8502176265, 6651226.449677298, 94.92263320777924], + [509023.4504077264, 6651223.220820889, 97.90264129977925], + [509023.5991195571, 6651222.420792453, 98.62805401177926], + [509022.71019068663, 6651227.202983428, 94.39445680277926], + [509034.8693510464, 6651215.876523727, 91.52147764848303], + [509022.8807583006, 6651226.285376933, 95.34444206677927], + [509023.3724983561, 6651223.639951711, 97.78048817777925], + [509023.5128377658, 6651222.88496458, 98.58527877077927], + [509022.91955264466, 6651226.076674115, 95.75479160977925], + [509023.2954116456, 6651224.054656851, 97.61337342077925], + [509022.7309350344, 6651227.091384585, 94.87735782277925], + [509022.96637628623, 6651225.824775898, 96.14657130377927], + [509023.2204191562, 6651224.45809566, 97.40109561177925], + [509023.0064757034, 6651225.609052147, 96.42405316377925], + [509023.1488203569, 6651224.843277358, 97.14488248877925], + [509023.4249512456, 6651223.357769702, 98.49611411877925], + [509022.7525094849, 6651226.975320023, 95.23906380777925], + [509023.0505135583, 6651225.372140692, 96.68449383677925], + [509034.76099470054, 6651216.476417507, 91.52147764848303], + [509023.09810979606, 6651225.1160861235, 96.92546348277926], + [509034.76099470054, 6651216.476417507, 91.65147764848305], + [509023.35869546636, 6651223.714207433, 98.39701862477925], + [509022.77934856294, 6651226.83093322, 95.59682165377924], + [509023.2927664609, 6651224.068887212, 98.26939586577925], + [509022.8114554747, 6651226.658206931, 95.94727786877925], + [509023.22776108695, 6651224.418598108, 98.11290457377926], + [509022.8487392913, 6651226.457630331, 96.28702289577924], + [509023.1642975329, 6651224.760014442, 97.92769567177925], + [509022.8910117901, 6651226.230216002, 96.61269000577924], + [509023.10299836716, 6651225.0897869645, 97.71444333677925], + [509022.93798848527, 6651225.977494401, 96.92105881377925], + [509023.0444720656, 6651225.4046422485, 97.47435488977925], + [509022.9892940606, 6651225.701484624, 97.20915716477926], + [509034.8693510464, 6651215.876523727, 93.35028130748304], + [509034.8656254, 6651215.89715004, 93.81587199448303], + [509034.76099470054, 6651216.476417507, 93.35028130748304], + [509034.7577073656, 6651216.494617197, 93.76109661948303], + [509034.85397480737, 6651215.961651274, 94.29314294648303], + [509034.74742743094, 6651216.551530052, 94.18221804748303], + [509034.8337983696, 6651216.073354189, 94.77604396648304], + [509034.7296246917, 6651216.650091445, 94.60830718248303], + [509034.8128145547, 6651216.189526988, 95.13774995148303], + [509034.70393557695, 6651216.792314221, 95.03321368648304], + [509034.7867102397, 6651216.33404844, 95.49550779748303], + [509034.7554823066, 6651216.506935802, 95.84596401248305], + [509034.6702061745, 6651216.979050481, 95.45018038848303], + [509034.7192191949, 6651216.707699451, 96.18570903948304], + [509034.62852541974, 6651217.209807852, 95.85212930548303], + [509034.678103974, 6651216.935325854, 96.51137614948303], + [509034.57924306527, 6651217.482650001, 96.23201010748305], + [509034.63241334184, 6651217.1882831305, 96.81974495748304], + [509034.53765002603, 6651217.712921752, 96.49841642248303], + [509034.58251233964, 6651217.4645503005, 97.10784330848304], + [509034.49246530223, 6651217.963078165, 96.74612616248305], + [509034.52884492173, 6651217.761669496, 97.37304103348303], + [509034.4273529177, 6651218.323560188, 97.04356863248303], + [509034.47192087234, 6651218.076818396, 97.61312948048304], + [509034.35771425127, 6651218.7091010865, 97.29978175548302], + [509034.4122998704, 6651218.406898449, 97.82638181548305], + [509034.2847748025, 6651219.112916124, 97.51205956448302], + [509034.3505737336, 6651218.7486331705, 98.01159071748303], + [509034.20979846537, 6651219.528007996, 97.67917432148303], + [509034.287347987, 6651219.098670189, 98.16808200948303], + [509034.13402199006, 6651219.947529678, 97.80132744348303], + [509034.2232238946, 6651219.453680726, 98.29570476848305], + [509034.05859803315, 6651220.3650997095, 97.88000213648304], + [509034.1587819745, 6651219.810450851, 98.39480026248305], + [509033.98455125, 6651220.775045289, 97.91774499548303], + [509034.0733014899, 6651220.283696888, 98.48396491448305], + [509033.9893818021, 6651220.748301878, 98.52674015548304], + [509032.5924513005, 6651228.482135238, 91.52147764848303], + [509032.5924513005, 6651228.482135238, 91.65147764848305], + [509032.4840949547, 6651229.082029021, 91.52147764848303], + [509033.6734895281, 6651222.497177863, 97.91774499548303], + [509032.59245088475, 6651228.48213754, 93.35028130848303], + [509032.5932588384, 6651228.477664462, 93.55410259248303], + [509032.4840949547, 6651229.082029021, 93.35028130748304], + [509032.59996761486, 6651228.44052263, 93.97068188048304], + [509033.3688943351, 6651224.183509762, 97.91774499548303], + [509032.61395200656, 6651228.363100773, 94.39500900048303], + [509032.48782060103, 6651229.061402706, 93.81587199448303], + [509033.29484755197, 6651224.59345534, 97.88000213648304], + [509032.6356646696, 6651228.2428928455, 94.82131935148304], + [509033.3640641989, 6651224.210250868, 98.52674015548304], + [509033.21942359506, 6651225.011025371, 97.80132744348303], + [509032.49947119365, 6651228.996901471, 94.29314294648303], + [509032.66536924336, 6651228.078439265, 95.24312821048304], + [509033.14364711975, 6651225.430547052, 97.67917432148303], + [509033.28014451114, 6651224.674855858, 98.48396491448305], + [509032.7031015295, 6651227.869541819, 95.65347775348303], + [509033.0686707826, 6651225.845638924, 97.51205956448302], + [509032.5196476314, 6651228.885198559, 94.77604396648304], + [509032.74864329817, 6651227.617408697, 96.04525744748305], + [509032.99573133385, 6651226.249453962, 97.29978175548302], + [509032.78764492896, 6651227.401483771, 96.32273930748303], + [509032.9260926674, 6651226.634994861, 97.04356863248303], + [509033.19466402655, 6651225.148101895, 98.39480026248305], + [509032.8304771764, 6651227.164351385, 96.58317998048304], + [509032.87677039014, 6651226.908058032, 96.82414962648303], + [509032.5406314463, 6651228.769025758, 95.13774995148303], + [509033.13022210647, 6651225.504872022, 98.29570476848305], + [509032.5667357613, 6651228.624504308, 95.49550779748303], + [509033.066098014, 6651225.859882557, 98.16808200948303], + [509032.5979636944, 6651228.451616945, 95.84596401248305], + [509033.0028722674, 6651226.209919576, 98.01159071748303], + [509032.63422680617, 6651228.250853297, 96.18570903948304], + [509032.9411461307, 6651226.551654297, 97.82638181548305], + [509032.67534202704, 6651228.0232268935, 96.51137614948303], + [509032.8815251288, 6651226.88173435, 97.61312948048304], + [509032.7210326592, 6651227.7702696165, 96.81974495748304], + [509032.8246010793, 6651227.19688325, 97.37304103348303], + [509032.7709336614, 6651227.494002446, 97.10784330848304], + [510538.3475552979, 6651106.192133014, 67.73428539412009], + [510538.3807739694, 6651106.800828477, 67.73428539412009], + [510538.3807739694, 6651106.800828477, 67.86428539412009], + [510538.3475552979, 6651106.192133014, 69.5630890531201], + [510538.3486974647, 6651106.213061959, 70.02867974012008], + [510538.3807739694, 6651106.800828477, 69.5630890531201], + [510538.3522691726, 6651106.278509561, 70.5059506921201], + [510538.3817817637, 6651106.819295193, 69.97390436512009], + [510538.3849332706, 6651106.877043078, 70.39502579312008], + [510538.3584546382, 6651106.391851387, 70.9888517121201], + [510538.36488762056, 6651106.509728681, 71.35055769712011], + [510538.3903910344, 6651106.977050571, 70.8211149281201], + [510541.804904192, 6651106.006721421, 67.77395593323926], + [510538.37289038824, 6651106.65637056, 71.70831554312011], + [510538.3982665147, 6651107.121360049, 71.24602143212009], + [510541.83697537443, 6651106.6154784225, 67.77395593323926], + [510538.38246389723, 6651106.831794538, 72.05877175812009], + [510541.83697537443, 6651106.6154784225, 67.90395593323927], + [510538.4086068961, 6651107.310836116, 71.66298813412008], + [510538.3935810348, 6651107.035503805, 72.3985167851201], + [510538.42138491385, 6651107.544979176, 72.0649370511201], + [510541.804904192, 6651106.006721421, 69.60275959223927], + [510538.40618567745, 6651107.266469957, 72.72418389512009], + [510541.80600690434, 6651106.0276524825, 70.06835027923925], + [510538.4364933446, 6651107.82182448, 72.44481785312009], + [510538.4201929983, 6651107.52313864, 73.0325527031201], + [510541.83697537443, 6651106.6154784225, 69.60275959223927], + [510541.8094552329, 6651106.0931067, 70.54562123123927], + [510538.4492444714, 6651108.055474795, 72.71122416812008], + [510541.837948356, 6651106.6339470055, 70.01357490423926], + [510538.43549108715, 6651107.80345922, 73.32065105412009], + [510538.4630966966, 6651108.30930152, 72.95893390812009], + [510541.8409909988, 6651106.691700729, 70.43469633223926], + [510541.81542703096, 6651106.206459986, 71.02852225123927], + [510538.4519438414, 6651108.104937769, 73.58584877912008], + [510541.82163779554, 6651106.324349198, 71.39022823623927], + [510541.8462602324, 6651106.791718332, 70.86078546723928], + [510545.0497702439, 6651105.838649935, 67.8111848015487], + [510538.4830581202, 6651108.675072559, 73.2563763781201], + [510538.4693949772, 6651108.424710556, 73.82593722612009], + [510541.82936411974, 6651106.471005901, 71.74798608223927], + [510541.85386366607, 6651106.936042399, 71.28569197123926], + [510545.0807644602, 6651106.447462719, 67.8111848015487], + [510538.5044071604, 6651109.066270138, 73.51258950112009], + [510545.0807644602, 6651106.447462719, 67.94118480154869], + [510538.48767291434, 6651108.759633563, 74.0391895611201], + [510541.83860692626, 6651106.646447614, 72.09844229723927], + [510541.86384685454, 6651107.125537623, 71.70265867323926], + [510538.52676811744, 6651109.476009977, 73.72486731012009], + [510538.50659622013, 6651109.10638224, 74.2243984631201], + [510541.849340039, 6651106.850177474, 72.43818732423927], + [510545.0497702439, 6651105.838649935, 69.6399884605487], + [510541.87618347484, 6651107.359704352, 72.10460759023925], + [510538.5259792594, 6651109.461555026, 74.3808897551201], + [510541.8615092733, 6651107.081166978, 72.76385443423926], + [510538.5497535208, 6651109.897192105, 73.8919820671201], + [510545.05083592667, 6651105.859582913, 70.10557914754868], + [510545.0807644602, 6651106.447462719, 69.6399884605487], + [510541.8907700076, 6651107.636577646, 72.48448839223927], + [510538.54563770344, 6651109.821774298, 74.50851251412008], + [510541.8750327323, 6651107.33786161, 73.07222324223926], + [510538.57298422157, 6651110.322869036, 74.0141351891201], + [510545.0541684587, 6651105.925043128, 70.58285009954871], + [510545.0817047684, 6651106.465932993, 70.05080377254869], + [510541.9030806659, 6651107.870251583, 72.75089470723927], + [510538.5653935836, 6651110.18377898, 74.6076080081201], + [510538.59610685124, 6651110.746565684, 74.0928098821201], + [510541.8898023716, 6651107.61821053, 73.36032159323926], + [510545.08464523783, 6651106.523692008, 70.4719252005487], + [510545.0599397207, 6651106.038406801, 71.0657511195487], + [510541.91645438684, 6651108.124103969, 72.99860444723927], + [510538.5915992306, 6651110.663968514, 74.69677266012009], + [510538.61880728236, 6651111.16252601, 74.13055274112008], + [510545.0659419248, 6651106.156306815, 71.4274571045487], + [510545.08973752795, 6651106.623718777, 70.8980143355487], + [510541.9056867903, 6651107.919719556, 73.62551931823926], + [510548.45917139295, 6651105.66825618, 67.85029779767426], + [510541.9357262731, 6651108.4899119865, 73.29604691723927], + [510545.0734087951, 6651106.302976958, 71.78521495054869], + [510538.6173263859, 6651111.135390218, 74.7395479011201], + [510545.09708563454, 6651106.768056069, 71.32292083954869], + [510541.9225351029, 6651108.239524672, 73.86560776523926], + [510548.48903403396, 6651106.277125518, 67.85029779767426], + [510545.08234122366, 6651106.478434748, 72.13567116554869], + [510541.95633784286, 6651108.881149115, 73.55226004023926], + [510548.48903403396, 6651106.277125518, 67.98029779767425], + [510545.1067335826, 6651106.957568655, 71.7398875415487], + [510541.9401816561, 6651108.574481541, 74.07886010023927], + [510545.09271391307, 6651106.682183276, 72.47541619254869], + [510541.9779263743, 6651109.290930377, 73.76453784923926], + [510541.95845128474, 6651108.921265272, 74.26406900223927], + [510545.11865593295, 6651107.191756844, 72.14183645854868], + [510538.71416909155, 6651112.909925829, 74.13055274112008], + [510548.45917139295, 6651105.66825618, 69.67910145667426], + [510545.10447449837, 6651106.913193947, 72.80108330254869], + [510541.9771647662, 6651109.276473965, 74.42056029423928], + [510542.00011778146, 6651109.712155086, 73.93165260623927], + [510548.4601981684, 6651105.689191103, 70.14469214367426], + [510545.1327526427, 6651107.468655508, 72.52171726054868], + [510548.48903403396, 6651106.277125518, 69.67910145667426], + [510545.117543833, 6651107.169912099, 73.10945211054869], + [510541.99614413886, 6651109.636729655, 74.54818305323927], + [510539.0455816504, 6651118.982694897, 67.73428539412009], + [510548.46340903227, 6651105.754657399, 70.62196309567426], + [510542.0225460126, 6651110.137875052, 74.05380572823927], + [510539.0455816504, 6651118.982694897, 67.86428539412009], + [510545.14464990306, 6651107.702350857, 72.78812357554871], + [510548.4899400123, 6651106.295597508, 70.08991676867427], + [510545.1318175005, 6651107.450286709, 73.3975504615487], + [510542.0152175819, 6651109.9987709345, 74.64727854723927], + [510542.0448699058, 6651110.561614534, 74.13248042123926], + [510545.15757452766, 6651107.956226505, 73.03583331554869], + [510548.4927731274, 6651106.353361887, 70.51103819667425], + [510548.4689695899, 6651105.868031602, 71.10486411567426], + [510539.0788003219, 6651119.59139036, 67.73428539412009], + [510545.1471685124, 6651107.751823364, 73.66274818654868], + [510538.8075484649, 6651114.6209997, 74.13055274112008], + [510542.04051799414, 6651110.4790090155, 74.73644319923926], + [510548.4747526581, 6651105.985942568, 71.46657010067428], + [510542.06678618473, 6651110.977616914, 74.17022328023926], + [510548.49767950195, 6651106.453397949, 70.93712733167426], + [510545.17619925446, 6651108.322068042, 73.3332757855487], + [510538.83024889615, 6651115.036960028, 74.0928098821201], + [510545.16345105023, 6651108.071657784, 73.90283663354869], + [510538.8090292339, 6651114.648133156, 74.7395479011201], + [510548.4819469187, 6651106.132626335, 71.82432794667427], + [510542.06535644364, 6651110.950478381, 74.77921844023926], + [510539.0455817779, 6651118.982697234, 69.56308905412008], + [510548.50475933467, 6651106.597748647, 71.36203383567425], + [510538.8533715257, 6651115.4606566755, 74.0141351891201], + [510539.0453340844, 6651118.978158525, 69.76691033812008], + [510545.19611867744, 6651108.713341023, 73.58948890854869], + [510538.83475638926, 6651115.119554861, 74.69677266012009], + [510548.490553231, 6651106.308100423, 72.17478416167425], + [510545.1805050235, 6651108.406645346, 74.1160889685487], + [510538.8766022266, 6651115.886333606, 73.8919820671201], + [510539.0432773831, 6651118.940471746, 70.18348962612009], + [510548.51405504346, 6651106.787278838, 71.77900053767425], + [510539.0788003219, 6651119.59139036, 69.5630890531201], + [510539.0389902054, 6651118.861913948, 70.6078167461201], + [510538.8995876299, 6651116.307515735, 73.72486731012009], + [510538.86096203624, 6651115.599744395, 74.6076080081201], + [510545.2169822552, 6651109.123159834, 73.8017667175487], + [510548.5005472215, 6651106.511867878, 72.51452918867426], + [510545.1981611489, 6651108.753460854, 74.30129787054871], + [510539.03233378095, 6651118.739942323, 71.03412709712009], + [510539.07765815506, 6651119.570461417, 70.02867974012008], + [510538.92194858694, 6651116.717255572, 73.51258950112009], + [510538.8807179163, 6651115.961749077, 74.50851251412008], + [510548.525542118, 6651107.02148878, 72.18094945467426], + [510539.02322728635, 6651118.573075869, 71.45593595612009], + [510538.9432976272, 6651117.108453153, 73.2563763781201], + [510542.1588538637, 6651112.725193391, 74.17022328023926], + [510538.95841829706, 6651117.385522725, 73.03695737212009], + [510539.0116597458, 6651118.361113467, 71.8662854991201], + [510539.07408644725, 6651119.505013815, 70.5059506921201], + [510538.90037636046, 6651116.321968349, 74.3808897551201], + [510538.97261035064, 6651117.6455764305, 72.79598772612009], + [510538.99769806187, 6651118.105281029, 72.25806519312009], + [510538.98574137996, 6651117.88618804, 72.5355470531201], + [510548.5118784368, 6651106.742900008, 72.84019629867427], + [510545.2162462223, 6651109.108702098, 74.45778916254869], + [510545.23842846387, 6651109.5444231415, 73.9688814745487], + [510538.9197593997, 6651116.677141135, 74.2243984631201], + [510539.06790098164, 6651119.391671988, 70.9888517121201], + [510548.5391241676, 6651107.298413167, 72.56083025667425], + [510538.9386827055, 6651117.023889812, 74.0391895611201], + [510539.0614679993, 6651119.273794693, 71.35055769712011], + [510545.2345882582, 6651109.468990799, 74.58541192154868], + [510538.95696064265, 6651117.358812819, 73.82593722612009], + [510548.5244706198, 6651106.999642007, 73.14856510667427], + [510539.05346523155, 6651119.1271528145, 71.70831554312011], + [510545.2601035439, 6651109.970182119, 74.0910345965487], + [510538.9744117784, 6651117.678585607, 73.58584877912008], + [510539.0438917225, 6651118.951728838, 72.05877175812009], + [510542.47881827434, 6651118.798576403, 67.77395593323926], + [510538.9908645327, 6651117.9800641555, 73.32065105412009], + [510539.032774585, 6651118.7480195705, 72.3985167851201], + [510539.00616262155, 6651118.260384735, 73.0325527031201], + [510539.0201699424, 6651118.517053418, 72.72418389512009], + [510548.5505870679, 6651107.532130225, 72.82723657167426], + [510542.47881827434, 6651118.798576403, 67.90395593323927], + [510545.2530212054, 6651109.831065253, 74.6845074155487], + [510548.5382231666, 6651107.28004266, 73.43666345767426], + [510545.28167778964, 6651110.393960429, 74.1697092895487], + [510548.5630398244, 6651107.786029454, 73.07494631167425], + [510542.51088945684, 6651119.407333405, 67.77395593323926], + [510545.27747201733, 6651110.311347341, 74.77367206754869], + [510545.30285810895, 6651110.810000929, 74.2074521485487], + [510548.55301372486, 6651107.581607326, 73.70186118267425], + [510542.24900758715, 6651114.436440249, 74.17022328023926], + [510548.58098457655, 6651108.151904975, 73.37238878167427], + [510545.30147637933, 6651110.7828599075, 74.81644730854869], + [510542.27092386613, 6651114.852442629, 74.13248042123926], + [510548.5687017996, 6651107.9014714565, 73.94194962967426], + [510542.25043720513, 6651114.463576447, 74.77921844023926], + [510542.47881839745, 6651118.798578739, 69.60275959323926], + [510542.2932477593, 6651115.276182111, 74.05380572823927], + [510542.4785792602, 6651118.794039574, 69.80658087723926], + [510548.6001767565, 6651108.543214302, 73.62860190467426], + [510542.2752756546, 6651114.935045811, 74.73644319923926], + [510548.5851331453, 6651108.236490136, 74.15520196467426], + [510542.3156759904, 6651115.7019020775, 73.93165260623927], + [510542.4765936046, 6651118.756348984, 70.22316016523926], + [510542.51088945684, 6651119.407333405, 69.60275959223927], + [510542.47245452093, 6651118.677783244, 70.64748728523927], + [510542.33786739764, 6651116.123126786, 73.76453784923926], + [510542.300576067, 6651115.415283892, 74.64727854723927], + [510548.62027862103, 6651108.953071182, 73.84087971367425], + [510548.602144659, 6651108.58333786, 74.34041086667426], + [510542.4660280327, 6651118.55579929, 71.07379763623926], + [510542.50978674454, 6651119.386402345, 70.06835027923925], + [510542.359455929, 6651116.532908048, 73.55226004023926], + [510542.3196495099, 6651115.777325171, 74.54818305323927], + [510545.39183410944, 6651112.557737542, 74.2074521485487], + [510542.45723610825, 6651118.388915964, 71.49560649523926], + [510542.3800674989, 6651116.924145179, 73.29604691723927], + [510542.3946658478, 6651117.201242763, 73.07662791123926], + [510542.4460681509, 6651118.176932132, 71.90595603823928], + [510542.50633841596, 6651119.320948128, 70.54562123123927], + [510542.3386288826, 6651116.137580863, 74.42056029423928], + [510542.40836765827, 6651117.461322758, 72.83565826523926], + [510542.4325887524, 6651117.921073833, 72.29773573223926], + [510542.42104509607, 6651117.701958692, 72.57521759223926], + [510548.61956946005, 6651108.938612102, 74.49690215867426], + [510548.64094184496, 6651109.374373621, 74.00799447067426], + [510542.35734236403, 6651116.492789555, 74.26406900223927], + [510542.5003666178, 6651119.207594842, 71.02852225123927], + [510542.37561199267, 6651116.8395732865, 74.07886010023927], + [510542.4941558532, 6651119.089705629, 71.39022823623927], + [510548.6372418422, 6651109.298934272, 74.62452491767425], + [510545.70105395577, 6651118.631677083, 67.8111848015487], + [510542.393258546, 6651117.174530156, 73.86560776523926], + [510542.48642952903, 6651118.943048925, 71.74798608223927], + [510548.66182558425, 6651109.800172147, 74.13014759267426], + [510545.70105395577, 6651118.631677083, 67.94118480154869], + [510542.4101068586, 6651117.494335271, 73.62551931823926], + [510542.4771867225, 6651118.767607212, 72.09844229723927], + [510542.42599127715, 6651117.795844297, 73.36032159323926], + [510542.46645360976, 6651118.5638773525, 72.43818732423927], + [510542.44076091656, 6651118.076193218, 73.07222324223926], + [510542.4542843756, 6651118.332887848, 72.76385443423926], + [510548.6550018166, 6651109.661042361, 74.72362041167426], + [510548.68261217064, 6651110.223989824, 74.20882228567426], + [510545.73204817204, 6651119.240489867, 67.8111848015487], + [510545.4789604259, 6651114.269141209, 74.2074521485487], + [510548.6785599479, 6651110.14136906, 74.81278506367426], + [510548.70301921276, 6651110.64006897, 74.24656514467425], + [510545.5001407453, 6651114.685181708, 74.1697092895487], + [510545.4803420366, 6651114.296279894, 74.81644730854869], + [510558.6812516685, 6651105.195443709, 67.96754571538673], + [510548.701687929, 6651110.612925427, 74.85556030467427], + [510545.7010540747, 6651118.631679418, 69.63998846154868], + [510545.521714991, 6651115.1089600185, 74.0910345965487], + [510545.70082296786, 6651118.627139836, 69.84380974554868], + [510545.5043463986, 6651114.7677924605, 74.77367206754869], + [510545.69890399143, 6651118.589445793, 70.26038903354869], + [510545.54339007096, 6651115.534718996, 73.9688814745487], + [510558.707721616, 6651105.804469973, 67.96754571538673], + [510545.73204817204, 6651119.240489867, 69.6399884605487], + [510558.707721616, 6651105.804469973, 68.09754571538674], + [510545.6949039004, 6651118.510872854, 70.68471615354869], + [510545.5648362797, 6651115.955982302, 73.8017667175487], + [510545.5287972104, 6651115.248074547, 74.6845074155487], + [510545.6886932168, 6651118.388877721, 71.11102650454869], + [510545.73098248924, 6651119.219556888, 70.10557914754868], + [510545.58569985745, 6651116.365801115, 73.58948890854869], + [510545.54723015777, 6651115.610149001, 74.58541192154868], + [510545.6801965295, 6651118.221979103, 71.53283536354868], + [510545.6056192805, 6651116.757074094, 73.3332757855487], + [510548.78874676715, 6651112.387967932, 74.24656514467425], + [510545.6197274097, 6651117.03419707, 73.1138567795487], + [510545.6694035978, 6651118.009975847, 71.9431849065487], + [510545.7276499573, 6651119.154096671, 70.58285009954871], + [510545.56557219365, 6651115.970437704, 74.45778916254869], + [510545.6329691065, 6651117.294300898, 72.87288713354869], + [510545.65637684416, 6651117.754094101, 72.33496460054869], + [510545.6452208295, 6651117.534958883, 72.61244646054868], + [510558.6812516685, 6651105.195443709, 69.79634937438674], + [510545.58365726704, 6651116.325678945, 74.30129787054871], + [510545.7218786951, 6651119.040732999, 71.0657511195487], + [510545.6013133924, 6651116.672494453, 74.1160889685487], + [510545.7158764911, 6651118.9228329845, 71.4274571045487], + [510558.682161792, 6651105.216384027, 70.26194006138672], + [510545.6183673657, 6651117.0074820155, 73.90283663354869], + [510545.7084096208, 6651118.776162843, 71.78521495054869], + [510545.6346499035, 6651117.327316436, 73.66274818654868], + [510549.0866772323, 6651118.462471688, 67.85029779767426], + [510545.69947719225, 6651118.600705054, 72.13567116554869], + [510558.707721616, 6651105.804469973, 69.79634937438674], + [510545.65000091546, 6651117.628853091, 73.3975504615487], + [510545.6891045028, 6651118.396956524, 72.47541619254869], + [510549.0866772323, 6651118.462471688, 67.98029779767425], + [510545.664274583, 6651117.9092277, 73.10945211054869], + [510545.6773439175, 6651118.165945854, 72.80108330254869], + [510558.6850078697, 6651105.281867197, 70.73921101338674], + [510558.70852466614, 6651105.822946724, 70.20716468638673], + [510549.11653987324, 6651119.071341026, 67.85029779767426], + [510558.7110359112, 6651105.880725991, 70.62828611438673], + [510558.68993669265, 6651105.39527062, 71.22211203338674], + [510548.87269216817, 6651114.099530574, 74.24656514467425], + [510558.69506274664, 6651105.513211976, 71.58381801838674], + [510558.71538487263, 6651105.980787834, 71.05437524938675], + [510548.89309921017, 6651114.51560972, 74.20882228567426], + [510548.87402333727, 6651114.126671779, 74.85556030467427], + [510549.08667734684, 6651118.462474025, 69.67910145767426], + [510548.91388579656, 6651114.939427396, 74.13014759267426], + [510549.0864546775, 6651118.457934021, 69.88292274167425], + [510558.70143966755, 6651105.6599335475, 71.94157586438673], + [510562.25216679554, 6651105.043722797, 68.00849746456501], + [510558.721660366, 6651106.125175738, 71.47928175338673], + [510548.89715131826, 6651114.598228146, 74.81278506367426], + [510549.08460576157, 6651118.420236477, 70.29950202967426], + [510548.93476953596, 6651115.365225922, 74.00799447067426], + [510549.11653987324, 6651119.071341026, 69.67910145667426], + [510558.70906821714, 6651105.835452861, 72.29203207938674], + [510549.08075171075, 6651118.341656239, 70.72382914967427], + [510548.9554327599, 6651115.78652836, 73.84087971367425], + [510548.9207094496, 6651115.078554845, 74.72362041167426], + [510558.7298999896, 6651106.314754777, 71.89624845538673], + [510562.2774515616, 6651105.652799416, 68.00849746456501], + [510562.2774515616, 6651105.652799416, 68.138497464565], + [510549.1155130978, 6651119.050406102, 70.14469214367426], + [510549.07476777444, 6651118.219649774, 71.15013950067426], + [510548.9755346243, 6651116.19638524, 73.62860190467426], + [510548.93846942397, 6651115.4406629335, 74.62452491767425], + [510558.71792679076, 6651106.039272834, 72.63177710638674], + [510549.06658129476, 6651118.052735654, 71.57194835967425], + [510548.9947268044, 6651116.587694567, 73.37238878167427], + [510549.0083198565, 6651116.864843285, 73.15296977567425], + [510549.0561824048, 6651117.840712703, 71.98229790267426], + [510549.112302234, 6651118.984939807, 70.62196309567426], + [510548.95614180615, 6651115.8009851035, 74.49690215867426], + [510549.021078109, 6651117.124971275, 72.91200012967427], + [510549.043631248, 6651117.584807188, 72.37407759667425], + [510558.740082018, 6651106.549025084, 72.29819737238674], + [510549.032882531, 6651117.365651615, 72.65155945667426], + [510548.9735666072, 6651116.156259344, 74.34041086667426], + [510549.1067416763, 6651118.871565604, 71.10486411567426], + [510558.7279706671, 6651106.270364508, 72.95744421638673], + [510562.25216679554, 6651105.043722797, 69.83730112356503], + [510548.99057812104, 6651116.50310707, 74.15520196467426], + [510549.1009586081, 6651118.753654637, 71.46657010067428], + [510549.00700946664, 6651116.838125749, 73.94194962967426], + [510549.0937643476, 6651118.606970871, 71.82432794667427], + [510558.7521210115, 6651106.8260208415, 72.67807817438674], + [510549.02269754146, 6651117.157989879, 73.70186118267425], + [510549.0851580352, 6651118.431496782, 72.17478416167425], + [510549.0374880996, 6651117.459554546, 73.43666345767426], + [510562.2530361687, 6651105.064664846, 70.302891810565], + [510549.0751640447, 6651118.227729328, 72.51452918867426], + [510558.7391322528, 6651106.527172679, 73.26581302438673], + [510549.0512406464, 6651117.739955198, 73.14856510667427], + [510549.0638328294, 6651117.996697198, 72.84019629867427], + [510562.2774515616, 6651105.652799416, 69.83730112356503], + [510558.7622816122, 6651107.0597981345, 72.94448448938672], + [510562.25575481437, 6651105.13015343, 70.78016276256501], + [510558.7513223732, 6651106.8076456, 73.55391137538673], + [510562.2782186556, 6651105.671277695, 70.24811643556501], + [510558.7733196115, 6651107.3137628045, 73.19219422938673], + [510562.28061746055, 6651105.7290617395, 70.669237863565], + [510562.2604629512, 6651105.24356623, 71.26306378256501], + [510558.76443257666, 6651107.109287989, 73.81910910038673], + [510558.78922566114, 6651107.679732623, 73.48963669938674], + [510562.2653594882, 6651105.361517337, 71.62476976756501], + [510562.284771699, 6651105.829131857, 71.09532699856501], + [510558.7783383299, 6651107.42923456, 74.05919754738673], + [510562.27145088505, 6651105.50825104, 71.98252761356501], + [510562.29076620954, 6651105.973531698, 71.52023350256502], + [510558.8062374183, 6651108.071142804, 73.74584982238673], + [510558.792902911, 6651107.764339584, 74.27244988238674], + [510562.2787378692, 6651105.683784867, 72.332983828565], + [510562.2986369073, 6651106.163126413, 71.937200204565], + [510558.82405551075, 6651108.481105316, 73.95812763138673], + [510558.8079817474, 6651108.111276703, 74.45765878438674], + [510562.28719980374, 6651105.887621691, 72.67272885556503], + [510562.3083630394, 6651106.397416089, 72.33914912156501], + [510558.8234269176, 6651108.46664251, 74.61415007638675], + [510558.84237118665, 6651108.902516339, 74.12524238838674], + [510562.29679396946, 6651106.118732473, 72.99839596556501], + [510558.839091541, 6651108.827057547, 74.74177283538674], + [510562.31986299163, 6651106.67443475, 72.719029923565], + [510558.8608823251, 6651109.328424607, 74.24739551038674], + [510562.3074557995, 6651106.375561878, 73.306764773565], + [510558.85483380547, 6651109.189258963, 74.84086832938674], + [510562.3295686555, 6651106.908231372, 72.98543623856501], + [510558.8793073483, 6651109.752351516, 74.32607020338673], + [510562.3191001122, 6651106.65605799, 73.59486312456501], + [510562.3401124328, 6651107.162217041, 73.233145978565], + [510558.87571549846, 6651109.669709458, 74.93003298138673], + [510558.8973959472, 6651110.168537899, 74.36381306238673], + [510562.33162331133, 6651106.957725319, 73.860060849565], + [510568.6902991316, 6651104.7877660515, 68.0823226047824], + [510558.89621591044, 6651110.141387361, 74.97280822238673], + [510562.35530629515, 6651107.528217118, 73.53058844856501], + [510562.34490644, 6651107.277698344, 74.10014929656501], + [510568.71344709094, 6651105.396927622, 68.0823226047824], + [510568.71344709094, 6651105.396927622, 68.2123226047824], + [510562.3715563576, 6651107.919659661, 73.78680157156501], + [510562.35881889774, 6651107.612831075, 74.31340163156503], + [510558.97338399757, 6651111.916887354, 74.36381306238673], + [510562.388576652, 6651108.329656073, 73.99907938056501], + [510562.3732225851, 6651107.959796879, 74.49861053356501], + [510568.6902991316, 6651104.7877660515, 69.9111262637824], + [510568.69109503424, 6651104.808711022, 70.37671695078241], + [510562.38797620387, 6651108.31519207, 74.65510182556501], + [510562.4060722507, 6651108.751101937, 74.16619413756501], + [510568.71344709094, 6651105.396927622, 69.9111262637824], + [510559.23746659444, 6651117.99295671, 67.96754571538673], + [510559.23746659444, 6651117.99295671, 68.09754571538674], + [510568.6935839281, 6651104.874208739, 70.8539879027824], + [510562.40293945, 6651108.675636907, 74.782724584565], + [510568.714149358, 6651105.415408478, 70.32194157578242], + [510562.4237545603, 6651109.177045421, 74.28834725956501], + [510559.263936542, 6651118.6019829735, 67.96754571538673], + [510562.41797686066, 6651109.037868269, 74.88182007856503], + [510568.7163454409, 6651105.473200583, 70.7430630037824], + [510568.69789418206, 6651104.987637357, 71.3368889227824], + [510562.44135461026, 6651109.601007381, 74.36702195256501], + [510559.0477923649, 6651113.628891122, 74.36381306238673], + [510568.7023769143, 6651105.105604916, 71.69859490778242], + [510568.72014860605, 6651105.573284656, 71.16915213878241], + [510562.437923584, 6651109.518358491, 74.97098473056502], + [510562.45863329916, 6651110.017228177, 74.404764811565], + [510559.06588096364, 6651114.045077505, 74.32607020338673], + [510559.0489722999, 6651113.656039322, 74.97280822238673], + [510559.237466696, 6651117.992959048, 69.79634937538673], + [510568.7079535294, 6651105.252359086, 72.0563527537824], + [510568.7256365227, 6651105.717704638, 71.5940586427824], + [510559.23726932413, 6651117.988417874, 70.00017065938673], + [510559.0843059868, 6651114.469004412, 74.24739551038674], + [510562.4575060982, 6651109.990075394, 75.01375997156501], + [510559.06947271194, 6651114.127717225, 74.93003298138673], + [510559.23563046346, 6651117.950710612, 70.41674994738673], + [510559.10281712544, 6651114.894912682, 74.12524238838674], + [510568.71462469315, 6651105.427917394, 72.4068089687824], + [510559.263936542, 6651118.6019829735, 69.79634937438674], + [510568.7328420705, 6651105.907325796, 72.0110253447824], + [510559.2322142711, 6651117.872110123, 70.84107706738673], + [510559.1211328013, 6651115.316323703, 73.95812763138673], + [510559.09035440494, 6651114.60816772, 74.84086832938674], + [510559.2630264184, 6651118.581042654, 70.26194006138672], + [510559.22691016964, 6651117.750072213, 71.26738741838673], + [510559.1389508937, 6651115.726286217, 73.74584982238673], + [510568.72237151256, 6651105.631782649, 72.7465539957824], + [510559.10609666933, 6651114.970369136, 74.74177283538674], + [510559.2196537556, 6651117.583115072, 71.68919627738673], + [510559.1559626509, 6651116.117696397, 73.48963669938674], + [510568.74174625066, 6651106.14164815, 72.41297426178241], + [510559.168011397, 6651116.394916545, 73.27021769338673], + [510559.21043628315, 6651117.371037477, 72.09954582038675], + [510559.2601803408, 6651118.515559485, 70.73921101338674], + [510559.12176129286, 6651115.330784173, 74.61415007638675], + [510559.1793201849, 6651116.655111578, 73.02924804738673], + [510559.19931106275, 6651117.115066006, 72.49132551438674], + [510559.18978350697, 6651116.89585395, 72.76880737438674], + [510562.5312190145, 6651111.765722188, 74.404764811565], + [510568.7311548786, 6651105.862925665, 73.07222110578242], + [510559.13720646297, 6651115.686149979, 74.45765878438674], + [510559.2552515178, 6651118.402156062, 71.22211203338674], + [510559.1522852993, 6651116.033087098, 74.27244988238674], + [510559.2501254637, 6651118.284214707, 71.58381801838674], + [510568.7522743459, 6651106.41870545, 72.7928550637824], + [510559.16684988054, 6651116.368192124, 74.05919754738673], + [510559.2437485428, 6651118.1374931345, 71.94157586438673], + [510568.7409156812, 6651106.119790891, 73.3805899137824], + [510559.1807556337, 6651116.688138693, 73.81910910038673], + [510559.2361199933, 6651117.961973821, 72.29203207938674], + [510559.1938658371, 6651116.989781082, 73.55391137538673], + [510559.2272614197, 6651117.758153848, 72.63177710638674], + [510559.20605595765, 6651117.270254004, 73.26581302438673], + [510559.21721754334, 6651117.527062175, 72.95744421638673], + [510562.783477417, 6651117.842293931, 68.00849746456501], + [510568.7611597876, 6651106.65253468, 73.0592613787824], + [510562.783477417, 6651117.842293931, 68.138497464565], + [510568.7515759371, 6651106.400326126, 73.6686882647824], + [510568.77081251383, 6651106.906555775, 73.3069711187824], + [510562.808762183, 6651118.451370551, 68.00849746456501], + [510568.7630408052, 6651106.7020355305, 73.93388598978241], + [510562.6022957765, 6651113.47786751, 74.404764811565], + [510568.7847223483, 6651107.2726069, 73.60441358878242], + [510562.6195744654, 6651113.894088304, 74.36702195256501], + [510568.77520138124, 6651107.022053183, 74.17397443678242], + [510575.56434793817, 6651104.539443691, 68.16113549753591], + [510562.6034228804, 6651113.505017955, 75.01375997156501], + [510562.783477514, 6651117.842296268, 69.837301124565], + [510562.7832889794, 6651117.837754719, 70.04112240856502], + [510562.63717451534, 6651114.318050263, 74.28834725956501], + [510568.7995991237, 6651107.66410404, 73.86062671178242], + [510568.7879381021, 6651107.357232659, 74.38722677178241], + [510562.6230053946, 6651113.976734857, 74.97098473056502], + [510562.78172349796, 6651117.80004434, 70.45770169656501], + [510575.5852144108, 6651105.148687679, 68.16113549753591], + [510562.654856825, 6651114.743993747, 74.16619413756501], + [510575.5852144108, 6651105.148687679, 68.2911354975359], + [510562.808762183, 6651118.451370551, 69.83730112356503], + [510562.7784602643, 6651117.721437353, 70.88202881656501], + [510562.6723524237, 6651115.165439613, 73.99907938056501], + [510568.815181039, 6651108.074157636, 74.0729045207824], + [510562.64295211795, 6651114.457225078, 74.88182007856503], + [510568.80112453894, 6651107.704246856, 74.57243567378241], + [510562.8078928099, 6651118.4304285, 70.302891810565], + [510562.773393652, 6651117.59938935, 71.30833916756502], + [510562.689372718, 6651115.575436023, 73.78680157156501], + [510562.65798952867, 6651114.819456441, 74.782724584565], + [510562.76646214095, 6651117.432418406, 71.73014802656502], + [510562.70562278054, 6651115.966878566, 73.53058844856501], + [510562.7171320486, 6651116.244121635, 73.311169442565], + [510562.75765737717, 6651117.220323276, 72.14049756956501], + [510562.80517416424, 6651118.364939917, 70.78016276256501], + [510568.8146313345, 6651108.0596916145, 74.7289269657824], + [510562.67295277474, 6651115.179901279, 74.65510182556501], + [510562.72793449013, 6651116.504338183, 73.070199796565], + [510568.83119809086, 6651108.495662283, 74.24001927778241], + [510562.74703028414, 6651116.964330641, 72.53227726356502], + [510562.737929321, 6651116.745100459, 72.80975912356502], + [510575.56434793817, 6651104.539443691, 69.98993915653591], + [510562.68770639354, 6651115.535296467, 74.49861053356501], + [510562.8004660274, 6651118.2515271185, 71.26306378256501], + [510562.7021100809, 6651115.882262272, 74.31340163156503], + [510562.79556949035, 6651118.133576009, 71.62476976756501], + [510568.828330042, 6651108.420186726, 74.8565497247824], + [510575.56506539584, 6651104.560391497, 70.4555298435359], + [510568.84738607466, 6651108.921665175, 74.36217239978242], + [510562.7160225386, 6651116.217395004, 74.10014929656501], + [510562.78947809356, 6651117.986842307, 71.98252761356501], + [510575.5852144108, 6651105.148687679, 69.98993915653591], + [510562.7293056672, 6651116.5373680275, 73.860060849565], + [510562.7821911093, 6651117.811308481, 72.332983828565], + [510562.7737291749, 6651117.607471656, 72.67272885556503], + [510562.7418288664, 6651116.839035358, 73.59486312456501], + [510562.76413500914, 6651117.376360874, 72.99839596556501], + [510562.75347317907, 6651117.11953147, 73.306764773565], + [510568.84209664643, 6651108.782468611, 74.95564521878241], + [510575.56730898184, 6651104.625898075, 70.93280079553591], + [510575.5858474617, 6651105.167171037, 70.40075446853591], + [510568.8634987506, 6651109.345686267, 74.4408470927824], + [510575.5878270964, 6651105.22497096, 70.8218758965359], + [510575.57119441265, 6651104.739342039, 71.41570181553591], + [510568.8603576792, 6651109.263025849, 75.0448098707824], + [510568.8793172237, 6651109.761965115, 74.4785899517824], + [510575.57523532223, 6651104.8573255595, 71.77740780053593], + [510575.5912554177, 6651105.325068575, 71.24796503153591], + [510568.87828528194, 6651109.734808546, 75.0875851117824], + [510575.5802623003, 6651105.004099584, 72.13516564653592], + [510575.5962024395, 6651105.469508097, 71.6728715355359], + [510579.46126029454, 6651104.410116288, 68.20581012757597], + [510575.5862759473, 6651105.179681645, 72.4856218615359], + [510575.60269780125, 6651105.65915491, 72.0898382375359], + [510568.94576874573, 6651111.510703002, 74.4785899517824], + [510575.5932592322, 6651105.383574483, 72.82536688853591], + [510579.4808333877, 6651105.0194032, 68.20581012757597], + [510579.4808333877, 6651105.0194032, 68.33581012757597], + [510575.6107243761, 6651105.893508967, 72.4917871545359], + [510575.6011769008, 6651105.614748772, 73.15103399853591], + [510569.1767088793, 6651117.58812228, 68.0823226047824], + [510569.1767088793, 6651117.58812228, 68.2123226047824], + [510575.6202148115, 6651106.170603752, 72.8716679565359], + [510579.46126029454, 6651104.410116288, 70.03461378657599], + [510575.60997566854, 6651105.871648751, 73.45940280653592], + [510575.62822449487, 6651106.40446462, 73.13807427153591], + [510569.19985683874, 6651118.197283852, 68.0823226047824], + [510579.46193328174, 6651104.431065568, 70.50020447357596], + [510575.6195852386, 6651106.152221941, 73.74750115753591], + [510579.4808333877, 6651105.0194032, 70.03461378657599], + [510569.01083883556, 6651113.223087125, 74.4785899517824], + [510575.6369258386, 6651106.65852008, 73.3857840115359], + [510579.46403780207, 6651104.496576762, 70.97747542557597], + [510579.48142719985, 6651105.037887859, 70.44542909857597], + [510569.0266573085, 6651113.639365973, 74.4408470927824], + [510575.6299201175, 6651106.453972166, 74.0126988825359], + [510569.0118706883, 6651113.250241357, 75.0875851117824], + [510569.1767089682, 6651117.588124618, 69.91112626478241], + [510575.6494647054, 6651107.024620732, 73.68322648153591], + [510579.48328412964, 6651105.095691853, 70.86655052657596], + [510579.4676823998, 6651104.610028719, 71.46037644557599], + [510569.1765363666, 6651117.583582436, 70.1149475487824], + [510569.04276998446, 6651114.063387065, 74.36217239978242], + [510575.64088213467, 6651106.774033116, 74.2527873295359], + [510569.02979829104, 6651113.722024052, 75.0448098707824], + [510569.1751031835, 6651117.545866797, 70.5315268367824], + [510569.05895796826, 6651114.489389959, 74.24001927778241], + [510579.4714728392, 6651104.728020551, 71.82208243057597], + [510579.4864999512, 6651105.195796522, 71.29263966157598], + [510569.19985683874, 6651118.197283852, 69.9111262637824], + [510575.6628752105, 6651107.416170841, 73.9394396045359], + [510569.1721157246, 6651117.467248845, 70.95585395678242], + [510569.07497502014, 6651114.910894604, 74.0729045207824], + [510569.0480593238, 6651114.202581291, 74.95564521878241], + [510575.6523635112, 6651107.10925794, 74.46603966453591], + [510569.199060936, 6651118.17633888, 70.37671695078241], + [510569.1674772898, 6651117.34518382, 71.3821643077824], + [510579.476188227, 6651104.874804918, 72.17984027657597], + [510569.09055693535, 6651115.3209482, 73.86062671178242], + [510579.4911403387, 6651105.340246219, 71.71754616557598], + [510569.06182592834, 6651114.564863176, 74.8565497247824], + [510569.16113155836, 6651117.178189588, 71.8039731667824], + [510569.1054337108, 6651115.71244534, 73.60441358878242], + [510569.1530708821, 6651116.966064875, 72.21432270978241], + [510569.11597033474, 6651115.989727079, 73.3849945827824], + [510569.1965720421, 6651118.110841163, 70.8539879027824], + [510575.6769213561, 6651107.826279915, 74.1517174135359], + [510569.1258598657, 6651116.249979919, 73.14402493678242], + [510569.07552463573, 6651114.925358287, 74.7289269657824], + [510575.66425027914, 6651107.456319088, 74.65124856653591], + [510569.14334188093, 6651116.710036535, 72.6061024037824], + [510569.135010037, 6651116.490775776, 72.88358426378241], + [510579.48182912637, 6651105.050399349, 72.53029649157597], + [510569.0890314314, 6651115.280803045, 74.57243567378241], + [510569.1922617883, 6651117.997412547, 71.3368889227824], + [510579.49723309436, 6651105.529906395, 72.13451286757596], + [510569.10221786815, 6651115.627817243, 74.38722677178241], + [510569.1877790559, 6651117.879444987, 71.69859490778242], + [510575.67642583116, 6651107.811811938, 74.80773985853591], + [510575.69135975087, 6651108.247841591, 74.31883217053591], + [510569.18220244086, 6651117.732690817, 72.0563527537824], + [510569.114954589, 6651115.9629967185, 74.17397443678242], + [510579.48837956204, 6651105.254306552, 72.87004151857599], + [510569.1755312772, 6651117.557132508, 72.4068089687824], + [510569.12711516506, 6651116.283014371, 73.93388598978241], + [510569.1677844578, 6651117.353267252, 72.7465539957824], + [510569.13858003315, 6651116.584723776, 73.6686882647824], + [510569.1590010916, 6651117.122124237, 73.07222110578242], + [510569.14924028906, 6651116.86525901, 73.3805899137824], + [510579.5047621531, 6651105.764276962, 72.53646178457598], + [510575.68877437984, 6651108.172355822, 74.9353626175359], + [510575.7059522304, 6651108.67390212, 74.44098529253591], + [510579.4958064648, 6651105.485497128, 73.19570862857597], + [510575.70118413365, 6651108.534686725, 75.03445811153591], + [510579.513664337, 6651106.041391268, 72.91634258657596], + [510575.7204768243, 6651109.097980581, 74.51965998553591], + [510579.5040598531, 6651105.742415206, 73.50407743657597], + [510579.5211775512, 6651106.275268613, 73.18274890157598], + [510575.7176453402, 6651109.01530898, 75.1236227635359], + [510575.73473621235, 6651109.51431575, 74.5574028445359], + [510579.5130737873, 6651106.023008165, 73.79217578757597], + [510579.52933955414, 6651106.529341973, 73.43045864157597], + [510585.5625478138, 6651104.224263366, 68.27574991362977], + [510575.73380597995, 6651109.487155505, 75.16639800453592], + [510579.5227680729, 6651106.324779649, 74.05737351257596], + [510579.54110121663, 6651106.8954684185, 73.72790111157597], + [510585.58009589853, 6651104.833611962, 68.27574991362977], + [510585.58009589853, 6651104.833611962, 68.40574991362976], + [510579.5330506246, 6651106.644863147, 74.29746195957597], + [510579.55368049006, 6651107.287046113, 73.98411423457597], + [510579.5438203439, 6651106.980111591, 74.51071429457599], + [510575.7946382039, 6651111.263290236, 74.5574028445359], + [510585.5625478138, 6651104.224263366, 70.10455357262977], + [510579.56685600476, 6651107.697184081, 74.19639204357597], + [510579.554970327, 6651107.327197189, 74.69592319657598], + [510585.56315117446, 6651104.24521477, 70.57014425962976], + [510576.0028166402, 6651117.341531774, 68.16113549753591], + [510576.0028166402, 6651117.341531774, 68.2911354975359], + [510585.58009589853, 6651104.833611962, 70.10455357262977], + [510579.5663911942, 6651107.682715084, 74.85241448857597], + [510579.5803994555, 6651108.118775458, 74.36350680057598], + [510585.5650379637, 6651104.310732596, 71.04741521162978], + [510585.58062827564, 6651104.852098494, 70.51536888462977], + [510576.02368311293, 6651117.950775762, 68.16113549753591], + [510579.5779743351, 6651108.043284371, 74.98003724757596], + [510579.59408744023, 6651108.544866005, 74.48565992257598], + [510585.5822930897, 6651104.909908341, 70.93649031262976], + [510585.5683054958, 6651104.424196037, 71.53031623162977], + [510575.8532949188, 6651112.9759060405, 74.5574028445359], + [510579.5896148874, 6651108.4056408005, 75.07913274157599], + [510579.6077117474, 6651108.968974344, 74.56433461557597], + [510585.57170378097, 6651104.542199816, 71.89202221662977], + [510585.58517620625, 6651105.010023143, 71.36257944762977], + [510575.86755430675, 6651113.39224121, 74.51965998553591], + [510576.00281672034, 6651117.341534112, 69.9899391575359], + [510575.8542250711, 6651113.003063948, 75.16639800453592], + [510588.92990477174, 6651104.130380348, 68.31382165648704], + [510576.00266113045, 6651117.336991314, 70.1937604415359], + [510579.6050557689, 6651108.886296918, 75.16829739357598], + [510579.62108728697, 6651109.385338846, 74.60207747457596], + [510575.88207890076, 6651113.816319671, 74.44098529253591], + [510585.5759313205, 6651104.688999041, 72.24978006262978], + [510585.589336505, 6651105.154487466, 71.78748595162976], + [510575.87038571085, 6651113.474910473, 75.1236227635359], + [510576.0013692033, 6651117.299270572, 70.61033972953591], + [510575.89667138027, 6651114.242380201, 74.31883217053591], + [510576.02368311293, 6651117.950775762, 69.98993915653591], + [510579.6202147137, 6651109.358176687, 75.21107263457597], + [510588.9463352356, 6651104.739760105, 68.31382165648704], + [510585.58098861936, 6651104.86461125, 72.60023627762976], + [510575.99867619155, 6651117.220641984, 71.03466684953591], + [510575.9111097749, 6651114.663941877, 74.1517174135359], + [510588.9463352356, 6651104.739760105, 68.44382165648703], + [510575.8868469174, 6651113.955532729, 75.03445811153591], + [510585.5947989115, 6651105.344166841, 72.20445265362977], + [510576.02296565514, 6651117.9298279565, 70.4555298435359], + [510575.9944949256, 6651117.098560444, 71.46097720053591], + [510575.9251559206, 6651115.074050951, 73.9394396045359], + [510575.8992566711, 6651114.31786363, 74.9353626175359], + [510575.988774636, 6651116.9315436175, 71.8827860595359], + [510575.93856642576, 6651115.46560106, 73.68322648153591], + [510585.58686135476, 6651105.068539097, 72.93998130462977], + [510575.9815084283, 6651116.719390206, 72.29313560253591], + [510576.0207220692, 6651117.864321377, 70.93280079553591], + [510575.9480645492, 6651115.742920312, 73.4638074755359], + [510575.95697935775, 6651116.003208364, 73.2228378295359], + [510575.9116052199, 6651114.6784075145, 74.80773985853591], + [510575.9727383275, 6651116.463327226, 72.6849152965359], + [510575.9652276787, 6651116.244036801, 72.96239715653591], + [510585.601549023, 6651105.578561137, 72.60640157062977], + [510576.0168366384, 6651117.750877414, 71.41570181553591], + [510575.92378077185, 6651115.033900364, 74.65124856653591], + [510588.92990477174, 6651104.130380348, 70.14262531548704], + [510585.5935198793, 6651105.299753079, 73.26564841462977], + [510576.0127957288, 6651117.632893895, 71.77740780053593], + [510575.93566753983, 6651115.380961512, 74.46603966453591], + [510576.0077687507, 6651117.486119869, 72.13516564653592], + [510579.67727633624, 6651111.134436552, 74.60207747457596], + [510575.94714891637, 6651115.716186337, 74.2527873295359], + [510585.60953019786, 6651105.855703498, 72.98628237262976], + [510576.0017551037, 6651117.310537808, 72.4856218615359], + [510588.93046970497, 6651104.151332822, 70.60821600248704], + [510575.95811093354, 6651116.036247287, 74.0126988825359], + [510575.99477181886, 6651117.106644969, 72.82536688853591], + [510575.96844581235, 6651116.337997512, 73.74750115753591], + [510575.9868541503, 6651116.875470681, 73.15103399853591], + [510575.97805538244, 6651116.618570702, 73.45940280653592], + [510585.6009193821, 6651105.556697167, 73.57401722262978], + [510588.9463352356, 6651104.739760105, 70.14262531548704], + [510585.61626610404, 6651106.089604521, 73.25268868762976], + [510588.93223632633, 6651104.216853999, 71.08548695448704], + [510588.9468337061, 6651104.758247582, 70.55344062748705], + [510579.87255111965, 6651117.213106325, 68.20581012757597], + [510579.87255111965, 6651117.213106325, 68.33581012757597], + [510585.6090007456, 6651105.837318534, 73.86211557362977], + [510585.623583676, 6651106.343703603, 73.50039842762976], + [510588.94839248975, 6651104.816060384, 70.97456205548703], + [510588.9352957525, 6651104.330323244, 71.56838797448704], + [510579.89212421275, 6651117.822393238, 68.20581012757597], + [510585.6176920723, 6651106.139120569, 74.12731329862976], + [510588.9384776041, 6651104.448333057, 71.93009395948705], + [510588.95109198336, 6651104.916180306, 71.40065119048704], + [510585.6341284912, 6651106.709867116, 73.79784089762977], + [510579.7322972956, 6651112.847173017, 74.60207747457596], + [510585.6269108037, 6651106.459236474, 74.36740174562976], + [510588.94243589556, 6651104.595139789, 72.28785180548705], + [510592.45276433567, 6651104.0387768755, 68.35252413432214], + [510588.9549873166, 6651105.060652016, 71.82555769448703], + [510579.7456728351, 6651113.263537521, 74.56433461557597], + [510579.8725511947, 6651117.213108663, 70.03461378757596], + [510585.64540632843, 6651107.101484454, 74.05405402062976], + [510579.73316979373, 6651112.874332837, 75.21107263457597], + [510585.6365663009, 6651106.794518856, 74.58065408062977], + [510579.8724052489, 6651117.208565545, 70.23843507157598], + [510588.9471710999, 6651104.770760979, 72.63830802048703], + [510579.7592971423, 6651113.687645858, 74.48565992257598], + [510588.96010182763, 6651105.25034109, 72.24252439648703], + [510592.46802556765, 6651104.648187035, 68.35252413432214], + [510579.7483287385, 6651113.346212606, 75.16829739357598], + [510579.8711934001, 6651117.1708421465, 70.65501435957597], + [510592.46802556765, 6651104.648187035, 68.48252413432213], + [510579.772985127, 6651114.113736405, 74.36350680057598], + [510585.65721872036, 6651107.511663944, 74.26633182962978], + [510579.89212421275, 6651117.822393238, 70.03461378657599], + [510585.6465627204, 6651107.141639595, 74.76586298262978], + [510588.95266980643, 6651104.974699252, 72.97805304748704], + [510579.8686673109, 6651117.092208018, 71.07934147957597], + [510579.78652857774, 6651114.535327782, 74.19639204357597], + [510579.76376962, 6651113.826868724, 75.07913274157599], + [510588.96642203105, 6651105.484747373, 72.64447331348704], + [510579.8914512257, 6651117.801443957, 70.50020447357596], + [510579.86474521505, 6651116.970117877, 71.50565183057599], + [510579.79970409244, 6651114.94546575, 73.98411423457597], + [510585.65680199856, 6651107.497193484, 74.92235427462977], + [510579.7754101722, 6651114.189225154, 74.98003724757596], + [510585.66936098225, 6651107.933298003, 74.43344658662977], + [510579.8593794896, 6651116.803089285, 71.92746068957598], + [510588.9589042558, 6651105.205925057, 73.30372015748704], + [510579.8122833659, 6651115.337043445, 73.72790111157597], + [510592.45276433567, 6651104.0387768755, 70.18132779332214], + [510579.8893467053, 6651117.735932763, 70.97747542557597], + [510579.8525636678, 6651116.590920925, 72.33781023257598], + [510579.82119276136, 6651115.614382235, 73.50848210557596], + [510579.82955499773, 6651115.874688626, 73.26751245957597], + [510579.84433716966, 6651116.334839905, 72.72958992657598], + [510579.78699331323, 6651114.549794439, 74.85241448857597], + [510579.8372920579, 6651116.115534031, 73.00707178657598], + [510588.9738948923, 6651105.761903906, 73.02435411548703], + [510585.66718676186, 6651107.857799273, 75.04997703362976], + [510579.88570210757, 6651117.622480806, 71.46037644557599], + [510579.7984141804, 6651114.905312335, 74.69592319657598], + [510585.6816328247, 6651108.359431689, 74.55559970862977], + [510588.96583249135, 6651105.462882286, 73.61208896548705], + [510592.4532890668, 6651104.059730395, 70.64691848032213], + [510579.8819116681, 6651117.504488974, 71.82208243057597], + [510579.8095641635, 6651115.252397935, 74.51071429457599], + [510592.46802556765, 6651104.648187035, 70.18132779332214], + [510579.8771962804, 6651117.357704608, 72.17984027657597], + [510579.82033388276, 6651115.587646376, 74.29746195957597], + [510588.9802017951, 6651105.995816889, 73.29076043048704], + [510585.67762299674, 6651108.220192387, 75.14907252762977], + [510579.87155538093, 6651117.182110176, 72.53029649157597], + [510579.8306164344, 6651115.907729876, 74.05737351257596], + [510579.8650049454, 6651116.978202973, 72.87004151857599], + [510579.8403107201, 6651116.209501361, 73.79217578757597], + [510585.69384757767, 6651108.783582963, 74.63427440162977], + [510592.45492997114, 6651104.1252548415, 71.12418943232214], + [510579.85757804255, 6651116.747012397, 73.19570862857597], + [510579.8493246542, 6651116.490094319, 73.50407743657597], + [510588.9733991605, 6651105.743518001, 73.90018731648703], + [510592.46848856576, 6651104.6666754335, 70.59214310532214], + [510588.98705331795, 6651106.249928965, 73.53847017048703], + [510585.6914663834, 6651108.7008971665, 75.23823717962976], + [510585.7058393002, 6651109.199989618, 74.67201726062976], + [510592.46993642254, 6651104.724491121, 71.01326453332213], + [510592.4577716811, 6651104.238729747, 71.60709045232214], + [510588.9815369448, 6651106.04533547, 74.16538504148703], + [510588.9969265438, 6651106.616111202, 73.83591264048705], + [510585.70505700225, 6651109.17282471, 75.28101242062978], + [510592.4607271044, 6651104.356745446, 71.96879643732214], + [510592.47244381363, 6651104.824616039, 71.43935366832216], + [510588.99016854394, 6651106.365467743, 74.40547348848703], + [510592.4644037142, 6651104.503559503, 72.32655428332214], + [510592.4760619455, 6651104.969094955, 71.86426017232213], + [510589.00748610625, 6651107.007748566, 74.09212576348703], + [510588.99920909177, 6651106.700767272, 74.61872582348704], + [510592.4688019497, 6651104.679189454, 72.67701049832213], + [510592.48081249546, 6651105.158793495, 72.28122687432213], + [510589.0185461783, 6651107.417949031, 74.30440357248703], + [510589.0085688487, 6651107.047905761, 74.80393472548704], + [510585.7562150989, 6651110.949264403, 74.67201726062976], + [510596.67553794186, 6651103.937886111, 68.39739721245486], + [510592.4739093549, 6651104.883137903, 73.01675552532214], + [510592.48668293766, 6651105.393211472, 72.68317579132213], + [510589.01815599704, 6651107.403477829, 74.96042601748704], + [510589.029915111, 6651107.83960465, 74.47151832948704], + [510596.6893976416, 6651104.5473297555, 68.39739721245486], + [510585.93128699105, 6651117.028549582, 68.27574991362977], + [510592.47970014566, 6651105.114375245, 73.34242263532214], + [510596.6893976416, 6651104.5473297555, 68.52739721245487], + [510585.93128699105, 6651117.028549582, 68.40574991362976], + [510589.02787936473, 6651107.764102059, 75.08804877648703], + [510589.0414053715, 6651108.265760126, 74.59367145148704], + [510592.4936240119, 6651105.670381833, 73.06305659332213], + [510592.4861353511, 6651105.371345293, 73.65079144332213], + [510585.9488350758, 6651117.637898179, 68.27574991362977], + [510589.03765092575, 6651108.126513705, 75.18714427048704], + [510592.4994821, 6651105.904306487, 73.32946290832214], + [510589.05284217844, 6651108.6899330905, 74.67234614448704], + [510596.67553794186, 6651103.937886111, 70.22620087145486], + [510585.80554365675, 6651112.662174267, 74.67201726062976], + [510592.49316355755, 6651105.65199501, 73.93888979432214], + [510589.0506126402, 6651108.607243066, 75.27630892248703], + [510589.06407015957, 6651109.106361039, 74.71008900348703], + [510592.5058460518, 6651106.158431242, 73.57717264832213], + [510596.67601448385, 6651103.958840781, 70.69179155845485], + [510585.81753537926, 6651113.078580921, 74.63427440162977], + [510596.6893976416, 6651104.5473297555, 70.22620087145486], + [510585.9312870584, 6651117.02855192, 70.10455357362976], + [510592.50072223734, 6651105.953827537, 74.20408751932213], + [510585.80632588733, 6651112.689336835, 75.28101242062978], + [510585.9311562119, 6651117.024008343, 70.30837485762976], + [510589.06333768554, 6651109.079194741, 75.31908416348705], + [510596.6775046939, 6651104.024368827, 71.16906251045486], + [510585.8297501322, 6651113.502732197, 74.55559970862977], + [510596.68981811975, 6651104.56581917, 70.63701618345486], + [510592.51501667494, 6651106.524631746, 73.87461511832214], + [510585.8199165061, 6651113.161264378, 75.23823717962976], + [510585.9300697396, 6651116.986281125, 70.72495414562977], + [510592.50873959076, 6651106.273975783, 74.44417596632213], + [510585.8420219748, 6651113.928865881, 74.43344658662977], + [510585.9488350758, 6651117.637898179, 70.10455357262977], + [510596.6911330109, 6651104.623638035, 71.05813761145485], + [510596.6800854321, 6651104.137849968, 71.65196353045486], + [510585.92780499643, 6651116.907639035, 71.14928126562977], + [510585.8541642366, 6651114.350499939, 74.26633182962978], + [510585.8337598928, 6651113.641969157, 75.14907252762977], + [510592.52482479316, 6651106.91628865, 74.13082824132213], + [510585.9482317151, 6651117.616946777, 70.57014425962976], + [510585.92428867583, 6651116.785536534, 71.57559161662977], + [510592.51713679114, 6651106.609292039, 74.65742830132216], + [510585.8659766286, 6651114.76067943, 74.05405402062976], + [510585.8441961277, 6651114.004362272, 75.04997703362976], + [510596.68276944075, 6651104.255872153, 72.01366951545486], + [510596.6934101329, 6651104.723768453, 71.48422674645488], + [510585.9194780818, 6651116.61849103, 71.99740047562976], + [510585.8772544657, 6651115.152296768, 73.79784089762977], + [510585.9463449259, 6651117.55142895, 71.04741521162978], + [510585.9133674166, 6651116.406301191, 72.40775001862977], + [510585.88524210587, 6651115.429663638, 73.57842189162976], + [510585.89273919555, 6651115.689996381, 73.33745224562976], + [510585.90599202196, 6651116.150194245, 72.79952971262976], + [510585.8545808911, 6651114.364968063, 74.92235427462977], + [510585.899675789, 6651115.930866169, 73.07701157262977], + [510589.11123757163, 6651110.855725275, 74.71008900348703], + [510592.53509780334, 6651107.326509581, 74.34310605032213], + [510592.525830485, 6651106.956447848, 74.84263720332214], + [510585.94307739375, 6651117.437965508, 71.53031623162977], + [510596.68610840506, 6651104.4026942765, 72.37142736145486], + [510585.86482016917, 6651114.720521951, 74.76586298262978], + [510596.6966959895, 6651104.868255309, 71.90913325045486], + [510585.93967910856, 6651117.319961729, 71.89202221662977], + [510585.8748165887, 6651115.067642689, 74.58065408062977], + [510585.9354515691, 6651117.173162503, 72.24978006262978], + [510585.88447208586, 6651115.402925071, 74.36740174562976], + [510592.5347353884, 6651107.312037658, 74.99912849532215], + [510592.54565769504, 6651107.748186238, 74.51022080732214], + [510585.93039427034, 6651116.997550295, 72.60023627762976], + [510596.6901027237, 6651104.578333879, 72.72188357645487], + [510585.8936908173, 6651115.723040977, 74.12731329862976], + [510589.2751593013, 6651116.935321324, 68.31382165648704], + [510585.92452153476, 6651116.793622448, 72.93998130462977], + [510585.902382144, 6651116.024843013, 73.86211557362977], + [510585.91786301025, 6651116.562408468, 73.26564841462977], + [510585.9104635074, 6651116.305464378, 73.57401722262978], + [510589.2751593013, 6651116.935321324, 68.44382165648703], + [510596.7010102675, 6651105.057964272, 72.32609995245485], + [510592.5437668175, 6651107.67267988, 75.12675125432214], + [510596.6947410846, 6651104.782293535, 73.06162860345486], + [510592.5563302806, 6651108.174362975, 74.63237392932214], + [510589.2915897653, 6651117.54470108, 68.31382165648704], + [510596.706341591, 6651105.292395129, 72.72804886945485], + [510592.55284301034, 6651108.0351096075, 75.22584674832214], + [510596.70000007167, 6651105.013543581, 73.38729571345486], + [510592.5669532165, 6651108.598557102, 74.71104862232214], + [510589.1574244405, 6651112.56872273, 74.71008900348703], + [510596.71264522395, 6651105.56958072, 73.10792967145487], + [510592.5648823376, 6651108.515862952, 75.31501140032215], + [510589.1686524216, 6651112.985150678, 74.67234614448704], + [510592.577382187, 6651109.015005826, 74.74879148132213], + [510596.70584429265, 6651105.27052775, 73.69566452145486], + [510589.27515936433, 6651116.935323662, 70.14262531648704], + [510589.1581568515, 6651112.595886688, 75.31908416348705], + [510589.2750368514, 6651116.930779853, 70.34644660048703], + [510596.71796532796, 6651105.803518227, 73.37433598645487], + [510589.18008922855, 6651113.409323642, 74.59367145148704], + [510592.57670183765, 6651108.987838173, 75.35778664132214], + [510596.712227056, 6651105.551192887, 73.98376287245486], + [510589.1708818968, 6651113.067838362, 75.27630892248703], + [510589.27401957544, 6651116.893050705, 70.76302588848704], + [510589.19157948904, 6651113.835479118, 74.47151832948704], + [510589.2915897653, 6651117.54470108, 70.14262531548704], + [510596.72374483914, 6651106.057656946, 73.62204572645486], + [510589.27189907164, 6651116.814404594, 71.18735300848705], + [510589.20294842176, 6651114.2571347365, 74.30440357248703], + [510589.1838436113, 6651113.548567724, 75.18714427048704], + [510589.29102483205, 6651117.523748606, 70.60821600248704], + [510596.7190915758, 6651105.853041999, 74.24896059745485], + [510589.26860670216, 6651116.69229585, 71.61366335948703], + [510589.21400849376, 6651114.667335203, 74.09212576348703], + [510589.1936151723, 6651113.910979369, 75.08804877648703], + [510589.2641024903, 6651116.525241805, 72.03547221848703], + [510589.22456805623, 6651115.058972565, 73.83591264048705], + [510596.7320732677, 6651106.423877573, 73.91948819645486], + [510589.2892582107, 6651117.45822743, 71.08548695448704], + [510589.2583810076, 6651116.313041114, 72.44582176148704], + [510589.23204697116, 6651115.336353619, 73.61649363448703], + [510589.23906657833, 6651115.5966996765, 73.37552398848705], + [510589.25147534476, 6651116.056921072, 72.83760145548703], + [510589.2033385399, 6651114.2716036, 74.96042601748704], + [510589.2455613867, 6651115.837581779, 73.11508331548704], + [510596.72637264675, 6651106.173207836, 74.48904904445486], + [510589.28619878454, 6651117.344758186, 71.56838797448704], + [510592.6211930509, 6651110.764457343, 74.74879148132213], + [510589.2129256882, 6651114.627175668, 74.80393472548704], + [510589.2830169329, 6651117.226748373, 71.93009395948705], + [510589.22228544526, 6651114.974314158, 74.61872582348704], + [510596.74098064634, 6651106.815555996, 74.17570131945486], + [510589.27905864135, 6651117.079941641, 72.28785180548705], + [510589.23132599297, 6651115.309613685, 74.40547348848703], + [510596.7339986807, 6651106.508542517, 74.70230137945487], + [510589.27432343713, 6651116.904320451, 72.63830802048703], + [510589.23995759216, 6651115.62974596, 74.16538504148703], + [510589.26882473053, 6651116.700382178, 72.97805304748704], + [510589.24809537653, 6651115.931563429, 73.90018731648703], + [510589.26259028114, 6651116.469156371, 73.30372015748704], + [510589.2556620456, 6651116.212199143, 73.61208896548705], + [510592.7734497102, 6651116.844356714, 68.35252413432214], + [510592.7734497102, 6651116.844356714, 68.48252413432213], + [510596.7503102232, 6651107.225799468, 74.38797912845486], + [510596.7418939794, 6651106.855717401, 74.88751028145487], + [510592.7887109422, 6651117.453766873, 68.35252413432214], + [510596.74998109107, 6651107.21132675, 75.04400157345488], + [510596.75990033546, 6651107.647499295, 74.55509388545487], + [510592.6640931494, 6651112.477540261, 74.74879148132213], + [510596.75818310864, 6651107.571988788, 75.17162433245487], + [510596.76959279214, 6651108.073699448, 74.67724700745487], + [510592.67452212004, 6651112.893988985, 74.71104862232214], + [510592.7734497688, 6651116.844359051, 70.18132779432213], + [510592.6647734403, 6651112.504705574, 75.35778664132214], + [510596.76642577926, 6651107.934438431, 75.27071982645487], + [510592.77333597414, 6651116.839815014, 70.38514907832213], + [510596.7792401587, 6651108.497916885, 74.75592170045486], + [510592.6851450558, 6651113.318183114, 74.63237392932214], + [510592.77239108994, 6651116.802083986, 70.80172836632214], + [510592.67659294023, 6651112.976680796, 75.31501140032215], + [510592.6958176414, 6651113.744359851, 74.51022080732214], + [510592.7887109422, 6651117.453766873, 70.18132779332214], + [510596.77735946135, 6651108.415218192, 75.35988447845486], + [510596.78871137305, 6651108.914388492, 74.79366455945485], + [510592.7704214864, 6651116.72343395, 71.22605548632214], + [510592.7063775331, 6651114.166036505, 74.34310605032213], + [510592.6886322676, 6651113.457434141, 75.22584674832214], + [510592.788186211, 6651117.432813353, 70.64691848032213], + [510592.7673634099, 6651116.601319114, 71.65236583732215], + [510592.7166505433, 6651114.5762574375, 74.13082824132213], + [510596.78809350426, 6651108.887219346, 75.40265971945486], + [510592.69770846044, 6651113.819863868, 75.12675125432214], + [510592.7631797288, 6651116.434256734, 72.07417469632213], + [510592.7264586615, 6651114.96791434, 73.87461511832214], + [510592.78654530674, 6651117.367288907, 71.12418943232214], + [510592.7578654008, 6651116.222045456, 72.48452423932214], + [510592.7334053586, 6651115.245309232, 73.65519611232213], + [510592.7399254335, 6651115.505668278, 73.41422646632213], + [510592.7514511618, 6651115.965912636, 72.87630393332215], + [510592.7459580553, 6651115.7465624, 73.15378579332213], + [510592.70673988946, 6651114.180506091, 74.99912849532215], + [510592.7837035968, 6651117.253814002, 71.60709045232214], + [510592.7156447929, 6651114.5360958995, 74.84263720332214], + [510592.78074817354, 6651117.1357983025, 71.96879643732214], + [510592.7243384867, 6651114.883251709, 74.65742830132216], + [510592.77707156364, 6651116.988984244, 72.32655428332214], + [510592.7327356871, 6651115.218567966, 74.44417596632213], + [510592.7726733281, 6651116.813354294, 72.67701049832213], + [510592.74075304053, 6651115.538716211, 74.20408751932213], + [510592.7675659229, 6651116.609405844, 73.01675552532214], + [510592.7483117203, 6651115.840548739, 73.93888979432214], + [510592.7617751322, 6651116.378168503, 73.34242263532214], + [510592.75533992675, 6651116.121198455, 73.65079144332213], + [510596.8284988171, 6651110.663936135, 74.79366455945485], + [510596.96677281527, 6651116.744169581, 68.39739721245486], + [510596.96677281527, 6651116.744169581, 68.52739721245487], + [510596.98063251487, 6651117.353613226, 68.39739721245486], + [510609.1755280418, 6651103.696178987, 68.52052626257824], + [510596.867459137, 6651112.377113184, 74.79366455945485], + [510609.3450717457, 6651103.693485635, 68.52209666841532], + [510596.8769303513, 6651112.793584791, 74.75592170045486], + [510596.9667728685, 6651116.744171919, 70.22620087245485], + [510609.18523901305, 6651104.305702854, 68.52052626257824], + [510596.8680769526, 6651112.404279989, 75.40265971945486], + [510596.9666695243, 6651116.739627633, 70.43002215645485], + [510609.18523901305, 6651104.305702854, 68.65052626257824], + [510609.3547264457, 6651104.303010396, 68.52209666841532], + [510596.8865777179, 6651113.217802227, 74.67724700745487], + [510609.3547264457, 6651104.303010396, 68.65209666841531], + [510596.96581141464, 6651116.70189453, 70.84660144445486], + [510596.87881099543, 6651112.876281145, 75.35988447845486], + [510596.89627017465, 6651113.644002382, 74.55509388545487], + [510596.98063251487, 6651117.353613226, 70.22620087145486], + [510596.96402269177, 6651116.623240175, 71.27092856445486], + [510596.90586028685, 6651114.065702207, 74.38797912845486], + [510596.8897446776, 6651113.3570609065, 75.27071982645487], + [510596.980155973, 6651117.332658556, 70.69179155845485], + [510596.9612454572, 6651116.501118627, 71.69723891545486], + [510609.1755280418, 6651103.696178987, 70.34932992157825], + [510596.9151898636, 6651114.4759456795, 74.17570131945486], + [510596.8979873482, 6651113.719510548, 75.17162433245487], + [510596.95744598925, 6651116.334047068, 72.11904777445486], + [510609.3450717457, 6651103.693485635, 70.35090032741533], + [510596.9240972423, 6651114.867624102, 73.91948819645486], + [510596.97866576293, 6651117.26713051, 71.16906251045486], + [510596.9526197084, 6651116.1218241295, 72.52939731745488], + [510596.93040598166, 6651115.145034237, 73.70006919045485], + [510596.93632727815, 6651115.405407589, 73.45909954445486], + [510596.9467945282, 6651115.865677235, 72.92117701145486], + [510609.17586193676, 6651103.717136416, 70.81492060857825], + [510596.94180588744, 6651115.646314947, 73.19865887145485], + [510596.9061893658, 6651114.080172587, 75.04400157345488], + [510609.18523901305, 6651104.305702854, 70.34932992157825], + [510609.3454037059, 6651103.714443094, 70.8164910144153], + [510596.97608502477, 6651117.153649368, 71.65196353045486], + [510596.91427647736, 6651114.435781935, 74.88751028145487], + [510609.3547264457, 6651104.303010396, 70.35090032741533], + [510596.973401016, 6651117.0356271835, 72.01366951545486], + [510596.9221717761, 6651114.782956819, 74.70230137945487], + [510609.176906071, 6651103.782673088, 71.29219156057825], + [510596.9700620517, 6651116.88880506, 72.37142736145486], + [510609.1855336263, 6651104.324194701, 70.76014523357826], + [510596.9297978101, 6651115.1182915, 74.48904904445486], + [510609.3464417898, 6651103.779979862, 71.29376196641532], + [510596.9660677331, 6651116.713165458, 72.72188357645487], + [510596.937078881, 6651115.438457337, 74.24896059745485], + [510609.3550193518, 6651104.321502272, 70.76171563941531], + [510596.96142937226, 6651116.509205802, 73.06162860345486], + [510596.94394340087, 6651115.740306449, 73.98376287245486], + [510596.9561703852, 6651116.277955756, 73.38729571345486], + [510596.9503261642, 6651116.020971587, 73.69566452145486], + [510609.18645492126, 6651104.382021178, 71.18126666157823], + [510609.1787142974, 6651103.896169165, 71.77509258057825], + [510609.3559353081, 6651104.379328833, 71.1828370674153], + [510609.3482395383, 6651103.893476107, 71.77666298641533], + [510609.18059488165, 6651104.014206886, 72.13679856557826], + [510609.18805041513, 6651104.482164776, 71.60735579657825], + [510609.3501092252, 6651104.011514001, 72.13836897141532], + [510609.3575215568, 6651104.479472578, 71.60892620241532], + [510609.18293436855, 6651104.161048336, 72.49455641157826], + [510609.19035269157, 6651104.626670651, 72.03226230057824], + [510609.3524351556, 6651104.158355666, 72.49612681741532], + [510609.3598104924, 6651104.623978665, 72.03383270641532], + [510609.1857330377, 6651104.336711057, 72.84501262657824], + [510609.1933755441, 6651104.816404587, 72.44922900257824], + [510609.35521760763, 6651104.334018646, 72.84658303241531], + [510609.36281582864, 6651104.813712877, 72.4507994084153], + [510609.18898296304, 6651104.540697562, 73.18475765357825], + [510609.3584487009, 6651104.538005449, 73.18632805941533], + [510609.19711100246, 6651105.050866302, 72.85117791957825], + [510609.36652964144, 6651105.048174938, 72.85274832541532], + [510613.89348648244, 6651103.627073775, 68.5632313089762], + [510609.1926677378, 6651104.771978049, 73.51042476357824], + [510609.3621121238, 6651104.769286274, 73.51199516941531], + [510609.2015277214, 6651105.32808838, 73.23105872157824], + [510609.37092076725, 6651105.325397422, 73.23262912741531], + [510609.1967625641, 6651105.028996043, 73.81879357157825], + [510613.9016315702, 6651104.236620578, 68.5632313089762], + [510613.9016315702, 6651104.236620578, 68.69323130897621], + [510609.3661832222, 6651105.026304646, 73.82036397741531], + [510609.20525531855, 6651105.56205668, 73.49746503657823], + [510609.3746267645, 6651105.559366065, 73.49903544241532], + [510609.20123472676, 6651105.309698125, 74.10689192257824], + [510609.3706294704, 6651105.3070071405, 74.10846232841533], + [510609.20930480503, 6651105.816228851, 73.74517477657824], + [510609.37865278573, 6651105.81353861, 73.74674518241531], + [510613.89348648244, 6651103.627073775, 70.3920349679762], + [510609.2060444381, 6651105.611586971, 74.37208964757824], + [510609.37541131146, 6651105.608896428, 74.3736600534153], + [510609.2151402224, 6651106.182497685, 74.04261724657826], + [510613.8937665372, 6651103.648031992, 70.85762565497619], + [510609.38445438904, 6651106.17980798, 74.04418765241532], + [510613.9016315702, 6651104.236620578, 70.3920349679762], + [510609.2111460112, 6651105.931794952, 74.61217809457824], + [510609.38048332284, 6651105.92910488, 74.61374850041531], + [510613.89464230597, 6651103.71357113, 71.3348966069762], + [510613.90187867737, 6651104.255113122, 70.8028502799762], + [510609.22138128825, 6651106.5742276665, 74.29883036957824], + [510609.2164892869, 6651106.267173775, 74.82543042957825], + [510609.39065929037, 6651106.571538536, 74.30040077541531], + [510609.3857956364, 6651106.264484194, 74.82700083541532], + [510613.9026514145, 6651104.312941775, 71.22397170797619], + [510613.8961589578, 6651103.82707148, 71.8177976269762], + [510609.2279181725, 6651106.984525139, 74.51110817857824], + [510609.2220212264, 6651106.6143943565, 75.01063933157825], + [510609.39715829596, 6651106.98183661, 74.51267858441531], + [510609.39129552036, 6651106.611705286, 75.01220973741532], + [510613.89773629984, 6651103.945113642, 72.1795036119762], + [510613.90398963675, 6651104.413089141, 71.65006084297622], + [510609.22768756194, 6651106.970050516, 75.16713062357825], + [510609.23463760415, 6651107.406280475, 74.67822293557825], + [510613.89969854703, 6651104.091960617, 72.5372614579762], + [510609.3969290217, 6651106.967361964, 75.16870102941532], + [510609.403838791, 6651107.403592563, 74.67979334141532], + [510613.90592067357, 6651104.5576004535, 72.0749673469762], + [510609.23343440774, 6651107.330760027, 75.29475338257824], + [510609.24142874463, 6651107.832536731, 74.80037605757825], + [510613.9020459338, 6651104.267629948, 72.88771767297621], + [510609.4026425668, 6651107.328072008, 75.29632378841531], + [510609.4105905796, 6651107.829849445, 74.80194646341532], + [510613.9084560945, 6651104.747341528, 72.49193404897619], + [510609.2392097376, 6651107.693257379, 75.39384887657825], + [510609.24818829226, 6651108.256810007, 74.87905075057824], + [510609.4083844308, 6651107.69056989, 75.39541928241533], + [510613.90477181226, 6651104.471624129, 73.2274626999762], + [510609.4173109583, 6651108.254123345, 74.88062115641533], + [510613.9115892142, 6651104.981812067, 72.89388296597619], + [510609.2468705583, 6651108.174100428, 75.48301352857824], + [510609.25482441665, 6651108.673336434, 74.91679360957824], + [510613.9078624212, 6651104.702913318, 73.5531298099762], + [510609.41600086004, 6651108.171413644, 75.48458393441531], + [510609.4239086289, 6651108.6706503825, 74.91836401541532], + [510613.9152937421, 6651105.2590445755, 73.2737637679762], + [510609.25439149915, 6651108.646163712, 75.52578876957826], + [510609.42347822, 6651108.643477621, 75.52735917541531], + [510613.91129696125, 6651104.959940986, 73.8614986179762], + [510613.9184202683, 6651105.49302168, 73.5401700829762], + [510613.91504799254, 6651105.240653629, 74.1495969689762], + [510613.92181677953, 6651105.747203415, 73.7878798229762], + [510613.9190821432, 6651105.542553835, 74.41479469397619], + [510609.2827019851, 6651110.423114375, 74.91679360957824], + [510609.45162465767, 6651110.420430889, 74.91836401541532], + [510613.92671124224, 6651106.113486032, 74.0853222929762], + [510613.92336109316, 6651105.862773865, 74.6548831409762], + [510609.3795853851, 6651116.504148172, 68.52052626257824], + [510609.3795853851, 6651116.504148172, 68.65052626257824], + [510609.5479466559, 6651116.501473606, 68.52209666841532], + [510613.931945943, 6651106.505230753, 74.3415354159762], + [510609.5479466559, 6651116.501473606, 68.65209666841531], + [510613.9278427716, 6651106.198165307, 74.8681354759762], + [510609.3892963563, 6651117.11367204, 68.52052626257824], + [510609.5576013559, 6651117.110998366, 68.52209666841532], + [510613.9374287619, 6651106.915543665, 74.5538132249762], + [510613.9324826919, 6651106.545398956, 75.0533443779762], + [510609.3100000188, 6651112.1365169315, 74.91679360957824], + [510609.4787645098, 6651112.13383596, 74.91836401541532], + [510613.937235337, 6651106.901068497, 75.20983566997621], + [510613.94306469255, 6651107.337314871, 74.7209279819762], + [510609.31663614314, 6651112.553043359, 74.87905075057824], + [510609.37958542234, 6651116.504150511, 70.34932992257825], + [510609.3104328989, 6651112.163687313, 75.52578876957826], + [510609.48536218033, 6651112.550362998, 74.88062115641533], + [510609.3795130129, 6651116.499605627, 70.55315120657824], + [510609.54794669297, 6651116.501475945, 70.3509003284153], + [510609.47919488157, 6651112.161006381, 75.52735917541531], + [510609.32339569076, 6651112.977316637, 74.80037605757825], + [510613.94205551024, 6651107.261791583, 75.3374584289762], + [510609.54787470313, 6651116.496931053, 70.55472161241532], + [510613.9487607691, 6651107.763587167, 74.8430811039762], + [510609.49208255904, 6651112.9746368965, 74.80194646341532], + [510609.3789117677, 6651116.461867557, 70.96973049457824], + [510609.3179538399, 6651112.635750599, 75.48301352857824], + [510609.3892963563, 6651117.11367204, 70.34932992157825], + [510609.3301868313, 6651113.403572893, 74.67822293557825], + [510609.5472769419, 6651116.459192928, 70.97130090041533], + [510609.4866722416, 6651112.633070359, 75.48458393441531], + [510609.37765847676, 6651116.383202848, 71.39405761457826], + [510613.9468995745, 6651107.624302576, 75.4365539229762], + [510609.5576013559, 6651117.110998366, 70.35090032741533], + [510609.49883434764, 6651113.400893778, 74.67979334141532], + [510609.3369062629, 6651113.825328227, 74.51110817857824], + [510613.9544303471, 6651108.187876408, 74.9217557969762], + [510609.32561466057, 6651113.116593648, 75.39384887657825], + [510609.5460309133, 6651116.380528104, 71.39562802041532], + [510609.3889624613, 6651117.092714612, 70.81492060857825], + [510609.3757125727, 6651116.261065225, 71.82036796557824], + [510609.50551484275, 6651113.822649731, 74.51267858441531], + [510609.3434431472, 6651114.235625701, 74.29883036957824], + [510609.4942886708, 6651113.113914112, 75.39541928241533], + [510609.5572693957, 6651117.090040907, 70.8164910144153], + [510609.54409628507, 6651116.258390302, 71.82193837141531], + [510609.3730504281, 6651116.093971674, 72.24217682457824], + [510609.33138999034, 6651113.479090998, 75.29475338257824], + [510609.349684213, 6651114.627355681, 74.04261724657826], + [510609.51201384823, 6651114.232947806, 74.30040077541531], + [510609.38791832706, 6651117.027177939, 71.29219156057825], + [510613.95332509617, 6651108.105163718, 75.5257185749762], + [510613.9599964036, 6651108.60441851, 74.95949865597619], + [510609.3696688343, 6651115.881720801, 72.65252636757825], + [510609.35410450987, 6651114.904802331, 73.82319824057824], + [510609.5414495666, 6651116.091296505, 72.24374723041532], + [510609.50003053475, 6651113.476411995, 75.29632378841531], + [510609.3655873492, 6651115.625540189, 73.04430606157824], + [510609.35825334, 6651115.1652099565, 73.58222859457825], + [510609.36209199595, 6651115.406149025, 73.32178792157825], + [510609.33713683626, 6651113.8398005115, 75.16713062357825], + [510609.51821874955, 6651114.624678362, 74.04418765241532], + [510609.5562313118, 6651117.024504139, 71.29376196641532], + [510609.5380875677, 6651115.879045322, 72.65409677341532], + [510609.52261343255, 6651114.902125418, 73.82476864641532], + [510609.5340297333, 6651115.622864335, 73.04587646741531], + [510609.5267382219, 6651115.162533427, 73.58379900041531], + [510609.38611010066, 6651116.913681861, 71.77509258057825], + [510609.5305546342, 6651115.403472849, 73.32335832741532], + [510609.50574408, 6651113.837122037, 75.16870102941532], + [510609.3428031718, 6651114.195456669, 75.01063933157825], + [510609.5544335634, 6651116.911007894, 71.77666298641533], + [510609.38422951655, 6651116.795644141, 72.13679856557826], + [510613.9596332937, 6651108.577244766, 75.5684938159762], + [510609.5113775812, 6651114.192778716, 75.01220973741532], + [510609.34833511116, 6651114.542677253, 74.82543042957825], + [510609.38189002965, 6651116.64880269, 72.49455641157826], + [510609.55256387644, 6651116.792970001, 72.13836897141532], + [510609.3536783869, 6651114.8780560745, 74.61217809457824], + [510609.5168774652, 6651114.539999809, 74.82700083541532], + [510609.3790913605, 6651116.47313997, 72.84501262657824], + [510609.3587799599, 6651115.198264056, 74.37208964757824], + [510609.550237946, 6651116.646128335, 72.49612681741532], + [510609.3758414351, 6651116.269153465, 73.18475765357825], + [510609.52218977874, 6651114.875379123, 74.61374850041531], + [510609.3635896713, 6651115.500152901, 74.10689192257824], + [510609.3721566603, 6651116.0378729785, 73.51042476357824], + [510609.36806183396, 6651115.780854982, 73.81879357157825], + [510609.54745549406, 6651116.4704653565, 72.84658303241531], + [510609.5272617901, 6651115.195587574, 74.3736600534153], + [510609.54422440066, 6651116.266478554, 73.18632805941533], + [510609.5320436312, 6651115.497476861, 74.10846232841533], + [510609.54056097777, 6651116.035197727, 73.51199516941531], + [510609.53648987936, 6651115.778179355, 73.82036397741531], + [510613.98337874474, 6651110.354262293, 74.95949865597619], + [510614.0646398025, 6651116.435524915, 68.5632313089762], + [510614.0646398025, 6651116.435524915, 68.69323130897621], + [510614.0727848903, 6651117.045071719, 68.5632313089762], + [510626.23984072346, 6651103.503599185, 68.66521709454246], + [510614.0062750003, 6651112.067729325, 74.95949865597619], + [510614.01184105687, 6651112.484271425, 74.9217557969762], + [510614.06463983376, 6651116.435527254, 70.39203496897619], + [510614.006638079, 6651112.094900728, 75.5684938159762], + [510626.2438880744, 6651104.11318697, 68.66521709454246], + [510614.06457910023, 6651116.4309822, 70.59585625297619], + [510626.2438880744, 6651104.11318697, 68.79521709454245], + [510614.01751063485, 6651112.908560668, 74.8430811039762], + [510614.0640748052, 6651116.393242709, 71.0124355409762], + [510614.0129462765, 6651112.566981778, 75.5257185749762], + [510614.0727848903, 6651117.045071719, 70.3920349679762], + [510614.0232067114, 6651113.3348329635, 74.7209279819762], + [510614.063023606, 6651116.314575039, 71.4367626609762], + [510614.02884264203, 6651113.756604169, 74.5538132249762], + [510614.01937179815, 6651113.04784292, 75.4365539229762], + [510614.07250483544, 6651117.024113502, 70.85762565497619], + [510614.06139147695, 6651116.192432822, 71.8630730119762], + [510626.23984072346, 6651103.503599185, 70.49402075354247], + [510614.03432546085, 6651114.166917081, 74.3415354159762], + [510614.05915860017, 6651116.025332983, 72.28488187097619], + [510614.0242158624, 6651113.41035391, 75.3374584289762], + [510614.0395601617, 6651114.558661803, 74.0853222929762], + [510614.07162906666, 6651116.958574363, 71.3348966069762], + [510614.05632228474, 6651115.813074122, 72.69523141397622], + [510614.0432676906, 6651114.836118892, 73.86590328697619], + [510614.0528989346, 6651115.556883871, 73.08701110797621], + [510614.0467475264, 6651115.096536316, 73.6249336409762], + [510614.0499672032, 6651115.337484452, 73.36449296797619], + [510614.02903603564, 6651113.771076997, 75.20983566997621], + [510626.23997988465, 6651103.524558811, 70.95961144054245], + [510614.0701124148, 6651116.845074014, 71.8177976269762], + [510626.2438880744, 6651104.11318697, 70.49402075354247], + [510614.0337886808, 6651114.126746538, 75.0533443779762], + [510614.06853507285, 6651116.727031852, 72.1795036119762], + [510614.038428601, 6651114.4739801865, 74.8681354759762], + [510626.24041506025, 6651103.590102356, 71.43688239254246], + [510614.06657282566, 6651116.580184877, 72.5372614579762], + [510614.0429102794, 6651114.809371629, 74.6548831409762], + [510626.2440108637, 6651104.131680758, 70.90483606554245], + [510614.0642254388, 6651116.404515545, 72.88771767297621], + [510614.04718922934, 6651115.12959166, 74.41479469397619], + [510614.06149956037, 6651116.200521367, 73.2274626999762], + [510614.05122338014, 6651115.431491864, 74.1495969689762], + [510614.0584089515, 6651115.9692321755, 73.5531298099762], + [510614.05497441144, 6651115.7122045085, 73.8614986179762], + [510626.2443948422, 6651104.189513296, 71.32595749354245], + [510626.2411686951, 6651103.7036103355, 71.91978341254247], + [510626.2419524874, 6651103.821660434, 72.28148939754246], + [510626.2450598141, 6651104.289667396, 71.75204662854246], + [510629.4247079386, 6651103.4852147475, 68.68923256011365], + [510626.24292754167, 6651103.968517283, 72.63924724354246], + [510626.2460193598, 6651104.434188425, 72.17695313254247], + [510629.4276982368, 6651104.094808633, 68.68923256011365], + [510629.4276982368, 6651104.094808633, 68.81923256011363], + [510626.2440939746, 6651104.144198425, 72.98970345854245], + [510626.2472792281, 6651104.623942256, 72.59391983454245], + [510626.24544848263, 6651104.348206319, 73.32944848554247], + [510626.2488360972, 6651104.858428558, 72.99586875154245], + [510629.4247079386, 6651103.4852147475, 70.51803621911364], + [510626.2469842277, 6651104.579511059, 73.65511559554245], + [510631.1135923384, 6651103.4777066065, 68.7015861260573], + [510629.4248107548, 6651103.506174582, 70.98362690611363], + [510626.2506769029, 6651105.135679706, 73.37574955354245], + [510629.4276982368, 6651104.094808633, 70.51803621911364], + [510626.2486908746, 6651104.836556006, 73.96348440354245], + [510629.4251322749, 6651103.571718783, 71.46089785811365], + [510631.1160220983, 6651104.087302984, 68.7015861260573], + [510626.25223049556, 6651105.369672542, 73.64215586854246], + [510629.42778895696, 6651104.113302606, 70.92885153111364], + [510631.1160220983, 6651104.087302984, 68.83158612605729], + [510626.2505547882, 6651105.117287523, 74.25158275454245], + [510629.4280726512, 6651104.171135723, 71.34997295911364], + [510629.4256890819, 6651103.6852279, 71.94379887811364], + [510626.2539182457, 6651105.623871366, 73.88986560854245], + [510626.2525593859, 6651105.419208026, 74.51678047954245], + [510629.4262681699, 6651103.80327918, 72.30550486311364], + [510629.4285639514, 6651104.271290826, 71.77606209411364], + [510631.1135923384, 6651103.4777066065, 70.5303897850573], + [510626.2563503383, 6651105.990178609, 74.18730807854246], + [510626.25468562596, 6651105.739449585, 74.75686892654245], + [510629.42698856787, 6651103.950137498, 72.66326270911364], + [510631.1136758815, 6651103.498666528, 70.99598047205728], + [510629.4292728911, 6651104.415813303, 72.20096859811363], + [510631.1160220983, 6651104.087302984, 70.5303897850573], + [510626.2589514977, 6651106.381949667, 74.44352120154245], + [510629.4278503617, 6651104.125820398, 73.01371892411363], + [510631.1139371319, 6651103.564210997, 71.4732514240573], + [510626.2569126032, 6651106.074863577, 74.97012126154247], + [510631.1160958128, 6651104.105797033, 70.9412050970573], + [510629.4302037177, 6651104.605569031, 72.61793530011364], + [510626.26167594857, 6651106.792290165, 74.65579901054245], + [510629.42885111074, 6651104.3298303345, 73.35346395111364], + [510631.11632632784, 6651104.163630388, 71.36232652505728], + [510626.25921821187, 6651106.422120571, 75.15533016354246], + [510631.11438956414, 6651103.6777205765, 71.9561524440573], + [510629.43135397695, 6651104.840057681, 73.01988421711363], + [510631.1148601008, 6651103.795772339, 72.3178584290573], + [510631.11672553275, 6651104.2637859, 71.7884156600573], + [510629.429985763, 6651104.561137389, 73.67913106111364], + [510626.2615798344, 6651106.777814023, 75.31182145554246], + [510626.2644764818, 6651107.214089728, 74.82291376754246], + [510629.43271401664, 6651105.117311604, 73.39976501911363], + [510631.11544545845, 6651103.942631259, 72.6756162750573], + [510626.2639750121, 6651107.138561362, 75.43944421454245], + [510631.1173015801, 6651104.408308966, 72.21332216405729], + [510629.43124668236, 6651104.818184911, 73.98749986911363], + [510626.26730690204, 6651107.640390683, 74.94506688954246], + [510629.43386185524, 6651105.351306782, 73.66617133411366], + [510631.1161457071, 6651104.118314878, 73.02607249005729], + [510626.2663820614, 6651107.501096726, 75.53853970854247], + [510631.11805792106, 6651104.598065472, 72.63028886605728], + [510626.2701241548, 6651108.06470845, 75.02374158254247], + [510629.4326237949, 6651105.098919239, 74.27559822011365], + [510629.4351088131, 6651105.6055081505, 73.91388107411363], + [510631.1169588634, 6651104.322325647, 73.3658175170573], + [510626.26957494795, 6651107.981990198, 75.62770436054247], + [510626.2728899672, 6651108.481278556, 75.06148444154246], + [510629.4341048487, 6651105.400842763, 74.54079594511363], + [510631.11899256153, 6651104.832555079, 73.0322377830573], + [510629.43690571235, 6651105.971819059, 74.21132354411364], + [510631.1178808225, 6651104.553633648, 73.6914846270573], + [510626.27270953526, 6651108.454102986, 75.67047960154245], + [510629.43567577546, 6651105.721087527, 74.78088439211363], + [510631.1200976588, 6651105.109810137, 73.41211858505729], + [510631.1189053796, 6651104.81068222, 73.99985343505729], + [510629.438827523, 6651106.363594039, 74.46753666711363], + [510629.4373211297, 6651106.056504875, 74.99413672711364], + [510631.1210303323, 6651105.3438062705, 73.67852490005728], + [510631.12002434925, 6651105.091417694, 74.28795178605729], + [510629.440840425, 6651106.773938647, 74.67981447611365], + [510629.4390245791, 6651106.403765346, 75.17934562911366], + [510631.12204354507, 6651105.598008678, 73.9262346400573], + [510626.2845088155, 6651110.231239986, 75.06148444154246], + [510631.12122777617, 6651105.393342453, 74.5531495110573], + [510629.44076941314, 6651106.75946236, 75.33583692111364], + [510629.4429095387, 6651107.19574243, 74.84692923311364], + [510626.32488800184, 6651116.312911464, 68.66521709454246], + [510631.1235036115, 6651105.964321085, 74.22367711005731], + [510626.32488800184, 6651116.312911464, 68.79521709454245], + [510631.122504229, 6651105.7135885265, 74.7932379580573], + [510629.4425390386, 6651107.120213309, 75.46345968011363], + [510629.4450007338, 6651107.622047652, 74.96908235511364], + [510626.32893535285, 6651116.922499247, 68.66521709454246], + [510631.12506517424, 6651106.356097667, 74.4798902330573], + [510629.4443174352, 6651107.482752302, 75.56255517411364], + [510631.1238411578, 6651106.049007246, 75.0064902930573], + [510629.44708220044, 6651108.046369667, 75.04775704811364], + [510626.29588612466, 6651111.9448222155, 75.06148444154246], + [510631.1267007531, 6651106.766443949, 74.69216804205729], + [510631.12522529176, 6651106.396269136, 75.1916991950573], + [510629.4466764307, 6651107.963650586, 75.65171982611363], + [510629.4491256614, 6651108.462943942, 75.08549990711363], + [510626.29865193693, 6651112.361392322, 75.02374158254247], + [510626.3248880174, 6651116.3129138015, 70.49402075454245], + [510626.29606654093, 6651111.971995447, 75.67047960154245], + [510626.32485783857, 6651116.308368442, 70.69784203854246], + [510631.1266430526, 6651106.751967603, 75.3481904870573], + [510631.1283820068, 6651107.188249458, 74.85928279905731], + [510629.44899235317, 6651108.4357680995, 75.69449506711364], + [510626.30146918976, 6651112.78571009, 74.94506688954246], + [510626.3246072508, 6651116.270626414, 71.11442132654247], + [510626.2992011283, 6651112.444108235, 75.62770436054247], + [510626.32893535285, 6651116.922499247, 70.49402075354247], + [510631.12808095774, 6651107.1127200285, 75.47581324605729], + [510626.30429960997, 6651113.212011044, 74.82291376754246], + [510631.13008120254, 6651107.614556422, 74.98143592105731], + [510626.3240849026, 6651116.191953456, 71.53874844654246], + [510626.30710014317, 6651113.633810608, 74.65579901054245], + [510626.3023940148, 6651112.925001705, 75.53853970854247], + [510626.3287961916, 6651116.901539621, 70.95961144054245], + [510626.3232738862, 6651116.0698030265, 71.96505879754247], + [510631.1295259898, 6651107.475260503, 75.5749087400573], + [510626.3098245941, 6651114.044151105, 74.44352120154245], + [510631.1317724935, 6651108.038880172, 75.0601106140573], + [510626.32216435426, 6651115.902691952, 72.38686765654246], + [510626.30480106414, 6651113.28753707, 75.43944421454245], + [510626.3124257535, 6651114.435922164, 74.18730807854246], + [510626.328361016, 6651116.835996076, 71.43688239254246], + [510626.32075496926, 6651115.690418822, 72.79721719954246], + [510626.3142680504, 6651114.713397908, 73.96788907254245], + [510626.31905388273, 6651115.434211346, 73.18899689354245], + [510626.3159972051, 6651114.973832841, 73.72691942654245], + [510626.3175970849, 6651115.2147971755, 73.46647875354245], + [510629.4577099976, 6651110.212922889, 75.08549990711363], + [510626.3071962418, 6651113.648284409, 75.31182145554246], + [510626.3276073811, 6651116.722488096, 71.91978341254247], + [510631.13144278625, 6651107.956160753, 75.66407339205729], + [510631.13343290304, 6651108.455456151, 75.09785347305728], + [510626.3095578643, 6651114.003977861, 75.15533016354246], + [510626.32682358887, 6651116.6044379985, 72.28148939754246], + [510626.31186347303, 6651114.351234855, 74.97012126154247], + [510626.3258485345, 6651116.457581149, 72.63924724354246], + [510629.48754329083, 6651116.294655242, 68.68923256011365], + [510626.3140904503, 6651114.686648847, 74.75686892654245], + [510629.48754329083, 6651116.294655242, 68.81923256011363], + [510626.32468210167, 6651116.281900008, 72.98970345854245], + [510631.13332458364, 6651108.428280197, 75.70684863305729], + [510626.31621669047, 6651115.006890406, 74.51678047954245], + [510626.3233275936, 6651116.0778921135, 73.32944848554247], + [510626.31822128803, 6651115.308810909, 74.25158275454245], + [510626.3217918486, 6651115.846587373, 73.65511559554245], + [510626.32008520165, 6651115.589542426, 73.96348440354245], + [510629.4905335889, 6651116.904249128, 68.68923256011365], + [510629.4661158777, 6651111.926522272, 75.08549990711363], + [510631.14040808566, 6651110.205442251, 75.09785347305728], + [510629.4681593386, 6651112.343096547, 75.04775704811364], + [510629.4875433023, 6651116.294657581, 70.51803622011363], + [510629.46624917444, 6651111.953695774, 75.69449506711364], + [510629.48752100527, 6651116.290112174, 70.72185750411363], + [510631.1646490596, 6651116.287199465, 68.7015861260573], + [510629.47024080524, 6651112.767418562, 74.96908235511364], + [510631.1646490596, 6651116.287199465, 68.83158612605729], + [510629.4873358639, 6651116.25236977, 71.13843679211364], + [510629.4685650968, 6651112.425813288, 75.65171982611363], + [510629.4905335889, 6651116.904249128, 70.51803621911364], + [510629.47233200027, 6651113.193723784, 74.84692923311364], + [510629.4869499381, 6651116.173696023, 71.56276391211364], + [510631.1670788195, 6651116.896795843, 68.7015861260573], + [510629.4744011141, 6651113.615527568, 74.67981447611365], + [510629.47092409234, 6651112.906711572, 75.56255517411364], + [510629.4904307727, 6651116.8832892915, 70.98362690611363], + [510629.4863507362, 6651116.05154437, 71.98907426311364], + [510629.476414016, 6651114.025872175, 74.46753666711363], + [510629.4855309823, 6651115.884431624, 72.41088312211363], + [510629.47270248894, 6651113.269250565, 75.46345968011363], + [510643.1356416159, 6651103.469133594, 68.78188541270163], + [510629.4783358266, 6651114.417647155, 74.21132354411364], + [510629.49010925257, 6651116.817745091, 71.46089785811365], + [510629.48448968853, 6651115.672156369, 72.82123266511364], + [510629.4796969681, 6651114.695125677, 73.99190453811364], + [510629.4832328774, 6651115.415946329, 73.21301235911363], + [510629.4809745169, 6651114.955563216, 73.75093489211363], + [510629.48215655365, 6651115.196529962, 73.49049421911363], + [510631.1472382642, 6651111.919048638, 75.09785347305728], + [510629.4744721144, 6651113.630001515, 75.33583692111364], + [510629.4895524457, 6651116.704235976, 71.94379887811364], + [510629.4762169484, 6651113.985698529, 75.17934562911366], + [510629.4889733576, 6651116.586184695, 72.30550486311364], + [510643.1340812753, 6651104.0787328165, 68.78188541270163], + [510631.14889867377, 6651112.335624617, 75.0601106140573], + [510631.16464906896, 6651116.287201805, 70.53038978605728], + [510629.4779203979, 6651114.332958998, 74.99413672711364], + [510643.1340812753, 6651104.0787328165, 68.91188541270164], + [510629.4882529597, 6651116.439326376, 72.66326270911364], + [510631.14734657423, 6651111.946222252, 75.70684863305729], + [510629.47956575215, 6651114.668376348, 74.78088439211363], + [510631.16463095153, 6651116.282656379, 70.73421107005728], + [510629.48739116587, 6651116.263643475, 73.01371892411363], + [510629.48113667883, 6651114.988621112, 74.54079594511363], + [510629.48639041674, 6651116.059633539, 73.35346395111364], + [510631.1505899647, 6651112.759948367, 74.98143592105731], + [510629.48261773266, 6651115.290544637, 74.27559822011365], + [510629.4852557645, 6651115.828326484, 73.67913106111364], + [510629.4839948451, 6651115.571278964, 73.98749986911363], + [510631.1644805153, 6651116.244913819, 71.1507903580573], + [510631.14922837156, 6651112.418341696, 75.66407339205729], + [510631.1670788195, 6651116.896795843, 70.5303897850573], + [510631.15228916047, 6651113.186255332, 74.85928279905731], + [510631.16416693234, 6651116.1662397515, 71.5751174780573], + [510631.153970414, 6651113.6080608405, 74.69216804205729], + [510643.1356416159, 6651103.469133594, 70.61068907170163], + [510631.16699527646, 6651116.875835921, 70.99598047205728], + [510631.15114516806, 6651112.899241946, 75.5749087400573], + [510631.1636800521, 6651116.0440876, 72.00142782905729], + [510631.15560599294, 6651114.018407123, 74.4798902330573], + [510631.16301396297, 6651115.87697417, 72.42323668805729], + [510631.1525902001, 6651113.261782422, 75.47581324605729], + [510631.15716755576, 6651114.410183704, 74.22367711005731], + [510631.166734026, 6651116.810291452, 71.4732514240573], + [510631.1621678622, 6651115.664698048, 72.8335862310573], + [510643.1355879663, 6651103.490093613, 71.07627975870162], + [510631.15827354806, 6651114.6876633605, 74.00425810405729], + [510631.1611466431, 6651115.40848696, 73.22536592505729], + [510631.1593116174, 6651114.948101965, 73.76328845805729], + [510631.1602720787, 6651115.189069697, 73.50284778505731], + [510631.15402810526, 6651113.622534845, 75.3481904870573], + [510643.1340812753, 6651104.0787328165, 70.61068907170163], + [510631.16628159373, 6651116.696781872, 71.9561524440573], + [510631.1554458661, 6651113.978233313, 75.1916991950573], + [510631.16581105714, 6651116.57873011, 72.3178584290573], + [510643.13542019675, 6651103.555638387, 71.55355071070163], + [510631.15683000005, 6651114.325495202, 75.0064902930573], + [510643.13403393736, 6651104.097226952, 71.02150438370163], + [510631.1652256994, 6651116.431871191, 72.6756162750573], + [510631.1581669288, 6651114.660913923, 74.7932379580573], + [510631.16452545085, 6651116.256187573, 73.02607249005729], + [510631.1594433817, 6651114.981159996, 74.5531495110573], + [510631.1637122944, 6651116.0521768015, 73.3658175170573], + [510631.1606468086, 6651115.283084755, 74.28795178605729], + [510631.16279033537, 6651115.820868801, 73.6914846270573], + [510631.1617657782, 6651115.563820231, 73.99985343505729], + [510643.1338859055, 6651104.155060575, 71.44262581170162], + [510643.1351296543, 6651103.669148497, 72.03645173070163], + [510643.1348274856, 6651103.78720081, 72.39815771570163], + [510643.13362954446, 6651104.255216556, 71.86871494670164], + [510643.1344515812, 6651103.934060415, 72.75591556170163], + [510643.13325961906, 6651104.399740296, 72.29362145070162], + [510643.1340018963, 6651104.109744854, 73.10637177670164], + [510643.13277391274, 6651104.589497688, 72.71058815270162], + [510643.1334797045, 6651104.313756577, 73.44611680370163], + [510643.13217370637, 6651104.823988391, 73.11253706970165], + [510643.13288764184, 6651104.545065657, 73.77178391370163], + [510643.1314640363, 6651105.101244741, 73.49241787170163], + [510643.13222969277, 6651104.802115428, 74.08015272170162], + [510648.33434174245, 6651103.489797736, 68.81246166369984], + [510643.130865093, 6651105.335241968, 73.75882418670162], + [510643.1315111141, 6651105.082852214, 74.36825107270163], + [510648.33105596085, 6651104.099390101, 68.81246166369984], + [510643.1302144291, 6651105.589445562, 74.00653392670162], + [510648.33105596085, 6651104.099390101, 68.94246166369982], + [510643.1307382987, 6651105.384778381, 74.63344879770162], + [510643.1292768052, 6651105.955759678, 74.30397639670163], + [510643.1299185876, 6651105.705025951, 74.87353724470162], + [510649.6749830265, 6651103.497513266, 68.81994054909241], + [510648.33434174245, 6651103.489797736, 70.64126532269984], + [510643.12827400246, 6651106.347538088, 74.56018951970162], + [510648.33422876644, 6651103.510757518, 71.10685600969981], + [510643.1290600401, 6651106.040446236, 75.08678957970163], + [510649.6712522881, 6651104.10710307, 68.81994054909241], + [510648.33105596085, 6651104.099390101, 70.64126532269984], + [510649.6712522881, 6651104.10710307, 68.9499405490924], + [510648.3338754756, 6651103.576301555, 71.58412696169982], + [510643.1272236682, 6651106.757886288, 74.77246732870162], + [510643.12817117845, 6651106.387709746, 75.27199848170163], + [510648.3309562763, 6651104.117884026, 71.05208063469982], + [510648.330644549, 6651104.175717, 71.47320206269981], + [510648.33326364844, 6651103.689810388, 72.06702798169984], + [510643.1272607223, 6651106.743409874, 75.42848977370164], + [510643.12614400254, 6651107.179693764, 74.93958208570163], + [510649.6749830265, 6651103.497513266, 70.64874420809241], + [510648.33262733836, 6651103.807861374, 72.42873396669982], + [510648.33010470145, 6651104.275871852, 71.89929119769982], + [510643.12633733, 6651107.104163982, 75.55611253270163], + [510649.67485475144, 6651103.518472962, 71.1143348950924], + [510643.1250528149, 6651107.606002719, 75.06173520770163], + [510649.6712522881, 6651104.10710307, 70.64874420809241], + [510648.331835755, 6651103.9547193255, 72.78649181269982], + [510643.12540936074, 6651107.466706149, 75.65520802670163], + [510648.3293257086, 6651104.420393968, 72.32419770169982], + [510649.67445361835, 6651103.584016724, 71.59160584709242], + [510643.12396670354, 6651108.030328449, 75.14040990070163], + [510649.6711391042, 6651104.12559692, 71.0595595200924], + [510648.3308888039, 6651104.130401788, 73.13694802769982], + [510648.3283029032, 6651104.610149223, 72.74116440369981], + [510643.1241784345, 6651107.947608644, 75.74437267870162], + [510643.1229004235, 6651108.446906372, 75.17815275970162], + [510649.67078516324, 6651104.18342965, 71.48068094809241], + [510649.67375893815, 6651103.697525079, 72.07450686709241], + [510648.3297891667, 6651104.334411216, 73.47669305469984], + [510649.67303645966, 6651103.81557557, 72.43621285209241], + [510649.67017221014, 6651104.283584083, 71.90677008309241], + [510643.1229699839, 6651108.419730292, 75.78714791970162], + [510648.3270389823, 6651104.844637289, 73.14311332069983], + [510648.328542395, 6651104.565717693, 73.80236016469982], + [510649.67213768105, 6651103.962432904, 72.79397069809241], + [510649.6692877269, 6651104.42810559, 72.3316765870924], + [510648.3255445516, 6651105.12189052, 73.52299412269981], + [510648.32715687907, 6651104.822764572, 74.11072897269982], + [510649.67106249486, 6651104.138114629, 73.1444269130924], + [510649.6681264144, 6651104.617860049, 72.74864328909241], + [510648.3242832905, 6651105.355885114, 73.78940043769981], + [510643.1184211083, 6651110.19690064, 75.17815275970162], + [510649.669813946, 6651104.3421232, 73.48417194009241], + [510648.3256436886, 6651105.103498199, 74.39882732369983], + [510648.3229131157, 6651105.610085848, 74.03711017769982], + [510649.66669133474, 6651104.852347129, 73.1505922060924], + [510643.1028540657, 6651116.278686242, 68.78188541270163], + [510643.1028540657, 6651116.278686242, 68.91188541270164], + [510649.6683983378, 6651104.573428706, 73.8098390500924], + [510648.3240162858, 6651105.40542097, 74.66402504869981], + [510649.66499452986, 6651105.129599195, 73.5304730080924], + [510648.3209386576, 6651105.976395843, 74.33455264769982], + [510643.10129372514, 6651116.888285465, 68.78188541270163], + [510649.6668251969, 6651104.830474504, 74.1182078580924], + [510648.3222901295, 6651105.725664936, 74.90411349569982], + [510649.6635624702, 6651105.363592806, 73.79687932309243], + [510648.31882694515, 6651106.368169847, 74.59076577069982], + [510643.11403491156, 6651111.910515026, 75.17815275970162], + [510649.66510709183, 6651105.1112069525, 74.4063062090924], + [510648.3204821912, 6651106.061081448, 75.11736583069982], + [510649.66200674785, 6651105.617792473, 74.0445890630924], + [510643.1028540597, 6651116.278688582, 70.61068907270162], + [510643.1129686315, 6651112.32709295, 75.14040990070163], + [510648.3166151402, 6651106.778513428, 74.80304357969982], + [510643.1028656944, 6651116.274143135, 70.81451035670162], + [510643.11396535713, 6651111.937688768, 75.78714791970162], + [510649.6632593081, 6651105.413128455, 74.6715039340924], + [510648.3186104172, 6651106.408341051, 75.30257473269982], + [510643.11188252014, 6651112.75141868, 75.06173520770163], + [510649.6597649108, 6651105.9841009285, 74.34203153309241], + [510643.1029623013, 6651116.236400399, 71.23108964470163], + [510643.10129372514, 6651116.888285465, 70.61068907170163], + [510643.11275690654, 6651112.4098104155, 75.74437267870162], + [510643.11079133244, 6651113.177727635, 74.93958208570163], + [510648.31669316906, 6651106.764037178, 75.45906602469982], + [510648.3143415691, 6651107.200316159, 74.97015833669982], + [510649.6612993976, 6651105.733371076, 74.9115923810924], + [510643.10316367773, 6651116.157725964, 71.65541676470163], + [510643.1097116668, 6651113.599535111, 74.77246732870162], + [510643.10134737473, 6651116.867325446, 71.07627975870162], + [510643.11152598023, 6651112.89071291, 75.65520802670163], + [510643.10347634193, 6651116.035573242, 72.08172711570163], + [510649.65736723255, 6651106.375873286, 74.5982446560924], + [510648.31474867975, 6651107.124787226, 75.58668878369981], + [510643.1086613325, 6651114.009883311, 74.56018951970162], + [510648.3120437346, 6651107.626620318, 75.09231145869983], + [510649.6592466303, 6651106.068786178, 75.12484471609241], + [510643.10390409036, 6651115.868459034, 72.50353597470162], + [510643.11059801106, 6651113.253255077, 75.55611253270163], + [510643.1015151443, 6651116.801780672, 71.55355071070163], + [510643.10765852977, 6651114.401661721, 74.30397639670163], + [510643.10444743844, 6651115.656181919, 72.91388551770164], + [510643.10694828484, 6651114.679142673, 74.08455739070162], + [510643.10510324384, 6651115.399969636, 73.30566521170162], + [510643.1062816586, 6651114.939582491, 73.84358774470162], + [510643.1056648706, 6651115.180551348, 73.58314707170163], + [510643.10967461875, 6651113.614009186, 75.42848977370164], + [510648.31279455265, 6651107.487325315, 75.68578427769984], + [510643.1018056867, 6651116.688270561, 72.03645173070163], + [510649.65485590755, 6651106.786215144, 74.81052246509242], + [510648.3097565898, 6651108.050941274, 75.17098615169984], + [510649.65712138265, 6651106.416044324, 75.31005361809243], + [510643.1087641626, 6651113.969709313, 75.27199848170163], + [510643.10210785543, 6651116.570218248, 72.39815771570163], + [510643.1078753009, 6651114.316972823, 75.08678957970163], + [510643.1024837598, 6651116.423358643, 72.75591556170163], + [510643.1070167535, 6651114.652393108, 74.87353724470162], + [510643.1029334447, 6651116.247674204, 73.10637177670164], + [510648.31020245526, 6651107.968222399, 75.77494892969982], + [510648.30751120637, 6651108.46751451, 75.20872901069983], + [510643.1061970423, 6651114.972640678, 74.63344879770162], + [510649.65494450304, 6651106.771738955, 75.46654491009241], + [510643.10345563653, 6651116.043662482, 73.44611680370163], + [510649.65227445186, 6651107.208016104, 74.97763722209241], + [510643.1054242269, 6651115.274566845, 74.36825107270163], + [510643.1040476992, 6651115.812353401, 73.77178391370163], + [510643.10470564826, 6651115.55530363, 74.08015272170162], + [510648.3076576872, 6651108.440338735, 75.81772417069982], + [510649.65273669304, 6651107.132487488, 75.5941676690924], + [510649.64966544724, 6651107.634318471, 75.09979034409241], + [510649.6505179403, 6651107.495024054, 75.69326316309241], + [510649.64706858, 6651108.058637645, 75.17846503709241], + [510649.647574824, 6651107.975919119, 75.7824278150924], + [510649.644519129, 6651108.475209132, 75.2162078960924], + [510648.29807861743, 6651110.21748909, 75.20872901069983], + [510649.6446854463, 6651108.448033472, 75.8252030560924], + [510648.26529737655, 6651116.299206267, 68.81246166369984], + [510648.26529737655, 6651116.299206267, 68.94246166369982], + [510648.26201159507, 6651116.908798631, 68.81246166369984], + [510660.03104468284, 6651103.590091781, 68.87210162289652], + [510649.6338091894, 6651110.2251763595, 75.2162078960924], + [510648.2888421186, 6651111.931084196, 75.20872901069983], + [510660.02387678274, 6651104.199650858, 68.87210162289652], + [510660.02387678274, 6651104.199650858, 69.0021016228965], + [510649.5965887496, 6651116.306867989, 68.81994054909241], + [510648.265297364, 6651116.299208607, 70.64126532369981], + [510648.28659673495, 6651112.347657433, 75.17098615169984], + [510649.5965887496, 6651116.306867989, 68.9499405490924], + [510648.2653218642, 6651116.294663211, 70.84508660769983], + [510648.28869565023, 6651111.958257632, 75.81772417069982], + [510648.2843095903, 6651112.771978389, 75.09231145869983], + [510648.26552530023, 6651116.2569209, 71.26166589569984], + [510649.5928580111, 6651116.916457793, 68.81994054909241], + [510648.26201159507, 6651116.908798631, 70.64126532269984], + [510648.2861508822, 6651112.430373968, 75.77494892969982], + [510648.28201175586, 6651113.198282547, 74.97015833669982], + [510648.2659493608, 6651116.17824735, 71.68599301569982], + [510660.03104468284, 6651103.590091781, 70.70090528189651], + [510648.2797381846, 6651113.6200852785, 74.80304357969982], + [510648.26212457096, 6651116.887838849, 71.10685600969981], + [510648.2835587848, 6651112.911271052, 75.68578427769984], + [510648.26660777227, 6651116.056096002, 72.11230336669982], + [510649.6233218942, 6651111.938764268, 75.2162078960924], + [510648.2775263798, 6651114.03042886, 74.59076577069982], + [510660.03079822694, 6651103.6110504195, 71.1664959688965], + [510648.2675085293, 6651115.888983673, 72.53411222569983], + [510648.28160465776, 6651113.27380914, 75.58668878369981], + [510648.26247786183, 6651116.822294813, 71.58412696169982], + [510648.27541466727, 6651114.422202865, 74.33455264769982], + [510648.2686527175, 6651115.676708948, 72.94446176869982], + [510660.02387678274, 6651104.199650858, 70.70090528189651], + [510648.2739190259, 6651114.6996806925, 74.11513364169983], + [510648.27003371925, 6651115.420499547, 73.33624146269982], + [510648.27251523745, 6651114.960117582, 73.87416399569982], + [510648.27121639886, 6651115.201083728, 73.61372332269983], + [510649.59658873524, 6651116.306870329, 70.6487442090924], + [510648.2796601684, 6651113.634559189, 75.45906602469982], + [510649.6207724433, 6651112.355335754, 75.17846503709241], + [510648.2630896891, 6651116.708785978, 72.06702798169984], + [510649.5966165533, 6651116.302324953, 70.8525654930924], + [510660.0300275265, 6651103.676590877, 71.64376692089652], + [510649.6231555913, 6651111.965937588, 75.8252030560924], + [510648.2777429203, 6651113.990255317, 75.30257473269982], + [510660.0236593216, 6651104.218143773, 71.11172059389651], + [510648.2637259991, 6651116.590734993, 72.42873396669982], + [510649.61817557603, 6651112.7796549285, 75.09979034409241], + [510648.27587114624, 6651114.337514919, 75.11736583069982], + [510648.26451758243, 6651116.44387704, 72.78649181269982], + [510649.5968475383, 6651116.2645828, 71.26914478109241], + [510648.27406320797, 6651114.67293143, 74.90411349569982], + [510649.5928580111, 6651116.916457793, 70.64874420809241], + [510648.26546453364, 6651116.268194579, 73.13694802769982], + [510649.6202662136, 6651112.438051941, 75.7824278150924], + [510648.27233705163, 6651114.993175397, 74.66402504869981], + [510660.02297929185, 6651104.27597359, 71.53284202189651], + [510649.61556657136, 6651113.205957295, 74.97763722209241], + [510648.2665641708, 6651116.064185151, 73.47669305469984], + [510660.02869283134, 6651103.790093511, 72.12666794089651], + [510648.27070964884, 6651115.295098167, 74.39882732369983], + [510648.2678109425, 6651115.832878673, 73.80236016469982], + [510648.26919645845, 6651115.575831794, 74.11072897269982], + [510649.59732902475, 6651116.18590958, 71.69347190109241], + [510649.61298511573, 6651113.627758255, 74.81052246509242], + [510649.5929862861, 6651116.895498098, 71.1143348950924], + [510649.61732309737, 6651112.918947006, 75.69326316309241], + [510649.5980765976, 6651116.063758746, 72.1197822520924], + [510660.0218016197, 6651104.376122974, 71.95893115689651], + [510660.0273047272, 6651103.908138051, 72.48837392589651], + [510649.6104737907, 6651114.038100113, 74.5982446560924], + [510649.5990993341, 6651115.896647119, 72.5415911110924], + [510649.6151043445, 6651113.281483571, 75.5941676690924], + [510649.59338741924, 6651116.829954336, 71.59160584709242], + [510649.60807611246, 6651114.42987247, 74.34203153309241], + [510649.600398467, 6651115.684373286, 72.95194065409241], + [510649.60637793306, 6651114.707349134, 74.1226125270924], + [510649.60196648247, 6651115.42816496, 73.3437203480924], + [510649.60478404514, 6651114.96778493, 73.8816428810924], + [510649.60330931924, 6651115.208750063, 73.6212022080924], + [510649.61289653456, 6651113.642232105, 75.46654491009241], + [510660.0255778959, 6651104.054987984, 72.84613177189651], + [510649.59408209944, 6651116.71644598, 72.07450686709241], + [510660.0201022544, 6651104.5206371965, 72.3838376608965], + [510649.61071965494, 6651113.997926737, 75.31005361809243], + [510649.59480457794, 6651116.598395491, 72.43621285209241], + [510649.60859440727, 6651114.345184882, 75.12484471609241], + [510649.59570335655, 6651116.451538155, 72.79397069809241], + [510660.0235121314, 6651104.230660852, 73.1965879868965], + [510649.60654164, 6651114.680599985, 74.9115923810924], + [510649.59677854273, 6651116.275856432, 73.1444269130924], + [510649.6045817295, 6651115.000842605, 74.6715039340924], + [510660.0178710146, 6651104.710382091, 72.80080436289651], + [510649.59802709153, 6651116.071847861, 73.48417194009241], + [510649.60273394577, 6651115.3027641075, 74.4063062090924], + [510649.59944269975, 6651115.840542354, 73.8098390500924], + [510649.60101584066, 6651115.583496555, 74.1182078580924], + [510660.02111328376, 6651104.434659139, 73.53633301389651], + [510660.0151137835, 6651104.944857352, 73.20275327989651], + [510660.01839346334, 6651104.665952987, 73.86200012389651], + [510660.0118536976, 6651105.222095443, 73.5826340818965], + [510660.0153709742, 6651104.922985829, 74.1703689318965], + [510660.009102269, 6651105.456077259, 73.8490403968965], + [510665.5542208707, 6651103.663346096, 68.89585792190336], + [510660.01206996397, 6651105.203704126, 74.45846728289652], + [510660.0061132462, 6651105.710264113, 74.0967501368965], + [510660.00851980096, 6651105.505610411, 74.7236650078965], + [510665.54521983647, 6651104.272880859, 68.89585792190336], + [510665.54521983647, 6651104.272880859, 69.02585792190335], + [510660.0018059852, 6651106.076554105, 74.39419260689651], + [510660.0047542079, 6651105.82583689, 74.9637534548965], + [510659.9971993053, 6651106.468306715, 74.6504057298965], + [510665.5542208707, 6651103.663346096, 70.72466158090337], + [510660.0008102083, 6651106.161235085, 75.17700578989651], + [510665.55391138565, 6651103.684303897, 71.19025226790335], + [510659.99237427465, 6651106.878627889, 74.86268353889652], + [510659.9967269516, 6651106.5084757265, 75.36221469189653], + [510665.54521983647, 6651104.272880859, 70.72466158090337], + [510665.55294358457, 6651103.749841741, 71.66752321990336], + [510665.54494676145, 6651104.291373038, 71.13547689290336], + [510659.9925444938, 6651106.864152429, 75.51870598389651], + [510659.9874145015, 6651107.300407588, 75.02979829589651], + [510665.5440928193, 6651104.349200548, 71.55659832090335], + [510665.55126755167, 6651103.86333985, 72.15042423990337], + [510659.9883026095, 6651107.22488278, 75.6463287428965], + [510659.98240179825, 6651107.726688467, 75.15195141789651], + [510665.5426139668, 6651104.449345936, 71.98268745590336], + [510665.5495244508, 6651103.981379679, 72.51213022490336], + [510659.9840397004, 6651107.587401071, 75.74542423689651], + [510659.97741241456, 6651108.150986253, 75.23062611089651], + [510665.54735599604, 6651104.128223756, 72.86988807090336], + [510665.54048000224, 6651104.593854395, 72.40759395990337], + [510659.97251413245, 6651108.5675367415, 75.2683689698965], + [510659.97838506557, 6651108.068271895, 75.8345888888965], + [510665.5447619284, 6651104.303889617, 73.22034428590335], + [510665.5376781404, 6651104.783591721, 72.82456066190335], + [510659.97283367923, 6651108.54036245, 75.8773641298965], + [510665.54174959444, 6651104.507879768, 73.56008931290337], + [510669.92389173683, 6651103.733073057, 68.91265022951784], + [510665.5342157692, 6651105.0180576295, 73.22650957890335], + [510665.5383342014, 6651104.73916439, 73.88575642290336], + [510669.9134404153, 6651104.342584677, 68.91265022951784], + [510665.530121942, 6651105.295284663, 73.60639038090335], + [510669.9134404153, 6651104.342584677, 69.04265022951783], + [510659.95193703263, 6651110.317415762, 75.2683689698965], + [510665.5345387343, 6651104.99618698, 74.19412523090335], + [510665.52666685707, 6651105.529257147, 73.87279669590336], + [510659.8804250786, 6651116.3988008415, 68.87210162289652], + [510659.8804250786, 6651116.3988008415, 69.0021016228965], + [510665.53039351676, 6651105.27689408, 74.48222358190336], + [510665.5229134153, 6651105.783433863, 74.12050643590335], + [510669.92389173683, 6651103.733073057, 70.74145388851784], + [510659.8732571785, 6651117.008359918, 68.87210162289652], + [510665.5259354275, 6651105.578788322, 74.74742130690335], + [510669.92353238614, 6651103.754030063, 71.20704457551783], + [510665.5175046061, 6651106.149709243, 74.41794890590336], + [510669.9134404153, 6651104.342584677, 70.74145388851784], + [510659.93178770127, 6651112.030917296, 75.2683689698965], + [510665.52120681363, 6651105.899002029, 74.98750975390335], + [510669.9224086487, 6651103.819565418, 71.68431552751784], + [510669.9131233412, 6651104.361076154, 71.15226920051784], + [510659.88042505103, 6651116.39880318, 70.7009052828965], + [510659.9268894192, 6651112.447467786, 75.23062611089651], + [510665.511719804, 6651106.541446228, 74.67416202890335], + [510659.8804784981, 6651116.394258033, 70.9047265668965], + [510665.5162541672, 6651106.234386846, 75.20076208890337], + [510659.9314681821, 6651112.058089248, 75.8773641298965], + [510669.9121318081, 6651104.418901469, 71.57339062851783], + [510669.92046256573, 6651103.9330592165, 72.16721654751784], + [510659.9219000355, 6651112.871765571, 75.15195141789651], + [510659.8809222916, 6651116.356517783, 71.32130585489651], + [510659.8732571785, 6651117.008359918, 70.70090528189651], + [510665.50566080975, 6651106.9517510375, 74.88643983790335], + [510659.9259167957, 6651112.530179803, 75.8345888888965], + [510659.9168873323, 6651113.29804645, 75.02979829589651], + [510665.51112664957, 6651106.5816136375, 75.38597099090336], + [510669.910414676, 6651104.519043056, 71.99947976351784], + [510669.9184386086, 6651104.051094566, 72.52892253251784], + [510659.8818473756, 6651116.27784853, 71.74563297489651], + [510659.87350363436, 6651116.987401279, 71.1664959688965], + [510659.9119275591, 6651113.71982615, 74.86268353889652], + [510659.8832836939, 6651116.155703852, 72.1719433258965], + [510659.9202621609, 6651113.011050627, 75.74542423689651], + [510669.9159207626, 6651104.197933067, 72.88668037851784], + [510665.50587456115, 6651106.937276154, 75.54246228290336], + [510665.4994326136, 6651107.373513913, 75.05355459490336], + [510659.9071025285, 6651114.130147324, 74.6504057298965], + [510659.88524868654, 6651115.988600648, 72.5937521848965], + [510669.90793687745, 6651104.663546028, 72.42438626751783], + [510659.91599925177, 6651113.373568919, 75.6463287428965], + [510659.8742743348, 6651116.921860822, 71.64376692089652], + [510659.9024958486, 6651114.521899933, 74.39419260689651], + [510659.8877447217, 6651115.776337514, 73.00410172789651], + [510659.8992331217, 6651114.79936261, 74.17477360089651], + [510659.8907573635, 6651115.520142104, 73.3958814218965], + [510659.89617077104, 6651115.0597852785, 73.9338039548965], + [510659.8933373674, 6651115.300738267, 73.67336328189651], + [510659.91175736743, 6651113.73429927, 75.51870598389651], + [510659.87560902996, 6651116.808358188, 72.12666794089651], + [510665.50054784823, 6651107.297992116, 75.67008504190335], + [510669.912908727, 6651104.373592258, 73.23713659351785], + [510665.493137951, 6651107.79977779, 75.17570771690336], + [510659.90757490974, 6651114.089975973, 75.36221469189653], + [510669.90468356706, 6651104.853276151, 72.84135296951783], + [510659.8769971341, 6651116.6903136475, 72.48837392589651], + [510659.903491653, 6651114.4372166125, 75.17700578989651], + [510659.8787239654, 6651116.543463715, 72.84613177189651], + [510665.4951947337, 6651107.660495948, 75.76918053590337], + [510659.89954765333, 6651114.772614809, 74.9637534548965], + [510659.8807897299, 6651116.367790846, 73.1965879868965], + [510669.90941103204, 6651104.577574664, 73.57688162051784], + [510665.4868725716, 6651108.22405865, 75.25438240990336], + [510659.8957820603, 6651115.092841287, 74.7236650078965], + [510659.8831885776, 6651116.163792559, 73.53633301389651], + [510659.8922318973, 6651115.394747573, 74.45846728289652], + [510659.8859083979, 6651115.932498712, 73.86200012389651], + [510659.88893088716, 6651115.67546587, 74.1703689318965], + [510669.9006633228, 6651105.087733156, 73.24330188651783], + [510665.48072159244, 6651108.640592525, 75.29212526890335], + [510665.4880939705, 6651108.141347594, 75.85834518790337], + [510669.90544533543, 6651104.808850504, 73.90254873051784], + [510669.8959098797, 6651105.364949665, 73.62318268851784], + [510665.48112286074, 6651108.613419318, 75.90112042890335], + [510669.9010383256, 6651105.065863336, 74.21091753851783], + [510669.891898096, 6651105.598913264, 73.88958900351784], + [510669.89622521185, 6651105.34655978, 74.49901588951784], + [510669.88753988256, 6651105.8530803295, 74.13729874351785], + [510669.8910488151, 6651105.64844256, 74.76421361451783], + [510665.4548820611, 6651110.390401749, 75.29212526890335], + [510669.8812595816, 6651106.219341805, 74.43474121351784], + [510665.3650814872, 6651116.471544266, 68.89585792190336], + [510669.8855583056, 6651105.968644109, 75.00430206151785], + [510665.3650814872, 6651116.471544266, 69.02585792190335], + [510669.87454270595, 6651106.611063915, 74.69095433651783], + [510669.87980766624, 6651106.304016193, 75.21755439651784], + [510665.356080453, 6651117.081079029, 68.89585792190336], + [510676.9246202175, 6651103.866463508, 68.93586572512353], + [510669.8675074592, 6651107.021353147, 74.90323214551783], + [510669.8738539799, 6651106.651229801, 75.40276329851784], + [510676.9118453645, 6651104.475930858, 68.93586572512353], + [510665.4295796968, 6651112.103834938, 75.29212526890335], + [510676.9118453645, 6651104.475930858, 69.06586572512353], + [510669.86775565124, 6651107.006878814, 75.55925459051784], + [510669.860275748, 6651107.443100009, 75.07034690251785], + [510665.36508145276, 6651116.471546603, 70.72466158190335], + [510665.42342871753, 6651112.520368813, 75.25438240990336], + [510665.36514856847, 6651116.467001638, 70.92848286590336], + [510665.429178463, 6651112.131005806, 75.90112042890335], + [510669.86157067417, 6651107.367581081, 75.68687734951783], + [510665.4171633382, 6651112.944649675, 75.17570771690336], + [510669.8529668608, 6651107.869347701, 75.19250002451786], + [510665.3657058586, 6651116.429262893, 71.34506215390337], + [510665.356080453, 6651117.081079029, 70.72466158090337], + [510676.9246202175, 6651103.866463508, 70.76466938412354], + [510665.42220735323, 6651112.603077531, 75.85834518790337], + [510665.41086867556, 6651113.370913551, 75.05355459490336], + [510665.3668675256, 6651116.350596778, 71.76938927390336], + [510669.85535504174, 6651107.730071149, 75.78597284351784], + [510669.84569197515, 6651108.293612454, 75.27117471751784], + [510665.3563899381, 6651117.060121227, 71.19025226790335], + [510665.4046404794, 6651113.792676427, 74.88643983790335], + [510665.368671171, 6651116.228456973, 72.19569962490337], + [510665.41510659, 6651113.0839291755, 75.76918053590337], + [510676.9241809761, 6651103.887418992, 71.23026007112352], + [510665.3985814852, 6651114.202981235, 74.67416202890335], + [510665.371138695, 6651116.061360433, 72.61750848390336], + [510676.9118453645, 6651104.475930858, 70.76466938412354], + [510665.3573577392, 6651116.994583382, 71.66752321990336], + [510665.4097534755, 6651113.446433008, 75.67008504190335], + [510669.8385499224, 6651108.710130515, 75.30891757651783], + [510669.84711017134, 6651108.210904537, 75.87513749551783], + [510665.39279668307, 6651114.59471822, 74.41794890590336], + [510665.3742730716, 6651115.849105765, 73.02785802690336], + [510665.3886995396, 6651114.87216983, 74.19852989990335], + [510665.3780561728, 6651115.592920573, 73.41963772090337], + [510665.3848540167, 6651115.132582111, 73.95756025390335], + [510665.3812959923, 6651115.373525488, 73.69711958090335], + [510676.92280740995, 6651103.952949587, 71.70753102312354], + [510665.4044267626, 6651113.807148971, 75.54246228290336], + [510676.9114577986, 6651104.49442099, 71.17548469612353], + [510665.35903377214, 6651116.881085275, 72.15042423990337], + [510665.3991746742, 6651114.162811486, 75.38597099090336], + [510665.36077687296, 6651116.763045445, 72.51213022490336], + [510669.83901584474, 6651108.682958338, 75.91791273651783], + [510665.39404715656, 6651114.510038278, 75.20076208890337], + [510665.3629453277, 6651116.616201368, 72.86988807090336], + [510676.9102458284, 6651104.552242105, 71.59660612412353], + [510676.920428675, 6651104.066435142, 72.19043204312354], + [510665.3890945101, 6651114.845423095, 74.98750975390335], + [510665.36553939537, 6651116.440535507, 73.22034428590335], + [510665.3843658962, 6651115.165636801, 74.74742130690335], + [510665.3685517293, 6651116.236545356, 73.56008931290337], + [510665.379907807, 6651115.467531043, 74.48222358190336], + [510665.37196712237, 6651116.005260734, 73.88575642290336], + [510665.37576258945, 6651115.7482381435, 74.19412523090335], + [510676.90814694465, 6651104.652376419, 72.02269525912354], + [510676.91795475304, 6651104.184461919, 72.55213802812354], + [510676.914877141, 6651104.331289752, 72.90989587412354], + [510676.9051182834, 6651104.796868893, 72.44760176312353], + [510669.80854700884, 6651110.459873303, 75.30891757651783], + [510669.7042773602, 6651116.540784936, 68.91265022951784], + [510676.9111954715, 6651104.506936187, 73.26035208912353], + [510669.7042773602, 6651116.540784936, 69.04265022951783], + [510676.90114169894, 6651104.986585236, 72.86456846512353], + [510676.9069201711, 6651104.710903775, 73.60009711612354], + [510669.6938260387, 6651117.150296558, 68.91265022951784], + [510676.89622767654, 6651105.221025213, 73.26651738212355], + [510676.90207282326, 6651104.942162817, 73.92576422612353], + [510669.779167813, 6651112.173241438, 75.30891757651783], + [510676.89041745075, 6651105.498221584, 73.64639818412354], + [510676.8966860496, 6651105.199156981, 74.23413303412353], + [510669.7042773201, 6651116.540787275, 70.74145388951783], + [510669.7720257603, 6651112.589759498, 75.27117471751784], + [510669.7043552498, 6651116.536242481, 70.94527517351783], + [510676.88551376964, 6651105.73216819, 73.91280449912352], + [510669.7787019307, 6651112.200411274, 75.91791273651783], + [510669.76475087466, 6651113.014024251, 75.19250002451786], + [510676.89080288727, 6651105.479833035, 74.52223138512353], + [510669.7050023331, 6651116.49850517, 71.36185446151784], + [510669.6938260387, 6651117.150296558, 70.74145388851784], + [510676.8801866408, 6651105.9863167945, 74.16051423912354], + [510669.77060760424, 6651112.672465077, 75.87513749551783], + [510669.75744198746, 6651113.440271944, 75.07034690251785], + [510669.7063511731, 6651116.41984204, 71.78618158151784], + [510682.7717159758, 6651103.998336429, 68.95177490066979], + [510669.6941853894, 6651117.129339551, 71.20704457551783], + [510676.88447567704, 6651105.781693889, 74.78742911012354], + [510669.75021027616, 6651113.862018806, 74.90323214551783], + [510669.70844543003, 6651116.297706873, 72.21249193251784], + [510669.7623627338, 6651113.153298464, 75.78597284351784], + [510669.7431750294, 6651114.272308037, 74.69095433651783], + [510669.7113105327, 6651116.130616677, 72.63430079151783], + [510676.87251010706, 6651106.352551666, 74.45795670912354], + [510669.69530912687, 6651117.063804195, 71.68431552751784], + [510669.75614710135, 6651113.515788534, 75.68687734951783], + [510669.7364581539, 6651114.664030148, 74.43474121351784], + [510669.7149499342, 6651115.918370069, 73.04465033451785], + [510682.7570004802, 6651104.607760011, 68.95177490066979], + [510669.73170085996, 6651114.941471224, 74.21532220751783], + [510669.71934258577, 6651115.662194603, 73.43643002851783], + [510669.72723572917, 6651115.201873618, 73.97435256151783], + [510676.8777645209, 6651106.101872179, 75.02751755712355], + [510669.7231044197, 6651115.442807847, 73.71391188851783], + [510682.7570004802, 6651104.607760011, 69.0817749006698], + [510669.7499621243, 6651113.8764908, 75.55925459051784], + [510669.69725520985, 6651116.950310396, 72.16721654751784], + [510669.7438637956, 6651114.232139813, 75.40276329851784], + [510669.69927916693, 6651116.832275048, 72.52892253251784], + [510676.86429993977, 6651106.744245323, 74.71416983212355], + [510669.7379101093, 6651114.579353421, 75.21755439651784], + [510669.70179701294, 6651116.685436548, 72.88668037851784], + [510676.8707354028, 6651106.437219903, 75.24076989212354], + [510669.7321594699, 6651114.914725506, 75.00430206151785], + [510669.7048090485, 6651116.509777355, 73.23713659351785], + [510669.7266689604, 6651115.2349270545, 74.76421361451783], + [510669.7083067435, 6651116.305794949, 73.57688162051784], + [510669.72149256367, 6651115.536809834, 74.49901588951784], + [510669.7122724401, 6651116.074519108, 73.90254873051784], + [510669.7166794499, 6651115.817506276, 74.21091753851783], + [510682.7717159758, 6651103.998336429, 70.78057855966979], + [510676.85570062115, 6651107.154504753, 74.92644764112353], + [510676.8634580965, 6651106.784408291, 75.42597879412354], + [510682.77121000877, 6651104.019290409, 71.24616924666978], + [510676.8468611602, 6651107.576220981, 75.09356239812355], + [510676.85600399104, 6651107.140031472, 75.58247008612354], + [510682.7570004802, 6651104.607760011, 70.78057855966979], + [510682.7696277826, 6651104.084816299, 71.72344019866979], + [510682.75655403873, 6651104.626248816, 71.19139387166979], + [510676.84844397375, 6651107.500707538, 75.71009284512353], + [510676.8379273656, 6651108.002437714, 75.21571552012355], + [510682.7551579568, 6651104.684065778, 71.61251529966978], + [510682.76688769134, 6651104.198293704, 72.20634121866979], + [510676.84084648546, 6651107.863171278, 75.80918833912354], + [510676.8290351318, 6651108.426671649, 75.29439021312353], + [510682.75274022925, 6651104.7841929, 72.03860443466981], + [510682.76403795293, 6651104.316312004, 72.56804720366979], + [510676.8203052621, 6651108.843159456, 75.33213307212353], + [510676.8307686204, 6651108.343969739, 75.89835299112353], + [510682.76049281744, 6651104.463129293, 72.92580504966979], + [510682.7492514806, 6651104.928675001, 72.46351093866978], + [510676.8208747682, 6651108.815989254, 75.94112823212353], + [510682.7562518612, 6651104.638763113, 73.2762612646698], + [510682.7446708086, 6651105.118377716, 72.88047764066978], + [510682.75132709515, 6651104.842716054, 73.61600629166979], + [510682.7390102914, 6651105.352800856, 73.2824265576698], + [510676.7836321189, 6651110.592775151, 75.33213307212353], + [510682.74574338115, 6651105.073958489, 73.94167340166979], + [510676.6561813048, 6651116.673245096, 68.93586572512353], + [510682.7323174276, 6651105.629977323, 73.66230735966978], + [510676.6561813048, 6651116.673245096, 69.06586572512353], + [510682.73953829653, 6651105.330934196, 74.25004220966979], + [510682.7266688227, 6651105.863907128, 73.92871367466978], + [510676.64340645174, 6651117.282712445, 68.93586572512353], + [510682.7327614163, 6651105.611590094, 74.53814056066979], + [510682.7205324437, 6651106.118037479, 74.17642341466978], + [510682.7254730324, 6651105.913429269, 74.80333828566978], + [510676.747721358, 6651112.306018835, 75.33213307212353], + [510682.711689759, 6651106.484246051, 74.47386588466979], + [510676.65618125576, 6651116.673247434, 70.76466938512353], + [510676.7389914884, 6651112.722506641, 75.29439021312353], + [510676.65627651074, 6651116.66870297, 70.96849066912353], + [510682.7177423767, 6651106.233584566, 75.04342673266979], + [510676.74715190096, 6651112.333186698, 75.94112823212353], + [510676.73009925446, 6651113.146740579, 75.21571552012355], + [510676.6570674532, 6651116.630968399, 71.38506995712353], + [510682.70223237574, 6651106.8759115795, 74.73007900766979], + [510676.64340645174, 6651117.282712445, 70.76466938412354], + [510676.73725804867, 6651112.805206212, 75.89835299112353], + [510682.7096454574, 6651106.568908208, 75.25667906766981], + [510676.72116545995, 6651113.57295731, 75.09356239812355], + [510676.6587161665, 6651116.552310984, 71.80939707712353], + [510676.64384569303, 6651117.26175696, 71.23026007112352], + [510676.712325999, 6651113.994673539, 74.92644764112353], + [510676.6612760173, 6651116.430184687, 72.23570742812353], + [510676.72718018363, 6651113.286004675, 75.80918833912354], + [510682.69232672494, 6651107.286141547, 74.94235681666979], + [510676.7037266803, 6651114.404932967, 74.71416983212355], + [510682.70126264717, 6651106.916071664, 75.44188796966979], + [510676.6647780878, 6651116.263106628, 72.65751628712353], + [510676.6452192592, 6651117.196226364, 71.70753102312354], + [510676.7195826955, 6651113.648468414, 75.71009284512353], + [510676.6955165131, 6651114.7966266265, 74.45795670912354], + [510676.66922659904, 6651116.0508754365, 73.06786583012355], + [510690.1689726671, 6651104.19186548, 68.96736160139059], + [510676.68970158044, 6651115.07404755, 74.23853770312353], + [510676.6745958222, 6651115.794718578, 73.45964552412353], + [510676.68424376444, 6651115.334431029, 73.99756805712353], + [510676.67919398483, 6651115.575347758, 73.73712738412355], + [510676.7120226781, 6651114.009144481, 75.58247008612354], + [510676.6475979941, 6651117.082740809, 72.19043204312354], + [510682.68214445136, 6651107.70782749, 75.1094715736698], + [510682.6926761801, 6651107.271669304, 75.5983792616698], + [510676.70456857275, 6651114.364767661, 75.42597879412354], + [510676.6500719161, 6651116.9647140335, 72.55213802812354], + [510676.6972912663, 6651114.711956049, 75.24076989212354], + [510690.1518020329, 6651104.801224829, 68.96736160139059], + [510676.65314952814, 6651116.8178862, 72.90989587412354], + [510690.1518020329, 6651104.801224829, 69.09736160139059], + [510676.69026214833, 6651115.047303773, 75.02751755712355], + [510676.6568311977, 6651116.642239766, 73.26035208912353], + [510682.68396771187, 6651107.632319469, 75.7260020206698], + [510676.6835509921, 6651115.367482063, 74.78742911012354], + [510676.661106498, 6651116.438272176, 73.60009711612354], + [510682.67185351375, 6651108.134013615, 75.2316246956698], + [510676.6772237819, 6651115.669342916, 74.52223138512353], + [510676.6659538459, 6651116.207013135, 73.92576422612353], + [510676.67134061956, 6651115.950018971, 74.23413303412353], + [510682.6752160805, 6651107.994757179, 75.82509751466979], + [510682.6616104506, 6651108.558217084, 75.31029938866979], + [510690.1689726671, 6651104.19186548, 70.79616526039061], + [510682.6515544164, 6651108.97467498, 75.34804224766978], + [510682.6636072755, 6651108.475521113, 75.9142621666698], + [510690.16838228446, 6651104.212817251, 71.26175594739058], + [510690.1518020329, 6651104.801224829, 70.79616526039061], + [510682.65221043676, 6651108.94750673, 75.95703740766979], + [510690.16653607914, 6651104.278336233, 71.7390268993906], + [510690.15128110704, 6651104.819711686, 71.20698057239059], + [510690.1496521023, 6651104.877522553, 71.62810200039058], + [510690.16333882994, 6651104.391801679, 72.22192791939061], + [510682.6093102142, 6651110.724165028, 75.34804224766978], + [510690.14683100017, 6651104.977639122, 72.0541911353906], + [510690.16001364024, 6651104.509807539, 72.5836339043906], + [510682.4624982014, 6651116.804198307, 68.95177490066979], + [510682.4624982014, 6651116.804198307, 69.0817749006698], + [510690.15587703296, 6651104.6566093555, 72.9413917503906], + [510690.1427601874, 6651105.122105994, 72.4790976393906], + [510693.8149386678, 6651104.298225386, 68.97317771938432], + [510682.4477827058, 6651117.413621889, 68.95177490066979], + [510690.15092851414, 6651104.832224664, 73.29184796539059], + [510690.13741527445, 6651105.311788716, 72.89606434139058], + [510693.7965579429, 6651104.907549433, 68.97317771938432], + [510690.1451820983, 6651105.0361561095, 73.63159299239061], + [510693.7965579429, 6651104.907549433, 69.1031777193843], + [510690.13081035455, 6651105.546187148, 73.2980132583906], + [510682.56794420857, 6651112.437285677, 75.34804224766978], + [510682.46249814495, 6651116.804200646, 70.78057856066978], + [510690.1386667954, 6651105.26737417, 73.95726010239059], + [510682.55788817455, 6651112.853743574, 75.31029938866979], + [510682.4626078702, 6651116.799656509, 70.98439984466978], + [510682.5672882447, 6651112.464451589, 75.95703740766979], + [510690.1230008509, 6651105.823334401, 73.67789406039059], + [510682.5476451112, 6651113.277947045, 75.2316246956698], + [510682.46351896564, 6651116.761924649, 71.40097913266979], + [510693.8149386678, 6651104.298225386, 70.80198137838431], + [510690.1314264522, 6651105.524322793, 74.26562891039059], + [510682.4477827058, 6651117.413621889, 70.78057855966979], + [510682.5558914061, 6651112.936437205, 75.9142621666698], + [510682.5373541738, 6651113.704133168, 75.1094715736698], + [510690.1164098307, 6651106.057239551, 73.9443003753906], + [510682.4654181369, 6651116.683272881, 71.82530625266979], + [510693.8143066783, 6651104.319175944, 71.2675720653843], + [510682.4482886728, 6651117.392667909, 71.24616924666978], + [510682.5271719002, 6651114.12581911, 74.94235681666979], + [510682.46836685756, 6651116.561155355, 72.2516166036698], + [510690.12351891474, 6651105.80494911, 74.5537272613906], + [510693.7965579429, 6651104.907549433, 70.80198137838431], + [510682.5442826011, 6651113.417201139, 75.82509751466979], + [510690.10924965603, 6651106.311343118, 74.19201011539059], + [510682.5172662492, 6651114.536049078, 74.73007900766979], + [510682.4724009316, 6651116.3940892955, 72.67342546266978], + [510682.4498708989, 6651117.327142019, 71.72344019866979], + [510682.53553096973, 6651113.779638848, 75.7260020206698], + [510682.50780886604, 6651114.927714606, 74.47386588466979], + [510682.4775252212, 6651116.181873344, 73.08377500566979], + [510693.8123303626, 6651104.38469113, 71.74484301738433], + [510682.50111058046, 6651115.205115609, 74.25444687866978], + [510693.796000305, 6651104.92603522, 71.21279669038431], + [510682.4837100891, 6651115.925734882, 73.4755546996698], + [510682.49482366134, 6651115.465480388, 74.01347723266979], + [510682.48900676396, 6651115.706379815, 73.7530365596698], + [510690.1150145342, 6651106.106756472, 74.81892498639058], + [510682.5268225015, 6651114.140289015, 75.5983792616698], + [510682.45261099027, 6651117.2136646155, 72.20634121866979], + [510682.51823603443, 6651114.4958866555, 75.44188796966979], + [510682.45546072855, 6651117.095646315, 72.56804720366979], + [510690.0989316545, 6651106.677513091, 74.4894525853906], + [510693.7942564971, 6651104.983842739, 71.63391811838432], + [510693.8089077892, 6651104.498150002, 72.22774403738431], + [510682.5098532241, 6651114.84305011, 75.25667906766981], + [510682.45900586416, 6651116.948829024, 72.92580504966979], + [510690.1059940932, 6651106.426878026, 75.05901343339059], + [510682.5017563049, 6651115.178373751, 75.04342673266979], + [510682.46324682026, 6651116.773195205, 73.2762612646698], + [510682.4940256492, 6651115.49852905, 74.80333828566978], + [510682.46817158634, 6651116.569242263, 73.61600629166979], + [510682.48673726525, 6651115.800368224, 74.53814056066979], + [510682.47375530045, 6651116.337999829, 73.94167340166979], + [510682.47996038507, 6651116.081024122, 74.25004220966979], + [510693.79123657936, 6651105.083953507, 72.06000725338431], + [510693.8053482585, 6651104.616149026, 72.58945002238431], + [510690.087896398, 6651107.06913734, 74.74566570839059], + [510690.0965462809, 6651106.762166326, 75.2722657683906], + [510693.80092012626, 6651104.762942339, 72.94720786838431], + [510693.7868788784, 6651105.22841201, 72.4849137573843], + [510690.0763380847, 6651107.479324068, 74.95794351739059], + [510690.0867648795, 6651107.10929319, 75.4574746703906], + [510693.7956228634, 6651104.9385474725, 73.2976640833843], + [510693.78115728573, 6651105.418083744, 72.90188045938432], + [510690.06445699686, 6651107.900965568, 75.1250582743906], + [510690.07674584317, 6651107.464853351, 75.6139659623906], + [510693.7894714721, 6651105.142467104, 73.63740911038431], + [510693.7740868878, 6651105.6524685975, 73.3038293763843], + [510690.06658445083, 6651107.825465506, 75.74158872139058], + [510690.0524491156, 6651108.327106771, 75.2472113963906], + [510693.7824970068, 6651105.37367177, 73.96307622038431], + [510690.05637269415, 6651108.187865014, 75.84068421539061], + [510690.0404970959, 6651108.751265531, 75.32588608939061], + [510693.7657270137, 6651105.9295997955, 73.6837101783843], + [510693.7747464045, 6651105.630605509, 74.2714450283843], + [510690.0287633094, 6651109.167679534, 75.3636289483906], + [510690.04282707185, 6651108.668578276, 75.92984886739059], + [510693.7586714951, 6651106.163491393, 73.95011649338433], + [510693.7662815879, 6651105.911215569, 74.55954337938432], + [510693.7510067111, 6651106.417580241, 74.1978262333843], + [510690.0295287805, 6651109.140514147, 75.97262410839059], + [510693.7571778659, 6651106.213005447, 74.8247411043843], + [510693.73996155435, 6651106.783729001, 74.49526870338431], + [510699.9853135196, 6651104.494739295, 68.98021260000013], + [510693.7475217143, 6651106.533108455, 75.0648295513843], + [510689.9794710692, 6651110.9169851905, 75.3636289483906], + [510693.7281485943, 6651107.1753305625, 74.7514818263843], + [510699.96488485625, 6651105.103998121, 68.98021260000013], + [510699.96488485625, 6651105.103998121, 69.11021260000012], + [510693.7374080728, 6651106.868377331, 75.27808188638431], + [510689.8081648865, 6651116.996377645, 68.96736160139059], + [510689.8081648865, 6651116.996377645, 69.09736160139059], + [510693.7157757155, 6651107.58549353, 74.96375963538432], + [510693.72693733266, 6651107.215484087, 75.46329078838433], + [510689.7909942523, 6651117.605736995, 68.96736160139059], + [510699.9853135196, 6651104.494739295, 70.80901625900015], + [510693.7030573146, 6651108.007110601, 75.13087439238431], + [510693.7162122104, 6651107.5710236505, 75.61978208038431], + [510699.9846111152, 6651104.51568761, 71.27460694600012], + [510693.7053346998, 6651107.931614913, 75.7474048393843], + [510699.96488485625, 6651105.103998121, 70.80901625900015], + [510689.9312035441, 6651112.62992528, 75.3636289483906], + [510693.6902031847, 6651108.433227119, 75.25302751438431], + [510689.8081648206, 6651116.996379984, 70.79616526139058], + [510699.98241460306, 6651104.581195785, 71.75187789800013], + [510699.96426508774, 6651105.122481928, 71.21983157100013], + [510689.9194697576, 6651113.046339281, 75.32588608939061], + [510693.6944032752, 6651108.293993428, 75.84650033338431], + [510689.80829285254, 6651116.991836326, 70.9999865453906], + [510693.6774088532, 6651108.857361308, 75.33170220738431], + [510689.9304381389, 6651112.657088327, 75.97262410839059], + [510689.9075177379, 6651113.470498042, 75.2472113963906], + [510689.80935595545, 6651116.954108442, 71.4165658333906], + [510699.9623269887, 6651105.18028326, 71.64095299900012], + [510689.7909942523, 6651117.605736995, 70.79616526039061], + [510699.97861069423, 6651104.694642511, 72.23477891800015], + [510693.66484813474, 6651109.273751187, 75.3694450663843], + [510693.6799030329, 6651108.774678842, 75.9356649853843], + [510689.9171398475, 6651113.129024197, 75.92984886739059], + [510689.89550985664, 6651113.8966392465, 75.1250582743906], + [510689.8115719851, 6651116.875464965, 71.8408929533906], + [510689.7915846349, 6651117.584785224, 71.26175594739058], + [510699.95897059864, 6651105.280383312, 72.06704213400013], + [510699.9746545689, 6651104.812628905, 72.59648490300013], + [510689.88362876873, 6651114.318280744, 74.95794351739059], + [510689.8150126714, 6651116.75336031, 72.26720330439059], + [510689.90359422524, 6651113.60973746, 75.84068421539061], + [510693.6656675519, 6651109.246587373, 75.97844022638431], + [510689.87207045546, 6651114.728467474, 74.74566570839059], + [510689.8197197918, 6651116.586311859, 72.6890121633906], + [510689.7934308403, 6651117.51926624, 71.7390268993906], + [510689.89338246855, 6651113.97213697, 75.74158872139058], + [510689.82569901977, 6651116.374118274, 73.0993617063906], + [510689.861035199, 6651115.120091722, 74.4894525853906], + [510699.9697330642, 6651104.9594065035, 72.95424274900013], + [510689.85321936896, 6651115.397463486, 74.2700335793906], + [510689.8329157733, 6651116.118006809, 73.49114140039059], + [510689.84588353796, 6651115.657800825, 74.02906393339059], + [510699.9541273726, 6651105.424826352, 72.49194863800014], + [510689.8390961473, 6651115.898674862, 73.7686232603906], + [510689.88322107634, 6651114.332749123, 75.6139659623906], + [510689.79662808945, 6651117.405800796, 72.22192791939061], + [510689.8732020399, 6651114.688309285, 75.4574746703906], + [510689.79995327914, 6651117.2877949355, 72.5836339043906], + [510699.96384559234, 6651105.134992841, 73.30469896400012], + [510689.8634206385, 6651115.035436149, 75.2722657683906], + [510689.8040898864, 6651117.140993119, 72.9413917503906], + [510699.9477682932, 6651105.6144777825, 72.90891534000012], + [510689.8539728262, 6651115.37072445, 75.05901343339059], + [510689.80903840525, 6651116.965377811, 73.29184796539059], + [510689.81478482106, 6651116.761446366, 73.63159299239061], + [510689.8449523852, 6651115.690846002, 74.81892498639058], + [510689.821300124, 6651116.530228306, 73.95726010239059], + [510689.83644800464, 6651115.992653363, 74.5537272613906], + [510689.8285404672, 6651116.273279681, 74.26562891039059], + [510693.6120820515, 6651111.022955503, 75.3694450663843], + [510699.9570088271, 6651105.338890645, 73.64444399100014], + [510699.93991012766, 6651105.848837548, 73.31086425700013], + [510693.42870316224, 6651117.1019957755, 68.97317771938432], + [510693.42870316224, 6651117.1019957755, 69.1031777193843], + [510699.94925728295, 6651105.570070563, 73.97011110100013], + [510693.41032243724, 6651117.711319824, 68.97317771938432], + [510699.93061881553, 6651106.12593908, 73.69074505900012], + [510699.9406431262, 6651105.8269767985, 74.27847990900013], + [510699.9227771871, 6651106.359805644, 73.95715137400013], + [510699.9312351791, 6651106.107556822, 74.56657826000014], + [510693.5604128998, 6651112.735796362, 75.3694450663843], + [510699.9142584104, 6651106.613867291, 74.20486111400012], + [510693.42870309163, 6651117.101998114, 70.8019813793843], + [510693.54785218136, 6651113.152186241, 75.33170220738431], + [510693.4288401466, 6651117.09745472, 71.0058026633843], + [510699.9211171412, 6651106.409314396, 74.83177598500012], + [510693.5595935532, 6651112.762957836, 75.97844022638431], + [510693.53505784983, 6651113.576320428, 75.25302751438431], + [510693.4299781711, 6651117.059729021, 71.42238195138431], + [510699.9019826275, 6651106.979976861, 74.50230358400013], + [510693.41032243724, 6651117.711319824, 70.80198137838431], + [510693.5453580722, 6651113.234866366, 75.9356649853843], + [510699.9103851233, 6651106.729383141, 75.07186443200013], + [510693.5222037198, 6651114.002436946, 75.13087439238431], + [510693.43235037423, 6651116.9810901, 71.84670907138431], + [510693.4109544268, 6651117.690369266, 71.2675720653843], + [510693.5094853191, 6651114.424054019, 74.96375963538432], + [510693.43603354093, 6651116.858992517, 72.27301942238431], + [510699.8888534946, 6651107.371536504, 74.75851670700013], + [510693.5308578298, 6651113.7155517815, 75.84650033338431], + [510693.441072393, 6651116.691953744, 72.6948282813843], + [510693.4971124401, 6651114.834216987, 74.7514818263843], + [510699.8991446429, 6651107.064616129, 75.28511676700013], + [510693.4129307424, 6651117.624854079, 71.74484301738433], + [510693.51992640534, 6651114.077930296, 75.7474048393843], + [510693.4474730036, 6651116.479772453, 73.10517782438431], + [510693.48529948015, 6651115.2258185465, 74.49526870338431], + [510693.4769328339, 6651115.503174243, 74.27584969738432], + [510693.4551983539, 6651116.223675824, 73.4969575183843], + [510693.46908001445, 6651115.7634964995, 74.0348800513843], + [510693.4618142862, 6651116.004356583, 73.7744393783843], + [510693.5090488947, 6651114.438521558, 75.61978208038431], + [510693.4163533159, 6651117.511395209, 72.22774403738431], + [510699.87510205776, 6651107.781655566, 74.97079451600013], + [510699.88750727684, 6651107.411685729, 75.47032566900013], + [510693.49832377234, 6651114.794061122, 75.46329078838433], + [510693.41991284647, 6651117.393396183, 72.58945002238431], + [510693.42434097873, 6651117.2466028705, 72.94720786838431], + [510693.48785303225, 6651115.141167878, 75.27808188638431], + [510693.4296382417, 6651117.070997736, 73.2976640833843], + [510693.4777393907, 6651115.476436754, 75.0648295513843], + [510693.435789633, 6651116.867078106, 73.63740911038431], + [510693.4680832391, 6651115.796539762, 74.8247411043843], + [510699.86096660176, 6651108.203227508, 75.13790927300013], + [510699.8755871859, 6651107.767187236, 75.62681696100013], + [510693.4427640982, 6651116.63587344, 73.96307622038431], + [510693.4589795171, 6651116.098329641, 74.55954337938432], + [510693.45051470055, 6651116.3789397, 74.2714450283843], + [510699.8634977279, 6651108.127739902, 75.75443972000012], + [510699.8466802941, 6651108.629298414, 75.26006239500013], + [510699.8513483491, 6651108.490079626, 75.85353521400015], + [510699.83246044745, 6651109.053387202, 75.33873708800014], + [510699.81850024237, 6651109.469732512, 75.37647994700013], + [510699.8352325228, 6651108.9707135875, 75.94269986600013], + [510699.81941095716, 6651109.442571606, 75.98547510700013], + [510699.7598550827, 6651111.218749591, 75.37647994700013], + [510699.5560445367, 6651117.297139156, 68.98021260000013], + [510710.4077648801, 6651104.8738347655, 68.98407466471348], + [510699.5560445367, 6651117.297139156, 69.11021260000012], + [510710.7005707575, 6651104.885340882, 68.9840376056788], + [510699.53561587346, 6651117.906397982, 68.98021260000013], + [510710.3838770205, 6651105.48296777, 68.98407466471348], + [510710.3838770205, 6651105.48296777, 69.11407466471347], + [510710.6765857161, 6651105.494470069, 68.9840376056788], + [510710.6765857161, 6651105.494470069, 69.11403760567879], + [510699.70242907223, 6651112.931407105, 75.37647994700013], + [510699.5560444584, 6651117.297141493, 70.80901626000012], + [510710.4077648801, 6651104.8738347655, 70.81287832371348], + [510699.6884688672, 6651113.347752413, 75.33873708800014], + [510699.55619678367, 6651117.292598586, 71.01283754400013], + [510699.7015184359, 6651112.958565671, 75.98547510700013], + [510710.7005707575, 6651104.885340882, 70.8128412646788], + [510710.4069435372, 6651104.894778755, 71.27846901071347], + [510699.6742490205, 6651113.771841201, 75.26006239500013], + [510699.55746160424, 6651117.254876926, 71.42941683200014], + [510699.53561587346, 6651117.906397982, 70.80901625900015], + [510710.3838770205, 6651105.48296777, 70.81287832371348], + [510699.68569687015, 6651113.430423689, 75.94269986600013], + [510710.69974607317, 6651104.906284741, 71.2784319516788], + [510699.5600981128, 6651117.176246421, 71.85374395200013], + [510699.6599627128, 6651114.197912107, 75.13790927300013], + [510710.4043750885, 6651104.960273401, 71.75573996271348], + [510710.6765857161, 6651105.494470069, 70.8128412646788], + [510710.3831523062, 6651105.501447761, 71.22369363571347], + [510699.53631827777, 6651117.8854496665, 71.27460694600012], + [510699.56419164955, 6651117.054161909, 72.28005430300013], + [510699.6458272569, 6651114.619484049, 74.97079451600013], + [510699.66958104394, 6651113.91105765, 75.85353521400015], + [510699.56979191897, 6651116.887141016, 72.70186316200014], + [510710.6971671753, 6651104.971778976, 71.7557029036788], + [510699.63207582006, 6651115.029603112, 74.75851670700013], + [510710.67585805344, 6651105.512949944, 71.2236565766788], + [510699.53851479, 6651117.819941492, 71.75187789800013], + [510710.3808860278, 6651105.559237155, 71.64481506371347], + [510699.65743166517, 6651114.273397376, 75.75443972000012], + [510699.57690567104, 6651116.674982437, 73.11221270500013], + [510699.61894668714, 6651115.421162756, 74.50230358400013], + [510710.39992706187, 6651105.073696698, 72.23864098271348], + [510699.60964784835, 6651115.698488763, 74.28288457800014], + [510699.5854917621, 6651116.418913221, 73.50399239900013], + [510699.60092008556, 6651115.958783154, 74.04191493200013], + [510699.5928448265, 6651116.199617455, 73.78147425900013], + [510699.54231869883, 6651117.706494765, 72.23477891800015], + [510699.64534220716, 6651114.633950041, 75.62681696100013], + [510710.6735825553, 6651105.570738974, 71.64477800467878], + [510710.692701053, 6651105.085201563, 72.2386039236788], + [510699.5462748242, 6651117.588508373, 72.59648490300013], + [510699.6334221162, 6651114.989451547, 75.47032566900013], + [510710.3769612984, 6651105.659316535, 72.07090419871348], + [510710.39530104364, 6651105.191658726, 72.60034696771348], + [510699.55119632883, 6651117.441730773, 72.95424274900013], + [510699.6217847501, 6651115.336521149, 75.28511676700013], + [510699.5570838006, 6651117.266144436, 73.30469896400012], + [510699.6105442698, 6651115.671754136, 75.07186443200013], + [510710.6696418591, 6651105.670817729, 72.0708671396788], + [510710.688056215, 6651105.203162851, 72.6003099086788], + [510699.56392056594, 6651117.062246632, 73.64444399100014], + [510699.59981225186, 6651115.99182288, 74.83177598500012], + [510699.5716721101, 6651116.831066714, 73.97011110100013], + [510699.589694214, 6651116.293580454, 74.56657826000014], + [510710.389546178, 6651105.338406014, 72.95810481371348], + [510699.5802862668, 6651116.574160478, 74.27847990900013], + [510710.3712979664, 6651105.803729745, 72.49581070271348], + [510710.68227793707, 6651105.349909219, 72.9580677546788], + [510710.6639554872, 6651105.815230032, 72.49577364367879], + [510710.38266177743, 6651105.51395609, 73.30856102871347], + [510710.3638621007, 6651105.993342011, 72.91277740471347], + [510710.6753655291, 6651105.525458194, 73.30852396967879], + [510710.65648937057, 6651106.00484111, 72.91274034567878], + [510710.3746673391, 6651105.717811785, 73.64830605571348], + [510710.3546733078, 6651106.227653377, 73.31472632171347], + [510710.6673385674, 6651105.729312612, 73.6482689966788], + [510710.3656032218, 6651105.948943961, 73.97397316571347], + [510710.64726319537, 6651106.239151007, 73.3146892626788], + [510710.34380869294, 6651106.504697682, 73.69460712371347], + [510710.658237575, 6651105.96044334, 73.9739361066788], + [510710.3555304255, 6651106.205797142, 74.28234197371347], + [510710.63635438046, 6651106.516193576, 73.69457006467879], + [510710.3346392375, 6651106.73851595, 73.96101343871348], + [510710.64812379994, 6651106.217294909, 74.28230491467879], + [510710.34452942567, 6651106.486319222, 74.57044032471347], + [510710.62714762136, 6651106.750010377, 73.96097637967878], + [510710.32467797195, 6651106.9925251305, 74.20872317871347], + [510710.6370780453, 6651106.49781523, 74.57040326567879], + [510710.61714583077, 6651107.004017965, 74.20868611967879], + [510710.33269809507, 6651106.788014479, 74.83563804971347], + [510710.3103235241, 6651107.358559091, 74.50616564871348], + [510710.62519858184, 6651106.799508596, 74.8356009906788], + [510710.320148819, 6651107.108017123, 75.07572649671347], + [510710.6027329855, 6651107.370049632, 74.50612858967881], + [510710.29497122817, 6651107.750037872, 74.76237877171347], + [510710.61259825213, 6651107.119509234, 75.0756894376788], + [510710.3070049822, 6651107.443180881, 75.2889788317135], + [510717.1935003072, 6651105.152511052, 68.98117101989592], + [510710.5873182326, 6651107.761525957, 74.7623417126788], + [510710.5994009429, 6651107.45467089, 75.2889417726788], + [510710.2788912533, 6651108.160072238, 74.97465658071347], + [510710.2933970547, 6651107.790178806, 75.47418773371348], + [510717.16736027185, 6651105.7615515655, 68.98117101989592], + [510710.57117284025, 6651108.171557753, 74.97461952167879], + [510717.16736027185, 6651105.7615515655, 69.11117101989592], + [510710.585737655, 6651107.80166664, 75.4741506746788], + [510710.2623622332, 6651108.581557119, 75.14177133771348], + [510710.27945852856, 6651108.145606897, 75.63067902571348], + [510710.554576576, 6651108.593039993, 75.14173427867881], + [510710.5717424233, 6651108.157092503, 75.6306419666788], + [510710.2653219562, 6651108.5060851015, 75.75830178471347], + [510710.24565681745, 6651109.007540036, 75.26392445971348], + [510717.1935003072, 6651105.152511052, 70.80997467889593], + [510710.5575483399, 6651108.517568449, 75.75826472567879], + [510710.5378031984, 6651109.019020237, 75.26388740067881], + [510710.2511153167, 6651108.868349999, 75.85739727871349], + [510710.2290291166, 6651109.431541244, 75.34259915271348], + [510717.19260152715, 6651105.173451861, 71.27556536589593], + [510710.5432839042, 6651108.879831074, 75.8573602196788], + [510717.16736027185, 6651105.7615515655, 70.80997467889593], + [510710.52110785194, 6651109.443018787, 75.3425620936788], + [510710.2127050227, 6651109.847800571, 75.38034201171347], + [510710.2322705891, 6651109.348884702, 75.94656193071349], + [510717.1897909219, 6651105.238936563, 71.75283631789593], + [510717.16656723066, 6651105.780028748, 71.22078999089594], + [510710.50471734744, 6651109.859275505, 75.38030495267878], + [510710.52436251147, 6651109.3603627635, 75.94652487167879], + [510710.2137699493, 6651109.820645273, 75.98933717171347], + [510717.1640872849, 6651105.837809368, 71.64191141889592], + [510717.18492353015, 6651105.352342638, 72.23573733789593], + [510710.50578660634, 6651109.832120378, 75.98930011267879], + [510717.15979252744, 6651105.937873553, 72.06800055389593], + [510717.1798613654, 6651105.470286753, 72.59744332289593], + [510717.1735639243, 6651105.6170117585, 72.95520116889593], + [510717.1535952497, 6651106.082264833, 72.49290705789592], + [510710.1441294474, 6651111.596456451, 75.38034201171347], + [510709.90580755426, 6651117.6735907355, 68.98407466471348], + [510709.90580755426, 6651117.6735907355, 69.11407466471347], + [510710.4358627894, 6651111.607920422, 75.38030495267878], + [510717.1660304544, 6651105.792535178, 73.30565738389592], + [510717.1454583218, 6651106.271848308, 72.90987375989592], + [510710.1965713426, 6651117.685016608, 68.9840376056788], + [510710.1965713426, 6651117.685016608, 69.11403760567879], + [510709.88191969466, 6651118.282723741, 68.98407466471348], + [510717.15728229086, 6651105.996359921, 73.64540241089593], + [510717.13540319866, 6651106.506124095, 73.31182267689593], + [510710.17258630117, 6651118.294145795, 68.9840376056788], + [510717.147363598, 6651106.227457001, 73.97106952089594], + [510710.07697946037, 6651113.308760275, 75.38034201171347], + [510717.12351425504, 6651106.783126335, 73.69170347889592], + [510709.90580746264, 6651117.673593073, 70.81287832471347], + [510717.13634112646, 6651106.48427118, 74.27943832889592], + [510710.3684396192, 6651113.320213512, 75.38030495267878], + [510709.9059855812, 6651117.669051103, 71.01669960871347], + [510710.06065536645, 6651113.725019602, 75.34259915271348], + [510717.11348029255, 6651107.016909098, 73.95810979389591], + [510710.19657125056, 6651117.685018945, 70.8128412656788], + [510710.0759146255, 6651113.3359132325, 75.98933717171347], + [510709.90746457456, 6651117.631337234, 71.43327889671347], + [510710.1967500939, 6651117.680477004, 71.01666254967878], + [510710.04402766563, 6651114.149020809, 75.26392445971348], + [510710.3520491147, 6651113.736470228, 75.3425620936788], + [510709.88191969466, 6651118.282723741, 70.81287832371348], + [510717.12430293934, 6651106.764750664, 74.56753667989592], + [510710.3673704523, 6651113.347366299, 75.98930011267879], + [510710.05741398566, 6651113.807673804, 75.94656193071349], + [510709.91054752446, 6651117.552722968, 71.85760601671348], + [510717.102579867, 6651107.270879709, 74.20581953389592], + [510710.02732224984, 6651114.575003725, 75.14177133771348], + [510710.19823510404, 6651117.64276337, 71.43324183767879], + [510710.3353537682, 6651114.160468778, 75.26388740067881], + [510710.17258630117, 6651118.294145795, 70.8128412646788], + [510709.8827410376, 6651118.261779752, 71.27846901071347], + [510709.91533422197, 6651117.430663668, 72.28391636771349], + [510710.0107932298, 6651114.996488606, 74.97465658071347], + [510710.3487945472, 6651113.8191239135, 75.94652487167879], + [510710.2013305962, 6651117.564149599, 71.85756895767881], + [510717.1113561369, 6651107.066400111, 74.83273440489593], + [510710.3185803906, 6651114.586449023, 75.14173427867881], + [510710.03856925806, 6651114.288208507, 75.85739727871349], + [510709.921882788, 6651117.263677267, 72.70572522671348], + [510709.99471325486, 6651115.406522973, 74.76237877171347], + [510710.1734109855, 6651118.273201936, 71.2784319516788], + [510709.8853094863, 6651118.196285105, 71.75573996271348], + [510710.2061367672, 6651117.442091064, 72.28387930867879], + [510717.086872065, 6651107.636858092, 74.50326200389594], + [510709.93020111544, 6651117.051562501, 73.11607476971348], + [510710.30198412633, 6651115.007931261, 74.97461952167879], + [510710.02436261857, 6651114.650473405, 75.75830178471347], + [510709.97936095897, 6651115.798001753, 74.50616564871348], + [510709.9684875428, 6651116.075270488, 74.28674664271347], + [510709.94024109386, 6651116.795546168, 73.50785446371349], + [510710.32987315446, 6651114.299655603, 75.8573602196788], + [510709.9582819034, 6651116.335511125, 74.04577699671347], + [510709.9488392565, 6651116.57629569, 73.78533632371347], + [510710.21271197445, 6651117.275105708, 72.70568816767879], + [510710.28583873407, 6651115.417963057, 74.7623417126788], + [510709.88975751295, 6651118.082861807, 72.23864098271348], + [510710.0102260462, 6651115.010951609, 75.63067902571348], + [510710.17598988337, 6651118.2077077, 71.7557029036788], + [510717.0976237003, 6651107.386354167, 75.07282285189594], + [510710.22106414294, 6651117.062992273, 73.1160377106788], + [510710.3156087188, 6651114.6619182285, 75.75826472567879], + [510710.2704239811, 6651115.809439384, 74.50612858967881], + [510709.8943835311, 6651117.96489978, 72.60034696771348], + [510710.2595063292, 6651116.08670638, 74.28670958367879], + [510710.23114496656, 6651116.806977544, 73.50781740467879], + [510709.99628752004, 6651115.3663797, 75.47418773371348], + [510710.24925917067, 6651116.346945386, 74.0457399376788], + [510710.2397781086, 6651116.587728441, 73.7852992646788], + [510710.1804560056, 6651118.094285113, 72.2386039236788], + [510717.0700723364, 6651108.02827743, 74.75947512689594], + [510710.3014146353, 6651115.022394176, 75.6306419666788], + [510709.90013839677, 6651117.818152492, 72.95810481371348], + [510709.9826795926, 6651115.713377625, 75.2889788317135], + [510709.9070227973, 6651117.642602418, 73.30856102871347], + [510709.96953575587, 6651116.048541383, 75.07572649671347], + [510717.08324064704, 6651107.721467031, 75.28607518689593], + [510710.18510084366, 6651117.976323825, 72.6003099086788], + [510710.28741940367, 6651115.377820036, 75.4741506746788], + [510709.9150172357, 6651117.4387467215, 73.64830605571348], + [510709.9569864797, 6651116.368544029, 74.83563804971347], + [510709.92408135295, 6651117.207614545, 73.97397316571347], + [510709.9451551491, 6651116.670239285, 74.57044032471347], + [510709.93415414926, 6651116.950761364, 74.28234197371347], + [510710.19087912154, 6651117.829577458, 72.9580677546788], + [510710.27375611576, 6651115.724815786, 75.2889417726788], + [510710.1977915296, 6651117.654028483, 73.30852396967879], + [510710.26055880653, 6651116.059977442, 75.0756894376788], + [510717.05247632257, 6651108.438249534, 74.97175293589592], + [510710.2058184913, 6651117.450174065, 73.6482689966788], + [510710.2479584768, 6651116.379978082, 74.8356009906788], + [510710.2149194837, 6651117.219043339, 73.9739361066788], + [510717.06834974803, 6651108.068412268, 75.47128408889593], + [510710.2360790134, 6651116.681671446, 74.57040326567879], + [510710.2250332587, 6651116.962191767, 74.28230491467879], + [510717.0343889269, 6651108.859670416, 75.13886769289594], + [510717.0530970812, 6651108.423786389, 75.62777538089593], + [510717.03762769606, 6651108.784209859, 75.75539813989592], + [510717.0161085048, 6651109.28558865, 75.26102081489594], + [510717.0220816379, 6651109.146419749, 75.85449363389593], + [510716.9979131247, 6651109.709525476, 75.33969550789593], + [510716.9800499759, 6651110.125721598, 75.37743836689592], + [510717.001460207, 6651109.626881486, 75.94365828589592], + [510716.98121530504, 6651110.098570424, 75.98643352689592], + [510716.90500901436, 6651111.874111958, 75.37743836689592], + [510716.64421785146, 6651117.950323476, 68.98117101989592], + [510716.64421785146, 6651117.950323476, 69.11117101989592], + [510727.58008760674, 6651105.627760315, 68.96844538400684], + [510716.6180778162, 6651118.559363989, 68.98117101989592], + [510727.5505002783, 6651106.236643095, 68.96844538400684], + [510727.5505002783, 6651106.236643095, 69.09844538400685], + [510716.8315280471, 6651113.5861557815, 75.37743836689592], + [510716.64421775116, 6651117.950325814, 70.80997467989593], + [510716.6444126631, 6651117.945784534, 71.01379596389592], + [510727.58008760674, 6651105.627760315, 70.79724904300684], + [510716.81366489833, 6651114.002351903, 75.33969550789593], + [510716.8303628184, 6651113.613304617, 75.98643352689592], + [510716.6460310976, 6651117.90807639, 71.43037525189592], + [510716.7954695182, 6651114.426288729, 75.26102081489594], + [510716.6180778162, 6651118.559363989, 70.80997467889593], + [510727.57907029736, 6651105.648695701, 71.26283973000683], + [510727.5505002783, 6651106.236643095, 70.79724904300684], + [510716.6494047117, 6651117.829474061, 71.85470237189594], + [510716.8101179163, 6651114.084993556, 75.94365828589592], + [510716.7771890962, 6651114.852206962, 75.13886769289594], + [510716.6189765963, 6651118.53842318, 71.27556536589593], + [510716.6546427047, 6651117.707433295, 72.28101272289592], + [510716.7591017005, 6651115.273627844, 74.97175293589592], + [510727.57588903554, 6651105.714163442, 71.74011068200684], + [510727.5496026525, 6651106.255115492, 71.20806435500684], + [510716.78949648555, 6651114.565455293, 75.85449363389593], + [510716.6618086773, 6651117.5404722495, 72.70282158189592], + [510716.7415056866, 6651115.68359995, 74.75947512689594], + [510716.62178720144, 6651118.472938479, 71.75283631789593], + [510716.67091126635, 6651117.328389692, 73.11317112489593], + [510716.7247059581, 6651116.075019288, 74.50326200389594], + [510716.77395042736, 6651114.927665182, 75.75539813989592], + [510716.7128073834, 6651116.352245921, 74.28384299789592], + [510716.68189782585, 6651117.072412233, 73.50495081889592], + [510716.7016395442, 6651116.612447043, 74.04287335189593], + [510716.6913066334, 6651116.853195047, 73.78243267889593], + [510727.54679565673, 6651106.312881147, 71.62918578300683], + [510727.57037974225, 6651105.827540148, 72.22301170200684], + [510716.6266545933, 6651118.359532403, 72.23573733789593], + [510716.7584810422, 6651115.288088651, 75.62777538089593], + [510716.6317167579, 6651118.241588288, 72.59744332289593], + [510716.7432283754, 6651115.6434627725, 75.47128408889593], + [510716.6380141991, 6651118.094863282, 72.95520116889593], + [510727.5419345156, 6651106.412919416, 72.05527491800686], + [510716.7283374764, 6651115.990408009, 75.28607518689593], + [510727.5646499899, 6651105.945453716, 72.58471768700684], + [510716.64554766903, 6651117.919339863, 73.30565738389592], + [510716.71395442315, 6651116.325520874, 75.07282285189594], + [510730.6378082029, 6651105.778898019, 68.96278941948812], + [510716.65429583244, 6651117.71551512, 73.64540241089593], + [510716.7002219864, 6651116.645474929, 74.83273440489593], + [510716.66421452543, 6651117.484418041, 73.97106952089594], + [510716.6872751841, 6651116.947124376, 74.56753667989592], + [510716.67523699696, 6651117.227603861, 74.27943832889592], + [510727.55752205546, 6651106.092140722, 72.94247553300684], + [510727.53491995385, 6651106.557273301, 72.48018142200684], + [510730.60720602155, 6651106.387730636, 68.96278941948812], + [510730.60720602155, 6651106.387730636, 69.0927894194881], + [510727.5489950873, 6651106.267618683, 73.29293174800685], + [510727.52570994495, 6651106.746807677, 72.89714812400683], + [510727.5390932343, 6651106.471390637, 73.63267677500684], + [510727.51432877325, 6651106.981022789, 73.29909704100683], + [510730.6378082029, 6651105.778898019, 70.7915930784881], + [510727.52786648495, 6651106.702427866, 73.95834388500684], + [510727.50087194075, 6651107.257953289, 73.67897784300683], + [510730.6367559996, 6651105.799831681, 71.2571837654881], + [510730.60720602155, 6651106.387730636, 70.7915930784881], + [510727.5153903929, 6651106.959175534, 74.26671269300684], + [510727.48951472016, 6651107.491675504, 73.94538415800685], + [510730.6334656197, 6651105.865294028, 71.73445471748812], + [510730.6062776069, 6651106.406201512, 71.2024083904881], + [510727.50176463503, 6651107.2395823775, 74.55481104400684], + [510727.47717676946, 6651107.74558034, 74.19309389800684], + [510730.60337433044, 6651106.463962407, 71.62352981848811], + [510730.6277673562, 6651105.978661393, 72.21735573748812], + [510727.48711043544, 6651107.5411537, 74.82000876900683], + [510730.59834645095, 6651106.563992436, 72.0496189534881], + [510730.62184107193, 6651106.0965652475, 72.5790617224881], + [510727.4593974553, 6651108.111463937, 74.49053636800684], + [510727.47156699374, 6651107.86102489, 75.06009721600684], + [510730.6144686474, 6651106.243240168, 72.9368195684881], + [510730.5910912879, 6651106.708334429, 72.4745254574881], + [510727.4403822138, 6651108.5027819015, 74.74674949100684], + [510727.4552871335, 6651108.196050965, 75.27334955100686], + [510730.605649202, 6651106.418703673, 73.2872757834881], + [510730.58156537334, 6651106.897853188, 72.8914921594881], + [510734.3947636187, 6651105.971593879, 68.95465016035759], + [510727.4204656744, 6651108.912647829, 74.95902730000684], + [510727.438432454, 6651108.542906347, 75.45855845300684], + [510730.595407713, 6651106.622458839, 73.6270208104881], + [510730.5697938245, 6651107.1320490055, 73.29344107648811], + [510734.3629145093, 6651106.58036254, 68.95465016035759], + [510734.3629145093, 6651106.58036254, 69.08465016035757], + [510727.39999295096, 6651109.333959568, 75.12614205700685], + [510727.4211682974, 6651108.89818843, 75.61504974500686], + [510730.5837958832, 6651106.853477035, 73.9526879204881], + [510730.5558754192, 6651107.40895669, 73.6733218784881], + [510727.4036588422, 6651109.258518553, 75.74267250400685], + [510727.37930174504, 6651109.759767494, 75.24829517900685], + [510730.570891858, 6651107.110203549, 74.2610567284881], + [510734.3947636187, 6651105.971593879, 70.78345381935759], + [510730.54412864306, 6651107.642659651, 73.9397281934881], + [510727.38606260234, 6651109.620634636, 75.84176799800684], + [510727.35870679637, 6651110.183594526, 75.32696987200684], + [510730.5567987331, 6651107.390587292, 74.54915507948812], + [510734.3936685419, 6651105.992525341, 71.24904450635756], + [510730.5313674974, 6651107.89654357, 74.1874379334881], + [510727.33848789294, 6651110.599682856, 75.36471273100683], + [510727.36272166047, 6651110.100971939, 75.93093265000685], + [510734.3629145093, 6651106.58036254, 70.78345381935759], + [510730.54164189065, 6651107.692133769, 74.8143528044881], + [510734.3902440909, 6651106.057980813, 71.72631545835758], + [510734.3619482651, 6651106.598831477, 71.19426913135757], + [510727.3398069032, 6651110.572538715, 75.97370789100684], + [510730.5129783483, 6651108.262397023, 74.4848804034881], + [510730.52556530497, 6651108.011978609, 75.0544412514881], + [510734.3589266907, 6651106.656586305, 71.61539055935756], + [510734.38431364385, 6651106.171336268, 72.20921647835759], + [510730.493310879, 6651108.653682749, 74.7410935264881], + [510734.35369394324, 6651106.756605824, 72.04147969435758], + [510730.50872704136, 6651108.346977082, 75.26769358648811], + [510734.3781458849, 6651106.289227738, 72.57092246335758], + [510727.2535506866, 6651112.347620404, 75.36471273100683], + [510730.4727111972, 6651109.06351491, 74.95337133548811], + [510734.3704730608, 6651106.435887252, 72.92868030935757], + [510730.49129424203, 6651108.693803888, 75.4529024884881], + [510734.34614315873, 6651106.900932655, 72.46638619835758], + [510726.9583669315, 6651118.422258254, 68.96844538400684], + [510726.9583669315, 6651118.422258254, 69.09844538400685], + [510734.361294255, 6651106.611332324, 73.27913652435757], + [510730.451536254, 6651109.484791939, 75.12048609248811], + [510730.47343792033, 6651109.049056702, 75.6093937804881], + [510734.3362290977, 6651107.090431508, 72.88335290035756], + [510726.9287796031, 6651119.0311410315, 68.96844538400684], + [510730.45532788633, 6651109.40935714, 75.7370165394881], + [510734.3506354625, 6651106.815066086, 73.61888155135759], + [510730.4301353345, 6651109.910564785, 75.24263921448811], + [510734.3239779009, 6651107.324602722, 73.28530181735758], + [510730.4371280909, 6651109.771443389, 75.8361120334881], + [510730.4088339738, 6651110.3343569, 75.32131390748812], + [510734.3385504927, 6651107.046060014, 73.94454866135757], + [510727.17037920334, 6651114.059220828, 75.36471273100683], + [510726.95836681797, 6651118.422260589, 70.79724904400683], + [510734.3094923709, 6651107.601481319, 73.66518261935757], + [510726.95858743443, 6651118.417720486, 71.00107032800683], + [510727.1501602999, 6651114.475309158, 75.32696987200684], + [510730.3879215568, 6651110.750410953, 75.35905676648811], + [510730.41298654873, 6651110.25174112, 75.9252766854881], + [510734.3251206753, 6651107.302759563, 74.25291746935757], + [510727.1690603067, 6651114.086362632, 75.97370789100684], + [510726.96041930467, 6651118.380022108, 71.41764961600684], + [510734.29726695624, 6651107.835159731, 73.93158893435758], + [510727.12956535124, 6651114.89913619, 75.24829517900685], + [510726.9287796031, 6651119.0311410315, 70.79724904300684], + [510730.3892858094, 6651110.723269046, 75.9680519264881], + [510726.9642378239, 6651118.301440137, 71.84197673600684], + [510727.1461455494, 6651114.557929408, 75.93093265000685], + [510734.3104533066, 6651107.583113851, 74.54101582035759], + [510727.1088741453, 6651115.324944116, 75.12614205700685], + [510726.9297969124, 6651119.010205645, 71.26283973000683], + [510734.28398584016, 6651108.089016979, 74.17929867435757], + [510726.97016659245, 6651118.179430978, 72.26828708700685], + [510727.08840142185, 6651115.746255854, 74.95902730000684], + [510727.1228046075, 6651115.038266711, 75.84176799800684], + [510726.9782775985, 6651118.012513173, 72.69009594600683], + [510727.0684848825, 6651116.156121782, 74.74674949100684], + [510726.93297817436, 6651118.944737904, 71.74011068200684], + [510734.29467887775, 6651107.884628652, 74.80621354535756], + [510726.988580618, 6651117.800485543, 73.10044548900684], + [510727.04946964094, 6651116.5474397475, 74.49053636800684], + [510727.10520836763, 6651115.400382793, 75.74267250400685], + [510727.001016062, 6651117.544574378, 73.49222518300685], + [510727.0360019072, 6651116.8245945815, 74.27111736200683], + [510727.0116656833, 6651117.325413967, 73.76970704300683], + [510727.02336127684, 6651117.084728314, 74.03014771600684], + [510734.26484739984, 6651108.454832002, 74.47674114435758], + [510726.9384874676, 6651118.831361199, 72.22301170200684], + [510727.0876989125, 6651115.760712918, 75.61504974500686], + [510726.94421721995, 6651118.7134476295, 72.58471768700684], + [510734.27794722933, 6651108.204439892, 75.04630199235757], + [510730.3000709823, 6651112.498204497, 75.35905676648811], + [510727.0704347558, 6651116.115995001, 75.45855845300684], + [510726.9513451545, 6651118.566760625, 72.94247553300684], + [510729.9947623485, 6651118.572341891, 68.96278941948812], + [510727.0535800763, 6651116.462850382, 75.27334955100686], + [510729.9947623485, 6651118.572341891, 69.0927894194881], + [510726.9598721226, 6651118.391282664, 73.29293174800685], + [510727.03730021615, 6651116.797876457, 75.06009721600684], + [510734.2443785525, 6651108.8460766245, 74.73295426735757], + [510726.9697739755, 6651118.187510709, 73.63267677500684], + [510727.02175677445, 6651117.117747648, 74.82000876900683], + [510726.9810007249, 6651117.956473481, 73.95834388500684], + [510727.00710257486, 6651117.41931897, 74.55481104400684], + [510726.993476817, 6651117.699725813, 74.26671269300684], + [510734.2604228676, 6651108.539403177, 75.25955432735758], + [510729.96416016715, 6651119.181174506, 68.96278941948812], + [510734.2229395084, 6651109.255865734, 74.94523207635757], + [510734.2422797448, 6651108.886193549, 75.44476322935758], + [510734.200901763, 6651109.67709851, 75.11234683335758], + [510734.2236958428, 6651109.241409045, 75.60125452135757], + [510730.21404669574, 6651114.209663911, 75.35905676648811], + [510729.994762231, 6651118.572344227, 70.7915930794881], + [510734.2048478906, 6651109.601671636, 75.72887728035757], + [510729.99499041465, 6651118.567804497, 70.9954143634881], + [510734.1786288335, 6651110.10282663, 75.23449995535758], + [510730.1931342788, 6651114.625717964, 75.32131390748812], + [510730.21268256055, 6651114.23680348, 75.9680519264881], + [510729.9968851186, 6651118.530109226, 71.41199365148812], + [510730.171832918, 6651115.049510078, 75.24263921448811], + [510729.96416016715, 6651119.181174506, 70.7915930784881], + [510734.18590651936, 6651109.963719849, 75.82797277435759], + [510734.1564595195, 6651110.526574227, 75.31317464835759], + [510730.00083461404, 6651118.451533728, 71.8363207714881], + [510730.1889818213, 6651114.708331407, 75.9252766854881], + [510730.1504319985, 6651115.475282923, 75.12048609248811], + [510729.96521237044, 6651119.160240846, 71.2571837654881], + [510730.0069667408, 6651118.32953462, 72.2626311224881], + [510734.13469499734, 6651110.942584574, 75.35091750735758], + [510730.12925705523, 6651115.896559953, 74.95337133548811], + [510734.16078129684, 6651110.443967126, 75.91713742635757], + [510730.16484027903, 6651115.188629137, 75.8361120334881], + [510730.0153559565, 6651118.162630567, 72.6844399814881], + [510730.10865737346, 6651116.306392115, 74.7410935264881], + [510729.96850275033, 6651119.094778499, 71.73445471748812], + [510730.0260123722, 6651117.950620405, 73.0947895244881], + [510730.0889899043, 6651116.6976778405, 74.4848804034881], + [510730.1466404837, 6651115.550715387, 75.7370165394881], + [510730.038874355, 6651117.694730324, 73.4865692184881], + [510730.0750602238, 6651116.974809842, 74.26546139748811], + [510730.0498892612, 6651117.475587968, 73.76405107848811], + [510730.0619860166, 6651117.234922144, 74.0244917514881], + [510734.13611483824, 6651110.91544552, 75.95991266735757], + [510729.9742010138, 6651118.981411134, 72.21735573748812], + [510730.1285304497, 6651115.911015824, 75.6093937804881], + [510729.9801272981, 6651118.863507279, 72.5790617224881], + [510730.110674128, 6651116.266268638, 75.4529024884881], + [510729.9874997227, 6651118.716832358, 72.9368195684881], + [510730.09324132866, 6651116.613095444, 75.26769358648811], + [510729.996319168, 6651118.541368853, 73.2872757834881], + [510730.07640306506, 6651116.948093918, 75.0544412514881], + [510730.00656065706, 6651118.337613688, 73.6270208104881], + [510730.0603264794, 6651117.267938757, 74.8143528044881], + [510730.0181724868, 6651118.106595492, 73.9526879204881], + [510730.04516963696, 6651117.569485234, 74.54915507948812], + [510730.031076512, 6651117.8498689765, 74.2610567284881], + [510734.04326483025, 6651112.69019452, 75.35091750735758], + [510733.72551597597, 6651118.763693851, 68.95465016035759], + [510744.45206085313, 6651106.525420858, 68.92640105436793], + [510733.72551597597, 6651118.763693851, 69.08465016035757], + [510733.69366686663, 6651119.372462511, 68.95465016035759], + [510744.41687374155, 6651107.134005704, 68.92640105436793], + [510744.41687374155, 6651107.134005704, 69.05640105436792], + [510733.9537353658, 6651114.401474153, 75.35091750735758], + [510733.72551585373, 6651118.763696186, 70.78345382035756], + [510744.45206085313, 6651106.525420858, 70.75520471336793], + [510733.7257533351, 6651118.759156933, 70.98727510435758], + [510733.9319708435, 6651114.817484501, 75.31317464835759], + [510733.952315647, 6651114.428610871, 75.95991266735757], + [510744.4508510049, 6651106.546345999, 71.22079540036792], + [510733.7277252413, 6651118.721465621, 71.40385439235759], + [510733.69366686663, 6651119.372462511, 70.78345381935759], + [510733.90980152955, 6651115.241232097, 75.23449995535758], + [510744.41687374155, 6651107.134005704, 70.75520471336793], + [510733.7318356643, 6651118.642898378, 71.82818151235757], + [510733.92764918844, 6651114.900089264, 75.91713742635757], + [510733.88752860005, 6651115.666960218, 75.11234683335758], + [510744.44706764823, 6651106.611781707, 71.69806635236795], + [510733.69476194336, 6651119.351531049, 71.24904450635756], + [510744.41580622847, 6651107.152469065, 71.16602002536793], + [510733.7382176531, 6651118.520912086, 72.25449186335757], + [510733.8654908548, 6651116.088192994, 74.94523207635757], + [510733.902523966, 6651115.380336542, 75.82797277435759], + [510733.74694869894, 6651118.354025566, 72.67630072235758], + [510733.6981863944, 6651119.286075577, 71.72631545835758], + [510733.84405181056, 6651116.497982102, 74.73295426735757], + [510744.4124679726, 6651107.210206454, 71.58714145336793], + [510733.7580393249, 6651118.142037674, 73.08665026535758], + [510744.4405156502, 6651106.725102936, 72.18096737236793], + [510733.8235829632, 6651116.889226725, 74.47674114435758], + [510733.8835825948, 6651115.742384755, 75.72887728035757], + [510733.77142538695, 6651117.886174472, 73.47842995935757], + [510733.80908569874, 6651117.166329616, 74.25732213835758], + [510733.7828891107, 6651117.667055137, 73.75591181935758], + [510733.79547876486, 6651117.426414593, 74.01635249235757], + [510733.7041168414, 6651119.172720123, 72.20921647835759], + [510733.86473464256, 6651116.102647346, 75.60125452135757], + [510733.7102846004, 6651119.054828652, 72.57092246335758], + [510744.40668679785, 6651107.310195773, 72.01323058836793], + [510744.4337014684, 6651106.842958809, 72.54267335736793], + [510733.84615074046, 6651116.457862841, 75.44476322935758], + [510733.71795742447, 6651118.908169139, 72.92868030935757], + [510733.8280076178, 6651116.804653214, 75.25955432735758], + [510733.7271362303, 6651118.732724067, 73.27913652435757], + [510733.8104832559, 6651117.139616499, 75.04630199235757], + [510733.7377950229, 6651118.528990304, 73.61888155135759], + [510733.79375160753, 6651117.459427739, 74.80621354535756], + [510733.7498799926, 6651118.297996378, 73.94454866135757], + [510744.42522448045, 6651106.989574039, 72.90043120336794], + [510733.7779771788, 6651117.76094254, 74.54101582035759], + [510733.7633098101, 6651118.041296829, 74.25291746935757], + [510744.3983446399, 6651107.454479025, 72.43813709236792], + [510744.4150836736, 6651107.164966137, 73.25088741836792], + [510744.38739151816, 6651107.643920658, 72.85510379436793], + [510744.4033077675, 6651107.368638382, 73.59063244536793], + [510744.37385631306, 6651107.878021168, 73.25705271136792], + [510744.38995621103, 6651107.599562564, 73.91629955536793], + [510744.35785260145, 6651108.154816163, 73.63693351336792], + [510744.3751188579, 6651107.856184602, 74.22466836336794], + [510744.3443458806, 6651108.388424016, 73.90333982836795], + [510744.35891424963, 6651108.1364542395, 74.51276671436793], + [510744.32967281365, 6651108.642204613, 74.15104956836792], + [510744.34148655395, 6651108.437878001, 74.77796443936792], + [510744.3085285353, 6651109.00790918, 74.44849203836793], + [510744.3230013157, 6651108.757592674, 75.01805288636793], + [510750.856643526, 6651106.906945225, 68.9035058657163], + [510744.2859144142, 6651109.399035669, 74.70470516136793], + [510744.3036402822, 6651109.092454818, 75.23130522136793], + [510750.8193307429, 6651107.515403444, 68.9035058657163], + [510744.26222841314, 6651109.808701046, 74.91698297036794], + [510750.8193307429, 6651107.515403444, 69.0335058657163], + [510744.28359563736, 6651109.43914048, 75.41651412336795], + [510751.5875913436, 6651106.951915768, 68.90065002138758], + [510744.23788096296, 6651110.229806632, 75.08409772736793], + [510744.26306401653, 6651109.794248721, 75.57300541536793], + [510751.5500359599, 6651107.560359061, 68.90065002138758], + [510751.5500359599, 6651107.560359061, 69.03065002138757], + [510750.856643526, 6651106.906945225, 70.7323095247163], + [510744.24224067136, 6651110.154402531, 75.70062817436792], + [510744.21327367966, 6651110.655406205, 75.20625084936793], + [510750.8553605902, 6651106.927866013, 71.1979002117163], + [510744.2213141163, 6651110.5163414255, 75.79972366836793], + [510744.1887808716, 6651111.079025854, 75.28492554236793], + [510750.8193307429, 6651107.515403444, 70.7323095247163], + [510751.5875913436, 6651106.951915768, 70.72945368038758], + [510750.851348679, 6651106.993288105, 71.6751711637163], + [510744.16473528015, 6651111.49491059, 75.32266840136792], + [510750.8181987407, 6651107.533862962, 71.14312483671631], + [510744.1935556005, 6651110.996443695, 75.88888832036793], + [510751.5863000664, 6651106.972836043, 71.19504436738757], + [510750.81465881906, 6651107.591588338, 71.56424626471629], + [510750.84440087137, 6651107.106585755, 72.1580721837163], + [510744.1663039301, 6651111.4677797295, 75.93166356136794], + [510751.5500359599, 6651107.560359061, 70.72945368038758], + [510751.5822620705, 6651107.038256531, 71.67231531938758], + [510751.5488965977, 6651107.578818127, 71.14026899238758], + [510750.80852840055, 6651107.691556854, 71.9903353997163], + [510750.8371750413, 6651107.224417107, 72.51977816871631], + [510751.54533366015, 6651107.636542086, 71.56139042038757], + [510750.82818595413, 6651107.37100183, 72.87753601471631], + [510751.5752690896, 6651107.1515514, 72.15521633938758], + [510750.7996822885, 6651107.835810084, 72.41524190371629], + [510744.06372261286, 6651113.2419928545, 75.32266840136792], + [510743.7126715283, 6651119.313658325, 68.92640105436793], + [510751.53916338284, 6651107.73650815, 71.9874795553876], + [510751.5679962787, 6651107.269379862, 72.51692232438758], + [510743.7126715283, 6651119.313658325, 69.05640105436792], + [510750.817432536, 6651107.546357435, 73.22799222971629], + [510750.78806748305, 6651108.025212301, 72.83220860571629], + [510751.5589487461, 6651107.415960989, 72.87468017038758], + [510751.53025975515, 6651107.880757842, 72.41238605938757], + [510743.6774844167, 6651119.92224317, 68.92640105436793], + [510750.8049452412, 6651107.749987303, 73.5677372567163], + [510750.77371460927, 6651108.259264101, 73.2341575227163], + [510751.54812541127, 6651107.591312292, 73.22513638538757], + [510751.5185694325, 6651108.070155413, 72.82935276138757], + [510750.79078711045, 6651107.980863436, 73.8934043667163], + [510750.7567441052, 6651108.536001503, 73.61403832471629], + [510751.53555692657, 6651107.794937166, 73.56488141238758], + [510743.96480985463, 6651114.952755776, 75.32266840136792], + [510743.71267139324, 6651119.31366066, 70.75520471436792], + [510750.77505342505, 6651108.237432078, 74.20177317471631], + [510751.5041232391, 6651108.304201472, 73.23130167838758], + [510743.7129337642, 6651119.309122778, 70.95902599836792], + [510750.74242143636, 6651108.769560751, 73.8804446397163], + [510743.94076426316, 6651115.36864051, 75.28492554236793], + [510751.52130674233, 6651108.025807634, 73.89054852238758], + [510743.9632413397, 6651114.979884299, 75.93166356136794], + [510743.71511233953, 6651119.271442845, 71.37560528636793], + [510750.75786988804, 6651108.5176434005, 74.4898715257163], + [510743.6774844167, 6651119.92224317, 70.75520471336793], + [510743.9162714551, 6651115.792260159, 75.20625084936793], + [510751.487042396, 6651108.580932085, 73.61118248038757], + [510750.72686196177, 6651109.023288545, 74.12815437971629], + [510743.71965356276, 6651119.192899325, 71.79993240636793], + [510743.93598966935, 6651115.451220333, 75.88888832036793], + [510743.8916641718, 6651116.217859733, 75.08409772736793], + [510751.5054707596, 6651108.282369984, 74.19891733038757], + [510743.6786942649, 6651119.901318029, 71.22079540036792], + [510750.7393893763, 6651108.819004444, 74.75506925071629], + [510743.72670442716, 6651119.070949866, 72.22624275736793], + [510751.472626604, 6651108.814485602, 73.87758879538757], + [510743.86731672165, 6651116.63896532, 74.91698297036794], + [510743.9082311535, 6651115.9313226035, 75.79972366836793], + [510743.7363505456, 6651118.904113736, 72.64805161636792], + [510750.7044403466, 6651109.38891702, 74.42559684971631], + [510743.6824776216, 6651119.835882322, 71.69806635236795], + [510743.84363072057, 6651117.048630697, 74.70470516136793], + [510751.4881754986, 6651108.562574432, 74.48701568138758], + [510743.74860354426, 6651118.692189854, 73.05840115936793], + [510743.8210165995, 6651117.439757184, 74.44849203836793], + [510743.88730459847, 6651116.293261498, 75.70062817436792], + [510743.7633925562, 6651118.436403908, 73.45018085336793], + [510743.8049999236, 6651117.716776405, 74.22907303236792], + [510750.7197874351, 6651109.1386525985, 74.9951576977163], + [510751.4569659648, 6651109.068207172, 74.12529853538757], + [510743.7760577557, 6651118.217350735, 73.72766271336792], + [510743.78996689094, 6651117.976782853, 73.98810338636792], + [510743.6890296196, 6651119.722561093, 72.18096737236793], + [510743.8664812533, 6651116.653415308, 75.57300541536793], + [510743.6958438014, 6651119.604705219, 72.54267335736793], + [510750.6804600949, 6651109.779962127, 74.6818099727163], + [510743.84594963246, 6651117.008523548, 75.41651412336795], + [510751.4695748301, 6651108.863928085, 74.75221340638757], + [510743.7043207894, 6651119.45808999, 72.90043120336794], + [510750.6992567916, 6651109.473445066, 75.2084100327163], + [510743.82590498775, 6651117.355209211, 75.23130522136793], + [510743.7144615962, 6651119.282697892, 73.25088741836792], + [510751.43439856864, 6651109.433826678, 74.42274100538758], + [510743.8065439542, 6651117.690071355, 75.01805288636793], + [510743.7262375024, 6651119.079025646, 73.59063244536793], + [510743.7880587159, 6651118.009786028, 74.77796443936792], + [510743.7395890588, 6651118.848101465, 73.91629955536793], + [510743.7706310202, 6651118.3112097895, 74.51276671436793], + [510743.75442641194, 6651118.591479427, 74.22466836336794], + [510751.44984544086, 6651109.183568395, 74.99230185338757], + [510750.65534321027, 6651110.189542265, 74.8940877817163], + [510750.67800123943, 6651109.820058594, 75.3936189347163], + [510751.4102624018, 6651109.824862193, 74.67895412838757], + [510751.42918131105, 6651109.518352652, 75.2055541883876], + [510750.6295249179, 6651110.610560233, 75.0612025387163], + [510750.6562292928, 6651110.175092947, 75.5501102267163], + [510751.3849822121, 6651110.234432285, 74.89123193738757], + [510751.40778755944, 6651109.864957676, 75.39076309038758], + [510750.63414799864, 6651110.535171822, 75.67773298571629], + [510750.603431096, 6651111.036071253, 75.1833556607163], + [510751.3589960542, 6651110.655439925, 75.05834669438758], + [510750.6119572596, 6651110.897035409, 75.7768284797163], + [510751.3858740558, 6651110.219983321, 75.54725438238759], + [510750.5774586647, 6651111.45960276, 75.2620303537163], + [510751.3636491933, 6651110.580053363, 75.67487714138758], + [510751.33273257525, 6651111.080940507, 75.18049981638758], + [510750.5519604666, 6651111.875400962, 75.29977321271629], + [510750.58252183744, 6651111.377037784, 75.8659931317163], + [510751.3413141743, 6651110.941908073, 75.77397263538758], + [510751.3065912763, 6651111.504461624, 75.25917450938758], + [510750.55362387956, 6651111.848275747, 75.90876837271631], + [510751.2809272938, 6651111.920249627, 75.29691736838757], + [510751.3116873687, 6651111.421898673, 75.86313728738759], + [510751.282601522, 6651111.893125078, 75.90591252838757], + [510750.44484557194, 6651113.6221197145, 75.29977321271629], + [510750.07258730987, 6651119.692521863, 68.9035058657163], + [510750.07258730987, 6651119.692521863, 69.0335058657163], + [510750.03527452674, 6651120.30098008, 68.9035058657163], + [510761.3150627726, 6651107.578246551, 68.8579046167634], + [510751.1731159588, 6651113.666925532, 75.29691736838757], + [510750.7984373454, 6651119.73717877, 68.90065002138758], + [510750.7984373454, 6651119.73717877, 69.03065002138757], + [510761.2742788554, 6651108.186481965, 68.8579046167634], + [510761.2742788554, 6651108.186481965, 68.98790461676339], + [510750.7608819617, 6651120.345622063, 68.90065002138758], + [510750.3399574428, 6651115.332526679, 75.29977321271629], + [510750.0725871666, 6651119.692524197, 70.7323095257163], + [510750.07286538754, 6651119.687987258, 70.93613080971629], + [510750.3144592448, 6651115.748324881, 75.2620303537163], + [510750.33829417307, 6651115.359649558, 75.90876837271631], + [510750.07517557184, 6651119.650315166, 71.3527100977163], + [510750.03527452674, 6651120.30098008, 70.7323095247163], + [510750.2884868135, 6651116.171856388, 75.1833556607163], + [510761.3150627726, 6651107.578246551, 70.68670827576341], + [510750.07999113266, 6651119.57178799, 71.77703721771631], + [510751.0675458673, 6651115.377290539, 75.29691736838757], + [510750.79843720124, 6651119.737181106, 70.72945368138757], + [510750.30939621525, 6651115.830887522, 75.8659931317163], + [510750.2623929916, 6651116.597367409, 75.0612025387163], + [510750.0365574624, 6651120.280059292, 71.1979002117163], + [510750.7987172311, 6651119.732644279, 70.93327496538757], + [510750.0874679433, 6651119.449863903, 72.2033475687163], + [510761.3136604879, 6651107.599159678, 71.15229896276338], + [510750.2365746992, 6651117.018385376, 74.8940877817163], + [510751.0418818849, 6651115.793078542, 75.25917450938758], + [510750.27996079304, 6651116.310889898, 75.7768284797163], + [510750.0976967889, 6651119.283062487, 72.62515642771629], + [510761.2742788554, 6651108.186481965, 70.68670827576341], + [510750.04056937364, 6651120.214637199, 71.6751711637163], + [510750.2114578146, 6651117.427965514, 74.6818099727163], + [510751.06587178336, 6651115.404412754, 75.90591252838757], + [510750.8010424357, 6651119.69497311, 71.34985425338758], + [510750.1106899975, 6651119.071182698, 73.0355059707163], + [510750.7608819617, 6651120.345622063, 70.72945368038758], + [510750.18747756275, 6651117.819010622, 74.42559684971631], + [510751.0157405858, 6651116.21659966, 75.18049981638758], + [510750.2577700541, 6651116.672753485, 75.67773298571629], + [510750.1263724214, 6651118.815449975, 73.4272856647163], + [510750.17049331125, 6651118.095972205, 74.20617784371629], + [510750.1398027321, 6651118.596442379, 73.7047675247163], + [510750.1545521254, 6651118.355924551, 73.96520819771631], + [510761.3092753565, 6651107.664557815, 71.6295699147634], + [510750.0475171813, 6651120.101339551, 72.1580721837163], + [510761.2730415454, 6651108.204934724, 71.09752358776339], + [510750.80588930636, 6651119.6164478585, 71.77418137338758], + [510750.2356887598, 6651117.032832358, 75.5501102267163], + [510751.03678593657, 6651115.875639157, 75.86313728738759], + [510750.9894771069, 6651116.642100242, 75.05834669438758], + [510750.76217323885, 6651120.324701788, 71.19504436738757], + [510750.0547430113, 6651119.9835081985, 72.51977816871631], + [510750.2139168132, 6651117.387866712, 75.3936189347163], + [510750.8134147299, 6651119.494526765, 72.20049172438759], + [510750.0637320985, 6651119.836923476, 72.87753601471631], + [510750.96349094907, 6651117.063107883, 74.89123193738757], + [510761.2691723118, 6651108.262638962, 71.5186450157634], + [510750.1926612611, 6651117.7344802385, 75.2084100327163], + [510751.007159131, 6651116.355629758, 75.77397263538758], + [510750.8237100814, 6651119.32772944, 72.62230058338757], + [510761.30168120813, 6651107.777813977, 72.11247093476341], + [510750.07448551664, 6651119.6615678705, 73.22799222971629], + [510750.7662112348, 6651120.259281302, 71.67231531938758], + [510750.17213061755, 6651118.069272708, 74.9951576977163], + [510750.93821075937, 6651117.472677973, 74.67895412838757], + [510750.08697281143, 6651119.457938003, 73.5677372567163], + [510750.15252867644, 6651118.38892086, 74.75506925071629], + [510750.83678776934, 6651119.115854849, 73.03265012638758], + [510750.1011309423, 6651119.2270618705, 73.8934043667163], + [510750.1340481646, 6651118.690281905, 74.4898715257163], + [510750.9140745925, 6651117.863713488, 74.42274100538758], + [510750.1168646276, 6651118.970493227, 74.20177317471631], + [510750.984824112, 6651116.717484468, 75.67487714138758], + [510750.85257215734, 6651118.860128398, 73.42442982038759], + [510750.8969799127, 6651118.140668276, 74.20332199938757], + [510750.8660897893, 6651118.6411261745, 73.70191168038758], + [510750.8809350803, 6651118.400614246, 73.96235235338757], + [510750.77320421574, 6651120.14598643, 72.15521633938758], + [510761.26247159275, 6651108.362570872, 71.9447341507634], + [510761.2937831736, 6651107.895602181, 72.4741769197634], + [510750.9625992495, 6651117.077554509, 75.54725438238759], + [510750.78047702665, 6651120.028157969, 72.51692232438758], + [510750.94068574585, 6651117.432580154, 75.39076309038758], + [510750.7895245592, 6651119.881576842, 72.87468017038758], + [510750.9192919943, 6651117.779185179, 75.2055541883876], + [510761.28395784943, 6651108.042133229, 72.83193476576339], + [510750.800347894, 6651119.706225539, 73.22513638538757], + [510761.2528025445, 6651108.5067712795, 72.36964065476339], + [510750.8986278645, 6651118.113969435, 74.99230185338757], + [510750.8129163787, 6651119.502600665, 73.56488141238758], + [510750.8788984752, 6651118.433609747, 74.75221340638757], + [510750.82716656296, 6651119.271730197, 73.89054852238758], + [510750.86029780674, 6651118.734963399, 74.48701568138758], + [510750.84300254576, 6651119.015167847, 74.19891733038757], + [510761.2722040622, 6651108.217424622, 73.18239098076339], + [510761.2401072368, 6651108.696104142, 72.78660735676338], + [510761.25855509925, 6651108.420979925, 73.52213600776341], + [510761.2244191437, 6651108.930070237, 73.1885562737634], + [510761.24307986564, 6651108.651771516, 73.84780311776339], + [510761.2058699073, 6651109.206706304, 73.56843707576338], + [510761.2258825069, 6651108.908246209, 74.15617192576339], + [510761.19021482917, 6651109.440180027, 73.83484339076338], + [510761.20710041956, 6651109.188354924, 74.4442702767634], + [510761.1732078877, 6651109.693814911, 74.08255313076339], + [510761.1869007026, 6651109.489605617, 74.70946800176338], + [510761.14870043425, 6651110.059309501, 74.3799956007634], + [510761.16547523177, 6651109.80913672, 74.94955644876339], + [510761.1224893473, 6651110.450211417, 74.63620872376339], + [510761.14303466334, 6651110.143806596, 75.1628087837634], + [510761.0950358888, 6651110.859641577, 74.84848653276339], + [510761.1198017494, 6651110.490293201, 75.3480176857634], + [510761.0668157721, 6651111.280505376, 75.0156012897634], + [510761.0960044019, 6651110.84519755, 75.5045089777634], + [510768.77047211194, 6651108.093390549, 68.81917060298551], + [510761.07186892885, 6651111.20514457, 75.63213173676338], + [510761.0382944938, 6651111.705860583, 75.1377544117634], + [510768.72721375537, 6651108.701454987, 68.81917060298551], + [510761.04761382943, 6651111.5668756515, 75.73122723076341], + [510768.72721375537, 6651108.701454987, 68.9491706029855], + [510761.0099058989, 6651112.129237003, 75.2164291047634], + [510760.9820356542, 6651112.5448829485, 75.2541719637634], + [510761.01544008846, 6651112.04670226, 75.82039188276339], + [510768.77047211194, 6651108.093390549, 70.64797426198551], + [510760.9838538111, 6651112.517767667, 75.86316712376339], + [510768.76898474793, 6651108.114297796, 71.1135649489855], + [510768.72721375537, 6651108.701454987, 70.64797426198551], + [510768.7643335621, 6651108.17967755, 71.59083590098551], + [510768.7259013753, 6651108.719902559, 71.05878957398552], + [510760.86495607387, 6651114.290962093, 75.2541719637634], + [510771.06181310286, 6651108.257839253, 68.80622400340143], + [510760.45806736604, 6651120.359141392, 68.8579046167634], + [510760.45806736604, 6651120.359141392, 68.98790461676339], + [510768.72179738793, 6651108.777590576, 71.4799110019855], + [510768.7562786621, 6651108.292901875, 72.07373692098551], + [510771.01779425354, 6651108.865849112, 68.80622400340143], + [510760.4172834488, 6651120.967376806, 68.8579046167634], + [510768.7146901231, 6651108.877494394, 71.90600013698551], + [510771.01779425354, 6651108.865849112, 68.93622400340142], + [510768.7479014383, 6651108.410656969, 72.43544290598551], + [510768.7374799928, 6651108.557146828, 72.79320075198551], + [510768.704434435, 6651109.021654268, 72.3309066409855], + [510760.7503104106, 6651116.000742743, 75.2541719637634], + [510768.72501308034, 6651108.732388945, 73.1436569669855], + [510771.06181310286, 6651108.257839253, 70.63502766240143], + [510760.45806720946, 6651120.359143726, 70.68670827676338], + [510768.6909688783, 6651109.210933909, 72.7478733429855], + [510760.45837131276, 6651120.354608448, 70.8905295607634], + [510760.72244016593, 6651116.416388689, 75.2164291047634], + [510771.0602995905, 6651108.278744626, 71.10061834940143], + [510768.7105360084, 6651108.935887029, 73.48340199398551], + [510760.46089640877, 6651120.316950152, 71.3071088487634], + [510760.7484924103, 6651116.027855691, 75.86316712376339], + [510771.01779425354, 6651108.865849112, 70.63502766240143], + [510760.4172834488, 6651120.967376806, 70.68670827576341], + [510760.694051571, 6651116.839765109, 75.1377544117634], + [510768.67432895803, 6651109.444834236, 73.1498222599855], + [510760.4661599517, 6651120.2384517295, 71.73143596876339], + [510771.0555666358, 6651108.34411851, 71.57788930140143], + [510760.71690613293, 6651116.498921096, 75.82039188276339], + [510760.6655302927, 6651117.265120316, 75.0156012897634], + [510771.0164588016, 6651108.884295029, 71.04584297440144], + [510760.41868573363, 6651120.946463679, 71.15229896276338], + [510768.69412186235, 6651109.166613744, 73.80906910398552], + [510760.47433231527, 6651120.116572291, 72.15774631976339], + [510760.6373101761, 6651117.685984117, 74.84848653276339], + [510768.65465430357, 6651109.721392539, 73.5297030619855], + [510760.48551272985, 6651119.949831951, 72.57955517876339], + [510760.68473239196, 6651116.978747706, 75.73122723076341], + [510760.42307086487, 6651120.881065543, 71.6295699147634], + [510771.012282665, 6651108.941977868, 71.46696440240142], + [510760.60985671764, 6651118.095414275, 74.63620872376339], + [510771.04737012857, 6651108.4573326735, 72.06079032140143], + [510760.4997146709, 6651119.73802975, 72.9899047217634], + [510768.6758811064, 6651109.423016342, 74.1174379119855], + [510760.5836456307, 6651118.486316191, 74.3799956007634], + [510760.66047729267, 6651117.340478787, 75.63213173676338], + [510760.5168559994, 6651119.482390669, 73.38168441576339], + [510760.5650813679, 6651118.763176355, 74.1605765947634], + [510760.5315357052, 6651119.263463269, 73.6591662757634], + [510760.5476572053, 6651119.023033513, 73.91960694876339], + [510760.43066501326, 6651120.76780938, 72.11247093476341], + [510768.6380494014, 6651109.954800633, 73.7961093769855], + [510760.6363418195, 6651117.700425807, 75.5045089777634], + [510771.0050504527, 6651109.041872717, 71.89305353740141], + [510760.4385630479, 6651120.650021177, 72.4741769197634], + [510771.03884563124, 6651108.575077197, 72.42249630640144], + [510760.61254447204, 6651118.055330155, 75.3480176857634], + [510768.65595947346, 6651109.703046319, 74.4055362629855], + [510760.44838837197, 6651120.503490129, 72.83193476576339], + [510760.5893115582, 6651118.40181676, 75.1628087837634], + [510768.62001061573, 6651110.20836422, 74.04381911698552], + [510760.4601421593, 6651120.328198736, 73.18239098076339], + [510760.5668709896, 6651118.736486637, 74.94955644876339], + [510760.4737911222, 6651120.124643432, 73.52213600776341], + [510771.028240974, 6651108.721553905, 72.78025415240143], + [510760.5454455189, 6651119.056017741, 74.70946800176338], + [510770.9946144671, 6651109.1860196525, 72.31796004140142], + [510760.4892663558, 6651119.893851841, 73.84780311776339], + [510760.5252458018, 6651119.357268432, 74.4442702767634], + [510760.5064637145, 6651119.637377148, 74.15617192576339], + [510768.6345342003, 6651110.004212329, 74.67073398798551], + [510768.5940162476, 6651110.57375607, 74.34126158698552], + [510771.01555489015, 6651108.896780294, 73.13071036740142], + [510770.98091218254, 6651109.375282303, 72.73492674340142], + [510768.61180880474, 6651110.323653613, 74.91082243498552], + [510771.0008233076, 6651109.1002601115, 73.47045539440143], + [510768.56621488306, 6651110.964548103, 74.59747470998552], + [510770.96397972835, 6651109.609161634, 73.13687566040143], + [510768.5880067233, 6651110.658229413, 75.12407476998551], + [510770.98412059684, 6651109.330966116, 73.79612250440144], + [510768.53709577, 6651111.37386317, 74.8097525189855], + [510768.5633642235, 6651111.00461862, 75.30928367198551], + [510770.9439591885, 6651109.885695116, 73.51675646240142], + [510770.9655591638, 6651109.587345701, 74.10449131240142], + [510768.5071634841, 6651111.794608666, 74.97686727598553], + [510768.5381230447, 6651111.359423203, 75.46577496398551], + [510770.92706236796, 6651110.119082257, 73.78316277740142], + [510770.9452873036, 6651109.86735054, 74.39258966340142], + [510768.5125232256, 6651111.719269044, 75.5933977229855], + [510768.4769117645, 6651112.219844305, 75.0990203979855], + [510770.908706456, 6651110.372623084, 74.03087251740142], + [510770.92348536884, 6651110.168489519, 74.65778738840143], + [510768.4867965223, 6651112.08089844, 75.69249321698551], + [510768.4468007783, 6651112.643101713, 75.17769509098551], + [510770.8822551003, 6651110.737982137, 74.32831498740144], + [510770.900360455, 6651110.487902128, 74.89787583540142], + [510768.4172395918, 6651113.05863082, 75.2154379499855], + [510768.452670738, 6651112.56059017, 75.7816578689855], + [510770.8539649809, 6651111.128739091, 74.58452811040144], + [510770.87613992713, 6651110.822447896, 75.11112817040143], + [510768.4191680598, 6651113.031523161, 75.8244331099855], + [510770.8243339465, 6651111.538017418, 74.79680591940142], + [510770.851064206, 6651111.168806013, 75.29633707240143], + [510778.1676664001, 6651108.786148307, 68.76295607119135], + [510770.7938754436, 6651111.958725148, 74.96392067640143], + [510770.82537928096, 6651111.523578749, 75.45282836440143], + [510767.86148113036, 6651120.870692668, 68.81917060298551], + [510768.293056566, 6651114.804219138, 75.2154379499855], + [510767.86148113036, 6651120.870692668, 68.9491706029855], + [510778.12128912844, 6651109.39398282, 68.76295607119135], + [510770.7993294106, 6651111.883392287, 75.58045112340142], + [510770.76309189113, 6651112.383922617, 75.08607379840143], + [510778.12128912844, 6651109.39398282, 68.89295607119135], + [510767.8182227738, 6651121.478757107, 68.81917060298551], + [510770.77315042546, 6651112.244989226, 75.67954661740143], + [510770.7324515464, 6651112.807142033, 75.16474849140143], + [510770.7023706667, 6651113.222633842, 75.20249135040142], + [510770.7384247013, 6651112.724637897, 75.76871126940142], + [510778.1676664001, 6651108.786148307, 70.59175973019136], + [510768.17145512794, 6651116.513519169, 75.2154379499855], + [510767.8614809644, 6651120.870695001, 70.6479742629855], + [510770.7043330378, 6651113.195528616, 75.81148651040142], + [510778.1660717975, 6651108.807047649, 71.05735041719136], + [510767.86180351814, 6651120.866161, 70.8517955469855], + [510778.12128912844, 6651109.39398282, 70.59175973019136], + [510768.14189394144, 6651116.9290482765, 75.17769509098551], + [510767.8644818167, 6651120.828513289, 71.26837483498551], + [510768.16952682595, 6651116.540624496, 75.8244331099855], + [510767.8182227738, 6651121.478757107, 70.64797426198551], + [510778.1610852626, 6651108.87240268, 71.53462136919136], + [510778.11988212616, 6651109.412423416, 71.00257504219137], + [510768.1117829553, 6651117.352305684, 75.0990203979855], + [510767.8700647089, 6651120.750036932, 71.69270195498551], + [510768.1360241478, 6651117.011557484, 75.7816578689855], + [510768.0815312357, 6651117.7775413245, 74.97686727598553], + [510767.81971013796, 6651121.457849858, 71.1135649489855], + [510778.1154822424, 6651109.470089621, 71.42369647019135], + [510767.8787329057, 6651120.628191753, 72.1190123059855], + [510778.1524496065, 6651108.985584193, 72.01752238919136], + [510770.1368418328, 6651121.0339944735, 68.80622400340143], + [510768.05159894977, 6651118.19828682, 74.8097525189855], + [510770.5760044724, 6651114.968065476, 75.20249135040142], + [510770.1368418328, 6651121.0339944735, 68.93622400340142], + [510767.8905916578, 6651120.461498286, 72.5408211649855], + [510768.1018983635, 6651117.491249215, 75.69249321698551], + [510767.82436132367, 6651121.3924701065, 71.59083590098551], + [510768.0224798366, 6651118.607601887, 74.59747470998552], + [510767.9056552582, 6651120.24975562, 72.95117070798551], + [510778.1078625459, 6651109.569955662, 71.84978560519136], + [510767.99467847217, 6651118.998393919, 74.34126158698552], + [510778.1434683874, 6651109.103294761, 72.37922837419137], + [510768.07617166016, 6651117.8528786125, 75.5933977229855], + [510767.9238365844, 6651119.994188401, 73.3429504019855], + [510767.97498787957, 6651119.275176259, 74.1218425809855], + [510767.9394069364, 6651119.7753225425, 73.6204322619855], + [510767.9565065591, 6651119.5349603705, 73.8808729349855], + [510767.83241622377, 6651121.279245781, 72.07373692098551], + [510770.09282298345, 6651121.642004333, 68.80622400340143], + [510768.0505718411, 6651118.212724451, 75.46577496398551], + [510767.84079344745, 6651121.161490685, 72.43544290598551], + [510768.02533066226, 6651118.567529035, 75.30928367198551], + [510778.1322955586, 6651109.249729227, 72.73698622019135], + [510778.09686742566, 6651109.7140610255, 72.27469210919135], + [510767.8512148931, 6651121.015000829, 72.79320075198551], + [510768.00068816246, 6651118.913918243, 75.12407476998551], + [510767.86368180544, 6651120.839758709, 73.1436569669855], + [510767.97688608104, 6651119.248494042, 74.91082243498552], + [510767.87815887737, 6651120.636260627, 73.48340199398551], + [510767.9541606855, 6651119.567935327, 74.67073398798551], + [510767.8945730234, 6651120.405533911, 73.80906910398552], + [510767.9327354123, 6651119.869101336, 74.4055362629855], + [510767.9128137794, 6651120.149131312, 74.1174379119855], + [510778.1189297854, 6651109.424905081, 73.08744243519135], + [510778.0824310062, 6651109.903269094, 72.69165881119135], + [510770.4522652506, 6651116.677212078, 75.20249135040142], + [510770.13684166386, 6651121.0339968065, 70.63502766340143], + [510778.1034089207, 6651109.628326218, 73.42718746219136], + [510770.13716988824, 6651121.029463212, 70.83884894740142], + [510778.0645913526, 6651110.137080977, 73.09360772819136], + [510770.42218437104, 6651117.092703887, 75.16474849140143], + [510770.1398952719, 6651120.991818881, 71.25542823540142], + [510770.45030304865, 6651116.70431497, 75.81148651040142], + [510770.09282298345, 6651121.642004333, 70.63502766240143], + [510778.08581131947, 6651109.858965688, 73.75285457219137], + [510770.3915440263, 6651117.515923304, 75.08607379840143], + [510770.14557631285, 6651120.913349567, 71.67975535540144], + [510778.04349816113, 6651110.413534708, 73.47348853019135], + [510770.36076047394, 6651117.941120773, 74.96392067640143], + [510770.416211385, 6651117.17520569, 75.76871126940142], + [510770.0943364958, 6651121.621098961, 71.10061834940143], + [510770.1543968986, 6651120.791515325, 72.10606570640142], + [510778.0662554103, 6651110.1152713355, 74.06122338019135], + [510770.3303019709, 6651118.361828502, 74.79680591940142], + [510770.1664641305, 6651120.624836821, 72.52787456540142], + [510770.0990694505, 6651121.555725077, 71.57788930140143], + [510770.38148566097, 6651117.654854361, 75.67954661740143], + [510778.0256960504, 6651110.646854544, 73.73989484519134], + [510770.3006709365, 6651118.771106829, 74.58452811040144], + [510770.18179255276, 6651120.413113163, 72.93822410840143], + [510770.27238081716, 6651119.161863784, 74.32831498740144], + [510770.2002935112, 6651120.157568882, 73.33000380240142], + [510770.3553066757, 6651118.016451299, 75.58045112340142], + [510770.252344059, 6651119.43862128, 74.10889598140142], + [510770.21613759396, 6651119.938722669, 73.60748566240143], + [510770.2335378323, 6651119.698382073, 73.86792633540144], + [510770.10726595775, 6651121.442510913, 72.06079032140143], + [510778.0448974334, 6651110.395195425, 74.34932173119135], + [510770.32925680536, 6651118.3762648385, 75.45282836440143], + [510778.00635667343, 6651110.900322251, 73.98760458519135], + [510770.1157904552, 6651121.32476639, 72.42249630640144], + [510770.3035718804, 6651118.731037575, 75.29633707240143], + [510770.1263951124, 6651121.178289681, 72.78025415240143], + [510770.2784961593, 6651119.07739569, 75.11112817040143], + [510770.13908119616, 6651121.003063292, 73.13071036740142], + [510778.02192740433, 6651110.696247556, 74.61451945619136], + [510770.25427563133, 6651119.411941458, 74.89787583540142], + [510770.15381277876, 6651120.799583474, 73.47045539440143], + [510770.2311507176, 6651119.731354068, 74.65778738840143], + [510770.1705154896, 6651120.56887747, 73.79612250440144], + [510770.20934878284, 6651120.0324930465, 74.39258966340142], + [510770.18907692254, 6651120.312497886, 74.10449131240142], + [510777.97848811885, 6651111.265575936, 74.28504705519137], + [510777.99756351416, 6651111.01556805, 74.85460790319135], + [510777.948682284, 6651111.6562202, 74.54126017819137], + [510777.97204530967, 6651111.350017337, 75.06786023819136], + [510777.9174636914, 6651112.065380495, 74.75353798719135], + [510777.94562609267, 6651111.696275567, 75.25306914019136], + [510777.8853732962, 6651112.485966895, 74.92065274419136], + [510777.91856503225, 6651112.05094599, 75.40956043219136], + [510777.8911194735, 6651112.410655761, 75.53718319119135], + [510777.8529404364, 6651112.911041741, 75.04280586619134], + [510785.94189542916, 6651109.395917872, 68.71021190515403], + [510777.86353788234, 6651112.772148418, 75.63627868519136], + [510777.8206584568, 6651113.334139104, 75.12148055919135], + [510785.8929379023, 6651110.003550005, 68.71021190515403], + [510777.7889659173, 6651113.74951109, 75.15922341819135], + [510785.8929379023, 6651110.003550005, 68.84021190515402], + [510777.8269516389, 6651113.251658762, 75.72544333719135], + [510777.79103342735, 6651113.72241368, 75.76821857819135], + [510785.94189542916, 6651109.395917872, 70.53901556415403], + [510785.94021210884, 6651109.416810256, 71.00460625115402], + [510785.8929379023, 6651110.003550005, 70.53901556415403], + [510777.1931374316, 6651121.55861899, 68.76295607119135], + [510777.6558293313, 6651115.494439354, 75.15922341819135], + [510777.1931374316, 6651121.55861899, 68.89295607119135], + [510785.9349481421, 6651109.482143528, 71.48187720315403], + [510785.89145261975, 6651110.021984461, 70.94983087615402], + [510777.14676016, 6651122.166453505, 68.76295607119135], + [510785.88680794317, 6651110.079631464, 71.37095230415402], + [510785.925832031, 6651109.5952873565, 71.96477822315403], + [510785.87876431574, 6651110.179464255, 71.79704143915401], + [510785.916351131, 6651109.712958732, 72.32648420815403], + [510777.1931372536, 6651121.558621322, 70.59175973119136], + [510777.5254604647, 6651117.203093054, 75.15922341819135], + [510785.9045566883, 6651109.8593444405, 72.68424205415403], + [510785.86715746875, 6651110.323521638, 72.22194794315402], + [510777.1934830634, 6651121.554089035, 70.79558101519135], + [510777.4937679251, 6651117.618465039, 75.12148055919135], + [510777.1963544665, 6651121.516455559, 71.21216030319135], + [510777.14676016, 6651122.166453505, 70.59175973019136], + [510785.89044729434, 6651110.03446197, 73.03469826915402], + [510777.5233931327, 6651117.23018813, 75.76821857819135], + [510785.8519178618, 6651110.51266671, 72.63891464515402], + [510777.4614859456, 6651118.041562402, 75.04280586619134], + [510777.20233988366, 6651121.438008877, 71.63648742319137], + [510777.1483547626, 6651122.145554162, 71.05735041719136], + [510777.42905308574, 6651118.466637248, 74.92065274419136], + [510777.48747492116, 6651117.700943048, 75.72544333719135], + [510785.8740629077, 6651110.237815375, 73.37444329615403], + [510777.21163305483, 6651121.316209772, 72.06279777419135], + [510777.3969626907, 6651118.887223649, 74.75353798719135], + [510785.8330856775, 6651110.746400744, 73.04086356215402], + [510777.2243468195, 6651121.149579335, 72.48460663319135], + [510777.15334129747, 6651122.080199131, 71.53462136919136], + [510777.4508886776, 6651118.180453393, 75.63627868519136], + [510777.3657440979, 6651119.296383943, 74.54126017819137], + [510777.2404965012, 6651120.937916735, 72.89495617619136], + [510777.33593826316, 6651119.687028207, 74.28504705519137], + [510785.8554862428, 6651110.468378054, 73.70011040615402], + [510777.25998869573, 6651120.682446152, 73.28673587019135], + [510777.4233070865, 6651118.541946049, 75.53718319119135], + [510777.31482798455, 6651119.963705887, 74.06562804919135], + [510777.2766816656, 6651120.463663052, 73.56421773019136], + [510777.2950141663, 6651120.2233917685, 73.82465840319136], + [510777.16197695344, 6651121.967017616, 72.01752238919136], + [510777.39586152777, 6651118.901655821, 75.40956043219136], + [510785.81081894116, 6651111.022762426, 73.42074436415402], + [510777.17095817265, 6651121.849307049, 72.37922837419137], + [510777.36880046735, 6651119.256326244, 75.25306914019136], + [510777.1821310015, 6651121.702872584, 72.73698622019135], + [510785.83484231716, 6651110.724598361, 74.00847921415402], + [510777.3423812504, 6651119.602584473, 75.06786023819136], + [510777.1954967746, 6651121.527696728, 73.08744243519135], + [510777.3168630458, 6651119.93703376, 74.85460790319135], + [510785.79202638846, 6651111.2560045775, 73.68715067915402], + [510777.21101763926, 6651121.324275592, 73.42718746219136], + [510777.29249915574, 6651120.256354256, 74.61451945619136], + [510777.2286152405, 6651121.093636122, 73.75285457219137], + [510777.2695291266, 6651120.557406387, 74.34932173119135], + [510777.24817114964, 6651120.837330476, 74.06122338019135], + [510785.81229606346, 6651111.004429248, 74.29657756515402], + [510785.77161104215, 6651111.509387892, 73.93486041915402], + [510791.2508608473, 6651109.831415902, 68.67094383254415], + [510785.7880480692, 6651111.305381143, 74.56177529015402], + [510791.2001412827, 6651110.438903492, 68.67094383254415], + [510785.742191987, 6651111.874519964, 74.23230288915403], + [510791.2001412827, 6651110.438903492, 68.80094383254415], + [510785.7623286649, 6651111.624595318, 74.80186373715402], + [510785.7107278688, 6651112.265034161, 74.48851601215402], + [510785.7353907243, 6651111.958933249, 75.01511607215404], + [510791.2508608473, 6651109.831415902, 70.49974749154416], + [510785.6777723921, 6651112.674058223, 74.70079382115402], + [510785.7075016425, 6651112.305076189, 75.20032497415403], + [510791.2491169424, 6651109.852303315, 70.96533817854414], + [510791.2001412827, 6651110.438903492, 70.49974749154416], + [510785.6438966093, 6651113.094504588, 74.86790857815402], + [510785.6789350074, 6651112.659628523, 75.35681626615404], + [510791.2436635195, 6651109.917621044, 71.44260913054416], + [510791.1986025431, 6651110.457333564, 70.91056280354415], + [510785.6499624821, 6651113.019218529, 75.48443902515403], + [510785.60965930833, 6651113.519437904, 74.99006170015403], + [510791.19379069924, 6651110.514966855, 71.33168423154414], + [510791.234219309, 6651110.030737959, 71.92551015054416], + [510785.62084635603, 6651113.3805908235, 75.58353451915403], + [510785.57558128214, 6651113.942394393, 75.06873639315403], + [510791.1854575724, 6651110.614775898, 71.75777336654414], + [510791.2243971805, 6651110.148381343, 72.28721613554416], + [510785.54212549014, 6651114.357628079, 75.10647925215402], + [510785.5822245929, 6651113.859941513, 75.67269917115404], + [510791.2121782422, 6651110.294732231, 72.64497398154415], + [510791.17343298154, 6651110.758799013, 72.18267987054416], + [510785.54430802853, 6651114.33053969, 75.71547441215402], + [510791.1975610349, 6651110.469808105, 72.99543019654415], + [510791.15764488355, 6651110.947899089, 72.59964657254415], + [510795.0084456514, 6651110.149023901, 68.64155541765334], + [510791.1805869553, 6651110.673113138, 73.33517522354416], + [510791.1381349073, 6651111.181577524, 73.00159548954414], + [510784.91314737085, 6651122.164135896, 68.71021190515403], + [510794.95647894987, 6651110.756406079, 68.64155541765334], + [510785.40158169024, 6651116.101975361, 75.10647925215402], + [510784.91314737085, 6651122.164135896, 68.84021190515402], + [510794.95647894987, 6651110.756406079, 68.77155541765335], + [510791.16134169477, 6651110.90362097, 73.66084233354415], + [510791.1150667654, 6651111.457873467, 73.38147629154415], + [510784.86418984405, 6651122.771768029, 68.71021190515403], + [510791.1399547704, 6651111.159780329, 73.96921114154415], + [510791.09559784713, 6651111.691060135, 73.64788260654416], + [510795.0084456514, 6651110.149023901, 70.47035907665334], + [510791.1165970511, 6651111.439544652, 74.25730949254415], + [510791.07444772887, 6651111.944383178, 73.89559234654415], + [510795.0066588658, 6651110.169907692, 70.93594976365333], + [510784.91314718296, 6651122.164138228, 70.53901556515402], + [510794.95647894987, 6651110.756406079, 70.47035907665334], + [510785.2639595951, 6651117.810060155, 75.10647925215402], + [510791.0914763436, 6651111.740424957, 74.52250721754415], + [510784.9135122323, 6651122.159607449, 70.74283684915402], + [510791.0439698481, 6651112.309428392, 74.19303481654416], + [510785.230503803, 6651118.225293839, 75.06873639315403], + [510795.00107134925, 6651110.235214085, 71.41322071565334], + [510794.95490237436, 6651110.774832951, 70.88117438865333], + [510784.9165433893, 6651122.121986504, 71.15941613715403], + [510784.86418984405, 6651122.771768029, 70.53901556415403], + [510785.26177724457, 6651117.8371462105, 75.71547441215402], + [510791.06483126816, 6651112.059563198, 74.76259566454415], + [510785.1964257768, 6651118.64825033, 74.99006170015403], + [510784.9228618124, 6651122.04356594, 71.58374325715403], + [510794.9499722127, 6651110.832456242, 71.30229581665333], + [510794.9913949164, 6651110.348311373, 71.89612173565334], + [510791.01137329993, 6651112.699849695, 74.44924793954415], + [510784.8658731642, 6651122.750875643, 71.00460625115402], + [510785.16218847584, 6651119.0731836455, 74.86790857815402], + [510785.22386068024, 6651118.307744387, 75.67269917115404], + [510784.93267202034, 6651121.921807388, 72.01005360815404], + [510791.03692380013, 6651112.393821598, 74.97584799954417], + [510785.12831269304, 6651119.493630009, 74.70079382115402], + [510784.9460931306, 6651121.755232432, 72.43186246715402], + [510794.9414341836, 6651110.932247965, 71.72838495165335], + [510784.87113713106, 6651122.685542373, 71.48187720315403], + [510794.98133127275, 6651110.465934342, 72.25782772065334], + [510785.18523891707, 6651118.787095077, 75.58353451915403], + [510785.0953572165, 6651119.902654071, 74.48851601215402], + [510784.9631413191, 6651121.543640307, 72.84221201015403], + [510790.9772317177, 6651113.108776461, 74.66152574854415], + [510785.0638930982, 6651120.293168268, 74.23230288915403], + [510784.9837179854, 6651121.288254784, 73.23399170415404], + [510785.15612279094, 6651119.148467371, 75.48443902515403], + [510785.04160832387, 6651120.5697538275, 74.01288388315402], + [510791.0080309581, 6651112.739882199, 75.16105690154416], + [510785.0013396887, 6651121.06954453, 73.51147356415402], + [510785.02069214004, 6651120.829353245, 73.77191423715402], + [510784.88025324215, 6651122.572398544, 71.96477822315403], + [510794.96881188464, 6651110.612259835, 72.61558556665334], + [510794.92911392177, 6651111.076246088, 72.15329145565333], + [510785.1271502656, 6651119.508057376, 75.35681626615404], + [510784.8897341422, 6651122.454727169, 72.32648420815403], + [510785.0985836306, 6651119.8626097115, 75.20032497415403], + [510784.9015285847, 6651122.30834146, 72.68424205415403], + [510790.9421367065, 6651113.529122812, 74.82864050554414], + [510790.9784361769, 6651113.094350194, 75.31754819354417], + [510785.0706945487, 6651120.20875265, 75.01511607215404], + [510784.91563797876, 6651122.13322393, 73.03469826915402], + [510794.9538352567, 6651110.787305329, 72.96604178165335], + [510785.0437566082, 6651120.543090581, 74.80186373715402], + [510784.9320223654, 6651121.929870525, 73.37444329615403], + [510794.91293761216, 6651111.265313352, 72.57025815765333], + [510785.0180372038, 6651120.862304756, 74.56177529015402], + [510784.9505990303, 6651121.699307847, 73.70011040615402], + [510784.9937892096, 6651121.163256651, 74.29657756515402], + [510784.971242956, 6651121.44308754, 74.00847921415402], + [510790.948420897, 6651113.453854661, 75.44517095254415], + [510790.9066671655, 6651113.953955046, 74.95079362754416], + [510794.93644380354, 6651110.990575083, 73.30578680865334], + [510794.8929479077, 6651111.498951239, 72.97220707465333], + [510790.9182568479, 6651113.815140994, 75.54426644654416], + [510790.8713626319, 6651114.376810925, 75.02946832054415], + [510794.91672532377, 6651111.221042917, 73.63145391865334], + [510790.83670272736, 6651114.791945835, 75.06721117954415], + [510790.8782450431, 6651114.294377658, 75.63343109854416], + [510794.8693125461, 6651111.775199239, 73.35208787665334], + [510794.8948125191, 6651111.477157826, 73.93982272665333], + [510790.8389638178, 6651114.7648638915, 75.67620633954415], + [510794.8493649091, 6651112.008345443, 73.61849419165333], + [510794.8708804599, 6651111.756873603, 74.22792107765333], + [510794.8276947333, 6651112.261624526, 73.86620393165335], + [510794.8451420624, 6651112.057701698, 74.49311880265333], + [510790.18508696026, 6651122.596596671, 68.67094383254415], + [510790.69110059395, 6651116.535878179, 75.06721117954415], + [510794.7964674358, 6651112.626606397, 74.16364640165334], + [510790.18508696026, 6651122.596596671, 68.80094383254415], + [510794.81784181466, 6651112.376784561, 74.73320724965333], + [510790.1343673957, 6651123.204084262, 68.67094383254415], + [510794.76306937524, 6651113.016959954, 74.41985952465333], + [510794.7892481335, 6651112.710984959, 74.94645958465334], + [510794.72808829, 6651113.42581576, 74.63213733365333], + [510794.75964484905, 6651113.0569855105, 75.13166848665334], + [510790.1850867657, 6651122.596599001, 70.49974749254415], + [510790.54852532095, 6651118.24355666, 75.06721117954415], + [510794.6921303321, 6651113.846089169, 74.79925209065334], + [510790.18546495354, 6651122.592069301, 70.70356877654415], + [510794.7293223656, 6651113.411391997, 75.28815977865335], + [510790.51386541646, 6651118.65869157, 75.02946832054415], + [510790.18860520545, 6651122.554457305, 71.12014806454415], + [510790.1343673957, 6651123.204084262, 70.49974749154416], + [510790.5462644252, 6651118.270636272, 75.67620633954415], + [510794.6985690438, 6651113.770834081, 75.41578253765334], + [510794.6557886352, 6651114.270847687, 74.92140521265333], + [510790.4785608828, 6651119.08154745, 74.95079362754416], + [510790.1951510358, 6651122.476055396, 71.54447518454415], + [510790.1361113005, 6651123.183196848, 70.96533817854414], + [510790.4430913418, 6651119.506379684, 74.82864050554414], + [510790.5069831999, 6651118.741122505, 75.63343109854416], + [510794.6676632947, 6651114.132057722, 75.51487803165334], + [510790.20531432447, 6651122.354325807, 71.97078553554417], + [510794.6196160029, 6651114.693630189, 75.00007990565334], + [510790.4079963306, 6651119.926726034, 74.66152574854415], + [510790.21921847604, 6651122.187790476, 72.39259439454416], + [510790.1415647235, 6651123.117879118, 71.44260913054416], + [510790.466971395, 6651119.220359169, 75.54426644654416], + [510803.10035180685, 6651110.859383242, 68.5737739278946], + [510790.3738547484, 6651120.335652799, 74.44924793954415], + [510790.23688024847, 6651121.976248683, 72.80294393754416], + [510794.5841038503, 6651115.108693064, 75.03782276465333], + [510790.3412582002, 6651120.726074102, 74.19303481654416], + [510794.6266676447, 6651114.611211228, 75.60404268365333], + [510790.2581974926, 6651121.720923911, 73.19472363154416], + [510790.436807346, 6651119.581645502, 75.44517095254415], + [510790.3181713712, 6651121.002593868, 73.97361581054415], + [510790.27645342145, 6651121.5022656815, 73.47220549154414], + [510790.15100893396, 6651123.004762203, 71.92551015054416], + [510790.29650238977, 6651121.262131533, 73.73264616454415], + [510790.4067920661, 6651119.94114997, 75.31754819354417], + [510790.16083106253, 6651122.88711882, 72.28721613554416], + [510803.0456994135, 6651111.4665296525, 68.5737739278946], + [510790.37719728483, 6651120.295617964, 75.16105690154416], + [510790.1730500008, 6651122.740767932, 72.64497398154415], + [510794.5864205384, 6651115.08161582, 75.64681792465333], + [510803.0456994135, 6651111.4665296525, 68.70377392789462], + [510790.3483044428, 6651120.641678565, 74.97584799954417], + [510790.187667208, 6651122.565692058, 72.99543019654415], + [510790.3203969748, 6651120.975936965, 74.76259566454415], + [510790.20464128774, 6651122.362387026, 73.33517522354416], + [510790.2937518994, 6651121.295075206, 74.52250721754415], + [510790.22388654825, 6651122.131879194, 73.66084233354415], + [510790.26863119187, 6651121.595955512, 74.25730949254415], + [510790.2452734725, 6651121.875719834, 73.96921114154415], + [510793.9164655865, 6651122.911989608, 68.64155541765334], + [510803.10035180685, 6651110.859383242, 70.40257758689461], + [510793.9164655865, 6651122.911989608, 68.77155541765335], + [510794.4349215247, 6651116.852322794, 75.03782276465333], + [510803.0984726784, 6651110.880258927, 70.8681682738946], + [510803.0456994135, 6651111.4665296525, 70.40257758689461], + [510793.864498885, 6651123.519371784, 68.64155541765334], + [510803.0925963934, 6651110.945539972, 71.34543922589461], + [510803.04404135904, 6651111.484949374, 70.8133928988946], + [510803.03885640175, 6651111.542550296, 71.2345143268946], + [510803.0824198726, 6651111.058593357, 71.82834024589461], + [510793.91646538716, 6651122.911991938, 70.47035907765333], + [510794.28884048655, 6651118.559704953, 75.03782276465333], + [510793.91685287433, 6651122.9074630225, 70.67418036165333], + [510803.0298771186, 6651111.642303282, 71.6606034618946], + [510803.0718361297, 6651111.1761706695, 72.19004623089461], + [510794.2533283341, 6651118.974767827, 75.00007990565334], + [510793.92007034144, 6651122.869857553, 71.09075964965334], + [510793.864498885, 6651123.519371784, 70.47035907665334], + [510794.2865239979, 6651118.5867798645, 75.64681792465333], + [510803.0586697269, 6651111.322439362, 72.54780407689461], + [510803.016920133, 6651111.786245511, 72.0855099658946], + [510794.2171557018, 6651119.3975503305, 74.92140521265333], + [510793.9267771263, 6651122.791469249, 71.51508676965334], + [510793.8662856706, 6651123.498487995, 70.93594976365333], + [510794.18081400485, 6651119.822308846, 74.79925209065334], + [510794.2462768916, 6651119.057184458, 75.60404268365333], + [510793.9371903188, 6651122.669760783, 71.94139712065333], + [510803.04291909165, 6651111.497416909, 72.89826029189462], + [510794.1448560469, 6651120.242582257, 74.63213733365333], + [510802.9999078155, 6651111.975239386, 72.5024766678946], + [510793.9514363577, 6651122.503254349, 72.36320597965333], + [510793.8718731871, 6651123.433181599, 71.41322071565334], + [510794.2052812416, 6651119.536337962, 75.51487803165334], + [510794.1098749616, 6651120.651438063, 74.41985952465333], + [510793.96953241323, 6651122.291749264, 72.77355552265335], + [510794.0764769012, 6651121.041791618, 74.16364640165334], + [510793.9913738244, 6651122.036468796, 73.16533521665333], + [510794.0528223931, 6651121.318263401, 73.94422739565333], + [510794.1743754926, 6651119.897561604, 75.41578253765334], + [510794.0100786459, 6651121.817848509, 73.44281707665333], + [510793.88154962007, 6651123.320084312, 71.89612173565334], + [510794.0306205958, 6651121.5777560305, 73.70325774965333], + [510803.02462883067, 6651111.70060776, 73.23800531889461], + [510802.97888502275, 6651112.20878658, 72.9044255848946], + [510794.14362217084, 6651120.257003688, 75.28815977865335], + [510793.89161326364, 6651123.202461343, 72.25782772065334], + [510794.11329968733, 6651120.6114101745, 75.13166848665334], + [510793.90413265175, 6651123.05613585, 72.61558556665334], + [510803.0038912799, 6651111.930986134, 73.5636724288946], + [510794.08369640284, 6651120.957410725, 74.94645958465334], + [510793.91910927976, 6651122.881090356, 72.96604178165335], + [510794.05510272173, 6651121.291611123, 74.73320724965333], + [510793.93650073285, 6651122.677820602, 73.30578680865334], + [510794.02780247387, 6651121.6106939865, 74.49311880265333], + [510793.95621921256, 6651122.447352768, 73.63145391865334], + [510794.00206407654, 6651121.911522082, 74.22792107765333], + [510793.97813201725, 6651122.1912378585, 73.93982272665333], + [510802.9540281618, 6651112.484927348, 73.28430638689461], + [510802.98084599926, 6651112.187001626, 73.8720412368946], + [510802.93304961064, 6651112.717983052, 73.5507127018946], + [510802.95567710686, 6651112.466608825, 74.1601395878946], + [510802.9102594982, 6651112.971163821, 73.7984224418946], + [510802.9286085231, 6651112.767320149, 74.4253373128946], + [510802.87741834234, 6651113.336004017, 74.09586491189461], + [510802.89989737084, 6651113.086279154, 74.6654257598946], + [510802.8422942363, 6651113.726206049, 74.3520780348946], + [510802.8698259392, 6651113.420349826, 74.87867809489461], + [510802.80550529313, 6651114.1349031525, 74.5643558438946], + [510802.83869272703, 6651113.766216071, 75.06388699689461], + [510802.7676889914, 6651114.555013424, 74.7314706008946], + [510802.80680314684, 6651114.120484985, 75.22037828889462], + [510802.7744604622, 6651114.479787547, 75.34800104789461], + [510802.7294691188, 6651114.979607061, 74.85362372289461], + [510802.7419574728, 6651114.840870972, 75.44709654189461], + [510802.6914270481, 6651115.402225453, 74.9322984158946], + [510802.65407959156, 6651115.817127215, 74.9700412748946], + [510802.698843126, 6651115.319838485, 75.5362611938946], + [510811.421332634, 6651111.627483879, 68.49766535314345], + [510802.6565160085, 6651115.790060479, 75.5790364348946], + [510811.8359754414, 6651111.666758015, 68.49370265615114], + [510811.36391851935, 6651112.234375359, 68.49766535314345], + [510811.36391851935, 6651112.234375359, 68.62766535314343], + [510811.7784237074, 6651112.273636458, 68.49370265615114], + [510811.7784237074, 6651112.273636458, 68.62370265615114], + [510801.951937106, 6651123.617394755, 68.5737739278946], + [510801.951937106, 6651123.617394755, 68.70377392789462], + [510802.49718737236, 6651117.560080119, 74.9700412748946], + [510811.421332634, 6651111.627483879, 70.32646901214345], + [510801.89728471264, 6651124.224541166, 68.5737739278946], + [510811.4193585485, 6651111.648350798, 70.79205969914342], + [510811.8359754414, 6651111.666758015, 70.32250631515114], + [510811.36391851935, 6651112.234375359, 70.32646901214345], + [510811.4131853202, 6651111.713604433, 71.26933065114343], + [510811.36217667925, 6651112.252787345, 70.73728432414343], + [510811.8339966241, 6651111.687624484, 70.78809700215113], + [510811.7784237074, 6651112.273636458, 70.32250631515114], + [510801.95193689625, 6651123.617397084, 70.4025775878946], + [510802.3435567181, 6651119.2667995235, 74.9700412748946], + [510811.3567297131, 6651112.3103640815, 71.15840575214342], + [510801.95234440913, 6651123.612869927, 70.6063988718946], + [510811.8278085988, 6651111.752876718, 71.26536795415115], + [510811.40249455447, 6651111.826610349, 71.75223167114345], + [510811.77667769225, 6651112.292048049, 70.73332162715114], + [510802.30620926153, 6651119.681701284, 74.9322984158946], + [510801.95572815824, 6651123.575279055, 71.0229781598946], + [510801.89728471264, 6651124.224541166, 70.40257758689461], + [510811.34729668446, 6651112.410075184, 71.58449488714342], + [510811.3913759888, 6651111.944138291, 72.11393765614343], + [510811.7712176699, 6651112.349623549, 71.15444305515113], + [510802.341120511, 6651119.293863927, 75.5790364348946], + [510811.8170922077, 6651111.865880206, 71.74826897415115], + [510802.26816719095, 6651120.104319678, 74.85362372289461], + [510801.96278155665, 6651123.496921178, 71.44730527989461], + [510801.8991638411, 6651124.203665481, 70.8681682738946], + [510802.2299473184, 6651120.5289133135, 74.7314706008946], + [510802.2987933934, 6651119.764085923, 75.5362611938946], + [510801.97373291344, 6651123.375259956, 71.8736156308946], + [510811.3775442549, 6651112.090345569, 72.47169550214343], + [510811.3336849502, 6651112.553956972, 72.00940139114343], + [510811.7617620306, 6651112.449332511, 71.58053219015113], + [510811.8059469912, 6651111.983405625, 72.10997495915115], + [510802.1921310166, 6651120.949023586, 74.5643558438946], + [510801.9887152021, 6651123.208818156, 72.2954244898946], + [510801.90504012606, 6651124.138384436, 71.34543922589461], + [510802.2556790467, 6651120.243053436, 75.44709654189461], + [510802.15534207347, 6651121.357720688, 74.3520780348946], + [510802.0077464801, 6651122.99739517, 72.70577403289462], + [510811.36099770083, 6651112.265249644, 72.82215171714343], + [510802.12021796743, 6651121.747922719, 74.09586491189461], + [510802.0307166775, 6651122.742213795, 73.09755372689462], + [510811.79208210326, 6651112.129609763, 72.46773280515114], + [510811.7481176696, 6651112.5932112085, 72.00543869415114], + [510802.0953409703, 6651122.024287186, 73.8764459058946], + [510801.915216647, 6651124.02533105, 71.82834024589461], + [510802.05038818304, 6651122.52367837, 73.3750355868946], + [510802.2231760573, 6651120.60413686, 75.34800104789461], + [510811.315812958, 6651112.742871491, 72.42636809314342], + [510802.0719917616, 6651122.283679088, 73.6354762598946], + [510801.9258003898, 6651123.907753739, 72.19004623089461], + [510802.19083337265, 6651120.963439422, 75.22037828889462], + [510801.9389667926, 6651123.761485045, 72.54780407689461], + [510802.15894379246, 6651121.317708337, 75.06388699689461], + [510811.3417831874, 6651112.468355179, 73.16189674414345], + [510811.7754958878, 6651112.304510082, 72.81818902015114], + [510811.73020283884, 6651112.78212167, 72.42240539615113], + [510801.95471742784, 6651123.586507498, 72.89826029189462], + [510802.12781058036, 6651121.663574581, 74.87867809489461], + [510811.2937278312, 6651112.9763206225, 72.82831701014342], + [510801.97300768894, 6651123.383316647, 73.23800531889461], + [510802.09773914865, 6651121.997645252, 74.6654257598946], + [510801.9937452397, 6651123.152938274, 73.5636724288946], + [510802.06902799645, 6651122.316604258, 74.4253373128946], + [510802.0167905203, 6651122.89692278, 73.8720412368946], + [510802.04195941257, 6651122.617315581, 74.1601395878946], + [510811.31999771675, 6651112.698636821, 73.48756385414343], + [510811.756235318, 6651112.507611254, 73.15793404715114], + [510811.70806477504, 6651113.015565787, 72.82435431315113], + [510811.2676148913, 6651113.252345445, 73.20819781214342], + [510811.29578790074, 6651112.954544818, 73.79593266214343], + [510811.73439762834, 6651112.73788795, 73.48360115715114], + [510811.2455762418, 6651113.485303292, 73.47460412714342], + [510811.6818892434, 6651113.291584682, 73.20423511515114], + [510811.2693471617, 6651113.234034614, 74.08403101314344], + [510811.71012978244, 6651112.99379045, 73.79196996515114], + [510811.2216344883, 6651113.738377754, 73.72231386714343], + [510811.65979776817, 6651113.524537525, 73.47064143015113], + [510811.240910735, 6651113.534619673, 74.34922873814342], + [510811.68362566596, 6651113.273274244, 74.08006831615114], + [510811.6357986272, 6651113.777606551, 73.71835117015114], + [510811.1871337872, 6651114.103064761, 74.01975633714343], + [510811.2107487368, 6651113.853444751, 74.58931718514343], + [510811.65512107825, 6651113.573852846, 74.34526604115113], + [510811.60121522925, 6651114.142285723, 74.01579364015114], + [510811.1502347726, 6651114.493102952, 74.27596946014343], + [510811.17915772105, 6651114.1873751525, 74.80256952014344], + [510811.6248867831, 6651113.892671078, 74.58535448815114], + [510811.5642277693, 6651114.532315538, 74.27200676315114], + [510811.1115867927, 6651114.901628448, 74.48824726914343], + [510811.14645127015, 6651114.533096174, 74.98777842214344], + [510811.5932200448, 6651114.226594306, 74.79860682315116], + [510811.52548715175, 6651114.94083226, 74.48428457215114], + [510811.07185953925, 6651115.321562323, 74.65536202614342], + [510811.11295023025, 6651114.887216336, 75.14426971414343], + [510811.56043519796, 6651114.5723079005, 74.98381572515115], + [510811.0789731894, 6651115.246368032, 75.27189247314342], + [510811.0317083214, 6651115.74597768, 74.77751514814344], + [510811.48566467356, 6651115.360757115, 74.65139932915113], + [510811.52685385733, 6651114.926420458, 75.14030701715116], + [510811.0448277431, 6651115.607299843, 75.37098796714345], + [510810.9917438904, 6651116.168418622, 74.85618984114345], + [510811.4927953749, 6651115.285564439, 75.26792977615115], + [510811.4454172149, 6651115.785163356, 74.77355245115115], + [510810.952509174, 6651116.583146171, 74.89393270014344], + [510810.9995347212, 6651116.086066245, 75.46015261914343], + [510811.4585680833, 6651115.646488498, 75.36702527015115], + [510811.40535699076, 6651116.207595225, 74.85222714415114], + [510810.9550687091, 6651116.556090802, 75.50292786014343], + [510811.36602823023, 6651116.622313866, 74.88997000315113], + [510811.41316649574, 6651116.125244617, 75.45618992215115], + [510820.24433289777, 6651112.483658005, 68.40985667120633], + [510811.3685939005, 6651116.595259079, 75.49896516315114], + [510810.2148856826, 6651124.380138498, 68.49766535314345], + [510820.1839904423, 6651113.09026532, 68.40985667120633], + [510810.2148856826, 6651124.380138498, 68.62766535314343], + [510820.1839904423, 6651113.09026532, 68.53985667120634], + [510810.7876888007, 6651118.3253672365, 74.89393270014344], + [510810.6266366848, 6651124.419138728, 68.49370265615114], + [510810.1574715679, 6651124.987029978, 68.49766535314345], + [510810.6266366848, 6651124.419138728, 68.62370265615114], + [510811.2008127892, 6651118.3644975135, 74.88997000315113], + [510810.56908495084, 6651125.026017172, 68.49370265615114], + [510820.24433289777, 6651112.483658005, 70.23866033020633], + [510820.2422581264, 6651112.5045151515, 70.70425101720632], + [510810.2148854623, 6651124.380140827, 70.32646901314342], + [510820.1839904423, 6651113.09026532, 70.23866033020633], + [510810.62629480753, 6651120.031370016, 74.89393270014344], + [510810.2153135678, 6651124.375615571, 70.53029029714344], + [510820.23577003967, 6651112.5697382325, 71.18152196920633], + [510820.18215976167, 6651113.108668686, 70.64947564220633], + [510810.58706009114, 6651120.446097565, 74.85618984114345], + [510810.2188683061, 6651124.338040482, 70.94686958514345], + [510810.626636464, 6651124.419141056, 70.32250631615113], + [510810.1574715679, 6651124.987029978, 70.32646901214345], + [510811.03903194104, 6651120.07046365, 74.88997000315113], + [510810.6237354928, 6651120.058423055, 75.50292786014343], + [510810.62706559565, 6651124.414615897, 70.52632760015113], + [510810.54709566006, 6651120.868538506, 74.77751514814344], + [510810.22627813026, 6651124.259715507, 71.37119670514343], + [510820.17643497925, 6651113.166218462, 71.07059707020632], + [510810.1594456534, 6651124.966163059, 70.79205969914342], + [510820.22453400376, 6651112.682691237, 71.66442298920633], + [510810.9997031806, 6651120.485182291, 74.85222714415114], + [510810.6306288545, 6651124.377041617, 70.94290688815114], + [510810.5069444423, 6651121.292953864, 74.65536202614342], + [510810.56908495084, 6651125.026017172, 70.32250631515114], + [510810.57926948083, 6651120.528447612, 75.46015261914343], + [510810.2377828864, 6651124.138105368, 71.79750705614343], + [510811.0364664917, 6651120.097516108, 75.49896516315114], + [510810.46721718885, 6651121.712887738, 74.48824726914343], + [510810.9596429564, 6651120.907614159, 74.77355245115115], + [510810.1656188817, 6651124.900909424, 71.26933065114343], + [510810.2535222673, 6651123.971733454, 72.21931591514344], + [510820.1665208299, 6651113.2658828795, 71.49668620520632], + [510810.6380564398, 6651124.298718323, 71.36723400815114], + [510820.21284834837, 6651112.800164151, 72.02612897420633], + [510810.53397645894, 6651121.007214014, 75.37098796714345], + [510810.42856920895, 6651122.121413235, 74.27596946014343], + [510810.5710637681, 6651125.005150702, 70.78809700215113], + [510810.2735152431, 6651123.760399242, 72.62966545814344], + [510810.9193954977, 6651121.3320204, 74.65139932915113], + [510810.9918938964, 6651120.56753057, 75.45618992215115], + [510810.39167019434, 6651122.511451426, 74.01975633714343], + [510810.2976461817, 6651123.505325014, 73.02144515214343], + [510810.6495887723, 6651124.177110796, 71.79354435915116], + [510810.1763096474, 6651124.787903508, 71.75223167114345], + [510810.3655361008, 6651122.787699851, 73.80033733114344], + [510810.3183117374, 6651123.286881349, 73.29892701214342], + [510810.49983101257, 6651121.368145825, 75.27189247314342], + [510810.34100699855, 6651123.046982837, 73.55936768514343], + [510810.8795730196, 6651121.751945255, 74.48428457215114], + [510810.5772517934, 6651124.939898468, 71.26536795415115], + [510820.19831114286, 6651112.946302971, 72.38388682020633], + [510810.66536587983, 6651124.010742455, 72.21535321815114], + [510820.1522148448, 6651113.409697298, 71.92159270920632], + [510810.18742821325, 6651124.670375564, 72.11393765614343], + [510810.4658539716, 6651121.72729752, 75.14426971414343], + [510810.9464923089, 6651121.046286688, 75.36702527015115], + [510810.84083240206, 6651122.160461978, 74.27200676315114], + [510810.68540677807, 6651123.799412782, 72.62570276115115], + [510810.20125994703, 6651124.524168288, 72.47169550214343], + [510810.4323529317, 6651122.0814176835, 74.98777842214344], + [510810.803844942, 6651122.550491793, 74.01579364015114], + [510810.7095955576, 6651123.544344032, 73.01748245515115], + [510810.5879681845, 6651124.826894979, 71.74826897415115], + [510810.77764820616, 6651122.826734283, 73.79637463415114], + [510810.7303106478, 6651123.3259050585, 73.29496431515113], + [510810.91226501734, 6651121.407210747, 75.26792977615115], + [510810.7530603086, 6651123.0860117, 73.55540498815114], + [510810.217806501, 6651124.349264212, 72.82215171714343], + [510810.399646481, 6651122.427138704, 74.80256952014344], + [510820.1809206509, 6651113.1211251505, 72.73434303520634], + [510810.23702101444, 6651124.1461586775, 73.16189674414345], + [510810.36805546505, 6651122.761069104, 74.58931718514343], + [510810.59911340097, 6651124.70936956, 72.10997495915115], + [510820.1334313121, 6651113.598523363, 72.33855941120632], + [510810.2588064852, 6651123.915877035, 73.48756385414343], + [510810.8782065349, 6651121.7663547285, 75.14030701715116], + [510810.337893467, 6651123.079894183, 74.34922873814342], + [510810.28301630117, 6651123.659969039, 73.79593266214343], + [510810.3094570402, 6651123.380479243, 74.08403101314344], + [510810.61297828896, 6651124.563165423, 72.46773280515114], + [510810.84462519427, 6651122.120467287, 74.98381572515115], + [510810.6295645044, 6651124.388265104, 72.81818902015114], + [510810.8118403474, 6651122.466180881, 74.79860682315116], + [510820.16072612326, 6651113.324135586, 73.07408806220633], + [510810.6488250742, 6651124.185163932, 73.15793404715114], + [510810.7801736092, 6651122.800104109, 74.58535448815114], + [510810.6706627638, 6651123.954887237, 73.48360115715114], + [510810.7499393139, 6651123.11892234, 74.34526604115113], + [510820.11021975894, 6651113.831863187, 72.74050832820632], + [510810.69493060984, 6651123.698984737, 73.79196996515114], + [510810.72143472626, 6651123.419500943, 74.08006831615114], + [510820.1378295097, 6651113.554309403, 73.39975517220633], + [510820.08277495846, 6651114.107758766, 73.12038913020633], + [510820.1123848999, 6651113.810097576, 73.70812398020632], + [510820.05961225304, 6651114.340607535, 73.38679544520632], + [510820.08459558134, 6651114.089456508, 73.99622233120633], + [510820.034449378, 6651114.593563502, 73.63450518520634], + [510820.0547087875, 6651114.389900825, 74.26142005620632], + [510819.99818900827, 6651114.958079752, 73.93194765520633], + [510820.02300841134, 6651114.7085766215, 74.50150850320632], + [510819.95940800203, 6651115.347935317, 74.18816077820632], + [510819.98980613204, 6651115.0423506675, 74.71476083820633], + [510819.9187888264, 6651115.75626953, 74.40043858720632], + [510819.9554315264, 6651115.387909813, 74.89996974020633], + [510819.87703533005, 6651116.176006781, 74.56755334420632], + [510819.92022180447, 6651115.741864166, 75.05646103220633], + [510819.88451180374, 6651116.100847697, 75.18408379120633], + [510819.8348362456, 6651116.600223415, 74.68970646620633], + [510819.84862480813, 6651116.461610511, 75.28317928520633], + [510819.79283347464, 6651117.022466558, 74.76838115920633], + [510819.7515976367, 6651117.43699992, 74.80612401820632], + [510819.8010216678, 6651116.940152741, 75.37234393720632], + [510828.64883180737, 6651113.339222212, 68.31939778668155], + [510819.75428771804, 6651117.409957219, 75.41511917820633], + [510828.58569991105, 6651113.945545568, 68.31939778668155], + [510828.58569991105, 6651113.945545568, 68.44939778668154], + [510818.976352508, 6651125.230341487, 68.40985667120633], + [510818.976352508, 6651125.230341487, 68.53985667120634], + [510819.57837078994, 6651119.178405232, 74.80612401820632], + [510818.91601005243, 6651125.836948804, 68.40985667120633], + [510828.64883180737, 6651113.339222212, 70.14820144568156], + [510828.6466611259, 6651113.360069597, 70.61379213268154], + [510828.58569991105, 6651113.945545568, 70.14820144568156], + [510818.97635227646, 6651125.230343814, 70.23866033120632], + [510828.63987311535, 6651113.425262147, 71.09106308468155], + [510828.5837846038, 6651113.963940319, 70.55901675768155], + [510819.4087450819, 6651120.883609215, 74.80612401820632], + [510818.97680221696, 6651125.225820677, 70.44248161520632], + [510828.5777951828, 6651114.021463157, 70.98013818568154], + [510819.3675092439, 6651121.2981425775, 74.76838115920633], + [510818.9805382606, 6651125.188263183, 70.85906090320633], + [510828.62811767304, 6651113.538162275, 71.57396410468156], + [510818.91601005243, 6651125.836948804, 70.23866033020633], + [510819.4060552323, 6651120.910649587, 75.41511917820633], + [510819.3255064731, 6651121.720385721, 74.68970646620633], + [510818.98832601437, 6651125.109974882, 71.28338802320633], + [510828.5674227337, 6651114.121080917, 71.40622732068155], + [510818.91808482393, 6651125.816091655, 70.70425101720632], + [510828.61589182675, 6651113.655580199, 71.93567008968155], + [510819.2833073886, 6651122.144602355, 74.56755334420632], + [510819.00041755725, 6651124.988421684, 71.70969837420633], + [510819.3593212824, 6651121.380454067, 75.37234393720632], + [510831.5707765937, 6651113.645824876, 68.28638856520544], + [510819.24155389227, 6651122.564339605, 74.40043858720632], + [510818.92457291065, 6651125.750868574, 71.18152196920633], + [510819.0169597072, 6651124.822127669, 72.13150723320632], + [510828.6006826123, 6651113.801650608, 72.29342793568155], + [510828.5524554282, 6651114.264828015, 71.83113382468156], + [510819.31171814207, 6651121.858996295, 75.28317928520633], + [510819.2009347166, 6651122.9726738185, 74.18816077820632], + [510819.0379724018, 6651124.610892409, 72.54185677620634], + [510819.1621537104, 6651123.362529384, 73.93194765520633], + [510819.0633341111, 6651124.355937613, 72.93363647020632], + [510818.93580894655, 6651125.637915569, 71.66442298920633], + [510819.1346866775, 6651123.6386484625, 73.71252864920632], + [510819.0850536898, 6651124.137596229, 73.21111833020632], + [510819.10890649655, 6651123.897810046, 73.47155900320632], + [510819.2758311466, 6651122.219759109, 75.18408379120633], + [510831.50667490816, 6651114.2520464705, 68.28638856520544], + [510831.50667490816, 6651114.2520464705, 68.41638856520542], + [510818.94749460195, 6651125.520442656, 72.02612897420633], + [510828.5824882128, 6651113.976390952, 72.64388415068154], + [510819.24012114585, 6651122.57874264, 75.05646103220633], + [510828.53280359216, 6651114.453565687, 72.24810052668154], + [510818.96203180746, 6651125.374303838, 72.38388682020633], + [510819.2049114239, 6651122.932696994, 74.89996974020633], + [510818.9794222994, 6651125.199481656, 72.73434303520634], + [510819.17053681816, 6651123.278256139, 74.71476083820633], + [510818.99961682694, 6651124.996471221, 73.07408806220633], + [510819.137334539, 6651123.612030185, 74.50150850320632], + [510828.5613601561, 6651114.179306355, 72.98362917768156], + [510819.02251344064, 6651124.766297404, 73.39975517220633], + [510819.10563416284, 6651123.930705981, 74.26142005620632], + [510819.0479580504, 6651124.51050923, 73.70812398020632], + [510819.07574736886, 6651124.231150298, 73.99622233120633], + [510828.5085190422, 6651114.686796282, 72.65004944368154], + [510831.5707765937, 6651113.645824876, 70.11519222420543], + [510828.5374051045, 6651114.409372427, 73.30929628768155], + [510828.4798055555, 6651114.962562713, 73.02993024568154], + [510831.56857256766, 6651113.666668761, 70.58078291120542], + [510831.50667490816, 6651114.2520464705, 70.11519222420543], + [510828.5107842709, 6651114.665040862, 73.61766509568155], + [510828.45557211153, 6651115.195302483, 73.29633656068155], + [510831.56168028445, 6651113.73185037, 71.05805386320544], + [510831.5047301793, 6651114.270438133, 70.52600753620543], + [510828.4817103401, 6651114.944269022, 73.90576344668155], + [510828.42924603634, 6651115.448140036, 73.54404630068154], + [510831.4986487529, 6651114.327951317, 70.94712896420543], + [510831.549744263, 6651113.84473155, 71.54095488320543], + [510828.4504419742, 6651115.244572698, 74.17096117168154], + [510828.3913094644, 6651115.812485652, 73.84148877068155], + [510831.4881169693, 6651114.427552359, 71.37321809920542], + [510831.53733061155, 6651113.962129766, 71.90266086820543], + [510828.41727618984, 6651115.563099318, 74.41104961868155], + [510831.5218877635, 6651114.108175661, 72.26041871420543], + [510831.47291974624, 6651114.571275331, 71.79812460320542], + [510828.35073573486, 6651116.202158721, 74.09770189368155], + [510828.38253907434, 6651115.89671712, 74.62430195368155], + [510831.5034138741, 6651114.282886677, 72.61087492920542], + [510831.45296603214, 6651114.759981328, 72.21509130520543], + [510828.30823886313, 6651116.610301789, 74.30997970268155], + [510828.34657543927, 6651116.242114503, 74.80951085568155], + [510831.48196126265, 6651114.485768025, 72.95061995620543], + [510831.42830843956, 6651114.99317278, 72.61704022220542], + [510828.26455523475, 6651117.029842554, 74.47709445968155], + [510828.3097380833, 6651116.595903168, 74.96600214768155], + [510831.45763822977, 6651114.7157954825, 73.27628706620543], + [510828.27237732214, 6651116.954718653, 75.09362490668154], + [510828.22040542006, 6651117.453860608, 74.59924758168154], + [510831.39915387577, 6651115.268892925, 72.99692102420542], + [510831.43060846505, 6651114.971421009, 73.58465587420542], + [510828.2348313843, 6651117.3153125895, 75.19272040068157], + [510828.176460994, 6651117.875906092, 74.67792227468156], + [510831.37454817403, 6651115.501593635, 73.26332733920542], + [510831.4010879203, 6651115.250602305, 73.87275422520543], + [510828.1333189536, 6651118.290245407, 74.71566513368155], + [510828.1850277013, 6651117.793630808, 75.28188505268155], + [510831.34781769564, 6651115.754388754, 73.51103707920542], + [510831.36933923105, 6651115.550855581, 74.13795195020542], + [510828.13613338885, 6651118.263215365, 75.32466029368155], + [510831.3092983679, 6651116.118673219, 73.80847954920543], + [510837.37233162613, 6651114.268599376, 68.21846013508599], + [510831.3356639766, 6651115.869328741, 74.37804039720542], + [510831.26810137235, 6651116.508280889, 74.06469267220542], + [510827.32223669457, 6651126.079938812, 68.31939778668155], + [510827.32223669457, 6651126.079938812, 68.44939778668154], + [510837.30630441307, 6651114.874614272, 68.21846013508599], + [510831.30039325304, 6651116.202890552, 74.59129273220543], + [510837.30630441307, 6651114.874614272, 68.34846013508599], + [510827.9520843777, 6651120.030835545, 74.71566513368155], + [510831.2249516927, 6651116.916355457, 74.27697048120544], + [510827.25910479826, 6651126.686262168, 68.31939778668155], + [510831.2638771692, 6651116.548229965, 74.77650163420545], + [510831.1805970262, 6651117.33582581, 74.44408523820542], + [510831.22647394286, 6651116.901959253, 74.93299292620543], + [510837.37233162613, 6651114.268599376, 70.04726379408599], + [510831.1885392712, 6651117.260714518, 75.06061568520542], + [510831.1357690121, 6651117.759772698, 74.56623836020543], + [510827.3222364523, 6651126.079941139, 70.14820144668154], + [510837.3700613941, 6651114.289436154, 70.51285448108598], + [510837.30630441307, 6651114.874614272, 70.04726379408599], + [510827.7746174096, 6651121.7352413, 74.71566513368155], + [510827.32270719216, 6651126.075420119, 70.35202273068155], + [510831.1504165782, 6651117.621247934, 75.15971117920543], + [510831.09114954167, 6651118.181747352, 74.64491305320543], + [510827.7314753693, 6651122.149580615, 74.67792227468156], + [510827.32661594136, 6651126.037880206, 70.76860201868156], + [510837.36296207603, 6651114.354595538, 70.990125433086], + [510837.3043012672, 6651114.892999666, 70.45807910608599], + [510827.25910479826, 6651126.686262168, 70.14820144568156], + [510827.7718032168, 6651121.762269015, 75.32466029368155], + [510831.0473447827, 6651118.596017126, 74.68265591220542], + [510827.68753094313, 6651122.571626102, 74.59924758168154], + [510831.0998478449, 6651118.099485875, 75.24887583120542], + [510827.3347636982, 6651125.959628552, 71.19292913868155], + [510827.26127547974, 6651126.665414784, 70.61379213268154], + [510837.2980371629, 6651114.950493239, 70.87920053408598], + [510837.35066751274, 6651114.46743823, 71.47302645308599], + [510827.64338112855, 6651122.995644155, 74.47709445968155], + [510827.347414195, 6651125.838132255, 71.61923948968155], + [510827.7229089042, 6651122.231853574, 75.28188505268155], + [510831.05020245136, 6651118.56899162, 75.29165107220543], + [510827.2680634902, 6651126.600222234, 71.09106308468155], + [510827.59969750006, 6651123.41518492, 74.30997970268155], + [510827.36472103617, 6651125.671916084, 72.04104834868156], + [510837.28718901885, 6651115.050060321, 71.305289669086], + [510827.6731052213, 6651122.710171792, 75.19272040068157], + [510837.33788097213, 6651114.584796419, 71.834732438086], + [510827.5572006284, 6651123.8233279865, 74.09770189368155], + [510827.3867050812, 6651125.460779707, 72.45139789168155], + [510827.5166268989, 6651124.213001057, 73.84148877068155], + [510827.4132391822, 6651125.20594426, 72.84317758568154], + [510827.2798189326, 6651126.487322106, 71.57396410468156], + [510827.4878901519, 6651124.48899088, 73.62206976468156], + [510827.4359627881, 6651124.987705083, 73.12065944568154], + [510827.46091823484, 6651124.748031147, 73.38110011868154], + [510827.6355592835, 6651123.070765727, 75.09362490668154], + [510827.2920447788, 6651126.369904182, 71.93567008968155], + [510827.5981985223, 6651123.429581213, 74.96600214768155], + [510837.3219742419, 6651114.730792518, 72.192490284086], + [510837.2715352918, 6651115.193734289, 71.73019617308599], + [510827.30725399335, 6651126.223833772, 72.29342793568155], + [510830.2238032305, 6651126.384403165, 68.28638856520544], + [510827.5613611663, 6651123.783369876, 74.80951085568155], + [510830.2238032305, 6651126.384403165, 68.41638856520542], + [510827.3254483928, 6651126.049093428, 72.64388415068154], + [510827.52539753134, 6651124.12876726, 74.62430195368155], + [510827.3465764494, 6651125.846178025, 72.98362917768156], + [510830.8633262046, 6651120.3363151355, 74.68265591220542], + [510827.4906604157, 6651124.462385063, 74.41104961868155], + [510837.30294542183, 6651114.9054439645, 72.54294649908599], + [510827.37053150113, 6651125.616111954, 73.30929628768155], + [510827.4574946314, 6651124.780911683, 74.17096117168154], + [510827.3971523348, 6651125.360443519, 73.61766509568155], + [510827.42622626555, 6651125.081215358, 73.90576344668155], + [510837.2509821952, 6651115.382375944, 72.147162875086], + [510830.15970154497, 6651126.99062476, 68.28638856520544], + [510837.280848403, 6651115.108256138, 72.88269152608599], + [510837.22558392194, 6651115.615487886, 72.54911179208598], + [510837.2557947393, 6651115.338205164, 73.20835863608599], + [510837.19555359473, 6651115.8911140235, 72.92899259408598], + [510830.22380298446, 6651126.384405491, 70.11519222520542], + [510830.6831331099, 6651122.040434836, 74.68265591220542], + [510830.2242809555, 6651126.37988523, 70.31901350920542], + [510837.2279530372, 6651115.593743532, 73.516727444086], + [510837.17020877113, 6651116.12373539, 73.19539890908598], + [510830.63932835095, 6651122.454704611, 74.64491305320543], + [510830.2282497482, 6651126.342351617, 70.73559279720543], + [510830.15970154497, 6651126.99062476, 70.11519222420543], + [510837.1975457353, 6651115.872829639, 73.80482579508599], + [510830.68027568725, 6651122.067458014, 75.29165107220543], + [510830.59470888047, 6651122.876679264, 74.56623836020543], + [510830.2365226654, 6651126.2641130965, 71.15991991720543], + [510837.14267534553, 6651116.376444316, 73.44310864908599], + [510830.161905571, 6651126.969780874, 70.58078291120542], + [510830.54988086637, 6651123.300626152, 74.44408523820542], + [510830.2493674905, 6651126.14263719, 71.58623026820543], + [510830.6306302937, 6651122.53696376, 75.24887583120542], + [510837.1648433586, 6651116.1729805395, 74.07002352008598], + [510830.16879785416, 6651126.904599266, 71.05805386320544], + [510830.50552619994, 6651123.720096505, 74.27697048120544], + [510830.26694018755, 6651125.976448917, 72.00803912720542], + [510837.1029989495, 6651116.740604575, 73.74055111908599], + [510830.58006156044, 6651123.015201701, 75.15971117920543], + [510830.46237652027, 6651124.128171072, 74.06469267220542], + [510830.2892619365, 6651125.765347974, 72.41838867020543], + [510830.4211795246, 6651124.517778742, 73.80847954920543], + [510830.3162036363, 6651125.510555296, 72.81016836420542], + [510830.1807338756, 6651126.791718086, 71.54095488320543], + [510830.39200134337, 6651124.793722245, 73.58906054320542], + [510830.33927630686, 6651125.292352748, 73.08765022420542], + [510830.364615102, 6651125.052719036, 73.34809089720542], + [510830.5419388675, 6651123.375735118, 75.06061568520542], + [510837.1301565452, 6651116.491345114, 74.31011196708599], + [510830.19314752705, 6651126.67431987, 71.90266086820543], + [510830.5040041958, 6651123.734490382, 74.93299292620543], + [510837.060564452, 6651117.130079404, 73.99676424208599], + [510830.20859037514, 6651126.528273975, 72.26041871420543], + [510830.46660096943, 6651124.088219669, 74.77650163420545], + [510830.22706426453, 6651126.353562958, 72.61087492920542], + [510837.0938263371, 6651116.824793192, 74.523364302086], + [510830.4300848855, 6651124.433559084, 74.59129273220543], + [510830.2485168761, 6651126.150681609, 72.95061995620543], + [510830.3948141621, 6651124.767120893, 74.37804039720542], + [510830.2728399089, 6651125.9206541525, 73.27628706620543], + [510830.36113890755, 6651125.085594055, 74.13795195020542], + [510830.2998696737, 6651125.665028627, 73.58465587420542], + [510830.32939021837, 6651125.385847329, 73.87275422520543], + [510837.0161186146, 6651117.538014834, 74.209042051086], + [510837.0562133596, 6651117.170014859, 74.70857320408601], + [510836.9704315941, 6651117.957342164, 74.376156808086], + [510837.0176865911, 6651117.523623538, 74.86506449608599], + [510836.97861241334, 6651117.882256482, 74.99268725508598], + [510836.9242570073, 6651118.381144502, 74.498309930086], + [510836.9393445665, 6651118.24266697, 75.091782749086], + [510836.87829722866, 6651118.802975278, 74.57698462308599], + [510836.83317663416, 6651119.2171038035, 74.61472748208598], + [510836.8872568171, 6651118.72074185, 75.18094740108599], + [510845.4455920274, 6651115.166274973, 68.11864080924303], + [510836.83612014324, 6651119.190087512, 75.223722642086], + [510845.376885311, 6651115.771991932, 68.11864080924303], + [510845.376885311, 6651115.771991932, 68.24864080924304], + [510835.9848970118, 6651127.002834307, 68.21846013508599], + [510835.9848970118, 6651127.002834307, 68.34846013508599], + [510836.6436303878, 6651120.95680844, 74.61472748208598], + [510845.4455920274, 6651115.166274973, 69.94744446824303], + [510835.9188697986, 6651127.608849202, 68.21846013508599], + [510845.4432296652, 6651115.187101508, 70.41303515524302], + [510845.376885311, 6651115.771991932, 69.94744446824303], + [510845.4358422441, 6651115.252228856, 70.89030610724303], + [510845.3748008738, 6651115.790368287, 70.35825978024303], + [510835.9848967584, 6651127.002836633, 70.04726379508598], + [510835.98538908706, 6651126.998317912, 70.25108507908598], + [510836.45802453713, 6651122.660347102, 74.61472748208598], + [510845.36828256096, 6651115.847833594, 70.77938120824302], + [510845.4230487452, 6651115.365016072, 71.37320712724303], + [510835.9894770969, 6651126.960797097, 70.66766436708599], + [510836.4129039427, 6651123.074475626, 74.57698462308599], + [510835.9188697986, 6651127.608849202, 70.04726379408599], + [510845.35699417966, 6651115.947351726, 71.20547034324305], + [510836.4550812815, 6651122.687361067, 75.223722642086], + [510845.4097433037, 6651115.482316563, 71.73491311224304], + [510835.99799852126, 6651126.882585252, 71.09199148708599], + [510836.3669441639, 6651123.496306403, 74.498309930086], + [510835.9211400306, 6651127.588012425, 70.51285448108598], + [510836.0112291874, 6651126.761150765, 71.51830183808599], + [510836.3207695772, 6651123.920108741, 74.376156808086], + [510836.4039446076, 6651123.156706729, 75.18094740108599], + [510845.34070519614, 6651116.090955059, 71.63037684724303], + [510845.3931910496, 6651115.628240884, 72.09267095824303], + [510835.92823934864, 6651127.522853041, 70.990125433086], + [510836.02932974446, 6651126.595019154, 71.94011069708598], + [510836.27508255665, 6651124.339436072, 74.209042051086], + [510836.3518568583, 6651123.634781609, 75.091782749086], + [510836.0523220085, 6651126.38399019, 72.350460240086], + [510836.23063671927, 6651124.747371501, 73.99676424208599], + [510836.0800730003, 6651126.129284386, 72.74223993408599], + [510836.1882022218, 6651125.136846331, 73.74055111908599], + [510835.9405339119, 6651127.410010348, 71.47302645308599], + [510836.1038387426, 6651125.911156236, 73.01972179408598], + [510836.1581475676, 6651125.412695746, 73.52113211308598], + [510845.3733900059, 6651115.802806468, 72.44312717324304], + [510836.1299386808, 6651125.67160423, 73.28016246708599], + [510836.3125890114, 6651123.9951920975, 74.99268725508598], + [510845.3193180178, 6651116.27950397, 72.04734354924302], + [510835.9533204526, 6651127.29265216, 71.834732438086], + [510836.27351483365, 6651124.353825041, 74.86506449608599], + [510835.9692271829, 6651127.1466560615, 72.192490284086], + [510836.23498806515, 6651124.707433719, 74.70857320408601], + [510845.3503962502, 6651116.005518931, 72.78287220024303], + [510835.98825600295, 6651126.972004614, 72.54294649908599], + [510836.19737508777, 6651125.052655388, 74.523364302086], + [510845.2928890369, 6651116.512501308, 72.44929246624302], + [510836.01035302173, 6651126.769192442, 72.88269152608599], + [510836.1610448796, 6651125.386103465, 74.31011196708599], + [510836.0354066855, 6651126.539243415, 73.20835863608599], + [510836.1263580662, 6651125.70446804, 74.07002352008598], + [510836.06324838765, 6651126.283705046, 73.516727444086], + [510836.09365568944, 6651126.00461894, 73.80482579508599], + [510845.3243258637, 6651116.235354909, 73.10853931024303], + [510845.2616400249, 6651116.787991937, 72.82917326824304], + [510845.295354295, 6651116.490767644, 73.41690811824303], + [510845.2352666627, 6651117.02049894, 73.09557958324302], + [510845.26371301006, 6651116.769716543, 73.70500646924303], + [510845.206615881, 6651117.273083625, 73.34328932324304], + [510845.22968351207, 6651117.069719879, 73.97020419424302], + [510845.16532934527, 6651117.637064851, 73.64073179324303], + [510845.19358904526, 6651117.3879279345, 74.21029264124303], + [510845.1211727796, 6651118.026348202, 73.89694491624303], + [510845.15578449174, 6651117.721212079, 74.42354497624304], + [510851.69674341613, 6651115.8861935325, 68.03711346873332], + [510845.07492324995, 6651118.434083077, 74.10922272524303], + [510845.1166451119, 6651118.066264023, 74.60875387824304], + [510851.6259619517, 6651116.491671551, 68.03711346873332], + [510851.6259619517, 6651116.491671551, 68.16711346873333], + [510845.02738216775, 6651118.85320425, 74.27633748224304], + [510845.0765548578, 6651118.419698858, 74.76524517024305], + [510845.03589497943, 6651118.778155483, 74.89286792924304], + [510844.9793337331, 6651119.276798235, 74.39849060424302], + [510851.69674341613, 6651115.8861935325, 69.86591712773333], + [510844.9950335726, 6651119.138388783, 74.99196342324304], + [510844.9315088237, 6651119.698421625, 74.47716529724303], + [510851.6943097174, 6651115.907011851, 70.33150781473331], + [510844.8845571542, 6651120.112346551, 74.51490815624302], + [510851.6259619517, 6651116.491671551, 69.86591712773333], + [510844.9408320085, 6651119.616228626, 75.08112807524303], + [510851.68669921707, 6651115.972113509, 70.80877876673333], + [510851.62381457054, 6651116.510040656, 70.27673243973332], + [510844.88762011623, 6651120.085343542, 75.12390331624303], + [510851.61709942314, 6651116.567483295, 70.69785386773331], + [510851.6735193908, 6651116.084856232, 71.29167978673333], + [510844.00185281615, 6651127.894249328, 68.11864080924303], + [510851.6054701646, 6651116.666962169, 71.12394300273331], + [510844.00185281615, 6651127.894249328, 68.24864080924304], + [510851.6598121627, 6651116.202110451, 71.65338577173333], + [510854.48284232145, 6651116.214050449, 67.99958431955216], + [510844.6873187797, 6651121.851195889, 74.51490815624302], + [510843.9331460998, 6651128.499966287, 68.11864080924303], + [510851.58868930006, 6651116.810508855, 71.54884950673332], + [510851.6427600775, 6651116.34797721, 72.01114361773332], + [510854.4111361548, 6651116.819419654, 67.99958431955216], + [510854.4111361548, 6651116.819419654, 68.12958431955215], + [510851.6223610983, 6651116.522473931, 72.36159983273332], + [510851.5666562896, 6651116.998983389, 71.96581620873332], + [510851.59867299645, 6651116.725106429, 72.70134485973333], + [510844.0018525525, 6651127.894251651, 69.94744446924302], + [510851.5394292285, 6651117.231888814, 72.36776512573331], + [510844.00236486073, 6651127.889735154, 70.15126575324302], + [510844.4941807091, 6651123.553897034, 74.51490815624302], + [510854.48284232145, 6651116.214050449, 69.82838797855216], + [510851.5718153582, 6651116.954851742, 73.02701196973332], + [510844.0066187695, 6651127.852232785, 70.56784504124303], + [510843.9331460998, 6651128.499966287, 69.94744446824303], + [510844.4472290397, 6651123.96782196, 74.47716529724303], + [510854.4803768284, 6651116.2348650275, 70.29397866555215], + [510851.5072365849, 6651117.50727077, 72.74764592773332], + [510854.4111361548, 6651116.819419654, 69.82838797855216], + [510844.49111801083, 6651123.580897719, 75.12390331624303], + [510844.01548600866, 6651127.7740593925, 70.99217216124303], + [510844.3994041303, 6651124.3894453505, 74.39849060424302], + [510851.54196893034, 6651117.210163725, 73.33538077773332], + [510843.9355084619, 6651128.479139752, 70.41303515524302], + [510844.029253599, 6651127.652684605, 71.41848251224303], + [510851.48006682197, 6651117.739686054, 73.01405224273331], + [510844.3513556956, 6651124.813039334, 74.27633748224304], + [510854.47266690305, 6651116.299954985, 70.77124961755217], + [510854.4089607199, 6651116.837785458, 70.23920329055215], + [510844.43790611863, 6651124.050012634, 75.08112807524303], + [510843.9428958831, 6651128.414012403, 70.89030610724303], + [510844.0480887093, 6651127.486634672, 71.84029137124303], + [510844.30381461343, 6651125.232160509, 74.10922272524303], + [510851.5093721684, 6651117.489002585, 73.62347912873332], + [510844.0720140408, 6651127.275709456, 72.25064091424305], + [510844.3837045546, 6651124.527852477, 74.99196342324304], + [510844.2575650838, 6651125.639895384, 73.89694491624303], + [510851.4505508679, 6651117.992171102, 73.26176198273332], + [510854.40215784457, 6651116.895217773, 70.66032471855216], + [510844.1008912178, 6651127.021128873, 72.64242060824303], + [510843.9556893819, 6651128.301225187, 71.37320712724303], + [510844.21340851806, 6651126.029178733, 73.64073179324303], + [510854.45931489306, 6651116.412677447, 71.25415063755216], + [510844.1256214168, 6651126.803107962, 72.91990246824302], + [510844.1821341918, 6651126.3048925325, 73.42131278724302], + [510844.15278053755, 6651126.563673728, 73.18034314124303], + [510844.3428431477, 6651124.888085776, 74.89286792924304], + [510843.9689948234, 6651128.183924696, 71.73491311224304], + [510851.4743150759, 6651117.788887577, 73.88867685373332], + [510844.3021832694, 6651125.246542403, 74.76524517024305], + [510854.3903766592, 6651116.994678769, 71.08641385355216], + [510843.9855470775, 6651128.038000376, 72.09267095824303], + [510854.4454285913, 6651116.529910593, 71.61585662255216], + [510844.2620930152, 6651125.599977236, 74.60875387824304], + [510851.4080175959, 6651118.356008747, 73.55920445273333], + [510844.0053481213, 6651127.863434792, 72.44312717324304], + [510844.2229536353, 6651125.945029182, 74.42354497624304], + [510844.0283418769, 6651127.660722328, 72.78287220024303], + [510844.1851490819, 6651126.278313325, 74.21029264124303], + [510844.0544122635, 6651127.430886352, 73.10853931024303], + [510851.43713065865, 6651118.106970107, 74.12876530073332], + [510844.1490546151, 6651126.596521381, 73.97020419424302], + [510844.08338383207, 6651127.1754736155, 73.41690811824303], + [510844.11502511706, 6651126.896524716, 73.70500646924303], + [510854.37337656633, 6651117.138199658, 71.51132035755215], + [510854.4281537344, 6651116.675751138, 71.97361446855217], + [510851.3625276271, 6651118.745138534, 73.81541757573332], + [510851.39818451484, 6651118.440122779, 74.34201763573334], + [510854.40748825925, 6651116.850216498, 72.32407068355215], + [510854.3510557126, 6651117.326640319, 71.92828705955216], + [510851.3148814928, 6651119.152712569, 74.02769538473332], + [510851.35786323674, 6651118.78503861, 74.52722653773333], + [510854.3834906916, 6651117.05281258, 72.66381571055216], + [510854.3234729521, 6651117.559503888, 72.33023597655215], + [510851.2659048049, 6651119.57166841, 74.19481014173331], + [510851.31656237063, 6651119.138334022, 74.68371782973334], + [510854.35628218023, 6651117.282516602, 72.98948282055215], + [510854.2908597379, 6651117.834836352, 72.71011677855215], + [510851.2746746793, 6651119.4966492485, 74.81134058873333], + [510851.2164054438, 6651119.995095297, 74.31696326373333], + [510854.3260458331, 6651117.537782702, 73.29785162855217], + [510854.2633350242, 6651118.067209868, 72.97652309355215], + [510851.23257937375, 6651119.856740445, 74.91043608273333], + [510851.1671363577, 6651120.416552367, 74.39563795673332], + [510854.29302322096, 6651117.81657145, 73.58594997955215], + [510851.118766881, 6651120.830314009, 74.43338081573332], + [510854.23343346815, 6651118.319649538, 73.22423283355215], + [510851.1767410762, 6651120.334391791, 74.99960073473333], + [510854.2575081362, 6651118.116402546, 73.85114770455215], + [510851.12192233576, 6651120.803321653, 75.04237597573332], + [510854.19034453365, 6651118.683421794, 73.52167530355216], + [510854.2198379348, 6651118.434427912, 74.09123615155215], + [510854.14426027547, 6651119.072481649, 73.77788842655215], + [510850.20940737537, 6651128.609147025, 68.03711346873332], + [510850.20940737537, 6651128.609147025, 68.16711346873333], + [510854.18038299144, 6651118.767520711, 74.30448848655216], + [510850.91557246685, 6651122.568477416, 74.43338081573332], + [510854.0959916833, 6651119.479982435, 73.99016623555217], + [510850.138625911, 6651129.214625044, 68.03711346873332], + [510854.13953494874, 6651119.112374554, 74.48969738855217], + [510854.0463751548, 6651119.898862982, 74.15728099255216], + [510854.0976945203, 6651119.465606473, 74.64618868055216], + [510853.99622912495, 6651120.322213772, 74.27943411455216], + [510854.05525960046, 6651119.823857303, 74.77381143955215], + [510850.2094071038, 6651128.609149347, 69.86591712873332], + [510850.2099348822, 6651128.6046346305, 70.06973841273332], + [510850.7166021744, 6651124.27050689, 74.43338081573332], + [510854.01261435414, 6651120.183883784, 74.87290693355216], + [510853.9463163784, 6651120.743595098, 74.35810880755216], + [510850.21431724686, 6651128.567147057, 70.48631770073332], + [510850.138625911, 6651129.214625044, 69.86591712773333], + [510850.6682326976, 6651124.684268533, 74.39563795673332], + [510862.22483474266, 6651117.147761682, 67.89143172384466], + [510853.8973149939, 6651121.157282381, 74.39585166655215], + [510850.7134469913, 6651124.297496922, 75.04237597573332], + [510853.9560465748, 6651120.661449288, 74.96207158555215], + [510850.22345225146, 6651128.489004501, 70.91064482073332], + [510850.6189636116, 6651125.105725602, 74.31696326373333], + [510850.1410596097, 6651129.193806725, 70.33150781473331], + [510850.2376355841, 6651128.367677594, 71.33695517173334], + [510862.15055902017, 6651117.752820987, 67.89143172384466], + [510850.56946425047, 6651125.52915249, 74.19481014173331], + [510850.6586282508, 6651124.766426786, 74.99960073473333], + [510862.15055902017, 6651117.752820987, 68.02143172384466], + [510853.90051167214, 6651121.130294875, 75.00484682655217], + [510850.14867011004, 6651129.128705067, 70.80877876673333], + [510850.25703946134, 6651128.201693161, 71.75876403073332], + [510850.52048756246, 6651125.948108331, 74.02769538473332], + [510850.2816872699, 6651127.990851151, 72.16911357373333], + [510850.60278995323, 6651125.244078131, 74.91043608273333], + [510850.4728414283, 6651126.355682366, 73.81541757573332], + [510850.3114364559, 6651127.736370994, 72.56089326773333], + [510850.16184993624, 6651129.015962344, 71.29167978673333], + [510850.42735145945, 6651126.744812154, 73.55920445273333], + [510850.33691343665, 6651127.518436086, 72.83837512773331], + [510850.3951327372, 6651127.02041719, 73.33978544673332], + [510850.36489268584, 6651127.2790963035, 73.09881580073332], + [510850.56069464784, 6651125.604169328, 74.81134058873333], + [510850.1755571644, 6651128.898708125, 71.65338577173333], + [510852.9760754476, 6651128.934717401, 67.99958431955216], + [510850.51880695653, 6651125.962484553, 74.68371782973334], + [510852.9760754476, 6651128.934717401, 68.12958431955215], + [510850.1926092496, 6651128.752841366, 72.01114361773332], + [510850.4775060903, 6651126.315779965, 74.52722653773333], + [510850.2130082287, 6651128.578344644, 72.36159983273332], + [510862.22483474266, 6651117.147761682, 69.72023538284466], + [510850.4371848122, 6651126.660695797, 74.34201763573334], + [510853.6914660104, 6651122.895133409, 74.39585166655215], + [510850.2366963306, 6651128.375712145, 72.70134485973333], + [510850.3982386684, 6651126.993848467, 74.12876530073332], + [510850.2635539689, 6651128.145966833, 73.02701196973332], + [510852.904369281, 6651129.540086604, 67.99958431955216], + [510850.36105425115, 6651127.311930998, 73.88867685373332], + [510850.29340039677, 6651127.890654851, 73.33538077773332], + [510850.32599715865, 6651127.611815992, 73.62347912873332], + [510862.22228089994, 6651117.168565603, 70.18582606984465], + [510862.15055902017, 6651117.752820987, 69.72023538284466], + [510862.14830562955, 6651117.77117739, 70.13105069484466], + [510862.21429469314, 6651117.233622242, 70.66309702184468], + [510852.97607517237, 6651128.934719723, 69.82838797955215], + [510862.1412589765, 6651117.828580305, 70.55217212284467], + [510862.20046422037, 6651117.346286998, 71.14599804184466], + [510852.9766098459, 6651128.930205817, 70.03220926355215], + [510853.48989633325, 6651124.596856996, 74.39585166655215], + [510862.12905561813, 6651117.927990385, 70.97826125784465], + [510852.98104946245, 6651128.89272498, 70.44878855155216], + [510852.904369281, 6651129.540086604, 69.82838797855216], + [510862.1860803095, 6651117.463460131, 71.50770402684466], + [510853.4408949487, 6651125.010544279, 74.35810880755216], + [510853.4866999302, 6651124.62384218, 75.00484682655217], + [510852.99030380853, 6651128.814596468, 70.87311567155216], + [510853.3909822022, 6651125.431925606, 74.27943411455216], + [510852.90683477395, 6651129.519272028, 70.29397866555215], + [510862.11144633504, 6651118.071437803, 71.40316776184466], + [510862.16818641656, 6651117.609226017, 71.86546187284466], + [510853.0046724348, 6651128.693291365, 71.29942602255215], + [510853.3408361722, 6651125.855276396, 74.15728099255216], + [510853.43116502755, 6651125.092687767, 74.96207158555215], + [510852.9145446993, 6651129.454182069, 70.77124961755217], + [510853.0243298079, 6651128.527336765, 71.72123488155215], + [510853.2912196437, 6651126.274156943, 73.99016623555217], + [510862.14678040403, 6651117.783602066, 72.21591808784466], + [510853.04929962, 6651128.316532645, 72.13158442455216], + [510853.3745972482, 6651125.570253271, 74.87290693355216], + [510862.0883256243, 6651118.259781999, 71.82013446384467], + [510853.24295105156, 6651126.681657729, 73.77788842655215], + [510852.9278967093, 6651129.341459608, 71.25415063755216], + [510853.0794374548, 6651128.062098224, 72.52336411855215], + [510853.19686679344, 6651127.070717583, 73.52167530355216], + [510853.10524727154, 6651127.844202482, 72.80084597855215], + [510853.1642271598, 6651127.346273089, 73.30225629755215], + [510853.13359204686, 6651127.604905712, 73.06128665155215], + [510853.3319520019, 6651125.930279752, 74.77381143955215], + [510852.9417830112, 6651129.224226462, 71.61585662255216], + [510862.1219228952, 6651117.986094437, 72.55566311484466], + [510853.28951708204, 6651126.288530582, 74.64618868055216], + [510852.95905786793, 6651129.0783859175, 71.97361446855217], + [510862.0597544488, 6651118.492526362, 72.22208338084465], + [510853.2476766537, 6651126.641762501, 74.48969738855217], + [510852.9797233431, 6651128.9039205555, 72.32407068355215], + [510853.2068286109, 6651126.986616343, 74.30448848655216], + [510853.00372091075, 6651128.701324473, 72.66381571055216], + [510853.16737366753, 6651127.319709142, 74.09123615155215], + [510853.0309294221, 6651128.471620451, 72.98948282055215], + [510862.09373937984, 6651118.21568087, 72.88133022484466], + [510853.12970346614, 6651127.637734507, 73.85114770455215], + [510853.06116576924, 6651128.216354353, 73.29785162855217], + [510853.09418838134, 6651127.937565605, 73.58594997955215], + [510862.02597255574, 6651118.767717878, 72.60196418284465], + [510862.06241952785, 6651118.470816296, 73.18969903284466], + [510861.99746150716, 6651118.999972439, 72.86837049784465], + [510862.02821356634, 6651118.749462327, 73.47779738384466], + [510861.9664884434, 6651119.252282882, 73.11608023784466], + [510861.9914258156, 6651119.0491399355, 73.74299510884465], + [510861.9218554377, 6651119.615868919, 73.41352270784466], + [510861.95240572066, 6651119.3670025, 73.98308355584466], + [510861.8741197723, 6651120.004729606, 73.66973583084466], + [510861.9115369284, 6651119.699924783, 74.19633589084467], + [510861.82412149844, 6651120.412021788, 73.88201363984467], + [510861.8692251157, 6651120.0446020905, 74.38154479284468], + [510861.77272698557, 6651120.830687904, 74.04912839684465], + [510861.82588535576, 6651120.397653185, 74.53803608484466], + [510861.7207839968, 6651121.253821974, 74.17128151884467], + [510861.781929801, 6651120.75572062, 74.66565884384465], + [510861.7377563828, 6651121.115562798, 74.76475433784466], + [510861.6690826511, 6651121.67498759, 74.24995621184466], + [510861.6183253255, 6651122.0884631, 74.28769907084465], + [510861.67916152434, 6651121.592883831, 74.85391898984466], + [510861.62163655524, 6651122.061489409, 74.89669423084466], + [510860.66407360387, 6651129.861916736, 67.89143172384466], + [510860.66407360387, 6651129.861916736, 68.02143172384466], + [510861.4050998429, 6651123.825424497, 74.28769907084465], + [510860.58979788143, 6651130.466976043, 67.89143172384466], + [510871.57436085044, 6651118.319840205, 67.75322922458413], + [510871.7967866418, 6651118.348317526, 67.74984006371746], + [510871.49698203395, 6651118.9245105, 67.75322922458413], + [510871.49698203395, 6651118.9245105, 67.88322922458413], + [510860.6640733189, 6651129.861919057, 69.72023538384465], + [510871.7193340025, 6651118.95297837, 67.74984006371746], + [510871.7193340025, 6651118.95297837, 67.87984006371745], + [510860.6646271521, 6651129.857407464, 69.92405666784465], + [510861.19630701345, 6651125.526276947, 74.28769907084465], + [510860.6692258602, 6651129.819945812, 70.34063595584466], + [510860.58979788143, 6651130.466976043, 69.72023538284466], + [510861.1455496879, 6651125.939752456, 74.24995621184466], + [510860.6788118313, 6651129.741857296, 70.76496307584466], + [510861.1929960688, 6651125.553248314, 74.89669423084466], + [510871.57436085044, 6651118.319840205, 69.58203288358415], + [510861.09384834213, 6651126.360918071, 74.17128151884467], + [510860.59235172416, 6651130.44617212, 70.18582606984465], + [510860.6936953504, 6651129.62061429, 71.19127342684466], + [510871.7967866418, 6651118.348317526, 69.57864372271747], + [510861.04190535337, 6651126.784052142, 74.04912839684465], + [510861.13547109975, 6651126.021853894, 74.85391898984466], + [510871.5717003131, 6651118.340630752, 70.04762357058412], + [510860.600337931, 6651130.381115482, 70.66309702184468], + [510860.714057136, 6651129.4547446435, 71.61308228584465], + [510871.49698203395, 6651118.9245105, 69.58203288358415], + [510860.99051084055, 6651127.202718259, 73.88201363984467], + [510860.7399217293, 6651129.244048439, 72.02343182884466], + [510860.9405125666, 6651127.610010439, 73.66973583084466], + [510861.07687624125, 6651126.499174925, 74.76475433784466], + [510871.7941235662, 6651118.369107748, 70.04423440971745], + [510860.61416840367, 6651130.268450725, 71.14599804184466], + [510860.7711395389, 6651128.989744266, 72.41521152284466], + [510860.89277690125, 6651127.998871128, 73.41352270784466], + [510871.7193340025, 6651118.95297837, 69.57864372271747], + [510860.79787423793, 6651128.7719600685, 72.69269338284465], + [510860.8589676421, 6651128.2742855735, 73.19410370184465], + [510860.82723473455, 6651128.532785799, 72.95313405584466], + [510871.494634501, 6651118.9428551, 69.99284819558413], + [510871.5633804583, 6651118.405645562, 70.52489452258413], + [510861.032702823, 6651126.859017103, 74.66565884384465], + [510860.6285523146, 6651130.151277592, 71.50770402684466], + [510860.98874726833, 6651127.217084538, 74.53803608484466], + [510860.64644620754, 6651130.005511706, 71.86546187284466], + [510871.71698423, 6651118.971322684, 69.98945903471746], + [510871.7857957739, 6651118.434121542, 70.52150536171746], + [510860.9454075084, 6651127.5701356325, 74.38154479284468], + [510871.48729345266, 6651119.00022111, 70.41396962358412], + [510860.66785222, 6651129.831135657, 72.21591808784466], + [510860.9030956957, 6651127.91481294, 74.19633589084467], + [510871.5489721755, 6651118.518237885, 71.00779554258415], + [510860.69270972896, 6651129.628643286, 72.55566311484466], + [510860.8622269034, 6651128.247735223, 73.98308355584466], + [510860.7208932442, 6651129.399056852, 72.88133022484466], + [510860.8232068085, 6651128.565597787, 73.74299510884465], + [510860.75221309625, 6651129.143921429, 73.18969903284466], + [510871.70963617787, 6651119.028687796, 70.41058046271745], + [510860.78641905775, 6651128.865275396, 73.47779738384466], + [510871.771373745, 6651118.546712104, 71.00440638171747], + [510871.4745802619, 6651119.099567277, 70.84005875858412], + [510871.533987333, 6651118.635335683, 71.36950152758413], + [510871.69691085815, 6651119.12803241, 70.83666959771745], + [510871.75637460634, 6651118.663808072, 71.36611236671746], + [510871.4562352976, 6651119.242922467, 71.26496526258414], + [510871.5153458683, 6651118.7810078515, 71.72725937358413], + [510871.678548392, 6651119.2713853605, 71.26157610171747], + [510871.73771535687, 6651118.8094779635, 71.72387021271746], + [510871.49304555455, 6651118.95527179, 72.07771558858413], + [510871.4321486488, 6651119.431145571, 71.68193196458412], + [510871.7153937676, 6651118.983739178, 72.07432642771745], + [510871.65443876345, 6651119.4596055215, 71.67854280371745], + [510871.4671495477, 6651119.157633971, 72.41746061558415], + [510871.4023838256, 6651119.663740294, 72.08388088158412], + [510871.68947305484, 6651119.186098197, 72.41407145471747], + [510871.6246455434, 6651119.692196609, 72.08049172071745], + [510871.43778858037, 6651119.387072797, 72.74312772558413], + [510871.36719059135, 6651119.938754884, 72.46376168358412], + [510871.6600840759, 6651119.415533436, 72.73973856471746], + [510871.4051602464, 6651119.642044187, 73.05149653358413], + [510871.58941873326, 6651119.967206899, 72.46037252271745], + [510871.33748840715, 6651120.170860121, 72.73016799858414], + [510871.62742461305, 6651119.67050084, 73.04810737271745], + [510871.55968821177, 6651120.199308507, 72.72677883771746], + [510871.369525227, 6651119.920511069, 73.33959488458414], + [510871.30522134947, 6651120.423008345, 72.97787773858413], + [510871.5917555961, 6651119.948963369, 73.33620572371747], + [510871.5273903699, 6651120.451452792, 72.97448857771745], + [510871.33120055613, 6651120.219996005, 73.60479260958412], + [510871.25872366433, 6651120.786360621, 73.27532020858413], + [510871.5533943619, 6651120.248443625, 73.60140344871745], + [510871.48084832396, 6651120.814799389, 73.27193104771746], + [510871.2905502782, 6651120.537654206, 73.84488105658413], + [510871.20899369643, 6651121.174971298, 73.53153333158413], + [510871.5127053018, 6651120.56609686, 73.84149189571745], + [510871.2479740679, 6651120.870362443, 74.05813339158414], + [510871.4310709115, 6651121.203403992, 73.52814417071745], + [510871.470088472, 6651120.898799897, 74.05474423071746], + [510871.1569065928, 6651121.582001618, 73.74381114058413], + [510871.20389455074, 6651121.214818148, 74.24334229358413], + [510871.3789341145, 6651121.610427949, 73.74042197971745], + [510871.42596690095, 6651121.243250218, 74.23995313271746], + [510871.103364918, 6651122.000398563, 73.91092589758412], + [510871.15874414064, 6651121.567642254, 74.39983358558413], + [510871.3253413585, 6651122.028818353, 73.90753673671745], + [510871.3807734153, 6651121.596068809, 74.39644442471746], + [510871.049251853, 6651122.423260587, 74.03307901958414], + [510871.112952209, 6651121.925479477, 74.52745634458412], + [510871.27117666724, 6651122.451673767, 74.02968985871746], + [510871.33493779623, 6651121.953900439, 74.52406718371745], + [510878.9851400758, 6651119.283514667, 67.63777053046715], + [510871.06693331205, 6651122.285090303, 74.62655183858415], + [510870.9953905264, 6651122.8441554215, 74.11175371258415], + [510871.28887499525, 6651122.313505642, 74.62316267771747], + [510871.21726395475, 6651122.872562024, 74.10836455171747], + [510870.94251265936, 6651123.257365095, 74.14949657158414], + [510878.90530163253, 6651119.887865121, 67.63777053046715], + [510871.0058904752, 6651122.762104449, 74.71571649058413], + [510878.90530163253, 6651119.887865121, 67.76777053046715], + [510871.1643356398, 6651123.285765238, 74.14610741071746], + [510871.22777392087, 6651122.790512334, 74.71232732971745], + [510870.9459622257, 6651123.230408748, 74.75849173158413], + [510871.1677884973, 6651123.258809312, 74.75510257071745], + [510869.9483941724, 6651131.02582094, 67.75322922458413], + [510878.9851400758, 6651119.283514667, 69.46657418946717], + [510869.9483941724, 6651131.02582094, 67.88322922458413], + [510870.1692687201, 6651131.054099654, 67.74984006371746], + [510870.1692687201, 6651131.054099654, 67.87984006371745], + [510870.72037903435, 6651124.993209746, 74.14949657158414], + [510869.871015356, 6651131.630491235, 67.75322922458413], + [510878.98239496845, 6651119.3042942155, 69.93216487646714], + [510878.90530163253, 6651119.887865121, 69.46657418946717], + [510870.94199008954, 6651125.021582756, 74.14610741071746], + [510870.0918160808, 6651131.658760498, 67.74984006371746], + [510878.90287947905, 6651119.906200016, 69.87738950146715], + [510878.9738106518, 6651119.369274637, 70.40943582846715], + [510878.89530508197, 6651119.963535681, 70.29851092946714], + [510878.95894437557, 6651119.481807402, 70.89233684846717], + [510869.9483938755, 6651131.02582326, 69.58203288458412], + [510869.9489708468, 6651131.021314566, 69.78585416858414], + [510878.88218777935, 6651120.0628293, 70.72460006446715], + [510870.16926842293, 6651131.054101975, 69.57864372371745], + [510870.5028632499, 6651126.6929686675, 74.14949657158414], + [510878.9434832126, 6651119.598843262, 71.25404283346715], + [510870.1698459446, 6651131.049593351, 69.78246500771746], + [510869.95376168005, 6651130.983877, 70.20243345658415], + [510869.871015356, 6651131.630491235, 69.58203288358415], + [510870.72426678555, 6651126.721315107, 74.14610741071746], + [510870.44998538285, 6651127.1061783405, 74.11175371258415], + [510878.86325968686, 6651120.206108662, 71.14950656846716], + [510878.9242491949, 6651119.744438377, 71.61180067946715], + [510870.1746413485, 6651131.01215637, 70.19904429571747], + [510870.0918160808, 6651131.658760498, 69.57864372271747], + [510869.96374813415, 6651130.905838689, 70.62676057658413], + [510870.4994139806, 6651126.719922694, 74.75849173158413], + [510870.6713384706, 6651127.1345183235, 74.10836455171747], + [510870.39612405637, 6651127.527073177, 74.03307901958414], + [510869.87367589324, 6651131.609700689, 70.04762357058412], + [510869.97925345745, 6651130.784673636, 71.05307092758413], + [510870.1846373302, 6651130.9341192795, 70.62337141571746], + [510870.72081422544, 6651126.748268713, 74.75510257071745], + [510870.3420109914, 6651127.9499352, 73.91092589758412], + [510870.6174257581, 6651127.555406579, 74.02968985871746], + [510870.0944791564, 6651131.637970276, 70.04423440971745], + [510870.4394857311, 6651127.188226991, 74.71571649058413], + [510878.90124002506, 6651119.918610138, 71.96225689446715], + [510869.88199574815, 6651131.544685878, 70.52489452258413], + [510878.83840740006, 6651120.394232205, 71.56647327046714], + [510870.00046591845, 6651130.618910633, 71.47487978658414], + [510870.2001574462, 6651130.812956119, 71.04968176671746], + [510870.2884693166, 6651128.368332145, 73.74381114058413], + [510870.56326106685, 6651127.978261993, 73.90753673671745], + [510870.0274110838, 6651130.408349889, 71.88522932958413], + [510870.66082880175, 6651127.216565691, 74.71232732971745], + [510870.23638221284, 6651128.775362463, 73.53153333158413], + [510870.3784428944, 6651127.66524114, 74.62655183858415], + [510870.10280694877, 6651131.572956482, 70.52150536171746], + [510870.22139014484, 6651130.647195706, 71.47149062571746], + [510869.8964040309, 6651131.432093557, 71.00779554258415], + [510870.0599331122, 6651130.154209216, 72.27700902358413], + [510870.18665224506, 6651129.163973141, 73.27532020858413], + [510870.5096683109, 6651128.396652397, 73.74042197971745], + [510870.0877847347, 6651129.93656504, 72.55449088358412], + [510870.15143050137, 6651129.439210514, 73.05590120258414], + [510870.1183718552, 6651129.697544542, 72.81493155658413], + [510878.87452086643, 6651120.120865279, 72.30200192146717], + [510870.33242399734, 6651128.024851964, 74.52745634458412], + [510870.2483610171, 6651130.436638256, 71.88184016871746], + [510870.4575315138, 6651128.803676354, 73.52814417071745], + [510869.9113888733, 6651131.314995757, 71.36950152758413], + [510870.5997277274, 6651127.6935723815, 74.62316267771747], + [510878.80769644777, 6651120.626703896, 71.96842218746714], + [510870.11722897773, 6651131.46036592, 71.00440638171747], + [510870.28091407294, 6651130.182501554, 72.27361986271745], + [510870.4077541014, 6651129.192280958, 73.27193104771746], + [510870.30879226705, 6651129.964860781, 72.55110172271745], + [510870.2866320657, 6651128.382689186, 74.39983358558413], + [510870.37249875464, 6651129.467514029, 73.05251204171746], + [510870.3394085691, 6651129.725844018, 72.81154239571745], + [510869.930030338, 6651131.16932359, 71.72725937358413], + [510870.5536649264, 6651128.053177586, 74.52406718371745], + [510870.1322281163, 6651131.343269952, 71.36611236671746], + [510870.24148165574, 6651128.735513294, 74.24334229358413], + [510869.9523306518, 6651130.995059651, 72.07771558858413], + [510878.84422660724, 6651120.350182742, 72.62766903146715], + [510870.5078293073, 6651128.411009216, 74.39644442471746], + [510870.19740213844, 6651129.079968997, 74.05813339158414], + [510870.15088736586, 6651131.19760006, 71.72387021271746], + [510869.97822665866, 6651130.79269747, 72.41746061558415], + [510870.15482592816, 6651129.412677235, 73.84488105658413], + [510870.007587626, 6651130.563258644, 72.74312772558413], + [510870.46263582166, 6651128.763827808, 74.23995313271746], + [510878.7713845324, 6651120.901573014, 72.34830298946714], + [510870.11417565023, 6651129.730335435, 73.60479260958412], + [510870.04021595995, 6651130.308287255, 73.05149653358413], + [510870.0758509794, 6651130.029820372, 73.33959488458414], + [510870.17320895504, 6651131.023338846, 72.07432642771745], + [510870.41851425066, 6651129.108278127, 74.05474423071746], + [510870.1991296678, 6651130.820979828, 72.41407145471747], + [510870.3758974208, 6651129.440981164, 73.84149189571745], + [510870.22851864673, 6651130.591544589, 72.73973856471746], + [510878.8105611221, 6651120.605019265, 72.93603783946715], + [510870.3352083607, 6651129.758634399, 73.60140344871745], + [510870.2611781097, 6651130.3365771845, 73.04810737271745], + [510870.2968471265, 6651130.058114655, 73.33620572371747], + [510878.74073821004, 6651121.133555479, 72.61470930446715], + [510878.77379337855, 6651120.88333885, 73.22413619046716], + [510878.70744548517, 6651121.38557033, 72.86241904446715], + [510878.7342504882, 6651121.182665374, 73.48933391546714], + [510878.6594697863, 6651121.74873041, 73.15986151446715], + [510878.69230806705, 6651121.500155548, 73.72942236246715], + [510878.6081590607, 6651122.137135531, 73.41607463746715], + [510878.64837849437, 6651121.832687799, 73.94267469746715], + [510878.55441627343, 6651122.543950549, 73.62835244646715], + [510878.6028978294, 6651122.176961301, 74.12788359946715], + [510878.49917267886, 6651122.9621261805, 73.79546720346715], + [510878.5563122312, 6651122.529598781, 74.28437489146715], + [510878.44333953154, 6651123.384764532, 73.91762032546714], + [510878.50906471943, 6651122.887246726, 74.41199765046714], + [510878.46158302797, 6651123.246667332, 74.51109314446717], + [510878.38776612456, 6651123.805436733, 73.99629501846717], + [510878.333207438, 6651124.218427839, 74.03403787746716], + [510878.3985998333, 6651123.723429161, 74.60025779646715], + [510878.3367666552, 6651124.191485749, 74.64303303746715], + [510877.30748908257, 6651131.982774536, 67.63777053046715], + [510877.30748908257, 6651131.982774536, 67.76777053046715], + [510878.10401289066, 6651125.953354308, 74.03403787746716], + [510877.22765063925, 6651132.587124988, 67.63777053046715], + [510888.6453847495, 6651120.58578353, 67.4793948502016], + [510877.3074887762, 6651131.982776854, 69.46657419046714], + [510877.30808408756, 6651131.9782705465, 69.67039547446716], + [510877.87958297064, 6651127.652214138, 74.03403787746716], + [510888.56234008534, 6651121.189701763, 67.4793948502016], + [510888.56234008534, 6651121.189701763, 67.60939485020158], + [510877.31302720617, 6651131.940852782, 70.08697476246716], + [510877.22765063925, 6651132.587124988, 69.46657418946717], + [510877.8250242841, 6651128.065205242, 73.99629501846717], + [510877.3233310979, 6651131.86285575, 70.51130188246715], + [510877.8760240599, 6651127.679153906, 74.64303303746715], + [510877.23039574665, 6651132.566345439, 69.93216487646714], + [510877.7694508771, 6651128.485877444, 73.91762032546714], + [510877.33932928625, 6651131.741754786, 70.93761223346715], + [510877.7136177298, 6651128.908515794, 73.79546720346715], + [510877.81419088185, 6651128.147210494, 74.60025779646715], + [510877.2389800633, 6651132.501365018, 70.40943582846715], + [510877.36121602403, 6651131.5760794645, 71.35942109246716], + [510877.65837413515, 6651129.326691425, 73.62835244646715], + [510888.6453847495, 6651120.58578353, 69.3081985092016], + [510877.3890176905, 6651131.365630099, 71.76977063546715], + [510877.6046313479, 6651129.733506445, 73.41607463746715], + [510877.75120768714, 6651128.623972323, 74.51109314446717], + [510877.25384633965, 6651132.3888322525, 70.89233684846717], + [510877.42257349094, 6651131.1116238525, 72.16155032946715], + [510877.55332062236, 6651130.121911566, 73.15986151446715], + [510877.45131042786, 6651130.894094801, 72.43903218946714], + [510877.5169792914, 6651130.397003351, 72.94044250846716], + [510877.48286981584, 6651130.655200734, 72.69947286246715], + [510877.70372599567, 6651128.983392931, 74.41199765046714], + [510877.2693075025, 6651132.271796394, 71.25404283346715], + [510888.6425294018, 6651120.606548218, 69.77378919620158], + [510888.56234008534, 6651121.189701763, 69.3081985092016], + [510877.656478484, 6651129.341040874, 74.28437489146715], + [510877.28854152025, 6651132.126201279, 71.61180067946715], + [510877.6098928858, 6651129.693678354, 74.12788359946715], + [510877.3115506901, 6651131.952029519, 71.96225689446715], + [510877.5644122208, 6651130.037951857, 73.94267469746715], + [510877.33826984867, 6651131.749774376, 72.30200192146717], + [510888.5598206608, 6651121.208023545, 69.71901382120159], + [510888.6336003488, 6651120.671482166, 70.25106014820159], + [510877.520482648, 6651130.370484107, 73.72942236246715], + [510877.3685641079, 6651131.520456913, 72.62766903146715], + [510877.4785402269, 6651130.687974281, 73.48933391546714], + [510877.402229593, 6651131.265620392, 72.93603783946715], + [510877.4389973365, 6651130.987300805, 73.22413619046716], + [510888.5519420846, 6651121.265318206, 70.14013524920158], + [510888.61813705973, 6651120.78393445, 70.7339611682016], + [510888.538298006, 6651121.36454081, 70.56622438420158], + [510888.60205499415, 6651120.900886607, 71.09566715320159], + [510888.5186097829, 6651121.507717702, 70.9911308882016], + [510888.58204856014, 6651121.0463775955, 71.45342499920159], + [510891.86846296454, 6651121.0318975635, 67.42456835018152], + [510888.5581153682, 6651121.220424791, 71.80388121420158], + [510888.49275945657, 6651121.695706701, 71.40809759020158], + [510891.7843485653, 6651121.635667731, 67.42456835018152], + [510891.7843485653, 6651121.635667731, 67.5545683501815], + [510888.53032319853, 6651121.422535284, 72.1436262412016], + [510888.4608151873, 6651121.928012133, 71.81004650720158], + [510888.4988123564, 6651121.651688743, 72.46929335120159], + [510888.4230450267, 6651122.20268467, 72.18992730920158], + [510891.86846296454, 6651121.0318975635, 69.2533720091815], + [510888.4637949038, 6651121.906343009, 72.77766215920158], + [510888.3911679829, 6651122.434501225, 72.45633362420159], + [510891.8655708358, 6651121.052657161, 69.71896269618149], + [510891.7843485653, 6651121.635667731, 69.2533720091815], + [510888.4255506094, 6651122.184463547, 73.0657605102016], + [510888.3565382601, 6651122.686335838, 72.70404336420158], + [510891.78179668705, 6651121.6539850235, 69.6641873211815], + [510891.85652676376, 6651121.117575189, 70.19623364818152], + [510888.3844197216, 6651122.483575998, 73.33095823520158], + [510888.3066359117, 6651123.049236191, 73.00148583420159], + [510891.77381662343, 6651121.711265636, 70.08530874918151], + [510891.8408642853, 6651121.229999903, 70.6791346681815], + [510888.3407929405, 6651122.8008391075, 73.57104668220158], + [510891.7599967895, 6651121.810463914, 70.51139788418149], + [510888.2532646058, 6651123.437363532, 73.25769895720158], + [510891.82457505947, 6651121.346923387, 71.0408406531815], + [510888.2950992062, 6651123.133133537, 73.78429901720159], + [510891.7400549536, 6651121.953605702, 70.9363043881815], + [510891.8043109138, 6651121.492378703, 71.3985984991815], + [510888.1973635694, 6651123.843887605, 73.46997676620158], + [510888.2477920894, 6651123.477160821, 73.96950791920159], + [510891.7800694279, 6651121.666383228, 71.7490547141815], + [510891.7138716378, 6651122.141548612, 71.35327109018151], + [510888.13990145497, 6651124.261764164, 73.63709152320158], + [510888.1993356666, 6651123.829546101, 74.12599921120159], + [510891.751919255, 6651121.868444168, 72.0887997411815], + [510888.0818261118, 6651124.684100252, 73.75924464520159], + [510888.1501907486, 6651124.186938261, 74.25362197020158], + [510895.7250897525, 6651121.573353198, 67.35765722912942], + [510891.6815158804, 6651122.373797089, 71.75522000718149], + [510888.1008022464, 6651124.546101817, 74.3527174642016], + [510891.72000250773, 6651122.097541446, 72.4144668511815], + [510888.02402094007, 6651125.104471595, 73.8379193382016], + [510895.6396953445, 6651122.176943657, 67.35765722912942], + [510891.6432591857, 6651122.648402283, 72.1351008091815], + [510895.6396953445, 6651122.176943657, 67.48765722912941], + [510887.96727123886, 6651125.517167335, 73.87566219720159], + [510888.03528971836, 6651125.022522674, 74.44188211620158], + [510891.6845339799, 6651122.352133278, 72.7228356591815], + [510891.61097151967, 6651122.8801620025, 72.40150712418149], + [510887.97097339004, 6651125.490244515, 74.48465735720158], + [510891.6457970439, 6651122.630185626, 73.01093401018151], + [510891.57589571615, 6651123.131934875, 72.6492168641815], + [510895.7250897525, 6651121.573353198, 69.18646088812942], + [510886.9003612012, 6651133.275961105, 67.4793948502016], + [510891.604136331, 6651122.9292247435, 73.2761317351815], + [510886.9003612012, 6651133.275961105, 67.60939485020158], + [510891.5253505536, 6651123.494746254, 72.9466593341815], + [510895.72215361294, 6651121.594106616, 69.6520515751294], + [510895.6396953445, 6651122.176943657, 69.18646088812942], + [510886.817316537, 6651133.879879337, 67.4793948502016], + [510887.7288724993, 6651127.250853017, 73.87566219720159], + [510891.55994757416, 6651123.24641007, 73.5162201821815], + [510895.6371046331, 6651122.195255497, 69.59727620012941], + [510895.7129719129, 6651121.659005322, 70.12932252712942], + [510891.47129174846, 6651123.882778435, 73.2028724571815], + [510891.5136652387, 6651123.5786230285, 73.7294725171815], + [510895.62900313304, 6651122.252519061, 70.0183976281294], + [510895.697071091, 6651121.771396574, 70.61222354712942], + [510891.4146706261, 6651124.289202839, 73.41515026618151], + [510891.46574873803, 6651123.922565967, 73.91468141918152], + [510886.9003608826, 6651133.275963422, 69.30819851020158], + [510895.61497299606, 6651122.351687812, 70.44448676312942], + [510895.6805339843, 6651121.888285257, 70.97392953212943], + [510886.900980101, 6651133.271460336, 69.51201979420159], + [510891.35646831675, 6651124.706976946, 73.58226502318149], + [510891.4166681267, 6651124.274864851, 74.0711727111815], + [510887.49542972894, 6651128.9484978495, 73.87566219720159], + [510886.9061217296, 6651133.234069334, 69.9285990822016], + [510886.817316537, 6651133.879879337, 69.3081985092016], + [510895.59472769586, 6651122.494786996, 70.86939326712941], + [510895.6599614695, 6651122.03369728, 71.33168737812943], + [510887.4386800276, 6651129.36119359, 73.8379193382016], + [510891.29764487955, 6651125.129209487, 73.7044181451815], + [510891.36689015134, 6651124.632169387, 74.1987954701815], + [510886.9168394139, 6651133.156128082, 70.35292620220159], + [510887.49172789644, 6651128.9754183525, 74.48465735720158], + [510886.82017188467, 6651133.859114649, 69.77378919620158], + [510887.38087485585, 6651129.781564935, 73.75924464520159], + [510895.6353510894, 6651122.207650012, 71.68214359312941], + [510895.5681459361, 6651122.682673966, 71.2863599691294], + [510886.9334800713, 6651133.0351137305, 70.77923655320159], + [510891.31686545414, 6651124.991244887, 74.2978909641815], + [510891.2390950939, 6651125.549477767, 73.7830928381815], + [510887.3227995129, 6651130.203901021, 73.63709152320158], + [510887.4274115682, 6651129.443140194, 74.44188211620158], + [510886.8291009377, 6651133.794180701, 70.25106014820159], + [510886.9562457555, 6651132.869556895, 71.2010454122016], + [510887.26533739833, 6651130.62177758, 73.46997676620158], + [510895.60677254194, 6651122.409650811, 72.02188862012942], + [510886.98516390525, 6651132.65925804, 71.61139495520159], + [510891.18161437474, 6651125.962072326, 73.8208356971815], + [510887.2094363619, 6651131.0283016525, 73.25769895720158], + [510887.3618990402, 6651129.91956105, 74.3527174642016], + [510886.84456422675, 6651133.681728418, 70.7339611682016], + [510895.53529780573, 6651122.914853315, 71.6883088861294], + [510891.2505090302, 6651125.467548939, 74.3870556161815], + [510887.0200672685, 6651132.4054334555, 72.00317464920158], + [510887.15606505604, 6651131.416428993, 73.00148583420159], + [510887.04995824816, 6651132.188059975, 72.28065650920158], + [510887.1182642985, 6651131.6913240375, 72.7820668282016], + [510887.08278502524, 6651131.949336761, 72.54109718220158], + [510887.3125105379, 6651130.278724607, 74.25362197020158], + [510886.86064629245, 6651133.5647762595, 71.09566715320159], + [510895.57437010243, 6651122.638679897, 72.34755573012941], + [510887.26336562, 6651130.636116766, 74.12599921120159], + [510886.8806527264, 6651133.419285271, 71.45342499920159], + [510891.185364215, 6651125.935156106, 74.4298308571815], + [510887.2149091972, 6651130.988502046, 73.96950791920159], + [510886.90458591835, 6651133.245238076, 71.80388121420158], + [510895.49645894073, 6651123.189376776, 72.06818968812941], + [510887.1676020804, 6651131.332529331, 73.78429901720159], + [510886.93237808795, 6651133.043127583, 72.1436262412016], + [510887.121908346, 6651131.664823759, 73.57104668220158], + [510886.96388893016, 6651132.813974124, 72.46929335120159], + [510887.0782815649, 6651131.98208687, 73.33095823520158], + [510886.99890638277, 6651132.559319858, 72.77766215920158], + [510895.53836183314, 6651122.893195953, 72.65592453812943], + [510887.03715067706, 6651132.28119932, 73.0657605102016], + [510890.10096099856, 6651133.718963847, 67.42456835018152], + [510890.10096099856, 6651133.718963847, 67.5545683501815], + [510895.46367993794, 6651123.421067513, 72.3345960031294], + [510895.49903541885, 6651123.171165542, 72.94402288912941], + [510890.0168465994, 6651134.322734014, 67.42456835018152], + [510890.9401447159, 6651127.695332954, 73.8208356971815], + [510895.4280703693, 6651123.672765445, 72.58230574312941], + [510895.4567407351, 6651123.47011565, 73.2092206141294], + [510895.37675603695, 6651124.035468836, 72.87974821312942], + [510895.41187953687, 6651123.787206569, 73.44930906112941], + [510890.1009606759, 6651133.718966164, 69.2533720101815], + [510895.32187459327, 6651124.423385523, 73.13596133612941], + [510890.1015878706, 6651133.714464181, 69.4571932941815], + [510895.36489290104, 6651124.119320646, 73.66256139612942], + [510890.7036948663, 6651129.392561571, 73.8208356971815], + [510890.1067957308, 6651133.677082348, 69.8737725821815], + [510890.0168465994, 6651134.322734014, 69.2533720091815], + [510895.2643918404, 6651124.829688958, 73.34823914512941], + [510890.6462141471, 6651129.805156129, 73.7830928381815], + [510895.31624723226, 6651124.463161212, 73.84777029812942], + [510890.11765147443, 6651133.599160205, 70.2980997021815], + [510890.0197387282, 6651134.301974417, 69.71896269618149], + [510890.69994534896, 6651129.4194754725, 74.4298308571815], + [510890.5876643615, 6651130.225424409, 73.7044181451815], + [510890.1345064874, 6651133.478175522, 70.7244100531815], + [510895.20530383894, 6651125.247338717, 73.51535390212942], + [510895.26641973795, 6651124.815355238, 74.00426159012942], + [510890.5288409244, 6651130.64765695, 73.58226502318149], + [510890.02878280025, 6651134.23705639, 70.19623364818152], + [510890.6348005337, 6651129.88708264, 74.3870556161815], + [510890.1575654265, 6651133.312659276, 71.1462189121815], + [510890.4706386151, 6651131.065431057, 73.41515026618151], + [510890.18685608363, 6651133.10241198, 71.5565684551815], + [510895.14558525756, 6651125.669445583, 73.63750702412942], + [510890.4140174926, 6651131.471855461, 73.2028724571815], + [510895.21588426747, 6651125.172553425, 74.13188434912941], + [510890.56844410993, 6651130.363386692, 74.2978909641815], + [510890.04444527865, 6651134.124631675, 70.6791346681815], + [510890.2222090524, 6651132.8486496275, 71.9483481491815], + [510890.35995868745, 6651131.859887643, 72.9466593341815], + [510890.252485071, 6651132.6313294405, 72.2258300091815], + [510890.3216710017, 6651132.134715291, 72.72724032818151], + [510890.28573470435, 6651132.392664757, 72.4862706821815], + [510890.51841941255, 6651130.72246219, 74.1987954701815], + [510890.06073450454, 6651134.007708192, 71.0408406531815], + [510895.1650983207, 6651125.531522047, 74.23097984312942], + [510895.086144492, 6651126.0895887725, 73.71618171712942], + [510890.46864143724, 6651131.079766729, 74.0711727111815], + [510890.0809986501, 6651133.862252874, 71.3985984991815], + [510890.4195608259, 6651131.432065613, 73.91468141918152], + [510890.1052401361, 6651133.688248351, 71.7490547141815], + [510890.37164432526, 6651131.776008551, 73.7294725171815], + [510890.1333903089, 6651133.486187411, 72.0887997411815], + [510895.02778906137, 6651126.502060527, 73.7539245761294], + [510890.32536198973, 6651132.1082215095, 73.5162201821815], + [510890.16530705616, 6651133.257090134, 72.4144668511815], + [510890.2811732329, 6651132.425406835, 73.2761317351815], + [510890.20077558403, 6651133.002498302, 72.7228356591815], + [510895.0977321196, 6651126.0076843295, 74.32014449512941], + [510890.23951251997, 6651132.724445951, 73.01093401018151], + [510895.03159596474, 6651126.4751523165, 74.36291973612943], + [510893.93069086946, 6651134.256643257, 67.35765722912942], + [510893.93069086946, 6651134.256643257, 67.48765722912941], + [510893.8452964614, 6651134.860233717, 67.35765722912942], + [510894.7826448441, 6651128.23480526, 73.7539245761294], + [510893.93069054175, 6651134.256645573, 69.1864608891294], + [510893.93132728094, 6651134.252144931, 69.3902821731294], + [510894.54259682476, 6651129.931528707, 73.7539245761294], + [510905.6944133563, 6651123.011681235, 67.17808119638813], + [510893.8452964614, 6651134.860233717, 69.18646088812942], + [510893.93661439157, 6651134.214774222, 69.80686146112942], + [510894.48424139415, 6651130.344000459, 73.71618171712942], + [510893.9476353321, 6651134.136875275, 70.23118858112942], + [510893.848232601, 6651134.839480299, 69.6520515751294], + [510894.5387902491, 6651129.9584345985, 74.36291973612943], + [510894.42480062856, 6651130.764143649, 73.63750702412942], + [510905.60571014445, 6651123.614794314, 67.17808119638813], + [510893.9647468358, 6651134.015926601, 70.65749893212941], + [510905.60571014445, 6651123.614794314, 67.30808119638813], + [510894.3650820473, 6651131.186250514, 73.51535390212942], + [510893.857414301, 6651134.7745815925, 70.12932252712942], + [510894.47265409434, 6651130.4259025855, 74.32014449512941], + [510893.98815667373, 6651133.850459621, 71.07930779112941], + [510894.30599404575, 6651131.603900274, 73.34823914512941], + [510894.0178930608, 6651133.640274904, 71.48965733412942], + [510894.24851129286, 6651132.010203708, 73.13596133612941], + [510893.8733151229, 6651134.662190341, 70.61222354712942], + [510894.4052878933, 6651130.902064868, 74.23097984312942], + [510894.05378401256, 6651133.38658808, 71.88143702812941], + [510894.1936298492, 6651132.398120395, 72.87974821312942], + [510894.0845207557, 6651133.16933258, 72.15891888812942], + [510894.15475952154, 6651132.672866243, 72.66032920712941], + [510894.11827636434, 6651132.93073893, 72.41935956112941], + [510893.8898522296, 6651134.54530166, 70.97392953212943], + [510894.35450194636, 6651131.26103349, 74.13188434912941], + [510893.9104247444, 6651134.399889637, 71.33168737812943], + [510894.303966476, 6651131.618231678, 74.00426159012942], + [510905.6944133563, 6651123.011681235, 69.00688485538814], + [510893.93503512454, 6651134.225936903, 71.68214359312941], + [510894.25413898163, 6651131.970425703, 73.84777029812942], + [510894.20549331285, 6651132.314266268, 73.66256139612942], + [510893.963613672, 6651134.023936105, 72.02188862012942], + [510894.1585066771, 6651132.646380346, 73.44930906112941], + [510893.9960161115, 6651133.794907017, 72.34755573012941], + [510894.11364547885, 6651132.963471265, 73.2092206141294], + [510894.0320243808, 6651133.540390962, 72.65592453812943], + [510894.0713507951, 6651133.262421373, 72.94402288912941], + [510905.6913634492, 6651123.032418239, 69.47247554238812], + [510905.60571014445, 6651123.614794314, 69.00688485538814], + [510905.60301905, 6651123.633091672, 69.41770016738813], + [510905.681825983, 6651123.097265616, 69.94974649438814], + [510905.5946036386, 6651123.690309946, 69.83882159538813], + [510905.665309047, 6651123.209567977, 70.43264751438814], + [510905.5800298714, 6651123.789400265, 70.26491073038812], + [510905.6481311718, 6651123.326364213, 70.79435349938814], + [510905.5590001202, 6651123.932386272, 70.68981723438813], + [510905.6267615274, 6651123.47166123, 71.15211134538814], + [510905.601197561, 6651123.645476383, 71.50256756038813], + [510905.53138838866, 6651124.120124641, 71.10678393638813], + [510905.57151167176, 6651123.847317419, 71.84231258738814], + [510905.4972674815, 6651124.352120361, 71.50873285338812], + [510905.5378537247, 6651124.076165368, 72.16797969738813], + [510905.45692371484, 6651124.6264267005, 71.88861365538813], + [510905.50045023166, 6651124.330480128, 72.47634850538813], + [510905.4228746138, 6651124.857934194, 72.15501997038814], + [510905.4596000245, 6651124.608229869, 72.76444685638813], + [510905.38588526996, 6651125.10943306, 72.40272971038813], + [510905.4156665354, 6651124.90694354, 73.02964458138813], + [510905.3325826452, 6651125.471849589, 72.70017218038814], + [510905.36906708626, 6651125.22378367, 73.26973302838813], + [510905.27557469293, 6651125.859459472, 72.95638530338813], + [510905.32025984454, 6651125.555635081, 73.48298536338815], + [510905.21586463787, 6651126.265441561, 73.16866311238813], + [510911.9093325254, 6651123.936607438, 67.0612983281163], + [510905.2697292868, 6651125.899203703, 73.66819426538814], + [510905.15448713506, 6651126.682761002, 73.33577786938812], + [510911.818566591, 6651124.539413537, 67.0612983281163], + [510905.21797111095, 6651126.251119177, 73.82468555738815], + [510911.818566591, 6651124.539413537, 67.19129832811629], + [510912.4432672205, 6651124.017083507, 67.0510918198317], + [510905.09245461907, 6651127.104534024, 73.45793099138814], + [510905.1654775269, 6651126.608034858, 73.95230831638814], + [510912.3523240739, 6651124.619862897, 67.0510918198317], + [510912.3523240739, 6651124.619862897, 67.18109181983169], + [510905.112723761, 6651126.966719572, 74.05140381038814], + [510905.03071068355, 6651127.524344925, 73.53660568438814], + [510911.9093325254, 6651123.936607438, 68.8901019871163], + [510904.97009413684, 6651127.936490453, 73.57434854338813], + [510905.04274730064, 6651127.442505258, 74.14056846238815], + [510911.9062116951, 6651123.957333889, 69.3556926741163], + [510911.818566591, 6651124.539413537, 68.8901019871163], + [510904.9740485475, 6651127.909603526, 74.18334370338813], + [510912.4432672205, 6651124.017083507, 68.8798954788317], + [510911.81581291725, 6651124.55770158, 69.3009172991163], + [510911.8964524427, 6651124.022148259, 69.8329636261163], + [510903.8304863374, 6651135.684940094, 67.17808119638813], + [510912.44014029705, 6651124.037809039, 69.3454861658317], + [510903.8304863374, 6651135.684940094, 67.30808119638813], + [510912.3523240739, 6651124.619862897, 68.8798954788317], + [510911.8072018121, 6651124.614890731, 69.72203872711628], + [510911.87955141853, 6651124.134393457, 70.3158646461163], + [510903.7417831255, 6651136.2880531745, 67.17808119638813], + [510912.34956502385, 6651124.638150129, 69.29071079083171], + [510912.4303619906, 6651124.102620537, 69.8227571178317], + [510904.7154512396, 6651129.667864761, 73.57434854338813], + [510911.79228914366, 6651124.713930614, 70.1481278621163], + [510911.86197408556, 6651124.251130244, 70.6775706311163], + [510912.34093710635, 6651124.695336746, 69.71183221883169], + [510912.4134279686, 6651124.214860763, 70.3056581378317], + [510911.7707703624, 6651124.85684384, 70.57303436611629], + [510911.8401075071, 6651124.396353305, 71.0353284771163], + [510912.32599532226, 6651124.794372239, 70.1379213538317], + [510912.3958163176, 6651124.331592378, 70.66736412283171], + [510903.830485997, 6651135.684942409, 69.00688485638813], + [510911.81394907105, 6651124.570079989, 71.38578469211629], + [510911.74251654197, 6651125.044486653, 70.99000106811629], + [510903.8311474081, 6651135.680445326, 69.21070614038813], + [510912.3044345275, 6651124.937279135, 70.56282785783169], + [510912.3739070466, 6651124.476809003, 71.0251219688317], + [510904.4661020046, 6651131.363246271, 73.57434854338813], + [510903.7417831255, 6651136.2880531745, 69.00688485538814], + [510903.8366393801, 6651135.643104174, 69.62728542838813], + [510911.78357286006, 6651124.771818289, 71.7255297191163], + [510911.7076021803, 6651125.276364288, 71.3919499851163], + [510904.4054854578, 6651131.775391801, 73.53660568438814], + [510912.3476975387, 6651124.6505279895, 71.37557818383169], + [510903.8480873526, 6651135.565266836, 70.05161254838814], + [510912.2761255442, 6651125.124913633, 70.97979455983169], + [510903.7448330327, 6651136.26731617, 69.47247554238812], + [510904.46214793436, 6651131.390130883, 74.18334370338813], + [510904.3437415222, 6651132.195202701, 73.45793099138814], + [510911.7491322243, 6651125.000549755, 72.05119682911631], + [510903.8658618811, 6651135.444413821, 70.47792289938815], + [510904.28170900635, 6651132.616975722, 73.33577786938812], + [510912.3172620209, 6651124.8522573495, 71.7153232108317], + [510911.6663202515, 6651125.550531007, 71.77183078711629], + [510903.754370499, 6651136.202468793, 69.94974649438814], + [510904.3934491813, 6651131.857229152, 74.14056846238815], + [510903.89017878723, 6651135.279077708, 70.89973175838813], + [510912.2411430154, 6651125.356780993, 71.3817434768317], + [510904.2203315035, 6651133.034295163, 73.16866311238813], + [510903.9210673794, 6651135.069059225, 71.31008130138814], + [510911.7108589428, 6651125.254735068, 72.35956563711629], + [510903.7708874349, 6651136.090166433, 70.43264751438814], + [510904.16062144836, 6651133.440277252, 72.95638530338813], + [510904.3234727209, 6651132.333014838, 74.05140381038814], + [510903.95834900916, 6651134.815573043, 71.70186099538815], + [510911.63147936563, 6651125.781920664, 72.03823710211628], + [510904.10361349623, 6651133.827887136, 72.70017218038814], + [510903.99027671845, 6651134.598489368, 71.97934285538813], + [510904.0632370478, 6651134.102415687, 72.48075317438813], + [510904.02534026635, 6651134.360084424, 72.23978352838813], + [510912.282754143, 6651125.080978681, 72.04099032083171], + [510903.7880653101, 6651135.973370197, 70.79435349938814], + [510904.2707189551, 6651132.691699551, 73.95230831638814], + [510912.1997804874, 6651125.630935564, 71.76162427883169], + [510903.8094349546, 6651135.82807318, 71.15211134538814], + [510911.66905879654, 6651125.532343438, 72.64766398811629], + [510904.2182253709, 6651133.048615232, 73.82468555738815], + [510911.59362986404, 6651126.033291517, 72.28594684211629], + [510903.83499892085, 6651135.654258027, 71.50256756038813], + [510904.1664671951, 6651133.400530706, 73.66819426538814], + [510912.24440613645, 6651125.335152732, 72.3493591288317], + [510903.8646848101, 6651135.45241699, 71.84231258738814], + [510904.11593663733, 6651133.74409933, 73.48298536338815], + [510912.16487157793, 6651125.862314968, 72.02803059383169], + [510903.89834275714, 6651135.223569042, 72.16797969738813], + [510904.0671293956, 6651134.07595074, 73.26973302838813], + [510903.93574625015, 6651134.969254282, 72.47634850538813], + [510904.02052994655, 6651134.39279087, 73.02964458138813], + [510903.9765964573, 6651134.691504541, 72.76444685638813], + [510911.6241036692, 6651125.830905064, 72.9128617131163], + [510911.5390877292, 6651126.395523578, 72.58338931211631], + [510912.2025243793, 6651125.612748801, 72.6374574798317], + [510912.1269481787, 6651126.1136746835, 72.27574033383169], + [510911.57642058696, 6651126.147583925, 73.1529501601163], + [510912.1574814811, 6651125.911297198, 72.9026552048317], + [510911.48075410246, 6651126.782936172, 72.8396024351163], + [510912.07229955535, 6651126.475890695, 72.57318280383171], + [510911.52647837176, 6651126.479266424, 73.3662024951163], + [510912.109705302, 6651126.227962027, 73.1427436518317], + [510911.4196555375, 6651127.188711617, 73.05188024411629], + [510911.47477276606, 6651126.822660171, 73.5514113971163], + [510912.01385203755, 6651126.863286121, 72.82939592683171], + [510912.0596655792, 6651126.55962983, 73.3559959868317], + [510911.3568507498, 6651127.605818644, 73.21899500111631], + [510911.42181099503, 6651127.174396523, 73.7079026891163], + [510911.95263418334, 6651127.269043588, 73.0416737358317], + [510912.0078590231, 6651126.903008361, 73.5412048888317], + [510911.2933757172, 6651128.027376986, 73.34114812311628], + [510911.36809671443, 6651127.531130535, 73.83552544811629], + [510911.889706775, 6651127.686132133, 73.2087884928317], + [510911.9547938491, 6651127.2547291275, 73.6976961808317], + [510911.3141162017, 6651127.88963268, 73.9346209421163], + [510911.2301959755, 6651128.446974205, 73.4198228161163], + [510911.8261078131, 6651128.107671796, 73.33094161483169], + [510911.90097469627, 6651127.611447334, 73.82531893983169], + [510911.1681698393, 6651128.858909952, 73.45756567511629], + [510911.2425124945, 6651128.365176194, 74.02378559411629], + [510911.8468887916, 6651127.969933594, 73.9244144338317], + [510911.7628047189, 6651128.527250421, 73.4096163078317], + [510911.17221620656, 6651128.832036711, 74.06656083511629], + [510911.70065748226, 6651128.939167919, 73.44735916683169], + [510911.7751452848, 6651128.445456036, 74.0135790858317], + [510910.0020613679, 6651136.603415671, 67.0612983281163], + [510910.0020613679, 6651136.603415671, 67.19129832811629], + [510911.70471174974, 6651128.912295869, 74.0563543268317], + [510909.9112954335, 6651137.2062217705, 67.0612983281163], + [510910.90760542435, 6651130.589403001, 73.45756567511629], + [510910.53227229137, 6651136.683330483, 67.0510918198317], + [510910.53227229137, 6651136.683330483, 67.18109181983169], + [510910.4413291449, 6651137.286109873, 67.0510918198317], + [510911.43958433927, 6651130.669584288, 73.44735916683169], + [510910.00206101965, 6651136.603417983, 68.8901019881163], + [510910.0027378113, 6651136.5989231905, 69.09392327211629], + [510910.65245777124, 6651132.283921569, 73.45756567511629], + [510909.9112954335, 6651137.2062217705, 68.8901019871163], + [510910.0083574948, 6651136.561601045, 69.5105025601163], + [510910.5322719425, 6651136.683332797, 68.8798954798317], + [510910.59043163504, 6651132.695857318, 73.4198228161163], + [510910.02007168066, 6651136.483803324, 69.93482968011631], + [510910.53295005544, 6651136.678838202, 69.08371676383169], + [510909.9144162638, 6651137.185495321, 69.3556926741163], + [510910.64841175237, 6651132.310792496, 74.06656083511629], + [510910.5272518934, 6651133.115454536, 73.34114812311628], + [510910.03825954173, 6651136.363011824, 70.36114003111629], + [510911.1839385339, 6651132.364027774, 73.44735916683169], + [510910.4413291449, 6651137.286109873, 68.8798954788317], + [510910.5385807108, 6651136.64151771, 69.5002960518317], + [510910.46377686074, 6651133.537012877, 73.21899500111631], + [510909.92417551624, 6651137.12068095, 69.8329636261163], + [510910.5781154644, 6651132.777653014, 74.02378559411629], + [510910.0631419182, 6651136.197759866, 70.78294889011629], + [510911.1217912973, 6651132.775945271, 73.4096163078317], + [510910.400972073, 6651133.954119906, 73.05188024411629], + [510910.55031776766, 6651136.5637234375, 69.92462317183171], + [510910.09474880004, 6651135.987848282, 71.1932984331163], + [510910.4444560683, 6651137.265384341, 69.3454861658317], + [510909.9410765405, 6651137.00843575, 70.3158646461163], + [510910.3398735081, 6651134.359895351, 72.8396024351163], + [510910.5065117572, 6651133.253196527, 73.9346209421163], + [510910.1328973843, 6651135.734491124, 71.58507812711629], + [510911.1798846155, 6651132.3908975115, 74.0563543268317], + [510911.0584882031, 6651133.195523898, 73.33094161483169], + [510910.28153988137, 6651134.747307943, 72.58338931211631], + [510910.1655675471, 6651135.517517943, 71.86255998711628], + [510910.2402245108, 6651135.021696761, 72.36397030611629], + [510910.2014464698, 6651135.279234346, 72.1230006601163], + [510910.5685411388, 6651136.4429372875, 70.3509335228317], + [510922.71994794323, 6651125.597320058, 66.84928826316256], + [510909.9586538735, 6651136.891698964, 70.6775706311163], + [510910.4525312445, 6651133.611698673, 73.83552544811629], + [510910.99488924124, 6651133.61706356, 73.2087884928317], + [510910.45423437475, 6651137.200572843, 69.8227571178317], + [510909.98052045197, 6651136.746475902, 71.0353284771163], + [510910.5934720958, 6651136.277692652, 70.77274238183169], + [510911.10945108056, 6651132.857737343, 74.0135790858317], + [510910.3988169639, 6651133.968432685, 73.7079026891163], + [510910.9319618329, 6651134.034152106, 73.0416737358317], + [510910.0066788879, 6651136.572749219, 71.38578469211629], + [510910.6251406871, 6651136.0677903695, 71.1830919248317], + [510910.34585519286, 6651134.320169036, 73.5514113971163], + [510910.4711683966, 6651137.088332616, 70.3056581378317], + [510922.6255939815, 6651126.199574968, 66.84928826316256], + [510910.8707439787, 6651134.439909572, 72.82939592683171], + [510910.03705509886, 6651136.371010919, 71.7255297191163], + [510910.2941495873, 6651134.663562784, 73.3662024951163], + [510911.0377075736, 6651133.333259786, 73.9244144338317], + [510910.66336375306, 6651135.814444437, 71.5748716188317], + [510910.81229646085, 6651134.827304999, 72.57318280383171], + [510910.69609770126, 6651135.597480871, 71.8523534788317], + [510910.07149573474, 6651136.142279453, 72.05119682911631], + [510922.6255939815, 6651126.199574968, 66.97928826316257], + [510910.244207372, 6651134.9952452835, 73.1529501601163], + [510910.77090042585, 6651135.101681658, 72.35376379783169], + [510910.73204667435, 6651135.35920783, 72.11279415183171], + [510910.1097690162, 6651135.888094139, 72.35956563711629], + [510910.19652428984, 6651135.311924145, 72.9128617131163], + [510910.1515691624, 6651135.61048577, 72.64766398811629], + [510910.48878004774, 6651136.971601002, 70.66736412283171], + [510910.98362166894, 6651133.691746046, 73.82531893983169], + [510910.5106893187, 6651136.826384375, 71.0251219688317], + [510910.9298025161, 6651134.048464252, 73.6976961808317], + [510910.5368988266, 6651136.652665391, 71.37557818383169], + [510910.8767373421, 6651134.400185017, 73.5412048888317], + [510910.56733434444, 6651136.450936031, 71.7153232108317], + [510910.82493078604, 6651134.7435635505, 73.3559959868317], + [510910.6018422223, 6651136.222214699, 72.04099032083171], + [510910.7748910632, 6651135.075231353, 73.1427436518317], + [510910.6401902289, 6651135.968040647, 72.3493591288317], + [510910.7271148843, 6651135.391896181, 72.9026552048317], + [510910.682071986, 6651135.690444578, 72.6374574798317], + [510922.71994794323, 6651125.597320058, 68.67809192216257], + [510922.71670374484, 6651125.618027556, 69.14368260916255], + [510922.6255939815, 6651126.199574968, 68.67809192216257], + [510922.62273145345, 6651126.217846289, 69.08890723416256], + [510922.70655870374, 6651125.682782662, 69.62095356116257], + [510922.61377994664, 6651126.274983148, 69.51002866216255], + [510922.68898957275, 6651125.794925229, 70.10385458116257], + [510922.59827777214, 6651126.3739324715, 69.93611779716255], + [510922.6707173981, 6651125.911555273, 70.46556056616257], + [510922.5759083416, 6651126.516715024, 70.36102430116256], + [510922.6479864217, 6651126.056645547, 70.82331841216256], + [510922.62079392845, 6651126.23021338, 71.17377462716257], + [510922.5465376321, 6651126.70418626, 70.77799100316255], + [510922.589216929, 6651126.431767216, 71.51351965416256], + [510922.51024308644, 6651126.935851873, 71.17993992016255], + [510922.55341483594, 6651126.660289537, 71.83918676416256], + [510922.4673292602, 6651127.209767902, 71.55982072216257], + [510922.5136285905, 6651126.9142424315, 72.14755557216256], + [510922.43111109495, 6651127.440945984, 71.82622703716255], + [510922.47017606156, 6651127.191596963, 72.43565392316256], + [510922.39176538173, 6651127.692086992, 72.07393677716257], + [510922.4234438331, 6651127.489885594, 72.70085164816255], + [510922.33506716625, 6651128.053987837, 72.37137924716257], + [510922.37387581245, 6651127.806274893, 72.94094009516256], + [510922.27442757913, 6651128.441046191, 72.62759237016256], + [510922.32195935387, 6651128.137654111, 73.15419243016257], + [510922.2109137543, 6651128.846450608, 72.83987017916256], + [510922.2682097972, 6651128.4807338705, 73.33940133216257], + [510929.1382577701, 6651126.614498805, 66.71807430255812], + [510922.14562625857, 6651129.263176247, 73.00698493616255], + [510922.2131544181, 6651128.832148603, 73.49589262416256], + [510929.0417735806, 6651127.216416116, 66.71807430255812], + [510922.0796420229, 6651129.684349127, 73.12913805816257], + [510929.0417735806, 6651127.216416116, 66.8480743025581], + [510922.1573167824, 6651129.188556428, 73.62351538316257], + [510922.10120239033, 6651129.546730771, 73.72261087716257], + [510922.0139647514, 6651130.103562677, 73.20781275116256], + [510921.94948668766, 6651130.5151217645, 73.24555561016255], + [510922.0267681491, 6651130.021839462, 73.81177552916256], + [510929.1382577701, 6651126.614498805, 68.54687796155812], + [510921.95369301015, 6651130.488273094, 73.85455077016256], + [510929.1349403274, 6651126.635194695, 69.0124686485581], + [510929.0417735806, 6651127.216416116, 68.54687796155812], + [510920.737281306, 6651138.252546136, 66.84928826316256], + [510920.737281306, 6651138.252546136, 66.97928826316257], + [510929.03884642536, 6651127.234677196, 68.9576932735581], + [510929.124566242, 6651126.699913502, 69.48973960055811], + [510920.64292734413, 6651138.854801047, 66.84928826316256], + [510921.6786220178, 6651132.2440325, 73.24555561016255], + [510929.02969282056, 6651127.291782024, 69.3788147015581], + [510929.10660045303, 6651126.811993206, 69.97264062055812], + [510929.0138406538, 6651127.390675882, 69.80490383655811], + [510929.08791574783, 6651126.928557873, 70.33434660555811], + [510931.9169592113, 6651127.062094056, 66.66002999750813], + [510920.7372809439, 6651138.252548446, 68.67809192316255], + [510928.99096618895, 6651127.533378394, 70.22981034055812], + [510929.0646715746, 6651127.073566816, 70.69210445155811], + [510920.73798448953, 6651138.248057762, 68.88191320716255], + [510931.81955277483, 6651127.6638628105, 66.66002999750813], + [510921.4133882375, 6651133.937001651, 73.24555561016255], + [510931.81955277483, 6651127.6638628105, 66.79002999750811], + [510920.64292734413, 6651138.854801047, 68.67809192216257], + [510920.7438263221, 6651138.210769743, 69.29849249516256], + [510929.03686515684, 6651127.247037352, 71.0425606665581], + [510928.96093237755, 6651127.720744543, 70.6467770425581], + [510921.3489101739, 6651134.348560738, 73.20781275116256], + [510920.75600357633, 6651138.13304316, 69.72281961516256], + [510920.6461715426, 6651138.834093549, 69.14368260916255], + [510921.4091822772, 6651133.963848009, 73.85455077016256], + [510929.00457524415, 6651127.448478205, 71.38230569355812], + [510921.28323290235, 6651134.767774289, 73.12913805816257], + [510920.7749104135, 6651138.012362106, 70.14912996616256], + [510928.9238184106, 6651127.952280293, 71.0487259595581], + [510920.6563165837, 6651138.769338443, 69.62095356116257], + [510921.2172486666, 6651135.188947171, 73.00698493616255], + [510920.80077640404, 6651137.847261251, 70.57093882516256], + [510921.33610713837, 6651134.430281643, 73.81177552916256], + [510931.9169592113, 6651127.062094056, 68.48883365650812], + [510921.151961171, 6651135.6056728065, 72.83987017916256], + [510928.96796484786, 6651127.676872426, 71.7079728035581], + [510920.83363272325, 6651137.637541602, 70.98128836816258], + [510920.67388571467, 6651138.657195876, 70.10385458116257], + [510921.08844734606, 6651136.011077224, 72.62759237016256], + [510920.87328934215, 6651137.384416107, 71.37306806216256], + [510921.2616728971, 6651134.905390334, 73.72261087716257], + [510928.8799357197, 6651128.226042776, 71.4286067615581], + [510921.02780775895, 6651136.398135577, 72.37137924716257], + [510920.9072509745, 6651137.16764132, 71.65054992216255], + [510920.98485916905, 6651136.672273502, 72.15196024116256], + [510920.9445482108, 6651136.9295756025, 71.91099059516256], + [510920.6921578893, 6651138.54056583, 70.46556056616257], + [510921.20555850497, 6651135.263564675, 73.62351538316257], + [510931.9136100587, 6651127.082784838, 68.95442434350811], + [510931.81955277483, 6651127.6638628105, 68.48883365650812], + [510928.9272803492, 6651127.930682964, 72.0163416115581], + [510920.7148888657, 6651138.395475556, 70.82331841216256], + [510921.1497208692, 6651135.6199725, 73.49589262416256], + [510928.84289985773, 6651128.457091268, 71.69501307655811], + [510920.742081359, 6651138.221907725, 71.17377462716257], + [510921.09466549027, 6651135.9713872345, 73.33940133216257], + [510920.77365835843, 6651138.020353888, 71.51351965416256], + [510931.81659764034, 6651127.682119383, 68.89964896850812], + [510921.04091593355, 6651136.314466992, 73.15419243016257], + [510931.9031368123, 6651127.147487671, 69.43169529550813], + [510920.80946045154, 6651137.791831567, 71.83918676416256], + [510920.988999475, 6651136.64584621, 72.94094009516256], + [510920.84924669686, 6651137.5378786735, 72.14755557216256], + [510928.8828467932, 6651128.207882023, 72.30443996255812], + [510920.9394314543, 6651136.962235509, 72.70085164816255], + [510920.8926992259, 6651137.26052414, 72.43565392316256], + [510928.80266583705, 6651128.708091495, 71.9427228165581], + [510931.8073565405, 6651127.739210118, 69.32077039650812], + [510931.8849992968, 6651127.259539713, 69.91459631550813], + [510928.83505949215, 6651128.506003444, 72.5696376875581], + [510928.7446875469, 6651129.069789475, 72.24016528655811], + [510931.7913528504, 6651127.838079567, 69.74685953150811], + [510931.86613599333, 6651127.376075613, 70.27630230050812], + [510928.78437237523, 6651128.822215388, 72.8097261345581], + [510928.682678901, 6651129.456630859, 72.4963784095581], + [510931.7682597393, 6651127.980746861, 70.17176603550811], + [510931.84266963997, 6651127.521048766, 70.63406014650812], + [510928.73128379975, 6651129.153408848, 73.02297846955811], + [510931.8145974338, 6651127.69447649, 70.98451636150811], + [510928.6177311257, 6651129.8618080225, 72.7086562185581], + [510931.7379388489, 6651128.168066767, 70.58873273750811], + [510928.6763207404, 6651129.496296291, 73.20818737155811], + [510931.78199887706, 6651127.895867626, 71.32426138850812], + [510928.5509696356, 6651130.278300061, 72.87577097555811], + [510928.62002237706, 6651129.847514034, 73.36467866355811], + [510931.70047012705, 6651128.3995453715, 70.99068165450811], + [510931.74503853923, 6651128.1242054785, 71.64992849850812], + [510928.483495675, 6651130.699236848, 72.9979240975581], + [510928.5629240961, 6651130.203722072, 73.4923014225581], + [510931.65616798215, 6651128.67324029, 71.37056245650811], + [510928.50554281037, 6651130.561695635, 73.59139691655812], + [510928.41633560887, 6651131.118215404, 73.07659879055812], + [510931.7039651566, 6651128.377953374, 71.95829730650811], + [510931.61877811176, 6651128.904231757, 71.63696877150811], + [510928.3504018253, 6651131.529543788, 73.11434164955811], + [510928.42942806875, 6651131.036537999, 73.6805615685581], + [510931.6591068812, 6651128.655084019, 72.24639565750813], + [510931.578159513, 6651129.1551700365, 71.88467851150811], + [510928.3547031138, 6651131.502710169, 73.7233368095581], + [510931.6108628039, 6651128.953131862, 72.51159338250811], + [510927.1108285054, 6651139.262630868, 66.71807430255812], + [510931.5196270357, 6651129.516778748, 72.18212098150812], + [510927.1108285054, 6651139.262630868, 66.8480743025581], + [510931.55969119264, 6651129.269265763, 72.75168182950812], + [510927.01434431603, 6651139.864548177, 66.71807430255812], + [510931.45702567836, 6651129.903524657, 72.43833410450812], + [510928.0734218488, 6651133.257485365, 73.11434164955811], + [510931.5060951684, 6651129.600377483, 72.96493416450812], + [510931.39145709784, 6651130.308601822, 72.65061191350811], + [510931.450606743, 6651129.943180299, 73.15014306650812], + [510927.1108281352, 6651139.2626331765, 68.5468779625581], + [510931.32405746606, 6651130.724991065, 72.81772667050811], + [510931.39377025014, 6651130.294311362, 73.30663435850812], + [510927.11154756474, 6651139.258145011, 68.75069924655811], + [510931.25593855366, 6651131.145823965, 72.93987979250812], + [510927.8021998904, 6651134.949505504, 73.11434164955811], + [510927.01434431603, 6651139.864548177, 68.54687796155812], + [510931.33612619364, 6651130.650431485, 73.43425711750811], + [510927.11752128834, 6651139.220877892, 69.16727853455812], + [510927.73626610683, 6651135.360833889, 73.07659879055812], + [510927.129973468, 6651139.143194879, 69.59160565455811], + [510931.2781964273, 6651131.008316698, 73.53335261150812], + [510931.18813653616, 6651131.564699115, 73.01855448550813], + [510927.01766175864, 6651139.843852287, 69.0124686485581], + [510927.79789897223, 6651134.9763368135, 73.7233368095581], + [510927.6691060406, 6651135.779812445, 72.9979240975581], + [510927.1493071646, 6651139.022581476, 70.0179160055581], + [510931.12157252245, 6651131.975925981, 73.05629734450812], + [510927.02803584404, 6651139.77913348, 69.48973960055811], + [510927.6016320801, 6651136.200749233, 72.87577097555811], + [510927.17575713113, 6651138.857573168, 70.43972486455812], + [510931.2013541406, 6651131.483041869, 73.62251726350812], + [510927.7231740173, 6651135.442508983, 73.6805615685581], + [510927.53487058997, 6651136.61724127, 72.7086562185581], + [510927.20935524686, 6651138.647971082, 70.85007440755811], + [510927.046001633, 6651139.667053777, 69.97264062055812], + [510927.4699228147, 6651137.022418435, 72.4963784095581], + [510927.2499071924, 6651138.394987477, 71.2418541015581], + [510927.64705927565, 6651135.917351346, 73.59139691655812], + [510927.2846355759, 6651138.178334206, 71.5193359615581], + [510927.40791416867, 6651137.409259818, 72.24016528655811], + [510939.7204918468, 6651128.342472709, 66.49301605051268], + [510927.32277487125, 6651137.940401938, 71.7797766345581], + [510927.36399592925, 6651137.683244072, 72.02074628055811], + [510931.12591492495, 6651131.949098984, 73.66529250450812], + [510927.0646863382, 6651139.550489109, 70.33434660555811], + [510927.5896779899, 6651136.275324911, 73.4923014225581], + [510929.870150705, 6651139.707104495, 66.66002999750813], + [510927.0879305114, 6651139.405480167, 70.69210445155811], + [510927.53257970896, 6651136.6315329475, 73.36467866355811], + [510929.870150705, 6651139.707104495, 66.79002999750811], + [510927.1157369292, 6651139.23200963, 71.0425606665581], + [510927.4762813457, 6651136.982750693, 73.20818737155811], + [510939.62049542944, 6651128.943816506, 66.49301605051268], + [510927.14802684187, 6651139.030568777, 71.38230569355812], + [510927.4213182863, 6651137.325638134, 73.02297846955811], + [510939.62049542944, 6651128.943816506, 66.62301605051267], + [510927.18463723816, 6651138.802174556, 71.7079728035581], + [510927.3682297108, 6651137.656831594, 72.8097261345581], + [510927.2253217368, 6651138.548364019, 72.0163416115581], + [510929.77274426864, 6651140.308873249, 66.66002999750813], + [510927.3175425938, 6651137.973043539, 72.5696376875581], + [510927.2697552928, 6651138.271164959, 72.30443996255812], + [510930.8419450249, 6651133.703441093, 73.05629734450812], + [510939.7204918468, 6651128.342472709, 68.32181970951268], + [510929.87015033123, 6651139.7071068045, 68.48883365750811], + [510929.87087663746, 6651139.702619746, 68.69265494150811], + [510939.7170536422, 6651128.363148879, 68.78741039651267], + [510939.62049542944, 6651128.943816506, 68.32181970951268], + [510930.5681305835, 6651135.395043635, 73.05629734450812], + [510929.77274426864, 6651140.308873249, 68.48883365650812], + [510929.8769074611, 6651139.665361826, 69.10923422950813], + [510939.61746171955, 6651128.962060186, 68.73263502151268], + [510939.70630191825, 6651128.427806021, 69.26468134851268], + [510930.50156656984, 6651135.8062705, 73.01855448550813], + [510929.88947866537, 6651139.587697985, 69.53356134950812], + [510929.7760934212, 6651140.288182467, 68.95442434350811], + [510930.56378855486, 6651135.421868321, 73.66529250450812], + [510939.6079749042, 6651129.019110605, 69.15375644951267], + [510930.43376455235, 6651136.22514565, 72.93987979250812], + [510929.9089971635, 6651139.467114348, 69.95987170050812], + [510939.68768213666, 6651128.539778934, 69.74758236851268], + [510929.7865666676, 6651140.223479633, 69.43169529550813], + [510930.36564563995, 6651136.645978549, 72.81772667050811], + [510929.9356999528, 6651139.302146767, 70.38168055950811], + [510930.48834933934, 6651135.887925437, 73.62251726350812], + [510930.2982460081, 6651137.062367794, 72.65061191350811], + [510939.59154568514, 6651129.117910235, 69.57984558451267], + [510929.96961921715, 6651139.092596412, 70.79203010250812], + [510929.804704183, 6651140.111427591, 69.91459631550813], + [510939.6683172688, 6651128.656232538, 70.10928835351268], + [510930.2326774276, 6651137.467444957, 72.43833410450812], + [510930.01055877964, 6651138.839675245, 71.18380979650811], + [510930.41150705266, 6651136.362650607, 73.53335261150812], + [510930.04561911547, 6651138.623075444, 71.46129165650811], + [510930.17007607024, 6651137.854190868, 72.18212098150812], + [510930.08412296633, 6651138.385201898, 71.72173232950811], + [510930.12573803705, 6651138.1281075, 71.96270197550812], + [510929.8235674865, 6651139.994891694, 70.27630230050812], + [510930.3535772863, 6651136.720535822, 73.43425711750811], + [510939.5678385415, 6651129.26047678, 70.00475208851269], + [510929.8470338399, 6651139.84991854, 70.63406014650812], + [510939.6442269587, 6651128.801103313, 70.46704619951268], + [510930.2959332297, 6651137.076655945, 73.30663435850812], + [510929.87510604603, 6651139.676490816, 70.98451636150811], + [510930.2390967368, 6651137.427787006, 73.15014306650812], + [510929.9077046028, 6651139.475099679, 71.32426138850812], + [510930.1836083114, 6651137.770589822, 72.96493416450812], + [510929.9446649406, 6651139.246761828, 71.64992849850812], + [510930.13001228723, 6651138.101701542, 72.75168182950812], + [510929.9857383233, 6651138.993013931, 71.95829730650811], + [510939.61540832865, 6651128.974408567, 70.81750241451267], + [510930.07884067605, 6651138.417835443, 72.51159338250811], + [510930.03059659875, 6651138.715883288, 72.24639565750813], + [510939.5367114361, 6651129.447664404, 70.42171879051267], + [510939.581942995, 6651129.175657485, 71.15724744151268], + [510939.4982464425, 6651129.678979545, 70.82366770751267], + [510939.54399990314, 6651129.40383409, 71.48291455151268], + [510939.45276632905, 6651129.952481185, 71.20354850951267], + [510939.50183440285, 6651129.657402795, 71.79128335951268], + [510939.4143822835, 6651130.183309532, 71.46995482451268], + [510939.45578337176, 6651129.934337736, 72.07938171051268], + [510939.37268365966, 6651130.434070605, 71.71766456451267], + [510939.4062565123, 6651130.232175105, 72.34457943551267], + [510939.31259483757, 6651130.795423956, 72.01510703451268], + [510939.35372427735, 6651130.54808576, 72.58466788251268], + [510939.2483289461, 6651131.181896754, 72.27132015751268], + [510939.2987031657, 6651130.878963656, 72.7979202175127], + [510939.1810169349, 6651131.586687861, 72.48359796651268], + [510945.8086486536, 6651129.365379294, 66.35860467732431], + [510939.241739335, 6651131.221524391, 72.98312911951268], + [510939.1118251857, 6651132.002783062, 72.65071272351267], + [510945.70663158584, 6651129.966383592, 66.35860467732431], + [510939.18339159264, 6651131.572407492, 73.1396204115127], + [510945.70663158584, 6651129.966383592, 66.4886046773243], + [510939.0418950307, 6651132.423318778, 72.77286584551268], + [510939.12421481375, 6651131.928276133, 73.26724317051267], + [510939.0647447283, 6651132.285908615, 73.36633866451268], + [510938.9722901965, 6651132.8418981265, 72.85154053851268], + [510945.8086486536, 6651129.365379294, 68.18740833632432], + [510938.90395628416, 6651133.252834594, 72.88928339751267], + [510938.98585924954, 6651132.760298545, 73.45550331651269], + [510945.80514097237, 6651129.386043793, 68.6529990233243], + [510945.70663158584, 6651129.966383592, 68.18740833632432], + [510938.90841414867, 6651133.2260265425, 73.49827855751268], + [510937.6192598813, 6651140.9785535205, 66.49301605051268], + [510945.70353657304, 6651129.984616972, 68.5982236483243], + [510937.6192598813, 6651140.9785535205, 66.62301605051267], + [510945.7941719858, 6651129.450664431, 69.13026997532431], + [510937.5192634639, 6651141.579897319, 66.49301605051268], + [510945.6938580555, 6651130.041635182, 69.0193450763243], + [510945.7751759502, 6651129.562574126, 69.61317099532432], + [510938.6168936525, 6651134.979129774, 72.88928339751267], + [510945.67709684744, 6651130.140379032, 69.44543421132431], + [510945.755419772, 6651129.678961985, 69.97487698032431], + [510945.65291064826, 6651130.2828650875, 69.87034071532432], + [510945.7308426635, 6651129.82375097, 70.33263482632431], + [510937.6192594977, 6651140.978555827, 68.32181971051267], + [510937.6200051159, 6651140.974071938, 68.52564099451267], + [510945.70144168887, 6651129.9969583815, 70.6830910413243], + [510945.6211545503, 6651130.469947032, 70.2873074173243], + [510937.5192634639, 6651141.579897319, 68.32181970951268], + [510938.3357986428, 6651136.669537742, 72.88928339751267], + [510937.62619629566, 6651140.936840328, 68.94222028251268], + [510945.6673001137, 6651130.19809368, 71.02283606832432], + [510938.2674647303, 6651137.080474208, 72.85154053851268], + [510937.639101761, 6651140.859231332, 69.36654740251268], + [510937.5227016685, 6651141.5592211485, 68.78741039651267], + [510945.58191228594, 6651130.7011315795, 70.6892563343243], + [510938.33134116215, 6651136.696343485, 73.49827855751268], + [510938.19785989623, 6651137.499053558, 72.77286584551268], + [510937.65913924476, 6651140.738732849, 69.79285775351269], + [510937.5334533925, 6651141.494564006, 69.26468134851268], + [510945.62859029707, 6651130.426141462, 71.34850317832431], + [510938.1279297412, 6651137.919589275, 72.65071272351267], + [510937.68655204587, 6651140.573881765, 70.21466661251267], + [510938.2538960613, 6651137.162071481, 73.45550331651269], + [510945.53551314556, 6651130.974478807, 71.0691371363243], + [510938.058737992, 6651138.335684474, 72.48359796651268], + [510937.72137320385, 6651140.364479389, 70.62501615551268], + [510937.55207317404, 6651141.382591093, 69.74758236851268], + [510937.9914259807, 6651138.740475582, 72.27132015751268], + [510937.76340132585, 6651140.111736829, 71.01679584951269], + [510938.1750105824, 6651137.636461412, 73.36633866451268], + [510937.79939389566, 6651139.895289987, 71.29427770951267], + [510937.92716008925, 6651139.126948379, 72.01510703451268], + [510945.58557274897, 6651130.679567009, 71.6568719863243], + [510937.8389215418, 6651139.657584422, 71.55471838251268], + [510937.8816431333, 6651139.400671579, 71.79568802851267], + [510937.5714380419, 6651141.26613749, 70.10928835351268], + [510945.49635346484, 6651131.205176835, 71.33554345132431], + [510938.11554049695, 6651137.994093895, 73.26724317051267], + [510937.595528352, 6651141.121266712, 70.46704619951268], + [510938.05636371806, 6651138.349962533, 73.1396204115127], + [510937.62434698205, 6651140.947961461, 70.81750241451267], + [510945.5385911543, 6651130.956345601, 71.9449703373243], + [510937.9980159757, 6651138.7008456355, 72.98312911951268], + [510937.6578123157, 6651140.746712541, 71.15724744151268], + [510945.45381222747, 6651131.455796335, 71.5832531913243], + [510937.9410521449, 6651139.043406372, 72.7979202175127], + [510937.69575540756, 6651140.518535936, 71.48291455151268], + [510937.88603103335, 6651139.374284267, 72.58466788251268], + [510937.7379209078, 6651140.264967231, 71.79128335951268], + [510937.8334987985, 6651139.6901949225, 72.34457943551267], + [510937.78397193894, 6651139.988032291, 72.07938171051268], + [510945.48806349415, 6651131.254014821, 72.2101680623243], + [510945.39250917686, 6651131.816945677, 71.88069566132431], + [510945.4344697285, 6651131.56974712, 72.4502565093243], + [510945.3269446499, 6651132.203200284, 72.1369087843243], + [510945.37833679287, 6651131.900438213, 72.66350884432433], + [510945.2582724496, 6651132.607762857, 72.3491865933243], + [510951.88891094783, 6651130.4079775, 66.2207633583812], + [510945.32022188103, 6651132.242805549, 72.84871774632431], + [510945.187682527, 6651133.023623142, 72.51630135032431], + [510951.78487584996, 6651131.008635759, 66.2207633583812], + [510945.2606950926, 6651132.593490551, 73.00520903832431], + [510951.78487584996, 6651131.008635759, 66.3507633583812], + [510945.1163392775, 6651133.443921437, 72.6384544723243], + [510945.20032251516, 6651132.949158277, 73.1328317973243], + [510945.04532792256, 6651133.862264468, 72.71712916532432], + [510945.1396507041, 6651133.306588852, 73.23192729132433], + [510951.88891094783, 6651130.4079775, 68.04956701738121], + [510944.9756131713, 6651134.272968933, 72.75487202432431], + [510945.05917116854, 6651133.780710955, 73.32109194332432], + [510951.88533388014, 6651130.428630099, 68.5151577043812], + [510951.78487584996, 6651131.008635759, 68.04956701738121], + [510944.9801611169, 6651134.246176015, 73.3638671843243], + [510943.6649566165, 6651141.9943261435, 66.35860467732431], + [510943.6649566165, 6651141.9943261435, 66.4886046773243], + [510951.7817196139, 6651131.026858642, 68.4603823293812], + [510951.87414791284, 6651130.493213531, 68.99242865638121], + [510943.5629395488, 6651142.59533044, 66.35860467732431], + [510951.77184964257, 6651131.083844024, 68.8815037573812], + [510951.85477611085, 6651130.605058793, 69.47532967638121], + [510944.68274979986, 6651135.998289496, 72.75487202432431], + [510951.7547568761, 6651131.18253102, 69.30759289238121], + [510951.8346291299, 6651130.721379639, 69.83703566138121], + [510951.7300922425, 6651131.324935039, 69.7324993963812], + [510951.8095658542, 6651130.866085261, 70.1947935073812], + [510943.66495622514, 6651141.994328449, 68.1874083373243], + [510943.66571691027, 6651141.98984709, 68.39122962132431], + [510951.7795832901, 6651131.039192946, 70.5452497223812], + [510951.6977079677, 6651131.511909266, 70.1494660983812], + [510943.5629395488, 6651142.59533044, 68.18740833632432], + [510943.67203319655, 6651141.952636503, 68.80780890932432], + [510944.39597463945, 6651137.687743109, 72.75487202432431], + [510943.6851994456, 6651141.875071323, 69.23213602932431], + [510944.3262598882, 6651138.098447572, 72.71712916532432], + [510951.7447663502, 6651131.240212437, 70.8849947493812], + [510943.56644723, 6651142.574665943, 68.6529990233243], + [510951.6576894403, 6651131.742960705, 70.5514150153812], + [510944.39142708544, 6651137.714533719, 73.3638671843243], + [510944.2552485334, 6651138.516790605, 72.6384544723243], + [510943.70564183145, 6651141.754640868, 69.65844638032432], + [510943.5774162165, 6651142.510045304, 69.13026997532431], + [510944.18390528375, 6651138.937088898, 72.51630135032431], + [510951.70529080316, 6651131.468128918, 71.2106618593812], + [510943.73360856925, 6651141.5898828525, 70.08025523932432], + [510944.3124170339, 6651138.179998779, 73.32109194332432], + [510944.11331536114, 6651139.352949184, 72.3491865933243], + [510943.76913336624, 6651141.380598699, 70.49060478232431], + [510951.6103724646, 6651132.01615055, 70.93129581738121], + [510943.5964122523, 6651142.398135608, 69.61317099532432], + [510944.04464316077, 6651139.757511758, 72.1369087843243], + [510943.81201075995, 6651141.127998831, 70.8823844763243], + [510944.2319374983, 6651138.654120883, 73.23192729132433], + [510943.84873063985, 6651140.911674188, 71.1598663363243], + [510943.9790786339, 6651140.143766365, 71.88069566132431], + [510943.88905703014, 6651140.674102826, 71.4203070093243], + [510943.9326419065, 6651140.417335027, 71.6612766553243], + [510943.61616843037, 6651142.28174775, 69.97487698032431], + [510951.6614223121, 6651131.7214085525, 71.5190306673812], + [510944.1712656873, 6651139.0115514565, 73.1328317973243], + [510951.5704381546, 6651132.2467157515, 71.1977021323812], + [510943.6407455389, 6651142.136958764, 70.33263482632431], + [510944.1108931098, 6651139.367219183, 73.00520903832431], + [510943.6701465135, 6651141.963751353, 70.6830910413243], + [510944.0513663213, 6651139.717904185, 72.84871774632431], + [510951.61351136037, 6651131.998027785, 71.8071290183812], + [510943.7042880887, 6651141.762616056, 71.02283606832432], + [510943.99325140956, 6651140.060271521, 72.66350884432433], + [510951.5270553962, 6651132.497190952, 71.44541187238121], + [510956.69455060066, 6651131.246897866, 66.10926455844026], + [510943.7429979053, 6651141.534568272, 71.34850317832431], + [510943.9371184739, 6651140.390962614, 72.4502565093243], + [510943.78601545334, 6651141.281142725, 71.6568719863243], + [510943.8835247082, 6651140.706694915, 72.2101680623243], + [510943.8329970481, 6651141.004364133, 71.9449703373243], + [510951.5619841975, 6651132.295525616, 72.07232674338121], + [510956.58892051806, 6651131.847277692, 66.10926455844026], + [510951.4645396917, 6651132.858132358, 71.74285434238121], + [510956.58892051806, 6651131.847277692, 66.23926455844025], + [510951.50733027747, 6651132.611076129, 72.31241519038122], + [510951.39767821325, 6651133.244164573, 71.99906746538122], + [510951.45008695946, 6651132.941576822, 72.52566752538121], + [510951.3276475875, 6651133.648494214, 72.2113452743812], + [510956.69455060066, 6651131.246897866, 67.93806821744026], + [510951.39082245925, 6651133.283747035, 72.71087642738121], + [510956.69091869215, 6651131.2675408935, 68.40365890444025], + [510951.2556613045, 6651134.064115061, 72.3784600313812], + [510956.58892051806, 6651131.847277692, 67.93806821744026], + [510951.3301181535, 6651133.634230126, 72.8673677193812], + [510956.5857158929, 6651131.865492125, 68.34888352944026], + [510956.6795612303, 6651131.332094387, 68.88092985644026], + [510951.18290679285, 6651134.484171363, 72.50061315338122], + [510951.2685513281, 6651133.98969307, 72.9949904783812], + [510956.5756946031, 6651131.922451091, 68.77000495744025], + [510951.1104907411, 6651134.902273528, 72.5792878463812], + [510951.2066793498, 6651134.346917849, 73.09408597238121], + [510956.659892435, 6651131.443887804, 69.36383087644026], + [510951.0393969415, 6651135.312741524, 72.6170307053812], + [510956.5583397836, 6651132.021092342, 69.19609409244028], + [510951.12460782443, 6651134.82076697, 73.1832506243812], + [510956.6394365763, 6651131.560154729, 69.72553686144026], + [510951.0440348513, 6651135.285964033, 73.2260258653812], + [510956.5332970111, 6651132.163430348, 69.62100059644025], + [510956.61398905015, 6651131.704793272, 70.08329470744026], + [510949.70281389734, 6651143.029653051, 66.2207633583812], + [510949.70281389734, 6651143.029653051, 66.3507633583812], + [510956.58354681684, 6651131.877820711, 70.43375092244025], + [510956.50041624595, 6651132.350317904, 70.03796729844025], + [510949.59877879947, 6651143.630311312, 66.2207633583812], + [510950.7407403521, 6651137.037068709, 72.6170307053812], + [510956.54819609073, 6651132.07874702, 70.77349594944026], + [510956.45978418575, 6651132.581262238, 70.43991621544025], + [510956.5081153355, 6651132.30655785, 71.09916305944026], + [510956.41174178326, 6651132.854325446, 70.81979701744025], + [510949.70281349815, 6651143.029655356, 68.0495670183812], + [510949.70358923066, 6651143.025176579, 68.2533883023812], + [510956.4635742871, 6651132.559720077, 71.40753186744026], + [510956.37119523156, 6651133.084783768, 71.08620333244025], + [510949.59877879947, 6651143.630311312, 68.04956701738121], + [510949.71003046125, 6651142.987987413, 68.6699675903812], + [510950.4482924064, 6651138.725549594, 72.6170307053812], + [510956.41492880206, 6651132.836211082, 71.69563021844026], + [510956.32714736264, 6651133.335142861, 71.33391307244025], + [510949.72345715575, 6651142.910466894, 69.0942947103812], + [510950.37719860673, 6651139.136017589, 72.5792878463812], + [510949.60235586704, 6651143.609658713, 68.5151577043812], + [510950.4436548959, 6651138.7523247795, 73.2260258653812], + [510949.7443039185, 6651142.790105779, 69.5206050613812], + [510950.30478255503, 6651139.554119755, 72.50061315338122], + [510956.3626116651, 6651133.133571006, 71.96082794344025], + [510949.61354183446, 6651143.545075281, 68.99242865638121], + [510956.2636732163, 6651133.695916952, 71.63135554244026], + [510949.7728238748, 6651142.625442625, 69.9424139203812], + [510950.23202804336, 6651139.974176056, 72.3784600313812], + [510950.3630819228, 6651139.217521841, 73.1832506243812], + [510950.16004176036, 6651140.389796902, 72.2113452743812], + [510949.8090513985, 6651142.4162789695, 70.35276346338122], + [510949.63291363645, 6651143.433230017, 69.47532967638121], + [510956.3071198339, 6651133.448975246, 72.20091639044026], + [510950.09001113474, 6651140.794126544, 71.99906746538122], + [510949.8527769627, 6651142.163824541, 70.7445431573812], + [510949.8902232096, 6651141.947624451, 71.0220250173812], + [510950.2810103975, 6651139.691370961, 73.09408597238121], + [510950.0231496563, 6651141.180158759, 71.74285434238121], + [510949.9313473083, 6651141.7101898715, 71.2824656903812], + [510949.97579435, 6651141.4535699105, 71.5234353363812], + [510949.6530606174, 6651143.316909172, 69.83703566138121], + [510956.19578666997, 6651134.081770221, 71.88756866544026], + [510950.2191384192, 6651140.04859574, 72.9949904783812], + [510949.6781238931, 6651143.172203549, 70.1947935073812], + [510962.45302920556, 6651132.269492191, 65.97268294412484], + [510956.24899890606, 6651133.779322733, 72.41416872544028], + [510950.1575715937, 6651140.4040586855, 72.8673677193812], + [510949.7081064571, 6651142.999095866, 70.5452497223812], + [510950.09686728806, 6651140.754541776, 72.71087642738121], + [510949.7429233971, 6651142.7980763735, 70.8849947493812], + [510956.1246823895, 6651134.485912433, 72.09984647444026], + [510950.0376027878, 6651141.0967119895, 72.52566752538121], + [510949.78239894414, 6651142.570159893, 71.2106618593812], + [510949.9803594697, 6651141.427212682, 72.31241519038122], + [510949.8262674352, 6651142.316880259, 71.5190306673812], + [510949.9257055497, 6651141.742763194, 72.07232674338121], + [510949.8741783869, 6651142.040261026, 71.8071290183812], + [510956.18882580893, 6651134.121334333, 72.59937762744026], + [510962.3454878923, 6651132.869532619, 65.97268294412484], + [510962.3454878923, 6651132.869532619, 66.10268294412484], + [510956.05159246904, 6651134.90134062, 72.26696123144026], + [510956.1271908323, 6651134.471654956, 72.75586891944027], + [510955.9777225421, 6651135.321202202, 72.38911435344025], + [510956.0646801124, 6651134.826953126, 72.88349167844027], + [510962.45302920556, 6651132.269492191, 67.80148660312486], + [510955.9041962641, 6651135.739110555, 72.46778904644026], + [510956.00185956137, 6651135.184012312, 72.98258717244026], + [510955.8320125099, 6651136.149388276, 72.50553190544025], + [510962.44933158264, 6651132.290123547, 68.26707729012483], + [510962.3454878923, 6651132.869532619, 67.80148660312486], + [510955.9185297795, 6651135.65764178, 73.07175182444027], + [510962.3422252839, 6651132.887736755, 68.21230191512484], + [510962.4377686233, 6651132.354640549, 68.74434824212484], + [510955.83672152465, 6651136.122623199, 73.11452706544026], + [510954.4749380199, 6651143.862722614, 66.10926455844026], + [510954.4749380199, 6651143.862722614, 66.23926455844025], + [510962.3320226727, 6651132.944663522, 68.63342334312483], + [510962.4177439483, 6651132.466370769, 69.22724926212486], + [510954.3693079373, 6651144.463102438, 66.10926455844026], + [510962.3143538417, 6651133.043249011, 69.05951247812484], + [510955.5287771513, 6651137.872916145, 72.50553190544025], + [510962.396917969, 6651132.5825719675, 69.58895524712484], + [510962.2888579548, 6651133.1855065515, 69.48441898212485], + [510962.37101000483, 6651132.727128746, 69.94671309312484], + [510954.4749376146, 6651143.862724918, 67.93806821844025], + [510962.34001696133, 6651132.900058372, 70.29716930812484], + [510962.2553822575, 6651133.37228846, 69.90138568412483], + [510954.4757252401, 6651143.858248216, 68.14188950244025], + [510954.3693079373, 6651144.463102438, 67.93806821744026], + [510954.4822652226, 6651143.821076291, 68.55846879044026], + [510955.2318456225, 6651139.560614333, 72.50553190544025], + [510962.3040266128, 6651133.100871096, 70.63691433512486], + [510962.2140150162, 6651133.603102241, 70.30333460112483], + [510954.4958977647, 6651143.743591704, 68.98279591044026], + [510955.1596618683, 6651139.970892055, 72.46778904644026], + [510954.3729398458, 6651144.442459412, 68.40365890444025], + [510962.2632206515, 6651133.328553145, 70.96258144512484], + [510954.51706413366, 6651143.623286384, 69.40910626144027], + [510955.2271370133, 6651139.587377106, 73.11452706544026], + [510955.0861355904, 6651140.388800407, 72.38911435344025], + [510962.16510335275, 6651133.876011085, 70.68321540312483], + [510954.38429730764, 6651144.377905917, 68.88092985644026], + [510954.5460213355, 6651143.458699561, 69.83091512044025], + [510955.01226566336, 6651140.808661992, 72.26696123144026], + [510955.14532875834, 6651140.052358526, 73.07175182444027], + [510962.21787369426, 6651133.581572256, 71.27095025312484], + [510954.58280427137, 6651143.249632864, 70.24126466344026], + [510954.939175743, 6651141.224090176, 72.09984647444026], + [510954.4039661029, 6651144.266112501, 69.36383087644026], + [510962.1238231672, 6651134.106339126, 70.94962171812485], + [510954.62720020174, 6651142.99729546, 70.63304435744027], + [510954.86807146255, 6651141.62823239, 71.88756866544026], + [510954.66522054514, 6651142.781195589, 70.91052621744025], + [510955.0619989766, 6651140.525987992, 72.98258717244026], + [510954.80018491624, 6651142.01408566, 71.63135554244026], + [510954.7069751263, 6651142.543871074, 71.17096689044025], + [510954.75210359547, 6651142.28737007, 71.41193653644025], + [510954.4244219616, 6651144.149845576, 69.72553686144026], + [510954.9991784255, 6651140.883047179, 72.88349167844027], + [510962.1683480363, 6651133.857906959, 71.55904860412484], + [510954.4498694878, 6651144.005207032, 70.08329470744026], + [510962.0789783129, 6651134.356556691, 71.19733145812484], + [510954.93666770565, 6651141.238345348, 72.75586891944027], + [510954.48031172116, 6651143.832179594, 70.43375092244025], + [510954.875032729, 6651141.5886659715, 72.59937762744026], + [510954.5156624472, 6651143.631253284, 70.77349594944026], + [510954.8148596318, 6651141.930677571, 72.41416872544028], + [510954.55574320245, 6651143.4034424545, 71.09916305944026], + [510962.1150842929, 6651134.155098786, 71.82424632912483], + [510954.75673870405, 6651142.261025059, 72.20091639044026], + [510954.60028425086, 6651143.150280228, 71.40753186744026], + [510954.70124687284, 6651142.576429299, 71.96082794344025], + [510954.6489297359, 6651142.873789223, 71.69563021844026], + [510962.01435568935, 6651134.717126833, 71.49477392812484], + [510962.05858841364, 6651134.470324727, 72.06433477612484], + [510961.94524082966, 6651135.102761977, 71.75098705112484], + [510961.99941586785, 6651134.800485467, 72.27758711112486], + [510961.8728500153, 6651135.506675729, 71.96326486012484], + [510961.9381540214, 6651135.142303725, 72.46279601312484], + [510961.7984376337, 6651135.92186907, 72.13037961712485], + [510961.87540384487, 6651135.492426311, 72.61928730512484], + [510961.72323113226, 6651136.341493303, 72.25253273912483], + [510961.81176207983, 6651135.84752363, 72.74691006412483], + [510961.64837449783, 6651136.75916541, 72.33120743212484], + [510961.7478048776, 6651136.204380968, 72.84600555812486], + [510961.5748846781, 6651137.1692111995, 72.36895029112483], + [510961.6629673583, 6651136.67774269, 72.93517021012485], + [510961.579678896, 6651137.142461253, 72.97794545112484], + [510960.1932557976, 6651144.878185154, 65.97268294412484], + [510960.1932557976, 6651144.878185154, 66.10268294412484], + [510960.08571448433, 6651145.47822558, 65.97268294412484], + [510961.266162694, 6651138.891764751, 72.36895029112483], + [510960.19325538503, 6651144.878187455, 67.80148660412483], + [510960.1940572614, 6651144.873713284, 68.00530788812485], + [510960.08571448433, 6651145.47822558, 67.80148660312486], + [510960.20071557583, 6651144.836562372, 68.42188717612486], + [510960.9638585989, 6651140.578508874, 72.36895029112483], + [510971.8227599998, 6651133.973851045, 65.74349841073101], + [510960.21459478, 6651144.759121588, 68.84621429612484], + [510960.8903687793, 6651140.988554664, 72.33120743212484], + [510960.0894121072, 6651145.457594223, 68.26707729012483], + [510971.7121088866, 6651134.573325796, 65.74349841073101], + [510960.2361441253, 6651144.638884278, 69.27252464712485], + [510960.959064794, 6651140.605256519, 72.97794545112484], + [510960.81551214476, 6651141.406226771, 72.25253273912483], + [510971.7121088866, 6651134.573325796, 65.87349841073102], + [510960.1009750667, 6651145.393077222, 68.74434824212484], + [510960.2656252678, 6651144.474390496, 69.69433350612485], + [510960.7403056434, 6651141.8258510055, 72.13037961712485], + [510960.8757763315, 6651141.069975081, 72.93517021012485], + [510960.30307374004, 6651144.265441985, 70.10468304912484], + [510960.6658932617, 6651142.241044347, 71.96326486012484], + [510960.1209997416, 6651145.281347002, 69.22724926212486], + [510960.34827295353, 6651144.013247228, 70.49646274312485], + [510960.5935024474, 6651142.644958097, 71.75098705112484], + [510960.38698122266, 6651143.797269521, 70.77394460312483], + [510960.79093881237, 6651141.543336804, 72.84600555812486], + [510960.5243875877, 6651143.030593241, 71.49477392812484], + [510960.42949129536, 6651143.560079167, 71.03438527612484], + [510960.47543630184, 6651143.303723163, 71.27535492212483], + [510960.1418257209, 6651145.165145803, 69.58895524712484], + [510960.7269816101, 6651141.900194142, 72.74691006412483], + [510960.16773368506, 6651145.020589026, 69.94671309312484], + [510960.663339845, 6651142.255291461, 72.61928730512484], + [510960.19872672856, 6651144.847659399, 70.29716930812484], + [510971.8227599998, 6651133.973851045, 67.57230206973101], + [510960.6005896685, 6651142.605414046, 72.46279601312484], + [510960.2347170771, 6651144.646846673, 70.63691433512486], + [510960.53932782204, 6651142.947232305, 72.27758711112486], + [510960.2755230384, 6651144.419164628, 70.96258144512484], + [510960.4801552763, 6651143.277393045, 72.06433477612484], + [510960.32086999563, 6651144.166145515, 71.27095025312484], + [510960.42365939694, 6651143.592618984, 71.82424632912483], + [510960.37039565353, 6651143.889810811, 71.55904860412484], + [510971.8189554519, 6651133.994462951, 68.037892756731], + [510971.7121088866, 6651134.573325796, 67.57230206973101], + [510973.640632066, 6651134.310340218, 65.69803378696157], + [510971.70875193266, 6651134.591512773, 67.983117381731], + [510971.80705812335, 6651134.058919131, 68.51516370873101], + [510973.5293776037, 6651134.90970329, 65.69803378696157], + [510971.69825428975, 6651134.648385874, 68.404238809731], + [510973.5293776037, 6651134.90970329, 65.82803378696157], + [510971.78645438957, 6651134.170544021, 68.99806472873101], + [510971.6800745247, 6651134.746878422, 68.83032794473101], + [510971.7650261801, 6651134.286635673, 69.35977071373101], + [510971.6538413666, 6651134.889001855, 69.255234448731], + [510971.7383690288, 6651134.431056174, 69.71752855973101], + [510973.640632066, 6651134.310340218, 67.52683744596158], + [510971.70647975145, 6651134.603822773, 70.06798477473102], + [510971.6193976439, 6651135.075607677, 69.672201150731], + [510973.63680677285, 6651134.330948285, 67.99242813296156], + [510973.5293776037, 6651134.90970329, 67.52683744596158], + [510971.6694486605, 6651134.804446187, 70.40772980173101], + [510973.5260023452, 6651134.927886878, 67.93765275796157], + [510971.5768341755, 6651135.306203864, 70.074150067731], + [510973.62484457163, 6651134.395392457, 68.46969908496158], + [510971.62746270286, 6651135.0319135925, 70.733396911731], + [510973.5154474616, 6651134.984749384, 68.35877418596156], + [510973.6041284916, 6651134.5069965515, 68.95260010496158], + [510971.52650812076, 6651135.57885543, 70.45403086973101], + [510971.5808044358, 6651135.284694177, 71.041765719731], + [510973.4971685675, 6651135.083223583, 68.78486332096156], + [510973.5825834401, 6651134.623066576, 69.31430608996158], + [510971.48403422546, 6651135.808966334, 70.720437184731], + [510971.52984663175, 6651135.560768371, 71.329864070731], + [510973.4707923675, 6651135.225320538, 69.20976982496158], + [510971.4378925809, 6651136.058948012, 70.96814692473102], + [510973.5557809349, 6651134.767460172, 69.67206393596157], + [510971.4750426469, 6651135.857680027, 71.595061795731], + [510973.5237177744, 6651134.940194585, 70.02252015096157], + [510973.436160833, 6651135.411891597, 69.62673652696157], + [510971.3714012484, 6651136.419178236, 71.26558939473101], + [510971.41691306175, 6651136.172608795, 71.835150242731], + [510973.48648476356, 6651135.140780623, 70.36226517796158], + [510973.3933652781, 6651135.642444826, 70.02868544396156], + [510971.3002877764, 6651136.804449832, 71.521802517731], + [510971.3560294081, 6651136.502458286, 72.04840257773101], + [510973.4442698683, 6651135.368205653, 70.68793228796157], + [510973.3427648097, 6651135.915045596, 70.40856624596157], + [510971.22580361826, 6651137.207982802, 71.734080326731], + [510971.2929960371, 6651136.843954301, 72.23361147973101], + [510973.3973571871, 6651135.620939145, 70.99630109596157], + [510973.3000593163, 6651136.145113632, 70.67497256096158], + [510971.14923943457, 6651137.622784729, 71.90119508373101], + [510971.2284312975, 6651137.193746817, 72.39010277173101], + [510973.3461215246, 6651135.896961908, 71.28439944696157], + [510973.2536660745, 6651136.39504874, 70.92268230096157], + [510971.0718581673, 6651138.042013371, 72.023348205731], + [510971.1629491871, 6651137.548509375, 72.51772553073101], + [510973.2910187092, 6651136.19381825, 71.54959717196157], + [510970.99483688414, 6651138.459291728, 72.10202289873101], + [510971.097142518, 6651137.905030296, 72.61682102473101], + [510973.1868121835, 6651136.7552118525, 71.22012477096158], + [510973.2325721599, 6651136.508688348, 71.78968561896157], + [510970.91922194045, 6651138.868950957, 72.139765757731], + [510979.0699909608, 6651135.326591749, 65.56030910294606], + [510971.00985173025, 6651138.377945767, 72.705985676731], + [510973.11531095003, 6651137.140411674, 71.47633789396157], + [510973.171356525, 6651136.838476388, 72.00293795396159], + [510969.49764014105, 6651146.5706574535, 65.74349841073101], + [510970.92415479396, 6651138.842226227, 72.748760917731], + [510978.95693450235, 6651135.925617528, 65.56030910294606], + [510969.49764014105, 6651146.5706574535, 65.87349841073102], + [510978.95693450235, 6651135.925617528, 65.69030910294606], + [510973.0404206509, 6651137.5438694665, 71.68861570296157], + [510973.107979451, 6651137.179908785, 72.18814685596158], + [510969.3869890279, 6651147.170132206, 65.74349841073101], + [510972.9634389844, 6651137.958594119, 71.85573045996156], + [510973.04306265817, 6651137.529636135, 72.34463814796158], + [510970.6015725631, 6651140.58988061, 72.139765757731], + [510972.88563577924, 6651138.37774466, 71.97788358196158], + [510979.0699909608, 6651135.326591749, 67.38911276194607], + [510972.97722349246, 6651137.884332602, 72.47226090696157], + [510972.8081945209, 6651138.794945278, 72.05655827496157], + [510972.9110579982, 6651138.240787105, 72.57135640096159], + [510979.06610370916, 6651135.347188219, 67.85470344894605], + [510969.4976397165, 6651146.570659755, 67.572302070731], + [510978.95693450235, 6651135.925617528, 67.38911276194607], + [510969.4984647809, 6651146.5661898, 67.776123354731], + [510972.7321672704, 6651139.204528188, 72.09430113396157], + [510972.82329123863, 6651138.713614472, 72.66052105296158], + [510978.9535045745, 6651135.943790884, 67.79992807394606], + [510979.05394775525, 6651135.411596125, 68.33197440094607], + [510969.3869890279, 6651147.170132206, 67.57230206973101], + [510969.5053156356, 6651146.529073913, 68.192702642731], + [510970.2905266624, 6651142.275034595, 72.139765757731], + [510971.3028339894, 6651146.904799883, 65.69803378696157], + [510972.73712702125, 6651139.1778084375, 72.70329629396157], + [510978.9427787328, 6651136.00062139, 68.22104950194606], + [510969.5195961883, 6651146.451706133, 68.61702976273101], + [510969.3907935758, 6651147.149520299, 68.037892756731], + [510971.3028339894, 6651146.904799883, 65.82803378696157], + [510970.2149117187, 6651142.684693824, 72.10202289873101], + [510979.0328961355, 6651135.523137413, 68.81487542094607], + [510969.54176868155, 6651146.331582173, 69.043340113731], + [510970.13789043564, 6651143.1019721795, 72.023348205731], + [510970.2855942337, 6651142.301757024, 72.748760917731], + [510969.40269090433, 6651147.08506412, 68.51516370873101], + [510971.1915795272, 6651147.504162954, 65.69803378696157], + [510978.9242037741, 6651136.099040172, 68.64713863694608], + [510969.57210233784, 6651146.167243464, 69.465148972731], + [510979.01100211736, 6651135.639142118, 69.17658140594607], + [510970.06050916837, 6651143.521200823, 71.90119508373101], + [510970.1998972974, 6651142.766037483, 72.705985676731], + [510969.61063371715, 6651145.958491934, 69.87549851573102], + [510969.98394498473, 6651143.93600275, 71.734080326731], + [510969.423294638, 6651146.973439231, 68.99806472873101], + [510972.4127858412, 6651140.925137239, 72.09430113396157], + [510969.657139968, 6651145.70653493, 70.267278209731], + [510969.90946082654, 6651144.339535721, 71.521802517731], + [510969.6969675741, 6651145.490760829, 70.544760069731], + [510978.897400357, 6651136.241057161, 69.07204514094606], + [510969.83834735455, 6651144.724807316, 71.26558939473101], + [510970.1126065097, 6651143.238952954, 72.61682102473101], + [510969.7407069216, 6651145.253794081, 70.805200742731], + [510969.4447228476, 6651146.857347578, 69.35977071373101], + [510978.98376549006, 6651135.783454456, 69.53433925194607], + [510969.78798053163, 6651144.99767975, 71.046170388731], + [510970.0467998406, 6651143.595473875, 72.51772553073101], + [510969.4713799989, 6651146.712927077, 69.71752855973101], + [510969.98131773015, 6651143.950236432, 72.39010277173101], + [510969.5032692763, 6651146.540160476, 70.06798477473102], + [510978.9511830004, 6651135.956091666, 69.88479546694606], + [510978.8622078931, 6651136.427523228, 69.48901184294606], + [510969.91675299057, 6651144.300028948, 72.23361147973101], + [510969.5403003671, 6651146.339537064, 70.40772980173101], + [510971.3028335625, 6651146.904802183, 67.52683744696157], + [510969.8537196195, 6651144.641524966, 72.04840257773101], + [510969.5822863248, 6651146.112069658, 70.733396911731], + [510969.7928359659, 6651144.971374456, 71.835150242731], + [510969.62894459174, 6651145.859289073, 71.041765719731], + [510969.7347063807, 6651145.286303224, 71.595061795731], + [510969.67990239593, 6651145.583214878, 71.329864070731], + [510971.30366312584, 6651146.900333062, 67.73065873096157], + [510978.91334692383, 6651136.156564822, 70.22454049394607], + [510978.8187191755, 6651136.657946712, 69.89096075994605], + [510971.1915795272, 6651147.504162954, 67.52683744596158], + [510971.3105513363, 6651146.863224088, 68.14723801896157], + [510972.10004389565, 6651142.609977284, 72.09430113396157], + [510978.870448271, 6651136.383861868, 70.55020760394606], + [510971.3249097568, 6651146.785870722, 68.57156513896157], + [510971.1954048202, 6651147.483554888, 67.99242813296156], + [510972.02401664515, 6651143.019560195, 72.05655827496157], + [510978.7672991279, 6651136.930394076, 70.27084156194606], + [510971.3472031503, 6651146.66576914, 68.99787548996159], + [510971.94657538686, 6651143.436760813, 71.97788358196158], + [510972.09508457186, 6651142.636694735, 72.70329629396157], + [510971.2073670216, 6651147.419110715, 68.46969908496158], + [510978.8227757418, 6651136.636453134, 70.85857641194606], + [510971.3777022074, 6651146.501461048, 69.41968434896158], + [510971.8687721816, 6651143.855911355, 71.85573045996156], + [510978.7239019306, 6651137.160332642, 70.53724787694605], + [510972.0089203545, 6651143.1008887, 72.66052105296158], + [510971.41644368746, 6651146.292748408, 69.83003389196158], + [510971.7917905152, 6651144.270636006, 71.68861570296157], + [510971.2280831015, 6651147.307506622, 68.95260010496158], + [510971.46320352366, 6651146.04083834, 70.22181358596158], + [510971.716900216, 6651144.6740938, 71.47633789396157], + [510978.7707102118, 6651136.9123205645, 71.14667476294606], + [510971.50324829837, 6651145.825104439, 70.49929544596156], + [510971.64539898257, 6651145.05929362, 71.22012477096158], + [510971.9211535949, 6651143.573716069, 72.57135640096159], + [510971.54722614406, 6651145.588181837, 70.75973611896157], + [510971.249628153, 6651147.191436598, 69.31430608996158], + [510971.5947575237, 6651145.33211522, 71.00070576496157], + [510978.67675725423, 6651137.410127097, 70.78495761694606], + [510971.85498810076, 6651143.9301705705, 72.47226090696157], + [510971.2764306582, 6651147.047043002, 69.67206393596157], + [510971.78914893494, 6651144.284867037, 72.34463814796158], + [510971.3084938187, 6651146.874308587, 70.02252015096157], + [510978.7147148922, 6651137.20900985, 71.41187248794606], + [510971.7242321422, 6651144.634594389, 72.18814685596158], + [510971.34572682955, 6651146.673722549, 70.36226517796158], + [510978.60882052616, 6651137.770087529, 71.08240008694607], + [510971.6608550681, 6651144.976026786, 72.00293795396159], + [510971.3879417248, 6651146.44629752, 70.68793228796157], + [510971.5996394333, 6651145.305814825, 71.78968561896157], + [510971.434854406, 6651146.193564028, 70.99630109596157], + [510971.5411928839, 6651145.620684923, 71.54959717196157], + [510971.48609006853, 6651145.917541265, 71.28439944696157], + [510978.65532168, 6651137.523702754, 71.65196093494606], + [510978.5361611822, 6651138.155070577, 71.33861320994606], + [510978.59311453137, 6651137.853305205, 71.86521326994608], + [510978.4600578797, 6651138.558301324, 71.55089101894606], + [510978.5287109344, 6651138.194545461, 72.05042217194607], + [510978.3818293359, 6651138.972792588, 71.71800577594607], + [510978.4627426798, 6651138.544076003, 72.20691346394608], + [510978.3027659467, 6651139.391707253, 71.84015889794605], + [510978.39583711256, 6651138.898572863, 72.33453622294607], + [510978.224070367, 6651139.808673091, 71.91883359094606], + [510978.32859993115, 6651139.254826769, 72.43363171694607], + [510978.1468116978, 6651140.218025507, 71.95657644994606], + [510978.2394116074, 6651139.727388053, 72.52279636894608], + [510976.69432740635, 6651147.913963863, 65.56030910294606], + [510978.15185178217, 6651140.191320795, 72.56557160994606], + [510976.69432740635, 6651147.913963863, 65.69030910294606], + [510976.5812709479, 6651148.512989643, 65.56030910294606], + [510977.82225722546, 6651141.937666283, 71.95657644994606], + [510976.69432697253, 6651147.913966162, 67.38911276294606], + [510976.69516997243, 6651147.909499556, 67.59293404694606], + [510976.5812709479, 6651148.512989643, 67.38911276194607], + [510976.7021697517, 6651147.872411465, 68.00951333494606], + [510977.50444977684, 6651143.621558183, 71.95657644994606], + [510976.7167607365, 6651147.7951016305, 68.43384045494606], + [510976.58515819954, 6651148.492393172, 67.85470344894605], + [510977.42719110777, 6651144.030910599, 71.91883359094606], + [510976.7394152177, 6651147.675067636, 68.86015080594608], + [510977.348495528, 6651144.447876438, 71.84015889794605], + [510977.49941012653, 6651143.648260597, 72.56557160994606], + [510976.59731415333, 6651148.427985267, 68.33197440094607], + [510976.7704082701, 6651147.510852007, 69.28195966494606], + [510977.26943213877, 6651144.866791102, 71.71800577594607], + [510977.4118503014, 6651144.112193339, 72.52279636894608], + [510976.8097772486, 6651147.302256822, 69.69230920794607], + [510976.6183657731, 6651148.316443979, 68.81487542094607], + [510977.191203595, 6651145.281282366, 71.55089101894606], + [510976.8572944571, 6651147.050488518, 70.08408890194607], + [510977.11510029243, 6651145.684513113, 71.33861320994606], + [510976.8979878398, 6651146.8348760195, 70.36157076194606], + [510977.0424409485, 6651146.069496163, 71.08240008694607], + [510976.6402597913, 6651148.200439272, 69.17658140594607], + [510976.9426779977, 6651146.598086746, 70.62201143494606], + [510977.3226619775, 6651144.584754623, 72.43363171694607], + [510976.99097924645, 6651146.342164231, 70.86298108094606], + [510976.6674964185, 6651148.056126935, 69.53433925194607], + [510977.25542479614, 6651144.941008529, 72.33453622294607], + [510977.1885192289, 6651145.295505389, 72.20691346394608], + [510976.7000789083, 6651147.883489726, 69.88479546694606], + [510977.1225509743, 6651145.64503593, 72.05042217194607], + [510976.7379149848, 6651147.683016569, 70.22454049394607], + [510977.05814737733, 6651145.986276187, 71.86521326994608], + [510976.78081363766, 6651147.455719523, 70.55020760394606], + [510976.9959402286, 6651146.315878637, 71.65196093494606], + [510976.8284861669, 6651147.203128258, 70.85857641194606], + [510976.93654701643, 6651146.63057154, 71.41187248794606], + [510976.880551697, 6651146.927260826, 71.14667476294606], + [510990.5572465645, 6651137.532530463, 65.25932373606133], + [510990.44037750276, 6651138.130824095, 65.25932373606133], + [510990.44037750276, 6651138.130824095, 65.38932373606133], + [510991.7160832611, 6651137.75928124, 65.22823515455318], + [510990.5572465645, 6651137.532530463, 67.08812739506133], + [510991.5988295832, 6651138.357499615, 65.22823515455318], + [510990.55322822306, 6651137.5531017585, 67.55371808206134], + [510990.44037750276, 6651138.130824095, 67.08812739506133], + [510991.5988295832, 6651138.357499615, 65.35823515455317], + [510990.4368319075, 6651138.148975237, 67.49894270706135], + [510990.5406623339, 6651137.617430944, 68.03098903406134], + [510990.4257443581, 6651138.205736283, 67.92006413506132], + [510990.5189007903, 6651137.728835903, 68.51389005406133], + [510991.7160832611, 6651137.75928124, 67.05703881355318], + [510990.40654299606, 6651138.304034777, 68.34615327006134], + [510990.4962684401, 6651137.844698825, 68.87559603906134], + [510991.7120516954, 6651137.77984995, 67.52262950055317], + [510991.5988295832, 6651138.357499615, 67.05703881355318], + [510990.3788356872, 6651138.445878189, 68.77105977406133], + [510990.468113312, 6651137.988834779, 69.23335388506133], + [510991.59527231933, 6651138.375648474, 67.46785412555317], + [510991.69944445184, 6651137.844171043, 67.99990045255318], + [510990.4344320428, 6651138.161260985, 69.58381010006133], + [510990.3424564278, 6651138.632116351, 69.18802647606132], + [510991.5841482809, 6651138.43240238, 67.88897555355317], + [510991.67761129106, 6651137.955561988, 68.48280147255318], + [510990.3953200202, 6651138.361489118, 69.92355512706133], + [510990.29750114004, 6651138.862258202, 69.58997539306134], + [510991.5648837271, 6651138.530688509, 68.31506468855319], + [510991.6549044578, 6651138.071410335, 68.84450745755318], + [510990.350974696, 6651138.588508354, 70.24922223706135], + [510991.53708523355, 6651138.672514077, 68.73997119255317], + [510991.626656671, 6651138.215528159, 69.20226530355318], + [510990.24434705405, 6651139.134372573, 69.96985619506133], + [510990.301694506, 6651138.840790896, 70.55759104506133], + [510990.199486373, 6651139.3640301, 70.23626251006132], + [510991.5928645568, 6651138.387932676, 69.55272151855317], + [510991.50058624987, 6651138.858728814, 69.15693789455317], + [510990.24787316984, 6651139.116321152, 70.84568939606133], + [510990.15075183654, 6651139.61351925, 70.48397225006133], + [510991.5536238165, 6651138.588135622, 69.89246654555318], + [510991.45548301435, 6651139.088841717, 69.55888681155317], + [510990.18998952, 6651139.4126478145, 71.11088712106134], + [510991.5091325518, 6651138.815126302, 70.21813365555317], + [510990.08052407793, 6651139.973039726, 70.78141472006135], + [510995.6581277741, 6651138.536419273, 65.12148315381185], + [510991.40215399803, 6651139.360921859, 69.93876761355317], + [510990.1285933904, 6651139.726956091, 71.35097556806134], + [510991.4596901806, 6651139.067377109, 70.52650246355317], + [510995.53956573736, 6651139.134379716, 65.12148315381185], + [510990.00541444274, 6651140.357552237, 71.03762784306134], + [510991.35714568046, 6651139.590550498, 70.20517392855317], + [510995.53956573736, 6651139.134379716, 65.25148315381185], + [510990.06428842974, 6651140.056155692, 71.56422790306134], + [510991.40569171833, 6651139.342872708, 70.81460081455317], + [510991.30825075856, 6651139.840008264, 70.45288366855317], + [510989.92674470827, 6651140.760290142, 71.24990565206133], + [510989.99771295016, 6651140.396978874, 71.74943680506134], + [510991.3476175734, 6651139.639162097, 71.07979853955317], + [510989.8458780631, 6651141.174274803, 71.41702040906135], + [510991.23779188044, 6651140.199483517, 70.75032613855318], + [510989.92952004797, 6651140.746082208, 71.90592809706133], + [510995.6581277741, 6651138.536419273, 66.95028681281185], + [510991.286019389, 6651139.953430836, 71.31988698655317], + [510989.764148419, 6651141.592677458, 71.53917353106132], + [510989.86035822396, 6651141.100145792, 72.03355085606132], + [510995.65405122266, 6651138.556979113, 67.41587749981184], + [510991.1624350594, 6651140.583947662, 71.00653926155317], + [510995.53956573736, 6651139.134379716, 66.95028681281185], + [510991.2215028007, 6651140.282589028, 71.5331393215532], + [510989.682798988, 6651142.009133668, 71.61784822406133], + [510989.7908536029, 6651141.455964274, 72.13264635006134], + [510995.5359687803, 6651139.152520751, 67.36110212481185], + [510995.64130330295, 6651138.621272473, 67.89314845181185], + [510991.08350642276, 6651140.986634906, 71.21881707055317], + [510989.60293492454, 6651142.417985761, 71.65559108306132], + [510991.1547082211, 6651140.623369339, 71.71834822355318], + [510989.69865758106, 6651141.9279479785, 72.22181100206133], + [510995.52472061577, 6651139.209250186, 67.78222355281184], + [510995.6192265198, 6651138.732615391, 68.37604947181185], + [510991.00237364526, 6651141.400567493, 71.38593182755318], + [510988.1014685009, 6651150.104517902, 65.25932373606133], + [510991.08629089594, 6651140.97242876, 71.87483951555319], + [510988.1014685009, 6651150.104517902, 65.38932373606133], + [510989.6081449755, 6651142.391313687, 72.26458624306133], + [510995.5052411012, 6651139.307493936, 68.20831268781185], + [510995.5962663155, 6651138.848413788, 68.73775545681185], + [510990.9203750289, 6651141.818917517, 71.50808494955317], + [510991.01690146036, 6651141.326447805, 72.00246227455318], + [510987.9845994391, 6651150.702811534, 65.25932373606133], + [510995.4771324219, 6651139.449258356, 68.63321919181186], + [510995.5677033298, 6651138.992469475, 69.09551330281185], + [510990.83875787683, 6651142.235321341, 71.58675964255318], + [510990.94716809964, 6651141.68222153, 72.10155776855318], + [510989.26743550063, 6651144.135524738, 71.65559108306132], + [510990.7586309806, 6651142.644122006, 71.62450250155317], + [510995.533534151, 6651139.164799656, 69.44596951781185], + [510995.4402261694, 6651139.635392802, 69.05018589381184], + [510990.8546686605, 6651142.154145865, 72.19072242055319], + [510989.25222322944, 6651150.329687274, 65.22823515455318], + [510988.1014680524, 6651150.104520198, 67.08812739606134], + [510989.25222322944, 6651150.329687274, 65.35823515455317], + [510990.763858178, 6651142.617453287, 72.23349766155317], + [510995.4938555483, 6651139.364916282, 69.78571454481185], + [510988.1023394807, 6651150.100059051, 67.29194868006132], + [510995.39461965574, 6651139.865406488, 69.45213481081184], + [510989.13496955147, 6651150.927905647, 65.22823515455318], + [510987.9845994391, 6651150.702811534, 67.08812739506133], + [510988.1095753136, 6651150.06301629, 67.70852796806133], + [510995.4488678341, 6651139.591809091, 70.11138165481185], + [510988.93891063053, 6651145.817358532, 71.65559108306132], + [510995.34069557517, 6651140.13736932, 69.83201561281184], + [510988.1246583503, 6651149.985800946, 68.13285508806135], + [510987.9886177805, 6651150.6822402375, 67.55371808206134], + [510990.4220274278, 6651144.361444937, 71.62450250155317], + [510988.859046567, 6651146.226210627, 71.61784822406133], + [510995.3988737671, 6651139.843951136, 70.41975046281185], + [510988.14807680855, 6651149.865913662, 68.55916543906133], + [510995.29518503847, 6651140.36689895, 70.09842192781186], + [510988.77769713604, 6651146.642666837, 71.53917353106132], + [510988.93370102806, 6651145.844028312, 72.26458624306133], + [510988.00118366966, 6651150.617911053, 68.03098903406134], + [510988.18011503987, 6651149.701898743, 68.98097429806133], + [510988.69596749195, 6651147.061069489, 71.41702040906135], + [510995.3442727705, 6651140.11932795, 70.70784881381185], + [510989.25222277956, 6651150.329689568, 67.05703881455317], + [510988.8431884226, 6651146.307394018, 72.22181100206133], + [510988.2208116584, 6651149.493558507, 69.39132384106134], + [510995.2457445295, 6651140.61624916, 70.34613166781185], + [510988.02294521325, 6651150.506506095, 68.51389005406133], + [510988.6151008467, 6651147.47505415, 71.24990565206133], + [510988.26993129, 6651149.242097922, 69.78310353506133], + [510989.2530970758, 6651150.325228983, 67.26086009855317], + [510988.5364311122, 6651147.877792056, 71.03762784306134], + [510988.31199697574, 6651149.026748953, 70.06058539506134], + [510988.0455775635, 6651150.390643174, 68.87559603906134], + [510988.4613214771, 6651148.262304568, 70.78141472006135], + [510988.35819422, 6651148.790249091, 70.32102606806134], + [510988.4081243318, 6651148.5346393725, 70.56199571406133], + [510988.7509924007, 6651146.779377723, 72.13264635006134], + [510995.2855506133, 6651140.41548959, 70.97304653881184], + [510989.13496955147, 6651150.927905647, 67.05703881355318], + [510988.0737326916, 6651150.246507218, 69.23335388506133], + [510988.68148777966, 6651147.135196205, 72.03355085606132], + [510989.2603567217, 6651150.288190882, 67.67743938655317], + [510995.17449944577, 6651140.975569419, 70.64357413781185], + [510988.1074139608, 6651150.074081012, 69.58381010006133], + [510988.6123259557, 6651147.489259789, 71.90592809706133], + [510990.09242138197, 6651146.043067177, 71.62450250155317], + [510988.14652598335, 6651149.873852879, 69.92355512706133], + [510988.5441330535, 6651147.838363124, 71.74943680506134], + [510989.2754893967, 6651150.210985251, 68.10176650655318], + [510989.13900111726, 6651150.907336939, 67.52262950055317], + [510995.2232650942, 6651140.729622828, 71.21313498581185], + [510988.19087130757, 6651149.646833643, 70.24922223706135], + [510988.4775575738, 6651148.179186306, 71.56422790306134], + [510990.01229448576, 6651146.451867842, 71.58675964255318], + [510988.2401514976, 6651149.394551103, 70.55759104506133], + [510988.4132526133, 6651148.508385905, 71.35097556806134], + [510988.29397283384, 6651149.119020846, 70.84568939606133], + [510988.35185648367, 6651148.822694182, 71.11088712106134], + [510995.09830176615, 6651141.359867796, 70.89978726081185], + [510989.2989849252, 6651150.091113046, 68.52807685755319], + [510989.9306773337, 6651146.868271667, 71.50808494955317], + [510990.0871946348, 6651146.069733602, 72.23349766155317], + [510989.1516083608, 6651150.843015845, 67.99990045255318], + [510995.1580286066, 6651141.058639097, 71.42638732081187], + [510989.33112859423, 6651149.927118758, 68.94988571655317], + [510989.8486787173, 6651147.286621691, 71.38593182755318], + [510989.3719591455, 6651149.71880473, 69.36023525955318], + [510989.99638415215, 6651146.533041022, 72.19072242055319], + [510989.1734415216, 6651150.7316249, 68.48280147255318], + [510995.0184924154, 6651141.762381416, 71.11206506981185], + [510989.76754593983, 6651147.700554278, 71.21881707055317], + [510989.4212404298, 6651149.467375776, 69.75201495355319], + [510989.6886173032, 6651148.103241523, 71.00653926155317], + [510995.090488709, 6651141.399272475, 71.61159622281185], + [510989.4634445538, 6651149.252053895, 70.02949681355317], + [510989.1961483549, 6651150.615776552, 68.84450745755318], + [510989.61326048215, 6651148.487705667, 70.75032613855318], + [510989.5097938332, 6651149.0155837815, 70.28993748655317], + [510989.55988826504, 6651148.760006216, 70.53090713255317], + [510989.903884713, 6651147.0049653575, 72.10155776855318], + [510989.22439614165, 6651150.471658727, 69.20226530355318], + [510989.83415135223, 6651147.360739081, 72.00246227455318], + [510994.93645432906, 6651142.176135529, 71.27917982681186], + [510995.0213079587, 6651141.748181393, 71.76808751481185], + [510989.25818825583, 6651150.299254212, 69.55272151855317], + [510989.76476191665, 6651147.714758128, 71.87483951555319], + [510989.2974289962, 6651150.099051264, 69.89246654555318], + [510989.69634459156, 6651148.0638175495, 71.71834822355318], + [510989.3419202609, 6651149.872060586, 70.21813365555317], + [510989.62955001194, 6651148.40459786, 71.5331393215532], + [510994.85354074254, 6651142.594305174, 71.40133294881184], + [510989.3913626321, 6651149.619809779, 70.52650246355317], + [510989.56503342366, 6651148.7337560505, 71.31988698655317], + [510989.4453610943, 6651149.344314179, 70.81460081455317], + [510989.5034352393, 6651149.04802479, 71.07979853955317], + [510994.9511442508, 6651142.102047801, 71.89571027381184], + [510994.77101287694, 6651143.01052946, 71.48000764181185], + [510994.88063278, 6651142.457668127, 71.99480576781185], + [510994.68999189587, 6651143.419153865, 71.51775050081184], + [510994.7871011988, 6651142.929388984, 72.08397041981186], + [510993.1667751042, 6651151.101405384, 65.12148315381185], + [510993.1667751042, 6651151.101405384, 65.25148315381185], + [510994.69527742016, 6651143.3924966445, 72.12674566081185], + [510993.04821306746, 6651151.699365826, 65.12148315381185], + [510994.3496323994, 6651145.135736346, 71.51775050081184], + [510993.16677464935, 6651151.101407679, 66.95028681381184], + [510993.16765870125, 6651151.096949016, 67.15410809781184], + [510993.04821306746, 6651151.699365826, 66.95028681281185], + [510993.17499935295, 6651151.059926884, 67.57068738581185], + [510994.01634849055, 6651146.816633529, 71.51775050081184], + [510993.1903008838, 6651150.982754541, 67.99501450581185], + [510993.0522896189, 6651151.6788059855, 67.41587749981184], + [510993.93532750953, 6651147.225257933, 71.48000764181185], + [510993.2140585838, 6651150.862934021, 68.42132485681186], + [510993.85279964394, 6651147.641482219, 71.40133294881184], + [510993.06503753865, 6651151.614512626, 67.89314845181185], + [510994.0110634214, 6651146.843288455, 72.12674566081185], + [510993.2465609235, 6651150.699010443, 68.84313371581186], + [510993.7698860573, 6651148.059651865, 71.27917982681186], + [510993.28784707683, 6651150.490786231, 69.25348325881185], + [510993.91923964274, 6651147.306396114, 72.08397041981186], + [510993.0871143217, 6651151.503169709, 68.37604947181185], + [510993.6878479711, 6651148.473405978, 71.11206506981185], + [510993.3376782594, 6651150.239465684, 69.64526295281186], + [510993.6080386203, 6651148.875919599, 70.89978726081185], + [510993.38035331224, 6651150.024236643, 69.92274481281184], + [510993.11007452605, 6651151.387371312, 68.73775545681185], + [510993.5318409407, 6651149.260217975, 70.64357413781185], + [510993.4272197735, 6651149.787868488, 70.18318548581185], + [510993.47787317715, 6651149.532401118, 70.42415513181184], + [510993.82570806146, 6651147.778116973, 71.99480576781185], + [510993.13863751176, 6651151.243315625, 69.09551330281185], + [510993.75519659073, 6651148.133737299, 71.89571027381184], + [510993.1728066905, 6651151.070985444, 69.44596951781185], + [510993.6850328828, 6651148.487603704, 71.76808751481185], + [510993.2124852932, 6651150.870868818, 69.78571454481185], + [510993.61585213256, 6651148.836512624, 71.61159622281185], + [510993.2574730075, 6651150.6439760085, 70.11138165481185], + [510993.5483122349, 6651149.177146002, 71.42638732081187], + [510993.30746707454, 6651150.391833963, 70.41975046281185], + [510993.4830757473, 6651149.506162272, 71.21313498581185], + [510993.36206807103, 6651150.116457149, 70.70784881381185], + [510993.4207902283, 6651149.820295509, 70.97304653881184], + [511007.4429070083, 6651140.913185345, 64.79313440574904], + [511007.3204336206, 6651141.510356942, 64.79313440574904], + [511007.3204336206, 6651141.510356942, 64.92313440574902], + [511007.4429070083, 6651140.913185345, 66.62193806474903], + [511007.4386959718, 6651140.933718062, 67.08752875174902], + [511007.3204336206, 6651141.510356942, 66.62193806474903], + [511007.31671800016, 6651141.528474045, 67.03275337674903], + [511007.4255274994, 6651140.997926604, 67.56479970374905], + [511007.30509875977, 6651141.585128642, 67.45387480474903], + [511007.4027224051, 6651141.109122635, 68.04770072374903], + [511007.2849766177, 6651141.683242787, 67.87996393974902], + [511007.3790047457, 6651141.224768269, 68.40940670874903], + [511007.25594063563, 6651141.824820186, 68.30487044374902], + [511007.3494994697, 6651141.368633913, 68.76716455474903], + [511007.3142030527, 6651141.540736752, 69.11762076974902], + [511007.21781684924, 6651142.010709079, 68.72183714574903], + [511007.2732154565, 6651141.740589378, 69.45736579674903], + [511007.17070578074, 6651142.240419325, 69.12378606274902], + [511007.22674360155, 6651141.967182864, 69.78303290674903], + [511007.11500274955, 6651142.512023376, 69.50366686474902], + [511011.56646255543, 6651141.763807931, 64.67497358985594], + [511007.1751002348, 6651142.218992277, 70.09140171474903], + [511007.06799082446, 6651142.741250206, 69.77007317974902], + [511011.44262056565, 6651142.360697208, 64.67497358985594], + [511011.44262056565, 6651142.360697208, 64.80497358985593], + [511007.1186979563, 6651142.494005808, 70.37950006574903], + [511007.0169192775, 6651142.990271466, 70.01778291974902], + [511012.21603594173, 6651141.898703137, 64.65620509671923], + [511007.05803856044, 6651142.789776742, 70.64469779074902], + [511006.9433238248, 6651143.349117701, 70.31522538974903], + [511012.09197835956, 6651142.495547644, 64.65620509671923], + [511012.09197835956, 6651142.495547644, 64.78620509671923], + [511006.99369824765, 6651143.103495568, 70.88478623774903], + [511011.56646255543, 6651141.763807931, 66.50377724885594], + [511006.8646123905, 6651143.7329091, 70.57143851274903], + [511006.9263096141, 6651143.432077792, 71.09803857274903], + [511011.5622044619, 6651141.784330942, 66.96936793585593], + [511011.44262056565, 6651142.360697208, 66.50377724885594], + [511006.7821701364, 6651144.134891714, 70.78371632174904], + [511006.85654158145, 6651143.7722617965, 71.28324747474905], + [511011.4388634244, 6651142.378805746, 66.91459256085594], + [511012.21603594173, 6651141.898703137, 66.48500875571924], + [511011.54888883594, 6651141.848509127, 67.44663888785594], + [511006.69742562115, 6651144.548099992, 70.95083107874902], + [511006.78507856437, 6651144.120710424, 71.43973876674903], + [511011.42711434263, 6651142.435433558, 67.33571398885593], + [511012.21177043545, 6651141.919224608, 66.95059944271922], + [511012.09197835956, 6651142.495547644, 66.48500875571924], + [511011.5258289018, 6651141.959652589, 67.92953990785594], + [511006.6117767228, 6651144.965717978, 71.07298420074903], + [511006.7126001621, 6651144.474110001, 71.56736152574902], + [511011.40676734183, 6651142.533501318, 67.76180312385594], + [511012.0882146775, 6651142.5136548225, 66.89582406771923], + [511012.19843162876, 6651141.983397981, 67.42787039471925], + [511011.501846205, 6651142.075243549, 68.29124589285595], + [511006.5265262703, 6651145.381393168, 71.15165889374903], + [511006.63976252417, 6651144.829261185, 71.66645701974903], + [511012.0764451422, 6651142.5702783875, 67.31694549571924], + [511011.3774068917, 6651142.675011787, 68.18670962785593], + [511011.4720112167, 6651142.21904118, 68.64900373885595], + [511006.44283241435, 6651145.789478505, 71.18940175274902], + [511012.17533155036, 6651142.094533105, 67.91077141471924], + [511006.5431453445, 6651145.300359735, 71.75562167174903], + [511004.8693648376, 6651153.461595396, 64.79313440574904], + [511012.05606272, 6651142.668338792, 67.74303463071922], + [511004.8693648376, 6651153.461595396, 64.92313440574902], + [511011.43632037326, 6651142.3910626555, 68.99945995385593], + [511012.1513071028, 6651142.210115396, 68.27247739971924], + [511011.33885708393, 6651142.860812798, 68.60367632985593], + [511006.4482923077, 6651145.762856451, 71.79839691274903], + [511004.74689144985, 6651154.058766993, 64.79313440574904], + [511012.02665115724, 6651142.809838645, 68.16794113471923], + [511012.12142017577, 6651142.35390224, 68.63023524571923], + [511011.39487475343, 6651142.590820799, 69.33920498085594], + [511011.2912195638, 6651143.090414445, 69.00562524685593], + [511012.08566719934, 6651142.525910812, 68.98069146071923], + [511011.98803423933, 6651142.995625719, 68.58490783671924], + [511006.09124448866, 6651147.503796426, 71.18940175274902], + [511011.34788358986, 6651142.81730716, 69.66487209085594], + [511011.23489406856, 6651143.361890092, 69.38550604885593], + [511012.0441494281, 6651142.725653973, 69.32043648771923], + [511011.2956631246, 6651143.068997527, 69.97324089885595], + [511011.94031378865, 6651143.225210145, 68.98685675371922], + [511004.8693643676, 6651153.461597687, 66.62193806574902], + [511011.18735679984, 6651143.5910085505, 69.65191236385593], + [511004.8702775843, 6651153.457144906, 66.82575934974902], + [511011.9970764592, 6651142.952123346, 69.64610359771923], + [511011.23863056814, 6651143.343881041, 70.26133924985594], + [511011.13571454416, 6651143.839912082, 69.89962210385593], + [511004.74689144985, 6651154.058766993, 66.62193806474903], + [511011.8838902381, 6651143.496665428, 69.36673755571923], + [511004.87786040345, 6651153.420171615, 67.24233863774903], + [511005.74696557363, 6651149.182476124, 71.18940175274902], + [511011.94476508506, 6651143.203794833, 69.95447240571923], + [511011.1772933223, 6651143.639512146, 70.52653697485593], + [511004.89366673044, 6651153.34310108, 67.66666575774903], + [511004.75110248633, 6651154.038234276, 67.08752875174902], + [511011.83627021336, 6651143.725766703, 69.63314387071922], + [511011.06129668525, 6651144.198588668, 70.19706457385594], + [511005.66327171767, 6651149.590561462, 71.15165889374903], + [511004.91820819484, 6651153.22343863, 68.09297610874903], + [511004.7642709587, 6651153.974025734, 67.56479970374905], + [511011.8876332425, 6651143.478657731, 70.24257075671923], + [511005.57802126516, 6651150.006236652, 71.07298420074903], + [511011.11223402654, 6651143.953082658, 70.76662542185593], + [511005.74150615046, 6651149.209095887, 71.79839691274903], + [511011.78453805536, 6651143.974651565, 69.88085361071923], + [511004.9517827839, 6651153.059731303, 68.51478496774902], + [511005.49237236683, 6651150.423854638, 70.95083107874902], + [511010.9817056751, 6651144.582198625, 70.45327769685593], + [511004.99443096365, 6651152.851781787, 68.92513451074903], + [511004.787076053, 6651153.862829702, 68.04770072374903], + [511005.6466531136, 6651149.6715926025, 71.75562167174903], + [511005.4076278515, 6651150.837062916, 70.78371632174904], + [511011.82618921663, 6651143.77426666, 70.50776848171922], + [511005.0459060724, 6651152.600792789, 69.31691420474903], + [511011.04409234604, 6651144.281509538, 70.97987775685594], + [511005.32518559747, 6651151.239045531, 70.57143851274903], + [511005.08998897136, 6651152.385847684, 69.59439606474902], + [511004.81079371244, 6651153.747184069, 68.40940670874903], + [511011.70999064477, 6651144.333301246, 70.17829608071924], + [511005.2464741632, 6651151.622836931, 70.31522538974903], + [511005.1384015531, 6651152.149791351, 69.85483673774903], + [511005.190726008, 6651151.894661001, 70.09580638374902], + [511005.5500359339, 6651150.142691153, 71.66645701974903], + [511010.89834215445, 6651144.983991197, 70.66555550585593], + [511004.84029898845, 6651153.603318425, 68.76716455474903], + [511005.4771982961, 6651150.497842337, 71.56736152574902], + [511010.9735446772, 6651144.621532718, 71.16508665885596], + [511011.7610166613, 6651144.087813651, 70.74785692871923], + [511004.8755954053, 6651153.431215585, 69.11762076974902], + [511005.40471989376, 6651150.851241913, 71.43973876674903], + [511004.91658300156, 6651153.231362958, 69.45736579674903], + [511011.6302610773, 6651144.716882431, 70.43450920371923], + [511005.3332568767, 6651151.199690541, 71.28324747474905], + [511004.9630548565, 6651153.004769472, 69.78303290674903], + [511010.81265064556, 6651145.397004127, 70.83267026285594], + [511005.2634888439, 6651151.539874546, 71.09803857274903], + [511005.0146982233, 6651152.752960061, 70.09140171474903], + [511005.1961002104, 6651151.868456769, 70.88478623774903], + [511010.9012830832, 6651144.969816613, 71.32157795085594], + [511005.07110050175, 6651152.47794653, 70.37950006574903], + [511005.13175989775, 6651152.182175594, 70.64469779074902], + [511011.6927563552, 6651144.416215898, 70.96110926371924], + [511011.5467524319, 6651145.118644866, 70.64678701271924], + [511010.72604464745, 6651145.814424677, 70.95482338485594], + [511010.8279947572, 6651145.323049115, 71.44920070985593], + [511011.6220858723, 6651144.756213572, 71.14631816571925], + [511010.6398415475, 6651146.229903353, 71.03349807785594], + [511010.75434318144, 6651145.678032395, 71.54829620385594], + [511011.4609117454, 6651145.531626815, 70.81390176971922], + [511011.54969848035, 6651145.104471343, 71.30280945771923], + [511010.5552124388, 6651146.637795762, 71.07124093685593], + [511010.65664633474, 6651146.1489082305, 71.63746085585593], + [511011.37415497773, 6651145.949016056, 70.93605489171924], + [511011.4762825692, 6651145.457677349, 71.43043221671923], + [511008.964161851, 6651154.306285562, 64.67497358985594], + [511008.964161851, 6651154.306285562, 64.80497358985593], + [511010.5607333447, 6651146.611186294, 71.68023609685595], + [511011.2878018097, 6651146.364463567, 71.01472958471923], + [511011.4025027757, 6651145.812634004, 71.52952771071924], + [511008.84031986113, 6651154.903174839, 64.67497358985594], + [511011.203025373, 6651146.772325381, 71.05247244371922], + [511011.3046358519, 6651146.283474518, 71.61869236271923], + [511009.60920497734, 6651154.440239982, 64.65620509671923], + [511009.60920497734, 6651154.440239982, 64.78620509671923], + [511010.1996956273, 6651148.351303216, 71.07124093685593], + [511011.20855589, 6651146.745717907, 71.66146760371923], + [511009.4851473952, 6651155.037084486, 64.65620509671923], + [511008.9641613757, 6651154.306287853, 66.50377724985593], + [511008.9650847973, 6651154.301837178, 66.70759853385593], + [511010.8468896539, 6651148.485704308, 71.05247244371922], + [511008.84031986113, 6651154.903174839, 66.50377724885594], + [511008.9727523522, 6651154.264881366, 67.12417782185594], + [511009.8515695024, 6651150.0291893, 71.07124093685593], + [511008.9887353098, 6651154.187847268, 67.54850494185594], + [511008.8445779547, 6651154.88265183, 66.96936793585593], + [511009.6092045014, 6651154.440242271, 66.48500875671922], + [511009.76694039366, 6651150.437081708, 71.03349807785594], + [511009.61012953054, 6651154.435791931, 66.68883004071922], + [511009.0135510175, 6651154.0682413895, 67.97481529285594], + [511008.85789358075, 6651154.818473643, 67.44663888785594], + [511009.68073729385, 6651150.852560385, 70.95482338485594], + [511009.84604907193, 6651150.055796476, 71.68023609685595], + [511009.4851473952, 6651155.037084486, 66.48500875571924], + [511009.04750079213, 6651153.904611457, 68.39662415185593], + [511009.6178104335, 6651154.398838891, 67.10540932871923], + [511009.5941312957, 6651151.269980936, 70.83267026285594], + [511009.090625552, 6651153.696760253, 68.80697369485594], + [511008.8809535148, 6651154.70733018, 67.92953990785594], + [511010.4981574877, 6651150.163464535, 71.05247244371922], + [511009.7501360818, 6651150.518074541, 71.63746085585593], + [511009.50843978673, 6651151.682993863, 70.66555550585593], + [511009.63382121536, 6651154.321810571, 67.52973644871923], + [511009.14267587924, 6651153.445889912, 69.19875338885593], + [511009.4894129014, 6651155.016563016, 66.95059944271922], + [511009.4250762661, 6651152.084786436, 70.45327769685593], + [511009.18725139095, 6651153.231046424, 69.47623524885593], + [511008.9049362116, 6651154.59173922, 68.29124589285595], + [511009.2362049682, 6651152.995101691, 69.73667592185593], + [511009.34548525605, 6651152.468396394, 70.19706457385594], + [511009.2891141325, 6651152.740091956, 69.97764556785593], + [511010.413381051, 6651150.571326349, 71.01472958471923], + [511009.65243923524, 6651150.988950375, 71.54829620385594], + [511009.6586801239, 6651154.202213665, 67.95604679971923], + [511008.93477119994, 6651154.44794159, 68.64900373885595], + [511009.5787876594, 6651151.343933655, 71.44920070985593], + [511009.50275170815, 6651154.952389644, 67.42787039471925], + [511010.327027883, 6651150.986773862, 70.93605489171924], + [511010.4926274468, 6651150.190069717, 71.66146760371923], + [511008.9704620434, 6651154.275920116, 68.99945995385593], + [511009.6926890006, 6651154.038596005, 68.37785565871923], + [511009.5054993335, 6651151.697166157, 71.32157795085594], + [511009.0119076632, 6651154.07616197, 69.33920498085594], + [511010.2402711152, 6651151.404163103, 70.81390176971922], + [511009.4332377394, 6651152.045450052, 71.16508665885596], + [511009.735888835, 6651153.830760391, 68.78820520171924], + [511009.52585178654, 6651154.841254518, 67.91077141471924], + [511009.0588988267, 6651153.84967561, 69.66487209085594], + [511009.36269007064, 6651152.385473231, 70.97987775685594], + [511010.39654748497, 6651150.652313107, 71.61869236271923], + [511009.1111192921, 6651153.597985243, 69.97324089885595], + [511010.1544304288, 6651151.817145051, 70.64678701271924], + [511009.29454839, 6651152.7139001135, 70.76662542185593], + [511009.1681518484, 6651153.323101728, 70.26133924985594], + [511009.2294890943, 6651153.027470623, 70.52653697485593], + [511009.7880297749, 6651153.579908868, 69.17998489571923], + [511010.0709217833, 6651152.218907485, 70.43450920371923], + [511009.8326828866, 6651153.365081496, 69.45746675571922], + [511009.5498762341, 6651154.725672228, 68.27247739971924], + [511009.8817216855, 6651153.12915446, 69.71790742871923], + [511009.9911922158, 6651152.60248867, 70.17829608071924], + [511009.9347229577, 6651152.874163853, 69.95887707471923], + [511010.29868056107, 6651151.12315362, 71.52952771071924], + [511009.5797631612, 6651154.581885384, 68.63023524571923], + [511010.22490076773, 6651151.478110275, 71.43043221671923], + [511009.6155161376, 6651154.409876812, 68.98069146071923], + [511010.15148485656, 6651151.831316282, 71.30280945771923], + [511009.65703390876, 6651154.210133651, 69.32043648771923], + [511010.0790974647, 6651152.179574053, 71.14631816571925], + [511009.7041068776, 6651153.98366428, 69.64610359771923], + [511010.0084269817, 6651152.519571727, 70.96110926371924], + [511009.75641825184, 6651153.731992792, 69.95447240571923], + [511009.9401666756, 6651152.847973974, 70.74785692871923], + [511009.81355009443, 6651153.457129896, 70.24257075671923], + [511009.87499412015, 6651153.161520965, 70.50776848171922], + [511024.2961290296, 6651144.452007684, 64.29946579601143], + [511024.1680620823, 6651145.048004751, 64.29946579601143], + [511024.1680620823, 6651145.048004751, 64.42946579601143], + [511024.2961290296, 6651144.452007684, 66.12826945501143], + [511024.2917256682, 6651144.472500016, 66.59386014201144], + [511024.1680620823, 6651145.048004751, 66.12826945501143], + [511024.16417676344, 6651145.066086221, 66.53908476701145], + [511024.27795577014, 6651144.536582272, 67.07113109401143], + [511024.1520268534, 6651145.122629388, 66.96020619501142], + [511024.25410913, 6651144.6475596, 67.55403211401143], + [511024.1309857002, 6651145.220550559, 67.38629533001144], + [511024.22930824646, 6651144.762977779, 67.91573809901143], + [511024.10062359745, 6651145.361849502, 67.81120183401143], + [511024.19845541625, 6651144.906560465, 68.27349594501143], + [511024.1615469543, 6651145.078324808, 68.62395216001143], + [511024.06075863546, 6651145.547372784, 68.22816853601142], + [511024.1186873876, 6651145.2777843615, 68.96369718701143], + [511024.01149592747, 6651145.776631232, 68.63011745301144], + [511024.07009308715, 6651145.503932178, 69.28936429701145], + [511023.9532488478, 6651146.047701085, 69.00999825501142], + [511024.01609108347, 6651145.755246326, 69.59773310501143], + [511023.90408981126, 6651146.276477067, 69.27640457001142], + [511028.7423143146, 6651145.413158831, 64.16447493163774], + [511023.95711282076, 6651146.029718955, 69.88583145601143], + [511023.8506857434, 6651146.525008547, 69.52411431001143], + [511028.6127716849, 6651146.008836894, 64.16447493163774], + [511028.6127716849, 6651146.008836894, 64.29447493163774], + [511023.8936830112, 6651146.324908161, 70.15102918101144], + [511023.77372906613, 6651146.883148995, 69.82155678001145], + [511023.8264041712, 6651146.638009957, 70.39111762801144], + [511023.69142275205, 6651147.266185545, 70.07776990301144], + [511023.7559377887, 6651146.965945918, 70.60436996301144], + [511028.7423143146, 6651145.413158831, 65.99327859063776], + [511023.60521522554, 6651147.6673775315, 70.29004771201143], + [511023.6829833359, 6651147.305460841, 70.78957886501144], + [511028.7378602144, 6651145.433640195, 66.45886927763773], + [511028.6127716849, 6651146.008836894, 65.99327859063776], + [511023.51660028985, 6651148.079773102, 70.45716246901142], + [511023.60825648624, 6651147.653224135, 70.94607015701143], + [511028.6088415965, 6651146.026908685, 66.40409390263774], + [511028.72393164935, 6651145.497688151, 66.93614022963774], + [511023.4270396664, 6651148.496569707, 70.57931559101145], + [511023.53246787685, 6651148.0059286365, 71.07369291601142], + [511028.5965516861, 6651146.083421589, 66.82521533063773], + [511023.33789568645, 6651148.91142734, 70.65799028401143], + [511028.69981023046, 6651145.608606079, 67.41904124963776], + [511023.45630362513, 6651148.3603813, 71.17278841001144], + [511028.5752680812, 6651146.181290348, 67.25130446563773], + [511023.2503793955, 6651149.318710045, 70.69573314301142], + [511028.6747235727, 6651145.723962481, 67.78074723463774], + [511023.35527378094, 6651148.830553286, 71.26195306201143], + [511021.6050489842, 6651156.97573725, 64.29946579601143], + [511031.37148492254, 6651145.986944344, 64.08371371663779], + [511021.6050489842, 6651156.97573725, 64.42946579601143], + [511028.54455612367, 6651146.322513661, 67.67621096963775], + [511028.64351523336, 6651145.867468315, 68.13850508063774], + [511023.256088651, 6651149.292140353, 71.30472830301143], + [511021.4769820368, 6651157.5717343185, 64.29946579601143], + [511031.2410696749, 6651146.582431968, 64.08371371663779], + [511031.2410696749, 6651146.582431968, 64.21371371663778], + [511028.60618148465, 6651146.039140723, 68.48896129563774], + [511028.504231808, 6651146.507937643, 68.09317767163773], + [511022.88273387484, 6651151.029656208, 70.69573314301142], + [511028.56282805826, 6651146.238493515, 68.82870632263776], + [511028.4544014587, 6651146.7370733805, 68.49512658863773], + [511021.60504849284, 6651156.975739538, 66.12826945601144], + [511031.37148492254, 6651145.986944344, 65.91251737563779], + [511028.5136738182, 6651146.464520288, 69.15437343263774], + [511021.60600341763, 6651156.971295516, 66.33209074001142], + [511028.3954832129, 6651147.007998145, 68.87500739063773], + [511031.36700081883, 6651146.007419161, 66.37810806263779], + [511021.4769820368, 6651157.5717343185, 66.12826945501143], + [511031.2410696749, 6651146.582431968, 65.91251737563779], + [511028.45904956345, 6651146.715699921, 69.46274224063774], + [511021.6139325565, 6651156.9343949435, 66.74867002801143], + [511028.34575772955, 6651147.236651676, 69.14141370563775], + [511022.5227311794, 6651152.705034244, 70.69573314301142], + [511021.6304607842, 6651156.857475993, 67.17299714801145], + [511031.2371131129, 6651146.600497983, 66.3233326876378], + [511021.48138539825, 6651157.551241985, 66.59386014201144], + [511031.35297842906, 6651146.071446641, 66.85537901463779], + [511028.39939170936, 6651146.9900256395, 69.75084059163775], + [511028.29173830024, 6651147.48505013, 69.38912344563774], + [511022.4352148884, 6651153.11231695, 70.65799028401143], + [511021.65612309735, 6651156.738048899, 67.59930749901143], + [511021.49515529623, 6651157.487159729, 67.07113109401143], + [511031.224740416, 6651146.656992819, 66.74445411563778], + [511022.3460709085, 6651153.527174582, 70.57931559101145], + [511022.5170224155, 6651152.731601651, 71.30472830301143], + [511021.6912310927, 6651156.574663554, 68.02111635801143], + [511031.3286945249, 6651146.182329107, 67.33828003463779], + [511028.33523101447, 6651147.285056848, 70.01603831663773], + [511022.256510285, 6651153.943971187, 70.45716246901142], + [511028.2138948712, 6651147.842998885, 69.68656591563774], + [511021.5190019365, 6651157.376182402, 67.55403211401143], + [511021.73582708446, 6651156.3671230385, 68.43146590101144], + [511022.41783728544, 6651153.193188718, 71.26195306201143], + [511022.16789534927, 6651154.356366758, 70.29004771201143], + [511031.2033134416, 6651146.75483029, 67.17054325063779], + [511021.78965314565, 6651156.116627689, 68.82324559501143], + [511021.54380282003, 6651157.260764223, 67.91573809901143], + [511022.08168782276, 6651154.757558744, 70.07776990301144], + [511021.8357493826, 6651155.9021053435, 69.10072745501142], + [511031.3034388796, 6651146.29764863, 67.6999860196378], + [511021.886373046, 6651155.666513291, 69.36116812801144], + [511021.9993815087, 6651155.140595295, 69.82155678001145], + [511021.94108724425, 6651155.411884738, 69.60213777401142], + [511028.2671769378, 6651147.597991058, 70.25612676363774], + [511022.31680744136, 6651153.663360701, 71.17278841001144], + [511021.5746556502, 6651157.117181537, 68.27349594501143], + [511028.1306401627, 6651148.225830417, 69.94277903863774], + [511022.24064318964, 6651154.017813366, 71.07369291601142], + [511021.6115641121, 6651156.945417193, 68.62395216001143], + [511031.17239460396, 6651146.896008453, 67.59544975463778], + [511031.27202031645, 6651146.441108585, 68.05774386563779], + [511022.16485458025, 6651154.370517868, 70.94607015701143], + [511028.19589858945, 6651147.925751491, 70.46937909863775], + [511021.6544236788, 6651156.74595764, 68.96369718701143], + [511022.0901277305, 6651154.71828116, 70.78957886501144], + [511021.70301797934, 6651156.5198098235, 69.28936429701145], + [511022.0171732778, 6651155.057796085, 70.60436996301144], + [511021.757019983, 6651156.268495674, 69.59773310501143], + [511021.9467068953, 6651155.385732044, 70.39111762801144], + [511028.0434392891, 6651148.626807668, 70.15505684763774], + [511021.81599824573, 6651155.994023046, 69.88583145601143], + [511021.8794280553, 6651155.698833841, 70.15102918101144], + [511031.2344350823, 6651146.61272611, 68.40820008063778], + [511031.1317986578, 6651147.081373155, 68.01241645663778], + [511028.12210350134, 6651148.265084692, 70.65458800063774], + [511027.9538032663, 6651149.038982505, 70.32217160463773], + [511031.1907896209, 6651146.812015168, 68.74794510763779], + [511028.04651559336, 6651148.612661846, 70.81107929263774], + [511031.08163264394, 6651147.310435638, 68.41436537363779], + [511027.86321065895, 6651149.455556022, 70.44432472663775], + [511027.9698536914, 6651148.965177565, 70.93870205163773], + [511031.1413042708, 6651147.037969681, 69.0736122176378], + [511031.02231751644, 6651147.581273788, 68.79424617563778], + [511027.773039496, 6651149.870191604, 70.52299941963776], + [511027.89281181875, 6651149.319440509, 71.03779754563776], + [511031.08631205914, 6651147.289069012, 69.38198102563778], + [511030.9722570751, 6651147.809854217, 69.06065249063778], + [511027.6845147774, 6651150.277256313, 70.56074227863775], + [511027.7906178337, 6651149.789360836, 71.12696219763774], + [511026.0202256484, 6651157.93018513, 64.16447493163774], + [511026.0202256484, 6651157.93018513, 64.29447493163774], + [511031.0262523412, 6651147.563307027, 69.67007937663779], + [511030.91787376313, 6651148.058173259, 69.30836223063778], + [511027.6902898191, 6651150.250700841, 71.16973743863774], + [511025.8906830187, 6651158.525863193, 64.16447493163774], + [511030.96165945055, 6651147.858243913, 69.9352771016378], + [511030.8395059694, 6651148.416007577, 69.6058047006378], + [511030.8931469518, 6651148.171078078, 70.17536554863779], + [511027.31263297226, 6651151.9872867, 70.56074227863775], + [511030.75569044525, 6651148.798716717, 69.8620178236378], + [511030.8213884621, 6651148.498733727, 70.38861788363779], + [511026.0202251514, 6651157.930187415, 65.99327859163773], + [511030.66790217394, 6651149.199565775, 70.07429563263779], + [511026.02119107946, 6651157.925745773, 66.19709987563775], + [511030.74709627964, 6651148.837958442, 70.57382678563779], + [511025.8906830187, 6651158.525863193, 65.99327859063776], + [511026.02921158384, 6651157.888864951, 66.61367916363776], + [511030.5776623499, 6651149.6116088405, 70.24141038963779], + [511030.67099920067, 6651149.185424476, 70.73031807763779], + [511026.94848205865, 6651153.661767998, 70.56074227863775], + [511026.045930262, 6651157.811987172, 67.03800628363774], + [511025.89513711893, 6651158.505381828, 66.45886927763773], + [511030.48645949777, 6651150.028049178, 70.36356351163778], + [511026.85995734, 6651154.068832707, 70.52299941963776], + [511030.59382089303, 6651149.5378274955, 70.85794083663778], + [511026.07188827544, 6651157.692623999, 67.46431663463774], + [511025.90906568395, 6651158.441333872, 66.93614022963774], + [511026.76978617697, 6651154.483468289, 70.44432472663775], + [511026.9427075141, 6651153.688321184, 71.16973743863774], + [511026.1074008111, 6651157.529326106, 67.88612549363775], + [511030.3956809287, 6651150.442552201, 70.44223820463779], + [511030.51626005507, 6651149.891977183, 70.95703633063779], + [511026.6791935697, 6651154.900041806, 70.32217160463773], + [511025.9331871027, 6651158.330415945, 67.41904124963776], + [511026.15251067106, 6651157.321896676, 68.29647503663774], + [511026.84237949946, 6651154.149661188, 71.12696219763774], + [511026.58955754683, 6651155.312216644, 70.15505684763774], + [511026.20695695595, 6651157.071535405, 68.68825473063774], + [511030.30655989476, 6651150.849486773, 70.47998106363778], + [511025.9582737605, 6651158.215059542, 67.78074723463774], + [511026.50235667324, 6651155.713193893, 69.94277903863774], + [511026.25358434796, 6651156.857127881, 68.96573659063773], + [511026.30479133484, 6651156.621661927, 69.22617726363774], + [511026.4191019648, 6651156.096025426, 69.68656591563774], + [511026.36013599054, 6651156.367169662, 69.46714690963775], + [511030.4133776768, 6651150.361747275, 71.04620098263779], + [511028.6310598739, 6651158.499968944, 64.08371371663779], + [511026.74018551456, 6651154.619581515, 71.03779754563776], + [511025.98948209995, 6651158.071553708, 68.13850508063774], + [511028.6310598739, 6651158.499968944, 64.21371371663778], + [511026.6631436418, 6651154.97384446, 70.93870205163773], + [511026.02681584854, 6651157.899881301, 68.48896129563774], + [511026.5864817398, 6651155.326360179, 70.81107929263774], + [511030.31237383815, 6651150.822939789, 71.08897622363779], + [511026.0701692749, 6651157.700528508, 68.82870632263776], + [511028.50064462627, 6651159.095456568, 64.08371371663779], + [511026.51089383196, 6651155.673937333, 70.65458800063774], + [511026.119323515, 6651157.474501736, 69.15437343263774], + [511026.43709874386, 6651156.013270534, 70.46937909863775], + [511026.17394776986, 6651157.223322102, 69.46274224063774], + [511026.3658203954, 6651156.3410309665, 70.25612676363774], + [511026.2336056238, 6651156.948996385, 69.75084059163775], + [511026.29776631884, 6651156.653965177, 70.01603831663773], + [511029.9321730401, 6651152.558970461, 70.47998106363778], + [511028.6310593735, 6651158.499971229, 65.9125173766378], + [511028.6320318082, 6651158.495531006, 66.11633866063778], + [511028.50064462627, 6651159.095456568, 65.91251737563779], + [511028.6401063399, 6651158.458661975, 66.53291794863779], + [511029.56556915335, 6651154.232916427, 70.47998106363778], + [511028.6569376374, 6651158.381808774, 66.9572450686378], + [511028.5051287299, 6651159.074981753, 66.37810806263779], + [511029.4764481195, 6651154.639850996, 70.44223820463779], + [511028.68307050783, 6651158.262483762, 67.38355541963779], + [511028.51915111975, 6651159.010954272, 66.85537901463779], + [511029.38566955045, 6651155.054354019, 70.36356351163778], + [511029.5597557107, 6651154.2594611235, 71.08897622363779], + [511028.7188222611, 6651158.099238075, 67.80536427863778], + [511029.2944666982, 6651155.470794357, 70.24141038963779], + [511028.5434350239, 6651158.900071804, 67.33828003463779], + [511028.7642359875, 6651157.89187496, 68.21571382163779], + [511029.458751872, 6651154.720653636, 71.04620098263779], + [511029.2042268743, 6651155.882837423, 70.07429563263779], + [511028.81904903054, 6651157.641593728, 68.60749351563778], + [511028.5686906691, 6651158.784752281, 67.6999860196378], + [511029.11643860297, 6651156.283686481, 69.8620178236378], + [511028.8659905114, 6651157.42725475, 68.8849753756378], + [511028.91754243587, 6651157.191864077, 69.1454160486378], + [511029.03262307873, 6651156.666395621, 69.6058047006378], + [511028.97325990116, 6651156.937453172, 69.38638569463778], + [511029.3558694937, 6651155.19042373, 70.95703633063779], + [511028.60010923236, 6651158.641292327, 68.05774386563779], + [511041.115431113, 6651148.148686391, 63.77831790688605], + [511029.2783086558, 6651155.544573417, 70.85794083663778], + [511028.6376944665, 6651158.469674803, 68.40820008063778], + [511029.20113034814, 6651155.8969764365, 70.73031807763779], + [511028.6813399279, 6651158.270385743, 68.74794510763779], + [511029.12503326917, 6651156.244442471, 70.57382678563779], + [511028.73082527803, 6651158.044431232, 69.0736122176378], + [511029.0507410867, 6651156.583667185, 70.38861788363779], + [511028.78581748967, 6651157.793331902, 69.38198102563778], + [511040.981781864, 6651148.743456536, 63.77831790688605], + [511028.978982597, 6651156.911322834, 70.17536554863779], + [511028.8458772076, 6651157.519093884, 69.67007937663779], + [511028.9104700983, 6651157.224157, 69.9352771016378], + [511040.981781864, 6651148.743456536, 63.90831790688606], + [511041.115431113, 6651148.148686391, 65.60712156588606], + [511041.11083581386, 6651148.169136538, 66.07271225288605], + [511040.981781864, 6651148.743456536, 65.60712156588606], + [511040.9777271882, 6651148.761500784, 66.01793687788606], + [511041.09646570054, 6651148.233086874, 66.54998320488606], + [511040.9650476766, 6651148.8179275505, 66.43905830588605], + [511041.07157961087, 6651148.343835743, 67.03288422488606], + [511040.943089362, 6651148.915647141, 66.86514744088608], + [511041.04569768306, 6651148.459016323, 67.39459020988606], + [511040.91140380746, 6651149.056655205, 67.29005394488605], + [511041.013500011, 6651148.602303429, 67.75234805588606], + [511040.97498274845, 6651148.773714176, 68.10280427088607], + [511040.86980117427, 6651149.241796569, 67.70702064688605], + [511040.93025497894, 6651148.972763121, 68.44254929788606], + [511040.8183911574, 6651149.470583063, 68.10896956388605], + [511040.8795425047, 6651149.198445389, 68.76821640788606], + [511040.7576051497, 6651149.74109489, 68.48885036588607], + [511045.23556442215, 6651149.079488954, 63.646292658619146], + [511040.8231866113, 6651149.449242182, 69.07658521588606], + [511040.7063033231, 6651149.969399913, 68.75525668088605], + [511045.10054770694, 6651149.673950167, 63.646292658619146], + [511040.76163754903, 6651149.723149778, 69.36468356688606], + [511045.10054770694, 6651149.673950167, 63.776292658619155], + [511040.6505714288, 6651150.217419764, 69.00296642088605], + [511040.69544290163, 6651150.017731307, 69.62988129188605], + [511040.5702602921, 6651150.574822943, 69.30040889088606], + [511040.62523144885, 6651150.33018855, 69.86996973888606], + [511045.23556442215, 6651149.079488954, 65.47509631761915], + [511040.4843663336, 6651150.957070973, 69.55662201388606], + [511040.5516935118, 6651150.65744942, 70.08322207388606], + [511045.23092210497, 6651149.09992848, 65.94068700461915], + [511045.10054770694, 6651149.673950167, 65.47509631761915], + [511040.39440111286, 6651151.357437064, 69.76889982288606], + [511040.4755590523, 6651150.996265417, 70.26843097588606], + [511045.0964515448, 6651149.691985042, 65.88591162961914], + [511045.21640496026, 6651149.163845598, 66.41795795661916], + [511040.30192354653, 6651151.768983676, 69.93601457988606], + [511040.3975749388, 6651151.343312804, 70.42492226788607], + [511045.0836422994, 6651149.7483825, 66.30703305761915], + [511040.2084590711, 6651152.184922261, 70.05816770188605], + [511045.1912642422, 6651149.274536943, 66.90085897661915], + [511040.3184827848, 6651151.695291226, 70.55254502688607], + [511045.06145931274, 6651149.8460513335, 66.73312219261915], + [511040.11542940006, 6651152.598925866, 70.13684239488606], + [511040.23899861454, 6651152.049014212, 70.65164052088606], + [511045.1651174969, 6651149.389657696, 67.26256496161915], + [511040.02409836726, 6651153.005370137, 70.17458525388605], + [511045.0294495594, 6651149.986986156, 67.15802869661917], + [511038.3070497575, 6651160.646634553, 63.77831790688605], + [511040.1335649872, 6651152.518218298, 70.74080517288606], + [511045.13259038614, 6651149.5328703765, 67.62032280761915], + [511038.3070497575, 6651160.646634553, 63.90831790688606], + [511040.0300564831, 6651152.978855141, 70.78358041388606], + [511038.1734005084, 6651161.241404697, 63.77831790688605], + [511045.09367902455, 6651149.704192091, 67.97077902261915], + [511044.98742125835, 6651150.172031355, 67.57499539861915], + [511045.04849361157, 6651149.903137647, 68.31052404961915], + [511044.93548522686, 6651150.400699014, 67.97694431561915], + [511039.6404275704, 6651154.712794139, 70.17458525388605], + [511044.9972622597, 6651150.128702692, 68.63619115961914], + [511044.87407727167, 6651150.6710703345, 68.35682511761915], + [511038.3070492447, 6651160.646636833, 65.60712156688605], + [511038.3080457937, 6651160.64220196, 65.81094285088605], + [511044.94032974663, 6651150.379369217, 68.94455996761916], + [511044.8222505375, 6651150.899256771, 68.62323143261916], + [511038.1734005084, 6651161.241404697, 65.60712156588606], + [511038.3163205552, 6651160.605377353, 66.22752213888606], + [511044.8781509296, 6651150.653134543, 69.23265831861914], + [511044.76594840817, 6651151.147147799, 68.87094117261915], + [511039.26473274117, 6651156.384723234, 70.17458525388605], + [511038.33356923074, 6651160.528616747, 66.65184925888606], + [511038.17799580767, 6651161.2209545495, 66.07271225288605], + [511039.1734017084, 6651156.791167505, 70.13684239488606], + [511038.3603501369, 6651160.409435506, 67.07815960988606], + [511044.8112789948, 6651150.9475630615, 69.49785604361915], + [511038.19236592087, 6651161.157004214, 66.54998320488606], + [511044.6848155476, 6651151.504365336, 69.16838364261915], + [511039.0803720374, 6651157.20517111, 70.05816770188605], + [511038.3969884523, 6651160.2463865075, 67.49996846888605], + [511039.2587751383, 6651156.411235948, 70.78358041388606], + [511038.9869075619, 6651157.621109696, 69.93601457988606], + [511038.21725201065, 6651161.0462553445, 67.03288422488606], + [511038.4435283358, 6651160.039273236, 67.91031801188608], + [511044.74034915573, 6651151.25985801, 69.73794449061916], + [511039.1552666343, 6651156.871872789, 70.74080517288606], + [511038.89442999556, 6651158.032656307, 69.76889982288606], + [511038.4997006175, 6651159.789293559, 68.30209770588606], + [511038.24313393835, 6651160.931074766, 67.39459020988606], + [511044.59804274334, 6651151.886414822, 69.42459676561916], + [511038.5478061403, 6651159.575212829, 68.57957956588605], + [511038.80446477485, 6651158.433022398, 69.55662201388606], + [511038.60063643527, 6651159.340105767, 68.84002023888605], + [511038.71857081633, 6651158.815270428, 69.30040889088606], + [511038.657735567, 6651159.086001392, 69.08098988488605], + [511039.049833007, 6651157.341076876, 70.65164052088606], + [511038.2753316105, 6651160.787787661, 67.75234805588606], + [511044.66605879663, 6651151.586948897, 69.95119682561915], + [511038.97034883674, 6651157.694799862, 70.55254502688607], + [511038.31384887296, 6651160.616376911, 68.10280427088607], + [511044.5071570207, 6651152.286572957, 69.63687457461916], + [511038.89125668263, 6651158.046778286, 70.42492226788607], + [511038.3585766425, 6651160.417327967, 68.44254929788606], + [511038.8132725692, 6651158.393825671, 70.26843097588606], + [511038.4092891167, 6651160.191645699, 68.76821640788606], + [511044.589145348, 6651151.925588907, 70.13640572761916], + [511038.73713810963, 6651158.732641668, 70.08322207388606], + [511038.4656450101, 6651159.940848907, 69.07658521588606], + [511038.66360017273, 6651159.059902538, 69.86996973888606], + [511038.52719407243, 6651159.666941309, 69.36468356688606], + [511038.5933887199, 6651159.3723597815, 69.62988129188605], + [511051.1287429177, 6651150.428177127, 63.45445553490367], + [511044.4137332466, 6651152.697905804, 69.80398933161915], + [511044.51036332035, 6651152.272456031, 70.29289701961915], + [511050.99177026504, 6651151.022190713, 63.45445553490367], + [511044.3193124656, 6651153.113628346, 69.92614245361915], + [511050.99177026504, 6651151.022190713, 63.584455534903675], + [511044.43046191486, 6651152.624251632, 70.42051977861915], + [511044.225330938, 6651153.527416913, 70.00481714661915], + [511044.35016448214, 6651152.977790889, 70.51961527261915], + [511044.13306542847, 6651153.933650071, 70.04256000561917], + [511042.39844840026, 6651161.570945504, 63.646292658619146], + [511044.2436520839, 6651153.446751265, 70.60877992461916], + [511042.39844840026, 6651161.570945504, 63.776292658619155], + [511051.1287429177, 6651150.428177127, 65.28325919390367], + [511042.263431685, 6651162.165406717, 63.646292658619146], + [511044.1390845064, 6651153.907148846, 70.65155516561916], + [511051.12403334887, 6651150.448601262, 65.74884988090368], + [511050.99177026504, 6651151.022190713, 65.28325919390367], + [511050.9876147634, 6651151.040212006, 65.69407450590369], + [511051.10930589976, 6651150.51247025, 66.22612083290367], + [511043.7454690065, 6651155.640187212, 70.04256000561917], + [511050.9746199552, 6651151.0965669975, 66.11519593390366], + [511042.3984478822, 6651161.570947786, 65.47509631861915], + [511051.08380097727, 6651150.623078245, 66.70902185290367], + [511042.39945462754, 6651161.566515215, 65.67891760261917], + [511050.95211561176, 6651151.194162289, 66.54128506890368], + [511042.263431685, 6651162.165406717, 65.47509631761915], + [511051.0572754539, 6651150.738112312, 67.07072783790368], + [511042.4078140545, 6651161.529709735, 66.09549689061915], + [511050.919642145, 6651151.334990987, 66.96619157290367], + [511042.42523921415, 6651161.452989, 66.51982401061915], + [511042.2680740021, 6651162.144967193, 65.94068700461915], + [511043.36593016033, 6651157.311247882, 70.04256000561917], + [511051.0242771348, 6651150.881217155, 67.42848568390367], + [511043.2736646509, 6651157.717481041, 70.00481714661915], + [511042.452294136, 6651161.333869664, 66.94613436161914], + [511042.2825911469, 6651162.081050075, 66.41795795661916], + [511050.8770049955, 6651151.519896845, 67.38315827490366], + [511050.98480207863, 6651151.052409864, 67.77894189890367], + [511043.17968312325, 6651158.131269607, 69.92614245361915], + [511042.48930732557, 6651161.170905354, 67.36794322061917], + [511043.3599116008, 6651157.337746827, 70.65155516561916], + [511042.307731865, 6651161.970358729, 66.90085897661915], + [511043.0852623423, 6651158.546992149, 69.80398933161915], + [511042.53632339375, 6651160.96389966, 67.77829276361915], + [511043.2553440232, 6651157.798144408, 70.60877992461916], + [511042.99183856824, 6651158.958324998, 69.63687457461916], + [511042.5930704165, 6651160.714049825, 68.17007245761916], + [511050.9389620813, 6651151.251205615, 68.11868692590367], + [511042.33387861017, 6651161.855237977, 67.26256496161915], + [511042.6416681431, 6651160.500080292, 68.44755431761915], + [511042.9009528455, 6651159.358483133, 69.42459676561916], + [511050.82431658584, 6651151.74839232, 67.78510719190368], + [511042.69503898453, 6651160.265095349, 68.70799499061916], + [511042.81418004126, 6651159.740532617, 69.16838364261915], + [511042.75272234064, 6651160.011122961, 68.94896463661917], + [511043.148831625, 6651158.267104781, 70.51961527261915], + [511042.36640572094, 6651161.712025296, 67.62032280761915], + [511043.0685341923, 6651158.620644039, 70.42051977861915], + [511042.40531708254, 6651161.54070358, 67.97077902261915], + [511050.88698855985, 6651151.476600811, 68.44435403590369], + [511042.9886327868, 6651158.972439639, 70.29289701961915], + [511042.4505024956, 6651161.341758025, 68.31052404961915], + [511050.7620190362, 6651152.018560051, 68.16498799390367], + [511042.90985075914, 6651159.319306764, 70.13640572761916], + [511042.50173384737, 6651161.116192979, 68.63619115961914], + [511042.83293731045, 6651159.657946776, 69.95119682561915], + [511042.5586663605, 6651160.8655264545, 68.94455996761916], + [511042.7586469514, 6651159.985037661, 69.73794449061916], + [511042.62084517756, 6651160.591761129, 69.23265831861914], + [511042.68771711236, 6651160.297332611, 69.49785604361915], + [511050.8292312865, 6651151.727078585, 68.75272284390367], + [511050.70944150735, 6651152.2465746645, 68.43139430890366], + [511050.7661517078, 6651152.000637765, 69.04082119490367], + [511050.65232374985, 6651152.49427903, 68.67910404890367], + [511050.69831102394, 6651152.294844581, 69.30601891990368], + [511050.5700155475, 6651152.851227584, 68.97654651890369], + [511050.6263536504, 6651152.606904372, 69.54610736690368], + [511050.4819856976, 6651153.232989387, 69.23275964190368], + [511050.5509870744, 6651152.933748959, 69.75935970190368], + [511050.3897833471, 6651153.632846204, 69.44503745090367], + [511050.47295940906, 6651153.272133974, 69.94456860390368], + [511050.2950061773, 6651154.043869319, 69.61215220790369], + [511050.39303609525, 6651153.6187399095, 70.10105989590367], + [511050.1992175574, 6651154.459278824, 69.73430532990369], + [511050.3119771876, 6651153.970270609, 70.22868265490368], + [511050.103874554, 6651154.872755808, 69.81298002290367], + [511050.2305165157, 6651154.323543652, 70.32777814890368], + [511050.01027242816, 6651155.278683073, 69.85072288190366], + [511048.2505266435, 6651162.910227645, 63.45445553490367], + [511050.1224611116, 6651154.792150903, 70.41694280090367], + [511048.2505266435, 6651162.910227645, 63.584455534903675], + [511048.11355399096, 6651163.504241231, 63.45445553490367], + [511050.0163787022, 6651155.252201804, 70.45971804190367], + [511049.61706103984, 6651156.983935197, 69.85072288190366], + [511048.2505261179, 6651162.910229924, 65.28325919490368], + [511048.2515474477, 6651162.905800693, 65.48708047890366], + [511048.11355399096, 6651163.504241231, 65.28325919390367], + [511048.26002797455, 6651162.869022926, 65.90365976690367], + [511048.277705566, 6651162.792359963, 66.32798688690369], + [511048.11826355965, 6651163.483817097, 65.74884988090368], + [511049.2320239546, 6651158.6537375655, 69.85072288190366], + [511048.30515242246, 6651162.673330323, 66.75429723790367], + [511049.13842182886, 6651159.0596648315, 69.81298002290367], + [511048.13299100887, 6651163.4199481085, 66.22612083290367], + [511049.0430788254, 6651159.473141815, 69.73430532990369], + [511048.3427018085, 6651162.510488725, 67.17610609690367], + [511049.22591820644, 6651158.680216554, 70.45971804190367], + [511048.15849593125, 6651163.309340114, 66.70902185290367], + [511048.9472902055, 6651159.888551319, 69.61215220790369], + [511048.3903989811, 6651162.303638905, 67.58645563990368], + [511049.11983579694, 6651159.140267456, 70.41694280090367], + [511048.8525130357, 6651160.299574434, 69.44503745090367], + [511048.4479680769, 6651162.053977206, 67.97823533390367], + [511048.18502145476, 6651163.194306046, 67.07072783790368], + [511048.497269821, 6651161.840168792, 68.25571719390368], + [511048.7603106852, 6651160.699431251, 69.23275964190368], + [511048.5514138261, 6651161.605360792, 68.51615786690368], + [511048.6722808353, 6651161.081193054, 68.97654651890369], + [511048.60993281956, 6651161.351579643, 68.75712751290366], + [511049.01178039296, 6651159.608874706, 70.32777814890368], + [511048.2180197737, 6651163.051201204, 67.42848568390367], + [511048.93031972094, 6651159.96214775, 70.22868265490368], + [511048.2574948299, 6651162.8800084945, 67.77894189890367], + [511048.8492608134, 6651160.313678448, 70.10105989590367], + [511048.30333482736, 6651162.681212743, 68.11868692590367], + [511048.76933749946, 6651160.660284384, 69.94456860390368], + [511048.3553083488, 6651162.455817548, 68.44435403590369], + [511048.69130983413, 6651160.9986694, 69.75935970190368], + [511048.41306562215, 6651162.2053397745, 68.75272284390367], + [511048.6159432581, 6651161.325513987, 69.54610736690368], + [511048.47614520084, 6651161.931780593, 69.04082119490367], + [511048.5439858846, 6651161.637573778, 69.30601891990368] + ], + "pointIndex": [ + 31, + 34, + 140, + 135, + 0, + 34, + 46, + 164, + 140, + 0, + 46, + 49, + 169, + 164, + 0, + 49, + 51, + 174, + 169, + 0, + 51, + 54, + 179, + 174, + 0, + 54, + 57, + 185, + 179, + 0, + 57, + 61, + 190, + 185, + 0, + 61, + 68, + 199, + 190, + 0, + 68, + 71, + 203, + 199, + 0, + 71, + 73, + 206, + 203, + 0, + 73, + 75, + 209, + 206, + 0, + 75, + 77, + 211, + 209, + 0, + 77, + 79, + 214, + 211, + 0, + 79, + 81, + 216, + 214, + 0, + 81, + 82, + 217, + 216, + 0, + 82, + 80, + 215, + 217, + 0, + 80, + 78, + 212, + 215, + 0, + 78, + 76, + 210, + 212, + 0, + 76, + 74, + 208, + 210, + 0, + 74, + 72, + 204, + 208, + 0, + 72, + 65, + 196, + 204, + 0, + 65, + 45, + 162, + 196, + 0, + 45, + 42, + 156, + 162, + 0, + 42, + 40, + 150, + 156, + 0, + 40, + 38, + 147, + 150, + 0, + 38, + 36, + 144, + 147, + 0, + 36, + 33, + 139, + 144, + 0, + 33, + 29, + 133, + 139, + 0, + 29, + 27, + 129, + 133, + 0, + 27, + 25, + 125, + 129, + 0, + 25, + 24, + 122, + 125, + 0, + 24, + 21, + 117, + 122, + 0, + 21, + 19, + 114, + 117, + 0, + 19, + 18, + 111, + 114, + 0, + 18, + 16, + 107, + 111, + 0, + 16, + 14, + 103, + 107, + 0, + 14, + 12, + 99, + 103, + 0, + 12, + 10, + 96, + 99, + 0, + 10, + 8, + 93, + 96, + 0, + 8, + 6, + 91, + 93, + 0, + 6, + 4, + 87, + 91, + 0, + 4, + 1, + 83, + 87, + 0, + 1, + 2, + 84, + 83, + 0, + 2, + 3, + 85, + 84, + 0, + 3, + 5, + 90, + 85, + 0, + 5, + 7, + 92, + 90, + 0, + 7, + 9, + 94, + 92, + 0, + 9, + 11, + 97, + 94, + 0, + 11, + 13, + 101, + 97, + 0, + 13, + 15, + 105, + 101, + 0, + 15, + 17, + 110, + 105, + 0, + 17, + 20, + 115, + 110, + 0, + 20, + 22, + 118, + 115, + 0, + 22, + 23, + 121, + 118, + 0, + 23, + 26, + 126, + 121, + 0, + 26, + 28, + 130, + 126, + 0, + 28, + 30, + 134, + 130, + 0, + 30, + 35, + 141, + 134, + 0, + 35, + 37, + 145, + 141, + 0, + 37, + 39, + 149, + 145, + 0, + 39, + 41, + 152, + 149, + 0, + 41, + 48, + 168, + 152, + 0, + 48, + 55, + 182, + 168, + 0, + 55, + 58, + 186, + 182, + 0, + 58, + 60, + 189, + 186, + 0, + 60, + 63, + 193, + 189, + 0, + 63, + 67, + 198, + 193, + 0, + 67, + 70, + 201, + 198, + 0, + 70, + 69, + 200, + 201, + 0, + 69, + 66, + 197, + 200, + 0, + 66, + 64, + 194, + 197, + 0, + 64, + 62, + 191, + 194, + 0, + 62, + 59, + 187, + 191, + 0, + 59, + 56, + 183, + 187, + 0, + 56, + 53, + 178, + 183, + 0, + 53, + 52, + 175, + 178, + 0, + 52, + 50, + 171, + 175, + 0, + 50, + 47, + 166, + 171, + 0, + 47, + 44, + 161, + 166, + 0, + 44, + 43, + 158, + 161, + 0, + 43, + 32, + 138, + 158, + 0, + 32, + 31, + 135, + 138, + 0, + 135, + 140, + 159, + 154, + 0, + 140, + 164, + 184, + 159, + 0, + 164, + 169, + 195, + 184, + 0, + 169, + 174, + 205, + 195, + 0, + 174, + 179, + 218, + 205, + 0, + 179, + 185, + 221, + 218, + 0, + 185, + 190, + 225, + 221, + 0, + 190, + 199, + 232, + 225, + 0, + 199, + 203, + 235, + 232, + 0, + 203, + 206, + 237, + 235, + 0, + 206, + 209, + 239, + 237, + 0, + 209, + 211, + 241, + 239, + 0, + 211, + 214, + 243, + 241, + 0, + 214, + 216, + 245, + 243, + 0, + 216, + 217, + 246, + 245, + 0, + 217, + 215, + 244, + 246, + 0, + 215, + 212, + 242, + 244, + 0, + 212, + 210, + 240, + 242, + 0, + 210, + 208, + 238, + 240, + 0, + 208, + 204, + 236, + 238, + 0, + 204, + 196, + 229, + 236, + 0, + 196, + 162, + 181, + 229, + 0, + 162, + 156, + 176, + 181, + 0, + 156, + 150, + 172, + 176, + 0, + 150, + 147, + 167, + 172, + 0, + 147, + 144, + 163, + 167, + 0, + 144, + 139, + 157, + 163, + 0, + 139, + 133, + 151, + 157, + 0, + 133, + 129, + 146, + 151, + 0, + 129, + 125, + 142, + 146, + 0, + 125, + 122, + 137, + 142, + 0, + 122, + 117, + 131, + 137, + 0, + 117, + 114, + 127, + 131, + 0, + 114, + 111, + 124, + 127, + 0, + 111, + 107, + 120, + 124, + 0, + 107, + 103, + 116, + 120, + 0, + 103, + 99, + 112, + 116, + 0, + 99, + 96, + 108, + 112, + 0, + 96, + 93, + 104, + 108, + 0, + 93, + 91, + 100, + 104, + 0, + 91, + 87, + 95, + 100, + 0, + 87, + 83, + 86, + 95, + 0, + 83, + 84, + 88, + 86, + 0, + 84, + 85, + 89, + 88, + 0, + 85, + 90, + 98, + 89, + 0, + 90, + 92, + 102, + 98, + 0, + 92, + 94, + 106, + 102, + 0, + 94, + 97, + 109, + 106, + 0, + 97, + 101, + 113, + 109, + 0, + 101, + 105, + 119, + 113, + 0, + 105, + 110, + 123, + 119, + 0, + 110, + 115, + 128, + 123, + 0, + 115, + 118, + 132, + 128, + 0, + 118, + 121, + 136, + 132, + 0, + 121, + 126, + 143, + 136, + 0, + 126, + 130, + 148, + 143, + 0, + 130, + 134, + 153, + 148, + 0, + 134, + 141, + 160, + 153, + 0, + 141, + 145, + 165, + 160, + 0, + 145, + 149, + 170, + 165, + 0, + 149, + 152, + 173, + 170, + 0, + 152, + 168, + 192, + 173, + 0, + 168, + 182, + 219, + 192, + 0, + 182, + 186, + 222, + 219, + 0, + 186, + 189, + 224, + 222, + 0, + 189, + 193, + 227, + 224, + 0, + 193, + 198, + 231, + 227, + 0, + 198, + 201, + 234, + 231, + 0, + 201, + 200, + 233, + 234, + 0, + 200, + 197, + 230, + 233, + 0, + 197, + 194, + 228, + 230, + 0, + 194, + 191, + 226, + 228, + 0, + 191, + 187, + 223, + 226, + 0, + 187, + 183, + 220, + 223, + 0, + 183, + 178, + 213, + 220, + 0, + 178, + 175, + 207, + 213, + 0, + 175, + 171, + 202, + 207, + 0, + 171, + 166, + 188, + 202, + 0, + 166, + 161, + 180, + 188, + 0, + 161, + 158, + 177, + 180, + 0, + 158, + 138, + 155, + 177, + 0, + 138, + 135, + 154, + 155, + 0, + 154, + 159, + 314, + 306, + 0, + 159, + 184, + 338, + 314, + 0, + 184, + 195, + 346, + 338, + 0, + 195, + 205, + 350, + 346, + 0, + 205, + 218, + 355, + 350, + 0, + 218, + 221, + 361, + 355, + 0, + 221, + 225, + 369, + 361, + 0, + 225, + 232, + 382, + 369, + 0, + 232, + 235, + 394, + 382, + 0, + 235, + 237, + 398, + 394, + 0, + 237, + 239, + 403, + 398, + 0, + 239, + 241, + 406, + 403, + 0, + 241, + 243, + 410, + 406, + 0, + 243, + 245, + 412, + 410, + 0, + 245, + 246, + 411, + 412, + 0, + 246, + 244, + 409, + 411, + 0, + 244, + 242, + 405, + 409, + 0, + 242, + 240, + 404, + 405, + 0, + 240, + 238, + 399, + 404, + 0, + 238, + 236, + 393, + 399, + 0, + 236, + 229, + 378, + 393, + 0, + 229, + 181, + 333, + 378, + 0, + 181, + 176, + 329, + 333, + 0, + 176, + 172, + 325, + 329, + 0, + 172, + 167, + 321, + 325, + 0, + 167, + 163, + 317, + 321, + 0, + 163, + 157, + 310, + 317, + 0, + 157, + 151, + 303, + 310, + 0, + 151, + 146, + 299, + 303, + 0, + 146, + 142, + 295, + 299, + 0, + 142, + 137, + 292, + 295, + 0, + 137, + 131, + 287, + 292, + 0, + 131, + 127, + 283, + 287, + 0, + 127, + 124, + 280, + 283, + 0, + 124, + 120, + 276, + 280, + 0, + 120, + 116, + 273, + 276, + 0, + 116, + 112, + 269, + 273, + 0, + 112, + 108, + 265, + 269, + 0, + 108, + 104, + 261, + 265, + 0, + 104, + 100, + 256, + 261, + 0, + 100, + 95, + 253, + 256, + 0, + 95, + 86, + 247, + 253, + 0, + 86, + 88, + 249, + 247, + 0, + 88, + 89, + 251, + 249, + 0, + 89, + 98, + 255, + 251, + 0, + 98, + 102, + 259, + 255, + 0, + 102, + 106, + 263, + 259, + 0, + 106, + 109, + 267, + 263, + 0, + 109, + 113, + 271, + 267, + 0, + 113, + 119, + 275, + 271, + 0, + 119, + 123, + 279, + 275, + 0, + 123, + 128, + 284, + 279, + 0, + 128, + 132, + 288, + 284, + 0, + 132, + 136, + 291, + 288, + 0, + 136, + 143, + 296, + 291, + 0, + 143, + 148, + 300, + 296, + 0, + 148, + 153, + 305, + 300, + 0, + 153, + 160, + 313, + 305, + 0, + 160, + 165, + 319, + 313, + 0, + 165, + 170, + 323, + 319, + 0, + 170, + 173, + 327, + 323, + 0, + 173, + 192, + 342, + 327, + 0, + 192, + 219, + 357, + 342, + 0, + 219, + 222, + 362, + 357, + 0, + 222, + 224, + 368, + 362, + 0, + 224, + 227, + 373, + 368, + 0, + 227, + 231, + 379, + 373, + 0, + 231, + 234, + 386, + 379, + 0, + 234, + 233, + 385, + 386, + 0, + 233, + 230, + 380, + 385, + 0, + 230, + 228, + 375, + 380, + 0, + 228, + 226, + 371, + 375, + 0, + 226, + 223, + 367, + 371, + 0, + 223, + 220, + 360, + 367, + 0, + 220, + 213, + 354, + 360, + 0, + 213, + 207, + 351, + 354, + 0, + 207, + 202, + 348, + 351, + 0, + 202, + 188, + 341, + 348, + 0, + 188, + 180, + 335, + 341, + 0, + 180, + 177, + 331, + 335, + 0, + 177, + 155, + 309, + 331, + 0, + 155, + 154, + 306, + 309, + 0, + 306, + 314, + 316, + 308, + 0, + 314, + 338, + 339, + 316, + 0, + 338, + 346, + 347, + 339, + 0, + 346, + 350, + 352, + 347, + 0, + 350, + 355, + 358, + 352, + 0, + 355, + 361, + 365, + 358, + 0, + 361, + 369, + 374, + 365, + 0, + 369, + 382, + 390, + 374, + 0, + 382, + 394, + 396, + 390, + 0, + 394, + 398, + 400, + 396, + 0, + 398, + 403, + 407, + 400, + 0, + 403, + 406, + 414, + 407, + 0, + 406, + 410, + 417, + 414, + 0, + 410, + 412, + 419, + 417, + 0, + 412, + 411, + 418, + 419, + 0, + 411, + 409, + 416, + 418, + 0, + 409, + 405, + 413, + 416, + 0, + 405, + 404, + 408, + 413, + 0, + 404, + 399, + 401, + 408, + 0, + 399, + 393, + 395, + 401, + 0, + 393, + 378, + 387, + 395, + 0, + 378, + 333, + 336, + 387, + 0, + 333, + 329, + 330, + 336, + 0, + 329, + 325, + 326, + 330, + 0, + 325, + 321, + 322, + 326, + 0, + 321, + 317, + 318, + 322, + 0, + 317, + 310, + 312, + 318, + 0, + 310, + 303, + 304, + 312, + 0, + 303, + 299, + 301, + 304, + 0, + 299, + 295, + 297, + 301, + 0, + 295, + 292, + 294, + 297, + 0, + 292, + 287, + 289, + 294, + 0, + 287, + 283, + 285, + 289, + 0, + 283, + 280, + 282, + 285, + 0, + 280, + 276, + 278, + 282, + 0, + 276, + 273, + 274, + 278, + 0, + 273, + 269, + 270, + 274, + 0, + 269, + 265, + 266, + 270, + 0, + 265, + 261, + 262, + 266, + 0, + 261, + 256, + 258, + 262, + 0, + 256, + 253, + 254, + 258, + 0, + 253, + 247, + 248, + 254, + 0, + 247, + 249, + 250, + 248, + 0, + 249, + 251, + 252, + 250, + 0, + 251, + 255, + 257, + 252, + 0, + 255, + 259, + 260, + 257, + 0, + 259, + 263, + 264, + 260, + 0, + 263, + 267, + 268, + 264, + 0, + 267, + 271, + 272, + 268, + 0, + 271, + 275, + 277, + 272, + 0, + 275, + 279, + 281, + 277, + 0, + 279, + 284, + 286, + 281, + 0, + 284, + 288, + 290, + 286, + 0, + 288, + 291, + 293, + 290, + 0, + 291, + 296, + 298, + 293, + 0, + 296, + 300, + 302, + 298, + 0, + 300, + 305, + 307, + 302, + 0, + 305, + 313, + 315, + 307, + 0, + 313, + 319, + 320, + 315, + 0, + 319, + 323, + 324, + 320, + 0, + 323, + 327, + 328, + 324, + 0, + 327, + 342, + 345, + 328, + 0, + 342, + 357, + 359, + 345, + 0, + 357, + 362, + 366, + 359, + 0, + 362, + 368, + 372, + 366, + 0, + 368, + 373, + 381, + 372, + 0, + 373, + 379, + 388, + 381, + 0, + 379, + 386, + 392, + 388, + 0, + 386, + 385, + 391, + 392, + 0, + 385, + 380, + 389, + 391, + 0, + 380, + 375, + 384, + 389, + 0, + 375, + 371, + 376, + 384, + 0, + 371, + 367, + 370, + 376, + 0, + 367, + 360, + 364, + 370, + 0, + 360, + 354, + 356, + 364, + 0, + 354, + 351, + 353, + 356, + 0, + 351, + 348, + 349, + 353, + 0, + 348, + 341, + 344, + 349, + 0, + 341, + 335, + 337, + 344, + 0, + 335, + 331, + 332, + 337, + 0, + 331, + 309, + 311, + 332, + 0, + 309, + 306, + 308, + 311, + 0, + 308, + 316, + 454, + 448, + 0, + 316, + 339, + 472, + 454, + 0, + 339, + 347, + 477, + 472, + 0, + 347, + 352, + 481, + 477, + 0, + 352, + 358, + 486, + 481, + 0, + 358, + 365, + 490, + 486, + 0, + 365, + 374, + 495, + 490, + 0, + 374, + 390, + 503, + 495, + 0, + 390, + 396, + 508, + 503, + 0, + 396, + 400, + 510, + 508, + 0, + 400, + 407, + 514, + 510, + 0, + 407, + 414, + 516, + 514, + 0, + 414, + 417, + 518, + 516, + 0, + 417, + 419, + 520, + 518, + 0, + 419, + 418, + 519, + 520, + 0, + 418, + 416, + 517, + 519, + 0, + 416, + 413, + 515, + 517, + 0, + 413, + 408, + 512, + 515, + 0, + 408, + 401, + 509, + 512, + 0, + 401, + 395, + 507, + 509, + 0, + 395, + 387, + 499, + 507, + 0, + 387, + 336, + 470, + 499, + 0, + 336, + 330, + 466, + 470, + 0, + 330, + 326, + 462, + 466, + 0, + 326, + 322, + 459, + 462, + 0, + 322, + 318, + 455, + 459, + 0, + 318, + 312, + 450, + 455, + 0, + 312, + 304, + 445, + 450, + 0, + 304, + 301, + 441, + 445, + 0, + 301, + 297, + 438, + 441, + 0, + 297, + 294, + 437, + 438, + 0, + 294, + 289, + 434, + 437, + 0, + 289, + 285, + 430, + 434, + 0, + 285, + 282, + 428, + 430, + 0, + 282, + 278, + 426, + 428, + 0, + 278, + 274, + 424, + 426, + 0, + 274, + 270, + 422, + 424, + 0, + 270, + 266, + 420, + 422, + 0, + 266, + 262, + 402, + 420, + 0, + 262, + 258, + 383, + 402, + 0, + 258, + 254, + 363, + 383, + 0, + 254, + 248, + 334, + 363, + 0, + 248, + 250, + 340, + 334, + 0, + 250, + 252, + 343, + 340, + 0, + 252, + 257, + 377, + 343, + 0, + 257, + 260, + 397, + 377, + 0, + 260, + 264, + 415, + 397, + 0, + 264, + 268, + 421, + 415, + 0, + 268, + 272, + 423, + 421, + 0, + 272, + 277, + 425, + 423, + 0, + 277, + 281, + 427, + 425, + 0, + 281, + 286, + 431, + 427, + 0, + 286, + 290, + 435, + 431, + 0, + 290, + 293, + 436, + 435, + 0, + 293, + 298, + 439, + 436, + 0, + 298, + 302, + 442, + 439, + 0, + 302, + 307, + 447, + 442, + 0, + 307, + 315, + 452, + 447, + 0, + 315, + 320, + 457, + 452, + 0, + 320, + 324, + 461, + 457, + 0, + 324, + 328, + 464, + 461, + 0, + 328, + 345, + 476, + 464, + 0, + 345, + 359, + 487, + 476, + 0, + 359, + 366, + 491, + 487, + 0, + 366, + 372, + 494, + 491, + 0, + 372, + 381, + 497, + 494, + 0, + 381, + 388, + 500, + 497, + 0, + 388, + 392, + 505, + 500, + 0, + 392, + 391, + 504, + 505, + 0, + 391, + 389, + 501, + 504, + 0, + 389, + 384, + 498, + 501, + 0, + 384, + 376, + 496, + 498, + 0, + 376, + 370, + 493, + 496, + 0, + 370, + 364, + 488, + 493, + 0, + 364, + 356, + 485, + 488, + 0, + 356, + 353, + 482, + 485, + 0, + 353, + 349, + 478, + 482, + 0, + 349, + 344, + 475, + 478, + 0, + 344, + 337, + 471, + 475, + 0, + 337, + 332, + 467, + 471, + 0, + 332, + 311, + 451, + 467, + 0, + 311, + 308, + 448, + 451, + 0, + 448, + 454, + 527, + 523, + 0, + 454, + 472, + 538, + 527, + 0, + 472, + 477, + 541, + 538, + 0, + 477, + 481, + 543, + 541, + 0, + 481, + 486, + 546, + 543, + 0, + 486, + 490, + 550, + 546, + 0, + 490, + 495, + 553, + 550, + 0, + 495, + 503, + 560, + 553, + 0, + 503, + 508, + 564, + 560, + 0, + 508, + 510, + 566, + 564, + 0, + 510, + 514, + 568, + 566, + 0, + 514, + 516, + 570, + 568, + 0, + 516, + 518, + 572, + 570, + 0, + 518, + 520, + 574, + 572, + 0, + 520, + 519, + 573, + 574, + 0, + 519, + 517, + 571, + 573, + 0, + 517, + 515, + 569, + 571, + 0, + 515, + 512, + 567, + 569, + 0, + 512, + 509, + 565, + 567, + 0, + 509, + 507, + 563, + 565, + 0, + 507, + 499, + 556, + 563, + 0, + 499, + 470, + 536, + 556, + 0, + 470, + 466, + 534, + 536, + 0, + 466, + 462, + 532, + 534, + 0, + 462, + 459, + 530, + 532, + 0, + 459, + 455, + 528, + 530, + 0, + 455, + 450, + 524, + 528, + 0, + 450, + 445, + 521, + 524, + 0, + 445, + 441, + 511, + 521, + 0, + 441, + 438, + 502, + 511, + 0, + 438, + 437, + 492, + 502, + 0, + 437, + 434, + 483, + 492, + 0, + 434, + 430, + 479, + 483, + 0, + 430, + 428, + 474, + 479, + 0, + 428, + 426, + 469, + 474, + 0, + 426, + 424, + 465, + 469, + 0, + 424, + 422, + 460, + 465, + 0, + 422, + 420, + 456, + 460, + 0, + 420, + 402, + 449, + 456, + 0, + 402, + 383, + 444, + 449, + 0, + 383, + 363, + 440, + 444, + 0, + 363, + 334, + 429, + 440, + 0, + 334, + 340, + 432, + 429, + 0, + 340, + 343, + 433, + 432, + 0, + 343, + 377, + 443, + 433, + 0, + 377, + 397, + 446, + 443, + 0, + 397, + 415, + 453, + 446, + 0, + 415, + 421, + 458, + 453, + 0, + 421, + 423, + 463, + 458, + 0, + 423, + 425, + 468, + 463, + 0, + 425, + 427, + 473, + 468, + 0, + 427, + 431, + 480, + 473, + 0, + 431, + 435, + 484, + 480, + 0, + 435, + 436, + 489, + 484, + 0, + 436, + 439, + 506, + 489, + 0, + 439, + 442, + 513, + 506, + 0, + 442, + 447, + 522, + 513, + 0, + 447, + 452, + 526, + 522, + 0, + 452, + 457, + 529, + 526, + 0, + 457, + 461, + 531, + 529, + 0, + 461, + 464, + 533, + 531, + 0, + 464, + 476, + 540, + 533, + 0, + 476, + 487, + 547, + 540, + 0, + 487, + 491, + 549, + 547, + 0, + 491, + 494, + 552, + 549, + 0, + 494, + 497, + 555, + 552, + 0, + 497, + 500, + 558, + 555, + 0, + 500, + 505, + 562, + 558, + 0, + 505, + 504, + 561, + 562, + 0, + 504, + 501, + 559, + 561, + 0, + 501, + 498, + 557, + 559, + 0, + 498, + 496, + 554, + 557, + 0, + 496, + 493, + 551, + 554, + 0, + 493, + 488, + 548, + 551, + 0, + 488, + 485, + 545, + 548, + 0, + 485, + 482, + 544, + 545, + 0, + 482, + 478, + 542, + 544, + 0, + 478, + 475, + 539, + 542, + 0, + 475, + 471, + 537, + 539, + 0, + 471, + 467, + 535, + 537, + 0, + 467, + 451, + 525, + 535, + 0, + 451, + 448, + 523, + 525, + 0, + 523, + 527, + 613, + 609, + 0, + 527, + 538, + 630, + 613, + 0, + 538, + 541, + 635, + 630, + 0, + 541, + 543, + 639, + 635, + 0, + 543, + 546, + 645, + 639, + 0, + 546, + 550, + 648, + 645, + 0, + 550, + 553, + 653, + 648, + 0, + 553, + 560, + 662, + 653, + 0, + 560, + 564, + 666, + 662, + 0, + 564, + 566, + 668, + 666, + 0, + 566, + 568, + 670, + 668, + 0, + 568, + 570, + 674, + 670, + 0, + 570, + 572, + 676, + 674, + 0, + 572, + 574, + 678, + 676, + 0, + 574, + 573, + 677, + 678, + 0, + 573, + 571, + 675, + 677, + 0, + 571, + 569, + 672, + 675, + 0, + 569, + 567, + 669, + 672, + 0, + 567, + 565, + 667, + 669, + 0, + 565, + 563, + 664, + 667, + 0, + 563, + 556, + 656, + 664, + 0, + 556, + 536, + 626, + 656, + 0, + 536, + 534, + 623, + 626, + 0, + 534, + 532, + 620, + 623, + 0, + 532, + 530, + 616, + 620, + 0, + 530, + 528, + 612, + 616, + 0, + 528, + 524, + 608, + 612, + 0, + 524, + 521, + 606, + 608, + 0, + 521, + 511, + 603, + 606, + 0, + 511, + 502, + 599, + 603, + 0, + 502, + 492, + 598, + 599, + 0, + 492, + 483, + 595, + 598, + 0, + 483, + 479, + 593, + 595, + 0, + 479, + 474, + 591, + 593, + 0, + 474, + 469, + 590, + 591, + 0, + 469, + 465, + 588, + 590, + 0, + 465, + 460, + 586, + 588, + 0, + 460, + 456, + 584, + 586, + 0, + 456, + 449, + 582, + 584, + 0, + 449, + 444, + 580, + 582, + 0, + 444, + 440, + 578, + 580, + 0, + 440, + 429, + 575, + 578, + 0, + 429, + 432, + 576, + 575, + 0, + 432, + 433, + 577, + 576, + 0, + 433, + 443, + 579, + 577, + 0, + 443, + 446, + 581, + 579, + 0, + 446, + 453, + 583, + 581, + 0, + 453, + 458, + 585, + 583, + 0, + 458, + 463, + 587, + 585, + 0, + 463, + 468, + 589, + 587, + 0, + 468, + 473, + 592, + 589, + 0, + 473, + 480, + 594, + 592, + 0, + 480, + 484, + 596, + 594, + 0, + 484, + 489, + 597, + 596, + 0, + 489, + 506, + 601, + 597, + 0, + 506, + 513, + 605, + 601, + 0, + 513, + 522, + 607, + 605, + 0, + 522, + 526, + 611, + 607, + 0, + 526, + 529, + 615, + 611, + 0, + 529, + 531, + 618, + 615, + 0, + 531, + 533, + 621, + 618, + 0, + 533, + 540, + 632, + 621, + 0, + 540, + 547, + 644, + 632, + 0, + 547, + 549, + 647, + 644, + 0, + 549, + 552, + 652, + 647, + 0, + 552, + 555, + 655, + 652, + 0, + 555, + 558, + 658, + 655, + 0, + 558, + 562, + 660, + 658, + 0, + 562, + 561, + 661, + 660, + 0, + 561, + 559, + 659, + 661, + 0, + 559, + 557, + 657, + 659, + 0, + 557, + 554, + 654, + 657, + 0, + 554, + 551, + 651, + 654, + 0, + 551, + 548, + 646, + 651, + 0, + 548, + 545, + 643, + 646, + 0, + 545, + 544, + 640, + 643, + 0, + 544, + 542, + 636, + 640, + 0, + 542, + 539, + 633, + 636, + 0, + 539, + 537, + 628, + 633, + 0, + 537, + 535, + 627, + 628, + 0, + 535, + 525, + 610, + 627, + 0, + 525, + 523, + 609, + 610, + 0, + 688, + 609, + 613, + 692, + 0, + 692, + 613, + 630, + 702, + 0, + 702, + 630, + 635, + 705, + 0, + 705, + 635, + 639, + 707, + 0, + 707, + 639, + 645, + 711, + 0, + 711, + 645, + 648, + 714, + 0, + 714, + 648, + 653, + 717, + 0, + 717, + 653, + 662, + 726, + 0, + 726, + 662, + 666, + 728, + 0, + 728, + 666, + 668, + 730, + 0, + 730, + 668, + 670, + 732, + 0, + 732, + 670, + 674, + 734, + 0, + 734, + 674, + 676, + 736, + 0, + 736, + 676, + 678, + 738, + 0, + 738, + 678, + 677, + 737, + 0, + 737, + 677, + 675, + 735, + 0, + 735, + 675, + 672, + 733, + 0, + 733, + 672, + 669, + 731, + 0, + 731, + 669, + 667, + 729, + 0, + 729, + 667, + 664, + 727, + 0, + 727, + 664, + 656, + 720, + 0, + 720, + 656, + 626, + 699, + 0, + 699, + 626, + 623, + 698, + 0, + 698, + 623, + 620, + 696, + 0, + 696, + 620, + 616, + 694, + 0, + 694, + 616, + 612, + 691, + 0, + 691, + 612, + 608, + 687, + 0, + 687, + 608, + 606, + 685, + 0, + 685, + 606, + 603, + 683, + 0, + 683, + 603, + 599, + 681, + 0, + 681, + 599, + 598, + 680, + 0, + 680, + 598, + 595, + 671, + 0, + 671, + 595, + 593, + 663, + 0, + 663, + 593, + 591, + 649, + 0, + 649, + 591, + 590, + 642, + 0, + 642, + 590, + 588, + 638, + 0, + 638, + 588, + 586, + 634, + 0, + 634, + 586, + 584, + 629, + 0, + 629, + 584, + 582, + 624, + 0, + 624, + 582, + 580, + 619, + 0, + 619, + 580, + 578, + 614, + 0, + 614, + 578, + 575, + 600, + 0, + 600, + 575, + 576, + 602, + 0, + 602, + 576, + 577, + 604, + 0, + 604, + 577, + 579, + 617, + 0, + 617, + 579, + 581, + 622, + 0, + 622, + 581, + 583, + 625, + 0, + 625, + 583, + 585, + 631, + 0, + 631, + 585, + 587, + 637, + 0, + 637, + 587, + 589, + 641, + 0, + 641, + 589, + 592, + 650, + 0, + 650, + 592, + 594, + 665, + 0, + 665, + 594, + 596, + 673, + 0, + 673, + 596, + 597, + 679, + 0, + 679, + 597, + 601, + 682, + 0, + 682, + 601, + 605, + 684, + 0, + 684, + 605, + 607, + 686, + 0, + 686, + 607, + 611, + 689, + 0, + 689, + 611, + 615, + 693, + 0, + 693, + 615, + 618, + 695, + 0, + 695, + 618, + 621, + 697, + 0, + 697, + 621, + 632, + 703, + 0, + 703, + 632, + 644, + 710, + 0, + 710, + 644, + 647, + 713, + 0, + 713, + 647, + 652, + 715, + 0, + 715, + 652, + 655, + 719, + 0, + 719, + 655, + 658, + 722, + 0, + 722, + 658, + 660, + 724, + 0, + 724, + 660, + 661, + 725, + 0, + 725, + 661, + 659, + 723, + 0, + 723, + 659, + 657, + 721, + 0, + 721, + 657, + 654, + 718, + 0, + 718, + 654, + 651, + 716, + 0, + 716, + 651, + 646, + 712, + 0, + 712, + 646, + 643, + 709, + 0, + 709, + 643, + 640, + 708, + 0, + 708, + 640, + 636, + 706, + 0, + 706, + 636, + 633, + 704, + 0, + 704, + 633, + 628, + 701, + 0, + 701, + 628, + 627, + 700, + 0, + 700, + 627, + 610, + 690, + 0, + 690, + 610, + 609, + 688, + 0, + 739, + 742, + 742, + 0, + 742, + 742, + 744, + 744, + 0, + 744, + 744, + 745, + 0, + 748, + 751, + 751, + 0, + 751, + 751, + 754, + 0, + 776, + 775, + 775, + 0, + 775, + 775, + 774, + 0, + 768, + 766, + 766, + 0, + 766, + 766, + 764, + 0, + 758, + 756, + 756, + 0, + 756, + 756, + 753, + 753, + 0, + 753, + 753, + 749, + 749, + 0, + 749, + 749, + 746, + 0, + 761, + 763, + 763, + 0, + 763, + 763, + 765, + 0, + 767, + 769, + 769, + 0, + 769, + 769, + 770, + 770, + 0, + 770, + 770, + 772, + 0, + 772, + 773, + 773, + 0, + 773, + 773, + 771, + 0, + 762, + 760, + 760, + 0, + 760, + 760, + 759, + 0, + 759, + 757, + 757, + 0, + 757, + 757, + 755, + 0, + 752, + 750, + 750, + 0, + 750, + 750, + 747, + 0, + 743, + 741, + 741, + 0, + 741, + 741, + 740, + 0, + 851, + 849, + 849, + 0, + 849, + 849, + 848, + 0, + 807, + 805, + 805, + 0, + 805, + 805, + 803, + 0, + 801, + 800, + 800, + 0, + 800, + 800, + 797, + 0, + 786, + 784, + 784, + 0, + 784, + 784, + 782, + 0, + 791, + 794, + 794, + 0, + 794, + 794, + 796, + 0, + 798, + 799, + 799, + 0, + 799, + 799, + 802, + 0, + 808, + 812, + 812, + 0, + 812, + 812, + 815, + 0, + 843, + 842, + 842, + 0, + 842, + 842, + 839, + 0, + 836, + 833, + 833, + 0, + 833, + 833, + 830, + 0, + 903, + 908, + 908, + 0, + 908, + 908, + 922, + 922, + 0, + 922, + 922, + 929, + 929, + 0, + 929, + 929, + 932, + 932, + 0, + 932, + 932, + 934, + 934, + 0, + 934, + 934, + 936, + 936, + 0, + 936, + 936, + 938, + 0, + 939, + 937, + 937, + 0, + 937, + 937, + 935, + 0, + 933, + 931, + 931, + 0, + 931, + 931, + 930, + 930, + 0, + 930, + 930, + 925, + 0, + 925, + 918, + 918, + 0, + 918, + 918, + 915, + 915, + 0, + 915, + 915, + 911, + 911, + 0, + 911, + 911, + 909, + 909, + 0, + 909, + 909, + 906, + 906, + 0, + 906, + 906, + 901, + 0, + 901, + 898, + 898, + 0, + 898, + 898, + 896, + 896, + 0, + 896, + 896, + 894, + 894, + 0, + 894, + 894, + 892, + 892, + 0, + 892, + 892, + 890, + 890, + 0, + 890, + 890, + 888, + 888, + 0, + 888, + 888, + 887, + 0, + 887, + 885, + 885, + 0, + 885, + 885, + 883, + 883, + 0, + 883, + 883, + 881, + 881, + 0, + 881, + 881, + 879, + 879, + 0, + 879, + 879, + 877, + 0, + 877, + 875, + 875, + 0, + 875, + 875, + 873, + 873, + 0, + 873, + 873, + 872, + 872, + 0, + 872, + 872, + 870, + 870, + 0, + 870, + 870, + 868, + 868, + 0, + 868, + 868, + 866, + 866, + 0, + 866, + 866, + 864, + 0, + 864, + 863, + 863, + 0, + 863, + 863, + 860, + 860, + 0, + 860, + 860, + 861, + 861, + 0, + 861, + 861, + 862, + 862, + 0, + 862, + 862, + 865, + 865, + 0, + 865, + 865, + 867, + 867, + 0, + 867, + 867, + 869, + 869, + 0, + 869, + 869, + 871, + 0, + 874, + 876, + 876, + 0, + 876, + 876, + 878, + 878, + 0, + 878, + 878, + 880, + 880, + 0, + 880, + 880, + 882, + 0, + 882, + 884, + 884, + 0, + 884, + 884, + 886, + 886, + 0, + 886, + 886, + 889, + 889, + 0, + 889, + 889, + 891, + 891, + 0, + 891, + 891, + 893, + 893, + 0, + 893, + 893, + 895, + 0, + 895, + 897, + 897, + 0, + 897, + 897, + 899, + 899, + 0, + 899, + 899, + 900, + 900, + 0, + 900, + 900, + 902, + 0, + 902, + 905, + 905, + 0, + 905, + 905, + 907, + 907, + 0, + 907, + 907, + 910, + 910, + 0, + 910, + 910, + 913, + 913, + 0, + 913, + 913, + 916, + 916, + 0, + 916, + 916, + 919, + 919, + 0, + 919, + 919, + 921, + 921, + 0, + 921, + 921, + 924, + 924, + 0, + 924, + 924, + 927, + 0, + 928, + 926, + 926, + 0, + 926, + 926, + 923, + 923, + 0, + 923, + 923, + 920, + 920, + 0, + 920, + 920, + 917, + 917, + 0, + 917, + 917, + 914, + 914, + 0, + 914, + 914, + 912, + 912, + 0, + 912, + 912, + 904, + 0, + 978, + 982, + 1081, + 1075, + 0, + 982, + 994, + 1094, + 1081, + 0, + 994, + 998, + 1098, + 1094, + 0, + 998, + 1004, + 1104, + 1098, + 0, + 1004, + 1010, + 1108, + 1104, + 0, + 1010, + 1015, + 1115, + 1108, + 0, + 1015, + 1026, + 1123, + 1115, + 0, + 1026, + 1029, + 1127, + 1123, + 0, + 1029, + 1033, + 1133, + 1127, + 0, + 1033, + 1036, + 1136, + 1133, + 0, + 1036, + 1038, + 1138, + 1136, + 0, + 1038, + 1040, + 1142, + 1138, + 0, + 1040, + 1042, + 1144, + 1142, + 0, + 1042, + 1041, + 1143, + 1144, + 0, + 1041, + 1039, + 1141, + 1143, + 0, + 1039, + 1037, + 1137, + 1141, + 0, + 1037, + 1035, + 1135, + 1137, + 0, + 1035, + 1034, + 1132, + 1135, + 0, + 1034, + 1030, + 1128, + 1132, + 0, + 1030, + 1023, + 1120, + 1128, + 0, + 1023, + 1013, + 1112, + 1120, + 0, + 1013, + 986, + 1086, + 1112, + 0, + 986, + 984, + 1083, + 1086, + 0, + 984, + 981, + 1078, + 1083, + 0, + 981, + 977, + 1072, + 1078, + 0, + 977, + 973, + 1070, + 1072, + 0, + 973, + 970, + 1066, + 1070, + 0, + 970, + 968, + 1062, + 1066, + 0, + 968, + 966, + 1058, + 1062, + 0, + 966, + 964, + 1054, + 1058, + 0, + 964, + 962, + 1050, + 1054, + 0, + 962, + 960, + 1046, + 1050, + 0, + 960, + 958, + 1043, + 1046, + 0, + 958, + 956, + 1031, + 1043, + 0, + 956, + 955, + 1019, + 1031, + 0, + 955, + 953, + 1009, + 1019, + 0, + 953, + 951, + 1001, + 1009, + 0, + 951, + 949, + 997, + 1001, + 0, + 949, + 947, + 992, + 997, + 0, + 947, + 945, + 988, + 992, + 0, + 945, + 943, + 985, + 988, + 0, + 943, + 940, + 971, + 985, + 0, + 940, + 941, + 974, + 971, + 0, + 941, + 942, + 975, + 974, + 0, + 942, + 944, + 987, + 975, + 0, + 944, + 946, + 991, + 987, + 0, + 946, + 948, + 995, + 991, + 0, + 948, + 950, + 1000, + 995, + 0, + 950, + 952, + 1005, + 1000, + 0, + 952, + 954, + 1017, + 1005, + 0, + 954, + 957, + 1032, + 1017, + 0, + 957, + 959, + 1044, + 1032, + 0, + 959, + 961, + 1047, + 1044, + 0, + 961, + 963, + 1051, + 1047, + 0, + 963, + 965, + 1055, + 1051, + 0, + 965, + 967, + 1059, + 1055, + 0, + 967, + 969, + 1063, + 1059, + 0, + 969, + 972, + 1067, + 1063, + 0, + 972, + 976, + 1071, + 1067, + 0, + 976, + 980, + 1076, + 1071, + 0, + 980, + 983, + 1080, + 1076, + 0, + 983, + 989, + 1089, + 1080, + 0, + 989, + 1002, + 1101, + 1089, + 0, + 1002, + 1006, + 1106, + 1101, + 0, + 1006, + 1011, + 1110, + 1106, + 0, + 1011, + 1014, + 1114, + 1110, + 0, + 1014, + 1020, + 1117, + 1114, + 0, + 1020, + 1025, + 1122, + 1117, + 0, + 1025, + 1028, + 1125, + 1122, + 0, + 1028, + 1027, + 1124, + 1125, + 0, + 1027, + 1024, + 1121, + 1124, + 0, + 1024, + 1021, + 1118, + 1121, + 0, + 1021, + 1016, + 1116, + 1118, + 0, + 1016, + 1012, + 1111, + 1116, + 0, + 1012, + 1007, + 1107, + 1111, + 0, + 1007, + 1003, + 1103, + 1107, + 0, + 1003, + 999, + 1099, + 1103, + 0, + 999, + 996, + 1096, + 1099, + 0, + 996, + 993, + 1093, + 1096, + 0, + 993, + 990, + 1090, + 1093, + 0, + 990, + 979, + 1077, + 1090, + 0, + 979, + 978, + 1075, + 1077, + 0, + 1075, + 1081, + 1140, + 1129, + 0, + 1081, + 1094, + 1150, + 1140, + 0, + 1094, + 1098, + 1152, + 1150, + 0, + 1098, + 1104, + 1156, + 1152, + 0, + 1104, + 1108, + 1159, + 1156, + 0, + 1108, + 1115, + 1164, + 1159, + 0, + 1115, + 1123, + 1171, + 1164, + 0, + 1123, + 1127, + 1175, + 1171, + 0, + 1127, + 1133, + 1177, + 1175, + 0, + 1133, + 1136, + 1179, + 1177, + 0, + 1136, + 1138, + 1181, + 1179, + 0, + 1138, + 1142, + 1183, + 1181, + 0, + 1142, + 1144, + 1185, + 1183, + 0, + 1144, + 1143, + 1184, + 1185, + 0, + 1143, + 1141, + 1182, + 1184, + 0, + 1141, + 1137, + 1180, + 1182, + 0, + 1137, + 1135, + 1178, + 1180, + 0, + 1135, + 1132, + 1176, + 1178, + 0, + 1132, + 1128, + 1174, + 1176, + 0, + 1128, + 1120, + 1168, + 1174, + 0, + 1120, + 1112, + 1162, + 1168, + 0, + 1112, + 1086, + 1146, + 1162, + 0, + 1086, + 1083, + 1145, + 1146, + 0, + 1083, + 1078, + 1134, + 1145, + 0, + 1078, + 1072, + 1126, + 1134, + 0, + 1072, + 1070, + 1113, + 1126, + 0, + 1070, + 1066, + 1105, + 1113, + 0, + 1066, + 1062, + 1100, + 1105, + 0, + 1062, + 1058, + 1095, + 1100, + 0, + 1058, + 1054, + 1091, + 1095, + 0, + 1054, + 1050, + 1087, + 1091, + 0, + 1050, + 1046, + 1084, + 1087, + 0, + 1046, + 1043, + 1079, + 1084, + 0, + 1043, + 1031, + 1073, + 1079, + 0, + 1031, + 1019, + 1069, + 1073, + 0, + 1019, + 1009, + 1065, + 1069, + 0, + 1009, + 1001, + 1061, + 1065, + 0, + 1001, + 997, + 1057, + 1061, + 0, + 997, + 992, + 1053, + 1057, + 0, + 992, + 988, + 1049, + 1053, + 0, + 988, + 985, + 1045, + 1049, + 0, + 985, + 971, + 1008, + 1045, + 0, + 971, + 974, + 1018, + 1008, + 0, + 974, + 975, + 1022, + 1018, + 0, + 975, + 987, + 1048, + 1022, + 0, + 987, + 991, + 1052, + 1048, + 0, + 991, + 995, + 1056, + 1052, + 0, + 995, + 1000, + 1060, + 1056, + 0, + 1000, + 1005, + 1064, + 1060, + 0, + 1005, + 1017, + 1068, + 1064, + 0, + 1017, + 1032, + 1074, + 1068, + 0, + 1032, + 1044, + 1082, + 1074, + 0, + 1044, + 1047, + 1085, + 1082, + 0, + 1047, + 1051, + 1088, + 1085, + 0, + 1051, + 1055, + 1092, + 1088, + 0, + 1055, + 1059, + 1097, + 1092, + 0, + 1059, + 1063, + 1102, + 1097, + 0, + 1063, + 1067, + 1109, + 1102, + 0, + 1067, + 1071, + 1119, + 1109, + 0, + 1071, + 1076, + 1130, + 1119, + 0, + 1076, + 1080, + 1139, + 1130, + 0, + 1080, + 1089, + 1147, + 1139, + 0, + 1089, + 1101, + 1154, + 1147, + 0, + 1101, + 1106, + 1157, + 1154, + 0, + 1106, + 1110, + 1160, + 1157, + 0, + 1110, + 1114, + 1163, + 1160, + 0, + 1114, + 1117, + 1166, + 1163, + 0, + 1117, + 1122, + 1170, + 1166, + 0, + 1122, + 1125, + 1173, + 1170, + 0, + 1125, + 1124, + 1172, + 1173, + 0, + 1124, + 1121, + 1169, + 1172, + 0, + 1121, + 1118, + 1167, + 1169, + 0, + 1118, + 1116, + 1165, + 1167, + 0, + 1116, + 1111, + 1161, + 1165, + 0, + 1111, + 1107, + 1158, + 1161, + 0, + 1107, + 1103, + 1155, + 1158, + 0, + 1103, + 1099, + 1153, + 1155, + 0, + 1099, + 1096, + 1151, + 1153, + 0, + 1096, + 1093, + 1149, + 1151, + 0, + 1093, + 1090, + 1148, + 1149, + 0, + 1090, + 1077, + 1131, + 1148, + 0, + 1077, + 1075, + 1129, + 1131, + 0, + 1129, + 1140, + 1232, + 1226, + 0, + 1140, + 1150, + 1244, + 1232, + 0, + 1150, + 1152, + 1248, + 1244, + 0, + 1152, + 1156, + 1254, + 1248, + 0, + 1156, + 1159, + 1260, + 1254, + 0, + 1159, + 1164, + 1264, + 1260, + 0, + 1164, + 1171, + 1274, + 1264, + 0, + 1171, + 1175, + 1277, + 1274, + 0, + 1175, + 1177, + 1280, + 1277, + 0, + 1177, + 1179, + 1283, + 1280, + 0, + 1179, + 1181, + 1285, + 1283, + 0, + 1181, + 1183, + 1287, + 1285, + 0, + 1183, + 1185, + 1289, + 1287, + 0, + 1185, + 1184, + 1288, + 1289, + 0, + 1184, + 1182, + 1286, + 1288, + 0, + 1182, + 1180, + 1284, + 1286, + 0, + 1180, + 1178, + 1282, + 1284, + 0, + 1178, + 1176, + 1278, + 1282, + 0, + 1176, + 1174, + 1276, + 1278, + 0, + 1174, + 1168, + 1269, + 1276, + 0, + 1168, + 1162, + 1261, + 1269, + 0, + 1162, + 1146, + 1235, + 1261, + 0, + 1146, + 1145, + 1233, + 1235, + 0, + 1145, + 1134, + 1227, + 1233, + 0, + 1134, + 1126, + 1223, + 1227, + 0, + 1126, + 1113, + 1221, + 1223, + 0, + 1113, + 1105, + 1219, + 1221, + 0, + 1105, + 1100, + 1215, + 1219, + 0, + 1100, + 1095, + 1212, + 1215, + 0, + 1095, + 1091, + 1210, + 1212, + 0, + 1091, + 1087, + 1208, + 1210, + 0, + 1087, + 1084, + 1206, + 1208, + 0, + 1084, + 1079, + 1204, + 1206, + 0, + 1079, + 1073, + 1202, + 1204, + 0, + 1073, + 1069, + 1201, + 1202, + 0, + 1069, + 1065, + 1199, + 1201, + 0, + 1065, + 1061, + 1197, + 1199, + 0, + 1061, + 1057, + 1195, + 1197, + 0, + 1057, + 1053, + 1193, + 1195, + 0, + 1053, + 1049, + 1191, + 1193, + 0, + 1049, + 1045, + 1189, + 1191, + 0, + 1045, + 1008, + 1186, + 1189, + 0, + 1008, + 1018, + 1187, + 1186, + 0, + 1018, + 1022, + 1188, + 1187, + 0, + 1022, + 1048, + 1190, + 1188, + 0, + 1048, + 1052, + 1192, + 1190, + 0, + 1052, + 1056, + 1194, + 1192, + 0, + 1056, + 1060, + 1196, + 1194, + 0, + 1060, + 1064, + 1198, + 1196, + 0, + 1064, + 1068, + 1200, + 1198, + 0, + 1068, + 1074, + 1203, + 1200, + 0, + 1074, + 1082, + 1205, + 1203, + 0, + 1082, + 1085, + 1207, + 1205, + 0, + 1085, + 1088, + 1209, + 1207, + 0, + 1088, + 1092, + 1211, + 1209, + 0, + 1092, + 1097, + 1213, + 1211, + 0, + 1097, + 1102, + 1217, + 1213, + 0, + 1102, + 1109, + 1220, + 1217, + 0, + 1109, + 1119, + 1222, + 1220, + 0, + 1119, + 1130, + 1225, + 1222, + 0, + 1130, + 1139, + 1229, + 1225, + 0, + 1139, + 1147, + 1239, + 1229, + 0, + 1147, + 1154, + 1252, + 1239, + 0, + 1154, + 1157, + 1255, + 1252, + 0, + 1157, + 1160, + 1259, + 1255, + 0, + 1160, + 1163, + 1263, + 1259, + 0, + 1163, + 1166, + 1266, + 1263, + 0, + 1166, + 1170, + 1270, + 1266, + 0, + 1170, + 1173, + 1273, + 1270, + 0, + 1173, + 1172, + 1272, + 1273, + 0, + 1172, + 1169, + 1271, + 1272, + 0, + 1169, + 1167, + 1267, + 1271, + 0, + 1167, + 1165, + 1265, + 1267, + 0, + 1165, + 1161, + 1262, + 1265, + 0, + 1161, + 1158, + 1256, + 1262, + 0, + 1158, + 1155, + 1253, + 1256, + 0, + 1155, + 1153, + 1249, + 1253, + 0, + 1153, + 1151, + 1246, + 1249, + 0, + 1151, + 1149, + 1243, + 1246, + 0, + 1149, + 1148, + 1241, + 1243, + 0, + 1148, + 1131, + 1228, + 1241, + 0, + 1131, + 1129, + 1226, + 1228, + 0, + 1226, + 1232, + 1308, + 1304, + 0, + 1232, + 1244, + 1314, + 1308, + 0, + 1244, + 1248, + 1316, + 1314, + 0, + 1248, + 1254, + 1320, + 1316, + 0, + 1254, + 1260, + 1324, + 1320, + 0, + 1260, + 1264, + 1329, + 1324, + 0, + 1264, + 1274, + 1337, + 1329, + 0, + 1274, + 1277, + 1339, + 1337, + 0, + 1277, + 1280, + 1341, + 1339, + 0, + 1280, + 1283, + 1343, + 1341, + 0, + 1283, + 1285, + 1345, + 1343, + 0, + 1285, + 1287, + 1347, + 1345, + 0, + 1287, + 1289, + 1349, + 1347, + 0, + 1289, + 1288, + 1348, + 1349, + 0, + 1288, + 1286, + 1346, + 1348, + 0, + 1286, + 1284, + 1344, + 1346, + 0, + 1284, + 1282, + 1342, + 1344, + 0, + 1282, + 1278, + 1340, + 1342, + 0, + 1278, + 1276, + 1338, + 1340, + 0, + 1276, + 1269, + 1332, + 1338, + 0, + 1269, + 1261, + 1325, + 1332, + 0, + 1261, + 1235, + 1310, + 1325, + 0, + 1235, + 1233, + 1309, + 1310, + 0, + 1233, + 1227, + 1305, + 1309, + 0, + 1227, + 1223, + 1302, + 1305, + 0, + 1223, + 1221, + 1300, + 1302, + 0, + 1221, + 1219, + 1298, + 1300, + 0, + 1219, + 1215, + 1296, + 1298, + 0, + 1215, + 1212, + 1294, + 1296, + 0, + 1212, + 1210, + 1292, + 1294, + 0, + 1210, + 1208, + 1290, + 1292, + 0, + 1208, + 1206, + 1279, + 1290, + 0, + 1206, + 1204, + 1268, + 1279, + 0, + 1204, + 1202, + 1257, + 1268, + 0, + 1202, + 1201, + 1251, + 1257, + 0, + 1201, + 1199, + 1247, + 1251, + 0, + 1199, + 1197, + 1242, + 1247, + 0, + 1197, + 1195, + 1238, + 1242, + 0, + 1195, + 1193, + 1236, + 1238, + 0, + 1193, + 1191, + 1231, + 1236, + 0, + 1191, + 1189, + 1224, + 1231, + 0, + 1189, + 1186, + 1214, + 1224, + 0, + 1186, + 1187, + 1216, + 1214, + 0, + 1187, + 1188, + 1218, + 1216, + 0, + 1188, + 1190, + 1230, + 1218, + 0, + 1190, + 1192, + 1234, + 1230, + 0, + 1192, + 1194, + 1237, + 1234, + 0, + 1194, + 1196, + 1240, + 1237, + 0, + 1196, + 1198, + 1245, + 1240, + 0, + 1198, + 1200, + 1250, + 1245, + 0, + 1200, + 1203, + 1258, + 1250, + 0, + 1203, + 1205, + 1275, + 1258, + 0, + 1205, + 1207, + 1281, + 1275, + 0, + 1207, + 1209, + 1291, + 1281, + 0, + 1209, + 1211, + 1293, + 1291, + 0, + 1211, + 1213, + 1295, + 1293, + 0, + 1213, + 1217, + 1297, + 1295, + 0, + 1217, + 1220, + 1299, + 1297, + 0, + 1220, + 1222, + 1301, + 1299, + 0, + 1222, + 1225, + 1303, + 1301, + 0, + 1225, + 1229, + 1307, + 1303, + 0, + 1229, + 1239, + 1311, + 1307, + 0, + 1239, + 1252, + 1318, + 1311, + 0, + 1252, + 1255, + 1321, + 1318, + 0, + 1255, + 1259, + 1323, + 1321, + 0, + 1259, + 1263, + 1327, + 1323, + 0, + 1263, + 1266, + 1330, + 1327, + 0, + 1266, + 1270, + 1333, + 1330, + 0, + 1270, + 1273, + 1336, + 1333, + 0, + 1273, + 1272, + 1335, + 1336, + 0, + 1272, + 1271, + 1334, + 1335, + 0, + 1271, + 1267, + 1331, + 1334, + 0, + 1267, + 1265, + 1328, + 1331, + 0, + 1265, + 1262, + 1326, + 1328, + 0, + 1262, + 1256, + 1322, + 1326, + 0, + 1256, + 1253, + 1319, + 1322, + 0, + 1253, + 1249, + 1317, + 1319, + 0, + 1249, + 1246, + 1315, + 1317, + 0, + 1246, + 1243, + 1313, + 1315, + 0, + 1243, + 1241, + 1312, + 1313, + 0, + 1241, + 1228, + 1306, + 1312, + 0, + 1228, + 1226, + 1304, + 1306, + 0, + 1304, + 1308, + 1391, + 1387, + 0, + 1308, + 1314, + 1399, + 1391, + 0, + 1314, + 1316, + 1401, + 1399, + 0, + 1316, + 1320, + 1405, + 1401, + 0, + 1320, + 1324, + 1410, + 1405, + 0, + 1324, + 1329, + 1415, + 1410, + 0, + 1329, + 1337, + 1425, + 1415, + 0, + 1337, + 1339, + 1427, + 1425, + 0, + 1339, + 1341, + 1431, + 1427, + 0, + 1341, + 1343, + 1433, + 1431, + 0, + 1343, + 1345, + 1435, + 1433, + 0, + 1345, + 1347, + 1437, + 1435, + 0, + 1347, + 1349, + 1439, + 1437, + 0, + 1349, + 1348, + 1438, + 1439, + 0, + 1348, + 1346, + 1436, + 1438, + 0, + 1346, + 1344, + 1434, + 1436, + 0, + 1344, + 1342, + 1432, + 1434, + 0, + 1342, + 1340, + 1429, + 1432, + 0, + 1340, + 1338, + 1426, + 1429, + 0, + 1338, + 1332, + 1417, + 1426, + 0, + 1332, + 1325, + 1411, + 1417, + 0, + 1325, + 1310, + 1392, + 1411, + 0, + 1310, + 1309, + 1390, + 1392, + 0, + 1309, + 1305, + 1386, + 1390, + 0, + 1305, + 1302, + 1384, + 1386, + 0, + 1302, + 1300, + 1382, + 1384, + 0, + 1300, + 1298, + 1380, + 1382, + 0, + 1298, + 1296, + 1378, + 1380, + 0, + 1296, + 1294, + 1376, + 1378, + 0, + 1294, + 1292, + 1374, + 1376, + 0, + 1292, + 1290, + 1372, + 1374, + 0, + 1290, + 1279, + 1370, + 1372, + 0, + 1279, + 1268, + 1368, + 1370, + 0, + 1268, + 1257, + 1366, + 1368, + 0, + 1257, + 1251, + 1365, + 1366, + 0, + 1251, + 1247, + 1363, + 1365, + 0, + 1247, + 1242, + 1361, + 1363, + 0, + 1242, + 1238, + 1359, + 1361, + 0, + 1238, + 1236, + 1357, + 1359, + 0, + 1236, + 1231, + 1355, + 1357, + 0, + 1231, + 1224, + 1353, + 1355, + 0, + 1224, + 1214, + 1350, + 1353, + 0, + 1214, + 1216, + 1351, + 1350, + 0, + 1216, + 1218, + 1352, + 1351, + 0, + 1218, + 1230, + 1354, + 1352, + 0, + 1230, + 1234, + 1356, + 1354, + 0, + 1234, + 1237, + 1358, + 1356, + 0, + 1237, + 1240, + 1360, + 1358, + 0, + 1240, + 1245, + 1362, + 1360, + 0, + 1245, + 1250, + 1364, + 1362, + 0, + 1250, + 1258, + 1367, + 1364, + 0, + 1258, + 1275, + 1369, + 1367, + 0, + 1275, + 1281, + 1371, + 1369, + 0, + 1281, + 1291, + 1373, + 1371, + 0, + 1291, + 1293, + 1375, + 1373, + 0, + 1293, + 1295, + 1377, + 1375, + 0, + 1295, + 1297, + 1379, + 1377, + 0, + 1297, + 1299, + 1381, + 1379, + 0, + 1299, + 1301, + 1383, + 1381, + 0, + 1301, + 1303, + 1385, + 1383, + 0, + 1303, + 1307, + 1389, + 1385, + 0, + 1307, + 1311, + 1393, + 1389, + 0, + 1311, + 1318, + 1403, + 1393, + 0, + 1318, + 1321, + 1406, + 1403, + 0, + 1321, + 1323, + 1409, + 1406, + 0, + 1323, + 1327, + 1413, + 1409, + 0, + 1327, + 1330, + 1416, + 1413, + 0, + 1330, + 1333, + 1421, + 1416, + 0, + 1333, + 1336, + 1424, + 1421, + 0, + 1336, + 1335, + 1423, + 1424, + 0, + 1335, + 1334, + 1422, + 1423, + 0, + 1334, + 1331, + 1420, + 1422, + 0, + 1331, + 1328, + 1414, + 1420, + 0, + 1328, + 1326, + 1412, + 1414, + 0, + 1326, + 1322, + 1407, + 1412, + 0, + 1322, + 1319, + 1404, + 1407, + 0, + 1319, + 1317, + 1402, + 1404, + 0, + 1317, + 1315, + 1400, + 1402, + 0, + 1315, + 1313, + 1396, + 1400, + 0, + 1313, + 1312, + 1395, + 1396, + 0, + 1312, + 1306, + 1388, + 1395, + 0, + 1306, + 1304, + 1387, + 1388, + 0, + 1387, + 1391, + 1473, + 1469, + 0, + 1391, + 1399, + 1478, + 1473, + 0, + 1399, + 1401, + 1480, + 1478, + 0, + 1401, + 1405, + 1484, + 1480, + 0, + 1405, + 1410, + 1489, + 1484, + 0, + 1410, + 1415, + 1493, + 1489, + 0, + 1415, + 1425, + 1501, + 1493, + 0, + 1425, + 1427, + 1503, + 1501, + 0, + 1427, + 1431, + 1505, + 1503, + 0, + 1431, + 1433, + 1507, + 1505, + 0, + 1433, + 1435, + 1509, + 1507, + 0, + 1435, + 1437, + 1511, + 1509, + 0, + 1437, + 1439, + 1513, + 1511, + 0, + 1439, + 1438, + 1512, + 1513, + 0, + 1438, + 1436, + 1510, + 1512, + 0, + 1436, + 1434, + 1508, + 1510, + 0, + 1434, + 1432, + 1506, + 1508, + 0, + 1432, + 1429, + 1504, + 1506, + 0, + 1429, + 1426, + 1502, + 1504, + 0, + 1426, + 1417, + 1495, + 1502, + 0, + 1417, + 1411, + 1488, + 1495, + 0, + 1411, + 1392, + 1474, + 1488, + 0, + 1392, + 1390, + 1472, + 1474, + 0, + 1390, + 1386, + 1468, + 1472, + 0, + 1386, + 1384, + 1466, + 1468, + 0, + 1384, + 1382, + 1464, + 1466, + 0, + 1382, + 1380, + 1462, + 1464, + 0, + 1380, + 1378, + 1460, + 1462, + 0, + 1378, + 1376, + 1458, + 1460, + 0, + 1376, + 1374, + 1456, + 1458, + 0, + 1374, + 1372, + 1454, + 1456, + 0, + 1372, + 1370, + 1452, + 1454, + 0, + 1370, + 1368, + 1450, + 1452, + 0, + 1368, + 1366, + 1448, + 1450, + 0, + 1366, + 1365, + 1447, + 1448, + 0, + 1365, + 1363, + 1445, + 1447, + 0, + 1363, + 1361, + 1443, + 1445, + 0, + 1361, + 1359, + 1441, + 1443, + 0, + 1359, + 1357, + 1430, + 1441, + 0, + 1357, + 1355, + 1418, + 1430, + 0, + 1355, + 1353, + 1408, + 1418, + 0, + 1353, + 1350, + 1394, + 1408, + 0, + 1350, + 1351, + 1397, + 1394, + 0, + 1351, + 1352, + 1398, + 1397, + 0, + 1352, + 1354, + 1419, + 1398, + 0, + 1354, + 1356, + 1428, + 1419, + 0, + 1356, + 1358, + 1440, + 1428, + 0, + 1358, + 1360, + 1442, + 1440, + 0, + 1360, + 1362, + 1444, + 1442, + 0, + 1362, + 1364, + 1446, + 1444, + 0, + 1364, + 1367, + 1449, + 1446, + 0, + 1367, + 1369, + 1451, + 1449, + 0, + 1369, + 1371, + 1453, + 1451, + 0, + 1371, + 1373, + 1455, + 1453, + 0, + 1373, + 1375, + 1457, + 1455, + 0, + 1375, + 1377, + 1459, + 1457, + 0, + 1377, + 1379, + 1461, + 1459, + 0, + 1379, + 1381, + 1463, + 1461, + 0, + 1381, + 1383, + 1465, + 1463, + 0, + 1383, + 1385, + 1467, + 1465, + 0, + 1385, + 1389, + 1471, + 1467, + 0, + 1389, + 1393, + 1475, + 1471, + 0, + 1393, + 1403, + 1482, + 1475, + 0, + 1403, + 1406, + 1485, + 1482, + 0, + 1406, + 1409, + 1487, + 1485, + 0, + 1409, + 1413, + 1491, + 1487, + 0, + 1413, + 1416, + 1494, + 1491, + 0, + 1416, + 1421, + 1497, + 1494, + 0, + 1421, + 1424, + 1499, + 1497, + 0, + 1424, + 1423, + 1500, + 1499, + 0, + 1423, + 1422, + 1498, + 1500, + 0, + 1422, + 1420, + 1496, + 1498, + 0, + 1420, + 1414, + 1492, + 1496, + 0, + 1414, + 1412, + 1490, + 1492, + 0, + 1412, + 1407, + 1486, + 1490, + 0, + 1407, + 1404, + 1483, + 1486, + 0, + 1404, + 1402, + 1481, + 1483, + 0, + 1402, + 1400, + 1479, + 1481, + 0, + 1400, + 1396, + 1477, + 1479, + 0, + 1396, + 1395, + 1476, + 1477, + 0, + 1395, + 1388, + 1470, + 1476, + 0, + 1388, + 1387, + 1469, + 1470, + 0, + 1469, + 1473, + 1555, + 1551, + 0, + 1473, + 1478, + 1560, + 1555, + 0, + 1478, + 1480, + 1562, + 1560, + 0, + 1480, + 1484, + 1566, + 1562, + 0, + 1484, + 1489, + 1571, + 1566, + 0, + 1489, + 1493, + 1576, + 1571, + 0, + 1493, + 1501, + 1583, + 1576, + 0, + 1501, + 1503, + 1585, + 1583, + 0, + 1503, + 1505, + 1587, + 1585, + 0, + 1505, + 1507, + 1589, + 1587, + 0, + 1507, + 1509, + 1591, + 1589, + 0, + 1509, + 1511, + 1593, + 1591, + 0, + 1511, + 1513, + 1595, + 1593, + 0, + 1513, + 1512, + 1594, + 1595, + 0, + 1512, + 1510, + 1592, + 1594, + 0, + 1510, + 1508, + 1590, + 1592, + 0, + 1508, + 1506, + 1588, + 1590, + 0, + 1506, + 1504, + 1586, + 1588, + 0, + 1504, + 1502, + 1584, + 1586, + 0, + 1502, + 1495, + 1577, + 1584, + 0, + 1495, + 1488, + 1570, + 1577, + 0, + 1488, + 1474, + 1556, + 1570, + 0, + 1474, + 1472, + 1554, + 1556, + 0, + 1472, + 1468, + 1550, + 1554, + 0, + 1468, + 1466, + 1548, + 1550, + 0, + 1466, + 1464, + 1546, + 1548, + 0, + 1464, + 1462, + 1544, + 1546, + 0, + 1462, + 1460, + 1542, + 1544, + 0, + 1460, + 1458, + 1540, + 1542, + 0, + 1458, + 1456, + 1538, + 1540, + 0, + 1456, + 1454, + 1536, + 1538, + 0, + 1454, + 1452, + 1534, + 1536, + 0, + 1452, + 1450, + 1532, + 1534, + 0, + 1450, + 1448, + 1530, + 1532, + 0, + 1448, + 1447, + 1529, + 1530, + 0, + 1447, + 1445, + 1527, + 1529, + 0, + 1445, + 1443, + 1525, + 1527, + 0, + 1443, + 1441, + 1523, + 1525, + 0, + 1441, + 1430, + 1521, + 1523, + 0, + 1430, + 1418, + 1518, + 1521, + 0, + 1418, + 1408, + 1517, + 1518, + 0, + 1408, + 1394, + 1514, + 1517, + 0, + 1394, + 1397, + 1515, + 1514, + 0, + 1397, + 1398, + 1516, + 1515, + 0, + 1398, + 1419, + 1519, + 1516, + 0, + 1419, + 1428, + 1520, + 1519, + 0, + 1428, + 1440, + 1522, + 1520, + 0, + 1440, + 1442, + 1524, + 1522, + 0, + 1442, + 1444, + 1526, + 1524, + 0, + 1444, + 1446, + 1528, + 1526, + 0, + 1446, + 1449, + 1531, + 1528, + 0, + 1449, + 1451, + 1533, + 1531, + 0, + 1451, + 1453, + 1535, + 1533, + 0, + 1453, + 1455, + 1537, + 1535, + 0, + 1455, + 1457, + 1539, + 1537, + 0, + 1457, + 1459, + 1541, + 1539, + 0, + 1459, + 1461, + 1543, + 1541, + 0, + 1461, + 1463, + 1545, + 1543, + 0, + 1463, + 1465, + 1547, + 1545, + 0, + 1465, + 1467, + 1549, + 1547, + 0, + 1467, + 1471, + 1552, + 1549, + 0, + 1471, + 1475, + 1557, + 1552, + 0, + 1475, + 1482, + 1564, + 1557, + 0, + 1482, + 1485, + 1567, + 1564, + 0, + 1485, + 1487, + 1569, + 1567, + 0, + 1487, + 1491, + 1573, + 1569, + 0, + 1491, + 1494, + 1575, + 1573, + 0, + 1494, + 1497, + 1579, + 1575, + 0, + 1497, + 1499, + 1581, + 1579, + 0, + 1499, + 1500, + 1582, + 1581, + 0, + 1500, + 1498, + 1580, + 1582, + 0, + 1498, + 1496, + 1578, + 1580, + 0, + 1496, + 1492, + 1574, + 1578, + 0, + 1492, + 1490, + 1572, + 1574, + 0, + 1490, + 1486, + 1568, + 1572, + 0, + 1486, + 1483, + 1565, + 1568, + 0, + 1483, + 1481, + 1563, + 1565, + 0, + 1481, + 1479, + 1561, + 1563, + 0, + 1479, + 1477, + 1559, + 1561, + 0, + 1477, + 1476, + 1558, + 1559, + 0, + 1476, + 1470, + 1553, + 1558, + 0, + 1470, + 1469, + 1551, + 1553, + 0, + 1551, + 1555, + 1637, + 1633, + 0, + 1555, + 1560, + 1645, + 1637, + 0, + 1560, + 1562, + 1647, + 1645, + 0, + 1562, + 1566, + 1653, + 1647, + 0, + 1566, + 1571, + 1659, + 1653, + 0, + 1571, + 1576, + 1666, + 1659, + 0, + 1576, + 1583, + 1673, + 1666, + 0, + 1583, + 1585, + 1676, + 1673, + 0, + 1585, + 1587, + 1678, + 1676, + 0, + 1587, + 1589, + 1681, + 1678, + 0, + 1589, + 1591, + 1683, + 1681, + 0, + 1591, + 1593, + 1685, + 1683, + 0, + 1593, + 1595, + 1688, + 1685, + 0, + 1595, + 1594, + 1686, + 1688, + 0, + 1594, + 1592, + 1684, + 1686, + 0, + 1592, + 1590, + 1682, + 1684, + 0, + 1590, + 1588, + 1680, + 1682, + 0, + 1588, + 1586, + 1677, + 1680, + 0, + 1586, + 1584, + 1674, + 1677, + 0, + 1584, + 1577, + 1665, + 1674, + 0, + 1577, + 1570, + 1658, + 1665, + 0, + 1570, + 1556, + 1638, + 1658, + 0, + 1556, + 1554, + 1636, + 1638, + 0, + 1554, + 1550, + 1632, + 1636, + 0, + 1550, + 1548, + 1630, + 1632, + 0, + 1548, + 1546, + 1628, + 1630, + 0, + 1546, + 1544, + 1626, + 1628, + 0, + 1544, + 1542, + 1624, + 1626, + 0, + 1542, + 1540, + 1622, + 1624, + 0, + 1540, + 1538, + 1620, + 1622, + 0, + 1538, + 1536, + 1618, + 1620, + 0, + 1536, + 1534, + 1616, + 1618, + 0, + 1534, + 1532, + 1614, + 1616, + 0, + 1532, + 1530, + 1612, + 1614, + 0, + 1530, + 1529, + 1611, + 1612, + 0, + 1529, + 1527, + 1609, + 1611, + 0, + 1527, + 1525, + 1607, + 1609, + 0, + 1525, + 1523, + 1605, + 1607, + 0, + 1523, + 1521, + 1603, + 1605, + 0, + 1521, + 1518, + 1600, + 1603, + 0, + 1518, + 1517, + 1599, + 1600, + 0, + 1517, + 1514, + 1596, + 1599, + 0, + 1514, + 1515, + 1597, + 1596, + 0, + 1515, + 1516, + 1598, + 1597, + 0, + 1516, + 1519, + 1601, + 1598, + 0, + 1519, + 1520, + 1602, + 1601, + 0, + 1520, + 1522, + 1604, + 1602, + 0, + 1522, + 1524, + 1606, + 1604, + 0, + 1524, + 1526, + 1608, + 1606, + 0, + 1526, + 1528, + 1610, + 1608, + 0, + 1528, + 1531, + 1613, + 1610, + 0, + 1531, + 1533, + 1615, + 1613, + 0, + 1533, + 1535, + 1617, + 1615, + 0, + 1535, + 1537, + 1619, + 1617, + 0, + 1537, + 1539, + 1621, + 1619, + 0, + 1539, + 1541, + 1623, + 1621, + 0, + 1541, + 1543, + 1625, + 1623, + 0, + 1543, + 1545, + 1627, + 1625, + 0, + 1545, + 1547, + 1629, + 1627, + 0, + 1547, + 1549, + 1631, + 1629, + 0, + 1549, + 1552, + 1634, + 1631, + 0, + 1552, + 1557, + 1640, + 1634, + 0, + 1557, + 1564, + 1649, + 1640, + 0, + 1564, + 1567, + 1652, + 1649, + 0, + 1567, + 1569, + 1657, + 1652, + 0, + 1569, + 1573, + 1661, + 1657, + 0, + 1573, + 1575, + 1664, + 1661, + 0, + 1575, + 1579, + 1669, + 1664, + 0, + 1579, + 1581, + 1671, + 1669, + 0, + 1581, + 1582, + 1672, + 1671, + 0, + 1582, + 1580, + 1670, + 1672, + 0, + 1580, + 1578, + 1668, + 1670, + 0, + 1578, + 1574, + 1662, + 1668, + 0, + 1574, + 1572, + 1660, + 1662, + 0, + 1572, + 1568, + 1656, + 1660, + 0, + 1568, + 1565, + 1651, + 1656, + 0, + 1565, + 1563, + 1648, + 1651, + 0, + 1563, + 1561, + 1646, + 1648, + 0, + 1561, + 1559, + 1644, + 1646, + 0, + 1559, + 1558, + 1643, + 1644, + 0, + 1558, + 1553, + 1635, + 1643, + 0, + 1553, + 1551, + 1633, + 1635, + 0, + 1633, + 1637, + 1719, + 1715, + 0, + 1637, + 1645, + 1724, + 1719, + 0, + 1645, + 1647, + 1726, + 1724, + 0, + 1647, + 1653, + 1731, + 1726, + 0, + 1653, + 1659, + 1735, + 1731, + 0, + 1659, + 1666, + 1741, + 1735, + 0, + 1666, + 1673, + 1747, + 1741, + 0, + 1673, + 1676, + 1749, + 1747, + 0, + 1676, + 1678, + 1751, + 1749, + 0, + 1678, + 1681, + 1754, + 1751, + 0, + 1681, + 1683, + 1756, + 1754, + 0, + 1683, + 1685, + 1758, + 1756, + 0, + 1685, + 1688, + 1759, + 1758, + 0, + 1688, + 1686, + 1757, + 1759, + 0, + 1686, + 1684, + 1755, + 1757, + 0, + 1684, + 1682, + 1753, + 1755, + 0, + 1682, + 1680, + 1752, + 1753, + 0, + 1680, + 1677, + 1750, + 1752, + 0, + 1677, + 1674, + 1748, + 1750, + 0, + 1674, + 1665, + 1740, + 1748, + 0, + 1665, + 1658, + 1734, + 1740, + 0, + 1658, + 1638, + 1720, + 1734, + 0, + 1638, + 1636, + 1718, + 1720, + 0, + 1636, + 1632, + 1714, + 1718, + 0, + 1632, + 1630, + 1712, + 1714, + 0, + 1630, + 1628, + 1710, + 1712, + 0, + 1628, + 1626, + 1708, + 1710, + 0, + 1626, + 1624, + 1706, + 1708, + 0, + 1624, + 1622, + 1704, + 1706, + 0, + 1622, + 1620, + 1702, + 1704, + 0, + 1620, + 1618, + 1700, + 1702, + 0, + 1618, + 1616, + 1698, + 1700, + 0, + 1616, + 1614, + 1696, + 1698, + 0, + 1614, + 1612, + 1694, + 1696, + 0, + 1612, + 1611, + 1693, + 1694, + 0, + 1611, + 1609, + 1691, + 1693, + 0, + 1609, + 1607, + 1689, + 1691, + 0, + 1607, + 1605, + 1679, + 1689, + 0, + 1605, + 1603, + 1667, + 1679, + 0, + 1603, + 1600, + 1654, + 1667, + 0, + 1600, + 1599, + 1650, + 1654, + 0, + 1599, + 1596, + 1639, + 1650, + 0, + 1596, + 1597, + 1641, + 1639, + 0, + 1597, + 1598, + 1642, + 1641, + 0, + 1598, + 1601, + 1655, + 1642, + 0, + 1601, + 1602, + 1663, + 1655, + 0, + 1602, + 1604, + 1675, + 1663, + 0, + 1604, + 1606, + 1687, + 1675, + 0, + 1606, + 1608, + 1690, + 1687, + 0, + 1608, + 1610, + 1692, + 1690, + 0, + 1610, + 1613, + 1695, + 1692, + 0, + 1613, + 1615, + 1697, + 1695, + 0, + 1615, + 1617, + 1699, + 1697, + 0, + 1617, + 1619, + 1701, + 1699, + 0, + 1619, + 1621, + 1703, + 1701, + 0, + 1621, + 1623, + 1705, + 1703, + 0, + 1623, + 1625, + 1707, + 1705, + 0, + 1625, + 1627, + 1709, + 1707, + 0, + 1627, + 1629, + 1711, + 1709, + 0, + 1629, + 1631, + 1713, + 1711, + 0, + 1631, + 1634, + 1716, + 1713, + 0, + 1634, + 1640, + 1721, + 1716, + 0, + 1640, + 1649, + 1728, + 1721, + 0, + 1649, + 1652, + 1730, + 1728, + 0, + 1652, + 1657, + 1733, + 1730, + 0, + 1657, + 1661, + 1737, + 1733, + 0, + 1661, + 1664, + 1738, + 1737, + 0, + 1664, + 1669, + 1743, + 1738, + 0, + 1669, + 1671, + 1745, + 1743, + 0, + 1671, + 1672, + 1746, + 1745, + 0, + 1672, + 1670, + 1744, + 1746, + 0, + 1670, + 1668, + 1742, + 1744, + 0, + 1668, + 1662, + 1739, + 1742, + 0, + 1662, + 1660, + 1736, + 1739, + 0, + 1660, + 1656, + 1732, + 1736, + 0, + 1656, + 1651, + 1729, + 1732, + 0, + 1651, + 1648, + 1727, + 1729, + 0, + 1648, + 1646, + 1725, + 1727, + 0, + 1646, + 1644, + 1723, + 1725, + 0, + 1644, + 1643, + 1722, + 1723, + 0, + 1643, + 1635, + 1717, + 1722, + 0, + 1635, + 1633, + 1715, + 1717, + 0, + 1715, + 1719, + 1810, + 1806, + 0, + 1719, + 1724, + 1822, + 1810, + 0, + 1724, + 1726, + 1827, + 1822, + 0, + 1726, + 1731, + 1833, + 1827, + 0, + 1731, + 1735, + 1838, + 1833, + 0, + 1735, + 1741, + 1845, + 1838, + 0, + 1741, + 1747, + 1853, + 1845, + 0, + 1747, + 1749, + 1856, + 1853, + 0, + 1749, + 1751, + 1858, + 1856, + 0, + 1751, + 1754, + 1861, + 1858, + 0, + 1754, + 1756, + 1863, + 1861, + 0, + 1756, + 1758, + 1866, + 1863, + 0, + 1758, + 1759, + 1867, + 1866, + 0, + 1759, + 1757, + 1865, + 1867, + 0, + 1757, + 1755, + 1862, + 1865, + 0, + 1755, + 1753, + 1860, + 1862, + 0, + 1753, + 1752, + 1857, + 1860, + 0, + 1752, + 1750, + 1855, + 1857, + 0, + 1750, + 1748, + 1852, + 1855, + 0, + 1748, + 1740, + 1842, + 1852, + 0, + 1740, + 1734, + 1836, + 1842, + 0, + 1734, + 1720, + 1811, + 1836, + 0, + 1720, + 1718, + 1807, + 1811, + 0, + 1718, + 1714, + 1802, + 1807, + 0, + 1714, + 1712, + 1798, + 1802, + 0, + 1712, + 1710, + 1795, + 1798, + 0, + 1710, + 1708, + 1793, + 1795, + 0, + 1708, + 1706, + 1791, + 1793, + 0, + 1706, + 1704, + 1787, + 1791, + 0, + 1704, + 1702, + 1784, + 1787, + 0, + 1702, + 1700, + 1782, + 1784, + 0, + 1700, + 1698, + 1780, + 1782, + 0, + 1698, + 1696, + 1778, + 1780, + 0, + 1696, + 1694, + 1776, + 1778, + 0, + 1694, + 1693, + 1775, + 1776, + 0, + 1693, + 1691, + 1773, + 1775, + 0, + 1691, + 1689, + 1771, + 1773, + 0, + 1689, + 1679, + 1769, + 1771, + 0, + 1679, + 1667, + 1767, + 1769, + 0, + 1667, + 1654, + 1764, + 1767, + 0, + 1654, + 1650, + 1763, + 1764, + 0, + 1650, + 1639, + 1760, + 1763, + 0, + 1639, + 1641, + 1761, + 1760, + 0, + 1641, + 1642, + 1762, + 1761, + 0, + 1642, + 1655, + 1765, + 1762, + 0, + 1655, + 1663, + 1766, + 1765, + 0, + 1663, + 1675, + 1768, + 1766, + 0, + 1675, + 1687, + 1770, + 1768, + 0, + 1687, + 1690, + 1772, + 1770, + 0, + 1690, + 1692, + 1774, + 1772, + 0, + 1692, + 1695, + 1777, + 1774, + 0, + 1695, + 1697, + 1779, + 1777, + 0, + 1697, + 1699, + 1781, + 1779, + 0, + 1699, + 1701, + 1783, + 1781, + 0, + 1701, + 1703, + 1785, + 1783, + 0, + 1703, + 1705, + 1788, + 1785, + 0, + 1705, + 1707, + 1792, + 1788, + 0, + 1707, + 1709, + 1794, + 1792, + 0, + 1709, + 1711, + 1797, + 1794, + 0, + 1711, + 1713, + 1801, + 1797, + 0, + 1713, + 1716, + 1804, + 1801, + 0, + 1716, + 1721, + 1815, + 1804, + 0, + 1721, + 1728, + 1828, + 1815, + 0, + 1728, + 1730, + 1831, + 1828, + 0, + 1730, + 1733, + 1834, + 1831, + 0, + 1733, + 1737, + 1839, + 1834, + 0, + 1737, + 1738, + 1843, + 1839, + 0, + 1738, + 1743, + 1847, + 1843, + 0, + 1743, + 1745, + 1849, + 1847, + 0, + 1745, + 1746, + 1850, + 1849, + 0, + 1746, + 1744, + 1848, + 1850, + 0, + 1744, + 1742, + 1846, + 1848, + 0, + 1742, + 1739, + 1844, + 1846, + 0, + 1739, + 1736, + 1840, + 1844, + 0, + 1736, + 1732, + 1835, + 1840, + 0, + 1732, + 1729, + 1830, + 1835, + 0, + 1729, + 1727, + 1826, + 1830, + 0, + 1727, + 1725, + 1823, + 1826, + 0, + 1725, + 1723, + 1821, + 1823, + 0, + 1723, + 1722, + 1818, + 1821, + 0, + 1722, + 1717, + 1808, + 1818, + 0, + 1717, + 1715, + 1806, + 1808, + 0, + 1806, + 1810, + 1884, + 1880, + 0, + 1810, + 1822, + 1888, + 1884, + 0, + 1822, + 1827, + 1892, + 1888, + 0, + 1827, + 1833, + 1895, + 1892, + 0, + 1833, + 1838, + 1900, + 1895, + 0, + 1838, + 1845, + 1905, + 1900, + 0, + 1845, + 1853, + 1912, + 1905, + 0, + 1853, + 1856, + 1914, + 1912, + 0, + 1856, + 1858, + 1916, + 1914, + 0, + 1858, + 1861, + 1918, + 1916, + 0, + 1861, + 1863, + 1920, + 1918, + 0, + 1863, + 1866, + 1922, + 1920, + 0, + 1866, + 1867, + 1923, + 1922, + 0, + 1867, + 1865, + 1921, + 1923, + 0, + 1865, + 1862, + 1919, + 1921, + 0, + 1862, + 1860, + 1917, + 1919, + 0, + 1860, + 1857, + 1915, + 1917, + 0, + 1857, + 1855, + 1913, + 1915, + 0, + 1855, + 1852, + 1911, + 1913, + 0, + 1852, + 1842, + 1902, + 1911, + 0, + 1842, + 1836, + 1898, + 1902, + 0, + 1836, + 1811, + 1883, + 1898, + 0, + 1811, + 1807, + 1881, + 1883, + 0, + 1807, + 1802, + 1878, + 1881, + 0, + 1802, + 1798, + 1876, + 1878, + 0, + 1798, + 1795, + 1874, + 1876, + 0, + 1795, + 1793, + 1872, + 1874, + 0, + 1793, + 1791, + 1870, + 1872, + 0, + 1791, + 1787, + 1868, + 1870, + 0, + 1787, + 1784, + 1859, + 1868, + 0, + 1784, + 1782, + 1851, + 1859, + 0, + 1782, + 1780, + 1837, + 1851, + 0, + 1780, + 1778, + 1829, + 1837, + 0, + 1778, + 1776, + 1824, + 1829, + 0, + 1776, + 1775, + 1819, + 1824, + 0, + 1775, + 1773, + 1817, + 1819, + 0, + 1773, + 1771, + 1814, + 1817, + 0, + 1771, + 1769, + 1812, + 1814, + 0, + 1769, + 1767, + 1805, + 1812, + 0, + 1767, + 1764, + 1799, + 1805, + 0, + 1764, + 1763, + 1796, + 1799, + 0, + 1763, + 1760, + 1786, + 1796, + 0, + 1760, + 1761, + 1789, + 1786, + 0, + 1761, + 1762, + 1790, + 1789, + 0, + 1762, + 1765, + 1800, + 1790, + 0, + 1765, + 1766, + 1803, + 1800, + 0, + 1766, + 1768, + 1809, + 1803, + 0, + 1768, + 1770, + 1813, + 1809, + 0, + 1770, + 1772, + 1816, + 1813, + 0, + 1772, + 1774, + 1820, + 1816, + 0, + 1774, + 1777, + 1825, + 1820, + 0, + 1777, + 1779, + 1832, + 1825, + 0, + 1779, + 1781, + 1841, + 1832, + 0, + 1781, + 1783, + 1854, + 1841, + 0, + 1783, + 1785, + 1864, + 1854, + 0, + 1785, + 1788, + 1869, + 1864, + 0, + 1788, + 1792, + 1871, + 1869, + 0, + 1792, + 1794, + 1873, + 1871, + 0, + 1794, + 1797, + 1875, + 1873, + 0, + 1797, + 1801, + 1877, + 1875, + 0, + 1801, + 1804, + 1879, + 1877, + 0, + 1804, + 1815, + 1885, + 1879, + 0, + 1815, + 1828, + 1891, + 1885, + 0, + 1828, + 1831, + 1893, + 1891, + 0, + 1831, + 1834, + 1896, + 1893, + 0, + 1834, + 1839, + 1899, + 1896, + 0, + 1839, + 1843, + 1903, + 1899, + 0, + 1843, + 1847, + 1907, + 1903, + 0, + 1847, + 1849, + 1909, + 1907, + 0, + 1849, + 1850, + 1910, + 1909, + 0, + 1850, + 1848, + 1908, + 1910, + 0, + 1848, + 1846, + 1906, + 1908, + 0, + 1846, + 1844, + 1904, + 1906, + 0, + 1844, + 1840, + 1901, + 1904, + 0, + 1840, + 1835, + 1897, + 1901, + 0, + 1835, + 1830, + 1894, + 1897, + 0, + 1830, + 1826, + 1890, + 1894, + 0, + 1826, + 1823, + 1889, + 1890, + 0, + 1823, + 1821, + 1887, + 1889, + 0, + 1821, + 1818, + 1886, + 1887, + 0, + 1818, + 1808, + 1882, + 1886, + 0, + 1808, + 1806, + 1880, + 1882, + 0, + 1880, + 1884, + 1990, + 1985, + 0, + 1884, + 1888, + 2001, + 1990, + 0, + 1888, + 1892, + 2007, + 2001, + 0, + 1892, + 1895, + 2012, + 2007, + 0, + 1895, + 1900, + 2019, + 2012, + 0, + 1900, + 1905, + 2025, + 2019, + 0, + 1905, + 1912, + 2034, + 2025, + 0, + 1912, + 1914, + 2037, + 2034, + 0, + 1914, + 1916, + 2040, + 2037, + 0, + 1916, + 1918, + 2043, + 2040, + 0, + 1918, + 1920, + 2045, + 2043, + 0, + 1920, + 1922, + 2047, + 2045, + 0, + 1922, + 1923, + 2048, + 2047, + 0, + 1923, + 1921, + 2046, + 2048, + 0, + 1921, + 1919, + 2044, + 2046, + 0, + 1919, + 1917, + 2042, + 2044, + 0, + 1917, + 1915, + 2038, + 2042, + 0, + 1915, + 1913, + 2036, + 2038, + 0, + 1913, + 1911, + 2032, + 2036, + 0, + 1911, + 1902, + 2021, + 2032, + 0, + 1902, + 1898, + 2014, + 2021, + 0, + 1898, + 1883, + 1989, + 2014, + 0, + 1883, + 1881, + 1984, + 1989, + 0, + 1881, + 1878, + 1980, + 1984, + 0, + 1878, + 1876, + 1976, + 1980, + 0, + 1876, + 1874, + 1973, + 1976, + 0, + 1874, + 1872, + 1970, + 1973, + 0, + 1872, + 1870, + 1966, + 1970, + 0, + 1870, + 1868, + 1962, + 1966, + 0, + 1868, + 1859, + 1958, + 1962, + 0, + 1859, + 1851, + 1954, + 1958, + 0, + 1851, + 1837, + 1950, + 1954, + 0, + 1837, + 1829, + 1946, + 1950, + 0, + 1829, + 1824, + 1943, + 1946, + 0, + 1824, + 1819, + 1941, + 1943, + 0, + 1819, + 1817, + 1938, + 1941, + 0, + 1817, + 1814, + 1935, + 1938, + 0, + 1814, + 1812, + 1933, + 1935, + 0, + 1812, + 1805, + 1931, + 1933, + 0, + 1805, + 1799, + 1928, + 1931, + 0, + 1799, + 1796, + 1927, + 1928, + 0, + 1796, + 1786, + 1924, + 1927, + 0, + 1786, + 1789, + 1925, + 1924, + 0, + 1789, + 1790, + 1926, + 1925, + 0, + 1790, + 1800, + 1929, + 1926, + 0, + 1800, + 1803, + 1930, + 1929, + 0, + 1803, + 1809, + 1932, + 1930, + 0, + 1809, + 1813, + 1934, + 1932, + 0, + 1813, + 1816, + 1937, + 1934, + 0, + 1816, + 1820, + 1942, + 1937, + 0, + 1820, + 1825, + 1944, + 1942, + 0, + 1825, + 1832, + 1947, + 1944, + 0, + 1832, + 1841, + 1951, + 1947, + 0, + 1841, + 1854, + 1955, + 1951, + 0, + 1854, + 1864, + 1959, + 1955, + 0, + 1864, + 1869, + 1963, + 1959, + 0, + 1869, + 1871, + 1967, + 1963, + 0, + 1871, + 1873, + 1971, + 1967, + 0, + 1873, + 1875, + 1975, + 1971, + 0, + 1875, + 1877, + 1979, + 1975, + 0, + 1877, + 1879, + 1983, + 1979, + 0, + 1879, + 1885, + 1994, + 1983, + 0, + 1885, + 1891, + 2005, + 1994, + 0, + 1891, + 1893, + 2009, + 2005, + 0, + 1893, + 1896, + 2013, + 2009, + 0, + 1896, + 1899, + 2018, + 2013, + 0, + 1899, + 1903, + 2022, + 2018, + 0, + 1903, + 1907, + 2026, + 2022, + 0, + 1907, + 1909, + 2029, + 2026, + 0, + 1909, + 1910, + 2030, + 2029, + 0, + 1910, + 1908, + 2028, + 2030, + 0, + 1908, + 1906, + 2027, + 2028, + 0, + 1906, + 1904, + 2023, + 2027, + 0, + 1904, + 1901, + 2020, + 2023, + 0, + 1901, + 1897, + 2015, + 2020, + 0, + 1897, + 1894, + 2011, + 2015, + 0, + 1894, + 1890, + 2006, + 2011, + 0, + 1890, + 1889, + 2002, + 2006, + 0, + 1889, + 1887, + 1999, + 2002, + 0, + 1887, + 1886, + 1997, + 1999, + 0, + 1886, + 1882, + 1986, + 1997, + 0, + 1882, + 1880, + 1985, + 1986, + 0, + 1985, + 1990, + 2041, + 2033, + 0, + 1990, + 2001, + 2052, + 2041, + 0, + 2001, + 2007, + 2056, + 2052, + 0, + 2007, + 2012, + 2059, + 2056, + 0, + 2012, + 2019, + 2064, + 2059, + 0, + 2019, + 2025, + 2069, + 2064, + 0, + 2025, + 2034, + 2076, + 2069, + 0, + 2034, + 2037, + 2078, + 2076, + 0, + 2037, + 2040, + 2080, + 2078, + 0, + 2040, + 2043, + 2082, + 2080, + 0, + 2043, + 2045, + 2084, + 2082, + 0, + 2045, + 2047, + 2086, + 2084, + 0, + 2047, + 2048, + 2087, + 2086, + 0, + 2048, + 2046, + 2085, + 2087, + 0, + 2046, + 2044, + 2083, + 2085, + 0, + 2044, + 2042, + 2081, + 2083, + 0, + 2042, + 2038, + 2079, + 2081, + 0, + 2038, + 2036, + 2077, + 2079, + 0, + 2036, + 2032, + 2075, + 2077, + 0, + 2032, + 2021, + 2066, + 2075, + 0, + 2021, + 2014, + 2061, + 2066, + 0, + 2014, + 1989, + 2039, + 2061, + 0, + 1989, + 1984, + 2031, + 2039, + 0, + 1984, + 1980, + 2017, + 2031, + 0, + 1980, + 1976, + 2010, + 2017, + 0, + 1976, + 1973, + 2004, + 2010, + 0, + 1973, + 1970, + 2000, + 2004, + 0, + 1970, + 1966, + 1996, + 2000, + 0, + 1966, + 1962, + 1993, + 1996, + 0, + 1962, + 1958, + 1991, + 1993, + 0, + 1958, + 1954, + 1987, + 1991, + 0, + 1954, + 1950, + 1981, + 1987, + 0, + 1950, + 1946, + 1977, + 1981, + 0, + 1946, + 1943, + 1972, + 1977, + 0, + 1943, + 1941, + 1968, + 1972, + 0, + 1941, + 1938, + 1965, + 1968, + 0, + 1938, + 1935, + 1961, + 1965, + 0, + 1935, + 1933, + 1957, + 1961, + 0, + 1933, + 1931, + 1953, + 1957, + 0, + 1931, + 1928, + 1948, + 1953, + 0, + 1928, + 1927, + 1945, + 1948, + 0, + 1927, + 1924, + 1936, + 1945, + 0, + 1924, + 1925, + 1939, + 1936, + 0, + 1925, + 1926, + 1940, + 1939, + 0, + 1926, + 1929, + 1949, + 1940, + 0, + 1929, + 1930, + 1952, + 1949, + 0, + 1930, + 1932, + 1956, + 1952, + 0, + 1932, + 1934, + 1960, + 1956, + 0, + 1934, + 1937, + 1964, + 1960, + 0, + 1937, + 1942, + 1969, + 1964, + 0, + 1942, + 1944, + 1974, + 1969, + 0, + 1944, + 1947, + 1978, + 1974, + 0, + 1947, + 1951, + 1982, + 1978, + 0, + 1951, + 1955, + 1988, + 1982, + 0, + 1955, + 1959, + 1992, + 1988, + 0, + 1959, + 1963, + 1995, + 1992, + 0, + 1963, + 1967, + 1998, + 1995, + 0, + 1967, + 1971, + 2003, + 1998, + 0, + 1971, + 1975, + 2008, + 2003, + 0, + 1975, + 1979, + 2016, + 2008, + 0, + 1979, + 1983, + 2024, + 2016, + 0, + 1983, + 1994, + 2049, + 2024, + 0, + 1994, + 2005, + 2054, + 2049, + 0, + 2005, + 2009, + 2057, + 2054, + 0, + 2009, + 2013, + 2060, + 2057, + 0, + 2013, + 2018, + 2063, + 2060, + 0, + 2018, + 2022, + 2067, + 2063, + 0, + 2022, + 2026, + 2070, + 2067, + 0, + 2026, + 2029, + 2073, + 2070, + 0, + 2029, + 2030, + 2074, + 2073, + 0, + 2030, + 2028, + 2072, + 2074, + 0, + 2028, + 2027, + 2071, + 2072, + 0, + 2027, + 2023, + 2068, + 2071, + 0, + 2023, + 2020, + 2065, + 2068, + 0, + 2020, + 2015, + 2062, + 2065, + 0, + 2015, + 2011, + 2058, + 2062, + 0, + 2011, + 2006, + 2055, + 2058, + 0, + 2006, + 2002, + 2053, + 2055, + 0, + 2002, + 1999, + 2051, + 2053, + 0, + 1999, + 1997, + 2050, + 2051, + 0, + 1997, + 1986, + 2035, + 2050, + 0, + 1986, + 1985, + 2033, + 2035, + 0, + 2033, + 2041, + 2171, + 2164, + 0, + 2041, + 2052, + 2179, + 2171, + 0, + 2052, + 2056, + 2186, + 2179, + 0, + 2056, + 2059, + 2192, + 2186, + 0, + 2059, + 2064, + 2201, + 2192, + 0, + 2064, + 2069, + 2211, + 2201, + 0, + 2069, + 2076, + 2220, + 2211, + 0, + 2076, + 2078, + 2229, + 2220, + 0, + 2078, + 2080, + 2233, + 2229, + 0, + 2080, + 2082, + 2236, + 2233, + 0, + 2082, + 2084, + 2239, + 2236, + 0, + 2084, + 2086, + 2242, + 2239, + 0, + 2086, + 2087, + 2243, + 2242, + 0, + 2087, + 2085, + 2240, + 2243, + 0, + 2085, + 2083, + 2237, + 2240, + 0, + 2083, + 2081, + 2234, + 2237, + 0, + 2081, + 2079, + 2231, + 2234, + 0, + 2079, + 2077, + 2222, + 2231, + 0, + 2077, + 2075, + 2217, + 2222, + 0, + 2075, + 2066, + 2204, + 2217, + 0, + 2066, + 2061, + 2194, + 2204, + 0, + 2061, + 2039, + 2168, + 2194, + 0, + 2039, + 2031, + 2163, + 2168, + 0, + 2031, + 2017, + 2159, + 2163, + 0, + 2017, + 2010, + 2155, + 2159, + 0, + 2010, + 2004, + 2151, + 2155, + 0, + 2004, + 2000, + 2147, + 2151, + 0, + 2000, + 1996, + 2143, + 2147, + 0, + 1996, + 1993, + 2139, + 2143, + 0, + 1993, + 1991, + 2136, + 2139, + 0, + 1991, + 1987, + 2132, + 2136, + 0, + 1987, + 1981, + 2127, + 2132, + 0, + 1981, + 1977, + 2124, + 2127, + 0, + 1977, + 1972, + 2120, + 2124, + 0, + 1972, + 1968, + 2116, + 2120, + 0, + 1968, + 1965, + 2113, + 2116, + 0, + 1965, + 1961, + 2109, + 2113, + 0, + 1961, + 1957, + 2105, + 2109, + 0, + 1957, + 1953, + 2101, + 2105, + 0, + 1953, + 1948, + 2096, + 2101, + 0, + 1948, + 1945, + 2094, + 2096, + 0, + 1945, + 1936, + 2088, + 2094, + 0, + 1936, + 1939, + 2090, + 2088, + 0, + 1939, + 1940, + 2091, + 2090, + 0, + 1940, + 1949, + 2097, + 2091, + 0, + 1949, + 1952, + 2100, + 2097, + 0, + 1952, + 1956, + 2104, + 2100, + 0, + 1956, + 1960, + 2107, + 2104, + 0, + 1960, + 1964, + 2112, + 2107, + 0, + 1964, + 1969, + 2117, + 2112, + 0, + 1969, + 1974, + 2121, + 2117, + 0, + 1974, + 1978, + 2125, + 2121, + 0, + 1978, + 1982, + 2129, + 2125, + 0, + 1982, + 1988, + 2133, + 2129, + 0, + 1988, + 1992, + 2137, + 2133, + 0, + 1992, + 1995, + 2141, + 2137, + 0, + 1995, + 1998, + 2145, + 2141, + 0, + 1998, + 2003, + 2149, + 2145, + 0, + 2003, + 2008, + 2154, + 2149, + 0, + 2008, + 2016, + 2158, + 2154, + 0, + 2016, + 2024, + 2162, + 2158, + 0, + 2024, + 2049, + 2174, + 2162, + 0, + 2049, + 2054, + 2182, + 2174, + 0, + 2054, + 2057, + 2187, + 2182, + 0, + 2057, + 2060, + 2193, + 2187, + 0, + 2060, + 2063, + 2198, + 2193, + 0, + 2063, + 2067, + 2205, + 2198, + 0, + 2067, + 2070, + 2208, + 2205, + 0, + 2070, + 2073, + 2213, + 2208, + 0, + 2073, + 2074, + 2214, + 2213, + 0, + 2074, + 2072, + 2212, + 2214, + 0, + 2072, + 2071, + 2209, + 2212, + 0, + 2071, + 2068, + 2207, + 2209, + 0, + 2068, + 2065, + 2200, + 2207, + 0, + 2065, + 2062, + 2196, + 2200, + 0, + 2062, + 2058, + 2189, + 2196, + 0, + 2058, + 2055, + 2184, + 2189, + 0, + 2055, + 2053, + 2181, + 2184, + 0, + 2053, + 2051, + 2177, + 2181, + 0, + 2051, + 2050, + 2176, + 2177, + 0, + 2050, + 2035, + 2166, + 2176, + 0, + 2035, + 2033, + 2164, + 2166, + 0, + 2164, + 2171, + 2173, + 2169, + 0, + 2171, + 2179, + 2183, + 2173, + 0, + 2179, + 2186, + 2191, + 2183, + 0, + 2186, + 2192, + 2199, + 2191, + 0, + 2192, + 2201, + 2216, + 2199, + 0, + 2201, + 2211, + 2225, + 2216, + 0, + 2211, + 2220, + 2232, + 2225, + 0, + 2220, + 2229, + 2238, + 2232, + 0, + 2229, + 2233, + 2244, + 2238, + 0, + 2233, + 2236, + 2246, + 2244, + 0, + 2236, + 2239, + 2248, + 2246, + 0, + 2239, + 2242, + 2250, + 2248, + 0, + 2242, + 2243, + 2251, + 2250, + 0, + 2243, + 2240, + 2249, + 2251, + 0, + 2240, + 2237, + 2247, + 2249, + 0, + 2237, + 2234, + 2245, + 2247, + 0, + 2234, + 2231, + 2241, + 2245, + 0, + 2231, + 2222, + 2235, + 2241, + 0, + 2222, + 2217, + 2230, + 2235, + 0, + 2217, + 2204, + 2218, + 2230, + 0, + 2204, + 2194, + 2203, + 2218, + 0, + 2194, + 2168, + 2172, + 2203, + 0, + 2168, + 2163, + 2167, + 2172, + 0, + 2163, + 2159, + 2161, + 2167, + 0, + 2159, + 2155, + 2157, + 2161, + 0, + 2155, + 2151, + 2153, + 2157, + 0, + 2151, + 2147, + 2150, + 2153, + 0, + 2147, + 2143, + 2146, + 2150, + 0, + 2143, + 2139, + 2142, + 2146, + 0, + 2139, + 2136, + 2138, + 2142, + 0, + 2136, + 2132, + 2134, + 2138, + 0, + 2132, + 2127, + 2130, + 2134, + 0, + 2127, + 2124, + 2126, + 2130, + 0, + 2124, + 2120, + 2122, + 2126, + 0, + 2120, + 2116, + 2118, + 2122, + 0, + 2116, + 2113, + 2115, + 2118, + 0, + 2113, + 2109, + 2111, + 2115, + 0, + 2109, + 2105, + 2108, + 2111, + 0, + 2105, + 2101, + 2103, + 2108, + 0, + 2101, + 2096, + 2098, + 2103, + 0, + 2096, + 2094, + 2095, + 2098, + 0, + 2094, + 2088, + 2089, + 2095, + 0, + 2088, + 2090, + 2092, + 2089, + 0, + 2090, + 2091, + 2093, + 2092, + 0, + 2091, + 2097, + 2099, + 2093, + 0, + 2097, + 2100, + 2102, + 2099, + 0, + 2100, + 2104, + 2106, + 2102, + 0, + 2104, + 2107, + 2110, + 2106, + 0, + 2107, + 2112, + 2114, + 2110, + 0, + 2112, + 2117, + 2119, + 2114, + 0, + 2117, + 2121, + 2123, + 2119, + 0, + 2121, + 2125, + 2128, + 2123, + 0, + 2125, + 2129, + 2131, + 2128, + 0, + 2129, + 2133, + 2135, + 2131, + 0, + 2133, + 2137, + 2140, + 2135, + 0, + 2137, + 2141, + 2144, + 2140, + 0, + 2141, + 2145, + 2148, + 2144, + 0, + 2145, + 2149, + 2152, + 2148, + 0, + 2149, + 2154, + 2156, + 2152, + 0, + 2154, + 2158, + 2160, + 2156, + 0, + 2158, + 2162, + 2165, + 2160, + 0, + 2162, + 2174, + 2175, + 2165, + 0, + 2174, + 2182, + 2188, + 2175, + 0, + 2182, + 2187, + 2195, + 2188, + 0, + 2187, + 2193, + 2202, + 2195, + 0, + 2193, + 2198, + 2210, + 2202, + 0, + 2198, + 2205, + 2219, + 2210, + 0, + 2205, + 2208, + 2223, + 2219, + 0, + 2208, + 2213, + 2227, + 2223, + 0, + 2213, + 2214, + 2228, + 2227, + 0, + 2214, + 2212, + 2226, + 2228, + 0, + 2212, + 2209, + 2224, + 2226, + 0, + 2209, + 2207, + 2221, + 2224, + 0, + 2207, + 2200, + 2215, + 2221, + 0, + 2200, + 2196, + 2206, + 2215, + 0, + 2196, + 2189, + 2197, + 2206, + 0, + 2189, + 2184, + 2190, + 2197, + 0, + 2184, + 2181, + 2185, + 2190, + 0, + 2181, + 2177, + 2180, + 2185, + 0, + 2177, + 2176, + 2178, + 2180, + 0, + 2176, + 2166, + 2170, + 2178, + 0, + 2166, + 2164, + 2169, + 2170, + 0, + 2169, + 2173, + 2322, + 2317, + 0, + 2173, + 2183, + 2333, + 2322, + 0, + 2183, + 2191, + 2339, + 2333, + 0, + 2191, + 2199, + 2345, + 2339, + 0, + 2199, + 2216, + 2354, + 2345, + 0, + 2216, + 2225, + 2360, + 2354, + 0, + 2225, + 2232, + 2365, + 2360, + 0, + 2232, + 2238, + 2367, + 2365, + 0, + 2238, + 2244, + 2370, + 2367, + 0, + 2244, + 2246, + 2372, + 2370, + 0, + 2246, + 2248, + 2374, + 2372, + 0, + 2248, + 2250, + 2376, + 2374, + 0, + 2250, + 2251, + 2377, + 2376, + 0, + 2251, + 2249, + 2375, + 2377, + 0, + 2249, + 2247, + 2373, + 2375, + 0, + 2247, + 2245, + 2371, + 2373, + 0, + 2245, + 2241, + 2368, + 2371, + 0, + 2241, + 2235, + 2366, + 2368, + 0, + 2235, + 2230, + 2364, + 2366, + 0, + 2230, + 2218, + 2353, + 2364, + 0, + 2218, + 2203, + 2346, + 2353, + 0, + 2203, + 2172, + 2320, + 2346, + 0, + 2172, + 2167, + 2315, + 2320, + 0, + 2167, + 2161, + 2312, + 2315, + 0, + 2161, + 2157, + 2308, + 2312, + 0, + 2157, + 2153, + 2304, + 2308, + 0, + 2153, + 2150, + 2300, + 2304, + 0, + 2150, + 2146, + 2296, + 2300, + 0, + 2146, + 2142, + 2292, + 2296, + 0, + 2142, + 2138, + 2288, + 2292, + 0, + 2138, + 2134, + 2284, + 2288, + 0, + 2134, + 2130, + 2280, + 2284, + 0, + 2130, + 2126, + 2276, + 2280, + 0, + 2126, + 2122, + 2272, + 2276, + 0, + 2122, + 2118, + 2269, + 2272, + 0, + 2118, + 2115, + 2268, + 2269, + 0, + 2115, + 2111, + 2265, + 2268, + 0, + 2111, + 2108, + 2262, + 2265, + 0, + 2108, + 2103, + 2259, + 2262, + 0, + 2103, + 2098, + 2256, + 2259, + 0, + 2098, + 2095, + 2255, + 2256, + 0, + 2095, + 2089, + 2252, + 2255, + 0, + 2089, + 2092, + 2253, + 2252, + 0, + 2092, + 2093, + 2254, + 2253, + 0, + 2093, + 2099, + 2257, + 2254, + 0, + 2099, + 2102, + 2258, + 2257, + 0, + 2102, + 2106, + 2261, + 2258, + 0, + 2106, + 2110, + 2263, + 2261, + 0, + 2110, + 2114, + 2267, + 2263, + 0, + 2114, + 2119, + 2270, + 2267, + 0, + 2119, + 2123, + 2273, + 2270, + 0, + 2123, + 2128, + 2279, + 2273, + 0, + 2128, + 2131, + 2282, + 2279, + 0, + 2131, + 2135, + 2286, + 2282, + 0, + 2135, + 2140, + 2291, + 2286, + 0, + 2140, + 2144, + 2295, + 2291, + 0, + 2144, + 2148, + 2299, + 2295, + 0, + 2148, + 2152, + 2303, + 2299, + 0, + 2152, + 2156, + 2307, + 2303, + 0, + 2156, + 2160, + 2311, + 2307, + 0, + 2160, + 2165, + 2313, + 2311, + 0, + 2165, + 2175, + 2325, + 2313, + 0, + 2175, + 2188, + 2337, + 2325, + 0, + 2188, + 2195, + 2341, + 2337, + 0, + 2195, + 2202, + 2344, + 2341, + 0, + 2202, + 2210, + 2351, + 2344, + 0, + 2210, + 2219, + 2355, + 2351, + 0, + 2219, + 2223, + 2358, + 2355, + 0, + 2223, + 2227, + 2361, + 2358, + 0, + 2227, + 2228, + 2363, + 2361, + 0, + 2228, + 2226, + 2362, + 2363, + 0, + 2226, + 2224, + 2359, + 2362, + 0, + 2224, + 2221, + 2356, + 2359, + 0, + 2221, + 2215, + 2352, + 2356, + 0, + 2215, + 2206, + 2348, + 2352, + 0, + 2206, + 2197, + 2343, + 2348, + 0, + 2197, + 2190, + 2338, + 2343, + 0, + 2190, + 2185, + 2334, + 2338, + 0, + 2185, + 2180, + 2331, + 2334, + 0, + 2180, + 2178, + 2329, + 2331, + 0, + 2178, + 2170, + 2318, + 2329, + 0, + 2170, + 2169, + 2317, + 2318, + 0, + 2317, + 2322, + 2357, + 2347, + 0, + 2322, + 2333, + 2380, + 2357, + 0, + 2333, + 2339, + 2384, + 2380, + 0, + 2339, + 2345, + 2389, + 2384, + 0, + 2345, + 2354, + 2394, + 2389, + 0, + 2354, + 2360, + 2399, + 2394, + 0, + 2360, + 2365, + 2404, + 2399, + 0, + 2365, + 2367, + 2406, + 2404, + 0, + 2367, + 2370, + 2408, + 2406, + 0, + 2370, + 2372, + 2410, + 2408, + 0, + 2372, + 2374, + 2412, + 2410, + 0, + 2374, + 2376, + 2414, + 2412, + 0, + 2376, + 2377, + 2415, + 2414, + 0, + 2377, + 2375, + 2413, + 2415, + 0, + 2375, + 2373, + 2411, + 2413, + 0, + 2373, + 2371, + 2409, + 2411, + 0, + 2371, + 2368, + 2407, + 2409, + 0, + 2368, + 2366, + 2405, + 2407, + 0, + 2366, + 2364, + 2403, + 2405, + 0, + 2364, + 2353, + 2393, + 2403, + 0, + 2353, + 2346, + 2388, + 2393, + 0, + 2346, + 2320, + 2350, + 2388, + 0, + 2320, + 2315, + 2342, + 2350, + 0, + 2315, + 2312, + 2336, + 2342, + 0, + 2312, + 2308, + 2332, + 2336, + 0, + 2308, + 2304, + 2328, + 2332, + 0, + 2304, + 2300, + 2326, + 2328, + 0, + 2300, + 2296, + 2323, + 2326, + 0, + 2296, + 2292, + 2319, + 2323, + 0, + 2292, + 2288, + 2314, + 2319, + 0, + 2288, + 2284, + 2309, + 2314, + 0, + 2284, + 2280, + 2305, + 2309, + 0, + 2280, + 2276, + 2301, + 2305, + 0, + 2276, + 2272, + 2297, + 2301, + 0, + 2272, + 2269, + 2293, + 2297, + 0, + 2269, + 2268, + 2290, + 2293, + 0, + 2268, + 2265, + 2287, + 2290, + 0, + 2265, + 2262, + 2283, + 2287, + 0, + 2262, + 2259, + 2278, + 2283, + 0, + 2259, + 2256, + 2274, + 2278, + 0, + 2256, + 2255, + 2271, + 2274, + 0, + 2255, + 2252, + 2260, + 2271, + 0, + 2252, + 2253, + 2264, + 2260, + 0, + 2253, + 2254, + 2266, + 2264, + 0, + 2254, + 2257, + 2275, + 2266, + 0, + 2257, + 2258, + 2277, + 2275, + 0, + 2258, + 2261, + 2281, + 2277, + 0, + 2261, + 2263, + 2285, + 2281, + 0, + 2263, + 2267, + 2289, + 2285, + 0, + 2267, + 2270, + 2294, + 2289, + 0, + 2270, + 2273, + 2298, + 2294, + 0, + 2273, + 2279, + 2302, + 2298, + 0, + 2279, + 2282, + 2306, + 2302, + 0, + 2282, + 2286, + 2310, + 2306, + 0, + 2286, + 2291, + 2316, + 2310, + 0, + 2291, + 2295, + 2321, + 2316, + 0, + 2295, + 2299, + 2324, + 2321, + 0, + 2299, + 2303, + 2327, + 2324, + 0, + 2303, + 2307, + 2330, + 2327, + 0, + 2307, + 2311, + 2335, + 2330, + 0, + 2311, + 2313, + 2340, + 2335, + 0, + 2313, + 2325, + 2369, + 2340, + 0, + 2325, + 2337, + 2382, + 2369, + 0, + 2337, + 2341, + 2385, + 2382, + 0, + 2341, + 2344, + 2387, + 2385, + 0, + 2344, + 2351, + 2391, + 2387, + 0, + 2351, + 2355, + 2395, + 2391, + 0, + 2355, + 2358, + 2397, + 2395, + 0, + 2358, + 2361, + 2400, + 2397, + 0, + 2361, + 2363, + 2402, + 2400, + 0, + 2363, + 2362, + 2401, + 2402, + 0, + 2362, + 2359, + 2398, + 2401, + 0, + 2359, + 2356, + 2396, + 2398, + 0, + 2356, + 2352, + 2392, + 2396, + 0, + 2352, + 2348, + 2390, + 2392, + 0, + 2348, + 2343, + 2386, + 2390, + 0, + 2343, + 2338, + 2383, + 2386, + 0, + 2338, + 2334, + 2381, + 2383, + 0, + 2334, + 2331, + 2379, + 2381, + 0, + 2331, + 2329, + 2378, + 2379, + 0, + 2329, + 2318, + 2349, + 2378, + 0, + 2318, + 2317, + 2347, + 2349, + 0, + 2347, + 2357, + 2474, + 2469, + 0, + 2357, + 2380, + 2484, + 2474, + 0, + 2380, + 2384, + 2490, + 2484, + 0, + 2384, + 2389, + 2497, + 2490, + 0, + 2389, + 2394, + 2503, + 2497, + 0, + 2394, + 2399, + 2510, + 2503, + 0, + 2399, + 2404, + 2515, + 2510, + 0, + 2404, + 2406, + 2518, + 2515, + 0, + 2406, + 2408, + 2521, + 2518, + 0, + 2408, + 2410, + 2524, + 2521, + 0, + 2410, + 2412, + 2526, + 2524, + 0, + 2412, + 2414, + 2528, + 2526, + 0, + 2414, + 2415, + 2527, + 2528, + 0, + 2415, + 2413, + 2525, + 2527, + 0, + 2413, + 2411, + 2523, + 2525, + 0, + 2411, + 2409, + 2520, + 2523, + 0, + 2409, + 2407, + 2517, + 2520, + 0, + 2407, + 2405, + 2516, + 2517, + 0, + 2405, + 2403, + 2512, + 2516, + 0, + 2403, + 2393, + 2500, + 2512, + 0, + 2393, + 2388, + 2495, + 2500, + 0, + 2388, + 2350, + 2470, + 2495, + 0, + 2350, + 2342, + 2466, + 2470, + 0, + 2342, + 2336, + 2462, + 2466, + 0, + 2336, + 2332, + 2458, + 2462, + 0, + 2332, + 2328, + 2454, + 2458, + 0, + 2328, + 2326, + 2450, + 2454, + 0, + 2326, + 2323, + 2447, + 2450, + 0, + 2323, + 2319, + 2445, + 2447, + 0, + 2319, + 2314, + 2443, + 2445, + 0, + 2314, + 2309, + 2439, + 2443, + 0, + 2309, + 2305, + 2436, + 2439, + 0, + 2305, + 2301, + 2434, + 2436, + 0, + 2301, + 2297, + 2432, + 2434, + 0, + 2297, + 2293, + 2430, + 2432, + 0, + 2293, + 2290, + 2429, + 2430, + 0, + 2290, + 2287, + 2427, + 2429, + 0, + 2287, + 2283, + 2425, + 2427, + 0, + 2283, + 2278, + 2423, + 2425, + 0, + 2278, + 2274, + 2420, + 2423, + 0, + 2274, + 2271, + 2419, + 2420, + 0, + 2271, + 2260, + 2416, + 2419, + 0, + 2260, + 2264, + 2417, + 2416, + 0, + 2264, + 2266, + 2418, + 2417, + 0, + 2266, + 2275, + 2421, + 2418, + 0, + 2275, + 2277, + 2422, + 2421, + 0, + 2277, + 2281, + 2424, + 2422, + 0, + 2281, + 2285, + 2426, + 2424, + 0, + 2285, + 2289, + 2428, + 2426, + 0, + 2289, + 2294, + 2431, + 2428, + 0, + 2294, + 2298, + 2433, + 2431, + 0, + 2298, + 2302, + 2435, + 2433, + 0, + 2302, + 2306, + 2437, + 2435, + 0, + 2306, + 2310, + 2440, + 2437, + 0, + 2310, + 2316, + 2444, + 2440, + 0, + 2316, + 2321, + 2446, + 2444, + 0, + 2321, + 2324, + 2449, + 2446, + 0, + 2324, + 2327, + 2453, + 2449, + 0, + 2327, + 2330, + 2457, + 2453, + 0, + 2330, + 2335, + 2461, + 2457, + 0, + 2335, + 2340, + 2465, + 2461, + 0, + 2340, + 2369, + 2477, + 2465, + 0, + 2369, + 2382, + 2487, + 2477, + 0, + 2382, + 2385, + 2491, + 2487, + 0, + 2385, + 2387, + 2494, + 2491, + 0, + 2387, + 2391, + 2499, + 2494, + 0, + 2391, + 2395, + 2504, + 2499, + 0, + 2395, + 2397, + 2506, + 2504, + 0, + 2397, + 2400, + 2509, + 2506, + 0, + 2400, + 2402, + 2513, + 2509, + 0, + 2402, + 2401, + 2511, + 2513, + 0, + 2401, + 2398, + 2508, + 2511, + 0, + 2398, + 2396, + 2505, + 2508, + 0, + 2396, + 2392, + 2502, + 2505, + 0, + 2392, + 2390, + 2498, + 2502, + 0, + 2390, + 2386, + 2493, + 2498, + 0, + 2386, + 2383, + 2489, + 2493, + 0, + 2383, + 2381, + 2485, + 2489, + 0, + 2381, + 2379, + 2482, + 2485, + 0, + 2379, + 2378, + 2480, + 2482, + 0, + 2378, + 2349, + 2471, + 2480, + 0, + 2349, + 2347, + 2469, + 2471, + 0, + 2469, + 2474, + 2540, + 2537, + 0, + 2474, + 2484, + 2544, + 2540, + 0, + 2484, + 2490, + 2548, + 2544, + 0, + 2490, + 2497, + 2553, + 2548, + 0, + 2497, + 2503, + 2560, + 2553, + 0, + 2503, + 2510, + 2566, + 2560, + 0, + 2510, + 2515, + 2572, + 2566, + 0, + 2515, + 2518, + 2574, + 2572, + 0, + 2518, + 2521, + 2576, + 2574, + 0, + 2521, + 2524, + 2578, + 2576, + 0, + 2524, + 2526, + 2580, + 2578, + 0, + 2526, + 2528, + 2582, + 2580, + 0, + 2528, + 2527, + 2581, + 2582, + 0, + 2527, + 2525, + 2579, + 2581, + 0, + 2525, + 2523, + 2577, + 2579, + 0, + 2523, + 2520, + 2575, + 2577, + 0, + 2520, + 2517, + 2573, + 2575, + 0, + 2517, + 2516, + 2571, + 2573, + 0, + 2516, + 2512, + 2565, + 2571, + 0, + 2512, + 2500, + 2557, + 2565, + 0, + 2500, + 2495, + 2552, + 2557, + 0, + 2495, + 2470, + 2538, + 2552, + 0, + 2470, + 2466, + 2536, + 2538, + 0, + 2466, + 2462, + 2534, + 2536, + 0, + 2462, + 2458, + 2532, + 2534, + 0, + 2458, + 2454, + 2530, + 2532, + 0, + 2454, + 2450, + 2522, + 2530, + 0, + 2450, + 2447, + 2514, + 2522, + 0, + 2447, + 2445, + 2501, + 2514, + 0, + 2445, + 2443, + 2492, + 2501, + 0, + 2443, + 2439, + 2486, + 2492, + 0, + 2439, + 2436, + 2481, + 2486, + 0, + 2436, + 2434, + 2478, + 2481, + 0, + 2434, + 2432, + 2475, + 2478, + 0, + 2432, + 2430, + 2472, + 2475, + 0, + 2430, + 2429, + 2468, + 2472, + 0, + 2429, + 2427, + 2464, + 2468, + 0, + 2427, + 2425, + 2460, + 2464, + 0, + 2425, + 2423, + 2456, + 2460, + 0, + 2423, + 2420, + 2451, + 2456, + 0, + 2420, + 2419, + 2448, + 2451, + 0, + 2419, + 2416, + 2438, + 2448, + 0, + 2416, + 2417, + 2441, + 2438, + 0, + 2417, + 2418, + 2442, + 2441, + 0, + 2418, + 2421, + 2452, + 2442, + 0, + 2421, + 2422, + 2455, + 2452, + 0, + 2422, + 2424, + 2459, + 2455, + 0, + 2424, + 2426, + 2463, + 2459, + 0, + 2426, + 2428, + 2467, + 2463, + 0, + 2428, + 2431, + 2473, + 2467, + 0, + 2431, + 2433, + 2476, + 2473, + 0, + 2433, + 2435, + 2479, + 2476, + 0, + 2435, + 2437, + 2483, + 2479, + 0, + 2437, + 2440, + 2488, + 2483, + 0, + 2440, + 2444, + 2496, + 2488, + 0, + 2444, + 2446, + 2507, + 2496, + 0, + 2446, + 2449, + 2519, + 2507, + 0, + 2449, + 2453, + 2529, + 2519, + 0, + 2453, + 2457, + 2531, + 2529, + 0, + 2457, + 2461, + 2533, + 2531, + 0, + 2461, + 2465, + 2535, + 2533, + 0, + 2465, + 2477, + 2541, + 2535, + 0, + 2477, + 2487, + 2546, + 2541, + 0, + 2487, + 2491, + 2549, + 2546, + 0, + 2491, + 2494, + 2551, + 2549, + 0, + 2494, + 2499, + 2556, + 2551, + 0, + 2499, + 2504, + 2559, + 2556, + 0, + 2504, + 2506, + 2562, + 2559, + 0, + 2506, + 2509, + 2564, + 2562, + 0, + 2509, + 2513, + 2569, + 2564, + 0, + 2513, + 2511, + 2567, + 2569, + 0, + 2511, + 2508, + 2563, + 2567, + 0, + 2508, + 2505, + 2561, + 2563, + 0, + 2505, + 2502, + 2558, + 2561, + 0, + 2502, + 2498, + 2555, + 2558, + 0, + 2498, + 2493, + 2550, + 2555, + 0, + 2493, + 2489, + 2547, + 2550, + 0, + 2489, + 2485, + 2545, + 2547, + 0, + 2485, + 2482, + 2543, + 2545, + 0, + 2482, + 2480, + 2542, + 2543, + 0, + 2480, + 2471, + 2539, + 2542, + 0, + 2471, + 2469, + 2537, + 2539, + 0, + 2537, + 2540, + 2622, + 2620, + 0, + 2540, + 2544, + 2626, + 2622, + 0, + 2544, + 2548, + 2630, + 2626, + 0, + 2548, + 2553, + 2635, + 2630, + 0, + 2553, + 2560, + 2641, + 2635, + 0, + 2560, + 2566, + 2649, + 2641, + 0, + 2566, + 2572, + 2651, + 2649, + 0, + 2572, + 2574, + 2653, + 2651, + 0, + 2574, + 2576, + 2655, + 2653, + 0, + 2576, + 2578, + 2657, + 2655, + 0, + 2578, + 2580, + 2659, + 2657, + 0, + 2580, + 2582, + 2661, + 2659, + 0, + 2582, + 2581, + 2660, + 2661, + 0, + 2581, + 2579, + 2658, + 2660, + 0, + 2579, + 2577, + 2656, + 2658, + 0, + 2577, + 2575, + 2654, + 2656, + 0, + 2575, + 2573, + 2652, + 2654, + 0, + 2573, + 2571, + 2650, + 2652, + 0, + 2571, + 2565, + 2646, + 2650, + 0, + 2565, + 2557, + 2638, + 2646, + 0, + 2557, + 2552, + 2633, + 2638, + 0, + 2552, + 2538, + 2619, + 2633, + 0, + 2538, + 2536, + 2618, + 2619, + 0, + 2536, + 2534, + 2616, + 2618, + 0, + 2534, + 2532, + 2614, + 2616, + 0, + 2532, + 2530, + 2612, + 2614, + 0, + 2530, + 2522, + 2610, + 2612, + 0, + 2522, + 2514, + 2608, + 2610, + 0, + 2514, + 2501, + 2606, + 2608, + 0, + 2501, + 2492, + 2604, + 2606, + 0, + 2492, + 2486, + 2602, + 2604, + 0, + 2486, + 2481, + 2600, + 2602, + 0, + 2481, + 2478, + 2598, + 2600, + 0, + 2478, + 2475, + 2596, + 2598, + 0, + 2475, + 2472, + 2594, + 2596, + 0, + 2472, + 2468, + 2593, + 2594, + 0, + 2468, + 2464, + 2591, + 2593, + 0, + 2464, + 2460, + 2589, + 2591, + 0, + 2460, + 2456, + 2587, + 2589, + 0, + 2456, + 2451, + 2584, + 2587, + 0, + 2451, + 2448, + 2583, + 2584, + 0, + 2448, + 2438, + 2554, + 2583, + 0, + 2438, + 2441, + 2568, + 2554, + 0, + 2441, + 2442, + 2570, + 2568, + 0, + 2442, + 2452, + 2585, + 2570, + 0, + 2452, + 2455, + 2586, + 2585, + 0, + 2455, + 2459, + 2588, + 2586, + 0, + 2459, + 2463, + 2590, + 2588, + 0, + 2463, + 2467, + 2592, + 2590, + 0, + 2467, + 2473, + 2595, + 2592, + 0, + 2473, + 2476, + 2597, + 2595, + 0, + 2476, + 2479, + 2599, + 2597, + 0, + 2479, + 2483, + 2601, + 2599, + 0, + 2483, + 2488, + 2603, + 2601, + 0, + 2488, + 2496, + 2605, + 2603, + 0, + 2496, + 2507, + 2607, + 2605, + 0, + 2507, + 2519, + 2609, + 2607, + 0, + 2519, + 2529, + 2611, + 2609, + 0, + 2529, + 2531, + 2613, + 2611, + 0, + 2531, + 2533, + 2615, + 2613, + 0, + 2533, + 2535, + 2617, + 2615, + 0, + 2535, + 2541, + 2623, + 2617, + 0, + 2541, + 2546, + 2628, + 2623, + 0, + 2546, + 2549, + 2631, + 2628, + 0, + 2549, + 2551, + 2634, + 2631, + 0, + 2551, + 2556, + 2637, + 2634, + 0, + 2556, + 2559, + 2640, + 2637, + 0, + 2559, + 2562, + 2643, + 2640, + 0, + 2562, + 2564, + 2645, + 2643, + 0, + 2564, + 2569, + 2648, + 2645, + 0, + 2569, + 2567, + 2647, + 2648, + 0, + 2567, + 2563, + 2644, + 2647, + 0, + 2563, + 2561, + 2642, + 2644, + 0, + 2561, + 2558, + 2639, + 2642, + 0, + 2558, + 2555, + 2636, + 2639, + 0, + 2555, + 2550, + 2632, + 2636, + 0, + 2550, + 2547, + 2629, + 2632, + 0, + 2547, + 2545, + 2627, + 2629, + 0, + 2545, + 2543, + 2625, + 2627, + 0, + 2543, + 2542, + 2624, + 2625, + 0, + 2542, + 2539, + 2621, + 2624, + 0, + 2539, + 2537, + 2620, + 2621, + 0, + 32, + 43, + 44, + 47, + 50, + 52, + 53, + 56, + 59, + 62, + 64, + 66, + 69, + 70, + 67, + 63, + 60, + 58, + 55, + 48, + 41, + 39, + 37, + 35, + 30, + 28, + 26, + 23, + 22, + 20, + 17, + 15, + 13, + 11, + 9, + 7, + 5, + 3, + 2, + 1, + 4, + 6, + 8, + 10, + 12, + 14, + 16, + 18, + 19, + 21, + 24, + 25, + 27, + 29, + 33, + 36, + 38, + 40, + 42, + 45, + 65, + 72, + 74, + 76, + 78, + 80, + 82, + 81, + 79, + 77, + 75, + 73, + 71, + 68, + 61, + 57, + 54, + 51, + 49, + 46, + 34, + 31, + 0, + 2620, + 2622, + 2626, + 2630, + 2635, + 2641, + 2649, + 2651, + 2653, + 2655, + 2657, + 2659, + 2661, + 2660, + 2658, + 2656, + 2654, + 2652, + 2650, + 2646, + 2638, + 2633, + 2619, + 2618, + 2616, + 2614, + 2612, + 2610, + 2608, + 2606, + 2604, + 2602, + 2600, + 2598, + 2596, + 2594, + 2593, + 2591, + 2589, + 2587, + 2584, + 2583, + 2554, + 2568, + 2570, + 2585, + 2586, + 2588, + 2590, + 2592, + 2595, + 2597, + 2599, + 2601, + 2603, + 2605, + 2607, + 2609, + 2611, + 2613, + 2615, + 2617, + 2623, + 2628, + 2631, + 2634, + 2637, + 2640, + 2643, + 2645, + 2648, + 2647, + 2644, + 2642, + 2639, + 2636, + 2632, + 2629, + 2627, + 2625, + 2624, + 2621, + 0, + 2764, + 2776, + 2848, + 2837, + 0, + 2776, + 2800, + 2866, + 2848, + 0, + 2800, + 2808, + 2873, + 2866, + 0, + 2808, + 2817, + 2881, + 2873, + 0, + 2817, + 2826, + 2889, + 2881, + 0, + 2826, + 2829, + 2891, + 2889, + 0, + 2829, + 2833, + 2895, + 2891, + 0, + 2833, + 2836, + 2899, + 2895, + 0, + 2836, + 2839, + 2901, + 2899, + 0, + 2839, + 2841, + 2903, + 2901, + 0, + 2841, + 2840, + 2902, + 2903, + 0, + 2840, + 2838, + 2900, + 2902, + 0, + 2838, + 2835, + 2898, + 2900, + 0, + 2835, + 2831, + 2894, + 2898, + 0, + 2831, + 2828, + 2890, + 2894, + 0, + 2828, + 2825, + 2888, + 2890, + 0, + 2825, + 2818, + 2882, + 2888, + 0, + 2818, + 2810, + 2875, + 2882, + 0, + 2810, + 2803, + 2869, + 2875, + 0, + 2803, + 2794, + 2862, + 2869, + 0, + 2794, + 2786, + 2857, + 2862, + 0, + 2786, + 2741, + 2788, + 2857, + 0, + 2741, + 2733, + 2779, + 2788, + 0, + 2733, + 2727, + 2771, + 2779, + 0, + 2727, + 2721, + 2763, + 2771, + 0, + 2721, + 2715, + 2757, + 2763, + 0, + 2715, + 2711, + 2752, + 2757, + 0, + 2711, + 2707, + 2749, + 2752, + 0, + 2707, + 2701, + 2743, + 2749, + 0, + 2701, + 2696, + 2737, + 2743, + 0, + 2696, + 2692, + 2729, + 2737, + 0, + 2692, + 2687, + 2722, + 2729, + 0, + 2687, + 2684, + 2716, + 2722, + 0, + 2684, + 2681, + 2712, + 2716, + 0, + 2681, + 2678, + 2708, + 2712, + 0, + 2678, + 2675, + 2702, + 2708, + 0, + 2675, + 2672, + 2697, + 2702, + 0, + 2672, + 2671, + 2695, + 2697, + 0, + 2671, + 2668, + 2689, + 2695, + 0, + 2668, + 2666, + 2685, + 2689, + 0, + 2666, + 2665, + 2683, + 2685, + 0, + 2665, + 2662, + 2674, + 2683, + 0, + 2662, + 2663, + 2677, + 2674, + 0, + 2663, + 2664, + 2679, + 2677, + 0, + 2664, + 2667, + 2688, + 2679, + 0, + 2667, + 2669, + 2691, + 2688, + 0, + 2669, + 2670, + 2694, + 2691, + 0, + 2670, + 2673, + 2698, + 2694, + 0, + 2673, + 2676, + 2703, + 2698, + 0, + 2676, + 2680, + 2709, + 2703, + 0, + 2680, + 2682, + 2714, + 2709, + 0, + 2682, + 2686, + 2720, + 2714, + 0, + 2686, + 2690, + 2726, + 2720, + 0, + 2690, + 2693, + 2732, + 2726, + 0, + 2693, + 2700, + 2739, + 2732, + 0, + 2700, + 2705, + 2746, + 2739, + 0, + 2705, + 2710, + 2751, + 2746, + 0, + 2710, + 2717, + 2758, + 2751, + 0, + 2717, + 2723, + 2766, + 2758, + 0, + 2723, + 2728, + 2772, + 2766, + 0, + 2728, + 2734, + 2781, + 2772, + 0, + 2734, + 2754, + 2814, + 2781, + 0, + 2754, + 2778, + 2852, + 2814, + 0, + 2778, + 2784, + 2855, + 2852, + 0, + 2784, + 2791, + 2859, + 2855, + 0, + 2791, + 2797, + 2864, + 2859, + 0, + 2797, + 2802, + 2868, + 2864, + 0, + 2802, + 2809, + 2874, + 2868, + 0, + 2809, + 2813, + 2878, + 2874, + 0, + 2813, + 2815, + 2879, + 2878, + 0, + 2815, + 2819, + 2883, + 2879, + 0, + 2819, + 2821, + 2885, + 2883, + 0, + 2821, + 2820, + 2884, + 2885, + 0, + 2820, + 2816, + 2880, + 2884, + 0, + 2816, + 2812, + 2877, + 2880, + 0, + 2812, + 2807, + 2872, + 2877, + 0, + 2807, + 2801, + 2867, + 2872, + 0, + 2801, + 2798, + 2865, + 2867, + 0, + 2798, + 2792, + 2860, + 2865, + 0, + 2792, + 2789, + 2858, + 2860, + 0, + 2789, + 2767, + 2843, + 2858, + 0, + 2767, + 2764, + 2837, + 2843, + 0, + 2837, + 2848, + 2906, + 2893, + 0, + 2848, + 2866, + 2921, + 2906, + 0, + 2866, + 2873, + 2927, + 2921, + 0, + 2873, + 2881, + 2935, + 2927, + 0, + 2881, + 2889, + 2942, + 2935, + 0, + 2889, + 2891, + 2944, + 2942, + 0, + 2891, + 2895, + 2947, + 2944, + 0, + 2895, + 2899, + 2950, + 2947, + 0, + 2899, + 2901, + 2953, + 2950, + 0, + 2901, + 2903, + 2956, + 2953, + 0, + 2903, + 2902, + 2955, + 2956, + 0, + 2902, + 2900, + 2952, + 2955, + 0, + 2900, + 2898, + 2948, + 2952, + 0, + 2898, + 2894, + 2946, + 2948, + 0, + 2894, + 2890, + 2943, + 2946, + 0, + 2890, + 2888, + 2941, + 2943, + 0, + 2888, + 2882, + 2936, + 2941, + 0, + 2882, + 2875, + 2929, + 2936, + 0, + 2875, + 2869, + 2925, + 2929, + 0, + 2869, + 2862, + 2917, + 2925, + 0, + 2862, + 2857, + 2911, + 2917, + 0, + 2857, + 2788, + 2854, + 2911, + 0, + 2788, + 2779, + 2849, + 2854, + 0, + 2779, + 2771, + 2844, + 2849, + 0, + 2771, + 2763, + 2830, + 2844, + 0, + 2763, + 2757, + 2823, + 2830, + 0, + 2757, + 2752, + 2806, + 2823, + 0, + 2752, + 2749, + 2796, + 2806, + 0, + 2749, + 2743, + 2785, + 2796, + 0, + 2743, + 2737, + 2777, + 2785, + 0, + 2737, + 2729, + 2770, + 2777, + 0, + 2729, + 2722, + 2762, + 2770, + 0, + 2722, + 2716, + 2756, + 2762, + 0, + 2716, + 2712, + 2750, + 2756, + 0, + 2712, + 2708, + 2745, + 2750, + 0, + 2708, + 2702, + 2740, + 2745, + 0, + 2702, + 2697, + 2735, + 2740, + 0, + 2697, + 2695, + 2731, + 2735, + 0, + 2695, + 2689, + 2724, + 2731, + 0, + 2689, + 2685, + 2718, + 2724, + 0, + 2685, + 2683, + 2713, + 2718, + 0, + 2683, + 2674, + 2699, + 2713, + 0, + 2674, + 2677, + 2704, + 2699, + 0, + 2677, + 2679, + 2706, + 2704, + 0, + 2679, + 2688, + 2719, + 2706, + 0, + 2688, + 2691, + 2725, + 2719, + 0, + 2691, + 2694, + 2730, + 2725, + 0, + 2694, + 2698, + 2736, + 2730, + 0, + 2698, + 2703, + 2742, + 2736, + 0, + 2703, + 2709, + 2748, + 2742, + 0, + 2709, + 2714, + 2753, + 2748, + 0, + 2714, + 2720, + 2760, + 2753, + 0, + 2720, + 2726, + 2768, + 2760, + 0, + 2726, + 2732, + 2773, + 2768, + 0, + 2732, + 2739, + 2783, + 2773, + 0, + 2739, + 2746, + 2793, + 2783, + 0, + 2746, + 2751, + 2804, + 2793, + 0, + 2751, + 2758, + 2824, + 2804, + 0, + 2758, + 2766, + 2834, + 2824, + 0, + 2766, + 2772, + 2846, + 2834, + 0, + 2772, + 2781, + 2850, + 2846, + 0, + 2781, + 2814, + 2876, + 2850, + 0, + 2814, + 2852, + 2907, + 2876, + 0, + 2852, + 2855, + 2910, + 2907, + 0, + 2855, + 2859, + 2915, + 2910, + 0, + 2859, + 2864, + 2919, + 2915, + 0, + 2864, + 2868, + 2924, + 2919, + 0, + 2868, + 2874, + 2928, + 2924, + 0, + 2874, + 2878, + 2931, + 2928, + 0, + 2878, + 2879, + 2933, + 2931, + 0, + 2879, + 2883, + 2937, + 2933, + 0, + 2883, + 2885, + 2939, + 2937, + 0, + 2885, + 2884, + 2938, + 2939, + 0, + 2884, + 2880, + 2934, + 2938, + 0, + 2880, + 2877, + 2930, + 2934, + 0, + 2877, + 2872, + 2926, + 2930, + 0, + 2872, + 2867, + 2923, + 2926, + 0, + 2867, + 2865, + 2918, + 2923, + 0, + 2865, + 2860, + 2916, + 2918, + 0, + 2860, + 2858, + 2914, + 2916, + 0, + 2858, + 2843, + 2897, + 2914, + 0, + 2843, + 2837, + 2893, + 2897, + 0, + 2893, + 2906, + 2959, + 2949, + 0, + 2906, + 2921, + 2976, + 2959, + 0, + 2921, + 2927, + 2984, + 2976, + 0, + 2927, + 2935, + 2993, + 2984, + 0, + 2935, + 2942, + 3000, + 2993, + 0, + 2942, + 2944, + 3004, + 3000, + 0, + 2944, + 2947, + 3006, + 3004, + 0, + 2947, + 2950, + 3009, + 3006, + 0, + 2950, + 2953, + 3012, + 3009, + 0, + 2953, + 2956, + 3015, + 3012, + 0, + 2956, + 2955, + 3014, + 3015, + 0, + 2955, + 2952, + 3010, + 3014, + 0, + 2952, + 2948, + 3008, + 3010, + 0, + 2948, + 2946, + 3005, + 3008, + 0, + 2946, + 2943, + 3003, + 3005, + 0, + 2943, + 2941, + 2999, + 3003, + 0, + 2941, + 2936, + 2994, + 2999, + 0, + 2936, + 2929, + 2987, + 2994, + 0, + 2929, + 2925, + 2980, + 2987, + 0, + 2925, + 2917, + 2973, + 2980, + 0, + 2917, + 2911, + 2966, + 2973, + 0, + 2911, + 2854, + 2913, + 2966, + 0, + 2854, + 2849, + 2908, + 2913, + 0, + 2849, + 2844, + 2904, + 2908, + 0, + 2844, + 2830, + 2892, + 2904, + 0, + 2830, + 2823, + 2886, + 2892, + 0, + 2823, + 2806, + 2871, + 2886, + 0, + 2806, + 2796, + 2863, + 2871, + 0, + 2796, + 2785, + 2856, + 2863, + 0, + 2785, + 2777, + 2851, + 2856, + 0, + 2777, + 2770, + 2845, + 2851, + 0, + 2770, + 2762, + 2832, + 2845, + 0, + 2762, + 2756, + 2822, + 2832, + 0, + 2756, + 2750, + 2805, + 2822, + 0, + 2750, + 2745, + 2795, + 2805, + 0, + 2745, + 2740, + 2787, + 2795, + 0, + 2740, + 2735, + 2780, + 2787, + 0, + 2735, + 2731, + 2775, + 2780, + 0, + 2731, + 2724, + 2765, + 2775, + 0, + 2724, + 2718, + 2759, + 2765, + 0, + 2718, + 2713, + 2755, + 2759, + 0, + 2713, + 2699, + 2738, + 2755, + 0, + 2699, + 2704, + 2744, + 2738, + 0, + 2704, + 2706, + 2747, + 2744, + 0, + 2706, + 2719, + 2761, + 2747, + 0, + 2719, + 2725, + 2769, + 2761, + 0, + 2725, + 2730, + 2774, + 2769, + 0, + 2730, + 2736, + 2782, + 2774, + 0, + 2736, + 2742, + 2790, + 2782, + 0, + 2742, + 2748, + 2799, + 2790, + 0, + 2748, + 2753, + 2811, + 2799, + 0, + 2753, + 2760, + 2827, + 2811, + 0, + 2760, + 2768, + 2842, + 2827, + 0, + 2768, + 2773, + 2847, + 2842, + 0, + 2773, + 2783, + 2853, + 2847, + 0, + 2783, + 2793, + 2861, + 2853, + 0, + 2793, + 2804, + 2870, + 2861, + 0, + 2804, + 2824, + 2887, + 2870, + 0, + 2824, + 2834, + 2896, + 2887, + 0, + 2834, + 2846, + 2905, + 2896, + 0, + 2846, + 2850, + 2909, + 2905, + 0, + 2850, + 2876, + 2932, + 2909, + 0, + 2876, + 2907, + 2962, + 2932, + 0, + 2907, + 2910, + 2965, + 2962, + 0, + 2910, + 2915, + 2968, + 2965, + 0, + 2915, + 2919, + 2975, + 2968, + 0, + 2919, + 2924, + 2979, + 2975, + 0, + 2924, + 2928, + 2986, + 2979, + 0, + 2928, + 2931, + 2990, + 2986, + 0, + 2931, + 2933, + 2991, + 2990, + 0, + 2933, + 2937, + 2995, + 2991, + 0, + 2937, + 2939, + 2998, + 2995, + 0, + 2939, + 2938, + 2996, + 2998, + 0, + 2938, + 2934, + 2992, + 2996, + 0, + 2934, + 2930, + 2989, + 2992, + 0, + 2930, + 2926, + 2985, + 2989, + 0, + 2926, + 2923, + 2978, + 2985, + 0, + 2923, + 2918, + 2974, + 2978, + 0, + 2918, + 2916, + 2969, + 2974, + 0, + 2916, + 2914, + 2967, + 2969, + 0, + 2914, + 2897, + 2954, + 2967, + 0, + 2897, + 2893, + 2949, + 2954, + 0, + 2949, + 2959, + 3076, + 3070, + 0, + 2959, + 2976, + 3098, + 3076, + 0, + 2976, + 2984, + 3103, + 3098, + 0, + 2984, + 2993, + 3113, + 3103, + 0, + 2993, + 3000, + 3121, + 3113, + 0, + 3000, + 3004, + 3123, + 3121, + 0, + 3004, + 3006, + 3126, + 3123, + 0, + 3006, + 3009, + 3129, + 3126, + 0, + 3009, + 3012, + 3131, + 3129, + 0, + 3012, + 3015, + 3133, + 3131, + 0, + 3015, + 3014, + 3132, + 3133, + 0, + 3014, + 3010, + 3130, + 3132, + 0, + 3010, + 3008, + 3128, + 3130, + 0, + 3008, + 3005, + 3125, + 3128, + 0, + 3005, + 3003, + 3122, + 3125, + 0, + 3003, + 2999, + 3120, + 3122, + 0, + 2999, + 2994, + 3114, + 3120, + 0, + 2994, + 2987, + 3107, + 3114, + 0, + 2987, + 2980, + 3102, + 3107, + 0, + 2980, + 2973, + 3094, + 3102, + 0, + 2973, + 2966, + 3087, + 3094, + 0, + 2966, + 2913, + 3055, + 3087, + 0, + 2913, + 2908, + 3051, + 3055, + 0, + 2908, + 2904, + 3046, + 3051, + 0, + 2904, + 2892, + 3042, + 3046, + 0, + 2892, + 2886, + 3039, + 3042, + 0, + 2886, + 2871, + 3036, + 3039, + 0, + 2871, + 2863, + 3032, + 3036, + 0, + 2863, + 2856, + 3028, + 3032, + 0, + 2856, + 2851, + 3024, + 3028, + 0, + 2851, + 2845, + 3019, + 3024, + 0, + 2845, + 2832, + 3013, + 3019, + 0, + 2832, + 2822, + 3001, + 3013, + 0, + 2822, + 2805, + 2988, + 3001, + 0, + 2805, + 2795, + 2977, + 2988, + 0, + 2795, + 2787, + 2970, + 2977, + 0, + 2787, + 2780, + 2963, + 2970, + 0, + 2780, + 2775, + 2961, + 2963, + 0, + 2775, + 2765, + 2957, + 2961, + 0, + 2765, + 2759, + 2945, + 2957, + 0, + 2759, + 2755, + 2940, + 2945, + 0, + 2755, + 2738, + 2912, + 2940, + 0, + 2738, + 2744, + 2920, + 2912, + 0, + 2744, + 2747, + 2922, + 2920, + 0, + 2747, + 2761, + 2951, + 2922, + 0, + 2761, + 2769, + 2958, + 2951, + 0, + 2769, + 2774, + 2960, + 2958, + 0, + 2774, + 2782, + 2964, + 2960, + 0, + 2782, + 2790, + 2972, + 2964, + 0, + 2790, + 2799, + 2981, + 2972, + 0, + 2799, + 2811, + 2997, + 2981, + 0, + 2811, + 2827, + 3007, + 2997, + 0, + 2827, + 2842, + 3017, + 3007, + 0, + 2842, + 2847, + 3021, + 3017, + 0, + 2847, + 2853, + 3025, + 3021, + 0, + 2853, + 2861, + 3031, + 3025, + 0, + 2861, + 2870, + 3035, + 3031, + 0, + 2870, + 2887, + 3040, + 3035, + 0, + 2887, + 2896, + 3044, + 3040, + 0, + 2896, + 2905, + 3048, + 3044, + 0, + 2905, + 2909, + 3052, + 3048, + 0, + 2909, + 2932, + 3062, + 3052, + 0, + 2932, + 2962, + 3081, + 3062, + 0, + 2962, + 2965, + 3086, + 3081, + 0, + 2965, + 2968, + 3092, + 3086, + 0, + 2968, + 2975, + 3096, + 3092, + 0, + 2975, + 2979, + 3101, + 3096, + 0, + 2979, + 2986, + 3105, + 3101, + 0, + 2986, + 2990, + 3109, + 3105, + 0, + 2990, + 2991, + 3111, + 3109, + 0, + 2991, + 2995, + 3115, + 3111, + 0, + 2995, + 2998, + 3117, + 3115, + 0, + 2998, + 2996, + 3116, + 3117, + 0, + 2996, + 2992, + 3112, + 3116, + 0, + 2992, + 2989, + 3108, + 3112, + 0, + 2989, + 2985, + 3104, + 3108, + 0, + 2985, + 2978, + 3100, + 3104, + 0, + 2978, + 2974, + 3095, + 3100, + 0, + 2974, + 2969, + 3091, + 3095, + 0, + 2969, + 2967, + 3088, + 3091, + 0, + 2967, + 2954, + 3071, + 3088, + 0, + 2954, + 2949, + 3070, + 3071, + 0, + 3070, + 3076, + 3139, + 3134, + 0, + 3076, + 3098, + 3157, + 3139, + 0, + 3098, + 3103, + 3163, + 3157, + 0, + 3103, + 3113, + 3171, + 3163, + 0, + 3113, + 3121, + 3180, + 3171, + 0, + 3121, + 3123, + 3182, + 3180, + 0, + 3123, + 3126, + 3187, + 3182, + 0, + 3126, + 3129, + 3190, + 3187, + 0, + 3129, + 3131, + 3191, + 3190, + 0, + 3131, + 3133, + 3193, + 3191, + 0, + 3133, + 3132, + 3194, + 3193, + 0, + 3132, + 3130, + 3192, + 3194, + 0, + 3130, + 3128, + 3189, + 3192, + 0, + 3128, + 3125, + 3186, + 3189, + 0, + 3125, + 3122, + 3181, + 3186, + 0, + 3122, + 3120, + 3179, + 3181, + 0, + 3120, + 3114, + 3173, + 3179, + 0, + 3114, + 3107, + 3166, + 3173, + 0, + 3107, + 3102, + 3161, + 3166, + 0, + 3102, + 3094, + 3152, + 3161, + 0, + 3094, + 3087, + 3146, + 3152, + 0, + 3087, + 3055, + 3093, + 3146, + 0, + 3055, + 3051, + 3084, + 3093, + 0, + 3051, + 3046, + 3077, + 3084, + 0, + 3046, + 3042, + 3073, + 3077, + 0, + 3042, + 3039, + 3067, + 3073, + 0, + 3039, + 3036, + 3064, + 3067, + 0, + 3036, + 3032, + 3061, + 3064, + 0, + 3032, + 3028, + 3057, + 3061, + 0, + 3028, + 3024, + 3053, + 3057, + 0, + 3024, + 3019, + 3049, + 3053, + 0, + 3019, + 3013, + 3045, + 3049, + 0, + 3013, + 3001, + 3041, + 3045, + 0, + 3001, + 2988, + 3037, + 3041, + 0, + 2988, + 2977, + 3033, + 3037, + 0, + 2977, + 2970, + 3029, + 3033, + 0, + 2970, + 2963, + 3026, + 3029, + 0, + 2963, + 2961, + 3023, + 3026, + 0, + 2961, + 2957, + 3018, + 3023, + 0, + 2957, + 2945, + 3011, + 3018, + 0, + 2945, + 2940, + 3002, + 3011, + 0, + 2940, + 2912, + 2971, + 3002, + 0, + 2912, + 2920, + 2982, + 2971, + 0, + 2920, + 2922, + 2983, + 2982, + 0, + 2922, + 2951, + 3016, + 2983, + 0, + 2951, + 2958, + 3020, + 3016, + 0, + 2958, + 2960, + 3022, + 3020, + 0, + 2960, + 2964, + 3027, + 3022, + 0, + 2964, + 2972, + 3030, + 3027, + 0, + 2972, + 2981, + 3034, + 3030, + 0, + 2981, + 2997, + 3038, + 3034, + 0, + 2997, + 3007, + 3043, + 3038, + 0, + 3007, + 3017, + 3047, + 3043, + 0, + 3017, + 3021, + 3050, + 3047, + 0, + 3021, + 3025, + 3056, + 3050, + 0, + 3025, + 3031, + 3060, + 3056, + 0, + 3031, + 3035, + 3063, + 3060, + 0, + 3035, + 3040, + 3068, + 3063, + 0, + 3040, + 3044, + 3075, + 3068, + 0, + 3044, + 3048, + 3080, + 3075, + 0, + 3048, + 3052, + 3085, + 3080, + 0, + 3052, + 3062, + 3118, + 3085, + 0, + 3062, + 3081, + 3141, + 3118, + 0, + 3081, + 3086, + 3143, + 3141, + 0, + 3086, + 3092, + 3149, + 3143, + 0, + 3092, + 3096, + 3155, + 3149, + 0, + 3096, + 3101, + 3159, + 3155, + 0, + 3101, + 3105, + 3165, + 3159, + 0, + 3105, + 3109, + 3168, + 3165, + 0, + 3109, + 3111, + 3169, + 3168, + 0, + 3111, + 3115, + 3174, + 3169, + 0, + 3115, + 3117, + 3177, + 3174, + 0, + 3117, + 3116, + 3176, + 3177, + 0, + 3116, + 3112, + 3170, + 3176, + 0, + 3112, + 3108, + 3167, + 3170, + 0, + 3108, + 3104, + 3164, + 3167, + 0, + 3104, + 3100, + 3158, + 3164, + 0, + 3100, + 3095, + 3153, + 3158, + 0, + 3095, + 3091, + 3148, + 3153, + 0, + 3091, + 3088, + 3147, + 3148, + 0, + 3088, + 3071, + 3136, + 3147, + 0, + 3071, + 3070, + 3134, + 3136, + 0, + 3134, + 3139, + 3223, + 3217, + 0, + 3139, + 3157, + 3246, + 3223, + 0, + 3157, + 3163, + 3252, + 3246, + 0, + 3163, + 3171, + 3262, + 3252, + 0, + 3171, + 3180, + 3271, + 3262, + 0, + 3180, + 3182, + 3274, + 3271, + 0, + 3182, + 3187, + 3277, + 3274, + 0, + 3187, + 3190, + 3280, + 3277, + 0, + 3190, + 3191, + 3282, + 3280, + 0, + 3191, + 3193, + 3284, + 3282, + 0, + 3193, + 3194, + 3285, + 3284, + 0, + 3194, + 3192, + 3283, + 3285, + 0, + 3192, + 3189, + 3281, + 3283, + 0, + 3189, + 3186, + 3278, + 3281, + 0, + 3186, + 3181, + 3273, + 3278, + 0, + 3181, + 3179, + 3270, + 3273, + 0, + 3179, + 3173, + 3265, + 3270, + 0, + 3173, + 3166, + 3257, + 3265, + 0, + 3166, + 3161, + 3250, + 3257, + 0, + 3161, + 3152, + 3241, + 3250, + 0, + 3152, + 3146, + 3233, + 3241, + 0, + 3146, + 3093, + 3205, + 3233, + 0, + 3093, + 3084, + 3201, + 3205, + 0, + 3084, + 3077, + 3195, + 3201, + 0, + 3077, + 3073, + 3183, + 3195, + 0, + 3073, + 3067, + 3172, + 3183, + 0, + 3067, + 3064, + 3162, + 3172, + 0, + 3064, + 3061, + 3151, + 3162, + 0, + 3061, + 3057, + 3144, + 3151, + 0, + 3057, + 3053, + 3140, + 3144, + 0, + 3053, + 3049, + 3137, + 3140, + 0, + 3049, + 3045, + 3127, + 3137, + 0, + 3045, + 3041, + 3119, + 3127, + 0, + 3041, + 3037, + 3106, + 3119, + 0, + 3037, + 3033, + 3097, + 3106, + 0, + 3033, + 3029, + 3089, + 3097, + 0, + 3029, + 3026, + 3082, + 3089, + 0, + 3026, + 3023, + 3079, + 3082, + 0, + 3023, + 3018, + 3072, + 3079, + 0, + 3018, + 3011, + 3066, + 3072, + 0, + 3011, + 3002, + 3065, + 3066, + 0, + 3002, + 2971, + 3054, + 3065, + 0, + 2971, + 2982, + 3058, + 3054, + 0, + 2982, + 2983, + 3059, + 3058, + 0, + 2983, + 3016, + 3069, + 3059, + 0, + 3016, + 3020, + 3074, + 3069, + 0, + 3020, + 3022, + 3078, + 3074, + 0, + 3022, + 3027, + 3083, + 3078, + 0, + 3027, + 3030, + 3090, + 3083, + 0, + 3030, + 3034, + 3099, + 3090, + 0, + 3034, + 3038, + 3110, + 3099, + 0, + 3038, + 3043, + 3124, + 3110, + 0, + 3043, + 3047, + 3135, + 3124, + 0, + 3047, + 3050, + 3138, + 3135, + 0, + 3050, + 3056, + 3142, + 3138, + 0, + 3056, + 3060, + 3150, + 3142, + 0, + 3060, + 3063, + 3160, + 3150, + 0, + 3063, + 3068, + 3175, + 3160, + 0, + 3068, + 3075, + 3185, + 3175, + 0, + 3075, + 3080, + 3198, + 3185, + 0, + 3080, + 3085, + 3202, + 3198, + 0, + 3085, + 3118, + 3211, + 3202, + 0, + 3118, + 3141, + 3227, + 3211, + 0, + 3141, + 3143, + 3231, + 3227, + 0, + 3143, + 3149, + 3239, + 3231, + 0, + 3149, + 3155, + 3243, + 3239, + 0, + 3155, + 3159, + 3249, + 3243, + 0, + 3159, + 3165, + 3255, + 3249, + 0, + 3165, + 3168, + 3259, + 3255, + 0, + 3168, + 3169, + 3261, + 3259, + 0, + 3169, + 3174, + 3264, + 3261, + 0, + 3174, + 3177, + 3268, + 3264, + 0, + 3177, + 3176, + 3267, + 3268, + 0, + 3176, + 3170, + 3260, + 3267, + 0, + 3170, + 3167, + 3258, + 3260, + 0, + 3167, + 3164, + 3253, + 3258, + 0, + 3164, + 3158, + 3248, + 3253, + 0, + 3158, + 3153, + 3242, + 3248, + 0, + 3153, + 3148, + 3238, + 3242, + 0, + 3148, + 3147, + 3234, + 3238, + 0, + 3147, + 3136, + 3218, + 3234, + 0, + 3136, + 3134, + 3217, + 3218, + 0, + 3217, + 3223, + 3320, + 3313, + 0, + 3223, + 3246, + 3343, + 3320, + 0, + 3246, + 3252, + 3352, + 3343, + 0, + 3252, + 3262, + 3360, + 3352, + 0, + 3262, + 3271, + 3367, + 3360, + 0, + 3271, + 3274, + 3371, + 3367, + 0, + 3274, + 3277, + 3373, + 3371, + 0, + 3277, + 3280, + 3377, + 3373, + 0, + 3280, + 3282, + 3380, + 3377, + 0, + 3282, + 3284, + 3382, + 3380, + 0, + 3284, + 3285, + 3383, + 3382, + 0, + 3285, + 3283, + 3381, + 3383, + 0, + 3283, + 3281, + 3379, + 3381, + 0, + 3281, + 3278, + 3375, + 3379, + 0, + 3278, + 3273, + 3372, + 3375, + 0, + 3273, + 3270, + 3368, + 3372, + 0, + 3270, + 3265, + 3363, + 3368, + 0, + 3265, + 3257, + 3355, + 3363, + 0, + 3257, + 3250, + 3350, + 3355, + 0, + 3250, + 3241, + 3340, + 3350, + 0, + 3241, + 3233, + 3332, + 3340, + 0, + 3233, + 3205, + 3300, + 3332, + 0, + 3205, + 3201, + 3295, + 3300, + 0, + 3201, + 3195, + 3290, + 3295, + 0, + 3195, + 3183, + 3287, + 3290, + 0, + 3183, + 3172, + 3275, + 3287, + 0, + 3172, + 3162, + 3266, + 3275, + 0, + 3162, + 3151, + 3251, + 3266, + 0, + 3151, + 3144, + 3240, + 3251, + 0, + 3144, + 3140, + 3232, + 3240, + 0, + 3140, + 3137, + 3225, + 3232, + 0, + 3137, + 3127, + 3221, + 3225, + 0, + 3127, + 3119, + 3216, + 3221, + 0, + 3119, + 3106, + 3212, + 3216, + 0, + 3106, + 3097, + 3209, + 3212, + 0, + 3097, + 3089, + 3206, + 3209, + 0, + 3089, + 3082, + 3203, + 3206, + 0, + 3082, + 3079, + 3200, + 3203, + 0, + 3079, + 3072, + 3196, + 3200, + 0, + 3072, + 3066, + 3184, + 3196, + 0, + 3066, + 3065, + 3178, + 3184, + 0, + 3065, + 3054, + 3145, + 3178, + 0, + 3054, + 3058, + 3154, + 3145, + 0, + 3058, + 3059, + 3156, + 3154, + 0, + 3059, + 3069, + 3188, + 3156, + 0, + 3069, + 3074, + 3197, + 3188, + 0, + 3074, + 3078, + 3199, + 3197, + 0, + 3078, + 3083, + 3204, + 3199, + 0, + 3083, + 3090, + 3207, + 3204, + 0, + 3090, + 3099, + 3210, + 3207, + 0, + 3099, + 3110, + 3215, + 3210, + 0, + 3110, + 3124, + 3219, + 3215, + 0, + 3124, + 3135, + 3222, + 3219, + 0, + 3135, + 3138, + 3228, + 3222, + 0, + 3138, + 3142, + 3235, + 3228, + 0, + 3142, + 3150, + 3247, + 3235, + 0, + 3150, + 3160, + 3263, + 3247, + 0, + 3160, + 3175, + 3276, + 3263, + 0, + 3175, + 3185, + 3288, + 3276, + 0, + 3185, + 3198, + 3292, + 3288, + 0, + 3198, + 3202, + 3296, + 3292, + 0, + 3202, + 3211, + 3308, + 3296, + 0, + 3211, + 3227, + 3325, + 3308, + 0, + 3227, + 3231, + 3330, + 3325, + 0, + 3231, + 3239, + 3337, + 3330, + 0, + 3239, + 3243, + 3342, + 3337, + 0, + 3243, + 3249, + 3348, + 3342, + 0, + 3249, + 3255, + 3354, + 3348, + 0, + 3255, + 3259, + 3357, + 3354, + 0, + 3259, + 3261, + 3361, + 3357, + 0, + 3261, + 3264, + 3362, + 3361, + 0, + 3264, + 3268, + 3365, + 3362, + 0, + 3268, + 3267, + 3364, + 3365, + 0, + 3267, + 3260, + 3359, + 3364, + 0, + 3260, + 3258, + 3356, + 3359, + 0, + 3258, + 3253, + 3353, + 3356, + 0, + 3253, + 3248, + 3347, + 3353, + 0, + 3248, + 3242, + 3341, + 3347, + 0, + 3242, + 3238, + 3334, + 3341, + 0, + 3238, + 3234, + 3331, + 3334, + 0, + 3234, + 3218, + 3314, + 3331, + 0, + 3218, + 3217, + 3313, + 3314, + 0, + 3313, + 3320, + 3395, + 3389, + 0, + 3320, + 3343, + 3420, + 3395, + 0, + 3343, + 3352, + 3427, + 3420, + 0, + 3352, + 3360, + 3437, + 3427, + 0, + 3360, + 3367, + 3446, + 3437, + 0, + 3367, + 3371, + 3451, + 3446, + 0, + 3371, + 3373, + 3454, + 3451, + 0, + 3373, + 3377, + 3458, + 3454, + 0, + 3377, + 3380, + 3460, + 3458, + 0, + 3380, + 3382, + 3464, + 3460, + 0, + 3382, + 3383, + 3465, + 3464, + 0, + 3383, + 3381, + 3461, + 3465, + 0, + 3381, + 3379, + 3459, + 3461, + 0, + 3379, + 3375, + 3455, + 3459, + 0, + 3375, + 3372, + 3452, + 3455, + 0, + 3372, + 3368, + 3447, + 3452, + 0, + 3368, + 3363, + 3442, + 3447, + 0, + 3363, + 3355, + 3431, + 3442, + 0, + 3355, + 3350, + 3425, + 3431, + 0, + 3350, + 3340, + 3415, + 3425, + 0, + 3340, + 3332, + 3408, + 3415, + 0, + 3332, + 3300, + 3344, + 3408, + 0, + 3300, + 3295, + 3335, + 3344, + 0, + 3295, + 3290, + 3326, + 3335, + 0, + 3290, + 3287, + 3321, + 3326, + 0, + 3287, + 3275, + 3316, + 3321, + 0, + 3275, + 3266, + 3311, + 3316, + 0, + 3266, + 3251, + 3307, + 3311, + 0, + 3251, + 3240, + 3305, + 3307, + 0, + 3240, + 3232, + 3301, + 3305, + 0, + 3232, + 3225, + 3297, + 3301, + 0, + 3225, + 3221, + 3293, + 3297, + 0, + 3221, + 3216, + 3289, + 3293, + 0, + 3216, + 3212, + 3279, + 3289, + 0, + 3212, + 3209, + 3269, + 3279, + 0, + 3209, + 3206, + 3254, + 3269, + 0, + 3206, + 3203, + 3244, + 3254, + 0, + 3203, + 3200, + 3237, + 3244, + 0, + 3200, + 3196, + 3229, + 3237, + 0, + 3196, + 3184, + 3224, + 3229, + 0, + 3184, + 3178, + 3220, + 3224, + 0, + 3178, + 3145, + 3208, + 3220, + 0, + 3145, + 3154, + 3213, + 3208, + 0, + 3154, + 3156, + 3214, + 3213, + 0, + 3156, + 3188, + 3226, + 3214, + 0, + 3188, + 3197, + 3230, + 3226, + 0, + 3197, + 3199, + 3236, + 3230, + 0, + 3199, + 3204, + 3245, + 3236, + 0, + 3204, + 3207, + 3256, + 3245, + 0, + 3207, + 3210, + 3272, + 3256, + 0, + 3210, + 3215, + 3286, + 3272, + 0, + 3215, + 3219, + 3291, + 3286, + 0, + 3219, + 3222, + 3294, + 3291, + 0, + 3222, + 3228, + 3298, + 3294, + 0, + 3228, + 3235, + 3302, + 3298, + 0, + 3235, + 3247, + 3306, + 3302, + 0, + 3247, + 3263, + 3310, + 3306, + 0, + 3263, + 3276, + 3317, + 3310, + 0, + 3276, + 3288, + 3322, + 3317, + 0, + 3288, + 3292, + 3327, + 3322, + 0, + 3292, + 3296, + 3336, + 3327, + 0, + 3296, + 3308, + 3374, + 3336, + 0, + 3308, + 3325, + 3400, + 3374, + 0, + 3325, + 3330, + 3405, + 3400, + 0, + 3330, + 3337, + 3412, + 3405, + 0, + 3337, + 3342, + 3418, + 3412, + 0, + 3342, + 3348, + 3424, + 3418, + 0, + 3348, + 3354, + 3429, + 3424, + 0, + 3354, + 3357, + 3435, + 3429, + 0, + 3357, + 3361, + 3439, + 3435, + 0, + 3361, + 3362, + 3440, + 3439, + 0, + 3362, + 3365, + 3443, + 3440, + 0, + 3365, + 3364, + 3441, + 3443, + 0, + 3364, + 3359, + 3438, + 3441, + 0, + 3359, + 3356, + 3433, + 3438, + 0, + 3356, + 3353, + 3428, + 3433, + 0, + 3353, + 3347, + 3423, + 3428, + 0, + 3347, + 3341, + 3416, + 3423, + 0, + 3341, + 3334, + 3410, + 3416, + 0, + 3334, + 3331, + 3406, + 3410, + 0, + 3331, + 3314, + 3390, + 3406, + 0, + 3314, + 3313, + 3389, + 3390, + 0, + 3389, + 3395, + 3502, + 3494, + 0, + 3395, + 3420, + 3528, + 3502, + 0, + 3420, + 3427, + 3535, + 3528, + 0, + 3427, + 3437, + 3544, + 3535, + 0, + 3437, + 3446, + 3554, + 3544, + 0, + 3446, + 3451, + 3558, + 3554, + 0, + 3451, + 3454, + 3560, + 3558, + 0, + 3454, + 3458, + 3564, + 3560, + 0, + 3458, + 3460, + 3568, + 3564, + 0, + 3460, + 3464, + 3570, + 3568, + 0, + 3464, + 3465, + 3571, + 3570, + 0, + 3465, + 3461, + 3569, + 3571, + 0, + 3461, + 3459, + 3566, + 3569, + 0, + 3459, + 3455, + 3561, + 3566, + 0, + 3455, + 3452, + 3559, + 3561, + 0, + 3452, + 3447, + 3556, + 3559, + 0, + 3447, + 3442, + 3549, + 3556, + 0, + 3442, + 3431, + 3539, + 3549, + 0, + 3431, + 3425, + 3533, + 3539, + 0, + 3425, + 3415, + 3524, + 3533, + 0, + 3415, + 3408, + 3517, + 3524, + 0, + 3408, + 3344, + 3475, + 3517, + 0, + 3344, + 3335, + 3469, + 3475, + 0, + 3335, + 3326, + 3457, + 3469, + 0, + 3326, + 3321, + 3445, + 3457, + 0, + 3321, + 3316, + 3430, + 3445, + 0, + 3316, + 3311, + 3421, + 3430, + 0, + 3311, + 3307, + 3409, + 3421, + 0, + 3307, + 3305, + 3401, + 3409, + 0, + 3305, + 3301, + 3396, + 3401, + 0, + 3301, + 3297, + 3391, + 3396, + 0, + 3297, + 3293, + 3384, + 3391, + 0, + 3293, + 3289, + 3370, + 3384, + 0, + 3289, + 3279, + 3358, + 3370, + 0, + 3279, + 3269, + 3346, + 3358, + 0, + 3269, + 3254, + 3338, + 3346, + 0, + 3254, + 3244, + 3328, + 3338, + 0, + 3244, + 3237, + 3324, + 3328, + 0, + 3237, + 3229, + 3318, + 3324, + 0, + 3229, + 3224, + 3312, + 3318, + 0, + 3224, + 3220, + 3309, + 3312, + 0, + 3220, + 3208, + 3299, + 3309, + 0, + 3208, + 3213, + 3303, + 3299, + 0, + 3213, + 3214, + 3304, + 3303, + 0, + 3214, + 3226, + 3315, + 3304, + 0, + 3226, + 3230, + 3319, + 3315, + 0, + 3230, + 3236, + 3323, + 3319, + 0, + 3236, + 3245, + 3329, + 3323, + 0, + 3245, + 3256, + 3339, + 3329, + 0, + 3256, + 3272, + 3351, + 3339, + 0, + 3272, + 3286, + 3366, + 3351, + 0, + 3286, + 3291, + 3376, + 3366, + 0, + 3291, + 3294, + 3386, + 3376, + 0, + 3294, + 3298, + 3392, + 3386, + 0, + 3298, + 3302, + 3399, + 3392, + 0, + 3302, + 3306, + 3407, + 3399, + 0, + 3306, + 3310, + 3419, + 3407, + 0, + 3310, + 3317, + 3432, + 3419, + 0, + 3317, + 3322, + 3448, + 3432, + 0, + 3322, + 3327, + 3462, + 3448, + 0, + 3327, + 3336, + 3470, + 3462, + 0, + 3336, + 3374, + 3487, + 3470, + 0, + 3374, + 3400, + 3507, + 3487, + 0, + 3400, + 3405, + 3513, + 3507, + 0, + 3405, + 3412, + 3521, + 3513, + 0, + 3412, + 3418, + 3527, + 3521, + 0, + 3418, + 3424, + 3532, + 3527, + 0, + 3424, + 3429, + 3538, + 3532, + 0, + 3429, + 3435, + 3543, + 3538, + 0, + 3435, + 3439, + 3546, + 3543, + 0, + 3439, + 3440, + 3547, + 3546, + 0, + 3440, + 3443, + 3550, + 3547, + 0, + 3443, + 3441, + 3548, + 3550, + 0, + 3441, + 3438, + 3545, + 3548, + 0, + 3438, + 3433, + 3542, + 3545, + 0, + 3433, + 3428, + 3536, + 3542, + 0, + 3428, + 3423, + 3531, + 3536, + 0, + 3423, + 3416, + 3525, + 3531, + 0, + 3416, + 3410, + 3518, + 3525, + 0, + 3410, + 3406, + 3515, + 3518, + 0, + 3406, + 3390, + 3497, + 3515, + 0, + 3390, + 3389, + 3494, + 3497, + 0, + 3494, + 3502, + 3577, + 3567, + 0, + 3502, + 3528, + 3598, + 3577, + 0, + 3528, + 3535, + 3603, + 3598, + 0, + 3535, + 3544, + 3611, + 3603, + 0, + 3544, + 3554, + 3619, + 3611, + 0, + 3554, + 3558, + 3622, + 3619, + 0, + 3558, + 3560, + 3625, + 3622, + 0, + 3560, + 3564, + 3628, + 3625, + 0, + 3564, + 3568, + 3630, + 3628, + 0, + 3568, + 3570, + 3632, + 3630, + 0, + 3570, + 3571, + 3633, + 3632, + 0, + 3571, + 3569, + 3631, + 3633, + 0, + 3569, + 3566, + 3629, + 3631, + 0, + 3566, + 3561, + 3626, + 3629, + 0, + 3561, + 3559, + 3623, + 3626, + 0, + 3559, + 3556, + 3621, + 3623, + 0, + 3556, + 3549, + 3616, + 3621, + 0, + 3549, + 3539, + 3607, + 3616, + 0, + 3539, + 3533, + 3602, + 3607, + 0, + 3533, + 3524, + 3595, + 3602, + 0, + 3524, + 3517, + 3589, + 3595, + 0, + 3517, + 3475, + 3519, + 3589, + 0, + 3475, + 3469, + 3509, + 3519, + 0, + 3469, + 3457, + 3503, + 3509, + 0, + 3457, + 3445, + 3498, + 3503, + 0, + 3445, + 3430, + 3491, + 3498, + 0, + 3430, + 3421, + 3486, + 3491, + 0, + 3421, + 3409, + 3482, + 3486, + 0, + 3409, + 3401, + 3478, + 3482, + 0, + 3401, + 3396, + 3473, + 3478, + 0, + 3396, + 3391, + 3466, + 3473, + 0, + 3391, + 3384, + 3449, + 3466, + 0, + 3384, + 3370, + 3434, + 3449, + 0, + 3370, + 3358, + 3422, + 3434, + 0, + 3358, + 3346, + 3411, + 3422, + 0, + 3346, + 3338, + 3402, + 3411, + 0, + 3338, + 3328, + 3397, + 3402, + 0, + 3328, + 3324, + 3394, + 3397, + 0, + 3324, + 3318, + 3387, + 3394, + 0, + 3318, + 3312, + 3378, + 3387, + 0, + 3312, + 3309, + 3369, + 3378, + 0, + 3309, + 3299, + 3333, + 3369, + 0, + 3299, + 3303, + 3345, + 3333, + 0, + 3303, + 3304, + 3349, + 3345, + 0, + 3304, + 3315, + 3385, + 3349, + 0, + 3315, + 3319, + 3388, + 3385, + 0, + 3319, + 3323, + 3393, + 3388, + 0, + 3323, + 3329, + 3398, + 3393, + 0, + 3329, + 3339, + 3404, + 3398, + 0, + 3339, + 3351, + 3413, + 3404, + 0, + 3351, + 3366, + 3426, + 3413, + 0, + 3366, + 3376, + 3444, + 3426, + 0, + 3376, + 3386, + 3456, + 3444, + 0, + 3386, + 3392, + 3468, + 3456, + 0, + 3392, + 3399, + 3474, + 3468, + 0, + 3399, + 3407, + 3481, + 3474, + 0, + 3407, + 3419, + 3485, + 3481, + 0, + 3419, + 3432, + 3492, + 3485, + 0, + 3432, + 3448, + 3499, + 3492, + 0, + 3448, + 3462, + 3505, + 3499, + 0, + 3462, + 3470, + 3510, + 3505, + 0, + 3470, + 3487, + 3551, + 3510, + 0, + 3487, + 3507, + 3582, + 3551, + 0, + 3507, + 3513, + 3585, + 3582, + 0, + 3513, + 3521, + 3592, + 3585, + 0, + 3521, + 3527, + 3597, + 3592, + 0, + 3527, + 3532, + 3601, + 3597, + 0, + 3532, + 3538, + 3606, + 3601, + 0, + 3538, + 3543, + 3609, + 3606, + 0, + 3543, + 3546, + 3613, + 3609, + 0, + 3546, + 3547, + 3614, + 3613, + 0, + 3547, + 3550, + 3617, + 3614, + 0, + 3550, + 3548, + 3615, + 3617, + 0, + 3548, + 3545, + 3612, + 3615, + 0, + 3545, + 3542, + 3608, + 3612, + 0, + 3542, + 3536, + 3605, + 3608, + 0, + 3536, + 3531, + 3600, + 3605, + 0, + 3531, + 3525, + 3596, + 3600, + 0, + 3525, + 3518, + 3590, + 3596, + 0, + 3518, + 3515, + 3588, + 3590, + 0, + 3515, + 3497, + 3572, + 3588, + 0, + 3497, + 3494, + 3567, + 3572, + 0, + 3567, + 3577, + 3638, + 3634, + 0, + 3577, + 3598, + 3654, + 3638, + 0, + 3598, + 3603, + 3660, + 3654, + 0, + 3603, + 3611, + 3667, + 3660, + 0, + 3611, + 3619, + 3674, + 3667, + 0, + 3619, + 3622, + 3676, + 3674, + 0, + 3622, + 3625, + 3678, + 3676, + 0, + 3625, + 3628, + 3680, + 3678, + 0, + 3628, + 3630, + 3682, + 3680, + 0, + 3630, + 3632, + 3684, + 3682, + 0, + 3632, + 3633, + 3685, + 3684, + 0, + 3633, + 3631, + 3683, + 3685, + 0, + 3631, + 3629, + 3681, + 3683, + 0, + 3629, + 3626, + 3679, + 3681, + 0, + 3626, + 3623, + 3677, + 3679, + 0, + 3623, + 3621, + 3675, + 3677, + 0, + 3621, + 3616, + 3673, + 3675, + 0, + 3616, + 3607, + 3664, + 3673, + 0, + 3607, + 3602, + 3659, + 3664, + 0, + 3602, + 3595, + 3652, + 3659, + 0, + 3595, + 3589, + 3646, + 3652, + 0, + 3589, + 3519, + 3593, + 3646, + 0, + 3519, + 3509, + 3584, + 3593, + 0, + 3509, + 3503, + 3579, + 3584, + 0, + 3503, + 3498, + 3574, + 3579, + 0, + 3498, + 3491, + 3562, + 3574, + 0, + 3491, + 3486, + 3553, + 3562, + 0, + 3486, + 3482, + 3537, + 3553, + 0, + 3482, + 3478, + 3526, + 3537, + 0, + 3478, + 3473, + 3516, + 3526, + 0, + 3473, + 3466, + 3508, + 3516, + 0, + 3466, + 3449, + 3501, + 3508, + 0, + 3449, + 3434, + 3495, + 3501, + 0, + 3434, + 3422, + 3489, + 3495, + 0, + 3422, + 3411, + 3483, + 3489, + 0, + 3411, + 3402, + 3479, + 3483, + 0, + 3402, + 3397, + 3476, + 3479, + 0, + 3397, + 3394, + 3472, + 3476, + 0, + 3394, + 3387, + 3463, + 3472, + 0, + 3387, + 3378, + 3450, + 3463, + 0, + 3378, + 3369, + 3436, + 3450, + 0, + 3369, + 3333, + 3403, + 3436, + 0, + 3333, + 3345, + 3414, + 3403, + 0, + 3345, + 3349, + 3417, + 3414, + 0, + 3349, + 3385, + 3453, + 3417, + 0, + 3385, + 3388, + 3467, + 3453, + 0, + 3388, + 3393, + 3471, + 3467, + 0, + 3393, + 3398, + 3477, + 3471, + 0, + 3398, + 3404, + 3480, + 3477, + 0, + 3404, + 3413, + 3484, + 3480, + 0, + 3413, + 3426, + 3490, + 3484, + 0, + 3426, + 3444, + 3500, + 3490, + 0, + 3444, + 3456, + 3504, + 3500, + 0, + 3456, + 3468, + 3511, + 3504, + 0, + 3468, + 3474, + 3523, + 3511, + 0, + 3474, + 3481, + 3534, + 3523, + 0, + 3481, + 3485, + 3552, + 3534, + 0, + 3485, + 3492, + 3563, + 3552, + 0, + 3492, + 3499, + 3576, + 3563, + 0, + 3499, + 3505, + 3581, + 3576, + 0, + 3505, + 3510, + 3586, + 3581, + 0, + 3510, + 3551, + 3620, + 3586, + 0, + 3551, + 3582, + 3641, + 3620, + 0, + 3582, + 3585, + 3644, + 3641, + 0, + 3585, + 3592, + 3650, + 3644, + 0, + 3592, + 3597, + 3653, + 3650, + 0, + 3597, + 3601, + 3658, + 3653, + 0, + 3601, + 3606, + 3662, + 3658, + 0, + 3606, + 3609, + 3666, + 3662, + 0, + 3609, + 3613, + 3669, + 3666, + 0, + 3613, + 3614, + 3670, + 3669, + 0, + 3614, + 3617, + 3672, + 3670, + 0, + 3617, + 3615, + 3671, + 3672, + 0, + 3615, + 3612, + 3668, + 3671, + 0, + 3612, + 3608, + 3665, + 3668, + 0, + 3608, + 3605, + 3661, + 3665, + 0, + 3605, + 3600, + 3657, + 3661, + 0, + 3600, + 3596, + 3651, + 3657, + 0, + 3596, + 3590, + 3648, + 3651, + 0, + 3590, + 3588, + 3645, + 3648, + 0, + 3588, + 3572, + 3635, + 3645, + 0, + 3572, + 3567, + 3634, + 3635, + 0, + 3634, + 3638, + 3689, + 3687, + 0, + 3638, + 3654, + 3705, + 3689, + 0, + 3654, + 3660, + 3709, + 3705, + 0, + 3660, + 3667, + 3717, + 3709, + 0, + 3667, + 3674, + 3727, + 3717, + 0, + 3674, + 3676, + 3730, + 3727, + 0, + 3676, + 3678, + 3733, + 3730, + 0, + 3678, + 3680, + 3737, + 3733, + 0, + 3680, + 3682, + 3740, + 3737, + 0, + 3682, + 3684, + 3742, + 3740, + 0, + 3684, + 3685, + 3743, + 3742, + 0, + 3685, + 3683, + 3741, + 3743, + 0, + 3683, + 3681, + 3738, + 3741, + 0, + 3681, + 3679, + 3735, + 3738, + 0, + 3679, + 3677, + 3731, + 3735, + 0, + 3677, + 3675, + 3728, + 3731, + 0, + 3675, + 3673, + 3724, + 3728, + 0, + 3673, + 3664, + 3713, + 3724, + 0, + 3664, + 3659, + 3708, + 3713, + 0, + 3659, + 3652, + 3703, + 3708, + 0, + 3652, + 3646, + 3696, + 3703, + 0, + 3646, + 3593, + 3663, + 3696, + 0, + 3593, + 3584, + 3655, + 3663, + 0, + 3584, + 3579, + 3647, + 3655, + 0, + 3579, + 3574, + 3642, + 3647, + 0, + 3574, + 3562, + 3639, + 3642, + 0, + 3562, + 3553, + 3637, + 3639, + 0, + 3553, + 3537, + 3627, + 3637, + 0, + 3537, + 3526, + 3618, + 3627, + 0, + 3526, + 3516, + 3604, + 3618, + 0, + 3516, + 3508, + 3594, + 3604, + 0, + 3508, + 3501, + 3587, + 3594, + 0, + 3501, + 3495, + 3580, + 3587, + 0, + 3495, + 3489, + 3575, + 3580, + 0, + 3489, + 3483, + 3565, + 3575, + 0, + 3483, + 3479, + 3555, + 3565, + 0, + 3479, + 3476, + 3540, + 3555, + 0, + 3476, + 3472, + 3530, + 3540, + 0, + 3472, + 3463, + 3520, + 3530, + 0, + 3463, + 3450, + 3512, + 3520, + 0, + 3450, + 3436, + 3506, + 3512, + 0, + 3436, + 3403, + 3488, + 3506, + 0, + 3403, + 3414, + 3493, + 3488, + 0, + 3414, + 3417, + 3496, + 3493, + 0, + 3417, + 3453, + 3514, + 3496, + 0, + 3453, + 3467, + 3522, + 3514, + 0, + 3467, + 3471, + 3529, + 3522, + 0, + 3471, + 3477, + 3541, + 3529, + 0, + 3477, + 3480, + 3557, + 3541, + 0, + 3480, + 3484, + 3573, + 3557, + 0, + 3484, + 3490, + 3578, + 3573, + 0, + 3490, + 3500, + 3583, + 3578, + 0, + 3500, + 3504, + 3591, + 3583, + 0, + 3504, + 3511, + 3599, + 3591, + 0, + 3511, + 3523, + 3610, + 3599, + 0, + 3523, + 3534, + 3624, + 3610, + 0, + 3534, + 3552, + 3636, + 3624, + 0, + 3552, + 3563, + 3640, + 3636, + 0, + 3563, + 3576, + 3643, + 3640, + 0, + 3576, + 3581, + 3649, + 3643, + 0, + 3581, + 3586, + 3656, + 3649, + 0, + 3586, + 3620, + 3686, + 3656, + 0, + 3620, + 3641, + 3691, + 3686, + 0, + 3641, + 3644, + 3693, + 3691, + 0, + 3644, + 3650, + 3700, + 3693, + 0, + 3650, + 3653, + 3704, + 3700, + 0, + 3653, + 3658, + 3707, + 3704, + 0, + 3658, + 3662, + 3712, + 3707, + 0, + 3662, + 3666, + 3716, + 3712, + 0, + 3666, + 3669, + 3719, + 3716, + 0, + 3669, + 3670, + 3720, + 3719, + 0, + 3670, + 3672, + 3723, + 3720, + 0, + 3672, + 3671, + 3721, + 3723, + 0, + 3671, + 3668, + 3718, + 3721, + 0, + 3668, + 3665, + 3714, + 3718, + 0, + 3665, + 3661, + 3710, + 3714, + 0, + 3661, + 3657, + 3706, + 3710, + 0, + 3657, + 3651, + 3702, + 3706, + 0, + 3651, + 3648, + 3697, + 3702, + 0, + 3648, + 3645, + 3694, + 3697, + 0, + 3645, + 3635, + 3688, + 3694, + 0, + 3635, + 3634, + 3687, + 3688, + 0, + 3687, + 3689, + 3843, + 3837, + 0, + 3689, + 3705, + 3865, + 3843, + 0, + 3705, + 3709, + 3877, + 3865, + 0, + 3709, + 3717, + 3888, + 3877, + 0, + 3717, + 3727, + 3905, + 3888, + 0, + 3727, + 3730, + 3910, + 3905, + 0, + 3730, + 3733, + 3914, + 3910, + 0, + 3733, + 3737, + 3918, + 3914, + 0, + 3737, + 3740, + 3921, + 3918, + 0, + 3740, + 3742, + 3924, + 3921, + 0, + 3742, + 3743, + 3925, + 3924, + 0, + 3743, + 3741, + 3923, + 3925, + 0, + 3741, + 3738, + 3919, + 3923, + 0, + 3738, + 3735, + 3916, + 3919, + 0, + 3735, + 3731, + 3913, + 3916, + 0, + 3731, + 3728, + 3908, + 3913, + 0, + 3728, + 3724, + 3898, + 3908, + 0, + 3724, + 3713, + 3885, + 3898, + 0, + 3713, + 3708, + 3875, + 3885, + 0, + 3708, + 3703, + 3864, + 3875, + 0, + 3703, + 3696, + 3853, + 3864, + 0, + 3696, + 3663, + 3826, + 3853, + 0, + 3663, + 3655, + 3820, + 3826, + 0, + 3655, + 3647, + 3814, + 3820, + 0, + 3647, + 3642, + 3808, + 3814, + 0, + 3642, + 3639, + 3802, + 3808, + 0, + 3639, + 3637, + 3797, + 3802, + 0, + 3637, + 3627, + 3791, + 3797, + 0, + 3627, + 3618, + 3786, + 3791, + 0, + 3618, + 3604, + 3780, + 3786, + 0, + 3604, + 3594, + 3775, + 3780, + 0, + 3594, + 3587, + 3769, + 3775, + 0, + 3587, + 3580, + 3765, + 3769, + 0, + 3580, + 3575, + 3760, + 3765, + 0, + 3575, + 3565, + 3756, + 3760, + 0, + 3565, + 3555, + 3752, + 3756, + 0, + 3555, + 3540, + 3748, + 3752, + 0, + 3540, + 3530, + 3745, + 3748, + 0, + 3530, + 3520, + 3732, + 3745, + 0, + 3520, + 3512, + 3722, + 3732, + 0, + 3512, + 3506, + 3711, + 3722, + 0, + 3506, + 3488, + 3690, + 3711, + 0, + 3488, + 3493, + 3695, + 3690, + 0, + 3493, + 3496, + 3698, + 3695, + 0, + 3496, + 3514, + 3725, + 3698, + 0, + 3514, + 3522, + 3734, + 3725, + 0, + 3522, + 3529, + 3744, + 3734, + 0, + 3529, + 3541, + 3749, + 3744, + 0, + 3541, + 3557, + 3753, + 3749, + 0, + 3557, + 3573, + 3757, + 3753, + 0, + 3573, + 3578, + 3762, + 3757, + 0, + 3578, + 3583, + 3767, + 3762, + 0, + 3583, + 3591, + 3773, + 3767, + 0, + 3591, + 3599, + 3777, + 3773, + 0, + 3599, + 3610, + 3782, + 3777, + 0, + 3610, + 3624, + 3790, + 3782, + 0, + 3624, + 3636, + 3796, + 3790, + 0, + 3636, + 3640, + 3803, + 3796, + 0, + 3640, + 3643, + 3809, + 3803, + 0, + 3643, + 3649, + 3815, + 3809, + 0, + 3649, + 3656, + 3821, + 3815, + 0, + 3656, + 3686, + 3833, + 3821, + 0, + 3686, + 3691, + 3847, + 3833, + 0, + 3691, + 3693, + 3851, + 3847, + 0, + 3693, + 3700, + 3858, + 3851, + 0, + 3700, + 3704, + 3866, + 3858, + 0, + 3704, + 3707, + 3873, + 3866, + 0, + 3707, + 3712, + 3880, + 3873, + 0, + 3712, + 3716, + 3886, + 3880, + 0, + 3716, + 3719, + 3892, + 3886, + 0, + 3719, + 3720, + 3896, + 3892, + 0, + 3720, + 3723, + 3897, + 3896, + 0, + 3723, + 3721, + 3895, + 3897, + 0, + 3721, + 3718, + 3891, + 3895, + 0, + 3718, + 3714, + 3884, + 3891, + 0, + 3714, + 3710, + 3878, + 3884, + 0, + 3710, + 3706, + 3869, + 3878, + 0, + 3706, + 3702, + 3863, + 3869, + 0, + 3702, + 3697, + 3855, + 3863, + 0, + 3697, + 3694, + 3852, + 3855, + 0, + 3694, + 3688, + 3838, + 3852, + 0, + 3688, + 3687, + 3837, + 3838, + 0, + 3837, + 3843, + 3844, + 3839, + 0, + 3843, + 3865, + 3871, + 3844, + 0, + 3865, + 3877, + 3882, + 3871, + 0, + 3877, + 3888, + 3900, + 3882, + 0, + 3888, + 3905, + 3909, + 3900, + 0, + 3905, + 3910, + 3915, + 3909, + 0, + 3910, + 3914, + 3920, + 3915, + 0, + 3914, + 3918, + 3926, + 3920, + 0, + 3918, + 3921, + 3928, + 3926, + 0, + 3921, + 3924, + 3930, + 3928, + 0, + 3924, + 3925, + 3931, + 3930, + 0, + 3925, + 3923, + 3929, + 3931, + 0, + 3923, + 3919, + 3927, + 3929, + 0, + 3919, + 3916, + 3922, + 3927, + 0, + 3916, + 3913, + 3917, + 3922, + 0, + 3913, + 3908, + 3912, + 3917, + 0, + 3908, + 3898, + 3907, + 3912, + 0, + 3898, + 3885, + 3894, + 3907, + 0, + 3885, + 3875, + 3881, + 3894, + 0, + 3875, + 3864, + 3868, + 3881, + 0, + 3864, + 3853, + 3857, + 3868, + 0, + 3853, + 3826, + 3827, + 3857, + 0, + 3826, + 3820, + 3823, + 3827, + 0, + 3820, + 3814, + 3816, + 3823, + 0, + 3814, + 3808, + 3811, + 3816, + 0, + 3808, + 3802, + 3805, + 3811, + 0, + 3802, + 3797, + 3799, + 3805, + 0, + 3797, + 3791, + 3793, + 3799, + 0, + 3791, + 3786, + 3787, + 3793, + 0, + 3786, + 3780, + 3781, + 3787, + 0, + 3780, + 3775, + 3776, + 3781, + 0, + 3775, + 3769, + 3772, + 3776, + 0, + 3769, + 3765, + 3766, + 3772, + 0, + 3765, + 3760, + 3761, + 3766, + 0, + 3760, + 3756, + 3758, + 3761, + 0, + 3756, + 3752, + 3754, + 3758, + 0, + 3752, + 3748, + 3750, + 3754, + 0, + 3748, + 3745, + 3747, + 3750, + 0, + 3745, + 3732, + 3736, + 3747, + 0, + 3732, + 3722, + 3726, + 3736, + 0, + 3722, + 3711, + 3715, + 3726, + 0, + 3711, + 3690, + 3692, + 3715, + 0, + 3690, + 3695, + 3699, + 3692, + 0, + 3695, + 3698, + 3701, + 3699, + 0, + 3698, + 3725, + 3729, + 3701, + 0, + 3725, + 3734, + 3739, + 3729, + 0, + 3734, + 3744, + 3746, + 3739, + 0, + 3744, + 3749, + 3751, + 3746, + 0, + 3749, + 3753, + 3755, + 3751, + 0, + 3753, + 3757, + 3759, + 3755, + 0, + 3757, + 3762, + 3763, + 3759, + 0, + 3762, + 3767, + 3768, + 3763, + 0, + 3767, + 3773, + 3774, + 3768, + 0, + 3773, + 3777, + 3778, + 3774, + 0, + 3777, + 3782, + 3784, + 3778, + 0, + 3782, + 3790, + 3792, + 3784, + 0, + 3790, + 3796, + 3798, + 3792, + 0, + 3796, + 3803, + 3806, + 3798, + 0, + 3803, + 3809, + 3812, + 3806, + 0, + 3809, + 3815, + 3818, + 3812, + 0, + 3815, + 3821, + 3824, + 3818, + 0, + 3821, + 3833, + 3834, + 3824, + 0, + 3833, + 3847, + 3848, + 3834, + 0, + 3847, + 3851, + 3854, + 3848, + 0, + 3851, + 3858, + 3862, + 3854, + 0, + 3858, + 3866, + 3872, + 3862, + 0, + 3866, + 3873, + 3879, + 3872, + 0, + 3873, + 3880, + 3887, + 3879, + 0, + 3880, + 3886, + 3899, + 3887, + 0, + 3886, + 3892, + 3902, + 3899, + 0, + 3892, + 3896, + 3904, + 3902, + 0, + 3896, + 3897, + 3906, + 3904, + 0, + 3897, + 3895, + 3903, + 3906, + 0, + 3895, + 3891, + 3901, + 3903, + 0, + 3891, + 3884, + 3893, + 3901, + 0, + 3884, + 3878, + 3883, + 3893, + 0, + 3878, + 3869, + 3876, + 3883, + 0, + 3869, + 3863, + 3867, + 3876, + 0, + 3863, + 3855, + 3860, + 3867, + 0, + 3855, + 3852, + 3856, + 3860, + 0, + 3852, + 3838, + 3841, + 3856, + 0, + 3838, + 3837, + 3839, + 3841, + 0, + 3839, + 3844, + 3935, + 3933, + 0, + 3844, + 3871, + 3947, + 3935, + 0, + 3871, + 3882, + 3952, + 3947, + 0, + 3882, + 3900, + 3959, + 3952, + 0, + 3900, + 3909, + 3967, + 3959, + 0, + 3909, + 3915, + 3970, + 3967, + 0, + 3915, + 3920, + 3973, + 3970, + 0, + 3920, + 3926, + 3976, + 3973, + 0, + 3926, + 3928, + 3978, + 3976, + 0, + 3928, + 3930, + 3980, + 3978, + 0, + 3930, + 3931, + 3981, + 3980, + 0, + 3931, + 3929, + 3979, + 3981, + 0, + 3929, + 3927, + 3977, + 3979, + 0, + 3927, + 3922, + 3974, + 3977, + 0, + 3922, + 3917, + 3971, + 3974, + 0, + 3917, + 3912, + 3969, + 3971, + 0, + 3912, + 3907, + 3965, + 3969, + 0, + 3907, + 3894, + 3957, + 3965, + 0, + 3894, + 3881, + 3951, + 3957, + 0, + 3881, + 3868, + 3946, + 3951, + 0, + 3868, + 3857, + 3940, + 3946, + 0, + 3857, + 3827, + 3911, + 3940, + 0, + 3827, + 3823, + 3889, + 3911, + 0, + 3823, + 3816, + 3870, + 3889, + 0, + 3816, + 3811, + 3859, + 3870, + 0, + 3811, + 3805, + 3849, + 3859, + 0, + 3805, + 3799, + 3846, + 3849, + 0, + 3799, + 3793, + 3842, + 3846, + 0, + 3793, + 3787, + 3836, + 3842, + 0, + 3787, + 3781, + 3832, + 3836, + 0, + 3781, + 3776, + 3830, + 3832, + 0, + 3776, + 3772, + 3828, + 3830, + 0, + 3772, + 3766, + 3822, + 3828, + 0, + 3766, + 3761, + 3817, + 3822, + 0, + 3761, + 3758, + 3810, + 3817, + 0, + 3758, + 3754, + 3804, + 3810, + 0, + 3754, + 3750, + 3800, + 3804, + 0, + 3750, + 3747, + 3795, + 3800, + 0, + 3747, + 3736, + 3788, + 3795, + 0, + 3736, + 3726, + 3783, + 3788, + 0, + 3726, + 3715, + 3779, + 3783, + 0, + 3715, + 3692, + 3764, + 3779, + 0, + 3692, + 3699, + 3770, + 3764, + 0, + 3699, + 3701, + 3771, + 3770, + 0, + 3701, + 3729, + 3785, + 3771, + 0, + 3729, + 3739, + 3789, + 3785, + 0, + 3739, + 3746, + 3794, + 3789, + 0, + 3746, + 3751, + 3801, + 3794, + 0, + 3751, + 3755, + 3807, + 3801, + 0, + 3755, + 3759, + 3813, + 3807, + 0, + 3759, + 3763, + 3819, + 3813, + 0, + 3763, + 3768, + 3825, + 3819, + 0, + 3768, + 3774, + 3829, + 3825, + 0, + 3774, + 3778, + 3831, + 3829, + 0, + 3778, + 3784, + 3835, + 3831, + 0, + 3784, + 3792, + 3840, + 3835, + 0, + 3792, + 3798, + 3845, + 3840, + 0, + 3798, + 3806, + 3850, + 3845, + 0, + 3806, + 3812, + 3861, + 3850, + 0, + 3812, + 3818, + 3874, + 3861, + 0, + 3818, + 3824, + 3890, + 3874, + 0, + 3824, + 3834, + 3932, + 3890, + 0, + 3834, + 3848, + 3937, + 3932, + 0, + 3848, + 3854, + 3938, + 3937, + 0, + 3854, + 3862, + 3944, + 3938, + 0, + 3862, + 3872, + 3948, + 3944, + 0, + 3872, + 3879, + 3950, + 3948, + 0, + 3879, + 3887, + 3955, + 3950, + 0, + 3887, + 3899, + 3958, + 3955, + 0, + 3899, + 3902, + 3961, + 3958, + 0, + 3902, + 3904, + 3963, + 3961, + 0, + 3904, + 3906, + 3964, + 3963, + 0, + 3906, + 3903, + 3962, + 3964, + 0, + 3903, + 3901, + 3960, + 3962, + 0, + 3901, + 3893, + 3956, + 3960, + 0, + 3893, + 3883, + 3953, + 3956, + 0, + 3883, + 3876, + 3949, + 3953, + 0, + 3876, + 3867, + 3945, + 3949, + 0, + 3867, + 3860, + 3942, + 3945, + 0, + 3860, + 3856, + 3939, + 3942, + 0, + 3856, + 3841, + 3934, + 3939, + 0, + 3841, + 3839, + 3933, + 3934, + 0, + 3933, + 3935, + 4079, + 4073, + 0, + 3935, + 3947, + 4099, + 4079, + 0, + 3947, + 3952, + 4106, + 4099, + 0, + 3952, + 3959, + 4114, + 4106, + 0, + 3959, + 3967, + 4122, + 4114, + 0, + 3967, + 3970, + 4126, + 4122, + 0, + 3970, + 3973, + 4128, + 4126, + 0, + 3973, + 3976, + 4132, + 4128, + 0, + 3976, + 3978, + 4135, + 4132, + 0, + 3978, + 3980, + 4137, + 4135, + 0, + 3980, + 3981, + 4138, + 4137, + 0, + 3981, + 3979, + 4136, + 4138, + 0, + 3979, + 3977, + 4134, + 4136, + 0, + 3977, + 3974, + 4130, + 4134, + 0, + 3974, + 3971, + 4127, + 4130, + 0, + 3971, + 3969, + 4125, + 4127, + 0, + 3969, + 3965, + 4121, + 4125, + 0, + 3965, + 3957, + 4112, + 4121, + 0, + 3957, + 3951, + 4105, + 4112, + 0, + 3951, + 3946, + 4098, + 4105, + 0, + 3946, + 3940, + 4091, + 4098, + 0, + 3940, + 3911, + 4058, + 4091, + 0, + 3911, + 3889, + 4052, + 4058, + 0, + 3889, + 3870, + 4046, + 4052, + 0, + 3870, + 3859, + 4040, + 4046, + 0, + 3859, + 3849, + 4036, + 4040, + 0, + 3849, + 3846, + 4030, + 4036, + 0, + 3846, + 3842, + 4024, + 4030, + 0, + 3842, + 3836, + 4016, + 4024, + 0, + 3836, + 3832, + 4011, + 4016, + 0, + 3832, + 3830, + 4007, + 4011, + 0, + 3830, + 3828, + 4001, + 4007, + 0, + 3828, + 3822, + 3996, + 4001, + 0, + 3822, + 3817, + 3993, + 3996, + 0, + 3817, + 3810, + 3991, + 3993, + 0, + 3810, + 3804, + 3987, + 3991, + 0, + 3804, + 3800, + 3984, + 3987, + 0, + 3800, + 3795, + 3983, + 3984, + 0, + 3795, + 3788, + 3972, + 3983, + 0, + 3788, + 3783, + 3966, + 3972, + 0, + 3783, + 3779, + 3954, + 3966, + 0, + 3779, + 3764, + 3936, + 3954, + 0, + 3764, + 3770, + 3941, + 3936, + 0, + 3770, + 3771, + 3943, + 3941, + 0, + 3771, + 3785, + 3968, + 3943, + 0, + 3785, + 3789, + 3975, + 3968, + 0, + 3789, + 3794, + 3982, + 3975, + 0, + 3794, + 3801, + 3985, + 3982, + 0, + 3801, + 3807, + 3988, + 3985, + 0, + 3807, + 3813, + 3992, + 3988, + 0, + 3813, + 3819, + 3994, + 3992, + 0, + 3819, + 3825, + 3999, + 3994, + 0, + 3825, + 3829, + 4004, + 3999, + 0, + 3829, + 3831, + 4010, + 4004, + 0, + 3831, + 3835, + 4015, + 4010, + 0, + 3835, + 3840, + 4021, + 4015, + 0, + 3840, + 3845, + 4027, + 4021, + 0, + 3845, + 3850, + 4037, + 4027, + 0, + 3850, + 3861, + 4043, + 4037, + 0, + 3861, + 3874, + 4048, + 4043, + 0, + 3874, + 3890, + 4053, + 4048, + 0, + 3890, + 3932, + 4069, + 4053, + 0, + 3932, + 3937, + 4084, + 4069, + 0, + 3937, + 3938, + 4089, + 4084, + 0, + 3938, + 3944, + 4096, + 4089, + 0, + 3944, + 3948, + 4101, + 4096, + 0, + 3948, + 3950, + 4104, + 4101, + 0, + 3950, + 3955, + 4109, + 4104, + 0, + 3955, + 3958, + 4113, + 4109, + 0, + 3958, + 3961, + 4116, + 4113, + 0, + 3961, + 3963, + 4118, + 4116, + 0, + 3963, + 3964, + 4119, + 4118, + 0, + 3964, + 3962, + 4117, + 4119, + 0, + 3962, + 3960, + 4115, + 4117, + 0, + 3960, + 3956, + 4111, + 4115, + 0, + 3956, + 3953, + 4107, + 4111, + 0, + 3953, + 3949, + 4103, + 4107, + 0, + 3949, + 3945, + 4097, + 4103, + 0, + 3945, + 3942, + 4092, + 4097, + 0, + 3942, + 3939, + 4090, + 4092, + 0, + 3939, + 3934, + 4075, + 4090, + 0, + 3934, + 3933, + 4073, + 4075, + 0, + 4073, + 4079, + 4139, + 4129, + 0, + 4079, + 4099, + 4151, + 4139, + 0, + 4099, + 4106, + 4157, + 4151, + 0, + 4106, + 4114, + 4164, + 4157, + 0, + 4114, + 4122, + 4172, + 4164, + 0, + 4122, + 4126, + 4174, + 4172, + 0, + 4126, + 4128, + 4180, + 4174, + 0, + 4128, + 4132, + 4184, + 4180, + 0, + 4132, + 4135, + 4186, + 4184, + 0, + 4135, + 4137, + 4189, + 4186, + 0, + 4137, + 4138, + 4190, + 4189, + 0, + 4138, + 4136, + 4188, + 4190, + 0, + 4136, + 4134, + 4185, + 4188, + 0, + 4134, + 4130, + 4182, + 4185, + 0, + 4130, + 4127, + 4178, + 4182, + 0, + 4127, + 4125, + 4173, + 4178, + 0, + 4125, + 4121, + 4171, + 4173, + 0, + 4121, + 4112, + 4161, + 4171, + 0, + 4112, + 4105, + 4156, + 4161, + 0, + 4105, + 4098, + 4150, + 4156, + 0, + 4098, + 4091, + 4144, + 4150, + 0, + 4091, + 4058, + 4095, + 4144, + 0, + 4058, + 4052, + 4087, + 4095, + 0, + 4052, + 4046, + 4081, + 4087, + 0, + 4046, + 4040, + 4077, + 4081, + 0, + 4040, + 4036, + 4071, + 4077, + 0, + 4036, + 4030, + 4067, + 4071, + 0, + 4030, + 4024, + 4063, + 4067, + 0, + 4024, + 4016, + 4059, + 4063, + 0, + 4016, + 4011, + 4054, + 4059, + 0, + 4011, + 4007, + 4049, + 4054, + 0, + 4007, + 4001, + 4042, + 4049, + 0, + 4001, + 3996, + 4035, + 4042, + 0, + 3996, + 3993, + 4028, + 4035, + 0, + 3993, + 3991, + 4022, + 4028, + 0, + 3991, + 3987, + 4017, + 4022, + 0, + 3987, + 3984, + 4012, + 4017, + 0, + 3984, + 3983, + 4009, + 4012, + 0, + 3983, + 3972, + 4002, + 4009, + 0, + 3972, + 3966, + 3998, + 4002, + 0, + 3966, + 3954, + 3995, + 3998, + 0, + 3954, + 3936, + 3986, + 3995, + 0, + 3936, + 3941, + 3989, + 3986, + 0, + 3941, + 3943, + 3990, + 3989, + 0, + 3943, + 3968, + 4000, + 3990, + 0, + 3968, + 3975, + 4005, + 4000, + 0, + 3975, + 3982, + 4008, + 4005, + 0, + 3982, + 3985, + 4013, + 4008, + 0, + 3985, + 3988, + 4019, + 4013, + 0, + 3988, + 3992, + 4026, + 4019, + 0, + 3992, + 3994, + 4032, + 4026, + 0, + 3994, + 3999, + 4038, + 4032, + 0, + 3999, + 4004, + 4044, + 4038, + 0, + 4004, + 4010, + 4050, + 4044, + 0, + 4010, + 4015, + 4056, + 4050, + 0, + 4015, + 4021, + 4062, + 4056, + 0, + 4021, + 4027, + 4066, + 4062, + 0, + 4027, + 4037, + 4072, + 4066, + 0, + 4037, + 4043, + 4078, + 4072, + 0, + 4043, + 4048, + 4083, + 4078, + 0, + 4048, + 4053, + 4088, + 4083, + 0, + 4053, + 4069, + 4120, + 4088, + 0, + 4069, + 4084, + 4140, + 4120, + 0, + 4084, + 4089, + 4142, + 4140, + 0, + 4089, + 4096, + 4147, + 4142, + 0, + 4096, + 4101, + 4152, + 4147, + 0, + 4101, + 4104, + 4155, + 4152, + 0, + 4104, + 4109, + 4159, + 4155, + 0, + 4109, + 4113, + 4163, + 4159, + 0, + 4113, + 4116, + 4166, + 4163, + 0, + 4116, + 4118, + 4168, + 4166, + 0, + 4118, + 4119, + 4169, + 4168, + 0, + 4119, + 4117, + 4167, + 4169, + 0, + 4117, + 4115, + 4165, + 4167, + 0, + 4115, + 4111, + 4160, + 4165, + 0, + 4111, + 4107, + 4158, + 4160, + 0, + 4107, + 4103, + 4153, + 4158, + 0, + 4103, + 4097, + 4149, + 4153, + 0, + 4097, + 4092, + 4145, + 4149, + 0, + 4092, + 4090, + 4143, + 4145, + 0, + 4090, + 4075, + 4131, + 4143, + 0, + 4075, + 4073, + 4129, + 4131, + 0, + 4129, + 4139, + 4154, + 4146, + 0, + 4139, + 4151, + 4193, + 4154, + 0, + 4151, + 4157, + 4198, + 4193, + 0, + 4157, + 4164, + 4205, + 4198, + 0, + 4164, + 4172, + 4214, + 4205, + 0, + 4172, + 4174, + 4216, + 4214, + 0, + 4174, + 4180, + 4220, + 4216, + 0, + 4180, + 4184, + 4222, + 4220, + 0, + 4184, + 4186, + 4224, + 4222, + 0, + 4186, + 4189, + 4226, + 4224, + 0, + 4189, + 4190, + 4227, + 4226, + 0, + 4190, + 4188, + 4225, + 4227, + 0, + 4188, + 4185, + 4223, + 4225, + 0, + 4185, + 4182, + 4221, + 4223, + 0, + 4182, + 4178, + 4218, + 4221, + 0, + 4178, + 4173, + 4215, + 4218, + 0, + 4173, + 4171, + 4212, + 4215, + 0, + 4171, + 4161, + 4203, + 4212, + 0, + 4161, + 4156, + 4199, + 4203, + 0, + 4156, + 4150, + 4192, + 4199, + 0, + 4150, + 4144, + 4181, + 4192, + 0, + 4144, + 4095, + 4133, + 4181, + 0, + 4095, + 4087, + 4123, + 4133, + 0, + 4087, + 4081, + 4108, + 4123, + 0, + 4081, + 4077, + 4100, + 4108, + 0, + 4077, + 4071, + 4093, + 4100, + 0, + 4071, + 4067, + 4086, + 4093, + 0, + 4067, + 4063, + 4082, + 4086, + 0, + 4063, + 4059, + 4076, + 4082, + 0, + 4059, + 4054, + 4070, + 4076, + 0, + 4054, + 4049, + 4065, + 4070, + 0, + 4049, + 4042, + 4061, + 4065, + 0, + 4042, + 4035, + 4057, + 4061, + 0, + 4035, + 4028, + 4051, + 4057, + 0, + 4028, + 4022, + 4045, + 4051, + 0, + 4022, + 4017, + 4039, + 4045, + 0, + 4017, + 4012, + 4033, + 4039, + 0, + 4012, + 4009, + 4031, + 4033, + 0, + 4009, + 4002, + 4023, + 4031, + 0, + 4002, + 3998, + 4018, + 4023, + 0, + 3998, + 3995, + 4014, + 4018, + 0, + 3995, + 3986, + 3997, + 4014, + 0, + 3986, + 3989, + 4003, + 3997, + 0, + 3989, + 3990, + 4006, + 4003, + 0, + 3990, + 4000, + 4020, + 4006, + 0, + 4000, + 4005, + 4025, + 4020, + 0, + 4005, + 4008, + 4029, + 4025, + 0, + 4008, + 4013, + 4034, + 4029, + 0, + 4013, + 4019, + 4041, + 4034, + 0, + 4019, + 4026, + 4047, + 4041, + 0, + 4026, + 4032, + 4055, + 4047, + 0, + 4032, + 4038, + 4060, + 4055, + 0, + 4038, + 4044, + 4064, + 4060, + 0, + 4044, + 4050, + 4068, + 4064, + 0, + 4050, + 4056, + 4074, + 4068, + 0, + 4056, + 4062, + 4080, + 4074, + 0, + 4062, + 4066, + 4085, + 4080, + 0, + 4066, + 4072, + 4094, + 4085, + 0, + 4072, + 4078, + 4102, + 4094, + 0, + 4078, + 4083, + 4110, + 4102, + 0, + 4083, + 4088, + 4124, + 4110, + 0, + 4088, + 4120, + 4141, + 4124, + 0, + 4120, + 4140, + 4170, + 4141, + 0, + 4140, + 4142, + 4176, + 4170, + 0, + 4142, + 4147, + 4187, + 4176, + 0, + 4147, + 4152, + 4194, + 4187, + 0, + 4152, + 4155, + 4196, + 4194, + 0, + 4155, + 4159, + 4201, + 4196, + 0, + 4159, + 4163, + 4204, + 4201, + 0, + 4163, + 4166, + 4208, + 4204, + 0, + 4166, + 4168, + 4210, + 4208, + 0, + 4168, + 4169, + 4211, + 4210, + 0, + 4169, + 4167, + 4209, + 4211, + 0, + 4167, + 4165, + 4206, + 4209, + 0, + 4165, + 4160, + 4202, + 4206, + 0, + 4160, + 4158, + 4200, + 4202, + 0, + 4158, + 4153, + 4195, + 4200, + 0, + 4153, + 4149, + 4191, + 4195, + 0, + 4149, + 4145, + 4183, + 4191, + 0, + 4145, + 4143, + 4177, + 4183, + 0, + 4143, + 4131, + 4148, + 4177, + 0, + 4131, + 4129, + 4146, + 4148, + 0, + 4146, + 4154, + 4309, + 4303, + 0, + 4154, + 4193, + 4328, + 4309, + 0, + 4193, + 4198, + 4336, + 4328, + 0, + 4198, + 4205, + 4346, + 4336, + 0, + 4205, + 4214, + 4355, + 4346, + 0, + 4214, + 4216, + 4360, + 4355, + 0, + 4216, + 4220, + 4362, + 4360, + 0, + 4220, + 4222, + 4364, + 4362, + 0, + 4222, + 4224, + 4369, + 4364, + 0, + 4224, + 4226, + 4372, + 4369, + 0, + 4226, + 4227, + 4373, + 4372, + 0, + 4227, + 4225, + 4371, + 4373, + 0, + 4225, + 4223, + 4367, + 4371, + 0, + 4223, + 4221, + 4363, + 4367, + 0, + 4221, + 4218, + 4361, + 4363, + 0, + 4218, + 4215, + 4359, + 4361, + 0, + 4215, + 4212, + 4353, + 4359, + 0, + 4212, + 4203, + 4345, + 4353, + 0, + 4203, + 4199, + 4337, + 4345, + 0, + 4199, + 4192, + 4329, + 4337, + 0, + 4192, + 4181, + 4322, + 4329, + 0, + 4181, + 4133, + 4288, + 4322, + 0, + 4133, + 4123, + 4281, + 4288, + 0, + 4123, + 4108, + 4274, + 4281, + 0, + 4108, + 4100, + 4269, + 4274, + 0, + 4100, + 4093, + 4264, + 4269, + 0, + 4093, + 4086, + 4260, + 4264, + 0, + 4086, + 4082, + 4254, + 4260, + 0, + 4082, + 4076, + 4249, + 4254, + 0, + 4076, + 4070, + 4247, + 4249, + 0, + 4070, + 4065, + 4243, + 4247, + 0, + 4065, + 4061, + 4240, + 4243, + 0, + 4061, + 4057, + 4238, + 4240, + 0, + 4057, + 4051, + 4236, + 4238, + 0, + 4051, + 4045, + 4234, + 4236, + 0, + 4045, + 4039, + 4232, + 4234, + 0, + 4039, + 4033, + 4230, + 4232, + 0, + 4033, + 4031, + 4229, + 4230, + 0, + 4031, + 4023, + 4217, + 4229, + 0, + 4023, + 4018, + 4207, + 4217, + 0, + 4018, + 4014, + 4197, + 4207, + 0, + 4014, + 3997, + 4162, + 4197, + 0, + 3997, + 4003, + 4175, + 4162, + 0, + 4003, + 4006, + 4179, + 4175, + 0, + 4006, + 4020, + 4213, + 4179, + 0, + 4020, + 4025, + 4219, + 4213, + 0, + 4025, + 4029, + 4228, + 4219, + 0, + 4029, + 4034, + 4231, + 4228, + 0, + 4034, + 4041, + 4233, + 4231, + 0, + 4041, + 4047, + 4235, + 4233, + 0, + 4047, + 4055, + 4237, + 4235, + 0, + 4055, + 4060, + 4239, + 4237, + 0, + 4060, + 4064, + 4242, + 4239, + 0, + 4064, + 4068, + 4245, + 4242, + 0, + 4068, + 4074, + 4248, + 4245, + 0, + 4074, + 4080, + 4252, + 4248, + 0, + 4080, + 4085, + 4259, + 4252, + 0, + 4085, + 4094, + 4265, + 4259, + 0, + 4094, + 4102, + 4271, + 4265, + 0, + 4102, + 4110, + 4277, + 4271, + 0, + 4110, + 4124, + 4282, + 4277, + 0, + 4124, + 4141, + 4298, + 4282, + 0, + 4141, + 4170, + 4314, + 4298, + 0, + 4170, + 4176, + 4319, + 4314, + 0, + 4176, + 4187, + 4325, + 4319, + 0, + 4187, + 4194, + 4330, + 4325, + 0, + 4194, + 4196, + 4335, + 4330, + 0, + 4196, + 4201, + 4341, + 4335, + 0, + 4201, + 4204, + 4347, + 4341, + 0, + 4204, + 4208, + 4349, + 4347, + 0, + 4208, + 4210, + 4351, + 4349, + 0, + 4210, + 4211, + 4352, + 4351, + 0, + 4211, + 4209, + 4350, + 4352, + 0, + 4209, + 4206, + 4348, + 4350, + 0, + 4206, + 4202, + 4344, + 4348, + 0, + 4202, + 4200, + 4338, + 4344, + 0, + 4200, + 4195, + 4334, + 4338, + 0, + 4195, + 4191, + 4327, + 4334, + 0, + 4191, + 4183, + 4321, + 4327, + 0, + 4183, + 4177, + 4318, + 4321, + 0, + 4177, + 4148, + 4304, + 4318, + 0, + 4148, + 4146, + 4303, + 4304, + 0, + 4303, + 4309, + 4385, + 4383, + 0, + 4309, + 4328, + 4400, + 4385, + 0, + 4328, + 4336, + 4406, + 4400, + 0, + 4336, + 4346, + 4414, + 4406, + 0, + 4346, + 4355, + 4425, + 4414, + 0, + 4355, + 4360, + 4431, + 4425, + 0, + 4360, + 4362, + 4434, + 4431, + 0, + 4362, + 4364, + 4438, + 4434, + 0, + 4364, + 4369, + 4443, + 4438, + 0, + 4369, + 4372, + 4446, + 4443, + 0, + 4372, + 4373, + 4447, + 4446, + 0, + 4373, + 4371, + 4445, + 4447, + 0, + 4371, + 4367, + 4440, + 4445, + 0, + 4367, + 4363, + 4436, + 4440, + 0, + 4363, + 4361, + 4433, + 4436, + 0, + 4361, + 4359, + 4429, + 4433, + 0, + 4359, + 4353, + 4423, + 4429, + 0, + 4353, + 4345, + 4413, + 4423, + 0, + 4345, + 4337, + 4407, + 4413, + 0, + 4337, + 4329, + 4401, + 4407, + 0, + 4329, + 4322, + 4396, + 4401, + 0, + 4322, + 4288, + 4374, + 4396, + 0, + 4288, + 4281, + 4365, + 4374, + 0, + 4281, + 4274, + 4354, + 4365, + 0, + 4274, + 4269, + 4340, + 4354, + 0, + 4269, + 4264, + 4331, + 4340, + 0, + 4264, + 4260, + 4324, + 4331, + 0, + 4260, + 4254, + 4316, + 4324, + 0, + 4254, + 4249, + 4311, + 4316, + 0, + 4249, + 4247, + 4306, + 4311, + 0, + 4247, + 4243, + 4300, + 4306, + 0, + 4243, + 4240, + 4294, + 4300, + 0, + 4240, + 4238, + 4290, + 4294, + 0, + 4238, + 4236, + 4285, + 4290, + 0, + 4236, + 4234, + 4279, + 4285, + 0, + 4234, + 4232, + 4273, + 4279, + 0, + 4232, + 4230, + 4267, + 4273, + 0, + 4230, + 4229, + 4263, + 4267, + 0, + 4229, + 4217, + 4258, + 4263, + 0, + 4217, + 4207, + 4253, + 4258, + 0, + 4207, + 4197, + 4251, + 4253, + 0, + 4197, + 4162, + 4241, + 4251, + 0, + 4162, + 4175, + 4244, + 4241, + 0, + 4175, + 4179, + 4246, + 4244, + 0, + 4179, + 4213, + 4256, + 4246, + 0, + 4213, + 4219, + 4261, + 4256, + 0, + 4219, + 4228, + 4262, + 4261, + 0, + 4228, + 4231, + 4268, + 4262, + 0, + 4231, + 4233, + 4275, + 4268, + 0, + 4233, + 4235, + 4280, + 4275, + 0, + 4235, + 4237, + 4289, + 4280, + 0, + 4237, + 4239, + 4293, + 4289, + 0, + 4239, + 4242, + 4297, + 4293, + 0, + 4242, + 4245, + 4301, + 4297, + 0, + 4245, + 4248, + 4308, + 4301, + 0, + 4248, + 4252, + 4313, + 4308, + 0, + 4252, + 4259, + 4320, + 4313, + 0, + 4259, + 4265, + 4332, + 4320, + 0, + 4265, + 4271, + 4342, + 4332, + 0, + 4271, + 4277, + 4357, + 4342, + 0, + 4277, + 4282, + 4366, + 4357, + 0, + 4282, + 4298, + 4381, + 4366, + 0, + 4298, + 4314, + 4388, + 4381, + 0, + 4314, + 4319, + 4393, + 4388, + 0, + 4319, + 4325, + 4397, + 4393, + 0, + 4325, + 4330, + 4402, + 4397, + 0, + 4330, + 4335, + 4405, + 4402, + 0, + 4335, + 4341, + 4410, + 4405, + 0, + 4341, + 4347, + 4415, + 4410, + 0, + 4347, + 4349, + 4418, + 4415, + 0, + 4349, + 4351, + 4420, + 4418, + 0, + 4351, + 4352, + 4421, + 4420, + 0, + 4352, + 4350, + 4419, + 4421, + 0, + 4350, + 4348, + 4416, + 4419, + 0, + 4348, + 4344, + 4412, + 4416, + 0, + 4344, + 4338, + 4408, + 4412, + 0, + 4338, + 4334, + 4403, + 4408, + 0, + 4334, + 4327, + 4398, + 4403, + 0, + 4327, + 4321, + 4395, + 4398, + 0, + 4321, + 4318, + 4392, + 4395, + 0, + 4318, + 4304, + 4384, + 4392, + 0, + 4304, + 4303, + 4383, + 4384, + 0, + 4383, + 4385, + 4399, + 4391, + 0, + 4385, + 4400, + 4437, + 4399, + 0, + 4400, + 4406, + 4450, + 4437, + 0, + 4406, + 4414, + 4458, + 4450, + 0, + 4414, + 4425, + 4467, + 4458, + 0, + 4425, + 4431, + 4470, + 4467, + 0, + 4431, + 4434, + 4472, + 4470, + 0, + 4434, + 4438, + 4475, + 4472, + 0, + 4438, + 4443, + 4478, + 4475, + 0, + 4443, + 4446, + 4480, + 4478, + 0, + 4446, + 4447, + 4481, + 4480, + 0, + 4447, + 4445, + 4479, + 4481, + 0, + 4445, + 4440, + 4476, + 4479, + 0, + 4440, + 4436, + 4474, + 4476, + 0, + 4436, + 4433, + 4471, + 4474, + 0, + 4433, + 4429, + 4469, + 4471, + 0, + 4429, + 4423, + 4465, + 4469, + 0, + 4423, + 4413, + 4457, + 4465, + 0, + 4413, + 4407, + 4451, + 4457, + 0, + 4407, + 4401, + 4439, + 4451, + 0, + 4401, + 4396, + 4428, + 4439, + 0, + 4396, + 4374, + 4382, + 4428, + 0, + 4374, + 4365, + 4379, + 4382, + 0, + 4365, + 4354, + 4377, + 4379, + 0, + 4354, + 4340, + 4375, + 4377, + 0, + 4340, + 4331, + 4368, + 4375, + 0, + 4331, + 4324, + 4358, + 4368, + 0, + 4324, + 4316, + 4343, + 4358, + 0, + 4316, + 4311, + 4333, + 4343, + 0, + 4311, + 4306, + 4323, + 4333, + 0, + 4306, + 4300, + 4315, + 4323, + 0, + 4300, + 4294, + 4310, + 4315, + 0, + 4294, + 4290, + 4305, + 4310, + 0, + 4290, + 4285, + 4299, + 4305, + 0, + 4285, + 4279, + 4295, + 4299, + 0, + 4279, + 4273, + 4291, + 4295, + 0, + 4273, + 4267, + 4286, + 4291, + 0, + 4267, + 4263, + 4284, + 4286, + 0, + 4263, + 4258, + 4276, + 4284, + 0, + 4258, + 4253, + 4270, + 4276, + 0, + 4253, + 4251, + 4266, + 4270, + 0, + 4251, + 4241, + 4250, + 4266, + 0, + 4241, + 4244, + 4255, + 4250, + 0, + 4244, + 4246, + 4257, + 4255, + 0, + 4246, + 4256, + 4272, + 4257, + 0, + 4256, + 4261, + 4278, + 4272, + 0, + 4261, + 4262, + 4283, + 4278, + 0, + 4262, + 4268, + 4287, + 4283, + 0, + 4268, + 4275, + 4292, + 4287, + 0, + 4275, + 4280, + 4296, + 4292, + 0, + 4280, + 4289, + 4302, + 4296, + 0, + 4289, + 4293, + 4307, + 4302, + 0, + 4293, + 4297, + 4312, + 4307, + 0, + 4297, + 4301, + 4317, + 4312, + 0, + 4301, + 4308, + 4326, + 4317, + 0, + 4308, + 4313, + 4339, + 4326, + 0, + 4313, + 4320, + 4356, + 4339, + 0, + 4320, + 4332, + 4370, + 4356, + 0, + 4332, + 4342, + 4376, + 4370, + 0, + 4342, + 4357, + 4378, + 4376, + 0, + 4357, + 4366, + 4380, + 4378, + 0, + 4366, + 4381, + 4387, + 4380, + 0, + 4381, + 4388, + 4409, + 4387, + 0, + 4388, + 4393, + 4424, + 4409, + 0, + 4393, + 4397, + 4432, + 4424, + 0, + 4397, + 4402, + 4442, + 4432, + 0, + 4402, + 4405, + 4449, + 4442, + 0, + 4405, + 4410, + 4455, + 4449, + 0, + 4410, + 4415, + 4459, + 4455, + 0, + 4415, + 4418, + 4461, + 4459, + 0, + 4418, + 4420, + 4463, + 4461, + 0, + 4420, + 4421, + 4464, + 4463, + 0, + 4421, + 4419, + 4462, + 4464, + 0, + 4419, + 4416, + 4460, + 4462, + 0, + 4416, + 4412, + 4456, + 4460, + 0, + 4412, + 4408, + 4452, + 4456, + 0, + 4408, + 4403, + 4448, + 4452, + 0, + 4403, + 4398, + 4435, + 4448, + 0, + 4398, + 4395, + 4426, + 4435, + 0, + 4395, + 4392, + 4422, + 4426, + 0, + 4392, + 4384, + 4394, + 4422, + 0, + 4384, + 4383, + 4391, + 4394, + 0, + 4391, + 4399, + 4537, + 4532, + 0, + 4399, + 4437, + 4556, + 4537, + 0, + 4437, + 4450, + 4564, + 4556, + 0, + 4450, + 4458, + 4575, + 4564, + 0, + 4458, + 4467, + 4583, + 4575, + 0, + 4467, + 4470, + 4589, + 4583, + 0, + 4470, + 4472, + 4591, + 4589, + 0, + 4472, + 4475, + 4594, + 4591, + 0, + 4475, + 4478, + 4598, + 4594, + 0, + 4478, + 4480, + 4600, + 4598, + 0, + 4480, + 4481, + 4601, + 4600, + 0, + 4481, + 4479, + 4599, + 4601, + 0, + 4479, + 4476, + 4597, + 4599, + 0, + 4476, + 4474, + 4593, + 4597, + 0, + 4474, + 4471, + 4590, + 4593, + 0, + 4471, + 4469, + 4587, + 4590, + 0, + 4469, + 4465, + 4582, + 4587, + 0, + 4465, + 4457, + 4574, + 4582, + 0, + 4457, + 4451, + 4567, + 4574, + 0, + 4451, + 4439, + 4558, + 4567, + 0, + 4439, + 4428, + 4551, + 4558, + 0, + 4428, + 4382, + 4521, + 4551, + 0, + 4382, + 4379, + 4518, + 4521, + 0, + 4379, + 4377, + 4513, + 4518, + 0, + 4377, + 4375, + 4509, + 4513, + 0, + 4375, + 4368, + 4505, + 4509, + 0, + 4368, + 4358, + 4501, + 4505, + 0, + 4358, + 4343, + 4498, + 4501, + 0, + 4343, + 4333, + 4495, + 4498, + 0, + 4333, + 4323, + 4491, + 4495, + 0, + 4323, + 4315, + 4489, + 4491, + 0, + 4315, + 4310, + 4486, + 4489, + 0, + 4310, + 4305, + 4484, + 4486, + 0, + 4305, + 4299, + 4482, + 4484, + 0, + 4299, + 4295, + 4473, + 4482, + 0, + 4295, + 4291, + 4466, + 4473, + 0, + 4291, + 4286, + 4454, + 4466, + 0, + 4286, + 4284, + 4444, + 4454, + 0, + 4284, + 4276, + 4427, + 4444, + 0, + 4276, + 4270, + 4411, + 4427, + 0, + 4270, + 4266, + 4404, + 4411, + 0, + 4266, + 4250, + 4386, + 4404, + 0, + 4250, + 4255, + 4389, + 4386, + 0, + 4255, + 4257, + 4390, + 4389, + 0, + 4257, + 4272, + 4417, + 4390, + 0, + 4272, + 4278, + 4430, + 4417, + 0, + 4278, + 4283, + 4441, + 4430, + 0, + 4283, + 4287, + 4453, + 4441, + 0, + 4287, + 4292, + 4468, + 4453, + 0, + 4292, + 4296, + 4477, + 4468, + 0, + 4296, + 4302, + 4483, + 4477, + 0, + 4302, + 4307, + 4485, + 4483, + 0, + 4307, + 4312, + 4487, + 4485, + 0, + 4312, + 4317, + 4490, + 4487, + 0, + 4317, + 4326, + 4494, + 4490, + 0, + 4326, + 4339, + 4496, + 4494, + 0, + 4339, + 4356, + 4500, + 4496, + 0, + 4356, + 4370, + 4506, + 4500, + 0, + 4370, + 4376, + 4510, + 4506, + 0, + 4376, + 4378, + 4514, + 4510, + 0, + 4378, + 4380, + 4517, + 4514, + 0, + 4380, + 4387, + 4529, + 4517, + 0, + 4387, + 4409, + 4542, + 4529, + 0, + 4409, + 4424, + 4547, + 4542, + 0, + 4424, + 4432, + 4554, + 4547, + 0, + 4432, + 4442, + 4559, + 4554, + 0, + 4442, + 4449, + 4565, + 4559, + 0, + 4449, + 4455, + 4571, + 4565, + 0, + 4455, + 4459, + 4576, + 4571, + 0, + 4459, + 4461, + 4578, + 4576, + 0, + 4461, + 4463, + 4580, + 4578, + 0, + 4463, + 4464, + 4581, + 4580, + 0, + 4464, + 4462, + 4579, + 4581, + 0, + 4462, + 4460, + 4577, + 4579, + 0, + 4460, + 4456, + 4572, + 4577, + 0, + 4456, + 4452, + 4566, + 4572, + 0, + 4452, + 4448, + 4563, + 4566, + 0, + 4448, + 4435, + 4555, + 4563, + 0, + 4435, + 4426, + 4549, + 4555, + 0, + 4426, + 4422, + 4546, + 4549, + 0, + 4422, + 4394, + 4533, + 4546, + 0, + 4394, + 4391, + 4532, + 4533, + 0, + 4532, + 4537, + 4620, + 4615, + 0, + 4537, + 4556, + 4637, + 4620, + 0, + 4556, + 4564, + 4644, + 4637, + 0, + 4564, + 4575, + 4652, + 4644, + 0, + 4575, + 4583, + 4665, + 4652, + 0, + 4583, + 4589, + 4667, + 4665, + 0, + 4589, + 4591, + 4670, + 4667, + 0, + 4591, + 4594, + 4674, + 4670, + 0, + 4594, + 4598, + 4676, + 4674, + 0, + 4598, + 4600, + 4678, + 4676, + 0, + 4600, + 4601, + 4679, + 4678, + 0, + 4601, + 4599, + 4677, + 4679, + 0, + 4599, + 4597, + 4675, + 4677, + 0, + 4597, + 4593, + 4673, + 4675, + 0, + 4593, + 4590, + 4669, + 4673, + 0, + 4590, + 4587, + 4666, + 4669, + 0, + 4587, + 4582, + 4663, + 4666, + 0, + 4582, + 4574, + 4653, + 4663, + 0, + 4574, + 4567, + 4647, + 4653, + 0, + 4567, + 4558, + 4639, + 4647, + 0, + 4558, + 4551, + 4632, + 4639, + 0, + 4551, + 4521, + 4607, + 4632, + 0, + 4521, + 4518, + 4604, + 4607, + 0, + 4518, + 4513, + 4592, + 4604, + 0, + 4513, + 4509, + 4584, + 4592, + 0, + 4509, + 4505, + 4569, + 4584, + 0, + 4505, + 4501, + 4560, + 4569, + 0, + 4501, + 4498, + 4550, + 4560, + 0, + 4498, + 4495, + 4543, + 4550, + 0, + 4495, + 4491, + 4538, + 4543, + 0, + 4491, + 4489, + 4534, + 4538, + 0, + 4489, + 4486, + 4530, + 4534, + 0, + 4486, + 4484, + 4525, + 4530, + 0, + 4484, + 4482, + 4522, + 4525, + 0, + 4482, + 4473, + 4519, + 4522, + 0, + 4473, + 4466, + 4515, + 4519, + 0, + 4466, + 4454, + 4512, + 4515, + 0, + 4454, + 4444, + 4508, + 4512, + 0, + 4444, + 4427, + 4503, + 4508, + 0, + 4427, + 4411, + 4499, + 4503, + 0, + 4411, + 4404, + 4497, + 4499, + 0, + 4404, + 4386, + 4488, + 4497, + 0, + 4386, + 4389, + 4492, + 4488, + 0, + 4389, + 4390, + 4493, + 4492, + 0, + 4390, + 4417, + 4502, + 4493, + 0, + 4417, + 4430, + 4504, + 4502, + 0, + 4430, + 4441, + 4507, + 4504, + 0, + 4441, + 4453, + 4511, + 4507, + 0, + 4453, + 4468, + 4516, + 4511, + 0, + 4468, + 4477, + 4520, + 4516, + 0, + 4477, + 4483, + 4524, + 4520, + 0, + 4483, + 4485, + 4527, + 4524, + 0, + 4485, + 4487, + 4531, + 4527, + 0, + 4487, + 4490, + 4535, + 4531, + 0, + 4490, + 4494, + 4540, + 4535, + 0, + 4494, + 4496, + 4548, + 4540, + 0, + 4496, + 4500, + 4557, + 4548, + 0, + 4500, + 4506, + 4570, + 4557, + 0, + 4506, + 4510, + 4586, + 4570, + 0, + 4510, + 4514, + 4596, + 4586, + 0, + 4514, + 4517, + 4603, + 4596, + 0, + 4517, + 4529, + 4613, + 4603, + 0, + 4529, + 4542, + 4625, + 4613, + 0, + 4542, + 4547, + 4630, + 4625, + 0, + 4547, + 4554, + 4634, + 4630, + 0, + 4554, + 4559, + 4640, + 4634, + 0, + 4559, + 4565, + 4645, + 4640, + 0, + 4565, + 4571, + 4649, + 4645, + 0, + 4571, + 4576, + 4656, + 4649, + 0, + 4576, + 4578, + 4658, + 4656, + 0, + 4578, + 4580, + 4660, + 4658, + 0, + 4580, + 4581, + 4661, + 4660, + 0, + 4581, + 4579, + 4659, + 4661, + 0, + 4579, + 4577, + 4657, + 4659, + 0, + 4577, + 4572, + 4650, + 4657, + 0, + 4572, + 4566, + 4646, + 4650, + 0, + 4566, + 4563, + 4641, + 4646, + 0, + 4563, + 4555, + 4636, + 4641, + 0, + 4555, + 4549, + 4631, + 4636, + 0, + 4549, + 4546, + 4629, + 4631, + 0, + 4546, + 4533, + 4617, + 4629, + 0, + 4533, + 4532, + 4615, + 4617, + 0, + 4615, + 4620, + 4690, + 4685, + 0, + 4620, + 4637, + 4704, + 4690, + 0, + 4637, + 4644, + 4710, + 4704, + 0, + 4644, + 4652, + 4718, + 4710, + 0, + 4652, + 4665, + 4730, + 4718, + 0, + 4665, + 4667, + 4732, + 4730, + 0, + 4667, + 4670, + 4735, + 4732, + 0, + 4670, + 4674, + 4738, + 4735, + 0, + 4674, + 4676, + 4740, + 4738, + 0, + 4676, + 4678, + 4742, + 4740, + 0, + 4678, + 4679, + 4743, + 4742, + 0, + 4679, + 4677, + 4741, + 4743, + 0, + 4677, + 4675, + 4739, + 4741, + 0, + 4675, + 4673, + 4737, + 4739, + 0, + 4673, + 4669, + 4734, + 4737, + 0, + 4669, + 4666, + 4731, + 4734, + 0, + 4666, + 4663, + 4729, + 4731, + 0, + 4663, + 4653, + 4719, + 4729, + 0, + 4653, + 4647, + 4714, + 4719, + 0, + 4647, + 4639, + 4706, + 4714, + 0, + 4639, + 4632, + 4700, + 4706, + 0, + 4632, + 4607, + 4668, + 4700, + 0, + 4607, + 4604, + 4655, + 4668, + 0, + 4604, + 4592, + 4642, + 4655, + 0, + 4592, + 4584, + 4633, + 4642, + 0, + 4584, + 4569, + 4627, + 4633, + 0, + 4569, + 4560, + 4623, + 4627, + 0, + 4560, + 4550, + 4619, + 4623, + 0, + 4550, + 4543, + 4616, + 4619, + 0, + 4543, + 4538, + 4612, + 4616, + 0, + 4538, + 4534, + 4610, + 4612, + 0, + 4534, + 4530, + 4608, + 4610, + 0, + 4530, + 4525, + 4605, + 4608, + 0, + 4525, + 4522, + 4595, + 4605, + 0, + 4522, + 4519, + 4585, + 4595, + 0, + 4519, + 4515, + 4568, + 4585, + 0, + 4515, + 4512, + 4562, + 4568, + 0, + 4512, + 4508, + 4553, + 4562, + 0, + 4508, + 4503, + 4544, + 4553, + 0, + 4503, + 4499, + 4539, + 4544, + 0, + 4499, + 4497, + 4536, + 4539, + 0, + 4497, + 4488, + 4523, + 4536, + 0, + 4488, + 4492, + 4526, + 4523, + 0, + 4492, + 4493, + 4528, + 4526, + 0, + 4493, + 4502, + 4541, + 4528, + 0, + 4502, + 4504, + 4545, + 4541, + 0, + 4504, + 4507, + 4552, + 4545, + 0, + 4507, + 4511, + 4561, + 4552, + 0, + 4511, + 4516, + 4573, + 4561, + 0, + 4516, + 4520, + 4588, + 4573, + 0, + 4520, + 4524, + 4602, + 4588, + 0, + 4524, + 4527, + 4606, + 4602, + 0, + 4527, + 4531, + 4609, + 4606, + 0, + 4531, + 4535, + 4611, + 4609, + 0, + 4535, + 4540, + 4614, + 4611, + 0, + 4540, + 4548, + 4618, + 4614, + 0, + 4548, + 4557, + 4622, + 4618, + 0, + 4557, + 4570, + 4628, + 4622, + 0, + 4570, + 4586, + 4635, + 4628, + 0, + 4586, + 4596, + 4643, + 4635, + 0, + 4596, + 4603, + 4654, + 4643, + 0, + 4603, + 4613, + 4684, + 4654, + 0, + 4613, + 4625, + 4693, + 4684, + 0, + 4625, + 4630, + 4697, + 4693, + 0, + 4630, + 4634, + 4701, + 4697, + 0, + 4634, + 4640, + 4707, + 4701, + 0, + 4640, + 4645, + 4712, + 4707, + 0, + 4645, + 4649, + 4715, + 4712, + 0, + 4649, + 4656, + 4720, + 4715, + 0, + 4656, + 4658, + 4723, + 4720, + 0, + 4658, + 4660, + 4725, + 4723, + 0, + 4660, + 4661, + 4727, + 4725, + 0, + 4661, + 4659, + 4724, + 4727, + 0, + 4659, + 4657, + 4721, + 4724, + 0, + 4657, + 4650, + 4716, + 4721, + 0, + 4650, + 4646, + 4713, + 4716, + 0, + 4646, + 4641, + 4708, + 4713, + 0, + 4641, + 4636, + 4703, + 4708, + 0, + 4636, + 4631, + 4698, + 4703, + 0, + 4631, + 4629, + 4696, + 4698, + 0, + 4629, + 4617, + 4687, + 4696, + 0, + 4617, + 4615, + 4685, + 4687, + 0, + 4685, + 4690, + 4777, + 4772, + 0, + 4690, + 4704, + 4791, + 4777, + 0, + 4704, + 4710, + 4796, + 4791, + 0, + 4710, + 4718, + 4804, + 4796, + 0, + 4718, + 4730, + 4814, + 4804, + 0, + 4730, + 4732, + 4818, + 4814, + 0, + 4732, + 4735, + 4821, + 4818, + 0, + 4735, + 4738, + 4824, + 4821, + 0, + 4738, + 4740, + 4827, + 4824, + 0, + 4740, + 4742, + 4830, + 4827, + 0, + 4742, + 4743, + 4831, + 4830, + 0, + 4743, + 4741, + 4829, + 4831, + 0, + 4741, + 4739, + 4826, + 4829, + 0, + 4739, + 4737, + 4823, + 4826, + 0, + 4737, + 4734, + 4819, + 4823, + 0, + 4734, + 4731, + 4817, + 4819, + 0, + 4731, + 4729, + 4813, + 4817, + 0, + 4729, + 4719, + 4805, + 4813, + 0, + 4719, + 4714, + 4799, + 4805, + 0, + 4714, + 4706, + 4792, + 4799, + 0, + 4706, + 4700, + 4787, + 4792, + 0, + 4700, + 4668, + 4765, + 4787, + 0, + 4668, + 4655, + 4762, + 4765, + 0, + 4655, + 4642, + 4757, + 4762, + 0, + 4642, + 4633, + 4753, + 4757, + 0, + 4633, + 4627, + 4749, + 4753, + 0, + 4627, + 4623, + 4746, + 4749, + 0, + 4623, + 4619, + 4736, + 4746, + 0, + 4619, + 4616, + 4726, + 4736, + 0, + 4616, + 4612, + 4711, + 4726, + 0, + 4612, + 4610, + 4702, + 4711, + 0, + 4610, + 4608, + 4695, + 4702, + 0, + 4608, + 4605, + 4692, + 4695, + 0, + 4605, + 4595, + 4689, + 4692, + 0, + 4595, + 4585, + 4686, + 4689, + 0, + 4585, + 4568, + 4682, + 4686, + 0, + 4568, + 4562, + 4681, + 4682, + 0, + 4562, + 4553, + 4672, + 4681, + 0, + 4553, + 4544, + 4662, + 4672, + 0, + 4544, + 4539, + 4648, + 4662, + 0, + 4539, + 4536, + 4638, + 4648, + 0, + 4536, + 4523, + 4621, + 4638, + 0, + 4523, + 4526, + 4624, + 4621, + 0, + 4526, + 4528, + 4626, + 4624, + 0, + 4528, + 4541, + 4651, + 4626, + 0, + 4541, + 4545, + 4664, + 4651, + 0, + 4545, + 4552, + 4671, + 4664, + 0, + 4552, + 4561, + 4680, + 4671, + 0, + 4561, + 4573, + 4683, + 4680, + 0, + 4573, + 4588, + 4688, + 4683, + 0, + 4588, + 4602, + 4691, + 4688, + 0, + 4602, + 4606, + 4694, + 4691, + 0, + 4606, + 4609, + 4699, + 4694, + 0, + 4609, + 4611, + 4705, + 4699, + 0, + 4611, + 4614, + 4717, + 4705, + 0, + 4614, + 4618, + 4733, + 4717, + 0, + 4618, + 4622, + 4745, + 4733, + 0, + 4622, + 4628, + 4748, + 4745, + 0, + 4628, + 4635, + 4754, + 4748, + 0, + 4635, + 4643, + 4758, + 4754, + 0, + 4643, + 4654, + 4761, + 4758, + 0, + 4654, + 4684, + 4770, + 4761, + 0, + 4684, + 4693, + 4781, + 4770, + 0, + 4693, + 4697, + 4784, + 4781, + 0, + 4697, + 4701, + 4788, + 4784, + 0, + 4701, + 4707, + 4794, + 4788, + 0, + 4707, + 4712, + 4797, + 4794, + 0, + 4712, + 4715, + 4801, + 4797, + 0, + 4715, + 4720, + 4806, + 4801, + 0, + 4720, + 4723, + 4809, + 4806, + 0, + 4723, + 4725, + 4811, + 4809, + 0, + 4725, + 4727, + 4812, + 4811, + 0, + 4727, + 4724, + 4810, + 4812, + 0, + 4724, + 4721, + 4807, + 4810, + 0, + 4721, + 4716, + 4803, + 4807, + 0, + 4716, + 4713, + 4798, + 4803, + 0, + 4713, + 4708, + 4795, + 4798, + 0, + 4708, + 4703, + 4789, + 4795, + 0, + 4703, + 4698, + 4785, + 4789, + 0, + 4698, + 4696, + 4783, + 4785, + 0, + 4696, + 4687, + 4774, + 4783, + 0, + 4687, + 4685, + 4772, + 4774, + 0, + 4772, + 4777, + 4852, + 4847, + 0, + 4777, + 4791, + 4870, + 4852, + 0, + 4791, + 4796, + 4876, + 4870, + 0, + 4796, + 4804, + 4885, + 4876, + 0, + 4804, + 4814, + 4897, + 4885, + 0, + 4814, + 4818, + 4899, + 4897, + 0, + 4818, + 4821, + 4904, + 4899, + 0, + 4821, + 4824, + 4907, + 4904, + 0, + 4824, + 4827, + 4909, + 4907, + 0, + 4827, + 4830, + 4911, + 4909, + 0, + 4830, + 4831, + 4912, + 4911, + 0, + 4831, + 4829, + 4910, + 4912, + 0, + 4829, + 4826, + 4908, + 4910, + 0, + 4826, + 4823, + 4906, + 4908, + 0, + 4823, + 4819, + 4903, + 4906, + 0, + 4819, + 4817, + 4898, + 4903, + 0, + 4817, + 4813, + 4896, + 4898, + 0, + 4813, + 4805, + 4886, + 4896, + 0, + 4805, + 4799, + 4881, + 4886, + 0, + 4799, + 4792, + 4871, + 4881, + 0, + 4792, + 4787, + 4864, + 4871, + 0, + 4787, + 4765, + 4839, + 4864, + 0, + 4765, + 4762, + 4836, + 4839, + 0, + 4762, + 4757, + 4832, + 4836, + 0, + 4757, + 4753, + 4825, + 4832, + 0, + 4753, + 4749, + 4816, + 4825, + 0, + 4749, + 4746, + 4802, + 4816, + 0, + 4746, + 4736, + 4793, + 4802, + 0, + 4736, + 4726, + 4786, + 4793, + 0, + 4726, + 4711, + 4780, + 4786, + 0, + 4711, + 4702, + 4778, + 4780, + 0, + 4702, + 4695, + 4775, + 4778, + 0, + 4695, + 4692, + 4771, + 4775, + 0, + 4692, + 4689, + 4768, + 4771, + 0, + 4689, + 4686, + 4766, + 4768, + 0, + 4686, + 4682, + 4763, + 4766, + 0, + 4682, + 4681, + 4760, + 4763, + 0, + 4681, + 4672, + 4756, + 4760, + 0, + 4672, + 4662, + 4751, + 4756, + 0, + 4662, + 4648, + 4747, + 4751, + 0, + 4648, + 4638, + 4744, + 4747, + 0, + 4638, + 4621, + 4709, + 4744, + 0, + 4621, + 4624, + 4722, + 4709, + 0, + 4624, + 4626, + 4728, + 4722, + 0, + 4626, + 4651, + 4750, + 4728, + 0, + 4651, + 4664, + 4752, + 4750, + 0, + 4664, + 4671, + 4755, + 4752, + 0, + 4671, + 4680, + 4759, + 4755, + 0, + 4680, + 4683, + 4764, + 4759, + 0, + 4683, + 4688, + 4767, + 4764, + 0, + 4688, + 4691, + 4769, + 4767, + 0, + 4691, + 4694, + 4773, + 4769, + 0, + 4694, + 4699, + 4776, + 4773, + 0, + 4699, + 4705, + 4779, + 4776, + 0, + 4705, + 4717, + 4782, + 4779, + 0, + 4717, + 4733, + 4790, + 4782, + 0, + 4733, + 4745, + 4800, + 4790, + 0, + 4745, + 4748, + 4815, + 4800, + 0, + 4748, + 4754, + 4828, + 4815, + 0, + 4754, + 4758, + 4833, + 4828, + 0, + 4758, + 4761, + 4835, + 4833, + 0, + 4761, + 4770, + 4844, + 4835, + 0, + 4770, + 4781, + 4859, + 4844, + 0, + 4781, + 4784, + 4862, + 4859, + 0, + 4784, + 4788, + 4866, + 4862, + 0, + 4788, + 4794, + 4872, + 4866, + 0, + 4794, + 4797, + 4877, + 4872, + 0, + 4797, + 4801, + 4883, + 4877, + 0, + 4801, + 4806, + 4887, + 4883, + 0, + 4806, + 4809, + 4890, + 4887, + 0, + 4809, + 4811, + 4893, + 4890, + 0, + 4811, + 4812, + 4894, + 4893, + 0, + 4812, + 4810, + 4892, + 4894, + 0, + 4810, + 4807, + 4888, + 4892, + 0, + 4807, + 4803, + 4884, + 4888, + 0, + 4803, + 4798, + 4878, + 4884, + 0, + 4798, + 4795, + 4874, + 4878, + 0, + 4795, + 4789, + 4867, + 4874, + 0, + 4789, + 4785, + 4863, + 4867, + 0, + 4785, + 4783, + 4860, + 4863, + 0, + 4783, + 4774, + 4848, + 4860, + 0, + 4774, + 4772, + 4847, + 4848, + 0, + 4847, + 4852, + 4953, + 4949, + 0, + 4852, + 4870, + 4973, + 4953, + 0, + 4870, + 4876, + 4980, + 4973, + 0, + 4876, + 4885, + 4989, + 4980, + 0, + 4885, + 4897, + 5000, + 4989, + 0, + 4897, + 4899, + 5002, + 5000, + 0, + 4899, + 4904, + 5005, + 5002, + 0, + 4904, + 4907, + 5008, + 5005, + 0, + 4907, + 4909, + 5009, + 5008, + 0, + 4909, + 4911, + 5011, + 5009, + 0, + 4911, + 4912, + 5013, + 5011, + 0, + 4912, + 4910, + 5012, + 5013, + 0, + 4910, + 4908, + 5010, + 5012, + 0, + 4908, + 4906, + 5007, + 5010, + 0, + 4906, + 4903, + 5004, + 5007, + 0, + 4903, + 4898, + 5001, + 5004, + 0, + 4898, + 4896, + 4999, + 5001, + 0, + 4896, + 4886, + 4990, + 4999, + 0, + 4886, + 4881, + 4985, + 4990, + 0, + 4881, + 4871, + 4977, + 4985, + 0, + 4871, + 4864, + 4969, + 4977, + 0, + 4864, + 4839, + 4939, + 4969, + 0, + 4839, + 4836, + 4935, + 4939, + 0, + 4836, + 4832, + 4930, + 4935, + 0, + 4832, + 4825, + 4927, + 4930, + 0, + 4825, + 4816, + 4924, + 4927, + 0, + 4816, + 4802, + 4920, + 4924, + 0, + 4802, + 4793, + 4916, + 4920, + 0, + 4793, + 4786, + 4905, + 4916, + 0, + 4786, + 4780, + 4895, + 4905, + 0, + 4780, + 4778, + 4879, + 4895, + 0, + 4778, + 4775, + 4869, + 4879, + 0, + 4775, + 4771, + 4861, + 4869, + 0, + 4771, + 4768, + 4856, + 4861, + 0, + 4768, + 4766, + 4853, + 4856, + 0, + 4766, + 4763, + 4849, + 4853, + 0, + 4763, + 4760, + 4846, + 4849, + 0, + 4760, + 4756, + 4843, + 4846, + 0, + 4756, + 4751, + 4840, + 4843, + 0, + 4751, + 4747, + 4837, + 4840, + 0, + 4747, + 4744, + 4834, + 4837, + 0, + 4744, + 4709, + 4808, + 4834, + 0, + 4709, + 4722, + 4820, + 4808, + 0, + 4722, + 4728, + 4822, + 4820, + 0, + 4728, + 4750, + 4838, + 4822, + 0, + 4750, + 4752, + 4841, + 4838, + 0, + 4752, + 4755, + 4842, + 4841, + 0, + 4755, + 4759, + 4845, + 4842, + 0, + 4759, + 4764, + 4850, + 4845, + 0, + 4764, + 4767, + 4854, + 4850, + 0, + 4767, + 4769, + 4858, + 4854, + 0, + 4769, + 4773, + 4865, + 4858, + 0, + 4773, + 4776, + 4873, + 4865, + 0, + 4776, + 4779, + 4882, + 4873, + 0, + 4779, + 4782, + 4900, + 4882, + 0, + 4782, + 4790, + 4915, + 4900, + 0, + 4790, + 4800, + 4919, + 4915, + 0, + 4800, + 4815, + 4923, + 4919, + 0, + 4815, + 4828, + 4928, + 4923, + 0, + 4828, + 4833, + 4931, + 4928, + 0, + 4833, + 4835, + 4934, + 4931, + 0, + 4835, + 4844, + 4944, + 4934, + 0, + 4844, + 4859, + 4960, + 4944, + 0, + 4859, + 4862, + 4965, + 4960, + 0, + 4862, + 4866, + 4970, + 4965, + 0, + 4866, + 4872, + 4978, + 4970, + 0, + 4872, + 4877, + 4983, + 4978, + 0, + 4877, + 4883, + 4987, + 4983, + 0, + 4883, + 4887, + 4992, + 4987, + 0, + 4887, + 4890, + 4994, + 4992, + 0, + 4890, + 4893, + 4996, + 4994, + 0, + 4893, + 4894, + 4998, + 4996, + 0, + 4894, + 4892, + 4995, + 4998, + 0, + 4892, + 4888, + 4991, + 4995, + 0, + 4888, + 4884, + 4988, + 4991, + 0, + 4884, + 4878, + 4984, + 4988, + 0, + 4878, + 4874, + 4979, + 4984, + 0, + 4874, + 4867, + 4971, + 4979, + 0, + 4867, + 4863, + 4967, + 4971, + 0, + 4863, + 4860, + 4962, + 4967, + 0, + 4860, + 4848, + 4950, + 4962, + 0, + 4848, + 4847, + 4949, + 4950, + 0, + 4949, + 4953, + 5020, + 5017, + 0, + 4953, + 4973, + 5035, + 5020, + 0, + 4973, + 4980, + 5040, + 5035, + 0, + 4980, + 4989, + 5048, + 5040, + 0, + 4989, + 5000, + 5057, + 5048, + 0, + 5000, + 5002, + 5061, + 5057, + 0, + 5002, + 5005, + 5062, + 5061, + 0, + 5005, + 5008, + 5064, + 5062, + 0, + 5008, + 5009, + 5066, + 5064, + 0, + 5009, + 5011, + 5070, + 5066, + 0, + 5011, + 5013, + 5072, + 5070, + 0, + 5013, + 5012, + 5071, + 5072, + 0, + 5012, + 5010, + 5067, + 5071, + 0, + 5010, + 5007, + 5065, + 5067, + 0, + 5007, + 5004, + 5063, + 5065, + 0, + 5004, + 5001, + 5060, + 5063, + 0, + 5001, + 4999, + 5056, + 5060, + 0, + 4999, + 4990, + 5049, + 5056, + 0, + 4990, + 4985, + 5044, + 5049, + 0, + 4985, + 4977, + 5036, + 5044, + 0, + 4977, + 4969, + 5031, + 5036, + 0, + 4969, + 4939, + 4986, + 5031, + 0, + 4939, + 4935, + 4976, + 4986, + 0, + 4935, + 4930, + 4966, + 4976, + 0, + 4930, + 4927, + 4958, + 4966, + 0, + 4927, + 4924, + 4956, + 4958, + 0, + 4924, + 4920, + 4952, + 4956, + 0, + 4920, + 4916, + 4948, + 4952, + 0, + 4916, + 4905, + 4943, + 4948, + 0, + 4905, + 4895, + 4940, + 4943, + 0, + 4895, + 4879, + 4937, + 4940, + 0, + 4879, + 4869, + 4933, + 4937, + 0, + 4869, + 4861, + 4929, + 4933, + 0, + 4861, + 4856, + 4925, + 4929, + 0, + 4856, + 4853, + 4921, + 4925, + 0, + 4853, + 4849, + 4917, + 4921, + 0, + 4849, + 4846, + 4914, + 4917, + 0, + 4846, + 4843, + 4902, + 4914, + 0, + 4843, + 4840, + 4889, + 4902, + 0, + 4840, + 4837, + 4875, + 4889, + 0, + 4837, + 4834, + 4868, + 4875, + 0, + 4834, + 4808, + 4851, + 4868, + 0, + 4808, + 4820, + 4855, + 4851, + 0, + 4820, + 4822, + 4857, + 4855, + 0, + 4822, + 4838, + 4880, + 4857, + 0, + 4838, + 4841, + 4891, + 4880, + 0, + 4841, + 4842, + 4901, + 4891, + 0, + 4842, + 4845, + 4913, + 4901, + 0, + 4845, + 4850, + 4918, + 4913, + 0, + 4850, + 4854, + 4922, + 4918, + 0, + 4854, + 4858, + 4926, + 4922, + 0, + 4858, + 4865, + 4932, + 4926, + 0, + 4865, + 4873, + 4936, + 4932, + 0, + 4873, + 4882, + 4938, + 4936, + 0, + 4882, + 4900, + 4941, + 4938, + 0, + 4900, + 4915, + 4945, + 4941, + 0, + 4915, + 4919, + 4951, + 4945, + 0, + 4919, + 4923, + 4955, + 4951, + 0, + 4923, + 4928, + 4961, + 4955, + 0, + 4928, + 4931, + 4968, + 4961, + 0, + 4931, + 4934, + 4975, + 4968, + 0, + 4934, + 4944, + 5014, + 4975, + 0, + 4944, + 4960, + 5025, + 5014, + 0, + 4960, + 4965, + 5028, + 5025, + 0, + 4965, + 4970, + 5032, + 5028, + 0, + 4970, + 4978, + 5038, + 5032, + 0, + 4978, + 4983, + 5041, + 5038, + 0, + 4983, + 4987, + 5046, + 5041, + 0, + 4987, + 4992, + 5051, + 5046, + 0, + 4992, + 4994, + 5052, + 5051, + 0, + 4994, + 4996, + 5054, + 5052, + 0, + 4996, + 4998, + 5055, + 5054, + 0, + 4998, + 4995, + 5053, + 5055, + 0, + 4995, + 4991, + 5050, + 5053, + 0, + 4991, + 4988, + 5045, + 5050, + 0, + 4988, + 4984, + 5042, + 5045, + 0, + 4984, + 4979, + 5039, + 5042, + 0, + 4979, + 4971, + 5033, + 5039, + 0, + 4971, + 4967, + 5029, + 5033, + 0, + 4967, + 4962, + 5027, + 5029, + 0, + 4962, + 4950, + 5018, + 5027, + 0, + 4950, + 4949, + 5017, + 5018, + 0, + 5017, + 5020, + 5085, + 5081, + 0, + 5020, + 5035, + 5100, + 5085, + 0, + 5035, + 5040, + 5109, + 5100, + 0, + 5040, + 5048, + 5117, + 5109, + 0, + 5048, + 5057, + 5127, + 5117, + 0, + 5057, + 5061, + 5131, + 5127, + 0, + 5061, + 5062, + 5135, + 5131, + 0, + 5062, + 5064, + 5137, + 5135, + 0, + 5064, + 5066, + 5141, + 5137, + 0, + 5066, + 5070, + 5143, + 5141, + 0, + 5070, + 5072, + 5146, + 5143, + 0, + 5072, + 5071, + 5144, + 5146, + 0, + 5071, + 5067, + 5142, + 5144, + 0, + 5067, + 5065, + 5138, + 5142, + 0, + 5065, + 5063, + 5136, + 5138, + 0, + 5063, + 5060, + 5132, + 5136, + 0, + 5060, + 5056, + 5128, + 5132, + 0, + 5056, + 5049, + 5119, + 5128, + 0, + 5049, + 5044, + 5112, + 5119, + 0, + 5044, + 5036, + 5102, + 5112, + 0, + 5036, + 5031, + 5095, + 5102, + 0, + 5031, + 4986, + 5079, + 5095, + 0, + 4986, + 4976, + 5078, + 5079, + 0, + 4976, + 4966, + 5075, + 5078, + 0, + 4966, + 4958, + 5073, + 5075, + 0, + 4958, + 4956, + 5069, + 5073, + 0, + 4956, + 4952, + 5059, + 5069, + 0, + 4952, + 4948, + 5047, + 5059, + 0, + 4948, + 4943, + 5037, + 5047, + 0, + 4943, + 4940, + 5030, + 5037, + 0, + 4940, + 4937, + 5024, + 5030, + 0, + 4937, + 4933, + 5022, + 5024, + 0, + 4933, + 4929, + 5019, + 5022, + 0, + 4929, + 4925, + 5015, + 5019, + 0, + 4925, + 4921, + 5003, + 5015, + 0, + 4921, + 4917, + 4993, + 5003, + 0, + 4917, + 4914, + 4982, + 4993, + 0, + 4914, + 4902, + 4974, + 4982, + 0, + 4902, + 4889, + 4963, + 4974, + 0, + 4889, + 4875, + 4957, + 4963, + 0, + 4875, + 4868, + 4954, + 4957, + 0, + 4868, + 4851, + 4942, + 4954, + 0, + 4851, + 4855, + 4946, + 4942, + 0, + 4855, + 4857, + 4947, + 4946, + 0, + 4857, + 4880, + 4959, + 4947, + 0, + 4880, + 4891, + 4964, + 4959, + 0, + 4891, + 4901, + 4972, + 4964, + 0, + 4901, + 4913, + 4981, + 4972, + 0, + 4913, + 4918, + 4997, + 4981, + 0, + 4918, + 4922, + 5006, + 4997, + 0, + 4922, + 4926, + 5016, + 5006, + 0, + 4926, + 4932, + 5021, + 5016, + 0, + 4932, + 4936, + 5023, + 5021, + 0, + 4936, + 4938, + 5026, + 5023, + 0, + 4938, + 4941, + 5034, + 5026, + 0, + 4941, + 4945, + 5043, + 5034, + 0, + 4945, + 4951, + 5058, + 5043, + 0, + 4951, + 4955, + 5068, + 5058, + 0, + 4955, + 4961, + 5074, + 5068, + 0, + 4961, + 4968, + 5076, + 5074, + 0, + 4968, + 4975, + 5077, + 5076, + 0, + 4975, + 5014, + 5080, + 5077, + 0, + 5014, + 5025, + 5090, + 5080, + 0, + 5025, + 5028, + 5093, + 5090, + 0, + 5028, + 5032, + 5098, + 5093, + 0, + 5032, + 5038, + 5105, + 5098, + 0, + 5038, + 5041, + 5111, + 5105, + 0, + 5041, + 5046, + 5115, + 5111, + 0, + 5046, + 5051, + 5121, + 5115, + 0, + 5051, + 5052, + 5123, + 5121, + 0, + 5052, + 5054, + 5125, + 5123, + 0, + 5054, + 5055, + 5126, + 5125, + 0, + 5055, + 5053, + 5124, + 5126, + 0, + 5053, + 5050, + 5120, + 5124, + 0, + 5050, + 5045, + 5113, + 5120, + 0, + 5045, + 5042, + 5110, + 5113, + 0, + 5042, + 5039, + 5104, + 5110, + 0, + 5039, + 5033, + 5099, + 5104, + 0, + 5033, + 5029, + 5094, + 5099, + 0, + 5029, + 5027, + 5091, + 5094, + 0, + 5027, + 5018, + 5083, + 5091, + 0, + 5018, + 5017, + 5081, + 5083, + 0, + 5081, + 5085, + 5224, + 5217, + 0, + 5085, + 5100, + 5243, + 5224, + 0, + 5100, + 5109, + 5253, + 5243, + 0, + 5109, + 5117, + 5264, + 5253, + 0, + 5117, + 5127, + 5278, + 5264, + 0, + 5127, + 5131, + 5285, + 5278, + 0, + 5131, + 5135, + 5294, + 5285, + 0, + 5135, + 5137, + 5296, + 5294, + 0, + 5137, + 5141, + 5301, + 5296, + 0, + 5141, + 5143, + 5303, + 5301, + 0, + 5143, + 5146, + 5305, + 5303, + 0, + 5146, + 5144, + 5304, + 5305, + 0, + 5144, + 5142, + 5302, + 5304, + 0, + 5142, + 5138, + 5297, + 5302, + 0, + 5138, + 5136, + 5295, + 5297, + 0, + 5136, + 5132, + 5288, + 5295, + 0, + 5132, + 5128, + 5279, + 5288, + 0, + 5128, + 5119, + 5269, + 5279, + 0, + 5119, + 5112, + 5260, + 5269, + 0, + 5112, + 5102, + 5246, + 5260, + 0, + 5102, + 5095, + 5238, + 5246, + 0, + 5095, + 5079, + 5208, + 5238, + 0, + 5079, + 5078, + 5203, + 5208, + 0, + 5078, + 5075, + 5196, + 5203, + 0, + 5075, + 5073, + 5191, + 5196, + 0, + 5073, + 5069, + 5188, + 5191, + 0, + 5069, + 5059, + 5182, + 5188, + 0, + 5059, + 5047, + 5177, + 5182, + 0, + 5047, + 5037, + 5173, + 5177, + 0, + 5037, + 5030, + 5170, + 5173, + 0, + 5030, + 5024, + 5165, + 5170, + 0, + 5024, + 5022, + 5161, + 5165, + 0, + 5022, + 5019, + 5157, + 5161, + 0, + 5019, + 5015, + 5154, + 5157, + 0, + 5015, + 5003, + 5150, + 5154, + 0, + 5003, + 4993, + 5145, + 5150, + 0, + 4993, + 4982, + 5134, + 5145, + 0, + 4982, + 4974, + 5122, + 5134, + 0, + 4974, + 4963, + 5106, + 5122, + 0, + 4963, + 4957, + 5097, + 5106, + 0, + 4957, + 4954, + 5092, + 5097, + 0, + 4954, + 4942, + 5082, + 5092, + 0, + 4942, + 4946, + 5086, + 5082, + 0, + 4946, + 4947, + 5087, + 5086, + 0, + 4947, + 4959, + 5101, + 5087, + 0, + 4959, + 4964, + 5108, + 5101, + 0, + 4964, + 4972, + 5118, + 5108, + 0, + 4972, + 4981, + 5133, + 5118, + 0, + 4981, + 4997, + 5147, + 5133, + 0, + 4997, + 5006, + 5151, + 5147, + 0, + 5006, + 5016, + 5155, + 5151, + 0, + 5016, + 5021, + 5159, + 5155, + 0, + 5021, + 5023, + 5163, + 5159, + 0, + 5023, + 5026, + 5167, + 5163, + 0, + 5026, + 5034, + 5171, + 5167, + 0, + 5034, + 5043, + 5175, + 5171, + 0, + 5043, + 5058, + 5181, + 5175, + 0, + 5058, + 5068, + 5187, + 5181, + 0, + 5068, + 5074, + 5192, + 5187, + 0, + 5074, + 5076, + 5197, + 5192, + 0, + 5076, + 5077, + 5202, + 5197, + 0, + 5077, + 5080, + 5216, + 5202, + 0, + 5080, + 5090, + 5229, + 5216, + 0, + 5090, + 5093, + 5235, + 5229, + 0, + 5093, + 5098, + 5241, + 5235, + 0, + 5098, + 5105, + 5249, + 5241, + 0, + 5105, + 5111, + 5255, + 5249, + 0, + 5111, + 5115, + 5262, + 5255, + 0, + 5115, + 5121, + 5270, + 5262, + 0, + 5121, + 5123, + 5271, + 5270, + 0, + 5123, + 5125, + 5274, + 5271, + 0, + 5125, + 5126, + 5275, + 5274, + 0, + 5126, + 5124, + 5272, + 5275, + 0, + 5124, + 5120, + 5267, + 5272, + 0, + 5120, + 5113, + 5261, + 5267, + 0, + 5113, + 5110, + 5254, + 5261, + 0, + 5110, + 5104, + 5247, + 5254, + 0, + 5104, + 5099, + 5239, + 5247, + 0, + 5099, + 5094, + 5234, + 5239, + 0, + 5094, + 5091, + 5231, + 5234, + 0, + 5091, + 5083, + 5218, + 5231, + 0, + 5083, + 5081, + 5217, + 5218, + 0, + 5217, + 5224, + 5227, + 5222, + 0, + 5224, + 5243, + 5252, + 5227, + 0, + 5243, + 5253, + 5263, + 5252, + 0, + 5253, + 5264, + 5280, + 5263, + 0, + 5264, + 5278, + 5291, + 5280, + 0, + 5278, + 5285, + 5299, + 5291, + 0, + 5285, + 5294, + 5306, + 5299, + 0, + 5294, + 5296, + 5308, + 5306, + 0, + 5296, + 5301, + 5311, + 5308, + 0, + 5301, + 5303, + 5313, + 5311, + 0, + 5303, + 5305, + 5316, + 5313, + 0, + 5305, + 5304, + 5315, + 5316, + 0, + 5304, + 5302, + 5312, + 5315, + 0, + 5302, + 5297, + 5309, + 5312, + 0, + 5297, + 5295, + 5307, + 5309, + 0, + 5295, + 5288, + 5300, + 5307, + 0, + 5288, + 5279, + 5293, + 5300, + 0, + 5279, + 5269, + 5283, + 5293, + 0, + 5269, + 5260, + 5273, + 5283, + 0, + 5260, + 5246, + 5256, + 5273, + 0, + 5246, + 5238, + 5245, + 5256, + 0, + 5238, + 5208, + 5211, + 5245, + 0, + 5208, + 5203, + 5207, + 5211, + 0, + 5203, + 5196, + 5199, + 5207, + 0, + 5196, + 5191, + 5194, + 5199, + 0, + 5191, + 5188, + 5190, + 5194, + 0, + 5188, + 5182, + 5186, + 5190, + 0, + 5182, + 5177, + 5180, + 5186, + 0, + 5177, + 5173, + 5176, + 5180, + 0, + 5173, + 5170, + 5172, + 5176, + 0, + 5170, + 5165, + 5168, + 5172, + 0, + 5165, + 5161, + 5164, + 5168, + 0, + 5161, + 5157, + 5160, + 5164, + 0, + 5157, + 5154, + 5156, + 5160, + 0, + 5154, + 5150, + 5152, + 5156, + 0, + 5150, + 5145, + 5148, + 5152, + 0, + 5145, + 5134, + 5140, + 5148, + 0, + 5134, + 5122, + 5130, + 5140, + 0, + 5122, + 5106, + 5114, + 5130, + 0, + 5106, + 5097, + 5103, + 5114, + 0, + 5097, + 5092, + 5096, + 5103, + 0, + 5092, + 5082, + 5084, + 5096, + 0, + 5082, + 5086, + 5088, + 5084, + 0, + 5086, + 5087, + 5089, + 5088, + 0, + 5087, + 5101, + 5107, + 5089, + 0, + 5101, + 5108, + 5116, + 5107, + 0, + 5108, + 5118, + 5129, + 5116, + 0, + 5118, + 5133, + 5139, + 5129, + 0, + 5133, + 5147, + 5149, + 5139, + 0, + 5147, + 5151, + 5153, + 5149, + 0, + 5151, + 5155, + 5158, + 5153, + 0, + 5155, + 5159, + 5162, + 5158, + 0, + 5159, + 5163, + 5166, + 5162, + 0, + 5163, + 5167, + 5169, + 5166, + 0, + 5167, + 5171, + 5174, + 5169, + 0, + 5171, + 5175, + 5179, + 5174, + 0, + 5175, + 5181, + 5184, + 5179, + 0, + 5181, + 5187, + 5189, + 5184, + 0, + 5187, + 5192, + 5195, + 5189, + 0, + 5192, + 5197, + 5201, + 5195, + 0, + 5197, + 5202, + 5206, + 5201, + 0, + 5202, + 5216, + 5219, + 5206, + 0, + 5216, + 5229, + 5233, + 5219, + 0, + 5229, + 5235, + 5242, + 5233, + 0, + 5235, + 5241, + 5251, + 5242, + 0, + 5241, + 5249, + 5259, + 5251, + 0, + 5249, + 5255, + 5268, + 5259, + 0, + 5255, + 5262, + 5277, + 5268, + 0, + 5262, + 5270, + 5284, + 5277, + 0, + 5270, + 5271, + 5286, + 5284, + 0, + 5271, + 5274, + 5289, + 5286, + 0, + 5274, + 5275, + 5290, + 5289, + 0, + 5275, + 5272, + 5287, + 5290, + 0, + 5272, + 5267, + 5282, + 5287, + 0, + 5267, + 5261, + 5276, + 5282, + 0, + 5261, + 5254, + 5265, + 5276, + 0, + 5254, + 5247, + 5257, + 5265, + 0, + 5247, + 5239, + 5250, + 5257, + 0, + 5239, + 5234, + 5240, + 5250, + 0, + 5234, + 5231, + 5237, + 5240, + 0, + 5231, + 5218, + 5223, + 5237, + 0, + 5218, + 5217, + 5222, + 5223, + 0, + 5222, + 5227, + 5330, + 5327, + 0, + 5227, + 5252, + 5341, + 5330, + 0, + 5252, + 5263, + 5347, + 5341, + 0, + 5263, + 5280, + 5355, + 5347, + 0, + 5280, + 5291, + 5365, + 5355, + 0, + 5291, + 5299, + 5367, + 5365, + 0, + 5299, + 5306, + 5369, + 5367, + 0, + 5306, + 5308, + 5373, + 5369, + 0, + 5308, + 5311, + 5376, + 5373, + 0, + 5311, + 5313, + 5378, + 5376, + 0, + 5313, + 5316, + 5380, + 5378, + 0, + 5316, + 5315, + 5379, + 5380, + 0, + 5315, + 5312, + 5377, + 5379, + 0, + 5312, + 5309, + 5374, + 5377, + 0, + 5309, + 5307, + 5371, + 5374, + 0, + 5307, + 5300, + 5368, + 5371, + 0, + 5300, + 5293, + 5366, + 5368, + 0, + 5293, + 5283, + 5358, + 5366, + 0, + 5283, + 5273, + 5352, + 5358, + 0, + 5273, + 5256, + 5345, + 5352, + 0, + 5256, + 5245, + 5338, + 5345, + 0, + 5245, + 5211, + 5325, + 5338, + 0, + 5211, + 5207, + 5324, + 5325, + 0, + 5207, + 5199, + 5321, + 5324, + 0, + 5199, + 5194, + 5319, + 5321, + 0, + 5194, + 5190, + 5318, + 5319, + 0, + 5190, + 5186, + 5314, + 5318, + 0, + 5186, + 5180, + 5298, + 5314, + 0, + 5180, + 5176, + 5281, + 5298, + 0, + 5176, + 5172, + 5258, + 5281, + 0, + 5172, + 5168, + 5244, + 5258, + 0, + 5168, + 5164, + 5232, + 5244, + 0, + 5164, + 5160, + 5228, + 5232, + 0, + 5160, + 5156, + 5225, + 5228, + 0, + 5156, + 5152, + 5220, + 5225, + 0, + 5152, + 5148, + 5214, + 5220, + 0, + 5148, + 5140, + 5213, + 5214, + 0, + 5140, + 5130, + 5210, + 5213, + 0, + 5130, + 5114, + 5204, + 5210, + 0, + 5114, + 5103, + 5198, + 5204, + 0, + 5103, + 5096, + 5193, + 5198, + 0, + 5096, + 5084, + 5178, + 5193, + 0, + 5084, + 5088, + 5183, + 5178, + 0, + 5088, + 5089, + 5185, + 5183, + 0, + 5089, + 5107, + 5200, + 5185, + 0, + 5107, + 5116, + 5205, + 5200, + 0, + 5116, + 5129, + 5209, + 5205, + 0, + 5129, + 5139, + 5212, + 5209, + 0, + 5139, + 5149, + 5215, + 5212, + 0, + 5149, + 5153, + 5221, + 5215, + 0, + 5153, + 5158, + 5226, + 5221, + 0, + 5158, + 5162, + 5230, + 5226, + 0, + 5162, + 5166, + 5236, + 5230, + 0, + 5166, + 5169, + 5248, + 5236, + 0, + 5169, + 5174, + 5266, + 5248, + 0, + 5174, + 5179, + 5292, + 5266, + 0, + 5179, + 5184, + 5310, + 5292, + 0, + 5184, + 5189, + 5317, + 5310, + 0, + 5189, + 5195, + 5320, + 5317, + 0, + 5195, + 5201, + 5322, + 5320, + 0, + 5201, + 5206, + 5323, + 5322, + 0, + 5206, + 5219, + 5326, + 5323, + 0, + 5219, + 5233, + 5333, + 5326, + 0, + 5233, + 5242, + 5337, + 5333, + 0, + 5242, + 5251, + 5340, + 5337, + 0, + 5251, + 5259, + 5346, + 5340, + 0, + 5259, + 5268, + 5349, + 5346, + 0, + 5268, + 5277, + 5354, + 5349, + 0, + 5277, + 5284, + 5357, + 5354, + 0, + 5284, + 5286, + 5359, + 5357, + 0, + 5286, + 5289, + 5361, + 5359, + 0, + 5289, + 5290, + 5362, + 5361, + 0, + 5290, + 5287, + 5360, + 5362, + 0, + 5287, + 5282, + 5356, + 5360, + 0, + 5282, + 5276, + 5353, + 5356, + 0, + 5276, + 5265, + 5348, + 5353, + 0, + 5265, + 5257, + 5344, + 5348, + 0, + 5257, + 5250, + 5339, + 5344, + 0, + 5250, + 5240, + 5335, + 5339, + 0, + 5240, + 5237, + 5334, + 5335, + 0, + 5237, + 5223, + 5328, + 5334, + 0, + 5223, + 5222, + 5327, + 5328, + 0, + 5327, + 5330, + 5460, + 5454, + 0, + 5330, + 5341, + 5480, + 5460, + 0, + 5341, + 5347, + 5486, + 5480, + 0, + 5347, + 5355, + 5493, + 5486, + 0, + 5355, + 5365, + 5503, + 5493, + 0, + 5365, + 5367, + 5505, + 5503, + 0, + 5367, + 5369, + 5509, + 5505, + 0, + 5369, + 5373, + 5513, + 5509, + 0, + 5373, + 5376, + 5516, + 5513, + 0, + 5376, + 5378, + 5518, + 5516, + 0, + 5378, + 5380, + 5520, + 5518, + 0, + 5380, + 5379, + 5519, + 5520, + 0, + 5379, + 5377, + 5517, + 5519, + 0, + 5377, + 5374, + 5514, + 5517, + 0, + 5374, + 5371, + 5511, + 5514, + 0, + 5371, + 5368, + 5508, + 5511, + 0, + 5368, + 5366, + 5504, + 5508, + 0, + 5366, + 5358, + 5497, + 5504, + 0, + 5358, + 5352, + 5490, + 5497, + 0, + 5352, + 5345, + 5483, + 5490, + 0, + 5345, + 5338, + 5476, + 5483, + 0, + 5338, + 5325, + 5440, + 5476, + 0, + 5325, + 5324, + 5435, + 5440, + 0, + 5324, + 5321, + 5429, + 5435, + 0, + 5321, + 5319, + 5424, + 5429, + 0, + 5319, + 5318, + 5421, + 5424, + 0, + 5318, + 5314, + 5415, + 5421, + 0, + 5314, + 5298, + 5410, + 5415, + 0, + 5298, + 5281, + 5406, + 5410, + 0, + 5281, + 5258, + 5402, + 5406, + 0, + 5258, + 5244, + 5398, + 5402, + 0, + 5244, + 5232, + 5394, + 5398, + 0, + 5232, + 5228, + 5390, + 5394, + 0, + 5228, + 5225, + 5387, + 5390, + 0, + 5225, + 5220, + 5385, + 5387, + 0, + 5220, + 5214, + 5381, + 5385, + 0, + 5214, + 5213, + 5372, + 5381, + 0, + 5213, + 5210, + 5364, + 5372, + 0, + 5210, + 5204, + 5350, + 5364, + 0, + 5204, + 5198, + 5342, + 5350, + 0, + 5198, + 5193, + 5336, + 5342, + 0, + 5193, + 5178, + 5329, + 5336, + 0, + 5178, + 5183, + 5331, + 5329, + 0, + 5183, + 5185, + 5332, + 5331, + 0, + 5185, + 5200, + 5343, + 5332, + 0, + 5200, + 5205, + 5351, + 5343, + 0, + 5205, + 5209, + 5363, + 5351, + 0, + 5209, + 5212, + 5370, + 5363, + 0, + 5212, + 5215, + 5382, + 5370, + 0, + 5215, + 5221, + 5386, + 5382, + 0, + 5221, + 5226, + 5388, + 5386, + 0, + 5226, + 5230, + 5391, + 5388, + 0, + 5230, + 5236, + 5395, + 5391, + 0, + 5236, + 5248, + 5399, + 5395, + 0, + 5248, + 5266, + 5405, + 5399, + 0, + 5266, + 5292, + 5409, + 5405, + 0, + 5292, + 5310, + 5414, + 5409, + 0, + 5310, + 5317, + 5420, + 5414, + 0, + 5317, + 5320, + 5425, + 5420, + 0, + 5320, + 5322, + 5430, + 5425, + 0, + 5322, + 5323, + 5434, + 5430, + 0, + 5323, + 5326, + 5449, + 5434, + 0, + 5326, + 5333, + 5468, + 5449, + 0, + 5333, + 5337, + 5472, + 5468, + 0, + 5337, + 5340, + 5479, + 5472, + 0, + 5340, + 5346, + 5485, + 5479, + 0, + 5346, + 5349, + 5489, + 5485, + 0, + 5349, + 5354, + 5492, + 5489, + 0, + 5354, + 5357, + 5496, + 5492, + 0, + 5357, + 5359, + 5499, + 5496, + 0, + 5359, + 5361, + 5501, + 5499, + 0, + 5361, + 5362, + 5500, + 5501, + 0, + 5362, + 5360, + 5498, + 5500, + 0, + 5360, + 5356, + 5495, + 5498, + 0, + 5356, + 5353, + 5491, + 5495, + 0, + 5353, + 5348, + 5488, + 5491, + 0, + 5348, + 5344, + 5482, + 5488, + 0, + 5344, + 5339, + 5477, + 5482, + 0, + 5339, + 5335, + 5471, + 5477, + 0, + 5335, + 5334, + 5469, + 5471, + 0, + 5334, + 5328, + 5455, + 5469, + 0, + 5328, + 5327, + 5454, + 5455, + 0, + 5454, + 5460, + 5522, + 5510, + 0, + 5460, + 5480, + 5536, + 5522, + 0, + 5480, + 5486, + 5542, + 5536, + 0, + 5486, + 5493, + 5550, + 5542, + 0, + 5493, + 5503, + 5559, + 5550, + 0, + 5503, + 5505, + 5561, + 5559, + 0, + 5505, + 5509, + 5563, + 5561, + 0, + 5509, + 5513, + 5565, + 5563, + 0, + 5513, + 5516, + 5567, + 5565, + 0, + 5516, + 5518, + 5569, + 5567, + 0, + 5518, + 5520, + 5571, + 5569, + 0, + 5520, + 5519, + 5570, + 5571, + 0, + 5519, + 5517, + 5568, + 5570, + 0, + 5517, + 5514, + 5566, + 5568, + 0, + 5514, + 5511, + 5564, + 5566, + 0, + 5511, + 5508, + 5562, + 5564, + 0, + 5508, + 5504, + 5560, + 5562, + 0, + 5504, + 5497, + 5553, + 5560, + 0, + 5497, + 5490, + 5547, + 5553, + 0, + 5490, + 5483, + 5540, + 5547, + 0, + 5483, + 5476, + 5533, + 5540, + 0, + 5476, + 5440, + 5481, + 5533, + 0, + 5440, + 5435, + 5474, + 5481, + 0, + 5435, + 5429, + 5465, + 5474, + 0, + 5429, + 5424, + 5461, + 5465, + 0, + 5424, + 5421, + 5458, + 5461, + 0, + 5421, + 5415, + 5452, + 5458, + 0, + 5415, + 5410, + 5447, + 5452, + 0, + 5410, + 5406, + 5442, + 5447, + 0, + 5406, + 5402, + 5437, + 5442, + 0, + 5402, + 5398, + 5431, + 5437, + 0, + 5398, + 5394, + 5426, + 5431, + 0, + 5394, + 5390, + 5422, + 5426, + 0, + 5390, + 5387, + 5416, + 5422, + 0, + 5387, + 5385, + 5411, + 5416, + 0, + 5385, + 5381, + 5407, + 5411, + 0, + 5381, + 5372, + 5404, + 5407, + 0, + 5372, + 5364, + 5401, + 5404, + 0, + 5364, + 5350, + 5396, + 5401, + 0, + 5350, + 5342, + 5392, + 5396, + 0, + 5342, + 5336, + 5389, + 5392, + 0, + 5336, + 5329, + 5375, + 5389, + 0, + 5329, + 5331, + 5383, + 5375, + 0, + 5331, + 5332, + 5384, + 5383, + 0, + 5332, + 5343, + 5393, + 5384, + 0, + 5343, + 5351, + 5397, + 5393, + 0, + 5351, + 5363, + 5400, + 5397, + 0, + 5363, + 5370, + 5403, + 5400, + 0, + 5370, + 5382, + 5408, + 5403, + 0, + 5382, + 5386, + 5412, + 5408, + 0, + 5386, + 5388, + 5417, + 5412, + 0, + 5388, + 5391, + 5423, + 5417, + 0, + 5391, + 5395, + 5428, + 5423, + 0, + 5395, + 5399, + 5433, + 5428, + 0, + 5399, + 5405, + 5441, + 5433, + 0, + 5405, + 5409, + 5445, + 5441, + 0, + 5409, + 5414, + 5450, + 5445, + 0, + 5414, + 5420, + 5457, + 5450, + 0, + 5420, + 5425, + 5463, + 5457, + 0, + 5425, + 5430, + 5466, + 5463, + 0, + 5430, + 5434, + 5473, + 5466, + 0, + 5434, + 5449, + 5507, + 5473, + 0, + 5449, + 5468, + 5527, + 5507, + 0, + 5468, + 5472, + 5532, + 5527, + 0, + 5472, + 5479, + 5535, + 5532, + 0, + 5479, + 5485, + 5541, + 5535, + 0, + 5485, + 5489, + 5545, + 5541, + 0, + 5489, + 5492, + 5549, + 5545, + 0, + 5492, + 5496, + 5552, + 5549, + 0, + 5496, + 5499, + 5555, + 5552, + 0, + 5499, + 5501, + 5557, + 5555, + 0, + 5501, + 5500, + 5556, + 5557, + 0, + 5500, + 5498, + 5554, + 5556, + 0, + 5498, + 5495, + 5551, + 5554, + 0, + 5495, + 5491, + 5548, + 5551, + 0, + 5491, + 5488, + 5543, + 5548, + 0, + 5488, + 5482, + 5539, + 5543, + 0, + 5482, + 5477, + 5534, + 5539, + 0, + 5477, + 5471, + 5530, + 5534, + 0, + 5471, + 5469, + 5528, + 5530, + 0, + 5469, + 5455, + 5512, + 5528, + 0, + 5455, + 5454, + 5510, + 5512, + 0, + 5510, + 5522, + 5576, + 5573, + 0, + 5522, + 5536, + 5587, + 5576, + 0, + 5536, + 5542, + 5594, + 5587, + 0, + 5542, + 5550, + 5600, + 5594, + 0, + 5550, + 5559, + 5611, + 5600, + 0, + 5559, + 5561, + 5613, + 5611, + 0, + 5561, + 5563, + 5617, + 5613, + 0, + 5563, + 5565, + 5619, + 5617, + 0, + 5565, + 5567, + 5621, + 5619, + 0, + 5567, + 5569, + 5623, + 5621, + 0, + 5569, + 5571, + 5626, + 5623, + 0, + 5571, + 5570, + 5625, + 5626, + 0, + 5570, + 5568, + 5622, + 5625, + 0, + 5568, + 5566, + 5620, + 5622, + 0, + 5566, + 5564, + 5618, + 5620, + 0, + 5564, + 5562, + 5616, + 5618, + 0, + 5562, + 5560, + 5612, + 5616, + 0, + 5560, + 5553, + 5606, + 5612, + 0, + 5553, + 5547, + 5598, + 5606, + 0, + 5547, + 5540, + 5591, + 5598, + 0, + 5540, + 5533, + 5584, + 5591, + 0, + 5533, + 5481, + 5558, + 5584, + 0, + 5481, + 5474, + 5546, + 5558, + 0, + 5474, + 5465, + 5537, + 5546, + 0, + 5465, + 5461, + 5529, + 5537, + 0, + 5461, + 5458, + 5526, + 5529, + 0, + 5458, + 5452, + 5524, + 5526, + 0, + 5452, + 5447, + 5521, + 5524, + 0, + 5447, + 5442, + 5506, + 5521, + 0, + 5442, + 5437, + 5494, + 5506, + 0, + 5437, + 5431, + 5484, + 5494, + 0, + 5431, + 5426, + 5475, + 5484, + 0, + 5426, + 5422, + 5467, + 5475, + 0, + 5422, + 5416, + 5462, + 5467, + 0, + 5416, + 5411, + 5456, + 5462, + 0, + 5411, + 5407, + 5451, + 5456, + 0, + 5407, + 5404, + 5448, + 5451, + 0, + 5404, + 5401, + 5444, + 5448, + 0, + 5401, + 5396, + 5438, + 5444, + 0, + 5396, + 5392, + 5432, + 5438, + 0, + 5392, + 5389, + 5427, + 5432, + 0, + 5389, + 5375, + 5413, + 5427, + 0, + 5375, + 5383, + 5418, + 5413, + 0, + 5383, + 5384, + 5419, + 5418, + 0, + 5384, + 5393, + 5436, + 5419, + 0, + 5393, + 5397, + 5439, + 5436, + 0, + 5397, + 5400, + 5443, + 5439, + 0, + 5400, + 5403, + 5446, + 5443, + 0, + 5403, + 5408, + 5453, + 5446, + 0, + 5408, + 5412, + 5459, + 5453, + 0, + 5412, + 5417, + 5464, + 5459, + 0, + 5417, + 5423, + 5470, + 5464, + 0, + 5423, + 5428, + 5478, + 5470, + 0, + 5428, + 5433, + 5487, + 5478, + 0, + 5433, + 5441, + 5502, + 5487, + 0, + 5441, + 5445, + 5515, + 5502, + 0, + 5445, + 5450, + 5523, + 5515, + 0, + 5450, + 5457, + 5525, + 5523, + 0, + 5457, + 5463, + 5531, + 5525, + 0, + 5463, + 5466, + 5538, + 5531, + 0, + 5466, + 5473, + 5544, + 5538, + 0, + 5473, + 5507, + 5572, + 5544, + 0, + 5507, + 5527, + 5579, + 5572, + 0, + 5527, + 5532, + 5583, + 5579, + 0, + 5532, + 5535, + 5588, + 5583, + 0, + 5535, + 5541, + 5592, + 5588, + 0, + 5541, + 5545, + 5597, + 5592, + 0, + 5545, + 5549, + 5601, + 5597, + 0, + 5549, + 5552, + 5605, + 5601, + 0, + 5552, + 5555, + 5608, + 5605, + 0, + 5555, + 5557, + 5610, + 5608, + 0, + 5557, + 5556, + 5609, + 5610, + 0, + 5556, + 5554, + 5607, + 5609, + 0, + 5554, + 5551, + 5603, + 5607, + 0, + 5551, + 5548, + 5599, + 5603, + 0, + 5548, + 5543, + 5596, + 5599, + 0, + 5543, + 5539, + 5590, + 5596, + 0, + 5539, + 5534, + 5586, + 5590, + 0, + 5534, + 5530, + 5582, + 5586, + 0, + 5530, + 5528, + 5580, + 5582, + 0, + 5528, + 5512, + 5575, + 5580, + 0, + 5512, + 5510, + 5573, + 5575, + 0, + 5573, + 5576, + 5687, + 5679, + 0, + 5576, + 5587, + 5706, + 5687, + 0, + 5587, + 5594, + 5714, + 5706, + 0, + 5594, + 5600, + 5722, + 5714, + 0, + 5600, + 5611, + 5734, + 5722, + 0, + 5611, + 5613, + 5736, + 5734, + 0, + 5613, + 5617, + 5740, + 5736, + 0, + 5617, + 5619, + 5743, + 5740, + 0, + 5619, + 5621, + 5746, + 5743, + 0, + 5621, + 5623, + 5748, + 5746, + 0, + 5623, + 5626, + 5750, + 5748, + 0, + 5626, + 5625, + 5749, + 5750, + 0, + 5625, + 5622, + 5747, + 5749, + 0, + 5622, + 5620, + 5745, + 5747, + 0, + 5620, + 5618, + 5742, + 5745, + 0, + 5618, + 5616, + 5738, + 5742, + 0, + 5616, + 5612, + 5735, + 5738, + 0, + 5612, + 5606, + 5727, + 5735, + 0, + 5606, + 5598, + 5719, + 5727, + 0, + 5598, + 5591, + 5711, + 5719, + 0, + 5591, + 5584, + 5703, + 5711, + 0, + 5584, + 5558, + 5668, + 5703, + 0, + 5558, + 5546, + 5664, + 5668, + 0, + 5546, + 5537, + 5657, + 5664, + 0, + 5537, + 5529, + 5654, + 5657, + 0, + 5529, + 5526, + 5650, + 5654, + 0, + 5526, + 5524, + 5647, + 5650, + 0, + 5524, + 5521, + 5643, + 5647, + 0, + 5521, + 5506, + 5640, + 5643, + 0, + 5506, + 5494, + 5638, + 5640, + 0, + 5494, + 5484, + 5636, + 5638, + 0, + 5484, + 5475, + 5634, + 5636, + 0, + 5475, + 5467, + 5632, + 5634, + 0, + 5467, + 5462, + 5630, + 5632, + 0, + 5462, + 5456, + 5628, + 5630, + 0, + 5456, + 5451, + 5624, + 5628, + 0, + 5451, + 5448, + 5615, + 5624, + 0, + 5448, + 5444, + 5604, + 5615, + 0, + 5444, + 5438, + 5593, + 5604, + 0, + 5438, + 5432, + 5585, + 5593, + 0, + 5432, + 5427, + 5581, + 5585, + 0, + 5427, + 5413, + 5574, + 5581, + 0, + 5413, + 5418, + 5577, + 5574, + 0, + 5418, + 5419, + 5578, + 5577, + 0, + 5419, + 5436, + 5589, + 5578, + 0, + 5436, + 5439, + 5595, + 5589, + 0, + 5439, + 5443, + 5602, + 5595, + 0, + 5443, + 5446, + 5614, + 5602, + 0, + 5446, + 5453, + 5627, + 5614, + 0, + 5453, + 5459, + 5629, + 5627, + 0, + 5459, + 5464, + 5631, + 5629, + 0, + 5464, + 5470, + 5633, + 5631, + 0, + 5470, + 5478, + 5635, + 5633, + 0, + 5478, + 5487, + 5637, + 5635, + 0, + 5487, + 5502, + 5639, + 5637, + 0, + 5502, + 5515, + 5642, + 5639, + 0, + 5515, + 5523, + 5645, + 5642, + 0, + 5523, + 5525, + 5649, + 5645, + 0, + 5525, + 5531, + 5655, + 5649, + 0, + 5531, + 5538, + 5658, + 5655, + 0, + 5538, + 5544, + 5662, + 5658, + 0, + 5544, + 5572, + 5678, + 5662, + 0, + 5572, + 5579, + 5695, + 5678, + 0, + 5579, + 5583, + 5701, + 5695, + 0, + 5583, + 5588, + 5707, + 5701, + 0, + 5588, + 5592, + 5712, + 5707, + 0, + 5592, + 5597, + 5718, + 5712, + 0, + 5597, + 5601, + 5723, + 5718, + 0, + 5601, + 5605, + 5726, + 5723, + 0, + 5605, + 5608, + 5729, + 5726, + 0, + 5608, + 5610, + 5733, + 5729, + 0, + 5610, + 5609, + 5732, + 5733, + 0, + 5609, + 5607, + 5728, + 5732, + 0, + 5607, + 5603, + 5725, + 5728, + 0, + 5603, + 5599, + 5720, + 5725, + 0, + 5599, + 5596, + 5716, + 5720, + 0, + 5596, + 5590, + 5710, + 5716, + 0, + 5590, + 5586, + 5704, + 5710, + 0, + 5586, + 5582, + 5699, + 5704, + 0, + 5582, + 5580, + 5696, + 5699, + 0, + 5580, + 5575, + 5682, + 5696, + 0, + 5575, + 5573, + 5679, + 5682, + 0, + 5679, + 5687, + 5779, + 5777, + 0, + 5687, + 5706, + 5793, + 5779, + 0, + 5706, + 5714, + 5801, + 5793, + 0, + 5714, + 5722, + 5810, + 5801, + 0, + 5722, + 5734, + 5824, + 5810, + 0, + 5734, + 5736, + 5831, + 5824, + 0, + 5736, + 5740, + 5834, + 5831, + 0, + 5740, + 5743, + 5841, + 5834, + 0, + 5743, + 5746, + 5845, + 5841, + 0, + 5746, + 5748, + 5848, + 5845, + 0, + 5748, + 5750, + 5851, + 5848, + 0, + 5750, + 5749, + 5849, + 5851, + 0, + 5749, + 5747, + 5846, + 5849, + 0, + 5747, + 5745, + 5843, + 5846, + 0, + 5745, + 5742, + 5837, + 5843, + 0, + 5742, + 5738, + 5832, + 5837, + 0, + 5738, + 5735, + 5827, + 5832, + 0, + 5735, + 5727, + 5818, + 5827, + 0, + 5727, + 5719, + 5807, + 5818, + 0, + 5719, + 5711, + 5799, + 5807, + 0, + 5711, + 5703, + 5791, + 5799, + 0, + 5703, + 5668, + 5772, + 5791, + 0, + 5668, + 5664, + 5769, + 5772, + 0, + 5664, + 5657, + 5763, + 5769, + 0, + 5657, + 5654, + 5760, + 5763, + 0, + 5654, + 5650, + 5757, + 5760, + 0, + 5650, + 5647, + 5753, + 5757, + 0, + 5647, + 5643, + 5741, + 5753, + 0, + 5643, + 5640, + 5730, + 5741, + 0, + 5640, + 5638, + 5715, + 5730, + 0, + 5638, + 5636, + 5705, + 5715, + 0, + 5636, + 5634, + 5697, + 5705, + 0, + 5634, + 5632, + 5692, + 5697, + 0, + 5632, + 5630, + 5688, + 5692, + 0, + 5630, + 5628, + 5683, + 5688, + 0, + 5628, + 5624, + 5675, + 5683, + 0, + 5624, + 5615, + 5673, + 5675, + 0, + 5615, + 5604, + 5667, + 5673, + 0, + 5604, + 5593, + 5661, + 5667, + 0, + 5593, + 5585, + 5656, + 5661, + 0, + 5585, + 5581, + 5653, + 5656, + 0, + 5581, + 5574, + 5641, + 5653, + 0, + 5574, + 5577, + 5644, + 5641, + 0, + 5577, + 5578, + 5646, + 5644, + 0, + 5578, + 5589, + 5659, + 5646, + 0, + 5589, + 5595, + 5663, + 5659, + 0, + 5595, + 5602, + 5666, + 5663, + 0, + 5602, + 5614, + 5672, + 5666, + 0, + 5614, + 5627, + 5677, + 5672, + 0, + 5627, + 5629, + 5684, + 5677, + 0, + 5629, + 5631, + 5689, + 5684, + 0, + 5631, + 5633, + 5693, + 5689, + 0, + 5633, + 5635, + 5700, + 5693, + 0, + 5635, + 5637, + 5709, + 5700, + 0, + 5637, + 5639, + 5721, + 5709, + 0, + 5639, + 5642, + 5737, + 5721, + 0, + 5642, + 5645, + 5752, + 5737, + 0, + 5645, + 5649, + 5756, + 5752, + 0, + 5649, + 5655, + 5761, + 5756, + 0, + 5655, + 5658, + 5765, + 5761, + 0, + 5658, + 5662, + 5768, + 5765, + 0, + 5662, + 5678, + 5776, + 5768, + 0, + 5678, + 5695, + 5787, + 5776, + 0, + 5695, + 5701, + 5790, + 5787, + 0, + 5701, + 5707, + 5794, + 5790, + 0, + 5707, + 5712, + 5800, + 5794, + 0, + 5712, + 5718, + 5805, + 5800, + 0, + 5718, + 5723, + 5811, + 5805, + 0, + 5723, + 5726, + 5816, + 5811, + 0, + 5726, + 5729, + 5820, + 5816, + 0, + 5729, + 5733, + 5822, + 5820, + 0, + 5733, + 5732, + 5821, + 5822, + 0, + 5732, + 5728, + 5819, + 5821, + 0, + 5728, + 5725, + 5814, + 5819, + 0, + 5725, + 5720, + 5808, + 5814, + 0, + 5720, + 5716, + 5803, + 5808, + 0, + 5716, + 5710, + 5796, + 5803, + 0, + 5710, + 5704, + 5792, + 5796, + 0, + 5704, + 5699, + 5789, + 5792, + 0, + 5699, + 5696, + 5788, + 5789, + 0, + 5696, + 5682, + 5778, + 5788, + 0, + 5682, + 5679, + 5777, + 5778, + 0, + 5777, + 5779, + 5786, + 5782, + 0, + 5779, + 5793, + 5815, + 5786, + 0, + 5793, + 5801, + 5830, + 5815, + 0, + 5801, + 5810, + 5842, + 5830, + 0, + 5810, + 5824, + 5857, + 5842, + 0, + 5824, + 5831, + 5861, + 5857, + 0, + 5831, + 5834, + 5863, + 5861, + 0, + 5834, + 5841, + 5866, + 5863, + 0, + 5841, + 5845, + 5869, + 5866, + 0, + 5845, + 5848, + 5871, + 5869, + 0, + 5848, + 5851, + 5873, + 5871, + 0, + 5851, + 5849, + 5872, + 5873, + 0, + 5849, + 5846, + 5870, + 5872, + 0, + 5846, + 5843, + 5868, + 5870, + 0, + 5843, + 5837, + 5864, + 5868, + 0, + 5837, + 5832, + 5862, + 5864, + 0, + 5832, + 5827, + 5860, + 5862, + 0, + 5827, + 5818, + 5852, + 5860, + 0, + 5818, + 5807, + 5838, + 5852, + 0, + 5807, + 5799, + 5828, + 5838, + 0, + 5799, + 5791, + 5812, + 5828, + 0, + 5791, + 5772, + 5775, + 5812, + 0, + 5772, + 5769, + 5774, + 5775, + 0, + 5769, + 5763, + 5770, + 5774, + 0, + 5763, + 5760, + 5766, + 5770, + 0, + 5760, + 5757, + 5764, + 5766, + 0, + 5757, + 5753, + 5759, + 5764, + 0, + 5753, + 5741, + 5755, + 5759, + 0, + 5741, + 5730, + 5751, + 5755, + 0, + 5730, + 5715, + 5739, + 5751, + 0, + 5715, + 5705, + 5724, + 5739, + 0, + 5705, + 5697, + 5713, + 5724, + 0, + 5697, + 5692, + 5702, + 5713, + 0, + 5692, + 5688, + 5694, + 5702, + 0, + 5688, + 5683, + 5690, + 5694, + 0, + 5683, + 5675, + 5685, + 5690, + 0, + 5675, + 5673, + 5681, + 5685, + 0, + 5673, + 5667, + 5676, + 5681, + 0, + 5667, + 5661, + 5670, + 5676, + 0, + 5661, + 5656, + 5665, + 5670, + 0, + 5656, + 5653, + 5660, + 5665, + 0, + 5653, + 5641, + 5648, + 5660, + 0, + 5641, + 5644, + 5651, + 5648, + 0, + 5644, + 5646, + 5652, + 5651, + 0, + 5646, + 5659, + 5669, + 5652, + 0, + 5659, + 5663, + 5671, + 5669, + 0, + 5663, + 5666, + 5674, + 5671, + 0, + 5666, + 5672, + 5680, + 5674, + 0, + 5672, + 5677, + 5686, + 5680, + 0, + 5677, + 5684, + 5691, + 5686, + 0, + 5684, + 5689, + 5698, + 5691, + 0, + 5689, + 5693, + 5708, + 5698, + 0, + 5693, + 5700, + 5717, + 5708, + 0, + 5700, + 5709, + 5731, + 5717, + 0, + 5709, + 5721, + 5744, + 5731, + 0, + 5721, + 5737, + 5754, + 5744, + 0, + 5737, + 5752, + 5758, + 5754, + 0, + 5752, + 5756, + 5762, + 5758, + 0, + 5756, + 5761, + 5767, + 5762, + 0, + 5761, + 5765, + 5771, + 5767, + 0, + 5765, + 5768, + 5773, + 5771, + 0, + 5768, + 5776, + 5781, + 5773, + 0, + 5776, + 5787, + 5797, + 5781, + 0, + 5787, + 5790, + 5806, + 5797, + 0, + 5790, + 5794, + 5817, + 5806, + 0, + 5794, + 5800, + 5829, + 5817, + 0, + 5800, + 5805, + 5835, + 5829, + 0, + 5805, + 5811, + 5844, + 5835, + 0, + 5811, + 5816, + 5850, + 5844, + 0, + 5816, + 5820, + 5854, + 5850, + 0, + 5820, + 5822, + 5856, + 5854, + 0, + 5822, + 5821, + 5855, + 5856, + 0, + 5821, + 5819, + 5853, + 5855, + 0, + 5819, + 5814, + 5847, + 5853, + 0, + 5814, + 5808, + 5839, + 5847, + 0, + 5808, + 5803, + 5833, + 5839, + 0, + 5803, + 5796, + 5826, + 5833, + 0, + 5796, + 5792, + 5813, + 5826, + 0, + 5792, + 5789, + 5802, + 5813, + 0, + 5789, + 5788, + 5798, + 5802, + 0, + 5788, + 5778, + 5783, + 5798, + 0, + 5778, + 5777, + 5782, + 5783, + 0, + 5782, + 5786, + 5915, + 5910, + 0, + 5786, + 5815, + 5933, + 5915, + 0, + 5815, + 5830, + 5941, + 5933, + 0, + 5830, + 5842, + 5948, + 5941, + 0, + 5842, + 5857, + 5960, + 5948, + 0, + 5857, + 5861, + 5964, + 5960, + 0, + 5861, + 5863, + 5968, + 5964, + 0, + 5863, + 5866, + 5971, + 5968, + 0, + 5866, + 5869, + 5973, + 5971, + 0, + 5869, + 5871, + 5977, + 5973, + 0, + 5871, + 5873, + 5979, + 5977, + 0, + 5873, + 5872, + 5978, + 5979, + 0, + 5872, + 5870, + 5975, + 5978, + 0, + 5870, + 5868, + 5972, + 5975, + 0, + 5868, + 5864, + 5969, + 5972, + 0, + 5864, + 5862, + 5966, + 5969, + 0, + 5862, + 5860, + 5962, + 5966, + 0, + 5860, + 5852, + 5955, + 5962, + 0, + 5852, + 5838, + 5947, + 5955, + 0, + 5838, + 5828, + 5938, + 5947, + 0, + 5828, + 5812, + 5931, + 5938, + 0, + 5812, + 5775, + 5903, + 5931, + 0, + 5775, + 5774, + 5901, + 5903, + 0, + 5774, + 5770, + 5897, + 5901, + 0, + 5770, + 5766, + 5894, + 5897, + 0, + 5766, + 5764, + 5892, + 5894, + 0, + 5764, + 5759, + 5890, + 5892, + 0, + 5759, + 5755, + 5888, + 5890, + 0, + 5755, + 5751, + 5886, + 5888, + 0, + 5751, + 5739, + 5884, + 5886, + 0, + 5739, + 5724, + 5882, + 5884, + 0, + 5724, + 5713, + 5880, + 5882, + 0, + 5713, + 5702, + 5878, + 5880, + 0, + 5702, + 5694, + 5876, + 5878, + 0, + 5694, + 5690, + 5874, + 5876, + 0, + 5690, + 5685, + 5865, + 5874, + 0, + 5685, + 5681, + 5859, + 5865, + 0, + 5681, + 5676, + 5840, + 5859, + 0, + 5676, + 5670, + 5823, + 5840, + 0, + 5670, + 5665, + 5804, + 5823, + 0, + 5665, + 5660, + 5795, + 5804, + 0, + 5660, + 5648, + 5780, + 5795, + 0, + 5648, + 5651, + 5784, + 5780, + 0, + 5651, + 5652, + 5785, + 5784, + 0, + 5652, + 5669, + 5809, + 5785, + 0, + 5669, + 5671, + 5825, + 5809, + 0, + 5671, + 5674, + 5836, + 5825, + 0, + 5674, + 5680, + 5858, + 5836, + 0, + 5680, + 5686, + 5867, + 5858, + 0, + 5686, + 5691, + 5875, + 5867, + 0, + 5691, + 5698, + 5877, + 5875, + 0, + 5698, + 5708, + 5879, + 5877, + 0, + 5708, + 5717, + 5881, + 5879, + 0, + 5717, + 5731, + 5883, + 5881, + 0, + 5731, + 5744, + 5885, + 5883, + 0, + 5744, + 5754, + 5887, + 5885, + 0, + 5754, + 5758, + 5889, + 5887, + 0, + 5758, + 5762, + 5891, + 5889, + 0, + 5762, + 5767, + 5895, + 5891, + 0, + 5767, + 5771, + 5899, + 5895, + 0, + 5771, + 5773, + 5900, + 5899, + 0, + 5773, + 5781, + 5908, + 5900, + 0, + 5781, + 5797, + 5921, + 5908, + 0, + 5797, + 5806, + 5927, + 5921, + 0, + 5806, + 5817, + 5934, + 5927, + 0, + 5817, + 5829, + 5939, + 5934, + 0, + 5829, + 5835, + 5944, + 5939, + 0, + 5835, + 5844, + 5950, + 5944, + 0, + 5844, + 5850, + 5954, + 5950, + 0, + 5850, + 5854, + 5957, + 5954, + 0, + 5854, + 5856, + 5959, + 5957, + 0, + 5856, + 5855, + 5958, + 5959, + 0, + 5855, + 5853, + 5956, + 5958, + 0, + 5853, + 5847, + 5952, + 5956, + 0, + 5847, + 5839, + 5946, + 5952, + 0, + 5839, + 5833, + 5943, + 5946, + 0, + 5833, + 5826, + 5936, + 5943, + 0, + 5826, + 5813, + 5930, + 5936, + 0, + 5813, + 5802, + 5926, + 5930, + 0, + 5802, + 5798, + 5924, + 5926, + 0, + 5798, + 5783, + 5911, + 5924, + 0, + 5783, + 5782, + 5910, + 5911, + 0, + 5910, + 5915, + 6023, + 6016, + 0, + 5915, + 5933, + 6038, + 6023, + 0, + 5933, + 5941, + 6045, + 6038, + 0, + 5941, + 5948, + 6055, + 6045, + 0, + 5948, + 5960, + 6066, + 6055, + 0, + 5960, + 5964, + 6069, + 6066, + 0, + 5964, + 5968, + 6073, + 6069, + 0, + 5968, + 5971, + 6075, + 6073, + 0, + 5971, + 5973, + 6077, + 6075, + 0, + 5973, + 5977, + 6079, + 6077, + 0, + 5977, + 5979, + 6081, + 6079, + 0, + 5979, + 5978, + 6080, + 6081, + 0, + 5978, + 5975, + 6078, + 6080, + 0, + 5975, + 5972, + 6076, + 6078, + 0, + 5972, + 5969, + 6074, + 6076, + 0, + 5969, + 5966, + 6070, + 6074, + 0, + 5966, + 5962, + 6068, + 6070, + 0, + 5962, + 5955, + 6061, + 6068, + 0, + 5955, + 5947, + 6054, + 6061, + 0, + 5947, + 5938, + 6043, + 6054, + 0, + 5938, + 5931, + 6037, + 6043, + 0, + 5931, + 5903, + 6010, + 6037, + 0, + 5903, + 5901, + 6007, + 6010, + 0, + 5901, + 5897, + 6002, + 6007, + 0, + 5897, + 5894, + 5998, + 6002, + 0, + 5894, + 5892, + 5995, + 5998, + 0, + 5892, + 5890, + 5991, + 5995, + 0, + 5890, + 5888, + 5988, + 5991, + 0, + 5888, + 5886, + 5984, + 5988, + 0, + 5886, + 5884, + 5980, + 5984, + 0, + 5884, + 5882, + 5967, + 5980, + 0, + 5882, + 5880, + 5953, + 5967, + 0, + 5880, + 5878, + 5942, + 5953, + 0, + 5878, + 5876, + 5929, + 5942, + 0, + 5876, + 5874, + 5922, + 5929, + 0, + 5874, + 5865, + 5919, + 5922, + 0, + 5865, + 5859, + 5918, + 5919, + 0, + 5859, + 5840, + 5913, + 5918, + 0, + 5840, + 5823, + 5906, + 5913, + 0, + 5823, + 5804, + 5904, + 5906, + 0, + 5804, + 5795, + 5902, + 5904, + 0, + 5795, + 5780, + 5893, + 5902, + 0, + 5780, + 5784, + 5896, + 5893, + 0, + 5784, + 5785, + 5898, + 5896, + 0, + 5785, + 5809, + 5905, + 5898, + 0, + 5809, + 5825, + 5907, + 5905, + 0, + 5825, + 5836, + 5912, + 5907, + 0, + 5836, + 5858, + 5916, + 5912, + 0, + 5858, + 5867, + 5920, + 5916, + 0, + 5867, + 5875, + 5925, + 5920, + 0, + 5875, + 5877, + 5935, + 5925, + 0, + 5877, + 5879, + 5945, + 5935, + 0, + 5879, + 5881, + 5961, + 5945, + 0, + 5881, + 5883, + 5970, + 5961, + 0, + 5883, + 5885, + 5981, + 5970, + 0, + 5885, + 5887, + 5986, + 5981, + 0, + 5887, + 5889, + 5990, + 5986, + 0, + 5889, + 5891, + 5994, + 5990, + 0, + 5891, + 5895, + 5999, + 5994, + 0, + 5895, + 5899, + 6003, + 5999, + 0, + 5899, + 5900, + 6006, + 6003, + 0, + 5900, + 5908, + 6017, + 6006, + 0, + 5908, + 5921, + 6029, + 6017, + 0, + 5921, + 5927, + 6035, + 6029, + 0, + 5927, + 5934, + 6041, + 6035, + 0, + 5934, + 5939, + 6044, + 6041, + 0, + 5939, + 5944, + 6050, + 6044, + 0, + 5944, + 5950, + 6056, + 6050, + 0, + 5950, + 5954, + 6059, + 6056, + 0, + 5954, + 5957, + 6063, + 6059, + 0, + 5957, + 5959, + 6065, + 6063, + 0, + 5959, + 5958, + 6064, + 6065, + 0, + 5958, + 5956, + 6062, + 6064, + 0, + 5956, + 5952, + 6057, + 6062, + 0, + 5952, + 5946, + 6053, + 6057, + 0, + 5946, + 5943, + 6047, + 6053, + 0, + 5943, + 5936, + 6042, + 6047, + 0, + 5936, + 5930, + 6036, + 6042, + 0, + 5930, + 5926, + 6033, + 6036, + 0, + 5926, + 5924, + 6030, + 6033, + 0, + 5924, + 5911, + 6018, + 6030, + 0, + 5911, + 5910, + 6016, + 6018, + 0, + 6016, + 6023, + 6067, + 6049, + 0, + 6023, + 6038, + 6092, + 6067, + 0, + 6038, + 6045, + 6099, + 6092, + 0, + 6045, + 6055, + 6104, + 6099, + 0, + 6055, + 6066, + 6115, + 6104, + 0, + 6066, + 6069, + 6119, + 6115, + 0, + 6069, + 6073, + 6121, + 6119, + 0, + 6073, + 6075, + 6123, + 6121, + 0, + 6075, + 6077, + 6126, + 6123, + 0, + 6077, + 6079, + 6128, + 6126, + 0, + 6079, + 6081, + 6130, + 6128, + 0, + 6081, + 6080, + 6129, + 6130, + 0, + 6080, + 6078, + 6127, + 6129, + 0, + 6078, + 6076, + 6125, + 6127, + 0, + 6076, + 6074, + 6122, + 6125, + 0, + 6074, + 6070, + 6120, + 6122, + 0, + 6070, + 6068, + 6117, + 6120, + 0, + 6068, + 6061, + 6111, + 6117, + 0, + 6061, + 6054, + 6105, + 6111, + 0, + 6054, + 6043, + 6098, + 6105, + 0, + 6043, + 6037, + 6091, + 6098, + 0, + 6037, + 6010, + 6031, + 6091, + 0, + 6010, + 6007, + 6027, + 6031, + 0, + 6007, + 6002, + 6024, + 6027, + 0, + 6002, + 5998, + 6020, + 6024, + 0, + 5998, + 5995, + 6015, + 6020, + 0, + 5995, + 5991, + 6012, + 6015, + 0, + 5991, + 5988, + 6009, + 6012, + 0, + 5988, + 5984, + 6005, + 6009, + 0, + 5984, + 5980, + 6001, + 6005, + 0, + 5980, + 5967, + 5997, + 6001, + 0, + 5967, + 5953, + 5993, + 5997, + 0, + 5953, + 5942, + 5989, + 5993, + 0, + 5942, + 5929, + 5985, + 5989, + 0, + 5929, + 5922, + 5982, + 5985, + 0, + 5922, + 5919, + 5974, + 5982, + 0, + 5919, + 5918, + 5965, + 5974, + 0, + 5918, + 5913, + 5951, + 5965, + 0, + 5913, + 5906, + 5937, + 5951, + 0, + 5906, + 5904, + 5928, + 5937, + 0, + 5904, + 5902, + 5923, + 5928, + 0, + 5902, + 5893, + 5909, + 5923, + 0, + 5893, + 5896, + 5914, + 5909, + 0, + 5896, + 5898, + 5917, + 5914, + 0, + 5898, + 5905, + 5932, + 5917, + 0, + 5905, + 5907, + 5940, + 5932, + 0, + 5907, + 5912, + 5949, + 5940, + 0, + 5912, + 5916, + 5963, + 5949, + 0, + 5916, + 5920, + 5976, + 5963, + 0, + 5920, + 5925, + 5983, + 5976, + 0, + 5925, + 5935, + 5987, + 5983, + 0, + 5935, + 5945, + 5992, + 5987, + 0, + 5945, + 5961, + 5996, + 5992, + 0, + 5961, + 5970, + 6000, + 5996, + 0, + 5970, + 5981, + 6004, + 6000, + 0, + 5981, + 5986, + 6008, + 6004, + 0, + 5986, + 5990, + 6011, + 6008, + 0, + 5990, + 5994, + 6014, + 6011, + 0, + 5994, + 5999, + 6021, + 6014, + 0, + 5999, + 6003, + 6025, + 6021, + 0, + 6003, + 6006, + 6026, + 6025, + 0, + 6006, + 6017, + 6051, + 6026, + 0, + 6017, + 6029, + 6084, + 6051, + 0, + 6029, + 6035, + 6089, + 6084, + 0, + 6035, + 6041, + 6094, + 6089, + 0, + 6041, + 6044, + 6097, + 6094, + 0, + 6044, + 6050, + 6102, + 6097, + 0, + 6050, + 6056, + 6107, + 6102, + 0, + 6056, + 6059, + 6109, + 6107, + 0, + 6059, + 6063, + 6112, + 6109, + 0, + 6063, + 6065, + 6114, + 6112, + 0, + 6065, + 6064, + 6113, + 6114, + 0, + 6064, + 6062, + 6110, + 6113, + 0, + 6062, + 6057, + 6108, + 6110, + 0, + 6057, + 6053, + 6103, + 6108, + 0, + 6053, + 6047, + 6100, + 6103, + 0, + 6047, + 6042, + 6095, + 6100, + 0, + 6042, + 6036, + 6090, + 6095, + 0, + 6036, + 6033, + 6087, + 6090, + 0, + 6033, + 6030, + 6085, + 6087, + 0, + 6030, + 6018, + 6052, + 6085, + 0, + 6018, + 6016, + 6049, + 6052, + 0, + 6049, + 6067, + 6157, + 6152, + 0, + 6067, + 6092, + 6169, + 6157, + 0, + 6092, + 6099, + 6175, + 6169, + 0, + 6099, + 6104, + 6183, + 6175, + 0, + 6104, + 6115, + 6194, + 6183, + 0, + 6115, + 6119, + 6197, + 6194, + 0, + 6119, + 6121, + 6199, + 6197, + 0, + 6121, + 6123, + 6202, + 6199, + 0, + 6123, + 6126, + 6205, + 6202, + 0, + 6126, + 6128, + 6207, + 6205, + 0, + 6128, + 6130, + 6209, + 6207, + 0, + 6130, + 6129, + 6208, + 6209, + 0, + 6129, + 6127, + 6206, + 6208, + 0, + 6127, + 6125, + 6203, + 6206, + 0, + 6125, + 6122, + 6201, + 6203, + 0, + 6122, + 6120, + 6198, + 6201, + 0, + 6120, + 6117, + 6195, + 6198, + 0, + 6117, + 6111, + 6190, + 6195, + 0, + 6111, + 6105, + 6184, + 6190, + 0, + 6105, + 6098, + 6177, + 6184, + 0, + 6098, + 6091, + 6171, + 6177, + 0, + 6091, + 6031, + 6148, + 6171, + 0, + 6031, + 6027, + 6147, + 6148, + 0, + 6027, + 6024, + 6142, + 6147, + 0, + 6024, + 6020, + 6139, + 6142, + 0, + 6020, + 6015, + 6138, + 6139, + 0, + 6015, + 6012, + 6136, + 6138, + 0, + 6012, + 6009, + 6134, + 6136, + 0, + 6009, + 6005, + 6132, + 6134, + 0, + 6005, + 6001, + 6124, + 6132, + 0, + 6001, + 5997, + 6116, + 6124, + 0, + 5997, + 5993, + 6101, + 6116, + 0, + 5993, + 5989, + 6093, + 6101, + 0, + 5989, + 5985, + 6086, + 6093, + 0, + 5985, + 5982, + 6082, + 6086, + 0, + 5982, + 5974, + 6071, + 6082, + 0, + 5974, + 5965, + 6060, + 6071, + 0, + 5965, + 5951, + 6048, + 6060, + 0, + 5951, + 5937, + 6039, + 6048, + 0, + 5937, + 5928, + 6032, + 6039, + 0, + 5928, + 5923, + 6028, + 6032, + 0, + 5923, + 5909, + 6013, + 6028, + 0, + 5909, + 5914, + 6019, + 6013, + 0, + 5914, + 5917, + 6022, + 6019, + 0, + 5917, + 5932, + 6034, + 6022, + 0, + 5932, + 5940, + 6040, + 6034, + 0, + 5940, + 5949, + 6046, + 6040, + 0, + 5949, + 5963, + 6058, + 6046, + 0, + 5963, + 5976, + 6072, + 6058, + 0, + 5976, + 5983, + 6083, + 6072, + 0, + 5983, + 5987, + 6088, + 6083, + 0, + 5987, + 5992, + 6096, + 6088, + 0, + 5992, + 5996, + 6106, + 6096, + 0, + 5996, + 6000, + 6118, + 6106, + 0, + 6000, + 6004, + 6131, + 6118, + 0, + 6004, + 6008, + 6133, + 6131, + 0, + 6008, + 6011, + 6135, + 6133, + 0, + 6011, + 6014, + 6137, + 6135, + 0, + 6014, + 6021, + 6140, + 6137, + 0, + 6021, + 6025, + 6143, + 6140, + 0, + 6025, + 6026, + 6145, + 6143, + 0, + 6026, + 6051, + 6153, + 6145, + 0, + 6051, + 6084, + 6163, + 6153, + 0, + 6084, + 6089, + 6167, + 6163, + 0, + 6089, + 6094, + 6173, + 6167, + 0, + 6094, + 6097, + 6176, + 6173, + 0, + 6097, + 6102, + 6180, + 6176, + 0, + 6102, + 6107, + 6185, + 6180, + 0, + 6107, + 6109, + 6187, + 6185, + 0, + 6109, + 6112, + 6191, + 6187, + 0, + 6112, + 6114, + 6193, + 6191, + 0, + 6114, + 6113, + 6192, + 6193, + 0, + 6113, + 6110, + 6189, + 6192, + 0, + 6110, + 6108, + 6186, + 6189, + 0, + 6108, + 6103, + 6182, + 6186, + 0, + 6103, + 6100, + 6179, + 6182, + 0, + 6100, + 6095, + 6174, + 6179, + 0, + 6095, + 6090, + 6168, + 6174, + 0, + 6090, + 6087, + 6166, + 6168, + 0, + 6087, + 6085, + 6162, + 6166, + 0, + 6085, + 6052, + 6154, + 6162, + 0, + 6052, + 6049, + 6152, + 6154, + 0, + 6152, + 6157, + 6254, + 6247, + 0, + 6157, + 6169, + 6271, + 6254, + 0, + 6169, + 6175, + 6279, + 6271, + 0, + 6175, + 6183, + 6287, + 6279, + 0, + 6183, + 6194, + 6300, + 6287, + 0, + 6194, + 6197, + 6304, + 6300, + 0, + 6197, + 6199, + 6306, + 6304, + 0, + 6199, + 6202, + 6310, + 6306, + 0, + 6202, + 6205, + 6313, + 6310, + 0, + 6205, + 6207, + 6316, + 6313, + 0, + 6207, + 6209, + 6318, + 6316, + 0, + 6209, + 6208, + 6317, + 6318, + 0, + 6208, + 6206, + 6315, + 6317, + 0, + 6206, + 6203, + 6312, + 6315, + 0, + 6203, + 6201, + 6309, + 6312, + 0, + 6201, + 6198, + 6305, + 6309, + 0, + 6198, + 6195, + 6303, + 6305, + 0, + 6195, + 6190, + 6295, + 6303, + 0, + 6190, + 6184, + 6289, + 6295, + 0, + 6184, + 6177, + 6281, + 6289, + 0, + 6177, + 6171, + 6272, + 6281, + 0, + 6171, + 6148, + 6241, + 6272, + 0, + 6148, + 6147, + 6238, + 6241, + 0, + 6147, + 6142, + 6233, + 6238, + 0, + 6142, + 6139, + 6229, + 6233, + 0, + 6139, + 6138, + 6226, + 6229, + 0, + 6138, + 6136, + 6222, + 6226, + 0, + 6136, + 6134, + 6219, + 6222, + 0, + 6134, + 6132, + 6217, + 6219, + 0, + 6132, + 6124, + 6213, + 6217, + 0, + 6124, + 6116, + 6210, + 6213, + 0, + 6116, + 6101, + 6200, + 6210, + 0, + 6101, + 6093, + 6188, + 6200, + 0, + 6093, + 6086, + 6178, + 6188, + 0, + 6086, + 6082, + 6170, + 6178, + 0, + 6082, + 6071, + 6164, + 6170, + 0, + 6071, + 6060, + 6161, + 6164, + 0, + 6060, + 6048, + 6159, + 6161, + 0, + 6048, + 6039, + 6155, + 6159, + 0, + 6039, + 6032, + 6150, + 6155, + 0, + 6032, + 6028, + 6149, + 6150, + 0, + 6028, + 6013, + 6141, + 6149, + 0, + 6013, + 6019, + 6144, + 6141, + 0, + 6019, + 6022, + 6146, + 6144, + 0, + 6022, + 6034, + 6151, + 6146, + 0, + 6034, + 6040, + 6156, + 6151, + 0, + 6040, + 6046, + 6158, + 6156, + 0, + 6046, + 6058, + 6160, + 6158, + 0, + 6058, + 6072, + 6165, + 6160, + 0, + 6072, + 6083, + 6172, + 6165, + 0, + 6083, + 6088, + 6181, + 6172, + 0, + 6088, + 6096, + 6196, + 6181, + 0, + 6096, + 6106, + 6204, + 6196, + 0, + 6106, + 6118, + 6211, + 6204, + 0, + 6118, + 6131, + 6215, + 6211, + 0, + 6131, + 6133, + 6218, + 6215, + 0, + 6133, + 6135, + 6221, + 6218, + 0, + 6135, + 6137, + 6225, + 6221, + 0, + 6137, + 6140, + 6230, + 6225, + 0, + 6140, + 6143, + 6234, + 6230, + 0, + 6143, + 6145, + 6237, + 6234, + 0, + 6145, + 6153, + 6249, + 6237, + 0, + 6153, + 6163, + 6263, + 6249, + 0, + 6163, + 6167, + 6267, + 6263, + 0, + 6167, + 6173, + 6274, + 6267, + 0, + 6173, + 6176, + 6280, + 6274, + 0, + 6176, + 6180, + 6284, + 6280, + 0, + 6180, + 6185, + 6290, + 6284, + 0, + 6185, + 6187, + 6293, + 6290, + 0, + 6187, + 6191, + 6296, + 6293, + 0, + 6191, + 6193, + 6299, + 6296, + 0, + 6193, + 6192, + 6298, + 6299, + 0, + 6192, + 6189, + 6294, + 6298, + 0, + 6189, + 6186, + 6291, + 6294, + 0, + 6186, + 6182, + 6285, + 6291, + 0, + 6182, + 6179, + 6282, + 6285, + 0, + 6179, + 6174, + 6275, + 6282, + 0, + 6174, + 6168, + 6270, + 6275, + 0, + 6168, + 6166, + 6265, + 6270, + 0, + 6166, + 6162, + 6261, + 6265, + 0, + 6162, + 6154, + 6250, + 6261, + 0, + 6154, + 6152, + 6247, + 6250, + 0, + 6247, + 6254, + 6340, + 6335, + 0, + 6254, + 6271, + 6352, + 6340, + 0, + 6271, + 6279, + 6358, + 6352, + 0, + 6279, + 6287, + 6366, + 6358, + 0, + 6287, + 6300, + 6378, + 6366, + 0, + 6300, + 6304, + 6381, + 6378, + 0, + 6304, + 6306, + 6384, + 6381, + 0, + 6306, + 6310, + 6388, + 6384, + 0, + 6310, + 6313, + 6390, + 6388, + 0, + 6313, + 6316, + 6392, + 6390, + 0, + 6316, + 6318, + 6394, + 6392, + 0, + 6318, + 6317, + 6393, + 6394, + 0, + 6317, + 6315, + 6391, + 6393, + 0, + 6315, + 6312, + 6389, + 6391, + 0, + 6312, + 6309, + 6387, + 6389, + 0, + 6309, + 6305, + 6383, + 6387, + 0, + 6305, + 6303, + 6380, + 6383, + 0, + 6303, + 6295, + 6375, + 6380, + 0, + 6295, + 6289, + 6367, + 6375, + 0, + 6289, + 6281, + 6360, + 6367, + 0, + 6281, + 6272, + 6353, + 6360, + 0, + 6272, + 6241, + 6330, + 6353, + 0, + 6241, + 6238, + 6327, + 6330, + 0, + 6238, + 6233, + 6323, + 6327, + 0, + 6233, + 6229, + 6319, + 6323, + 0, + 6229, + 6226, + 6308, + 6319, + 0, + 6226, + 6222, + 6297, + 6308, + 0, + 6222, + 6219, + 6283, + 6297, + 0, + 6219, + 6217, + 6273, + 6283, + 0, + 6217, + 6213, + 6264, + 6273, + 0, + 6213, + 6210, + 6258, + 6264, + 0, + 6210, + 6200, + 6255, + 6258, + 0, + 6200, + 6188, + 6252, + 6255, + 0, + 6188, + 6178, + 6245, + 6252, + 0, + 6178, + 6170, + 6242, + 6245, + 0, + 6170, + 6164, + 6239, + 6242, + 0, + 6164, + 6161, + 6236, + 6239, + 0, + 6161, + 6159, + 6232, + 6236, + 0, + 6159, + 6155, + 6227, + 6232, + 0, + 6155, + 6150, + 6223, + 6227, + 0, + 6150, + 6149, + 6220, + 6223, + 0, + 6149, + 6141, + 6212, + 6220, + 0, + 6141, + 6144, + 6214, + 6212, + 0, + 6144, + 6146, + 6216, + 6214, + 0, + 6146, + 6151, + 6224, + 6216, + 0, + 6151, + 6156, + 6228, + 6224, + 0, + 6156, + 6158, + 6231, + 6228, + 0, + 6158, + 6160, + 6235, + 6231, + 0, + 6160, + 6165, + 6240, + 6235, + 0, + 6165, + 6172, + 6243, + 6240, + 0, + 6172, + 6181, + 6246, + 6243, + 0, + 6181, + 6196, + 6253, + 6246, + 0, + 6196, + 6204, + 6256, + 6253, + 0, + 6204, + 6211, + 6259, + 6256, + 0, + 6211, + 6215, + 6266, + 6259, + 0, + 6215, + 6218, + 6278, + 6266, + 0, + 6218, + 6221, + 6292, + 6278, + 0, + 6221, + 6225, + 6307, + 6292, + 0, + 6225, + 6230, + 6320, + 6307, + 0, + 6230, + 6234, + 6324, + 6320, + 0, + 6234, + 6237, + 6326, + 6324, + 0, + 6237, + 6249, + 6336, + 6326, + 0, + 6249, + 6263, + 6346, + 6336, + 0, + 6263, + 6267, + 6350, + 6346, + 0, + 6267, + 6274, + 6356, + 6350, + 0, + 6274, + 6280, + 6359, + 6356, + 0, + 6280, + 6284, + 6364, + 6359, + 0, + 6284, + 6290, + 6369, + 6364, + 0, + 6290, + 6293, + 6372, + 6369, + 0, + 6293, + 6296, + 6376, + 6372, + 0, + 6296, + 6299, + 6379, + 6376, + 0, + 6299, + 6298, + 6377, + 6379, + 0, + 6298, + 6294, + 6374, + 6377, + 0, + 6294, + 6291, + 6370, + 6374, + 0, + 6291, + 6285, + 6365, + 6370, + 0, + 6285, + 6282, + 6362, + 6365, + 0, + 6282, + 6275, + 6357, + 6362, + 0, + 6275, + 6270, + 6351, + 6357, + 0, + 6270, + 6265, + 6348, + 6351, + 0, + 6265, + 6261, + 6345, + 6348, + 0, + 6261, + 6250, + 6338, + 6345, + 0, + 6250, + 6247, + 6335, + 6338, + 0, + 6335, + 6340, + 6401, + 6395, + 0, + 6340, + 6352, + 6413, + 6401, + 0, + 6352, + 6358, + 6419, + 6413, + 0, + 6358, + 6366, + 6427, + 6419, + 0, + 6366, + 6378, + 6436, + 6427, + 0, + 6378, + 6381, + 6441, + 6436, + 0, + 6381, + 6384, + 6443, + 6441, + 0, + 6384, + 6388, + 6446, + 6443, + 0, + 6388, + 6390, + 6448, + 6446, + 0, + 6390, + 6392, + 6450, + 6448, + 0, + 6392, + 6394, + 6452, + 6450, + 0, + 6394, + 6393, + 6451, + 6452, + 0, + 6393, + 6391, + 6449, + 6451, + 0, + 6391, + 6389, + 6447, + 6449, + 0, + 6389, + 6387, + 6445, + 6447, + 0, + 6387, + 6383, + 6442, + 6445, + 0, + 6383, + 6380, + 6440, + 6442, + 0, + 6380, + 6375, + 6434, + 6440, + 0, + 6375, + 6367, + 6428, + 6434, + 0, + 6367, + 6360, + 6421, + 6428, + 0, + 6360, + 6353, + 6414, + 6421, + 0, + 6353, + 6330, + 6385, + 6414, + 0, + 6330, + 6327, + 6373, + 6385, + 0, + 6327, + 6323, + 6361, + 6373, + 0, + 6323, + 6319, + 6354, + 6361, + 0, + 6319, + 6308, + 6349, + 6354, + 0, + 6308, + 6297, + 6344, + 6349, + 0, + 6297, + 6283, + 6342, + 6344, + 0, + 6283, + 6273, + 6339, + 6342, + 0, + 6273, + 6264, + 6334, + 6339, + 0, + 6264, + 6258, + 6332, + 6334, + 0, + 6258, + 6255, + 6329, + 6332, + 0, + 6255, + 6252, + 6325, + 6329, + 0, + 6252, + 6245, + 6321, + 6325, + 0, + 6245, + 6242, + 6311, + 6321, + 0, + 6242, + 6239, + 6301, + 6311, + 0, + 6239, + 6236, + 6288, + 6301, + 0, + 6236, + 6232, + 6277, + 6288, + 0, + 6232, + 6227, + 6268, + 6277, + 0, + 6227, + 6223, + 6260, + 6268, + 0, + 6223, + 6220, + 6257, + 6260, + 0, + 6220, + 6212, + 6244, + 6257, + 0, + 6212, + 6214, + 6248, + 6244, + 0, + 6214, + 6216, + 6251, + 6248, + 0, + 6216, + 6224, + 6262, + 6251, + 0, + 6224, + 6228, + 6269, + 6262, + 0, + 6228, + 6231, + 6276, + 6269, + 0, + 6231, + 6235, + 6286, + 6276, + 0, + 6235, + 6240, + 6302, + 6286, + 0, + 6240, + 6243, + 6314, + 6302, + 0, + 6243, + 6246, + 6322, + 6314, + 0, + 6246, + 6253, + 6328, + 6322, + 0, + 6253, + 6256, + 6331, + 6328, + 0, + 6256, + 6259, + 6333, + 6331, + 0, + 6259, + 6266, + 6337, + 6333, + 0, + 6266, + 6278, + 6341, + 6337, + 0, + 6278, + 6292, + 6343, + 6341, + 0, + 6292, + 6307, + 6347, + 6343, + 0, + 6307, + 6320, + 6355, + 6347, + 0, + 6320, + 6324, + 6363, + 6355, + 0, + 6324, + 6326, + 6371, + 6363, + 0, + 6326, + 6336, + 6398, + 6371, + 0, + 6336, + 6346, + 6407, + 6398, + 0, + 6346, + 6350, + 6411, + 6407, + 0, + 6350, + 6356, + 6417, + 6411, + 0, + 6356, + 6359, + 6420, + 6417, + 0, + 6359, + 6364, + 6424, + 6420, + 0, + 6364, + 6369, + 6429, + 6424, + 0, + 6369, + 6372, + 6431, + 6429, + 0, + 6372, + 6376, + 6433, + 6431, + 0, + 6376, + 6379, + 6437, + 6433, + 0, + 6379, + 6377, + 6435, + 6437, + 0, + 6377, + 6374, + 6432, + 6435, + 0, + 6374, + 6370, + 6430, + 6432, + 0, + 6370, + 6365, + 6426, + 6430, + 0, + 6365, + 6362, + 6422, + 6426, + 0, + 6362, + 6357, + 6418, + 6422, + 0, + 6357, + 6351, + 6412, + 6418, + 0, + 6351, + 6348, + 6408, + 6412, + 0, + 6348, + 6345, + 6406, + 6408, + 0, + 6345, + 6338, + 6397, + 6406, + 0, + 6338, + 6335, + 6395, + 6397, + 0, + 6395, + 6401, + 6484, + 6480, + 0, + 6401, + 6413, + 6501, + 6484, + 0, + 6413, + 6419, + 6509, + 6501, + 0, + 6419, + 6427, + 6519, + 6509, + 0, + 6427, + 6436, + 6529, + 6519, + 0, + 6436, + 6441, + 6534, + 6529, + 0, + 6441, + 6443, + 6536, + 6534, + 0, + 6443, + 6446, + 6541, + 6536, + 0, + 6446, + 6448, + 6544, + 6541, + 0, + 6448, + 6450, + 6546, + 6544, + 0, + 6450, + 6452, + 6548, + 6546, + 0, + 6452, + 6451, + 6549, + 6548, + 0, + 6451, + 6449, + 6547, + 6549, + 0, + 6449, + 6447, + 6545, + 6547, + 0, + 6447, + 6445, + 6542, + 6545, + 0, + 6445, + 6442, + 6537, + 6542, + 0, + 6442, + 6440, + 6535, + 6537, + 0, + 6440, + 6434, + 6531, + 6535, + 0, + 6434, + 6428, + 6520, + 6531, + 0, + 6428, + 6421, + 6511, + 6520, + 0, + 6421, + 6414, + 6505, + 6511, + 0, + 6414, + 6385, + 6474, + 6505, + 0, + 6385, + 6373, + 6472, + 6474, + 0, + 6373, + 6361, + 6469, + 6472, + 0, + 6361, + 6354, + 6467, + 6469, + 0, + 6354, + 6349, + 6466, + 6467, + 0, + 6349, + 6344, + 6464, + 6466, + 0, + 6344, + 6342, + 6462, + 6464, + 0, + 6342, + 6339, + 6460, + 6462, + 0, + 6339, + 6334, + 6458, + 6460, + 0, + 6334, + 6332, + 6456, + 6458, + 0, + 6332, + 6329, + 6454, + 6456, + 0, + 6329, + 6325, + 6444, + 6454, + 0, + 6325, + 6321, + 6438, + 6444, + 0, + 6321, + 6311, + 6423, + 6438, + 0, + 6311, + 6301, + 6415, + 6423, + 0, + 6301, + 6288, + 6410, + 6415, + 0, + 6288, + 6277, + 6405, + 6410, + 0, + 6277, + 6268, + 6402, + 6405, + 0, + 6268, + 6260, + 6399, + 6402, + 0, + 6260, + 6257, + 6396, + 6399, + 0, + 6257, + 6244, + 6368, + 6396, + 0, + 6244, + 6248, + 6382, + 6368, + 0, + 6248, + 6251, + 6386, + 6382, + 0, + 6251, + 6262, + 6400, + 6386, + 0, + 6262, + 6269, + 6403, + 6400, + 0, + 6269, + 6276, + 6404, + 6403, + 0, + 6276, + 6286, + 6409, + 6404, + 0, + 6286, + 6302, + 6416, + 6409, + 0, + 6302, + 6314, + 6425, + 6416, + 0, + 6314, + 6322, + 6439, + 6425, + 0, + 6322, + 6328, + 6453, + 6439, + 0, + 6328, + 6331, + 6455, + 6453, + 0, + 6331, + 6333, + 6457, + 6455, + 0, + 6333, + 6337, + 6459, + 6457, + 0, + 6337, + 6341, + 6461, + 6459, + 0, + 6341, + 6343, + 6463, + 6461, + 0, + 6343, + 6347, + 6465, + 6463, + 0, + 6347, + 6355, + 6468, + 6465, + 0, + 6355, + 6363, + 6470, + 6468, + 0, + 6363, + 6371, + 6471, + 6470, + 0, + 6371, + 6398, + 6482, + 6471, + 0, + 6398, + 6407, + 6493, + 6482, + 0, + 6407, + 6411, + 6499, + 6493, + 0, + 6411, + 6417, + 6507, + 6499, + 0, + 6417, + 6420, + 6510, + 6507, + 0, + 6420, + 6424, + 6517, + 6510, + 0, + 6424, + 6429, + 6521, + 6517, + 0, + 6429, + 6431, + 6524, + 6521, + 0, + 6431, + 6433, + 6528, + 6524, + 0, + 6433, + 6437, + 6533, + 6528, + 0, + 6437, + 6435, + 6530, + 6533, + 0, + 6435, + 6432, + 6525, + 6530, + 0, + 6432, + 6430, + 6522, + 6525, + 0, + 6430, + 6426, + 6518, + 6522, + 0, + 6426, + 6422, + 6512, + 6518, + 0, + 6422, + 6418, + 6508, + 6512, + 0, + 6418, + 6412, + 6500, + 6508, + 0, + 6412, + 6408, + 6495, + 6500, + 0, + 6408, + 6406, + 6492, + 6495, + 0, + 6406, + 6397, + 6481, + 6492, + 0, + 6397, + 6395, + 6480, + 6481, + 0, + 6480, + 6484, + 6603, + 6597, + 0, + 6484, + 6501, + 6618, + 6603, + 0, + 6501, + 6509, + 6625, + 6618, + 0, + 6509, + 6519, + 6636, + 6625, + 0, + 6519, + 6529, + 6650, + 6636, + 0, + 6529, + 6534, + 6660, + 6650, + 0, + 6534, + 6536, + 6665, + 6660, + 0, + 6536, + 6541, + 6674, + 6665, + 0, + 6541, + 6544, + 6677, + 6674, + 0, + 6544, + 6546, + 6681, + 6677, + 0, + 6546, + 6548, + 6684, + 6681, + 0, + 6548, + 6549, + 6685, + 6684, + 0, + 6549, + 6547, + 6683, + 6685, + 0, + 6547, + 6545, + 6678, + 6683, + 0, + 6545, + 6542, + 6675, + 6678, + 0, + 6542, + 6537, + 6666, + 6675, + 0, + 6537, + 6535, + 6661, + 6666, + 0, + 6535, + 6531, + 6653, + 6661, + 0, + 6531, + 6520, + 6641, + 6653, + 0, + 6520, + 6511, + 6631, + 6641, + 0, + 6511, + 6505, + 6620, + 6631, + 0, + 6505, + 6474, + 6592, + 6620, + 0, + 6474, + 6472, + 6589, + 6592, + 0, + 6472, + 6469, + 6584, + 6589, + 0, + 6469, + 6467, + 6580, + 6584, + 0, + 6467, + 6466, + 6578, + 6580, + 0, + 6466, + 6464, + 6574, + 6578, + 0, + 6464, + 6462, + 6570, + 6574, + 0, + 6462, + 6460, + 6566, + 6570, + 0, + 6460, + 6458, + 6562, + 6566, + 0, + 6458, + 6456, + 6558, + 6562, + 0, + 6456, + 6454, + 6554, + 6558, + 0, + 6454, + 6444, + 6550, + 6554, + 0, + 6444, + 6438, + 6538, + 6550, + 0, + 6438, + 6423, + 6523, + 6538, + 0, + 6423, + 6415, + 6513, + 6523, + 0, + 6415, + 6410, + 6503, + 6513, + 0, + 6410, + 6405, + 6497, + 6503, + 0, + 6405, + 6402, + 6488, + 6497, + 0, + 6402, + 6399, + 6485, + 6488, + 0, + 6399, + 6396, + 6483, + 6485, + 0, + 6396, + 6368, + 6473, + 6483, + 0, + 6368, + 6382, + 6476, + 6473, + 0, + 6382, + 6386, + 6477, + 6476, + 0, + 6386, + 6400, + 6487, + 6477, + 0, + 6400, + 6403, + 6489, + 6487, + 0, + 6403, + 6404, + 6494, + 6489, + 0, + 6404, + 6409, + 6502, + 6494, + 0, + 6409, + 6416, + 6514, + 6502, + 0, + 6416, + 6425, + 6532, + 6514, + 0, + 6425, + 6439, + 6543, + 6532, + 0, + 6439, + 6453, + 6553, + 6543, + 0, + 6453, + 6455, + 6556, + 6553, + 0, + 6455, + 6457, + 6560, + 6556, + 0, + 6457, + 6459, + 6565, + 6560, + 0, + 6459, + 6461, + 6569, + 6565, + 0, + 6461, + 6463, + 6573, + 6569, + 0, + 6463, + 6465, + 6577, + 6573, + 0, + 6465, + 6468, + 6581, + 6577, + 0, + 6468, + 6470, + 6585, + 6581, + 0, + 6470, + 6471, + 6588, + 6585, + 0, + 6471, + 6482, + 6601, + 6588, + 0, + 6482, + 6493, + 6611, + 6601, + 0, + 6493, + 6499, + 6615, + 6611, + 0, + 6499, + 6507, + 6622, + 6615, + 0, + 6507, + 6510, + 6629, + 6622, + 0, + 6510, + 6517, + 6634, + 6629, + 0, + 6517, + 6521, + 6642, + 6634, + 0, + 6521, + 6524, + 6647, + 6642, + 0, + 6524, + 6528, + 6651, + 6647, + 0, + 6528, + 6533, + 6654, + 6651, + 0, + 6533, + 6530, + 6652, + 6654, + 0, + 6530, + 6525, + 6648, + 6652, + 0, + 6525, + 6522, + 6644, + 6648, + 0, + 6522, + 6518, + 6637, + 6644, + 0, + 6518, + 6512, + 6632, + 6637, + 0, + 6512, + 6508, + 6623, + 6632, + 0, + 6508, + 6500, + 6616, + 6623, + 0, + 6500, + 6495, + 6612, + 6616, + 0, + 6495, + 6492, + 6609, + 6612, + 0, + 6492, + 6481, + 6599, + 6609, + 0, + 6481, + 6480, + 6597, + 6599, + 0, + 6597, + 6603, + 6606, + 6602, + 0, + 6603, + 6618, + 6630, + 6606, + 0, + 6618, + 6625, + 6643, + 6630, + 0, + 6625, + 6636, + 6656, + 6643, + 0, + 6636, + 6650, + 6669, + 6656, + 0, + 6650, + 6660, + 6679, + 6669, + 0, + 6660, + 6665, + 6686, + 6679, + 0, + 6665, + 6674, + 6688, + 6686, + 0, + 6674, + 6677, + 6691, + 6688, + 0, + 6677, + 6681, + 6693, + 6691, + 0, + 6681, + 6684, + 6696, + 6693, + 0, + 6684, + 6685, + 6697, + 6696, + 0, + 6685, + 6683, + 6694, + 6697, + 0, + 6683, + 6678, + 6692, + 6694, + 0, + 6678, + 6675, + 6689, + 6692, + 0, + 6675, + 6666, + 6687, + 6689, + 0, + 6666, + 6661, + 6682, + 6687, + 0, + 6661, + 6653, + 6672, + 6682, + 0, + 6653, + 6641, + 6662, + 6672, + 0, + 6641, + 6631, + 6646, + 6662, + 0, + 6631, + 6620, + 6633, + 6646, + 0, + 6620, + 6592, + 6596, + 6633, + 0, + 6592, + 6589, + 6594, + 6596, + 0, + 6589, + 6584, + 6590, + 6594, + 0, + 6584, + 6580, + 6586, + 6590, + 0, + 6580, + 6578, + 6583, + 6586, + 0, + 6578, + 6574, + 6579, + 6583, + 0, + 6574, + 6570, + 6575, + 6579, + 0, + 6570, + 6566, + 6571, + 6575, + 0, + 6566, + 6562, + 6567, + 6571, + 0, + 6562, + 6558, + 6563, + 6567, + 0, + 6558, + 6554, + 6559, + 6563, + 0, + 6554, + 6550, + 6555, + 6559, + 0, + 6550, + 6538, + 6551, + 6555, + 0, + 6538, + 6523, + 6539, + 6551, + 0, + 6523, + 6513, + 6526, + 6539, + 0, + 6513, + 6503, + 6516, + 6526, + 0, + 6503, + 6497, + 6506, + 6516, + 0, + 6497, + 6488, + 6496, + 6506, + 0, + 6488, + 6485, + 6490, + 6496, + 0, + 6485, + 6483, + 6486, + 6490, + 0, + 6483, + 6473, + 6475, + 6486, + 0, + 6473, + 6476, + 6478, + 6475, + 0, + 6476, + 6477, + 6479, + 6478, + 0, + 6477, + 6487, + 6491, + 6479, + 0, + 6487, + 6489, + 6498, + 6491, + 0, + 6489, + 6494, + 6504, + 6498, + 0, + 6494, + 6502, + 6515, + 6504, + 0, + 6502, + 6514, + 6527, + 6515, + 0, + 6514, + 6532, + 6540, + 6527, + 0, + 6532, + 6543, + 6552, + 6540, + 0, + 6543, + 6553, + 6557, + 6552, + 0, + 6553, + 6556, + 6561, + 6557, + 0, + 6556, + 6560, + 6564, + 6561, + 0, + 6560, + 6565, + 6568, + 6564, + 0, + 6565, + 6569, + 6572, + 6568, + 0, + 6569, + 6573, + 6576, + 6572, + 0, + 6573, + 6577, + 6582, + 6576, + 0, + 6577, + 6581, + 6587, + 6582, + 0, + 6581, + 6585, + 6591, + 6587, + 0, + 6585, + 6588, + 6593, + 6591, + 0, + 6588, + 6601, + 6605, + 6593, + 0, + 6601, + 6611, + 6619, + 6605, + 0, + 6611, + 6615, + 6627, + 6619, + 0, + 6615, + 6622, + 6635, + 6627, + 0, + 6622, + 6629, + 6645, + 6635, + 0, + 6629, + 6634, + 6655, + 6645, + 0, + 6634, + 6642, + 6663, + 6655, + 0, + 6642, + 6647, + 6667, + 6663, + 0, + 6647, + 6651, + 6670, + 6667, + 0, + 6651, + 6654, + 6673, + 6670, + 0, + 6654, + 6652, + 6671, + 6673, + 0, + 6652, + 6648, + 6668, + 6671, + 0, + 6648, + 6644, + 6664, + 6668, + 0, + 6644, + 6637, + 6658, + 6664, + 0, + 6637, + 6632, + 6649, + 6658, + 0, + 6632, + 6623, + 6639, + 6649, + 0, + 6623, + 6616, + 6628, + 6639, + 0, + 6616, + 6612, + 6621, + 6628, + 0, + 6612, + 6609, + 6617, + 6621, + 0, + 6609, + 6599, + 6604, + 6617, + 0, + 6599, + 6597, + 6602, + 6604, + 0, + 6602, + 6606, + 6726, + 6723, + 0, + 6606, + 6630, + 6739, + 6726, + 0, + 6630, + 6643, + 6744, + 6739, + 0, + 6643, + 6656, + 6751, + 6744, + 0, + 6656, + 6669, + 6760, + 6751, + 0, + 6669, + 6679, + 6767, + 6760, + 0, + 6679, + 6686, + 6771, + 6767, + 0, + 6686, + 6688, + 6773, + 6771, + 0, + 6688, + 6691, + 6775, + 6773, + 0, + 6691, + 6693, + 6778, + 6775, + 0, + 6693, + 6696, + 6780, + 6778, + 0, + 6696, + 6697, + 6781, + 6780, + 0, + 6697, + 6694, + 6779, + 6781, + 0, + 6694, + 6692, + 6776, + 6779, + 0, + 6692, + 6689, + 6774, + 6776, + 0, + 6689, + 6687, + 6772, + 6774, + 0, + 6687, + 6682, + 6769, + 6772, + 0, + 6682, + 6672, + 6764, + 6769, + 0, + 6672, + 6662, + 6755, + 6764, + 0, + 6662, + 6646, + 6748, + 6755, + 0, + 6646, + 6633, + 6740, + 6748, + 0, + 6633, + 6596, + 6720, + 6740, + 0, + 6596, + 6594, + 6718, + 6720, + 0, + 6594, + 6590, + 6715, + 6718, + 0, + 6590, + 6586, + 6713, + 6715, + 0, + 6586, + 6583, + 6712, + 6713, + 0, + 6583, + 6579, + 6710, + 6712, + 0, + 6579, + 6575, + 6708, + 6710, + 0, + 6575, + 6571, + 6706, + 6708, + 0, + 6571, + 6567, + 6704, + 6706, + 0, + 6567, + 6563, + 6702, + 6704, + 0, + 6563, + 6559, + 6700, + 6702, + 0, + 6559, + 6555, + 6698, + 6700, + 0, + 6555, + 6551, + 6690, + 6698, + 0, + 6551, + 6539, + 6676, + 6690, + 0, + 6539, + 6526, + 6657, + 6676, + 0, + 6526, + 6516, + 6640, + 6657, + 0, + 6516, + 6506, + 6626, + 6640, + 0, + 6506, + 6496, + 6613, + 6626, + 0, + 6496, + 6490, + 6608, + 6613, + 0, + 6490, + 6486, + 6607, + 6608, + 0, + 6486, + 6475, + 6595, + 6607, + 0, + 6475, + 6478, + 6598, + 6595, + 0, + 6478, + 6479, + 6600, + 6598, + 0, + 6479, + 6491, + 6610, + 6600, + 0, + 6491, + 6498, + 6614, + 6610, + 0, + 6498, + 6504, + 6624, + 6614, + 0, + 6504, + 6515, + 6638, + 6624, + 0, + 6515, + 6527, + 6659, + 6638, + 0, + 6527, + 6540, + 6680, + 6659, + 0, + 6540, + 6552, + 6695, + 6680, + 0, + 6552, + 6557, + 6699, + 6695, + 0, + 6557, + 6561, + 6701, + 6699, + 0, + 6561, + 6564, + 6703, + 6701, + 0, + 6564, + 6568, + 6705, + 6703, + 0, + 6568, + 6572, + 6707, + 6705, + 0, + 6572, + 6576, + 6709, + 6707, + 0, + 6576, + 6582, + 6711, + 6709, + 0, + 6582, + 6587, + 6714, + 6711, + 0, + 6587, + 6591, + 6716, + 6714, + 0, + 6591, + 6593, + 6717, + 6716, + 0, + 6593, + 6605, + 6725, + 6717, + 0, + 6605, + 6619, + 6733, + 6725, + 0, + 6619, + 6627, + 6736, + 6733, + 0, + 6627, + 6635, + 6741, + 6736, + 0, + 6635, + 6645, + 6746, + 6741, + 0, + 6645, + 6655, + 6750, + 6746, + 0, + 6655, + 6663, + 6756, + 6750, + 0, + 6663, + 6667, + 6758, + 6756, + 0, + 6667, + 6670, + 6761, + 6758, + 0, + 6670, + 6673, + 6763, + 6761, + 0, + 6673, + 6671, + 6762, + 6763, + 0, + 6671, + 6668, + 6759, + 6762, + 0, + 6668, + 6664, + 6757, + 6759, + 0, + 6664, + 6658, + 6752, + 6757, + 0, + 6658, + 6649, + 6747, + 6752, + 0, + 6649, + 6639, + 6742, + 6747, + 0, + 6639, + 6628, + 6737, + 6742, + 0, + 6628, + 6621, + 6734, + 6737, + 0, + 6621, + 6617, + 6730, + 6734, + 0, + 6617, + 6604, + 6724, + 6730, + 0, + 6604, + 6602, + 6723, + 6724, + 0, + 6723, + 6726, + 6838, + 6831, + 0, + 6726, + 6739, + 6856, + 6838, + 0, + 6739, + 6744, + 6862, + 6856, + 0, + 6744, + 6751, + 6869, + 6862, + 0, + 6751, + 6760, + 6879, + 6869, + 0, + 6760, + 6767, + 6884, + 6879, + 0, + 6767, + 6771, + 6888, + 6884, + 0, + 6771, + 6773, + 6892, + 6888, + 0, + 6773, + 6775, + 6894, + 6892, + 0, + 6775, + 6778, + 6898, + 6894, + 0, + 6778, + 6780, + 6900, + 6898, + 0, + 6780, + 6781, + 6901, + 6900, + 0, + 6781, + 6779, + 6899, + 6901, + 0, + 6779, + 6776, + 6896, + 6899, + 0, + 6776, + 6774, + 6893, + 6896, + 0, + 6774, + 6772, + 6890, + 6893, + 0, + 6772, + 6769, + 6885, + 6890, + 0, + 6769, + 6764, + 6883, + 6885, + 0, + 6764, + 6755, + 6873, + 6883, + 0, + 6755, + 6748, + 6867, + 6873, + 0, + 6748, + 6740, + 6857, + 6867, + 0, + 6740, + 6720, + 6826, + 6857, + 0, + 6720, + 6718, + 6823, + 6826, + 0, + 6718, + 6715, + 6818, + 6823, + 0, + 6715, + 6713, + 6814, + 6818, + 0, + 6713, + 6712, + 6812, + 6814, + 0, + 6712, + 6710, + 6808, + 6812, + 0, + 6710, + 6708, + 6804, + 6808, + 0, + 6708, + 6706, + 6800, + 6804, + 0, + 6706, + 6704, + 6796, + 6800, + 0, + 6704, + 6702, + 6792, + 6796, + 0, + 6702, + 6700, + 6788, + 6792, + 0, + 6700, + 6698, + 6784, + 6788, + 0, + 6698, + 6690, + 6777, + 6784, + 0, + 6690, + 6676, + 6768, + 6777, + 0, + 6676, + 6657, + 6753, + 6768, + 0, + 6657, + 6640, + 6745, + 6753, + 0, + 6640, + 6626, + 6738, + 6745, + 0, + 6626, + 6613, + 6731, + 6738, + 0, + 6613, + 6608, + 6728, + 6731, + 0, + 6608, + 6607, + 6727, + 6728, + 0, + 6607, + 6595, + 6719, + 6727, + 0, + 6595, + 6598, + 6721, + 6719, + 0, + 6598, + 6600, + 6722, + 6721, + 0, + 6600, + 6610, + 6729, + 6722, + 0, + 6610, + 6614, + 6732, + 6729, + 0, + 6614, + 6624, + 6735, + 6732, + 0, + 6624, + 6638, + 6743, + 6735, + 0, + 6638, + 6659, + 6754, + 6743, + 0, + 6659, + 6680, + 6770, + 6754, + 0, + 6680, + 6695, + 6782, + 6770, + 0, + 6695, + 6699, + 6785, + 6782, + 0, + 6699, + 6701, + 6789, + 6785, + 0, + 6701, + 6703, + 6793, + 6789, + 0, + 6703, + 6705, + 6797, + 6793, + 0, + 6705, + 6707, + 6803, + 6797, + 0, + 6707, + 6709, + 6807, + 6803, + 0, + 6709, + 6711, + 6811, + 6807, + 0, + 6711, + 6714, + 6815, + 6811, + 0, + 6714, + 6716, + 6819, + 6815, + 0, + 6716, + 6717, + 6822, + 6819, + 0, + 6717, + 6725, + 6836, + 6822, + 0, + 6725, + 6733, + 6848, + 6836, + 0, + 6733, + 6736, + 6852, + 6848, + 0, + 6736, + 6741, + 6859, + 6852, + 0, + 6741, + 6746, + 6865, + 6859, + 0, + 6746, + 6750, + 6870, + 6865, + 0, + 6750, + 6756, + 6875, + 6870, + 0, + 6756, + 6758, + 6877, + 6875, + 0, + 6758, + 6761, + 6880, + 6877, + 0, + 6761, + 6763, + 6882, + 6880, + 0, + 6763, + 6762, + 6881, + 6882, + 0, + 6762, + 6759, + 6878, + 6881, + 0, + 6759, + 6757, + 6876, + 6878, + 0, + 6757, + 6752, + 6871, + 6876, + 0, + 6752, + 6747, + 6866, + 6871, + 0, + 6747, + 6742, + 6861, + 6866, + 0, + 6742, + 6737, + 6853, + 6861, + 0, + 6737, + 6734, + 6849, + 6853, + 0, + 6734, + 6730, + 6845, + 6849, + 0, + 6730, + 6724, + 6832, + 6845, + 0, + 6724, + 6723, + 6831, + 6832, + 0, + 6831, + 6838, + 6903, + 6889, + 0, + 6838, + 6856, + 6915, + 6903, + 0, + 6856, + 6862, + 6921, + 6915, + 0, + 6862, + 6869, + 6926, + 6921, + 0, + 6869, + 6879, + 6935, + 6926, + 0, + 6879, + 6884, + 6941, + 6935, + 0, + 6884, + 6888, + 6944, + 6941, + 0, + 6888, + 6892, + 6946, + 6944, + 0, + 6892, + 6894, + 6949, + 6946, + 0, + 6894, + 6898, + 6951, + 6949, + 0, + 6898, + 6900, + 6953, + 6951, + 0, + 6900, + 6901, + 6954, + 6953, + 0, + 6901, + 6899, + 6952, + 6954, + 0, + 6899, + 6896, + 6950, + 6952, + 0, + 6896, + 6893, + 6948, + 6950, + 0, + 6893, + 6890, + 6945, + 6948, + 0, + 6890, + 6885, + 6942, + 6945, + 0, + 6885, + 6883, + 6939, + 6942, + 0, + 6883, + 6873, + 6930, + 6939, + 0, + 6873, + 6867, + 6924, + 6930, + 0, + 6867, + 6857, + 6917, + 6924, + 0, + 6857, + 6826, + 6868, + 6917, + 0, + 6826, + 6823, + 6860, + 6868, + 0, + 6823, + 6818, + 6850, + 6860, + 0, + 6818, + 6814, + 6843, + 6850, + 0, + 6814, + 6812, + 6841, + 6843, + 0, + 6812, + 6808, + 6839, + 6841, + 0, + 6808, + 6804, + 6834, + 6839, + 0, + 6804, + 6800, + 6829, + 6834, + 0, + 6800, + 6796, + 6825, + 6829, + 0, + 6796, + 6792, + 6821, + 6825, + 0, + 6792, + 6788, + 6817, + 6821, + 0, + 6788, + 6784, + 6813, + 6817, + 0, + 6784, + 6777, + 6809, + 6813, + 0, + 6777, + 6768, + 6805, + 6809, + 0, + 6768, + 6753, + 6801, + 6805, + 0, + 6753, + 6745, + 6799, + 6801, + 0, + 6745, + 6738, + 6795, + 6799, + 0, + 6738, + 6731, + 6790, + 6795, + 0, + 6731, + 6728, + 6786, + 6790, + 0, + 6728, + 6727, + 6783, + 6786, + 0, + 6727, + 6719, + 6749, + 6783, + 0, + 6719, + 6721, + 6765, + 6749, + 0, + 6721, + 6722, + 6766, + 6765, + 0, + 6722, + 6729, + 6787, + 6766, + 0, + 6729, + 6732, + 6791, + 6787, + 0, + 6732, + 6735, + 6794, + 6791, + 0, + 6735, + 6743, + 6798, + 6794, + 0, + 6743, + 6754, + 6802, + 6798, + 0, + 6754, + 6770, + 6806, + 6802, + 0, + 6770, + 6782, + 6810, + 6806, + 0, + 6782, + 6785, + 6816, + 6810, + 0, + 6785, + 6789, + 6820, + 6816, + 0, + 6789, + 6793, + 6824, + 6820, + 0, + 6793, + 6797, + 6827, + 6824, + 0, + 6797, + 6803, + 6830, + 6827, + 0, + 6803, + 6807, + 6837, + 6830, + 0, + 6807, + 6811, + 6840, + 6837, + 0, + 6811, + 6815, + 6844, + 6840, + 0, + 6815, + 6819, + 6851, + 6844, + 0, + 6819, + 6822, + 6858, + 6851, + 0, + 6822, + 6836, + 6895, + 6858, + 0, + 6836, + 6848, + 6909, + 6895, + 0, + 6848, + 6852, + 6913, + 6909, + 0, + 6852, + 6859, + 6918, + 6913, + 0, + 6859, + 6865, + 6922, + 6918, + 0, + 6865, + 6870, + 6927, + 6922, + 0, + 6870, + 6875, + 6931, + 6927, + 0, + 6875, + 6877, + 6933, + 6931, + 0, + 6877, + 6880, + 6936, + 6933, + 0, + 6880, + 6882, + 6938, + 6936, + 0, + 6882, + 6881, + 6937, + 6938, + 0, + 6881, + 6878, + 6934, + 6937, + 0, + 6878, + 6876, + 6932, + 6934, + 0, + 6876, + 6871, + 6928, + 6932, + 0, + 6871, + 6866, + 6923, + 6928, + 0, + 6866, + 6861, + 6919, + 6923, + 0, + 6861, + 6853, + 6914, + 6919, + 0, + 6853, + 6849, + 6910, + 6914, + 0, + 6849, + 6845, + 6908, + 6910, + 0, + 6845, + 6832, + 6891, + 6908, + 0, + 6832, + 6831, + 6889, + 6891, + 0, + 6889, + 6903, + 6973, + 6969, + 0, + 6903, + 6915, + 6985, + 6973, + 0, + 6915, + 6921, + 6991, + 6985, + 0, + 6921, + 6926, + 6997, + 6991, + 0, + 6926, + 6935, + 7005, + 6997, + 0, + 6935, + 6941, + 7012, + 7005, + 0, + 6941, + 6944, + 7014, + 7012, + 0, + 6944, + 6946, + 7017, + 7014, + 0, + 6946, + 6949, + 7020, + 7017, + 0, + 6949, + 6951, + 7022, + 7020, + 0, + 6951, + 6953, + 7024, + 7022, + 0, + 6953, + 6954, + 7025, + 7024, + 0, + 6954, + 6952, + 7023, + 7025, + 0, + 6952, + 6950, + 7021, + 7023, + 0, + 6950, + 6948, + 7018, + 7021, + 0, + 6948, + 6945, + 7015, + 7018, + 0, + 6945, + 6942, + 7013, + 7015, + 0, + 6942, + 6939, + 7010, + 7013, + 0, + 6939, + 6930, + 7000, + 7010, + 0, + 6930, + 6924, + 6994, + 7000, + 0, + 6924, + 6917, + 6987, + 6994, + 0, + 6917, + 6868, + 6966, + 6987, + 0, + 6868, + 6860, + 6964, + 6966, + 0, + 6860, + 6850, + 6961, + 6964, + 0, + 6850, + 6843, + 6959, + 6961, + 0, + 6843, + 6841, + 6958, + 6959, + 0, + 6841, + 6839, + 6956, + 6958, + 0, + 6839, + 6834, + 6947, + 6956, + 0, + 6834, + 6829, + 6940, + 6947, + 0, + 6829, + 6825, + 6925, + 6940, + 0, + 6825, + 6821, + 6916, + 6925, + 0, + 6821, + 6817, + 6911, + 6916, + 0, + 6817, + 6813, + 6906, + 6911, + 0, + 6813, + 6809, + 6904, + 6906, + 0, + 6809, + 6805, + 6897, + 6904, + 0, + 6805, + 6801, + 6886, + 6897, + 0, + 6801, + 6799, + 6874, + 6886, + 0, + 6799, + 6795, + 6864, + 6874, + 0, + 6795, + 6790, + 6854, + 6864, + 0, + 6790, + 6786, + 6846, + 6854, + 0, + 6786, + 6783, + 6842, + 6846, + 0, + 6783, + 6749, + 6828, + 6842, + 0, + 6749, + 6765, + 6833, + 6828, + 0, + 6765, + 6766, + 6835, + 6833, + 0, + 6766, + 6787, + 6847, + 6835, + 0, + 6787, + 6791, + 6855, + 6847, + 0, + 6791, + 6794, + 6863, + 6855, + 0, + 6794, + 6798, + 6872, + 6863, + 0, + 6798, + 6802, + 6887, + 6872, + 0, + 6802, + 6806, + 6902, + 6887, + 0, + 6806, + 6810, + 6905, + 6902, + 0, + 6810, + 6816, + 6907, + 6905, + 0, + 6816, + 6820, + 6912, + 6907, + 0, + 6820, + 6824, + 6920, + 6912, + 0, + 6824, + 6827, + 6929, + 6920, + 0, + 6827, + 6830, + 6943, + 6929, + 0, + 6830, + 6837, + 6955, + 6943, + 0, + 6837, + 6840, + 6957, + 6955, + 0, + 6840, + 6844, + 6960, + 6957, + 0, + 6844, + 6851, + 6962, + 6960, + 0, + 6851, + 6858, + 6963, + 6962, + 0, + 6858, + 6895, + 6971, + 6963, + 0, + 6895, + 6909, + 6980, + 6971, + 0, + 6909, + 6913, + 6984, + 6980, + 0, + 6913, + 6918, + 6990, + 6984, + 0, + 6918, + 6922, + 6993, + 6990, + 0, + 6922, + 6927, + 6999, + 6993, + 0, + 6927, + 6931, + 7002, + 6999, + 0, + 6931, + 6933, + 7004, + 7002, + 0, + 6933, + 6936, + 7007, + 7004, + 0, + 6936, + 6938, + 7009, + 7007, + 0, + 6938, + 6937, + 7006, + 7009, + 0, + 6937, + 6934, + 7003, + 7006, + 0, + 6934, + 6932, + 7001, + 7003, + 0, + 6932, + 6928, + 6998, + 7001, + 0, + 6928, + 6923, + 6992, + 6998, + 0, + 6923, + 6919, + 6989, + 6992, + 0, + 6919, + 6914, + 6983, + 6989, + 0, + 6914, + 6910, + 6979, + 6983, + 0, + 6910, + 6908, + 6978, + 6979, + 0, + 6908, + 6891, + 6970, + 6978, + 0, + 6891, + 6889, + 6969, + 6970, + 0, + 6969, + 6973, + 7064, + 7058, + 0, + 6973, + 6985, + 7079, + 7064, + 0, + 6985, + 6991, + 7088, + 7079, + 0, + 6991, + 6997, + 7095, + 7088, + 0, + 6997, + 7005, + 7105, + 7095, + 0, + 7005, + 7012, + 7112, + 7105, + 0, + 7012, + 7014, + 7116, + 7112, + 0, + 7014, + 7017, + 7120, + 7116, + 0, + 7017, + 7020, + 7122, + 7120, + 0, + 7020, + 7022, + 7124, + 7122, + 0, + 7022, + 7024, + 7127, + 7124, + 0, + 7024, + 7025, + 7128, + 7127, + 0, + 7025, + 7023, + 7126, + 7128, + 0, + 7023, + 7021, + 7123, + 7126, + 0, + 7021, + 7018, + 7121, + 7123, + 0, + 7018, + 7015, + 7118, + 7121, + 0, + 7015, + 7013, + 7114, + 7118, + 0, + 7013, + 7010, + 7111, + 7114, + 0, + 7010, + 7000, + 7100, + 7111, + 0, + 7000, + 6994, + 7094, + 7100, + 0, + 6994, + 6987, + 7084, + 7094, + 0, + 6987, + 6966, + 7055, + 7084, + 0, + 6966, + 6964, + 7052, + 7055, + 0, + 6964, + 6961, + 7047, + 7052, + 0, + 6961, + 6959, + 7044, + 7047, + 0, + 6959, + 6958, + 7043, + 7044, + 0, + 6958, + 6956, + 7039, + 7043, + 0, + 6956, + 6947, + 7036, + 7039, + 0, + 6947, + 6940, + 7034, + 7036, + 0, + 6940, + 6925, + 7032, + 7034, + 0, + 6925, + 6916, + 7030, + 7032, + 0, + 6916, + 6911, + 7028, + 7030, + 0, + 6911, + 6906, + 7026, + 7028, + 0, + 6906, + 6904, + 7016, + 7026, + 0, + 6904, + 6897, + 7008, + 7016, + 0, + 6897, + 6886, + 6996, + 7008, + 0, + 6886, + 6874, + 6988, + 6996, + 0, + 6874, + 6864, + 6982, + 6988, + 0, + 6864, + 6854, + 6976, + 6982, + 0, + 6854, + 6846, + 6974, + 6976, + 0, + 6846, + 6842, + 6972, + 6974, + 0, + 6842, + 6828, + 6965, + 6972, + 0, + 6828, + 6833, + 6967, + 6965, + 0, + 6833, + 6835, + 6968, + 6967, + 0, + 6835, + 6847, + 6975, + 6968, + 0, + 6847, + 6855, + 6977, + 6975, + 0, + 6855, + 6863, + 6981, + 6977, + 0, + 6863, + 6872, + 6986, + 6981, + 0, + 6872, + 6887, + 6995, + 6986, + 0, + 6887, + 6902, + 7011, + 6995, + 0, + 6902, + 6905, + 7019, + 7011, + 0, + 6905, + 6907, + 7027, + 7019, + 0, + 6907, + 6912, + 7029, + 7027, + 0, + 6912, + 6920, + 7031, + 7029, + 0, + 6920, + 6929, + 7033, + 7031, + 0, + 6929, + 6943, + 7035, + 7033, + 0, + 6943, + 6955, + 7038, + 7035, + 0, + 6955, + 6957, + 7042, + 7038, + 0, + 6957, + 6960, + 7045, + 7042, + 0, + 6960, + 6962, + 7048, + 7045, + 0, + 6962, + 6963, + 7050, + 7048, + 0, + 6963, + 6971, + 7063, + 7050, + 0, + 6971, + 6980, + 7075, + 7063, + 0, + 6980, + 6984, + 7080, + 7075, + 0, + 6984, + 6990, + 7086, + 7080, + 0, + 6990, + 6993, + 7091, + 7086, + 0, + 6993, + 6999, + 7097, + 7091, + 0, + 6999, + 7002, + 7101, + 7097, + 0, + 7002, + 7004, + 7106, + 7101, + 0, + 7004, + 7007, + 7109, + 7106, + 0, + 7007, + 7009, + 7110, + 7109, + 0, + 7009, + 7006, + 7108, + 7110, + 0, + 7006, + 7003, + 7104, + 7108, + 0, + 7003, + 7001, + 7099, + 7104, + 0, + 7001, + 6998, + 7096, + 7099, + 0, + 6998, + 6992, + 7089, + 7096, + 0, + 6992, + 6989, + 7085, + 7089, + 0, + 6989, + 6983, + 7078, + 7085, + 0, + 6983, + 6979, + 7074, + 7078, + 0, + 6979, + 6978, + 7072, + 7074, + 0, + 6978, + 6970, + 7060, + 7072, + 0, + 6970, + 6969, + 7058, + 7060, + 0, + 7058, + 7064, + 7163, + 7158, + 0, + 7064, + 7079, + 7175, + 7163, + 0, + 7079, + 7088, + 7183, + 7175, + 0, + 7088, + 7095, + 7190, + 7183, + 0, + 7095, + 7105, + 7197, + 7190, + 0, + 7105, + 7112, + 7203, + 7197, + 0, + 7112, + 7116, + 7207, + 7203, + 0, + 7116, + 7120, + 7209, + 7207, + 0, + 7120, + 7122, + 7213, + 7209, + 0, + 7122, + 7124, + 7215, + 7213, + 0, + 7124, + 7127, + 7218, + 7215, + 0, + 7127, + 7128, + 7219, + 7218, + 0, + 7128, + 7126, + 7217, + 7219, + 0, + 7126, + 7123, + 7214, + 7217, + 0, + 7123, + 7121, + 7211, + 7214, + 0, + 7121, + 7118, + 7208, + 7211, + 0, + 7118, + 7114, + 7205, + 7208, + 0, + 7114, + 7111, + 7202, + 7205, + 0, + 7111, + 7100, + 7194, + 7202, + 0, + 7100, + 7094, + 7187, + 7194, + 0, + 7094, + 7084, + 7179, + 7187, + 0, + 7084, + 7055, + 7154, + 7179, + 0, + 7055, + 7052, + 7152, + 7154, + 0, + 7052, + 7047, + 7147, + 7152, + 0, + 7047, + 7044, + 7143, + 7147, + 0, + 7044, + 7043, + 7140, + 7143, + 0, + 7043, + 7039, + 7136, + 7140, + 0, + 7039, + 7036, + 7132, + 7136, + 0, + 7036, + 7034, + 7125, + 7132, + 0, + 7034, + 7032, + 7113, + 7125, + 0, + 7032, + 7030, + 7098, + 7113, + 0, + 7030, + 7028, + 7087, + 7098, + 0, + 7028, + 7026, + 7077, + 7087, + 0, + 7026, + 7016, + 7071, + 7077, + 0, + 7016, + 7008, + 7069, + 7071, + 0, + 7008, + 6996, + 7066, + 7069, + 0, + 6996, + 6988, + 7061, + 7066, + 0, + 6988, + 6982, + 7057, + 7061, + 0, + 6982, + 6976, + 7053, + 7057, + 0, + 6976, + 6974, + 7049, + 7053, + 0, + 6974, + 6972, + 7046, + 7049, + 0, + 6972, + 6965, + 7037, + 7046, + 0, + 6965, + 6967, + 7040, + 7037, + 0, + 6967, + 6968, + 7041, + 7040, + 0, + 6968, + 6975, + 7051, + 7041, + 0, + 6975, + 6977, + 7054, + 7051, + 0, + 6977, + 6981, + 7056, + 7054, + 0, + 6981, + 6986, + 7059, + 7056, + 0, + 6986, + 6995, + 7065, + 7059, + 0, + 6995, + 7011, + 7070, + 7065, + 0, + 7011, + 7019, + 7073, + 7070, + 0, + 7019, + 7027, + 7082, + 7073, + 0, + 7027, + 7029, + 7090, + 7082, + 0, + 7029, + 7031, + 7102, + 7090, + 0, + 7031, + 7033, + 7119, + 7102, + 0, + 7033, + 7035, + 7131, + 7119, + 0, + 7035, + 7038, + 7135, + 7131, + 0, + 7038, + 7042, + 7139, + 7135, + 0, + 7042, + 7045, + 7144, + 7139, + 0, + 7045, + 7048, + 7148, + 7144, + 0, + 7048, + 7050, + 7150, + 7148, + 0, + 7050, + 7063, + 7161, + 7150, + 0, + 7063, + 7075, + 7171, + 7161, + 0, + 7075, + 7080, + 7176, + 7171, + 0, + 7080, + 7086, + 7182, + 7176, + 0, + 7086, + 7091, + 7186, + 7182, + 0, + 7091, + 7097, + 7192, + 7186, + 0, + 7097, + 7101, + 7195, + 7192, + 0, + 7101, + 7106, + 7198, + 7195, + 0, + 7106, + 7109, + 7200, + 7198, + 0, + 7109, + 7110, + 7201, + 7200, + 0, + 7110, + 7108, + 7199, + 7201, + 0, + 7108, + 7104, + 7196, + 7199, + 0, + 7104, + 7099, + 7193, + 7196, + 0, + 7099, + 7096, + 7191, + 7193, + 0, + 7096, + 7089, + 7184, + 7191, + 0, + 7089, + 7085, + 7181, + 7184, + 0, + 7085, + 7078, + 7174, + 7181, + 0, + 7078, + 7074, + 7170, + 7174, + 0, + 7074, + 7072, + 7169, + 7170, + 0, + 7072, + 7060, + 7159, + 7169, + 0, + 7060, + 7058, + 7158, + 7159, + 0, + 7158, + 7163, + 7216, + 7204, + 0, + 7163, + 7175, + 7231, + 7216, + 0, + 7175, + 7183, + 7237, + 7231, + 0, + 7183, + 7190, + 7243, + 7237, + 0, + 7190, + 7197, + 7251, + 7243, + 0, + 7197, + 7203, + 7258, + 7251, + 0, + 7203, + 7207, + 7261, + 7258, + 0, + 7207, + 7209, + 7264, + 7261, + 0, + 7209, + 7213, + 7266, + 7264, + 0, + 7213, + 7215, + 7268, + 7266, + 0, + 7215, + 7218, + 7271, + 7268, + 0, + 7218, + 7219, + 7272, + 7271, + 0, + 7219, + 7217, + 7270, + 7272, + 0, + 7217, + 7214, + 7267, + 7270, + 0, + 7214, + 7211, + 7265, + 7267, + 0, + 7211, + 7208, + 7263, + 7265, + 0, + 7208, + 7205, + 7260, + 7263, + 0, + 7205, + 7202, + 7257, + 7260, + 0, + 7202, + 7194, + 7248, + 7257, + 0, + 7194, + 7187, + 7242, + 7248, + 0, + 7187, + 7179, + 7234, + 7242, + 0, + 7179, + 7154, + 7189, + 7234, + 0, + 7154, + 7152, + 7180, + 7189, + 0, + 7152, + 7147, + 7172, + 7180, + 0, + 7147, + 7143, + 7168, + 7172, + 0, + 7143, + 7140, + 7166, + 7168, + 0, + 7140, + 7136, + 7164, + 7166, + 0, + 7136, + 7132, + 7160, + 7164, + 0, + 7132, + 7125, + 7156, + 7160, + 0, + 7125, + 7113, + 7153, + 7156, + 0, + 7113, + 7098, + 7149, + 7153, + 0, + 7098, + 7087, + 7145, + 7149, + 0, + 7087, + 7077, + 7141, + 7145, + 0, + 7077, + 7071, + 7137, + 7141, + 0, + 7071, + 7069, + 7133, + 7137, + 0, + 7069, + 7066, + 7130, + 7133, + 0, + 7066, + 7061, + 7117, + 7130, + 0, + 7061, + 7057, + 7107, + 7117, + 0, + 7057, + 7053, + 7092, + 7107, + 0, + 7053, + 7049, + 7081, + 7092, + 0, + 7049, + 7046, + 7076, + 7081, + 0, + 7046, + 7037, + 7062, + 7076, + 0, + 7037, + 7040, + 7067, + 7062, + 0, + 7040, + 7041, + 7068, + 7067, + 0, + 7041, + 7051, + 7083, + 7068, + 0, + 7051, + 7054, + 7093, + 7083, + 0, + 7054, + 7056, + 7103, + 7093, + 0, + 7056, + 7059, + 7115, + 7103, + 0, + 7059, + 7065, + 7129, + 7115, + 0, + 7065, + 7070, + 7134, + 7129, + 0, + 7070, + 7073, + 7138, + 7134, + 0, + 7073, + 7082, + 7142, + 7138, + 0, + 7082, + 7090, + 7146, + 7142, + 0, + 7090, + 7102, + 7151, + 7146, + 0, + 7102, + 7119, + 7155, + 7151, + 0, + 7119, + 7131, + 7157, + 7155, + 0, + 7131, + 7135, + 7162, + 7157, + 0, + 7135, + 7139, + 7165, + 7162, + 0, + 7139, + 7144, + 7167, + 7165, + 0, + 7144, + 7148, + 7173, + 7167, + 0, + 7148, + 7150, + 7178, + 7173, + 0, + 7150, + 7161, + 7212, + 7178, + 0, + 7161, + 7171, + 7228, + 7212, + 0, + 7171, + 7176, + 7233, + 7228, + 0, + 7176, + 7182, + 7236, + 7233, + 0, + 7182, + 7186, + 7241, + 7236, + 0, + 7186, + 7192, + 7245, + 7241, + 0, + 7192, + 7195, + 7250, + 7245, + 0, + 7195, + 7198, + 7253, + 7250, + 0, + 7198, + 7200, + 7255, + 7253, + 0, + 7200, + 7201, + 7256, + 7255, + 0, + 7201, + 7199, + 7254, + 7256, + 0, + 7199, + 7196, + 7252, + 7254, + 0, + 7196, + 7193, + 7247, + 7252, + 0, + 7193, + 7191, + 7244, + 7247, + 0, + 7191, + 7184, + 7240, + 7244, + 0, + 7184, + 7181, + 7235, + 7240, + 0, + 7181, + 7174, + 7230, + 7235, + 0, + 7174, + 7170, + 7227, + 7230, + 0, + 7170, + 7169, + 7224, + 7227, + 0, + 7169, + 7159, + 7206, + 7224, + 0, + 7159, + 7158, + 7204, + 7206, + 0, + 7204, + 7216, + 7297, + 7294, + 0, + 7216, + 7231, + 7308, + 7297, + 0, + 7231, + 7237, + 7314, + 7308, + 0, + 7237, + 7243, + 7320, + 7314, + 0, + 7243, + 7251, + 7328, + 7320, + 0, + 7251, + 7258, + 7338, + 7328, + 0, + 7258, + 7261, + 7340, + 7338, + 0, + 7261, + 7264, + 7345, + 7340, + 0, + 7264, + 7266, + 7348, + 7345, + 0, + 7266, + 7268, + 7350, + 7348, + 0, + 7268, + 7271, + 7352, + 7350, + 0, + 7271, + 7272, + 7354, + 7352, + 0, + 7272, + 7270, + 7351, + 7354, + 0, + 7270, + 7267, + 7349, + 7351, + 0, + 7267, + 7265, + 7346, + 7349, + 0, + 7265, + 7263, + 7343, + 7346, + 0, + 7263, + 7260, + 7339, + 7343, + 0, + 7260, + 7257, + 7337, + 7339, + 0, + 7257, + 7248, + 7326, + 7337, + 0, + 7248, + 7242, + 7318, + 7326, + 0, + 7242, + 7234, + 7311, + 7318, + 0, + 7234, + 7189, + 7293, + 7311, + 0, + 7189, + 7180, + 7292, + 7293, + 0, + 7180, + 7172, + 7289, + 7292, + 0, + 7172, + 7168, + 7288, + 7289, + 0, + 7168, + 7166, + 7286, + 7288, + 0, + 7166, + 7164, + 7284, + 7286, + 0, + 7164, + 7160, + 7282, + 7284, + 0, + 7160, + 7156, + 7280, + 7282, + 0, + 7156, + 7153, + 7278, + 7280, + 0, + 7153, + 7149, + 7276, + 7278, + 0, + 7149, + 7145, + 7274, + 7276, + 0, + 7145, + 7141, + 7269, + 7274, + 0, + 7141, + 7137, + 7259, + 7269, + 0, + 7137, + 7133, + 7246, + 7259, + 0, + 7133, + 7130, + 7239, + 7246, + 0, + 7130, + 7117, + 7232, + 7239, + 0, + 7117, + 7107, + 7226, + 7232, + 0, + 7107, + 7092, + 7223, + 7226, + 0, + 7092, + 7081, + 7220, + 7223, + 0, + 7081, + 7076, + 7210, + 7220, + 0, + 7076, + 7062, + 7177, + 7210, + 0, + 7062, + 7067, + 7185, + 7177, + 0, + 7067, + 7068, + 7188, + 7185, + 0, + 7068, + 7083, + 7221, + 7188, + 0, + 7083, + 7093, + 7222, + 7221, + 0, + 7093, + 7103, + 7225, + 7222, + 0, + 7103, + 7115, + 7229, + 7225, + 0, + 7115, + 7129, + 7238, + 7229, + 0, + 7129, + 7134, + 7249, + 7238, + 0, + 7134, + 7138, + 7262, + 7249, + 0, + 7138, + 7142, + 7273, + 7262, + 0, + 7142, + 7146, + 7275, + 7273, + 0, + 7146, + 7151, + 7277, + 7275, + 0, + 7151, + 7155, + 7279, + 7277, + 0, + 7155, + 7157, + 7281, + 7279, + 0, + 7157, + 7162, + 7283, + 7281, + 0, + 7162, + 7165, + 7285, + 7283, + 0, + 7165, + 7167, + 7287, + 7285, + 0, + 7167, + 7173, + 7290, + 7287, + 0, + 7173, + 7178, + 7291, + 7290, + 0, + 7178, + 7212, + 7296, + 7291, + 0, + 7212, + 7228, + 7306, + 7296, + 0, + 7228, + 7233, + 7309, + 7306, + 0, + 7233, + 7236, + 7313, + 7309, + 0, + 7236, + 7241, + 7317, + 7313, + 0, + 7241, + 7245, + 7323, + 7317, + 0, + 7245, + 7250, + 7325, + 7323, + 0, + 7250, + 7253, + 7330, + 7325, + 0, + 7253, + 7255, + 7333, + 7330, + 0, + 7255, + 7256, + 7334, + 7333, + 0, + 7256, + 7254, + 7332, + 7334, + 0, + 7254, + 7252, + 7329, + 7332, + 0, + 7252, + 7247, + 7324, + 7329, + 0, + 7247, + 7244, + 7321, + 7324, + 0, + 7244, + 7240, + 7315, + 7321, + 0, + 7240, + 7235, + 7310, + 7315, + 0, + 7235, + 7230, + 7307, + 7310, + 0, + 7230, + 7227, + 7305, + 7307, + 0, + 7227, + 7224, + 7302, + 7305, + 0, + 7224, + 7206, + 7295, + 7302, + 0, + 7206, + 7204, + 7294, + 7295, + 0, + 7294, + 7297, + 7425, + 7419, + 0, + 7297, + 7308, + 7442, + 7425, + 0, + 7308, + 7314, + 7453, + 7442, + 0, + 7314, + 7320, + 7462, + 7453, + 0, + 7320, + 7328, + 7474, + 7462, + 0, + 7328, + 7338, + 7485, + 7474, + 0, + 7338, + 7340, + 7495, + 7485, + 0, + 7340, + 7345, + 7499, + 7495, + 0, + 7345, + 7348, + 7504, + 7499, + 0, + 7348, + 7350, + 7506, + 7504, + 0, + 7350, + 7352, + 7510, + 7506, + 0, + 7352, + 7354, + 7511, + 7510, + 0, + 7354, + 7351, + 7509, + 7511, + 0, + 7351, + 7349, + 7505, + 7509, + 0, + 7349, + 7346, + 7502, + 7505, + 0, + 7346, + 7343, + 7498, + 7502, + 0, + 7343, + 7339, + 7492, + 7498, + 0, + 7339, + 7337, + 7482, + 7492, + 0, + 7337, + 7326, + 7471, + 7482, + 0, + 7326, + 7318, + 7460, + 7471, + 0, + 7318, + 7311, + 7450, + 7460, + 0, + 7311, + 7293, + 7417, + 7450, + 0, + 7293, + 7292, + 7413, + 7417, + 0, + 7292, + 7289, + 7407, + 7413, + 0, + 7289, + 7288, + 7403, + 7407, + 0, + 7288, + 7286, + 7399, + 7403, + 0, + 7286, + 7284, + 7395, + 7399, + 0, + 7284, + 7282, + 7391, + 7395, + 0, + 7282, + 7280, + 7388, + 7391, + 0, + 7280, + 7278, + 7384, + 7388, + 0, + 7278, + 7276, + 7380, + 7384, + 0, + 7276, + 7274, + 7375, + 7380, + 0, + 7274, + 7269, + 7372, + 7375, + 0, + 7269, + 7259, + 7368, + 7372, + 0, + 7259, + 7246, + 7364, + 7368, + 0, + 7246, + 7239, + 7361, + 7364, + 0, + 7239, + 7232, + 7357, + 7361, + 0, + 7232, + 7226, + 7347, + 7357, + 0, + 7226, + 7223, + 7336, + 7347, + 0, + 7223, + 7220, + 7319, + 7336, + 0, + 7220, + 7210, + 7312, + 7319, + 0, + 7210, + 7177, + 7298, + 7312, + 0, + 7177, + 7185, + 7300, + 7298, + 0, + 7185, + 7188, + 7301, + 7300, + 0, + 7188, + 7221, + 7322, + 7301, + 0, + 7221, + 7222, + 7335, + 7322, + 0, + 7222, + 7225, + 7344, + 7335, + 0, + 7225, + 7229, + 7356, + 7344, + 0, + 7229, + 7238, + 7360, + 7356, + 0, + 7238, + 7249, + 7365, + 7360, + 0, + 7249, + 7262, + 7369, + 7365, + 0, + 7262, + 7273, + 7373, + 7369, + 0, + 7273, + 7275, + 7377, + 7373, + 0, + 7275, + 7277, + 7381, + 7377, + 0, + 7277, + 7279, + 7385, + 7381, + 0, + 7279, + 7281, + 7389, + 7385, + 0, + 7281, + 7283, + 7394, + 7389, + 0, + 7283, + 7285, + 7398, + 7394, + 0, + 7285, + 7287, + 7402, + 7398, + 0, + 7287, + 7290, + 7408, + 7402, + 0, + 7290, + 7291, + 7411, + 7408, + 0, + 7291, + 7296, + 7424, + 7411, + 0, + 7296, + 7306, + 7438, + 7424, + 0, + 7306, + 7309, + 7444, + 7438, + 0, + 7309, + 7313, + 7452, + 7444, + 0, + 7313, + 7317, + 7457, + 7452, + 0, + 7317, + 7323, + 7466, + 7457, + 0, + 7323, + 7325, + 7470, + 7466, + 0, + 7325, + 7330, + 7476, + 7470, + 0, + 7330, + 7333, + 7479, + 7476, + 0, + 7333, + 7334, + 7480, + 7479, + 0, + 7334, + 7332, + 7478, + 7480, + 0, + 7332, + 7329, + 7475, + 7478, + 0, + 7329, + 7324, + 7468, + 7475, + 0, + 7324, + 7321, + 7464, + 7468, + 0, + 7321, + 7315, + 7454, + 7464, + 0, + 7315, + 7310, + 7449, + 7454, + 0, + 7310, + 7307, + 7441, + 7449, + 0, + 7307, + 7305, + 7435, + 7441, + 0, + 7305, + 7302, + 7434, + 7435, + 0, + 7302, + 7295, + 7421, + 7434, + 0, + 7295, + 7294, + 7419, + 7421, + 0, + 7419, + 7425, + 7429, + 7422, + 0, + 7425, + 7442, + 7448, + 7429, + 0, + 7442, + 7453, + 7459, + 7448, + 0, + 7453, + 7462, + 7472, + 7459, + 0, + 7462, + 7474, + 7488, + 7472, + 0, + 7474, + 7485, + 7497, + 7488, + 0, + 7485, + 7495, + 7503, + 7497, + 0, + 7495, + 7499, + 7512, + 7503, + 0, + 7499, + 7504, + 7514, + 7512, + 0, + 7504, + 7506, + 7516, + 7514, + 0, + 7506, + 7510, + 7519, + 7516, + 0, + 7510, + 7511, + 7520, + 7519, + 0, + 7511, + 7509, + 7518, + 7520, + 0, + 7509, + 7505, + 7515, + 7518, + 0, + 7505, + 7502, + 7513, + 7515, + 0, + 7502, + 7498, + 7507, + 7513, + 0, + 7498, + 7492, + 7501, + 7507, + 0, + 7492, + 7482, + 7496, + 7501, + 0, + 7482, + 7471, + 7486, + 7496, + 0, + 7471, + 7460, + 7469, + 7486, + 0, + 7460, + 7450, + 7456, + 7469, + 0, + 7450, + 7417, + 7418, + 7456, + 0, + 7417, + 7413, + 7416, + 7418, + 0, + 7413, + 7407, + 7409, + 7416, + 0, + 7407, + 7403, + 7405, + 7409, + 0, + 7403, + 7399, + 7401, + 7405, + 0, + 7399, + 7395, + 7397, + 7401, + 0, + 7395, + 7391, + 7393, + 7397, + 0, + 7391, + 7388, + 7390, + 7393, + 0, + 7388, + 7384, + 7386, + 7390, + 0, + 7384, + 7380, + 7382, + 7386, + 0, + 7380, + 7375, + 7378, + 7382, + 0, + 7375, + 7372, + 7374, + 7378, + 0, + 7372, + 7368, + 7370, + 7374, + 0, + 7368, + 7364, + 7366, + 7370, + 0, + 7364, + 7361, + 7363, + 7366, + 0, + 7361, + 7357, + 7359, + 7363, + 0, + 7357, + 7347, + 7355, + 7359, + 0, + 7347, + 7336, + 7342, + 7355, + 0, + 7336, + 7319, + 7327, + 7342, + 0, + 7319, + 7312, + 7316, + 7327, + 0, + 7312, + 7298, + 7299, + 7316, + 0, + 7298, + 7300, + 7303, + 7299, + 0, + 7300, + 7301, + 7304, + 7303, + 0, + 7301, + 7322, + 7331, + 7304, + 0, + 7322, + 7335, + 7341, + 7331, + 0, + 7335, + 7344, + 7353, + 7341, + 0, + 7344, + 7356, + 7358, + 7353, + 0, + 7356, + 7360, + 7362, + 7358, + 0, + 7360, + 7365, + 7367, + 7362, + 0, + 7365, + 7369, + 7371, + 7367, + 0, + 7369, + 7373, + 7376, + 7371, + 0, + 7373, + 7377, + 7379, + 7376, + 0, + 7377, + 7381, + 7383, + 7379, + 0, + 7381, + 7385, + 7387, + 7383, + 0, + 7385, + 7389, + 7392, + 7387, + 0, + 7389, + 7394, + 7396, + 7392, + 0, + 7394, + 7398, + 7400, + 7396, + 0, + 7398, + 7402, + 7404, + 7400, + 0, + 7402, + 7408, + 7410, + 7404, + 0, + 7408, + 7411, + 7415, + 7410, + 0, + 7411, + 7424, + 7428, + 7415, + 0, + 7424, + 7438, + 7443, + 7428, + 0, + 7438, + 7444, + 7451, + 7443, + 0, + 7444, + 7452, + 7458, + 7451, + 0, + 7452, + 7457, + 7467, + 7458, + 0, + 7457, + 7466, + 7477, + 7467, + 0, + 7466, + 7470, + 7484, + 7477, + 0, + 7470, + 7476, + 7490, + 7484, + 0, + 7476, + 7479, + 7493, + 7490, + 0, + 7479, + 7480, + 7494, + 7493, + 0, + 7480, + 7478, + 7491, + 7494, + 0, + 7478, + 7475, + 7489, + 7491, + 0, + 7475, + 7468, + 7483, + 7489, + 0, + 7468, + 7464, + 7473, + 7483, + 0, + 7464, + 7454, + 7465, + 7473, + 0, + 7454, + 7449, + 7455, + 7465, + 0, + 7449, + 7441, + 7447, + 7455, + 0, + 7441, + 7435, + 7440, + 7447, + 0, + 7435, + 7434, + 7437, + 7440, + 0, + 7434, + 7421, + 7423, + 7437, + 0, + 7421, + 7419, + 7422, + 7423, + 0, + 7422, + 7429, + 7543, + 7540, + 0, + 7429, + 7448, + 7551, + 7543, + 0, + 7448, + 7459, + 7555, + 7551, + 0, + 7459, + 7472, + 7560, + 7555, + 0, + 7472, + 7488, + 7567, + 7560, + 0, + 7488, + 7497, + 7574, + 7567, + 0, + 7497, + 7503, + 7578, + 7574, + 0, + 7503, + 7512, + 7580, + 7578, + 0, + 7512, + 7514, + 7582, + 7580, + 0, + 7514, + 7516, + 7586, + 7582, + 0, + 7516, + 7519, + 7588, + 7586, + 0, + 7519, + 7520, + 7589, + 7588, + 0, + 7520, + 7518, + 7587, + 7589, + 0, + 7518, + 7515, + 7585, + 7587, + 0, + 7515, + 7513, + 7581, + 7585, + 0, + 7513, + 7507, + 7579, + 7581, + 0, + 7507, + 7501, + 7577, + 7579, + 0, + 7501, + 7496, + 7573, + 7577, + 0, + 7496, + 7486, + 7566, + 7573, + 0, + 7486, + 7469, + 7559, + 7566, + 0, + 7469, + 7456, + 7554, + 7559, + 0, + 7456, + 7418, + 7539, + 7554, + 0, + 7418, + 7416, + 7538, + 7539, + 0, + 7416, + 7409, + 7535, + 7538, + 0, + 7409, + 7405, + 7534, + 7535, + 0, + 7405, + 7401, + 7532, + 7534, + 0, + 7401, + 7397, + 7530, + 7532, + 0, + 7397, + 7393, + 7528, + 7530, + 0, + 7393, + 7390, + 7526, + 7528, + 0, + 7390, + 7386, + 7524, + 7526, + 0, + 7386, + 7382, + 7522, + 7524, + 0, + 7382, + 7378, + 7517, + 7522, + 0, + 7378, + 7374, + 7500, + 7517, + 0, + 7374, + 7370, + 7481, + 7500, + 0, + 7370, + 7366, + 7461, + 7481, + 0, + 7366, + 7363, + 7446, + 7461, + 0, + 7363, + 7359, + 7439, + 7446, + 0, + 7359, + 7355, + 7433, + 7439, + 0, + 7355, + 7342, + 7431, + 7433, + 0, + 7342, + 7327, + 7426, + 7431, + 0, + 7327, + 7316, + 7420, + 7426, + 0, + 7316, + 7299, + 7406, + 7420, + 0, + 7299, + 7303, + 7412, + 7406, + 0, + 7303, + 7304, + 7414, + 7412, + 0, + 7304, + 7331, + 7427, + 7414, + 0, + 7331, + 7341, + 7430, + 7427, + 0, + 7341, + 7353, + 7432, + 7430, + 0, + 7353, + 7358, + 7436, + 7432, + 0, + 7358, + 7362, + 7445, + 7436, + 0, + 7362, + 7367, + 7463, + 7445, + 0, + 7367, + 7371, + 7487, + 7463, + 0, + 7371, + 7376, + 7508, + 7487, + 0, + 7376, + 7379, + 7521, + 7508, + 0, + 7379, + 7383, + 7523, + 7521, + 0, + 7383, + 7387, + 7525, + 7523, + 0, + 7387, + 7392, + 7527, + 7525, + 0, + 7392, + 7396, + 7529, + 7527, + 0, + 7396, + 7400, + 7531, + 7529, + 0, + 7400, + 7404, + 7533, + 7531, + 0, + 7404, + 7410, + 7536, + 7533, + 0, + 7410, + 7415, + 7537, + 7536, + 0, + 7415, + 7428, + 7542, + 7537, + 0, + 7428, + 7443, + 7547, + 7542, + 0, + 7443, + 7451, + 7552, + 7547, + 0, + 7451, + 7458, + 7556, + 7552, + 0, + 7458, + 7467, + 7558, + 7556, + 0, + 7467, + 7477, + 7562, + 7558, + 0, + 7477, + 7484, + 7565, + 7562, + 0, + 7484, + 7490, + 7569, + 7565, + 0, + 7490, + 7493, + 7571, + 7569, + 0, + 7493, + 7494, + 7572, + 7571, + 0, + 7494, + 7491, + 7570, + 7572, + 0, + 7491, + 7489, + 7568, + 7570, + 0, + 7489, + 7483, + 7564, + 7568, + 0, + 7483, + 7473, + 7561, + 7564, + 0, + 7473, + 7465, + 7557, + 7561, + 0, + 7465, + 7455, + 7553, + 7557, + 0, + 7455, + 7447, + 7550, + 7553, + 0, + 7447, + 7440, + 7546, + 7550, + 0, + 7440, + 7437, + 7545, + 7546, + 0, + 7437, + 7423, + 7541, + 7545, + 0, + 7423, + 7422, + 7540, + 7541, + 0, + 7540, + 7543, + 7656, + 7650, + 0, + 7543, + 7551, + 7675, + 7656, + 0, + 7551, + 7555, + 7683, + 7675, + 0, + 7555, + 7560, + 7692, + 7683, + 0, + 7560, + 7567, + 7700, + 7692, + 0, + 7567, + 7574, + 7709, + 7700, + 0, + 7574, + 7578, + 7712, + 7709, + 0, + 7578, + 7580, + 7715, + 7712, + 0, + 7580, + 7582, + 7718, + 7715, + 0, + 7582, + 7586, + 7720, + 7718, + 0, + 7586, + 7588, + 7722, + 7720, + 0, + 7588, + 7589, + 7724, + 7722, + 0, + 7589, + 7587, + 7721, + 7724, + 0, + 7587, + 7585, + 7719, + 7721, + 0, + 7585, + 7581, + 7717, + 7719, + 0, + 7581, + 7579, + 7714, + 7717, + 0, + 7579, + 7577, + 7711, + 7714, + 0, + 7577, + 7573, + 7708, + 7711, + 0, + 7573, + 7566, + 7699, + 7708, + 0, + 7566, + 7559, + 7691, + 7699, + 0, + 7559, + 7554, + 7682, + 7691, + 0, + 7554, + 7539, + 7646, + 7682, + 0, + 7539, + 7538, + 7643, + 7646, + 0, + 7538, + 7535, + 7636, + 7643, + 0, + 7535, + 7534, + 7633, + 7636, + 0, + 7534, + 7532, + 7630, + 7633, + 0, + 7532, + 7530, + 7626, + 7630, + 0, + 7530, + 7528, + 7622, + 7626, + 0, + 7528, + 7526, + 7618, + 7622, + 0, + 7526, + 7524, + 7614, + 7618, + 0, + 7524, + 7522, + 7610, + 7614, + 0, + 7522, + 7517, + 7606, + 7610, + 0, + 7517, + 7500, + 7603, + 7606, + 0, + 7500, + 7481, + 7601, + 7603, + 0, + 7481, + 7461, + 7597, + 7601, + 0, + 7461, + 7446, + 7595, + 7597, + 0, + 7446, + 7439, + 7593, + 7595, + 0, + 7439, + 7433, + 7591, + 7593, + 0, + 7433, + 7431, + 7584, + 7591, + 0, + 7431, + 7426, + 7575, + 7584, + 0, + 7426, + 7420, + 7563, + 7575, + 0, + 7420, + 7406, + 7544, + 7563, + 0, + 7406, + 7412, + 7548, + 7544, + 0, + 7412, + 7414, + 7549, + 7548, + 0, + 7414, + 7427, + 7576, + 7549, + 0, + 7427, + 7430, + 7583, + 7576, + 0, + 7430, + 7432, + 7590, + 7583, + 0, + 7432, + 7436, + 7592, + 7590, + 0, + 7436, + 7445, + 7594, + 7592, + 0, + 7445, + 7463, + 7598, + 7594, + 0, + 7463, + 7487, + 7602, + 7598, + 0, + 7487, + 7508, + 7604, + 7602, + 0, + 7508, + 7521, + 7607, + 7604, + 0, + 7521, + 7523, + 7611, + 7607, + 0, + 7523, + 7525, + 7615, + 7611, + 0, + 7525, + 7527, + 7620, + 7615, + 0, + 7527, + 7529, + 7625, + 7620, + 0, + 7529, + 7531, + 7629, + 7625, + 0, + 7531, + 7533, + 7632, + 7629, + 0, + 7533, + 7536, + 7638, + 7632, + 0, + 7536, + 7537, + 7642, + 7638, + 0, + 7537, + 7542, + 7657, + 7642, + 0, + 7542, + 7547, + 7673, + 7657, + 0, + 7547, + 7552, + 7678, + 7673, + 0, + 7552, + 7556, + 7684, + 7678, + 0, + 7556, + 7558, + 7690, + 7684, + 0, + 7558, + 7562, + 7694, + 7690, + 0, + 7562, + 7565, + 7698, + 7694, + 0, + 7565, + 7569, + 7704, + 7698, + 0, + 7569, + 7571, + 7706, + 7704, + 0, + 7571, + 7572, + 7707, + 7706, + 0, + 7572, + 7570, + 7705, + 7707, + 0, + 7570, + 7568, + 7703, + 7705, + 0, + 7568, + 7564, + 7696, + 7703, + 0, + 7564, + 7561, + 7693, + 7696, + 0, + 7561, + 7557, + 7687, + 7693, + 0, + 7557, + 7553, + 7681, + 7687, + 0, + 7553, + 7550, + 7674, + 7681, + 0, + 7550, + 7546, + 7670, + 7674, + 0, + 7546, + 7545, + 7667, + 7670, + 0, + 7545, + 7541, + 7652, + 7667, + 0, + 7541, + 7540, + 7650, + 7652, + 0, + 7650, + 7656, + 7729, + 7725, + 0, + 7656, + 7675, + 7741, + 7729, + 0, + 7675, + 7683, + 7746, + 7741, + 0, + 7683, + 7692, + 7753, + 7746, + 0, + 7692, + 7700, + 7762, + 7753, + 0, + 7700, + 7709, + 7769, + 7762, + 0, + 7709, + 7712, + 7773, + 7769, + 0, + 7712, + 7715, + 7775, + 7773, + 0, + 7715, + 7718, + 7777, + 7775, + 0, + 7718, + 7720, + 7780, + 7777, + 0, + 7720, + 7722, + 7782, + 7780, + 0, + 7722, + 7724, + 7784, + 7782, + 0, + 7724, + 7721, + 7781, + 7784, + 0, + 7721, + 7719, + 7779, + 7781, + 0, + 7719, + 7717, + 7776, + 7779, + 0, + 7717, + 7714, + 7774, + 7776, + 0, + 7714, + 7711, + 7772, + 7774, + 0, + 7711, + 7708, + 7768, + 7772, + 0, + 7708, + 7699, + 7761, + 7768, + 0, + 7699, + 7691, + 7754, + 7761, + 0, + 7691, + 7682, + 7747, + 7754, + 0, + 7682, + 7646, + 7713, + 7747, + 0, + 7646, + 7643, + 7702, + 7713, + 0, + 7643, + 7636, + 7688, + 7702, + 0, + 7636, + 7633, + 7680, + 7688, + 0, + 7633, + 7630, + 7672, + 7680, + 0, + 7630, + 7626, + 7666, + 7672, + 0, + 7626, + 7622, + 7662, + 7666, + 0, + 7622, + 7618, + 7658, + 7662, + 0, + 7618, + 7614, + 7651, + 7658, + 0, + 7614, + 7610, + 7647, + 7651, + 0, + 7610, + 7606, + 7644, + 7647, + 0, + 7606, + 7603, + 7637, + 7644, + 0, + 7603, + 7601, + 7631, + 7637, + 0, + 7601, + 7597, + 7627, + 7631, + 0, + 7597, + 7595, + 7624, + 7627, + 0, + 7595, + 7593, + 7621, + 7624, + 0, + 7593, + 7591, + 7617, + 7621, + 0, + 7591, + 7584, + 7613, + 7617, + 0, + 7584, + 7575, + 7608, + 7613, + 0, + 7575, + 7563, + 7605, + 7608, + 0, + 7563, + 7544, + 7596, + 7605, + 0, + 7544, + 7548, + 7599, + 7596, + 0, + 7548, + 7549, + 7600, + 7599, + 0, + 7549, + 7576, + 7609, + 7600, + 0, + 7576, + 7583, + 7612, + 7609, + 0, + 7583, + 7590, + 7616, + 7612, + 0, + 7590, + 7592, + 7619, + 7616, + 0, + 7592, + 7594, + 7623, + 7619, + 0, + 7594, + 7598, + 7628, + 7623, + 0, + 7598, + 7602, + 7635, + 7628, + 0, + 7602, + 7604, + 7640, + 7635, + 0, + 7604, + 7607, + 7645, + 7640, + 0, + 7607, + 7611, + 7648, + 7645, + 0, + 7611, + 7615, + 7653, + 7648, + 0, + 7615, + 7620, + 7661, + 7653, + 0, + 7620, + 7625, + 7665, + 7661, + 0, + 7625, + 7629, + 7671, + 7665, + 0, + 7629, + 7632, + 7679, + 7671, + 0, + 7632, + 7638, + 7689, + 7679, + 0, + 7638, + 7642, + 7697, + 7689, + 0, + 7642, + 7657, + 7730, + 7697, + 0, + 7657, + 7673, + 7739, + 7730, + 0, + 7673, + 7678, + 7743, + 7739, + 0, + 7678, + 7684, + 7748, + 7743, + 0, + 7684, + 7690, + 7752, + 7748, + 0, + 7690, + 7694, + 7756, + 7752, + 0, + 7694, + 7698, + 7759, + 7756, + 0, + 7698, + 7704, + 7764, + 7759, + 0, + 7704, + 7706, + 7766, + 7764, + 0, + 7706, + 7707, + 7767, + 7766, + 0, + 7707, + 7705, + 7765, + 7767, + 0, + 7705, + 7703, + 7763, + 7765, + 0, + 7703, + 7696, + 7757, + 7763, + 0, + 7696, + 7693, + 7755, + 7757, + 0, + 7693, + 7687, + 7749, + 7755, + 0, + 7687, + 7681, + 7745, + 7749, + 0, + 7681, + 7674, + 7740, + 7745, + 0, + 7674, + 7670, + 7737, + 7740, + 0, + 7670, + 7667, + 7735, + 7737, + 0, + 7667, + 7652, + 7726, + 7735, + 0, + 7652, + 7650, + 7725, + 7726, + 0, + 7725, + 7729, + 7788, + 7786, + 0, + 7729, + 7741, + 7794, + 7788, + 0, + 7741, + 7746, + 7798, + 7794, + 0, + 7746, + 7753, + 7805, + 7798, + 0, + 7753, + 7762, + 7811, + 7805, + 0, + 7762, + 7769, + 7818, + 7811, + 0, + 7769, + 7773, + 7820, + 7818, + 0, + 7773, + 7775, + 7823, + 7820, + 0, + 7775, + 7777, + 7826, + 7823, + 0, + 7777, + 7780, + 7828, + 7826, + 0, + 7780, + 7782, + 7830, + 7828, + 0, + 7782, + 7784, + 7831, + 7830, + 0, + 7784, + 7781, + 7829, + 7831, + 0, + 7781, + 7779, + 7827, + 7829, + 0, + 7779, + 7776, + 7825, + 7827, + 0, + 7776, + 7774, + 7824, + 7825, + 0, + 7774, + 7772, + 7821, + 7824, + 0, + 7772, + 7768, + 7819, + 7821, + 0, + 7768, + 7761, + 7812, + 7819, + 0, + 7761, + 7754, + 7806, + 7812, + 0, + 7754, + 7747, + 7799, + 7806, + 0, + 7747, + 7713, + 7785, + 7799, + 0, + 7713, + 7702, + 7783, + 7785, + 0, + 7702, + 7688, + 7770, + 7783, + 0, + 7688, + 7680, + 7760, + 7770, + 0, + 7680, + 7672, + 7751, + 7760, + 0, + 7672, + 7666, + 7744, + 7751, + 0, + 7666, + 7662, + 7738, + 7744, + 0, + 7662, + 7658, + 7734, + 7738, + 0, + 7658, + 7651, + 7732, + 7734, + 0, + 7651, + 7647, + 7728, + 7732, + 0, + 7647, + 7644, + 7723, + 7728, + 0, + 7644, + 7637, + 7710, + 7723, + 0, + 7637, + 7631, + 7695, + 7710, + 0, + 7631, + 7627, + 7685, + 7695, + 0, + 7627, + 7624, + 7677, + 7685, + 0, + 7624, + 7621, + 7669, + 7677, + 0, + 7621, + 7617, + 7664, + 7669, + 0, + 7617, + 7613, + 7660, + 7664, + 0, + 7613, + 7608, + 7654, + 7660, + 0, + 7608, + 7605, + 7649, + 7654, + 0, + 7605, + 7596, + 7634, + 7649, + 0, + 7596, + 7599, + 7639, + 7634, + 0, + 7599, + 7600, + 7641, + 7639, + 0, + 7600, + 7609, + 7655, + 7641, + 0, + 7609, + 7612, + 7659, + 7655, + 0, + 7612, + 7616, + 7663, + 7659, + 0, + 7616, + 7619, + 7668, + 7663, + 0, + 7619, + 7623, + 7676, + 7668, + 0, + 7623, + 7628, + 7686, + 7676, + 0, + 7628, + 7635, + 7701, + 7686, + 0, + 7635, + 7640, + 7716, + 7701, + 0, + 7640, + 7645, + 7727, + 7716, + 0, + 7645, + 7648, + 7731, + 7727, + 0, + 7648, + 7653, + 7733, + 7731, + 0, + 7653, + 7661, + 7736, + 7733, + 0, + 7661, + 7665, + 7742, + 7736, + 0, + 7665, + 7671, + 7750, + 7742, + 0, + 7671, + 7679, + 7758, + 7750, + 0, + 7679, + 7689, + 7771, + 7758, + 0, + 7689, + 7697, + 7778, + 7771, + 0, + 7697, + 7730, + 7789, + 7778, + 0, + 7730, + 7739, + 7792, + 7789, + 0, + 7739, + 7743, + 7796, + 7792, + 0, + 7743, + 7748, + 7800, + 7796, + 0, + 7748, + 7752, + 7804, + 7800, + 0, + 7752, + 7756, + 7808, + 7804, + 0, + 7756, + 7759, + 7810, + 7808, + 0, + 7759, + 7764, + 7814, + 7810, + 0, + 7764, + 7766, + 7816, + 7814, + 0, + 7766, + 7767, + 7817, + 7816, + 0, + 7767, + 7765, + 7815, + 7817, + 0, + 7765, + 7763, + 7813, + 7815, + 0, + 7763, + 7757, + 7809, + 7813, + 0, + 7757, + 7755, + 7807, + 7809, + 0, + 7755, + 7749, + 7802, + 7807, + 0, + 7749, + 7745, + 7797, + 7802, + 0, + 7745, + 7740, + 7795, + 7797, + 0, + 7740, + 7737, + 7791, + 7795, + 0, + 7737, + 7735, + 7790, + 7791, + 0, + 7735, + 7726, + 7787, + 7790, + 0, + 7726, + 7725, + 7786, + 7787, + 0, + 7786, + 7788, + 7886, + 7880, + 0, + 7788, + 7794, + 7905, + 7886, + 0, + 7794, + 7798, + 7913, + 7905, + 0, + 7798, + 7805, + 7921, + 7913, + 0, + 7805, + 7811, + 7928, + 7921, + 0, + 7811, + 7818, + 7938, + 7928, + 0, + 7818, + 7820, + 7941, + 7938, + 0, + 7820, + 7823, + 7945, + 7941, + 0, + 7823, + 7826, + 7948, + 7945, + 0, + 7826, + 7828, + 7951, + 7948, + 0, + 7828, + 7830, + 7953, + 7951, + 0, + 7830, + 7831, + 7955, + 7953, + 0, + 7831, + 7829, + 7954, + 7955, + 0, + 7829, + 7827, + 7952, + 7954, + 0, + 7827, + 7825, + 7949, + 7952, + 0, + 7825, + 7824, + 7946, + 7949, + 0, + 7824, + 7821, + 7943, + 7946, + 0, + 7821, + 7819, + 7939, + 7943, + 0, + 7819, + 7812, + 7930, + 7939, + 0, + 7812, + 7806, + 7922, + 7930, + 0, + 7806, + 7799, + 7914, + 7922, + 0, + 7799, + 7785, + 7876, + 7914, + 0, + 7785, + 7783, + 7873, + 7876, + 0, + 7783, + 7770, + 7869, + 7873, + 0, + 7770, + 7760, + 7866, + 7869, + 0, + 7760, + 7751, + 7862, + 7866, + 0, + 7751, + 7744, + 7859, + 7862, + 0, + 7744, + 7738, + 7856, + 7859, + 0, + 7738, + 7734, + 7854, + 7856, + 0, + 7734, + 7732, + 7852, + 7854, + 0, + 7732, + 7728, + 7850, + 7852, + 0, + 7728, + 7723, + 7848, + 7850, + 0, + 7723, + 7710, + 7846, + 7848, + 0, + 7710, + 7695, + 7844, + 7846, + 0, + 7695, + 7685, + 7842, + 7844, + 0, + 7685, + 7677, + 7841, + 7842, + 0, + 7677, + 7669, + 7839, + 7841, + 0, + 7669, + 7664, + 7837, + 7839, + 0, + 7664, + 7660, + 7835, + 7837, + 0, + 7660, + 7654, + 7832, + 7835, + 0, + 7654, + 7649, + 7822, + 7832, + 0, + 7649, + 7634, + 7793, + 7822, + 0, + 7634, + 7639, + 7801, + 7793, + 0, + 7639, + 7641, + 7803, + 7801, + 0, + 7641, + 7655, + 7833, + 7803, + 0, + 7655, + 7659, + 7834, + 7833, + 0, + 7659, + 7663, + 7836, + 7834, + 0, + 7663, + 7668, + 7838, + 7836, + 0, + 7668, + 7676, + 7840, + 7838, + 0, + 7676, + 7686, + 7843, + 7840, + 0, + 7686, + 7701, + 7845, + 7843, + 0, + 7701, + 7716, + 7847, + 7845, + 0, + 7716, + 7727, + 7849, + 7847, + 0, + 7727, + 7731, + 7851, + 7849, + 0, + 7731, + 7733, + 7853, + 7851, + 0, + 7733, + 7736, + 7855, + 7853, + 0, + 7736, + 7742, + 7857, + 7855, + 0, + 7742, + 7750, + 7860, + 7857, + 0, + 7750, + 7758, + 7865, + 7860, + 0, + 7758, + 7771, + 7870, + 7865, + 0, + 7771, + 7778, + 7872, + 7870, + 0, + 7778, + 7789, + 7889, + 7872, + 0, + 7789, + 7792, + 7904, + 7889, + 0, + 7792, + 7796, + 7909, + 7904, + 0, + 7796, + 7800, + 7915, + 7909, + 0, + 7800, + 7804, + 7918, + 7915, + 0, + 7804, + 7808, + 7925, + 7918, + 0, + 7808, + 7810, + 7929, + 7925, + 0, + 7810, + 7814, + 7933, + 7929, + 0, + 7814, + 7816, + 7935, + 7933, + 0, + 7816, + 7817, + 7936, + 7935, + 0, + 7817, + 7815, + 7934, + 7936, + 0, + 7815, + 7813, + 7931, + 7934, + 0, + 7813, + 7809, + 7926, + 7931, + 0, + 7809, + 7807, + 7923, + 7926, + 0, + 7807, + 7802, + 7917, + 7923, + 0, + 7802, + 7797, + 7911, + 7917, + 0, + 7797, + 7795, + 7906, + 7911, + 0, + 7795, + 7791, + 7901, + 7906, + 0, + 7791, + 7790, + 7898, + 7901, + 0, + 7790, + 7787, + 7882, + 7898, + 0, + 7787, + 7786, + 7880, + 7882, + 0, + 7880, + 7886, + 7992, + 7989, + 0, + 7886, + 7905, + 8001, + 7992, + 0, + 7905, + 7913, + 8007, + 8001, + 0, + 7913, + 7921, + 8015, + 8007, + 0, + 7921, + 7928, + 8023, + 8015, + 0, + 7928, + 7938, + 8035, + 8023, + 0, + 7938, + 7941, + 8039, + 8035, + 0, + 7941, + 7945, + 8044, + 8039, + 0, + 7945, + 7948, + 8050, + 8044, + 0, + 7948, + 7951, + 8056, + 8050, + 0, + 7951, + 7953, + 8061, + 8056, + 0, + 7953, + 7955, + 8063, + 8061, + 0, + 7955, + 7954, + 8062, + 8063, + 0, + 7954, + 7952, + 8058, + 8062, + 0, + 7952, + 7949, + 8051, + 8058, + 0, + 7949, + 7946, + 8046, + 8051, + 0, + 7946, + 7943, + 8042, + 8046, + 0, + 7943, + 7939, + 8036, + 8042, + 0, + 7939, + 7930, + 8025, + 8036, + 0, + 7930, + 7922, + 8016, + 8025, + 0, + 7922, + 7914, + 8008, + 8016, + 0, + 7914, + 7876, + 7986, + 8008, + 0, + 7876, + 7873, + 7983, + 7986, + 0, + 7873, + 7869, + 7978, + 7983, + 0, + 7869, + 7866, + 7975, + 7978, + 0, + 7866, + 7862, + 7971, + 7975, + 0, + 7862, + 7859, + 7967, + 7971, + 0, + 7859, + 7856, + 7964, + 7967, + 0, + 7856, + 7854, + 7960, + 7964, + 0, + 7854, + 7852, + 7956, + 7960, + 0, + 7852, + 7850, + 7942, + 7956, + 0, + 7850, + 7848, + 7927, + 7942, + 0, + 7848, + 7846, + 7916, + 7927, + 0, + 7846, + 7844, + 7907, + 7916, + 0, + 7844, + 7842, + 7899, + 7907, + 0, + 7842, + 7841, + 7895, + 7899, + 0, + 7841, + 7839, + 7891, + 7895, + 0, + 7839, + 7837, + 7885, + 7891, + 0, + 7837, + 7835, + 7879, + 7885, + 0, + 7835, + 7832, + 7874, + 7879, + 0, + 7832, + 7822, + 7871, + 7874, + 0, + 7822, + 7793, + 7858, + 7871, + 0, + 7793, + 7801, + 7861, + 7858, + 0, + 7801, + 7803, + 7863, + 7861, + 0, + 7803, + 7833, + 7875, + 7863, + 0, + 7833, + 7834, + 7878, + 7875, + 0, + 7834, + 7836, + 7884, + 7878, + 0, + 7836, + 7838, + 7890, + 7884, + 0, + 7838, + 7840, + 7894, + 7890, + 0, + 7840, + 7843, + 7900, + 7894, + 0, + 7843, + 7845, + 7908, + 7900, + 0, + 7845, + 7847, + 7920, + 7908, + 0, + 7847, + 7849, + 7932, + 7920, + 0, + 7849, + 7851, + 7944, + 7932, + 0, + 7851, + 7853, + 7957, + 7944, + 0, + 7853, + 7855, + 7962, + 7957, + 0, + 7855, + 7857, + 7966, + 7962, + 0, + 7857, + 7860, + 7970, + 7966, + 0, + 7860, + 7865, + 7974, + 7970, + 0, + 7865, + 7870, + 7979, + 7974, + 0, + 7870, + 7872, + 7982, + 7979, + 0, + 7872, + 7889, + 7993, + 7982, + 0, + 7889, + 7904, + 8000, + 7993, + 0, + 7904, + 7909, + 8004, + 8000, + 0, + 7909, + 7915, + 8009, + 8004, + 0, + 7915, + 7918, + 8014, + 8009, + 0, + 7918, + 7925, + 8019, + 8014, + 0, + 7925, + 7929, + 8024, + 8019, + 0, + 7929, + 7933, + 8029, + 8024, + 0, + 7933, + 7935, + 8031, + 8029, + 0, + 7935, + 7936, + 8032, + 8031, + 0, + 7936, + 7934, + 8030, + 8032, + 0, + 7934, + 7931, + 8026, + 8030, + 0, + 7931, + 7926, + 8021, + 8026, + 0, + 7926, + 7923, + 8017, + 8021, + 0, + 7923, + 7917, + 8010, + 8017, + 0, + 7917, + 7911, + 8005, + 8010, + 0, + 7911, + 7906, + 8002, + 8005, + 0, + 7906, + 7901, + 7999, + 8002, + 0, + 7901, + 7898, + 7998, + 7999, + 0, + 7898, + 7882, + 7990, + 7998, + 0, + 7882, + 7880, + 7989, + 7990, + 0, + 7989, + 7992, + 7996, + 7994, + 0, + 7992, + 8001, + 8012, + 7996, + 0, + 8001, + 8007, + 8022, + 8012, + 0, + 8007, + 8015, + 8038, + 8022, + 0, + 8015, + 8023, + 8047, + 8038, + 0, + 8023, + 8035, + 8064, + 8047, + 0, + 8035, + 8039, + 8066, + 8064, + 0, + 8039, + 8044, + 8068, + 8066, + 0, + 8044, + 8050, + 8070, + 8068, + 0, + 8050, + 8056, + 8072, + 8070, + 0, + 8056, + 8061, + 8074, + 8072, + 0, + 8061, + 8063, + 8076, + 8074, + 0, + 8063, + 8062, + 8075, + 8076, + 0, + 8062, + 8058, + 8073, + 8075, + 0, + 8058, + 8051, + 8071, + 8073, + 0, + 8051, + 8046, + 8069, + 8071, + 0, + 8046, + 8042, + 8067, + 8069, + 0, + 8042, + 8036, + 8065, + 8067, + 0, + 8036, + 8025, + 8052, + 8065, + 0, + 8025, + 8016, + 8041, + 8052, + 0, + 8016, + 8008, + 8027, + 8041, + 0, + 8008, + 7986, + 7991, + 8027, + 0, + 7986, + 7983, + 7988, + 7991, + 0, + 7983, + 7978, + 7984, + 7988, + 0, + 7978, + 7975, + 7981, + 7984, + 0, + 7975, + 7971, + 7977, + 7981, + 0, + 7971, + 7967, + 7973, + 7977, + 0, + 7967, + 7964, + 7969, + 7973, + 0, + 7964, + 7960, + 7965, + 7969, + 0, + 7960, + 7956, + 7961, + 7965, + 0, + 7956, + 7942, + 7958, + 7961, + 0, + 7942, + 7927, + 7947, + 7958, + 0, + 7927, + 7916, + 7937, + 7947, + 0, + 7916, + 7907, + 7919, + 7937, + 0, + 7907, + 7899, + 7910, + 7919, + 0, + 7899, + 7895, + 7903, + 7910, + 0, + 7895, + 7891, + 7897, + 7903, + 0, + 7891, + 7885, + 7893, + 7897, + 0, + 7885, + 7879, + 7888, + 7893, + 0, + 7879, + 7874, + 7881, + 7888, + 0, + 7874, + 7871, + 7877, + 7881, + 0, + 7871, + 7858, + 7864, + 7877, + 0, + 7858, + 7861, + 7867, + 7864, + 0, + 7861, + 7863, + 7868, + 7867, + 0, + 7863, + 7875, + 7883, + 7868, + 0, + 7875, + 7878, + 7887, + 7883, + 0, + 7878, + 7884, + 7892, + 7887, + 0, + 7884, + 7890, + 7896, + 7892, + 0, + 7890, + 7894, + 7902, + 7896, + 0, + 7894, + 7900, + 7912, + 7902, + 0, + 7900, + 7908, + 7924, + 7912, + 0, + 7908, + 7920, + 7940, + 7924, + 0, + 7920, + 7932, + 7950, + 7940, + 0, + 7932, + 7944, + 7959, + 7950, + 0, + 7944, + 7957, + 7963, + 7959, + 0, + 7957, + 7962, + 7968, + 7963, + 0, + 7962, + 7966, + 7972, + 7968, + 0, + 7966, + 7970, + 7976, + 7972, + 0, + 7970, + 7974, + 7980, + 7976, + 0, + 7974, + 7979, + 7985, + 7980, + 0, + 7979, + 7982, + 7987, + 7985, + 0, + 7982, + 7993, + 7997, + 7987, + 0, + 7993, + 8000, + 8011, + 7997, + 0, + 8000, + 8004, + 8018, + 8011, + 0, + 8004, + 8009, + 8028, + 8018, + 0, + 8009, + 8014, + 8037, + 8028, + 0, + 8014, + 8019, + 8043, + 8037, + 0, + 8019, + 8024, + 8049, + 8043, + 0, + 8024, + 8029, + 8054, + 8049, + 0, + 8029, + 8031, + 8059, + 8054, + 0, + 8031, + 8032, + 8060, + 8059, + 0, + 8032, + 8030, + 8055, + 8060, + 0, + 8030, + 8026, + 8053, + 8055, + 0, + 8026, + 8021, + 8045, + 8053, + 0, + 8021, + 8017, + 8040, + 8045, + 0, + 8017, + 8010, + 8033, + 8040, + 0, + 8010, + 8005, + 8020, + 8033, + 0, + 8005, + 8002, + 8013, + 8020, + 0, + 8002, + 7999, + 8006, + 8013, + 0, + 7999, + 7998, + 8003, + 8006, + 0, + 7998, + 7990, + 7995, + 8003, + 0, + 7990, + 7989, + 7994, + 7995, + 0, + 7994, + 7996, + 8124, + 8120, + 0, + 7996, + 8012, + 8138, + 8124, + 0, + 8012, + 8022, + 8144, + 8138, + 0, + 8022, + 8038, + 8150, + 8144, + 0, + 8038, + 8047, + 8158, + 8150, + 0, + 8047, + 8064, + 8167, + 8158, + 0, + 8064, + 8066, + 8172, + 8167, + 0, + 8066, + 8068, + 8175, + 8172, + 0, + 8068, + 8070, + 8177, + 8175, + 0, + 8070, + 8072, + 8181, + 8177, + 0, + 8072, + 8074, + 8183, + 8181, + 0, + 8074, + 8076, + 8186, + 8183, + 0, + 8076, + 8075, + 8185, + 8186, + 0, + 8075, + 8073, + 8182, + 8185, + 0, + 8073, + 8071, + 8179, + 8182, + 0, + 8071, + 8069, + 8176, + 8179, + 0, + 8069, + 8067, + 8173, + 8176, + 0, + 8067, + 8065, + 8168, + 8173, + 0, + 8065, + 8052, + 8161, + 8168, + 0, + 8052, + 8041, + 8153, + 8161, + 0, + 8041, + 8027, + 8145, + 8153, + 0, + 8027, + 7991, + 8117, + 8145, + 0, + 7991, + 7988, + 8115, + 8117, + 0, + 7988, + 7984, + 8112, + 8115, + 0, + 7984, + 7981, + 8111, + 8112, + 0, + 7981, + 7977, + 8107, + 8111, + 0, + 7977, + 7973, + 8104, + 8107, + 0, + 7973, + 7969, + 8102, + 8104, + 0, + 7969, + 7965, + 8100, + 8102, + 0, + 7965, + 7961, + 8098, + 8100, + 0, + 7961, + 7958, + 8096, + 8098, + 0, + 7958, + 7947, + 8094, + 8096, + 0, + 7947, + 7937, + 8092, + 8094, + 0, + 7937, + 7919, + 8090, + 8092, + 0, + 7919, + 7910, + 8088, + 8090, + 0, + 7910, + 7903, + 8087, + 8088, + 0, + 7903, + 7897, + 8085, + 8087, + 0, + 7897, + 7893, + 8083, + 8085, + 0, + 7893, + 7888, + 8081, + 8083, + 0, + 7888, + 7881, + 8078, + 8081, + 0, + 7881, + 7877, + 8077, + 8078, + 0, + 7877, + 7864, + 8034, + 8077, + 0, + 7864, + 7867, + 8048, + 8034, + 0, + 7867, + 7868, + 8057, + 8048, + 0, + 7868, + 7883, + 8079, + 8057, + 0, + 7883, + 7887, + 8080, + 8079, + 0, + 7887, + 7892, + 8082, + 8080, + 0, + 7892, + 7896, + 8084, + 8082, + 0, + 7896, + 7902, + 8086, + 8084, + 0, + 7902, + 7912, + 8089, + 8086, + 0, + 7912, + 7924, + 8091, + 8089, + 0, + 7924, + 7940, + 8093, + 8091, + 0, + 7940, + 7950, + 8095, + 8093, + 0, + 7950, + 7959, + 8097, + 8095, + 0, + 7959, + 7963, + 8099, + 8097, + 0, + 7963, + 7968, + 8101, + 8099, + 0, + 7968, + 7972, + 8103, + 8101, + 0, + 7972, + 7976, + 8106, + 8103, + 0, + 7976, + 7980, + 8109, + 8106, + 0, + 7980, + 7985, + 8113, + 8109, + 0, + 7985, + 7987, + 8114, + 8113, + 0, + 7987, + 7997, + 8125, + 8114, + 0, + 7997, + 8011, + 8136, + 8125, + 0, + 8011, + 8018, + 8142, + 8136, + 0, + 8018, + 8028, + 8147, + 8142, + 0, + 8028, + 8037, + 8151, + 8147, + 0, + 8037, + 8043, + 8155, + 8151, + 0, + 8043, + 8049, + 8159, + 8155, + 0, + 8049, + 8054, + 8163, + 8159, + 0, + 8054, + 8059, + 8165, + 8163, + 0, + 8059, + 8060, + 8166, + 8165, + 0, + 8060, + 8055, + 8164, + 8166, + 0, + 8055, + 8053, + 8160, + 8164, + 0, + 8053, + 8045, + 8157, + 8160, + 0, + 8045, + 8040, + 8152, + 8157, + 0, + 8040, + 8033, + 8148, + 8152, + 0, + 8033, + 8020, + 8143, + 8148, + 0, + 8020, + 8013, + 8139, + 8143, + 0, + 8013, + 8006, + 8134, + 8139, + 0, + 8006, + 8003, + 8131, + 8134, + 0, + 8003, + 7995, + 8121, + 8131, + 0, + 7995, + 7994, + 8120, + 8121, + 0, + 8120, + 8124, + 8225, + 8221, + 0, + 8124, + 8138, + 8237, + 8225, + 0, + 8138, + 8144, + 8244, + 8237, + 0, + 8144, + 8150, + 8249, + 8244, + 0, + 8150, + 8158, + 8256, + 8249, + 0, + 8158, + 8167, + 8266, + 8256, + 0, + 8167, + 8172, + 8269, + 8266, + 0, + 8172, + 8175, + 8272, + 8269, + 0, + 8175, + 8177, + 8275, + 8272, + 0, + 8177, + 8181, + 8278, + 8275, + 0, + 8181, + 8183, + 8280, + 8278, + 0, + 8183, + 8186, + 8283, + 8280, + 0, + 8186, + 8185, + 8282, + 8283, + 0, + 8185, + 8182, + 8279, + 8282, + 0, + 8182, + 8179, + 8276, + 8279, + 0, + 8179, + 8176, + 8273, + 8276, + 0, + 8176, + 8173, + 8270, + 8273, + 0, + 8173, + 8168, + 8267, + 8270, + 0, + 8168, + 8161, + 8259, + 8267, + 0, + 8161, + 8153, + 8253, + 8259, + 0, + 8153, + 8145, + 8245, + 8253, + 0, + 8145, + 8117, + 8219, + 8245, + 0, + 8117, + 8115, + 8216, + 8219, + 0, + 8115, + 8112, + 8211, + 8216, + 0, + 8112, + 8111, + 8209, + 8211, + 0, + 8111, + 8107, + 8205, + 8209, + 0, + 8107, + 8104, + 8202, + 8205, + 0, + 8104, + 8102, + 8198, + 8202, + 0, + 8102, + 8100, + 8194, + 8198, + 0, + 8100, + 8098, + 8190, + 8194, + 0, + 8098, + 8096, + 8184, + 8190, + 0, + 8096, + 8094, + 8171, + 8184, + 0, + 8094, + 8092, + 8156, + 8171, + 0, + 8092, + 8090, + 8146, + 8156, + 0, + 8090, + 8088, + 8140, + 8146, + 0, + 8088, + 8087, + 8133, + 8140, + 0, + 8087, + 8085, + 8129, + 8133, + 0, + 8085, + 8083, + 8127, + 8129, + 0, + 8083, + 8081, + 8123, + 8127, + 0, + 8081, + 8078, + 8118, + 8123, + 0, + 8078, + 8077, + 8116, + 8118, + 0, + 8077, + 8034, + 8105, + 8116, + 0, + 8034, + 8048, + 8108, + 8105, + 0, + 8048, + 8057, + 8110, + 8108, + 0, + 8057, + 8079, + 8119, + 8110, + 0, + 8079, + 8080, + 8122, + 8119, + 0, + 8080, + 8082, + 8126, + 8122, + 0, + 8082, + 8084, + 8128, + 8126, + 0, + 8084, + 8086, + 8132, + 8128, + 0, + 8086, + 8089, + 8141, + 8132, + 0, + 8089, + 8091, + 8149, + 8141, + 0, + 8091, + 8093, + 8162, + 8149, + 0, + 8093, + 8095, + 8174, + 8162, + 0, + 8095, + 8097, + 8187, + 8174, + 0, + 8097, + 8099, + 8191, + 8187, + 0, + 8099, + 8101, + 8195, + 8191, + 0, + 8101, + 8103, + 8200, + 8195, + 0, + 8103, + 8106, + 8204, + 8200, + 0, + 8106, + 8109, + 8208, + 8204, + 0, + 8109, + 8113, + 8212, + 8208, + 0, + 8113, + 8114, + 8215, + 8212, + 0, + 8114, + 8125, + 8227, + 8215, + 0, + 8125, + 8136, + 8236, + 8227, + 0, + 8136, + 8142, + 8240, + 8236, + 0, + 8142, + 8147, + 8246, + 8240, + 0, + 8147, + 8151, + 8250, + 8246, + 0, + 8151, + 8155, + 8254, + 8250, + 0, + 8155, + 8159, + 8257, + 8254, + 0, + 8159, + 8163, + 8261, + 8257, + 0, + 8163, + 8165, + 8264, + 8261, + 0, + 8165, + 8166, + 8263, + 8264, + 0, + 8166, + 8164, + 8260, + 8263, + 0, + 8164, + 8160, + 8258, + 8260, + 0, + 8160, + 8157, + 8255, + 8258, + 0, + 8157, + 8152, + 8251, + 8255, + 0, + 8152, + 8148, + 8247, + 8251, + 0, + 8148, + 8143, + 8241, + 8247, + 0, + 8143, + 8139, + 8239, + 8241, + 0, + 8139, + 8134, + 8234, + 8239, + 0, + 8134, + 8131, + 8231, + 8234, + 0, + 8131, + 8121, + 8223, + 8231, + 0, + 8121, + 8120, + 8221, + 8223, + 0, + 8221, + 8225, + 8281, + 8268, + 0, + 8225, + 8237, + 8291, + 8281, + 0, + 8237, + 8244, + 8297, + 8291, + 0, + 8244, + 8249, + 8303, + 8297, + 0, + 8249, + 8256, + 8310, + 8303, + 0, + 8256, + 8266, + 8319, + 8310, + 0, + 8266, + 8269, + 8322, + 8319, + 0, + 8269, + 8272, + 8325, + 8322, + 0, + 8272, + 8275, + 8327, + 8325, + 0, + 8275, + 8278, + 8329, + 8327, + 0, + 8278, + 8280, + 8331, + 8329, + 0, + 8280, + 8283, + 8334, + 8331, + 0, + 8283, + 8282, + 8333, + 8334, + 0, + 8282, + 8279, + 8330, + 8333, + 0, + 8279, + 8276, + 8328, + 8330, + 0, + 8276, + 8273, + 8326, + 8328, + 0, + 8273, + 8270, + 8324, + 8326, + 0, + 8270, + 8267, + 8320, + 8324, + 0, + 8267, + 8259, + 8314, + 8320, + 0, + 8259, + 8253, + 8306, + 8314, + 0, + 8253, + 8245, + 8298, + 8306, + 0, + 8245, + 8219, + 8265, + 8298, + 0, + 8219, + 8216, + 8252, + 8265, + 0, + 8216, + 8211, + 8242, + 8252, + 0, + 8211, + 8209, + 8238, + 8242, + 0, + 8209, + 8205, + 8233, + 8238, + 0, + 8205, + 8202, + 8230, + 8233, + 0, + 8202, + 8198, + 8228, + 8230, + 0, + 8198, + 8194, + 8224, + 8228, + 0, + 8194, + 8190, + 8220, + 8224, + 0, + 8190, + 8184, + 8217, + 8220, + 0, + 8184, + 8171, + 8213, + 8217, + 0, + 8171, + 8156, + 8207, + 8213, + 0, + 8156, + 8146, + 8203, + 8207, + 0, + 8146, + 8140, + 8199, + 8203, + 0, + 8140, + 8133, + 8197, + 8199, + 0, + 8133, + 8129, + 8193, + 8197, + 0, + 8129, + 8127, + 8189, + 8193, + 0, + 8127, + 8123, + 8180, + 8189, + 0, + 8123, + 8118, + 8169, + 8180, + 0, + 8118, + 8116, + 8154, + 8169, + 0, + 8116, + 8105, + 8130, + 8154, + 0, + 8105, + 8108, + 8135, + 8130, + 0, + 8108, + 8110, + 8137, + 8135, + 0, + 8110, + 8119, + 8170, + 8137, + 0, + 8119, + 8122, + 8178, + 8170, + 0, + 8122, + 8126, + 8188, + 8178, + 0, + 8126, + 8128, + 8192, + 8188, + 0, + 8128, + 8132, + 8196, + 8192, + 0, + 8132, + 8141, + 8201, + 8196, + 0, + 8141, + 8149, + 8206, + 8201, + 0, + 8149, + 8162, + 8210, + 8206, + 0, + 8162, + 8174, + 8214, + 8210, + 0, + 8174, + 8187, + 8218, + 8214, + 0, + 8187, + 8191, + 8222, + 8218, + 0, + 8191, + 8195, + 8226, + 8222, + 0, + 8195, + 8200, + 8229, + 8226, + 0, + 8200, + 8204, + 8232, + 8229, + 0, + 8204, + 8208, + 8235, + 8232, + 0, + 8208, + 8212, + 8243, + 8235, + 0, + 8212, + 8215, + 8248, + 8243, + 0, + 8215, + 8227, + 8284, + 8248, + 0, + 8227, + 8236, + 8290, + 8284, + 0, + 8236, + 8240, + 8295, + 8290, + 0, + 8240, + 8246, + 8300, + 8295, + 0, + 8246, + 8250, + 8304, + 8300, + 0, + 8250, + 8254, + 8307, + 8304, + 0, + 8254, + 8257, + 8312, + 8307, + 0, + 8257, + 8261, + 8316, + 8312, + 0, + 8261, + 8264, + 8318, + 8316, + 0, + 8264, + 8263, + 8317, + 8318, + 0, + 8263, + 8260, + 8315, + 8317, + 0, + 8260, + 8258, + 8313, + 8315, + 0, + 8258, + 8255, + 8309, + 8313, + 0, + 8255, + 8251, + 8305, + 8309, + 0, + 8251, + 8247, + 8301, + 8305, + 0, + 8247, + 8241, + 8296, + 8301, + 0, + 8241, + 8239, + 8292, + 8296, + 0, + 8239, + 8234, + 8287, + 8292, + 0, + 8234, + 8231, + 8286, + 8287, + 0, + 8231, + 8223, + 8271, + 8286, + 0, + 8223, + 8221, + 8268, + 8271, + 0, + 8268, + 8281, + 8370, + 8366, + 0, + 8281, + 8291, + 8382, + 8370, + 0, + 8291, + 8297, + 8388, + 8382, + 0, + 8297, + 8303, + 8393, + 8388, + 0, + 8303, + 8310, + 8401, + 8393, + 0, + 8310, + 8319, + 8410, + 8401, + 0, + 8319, + 8322, + 8413, + 8410, + 0, + 8322, + 8325, + 8415, + 8413, + 0, + 8325, + 8327, + 8418, + 8415, + 0, + 8327, + 8329, + 8421, + 8418, + 0, + 8329, + 8331, + 8423, + 8421, + 0, + 8331, + 8334, + 8425, + 8423, + 0, + 8334, + 8333, + 8424, + 8425, + 0, + 8333, + 8330, + 8422, + 8424, + 0, + 8330, + 8328, + 8420, + 8422, + 0, + 8328, + 8326, + 8417, + 8420, + 0, + 8326, + 8324, + 8414, + 8417, + 0, + 8324, + 8320, + 8412, + 8414, + 0, + 8320, + 8314, + 8404, + 8412, + 0, + 8314, + 8306, + 8397, + 8404, + 0, + 8306, + 8298, + 8390, + 8397, + 0, + 8298, + 8265, + 8365, + 8390, + 0, + 8265, + 8252, + 8362, + 8365, + 0, + 8252, + 8242, + 8358, + 8362, + 0, + 8242, + 8238, + 8357, + 8358, + 0, + 8238, + 8233, + 8354, + 8357, + 0, + 8233, + 8230, + 8351, + 8354, + 0, + 8230, + 8228, + 8348, + 8351, + 0, + 8228, + 8224, + 8346, + 8348, + 0, + 8224, + 8220, + 8344, + 8346, + 0, + 8220, + 8217, + 8342, + 8344, + 0, + 8217, + 8213, + 8340, + 8342, + 0, + 8213, + 8207, + 8338, + 8340, + 0, + 8207, + 8203, + 8336, + 8338, + 0, + 8203, + 8199, + 8332, + 8336, + 0, + 8199, + 8197, + 8323, + 8332, + 0, + 8197, + 8193, + 8311, + 8323, + 0, + 8193, + 8189, + 8302, + 8311, + 0, + 8189, + 8180, + 8294, + 8302, + 0, + 8180, + 8169, + 8288, + 8294, + 0, + 8169, + 8154, + 8285, + 8288, + 0, + 8154, + 8130, + 8262, + 8285, + 0, + 8130, + 8135, + 8274, + 8262, + 0, + 8135, + 8137, + 8277, + 8274, + 0, + 8137, + 8170, + 8289, + 8277, + 0, + 8170, + 8178, + 8293, + 8289, + 0, + 8178, + 8188, + 8299, + 8293, + 0, + 8188, + 8192, + 8308, + 8299, + 0, + 8192, + 8196, + 8321, + 8308, + 0, + 8196, + 8201, + 8335, + 8321, + 0, + 8201, + 8206, + 8337, + 8335, + 0, + 8206, + 8210, + 8339, + 8337, + 0, + 8210, + 8214, + 8341, + 8339, + 0, + 8214, + 8218, + 8343, + 8341, + 0, + 8218, + 8222, + 8345, + 8343, + 0, + 8222, + 8226, + 8347, + 8345, + 0, + 8226, + 8229, + 8349, + 8347, + 0, + 8229, + 8232, + 8352, + 8349, + 0, + 8232, + 8235, + 8356, + 8352, + 0, + 8235, + 8243, + 8359, + 8356, + 0, + 8243, + 8248, + 8361, + 8359, + 0, + 8248, + 8284, + 8373, + 8361, + 0, + 8284, + 8290, + 8383, + 8373, + 0, + 8290, + 8295, + 8386, + 8383, + 0, + 8295, + 8300, + 8391, + 8386, + 0, + 8300, + 8304, + 8395, + 8391, + 0, + 8304, + 8307, + 8399, + 8395, + 0, + 8307, + 8312, + 8402, + 8399, + 0, + 8312, + 8316, + 8406, + 8402, + 0, + 8316, + 8318, + 8409, + 8406, + 0, + 8318, + 8317, + 8408, + 8409, + 0, + 8317, + 8315, + 8405, + 8408, + 0, + 8315, + 8313, + 8403, + 8405, + 0, + 8313, + 8309, + 8400, + 8403, + 0, + 8309, + 8305, + 8396, + 8400, + 0, + 8305, + 8301, + 8392, + 8396, + 0, + 8301, + 8296, + 8387, + 8392, + 0, + 8296, + 8292, + 8384, + 8387, + 0, + 8292, + 8287, + 8379, + 8384, + 0, + 8287, + 8286, + 8378, + 8379, + 0, + 8286, + 8271, + 8368, + 8378, + 0, + 8271, + 8268, + 8366, + 8368, + 0, + 8366, + 8370, + 8452, + 8448, + 0, + 8370, + 8382, + 8464, + 8452, + 0, + 8382, + 8388, + 8470, + 8464, + 0, + 8388, + 8393, + 8475, + 8470, + 0, + 8393, + 8401, + 8483, + 8475, + 0, + 8401, + 8410, + 8491, + 8483, + 0, + 8410, + 8413, + 8495, + 8491, + 0, + 8413, + 8415, + 8497, + 8495, + 0, + 8415, + 8418, + 8500, + 8497, + 0, + 8418, + 8421, + 8504, + 8500, + 0, + 8421, + 8423, + 8506, + 8504, + 0, + 8423, + 8425, + 8508, + 8506, + 0, + 8425, + 8424, + 8507, + 8508, + 0, + 8424, + 8422, + 8505, + 8507, + 0, + 8422, + 8420, + 8501, + 8505, + 0, + 8420, + 8417, + 8498, + 8501, + 0, + 8417, + 8414, + 8496, + 8498, + 0, + 8414, + 8412, + 8493, + 8496, + 0, + 8412, + 8404, + 8486, + 8493, + 0, + 8404, + 8397, + 8479, + 8486, + 0, + 8397, + 8390, + 8472, + 8479, + 0, + 8390, + 8365, + 8447, + 8472, + 0, + 8365, + 8362, + 8444, + 8447, + 0, + 8362, + 8358, + 8441, + 8444, + 0, + 8358, + 8357, + 8439, + 8441, + 0, + 8357, + 8354, + 8436, + 8439, + 0, + 8354, + 8351, + 8433, + 8436, + 0, + 8351, + 8348, + 8430, + 8433, + 0, + 8348, + 8346, + 8428, + 8430, + 0, + 8346, + 8344, + 8426, + 8428, + 0, + 8344, + 8342, + 8416, + 8426, + 0, + 8342, + 8340, + 8407, + 8416, + 0, + 8340, + 8338, + 8394, + 8407, + 0, + 8338, + 8336, + 8385, + 8394, + 0, + 8336, + 8332, + 8380, + 8385, + 0, + 8332, + 8323, + 8377, + 8380, + 0, + 8323, + 8311, + 8375, + 8377, + 0, + 8311, + 8302, + 8372, + 8375, + 0, + 8302, + 8294, + 8369, + 8372, + 0, + 8294, + 8288, + 8363, + 8369, + 0, + 8288, + 8285, + 8360, + 8363, + 0, + 8285, + 8262, + 8350, + 8360, + 0, + 8262, + 8274, + 8353, + 8350, + 0, + 8274, + 8277, + 8355, + 8353, + 0, + 8277, + 8289, + 8364, + 8355, + 0, + 8289, + 8293, + 8367, + 8364, + 0, + 8293, + 8299, + 8371, + 8367, + 0, + 8299, + 8308, + 8374, + 8371, + 0, + 8308, + 8321, + 8376, + 8374, + 0, + 8321, + 8335, + 8381, + 8376, + 0, + 8335, + 8337, + 8389, + 8381, + 0, + 8337, + 8339, + 8398, + 8389, + 0, + 8339, + 8341, + 8411, + 8398, + 0, + 8341, + 8343, + 8419, + 8411, + 0, + 8343, + 8345, + 8427, + 8419, + 0, + 8345, + 8347, + 8429, + 8427, + 0, + 8347, + 8349, + 8431, + 8429, + 0, + 8349, + 8352, + 8434, + 8431, + 0, + 8352, + 8356, + 8438, + 8434, + 0, + 8356, + 8359, + 8440, + 8438, + 0, + 8359, + 8361, + 8443, + 8440, + 0, + 8361, + 8373, + 8455, + 8443, + 0, + 8373, + 8383, + 8466, + 8455, + 0, + 8383, + 8386, + 8468, + 8466, + 0, + 8386, + 8391, + 8473, + 8468, + 0, + 8391, + 8395, + 8476, + 8473, + 0, + 8395, + 8399, + 8480, + 8476, + 0, + 8399, + 8402, + 8484, + 8480, + 0, + 8402, + 8406, + 8488, + 8484, + 0, + 8406, + 8409, + 8490, + 8488, + 0, + 8409, + 8408, + 8489, + 8490, + 0, + 8408, + 8405, + 8487, + 8489, + 0, + 8405, + 8403, + 8485, + 8487, + 0, + 8403, + 8400, + 8481, + 8485, + 0, + 8400, + 8396, + 8478, + 8481, + 0, + 8396, + 8392, + 8474, + 8478, + 0, + 8392, + 8387, + 8467, + 8474, + 0, + 8387, + 8384, + 8465, + 8467, + 0, + 8384, + 8379, + 8461, + 8465, + 0, + 8379, + 8378, + 8460, + 8461, + 0, + 8378, + 8368, + 8449, + 8460, + 0, + 8368, + 8366, + 8448, + 8449, + 0, + 8448, + 8452, + 8542, + 8538, + 0, + 8452, + 8464, + 8552, + 8542, + 0, + 8464, + 8470, + 8559, + 8552, + 0, + 8470, + 8475, + 8564, + 8559, + 0, + 8475, + 8483, + 8571, + 8564, + 0, + 8483, + 8491, + 8580, + 8571, + 0, + 8491, + 8495, + 8583, + 8580, + 0, + 8495, + 8497, + 8587, + 8583, + 0, + 8497, + 8500, + 8589, + 8587, + 0, + 8500, + 8504, + 8592, + 8589, + 0, + 8504, + 8506, + 8594, + 8592, + 0, + 8506, + 8508, + 8596, + 8594, + 0, + 8508, + 8507, + 8595, + 8596, + 0, + 8507, + 8505, + 8593, + 8595, + 0, + 8505, + 8501, + 8591, + 8593, + 0, + 8501, + 8498, + 8588, + 8591, + 0, + 8498, + 8496, + 8586, + 8588, + 0, + 8496, + 8493, + 8582, + 8586, + 0, + 8493, + 8486, + 8576, + 8582, + 0, + 8486, + 8479, + 8568, + 8576, + 0, + 8479, + 8472, + 8560, + 8568, + 0, + 8472, + 8447, + 8535, + 8560, + 0, + 8447, + 8444, + 8533, + 8535, + 0, + 8444, + 8441, + 8529, + 8533, + 0, + 8441, + 8439, + 8526, + 8529, + 0, + 8439, + 8436, + 8522, + 8526, + 0, + 8436, + 8433, + 8518, + 8522, + 0, + 8433, + 8430, + 8515, + 8518, + 0, + 8430, + 8428, + 8513, + 8515, + 0, + 8428, + 8426, + 8509, + 8513, + 0, + 8426, + 8416, + 8499, + 8509, + 0, + 8416, + 8407, + 8492, + 8499, + 0, + 8407, + 8394, + 8477, + 8492, + 0, + 8394, + 8385, + 8469, + 8477, + 0, + 8385, + 8380, + 8462, + 8469, + 0, + 8380, + 8377, + 8459, + 8462, + 0, + 8377, + 8375, + 8457, + 8459, + 0, + 8375, + 8372, + 8454, + 8457, + 0, + 8372, + 8369, + 8451, + 8454, + 0, + 8369, + 8363, + 8445, + 8451, + 0, + 8363, + 8360, + 8442, + 8445, + 0, + 8360, + 8350, + 8432, + 8442, + 0, + 8350, + 8353, + 8435, + 8432, + 0, + 8353, + 8355, + 8437, + 8435, + 0, + 8355, + 8364, + 8446, + 8437, + 0, + 8364, + 8367, + 8450, + 8446, + 0, + 8367, + 8371, + 8453, + 8450, + 0, + 8371, + 8374, + 8456, + 8453, + 0, + 8374, + 8376, + 8458, + 8456, + 0, + 8376, + 8381, + 8463, + 8458, + 0, + 8381, + 8389, + 8471, + 8463, + 0, + 8389, + 8398, + 8482, + 8471, + 0, + 8398, + 8411, + 8494, + 8482, + 0, + 8411, + 8419, + 8502, + 8494, + 0, + 8419, + 8427, + 8511, + 8502, + 0, + 8427, + 8429, + 8514, + 8511, + 0, + 8429, + 8431, + 8516, + 8514, + 0, + 8431, + 8434, + 8520, + 8516, + 0, + 8434, + 8438, + 8525, + 8520, + 0, + 8438, + 8440, + 8528, + 8525, + 0, + 8440, + 8443, + 8531, + 8528, + 0, + 8443, + 8455, + 8543, + 8531, + 0, + 8455, + 8466, + 8554, + 8543, + 0, + 8466, + 8468, + 8558, + 8554, + 0, + 8468, + 8473, + 8562, + 8558, + 0, + 8473, + 8476, + 8567, + 8562, + 0, + 8476, + 8480, + 8569, + 8567, + 0, + 8480, + 8484, + 8573, + 8569, + 0, + 8484, + 8488, + 8577, + 8573, + 0, + 8488, + 8490, + 8579, + 8577, + 0, + 8490, + 8489, + 8578, + 8579, + 0, + 8489, + 8487, + 8575, + 8578, + 0, + 8487, + 8485, + 8574, + 8575, + 0, + 8485, + 8481, + 8570, + 8574, + 0, + 8481, + 8478, + 8566, + 8570, + 0, + 8478, + 8474, + 8561, + 8566, + 0, + 8474, + 8467, + 8557, + 8561, + 0, + 8467, + 8465, + 8553, + 8557, + 0, + 8465, + 8461, + 8549, + 8553, + 0, + 8461, + 8460, + 8548, + 8549, + 0, + 8460, + 8449, + 8539, + 8548, + 0, + 8449, + 8448, + 8538, + 8539, + 0, + 8538, + 8542, + 8618, + 8614, + 0, + 8542, + 8552, + 8628, + 8618, + 0, + 8552, + 8559, + 8635, + 8628, + 0, + 8559, + 8564, + 8641, + 8635, + 0, + 8564, + 8571, + 8648, + 8641, + 0, + 8571, + 8580, + 8657, + 8648, + 0, + 8580, + 8583, + 8660, + 8657, + 0, + 8583, + 8587, + 8663, + 8660, + 0, + 8587, + 8589, + 8665, + 8663, + 0, + 8589, + 8592, + 8667, + 8665, + 0, + 8592, + 8594, + 8670, + 8667, + 0, + 8594, + 8596, + 8672, + 8670, + 0, + 8596, + 8595, + 8671, + 8672, + 0, + 8595, + 8593, + 8669, + 8671, + 0, + 8593, + 8591, + 8666, + 8669, + 0, + 8591, + 8588, + 8664, + 8666, + 0, + 8588, + 8586, + 8662, + 8664, + 0, + 8586, + 8582, + 8658, + 8662, + 0, + 8582, + 8576, + 8653, + 8658, + 0, + 8576, + 8568, + 8644, + 8653, + 0, + 8568, + 8560, + 8638, + 8644, + 0, + 8560, + 8535, + 8613, + 8638, + 0, + 8535, + 8533, + 8610, + 8613, + 0, + 8533, + 8529, + 8606, + 8610, + 0, + 8529, + 8526, + 8603, + 8606, + 0, + 8526, + 8522, + 8601, + 8603, + 0, + 8522, + 8518, + 8597, + 8601, + 0, + 8518, + 8515, + 8585, + 8597, + 0, + 8515, + 8513, + 8572, + 8585, + 0, + 8513, + 8509, + 8563, + 8572, + 0, + 8509, + 8499, + 8555, + 8563, + 0, + 8499, + 8492, + 8550, + 8555, + 0, + 8492, + 8477, + 8546, + 8550, + 0, + 8477, + 8469, + 8544, + 8546, + 0, + 8469, + 8462, + 8540, + 8544, + 0, + 8462, + 8459, + 8537, + 8540, + 0, + 8459, + 8457, + 8534, + 8537, + 0, + 8457, + 8454, + 8530, + 8534, + 0, + 8454, + 8451, + 8524, + 8530, + 0, + 8451, + 8445, + 8519, + 8524, + 0, + 8445, + 8442, + 8517, + 8519, + 0, + 8442, + 8432, + 8503, + 8517, + 0, + 8432, + 8435, + 8510, + 8503, + 0, + 8435, + 8437, + 8512, + 8510, + 0, + 8437, + 8446, + 8521, + 8512, + 0, + 8446, + 8450, + 8523, + 8521, + 0, + 8450, + 8453, + 8527, + 8523, + 0, + 8453, + 8456, + 8532, + 8527, + 0, + 8456, + 8458, + 8536, + 8532, + 0, + 8458, + 8463, + 8541, + 8536, + 0, + 8463, + 8471, + 8545, + 8541, + 0, + 8471, + 8482, + 8547, + 8545, + 0, + 8482, + 8494, + 8551, + 8547, + 0, + 8494, + 8502, + 8556, + 8551, + 0, + 8502, + 8511, + 8565, + 8556, + 0, + 8511, + 8514, + 8581, + 8565, + 0, + 8514, + 8516, + 8590, + 8581, + 0, + 8516, + 8520, + 8600, + 8590, + 0, + 8520, + 8525, + 8602, + 8600, + 0, + 8525, + 8528, + 8605, + 8602, + 0, + 8528, + 8531, + 8607, + 8605, + 0, + 8531, + 8543, + 8620, + 8607, + 0, + 8543, + 8554, + 8630, + 8620, + 0, + 8554, + 8558, + 8634, + 8630, + 0, + 8558, + 8562, + 8639, + 8634, + 0, + 8562, + 8567, + 8643, + 8639, + 0, + 8567, + 8569, + 8647, + 8643, + 0, + 8569, + 8573, + 8651, + 8647, + 0, + 8573, + 8577, + 8654, + 8651, + 0, + 8577, + 8579, + 8656, + 8654, + 0, + 8579, + 8578, + 8655, + 8656, + 0, + 8578, + 8575, + 8652, + 8655, + 0, + 8575, + 8574, + 8650, + 8652, + 0, + 8574, + 8570, + 8646, + 8650, + 0, + 8570, + 8566, + 8642, + 8646, + 0, + 8566, + 8561, + 8637, + 8642, + 0, + 8561, + 8557, + 8633, + 8637, + 0, + 8557, + 8553, + 8629, + 8633, + 0, + 8553, + 8549, + 8627, + 8629, + 0, + 8549, + 8548, + 8624, + 8627, + 0, + 8548, + 8539, + 8615, + 8624, + 0, + 8539, + 8538, + 8614, + 8615, + 0, + 8614, + 8618, + 8690, + 8688, + 0, + 8618, + 8628, + 8694, + 8690, + 0, + 8628, + 8635, + 8700, + 8694, + 0, + 8635, + 8641, + 8706, + 8700, + 0, + 8641, + 8648, + 8712, + 8706, + 0, + 8648, + 8657, + 8720, + 8712, + 0, + 8657, + 8660, + 8722, + 8720, + 0, + 8660, + 8663, + 8724, + 8722, + 0, + 8663, + 8665, + 8727, + 8724, + 0, + 8665, + 8667, + 8729, + 8727, + 0, + 8667, + 8670, + 8731, + 8729, + 0, + 8670, + 8672, + 8733, + 8731, + 0, + 8672, + 8671, + 8732, + 8733, + 0, + 8671, + 8669, + 8730, + 8732, + 0, + 8669, + 8666, + 8728, + 8730, + 0, + 8666, + 8664, + 8726, + 8728, + 0, + 8664, + 8662, + 8723, + 8726, + 0, + 8662, + 8658, + 8721, + 8723, + 0, + 8658, + 8653, + 8716, + 8721, + 0, + 8653, + 8644, + 8709, + 8716, + 0, + 8644, + 8638, + 8703, + 8709, + 0, + 8638, + 8613, + 8687, + 8703, + 0, + 8613, + 8610, + 8686, + 8687, + 0, + 8610, + 8606, + 8684, + 8686, + 0, + 8606, + 8603, + 8682, + 8684, + 0, + 8603, + 8601, + 8680, + 8682, + 0, + 8601, + 8597, + 8678, + 8680, + 0, + 8597, + 8585, + 8676, + 8678, + 0, + 8585, + 8572, + 8674, + 8676, + 0, + 8572, + 8563, + 8668, + 8674, + 0, + 8563, + 8555, + 8659, + 8668, + 0, + 8555, + 8550, + 8645, + 8659, + 0, + 8550, + 8546, + 8636, + 8645, + 0, + 8546, + 8544, + 8631, + 8636, + 0, + 8544, + 8540, + 8625, + 8631, + 0, + 8540, + 8537, + 8623, + 8625, + 0, + 8537, + 8534, + 8621, + 8623, + 0, + 8534, + 8530, + 8617, + 8621, + 0, + 8530, + 8524, + 8612, + 8617, + 0, + 8524, + 8519, + 8608, + 8612, + 0, + 8519, + 8517, + 8604, + 8608, + 0, + 8517, + 8503, + 8584, + 8604, + 0, + 8503, + 8510, + 8598, + 8584, + 0, + 8510, + 8512, + 8599, + 8598, + 0, + 8512, + 8521, + 8609, + 8599, + 0, + 8521, + 8523, + 8611, + 8609, + 0, + 8523, + 8527, + 8616, + 8611, + 0, + 8527, + 8532, + 8619, + 8616, + 0, + 8532, + 8536, + 8622, + 8619, + 0, + 8536, + 8541, + 8626, + 8622, + 0, + 8541, + 8545, + 8632, + 8626, + 0, + 8545, + 8547, + 8640, + 8632, + 0, + 8547, + 8551, + 8649, + 8640, + 0, + 8551, + 8556, + 8661, + 8649, + 0, + 8556, + 8565, + 8673, + 8661, + 0, + 8565, + 8581, + 8675, + 8673, + 0, + 8581, + 8590, + 8677, + 8675, + 0, + 8590, + 8600, + 8679, + 8677, + 0, + 8600, + 8602, + 8681, + 8679, + 0, + 8602, + 8605, + 8683, + 8681, + 0, + 8605, + 8607, + 8685, + 8683, + 0, + 8607, + 8620, + 8691, + 8685, + 0, + 8620, + 8630, + 8696, + 8691, + 0, + 8630, + 8634, + 8699, + 8696, + 0, + 8634, + 8639, + 8704, + 8699, + 0, + 8639, + 8643, + 8708, + 8704, + 0, + 8643, + 8647, + 8711, + 8708, + 0, + 8647, + 8651, + 8714, + 8711, + 0, + 8651, + 8654, + 8717, + 8714, + 0, + 8654, + 8656, + 8719, + 8717, + 0, + 8656, + 8655, + 8718, + 8719, + 0, + 8655, + 8652, + 8715, + 8718, + 0, + 8652, + 8650, + 8713, + 8715, + 0, + 8650, + 8646, + 8710, + 8713, + 0, + 8646, + 8642, + 8707, + 8710, + 0, + 8642, + 8637, + 8702, + 8707, + 0, + 8637, + 8633, + 8698, + 8702, + 0, + 8633, + 8629, + 8695, + 8698, + 0, + 8629, + 8627, + 8693, + 8695, + 0, + 8627, + 8624, + 8692, + 8693, + 0, + 8624, + 8615, + 8689, + 8692, + 0, + 8615, + 8614, + 8688, + 8689, + 0, + 8688, + 8690, + 8806, + 8799, + 0, + 8690, + 8694, + 8823, + 8806, + 0, + 8694, + 8700, + 8830, + 8823, + 0, + 8700, + 8706, + 8837, + 8830, + 0, + 8706, + 8712, + 8846, + 8837, + 0, + 8712, + 8720, + 8855, + 8846, + 0, + 8720, + 8722, + 8859, + 8855, + 0, + 8722, + 8724, + 8861, + 8859, + 0, + 8724, + 8727, + 8865, + 8861, + 0, + 8727, + 8729, + 8868, + 8865, + 0, + 8729, + 8731, + 8870, + 8868, + 0, + 8731, + 8733, + 8872, + 8870, + 0, + 8733, + 8732, + 8871, + 8872, + 0, + 8732, + 8730, + 8869, + 8871, + 0, + 8730, + 8728, + 8867, + 8869, + 0, + 8728, + 8726, + 8864, + 8867, + 0, + 8726, + 8723, + 8860, + 8864, + 0, + 8723, + 8721, + 8858, + 8860, + 0, + 8721, + 8716, + 8853, + 8858, + 0, + 8716, + 8709, + 8843, + 8853, + 0, + 8709, + 8703, + 8836, + 8843, + 0, + 8703, + 8687, + 8800, + 8836, + 0, + 8687, + 8686, + 8796, + 8800, + 0, + 8686, + 8684, + 8791, + 8796, + 0, + 8684, + 8682, + 8788, + 8791, + 0, + 8682, + 8680, + 8784, + 8788, + 0, + 8680, + 8678, + 8780, + 8784, + 0, + 8678, + 8676, + 8776, + 8780, + 0, + 8676, + 8674, + 8772, + 8776, + 0, + 8674, + 8668, + 8768, + 8772, + 0, + 8668, + 8659, + 8764, + 8768, + 0, + 8659, + 8645, + 8760, + 8764, + 0, + 8645, + 8636, + 8756, + 8760, + 0, + 8636, + 8631, + 8752, + 8756, + 0, + 8631, + 8625, + 8748, + 8752, + 0, + 8625, + 8623, + 8746, + 8748, + 0, + 8623, + 8621, + 8744, + 8746, + 0, + 8621, + 8617, + 8742, + 8744, + 0, + 8617, + 8612, + 8738, + 8742, + 0, + 8612, + 8608, + 8734, + 8738, + 0, + 8608, + 8604, + 8725, + 8734, + 0, + 8604, + 8584, + 8697, + 8725, + 0, + 8584, + 8598, + 8701, + 8697, + 0, + 8598, + 8599, + 8705, + 8701, + 0, + 8599, + 8609, + 8735, + 8705, + 0, + 8609, + 8611, + 8737, + 8735, + 0, + 8611, + 8616, + 8740, + 8737, + 0, + 8616, + 8619, + 8743, + 8740, + 0, + 8619, + 8622, + 8745, + 8743, + 0, + 8622, + 8626, + 8749, + 8745, + 0, + 8626, + 8632, + 8754, + 8749, + 0, + 8632, + 8640, + 8759, + 8754, + 0, + 8640, + 8649, + 8763, + 8759, + 0, + 8649, + 8661, + 8766, + 8763, + 0, + 8661, + 8673, + 8771, + 8766, + 0, + 8673, + 8675, + 8775, + 8771, + 0, + 8675, + 8677, + 8779, + 8775, + 0, + 8677, + 8679, + 8783, + 8779, + 0, + 8679, + 8681, + 8787, + 8783, + 0, + 8681, + 8683, + 8790, + 8787, + 0, + 8683, + 8685, + 8794, + 8790, + 0, + 8685, + 8691, + 8809, + 8794, + 0, + 8691, + 8696, + 8825, + 8809, + 0, + 8696, + 8699, + 8832, + 8825, + 0, + 8699, + 8704, + 8835, + 8832, + 0, + 8704, + 8708, + 8842, + 8835, + 0, + 8708, + 8711, + 8845, + 8842, + 0, + 8711, + 8714, + 8849, + 8845, + 0, + 8714, + 8717, + 8852, + 8849, + 0, + 8717, + 8719, + 8857, + 8852, + 0, + 8719, + 8718, + 8854, + 8857, + 0, + 8718, + 8715, + 8850, + 8854, + 0, + 8715, + 8713, + 8848, + 8850, + 0, + 8713, + 8710, + 8844, + 8848, + 0, + 8710, + 8707, + 8840, + 8844, + 0, + 8707, + 8702, + 8834, + 8840, + 0, + 8702, + 8698, + 8829, + 8834, + 0, + 8698, + 8695, + 8824, + 8829, + 0, + 8695, + 8693, + 8818, + 8824, + 0, + 8693, + 8692, + 8816, + 8818, + 0, + 8692, + 8689, + 8802, + 8816, + 0, + 8689, + 8688, + 8799, + 8802, + 0, + 8799, + 8806, + 8838, + 8826, + 0, + 8806, + 8823, + 8876, + 8838, + 0, + 8823, + 8830, + 8881, + 8876, + 0, + 8830, + 8837, + 8887, + 8881, + 0, + 8837, + 8846, + 8895, + 8887, + 0, + 8846, + 8855, + 8903, + 8895, + 0, + 8855, + 8859, + 8907, + 8903, + 0, + 8859, + 8861, + 8909, + 8907, + 0, + 8861, + 8865, + 8912, + 8909, + 0, + 8865, + 8868, + 8915, + 8912, + 0, + 8868, + 8870, + 8917, + 8915, + 0, + 8870, + 8872, + 8919, + 8917, + 0, + 8872, + 8871, + 8918, + 8919, + 0, + 8871, + 8869, + 8916, + 8918, + 0, + 8869, + 8867, + 8914, + 8916, + 0, + 8867, + 8864, + 8911, + 8914, + 0, + 8864, + 8860, + 8908, + 8911, + 0, + 8860, + 8858, + 8906, + 8908, + 0, + 8858, + 8853, + 8901, + 8906, + 0, + 8853, + 8843, + 8892, + 8901, + 0, + 8843, + 8836, + 8886, + 8892, + 0, + 8836, + 8800, + 8827, + 8886, + 0, + 8800, + 8796, + 8820, + 8827, + 0, + 8796, + 8791, + 8814, + 8820, + 0, + 8791, + 8788, + 8812, + 8814, + 0, + 8788, + 8784, + 8808, + 8812, + 0, + 8784, + 8780, + 8805, + 8808, + 0, + 8780, + 8776, + 8798, + 8805, + 0, + 8776, + 8772, + 8793, + 8798, + 0, + 8772, + 8768, + 8789, + 8793, + 0, + 8768, + 8764, + 8785, + 8789, + 0, + 8764, + 8760, + 8781, + 8785, + 0, + 8760, + 8756, + 8777, + 8781, + 0, + 8756, + 8752, + 8773, + 8777, + 0, + 8752, + 8748, + 8769, + 8773, + 0, + 8748, + 8746, + 8767, + 8769, + 0, + 8746, + 8744, + 8762, + 8767, + 0, + 8744, + 8742, + 8758, + 8762, + 0, + 8742, + 8738, + 8755, + 8758, + 0, + 8738, + 8734, + 8750, + 8755, + 0, + 8734, + 8725, + 8747, + 8750, + 0, + 8725, + 8697, + 8736, + 8747, + 0, + 8697, + 8701, + 8739, + 8736, + 0, + 8701, + 8705, + 8741, + 8739, + 0, + 8705, + 8735, + 8751, + 8741, + 0, + 8735, + 8737, + 8753, + 8751, + 0, + 8737, + 8740, + 8757, + 8753, + 0, + 8740, + 8743, + 8761, + 8757, + 0, + 8743, + 8745, + 8765, + 8761, + 0, + 8745, + 8749, + 8770, + 8765, + 0, + 8749, + 8754, + 8774, + 8770, + 0, + 8754, + 8759, + 8778, + 8774, + 0, + 8759, + 8763, + 8782, + 8778, + 0, + 8763, + 8766, + 8786, + 8782, + 0, + 8766, + 8771, + 8792, + 8786, + 0, + 8771, + 8775, + 8797, + 8792, + 0, + 8775, + 8779, + 8804, + 8797, + 0, + 8779, + 8783, + 8807, + 8804, + 0, + 8783, + 8787, + 8810, + 8807, + 0, + 8787, + 8790, + 8813, + 8810, + 0, + 8790, + 8794, + 8819, + 8813, + 0, + 8794, + 8809, + 8847, + 8819, + 0, + 8809, + 8825, + 8878, + 8847, + 0, + 8825, + 8832, + 8882, + 8878, + 0, + 8832, + 8835, + 8885, + 8882, + 0, + 8835, + 8842, + 8890, + 8885, + 0, + 8842, + 8845, + 8894, + 8890, + 0, + 8845, + 8849, + 8897, + 8894, + 0, + 8849, + 8852, + 8900, + 8897, + 0, + 8852, + 8857, + 8904, + 8900, + 0, + 8857, + 8854, + 8902, + 8904, + 0, + 8854, + 8850, + 8899, + 8902, + 0, + 8850, + 8848, + 8896, + 8899, + 0, + 8848, + 8844, + 8893, + 8896, + 0, + 8844, + 8840, + 8889, + 8893, + 0, + 8840, + 8834, + 8884, + 8889, + 0, + 8834, + 8829, + 8880, + 8884, + 0, + 8829, + 8824, + 8877, + 8880, + 0, + 8824, + 8818, + 8873, + 8877, + 0, + 8818, + 8816, + 8866, + 8873, + 0, + 8816, + 8802, + 8831, + 8866, + 0, + 8802, + 8799, + 8826, + 8831, + 0, + 8826, + 8838, + 8936, + 8933, + 0, + 8838, + 8876, + 8940, + 8936, + 0, + 8876, + 8881, + 8944, + 8940, + 0, + 8881, + 8887, + 8949, + 8944, + 0, + 8887, + 8895, + 8954, + 8949, + 0, + 8895, + 8903, + 8960, + 8954, + 0, + 8903, + 8907, + 8964, + 8960, + 0, + 8907, + 8909, + 8967, + 8964, + 0, + 8909, + 8912, + 8969, + 8967, + 0, + 8912, + 8915, + 8971, + 8969, + 0, + 8915, + 8917, + 8973, + 8971, + 0, + 8917, + 8919, + 8975, + 8973, + 0, + 8919, + 8918, + 8974, + 8975, + 0, + 8918, + 8916, + 8972, + 8974, + 0, + 8916, + 8914, + 8970, + 8972, + 0, + 8914, + 8911, + 8968, + 8970, + 0, + 8911, + 8908, + 8966, + 8968, + 0, + 8908, + 8906, + 8965, + 8966, + 0, + 8906, + 8901, + 8962, + 8965, + 0, + 8901, + 8892, + 8952, + 8962, + 0, + 8892, + 8886, + 8948, + 8952, + 0, + 8886, + 8827, + 8934, + 8948, + 0, + 8827, + 8820, + 8932, + 8934, + 0, + 8820, + 8814, + 8930, + 8932, + 0, + 8814, + 8812, + 8928, + 8930, + 0, + 8812, + 8808, + 8926, + 8928, + 0, + 8808, + 8805, + 8924, + 8926, + 0, + 8805, + 8798, + 8922, + 8924, + 0, + 8798, + 8793, + 8920, + 8922, + 0, + 8793, + 8789, + 8910, + 8920, + 0, + 8789, + 8785, + 8898, + 8910, + 0, + 8785, + 8781, + 8888, + 8898, + 0, + 8781, + 8777, + 8879, + 8888, + 0, + 8777, + 8773, + 8874, + 8879, + 0, + 8773, + 8769, + 8862, + 8874, + 0, + 8769, + 8767, + 8856, + 8862, + 0, + 8767, + 8762, + 8841, + 8856, + 0, + 8762, + 8758, + 8833, + 8841, + 0, + 8758, + 8755, + 8822, + 8833, + 0, + 8755, + 8750, + 8815, + 8822, + 0, + 8750, + 8747, + 8811, + 8815, + 0, + 8747, + 8736, + 8795, + 8811, + 0, + 8736, + 8739, + 8801, + 8795, + 0, + 8739, + 8741, + 8803, + 8801, + 0, + 8741, + 8751, + 8817, + 8803, + 0, + 8751, + 8753, + 8821, + 8817, + 0, + 8753, + 8757, + 8828, + 8821, + 0, + 8757, + 8761, + 8839, + 8828, + 0, + 8761, + 8765, + 8851, + 8839, + 0, + 8765, + 8770, + 8863, + 8851, + 0, + 8770, + 8774, + 8875, + 8863, + 0, + 8774, + 8778, + 8883, + 8875, + 0, + 8778, + 8782, + 8891, + 8883, + 0, + 8782, + 8786, + 8905, + 8891, + 0, + 8786, + 8792, + 8913, + 8905, + 0, + 8792, + 8797, + 8921, + 8913, + 0, + 8797, + 8804, + 8923, + 8921, + 0, + 8804, + 8807, + 8925, + 8923, + 0, + 8807, + 8810, + 8927, + 8925, + 0, + 8810, + 8813, + 8929, + 8927, + 0, + 8813, + 8819, + 8931, + 8929, + 0, + 8819, + 8847, + 8937, + 8931, + 0, + 8847, + 8878, + 8942, + 8937, + 0, + 8878, + 8882, + 8945, + 8942, + 0, + 8882, + 8885, + 8947, + 8945, + 0, + 8885, + 8890, + 8951, + 8947, + 0, + 8890, + 8894, + 8955, + 8951, + 0, + 8894, + 8897, + 8957, + 8955, + 0, + 8897, + 8900, + 8959, + 8957, + 0, + 8900, + 8904, + 8963, + 8959, + 0, + 8904, + 8902, + 8961, + 8963, + 0, + 8902, + 8899, + 8958, + 8961, + 0, + 8899, + 8896, + 8956, + 8958, + 0, + 8896, + 8893, + 8953, + 8956, + 0, + 8893, + 8889, + 8950, + 8953, + 0, + 8889, + 8884, + 8946, + 8950, + 0, + 8884, + 8880, + 8943, + 8946, + 0, + 8880, + 8877, + 8941, + 8943, + 0, + 8877, + 8873, + 8939, + 8941, + 0, + 8873, + 8866, + 8938, + 8939, + 0, + 8866, + 8831, + 8935, + 8938, + 0, + 8831, + 8826, + 8933, + 8935, + 0, + 8933, + 8936, + 9065, + 9057, + 0, + 8936, + 8940, + 9083, + 9065, + 0, + 8940, + 8944, + 9089, + 9083, + 0, + 8944, + 8949, + 9097, + 9089, + 0, + 8949, + 8954, + 9105, + 9097, + 0, + 8954, + 8960, + 9111, + 9105, + 0, + 8960, + 8964, + 9118, + 9111, + 0, + 8964, + 8967, + 9122, + 9118, + 0, + 8967, + 8969, + 9125, + 9122, + 0, + 8969, + 8971, + 9130, + 9125, + 0, + 8971, + 8973, + 9133, + 9130, + 0, + 8973, + 8975, + 9135, + 9133, + 0, + 8975, + 8974, + 9136, + 9135, + 0, + 8974, + 8972, + 9134, + 9136, + 0, + 8972, + 8970, + 9131, + 9134, + 0, + 8970, + 8968, + 9126, + 9131, + 0, + 8968, + 8966, + 9123, + 9126, + 0, + 8966, + 8965, + 9119, + 9123, + 0, + 8965, + 8962, + 9115, + 9119, + 0, + 8962, + 8952, + 9102, + 9115, + 0, + 8952, + 8948, + 9096, + 9102, + 0, + 8948, + 8934, + 9060, + 9096, + 0, + 8934, + 8932, + 9053, + 9060, + 0, + 8932, + 8930, + 9047, + 9053, + 0, + 8930, + 8928, + 9041, + 9047, + 0, + 8928, + 8926, + 9037, + 9041, + 0, + 8926, + 8924, + 9033, + 9037, + 0, + 8924, + 8922, + 9029, + 9033, + 0, + 8922, + 8920, + 9023, + 9029, + 0, + 8920, + 8910, + 9018, + 9023, + 0, + 8910, + 8898, + 9014, + 9018, + 0, + 8898, + 8888, + 9010, + 9014, + 0, + 8888, + 8879, + 9006, + 9010, + 0, + 8879, + 8874, + 9002, + 9006, + 0, + 8874, + 8862, + 8998, + 9002, + 0, + 8862, + 8856, + 8995, + 8998, + 0, + 8856, + 8841, + 8991, + 8995, + 0, + 8841, + 8833, + 8988, + 8991, + 0, + 8833, + 8822, + 8986, + 8988, + 0, + 8822, + 8815, + 8982, + 8986, + 0, + 8815, + 8811, + 8980, + 8982, + 0, + 8811, + 8795, + 8976, + 8980, + 0, + 8795, + 8801, + 8977, + 8976, + 0, + 8801, + 8803, + 8978, + 8977, + 0, + 8803, + 8817, + 8983, + 8978, + 0, + 8817, + 8821, + 8985, + 8983, + 0, + 8821, + 8828, + 8987, + 8985, + 0, + 8828, + 8839, + 8990, + 8987, + 0, + 8839, + 8851, + 8994, + 8990, + 0, + 8851, + 8863, + 8999, + 8994, + 0, + 8863, + 8875, + 9003, + 8999, + 0, + 8875, + 8883, + 9009, + 9003, + 0, + 8883, + 8891, + 9011, + 9009, + 0, + 8891, + 8905, + 9015, + 9011, + 0, + 8905, + 8913, + 9020, + 9015, + 0, + 8913, + 8921, + 9026, + 9020, + 0, + 8921, + 8923, + 9032, + 9026, + 0, + 8923, + 8925, + 9035, + 9032, + 0, + 8925, + 8927, + 9040, + 9035, + 0, + 8927, + 8929, + 9046, + 9040, + 0, + 8929, + 8931, + 9051, + 9046, + 0, + 8931, + 8937, + 9070, + 9051, + 0, + 8937, + 8942, + 9086, + 9070, + 0, + 8942, + 8945, + 9091, + 9086, + 0, + 8945, + 8947, + 9095, + 9091, + 0, + 8947, + 8951, + 9099, + 9095, + 0, + 8951, + 8955, + 9106, + 9099, + 0, + 8955, + 8957, + 9109, + 9106, + 0, + 8957, + 8959, + 9112, + 9109, + 0, + 8959, + 8963, + 9114, + 9112, + 0, + 8963, + 8961, + 9113, + 9114, + 0, + 8961, + 8958, + 9110, + 9113, + 0, + 8958, + 8956, + 9107, + 9110, + 0, + 8956, + 8953, + 9103, + 9107, + 0, + 8953, + 8950, + 9098, + 9103, + 0, + 8950, + 8946, + 9093, + 9098, + 0, + 8946, + 8943, + 9088, + 9093, + 0, + 8943, + 8941, + 9084, + 9088, + 0, + 8941, + 8939, + 9080, + 9084, + 0, + 8939, + 8938, + 9076, + 9080, + 0, + 8938, + 8935, + 9059, + 9076, + 0, + 8935, + 8933, + 9057, + 9059, + 0, + 9057, + 9065, + 9082, + 9075, + 0, + 9065, + 9083, + 9117, + 9082, + 0, + 9083, + 9089, + 9128, + 9117, + 0, + 9089, + 9097, + 9141, + 9128, + 0, + 9097, + 9105, + 9147, + 9141, + 0, + 9105, + 9111, + 9154, + 9147, + 0, + 9111, + 9118, + 9159, + 9154, + 0, + 9118, + 9122, + 9163, + 9159, + 0, + 9122, + 9125, + 9165, + 9163, + 0, + 9125, + 9130, + 9167, + 9165, + 0, + 9130, + 9133, + 9170, + 9167, + 0, + 9133, + 9135, + 9172, + 9170, + 0, + 9135, + 9136, + 9173, + 9172, + 0, + 9136, + 9134, + 9171, + 9173, + 0, + 9134, + 9131, + 9168, + 9171, + 0, + 9131, + 9126, + 9166, + 9168, + 0, + 9126, + 9123, + 9164, + 9166, + 0, + 9123, + 9119, + 9160, + 9164, + 0, + 9119, + 9115, + 9158, + 9160, + 0, + 9115, + 9102, + 9146, + 9158, + 0, + 9102, + 9096, + 9140, + 9146, + 0, + 9096, + 9060, + 9078, + 9140, + 0, + 9060, + 9053, + 9074, + 9078, + 0, + 9053, + 9047, + 9069, + 9074, + 0, + 9047, + 9041, + 9064, + 9069, + 0, + 9041, + 9037, + 9058, + 9064, + 0, + 9037, + 9033, + 9052, + 9058, + 0, + 9033, + 9029, + 9045, + 9052, + 0, + 9029, + 9023, + 9039, + 9045, + 0, + 9023, + 9018, + 9034, + 9039, + 0, + 9018, + 9014, + 9030, + 9034, + 0, + 9014, + 9010, + 9024, + 9030, + 0, + 9010, + 9006, + 9019, + 9024, + 0, + 9006, + 9002, + 9016, + 9019, + 0, + 9002, + 8998, + 9012, + 9016, + 0, + 8998, + 8995, + 9008, + 9012, + 0, + 8995, + 8991, + 9005, + 9008, + 0, + 8991, + 8988, + 9001, + 9005, + 0, + 8988, + 8986, + 8997, + 9001, + 0, + 8986, + 8982, + 8992, + 8997, + 0, + 8982, + 8980, + 8989, + 8992, + 0, + 8980, + 8976, + 8979, + 8989, + 0, + 8976, + 8977, + 8981, + 8979, + 0, + 8977, + 8978, + 8984, + 8981, + 0, + 8978, + 8983, + 8993, + 8984, + 0, + 8983, + 8985, + 8996, + 8993, + 0, + 8985, + 8987, + 9000, + 8996, + 0, + 8987, + 8990, + 9004, + 9000, + 0, + 8990, + 8994, + 9007, + 9004, + 0, + 8994, + 8999, + 9013, + 9007, + 0, + 8999, + 9003, + 9017, + 9013, + 0, + 9003, + 9009, + 9022, + 9017, + 0, + 9009, + 9011, + 9027, + 9022, + 0, + 9011, + 9015, + 9031, + 9027, + 0, + 9015, + 9020, + 9036, + 9031, + 0, + 9020, + 9026, + 9043, + 9036, + 0, + 9026, + 9032, + 9050, + 9043, + 0, + 9032, + 9035, + 9056, + 9050, + 0, + 9035, + 9040, + 9063, + 9056, + 0, + 9040, + 9046, + 9068, + 9063, + 0, + 9046, + 9051, + 9071, + 9068, + 0, + 9051, + 9070, + 9090, + 9071, + 0, + 9070, + 9086, + 9124, + 9090, + 0, + 9086, + 9091, + 9132, + 9124, + 0, + 9091, + 9095, + 9139, + 9132, + 0, + 9095, + 9099, + 9144, + 9139, + 0, + 9099, + 9106, + 9149, + 9144, + 0, + 9106, + 9109, + 9151, + 9149, + 0, + 9109, + 9112, + 9155, + 9151, + 0, + 9112, + 9114, + 9157, + 9155, + 0, + 9114, + 9113, + 9156, + 9157, + 0, + 9113, + 9110, + 9153, + 9156, + 0, + 9110, + 9107, + 9150, + 9153, + 0, + 9107, + 9103, + 9145, + 9150, + 0, + 9103, + 9098, + 9143, + 9145, + 0, + 9098, + 9093, + 9138, + 9143, + 0, + 9093, + 9088, + 9127, + 9138, + 0, + 9088, + 9084, + 9120, + 9127, + 0, + 9084, + 9080, + 9108, + 9120, + 0, + 9080, + 9076, + 9101, + 9108, + 0, + 9076, + 9059, + 9077, + 9101, + 0, + 9059, + 9057, + 9075, + 9077, + 0, + 9075, + 9082, + 9182, + 9179, + 0, + 9082, + 9117, + 9186, + 9182, + 0, + 9117, + 9128, + 9190, + 9186, + 0, + 9128, + 9141, + 9194, + 9190, + 0, + 9141, + 9147, + 9200, + 9194, + 0, + 9147, + 9154, + 9205, + 9200, + 0, + 9154, + 9159, + 9210, + 9205, + 0, + 9159, + 9163, + 9212, + 9210, + 0, + 9163, + 9165, + 9214, + 9212, + 0, + 9165, + 9167, + 9216, + 9214, + 0, + 9167, + 9170, + 9218, + 9216, + 0, + 9170, + 9172, + 9220, + 9218, + 0, + 9172, + 9173, + 9221, + 9220, + 0, + 9173, + 9171, + 9219, + 9221, + 0, + 9171, + 9168, + 9217, + 9219, + 0, + 9168, + 9166, + 9215, + 9217, + 0, + 9166, + 9164, + 9213, + 9215, + 0, + 9164, + 9160, + 9211, + 9213, + 0, + 9160, + 9158, + 9209, + 9211, + 0, + 9158, + 9146, + 9199, + 9209, + 0, + 9146, + 9140, + 9195, + 9199, + 0, + 9140, + 9078, + 9181, + 9195, + 0, + 9078, + 9074, + 9178, + 9181, + 0, + 9074, + 9069, + 9176, + 9178, + 0, + 9069, + 9064, + 9174, + 9176, + 0, + 9064, + 9058, + 9162, + 9174, + 0, + 9058, + 9052, + 9152, + 9162, + 0, + 9052, + 9045, + 9142, + 9152, + 0, + 9045, + 9039, + 9129, + 9142, + 0, + 9039, + 9034, + 9116, + 9129, + 0, + 9034, + 9030, + 9100, + 9116, + 0, + 9030, + 9024, + 9092, + 9100, + 0, + 9024, + 9019, + 9085, + 9092, + 0, + 9019, + 9016, + 9079, + 9085, + 0, + 9016, + 9012, + 9072, + 9079, + 0, + 9012, + 9008, + 9067, + 9072, + 0, + 9008, + 9005, + 9062, + 9067, + 0, + 9005, + 9001, + 9055, + 9062, + 0, + 9001, + 8997, + 9049, + 9055, + 0, + 8997, + 8992, + 9042, + 9049, + 0, + 8992, + 8989, + 9038, + 9042, + 0, + 8989, + 8979, + 9021, + 9038, + 0, + 8979, + 8981, + 9025, + 9021, + 0, + 8981, + 8984, + 9028, + 9025, + 0, + 8984, + 8993, + 9044, + 9028, + 0, + 8993, + 8996, + 9048, + 9044, + 0, + 8996, + 9000, + 9054, + 9048, + 0, + 9000, + 9004, + 9061, + 9054, + 0, + 9004, + 9007, + 9066, + 9061, + 0, + 9007, + 9013, + 9073, + 9066, + 0, + 9013, + 9017, + 9081, + 9073, + 0, + 9017, + 9022, + 9087, + 9081, + 0, + 9022, + 9027, + 9094, + 9087, + 0, + 9027, + 9031, + 9104, + 9094, + 0, + 9031, + 9036, + 9121, + 9104, + 0, + 9036, + 9043, + 9137, + 9121, + 0, + 9043, + 9050, + 9148, + 9137, + 0, + 9050, + 9056, + 9161, + 9148, + 0, + 9056, + 9063, + 9169, + 9161, + 0, + 9063, + 9068, + 9175, + 9169, + 0, + 9068, + 9071, + 9177, + 9175, + 0, + 9071, + 9090, + 9183, + 9177, + 0, + 9090, + 9124, + 9188, + 9183, + 0, + 9124, + 9132, + 9191, + 9188, + 0, + 9132, + 9139, + 9193, + 9191, + 0, + 9139, + 9144, + 9197, + 9193, + 0, + 9144, + 9149, + 9201, + 9197, + 0, + 9149, + 9151, + 9203, + 9201, + 0, + 9151, + 9155, + 9206, + 9203, + 0, + 9155, + 9157, + 9208, + 9206, + 0, + 9157, + 9156, + 9207, + 9208, + 0, + 9156, + 9153, + 9204, + 9207, + 0, + 9153, + 9150, + 9202, + 9204, + 0, + 9150, + 9145, + 9198, + 9202, + 0, + 9145, + 9143, + 9196, + 9198, + 0, + 9143, + 9138, + 9192, + 9196, + 0, + 9138, + 9127, + 9189, + 9192, + 0, + 9127, + 9120, + 9187, + 9189, + 0, + 9120, + 9108, + 9185, + 9187, + 0, + 9108, + 9101, + 9184, + 9185, + 0, + 9101, + 9077, + 9180, + 9184, + 0, + 9077, + 9075, + 9179, + 9180, + 0, + 9179, + 9182, + 9292, + 9285, + 0, + 9182, + 9186, + 9311, + 9292, + 0, + 9186, + 9190, + 9318, + 9311, + 0, + 9190, + 9194, + 9323, + 9318, + 0, + 9194, + 9200, + 9333, + 9323, + 0, + 9200, + 9205, + 9341, + 9333, + 0, + 9205, + 9210, + 9348, + 9341, + 0, + 9210, + 9212, + 9352, + 9348, + 0, + 9212, + 9214, + 9354, + 9352, + 0, + 9214, + 9216, + 9357, + 9354, + 0, + 9216, + 9218, + 9360, + 9357, + 0, + 9218, + 9220, + 9363, + 9360, + 0, + 9220, + 9221, + 9364, + 9363, + 0, + 9221, + 9219, + 9361, + 9364, + 0, + 9219, + 9217, + 9359, + 9361, + 0, + 9217, + 9215, + 9356, + 9359, + 0, + 9215, + 9213, + 9353, + 9356, + 0, + 9213, + 9211, + 9349, + 9353, + 0, + 9211, + 9209, + 9346, + 9349, + 0, + 9209, + 9199, + 9334, + 9346, + 0, + 9199, + 9195, + 9327, + 9334, + 0, + 9195, + 9181, + 9291, + 9327, + 0, + 9181, + 9178, + 9284, + 9291, + 0, + 9178, + 9176, + 9278, + 9284, + 0, + 9176, + 9174, + 9272, + 9278, + 0, + 9174, + 9162, + 9266, + 9272, + 0, + 9162, + 9152, + 9261, + 9266, + 0, + 9152, + 9142, + 9257, + 9261, + 0, + 9142, + 9129, + 9254, + 9257, + 0, + 9129, + 9116, + 9250, + 9254, + 0, + 9116, + 9100, + 9247, + 9250, + 0, + 9100, + 9092, + 9243, + 9247, + 0, + 9092, + 9085, + 9240, + 9243, + 0, + 9085, + 9079, + 9238, + 9240, + 0, + 9079, + 9072, + 9236, + 9238, + 0, + 9072, + 9067, + 9235, + 9236, + 0, + 9067, + 9062, + 9233, + 9235, + 0, + 9062, + 9055, + 9231, + 9233, + 0, + 9055, + 9049, + 9229, + 9231, + 0, + 9049, + 9042, + 9226, + 9229, + 0, + 9042, + 9038, + 9225, + 9226, + 0, + 9038, + 9021, + 9222, + 9225, + 0, + 9021, + 9025, + 9223, + 9222, + 0, + 9025, + 9028, + 9224, + 9223, + 0, + 9028, + 9044, + 9227, + 9224, + 0, + 9044, + 9048, + 9228, + 9227, + 0, + 9048, + 9054, + 9230, + 9228, + 0, + 9054, + 9061, + 9232, + 9230, + 0, + 9061, + 9066, + 9234, + 9232, + 0, + 9066, + 9073, + 9237, + 9234, + 0, + 9073, + 9081, + 9239, + 9237, + 0, + 9081, + 9087, + 9241, + 9239, + 0, + 9087, + 9094, + 9244, + 9241, + 0, + 9094, + 9104, + 9248, + 9244, + 0, + 9104, + 9121, + 9251, + 9248, + 0, + 9121, + 9137, + 9256, + 9251, + 0, + 9137, + 9148, + 9260, + 9256, + 0, + 9148, + 9161, + 9265, + 9260, + 0, + 9161, + 9169, + 9271, + 9265, + 0, + 9169, + 9175, + 9277, + 9271, + 0, + 9175, + 9177, + 9282, + 9277, + 0, + 9177, + 9183, + 9299, + 9282, + 0, + 9183, + 9188, + 9314, + 9299, + 0, + 9188, + 9191, + 9321, + 9314, + 0, + 9191, + 9193, + 9325, + 9321, + 0, + 9193, + 9197, + 9330, + 9325, + 0, + 9197, + 9201, + 9335, + 9330, + 0, + 9201, + 9203, + 9339, + 9335, + 0, + 9203, + 9206, + 9343, + 9339, + 0, + 9206, + 9208, + 9345, + 9343, + 0, + 9208, + 9207, + 9344, + 9345, + 0, + 9207, + 9204, + 9340, + 9344, + 0, + 9204, + 9202, + 9337, + 9340, + 0, + 9202, + 9198, + 9332, + 9337, + 0, + 9198, + 9196, + 9329, + 9332, + 0, + 9196, + 9192, + 9322, + 9329, + 0, + 9192, + 9189, + 9317, + 9322, + 0, + 9189, + 9187, + 9313, + 9317, + 0, + 9187, + 9185, + 9307, + 9313, + 0, + 9185, + 9184, + 9305, + 9307, + 0, + 9184, + 9180, + 9287, + 9305, + 0, + 9180, + 9179, + 9285, + 9287, + 0, + 9285, + 9292, + 9383, + 9378, + 0, + 9292, + 9311, + 9394, + 9383, + 0, + 9311, + 9318, + 9398, + 9394, + 0, + 9318, + 9323, + 9403, + 9398, + 0, + 9323, + 9333, + 9411, + 9403, + 0, + 9333, + 9341, + 9420, + 9411, + 0, + 9341, + 9348, + 9427, + 9420, + 0, + 9348, + 9352, + 9432, + 9427, + 0, + 9352, + 9354, + 9435, + 9432, + 0, + 9354, + 9357, + 9440, + 9435, + 0, + 9357, + 9360, + 9443, + 9440, + 0, + 9360, + 9363, + 9446, + 9443, + 0, + 9363, + 9364, + 9447, + 9446, + 0, + 9364, + 9361, + 9445, + 9447, + 0, + 9361, + 9359, + 9441, + 9445, + 0, + 9359, + 9356, + 9437, + 9441, + 0, + 9356, + 9353, + 9434, + 9437, + 0, + 9353, + 9349, + 9428, + 9434, + 0, + 9349, + 9346, + 9425, + 9428, + 0, + 9346, + 9334, + 9413, + 9425, + 0, + 9334, + 9327, + 9405, + 9413, + 0, + 9327, + 9291, + 9380, + 9405, + 0, + 9291, + 9284, + 9375, + 9380, + 0, + 9284, + 9278, + 9371, + 9375, + 0, + 9278, + 9272, + 9368, + 9371, + 0, + 9272, + 9266, + 9362, + 9368, + 0, + 9266, + 9261, + 9350, + 9362, + 0, + 9261, + 9257, + 9338, + 9350, + 0, + 9257, + 9254, + 9326, + 9338, + 0, + 9254, + 9250, + 9316, + 9326, + 0, + 9250, + 9247, + 9309, + 9316, + 0, + 9247, + 9243, + 9303, + 9309, + 0, + 9243, + 9240, + 9300, + 9303, + 0, + 9240, + 9238, + 9295, + 9300, + 0, + 9238, + 9236, + 9288, + 9295, + 0, + 9236, + 9235, + 9281, + 9288, + 0, + 9235, + 9233, + 9276, + 9281, + 0, + 9233, + 9231, + 9270, + 9276, + 0, + 9231, + 9229, + 9264, + 9270, + 0, + 9229, + 9226, + 9258, + 9264, + 0, + 9226, + 9225, + 9255, + 9258, + 0, + 9225, + 9222, + 9242, + 9255, + 0, + 9222, + 9223, + 9245, + 9242, + 0, + 9223, + 9224, + 9246, + 9245, + 0, + 9224, + 9227, + 9259, + 9246, + 0, + 9227, + 9228, + 9262, + 9259, + 0, + 9228, + 9230, + 9267, + 9262, + 0, + 9230, + 9232, + 9273, + 9267, + 0, + 9232, + 9234, + 9280, + 9273, + 0, + 9234, + 9237, + 9290, + 9280, + 0, + 9237, + 9239, + 9296, + 9290, + 0, + 9239, + 9241, + 9301, + 9296, + 0, + 9241, + 9244, + 9306, + 9301, + 0, + 9244, + 9248, + 9310, + 9306, + 0, + 9248, + 9251, + 9320, + 9310, + 0, + 9251, + 9256, + 9331, + 9320, + 0, + 9256, + 9260, + 9347, + 9331, + 0, + 9260, + 9265, + 9358, + 9347, + 0, + 9265, + 9271, + 9367, + 9358, + 0, + 9271, + 9277, + 9370, + 9367, + 0, + 9277, + 9282, + 9374, + 9370, + 0, + 9282, + 9299, + 9388, + 9374, + 0, + 9299, + 9314, + 9396, + 9388, + 0, + 9314, + 9321, + 9400, + 9396, + 0, + 9321, + 9325, + 9404, + 9400, + 0, + 9325, + 9330, + 9409, + 9404, + 0, + 9330, + 9335, + 9414, + 9409, + 0, + 9335, + 9339, + 9418, + 9414, + 0, + 9339, + 9343, + 9422, + 9418, + 0, + 9343, + 9345, + 9423, + 9422, + 0, + 9345, + 9344, + 9421, + 9423, + 0, + 9344, + 9340, + 9419, + 9421, + 0, + 9340, + 9337, + 9416, + 9419, + 0, + 9337, + 9332, + 9410, + 9416, + 0, + 9332, + 9329, + 9407, + 9410, + 0, + 9329, + 9322, + 9402, + 9407, + 0, + 9322, + 9317, + 9397, + 9402, + 0, + 9317, + 9313, + 9395, + 9397, + 0, + 9313, + 9307, + 9392, + 9395, + 0, + 9307, + 9305, + 9391, + 9392, + 0, + 9305, + 9287, + 9379, + 9391, + 0, + 9287, + 9285, + 9378, + 9379, + 0, + 9378, + 9383, + 9390, + 9386, + 0, + 9383, + 9394, + 9406, + 9390, + 0, + 9394, + 9398, + 9417, + 9406, + 0, + 9398, + 9403, + 9429, + 9417, + 0, + 9403, + 9411, + 9439, + 9429, + 0, + 9411, + 9420, + 9451, + 9439, + 0, + 9420, + 9427, + 9456, + 9451, + 0, + 9427, + 9432, + 9458, + 9456, + 0, + 9432, + 9435, + 9460, + 9458, + 0, + 9435, + 9440, + 9462, + 9460, + 0, + 9440, + 9443, + 9464, + 9462, + 0, + 9443, + 9446, + 9466, + 9464, + 0, + 9446, + 9447, + 9467, + 9466, + 0, + 9447, + 9445, + 9465, + 9467, + 0, + 9445, + 9441, + 9463, + 9465, + 0, + 9441, + 9437, + 9461, + 9463, + 0, + 9437, + 9434, + 9459, + 9461, + 0, + 9434, + 9428, + 9457, + 9459, + 0, + 9428, + 9425, + 9455, + 9457, + 0, + 9425, + 9413, + 9442, + 9455, + 0, + 9413, + 9405, + 9431, + 9442, + 0, + 9405, + 9380, + 9389, + 9431, + 0, + 9380, + 9375, + 9385, + 9389, + 0, + 9375, + 9371, + 9382, + 9385, + 0, + 9371, + 9368, + 9377, + 9382, + 0, + 9368, + 9362, + 9373, + 9377, + 0, + 9362, + 9350, + 9369, + 9373, + 0, + 9350, + 9338, + 9365, + 9369, + 0, + 9338, + 9326, + 9351, + 9365, + 0, + 9326, + 9316, + 9336, + 9351, + 0, + 9316, + 9309, + 9324, + 9336, + 0, + 9309, + 9303, + 9315, + 9324, + 0, + 9303, + 9300, + 9308, + 9315, + 0, + 9300, + 9295, + 9302, + 9308, + 0, + 9295, + 9288, + 9297, + 9302, + 0, + 9288, + 9281, + 9294, + 9297, + 0, + 9281, + 9276, + 9289, + 9294, + 0, + 9276, + 9270, + 9283, + 9289, + 0, + 9270, + 9264, + 9275, + 9283, + 0, + 9264, + 9258, + 9268, + 9275, + 0, + 9258, + 9255, + 9263, + 9268, + 0, + 9255, + 9242, + 9249, + 9263, + 0, + 9242, + 9245, + 9252, + 9249, + 0, + 9245, + 9246, + 9253, + 9252, + 0, + 9246, + 9259, + 9269, + 9253, + 0, + 9259, + 9262, + 9274, + 9269, + 0, + 9262, + 9267, + 9279, + 9274, + 0, + 9267, + 9273, + 9286, + 9279, + 0, + 9273, + 9280, + 9293, + 9286, + 0, + 9280, + 9290, + 9298, + 9293, + 0, + 9290, + 9296, + 9304, + 9298, + 0, + 9296, + 9301, + 9312, + 9304, + 0, + 9301, + 9306, + 9319, + 9312, + 0, + 9306, + 9310, + 9328, + 9319, + 0, + 9310, + 9320, + 9342, + 9328, + 0, + 9320, + 9331, + 9355, + 9342, + 0, + 9331, + 9347, + 9366, + 9355, + 0, + 9347, + 9358, + 9372, + 9366, + 0, + 9358, + 9367, + 9376, + 9372, + 0, + 9367, + 9370, + 9381, + 9376, + 0, + 9370, + 9374, + 9384, + 9381, + 0, + 9374, + 9388, + 9393, + 9384, + 0, + 9388, + 9396, + 9412, + 9393, + 0, + 9396, + 9400, + 9424, + 9412, + 0, + 9400, + 9404, + 9430, + 9424, + 0, + 9404, + 9409, + 9436, + 9430, + 0, + 9409, + 9414, + 9444, + 9436, + 0, + 9414, + 9418, + 9449, + 9444, + 0, + 9418, + 9422, + 9453, + 9449, + 0, + 9422, + 9423, + 9454, + 9453, + 0, + 9423, + 9421, + 9452, + 9454, + 0, + 9421, + 9419, + 9450, + 9452, + 0, + 9419, + 9416, + 9448, + 9450, + 0, + 9416, + 9410, + 9438, + 9448, + 0, + 9410, + 9407, + 9433, + 9438, + 0, + 9407, + 9402, + 9426, + 9433, + 0, + 9402, + 9397, + 9415, + 9426, + 0, + 9397, + 9395, + 9408, + 9415, + 0, + 9395, + 9392, + 9401, + 9408, + 0, + 9392, + 9391, + 9399, + 9401, + 0, + 9391, + 9379, + 9387, + 9399, + 0, + 9379, + 9378, + 9386, + 9387, + 0, + 9386, + 9390, + 9525, + 9519, + 0, + 9390, + 9406, + 9539, + 9525, + 0, + 9406, + 9417, + 9547, + 9539, + 0, + 9417, + 9429, + 9553, + 9547, + 0, + 9429, + 9439, + 9562, + 9553, + 0, + 9439, + 9451, + 9568, + 9562, + 0, + 9451, + 9456, + 9577, + 9568, + 0, + 9456, + 9458, + 9580, + 9577, + 0, + 9458, + 9460, + 9585, + 9580, + 0, + 9460, + 9462, + 9587, + 9585, + 0, + 9462, + 9464, + 9589, + 9587, + 0, + 9464, + 9466, + 9592, + 9589, + 0, + 9466, + 9467, + 9593, + 9592, + 0, + 9467, + 9465, + 9590, + 9593, + 0, + 9465, + 9463, + 9588, + 9590, + 0, + 9463, + 9461, + 9586, + 9588, + 0, + 9461, + 9459, + 9583, + 9586, + 0, + 9459, + 9457, + 9579, + 9583, + 0, + 9457, + 9455, + 9576, + 9579, + 0, + 9455, + 9442, + 9564, + 9576, + 0, + 9442, + 9431, + 9556, + 9564, + 0, + 9431, + 9389, + 9524, + 9556, + 0, + 9389, + 9385, + 9518, + 9524, + 0, + 9385, + 9382, + 9514, + 9518, + 0, + 9382, + 9377, + 9510, + 9514, + 0, + 9377, + 9373, + 9506, + 9510, + 0, + 9373, + 9369, + 9502, + 9506, + 0, + 9369, + 9365, + 9499, + 9502, + 0, + 9365, + 9351, + 9497, + 9499, + 0, + 9351, + 9336, + 9495, + 9497, + 0, + 9336, + 9324, + 9491, + 9495, + 0, + 9324, + 9315, + 9488, + 9491, + 0, + 9315, + 9308, + 9486, + 9488, + 0, + 9308, + 9302, + 9484, + 9486, + 0, + 9302, + 9297, + 9482, + 9484, + 0, + 9297, + 9294, + 9481, + 9482, + 0, + 9294, + 9289, + 9479, + 9481, + 0, + 9289, + 9283, + 9477, + 9479, + 0, + 9283, + 9275, + 9475, + 9477, + 0, + 9275, + 9268, + 9472, + 9475, + 0, + 9268, + 9263, + 9471, + 9472, + 0, + 9263, + 9249, + 9468, + 9471, + 0, + 9249, + 9252, + 9469, + 9468, + 0, + 9252, + 9253, + 9470, + 9469, + 0, + 9253, + 9269, + 9473, + 9470, + 0, + 9269, + 9274, + 9474, + 9473, + 0, + 9274, + 9279, + 9476, + 9474, + 0, + 9279, + 9286, + 9478, + 9476, + 0, + 9286, + 9293, + 9480, + 9478, + 0, + 9293, + 9298, + 9483, + 9480, + 0, + 9298, + 9304, + 9485, + 9483, + 0, + 9304, + 9312, + 9487, + 9485, + 0, + 9312, + 9319, + 9489, + 9487, + 0, + 9319, + 9328, + 9492, + 9489, + 0, + 9328, + 9342, + 9496, + 9492, + 0, + 9342, + 9355, + 9498, + 9496, + 0, + 9355, + 9366, + 9501, + 9498, + 0, + 9366, + 9372, + 9505, + 9501, + 0, + 9372, + 9376, + 9509, + 9505, + 0, + 9376, + 9381, + 9512, + 9509, + 0, + 9381, + 9384, + 9516, + 9512, + 0, + 9384, + 9393, + 9530, + 9516, + 0, + 9393, + 9412, + 9544, + 9530, + 0, + 9412, + 9424, + 9551, + 9544, + 0, + 9424, + 9430, + 9555, + 9551, + 0, + 9430, + 9436, + 9560, + 9555, + 0, + 9436, + 9444, + 9565, + 9560, + 0, + 9444, + 9449, + 9569, + 9565, + 0, + 9449, + 9453, + 9573, + 9569, + 0, + 9453, + 9454, + 9574, + 9573, + 0, + 9454, + 9452, + 9572, + 9574, + 0, + 9452, + 9450, + 9570, + 9572, + 0, + 9450, + 9448, + 9567, + 9570, + 0, + 9448, + 9438, + 9563, + 9567, + 0, + 9438, + 9433, + 9557, + 9563, + 0, + 9433, + 9426, + 9552, + 9557, + 0, + 9426, + 9415, + 9545, + 9552, + 0, + 9415, + 9408, + 9542, + 9545, + 0, + 9408, + 9401, + 9536, + 9542, + 0, + 9401, + 9399, + 9533, + 9536, + 0, + 9399, + 9387, + 9521, + 9533, + 0, + 9387, + 9386, + 9519, + 9521, + 0, + 9519, + 9525, + 9616, + 9611, + 0, + 9525, + 9539, + 9627, + 9616, + 0, + 9539, + 9547, + 9633, + 9627, + 0, + 9547, + 9553, + 9638, + 9633, + 0, + 9553, + 9562, + 9645, + 9638, + 0, + 9562, + 9568, + 9651, + 9645, + 0, + 9568, + 9577, + 9660, + 9651, + 0, + 9577, + 9580, + 9663, + 9660, + 0, + 9580, + 9585, + 9666, + 9663, + 0, + 9585, + 9587, + 9669, + 9666, + 0, + 9587, + 9589, + 9671, + 9669, + 0, + 9589, + 9592, + 9673, + 9671, + 0, + 9592, + 9593, + 9674, + 9673, + 0, + 9593, + 9590, + 9672, + 9674, + 0, + 9590, + 9588, + 9670, + 9672, + 0, + 9588, + 9586, + 9668, + 9670, + 0, + 9586, + 9583, + 9664, + 9668, + 0, + 9583, + 9579, + 9662, + 9664, + 0, + 9579, + 9576, + 9659, + 9662, + 0, + 9576, + 9564, + 9647, + 9659, + 0, + 9564, + 9556, + 9640, + 9647, + 0, + 9556, + 9524, + 9615, + 9640, + 0, + 9524, + 9518, + 9610, + 9615, + 0, + 9518, + 9514, + 9606, + 9610, + 0, + 9514, + 9510, + 9602, + 9606, + 0, + 9510, + 9506, + 9599, + 9602, + 0, + 9506, + 9502, + 9596, + 9599, + 0, + 9502, + 9499, + 9584, + 9596, + 0, + 9499, + 9497, + 9575, + 9584, + 0, + 9497, + 9495, + 9559, + 9575, + 0, + 9495, + 9491, + 9549, + 9559, + 0, + 9491, + 9488, + 9541, + 9549, + 0, + 9488, + 9486, + 9535, + 9541, + 0, + 9486, + 9484, + 9531, + 9535, + 0, + 9484, + 9482, + 9528, + 9531, + 0, + 9482, + 9481, + 9523, + 9528, + 0, + 9481, + 9479, + 9517, + 9523, + 0, + 9479, + 9477, + 9513, + 9517, + 0, + 9477, + 9475, + 9508, + 9513, + 0, + 9475, + 9472, + 9503, + 9508, + 0, + 9472, + 9471, + 9500, + 9503, + 0, + 9471, + 9468, + 9490, + 9500, + 0, + 9468, + 9469, + 9493, + 9490, + 0, + 9469, + 9470, + 9494, + 9493, + 0, + 9470, + 9473, + 9504, + 9494, + 0, + 9473, + 9474, + 9507, + 9504, + 0, + 9474, + 9476, + 9511, + 9507, + 0, + 9476, + 9478, + 9515, + 9511, + 0, + 9478, + 9480, + 9522, + 9515, + 0, + 9480, + 9483, + 9529, + 9522, + 0, + 9483, + 9485, + 9532, + 9529, + 0, + 9485, + 9487, + 9537, + 9532, + 0, + 9487, + 9489, + 9543, + 9537, + 0, + 9489, + 9492, + 9550, + 9543, + 0, + 9492, + 9496, + 9561, + 9550, + 0, + 9496, + 9498, + 9578, + 9561, + 0, + 9498, + 9501, + 9591, + 9578, + 0, + 9501, + 9505, + 9597, + 9591, + 0, + 9505, + 9509, + 9601, + 9597, + 0, + 9509, + 9512, + 9605, + 9601, + 0, + 9512, + 9516, + 9609, + 9605, + 0, + 9516, + 9530, + 9620, + 9609, + 0, + 9530, + 9544, + 9631, + 9620, + 0, + 9544, + 9551, + 9635, + 9631, + 0, + 9551, + 9555, + 9639, + 9635, + 0, + 9555, + 9560, + 9644, + 9639, + 0, + 9560, + 9565, + 9648, + 9644, + 0, + 9565, + 9569, + 9652, + 9648, + 0, + 9569, + 9573, + 9655, + 9652, + 0, + 9573, + 9574, + 9656, + 9655, + 0, + 9574, + 9572, + 9654, + 9656, + 0, + 9572, + 9570, + 9653, + 9654, + 0, + 9570, + 9567, + 9649, + 9653, + 0, + 9567, + 9563, + 9646, + 9649, + 0, + 9563, + 9557, + 9641, + 9646, + 0, + 9557, + 9552, + 9637, + 9641, + 0, + 9552, + 9545, + 9632, + 9637, + 0, + 9545, + 9542, + 9628, + 9632, + 0, + 9542, + 9536, + 9625, + 9628, + 0, + 9536, + 9533, + 9623, + 9625, + 0, + 9533, + 9521, + 9612, + 9623, + 0, + 9521, + 9519, + 9611, + 9612, + 0, + 9611, + 9616, + 9667, + 9658, + 0, + 9616, + 9627, + 9678, + 9667, + 0, + 9627, + 9633, + 9682, + 9678, + 0, + 9633, + 9638, + 9685, + 9682, + 0, + 9638, + 9645, + 9690, + 9685, + 0, + 9645, + 9651, + 9695, + 9690, + 0, + 9651, + 9660, + 9702, + 9695, + 0, + 9660, + 9663, + 9705, + 9702, + 0, + 9663, + 9666, + 9707, + 9705, + 0, + 9666, + 9669, + 9709, + 9707, + 0, + 9669, + 9671, + 9711, + 9709, + 0, + 9671, + 9673, + 9714, + 9711, + 0, + 9673, + 9674, + 9715, + 9714, + 0, + 9674, + 9672, + 9713, + 9715, + 0, + 9672, + 9670, + 9710, + 9713, + 0, + 9670, + 9668, + 9708, + 9710, + 0, + 9668, + 9664, + 9706, + 9708, + 0, + 9664, + 9662, + 9704, + 9706, + 0, + 9662, + 9659, + 9701, + 9704, + 0, + 9659, + 9647, + 9692, + 9701, + 0, + 9647, + 9640, + 9687, + 9692, + 0, + 9640, + 9615, + 9665, + 9687, + 0, + 9615, + 9610, + 9657, + 9665, + 0, + 9610, + 9606, + 9643, + 9657, + 0, + 9606, + 9602, + 9636, + 9643, + 0, + 9602, + 9599, + 9630, + 9636, + 0, + 9599, + 9596, + 9626, + 9630, + 0, + 9596, + 9584, + 9622, + 9626, + 0, + 9584, + 9575, + 9619, + 9622, + 0, + 9575, + 9559, + 9617, + 9619, + 0, + 9559, + 9549, + 9613, + 9617, + 0, + 9549, + 9541, + 9607, + 9613, + 0, + 9541, + 9535, + 9603, + 9607, + 0, + 9535, + 9531, + 9598, + 9603, + 0, + 9531, + 9528, + 9594, + 9598, + 0, + 9528, + 9523, + 9582, + 9594, + 0, + 9523, + 9517, + 9571, + 9582, + 0, + 9517, + 9513, + 9558, + 9571, + 0, + 9513, + 9508, + 9548, + 9558, + 0, + 9508, + 9503, + 9538, + 9548, + 0, + 9503, + 9500, + 9534, + 9538, + 0, + 9500, + 9490, + 9520, + 9534, + 0, + 9490, + 9493, + 9526, + 9520, + 0, + 9493, + 9494, + 9527, + 9526, + 0, + 9494, + 9504, + 9540, + 9527, + 0, + 9504, + 9507, + 9546, + 9540, + 0, + 9507, + 9511, + 9554, + 9546, + 0, + 9511, + 9515, + 9566, + 9554, + 0, + 9515, + 9522, + 9581, + 9566, + 0, + 9522, + 9529, + 9595, + 9581, + 0, + 9529, + 9532, + 9600, + 9595, + 0, + 9532, + 9537, + 9604, + 9600, + 0, + 9537, + 9543, + 9608, + 9604, + 0, + 9543, + 9550, + 9614, + 9608, + 0, + 9550, + 9561, + 9618, + 9614, + 0, + 9561, + 9578, + 9621, + 9618, + 0, + 9578, + 9591, + 9624, + 9621, + 0, + 9591, + 9597, + 9629, + 9624, + 0, + 9597, + 9601, + 9634, + 9629, + 0, + 9601, + 9605, + 9642, + 9634, + 0, + 9605, + 9609, + 9650, + 9642, + 0, + 9609, + 9620, + 9675, + 9650, + 0, + 9620, + 9631, + 9680, + 9675, + 0, + 9631, + 9635, + 9683, + 9680, + 0, + 9635, + 9639, + 9686, + 9683, + 0, + 9639, + 9644, + 9689, + 9686, + 0, + 9644, + 9648, + 9693, + 9689, + 0, + 9648, + 9652, + 9696, + 9693, + 0, + 9652, + 9655, + 9699, + 9696, + 0, + 9655, + 9656, + 9700, + 9699, + 0, + 9656, + 9654, + 9698, + 9700, + 0, + 9654, + 9653, + 9697, + 9698, + 0, + 9653, + 9649, + 9694, + 9697, + 0, + 9649, + 9646, + 9691, + 9694, + 0, + 9646, + 9641, + 9688, + 9691, + 0, + 9641, + 9637, + 9684, + 9688, + 0, + 9637, + 9632, + 9681, + 9684, + 0, + 9632, + 9628, + 9679, + 9681, + 0, + 9628, + 9625, + 9677, + 9679, + 0, + 9625, + 9623, + 9676, + 9677, + 0, + 9623, + 9612, + 9661, + 9676, + 0, + 9612, + 9611, + 9658, + 9661, + 0, + 9658, + 9667, + 9770, + 9765, + 0, + 9667, + 9678, + 9782, + 9770, + 0, + 9678, + 9682, + 9788, + 9782, + 0, + 9682, + 9685, + 9792, + 9788, + 0, + 9685, + 9690, + 9798, + 9792, + 0, + 9690, + 9695, + 9804, + 9798, + 0, + 9695, + 9702, + 9812, + 9804, + 0, + 9702, + 9705, + 9815, + 9812, + 0, + 9705, + 9707, + 9818, + 9815, + 0, + 9707, + 9709, + 9820, + 9818, + 0, + 9709, + 9711, + 9823, + 9820, + 0, + 9711, + 9714, + 9825, + 9823, + 0, + 9714, + 9715, + 9826, + 9825, + 0, + 9715, + 9713, + 9824, + 9826, + 0, + 9713, + 9710, + 9822, + 9824, + 0, + 9710, + 9708, + 9819, + 9822, + 0, + 9708, + 9706, + 9817, + 9819, + 0, + 9706, + 9704, + 9814, + 9817, + 0, + 9704, + 9701, + 9811, + 9814, + 0, + 9701, + 9692, + 9801, + 9811, + 0, + 9692, + 9687, + 9796, + 9801, + 0, + 9687, + 9665, + 9769, + 9796, + 0, + 9665, + 9657, + 9766, + 9769, + 0, + 9657, + 9643, + 9761, + 9766, + 0, + 9643, + 9636, + 9758, + 9761, + 0, + 9636, + 9630, + 9754, + 9758, + 0, + 9630, + 9626, + 9750, + 9754, + 0, + 9626, + 9622, + 9746, + 9750, + 0, + 9622, + 9619, + 9743, + 9746, + 0, + 9619, + 9617, + 9741, + 9743, + 0, + 9617, + 9613, + 9738, + 9741, + 0, + 9613, + 9607, + 9735, + 9738, + 0, + 9607, + 9603, + 9732, + 9735, + 0, + 9603, + 9598, + 9730, + 9732, + 0, + 9598, + 9594, + 9728, + 9730, + 0, + 9594, + 9582, + 9727, + 9728, + 0, + 9582, + 9571, + 9725, + 9727, + 0, + 9571, + 9558, + 9723, + 9725, + 0, + 9558, + 9548, + 9721, + 9723, + 0, + 9548, + 9538, + 9718, + 9721, + 0, + 9538, + 9534, + 9717, + 9718, + 0, + 9534, + 9520, + 9703, + 9717, + 0, + 9520, + 9526, + 9712, + 9703, + 0, + 9526, + 9527, + 9716, + 9712, + 0, + 9527, + 9540, + 9719, + 9716, + 0, + 9540, + 9546, + 9720, + 9719, + 0, + 9546, + 9554, + 9722, + 9720, + 0, + 9554, + 9566, + 9724, + 9722, + 0, + 9566, + 9581, + 9726, + 9724, + 0, + 9581, + 9595, + 9729, + 9726, + 0, + 9595, + 9600, + 9731, + 9729, + 0, + 9600, + 9604, + 9733, + 9731, + 0, + 9604, + 9608, + 9736, + 9733, + 0, + 9608, + 9614, + 9740, + 9736, + 0, + 9614, + 9618, + 9742, + 9740, + 0, + 9618, + 9621, + 9745, + 9742, + 0, + 9621, + 9624, + 9749, + 9745, + 0, + 9624, + 9629, + 9753, + 9749, + 0, + 9629, + 9634, + 9756, + 9753, + 0, + 9634, + 9642, + 9760, + 9756, + 0, + 9642, + 9650, + 9763, + 9760, + 0, + 9650, + 9675, + 9775, + 9763, + 0, + 9675, + 9680, + 9786, + 9775, + 0, + 9680, + 9683, + 9789, + 9786, + 0, + 9683, + 9686, + 9794, + 9789, + 0, + 9686, + 9689, + 9797, + 9794, + 0, + 9689, + 9693, + 9802, + 9797, + 0, + 9693, + 9696, + 9807, + 9802, + 0, + 9696, + 9699, + 9809, + 9807, + 0, + 9699, + 9700, + 9810, + 9809, + 0, + 9700, + 9698, + 9808, + 9810, + 0, + 9698, + 9697, + 9806, + 9808, + 0, + 9697, + 9694, + 9803, + 9806, + 0, + 9694, + 9691, + 9799, + 9803, + 0, + 9691, + 9688, + 9795, + 9799, + 0, + 9688, + 9684, + 9790, + 9795, + 0, + 9684, + 9681, + 9787, + 9790, + 0, + 9681, + 9679, + 9783, + 9787, + 0, + 9679, + 9677, + 9779, + 9783, + 0, + 9677, + 9676, + 9778, + 9779, + 0, + 9676, + 9661, + 9768, + 9778, + 0, + 9661, + 9658, + 9765, + 9768, + 0, + 9765, + 9770, + 9841, + 9837, + 0, + 9770, + 9782, + 9853, + 9841, + 0, + 9782, + 9788, + 9858, + 9853, + 0, + 9788, + 9792, + 9863, + 9858, + 0, + 9792, + 9798, + 9869, + 9863, + 0, + 9798, + 9804, + 9876, + 9869, + 0, + 9804, + 9812, + 9884, + 9876, + 0, + 9812, + 9815, + 9886, + 9884, + 0, + 9815, + 9818, + 9889, + 9886, + 0, + 9818, + 9820, + 9892, + 9889, + 0, + 9820, + 9823, + 9894, + 9892, + 0, + 9823, + 9825, + 9896, + 9894, + 0, + 9825, + 9826, + 9897, + 9896, + 0, + 9826, + 9824, + 9895, + 9897, + 0, + 9824, + 9822, + 9893, + 9895, + 0, + 9822, + 9819, + 9891, + 9893, + 0, + 9819, + 9817, + 9888, + 9891, + 0, + 9817, + 9814, + 9885, + 9888, + 0, + 9814, + 9811, + 9883, + 9885, + 0, + 9811, + 9801, + 9872, + 9883, + 0, + 9801, + 9796, + 9868, + 9872, + 0, + 9796, + 9769, + 9842, + 9868, + 0, + 9769, + 9766, + 9838, + 9842, + 0, + 9766, + 9761, + 9835, + 9838, + 0, + 9761, + 9758, + 9833, + 9835, + 0, + 9758, + 9754, + 9829, + 9833, + 0, + 9754, + 9750, + 9821, + 9829, + 0, + 9750, + 9746, + 9813, + 9821, + 0, + 9746, + 9743, + 9800, + 9813, + 0, + 9743, + 9741, + 9791, + 9800, + 0, + 9741, + 9738, + 9784, + 9791, + 0, + 9738, + 9735, + 9780, + 9784, + 0, + 9735, + 9732, + 9776, + 9780, + 0, + 9732, + 9730, + 9773, + 9776, + 0, + 9730, + 9728, + 9771, + 9773, + 0, + 9728, + 9727, + 9767, + 9771, + 0, + 9727, + 9725, + 9762, + 9767, + 0, + 9725, + 9723, + 9757, + 9762, + 0, + 9723, + 9721, + 9752, + 9757, + 0, + 9721, + 9718, + 9747, + 9752, + 0, + 9718, + 9717, + 9744, + 9747, + 0, + 9717, + 9703, + 9734, + 9744, + 0, + 9703, + 9712, + 9737, + 9734, + 0, + 9712, + 9716, + 9739, + 9737, + 0, + 9716, + 9719, + 9748, + 9739, + 0, + 9719, + 9720, + 9751, + 9748, + 0, + 9720, + 9722, + 9755, + 9751, + 0, + 9722, + 9724, + 9759, + 9755, + 0, + 9724, + 9726, + 9764, + 9759, + 0, + 9726, + 9729, + 9772, + 9764, + 0, + 9729, + 9731, + 9774, + 9772, + 0, + 9731, + 9733, + 9777, + 9774, + 0, + 9733, + 9736, + 9781, + 9777, + 0, + 9736, + 9740, + 9785, + 9781, + 0, + 9740, + 9742, + 9793, + 9785, + 0, + 9742, + 9745, + 9805, + 9793, + 0, + 9745, + 9749, + 9816, + 9805, + 0, + 9749, + 9753, + 9828, + 9816, + 0, + 9753, + 9756, + 9831, + 9828, + 0, + 9756, + 9760, + 9834, + 9831, + 0, + 9760, + 9763, + 9836, + 9834, + 0, + 9763, + 9775, + 9847, + 9836, + 0, + 9775, + 9786, + 9859, + 9847, + 0, + 9786, + 9789, + 9861, + 9859, + 0, + 9789, + 9794, + 9866, + 9861, + 0, + 9794, + 9797, + 9870, + 9866, + 0, + 9797, + 9802, + 9873, + 9870, + 0, + 9802, + 9807, + 9878, + 9873, + 0, + 9807, + 9809, + 9881, + 9878, + 0, + 9809, + 9810, + 9882, + 9881, + 0, + 9810, + 9808, + 9880, + 9882, + 0, + 9808, + 9806, + 9877, + 9880, + 0, + 9806, + 9803, + 9874, + 9877, + 0, + 9803, + 9799, + 9871, + 9874, + 0, + 9799, + 9795, + 9867, + 9871, + 0, + 9795, + 9790, + 9862, + 9867, + 0, + 9790, + 9787, + 9857, + 9862, + 0, + 9787, + 9783, + 9855, + 9857, + 0, + 9783, + 9779, + 9851, + 9855, + 0, + 9779, + 9778, + 9849, + 9851, + 0, + 9778, + 9768, + 9839, + 9849, + 0, + 9768, + 9765, + 9837, + 9839, + 0, + 9837, + 9841, + 9919, + 9916, + 0, + 9841, + 9853, + 9924, + 9919, + 0, + 9853, + 9858, + 9927, + 9924, + 0, + 9858, + 9863, + 9931, + 9927, + 0, + 9863, + 9869, + 9935, + 9931, + 0, + 9869, + 9876, + 9941, + 9935, + 0, + 9876, + 9884, + 9948, + 9941, + 0, + 9884, + 9886, + 9950, + 9948, + 0, + 9886, + 9889, + 9952, + 9950, + 0, + 9889, + 9892, + 9954, + 9952, + 0, + 9892, + 9894, + 9956, + 9954, + 0, + 9894, + 9896, + 9958, + 9956, + 0, + 9896, + 9897, + 9959, + 9958, + 0, + 9897, + 9895, + 9957, + 9959, + 0, + 9895, + 9893, + 9955, + 9957, + 0, + 9893, + 9891, + 9953, + 9955, + 0, + 9891, + 9888, + 9951, + 9953, + 0, + 9888, + 9885, + 9949, + 9951, + 0, + 9885, + 9883, + 9947, + 9949, + 0, + 9883, + 9872, + 9938, + 9947, + 0, + 9872, + 9868, + 9934, + 9938, + 0, + 9868, + 9842, + 9920, + 9934, + 0, + 9842, + 9838, + 9917, + 9920, + 0, + 9838, + 9835, + 9914, + 9917, + 0, + 9835, + 9833, + 9912, + 9914, + 0, + 9833, + 9829, + 9910, + 9912, + 0, + 9829, + 9821, + 9908, + 9910, + 0, + 9821, + 9813, + 9906, + 9908, + 0, + 9813, + 9800, + 9904, + 9906, + 0, + 9800, + 9791, + 9902, + 9904, + 0, + 9791, + 9784, + 9900, + 9902, + 0, + 9784, + 9780, + 9898, + 9900, + 0, + 9780, + 9776, + 9887, + 9898, + 0, + 9776, + 9773, + 9875, + 9887, + 0, + 9773, + 9771, + 9865, + 9875, + 0, + 9771, + 9767, + 9860, + 9865, + 0, + 9767, + 9762, + 9854, + 9860, + 0, + 9762, + 9757, + 9850, + 9854, + 0, + 9757, + 9752, + 9846, + 9850, + 0, + 9752, + 9747, + 9843, + 9846, + 0, + 9747, + 9744, + 9840, + 9843, + 0, + 9744, + 9734, + 9827, + 9840, + 0, + 9734, + 9737, + 9830, + 9827, + 0, + 9737, + 9739, + 9832, + 9830, + 0, + 9739, + 9748, + 9844, + 9832, + 0, + 9748, + 9751, + 9845, + 9844, + 0, + 9751, + 9755, + 9848, + 9845, + 0, + 9755, + 9759, + 9852, + 9848, + 0, + 9759, + 9764, + 9856, + 9852, + 0, + 9764, + 9772, + 9864, + 9856, + 0, + 9772, + 9774, + 9879, + 9864, + 0, + 9774, + 9777, + 9890, + 9879, + 0, + 9777, + 9781, + 9899, + 9890, + 0, + 9781, + 9785, + 9901, + 9899, + 0, + 9785, + 9793, + 9903, + 9901, + 0, + 9793, + 9805, + 9905, + 9903, + 0, + 9805, + 9816, + 9907, + 9905, + 0, + 9816, + 9828, + 9909, + 9907, + 0, + 9828, + 9831, + 9911, + 9909, + 0, + 9831, + 9834, + 9913, + 9911, + 0, + 9834, + 9836, + 9915, + 9913, + 0, + 9836, + 9847, + 9921, + 9915, + 0, + 9847, + 9859, + 9928, + 9921, + 0, + 9859, + 9861, + 9930, + 9928, + 0, + 9861, + 9866, + 9932, + 9930, + 0, + 9866, + 9870, + 9936, + 9932, + 0, + 9870, + 9873, + 9939, + 9936, + 0, + 9873, + 9878, + 9943, + 9939, + 0, + 9878, + 9881, + 9945, + 9943, + 0, + 9881, + 9882, + 9946, + 9945, + 0, + 9882, + 9880, + 9944, + 9946, + 0, + 9880, + 9877, + 9942, + 9944, + 0, + 9877, + 9874, + 9940, + 9942, + 0, + 9874, + 9871, + 9937, + 9940, + 0, + 9871, + 9867, + 9933, + 9937, + 0, + 9867, + 9862, + 9929, + 9933, + 0, + 9862, + 9857, + 9926, + 9929, + 0, + 9857, + 9855, + 9925, + 9926, + 0, + 9855, + 9851, + 9923, + 9925, + 0, + 9851, + 9849, + 9922, + 9923, + 0, + 9849, + 9839, + 9918, + 9922, + 0, + 9839, + 9837, + 9916, + 9918, + 0, + 2767, + 2789, + 2792, + 2798, + 2801, + 2807, + 2812, + 2816, + 2820, + 2821, + 2819, + 2815, + 2813, + 2809, + 2802, + 2797, + 2791, + 2784, + 2778, + 2754, + 2734, + 2728, + 2723, + 2717, + 2710, + 2705, + 2700, + 2693, + 2690, + 2686, + 2682, + 2680, + 2676, + 2673, + 2670, + 2669, + 2667, + 2664, + 2663, + 2662, + 2665, + 2666, + 2668, + 2671, + 2672, + 2675, + 2678, + 2681, + 2684, + 2687, + 2692, + 2696, + 2701, + 2707, + 2711, + 2715, + 2721, + 2727, + 2733, + 2741, + 2786, + 2794, + 2803, + 2810, + 2818, + 2825, + 2828, + 2831, + 2835, + 2838, + 2840, + 2841, + 2839, + 2836, + 2833, + 2829, + 2826, + 2817, + 2808, + 2800, + 2776, + 2764, + 0, + 9916, + 9919, + 9924, + 9927, + 9931, + 9935, + 9941, + 9948, + 9950, + 9952, + 9954, + 9956, + 9958, + 9959, + 9957, + 9955, + 9953, + 9951, + 9949, + 9947, + 9938, + 9934, + 9920, + 9917, + 9914, + 9912, + 9910, + 9908, + 9906, + 9904, + 9902, + 9900, + 9898, + 9887, + 9875, + 9865, + 9860, + 9854, + 9850, + 9846, + 9843, + 9840, + 9827, + 9830, + 9832, + 9844, + 9845, + 9848, + 9852, + 9856, + 9864, + 9879, + 9890, + 9899, + 9901, + 9903, + 9905, + 9907, + 9909, + 9911, + 9913, + 9915, + 9921, + 9928, + 9930, + 9932, + 9936, + 9939, + 9943, + 9945, + 9946, + 9944, + 9942, + 9940, + 9937, + 9933, + 9929, + 9926, + 9925, + 9923, + 9922, + 9918, + 0, + 690, + 692, + 688, + 0, + 690, + 702, + 692, + 0, + 701, + 705, + 702, + 0, + 704, + 707, + 705, + 0, + 706, + 711, + 707, + 0, + 708, + 714, + 711, + 0, + 709, + 717, + 714, + 0, + 709, + 726, + 717, + 0, + 712, + 728, + 726, + 0, + 716, + 730, + 728, + 0, + 718, + 732, + 730, + 0, + 721, + 734, + 732, + 0, + 723, + 736, + 734, + 0, + 725, + 738, + 736, + 0, + 724, + 737, + 738, + 0, + 724, + 735, + 737, + 0, + 722, + 733, + 735, + 0, + 719, + 731, + 733, + 0, + 715, + 729, + 731, + 0, + 713, + 727, + 729, + 0, + 710, + 720, + 727, + 0, + 703, + 699, + 720, + 0, + 697, + 698, + 699, + 0, + 695, + 696, + 698, + 0, + 693, + 694, + 696, + 0, + 689, + 691, + 694, + 0, + 686, + 687, + 691, + 0, + 684, + 685, + 687, + 0, + 684, + 683, + 685, + 0, + 682, + 681, + 683, + 0, + 679, + 680, + 681, + 0, + 673, + 671, + 680, + 0, + 665, + 663, + 671, + 0, + 650, + 649, + 663, + 0, + 650, + 642, + 649, + 0, + 641, + 638, + 642, + 0, + 637, + 634, + 638, + 0, + 631, + 629, + 634, + 0, + 631, + 624, + 629, + 0, + 625, + 619, + 624, + 0, + 622, + 614, + 619, + 0, + 604, + 600, + 614, + 0, + 604, + 602, + 600, + 0, + 614, + 617, + 604, + 0, + 614, + 622, + 617, + 0, + 619, + 625, + 622, + 0, + 624, + 631, + 625, + 0, + 634, + 637, + 631, + 0, + 638, + 641, + 637, + 0, + 642, + 650, + 641, + 0, + 663, + 665, + 650, + 0, + 671, + 673, + 665, + 0, + 680, + 679, + 673, + 0, + 681, + 682, + 679, + 0, + 683, + 684, + 682, + 0, + 687, + 686, + 684, + 0, + 691, + 689, + 686, + 0, + 694, + 693, + 689, + 0, + 696, + 695, + 693, + 0, + 698, + 697, + 695, + 0, + 699, + 703, + 697, + 0, + 720, + 710, + 703, + 0, + 727, + 713, + 710, + 0, + 729, + 715, + 713, + 0, + 731, + 719, + 715, + 0, + 733, + 722, + 719, + 0, + 735, + 724, + 722, + 0, + 738, + 725, + 724, + 0, + 736, + 723, + 725, + 0, + 734, + 721, + 723, + 0, + 732, + 718, + 721, + 0, + 730, + 716, + 718, + 0, + 728, + 712, + 716, + 0, + 726, + 709, + 712, + 0, + 714, + 708, + 709, + 0, + 711, + 706, + 708, + 0, + 707, + 704, + 706, + 0, + 705, + 701, + 704, + 0, + 702, + 700, + 701, + 0, + 702, + 690, + 700, + 0, + 811, + 810, + 814, + 0, + 823, + 820, + 811, + 0, + 823, + 821, + 820, + 0, + 825, + 824, + 821, + 0, + 828, + 826, + 824, + 0, + 831, + 827, + 826, + 0, + 835, + 830, + 827, + 0, + 847, + 833, + 830, + 0, + 850, + 836, + 833, + 0, + 852, + 839, + 836, + 0, + 854, + 842, + 839, + 0, + 856, + 843, + 842, + 0, + 858, + 845, + 843, + 0, + 859, + 844, + 845, + 0, + 855, + 841, + 844, + 0, + 853, + 838, + 841, + 0, + 851, + 834, + 838, + 0, + 849, + 832, + 834, + 0, + 846, + 829, + 832, + 0, + 837, + 822, + 829, + 0, + 819, + 817, + 822, + 0, + 818, + 815, + 817, + 0, + 816, + 812, + 815, + 0, + 813, + 808, + 812, + 0, + 809, + 806, + 808, + 0, + 807, + 804, + 806, + 0, + 803, + 802, + 804, + 0, + 801, + 799, + 802, + 0, + 800, + 798, + 799, + 0, + 797, + 796, + 798, + 0, + 795, + 794, + 796, + 0, + 792, + 791, + 794, + 0, + 790, + 789, + 791, + 0, + 788, + 787, + 789, + 0, + 784, + 785, + 787, + 0, + 782, + 783, + 785, + 0, + 780, + 781, + 783, + 0, + 780, + 779, + 781, + 0, + 777, + 778, + 779, + 0, + 779, + 780, + 777, + 0, + 783, + 782, + 780, + 0, + 785, + 784, + 782, + 0, + 787, + 786, + 784, + 0, + 787, + 788, + 786, + 0, + 789, + 790, + 788, + 0, + 791, + 792, + 790, + 0, + 794, + 793, + 792, + 0, + 794, + 795, + 793, + 0, + 796, + 797, + 795, + 0, + 798, + 800, + 797, + 0, + 799, + 801, + 800, + 0, + 802, + 803, + 801, + 0, + 804, + 805, + 803, + 0, + 804, + 807, + 805, + 0, + 806, + 809, + 807, + 0, + 808, + 813, + 809, + 0, + 812, + 816, + 813, + 0, + 815, + 818, + 816, + 0, + 817, + 819, + 818, + 0, + 822, + 837, + 819, + 0, + 829, + 846, + 837, + 0, + 832, + 849, + 848, + 846, + 0, + 834, + 851, + 849, + 0, + 838, + 853, + 851, + 0, + 841, + 855, + 853, + 0, + 844, + 857, + 855, + 0, + 844, + 859, + 857, + 0, + 845, + 858, + 859, + 0, + 843, + 856, + 858, + 0, + 842, + 854, + 856, + 0, + 839, + 852, + 854, + 0, + 836, + 850, + 852, + 0, + 833, + 847, + 850, + 0, + 830, + 840, + 847, + 0, + 830, + 835, + 840, + 0, + 827, + 831, + 835, + 0, + 826, + 828, + 831, + 0, + 824, + 825, + 828, + 0, + 821, + 823, + 825, + 0, + 811, + 814, + 823, + 0, + 979, + 978, + 982, + 0, + 994, + 990, + 979, + 0, + 994, + 993, + 990, + 0, + 998, + 996, + 993, + 0, + 1004, + 999, + 996, + 0, + 1010, + 1003, + 999, + 0, + 1015, + 1007, + 1003, + 0, + 1029, + 1012, + 1007, + 0, + 1033, + 1016, + 1012, + 0, + 1036, + 1021, + 1016, + 0, + 1038, + 1024, + 1021, + 0, + 1040, + 1027, + 1024, + 0, + 1042, + 1028, + 1027, + 0, + 1041, + 1025, + 1028, + 0, + 1037, + 1020, + 1025, + 0, + 1035, + 1014, + 1020, + 0, + 1034, + 1011, + 1014, + 0, + 1030, + 1006, + 1011, + 0, + 1023, + 1002, + 1006, + 0, + 1013, + 989, + 1002, + 0, + 986, + 983, + 989, + 0, + 984, + 980, + 983, + 0, + 981, + 976, + 980, + 0, + 977, + 972, + 976, + 0, + 973, + 969, + 972, + 0, + 970, + 967, + 969, + 0, + 966, + 965, + 967, + 0, + 964, + 963, + 965, + 0, + 962, + 961, + 963, + 0, + 960, + 959, + 961, + 0, + 958, + 957, + 959, + 0, + 955, + 954, + 957, + 0, + 953, + 952, + 954, + 0, + 951, + 950, + 952, + 0, + 947, + 948, + 950, + 0, + 945, + 946, + 948, + 0, + 943, + 944, + 946, + 0, + 943, + 942, + 944, + 0, + 940, + 941, + 942, + 0, + 942, + 943, + 940, + 0, + 946, + 945, + 943, + 0, + 948, + 947, + 945, + 0, + 950, + 949, + 947, + 0, + 950, + 951, + 949, + 0, + 952, + 953, + 951, + 0, + 954, + 955, + 953, + 0, + 957, + 956, + 955, + 0, + 957, + 958, + 956, + 0, + 959, + 960, + 958, + 0, + 961, + 962, + 960, + 0, + 963, + 964, + 962, + 0, + 965, + 966, + 964, + 0, + 967, + 968, + 966, + 0, + 967, + 970, + 968, + 0, + 969, + 973, + 970, + 0, + 972, + 977, + 973, + 0, + 976, + 981, + 977, + 0, + 980, + 984, + 981, + 0, + 983, + 986, + 984, + 0, + 989, + 1013, + 986, + 0, + 1002, + 1023, + 1013, + 0, + 1006, + 1030, + 1023, + 0, + 1011, + 1034, + 1030, + 0, + 1014, + 1035, + 1034, + 0, + 1020, + 1037, + 1035, + 0, + 1025, + 1039, + 1037, + 0, + 1025, + 1041, + 1039, + 0, + 1028, + 1042, + 1041, + 0, + 1027, + 1040, + 1042, + 0, + 1024, + 1038, + 1040, + 0, + 1021, + 1036, + 1038, + 0, + 1016, + 1033, + 1036, + 0, + 1012, + 1029, + 1033, + 0, + 1007, + 1026, + 1029, + 0, + 1007, + 1015, + 1026, + 0, + 1003, + 1010, + 1015, + 0, + 999, + 1004, + 1010, + 0, + 996, + 998, + 1004, + 0, + 993, + 994, + 998, + 0, + 979, + 982, + 994, + 0, + 811, + 814, + 810, + 0, + 811, + 823, + 814, + 0, + 821, + 825, + 823, + 0, + 824, + 828, + 825, + 0, + 826, + 831, + 828, + 0, + 827, + 835, + 831, + 0, + 830, + 840, + 835, + 0, + 830, + 847, + 840, + 0, + 833, + 850, + 847, + 0, + 836, + 852, + 850, + 0, + 839, + 854, + 852, + 0, + 842, + 856, + 854, + 0, + 843, + 858, + 856, + 0, + 845, + 859, + 858, + 0, + 844, + 857, + 859, + 0, + 844, + 855, + 857, + 0, + 841, + 853, + 855, + 0, + 838, + 851, + 853, + 0, + 834, + 849, + 851, + 0, + 832, + 846, + 848, + 849, + 0, + 829, + 837, + 846, + 0, + 822, + 819, + 837, + 0, + 817, + 818, + 819, + 0, + 815, + 816, + 818, + 0, + 812, + 813, + 816, + 0, + 808, + 809, + 813, + 0, + 806, + 807, + 809, + 0, + 804, + 805, + 807, + 0, + 804, + 803, + 805, + 0, + 802, + 801, + 803, + 0, + 799, + 800, + 801, + 0, + 798, + 797, + 800, + 0, + 796, + 795, + 797, + 0, + 794, + 793, + 795, + 0, + 794, + 792, + 793, + 0, + 791, + 790, + 792, + 0, + 789, + 788, + 790, + 0, + 787, + 786, + 788, + 0, + 787, + 784, + 786, + 0, + 785, + 782, + 784, + 0, + 783, + 780, + 782, + 0, + 779, + 777, + 780, + 0, + 779, + 778, + 777, + 0, + 780, + 781, + 779, + 0, + 780, + 783, + 781, + 0, + 782, + 785, + 783, + 0, + 784, + 787, + 785, + 0, + 788, + 789, + 787, + 0, + 790, + 791, + 789, + 0, + 792, + 794, + 791, + 0, + 795, + 796, + 794, + 0, + 797, + 798, + 796, + 0, + 800, + 799, + 798, + 0, + 801, + 802, + 799, + 0, + 803, + 804, + 802, + 0, + 807, + 806, + 804, + 0, + 809, + 808, + 806, + 0, + 813, + 812, + 808, + 0, + 816, + 815, + 812, + 0, + 818, + 817, + 815, + 0, + 819, + 822, + 817, + 0, + 837, + 829, + 822, + 0, + 846, + 832, + 829, + 0, + 849, + 834, + 832, + 0, + 851, + 838, + 834, + 0, + 853, + 841, + 838, + 0, + 855, + 844, + 841, + 0, + 859, + 845, + 844, + 0, + 858, + 843, + 845, + 0, + 856, + 842, + 843, + 0, + 854, + 839, + 842, + 0, + 852, + 836, + 839, + 0, + 850, + 833, + 836, + 0, + 847, + 830, + 833, + 0, + 835, + 827, + 830, + 0, + 831, + 826, + 827, + 0, + 828, + 824, + 826, + 0, + 825, + 821, + 824, + 0, + 823, + 820, + 821, + 0, + 823, + 811, + 820, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/source.json b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/source.json index 20b19959dd96..5994de126cc5 100644 --- a/core/geometry/src/test/data/clipping/arnoldasInOut/case2/source.json +++ b/core/geometry/src/test/data/clipping/arnoldasInOut/case2/source.json @@ -1 +1,62988 @@ -{"indexedMesh":{"point":[[508706.2777792843,6651140.513853399,90.64963022028905],[508706.4851137081,6651139.940594222,90.64963022028905],[508706.4851137081,6651139.940594222,90.77963022028906],[508706.2777792843,6651140.513853399,92.47843387928906],[508706.28490812134,6651140.49414287,92.94402456628906],[508706.30720094504,6651140.432505418,93.42129551828906],[508706.4851129126,6651139.940596422,92.47843388028906],[508706.4866588913,6651139.936321944,92.68225516428906],[508706.34580754495,6651140.325761987,93.90419653828906],[508706.49949579797,6651139.900829167,93.09883445228905],[508706.3859590205,6651140.214747127,94.26590252328907],[508706.5262542289,6651139.826844751,93.52316157228907],[508706.43590831576,6651140.076642266,94.62366036928907],[508706.5678003188,6651139.711973921,93.94947192328905],[508706.4956613969,6651139.9114309065,94.97411658428906],[508706.6246385284,6651139.554821893,94.37128078228906],[508706.5650490394,6651139.719580937,95.31386161128906],[508706.6968373622,6651139.355199258,94.78163032528906],[508706.64372094884,6651139.502060887,95.63952872128907],[508706.78397924855,6651139.11426056,95.17341001928907],[508706.7311476779,6651139.260334628,95.94789752928908],[508706.8586069096,6651138.907922458,95.45089187928906],[508706.8266307387,6651138.996333408,96.23599588028905],[508706.9405642631,6651138.681318481,95.71133255228906],[508707.0291440019,6651138.436404263,95.95230219828906],[508706.9293206465,6651138.712405968,96.50119360528906],[508707.1235197014,6651138.175464787,96.17172120428907],[508707.0382419553,6651138.411249321,96.74128205228907],[508707.1523237469,6651138.095824449,96.95453438728906],[508707.25676979084,6651137.807041467,96.42793432728907],[508707.27043360844,6651137.769262364,97.13974328928906],[508707.3963357616,6651137.4211553605,96.64021213628908],[508707.3914128982,6651137.4347665915,97.29623458128906],[508707.5397992159,6651137.024493099,96.80732689328907],[508707.5141111274,6651137.095518122,97.42385734028906],[508707.68479369435,6651136.623597706,96.92948001528907],[508707.637417504,6651136.754588186,97.52295283428906],[508707.8291136465,6651136.224567309,97.00815470828906],[508707.8009801167,6651136.302353737,97.61211748628907],[508707.97079844604,6651135.832822851,97.04589756728906],[508707.96155622305,6651135.858376684,97.65489272728908],[508708.55362604477,6651134.221362181,97.04589756728906],[508709.14882702165,6651132.575690342,97.04589756728906],[508709.15807004046,6651132.55013431,97.65489272728908],[508709.2905118211,6651132.183945884,97.00815470828906],[508709.4348317733,6651131.784915489,96.92948001528907],[508709.3186461469,6651132.106157256,97.61211748628907],[508710.63451255544,6651128.467916771,90.64963022028905],[508710.63451255544,6651128.467916771,90.77963022028906],[508709.57982625184,6651131.384020096,96.80732689328907],[508709.4822087595,6651131.653922807,97.52295283428906],[508709.723289706,6651130.9873578325,96.64021213628908],[508710.84184697916,6651127.894657594,90.64963022028905],[508709.60551513615,6651131.31299287,97.42385734028906],[508709.86285567685,6651130.601471727,96.42793432728907],[508709.7282133653,6651130.973744401,97.29623458128906],[508710.63451255544,6651128.467916771,92.47843387928906],[508709.9961057662,6651130.233048406,96.17172120428907],[508710.62822240515,6651128.485308414,92.88924919128907],[508709.849192655,6651130.639248629,97.13974328928906],[508710.12069504283,6651129.888571378,95.87427873428906],[508710.6085522666,6651128.539694401,93.31037061928907],[508710.2071537418,6651129.649521626,95.62656899428906],[508709.96730251657,6651130.312686544,96.95453438728906],[508710.5744876195,6651128.633879782,93.73645975428906],[508710.28673993266,6651129.429473679,95.36016267928906],[508710.52533278905,6651128.769788027,94.16136625828906],[508710.381039242,6651129.168745415,94.98028187728906],[508710.84184697916,6651127.894657594,92.47843387928906],[508710.46079327207,6651128.94823341,94.57833296028907],[508710.0813843083,6651129.997261671,96.74128205228907],[508710.83471814217,6651127.914368123,92.94402456628906],[508710.190305617,6651129.696105025,96.50119360528906],[508710.2929955248,6651129.412177585,96.23599588028905],[508710.81242531847,6651127.976005576,93.42129551828906],[508710.3884785856,6651129.1481763655,95.94789752928908],[508710.77381871856,6651128.082749007,93.90419653828906],[508710.47590531467,6651128.906450105,95.63952872128907],[508710.7336672429,6651128.193763865,94.26590252328907],[508710.5545772241,6651128.688930056,95.31386161128906],[508710.6837179477,6651128.331868728,94.62366036928907],[508710.6239648667,6651128.497080087,94.97411658428906],[508714.78237503424,6651143.589766587,90.78879207594775],[508714.9897094581,6651143.01650741,90.78879207594775],[508714.9897094581,6651143.01650741,90.91879207594776],[508714.78237503424,6651143.589766587,92.61759573494776],[508714.78950387135,6651143.5700560585,93.08318642194777],[508714.81179669505,6651143.508418606,93.56045737394776],[508714.98970866256,6651143.01650961,92.61759573594777],[508714.99125464127,6651143.012235131,92.82141701994776],[508714.85040329496,6651143.401675175,94.04335839394776],[508715.0040915479,6651142.976742355,93.23799630794775],[508714.8905547706,6651143.290660315,94.40506437894776],[508715.03084997885,6651142.90275794,93.66232342794775],[508714.94050406583,6651143.152555454,94.76282222494775],[508715.0723960689,6651142.787887109,94.08863377894775],[508715.00025714684,6651142.987344094,95.11327843994776],[508715.12923427834,6651142.630735081,94.51044263794776],[508715.06964478944,6651142.795494125,95.45302346694776],[508715.20143311226,6651142.431112445,94.92079218094777],[508715.6774476409,6651143.913247264,90.80304684876648],[508715.1483166988,6651142.577974075,95.77869057694775],[508715.2885749985,6651142.190173748,95.31257187494776],[508715.23574342794,6651142.336247816,96.08705938494776],[508715.8845032102,6651143.339887308,90.80304684876648],[508715.36320265953,6651141.983835646,95.59005373494777],[508715.8845032102,6651143.339887308,90.9330468487665],[508715.6774476409,6651143.913247264,92.63185050776649],[508715.33122648863,6651142.072246595,96.37515773594775],[508715.44516001304,6651141.7572316695,95.85049440794778],[508715.68456689,6651143.893533269,93.0974411947665],[508715.53373975185,6651141.512317451,96.09146405394776],[508715.4339163965,6651141.7883191565,96.64035546094777],[508715.706829731,6651143.83188498,93.57471214676649],[508715.8845024158,6651143.339889509,92.6318505087665],[508715.8860463153,6651143.335614278,92.83567179276649],[508715.62811545137,6651141.251377975,96.31088305994776],[508715.54283770523,6651141.48716251,96.88044390794778],[508715.7453844069,6651143.725122785,94.05761316676649],[508715.89886595693,6651143.300115261,93.25225108076648],[508715.78548188077,6651143.614088409,94.41931915176649],[508715.92558839906,6651143.22611784,93.6765782007665],[508715.65691949695,6651141.171737637,97.09369624294777],[508715.7613655408,6651140.882954656,96.56709618294778],[508715.83536399674,6651143.475959268,94.77707699776649],[508715.96707861166,6651143.111226816,94.10288855176648],[508715.7750293585,6651140.845175552,97.27890514494776],[508715.9009315116,6651140.497068549,96.77937399194776],[508715.89503671293,6651143.310718865,95.1275332127665],[508716.0238403766,6651142.95404716,94.52469741076649],[508715.89600864815,6651140.5106797805,97.43539643694777],[508715.9643310326,6651143.11883517,95.46727823976649],[508716.04439496587,6651140.100406287,96.94648874894776],[508716.09594210674,6651142.754389431,94.93504695376649],[508716.01870687737,6651140.1714313105,97.56301919594776],[508716.0428971322,6651142.901276879,95.7929453497665],[508716.18938944436,6651139.699510893,97.06864187094776],[508716.18296679156,6651142.513408378,95.3268266477665],[508716.142013254,6651139.830501375,97.66211468994776],[508716.13020627684,6651142.659508124,96.10131415776651],[508716.2574940821,6651142.307034001,95.6043085077665],[508716.3337093965,6651139.300480497,97.14731656394775],[508716.3055758666,6651139.378266925,97.75127934194776],[508716.2255609175,6651142.395460493,96.38941250876648],[508716.33934120706,6651142.080390187,95.86474918076651],[508716.47539419605,6651138.908736039,97.18505942294776],[508716.42780181055,6651141.835432913,96.10571882676649],[508716.3281127127,6651142.11148314,96.65461023376649],[508716.46615197306,6651138.934289873,97.79405458294777],[508716.5220505795,6651141.574447565,96.3251378327665],[508716.4368875277,6651141.8102735495,96.8946986807665],[508716.550815885,6651141.494793227,97.10795101576649],[508716.65512145427,6651141.2059594765,96.5813509557665],[508716.6687668947,6651141.168173731,97.29315991776649],[508716.79449971585,6651140.820005531,96.79362876476651],[508717.05822179484,6651137.297275369,97.18505942294776],[508716.7895834734,6651140.833619155,97.44965120976649],[508716.9377702189,6651140.423273537,96.9607435217665],[508716.9121166796,6651140.494311047,97.57727396876649],[508717.0825696871,6651140.022307666,97.0828966437665],[508717.0352572153,6651140.153321175,97.67636946276649],[508717.22669553617,6651139.623207121,97.16157133676649],[508717.1985998445,6651139.701007224,97.7655341147665],[508717.65342277166,6651135.65160353,97.18505942294776],[508717.3681897767,6651139.2313937945,97.19931419576649],[508717.6626657904,6651135.626047498,97.79405458294777],[508717.7951075712,6651135.259859072,97.14731656394775],[508717.35895998415,6651139.256952119,97.80830935576651],[508717.93942752335,6651134.860828677,97.06864187094776],[508717.82324189687,6651135.182070444,97.75127934194776],[508719.1391083054,6651131.543829958,90.78879207594775],[508719.1391083054,6651131.543829958,90.91879207594776],[508718.0844220018,6651134.459933283,96.94648874894776],[508717.9868045096,6651134.7298359955,97.66211468994776],[508718.227885456,6651134.063271021,96.77937399194776],[508719.34644272923,6651130.970570781,90.78879207594775],[508718.1101108861,6651134.388906058,97.56301919594776],[508718.3674514268,6651133.677384914,96.56709618294778],[508718.23280911526,6651134.049657589,97.43539643694777],[508717.9502335017,6651137.619649831,97.19931419576649],[508719.1391083054,6651131.543829958,92.61759573494776],[508718.5007015163,6651133.3089615945,96.31088305994776],[508719.1328181552,6651131.561221601,93.02841104694775],[508718.3537884051,6651133.715161817,97.27890514494776],[508718.6252907928,6651132.964484566,96.01344058994778],[508719.11314801656,6651131.61560759,93.44953247494776],[508718.7117494918,6651132.725434814,95.76573084994776],[508718.4718982665,6651133.388599731,97.09369624294777],[508719.07908336946,6651131.70979297,93.87562160994777],[508718.7913356826,6651132.505386867,95.49932453494776],[508719.029928539,6651131.845701215,94.30052811394776],[508718.88563499204,6651132.244658602,95.11944373294777],[508719.34644272923,6651130.970570781,92.61759573494776],[508718.9653890221,6651132.024146597,94.71749481594776],[508718.58598005824,6651133.07317486,96.88044390794778],[508719.3393138921,6651130.990281312,93.08318642194777],[508718.694901367,6651132.772018213,96.64035546094777],[508718.7975912748,6651132.488090773,96.37515773594775],[508719.3170210684,6651131.051918764,93.56045737394776],[508718.8930743356,6651132.224089553,96.08705938494776],[508719.2784144686,6651131.158662194,94.04335839394776],[508718.9805010646,6651131.982363293,95.77869057694775],[508719.238262993,6651131.269677053,94.40506437894776],[508719.05917297414,6651131.764843244,95.45302346694776],[508719.18831369776,6651131.407781915,94.76282222494775],[508719.12856061663,6651131.572993275,95.11327843994776],[508718.544633963,6651135.973688684,97.19931419576649],[508718.5538645504,6651135.94812816,97.80830935576651],[508718.6861282035,6651135.581875358,97.16157133676649],[508718.8302540526,6651135.182774814,97.0828966437665],[508718.71422469,6651135.5040730545,97.7655341147665],[508720.02832132427,6651131.86519297,90.80304684876648],[508720.02832132427,6651131.86519297,90.9330468487665],[508718.9750535208,6651134.7818089435,96.9607435217665],[508718.8775673192,6651135.051759104,97.67636946276649],[508719.11832402385,6651134.385076948,96.79362876476651],[508720.23537689366,6651131.291833014,90.80304684876648],[508719.00070785487,6651134.710769232,97.57727396876649],[508719.2577022854,6651133.999123003,96.5813509557665],[508719.12324106105,6651134.371461123,97.44965120976649],[508720.02832132427,6651131.86519297,92.63185050776649],[508719.3907731602,6651133.630634915,96.3251378327665],[508720.02203963394,6651131.882587671,93.0426658197665],[508719.24405763973,6651134.036906548,97.29315991776649],[508719.5151948704,6651133.286097328,96.0276953627665],[508720.0023959507,6651131.93698322,93.46378724776649],[508719.60153728677,6651133.047005552,95.77998562276649],[508719.36200864945,6651133.710287051,97.10795101576649],[508719.9683771189,6651132.0311851585,93.88987638276649],[508719.68101643823,6651132.82691892,95.51357930776649],[508719.91928839916,6651132.167117296,94.3147828867665],[508719.7751889197,6651132.56614482,95.1336985057665],[508720.23537689366,6651131.291833014,92.63185050776649],[508719.8548356846,6651132.345594048,94.7317495887665],[508719.4759370069,6651133.394806729,96.8946986807665],[508720.2282576446,6651131.311547009,93.0974411947665],[508719.58471182187,6651133.093597139,96.65461023376649],[508719.68726361694,6651132.809619785,96.38941250876648],[508720.2059948036,6651131.373195298,93.57471214676649],[508719.78261825774,6651132.545572154,96.10131415776651],[508720.1674401276,6651131.479957494,94.05761316676649],[508719.86992740224,6651132.303803399,95.7929453497665],[508720.1273426537,6651131.59099187,94.41931915176649],[508719.948493502,6651132.08624511,95.46727823976649],[508720.07746053784,6651131.72912101,94.77707699776649],[508720.0177878216,6651131.894361413,95.1275332127665],[508725.32253985456,6651147.367830913,90.95204076656832],[508725.38733578427,6651147.390846381,90.9530132307946],[508725.52659055294,6651146.793394702,90.95204076656832],[508725.52659055294,6651146.793394702,91.08204076656834],[508725.59136629594,6651146.816403001,90.9530132307946],[508725.59136629594,6651146.816403001,91.08301323079462],[508725.32253985456,6651147.367830913,92.78084442556833],[508725.38733578427,6651147.390846381,92.78181688979461],[508725.32955578633,6651147.348079913,93.24643511256832],[508725.3943510221,6651147.371095134,93.2474075767946],[508725.35149554035,6651147.286315903,93.72370606456832],[508725.52658977,6651146.793396905,92.78084442656832],[508725.52811126376,6651146.789113652,92.98466571056832],[508725.41628860554,6651147.309330354,93.7246785287946],[508725.591365513,6651146.816405204,92.7818168907946],[508725.3894906958,6651147.179353304,94.20660708456833],[508725.5407448617,6651146.753547998,93.40124499856833],[508725.5928868563,6651146.812121895,92.9856381747946],[508725.45428000204,6651147.20236642,94.20757954879461],[508725.60551920446,6651146.7765558,93.40221746279461],[508725.4290062595,6651147.068110505,94.56831306956832],[508725.56707949744,6651146.679411677,93.82557211856832],[508725.4937916565,6651147.091122234,94.5692855337946],[508725.6318512348,6651146.702418552,93.8265445827946],[508725.4781644668,6651146.929722083,94.92607091556832],[508725.60796758794,6651146.56430499,94.25188246956833],[508725.5429450006,6651146.952732083,94.9270433797946],[508725.67273528024,6651146.587310429,94.25285493379461],[508725.53697118926,6651146.764171507,95.27652713056834],[508725.6639056041,6651146.406830293,94.67369132856832],[508725.60174590535,6651146.78717944,95.27749959479462],[508725.7286677624,6651146.429833766,94.6746637927946],[508725.60525988275,6651146.571927624,95.61627215756833],[508725.73496096575,6651146.206797785,95.08404087156832],[508725.67002784304,6651146.59493316,95.61724462179461],[508725.7997160946,6651146.229798762,95.0850133357946],[508725.6826858006,6651146.353960956,95.94193926756832],[508725.82072271453,6651145.965364385,95.47582056556834],[508725.74744610104,6651146.376963769,95.9429117317946],[508725.88546935894,6651145.988362348,95.47679302979462],[508725.7687278809,6651146.111738377,96.25030807556833],[508725.894168436,6651145.758602623,95.75330242556832],[508725.8334796691,6651146.134738167,96.2512805397946],[508725.9589078144,6651145.7815980045,95.7542748897946],[508725.86269869795,6651145.847195102,96.53840642656833],[508725.9748277637,6651145.531533376,96.01374309856833],[508725.9274411897,6651145.87019159,96.5393788907946],[508726.03955916245,6651145.554525924,96.0147155627946],[508726.06200459244,6651145.286116293,96.25471274456832],[508725.96376222157,6651145.562684693,96.80360415156832],[508726.1267273669,6651145.309105776,96.2556852087946],[508726.02849471505,6651145.585677629,96.8045766157946],[508726.1548855866,6651145.024641049,96.47413175056832],[508726.07095845405,6651145.260909703,97.04369259856833],[508726.21959917224,6651145.047627268,96.4751042147946],[508726.1356803426,6651145.283898872,97.0446650627946],[508726.1832334388,6651144.94483719,97.25694493356833],[508726.28602528496,6651144.65546127,96.73034487356833],[508726.2479442199,6651144.967822416,97.25791739779461],[508726.35072589695,6651144.678442883,96.73131733779461],[508726.2994726975,6651144.6176045975,97.44215383556832],[508726.423380835,6651144.268782851,96.94262268256833],[508726.3641719791,6651144.640585736,97.4431262997946],[508726.4880678583,6651144.291759636,96.9435951467946],[508726.41853593895,6651144.2824220285,97.59864512756832],[508726.5645721407,6651143.871306149,97.10973743956832],[508726.48322344164,6651144.305398984,97.5996175917946],[508726.53929089557,6651143.942477004,97.72626788656834],[508726.629245196,6651143.894277973,97.1107099037946],[508726.7072702227,6651143.469587625,97.23189056156832],[508726.60396645183,6651143.965449717,97.72724035079462],[508726.6606443679,6651143.600847059,97.82536338056833],[508726.7719291607,6651143.492554434,97.2328630257946],[508726.7253079187,6651143.623815507,97.82633584479461],[508726.8493044613,6651143.069737928,97.31056525456833],[508726.8216165053,6651143.147684069,97.91452803256834],[508726.9139493479,6651143.092699747,97.31153771879461],[508726.9887452824,6651142.677189128,97.34830811356832],[508726.886264131,6651143.170646861,97.9155004967946],[508727.05337637407,6651142.7001460465,97.3492805777946],[508726.97964943614,6651142.702795427,97.95730327356833],[508727.0442814277,6651142.725752666,97.95827573779461],[508727.56234216224,6651141.062419756,97.34830811356832],[508727.62691650784,6651141.085356518,97.3492805777946],[508728.14811645274,6651139.413368974,97.34830811356832],[508728.21263284754,6651139.436285153,97.3492805777946],[508728.15721308225,6651139.38776047,97.95730327356833],[508728.2875572738,6651139.020820174,97.31056525456833],[508728.22172857705,6651139.4106763275,97.95827573779461],[508728.3520598737,6651139.043731453,97.31153771879461],[508728.4295915124,6651138.620970477,97.23189056156832],[508728.3152460131,6651138.942871828,97.91452803256834],[508729.61027196544,6651135.2971611945,90.95204076656832],[508729.61027196544,6651135.2971611945,91.08204076656834],[508728.4940800608,6651138.643876764,97.2328630257946],[508728.3797458737,6651138.965782133,97.9155004967946],[508729.6746437088,6651135.320025993,90.9530132307946],[508728.5722895944,6651138.219251953,97.10973743956832],[508729.6746437088,6651135.320025993,91.08301323079462],[508728.47621815046,6651138.489708837,97.82536338056833],[508728.6367640256,6651138.242153226,97.1107099037946],[508729.8143226638,6651134.722724985,90.95204076656832],[508728.7134809001,6651137.821775251,96.94262268256833],[508728.5407020861,6651138.5126134865,97.82633584479461],[508728.59757162275,6651138.148078892,97.72626788656834],[508729.8786742204,6651134.745582613,90.9530132307946],[508728.7779413633,6651137.844671562,96.9435951467946],[508728.8508364501,6651137.435096831,96.73034487356833],[508728.6620435529,6651138.170979277,97.72724035079462],[508728.7183265793,6651137.8081338685,97.59864512756832],[508729.61027196544,6651135.2971611945,92.78084442556833],[508728.98197614856,6651137.065917053,96.47413175056832],[508728.91528332455,6651137.457988316,96.73131733779461],[508729.6040814375,6651135.314588548,93.19165973756832],[508728.78278656316,6651137.831030009,97.5996175917946],[508728.8373898208,6651137.4729512995,97.44215383556832],[508729.6746437088,6651135.320025993,92.78181688979461],[508729.1045922024,6651136.720732735,96.17668928056834],[508729.584722831,6651135.369086202,93.61278116556832],[508729.04641004937,6651137.088803929,96.4751042147946],[508729.6684537933,6651135.337453564,93.1926322017946],[508729.189681584,6651136.481192158,95.92897954056832],[508728.95362907957,6651137.145718706,97.25694493356833],[508729.55119769374,6651135.463464968,94.03887030056832],[508728.9018380256,6651137.495843258,97.4431262997946],[508729.26800730306,6651136.260692402,95.66257322556834],[508729.50282136863,6651135.599652262,94.46377680456833],[508729.8143226638,6651134.722724985,92.78084442556833],[508729.1690139728,6651136.743615302,96.17766174479462],[508729.36081311695,6651135.999428803,95.28269242356832],[508729.439304017,6651135.778464034,94.88074350656832],[508729.649097102,6651135.391951898,93.6137536297946],[508729.0659040642,6651136.829646194,97.04369259856833],[508729.2540949366,6651136.504071737,95.9299520047946],[508729.01806578477,6651137.168606578,97.25791739779461],[508729.6155752814,6651135.486331842,94.0398427647946],[508729.33241290686,6651136.283569227,95.66354568979462],[508729.807306732,6651134.742475984,93.24643511256832],[508729.56720374216,6651135.622520837,94.4647492687946],[508729.8786742204,6651134.745582613,92.78181688979461],[508729.42520953936,6651136.022302366,95.2836648877946],[508729.1731002968,6651136.527871204,96.80360415156832],[508729.5036926743,6651135.801334841,94.8817159707946],[508729.13032966206,6651136.852530121,97.0446650627946],[508729.7853669781,6651134.804239994,93.72370606456832],[508729.2741638204,6651136.243360795,96.53840642656833],[508729.8716589827,6651134.765333859,93.2474075767946],[508729.2375152897,6651136.550751365,96.8045766157946],[508729.3681346375,6651135.97881752,96.25030807556833],[508729.7473718226,6651134.911202593,94.20660708456833],[508729.45417671767,6651135.73659494,95.94193926756832],[508729.7078562588,6651135.022445392,94.56831306956832],[508729.84972139925,6651134.827098639,93.7246785287946],[508729.6586980516,6651135.160833814,94.92607091556832],[508729.5316026356,6651135.518628272,95.61627215756833],[508729.338568815,6651136.266237404,96.5393788907946],[508729.599891329,6651135.326384392,95.27652713056834],[508729.43253033556,6651136.001690826,96.2512805397946],[508729.81173000264,6651134.934062573,94.20757954879461],[508729.51856390364,6651135.759465223,95.9429117317946],[508729.77221834817,6651135.04530676,94.5692855337946],[508729.72306500416,6651135.183696911,94.9270433797946],[508729.59598216176,6651135.5414958345,95.61724462179461],[508729.66426409944,6651135.349249553,95.27749959479462],[508731.2576440958,6651149.465347872,91.03954345236868],[508731.4598457478,6651148.890258194,91.03954345236868],[508731.4598457478,6651148.890258194,91.16954345236869],[508731.2576440958,6651149.465347872,92.86834711136868],[508731.2645964514,6651149.445574404,93.33393779836867],[508731.45984497207,6651148.8902604,92.86834711236867],[508731.28633739386,6651149.383740134,93.81120875036866],[508731.46135267854,6651148.885972272,93.07216839636867],[508731.32398824865,6651149.276655856,94.29410977036868],[508731.47387179465,6651148.850366161,93.48874768436868],[508731.4999677937,6651148.776145502,93.91307480436866],[508731.3631457341,6651149.165286509,94.65581575536866],[508731.4118584844,6651149.026740658,95.01357360136866],[508731.5404853686,6651148.660907873,94.33938515536866],[508731.47013231803,6651148.861001753,95.36402981636869],[508731.5959164912,6651148.503254035,94.76119401436867],[508731.5378021998,6651148.668539179,95.70377484336868],[508731.66632797045,6651148.302993974,95.17154355736866],[508731.6145265072,6651148.450324556,96.02944195336866],[508731.7513125718,6651148.061285923,95.56332325136869],[508731.6997888998,6651148.207826428,96.33781076136867],[508731.8240927502,6651147.854288953,95.84080511136867],[508731.7929081815,6651147.942982213,96.62590911236867],[508731.9040211672,6651147.626961395,96.10124578436867],[508731.9904080257,6651147.38126513,96.34221543036867],[508731.8930558976,6651147.65814815,96.89110683736867],[508732.08244736,6651147.119492435,96.56163443636866],[508731.99928075,6651147.356029864,97.13119528436867],[508732.1105383324,6651147.039597794,97.34444761936867],[508732.21239870973,6651146.749892686,96.81784755936867],[508732.2257242658,6651146.711992947,97.52965652136866],[508732.3485095847,6651146.362774386,97.03012536836867],[508732.34370859177,6651146.37642908,97.68614781336866],[508732.4884214571,6651145.964845522,97.19724012536867],[508732.46336930303,6651146.03609734,97.81377057236868],[508732.6298264518,6651145.562670009,97.31939324736867],[508732.5836231066,6651145.694078762,97.91286606636868],[508732.77057361865,6651145.16236545,97.39806794036868],[508732.7431365626,6651145.240400261,98.00203071836869],[508732.90875086875,6651144.769370093,97.43581079936867],[508732.89973744634,6651144.795005524,98.04480595936867],[508733.47714998526,6651143.152763788,97.43581079936867],[508734.05761616444,6651141.501837073,97.43581079936867],[508734.066630363,6651141.476199437,98.04480595936867],[508734.19579341455,6651141.108841715,97.39806794036868],[508734.33654058137,6651140.708537157,97.31939324736867],[508735.5065220615,6651137.380946767,91.03954345236868],[508734.22323124675,6651141.030804697,98.00203071836869],[508735.5065220615,6651137.380946767,91.16954345236869],[508734.477945576,6651140.306361645,97.19724012536867],[508734.38274470274,6651140.577126197,97.91286606636868],[508734.433606892,6651150.578949004,91.08506430210429],[508735.7087237135,6651136.805857087,91.03954345236868],[508734.6178574484,6651139.90843278,97.03012536836867],[508734.5029985063,6651140.23510762,97.81377057236868],[508734.75396832346,6651139.521314481,96.81784755936867],[508735.5065220615,6651137.380946767,92.86834711136868],[508734.62265921757,6651139.89477588,97.68614781336866],[508734.6348190917,6651150.003512391,91.08506430210429],[508734.6348190917,6651150.003512391,91.2150643021043],[508734.8839196733,6651139.151714731,96.56163443636866],[508735.5003876302,6651137.398393943,93.27916242336866],[508734.74064354354,6651139.559212013,97.52965652136866],[508735.00542461715,6651138.806137736,96.26419196636867],[508735.4812044456,6651137.452953594,93.70028385136867],[508734.433606892,6651150.578949004,92.91386796110429],[508735.0897429443,6651138.566324663,96.01648222636868],[508735.4479831031,6651137.547439722,94.12637298636866],[508734.85582947696,6651139.231607164,97.34444761936867],[508735.167358899,6651138.34557407,95.75007591136868],[508735.7087237135,6651136.805857087,92.86834711136868],[508735.40004514984,6651137.683781942,94.55127949036867],[508735.2593237343,6651138.08401326,95.37019510936867],[508735.3371033734,6651137.862797127,94.96824619236867],[508734.440525227,6651150.559163608,93.37945864810429],[508734.96708705934,6651138.915175093,97.13119528436867],[508735.70177135797,6651136.825630555,93.33393779836867],[508735.0733119117,6651138.613056809,96.89110683736867],[508735.6800304155,6651136.887464826,93.81120875036866],[508734.63481831976,6651150.003514597,92.91386796210429],[508734.4621597824,6651150.497292034,93.85672960010429],[508735.17345962784,6651138.328222747,96.62590911236867],[508734.63631864847,6651149.999223883,93.1176892461043],[508735.6423795607,6651136.994549103,94.29410977036868],[508735.26657890953,6651138.0633785315,96.33781076136867],[508735.6032220752,6651137.105918449,94.65581575536866],[508735.3518413021,6651137.820880404,96.02944195336866],[508735.55450932495,6651137.244464301,95.01357360136866],[508735.4285656095,6651137.60266578,95.70377484336868],[508735.4962354913,6651137.4102032045,95.36402981636869],[508734.6487765035,6651149.963596293,93.53426853410429],[508734.4996263967,6651150.390143155,94.33963062010429],[508734.6747448047,6651149.889330859,93.9585956541043],[508734.53859226924,6651150.278706622,94.7013366051043],[508734.5870666489,6651150.1400771905,95.0590944511043],[508734.71506411105,6651149.77402371,94.38490600510428],[508734.64505532564,6651149.974238301,95.4095506661043],[508734.7702239873,6651149.616274762,94.8067148641043],[508734.7123940721,6651149.781659619,95.74929569310429],[508734.8402909155,6651149.415893892,95.21706440710429],[508734.7887429372,6651149.563313353,96.07496280310428],[508734.92485965387,6651149.174040023,95.6088441011043],[508734.8735881074,6651149.320668933,96.3833316111043],[508734.9972836901,6651148.966918178,95.88632596110429],[508734.9662517198,6651149.055664944,96.67142996210428],[508735.0768209858,6651148.73945348,96.1467666341043],[508735.1627851194,6651148.4936089935,96.3877362801043],[508735.0659093737,6651148.770659049,96.93662768710429],[508735.25437406905,6651148.231678378,96.6071552861043],[508735.1716144261,6651148.468358504,97.1767161341043],[508735.2823275813,6651148.151735539,97.38996846910429],[508735.3836895157,6651147.861855659,96.8633684091043],[508735.3969498646,6651147.823933057,97.5751773711043],[508735.5191343467,6651147.474503822,97.07564621810431],[508735.51435684675,6651147.488166753,97.73166866310429],[508735.65836157516,6651147.076334898,97.24276097510429],[508735.6334320112,6651147.1476297,97.85929142210429],[508735.7990746194,6651146.673916763,97.36491409710429],[508735.7530973654,6651146.805404792,97.95838691610429],[508735.93913305504,6651146.273370711,97.44358879010429],[508735.91183025925,6651146.351452599,98.0475515681043],[508736.0766341495,6651145.8801382715,97.4813316491043],[508736.0676648333,6651145.905789166,98.0903268091043],[508736.6422518653,6651144.262556712,97.4813316491043],[508737.21987759497,6651142.610634039,97.4813316491043],[508737.2288476835,6651142.584980935,98.0903268091043],[508737.3573786894,6651142.217401598,97.44358879010429],[508738.66169342503,6651138.487257712,91.08506430210429],[508737.49743712496,6651141.816855546,97.36491409710429],[508737.3846822575,6651142.139317501,98.0475515681043],[508738.66169342503,6651138.487257712,91.2150643021043],[508737.6381501692,6651141.414437412,97.24276097510429],[508737.5434151514,6651141.685365309,97.95838691610429],[508738.8629056248,6651137.911821096,91.08506430210429],[508737.77737739775,6651141.016268489,97.07564621810431],[508737.6630805057,6651141.343140403,97.85929142210429],[508737.91282222874,6651140.628916651,96.8633684091043],[508738.66169342503,6651138.487257712,92.91386796110429],[508737.78215567,6651141.002603349,97.73166866310429],[508738.0421376754,6651140.259093932,96.6071552861043],[508738.6555890119,6651138.504715414,93.3246832731043],[508737.8995626522,6651140.666837046,97.5751773711043],[508738.6364996983,6651138.559307979,93.7458047011043],[508738.16304804775,6651139.91330846,96.3097128161043],[508738.2469537721,6651139.673350713,96.06200307610429],[508738.60344092076,6651138.653851108,94.17189383610429],[508738.0141849354,6651140.339034562,97.38996846910429],[508738.3241899215,6651139.452466948,95.79559676110429],[508738.8629056248,6651137.911821096,92.91386796110429],[508738.55573754676,6651138.790275581,94.5968003401043],[508738.41570473666,6651139.190748346,95.41571595910429],[508738.49310376926,6651138.96939876,95.0137670421043],[508738.12489809067,6651140.022411597,97.1767161341043],[508738.85598728986,6651137.931606493,93.37945864810429],[508738.23060314305,6651139.720111053,96.93662768710429],[508738.8343527343,6651137.993478066,93.85672960010429],[508738.33026079694,6651139.435105157,96.67142996210428],[508738.79688612005,6651138.1006269455,94.33963062010429],[508738.42292440933,6651139.1701011695,96.3833316111043],[508738.7579202475,6651138.212063477,94.7013366051043],[508738.50776957953,6651138.92745675,96.07496280310428],[508738.70944586786,6651138.35069291,95.0590944511043],[508738.58411844465,6651138.7091104835,95.74929569310429],[508738.65145719104,6651138.516531801,95.4095506661043],[508747.7847779702,6651155.193418403,91.26653404189648],[508747.9818306922,6651154.616544179,91.26653404189648],[508747.9818306922,6651154.616544179,91.39653404189649],[508747.7847779702,6651155.193418403,93.09533770089648],[508747.7915532887,6651155.173583576,93.56092838789648],[508747.98182993603,6651154.616546391,93.09533770189648],[508747.8127406126,6651155.11155743,94.03819933989648],[508747.98329924984,6651154.612244957,93.29915898589648],[508747.995499575,6651154.576528358,93.71573827389648],[508747.8494327134,6651155.004140861,94.52110035989648],[508748.02093105693,6651154.502077387,94.14006539389649],[508747.88759307977,6651154.892425927,94.8828063448965],[508748.0604168787,6651154.386482167,94.56637574489648],[508747.93506539235,6651154.753450158,95.24056419089648],[508747.99185532174,6651154.587196954,95.59102040589649],[508748.11443648476,6651154.228339116,94.98818460389649],[508748.05780203507,6651154.3941371525,95.93076543289648],[508748.1830549827,6651154.027457634,95.39853414689648],[508748.1325726092,6651154.175245394,96.25643254289649],[508748.265875508,6651153.784999545,95.79031384089649],[508748.21566385194,6651153.931994775,96.5648013508965],[508748.3368023877,6651153.577360247,96.06779570089648],[508748.30641191325,6651153.666328729,96.85289970189648],[508748.41469548084,6651153.349327276,96.32823637389649],[508748.4988825557,6651153.102868596,96.56920601989648],[508748.4040094346,6651153.380610805,97.11809742689648],[508748.58857816976,6651152.840283602,96.7886250258965],[508748.5075293421,6651153.077555024,97.35818587389649],[508748.61595382437,6651152.760141041,97.57143820889648],[508748.7152203951,6651152.4695369555,97.04483814889649],[508748.7282066249,6651152.431519611,97.75664711089648],[508748.84786529763,6651152.0812174,97.2571159578965],[508748.84318655875,6651152.094914465,97.91313840289648],[508748.98421440757,6651151.682053732,97.4242307148965],[508748.9598001899,6651151.753526649,98.04076116189648],[508749.1220186184,6651151.27863024,97.5463838368965],[508749.0769918105,6651151.410446763,98.13985665589648],[508749.2591817526,6651150.877083505,97.62505852989648],[508749.23244336294,6651150.955360464,98.22902130789649],[508749.3938404113,6651150.482868655,97.66280138889648],[508749.38505650964,6651150.508583633,98.2717965488965],[508749.9477656237,6651148.861245898,97.66280138889648],[508750.51345061907,6651147.205196234,97.66280138889648],[508750.5222352771,6651147.179479042,98.2717965488965],[508750.64810927777,6651146.810981384,97.62505852989648],[508751.9254610946,6651143.071518497,91.26653404189648],[508751.9254610946,6651143.071518497,91.39653404189649],[508750.78527241194,6651146.409434651,97.5463838368965],[508750.67484842386,6651146.73270221,98.22902130789649],[508750.92307662277,6651146.006011156,97.4242307148965],[508750.8302999763,6651146.277615911,98.13985665589648],[508752.12251381646,6651142.494644271,91.26653404189648],[508751.05942573276,6651145.606847488,97.2571159578965],[508750.9474915969,6651145.934536026,98.04076116189648],[508751.9254610946,6651143.071518497,93.09533770089648],[508751.19207063527,6651145.218527934,97.04483814889649],[508751.06410522806,6651145.59314821,97.91313840289648],[508751.91948287253,6651143.0890198145,93.50615301289649],[508751.31871286064,6651144.8477812875,96.7886250258965],[508751.1790851619,6651145.256543064,97.75664711089648],[508751.90078817494,6651143.143748769,93.9272744408965],[508751.43712376215,6651144.501131942,96.49118255589649],[508751.86841279175,6651143.238528093,94.35336357589648],[508751.5192949794,6651144.26057471,96.24347281589648],[508752.12251381646,6651142.494644271,93.09533770089648],[508751.2913379624,6651144.927921632,97.57143820889648],[508751.59493449575,6651144.039139111,95.97706650089648],[508751.8216955464,6651143.375293394,94.77827007989649],[508751.6845575079,6651143.77676666,95.59718569889648],[508751.7603565403,6651143.554864077,95.1952367818965],[508751.3997624447,6651144.61050765,97.35818587389649],[508752.11573849805,6651142.514479098,93.56092838789648],[508751.5032823521,6651144.307451869,97.11809742689648],[508752.0945511742,6651142.576505245,94.03819933989648],[508751.6008798735,6651144.021733946,96.85289970189648],[508752.0578590733,6651142.683921814,94.52110035989648],[508751.69162793487,6651143.7560679,96.5648013508965],[508752.01969870704,6651142.795636747,94.8828063448965],[508751.77471917757,6651143.512817281,96.25643254289649],[508751.9722263944,6651142.934612516,95.24056419089648],[508751.8494897516,6651143.293925522,95.93076543289648],[508751.9154364651,6651143.100865722,95.59102040589649],[508753.2566042391,6651157.053503849,91.33631063381246],[508753.45195224613,6651156.4760501245,91.33631063381246],[508753.45195224613,6651156.4760501245,91.46631063381247],[508753.2566042391,6651157.053503849,93.16511429281246],[508753.26332094386,6651157.033649098,93.63070497981245],[508753.45195149665,6651156.47605234,93.16511429381245],[508753.2843249749,6651156.971560642,94.10797593181246],[508753.4534080993,6651156.471746585,93.36893557781245],[508753.4655028787,6651156.435994107,93.78551486581246],[508753.3206996502,6651156.864036168,94.59087695181246],[508753.4907143513,6651156.361468348,94.20984198581245],[508753.358529889,6651156.752209012,94.95258293681245],[508753.529858579,6651156.245757005,94.63615233681244],[508753.40559151577,6651156.613093634,95.31034078281245],[508753.461890152,6651156.446673419,95.66079699781247],[508753.5834108582,6651156.087455093,95.05796119581247],[508753.5272663565,6651156.253419681,96.00054202481246],[508753.65143573337,6651155.886371815,95.46831073881245],[508753.6013900858,6651156.034308034,96.32620913481244],[508753.7335397734,6651155.643670166,95.86009043281247],[508753.6837625013,6651155.790813059,96.63457794281246],[508753.80385306035,6651155.435822284,96.13757229281245],[508753.77372549573,6651155.524880138,96.92267629381246],[508753.8810722957,6651155.20756024,96.39801296581246],[508753.9645310631,6651154.960853982,96.63898261181245],[508753.87047869514,6651155.238875196,97.18787401881245],[508754.0534507151,6651154.698005208,96.85840161781245],[508753.9731030456,6651154.935514982,97.42796246581246],[508754.17899735103,6651154.32688613,97.11461474081246],[508754.0805895413,6651154.617782141,97.64121480081245],[508754.1918712361,6651154.288830593,97.82642370281246],[508754.3104947345,6651153.938176488,97.32689254981246],[508754.30585647165,6651153.951887311,97.98291499481245],[508754.44566428015,6651153.5386118395,97.49400730681245],[508754.4214612713,6651153.610156555,98.11053775381247],[508754.5822763385,6651153.134783087,97.61616042881245],[508754.53763906023,6651153.266732028,98.20963324781246],[508754.7182528663,6651152.73283298,97.69483512181246],[508754.69174579193,6651152.811188572,98.29879789981247],[508754.8517465848,6651152.338222121,97.73257798081245],[508754.8430386732,6651152.363962931,98.34157314081246],[508755.40087975713,6651150.714970364,97.73257798081245],[508755.9616709778,6651149.05725712,97.73257798081245],[508755.9703796392,6651149.031514091,98.34157314081246],[508756.09516469634,6651148.662646259,97.69483512181246],[508757.3614660662,6651144.919426898,91.33631063381246],[508757.3614660662,6651144.919426898,91.46631063381247],[508756.23114122404,6651148.260696153,97.61616042881245],[508756.1216725205,6651148.58428845,98.29879789981247],[508756.36775328236,6651147.856867401,97.49400730681245],[508757.5568140733,6651144.341973173,91.33631063381246],[508756.2757792522,6651148.128744994,98.20963324781246],[508756.502922828,6651147.457302753,97.32689254981246],[508756.3919570411,6651147.785320468,98.11053775381247],[508757.3614660662,6651144.919426898,93.16511429281246],[508756.63442021154,6651147.068593111,97.11461474081246],[508756.50756184076,6651147.4435897125,97.98291499481245],[508757.3555395622,6651144.936945797,93.57592960481244],[508756.7599668474,6651146.697474032,96.85840161781245],[508757.33700659353,6651144.991729728,93.99705103281245],[508756.6215470763,6651147.106646429,97.82642370281246],[508756.87735336926,6651146.35047646,96.56095914781245],[508757.30491129163,6651145.086604264,94.42314016781245],[508756.95881371835,6651146.109677576,96.31324940781246],[508757.5568140733,6651144.341973173,93.16511429281246],[508756.7328287711,6651146.777694883,97.64121480081245],[508757.2585982,6651145.223506953,94.84804667181247],[508757.0337988728,6651145.888019536,96.04684309281245],[508757.1977898413,6651145.403258021,95.26501337381245],[508757.1226465509,6651145.625383517,95.66696229081245],[508757.55009736854,6651144.361827926,93.63070497981245],[508756.84031526675,6651146.459962042,97.42796246581246],[508756.94293961726,6651146.156601827,97.18787401881245],[508757.5290933375,6651144.423916382,94.10797593181246],[508757.0396928167,6651145.870596886,96.92267629381246],[508757.4927186622,6651144.531440855,94.59087695181246],[508757.1296558111,6651145.604663963,96.63457794281246],[508757.45488842344,6651144.6432680115,94.95258293681245],[508757.2120282266,6651145.361168989,96.32620913481244],[508757.40782679664,6651144.782383389,95.31034078281245],[508757.2861519559,6651145.142057342,96.00054202481246],[508757.35152816033,6651144.948803603,95.66079699781247],[508764.36245595507,6651160.77352044,91.46976384454798],[508764.5543440002,6651160.194907766,91.46976384454798],[508764.5543440002,6651160.194907766,91.599763844548],[508764.36245595507,6651160.77352044,93.29856750354799],[508764.36905369506,6651160.75362584,93.76415819054799],[508764.5543432639,6651160.194909986,93.29856750454799],[508764.3896857072,6651160.691412774,94.24142914254799],[508764.5557740675,6651160.19059559,93.50238878854799],[508764.5676546268,6651160.154771357,93.91896807654798],[508764.4254161221,6651160.583672497,94.72433016254799],[508764.5924195593,6651160.080096022,94.343295196548],[508764.4625763197,6651160.471620903,95.086036147548],[508764.63087047276,6651159.964152448,94.76960554754798],[508764.50880440115,6651160.332226322,95.443793993548],[508764.564105888,6651160.165472102,95.794250208548],[508764.6834742455,6651159.805532824,95.19141440654799],[508764.62832416315,6651159.971830503,96.13399523554799],[508764.75029427867,6651159.604045973,95.60176394954799],[508764.70113502897,6651159.7522791,96.459662345548],[508764.83094410953,6651159.36085722,95.993543643548],[508764.78204848187,6651159.50829543,96.768031153548],[508764.9000120227,6651159.15259219,96.27102550354799],[508764.8704180711,6651159.2418287825,97.05612950454798],[508764.97586356755,6651158.923872025,96.531466176548],[508765.0578441312,6651158.676670627,96.772435822548],[508764.9654575986,6651158.955249829,97.32132722954799],[508765.1451888574,6651158.413294315,96.991854828548],[508765.0662642886,6651158.65128077,97.561415676548],[508765.2685118383,6651158.041430401,97.248067951548],[508765.17184700654,6651158.33291024,97.77466801154799],[508765.2811577039,6651158.003298488,97.95987691354799],[508765.3976801684,6651157.65194062,97.46034576054801],[508765.3931240574,6651157.665678961,98.11636820554799],[508765.53045562014,6651157.251574045,97.62746051754799],[508765.5066812897,6651157.323262351,98.24399096454799],[508765.66464803496,6651156.846934809,97.74961363954799],[508765.62080136256,6651156.979148571,98.34308645854799],[508765.7982161757,6651156.44417799,97.82828833254798],[508765.7721785889,6651156.522690841,98.432251110548],[508765.9293454822,6651156.048775146,97.866031191548],[508765.9207918033,6651156.074567618,98.475026351548],[508766.46875252575,6651154.422265525,97.866031191548],[508767.01961113274,6651152.761225251,97.866031191548],[508767.02816554817,6651152.735430557,98.475026351548],[508767.15074043913,6651152.365822407,97.82828833254798],[508768.39461335127,6651148.615090409,91.46976384454798],[508768.39461335127,6651148.615090409,91.599763844548],[508767.28430857987,6651151.963065587,97.74961363954799],[508767.17677876254,6651152.287307334,98.432251110548],[508767.4185009948,6651151.558426351,97.62746051754799],[508768.5865013963,6651148.036477735,91.46976384454798],[508767.3281559888,6651151.830849605,98.34308645854799],[508767.55127644655,6651151.158059778,97.46034576054801],[508767.44227606175,6651151.4867358245,98.24399096454799],[508768.39461335127,6651148.615090409,93.29856750354799],[508767.68044477655,6651150.768569997,97.248067951548],[508768.3887918162,6651148.632644468,93.709382815548],[508767.55583329406,6651151.144319215,98.11636820554799],[508767.80376775743,6651150.396706083,96.991854828548],[508768.3705870994,6651148.68753835,94.130504243548],[508767.66779964755,6651150.806699689,97.95987691354799],[508767.9190751544,6651150.049012086,96.69441235854799],[508768.3390602627,6651148.782603299,94.55659337854799],[508768.5865013963,6651148.036477735,93.29856750354799],[508767.99909269536,6651149.807729919,96.44670261854799],[508768.2935674586,6651148.919780752,94.981499882548],[508768.0727497287,6651149.585627011,96.18029630354799],[508767.7771103449,6651150.477087936,97.77466801154799],[508768.2338361244,6651149.099892582,95.398466584548],[508768.16002375586,6651149.322463883,95.80041550154799],[508768.5799036564,6651148.056372336,93.76415819054799],[508767.8826930628,6651150.158717405,97.561415676548],[508768.5592716442,6651148.118585402,94.24142914254799],[508767.9834997528,6651149.854748346,97.32132722954799],[508768.07853928034,6651149.5681693945,97.05612950454798],[508768.52354122937,6651148.226325678,94.72433016254799],[508768.1669088696,6651149.301702744,96.768031153548],[508768.48638103175,6651148.338377273,95.086036147548],[508768.2478223225,6651149.057719076,96.459662345548],[508768.4401529504,6651148.477771853,95.443793993548],[508768.38485146343,6651148.644526073,95.794250208548],[508768.32063318836,6651148.838167672,96.13399523554799],[508772.1444917337,6651163.336241752,91.55678584387401],[508772.33395533194,6651162.756830677,91.55678584387401],[508772.33395533194,6651162.756830677,91.686785843874],[508772.1444917337,6651163.336241752,93.385589502874],[508772.1510061133,6651163.316319699,93.851180189874],[508772.3339546049,6651162.7568329,93.385589503874],[508772.1713774462,6651163.254020788,94.32845114187401],[508772.33536733076,6651162.752512552,93.58941078787402],[508772.3470977828,6651162.716638885,94.005990075874],[508772.20665641816,6651163.146131848,94.811352161874],[508772.37154981797,6651162.641860511,94.430317195874],[508772.24334710813,6651163.0339256385,95.17305814687401],[508772.4095149159,6651162.525756951,94.856627546874],[508772.2889911118,6651162.894338713,95.53081599287401],[508772.34359388123,6651162.727354397,95.881272207874],[508772.461454056,6651162.366918456,95.27843640587402],[508772.4070007781,6651162.533445602,96.221017234874],[508772.5274298385,6651162.165153583,95.688785948874],[508772.47889170086,6651162.313591248,96.546684344874],[508772.60706068337,6651161.921629265,96.080565642874],[508772.55878283695,6651162.069270918,96.855053152874],[508772.6752559445,6651161.713076858,96.358047502874],[508772.64603590337,6651161.802436585,97.143151503874],[508772.75014912826,6651161.484041093,96.618488175874],[508772.8310938925,6651161.236498593,96.85945782187402],[508772.73987463553,6651161.5154621955,97.408349228874],[508772.9173350447,6651160.972758862,97.078876827874],[508772.83940766373,6651161.211073703,97.648437675874],[508773.0390998774,6651160.60038183,97.335089950874],[508772.9436563763,6651160.892263868,97.861690010874],[508773.0515859663,6651160.562197301,98.04689891287401],[508773.16663620505,6651160.2103546085,97.547367759874],[508773.1621376592,6651160.224111907,98.203390204874],[508773.2977340795,6651159.809435588,97.714482516874],[508773.27426013054,6651159.881222813,98.331012963874],[508773.4302310141,6651159.40423801,97.836635638874],[508773.38693833107,6651159.536634209,98.430108457874],[508773.5621115622,6651159.000925444,97.915310331874],[508773.53640295233,6651159.079546632,98.519273109874],[508773.6915840899,6651158.604977004,97.95305319087402],[508773.683138484,6651158.630805066,98.56204835087401],[508774.22417589,6651156.976223038,97.95305319087402],[508774.7680745667,6651155.312890771,97.95305319087402],[508774.89754709427,6651154.91694233,97.915310331874],[508774.77652089973,6651155.287060485,98.56204835087401],[508776.1257040518,6651151.161034873,91.55678584387401],[508776.1257040518,6651151.161034873,91.686785843874],[508775.0294276423,6651154.513629765,97.836635638874],[508774.9232564314,6651154.838318918,98.519273109874],[508776.31516765006,6651150.581623798,91.55678584387401],[508775.1619245771,6651154.108432187,97.714482516874],[508775.0727210527,6651154.381231342,98.430108457874],[508775.2930224514,6651153.707513166,97.547367759874],[508775.1853992532,6651154.036642737,98.331012963874],[508776.1257040518,6651151.161034873,93.385589502874],[508775.4205587791,6651153.317485945,97.335089950874],[508776.11995607,6651151.178613153,93.796404814874],[508775.29752172454,6651153.693753643,98.203390204874],[508775.54232361173,6651152.945108913,97.078876827874],[508776.10198136437,6651151.233582781,94.21752624287402],[508775.4080734175,6651153.35566825,98.04689891287401],[508775.6561741349,6651152.59693515,96.781434357874],[508776.0708528595,6651151.328778906,94.643615377874],[508776.31516765006,6651150.581623798,93.385589502874],[508775.7351806786,6651152.355320049,96.53372461787401],[508776.0259348432,6651151.466145642,95.06852188187402],[508775.8079070779,6651152.132910673,96.267318302874],[508775.9669581962,6651151.646506001,95.485488583874],[508775.5160030074,6651153.025601682,97.861690010874],[508775.8940784244,6651151.869384417,95.887437500874],[508776.3086532705,6651150.601545851,93.851180189874],[508775.62025171996,6651152.706791848,97.648437675874],[508776.28828193754,6651150.663844762,94.32845114187401],[508775.7197847482,6651152.402403356,97.408349228874],[508776.2530029656,6651150.771733703,94.811352161874],[508775.8136234803,6651152.1154289665,97.143151503874],[508776.2163122756,6651150.883939912,95.17305814687401],[508775.9008765468,6651151.848594632,96.855053152874],[508776.17066827195,6651151.023526837,95.53081599287401],[508775.98076768295,6651151.604274302,96.546684344874],[508776.11606550246,6651151.190511154,95.881272207874],[508776.0526586056,6651151.384419949,96.221017234874],[508780.98935330793,6651166.2052080715,91.64923286031915],[508781.1760613422,6651165.624903189,91.64923286031915],[508781.1760613422,6651165.624903189,91.77923286031915],[508780.98935330793,6651166.2052080715,93.47803651931915],[508780.9957729421,6651166.185255287,93.94362720631915],[508781.17606062576,6651165.624905415,93.47803652031915],[508781.0158479939,6651166.122860272,94.42089815831915],[508781.17745280487,6651165.620578401,93.68185780431915],[508781.1890126489,6651165.584649395,94.09843709231914],[508781.0506138674,6651166.0148049,94.90379917831915],[508781.21310905286,6651165.509755666,94.52276421231916],[508781.0867709269,6651165.902425601,95.26550516331916],[508781.25052198535,6651165.393473004,94.94907456331914],[508781.1317510829,6651165.7626233455,95.62326300931916],[508781.18555970816,6651165.595381437,95.97371922431915],[508781.3017057211,6651165.234389482,95.37088342231915],[508781.2480444133,6651165.401173515,96.31346425131915],[508781.36672195,6651165.032313361,95.78123296531915],[508781.3188897525,6651165.180980011,96.63913136131916],[508781.4451946417,6651164.78841338,96.17301265931916],[508781.39761894965,6651164.936282787,96.94750016931917],[508781.512398069,6651164.579539256,96.45049451931915],[508781.48360300495,6651164.669036831,97.23559852031914],[508781.58620200417,6651164.350150177,96.71093519231916],[508781.66596950544,6651164.102225814,96.95190483831915],[508781.5760769439,6651164.381619749,97.50079624531915],[508781.750956364,6651163.838079233,97.17132384431916],[508781.6741623611,6651164.076761703,97.74088469231916],[508781.8709502454,6651163.465127764,97.42753696731916],[508781.77689487726,6651163.757460066,97.95413702731915],[508781.88325473625,6651163.426884332,98.13934592931915],[508781.9966316811,6651163.074498882,97.63981477631917],[508781.9921985622,6651163.088277403,98.29583722131915],[508782.12582286436,6651162.672961397,97.80692953331916],[508782.1026903211,6651162.744859362,98.42345998031915],[508782.2563927599,6651162.267138755,97.92908265531916],[508782.21372972673,6651162.399739189,98.52255547431915],[508782.3863552335,6651161.863204031,98.00775734831915],[508782.36102053046,6651161.941946502,98.61172012631916],[508782.51394470903,6651161.466644794,98.04550020731915],[508782.50562193635,6651161.492512698,98.65449536731917],[508783.038790479,6651159.835378285,98.04550020731915],[508783.5747786779,6651158.169480134,98.04550020731915],[508784.9126627614,6651154.011219511,91.64923286031915],[508783.7023681535,6651157.772920896,98.00775734831915],[508783.58310216723,6651158.143610002,98.65449536731917],[508784.9126627614,6651154.011219511,91.77923286031915],[508783.8323306271,6651157.3689861735,97.92908265531916],[508783.72770357324,6651157.694176198,98.61172012631916],[508785.09937079577,6651153.430914629,91.64923286031915],[508783.96290052263,6651156.9631635295,97.80692953331916],[508783.8749943768,6651157.236383512,98.52255547431915],[508784.0920917058,6651156.561626046,97.63981477631917],[508784.9126627614,6651154.011219511,93.47803651931915],[508783.9860337824,6651156.891263337,98.42345998031915],[508784.2177731415,6651156.170997163,97.42753696731916],[508784.9069983784,6651154.028824909,93.88885183131916],[508784.09652554145,6651156.547845297,98.29583722131915],[508784.337767023,6651155.798045695,97.17132384431916],[508784.8892850974,6651154.083879335,94.30997325931916],[508784.2054693673,6651156.209238368,98.13934592931915],[508784.8586093265,6651154.17922231,94.73606239431915],[508784.44996170094,6651155.449334833,96.87388137431915],[508785.09937079577,6651153.430914629,93.47803651931915],[508784.52781917126,6651155.207347013,96.62617163431915],[508784.8143445989,6651154.31680095,95.16096889831915],[508784.5994878357,6651154.984594543,96.35976531931915],[508784.75622571004,6651154.497439536,95.57793560031917],[508784.6844059036,6651154.720661768,95.97988451731915],[508784.3118292263,6651155.878662633,97.95413702731915],[508785.0929511615,6651153.450867412,93.94362720631915],[508784.4145617426,6651155.559360998,97.74088469231916],[508785.07287610974,6651153.513262427,94.42089815831915],[508784.5126471597,6651155.25450295,97.50079624531915],[508785.0381102361,6651153.6213178,94.90379917831915],[508784.60512109863,6651154.967085869,97.23559852031914],[508785.0019531767,6651153.7336971,95.26550516331916],[508784.691105154,6651154.699839912,96.94750016931917],[508784.9569730207,6651153.873499355,95.62326300931916],[508784.7698343512,6651154.455142689,96.63913136131916],[508784.9031643955,6651154.040741263,95.97371922431915],[508784.8406796903,6651154.2349491855,96.31346425131915],[508791.0953147082,6651169.42651253,91.7464899322843],[508791.2788742904,6651168.845204068,91.7464899322843],[508791.2788742904,6651168.845204068,91.87648993228431],[508791.0953147082,6651169.42651253,93.57529359128431],[508791.10162608826,6651169.40652524,94.0408842782843],[508791.2788735861,6651168.845206299,93.5752935922843],[508791.121362615,6651169.34402232,94.51815523028431],[508791.2802422889,6651168.8408718025,93.7791148762843],[508791.2916071996,6651168.804880661,94.1956941642843],[508791.15554223274,6651169.235780076,95.00105625028431],[508791.3152972667,6651168.729857411,94.62002128428429],[508791.19108957675,6651169.123206427,95.3627622352843],[508791.352079306,6651168.61337365,95.04633163528429],[508791.23531123373,6651168.983162398,95.72052008128429],[508791.40239993186,6651168.454015007,95.46814049428431],[508791.2882124857,6651168.815631263,96.07097629628431],[508791.34964351315,6651168.621087477,96.4107213232843],[508791.466319794,6651168.251589417,95.8784900372843],[508791.41929418937,6651168.400513171,96.73638843328429],[508791.54346920294,6651168.007267636,96.27026973128432],[508791.4966957784,6651168.155392769,97.0447572412843],[508791.6095393809,6651167.798032286,96.5477515912843],[508791.68209876254,6651167.5682465015,96.8081922642843],[508791.5812298872,6651167.887684638,97.3328555922843],[508791.7605211467,6651167.319893379,97.0491619102843],[508791.67214444076,6651167.599770498,97.5980533172843],[508791.8440748743,6651167.055289983,97.2685809162843],[508791.7685758464,6651167.29438523,97.8381417642843],[508791.9620453025,6651166.681693533,97.5247940392843],[508791.8695759873,6651166.974531394,98.0513940992843],[508791.9741423031,6651166.643383963,98.23660300128431],[508792.08560737595,6651166.290389098,97.7370718482843],[508792.0812490126,6651166.304191447,98.39309429328429],[508792.212620012,6651165.8881571945,97.9041866052843],[508792.1898775523,6651165.960179501,98.52071705228431],[508792.3409881112,6651165.481632723,98.0263397272843],[508792.2990445036,6651165.614462476,98.61981254628431],[508792.4687590315,6651165.076999436,98.1050144202843],[508792.4438515468,6651165.155878084,98.70897719828432],[508792.5941969695,6651164.679754389,98.1427572792843],[508792.5860145435,6651164.705667031,98.7517524392843],[508793.1101922808,6651163.045666771,98.1427572792843],[508793.6371421265,6651161.376887619,98.1427572792843],[508794.9524655103,6651157.211435708,91.7464899322843],[508794.9524655103,6651157.211435708,91.87648993228431],[508793.76258006453,6651160.979642573,98.1050144202843],[508793.64532525715,6651161.3509727465,98.7517524392843],[508793.8903509847,6651160.575009286,98.0263397272843],[508793.7874882538,6651160.900761694,98.70897719828432],[508795.13602509245,6651156.630127247,91.7464899322843],[508794.018719084,6651160.168484814,97.9041866052843],[508793.932295297,6651160.442177301,98.61981254628431],[508794.1457317201,6651159.766252911,97.7370718482843],[508794.9524655103,6651157.211435708,93.57529359128431],[508794.04146224837,6651160.096460278,98.52071705228431],[508794.9468966456,6651157.229071553,93.98610890328429],[508794.2692937934,6651159.3749484755,97.5247940392843],[508794.150090788,6651159.752448331,98.39309429328429],[508794.92948206305,6651157.284221189,94.4072303312843],[508794.3872642216,6651159.001352027,97.2685809162843],[508795.13602509245,6651156.630127247,93.57529359128431],[508794.89932357677,6651157.379729051,94.8333194662843],[508794.49756696407,6651158.652038105,96.9711384462843],[508794.2571974974,6651159.413255814,98.23660300128431],[508794.85580528405,6651157.51754562,95.25822597028431],[508794.57411152613,6651158.4096317915,96.72342870628431],[508794.644571644,6651158.186494092,96.4570223912843],[508794.79866645223,6651157.6984966,95.6751926722843],[508794.7280577411,6651157.922104873,96.0771415892843],[508795.1297137123,6651156.650114537,94.0408842782843],[508794.36176381324,6651159.082108383,98.0513940992843],[508794.4627639542,6651158.762254546,97.8381417642843],[508795.10997718555,6651156.712617458,94.51815523028431],[508794.5591953598,6651158.456869281,97.5980533172843],[508795.07579756796,6651156.820859702,95.00105625028431],[508794.6501099134,6651158.16895514,97.3328555922843],[508795.0402502238,6651156.93343335,95.3627622352843],[508794.73464402213,6651157.901247009,97.0447572412843],[508794.99602856697,6651157.073477378,95.72052008128429],[508794.8120456112,6651157.656126606,96.73638843328429],[508794.94312731485,6651157.241008515,96.07097629628431],[508794.8816962875,6651157.435552301,96.4107213232843],[508797.66414135316,6651171.488047247,91.80494108921562],[508797.8456544565,6651170.906096526,91.80494108921562],[508797.8456544565,6651170.906096526,91.93494108921564],[508797.66414135316,6651171.488047247,93.63374474821562],[508797.6703823686,6651171.468037874,94.09933543521562],[508797.8456537601,6651170.90609876,93.63374474921562],[508797.6898988557,6651171.405465897,94.57660638721562],[508797.8470072035,6651170.901759473,93.83756603321562],[508797.85824540845,6651170.865728568,94.25414532121562],[508797.72369740985,6651171.2971040625,95.05950740721562],[508797.8816713584,6651170.790622428,94.67847244121562],[508797.7588484418,6651171.1844060365,95.42121339221562],[508797.9180433202,6651170.674009969,95.10478279221563],[508797.802577078,6651171.044207281,95.77897123821562],[508797.96780292894,6651170.514475261,95.52659165121563],[508797.85488854174,6651170.8764910465,96.12942745321564],[508797.9156346836,6651170.68173232,96.46917248021562],[508798.0310101579,6651170.311826021,95.93694119421562],[508797.9845088348,6651170.460914312,96.79483959021562],[508798.1072994394,6651170.0672343,96.32872088821563],[508798.0610474849,6651170.215523088,97.10320839821563],[508798.1726330106,6651169.857767776,96.60620274821562],[508798.2443834383,6651169.627728113,96.86664342121563],[508798.1446391353,6651169.947519179,97.39130674921562],[508798.32193150296,6651169.3791005965,97.10761306721562],[508798.23454009584,6651169.659286938,97.65650447421564],[508798.4045537023,6651169.114204854,97.32703207321562],[508798.3298964019,6651169.353564266,97.89659292121564],[508798.52120889554,6651168.740195637,97.58324519621564],[508798.4297705071,6651169.033357039,98.10984525621564],[508798.5331710284,6651168.701843739,98.29505415821562],[508798.64339339343,6651168.3484588675,97.79552300521563],[508798.63908362086,6651168.362276467,98.45154545021563],[508798.76898998435,6651167.945782559,97.96263776221562],[508798.7465010769,6651168.017884438,98.57916820921564],[508798.8959269265,6651167.538808937,98.08479088421562],[508798.8544509421,6651167.671785448,98.67826370321563],[508799.0222733476,6651167.133728593,98.16346557721562],[508798.9976435527,6651167.212694388,98.76742835521563],[508799.1463127965,6651166.736044649,98.20120843621562],[508799.13822159515,6651166.7619859185,98.81020359621563],[508799.65655535174,6651165.10015161,98.20120843621562],[508800.1776303111,6651163.429528705,98.20120843621562],[508801.4782893478,6651159.259474593,91.80494108921562],[508801.4782893478,6651159.259474593,91.93494108921564],[508800.30166975997,6651163.031844763,98.16346557721562],[508800.1857222093,6651163.403585201,98.81020359621563],[508800.428016181,6651162.626764416,98.08479088421562],[508801.65980245115,6651158.677523874,91.80494108921562],[508800.32630025153,6651162.952876732,98.76742835521563],[508800.5549531232,6651162.219790796,97.96263776221562],[508800.46949286223,6651162.493785672,98.67826370321563],[508801.4782893478,6651159.259474593,93.63374474821562],[508800.68054971413,6651161.817114487,97.79552300521563],[508800.5774427274,6651162.147686682,98.57916820921564],[508801.47278256953,6651159.277129922,94.04456006021562],[508800.802734212,6651161.425377718,97.58324519621564],[508801.4555621396,6651159.33234049,94.46568148821562],[508800.68486018345,6651161.803294654,98.45154545021563],[508800.9193894053,6651161.0513685,97.32703207321562],[508801.65980245115,6651158.677523874,93.63374474821562],[508801.42573988595,6651159.427953876,94.89177062321563],[508801.0284623986,6651160.70166864,97.02958960321564],[508800.7907727759,6651161.463727381,98.29505415821562],[508801.38270677225,6651159.565922711,95.31667712721563],[508801.1041535766,6651160.458994503,96.78187986321562],[508801.173828145,6651160.235610271,96.51547354821564],[508801.32620497287,6651159.747073614,95.73364382921562],[508801.2563834678,6651159.970928941,96.13559274621562],[508801.6535614357,6651158.697533246,94.09933543521562],[508800.8941732972,6651161.1322140815,98.10984525621564],[508801.6340449486,6651158.760105223,94.57660638721562],[508800.9940474024,6651160.812006854,97.89659292121564],[508801.0894037084,6651160.506284182,97.65650447421564],[508801.60024639446,6651158.868467058,95.05950740721562],[508801.179304669,6651160.21805194,97.39130674921562],[508801.5650953625,6651158.981165084,95.42121339221562],[508801.2628963195,6651159.950048032,97.10320839821563],[508801.5213667263,6651159.12136384,95.77897123821562],[508801.33943496953,6651159.704656808,96.79483959021562],[508801.46905526257,6651159.289080073,96.12942745321564],[508801.4083091207,6651159.4838388,96.46917248021562],[508810.1071119834,6651175.323685916,91.90542289905302],[508810.2847485534,6651174.740540226,91.90542289905302],[508810.2847485534,6651174.740540226,92.03542289905302],[508810.1071119834,6651175.323685916,93.73422655805301],[508810.1132197108,6651175.303635455,94.19981724505301],[508810.2847478718,6651174.740542462,93.73422655905301],[508810.1323193889,6651175.240934993,94.67708819705302],[508810.28607240994,6651174.736194265,93.93804784305303],[508810.2970706032,6651174.700089375,94.35462713105301],[508810.1653961152,6651175.132350651,95.15998921705301],[508810.31999625056,6651174.624829014,94.77895425105301],[508810.1997964346,6651175.019421211,95.52169520205301],[508810.3555914248,6651174.507977105,95.205264602053],[508810.24259116844,6651174.878934573,95.87945304805302],[508810.40428832907,6651174.348114808,95.62707346105303],[508810.29378542834,6651174.710873954,96.22990926305302],[508810.3532342289,6651174.515715311,96.56965429005301],[508810.46614565584,6651174.145049451,96.03742300405301],[508810.4206374507,6651174.294443878,96.895321400053],[508810.5408056448,6651173.899955488,96.42920269805303],[508810.4955414826,6651174.048548771,97.20369020805302],[508810.60474390205,6651173.690058848,96.70668455805301],[508810.67496197246,6651173.459546825,96.96712523105302],[508810.5773478855,6651173.779994546,97.49178855905302],[508810.750853861,6651173.21040878,97.20809487705303],[508810.665328852,6651173.491170452,97.75698628405301],[508810.8317115172,6651172.944969103,97.42751388305301],[508810.75864865555,6651173.184820014,97.99707473105302],[508810.9458753324,6651172.5701919,97.68372700605302],[508810.85638977255,6651172.863955278,98.21032706605301],[508810.95758199284,6651172.531761251,98.39553596805303],[508811.0654503643,6651172.177650744,97.89600481505302],[508811.0612326346,6651172.191496716,98.55202726005301],[508811.1883646179,6651171.774147584,98.06311957205301],[508811.1663560008,6651171.846397517,98.67965001905301],[508811.3125905971,6651171.36633829,98.18527269405301],[508811.27200040565,6651171.499587852,98.77874551305301],[508811.4362386668,6651170.960426157,98.26394738705301],[508811.41213488486,6651171.039554101,98.86791016505303],[508811.55762903386,6651170.561925614,98.30169024605303],[508811.54971063446,6651170.587920152,98.91068540605302],[508812.056974457,6651168.922673453,98.30169024605303],[508812.5669209389,6651167.248620112,98.30169024605303],[508813.83980210137,6651163.070003264,91.90542289905302],[508813.83980210137,6651163.070003264,92.03542289905302],[508812.68831130594,6651166.850119569,98.26394738705301],[508812.5748400202,6651167.222623335,98.91068540605302],[508814.0174386713,6651162.486857572,91.90542289905302],[508812.8119593757,6651166.444207436,98.18527269405301],[508812.7124157698,6651166.770989386,98.86791016505303],[508812.936185355,6651166.036398141,98.06311957205301],[508812.852550249,6651166.310955635,98.77874551305301],[508813.83980210137,6651163.070003264,93.73422655805301],[508813.05909960857,6651165.632894982,97.89600481505302],[508813.8344129301,6651163.087694844,94.145041870053],[508812.9581946539,6651165.9641459705,98.67965001905301],[508813.1786746405,6651165.2403538255,97.68372700605302],[508813.81756027293,6651163.143018781,94.56616329805301],[508813.0633180202,6651165.619046772,98.55202726005301],[508813.2928384557,6651164.865576622,97.42751388305301],[508814.0174386713,6651162.486857572,93.73422655805301],[508813.7883749262,6651163.238828498,94.99225243305301],[508813.39958200237,6651164.515158691,97.13007141305302],[508813.74626086076,6651163.377080636,95.41715893705303],[508813.1669686618,6651165.278782236,98.39553596805303],[508813.47365666134,6651164.271986252,96.88236167305303],[508813.6909657572,6651163.558603514,95.83412563905301],[508814.0113309439,6651162.506908032,94.19981724505301],[508813.54184320604,6651164.048143325,96.61595535805301],[508813.62263541395,6651163.782918502,96.23607455605301],[508813.26816088223,6651164.946588212,98.21032706605301],[508813.9922312659,6651162.569608494,94.67708819705302],[508813.36590199923,6651164.625723476,97.99707473105302],[508813.9591545395,6651162.678192838,95.15998921705301],[508813.45922180265,6651164.319373035,97.75698628405301],[508813.9247542201,6651162.791122275,95.52169520205301],[508813.5472027692,6651164.03054894,97.49178855905302],[508813.8819594862,6651162.931608914,95.87945304805302],[508813.6290091721,6651163.761994716,97.20369020805302],[508813.8307652264,6651163.099669534,96.22990926305302],[508813.703913204,6651163.5160996085,96.895321400053],[508813.7713164258,6651163.294828177,96.56965429005301],[508814.38548758865,6651176.62161581,91.93688853122363],[508814.5617912562,6651176.038065758,91.93688853122363],[508814.5617912562,6651176.038065758,92.06688853122364],[508814.38548758865,6651176.62161581,93.76569219022363],[508814.39154948655,6651176.601551446,94.23128287722363],[508814.5617905797,6651176.038067996,93.76569219122364],[508814.41050584946,6651176.538807507,94.70855382922363],[508814.56310517923,6651176.033716784,93.96951347522364],[508814.57402084715,6651175.9975868575,94.38609276322363],[508814.4433343833,6651176.430147869,95.19145484922363],[508814.5967744711,6651175.92227431,94.81041988322364],[508814.47747657873,6651176.317140124,95.55316083422365],[508814.6321025556,6651175.805341372,95.23673023422363],[508814.51995020075,6651176.176556069,95.91091868022365],[508814.6804340608,6651175.645368226,95.65853909322364],[508814.5707603226,6651176.008378915,96.26137489522364],[508814.62976304704,6651175.813084945,96.60111992222363],[508814.741827239,6651175.442162061,96.06888863622363],[508814.69666050636,6651175.59166008,96.92678703222364],[508814.815927014,6651175.196898146,96.46066833022364],[508814.77100249304,6651175.345594465,97.23515584022365],[508814.8793855082,6651174.9868559595,96.73815019022364],[508814.9490766948,6651174.756184096,96.99859086322364],[508814.85219505866,6651175.076854022,97.52325419122363],[508815.0243991258,6651174.506873295,97.23956050922365],[508814.93951585685,6651174.7878296515,97.78845191622364],[508815.1046500636,6651174.241249558,97.45897951522365],[508815.0321354318,6651174.4812667845,98.02854036322364],[508815.2179572465,6651173.866212479,97.71519263822364],[508815.1291431448,6651174.160179555,98.24179269822363],[508815.22957606567,6651173.827755182,98.42700160022363],[508815.33663504286,6651173.473399128,97.92747044722366],[508815.332448961,6651173.487254701,98.58349289222363],[508815.4586270048,6651173.069616174,98.09458520422365],[508815.4367835303,6651173.141916205,98.71111565122364],[508815.58192085003,6651172.661524097,98.21673832622365],[508815.5416352285,6651172.794866056,98.81021114522363],[508815.7046411219,6651172.255330498,98.29541301922363],[508815.68071820354,6651172.33451331,98.89937579722364],[508815.825120632,6651171.85655363,98.33315587822364],[508815.8172616486,6651171.882566192,98.94215103822366],[508816.3207191986,6651170.216164784,98.33315587822364],[508816.82683927874,6651168.540950629,98.33315587822364],[508818.0901693312,6651164.359436262,91.93688853122363],[508818.0901693312,6651164.359436262,92.06688853122364],[508816.94731878873,6651168.142173761,98.29541301922363],[508816.8346989389,6651168.514935827,98.94215103822366],[508818.26647299883,6651163.77588621,91.93688853122363],[508817.0700390607,6651167.7359801615,98.21673832622365],[508816.9712423839,6651168.062988708,98.89937579722364],[508817.1933329059,6651167.327888085,98.09458520422365],[508818.0901693312,6651164.359436262,93.76569219022363],[508817.110325359,6651167.602635962,98.81021114522363],[508817.31532486784,6651166.92410513,97.92747044722366],[508818.0848205978,6651164.377140112,94.17650750222364],[508817.2151770572,6651167.255585814,98.71111565122364],[508817.4340026641,6651166.53129178,97.71519263822364],[508818.06809439516,6651164.432502412,94.59762893022365],[508817.31951162644,6651166.9102473175,98.58349289222363],[508818.26647299883,6651163.77588621,93.76569219022363],[508817.5473098471,6651166.1562547,97.45897951522365],[508818.03912804177,6651164.528378562,95.02371806522363],[508817.65325243963,6651165.805593786,97.16153704522364],[508817.99732998066,6651164.666726568,95.44862456922364],[508817.4223845218,6651166.569746836,98.42700160022363],[508817.7267712768,6651165.562252725,96.91382730522363],[508818.2604111008,6651163.795950573,94.23128287722363],[508817.942449786,6651164.848375316,95.86559127122365],[508817.79444618133,6651165.338254582,96.64742099022364],[508817.8746321619,6651165.072845848,96.26754018822363],[508817.52281744266,6651166.237322463,98.24179269822363],[508818.2414547379,6651163.8586945115,94.70855382922363],[508817.6198251556,6651165.9162352355,98.02854036322364],[508818.20862620405,6651163.96735415,95.19145484922363],[508817.71244473057,6651165.609672367,97.78845191622364],[508818.1744840087,6651164.080361894,95.55316083422365],[508817.7997655288,6651165.320647997,97.52325419122363],[508818.1320103867,6651164.220945949,95.91091868022365],[508817.8809580943,6651165.051907552,97.23515584022365],[508818.08120026474,6651164.389123105,96.26137489522364],[508817.9553000812,6651164.8058419395,96.92678703222364],[508818.0221975404,6651164.584417073,96.60111992222363],[508829.1779160704,6651181.02715162,92.03358474417486],[508829.349611245,6651180.442229048,92.03358474417486],[508829.349611245,6651180.442229048,92.16358474417487],[508829.1779160704,6651181.02715162,93.86238840317486],[508829.18381951324,6651181.007040066,94.32797909017485],[508829.3496105863,6651180.442231293,93.86238840417485],[508829.202280366,6651180.944148551,94.80525004217485],[508829.3508908227,6651180.437869848,94.06620968817485],[508829.36152116035,6651180.401654943,94.48278897617486],[508829.23425077775,6651180.835233344,95.28815106217486],[508829.3836800155,6651180.326165258,94.90711609617485],[508829.26750051265,6651180.721959803,95.64985704717485],[508829.4180846409,6651180.208957293,95.33342644717486],[508829.3088638946,6651180.581045093,96.00761489317485],[508829.4651527839,6651180.048607889,95.75523530617485],[508829.35834586434,6651180.412472383,96.35807110817487],[508829.415806286,6651180.216719079,96.69781613517486],[508829.52494117385,6651179.844923778,96.16558484917485],[508829.48095507786,6651179.9947734205,97.02348324517484],[508829.5971040165,6651179.599082999,96.55736454317487],[508829.5533538009,6651179.748129055,97.33185205317486],[508829.6589037362,6651179.388546792,96.83484640317485],[508829.7267732288,6651179.157332383,97.09528707617486],[508829.63242403185,6651179.478756529,97.61995040417486],[508829.80012676766,6651178.907435199,97.33625672217485],[508829.71746230655,6651179.18905237,97.88514812917485],[508829.8782799847,6651178.641186711,97.55567572817485],[508829.80766085035,6651178.881768462,98.12523657617486],[508829.98862537235,6651178.265267541,97.81188885117486],[508829.9021328284,6651178.559926032,98.33848891117486],[508829.9999404811,6651178.22671979,98.52369781317485],[508830.1042009882,6651177.871530287,98.02416666017486],[508830.1001243285,6651177.885418449,98.68018910517485],[508830.2230041391,6651177.4667976275,98.19128141717485],[508830.20173164236,6651177.53926771,98.80781186417487],[508830.3430751425,6651177.057745712,98.31343453917485],[508830.30384256766,6651177.191401295,98.90690735817486],[508830.46258756565,6651176.650596741,98.39210923217486],[508830.4392899808,6651176.729965792,98.99607201017487],[508830.57991779933,6651176.250881943,98.42985209117485],[508830.57226424594,6651176.276955688,99.03884725117486],[508831.15205576975,6651181.605503514,92.04507518621509],[508831.32313591294,6651181.020400761,92.04507518621509],[508831.32313591294,6651181.020400761,92.1750751862151],[508831.06256165804,6651174.606634879,98.42985209117485],[508831.15205576975,6651181.605503514,93.87387884521509],[508831.1579380658,6651181.585385765,94.3394695322151],[508831.32313525653,6651181.020403006,93.8738788462151],[508831.17633278965,6651181.522474877,94.81674048421509],[508831.324410907,6651181.016040216,94.07770013021509],[508831.3350031655,6651180.979814156,94.49427941821509],[508832.78575921635,6651168.736131243,92.03358474417486],[508831.2081886798,6651181.413526119,95.29964150421509],[508832.78575921635,6651168.736131243,92.16358474417487],[508831.555452003,6651172.927480595,98.42985209117485],[508831.3570826452,6651180.904301217,94.91860653821509],[508831.2413193104,6651181.300217684,95.66134748921509],[508831.6727822367,6651172.5277657965,98.39210923217486],[508831.5631062154,6651172.901404604,99.03884725117486],[508832.95745439094,6651168.151208672,92.03358474417486],[508831.3913640293,6651180.787057147,95.34491688921509],[508831.2825345241,6651181.159259568,96.01910533521509],[508831.7922946598,6651172.120616824,98.31343453917485],[508831.6960804805,6651172.448394501,98.99607201017487],[508831.4382635689,6651180.6266583465,95.7667257482151],[508831.91236566316,6651171.711564909,98.19128141717485],[508831.33183924394,6651180.990634928,96.3695615502151],[508832.78575921635,6651168.736131243,93.86238840317486],[508831.83152789366,6651171.986958997,98.90690735817486],[508832.0311688141,6651171.30683225,98.02416666017486],[508832.78055029624,6651168.753876733,94.27320371517484],[508831.3890938358,6651180.794821326,96.70930657721509],[508831.49783779023,6651180.422911493,96.1770752912151],[508831.93363881897,6651171.639092581,98.80781186417487],[508832.7642613085,6651168.809369245,94.69432514317485],[508832.1467444299,6651170.913094997,97.81188885117486],[508832.95745439094,6651168.151208672,93.86238840317486],[508832.73605212156,6651168.905470898,95.12041427817485],[508832.25708981766,6651170.537175825,97.55567572817485],[508832.0352461329,6651171.292941844,98.68018910517485],[508831.4540092573,6651180.572807295,97.0349736872151],[508832.69534664176,6651169.044144301,95.54532078217485],[508832.3602631219,6651170.18569015,97.25823325817485],[508832.9515509481,6651168.171320227,94.32797909017485],[508831.56974213733,6651180.176994984,96.5688549852151],[508832.43186021206,6651169.941776749,97.01052351817485],[508832.6419009889,6651169.22622029,95.96228748417485],[508832.1354299803,6651170.951640502,98.52369781317485],[508832.4977661271,6651169.717251758,96.74411720317487],[508832.5758560848,6651169.451218779,96.36423640117485],[508832.93309009535,6651168.23421174,94.80525004217485],[508832.23323763296,6651170.618434261,98.33848891117486],[508831.52614863997,6651180.326086953,97.34334249521511],[508831.6313204835,6651179.966393922,96.8463368452151],[508832.327709611,6651170.29659183,98.12523657617486],[508832.9011196836,6651168.343126947,95.28815106217486],[508832.4179081549,6651169.989307922,97.88514812917485],[508832.8678699487,6651168.4564004885,95.64985704717485],[508832.5029464295,6651169.699603763,97.61995040417486],[508832.8265065667,6651168.597315199,96.00761489317485],[508832.5820166604,6651169.430231238,97.33185205317486],[508832.777024597,6651168.76588791,96.35807110817487],[508832.65441538347,6651169.183586872,97.02348324517484],[508832.71956417535,6651168.961641212,96.69781613517486],[508831.69894685986,6651179.735108291,97.10677751821511],[508831.60493563255,6651180.056631449,97.63144084621509],[508831.77203763823,6651179.485134127,97.3477471642151],[508831.6896692904,6651179.766838048,97.8966385712151],[508831.84991090157,6651179.218803623,97.56716617021509],[508831.779544733,6651179.459459483,98.1367270182151],[508831.9598610196,6651178.842768651,97.82337929321511],[508831.87367830175,6651179.137517911,98.34997935321509],[508831.9711355964,6651178.804209027,98.53518825521509],[508832.0750226306,6651178.44891011,98.0356571022151],[508832.07096057397,6651178.462802549,98.69167954721509],[508832.1934002152,6651178.044052775,98.2027718592151],[508832.172203919,6651178.116545183,98.81930230621509],[508832.31304111076,6651177.634874854,98.3249249812151],[508832.27394907153,6651177.768571609,98.91839780021509],[508832.4321254269,6651177.227600462,98.40359967421509],[508832.4089112967,6651177.306993962,99.0075624522151],[508832.54903537047,6651176.827762534,98.44134253321509],[508832.54140923294,6651176.85384431,99.05033769321511],[508833.0299503446,6651175.183008968,98.44134253321509],[508834.746975215,6651169.310696958,92.04507518621509],[508834.746975215,6651169.310696958,92.1750751862151],[508833.52107510075,6651173.503337431,98.44134253321509],[508833.63798504433,6651173.103499503,98.40359967421509],[508834.91805535817,6651168.725594205,92.04507518621509],[508833.528701895,6651173.477253408,99.05033769321511],[508833.75706936046,6651172.696225111,98.3249249812151],[508833.66119983123,6651173.024103756,99.0075624522151],[508833.87671025604,6651172.28704719,98.2027718592151],[508834.746975215,6651169.310696958,93.87387884521509],[508833.7961620564,6651172.5625261115,98.91839780021509],[508833.9950878406,6651171.882189856,98.0356571022151],[508834.7417849538,6651169.328447915,94.28469415721509],[508833.89790720894,6651172.214552538,98.81930230621509],[508834.72555431514,6651169.383957521,94.70581558521509],[508834.1102494516,6651171.488331314,97.82337929321511],[508834.91805535817,6651168.725594205,93.87387884521509],[508834.69744617667,6651169.480088778,95.13190472021509],[508834.22019956965,6651171.112296342,97.56716617021509],[508833.9991505539,6651171.868295171,98.69167954721509],[508834.6568865084,6651169.618804897,95.5568112242151],[508834.3230032955,6651170.760702394,97.2697237002151],[508834.91217306204,6651168.745711955,94.3394695322151],[508834.39434391685,6651170.516713856,97.02201396021509],[508834.60363230394,6651169.800936973,95.97377792621509],[508834.0989755315,6651171.526888691,98.53518825521509],[508834.46001374954,6651170.292119702,96.7556076452151],[508834.53782398015,6651170.026004774,96.3757268432151],[508834.8937783383,6651168.808622842,94.81674048421509],[508834.19643282617,6651171.193579809,98.34997935321509],[508834.2905663949,6651170.871638236,98.1367270182151],[508834.8619224481,6651168.9175716,95.29964150421509],[508834.38044183754,6651170.564259672,97.8966385712151],[508834.8287918175,6651169.030880034,95.66134748921509],[508834.46517549537,6651170.27446627,97.63144084621509],[508834.7875766038,6651169.171838152,96.01910533521509],[508834.5439624879,6651170.005010765,97.34334249521511],[508834.738271884,6651169.340462791,96.3695615502151],[508834.61610187055,6651169.758290425,97.0349736872151],[508834.68101729214,6651169.536276395,96.70930657721509],[508847.96250603726,6651186.439312099,92.12950105420167],[508848.12834898476,6651185.8527034,92.12950105420167],[508848.12834898476,6651185.8527034,92.25950105420169],[508847.96250603726,6651186.439312099,93.95830471320168],[508847.9682082613,6651186.419142568,94.42389540020167],[508848.3057533731,6651186.536319407,92.13097546765042],[508848.1283483484,6651185.852705651,93.95830471420167],[508848.129584948,6651185.848331632,94.16212599820167],[508847.9860398761,6651186.35606976,94.90116635220167],[508848.1398529508,6651185.8120123325,94.57870528620168],[508848.4714893839,6651185.949680488,92.13097546765042],[508848.4714893839,6651185.949680488,92.26097546765041],[508848.016920577,6651186.246840589,95.38406737220168],[508848.1612565217,6651185.736305038,95.00303240620167],[508848.0490369952,6651186.13324052,95.74577335720167],[508848.3057533731,6651186.536319407,93.9597791266504],[508848.194488466,6651185.618759204,95.42934275720168],[508848.08899050707,6651185.991919602,96.10353120320167],[508848.31145192037,6651186.516148837,94.4253698136504],[508848.2399522922,6651185.457947567,95.85115161620168],[508848.1367858848,6651185.822860955,96.45398741820169],[508848.471488748,6651185.949682738,93.9597791276504],[508848.4727245503,6651185.945308494,94.16360041165042],[508848.32927203726,6651186.45307278,94.90264076565042],[508848.2977027959,6651185.253676308,96.26150115920167],[508848.1922877689,6651185.626543365,96.79373244520168],[508848.4829859321,6651185.908987324,94.5801796996504],[508848.3601328261,6651186.343837982,95.3855417856504],[508848.50437570194,6651185.833276128,95.0045068196504],[508848.25521596527,6651185.403957913,97.11939955520167],[508848.36740596924,6651185.007126857,96.6532808532017],[508848.3922285353,6651186.230232061,95.7472477706504],[508848.5375862181,6651185.715724237,95.4308171706504],[508848.32514697907,6651185.15660256,97.42776836320168],[508848.42709924665,6651184.795983747,96.93076271320167],[508848.4321562849,6651186.088903861,96.1050056166504],[508848.5830207288,6651185.554904317,95.85262602965042],[508848.4926554087,6651184.5641028285,97.19120338620168],[508848.47992084373,6651185.919836504,96.45546183165041],[508848.4015221026,6651184.886453527,97.71586671420168],[508848.56350869354,6651184.31348528,97.43217303220167],[508848.6407339946,6651185.350622532,96.2629755726504],[508848.53538693994,6651185.7235088,96.7952068586504],[508848.48366184905,6651184.595914254,97.98106443920167],[508848.6389980594,6651184.046469292,97.65159203820167],[508848.59827455983,6651185.500911881,97.1208739686504],[508848.7103922229,6651185.10406038,96.65475526665043],[508848.5707859771,6651184.287744553,98.22115288620168],[508848.66816048155,6651185.253543783,97.42924277665041],[508848.7700470097,6651184.892906391,96.9322371266504],[508848.74558232643,6651183.669466475,97.90780516120168],[508848.6620378794,6651183.964974364,98.43440522120169],[508848.8355609006,6651184.661013527,97.19267779965041],[508848.7444863579,6651184.983380833,97.71734112765041],[508848.85721854947,6651183.274594216,98.12008297020168],[508848.7565117599,6651183.6308076065,98.61961412320167],[508848.90636849875,6651184.410383065,97.43364744565042],[508848.82657314016,6651184.69282659,97.9825388526504],[508848.85328084254,6651183.288522412,98.77610541520167],[508848.97197229695,6651182.868694855,98.28719772720167],[508848.98180918855,6651184.14335332,97.6530664516504],[508848.91364108986,6651184.384641014,98.22262729965041],[508848.9514248729,6651182.941373844,98.90372817420169],[508849.0879506822,6651182.458463787,98.40935084920167],[508849.08832472935,6651183.766331081,97.90927957465041],[508849.0500553491,6651182.592504652,99.00282366820169],[508849.00483415235,6651184.061854195,98.4358796346504],[508849.2033895264,6651182.050141148,98.48802554220168],[508849.1998889686,6651183.371438478,98.12155738365041],[508849.09924711543,6651183.727670222,98.62108853665042],[508849.1808860394,6651182.129738993,99.0919883202017],[508849.3167205611,6651181.649274113,98.52576840120167],[508849.1959538008,6651183.385367393,98.7775798286504],[508849.309327879,6651181.675423019,99.13476356120168],[508849.3145687221,6651182.965518205,98.2886721406504],[508849.2940345472,6651183.038200939,98.90520258765041],[508849.43047232373,6651182.555266002,98.4108252626504],[508849.39260142576,6651182.689313772,99.0042980816504],[508849.5458367322,6651182.146922327,98.48949995565042],[508849.78291351214,6651180.000287262,98.52576840120167],[508849.52334775554,6651182.226524273,99.09346273365043],[508849.6590946902,6651181.746034639,98.52724281465042],[508849.65170677495,6651181.772184892,99.13623797465041],[508851.44737591106,6651174.112861025,92.12950105420167],[508851.44737591106,6651174.112861025,92.25950105420169],[508850.25900369807,6651178.316292565,98.52576840120167],[508850.1249870369,6651180.096962831,98.52724281465042],[508851.61321885866,6651173.526252328,92.12950105420167],[508850.37233473273,6651177.91542553,98.48802554220168],[508850.2663970168,6651178.290141408,99.13476356120168],[508850.48777357704,6651177.50710289,98.40935084920167],[508850.39483885636,6651177.835825434,99.0919883202017],[508851.44737591106,6651174.112861025,93.95830471320168],[508850.6037519623,6651177.096871823,98.28719772720167],[508851.442344537,6651174.130657669,94.36912002520167],[508850.52566954674,6651177.373059775,99.00282366820169],[508850.7185057098,6651176.690972462,98.12008297020168],[508851.7883761792,6651174.209233276,92.13097546765042],[508851.4266107591,6651174.186310148,94.79024145320167],[508851.61321885866,6651173.526252328,93.95830471320168],[508851.7883761792,6651174.209233276,92.26097546765041],[508850.6243000229,6651177.024190582,98.90372817420169],[508850.8301419328,6651176.296100203,97.90780516120168],[508851.3993630818,6651174.282688828,95.21633058820167],[508850.93672619987,6651175.919097387,97.65159203820167],[508850.60077023663,6651178.412881376,98.52724281465042],[508850.7224440532,6651176.677042015,98.77610541520167],[508851.3600450476,6651174.421761977,95.64123709220168],[508851.6075166345,6651173.546421858,94.42389540020167],[508851.0363828438,6651175.566598503,97.35414956820169],[508851.3084210889,6651174.604362826,96.05820379420167],[508851.1055395483,6651175.321981983,97.10643982820167],[508851.24462732434,6651174.8300099075,96.46015271120167],[508851.1691990614,6651175.096809767,96.84003351320169],[508851.95411219,6651173.622594357,92.13097546765042],[508850.8192131359,6651176.334756819,98.61961412320167],[508851.58968501963,6651173.609494666,94.90116635220167],[508850.71402819466,6651178.0119936885,98.48949995565042],[508850.9136870164,6651176.000590063,98.43440522120169],[508850.6081587881,6651178.386728871,99.13623797465041],[508851.55880431883,6651173.718723837,95.38406737220168],[508851.0049389187,6651175.677819872,98.22115288620168],[508851.5266879006,6651173.832323905,95.74577335720167],[508850.82939260313,6651177.603650013,98.4108252626504],[508851.09206304676,6651175.369650174,97.98106443920167],[508851.48673438875,6651173.973644823,96.10353120320167],[508851.1742027932,6651175.079110898,97.71586671420168],[508851.43893901113,6651174.14270347,96.45398741820169],[508850.7365178075,6651177.932389491,99.09346273365043],[508851.25057791674,6651174.808961867,97.42776836320168],[508851.38343712705,6651174.339021062,96.79373244520168],[508851.3205089306,6651174.561606512,97.11939955520167],[508851.7883761792,6651174.209233276,93.9597791266504],[508850.9452962049,6651177.193397809,98.2886721406504],[508851.78334804927,6651174.227030836,94.3705944386504],[508850.8672641373,6651177.46959999,99.0042980816504],[508851.0599759584,6651176.787477536,98.12155738365041],[508851.7676244167,6651174.282686182,94.7917158666504],[508851.95411219,6651173.622594357,93.9597791266504],[508850.9658310159,6651177.120712824,98.90520258765041],[508851.1715401975,6651176.392584933,97.90927957465041],[508851.7403943089,6651174.3790698275,95.2178050016504],[508851.2780557383,6651176.0155626945,97.6530664516504],[508851.06391176226,6651176.773546371,98.7775798286504],[508851.7011016271,6651174.5181501405,95.64271150565042],[508851.9484136427,6651173.642764926,94.4253698136504],[508851.3776481229,6651175.6630456485,97.35562398165041],[508851.6495109559,6651174.700760398,96.0596782076504],[508851.4467602348,6651175.418416529,97.10791424165042],[508851.585758326,6651174.926419106,96.4616271246504],[508851.5103786998,6651175.1932327105,96.84150792665041],[508851.16061844764,6651176.431243542,98.62108853665042],[508851.9305935258,6651173.705840983,94.90264076565042],[508851.2550314107,6651176.097059567,98.4358796346504],[508851.8997327371,6651173.815075781,95.3855417856504],[508851.3462244732,6651175.774272749,98.22262729965041],[508851.86763702775,6651173.928681702,95.7472477706504],[508851.43329242297,6651175.466087173,97.9825388526504],[508851.8277092782,6651174.070009902,96.1050056166504],[508851.5153792052,6651175.17553293,97.71734112765041],[508851.77994471934,6651174.239077259,96.45546183165041],[508851.59170508146,6651174.905369979,97.42924277665041],[508851.72447862325,6651174.435404963,96.7952068586504],[508851.66159100324,6651174.658001883,97.1208739686504],[508864.81549509364,6651191.122655294,92.19016613550315],[508864.97608759283,6651190.534587528,92.19016613550315],[508864.97608759283,6651190.534587528,92.32016613550316],[508864.81549509364,6651191.122655294,94.01896979450315],[508864.8210167901,6651191.102435596,94.48456048150315],[508864.97608697665,6651190.534589784,94.01896979550315],[508864.9772844266,6651190.530204887,94.22279107950317],[508864.8382838711,6651191.039205907,94.96183143350316],[508864.98722735303,6651190.493795251,94.63937036750315],[508864.86818691494,6651190.929705051,95.44473245350315],[508865.0079533049,6651190.417899649,95.06369748750315],[508864.89928655425,6651190.815822425,95.80643843850316],[508865.04013315385,6651190.300061445,95.49000783850315],[508864.9379751715,6651190.674150002,96.16419628450316],[508865.0841576334,6651190.138849821,95.91181669750317],[508864.98425738775,6651190.504670856,96.51465249950316],[508865.14007980475,6651189.934070479,96.32216624050315],[508865.03800212883,6651190.307864966,96.85439752650315],[508865.09893807146,6651190.084725879,97.18006463650315],[508865.2075762342,6651189.686907787,96.71394593450316],[508865.2653796726,6651189.475239502,96.99142779450315],[508865.1666551281,6651189.83675528,97.48843344450316],[508865.3288603816,6651189.242781829,97.25186846750316],[508865.24061227933,6651189.565934308,97.77653179550315],[508865.397470511,6651188.991540921,97.49283811350317],[508865.3201515505,6651189.274672377,98.04172952050315],[508865.470569947,6651188.723860784,97.71225711950315],[508865.4045174018,6651188.965736169,98.28181796750316],[508865.5737798457,6651188.345920254,97.96847024250314],[508865.4928803457,6651188.642163156,98.49507030250315],[508865.68188175966,6651187.950065832,98.18074805150316],[508865.58436326246,6651188.307165228,98.68027920450317],[508865.6780687173,6651187.96402867,98.83677049650315],[508865.79300249997,6651187.543156879,98.34786280850315],[508865.7731055902,6651187.616016641,98.96439325550315],[508865.90530910704,6651187.131905446,98.47001593050315],[508865.86861350836,6651187.2662797095,99.06348874950315],[508866.0170932545,6651186.722567189,98.54869062350315],[508865.99530220893,6651186.802363017,99.15265340150316],[508866.1268363239,6651186.32070308,98.58643348250317],[508866.1196776879,6651186.346917026,99.19542864250316],[508866.5782699979,6651184.667614714,98.58643348250317],[508868.1900369162,6651178.7655447265,92.19016613550315],[508868.1900369162,6651178.7655447265,92.32016613550316],[508868.35062941536,6651178.17747696,92.19016613550315],[508867.0392875687,6651182.979431431,98.58643348250317],[508867.14903063804,6651182.577567323,98.54869062350315],[508867.0464468211,6651182.953215227,99.19542864250316],[508867.2608147855,6651182.168229065,98.47001593050315],[508868.1900369162,6651178.7655447265,94.01896979450315],[508867.1708223001,6651182.4977692375,99.15265340150316],[508867.37312139256,6651181.756977631,98.34786280850315],[508868.1851648311,6651178.783385635,94.42978510650315],[508867.29751100065,6651182.033852544,99.06348874950315],[508867.48424213286,6651181.35006868,98.18074805150316],[508868.1699291714,6651178.839176537,94.85090653450317],[508868.35062941536,6651178.17747696,94.01896979450315],[508868.14354413265,6651178.935794939,95.27699566950315],[508867.5923440468,6651180.954214257,97.96847024250314],[508867.3930189188,6651181.684115612,98.96439325550315],[508868.3451077189,6651178.197696658,94.48456048150315],[508868.10547087435,6651179.075214003,95.70190217350317],[508867.69555394555,6651180.576273727,97.71225711950315],[508867.4880557917,6651181.336103583,98.83677049650315],[508868.05548128684,6651179.258269035,96.11886887550315],[508867.7920555439,6651180.2228980735,97.41481464950316],[508867.85902280535,6651179.977673122,97.16710490950317],[508867.9937071792,6651179.484477368,96.52081779250315],[508867.9206669118,6651179.751940836,96.90069859450315],[508867.48864439264,6651191.850619145,92.19759506947767],[508868.3278406379,6651178.260926347,94.96183143350316],[508867.5817612465,6651180.992967024,98.68027920450317],[508868.29793759406,6651178.370427203,95.44473245350315],[508867.67324416334,6651180.657969097,98.49507030250315],[508868.26683795475,6651178.484309829,95.80643843850316],[508867.76160710707,6651180.334396084,98.28181796750316],[508868.2281493375,6651178.625982252,96.16419628450316],[508867.8459729585,6651180.025459875,98.04172952050315],[508867.64840408805,6651191.2623245865,92.19759506947767],[508868.18186712125,6651178.795461397,96.51465249950316],[508867.9255122297,6651179.734197945,97.77653179550315],[508867.64840408805,6651191.2623245865,92.3275950694777],[508868.1281223802,6651178.992267287,96.85439752650315],[508867.9994693809,6651179.463376973,97.48843344450316],[508868.06718643755,6651179.215406375,97.18006463650315],[508867.48864439264,6651191.850619145,94.02639872847767],[508867.49413745455,6651191.830391649,94.49198941547768],[508867.648403475,6651191.262326844,94.02639872947768],[508867.6495947152,6651191.257940255,94.23022001347768],[508867.5113149915,6651191.767137576,94.96926036747767],[508867.65948607936,6651191.221516577,94.64679930147767],[508867.5410629635,6651191.657594491,95.45216138747767],[508867.6801045502,6651191.145591706,95.07112642147767],[508867.57200132584,6651191.543667945,95.81386737247767],[508867.7121175203,6651191.027708057,95.49743677247768],[508867.6104893109,6651191.401940885,96.17162521847767],[508867.7559136969,6651190.866434261,95.91924563147768],[508867.6565315158,6651191.232396378,96.5220814334777],[508867.81154586584,6651190.661575945,96.32959517447769],[508867.70999754634,6651191.035514588,96.86182646047767],[508867.7706174862,6651190.812289446,97.18749357047767],[508867.8786922711,6651190.414317933,96.72137486847768],[508867.9361959512,6651190.202568016,96.99885672847768],[508867.8379833744,6651190.564223215,97.49586237847768],[508867.9993474607,6651189.970020695,97.25929740147768],[508867.9115569972,6651190.2932978,97.78396072947767],[508868.06760179036,6651189.718682893,97.50026704747768],[508867.99068379204,6651190.001923541,98.04915845447769],[508868.1403221459,6651189.450899523,97.71968605347767],[508868.07461213734,6651189.69286819,98.2892469014777],[508868.24299681664,6651189.072813236,97.97589917647767],[508868.1625168468,6651189.369170387,98.50249923647769],[508868.35053813364,6651188.67680615,98.18817698547767],[508868.2535253497,6651189.0340432655,98.68770813847767],[508868.34674486506,6651188.690774374,98.84419943047769],[508868.46108262177,6651188.26974027,98.35529174247768],[508868.44128889375,6651188.342628133,98.97182218947768],[508868.5728068271,6651187.858330235,98.47744486447768],[508868.53630152514,6651187.99275632,99.07091768347767],[508868.6840112821,6651187.448834113,98.55611955747767],[508868.662333241,6651187.528660715,99.16008233547768],[508868.79318524373,6651187.046815022,98.59386241647768],[508868.786063731,6651187.073039079,99.20285757647768],[508869.2422778641,6651185.393089131,98.59386241647768],[508870.8456864497,6651179.488742964,92.19759506947767],[508870.8456864497,6651179.488742964,92.3275950694777],[508871.0054461452,6651178.900448406,92.19759506947767],[508869.7009046808,6651183.704254787,98.59386241647768],[508869.8100786425,6651183.302235696,98.55611955747767],[508869.70802680677,6651183.678028474,99.20285757647768],[508869.9212830975,6651182.892739574,98.47744486447768],[508870.8456864497,6651179.488742964,94.02639872847767],[508869.83175729687,6651183.222406836,99.16008233547768],[508870.0330073028,6651182.481329539,98.35529174247768],[508870.84083963046,6651179.506590754,94.43721404047767],[508869.95778901275,6651182.758311231,99.07091768347767],[508870.8256829802,6651179.562403172,94.85833546847768],[508870.1435517909,6651182.074263661,98.18817698547767],[508871.0054461452,6651178.900448406,94.02639872847767],[508870.7994347695,6651179.659058836,95.28442460347769],[508870.2510931079,6651181.678256574,97.97589917647767],[508870.0528016441,6651182.40843942,98.97182218947768],[508870.9999530832,6651178.920675902,94.49198941547768],[508870.76155895216,6651179.798531668,95.70933110747768],[508870.3537677787,6651181.300170287,97.71968605347767],[508870.1473456728,6651182.060293177,98.84419943047769],[508870.71182860166,6651179.981657297,96.12629780947768],[508870.44976893713,6651180.9466583505,97.4222435834777],[508870.51638891845,6651180.701338827,97.17453384347768],[508870.65037484345,6651180.207952868,96.52824672647768],[508870.57771334966,6651180.475519486,96.90812752847769],[508870.98277554626,6651178.983929976,94.96926036747767],[508870.24056518805,6651181.717024285,98.68770813847767],[508870.9530275743,6651179.093473061,95.45216138747767],[508870.3315736909,6651181.381897164,98.50249923647769],[508870.922089212,6651179.207399606,95.81386737247767],[508870.41947840044,6651181.058199363,98.2892469014777],[508870.883601227,6651179.349126668,96.17162521847767],[508870.50340674573,6651180.74914401,98.04915845447769],[508870.83755902195,6651179.5186711745,96.5220814334777],[508870.58253354055,6651180.4577697525,97.78396072947767],[508870.7840929915,6651179.715552963,96.86182646047767],[508870.65610716335,6651180.186844336,97.49586237847768],[508870.72347305156,6651179.938778105,97.18749357047767],[508881.7096761964,6651195.6551588485,92.22707043011843],[508881.8650054141,6651195.06567901,92.22707043011843],[508881.8650054141,6651195.06567901,92.35707043011844],[508881.7096761964,6651195.6551588485,94.05587408911843],[508881.715016924,6651195.6348906,94.52146477611844],[508881.8650048182,6651195.065681271,94.05587409011844],[508881.86616302264,6651195.061285845,94.25969537411844],[508881.73171809124,6651195.571509084,94.99873572811843],[508881.87578007823,6651195.02478878,94.67627466211843],[508881.7606410884,6651195.461745293,95.48163674811843],[508881.8958267548,6651194.948710939,95.10060178211845],[508881.7907214638,6651195.347589212,95.84334273311845],[508881.92695193674,6651194.83058978,95.52691213311843],[508881.82814209466,6651195.205576601,96.20110057911843],[508881.9695335517,6651194.668991054,95.94872099211844],[508881.872907451,6651195.035690501,96.55155679411844],[508882.0236229219,6651194.463719993,96.35907053511843],[508881.9248907542,6651194.83841204,96.89130182111843],[508881.98382957355,6651194.614737148,97.21696893111844],[508882.0889072137,6651194.215963812,96.75085022911844],[508882.1448161939,6651194.003787266,97.02833208911844],[508882.04932726175,6651194.36617112,97.52533773911846],[508882.2062163772,6651193.770771414,97.28877276211844],[508882.1208605309,6651194.09469985,97.81343609011843],[508882.27257786837,6651193.518927223,97.52974240811844],[508882.1977929706,6651193.802738537,98.07863381511844],[508882.343281533,6651193.25060433,97.74916141411845],[508882.27939380344,6651193.493060509,98.31872226211844],[508882.4431088159,6651192.871756284,98.00537453711844],[508882.3648607275,6651193.168710529,98.53197459711843],[508882.54766778223,6651192.4749513315,98.21765234611843],[508882.45334537025,6651192.8329082,98.71718349911843],[508882.5439797091,6651192.488947699,98.87367479111843],[508882.65514663554,6651192.067065306,98.38476710311845],[508882.6359018299,6651192.14010002,99.00129755011844],[508882.76377248985,6651191.654826372,98.50692022511845],[508882.728279558,6651191.789523297,99.10039304411843],[508882.8718930078,6651191.244505207,98.58559491811843],[508882.8508161451,6651191.324492642,99.18955769611844],[508882.97803934215,6651190.841676137,98.62333777711844],[508882.97111532424,6651190.86795303,99.23233293711846],[508883.4146776646,6651189.184618359,98.62333777711844],[508884.97362030385,6651183.268376259,92.22707043011843],[508884.97362030385,6651183.268376259,92.35707043011844],[508885.1289495216,6651182.678896419,92.22707043011843],[508883.8605857796,6651187.492381393,98.62333777711844],[508883.966732114,6651187.089552323,98.58559491811843],[508883.8675103937,6651187.466102239,99.23233293711846],[508884.97362030385,6651183.268376259,94.05587408911843],[508884.0748526319,6651186.679231158,98.50692022511845],[508884.9689078972,6651183.286260009,94.46668940111844],[508883.9878095729,6651187.009562627,99.18955769611844],[508884.1834784862,6651186.266992224,98.38476710311845],[508884.95417157316,6651183.342184876,94.88781082911845],[508885.1289495216,6651182.678896419,94.05587408911843],[508884.2909573395,6651185.859106199,98.21765234611843],[508884.1103461601,6651186.544531973,99.10039304411843],[508884.92865128146,6651183.43903528,95.31389996411843],[508885.12360879395,6651182.699164669,94.52146477611844],[508884.39551630587,6651185.462301247,98.00537453711844],[508884.20272388804,6651186.193955248,99.00129755011844],[508884.89182584157,6651183.578789118,95.73880646811844],[508884.49534358876,6651185.083453201,97.74916141411845],[508884.8434746199,6651183.762283704,96.15577317011845],[508884.5886824299,6651184.729229019,97.45171894411844],[508884.2946460089,6651185.845107568,98.87367479111843],[508885.10690762685,6651182.7625461845,94.99873572811843],[508884.7837251057,6651183.98903521,96.55772208711844],[508884.65345489676,6651184.48341523,97.20400920411844],[508884.71307867044,6651184.257140915,96.93760288911844],[508884.38528034784,6651185.501147067,98.71718349911843],[508885.07798462966,6651182.872309975,95.48163674811843],[508884.47376499046,6651185.16534474,98.53197459711843],[508885.04790425417,6651182.986466058,95.84334273311845],[508884.55923191446,6651184.8409947585,98.31872226211844],[508885.01048362325,6651183.128478666,96.20110057911843],[508884.6408327474,6651184.531316731,98.07863381511844],[508884.9657182671,6651183.298364766,96.55155679411844],[508884.7177651871,6651184.239355418,97.81343609011843],[508884.91373496375,6651183.495643229,96.89130182111843],[508884.7892984562,6651183.967884148,97.52533773911846],[508884.8547961444,6651183.71931812,97.21696893111844],[508886.72460393567,6651196.969500862,92.23344354966014],[508886.8783707826,6651196.379611547,92.23344354966014],[508886.8783707826,6651196.379611547,92.36344354966016],[508886.72460393567,6651196.969500862,94.06224720866015],[508886.72989094385,6651196.949218535,94.52783789566014],[508886.87837019254,6651196.37961381,94.06224720966014],[508886.8795167473,6651196.375215331,94.26606849366014],[508886.74642412324,6651196.88579299,95.00510884766014],[508886.8890370702,6651196.338692915,94.68264778166015],[508886.77505619987,6651196.775952955,95.48800986766015],[508886.90888210834,6651196.262562226,95.10697490166014],[508886.8048340134,6651196.661717575,95.84971585266014],[508886.9396942192,6651196.144359015,95.53328525266015],[508886.8418782509,6651196.519606319,96.20747369866014],[508886.98184752936,6651195.982648036,95.95509411166015],[508886.8861933371,6651196.349602209,96.55792991366016],[508887.0353928443,6651195.777234387,96.36544365466014],[508886.93765376904,6651196.152186709,96.89767494066015],[508886.9959997554,6651195.928356444,97.22334205066014],[508887.1000204775,6651195.529306104,96.75722334866015],[508887.15536710015,6651195.316982173,97.03470520866014],[508887.0608386385,6651195.679617752,97.53171085866015],[508887.21614969283,6651195.083804459,97.29514588166015],[508887.13165239384,6651195.407957908,97.81980920966014],[508887.28184369043,6651194.831785328,97.53611552766014],[508887.2078110126,6651195.115793789,98.08500693466014],[508887.35183618596,6651194.563276047,97.75553453366014],[508887.28859106783,6651194.805900645,98.32509538166015],[508887.4506593612,6651194.184164838,98.01174765666013],[508887.37319832726,6651194.48132536,98.53834771666016],[508887.55416662677,6651193.787084251,98.22402546566013],[508887.4607929517,6651194.14528977,98.72355661866014],[508887.55051564984,6651193.801090341,98.88004791066015],[508887.66056440957,6651193.378914892,98.39114022266014],[508887.64151317684,6651193.452000339,99.00767066966016],[508887.7680976564,6651192.966389601,98.51329334466014],[508887.73296172824,6651193.10118009,99.10676616366015],[508887.8751306496,6651192.555783411,98.59196803766015],[508887.8542657875,6651192.635826407,99.19593081566015],[508887.98020931665,6651192.15267452,98.62971089666014],[508887.97335494356,6651192.178969665,99.23870605666015],[508888.41245573515,6651190.494465686,98.62971089666014],[508889.955717831,6651184.574113935,92.23344354966014],[508889.955717831,6651184.574113935,92.36344354966016],[508890.1094846779,6651183.98422462,92.23344354966014],[508888.85387870675,6651188.801053226,98.62971089666014],[508888.95895737363,6651188.397944337,98.59196803766015],[508888.86073366995,6651188.774755819,99.23870605666015],[508889.955717831,6651184.574113935,94.06224720866015],[508889.065990367,6651187.987338146,98.51329334466014],[508889.95105282386,6651184.592010107,94.47306252066014],[508888.97982282605,6651188.317899075,99.19593081566015],[508889.1735236138,6651187.574812855,98.39114022266014],[508890.1094846779,6651183.98422462,94.06224720866015],[508889.93646472436,6651184.6479738215,94.89418394866014],[508889.2799213966,6651187.166643497,98.22402546566013],[508889.10112688533,6651187.852545393,99.10676616366015],[508889.91120112716,6651184.744891502,95.32027308366015],[508890.1041976697,6651184.004506948,94.52783789566014],[508889.383428662,6651186.769562908,98.01174765666013],[508889.87474609405,6651184.88474242,95.74517958766015],[508889.1925754367,6651187.501725144,99.00767066966016],[508889.4822518374,6651186.3904517,97.75553453366014],[508889.8268812106,6651185.0683644675,96.16214628966014],[508890.08766449033,6651184.067932491,95.00510884766014],[508889.5746518346,6651186.0359814605,97.45809206366016],[508889.76773268386,6651185.295273483,96.56409520666014],[508889.28357296373,6651187.152635143,98.88004791066015],[508889.638772791,6651185.789996919,97.21038232366014],[508889.697796842,6651185.563565425,96.94397600866016],[508889.37329566176,6651186.808435714,98.72355661866014],[508890.0590324136,6651184.177772529,95.48800986766015],[508889.46089028625,6651186.472400124,98.53834771666016],[508890.0292546002,6651184.292007907,95.84971585266014],[508889.54549754574,6651186.147824837,98.32509538166015],[508889.99221036263,6651184.434119165,96.20747369866014],[508889.6262776009,6651185.8379316935,98.08500693466014],[508889.94789527636,6651184.604123275,96.55792991366016],[508889.7024362197,6651185.545767575,97.81980920966014],[508889.89643484453,6651184.801538775,96.89767494066015],[508889.77324997506,6651185.27410773,97.53171085866015],[508889.8380888582,6651185.025369038,97.22334205066014],[508898.64369931177,6651200.036460568,92.24021393804705],[508898.7937528355,6651199.44561576,92.24021393804705],[508898.7937528355,6651199.44561576,92.37021393804707],[508898.64369931177,6651200.036460568,94.06901759704706],[508898.6488586437,6651200.016145387,94.53460828404705],[508898.79375225975,6651199.445618027,94.06901759804705],[508898.7948711263,6651199.441212422,94.27283888204705],[508898.66499256244,6651199.952617109,95.01187923604705],[508898.80416154244,6651199.404630847,94.68941817004705],[508898.69293320173,6651199.8425991535,95.49478025604706],[508898.82352734177,6651199.328376844,95.11374529004705],[508898.72199190944,6651199.728178738,95.85648624104705],[508898.85359536944,6651199.209982169,95.54005564104706],[508898.75814156374,6651199.5858372925,96.21424408704705],[508898.8947307171,6651199.048009254,95.96186450004706],[508898.80138648284,6651199.415557812,96.56470030204707],[508898.94698296377,6651198.84226288,96.37221404304705],[508898.8516041942,6651199.217822542,96.90444532904706],[508898.90854118037,6651198.993629721,97.23011243904705],[508899.01004990103,6651198.593933006,96.76399373704706],[508899.06405995536,6651198.381265156,97.04147559704705],[508898.9718142661,6651198.744488127,97.53848124704706],[508899.1233747062,6651198.147709745,97.30191627004706],[508899.04091793665,6651198.472388252,97.82657959804705],[508899.18748225627,6651197.895282396,97.54288591604706],[508899.11523739714,6651198.17975089,98.09177732304707],[508899.2557844996,6651197.62633819,97.76230492204705],[508899.19406669086,6651197.8693557875,98.33186577004707],[508899.35222118907,6651197.246612903,98.01851804504705],[508899.27663076547,6651197.544254758,98.54511810504707],[508899.4532288525,6651196.848889129,98.23079585404705],[508899.362110063,6651197.207674866,98.73032700704705],[508899.4496660433,6651196.862917906,98.88681829904706],[508899.55705723003,6651196.440058625,98.39791061104705],[508899.5384660665,6651196.513262454,99.01444105804707],[508899.66199365124,6651196.026865132,98.52006373304705],[508899.6277062223,6651196.1618739525,99.11353655204707],[508899.7664418994,6651195.615593849,98.59873842604705],[508899.74608090386,6651195.695766499,99.20270120404706],[508899.8689830165,6651195.21183201,98.63648128504705],[508899.86229417,6651195.2381697465,99.24547644504706],[508900.290791095,6651193.550937236,98.63648128504705],[508901.7967848785,6651187.620995796,92.24021393804705],[508901.7967848785,6651187.620995796,92.37021393804707],[508901.9468384022,6651187.030150988,92.24021393804705],[508900.7215541214,6651191.854781814,98.63648128504705],[508900.8240952385,6651191.451019975,98.59873842604705],[508901.7967848785,6651187.620995796,94.06901759704706],[508900.7282435438,6651191.82844181,99.24547644504706],[508900.9285434868,6651191.039748694,98.52006373304705],[508901.7922325268,6651187.638920956,94.47983290904705],[508900.8444568101,6651191.370845058,99.20270120404706],[508901.9468384022,6651187.030150988,94.06901759704706],[508901.77799671615,6651187.694975321,94.90095433704705],[508901.0334799079,6651190.626555199,98.39791061104705],[508901.7533432108,6651187.792049986,95.32704347204707],[508901.13730828546,6651190.217724695,98.23079585404705],[508900.9628314916,6651190.904737604,99.11353655204707],[508901.94167907024,6651187.05046617,94.53460828404705],[508901.717768532,6651187.932127431,95.75194997604706],[508901.23831594887,6651189.820000922,98.01851804504705],[508901.0520716475,6651190.553349102,99.01444105804707],[508901.67105954,6651188.116046907,96.16891667804705],[508901.3347526385,6651189.440275635,97.76230492204705],[508901.92554515146,6651187.113994448,95.01187923604705],[508901.6133393939,6651188.343323467,96.57086559504705],[508901.4249212637,6651189.08523123,97.46486245204707],[508901.48749375984,6651188.838848249,97.21715271204705],[508901.54509243625,6651188.612049984,96.95074639704707],[508901.1408716707,6651190.203693651,98.88681829904706],[508901.8976045122,6651187.224012404,95.49478025604706],[508901.22842765093,6651189.858936692,98.73032700704705],[508901.8685458045,6651187.338432819,95.85648624104705],[508901.3139069485,6651189.522356797,98.54511810504707],[508901.83239615016,6651187.480774265,96.21424408704705],[508901.3964710231,6651189.197255771,98.33186577004707],[508901.7891512311,6651187.651053744,96.56470030204707],[508901.47530031676,6651188.886860667,98.09177732304707],[508901.7389335197,6651187.848789014,96.90444532904706],[508901.54961977724,6651188.594223305,97.82657959804705],[508901.68199653353,6651188.072981834,97.23011243904705],[508901.61872344784,6651188.32212343,97.53848124704706],[508906.01164131216,6651201.892434828,92.23852090819406],[508906.1593993975,6651201.301011802,92.23852090819406],[508906.1593993975,6651201.301011802,92.36852090819407],[508906.01164131216,6651201.892434828,94.06732456719406],[508906.01672171947,6651201.872099766,94.53291525419407],[508906.15939883055,6651201.30101407,94.06732456819407],[508906.16050058126,6651201.296604154,94.27114585219407],[508906.0326088302,6651201.808509315,95.01018620619406],[508906.1696488776,6651201.25998678,94.68772514019406],[508906.0601220485,6651201.6983836945,95.49308722619406],[508906.1887184293,6651201.183658152,95.11205226019408],[508906.08873623156,6651201.583851304,95.85479321119408],[508906.2183264924,6651201.065147614,95.53836261119406],[508906.1243328879,6651201.441370559,96.21255105719406],[508906.25883257366,6651200.903016187,95.96017147019407],[508906.16691626934,6651201.270924438,96.56300727219407],[508906.3102854933,6651200.697068463,96.37052101319406],[508906.21636577713,6651201.072995658,96.90275229919406],[508906.3723876664,6651200.448495566,96.76230070719407],[508906.2724317718,6651200.848583437,97.22841940919407],[508906.4255715039,6651200.235619593,97.03978256719408],[508906.33473693975,6651200.599198025,97.53678821719409],[508906.4839788894,6651200.001835617,97.30022324019407],[508906.40278349933,6651200.326831865,97.82488656819406],[508906.5471057564,6651199.749161236,97.54119288619407],[508906.4759660606,6651200.033908119,98.09008429319407],[508906.61436314863,6651199.479953834,97.76061189219408],[508906.55358946585,6651199.723209255,98.33017274019407],[508906.7093246013,6651199.099856937,98.01682501519407],[508906.63489051955,6651199.397790073,98.54342507519407],[508906.8087871037,6651198.70174394,98.22910282419406],[508906.7190622006,6651199.060880792,98.72863397719406],[508906.8052787963,6651198.715786445,98.88512526919406],[508906.9110271703,6651198.292513342,98.39621758119408],[508906.89272040426,6651198.36578881,99.01274802819407],[508907.0143583303,6651197.878915487,98.51837070319408],[508906.9805954121,6651198.01405643,99.11184352219406],[508907.1172087851,6651197.467241721,98.59704539619406],[508907.21818128304,6651197.0630847495,98.63478825519407],[508907.0971592612,6651197.547492829,99.20100817419407],[508907.211594759,6651197.089448261,99.24378341519409],[508907.6335367675,6651195.400564576,98.63478825519407],[508909.11649266473,6651189.464819925,92.23852090819406],[508909.11649266473,6651189.464819925,92.36852090819407],[508909.26425075,6651188.873396899,92.23852090819406],[508908.05771021196,6651193.702749248,98.63478825519407],[508909.11649266473,6651189.464819925,94.06732456719406],[508908.1586827099,6651193.298592276,98.59704539619406],[508908.06429730315,6651193.6763834655,99.24378341519409],[508909.1120099525,6651189.482762627,94.47813987919407],[508908.2615331648,6651192.88691851,98.51837070319408],[508909.26425075,6651188.873396899,94.06732456719406],[508909.0979919136,6651189.538871847,94.89926130719408],[508908.17873280105,6651193.2183388965,99.20100817419407],[508908.3648643248,6651192.473320655,98.39621758119408],[508909.07371554436,6651189.636041514,95.32535044219406],[508909.25917034276,6651188.893731961,94.53291525419407],[508908.4671043914,6651192.064090057,98.22910282419406],[508908.29529665015,6651192.751775297,99.11184352219406],[508909.0386850681,6651189.776256042,95.75025694619407],[508908.5665668937,6651191.66597706,98.01682501519407],[508908.99269060517,6651189.960355506,96.16722364819408],[508909.24328323203,6651188.957322411,95.01018620619406],[508908.38317165786,6651192.400042916,99.01274802819407],[508908.6615283465,6651191.285880164,97.76061189219408],[508908.9358534309,6651190.187854486,96.56917256519407],[508908.7503176203,6651190.9304883005,97.46316942219407],[508908.86865047866,6651190.456843985,96.94905336719407],[508908.811932916,6651190.683864202,97.21545968219407],[508908.4706132658,6651192.050045281,98.88512526919406],[508909.21577001363,6651189.067448033,95.49308722619406],[508908.55682986166,6651191.704950933,98.72863397719406],[508909.1871558306,6651189.181980424,95.85479321119408],[508908.6410015427,6651191.368041652,98.54342507519407],[508909.1515591743,6651189.324461169,96.21255105719406],[508908.7223025963,6651191.042622471,98.33017274019407],[508909.1089757928,6651189.494907288,96.56300727219407],[508908.7999260017,6651190.731923607,98.09008429319407],[508909.0595262851,6651189.692836069,96.90275229919406],[508908.8731085629,6651190.438999861,97.82488656819406],[508909.0034602904,6651189.917248291,97.22841940919407],[508908.9411551224,6651190.166633703,97.53678821719409],[508915.6162112216,6651204.266210336,92.22959665928788],[508915.76097706036,6651203.674047774,92.22959665928788],[508915.76097706036,6651203.674047774,92.35959665928787],[508915.6162112216,6651204.266210336,94.05840031828788],[508915.6211887457,6651204.245849845,94.52399100528787],[508915.76097650494,6651203.674050045,94.05840031928787],[508915.7620559442,6651203.669634616,94.26222160328788],[508915.63675412675,6651204.18217988,95.00126195728788],[508915.77101897844,6651203.632971454,94.67880089128788],[508915.66371017543,6651204.071916554,95.48416297728788],[508915.78970235295,6651203.556547381,95.10312801128786],[508915.6917448931,6651203.957240948,95.84586896228787],[508915.8187108238,6651203.437888652,95.52943836228786],[508915.72662068217,6651203.81458204,96.20362680828786],[508915.85839661694,6651203.275554492,95.95124722128789],[508915.76834170823,6651203.643922789,96.55408302328787],[508915.90880756435,6651203.069349243,96.36159676428787],[508915.8167898148,6651203.445746511,96.89382805028788],[508915.96965210733,6651202.820465523,96.75337645828789],[508915.871720418,6651203.221053677,97.21949516028786],[508916.0217589198,6651202.607323363,97.03085831828787],[508915.932763845,6651202.971356425,97.52786396828787],[508916.0789834984,6651202.373247055,97.29129899128787],[508915.9994323948,6651202.69864969,97.81596231928788],[508916.14083198435,6651202.120256723,97.53226863728787],[508916.0711329373,6651202.405359662,98.08116004428787],[508916.20672734815,6651201.850712692,97.75168764328787],[508916.14718439226,6651202.094272289,98.32124849128788],[508916.299765738,6651201.470140509,98.00790076628786],[508916.2268390196,6651201.768446192,98.53450082628787],[508916.39721402683,6651201.071529699,98.22017857528787],[508916.3093061413,6651201.431115628,98.71970972828788],[508916.49738363165,6651200.661787384,98.38729333228787],[508916.3937767663,6651201.085589763,98.87620102028787],[508916.4794475957,6651200.735154479,99.00382377928788],[508916.598622234,6651200.247672351,98.50944645428787],[508916.56554304814,6651200.382982281,99.10291927328788],[508916.699389866,6651199.835483816,98.58812114728788],[508916.7983175716,6651199.430821473,98.62586400628788],[508916.6797463646,6651199.9158352725,99.19208392528789],[508916.7918644311,6651199.45721795,99.23485916628788],[508917.20526169904,6651197.766222427,98.62586400628788],[508918.6581862809,6651191.823055518,92.22959665928788],[508918.6581862809,6651191.823055518,92.35959665928787],[508918.8029521197,6651191.230892957,92.22959665928788],[508917.620845214,6651196.066284092,98.62586400628788],[508918.6581862809,6651191.823055518,94.05840031828788],[508917.7197729196,6651195.6616217485,98.58812114728788],[508918.65379434807,6651191.841020656,94.46921563028786],[508917.62729891017,6651196.039885341,99.23485916628788],[508917.8205405517,6651195.249433213,98.50944645428787],[508918.8029521197,6651191.230892957,94.05840031828788],[508918.64006018825,6651191.897200037,94.89033705828787],[508917.73941697675,6651195.581268019,99.19208392528789],[508917.92177915404,6651194.835318179,98.38729333228787],[508918.6162754394,6651191.9944912065,95.31642619328787],[508918.7979745957,6651191.251253446,94.52399100528787],[508918.02194875875,6651194.425575865,98.22017857528787],[508918.5819543646,6651192.134881065,95.74133269728789],[508917.85362029314,6651195.1141210105,99.10291927328788],[508918.11939704756,6651194.026965055,98.00790076628786],[508918.78240921453,6651191.314923412,95.00126195728788],[508918.53689133486,6651192.319210733,96.15829939928787],[508918.2124354374,6651193.646392873,97.75168764328787],[508917.9397157457,6651194.761948813,99.00382377928788],[508918.4812051692,6651192.546994185,96.56024831628787],[508918.2994266412,6651193.290556616,97.45424517328787],[508918.4153631428,6651192.816320039,96.94012911828787],[508918.3597941666,6651193.04362413,97.20653543328788],[508918.75545316585,6651191.4251867365,95.48416297728788],[508918.025386575,6651194.411513528,98.87620102028787],[508918.7274184482,6651191.539862342,95.84586896228787],[508918.1098572,6651194.065987662,98.71970972828788],[508918.6925426591,6651191.682521251,96.20362680828786],[508918.1923243218,6651193.7286570985,98.53450082628787],[508918.65082163305,6651191.853180503,96.55408302328787],[508918.271978949,6651193.402831002,98.32124849128788],[508918.6023735265,6651192.051356779,96.89382805028788],[508918.348030404,6651193.091743629,98.08116004428787],[508918.5474429233,6651192.276049614,97.21949516028786],[508918.4197309465,6651192.798453601,97.81596231928788],[508918.48639949627,6651192.525746866,97.52786396828787],[508925.34776055074,6651206.618911569,92.21282714508105],[508925.48949458316,6651206.026016037,92.21282714508105],[508925.48949458316,6651206.026016037,92.34282714508106],[508925.34776055074,6651206.618911569,94.04163080408105],[508925.3526338313,6651206.598525876,94.50722149108107],[508925.4894940394,6651206.026018311,94.04163080508107],[508925.49055087205,6651206.021597415,94.24545208908106],[508925.36787322926,6651206.534777101,94.98449244308105],[508925.4993261951,6651205.984888872,94.66203137708105],[508925.3942647419,6651206.424377293,95.46739346308105],[508925.51761828695,6651205.908370203,95.08635849708105],[508925.42171233334,6651206.309559744,95.82909944808105],[508925.5460192382,6651205.789564601,95.51266884808105],[508925.4558577247,6651206.166724255,96.18685729408105],[508925.58487389865,6651205.6270295065,95.93447770708106],[508925.4967049945,6651205.995853763,96.53731350908106],[508925.6342290983,6651205.420569018,96.34482725008107],[508925.54413846065,6651205.797432187,96.87705853608105],[508925.69379938435,6651205.171377234,96.73660694408106],[508925.59791866154,6651205.572461231,97.20272564608106],[508925.74481493275,6651204.957971252,97.01408880408107],[508925.65768366656,6651205.322454908,97.51109445408107],[508925.80084106675,6651204.723605206,97.27452947708107],[508925.7229559883,6651205.049410619,97.79919280508105],[508925.8613942703,6651204.470301725,97.51549912308106],[508925.7931549186,6651204.755757561,98.06439053008107],[508925.9259095988,6651204.200424059,97.73491812908105],[508925.867613641,6651204.44428513,98.30447897708106],[508926.0169995016,6651203.819380809,97.99113125208108],[508925.94560007507,6651204.118055731,98.51773131208105],[508926.11240694765,6651203.420276604,98.20340906108106],[508926.02634010196,6651203.780307623,98.70294021408105],[508926.21047871746,6651203.010027117,98.37052381808107],[508926.109041673,6651203.434354072,98.85943150608105],[508926.19291831285,6651203.083485024,98.98705426508106],[508926.30959709705,6651202.595399497,98.49267694008107],[508926.277210683,6651202.730876911,99.08614975908105],[508926.40825436986,6651202.182700761,98.57135163308105],[508926.50511024933,6651201.777537532,98.60909449208106],[508926.38902225887,6651202.263151676,99.17531441108106],[508926.498792256,6651201.803966682,99.21808965208108],[508926.90353181545,6651200.110878071,98.60909449208106],[508928.32602804626,6651194.160354798,92.21282714508105],[508928.32602804626,6651194.160354798,92.34282714508106],[508928.4677620787,6651193.567459267,92.21282714508105],[508927.3104118359,6651198.408835579,98.60909449208106],[508928.32602804626,6651194.160354798,94.04163080408105],[508927.4072677155,6651198.00367235,98.57135163308105],[508928.3217280928,6651194.178342173,94.45244611608105],[508927.3167303734,6651198.382404151,99.21808965208108],[508928.4677620787,6651193.567459267,94.04163080408105],[508927.5059249883,6651197.590973613,98.49267694008107],[508928.3082815652,6651194.234591092,94.87356754408106],[508927.42650037055,6651197.923219158,99.17531441108106],[508927.6050433679,6651197.176345994,98.37052381808107],[508928.2849949362,6651194.332002687,95.29965667908105],[508928.46288879815,6651193.587844958,94.50722149108107],[508927.7031151377,6651196.766096507,98.20340906108106],[508928.25139264186,6651194.472566318,95.72456318308106],[508927.53831194644,6651197.455493922,99.08614975908105],[508928.44764940016,6651193.651593733,94.98449244308105],[508927.7985225836,6651196.366992301,97.99113125208108],[508928.2072733594,6651194.657124148,96.14152988508106],[508927.88961248647,6651195.985949052,97.73491812908105],[508928.1527534197,6651194.885189546,96.54347880208107],[508927.62260431657,6651197.102885812,98.98705426508106],[508927.9747818484,6651195.629672347,97.43747565908106],[508928.08829031157,6651195.154848767,96.92335960408106],[508928.03388510685,6651195.382434212,97.18976591908105],[508928.4212578874,6651193.76199354,95.46739346308105],[508927.7064809564,6651196.752016763,98.85943150608105],[508928.39381029597,6651193.876811091,95.82909944808105],[508927.78918252746,6651196.406063211,98.70294021408105],[508928.3596649047,6651194.019646581,96.18685729408105],[508927.8699225544,6651196.068315105,98.51773131208105],[508928.3188176349,6651194.190517071,96.53731350908106],[508927.9479089884,6651195.7420857055,98.30447897708106],[508928.27138416877,6651194.388938648,96.87705853608105],[508928.0223677109,6651195.430613273,98.06439053008107],[508928.21760396776,6651194.613909604,97.20272564608106],[508928.09256664105,6651195.136960215,97.79919280508105],[508928.15783896286,6651194.863915928,97.51109445408107],[508932.6258556321,6651208.344070148,92.19521859384106],[508932.7653222175,6651207.750637153,92.19521859384106],[508932.7653222175,6651207.750637153,92.32521859384107],[508932.6258556321,6651208.344070148,94.02402225284106],[508932.6306509505,6651208.323665977,94.48961293984107],[508932.7653216824,6651207.75063943,94.02402225384107],[508932.76636160794,6651207.746214527,94.22784353784107],[508932.6456465501,6651208.259859414,94.96688389184106],[508932.7749965442,6651207.7094727075,94.64442282584106],[508932.6716158539,6651208.149359527,95.44978491184106],[508932.7929960009,6651207.632884675,95.06874994584108],[508932.6986243415,6651208.034437896,95.81149089684108],[508932.82094259665,6651207.513971374,95.49506029684106],[508932.73222347815,6651207.891472924,96.16924874284108],[508932.85917566397,6651207.351288939,95.91686915584107],[508932.7724172773,6651207.7204475375,96.51970495784107],[508932.90774128394,6651207.144641295,96.32721869884107],[508932.8190919075,6651207.521846091,96.85944998484106],[508932.9663585705,6651206.895223618,96.71899839284107],[508932.87201173813,6651207.296671198,97.18511709484108],[508933.0165579771,6651206.68162418,96.99648025284107],[508932.93082062836,6651207.046438242,97.49348590284107],[508933.07168781053,6651206.447045681,97.25692092584107],[508932.99504872994,6651206.773146439,97.78158425384106],[508933.13127228996,6651206.193512579,97.49789057184108],[508933.06412462454,6651206.479227183,98.04678197884107],[508933.19475550856,6651205.9233902665,97.71730957784108],[508933.1373921637,6651206.1674724,98.28687042584107],[508933.284388164,6651205.542001599,97.97352270084107],[508933.21413097833,6651205.840947271,98.50012276084107],[508933.37826929096,6651205.142535604,98.18580050984109],[508933.2935793343,6651205.502892993,98.68533166284107],[508933.4747721182,6651204.731914224,98.35291526684107],[508933.37495785364,6651205.156625833,98.84182295484106],[508933.45749264327,6651204.805438722,98.96944571384107],[508933.5723048118,6651204.316910744,98.47506838884107],[508933.5404365123,6651204.452510969,99.06854120784106],[508933.66938377515,6651203.903837893,98.55374308184106],[508933.76469016384,6651203.498307382,98.59148594084108],[508933.65045933763,6651203.984361737,99.15770585984107],[508933.75847324496,6651203.52476049,99.20048110084107],[508935.5564770961,6651195.874219633,92.19521859384106],[508934.15673782077,6651201.830137085,98.59148594084108],[508935.5564770961,6651195.874219633,92.32521859384107],[508935.69594368146,6651195.280786637,92.19521859384106],[508935.5564770961,6651195.874219633,94.02402225284106],[508934.5571086145,6651200.126551682,98.59148594084108],[508935.552245933,6651195.892223312,94.43483756484108],[508934.6524150032,6651199.721021171,98.55374308184106],[508935.69594368146,6651195.280786637,94.02402225284106],[508934.56332606863,6651200.100096295,99.20048110084107],[508935.5390145215,6651195.948523222,94.85595899284108],[508934.7494939665,6651199.30794832,98.47506838884107],[508935.6911483631,6651195.301190808,94.48961293984107],[508935.51610042976,6651196.046023121,95.28204812784107],[508934.84702666,6651198.892944839,98.35291526684107],[508934.6713399761,6651199.640495048,99.15770585984107],[508935.4830357017,6651196.186714173,95.70695463184107],[508934.94352948724,6651198.482323458,98.18580050984109],[508935.6761527636,6651195.364997372,94.96688389184106],[508934.78136280127,6651199.172345817,99.06854120784106],[508935.43962223514,6651196.371439305,96.12392133384108],[508935.0374106143,6651198.082857464,97.97352270084107],[508935.3859745001,6651196.599711447,96.52587025084107],[508935.12704326975,6651197.7014687965,97.71730957784108],[508935.32254266646,6651196.869615115,96.90575105284107],[508934.8643066703,6651198.819418063,98.96944571384107],[508935.6501834597,6651195.475497258,95.44978491184106],[508935.21085010056,6651197.344869125,97.41986710784107],[508935.26900783094,6651197.097406866,97.17215736784107],[508934.94684145995,6651198.468230952,98.84182295484106],[508935.6231749722,6651195.590418891,95.81149089684108],[508935.02821997943,6651198.121963792,98.68533166284107],[508935.58957583545,6651195.733383862,96.16924874284108],[508935.10766833526,6651197.783909515,98.50012276084107],[508935.5493820363,6651195.904409247,96.51970495784107],[508935.50270740606,6651196.103010694,96.85944998484106],[508935.18440715,6651197.457384387,98.28687042584107],[508935.44978757546,6651196.328185587,97.18511709484108],[508935.2576746891,6651197.145629603,98.04678197884107],[508935.39097868523,6651196.578418543,97.49348590284107],[508935.3267505836,6651196.8517103465,97.78158425384106],[508944.7309605982,6651211.148441953,92.15636226031798],[508944.86665591015,6651210.554135273,92.15636226031798],[508944.86665591015,6651210.554135273,92.28636226031799],[508944.7309605982,6651211.148441953,93.98516591931798],[508944.7356262477,6651211.128007742,94.45075660631797],[508944.86665538955,6651210.554137555,93.98516592031797],[508944.86766719486,6651210.549706136,94.18898720431797],[508944.7502163559,6651211.064107238,94.92802755831796],[508944.87606863637,6651210.512910223,94.60556649231798],[508944.77548343176,6651210.953444668,95.41092857831798],[508944.89358137525,6651210.436209433,95.02989361231796],[508944.801761591,6651210.838353842,95.77263456331796],[508944.92077227565,6651210.3171210615,95.45620396331798],[508944.83445218374,6651210.6951783905,96.13039240931796],[508944.95797149424,6651210.154199116,95.87801282231797],[508944.8735591147,6651210.523901211,96.48084862431799],[508945.0052238661,6651209.947247235,96.28836236531797],[508944.9189716305,6651210.325007372,96.82059365131798],[508945.0622561005,6651209.697462349,96.68014205931799],[508944.97046047205,6651210.099500963,97.14626076131796],[508945.1110980803,6651209.483548438,96.95762391931797],[508945.02767912904,6651209.848899601,97.45462956931797],[508945.1647371648,6651209.248624582,97.21806459231797],[508945.09017045813,6651209.575205442,97.74272792031798],[508945.2227104385,6651208.994718214,97.45903423831797],[508945.1573784926,6651209.2808534615,98.00792564531797],[508945.28447702667,6651208.724198211,97.67845324431796],[508945.2286648265,6651208.968639695,98.24801409231797],[508945.3716859529,6651208.342248043,97.93466636731796],[508945.3033285704,6651208.641633839,98.46126642731798],[508945.463028469,6651207.94219393,98.14694417631796],[508945.38062858756,6651208.303081859,98.64647532931797],[508945.5569217928,6651207.530968011,98.31405893331797],[508945.4598065753,6651207.956304904,98.80296662131796],[508945.6518171345,6651207.115353539,98.43621205531797],[508945.5401095668,6651207.604600755,98.93058938031798],[508945.6208105761,6651207.251153402,99.02968487431798],[508945.74627101526,6651206.701672539,98.51488674831798],[508945.839000253,6651206.295544983,98.55262960731797],[508945.7278583078,6651206.782314935,99.11884952631799],[508945.8329514441,6651206.322037038,99.16162476731797],[508947.5823360222,6651198.660232624,92.15636226031798],[508947.5823360222,6651198.660232624,92.28636226031799],[508946.22044666903,6651204.624918713,98.55262960731797],[508947.7180313342,6651198.065925944,92.15636226031798],[508947.5823360222,6651198.660232624,93.98516591931798],[508946.6099911584,6651202.918825195,98.55262960731797],[508947.5782192727,6651198.678262811,94.39598123131796],[508947.7180313342,6651198.065925944,93.98516591931798],[508946.70272039616,6651202.512697639,98.51488674831798],[508947.56534564774,6651198.734645607,94.81710265931797],[508946.61604048836,6651202.892330859,99.16162476731797],[508946.79717427696,6651202.09901664,98.43621205531797],[508947.7133656846,6651198.086360155,94.45075660631797],[508947.54305116896,6651198.832289051,95.24319179431797],[508946.89206961874,6651201.683402168,98.31405893331797],[508946.72113362467,6651202.4320529625,99.11884952631799],[508947.510880534,6651198.973187237,95.66809829831797],[508947.69877557654,6651198.150260659,94.92802755831796],[508946.9859629424,6651201.272176248,98.14694417631796],[508947.4686409979,6651199.158184332,96.08506500031797],[508946.82818135637,6651201.963214495,99.02968487431798],[508947.07730545854,6651200.872122136,97.93466636731796],[508947.41644393484,6651199.386792549,96.48701391731797],[508947.6735085006,6651198.260923229,95.41092857831798],[508947.16451438476,6651200.490171966,97.67845324431796],[508947.3547273421,6651199.657093584,96.86689471931798],[508947.24605502066,6651200.133047289,97.38101077431797],[508947.3026401257,6651199.885220703,97.13330103431797],[508946.90888236556,6651201.609767142,98.93058938031798],[508947.6472303414,6651198.376014055,95.77263456331796],[508946.9891853571,6651201.258062992,98.80296662131796],[508947.6145397487,6651198.519189507,96.13039240931796],[508947.0683633449,6651200.911286038,98.64647532931797],[508947.57543281774,6651198.690466686,96.48084862431799],[508947.14566336205,6651200.572734058,98.46126642731798],[508947.5300203019,6651198.889360525,96.82059365131798],[508947.22032710584,6651200.245728201,98.24801409231797],[508947.4785314604,6651199.114866933,97.14626076131796],[508947.2916134398,6651199.933514435,98.00792564531797],[508947.4213128033,6651199.365468296,97.45462956931797],[508947.3588214742,6651199.639162456,97.74272792031798],[508949.67127328314,6651212.269714138,92.13707974170651],[508949.8054294701,6651211.675058132,92.13707974170651],[508949.8054294701,6651211.675058132,92.26707974170652],[508949.67127328314,6651212.269714138,93.96588340070652],[508949.6758860125,6651212.249267915,94.43147408770653],[508949.8054289554,6651211.675060415,93.96588340170653],[508949.8064292842,6651211.670626392,94.16970468570652],[508949.6903106322,6651212.185329852,94.90874503970652],[508949.81473543245,6651211.63380885,94.58628397370651],[508949.71529111615,6651212.074602236,95.39164605970652],[508949.832049533,6651211.557062976,95.01061109370652],[508949.7412712152,6651211.959443761,95.75335204470652],[508949.8589320203,6651211.437904607,95.43692144470651],[508949.7735910147,6651211.816184153,96.11110989070652],[508949.89570930664,6651211.274886899,95.85873030370652],[508949.8122543749,6651211.644806298,96.46156610570652],[508949.94242571807,6651211.067813372,96.26907984670653],[508949.85715179896,6651211.445795553,96.80131113270652],[508949.998811064,6651210.817881668,96.66085954070653],[508949.9080566281,6651211.220156594,97.12697824270653],[508950.04709905334,6651210.603842022,96.93834140070653],[508949.96462628205,6651210.969407933,97.43534705070654],[508950.10012973606,6651210.368780077,97.19878207370654],[508950.02640880283,6651210.695552899,97.72344540170651],[508950.1574454476,6651210.114724467,97.43975171970652],[508950.0928545297,6651210.401027903,97.98864312670652],[508950.21851144783,6651209.844045457,97.65917072570653],[508950.16333229793,6651210.088630621,98.22873157370653],[508950.30473120627,6651209.461870784,97.91538384870653],[508950.23714916775,6651209.761432555,98.44198390870652],[508950.3950376692,6651209.061581525,98.12766165770651],[508950.313572409,6651209.422681578,98.62719281070652],[508950.4878660074,6651208.650113892,98.29477641470653],[508950.3918523198,6651209.075700793,98.78368410270652],[508950.58168499806,6651208.234255128,98.41692953670653],[508950.47124447423,6651208.723789916,98.91130686170652],[508950.55103013164,6651208.370134811,99.01040235570652],[508950.675067535,6651207.820330971,98.49560422970652],[508950.7667449908,6651207.413964699,98.53334708870652],[508950.6568636737,6651207.901020768,99.09956700770653],[508950.76076479047,6651207.440472324,99.14234224870654],[508952.49030696234,6651199.774164403,92.13707974170651],[508952.49030696234,6651199.774164403,92.26707974170652],[508951.14386484824,6651205.742356456,98.53334708870652],[508952.6244631494,6651199.179508398,92.13707974170651],[508952.49030696234,6651199.774164403,93.96588340070652],[508951.5289909267,6651204.0352601195,98.53334708870652],[508952.486236907,6651199.792205187,94.37669871270653],[508952.6244631494,6651199.179508398,93.96588340070652],[508951.6206683824,6651203.628893848,98.49560422970652],[508952.4735093013,6651199.848621125,94.79782014070652],[508951.53497164196,6651204.0087502105,99.14234224870654],[508952.6198504199,6651199.19995462,94.43147408770653],[508951.71405091946,6651203.214969691,98.41692953670653],[508952.45146769786,6651199.946321964,95.22390927570652],[508951.8078699101,6651202.799110927,98.29477641470653],[508952.4196619585,6651200.087302967,95.64881577970652],[508951.6388727587,6651203.548201768,99.09956700770653],[508952.60542580014,6651199.263892684,94.90874503970652],[508951.90069824824,6651202.387643293,98.12766165770651],[508952.3779015246,6651200.272408801,96.06578248170652],[508951.9910047112,6651201.987354035,97.91538384870653],[508952.3262965071,6651200.501151389,96.46773139870653],[508951.7447063008,6651203.079087725,99.01040235570652],[508952.58044531633,6651199.374620299,95.39164605970652],[508952.07722446957,6651201.60517936,97.65917072570653],[508952.2652799351,6651200.771611306,96.84761220070652],[508952.21378351835,6651200.999872515,97.11401851570652],[508952.1578402302,6651201.24784477,97.36172825570652],[508951.82449195825,6651202.725432619,98.91130686170652],[508952.5544652172,6651199.489778774,95.75335204470652],[508951.9038841126,6651202.373521742,98.78368410270652],[508952.5221454178,6651199.633038383,96.11110989070652],[508951.98216402344,6651202.026540956,98.62719281070652],[508952.4834820575,6651199.8044162365,96.46156610570652],[508952.0585872647,6651201.68778998,98.44198390870652],[508952.43858463346,6651200.003426982,96.80131113270652],[508952.1324041345,6651201.3605919145,98.22873157370653],[508952.38767980435,6651200.229065941,97.12697824270653],[508952.20288190275,6651201.048194633,97.98864312670652],[508952.3311101504,6651200.479814603,97.43534705070654],[508952.2693276296,6651200.753669637,97.72344540170651],[508964.1592355286,6651215.480557236,92.06912625390798],[508964.28887807723,6651214.884900912,92.06912625390798],[508964.28887807723,6651214.884900912,92.19912625390799],[508964.1592355286,6651215.480557236,93.89792991290798],[508964.16369306436,6651215.460076619,94.36352059990799],[508964.2888775799,6651214.884903196,93.89792991390799],[508964.289844253,6651214.880461715,94.101751197908],[508964.17763237277,6651215.396031001,94.840791551908],[508964.2978709437,6651214.843582242,94.51833048590798],[508964.201772397,6651215.2851171205,95.32369257190798],[508964.31460251735,6651214.766707266,94.94265760590798],[508964.2268784046,6651215.169764928,95.685398556908],[508964.3405805528,6651214.64734845,95.36896795690798],[508964.25811081566,6651215.02626433,96.043156402908],[508964.37612048,6651214.484056517,95.790776815908],[508964.2954733606,6651214.854598189,96.39361261790799],[508964.42126513406,6651214.276634655,96.20112635890798],[508964.3388602264,6651214.655252671,96.73335764490798],[508964.47575341456,6651214.026282521,96.59290605290799],[508964.3880523801,6651214.429234146,97.05902475490798],[508964.52241677133,6651213.811882821,96.87038791290799],[508964.44271876774,6651214.1780636795,97.36739356290799],[508964.57366325514,6651213.57642546,97.13082858590799],[508964.5024226372,6651213.903747972,97.65549191390798],[508964.6290505994,6651213.321942482,97.371798231908],[508964.5666328205,6651213.6087275315,97.92068963890799],[508964.6880620553,6651213.050808142,97.59121723790798],[508964.63473938877,6651213.295804741,98.16077808590799],[508964.77138097986,6651212.66799058,97.84743036090799],[508964.7060727157,6651212.968056269,98.37403042090799],[508964.8586491133,6651212.267027964,98.059708169908],[508964.7799247234,6651212.628735453,98.559239322908],[508964.9483542742,6651211.854868167,98.22682292690799],[508964.85557093384,6651212.281170982,98.71573061490798],[508965.0390167575,6651211.438309852,98.34897604890799],[508964.93229196675,6651211.928668127,98.84335337390799],[508965.1292574715,6651211.023689401,98.42765074190798],[508965.00939326355,6651211.574418111,98.94244886790798],[508965.21785047103,6651210.616639547,98.465393600908],[508965.1116660728,6651211.104514932,99.03161351990799],[508965.2120714725,6651210.643191763,99.074388760908],[508966.8834237986,6651202.963987725,92.06912625390798],[508966.8834237986,6651202.963987725,92.19912625390799],[508967.01306634734,6651202.3683314,92.06912625390798],[508965.58228226186,6651208.942219356,98.465393600908],[508966.8834237986,6651202.963987725,93.89792991290798],[508966.8794906789,6651202.982058856,94.30874522490798],[508967.01306634734,6651202.3683314,93.89792991290798],[508965.9544509072,6651207.232251374,98.465393600908],[508966.8671912891,6651203.038569696,94.729866652908],[508966.0430439068,6651206.825201521,98.42765074190798],[508967.0086088116,6651202.388812016,94.36352059990799],[508966.8458912677,6651203.136434885,95.15595578790798],[508965.96023040335,6651207.2056968715,99.074388760908],[508966.1332846207,6651206.41058107,98.34897604890799],[508966.8151556214,6651203.277653044,95.580862291908],[508966.9946695031,6651202.452857635,94.840791551908],[508966.223947104,6651205.994022755,98.22682292690799],[508966.06063580315,6651206.744373702,99.03161351990799],[508966.77480020275,6651203.463070259,95.997828993908],[508966.3136522649,6651205.58186296,98.059708169908],[508966.970529479,6651202.563771514,95.32369257190798],[508966.72493141814,6651203.692197635,96.39977791090799],[508966.40092039836,6651205.180900342,97.84743036090799],[508966.6659677276,6651203.963112514,96.77965871290799],[508966.16290861234,6651206.274470524,98.94244886790798],[508966.4842393229,6651204.798082781,97.59121723790798],[508966.6162038899,6651204.1917576995,97.046065027908],[508966.56214279425,6651204.440147088,97.29377476790799],[508966.9454234713,6651202.679123707,95.685398556908],[508966.2400099091,6651205.920220507,98.84335337390799],[508966.9141910603,6651202.822624304,96.043156402908],[508966.316730942,6651205.567717653,98.71573061490798],[508966.8768285154,6651202.994290448,96.39361261790799],[508966.39237715246,6651205.220153184,98.559239322908],[508966.83344164956,6651203.193635966,96.73335764490798],[508966.46622916026,6651204.880832368,98.37403042090799],[508966.78424949583,6651203.419654489,97.05902475490798],[508966.5375624871,6651204.553083894,98.16077808590799],[508966.72958310816,6651203.670824957,97.36739356290799],[508966.6056690553,6651204.240161103,97.92068963890799],[508966.6698792388,6651203.945140663,97.65549191390798],[508966.7511020551,6651216.042828602,92.05518010288448],[508966.8799371232,6651215.446997104,92.05518010288448],[508966.8799371232,6651215.446997104,92.18518010288449],[508966.7511020551,6651216.042828602,93.88398376188448],[508966.755531827,6651216.022341961,94.34957444888448],[508966.87993662886,6651215.446999391,93.88398376288448],[508966.8808972811,6651215.442556604,94.08780504688448],[508966.7693843142,6651215.958277508,94.82684540088448],[508966.8888739774,6651215.405666283,94.50438433488448],[508966.7933739819,6651215.84733101,95.30974642088448],[508966.90550133825,6651215.3287687,94.92871145488448],[508966.81832361646,6651215.731944894,95.67145240588448],[508966.931317569,6651215.209374783,95.35502180588449],[508966.84936149593,6651215.588402097,96.02921025188448],[508966.9666361353,6651215.046034829,95.77683066488449],[508966.88649132766,6651215.41668547,96.3796664668845],[508967.0114996052,6651214.838551968,96.1871802078845],[508966.9296079578,6651215.2172813285,96.71941149388448],[508967.06564850465,6651214.588126208,96.57895990188449],[508966.9784937174,6651214.991196336,97.04507860388448],[508967.11202121794,6651214.373663458,96.85644176188448],[508967.03281961463,6651214.739952004,97.35344741188449],[508967.1629485123,6651214.138136854,97.1168824348845],[508967.0921516176,6651214.465555625,97.64154576288448],[508967.21799087565,6651213.883579036,97.35785208088448],[508967.1559618669,6651214.170448423,97.9067434878845],[508967.2766347778,6651213.612364959,97.57727108688448],[508967.2236442322,6651213.857433608,98.1468319348845],[508967.35943474923,6651213.229434817,97.8334842098845],[508967.2945332585,6651213.529588751,98.3600842698845],[508967.4461593317,6651212.828354284,98.04576201888449],[508967.36792527785,6651213.190168145,98.54529317188448],[508967.5353057627,6651212.416073279,98.21287677588448],[508967.4431003248,6651212.842501462,98.7017844638845],[508967.6254035534,6651211.999392463,98.33502989788448],[508967.5193434995,6651212.489894943,98.82940722288448],[508967.7150822017,6651211.584650078,98.41370459088448],[508967.5959645697,6651212.135540748,98.92850271688448],[508967.80312339845,6651211.177480518,98.45144744988448],[508967.6976003712,6651211.665499379,99.01766736888449],[508967.79738039436,6651211.204040544,99.06044260988449],[508969.45832267724,6651203.522578181,92.05518010288448],[508969.45832267724,6651203.522578181,92.18518010288449],[508969.5871577454,6651202.926746684,92.05518010288448],[508968.1652853203,6651209.502567909,98.45144744988448],[508969.45832267724,6651203.522578181,93.88398376188448],[508969.4544140551,6651203.540654628,94.29479907388448],[508969.5871577454,6651202.926746684,93.88398376188448],[508968.5351359076,6651207.792097054,98.45144744988448],[508969.44219127216,6651203.597182088,94.71592050188448],[508968.6231771042,6651207.384927495,98.41370459088448],[508969.58272797347,6651202.947233324,94.34957444888448],[508969.42102391826,6651203.695076056,95.1420096368845],[508968.5408794061,6651207.765534743,99.06044260988449],[508968.7128557526,6651206.97018511,98.33502989788448],[508969.3904797095,6651203.836335745,95.56691614088449],[508969.5688754862,6651203.011297778,94.82684540088448],[508968.8029535432,6651206.553504294,98.21287677588448],[508969.3503756451,6651204.021807489,95.98388284288448],[508968.6406594292,6651207.304075907,99.01766736888449],[508968.89209997427,6651206.141223288,98.04576201888449],[508969.5448858186,6651203.122244275,95.30974642088448],[508969.30081746896,6651204.251002246,96.3858317598845],[508968.97882455675,6651205.740142754,97.8334842098845],[508969.24222103466,6651204.521996795,96.7657125618845],[508968.7422952308,6651206.834034539,98.92850271688448],[508969.06162452814,6651205.357212614,97.57727108688448],[508969.19276715175,6651204.750709222,97.03211887688448],[508969.1390427766,6651204.9991716575,97.2798286168845],[508969.51993618405,6651203.2376303915,95.67145240588448],[508968.8189163009,6651206.479680342,98.82940722288448],[508969.4888983046,6651203.381173189,96.02921025188448],[508968.89515947574,6651206.1270738235,98.7017844638845],[508969.4517684728,6651203.5528898155,96.3796664668845],[508968.97033452266,6651205.77940714,98.54529317188448],[508969.40865184274,6651203.752293957,96.71941149388448],[508969.04372654203,6651205.439986534,98.3600842698845],[508969.3597660831,6651203.97837895,97.04507860388448],[508969.1146155682,6651205.112141677,98.1468319348845],[508969.3054401859,6651204.229623281,97.35344741188449],[508969.1822979336,6651204.799126862,97.9067434878845],[508969.24610818294,6651204.504019661,97.64154576288448],[508983.63057475275,6651219.614809092,91.95111912584724],[508983.7541511217,6651219.0178647665,91.95111912584724],[508983.7541511217,6651219.0178647665,92.08111912584725],[508983.8639770783,6651219.663112026,91.94951967737245],[508983.63057475275,6651219.614809092,93.77992278484724],[508983.9874807321,6651219.066152652,91.94951967737245],[508983.6348237134,6651219.59428419,94.24551347184725],[508983.75415064755,6651219.017867057,93.77992278584725],[508983.9874807321,6651219.066152652,92.07951967737247],[508983.75507208856,6651219.013415971,93.98374406984725],[508983.6481107796,6651219.530100084,94.72278442384724],[508983.76272319775,6651218.976456751,94.40032335784724],[508983.6711212539,6651219.418946372,95.20568544384724],[508983.77867187466,6651218.899415548,94.82465047784726],[508983.8639770783,6651219.663112026,93.77832333637247],[508983.6950525118,6651219.303344752,95.56739142884726],[508983.8034343567,6651218.77979864,95.25096082884724],[508983.8682235387,6651219.642586607,94.24391402337245],[508983.9874802582,6651219.066154941,93.77832333737246],[508983.988401157,6651219.061703744,93.98214462137246],[508983.7248235089,6651219.159533859,95.92514927484724],[508983.8815027865,6651219.578400882,94.72118497537245],[508983.8373113146,6651218.6161536155,95.67276968784725],[508983.99604776414,6651219.024743592,94.39872390937245],[508983.7604378013,6651218.987496519,96.27560548984725],[508983.9044997209,6651219.467244368,95.20408599537247],[508983.88034357893,6651218.408283242,96.08311923084725],[508984.01198705647,6651218.9477004465,94.82305102937245],[508983.8017945271,6651218.787719951,96.61535051684724],[508983.92841689714,6651219.351639832,95.56579198037245],[508984.0367349677,6651218.828080523,95.24936138037246],[508983.93228226673,6651218.157389765,96.47489892484725],[508983.8486849023,6651218.561212704,96.94101762684726],[508983.95817037625,6651219.207825315,95.92354982637245],[508983.9767621712,6651217.9425264625,96.75238078484726],[508984.07059199165,6651218.664431374,95.67117023937246],[508983.9007933632,6651218.309499124,97.24938643484727],[508983.9937637125,6651219.035783638,96.27400604137247],[508984.02561075106,6651217.706559968,97.01282145784725],[508984.11359893484,6651218.4565557595,96.08151978237245],[508983.95770359423,6651218.034590257,97.53748478584724],[508984.03509610303,6651218.836002034,96.61375106837247],[508984.078406434,6651217.451526715,97.25379110384725],[508984.01890928164,6651217.738931888,97.80268251084725],[508984.16550706077,6651218.2056559585,96.47329947637246],[508984.13465665065,6651217.179806095,97.47321010984726],[508984.0819588868,6651218.609489076,96.93941817837245],[508984.2099607923,6651217.99078724,96.75078133637246],[508984.08382903587,6651217.425332457,98.04277095784725],[508984.134036686,6651218.357769151,97.24778698637246],[508984.21407695103,6651216.796160758,97.72942323284725],[508984.2587806285,6651217.754814797,97.01122200937246],[508984.1518245636,6651217.096875287,98.25602329284725],[508984.1909134298,6651218.0828533545,97.53588533737245],[508984.29726167064,6651216.39433113,97.94170104184724],[508984.3115452453,6651217.4997751145,97.25219165537246],[508984.22222091927,6651216.756820748,98.44123219484725],[508984.25208310236,6651217.787187531,97.80108306237247],[508984.3827693853,6651215.981280112,98.10881579884726],[508984.367762363,6651217.228047645,97.47161066137245],[508984.294327524,6651216.408504731,98.59772348684724],[508984.3169646564,6651217.473580196,98.04117150937248],[508984.4691896277,6651215.563821062,98.23096892084726],[508984.3674586585,6651216.055239651,98.72534624584725],[508984.44713593076,6651216.844392635,97.72782378437245],[508984.555207836,6651215.148304069,98.30964361384724],[508984.38492017414,6651217.145114744,98.25442384437247],[508984.4409522638,6651215.700223631,98.82444173984725],[508984.5302717025,6651216.4425528785,97.94010159337245],[508984.6396554291,6651214.740374042,98.34738647284725],[508984.45527510694,6651216.805051634,98.43963274637245],[508986.22729394847,6651207.071174711,91.95111912584724],[508984.5384395666,6651215.2293043705,98.91360639184725],[508986.22729394847,6651207.071174711,92.08111912584725],[508984.6157291025,6651216.029491446,98.10721635037245],[508984.52733928256,6651216.456726837,98.59612403837247],[508984.6341468391,6651214.766983673,98.95638163284727],[508986.3508703175,6651206.474230385,91.95111912584724],[508984.7020984934,6651215.612021874,98.22936947237245],[508984.60042738507,6651216.103452851,98.72374679737247],[508984.7880660867,6651215.196494405,98.30804416537245],[508984.673877745,6651215.748427881,98.82284229137247],[508984.98703488056,6651213.062333213,98.34738647284725],[508984.872463989,6651214.788554094,98.34578702437246],[508986.4591683062,6651207.119161429,91.94951967737245],[508984.77130768413,6651215.277496749,98.91200694337246],[508986.22729394847,6651207.071174711,93.77992278484724],[508986.4591683062,6651207.119161429,92.07951967737247],[508984.8669586402,6651214.815164397,98.95478218437246],[508986.5826719601,6651206.522202054,91.94951967737245],[508986.22354486573,6651207.089284918,94.19073809684726],[508986.3508703175,6651206.474230385,93.77992278484724],[508986.21182098374,6651207.145917953,94.61185952484726],[508985.34178916673,6651211.348667727,98.34738647284725],[508986.3466213569,6651206.494755287,94.24551347184725],[508986.191517624,6651207.243994758,95.03794865984725],[508985.2196390345,6651213.110470964,98.34578702437246],[508985.4262367599,6651210.9407377,98.30964361384724],[508986.3333342907,6651206.558939394,94.72278442384724],[508986.16222014715,6651207.385518276,95.46285516384725],[508985.51225496817,6651210.525220706,98.23096892084726],[508985.34729823115,6651211.322055805,98.95638163284727],[508986.1237530224,6651207.571336425,95.87982186584726],[508986.4591683062,6651207.119161429,93.77832333637247],[508985.5986752106,6651210.107761657,98.10881579884726],[508986.31032381643,6651206.670093105,95.20568544384724],[508986.07621767704,6651207.800959247,96.28177078284725],[508985.44300550356,6651210.859735106,98.91360639184725],[508985.68418292527,6651209.694710638,97.94170104184724],[508986.0200129907,6651208.07245993,96.66165158484725],[508986.2863925585,6651206.785694726,95.56739142884726],[508985.76736764493,6651209.292881011,97.72942323284725],[508985.9725776816,6651208.301599521,96.92805789984725],[508986.4554214295,6651207.137272093,94.18913864837245],[508985.8467879453,6651208.909235673,97.47321010984726],[508985.9210461901,6651208.550526008,97.17576763984725],[508986.5826719601,6651206.522202054,93.77832333637247],[508985.54049280647,6651210.388815845,98.82444173984725],[508986.25662156136,6651206.929505618,95.92514927484724],[508985.6139864117,6651210.033799825,98.72534624584725],[508986.22100726893,6651207.101542958,96.27560548984725],[508986.44370444614,6651207.193906556,94.61026007637246],[508985.6871175462,6651209.6805347465,98.59772348684724],[508986.17965054314,6651207.3013195265,96.61535051684724],[508985.5741845753,6651211.396762278,98.34578702437246],[508986.57842549967,6651206.542727474,94.24391402337245],[508985.75922415097,6651209.332218729,98.44123219484725],[508986.132760168,6651207.527826774,96.94101762684726],[508986.4234130333,6651207.291985833,95.03634921137247],[508985.8296205066,6651208.992164191,98.25602329284725],[508986.080651707,6651207.779540353,97.24938643484727],[508985.89761603443,6651208.663707021,98.04277095784725],[508986.02374147606,6651208.05444922,97.53748478584724],[508985.96253578865,6651208.35010759,97.80268251084725],[508985.6585824776,6651210.988821967,98.30804416537245],[508986.5651462519,6651206.606913199,94.72118497537245],[508986.39413279586,6651207.43351292,95.46125571537246],[508985.7445500709,6651210.573294497,98.22936947237245],[508985.5796903981,6651211.370149684,98.95478218437246],[508986.35568830586,6651207.619335752,95.87822241737246],[508985.8309194617,6651210.155824927,98.10721635037245],[508986.54214931745,6651206.718069713,95.20408599537247],[508986.3081809314,6651207.848964362,96.28017133437245],[508985.6753413542,6651210.907817331,98.91200694337246],[508985.9163768618,6651209.742763494,97.94010159337245],[508986.51823214133,6651206.833674248,95.56579198037245],[508986.2520093172,6651208.120471891,96.66005213637247],[508985.99951263354,6651209.340923736,97.72782378437245],[508986.20460192004,6651208.349617258,96.92645845137245],[508986.0788862013,6651208.957268728,97.47161066137245],[508986.1531007509,6651208.59855002,97.17416819137247],[508985.77277129336,6651210.4368862,98.82284229137247],[508986.48847866204,6651206.977488765,95.92354982637245],[508985.8462216534,6651210.08186123,98.72374679737247],[508986.45288532594,6651207.1495304415,96.27400604137247],[508985.91930975585,6651209.728587244,98.59612403837247],[508986.4115529353,6651207.349312046,96.61375106837247],[508985.9913739314,6651209.380262447,98.43963274637245],[508986.36469015153,6651207.575825005,96.93941817837245],[508986.0617288643,6651209.040199336,98.25442384437247],[508986.3126123523,6651207.827544929,97.24778698637246],[508986.129684382,6651208.711733885,98.04117150937248],[508986.2557356087,6651208.102460726,97.53588533737245],[508986.19456593593,6651208.398126549,97.80108306237247],[509001.0085308428,6651223.13027511,91.82009846517153],[509001.1266932131,6651222.532235561,91.82009846517153],[509001.1266932131,6651222.532235561,91.95009846517154],[509001.0085308428,6651223.13027511,93.64890212417153],[509001.12669275975,6651222.532237856,93.64890212517152],[509001.0125936525,6651223.1097125495,94.11449281117152],[509001.1275738315,6651222.527778604,93.85272340917152],[509001.02529859956,6651223.045410684,94.59176376317151],[509001.1348897383,6651222.490751574,94.26930269717153],[509001.04730096296,6651222.934053037,95.07466478317153],[509001.1501396884,6651222.413569022,94.69362981717151],[509001.0701837696,6651222.818239321,95.43637076817151],[509001.17381730245,6651222.2937326515,95.11994016817152],[509001.09865047096,6651222.6741645755,95.79412861417151],[509001.20621007856,6651222.129787385,95.54174902717152],[509001.1327044672,6651222.501811597,96.14458482917154],[509001.2473570583,6651221.921535629,95.95209857017151],[509001.17224931536,6651222.301668496,96.48432985617153],[509001.2970202626,6651221.670181833,96.34387826417154],[509001.2170853785,6651222.074745672,96.80999696617151],[509001.33955146,6651221.454924319,96.62136012417152],[509001.266910918,6651221.822570269,97.11836577417152],[509001.3862599369,6651221.218524894,96.88180079717152],[509001.32132785744,6651221.547157025,97.40646412517152],[509001.43674259057,6651220.963023727,97.12277044317152],[509001.3798520653,6651221.250956206,97.67166185017152],[509001.49052843155,6651220.690804577,97.34218944917151],[509001.4419276231,6651220.936781408,97.91175029717152],[509001.5664692527,6651220.30645536,97.59840257217152],[509001.5069442019,6651220.607721613,98.12500263217153],[509001.64600957034,6651219.903888489,97.81068038117152],[509001.57425642596,6651220.267043172,98.31021153417151],[509001.72777111037,6651219.4900796395,97.97779513817152],[509001.6432039715,6651219.918088094,98.46670282617151],[509001.8104051995,6651219.071854672,98.09994826017152],[509001.71313116123,6651219.564174876,98.59432558517153],[509003.4914852917,6651210.563626738,91.82009846517153],[509001.8926548681,6651218.655575323,98.17862295317153],[509001.7834049415,6651219.2085075015,98.69342107917153],[509003.4914852917,6651210.563626738,91.95009846517154],[509001.9734027315,6651218.246896861,98.21636581217152],[509003.609647662,6651209.965587189,91.82009846517153],[509001.87662123254,6651218.736724238,98.78258573117154],[509001.96813547803,6651218.273555313,98.82536097217152],[509002.3055631575,6651216.565777306,98.21636581217152],[509003.4914852917,6651210.563626738,93.64890212417153],[509003.4879004598,6651210.581770174,94.05971743617151],[509003.609647662,6651209.965587189,93.64890212417153],[509003.47669021226,6651210.638507114,94.48083886417152],[509003.60558485246,6651209.98614975,94.11449281117152],[509003.45727636217,6651210.736763861,94.90692799917151],[509002.6447753198,6651214.848967734,98.21636581217152],[509003.59287990525,6651210.050451616,94.59176376317151],[509003.42926243576,6651210.878547035,95.33183450317152],[509002.7255231832,6651214.440289271,98.17862295317153],[509003.39248059236,6651211.064706106,95.74880120517152],[509003.57087754185,6651210.161809263,95.07466478317153],[509002.8077728518,6651214.024009922,98.09994826017152],[509002.65004302684,6651214.822306987,98.82536097217152],[509003.34702781594,6651211.294750222,96.15075012217152],[509002.8904069409,6651213.605784956,97.97779513817152],[509003.5479947352,6651210.277622979,95.43637076817151],[509003.29328551056,6651211.56674903,96.53063092417153],[509002.9721684809,6651213.191976106,97.81068038117152],[509002.74155727227,6651214.35913806,98.78258573117154],[509003.24792838754,6651211.796309028,96.79703723917152],[509003.0517087985,6651212.789409236,97.59840257217152],[509003.19865454,6651212.045692224,97.04474697917152],[509003.1276496197,6651212.405060018,97.34218944917151],[509003.51952803385,6651210.421697723,95.79412861417151],[509002.83477356343,6651213.887354798,98.69342107917153],[509003.4854740376,6651210.594050703,96.14458482917154],[509002.9050473436,6651213.5316874245,98.59432558517153],[509003.44592918945,6651210.794193803,96.48432985617153],[509002.9749745333,6651213.177774205,98.46670282617151],[509003.4010931264,6651211.021116628,96.80999696617151],[509003.0439220788,6651212.828819128,98.31021153417151],[509003.3512675868,6651211.27329203,97.11836577417152],[509003.1112343029,6651212.488140686,98.12500263217153],[509003.2968506475,6651211.548705275,97.40646412517152],[509003.1762508817,6651212.15908089,97.91175029717152],[509003.2383264395,6651211.8449060945,97.67166185017152],[509003.1429632246,6651223.550769676,91.80234087613896],[509003.2604606253,6651222.952599125,91.80234087613896],[509003.2604606253,6651222.952599125,91.93234087613897],[509003.1429632246,6651223.550769676,93.63114453513896],[509003.2604601744,6651222.952601421,93.63114453613898],[509003.1470031704,6651223.530202612,94.09673522213897],[509003.2613362879,6651222.948141192,93.83496582013896],[509003.1596366192,6651223.465886662,94.57400617413896],[509003.2686110237,6651222.911106051,94.25154510813896],[509003.1815151624,6651223.3545046225,95.05690719413896],[509003.2837751533,6651222.833906592,94.67587222813896],[509003.20426919387,6651223.238665534,95.41861317913896],[509003.30731951946,6651222.714043971,95.10218257913895],[509003.2325756962,6651223.094559231,95.77637102513896],[509003.33953000215,6651222.550062792,95.52399143813896],[509003.2664380505,6651222.922168497,96.12682724013897],[509003.3804454234,6651222.341765418,95.93434098113897],[509003.30576035636,6651222.721981554,96.46657226713896],[509003.42982914345,6651222.090356562,96.32612067513897],[509003.3503441003,6651222.495009021,96.79223937713896],[509003.4721209926,6651221.875051895,96.60360253513898],[509003.399889242,6651222.24277838,97.10060818513897],[509003.5185666132,6651221.638600685,96.86404320813898],[509003.4539999451,6651221.967304803,97.38870653613895],[509003.56876517105,6651221.383043551,97.10501285413896],[509003.5121948025,6651221.671039101,97.65390426113898],[509003.6222483272,6651221.11076477,97.32443186013896],[509003.57392102433,6651221.356795484,97.89399270813898],[509003.6977617845,6651220.726331361,97.58064498313898],[509003.6385717163,6651221.027663606,98.10724504313896],[509003.77685448155,6651220.323676307,97.79292279213897],[509003.7055051346,6651220.686910538,98.29245394513896],[509003.8581559009,6651219.90977681,97.96003754913897],[509003.77406467154,6651220.337879022,98.44894523713897],[509003.9403249591,6651219.49146023,98.08219067113896],[509003.8435983395,6651219.983888276,98.57656799613896],[509005.6119446172,6651210.981368539,91.80234087613896],[509004.02211176,6651219.075089693,98.16086536413896],[509005.6119446172,6651210.981368539,91.93234087613897],[509003.9134766474,6651219.628142994,98.67566349013896],[509004.1024052073,6651218.666321708,98.19860822313896],[509005.7294420178,6651210.383197987,91.80234087613896],[509004.0061683553,6651219.156256384,98.76482814213897],[509004.0971675958,6651218.692985999,98.80760338313898],[509004.43269636977,6651216.984833899,98.19860822313896],[509005.6119446172,6651210.981368539,93.63114453513896],[509005.60837995925,6651210.999515948,94.04195984713895],[509005.7294420178,6651210.383197987,93.63114453513896],[509005.5972327985,6651211.056265317,94.46308127513896],[509005.7254020721,6651210.403765052,94.09673522213897],[509005.5779282015,6651211.154543589,94.88917041013897],[509004.7699995841,6651215.267648254,98.19860822313896],[509005.7127686232,6651210.468081003,94.57400617413896],[509005.55007192615,6651211.296357821,95.31407691413897],[509004.85029303154,6651214.858880268,98.16086536413896],[509005.51349707606,6651211.482557669,95.73104361613896],[509005.6908900801,6651210.579463043,95.05690719413896],[509004.93207983236,6651214.442509731,98.08219067113896],[509004.7752376467,6651215.2409816645,98.80760338313898],[509005.4683000892,6651211.712652177,96.13299253313897],[509005.0142488905,6651214.024193152,97.96003754913897],[509005.66813604854,6651210.69530213,95.41861317913896],[509005.4148602237,6651211.984710569,96.51287333513896],[509005.09555030987,6651213.610293655,97.79292279213897],[509005.3697583521,6651212.214320851,96.77927965013896],[509004.8662368872,6651214.777711282,98.76482814213897],[509005.174643007,6651213.207638601,97.58064498313898],[509005.32076179766,6651212.463758675,97.02698939013897],[509005.6398295462,6651210.839408435,95.77637102513896],[509005.25015646423,6651212.823205192,97.32443186013896],[509004.958928595,6651214.305824672,98.67566349013896],[509005.605967192,6651211.011799168,96.12682724013897],[509005.028806903,6651213.95007939,98.57656799613896],[509005.56664488616,6651211.211986111,96.46657226713896],[509005.0983405709,6651213.596088643,98.44894523713897],[509005.5220611422,6651211.438958645,96.79223937713896],[509005.1669001078,6651213.247057126,98.29245394513896],[509005.4725160005,6651211.691189285,97.10060818513897],[509005.2338335261,6651212.90630406,98.10724504313896],[509005.4184052974,6651211.9666628605,97.38870653613895],[509005.29848421813,6651212.577172182,97.89399270813898],[509005.36021044,6651212.262928563,97.65390426113898],[509018.18339330686,6651226.444040789,91.66691646628368],[509018.296204951,6651225.844968856,91.66691646628368],[509018.296204951,6651225.844968856,91.7969164662837],[509018.18339330686,6651226.444040789,93.49572012528368],[509018.29620451824,6651225.844971155,93.49572012628369],[509018.18727214093,6651226.423442733,93.96131081228368],[509018.29704569257,6651225.840504205,93.69954141028369],[509018.1994017721,6651226.359029864,94.43858176428368],[509018.3040303144,6651225.803413256,94.11612069828368],[509018.3185897037,6651225.7260974655,94.54044781828368],[509018.2204078064,6651226.247479983,94.92148278428368],[509018.2422544149,6651226.131466338,95.28318876928368],[509018.34119512845,6651225.606054223,94.9667581692837],[509018.2694320635,6651225.98714288,95.64094661528368],[509018.3721210681,6651225.441825942,95.38856702828369],[509018.30194399855,6651225.814492373,95.9914028302837],[509018.41140479635,6651225.233214686,95.79891657128368],[509018.3396981443,6651225.614003768,96.3311478572837],[509018.4588191103,6651224.981426982,96.19069626528369],[509018.3825039037,6651225.386689211,96.65681496728368],[509018.4994243749,6651224.765797873,96.46817812528369],[509018.43007320195,6651225.134078483,96.96518377528369],[509018.54401776,6651224.528990356,96.72861879828369],[509018.4820259885,6651224.858189798,97.25328212628368],[509018.5922144164,6651224.273048123,96.96958844428369],[509018.53790005494,6651224.561477653,97.5184798512837],[509018.6435646825,6651224.000359045,97.18900745028368],[509018.597164656,6651224.246760503,97.7585682982837],[509018.71606668865,6651223.615346335,97.44522057328368],[509018.65923710045,6651223.917132658,97.9718206332837],[509018.7920051959,6651223.212084521,97.65749838228368],[509018.72350123676,6651223.57586611,98.15702953528368],[509018.87006434234,6651222.7975613205,97.82461313928368],[509018.7893266425,6651223.226308638,98.3135208272837],[509020.55391256086,6651213.855698859,91.66691646628368],[509020.55391256086,6651213.855698859,91.7969164662837],[509018.9489565264,6651222.378614381,97.94676626128368],[509018.8560873314,6651222.871784465,98.4411435862837],[509020.666724205,6651213.256626926,91.66691646628368],[509019.0274816975,6651221.961616416,98.02544095428368],[509018.9231789163,6651222.51550311,98.5402390802837],[509019.1045730695,6651221.55223246,98.06318381328369],[509019.01217411034,6651222.042905418,98.62940373228369],[509019.0995443321,6651221.578936933,98.67217897328369],[509020.55391256086,6651213.855698859,93.49572012528368],[509019.4216923326,6651219.868210822,98.06318381328369],[509020.55049006024,6651213.873873615,93.90653543728368],[509020.666724205,6651213.256626926,93.49572012528368],[509020.5397874445,6651213.930708499,94.32765686528369],[509020.662845371,6651213.277224983,93.96131081228368],[509020.5212527083,6651214.029134865,94.7537460002837],[509020.65071573976,6651213.341637852,94.43858176428368],[509020.4945073317,6651214.171162796,95.17865250428369],[509019.74554400943,6651218.148437555,98.06318381328369],[509020.6297097055,6651213.453187733,94.92148278428368],[509020.4593910742,6651214.35764323,95.59561920628369],[509019.8226353814,6651217.7390536,98.02544095428368],[509019.9011605525,6651217.322055635,97.94676626128368],[509020.41599652776,6651214.588084466,95.99756812328368],[509020.60786309704,6651213.569201377,95.28318876928368],[509019.75057317986,6651218.121730783,98.67217897328369],[509019.9800527366,6651216.903108694,97.82461313928368],[509020.364687826,6651214.860552821,96.3774489252837],[509020.58068544837,6651213.713524835,95.64094661528368],[509020.3213846017,6651215.090509103,96.64385524028368],[509020.058111883,6651216.488585494,97.65749838228368],[509020.2743420132,6651215.340322805,96.8915649802837],[509020.13405039016,6651216.08532368,97.44522057328368],[509020.2065523964,6651215.70031097,97.18900745028368],[509019.83794340165,6651217.657762299,98.62940373228369],[509020.5481735133,6651213.886175345,95.9914028302837],[509019.9269385956,6651217.185164605,98.5402390802837],[509020.51041936764,6651214.086663947,96.3311478572837],[509019.9940301805,6651216.828883251,98.4411435862837],[509020.4676136083,6651214.313978504,96.65681496728368],[509020.06079086935,6651216.474359077,98.3135208272837],[509020.4200443099,6651214.5665892325,96.96518377528369],[509020.1266162752,6651216.124801606,98.15702953528368],[509020.3680915234,6651214.842477918,97.25328212628368],[509020.1908804115,6651215.783535059,97.9718206332837],[509020.31221745705,6651215.139190063,97.5184798512837],[509020.2529528559,6651215.453907212,97.7585682982837],[509022.6943816497,6651227.288031666,91.62279150477926],[509022.8057879224,6651226.688696793,91.62279150477926],[509022.8057879224,6651226.688696793,91.75279150477925],[509022.6943816497,6651227.288031666,93.45159516377925],[509022.805787495,6651226.688699093,93.45159516477925],[509022.69821216253,6651227.267424568,93.91718585077925],[509022.8066181902,6651226.684230181,93.65541644877926],[509022.71019068663,6651227.202983428,94.39445680277926],[509022.8135157998,6651226.647122953,94.07199573677924],[509022.82789381297,6651226.569773227,94.49632285677924],[509022.7309350344,6651227.091384585,94.87735782277925],[509022.7525094849,6651226.975320023,95.23906380777925],[509022.8502176265,6651226.449677298,94.92263320777924],[509022.77934856294,6651226.83093322,95.59682165377924],[509022.8807583006,6651226.285376933,95.34444206677927],[509022.8114554747,6651226.658206931,95.94727786877925],[509022.91955264466,6651226.076674115,95.75479160977925],[509022.8487392913,6651226.457630331,96.28702289577924],[509022.96637628623,6651225.824775898,96.14657130377927],[509022.8910117901,6651226.230216002,96.61269000577924],[509023.0064757034,6651225.609052147,96.42405316377925],[509022.93798848527,6651225.977494401,96.92105881377925],[509023.0505135583,6651225.372140692,96.68449383677925],[509022.9892940606,6651225.701484624,97.20915716477926],[509023.09810979606,6651225.1160861235,96.92546348277926],[509023.0444720656,6651225.4046422485,97.47435488977925],[509023.1488203569,6651224.843277358,97.14488248877925],[509023.10299836716,6651225.0897869645,97.71444333677925],[509023.2204191562,6651224.45809566,97.40109561177925],[509023.1642975329,6651224.760014442,97.92769567177925],[509023.2954116456,6651224.054656851,97.61337342077925],[509023.22776108695,6651224.418598108,98.11290457377926],[509023.3724983561,6651223.639951711,97.78048817777925],[509025.03536972974,6651214.694164551,91.62279150477926],[509023.2927664609,6651224.068887212,98.26939586577925],[509025.03536972974,6651214.694164551,91.75279150477925],[509023.4504077264,6651223.220820889,97.90264129977925],[509025.1467760023,6651214.094829679,91.62279150477926],[509023.35869546636,6651223.714207433,98.39701862477925],[509023.5279546559,6651222.803639899,97.98131599277926],[509023.4249512456,6651223.357769702,98.49611411877925],[509023.6040856482,6651222.394076259,98.01905885177926],[509023.5128377658,6651222.88496458,98.58527877077927],[509023.5991195571,6651222.420792453,98.62805401177926],[509025.03536972974,6651214.694164551,93.45159516377925],[509023.9172543405,6651220.7093154825,98.01905885177926],[509025.0319898655,6651214.712347284,93.86241047577924],[509025.1467760023,6651214.094829679,93.45159516377925],[509025.02142057946,6651214.769207114,94.28353190377925],[509025.14294548956,6651214.115436777,93.91718585077925],[509025.0031167431,6651214.86767668,94.70962103877925],[509025.1309669654,6651214.179877915,94.39445680277926],[509024.9767045519,6651215.009766949,95.13452754277927],[509024.23707157624,6651218.988787385,98.01905885177926],[509025.11022261763,6651214.291476759,94.87735782277925],[509024.9420257615,6651215.196329231,95.55149424477925],[509024.31320256856,6651218.579223745,97.98131599277926],[509025.08864816726,6651214.4075413225,95.23906380777925],[509024.89917181066,6651215.426871612,95.95344316177925],[509024.39074949804,6651218.162042755,97.90264129977925],[509024.84850229626,6651215.6994595565,96.33332396377925],[509024.2420380949,6651218.962068891,98.62805401177926],[509024.46865886834,6651217.742911933,97.78048817777925],[509025.0618090891,6651214.551928124,95.59682165377924],[509024.80573852983,6651215.929516769,96.59973027877926],[509024.54574557877,6651217.328206794,97.61337342077925],[509024.75928198284,6651216.179440118,96.84744001877925],[509024.62073806825,6651216.924767983,97.40109561177925],[509024.69233686756,6651216.539586286,97.14488248877925],[509025.02970217733,6651214.724654413,95.94727786877925],[509024.32831988623,6651218.497896764,98.58527877077927],[509024.99241836084,6651214.925231013,96.28702289577924],[509024.41620640643,6651218.025091642,98.49611411877925],[509024.95014586195,6651215.152645342,96.61269000577924],[509024.48246218567,6651217.668653911,98.39701862477925],[509024.90316916676,6651215.405366943,96.92105881377925],[509024.54839119123,6651217.313974132,98.26939586577925],[509024.8518635915,6651215.68137672,97.20915716477926],[509024.6133965651,6651216.964263236,98.11290457377926],[509024.79668558645,6651215.978219096,97.47435488977925],[509024.6768601193,6651216.622846902,97.92769567177925],[509024.7381592849,6651216.29307438,97.71444333677925],[509032.4840949547,6651229.082029021,91.52147764848303],[509032.5924513005,6651228.482135238,91.52147764848303],[509032.5924513005,6651228.482135238,91.65147764848305],[509032.4840949547,6651229.082029021,93.35028130748304],[509032.59245088475,6651228.48213754,93.35028130848303],[509032.48782060103,6651229.061402706,93.81587199448303],[509032.5932588384,6651228.477664462,93.55410259248303],[509032.49947119365,6651228.996901471,94.29314294648303],[509032.59996761486,6651228.44052263,93.97068188048304],[509032.61395200656,6651228.363100773,94.39500900048303],[509032.5196476314,6651228.885198559,94.77604396648304],[509032.5406314463,6651228.769025758,95.13774995148303],[509032.6356646696,6651228.2428928455,94.82131935148304],[509032.5667357613,6651228.624504308,95.49550779748303],[509032.66536924336,6651228.078439265,95.24312821048304],[509032.5979636944,6651228.451616945,95.84596401248305],[509032.7031015295,6651227.869541819,95.65347775348303],[509032.63422680617,6651228.250853297,96.18570903948304],[509032.74864329817,6651227.617408697,96.04525744748305],[509032.67534202704,6651228.0232268935,96.51137614948303],[509032.78764492896,6651227.401483771,96.32273930748303],[509032.7210326592,6651227.7702696165,96.81974495748304],[509032.8304771764,6651227.164351385,96.58317998048304],[509032.7709336614,6651227.494002446,97.10784330848304],[509032.87677039014,6651226.908058032,96.82414962648303],[509032.8246010793,6651227.19688325,97.37304103348303],[509032.9260926674,6651226.634994861,97.04356863248303],[509032.8815251288,6651226.88173435,97.61312948048304],[509032.99573133385,6651226.249453962,97.29978175548302],[509032.9411461307,6651226.551654297,97.82638181548305],[509033.0686707826,6651225.845638924,97.51205956448302],[509034.76099470054,6651216.476417507,91.52147764848303],[509033.0028722674,6651226.209919576,98.01159071748303],[509034.76099470054,6651216.476417507,91.65147764848305],[509033.14364711975,6651225.430547052,97.67917432148303],[509034.8693510464,6651215.876523727,91.52147764848303],[509033.066098014,6651225.859882557,98.16808200948303],[509033.21942359506,6651225.011025371,97.80132744348303],[509033.13022210647,6651225.504872022,98.29570476848305],[509033.29484755197,6651224.59345534,97.88000213648304],[509033.19466402655,6651225.148101895,98.39480026248305],[509033.3688943351,6651224.183509762,97.91774499548303],[509033.28014451114,6651224.674855858,98.48396491448305],[509034.76099470054,6651216.476417507,93.35028130748304],[509033.3640641989,6651224.210250868,98.52674015548304],[509034.8693510464,6651215.876523727,93.35028130748304],[509034.7577073656,6651216.494617197,93.76109661948303],[509033.6734895281,6651222.497177863,97.91774499548303],[509034.74742743094,6651216.551530052,94.18221804748303],[509034.8656254,6651215.89715004,93.81587199448303],[509034.7296246917,6651216.650091445,94.60830718248303],[509034.85397480737,6651215.961651274,94.29314294648303],[509034.70393557695,6651216.792314221,95.03321368648304],[509034.8337983696,6651216.073354189,94.77604396648304],[509033.98455125,6651220.775045289,97.91774499548303],[509034.6702061745,6651216.979050481,95.45018038848303],[509034.05859803315,6651220.3650997095,97.88000213648304],[509034.8128145547,6651216.189526988,95.13774995148303],[509034.62852541974,6651217.209807852,95.85212930548303],[509034.13402199006,6651219.947529678,97.80132744348303],[509034.57924306527,6651217.482650001,96.23201010748305],[509034.7867102397,6651216.33404844,95.49550779748303],[509034.20979846537,6651219.528007996,97.67917432148303],[509034.53765002603,6651217.712921752,96.49841642248303],[509033.9893818021,6651220.748301878,98.52674015548304],[509034.49246530223,6651217.963078165,96.74612616248305],[509034.2847748025,6651219.112916124,97.51205956448302],[509034.4273529177,6651218.323560188,97.04356863248303],[509034.7554823066,6651216.506935802,95.84596401248305],[509034.35771425127,6651218.7091010865,97.29978175548302],[509034.0733014899,6651220.283696888,98.48396491448305],[509034.7192191949,6651216.707699451,96.18570903948304],[509034.1587819745,6651219.810450851,98.39480026248305],[509034.678103974,6651216.935325854,96.51137614948303],[509034.2232238946,6651219.453680726,98.29570476848305],[509034.63241334184,6651217.1882831305,96.81974495748304],[509034.287347987,6651219.098670189,98.16808200948303],[509034.58251233964,6651217.4645503005,97.10784330848304],[509034.3505737336,6651218.7486331705,98.01159071748303],[509034.52884492173,6651217.761669496,97.37304103348303],[509034.4122998704,6651218.406898449,97.82638181548305],[509034.47192087234,6651218.076818396,97.61312948048304],[510538.3475552979,6651106.192133014,67.73428539412009],[510538.3807739694,6651106.800828477,67.73428539412009],[510538.3807739694,6651106.800828477,67.86428539412009],[510538.3475552979,6651106.192133014,69.5630890531201],[510538.3486974647,6651106.213061959,70.02867974012008],[510538.3807739694,6651106.800828477,69.5630890531201],[510538.3522691726,6651106.278509561,70.5059506921201],[510538.3817817637,6651106.819295193,69.97390436512009],[510538.3849332706,6651106.877043078,70.39502579312008],[510538.3584546382,6651106.391851387,70.9888517121201],[510538.3903910344,6651106.977050571,70.8211149281201],[510538.36488762056,6651106.509728681,71.35055769712011],[510538.37289038824,6651106.65637056,71.70831554312011],[510538.3982665147,6651107.121360049,71.24602143212009],[510538.38246389723,6651106.831794538,72.05877175812009],[510538.4086068961,6651107.310836116,71.66298813412008],[510538.3935810348,6651107.035503805,72.3985167851201],[510538.42138491385,6651107.544979176,72.0649370511201],[510538.40618567745,6651107.266469957,72.72418389512009],[510538.4364933446,6651107.82182448,72.44481785312009],[510538.4201929983,6651107.52313864,73.0325527031201],[510538.4492444714,6651108.055474795,72.71122416812008],[510538.43549108715,6651107.80345922,73.32065105412009],[510538.4630966966,6651108.30930152,72.95893390812009],[510538.4519438414,6651108.104937769,73.58584877912008],[510538.4830581202,6651108.675072559,73.2563763781201],[510538.4693949772,6651108.424710556,73.82593722612009],[510538.5044071604,6651109.066270138,73.51258950112009],[510538.48767291434,6651108.759633563,74.0391895611201],[510538.52676811744,6651109.476009977,73.72486731012009],[510538.50659622013,6651109.10638224,74.2243984631201],[510538.5497535208,6651109.897192105,73.8919820671201],[510538.5259792594,6651109.461555026,74.3808897551201],[510538.54563770344,6651109.821774298,74.50851251412008],[510538.57298422157,6651110.322869036,74.0141351891201],[510538.5653935836,6651110.18377898,74.6076080081201],[510538.59610685124,6651110.746565684,74.0928098821201],[510538.61880728236,6651111.16252601,74.13055274112008],[510538.5915992306,6651110.663968514,74.69677266012009],[510538.6173263859,6651111.135390218,74.7395479011201],[510539.0455816504,6651118.982694897,67.73428539412009],[510538.71416909155,6651112.909925829,74.13055274112008],[510539.0455816504,6651118.982694897,67.86428539412009],[510539.0788003219,6651119.59139036,67.73428539412009],[510539.0455817779,6651118.982697234,69.56308905412008],[510538.8075484649,6651114.6209997,74.13055274112008],[510539.0453340844,6651118.978158525,69.76691033812008],[510538.83024889615,6651115.036960028,74.0928098821201],[510539.0432773831,6651118.940471746,70.18348962612009],[510539.0788003219,6651119.59139036,69.5630890531201],[510538.8090292339,6651114.648133156,74.7395479011201],[510538.8533715257,6651115.4606566755,74.0141351891201],[510539.0389902054,6651118.861913948,70.6078167461201],[510539.07765815506,6651119.570461417,70.02867974012008],[510538.8766022266,6651115.886333606,73.8919820671201],[510538.83475638926,6651115.119554861,74.69677266012009],[510539.03233378095,6651118.739942323,71.03412709712009],[510538.8995876299,6651116.307515735,73.72486731012009],[510539.02322728635,6651118.573075869,71.45593595612009],[510539.07408644725,6651119.505013815,70.5059506921201],[510538.86096203624,6651115.599744395,74.6076080081201],[510538.92194858694,6651116.717255572,73.51258950112009],[510539.0116597458,6651118.361113467,71.8662854991201],[510538.9432976272,6651117.108453153,73.2563763781201],[510538.99769806187,6651118.105281029,72.25806519312009],[510538.8807179163,6651115.961749077,74.50851251412008],[510538.95841829706,6651117.385522725,73.03695737212009],[510538.98574137996,6651117.88618804,72.5355470531201],[510538.97261035064,6651117.6455764305,72.79598772612009],[510539.06790098164,6651119.391671988,70.9888517121201],[510538.90037636046,6651116.321968349,74.3808897551201],[510539.0614679993,6651119.273794693,71.35055769712011],[510538.9197593997,6651116.677141135,74.2243984631201],[510539.05346523155,6651119.1271528145,71.70831554312011],[510538.9386827055,6651117.023889812,74.0391895611201],[510539.0438917225,6651118.951728838,72.05877175812009],[510538.95696064265,6651117.358812819,73.82593722612009],[510539.032774585,6651118.7480195705,72.3985167851201],[510538.9744117784,6651117.678585607,73.58584877912008],[510539.0201699424,6651118.517053418,72.72418389512009],[510538.9908645327,6651117.9800641555,73.32065105412009],[510539.00616262155,6651118.260384735,73.0325527031201],[510541.804904192,6651106.006721421,67.77395593323926],[510541.83697537443,6651106.6154784225,67.77395593323926],[510541.83697537443,6651106.6154784225,67.90395593323927],[510541.804904192,6651106.006721421,69.60275959223927],[510541.80600690434,6651106.0276524825,70.06835027923925],[510541.83697537443,6651106.6154784225,69.60275959223927],[510541.8094552329,6651106.0931067,70.54562123123927],[510541.837948356,6651106.6339470055,70.01357490423926],[510541.8409909988,6651106.691700729,70.43469633223926],[510541.81542703096,6651106.206459986,71.02852225123927],[510541.8462602324,6651106.791718332,70.86078546723928],[510541.82163779554,6651106.324349198,71.39022823623927],[510541.82936411974,6651106.471005901,71.74798608223927],[510541.85386366607,6651106.936042399,71.28569197123926],[510541.83860692626,6651106.646447614,72.09844229723927],[510541.86384685454,6651107.125537623,71.70265867323926],[510541.849340039,6651106.850177474,72.43818732423927],[510541.87618347484,6651107.359704352,72.10460759023925],[510541.8615092733,6651107.081166978,72.76385443423926],[510541.8907700076,6651107.636577646,72.48448839223927],[510541.8750327323,6651107.33786161,73.07222324223926],[510541.9030806659,6651107.870251583,72.75089470723927],[510541.8898023716,6651107.61821053,73.36032159323926],[510541.91645438684,6651108.124103969,72.99860444723927],[510541.9056867903,6651107.919719556,73.62551931823926],[510541.9357262731,6651108.4899119865,73.29604691723927],[510541.9225351029,6651108.239524672,73.86560776523926],[510541.95633784286,6651108.881149115,73.55226004023926],[510541.9401816561,6651108.574481541,74.07886010023927],[510541.9779263743,6651109.290930377,73.76453784923926],[510541.95845128474,6651108.921265272,74.26406900223927],[510542.00011778146,6651109.712155086,73.93165260623927],[510541.9771647662,6651109.276473965,74.42056029423928],[510541.99614413886,6651109.636729655,74.54818305323927],[510542.0225460126,6651110.137875052,74.05380572823927],[510542.0152175819,6651109.9987709345,74.64727854723927],[510542.0448699058,6651110.561614534,74.13248042123926],[510542.06678618473,6651110.977616914,74.17022328023926],[510542.04051799414,6651110.4790090155,74.73644319923926],[510542.06535644364,6651110.950478381,74.77921844023926],[510542.47881827434,6651118.798576403,67.77395593323926],[510542.1588538637,6651112.725193391,74.17022328023926],[510542.47881827434,6651118.798576403,67.90395593323927],[510542.51088945684,6651119.407333405,67.77395593323926],[510542.47881839745,6651118.798578739,69.60275959323926],[510542.24900758715,6651114.436440249,74.17022328023926],[510542.4785792602,6651118.794039574,69.80658087723926],[510542.27092386613,6651114.852442629,74.13248042123926],[510542.4765936046,6651118.756348984,70.22316016523926],[510542.51088945684,6651119.407333405,69.60275959223927],[510542.25043720513,6651114.463576447,74.77921844023926],[510542.2932477593,6651115.276182111,74.05380572823927],[510542.47245452093,6651118.677783244,70.64748728523927],[510542.50978674454,6651119.386402345,70.06835027923925],[510542.3156759904,6651115.7019020775,73.93165260623927],[510542.2752756546,6651114.935045811,74.73644319923926],[510542.4660280327,6651118.55579929,71.07379763623926],[510542.33786739764,6651116.123126786,73.76453784923926],[510542.45723610825,6651118.388915964,71.49560649523926],[510542.50633841596,6651119.320948128,70.54562123123927],[510542.300576067,6651115.415283892,74.64727854723927],[510542.359455929,6651116.532908048,73.55226004023926],[510542.4460681509,6651118.176932132,71.90595603823928],[510542.3800674989,6651116.924145179,73.29604691723927],[510542.4325887524,6651117.921073833,72.29773573223926],[510542.3946658478,6651117.201242763,73.07662791123926],[510542.3196495099,6651115.777325171,74.54818305323927],[510542.42104509607,6651117.701958692,72.57521759223926],[510542.5003666178,6651119.207594842,71.02852225123927],[510542.40836765827,6651117.461322758,72.83565826523926],[510542.3386288826,6651116.137580863,74.42056029423928],[510542.4941558532,6651119.089705629,71.39022823623927],[510542.35734236403,6651116.492789555,74.26406900223927],[510542.48642952903,6651118.943048925,71.74798608223927],[510542.37561199267,6651116.8395732865,74.07886010023927],[510542.4771867225,6651118.767607212,72.09844229723927],[510542.393258546,6651117.174530156,73.86560776523926],[510542.46645360976,6651118.5638773525,72.43818732423927],[510542.4101068586,6651117.494335271,73.62551931823926],[510542.4542843756,6651118.332887848,72.76385443423926],[510542.42599127715,6651117.795844297,73.36032159323926],[510542.44076091656,6651118.076193218,73.07222324223926],[510545.0497702439,6651105.838649935,67.8111848015487],[510545.0807644602,6651106.447462719,67.8111848015487],[510545.0807644602,6651106.447462719,67.94118480154869],[510545.0497702439,6651105.838649935,69.6399884605487],[510545.05083592667,6651105.859582913,70.10557914754868],[510545.0807644602,6651106.447462719,69.6399884605487],[510545.0541684587,6651105.925043128,70.58285009954871],[510545.0817047684,6651106.465932993,70.05080377254869],[510545.08464523783,6651106.523692008,70.4719252005487],[510545.0599397207,6651106.038406801,71.0657511195487],[510545.08973752795,6651106.623718777,70.8980143355487],[510545.0659419248,6651106.156306815,71.4274571045487],[510545.0734087951,6651106.302976958,71.78521495054869],[510545.09708563454,6651106.768056069,71.32292083954869],[510545.08234122366,6651106.478434748,72.13567116554869],[510545.1067335826,6651106.957568655,71.7398875415487],[510545.09271391307,6651106.682183276,72.47541619254869],[510545.11865593295,6651107.191756844,72.14183645854868],[510545.10447449837,6651106.913193947,72.80108330254869],[510545.1327526427,6651107.468655508,72.52171726054868],[510545.117543833,6651107.169912099,73.10945211054869],[510545.14464990306,6651107.702350857,72.78812357554871],[510545.1318175005,6651107.450286709,73.3975504615487],[510545.15757452766,6651107.956226505,73.03583331554869],[510545.1471685124,6651107.751823364,73.66274818654868],[510545.17619925446,6651108.322068042,73.3332757855487],[510545.16345105023,6651108.071657784,73.90283663354869],[510545.19611867744,6651108.713341023,73.58948890854869],[510545.1805050235,6651108.406645346,74.1160889685487],[510545.2169822552,6651109.123159834,73.8017667175487],[510545.1981611489,6651108.753460854,74.30129787054871],[510545.23842846387,6651109.5444231415,73.9688814745487],[510545.2162462223,6651109.108702098,74.45778916254869],[510545.2345882582,6651109.468990799,74.58541192154868],[510545.2601035439,6651109.970182119,74.0910345965487],[510545.2530212054,6651109.831065253,74.6845074155487],[510545.28167778964,6651110.393960429,74.1697092895487],[510545.30285810895,6651110.810000929,74.2074521485487],[510545.27747201733,6651110.311347341,74.77367206754869],[510545.30147637933,6651110.7828599075,74.81644730854869],[510545.70105395577,6651118.631677083,67.8111848015487],[510545.70105395577,6651118.631677083,67.94118480154869],[510545.39183410944,6651112.557737542,74.2074521485487],[510545.73204817204,6651119.240489867,67.8111848015487],[510545.7010540747,6651118.631679418,69.63998846154868],[510545.4789604259,6651114.269141209,74.2074521485487],[510545.70082296786,6651118.627139836,69.84380974554868],[510545.5001407453,6651114.685181708,74.1697092895487],[510545.69890399143,6651118.589445793,70.26038903354869],[510545.73204817204,6651119.240489867,69.6399884605487],[510545.4803420366,6651114.296279894,74.81644730854869],[510545.521714991,6651115.1089600185,74.0910345965487],[510545.6949039004,6651118.510872854,70.68471615354869],[510545.73098248924,6651119.219556888,70.10557914754868],[510545.54339007096,6651115.534718996,73.9688814745487],[510545.5043463986,6651114.7677924605,74.77367206754869],[510545.6886932168,6651118.388877721,71.11102650454869],[510545.5648362797,6651115.955982302,73.8017667175487],[510545.7276499573,6651119.154096671,70.58285009954871],[510545.6801965295,6651118.221979103,71.53283536354868],[510545.5287972104,6651115.248074547,74.6845074155487],[510545.58569985745,6651116.365801115,73.58948890854869],[510545.6694035978,6651118.009975847,71.9431849065487],[510545.6056192805,6651116.757074094,73.3332757855487],[510545.65637684416,6651117.754094101,72.33496460054869],[510545.7218786951,6651119.040732999,71.0657511195487],[510545.6197274097,6651117.03419707,73.1138567795487],[510545.6452208295,6651117.534958883,72.61244646054868],[510545.54723015777,6651115.610149001,74.58541192154868],[510545.6329691065,6651117.294300898,72.87288713354869],[510545.7158764911,6651118.9228329845,71.4274571045487],[510545.56557219365,6651115.970437704,74.45778916254869],[510545.7084096208,6651118.776162843,71.78521495054869],[510545.58365726704,6651116.325678945,74.30129787054871],[510545.69947719225,6651118.600705054,72.13567116554869],[510545.6013133924,6651116.672494453,74.1160889685487],[510545.6891045028,6651118.396956524,72.47541619254869],[510545.6183673657,6651117.0074820155,73.90283663354869],[510545.6773439175,6651118.165945854,72.80108330254869],[510545.6346499035,6651117.327316436,73.66274818654868],[510545.664274583,6651117.9092277,73.10945211054869],[510545.65000091546,6651117.628853091,73.3975504615487],[510548.45917139295,6651105.66825618,67.85029779767426],[510548.48903403396,6651106.277125518,67.85029779767426],[510548.48903403396,6651106.277125518,67.98029779767425],[510548.45917139295,6651105.66825618,69.67910145667426],[510548.4601981684,6651105.689191103,70.14469214367426],[510548.48903403396,6651106.277125518,69.67910145667426],[510548.46340903227,6651105.754657399,70.62196309567426],[510548.4899400123,6651106.295597508,70.08991676867427],[510548.4927731274,6651106.353361887,70.51103819667425],[510548.4689695899,6651105.868031602,71.10486411567426],[510548.49767950195,6651106.453397949,70.93712733167426],[510548.4747526581,6651105.985942568,71.46657010067428],[510548.4819469187,6651106.132626335,71.82432794667427],[510548.50475933467,6651106.597748647,71.36203383567425],[510548.490553231,6651106.308100423,72.17478416167425],[510548.51405504346,6651106.787278838,71.77900053767425],[510548.5005472215,6651106.511867878,72.51452918867426],[510548.525542118,6651107.02148878,72.18094945467426],[510548.5118784368,6651106.742900008,72.84019629867427],[510548.5391241676,6651107.298413167,72.56083025667425],[510548.5244706198,6651106.999642007,73.14856510667427],[510548.5505870679,6651107.532130225,72.82723657167426],[510548.5382231666,6651107.28004266,73.43666345767426],[510548.5630398244,6651107.786029454,73.07494631167425],[510548.55301372486,6651107.581607326,73.70186118267425],[510548.58098457655,6651108.151904975,73.37238878167427],[510548.5687017996,6651107.9014714565,73.94194962967426],[510548.6001767565,6651108.543214302,73.62860190467426],[510548.5851331453,6651108.236490136,74.15520196467426],[510548.62027862103,6651108.953071182,73.84087971367425],[510548.602144659,6651108.58333786,74.34041086667426],[510548.64094184496,6651109.374373621,74.00799447067426],[510548.61956946005,6651108.938612102,74.49690215867426],[510548.6372418422,6651109.298934272,74.62452491767425],[510548.66182558425,6651109.800172147,74.13014759267426],[510548.6550018166,6651109.661042361,74.72362041167426],[510548.68261217064,6651110.223989824,74.20882228567426],[510548.70301921276,6651110.64006897,74.24656514467425],[510548.6785599479,6651110.14136906,74.81278506367426],[510548.701687929,6651110.612925427,74.85556030467427],[510549.0866772323,6651118.462471688,67.85029779767426],[510549.0866772323,6651118.462471688,67.98029779767425],[510548.78874676715,6651112.387967932,74.24656514467425],[510549.11653987324,6651119.071341026,67.85029779767426],[510549.08667734684,6651118.462474025,69.67910145767426],[510548.87269216817,6651114.099530574,74.24656514467425],[510549.0864546775,6651118.457934021,69.88292274167425],[510548.89309921017,6651114.51560972,74.20882228567426],[510549.08460576157,6651118.420236477,70.29950202967426],[510549.11653987324,6651119.071341026,69.67910145667426],[510548.87402333727,6651114.126671779,74.85556030467427],[510548.91388579656,6651114.939427396,74.13014759267426],[510549.08075171075,6651118.341656239,70.72382914967427],[510549.1155130978,6651119.050406102,70.14469214367426],[510548.93476953596,6651115.365225922,74.00799447067426],[510549.07476777444,6651118.219649774,71.15013950067426],[510548.89715131826,6651114.598228146,74.81278506367426],[510549.112302234,6651118.984939807,70.62196309567426],[510548.9554327599,6651115.78652836,73.84087971367425],[510549.06658129476,6651118.052735654,71.57194835967425],[510548.9207094496,6651115.078554845,74.72362041167426],[510548.9755346243,6651116.19638524,73.62860190467426],[510549.0561824048,6651117.840712703,71.98229790267426],[510548.9947268044,6651116.587694567,73.37238878167427],[510549.043631248,6651117.584807188,72.37407759667425],[510549.1067416763,6651118.871565604,71.10486411567426],[510549.0083198565,6651116.864843285,73.15296977567425],[510549.032882531,6651117.365651615,72.65155945667426],[510549.021078109,6651117.124971275,72.91200012967427],[510548.93846942397,6651115.4406629335,74.62452491767425],[510549.1009586081,6651118.753654637,71.46657010067428],[510548.95614180615,6651115.8009851035,74.49690215867426],[510549.0937643476,6651118.606970871,71.82432794667427],[510548.9735666072,6651116.156259344,74.34041086667426],[510549.0851580352,6651118.431496782,72.17478416167425],[510548.99057812104,6651116.50310707,74.15520196467426],[510549.0751640447,6651118.227729328,72.51452918867426],[510549.00700946664,6651116.838125749,73.94194962967426],[510549.0638328294,6651117.996697198,72.84019629867427],[510549.02269754146,6651117.157989879,73.70186118267425],[510549.0512406464,6651117.739955198,73.14856510667427],[510549.0374880996,6651117.459554546,73.43666345767426],[510558.6812516685,6651105.195443709,67.96754571538673],[510558.707721616,6651105.804469973,67.96754571538673],[510558.707721616,6651105.804469973,68.09754571538674],[510558.6812516685,6651105.195443709,69.79634937438674],[510558.682161792,6651105.216384027,70.26194006138672],[510558.707721616,6651105.804469973,69.79634937438674],[510558.70852466614,6651105.822946724,70.20716468638673],[510558.6850078697,6651105.281867197,70.73921101338674],[510558.7110359112,6651105.880725991,70.62828611438673],[510558.68993669265,6651105.39527062,71.22211203338674],[510558.71538487263,6651105.980787834,71.05437524938675],[510558.69506274664,6651105.513211976,71.58381801838674],[510558.721660366,6651106.125175738,71.47928175338673],[510558.70143966755,6651105.6599335475,71.94157586438673],[510558.70906821714,6651105.835452861,72.29203207938674],[510558.7298999896,6651106.314754777,71.89624845538673],[510558.71792679076,6651106.039272834,72.63177710638674],[510558.740082018,6651106.549025084,72.29819737238674],[510558.7279706671,6651106.270364508,72.95744421638673],[510558.7521210115,6651106.8260208415,72.67807817438674],[510558.7391322528,6651106.527172679,73.26581302438673],[510558.7622816122,6651107.0597981345,72.94448448938672],[510558.7513223732,6651106.8076456,73.55391137538673],[510558.7733196115,6651107.3137628045,73.19219422938673],[510558.76443257666,6651107.109287989,73.81910910038673],[510558.78922566114,6651107.679732623,73.48963669938674],[510558.7783383299,6651107.42923456,74.05919754738673],[510558.8062374183,6651108.071142804,73.74584982238673],[510558.792902911,6651107.764339584,74.27244988238674],[510558.82405551075,6651108.481105316,73.95812763138673],[510558.8079817474,6651108.111276703,74.45765878438674],[510558.84237118665,6651108.902516339,74.12524238838674],[510558.8234269176,6651108.46664251,74.61415007638675],[510558.8608823251,6651109.328424607,74.24739551038674],[510558.839091541,6651108.827057547,74.74177283538674],[510558.85483380547,6651109.189258963,74.84086832938674],[510558.8793073483,6651109.752351516,74.32607020338673],[510558.8973959472,6651110.168537899,74.36381306238673],[510558.87571549846,6651109.669709458,74.93003298138673],[510558.89621591044,6651110.141387361,74.97280822238673],[510559.23746659444,6651117.99295671,67.96754571538673],[510559.23746659444,6651117.99295671,68.09754571538674],[510558.97338399757,6651111.916887354,74.36381306238673],[510559.263936542,6651118.6019829735,67.96754571538673],[510559.237466696,6651117.992959048,69.79634937538673],[510559.23726932413,6651117.988417874,70.00017065938673],[510559.0477923649,6651113.628891122,74.36381306238673],[510559.23563046346,6651117.950710612,70.41674994738673],[510559.263936542,6651118.6019829735,69.79634937438674],[510559.06588096364,6651114.045077505,74.32607020338673],[510559.2322142711,6651117.872110123,70.84107706738673],[510559.0489722999,6651113.656039322,74.97280822238673],[510559.2630264184,6651118.581042654,70.26194006138672],[510559.0843059868,6651114.469004412,74.24739551038674],[510559.22691016964,6651117.750072213,71.26738741838673],[510559.10281712544,6651114.894912682,74.12524238838674],[510559.06947271194,6651114.127717225,74.93003298138673],[510559.2601803408,6651118.515559485,70.73921101338674],[510559.2196537556,6651117.583115072,71.68919627738673],[510559.1211328013,6651115.316323703,73.95812763138673],[510559.21043628315,6651117.371037477,72.09954582038675],[510559.1389508937,6651115.726286217,73.74584982238673],[510559.09035440494,6651114.60816772,74.84086832938674],[510559.2552515178,6651118.402156062,71.22211203338674],[510559.19931106275,6651117.115066006,72.49132551438674],[510559.1559626509,6651116.117696397,73.48963669938674],[510559.18978350697,6651116.89585395,72.76880737438674],[510559.168011397,6651116.394916545,73.27021769338673],[510559.1793201849,6651116.655111578,73.02924804738673],[510559.10609666933,6651114.970369136,74.74177283538674],[510559.2501254637,6651118.284214707,71.58381801838674],[510559.12176129286,6651115.330784173,74.61415007638675],[510559.2437485428,6651118.1374931345,71.94157586438673],[510559.13720646297,6651115.686149979,74.45765878438674],[510559.2361199933,6651117.961973821,72.29203207938674],[510559.1522852993,6651116.033087098,74.27244988238674],[510559.2272614197,6651117.758153848,72.63177710638674],[510559.16684988054,6651116.368192124,74.05919754738673],[510559.21721754334,6651117.527062175,72.95744421638673],[510559.1807556337,6651116.688138693,73.81910910038673],[510559.20605595765,6651117.270254004,73.26581302438673],[510559.1938658371,6651116.989781082,73.55391137538673],[510562.25216679554,6651105.043722797,68.00849746456501],[510562.2774515616,6651105.652799416,68.00849746456501],[510562.2774515616,6651105.652799416,68.138497464565],[510562.25216679554,6651105.043722797,69.83730112356503],[510562.2530361687,6651105.064664846,70.302891810565],[510562.2774515616,6651105.652799416,69.83730112356503],[510562.2782186556,6651105.671277695,70.24811643556501],[510562.25575481437,6651105.13015343,70.78016276256501],[510562.28061746055,6651105.7290617395,70.669237863565],[510562.2604629512,6651105.24356623,71.26306378256501],[510562.284771699,6651105.829131857,71.09532699856501],[510562.2653594882,6651105.361517337,71.62476976756501],[510562.29076620954,6651105.973531698,71.52023350256502],[510562.27145088505,6651105.50825104,71.98252761356501],[510562.2787378692,6651105.683784867,72.332983828565],[510562.2986369073,6651106.163126413,71.937200204565],[510562.28719980374,6651105.887621691,72.67272885556503],[510562.3083630394,6651106.397416089,72.33914912156501],[510562.29679396946,6651106.118732473,72.99839596556501],[510562.31986299163,6651106.67443475,72.719029923565],[510562.3074557995,6651106.375561878,73.306764773565],[510562.3295686555,6651106.908231372,72.98543623856501],[510562.3191001122,6651106.65605799,73.59486312456501],[510562.3401124328,6651107.162217041,73.233145978565],[510562.33162331133,6651106.957725319,73.860060849565],[510562.35530629515,6651107.528217118,73.53058844856501],[510562.34490644,6651107.277698344,74.10014929656501],[510562.3715563576,6651107.919659661,73.78680157156501],[510562.35881889774,6651107.612831075,74.31340163156503],[510562.388576652,6651108.329656073,73.99907938056501],[510562.3732225851,6651107.959796879,74.49861053356501],[510562.4060722507,6651108.751101937,74.16619413756501],[510562.38797620387,6651108.31519207,74.65510182556501],[510562.4237545603,6651109.177045421,74.28834725956501],[510562.40293945,6651108.675636907,74.782724584565],[510562.41797686066,6651109.037868269,74.88182007856503],[510562.44135461026,6651109.601007381,74.36702195256501],[510562.45863329916,6651110.017228177,74.404764811565],[510562.437923584,6651109.518358491,74.97098473056502],[510562.4575060982,6651109.990075394,75.01375997156501],[510562.783477417,6651117.842293931,68.00849746456501],[510562.783477417,6651117.842293931,68.138497464565],[510562.808762183,6651118.451370551,68.00849746456501],[510562.5312190145,6651111.765722188,74.404764811565],[510562.783477514,6651117.842296268,69.837301124565],[510562.7832889794,6651117.837754719,70.04112240856502],[510562.6022957765,6651113.47786751,74.404764811565],[510562.808762183,6651118.451370551,69.83730112356503],[510562.78172349796,6651117.80004434,70.45770169656501],[510562.6195744654,6651113.894088304,74.36702195256501],[510562.7784602643,6651117.721437353,70.88202881656501],[510562.8078928099,6651118.4304285,70.302891810565],[510562.6034228804,6651113.505017955,75.01375997156501],[510562.63717451534,6651114.318050263,74.28834725956501],[510562.773393652,6651117.59938935,71.30833916756502],[510562.654856825,6651114.743993747,74.16619413756501],[510562.80517416424,6651118.364939917,70.78016276256501],[510562.6230053946,6651113.976734857,74.97098473056502],[510562.76646214095,6651117.432418406,71.73014802656502],[510562.6723524237,6651115.165439613,73.99907938056501],[510562.75765737717,6651117.220323276,72.14049756956501],[510562.689372718,6651115.575436023,73.78680157156501],[510562.8004660274,6651118.2515271185,71.26306378256501],[510562.64295211795,6651114.457225078,74.88182007856503],[510562.74703028414,6651116.964330641,72.53227726356502],[510562.70562278054,6651115.966878566,73.53058844856501],[510562.737929321,6651116.745100459,72.80975912356502],[510562.7171320486,6651116.244121635,73.311169442565],[510562.72793449013,6651116.504338183,73.070199796565],[510562.79556949035,6651118.133576009,71.62476976756501],[510562.65798952867,6651114.819456441,74.782724584565],[510562.78947809356,6651117.986842307,71.98252761356501],[510562.67295277474,6651115.179901279,74.65510182556501],[510562.7821911093,6651117.811308481,72.332983828565],[510562.68770639354,6651115.535296467,74.49861053356501],[510562.7737291749,6651117.607471656,72.67272885556503],[510562.7021100809,6651115.882262272,74.31340163156503],[510562.7160225386,6651116.217395004,74.10014929656501],[510562.76413500914,6651117.376360874,72.99839596556501],[510562.7293056672,6651116.5373680275,73.860060849565],[510562.75347317907,6651117.11953147,73.306764773565],[510562.7418288664,6651116.839035358,73.59486312456501],[510568.6902991316,6651104.7877660515,68.0823226047824],[510568.71344709094,6651105.396927622,68.0823226047824],[510568.71344709094,6651105.396927622,68.2123226047824],[510568.6902991316,6651104.7877660515,69.9111262637824],[510568.69109503424,6651104.808711022,70.37671695078241],[510568.71344709094,6651105.396927622,69.9111262637824],[510568.714149358,6651105.415408478,70.32194157578242],[510568.6935839281,6651104.874208739,70.8539879027824],[510568.7163454409,6651105.473200583,70.7430630037824],[510568.69789418206,6651104.987637357,71.3368889227824],[510568.72014860605,6651105.573284656,71.16915213878241],[510568.7023769143,6651105.105604916,71.69859490778242],[510568.7256365227,6651105.717704638,71.5940586427824],[510568.7079535294,6651105.252359086,72.0563527537824],[510568.71462469315,6651105.427917394,72.4068089687824],[510568.7328420705,6651105.907325796,72.0110253447824],[510568.72237151256,6651105.631782649,72.7465539957824],[510568.74174625066,6651106.14164815,72.41297426178241],[510568.7311548786,6651105.862925665,73.07222110578242],[510568.7522743459,6651106.41870545,72.7928550637824],[510568.7409156812,6651106.119790891,73.3805899137824],[510568.7611597876,6651106.65253468,73.0592613787824],[510568.7515759371,6651106.400326126,73.6686882647824],[510568.77081251383,6651106.906555775,73.3069711187824],[510568.7630408052,6651106.7020355305,73.93388598978241],[510568.7847223483,6651107.2726069,73.60441358878242],[510568.77520138124,6651107.022053183,74.17397443678242],[510568.7995991237,6651107.66410404,73.86062671178242],[510568.7879381021,6651107.357232659,74.38722677178241],[510568.815181039,6651108.074157636,74.0729045207824],[510568.80112453894,6651107.704246856,74.57243567378241],[510568.83119809086,6651108.495662283,74.24001927778241],[510568.8146313345,6651108.0596916145,74.7289269657824],[510568.84738607466,6651108.921665175,74.36217239978242],[510568.828330042,6651108.420186726,74.8565497247824],[510568.84209664643,6651108.782468611,74.95564521878241],[510568.8634987506,6651109.345686267,74.4408470927824],[510568.8793172237,6651109.761965115,74.4785899517824],[510568.8603576792,6651109.263025849,75.0448098707824],[510568.87828528194,6651109.734808546,75.0875851117824],[510569.1767088793,6651117.58812228,68.0823226047824],[510569.1767088793,6651117.58812228,68.2123226047824],[510569.19985683874,6651118.197283852,68.0823226047824],[510568.94576874573,6651111.510703002,74.4785899517824],[510569.1767089682,6651117.588124618,69.91112626478241],[510569.1765363666,6651117.583582436,70.1149475487824],[510569.01083883556,6651113.223087125,74.4785899517824],[510569.19985683874,6651118.197283852,69.9111262637824],[510569.1751031835,6651117.545866797,70.5315268367824],[510569.0266573085,6651113.639365973,74.4408470927824],[510569.1721157246,6651117.467248845,70.95585395678242],[510569.199060936,6651118.17633888,70.37671695078241],[510569.0118706883,6651113.250241357,75.0875851117824],[510569.04276998446,6651114.063387065,74.36217239978242],[510569.1674772898,6651117.34518382,71.3821643077824],[510569.1965720421,6651118.110841163,70.8539879027824],[510569.05895796826,6651114.489389959,74.24001927778241],[510569.16113155836,6651117.178189588,71.8039731667824],[510569.02979829104,6651113.722024052,75.0448098707824],[510569.07497502014,6651114.910894604,74.0729045207824],[510569.1530708821,6651116.966064875,72.21432270978241],[510569.1922617883,6651117.997412547,71.3368889227824],[510569.09055693535,6651115.3209482,73.86062671178242],[510569.14334188093,6651116.710036535,72.6061024037824],[510569.0480593238,6651114.202581291,74.95564521878241],[510569.135010037,6651116.490775776,72.88358426378241],[510569.1054337108,6651115.71244534,73.60441358878242],[510569.1258598657,6651116.249979919,73.14402493678242],[510569.11597033474,6651115.989727079,73.3849945827824],[510569.1877790559,6651117.879444987,71.69859490778242],[510569.06182592834,6651114.564863176,74.8565497247824],[510569.18220244086,6651117.732690817,72.0563527537824],[510569.07552463573,6651114.925358287,74.7289269657824],[510569.1755312772,6651117.557132508,72.4068089687824],[510569.0890314314,6651115.280803045,74.57243567378241],[510569.1677844578,6651117.353267252,72.7465539957824],[510569.10221786815,6651115.627817243,74.38722677178241],[510569.1590010916,6651117.122124237,73.07222110578242],[510569.114954589,6651115.9629967185,74.17397443678242],[510569.14924028906,6651116.86525901,73.3805899137824],[510569.12711516506,6651116.283014371,73.93388598978241],[510569.13858003315,6651116.584723776,73.6686882647824],[510575.56434793817,6651104.539443691,68.16113549753591],[510575.5852144108,6651105.148687679,68.16113549753591],[510575.5852144108,6651105.148687679,68.2911354975359],[510575.56434793817,6651104.539443691,69.98993915653591],[510575.56506539584,6651104.560391497,70.4555298435359],[510575.5852144108,6651105.148687679,69.98993915653591],[510575.5858474617,6651105.167171037,70.40075446853591],[510575.56730898184,6651104.625898075,70.93280079553591],[510575.5878270964,6651105.22497096,70.8218758965359],[510575.57119441265,6651104.739342039,71.41570181553591],[510575.5912554177,6651105.325068575,71.24796503153591],[510575.57523532223,6651104.8573255595,71.77740780053593],[510575.5962024395,6651105.469508097,71.6728715355359],[510575.5802623003,6651105.004099584,72.13516564653592],[510575.5862759473,6651105.179681645,72.4856218615359],[510575.60269780125,6651105.65915491,72.0898382375359],[510575.5932592322,6651105.383574483,72.82536688853591],[510575.6107243761,6651105.893508967,72.4917871545359],[510575.6011769008,6651105.614748772,73.15103399853591],[510575.6202148115,6651106.170603752,72.8716679565359],[510575.60997566854,6651105.871648751,73.45940280653592],[510575.62822449487,6651106.40446462,73.13807427153591],[510575.6195852386,6651106.152221941,73.74750115753591],[510575.6369258386,6651106.65852008,73.3857840115359],[510575.6299201175,6651106.453972166,74.0126988825359],[510575.6494647054,6651107.024620732,73.68322648153591],[510575.64088213467,6651106.774033116,74.2527873295359],[510575.6628752105,6651107.416170841,73.9394396045359],[510575.6523635112,6651107.10925794,74.46603966453591],[510575.6769213561,6651107.826279915,74.1517174135359],[510575.66425027914,6651107.456319088,74.65124856653591],[510575.69135975087,6651108.247841591,74.31883217053591],[510575.67642583116,6651107.811811938,74.80773985853591],[510575.7059522304,6651108.67390212,74.44098529253591],[510575.68877437984,6651108.172355822,74.9353626175359],[510575.7204768243,6651109.097980581,74.51965998553591],[510575.70118413365,6651108.534686725,75.03445811153591],[510575.73473621235,6651109.51431575,74.5574028445359],[510575.7176453402,6651109.01530898,75.1236227635359],[510575.73380597995,6651109.487155505,75.16639800453592],[510576.0028166402,6651117.341531774,68.16113549753591],[510576.0028166402,6651117.341531774,68.2911354975359],[510576.02368311293,6651117.950775762,68.16113549753591],[510575.7946382039,6651111.263290236,74.5574028445359],[510576.00281672034,6651117.341534112,69.9899391575359],[510576.00266113045,6651117.336991314,70.1937604415359],[510576.02368311293,6651117.950775762,69.98993915653591],[510576.0013692033,6651117.299270572,70.61033972953591],[510575.8532949188,6651112.9759060405,74.5574028445359],[510575.99867619155,6651117.220641984,71.03466684953591],[510575.86755430675,6651113.39224121,74.51965998553591],[510576.02296565514,6651117.9298279565,70.4555298435359],[510575.9944949256,6651117.098560444,71.46097720053591],[510575.8542250711,6651113.003063948,75.16639800453592],[510575.88207890076,6651113.816319671,74.44098529253591],[510576.0207220692,6651117.864321377,70.93280079553591],[510575.988774636,6651116.9315436175,71.8827860595359],[510575.89667138027,6651114.242380201,74.31883217053591],[510575.87038571085,6651113.474910473,75.1236227635359],[510575.9815084283,6651116.719390206,72.29313560253591],[510575.9111097749,6651114.663941877,74.1517174135359],[510576.0168366384,6651117.750877414,71.41570181553591],[510575.9727383275,6651116.463327226,72.6849152965359],[510575.9251559206,6651115.074050951,73.9394396045359],[510575.9652276787,6651116.244036801,72.96239715653591],[510575.8868469174,6651113.955532729,75.03445811153591],[510575.93856642576,6651115.46560106,73.68322648153591],[510575.95697935775,6651116.003208364,73.2228378295359],[510575.9480645492,6651115.742920312,73.4638074755359],[510576.0127957288,6651117.632893895,71.77740780053593],[510575.8992566711,6651114.31786363,74.9353626175359],[510576.0077687507,6651117.486119869,72.13516564653592],[510575.9116052199,6651114.6784075145,74.80773985853591],[510576.0017551037,6651117.310537808,72.4856218615359],[510575.92378077185,6651115.033900364,74.65124856653591],[510575.99477181886,6651117.106644969,72.82536688853591],[510575.93566753983,6651115.380961512,74.46603966453591],[510575.9868541503,6651116.875470681,73.15103399853591],[510575.94714891637,6651115.716186337,74.2527873295359],[510575.97805538244,6651116.618570702,73.45940280653592],[510575.95811093354,6651116.036247287,74.0126988825359],[510575.96844581235,6651116.337997512,73.74750115753591],[510579.46126029454,6651104.410116288,68.20581012757597],[510579.4808333877,6651105.0194032,68.20581012757597],[510579.4808333877,6651105.0194032,68.33581012757597],[510579.46126029454,6651104.410116288,70.03461378657599],[510579.46193328174,6651104.431065568,70.50020447357596],[510579.4808333877,6651105.0194032,70.03461378657599],[510579.48142719985,6651105.037887859,70.44542909857597],[510579.46403780207,6651104.496576762,70.97747542557597],[510579.48328412964,6651105.095691853,70.86655052657596],[510579.4676823998,6651104.610028719,71.46037644557599],[510579.4864999512,6651105.195796522,71.29263966157598],[510579.4714728392,6651104.728020551,71.82208243057597],[510579.4911403387,6651105.340246219,71.71754616557598],[510579.476188227,6651104.874804918,72.17984027657597],[510579.48182912637,6651105.050399349,72.53029649157597],[510579.49723309436,6651105.529906395,72.13451286757596],[510579.48837956204,6651105.254306552,72.87004151857599],[510579.5047621531,6651105.764276962,72.53646178457598],[510579.4958064648,6651105.485497128,73.19570862857597],[510579.513664337,6651106.041391268,72.91634258657596],[510579.5040598531,6651105.742415206,73.50407743657597],[510579.5211775512,6651106.275268613,73.18274890157598],[510579.5130737873,6651106.023008165,73.79217578757597],[510579.52933955414,6651106.529341973,73.43045864157597],[510579.5227680729,6651106.324779649,74.05737351257596],[510579.54110121663,6651106.8954684185,73.72790111157597],[510579.5330506246,6651106.644863147,74.29746195957597],[510579.55368049006,6651107.287046113,73.98411423457597],[510579.5438203439,6651106.980111591,74.51071429457599],[510579.56685600476,6651107.697184081,74.19639204357597],[510579.554970327,6651107.327197189,74.69592319657598],[510579.5803994555,6651108.118775458,74.36350680057598],[510579.5663911942,6651107.682715084,74.85241448857597],[510579.59408744023,6651108.544866005,74.48565992257598],[510579.5779743351,6651108.043284371,74.98003724757596],[510579.6077117474,6651108.968974344,74.56433461557597],[510579.5896148874,6651108.4056408005,75.07913274157599],[510579.62108728697,6651109.385338846,74.60207747457596],[510579.6050557689,6651108.886296918,75.16829739357598],[510579.87255111965,6651117.213106325,68.20581012757597],[510579.6202147137,6651109.358176687,75.21107263457597],[510579.87255111965,6651117.213106325,68.33581012757597],[510579.89212421275,6651117.822393238,68.20581012757597],[510579.67727633624,6651111.134436552,74.60207747457596],[510579.8725511947,6651117.213108663,70.03461378757596],[510579.8724052489,6651117.208565545,70.23843507157598],[510579.89212421275,6651117.822393238,70.03461378657599],[510579.8711934001,6651117.1708421465,70.65501435957597],[510579.7322972956,6651112.847173017,74.60207747457596],[510579.8686673109,6651117.092208018,71.07934147957597],[510579.8914512257,6651117.801443957,70.50020447357596],[510579.7456728351,6651113.263537521,74.56433461557597],[510579.86474521505,6651116.970117877,71.50565183057599],[510579.7592971423,6651113.687645858,74.48565992257598],[510579.73316979373,6651112.874332837,75.21107263457597],[510579.8893467053,6651117.735932763,70.97747542557597],[510579.8593794896,6651116.803089285,71.92746068957598],[510579.772985127,6651114.113736405,74.36350680057598],[510579.7483287385,6651113.346212606,75.16829739357598],[510579.8525636678,6651116.590920925,72.33781023257598],[510579.88570210757,6651117.622480806,71.46037644557599],[510579.78652857774,6651114.535327782,74.19639204357597],[510579.84433716966,6651116.334839905,72.72958992657598],[510579.79970409244,6651114.94546575,73.98411423457597],[510579.8372920579,6651116.115534031,73.00707178657598],[510579.8122833659,6651115.337043445,73.72790111157597],[510579.8819116681,6651117.504488974,71.82208243057597],[510579.82955499773,6651115.874688626,73.26751245957597],[510579.76376962,6651113.826868724,75.07913274157599],[510579.82119276136,6651115.614382235,73.50848210557596],[510579.8771962804,6651117.357704608,72.17984027657597],[510579.7754101722,6651114.189225154,74.98003724757596],[510579.78699331323,6651114.549794439,74.85241448857597],[510579.87155538093,6651117.182110176,72.53029649157597],[510579.7984141804,6651114.905312335,74.69592319657598],[510579.8650049454,6651116.978202973,72.87004151857599],[510579.8095641635,6651115.252397935,74.51071429457599],[510579.85757804255,6651116.747012397,73.19570862857597],[510579.82033388276,6651115.587646376,74.29746195957597],[510579.8493246542,6651116.490094319,73.50407743657597],[510579.8306164344,6651115.907729876,74.05737351257596],[510579.8403107201,6651116.209501361,73.79217578757597],[510585.5625478138,6651104.224263366,68.27574991362977],[510585.58009589853,6651104.833611962,68.27574991362977],[510585.58009589853,6651104.833611962,68.40574991362976],[510585.5625478138,6651104.224263366,70.10455357262977],[510585.56315117446,6651104.24521477,70.57014425962976],[510585.58009589853,6651104.833611962,70.10455357262977],[510585.58062827564,6651104.852098494,70.51536888462977],[510585.5650379637,6651104.310732596,71.04741521162978],[510585.5822930897,6651104.909908341,70.93649031262976],[510585.5683054958,6651104.424196037,71.53031623162977],[510585.58517620625,6651105.010023143,71.36257944762977],[510585.57170378097,6651104.542199816,71.89202221662977],[510585.589336505,6651105.154487466,71.78748595162976],[510585.5759313205,6651104.688999041,72.24978006262978],[510585.58098861936,6651104.86461125,72.60023627762976],[510585.5947989115,6651105.344166841,72.20445265362977],[510585.58686135476,6651105.068539097,72.93998130462977],[510585.601549023,6651105.578561137,72.60640157062977],[510585.5935198793,6651105.299753079,73.26564841462977],[510585.60953019786,6651105.855703498,72.98628237262976],[510585.6009193821,6651105.556697167,73.57401722262978],[510585.61626610404,6651106.089604521,73.25268868762976],[510585.6090007456,6651105.837318534,73.86211557362977],[510585.623583676,6651106.343703603,73.50039842762976],[510585.6176920723,6651106.139120569,74.12731329862976],[510585.6341284912,6651106.709867116,73.79784089762977],[510585.6269108037,6651106.459236474,74.36740174562976],[510585.64540632843,6651107.101484454,74.05405402062976],[510585.6365663009,6651106.794518856,74.58065408062977],[510585.65721872036,6651107.511663944,74.26633182962978],[510585.6465627204,6651107.141639595,74.76586298262978],[510585.66936098225,6651107.933298003,74.43344658662977],[510585.65680199856,6651107.497193484,74.92235427462977],[510585.6816328247,6651108.359431689,74.55559970862977],[510585.66718676186,6651107.857799273,75.04997703362976],[510585.69384757767,6651108.783582963,74.63427440162977],[510585.67762299674,6651108.220192387,75.14907252762977],[510585.7058393002,6651109.199989618,74.67201726062976],[510585.6914663834,6651108.7008971665,75.23823717962976],[510585.93128699105,6651117.028549582,68.27574991362977],[510585.93128699105,6651117.028549582,68.40574991362976],[510585.70505700225,6651109.17282471,75.28101242062978],[510585.9488350758,6651117.637898179,68.27574991362977],[510585.7562150989,6651110.949264403,74.67201726062976],[510585.9312870584,6651117.02855192,70.10455357362976],[510585.9311562119,6651117.024008343,70.30837485762976],[510585.9488350758,6651117.637898179,70.10455357262977],[510585.9300697396,6651116.986281125,70.72495414562977],[510585.80554365675,6651112.662174267,74.67201726062976],[510585.92780499643,6651116.907639035,71.14928126562977],[510585.9482317151,6651117.616946777,70.57014425962976],[510585.81753537926,6651113.078580921,74.63427440162977],[510585.92428867583,6651116.785536534,71.57559161662977],[510585.9463449259,6651117.55142895,71.04741521162978],[510585.8297501322,6651113.502732197,74.55559970862977],[510585.80632588733,6651112.689336835,75.28101242062978],[510585.9194780818,6651116.61849103,71.99740047562976],[510585.8420219748,6651113.928865881,74.43344658662977],[510585.9133674166,6651116.406301191,72.40775001862977],[510585.94307739375,6651117.437965508,71.53031623162977],[510585.8199165061,6651113.161264378,75.23823717962976],[510585.8541642366,6651114.350499939,74.26633182962978],[510585.90599202196,6651116.150194245,72.79952971262976],[510585.8659766286,6651114.76067943,74.05405402062976],[510585.899675789,6651115.930866169,73.07701157262977],[510585.93967910856,6651117.319961729,71.89202221662977],[510585.8772544657,6651115.152296768,73.79784089762977],[510585.89273919555,6651115.689996381,73.33745224562976],[510585.88524210587,6651115.429663638,73.57842189162976],[510585.8337598928,6651113.641969157,75.14907252762977],[510585.9354515691,6651117.173162503,72.24978006262978],[510585.8441961277,6651114.004362272,75.04997703362976],[510585.93039427034,6651116.997550295,72.60023627762976],[510585.8545808911,6651114.364968063,74.92235427462977],[510585.92452153476,6651116.793622448,72.93998130462977],[510585.86482016917,6651114.720521951,74.76586298262978],[510585.91786301025,6651116.562408468,73.26564841462977],[510585.8748165887,6651115.067642689,74.58065408062977],[510585.9104635074,6651116.305464378,73.57401722262978],[510585.88447208586,6651115.402925071,74.36740174562976],[510585.902382144,6651116.024843013,73.86211557362977],[510585.8936908173,6651115.723040977,74.12731329862976],[510588.92990477174,6651104.130380348,68.31382165648704],[510588.9463352356,6651104.739760105,68.31382165648704],[510588.9463352356,6651104.739760105,68.44382165648703],[510588.92990477174,6651104.130380348,70.14262531548704],[510588.93046970497,6651104.151332822,70.60821600248704],[510588.9463352356,6651104.739760105,70.14262531548704],[510588.9468337061,6651104.758247582,70.55344062748705],[510588.93223632633,6651104.216853999,71.08548695448704],[510588.94839248975,6651104.816060384,70.97456205548703],[510588.9352957525,6651104.330323244,71.56838797448704],[510588.95109198336,6651104.916180306,71.40065119048704],[510588.9384776041,6651104.448333057,71.93009395948705],[510588.9549873166,6651105.060652016,71.82555769448703],[510588.94243589556,6651104.595139789,72.28785180548705],[510588.9471710999,6651104.770760979,72.63830802048703],[510588.96010182763,6651105.25034109,72.24252439648703],[510588.95266980643,6651104.974699252,72.97805304748704],[510588.96642203105,6651105.484747373,72.64447331348704],[510588.9589042558,6651105.205925057,73.30372015748704],[510588.9738948923,6651105.761903906,73.02435411548703],[510588.96583249135,6651105.462882286,73.61208896548705],[510588.9802017951,6651105.995816889,73.29076043048704],[510588.9733991605,6651105.743518001,73.90018731648703],[510588.98705331795,6651106.249928965,73.53847017048703],[510588.9815369448,6651106.04533547,74.16538504148703],[510588.9969265438,6651106.616111202,73.83591264048705],[510588.99016854394,6651106.365467743,74.40547348848703],[510589.00748610625,6651107.007748566,74.09212576348703],[510588.99920909177,6651106.700767272,74.61872582348704],[510589.0185461783,6651107.417949031,74.30440357248703],[510589.0085688487,6651107.047905761,74.80393472548704],[510589.029915111,6651107.83960465,74.47151832948704],[510589.01815599704,6651107.403477829,74.96042601748704],[510589.0414053715,6651108.265760126,74.59367145148704],[510589.02787936473,6651107.764102059,75.08804877648703],[510589.05284217844,6651108.6899330905,74.67234614448704],[510589.03765092575,6651108.126513705,75.18714427048704],[510589.06407015957,6651109.106361039,74.71008900348703],[510589.0506126402,6651108.607243066,75.27630892248703],[510589.2751593013,6651116.935321324,68.31382165648704],[510589.2751593013,6651116.935321324,68.44382165648703],[510589.06333768554,6651109.079194741,75.31908416348705],[510589.2915897653,6651117.54470108,68.31382165648704],[510589.11123757163,6651110.855725275,74.71008900348703],[510589.27515936433,6651116.935323662,70.14262531648704],[510589.2750368514,6651116.930779853,70.34644660048703],[510589.2915897653,6651117.54470108,70.14262531548704],[510589.27401957544,6651116.893050705,70.76302588848704],[510589.1574244405,6651112.56872273,74.71008900348703],[510589.27189907164,6651116.814404594,71.18735300848705],[510589.29102483205,6651117.523748606,70.60821600248704],[510589.1686524216,6651112.985150678,74.67234614448704],[510589.26860670216,6651116.69229585,71.61366335948703],[510589.2892582107,6651117.45822743,71.08548695448704],[510589.18008922855,6651113.409323642,74.59367145148704],[510589.1581568515,6651112.595886688,75.31908416348705],[510589.2641024903,6651116.525241805,72.03547221848703],[510589.19157948904,6651113.835479118,74.47151832948704],[510589.28619878454,6651117.344758186,71.56838797448704],[510589.2583810076,6651116.313041114,72.44582176148704],[510589.1708818968,6651113.067838362,75.27630892248703],[510589.20294842176,6651114.2571347365,74.30440357248703],[510589.25147534476,6651116.056921072,72.83760145548703],[510589.21400849376,6651114.667335203,74.09212576348703],[510589.2830169329,6651117.226748373,71.93009395948705],[510589.2455613867,6651115.837581779,73.11508331548704],[510589.23906657833,6651115.5966996765,73.37552398848705],[510589.22456805623,6651115.058972565,73.83591264048705],[510589.23204697116,6651115.336353619,73.61649363448703],[510589.1838436113,6651113.548567724,75.18714427048704],[510589.27905864135,6651117.079941641,72.28785180548705],[510589.1936151723,6651113.910979369,75.08804877648703],[510589.27432343713,6651116.904320451,72.63830802048703],[510589.2033385399,6651114.2716036,74.96042601748704],[510589.26882473053,6651116.700382178,72.97805304748704],[510589.2129256882,6651114.627175668,74.80393472548704],[510589.26259028114,6651116.469156371,73.30372015748704],[510589.22228544526,6651114.974314158,74.61872582348704],[510589.2556620456,6651116.212199143,73.61208896548705],[510589.23132599297,6651115.309613685,74.40547348848703],[510589.24809537653,6651115.931563429,73.90018731648703],[510589.23995759216,6651115.62974596,74.16538504148703],[510592.45276433567,6651104.0387768755,68.35252413432214],[510592.46802556765,6651104.648187035,68.35252413432214],[510592.46802556765,6651104.648187035,68.48252413432213],[510592.45276433567,6651104.0387768755,70.18132779332214],[510592.4532890668,6651104.059730395,70.64691848032213],[510592.46802556765,6651104.648187035,70.18132779332214],[510592.46848856576,6651104.6666754335,70.59214310532214],[510592.45492997114,6651104.1252548415,71.12418943232214],[510592.46993642254,6651104.724491121,71.01326453332213],[510592.4577716811,6651104.238729747,71.60709045232214],[510592.47244381363,6651104.824616039,71.43935366832216],[510592.4607271044,6651104.356745446,71.96879643732214],[510592.4760619455,6651104.969094955,71.86426017232213],[510592.4644037142,6651104.503559503,72.32655428332214],[510592.4688019497,6651104.679189454,72.67701049832213],[510592.48081249546,6651105.158793495,72.28122687432213],[510592.4739093549,6651104.883137903,73.01675552532214],[510592.48668293766,6651105.393211472,72.68317579132213],[510592.47970014566,6651105.114375245,73.34242263532214],[510592.4936240119,6651105.670381833,73.06305659332213],[510592.4861353511,6651105.371345293,73.65079144332213],[510592.4994821,6651105.904306487,73.32946290832214],[510592.49316355755,6651105.65199501,73.93888979432214],[510592.5058460518,6651106.158431242,73.57717264832213],[510592.50072223734,6651105.953827537,74.20408751932213],[510592.51501667494,6651106.524631746,73.87461511832214],[510592.50873959076,6651106.273975783,74.44417596632213],[510592.52482479316,6651106.91628865,74.13082824132213],[510592.51713679114,6651106.609292039,74.65742830132216],[510592.53509780334,6651107.326509581,74.34310605032213],[510592.525830485,6651106.956447848,74.84263720332214],[510592.54565769504,6651107.748186238,74.51022080732214],[510592.5347353884,6651107.312037658,74.99912849532215],[510592.5563302806,6651108.174362975,74.63237392932214],[510592.5437668175,6651107.67267988,75.12675125432214],[510592.5669532165,6651108.598557102,74.71104862232214],[510592.55284301034,6651108.0351096075,75.22584674832214],[510592.577382187,6651109.015005826,74.74879148132213],[510592.7734497102,6651116.844356714,68.35252413432214],[510592.5648823376,6651108.515862952,75.31501140032215],[510592.7734497102,6651116.844356714,68.48252413432213],[510592.57670183765,6651108.987838173,75.35778664132214],[510592.7887109422,6651117.453766873,68.35252413432214],[510592.6211930509,6651110.764457343,74.74879148132213],[510592.7734497688,6651116.844359051,70.18132779432213],[510592.77333597414,6651116.839815014,70.38514907832213],[510592.7887109422,6651117.453766873,70.18132779332214],[510592.77239108994,6651116.802083986,70.80172836632214],[510592.6640931494,6651112.477540261,74.74879148132213],[510592.7704214864,6651116.72343395,71.22605548632214],[510592.788186211,6651117.432813353,70.64691848032213],[510592.67452212004,6651112.893988985,74.71104862232214],[510592.7673634099,6651116.601319114,71.65236583732215],[510592.78654530674,6651117.367288907,71.12418943232214],[510592.6851450558,6651113.318183114,74.63237392932214],[510592.7631797288,6651116.434256734,72.07417469632213],[510592.6647734403,6651112.504705574,75.35778664132214],[510592.6958176414,6651113.744359851,74.51022080732214],[510592.7837035968,6651117.253814002,71.60709045232214],[510592.7578654008,6651116.222045456,72.48452423932214],[510592.67659294023,6651112.976680796,75.31501140032215],[510592.7063775331,6651114.166036505,74.34310605032213],[510592.7514511618,6651115.965912636,72.87630393332215],[510592.78074817354,6651117.1357983025,71.96879643732214],[510592.7459580553,6651115.7465624,73.15378579332213],[510592.7166505433,6651114.5762574375,74.13082824132213],[510592.7399254335,6651115.505668278,73.41422646632213],[510592.7264586615,6651114.96791434,73.87461511832214],[510592.7334053586,6651115.245309232,73.65519611232213],[510592.6886322676,6651113.457434141,75.22584674832214],[510592.77707156364,6651116.988984244,72.32655428332214],[510592.69770846044,6651113.819863868,75.12675125432214],[510592.7726733281,6651116.813354294,72.67701049832213],[510592.70673988946,6651114.180506091,74.99912849532215],[510592.7675659229,6651116.609405844,73.01675552532214],[510592.7156447929,6651114.5360958995,74.84263720332214],[510592.7617751322,6651116.378168503,73.34242263532214],[510592.7243384867,6651114.883251709,74.65742830132216],[510592.75533992675,6651116.121198455,73.65079144332213],[510592.7327356871,6651115.218567966,74.44417596632213],[510592.7483117203,6651115.840548739,73.93888979432214],[510592.74075304053,6651115.538716211,74.20408751932213],[510596.67553794186,6651103.937886111,68.39739721245486],[510596.6893976416,6651104.5473297555,68.39739721245486],[510596.6893976416,6651104.5473297555,68.52739721245487],[510596.67553794186,6651103.937886111,70.22620087145486],[510596.67601448385,6651103.958840781,70.69179155845485],[510596.6893976416,6651104.5473297555,70.22620087145486],[510596.68981811975,6651104.56581917,70.63701618345486],[510596.6775046939,6651104.024368827,71.16906251045486],[510596.6911330109,6651104.623638035,71.05813761145485],[510596.6800854321,6651104.137849968,71.65196353045486],[510596.6934101329,6651104.723768453,71.48422674645488],[510596.68276944075,6651104.255872153,72.01366951545486],[510596.6966959895,6651104.868255309,71.90913325045486],[510596.68610840506,6651104.4026942765,72.37142736145486],[510596.7010102675,6651105.057964272,72.32609995245485],[510596.6901027237,6651104.578333879,72.72188357645487],[510596.6947410846,6651104.782293535,73.06162860345486],[510596.706341591,6651105.292395129,72.72804886945485],[510596.70000007167,6651105.013543581,73.38729571345486],[510596.71264522395,6651105.56958072,73.10792967145487],[510596.70584429265,6651105.27052775,73.69566452145486],[510596.71796532796,6651105.803518227,73.37433598645487],[510596.712227056,6651105.551192887,73.98376287245486],[510596.72374483914,6651106.057656946,73.62204572645486],[510596.7190915758,6651105.853041999,74.24896059745485],[510596.7320732677,6651106.423877573,73.91948819645486],[510596.72637264675,6651106.173207836,74.48904904445486],[510596.74098064634,6651106.815555996,74.17570131945486],[510596.7339986807,6651106.508542517,74.70230137945487],[510596.7503102232,6651107.225799468,74.38797912845486],[510596.7418939794,6651106.855717401,74.88751028145487],[510596.75990033546,6651107.647499295,74.55509388545487],[510596.74998109107,6651107.21132675,75.04400157345488],[510596.76959279214,6651108.073699448,74.67724700745487],[510596.75818310864,6651107.571988788,75.17162433245487],[510596.7792401587,6651108.497916885,74.75592170045486],[510596.76642577926,6651107.934438431,75.27071982645487],[510596.96677281527,6651116.744169581,68.39739721245486],[510596.78871137305,6651108.914388492,74.79366455945485],[510596.96677281527,6651116.744169581,68.52739721245487],[510596.77735946135,6651108.415218192,75.35988447845486],[510596.98063251487,6651117.353613226,68.39739721245486],[510596.78809350426,6651108.887219346,75.40265971945486],[510596.8284988171,6651110.663936135,74.79366455945485],[510596.9667728685,6651116.744171919,70.22620087245485],[510596.9666695243,6651116.739627633,70.43002215645485],[510596.98063251487,6651117.353613226,70.22620087145486],[510596.96581141464,6651116.70189453,70.84660144445486],[510596.980155973,6651117.332658556,70.69179155845485],[510596.96402269177,6651116.623240175,71.27092856445486],[510596.867459137,6651112.377113184,74.79366455945485],[510596.9612454572,6651116.501118627,71.69723891545486],[510596.8769303513,6651112.793584791,74.75592170045486],[510596.97866576293,6651117.26713051,71.16906251045486],[510596.95744598925,6651116.334047068,72.11904777445486],[510596.8865777179,6651113.217802227,74.67724700745487],[510596.8680769526,6651112.404279989,75.40265971945486],[510596.97608502477,6651117.153649368,71.65196353045486],[510596.9526197084,6651116.1218241295,72.52939731745488],[510596.89627017465,6651113.644002382,74.55509388545487],[510596.9467945282,6651115.865677235,72.92117701145486],[510596.90586028685,6651114.065702207,74.38797912845486],[510596.87881099543,6651112.876281145,75.35988447845486],[510596.973401016,6651117.0356271835,72.01366951545486],[510596.94180588744,6651115.646314947,73.19865887145485],[510596.9151898636,6651114.4759456795,74.17570131945486],[510596.93632727815,6651115.405407589,73.45909954445486],[510596.9240972423,6651114.867624102,73.91948819645486],[510596.93040598166,6651115.145034237,73.70006919045485],[510596.9700620517,6651116.88880506,72.37142736145486],[510596.8897446776,6651113.3570609065,75.27071982645487],[510596.9660677331,6651116.713165458,72.72188357645487],[510596.8979873482,6651113.719510548,75.17162433245487],[510596.96142937226,6651116.509205802,73.06162860345486],[510596.9061893658,6651114.080172587,75.04400157345488],[510596.91427647736,6651114.435781935,74.88751028145487],[510596.9561703852,6651116.277955756,73.38729571345486],[510596.9221717761,6651114.782956819,74.70230137945487],[510596.9503261642,6651116.020971587,73.69566452145486],[510596.9297978101,6651115.1182915,74.48904904445486],[510596.94394340087,6651115.740306449,73.98376287245486],[510596.937078881,6651115.438457337,74.24896059745485],[510609.1755280418,6651103.696178987,68.52052626257824],[510609.18523901305,6651104.305702854,68.52052626257824],[510609.18523901305,6651104.305702854,68.65052626257824],[510609.3450717457,6651103.693485635,68.52209666841532],[510609.3547264457,6651104.303010396,68.52209666841532],[510609.3547264457,6651104.303010396,68.65209666841531],[510609.1755280418,6651103.696178987,70.34932992157825],[510609.18523901305,6651104.305702854,70.34932992157825],[510609.17586193676,6651103.717136416,70.81492060857825],[510609.1855336263,6651104.324194701,70.76014523357826],[510609.176906071,6651103.782673088,71.29219156057825],[510609.3450717457,6651103.693485635,70.35090032741533],[510609.18645492126,6651104.382021178,71.18126666157823],[510609.1787142974,6651103.896169165,71.77509258057825],[510609.3547264457,6651104.303010396,70.35090032741533],[510609.3454037059,6651103.714443094,70.8164910144153],[510609.18805041513,6651104.482164776,71.60735579657825],[510609.18059488165,6651104.014206886,72.13679856557826],[510609.3550193518,6651104.321502272,70.76171563941531],[510609.3464417898,6651103.779979862,71.29376196641532],[510609.19035269157,6651104.626670651,72.03226230057824],[510609.18293436855,6651104.161048336,72.49455641157826],[510609.3559353081,6651104.379328833,71.1828370674153],[510609.3482395383,6651103.893476107,71.77666298641533],[510609.1933755441,6651104.816404587,72.44922900257824],[510609.1857330377,6651104.336711057,72.84501262657824],[510609.3575215568,6651104.479472578,71.60892620241532],[510609.3501092252,6651104.011514001,72.13836897141532],[510609.18898296304,6651104.540697562,73.18475765357825],[510609.19711100246,6651105.050866302,72.85117791957825],[510609.3598104924,6651104.623978665,72.03383270641532],[510609.3524351556,6651104.158355666,72.49612681741532],[510609.1926677378,6651104.771978049,73.51042476357824],[510609.2015277214,6651105.32808838,73.23105872157824],[510609.36281582864,6651104.813712877,72.4507994084153],[510609.35521760763,6651104.334018646,72.84658303241531],[510609.1967625641,6651105.028996043,73.81879357157825],[510609.20525531855,6651105.56205668,73.49746503657823],[510609.3584487009,6651104.538005449,73.18632805941533],[510609.36652964144,6651105.048174938,72.85274832541532],[510609.20123472676,6651105.309698125,74.10689192257824],[510609.20930480503,6651105.816228851,73.74517477657824],[510609.3621121238,6651104.769286274,73.51199516941531],[510609.37092076725,6651105.325397422,73.23262912741531],[510609.2060444381,6651105.611586971,74.37208964757824],[510609.2151402224,6651106.182497685,74.04261724657826],[510609.3661832222,6651105.026304646,73.82036397741531],[510609.3746267645,6651105.559366065,73.49903544241532],[510609.2111460112,6651105.931794952,74.61217809457824],[510609.22138128825,6651106.5742276665,74.29883036957824],[510609.3706294704,6651105.3070071405,74.10846232841533],[510609.37865278573,6651105.81353861,73.74674518241531],[510609.2164892869,6651106.267173775,74.82543042957825],[510609.2279181725,6651106.984525139,74.51110817857824],[510609.37541131146,6651105.608896428,74.3736600534153],[510609.38445438904,6651106.17980798,74.04418765241532],[510609.2220212264,6651106.6143943565,75.01063933157825],[510609.23463760415,6651107.406280475,74.67822293557825],[510609.38048332284,6651105.92910488,74.61374850041531],[510609.22768756194,6651106.970050516,75.16713062357825],[510609.39065929037,6651106.571538536,74.30040077541531],[510609.24142874463,6651107.832536731,74.80037605757825],[510609.3857956364,6651106.264484194,74.82700083541532],[510609.23343440774,6651107.330760027,75.29475338257824],[510609.39715829596,6651106.98183661,74.51267858441531],[510609.3795853851,6651116.504148172,68.52052626257824],[510609.24818829226,6651108.256810007,74.87905075057824],[510609.2392097376,6651107.693257379,75.39384887657825],[510609.3795853851,6651116.504148172,68.65052626257824],[510609.39129552036,6651106.611705286,75.01220973741532],[510609.25482441665,6651108.673336434,74.91679360957824],[510609.403838791,6651107.403592563,74.67979334141532],[510609.3892963563,6651117.11367204,68.52052626257824],[510609.3969290217,6651106.967361964,75.16870102941532],[510609.2468705583,6651108.174100428,75.48301352857824],[510609.4105905796,6651107.829849445,74.80194646341532],[510609.4026425668,6651107.328072008,75.29632378841531],[510609.25439149915,6651108.646163712,75.52578876957826],[510609.5479466559,6651116.501473606,68.52209666841532],[510609.4173109583,6651108.254123345,74.88062115641533],[510609.5479466559,6651116.501473606,68.65209666841531],[510609.4083844308,6651107.69056989,75.39541928241533],[510609.4239086289,6651108.6706503825,74.91836401541532],[510609.5576013559,6651117.110998366,68.52209666841532],[510609.2827019851,6651110.423114375,74.91679360957824],[510609.41600086004,6651108.171413644,75.48458393441531],[510609.37958542234,6651116.504150511,70.34932992257825],[510609.3795130129,6651116.499605627,70.55315120657824],[510609.42347822,6651108.643477621,75.52735917541531],[510609.3892963563,6651117.11367204,70.34932992157825],[510609.3789117677,6651116.461867557,70.96973049457824],[510609.3889624613,6651117.092714612,70.81492060857825],[510609.37765847676,6651116.383202848,71.39405761457826],[510609.45162465767,6651110.420430889,74.91836401541532],[510609.54794669297,6651116.501475945,70.3509003284153],[510609.3100000188,6651112.1365169315,74.91679360957824],[510609.3757125727,6651116.261065225,71.82036796557824],[510609.38791832706,6651117.027177939,71.29219156057825],[510609.54787470313,6651116.496931053,70.55472161241532],[510609.31663614314,6651112.553043359,74.87905075057824],[510609.3730504281,6651116.093971674,72.24217682457824],[510609.5576013559,6651117.110998366,70.35090032741533],[510609.38611010066,6651116.913681861,71.77509258057825],[510609.32339569076,6651112.977316637,74.80037605757825],[510609.5472769419,6651116.459192928,70.97130090041533],[510609.3696688343,6651115.881720801,72.65252636757825],[510609.3104328989,6651112.163687313,75.52578876957826],[510609.3301868313,6651113.403572893,74.67822293557825],[510609.38422951655,6651116.795644141,72.13679856557826],[510609.3655873492,6651115.625540189,73.04430606157824],[510609.3369062629,6651113.825328227,74.51110817857824],[510609.36209199595,6651115.406149025,73.32178792157825],[510609.5572693957,6651117.090040907,70.8164910144153],[510609.3179538399,6651112.635750599,75.48301352857824],[510609.5460309133,6651116.380528104,71.39562802041532],[510609.35825334,6651115.1652099565,73.58222859457825],[510609.3434431472,6651114.235625701,74.29883036957824],[510609.35410450987,6651114.904802331,73.82319824057824],[510609.38189002965,6651116.64880269,72.49455641157826],[510609.349684213,6651114.627355681,74.04261724657826],[510609.4787645098,6651112.13383596,74.91836401541532],[510609.32561466057,6651113.116593648,75.39384887657825],[510609.3790913605,6651116.47313997,72.84501262657824],[510609.54409628507,6651116.258390302,71.82193837141531],[510609.5562313118,6651117.024504139,71.29376196641532],[510609.33138999034,6651113.479090998,75.29475338257824],[510609.3758414351,6651116.269153465,73.18475765357825],[510609.48536218033,6651112.550362998,74.88062115641533],[510609.33713683626,6651113.8398005115,75.16713062357825],[510609.5414495666,6651116.091296505,72.24374723041532],[510609.3721566603,6651116.0378729785,73.51042476357824],[510609.3428031718,6651114.195456669,75.01063933157825],[510609.36806183396,6651115.780854982,73.81879357157825],[510609.5544335634,6651116.911007894,71.77666298641533],[510609.49208255904,6651112.9746368965,74.80194646341532],[510609.34833511116,6651114.542677253,74.82543042957825],[510609.3635896713,6651115.500152901,74.10689192257824],[510609.3536783869,6651114.8780560745,74.61217809457824],[510609.3587799599,6651115.198264056,74.37208964757824],[510609.5380875677,6651115.879045322,72.65409677341532],[510609.47919488157,6651112.161006381,75.52735917541531],[510609.49883434764,6651113.400893778,74.67979334141532],[510609.55256387644,6651116.792970001,72.13836897141532],[510609.5340297333,6651115.622864335,73.04587646741531],[510609.50551484275,6651113.822649731,74.51267858441531],[510609.5305546342,6651115.403472849,73.32335832741532],[510609.4866722416,6651112.633070359,75.48458393441531],[510609.5267382219,6651115.162533427,73.58379900041531],[510609.51201384823,6651114.232947806,74.30040077541531],[510609.52261343255,6651114.902125418,73.82476864641532],[510609.550237946,6651116.646128335,72.49612681741532],[510609.51821874955,6651114.624678362,74.04418765241532],[510609.4942886708,6651113.113914112,75.39541928241533],[510609.54745549406,6651116.4704653565,72.84658303241531],[510609.50003053475,6651113.476411995,75.29632378841531],[510609.54422440066,6651116.266478554,73.18632805941533],[510609.50574408,6651113.837122037,75.16870102941532],[510609.54056097777,6651116.035197727,73.51199516941531],[510609.5113775812,6651114.192778716,75.01220973741532],[510609.53648987936,6651115.778179355,73.82036397741531],[510609.5168774652,6651114.539999809,74.82700083541532],[510609.5320436312,6651115.497476861,74.10846232841533],[510609.52218977874,6651114.875379123,74.61374850041531],[510609.5272617901,6651115.195587574,74.3736600534153],[510613.89348648244,6651103.627073775,68.5632313089762],[510613.9016315702,6651104.236620578,68.5632313089762],[510613.9016315702,6651104.236620578,68.69323130897621],[510613.89348648244,6651103.627073775,70.3920349679762],[510613.9016315702,6651104.236620578,70.3920349679762],[510613.8937665372,6651103.648031992,70.85762565497619],[510613.90187867737,6651104.255113122,70.8028502799762],[510613.89464230597,6651103.71357113,71.3348966069762],[510613.9026514145,6651104.312941775,71.22397170797619],[510613.8961589578,6651103.82707148,71.8177976269762],[510613.90398963675,6651104.413089141,71.65006084297622],[510613.89773629984,6651103.945113642,72.1795036119762],[510613.90592067357,6651104.5576004535,72.0749673469762],[510613.89969854703,6651104.091960617,72.5372614579762],[510613.9084560945,6651104.747341528,72.49193404897619],[510613.9020459338,6651104.267629948,72.88771767297621],[510613.90477181226,6651104.471624129,73.2274626999762],[510613.9115892142,6651104.981812067,72.89388296597619],[510613.9078624212,6651104.702913318,73.5531298099762],[510613.9152937421,6651105.2590445755,73.2737637679762],[510613.91129696125,6651104.959940986,73.8614986179762],[510613.9184202683,6651105.49302168,73.5401700829762],[510613.91504799254,6651105.240653629,74.1495969689762],[510613.92181677953,6651105.747203415,73.7878798229762],[510613.9190821432,6651105.542553835,74.41479469397619],[510613.92671124224,6651106.113486032,74.0853222929762],[510613.92336109316,6651105.862773865,74.6548831409762],[510613.931945943,6651106.505230753,74.3415354159762],[510613.9278427716,6651106.198165307,74.8681354759762],[510613.9374287619,6651106.915543665,74.5538132249762],[510613.9324826919,6651106.545398956,75.0533443779762],[510613.94306469255,6651107.337314871,74.7209279819762],[510613.937235337,6651106.901068497,75.20983566997621],[510613.9487607691,6651107.763587167,74.8430811039762],[510613.94205551024,6651107.261791583,75.3374584289762],[510614.0646398025,6651116.435524915,68.5632313089762],[510614.0646398025,6651116.435524915,68.69323130897621],[510613.9544303471,6651108.187876408,74.9217557969762],[510613.9468995745,6651107.624302576,75.4365539229762],[510614.0727848903,6651117.045071719,68.5632313089762],[510613.9599964036,6651108.60441851,74.95949865597619],[510613.95332509617,6651108.105163718,75.5257185749762],[510613.9596332937,6651108.577244766,75.5684938159762],[510614.06463983376,6651116.435527254,70.39203496897619],[510613.98337874474,6651110.354262293,74.95949865597619],[510614.06457910023,6651116.4309822,70.59585625297619],[510614.0727848903,6651117.045071719,70.3920349679762],[510614.0640748052,6651116.393242709,71.0124355409762],[510614.07250483544,6651117.024113502,70.85762565497619],[510614.063023606,6651116.314575039,71.4367626609762],[510614.06139147695,6651116.192432822,71.8630730119762],[510614.0062750003,6651112.067729325,74.95949865597619],[510614.07162906666,6651116.958574363,71.3348966069762],[510614.01184105687,6651112.484271425,74.9217557969762],[510614.05915860017,6651116.025332983,72.28488187097619],[510614.0701124148,6651116.845074014,71.8177976269762],[510614.01751063485,6651112.908560668,74.8430811039762],[510614.05632228474,6651115.813074122,72.69523141397622],[510614.006638079,6651112.094900728,75.5684938159762],[510614.06853507285,6651116.727031852,72.1795036119762],[510614.0232067114,6651113.3348329635,74.7209279819762],[510614.0528989346,6651115.556883871,73.08701110797621],[510614.0499672032,6651115.337484452,73.36449296797619],[510614.02884264203,6651113.756604169,74.5538132249762],[510614.0467475264,6651115.096536316,73.6249336409762],[510614.0129462765,6651112.566981778,75.5257185749762],[510614.06657282566,6651116.580184877,72.5372614579762],[510614.03432546085,6651114.166917081,74.3415354159762],[510614.0432676906,6651114.836118892,73.86590328697619],[510614.0395601617,6651114.558661803,74.0853222929762],[510614.0642254388,6651116.404515545,72.88771767297621],[510614.01937179815,6651113.04784292,75.4365539229762],[510614.06149956037,6651116.200521367,73.2274626999762],[510614.0242158624,6651113.41035391,75.3374584289762],[510614.0584089515,6651115.9692321755,73.5531298099762],[510614.02903603564,6651113.771076997,75.20983566997621],[510614.05497441144,6651115.7122045085,73.8614986179762],[510614.0337886808,6651114.126746538,75.0533443779762],[510614.05122338014,6651115.431491864,74.1495969689762],[510614.038428601,6651114.4739801865,74.8681354759762],[510614.04718922934,6651115.12959166,74.41479469397619],[510614.0429102794,6651114.809371629,74.6548831409762],[510626.23984072346,6651103.503599185,68.66521709454246],[510626.2438880744,6651104.11318697,68.66521709454246],[510626.2438880744,6651104.11318697,68.79521709454245],[510626.23984072346,6651103.503599185,70.49402075354247],[510626.2438880744,6651104.11318697,70.49402075354247],[510626.23997988465,6651103.524558811,70.95961144054245],[510626.2440108637,6651104.131680758,70.90483606554245],[510626.24041506025,6651103.590102356,71.43688239254246],[510626.2443948422,6651104.189513296,71.32595749354245],[510626.2411686951,6651103.7036103355,71.91978341254247],[510626.2450598141,6651104.289667396,71.75204662854246],[510626.2419524874,6651103.821660434,72.28148939754246],[510626.2460193598,6651104.434188425,72.17695313254247],[510626.24292754167,6651103.968517283,72.63924724354246],[510626.2472792281,6651104.623942256,72.59391983454245],[510626.2440939746,6651104.144198425,72.98970345854245],[510626.24544848263,6651104.348206319,73.32944848554247],[510626.2488360972,6651104.858428558,72.99586875154245],[510626.2469842277,6651104.579511059,73.65511559554245],[510626.2506769029,6651105.135679706,73.37574955354245],[510626.2486908746,6651104.836556006,73.96348440354245],[510626.25223049556,6651105.369672542,73.64215586854246],[510626.2539182457,6651105.623871366,73.88986560854245],[510626.2505547882,6651105.117287523,74.25158275454245],[510626.2525593859,6651105.419208026,74.51678047954245],[510626.2563503383,6651105.990178609,74.18730807854246],[510626.25468562596,6651105.739449585,74.75686892654245],[510626.2589514977,6651106.381949667,74.44352120154245],[510626.2569126032,6651106.074863577,74.97012126154247],[510626.26167594857,6651106.792290165,74.65579901054245],[510626.25921821187,6651106.422120571,75.15533016354246],[510626.2644764818,6651107.214089728,74.82291376754246],[510626.2615798344,6651106.777814023,75.31182145554246],[510626.32488800184,6651116.312911464,68.66521709454246],[510626.32488800184,6651116.312911464,68.79521709454245],[510626.26730690204,6651107.640390683,74.94506688954246],[510626.2639750121,6651107.138561362,75.43944421454245],[510626.32893535285,6651116.922499247,68.66521709454246],[510626.2701241548,6651108.06470845,75.02374158254247],[510626.2663820614,6651107.501096726,75.53853970854247],[510626.2728899672,6651108.481278556,75.06148444154246],[510626.26957494795,6651107.981990198,75.62770436054247],[510626.27270953526,6651108.454102986,75.67047960154245],[510626.3248880174,6651116.3129138015,70.49402075454245],[510626.32485783857,6651116.308368442,70.69784203854246],[510626.2845088155,6651110.231239986,75.06148444154246],[510626.32893535285,6651116.922499247,70.49402075354247],[510626.3246072508,6651116.270626414,71.11442132654247],[510626.3287961916,6651116.901539621,70.95961144054245],[510626.3240849026,6651116.191953456,71.53874844654246],[510626.3232738862,6651116.0698030265,71.96505879754247],[510626.328361016,6651116.835996076,71.43688239254246],[510626.29588612466,6651111.9448222155,75.06148444154246],[510626.32216435426,6651115.902691952,72.38686765654246],[510626.3276073811,6651116.722488096,71.91978341254247],[510626.29865193693,6651112.361392322,75.02374158254247],[510626.32075496926,6651115.690418822,72.79721719954246],[510626.30146918976,6651112.78571009,74.94506688954246],[510626.32682358887,6651116.6044379985,72.28148939754246],[510626.31905388273,6651115.434211346,73.18899689354245],[510626.29606654093,6651111.971995447,75.67047960154245],[510626.30429960997,6651113.212011044,74.82291376754246],[510626.3175970849,6651115.2147971755,73.46647875354245],[510626.3258485345,6651116.457581149,72.63924724354246],[510626.30710014317,6651113.633810608,74.65579901054245],[510626.3159972051,6651114.973832841,73.72691942654245],[510626.3142680504,6651114.713397908,73.96788907254245],[510626.3098245941,6651114.044151105,74.44352120154245],[510626.3124257535,6651114.435922164,74.18730807854246],[510626.2992011283,6651112.444108235,75.62770436054247],[510626.32468210167,6651116.281900008,72.98970345854245],[510626.3233275936,6651116.0778921135,73.32944848554247],[510626.3023940148,6651112.925001705,75.53853970854247],[510626.30480106414,6651113.28753707,75.43944421454245],[510626.3217918486,6651115.846587373,73.65511559554245],[510626.3071962418,6651113.648284409,75.31182145554246],[510626.32008520165,6651115.589542426,73.96348440354245],[510626.3095578643,6651114.003977861,75.15533016354246],[510626.31822128803,6651115.308810909,74.25158275454245],[510626.31186347303,6651114.351234855,74.97012126154247],[510626.31621669047,6651115.006890406,74.51678047954245],[510626.3140904503,6651114.686648847,74.75686892654245],[510629.4247079386,6651103.4852147475,68.68923256011365],[510629.4276982368,6651104.094808633,68.68923256011365],[510629.4276982368,6651104.094808633,68.81923256011363],[510629.4247079386,6651103.4852147475,70.51803621911364],[510629.4276982368,6651104.094808633,70.51803621911364],[510629.4248107548,6651103.506174582,70.98362690611363],[510629.42778895696,6651104.113302606,70.92885153111364],[510629.4251322749,6651103.571718783,71.46089785811365],[510629.4280726512,6651104.171135723,71.34997295911364],[510629.4256890819,6651103.6852279,71.94379887811364],[510629.4285639514,6651104.271290826,71.77606209411364],[510629.4262681699,6651103.80327918,72.30550486311364],[510629.4292728911,6651104.415813303,72.20096859811363],[510629.42698856787,6651103.950137498,72.66326270911364],[510629.4302037177,6651104.605569031,72.61793530011364],[510629.4278503617,6651104.125820398,73.01371892411363],[510629.42885111074,6651104.3298303345,73.35346395111364],[510629.43135397695,6651104.840057681,73.01988421711363],[510629.429985763,6651104.561137389,73.67913106111364],[510629.43271401664,6651105.117311604,73.39976501911363],[510629.43124668236,6651104.818184911,73.98749986911363],[510629.43386185524,6651105.351306782,73.66617133411366],[510629.4351088131,6651105.6055081505,73.91388107411363],[510629.4326237949,6651105.098919239,74.27559822011365],[510629.4341048487,6651105.400842763,74.54079594511363],[510629.43690571235,6651105.971819059,74.21132354411364],[510629.43567577546,6651105.721087527,74.78088439211363],[510629.438827523,6651106.363594039,74.46753666711363],[510629.4373211297,6651106.056504875,74.99413672711364],[510629.440840425,6651106.773938647,74.67981447611365],[510629.4390245791,6651106.403765346,75.17934562911366],[510629.4429095387,6651107.19574243,74.84692923311364],[510629.48754329083,6651116.294655242,68.68923256011365],[510629.44076941314,6651106.75946236,75.33583692111364],[510629.48754329083,6651116.294655242,68.81923256011363],[510629.4450007338,6651107.622047652,74.96908235511364],[510629.4905335889,6651116.904249128,68.68923256011365],[510629.4425390386,6651107.120213309,75.46345968011363],[510629.44708220044,6651108.046369667,75.04775704811364],[510629.4443174352,6651107.482752302,75.56255517411364],[510629.4491256614,6651108.462943942,75.08549990711363],[510629.4466764307,6651107.963650586,75.65171982611363],[510629.44899235317,6651108.4357680995,75.69449506711364],[510629.4875433023,6651116.294657581,70.51803622011363],[510629.48752100527,6651116.290112174,70.72185750411363],[510629.4577099976,6651110.212922889,75.08549990711363],[510629.4905335889,6651116.904249128,70.51803621911364],[510629.4873358639,6651116.25236977,71.13843679211364],[510629.4904307727,6651116.8832892915,70.98362690611363],[510629.4869499381,6651116.173696023,71.56276391211364],[510629.49010925257,6651116.817745091,71.46089785811365],[510629.4863507362,6651116.05154437,71.98907426311364],[510629.4661158777,6651111.926522272,75.08549990711363],[510629.4855309823,6651115.884431624,72.41088312211363],[510631.1135923384,6651103.4777066065,68.7015861260573],[510629.4895524457,6651116.704235976,71.94379887811364],[510629.4681593386,6651112.343096547,75.04775704811364],[510629.48448968853,6651115.672156369,72.82123266511364],[510629.4889733576,6651116.586184695,72.30550486311364],[510629.47024080524,6651112.767418562,74.96908235511364],[510631.1160220983,6651104.087302984,68.7015861260573],[510629.4832328774,6651115.415946329,73.21301235911363],[510631.1160220983,6651104.087302984,68.83158612605729],[510629.46624917444,6651111.953695774,75.69449506711364],[510629.47233200027,6651113.193723784,74.84692923311364],[510629.48215655365,6651115.196529962,73.49049421911363],[510629.4882529597,6651116.439326376,72.66326270911364],[510629.4809745169,6651114.955563216,73.75093489211363],[510629.4744011141,6651113.615527568,74.67981447611365],[510629.4796969681,6651114.695125677,73.99190453811364],[510629.476414016,6651114.025872175,74.46753666711363],[510629.4783358266,6651114.417647155,74.21132354411364],[510629.48739116587,6651116.263643475,73.01371892411363],[510629.4685650968,6651112.425813288,75.65171982611363],[510629.48639041674,6651116.059633539,73.35346395111364],[510629.47092409234,6651112.906711572,75.56255517411364],[510629.4852557645,6651115.828326484,73.67913106111364],[510629.47270248894,6651113.269250565,75.46345968011363],[510629.4839948451,6651115.571278964,73.98749986911363],[510629.4744721144,6651113.630001515,75.33583692111364],[510629.48261773266,6651115.290544637,74.27559822011365],[510629.4762169484,6651113.985698529,75.17934562911366],[510629.48113667883,6651114.988621112,74.54079594511363],[510629.4779203979,6651114.332958998,74.99413672711364],[510629.47956575215,6651114.668376348,74.78088439211363],[510631.1135923384,6651103.4777066065,70.5303897850573],[510631.1160220983,6651104.087302984,70.5303897850573],[510631.1136758815,6651103.498666528,70.99598047205728],[510631.1160958128,6651104.105797033,70.9412050970573],[510631.1139371319,6651103.564210997,71.4732514240573],[510631.11632632784,6651104.163630388,71.36232652505728],[510631.11438956414,6651103.6777205765,71.9561524440573],[510631.11672553275,6651104.2637859,71.7884156600573],[510631.1148601008,6651103.795772339,72.3178584290573],[510631.1173015801,6651104.408308966,72.21332216405729],[510631.11544545845,6651103.942631259,72.6756162750573],[510631.11805792106,6651104.598065472,72.63028886605728],[510631.1161457071,6651104.118314878,73.02607249005729],[510631.1169588634,6651104.322325647,73.3658175170573],[510631.11899256153,6651104.832555079,73.0322377830573],[510631.1178808225,6651104.553633648,73.6914846270573],[510631.1200976588,6651105.109810137,73.41211858505729],[510631.1189053796,6651104.81068222,73.99985343505729],[510631.1210303323,6651105.3438062705,73.67852490005728],[510631.12204354507,6651105.598008678,73.9262346400573],[510631.12002434925,6651105.091417694,74.28795178605729],[510631.12122777617,6651105.393342453,74.5531495110573],[510631.1235036115,6651105.964321085,74.22367711005731],[510631.122504229,6651105.7135885265,74.7932379580573],[510631.12506517424,6651106.356097667,74.4798902330573],[510631.1238411578,6651106.049007246,75.0064902930573],[510631.1267007531,6651106.766443949,74.69216804205729],[510631.12522529176,6651106.396269136,75.1916991950573],[510631.1283820068,6651107.188249458,74.85928279905731],[510631.1646490596,6651116.287199465,68.7015861260573],[510631.1646490596,6651116.287199465,68.83158612605729],[510631.1266430526,6651106.751967603,75.3481904870573],[510631.13008120254,6651107.614556422,74.98143592105731],[510631.1670788195,6651116.896795843,68.7015861260573],[510631.12808095774,6651107.1127200285,75.47581324605729],[510631.1317724935,6651108.038880172,75.0601106140573],[510631.1295259898,6651107.475260503,75.5749087400573],[510631.13343290304,6651108.455456151,75.09785347305728],[510631.13144278625,6651107.956160753,75.66407339205729],[510631.13332458364,6651108.428280197,75.70684863305729],[510631.16464906896,6651116.287201805,70.53038978605728],[510631.16463095153,6651116.282656379,70.73421107005728],[510631.1670788195,6651116.896795843,70.5303897850573],[510631.14040808566,6651110.205442251,75.09785347305728],[510631.1644805153,6651116.244913819,71.1507903580573],[510631.16699527646,6651116.875835921,70.99598047205728],[510631.16416693234,6651116.1662397515,71.5751174780573],[510631.166734026,6651116.810291452,71.4732514240573],[510631.1636800521,6651116.0440876,72.00142782905729],[510631.1472382642,6651111.919048638,75.09785347305728],[510631.16301396297,6651115.87697417,72.42323668805729],[510631.16628159373,6651116.696781872,71.9561524440573],[510631.14889867377,6651112.335624617,75.0601106140573],[510631.1621678622,6651115.664698048,72.8335862310573],[510631.16581105714,6651116.57873011,72.3178584290573],[510631.1505899647,6651112.759948367,74.98143592105731],[510631.1611466431,6651115.40848696,73.22536592505729],[510631.15228916047,6651113.186255332,74.85928279905731],[510631.1602720787,6651115.189069697,73.50284778505731],[510631.14734657423,6651111.946222252,75.70684863305729],[510631.1652256994,6651116.431871191,72.6756162750573],[510631.1593116174,6651114.948101965,73.76328845805729],[510631.153970414,6651113.6080608405,74.69216804205729],[510631.15827354806,6651114.6876633605,74.00425810405729],[510631.15560599294,6651114.018407123,74.4798902330573],[510631.15716755576,6651114.410183704,74.22367711005731],[510631.16452545085,6651116.256187573,73.02607249005729],[510631.14922837156,6651112.418341696,75.66407339205729],[510631.1637122944,6651116.0521768015,73.3658175170573],[510631.15114516806,6651112.899241946,75.5749087400573],[510631.16279033537,6651115.820868801,73.6914846270573],[510631.1525902001,6651113.261782422,75.47581324605729],[510631.1617657782,6651115.563820231,73.99985343505729],[510631.15402810526,6651113.622534845,75.3481904870573],[510631.1606468086,6651115.283084755,74.28795178605729],[510631.1554458661,6651113.978233313,75.1916991950573],[510631.1594433817,6651114.981159996,74.5531495110573],[510631.15683000005,6651114.325495202,75.0064902930573],[510631.1581669288,6651114.660913923,74.7932379580573],[510643.1356416159,6651103.469133594,68.78188541270163],[510643.1340812753,6651104.0787328165,68.78188541270163],[510643.1340812753,6651104.0787328165,68.91188541270164],[510643.1356416159,6651103.469133594,70.61068907170163],[510643.1340812753,6651104.0787328165,70.61068907170163],[510643.1355879663,6651103.490093613,71.07627975870162],[510643.13403393736,6651104.097226952,71.02150438370163],[510643.13542019675,6651103.555638387,71.55355071070163],[510643.1338859055,6651104.155060575,71.44262581170162],[510643.1351296543,6651103.669148497,72.03645173070163],[510643.13362954446,6651104.255216556,71.86871494670164],[510643.1348274856,6651103.78720081,72.39815771570163],[510643.13325961906,6651104.399740296,72.29362145070162],[510643.1344515812,6651103.934060415,72.75591556170163],[510643.13277391274,6651104.589497688,72.71058815270162],[510643.1340018963,6651104.109744854,73.10637177670164],[510643.13217370637,6651104.823988391,73.11253706970165],[510643.1334797045,6651104.313756577,73.44611680370163],[510643.13288764184,6651104.545065657,73.77178391370163],[510643.1314640363,6651105.101244741,73.49241787170163],[510643.13222969277,6651104.802115428,74.08015272170162],[510643.130865093,6651105.335241968,73.75882418670162],[510643.1302144291,6651105.589445562,74.00653392670162],[510643.1315111141,6651105.082852214,74.36825107270163],[510643.1307382987,6651105.384778381,74.63344879770162],[510643.1292768052,6651105.955759678,74.30397639670163],[510643.1299185876,6651105.705025951,74.87353724470162],[510643.12827400246,6651106.347538088,74.56018951970162],[510643.1290600401,6651106.040446236,75.08678957970163],[510643.1272236682,6651106.757886288,74.77246732870162],[510643.1028540657,6651116.278686242,68.78188541270163],[510643.1028540657,6651116.278686242,68.91188541270164],[510643.12817117845,6651106.387709746,75.27199848170163],[510643.10129372514,6651116.888285465,68.78188541270163],[510643.12614400254,6651107.179693764,74.93958208570163],[510643.1272607223,6651106.743409874,75.42848977370164],[510643.1250528149,6651107.606002719,75.06173520770163],[510643.12633733,6651107.104163982,75.55611253270163],[510643.12396670354,6651108.030328449,75.14040990070163],[510643.12540936074,6651107.466706149,75.65520802670163],[510643.1229004235,6651108.446906372,75.17815275970162],[510643.1241784345,6651107.947608644,75.74437267870162],[510643.1028540597,6651116.278688582,70.61068907270162],[510643.1028656944,6651116.274143135,70.81451035670162],[510643.1229699839,6651108.419730292,75.78714791970162],[510643.10129372514,6651116.888285465,70.61068907170163],[510643.1029623013,6651116.236400399,71.23108964470163],[510643.1184211083,6651110.19690064,75.17815275970162],[510643.10134737473,6651116.867325446,71.07627975870162],[510643.10316367773,6651116.157725964,71.65541676470163],[510643.1015151443,6651116.801780672,71.55355071070163],[510643.10347634193,6651116.035573242,72.08172711570163],[510643.10390409036,6651115.868459034,72.50353597470162],[510643.1018056867,6651116.688270561,72.03645173070163],[510643.11403491156,6651111.910515026,75.17815275970162],[510643.10444743844,6651115.656181919,72.91388551770164],[510643.10210785543,6651116.570218248,72.39815771570163],[510643.1129686315,6651112.32709295,75.14040990070163],[510643.10510324384,6651115.399969636,73.30566521170162],[510643.11188252014,6651112.75141868,75.06173520770163],[510643.1024837598,6651116.423358643,72.75591556170163],[510643.1056648706,6651115.180551348,73.58314707170163],[510643.11079133244,6651113.177727635,74.93958208570163],[510643.1062816586,6651114.939582491,73.84358774470162],[510643.11396535713,6651111.937688768,75.78714791970162],[510643.10694828484,6651114.679142673,74.08455739070162],[510643.1097116668,6651113.599535111,74.77246732870162],[510643.1029334447,6651116.247674204,73.10637177670164],[510643.10765852977,6651114.401661721,74.30397639670163],[510643.1086613325,6651114.009883311,74.56018951970162],[510643.10345563653,6651116.043662482,73.44611680370163],[510643.11275690654,6651112.4098104155,75.74437267870162],[510643.1040476992,6651115.812353401,73.77178391370163],[510643.11152598023,6651112.89071291,75.65520802670163],[510643.10470564826,6651115.55530363,74.08015272170162],[510643.11059801106,6651113.253255077,75.55611253270163],[510643.1054242269,6651115.274566845,74.36825107270163],[510643.10967461875,6651113.614009186,75.42848977370164],[510643.1061970423,6651114.972640678,74.63344879770162],[510643.1087641626,6651113.969709313,75.27199848170163],[510643.1070167535,6651114.652393108,74.87353724470162],[510643.1078753009,6651114.316972823,75.08678957970163],[510648.33434174245,6651103.489797736,68.81246166369984],[510648.33105596085,6651104.099390101,68.81246166369984],[510648.33105596085,6651104.099390101,68.94246166369982],[510648.33434174245,6651103.489797736,70.64126532269984],[510648.33105596085,6651104.099390101,70.64126532269984],[510648.33422876644,6651103.510757518,71.10685600969981],[510648.3309562763,6651104.117884026,71.05208063469982],[510648.3338754756,6651103.576301555,71.58412696169982],[510648.330644549,6651104.175717,71.47320206269981],[510648.33326364844,6651103.689810388,72.06702798169984],[510648.33010470145,6651104.275871852,71.89929119769982],[510648.33262733836,6651103.807861374,72.42873396669982],[510648.3293257086,6651104.420393968,72.32419770169982],[510648.331835755,6651103.9547193255,72.78649181269982],[510648.3283029032,6651104.610149223,72.74116440369981],[510648.3308888039,6651104.130401788,73.13694802769982],[510648.3270389823,6651104.844637289,73.14311332069983],[510648.3297891667,6651104.334411216,73.47669305469984],[510648.328542395,6651104.565717693,73.80236016469982],[510648.3255445516,6651105.12189052,73.52299412269981],[510648.32715687907,6651104.822764572,74.11072897269982],[510648.3242832905,6651105.355885114,73.78940043769981],[510648.3229131157,6651105.610085848,74.03711017769982],[510648.3256436886,6651105.103498199,74.39882732369983],[510648.3240162858,6651105.40542097,74.66402504869981],[510648.3209386576,6651105.976395843,74.33455264769982],[510648.3222901295,6651105.725664936,74.90411349569982],[510648.31882694515,6651106.368169847,74.59076577069982],[510648.26529737655,6651116.299206267,68.81246166369984],[510648.3204821912,6651106.061081448,75.11736583069982],[510648.26529737655,6651116.299206267,68.94246166369982],[510648.3166151402,6651106.778513428,74.80304357969982],[510648.26201159507,6651116.908798631,68.81246166369984],[510648.3186104172,6651106.408341051,75.30257473269982],[510648.3143415691,6651107.200316159,74.97015833669982],[510648.31669316906,6651106.764037178,75.45906602469982],[510648.3120437346,6651107.626620318,75.09231145869983],[510648.31474867975,6651107.124787226,75.58668878369981],[510648.3097565898,6651108.050941274,75.17098615169984],[510648.31279455265,6651107.487325315,75.68578427769984],[510648.30751120637,6651108.46751451,75.20872901069983],[510648.265297364,6651116.299208607,70.64126532369981],[510648.31020245526,6651107.968222399,75.77494892969982],[510649.6749830265,6651103.497513266,68.81994054909241],[510648.2653218642,6651116.294663211,70.84508660769983],[510648.26201159507,6651116.908798631,70.64126532269984],[510648.3076576872,6651108.440338735,75.81772417069982],[510649.6712522881,6651104.10710307,68.81994054909241],[510649.6712522881,6651104.10710307,68.9499405490924],[510648.26552530023,6651116.2569209,71.26166589569984],[510648.26212457096,6651116.887838849,71.10685600969981],[510648.29807861743,6651110.21748909,75.20872901069983],[510648.2659493608,6651116.17824735,71.68599301569982],[510648.26247786183,6651116.822294813,71.58412696169982],[510648.26660777227,6651116.056096002,72.11230336669982],[510648.2675085293,6651115.888983673,72.53411222569983],[510648.2630896891,6651116.708785978,72.06702798169984],[510648.2888421186,6651111.931084196,75.20872901069983],[510649.6749830265,6651103.497513266,70.64874420809241],[510648.2686527175,6651115.676708948,72.94446176869982],[510648.2637259991,6651116.590734993,72.42873396669982],[510648.28659673495,6651112.347657433,75.17098615169984],[510648.27003371925,6651115.420499547,73.33624146269982],[510648.26451758243,6651116.44387704,72.78649181269982],[510649.6712522881,6651104.10710307,70.64874420809241],[510648.2843095903,6651112.771978389,75.09231145869983],[510648.27121639886,6651115.201083728,73.61372332269983],[510649.67485475144,6651103.518472962,71.1143348950924],[510648.27251523745,6651114.960117582,73.87416399569982],[510648.28201175586,6651113.198282547,74.97015833669982],[510648.26546453364,6651116.268194579,73.13694802769982],[510648.2739190259,6651114.6996806925,74.11513364169983],[510648.28869565023,6651111.958257632,75.81772417069982],[510648.2797381846,6651113.6200852785,74.80304357969982],[510648.27541466727,6651114.422202865,74.33455264769982],[510648.2775263798,6651114.03042886,74.59076577069982],[510648.2665641708,6651116.064185151,73.47669305469984],[510649.6711391042,6651104.12559692,71.0595595200924],[510648.2861508822,6651112.430373968,75.77494892969982],[510648.2678109425,6651115.832878673,73.80236016469982],[510649.67445361835,6651103.584016724,71.59160584709242],[510648.2835587848,6651112.911271052,75.68578427769984],[510648.26919645845,6651115.575831794,74.11072897269982],[510648.28160465776,6651113.27380914,75.58668878369981],[510648.27070964884,6651115.295098167,74.39882732369983],[510649.67078516324,6651104.18342965,71.48068094809241],[510648.2796601684,6651113.634559189,75.45906602469982],[510648.27233705163,6651114.993175397,74.66402504869981],[510648.2777429203,6651113.990255317,75.30257473269982],[510648.27406320797,6651114.67293143,74.90411349569982],[510648.27587114624,6651114.337514919,75.11736583069982],[510649.67375893815,6651103.697525079,72.07450686709241],[510649.67017221014,6651104.283584083,71.90677008309241],[510649.67303645966,6651103.81557557,72.43621285209241],[510649.6692877269,6651104.42810559,72.3316765870924],[510649.67213768105,6651103.962432904,72.79397069809241],[510649.6681264144,6651104.617860049,72.74864328909241],[510649.67106249486,6651104.138114629,73.1444269130924],[510649.66669133474,6651104.852347129,73.1505922060924],[510649.669813946,6651104.3421232,73.48417194009241],[510649.6683983378,6651104.573428706,73.8098390500924],[510649.66499452986,6651105.129599195,73.5304730080924],[510649.6668251969,6651104.830474504,74.1182078580924],[510649.6635624702,6651105.363592806,73.79687932309243],[510649.66200674785,6651105.617792473,74.0445890630924],[510649.66510709183,6651105.1112069525,74.4063062090924],[510649.6632593081,6651105.413128455,74.6715039340924],[510649.6597649108,6651105.9841009285,74.34203153309241],[510649.6612993976,6651105.733371076,74.9115923810924],[510649.65736723255,6651106.375873286,74.5982446560924],[510649.5965887496,6651116.306867989,68.81994054909241],[510649.6592466303,6651106.068786178,75.12484471609241],[510649.5965887496,6651116.306867989,68.9499405490924],[510649.65485590755,6651106.786215144,74.81052246509242],[510649.5928580111,6651116.916457793,68.81994054909241],[510649.65712138265,6651106.416044324,75.31005361809243],[510649.65227445186,6651107.208016104,74.97763722209241],[510649.65494450304,6651106.771738955,75.46654491009241],[510649.64966544724,6651107.634318471,75.09979034409241],[510649.65273669304,6651107.132487488,75.5941676690924],[510649.64706858,6651108.058637645,75.17846503709241],[510649.6505179403,6651107.495024054,75.69326316309241],[510649.644519129,6651108.475209132,75.2162078960924],[510649.59658873524,6651116.306870329,70.6487442090924],[510649.647574824,6651107.975919119,75.7824278150924],[510649.5966165533,6651116.302324953,70.8525654930924],[510649.5928580111,6651116.916457793,70.64874420809241],[510649.6446854463,6651108.448033472,75.8252030560924],[510649.5968475383,6651116.2645828,71.26914478109241],[510649.5929862861,6651116.895498098,71.1143348950924],[510649.6338091894,6651110.2251763595,75.2162078960924],[510649.59732902475,6651116.18590958,71.69347190109241],[510649.59338741924,6651116.829954336,71.59160584709242],[510649.5980765976,6651116.063758746,72.1197822520924],[510649.5990993341,6651115.896647119,72.5415911110924],[510649.59408209944,6651116.71644598,72.07450686709241],[510649.6233218942,6651111.938764268,75.2162078960924],[510649.600398467,6651115.684373286,72.95194065409241],[510649.59480457794,6651116.598395491,72.43621285209241],[510649.6207724433,6651112.355335754,75.17846503709241],[510649.60196648247,6651115.42816496,73.3437203480924],[510649.59570335655,6651116.451538155,72.79397069809241],[510649.60330931924,6651115.208750063,73.6212022080924],[510649.61817557603,6651112.7796549285,75.09979034409241],[510649.60478404514,6651114.96778493,73.8816428810924],[510649.61556657136,6651113.205957295,74.97763722209241],[510649.59677854273,6651116.275856432,73.1444269130924],[510649.60637793306,6651114.707349134,74.1226125270924],[510649.61298511573,6651113.627758255,74.81052246509242],[510649.6231555913,6651111.965937588,75.8252030560924],[510649.60807611246,6651114.42987247,74.34203153309241],[510649.6104737907,6651114.038100113,74.5982446560924],[510649.59802709153,6651116.071847861,73.48417194009241],[510649.6202662136,6651112.438051941,75.7824278150924],[510649.59944269975,6651115.840542354,73.8098390500924],[510649.61732309737,6651112.918947006,75.69326316309241],[510649.60101584066,6651115.583496555,74.1182078580924],[510649.6151043445,6651113.281483571,75.5941676690924],[510649.60273394577,6651115.3027641075,74.4063062090924],[510649.61289653456,6651113.642232105,75.46654491009241],[510649.6045817295,6651115.000842605,74.6715039340924],[510649.61071965494,6651113.997926737,75.31005361809243],[510649.60654164,6651114.680599985,74.9115923810924],[510649.60859440727,6651114.345184882,75.12484471609241],[510660.03104468284,6651103.590091781,68.87210162289652],[510660.02387678274,6651104.199650858,68.87210162289652],[510660.02387678274,6651104.199650858,69.0021016228965],[510660.03104468284,6651103.590091781,70.70090528189651],[510660.02387678274,6651104.199650858,70.70090528189651],[510660.03079822694,6651103.6110504195,71.1664959688965],[510660.0236593216,6651104.218143773,71.11172059389651],[510660.0300275265,6651103.676590877,71.64376692089652],[510660.02297929185,6651104.27597359,71.53284202189651],[510660.02869283134,6651103.790093511,72.12666794089651],[510660.0218016197,6651104.376122974,71.95893115689651],[510660.0273047272,6651103.908138051,72.48837392589651],[510660.0201022544,6651104.5206371965,72.3838376608965],[510660.0255778959,6651104.054987984,72.84613177189651],[510660.0178710146,6651104.710382091,72.80080436289651],[510660.0235121314,6651104.230660852,73.1965879868965],[510660.0151137835,6651104.944857352,73.20275327989651],[510660.02111328376,6651104.434659139,73.53633301389651],[510660.01839346334,6651104.665952987,73.86200012389651],[510660.0118536976,6651105.222095443,73.5826340818965],[510660.009102269,6651105.456077259,73.8490403968965],[510660.0153709742,6651104.922985829,74.1703689318965],[510660.0061132462,6651105.710264113,74.0967501368965],[510660.01206996397,6651105.203704126,74.45846728289652],[510660.0018059852,6651106.076554105,74.39419260689651],[510660.00851980096,6651105.505610411,74.7236650078965],[510659.8804250786,6651116.3988008415,68.87210162289652],[510660.0047542079,6651105.82583689,74.9637534548965],[510659.8804250786,6651116.3988008415,69.0021016228965],[510659.9971993053,6651106.468306715,74.6504057298965],[510659.8732571785,6651117.008359918,68.87210162289652],[510660.0008102083,6651106.161235085,75.17700578989651],[510659.99237427465,6651106.878627889,74.86268353889652],[510659.9967269516,6651106.5084757265,75.36221469189653],[510659.9874145015,6651107.300407588,75.02979829589651],[510659.9925444938,6651106.864152429,75.51870598389651],[510659.98240179825,6651107.726688467,75.15195141789651],[510659.9883026095,6651107.22488278,75.6463287428965],[510659.97741241456,6651108.150986253,75.23062611089651],[510659.88042505103,6651116.39880318,70.7009052828965],[510659.9840397004,6651107.587401071,75.74542423689651],[510659.97251413245,6651108.5675367415,75.2683689698965],[510659.8804784981,6651116.394258033,70.9047265668965],[510659.8732571785,6651117.008359918,70.70090528189651],[510659.97838506557,6651108.068271895,75.8345888888965],[510659.8809222916,6651116.356517783,71.32130585489651],[510659.97283367923,6651108.54036245,75.8773641298965],[510659.87350363436,6651116.987401279,71.1664959688965],[510659.8818473756,6651116.27784853,71.74563297489651],[510659.95193703263,6651110.317415762,75.2683689698965],[510659.8742743348,6651116.921860822,71.64376692089652],[510659.8832836939,6651116.155703852,72.1719433258965],[510659.87560902996,6651116.808358188,72.12666794089651],[510659.88524868654,6651115.988600648,72.5937521848965],[510659.8877447217,6651115.776337514,73.00410172789651],[510659.8769971341,6651116.6903136475,72.48837392589651],[510659.93178770127,6651112.030917296,75.2683689698965],[510659.8907573635,6651115.520142104,73.3958814218965],[510659.8787239654,6651116.543463715,72.84613177189651],[510659.9268894192,6651112.447467786,75.23062611089651],[510659.8933373674,6651115.300738267,73.67336328189651],[510659.9219000355,6651112.871765571,75.15195141789651],[510659.89617077104,6651115.0597852785,73.9338039548965],[510659.8807897299,6651116.367790846,73.1965879868965],[510659.8992331217,6651114.79936261,74.17477360089651],[510659.9168873323,6651113.29804645,75.02979829589651],[510659.9024958486,6651114.521899933,74.39419260689651],[510659.9119275591,6651113.71982615,74.86268353889652],[510659.9071025285,6651114.130147324,74.6504057298965],[510659.8831885776,6651116.163792559,73.53633301389651],[510659.9314681821,6651112.058089248,75.8773641298965],[510659.8859083979,6651115.932498712,73.86200012389651],[510659.9259167957,6651112.530179803,75.8345888888965],[510659.88893088716,6651115.67546587,74.1703689318965],[510659.9202621609,6651113.011050627,75.74542423689651],[510659.8922318973,6651115.394747573,74.45846728289652],[510659.91599925177,6651113.373568919,75.6463287428965],[510659.8957820603,6651115.092841287,74.7236650078965],[510659.91175736743,6651113.73429927,75.51870598389651],[510659.89954765333,6651114.772614809,74.9637534548965],[510659.90757490974,6651114.089975973,75.36221469189653],[510659.903491653,6651114.4372166125,75.17700578989651],[510665.5542208707,6651103.663346096,68.89585792190336],[510665.54521983647,6651104.272880859,68.89585792190336],[510665.54521983647,6651104.272880859,69.02585792190335],[510665.5542208707,6651103.663346096,70.72466158090337],[510665.54521983647,6651104.272880859,70.72466158090337],[510665.55391138565,6651103.684303897,71.19025226790335],[510665.54494676145,6651104.291373038,71.13547689290336],[510665.55294358457,6651103.749841741,71.66752321990336],[510665.5440928193,6651104.349200548,71.55659832090335],[510665.55126755167,6651103.86333985,72.15042423990337],[510665.5426139668,6651104.449345936,71.98268745590336],[510665.5495244508,6651103.981379679,72.51213022490336],[510665.54048000224,6651104.593854395,72.40759395990337],[510665.54735599604,6651104.128223756,72.86988807090336],[510665.5376781404,6651104.783591721,72.82456066190335],[510665.5447619284,6651104.303889617,73.22034428590335],[510665.5342157692,6651105.0180576295,73.22650957890335],[510665.54174959444,6651104.507879768,73.56008931290337],[510665.5383342014,6651104.73916439,73.88575642290336],[510665.530121942,6651105.295284663,73.60639038090335],[510665.52666685707,6651105.529257147,73.87279669590336],[510665.5345387343,6651104.99618698,74.19412523090335],[510665.5229134153,6651105.783433863,74.12050643590335],[510665.53039351676,6651105.27689408,74.48222358190336],[510665.5175046061,6651106.149709243,74.41794890590336],[510665.5259354275,6651105.578788322,74.74742130690335],[510665.3650814872,6651116.471544266,68.89585792190336],[510665.3650814872,6651116.471544266,69.02585792190335],[510665.356080453,6651117.081079029,68.89585792190336],[510665.52120681363,6651105.899002029,74.98750975390335],[510665.511719804,6651106.541446228,74.67416202890335],[510665.5162541672,6651106.234386846,75.20076208890337],[510665.50566080975,6651106.9517510375,74.88643983790335],[510665.51112664957,6651106.5816136375,75.38597099090336],[510665.4994326136,6651107.373513913,75.05355459490336],[510665.50587456115,6651106.937276154,75.54246228290336],[510665.493137951,6651107.79977779,75.17570771690336],[510665.50054784823,6651107.297992116,75.67008504190335],[510665.36508145276,6651116.471546603,70.72466158190335],[510665.4868725716,6651108.22405865,75.25438240990336],[510665.36514856847,6651116.467001638,70.92848286590336],[510665.4951947337,6651107.660495948,75.76918053590337],[510665.48072159244,6651108.640592525,75.29212526890335],[510665.356080453,6651117.081079029,70.72466158090337],[510665.3657058586,6651116.429262893,71.34506215390337],[510665.4880939705,6651108.141347594,75.85834518790337],[510665.3563899381,6651117.060121227,71.19025226790335],[510665.48112286074,6651108.613419318,75.90112042890335],[510665.3668675256,6651116.350596778,71.76938927390336],[510665.3573577392,6651116.994583382,71.66752321990336],[510665.4548820611,6651110.390401749,75.29212526890335],[510665.368671171,6651116.228456973,72.19569962490337],[510665.35903377214,6651116.881085275,72.15042423990337],[510665.371138695,6651116.061360433,72.61750848390336],[510665.36077687296,6651116.763045445,72.51213022490336],[510665.3742730716,6651115.849105765,73.02785802690336],[510665.4295796968,6651112.103834938,75.29212526890335],[510665.3780561728,6651115.592920573,73.41963772090337],[510665.3629453277,6651116.616201368,72.86988807090336],[510665.3812959923,6651115.373525488,73.69711958090335],[510665.42342871753,6651112.520368813,75.25438240990336],[510665.36553939537,6651116.440535507,73.22034428590335],[510665.3848540167,6651115.132582111,73.95756025390335],[510665.4171633382,6651112.944649675,75.17570771690336],[510665.3886995396,6651114.87216983,74.19852989990335],[510665.41086867556,6651113.370913551,75.05355459490336],[510665.39279668307,6651114.59471822,74.41794890590336],[510665.4046404794,6651113.792676427,74.88643983790335],[510665.3685517293,6651116.236545356,73.56008931290337],[510665.3985814852,6651114.202981235,74.67416202890335],[510665.429178463,6651112.131005806,75.90112042890335],[510665.37196712237,6651116.005260734,73.88575642290336],[510665.42220735323,6651112.603077531,75.85834518790337],[510665.37576258945,6651115.7482381435,74.19412523090335],[510665.41510659,6651113.0839291755,75.76918053590337],[510665.379907807,6651115.467531043,74.48222358190336],[510665.4097534755,6651113.446433008,75.67008504190335],[510665.3843658962,6651115.165636801,74.74742130690335],[510665.4044267626,6651113.807148971,75.54246228290336],[510665.3890945101,6651114.845423095,74.98750975390335],[510665.3991746742,6651114.162811486,75.38597099090336],[510665.39404715656,6651114.510038278,75.20076208890337],[510669.92389173683,6651103.733073057,68.91265022951784],[510669.9134404153,6651104.342584677,68.91265022951784],[510669.9134404153,6651104.342584677,69.04265022951783],[510669.92389173683,6651103.733073057,70.74145388851784],[510669.9134404153,6651104.342584677,70.74145388851784],[510669.92353238614,6651103.754030063,71.20704457551783],[510669.9131233412,6651104.361076154,71.15226920051784],[510669.9224086487,6651103.819565418,71.68431552751784],[510669.9121318081,6651104.418901469,71.57339062851783],[510669.92046256573,6651103.9330592165,72.16721654751784],[510669.910414676,6651104.519043056,71.99947976351784],[510669.9184386086,6651104.051094566,72.52892253251784],[510669.90793687745,6651104.663546028,72.42438626751783],[510669.9159207626,6651104.197933067,72.88668037851784],[510669.90468356706,6651104.853276151,72.84135296951783],[510669.912908727,6651104.373592258,73.23713659351785],[510669.9006633228,6651105.087733156,73.24330188651783],[510669.90941103204,6651104.577574664,73.57688162051784],[510669.90544533543,6651104.808850504,73.90254873051784],[510669.8959098797,6651105.364949665,73.62318268851784],[510669.891898096,6651105.598913264,73.88958900351784],[510669.9010383256,6651105.065863336,74.21091753851783],[510669.88753988256,6651105.8530803295,74.13729874351785],[510669.89622521185,6651105.34655978,74.49901588951784],[510669.7042773602,6651116.540784936,68.91265022951784],[510669.8812595816,6651106.219341805,74.43474121351784],[510669.8910488151,6651105.64844256,74.76421361451783],[510669.7042773602,6651116.540784936,69.04265022951783],[510669.6938260387,6651117.150296558,68.91265022951784],[510669.8855583056,6651105.968644109,75.00430206151785],[510669.87454270595,6651106.611063915,74.69095433651783],[510669.87980766624,6651106.304016193,75.21755439651784],[510669.8675074592,6651107.021353147,74.90323214551783],[510669.8738539799,6651106.651229801,75.40276329851784],[510669.860275748,6651107.443100009,75.07034690251785],[510669.86775565124,6651107.006878814,75.55925459051784],[510669.8529668608,6651107.869347701,75.19250002451786],[510669.7042773201,6651116.540787275,70.74145388951783],[510669.86157067417,6651107.367581081,75.68687734951783],[510669.84569197515,6651108.293612454,75.27117471751784],[510669.7043552498,6651116.536242481,70.94527517351783],[510669.6938260387,6651117.150296558,70.74145388851784],[510669.85535504174,6651107.730071149,75.78597284351784],[510669.8385499224,6651108.710130515,75.30891757651783],[510669.7050023331,6651116.49850517,71.36185446151784],[510669.84711017134,6651108.210904537,75.87513749551783],[510669.6941853894,6651117.129339551,71.20704457551783],[510669.7063511731,6651116.41984204,71.78618158151784],[510669.83901584474,6651108.682958338,75.91791273651783],[510669.69530912687,6651117.063804195,71.68431552751784],[510669.70844543003,6651116.297706873,72.21249193251784],[510669.80854700884,6651110.459873303,75.30891757651783],[510669.69725520985,6651116.950310396,72.16721654751784],[510669.7113105327,6651116.130616677,72.63430079151783],[510669.69927916693,6651116.832275048,72.52892253251784],[510669.7149499342,6651115.918370069,73.04465033451785],[510669.70179701294,6651116.685436548,72.88668037851784],[510669.71934258577,6651115.662194603,73.43643002851783],[510669.779167813,6651112.173241438,75.30891757651783],[510669.7231044197,6651115.442807847,73.71391188851783],[510669.7720257603,6651112.589759498,75.27117471751784],[510669.7048090485,6651116.509777355,73.23713659351785],[510669.72723572917,6651115.201873618,73.97435256151783],[510669.76475087466,6651113.014024251,75.19250002451786],[510669.73170085996,6651114.941471224,74.21532220751783],[510669.75744198746,6651113.440271944,75.07034690251785],[510669.7364581539,6651114.664030148,74.43474121351784],[510669.7083067435,6651116.305794949,73.57688162051784],[510669.75021027616,6651113.862018806,74.90323214551783],[510669.7431750294,6651114.272308037,74.69095433651783],[510669.7787019307,6651112.200411274,75.91791273651783],[510669.7122724401,6651116.074519108,73.90254873051784],[510669.7166794499,6651115.817506276,74.21091753851783],[510669.77060760424,6651112.672465077,75.87513749551783],[510669.72149256367,6651115.536809834,74.49901588951784],[510669.7623627338,6651113.153298464,75.78597284351784],[510669.7266689604,6651115.2349270545,74.76421361451783],[510669.75614710135,6651113.515788534,75.68687734951783],[510669.7321594699,6651114.914725506,75.00430206151785],[510669.7499621243,6651113.8764908,75.55925459051784],[510669.7379101093,6651114.579353421,75.21755439651784],[510669.7438637956,6651114.232139813,75.40276329851784],[510676.9246202175,6651103.866463508,68.93586572512353],[510676.9118453645,6651104.475930858,68.93586572512353],[510676.9118453645,6651104.475930858,69.06586572512353],[510676.9246202175,6651103.866463508,70.76466938412354],[510676.9118453645,6651104.475930858,70.76466938412354],[510676.9241809761,6651103.887418992,71.23026007112352],[510676.9114577986,6651104.49442099,71.17548469612353],[510676.92280740995,6651103.952949587,71.70753102312354],[510676.9102458284,6651104.552242105,71.59660612412353],[510676.920428675,6651104.066435142,72.19043204312354],[510676.90814694465,6651104.652376419,72.02269525912354],[510676.91795475304,6651104.184461919,72.55213802812354],[510676.9051182834,6651104.796868893,72.44760176312353],[510676.914877141,6651104.331289752,72.90989587412354],[510676.90114169894,6651104.986585236,72.86456846512353],[510676.9111954715,6651104.506936187,73.26035208912353],[510676.89622767654,6651105.221025213,73.26651738212355],[510676.9069201711,6651104.710903775,73.60009711612354],[510676.89041745075,6651105.498221584,73.64639818412354],[510676.90207282326,6651104.942162817,73.92576422612353],[510676.88551376964,6651105.73216819,73.91280449912352],[510676.8966860496,6651105.199156981,74.23413303412353],[510676.8801866408,6651105.9863167945,74.16051423912354],[510676.6561813048,6651116.673245096,68.93586572512353],[510676.89080288727,6651105.479833035,74.52223138512353],[510676.6561813048,6651116.673245096,69.06586572512353],[510676.64340645174,6651117.282712445,68.93586572512353],[510676.87251010706,6651106.352551666,74.45795670912354],[510676.88447567704,6651105.781693889,74.78742911012354],[510676.8777645209,6651106.101872179,75.02751755712355],[510676.86429993977,6651106.744245323,74.71416983212355],[510676.8707354028,6651106.437219903,75.24076989212354],[510676.85570062115,6651107.154504753,74.92644764112353],[510676.8634580965,6651106.784408291,75.42597879412354],[510676.8468611602,6651107.576220981,75.09356239812355],[510676.65618125576,6651116.673247434,70.76466938512353],[510676.85600399104,6651107.140031472,75.58247008612354],[510676.8379273656,6651108.002437714,75.21571552012355],[510676.65627651074,6651116.66870297,70.96849066912353],[510676.64340645174,6651117.282712445,70.76466938412354],[510676.84844397375,6651107.500707538,75.71009284512353],[510676.8290351318,6651108.426671649,75.29439021312353],[510676.6570674532,6651116.630968399,71.38506995712353],[510676.84084648546,6651107.863171278,75.80918833912354],[510676.8203052621,6651108.843159456,75.33213307212353],[510676.64384569303,6651117.26175696,71.23026007112352],[510676.6587161665,6651116.552310984,71.80939707712353],[510676.8307686204,6651108.343969739,75.89835299112353],[510676.6452192592,6651117.196226364,71.70753102312354],[510676.8208747682,6651108.815989254,75.94112823212353],[510676.6612760173,6651116.430184687,72.23570742812353],[510676.7836321189,6651110.592775151,75.33213307212353],[510676.6475979941,6651117.082740809,72.19043204312354],[510676.6647780878,6651116.263106628,72.65751628712353],[510676.6500719161,6651116.9647140335,72.55213802812354],[510676.66922659904,6651116.0508754365,73.06786583012355],[510676.65314952814,6651116.8178862,72.90989587412354],[510676.6745958222,6651115.794718578,73.45964552412353],[510676.747721358,6651112.306018835,75.33213307212353],[510676.67919398483,6651115.575347758,73.73712738412355],[510676.6568311977,6651116.642239766,73.26035208912353],[510676.7389914884,6651112.722506641,75.29439021312353],[510676.68424376444,6651115.334431029,73.99756805712353],[510676.68970158044,6651115.07404755,74.23853770312353],[510676.73009925446,6651113.146740579,75.21571552012355],[510676.661106498,6651116.438272176,73.60009711612354],[510676.6955165131,6651114.7966266265,74.45795670912354],[510676.72116545995,6651113.57295731,75.09356239812355],[510676.7037266803,6651114.404932967,74.71416983212355],[510676.712325999,6651113.994673539,74.92644764112353],[510676.6659538459,6651116.207013135,73.92576422612353],[510676.74715190096,6651112.333186698,75.94112823212353],[510676.67134061956,6651115.950018971,74.23413303412353],[510676.73725804867,6651112.805206212,75.89835299112353],[510676.6772237819,6651115.669342916,74.52223138512353],[510676.72718018363,6651113.286004675,75.80918833912354],[510676.6835509921,6651115.367482063,74.78742911012354],[510676.7195826955,6651113.648468414,75.71009284512353],[510676.69026214833,6651115.047303773,75.02751755712355],[510676.7120226781,6651114.009144481,75.58247008612354],[510676.6972912663,6651114.711956049,75.24076989212354],[510676.70456857275,6651114.364767661,75.42597879412354],[510682.7717159758,6651103.998336429,68.95177490066979],[510682.7570004802,6651104.607760011,68.95177490066979],[510682.7570004802,6651104.607760011,69.0817749006698],[510682.7717159758,6651103.998336429,70.78057855966979],[510682.7570004802,6651104.607760011,70.78057855966979],[510682.77121000877,6651104.019290409,71.24616924666978],[510682.75655403873,6651104.626248816,71.19139387166979],[510682.7696277826,6651104.084816299,71.72344019866979],[510682.7551579568,6651104.684065778,71.61251529966978],[510682.76688769134,6651104.198293704,72.20634121866979],[510682.75274022925,6651104.7841929,72.03860443466981],[510682.76403795293,6651104.316312004,72.56804720366979],[510682.7492514806,6651104.928675001,72.46351093866978],[510682.76049281744,6651104.463129293,72.92580504966979],[510682.7446708086,6651105.118377716,72.88047764066978],[510682.7562518612,6651104.638763113,73.2762612646698],[510682.7390102914,6651105.352800856,73.2824265576698],[510682.75132709515,6651104.842716054,73.61600629166979],[510682.7323174276,6651105.629977323,73.66230735966978],[510682.74574338115,6651105.073958489,73.94167340166979],[510682.7266688227,6651105.863907128,73.92871367466978],[510682.73953829653,6651105.330934196,74.25004220966979],[510682.4624982014,6651116.804198307,68.95177490066979],[510682.4624982014,6651116.804198307,69.0817749006698],[510682.7205324437,6651106.118037479,74.17642341466978],[510682.7327614163,6651105.611590094,74.53814056066979],[510682.4477827058,6651117.413621889,68.95177490066979],[510682.711689759,6651106.484246051,74.47386588466979],[510682.7254730324,6651105.913429269,74.80333828566978],[510682.70223237574,6651106.8759115795,74.73007900766979],[510682.7177423767,6651106.233584566,75.04342673266979],[510682.7096454574,6651106.568908208,75.25667906766981],[510682.69232672494,6651107.286141547,74.94235681666979],[510682.70126264717,6651106.916071664,75.44188796966979],[510682.46249814495,6651116.804200646,70.78057856066978],[510682.68214445136,6651107.70782749,75.1094715736698],[510682.4626078702,6651116.799656509,70.98439984466978],[510682.4477827058,6651117.413621889,70.78057855966979],[510682.6926761801,6651107.271669304,75.5983792616698],[510682.67185351375,6651108.134013615,75.2316246956698],[510682.68396771187,6651107.632319469,75.7260020206698],[510682.46351896564,6651116.761924649,71.40097913266979],[510682.6616104506,6651108.558217084,75.31029938866979],[510682.4482886728,6651117.392667909,71.24616924666978],[510682.6515544164,6651108.97467498,75.34804224766978],[510682.6752160805,6651107.994757179,75.82509751466979],[510682.4654181369,6651116.683272881,71.82530625266979],[510682.6636072755,6651108.475521113,75.9142621666698],[510682.4498708989,6651117.327142019,71.72344019866979],[510682.46836685756,6651116.561155355,72.2516166036698],[510682.65221043676,6651108.94750673,75.95703740766979],[510682.45261099027,6651117.2136646155,72.20634121866979],[510682.6093102142,6651110.724165028,75.34804224766978],[510682.4724009316,6651116.3940892955,72.67342546266978],[510682.45546072855,6651117.095646315,72.56804720366979],[510682.4775252212,6651116.181873344,73.08377500566979],[510682.45900586416,6651116.948829024,72.92580504966979],[510682.4837100891,6651115.925734882,73.4755546996698],[510682.48900676396,6651115.706379815,73.7530365596698],[510682.46324682026,6651116.773195205,73.2762612646698],[510682.56794420857,6651112.437285677,75.34804224766978],[510682.49482366134,6651115.465480388,74.01347723266979],[510682.55788817455,6651112.853743574,75.31029938866979],[510682.50111058046,6651115.205115609,74.25444687866978],[510682.46817158634,6651116.569242263,73.61600629166979],[510682.5476451112,6651113.277947045,75.2316246956698],[510682.50780886604,6651114.927714606,74.47386588466979],[510682.5373541738,6651113.704133168,75.1094715736698],[510682.5172662492,6651114.536049078,74.73007900766979],[510682.5271719002,6651114.12581911,74.94235681666979],[510682.47375530045,6651116.337999829,73.94167340166979],[510682.5672882447,6651112.464451589,75.95703740766979],[510682.47996038507,6651116.081024122,74.25004220966979],[510682.48673726525,6651115.800368224,74.53814056066979],[510682.5558914061,6651112.936437205,75.9142621666698],[510682.4940256492,6651115.49852905,74.80333828566978],[510682.5442826011,6651113.417201139,75.82509751466979],[510682.5017563049,6651115.178373751,75.04342673266979],[510682.53553096973,6651113.779638848,75.7260020206698],[510682.5098532241,6651114.84305011,75.25667906766981],[510682.5268225015,6651114.140289015,75.5983792616698],[510682.51823603443,6651114.4958866555,75.44188796966979],[510690.1689726671,6651104.19186548,68.96736160139059],[510690.1518020329,6651104.801224829,68.96736160139059],[510690.1518020329,6651104.801224829,69.09736160139059],[510690.1689726671,6651104.19186548,70.79616526039061],[510690.1518020329,6651104.801224829,70.79616526039061],[510690.16838228446,6651104.212817251,71.26175594739058],[510690.15128110704,6651104.819711686,71.20698057239059],[510690.16653607914,6651104.278336233,71.7390268993906],[510690.1496521023,6651104.877522553,71.62810200039058],[510690.16333882994,6651104.391801679,72.22192791939061],[510690.14683100017,6651104.977639122,72.0541911353906],[510690.16001364024,6651104.509807539,72.5836339043906],[510690.1427601874,6651105.122105994,72.4790976393906],[510690.15587703296,6651104.6566093555,72.9413917503906],[510690.13741527445,6651105.311788716,72.89606434139058],[510690.15092851414,6651104.832224664,73.29184796539059],[510690.13081035455,6651105.546187148,73.2980132583906],[510690.1451820983,6651105.0361561095,73.63159299239061],[510690.1230008509,6651105.823334401,73.67789406039059],[510690.1386667954,6651105.26737417,73.95726010239059],[510689.8081648865,6651116.996377645,68.96736160139059],[510690.1164098307,6651106.057239551,73.9443003753906],[510689.8081648865,6651116.996377645,69.09736160139059],[510690.1314264522,6651105.524322793,74.26562891039059],[510689.7909942523,6651117.605736995,68.96736160139059],[510690.10924965603,6651106.311343118,74.19201011539059],[510690.12351891474,6651105.80494911,74.5537272613906],[510690.0989316545,6651106.677513091,74.4894525853906],[510690.1150145342,6651106.106756472,74.81892498639058],[510690.087896398,6651107.06913734,74.74566570839059],[510690.1059940932,6651106.426878026,75.05901343339059],[510690.0965462809,6651106.762166326,75.2722657683906],[510690.0763380847,6651107.479324068,74.95794351739059],[510689.8081648206,6651116.996379984,70.79616526139058],[510689.80829285254,6651116.991836326,70.9999865453906],[510690.0867648795,6651107.10929319,75.4574746703906],[510689.7909942523,6651117.605736995,70.79616526039061],[510690.06445699686,6651107.900965568,75.1250582743906],[510690.07674584317,6651107.464853351,75.6139659623906],[510690.0524491156,6651108.327106771,75.2472113963906],[510689.80935595545,6651116.954108442,71.4165658333906],[510689.7915846349,6651117.584785224,71.26175594739058],[510690.0404970959,6651108.751265531,75.32588608939061],[510690.06658445083,6651107.825465506,75.74158872139058],[510689.8115719851,6651116.875464965,71.8408929533906],[510690.0287633094,6651109.167679534,75.3636289483906],[510690.05637269415,6651108.187865014,75.84068421539061],[510689.7934308403,6651117.51926624,71.7390268993906],[510689.8150126714,6651116.75336031,72.26720330439059],[510690.04282707185,6651108.668578276,75.92984886739059],[510689.79662808945,6651117.405800796,72.22192791939061],[510690.0295287805,6651109.140514147,75.97262410839059],[510689.8197197918,6651116.586311859,72.6890121633906],[510689.9794710692,6651110.9169851905,75.3636289483906],[510689.79995327914,6651117.2877949355,72.5836339043906],[510689.82569901977,6651116.374118274,73.0993617063906],[510689.8040898864,6651117.140993119,72.9413917503906],[510689.8329157733,6651116.118006809,73.49114140039059],[510689.80903840525,6651116.965377811,73.29184796539059],[510689.8390961473,6651115.898674862,73.7686232603906],[510689.9312035441,6651112.62992528,75.3636289483906],[510689.84588353796,6651115.657800825,74.02906393339059],[510689.81478482106,6651116.761446366,73.63159299239061],[510689.85321936896,6651115.397463486,74.2700335793906],[510689.9194697576,6651113.046339281,75.32588608939061],[510689.861035199,6651115.120091722,74.4894525853906],[510689.9075177379,6651113.470498042,75.2472113963906],[510689.87207045546,6651114.728467474,74.74566570839059],[510689.89550985664,6651113.8966392465,75.1250582743906],[510689.821300124,6651116.530228306,73.95726010239059],[510689.88362876873,6651114.318280744,74.95794351739059],[510689.8285404672,6651116.273279681,74.26562891039059],[510689.9304381389,6651112.657088327,75.97262410839059],[510689.83644800464,6651115.992653363,74.5537272613906],[510689.9171398475,6651113.129024197,75.92984886739059],[510689.8449523852,6651115.690846002,74.81892498639058],[510689.90359422524,6651113.60973746,75.84068421539061],[510689.8539728262,6651115.37072445,75.05901343339059],[510689.89338246855,6651113.97213697,75.74158872139058],[510689.8634206385,6651115.035436149,75.2722657683906],[510689.88322107634,6651114.332749123,75.6139659623906],[510689.8732020399,6651114.688309285,75.4574746703906],[510693.8149386678,6651104.298225386,68.97317771938432],[510693.7965579429,6651104.907549433,68.97317771938432],[510693.7965579429,6651104.907549433,69.1031777193843],[510693.8149386678,6651104.298225386,70.80198137838431],[510693.7965579429,6651104.907549433,70.80198137838431],[510693.8143066783,6651104.319175944,71.2675720653843],[510693.796000305,6651104.92603522,71.21279669038431],[510693.8123303626,6651104.38469113,71.74484301738433],[510693.7942564971,6651104.983842739,71.63391811838432],[510693.8089077892,6651104.498150002,72.22774403738431],[510693.79123657936,6651105.083953507,72.06000725338431],[510693.8053482585,6651104.616149026,72.58945002238431],[510693.7868788784,6651105.22841201,72.4849137573843],[510693.80092012626,6651104.762942339,72.94720786838431],[510693.78115728573,6651105.418083744,72.90188045938432],[510693.7956228634,6651104.9385474725,73.2976640833843],[510693.7740868878,6651105.6524685975,73.3038293763843],[510693.7894714721,6651105.142467104,73.63740911038431],[510693.7657270137,6651105.9295997955,73.6837101783843],[510693.7824970068,6651105.37367177,73.96307622038431],[510693.42870316224,6651117.1019957755,68.97317771938432],[510693.42870316224,6651117.1019957755,69.1031777193843],[510693.7586714951,6651106.163491393,73.95011649338433],[510693.41032243724,6651117.711319824,68.97317771938432],[510693.7747464045,6651105.630605509,74.2714450283843],[510693.7510067111,6651106.417580241,74.1978262333843],[510693.7662815879,6651105.911215569,74.55954337938432],[510693.73996155435,6651106.783729001,74.49526870338431],[510693.7571778659,6651106.213005447,74.8247411043843],[510693.7281485943,6651107.1753305625,74.7514818263843],[510693.7475217143,6651106.533108455,75.0648295513843],[510693.42870309163,6651117.101998114,70.8019813793843],[510693.7157757155,6651107.58549353,74.96375963538432],[510693.7374080728,6651106.868377331,75.27808188638431],[510693.4288401466,6651117.09745472,71.0058026633843],[510693.41032243724,6651117.711319824,70.80198137838431],[510693.72693733266,6651107.215484087,75.46329078838433],[510693.7030573146,6651108.007110601,75.13087439238431],[510693.4299781711,6651117.059729021,71.42238195138431],[510693.7162122104,6651107.5710236505,75.61978208038431],[510693.6902031847,6651108.433227119,75.25302751438431],[510693.4109544268,6651117.690369266,71.2675720653843],[510693.6774088532,6651108.857361308,75.33170220738431],[510693.7053346998,6651107.931614913,75.7474048393843],[510693.43235037423,6651116.9810901,71.84670907138431],[510693.4129307424,6651117.624854079,71.74484301738433],[510693.66484813474,6651109.273751187,75.3694450663843],[510693.6944032752,6651108.293993428,75.84650033338431],[510693.43603354093,6651116.858992517,72.27301942238431],[510693.6799030329,6651108.774678842,75.9356649853843],[510693.4163533159,6651117.511395209,72.22774403738431],[510693.441072393,6651116.691953744,72.6948282813843],[510693.6656675519,6651109.246587373,75.97844022638431],[510693.41991284647,6651117.393396183,72.58945002238431],[510693.6120820515,6651111.022955503,75.3694450663843],[510693.4474730036,6651116.479772453,73.10517782438431],[510693.42434097873,6651117.2466028705,72.94720786838431],[510693.4551983539,6651116.223675824,73.4969575183843],[510693.4296382417,6651117.070997736,73.2976640833843],[510693.4618142862,6651116.004356583,73.7744393783843],[510693.46908001445,6651115.7634964995,74.0348800513843],[510693.5604128998,6651112.735796362,75.3694450663843],[510693.435789633,6651116.867078106,73.63740911038431],[510693.4769328339,6651115.503174243,74.27584969738432],[510693.54785218136,6651113.152186241,75.33170220738431],[510693.48529948015,6651115.2258185465,74.49526870338431],[510693.53505784983,6651113.576320428,75.25302751438431],[510693.4427640982,6651116.63587344,73.96307622038431],[510693.4971124401,6651114.834216987,74.7514818263843],[510693.5222037198,6651114.002436946,75.13087439238431],[510693.5094853191,6651114.424054019,74.96375963538432],[510693.45051470055,6651116.3789397,74.2714450283843],[510693.5595935532,6651112.762957836,75.97844022638431],[510693.4589795171,6651116.098329641,74.55954337938432],[510693.4680832391,6651115.796539762,74.8247411043843],[510693.5453580722,6651113.234866366,75.9356649853843],[510693.4777393907,6651115.476436754,75.0648295513843],[510693.5308578298,6651113.7155517815,75.84650033338431],[510693.48785303225,6651115.141167878,75.27808188638431],[510693.51992640534,6651114.077930296,75.7474048393843],[510693.49832377234,6651114.794061122,75.46329078838433],[510693.5090488947,6651114.438521558,75.61978208038431],[510699.9853135196,6651104.494739295,68.98021260000013],[510699.96488485625,6651105.103998121,68.98021260000013],[510699.96488485625,6651105.103998121,69.11021260000012],[510699.9853135196,6651104.494739295,70.80901625900015],[510699.96488485625,6651105.103998121,70.80901625900015],[510699.9846111152,6651104.51568761,71.27460694600012],[510699.96426508774,6651105.122481928,71.21983157100013],[510699.98241460306,6651104.581195785,71.75187789800013],[510699.9623269887,6651105.18028326,71.64095299900012],[510699.97861069423,6651104.694642511,72.23477891800015],[510699.95897059864,6651105.280383312,72.06704213400013],[510699.9746545689,6651104.812628905,72.59648490300013],[510699.9541273726,6651105.424826352,72.49194863800014],[510699.9697330642,6651104.9594065035,72.95424274900013],[510699.9477682932,6651105.6144777825,72.90891534000012],[510699.96384559234,6651105.134992841,73.30469896400012],[510699.93991012766,6651105.848837548,73.31086425700013],[510699.9570088271,6651105.338890645,73.64444399100014],[510699.5560445367,6651117.297139156,68.98021260000013],[510699.5560445367,6651117.297139156,69.11021260000012],[510699.93061881553,6651106.12593908,73.69074505900012],[510699.94925728295,6651105.570070563,73.97011110100013],[510699.53561587346,6651117.906397982,68.98021260000013],[510699.9227771871,6651106.359805644,73.95715137400013],[510699.9406431262,6651105.8269767985,74.27847990900013],[510699.9142584104,6651106.613867291,74.20486111400012],[510699.9312351791,6651106.107556822,74.56657826000014],[510699.9019826275,6651106.979976861,74.50230358400013],[510699.9211171412,6651106.409314396,74.83177598500012],[510699.8888534946,6651107.371536504,74.75851670700013],[510699.9103851233,6651106.729383141,75.07186443200013],[510699.5560444584,6651117.297141493,70.80901626000012],[510699.55619678367,6651117.292598586,71.01283754400013],[510699.53561587346,6651117.906397982,70.80901625900015],[510699.87510205776,6651107.781655566,74.97079451600013],[510699.8991446429,6651107.064616129,75.28511676700013],[510699.55746160424,6651117.254876926,71.42941683200014],[510699.86096660176,6651108.203227508,75.13790927300013],[510699.88750727684,6651107.411685729,75.47032566900013],[510699.53631827777,6651117.8854496665,71.27460694600012],[510699.8466802941,6651108.629298414,75.26006239500013],[510699.8755871859,6651107.767187236,75.62681696100013],[510699.5600981128,6651117.176246421,71.85374395200013],[510699.53851479,6651117.819941492,71.75187789800013],[510699.83246044745,6651109.053387202,75.33873708800014],[510699.8634977279,6651108.127739902,75.75443972000012],[510699.56419164955,6651117.054161909,72.28005430300013],[510699.81850024237,6651109.469732512,75.37647994700013],[510699.8513483491,6651108.490079626,75.85353521400015],[510699.54231869883,6651117.706494765,72.23477891800015],[510699.56979191897,6651116.887141016,72.70186316200014],[510699.8352325228,6651108.9707135875,75.94269986600013],[510699.5462748242,6651117.588508373,72.59648490300013],[510699.81941095716,6651109.442571606,75.98547510700013],[510699.57690567104,6651116.674982437,73.11221270500013],[510699.7598550827,6651111.218749591,75.37647994700013],[510699.55119632883,6651117.441730773,72.95424274900013],[510699.5854917621,6651116.418913221,73.50399239900013],[510699.5570838006,6651117.266144436,73.30469896400012],[510699.5928448265,6651116.199617455,73.78147425900013],[510699.60092008556,6651115.958783154,74.04191493200013],[510699.56392056594,6651117.062246632,73.64444399100014],[510699.70242907223,6651112.931407105,75.37647994700013],[510699.60964784835,6651115.698488763,74.28288457800014],[510699.6884688672,6651113.347752413,75.33873708800014],[510699.61894668714,6651115.421162756,74.50230358400013],[510699.5716721101,6651116.831066714,73.97011110100013],[510699.6742490205,6651113.771841201,75.26006239500013],[510699.63207582006,6651115.029603112,74.75851670700013],[510699.6599627128,6651114.197912107,75.13790927300013],[510699.6458272569,6651114.619484049,74.97079451600013],[510699.5802862668,6651116.574160478,74.27847990900013],[510699.589694214,6651116.293580454,74.56657826000014],[510699.7015184359,6651112.958565671,75.98547510700013],[510699.59981225186,6651115.99182288,74.83177598500012],[510699.68569687015,6651113.430423689,75.94269986600013],[510699.6105442698,6651115.671754136,75.07186443200013],[510699.66958104394,6651113.91105765,75.85353521400015],[510699.6217847501,6651115.336521149,75.28511676700013],[510699.65743166517,6651114.273397376,75.75443972000012],[510699.6334221162,6651114.989451547,75.47032566900013],[510699.64534220716,6651114.633950041,75.62681696100013],[510710.4077648801,6651104.8738347655,68.98407466471348],[510710.3838770205,6651105.48296777,68.98407466471348],[510710.3838770205,6651105.48296777,69.11407466471347],[510710.4077648801,6651104.8738347655,70.81287832371348],[510710.3838770205,6651105.48296777,70.81287832371348],[510710.7005707575,6651104.885340882,68.9840376056788],[510710.4069435372,6651104.894778755,71.27846901071347],[510710.6765857161,6651105.494470069,68.9840376056788],[510710.3831523062,6651105.501447761,71.22369363571347],[510710.6765857161,6651105.494470069,69.11403760567879],[510710.4043750885,6651104.960273401,71.75573996271348],[510710.3808860278,6651105.559237155,71.64481506371347],[510710.39992706187,6651105.073696698,72.23864098271348],[510710.3769612984,6651105.659316535,72.07090419871348],[510710.39530104364,6651105.191658726,72.60034696771348],[510710.3712979664,6651105.803729745,72.49581070271348],[510710.7005707575,6651104.885340882,70.8128412646788],[510710.389546178,6651105.338406014,72.95810481371348],[510710.6765857161,6651105.494470069,70.8128412646788],[510710.3638621007,6651105.993342011,72.91277740471347],[510710.69974607317,6651104.906284741,71.2784319516788],[510710.38266177743,6651105.51395609,73.30856102871347],[510710.67585805344,6651105.512949944,71.2236565766788],[510709.90580755426,6651117.6735907355,68.98407466471348],[510709.90580755426,6651117.6735907355,69.11407466471347],[510710.3546733078,6651106.227653377,73.31472632171347],[510709.88191969466,6651118.282723741,68.98407466471348],[510710.6971671753,6651104.971778976,71.7557029036788],[510710.3746673391,6651105.717811785,73.64830605571348],[510710.6735825553,6651105.570738974,71.64477800467878],[510710.34380869294,6651106.504697682,73.69460712371347],[510710.3656032218,6651105.948943961,73.97397316571347],[510710.692701053,6651105.085201563,72.2386039236788],[510710.6696418591,6651105.670817729,72.0708671396788],[510710.3346392375,6651106.73851595,73.96101343871348],[510710.3555304255,6651106.205797142,74.28234197371347],[510710.688056215,6651105.203162851,72.6003099086788],[510710.6639554872,6651105.815230032,72.49577364367879],[510710.32467797195,6651106.9925251305,74.20872317871347],[510710.34452942567,6651106.486319222,74.57044032471347],[510710.68227793707,6651105.349909219,72.9580677546788],[510710.3103235241,6651107.358559091,74.50616564871348],[510710.65648937057,6651106.00484111,72.91274034567878],[510709.90580746264,6651117.673593073,70.81287832471347],[510710.33269809507,6651106.788014479,74.83563804971347],[510710.6753655291,6651105.525458194,73.30852396967879],[510709.9059855812,6651117.669051103,71.01669960871347],[510709.88191969466,6651118.282723741,70.81287832371348],[510710.1965713426,6651117.685016608,68.9840376056788],[510710.29497122817,6651107.750037872,74.76237877171347],[510710.320148819,6651107.108017123,75.07572649671347],[510710.1965713426,6651117.685016608,69.11403760567879],[510710.64726319537,6651106.239151007,73.3146892626788],[510710.17258630117,6651118.294145795,68.9840376056788],[510710.6673385674,6651105.729312612,73.6482689966788],[510709.90746457456,6651117.631337234,71.43327889671347],[510709.8827410376,6651118.261779752,71.27846901071347],[510710.2788912533,6651108.160072238,74.97465658071347],[510710.3070049822,6651107.443180881,75.2889788317135],[510710.63635438046,6651106.516193576,73.69457006467879],[510709.91054752446,6651117.552722968,71.85760601671348],[510710.658237575,6651105.96044334,73.9739361066788],[510710.2623622332,6651108.581557119,75.14177133771348],[510710.2933970547,6651107.790178806,75.47418773371348],[510709.8853094863,6651118.196285105,71.75573996271348],[510710.62714762136,6651106.750010377,73.96097637967878],[510710.24565681745,6651109.007540036,75.26392445971348],[510710.27945852856,6651108.145606897,75.63067902571348],[510709.91533422197,6651117.430663668,72.28391636771349],[510710.64812379994,6651106.217294909,74.28230491467879],[510710.2290291166,6651109.431541244,75.34259915271348],[510709.88975751295,6651118.082861807,72.23864098271348],[510710.2653219562,6651108.5060851015,75.75830178471347],[510710.61714583077,6651107.004017965,74.20868611967879],[510710.2127050227,6651109.847800571,75.38034201171347],[510709.921882788,6651117.263677267,72.70572522671348],[510710.6370780453,6651106.49781523,74.57040326567879],[510710.2511153167,6651108.868349999,75.85739727871349],[510709.8943835311,6651117.96489978,72.60034696771348],[510710.6027329855,6651107.370049632,74.50612858967881],[510709.93020111544,6651117.051562501,73.11607476971348],[510710.2322705891,6651109.348884702,75.94656193071349],[510710.19657125056,6651117.685018945,70.8128412656788],[510710.62519858184,6651106.799508596,74.8356009906788],[510709.90013839677,6651117.818152492,72.95810481371348],[510710.2137699493,6651109.820645273,75.98933717171347],[510710.1967500939,6651117.680477004,71.01666254967878],[510710.17258630117,6651118.294145795,70.8128412646788],[510710.1441294474,6651111.596456451,75.38034201171347],[510709.94024109386,6651116.795546168,73.50785446371349],[510710.5873182326,6651107.761525957,74.7623417126788],[510709.9070227973,6651117.642602418,73.30856102871347],[510710.61259825213,6651107.119509234,75.0756894376788],[510709.9488392565,6651116.57629569,73.78533632371347],[510710.19823510404,6651117.64276337,71.43324183767879],[510709.9582819034,6651116.335511125,74.04577699671347],[510709.9150172357,6651117.4387467215,73.64830605571348],[510710.1734109855,6651118.273201936,71.2784319516788],[510710.57117284025,6651108.171557753,74.97461952167879],[510710.5994009429,6651107.45467089,75.2889417726788],[510709.9684875428,6651116.075270488,74.28674664271347],[510710.07697946037,6651113.308760275,75.38034201171347],[510709.92408135295,6651117.207614545,73.97397316571347],[510709.97936095897,6651115.798001753,74.50616564871348],[510710.06065536645,6651113.725019602,75.34259915271348],[510710.2013305962,6651117.564149599,71.85756895767881],[510709.99471325486,6651115.406522973,74.76237877171347],[510710.554576576,6651108.593039993,75.14173427867881],[510710.04402766563,6651114.149020809,75.26392445971348],[510710.585737655,6651107.80166664,75.4741506746788],[510710.0107932298,6651114.996488606,74.97465658071347],[510710.02732224984,6651114.575003725,75.14177133771348],[510709.93415414926,6651116.950761364,74.28234197371347],[510710.17598988337,6651118.2077077,71.7557029036788],[510709.9451551491,6651116.670239285,74.57044032471347],[510710.5378031984,6651109.019020237,75.26388740067881],[510710.5717424233,6651108.157092503,75.6306419666788],[510710.2061367672,6651117.442091064,72.28387930867879],[510709.9569864797,6651116.368544029,74.83563804971347],[510710.0759146255,6651113.3359132325,75.98933717171347],[510710.52110785194,6651109.443018787,75.3425620936788],[510709.96953575587,6651116.048541383,75.07572649671347],[510710.1804560056,6651118.094285113,72.2386039236788],[510710.5575483399,6651108.517568449,75.75826472567879],[510710.05741398566,6651113.807673804,75.94656193071349],[510709.9826795926,6651115.713377625,75.2889788317135],[510710.03856925806,6651114.288208507,75.85739727871349],[510709.99628752004,6651115.3663797,75.47418773371348],[510710.50471734744,6651109.859275505,75.38030495267878],[510710.02436261857,6651114.650473405,75.75830178471347],[510710.0102260462,6651115.010951609,75.63067902571348],[510710.21271197445,6651117.275105708,72.70568816767879],[510710.5432839042,6651108.879831074,75.8573602196788],[510710.18510084366,6651117.976323825,72.6003099086788],[510710.22106414294,6651117.062992273,73.1160377106788],[510710.52436251147,6651109.3603627635,75.94652487167879],[510710.19087912154,6651117.829577458,72.9580677546788],[510710.50578660634,6651109.832120378,75.98930011267879],[510710.4358627894,6651111.607920422,75.38030495267878],[510710.23114496656,6651116.806977544,73.50781740467879],[510710.1977915296,6651117.654028483,73.30852396967879],[510710.2397781086,6651116.587728441,73.7852992646788],[510710.24925917067,6651116.346945386,74.0457399376788],[510710.2058184913,6651117.450174065,73.6482689966788],[510710.2595063292,6651116.08670638,74.28670958367879],[510710.3684396192,6651113.320213512,75.38030495267878],[510710.2149194837,6651117.219043339,73.9739361066788],[510710.2704239811,6651115.809439384,74.50612858967881],[510710.3520491147,6651113.736470228,75.3425620936788],[510710.28583873407,6651115.417963057,74.7623417126788],[510710.3353537682,6651114.160468778,75.26388740067881],[510710.30198412633,6651115.007931261,74.97461952167879],[510710.3185803906,6651114.586449023,75.14173427867881],[510710.2250332587,6651116.962191767,74.28230491467879],[510710.2360790134,6651116.681671446,74.57040326567879],[510710.2479584768,6651116.379978082,74.8356009906788],[510710.3673704523,6651113.347366299,75.98930011267879],[510710.26055880653,6651116.059977442,75.0756894376788],[510710.3487945472,6651113.8191239135,75.94652487167879],[510710.27375611576,6651115.724815786,75.2889417726788],[510710.32987315446,6651114.299655603,75.8573602196788],[510710.28741940367,6651115.377820036,75.4741506746788],[510710.3156087188,6651114.6619182285,75.75826472567879],[510710.3014146353,6651115.022394176,75.6306419666788],[510717.1935003072,6651105.152511052,68.98117101989592],[510717.16736027185,6651105.7615515655,68.98117101989592],[510717.16736027185,6651105.7615515655,69.11117101989592],[510717.1935003072,6651105.152511052,70.80997467889593],[510717.16736027185,6651105.7615515655,70.80997467889593],[510717.19260152715,6651105.173451861,71.27556536589593],[510717.16656723066,6651105.780028748,71.22078999089594],[510717.1897909219,6651105.238936563,71.75283631789593],[510717.1640872849,6651105.837809368,71.64191141889592],[510717.18492353015,6651105.352342638,72.23573733789593],[510717.15979252744,6651105.937873553,72.06800055389593],[510717.1798613654,6651105.470286753,72.59744332289593],[510717.1535952497,6651106.082264833,72.49290705789592],[510717.1735639243,6651105.6170117585,72.95520116889593],[510717.1454583218,6651106.271848308,72.90987375989592],[510716.64421785146,6651117.950323476,68.98117101989592],[510716.64421785146,6651117.950323476,69.11117101989592],[510717.1660304544,6651105.792535178,73.30565738389592],[510716.6180778162,6651118.559363989,68.98117101989592],[510717.13540319866,6651106.506124095,73.31182267689593],[510717.15728229086,6651105.996359921,73.64540241089593],[510717.12351425504,6651106.783126335,73.69170347889592],[510717.147363598,6651106.227457001,73.97106952089594],[510717.11348029255,6651107.016909098,73.95810979389591],[510717.13634112646,6651106.48427118,74.27943832889592],[510717.102579867,6651107.270879709,74.20581953389592],[510717.12430293934,6651106.764750664,74.56753667989592],[510716.64421775116,6651117.950325814,70.80997467989593],[510717.086872065,6651107.636858092,74.50326200389594],[510716.6444126631,6651117.945784534,71.01379596389592],[510716.6180778162,6651118.559363989,70.80997467889593],[510717.1113561369,6651107.066400111,74.83273440489593],[510717.0700723364,6651108.02827743,74.75947512689594],[510716.6460310976,6651117.90807639,71.43037525189592],[510716.6189765963,6651118.53842318,71.27556536589593],[510717.0976237003,6651107.386354167,75.07282285189594],[510717.05247632257,6651108.438249534,74.97175293589592],[510716.6494047117,6651117.829474061,71.85470237189594],[510717.08324064704,6651107.721467031,75.28607518689593],[510716.62178720144,6651118.472938479,71.75283631789593],[510717.0343889269,6651108.859670416,75.13886769289594],[510717.06834974803,6651108.068412268,75.47128408889593],[510716.6546427047,6651117.707433295,72.28101272289592],[510717.0161085048,6651109.28558865,75.26102081489594],[510716.6266545933,6651118.359532403,72.23573733789593],[510717.0530970812,6651108.423786389,75.62777538089593],[510716.9979131247,6651109.709525476,75.33969550789593],[510716.6618086773,6651117.5404722495,72.70282158189592],[510717.03762769606,6651108.784209859,75.75539813989592],[510716.6317167579,6651118.241588288,72.59744332289593],[510716.9800499759,6651110.125721598,75.37743836689592],[510717.0220816379,6651109.146419749,75.85449363389593],[510716.67091126635,6651117.328389692,73.11317112489593],[510716.6380141991,6651118.094863282,72.95520116889593],[510717.001460207,6651109.626881486,75.94365828589592],[510716.68189782585,6651117.072412233,73.50495081889592],[510716.64554766903,6651117.919339863,73.30565738389592],[510716.90500901436,6651111.874111958,75.37743836689592],[510716.98121530504,6651110.098570424,75.98643352689592],[510716.6913066334,6651116.853195047,73.78243267889593],[510716.65429583244,6651117.71551512,73.64540241089593],[510716.7016395442,6651116.612447043,74.04287335189593],[510716.7128073834,6651116.352245921,74.28384299789592],[510716.66421452543,6651117.484418041,73.97106952089594],[510716.7247059581,6651116.075019288,74.50326200389594],[510716.8315280471,6651113.5861557815,75.37743836689592],[510716.7415056866,6651115.68359995,74.75947512689594],[510716.81366489833,6651114.002351903,75.33969550789593],[510716.67523699696,6651117.227603861,74.27943832889592],[510716.7591017005,6651115.273627844,74.97175293589592],[510716.7954695182,6651114.426288729,75.26102081489594],[510716.7771890962,6651114.852206962,75.13886769289594],[510716.6872751841,6651116.947124376,74.56753667989592],[510716.7002219864,6651116.645474929,74.83273440489593],[510716.8303628184,6651113.613304617,75.98643352689592],[510716.71395442315,6651116.325520874,75.07282285189594],[510716.7283374764,6651115.990408009,75.28607518689593],[510716.8101179163,6651114.084993556,75.94365828589592],[510716.7432283754,6651115.6434627725,75.47128408889593],[510716.78949648555,6651114.565455293,75.85449363389593],[510716.7584810422,6651115.288088651,75.62777538089593],[510716.77395042736,6651114.927665182,75.75539813989592],[510727.58008760674,6651105.627760315,68.96844538400684],[510727.5505002783,6651106.236643095,68.96844538400684],[510727.5505002783,6651106.236643095,69.09844538400685],[510727.58008760674,6651105.627760315,70.79724904300684],[510727.5505002783,6651106.236643095,70.79724904300684],[510727.57907029736,6651105.648695701,71.26283973000683],[510727.5496026525,6651106.255115492,71.20806435500684],[510727.57588903554,6651105.714163442,71.74011068200684],[510727.54679565673,6651106.312881147,71.62918578300683],[510727.57037974225,6651105.827540148,72.22301170200684],[510727.5419345156,6651106.412919416,72.05527491800686],[510727.5646499899,6651105.945453716,72.58471768700684],[510727.53491995385,6651106.557273301,72.48018142200684],[510726.9583669315,6651118.422258254,68.96844538400684],[510726.9583669315,6651118.422258254,69.09844538400685],[510726.9287796031,6651119.0311410315,68.96844538400684],[510727.55752205546,6651106.092140722,72.94247553300684],[510727.52570994495,6651106.746807677,72.89714812400683],[510727.5489950873,6651106.267618683,73.29293174800685],[510727.51432877325,6651106.981022789,73.29909704100683],[510727.5390932343,6651106.471390637,73.63267677500684],[510727.50087194075,6651107.257953289,73.67897784300683],[510727.52786648495,6651106.702427866,73.95834388500684],[510727.48951472016,6651107.491675504,73.94538415800685],[510726.95836681797,6651118.422260589,70.79724904400683],[510727.5153903929,6651106.959175534,74.26671269300684],[510726.9287796031,6651119.0311410315,70.79724904300684],[510726.95858743443,6651118.417720486,71.00107032800683],[510727.47717676946,6651107.74558034,74.19309389800684],[510727.50176463503,6651107.2395823775,74.55481104400684],[510726.96041930467,6651118.380022108,71.41764961600684],[510727.4593974553,6651108.111463937,74.49053636800684],[510726.9297969124,6651119.010205645,71.26283973000683],[510727.48711043544,6651107.5411537,74.82000876900683],[510727.4403822138,6651108.5027819015,74.74674949100684],[510726.9642378239,6651118.301440137,71.84197673600684],[510726.93297817436,6651118.944737904,71.74011068200684],[510727.47156699374,6651107.86102489,75.06009721600684],[510727.4204656744,6651108.912647829,74.95902730000684],[510726.97016659245,6651118.179430978,72.26828708700685],[510727.4552871335,6651108.196050965,75.27334955100686],[510726.9384874676,6651118.831361199,72.22301170200684],[510727.39999295096,6651109.333959568,75.12614205700685],[510727.438432454,6651108.542906347,75.45855845300684],[510726.9782775985,6651118.012513173,72.69009594600683],[510727.37930174504,6651109.759767494,75.24829517900685],[510726.94421721995,6651118.7134476295,72.58471768700684],[510727.4211682974,6651108.89818843,75.61504974500686],[510727.35870679637,6651110.183594526,75.32696987200684],[510726.988580618,6651117.800485543,73.10044548900684],[510726.9513451545,6651118.566760625,72.94247553300684],[510727.4036588422,6651109.258518553,75.74267250400685],[510727.33848789294,6651110.599682856,75.36471273100683],[510727.38606260234,6651109.620634636,75.84176799800684],[510727.001016062,6651117.544574378,73.49222518300685],[510726.9598721226,6651118.391282664,73.29293174800685],[510727.0116656833,6651117.325413967,73.76970704300683],[510727.36272166047,6651110.100971939,75.93093265000685],[510727.2535506866,6651112.347620404,75.36471273100683],[510726.9697739755,6651118.187510709,73.63267677500684],[510727.02336127684,6651117.084728314,74.03014771600684],[510727.3398069032,6651110.572538715,75.97370789100684],[510727.0360019072,6651116.8245945815,74.27111736200683],[510726.9810007249,6651117.956473481,73.95834388500684],[510727.04946964094,6651116.5474397475,74.49053636800684],[510726.993476817,6651117.699725813,74.26671269300684],[510727.17037920334,6651114.059220828,75.36471273100683],[510727.0684848825,6651116.156121782,74.74674949100684],[510727.1501602999,6651114.475309158,75.32696987200684],[510727.08840142185,6651115.746255854,74.95902730000684],[510727.12956535124,6651114.89913619,75.24829517900685],[510727.1088741453,6651115.324944116,75.12614205700685],[510727.00710257486,6651117.41931897,74.55481104400684],[510727.02175677445,6651117.117747648,74.82000876900683],[510727.03730021615,6651116.797876457,75.06009721600684],[510727.1690603067,6651114.086362632,75.97370789100684],[510727.0535800763,6651116.462850382,75.27334955100686],[510727.0704347558,6651116.115995001,75.45855845300684],[510727.1461455494,6651114.557929408,75.93093265000685],[510727.0876989125,6651115.760712918,75.61504974500686],[510727.1228046075,6651115.038266711,75.84176799800684],[510727.10520836763,6651115.400382793,75.74267250400685],[510730.6378082029,6651105.778898019,68.96278941948812],[510730.60720602155,6651106.387730636,68.96278941948812],[510730.60720602155,6651106.387730636,69.0927894194881],[510730.6378082029,6651105.778898019,70.7915930784881],[510730.60720602155,6651106.387730636,70.7915930784881],[510730.6367559996,6651105.799831681,71.2571837654881],[510730.6062776069,6651106.406201512,71.2024083904881],[510730.6334656197,6651105.865294028,71.73445471748812],[510730.60337433044,6651106.463962407,71.62352981848811],[510730.59834645095,6651106.563992436,72.0496189534881],[510730.6277673562,6651105.978661393,72.21735573748812],[510729.9947623485,6651118.572341891,68.96278941948812],[510730.62184107193,6651106.0965652475,72.5790617224881],[510730.5910912879,6651106.708334429,72.4745254574881],[510729.9947623485,6651118.572341891,69.0927894194881],[510729.96416016715,6651119.181174506,68.96278941948812],[510730.6144686474,6651106.243240168,72.9368195684881],[510730.58156537334,6651106.897853188,72.8914921594881],[510730.605649202,6651106.418703673,73.2872757834881],[510730.5697938245,6651107.1320490055,73.29344107648811],[510730.595407713,6651106.622458839,73.6270208104881],[510730.5558754192,6651107.40895669,73.6733218784881],[510730.5837958832,6651106.853477035,73.9526879204881],[510729.994762231,6651118.572344227,70.7915930794881],[510730.54412864306,6651107.642659651,73.9397281934881],[510729.96416016715,6651119.181174506,70.7915930784881],[510730.570891858,6651107.110203549,74.2610567284881],[510729.99499041465,6651118.567804497,70.9954143634881],[510730.5313674974,6651107.89654357,74.1874379334881],[510730.5567987331,6651107.390587292,74.54915507948812],[510729.9968851186,6651118.530109226,71.41199365148812],[510729.96521237044,6651119.160240846,71.2571837654881],[510730.5129783483,6651108.262397023,74.4848804034881],[510730.54164189065,6651107.692133769,74.8143528044881],[510730.00083461404,6651118.451533728,71.8363207714881],[510729.96850275033,6651119.094778499,71.73445471748812],[510730.493310879,6651108.653682749,74.7410935264881],[510730.52556530497,6651108.011978609,75.0544412514881],[510730.0069667408,6651118.32953462,72.2626311224881],[510730.4727111972,6651109.06351491,74.95337133548811],[510729.9742010138,6651118.981411134,72.21735573748812],[510730.50872704136,6651108.346977082,75.26769358648811],[510730.451536254,6651109.484791939,75.12048609248811],[510730.0153559565,6651118.162630567,72.6844399814881],[510730.49129424203,6651108.693803888,75.4529024884881],[510729.9801272981,6651118.863507279,72.5790617224881],[510730.4301353345,6651109.910564785,75.24263921448811],[510730.47343792033,6651109.049056702,75.6093937804881],[510730.0260123722,6651117.950620405,73.0947895244881],[510730.4088339738,6651110.3343569,75.32131390748812],[510729.9874997227,6651118.716832358,72.9368195684881],[510730.45532788633,6651109.40935714,75.7370165394881],[510730.3879215568,6651110.750410953,75.35905676648811],[510730.038874355,6651117.694730324,73.4865692184881],[510729.996319168,6651118.541368853,73.2872757834881],[510730.4371280909,6651109.771443389,75.8361120334881],[510730.0498892612,6651117.475587968,73.76405107848811],[510730.41298654873,6651110.25174112,75.9252766854881],[510730.00656065706,6651118.337613688,73.6270208104881],[510730.3000709823,6651112.498204497,75.35905676648811],[510730.0619860166,6651117.234922144,74.0244917514881],[510730.3892858094,6651110.723269046,75.9680519264881],[510730.0750602238,6651116.974809842,74.26546139748811],[510730.0181724868,6651118.106595492,73.9526879204881],[510730.0889899043,6651116.6976778405,74.4848804034881],[510730.031076512,6651117.8498689765,74.2610567284881],[510730.10865737346,6651116.306392115,74.7410935264881],[510730.21404669574,6651114.209663911,75.35905676648811],[510730.12925705523,6651115.896559953,74.95337133548811],[510730.1931342788,6651114.625717964,75.32131390748812],[510730.1504319985,6651115.475282923,75.12048609248811],[510730.171832918,6651115.049510078,75.24263921448811],[510730.04516963696,6651117.569485234,74.54915507948812],[510730.0603264794,6651117.267938757,74.8143528044881],[510730.07640306506,6651116.948093918,75.0544412514881],[510730.09324132866,6651116.613095444,75.26769358648811],[510730.21268256055,6651114.23680348,75.9680519264881],[510730.110674128,6651116.266268638,75.4529024884881],[510730.1889818213,6651114.708331407,75.9252766854881],[510730.1285304497,6651115.911015824,75.6093937804881],[510730.16484027903,6651115.188629137,75.8361120334881],[510730.1466404837,6651115.550715387,75.7370165394881],[510734.3947636187,6651105.971593879,68.95465016035759],[510734.3629145093,6651106.58036254,68.95465016035759],[510734.3629145093,6651106.58036254,69.08465016035757],[510734.3947636187,6651105.971593879,70.78345381935759],[510734.3629145093,6651106.58036254,70.78345381935759],[510734.3936685419,6651105.992525341,71.24904450635756],[510734.3619482651,6651106.598831477,71.19426913135757],[510734.3902440909,6651106.057980813,71.72631545835758],[510734.3589266907,6651106.656586305,71.61539055935756],[510734.35369394324,6651106.756605824,72.04147969435758],[510734.38431364385,6651106.171336268,72.20921647835759],[510733.72551597597,6651118.763693851,68.95465016035759],[510733.72551597597,6651118.763693851,69.08465016035757],[510733.69366686663,6651119.372462511,68.95465016035759],[510734.3781458849,6651106.289227738,72.57092246335758],[510734.34614315873,6651106.900932655,72.46638619835758],[510734.3704730608,6651106.435887252,72.92868030935757],[510734.3362290977,6651107.090431508,72.88335290035756],[510734.361294255,6651106.611332324,73.27913652435757],[510734.3239779009,6651107.324602722,73.28530181735758],[510734.3506354625,6651106.815066086,73.61888155135759],[510734.3094923709,6651107.601481319,73.66518261935757],[510734.3385504927,6651107.046060014,73.94454866135757],[510733.72551585373,6651118.763696186,70.78345382035756],[510733.69366686663,6651119.372462511,70.78345381935759],[510734.29726695624,6651107.835159731,73.93158893435758],[510733.7257533351,6651118.759156933,70.98727510435758],[510734.3251206753,6651107.302759563,74.25291746935757],[510734.28398584016,6651108.089016979,74.17929867435757],[510733.7277252413,6651118.721465621,71.40385439235759],[510733.69476194336,6651119.351531049,71.24904450635756],[510734.3104533066,6651107.583113851,74.54101582035759],[510734.26484739984,6651108.454832002,74.47674114435758],[510733.7318356643,6651118.642898378,71.82818151235757],[510734.29467887775,6651107.884628652,74.80621354535756],[510733.6981863944,6651119.286075577,71.72631545835758],[510734.2443785525,6651108.8460766245,74.73295426735757],[510734.27794722933,6651108.204439892,75.04630199235757],[510733.7382176531,6651118.520912086,72.25449186335757],[510733.7041168414,6651119.172720123,72.20921647835759],[510734.2229395084,6651109.255865734,74.94523207635757],[510734.2604228676,6651108.539403177,75.25955432735758],[510733.74694869894,6651118.354025566,72.67630072235758],[510733.7102846004,6651119.054828652,72.57092246335758],[510734.200901763,6651109.67709851,75.11234683335758],[510734.2422797448,6651108.886193549,75.44476322935758],[510734.1786288335,6651110.10282663,75.23449995535758],[510733.7580393249,6651118.142037674,73.08665026535758],[510733.71795742447,6651118.908169139,72.92868030935757],[510734.2236958428,6651109.241409045,75.60125452135757],[510734.1564595195,6651110.526574227,75.31317464835759],[510734.13469499734,6651110.942584574,75.35091750735758],[510733.77142538695,6651117.886174472,73.47842995935757],[510734.2048478906,6651109.601671636,75.72887728035757],[510733.7271362303,6651118.732724067,73.27913652435757],[510734.18590651936,6651109.963719849,75.82797277435759],[510733.7828891107,6651117.667055137,73.75591181935758],[510733.7377950229,6651118.528990304,73.61888155135759],[510733.79547876486,6651117.426414593,74.01635249235757],[510734.16078129684,6651110.443967126,75.91713742635757],[510734.04326483025,6651112.69019452,75.35091750735758],[510733.7498799926,6651118.297996378,73.94454866135757],[510733.80908569874,6651117.166329616,74.25732213835758],[510734.13611483824,6651110.91544552,75.95991266735757],[510733.8235829632,6651116.889226725,74.47674114435758],[510733.7633098101,6651118.041296829,74.25291746935757],[510733.84405181056,6651116.497982102,74.73295426735757],[510733.9537353658,6651114.401474153,75.35091750735758],[510733.8654908548,6651116.088192994,74.94523207635757],[510733.9319708435,6651114.817484501,75.31317464835759],[510733.7779771788,6651117.76094254,74.54101582035759],[510733.88752860005,6651115.666960218,75.11234683335758],[510733.90980152955,6651115.241232097,75.23449995535758],[510733.79375160753,6651117.459427739,74.80621354535756],[510733.8104832559,6651117.139616499,75.04630199235757],[510733.8280076178,6651116.804653214,75.25955432735758],[510733.952315647,6651114.428610871,75.95991266735757],[510733.84615074046,6651116.457862841,75.44476322935758],[510733.92764918844,6651114.900089264,75.91713742635757],[510733.86473464256,6651116.102647346,75.60125452135757],[510733.8835825948,6651115.742384755,75.72887728035757],[510733.902523966,6651115.380336542,75.82797277435759],[510744.45206085313,6651106.525420858,68.92640105436793],[510744.41687374155,6651107.134005704,68.92640105436793],[510744.41687374155,6651107.134005704,69.05640105436792],[510744.45206085313,6651106.525420858,70.75520471336793],[510744.41687374155,6651107.134005704,70.75520471336793],[510744.4508510049,6651106.546345999,71.22079540036792],[510744.41580622847,6651107.152469065,71.16602002536793],[510744.44706764823,6651106.611781707,71.69806635236795],[510744.4124679726,6651107.210206454,71.58714145336793],[510743.7126715283,6651119.313658325,68.92640105436793],[510743.7126715283,6651119.313658325,69.05640105436792],[510743.6774844167,6651119.92224317,68.92640105436793],[510744.40668679785,6651107.310195773,72.01323058836793],[510744.4405156502,6651106.725102936,72.18096737236793],[510744.4337014684,6651106.842958809,72.54267335736793],[510744.3983446399,6651107.454479025,72.43813709236792],[510744.42522448045,6651106.989574039,72.90043120336794],[510744.38739151816,6651107.643920658,72.85510379436793],[510744.4150836736,6651107.164966137,73.25088741836792],[510744.37385631306,6651107.878021168,73.25705271136792],[510743.71267139324,6651119.31366066,70.75520471436792],[510744.4033077675,6651107.368638382,73.59063244536793],[510743.6774844167,6651119.92224317,70.75520471336793],[510743.7129337642,6651119.309122778,70.95902599836792],[510744.35785260145,6651108.154816163,73.63693351336792],[510744.38995621103,6651107.599562564,73.91629955536793],[510743.6786942649,6651119.901318029,71.22079540036792],[510743.71511233953,6651119.271442845,71.37560528636793],[510744.3443458806,6651108.388424016,73.90333982836795],[510744.3751188579,6651107.856184602,74.22466836336794],[510744.32967281365,6651108.642204613,74.15104956836792],[510743.71965356276,6651119.192899325,71.79993240636793],[510743.6824776216,6651119.835882322,71.69806635236795],[510744.35891424963,6651108.1364542395,74.51276671436793],[510744.3085285353,6651109.00790918,74.44849203836793],[510743.72670442716,6651119.070949866,72.22624275736793],[510744.34148655395,6651108.437878001,74.77796443936792],[510743.6890296196,6651119.722561093,72.18096737236793],[510744.2859144142,6651109.399035669,74.70470516136793],[510743.7363505456,6651118.904113736,72.64805161636792],[510744.3230013157,6651108.757592674,75.01805288636793],[510743.6958438014,6651119.604705219,72.54267335736793],[510744.26222841314,6651109.808701046,74.91698297036794],[510744.3036402822,6651109.092454818,75.23130522136793],[510743.74860354426,6651118.692189854,73.05840115936793],[510743.7043207894,6651119.45808999,72.90043120336794],[510744.23788096296,6651110.229806632,75.08409772736793],[510744.28359563736,6651109.43914048,75.41651412336795],[510744.21327367966,6651110.655406205,75.20625084936793],[510743.7144615962,6651119.282697892,73.25088741836792],[510743.7633925562,6651118.436403908,73.45018085336793],[510744.26306401653,6651109.794248721,75.57300541536793],[510744.1887808716,6651111.079025854,75.28492554236793],[510743.7760577557,6651118.217350735,73.72766271336792],[510744.16473528015,6651111.49491059,75.32266840136792],[510743.7262375024,6651119.079025646,73.59063244536793],[510744.24224067136,6651110.154402531,75.70062817436792],[510743.78996689094,6651117.976782853,73.98810338636792],[510744.2213141163,6651110.5163414255,75.79972366836793],[510743.7395890588,6651118.848101465,73.91629955536793],[510743.8049999236,6651117.716776405,74.22907303236792],[510744.06372261286,6651113.2419928545,75.32266840136792],[510744.1935556005,6651110.996443695,75.88888832036793],[510743.8210165995,6651117.439757184,74.44849203836793],[510743.75442641194,6651118.591479427,74.22466836336794],[510744.1663039301,6651111.4677797295,75.93166356136794],[510743.84363072057,6651117.048630697,74.70470516136793],[510743.7706310202,6651118.3112097895,74.51276671436793],[510743.86731672165,6651116.63896532,74.91698297036794],[510743.96480985463,6651114.952755776,75.32266840136792],[510743.8916641718,6651116.217859733,75.08409772736793],[510743.94076426316,6651115.36864051,75.28492554236793],[510743.9162714551,6651115.792260159,75.20625084936793],[510743.7880587159,6651118.009786028,74.77796443936792],[510743.8065439542,6651117.690071355,75.01805288636793],[510743.82590498775,6651117.355209211,75.23130522136793],[510743.84594963246,6651117.008523548,75.41651412336795],[510743.9632413397,6651114.979884299,75.93166356136794],[510743.8664812533,6651116.653415308,75.57300541536793],[510743.93598966935,6651115.451220333,75.88888832036793],[510743.88730459847,6651116.293261498,75.70062817436792],[510743.9082311535,6651115.9313226035,75.79972366836793],[510750.856643526,6651106.906945225,68.9035058657163],[510750.8193307429,6651107.515403444,68.9035058657163],[510750.8193307429,6651107.515403444,69.0335058657163],[510750.856643526,6651106.906945225,70.7323095247163],[510750.8193307429,6651107.515403444,70.7323095247163],[510750.8553605902,6651106.927866013,71.1979002117163],[510750.8181987407,6651107.533862962,71.14312483671631],[510750.07258730987,6651119.692521863,68.9035058657163],[510750.03527452674,6651120.30098008,68.9035058657163],[510750.07258730987,6651119.692521863,69.0335058657163],[510750.851348679,6651106.993288105,71.6751711637163],[510750.81465881906,6651107.591588338,71.56424626471629],[510750.80852840055,6651107.691556854,71.9903353997163],[510750.84440087137,6651107.106585755,72.1580721837163],[510750.8371750413,6651107.224417107,72.51977816871631],[510750.7996822885,6651107.835810084,72.41524190371629],[510750.82818595413,6651107.37100183,72.87753601471631],[510750.78806748305,6651108.025212301,72.83220860571629],[510750.0725871666,6651119.692524197,70.7323095257163],[510750.817432536,6651107.546357435,73.22799222971629],[510750.03527452674,6651120.30098008,70.7323095247163],[510750.77371460927,6651108.259264101,73.2341575227163],[510750.07286538754,6651119.687987258,70.93613080971629],[510750.8049452412,6651107.749987303,73.5677372567163],[510750.0365574624,6651120.280059292,71.1979002117163],[510750.7567441052,6651108.536001503,73.61403832471629],[510750.07517557184,6651119.650315166,71.3527100977163],[510750.79078711045,6651107.980863436,73.8934043667163],[510751.5875913436,6651106.951915768,68.90065002138758],[510750.74242143636,6651108.769560751,73.8804446397163],[510751.5500359599,6651107.560359061,68.90065002138758],[510750.07999113266,6651119.57178799,71.77703721771631],[510750.04056937364,6651120.214637199,71.6751711637163],[510750.77505342505,6651108.237432078,74.20177317471631],[510751.5500359599,6651107.560359061,69.03065002138757],[510750.72686196177,6651109.023288545,74.12815437971629],[510750.0874679433,6651119.449863903,72.2033475687163],[510750.75786988804,6651108.5176434005,74.4898715257163],[510750.0475171813,6651120.101339551,72.1580721837163],[510750.7044403466,6651109.38891702,74.42559684971631],[510750.7393893763,6651108.819004444,74.75506925071629],[510750.0976967889,6651119.283062487,72.62515642771629],[510750.0547430113,6651119.9835081985,72.51977816871631],[510750.6804600949,6651109.779962127,74.6818099727163],[510750.7197874351,6651109.1386525985,74.9951576977163],[510750.0637320985,6651119.836923476,72.87753601471631],[510750.1106899975,6651119.071182698,73.0355059707163],[510750.65534321027,6651110.189542265,74.8940877817163],[510750.6992567916,6651109.473445066,75.2084100327163],[510750.6295249179,6651110.610560233,75.0612025387163],[510750.07448551664,6651119.6615678705,73.22799222971629],[510750.1263724214,6651118.815449975,73.4272856647163],[510750.67800123943,6651109.820058594,75.3936189347163],[510750.603431096,6651111.036071253,75.1833556607163],[510751.5875913436,6651106.951915768,70.72945368038758],[510750.1398027321,6651118.596442379,73.7047675247163],[510750.08697281143,6651119.457938003,73.5677372567163],[510751.5500359599,6651107.560359061,70.72945368038758],[510750.5774586647,6651111.45960276,75.2620303537163],[510750.6562292928,6651110.175092947,75.5501102267163],[510750.1545521254,6651118.355924551,73.96520819771631],[510750.5519604666,6651111.875400962,75.29977321271629],[510750.63414799864,6651110.535171822,75.67773298571629],[510750.1011309423,6651119.2270618705,73.8934043667163],[510750.17049331125,6651118.095972205,74.20617784371629],[510751.5863000664,6651106.972836043,71.19504436738757],[510751.5488965977,6651107.578818127,71.14026899238758],[510750.6119572596,6651110.897035409,75.7768284797163],[510750.18747756275,6651117.819010622,74.42559684971631],[510750.44484557194,6651113.6221197145,75.29977321271629],[510750.1168646276,6651118.970493227,74.20177317471631],[510750.58252183744,6651111.377037784,75.8659931317163],[510750.7984373454,6651119.73717877,68.90065002138758],[510750.2114578146,6651117.427965514,74.6818099727163],[510750.1340481646,6651118.690281905,74.4898715257163],[510750.55362387956,6651111.848275747,75.90876837271631],[510750.7608819617,6651120.345622063,68.90065002138758],[510750.7984373454,6651119.73717877,69.03065002138757],[510750.2365746992,6651117.018385376,74.8940877817163],[510751.5822620705,6651107.038256531,71.67231531938758],[510751.54533366015,6651107.636542086,71.56139042038757],[510750.3399574428,6651115.332526679,75.29977321271629],[510750.2623929916,6651116.597367409,75.0612025387163],[510750.3144592448,6651115.748324881,75.2620303537163],[510750.2884868135,6651116.171856388,75.1833556607163],[510750.15252867644,6651118.38892086,74.75506925071629],[510750.17213061755,6651118.069272708,74.9951576977163],[510750.1926612611,6651117.7344802385,75.2084100327163],[510751.53916338284,6651107.73650815,71.9874795553876],[510751.5752690896,6651107.1515514,72.15521633938758],[510750.2139168132,6651117.387866712,75.3936189347163],[510750.2356887598,6651117.032832358,75.5501102267163],[510750.33829417307,6651115.359649558,75.90876837271631],[510750.2577700541,6651116.672753485,75.67773298571629],[510750.30939621525,6651115.830887522,75.8659931317163],[510750.27996079304,6651116.310889898,75.7768284797163],[510751.5679962787,6651107.269379862,72.51692232438758],[510751.53025975515,6651107.880757842,72.41238605938757],[510751.5589487461,6651107.415960989,72.87468017038758],[510751.5185694325,6651108.070155413,72.82935276138757],[510750.79843720124,6651119.737181106,70.72945368138757],[510751.54812541127,6651107.591312292,73.22513638538757],[510750.7608819617,6651120.345622063,70.72945368038758],[510751.5041232391,6651108.304201472,73.23130167838758],[510750.7987172311,6651119.732644279,70.93327496538757],[510751.53555692657,6651107.794937166,73.56488141238758],[510750.76217323885,6651120.324701788,71.19504436738757],[510750.8010424357,6651119.69497311,71.34985425338758],[510751.487042396,6651108.580932085,73.61118248038757],[510751.52130674233,6651108.025807634,73.89054852238758],[510751.472626604,6651108.814485602,73.87758879538757],[510750.80588930636,6651119.6164478585,71.77418137338758],[510750.7662112348,6651120.259281302,71.67231531938758],[510751.5054707596,6651108.282369984,74.19891733038757],[510751.4569659648,6651109.068207172,74.12529853538757],[510750.8134147299,6651119.494526765,72.20049172438759],[510751.4881754986,6651108.562574432,74.48701568138758],[510750.77320421574,6651120.14598643,72.15521633938758],[510751.43439856864,6651109.433826678,74.42274100538758],[510750.8237100814,6651119.32772944,72.62230058338757],[510751.4695748301,6651108.863928085,74.75221340638757],[510750.78047702665,6651120.028157969,72.51692232438758],[510751.4102624018,6651109.824862193,74.67895412838757],[510751.44984544086,6651109.183568395,74.99230185338757],[510750.7895245592,6651119.881576842,72.87468017038758],[510750.83678776934,6651119.115854849,73.03265012638758],[510751.3849822121,6651110.234432285,74.89123193738757],[510751.42918131105,6651109.518352652,75.2055541883876],[510750.800347894,6651119.706225539,73.22513638538757],[510751.3589960542,6651110.655439925,75.05834669438758],[510750.85257215734,6651118.860128398,73.42442982038759],[510751.40778755944,6651109.864957676,75.39076309038758],[510751.33273257525,6651111.080940507,75.18049981638758],[510750.8660897893,6651118.6411261745,73.70191168038758],[510750.8129163787,6651119.502600665,73.56488141238758],[510751.3065912763,6651111.504461624,75.25917450938758],[510751.3858740558,6651110.219983321,75.54725438238759],[510750.8809350803,6651118.400614246,73.96235235338757],[510751.2809272938,6651111.920249627,75.29691736838757],[510750.82716656296,6651119.271730197,73.89054852238758],[510751.3636491933,6651110.580053363,75.67487714138758],[510750.8969799127,6651118.140668276,74.20332199938757],[510751.3413141743,6651110.941908073,75.77397263538758],[510750.9140745925,6651117.863713488,74.42274100538758],[510750.84300254576,6651119.015167847,74.19891733038757],[510751.1731159588,6651113.666925532,75.29691736838757],[510751.3116873687,6651111.421898673,75.86313728738759],[510750.93821075937,6651117.472677973,74.67895412838757],[510750.86029780674,6651118.734963399,74.48701568138758],[510751.282601522,6651111.893125078,75.90591252838757],[510750.96349094907,6651117.063107883,74.89123193738757],[510751.0675458673,6651115.377290539,75.29691736838757],[510750.9894771069,6651116.642100242,75.05834669438758],[510751.0418818849,6651115.793078542,75.25917450938758],[510751.0157405858,6651116.21659966,75.18049981638758],[510750.8788984752,6651118.433609747,74.75221340638757],[510750.8986278645,6651118.113969435,74.99230185338757],[510750.9192919943,6651117.779185179,75.2055541883876],[510750.94068574585,6651117.432580154,75.39076309038758],[510750.9625992495,6651117.077554509,75.54725438238759],[510751.06587178336,6651115.404412754,75.90591252838757],[510750.984824112,6651116.717484468,75.67487714138758],[510751.03678593657,6651115.875639157,75.86313728738759],[510751.007159131,6651116.355629758,75.77397263538758],[510761.3150627726,6651107.578246551,68.8579046167634],[510761.2742788554,6651108.186481965,68.8579046167634],[510761.2742788554,6651108.186481965,68.98790461676339],[510761.3150627726,6651107.578246551,70.68670827576341],[510761.2742788554,6651108.186481965,70.68670827576341],[510760.45806736604,6651120.359141392,68.8579046167634],[510760.4172834488,6651120.967376806,68.8579046167634],[510760.45806736604,6651120.359141392,68.98790461676339],[510761.3136604879,6651107.599159678,71.15229896276338],[510761.2730415454,6651108.204934724,71.09752358776339],[510761.2691723118,6651108.262638962,71.5186450157634],[510761.3092753565,6651107.664557815,71.6295699147634],[510761.26247159275,6651108.362570872,71.9447341507634],[510761.30168120813,6651107.777813977,72.11247093476341],[510761.2528025445,6651108.5067712795,72.36964065476339],[510761.2937831736,6651107.895602181,72.4741769197634],[510760.45806720946,6651120.359143726,70.68670827676338],[510760.4172834488,6651120.967376806,70.68670827576341],[510761.28395784943,6651108.042133229,72.83193476576339],[510761.2401072368,6651108.696104142,72.78660735676338],[510760.45837131276,6651120.354608448,70.8905295607634],[510761.2722040622,6651108.217424622,73.18239098076339],[510760.41868573363,6651120.946463679,71.15229896276338],[510760.46089640877,6651120.316950152,71.3071088487634],[510761.2244191437,6651108.930070237,73.1885562737634],[510761.25855509925,6651108.420979925,73.52213600776341],[510760.4661599517,6651120.2384517295,71.73143596876339],[510760.42307086487,6651120.881065543,71.6295699147634],[510761.2058699073,6651109.206706304,73.56843707576338],[510761.24307986564,6651108.651771516,73.84780311776339],[510761.19021482917,6651109.440180027,73.83484339076338],[510760.47433231527,6651120.116572291,72.15774631976339],[510760.43066501326,6651120.76780938,72.11247093476341],[510761.2258825069,6651108.908246209,74.15617192576339],[510761.1732078877,6651109.693814911,74.08255313076339],[510760.48551272985,6651119.949831951,72.57955517876339],[510760.4385630479,6651120.650021177,72.4741769197634],[510761.20710041956,6651109.188354924,74.4442702767634],[510761.14870043425,6651110.059309501,74.3799956007634],[510760.44838837197,6651120.503490129,72.83193476576339],[510760.4997146709,6651119.73802975,72.9899047217634],[510761.1869007026,6651109.489605617,74.70946800176338],[510761.1224893473,6651110.450211417,74.63620872376339],[510760.4601421593,6651120.328198736,73.18239098076339],[510761.16547523177,6651109.80913672,74.94955644876339],[510760.5168559994,6651119.482390669,73.38168441576339],[510761.0950358888,6651110.859641577,74.84848653276339],[510760.5315357052,6651119.263463269,73.6591662757634],[510760.4737911222,6651120.124643432,73.52213600776341],[510761.14303466334,6651110.143806596,75.1628087837634],[510761.0668157721,6651111.280505376,75.0156012897634],[510760.5476572053,6651119.023033513,73.91960694876339],[510761.0382944938,6651111.705860583,75.1377544117634],[510761.1198017494,6651110.490293201,75.3480176857634],[510760.4892663558,6651119.893851841,73.84780311776339],[510761.0099058989,6651112.129237003,75.2164291047634],[510760.5650813679,6651118.763176355,74.1605765947634],[510761.0960044019,6651110.84519755,75.5045089777634],[510760.9820356542,6651112.5448829485,75.2541719637634],[510760.5064637145,6651119.637377148,74.15617192576339],[510760.5836456307,6651118.486316191,74.3799956007634],[510761.07186892885,6651111.20514457,75.63213173676338],[510760.86495607387,6651114.290962093,75.2541719637634],[510760.60985671764,6651118.095414275,74.63620872376339],[510760.5252458018,6651119.357268432,74.4442702767634],[510761.04761382943,6651111.5668756515,75.73122723076341],[510760.6373101761,6651117.685984117,74.84848653276339],[510761.01544008846,6651112.04670226,75.82039188276339],[510760.5454455189,6651119.056017741,74.70946800176338],[510760.6655302927,6651117.265120316,75.0156012897634],[510760.7503104106,6651116.000742743,75.2541719637634],[510760.694051571,6651116.839765109,75.1377544117634],[510760.72244016593,6651116.416388689,75.2164291047634],[510760.9838538111,6651112.517767667,75.86316712376339],[510760.5668709896,6651118.736486637,74.94955644876339],[510760.5893115582,6651118.40181676,75.1628087837634],[510760.61254447204,6651118.055330155,75.3480176857634],[510760.6363418195,6651117.700425807,75.5045089777634],[510760.66047729267,6651117.340478787,75.63213173676338],[510760.7484924103,6651116.027855691,75.86316712376339],[510760.68473239196,6651116.978747706,75.73122723076341],[510760.71690613293,6651116.498921096,75.82039188276339],[510768.77047211194,6651108.093390549,68.81917060298551],[510768.72721375537,6651108.701454987,68.81917060298551],[510768.72721375537,6651108.701454987,68.9491706029855],[510767.86148113036,6651120.870692668,68.81917060298551],[510767.8182227738,6651121.478757107,68.81917060298551],[510768.77047211194,6651108.093390549,70.64797426198551],[510767.86148113036,6651120.870692668,68.9491706029855],[510768.72721375537,6651108.701454987,70.64797426198551],[510768.76898474793,6651108.114297796,71.1135649489855],[510768.7259013753,6651108.719902559,71.05878957398552],[510768.72179738793,6651108.777590576,71.4799110019855],[510768.7643335621,6651108.17967755,71.59083590098551],[510768.7146901231,6651108.877494394,71.90600013698551],[510768.7562786621,6651108.292901875,72.07373692098551],[510767.8614809644,6651120.870695001,70.6479742629855],[510767.8182227738,6651121.478757107,70.64797426198551],[510768.704434435,6651109.021654268,72.3309066409855],[510768.7479014383,6651108.410656969,72.43544290598551],[510767.86180351814,6651120.866161,70.8517955469855],[510768.7374799928,6651108.557146828,72.79320075198551],[510768.6909688783,6651109.210933909,72.7478733429855],[510767.81971013796,6651121.457849858,71.1135649489855],[510767.8644818167,6651120.828513289,71.26837483498551],[510768.72501308034,6651108.732388945,73.1436569669855],[510768.67432895803,6651109.444834236,73.1498222599855],[510767.82436132367,6651121.3924701065,71.59083590098551],[510767.8700647089,6651120.750036932,71.69270195498551],[510768.7105360084,6651108.935887029,73.48340199398551],[510768.65465430357,6651109.721392539,73.5297030619855],[510767.8787329057,6651120.628191753,72.1190123059855],[510767.83241622377,6651121.279245781,72.07373692098551],[510768.69412186235,6651109.166613744,73.80906910398552],[510768.6380494014,6651109.954800633,73.7961093769855],[510767.84079344745,6651121.161490685,72.43544290598551],[510767.8905916578,6651120.461498286,72.5408211649855],[510768.6758811064,6651109.423016342,74.1174379119855],[510768.62001061573,6651110.20836422,74.04381911698552],[510767.8512148931,6651121.015000829,72.79320075198551],[510767.9056552582,6651120.24975562,72.95117070798551],[510768.65595947346,6651109.703046319,74.4055362629855],[510768.5940162476,6651110.57375607,74.34126158698552],[510767.86368180544,6651120.839758709,73.1436569669855],[510768.6345342003,6651110.004212329,74.67073398798551],[510767.9238365844,6651119.994188401,73.3429504019855],[510768.56621488306,6651110.964548103,74.59747470998552],[510767.87815887737,6651120.636260627,73.48340199398551],[510767.9394069364,6651119.7753225425,73.6204322619855],[510768.61180880474,6651110.323653613,74.91082243498552],[510768.53709577,6651111.37386317,74.8097525189855],[510767.9565065591,6651119.5349603705,73.8808729349855],[510767.8945730234,6651120.405533911,73.80906910398552],[510768.5880067233,6651110.658229413,75.12407476998551],[510768.5071634841,6651111.794608666,74.97686727598553],[510767.97498787957,6651119.275176259,74.1218425809855],[510768.4769117645,6651112.219844305,75.0990203979855],[510768.5633642235,6651111.00461862,75.30928367198551],[510767.9128137794,6651120.149131312,74.1174379119855],[510768.4468007783,6651112.643101713,75.17769509098551],[510767.99467847217,6651118.998393919,74.34126158698552],[510768.4172395918,6651113.05863082,75.2154379499855],[510768.5381230447,6651111.359423203,75.46577496398551],[510767.9327354123,6651119.869101336,74.4055362629855],[510768.0224798366,6651118.607601887,74.59747470998552],[510768.5125232256,6651111.719269044,75.5933977229855],[510768.293056566,6651114.804219138,75.2154379499855],[510768.05159894977,6651118.19828682,74.8097525189855],[510767.9541606855,6651119.567935327,74.67073398798551],[510768.4867965223,6651112.08089844,75.69249321698551],[510768.0815312357,6651117.7775413245,74.97686727598553],[510768.1117829553,6651117.352305684,75.0990203979855],[510768.17145512794,6651116.513519169,75.2154379499855],[510768.14189394144,6651116.9290482765,75.17769509098551],[510768.452670738,6651112.56059017,75.7816578689855],[510767.97688608104,6651119.248494042,74.91082243498552],[510768.4191680598,6651113.031523161,75.8244331099855],[510768.00068816246,6651118.913918243,75.12407476998551],[510768.02533066226,6651118.567529035,75.30928367198551],[510768.0505718411,6651118.212724451,75.46577496398551],[510768.07617166016,6651117.8528786125,75.5933977229855],[510768.1018983635,6651117.491249215,75.69249321698551],[510768.16952682595,6651116.540624496,75.8244331099855],[510768.1360241478,6651117.011557484,75.7816578689855],[510771.06181310286,6651108.257839253,68.80622400340143],[510771.01779425354,6651108.865849112,68.80622400340143],[510771.01779425354,6651108.865849112,68.93622400340142],[510770.1368418328,6651121.0339944735,68.80622400340143],[510770.09282298345,6651121.642004333,68.80622400340143],[510770.1368418328,6651121.0339944735,68.93622400340142],[510771.06181310286,6651108.257839253,70.63502766240143],[510771.01779425354,6651108.865849112,70.63502766240143],[510771.0602995905,6651108.278744626,71.10061834940143],[510771.0164588016,6651108.884295029,71.04584297440144],[510771.012282665,6651108.941977868,71.46696440240142],[510771.0555666358,6651108.34411851,71.57788930140143],[510771.0050504527,6651109.041872717,71.89305353740141],[510771.04737012857,6651108.4573326735,72.06079032140143],[510770.13684166386,6651121.0339968065,70.63502766340143],[510770.09282298345,6651121.642004333,70.63502766240143],[510770.9946144671,6651109.1860196525,72.31796004140142],[510770.13716988824,6651121.029463212,70.83884894740142],[510771.03884563124,6651108.575077197,72.42249630640144],[510770.0943364958,6651121.621098961,71.10061834940143],[510771.028240974,6651108.721553905,72.78025415240143],[510770.1398952719,6651120.991818881,71.25542823540142],[510770.98091218254,6651109.375282303,72.73492674340142],[510771.01555489015,6651108.896780294,73.13071036740142],[510770.0990694505,6651121.555725077,71.57788930140143],[510770.14557631285,6651120.913349567,71.67975535540144],[510770.96397972835,6651109.609161634,73.13687566040143],[510771.0008233076,6651109.1002601115,73.47045539440143],[510770.1543968986,6651120.791515325,72.10606570640142],[510770.10726595775,6651121.442510913,72.06079032140143],[510770.9439591885,6651109.885695116,73.51675646240142],[510770.98412059684,6651109.330966116,73.79612250440144],[510770.92706236796,6651110.119082257,73.78316277740142],[510770.1157904552,6651121.32476639,72.42249630640144],[510770.1664641305,6651120.624836821,72.52787456540142],[510770.9655591638,6651109.587345701,74.10449131240142],[510770.908706456,6651110.372623084,74.03087251740142],[510770.1263951124,6651121.178289681,72.78025415240143],[510770.18179255276,6651120.413113163,72.93822410840143],[510770.9452873036,6651109.86735054,74.39258966340142],[510770.8822551003,6651110.737982137,74.32831498740144],[510770.13908119616,6651121.003063292,73.13071036740142],[510770.2002935112,6651120.157568882,73.33000380240142],[510770.92348536884,6651110.168489519,74.65778738840143],[510770.8539649809,6651111.128739091,74.58452811040144],[510770.15381277876,6651120.799583474,73.47045539440143],[510770.21613759396,6651119.938722669,73.60748566240143],[510770.900360455,6651110.487902128,74.89787583540142],[510770.8243339465,6651111.538017418,74.79680591940142],[510770.2335378323,6651119.698382073,73.86792633540144],[510770.1705154896,6651120.56887747,73.79612250440144],[510770.7938754436,6651111.958725148,74.96392067640143],[510770.87613992713,6651110.822447896,75.11112817040143],[510770.252344059,6651119.43862128,74.10889598140142],[510770.76309189113,6651112.383922617,75.08607379840143],[510770.18907692254,6651120.312497886,74.10449131240142],[510770.851064206,6651111.168806013,75.29633707240143],[510770.27238081716,6651119.161863784,74.32831498740144],[510770.7324515464,6651112.807142033,75.16474849140143],[510770.7023706667,6651113.222633842,75.20249135040142],[510770.82537928096,6651111.523578749,75.45282836440143],[510770.20934878284,6651120.0324930465,74.39258966340142],[510770.3006709365,6651118.771106829,74.58452811040144],[510770.7993294106,6651111.883392287,75.58045112340142],[510770.5760044724,6651114.968065476,75.20249135040142],[510770.3303019709,6651118.361828502,74.79680591940142],[510770.2311507176,6651119.731354068,74.65778738840143],[510770.36076047394,6651117.941120773,74.96392067640143],[510770.77315042546,6651112.244989226,75.67954661740143],[510770.3915440263,6651117.515923304,75.08607379840143],[510770.4522652506,6651116.677212078,75.20249135040142],[510770.42218437104,6651117.092703887,75.16474849140143],[510770.25427563133,6651119.411941458,74.89787583540142],[510770.7384247013,6651112.724637897,75.76871126940142],[510770.7043330378,6651113.195528616,75.81148651040142],[510770.2784961593,6651119.07739569,75.11112817040143],[510770.3035718804,6651118.731037575,75.29633707240143],[510770.32925680536,6651118.3762648385,75.45282836440143],[510770.3553066757,6651118.016451299,75.58045112340142],[510770.38148566097,6651117.654854361,75.67954661740143],[510770.45030304865,6651116.70431497,75.81148651040142],[510770.416211385,6651117.17520569,75.76871126940142],[510778.1676664001,6651108.786148307,68.76295607119135],[510778.12128912844,6651109.39398282,68.76295607119135],[510778.12128912844,6651109.39398282,68.89295607119135],[510777.1931374316,6651121.55861899,68.76295607119135],[510777.14676016,6651122.166453505,68.76295607119135],[510777.1931374316,6651121.55861899,68.89295607119135],[510778.1676664001,6651108.786148307,70.59175973019136],[510778.12128912844,6651109.39398282,70.59175973019136],[510778.1660717975,6651108.807047649,71.05735041719136],[510778.11988212616,6651109.412423416,71.00257504219137],[510778.1154822424,6651109.470089621,71.42369647019135],[510778.1610852626,6651108.87240268,71.53462136919136],[510777.1931372536,6651121.558621322,70.59175973119136],[510777.14676016,6651122.166453505,70.59175973019136],[510778.1078625459,6651109.569955662,71.84978560519136],[510777.1934830634,6651121.554089035,70.79558101519135],[510778.1524496065,6651108.985584193,72.01752238919136],[510777.1483547626,6651122.145554162,71.05735041719136],[510778.09686742566,6651109.7140610255,72.27469210919135],[510778.1434683874,6651109.103294761,72.37922837419137],[510777.1963544665,6651121.516455559,71.21216030319135],[510778.1322955586,6651109.249729227,72.73698622019135],[510778.0824310062,6651109.903269094,72.69165881119135],[510777.15334129747,6651122.080199131,71.53462136919136],[510777.20233988366,6651121.438008877,71.63648742319137],[510778.1189297854,6651109.424905081,73.08744243519135],[510778.0645913526,6651110.137080977,73.09360772819136],[510777.21163305483,6651121.316209772,72.06279777419135],[510777.16197695344,6651121.967017616,72.01752238919136],[510778.1034089207,6651109.628326218,73.42718746219136],[510778.04349816113,6651110.413534708,73.47348853019135],[510777.17095817265,6651121.849307049,72.37922837419137],[510777.2243468195,6651121.149579335,72.48460663319135],[510778.08581131947,6651109.858965688,73.75285457219137],[510778.0256960504,6651110.646854544,73.73989484519134],[510777.1821310015,6651121.702872584,72.73698622019135],[510777.2404965012,6651120.937916735,72.89495617619136],[510778.0662554103,6651110.1152713355,74.06122338019135],[510778.00635667343,6651110.900322251,73.98760458519135],[510777.1954967746,6651121.527696728,73.08744243519135],[510777.25998869573,6651120.682446152,73.28673587019135],[510778.0448974334,6651110.395195425,74.34932173119135],[510777.97848811885,6651111.265575936,74.28504705519137],[510777.21101763926,6651121.324275592,73.42718746219136],[510777.2766816656,6651120.463663052,73.56421773019136],[510778.02192740433,6651110.696247556,74.61451945619136],[510777.948682284,6651111.6562202,74.54126017819137],[510777.2950141663,6651120.2233917685,73.82465840319136],[510777.2286152405,6651121.093636122,73.75285457219137],[510777.99756351416,6651111.01556805,74.85460790319135],[510777.9174636914,6651112.065380495,74.75353798719135],[510777.31482798455,6651119.963705887,74.06562804919135],[510777.24817114964,6651120.837330476,74.06122338019135],[510777.8853732962,6651112.485966895,74.92065274419136],[510777.97204530967,6651111.350017337,75.06786023819136],[510777.33593826316,6651119.687028207,74.28504705519137],[510777.8529404364,6651112.911041741,75.04280586619134],[510777.2695291266,6651120.557406387,74.34932173119135],[510777.94562609267,6651111.696275567,75.25306914019136],[510777.3657440979,6651119.296383943,74.54126017819137],[510777.8206584568,6651113.334139104,75.12148055919135],[510777.7889659173,6651113.74951109,75.15922341819135],[510777.29249915574,6651120.256354256,74.61451945619136],[510777.91856503225,6651112.05094599,75.40956043219136],[510777.3969626907,6651118.887223649,74.75353798719135],[510777.6558293313,6651115.494439354,75.15922341819135],[510777.42905308574,6651118.466637248,74.92065274419136],[510777.8911194735,6651112.410655761,75.53718319119135],[510777.3168630458,6651119.93703376,74.85460790319135],[510777.4614859456,6651118.041562402,75.04280586619134],[510777.5254604647,6651117.203093054,75.15922341819135],[510777.4937679251,6651117.618465039,75.12148055919135],[510777.86353788234,6651112.772148418,75.63627868519136],[510777.3423812504,6651119.602584473,75.06786023819136],[510777.8269516389,6651113.251658762,75.72544333719135],[510777.79103342735,6651113.72241368,75.76821857819135],[510777.36880046735,6651119.256326244,75.25306914019136],[510777.39586152777,6651118.901655821,75.40956043219136],[510777.4233070865,6651118.541946049,75.53718319119135],[510777.4508886776,6651118.180453393,75.63627868519136],[510777.5233931327,6651117.23018813,75.76821857819135],[510777.48747492116,6651117.700943048,75.72544333719135],[510785.94189542916,6651109.395917872,68.71021190515403],[510785.8929379023,6651110.003550005,68.71021190515403],[510785.8929379023,6651110.003550005,68.84021190515402],[510784.91314737085,6651122.164135896,68.71021190515403],[510784.86418984405,6651122.771768029,68.71021190515403],[510784.91314737085,6651122.164135896,68.84021190515402],[510785.94189542916,6651109.395917872,70.53901556415403],[510785.8929379023,6651110.003550005,70.53901556415403],[510785.89145261975,6651110.021984461,70.94983087615402],[510785.94021210884,6651109.416810256,71.00460625115402],[510784.91314718296,6651122.164138228,70.53901556515402],[510785.88680794317,6651110.079631464,71.37095230415402],[510784.86418984405,6651122.771768029,70.53901556415403],[510785.9349481421,6651109.482143528,71.48187720315403],[510784.9135122323,6651122.159607449,70.74283684915402],[510785.87876431574,6651110.179464255,71.79704143915401],[510784.8658731642,6651122.750875643,71.00460625115402],[510785.925832031,6651109.5952873565,71.96477822315403],[510784.9165433893,6651122.121986504,71.15941613715403],[510785.86715746875,6651110.323521638,72.22194794315402],[510785.916351131,6651109.712958732,72.32648420815403],[510784.87113713106,6651122.685542373,71.48187720315403],[510784.9228618124,6651122.04356594,71.58374325715403],[510785.8519178618,6651110.51266671,72.63891464515402],[510785.9045566883,6651109.8593444405,72.68424205415403],[510784.88025324215,6651122.572398544,71.96477822315403],[510784.93267202034,6651121.921807388,72.01005360815404],[510785.89044729434,6651110.03446197,73.03469826915402],[510785.8330856775,6651110.746400744,73.04086356215402],[510784.8897341422,6651122.454727169,72.32648420815403],[510784.9460931306,6651121.755232432,72.43186246715402],[510785.8740629077,6651110.237815375,73.37444329615403],[510785.81081894116,6651111.022762426,73.42074436415402],[510784.9015285847,6651122.30834146,72.68424205415403],[510784.9631413191,6651121.543640307,72.84221201015403],[510785.8554862428,6651110.468378054,73.70011040615402],[510785.79202638846,6651111.2560045775,73.68715067915402],[510784.91563797876,6651122.13322393,73.03469826915402],[510784.9837179854,6651121.288254784,73.23399170415404],[510785.77161104215,6651111.509387892,73.93486041915402],[510785.83484231716,6651110.724598361,74.00847921415402],[510784.9320223654,6651121.929870525,73.37444329615403],[510785.0013396887,6651121.06954453,73.51147356415402],[510785.742191987,6651111.874519964,74.23230288915403],[510785.81229606346,6651111.004429248,74.29657756515402],[510784.9505990303,6651121.699307847,73.70011040615402],[510785.02069214004,6651120.829353245,73.77191423715402],[510785.7107278688,6651112.265034161,74.48851601215402],[510785.7880480692,6651111.305381143,74.56177529015402],[510785.04160832387,6651120.5697538275,74.01288388315402],[510784.971242956,6651121.44308754,74.00847921415402],[510785.6777723921,6651112.674058223,74.70079382115402],[510785.7623286649,6651111.624595318,74.80186373715402],[510785.0638930982,6651120.293168268,74.23230288915403],[510784.9937892096,6651121.163256651,74.29657756515402],[510785.6438966093,6651113.094504588,74.86790857815402],[510785.0953572165,6651119.902654071,74.48851601215402],[510785.7353907243,6651111.958933249,75.01511607215404],[510785.60965930833,6651113.519437904,74.99006170015403],[510785.0180372038,6651120.862304756,74.56177529015402],[510785.12831269304,6651119.493630009,74.70079382115402],[510785.57558128214,6651113.942394393,75.06873639315403],[510785.7075016425,6651112.305076189,75.20032497415403],[510785.54212549014,6651114.357628079,75.10647925215402],[510785.16218847584,6651119.0731836455,74.86790857815402],[510785.0437566082,6651120.543090581,74.80186373715402],[510785.40158169024,6651116.101975361,75.10647925215402],[510785.6789350074,6651112.659628523,75.35681626615404],[510785.1964257768,6651118.64825033,74.99006170015403],[510785.230503803,6651118.225293839,75.06873639315403],[510785.2639595951,6651117.810060155,75.10647925215402],[510785.6499624821,6651113.019218529,75.48443902515403],[510785.0706945487,6651120.20875265,75.01511607215404],[510785.62084635603,6651113.3805908235,75.58353451915403],[510785.0985836306,6651119.8626097115,75.20032497415403],[510785.5822245929,6651113.859941513,75.67269917115404],[510785.1271502656,6651119.508057376,75.35681626615404],[510785.54430802853,6651114.33053969,75.71547441215402],[510785.15612279094,6651119.148467371,75.48443902515403],[510785.18523891707,6651118.787095077,75.58353451915403],[510785.22386068024,6651118.307744387,75.67269917115404],[510785.26177724457,6651117.8371462105,75.71547441215402],[510791.2508608473,6651109.831415902,68.67094383254415],[510791.2001412827,6651110.438903492,68.67094383254415],[510791.2001412827,6651110.438903492,68.80094383254415],[510790.18508696026,6651122.596596671,68.67094383254415],[510790.1343673957,6651123.204084262,68.67094383254415],[510790.18508696026,6651122.596596671,68.80094383254415],[510791.2508608473,6651109.831415902,70.49974749154416],[510791.2001412827,6651110.438903492,70.49974749154416],[510791.1986025431,6651110.457333564,70.91056280354415],[510791.2491169424,6651109.852303315,70.96533817854414],[510790.1850867657,6651122.596599001,70.49974749254415],[510790.1343673957,6651123.204084262,70.49974749154416],[510790.18546495354,6651122.592069301,70.70356877654415],[510791.19379069924,6651110.514966855,71.33168423154414],[510791.2436635195,6651109.917621044,71.44260913054416],[510790.1361113005,6651123.183196848,70.96533817854414],[510790.18860520545,6651122.554457305,71.12014806454415],[510791.1854575724,6651110.614775898,71.75777336654414],[510791.234219309,6651110.030737959,71.92551015054416],[510790.1415647235,6651123.117879118,71.44260913054416],[510790.1951510358,6651122.476055396,71.54447518454415],[510791.17343298154,6651110.758799013,72.18267987054416],[510791.2243971805,6651110.148381343,72.28721613554416],[510790.15100893396,6651123.004762203,71.92551015054416],[510790.20531432447,6651122.354325807,71.97078553554417],[510791.15764488355,6651110.947899089,72.59964657254415],[510791.2121782422,6651110.294732231,72.64497398154415],[510790.16083106253,6651122.88711882,72.28721613554416],[510790.21921847604,6651122.187790476,72.39259439454416],[510791.1975610349,6651110.469808105,72.99543019654415],[510791.1381349073,6651111.181577524,73.00159548954414],[510790.1730500008,6651122.740767932,72.64497398154415],[510790.23688024847,6651121.976248683,72.80294393754416],[510791.1805869553,6651110.673113138,73.33517522354416],[510791.1150667654,6651111.457873467,73.38147629154415],[510790.187667208,6651122.565692058,72.99543019654415],[510791.16134169477,6651110.90362097,73.66084233354415],[510790.2581974926,6651121.720923911,73.19472363154416],[510791.09559784713,6651111.691060135,73.64788260654416],[510790.20464128774,6651122.362387026,73.33517522354416],[510791.07444772887,6651111.944383178,73.89559234654415],[510790.27645342145,6651121.5022656815,73.47220549154414],[510791.1399547704,6651111.159780329,73.96921114154415],[510790.22388654825,6651122.131879194,73.66084233354415],[510790.29650238977,6651121.262131533,73.73264616454415],[510791.0439698481,6651112.309428392,74.19303481654416],[510791.1165970511,6651111.439544652,74.25730949254415],[510790.3181713712,6651121.002593868,73.97361581054415],[510790.2452734725,6651121.875719834,73.96921114154415],[510791.01137329993,6651112.699849695,74.44924793954415],[510791.0914763436,6651111.740424957,74.52250721754415],[510790.3412582002,6651120.726074102,74.19303481654416],[510790.26863119187,6651121.595955512,74.25730949254415],[510790.9772317177,6651113.108776461,74.66152574854415],[510791.06483126816,6651112.059563198,74.76259566454415],[510790.3738547484,6651120.335652799,74.44924793954415],[510790.9421367065,6651113.529122812,74.82864050554414],[510790.2937518994,6651121.295075206,74.52250721754415],[510791.03692380013,6651112.393821598,74.97584799954417],[510790.4079963306,6651119.926726034,74.66152574854415],[510790.9066671655,6651113.953955046,74.95079362754416],[510790.8713626319,6651114.376810925,75.02946832054415],[510790.3203969748,6651120.975936965,74.76259566454415],[510790.4430913418,6651119.506379684,74.82864050554414],[510790.83670272736,6651114.791945835,75.06721117954415],[510791.0080309581,6651112.739882199,75.16105690154416],[510790.4785608828,6651119.08154745,74.95079362754416],[510790.69110059395,6651116.535878179,75.06721117954415],[510790.51386541646,6651118.65869157,75.02946832054415],[510790.54852532095,6651118.24355666,75.06721117954415],[510790.3483044428,6651120.641678565,74.97584799954417],[510790.9784361769,6651113.094350194,75.31754819354417],[510790.948420897,6651113.453854661,75.44517095254415],[510790.37719728483,6651120.295617964,75.16105690154416],[510790.9182568479,6651113.815140994,75.54426644654416],[510790.4067920661,6651119.94114997,75.31754819354417],[510790.8782450431,6651114.294377658,75.63343109854416],[510790.436807346,6651119.581645502,75.44517095254415],[510790.8389638178,6651114.7648638915,75.67620633954415],[510790.466971395,6651119.220359169,75.54426644654416],[510790.5069831999,6651118.741122505,75.63343109854416],[510790.5462644252,6651118.270636272,75.67620633954415],[510795.0084456514,6651110.149023901,68.64155541765334],[510794.95647894987,6651110.756406079,68.64155541765334],[510794.95647894987,6651110.756406079,68.77155541765335],[510793.9164655865,6651122.911989608,68.64155541765334],[510793.864498885,6651123.519371784,68.64155541765334],[510793.9164655865,6651122.911989608,68.77155541765335],[510795.0084456514,6651110.149023901,70.47035907665334],[510794.95647894987,6651110.756406079,70.47035907665334],[510793.91646538716,6651122.911991938,70.47035907765333],[510793.864498885,6651123.519371784,70.47035907665334],[510794.95490237436,6651110.774832951,70.88117438865333],[510795.0066588658,6651110.169907692,70.93594976365333],[510793.91685287433,6651122.9074630225,70.67418036165333],[510794.9499722127,6651110.832456242,71.30229581665333],[510793.8662856706,6651123.498487995,70.93594976365333],[510795.00107134925,6651110.235214085,71.41322071565334],[510793.92007034144,6651122.869857553,71.09075964965334],[510794.9414341836,6651110.932247965,71.72838495165335],[510793.8718731871,6651123.433181599,71.41322071565334],[510793.9267771263,6651122.791469249,71.51508676965334],[510794.9913949164,6651110.348311373,71.89612173565334],[510794.92911392177,6651111.076246088,72.15329145565333],[510794.98133127275,6651110.465934342,72.25782772065334],[510793.88154962007,6651123.320084312,71.89612173565334],[510793.9371903188,6651122.669760783,71.94139712065333],[510794.91293761216,6651111.265313352,72.57025815765333],[510794.96881188464,6651110.612259835,72.61558556665334],[510793.89161326364,6651123.202461343,72.25782772065334],[510793.9514363577,6651122.503254349,72.36320597965333],[510794.9538352567,6651110.787305329,72.96604178165335],[510793.90413265175,6651123.05613585,72.61558556665334],[510794.8929479077,6651111.498951239,72.97220707465333],[510793.96953241323,6651122.291749264,72.77355552265335],[510794.93644380354,6651110.990575083,73.30578680865334],[510793.91910927976,6651122.881090356,72.96604178165335],[510794.8693125461,6651111.775199239,73.35208787665334],[510793.9913738244,6651122.036468796,73.16533521665333],[510794.91672532377,6651111.221042917,73.63145391865334],[510794.8493649091,6651112.008345443,73.61849419165333],[510793.93650073285,6651122.677820602,73.30578680865334],[510794.0100786459,6651121.817848509,73.44281707665333],[510794.8276947333,6651112.261624526,73.86620393165335],[510794.8948125191,6651111.477157826,73.93982272665333],[510793.95621921256,6651122.447352768,73.63145391865334],[510794.0306205958,6651121.5777560305,73.70325774965333],[510794.7964674358,6651112.626606397,74.16364640165334],[510794.8708804599,6651111.756873603,74.22792107765333],[510794.0528223931,6651121.318263401,73.94422739565333],[510793.97813201725,6651122.1912378585,73.93982272665333],[510794.0764769012,6651121.041791618,74.16364640165334],[510794.76306937524,6651113.016959954,74.41985952465333],[510794.8451420624,6651112.057701698,74.49311880265333],[510794.00206407654,6651121.911522082,74.22792107765333],[510794.72808829,6651113.42581576,74.63213733365333],[510794.1098749616,6651120.651438063,74.41985952465333],[510794.81784181466,6651112.376784561,74.73320724965333],[510794.02780247387,6651121.6106939865,74.49311880265333],[510794.6921303321,6651113.846089169,74.79925209065334],[510794.1448560469,6651120.242582257,74.63213733365333],[510794.7892481335,6651112.710984959,74.94645958465334],[510794.6557886352,6651114.270847687,74.92140521265333],[510794.05510272173,6651121.291611123,74.73320724965333],[510794.18081400485,6651119.822308846,74.79925209065334],[510794.6196160029,6651114.693630189,75.00007990565334],[510794.5841038503,6651115.108693064,75.03782276465333],[510794.2171557018,6651119.3975503305,74.92140521265333],[510794.75964484905,6651113.0569855105,75.13166848665334],[510794.4349215247,6651116.852322794,75.03782276465333],[510794.2533283341,6651118.974767827,75.00007990565334],[510794.08369640284,6651120.957410725,74.94645958465334],[510794.28884048655,6651118.559704953,75.03782276465333],[510794.7293223656,6651113.411391997,75.28815977865335],[510794.11329968733,6651120.6114101745,75.13166848665334],[510794.6985690438,6651113.770834081,75.41578253765334],[510794.14362217084,6651120.257003688,75.28815977865335],[510794.6676632947,6651114.132057722,75.51487803165334],[510794.1743754926,6651119.897561604,75.41578253765334],[510794.6266676447,6651114.611211228,75.60404268365333],[510794.5864205384,6651115.08161582,75.64681792465333],[510794.2052812416,6651119.536337962,75.51487803165334],[510794.2462768916,6651119.057184458,75.60404268365333],[510794.2865239979,6651118.5867798645,75.64681792465333],[510801.89728471264,6651124.224541166,68.5737739278946],[510801.951937106,6651123.617394755,68.5737739278946],[510803.0456994135,6651111.4665296525,68.5737739278946],[510803.10035180685,6651110.859383242,68.5737739278946],[510801.951937106,6651123.617394755,68.70377392789462],[510803.0456994135,6651111.4665296525,68.70377392789462],[510801.89728471264,6651124.224541166,70.40257758689461],[510801.95193689625,6651123.617397084,70.4025775878946],[510803.0456994135,6651111.4665296525,70.40257758689461],[510803.10035180685,6651110.859383242,70.40257758689461],[510801.95234440913,6651123.612869927,70.6063988718946],[510803.04404135904,6651111.484949374,70.8133928988946],[510801.8991638411,6651124.203665481,70.8681682738946],[510803.0984726784,6651110.880258927,70.8681682738946],[510801.95572815824,6651123.575279055,71.0229781598946],[510803.03885640175,6651111.542550296,71.2345143268946],[510801.90504012606,6651124.138384436,71.34543922589461],[510803.0925963934,6651110.945539972,71.34543922589461],[510801.96278155665,6651123.496921178,71.44730527989461],[510803.0298771186,6651111.642303282,71.6606034618946],[510801.915216647,6651124.02533105,71.82834024589461],[510803.0824198726,6651111.058593357,71.82834024589461],[510801.97373291344,6651123.375259956,71.8736156308946],[510803.016920133,6651111.786245511,72.0855099658946],[510801.9258003898,6651123.907753739,72.19004623089461],[510803.0718361297,6651111.1761706695,72.19004623089461],[510801.9887152021,6651123.208818156,72.2954244898946],[510802.9999078155,6651111.975239386,72.5024766678946],[510801.9389667926,6651123.761485045,72.54780407689461],[510803.0586697269,6651111.322439362,72.54780407689461],[510802.0077464801,6651122.99739517,72.70577403289462],[510801.95471742784,6651123.586507498,72.89826029189462],[510803.04291909165,6651111.497416909,72.89826029189462],[510802.97888502275,6651112.20878658,72.9044255848946],[510802.0307166775,6651122.742213795,73.09755372689462],[510801.97300768894,6651123.383316647,73.23800531889461],[510803.02462883067,6651111.70060776,73.23800531889461],[510802.9540281618,6651112.484927348,73.28430638689461],[510802.05038818304,6651122.52367837,73.3750355868946],[510801.9937452397,6651123.152938274,73.5636724288946],[510802.93304961064,6651112.717983052,73.5507127018946],[510803.0038912799,6651111.930986134,73.5636724288946],[510802.0719917616,6651122.283679088,73.6354762598946],[510802.9102594982,6651112.971163821,73.7984224418946],[510802.0167905203,6651122.89692278,73.8720412368946],[510802.0953409703,6651122.024287186,73.8764459058946],[510802.98084599926,6651112.187001626,73.8720412368946],[510802.12021796743,6651121.747922719,74.09586491189461],[510802.87741834234,6651113.336004017,74.09586491189461],[510802.04195941257,6651122.617315581,74.1601395878946],[510802.95567710686,6651112.466608825,74.1601395878946],[510802.15534207347,6651121.357720688,74.3520780348946],[510802.8422942363,6651113.726206049,74.3520780348946],[510802.06902799645,6651122.316604258,74.4253373128946],[510802.9286085231,6651112.767320149,74.4253373128946],[510802.1921310166,6651120.949023586,74.5643558438946],[510802.80550529313,6651114.1349031525,74.5643558438946],[510802.09773914865,6651121.997645252,74.6654257598946],[510802.89989737084,6651113.086279154,74.6654257598946],[510802.2299473184,6651120.5289133135,74.7314706008946],[510802.7676889914,6651114.555013424,74.7314706008946],[510802.26816719095,6651120.104319678,74.85362372289461],[510802.7294691188,6651114.979607061,74.85362372289461],[510802.12781058036,6651121.663574581,74.87867809489461],[510802.8698259392,6651113.420349826,74.87867809489461],[510802.30620926153,6651119.681701284,74.9322984158946],[510802.6914270481,6651115.402225453,74.9322984158946],[510802.3435567181,6651119.2667995235,74.9700412748946],[510802.49718737236,6651117.560080119,74.9700412748946],[510802.65407959156,6651115.817127215,74.9700412748946],[510802.15894379246,6651121.317708337,75.06388699689461],[510802.83869272703,6651113.766216071,75.06388699689461],[510802.19083337265,6651120.963439422,75.22037828889462],[510802.80680314684,6651114.120484985,75.22037828889462],[510802.2231760573,6651120.60413686,75.34800104789461],[510802.7744604622,6651114.479787547,75.34800104789461],[510802.2556790467,6651120.243053436,75.44709654189461],[510802.7419574728,6651114.840870972,75.44709654189461],[510802.2987933934,6651119.764085923,75.5362611938946],[510802.698843126,6651115.319838485,75.5362611938946],[510802.341120511,6651119.293863927,75.5790364348946],[510802.6565160085,6651115.790060479,75.5790364348946],[510810.1574715679,6651124.987029978,68.49766535314345],[510810.2148856826,6651124.380138498,68.49766535314345],[510810.2148856826,6651124.380138498,68.62766535314343],[510811.36391851935,6651112.234375359,68.49766535314345],[510811.421332634,6651111.627483879,68.49766535314345],[510811.36391851935,6651112.234375359,68.62766535314343],[510810.1574715679,6651124.987029978,70.32646901214345],[510810.2148854623,6651124.380140827,70.32646901314342],[510810.2153135678,6651124.375615571,70.53029029714344],[510811.36391851935,6651112.234375359,70.32646901214345],[510810.1594456534,6651124.966163059,70.79205969914342],[510811.421332634,6651111.627483879,70.32646901214345],[510810.2188683061,6651124.338040482,70.94686958514345],[510811.36217667925,6651112.252787345,70.73728432414343],[510811.4193585485,6651111.648350798,70.79205969914342],[510810.1656188817,6651124.900909424,71.26933065114343],[510810.22627813026,6651124.259715507,71.37119670514343],[510810.56908495084,6651125.026017172,68.49370265615114],[510810.6266366848,6651124.419138728,68.49370265615114],[510811.3567297131,6651112.3103640815,71.15840575214342],[510810.6266366848,6651124.419138728,68.62370265615114],[510811.4131853202,6651111.713604433,71.26933065114343],[510810.1763096474,6651124.787903508,71.75223167114345],[510810.2377828864,6651124.138105368,71.79750705614343],[510811.7784237074,6651112.273636458,68.49370265615114],[510811.8359754414,6651111.666758015,68.49370265615114],[510811.34729668446,6651112.410075184,71.58449488714342],[510811.7784237074,6651112.273636458,68.62370265615114],[510810.18742821325,6651124.670375564,72.11393765614343],[510811.40249455447,6651111.826610349,71.75223167114345],[510810.2535222673,6651123.971733454,72.21931591514344],[510811.3336849502,6651112.553956972,72.00940139114343],[510810.20125994703,6651124.524168288,72.47169550214343],[510811.3913759888,6651111.944138291,72.11393765614343],[510810.2735152431,6651123.760399242,72.62966545814344],[510810.217806501,6651124.349264212,72.82215171714343],[510811.315812958,6651112.742871491,72.42636809314342],[510811.3775442549,6651112.090345569,72.47169550214343],[510810.2976461817,6651123.505325014,73.02144515214343],[510810.23702101444,6651124.1461586775,73.16189674414345],[510811.2937278312,6651112.9763206225,72.82831701014342],[510811.36099770083,6651112.265249644,72.82215171714343],[510810.56908495084,6651125.026017172,70.32250631515114],[510810.626636464,6651124.419141056,70.32250631615113],[510810.3183117374,6651123.286881349,73.29892701214342],[510810.2588064852,6651123.915877035,73.48756385414343],[510810.62706559565,6651124.414615897,70.52632760015113],[510811.3417831874,6651112.468355179,73.16189674414345],[510810.34100699855,6651123.046982837,73.55936768514343],[510811.2676148913,6651113.252345445,73.20819781214342],[510810.5710637681,6651125.005150702,70.78809700215113],[510811.7784237074,6651112.273636458,70.32250631515114],[510811.8359754414,6651111.666758015,70.32250631515114],[510810.28301630117,6651123.659969039,73.79593266214343],[510810.3655361008,6651122.787699851,73.80033733114344],[510811.2455762418,6651113.485303292,73.47460412714342],[510811.31999771675,6651112.698636821,73.48756385414343],[510810.6306288545,6651124.377041617,70.94290688815114],[510810.39167019434,6651122.511451426,74.01975633714343],[510811.2216344883,6651113.738377754,73.72231386714343],[510810.3094570402,6651123.380479243,74.08403101314344],[510811.77667769225,6651112.292048049,70.73332162715114],[510811.29578790074,6651112.954544818,73.79593266214343],[510810.5772517934,6651124.939898468,71.26536795415115],[510811.8339966241,6651111.687624484,70.78809700215113],[510810.42856920895,6651122.121413235,74.27596946014343],[510810.6380564398,6651124.298718323,71.36723400815114],[510811.1871337872,6651114.103064761,74.01975633714343],[510810.337893467,6651123.079894183,74.34922873814342],[510811.2693471617,6651113.234034614,74.08403101314344],[510810.46721718885,6651121.712887738,74.48824726914343],[510811.7712176699,6651112.349623549,71.15444305515113],[510811.1502347726,6651114.493102952,74.27596946014343],[510810.36805546505,6651122.761069104,74.58931718514343],[510811.240910735,6651113.534619673,74.34922873814342],[510810.5879681845,6651124.826894979,71.74826897415115],[510811.8278085988,6651111.752876718,71.26536795415115],[510810.5069444423,6651121.292953864,74.65536202614342],[510810.6495887723,6651124.177110796,71.79354435915116],[510811.1115867927,6651114.901628448,74.48824726914343],[510810.399646481,6651122.427138704,74.80256952014344],[510810.54709566006,6651120.868538506,74.77751514814344],[510811.2107487368,6651113.853444751,74.58931718514343],[510811.07185953925,6651115.321562323,74.65536202614342],[510810.58706009114,6651120.446097565,74.85618984114345],[510811.7617620306,6651112.449332511,71.58053219015113],[510810.62629480753,6651120.031370016,74.89393270014344],[510810.4323529317,6651122.0814176835,74.98777842214344],[510811.0317083214,6651115.74597768,74.77751514814344],[510810.59911340097,6651124.70936956,72.10997495915115],[510810.7876888007,6651118.3253672365,74.89393270014344],[510810.9917438904,6651116.168418622,74.85618984114345],[510811.17915772105,6651114.1873751525,74.80256952014344],[510810.952509174,6651116.583146171,74.89393270014344],[510811.8170922077,6651111.865880206,71.74826897415115],[510810.4658539716,6651121.72729752,75.14426971414343],[510810.66536587983,6651124.010742455,72.21535321815114],[510811.14645127015,6651114.533096174,74.98777842214344],[510810.49983101257,6651121.368145825,75.27189247314342],[510811.7481176696,6651112.5932112085,72.00543869415114],[510810.61297828896,6651124.563165423,72.46773280515114],[510811.11295023025,6651114.887216336,75.14426971414343],[510810.53397645894,6651121.007214014,75.37098796714345],[510811.8059469912,6651111.983405625,72.10997495915115],[510810.57926948083,6651120.528447612,75.46015261914343],[510811.0789731894,6651115.246368032,75.27189247314342],[510810.6237354928,6651120.058423055,75.50292786014343],[510810.68540677807,6651123.799412782,72.62570276115115],[510811.0448277431,6651115.607299843,75.37098796714345],[510810.9995347212,6651116.086066245,75.46015261914343],[510810.9550687091,6651116.556090802,75.50292786014343],[510810.6295645044,6651124.388265104,72.81818902015114],[510811.73020283884,6651112.78212167,72.42240539615113],[510811.79208210326,6651112.129609763,72.46773280515114],[510810.7095955576,6651123.544344032,73.01748245515115],[510810.6488250742,6651124.185163932,73.15793404715114],[510811.70806477504,6651113.015565787,72.82435431315113],[510811.7754958878,6651112.304510082,72.81818902015114],[510810.7303106478,6651123.3259050585,73.29496431515113],[510810.6706627638,6651123.954887237,73.48360115715114],[510811.756235318,6651112.507611254,73.15793404715114],[510810.7530603086,6651123.0860117,73.55540498815114],[510811.6818892434,6651113.291584682,73.20423511515114],[510810.69493060984,6651123.698984737,73.79196996515114],[510810.77764820616,6651122.826734283,73.79637463415114],[510811.65979776817,6651113.524537525,73.47064143015113],[510811.73439762834,6651112.73788795,73.48360115715114],[510810.803844942,6651122.550491793,74.01579364015114],[510810.72143472626,6651123.419500943,74.08006831615114],[510811.6357986272,6651113.777606551,73.71835117015114],[510811.71012978244,6651112.99379045,73.79196996515114],[510810.84083240206,6651122.160461978,74.27200676315114],[510810.7499393139,6651123.11892234,74.34526604115113],[510811.60121522925,6651114.142285723,74.01579364015114],[510811.68362566596,6651113.273274244,74.08006831615114],[510810.8795730196,6651121.751945255,74.48428457215114],[510811.5642277693,6651114.532315538,74.27200676315114],[510810.7801736092,6651122.800104109,74.58535448815114],[510811.65512107825,6651113.573852846,74.34526604115113],[510810.9193954977,6651121.3320204,74.65139932915113],[510811.52548715175,6651114.94083226,74.48428457215114],[510810.8118403474,6651122.466180881,74.79860682315116],[510810.9596429564,6651120.907614159,74.77355245115115],[510811.6248867831,6651113.892671078,74.58535448815114],[510811.48566467356,6651115.360757115,74.65139932915113],[510810.9997031806,6651120.485182291,74.85222714415114],[510811.03903194104,6651120.07046365,74.88997000315113],[510810.84462519427,6651122.120467287,74.98381572515115],[510811.4454172149,6651115.785163356,74.77355245115115],[510811.2008127892,6651118.3644975135,74.88997000315113],[510811.40535699076,6651116.207595225,74.85222714415114],[510811.5932200448,6651114.226594306,74.79860682315116],[510811.36602823023,6651116.622313866,74.88997000315113],[510810.8782065349,6651121.7663547285,75.14030701715116],[510811.56043519796,6651114.5723079005,74.98381572515115],[510810.91226501734,6651121.407210747,75.26792977615115],[510810.9464923089,6651121.046286688,75.36702527015115],[510811.52685385733,6651114.926420458,75.14030701715116],[510810.9918938964,6651120.56753057,75.45618992215115],[510811.4927953749,6651115.285564439,75.26792977615115],[510811.0364664917,6651120.097516108,75.49896516315114],[510811.4585680833,6651115.646488498,75.36702527015115],[510811.41316649574,6651116.125244617,75.45618992215115],[510811.3685939005,6651116.595259079,75.49896516315114],[510818.91601005243,6651125.836948804,68.40985667120633],[510818.976352508,6651125.230341487,68.40985667120633],[510818.976352508,6651125.230341487,68.53985667120634],[510820.1839904423,6651113.09026532,68.40985667120633],[510820.24433289777,6651112.483658005,68.40985667120633],[510820.1839904423,6651113.09026532,68.53985667120634],[510818.91601005243,6651125.836948804,70.23866033020633],[510818.97635227646,6651125.230343814,70.23866033120632],[510818.97680221696,6651125.225820677,70.44248161520632],[510818.91808482393,6651125.816091655,70.70425101720632],[510818.9805382606,6651125.188263183,70.85906090320633],[510820.1839904423,6651113.09026532,70.23866033020633],[510818.92457291065,6651125.750868574,71.18152196920633],[510820.24433289777,6651112.483658005,70.23866033020633],[510818.98832601437,6651125.109974882,71.28338802320633],[510820.18215976167,6651113.108668686,70.64947564220633],[510820.2422581264,6651112.5045151515,70.70425101720632],[510818.93580894655,6651125.637915569,71.66442298920633],[510819.00041755725,6651124.988421684,71.70969837420633],[510820.17643497925,6651113.166218462,71.07059707020632],[510818.94749460195,6651125.520442656,72.02612897420633],[510820.23577003967,6651112.5697382325,71.18152196920633],[510819.0169597072,6651124.822127669,72.13150723320632],[510820.1665208299,6651113.2658828795,71.49668620520632],[510818.96203180746,6651125.374303838,72.38388682020633],[510820.22453400376,6651112.682691237,71.66442298920633],[510819.0379724018,6651124.610892409,72.54185677620634],[510818.9794222994,6651125.199481656,72.73434303520634],[510820.1522148448,6651113.409697298,71.92159270920632],[510820.21284834837,6651112.800164151,72.02612897420633],[510819.0633341111,6651124.355937613,72.93363647020632],[510818.99961682694,6651124.996471221,73.07408806220633],[510820.1334313121,6651113.598523363,72.33855941120632],[510820.19831114286,6651112.946302971,72.38388682020633],[510819.0850536898,6651124.137596229,73.21111833020632],[510819.02251344064,6651124.766297404,73.39975517220633],[510820.11021975894,6651113.831863187,72.74050832820632],[510819.10890649655,6651123.897810046,73.47155900320632],[510820.1809206509,6651113.1211251505,72.73434303520634],[510819.0479580504,6651124.51050923,73.70812398020632],[510819.1346866775,6651123.6386484625,73.71252864920632],[510820.08277495846,6651114.107758766,73.12038913020633],[510820.16072612326,6651113.324135586,73.07408806220633],[510819.1621537104,6651123.362529384,73.93194765520633],[510819.07574736886,6651124.231150298,73.99622233120633],[510820.05961225304,6651114.340607535,73.38679544520632],[510820.1378295097,6651113.554309403,73.39975517220633],[510819.2009347166,6651122.9726738185,74.18816077820632],[510819.10563416284,6651123.930705981,74.26142005620632],[510820.034449378,6651114.593563502,73.63450518520634],[510820.1123848999,6651113.810097576,73.70812398020632],[510819.24155389227,6651122.564339605,74.40043858720632],[510819.137334539,6651123.612030185,74.50150850320632],[510819.99818900827,6651114.958079752,73.93194765520633],[510819.2833073886,6651122.144602355,74.56755334420632],[510820.08459558134,6651114.089456508,73.99622233120633],[510819.17053681816,6651123.278256139,74.71476083820633],[510819.95940800203,6651115.347935317,74.18816077820632],[510819.3255064731,6651121.720385721,74.68970646620633],[510820.0547087875,6651114.389900825,74.26142005620632],[510819.3675092439,6651121.2981425775,74.76838115920633],[510819.2049114239,6651122.932696994,74.89996974020633],[510819.9187888264,6651115.75626953,74.40043858720632],[510819.4087450819,6651120.883609215,74.80612401820632],[510819.87703533005,6651116.176006781,74.56755334420632],[510819.57837078994,6651119.178405232,74.80612401820632],[510819.24012114585,6651122.57874264,75.05646103220633],[510820.02300841134,6651114.7085766215,74.50150850320632],[510819.8348362456,6651116.600223415,74.68970646620633],[510819.79283347464,6651117.022466558,74.76838115920633],[510819.7515976367,6651117.43699992,74.80612401820632],[510819.2758311466,6651122.219759109,75.18408379120633],[510819.98980613204,6651115.0423506675,74.71476083820633],[510819.31171814207,6651121.858996295,75.28317928520633],[510819.9554315264,6651115.387909813,74.89996974020633],[510819.3593212824,6651121.380454067,75.37234393720632],[510819.4060552323,6651120.910649587,75.41511917820633],[510819.92022180447,6651115.741864166,75.05646103220633],[510819.88451180374,6651116.100847697,75.18408379120633],[510819.84862480813,6651116.461610511,75.28317928520633],[510819.8010216678,6651116.940152741,75.37234393720632],[510819.75428771804,6651117.409957219,75.41511917820633],[510827.25910479826,6651126.686262168,68.31939778668155],[510827.32223669457,6651126.079938812,68.31939778668155],[510827.32223669457,6651126.079938812,68.44939778668154],[510828.58569991105,6651113.945545568,68.31939778668155],[510828.64883180737,6651113.339222212,68.31939778668155],[510828.58569991105,6651113.945545568,68.44939778668154],[510827.25910479826,6651126.686262168,70.14820144568156],[510827.3222364523,6651126.079941139,70.14820144668154],[510827.32270719216,6651126.075420119,70.35202273068155],[510827.26127547974,6651126.665414784,70.61379213268154],[510827.32661594136,6651126.037880206,70.76860201868156],[510827.2680634902,6651126.600222234,71.09106308468155],[510827.3347636982,6651125.959628552,71.19292913868155],[510828.58569991105,6651113.945545568,70.14820144568156],[510828.64883180737,6651113.339222212,70.14820144568156],[510827.2798189326,6651126.487322106,71.57396410468156],[510827.347414195,6651125.838132255,71.61923948968155],[510828.5837846038,6651113.963940319,70.55901675768155],[510827.2920447788,6651126.369904182,71.93567008968155],[510828.6466611259,6651113.360069597,70.61379213268154],[510827.36472103617,6651125.671916084,72.04104834868156],[510828.5777951828,6651114.021463157,70.98013818568154],[510827.30725399335,6651126.223833772,72.29342793568155],[510828.63987311535,6651113.425262147,71.09106308468155],[510827.3867050812,6651125.460779707,72.45139789168155],[510827.3254483928,6651126.049093428,72.64388415068154],[510828.5674227337,6651114.121080917,71.40622732068155],[510828.62811767304,6651113.538162275,71.57396410468156],[510827.4132391822,6651125.20594426,72.84317758568154],[510827.3465764494,6651125.846178025,72.98362917768156],[510828.5524554282,6651114.264828015,71.83113382468156],[510827.4359627881,6651124.987705083,73.12065944568154],[510828.61589182675,6651113.655580199,71.93567008968155],[510827.37053150113,6651125.616111954,73.30929628768155],[510828.53280359216,6651114.453565687,72.24810052668154],[510827.46091823484,6651124.748031147,73.38110011868154],[510828.6006826123,6651113.801650608,72.29342793568155],[510827.3971523348,6651125.360443519,73.61766509568155],[510827.4878901519,6651124.48899088,73.62206976468156],[510828.5085190422,6651114.686796282,72.65004944368154],[510828.5824882128,6651113.976390952,72.64388415068154],[510827.42622626555,6651125.081215358,73.90576344668155],[510827.5166268989,6651124.213001057,73.84148877068155],[510828.4798055555,6651114.962562713,73.02993024568154],[510828.5613601561,6651114.179306355,72.98362917768156],[510827.4574946314,6651124.780911683,74.17096117168154],[510827.5572006284,6651123.8233279865,74.09770189368155],[510828.45557211153,6651115.195302483,73.29633656068155],[510828.5374051045,6651114.409372427,73.30929628768155],[510827.4906604157,6651124.462385063,74.41104961868155],[510827.59969750006,6651123.41518492,74.30997970268155],[510828.42924603634,6651115.448140036,73.54404630068154],[510827.64338112855,6651122.995644155,74.47709445968155],[510828.5107842709,6651114.665040862,73.61766509568155],[510827.52539753134,6651124.12876726,74.62430195368155],[510828.3913094644,6651115.812485652,73.84148877068155],[510827.68753094313,6651122.571626102,74.59924758168154],[510827.5613611663,6651123.783369876,74.80951085568155],[510828.4817103401,6651114.944269022,73.90576344668155],[510827.7314753693,6651122.149580615,74.67792227468156],[510828.35073573486,6651116.202158721,74.09770189368155],[510827.7746174096,6651121.7352413,74.71566513368155],[510827.5981985223,6651123.429581213,74.96600214768155],[510828.30823886313,6651116.610301789,74.30997970268155],[510828.4504419742,6651115.244572698,74.17096117168154],[510827.9520843777,6651120.030835545,74.71566513368155],[510827.6355592835,6651123.070765727,75.09362490668154],[510828.26455523475,6651117.029842554,74.47709445968155],[510828.22040542006,6651117.453860608,74.59924758168154],[510828.41727618984,6651115.563099318,74.41104961868155],[510828.1333189536,6651118.290245407,74.71566513368155],[510828.176460994,6651117.875906092,74.67792227468156],[510827.6731052213,6651122.710171792,75.19272040068157],[510827.7229089042,6651122.231853574,75.28188505268155],[510828.38253907434,6651115.89671712,74.62430195368155],[510827.7718032168,6651121.762269015,75.32466029368155],[510828.34657543927,6651116.242114503,74.80951085568155],[510828.3097380833,6651116.595903168,74.96600214768155],[510828.27237732214,6651116.954718653,75.09362490668154],[510828.2348313843,6651117.3153125895,75.19272040068157],[510828.13613338885,6651118.263215365,75.32466029368155],[510828.1850277013,6651117.793630808,75.28188505268155],[510830.15970154497,6651126.99062476,68.28638856520544],[510830.2238032305,6651126.384403165,68.28638856520544],[510830.2238032305,6651126.384403165,68.41638856520542],[510831.50667490816,6651114.2520464705,68.28638856520544],[510831.5707765937,6651113.645824876,68.28638856520544],[510831.50667490816,6651114.2520464705,68.41638856520542],[510830.15970154497,6651126.99062476,70.11519222420543],[510830.22380298446,6651126.384405491,70.11519222520542],[510830.2242809555,6651126.37988523,70.31901350920542],[510830.161905571,6651126.969780874,70.58078291120542],[510830.2282497482,6651126.342351617,70.73559279720543],[510830.16879785416,6651126.904599266,71.05805386320544],[510830.2365226654,6651126.2641130965,71.15991991720543],[510830.1807338756,6651126.791718086,71.54095488320543],[510831.50667490816,6651114.2520464705,70.11519222420543],[510831.5707765937,6651113.645824876,70.11519222420543],[510830.2493674905,6651126.14263719,71.58623026820543],[510830.19314752705,6651126.67431987,71.90266086820543],[510831.5047301793,6651114.270438133,70.52600753620543],[510830.26694018755,6651125.976448917,72.00803912720542],[510831.56857256766,6651113.666668761,70.58078291120542],[510830.20859037514,6651126.528273975,72.26041871420543],[510831.4986487529,6651114.327951317,70.94712896420543],[510830.2892619365,6651125.765347974,72.41838867020543],[510831.56168028445,6651113.73185037,71.05805386320544],[510830.22706426453,6651126.353562958,72.61087492920542],[510831.4881169693,6651114.427552359,71.37321809920542],[510830.3162036363,6651125.510555296,72.81016836420542],[510830.2485168761,6651126.150681609,72.95061995620543],[510831.549744263,6651113.84473155,71.54095488320543],[510831.47291974624,6651114.571275331,71.79812460320542],[510830.33927630686,6651125.292352748,73.08765022420542],[510830.2728399089,6651125.9206541525,73.27628706620543],[510831.53733061155,6651113.962129766,71.90266086820543],[510830.364615102,6651125.052719036,73.34809089720542],[510831.45296603214,6651114.759981328,72.21509130520543],[510830.2998696737,6651125.665028627,73.58465587420542],[510831.5218877635,6651114.108175661,72.26041871420543],[510830.39200134337,6651124.793722245,73.58906054320542],[510831.42830843956,6651114.99317278,72.61704022220542],[510830.32939021837,6651125.385847329,73.87275422520543],[510831.5034138741,6651114.282886677,72.61087492920542],[510830.4211795246,6651124.517778742,73.80847954920543],[510830.36113890755,6651125.085594055,74.13795195020542],[510831.39915387577,6651115.268892925,72.99692102420542],[510830.46237652027,6651124.128171072,74.06469267220542],[510831.48196126265,6651114.485768025,72.95061995620543],[510831.37454817403,6651115.501593635,73.26332733920542],[510830.3948141621,6651124.767120893,74.37804039720542],[510830.50552619994,6651123.720096505,74.27697048120544],[510831.45763822977,6651114.7157954825,73.27628706620543],[510831.34781769564,6651115.754388754,73.51103707920542],[510830.54988086637,6651123.300626152,74.44408523820542],[510830.4300848855,6651124.433559084,74.59129273220543],[510831.43060846505,6651114.971421009,73.58465587420542],[510830.59470888047,6651122.876679264,74.56623836020543],[510831.3092983679,6651116.118673219,73.80847954920543],[510830.46660096943,6651124.088219669,74.77650163420545],[510830.63932835095,6651122.454704611,74.64491305320543],[510831.4010879203,6651115.250602305,73.87275422520543],[510830.6831331099,6651122.040434836,74.68265591220542],[510831.26810137235,6651116.508280889,74.06469267220542],[510830.5040041958,6651123.734490382,74.93299292620543],[510831.2249516927,6651116.916355457,74.27697048120544],[510830.8633262046,6651120.3363151355,74.68265591220542],[510831.36933923105,6651115.550855581,74.13795195020542],[510830.5419388675,6651123.375735118,75.06061568520542],[510831.1805970262,6651117.33582581,74.44408523820542],[510830.58006156044,6651123.015201701,75.15971117920543],[510831.1357690121,6651117.759772698,74.56623836020543],[510831.0473447827,6651118.596017126,74.68265591220542],[510831.09114954167,6651118.181747352,74.64491305320543],[510831.3356639766,6651115.869328741,74.37804039720542],[510830.6306302937,6651122.53696376,75.24887583120542],[510831.30039325304,6651116.202890552,74.59129273220543],[510830.68027568725,6651122.067458014,75.29165107220543],[510831.2638771692,6651116.548229965,74.77650163420545],[510831.22647394286,6651116.901959253,74.93299292620543],[510831.1885392712,6651117.260714518,75.06061568520542],[510831.1504165782,6651117.621247934,75.15971117920543],[510831.05020245136,6651118.56899162,75.29165107220543],[510831.0998478449,6651118.099485875,75.24887583120542],[510835.9188697986,6651127.608849202,68.21846013508599],[510835.9848970118,6651127.002834307,68.21846013508599],[510835.9848970118,6651127.002834307,68.34846013508599],[510837.30630441307,6651114.874614272,68.21846013508599],[510835.9188697986,6651127.608849202,70.04726379408599],[510837.37233162613,6651114.268599376,68.21846013508599],[510837.30630441307,6651114.874614272,68.34846013508599],[510835.9848967584,6651127.002836633,70.04726379508598],[510835.98538908706,6651126.998317912,70.25108507908598],[510835.9211400306,6651127.588012425,70.51285448108598],[510835.9894770969,6651126.960797097,70.66766436708599],[510835.92823934864,6651127.522853041,70.990125433086],[510835.99799852126,6651126.882585252,71.09199148708599],[510835.9405339119,6651127.410010348,71.47302645308599],[510836.0112291874,6651126.761150765,71.51830183808599],[510837.30630441307,6651114.874614272,70.04726379408599],[510835.9533204526,6651127.29265216,71.834732438086],[510837.37233162613,6651114.268599376,70.04726379408599],[510836.02932974446,6651126.595019154,71.94011069708598],[510837.3043012672,6651114.892999666,70.45807910608599],[510835.9692271829,6651127.1466560615,72.192490284086],[510837.3700613941,6651114.289436154,70.51285448108598],[510836.0523220085,6651126.38399019,72.350460240086],[510835.98825600295,6651126.972004614,72.54294649908599],[510837.2980371629,6651114.950493239,70.87920053408598],[510837.36296207603,6651114.354595538,70.990125433086],[510836.0800730003,6651126.129284386,72.74223993408599],[510836.01035302173,6651126.769192442,72.88269152608599],[510837.28718901885,6651115.050060321,71.305289669086],[510836.1038387426,6651125.911156236,73.01972179408598],[510837.35066751274,6651114.46743823,71.47302645308599],[510836.0354066855,6651126.539243415,73.20835863608599],[510837.2715352918,6651115.193734289,71.73019617308599],[510836.1299386808,6651125.67160423,73.28016246708599],[510837.33788097213,6651114.584796419,71.834732438086],[510836.06324838765,6651126.283705046,73.516727444086],[510836.1581475676,6651125.412695746,73.52113211308598],[510837.2509821952,6651115.382375944,72.147162875086],[510837.3219742419,6651114.730792518,72.192490284086],[510836.09365568944,6651126.00461894,73.80482579508599],[510836.1882022218,6651125.136846331,73.74055111908599],[510837.22558392194,6651115.615487886,72.54911179208598],[510837.30294542183,6651114.9054439645,72.54294649908599],[510836.1263580662,6651125.70446804,74.07002352008598],[510836.23063671927,6651124.747371501,73.99676424208599],[510837.19555359473,6651115.8911140235,72.92899259408598],[510836.1610448796,6651125.386103465,74.31011196708599],[510837.280848403,6651115.108256138,72.88269152608599],[510836.27508255665,6651124.339436072,74.209042051086],[510837.17020877113,6651116.12373539,73.19539890908598],[510836.19737508777,6651125.052655388,74.523364302086],[510836.3207695772,6651123.920108741,74.376156808086],[510837.2557947393,6651115.338205164,73.20835863608599],[510837.14267534553,6651116.376444316,73.44310864908599],[510836.3669441639,6651123.496306403,74.498309930086],[510836.23498806515,6651124.707433719,74.70857320408601],[510837.2279530372,6651115.593743532,73.516727444086],[510836.4129039427,6651123.074475626,74.57698462308599],[510837.1029989495,6651116.740604575,73.74055111908599],[510836.45802453713,6651122.660347102,74.61472748208598],[510836.27351483365,6651124.353825041,74.86506449608599],[510837.1975457353,6651115.872829639,73.80482579508599],[510837.060564452,6651117.130079404,73.99676424208599],[510836.3125890114,6651123.9951920975,74.99268725508598],[510836.6436303878,6651120.95680844,74.61472748208598],[510837.0161186146,6651117.538014834,74.209042051086],[510836.3518568583,6651123.634781609,75.091782749086],[510837.1648433586,6651116.1729805395,74.07002352008598],[510836.9704315941,6651117.957342164,74.376156808086],[510836.83317663416,6651119.2171038035,74.61472748208598],[510836.9242570073,6651118.381144502,74.498309930086],[510836.4039446076,6651123.156706729,75.18094740108599],[510836.87829722866,6651118.802975278,74.57698462308599],[510837.1301565452,6651116.491345114,74.31011196708599],[510836.4550812815,6651122.687361067,75.223722642086],[510837.0938263371,6651116.824793192,74.523364302086],[510837.0562133596,6651117.170014859,74.70857320408601],[510837.0176865911,6651117.523623538,74.86506449608599],[510836.97861241334,6651117.882256482,74.99268725508598],[510836.83612014324,6651119.190087512,75.223722642086],[510836.9393445665,6651118.24266697,75.091782749086],[510836.8872568171,6651118.72074185,75.18094740108599],[510843.9331460998,6651128.499966287,68.11864080924303],[510844.00185281615,6651127.894249328,68.11864080924303],[510844.00185281615,6651127.894249328,68.24864080924304],[510843.9331460998,6651128.499966287,69.94744446824303],[510844.0018525525,6651127.894251651,69.94744446924302],[510844.00236486073,6651127.889735154,70.15126575324302],[510845.376885311,6651115.771991932,68.11864080924303],[510843.9355084619,6651128.479139752,70.41303515524302],[510845.4455920274,6651115.166274973,68.11864080924303],[510845.376885311,6651115.771991932,68.24864080924304],[510844.0066187695,6651127.852232785,70.56784504124303],[510843.9428958831,6651128.414012403,70.89030610724303],[510844.01548600866,6651127.7740593925,70.99217216124303],[510843.9556893819,6651128.301225187,71.37320712724303],[510844.029253599,6651127.652684605,71.41848251224303],[510843.9689948234,6651128.183924696,71.73491311224304],[510844.0480887093,6651127.486634672,71.84029137124303],[510845.376885311,6651115.771991932,69.94744446824303],[510843.9855470775,6651128.038000376,72.09267095824303],[510845.4455920274,6651115.166274973,69.94744446824303],[510844.0720140408,6651127.275709456,72.25064091424305],[510845.3748008738,6651115.790368287,70.35825978024303],[510844.0053481213,6651127.863434792,72.44312717324304],[510845.4432296652,6651115.187101508,70.41303515524302],[510844.1008912178,6651127.021128873,72.64242060824303],[510844.0283418769,6651127.660722328,72.78287220024303],[510845.36828256096,6651115.847833594,70.77938120824302],[510845.4358422441,6651115.252228856,70.89030610724303],[510844.1256214168,6651126.803107962,72.91990246824302],[510844.0544122635,6651127.430886352,73.10853931024303],[510845.35699417966,6651115.947351726,71.20547034324305],[510844.15278053755,6651126.563673728,73.18034314124303],[510845.4230487452,6651115.365016072,71.37320712724303],[510844.08338383207,6651127.1754736155,73.41690811824303],[510845.34070519614,6651116.090955059,71.63037684724303],[510844.1821341918,6651126.3048925325,73.42131278724302],[510845.4097433037,6651115.482316563,71.73491311224304],[510844.11502511706,6651126.896524716,73.70500646924303],[510844.21340851806,6651126.029178733,73.64073179324303],[510845.3193180178,6651116.27950397,72.04734354924302],[510844.1490546151,6651126.596521381,73.97020419424302],[510845.3931910496,6651115.628240884,72.09267095824303],[510844.2575650838,6651125.639895384,73.89694491624303],[510845.2928890369,6651116.512501308,72.44929246624302],[510844.1851490819,6651126.278313325,74.21029264124303],[510845.3733900059,6651115.802806468,72.44312717324304],[510844.30381461343,6651125.232160509,74.10922272524303],[510845.2616400249,6651116.787991937,72.82917326824304],[510844.2229536353,6651125.945029182,74.42354497624304],[510844.3513556956,6651124.813039334,74.27633748224304],[510845.3503962502,6651116.005518931,72.78287220024303],[510845.2352666627,6651117.02049894,73.09557958324302],[510844.3994041303,6651124.3894453505,74.39849060424302],[510844.2620930152,6651125.599977236,74.60875387824304],[510845.3243258637,6651116.235354909,73.10853931024303],[510844.4472290397,6651123.96782196,74.47716529724303],[510845.206615881,6651117.273083625,73.34328932324304],[510844.3021832694,6651125.246542403,74.76524517024305],[510844.4941807091,6651123.553897034,74.51490815624302],[510845.295354295,6651116.490767644,73.41690811824303],[510845.16532934527,6651117.637064851,73.64073179324303],[510844.3428431477,6651124.888085776,74.89286792924304],[510844.6873187797,6651121.851195889,74.51490815624302],[510844.3837045546,6651124.527852477,74.99196342324304],[510845.1211727796,6651118.026348202,73.89694491624303],[510845.26371301006,6651116.769716543,73.70500646924303],[510845.07492324995,6651118.434083077,74.10922272524303],[510844.43790611863,6651124.050012634,75.08112807524303],[510845.02738216775,6651118.85320425,74.27633748224304],[510845.22968351207,6651117.069719879,73.97020419424302],[510844.8845571542,6651120.112346551,74.51490815624302],[510844.49111801083,6651123.580897719,75.12390331624303],[510844.9793337331,6651119.276798235,74.39849060424302],[510844.9315088237,6651119.698421625,74.47716529724303],[510845.19358904526,6651117.3879279345,74.21029264124303],[510845.15578449174,6651117.721212079,74.42354497624304],[510845.1166451119,6651118.066264023,74.60875387824304],[510845.0765548578,6651118.419698858,74.76524517024305],[510845.03589497943,6651118.778155483,74.89286792924304],[510844.88762011623,6651120.085343542,75.12390331624303],[510844.9950335726,6651119.138388783,74.99196342324304],[510844.9408320085,6651119.616228626,75.08112807524303],[510850.138625911,6651129.214625044,68.03711346873332],[510850.20940737537,6651128.609147025,68.03711346873332],[510850.20940737537,6651128.609147025,68.16711346873333],[510850.138625911,6651129.214625044,69.86591712773333],[510850.2094071038,6651128.609149347,69.86591712873332],[510850.2099348822,6651128.6046346305,70.06973841273332],[510850.1410596097,6651129.193806725,70.33150781473331],[510851.6259619517,6651116.491671551,68.03711346873332],[510850.21431724686,6651128.567147057,70.48631770073332],[510851.69674341613,6651115.8861935325,68.03711346873332],[510851.6259619517,6651116.491671551,68.16711346873333],[510850.14867011004,6651129.128705067,70.80877876673333],[510850.22345225146,6651128.489004501,70.91064482073332],[510850.16184993624,6651129.015962344,71.29167978673333],[510850.2376355841,6651128.367677594,71.33695517173334],[510850.1755571644,6651128.898708125,71.65338577173333],[510850.25703946134,6651128.201693161,71.75876403073332],[510850.1926092496,6651128.752841366,72.01114361773332],[510851.6259619517,6651116.491671551,69.86591712773333],[510850.2816872699,6651127.990851151,72.16911357373333],[510850.2130082287,6651128.578344644,72.36159983273332],[510851.69674341613,6651115.8861935325,69.86591712773333],[510851.62381457054,6651116.510040656,70.27673243973332],[510850.3114364559,6651127.736370994,72.56089326773333],[510850.2366963306,6651128.375712145,72.70134485973333],[510851.6943097174,6651115.907011851,70.33150781473331],[510850.33691343665,6651127.518436086,72.83837512773331],[510851.61709942314,6651116.567483295,70.69785386773331],[510850.2635539689,6651128.145966833,73.02701196973332],[510851.68669921707,6651115.972113509,70.80877876673333],[510850.36489268584,6651127.2790963035,73.09881580073332],[510850.29340039677,6651127.890654851,73.33538077773332],[510851.6054701646,6651116.666962169,71.12394300273331],[510850.3951327372,6651127.02041719,73.33978544673332],[510851.6735193908,6651116.084856232,71.29167978673333],[510850.32599715865,6651127.611815992,73.62347912873332],[510851.58868930006,6651116.810508855,71.54884950673332],[510850.42735145945,6651126.744812154,73.55920445273333],[510851.6598121627,6651116.202110451,71.65338577173333],[510850.36105425115,6651127.311930998,73.88867685373332],[510851.5666562896,6651116.998983389,71.96581620873332],[510850.4728414283,6651126.355682366,73.81541757573332],[510851.6427600775,6651116.34797721,72.01114361773332],[510850.3982386684,6651126.993848467,74.12876530073332],[510850.52048756246,6651125.948108331,74.02769538473332],[510851.5394292285,6651117.231888814,72.36776512573331],[510850.4371848122,6651126.660695797,74.34201763573334],[510851.6223610983,6651116.522473931,72.36159983273332],[510850.56946425047,6651125.52915249,74.19481014173331],[510851.5072365849,6651117.50727077,72.74764592773332],[510850.4775060903,6651126.315779965,74.52722653773333],[510850.6189636116,6651125.105725602,74.31696326373333],[510851.59867299645,6651116.725106429,72.70134485973333],[510851.48006682197,6651117.739686054,73.01405224273331],[510850.6682326976,6651124.684268533,74.39563795673332],[510850.51880695653,6651125.962484553,74.68371782973334],[510850.7166021744,6651124.27050689,74.43338081573332],[510851.5718153582,6651116.954851742,73.02701196973332],[510851.4505508679,6651117.992171102,73.26176198273332],[510850.56069464784,6651125.604169328,74.81134058873333],[510850.60278995323,6651125.244078131,74.91043608273333],[510851.4080175959,6651118.356008747,73.55920445273333],[510851.54196893034,6651117.210163725,73.33538077773332],[510850.91557246685,6651122.568477416,74.43338081573332],[510850.6586282508,6651124.766426786,74.99960073473333],[510851.3625276271,6651118.745138534,73.81541757573332],[510851.5093721684,6651117.489002585,73.62347912873332],[510850.7134469913,6651124.297496922,75.04237597573332],[510851.3148814928,6651119.152712569,74.02769538473332],[510851.118766881,6651120.830314009,74.43338081573332],[510851.2659048049,6651119.57166841,74.19481014173331],[510851.1671363577,6651120.416552367,74.39563795673332],[510851.2164054438,6651119.995095297,74.31696326373333],[510851.4743150759,6651117.788887577,73.88867685373332],[510851.43713065865,6651118.106970107,74.12876530073332],[510851.39818451484,6651118.440122779,74.34201763573334],[510851.35786323674,6651118.78503861,74.52722653773333],[510851.31656237063,6651119.138334022,74.68371782973334],[510851.12192233576,6651120.803321653,75.04237597573332],[510851.2746746793,6651119.4966492485,74.81134058873333],[510851.1767410762,6651120.334391791,74.99960073473333],[510851.23257937375,6651119.856740445,74.91043608273333],[510852.904369281,6651129.540086604,67.99958431955216],[510852.9760754476,6651128.934717401,67.99958431955216],[510852.9760754476,6651128.934717401,68.12958431955215],[510852.904369281,6651129.540086604,69.82838797855216],[510852.97607517237,6651128.934719723,69.82838797955215],[510852.9766098459,6651128.930205817,70.03220926355215],[510852.90683477395,6651129.519272028,70.29397866555215],[510852.98104946245,6651128.89272498,70.44878855155216],[510854.4111361548,6651116.819419654,67.99958431955216],[510854.48284232145,6651116.214050449,67.99958431955216],[510854.4111361548,6651116.819419654,68.12958431955215],[510852.9145446993,6651129.454182069,70.77124961755217],[510852.99030380853,6651128.814596468,70.87311567155216],[510852.9278967093,6651129.341459608,71.25415063755216],[510853.0046724348,6651128.693291365,71.29942602255215],[510852.9417830112,6651129.224226462,71.61585662255216],[510853.0243298079,6651128.527336765,71.72123488155215],[510852.95905786793,6651129.0783859175,71.97361446855217],[510853.04929962,6651128.316532645,72.13158442455216],[510852.9797233431,6651128.9039205555,72.32407068355215],[510854.4111361548,6651116.819419654,69.82838797855216],[510854.48284232145,6651116.214050449,69.82838797855216],[510853.0794374548,6651128.062098224,72.52336411855215],[510853.00372091075,6651128.701324473,72.66381571055216],[510854.4089607199,6651116.837785458,70.23920329055215],[510854.4803768284,6651116.2348650275,70.29397866555215],[510853.10524727154,6651127.844202482,72.80084597855215],[510853.0309294221,6651128.471620451,72.98948282055215],[510854.40215784457,6651116.895217773,70.66032471855216],[510853.13359204686,6651127.604905712,73.06128665155215],[510854.47266690305,6651116.299954985,70.77124961755217],[510853.06116576924,6651128.216354353,73.29785162855217],[510854.3903766592,6651116.994678769,71.08641385355216],[510853.1642271598,6651127.346273089,73.30225629755215],[510853.09418838134,6651127.937565605,73.58594997955215],[510854.45931489306,6651116.412677447,71.25415063755216],[510853.19686679344,6651127.070717583,73.52167530355216],[510854.37337656633,6651117.138199658,71.51132035755215],[510853.12970346614,6651127.637734507,73.85114770455215],[510854.4454285913,6651116.529910593,71.61585662255216],[510853.24295105156,6651126.681657729,73.77788842655215],[510854.3510557126,6651117.326640319,71.92828705955216],[510853.16737366753,6651127.319709142,74.09123615155215],[510854.4281537344,6651116.675751138,71.97361446855217],[510853.2912196437,6651126.274156943,73.99016623555217],[510854.3234729521,6651117.559503888,72.33023597655215],[510853.2068286109,6651126.986616343,74.30448848655216],[510853.3408361722,6651125.855276396,74.15728099255216],[510854.40748825925,6651116.850216498,72.32407068355215],[510853.2476766537,6651126.641762501,74.48969738855217],[510853.3909822022,6651125.431925606,74.27943411455216],[510854.2908597379,6651117.834836352,72.71011677855215],[510854.3834906916,6651117.05281258,72.66381571055216],[510853.4408949487,6651125.010544279,74.35810880755216],[510853.28951708204,6651126.288530582,74.64618868055216],[510854.2633350242,6651118.067209868,72.97652309355215],[510853.48989633325,6651124.596856996,74.39585166655215],[510853.3319520019,6651125.930279752,74.77381143955215],[510854.35628218023,6651117.282516602,72.98948282055215],[510854.23343346815,6651118.319649538,73.22423283355215],[510853.3745972482,6651125.570253271,74.87290693355216],[510853.6914660104,6651122.895133409,74.39585166655215],[510854.19034453365,6651118.683421794,73.52167530355216],[510854.3260458331,6651117.537782702,73.29785162855217],[510853.43116502755,6651125.092687767,74.96207158555215],[510854.14426027547,6651119.072481649,73.77788842655215],[510853.4866999302,6651124.62384218,75.00484682655217],[510854.29302322096,6651117.81657145,73.58594997955215],[510854.0959916833,6651119.479982435,73.99016623555217],[510853.8973149939,6651121.157282381,74.39585166655215],[510854.0463751548,6651119.898862982,74.15728099255216],[510853.9463163784,6651120.743595098,74.35810880755216],[510853.99622912495,6651120.322213772,74.27943411455216],[510854.2575081362,6651118.116402546,73.85114770455215],[510854.2198379348,6651118.434427912,74.09123615155215],[510854.18038299144,6651118.767520711,74.30448848655216],[510854.13953494874,6651119.112374554,74.48969738855217],[510854.0976945203,6651119.465606473,74.64618868055216],[510853.90051167214,6651121.130294875,75.00484682655217],[510854.05525960046,6651119.823857303,74.77381143955215],[510853.9560465748,6651120.661449288,74.96207158555215],[510854.01261435414,6651120.183883784,74.87290693355216],[510860.58979788143,6651130.466976043,67.89143172384466],[510860.66407360387,6651129.861916736,67.89143172384466],[510860.66407360387,6651129.861916736,68.02143172384466],[510860.58979788143,6651130.466976043,69.72023538284466],[510860.6640733189,6651129.861919057,69.72023538384465],[510860.6646271521,6651129.857407464,69.92405666784465],[510860.59235172416,6651130.44617212,70.18582606984465],[510860.6692258602,6651129.819945812,70.34063595584466],[510860.600337931,6651130.381115482,70.66309702184468],[510860.6788118313,6651129.741857296,70.76496307584466],[510862.15055902017,6651117.752820987,67.89143172384466],[510862.15055902017,6651117.752820987,68.02143172384466],[510862.22483474266,6651117.147761682,67.89143172384466],[510860.61416840367,6651130.268450725,71.14599804184466],[510860.6936953504,6651129.62061429,71.19127342684466],[510860.6285523146,6651130.151277592,71.50770402684466],[510860.714057136,6651129.4547446435,71.61308228584465],[510860.64644620754,6651130.005511706,71.86546187284466],[510860.7399217293,6651129.244048439,72.02343182884466],[510860.66785222,6651129.831135657,72.21591808784466],[510860.69270972896,6651129.628643286,72.55566311484466],[510860.7711395389,6651128.989744266,72.41521152284466],[510862.15055902017,6651117.752820987,69.72023538284466],[510862.22483474266,6651117.147761682,69.72023538284466],[510860.79787423793,6651128.7719600685,72.69269338284465],[510860.7208932442,6651129.399056852,72.88133022484466],[510862.14830562955,6651117.77117739,70.13105069484466],[510862.22228089994,6651117.168565603,70.18582606984465],[510860.82723473455,6651128.532785799,72.95313405584466],[510860.75221309625,6651129.143921429,73.18969903284466],[510862.1412589765,6651117.828580305,70.55217212284467],[510860.8589676421,6651128.2742855735,73.19410370184465],[510862.21429469314,6651117.233622242,70.66309702184468],[510860.78641905775,6651128.865275396,73.47779738384466],[510862.12905561813,6651117.927990385,70.97826125784465],[510860.89277690125,6651127.998871128,73.41352270784466],[510860.8232068085,6651128.565597787,73.74299510884465],[510862.20046422037,6651117.346286998,71.14599804184466],[510860.9405125666,6651127.610010439,73.66973583084466],[510862.11144633504,6651118.071437803,71.40316776184466],[510860.8622269034,6651128.247735223,73.98308355584466],[510862.1860803095,6651117.463460131,71.50770402684466],[510860.99051084055,6651127.202718259,73.88201363984467],[510862.0883256243,6651118.259781999,71.82013446384467],[510860.9030956957,6651127.91481294,74.19633589084467],[510861.04190535337,6651126.784052142,74.04912839684465],[510862.16818641656,6651117.609226017,71.86546187284466],[510860.9454075084,6651127.5701356325,74.38154479284468],[510862.0597544488,6651118.492526362,72.22208338084465],[510861.09384834213,6651126.360918071,74.17128151884467],[510862.14678040403,6651117.783602066,72.21591808784466],[510860.98874726833,6651127.217084538,74.53803608484466],[510861.1455496879,6651125.939752456,74.24995621184466],[510862.02597255574,6651118.767717878,72.60196418284465],[510861.19630701345,6651125.526276947,74.28769907084465],[510861.032702823,6651126.859017103,74.66565884384465],[510862.1219228952,6651117.986094437,72.55566311484466],[510861.99746150716,6651118.999972439,72.86837049784465],[510861.07687624125,6651126.499174925,74.76475433784466],[510861.9664884434,6651119.252282882,73.11608023784466],[510862.09373937984,6651118.21568087,72.88133022484466],[510861.4050998429,6651123.825424497,74.28769907084465],[510861.13547109975,6651126.021853894,74.85391898984466],[510861.9218554377,6651119.615868919,73.41352270784466],[510862.06241952785,6651118.470816296,73.18969903284466],[510861.1929960688,6651125.553248314,74.89669423084466],[510861.8741197723,6651120.004729606,73.66973583084466],[510862.02821356634,6651118.749462327,73.47779738384466],[510861.82412149844,6651120.412021788,73.88201363984467],[510861.6183253255,6651122.0884631,74.28769907084465],[510861.6690826511,6651121.67498759,74.24995621184466],[510861.77272698557,6651120.830687904,74.04912839684465],[510861.7207839968,6651121.253821974,74.17128151884467],[510861.9914258156,6651119.0491399355,73.74299510884465],[510861.95240572066,6651119.3670025,73.98308355584466],[510861.9115369284,6651119.699924783,74.19633589084467],[510861.8692251157,6651120.0446020905,74.38154479284468],[510861.62163655524,6651122.061489409,74.89669423084466],[510861.82588535576,6651120.397653185,74.53803608484466],[510861.67916152434,6651121.592883831,74.85391898984466],[510861.781929801,6651120.75572062,74.66565884384465],[510861.7377563828,6651121.115562798,74.76475433784466],[510869.871015356,6651131.630491235,67.75322922458413],[510869.9483941724,6651131.02582094,67.75322922458413],[510869.9483941724,6651131.02582094,67.88322922458413],[510870.0918160808,6651131.658760498,67.74984006371746],[510870.1692687201,6651131.054099654,67.74984006371746],[510869.871015356,6651131.630491235,69.58203288358415],[510870.1692687201,6651131.054099654,67.87984006371745],[510869.9483938755,6651131.02582326,69.58203288458412],[510869.9489708468,6651131.021314566,69.78585416858414],[510869.87367589324,6651131.609700689,70.04762357058412],[510869.95376168005,6651130.983877,70.20243345658415],[510869.88199574815,6651131.544685878,70.52489452258413],[510869.96374813415,6651130.905838689,70.62676057658413],[510869.8964040309,6651131.432093557,71.00779554258415],[510870.0918160808,6651131.658760498,69.57864372271747],[510871.49698203395,6651118.9245105,67.75322922458413],[510869.97925345745,6651130.784673636,71.05307092758413],[510870.16926842293,6651131.054101975,69.57864372371745],[510871.49698203395,6651118.9245105,67.88322922458413],[510871.57436085044,6651118.319840205,67.75322922458413],[510869.9113888733,6651131.314995757,71.36950152758413],[510870.1698459446,6651131.049593351,69.78246500771746],[510870.0944791564,6651131.637970276,70.04423440971745],[510870.00046591845,6651130.618910633,71.47487978658414],[510869.930030338,6651131.16932359,71.72725937358413],[510870.1746413485,6651131.01215637,70.19904429571747],[510870.10280694877,6651131.572956482,70.52150536171746],[510870.0274110838,6651130.408349889,71.88522932958413],[510869.9523306518,6651130.995059651,72.07771558858413],[510870.1846373302,6651130.9341192795,70.62337141571746],[510869.97822665866,6651130.79269747,72.41746061558415],[510870.11722897773,6651131.46036592,71.00440638171747],[510870.0599331122,6651130.154209216,72.27700902358413],[510870.2001574462,6651130.812956119,71.04968176671746],[510871.7193340025,6651118.95297837,67.74984006371746],[510870.0877847347,6651129.93656504,72.55449088358412],[510870.007587626,6651130.563258644,72.74312772558413],[510871.7193340025,6651118.95297837,67.87984006371745],[510870.1322281163,6651131.343269952,71.36611236671746],[510871.7967866418,6651118.348317526,67.74984006371746],[510871.49698203395,6651118.9245105,69.58203288358415],[510871.57436085044,6651118.319840205,69.58203288358415],[510870.1183718552,6651129.697544542,72.81493155658413],[510870.22139014484,6651130.647195706,71.47149062571746],[510870.04021595995,6651130.308287255,73.05149653358413],[510870.15088736586,6651131.19760006,71.72387021271746],[510871.494634501,6651118.9428551,69.99284819558413],[510870.15143050137,6651129.439210514,73.05590120258414],[510871.5717003131,6651118.340630752,70.04762357058412],[510870.0758509794,6651130.029820372,73.33959488458414],[510870.2483610171,6651130.436638256,71.88184016871746],[510870.17320895504,6651131.023338846,72.07432642771745],[510871.48729345266,6651119.00022111,70.41396962358412],[510870.18665224506,6651129.163973141,73.27532020858413],[510870.11417565023,6651129.730335435,73.60479260958412],[510871.5633804583,6651118.405645562,70.52489452258413],[510870.1991296678,6651130.820979828,72.41407145471747],[510870.28091407294,6651130.182501554,72.27361986271745],[510871.4745802619,6651119.099567277,70.84005875858412],[510870.23638221284,6651128.775362463,73.53153333158413],[510870.15482592816,6651129.412677235,73.84488105658413],[510870.30879226705,6651129.964860781,72.55110172271745],[510870.2884693166,6651128.368332145,73.74381114058413],[510871.5489721755,6651118.518237885,71.00779554258415],[510870.22851864673,6651130.591544589,72.73973856471746],[510871.4562352976,6651119.242922467,71.26496526258414],[510871.7193340025,6651118.95297837,69.57864372271747],[510870.19740213844,6651129.079968997,74.05813339158414],[510871.7967866418,6651118.348317526,69.57864372271747],[510870.3420109914,6651127.9499352,73.91092589758412],[510870.3394085691,6651129.725844018,72.81154239571745],[510871.533987333,6651118.635335683,71.36950152758413],[510870.2611781097,6651130.3365771845,73.04810737271745],[510870.24148165574,6651128.735513294,74.24334229358413],[510871.4321486488,6651119.431145571,71.68193196458412],[510871.71698423,6651118.971322684,69.98945903471746],[510870.39612405637,6651127.527073177,74.03307901958414],[510870.37249875464,6651129.467514029,73.05251204171746],[510871.5153458683,6651118.7810078515,71.72725937358413],[510870.2866320657,6651128.382689186,74.39983358558413],[510871.7941235662,6651118.369107748,70.04423440971745],[510870.44998538285,6651127.1061783405,74.11175371258415],[510870.2968471265,6651130.058114655,73.33620572371747],[510871.4023838256,6651119.663740294,72.08388088158412],[510870.5028632499,6651126.6929686675,74.14949657158414],[510870.33242399734,6651128.024851964,74.52745634458412],[510871.70963617787,6651119.028687796,70.41058046271745],[510870.4077541014,6651129.192280958,73.27193104771746],[510871.49304555455,6651118.95527179,72.07771558858413],[510871.36719059135,6651119.938754884,72.46376168358412],[510870.3784428944,6651127.66524114,74.62655183858415],[510870.3352083607,6651129.758634399,73.60140344871745],[510871.7857957739,6651118.434121542,70.52150536171746],[510871.4671495477,6651119.157633971,72.41746061558415],[510871.33748840715,6651120.170860121,72.73016799858414],[510870.4575315138,6651128.803676354,73.52814417071745],[510871.69691085815,6651119.12803241,70.83666959771745],[510870.4394857311,6651127.188226991,74.71571649058413],[510870.72037903435,6651124.993209746,74.14949657158414],[510870.3758974208,6651129.440981164,73.84149189571745],[510871.30522134947,6651120.423008345,72.97787773858413],[510870.4994139806,6651126.719922694,74.75849173158413],[510871.43778858037,6651119.387072797,72.74312772558413],[510870.5096683109,6651128.396652397,73.74042197971745],[510871.771373745,6651118.546712104,71.00440638171747],[510871.25872366433,6651120.786360621,73.27532020858413],[510871.678548392,6651119.2713853605,71.26157610171747],[510871.4051602464,6651119.642044187,73.05149653358413],[510870.41851425066,6651129.108278127,74.05474423071746],[510871.20899369643,6651121.174971298,73.53153333158413],[510870.94251265936,6651123.257365095,74.14949657158414],[510871.1569065928,6651121.582001618,73.74381114058413],[510870.9953905264,6651122.8441554215,74.11175371258415],[510870.56326106685,6651127.978261993,73.90753673671745],[510871.103364918,6651122.000398563,73.91092589758412],[510871.049251853,6651122.423260587,74.03307901958414],[510871.369525227,6651119.920511069,73.33959488458414],[510871.75637460634,6651118.663808072,71.36611236671746],[510870.46263582166,6651128.763827808,74.23995313271746],[510871.65443876345,6651119.4596055215,71.67854280371745],[510871.33120055613,6651120.219996005,73.60479260958412],[510870.6174257581,6651127.555406579,74.02968985871746],[510870.5078293073,6651128.411009216,74.39644442471746],[510871.73771535687,6651118.8094779635,71.72387021271746],[510871.2905502782,6651120.537654206,73.84488105658413],[510870.6713384706,6651127.1345183235,74.10836455171747],[510871.6246455434,6651119.692196609,72.08049172071745],[510871.2479740679,6651120.870362443,74.05813339158414],[510870.9459622257,6651123.230408748,74.75849173158413],[510871.20389455074,6651121.214818148,74.24334229358413],[510870.72426678555,6651126.721315107,74.14610741071746],[510870.5536649264,6651128.053177586,74.52406718371745],[510871.0058904752,6651122.762104449,74.71571649058413],[510871.15874414064,6651121.567642254,74.39983358558413],[510871.06693331205,6651122.285090303,74.62655183858415],[510871.112952209,6651121.925479477,74.52745634458412],[510871.7153937676,6651118.983739178,72.07432642771745],[510871.58941873326,6651119.967206899,72.46037252271745],[510870.5997277274,6651127.6935723815,74.62316267771747],[510871.68947305484,6651119.186098197,72.41407145471747],[510871.55968821177,6651120.199308507,72.72677883771746],[510870.66082880175,6651127.216565691,74.71232732971745],[510870.94199008954,6651125.021582756,74.14610741071746],[510871.5273903699,6651120.451452792,72.97448857771745],[510870.72081422544,6651126.748268713,74.75510257071745],[510871.6600840759,6651119.415533436,72.73973856471746],[510871.48084832396,6651120.814799389,73.27193104771746],[510871.62742461305,6651119.67050084,73.04810737271745],[510871.4310709115,6651121.203403992,73.52814417071745],[510871.1643356398,6651123.285765238,74.14610741071746],[510871.3789341145,6651121.610427949,73.74042197971745],[510871.21726395475,6651122.872562024,74.10836455171747],[510871.3253413585,6651122.028818353,73.90753673671745],[510871.27117666724,6651122.451673767,74.02968985871746],[510871.5917555961,6651119.948963369,73.33620572371747],[510871.5533943619,6651120.248443625,73.60140344871745],[510871.5127053018,6651120.56609686,73.84149189571745],[510871.470088472,6651120.898799897,74.05474423071746],[510871.1677884973,6651123.258809312,74.75510257071745],[510871.42596690095,6651121.243250218,74.23995313271746],[510871.22777392087,6651122.790512334,74.71232732971745],[510871.3807734153,6651121.596068809,74.39644442471746],[510871.28887499525,6651122.313505642,74.62316267771747],[510871.33493779623,6651121.953900439,74.52406718371745],[510877.22765063925,6651132.587124988,67.63777053046715],[510877.30748908257,6651131.982774536,67.63777053046715],[510877.30748908257,6651131.982774536,67.76777053046715],[510877.22765063925,6651132.587124988,69.46657418946717],[510877.3074887762,6651131.982776854,69.46657419046714],[510877.30808408756,6651131.9782705465,69.67039547446716],[510877.23039574665,6651132.566345439,69.93216487646714],[510877.31302720617,6651131.940852782,70.08697476246716],[510877.2389800633,6651132.501365018,70.40943582846715],[510877.3233310979,6651131.86285575,70.51130188246715],[510877.25384633965,6651132.3888322525,70.89233684846717],[510877.33932928625,6651131.741754786,70.93761223346715],[510877.2693075025,6651132.271796394,71.25404283346715],[510878.90530163253,6651119.887865121,67.63777053046715],[510877.36121602403,6651131.5760794645,71.35942109246716],[510878.90530163253,6651119.887865121,67.76777053046715],[510878.9851400758,6651119.283514667,67.63777053046715],[510877.28854152025,6651132.126201279,71.61180067946715],[510877.3890176905,6651131.365630099,71.76977063546715],[510877.3115506901,6651131.952029519,71.96225689446715],[510877.33826984867,6651131.749774376,72.30200192146717],[510877.42257349094,6651131.1116238525,72.16155032946715],[510877.3685641079,6651131.520456913,72.62766903146715],[510877.45131042786,6651130.894094801,72.43903218946714],[510877.48286981584,6651130.655200734,72.69947286246715],[510877.402229593,6651131.265620392,72.93603783946715],[510878.90530163253,6651119.887865121,69.46657418946717],[510878.9851400758,6651119.283514667,69.46657418946717],[510877.5169792914,6651130.397003351,72.94044250846716],[510877.4389973365,6651130.987300805,73.22413619046716],[510878.90287947905,6651119.906200016,69.87738950146715],[510877.55332062236,6651130.121911566,73.15986151446715],[510878.98239496845,6651119.3042942155,69.93216487646714],[510877.4785402269,6651130.687974281,73.48933391546714],[510878.89530508197,6651119.963535681,70.29851092946714],[510877.6046313479,6651129.733506445,73.41607463746715],[510877.520482648,6651130.370484107,73.72942236246715],[510878.9738106518,6651119.369274637,70.40943582846715],[510878.88218777935,6651120.0628293,70.72460006446715],[510877.65837413515,6651129.326691425,73.62835244646715],[510877.5644122208,6651130.037951857,73.94267469746715],[510878.95894437557,6651119.481807402,70.89233684846717],[510877.7136177298,6651128.908515794,73.79546720346715],[510878.86325968686,6651120.206108662,71.14950656846716],[510877.6098928858,6651129.693678354,74.12788359946715],[510877.7694508771,6651128.485877444,73.91762032546714],[510878.9434832126,6651119.598843262,71.25404283346715],[510877.656478484,6651129.341040874,74.28437489146715],[510878.83840740006,6651120.394232205,71.56647327046714],[510877.8250242841,6651128.065205242,73.99629501846717],[510877.70372599567,6651128.983392931,74.41199765046714],[510877.87958297064,6651127.652214138,74.03403787746716],[510878.9242491949,6651119.744438377,71.61180067946715],[510878.80769644777,6651120.626703896,71.96842218746714],[510877.75120768714,6651128.623972323,74.51109314446717],[510878.90124002506,6651119.918610138,71.96225689446715],[510878.7713845324,6651120.901573014,72.34830298946714],[510877.81419088185,6651128.147210494,74.60025779646715],[510878.10401289066,6651125.953354308,74.03403787746716],[510878.87452086643,6651120.120865279,72.30200192146717],[510878.74073821004,6651121.133555479,72.61470930446715],[510877.8760240599,6651127.679153906,74.64303303746715],[510878.70744548517,6651121.38557033,72.86241904446715],[510878.84422660724,6651120.350182742,72.62766903146715],[510878.6594697863,6651121.74873041,73.15986151446715],[510878.333207438,6651124.218427839,74.03403787746716],[510878.8105611221,6651120.605019265,72.93603783946715],[510878.6081590607,6651122.137135531,73.41607463746715],[510878.38776612456,6651123.805436733,73.99629501846717],[510878.55441627343,6651122.543950549,73.62835244646715],[510878.44333953154,6651123.384764532,73.91762032546714],[510878.49917267886,6651122.9621261805,73.79546720346715],[510878.77379337855,6651120.88333885,73.22413619046716],[510878.7342504882,6651121.182665374,73.48933391546714],[510878.69230806705,6651121.500155548,73.72942236246715],[510878.3367666552,6651124.191485749,74.64303303746715],[510878.64837849437,6651121.832687799,73.94267469746715],[510878.3985998333,6651123.723429161,74.60025779646715],[510878.6028978294,6651122.176961301,74.12788359946715],[510878.5563122312,6651122.529598781,74.28437489146715],[510878.46158302797,6651123.246667332,74.51109314446717],[510878.50906471943,6651122.887246726,74.41199765046714],[510886.817316537,6651133.879879337,67.4793948502016],[510886.9003612012,6651133.275961105,67.4793948502016],[510886.9003612012,6651133.275961105,67.60939485020158],[510886.817316537,6651133.879879337,69.3081985092016],[510886.9003608826,6651133.275963422,69.30819851020158],[510886.900980101,6651133.271460336,69.51201979420159],[510886.82017188467,6651133.859114649,69.77378919620158],[510886.9061217296,6651133.234069334,69.9285990822016],[510886.8291009377,6651133.794180701,70.25106014820159],[510886.9168394139,6651133.156128082,70.35292620220159],[510886.84456422675,6651133.681728418,70.7339611682016],[510886.9334800713,6651133.0351137305,70.77923655320159],[510886.86064629245,6651133.5647762595,71.09566715320159],[510886.9562457555,6651132.869556895,71.2010454122016],[510886.8806527264,6651133.419285271,71.45342499920159],[510888.56234008534,6651121.189701763,67.4793948502016],[510888.56234008534,6651121.189701763,67.60939485020158],[510886.90458591835,6651133.245238076,71.80388121420158],[510886.98516390525,6651132.65925804,71.61139495520159],[510888.6453847495,6651120.58578353,67.4793948502016],[510886.93237808795,6651133.043127583,72.1436262412016],[510887.0200672685,6651132.4054334555,72.00317464920158],[510886.96388893016,6651132.813974124,72.46929335120159],[510887.04995824816,6651132.188059975,72.28065650920158],[510887.08278502524,6651131.949336761,72.54109718220158],[510886.99890638277,6651132.559319858,72.77766215920158],[510887.1182642985,6651131.6913240375,72.7820668282016],[510887.03715067706,6651132.28119932,73.0657605102016],[510888.56234008534,6651121.189701763,69.3081985092016],[510887.15606505604,6651131.416428993,73.00148583420159],[510888.6453847495,6651120.58578353,69.3081985092016],[510887.0782815649,6651131.98208687,73.33095823520158],[510888.5598206608,6651121.208023545,69.71901382120159],[510887.2094363619,6651131.0283016525,73.25769895720158],[510887.121908346,6651131.664823759,73.57104668220158],[510888.6425294018,6651120.606548218,69.77378919620158],[510888.5519420846,6651121.265318206,70.14013524920158],[510887.26533739833,6651130.62177758,73.46997676620158],[510887.1676020804,6651131.332529331,73.78429901720159],[510888.6336003488,6651120.671482166,70.25106014820159],[510888.538298006,6651121.36454081,70.56622438420158],[510887.3227995129,6651130.203901021,73.63709152320158],[510887.2149091972,6651130.988502046,73.96950791920159],[510887.38087485585,6651129.781564935,73.75924464520159],[510887.26336562,6651130.636116766,74.12599921120159],[510888.61813705973,6651120.78393445,70.7339611682016],[510888.5186097829,6651121.507717702,70.9911308882016],[510887.4386800276,6651129.36119359,73.8379193382016],[510887.3125105379,6651130.278724607,74.25362197020158],[510887.49542972894,6651128.9484978495,73.87566219720159],[510888.60205499415,6651120.900886607,71.09566715320159],[510888.49275945657,6651121.695706701,71.40809759020158],[510887.3618990402,6651129.91956105,74.3527174642016],[510888.58204856014,6651121.0463775955,71.45342499920159],[510888.4608151873,6651121.928012133,71.81004650720158],[510887.4274115682,6651129.443140194,74.44188211620158],[510887.7288724993,6651127.250853017,73.87566219720159],[510887.49172789644,6651128.9754183525,74.48465735720158],[510888.5581153682,6651121.220424791,71.80388121420158],[510888.4230450267,6651122.20268467,72.18992730920158],[510888.3911679829,6651122.434501225,72.45633362420159],[510888.53032319853,6651121.422535284,72.1436262412016],[510888.3565382601,6651122.686335838,72.70404336420158],[510888.4988123564,6651121.651688743,72.46929335120159],[510888.3066359117,6651123.049236191,73.00148583420159],[510887.96727123886,6651125.517167335,73.87566219720159],[510888.2532646058,6651123.437363532,73.25769895720158],[510888.02402094007,6651125.104471595,73.8379193382016],[510888.4637949038,6651121.906343009,72.77766215920158],[510888.0818261118,6651124.684100252,73.75924464520159],[510888.1973635694,6651123.843887605,73.46997676620158],[510888.13990145497,6651124.261764164,73.63709152320158],[510888.4255506094,6651122.184463547,73.0657605102016],[510888.3844197216,6651122.483575998,73.33095823520158],[510887.97097339004,6651125.490244515,74.48465735720158],[510888.3407929405,6651122.8008391075,73.57104668220158],[510888.2950992062,6651123.133133537,73.78429901720159],[510888.03528971836,6651125.022522674,74.44188211620158],[510888.2477920894,6651123.477160821,73.96950791920159],[510888.1008022464,6651124.546101817,74.3527174642016],[510888.1993356666,6651123.829546101,74.12599921120159],[510888.1501907486,6651124.186938261,74.25362197020158],[510890.0168465994,6651134.322734014,67.42456835018152],[510890.10096099856,6651133.718963847,67.42456835018152],[510890.10096099856,6651133.718963847,67.5545683501815],[510890.0168465994,6651134.322734014,69.2533720091815],[510890.1009606759,6651133.718966164,69.2533720101815],[510890.1015878706,6651133.714464181,69.4571932941815],[510890.0197387282,6651134.301974417,69.71896269618149],[510890.1067957308,6651133.677082348,69.8737725821815],[510890.02878280025,6651134.23705639,70.19623364818152],[510890.11765147443,6651133.599160205,70.2980997021815],[510890.04444527865,6651134.124631675,70.6791346681815],[510890.1345064874,6651133.478175522,70.7244100531815],[510890.06073450454,6651134.007708192,71.0408406531815],[510890.1575654265,6651133.312659276,71.1462189121815],[510890.0809986501,6651133.862252874,71.3985984991815],[510890.1052401361,6651133.688248351,71.7490547141815],[510891.7843485653,6651121.635667731,67.42456835018152],[510890.18685608363,6651133.10241198,71.5565684551815],[510891.7843485653,6651121.635667731,67.5545683501815],[510891.86846296454,6651121.0318975635,67.42456835018152],[510890.1333903089,6651133.486187411,72.0887997411815],[510890.2222090524,6651132.8486496275,71.9483481491815],[510890.16530705616,6651133.257090134,72.4144668511815],[510890.252485071,6651132.6313294405,72.2258300091815],[510890.28573470435,6651132.392664757,72.4862706821815],[510890.20077558403,6651133.002498302,72.7228356591815],[510890.3216710017,6651132.134715291,72.72724032818151],[510890.23951251997,6651132.724445951,73.01093401018151],[510891.7843485653,6651121.635667731,69.2533720091815],[510890.35995868745,6651131.859887643,72.9466593341815],[510890.2811732329,6651132.425406835,73.2761317351815],[510891.86846296454,6651121.0318975635,69.2533720091815],[510891.78179668705,6651121.6539850235,69.6641873211815],[510890.4140174926,6651131.471855461,73.2028724571815],[510890.32536198973,6651132.1082215095,73.5162201821815],[510891.8655708358,6651121.052657161,69.71896269618149],[510890.4706386151,6651131.065431057,73.41515026618151],[510891.77381662343,6651121.711265636,70.08530874918151],[510890.37164432526,6651131.776008551,73.7294725171815],[510890.5288409244,6651130.64765695,73.58226502318149],[510891.85652676376,6651121.117575189,70.19623364818152],[510890.4195608259,6651131.432065613,73.91468141918152],[510891.7599967895,6651121.810463914,70.51139788418149],[510890.5876643615,6651130.225424409,73.7044181451815],[510890.46864143724,6651131.079766729,74.0711727111815],[510891.7400549536,6651121.953605702,70.9363043881815],[510891.8408642853,6651121.229999903,70.6791346681815],[510890.6462141471,6651129.805156129,73.7830928381815],[510890.51841941255,6651130.72246219,74.1987954701815],[510890.7036948663,6651129.392561571,73.8208356971815],[510891.82457505947,6651121.346923387,71.0408406531815],[510890.56844410993,6651130.363386692,74.2978909641815],[510891.7138716378,6651122.141548612,71.35327109018151],[510890.6348005337,6651129.88708264,74.3870556161815],[510891.8043109138,6651121.492378703,71.3985984991815],[510891.6815158804,6651122.373797089,71.75522000718149],[510890.69994534896,6651129.4194754725,74.4298308571815],[510890.9401447159,6651127.695332954,73.8208356971815],[510891.7800694279,6651121.666383228,71.7490547141815],[510891.6432591857,6651122.648402283,72.1351008091815],[510891.61097151967,6651122.8801620025,72.40150712418149],[510891.751919255,6651121.868444168,72.0887997411815],[510891.57589571615,6651123.131934875,72.6492168641815],[510891.72000250773,6651122.097541446,72.4144668511815],[510891.18161437474,6651125.962072326,73.8208356971815],[510891.5253505536,6651123.494746254,72.9466593341815],[510891.2390950939,6651125.549477767,73.7830928381815],[510891.47129174846,6651123.882778435,73.2028724571815],[510891.29764487955,6651125.129209487,73.7044181451815],[510891.4146706261,6651124.289202839,73.41515026618151],[510891.6845339799,6651122.352133278,72.7228356591815],[510891.35646831675,6651124.706976946,73.58226502318149],[510891.6457970439,6651122.630185626,73.01093401018151],[510891.604136331,6651122.9292247435,73.2761317351815],[510891.185364215,6651125.935156106,74.4298308571815],[510891.55994757416,6651123.24641007,73.5162201821815],[510891.2505090302,6651125.467548939,74.3870556161815],[510891.5136652387,6651123.5786230285,73.7294725171815],[510891.31686545414,6651124.991244887,74.2978909641815],[510891.46574873803,6651123.922565967,73.91468141918152],[510891.36689015134,6651124.632169387,74.1987954701815],[510891.4166681267,6651124.274864851,74.0711727111815],[510893.8452964614,6651134.860233717,67.35765722912942],[510893.93069086946,6651134.256643257,67.35765722912942],[510893.93069086946,6651134.256643257,67.48765722912941],[510893.8452964614,6651134.860233717,69.18646088812942],[510893.93069054175,6651134.256645573,69.1864608891294],[510893.93132728094,6651134.252144931,69.3902821731294],[510893.848232601,6651134.839480299,69.6520515751294],[510893.93661439157,6651134.214774222,69.80686146112942],[510893.857414301,6651134.7745815925,70.12932252712942],[510893.9476353321,6651134.136875275,70.23118858112942],[510893.8733151229,6651134.662190341,70.61222354712942],[510893.9647468358,6651134.015926601,70.65749893212941],[510893.8898522296,6651134.54530166,70.97392953212943],[510893.98815667373,6651133.850459621,71.07930779112941],[510893.9104247444,6651134.399889637,71.33168737812943],[510893.93503512454,6651134.225936903,71.68214359312941],[510894.0178930608,6651133.640274904,71.48965733412942],[510895.6396953445,6651122.176943657,67.35765722912942],[510895.6396953445,6651122.176943657,67.48765722912941],[510893.963613672,6651134.023936105,72.02188862012942],[510895.7250897525,6651121.573353198,67.35765722912942],[510894.05378401256,6651133.38658808,71.88143702812941],[510893.9960161115,6651133.794907017,72.34755573012941],[510894.0845207557,6651133.16933258,72.15891888812942],[510894.11827636434,6651132.93073893,72.41935956112941],[510894.0320243808,6651133.540390962,72.65592453812943],[510894.15475952154,6651132.672866243,72.66032920712941],[510894.0713507951,6651133.262421373,72.94402288912941],[510894.1936298492,6651132.398120395,72.87974821312942],[510894.11364547885,6651132.963471265,73.2092206141294],[510895.6396953445,6651122.176943657,69.18646088812942],[510895.7250897525,6651121.573353198,69.18646088812942],[510894.24851129286,6651132.010203708,73.13596133612941],[510894.1585066771,6651132.646380346,73.44930906112941],[510895.6371046331,6651122.195255497,69.59727620012941],[510894.30599404575,6651131.603900274,73.34823914512941],[510894.20549331285,6651132.314266268,73.66256139612942],[510895.72215361294,6651121.594106616,69.6520515751294],[510895.62900313304,6651122.252519061,70.0183976281294],[510894.3650820473,6651131.186250514,73.51535390212942],[510894.25413898163,6651131.970425703,73.84777029812942],[510895.7129719129,6651121.659005322,70.12932252712942],[510895.61497299606,6651122.351687812,70.44448676312942],[510894.42480062856,6651130.764143649,73.63750702412942],[510894.303966476,6651131.618231678,74.00426159012942],[510894.48424139415,6651130.344000459,73.71618171712942],[510894.35450194636,6651131.26103349,74.13188434912941],[510895.59472769586,6651122.494786996,70.86939326712941],[510895.697071091,6651121.771396574,70.61222354712942],[510894.54259682476,6651129.931528707,73.7539245761294],[510894.4052878933,6651130.902064868,74.23097984312942],[510895.6805339843,6651121.888285257,70.97392953212943],[510895.5681459361,6651122.682673966,71.2863599691294],[510894.47265409434,6651130.4259025855,74.32014449512941],[510895.6599614695,6651122.03369728,71.33168737812943],[510895.53529780573,6651122.914853315,71.6883088861294],[510894.5387902491,6651129.9584345985,74.36291973612943],[510894.7826448441,6651128.23480526,73.7539245761294],[510895.6353510894,6651122.207650012,71.68214359312941],[510895.49645894073,6651123.189376776,72.06818968812941],[510895.46367993794,6651123.421067513,72.3345960031294],[510895.60677254194,6651122.409650811,72.02188862012942],[510895.4280703693,6651123.672765445,72.58230574312941],[510895.02778906137,6651126.502060527,73.7539245761294],[510895.57437010243,6651122.638679897,72.34755573012941],[510895.37675603695,6651124.035468836,72.87974821312942],[510895.086144492,6651126.0895887725,73.71618171712942],[510895.32187459327,6651124.423385523,73.13596133612941],[510895.14558525756,6651125.669445583,73.63750702412942],[510895.2643918404,6651124.829688958,73.34823914512941],[510895.20530383894,6651125.247338717,73.51535390212942],[510895.53836183314,6651122.893195953,72.65592453812943],[510895.49903541885,6651123.171165542,72.94402288912941],[510895.4567407351,6651123.47011565,73.2092206141294],[510895.03159596474,6651126.4751523165,74.36291973612943],[510895.41187953687,6651123.787206569,73.44930906112941],[510895.0977321196,6651126.0076843295,74.32014449512941],[510895.36489290104,6651124.119320646,73.66256139612942],[510895.1650983207,6651125.531522047,74.23097984312942],[510895.31624723226,6651124.463161212,73.84777029812942],[510895.21588426747,6651125.172553425,74.13188434912941],[510895.26641973795,6651124.815355238,74.00426159012942],[510903.7417831255,6651136.2880531745,67.17808119638813],[510903.8304863374,6651135.684940094,67.17808119638813],[510903.8304863374,6651135.684940094,67.30808119638813],[510903.7417831255,6651136.2880531745,69.00688485538814],[510903.830485997,6651135.684942409,69.00688485638813],[510903.8311474081,6651135.680445326,69.21070614038813],[510903.7448330327,6651136.26731617,69.47247554238812],[510903.8366393801,6651135.643104174,69.62728542838813],[510903.754370499,6651136.202468793,69.94974649438814],[510903.8480873526,6651135.565266836,70.05161254838814],[510903.7708874349,6651136.090166433,70.43264751438814],[510903.8658618811,6651135.444413821,70.47792289938815],[510903.7880653101,6651135.973370197,70.79435349938814],[510903.89017878723,6651135.279077708,70.89973175838813],[510903.8094349546,6651135.82807318,71.15211134538814],[510903.83499892085,6651135.654258027,71.50256756038813],[510903.9210673794,6651135.069059225,71.31008130138814],[510903.8646848101,6651135.45241699,71.84231258738814],[510903.95834900916,6651134.815573043,71.70186099538815],[510905.60571014445,6651123.614794314,67.17808119638813],[510905.60571014445,6651123.614794314,67.30808119638813],[510903.89834275714,6651135.223569042,72.16797969738813],[510903.99027671845,6651134.598489368,71.97934285538813],[510905.6944133563,6651123.011681235,67.17808119638813],[510903.93574625015,6651134.969254282,72.47634850538813],[510904.02534026635,6651134.360084424,72.23978352838813],[510904.0632370478,6651134.102415687,72.48075317438813],[510903.9765964573,6651134.691504541,72.76444685638813],[510904.10361349623,6651133.827887136,72.70017218038814],[510904.02052994655,6651134.39279087,73.02964458138813],[510904.16062144836,6651133.440277252,72.95638530338813],[510904.0671293956,6651134.07595074,73.26973302838813],[510905.60571014445,6651123.614794314,69.00688485538814],[510904.2203315035,6651133.034295163,73.16866311238813],[510905.6944133563,6651123.011681235,69.00688485538814],[510904.11593663733,6651133.74409933,73.48298536338815],[510905.60301905,6651123.633091672,69.41770016738813],[510904.28170900635,6651132.616975722,73.33577786938812],[510904.1664671951,6651133.400530706,73.66819426538814],[510905.6913634492,6651123.032418239,69.47247554238812],[510905.5946036386,6651123.690309946,69.83882159538813],[510904.3437415222,6651132.195202701,73.45793099138814],[510904.2182253709,6651133.048615232,73.82468555738815],[510904.4054854578,6651131.775391801,73.53660568438814],[510905.681825983,6651123.097265616,69.94974649438814],[510904.2707189551,6651132.691699551,73.95230831638814],[510905.5800298714,6651123.789400265,70.26491073038812],[510904.4661020046,6651131.363246271,73.57434854338813],[510904.3234727209,6651132.333014838,74.05140381038814],[510905.5590001202,6651123.932386272,70.68981723438813],[510905.665309047,6651123.209567977,70.43264751438814],[510904.3934491813,6651131.857229152,74.14056846238815],[510905.53138838866,6651124.120124641,71.10678393638813],[510905.6481311718,6651123.326364213,70.79435349938814],[510904.46214793436,6651131.390130883,74.18334370338813],[510904.7154512396,6651129.667864761,73.57434854338813],[510905.4972674815,6651124.352120361,71.50873285338812],[510905.6267615274,6651123.47166123,71.15211134538814],[510905.45692371484,6651124.6264267005,71.88861365538813],[510905.601197561,6651123.645476383,71.50256756038813],[510905.4228746138,6651124.857934194,72.15501997038814],[510905.57151167176,6651123.847317419,71.84231258738814],[510904.97009413684,6651127.936490453,73.57434854338813],[510905.38588526996,6651125.10943306,72.40272971038813],[510905.03071068355,6651127.524344925,73.53660568438814],[510905.3325826452,6651125.471849589,72.70017218038814],[510905.5378537247,6651124.076165368,72.16797969738813],[510905.09245461907,6651127.104534024,73.45793099138814],[510905.27557469293,6651125.859459472,72.95638530338813],[510905.15448713506,6651126.682761002,73.33577786938812],[510905.21586463787,6651126.265441561,73.16866311238813],[510905.50045023166,6651124.330480128,72.47634850538813],[510905.4596000245,6651124.608229869,72.76444685638813],[510904.9740485475,6651127.909603526,74.18334370338813],[510905.4156665354,6651124.90694354,73.02964458138813],[510905.04274730064,6651127.442505258,74.14056846238815],[510905.36906708626,6651125.22378367,73.26973302838813],[510905.112723761,6651126.966719572,74.05140381038814],[510905.32025984454,6651125.555635081,73.48298536338815],[510905.1654775269,6651126.608034858,73.95230831638814],[510905.2697292868,6651125.899203703,73.66819426538814],[510905.21797111095,6651126.251119177,73.82468555738815],[510909.9112954335,6651137.2062217705,67.0612983281163],[510910.0020613679,6651136.603415671,67.0612983281163],[510910.0020613679,6651136.603415671,67.19129832811629],[510909.9112954335,6651137.2062217705,68.8901019871163],[510910.00206101965,6651136.603417983,68.8901019881163],[510910.0027378113,6651136.5989231905,69.09392327211629],[510909.9144162638,6651137.185495321,69.3556926741163],[510910.0083574948,6651136.561601045,69.5105025601163],[510909.92417551624,6651137.12068095,69.8329636261163],[510910.02007168066,6651136.483803324,69.93482968011631],[510909.9410765405,6651137.00843575,70.3158646461163],[510910.03825954173,6651136.363011824,70.36114003111629],[510909.9586538735,6651136.891698964,70.6775706311163],[510910.4413291449,6651137.286109873,67.0510918198317],[510910.53227229137,6651136.683330483,67.0510918198317],[510910.0631419182,6651136.197759866,70.78294889011629],[510909.98052045197,6651136.746475902,71.0353284771163],[510910.53227229137,6651136.683330483,67.18109181983169],[510910.0066788879,6651136.572749219,71.38578469211629],[510910.09474880004,6651135.987848282,71.1932984331163],[510910.03705509886,6651136.371010919,71.7255297191163],[510910.1328973843,6651135.734491124,71.58507812711629],[510910.07149573474,6651136.142279453,72.05119682911631],[510910.1655675471,6651135.517517943,71.86255998711628],[510911.818566591,6651124.539413537,67.0612983281163],[510910.4413291449,6651137.286109873,68.8798954788317],[510911.818566591,6651124.539413537,67.19129832811629],[510911.9093325254,6651123.936607438,67.0612983281163],[510910.1097690162,6651135.888094139,72.35956563711629],[510910.2014464698,6651135.279234346,72.1230006601163],[510910.5322719425,6651136.683332797,68.8798954798317],[510910.53295005544,6651136.678838202,69.08371676383169],[510910.4444560683,6651137.265384341,69.3454861658317],[510910.2402245108,6651135.021696761,72.36397030611629],[510910.1515691624,6651135.61048577,72.64766398811629],[510910.28153988137,6651134.747307943,72.58338931211631],[510910.5385807108,6651136.64151771,69.5002960518317],[510910.19652428984,6651135.311924145,72.9128617131163],[510910.45423437475,6651137.200572843,69.8227571178317],[510910.3398735081,6651134.359895351,72.8396024351163],[510910.244207372,6651134.9952452835,73.1529501601163],[510910.55031776766,6651136.5637234375,69.92462317183171],[510910.4711683966,6651137.088332616,70.3056581378317],[510911.818566591,6651124.539413537,68.8901019871163],[510910.400972073,6651133.954119906,73.05188024411629],[510910.2941495873,6651134.663562784,73.3662024951163],[510910.5685411388,6651136.4429372875,70.3509335228317],[510910.48878004774,6651136.971601002,70.66736412283171],[510911.9093325254,6651123.936607438,68.8901019871163],[510910.34585519286,6651134.320169036,73.5514113971163],[510910.46377686074,6651133.537012877,73.21899500111631],[510911.81581291725,6651124.55770158,69.3009172991163],[510910.5934720958,6651136.277692652,70.77274238183169],[510910.5106893187,6651136.826384375,71.0251219688317],[510910.3988169639,6651133.968432685,73.7079026891163],[510910.5272518934,6651133.115454536,73.34114812311628],[510911.9062116951,6651123.957333889,69.3556926741163],[510911.8072018121,6651124.614890731,69.72203872711628],[510910.59043163504,6651132.695857318,73.4198228161163],[510910.4525312445,6651133.611698673,73.83552544811629],[510910.5368988266,6651136.652665391,71.37557818383169],[510910.6251406871,6651136.0677903695,71.1830919248317],[510910.65245777124,6651132.283921569,73.45756567511629],[510911.8964524427,6651124.022148259,69.8329636261163],[510911.79228914366,6651124.713930614,70.1481278621163],[510910.5065117572,6651133.253196527,73.9346209421163],[510910.5781154644,6651132.777653014,74.02378559411629],[510910.56733434444,6651136.450936031,71.7153232108317],[510911.7707703624,6651124.85684384,70.57303436611629],[510911.87955141853,6651124.134393457,70.3158646461163],[510910.66336375306,6651135.814444437,71.5748716188317],[510910.64841175237,6651132.310792496,74.06656083511629],[510911.74251654197,6651125.044486653,70.99000106811629],[510910.90760542435,6651130.589403001,73.45756567511629],[510911.86197408556,6651124.251130244,70.6775706311163],[510910.6018422223,6651136.222214699,72.04099032083171],[510910.69609770126,6651135.597480871,71.8523534788317],[510912.3523240739,6651124.619862897,67.0510918198317],[510911.7076021803,6651125.276364288,71.3919499851163],[510911.8401075071,6651124.396353305,71.0353284771163],[510912.3523240739,6651124.619862897,67.18109181983169],[510910.6401902289,6651135.968040647,72.3493591288317],[510912.4432672205,6651124.017083507,67.0510918198317],[510910.73204667435,6651135.35920783,72.11279415183171],[510911.6663202515,6651125.550531007,71.77183078711629],[510911.81394907105,6651124.570079989,71.38578469211629],[510911.63147936563,6651125.781920664,72.03823710211628],[510911.1681698393,6651128.858909952,73.45756567511629],[510911.78357286006,6651124.771818289,71.7255297191163],[510910.77090042585,6651135.101681658,72.35376379783169],[510911.59362986404,6651126.033291517,72.28594684211629],[510910.682071986,6651135.690444578,72.6374574798317],[510911.2301959755,6651128.446974205,73.4198228161163],[510911.5390877292,6651126.395523578,72.58338931211631],[510911.2933757172,6651128.027376986,73.34114812311628],[510911.7491322243,6651125.000549755,72.05119682911631],[510911.48075410246,6651126.782936172,72.8396024351163],[510911.3568507498,6651127.605818644,73.21899500111631],[510911.4196555375,6651127.188711617,73.05188024411629],[510910.81229646085,6651134.827304999,72.57318280383171],[510911.7108589428,6651125.254735068,72.35956563711629],[510910.7271148843,6651135.391896181,72.9026552048317],[510911.17221620656,6651128.832036711,74.06656083511629],[510911.66905879654,6651125.532343438,72.64766398811629],[510911.2425124945,6651128.365176194,74.02378559411629],[510911.6241036692,6651125.830905064,72.9128617131163],[510910.8707439787,6651134.439909572,72.82939592683171],[510910.7748910632,6651135.075231353,73.1427436518317],[510911.57642058696,6651126.147583925,73.1529501601163],[510911.3141162017,6651127.88963268,73.9346209421163],[510911.52647837176,6651126.479266424,73.3662024951163],[510911.36809671443,6651127.531130535,73.83552544811629],[510911.47477276606,6651126.822660171,73.5514113971163],[510911.42181099503,6651127.174396523,73.7079026891163],[510910.82493078604,6651134.7435635505,73.3559959868317],[510910.9319618329,6651134.034152106,73.0416737358317],[510912.3523240739,6651124.619862897,68.8798954788317],[510912.4432672205,6651124.017083507,68.8798954788317],[510910.8767373421,6651134.400185017,73.5412048888317],[510910.99488924124,6651133.61706356,73.2087884928317],[510912.34956502385,6651124.638150129,69.29071079083171],[510910.9298025161,6651134.048464252,73.6976961808317],[510911.0584882031,6651133.195523898,73.33094161483169],[510912.44014029705,6651124.037809039,69.3454861658317],[510912.34093710635,6651124.695336746,69.71183221883169],[510911.1217912973,6651132.775945271,73.4096163078317],[510910.98362166894,6651133.691746046,73.82531893983169],[510911.1839385339,6651132.364027774,73.44735916683169],[510912.4303619906,6651124.102620537,69.8227571178317],[510911.0377075736,6651133.333259786,73.9244144338317],[510912.32599532226,6651124.794372239,70.1379213538317],[510911.10945108056,6651132.857737343,74.0135790858317],[510912.3044345275,6651124.937279135,70.56282785783169],[510912.4134279686,6651124.214860763,70.3056581378317],[510911.1798846155,6651132.3908975115,74.0563543268317],[510912.2761255442,6651125.124913633,70.97979455983169],[510911.43958433927,6651130.669584288,73.44735916683169],[510912.3958163176,6651124.331592378,70.66736412283171],[510912.2411430154,6651125.356780993,71.3817434768317],[510912.3739070466,6651124.476809003,71.0251219688317],[510912.1997804874,6651125.630935564,71.76162427883169],[510912.3476975387,6651124.6505279895,71.37557818383169],[510912.16487157793,6651125.862314968,72.02803059383169],[510911.70065748226,6651128.939167919,73.44735916683169],[510912.3172620209,6651124.8522573495,71.7153232108317],[510912.1269481787,6651126.1136746835,72.27574033383169],[510911.7628047189,6651128.527250421,73.4096163078317],[510912.07229955535,6651126.475890695,72.57318280383171],[510911.8261078131,6651128.107671796,73.33094161483169],[510912.01385203755,6651126.863286121,72.82939592683171],[510912.282754143,6651125.080978681,72.04099032083171],[510911.889706775,6651127.686132133,73.2087884928317],[510911.95263418334,6651127.269043588,73.0416737358317],[510912.24440613645,6651125.335152732,72.3493591288317],[510911.70471174974,6651128.912295869,74.0563543268317],[510912.2025243793,6651125.612748801,72.6374574798317],[510911.7751452848,6651128.445456036,74.0135790858317],[510912.1574814811,6651125.911297198,72.9026552048317],[510912.109705302,6651126.227962027,73.1427436518317],[510911.8468887916,6651127.969933594,73.9244144338317],[510912.0596655792,6651126.55962983,73.3559959868317],[510911.90097469627,6651127.611447334,73.82531893983169],[510912.0078590231,6651126.903008361,73.5412048888317],[510911.9547938491,6651127.2547291275,73.6976961808317],[510920.64292734413,6651138.854801047,66.84928826316256],[510920.737281306,6651138.252546136,66.84928826316256],[510920.737281306,6651138.252546136,66.97928826316257],[510920.64292734413,6651138.854801047,68.67809192216257],[510920.7372809439,6651138.252548446,68.67809192316255],[510920.6461715426,6651138.834093549,69.14368260916255],[510920.73798448953,6651138.248057762,68.88191320716255],[510920.7438263221,6651138.210769743,69.29849249516256],[510920.6563165837,6651138.769338443,69.62095356116257],[510920.75600357633,6651138.13304316,69.72281961516256],[510920.67388571467,6651138.657195876,70.10385458116257],[510920.7749104135,6651138.012362106,70.14912996616256],[510920.6921578893,6651138.54056583,70.46556056616257],[510920.7148888657,6651138.395475556,70.82331841216256],[510920.80077640404,6651137.847261251,70.57093882516256],[510920.742081359,6651138.221907725,71.17377462716257],[510920.83363272325,6651137.637541602,70.98128836816258],[510920.77365835843,6651138.020353888,71.51351965416256],[510920.87328934215,6651137.384416107,71.37306806216256],[510920.80946045154,6651137.791831567,71.83918676416256],[510920.9072509745,6651137.16764132,71.65054992216255],[510920.84924669686,6651137.5378786735,72.14755557216256],[510920.9445482108,6651136.9295756025,71.91099059516256],[510922.6255939815,6651126.199574968,66.84928826316256],[510922.6255939815,6651126.199574968,66.97928826316257],[510920.8926992259,6651137.26052414,72.43565392316256],[510920.98485916905,6651136.672273502,72.15196024116256],[510922.71994794323,6651125.597320058,66.84928826316256],[510921.02780775895,6651136.398135577,72.37137924716257],[510920.9394314543,6651136.962235509,72.70085164816255],[510921.08844734606,6651136.011077224,72.62759237016256],[510920.988999475,6651136.64584621,72.94094009516256],[510921.04091593355,6651136.314466992,73.15419243016257],[510921.151961171,6651135.6056728065,72.83987017916256],[510921.09466549027,6651135.9713872345,73.33940133216257],[510921.2172486666,6651135.188947171,73.00698493616255],[510922.6255939815,6651126.199574968,68.67809192216257],[510921.1497208692,6651135.6199725,73.49589262416256],[510921.28323290235,6651134.767774289,73.12913805816257],[510922.71994794323,6651125.597320058,68.67809192216257],[510922.62273145345,6651126.217846289,69.08890723416256],[510921.20555850497,6651135.263564675,73.62351538316257],[510921.3489101739,6651134.348560738,73.20781275116256],[510922.71670374484,6651125.618027556,69.14368260916255],[510922.61377994664,6651126.274983148,69.51002866216255],[510921.4133882375,6651133.937001651,73.24555561016255],[510921.2616728971,6651134.905390334,73.72261087716257],[510921.33610713837,6651134.430281643,73.81177552916256],[510922.59827777214,6651126.3739324715,69.93611779716255],[510922.70655870374,6651125.682782662,69.62095356116257],[510921.4091822772,6651133.963848009,73.85455077016256],[510922.5759083416,6651126.516715024,70.36102430116256],[510922.68898957275,6651125.794925229,70.10385458116257],[510921.6786220178,6651132.2440325,73.24555561016255],[510922.5465376321,6651126.70418626,70.77799100316255],[510922.6707173981,6651125.911555273,70.46556056616257],[510922.51024308644,6651126.935851873,71.17993992016255],[510922.6479864217,6651126.056645547,70.82331841216256],[510922.4673292602,6651127.209767902,71.55982072216257],[510921.94948668766,6651130.5151217645,73.24555561016255],[510922.62079392845,6651126.23021338,71.17377462716257],[510922.43111109495,6651127.440945984,71.82622703716255],[510922.0139647514,6651130.103562677,73.20781275116256],[510922.39176538173,6651127.692086992,72.07393677716257],[510922.589216929,6651126.431767216,71.51351965416256],[510922.0796420229,6651129.684349127,73.12913805816257],[510922.33506716625,6651128.053987837,72.37137924716257],[510922.14562625857,6651129.263176247,73.00698493616255],[510922.27442757913,6651128.441046191,72.62759237016256],[510922.2109137543,6651128.846450608,72.83987017916256],[510922.55341483594,6651126.660289537,71.83918676416256],[510921.95369301015,6651130.488273094,73.85455077016256],[510922.5136285905,6651126.9142424315,72.14755557216256],[510922.47017606156,6651127.191596963,72.43565392316256],[510922.0267681491,6651130.021839462,73.81177552916256],[510922.4234438331,6651127.489885594,72.70085164816255],[510922.10120239033,6651129.546730771,73.72261087716257],[510922.37387581245,6651127.806274893,72.94094009516256],[510922.1573167824,6651129.188556428,73.62351538316257],[510922.32195935387,6651128.137654111,73.15419243016257],[510922.2131544181,6651128.832148603,73.49589262416256],[510922.2682097972,6651128.4807338705,73.33940133216257],[510927.01434431603,6651139.864548177,66.71807430255812],[510927.1108285054,6651139.262630868,66.71807430255812],[510927.1108285054,6651139.262630868,66.8480743025581],[510927.01434431603,6651139.864548177,68.54687796155812],[510927.1108281352,6651139.2626331765,68.5468779625581],[510927.01766175864,6651139.843852287,69.0124686485581],[510927.11154756474,6651139.258145011,68.75069924655811],[510927.11752128834,6651139.220877892,69.16727853455812],[510927.02803584404,6651139.77913348,69.48973960055811],[510927.129973468,6651139.143194879,69.59160565455811],[510927.046001633,6651139.667053777,69.97264062055812],[510927.1493071646,6651139.022581476,70.0179160055581],[510927.0646863382,6651139.550489109,70.33434660555811],[510927.0879305114,6651139.405480167,70.69210445155811],[510927.17575713113,6651138.857573168,70.43972486455812],[510927.1157369292,6651139.23200963,71.0425606665581],[510927.20935524686,6651138.647971082,70.85007440755811],[510927.14802684187,6651139.030568777,71.38230569355812],[510927.2499071924,6651138.394987477,71.2418541015581],[510927.18463723816,6651138.802174556,71.7079728035581],[510927.2846355759,6651138.178334206,71.5193359615581],[510927.2253217368,6651138.548364019,72.0163416115581],[510927.32277487125,6651137.940401938,71.7797766345581],[510927.2697552928,6651138.271164959,72.30443996255812],[510927.36399592925,6651137.683244072,72.02074628055811],[510929.0417735806,6651127.216416116,66.71807430255812],[510929.0417735806,6651127.216416116,66.8480743025581],[510927.40791416867,6651137.409259818,72.24016528655811],[510929.1382577701,6651126.614498805,66.71807430255812],[510927.3175425938,6651137.973043539,72.5696376875581],[510927.3682297108,6651137.656831594,72.8097261345581],[510927.4699228147,6651137.022418435,72.4963784095581],[510927.4213182863,6651137.325638134,73.02297846955811],[510927.53487058997,6651136.61724127,72.7086562185581],[510927.4762813457,6651136.982750693,73.20818737155811],[510927.6016320801,6651136.200749233,72.87577097555811],[510927.53257970896,6651136.6315329475,73.36467866355811],[510929.0417735806,6651127.216416116,68.54687796155812],[510927.6691060406,6651135.779812445,72.9979240975581],[510927.5896779899,6651136.275324911,73.4923014225581],[510929.1382577701,6651126.614498805,68.54687796155812],[510927.73626610683,6651135.360833889,73.07659879055812],[510929.03884642536,6651127.234677196,68.9576932735581],[510927.64705927565,6651135.917351346,73.59139691655812],[510927.8021998904,6651134.949505504,73.11434164955811],[510929.1349403274,6651126.635194695,69.0124686485581],[510929.02969282056,6651127.291782024,69.3788147015581],[510927.7231740173,6651135.442508983,73.6805615685581],[510929.0138406538,6651127.390675882,69.80490383655811],[510927.79789897223,6651134.9763368135,73.7233368095581],[510929.124566242,6651126.699913502,69.48973960055811],[510928.0734218488,6651133.257485365,73.11434164955811],[510928.99096618895,6651127.533378394,70.22981034055812],[510929.10660045303,6651126.811993206,69.97264062055812],[510928.96093237755,6651127.720744543,70.6467770425581],[510929.08791574783,6651126.928557873,70.33434660555811],[510928.9238184106,6651127.952280293,71.0487259595581],[510929.0646715746,6651127.073566816,70.69210445155811],[510928.3504018253,6651131.529543788,73.11434164955811],[510928.8799357197,6651128.226042776,71.4286067615581],[510929.03686515684,6651127.247037352,71.0425606665581],[510928.84289985773,6651128.457091268,71.69501307655811],[510928.41633560887,6651131.118215404,73.07659879055812],[510928.80266583705,6651128.708091495,71.9427228165581],[510928.483495675,6651130.699236848,72.9979240975581],[510929.00457524415,6651127.448478205,71.38230569355812],[510928.7446875469,6651129.069789475,72.24016528655811],[510928.5509696356,6651130.278300061,72.87577097555811],[510928.682678901,6651129.456630859,72.4963784095581],[510928.6177311257,6651129.8618080225,72.7086562185581],[510928.96796484786,6651127.676872426,71.7079728035581],[510928.3547031138,6651131.502710169,73.7233368095581],[510928.9272803492,6651127.930682964,72.0163416115581],[510928.42942806875,6651131.036537999,73.6805615685581],[510928.8828467932,6651128.207882023,72.30443996255812],[510928.50554281037,6651130.561695635,73.59139691655812],[510928.83505949215,6651128.506003444,72.5696376875581],[510928.5629240961,6651130.203722072,73.4923014225581],[510928.78437237523,6651128.822215388,72.8097261345581],[510928.62002237706,6651129.847514034,73.36467866355811],[510928.73128379975,6651129.153408848,73.02297846955811],[510928.6763207404,6651129.496296291,73.20818737155811],[510929.77274426864,6651140.308873249,66.66002999750813],[510929.870150705,6651139.707104495,66.66002999750813],[510929.870150705,6651139.707104495,66.79002999750811],[510929.77274426864,6651140.308873249,68.48883365650812],[510929.87015033123,6651139.7071068045,68.48883365750811],[510929.7760934212,6651140.288182467,68.95442434350811],[510929.87087663746,6651139.702619746,68.69265494150811],[510929.8769074611,6651139.665361826,69.10923422950813],[510929.7865666676,6651140.223479633,69.43169529550813],[510929.88947866537,6651139.587697985,69.53356134950812],[510929.804704183,6651140.111427591,69.91459631550813],[510929.9089971635,6651139.467114348,69.95987170050812],[510929.8235674865,6651139.994891694,70.27630230050812],[510929.8470338399,6651139.84991854,70.63406014650812],[510929.9356999528,6651139.302146767,70.38168055950811],[510929.87510604603,6651139.676490816,70.98451636150811],[510929.96961921715,6651139.092596412,70.79203010250812],[510929.9077046028,6651139.475099679,71.32426138850812],[510930.01055877964,6651138.839675245,71.18380979650811],[510929.9446649406,6651139.246761828,71.64992849850812],[510930.04561911547,6651138.623075444,71.46129165650811],[510929.9857383233,6651138.993013931,71.95829730650811],[510930.08412296633,6651138.385201898,71.72173232950811],[510930.03059659875,6651138.715883288,72.24639565750813],[510930.12573803705,6651138.1281075,71.96270197550812],[510931.81955277483,6651127.6638628105,66.66002999750813],[510931.81955277483,6651127.6638628105,66.79002999750811],[510930.17007607024,6651137.854190868,72.18212098150812],[510930.07884067605,6651138.417835443,72.51159338250811],[510931.9169592113,6651127.062094056,66.66002999750813],[510930.13001228723,6651138.101701542,72.75168182950812],[510930.2326774276,6651137.467444957,72.43833410450812],[510930.1836083114,6651137.770589822,72.96493416450812],[510930.2982460081,6651137.062367794,72.65061191350811],[510930.2390967368,6651137.427787006,73.15014306650812],[510930.36564563995,6651136.645978549,72.81772667050811],[510930.2959332297,6651137.076655945,73.30663435850812],[510930.43376455235,6651136.22514565,72.93987979250812],[510931.81955277483,6651127.6638628105,68.48883365650812],[510930.3535772863,6651136.720535822,73.43425711750811],[510930.50156656984,6651135.8062705,73.01855448550813],[510931.9169592113,6651127.062094056,68.48883365650812],[510931.81659764034,6651127.682119383,68.89964896850812],[510930.41150705266,6651136.362650607,73.53335261150812],[510930.5681305835,6651135.395043635,73.05629734450812],[510931.9136100587,6651127.082784838,68.95442434350811],[510931.8073565405,6651127.739210118,69.32077039650812],[510930.48834933934,6651135.887925437,73.62251726350812],[510930.56378855486,6651135.421868321,73.66529250450812],[510931.7913528504,6651127.838079567,69.74685953150811],[510931.9031368123,6651127.147487671,69.43169529550813],[510930.8419450249,6651133.703441093,73.05629734450812],[510931.7682597393,6651127.980746861,70.17176603550811],[510931.8849992968,6651127.259539713,69.91459631550813],[510931.7379388489,6651128.168066767,70.58873273750811],[510931.86613599333,6651127.376075613,70.27630230050812],[510931.70047012705,6651128.3995453715,70.99068165450811],[510931.84266963997,6651127.521048766,70.63406014650812],[510931.12157252245,6651131.975925981,73.05629734450812],[510931.65616798215,6651128.67324029,71.37056245650811],[510931.8145974338,6651127.69447649,70.98451636150811],[510931.18813653616,6651131.564699115,73.01855448550813],[510931.61877811176,6651128.904231757,71.63696877150811],[510931.578159513,6651129.1551700365,71.88467851150811],[510931.25593855366,6651131.145823965,72.93987979250812],[510931.78199887706,6651127.895867626,71.32426138850812],[510931.5196270357,6651129.516778748,72.18212098150812],[510931.32405746606,6651130.724991065,72.81772667050811],[510931.45702567836,6651129.903524657,72.43833410450812],[510931.39145709784,6651130.308601822,72.65061191350811],[510931.74503853923,6651128.1242054785,71.64992849850812],[510931.12591492495,6651131.949098984,73.66529250450812],[510931.7039651566,6651128.377953374,71.95829730650811],[510931.2013541406,6651131.483041869,73.62251726350812],[510931.6591068812,6651128.655084019,72.24639565750813],[510931.2781964273,6651131.008316698,73.53335261150812],[510931.6108628039,6651128.953131862,72.51159338250811],[510931.33612619364,6651130.650431485,73.43425711750811],[510931.55969119264,6651129.269265763,72.75168182950812],[510931.39377025014,6651130.294311362,73.30663435850812],[510931.5060951684,6651129.600377483,72.96493416450812],[510931.450606743,6651129.943180299,73.15014306650812],[510937.5192634639,6651141.579897319,66.49301605051268],[510937.6192598813,6651140.9785535205,66.49301605051268],[510937.6192598813,6651140.9785535205,66.62301605051267],[510937.5192634639,6651141.579897319,68.32181970951268],[510937.6192594977,6651140.978555827,68.32181971051267],[510937.5227016685,6651141.5592211485,68.78741039651267],[510937.6200051159,6651140.974071938,68.52564099451267],[510937.62619629566,6651140.936840328,68.94222028251268],[510937.5334533925,6651141.494564006,69.26468134851268],[510937.639101761,6651140.859231332,69.36654740251268],[510937.55207317404,6651141.382591093,69.74758236851268],[510937.65913924476,6651140.738732849,69.79285775351269],[510937.5714380419,6651141.26613749,70.10928835351268],[510937.595528352,6651141.121266712,70.46704619951268],[510937.68655204587,6651140.573881765,70.21466661251267],[510937.62434698205,6651140.947961461,70.81750241451267],[510937.72137320385,6651140.364479389,70.62501615551268],[510937.6578123157,6651140.746712541,71.15724744151268],[510937.76340132585,6651140.111736829,71.01679584951269],[510937.69575540756,6651140.518535936,71.48291455151268],[510937.79939389566,6651139.895289987,71.29427770951267],[510937.7379209078,6651140.264967231,71.79128335951268],[510937.8389215418,6651139.657584422,71.55471838251268],[510937.78397193894,6651139.988032291,72.07938171051268],[510937.8816431333,6651139.400671579,71.79568802851267],[510937.92716008925,6651139.126948379,72.01510703451268],[510937.8334987985,6651139.6901949225,72.34457943551267],[510939.62049542944,6651128.943816506,66.49301605051268],[510939.62049542944,6651128.943816506,66.62301605051267],[510937.88603103335,6651139.374284267,72.58466788251268],[510939.7204918468,6651128.342472709,66.49301605051268],[510937.9914259807,6651138.740475582,72.27132015751268],[510937.9410521449,6651139.043406372,72.7979202175127],[510938.058737992,6651138.335684474,72.48359796651268],[510937.9980159757,6651138.7008456355,72.98312911951268],[510938.1279297412,6651137.919589275,72.65071272351267],[510938.05636371806,6651138.349962533,73.1396204115127],[510938.19785989623,6651137.499053558,72.77286584551268],[510938.11554049695,6651137.994093895,73.26724317051267],[510939.62049542944,6651128.943816506,68.32181970951268],[510938.2674647303,6651137.080474208,72.85154053851268],[510938.1750105824,6651137.636461412,73.36633866451268],[510938.3357986428,6651136.669537742,72.88928339751267],[510939.7204918468,6651128.342472709,68.32181970951268],[510939.61746171955,6651128.962060186,68.73263502151268],[510938.2538960613,6651137.162071481,73.45550331651269],[510939.7170536422,6651128.363148879,68.78741039651267],[510939.6079749042,6651129.019110605,69.15375644951267],[510938.33134116215,6651136.696343485,73.49827855751268],[510939.59154568514,6651129.117910235,69.57984558451267],[510938.6168936525,6651134.979129774,72.88928339751267],[510939.70630191825,6651128.427806021,69.26468134851268],[510939.5678385415,6651129.26047678,70.00475208851269],[510939.68768213666,6651128.539778934,69.74758236851268],[510939.5367114361,6651129.447664404,70.42171879051267],[510939.6683172688,6651128.656232538,70.10928835351268],[510939.4982464425,6651129.678979545,70.82366770751267],[510938.90395628416,6651133.252834594,72.88928339751267],[510939.6442269587,6651128.801103313,70.46704619951268],[510939.45276632905,6651129.952481185,71.20354850951267],[510938.9722901965,6651132.8418981265,72.85154053851268],[510939.4143822835,6651130.183309532,71.46995482451268],[510939.61540832865,6651128.974408567,70.81750241451267],[510939.0418950307,6651132.423318778,72.77286584551268],[510939.37268365966,6651130.434070605,71.71766456451267],[510939.1118251857,6651132.002783062,72.65071272351267],[510939.31259483757,6651130.795423956,72.01510703451268],[510939.1810169349,6651131.586687861,72.48359796651268],[510939.2483289461,6651131.181896754,72.27132015751268],[510939.581942995,6651129.175657485,71.15724744151268],[510938.90841414867,6651133.2260265425,73.49827855751268],[510939.54399990314,6651129.40383409,71.48291455151268],[510938.98585924954,6651132.760298545,73.45550331651269],[510939.50183440285,6651129.657402795,71.79128335951268],[510939.0647447283,6651132.285908615,73.36633866451268],[510939.45578337176,6651129.934337736,72.07938171051268],[510939.12421481375,6651131.928276133,73.26724317051267],[510939.4062565123,6651130.232175105,72.34457943551267],[510939.18339159264,6651131.572407492,73.1396204115127],[510939.35372427735,6651130.54808576,72.58466788251268],[510939.241739335,6651131.221524391,72.98312911951268],[510939.2987031657,6651130.878963656,72.7979202175127],[510943.5629395488,6651142.59533044,66.35860467732431],[510943.6649566165,6651141.9943261435,66.35860467732431],[510943.6649566165,6651141.9943261435,66.4886046773243],[510943.5629395488,6651142.59533044,68.18740833632432],[510943.66495622514,6651141.994328449,68.1874083373243],[510943.56644723,6651142.574665943,68.6529990233243],[510943.66571691027,6651141.98984709,68.39122962132431],[510943.5774162165,6651142.510045304,69.13026997532431],[510943.67203319655,6651141.952636503,68.80780890932432],[510943.6851994456,6651141.875071323,69.23213602932431],[510943.5964122523,6651142.398135608,69.61317099532432],[510943.70564183145,6651141.754640868,69.65844638032432],[510943.61616843037,6651142.28174775,69.97487698032431],[510943.6407455389,6651142.136958764,70.33263482632431],[510943.73360856925,6651141.5898828525,70.08025523932432],[510943.6701465135,6651141.963751353,70.6830910413243],[510943.76913336624,6651141.380598699,70.49060478232431],[510943.7042880887,6651141.762616056,71.02283606832432],[510943.81201075995,6651141.127998831,70.8823844763243],[510943.7429979053,6651141.534568272,71.34850317832431],[510943.84873063985,6651140.911674188,71.1598663363243],[510943.78601545334,6651141.281142725,71.6568719863243],[510943.88905703014,6651140.674102826,71.4203070093243],[510943.8329970481,6651141.004364133,71.9449703373243],[510943.9326419065,6651140.417335027,71.6612766553243],[510943.9790786339,6651140.143766365,71.88069566132431],[510943.8835247082,6651140.706694915,72.2101680623243],[510945.70663158584,6651129.966383592,66.35860467732431],[510943.9371184739,6651140.390962614,72.4502565093243],[510944.04464316077,6651139.757511758,72.1369087843243],[510945.70663158584,6651129.966383592,66.4886046773243],[510945.8086486536,6651129.365379294,66.35860467732431],[510943.99325140956,6651140.060271521,72.66350884432433],[510944.11331536114,6651139.352949184,72.3491865933243],[510944.0513663213,6651139.717904185,72.84871774632431],[510944.18390528375,6651138.937088898,72.51630135032431],[510944.1108931098,6651139.367219183,73.00520903832431],[510944.2552485334,6651138.516790605,72.6384544723243],[510944.1712656873,6651139.0115514565,73.1328317973243],[510944.3262598882,6651138.098447572,72.71712916532432],[510945.70663158584,6651129.966383592,68.18740833632432],[510944.2319374983,6651138.654120883,73.23192729132433],[510944.39597463945,6651137.687743109,72.75487202432431],[510945.8086486536,6651129.365379294,68.18740833632432],[510944.3124170339,6651138.179998779,73.32109194332432],[510945.70353657304,6651129.984616972,68.5982236483243],[510944.39142708544,6651137.714533719,73.3638671843243],[510945.6938580555,6651130.041635182,69.0193450763243],[510945.80514097237,6651129.386043793,68.6529990233243],[510944.68274979986,6651135.998289496,72.75487202432431],[510945.67709684744,6651130.140379032,69.44543421132431],[510945.7941719858,6651129.450664431,69.13026997532431],[510945.65291064826,6651130.2828650875,69.87034071532432],[510945.7751759502,6651129.562574126,69.61317099532432],[510945.6211545503,6651130.469947032,70.2873074173243],[510945.755419772,6651129.678961985,69.97487698032431],[510944.9756131713,6651134.272968933,72.75487202432431],[510945.58191228594,6651130.7011315795,70.6892563343243],[510945.7308426635,6651129.82375097,70.33263482632431],[510945.04532792256,6651133.862264468,72.71712916532432],[510945.53551314556,6651130.974478807,71.0691371363243],[510945.49635346484,6651131.205176835,71.33554345132431],[510945.1163392775,6651133.443921437,72.6384544723243],[510945.70144168887,6651129.9969583815,70.6830910413243],[510945.45381222747,6651131.455796335,71.5832531913243],[510945.187682527,6651133.023623142,72.51630135032431],[510945.39250917686,6651131.816945677,71.88069566132431],[510945.2582724496,6651132.607762857,72.3491865933243],[510945.3269446499,6651132.203200284,72.1369087843243],[510944.9801611169,6651134.246176015,73.3638671843243],[510945.6673001137,6651130.19809368,71.02283606832432],[510945.62859029707,6651130.426141462,71.34850317832431],[510945.05917116854,6651133.780710955,73.32109194332432],[510945.58557274897,6651130.679567009,71.6568719863243],[510945.1396507041,6651133.306588852,73.23192729132433],[510945.5385911543,6651130.956345601,71.9449703373243],[510945.20032251516,6651132.949158277,73.1328317973243],[510945.48806349415,6651131.254014821,72.2101680623243],[510945.2606950926,6651132.593490551,73.00520903832431],[510945.4344697285,6651131.56974712,72.4502565093243],[510945.32022188103,6651132.242805549,72.84871774632431],[510945.37833679287,6651131.900438213,72.66350884432433],[510949.59877879947,6651143.630311312,66.2207633583812],[510949.70281389734,6651143.029653051,66.2207633583812],[510949.70281389734,6651143.029653051,66.3507633583812],[510949.59877879947,6651143.630311312,68.04956701738121],[510949.70281349815,6651143.029655356,68.0495670183812],[510949.60235586704,6651143.609658713,68.5151577043812],[510949.70358923066,6651143.025176579,68.2533883023812],[510949.61354183446,6651143.545075281,68.99242865638121],[510949.71003046125,6651142.987987413,68.6699675903812],[510949.72345715575,6651142.910466894,69.0942947103812],[510949.63291363645,6651143.433230017,69.47532967638121],[510949.6530606174,6651143.316909172,69.83703566138121],[510949.7443039185,6651142.790105779,69.5206050613812],[510949.6781238931,6651143.172203549,70.1947935073812],[510949.7728238748,6651142.625442625,69.9424139203812],[510949.7081064571,6651142.999095866,70.5452497223812],[510949.8090513985,6651142.4162789695,70.35276346338122],[510949.7429233971,6651142.7980763735,70.8849947493812],[510949.8527769627,6651142.163824541,70.7445431573812],[510949.78239894414,6651142.570159893,71.2106618593812],[510949.8902232096,6651141.947624451,71.0220250173812],[510949.8262674352,6651142.316880259,71.5190306673812],[510949.9313473083,6651141.7101898715,71.2824656903812],[510949.8741783869,6651142.040261026,71.8071290183812],[510949.97579435,6651141.4535699105,71.5234353363812],[510949.9257055497,6651141.742763194,72.07232674338121],[510950.0231496563,6651141.180158759,71.74285434238121],[510949.9803594697,6651141.427212682,72.31241519038122],[510950.09001113474,6651140.794126544,71.99906746538122],[510951.78487584996,6651131.008635759,66.2207633583812],[510951.78487584996,6651131.008635759,66.3507633583812],[510950.0376027878,6651141.0967119895,72.52566752538121],[510950.16004176036,6651140.389796902,72.2113452743812],[510951.88891094783,6651130.4079775,66.2207633583812],[510950.09686728806,6651140.754541776,72.71087642738121],[510950.23202804336,6651139.974176056,72.3784600313812],[510950.1575715937,6651140.4040586855,72.8673677193812],[510950.30478255503,6651139.554119755,72.50061315338122],[510950.2191384192,6651140.04859574,72.9949904783812],[510950.37719860673,6651139.136017589,72.5792878463812],[510950.2810103975,6651139.691370961,73.09408597238121],[510950.4482924064,6651138.725549594,72.6170307053812],[510951.78487584996,6651131.008635759,68.04956701738121],[510950.3630819228,6651139.217521841,73.1832506243812],[510951.88891094783,6651130.4079775,68.04956701738121],[510951.7817196139,6651131.026858642,68.4603823293812],[510950.4436548959,6651138.7523247795,73.2260258653812],[510951.77184964257,6651131.083844024,68.8815037573812],[510951.88533388014,6651130.428630099,68.5151577043812],[510950.7407403521,6651137.037068709,72.6170307053812],[510951.7547568761,6651131.18253102,69.30759289238121],[510951.87414791284,6651130.493213531,68.99242865638121],[510951.7300922425,6651131.324935039,69.7324993963812],[510951.85477611085,6651130.605058793,69.47532967638121],[510951.6977079677,6651131.511909266,70.1494660983812],[510951.0393969415,6651135.312741524,72.6170307053812],[510951.8346291299,6651130.721379639,69.83703566138121],[510951.6576894403,6651131.742960705,70.5514150153812],[510951.1104907411,6651134.902273528,72.5792878463812],[510951.8095658542,6651130.866085261,70.1947935073812],[510951.6103724646,6651132.01615055,70.93129581738121],[510951.18290679285,6651134.484171363,72.50061315338122],[510951.5704381546,6651132.2467157515,71.1977021323812],[510951.7795832901,6651131.039192946,70.5452497223812],[510951.2556613045,6651134.064115061,72.3784600313812],[510951.5270553962,6651132.497190952,71.44541187238121],[510951.3276475875,6651133.648494214,72.2113452743812],[510951.4645396917,6651132.858132358,71.74285434238121],[510951.0440348513,6651135.285964033,73.2260258653812],[510951.39767821325,6651133.244164573,71.99906746538122],[510951.7447663502,6651131.240212437,70.8849947493812],[510951.12460782443,6651134.82076697,73.1832506243812],[510951.70529080316,6651131.468128918,71.2106618593812],[510951.2066793498,6651134.346917849,73.09408597238121],[510951.6614223121,6651131.7214085525,71.5190306673812],[510951.2685513281,6651133.98969307,72.9949904783812],[510951.61351136037,6651131.998027785,71.8071290183812],[510951.3301181535,6651133.634230126,72.8673677193812],[510951.5619841975,6651132.295525616,72.07232674338121],[510951.39082245925,6651133.283747035,72.71087642738121],[510951.50733027747,6651132.611076129,72.31241519038122],[510951.45008695946,6651132.941576822,72.52566752538121],[510954.3693079373,6651144.463102438,66.10926455844026],[510954.4749380199,6651143.862722614,66.10926455844026],[510954.4749380199,6651143.862722614,66.23926455844025],[510954.3693079373,6651144.463102438,67.93806821744026],[510954.4749376146,6651143.862724918,67.93806821844025],[510954.3729398458,6651144.442459412,68.40365890444025],[510954.4757252401,6651143.858248216,68.14188950244025],[510954.38429730764,6651144.377905917,68.88092985644026],[510954.4822652226,6651143.821076291,68.55846879044026],[510954.4958977647,6651143.743591704,68.98279591044026],[510954.4039661029,6651144.266112501,69.36383087644026],[510954.4244219616,6651144.149845576,69.72553686144026],[510954.51706413366,6651143.623286384,69.40910626144027],[510954.4498694878,6651144.005207032,70.08329470744026],[510954.5460213355,6651143.458699561,69.83091512044025],[510954.48031172116,6651143.832179594,70.43375092244025],[510954.58280427137,6651143.249632864,70.24126466344026],[510954.5156624472,6651143.631253284,70.77349594944026],[510954.62720020174,6651142.99729546,70.63304435744027],[510954.55574320245,6651143.4034424545,71.09916305944026],[510954.66522054514,6651142.781195589,70.91052621744025],[510954.60028425086,6651143.150280228,71.40753186744026],[510954.7069751263,6651142.543871074,71.17096689044025],[510954.6489297359,6651142.873789223,71.69563021844026],[510954.75210359547,6651142.28737007,71.41193653644025],[510954.70124687284,6651142.576429299,71.96082794344025],[510954.80018491624,6651142.01408566,71.63135554244026],[510954.75673870405,6651142.261025059,72.20091639044026],[510954.86807146255,6651141.62823239,71.88756866544026],[510954.8148596318,6651141.930677571,72.41416872544028],[510956.58892051806,6651131.847277692,66.10926455844026],[510954.939175743,6651141.224090176,72.09984647444026],[510956.58892051806,6651131.847277692,66.23926455844025],[510956.69455060066,6651131.246897866,66.10926455844026],[510954.875032729,6651141.5886659715,72.59937762744026],[510955.01226566336,6651140.808661992,72.26696123144026],[510954.93666770565,6651141.238345348,72.75586891944027],[510955.0861355904,6651140.388800407,72.38911435344025],[510954.9991784255,6651140.883047179,72.88349167844027],[510955.1596618683,6651139.970892055,72.46778904644026],[510955.0619989766,6651140.525987992,72.98258717244026],[510955.2318456225,6651139.560614333,72.50553190544025],[510956.58892051806,6651131.847277692,67.93806821744026],[510955.14532875834,6651140.052358526,73.07175182444027],[510955.2271370133,6651139.587377106,73.11452706544026],[510956.69455060066,6651131.246897866,67.93806821744026],[510956.5857158929,6651131.865492125,68.34888352944026],[510956.5756946031,6651131.922451091,68.77000495744025],[510955.5287771513,6651137.872916145,72.50553190544025],[510956.69091869215,6651131.2675408935,68.40365890444025],[510956.5583397836,6651132.021092342,69.19609409244028],[510956.6795612303,6651131.332094387,68.88092985644026],[510956.5332970111,6651132.163430348,69.62100059644025],[510956.659892435,6651131.443887804,69.36383087644026],[510956.50041624595,6651132.350317904,70.03796729844025],[510955.8320125099,6651136.149388276,72.50553190544025],[510956.6394365763,6651131.560154729,69.72553686144026],[510956.45978418575,6651132.581262238,70.43991621544025],[510955.9041962641,6651135.739110555,72.46778904644026],[510956.61398905015,6651131.704793272,70.08329470744026],[510956.41174178326,6651132.854325446,70.81979701744025],[510955.9777225421,6651135.321202202,72.38911435344025],[510956.37119523156,6651133.084783768,71.08620333244025],[510956.05159246904,6651134.90134062,72.26696123144026],[510956.32714736264,6651133.335142861,71.33391307244025],[510956.58354681684,6651131.877820711,70.43375092244025],[510955.83672152465,6651136.122623199,73.11452706544026],[510956.1246823895,6651134.485912433,72.09984647444026],[510956.2636732163,6651133.695916952,71.63135554244026],[510956.19578666997,6651134.081770221,71.88756866544026],[510956.54819609073,6651132.07874702,70.77349594944026],[510955.9185297795,6651135.65764178,73.07175182444027],[510956.5081153355,6651132.30655785,71.09916305944026],[510956.00185956137,6651135.184012312,72.98258717244026],[510956.4635742871,6651132.559720077,71.40753186744026],[510956.0646801124,6651134.826953126,72.88349167844027],[510956.41492880206,6651132.836211082,71.69563021844026],[510956.1271908323,6651134.471654956,72.75586891944027],[510956.3626116651,6651133.133571006,71.96082794344025],[510956.18882580893,6651134.121334333,72.59937762744026],[510956.3071198339,6651133.448975246,72.20091639044026],[510956.24899890606,6651133.779322733,72.41416872544028],[510960.08571448433,6651145.47822558,65.97268294412484],[510960.1932557976,6651144.878185154,65.97268294412484],[510960.1932557976,6651144.878185154,66.10268294412484],[510960.08571448433,6651145.47822558,67.80148660312486],[510960.19325538503,6651144.878187455,67.80148660412483],[510960.0894121072,6651145.457594223,68.26707729012483],[510960.1940572614,6651144.873713284,68.00530788812485],[510960.1009750667,6651145.393077222,68.74434824212484],[510960.20071557583,6651144.836562372,68.42188717612486],[510960.21459478,6651144.759121588,68.84621429612484],[510960.1209997416,6651145.281347002,69.22724926212486],[510960.1418257209,6651145.165145803,69.58895524712484],[510960.2361441253,6651144.638884278,69.27252464712485],[510960.16773368506,6651145.020589026,69.94671309312484],[510960.2656252678,6651144.474390496,69.69433350612485],[510960.19872672856,6651144.847659399,70.29716930812484],[510960.30307374004,6651144.265441985,70.10468304912484],[510960.2347170771,6651144.646846673,70.63691433512486],[510960.34827295353,6651144.013247228,70.49646274312485],[510960.2755230384,6651144.419164628,70.96258144512484],[510960.38698122266,6651143.797269521,70.77394460312483],[510960.32086999563,6651144.166145515,71.27095025312484],[510960.42949129536,6651143.560079167,71.03438527612484],[510960.37039565353,6651143.889810811,71.55904860412484],[510960.47543630184,6651143.303723163,71.27535492212483],[510960.42365939694,6651143.592618984,71.82424632912483],[510960.5243875877,6651143.030593241,71.49477392812484],[510960.4801552763,6651143.277393045,72.06433477612484],[510960.5935024474,6651142.644958097,71.75098705112484],[510960.53932782204,6651142.947232305,72.27758711112486],[510960.6658932617,6651142.241044347,71.96326486012484],[510962.3454878923,6651132.869532619,65.97268294412484],[510962.3454878923,6651132.869532619,66.10268294412484],[510960.6005896685,6651142.605414046,72.46279601312484],[510960.7403056434,6651141.8258510055,72.13037961712485],[510962.45302920556,6651132.269492191,65.97268294412484],[510960.663339845,6651142.255291461,72.61928730512484],[510960.81551214476,6651141.406226771,72.25253273912483],[510960.7269816101,6651141.900194142,72.74691006412483],[510960.8903687793,6651140.988554664,72.33120743212484],[510960.79093881237,6651141.543336804,72.84600555812486],[510960.9638585989,6651140.578508874,72.36895029112483],[510960.8757763315,6651141.069975081,72.93517021012485],[510962.3454878923,6651132.869532619,67.80148660312486],[510960.959064794,6651140.605256519,72.97794545112484],[510962.45302920556,6651132.269492191,67.80148660312486],[510962.3422252839,6651132.887736755,68.21230191512484],[510961.266162694,6651138.891764751,72.36895029112483],[510962.3320226727,6651132.944663522,68.63342334312483],[510962.44933158264,6651132.290123547,68.26707729012483],[510962.3143538417,6651133.043249011,69.05951247812484],[510962.4377686233,6651132.354640549,68.74434824212484],[510962.2888579548,6651133.1855065515,69.48441898212485],[510962.4177439483,6651132.466370769,69.22724926212486],[510962.2553822575,6651133.37228846,69.90138568412483],[510961.5748846781,6651137.1692111995,72.36895029112483],[510962.396917969,6651132.5825719675,69.58895524712484],[510961.64837449783,6651136.75916541,72.33120743212484],[510962.2140150162,6651133.603102241,70.30333460112483],[510961.72323113226,6651136.341493303,72.25253273912483],[510962.16510335275,6651133.876011085,70.68321540312483],[510962.37101000483,6651132.727128746,69.94671309312484],[510962.1238231672,6651134.106339126,70.94962171812485],[510961.7984376337,6651135.92186907,72.13037961712485],[510961.579678896,6651137.142461253,72.97794545112484],[510962.0789783129,6651134.356556691,71.19733145812484],[510961.8728500153,6651135.506675729,71.96326486012484],[510962.34001696133,6651132.900058372,70.29716930812484],[510962.01435568935,6651134.717126833,71.49477392812484],[510961.94524082966,6651135.102761977,71.75098705112484],[510961.6629673583,6651136.67774269,72.93517021012485],[510962.3040266128,6651133.100871096,70.63691433512486],[510962.2632206515,6651133.328553145,70.96258144512484],[510961.7478048776,6651136.204380968,72.84600555812486],[510962.21787369426,6651133.581572256,71.27095025312484],[510961.81176207983,6651135.84752363,72.74691006412483],[510961.87540384487,6651135.492426311,72.61928730512484],[510962.1683480363,6651133.857906959,71.55904860412484],[510961.9381540214,6651135.142303725,72.46279601312484],[510962.1150842929,6651134.155098786,71.82424632912483],[510961.99941586785,6651134.800485467,72.27758711112486],[510962.05858841364,6651134.470324727,72.06433477612484],[510969.3869890279,6651147.170132206,65.74349841073101],[510969.49764014105,6651146.5706574535,65.74349841073101],[510969.49764014105,6651146.5706574535,65.87349841073102],[510969.3869890279,6651147.170132206,67.57230206973101],[510969.4976397165,6651146.570659755,67.572302070731],[510969.3907935758,6651147.149520299,68.037892756731],[510969.4984647809,6651146.5661898,67.776123354731],[510969.40269090433,6651147.08506412,68.51516370873101],[510969.5053156356,6651146.529073913,68.192702642731],[510969.5195961883,6651146.451706133,68.61702976273101],[510969.423294638,6651146.973439231,68.99806472873101],[510969.4447228476,6651146.857347578,69.35977071373101],[510969.54176868155,6651146.331582173,69.043340113731],[510969.4713799989,6651146.712927077,69.71752855973101],[510969.57210233784,6651146.167243464,69.465148972731],[510969.5032692763,6651146.540160476,70.06798477473102],[510969.61063371715,6651145.958491934,69.87549851573102],[510969.5403003671,6651146.339537064,70.40772980173101],[510969.657139968,6651145.70653493,70.267278209731],[510969.5822863248,6651146.112069658,70.733396911731],[510969.6969675741,6651145.490760829,70.544760069731],[510969.62894459174,6651145.859289073,71.041765719731],[510969.7407069216,6651145.253794081,70.805200742731],[510969.67990239593,6651145.583214878,71.329864070731],[510969.78798053163,6651144.99767975,71.046170388731],[510969.7347063807,6651145.286303224,71.595061795731],[510969.83834735455,6651144.724807316,71.26558939473101],[510969.7928359659,6651144.971374456,71.835150242731],[510969.90946082654,6651144.339535721,71.521802517731],[510969.8537196195,6651144.641524966,72.04840257773101],[510969.98394498473,6651143.93600275,71.734080326731],[510969.91675299057,6651144.300028948,72.23361147973101],[510970.06050916837,6651143.521200823,71.90119508373101],[510971.7121088866,6651134.573325796,65.74349841073101],[510971.7121088866,6651134.573325796,65.87349841073102],[510969.98131773015,6651143.950236432,72.39010277173101],[510970.13789043564,6651143.1019721795,72.023348205731],[510971.8227599998,6651133.973851045,65.74349841073101],[510970.0467998406,6651143.595473875,72.51772553073101],[510970.2149117187,6651142.684693824,72.10202289873101],[510970.1126065097,6651143.238952954,72.61682102473101],[510970.2905266624,6651142.275034595,72.139765757731],[510970.1998972974,6651142.766037483,72.705985676731],[510970.2855942337,6651142.301757024,72.748760917731],[510971.7121088866,6651134.573325796,67.57230206973101],[510971.70875193266,6651134.591512773,67.983117381731],[510971.8227599998,6651133.973851045,67.57230206973101],[510970.6015725631,6651140.58988061,72.139765757731],[510971.69825428975,6651134.648385874,68.404238809731],[510971.8189554519,6651133.994462951,68.037892756731],[510971.6800745247,6651134.746878422,68.83032794473101],[510971.80705812335,6651134.058919131,68.51516370873101],[510971.6538413666,6651134.889001855,69.255234448731],[510970.91922194045,6651138.868950957,72.139765757731],[510971.78645438957,6651134.170544021,68.99806472873101],[510971.6193976439,6651135.075607677,69.672201150731],[510970.99483688414,6651138.459291728,72.10202289873101],[510971.7650261801,6651134.286635673,69.35977071373101],[510971.5768341755,6651135.306203864,70.074150067731],[510971.0718581673,6651138.042013371,72.023348205731],[510971.52650812076,6651135.57885543,70.45403086973101],[510971.14923943457,6651137.622784729,71.90119508373101],[510970.92415479396,6651138.842226227,72.748760917731],[510971.7383690288,6651134.431056174,69.71752855973101],[510971.48403422546,6651135.808966334,70.720437184731],[510971.22580361826,6651137.207982802,71.734080326731],[510971.4378925809,6651136.058948012,70.96814692473102],[510971.3002877764,6651136.804449832,71.521802517731],[510971.3714012484,6651136.419178236,71.26558939473101],[510971.70647975145,6651134.603822773,70.06798477473102],[510971.00985173025,6651138.377945767,72.705985676731],[510971.6694486605,6651134.804446187,70.40772980173101],[510971.097142518,6651137.905030296,72.61682102473101],[510971.1915795272,6651147.504162954,65.69803378696157],[510971.62746270286,6651135.0319135925,70.733396911731],[510971.1629491871,6651137.548509375,72.51772553073101],[510971.5808044358,6651135.284694177,71.041765719731],[510971.2284312975,6651137.193746817,72.39010277173101],[510971.52984663175,6651135.560768371,71.329864070731],[510971.2929960371,6651136.843954301,72.23361147973101],[510971.4750426469,6651135.857680027,71.595061795731],[510971.3560294081,6651136.502458286,72.04840257773101],[510971.41691306175,6651136.172608795,71.835150242731],[510971.3028339894,6651146.904799883,65.69803378696157],[510971.3028339894,6651146.904799883,65.82803378696157],[510971.1915795272,6651147.504162954,67.52683744596158],[510971.3028335625,6651146.904802183,67.52683744696157],[510971.1954048202,6651147.483554888,67.99242813296156],[510971.30366312584,6651146.900333062,67.73065873096157],[510971.2073670216,6651147.419110715,68.46969908496158],[510971.3105513363,6651146.863224088,68.14723801896157],[510971.3249097568,6651146.785870722,68.57156513896157],[510971.2280831015,6651147.307506622,68.95260010496158],[510971.249628153,6651147.191436598,69.31430608996158],[510971.3472031503,6651146.66576914,68.99787548996159],[510971.2764306582,6651147.047043002,69.67206393596157],[510971.3777022074,6651146.501461048,69.41968434896158],[510971.3084938187,6651146.874308587,70.02252015096157],[510971.41644368746,6651146.292748408,69.83003389196158],[510971.34572682955,6651146.673722549,70.36226517796158],[510971.46320352366,6651146.04083834,70.22181358596158],[510971.3879417248,6651146.44629752,70.68793228796157],[510971.50324829837,6651145.825104439,70.49929544596156],[510971.434854406,6651146.193564028,70.99630109596157],[510971.54722614406,6651145.588181837,70.75973611896157],[510971.48609006853,6651145.917541265,71.28439944696157],[510971.5947575237,6651145.33211522,71.00070576496157],[510971.5411928839,6651145.620684923,71.54959717196157],[510971.64539898257,6651145.05929362,71.22012477096158],[510971.5996394333,6651145.305814825,71.78968561896157],[510971.716900216,6651144.6740938,71.47633789396157],[510971.6608550681,6651144.976026786,72.00293795396159],[510971.7917905152,6651144.270636006,71.68861570296157],[510971.7242321422,6651144.634594389,72.18814685596158],[510971.8687721816,6651143.855911355,71.85573045996156],[510973.5293776037,6651134.90970329,65.69803378696157],[510971.78914893494,6651144.284867037,72.34463814796158],[510973.5293776037,6651134.90970329,65.82803378696157],[510971.94657538686,6651143.436760813,71.97788358196158],[510973.640632066,6651134.310340218,65.69803378696157],[510971.85498810076,6651143.9301705705,72.47226090696157],[510972.02401664515,6651143.019560195,72.05655827496157],[510971.9211535949,6651143.573716069,72.57135640096159],[510972.10004389565,6651142.609977284,72.09430113396157],[510972.0089203545,6651143.1008887,72.66052105296158],[510972.09508457186,6651142.636694735,72.70329629396157],[510973.5293776037,6651134.90970329,67.52683744596158],[510972.4127858412,6651140.925137239,72.09430113396157],[510973.5260023452,6651134.927886878,67.93765275796157],[510973.640632066,6651134.310340218,67.52683744596158],[510973.5154474616,6651134.984749384,68.35877418596156],[510973.63680677285,6651134.330948285,67.99242813296156],[510973.4971685675,6651135.083223583,68.78486332096156],[510973.62484457163,6651134.395392457,68.46969908496158],[510973.4707923675,6651135.225320538,69.20976982496158],[510972.7321672704,6651139.204528188,72.09430113396157],[510973.6041284916,6651134.5069965515,68.95260010496158],[510973.436160833,6651135.411891597,69.62673652696157],[510972.8081945209,6651138.794945278,72.05655827496157],[510973.5825834401,6651134.623066576,69.31430608996158],[510973.3933652781,6651135.642444826,70.02868544396156],[510972.88563577924,6651138.37774466,71.97788358196158],[510973.3427648097,6651135.915045596,70.40856624596157],[510972.73712702125,6651139.1778084375,72.70329629396157],[510972.9634389844,6651137.958594119,71.85573045996156],[510973.5557809349,6651134.767460172,69.67206393596157],[510973.3000593163,6651136.145113632,70.67497256096158],[510973.0404206509,6651137.5438694665,71.68861570296157],[510973.2536660745,6651136.39504874,70.92268230096157],[510973.11531095003,6651137.140411674,71.47633789396157],[510973.1868121835,6651136.7552118525,71.22012477096158],[510973.5237177744,6651134.940194585,70.02252015096157],[510972.82329123863,6651138.713614472,72.66052105296158],[510973.48648476356,6651135.140780623,70.36226517796158],[510972.9110579982,6651138.240787105,72.57135640096159],[510973.4442698683,6651135.368205653,70.68793228796157],[510972.97722349246,6651137.884332602,72.47226090696157],[510973.3973571871,6651135.620939145,70.99630109596157],[510973.04306265817,6651137.529636135,72.34463814796158],[510973.3461215246,6651135.896961908,71.28439944696157],[510973.107979451,6651137.179908785,72.18814685596158],[510973.2910187092,6651136.19381825,71.54959717196157],[510973.171356525,6651136.838476388,72.00293795396159],[510973.2325721599,6651136.508688348,71.78968561896157],[510976.5812709479,6651148.512989643,65.56030910294606],[510976.69432740635,6651147.913963863,65.56030910294606],[510976.69432740635,6651147.913963863,65.69030910294606],[510976.5812709479,6651148.512989643,67.38911276194607],[510976.69432697253,6651147.913966162,67.38911276294606],[510976.58515819954,6651148.492393172,67.85470344894605],[510976.69516997243,6651147.909499556,67.59293404694606],[510976.59731415333,6651148.427985267,68.33197440094607],[510976.7021697517,6651147.872411465,68.00951333494606],[510976.7167607365,6651147.7951016305,68.43384045494606],[510976.6183657731,6651148.316443979,68.81487542094607],[510976.6402597913,6651148.200439272,69.17658140594607],[510976.7394152177,6651147.675067636,68.86015080594608],[510976.6674964185,6651148.056126935,69.53433925194607],[510976.7704082701,6651147.510852007,69.28195966494606],[510976.7000789083,6651147.883489726,69.88479546694606],[510976.8097772486,6651147.302256822,69.69230920794607],[510976.7379149848,6651147.683016569,70.22454049394607],[510976.8572944571,6651147.050488518,70.08408890194607],[510976.78081363766,6651147.455719523,70.55020760394606],[510976.8979878398,6651146.8348760195,70.36157076194606],[510976.8284861669,6651147.203128258,70.85857641194606],[510976.9426779977,6651146.598086746,70.62201143494606],[510976.880551697,6651146.927260826,71.14667476294606],[510976.99097924645,6651146.342164231,70.86298108094606],[510976.93654701643,6651146.63057154,71.41187248794606],[510977.0424409485,6651146.069496163,71.08240008694607],[510976.9959402286,6651146.315878637,71.65196093494606],[510977.11510029243,6651145.684513113,71.33861320994606],[510977.05814737733,6651145.986276187,71.86521326994608],[510977.191203595,6651145.281282366,71.55089101894606],[510977.1225509743,6651145.64503593,72.05042217194607],[510977.26943213877,6651144.866791102,71.71800577594607],[510977.1885192289,6651145.295505389,72.20691346394608],[510978.95693450235,6651135.925617528,65.56030910294606],[510978.95693450235,6651135.925617528,65.69030910294606],[510977.348495528,6651144.447876438,71.84015889794605],[510977.25542479614,6651144.941008529,72.33453622294607],[510979.0699909608,6651135.326591749,65.56030910294606],[510977.42719110777,6651144.030910599,71.91883359094606],[510977.3226619775,6651144.584754623,72.43363171694607],[510977.50444977684,6651143.621558183,71.95657644994606],[510977.4118503014,6651144.112193339,72.52279636894608],[510977.49941012653,6651143.648260597,72.56557160994606],[510978.95693450235,6651135.925617528,67.38911276194607],[510977.82225722546,6651141.937666283,71.95657644994606],[510978.9535045745,6651135.943790884,67.79992807394606],[510979.0699909608,6651135.326591749,67.38911276194607],[510978.9427787328,6651136.00062139,68.22104950194606],[510979.06610370916,6651135.347188219,67.85470344894605],[510978.9242037741,6651136.099040172,68.64713863694608],[510979.05394775525,6651135.411596125,68.33197440094607],[510978.897400357,6651136.241057161,69.07204514094606],[510978.1468116978,6651140.218025507,71.95657644994606],[510979.0328961355,6651135.523137413,68.81487542094607],[510978.8622078931,6651136.427523228,69.48901184294606],[510978.224070367,6651139.808673091,71.91883359094606],[510978.3027659467,6651139.391707253,71.84015889794605],[510978.8187191755,6651136.657946712,69.89096075994605],[510979.01100211736,6651135.639142118,69.17658140594607],[510978.15185178217,6651140.191320795,72.56557160994606],[510978.3818293359,6651138.972792588,71.71800577594607],[510978.7672991279,6651136.930394076,70.27084156194606],[510978.98376549006,6651135.783454456,69.53433925194607],[510978.7239019306,6651137.160332642,70.53724787694605],[510978.4600578797,6651138.558301324,71.55089101894606],[510978.67675725423,6651137.410127097,70.78495761694606],[510978.5361611822,6651138.155070577,71.33861320994606],[510978.60882052616,6651137.770087529,71.08240008694607],[510978.2394116074,6651139.727388053,72.52279636894608],[510978.9511830004,6651135.956091666,69.88479546694606],[510978.32859993115,6651139.254826769,72.43363171694607],[510978.91334692383,6651136.156564822,70.22454049394607],[510978.39583711256,6651138.898572863,72.33453622294607],[510978.870448271,6651136.383861868,70.55020760394606],[510978.4627426798,6651138.544076003,72.20691346394608],[510978.8227757418,6651136.636453134,70.85857641194606],[510978.5287109344,6651138.194545461,72.05042217194607],[510978.7707102118,6651136.9123205645,71.14667476294606],[510978.59311453137,6651137.853305205,71.86521326994608],[510978.7147148922,6651137.20900985,71.41187248794606],[510978.65532168,6651137.523702754,71.65196093494606],[510987.9845994391,6651150.702811534,65.25932373606133],[510988.1014685009,6651150.104517902,65.25932373606133],[510988.1014685009,6651150.104517902,65.38932373606133],[510987.9845994391,6651150.702811534,67.08812739506133],[510988.1014680524,6651150.104520198,67.08812739606134],[510987.9886177805,6651150.6822402375,67.55371808206134],[510988.1023394807,6651150.100059051,67.29194868006132],[510988.00118366966,6651150.617911053,68.03098903406134],[510988.1095753136,6651150.06301629,67.70852796806133],[510988.02294521325,6651150.506506095,68.51389005406133],[510988.1246583503,6651149.985800946,68.13285508806135],[510988.0455775635,6651150.390643174,68.87559603906134],[510988.14807680855,6651149.865913662,68.55916543906133],[510988.0737326916,6651150.246507218,69.23335388506133],[510988.18011503987,6651149.701898743,68.98097429806133],[510988.1074139608,6651150.074081012,69.58381010006133],[510988.2208116584,6651149.493558507,69.39132384106134],[510988.14652598335,6651149.873852879,69.92355512706133],[510988.26993129,6651149.242097922,69.78310353506133],[510988.19087130757,6651149.646833643,70.24922223706135],[510988.31199697574,6651149.026748953,70.06058539506134],[510988.2401514976,6651149.394551103,70.55759104506133],[510988.35819422,6651148.790249091,70.32102606806134],[510988.29397283384,6651149.119020846,70.84568939606133],[510988.4081243318,6651148.5346393725,70.56199571406133],[510988.35185648367,6651148.822694182,71.11088712106134],[510988.4613214771,6651148.262304568,70.78141472006135],[510988.4132526133,6651148.508385905,71.35097556806134],[510988.5364311122,6651147.877792056,71.03762784306134],[510988.4775575738,6651148.179186306,71.56422790306134],[510989.13496955147,6651150.927905647,65.22823515455318],[510988.6151008467,6651147.47505415,71.24990565206133],[510988.5441330535,6651147.838363124,71.74943680506134],[510989.25222322944,6651150.329687274,65.22823515455318],[510988.69596749195,6651147.061069489,71.41702040906135],[510989.25222322944,6651150.329687274,65.35823515455317],[510988.6123259557,6651147.489259789,71.90592809706133],[510988.77769713604,6651146.642666837,71.53917353106132],[510988.68148777966,6651147.135196205,72.03355085606132],[510990.44037750276,6651138.130824095,65.25932373606133],[510990.44037750276,6651138.130824095,65.38932373606133],[510988.859046567,6651146.226210627,71.61784822406133],[510988.7509924007,6651146.779377723,72.13264635006134],[510990.5572465645,6651137.532530463,65.25932373606133],[510988.93891063053,6651145.817358532,71.65559108306132],[510989.13496955147,6651150.927905647,67.05703881355318],[510988.8431884226,6651146.307394018,72.22181100206133],[510988.93370102806,6651145.844028312,72.26458624306133],[510989.25222277956,6651150.329689568,67.05703881455317],[510989.13900111726,6651150.907336939,67.52262950055317],[510989.2530970758,6651150.325228983,67.26086009855317],[510989.1516083608,6651150.843015845,67.99990045255318],[510989.2603567217,6651150.288190882,67.67743938655317],[510989.26743550063,6651144.135524738,71.65559108306132],[510990.44037750276,6651138.130824095,67.08812739506133],[510990.4368319075,6651138.148975237,67.49894270706135],[510989.1734415216,6651150.7316249,68.48280147255318],[510989.2754893967,6651150.210985251,68.10176650655318],[510990.5572465645,6651137.532530463,67.08812739506133],[510990.4257443581,6651138.205736283,67.92006413506132],[510989.1961483549,6651150.615776552,68.84450745755318],[510990.55322822306,6651137.5531017585,67.55371808206134],[510989.2989849252,6651150.091113046,68.52807685755319],[510990.40654299606,6651138.304034777,68.34615327006134],[510989.60293492454,6651142.417985761,71.65559108306132],[510989.22439614165,6651150.471658727,69.20226530355318],[510990.5406623339,6651137.617430944,68.03098903406134],[510990.3788356872,6651138.445878189,68.77105977406133],[510989.33112859423,6651149.927118758,68.94988571655317],[510989.682798988,6651142.009133668,71.61784822406133],[510990.3424564278,6651138.632116351,69.18802647606132],[510990.5189007903,6651137.728835903,68.51389005406133],[510989.764148419,6651141.592677458,71.53917353106132],[510989.25818825583,6651150.299254212,69.55272151855317],[510989.6081449755,6651142.391313687,72.26458624306133],[510990.29750114004,6651138.862258202,69.58997539306134],[510989.8458780631,6651141.174274803,71.41702040906135],[510990.4962684401,6651137.844698825,68.87559603906134],[510989.3719591455,6651149.71880473,69.36023525955318],[510990.24434705405,6651139.134372573,69.96985619506133],[510989.92674470827,6651140.760290142,71.24990565206133],[510990.199486373,6651139.3640301,70.23626251006132],[510989.69865758106,6651141.9279479785,72.22181100206133],[510990.00541444274,6651140.357552237,71.03762784306134],[510990.468113312,6651137.988834779,69.23335388506133],[510990.15075183654,6651139.61351925,70.48397225006133],[510990.08052407793,6651139.973039726,70.78141472006135],[510989.2974289962,6651150.099051264,69.89246654555318],[510990.4344320428,6651138.161260985,69.58381010006133],[510989.7908536029,6651141.455964274,72.13264635006134],[510989.4212404298,6651149.467375776,69.75201495355319],[510990.3953200202,6651138.361489118,69.92355512706133],[510989.86035822396,6651141.100145792,72.03355085606132],[510989.3419202609,6651149.872060586,70.21813365555317],[510990.350974696,6651138.588508354,70.24922223706135],[510989.92952004797,6651140.746082208,71.90592809706133],[510989.99771295016,6651140.396978874,71.74943680506134],[510990.301694506,6651138.840790896,70.55759104506133],[510990.06428842974,6651140.056155692,71.56422790306134],[510990.24787316984,6651139.116321152,70.84568939606133],[510990.1285933904,6651139.726956091,71.35097556806134],[510990.18998952,6651139.4126478145,71.11088712106134],[510989.4634445538,6651149.252053895,70.02949681355317],[510989.3913626321,6651149.619809779,70.52650246355317],[510989.5097938332,6651149.0155837815,70.28993748655317],[510989.4453610943,6651149.344314179,70.81460081455317],[510989.55988826504,6651148.760006216,70.53090713255317],[510989.5034352393,6651149.04802479,71.07979853955317],[510989.61326048215,6651148.487705667,70.75032613855318],[510989.56503342366,6651148.7337560505,71.31988698655317],[510989.6886173032,6651148.103241523,71.00653926155317],[510989.62955001194,6651148.40459786,71.5331393215532],[510989.76754593983,6651147.700554278,71.21881707055317],[510989.69634459156,6651148.0638175495,71.71834822355318],[510989.8486787173,6651147.286621691,71.38593182755318],[510989.76476191665,6651147.714758128,71.87483951555319],[510989.9306773337,6651146.868271667,71.50808494955317],[510989.83415135223,6651147.360739081,72.00246227455318],[510991.5988295832,6651138.357499615,65.22823515455318],[510990.01229448576,6651146.451867842,71.58675964255318],[510991.5988295832,6651138.357499615,65.35823515455317],[510989.903884713,6651147.0049653575,72.10155776855318],[510991.7160832611,6651137.75928124,65.22823515455318],[510990.09242138197,6651146.043067177,71.62450250155317],[510989.99638415215,6651146.533041022,72.19072242055319],[510990.0871946348,6651146.069733602,72.23349766155317],[510990.4220274278,6651144.361444937,71.62450250155317],[510991.5988295832,6651138.357499615,67.05703881355318],[510991.59527231933,6651138.375648474,67.46785412555317],[510991.7160832611,6651137.75928124,67.05703881355318],[510991.5841482809,6651138.43240238,67.88897555355317],[510991.7120516954,6651137.77984995,67.52262950055317],[510991.5648837271,6651138.530688509,68.31506468855319],[510990.7586309806,6651142.644122006,71.62450250155317],[510991.69944445184,6651137.844171043,67.99990045255318],[510991.53708523355,6651138.672514077,68.73997119255317],[510990.83875787683,6651142.235321341,71.58675964255318],[510991.50058624987,6651138.858728814,69.15693789455317],[510991.67761129106,6651137.955561988,68.48280147255318],[510990.9203750289,6651141.818917517,71.50808494955317],[510990.763858178,6651142.617453287,72.23349766155317],[510991.45548301435,6651139.088841717,69.55888681155317],[510991.00237364526,6651141.400567493,71.38593182755318],[510991.6549044578,6651138.071410335,68.84450745755318],[510991.40215399803,6651139.360921859,69.93876761355317],[510991.08350642276,6651140.986634906,71.21881707055317],[510991.35714568046,6651139.590550498,70.20517392855317],[510990.8546686605,6651142.154145865,72.19072242055319],[510991.1624350594,6651140.583947662,71.00653926155317],[510991.30825075856,6651139.840008264,70.45288366855317],[510991.626656671,6651138.215528159,69.20226530355318],[510991.23779188044,6651140.199483517,70.75032613855318],[510991.5928645568,6651138.387932676,69.55272151855317],[510990.94716809964,6651141.68222153,72.10155776855318],[510991.01690146036,6651141.326447805,72.00246227455318],[510991.5536238165,6651138.588135622,69.89246654555318],[510991.08629089594,6651140.97242876,71.87483951555319],[510991.5091325518,6651138.815126302,70.21813365555317],[510991.1547082211,6651140.623369339,71.71834822355318],[510991.4596901806,6651139.067377109,70.52650246355317],[510991.2215028007,6651140.282589028,71.5331393215532],[510991.40569171833,6651139.342872708,70.81460081455317],[510991.286019389,6651139.953430836,71.31988698655317],[510991.3476175734,6651139.639162097,71.07979853955317],[510993.04821306746,6651151.699365826,65.12148315381185],[510993.1667751042,6651151.101405384,65.12148315381185],[510993.1667751042,6651151.101405384,65.25148315381185],[510993.04821306746,6651151.699365826,66.95028681281185],[510993.16677464935,6651151.101407679,66.95028681381184],[510993.0522896189,6651151.6788059855,67.41587749981184],[510993.16765870125,6651151.096949016,67.15410809781184],[510993.06503753865,6651151.614512626,67.89314845181185],[510993.17499935295,6651151.059926884,67.57068738581185],[510993.0871143217,6651151.503169709,68.37604947181185],[510993.1903008838,6651150.982754541,67.99501450581185],[510993.11007452605,6651151.387371312,68.73775545681185],[510993.2140585838,6651150.862934021,68.42132485681186],[510993.13863751176,6651151.243315625,69.09551330281185],[510993.2465609235,6651150.699010443,68.84313371581186],[510993.1728066905,6651151.070985444,69.44596951781185],[510993.28784707683,6651150.490786231,69.25348325881185],[510993.2124852932,6651150.870868818,69.78571454481185],[510993.3376782594,6651150.239465684,69.64526295281186],[510993.2574730075,6651150.6439760085,70.11138165481185],[510993.38035331224,6651150.024236643,69.92274481281184],[510993.30746707454,6651150.391833963,70.41975046281185],[510993.4272197735,6651149.787868488,70.18318548581185],[510993.36206807103,6651150.116457149,70.70784881381185],[510993.47787317715,6651149.532401118,70.42415513181184],[510993.4207902283,6651149.820295509,70.97304653881184],[510993.5318409407,6651149.260217975,70.64357413781185],[510993.4830757473,6651149.506162272,71.21313498581185],[510993.6080386203,6651148.875919599,70.89978726081185],[510993.5483122349,6651149.177146002,71.42638732081187],[510993.6878479711,6651148.473405978,71.11206506981185],[510993.61585213256,6651148.836512624,71.61159622281185],[510993.7698860573,6651148.059651865,71.27917982681186],[510993.6850328828,6651148.487603704,71.76808751481185],[510993.85279964394,6651147.641482219,71.40133294881184],[510993.75519659073,6651148.133737299,71.89571027381184],[510993.93532750953,6651147.225257933,71.48000764181185],[510995.53956573736,6651139.134379716,65.12148315381185],[510993.82570806146,6651147.778116973,71.99480576781185],[510995.53956573736,6651139.134379716,65.25148315381185],[510994.01634849055,6651146.816633529,71.51775050081184],[510995.6581277741,6651138.536419273,65.12148315381185],[510993.91923964274,6651147.306396114,72.08397041981186],[510994.0110634214,6651146.843288455,72.12674566081185],[510994.3496323994,6651145.135736346,71.51775050081184],[510995.53956573736,6651139.134379716,66.95028681281185],[510995.5359687803,6651139.152520751,67.36110212481185],[510995.6581277741,6651138.536419273,66.95028681281185],[510995.52472061577,6651139.209250186,67.78222355281184],[510995.65405122266,6651138.556979113,67.41587749981184],[510995.5052411012,6651139.307493936,68.20831268781185],[510994.68999189587,6651143.419153865,71.51775050081184],[510995.64130330295,6651138.621272473,67.89314845181185],[510995.4771324219,6651139.449258356,68.63321919181186],[510994.77101287694,6651143.01052946,71.48000764181185],[510995.4402261694,6651139.635392802,69.05018589381184],[510994.85354074254,6651142.594305174,71.40133294881184],[510995.6192265198,6651138.732615391,68.37604947181185],[510994.69527742016,6651143.3924966445,72.12674566081185],[510995.39461965574,6651139.865406488,69.45213481081184],[510994.93645432906,6651142.176135529,71.27917982681186],[510995.5962663155,6651138.848413788,68.73775545681185],[510995.34069557517,6651140.13736932,69.83201561281184],[510995.0184924154,6651141.762381416,71.11206506981185],[510994.7871011988,6651142.929388984,72.08397041981186],[510995.29518503847,6651140.36689895,70.09842192781186],[510995.09830176615,6651141.359867796,70.89978726081185],[510995.2457445295,6651140.61624916,70.34613166781185],[510995.17449944577,6651140.975569419,70.64357413781185],[510995.5677033298,6651138.992469475,69.09551330281185],[510994.88063278,6651142.457668127,71.99480576781185],[510995.533534151,6651139.164799656,69.44596951781185],[510994.9511442508,6651142.102047801,71.89571027381184],[510995.4938555483,6651139.364916282,69.78571454481185],[510995.0213079587,6651141.748181393,71.76808751481185],[510995.4488678341,6651139.591809091,70.11138165481185],[510995.090488709,6651141.399272475,71.61159622281185],[510995.3988737671,6651139.843951136,70.41975046281185],[510995.1580286066,6651141.058639097,71.42638732081187],[510995.3442727705,6651140.11932795,70.70784881381185],[510995.2232650942,6651140.729622828,71.21313498581185],[510995.2855506133,6651140.41548959,70.97304653881184],[511004.74689144985,6651154.058766993,64.79313440574904],[511004.8693648376,6651153.461595396,64.79313440574904],[511004.8693648376,6651153.461595396,64.92313440574902],[511004.74689144985,6651154.058766993,66.62193806474903],[511004.75110248633,6651154.038234276,67.08752875174902],[511004.8693643676,6651153.461597687,66.62193806574902],[511004.8702775843,6651153.457144906,66.82575934974902],[511004.7642709587,6651153.974025734,67.56479970374905],[511004.87786040345,6651153.420171615,67.24233863774903],[511004.787076053,6651153.862829702,68.04770072374903],[511004.89366673044,6651153.34310108,67.66666575774903],[511004.81079371244,6651153.747184069,68.40940670874903],[511004.91820819484,6651153.22343863,68.09297610874903],[511004.84029898845,6651153.603318425,68.76716455474903],[511004.9517827839,6651153.059731303,68.51478496774902],[511004.8755954053,6651153.431215585,69.11762076974902],[511004.99443096365,6651152.851781787,68.92513451074903],[511004.91658300156,6651153.231362958,69.45736579674903],[511005.0459060724,6651152.600792789,69.31691420474903],[511004.9630548565,6651153.004769472,69.78303290674903],[511005.08998897136,6651152.385847684,69.59439606474902],[511005.0146982233,6651152.752960061,70.09140171474903],[511005.1384015531,6651152.149791351,69.85483673774903],[511005.07110050175,6651152.47794653,70.37950006574903],[511005.190726008,6651151.894661001,70.09580638374902],[511005.13175989775,6651152.182175594,70.64469779074902],[511005.2464741632,6651151.622836931,70.31522538974903],[511005.1961002104,6651151.868456769,70.88478623774903],[511005.32518559747,6651151.239045531,70.57143851274903],[511005.2634888439,6651151.539874546,71.09803857274903],[511005.4076278515,6651150.837062916,70.78371632174904],[511005.3332568767,6651151.199690541,71.28324747474905],[511005.49237236683,6651150.423854638,70.95083107874902],[511005.40471989376,6651150.851241913,71.43973876674903],[511005.57802126516,6651150.006236652,71.07298420074903],[511005.4771982961,6651150.497842337,71.56736152574902],[511005.66327171767,6651149.590561462,71.15165889374903],[511005.5500359339,6651150.142691153,71.66645701974903],[511005.74696557363,6651149.182476124,71.18940175274902],[511007.3204336206,6651141.510356942,64.79313440574904],[511007.3204336206,6651141.510356942,64.92313440574902],[511005.6466531136,6651149.6715926025,71.75562167174903],[511007.4429070083,6651140.913185345,64.79313440574904],[511005.74150615046,6651149.209095887,71.79839691274903],[511006.09124448866,6651147.503796426,71.18940175274902],[511007.3204336206,6651141.510356942,66.62193806474903],[511007.31671800016,6651141.528474045,67.03275337674903],[511007.4429070083,6651140.913185345,66.62193806474903],[511007.30509875977,6651141.585128642,67.45387480474903],[511007.4386959718,6651140.933718062,67.08752875174902],[511006.44283241435,6651145.789478505,71.18940175274902],[511007.2849766177,6651141.683242787,67.87996393974902],[511006.5265262703,6651145.381393168,71.15165889374903],[511007.4255274994,6651140.997926604,67.56479970374905],[511007.25594063563,6651141.824820186,68.30487044374902],[511006.6117767228,6651144.965717978,71.07298420074903],[511006.4482923077,6651145.762856451,71.79839691274903],[511007.21781684924,6651142.010709079,68.72183714574903],[511007.4027224051,6651141.109122635,68.04770072374903],[511006.69742562115,6651144.548099992,70.95083107874902],[511007.17070578074,6651142.240419325,69.12378606274902],[511006.5431453445,6651145.300359735,71.75562167174903],[511006.7821701364,6651144.134891714,70.78371632174904],[511007.3790047457,6651141.224768269,68.40940670874903],[511007.11500274955,6651142.512023376,69.50366686474902],[511006.8646123905,6651143.7329091,70.57143851274903],[511007.06799082446,6651142.741250206,69.77007317974902],[511006.9433238248,6651143.349117701,70.31522538974903],[511007.0169192775,6651142.990271466,70.01778291974902],[511007.3494994697,6651141.368633913,68.76716455474903],[511006.63976252417,6651144.829261185,71.66645701974903],[511006.7126001621,6651144.474110001,71.56736152574902],[511007.3142030527,6651141.540736752,69.11762076974902],[511006.78507856437,6651144.120710424,71.43973876674903],[511007.2732154565,6651141.740589378,69.45736579674903],[511006.85654158145,6651143.7722617965,71.28324747474905],[511007.22674360155,6651141.967182864,69.78303290674903],[511006.9263096141,6651143.432077792,71.09803857274903],[511007.1751002348,6651142.218992277,70.09140171474903],[511006.99369824765,6651143.103495568,70.88478623774903],[511007.1186979563,6651142.494005808,70.37950006574903],[511007.05803856044,6651142.789776742,70.64469779074902],[511008.84031986113,6651154.903174839,64.67497358985594],[511008.964161851,6651154.306285562,64.67497358985594],[511008.964161851,6651154.306285562,64.80497358985593],[511008.84031986113,6651154.903174839,66.50377724885594],[511008.8445779547,6651154.88265183,66.96936793585593],[511008.9641613757,6651154.306287853,66.50377724985593],[511008.9650847973,6651154.301837178,66.70759853385593],[511008.85789358075,6651154.818473643,67.44663888785594],[511008.9727523522,6651154.264881366,67.12417782185594],[511008.8809535148,6651154.70733018,67.92953990785594],[511008.9887353098,6651154.187847268,67.54850494185594],[511008.9049362116,6651154.59173922,68.29124589285595],[511009.0135510175,6651154.0682413895,67.97481529285594],[511008.93477119994,6651154.44794159,68.64900373885595],[511009.04750079213,6651153.904611457,68.39662415185593],[511009.4851473952,6651155.037084486,64.65620509671923],[511008.9704620434,6651154.275920116,68.99945995385593],[511009.090625552,6651153.696760253,68.80697369485594],[511009.60920497734,6651154.440239982,64.65620509671923],[511009.0119076632,6651154.07616197,69.33920498085594],[511009.60920497734,6651154.440239982,64.78620509671923],[511009.14267587924,6651153.445889912,69.19875338885593],[511009.0588988267,6651153.84967561,69.66487209085594],[511009.18725139095,6651153.231046424,69.47623524885593],[511009.1111192921,6651153.597985243,69.97324089885595],[511009.4851473952,6651155.037084486,66.48500875571924],[511009.2362049682,6651152.995101691,69.73667592185593],[511009.1681518484,6651153.323101728,70.26133924985594],[511009.4894129014,6651155.016563016,66.95059944271922],[511009.6092045014,6651154.440242271,66.48500875671922],[511009.2891141325,6651152.740091956,69.97764556785593],[511009.61012953054,6651154.435791931,66.68883004071922],[511009.2294890943,6651153.027470623,70.52653697485593],[511009.50275170815,6651154.952389644,67.42787039471925],[511009.34548525605,6651152.468396394,70.19706457385594],[511009.6178104335,6651154.398838891,67.10540932871923],[511009.29454839,6651152.7139001135,70.76662542185593],[511009.52585178654,6651154.841254518,67.91077141471924],[511009.4250762661,6651152.084786436,70.45327769685593],[511009.63382121536,6651154.321810571,67.52973644871923],[511009.36269007064,6651152.385473231,70.97987775685594],[511009.5498762341,6651154.725672228,68.27247739971924],[511009.50843978673,6651151.682993863,70.66555550585593],[511009.6586801239,6651154.202213665,67.95604679971923],[511009.4332377394,6651152.045450052,71.16508665885596],[511009.5797631612,6651154.581885384,68.63023524571923],[511009.5941312957,6651151.269980936,70.83267026285594],[511009.6926890006,6651154.038596005,68.37785565871923],[511009.5054993335,6651151.697166157,71.32157795085594],[511009.6155161376,6651154.409876812,68.98069146071923],[511009.68073729385,6651150.852560385,70.95482338485594],[511009.5787876594,6651151.343933655,71.44920070985593],[511009.735888835,6651153.830760391,68.78820520171924],[511009.65703390876,6651154.210133651,69.32043648771923],[511009.76694039366,6651150.437081708,71.03349807785594],[511009.65243923524,6651150.988950375,71.54829620385594],[511009.7880297749,6651153.579908868,69.17998489571923],[511009.8515695024,6651150.0291893,71.07124093685593],[511009.7041068776,6651153.98366428,69.64610359771923],[511009.7501360818,6651150.518074541,71.63746085585593],[511011.44262056565,6651142.360697208,64.67497358985594],[511011.44262056565,6651142.360697208,64.80497358985593],[511009.8326828866,6651153.365081496,69.45746675571922],[511009.84604907193,6651150.055796476,71.68023609685595],[511009.75641825184,6651153.731992792,69.95447240571923],[511011.56646255543,6651141.763807931,64.67497358985594],[511009.8817216855,6651153.12915446,69.71790742871923],[511009.81355009443,6651153.457129896,70.24257075671923],[511009.9347229577,6651152.874163853,69.95887707471923],[511010.1996956273,6651148.351303216,71.07124093685593],[511009.87499412015,6651153.161520965,70.50776848171922],[511009.9911922158,6651152.60248867,70.17829608071924],[511011.44262056565,6651142.360697208,66.50377724885594],[511009.9401666756,6651152.847973974,70.74785692871923],[511010.0709217833,6651152.218907485,70.43450920371923],[511011.4388634244,6651142.378805746,66.91459256085594],[511011.56646255543,6651141.763807931,66.50377724885594],[511010.0084269817,6651152.519571727,70.96110926371924],[511011.42711434263,6651142.435433558,67.33571398885593],[511010.5552124388,6651146.637795762,71.07124093685593],[511010.1544304288,6651151.817145051,70.64678701271924],[511011.5622044619,6651141.784330942,66.96936793585593],[511011.40676734183,6651142.533501318,67.76180312385594],[511010.0790974647,6651152.179574053,71.14631816571925],[511010.6398415475,6651146.229903353,71.03349807785594],[511011.54888883594,6651141.848509127,67.44663888785594],[511011.3774068917,6651142.675011787,68.18670962785593],[511010.2402711152,6651151.404163103,70.81390176971922],[511010.72604464745,6651145.814424677,70.95482338485594],[511010.5607333447,6651146.611186294,71.68023609685595],[511010.15148485656,6651151.831316282,71.30280945771923],[511011.33885708393,6651142.860812798,68.60367632985593],[511010.81265064556,6651145.397004127,70.83267026285594],[511011.5258289018,6651141.959652589,67.92953990785594],[511011.2912195638,6651143.090414445,69.00562524685593],[511010.65664633474,6651146.1489082305,71.63746085585593],[511010.89834215445,6651144.983991197,70.66555550585593],[511010.327027883,6651150.986773862,70.93605489171924],[511010.22490076773,6651151.478110275,71.43043221671923],[511011.23489406856,6651143.361890092,69.38550604885593],[511011.501846205,6651142.075243549,68.29124589285595],[511010.9817056751,6651144.582198625,70.45327769685593],[511011.18735679984,6651143.5910085505,69.65191236385593],[511011.06129668525,6651144.198588668,70.19706457385594],[511011.13571454416,6651143.839912082,69.89962210385593],[511010.75434318144,6651145.678032395,71.54829620385594],[511011.4720112167,6651142.21904118,68.64900373885595],[511010.413381051,6651150.571326349,71.01472958471923],[511010.8279947572,6651145.323049115,71.44920070985593],[511010.29868056107,6651151.12315362,71.52952771071924],[511011.43632037326,6651142.3910626555,68.99945995385593],[511010.9012830832,6651144.969816613,71.32157795085594],[511011.39487475343,6651142.590820799,69.33920498085594],[511010.9735446772,6651144.621532718,71.16508665885596],[511011.34788358986,6651142.81730716,69.66487209085594],[511010.4981574877,6651150.163464535,71.05247244371922],[511011.04409234604,6651144.281509538,70.97987775685594],[511011.2956631246,6651143.068997527,69.97324089885595],[511011.11223402654,6651143.953082658,70.76662542185593],[511011.23863056814,6651143.343881041,70.26133924985594],[511010.39654748497,6651150.652313107,71.61869236271923],[511011.1772933223,6651143.639512146,70.52653697485593],[511012.09197835956,6651142.495547644,64.65620509671923],[511012.09197835956,6651142.495547644,64.78620509671923],[511010.4926274468,6651150.190069717,71.66146760371923],[511012.21603594173,6651141.898703137,64.65620509671923],[511010.8468896539,6651148.485704308,71.05247244371922],[511012.09197835956,6651142.495547644,66.48500875571924],[511012.0882146775,6651142.5136548225,66.89582406771923],[511012.21603594173,6651141.898703137,66.48500875571924],[511012.0764451422,6651142.5702783875,67.31694549571924],[511011.203025373,6651146.772325381,71.05247244371922],[511012.21177043545,6651141.919224608,66.95059944271922],[511012.05606272,6651142.668338792,67.74303463071922],[511011.2878018097,6651146.364463567,71.01472958471923],[511012.19843162876,6651141.983397981,67.42787039471925],[511012.02665115724,6651142.809838645,68.16794113471923],[511011.37415497773,6651145.949016056,70.93605489171924],[511011.20855589,6651146.745717907,71.66146760371923],[511011.98803423933,6651142.995625719,68.58490783671924],[511011.4609117454,6651145.531626815,70.81390176971922],[511012.17533155036,6651142.094533105,67.91077141471924],[511011.94031378865,6651143.225210145,68.98685675371922],[511011.3046358519,6651146.283474518,71.61869236271923],[511011.5467524319,6651145.118644866,70.64678701271924],[511011.8838902381,6651143.496665428,69.36673755571923],[511012.1513071028,6651142.210115396,68.27247739971924],[511011.6302610773,6651144.716882431,70.43450920371923],[511011.83627021336,6651143.725766703,69.63314387071922],[511011.70999064477,6651144.333301246,70.17829608071924],[511011.78453805536,6651143.974651565,69.88085361071923],[511011.4025027757,6651145.812634004,71.52952771071924],[511012.12142017577,6651142.35390224,68.63023524571923],[511011.4762825692,6651145.457677349,71.43043221671923],[511012.08566719934,6651142.525910812,68.98069146071923],[511011.54969848035,6651145.104471343,71.30280945771923],[511012.0441494281,6651142.725653973,69.32043648771923],[511011.6220858723,6651144.756213572,71.14631816571925],[511011.9970764592,6651142.952123346,69.64610359771923],[511011.6927563552,6651144.416215898,70.96110926371924],[511011.94476508506,6651143.203794833,69.95447240571923],[511011.7610166613,6651144.087813651,70.74785692871923],[511011.8876332425,6651143.478657731,70.24257075671923],[511011.82618921663,6651143.77426666,70.50776848171922],[511021.4769820368,6651157.5717343185,64.29946579601143],[511021.6050489842,6651156.97573725,64.29946579601143],[511021.6050489842,6651156.97573725,64.42946579601143],[511021.4769820368,6651157.5717343185,66.12826945501143],[511021.48138539825,6651157.551241985,66.59386014201144],[511021.60504849284,6651156.975739538,66.12826945601144],[511021.60600341763,6651156.971295516,66.33209074001142],[511021.49515529623,6651157.487159729,67.07113109401143],[511021.6139325565,6651156.9343949435,66.74867002801143],[511021.5190019365,6651157.376182402,67.55403211401143],[511021.6304607842,6651156.857475993,67.17299714801145],[511021.54380282003,6651157.260764223,67.91573809901143],[511021.65612309735,6651156.738048899,67.59930749901143],[511021.5746556502,6651157.117181537,68.27349594501143],[511021.6912310927,6651156.574663554,68.02111635801143],[511021.6115641121,6651156.945417193,68.62395216001143],[511021.73582708446,6651156.3671230385,68.43146590101144],[511021.6544236788,6651156.74595764,68.96369718701143],[511021.78965314565,6651156.116627689,68.82324559501143],[511021.70301797934,6651156.5198098235,69.28936429701145],[511021.8357493826,6651155.9021053435,69.10072745501142],[511021.757019983,6651156.268495674,69.59773310501143],[511021.886373046,6651155.666513291,69.36116812801144],[511021.81599824573,6651155.994023046,69.88583145601143],[511021.94108724425,6651155.411884738,69.60213777401142],[511021.8794280553,6651155.698833841,70.15102918101144],[511021.9993815087,6651155.140595295,69.82155678001145],[511021.9467068953,6651155.385732044,70.39111762801144],[511022.08168782276,6651154.757558744,70.07776990301144],[511022.0171732778,6651155.057796085,70.60436996301144],[511022.16789534927,6651154.356366758,70.29004771201143],[511022.0901277305,6651154.71828116,70.78957886501144],[511022.256510285,6651153.943971187,70.45716246901142],[511022.16485458025,6651154.370517868,70.94607015701143],[511022.3460709085,6651153.527174582,70.57931559101145],[511022.24064318964,6651154.017813366,71.07369291601142],[511022.4352148884,6651153.11231695,70.65799028401143],[511022.31680744136,6651153.663360701,71.17278841001144],[511022.5227311794,6651152.705034244,70.69573314301142],[511022.41783728544,6651153.193188718,71.26195306201143],[511024.1680620823,6651145.048004751,64.29946579601143],[511022.5170224155,6651152.731601651,71.30472830301143],[511024.1680620823,6651145.048004751,64.42946579601143],[511024.2961290296,6651144.452007684,64.29946579601143],[511022.88273387484,6651151.029656208,70.69573314301142],[511024.1680620823,6651145.048004751,66.12826945501143],[511024.16417676344,6651145.066086221,66.53908476701145],[511024.2961290296,6651144.452007684,66.12826945501143],[511023.2503793955,6651149.318710045,70.69573314301142],[511024.1520268534,6651145.122629388,66.96020619501142],[511024.2917256682,6651144.472500016,66.59386014201144],[511023.33789568645,6651148.91142734,70.65799028401143],[511024.1309857002,6651145.220550559,67.38629533001144],[511023.4270396664,6651148.496569707,70.57931559101145],[511023.256088651,6651149.292140353,71.30472830301143],[511024.10062359745,6651145.361849502,67.81120183401143],[511024.27795577014,6651144.536582272,67.07113109401143],[511023.51660028985,6651148.079773102,70.45716246901142],[511024.06075863546,6651145.547372784,68.22816853601142],[511023.35527378094,6651148.830553286,71.26195306201143],[511023.60521522554,6651147.6673775315,70.29004771201143],[511024.25410913,6651144.6475596,67.55403211401143],[511024.01149592747,6651145.776631232,68.63011745301144],[511023.69142275205,6651147.266185545,70.07776990301144],[511023.9532488478,6651146.047701085,69.00999825501142],[511023.77372906613,6651146.883148995,69.82155678001145],[511023.90408981126,6651146.276477067,69.27640457001142],[511023.45630362513,6651148.3603813,71.17278841001144],[511024.22930824646,6651144.762977779,67.91573809901143],[511023.8506857434,6651146.525008547,69.52411431001143],[511023.53246787685,6651148.0059286365,71.07369291601142],[511024.19845541625,6651144.906560465,68.27349594501143],[511023.60825648624,6651147.653224135,70.94607015701143],[511024.1615469543,6651145.078324808,68.62395216001143],[511023.6829833359,6651147.305460841,70.78957886501144],[511024.1186873876,6651145.2777843615,68.96369718701143],[511023.7559377887,6651146.965945918,70.60436996301144],[511024.07009308715,6651145.503932178,69.28936429701145],[511023.8264041712,6651146.638009957,70.39111762801144],[511024.01609108347,6651145.755246326,69.59773310501143],[511023.8936830112,6651146.324908161,70.15102918101144],[511023.95711282076,6651146.029718955,69.88583145601143],[511025.8906830187,6651158.525863193,64.16447493163774],[511026.0202256484,6651157.93018513,64.16447493163774],[511026.0202256484,6651157.93018513,64.29447493163774],[511025.8906830187,6651158.525863193,65.99327859063776],[511025.89513711893,6651158.505381828,66.45886927763773],[511026.0202251514,6651157.930187415,65.99327859163773],[511026.02119107946,6651157.925745773,66.19709987563775],[511025.90906568395,6651158.441333872,66.93614022963774],[511026.02921158384,6651157.888864951,66.61367916363776],[511025.9331871027,6651158.330415945,67.41904124963776],[511026.045930262,6651157.811987172,67.03800628363774],[511025.9582737605,6651158.215059542,67.78074723463774],[511026.07188827544,6651157.692623999,67.46431663463774],[511025.98948209995,6651158.071553708,68.13850508063774],[511026.1074008111,6651157.529326106,67.88612549363775],[511026.02681584854,6651157.899881301,68.48896129563774],[511026.15251067106,6651157.321896676,68.29647503663774],[511026.0701692749,6651157.700528508,68.82870632263776],[511026.20695695595,6651157.071535405,68.68825473063774],[511026.119323515,6651157.474501736,69.15437343263774],[511026.25358434796,6651156.857127881,68.96573659063773],[511026.17394776986,6651157.223322102,69.46274224063774],[511026.30479133484,6651156.621661927,69.22617726363774],[511026.2336056238,6651156.948996385,69.75084059163775],[511026.36013599054,6651156.367169662,69.46714690963775],[511026.29776631884,6651156.653965177,70.01603831663773],[511026.4191019648,6651156.096025426,69.68656591563774],[511026.3658203954,6651156.3410309665,70.25612676363774],[511026.50235667324,6651155.713193893,69.94277903863774],[511026.43709874386,6651156.013270534,70.46937909863775],[511026.58955754683,6651155.312216644,70.15505684763774],[511026.51089383196,6651155.673937333,70.65458800063774],[511026.6791935697,6651154.900041806,70.32217160463773],[511026.5864817398,6651155.326360179,70.81107929263774],[511026.76978617697,6651154.483468289,70.44432472663775],[511026.6631436418,6651154.97384446,70.93870205163773],[511026.85995734,6651154.068832707,70.52299941963776],[511026.74018551456,6651154.619581515,71.03779754563776],[511026.94848205865,6651153.661767998,70.56074227863775],[511026.84237949946,6651154.149661188,71.12696219763774],[511026.9427075141,6651153.688321184,71.16973743863774],[511028.6127716849,6651146.008836894,64.16447493163774],[511028.6127716849,6651146.008836894,64.29447493163774],[511028.7423143146,6651145.413158831,64.16447493163774],[511027.31263297226,6651151.9872867,70.56074227863775],[511028.6127716849,6651146.008836894,65.99327859063776],[511028.6088415965,6651146.026908685,66.40409390263774],[511028.7423143146,6651145.413158831,65.99327859063776],[511027.6845147774,6651150.277256313,70.56074227863775],[511028.5965516861,6651146.083421589,66.82521533063773],[511027.773039496,6651149.870191604,70.52299941963776],[511028.7378602144,6651145.433640195,66.45886927763773],[511028.5752680812,6651146.181290348,67.25130446563773],[511027.6902898191,6651150.250700841,71.16973743863774],[511027.86321065895,6651149.455556022,70.44432472663775],[511028.54455612367,6651146.322513661,67.67621096963775],[511028.72393164935,6651145.497688151,66.93614022963774],[511027.9538032663,6651149.038982505,70.32217160463773],[511027.7906178337,6651149.789360836,71.12696219763774],[511028.504231808,6651146.507937643,68.09317767163773],[511028.0434392891,6651148.626807668,70.15505684763774],[511028.69981023046,6651145.608606079,67.41904124963776],[511028.4544014587,6651146.7370733805,68.49512658863773],[511028.1306401627,6651148.225830417,69.94277903863774],[511028.3954832129,6651147.007998145,68.87500739063773],[511027.89281181875,6651149.319440509,71.03779754563776],[511028.2138948712,6651147.842998885,69.68656591563774],[511028.34575772955,6651147.236651676,69.14141370563775],[511028.29173830024,6651147.48505013,69.38912344563774],[511028.6747235727,6651145.723962481,67.78074723463774],[511027.9698536914,6651148.965177565,70.93870205163773],[511028.64351523336,6651145.867468315,68.13850508063774],[511028.04651559336,6651148.612661846,70.81107929263774],[511028.60618148465,6651146.039140723,68.48896129563774],[511028.12210350134,6651148.265084692,70.65458800063774],[511028.56282805826,6651146.238493515,68.82870632263776],[511028.19589858945,6651147.925751491,70.46937909863775],[511028.5136738182,6651146.464520288,69.15437343263774],[511028.2671769378,6651147.597991058,70.25612676363774],[511028.45904956345,6651146.715699921,69.46274224063774],[511028.33523101447,6651147.285056848,70.01603831663773],[511028.39939170936,6651146.9900256395,69.75084059163775],[511028.50064462627,6651159.095456568,64.08371371663779],[511028.6310598739,6651158.499968944,64.08371371663779],[511028.6310598739,6651158.499968944,64.21371371663778],[511028.50064462627,6651159.095456568,65.91251737563779],[511028.5051287299,6651159.074981753,66.37810806263779],[511028.6310593735,6651158.499971229,65.9125173766378],[511028.6320318082,6651158.495531006,66.11633866063778],[511028.51915111975,6651159.010954272,66.85537901463779],[511028.6401063399,6651158.458661975,66.53291794863779],[511028.5434350239,6651158.900071804,67.33828003463779],[511028.6569376374,6651158.381808774,66.9572450686378],[511028.5686906691,6651158.784752281,67.6999860196378],[511028.68307050783,6651158.262483762,67.38355541963779],[511028.60010923236,6651158.641292327,68.05774386563779],[511028.7188222611,6651158.099238075,67.80536427863778],[511028.6376944665,6651158.469674803,68.40820008063778],[511028.7642359875,6651157.89187496,68.21571382163779],[511028.6813399279,6651158.270385743,68.74794510763779],[511028.81904903054,6651157.641593728,68.60749351563778],[511028.73082527803,6651158.044431232,69.0736122176378],[511028.8659905114,6651157.42725475,68.8849753756378],[511028.78581748967,6651157.793331902,69.38198102563778],[511028.91754243587,6651157.191864077,69.1454160486378],[511028.8458772076,6651157.519093884,69.67007937663779],[511028.97325990116,6651156.937453172,69.38638569463778],[511028.9104700983,6651157.224157,69.9352771016378],[511029.03262307873,6651156.666395621,69.6058047006378],[511028.978982597,6651156.911322834,70.17536554863779],[511029.11643860297,6651156.283686481,69.8620178236378],[511029.0507410867,6651156.583667185,70.38861788363779],[511029.2042268743,6651155.882837423,70.07429563263779],[511029.12503326917,6651156.244442471,70.57382678563779],[511029.2944666982,6651155.470794357,70.24141038963779],[511029.20113034814,6651155.8969764365,70.73031807763779],[511029.38566955045,6651155.054354019,70.36356351163778],[511029.2783086558,6651155.544573417,70.85794083663778],[511029.3558694937,6651155.19042373,70.95703633063779],[511029.4764481195,6651154.639850996,70.44223820463779],[511029.56556915335,6651154.232916427,70.47998106363778],[511029.458751872,6651154.720653636,71.04620098263779],[511029.5597557107,6651154.2594611235,71.08897622363779],[511031.2410696749,6651146.582431968,64.08371371663779],[511031.2410696749,6651146.582431968,64.21371371663778],[511031.37148492254,6651145.986944344,64.08371371663779],[511029.9321730401,6651152.558970461,70.47998106363778],[511031.2410696749,6651146.582431968,65.91251737563779],[511031.2371131129,6651146.600497983,66.3233326876378],[511031.37148492254,6651145.986944344,65.91251737563779],[511030.30655989476,6651150.849486773,70.47998106363778],[511031.224740416,6651146.656992819,66.74445411563778],[511030.3956809287,6651150.442552201,70.44223820463779],[511031.36700081883,6651146.007419161,66.37810806263779],[511031.2033134416,6651146.75483029,67.17054325063779],[511030.31237383815,6651150.822939789,71.08897622363779],[511030.48645949777,6651150.028049178,70.36356351163778],[511031.17239460396,6651146.896008453,67.59544975463778],[511031.35297842906,6651146.071446641,66.85537901463779],[511030.5776623499,6651149.6116088405,70.24141038963779],[511030.4133776768,6651150.361747275,71.04620098263779],[511031.1317986578,6651147.081373155,68.01241645663778],[511030.66790217394,6651149.199565775,70.07429563263779],[511031.3286945249,6651146.182329107,67.33828003463779],[511031.08163264394,6651147.310435638,68.41436537363779],[511030.75569044525,6651148.798716717,69.8620178236378],[511030.51626005507,6651149.891977183,70.95703633063779],[511031.02231751644,6651147.581273788,68.79424617563778],[511030.8395059694,6651148.416007577,69.6058047006378],[511030.9722570751,6651147.809854217,69.06065249063778],[511030.91787376313,6651148.058173259,69.30836223063778],[511031.3034388796,6651146.29764863,67.6999860196378],[511030.59382089303,6651149.5378274955,70.85794083663778],[511031.27202031645,6651146.441108585,68.05774386563779],[511030.67099920067,6651149.185424476,70.73031807763779],[511031.2344350823,6651146.61272611,68.40820008063778],[511030.74709627964,6651148.837958442,70.57382678563779],[511031.1907896209,6651146.812015168,68.74794510763779],[511030.8213884621,6651148.498733727,70.38861788363779],[511031.1413042708,6651147.037969681,69.0736122176378],[511030.8931469518,6651148.171078078,70.17536554863779],[511031.08631205914,6651147.289069012,69.38198102563778],[511030.96165945055,6651147.858243913,69.9352771016378],[511031.0262523412,6651147.563307027,69.67007937663779],[511038.1734005084,6651161.241404697,63.77831790688605],[511038.3070497575,6651160.646634553,63.77831790688605],[511038.3070497575,6651160.646634553,63.90831790688606],[511038.1734005084,6651161.241404697,65.60712156588606],[511038.17799580767,6651161.2209545495,66.07271225288605],[511038.3070492447,6651160.646636833,65.60712156688605],[511038.3080457937,6651160.64220196,65.81094285088605],[511038.19236592087,6651161.157004214,66.54998320488606],[511038.3163205552,6651160.605377353,66.22752213888606],[511038.21725201065,6651161.0462553445,67.03288422488606],[511038.33356923074,6651160.528616747,66.65184925888606],[511038.24313393835,6651160.931074766,67.39459020988606],[511038.3603501369,6651160.409435506,67.07815960988606],[511038.2753316105,6651160.787787661,67.75234805588606],[511038.3969884523,6651160.2463865075,67.49996846888605],[511038.31384887296,6651160.616376911,68.10280427088607],[511038.4435283358,6651160.039273236,67.91031801188608],[511038.3585766425,6651160.417327967,68.44254929788606],[511038.4997006175,6651159.789293559,68.30209770588606],[511038.4092891167,6651160.191645699,68.76821640788606],[511038.5478061403,6651159.575212829,68.57957956588605],[511038.4656450101,6651159.940848907,69.07658521588606],[511038.60063643527,6651159.340105767,68.84002023888605],[511038.52719407243,6651159.666941309,69.36468356688606],[511038.657735567,6651159.086001392,69.08098988488605],[511038.5933887199,6651159.3723597815,69.62988129188605],[511038.71857081633,6651158.815270428,69.30040889088606],[511038.66360017273,6651159.059902538,69.86996973888606],[511038.80446477485,6651158.433022398,69.55662201388606],[511038.73713810963,6651158.732641668,70.08322207388606],[511038.89442999556,6651158.032656307,69.76889982288606],[511038.8132725692,6651158.393825671,70.26843097588606],[511038.9869075619,6651157.621109696,69.93601457988606],[511038.89125668263,6651158.046778286,70.42492226788607],[511039.0803720374,6651157.20517111,70.05816770188605],[511038.97034883674,6651157.694799862,70.55254502688607],[511039.049833007,6651157.341076876,70.65164052088606],[511039.1734017084,6651156.791167505,70.13684239488606],[511039.26473274117,6651156.384723234,70.17458525388605],[511039.1552666343,6651156.871872789,70.74080517288606],[511039.2587751383,6651156.411235948,70.78358041388606],[511040.981781864,6651148.743456536,63.77831790688605],[511040.981781864,6651148.743456536,63.90831790688606],[511039.6404275704,6651154.712794139,70.17458525388605],[511041.115431113,6651148.148686391,63.77831790688605],[511040.981781864,6651148.743456536,65.60712156588606],[511040.9777271882,6651148.761500784,66.01793687788606],[511040.02409836726,6651153.005370137,70.17458525388605],[511041.115431113,6651148.148686391,65.60712156588606],[511040.11542940006,6651152.598925866,70.13684239488606],[511040.9650476766,6651148.8179275505,66.43905830588605],[511041.11083581386,6651148.169136538,66.07271225288605],[511040.0300564831,6651152.978855141,70.78358041388606],[511040.2084590711,6651152.184922261,70.05816770188605],[511040.943089362,6651148.915647141,66.86514744088608],[511040.30192354653,6651151.768983676,69.93601457988606],[511040.91140380746,6651149.056655205,67.29005394488605],[511040.1335649872,6651152.518218298,70.74080517288606],[511041.09646570054,6651148.233086874,66.54998320488606],[511040.39440111286,6651151.357437064,69.76889982288606],[511040.86980117427,6651149.241796569,67.70702064688605],[511040.4843663336,6651150.957070973,69.55662201388606],[511040.8183911574,6651149.470583063,68.10896956388605],[511040.23899861454,6651152.049014212,70.65164052088606],[511041.07157961087,6651148.343835743,67.03288422488606],[511040.5702602921,6651150.574822943,69.30040889088606],[511040.7576051497,6651149.74109489,68.48885036588607],[511040.7063033231,6651149.969399913,68.75525668088605],[511040.6505714288,6651150.217419764,69.00296642088605],[511040.3184827848,6651151.695291226,70.55254502688607],[511041.04569768306,6651148.459016323,67.39459020988606],[511040.3975749388,6651151.343312804,70.42492226788607],[511041.013500011,6651148.602303429,67.75234805588606],[511040.4755590523,6651150.996265417,70.26843097588606],[511040.97498274845,6651148.773714176,68.10280427088607],[511040.5516935118,6651150.65744942,70.08322207388606],[511040.93025497894,6651148.972763121,68.44254929788606],[511040.62523144885,6651150.33018855,69.86996973888606],[511040.8795425047,6651149.198445389,68.76821640788606],[511040.69544290163,6651150.017731307,69.62988129188605],[511040.8231866113,6651149.449242182,69.07658521588606],[511040.76163754903,6651149.723149778,69.36468356688606],[511042.263431685,6651162.165406717,63.646292658619146],[511042.39844840026,6651161.570945504,63.646292658619146],[511042.39844840026,6651161.570945504,63.776292658619155],[511042.263431685,6651162.165406717,65.47509631761915],[511042.2680740021,6651162.144967193,65.94068700461915],[511042.3984478822,6651161.570947786,65.47509631861915],[511042.39945462754,6651161.566515215,65.67891760261917],[511042.2825911469,6651162.081050075,66.41795795661916],[511042.4078140545,6651161.529709735,66.09549689061915],[511042.307731865,6651161.970358729,66.90085897661915],[511042.42523921415,6651161.452989,66.51982401061915],[511042.33387861017,6651161.855237977,67.26256496161915],[511042.452294136,6651161.333869664,66.94613436161914],[511042.36640572094,6651161.712025296,67.62032280761915],[511042.48930732557,6651161.170905354,67.36794322061917],[511042.40531708254,6651161.54070358,67.97077902261915],[511042.53632339375,6651160.96389966,67.77829276361915],[511042.4505024956,6651161.341758025,68.31052404961915],[511042.5930704165,6651160.714049825,68.17007245761916],[511042.50173384737,6651161.116192979,68.63619115961914],[511042.6416681431,6651160.500080292,68.44755431761915],[511042.5586663605,6651160.8655264545,68.94455996761916],[511042.69503898453,6651160.265095349,68.70799499061916],[511042.62084517756,6651160.591761129,69.23265831861914],[511042.75272234064,6651160.011122961,68.94896463661917],[511042.68771711236,6651160.297332611,69.49785604361915],[511042.81418004126,6651159.740532617,69.16838364261915],[511042.7586469514,6651159.985037661,69.73794449061916],[511042.9009528455,6651159.358483133,69.42459676561916],[511042.83293731045,6651159.657946776,69.95119682561915],[511042.99183856824,6651158.958324998,69.63687457461916],[511042.90985075914,6651159.319306764,70.13640572761916],[511043.0852623423,6651158.546992149,69.80398933161915],[511042.9886327868,6651158.972439639,70.29289701961915],[511043.17968312325,6651158.131269607,69.92614245361915],[511043.0685341923,6651158.620644039,70.42051977861915],[511043.148831625,6651158.267104781,70.51961527261915],[511043.2736646509,6651157.717481041,70.00481714661915],[511043.36593016033,6651157.311247882,70.04256000561917],[511043.2553440232,6651157.798144408,70.60877992461916],[511043.3599116008,6651157.337746827,70.65155516561916],[511045.10054770694,6651149.673950167,63.646292658619146],[511045.10054770694,6651149.673950167,63.776292658619155],[511043.7454690065,6651155.640187212,70.04256000561917],[511045.23556442215,6651149.079488954,63.646292658619146],[511045.10054770694,6651149.673950167,65.47509631761915],[511044.13306542847,6651153.933650071,70.04256000561917],[511045.0964515448,6651149.691985042,65.88591162961914],[511045.23556442215,6651149.079488954,65.47509631761915],[511044.225330938,6651153.527416913,70.00481714661915],[511045.0836422994,6651149.7483825,66.30703305761915],[511044.1390845064,6651153.907148846,70.65155516561916],[511044.3193124656,6651153.113628346,69.92614245361915],[511045.23092210497,6651149.09992848,65.94068700461915],[511045.06145931274,6651149.8460513335,66.73312219261915],[511044.4137332466,6651152.697905804,69.80398933161915],[511045.0294495594,6651149.986986156,67.15802869661917],[511044.2436520839,6651153.446751265,70.60877992461916],[511045.21640496026,6651149.163845598,66.41795795661916],[511044.5071570207,6651152.286572957,69.63687457461916],[511044.98742125835,6651150.172031355,67.57499539861915],[511044.59804274334,6651151.886414822,69.42459676561916],[511044.35016448214,6651152.977790889,70.51961527261915],[511044.93548522686,6651150.400699014,67.97694431561915],[511045.1912642422,6651149.274536943,66.90085897661915],[511044.6848155476,6651151.504365336,69.16838364261915],[511044.87407727167,6651150.6710703345,68.35682511761915],[511044.8222505375,6651150.899256771,68.62323143261916],[511044.76594840817,6651151.147147799,68.87094117261915],[511044.43046191486,6651152.624251632,70.42051977861915],[511045.1651174969,6651149.389657696,67.26256496161915],[511044.51036332035,6651152.272456031,70.29289701961915],[511045.13259038614,6651149.5328703765,67.62032280761915],[511044.589145348,6651151.925588907,70.13640572761916],[511045.09367902455,6651149.704192091,67.97077902261915],[511044.66605879663,6651151.586948897,69.95119682561915],[511045.04849361157,6651149.903137647,68.31052404961915],[511044.74034915573,6651151.25985801,69.73794449061916],[511044.9972622597,6651150.128702692,68.63619115961914],[511044.8112789948,6651150.9475630615,69.49785604361915],[511044.94032974663,6651150.379369217,68.94455996761916],[511044.8781509296,6651150.653134543,69.23265831861914],[511048.11355399096,6651163.504241231,63.45445553490367],[511048.2505266435,6651162.910227645,63.45445553490367],[511048.2505266435,6651162.910227645,63.584455534903675],[511048.11355399096,6651163.504241231,65.28325919390367],[511048.11826355965,6651163.483817097,65.74884988090368],[511048.2505261179,6651162.910229924,65.28325919490368],[511048.2515474477,6651162.905800693,65.48708047890366],[511048.13299100887,6651163.4199481085,66.22612083290367],[511048.26002797455,6651162.869022926,65.90365976690367],[511048.15849593125,6651163.309340114,66.70902185290367],[511048.277705566,6651162.792359963,66.32798688690369],[511048.18502145476,6651163.194306046,67.07072783790368],[511048.30515242246,6651162.673330323,66.75429723790367],[511048.2180197737,6651163.051201204,67.42848568390367],[511048.3427018085,6651162.510488725,67.17610609690367],[511048.2574948299,6651162.8800084945,67.77894189890367],[511048.3903989811,6651162.303638905,67.58645563990368],[511048.30333482736,6651162.681212743,68.11868692590367],[511048.4479680769,6651162.053977206,67.97823533390367],[511048.3553083488,6651162.455817548,68.44435403590369],[511048.497269821,6651161.840168792,68.25571719390368],[511048.41306562215,6651162.2053397745,68.75272284390367],[511048.5514138261,6651161.605360792,68.51615786690368],[511048.47614520084,6651161.931780593,69.04082119490367],[511048.60993281956,6651161.351579643,68.75712751290366],[511048.5439858846,6651161.637573778,69.30601891990368],[511048.6722808353,6651161.081193054,68.97654651890369],[511048.6159432581,6651161.325513987,69.54610736690368],[511048.7603106852,6651160.699431251,69.23275964190368],[511048.69130983413,6651160.9986694,69.75935970190368],[511048.8525130357,6651160.299574434,69.44503745090367],[511048.76933749946,6651160.660284384,69.94456860390368],[511048.9472902055,6651159.888551319,69.61215220790369],[511048.8492608134,6651160.313678448,70.10105989590367],[511048.93031972094,6651159.96214775,70.22868265490368],[511049.0430788254,6651159.473141815,69.73430532990369],[511049.01178039296,6651159.608874706,70.32777814890368],[511049.13842182886,6651159.0596648315,69.81298002290367],[511049.2320239546,6651158.6537375655,69.85072288190366],[511049.11983579694,6651159.140267456,70.41694280090367],[511049.22591820644,6651158.680216554,70.45971804190367],[511050.99177026504,6651151.022190713,63.45445553490367],[511050.99177026504,6651151.022190713,63.584455534903675],[511049.61706103984,6651156.983935197,69.85072288190366],[511051.1287429177,6651150.428177127,63.45445553490367],[511050.99177026504,6651151.022190713,65.28325919390367],[511050.01027242816,6651155.278683073,69.85072288190366],[511050.9876147634,6651151.040212006,65.69407450590369],[511050.103874554,6651154.872755808,69.81298002290367],[511051.1287429177,6651150.428177127,65.28325919390367],[511050.9746199552,6651151.0965669975,66.11519593390366],[511050.0163787022,6651155.252201804,70.45971804190367],[511050.1992175574,6651154.459278824,69.73430532990369],[511051.12403334887,6651150.448601262,65.74884988090368],[511050.95211561176,6651151.194162289,66.54128506890368],[511050.2950061773,6651154.043869319,69.61215220790369],[511050.1224611116,6651154.792150903,70.41694280090367],[511050.919642145,6651151.334990987,66.96619157290367],[511051.10930589976,6651150.51247025,66.22612083290367],[511050.3897833471,6651153.632846204,69.44503745090367],[511050.8770049955,6651151.519896845,67.38315827490366],[511050.2305165157,6651154.323543652,70.32777814890368],[511050.4819856976,6651153.232989387,69.23275964190368],[511050.82431658584,6651151.74839232,67.78510719190368],[511050.5700155475,6651152.851227584,68.97654651890369],[511051.08380097727,6651150.623078245,66.70902185290367],[511050.7620190362,6651152.018560051,68.16498799390367],[511050.65232374985,6651152.49427903,68.67910404890367],[511050.70944150735,6651152.2465746645,68.43139430890366],[511050.3119771876,6651153.970270609,70.22868265490368],[511051.0572754539,6651150.738112312,67.07072783790368],[511050.39303609525,6651153.6187399095,70.10105989590367],[511051.0242771348,6651150.881217155,67.42848568390367],[511050.47295940906,6651153.272133974,69.94456860390368],[511050.98480207863,6651151.052409864,67.77894189890367],[511050.5509870744,6651152.933748959,69.75935970190368],[511050.9389620813,6651151.251205615,68.11868692590367],[511050.6263536504,6651152.606904372,69.54610736690368],[511050.88698855985,6651151.476600811,68.44435403590369],[511050.69831102394,6651152.294844581,69.30601891990368],[511050.8292312865,6651151.727078585,68.75272284390367],[511050.7661517078,6651152.000637765,69.04082119490367]],"pointIndex":[2,1,83,84,0,1,4,86,83,0,4,5,87,86,0,5,6,88,87,0,6,9,91,88,0,9,11,93,91,0,11,13,95,93,0,13,15,97,95,0,15,17,99,97,0,17,19,102,99,0,19,21,104,102,0,21,23,109,104,0,23,26,113,109,0,26,28,118,113,0,28,29,123,118,0,29,31,127,123,0,31,33,131,127,0,33,35,135,131,0,35,37,139,135,0,37,39,143,139,0,39,41,149,143,0,41,44,166,149,0,44,47,170,166,0,47,51,174,170,0,51,54,177,174,0,54,56,179,177,0,56,60,184,179,0,60,64,188,184,0,64,71,195,188,0,71,73,197,195,0,73,74,198,197,0,74,76,200,198,0,76,78,202,200,0,78,80,204,202,0,80,82,206,204,0,82,81,205,206,0,81,79,203,205,0,79,77,201,203,0,77,75,199,201,0,75,72,196,199,0,72,69,193,196,0,69,53,176,193,0,53,48,171,176,0,48,49,172,171,0,49,57,181,172,0,57,59,183,181,0,59,62,186,183,0,62,65,189,186,0,65,67,191,189,0,67,70,194,191,0,70,68,192,194,0,68,66,190,192,0,66,63,187,190,0,63,61,185,187,0,61,58,182,185,0,58,55,178,182,0,55,52,175,178,0,52,50,173,175,0,50,46,169,173,0,46,45,167,169,0,45,43,164,167,0,43,42,156,164,0,42,40,146,156,0,40,38,142,146,0,38,36,137,142,0,36,34,133,137,0,34,32,128,133,0,32,30,124,128,0,30,27,117,124,0,27,25,112,117,0,25,24,110,112,0,24,22,106,110,0,22,20,103,106,0,20,18,100,103,0,18,16,98,100,0,16,14,96,98,0,14,12,94,96,0,12,10,92,94,0,10,8,90,92,0,8,7,89,90,0,7,3,85,89,0,3,2,84,85,0,84,83,101,105,0,83,86,108,101,0,86,87,111,108,0,87,88,114,111,0,88,91,119,114,0,91,93,121,119,0,93,95,125,121,0,95,97,129,125,0,97,99,132,129,0,99,102,136,132,0,102,104,140,136,0,104,109,144,140,0,109,113,148,144,0,113,118,151,148,0,118,123,152,151,0,123,127,154,152,0,127,131,157,154,0,131,135,159,157,0,135,139,161,159,0,139,143,163,161,0,143,149,168,163,0,149,166,208,168,0,166,170,211,208,0,170,174,215,211,0,174,177,218,215,0,177,179,220,218,0,179,184,224,220,0,184,188,228,224,0,188,195,235,228,0,195,197,237,235,0,197,198,238,237,0,198,200,240,238,0,200,202,242,240,0,202,204,244,242,0,204,206,246,244,0,206,205,245,246,0,205,203,243,245,0,203,201,241,243,0,201,199,239,241,0,199,196,236,239,0,196,193,233,236,0,193,176,217,233,0,176,171,212,217,0,171,172,213,212,0,172,181,221,213,0,181,183,223,221,0,183,186,226,223,0,186,189,229,226,0,189,191,231,229,0,191,194,234,231,0,194,192,232,234,0,192,190,230,232,0,190,187,227,230,0,187,185,225,227,0,185,182,222,225,0,182,178,219,222,0,178,175,216,219,0,175,173,214,216,0,173,169,210,214,0,169,167,209,210,0,167,164,207,209,0,164,156,180,207,0,156,146,165,180,0,146,142,162,165,0,142,137,160,162,0,137,133,158,160,0,133,128,155,158,0,128,124,153,155,0,124,117,150,153,0,117,112,147,150,0,112,110,145,147,0,110,106,141,145,0,106,103,138,141,0,103,100,134,138,0,100,98,130,134,0,98,96,126,130,0,96,94,122,126,0,94,92,120,122,0,92,90,116,120,0,90,89,115,116,0,89,85,107,115,0,85,84,105,107,0,105,101,247,249,0,101,108,253,247,0,108,111,255,253,0,111,114,257,255,0,114,119,262,257,0,119,121,267,262,0,121,125,271,267,0,125,129,275,271,0,129,132,279,275,0,132,136,283,279,0,136,140,287,283,0,140,144,291,287,0,144,148,296,291,0,148,151,300,296,0,151,152,303,300,0,152,154,307,303,0,154,157,311,307,0,157,159,314,311,0,159,161,318,314,0,161,163,322,318,0,163,168,327,322,0,168,208,333,327,0,208,211,338,333,0,211,215,346,338,0,215,218,351,346,0,218,220,356,351,0,220,224,362,356,0,224,228,369,362,0,228,235,379,369,0,235,237,388,379,0,237,238,392,388,0,238,240,395,392,0,240,242,397,395,0,242,244,401,397,0,244,246,403,401,0,246,245,400,403,0,245,243,398,400,0,243,241,396,398,0,241,239,391,396,0,239,236,384,391,0,236,233,374,384,0,233,217,348,374,0,217,212,339,348,0,212,213,340,339,0,213,221,357,340,0,221,223,360,357,0,223,226,365,360,0,226,229,370,365,0,229,231,373,370,0,231,234,377,373,0,234,232,376,377,0,232,230,372,376,0,230,227,368,372,0,227,225,364,368,0,225,222,358,364,0,222,219,354,358,0,219,216,349,354,0,216,214,344,349,0,214,210,337,344,0,210,209,334,337,0,209,207,331,334,0,207,180,329,331,0,180,165,324,329,0,165,162,321,324,0,162,160,316,321,0,160,158,312,316,0,158,155,308,312,0,155,153,304,308,0,153,150,299,304,0,150,147,295,299,0,147,145,292,295,0,145,141,288,292,0,141,138,284,288,0,138,134,280,284,0,134,130,276,280,0,130,126,272,276,0,126,122,268,272,0,122,120,263,268,0,120,116,259,263,0,116,115,258,259,0,115,107,250,258,0,107,105,249,250,0,249,247,248,251,0,247,253,254,248,0,253,255,256,254,0,255,257,260,256,0,257,262,265,260,0,262,267,269,265,0,267,271,273,269,0,271,275,277,273,0,275,279,281,277,0,279,283,285,281,0,283,287,289,285,0,287,291,293,289,0,291,296,298,293,0,296,300,302,298,0,300,303,305,302,0,303,307,309,305,0,307,311,313,309,0,311,314,317,313,0,314,318,320,317,0,318,322,325,320,0,322,327,328,325,0,327,333,335,328,0,333,338,342,335,0,338,346,350,342,0,346,351,355,350,0,351,356,361,355,0,356,362,371,361,0,362,369,381,371,0,369,379,390,381,0,379,388,394,390,0,388,392,402,394,0,392,395,404,402,0,395,397,406,404,0,397,401,409,406,0,401,403,410,409,0,403,400,408,410,0,400,398,407,408,0,398,396,405,407,0,396,391,399,405,0,391,384,393,399,0,384,374,386,393,0,374,348,352,386,0,348,339,343,352,0,339,340,345,343,0,340,357,363,345,0,357,360,367,363,0,360,365,378,367,0,365,370,382,378,0,370,373,385,382,0,373,377,389,385,0,377,376,387,389,0,376,372,383,387,0,372,368,380,383,0,368,364,375,380,0,364,358,366,375,0,358,354,359,366,0,354,349,353,359,0,349,344,347,353,0,344,337,341,347,0,337,334,336,341,0,334,331,332,336,0,331,329,330,332,0,329,324,326,330,0,324,321,323,326,0,321,316,319,323,0,316,312,315,319,0,312,308,310,315,0,308,304,306,310,0,304,299,301,306,0,299,295,297,301,0,295,292,294,297,0,292,288,290,294,0,288,284,286,290,0,284,280,282,286,0,280,276,278,282,0,276,272,274,278,0,272,268,270,274,0,268,263,266,270,0,263,259,264,266,0,259,258,261,264,0,258,250,252,261,0,250,249,251,252,0,251,248,411,412,0,248,254,414,411,0,254,256,415,414,0,256,260,417,415,0,260,265,419,417,0,265,269,422,419,0,269,273,423,422,0,273,277,425,423,0,277,281,427,425,0,281,285,429,427,0,285,289,431,429,0,289,293,433,431,0,293,298,436,433,0,298,302,438,436,0,302,305,439,438,0,305,309,441,439,0,309,313,443,441,0,313,317,445,443,0,317,320,447,445,0,320,325,449,447,0,325,328,451,449,0,328,335,454,451,0,335,342,458,454,0,342,350,461,458,0,350,355,465,461,0,355,361,468,465,0,361,371,473,468,0,371,381,479,473,0,381,390,486,479,0,390,394,488,486,0,394,402,492,488,0,402,404,495,492,0,404,406,497,495,0,406,409,499,497,0,409,410,500,499,0,410,408,498,500,0,408,407,496,498,0,407,405,494,496,0,405,399,489,494,0,399,393,487,489,0,393,386,481,487,0,386,352,463,481,0,352,343,457,463,0,343,345,459,457,0,345,363,467,459,0,363,367,472,467,0,367,378,475,472,0,378,382,478,475,0,382,385,482,478,0,385,389,484,482,0,389,387,483,484,0,387,383,480,483,0,383,380,477,480,0,380,375,474,477,0,375,366,471,474,0,366,359,466,471,0,359,353,464,466,0,353,347,460,464,0,347,341,456,460,0,341,336,455,456,0,336,332,453,455,0,332,330,452,453,0,330,326,450,452,0,326,323,448,450,0,323,319,446,448,0,319,315,444,446,0,315,310,442,444,0,310,306,440,442,0,306,301,437,440,0,301,297,435,437,0,297,294,434,435,0,294,290,432,434,0,290,286,430,432,0,286,282,428,430,0,282,278,426,428,0,278,274,424,426,0,274,270,421,424,0,270,266,420,421,0,266,264,418,420,0,264,261,416,418,0,261,252,413,416,0,252,251,412,413,0,412,411,462,469,0,411,414,476,462,0,414,415,485,476,0,415,417,491,485,0,417,419,502,491,0,419,422,504,502,0,422,423,505,504,0,423,425,507,505,0,425,427,509,507,0,427,429,511,509,0,429,431,513,511,0,431,433,515,513,0,433,436,518,515,0,436,438,520,518,0,438,439,521,520,0,439,441,523,521,0,441,443,525,523,0,443,445,527,525,0,445,447,529,527,0,447,449,531,529,0,449,451,533,531,0,451,454,536,533,0,454,458,540,536,0,458,461,543,540,0,461,465,546,543,0,465,468,549,546,0,468,473,552,549,0,473,479,557,552,0,479,486,563,557,0,486,488,565,563,0,488,492,567,565,0,492,495,569,567,0,495,497,571,569,0,497,499,573,571,0,499,500,574,573,0,500,498,572,574,0,498,496,570,572,0,496,494,568,570,0,494,489,566,568,0,489,487,564,566,0,487,481,559,564,0,481,463,544,559,0,463,457,538,544,0,457,459,541,538,0,459,467,548,541,0,467,472,551,548,0,472,475,553,551,0,475,478,556,553,0,478,482,560,556,0,482,484,562,560,0,484,483,561,562,0,483,480,558,561,0,480,477,555,558,0,477,474,554,555,0,474,471,550,554,0,471,466,547,550,0,466,464,545,547,0,464,460,542,545,0,460,456,539,542,0,456,455,537,539,0,455,453,535,537,0,453,452,534,535,0,452,450,532,534,0,450,448,530,532,0,448,446,528,530,0,446,444,526,528,0,444,442,524,526,0,442,440,522,524,0,440,437,519,522,0,437,435,517,519,0,435,434,516,517,0,434,432,514,516,0,432,430,512,514,0,430,428,510,512,0,428,426,508,510,0,426,424,506,508,0,424,421,503,506,0,421,420,501,503,0,420,418,493,501,0,418,416,490,493,0,416,413,470,490,0,413,412,469,470,0,469,462,575,576,0,462,476,578,575,0,476,485,579,578,0,485,491,581,579,0,491,502,584,581,0,502,504,586,584,0,504,505,588,586,0,505,507,589,588,0,507,509,591,589,0,509,511,593,591,0,511,513,595,593,0,513,515,597,595,0,515,518,600,597,0,518,520,602,600,0,520,521,603,602,0,521,523,605,603,0,523,525,607,605,0,525,527,609,607,0,527,529,611,609,0,529,531,613,611,0,531,533,615,613,0,533,536,618,615,0,536,540,623,618,0,540,543,625,623,0,543,546,628,625,0,546,549,631,628,0,549,552,634,631,0,552,557,640,634,0,557,563,645,640,0,563,565,647,645,0,565,567,649,647,0,567,569,651,649,0,569,571,653,651,0,571,573,655,653,0,573,574,656,655,0,574,572,654,656,0,572,570,652,654,0,570,568,650,652,0,568,566,648,650,0,566,564,646,648,0,564,559,639,646,0,559,544,626,639,0,544,538,620,626,0,538,541,621,620,0,541,548,629,621,0,548,551,632,629,0,551,553,635,632,0,553,556,637,635,0,556,560,642,637,0,560,562,644,642,0,562,561,643,644,0,561,558,641,643,0,558,555,638,641,0,555,554,636,638,0,554,550,633,636,0,550,547,630,633,0,547,545,627,630,0,545,542,624,627,0,542,539,622,624,0,539,537,619,622,0,537,535,617,619,0,535,534,616,617,0,534,532,614,616,0,532,530,612,614,0,530,528,610,612,0,528,526,608,610,0,526,524,606,608,0,524,522,604,606,0,522,519,601,604,0,519,517,599,601,0,517,516,598,599,0,516,514,596,598,0,514,512,594,596,0,512,510,592,594,0,510,508,590,592,0,508,506,587,590,0,506,503,585,587,0,503,501,583,585,0,501,493,582,583,0,493,490,580,582,0,490,470,577,580,0,470,469,576,577,0,576,575,657,658,0,575,578,660,657,0,578,579,661,660,0,579,581,663,661,0,581,584,666,663,0,584,586,668,666,0,586,588,670,668,0,588,589,671,670,0,589,591,673,671,0,591,593,675,673,0,593,595,677,675,0,595,597,679,677,0,597,600,682,679,0,600,602,684,682,0,602,603,686,684,0,603,605,687,686,0,605,607,689,687,0,607,609,691,689,0,609,611,693,691,0,611,613,695,693,0,613,615,697,695,0,615,618,700,697,0,618,623,705,700,0,623,625,708,705,0,625,628,710,708,0,628,631,713,710,0,631,634,717,713,0,634,640,722,717,0,640,645,728,722,0,645,647,729,728,0,647,649,731,729,0,649,651,733,731,0,651,653,735,733,0,653,655,737,735,0,655,656,738,737,0,656,654,736,738,0,654,652,734,736,0,652,650,732,734,0,650,648,730,732,0,648,646,727,730,0,646,639,721,727,0,639,626,707,721,0,626,620,702,707,0,620,621,703,702,0,621,629,711,703,0,629,632,714,711,0,632,635,716,714,0,635,637,719,716,0,637,642,723,719,0,642,644,725,723,0,644,643,726,725,0,643,641,724,726,0,641,638,720,724,0,638,636,718,720,0,636,633,715,718,0,633,630,712,715,0,630,627,709,712,0,627,624,706,709,0,624,622,704,706,0,622,619,701,704,0,619,617,699,701,0,617,616,698,699,0,616,614,696,698,0,614,612,694,696,0,612,610,692,694,0,610,608,690,692,0,608,606,688,690,0,606,604,685,688,0,604,601,683,685,0,601,599,681,683,0,599,598,680,681,0,598,596,678,680,0,596,594,676,678,0,594,592,674,676,0,592,590,672,674,0,590,587,669,672,0,587,585,667,669,0,585,583,665,667,0,583,582,664,665,0,582,580,662,664,0,580,577,659,662,0,577,576,658,659,0,658,657,739,740,0,657,660,742,739,0,660,661,743,742,0,661,663,745,743,0,663,666,748,745,0,666,668,750,748,0,668,670,752,750,0,670,671,753,752,0,671,673,755,753,0,673,675,757,755,0,675,677,759,757,0,677,679,761,759,0,679,682,764,761,0,682,684,766,764,0,684,686,768,766,0,686,687,769,768,0,687,689,771,769,0,689,691,773,771,0,691,693,775,773,0,693,695,777,775,0,695,697,779,777,0,697,700,782,779,0,700,705,787,782,0,705,708,790,787,0,708,710,792,790,0,710,713,796,792,0,713,717,799,796,0,717,722,806,799,0,722,728,810,806,0,728,729,812,810,0,729,731,813,812,0,731,733,815,813,0,733,735,817,815,0,735,737,820,817,0,737,738,819,820,0,738,736,818,819,0,736,734,816,818,0,734,732,814,816,0,732,730,811,814,0,730,727,809,811,0,727,721,802,809,0,721,707,789,802,0,707,702,784,789,0,702,703,785,784,0,703,711,793,785,0,711,714,795,793,0,714,716,798,795,0,716,719,801,798,0,719,723,804,801,0,723,725,807,804,0,725,726,808,807,0,726,724,805,808,0,724,720,803,805,0,720,718,800,803,0,718,715,797,800,0,715,712,794,797,0,712,709,791,794,0,709,706,788,791,0,706,704,786,788,0,704,701,783,786,0,701,699,781,783,0,699,698,780,781,0,698,696,778,780,0,696,694,776,778,0,694,692,774,776,0,692,690,772,774,0,690,688,770,772,0,688,685,767,770,0,685,683,765,767,0,683,681,763,765,0,681,680,762,763,0,680,678,760,762,0,678,676,758,760,0,676,674,756,758,0,674,672,754,756,0,672,669,751,754,0,669,667,749,751,0,667,665,747,749,0,665,664,746,747,0,664,662,744,746,0,662,659,741,744,0,659,658,740,741,0,740,739,821,822,0,739,742,824,821,0,742,743,825,824,0,743,745,827,825,0,745,748,830,827,0,748,750,832,830,0,750,752,834,832,0,752,753,835,834,0,753,755,837,835,0,755,757,839,837,0,757,759,841,839,0,759,761,843,841,0,761,764,846,843,0,764,766,848,846,0,766,768,850,848,0,768,769,851,850,0,769,771,853,851,0,771,773,855,853,0,773,775,857,855,0,775,777,859,857,0,777,779,861,859,0,779,782,865,861,0,782,787,869,865,0,787,790,872,869,0,790,792,874,872,0,792,796,878,874,0,796,799,881,878,0,799,806,889,881,0,806,810,892,889,0,810,812,894,892,0,812,813,896,894,0,813,815,898,896,0,815,817,900,898,0,817,820,902,900,0,820,819,901,902,0,819,818,899,901,0,818,816,897,899,0,816,814,895,897,0,814,811,893,895,0,811,809,891,893,0,809,802,884,891,0,802,789,870,884,0,789,784,866,870,0,784,785,867,866,0,785,793,875,867,0,793,795,877,875,0,795,798,880,877,0,798,801,883,880,0,801,804,886,883,0,804,807,888,886,0,807,808,890,888,0,808,805,887,890,0,805,803,885,887,0,803,800,882,885,0,800,797,879,882,0,797,794,876,879,0,794,791,873,876,0,791,788,871,873,0,788,786,868,871,0,786,783,864,868,0,783,781,863,864,0,781,780,862,863,0,780,778,860,862,0,778,776,858,860,0,776,774,856,858,0,774,772,854,856,0,772,770,852,854,0,770,767,849,852,0,767,765,847,849,0,765,763,845,847,0,763,762,844,845,0,762,760,842,844,0,760,758,840,842,0,758,756,838,840,0,756,754,836,838,0,754,751,833,836,0,751,749,831,833,0,749,747,829,831,0,747,746,828,829,0,746,744,826,828,0,744,741,823,826,0,741,740,822,823,0,822,821,903,904,0,821,824,906,903,0,824,825,907,906,0,825,827,909,907,0,827,830,912,909,0,830,832,914,912,0,832,834,916,914,0,834,835,917,916,0,835,837,919,917,0,837,839,921,919,0,839,841,923,921,0,841,843,925,923,0,843,846,928,925,0,846,848,930,928,0,848,850,932,930,0,850,851,933,932,0,851,853,935,933,0,853,855,937,935,0,855,857,939,937,0,857,859,941,939,0,859,861,943,941,0,861,865,948,943,0,865,869,951,948,0,869,872,954,951,0,872,874,957,954,0,874,878,960,957,0,878,881,963,960,0,881,889,972,963,0,889,892,974,972,0,892,894,976,974,0,894,896,978,976,0,896,898,980,978,0,898,900,982,980,0,900,902,984,982,0,902,901,983,984,0,901,899,981,983,0,899,897,979,981,0,897,895,977,979,0,895,893,975,977,0,893,891,973,975,0,891,884,966,973,0,884,870,952,966,0,870,866,946,952,0,866,867,949,946,0,867,875,956,949,0,875,877,959,956,0,877,880,962,959,0,880,883,964,962,0,883,886,968,964,0,886,888,970,968,0,888,890,971,970,0,890,887,969,971,0,887,885,967,969,0,885,882,965,967,0,882,879,961,965,0,879,876,958,961,0,876,873,955,958,0,873,871,953,955,0,871,868,950,953,0,868,864,947,950,0,864,863,945,947,0,863,862,944,945,0,862,860,942,944,0,860,858,940,942,0,858,856,938,940,0,856,854,936,938,0,854,852,934,936,0,852,849,931,934,0,849,847,929,931,0,847,845,927,929,0,845,844,926,927,0,844,842,924,926,0,842,840,922,924,0,840,838,920,922,0,838,836,918,920,0,836,833,915,918,0,833,831,913,915,0,831,829,911,913,0,829,828,910,911,0,828,826,908,910,0,826,823,905,908,0,823,822,904,905,0,904,903,985,986,0,903,906,988,985,0,906,907,989,988,0,907,909,991,989,0,909,912,994,991,0,912,914,996,994,0,914,916,998,996,0,916,917,1000,998,0,917,919,1001,1000,0,919,921,1003,1001,0,921,923,1005,1003,0,923,925,1008,1005,0,925,928,1010,1008,0,928,930,1012,1010,0,930,932,1014,1012,0,932,933,1015,1014,0,933,935,1017,1015,0,935,937,1019,1017,0,937,939,1021,1019,0,939,941,1023,1021,0,941,943,1025,1023,0,943,948,1031,1025,0,948,951,1033,1031,0,951,954,1036,1033,0,954,957,1039,1036,0,957,960,1042,1039,0,960,963,1048,1042,0,963,972,1055,1048,0,972,974,1056,1055,0,974,976,1058,1056,0,976,978,1060,1058,0,978,980,1062,1060,0,980,982,1064,1062,0,982,984,1066,1064,0,984,983,1065,1066,0,983,981,1063,1065,0,981,979,1061,1063,0,979,977,1059,1061,0,977,975,1057,1059,0,975,973,1054,1057,0,973,966,1045,1054,0,966,952,1034,1045,0,952,946,1028,1034,0,946,949,1029,1028,0,949,956,1038,1029,0,956,959,1040,1038,0,959,962,1043,1040,0,962,964,1046,1043,0,964,968,1049,1046,0,968,970,1052,1049,0,970,971,1053,1052,0,971,969,1051,1053,0,969,967,1050,1051,0,967,965,1047,1050,0,965,961,1044,1047,0,961,958,1041,1044,0,958,955,1037,1041,0,955,953,1035,1037,0,953,950,1032,1035,0,950,947,1030,1032,0,947,945,1027,1030,0,945,944,1026,1027,0,944,942,1024,1026,0,942,940,1022,1024,0,940,938,1020,1022,0,938,936,1018,1020,0,936,934,1016,1018,0,934,931,1013,1016,0,931,929,1011,1013,0,929,927,1009,1011,0,927,926,1007,1009,0,926,924,1006,1007,0,924,922,1004,1006,0,922,920,1002,1004,0,920,918,999,1002,0,918,915,997,999,0,915,913,995,997,0,913,911,993,995,0,911,910,992,993,0,910,908,990,992,0,908,905,987,990,0,905,904,986,987,0,986,985,1067,1068,0,985,988,1070,1067,0,988,989,1071,1070,0,989,991,1073,1071,0,991,994,1076,1073,0,994,996,1078,1076,0,996,998,1080,1078,0,998,1000,1082,1080,0,1000,1001,1083,1082,0,1001,1003,1085,1083,0,1003,1005,1087,1085,0,1005,1008,1090,1087,0,1008,1010,1092,1090,0,1010,1012,1094,1092,0,1012,1014,1096,1094,0,1014,1015,1097,1096,0,1015,1017,1099,1097,0,1017,1019,1101,1099,0,1019,1021,1103,1101,0,1021,1023,1105,1103,0,1023,1025,1107,1105,0,1025,1031,1113,1107,0,1031,1033,1116,1113,0,1033,1036,1118,1116,0,1036,1039,1121,1118,0,1039,1042,1125,1121,0,1042,1048,1130,1125,0,1048,1055,1137,1130,0,1055,1056,1139,1137,0,1056,1058,1140,1139,0,1058,1060,1142,1140,0,1060,1062,1144,1142,0,1062,1064,1146,1144,0,1064,1066,1148,1146,0,1066,1065,1147,1148,0,1065,1063,1145,1147,0,1063,1061,1143,1145,0,1061,1059,1141,1143,0,1059,1057,1138,1141,0,1057,1054,1136,1138,0,1054,1045,1127,1136,0,1045,1034,1115,1127,0,1034,1028,1110,1115,0,1028,1029,1111,1110,0,1029,1038,1119,1111,0,1038,1040,1122,1119,0,1040,1043,1124,1122,0,1043,1046,1128,1124,0,1046,1049,1131,1128,0,1049,1052,1134,1131,0,1052,1053,1135,1134,0,1053,1051,1133,1135,0,1051,1050,1132,1133,0,1050,1047,1129,1132,0,1047,1044,1126,1129,0,1044,1041,1123,1126,0,1041,1037,1120,1123,0,1037,1035,1117,1120,0,1035,1032,1114,1117,0,1032,1030,1112,1114,0,1030,1027,1109,1112,0,1027,1026,1108,1109,0,1026,1024,1106,1108,0,1024,1022,1104,1106,0,1022,1020,1102,1104,0,1020,1018,1100,1102,0,1018,1016,1098,1100,0,1016,1013,1095,1098,0,1013,1011,1093,1095,0,1011,1009,1091,1093,0,1009,1007,1089,1091,0,1007,1006,1088,1089,0,1006,1004,1086,1088,0,1004,1002,1084,1086,0,1002,999,1081,1084,0,999,997,1079,1081,0,997,995,1077,1079,0,995,993,1075,1077,0,993,992,1074,1075,0,992,990,1072,1074,0,990,987,1069,1072,0,987,986,1068,1069,0,1068,1067,1149,1150,0,1067,1070,1152,1149,0,1070,1071,1153,1152,0,1071,1073,1155,1153,0,1073,1076,1158,1155,0,1076,1078,1160,1158,0,1078,1080,1162,1160,0,1080,1082,1164,1162,0,1082,1083,1165,1164,0,1083,1085,1167,1165,0,1085,1087,1169,1167,0,1087,1090,1172,1169,0,1090,1092,1174,1172,0,1092,1094,1176,1174,0,1094,1096,1178,1176,0,1096,1097,1179,1178,0,1097,1099,1181,1179,0,1099,1101,1183,1181,0,1101,1103,1185,1183,0,1103,1105,1187,1185,0,1105,1107,1189,1187,0,1107,1113,1195,1189,0,1113,1116,1198,1195,0,1116,1118,1200,1198,0,1118,1121,1204,1200,0,1121,1125,1207,1204,0,1125,1130,1213,1207,0,1130,1137,1219,1213,0,1137,1139,1221,1219,0,1139,1140,1223,1221,0,1140,1142,1225,1223,0,1142,1144,1227,1225,0,1144,1146,1229,1227,0,1146,1148,1230,1229,0,1148,1147,1228,1230,0,1147,1145,1226,1228,0,1145,1143,1224,1226,0,1143,1141,1222,1224,0,1141,1138,1220,1222,0,1138,1136,1216,1220,0,1136,1127,1209,1216,0,1127,1115,1196,1209,0,1115,1110,1192,1196,0,1110,1111,1193,1192,0,1111,1119,1201,1193,0,1119,1122,1203,1201,0,1122,1124,1206,1203,0,1124,1128,1210,1206,0,1128,1131,1212,1210,0,1131,1134,1215,1212,0,1134,1135,1218,1215,0,1135,1133,1217,1218,0,1133,1132,1214,1217,0,1132,1129,1211,1214,0,1129,1126,1208,1211,0,1126,1123,1205,1208,0,1123,1120,1202,1205,0,1120,1117,1199,1202,0,1117,1114,1197,1199,0,1114,1112,1194,1197,0,1112,1109,1191,1194,0,1109,1108,1190,1191,0,1108,1106,1188,1190,0,1106,1104,1186,1188,0,1104,1102,1184,1186,0,1102,1100,1182,1184,0,1100,1098,1180,1182,0,1098,1095,1177,1180,0,1095,1093,1175,1177,0,1093,1091,1173,1175,0,1091,1089,1171,1173,0,1089,1088,1170,1171,0,1088,1086,1168,1170,0,1086,1084,1166,1168,0,1084,1081,1163,1166,0,1081,1079,1161,1163,0,1079,1077,1159,1161,0,1077,1075,1157,1159,0,1075,1074,1156,1157,0,1074,1072,1154,1156,0,1072,1069,1151,1154,0,1069,1068,1150,1151,0,1150,1149,1231,1232,0,1149,1152,1234,1231,0,1152,1153,1235,1234,0,1153,1155,1237,1235,0,1155,1158,1240,1237,0,1158,1160,1242,1240,0,1160,1162,1244,1242,0,1162,1164,1246,1244,0,1164,1165,1247,1246,0,1165,1167,1249,1247,0,1167,1169,1251,1249,0,1169,1172,1254,1251,0,1172,1174,1256,1254,0,1174,1176,1258,1256,0,1176,1178,1260,1258,0,1178,1179,1261,1260,0,1179,1181,1263,1261,0,1181,1183,1265,1263,0,1183,1185,1267,1265,0,1185,1187,1269,1267,0,1187,1189,1271,1269,0,1189,1195,1277,1271,0,1195,1198,1280,1277,0,1198,1200,1283,1280,0,1200,1204,1286,1283,0,1204,1207,1289,1286,0,1207,1213,1295,1289,0,1213,1219,1301,1295,0,1219,1221,1303,1301,0,1221,1223,1305,1303,0,1223,1225,1307,1305,0,1225,1227,1309,1307,0,1227,1229,1311,1309,0,1229,1230,1312,1311,0,1230,1228,1310,1312,0,1228,1226,1308,1310,0,1226,1224,1306,1308,0,1224,1222,1304,1306,0,1222,1220,1302,1304,0,1220,1216,1297,1302,0,1216,1209,1290,1297,0,1209,1196,1278,1290,0,1196,1192,1274,1278,0,1192,1193,1275,1274,0,1193,1201,1282,1275,0,1201,1203,1285,1282,0,1203,1206,1288,1285,0,1206,1210,1292,1288,0,1210,1212,1294,1292,0,1212,1215,1298,1294,0,1215,1218,1300,1298,0,1218,1217,1299,1300,0,1217,1214,1296,1299,0,1214,1211,1293,1296,0,1211,1208,1291,1293,0,1208,1205,1287,1291,0,1205,1202,1284,1287,0,1202,1199,1281,1284,0,1199,1197,1279,1281,0,1197,1194,1276,1279,0,1194,1191,1273,1276,0,1191,1190,1272,1273,0,1190,1188,1270,1272,0,1188,1186,1268,1270,0,1186,1184,1266,1268,0,1184,1182,1264,1266,0,1182,1180,1262,1264,0,1180,1177,1259,1262,0,1177,1175,1257,1259,0,1175,1173,1255,1257,0,1173,1171,1253,1255,0,1171,1170,1252,1253,0,1170,1168,1250,1252,0,1168,1166,1248,1250,0,1166,1163,1245,1248,0,1163,1161,1243,1245,0,1161,1159,1241,1243,0,1159,1157,1239,1241,0,1157,1156,1238,1239,0,1156,1154,1236,1238,0,1154,1151,1233,1236,0,1151,1150,1232,1233,0,1232,1231,1313,1314,0,1231,1234,1316,1313,0,1234,1235,1317,1316,0,1235,1237,1319,1317,0,1237,1240,1322,1319,0,1240,1242,1324,1322,0,1242,1244,1326,1324,0,1244,1246,1328,1326,0,1246,1247,1329,1328,0,1247,1249,1331,1329,0,1249,1251,1333,1331,0,1251,1254,1336,1333,0,1254,1256,1338,1336,0,1256,1258,1340,1338,0,1258,1260,1342,1340,0,1260,1261,1343,1342,0,1261,1263,1345,1343,0,1263,1265,1347,1345,0,1265,1267,1349,1347,0,1267,1269,1351,1349,0,1269,1271,1353,1351,0,1271,1277,1371,1353,0,1277,1280,1376,1371,0,1280,1283,1381,1376,0,1283,1286,1386,1381,0,1286,1289,1392,1386,0,1289,1295,1400,1392,0,1295,1301,1404,1400,0,1301,1303,1407,1404,0,1303,1305,1409,1407,0,1305,1307,1411,1409,0,1307,1309,1413,1411,0,1309,1311,1415,1413,0,1311,1312,1416,1415,0,1312,1310,1414,1416,0,1310,1308,1412,1414,0,1308,1306,1410,1412,0,1306,1304,1408,1410,0,1304,1302,1403,1408,0,1302,1297,1396,1403,0,1297,1290,1389,1396,0,1290,1278,1372,1389,0,1278,1274,1364,1372,0,1274,1275,1366,1364,0,1275,1282,1380,1366,0,1282,1285,1383,1380,0,1285,1288,1387,1383,0,1288,1292,1390,1387,0,1292,1294,1394,1390,0,1294,1298,1399,1394,0,1298,1300,1402,1399,0,1300,1299,1401,1402,0,1299,1296,1398,1401,0,1296,1293,1395,1398,0,1293,1291,1391,1395,0,1291,1287,1388,1391,0,1287,1284,1382,1388,0,1284,1281,1378,1382,0,1281,1279,1375,1378,0,1279,1276,1370,1375,0,1276,1273,1367,1370,0,1273,1272,1357,1367,0,1272,1270,1352,1357,0,1270,1268,1350,1352,0,1268,1266,1348,1350,0,1266,1264,1346,1348,0,1264,1262,1344,1346,0,1262,1259,1341,1344,0,1259,1257,1339,1341,0,1257,1255,1337,1339,0,1255,1253,1335,1337,0,1253,1252,1334,1335,0,1252,1250,1332,1334,0,1250,1248,1330,1332,0,1248,1245,1327,1330,0,1245,1243,1325,1327,0,1243,1241,1323,1325,0,1241,1239,1321,1323,0,1239,1238,1320,1321,0,1238,1236,1318,1320,0,1236,1233,1315,1318,0,1233,1232,1314,1315,0,1314,1313,1354,1355,0,1313,1316,1358,1354,0,1316,1317,1359,1358,0,1317,1319,1361,1359,0,1319,1322,1365,1361,0,1322,1324,1369,1365,0,1324,1326,1374,1369,0,1326,1328,1379,1374,0,1328,1329,1384,1379,0,1329,1331,1393,1384,0,1331,1333,1405,1393,0,1333,1336,1418,1405,0,1336,1338,1420,1418,0,1338,1340,1422,1420,0,1340,1342,1424,1422,0,1342,1343,1425,1424,0,1343,1345,1427,1425,0,1345,1347,1429,1427,0,1347,1349,1431,1429,0,1349,1351,1433,1431,0,1351,1353,1435,1433,0,1353,1371,1442,1435,0,1371,1376,1444,1442,0,1376,1381,1447,1444,0,1381,1386,1450,1447,0,1386,1392,1456,1450,0,1392,1400,1462,1456,0,1400,1404,1466,1462,0,1404,1407,1467,1466,0,1407,1409,1469,1467,0,1409,1411,1471,1469,0,1411,1413,1473,1471,0,1413,1415,1475,1473,0,1415,1416,1476,1475,0,1416,1414,1474,1476,0,1414,1412,1472,1474,0,1412,1410,1470,1472,0,1410,1408,1468,1470,0,1408,1403,1465,1468,0,1403,1396,1459,1465,0,1396,1389,1453,1459,0,1389,1372,1441,1453,0,1372,1364,1437,1441,0,1364,1366,1438,1437,0,1366,1380,1446,1438,0,1380,1383,1449,1446,0,1383,1387,1451,1449,0,1387,1390,1454,1451,0,1390,1394,1457,1454,0,1394,1399,1461,1457,0,1399,1402,1464,1461,0,1402,1401,1463,1464,0,1401,1398,1460,1463,0,1398,1395,1458,1460,0,1395,1391,1455,1458,0,1391,1388,1452,1455,0,1388,1382,1448,1452,0,1382,1378,1445,1448,0,1378,1375,1443,1445,0,1375,1370,1440,1443,0,1370,1367,1439,1440,0,1367,1357,1436,1439,0,1357,1352,1434,1436,0,1352,1350,1432,1434,0,1350,1348,1430,1432,0,1348,1346,1428,1430,0,1346,1344,1426,1428,0,1344,1341,1423,1426,0,1341,1339,1421,1423,0,1339,1337,1419,1421,0,1337,1335,1417,1419,0,1335,1334,1406,1417,0,1334,1332,1397,1406,0,1332,1330,1385,1397,0,1330,1327,1377,1385,0,1327,1325,1373,1377,0,1325,1323,1368,1373,0,1323,1321,1363,1368,0,1321,1320,1362,1363,0,1320,1318,1360,1362,0,1318,1315,1356,1360,0,1315,1314,1355,1356,0,1355,1354,1477,1478,0,1354,1358,1480,1477,0,1358,1359,1481,1480,0,1359,1361,1485,1481,0,1361,1365,1489,1485,0,1365,1369,1491,1489,0,1369,1374,1494,1491,0,1374,1379,1497,1494,0,1379,1384,1502,1497,0,1384,1393,1506,1502,0,1393,1405,1510,1506,0,1405,1418,1516,1510,0,1418,1420,1520,1516,0,1420,1422,1524,1520,0,1422,1424,1528,1524,0,1424,1425,1532,1528,0,1425,1427,1535,1532,0,1427,1429,1539,1535,0,1429,1431,1542,1539,0,1431,1433,1547,1542,0,1433,1435,1550,1547,0,1435,1442,1566,1550,0,1442,1444,1568,1566,0,1444,1447,1572,1568,0,1447,1450,1578,1572,0,1450,1456,1583,1578,0,1456,1462,1592,1583,0,1462,1466,1595,1592,0,1466,1467,1598,1595,0,1467,1469,1601,1598,0,1469,1471,1603,1601,0,1471,1473,1606,1603,0,1473,1475,1608,1606,0,1475,1476,1607,1608,0,1476,1474,1604,1607,0,1474,1472,1602,1604,0,1472,1470,1599,1602,0,1470,1468,1597,1599,0,1468,1465,1593,1597,0,1465,1459,1585,1593,0,1459,1453,1576,1585,0,1453,1441,1564,1576,0,1441,1437,1560,1564,0,1437,1438,1561,1560,0,1438,1446,1569,1561,0,1446,1449,1571,1569,0,1449,1451,1575,1571,0,1451,1454,1580,1575,0,1454,1457,1584,1580,0,1457,1461,1587,1584,0,1461,1464,1589,1587,0,1464,1463,1590,1589,0,1463,1460,1588,1590,0,1460,1458,1586,1588,0,1458,1455,1581,1586,0,1455,1452,1579,1581,0,1452,1448,1573,1579,0,1448,1445,1570,1573,0,1445,1443,1567,1570,0,1443,1440,1565,1567,0,1440,1439,1562,1565,0,1439,1436,1556,1562,0,1436,1434,1548,1556,0,1434,1432,1544,1548,0,1432,1430,1540,1544,0,1430,1428,1536,1540,0,1428,1426,1531,1536,0,1426,1423,1527,1531,0,1423,1421,1521,1527,0,1421,1419,1517,1521,0,1419,1417,1514,1517,0,1417,1406,1511,1514,0,1406,1397,1507,1511,0,1397,1385,1501,1507,0,1385,1377,1496,1501,0,1377,1373,1493,1496,0,1373,1368,1490,1493,0,1368,1363,1486,1490,0,1363,1362,1484,1486,0,1362,1360,1483,1484,0,1360,1356,1479,1483,0,1356,1355,1478,1479,0,1478,1477,1482,1487,0,1477,1480,1492,1482,0,1480,1481,1495,1492,0,1481,1485,1500,1495,0,1485,1489,1504,1500,0,1489,1491,1508,1504,0,1491,1494,1512,1508,0,1494,1497,1515,1512,0,1497,1502,1519,1515,0,1502,1506,1522,1519,0,1506,1510,1525,1522,0,1510,1516,1530,1525,0,1516,1520,1534,1530,0,1520,1524,1538,1534,0,1524,1528,1543,1538,0,1528,1532,1546,1543,0,1532,1535,1549,1546,0,1535,1539,1552,1549,0,1539,1542,1554,1552,0,1542,1547,1557,1554,0,1547,1550,1559,1557,0,1550,1566,1596,1559,0,1566,1568,1605,1596,0,1568,1572,1612,1605,0,1572,1578,1616,1612,0,1578,1583,1620,1616,0,1583,1592,1628,1620,0,1592,1595,1630,1628,0,1595,1598,1632,1630,0,1598,1601,1634,1632,0,1601,1603,1636,1634,0,1603,1606,1638,1636,0,1606,1608,1640,1638,0,1608,1607,1639,1640,0,1607,1604,1637,1639,0,1604,1602,1635,1637,0,1602,1599,1633,1635,0,1599,1597,1631,1633,0,1597,1593,1629,1631,0,1593,1585,1622,1629,0,1585,1576,1615,1622,0,1576,1564,1591,1615,0,1564,1560,1574,1591,0,1560,1561,1577,1574,0,1561,1569,1609,1577,0,1569,1571,1611,1609,0,1571,1575,1614,1611,0,1575,1580,1618,1614,0,1580,1584,1621,1618,0,1584,1587,1624,1621,0,1587,1589,1626,1624,0,1589,1590,1627,1626,0,1590,1588,1625,1627,0,1588,1586,1623,1625,0,1586,1581,1619,1623,0,1581,1579,1617,1619,0,1579,1573,1613,1617,0,1573,1570,1610,1613,0,1570,1567,1600,1610,0,1567,1565,1594,1600,0,1565,1562,1582,1594,0,1562,1556,1563,1582,0,1556,1548,1558,1563,0,1548,1544,1555,1558,0,1544,1540,1553,1555,0,1540,1536,1551,1553,0,1536,1531,1545,1551,0,1531,1527,1541,1545,0,1527,1521,1537,1541,0,1521,1517,1533,1537,0,1517,1514,1529,1533,0,1514,1511,1526,1529,0,1511,1507,1523,1526,0,1507,1501,1518,1523,0,1501,1496,1513,1518,0,1496,1493,1509,1513,0,1493,1490,1505,1509,0,1490,1486,1503,1505,0,1486,1484,1499,1503,0,1484,1483,1498,1499,0,1483,1479,1488,1498,0,1479,1478,1487,1488,0,1487,1482,1641,1642,0,1482,1492,1644,1641,0,1492,1495,1645,1644,0,1495,1500,1648,1645,0,1500,1504,1650,1648,0,1504,1508,1652,1650,0,1508,1512,1654,1652,0,1512,1515,1656,1654,0,1515,1519,1658,1656,0,1519,1522,1659,1658,0,1522,1525,1662,1659,0,1525,1530,1664,1662,0,1530,1534,1666,1664,0,1534,1538,1668,1666,0,1538,1543,1670,1668,0,1543,1546,1672,1670,0,1546,1549,1673,1672,0,1549,1552,1675,1673,0,1552,1554,1677,1675,0,1554,1557,1679,1677,0,1557,1559,1681,1679,0,1559,1596,1688,1681,0,1596,1605,1691,1688,0,1605,1612,1694,1691,0,1612,1616,1700,1694,0,1616,1620,1704,1700,0,1620,1628,1712,1704,0,1628,1630,1714,1712,0,1630,1632,1716,1714,0,1632,1634,1718,1716,0,1634,1636,1721,1718,0,1636,1638,1724,1721,0,1638,1640,1725,1724,0,1640,1639,1723,1725,0,1639,1637,1720,1723,0,1637,1635,1717,1720,0,1635,1633,1715,1717,0,1633,1631,1713,1715,0,1631,1629,1711,1713,0,1629,1622,1701,1711,0,1622,1615,1697,1701,0,1615,1591,1685,1697,0,1591,1574,1683,1685,0,1574,1577,1684,1683,0,1577,1609,1690,1684,0,1609,1611,1693,1690,0,1611,1614,1696,1693,0,1614,1618,1698,1696,0,1618,1621,1702,1698,0,1621,1624,1705,1702,0,1624,1626,1708,1705,0,1626,1627,1709,1708,0,1627,1625,1707,1709,0,1625,1623,1706,1707,0,1623,1619,1703,1706,0,1619,1617,1699,1703,0,1617,1613,1695,1699,0,1613,1610,1692,1695,0,1610,1600,1689,1692,0,1600,1594,1687,1689,0,1594,1582,1686,1687,0,1582,1563,1682,1686,0,1563,1558,1680,1682,0,1558,1555,1678,1680,0,1555,1553,1676,1678,0,1553,1551,1674,1676,0,1551,1545,1671,1674,0,1545,1541,1669,1671,0,1541,1537,1667,1669,0,1537,1533,1665,1667,0,1533,1529,1663,1665,0,1529,1526,1661,1663,0,1526,1523,1660,1661,0,1523,1518,1657,1660,0,1518,1513,1655,1657,0,1513,1509,1653,1655,0,1509,1505,1651,1653,0,1505,1503,1649,1651,0,1503,1499,1647,1649,0,1499,1498,1646,1647,0,1498,1488,1643,1646,0,1488,1487,1642,1643,0,1642,1641,1710,1719,0,1641,1644,1726,1710,0,1644,1645,1727,1726,0,1645,1648,1730,1727,0,1648,1650,1732,1730,0,1650,1652,1734,1732,0,1652,1654,1736,1734,0,1654,1656,1738,1736,0,1656,1658,1740,1738,0,1658,1659,1741,1740,0,1659,1662,1744,1741,0,1662,1664,1746,1744,0,1664,1666,1748,1746,0,1666,1668,1750,1748,0,1668,1670,1752,1750,0,1670,1672,1754,1752,0,1672,1673,1755,1754,0,1673,1675,1757,1755,0,1675,1677,1759,1757,0,1677,1679,1761,1759,0,1679,1681,1763,1761,0,1681,1688,1770,1763,0,1688,1691,1773,1770,0,1691,1694,1776,1773,0,1694,1700,1782,1776,0,1700,1704,1786,1782,0,1704,1712,1793,1786,0,1712,1714,1795,1793,0,1714,1716,1797,1795,0,1716,1718,1799,1797,0,1718,1721,1801,1799,0,1721,1724,1803,1801,0,1724,1725,1804,1803,0,1725,1723,1802,1804,0,1723,1720,1800,1802,0,1720,1717,1798,1800,0,1717,1715,1796,1798,0,1715,1713,1794,1796,0,1713,1711,1792,1794,0,1711,1701,1783,1792,0,1701,1697,1779,1783,0,1697,1685,1767,1779,0,1685,1683,1765,1767,0,1683,1684,1766,1765,0,1684,1690,1772,1766,0,1690,1693,1775,1772,0,1693,1696,1777,1775,0,1696,1698,1780,1777,0,1698,1702,1784,1780,0,1702,1705,1787,1784,0,1705,1708,1790,1787,0,1708,1709,1791,1790,0,1709,1707,1789,1791,0,1707,1706,1788,1789,0,1706,1703,1785,1788,0,1703,1699,1781,1785,0,1699,1695,1778,1781,0,1695,1692,1774,1778,0,1692,1689,1771,1774,0,1689,1687,1769,1771,0,1687,1686,1768,1769,0,1686,1682,1764,1768,0,1682,1680,1762,1764,0,1680,1678,1760,1762,0,1678,1676,1758,1760,0,1676,1674,1756,1758,0,1674,1671,1753,1756,0,1671,1669,1751,1753,0,1669,1667,1749,1751,0,1667,1665,1747,1749,0,1665,1663,1745,1747,0,1663,1661,1743,1745,0,1661,1660,1742,1743,0,1660,1657,1739,1742,0,1657,1655,1737,1739,0,1655,1653,1735,1737,0,1653,1651,1733,1735,0,1651,1649,1731,1733,0,1649,1647,1729,1731,0,1647,1646,1728,1729,0,1646,1643,1722,1728,0,1643,1642,1719,1722,0,1719,1710,1805,1806,0,1710,1726,1808,1805,0,1726,1727,1809,1808,0,1727,1730,1812,1809,0,1730,1732,1814,1812,0,1732,1734,1816,1814,0,1734,1736,1818,1816,0,1736,1738,1820,1818,0,1738,1740,1822,1820,0,1740,1741,1823,1822,0,1741,1744,1826,1823,0,1744,1746,1828,1826,0,1746,1748,1830,1828,0,1748,1750,1832,1830,0,1750,1752,1834,1832,0,1752,1754,1836,1834,0,1754,1755,1837,1836,0,1755,1757,1839,1837,0,1757,1759,1841,1839,0,1759,1761,1843,1841,0,1761,1763,1845,1843,0,1763,1770,1852,1845,0,1770,1773,1856,1852,0,1773,1776,1861,1856,0,1776,1782,1865,1861,0,1782,1786,1870,1865,0,1786,1793,1875,1870,0,1793,1795,1877,1875,0,1795,1797,1879,1877,0,1797,1799,1881,1879,0,1799,1801,1883,1881,0,1801,1803,1885,1883,0,1803,1804,1886,1885,0,1804,1802,1884,1886,0,1802,1800,1882,1884,0,1800,1798,1880,1882,0,1798,1796,1878,1880,0,1796,1794,1876,1878,0,1794,1792,1871,1876,0,1792,1783,1863,1871,0,1783,1779,1859,1863,0,1779,1767,1849,1859,0,1767,1765,1847,1849,0,1765,1766,1848,1847,0,1766,1772,1853,1848,0,1772,1775,1855,1853,0,1775,1777,1858,1855,0,1777,1780,1862,1858,0,1780,1784,1866,1862,0,1784,1787,1868,1866,0,1787,1790,1872,1868,0,1790,1791,1874,1872,0,1791,1789,1873,1874,0,1789,1788,1869,1873,0,1788,1785,1867,1869,0,1785,1781,1864,1867,0,1781,1778,1860,1864,0,1778,1774,1857,1860,0,1774,1771,1854,1857,0,1771,1769,1851,1854,0,1769,1768,1850,1851,0,1768,1764,1846,1850,0,1764,1762,1844,1846,0,1762,1760,1842,1844,0,1760,1758,1840,1842,0,1758,1756,1838,1840,0,1756,1753,1835,1838,0,1753,1751,1833,1835,0,1751,1749,1831,1833,0,1749,1747,1829,1831,0,1747,1745,1827,1829,0,1745,1743,1825,1827,0,1743,1742,1824,1825,0,1742,1739,1821,1824,0,1739,1737,1819,1821,0,1737,1735,1817,1819,0,1735,1733,1815,1817,0,1733,1731,1813,1815,0,1731,1729,1811,1813,0,1729,1728,1810,1811,0,1728,1722,1807,1810,0,1722,1719,1806,1807,0,1806,1805,1887,1888,0,1805,1808,1890,1887,0,1808,1809,1891,1890,0,1809,1812,1894,1891,0,1812,1814,1896,1894,0,1814,1816,1898,1896,0,1816,1818,1900,1898,0,1818,1820,1902,1900,0,1820,1822,1904,1902,0,1822,1823,1905,1904,0,1823,1826,1908,1905,0,1826,1828,1910,1908,0,1828,1830,1912,1910,0,1830,1832,1914,1912,0,1832,1834,1916,1914,0,1834,1836,1918,1916,0,1836,1837,1919,1918,0,1837,1839,1921,1919,0,1839,1841,1923,1921,0,1841,1843,1925,1923,0,1843,1845,1927,1925,0,1845,1852,1934,1927,0,1852,1856,1938,1934,0,1856,1861,1943,1938,0,1861,1865,1948,1943,0,1865,1870,1954,1948,0,1870,1875,1957,1954,0,1875,1877,1959,1957,0,1877,1879,1961,1959,0,1879,1881,1963,1961,0,1881,1883,1965,1963,0,1883,1885,1967,1965,0,1885,1886,1968,1967,0,1886,1884,1966,1968,0,1884,1882,1964,1966,0,1882,1880,1962,1964,0,1880,1878,1960,1962,0,1878,1876,1958,1960,0,1876,1871,1951,1958,0,1871,1863,1945,1951,0,1863,1859,1940,1945,0,1859,1849,1931,1940,0,1849,1847,1929,1931,0,1847,1848,1930,1929,0,1848,1853,1935,1930,0,1853,1855,1937,1935,0,1855,1858,1941,1937,0,1858,1862,1944,1941,0,1862,1866,1947,1944,0,1866,1868,1950,1947,0,1868,1872,1953,1950,0,1872,1874,1956,1953,0,1874,1873,1955,1956,0,1873,1869,1952,1955,0,1869,1867,1949,1952,0,1867,1864,1946,1949,0,1864,1860,1942,1946,0,1860,1857,1939,1942,0,1857,1854,1936,1939,0,1854,1851,1933,1936,0,1851,1850,1932,1933,0,1850,1846,1928,1932,0,1846,1844,1926,1928,0,1844,1842,1924,1926,0,1842,1840,1922,1924,0,1840,1838,1920,1922,0,1838,1835,1917,1920,0,1835,1833,1915,1917,0,1833,1831,1913,1915,0,1831,1829,1911,1913,0,1829,1827,1909,1911,0,1827,1825,1907,1909,0,1825,1824,1906,1907,0,1824,1821,1903,1906,0,1821,1819,1901,1903,0,1819,1817,1899,1901,0,1817,1815,1897,1899,0,1815,1813,1895,1897,0,1813,1811,1893,1895,0,1811,1810,1892,1893,0,1810,1807,1889,1892,0,1807,1806,1888,1889,0,1888,1887,1969,1970,0,1887,1890,1972,1969,0,1890,1891,1973,1972,0,1891,1894,1976,1973,0,1894,1896,1978,1976,0,1896,1898,1980,1978,0,1898,1900,1982,1980,0,1900,1902,1984,1982,0,1902,1904,1986,1984,0,1904,1905,1987,1986,0,1905,1908,1990,1987,0,1908,1910,1992,1990,0,1910,1912,1994,1992,0,1912,1914,1996,1994,0,1914,1916,1998,1996,0,1916,1918,2000,1998,0,1918,1919,2001,2000,0,1919,1921,2003,2001,0,1921,1923,2005,2003,0,1923,1925,2007,2005,0,1925,1927,2009,2007,0,1927,1934,2017,2009,0,1934,1938,2020,2017,0,1938,1943,2026,2020,0,1943,1948,2030,2026,0,1948,1954,2038,2030,0,1954,1957,2040,2038,0,1957,1959,2042,2040,0,1959,1961,2044,2042,0,1961,1963,2046,2044,0,1963,1965,2048,2046,0,1965,1967,2050,2048,0,1967,1968,2049,2050,0,1968,1966,2047,2049,0,1966,1964,2045,2047,0,1964,1962,2043,2045,0,1962,1960,2041,2043,0,1960,1958,2039,2041,0,1958,1951,2033,2039,0,1951,1945,2027,2033,0,1945,1940,2021,2027,0,1940,1931,2013,2021,0,1931,1929,2011,2013,0,1929,1930,2012,2011,0,1930,1935,2016,2012,0,1935,1937,2019,2016,0,1937,1941,2022,2019,0,1941,1944,2024,2022,0,1944,1947,2028,2024,0,1947,1950,2031,2028,0,1950,1953,2034,2031,0,1953,1956,2037,2034,0,1956,1955,2036,2037,0,1955,1952,2035,2036,0,1952,1949,2032,2035,0,1949,1946,2029,2032,0,1946,1942,2025,2029,0,1942,1939,2023,2025,0,1939,1936,2018,2023,0,1936,1933,2015,2018,0,1933,1932,2014,2015,0,1932,1928,2010,2014,0,1928,1926,2008,2010,0,1926,1924,2006,2008,0,1924,1922,2004,2006,0,1922,1920,2002,2004,0,1920,1917,1999,2002,0,1917,1915,1997,1999,0,1915,1913,1995,1997,0,1913,1911,1993,1995,0,1911,1909,1991,1993,0,1909,1907,1989,1991,0,1907,1906,1988,1989,0,1906,1903,1985,1988,0,1903,1901,1983,1985,0,1901,1899,1981,1983,0,1899,1897,1979,1981,0,1897,1895,1977,1979,0,1895,1893,1975,1977,0,1893,1892,1974,1975,0,1892,1889,1971,1974,0,1889,1888,1970,1971,0,1970,1969,2051,2052,0,1969,1972,2054,2051,0,1972,1973,2055,2054,0,1973,1976,2058,2055,0,1976,1978,2060,2058,0,1978,1980,2062,2060,0,1980,1982,2064,2062,0,1982,1984,2066,2064,0,1984,1986,2068,2066,0,1986,1987,2070,2068,0,1987,1990,2072,2070,0,1990,1992,2074,2072,0,1992,1994,2076,2074,0,1994,1996,2078,2076,0,1996,1998,2080,2078,0,1998,2000,2082,2080,0,2000,2001,2083,2082,0,2001,2003,2085,2083,0,2003,2005,2087,2085,0,2005,2007,2090,2087,0,2007,2009,2091,2090,0,2009,2017,2099,2091,0,2017,2020,2104,2099,0,2020,2026,2109,2104,0,2026,2030,2114,2109,0,2030,2038,2120,2114,0,2038,2040,2122,2120,0,2040,2042,2124,2122,0,2042,2044,2126,2124,0,2044,2046,2128,2126,0,2046,2048,2130,2128,0,2048,2050,2132,2130,0,2050,2049,2131,2132,0,2049,2047,2129,2131,0,2047,2045,2127,2129,0,2045,2043,2125,2127,0,2043,2041,2123,2125,0,2041,2039,2121,2123,0,2039,2033,2113,2121,0,2033,2027,2107,2113,0,2027,2021,2102,2107,0,2021,2013,2095,2102,0,2013,2011,2093,2095,0,2011,2012,2094,2093,0,2012,2016,2097,2094,0,2016,2019,2100,2097,0,2019,2022,2103,2100,0,2022,2024,2106,2103,0,2024,2028,2110,2106,0,2028,2031,2112,2110,0,2031,2034,2116,2112,0,2034,2037,2118,2116,0,2037,2036,2119,2118,0,2036,2035,2117,2119,0,2035,2032,2115,2117,0,2032,2029,2111,2115,0,2029,2025,2108,2111,0,2025,2023,2105,2108,0,2023,2018,2101,2105,0,2018,2015,2098,2101,0,2015,2014,2096,2098,0,2014,2010,2092,2096,0,2010,2008,2089,2092,0,2008,2006,2088,2089,0,2006,2004,2086,2088,0,2004,2002,2084,2086,0,2002,1999,2081,2084,0,1999,1997,2079,2081,0,1997,1995,2077,2079,0,1995,1993,2075,2077,0,1993,1991,2073,2075,0,1991,1989,2071,2073,0,1989,1988,2069,2071,0,1988,1985,2067,2069,0,1985,1983,2065,2067,0,1983,1981,2063,2065,0,1981,1979,2061,2063,0,1979,1977,2059,2061,0,1977,1975,2057,2059,0,1975,1974,2056,2057,0,1974,1971,2053,2056,0,1971,1970,2052,2053,0,2052,2051,2133,2134,0,2051,2054,2136,2133,0,2054,2055,2137,2136,0,2055,2058,2140,2137,0,2058,2060,2142,2140,0,2060,2062,2144,2142,0,2062,2064,2146,2144,0,2064,2066,2148,2146,0,2066,2068,2150,2148,0,2068,2070,2152,2150,0,2070,2072,2154,2152,0,2072,2074,2156,2154,0,2074,2076,2158,2156,0,2076,2078,2160,2158,0,2078,2080,2162,2160,0,2080,2082,2164,2162,0,2082,2083,2166,2164,0,2083,2085,2167,2166,0,2085,2087,2169,2167,0,2087,2090,2172,2169,0,2090,2091,2173,2172,0,2091,2099,2182,2173,0,2099,2104,2186,2182,0,2104,2109,2192,2186,0,2109,2114,2197,2192,0,2114,2120,2203,2197,0,2120,2122,2205,2203,0,2122,2124,2207,2205,0,2124,2126,2209,2207,0,2126,2128,2211,2209,0,2128,2130,2213,2211,0,2130,2132,2214,2213,0,2132,2131,2212,2214,0,2131,2129,2210,2212,0,2129,2127,2208,2210,0,2127,2125,2206,2208,0,2125,2123,2204,2206,0,2123,2121,2202,2204,0,2121,2113,2194,2202,0,2113,2107,2189,2194,0,2107,2102,2184,2189,0,2102,2095,2177,2184,0,2095,2093,2175,2177,0,2093,2094,2176,2175,0,2094,2097,2179,2176,0,2097,2100,2181,2179,0,2100,2103,2185,2181,0,2103,2106,2188,2185,0,2106,2110,2191,2188,0,2110,2112,2195,2191,0,2112,2116,2198,2195,0,2116,2118,2200,2198,0,2118,2119,2201,2200,0,2119,2117,2199,2201,0,2117,2115,2196,2199,0,2115,2111,2193,2196,0,2111,2108,2190,2193,0,2108,2105,2187,2190,0,2105,2101,2183,2187,0,2101,2098,2180,2183,0,2098,2096,2178,2180,0,2096,2092,2174,2178,0,2092,2089,2171,2174,0,2089,2088,2170,2171,0,2088,2086,2168,2170,0,2086,2084,2165,2168,0,2084,2081,2163,2165,0,2081,2079,2161,2163,0,2079,2077,2159,2161,0,2077,2075,2157,2159,0,2075,2073,2155,2157,0,2073,2071,2153,2155,0,2071,2069,2151,2153,0,2069,2067,2149,2151,0,2067,2065,2147,2149,0,2065,2063,2145,2147,0,2063,2061,2143,2145,0,2061,2059,2141,2143,0,2059,2057,2139,2141,0,2057,2056,2138,2139,0,2056,2053,2135,2138,0,2053,2052,2134,2135,0,2134,2133,2215,2216,0,2133,2136,2218,2215,0,2136,2137,2219,2218,0,2137,2140,2222,2219,0,2140,2142,2224,2222,0,2142,2144,2226,2224,0,2144,2146,2228,2226,0,2146,2148,2230,2228,0,2148,2150,2232,2230,0,2150,2152,2234,2232,0,2152,2154,2236,2234,0,2154,2156,2238,2236,0,2156,2158,2240,2238,0,2158,2160,2242,2240,0,2160,2162,2244,2242,0,2162,2164,2246,2244,0,2164,2166,2248,2246,0,2166,2167,2249,2248,0,2167,2169,2251,2249,0,2169,2172,2254,2251,0,2172,2173,2255,2254,0,2173,2182,2264,2255,0,2182,2186,2268,2264,0,2186,2192,2274,2268,0,2192,2197,2280,2274,0,2197,2203,2285,2280,0,2203,2205,2287,2285,0,2205,2207,2289,2287,0,2207,2209,2291,2289,0,2209,2211,2293,2291,0,2211,2213,2295,2293,0,2213,2214,2296,2295,0,2214,2212,2294,2296,0,2212,2210,2292,2294,0,2210,2208,2290,2292,0,2208,2206,2288,2290,0,2206,2204,2286,2288,0,2204,2202,2284,2286,0,2202,2194,2275,2284,0,2194,2189,2271,2275,0,2189,2184,2265,2271,0,2184,2177,2259,2265,0,2177,2175,2257,2259,0,2175,2176,2258,2257,0,2176,2179,2261,2258,0,2179,2181,2263,2261,0,2181,2185,2267,2263,0,2185,2188,2270,2267,0,2188,2191,2273,2270,0,2191,2195,2277,2273,0,2195,2198,2279,2277,0,2198,2200,2282,2279,0,2200,2201,2283,2282,0,2201,2199,2281,2283,0,2199,2196,2278,2281,0,2196,2193,2276,2278,0,2193,2190,2272,2276,0,2190,2187,2269,2272,0,2187,2183,2266,2269,0,2183,2180,2262,2266,0,2180,2178,2260,2262,0,2178,2174,2256,2260,0,2174,2171,2253,2256,0,2171,2170,2252,2253,0,2170,2168,2250,2252,0,2168,2165,2247,2250,0,2165,2163,2245,2247,0,2163,2161,2243,2245,0,2161,2159,2241,2243,0,2159,2157,2239,2241,0,2157,2155,2237,2239,0,2155,2153,2235,2237,0,2153,2151,2233,2235,0,2151,2149,2231,2233,0,2149,2147,2229,2231,0,2147,2145,2227,2229,0,2145,2143,2225,2227,0,2143,2141,2223,2225,0,2141,2139,2221,2223,0,2139,2138,2220,2221,0,2138,2135,2217,2220,0,2135,2134,2216,2217,0,2216,2215,2297,2298,0,2215,2218,2300,2297,0,2218,2219,2301,2300,0,2219,2222,2304,2301,0,2222,2224,2306,2304,0,2224,2226,2308,2306,0,2226,2228,2310,2308,0,2228,2230,2312,2310,0,2230,2232,2314,2312,0,2232,2234,2316,2314,0,2234,2236,2318,2316,0,2236,2238,2320,2318,0,2238,2240,2322,2320,0,2240,2242,2324,2322,0,2242,2244,2326,2324,0,2244,2246,2328,2326,0,2246,2248,2330,2328,0,2248,2249,2331,2330,0,2249,2251,2333,2331,0,2251,2254,2336,2333,0,2254,2255,2337,2336,0,2255,2264,2347,2337,0,2264,2268,2353,2347,0,2268,2274,2357,2353,0,2274,2280,2363,2357,0,2280,2285,2367,2363,0,2285,2287,2369,2367,0,2287,2289,2371,2369,0,2289,2291,2374,2371,0,2291,2293,2376,2374,0,2293,2295,2378,2376,0,2295,2296,2377,2378,0,2296,2294,2375,2377,0,2294,2292,2373,2375,0,2292,2290,2372,2373,0,2290,2288,2370,2372,0,2288,2286,2368,2370,0,2286,2284,2364,2368,0,2284,2275,2356,2364,0,2275,2271,2350,2356,0,2271,2265,2346,2350,0,2265,2259,2341,2346,0,2259,2257,2338,2341,0,2257,2258,2340,2338,0,2258,2261,2342,2340,0,2261,2263,2344,2342,0,2263,2267,2348,2344,0,2267,2270,2351,2348,0,2270,2273,2354,2351,0,2273,2277,2358,2354,0,2277,2279,2360,2358,0,2279,2282,2362,2360,0,2282,2283,2366,2362,0,2283,2281,2365,2366,0,2281,2278,2361,2365,0,2278,2276,2359,2361,0,2276,2272,2355,2359,0,2272,2269,2352,2355,0,2269,2266,2349,2352,0,2266,2262,2345,2349,0,2262,2260,2343,2345,0,2260,2256,2339,2343,0,2256,2253,2335,2339,0,2253,2252,2334,2335,0,2252,2250,2332,2334,0,2250,2247,2329,2332,0,2247,2245,2327,2329,0,2245,2243,2325,2327,0,2243,2241,2323,2325,0,2241,2239,2321,2323,0,2239,2237,2319,2321,0,2237,2235,2317,2319,0,2235,2233,2315,2317,0,2233,2231,2313,2315,0,2231,2229,2311,2313,0,2229,2227,2309,2311,0,2227,2225,2307,2309,0,2225,2223,2305,2307,0,2223,2221,2303,2305,0,2221,2220,2302,2303,0,2220,2217,2299,2302,0,2217,2216,2298,2299,0,2298,2297,2379,2380,0,2297,2300,2382,2379,0,2300,2301,2383,2382,0,2301,2304,2386,2383,0,2304,2306,2388,2386,0,2306,2308,2390,2388,0,2308,2310,2392,2390,0,2310,2312,2394,2392,0,2312,2314,2396,2394,0,2314,2316,2398,2396,0,2316,2318,2400,2398,0,2318,2320,2402,2400,0,2320,2322,2404,2402,0,2322,2324,2406,2404,0,2324,2326,2408,2406,0,2326,2328,2410,2408,0,2328,2330,2412,2410,0,2330,2331,2414,2412,0,2331,2333,2415,2414,0,2333,2336,2418,2415,0,2336,2337,2419,2418,0,2337,2347,2430,2419,0,2347,2353,2435,2430,0,2353,2357,2440,2435,0,2357,2363,2448,2440,0,2363,2367,2450,2448,0,2367,2369,2452,2450,0,2369,2371,2454,2452,0,2371,2374,2456,2454,0,2374,2376,2458,2456,0,2376,2378,2460,2458,0,2378,2377,2459,2460,0,2377,2375,2457,2459,0,2375,2373,2455,2457,0,2373,2372,2453,2455,0,2372,2370,2451,2453,0,2370,2368,2449,2451,0,2368,2364,2443,2449,0,2364,2356,2437,2443,0,2356,2350,2432,2437,0,2350,2346,2427,2432,0,2346,2341,2423,2427,0,2341,2338,2420,2423,0,2338,2340,2421,2420,0,2340,2342,2424,2421,0,2342,2344,2426,2424,0,2344,2348,2429,2426,0,2348,2351,2433,2429,0,2351,2354,2436,2433,0,2354,2358,2439,2436,0,2358,2360,2442,2439,0,2360,2362,2445,2442,0,2362,2366,2447,2445,0,2366,2365,2446,2447,0,2365,2361,2444,2446,0,2361,2359,2441,2444,0,2359,2355,2438,2441,0,2355,2352,2434,2438,0,2352,2349,2431,2434,0,2349,2345,2428,2431,0,2345,2343,2425,2428,0,2343,2339,2422,2425,0,2339,2335,2417,2422,0,2335,2334,2416,2417,0,2334,2332,2413,2416,0,2332,2329,2411,2413,0,2329,2327,2409,2411,0,2327,2325,2407,2409,0,2325,2323,2405,2407,0,2323,2321,2403,2405,0,2321,2319,2401,2403,0,2319,2317,2399,2401,0,2317,2315,2397,2399,0,2315,2313,2395,2397,0,2313,2311,2393,2395,0,2311,2309,2391,2393,0,2309,2307,2389,2391,0,2307,2305,2387,2389,0,2305,2303,2385,2387,0,2303,2302,2384,2385,0,2302,2299,2381,2384,0,2299,2298,2380,2381,0,2380,2379,2461,2462,0,2379,2382,2464,2461,0,2382,2383,2465,2464,0,2383,2386,2468,2465,0,2386,2388,2470,2468,0,2388,2390,2472,2470,0,2390,2392,2474,2472,0,2392,2394,2476,2474,0,2394,2396,2478,2476,0,2396,2398,2480,2478,0,2398,2400,2482,2480,0,2400,2402,2484,2482,0,2402,2404,2486,2484,0,2404,2406,2488,2486,0,2406,2408,2490,2488,0,2408,2410,2492,2490,0,2410,2412,2494,2492,0,2412,2414,2496,2494,0,2414,2415,2497,2496,0,2415,2418,2500,2497,0,2418,2419,2501,2500,0,2419,2430,2512,2501,0,2430,2435,2518,2512,0,2435,2440,2524,2518,0,2440,2448,2530,2524,0,2448,2450,2532,2530,0,2450,2452,2534,2532,0,2452,2454,2536,2534,0,2454,2456,2538,2536,0,2456,2458,2540,2538,0,2458,2460,2542,2540,0,2460,2459,2541,2542,0,2459,2457,2539,2541,0,2457,2455,2537,2539,0,2455,2453,2535,2537,0,2453,2451,2533,2535,0,2451,2449,2531,2533,0,2449,2443,2525,2531,0,2443,2437,2519,2525,0,2437,2432,2513,2519,0,2432,2427,2509,2513,0,2427,2423,2505,2509,0,2423,2420,2502,2505,0,2420,2421,2503,2502,0,2421,2424,2506,2503,0,2424,2426,2508,2506,0,2426,2429,2511,2508,0,2429,2433,2515,2511,0,2433,2436,2517,2515,0,2436,2439,2521,2517,0,2439,2442,2523,2521,0,2442,2445,2527,2523,0,2445,2447,2528,2527,0,2447,2446,2529,2528,0,2446,2444,2526,2529,0,2444,2441,2522,2526,0,2441,2438,2520,2522,0,2438,2434,2516,2520,0,2434,2431,2514,2516,0,2431,2428,2510,2514,0,2428,2425,2507,2510,0,2425,2422,2504,2507,0,2422,2417,2499,2504,0,2417,2416,2498,2499,0,2416,2413,2495,2498,0,2413,2411,2493,2495,0,2411,2409,2491,2493,0,2409,2407,2489,2491,0,2407,2405,2487,2489,0,2405,2403,2485,2487,0,2403,2401,2483,2485,0,2401,2399,2481,2483,0,2399,2397,2479,2481,0,2397,2395,2477,2479,0,2395,2393,2475,2477,0,2393,2391,2473,2475,0,2391,2389,2471,2473,0,2389,2387,2469,2471,0,2387,2385,2467,2469,0,2385,2384,2466,2467,0,2384,2381,2463,2466,0,2381,2380,2462,2463,0,2462,2461,2543,2544,0,2461,2464,2546,2543,0,2464,2465,2547,2546,0,2465,2468,2550,2547,0,2468,2470,2552,2550,0,2470,2472,2554,2552,0,2472,2474,2556,2554,0,2474,2476,2558,2556,0,2476,2478,2560,2558,0,2478,2480,2562,2560,0,2480,2482,2564,2562,0,2482,2484,2566,2564,0,2484,2486,2568,2566,0,2486,2488,2570,2568,0,2488,2490,2572,2570,0,2490,2492,2574,2572,0,2492,2494,2576,2574,0,2494,2496,2578,2576,0,2496,2497,2580,2578,0,2497,2500,2582,2580,0,2500,2501,2583,2582,0,2501,2512,2596,2583,0,2512,2518,2601,2596,0,2518,2524,2608,2601,0,2524,2530,2613,2608,0,2530,2532,2615,2613,0,2532,2534,2617,2615,0,2534,2536,2619,2617,0,2536,2538,2621,2619,0,2538,2540,2623,2621,0,2540,2542,2624,2623,0,2542,2541,2622,2624,0,2541,2539,2620,2622,0,2539,2537,2618,2620,0,2537,2535,2616,2618,0,2535,2533,2614,2616,0,2533,2531,2612,2614,0,2531,2525,2604,2612,0,2525,2519,2599,2604,0,2519,2513,2594,2599,0,2513,2509,2590,2594,0,2509,2505,2586,2590,0,2505,2502,2584,2586,0,2502,2503,2585,2584,0,2503,2506,2588,2585,0,2506,2508,2589,2588,0,2508,2511,2592,2589,0,2511,2515,2595,2592,0,2515,2517,2598,2595,0,2517,2521,2602,2598,0,2521,2523,2605,2602,0,2523,2527,2607,2605,0,2527,2528,2610,2607,0,2528,2529,2611,2610,0,2529,2526,2609,2611,0,2526,2522,2606,2609,0,2522,2520,2603,2606,0,2520,2516,2600,2603,0,2516,2514,2597,2600,0,2514,2510,2593,2597,0,2510,2507,2591,2593,0,2507,2504,2587,2591,0,2504,2499,2581,2587,0,2499,2498,2579,2581,0,2498,2495,2577,2579,0,2495,2493,2575,2577,0,2493,2491,2573,2575,0,2491,2489,2571,2573,0,2489,2487,2569,2571,0,2487,2485,2567,2569,0,2485,2483,2565,2567,0,2483,2481,2563,2565,0,2481,2479,2561,2563,0,2479,2477,2559,2561,0,2477,2475,2557,2559,0,2475,2473,2555,2557,0,2473,2471,2553,2555,0,2471,2469,2551,2553,0,2469,2467,2549,2551,0,2467,2466,2548,2549,0,2466,2463,2545,2548,0,2463,2462,2544,2545,0,2544,2543,2625,2626,0,2543,2546,2628,2625,0,2546,2547,2629,2628,0,2547,2550,2632,2629,0,2550,2552,2634,2632,0,2552,2554,2636,2634,0,2554,2556,2638,2636,0,2556,2558,2640,2638,0,2558,2560,2642,2640,0,2560,2562,2644,2642,0,2562,2564,2646,2644,0,2564,2566,2648,2646,0,2566,2568,2650,2648,0,2568,2570,2652,2650,0,2570,2572,2654,2652,0,2572,2574,2656,2654,0,2574,2576,2658,2656,0,2576,2578,2660,2658,0,2578,2580,2662,2660,0,2580,2582,2664,2662,0,2582,2583,2665,2664,0,2583,2596,2678,2665,0,2596,2601,2684,2678,0,2601,2608,2690,2684,0,2608,2613,2695,2690,0,2613,2615,2697,2695,0,2615,2617,2699,2697,0,2617,2619,2701,2699,0,2619,2621,2703,2701,0,2621,2623,2705,2703,0,2623,2624,2706,2705,0,2624,2622,2704,2706,0,2622,2620,2702,2704,0,2620,2618,2700,2702,0,2618,2616,2698,2700,0,2616,2614,2696,2698,0,2614,2612,2694,2696,0,2612,2604,2686,2694,0,2604,2599,2681,2686,0,2599,2594,2676,2681,0,2594,2590,2672,2676,0,2590,2586,2668,2672,0,2586,2584,2666,2668,0,2584,2585,2667,2666,0,2585,2588,2670,2667,0,2588,2589,2671,2670,0,2589,2592,2674,2671,0,2592,2595,2677,2674,0,2595,2598,2680,2677,0,2598,2602,2683,2680,0,2602,2605,2687,2683,0,2605,2607,2689,2687,0,2607,2610,2692,2689,0,2610,2611,2693,2692,0,2611,2609,2691,2693,0,2609,2606,2688,2691,0,2606,2603,2685,2688,0,2603,2600,2682,2685,0,2600,2597,2679,2682,0,2597,2593,2675,2679,0,2593,2591,2673,2675,0,2591,2587,2669,2673,0,2587,2581,2663,2669,0,2581,2579,2661,2663,0,2579,2577,2659,2661,0,2577,2575,2657,2659,0,2575,2573,2655,2657,0,2573,2571,2653,2655,0,2571,2569,2651,2653,0,2569,2567,2649,2651,0,2567,2565,2647,2649,0,2565,2563,2645,2647,0,2563,2561,2643,2645,0,2561,2559,2641,2643,0,2559,2557,2639,2641,0,2557,2555,2637,2639,0,2555,2553,2635,2637,0,2553,2551,2633,2635,0,2551,2549,2631,2633,0,2549,2548,2630,2631,0,2548,2545,2627,2630,0,2545,2544,2626,2627,0,2626,2625,2707,2708,0,2625,2628,2711,2707,0,2628,2629,2713,2711,0,2629,2632,2717,2713,0,2632,2634,2719,2717,0,2634,2636,2722,2719,0,2636,2638,2727,2722,0,2638,2640,2731,2727,0,2640,2642,2735,2731,0,2642,2644,2739,2735,0,2644,2646,2743,2739,0,2646,2648,2747,2743,0,2648,2650,2750,2747,0,2650,2652,2755,2750,0,2652,2654,2759,2755,0,2654,2656,2763,2759,0,2656,2658,2767,2763,0,2658,2660,2770,2767,0,2660,2662,2774,2770,0,2662,2664,2779,2774,0,2664,2665,2783,2779,0,2665,2678,2808,2783,0,2678,2684,2814,2808,0,2684,2690,2824,2814,0,2690,2695,2826,2824,0,2695,2697,2829,2826,0,2697,2699,2833,2829,0,2699,2701,2836,2833,0,2701,2703,2838,2836,0,2703,2705,2840,2838,0,2705,2706,2839,2840,0,2706,2704,2837,2839,0,2704,2702,2834,2837,0,2702,2700,2830,2834,0,2700,2698,2827,2830,0,2698,2696,2825,2827,0,2696,2694,2817,2825,0,2694,2686,2812,2817,0,2686,2681,2805,2812,0,2681,2676,2801,2805,0,2676,2672,2798,2801,0,2672,2668,2784,2798,0,2668,2666,2778,2784,0,2666,2667,2780,2778,0,2667,2670,2793,2780,0,2670,2671,2797,2793,0,2671,2674,2799,2797,0,2674,2677,2802,2799,0,2677,2680,2806,2802,0,2680,2683,2809,2806,0,2683,2687,2813,2809,0,2687,2689,2816,2813,0,2689,2692,2819,2816,0,2692,2693,2822,2819,0,2693,2691,2821,2822,0,2691,2688,2818,2821,0,2688,2685,2815,2818,0,2685,2682,2811,2815,0,2682,2679,2807,2811,0,2679,2675,2804,2807,0,2675,2673,2800,2804,0,2673,2669,2789,2800,0,2669,2663,2776,2789,0,2663,2661,2772,2776,0,2661,2659,2769,2772,0,2659,2657,2765,2769,0,2657,2655,2761,2765,0,2655,2653,2757,2761,0,2653,2651,2752,2757,0,2651,2649,2749,2752,0,2649,2647,2745,2749,0,2647,2645,2741,2745,0,2645,2643,2738,2741,0,2643,2641,2733,2738,0,2641,2639,2729,2733,0,2639,2637,2723,2729,0,2637,2635,2720,2723,0,2635,2633,2718,2720,0,2633,2631,2716,2718,0,2631,2630,2714,2716,0,2630,2627,2709,2714,0,2627,2626,2708,2709,0,2708,2707,2710,2712,0,2707,2711,2721,2710,0,2711,2713,2724,2721,0,2713,2717,2728,2724,0,2717,2719,2732,2728,0,2719,2722,2736,2732,0,2722,2727,2740,2736,0,2727,2731,2744,2740,0,2731,2735,2748,2744,0,2735,2739,2753,2748,0,2739,2743,2756,2753,0,2743,2747,2760,2756,0,2747,2750,2764,2760,0,2750,2755,2768,2764,0,2755,2759,2773,2768,0,2759,2763,2777,2773,0,2763,2767,2782,2777,0,2767,2770,2786,2782,0,2770,2774,2788,2786,0,2774,2779,2792,2788,0,2779,2783,2795,2792,0,2783,2808,2845,2795,0,2808,2814,2850,2845,0,2814,2824,2858,2850,0,2824,2826,2860,2858,0,2826,2829,2862,2860,0,2829,2833,2864,2862,0,2833,2836,2866,2864,0,2836,2838,2868,2866,0,2838,2840,2870,2868,0,2840,2839,2869,2870,0,2839,2837,2867,2869,0,2837,2834,2865,2867,0,2834,2830,2863,2865,0,2830,2827,2861,2863,0,2827,2825,2859,2861,0,2825,2817,2852,2859,0,2817,2812,2848,2852,0,2812,2805,2842,2848,0,2805,2801,2832,2842,0,2801,2798,2823,2832,0,2798,2784,2796,2823,0,2784,2778,2791,2796,0,2778,2780,2794,2791,0,2780,2793,2810,2794,0,2793,2797,2820,2810,0,2797,2799,2828,2820,0,2799,2802,2835,2828,0,2802,2806,2843,2835,0,2806,2809,2846,2843,0,2809,2813,2849,2846,0,2813,2816,2853,2849,0,2816,2819,2855,2853,0,2819,2822,2857,2855,0,2822,2821,2856,2857,0,2821,2818,2854,2856,0,2818,2815,2851,2854,0,2815,2811,2847,2851,0,2811,2807,2844,2847,0,2807,2804,2841,2844,0,2804,2800,2831,2841,0,2800,2789,2803,2831,0,2789,2776,2790,2803,0,2776,2772,2787,2790,0,2772,2769,2785,2787,0,2769,2765,2781,2785,0,2765,2761,2775,2781,0,2761,2757,2771,2775,0,2757,2752,2766,2771,0,2752,2749,2762,2766,0,2749,2745,2758,2762,0,2745,2741,2754,2758,0,2741,2738,2751,2754,0,2738,2733,2746,2751,0,2733,2729,2742,2746,0,2729,2723,2737,2742,0,2723,2720,2734,2737,0,2720,2718,2730,2734,0,2718,2716,2726,2730,0,2716,2714,2725,2726,0,2714,2709,2715,2725,0,2709,2708,2712,2715,0,2712,2710,2871,2872,0,2710,2721,2874,2871,0,2721,2724,2876,2874,0,2724,2728,2878,2876,0,2728,2732,2880,2878,0,2732,2736,2882,2880,0,2736,2740,2884,2882,0,2740,2744,2886,2884,0,2744,2748,2888,2886,0,2748,2753,2890,2888,0,2753,2756,2892,2890,0,2756,2760,2894,2892,0,2760,2764,2896,2894,0,2764,2768,2898,2896,0,2768,2773,2900,2898,0,2773,2777,2902,2900,0,2777,2782,2904,2902,0,2782,2786,2906,2904,0,2786,2788,2909,2906,0,2788,2792,2913,2909,0,2792,2795,2914,2913,0,2795,2845,2929,2914,0,2845,2850,2935,2929,0,2850,2858,2941,2935,0,2858,2860,2943,2941,0,2860,2862,2945,2943,0,2862,2864,2947,2945,0,2864,2866,2949,2947,0,2866,2868,2951,2949,0,2868,2870,2952,2951,0,2870,2869,2950,2952,0,2869,2867,2948,2950,0,2867,2865,2946,2948,0,2865,2863,2944,2946,0,2863,2861,2942,2944,0,2861,2859,2940,2942,0,2859,2852,2932,2940,0,2852,2848,2927,2932,0,2848,2842,2923,2927,0,2842,2832,2920,2923,0,2832,2823,2918,2920,0,2823,2796,2912,2918,0,2796,2791,2907,2912,0,2791,2794,2910,2907,0,2794,2810,2916,2910,0,2810,2820,2917,2916,0,2820,2828,2919,2917,0,2828,2835,2921,2919,0,2835,2843,2924,2921,0,2843,2846,2926,2924,0,2846,2849,2930,2926,0,2849,2853,2933,2930,0,2853,2855,2936,2933,0,2855,2857,2938,2936,0,2857,2856,2939,2938,0,2856,2854,2937,2939,0,2854,2851,2934,2937,0,2851,2847,2931,2934,0,2847,2844,2928,2931,0,2844,2841,2925,2928,0,2841,2831,2922,2925,0,2831,2803,2915,2922,0,2803,2790,2911,2915,0,2790,2787,2908,2911,0,2787,2785,2905,2908,0,2785,2781,2903,2905,0,2781,2775,2901,2903,0,2775,2771,2899,2901,0,2771,2766,2897,2899,0,2766,2762,2895,2897,0,2762,2758,2893,2895,0,2758,2754,2891,2893,0,2754,2751,2889,2891,0,2751,2746,2887,2889,0,2746,2742,2885,2887,0,2742,2737,2883,2885,0,2737,2734,2881,2883,0,2734,2730,2879,2881,0,2730,2726,2877,2879,0,2726,2725,2875,2877,0,2725,2715,2873,2875,0,2715,2712,2872,2873,0,2872,2871,2953,2954,0,2871,2874,2956,2953,0,2874,2876,2958,2956,0,2876,2878,2960,2958,0,2878,2880,2962,2960,0,2880,2882,2964,2962,0,2882,2884,2966,2964,0,2884,2886,2968,2966,0,2886,2888,2970,2968,0,2888,2890,2972,2970,0,2890,2892,2974,2972,0,2892,2894,2976,2974,0,2894,2896,2978,2976,0,2896,2898,2980,2978,0,2898,2900,2982,2980,0,2900,2902,2984,2982,0,2902,2904,2986,2984,0,2904,2906,2988,2986,0,2906,2909,2992,2988,0,2909,2913,2995,2992,0,2913,2914,2996,2995,0,2914,2929,3011,2996,0,2929,2935,3018,3011,0,2935,2941,3023,3018,0,2941,2943,3025,3023,0,2943,2945,3027,3025,0,2945,2947,3029,3027,0,2947,2949,3031,3029,0,2949,2951,3033,3031,0,2951,2952,3034,3033,0,2952,2950,3032,3034,0,2950,2948,3030,3032,0,2948,2946,3028,3030,0,2946,2944,3026,3028,0,2944,2942,3024,3026,0,2942,2940,3021,3024,0,2940,2932,3014,3021,0,2932,2927,3009,3014,0,2927,2923,3005,3009,0,2923,2920,3002,3005,0,2920,2918,3000,3002,0,2918,2912,2994,3000,0,2912,2907,2989,2994,0,2907,2910,2991,2989,0,2910,2916,2998,2991,0,2916,2917,2999,2998,0,2917,2919,3001,2999,0,2919,2921,3003,3001,0,2921,2924,3006,3003,0,2924,2926,3008,3006,0,2926,2930,3012,3008,0,2930,2933,3015,3012,0,2933,2936,3017,3015,0,2936,2938,3020,3017,0,2938,2939,3022,3020,0,2939,2937,3019,3022,0,2937,2934,3016,3019,0,2934,2931,3013,3016,0,2931,2928,3010,3013,0,2928,2925,3007,3010,0,2925,2922,3004,3007,0,2922,2915,2997,3004,0,2915,2911,2993,2997,0,2911,2908,2990,2993,0,2908,2905,2987,2990,0,2905,2903,2985,2987,0,2903,2901,2983,2985,0,2901,2899,2981,2983,0,2899,2897,2979,2981,0,2897,2895,2977,2979,0,2895,2893,2975,2977,0,2893,2891,2973,2975,0,2891,2889,2971,2973,0,2889,2887,2969,2971,0,2887,2885,2967,2969,0,2885,2883,2965,2967,0,2883,2881,2963,2965,0,2881,2879,2961,2963,0,2879,2877,2959,2961,0,2877,2875,2957,2959,0,2875,2873,2955,2957,0,2873,2872,2954,2955,0,2954,2953,3035,3036,0,2953,2956,3038,3035,0,2956,2958,3040,3038,0,2958,2960,3042,3040,0,2960,2962,3045,3042,0,2962,2964,3046,3045,0,2964,2966,3048,3046,0,2966,2968,3050,3048,0,2968,2970,3052,3050,0,2970,2972,3054,3052,0,2972,2974,3056,3054,0,2974,2976,3058,3056,0,2976,2978,3060,3058,0,2978,2980,3062,3060,0,2980,2982,3064,3062,0,2982,2984,3066,3064,0,2984,2986,3068,3066,0,2986,2988,3072,3068,0,2988,2992,3075,3072,0,2992,2995,3077,3075,0,2995,2996,3078,3077,0,2996,3011,3095,3078,0,3011,3018,3104,3095,0,3018,3023,3106,3104,0,3023,3025,3108,3106,0,3025,3027,3110,3108,0,3027,3029,3112,3110,0,3029,3031,3114,3112,0,3031,3033,3116,3114,0,3033,3034,3115,3116,0,3034,3032,3113,3115,0,3032,3030,3111,3113,0,3030,3028,3109,3111,0,3028,3026,3107,3109,0,3026,3024,3105,3107,0,3024,3021,3098,3105,0,3021,3014,3094,3098,0,3014,3009,3089,3094,0,3009,3005,3086,3089,0,3005,3002,3084,3086,0,3002,3000,3082,3084,0,3000,2994,3073,3082,0,2994,2989,3069,3073,0,2989,2991,3070,3069,0,2991,2998,3079,3070,0,2998,2999,3081,3079,0,2999,3001,3083,3081,0,3001,3003,3085,3083,0,3003,3006,3087,3085,0,3006,3008,3090,3087,0,3008,3012,3093,3090,0,3012,3015,3097,3093,0,3015,3017,3099,3097,0,3017,3020,3101,3099,0,3020,3022,3103,3101,0,3022,3019,3102,3103,0,3019,3016,3100,3102,0,3016,3013,3096,3100,0,3013,3010,3092,3096,0,3010,3007,3091,3092,0,3007,3004,3088,3091,0,3004,2997,3080,3088,0,2997,2993,3076,3080,0,2993,2990,3074,3076,0,2990,2987,3071,3074,0,2987,2985,3067,3071,0,2985,2983,3065,3067,0,2983,2981,3063,3065,0,2981,2979,3061,3063,0,2979,2977,3059,3061,0,2977,2975,3057,3059,0,2975,2973,3055,3057,0,2973,2971,3053,3055,0,2971,2969,3051,3053,0,2969,2967,3049,3051,0,2967,2965,3047,3049,0,2965,2963,3044,3047,0,2963,2961,3043,3044,0,2961,2959,3041,3043,0,2959,2957,3039,3041,0,2957,2955,3037,3039,0,2955,2954,3036,3037,0,3036,3035,3117,3118,0,3035,3038,3120,3117,0,3038,3040,3122,3120,0,3040,3042,3124,3122,0,3042,3045,3127,3124,0,3045,3046,3128,3127,0,3046,3048,3130,3128,0,3048,3050,3132,3130,0,3050,3052,3134,3132,0,3052,3054,3136,3134,0,3054,3056,3138,3136,0,3056,3058,3140,3138,0,3058,3060,3142,3140,0,3060,3062,3144,3142,0,3062,3064,3146,3144,0,3064,3066,3148,3146,0,3066,3068,3151,3148,0,3068,3072,3155,3151,0,3072,3075,3157,3155,0,3075,3077,3159,3157,0,3077,3078,3160,3159,0,3078,3095,3178,3160,0,3095,3104,3187,3178,0,3104,3106,3189,3187,0,3106,3108,3191,3189,0,3108,3110,3193,3191,0,3110,3112,3195,3193,0,3112,3114,3197,3195,0,3114,3116,3198,3197,0,3116,3115,3196,3198,0,3115,3113,3194,3196,0,3113,3111,3192,3194,0,3111,3109,3190,3192,0,3109,3107,3188,3190,0,3107,3105,3186,3188,0,3105,3098,3180,3186,0,3098,3094,3174,3180,0,3094,3089,3171,3174,0,3089,3086,3168,3171,0,3086,3084,3166,3168,0,3084,3082,3164,3166,0,3082,3073,3154,3164,0,3073,3069,3150,3154,0,3069,3070,3152,3150,0,3070,3079,3161,3152,0,3079,3081,3163,3161,0,3081,3083,3165,3163,0,3083,3085,3167,3165,0,3085,3087,3169,3167,0,3087,3090,3172,3169,0,3090,3093,3175,3172,0,3093,3097,3177,3175,0,3097,3099,3181,3177,0,3099,3101,3183,3181,0,3101,3103,3185,3183,0,3103,3102,3184,3185,0,3102,3100,3182,3184,0,3100,3096,3179,3182,0,3096,3092,3176,3179,0,3092,3091,3173,3176,0,3091,3088,3170,3173,0,3088,3080,3162,3170,0,3080,3076,3158,3162,0,3076,3074,3156,3158,0,3074,3071,3153,3156,0,3071,3067,3149,3153,0,3067,3065,3147,3149,0,3065,3063,3145,3147,0,3063,3061,3143,3145,0,3061,3059,3141,3143,0,3059,3057,3139,3141,0,3057,3055,3137,3139,0,3055,3053,3135,3137,0,3053,3051,3133,3135,0,3051,3049,3131,3133,0,3049,3047,3129,3131,0,3047,3044,3126,3129,0,3044,3043,3125,3126,0,3043,3041,3123,3125,0,3041,3039,3121,3123,0,3039,3037,3119,3121,0,3037,3036,3118,3119,0,3118,3117,3199,3200,0,3117,3120,3202,3199,0,3120,3122,3204,3202,0,3122,3124,3206,3204,0,3124,3127,3209,3206,0,3127,3128,3210,3209,0,3128,3130,3212,3210,0,3130,3132,3214,3212,0,3132,3134,3216,3214,0,3134,3136,3218,3216,0,3136,3138,3220,3218,0,3138,3140,3222,3220,0,3140,3142,3224,3222,0,3142,3144,3226,3224,0,3144,3146,3228,3226,0,3146,3148,3231,3228,0,3148,3151,3235,3231,0,3151,3155,3237,3235,0,3155,3157,3239,3237,0,3157,3159,3241,3239,0,3159,3160,3243,3241,0,3160,3178,3263,3243,0,3178,3187,3269,3263,0,3187,3189,3271,3269,0,3189,3191,3273,3271,0,3191,3193,3275,3273,0,3193,3195,3277,3275,0,3195,3197,3279,3277,0,3197,3198,3280,3279,0,3198,3196,3278,3280,0,3196,3194,3276,3278,0,3194,3192,3274,3276,0,3192,3190,3272,3274,0,3190,3188,3270,3272,0,3188,3186,3267,3270,0,3186,3180,3260,3267,0,3180,3174,3256,3260,0,3174,3171,3252,3256,0,3171,3168,3250,3252,0,3168,3166,3248,3250,0,3166,3164,3244,3248,0,3164,3154,3234,3244,0,3154,3150,3230,3234,0,3150,3152,3232,3230,0,3152,3161,3242,3232,0,3161,3163,3245,3242,0,3163,3165,3247,3245,0,3165,3167,3249,3247,0,3167,3169,3251,3249,0,3169,3172,3254,3251,0,3172,3175,3257,3254,0,3175,3177,3259,3257,0,3177,3181,3262,3259,0,3181,3183,3264,3262,0,3183,3185,3266,3264,0,3185,3184,3268,3266,0,3184,3182,3265,3268,0,3182,3179,3261,3265,0,3179,3176,3258,3261,0,3176,3173,3255,3258,0,3173,3170,3253,3255,0,3170,3162,3246,3253,0,3162,3158,3240,3246,0,3158,3156,3238,3240,0,3156,3153,3236,3238,0,3153,3149,3233,3236,0,3149,3147,3229,3233,0,3147,3145,3227,3229,0,3145,3143,3225,3227,0,3143,3141,3223,3225,0,3141,3139,3221,3223,0,3139,3137,3219,3221,0,3137,3135,3217,3219,0,3135,3133,3215,3217,0,3133,3131,3213,3215,0,3131,3129,3211,3213,0,3129,3126,3208,3211,0,3126,3125,3207,3208,0,3125,3123,3205,3207,0,3123,3121,3203,3205,0,3121,3119,3201,3203,0,3119,3118,3200,3201,0,3,7,8,10,12,14,16,18,20,22,24,25,27,30,32,34,36,38,40,42,43,45,46,50,52,55,58,61,63,66,68,70,67,65,62,59,57,49,48,53,69,72,75,77,79,81,82,80,78,76,74,73,71,64,60,56,54,51,47,44,41,39,37,35,33,31,29,28,26,23,21,19,17,15,13,11,9,6,5,4,1,2,0,3200,3199,3202,3204,3206,3209,3210,3212,3214,3216,3218,3220,3222,3224,3226,3228,3231,3235,3237,3239,3241,3243,3263,3269,3271,3273,3275,3277,3279,3280,3278,3276,3274,3272,3270,3267,3260,3256,3252,3250,3248,3244,3234,3230,3232,3242,3245,3247,3249,3251,3254,3257,3259,3262,3264,3266,3268,3265,3261,3258,3255,3253,3246,3240,3238,3236,3233,3229,3227,3225,3223,3221,3219,3217,3215,3213,3211,3208,3207,3205,3203,3201,0,3321,3324,3406,3403,0,3324,3330,3412,3406,0,3330,3334,3416,3412,0,3334,3340,3422,3416,0,3340,3350,3431,3422,0,3350,3352,3434,3431,0,3352,3354,3436,3434,0,3354,3356,3438,3436,0,3356,3358,3440,3438,0,3358,3360,3442,3440,0,3360,3362,3444,3442,0,3362,3361,3443,3444,0,3361,3359,3441,3443,0,3359,3357,3439,3441,0,3357,3355,3437,3439,0,3355,3353,3435,3437,0,3353,3351,3433,3435,0,3351,3346,3429,3433,0,3346,3341,3423,3429,0,3341,3336,3418,3423,0,3336,3331,3413,3418,0,3331,3320,3402,3413,0,3320,3319,3401,3402,0,3319,3316,3398,3401,0,3316,3314,3396,3398,0,3314,3313,3395,3396,0,3313,3311,3393,3395,0,3311,3309,3391,3393,0,3309,3307,3389,3391,0,3307,3305,3387,3389,0,3305,3303,3385,3387,0,3303,3301,3383,3385,0,3301,3299,3381,3383,0,3299,3297,3379,3381,0,3297,3295,3377,3379,0,3295,3293,3375,3377,0,3293,3292,3374,3375,0,3292,3290,3372,3374,0,3290,3287,3369,3372,0,3287,3285,3367,3369,0,3285,3284,3366,3367,0,3284,3281,3363,3366,0,3281,3282,3364,3363,0,3282,3283,3365,3364,0,3283,3286,3368,3365,0,3286,3288,3370,3368,0,3288,3289,3371,3370,0,3289,3291,3373,3371,0,3291,3294,3376,3373,0,3294,3296,3378,3376,0,3296,3298,3380,3378,0,3298,3300,3382,3380,0,3300,3302,3384,3382,0,3302,3304,3386,3384,0,3304,3306,3388,3386,0,3306,3308,3390,3388,0,3308,3310,3392,3390,0,3310,3312,3394,3392,0,3312,3315,3397,3394,0,3315,3317,3399,3397,0,3317,3318,3400,3399,0,3318,3322,3404,3400,0,3322,3326,3408,3404,0,3326,3328,3410,3408,0,3328,3332,3414,3410,0,3332,3335,3417,3414,0,3335,3338,3420,3417,0,3338,3342,3424,3420,0,3342,3344,3426,3424,0,3344,3347,3428,3426,0,3347,3349,3432,3428,0,3349,3348,3430,3432,0,3348,3345,3427,3430,0,3345,3343,3425,3427,0,3343,3339,3421,3425,0,3339,3337,3419,3421,0,3337,3333,3415,3419,0,3333,3329,3411,3415,0,3329,3327,3409,3411,0,3327,3325,3407,3409,0,3325,3323,3405,3407,0,3323,3321,3403,3405,0,3403,3406,3488,3485,0,3406,3412,3494,3488,0,3412,3416,3498,3494,0,3416,3422,3503,3498,0,3422,3431,3510,3503,0,3431,3434,3515,3510,0,3434,3436,3517,3515,0,3436,3438,3519,3517,0,3438,3440,3521,3519,0,3440,3442,3523,3521,0,3442,3444,3525,3523,0,3444,3443,3526,3525,0,3443,3441,3524,3526,0,3441,3439,3522,3524,0,3439,3437,3520,3522,0,3437,3435,3518,3520,0,3435,3433,3516,3518,0,3433,3429,3513,3516,0,3429,3423,3505,3513,0,3423,3418,3500,3505,0,3418,3413,3495,3500,0,3413,3402,3484,3495,0,3402,3401,3483,3484,0,3401,3398,3480,3483,0,3398,3396,3478,3480,0,3396,3395,3477,3478,0,3395,3393,3475,3477,0,3393,3391,3473,3475,0,3391,3389,3471,3473,0,3389,3387,3469,3471,0,3387,3385,3467,3469,0,3385,3383,3465,3467,0,3383,3381,3463,3465,0,3381,3379,3461,3463,0,3379,3377,3459,3461,0,3377,3375,3457,3459,0,3375,3374,3456,3457,0,3374,3372,3454,3456,0,3372,3369,3451,3454,0,3369,3367,3449,3451,0,3367,3366,3448,3449,0,3366,3363,3445,3448,0,3363,3364,3446,3445,0,3364,3365,3447,3446,0,3365,3368,3450,3447,0,3368,3370,3452,3450,0,3370,3371,3453,3452,0,3371,3373,3455,3453,0,3373,3376,3458,3455,0,3376,3378,3460,3458,0,3378,3380,3462,3460,0,3380,3382,3464,3462,0,3382,3384,3466,3464,0,3384,3386,3468,3466,0,3386,3388,3470,3468,0,3388,3390,3472,3470,0,3390,3392,3474,3472,0,3392,3394,3476,3474,0,3394,3397,3479,3476,0,3397,3399,3481,3479,0,3399,3400,3482,3481,0,3400,3404,3487,3482,0,3404,3408,3490,3487,0,3408,3410,3492,3490,0,3410,3414,3496,3492,0,3414,3417,3499,3496,0,3417,3420,3502,3499,0,3420,3424,3506,3502,0,3424,3426,3508,3506,0,3426,3428,3511,3508,0,3428,3432,3514,3511,0,3432,3430,3512,3514,0,3430,3427,3509,3512,0,3427,3425,3507,3509,0,3425,3421,3504,3507,0,3421,3419,3501,3504,0,3419,3415,3497,3501,0,3415,3411,3493,3497,0,3411,3409,3491,3493,0,3409,3407,3489,3491,0,3407,3405,3486,3489,0,3405,3403,3485,3486,0,3485,3488,3570,3567,0,3488,3494,3576,3570,0,3494,3498,3580,3576,0,3498,3503,3584,3580,0,3503,3510,3592,3584,0,3510,3515,3597,3592,0,3515,3517,3599,3597,0,3517,3519,3601,3599,0,3519,3521,3603,3601,0,3521,3523,3605,3603,0,3523,3525,3607,3605,0,3525,3526,3608,3607,0,3526,3524,3606,3608,0,3524,3522,3604,3606,0,3522,3520,3602,3604,0,3520,3518,3600,3602,0,3518,3516,3598,3600,0,3516,3513,3596,3598,0,3513,3505,3587,3596,0,3505,3500,3583,3587,0,3500,3495,3577,3583,0,3495,3484,3566,3577,0,3484,3483,3565,3566,0,3483,3480,3562,3565,0,3480,3478,3560,3562,0,3478,3477,3559,3560,0,3477,3475,3557,3559,0,3475,3473,3555,3557,0,3473,3471,3553,3555,0,3471,3469,3551,3553,0,3469,3467,3549,3551,0,3467,3465,3547,3549,0,3465,3463,3545,3547,0,3463,3461,3543,3545,0,3461,3459,3541,3543,0,3459,3457,3539,3541,0,3457,3456,3538,3539,0,3456,3454,3536,3538,0,3454,3451,3533,3536,0,3451,3449,3531,3533,0,3449,3448,3530,3531,0,3448,3445,3527,3530,0,3445,3446,3528,3527,0,3446,3447,3529,3528,0,3447,3450,3532,3529,0,3450,3452,3534,3532,0,3452,3453,3535,3534,0,3453,3455,3537,3535,0,3455,3458,3540,3537,0,3458,3460,3542,3540,0,3460,3462,3544,3542,0,3462,3464,3546,3544,0,3464,3466,3548,3546,0,3466,3468,3550,3548,0,3468,3470,3552,3550,0,3470,3472,3554,3552,0,3472,3474,3556,3554,0,3474,3476,3558,3556,0,3476,3479,3561,3558,0,3479,3481,3563,3561,0,3481,3482,3564,3563,0,3482,3487,3569,3564,0,3487,3490,3572,3569,0,3490,3492,3574,3572,0,3492,3496,3578,3574,0,3496,3499,3581,3578,0,3499,3502,3585,3581,0,3502,3506,3588,3585,0,3506,3508,3590,3588,0,3508,3511,3593,3590,0,3511,3514,3595,3593,0,3514,3512,3594,3595,0,3512,3509,3591,3594,0,3509,3507,3589,3591,0,3507,3504,3586,3589,0,3504,3501,3582,3586,0,3501,3497,3579,3582,0,3497,3493,3575,3579,0,3493,3491,3573,3575,0,3491,3489,3571,3573,0,3489,3486,3568,3571,0,3486,3485,3567,3568,0,3567,3570,3652,3649,0,3570,3576,3657,3652,0,3576,3580,3661,3657,0,3580,3584,3666,3661,0,3584,3592,3672,3666,0,3592,3597,3679,3672,0,3597,3599,3681,3679,0,3599,3601,3683,3681,0,3601,3603,3685,3683,0,3603,3605,3687,3685,0,3605,3607,3689,3687,0,3607,3608,3690,3689,0,3608,3606,3688,3690,0,3606,3604,3686,3688,0,3604,3602,3684,3686,0,3602,3600,3682,3684,0,3600,3598,3680,3682,0,3598,3596,3678,3680,0,3596,3587,3671,3678,0,3587,3583,3665,3671,0,3583,3577,3660,3665,0,3577,3566,3648,3660,0,3566,3565,3647,3648,0,3565,3562,3644,3647,0,3562,3560,3643,3644,0,3560,3559,3641,3643,0,3559,3557,3639,3641,0,3557,3555,3637,3639,0,3555,3553,3635,3637,0,3553,3551,3633,3635,0,3551,3549,3631,3633,0,3549,3547,3629,3631,0,3547,3545,3627,3629,0,3545,3543,3625,3627,0,3543,3541,3623,3625,0,3541,3539,3622,3623,0,3539,3538,3620,3622,0,3538,3536,3618,3620,0,3536,3533,3616,3618,0,3533,3531,3613,3616,0,3531,3530,3612,3613,0,3530,3527,3609,3612,0,3527,3528,3610,3609,0,3528,3529,3611,3610,0,3529,3532,3614,3611,0,3532,3534,3615,3614,0,3534,3535,3617,3615,0,3535,3537,3619,3617,0,3537,3540,3621,3619,0,3540,3542,3624,3621,0,3542,3544,3626,3624,0,3544,3546,3628,3626,0,3546,3548,3630,3628,0,3548,3550,3632,3630,0,3550,3552,3634,3632,0,3552,3554,3636,3634,0,3554,3556,3638,3636,0,3556,3558,3640,3638,0,3558,3561,3642,3640,0,3561,3563,3645,3642,0,3563,3564,3646,3645,0,3564,3569,3651,3646,0,3569,3572,3655,3651,0,3572,3574,3658,3655,0,3574,3578,3662,3658,0,3578,3581,3664,3662,0,3581,3585,3668,3664,0,3585,3588,3670,3668,0,3588,3590,3674,3670,0,3590,3593,3676,3674,0,3593,3595,3677,3676,0,3595,3594,3675,3677,0,3594,3591,3673,3675,0,3591,3589,3669,3673,0,3589,3586,3667,3669,0,3586,3582,3663,3667,0,3582,3579,3659,3663,0,3579,3575,3656,3659,0,3575,3573,3654,3656,0,3573,3571,3653,3654,0,3571,3568,3650,3653,0,3568,3567,3649,3650,0,3649,3652,3733,3731,0,3652,3657,3738,3733,0,3657,3661,3742,3738,0,3661,3666,3747,3742,0,3666,3672,3753,3747,0,3672,3679,3760,3753,0,3679,3681,3762,3760,0,3681,3683,3764,3762,0,3683,3685,3766,3764,0,3685,3687,3769,3766,0,3687,3689,3771,3769,0,3689,3690,3772,3771,0,3690,3688,3770,3772,0,3688,3686,3768,3770,0,3686,3684,3767,3768,0,3684,3682,3765,3767,0,3682,3680,3763,3765,0,3680,3678,3761,3763,0,3678,3671,3754,3761,0,3671,3665,3748,3754,0,3665,3660,3743,3748,0,3660,3648,3730,3743,0,3648,3647,3729,3730,0,3647,3644,3726,3729,0,3644,3643,3725,3726,0,3643,3641,3723,3725,0,3641,3639,3721,3723,0,3639,3637,3719,3721,0,3637,3635,3717,3719,0,3635,3633,3715,3717,0,3633,3631,3713,3715,0,3631,3629,3711,3713,0,3629,3627,3709,3711,0,3627,3625,3707,3709,0,3625,3623,3705,3707,0,3623,3622,3704,3705,0,3622,3620,3702,3704,0,3620,3618,3700,3702,0,3618,3616,3698,3700,0,3616,3613,3695,3698,0,3613,3612,3694,3695,0,3612,3609,3691,3694,0,3609,3610,3692,3691,0,3610,3611,3693,3692,0,3611,3614,3696,3693,0,3614,3615,3697,3696,0,3615,3617,3699,3697,0,3617,3619,3701,3699,0,3619,3621,3703,3701,0,3621,3624,3706,3703,0,3624,3626,3708,3706,0,3626,3628,3710,3708,0,3628,3630,3712,3710,0,3630,3632,3714,3712,0,3632,3634,3716,3714,0,3634,3636,3718,3716,0,3636,3638,3720,3718,0,3638,3640,3722,3720,0,3640,3642,3724,3722,0,3642,3645,3727,3724,0,3645,3646,3728,3727,0,3646,3651,3734,3728,0,3651,3655,3737,3734,0,3655,3658,3740,3737,0,3658,3662,3744,3740,0,3662,3664,3746,3744,0,3664,3668,3750,3746,0,3668,3670,3752,3750,0,3670,3674,3756,3752,0,3674,3676,3758,3756,0,3676,3677,3759,3758,0,3677,3675,3757,3759,0,3675,3673,3755,3757,0,3673,3669,3751,3755,0,3669,3667,3749,3751,0,3667,3663,3745,3749,0,3663,3659,3741,3745,0,3659,3656,3739,3741,0,3656,3654,3736,3739,0,3654,3653,3735,3736,0,3653,3650,3732,3735,0,3650,3649,3731,3732,0,3731,3733,3815,3813,0,3733,3738,3820,3815,0,3738,3742,3824,3820,0,3742,3747,3828,3824,0,3747,3753,3834,3828,0,3753,3760,3842,3834,0,3760,3762,3844,3842,0,3762,3764,3846,3844,0,3764,3766,3848,3846,0,3766,3769,3850,3848,0,3769,3771,3852,3850,0,3771,3772,3854,3852,0,3772,3770,3853,3854,0,3770,3768,3851,3853,0,3768,3767,3849,3851,0,3767,3765,3847,3849,0,3765,3763,3845,3847,0,3763,3761,3843,3845,0,3761,3754,3837,3843,0,3754,3748,3831,3837,0,3748,3743,3825,3831,0,3743,3730,3812,3825,0,3730,3729,3811,3812,0,3729,3726,3808,3811,0,3726,3725,3807,3808,0,3725,3723,3805,3807,0,3723,3721,3803,3805,0,3721,3719,3801,3803,0,3719,3717,3799,3801,0,3717,3715,3797,3799,0,3715,3713,3795,3797,0,3713,3711,3793,3795,0,3711,3709,3791,3793,0,3709,3707,3789,3791,0,3707,3705,3787,3789,0,3705,3704,3786,3787,0,3704,3702,3784,3786,0,3702,3700,3782,3784,0,3700,3698,3780,3782,0,3698,3695,3777,3780,0,3695,3694,3776,3777,0,3694,3691,3773,3776,0,3691,3692,3774,3773,0,3692,3693,3775,3774,0,3693,3696,3778,3775,0,3696,3697,3779,3778,0,3697,3699,3781,3779,0,3699,3701,3783,3781,0,3701,3703,3785,3783,0,3703,3706,3788,3785,0,3706,3708,3790,3788,0,3708,3710,3792,3790,0,3710,3712,3794,3792,0,3712,3714,3796,3794,0,3714,3716,3798,3796,0,3716,3718,3800,3798,0,3718,3720,3802,3800,0,3720,3722,3804,3802,0,3722,3724,3806,3804,0,3724,3727,3809,3806,0,3727,3728,3810,3809,0,3728,3734,3816,3810,0,3734,3737,3819,3816,0,3737,3740,3822,3819,0,3740,3744,3826,3822,0,3744,3746,3829,3826,0,3746,3750,3832,3829,0,3750,3752,3835,3832,0,3752,3756,3839,3835,0,3756,3758,3841,3839,0,3758,3759,3840,3841,0,3759,3757,3838,3840,0,3757,3755,3836,3838,0,3755,3751,3833,3836,0,3751,3749,3830,3833,0,3749,3745,3827,3830,0,3745,3741,3823,3827,0,3741,3739,3821,3823,0,3739,3736,3818,3821,0,3736,3735,3817,3818,0,3735,3732,3814,3817,0,3732,3731,3813,3814,0,3813,3815,3897,3895,0,3815,3820,3901,3897,0,3820,3824,3906,3901,0,3824,3828,3910,3906,0,3828,3834,3916,3910,0,3834,3842,3924,3916,0,3842,3844,3926,3924,0,3844,3846,3928,3926,0,3846,3848,3930,3928,0,3848,3850,3932,3930,0,3850,3852,3934,3932,0,3852,3854,3936,3934,0,3854,3853,3935,3936,0,3853,3851,3933,3935,0,3851,3849,3931,3933,0,3849,3847,3929,3931,0,3847,3845,3927,3929,0,3845,3843,3925,3927,0,3843,3837,3920,3925,0,3837,3831,3913,3920,0,3831,3825,3908,3913,0,3825,3812,3894,3908,0,3812,3811,3893,3894,0,3811,3808,3891,3893,0,3808,3807,3889,3891,0,3807,3805,3887,3889,0,3805,3803,3885,3887,0,3803,3801,3883,3885,0,3801,3799,3881,3883,0,3799,3797,3879,3881,0,3797,3795,3877,3879,0,3795,3793,3875,3877,0,3793,3791,3873,3875,0,3791,3789,3871,3873,0,3789,3787,3869,3871,0,3787,3786,3868,3869,0,3786,3784,3866,3868,0,3784,3782,3864,3866,0,3782,3780,3862,3864,0,3780,3777,3859,3862,0,3777,3776,3858,3859,0,3776,3773,3855,3858,0,3773,3774,3856,3855,0,3774,3775,3857,3856,0,3775,3778,3860,3857,0,3778,3779,3861,3860,0,3779,3781,3863,3861,0,3781,3783,3865,3863,0,3783,3785,3867,3865,0,3785,3788,3870,3867,0,3788,3790,3872,3870,0,3790,3792,3874,3872,0,3792,3794,3876,3874,0,3794,3796,3878,3876,0,3796,3798,3880,3878,0,3798,3800,3882,3880,0,3800,3802,3884,3882,0,3802,3804,3886,3884,0,3804,3806,3888,3886,0,3806,3809,3890,3888,0,3809,3810,3892,3890,0,3810,3816,3898,3892,0,3816,3819,3903,3898,0,3819,3822,3905,3903,0,3822,3826,3909,3905,0,3826,3829,3912,3909,0,3829,3832,3915,3912,0,3832,3835,3918,3915,0,3835,3839,3921,3918,0,3839,3841,3923,3921,0,3841,3840,3922,3923,0,3840,3838,3919,3922,0,3838,3836,3917,3919,0,3836,3833,3914,3917,0,3833,3830,3911,3914,0,3830,3827,3907,3911,0,3827,3823,3904,3907,0,3823,3821,3902,3904,0,3821,3818,3900,3902,0,3818,3817,3899,3900,0,3817,3814,3896,3899,0,3814,3813,3895,3896,0,3895,3897,3979,3976,0,3897,3901,3983,3979,0,3901,3906,3987,3983,0,3906,3910,3992,3987,0,3910,3916,3997,3992,0,3916,3924,4003,3997,0,3924,3926,4007,4003,0,3926,3928,4010,4007,0,3928,3930,4012,4010,0,3930,3932,4014,4012,0,3932,3934,4016,4014,0,3934,3936,4018,4016,0,3936,3935,4017,4018,0,3935,3933,4015,4017,0,3933,3931,4013,4015,0,3931,3929,4011,4013,0,3929,3927,4009,4011,0,3927,3925,4008,4009,0,3925,3920,4005,4008,0,3920,3913,3995,4005,0,3913,3908,3991,3995,0,3908,3894,3977,3991,0,3894,3893,3975,3977,0,3893,3891,3973,3975,0,3891,3889,3971,3973,0,3889,3887,3969,3971,0,3887,3885,3967,3969,0,3885,3883,3965,3967,0,3883,3881,3963,3965,0,3881,3879,3961,3963,0,3879,3877,3959,3961,0,3877,3875,3957,3959,0,3875,3873,3955,3957,0,3873,3871,3953,3955,0,3871,3869,3951,3953,0,3869,3868,3950,3951,0,3868,3866,3948,3950,0,3866,3864,3946,3948,0,3864,3862,3944,3946,0,3862,3859,3941,3944,0,3859,3858,3940,3941,0,3858,3855,3937,3940,0,3855,3856,3938,3937,0,3856,3857,3939,3938,0,3857,3860,3942,3939,0,3860,3861,3943,3942,0,3861,3863,3945,3943,0,3863,3865,3947,3945,0,3865,3867,3949,3947,0,3867,3870,3952,3949,0,3870,3872,3954,3952,0,3872,3874,3956,3954,0,3874,3876,3958,3956,0,3876,3878,3960,3958,0,3878,3880,3962,3960,0,3880,3882,3964,3962,0,3882,3884,3966,3964,0,3884,3886,3968,3966,0,3886,3888,3970,3968,0,3888,3890,3972,3970,0,3890,3892,3974,3972,0,3892,3898,3980,3974,0,3898,3903,3985,3980,0,3903,3905,3988,3985,0,3905,3909,3990,3988,0,3909,3912,3994,3990,0,3912,3915,3998,3994,0,3915,3918,4000,3998,0,3918,3921,4002,4000,0,3921,3923,4006,4002,0,3923,3922,4004,4006,0,3922,3919,4001,4004,0,3919,3917,3999,4001,0,3917,3914,3996,3999,0,3914,3911,3993,3996,0,3911,3907,3989,3993,0,3907,3904,3986,3989,0,3904,3902,3984,3986,0,3902,3900,3982,3984,0,3900,3899,3981,3982,0,3899,3896,3978,3981,0,3896,3895,3976,3978,0,3976,3979,4061,4058,0,3979,3983,4065,4061,0,3983,3987,4069,4065,0,3987,3992,4072,4069,0,3992,3997,4078,4072,0,3997,4003,4084,4078,0,4003,4007,4089,4084,0,4007,4010,4091,4089,0,4010,4012,4093,4091,0,4012,4014,4095,4093,0,4014,4016,4097,4095,0,4016,4018,4099,4097,0,4018,4017,4100,4099,0,4017,4015,4098,4100,0,4015,4013,4096,4098,0,4013,4011,4094,4096,0,4011,4009,4092,4094,0,4009,4008,4090,4092,0,4008,4005,4088,4090,0,4005,3995,4079,4088,0,3995,3991,4074,4079,0,3991,3977,4060,4074,0,3977,3975,4057,4060,0,3975,3973,4055,4057,0,3973,3971,4053,4055,0,3971,3969,4051,4053,0,3969,3967,4049,4051,0,3967,3965,4047,4049,0,3965,3963,4045,4047,0,3963,3961,4043,4045,0,3961,3959,4041,4043,0,3959,3957,4039,4041,0,3957,3955,4037,4039,0,3955,3953,4035,4037,0,3953,3951,4033,4035,0,3951,3950,4032,4033,0,3950,3948,4030,4032,0,3948,3946,4028,4030,0,3946,3944,4026,4028,0,3944,3941,4023,4026,0,3941,3940,4022,4023,0,3940,3937,4019,4022,0,3937,3938,4020,4019,0,3938,3939,4021,4020,0,3939,3942,4024,4021,0,3942,3943,4025,4024,0,3943,3945,4027,4025,0,3945,3947,4029,4027,0,3947,3949,4031,4029,0,3949,3952,4034,4031,0,3952,3954,4036,4034,0,3954,3956,4038,4036,0,3956,3958,4040,4038,0,3958,3960,4042,4040,0,3960,3962,4044,4042,0,3962,3964,4046,4044,0,3964,3966,4048,4046,0,3966,3968,4050,4048,0,3968,3970,4052,4050,0,3970,3972,4054,4052,0,3972,3974,4056,4054,0,3974,3980,4062,4056,0,3980,3985,4067,4062,0,3985,3988,4070,4067,0,3988,3990,4073,4070,0,3990,3994,4076,4073,0,3994,3998,4080,4076,0,3998,4000,4082,4080,0,4000,4002,4085,4082,0,4002,4006,4087,4085,0,4006,4004,4086,4087,0,4004,4001,4083,4086,0,4001,3999,4081,4083,0,3999,3996,4077,4081,0,3996,3993,4075,4077,0,3993,3989,4071,4075,0,3989,3986,4068,4071,0,3986,3984,4066,4068,0,3984,3982,4064,4066,0,3982,3981,4063,4064,0,3981,3978,4059,4063,0,3978,3976,4058,4059,0,4058,4061,4143,4140,0,4061,4065,4147,4143,0,4065,4069,4151,4147,0,4069,4072,4154,4151,0,4072,4078,4159,4154,0,4078,4084,4165,4159,0,4084,4089,4171,4165,0,4089,4091,4173,4171,0,4091,4093,4175,4173,0,4093,4095,4177,4175,0,4095,4097,4179,4177,0,4097,4099,4181,4179,0,4099,4100,4182,4181,0,4100,4098,4180,4182,0,4098,4096,4178,4180,0,4096,4094,4176,4178,0,4094,4092,4174,4176,0,4092,4090,4172,4174,0,4090,4088,4170,4172,0,4088,4079,4161,4170,0,4079,4074,4156,4161,0,4074,4060,4142,4156,0,4060,4057,4139,4142,0,4057,4055,4137,4139,0,4055,4053,4135,4137,0,4053,4051,4133,4135,0,4051,4049,4131,4133,0,4049,4047,4129,4131,0,4047,4045,4127,4129,0,4045,4043,4125,4127,0,4043,4041,4123,4125,0,4041,4039,4121,4123,0,4039,4037,4119,4121,0,4037,4035,4117,4119,0,4035,4033,4115,4117,0,4033,4032,4114,4115,0,4032,4030,4112,4114,0,4030,4028,4110,4112,0,4028,4026,4108,4110,0,4026,4023,4105,4108,0,4023,4022,4104,4105,0,4022,4019,4101,4104,0,4019,4020,4102,4101,0,4020,4021,4103,4102,0,4021,4024,4106,4103,0,4024,4025,4107,4106,0,4025,4027,4109,4107,0,4027,4029,4111,4109,0,4029,4031,4113,4111,0,4031,4034,4116,4113,0,4034,4036,4118,4116,0,4036,4038,4120,4118,0,4038,4040,4122,4120,0,4040,4042,4124,4122,0,4042,4044,4126,4124,0,4044,4046,4128,4126,0,4046,4048,4130,4128,0,4048,4050,4132,4130,0,4050,4052,4134,4132,0,4052,4054,4136,4134,0,4054,4056,4138,4136,0,4056,4062,4144,4138,0,4062,4067,4149,4144,0,4067,4070,4152,4149,0,4070,4073,4155,4152,0,4073,4076,4158,4155,0,4076,4080,4162,4158,0,4080,4082,4164,4162,0,4082,4085,4168,4164,0,4085,4087,4169,4168,0,4087,4086,4167,4169,0,4086,4083,4166,4167,0,4083,4081,4163,4166,0,4081,4077,4160,4163,0,4077,4075,4157,4160,0,4075,4071,4153,4157,0,4071,4068,4150,4153,0,4068,4066,4148,4150,0,4066,4064,4146,4148,0,4064,4063,4145,4146,0,4063,4059,4141,4145,0,4059,4058,4140,4141,0,4140,4143,4225,4221,0,4143,4147,4229,4225,0,4147,4151,4233,4229,0,4151,4154,4236,4233,0,4154,4159,4241,4236,0,4159,4165,4246,4241,0,4165,4171,4253,4246,0,4171,4173,4255,4253,0,4173,4175,4257,4255,0,4175,4177,4259,4257,0,4177,4179,4261,4259,0,4179,4181,4263,4261,0,4181,4182,4264,4263,0,4182,4180,4262,4264,0,4180,4178,4260,4262,0,4178,4176,4258,4260,0,4176,4174,4256,4258,0,4174,4172,4254,4256,0,4172,4170,4252,4254,0,4170,4161,4243,4252,0,4161,4156,4239,4243,0,4156,4142,4224,4239,0,4142,4139,4222,4224,0,4139,4137,4219,4222,0,4137,4135,4217,4219,0,4135,4133,4215,4217,0,4133,4131,4213,4215,0,4131,4129,4211,4213,0,4129,4127,4209,4211,0,4127,4125,4207,4209,0,4125,4123,4205,4207,0,4123,4121,4203,4205,0,4121,4119,4201,4203,0,4119,4117,4199,4201,0,4117,4115,4197,4199,0,4115,4114,4196,4197,0,4114,4112,4194,4196,0,4112,4110,4192,4194,0,4110,4108,4190,4192,0,4108,4105,4187,4190,0,4105,4104,4186,4187,0,4104,4101,4183,4186,0,4101,4102,4184,4183,0,4102,4103,4185,4184,0,4103,4106,4188,4185,0,4106,4107,4189,4188,0,4107,4109,4191,4189,0,4109,4111,4193,4191,0,4111,4113,4195,4193,0,4113,4116,4198,4195,0,4116,4118,4200,4198,0,4118,4120,4202,4200,0,4120,4122,4204,4202,0,4122,4124,4206,4204,0,4124,4126,4208,4206,0,4126,4128,4210,4208,0,4128,4130,4212,4210,0,4130,4132,4214,4212,0,4132,4134,4216,4214,0,4134,4136,4218,4216,0,4136,4138,4220,4218,0,4138,4144,4226,4220,0,4144,4149,4231,4226,0,4149,4152,4234,4231,0,4152,4155,4237,4234,0,4155,4158,4240,4237,0,4158,4162,4244,4240,0,4162,4164,4248,4244,0,4164,4168,4250,4248,0,4168,4169,4251,4250,0,4169,4167,4249,4251,0,4167,4166,4247,4249,0,4166,4163,4245,4247,0,4163,4160,4242,4245,0,4160,4157,4238,4242,0,4157,4153,4235,4238,0,4153,4150,4232,4235,0,4150,4148,4230,4232,0,4148,4146,4228,4230,0,4146,4145,4227,4228,0,4145,4141,4223,4227,0,4141,4140,4221,4223,0,4221,4225,4306,4302,0,4225,4229,4311,4306,0,4229,4233,4313,4311,0,4233,4236,4318,4313,0,4236,4241,4322,4318,0,4241,4246,4328,4322,0,4246,4253,4334,4328,0,4253,4255,4336,4334,0,4255,4257,4338,4336,0,4257,4259,4341,4338,0,4259,4261,4343,4341,0,4261,4263,4345,4343,0,4263,4264,4346,4345,0,4264,4262,4344,4346,0,4262,4260,4342,4344,0,4260,4258,4340,4342,0,4258,4256,4339,4340,0,4256,4254,4337,4339,0,4254,4252,4335,4337,0,4252,4243,4327,4335,0,4243,4239,4321,4327,0,4239,4224,4307,4321,0,4224,4222,4305,4307,0,4222,4219,4301,4305,0,4219,4217,4299,4301,0,4217,4215,4297,4299,0,4215,4213,4295,4297,0,4213,4211,4293,4295,0,4211,4209,4291,4293,0,4209,4207,4289,4291,0,4207,4205,4287,4289,0,4205,4203,4285,4287,0,4203,4201,4283,4285,0,4201,4199,4281,4283,0,4199,4197,4280,4281,0,4197,4196,4278,4280,0,4196,4194,4276,4278,0,4194,4192,4274,4276,0,4192,4190,4272,4274,0,4190,4187,4269,4272,0,4187,4186,4268,4269,0,4186,4183,4265,4268,0,4183,4184,4266,4265,0,4184,4185,4267,4266,0,4185,4188,4270,4267,0,4188,4189,4271,4270,0,4189,4191,4273,4271,0,4191,4193,4275,4273,0,4193,4195,4277,4275,0,4195,4198,4279,4277,0,4198,4200,4282,4279,0,4200,4202,4284,4282,0,4202,4204,4286,4284,0,4204,4206,4288,4286,0,4206,4208,4290,4288,0,4208,4210,4292,4290,0,4210,4212,4294,4292,0,4212,4214,4296,4294,0,4214,4216,4298,4296,0,4216,4218,4300,4298,0,4218,4220,4303,4300,0,4220,4226,4308,4303,0,4226,4231,4315,4308,0,4231,4234,4317,4315,0,4234,4237,4320,4317,0,4237,4240,4324,4320,0,4240,4244,4326,4324,0,4244,4248,4330,4326,0,4248,4250,4332,4330,0,4250,4251,4333,4332,0,4251,4249,4331,4333,0,4249,4247,4329,4331,0,4247,4245,4325,4329,0,4245,4242,4323,4325,0,4242,4238,4319,4323,0,4238,4235,4316,4319,0,4235,4232,4314,4316,0,4232,4230,4312,4314,0,4230,4228,4310,4312,0,4228,4227,4309,4310,0,4227,4223,4304,4309,0,4223,4221,4302,4304,0,4302,4306,4419,4412,0,4306,4311,4436,4419,0,4311,4313,4438,4436,0,4313,4318,4444,4438,0,4318,4322,4449,4444,0,4322,4328,4455,4449,0,4328,4334,4465,4455,0,4334,4336,4469,4465,0,4336,4338,4473,4469,0,4338,4341,4477,4473,0,4341,4343,4479,4477,0,4343,4345,4483,4479,0,4345,4346,4485,4483,0,4346,4344,4484,4485,0,4344,4342,4482,4484,0,4342,4340,4478,4482,0,4340,4339,4475,4478,0,4339,4337,4472,4475,0,4337,4335,4468,4472,0,4335,4327,4460,4468,0,4327,4321,4453,4460,0,4321,4307,4424,4453,0,4307,4305,4421,4424,0,4305,4301,4414,4421,0,4301,4299,4410,4414,0,4299,4297,4406,4410,0,4297,4295,4403,4406,0,4295,4293,4399,4403,0,4293,4291,4395,4399,0,4291,4289,4391,4395,0,4289,4287,4387,4391,0,4287,4285,4383,4387,0,4285,4283,4379,4383,0,4283,4281,4375,4379,0,4281,4280,4372,4375,0,4280,4278,4368,4372,0,4278,4276,4364,4368,0,4276,4274,4360,4364,0,4274,4272,4357,4360,0,4272,4269,4355,4357,0,4269,4268,4353,4355,0,4268,4265,4347,4353,0,4265,4266,4348,4347,0,4266,4267,4349,4348,0,4267,4270,4354,4349,0,4270,4271,4356,4354,0,4271,4273,4359,4356,0,4273,4275,4363,4359,0,4275,4277,4367,4363,0,4277,4279,4371,4367,0,4279,4282,4376,4371,0,4282,4284,4380,4376,0,4284,4286,4384,4380,0,4286,4288,4388,4384,0,4288,4290,4392,4388,0,4290,4292,4396,4392,0,4292,4294,4400,4396,0,4294,4296,4404,4400,0,4296,4298,4408,4404,0,4298,4300,4413,4408,0,4300,4303,4417,4413,0,4303,4308,4431,4417,0,4308,4315,4442,4431,0,4315,4317,4446,4442,0,4317,4320,4450,4446,0,4320,4324,4454,4450,0,4324,4326,4457,4454,0,4326,4330,4463,4457,0,4330,4332,4466,4463,0,4332,4333,4464,4466,0,4333,4331,4462,4464,0,4331,4329,4458,4462,0,4329,4325,4456,4458,0,4325,4323,4452,4456,0,4323,4319,4447,4452,0,4319,4316,4443,4447,0,4316,4314,4439,4443,0,4314,4312,4437,4439,0,4312,4310,4434,4437,0,4310,4309,4433,4434,0,4309,4304,4415,4433,0,4304,4302,4412,4415,0,4412,4419,4430,4425,0,4419,4436,4448,4430,0,4436,4438,4459,4448,0,4438,4444,4471,4459,0,4444,4449,4480,4471,0,4449,4455,4489,4480,0,4455,4465,4497,4489,0,4465,4469,4500,4497,0,4469,4473,4502,4500,0,4473,4477,4504,4502,0,4477,4479,4506,4504,0,4479,4483,4508,4506,0,4483,4485,4510,4508,0,4485,4484,4509,4510,0,4484,4482,4507,4509,0,4482,4478,4505,4507,0,4478,4475,4503,4505,0,4475,4472,4501,4503,0,4472,4468,4499,4501,0,4468,4460,4493,4499,0,4460,4453,4487,4493,0,4453,4424,4435,4487,0,4424,4421,4432,4435,0,4421,4414,4428,4432,0,4414,4410,4423,4428,0,4410,4406,4420,4423,0,4406,4403,4416,4420,0,4403,4399,4409,4416,0,4399,4395,4405,4409,0,4395,4391,4401,4405,0,4391,4387,4397,4401,0,4387,4383,4393,4397,0,4383,4379,4389,4393,0,4379,4375,4385,4389,0,4375,4372,4382,4385,0,4372,4368,4378,4382,0,4368,4364,4374,4378,0,4364,4360,4370,4374,0,4360,4357,4366,4370,0,4357,4355,4362,4366,0,4355,4353,4358,4362,0,4353,4347,4350,4358,0,4347,4348,4351,4350,0,4348,4349,4352,4351,0,4349,4354,4361,4352,0,4354,4356,4365,4361,0,4356,4359,4369,4365,0,4359,4363,4373,4369,0,4363,4367,4377,4373,0,4367,4371,4381,4377,0,4371,4376,4386,4381,0,4376,4380,4390,4386,0,4380,4384,4394,4390,0,4384,4388,4398,4394,0,4388,4392,4402,4398,0,4392,4396,4407,4402,0,4396,4400,4411,4407,0,4400,4404,4418,4411,0,4404,4408,4422,4418,0,4408,4413,4426,4422,0,4413,4417,4429,4426,0,4417,4431,4440,4429,0,4431,4442,4467,4440,0,4442,4446,4474,4467,0,4446,4450,4481,4474,0,4450,4454,4488,4481,0,4454,4457,4491,4488,0,4457,4463,4495,4491,0,4463,4466,4498,4495,0,4466,4464,4496,4498,0,4464,4462,4494,4496,0,4462,4458,4492,4494,0,4458,4456,4490,4492,0,4456,4452,4486,4490,0,4452,4447,4476,4486,0,4447,4443,4470,4476,0,4443,4439,4461,4470,0,4439,4437,4451,4461,0,4437,4434,4445,4451,0,4434,4433,4441,4445,0,4433,4415,4427,4441,0,4415,4412,4425,4427,0,4425,4430,4550,4546,0,4430,4448,4557,4550,0,4448,4459,4559,4557,0,4459,4471,4563,4559,0,4471,4480,4566,4563,0,4480,4489,4570,4566,0,4489,4497,4577,4570,0,4497,4500,4581,4577,0,4500,4502,4583,4581,0,4502,4504,4585,4583,0,4504,4506,4587,4585,0,4506,4508,4589,4587,0,4508,4510,4591,4589,0,4510,4509,4592,4591,0,4509,4507,4590,4592,0,4507,4505,4588,4590,0,4505,4503,4586,4588,0,4503,4501,4584,4586,0,4501,4499,4582,4584,0,4499,4493,4576,4582,0,4493,4487,4569,4576,0,4487,4435,4553,4569,0,4435,4432,4552,4553,0,4432,4428,4549,4552,0,4428,4423,4545,4549,0,4423,4420,4543,4545,0,4420,4416,4541,4543,0,4416,4409,4539,4541,0,4409,4405,4537,4539,0,4405,4401,4535,4537,0,4401,4397,4533,4535,0,4397,4393,4531,4533,0,4393,4389,4529,4531,0,4389,4385,4527,4529,0,4385,4382,4526,4527,0,4382,4378,4524,4526,0,4378,4374,4522,4524,0,4374,4370,4520,4522,0,4370,4366,4518,4520,0,4366,4362,4516,4518,0,4362,4358,4514,4516,0,4358,4350,4511,4514,0,4350,4351,4512,4511,0,4351,4352,4513,4512,0,4352,4361,4515,4513,0,4361,4365,4517,4515,0,4365,4369,4519,4517,0,4369,4373,4521,4519,0,4373,4377,4523,4521,0,4377,4381,4525,4523,0,4381,4386,4528,4525,0,4386,4390,4530,4528,0,4390,4394,4532,4530,0,4394,4398,4534,4532,0,4398,4402,4536,4534,0,4402,4407,4538,4536,0,4407,4411,4540,4538,0,4411,4418,4542,4540,0,4418,4422,4544,4542,0,4422,4426,4548,4544,0,4426,4429,4551,4548,0,4429,4440,4555,4551,0,4440,4467,4562,4555,0,4467,4474,4564,4562,0,4474,4481,4567,4564,0,4481,4488,4571,4567,0,4488,4491,4574,4571,0,4491,4495,4578,4574,0,4495,4498,4580,4578,0,4498,4496,4579,4580,0,4496,4494,4575,4579,0,4494,4492,4573,4575,0,4492,4490,4572,4573,0,4490,4486,4568,4572,0,4486,4476,4565,4568,0,4476,4470,4561,4565,0,4470,4461,4560,4561,0,4461,4451,4558,4560,0,4451,4445,4556,4558,0,4445,4441,4554,4556,0,4441,4427,4547,4554,0,4427,4425,4546,4547,0,4546,4550,4630,4626,0,4550,4557,4639,4630,0,4557,4559,4641,4639,0,4559,4563,4644,4641,0,4563,4566,4647,4644,0,4566,4570,4651,4647,0,4570,4577,4656,4651,0,4577,4581,4663,4656,0,4581,4583,4664,4663,0,4583,4585,4667,4664,0,4585,4587,4669,4667,0,4587,4589,4671,4669,0,4589,4591,4673,4671,0,4591,4592,4674,4673,0,4592,4590,4672,4674,0,4590,4588,4670,4672,0,4588,4586,4668,4670,0,4586,4584,4666,4668,0,4584,4582,4665,4666,0,4582,4576,4662,4665,0,4576,4569,4653,4662,0,4569,4553,4635,4653,0,4553,4552,4634,4635,0,4552,4549,4632,4634,0,4549,4545,4629,4632,0,4545,4543,4625,4629,0,4543,4541,4623,4625,0,4541,4539,4621,4623,0,4539,4537,4619,4621,0,4537,4535,4617,4619,0,4535,4533,4616,4617,0,4533,4531,4613,4616,0,4531,4529,4611,4613,0,4529,4527,4609,4611,0,4527,4526,4608,4609,0,4526,4524,4606,4608,0,4524,4522,4604,4606,0,4522,4520,4602,4604,0,4520,4518,4600,4602,0,4518,4516,4598,4600,0,4516,4514,4596,4598,0,4514,4511,4593,4596,0,4511,4512,4594,4593,0,4512,4513,4595,4594,0,4513,4515,4597,4595,0,4515,4517,4599,4597,0,4517,4519,4601,4599,0,4519,4521,4603,4601,0,4521,4523,4605,4603,0,4523,4525,4607,4605,0,4525,4528,4610,4607,0,4528,4530,4612,4610,0,4530,4532,4614,4612,0,4532,4534,4615,4614,0,4534,4536,4618,4615,0,4536,4538,4620,4618,0,4538,4540,4622,4620,0,4540,4542,4624,4622,0,4542,4544,4628,4624,0,4544,4548,4631,4628,0,4548,4551,4633,4631,0,4551,4555,4638,4633,0,4555,4562,4645,4638,0,4562,4564,4648,4645,0,4564,4567,4650,4648,0,4567,4571,4654,4650,0,4571,4574,4657,4654,0,4574,4578,4660,4657,0,4578,4580,4661,4660,0,4580,4579,4659,4661,0,4579,4575,4658,4659,0,4575,4573,4655,4658,0,4573,4572,4652,4655,0,4572,4568,4649,4652,0,4568,4565,4646,4649,0,4565,4561,4643,4646,0,4561,4560,4642,4643,0,4560,4558,4640,4642,0,4558,4556,4637,4640,0,4556,4554,4636,4637,0,4554,4547,4627,4636,0,4547,4546,4626,4627,0,4626,4630,4711,4707,0,4630,4639,4721,4711,0,4639,4641,4723,4721,0,4641,4644,4725,4723,0,4644,4647,4730,4725,0,4647,4651,4733,4730,0,4651,4656,4741,4733,0,4656,4663,4747,4741,0,4663,4664,4749,4747,0,4664,4667,4751,4749,0,4667,4669,4753,4751,0,4669,4671,4755,4753,0,4671,4673,4757,4755,0,4673,4674,4759,4757,0,4674,4672,4758,4759,0,4672,4670,4756,4758,0,4670,4668,4754,4756,0,4668,4666,4752,4754,0,4666,4665,4750,4752,0,4665,4662,4748,4750,0,4662,4653,4738,4748,0,4653,4635,4717,4738,0,4635,4634,4716,4717,0,4634,4632,4714,4716,0,4632,4629,4712,4714,0,4629,4625,4708,4712,0,4625,4623,4705,4708,0,4623,4621,4703,4705,0,4621,4619,4701,4703,0,4619,4617,4699,4701,0,4617,4616,4698,4699,0,4616,4613,4695,4698,0,4613,4611,4693,4695,0,4611,4609,4691,4693,0,4609,4608,4690,4691,0,4608,4606,4688,4690,0,4606,4604,4686,4688,0,4604,4602,4684,4686,0,4602,4600,4682,4684,0,4600,4598,4680,4682,0,4598,4596,4678,4680,0,4596,4593,4675,4678,0,4593,4594,4676,4675,0,4594,4595,4677,4676,0,4595,4597,4679,4677,0,4597,4599,4681,4679,0,4599,4601,4683,4681,0,4601,4603,4685,4683,0,4603,4605,4687,4685,0,4605,4607,4689,4687,0,4607,4610,4692,4689,0,4610,4612,4694,4692,0,4612,4614,4696,4694,0,4614,4615,4697,4696,0,4615,4618,4700,4697,0,4618,4620,4702,4700,0,4620,4622,4704,4702,0,4622,4624,4706,4704,0,4624,4628,4710,4706,0,4628,4631,4713,4710,0,4631,4633,4715,4713,0,4633,4638,4720,4715,0,4638,4645,4727,4720,0,4645,4648,4731,4727,0,4648,4650,4734,4731,0,4650,4654,4739,4734,0,4654,4657,4743,4739,0,4657,4660,4745,4743,0,4660,4661,4746,4745,0,4661,4659,4744,4746,0,4659,4658,4742,4744,0,4658,4655,4740,4742,0,4655,4652,4736,4740,0,4652,4649,4732,4736,0,4649,4646,4728,4732,0,4646,4643,4726,4728,0,4643,4642,4724,4726,0,4642,4640,4722,4724,0,4640,4637,4719,4722,0,4637,4636,4718,4719,0,4636,4627,4709,4718,0,4627,4626,4707,4709,0,4707,4711,4793,4789,0,4711,4721,4802,4793,0,4721,4723,4805,4802,0,4723,4725,4807,4805,0,4725,4730,4811,4807,0,4730,4733,4814,4811,0,4733,4741,4820,4814,0,4741,4747,4826,4820,0,4747,4749,4828,4826,0,4749,4751,4830,4828,0,4751,4753,4832,4830,0,4753,4755,4834,4832,0,4755,4757,4836,4834,0,4757,4759,4838,4836,0,4759,4758,4837,4838,0,4758,4756,4835,4837,0,4756,4754,4833,4835,0,4754,4752,4831,4833,0,4752,4750,4829,4831,0,4750,4748,4827,4829,0,4748,4738,4819,4827,0,4738,4717,4799,4819,0,4717,4716,4798,4799,0,4716,4714,4796,4798,0,4714,4712,4794,4796,0,4712,4708,4791,4794,0,4708,4705,4787,4791,0,4705,4703,4785,4787,0,4703,4701,4783,4785,0,4701,4699,4781,4783,0,4699,4698,4780,4781,0,4698,4695,4777,4780,0,4695,4693,4775,4777,0,4693,4691,4773,4775,0,4691,4690,4772,4773,0,4690,4688,4770,4772,0,4688,4686,4768,4770,0,4686,4684,4766,4768,0,4684,4682,4764,4766,0,4682,4680,4762,4764,0,4680,4678,4760,4762,0,4678,4675,4729,4760,0,4675,4676,4735,4729,0,4676,4677,4737,4735,0,4677,4679,4761,4737,0,4679,4681,4763,4761,0,4681,4683,4765,4763,0,4683,4685,4767,4765,0,4685,4687,4769,4767,0,4687,4689,4771,4769,0,4689,4692,4774,4771,0,4692,4694,4776,4774,0,4694,4696,4778,4776,0,4696,4697,4779,4778,0,4697,4700,4782,4779,0,4700,4702,4784,4782,0,4702,4704,4786,4784,0,4704,4706,4788,4786,0,4706,4710,4792,4788,0,4710,4713,4795,4792,0,4713,4715,4797,4795,0,4715,4720,4803,4797,0,4720,4727,4809,4803,0,4727,4731,4812,4809,0,4731,4734,4815,4812,0,4734,4739,4817,4815,0,4739,4743,4822,4817,0,4743,4745,4824,4822,0,4745,4746,4825,4824,0,4746,4744,4823,4825,0,4744,4742,4821,4823,0,4742,4740,4818,4821,0,4740,4736,4816,4818,0,4736,4732,4813,4816,0,4732,4728,4810,4813,0,4728,4726,4808,4810,0,4726,4724,4806,4808,0,4724,4722,4804,4806,0,4722,4719,4801,4804,0,4719,4718,4800,4801,0,4718,4709,4790,4800,0,4709,4707,4789,4790,0,4789,4793,4872,4869,0,4793,4802,4884,4872,0,4802,4805,4887,4884,0,4805,4807,4889,4887,0,4807,4811,4892,4889,0,4811,4814,4895,4892,0,4814,4820,4899,4895,0,4820,4826,4906,4899,0,4826,4828,4909,4906,0,4828,4830,4911,4909,0,4830,4832,4913,4911,0,4832,4834,4915,4913,0,4834,4836,4917,4915,0,4836,4838,4919,4917,0,4838,4837,4920,4919,0,4837,4835,4918,4920,0,4835,4833,4916,4918,0,4833,4831,4914,4916,0,4831,4829,4912,4914,0,4829,4827,4910,4912,0,4827,4819,4903,4910,0,4819,4799,4883,4903,0,4799,4798,4880,4883,0,4798,4796,4878,4880,0,4796,4794,4876,4878,0,4794,4791,4874,4876,0,4791,4787,4871,4874,0,4787,4785,4867,4871,0,4785,4783,4865,4867,0,4783,4781,4863,4865,0,4781,4780,4862,4863,0,4780,4777,4859,4862,0,4777,4775,4857,4859,0,4775,4773,4856,4857,0,4773,4772,4854,4856,0,4772,4770,4852,4854,0,4770,4768,4850,4852,0,4768,4766,4848,4850,0,4766,4764,4846,4848,0,4764,4762,4844,4846,0,4762,4760,4842,4844,0,4760,4729,4839,4842,0,4729,4735,4840,4839,0,4735,4737,4841,4840,0,4737,4761,4843,4841,0,4761,4763,4845,4843,0,4763,4765,4847,4845,0,4765,4767,4849,4847,0,4767,4769,4851,4849,0,4769,4771,4853,4851,0,4771,4774,4855,4853,0,4774,4776,4858,4855,0,4776,4778,4860,4858,0,4778,4779,4861,4860,0,4779,4782,4864,4861,0,4782,4784,4866,4864,0,4784,4786,4868,4866,0,4786,4788,4873,4868,0,4788,4792,4875,4873,0,4792,4795,4877,4875,0,4795,4797,4879,4877,0,4797,4803,4886,4879,0,4803,4809,4893,4886,0,4809,4812,4896,4893,0,4812,4815,4898,4896,0,4815,4817,4901,4898,0,4817,4822,4905,4901,0,4822,4824,4908,4905,0,4824,4825,4907,4908,0,4825,4823,4904,4907,0,4823,4821,4902,4904,0,4821,4818,4900,4902,0,4818,4816,4897,4900,0,4816,4813,4894,4897,0,4813,4810,4891,4894,0,4810,4808,4890,4891,0,4808,4806,4888,4890,0,4806,4804,4885,4888,0,4804,4801,4882,4885,0,4801,4800,4881,4882,0,4800,4790,4870,4881,0,4790,4789,4869,4870,0,4869,4872,4953,4949,0,4872,4884,4966,4953,0,4884,4887,4971,4966,0,4887,4889,4974,4971,0,4889,4892,4977,4974,0,4892,4895,4981,4977,0,4895,4899,4984,4981,0,4899,4906,4991,4984,0,4906,4909,4997,4991,0,4909,4911,5000,4997,0,4911,4913,5003,5000,0,4913,4915,5005,5003,0,4915,4917,5008,5005,0,4917,4919,5010,5008,0,4919,4920,5011,5010,0,4920,4918,5009,5011,0,4918,4916,5007,5009,0,4916,4914,5004,5007,0,4914,4912,5002,5004,0,4912,4910,4999,5002,0,4910,4903,4993,4999,0,4903,4883,4967,4993,0,4883,4880,4963,4967,0,4880,4878,4960,4963,0,4878,4876,4958,4960,0,4876,4874,4956,4958,0,4874,4871,4954,4956,0,4871,4867,4950,4954,0,4867,4865,4947,4950,0,4865,4863,4945,4947,0,4863,4862,4944,4945,0,4862,4859,4941,4944,0,4859,4857,4939,4941,0,4857,4856,4938,4939,0,4856,4854,4936,4938,0,4854,4852,4934,4936,0,4852,4850,4932,4934,0,4850,4848,4930,4932,0,4848,4846,4928,4930,0,4846,4844,4926,4928,0,4844,4842,4924,4926,0,4842,4839,4921,4924,0,4839,4840,4922,4921,0,4840,4841,4923,4922,0,4841,4843,4925,4923,0,4843,4845,4927,4925,0,4845,4847,4929,4927,0,4847,4849,4931,4929,0,4849,4851,4933,4931,0,4851,4853,4935,4933,0,4853,4855,4937,4935,0,4855,4858,4940,4937,0,4858,4860,4942,4940,0,4860,4861,4943,4942,0,4861,4864,4946,4943,0,4864,4866,4948,4946,0,4866,4868,4952,4948,0,4868,4873,4955,4952,0,4873,4875,4957,4955,0,4875,4877,4959,4957,0,4877,4879,4961,4959,0,4879,4886,4972,4961,0,4886,4893,4978,4972,0,4893,4896,4982,4978,0,4896,4898,4986,4982,0,4898,4901,4990,4986,0,4901,4905,4994,4990,0,4905,4908,4996,4994,0,4908,4907,4995,4996,0,4907,4904,4992,4995,0,4904,4902,4989,4992,0,4902,4900,4987,4989,0,4900,4897,4983,4987,0,4897,4894,4980,4983,0,4894,4891,4976,4980,0,4891,4890,4975,4976,0,4890,4888,4973,4975,0,4888,4885,4970,4973,0,4885,4882,4965,4970,0,4882,4881,4962,4965,0,4881,4870,4951,4962,0,4870,4869,4949,4951,0,4949,4953,5035,5031,0,4953,4966,5047,5035,0,4966,4971,5050,5047,0,4971,4974,5053,5050,0,4974,4977,5056,5053,0,4977,4981,5059,5056,0,4981,4984,5062,5059,0,4984,4991,5067,5062,0,4991,4997,5073,5067,0,4997,5000,5075,5073,0,5000,5003,5077,5075,0,5003,5005,5079,5077,0,5005,5008,5081,5079,0,5008,5010,5083,5081,0,5010,5011,5084,5083,0,5011,5009,5082,5084,0,5009,5007,5080,5082,0,5007,5004,5078,5080,0,5004,5002,5076,5078,0,5002,4999,5074,5076,0,4999,4993,5070,5074,0,4993,4967,5048,5070,0,4967,4963,5045,5048,0,4963,4960,5042,5045,0,4960,4958,5040,5042,0,4958,4956,5038,5040,0,4956,4954,5036,5038,0,4954,4950,5032,5036,0,4950,4947,5029,5032,0,4947,4945,5027,5029,0,4945,4944,5026,5027,0,4944,4941,5023,5026,0,4941,4939,5021,5023,0,4939,4938,5020,5021,0,4938,4936,5018,5020,0,4936,4934,5016,5018,0,4934,4932,5014,5016,0,4932,4930,5012,5014,0,4930,4928,5001,5012,0,4928,4926,4988,5001,0,4926,4924,4979,4988,0,4924,4921,4964,4979,0,4921,4922,4968,4964,0,4922,4923,4969,4968,0,4923,4925,4985,4969,0,4925,4927,4998,4985,0,4927,4929,5006,4998,0,4929,4931,5013,5006,0,4931,4933,5015,5013,0,4933,4935,5017,5015,0,4935,4937,5019,5017,0,4937,4940,5022,5019,0,4940,4942,5024,5022,0,4942,4943,5025,5024,0,4943,4946,5028,5025,0,4946,4948,5030,5028,0,4948,4952,5034,5030,0,4952,4955,5037,5034,0,4955,4957,5039,5037,0,4957,4959,5041,5039,0,4959,4961,5043,5041,0,4961,4972,5051,5043,0,4972,4978,5057,5051,0,4978,4982,5060,5057,0,4982,4986,5064,5060,0,4986,4990,5066,5064,0,4990,4994,5069,5066,0,4994,4996,5072,5069,0,4996,4995,5071,5072,0,4995,4992,5068,5071,0,4992,4989,5065,5068,0,4989,4987,5063,5065,0,4987,4983,5061,5063,0,4983,4980,5058,5061,0,4980,4976,5055,5058,0,4976,4975,5054,5055,0,4975,4973,5052,5054,0,4973,4970,5049,5052,0,4970,4965,5046,5049,0,4965,4962,5044,5046,0,4962,4951,5033,5044,0,4951,4949,5031,5033,0,5031,5035,5115,5111,0,5035,5047,5128,5115,0,5047,5050,5132,5128,0,5050,5053,5135,5132,0,5053,5056,5137,5135,0,5056,5059,5140,5137,0,5059,5062,5143,5140,0,5062,5067,5148,5143,0,5067,5073,5154,5148,0,5073,5075,5156,5154,0,5075,5077,5158,5156,0,5077,5079,5160,5158,0,5079,5081,5162,5160,0,5081,5083,5164,5162,0,5083,5084,5166,5164,0,5084,5082,5165,5166,0,5082,5080,5163,5165,0,5080,5078,5161,5163,0,5078,5076,5159,5161,0,5076,5074,5157,5159,0,5074,5070,5155,5157,0,5070,5048,5131,5155,0,5048,5045,5129,5131,0,5045,5042,5125,5129,0,5042,5040,5122,5125,0,5040,5038,5120,5122,0,5038,5036,5118,5120,0,5036,5032,5116,5118,0,5032,5029,5112,5116,0,5029,5027,5110,5112,0,5027,5026,5108,5110,0,5026,5023,5106,5108,0,5023,5021,5103,5106,0,5021,5020,5102,5103,0,5020,5018,5100,5102,0,5018,5016,5098,5100,0,5016,5014,5096,5098,0,5014,5012,5094,5096,0,5012,5001,5092,5094,0,5001,4988,5090,5092,0,4988,4979,5088,5090,0,4979,4964,5085,5088,0,4964,4968,5086,5085,0,4968,4969,5087,5086,0,4969,4985,5089,5087,0,4985,4998,5091,5089,0,4998,5006,5093,5091,0,5006,5013,5095,5093,0,5013,5015,5097,5095,0,5015,5017,5099,5097,0,5017,5019,5101,5099,0,5019,5022,5104,5101,0,5022,5024,5105,5104,0,5024,5025,5107,5105,0,5025,5028,5109,5107,0,5028,5030,5114,5109,0,5030,5034,5117,5114,0,5034,5037,5119,5117,0,5037,5039,5121,5119,0,5039,5041,5123,5121,0,5041,5043,5126,5123,0,5043,5051,5134,5126,0,5051,5057,5141,5134,0,5057,5060,5144,5141,0,5060,5064,5146,5144,0,5064,5066,5150,5146,0,5066,5069,5152,5150,0,5069,5072,5153,5152,0,5072,5071,5151,5153,0,5071,5068,5149,5151,0,5068,5065,5147,5149,0,5065,5063,5145,5147,0,5063,5061,5142,5145,0,5061,5058,5139,5142,0,5058,5055,5138,5139,0,5055,5054,5136,5138,0,5054,5052,5133,5136,0,5052,5049,5130,5133,0,5049,5046,5127,5130,0,5046,5044,5124,5127,0,5044,5033,5113,5124,0,5033,5031,5111,5113,0,5111,5115,5195,5193,0,5115,5128,5210,5195,0,5128,5132,5213,5210,0,5132,5135,5216,5213,0,5135,5137,5219,5216,0,5137,5140,5221,5219,0,5140,5143,5225,5221,0,5143,5148,5228,5225,0,5148,5154,5235,5228,0,5154,5156,5238,5235,0,5156,5158,5240,5238,0,5158,5160,5242,5240,0,5160,5162,5244,5242,0,5162,5164,5246,5244,0,5164,5166,5248,5246,0,5166,5165,5247,5248,0,5165,5163,5245,5247,0,5163,5161,5243,5245,0,5161,5159,5241,5243,0,5159,5157,5239,5241,0,5157,5155,5237,5239,0,5155,5131,5214,5237,0,5131,5129,5212,5214,0,5129,5125,5208,5212,0,5125,5122,5204,5208,0,5122,5120,5202,5204,0,5120,5118,5200,5202,0,5118,5116,5198,5200,0,5116,5112,5196,5198,0,5112,5110,5192,5196,0,5110,5108,5190,5192,0,5108,5106,5188,5190,0,5106,5103,5185,5188,0,5103,5102,5184,5185,0,5102,5100,5182,5184,0,5100,5098,5180,5182,0,5098,5096,5178,5180,0,5096,5094,5176,5178,0,5094,5092,5174,5176,0,5092,5090,5172,5174,0,5090,5088,5170,5172,0,5088,5085,5167,5170,0,5085,5086,5168,5167,0,5086,5087,5169,5168,0,5087,5089,5171,5169,0,5089,5091,5173,5171,0,5091,5093,5175,5173,0,5093,5095,5177,5175,0,5095,5097,5179,5177,0,5097,5099,5181,5179,0,5099,5101,5183,5181,0,5101,5104,5186,5183,0,5104,5105,5187,5186,0,5105,5107,5189,5187,0,5107,5109,5191,5189,0,5109,5114,5197,5191,0,5114,5117,5199,5197,0,5117,5119,5201,5199,0,5119,5121,5203,5201,0,5121,5123,5206,5203,0,5123,5126,5209,5206,0,5126,5134,5217,5209,0,5134,5141,5223,5217,0,5141,5144,5227,5223,0,5144,5146,5230,5227,0,5146,5150,5232,5230,0,5150,5152,5234,5232,0,5152,5153,5236,5234,0,5153,5151,5233,5236,0,5151,5149,5231,5233,0,5149,5147,5229,5231,0,5147,5145,5226,5229,0,5145,5142,5224,5226,0,5142,5139,5222,5224,0,5139,5138,5220,5222,0,5138,5136,5218,5220,0,5136,5133,5215,5218,0,5133,5130,5211,5215,0,5130,5127,5207,5211,0,5127,5124,5205,5207,0,5124,5113,5194,5205,0,5113,5111,5193,5194,0,5193,5195,5277,5273,0,5195,5210,5290,5277,0,5210,5213,5295,5290,0,5213,5216,5298,5295,0,5216,5219,5301,5298,0,5219,5221,5303,5301,0,5221,5225,5305,5303,0,5225,5228,5310,5305,0,5228,5235,5316,5310,0,5235,5238,5320,5316,0,5238,5240,5321,5320,0,5240,5242,5323,5321,0,5242,5244,5325,5323,0,5244,5246,5327,5325,0,5246,5248,5329,5327,0,5248,5247,5330,5329,0,5247,5245,5328,5330,0,5245,5243,5326,5328,0,5243,5241,5324,5326,0,5241,5239,5322,5324,0,5239,5237,5319,5322,0,5237,5214,5297,5319,0,5214,5212,5294,5297,0,5212,5208,5291,5294,0,5208,5204,5287,5291,0,5204,5202,5284,5287,0,5202,5200,5282,5284,0,5200,5198,5280,5282,0,5198,5196,5278,5280,0,5196,5192,5275,5278,0,5192,5190,5272,5275,0,5190,5188,5270,5272,0,5188,5185,5267,5270,0,5185,5184,5266,5267,0,5184,5182,5264,5266,0,5182,5180,5262,5264,0,5180,5178,5260,5262,0,5178,5176,5258,5260,0,5176,5174,5256,5258,0,5174,5172,5254,5256,0,5172,5170,5252,5254,0,5170,5167,5249,5252,0,5167,5168,5250,5249,0,5168,5169,5251,5250,0,5169,5171,5253,5251,0,5171,5173,5255,5253,0,5173,5175,5257,5255,0,5175,5177,5259,5257,0,5177,5179,5261,5259,0,5179,5181,5263,5261,0,5181,5183,5265,5263,0,5183,5186,5268,5265,0,5186,5187,5269,5268,0,5187,5189,5271,5269,0,5189,5191,5274,5271,0,5191,5197,5279,5274,0,5197,5199,5281,5279,0,5199,5201,5283,5281,0,5201,5203,5285,5283,0,5203,5206,5288,5285,0,5206,5209,5292,5288,0,5209,5217,5300,5292,0,5217,5223,5307,5300,0,5223,5227,5309,5307,0,5227,5230,5312,5309,0,5230,5232,5314,5312,0,5232,5234,5317,5314,0,5234,5236,5318,5317,0,5236,5233,5315,5318,0,5233,5231,5313,5315,0,5231,5229,5311,5313,0,5229,5226,5308,5311,0,5226,5224,5306,5308,0,5224,5222,5304,5306,0,5222,5220,5302,5304,0,5220,5218,5299,5302,0,5218,5215,5296,5299,0,5215,5211,5293,5296,0,5211,5207,5289,5293,0,5207,5205,5286,5289,0,5205,5194,5276,5286,0,5194,5193,5273,5276,0,5273,5277,5357,5354,0,5277,5290,5370,5357,0,5290,5295,5376,5370,0,5295,5298,5379,5376,0,5298,5301,5383,5379,0,5301,5303,5385,5383,0,5303,5305,5387,5385,0,5305,5310,5391,5387,0,5310,5316,5396,5391,0,5316,5320,5401,5396,0,5320,5321,5403,5401,0,5321,5323,5405,5403,0,5323,5325,5407,5405,0,5325,5327,5409,5407,0,5327,5329,5411,5409,0,5329,5330,5412,5411,0,5330,5328,5410,5412,0,5328,5326,5408,5410,0,5326,5324,5406,5408,0,5324,5322,5404,5406,0,5322,5319,5402,5404,0,5319,5297,5380,5402,0,5297,5294,5378,5380,0,5294,5291,5374,5378,0,5291,5287,5371,5374,0,5287,5284,5367,5371,0,5284,5282,5364,5367,0,5282,5280,5362,5364,0,5280,5278,5360,5362,0,5278,5275,5359,5360,0,5275,5272,5355,5359,0,5272,5270,5352,5355,0,5270,5267,5350,5352,0,5267,5266,5348,5350,0,5266,5264,5346,5348,0,5264,5262,5344,5346,0,5262,5260,5342,5344,0,5260,5258,5340,5342,0,5258,5256,5338,5340,0,5256,5254,5336,5338,0,5254,5252,5334,5336,0,5252,5249,5331,5334,0,5249,5250,5332,5331,0,5250,5251,5333,5332,0,5251,5253,5335,5333,0,5253,5255,5337,5335,0,5255,5257,5339,5337,0,5257,5259,5341,5339,0,5259,5261,5343,5341,0,5261,5263,5345,5343,0,5263,5265,5347,5345,0,5265,5268,5349,5347,0,5268,5269,5351,5349,0,5269,5271,5353,5351,0,5271,5274,5358,5353,0,5274,5279,5361,5358,0,5279,5281,5363,5361,0,5281,5283,5365,5363,0,5283,5285,5368,5365,0,5285,5288,5372,5368,0,5288,5292,5375,5372,0,5292,5300,5382,5375,0,5300,5307,5389,5382,0,5307,5309,5392,5389,0,5309,5312,5395,5392,0,5312,5314,5398,5395,0,5314,5317,5400,5398,0,5317,5318,5399,5400,0,5318,5315,5397,5399,0,5315,5313,5394,5397,0,5313,5311,5393,5394,0,5311,5308,5390,5393,0,5308,5306,5388,5390,0,5306,5304,5386,5388,0,5304,5302,5384,5386,0,5302,5299,5381,5384,0,5299,5296,5377,5381,0,5296,5293,5373,5377,0,5293,5289,5369,5373,0,5289,5286,5366,5369,0,5286,5276,5356,5366,0,5276,5273,5354,5356,0,5354,5357,5439,5435,0,5357,5370,5450,5439,0,5370,5376,5456,5450,0,5376,5379,5461,5456,0,5379,5383,5464,5461,0,5383,5385,5467,5464,0,5385,5387,5469,5467,0,5387,5391,5472,5469,0,5391,5396,5477,5472,0,5396,5401,5483,5477,0,5401,5403,5485,5483,0,5403,5405,5486,5485,0,5405,5407,5488,5486,0,5407,5409,5490,5488,0,5409,5411,5492,5490,0,5411,5412,5494,5492,0,5412,5410,5493,5494,0,5410,5408,5491,5493,0,5408,5406,5489,5491,0,5406,5404,5487,5489,0,5404,5402,5484,5487,0,5402,5380,5463,5484,0,5380,5378,5460,5463,0,5378,5374,5458,5460,0,5374,5371,5453,5458,0,5371,5367,5451,5453,0,5367,5364,5446,5451,0,5364,5362,5444,5446,0,5362,5360,5443,5444,0,5360,5359,5441,5443,0,5359,5355,5438,5441,0,5355,5352,5434,5438,0,5352,5350,5432,5434,0,5350,5348,5430,5432,0,5348,5346,5428,5430,0,5346,5344,5426,5428,0,5344,5342,5424,5426,0,5342,5340,5422,5424,0,5340,5338,5420,5422,0,5338,5336,5418,5420,0,5336,5334,5416,5418,0,5334,5331,5413,5416,0,5331,5332,5414,5413,0,5332,5333,5415,5414,0,5333,5335,5417,5415,0,5335,5337,5419,5417,0,5337,5339,5421,5419,0,5339,5341,5423,5421,0,5341,5343,5425,5423,0,5343,5345,5427,5425,0,5345,5347,5429,5427,0,5347,5349,5431,5429,0,5349,5351,5433,5431,0,5351,5353,5437,5433,0,5353,5358,5440,5437,0,5358,5361,5442,5440,0,5361,5363,5445,5442,0,5363,5365,5448,5445,0,5365,5368,5452,5448,0,5368,5372,5455,5452,0,5372,5375,5457,5455,0,5375,5382,5465,5457,0,5382,5389,5473,5465,0,5389,5392,5475,5473,0,5392,5395,5478,5475,0,5395,5398,5480,5478,0,5398,5400,5482,5480,0,5400,5399,5481,5482,0,5399,5397,5479,5481,0,5397,5394,5476,5479,0,5394,5393,5474,5476,0,5393,5390,5471,5474,0,5390,5388,5470,5471,0,5388,5386,5468,5470,0,5386,5384,5466,5468,0,5384,5381,5462,5466,0,5381,5377,5459,5462,0,5377,5373,5454,5459,0,5373,5369,5449,5454,0,5369,5366,5447,5449,0,5366,5356,5436,5447,0,5356,5354,5435,5436,0,5435,5439,5519,5515,0,5439,5450,5531,5519,0,5450,5456,5536,5531,0,5456,5461,5542,5536,0,5461,5464,5545,5542,0,5464,5467,5549,5545,0,5467,5469,5551,5549,0,5469,5472,5553,5551,0,5472,5477,5557,5553,0,5477,5483,5564,5557,0,5483,5485,5566,5564,0,5485,5486,5568,5566,0,5486,5488,5570,5568,0,5488,5490,5572,5570,0,5490,5492,5574,5572,0,5492,5494,5576,5574,0,5494,5493,5575,5576,0,5493,5491,5573,5575,0,5491,5489,5571,5573,0,5489,5487,5569,5571,0,5487,5484,5567,5569,0,5484,5463,5546,5567,0,5463,5460,5544,5546,0,5460,5458,5541,5544,0,5458,5453,5538,5541,0,5453,5451,5533,5538,0,5451,5446,5530,5533,0,5446,5444,5526,5530,0,5444,5443,5525,5526,0,5443,5441,5523,5525,0,5441,5438,5521,5523,0,5438,5434,5518,5521,0,5434,5432,5514,5518,0,5432,5430,5512,5514,0,5430,5428,5510,5512,0,5428,5426,5508,5510,0,5426,5424,5506,5508,0,5424,5422,5504,5506,0,5422,5420,5502,5504,0,5420,5418,5500,5502,0,5418,5416,5498,5500,0,5416,5413,5495,5498,0,5413,5414,5496,5495,0,5414,5415,5497,5496,0,5415,5417,5499,5497,0,5417,5419,5501,5499,0,5419,5421,5503,5501,0,5421,5423,5505,5503,0,5423,5425,5507,5505,0,5425,5427,5509,5507,0,5427,5429,5511,5509,0,5429,5431,5513,5511,0,5431,5433,5516,5513,0,5433,5437,5520,5516,0,5437,5440,5522,5520,0,5440,5442,5524,5522,0,5442,5445,5527,5524,0,5445,5448,5532,5527,0,5448,5452,5534,5532,0,5452,5455,5537,5534,0,5455,5457,5540,5537,0,5457,5465,5548,5540,0,5465,5473,5555,5548,0,5473,5475,5559,5555,0,5475,5478,5561,5559,0,5478,5480,5563,5561,0,5480,5482,5565,5563,0,5482,5481,5562,5565,0,5481,5479,5560,5562,0,5479,5476,5558,5560,0,5476,5474,5556,5558,0,5474,5471,5554,5556,0,5471,5470,5552,5554,0,5470,5468,5550,5552,0,5468,5466,5547,5550,0,5466,5462,5543,5547,0,5462,5459,5539,5543,0,5459,5454,5535,5539,0,5454,5449,5529,5535,0,5449,5447,5528,5529,0,5447,5436,5517,5528,0,5436,5435,5515,5517,0,5515,5519,5600,5597,0,5519,5531,5612,5600,0,5531,5536,5618,5612,0,5536,5542,5622,5618,0,5542,5545,5627,5622,0,5545,5549,5630,5627,0,5549,5551,5633,5630,0,5551,5553,5635,5633,0,5553,5557,5639,5635,0,5557,5564,5644,5639,0,5564,5566,5648,5644,0,5566,5568,5650,5648,0,5568,5570,5651,5650,0,5570,5572,5653,5651,0,5572,5574,5655,5653,0,5574,5576,5657,5655,0,5576,5575,5658,5657,0,5575,5573,5656,5658,0,5573,5571,5654,5656,0,5571,5569,5652,5654,0,5569,5567,5649,5652,0,5567,5546,5629,5649,0,5546,5544,5626,5629,0,5544,5541,5624,5626,0,5541,5538,5620,5624,0,5538,5533,5616,5620,0,5533,5530,5613,5616,0,5530,5526,5610,5613,0,5526,5525,5607,5610,0,5525,5523,5605,5607,0,5523,5521,5603,5605,0,5521,5518,5601,5603,0,5518,5514,5596,5601,0,5514,5512,5594,5596,0,5512,5510,5592,5594,0,5510,5508,5590,5592,0,5508,5506,5588,5590,0,5506,5504,5586,5588,0,5504,5502,5584,5586,0,5502,5500,5582,5584,0,5500,5498,5580,5582,0,5498,5495,5577,5580,0,5495,5496,5578,5577,0,5496,5497,5579,5578,0,5497,5499,5581,5579,0,5499,5501,5583,5581,0,5501,5503,5585,5583,0,5503,5505,5587,5585,0,5505,5507,5589,5587,0,5507,5509,5591,5589,0,5509,5511,5593,5591,0,5511,5513,5595,5593,0,5513,5516,5599,5595,0,5516,5520,5602,5599,0,5520,5522,5604,5602,0,5522,5524,5606,5604,0,5524,5527,5609,5606,0,5527,5532,5614,5609,0,5532,5534,5617,5614,0,5534,5537,5619,5617,0,5537,5540,5623,5619,0,5540,5548,5631,5623,0,5548,5555,5638,5631,0,5555,5559,5641,5638,0,5559,5561,5643,5641,0,5561,5563,5646,5643,0,5563,5565,5647,5646,0,5565,5562,5645,5647,0,5562,5560,5642,5645,0,5560,5558,5640,5642,0,5558,5556,5637,5640,0,5556,5554,5636,5637,0,5554,5552,5634,5636,0,5552,5550,5632,5634,0,5550,5547,5628,5632,0,5547,5543,5625,5628,0,5543,5539,5621,5625,0,5539,5535,5615,5621,0,5535,5529,5611,5615,0,5529,5528,5608,5611,0,5528,5517,5598,5608,0,5517,5515,5597,5598,0,5597,5600,5681,5677,0,5600,5612,5692,5681,0,5612,5618,5698,5692,0,5618,5622,5702,5698,0,5622,5627,5708,5702,0,5627,5630,5711,5708,0,5630,5633,5715,5711,0,5633,5635,5717,5715,0,5635,5639,5720,5717,0,5639,5644,5725,5720,0,5644,5648,5730,5725,0,5648,5650,5731,5730,0,5650,5651,5733,5731,0,5651,5653,5735,5733,0,5653,5655,5737,5735,0,5655,5657,5739,5737,0,5657,5658,5740,5739,0,5658,5656,5738,5740,0,5656,5654,5736,5738,0,5654,5652,5734,5736,0,5652,5649,5732,5734,0,5649,5629,5712,5732,0,5629,5626,5710,5712,0,5626,5624,5707,5710,0,5624,5620,5704,5707,0,5620,5616,5700,5704,0,5616,5613,5697,5700,0,5613,5610,5694,5697,0,5610,5607,5689,5694,0,5607,5605,5687,5689,0,5605,5603,5685,5687,0,5603,5601,5683,5685,0,5601,5596,5680,5683,0,5596,5594,5676,5680,0,5594,5592,5674,5676,0,5592,5590,5672,5674,0,5590,5588,5670,5672,0,5588,5586,5668,5670,0,5586,5584,5666,5668,0,5584,5582,5664,5666,0,5582,5580,5662,5664,0,5580,5577,5659,5662,0,5577,5578,5660,5659,0,5578,5579,5661,5660,0,5579,5581,5663,5661,0,5581,5583,5665,5663,0,5583,5585,5667,5665,0,5585,5587,5669,5667,0,5587,5589,5671,5669,0,5589,5591,5673,5671,0,5591,5593,5675,5673,0,5593,5595,5679,5675,0,5595,5599,5682,5679,0,5599,5602,5684,5682,0,5602,5604,5686,5684,0,5604,5606,5688,5686,0,5606,5609,5693,5688,0,5609,5614,5696,5693,0,5614,5617,5699,5696,0,5617,5619,5703,5699,0,5619,5623,5706,5703,0,5623,5631,5714,5706,0,5631,5638,5721,5714,0,5638,5641,5723,5721,0,5641,5643,5726,5723,0,5643,5646,5728,5726,0,5646,5647,5729,5728,0,5647,5645,5727,5729,0,5645,5642,5724,5727,0,5642,5640,5722,5724,0,5640,5637,5719,5722,0,5637,5636,5718,5719,0,5636,5634,5716,5718,0,5634,5632,5713,5716,0,5632,5628,5709,5713,0,5628,5625,5705,5709,0,5625,5621,5701,5705,0,5621,5615,5695,5701,0,5615,5611,5691,5695,0,5611,5608,5690,5691,0,5608,5598,5678,5690,0,5598,5597,5677,5678,0,5677,5681,5767,5764,0,5681,5692,5788,5767,0,5692,5698,5797,5788,0,5698,5702,5805,5797,0,5702,5708,5812,5805,0,5708,5711,5819,5812,0,5711,5715,5825,5819,0,5715,5717,5832,5825,0,5717,5720,5837,5832,0,5720,5725,5843,5837,0,5725,5730,5853,5843,0,5730,5731,5855,5853,0,5731,5733,5859,5855,0,5733,5735,5862,5859,0,5735,5737,5866,5862,0,5737,5739,5868,5866,0,5739,5740,5871,5868,0,5740,5738,5870,5871,0,5738,5736,5867,5870,0,5736,5734,5865,5867,0,5734,5732,5860,5865,0,5732,5712,5826,5860,0,5712,5710,5822,5826,0,5710,5707,5818,5822,0,5707,5704,5813,5818,0,5704,5700,5808,5813,0,5700,5697,5804,5808,0,5697,5694,5799,5804,0,5694,5689,5791,5799,0,5689,5687,5785,5791,0,5687,5685,5780,5785,0,5685,5683,5776,5780,0,5683,5680,5772,5776,0,5680,5676,5769,5772,0,5676,5674,5762,5769,0,5674,5672,5758,5762,0,5672,5670,5755,5758,0,5670,5668,5753,5755,0,5668,5666,5751,5753,0,5666,5664,5747,5751,0,5664,5662,5744,5747,0,5662,5659,5741,5744,0,5659,5660,5742,5741,0,5660,5661,5743,5742,0,5661,5663,5745,5743,0,5663,5665,5749,5745,0,5665,5667,5752,5749,0,5667,5669,5754,5752,0,5669,5671,5756,5754,0,5671,5673,5760,5756,0,5673,5675,5766,5760,0,5675,5679,5771,5766,0,5679,5682,5775,5771,0,5682,5684,5779,5775,0,5684,5686,5782,5779,0,5686,5688,5790,5782,0,5688,5693,5798,5790,0,5693,5696,5803,5798,0,5696,5699,5807,5803,0,5699,5703,5811,5807,0,5703,5706,5815,5811,0,5706,5714,5829,5815,0,5714,5721,5842,5829,0,5721,5723,5845,5842,0,5723,5726,5849,5845,0,5726,5728,5852,5849,0,5728,5729,5851,5852,0,5729,5727,5847,5851,0,5727,5724,5844,5847,0,5724,5722,5841,5844,0,5722,5719,5836,5841,0,5719,5718,5834,5836,0,5718,5716,5830,5834,0,5716,5713,5821,5830,0,5713,5709,5816,5821,0,5709,5705,5809,5816,0,5705,5701,5801,5809,0,5701,5695,5796,5801,0,5695,5691,5787,5796,0,5691,5690,5784,5787,0,5690,5678,5765,5784,0,5678,5677,5764,5765,0,5764,5767,5794,5789,0,5767,5788,5828,5794,0,5788,5797,5838,5828,0,5797,5805,5854,5838,0,5805,5812,5863,5854,0,5812,5819,5874,5863,0,5819,5825,5877,5874,0,5825,5832,5881,5877,0,5832,5837,5884,5881,0,5837,5843,5887,5884,0,5843,5853,5894,5887,0,5853,5855,5895,5894,0,5855,5859,5896,5895,0,5859,5862,5898,5896,0,5862,5866,5900,5898,0,5866,5868,5902,5900,0,5868,5871,5904,5902,0,5871,5870,5903,5904,0,5870,5867,5901,5903,0,5867,5865,5899,5901,0,5865,5860,5897,5899,0,5860,5826,5878,5897,0,5826,5822,5876,5878,0,5822,5818,5873,5876,0,5818,5813,5864,5873,0,5813,5808,5857,5864,0,5808,5804,5850,5857,0,5804,5799,5840,5850,0,5799,5791,5833,5840,0,5791,5785,5824,5833,0,5785,5780,5817,5824,0,5780,5776,5810,5817,0,5776,5772,5802,5810,0,5772,5769,5795,5802,0,5769,5762,5786,5795,0,5762,5758,5781,5786,0,5758,5755,5777,5781,0,5755,5753,5773,5777,0,5753,5751,5768,5773,0,5751,5747,5761,5768,0,5747,5744,5757,5761,0,5744,5741,5746,5757,0,5741,5742,5748,5746,0,5742,5743,5750,5748,0,5743,5745,5759,5750,0,5745,5749,5763,5759,0,5749,5752,5770,5763,0,5752,5754,5774,5770,0,5754,5756,5778,5774,0,5756,5760,5783,5778,0,5760,5766,5793,5783,0,5766,5771,5800,5793,0,5771,5775,5806,5800,0,5775,5779,5814,5806,0,5779,5782,5820,5814,0,5782,5790,5831,5820,0,5790,5798,5839,5831,0,5798,5803,5848,5839,0,5803,5807,5856,5848,0,5807,5811,5861,5856,0,5811,5815,5869,5861,0,5815,5829,5879,5869,0,5829,5842,5886,5879,0,5842,5845,5889,5886,0,5845,5849,5891,5889,0,5849,5852,5893,5891,0,5852,5851,5892,5893,0,5851,5847,5890,5892,0,5847,5844,5888,5890,0,5844,5841,5885,5888,0,5841,5836,5883,5885,0,5836,5834,5882,5883,0,5834,5830,5880,5882,0,5830,5821,5875,5880,0,5821,5816,5872,5875,0,5816,5809,5858,5872,0,5809,5801,5846,5858,0,5801,5796,5835,5846,0,5796,5787,5827,5835,0,5787,5784,5823,5827,0,5784,5765,5792,5823,0,5765,5764,5789,5792,0,5789,5794,5923,5920,0,5794,5828,5935,5923,0,5828,5838,5939,5935,0,5838,5854,5944,5939,0,5854,5863,5949,5944,0,5863,5874,5954,5949,0,5874,5877,5958,5954,0,5877,5881,5961,5958,0,5881,5884,5965,5961,0,5884,5887,5968,5965,0,5887,5894,5973,5968,0,5894,5895,5977,5973,0,5895,5896,5978,5977,0,5896,5898,5980,5978,0,5898,5900,5981,5980,0,5900,5902,5983,5981,0,5902,5904,5985,5983,0,5904,5903,5986,5985,0,5903,5901,5984,5986,0,5901,5899,5982,5984,0,5899,5897,5979,5982,0,5897,5878,5963,5979,0,5878,5876,5959,5963,0,5876,5873,5956,5959,0,5873,5864,5953,5956,0,5864,5857,5950,5953,0,5857,5850,5946,5950,0,5850,5840,5943,5946,0,5840,5833,5940,5943,0,5833,5824,5936,5940,0,5824,5817,5931,5936,0,5817,5810,5929,5931,0,5810,5802,5927,5929,0,5802,5795,5925,5927,0,5795,5786,5922,5925,0,5786,5781,5918,5922,0,5781,5777,5916,5918,0,5777,5773,5914,5916,0,5773,5768,5912,5914,0,5768,5761,5910,5912,0,5761,5757,5908,5910,0,5757,5746,5905,5908,0,5746,5748,5906,5905,0,5748,5750,5907,5906,0,5750,5759,5909,5907,0,5759,5763,5911,5909,0,5763,5770,5913,5911,0,5770,5774,5915,5913,0,5774,5778,5917,5915,0,5778,5783,5919,5917,0,5783,5793,5924,5919,0,5793,5800,5926,5924,0,5800,5806,5928,5926,0,5806,5814,5930,5928,0,5814,5820,5933,5930,0,5820,5831,5937,5933,0,5831,5839,5941,5937,0,5839,5848,5945,5941,0,5848,5856,5948,5945,0,5856,5861,5951,5948,0,5861,5869,5955,5951,0,5869,5879,5962,5955,0,5879,5886,5970,5962,0,5886,5889,5972,5970,0,5889,5891,5975,5972,0,5891,5893,5976,5975,0,5893,5892,5974,5976,0,5892,5890,5971,5974,0,5890,5888,5969,5971,0,5888,5885,5967,5969,0,5885,5883,5966,5967,0,5883,5882,5964,5966,0,5882,5880,5960,5964,0,5880,5875,5957,5960,0,5875,5872,5952,5957,0,5872,5858,5947,5952,0,5858,5846,5942,5947,0,5846,5835,5938,5942,0,5835,5827,5934,5938,0,5827,5823,5932,5934,0,5823,5792,5921,5932,0,5792,5789,5920,5921,0,5920,5923,6002,6000,0,5923,5935,6013,6002,0,5935,5939,6019,6013,0,5939,5944,6023,6019,0,5944,5949,6028,6023,0,5949,5954,6033,6028,0,5954,5958,6037,6033,0,5958,5961,6042,6037,0,5961,5965,6046,6042,0,5965,5968,6050,6046,0,5968,5973,6052,6050,0,5973,5977,6059,6052,0,5977,5978,6060,6059,0,5978,5980,6061,6060,0,5980,5981,6063,6061,0,5981,5983,6064,6063,0,5983,5985,6066,6064,0,5985,5986,6068,6066,0,5986,5984,6067,6068,0,5984,5982,6065,6067,0,5982,5979,6062,6065,0,5979,5963,6048,6062,0,5963,5959,6044,6048,0,5959,5956,6040,6044,0,5956,5953,6038,6040,0,5953,5950,6034,6038,0,5950,5946,6030,6034,0,5946,5943,6027,6030,0,5943,5940,6024,6027,0,5940,5936,6020,6024,0,5936,5931,6016,6020,0,5931,5929,6012,6016,0,5929,5927,6009,6012,0,5927,5925,6007,6009,0,5925,5922,6005,6007,0,5922,5918,6003,6005,0,5918,5916,5998,6003,0,5916,5914,5996,5998,0,5914,5912,5994,5996,0,5912,5910,5992,5994,0,5910,5908,5990,5992,0,5908,5905,5987,5990,0,5905,5906,5988,5987,0,5906,5907,5989,5988,0,5907,5909,5991,5989,0,5909,5911,5993,5991,0,5911,5913,5995,5993,0,5913,5915,5997,5995,0,5915,5917,5999,5997,0,5917,5919,6004,5999,0,5919,5924,6006,6004,0,5924,5926,6008,6006,0,5926,5928,6010,6008,0,5928,5930,6015,6010,0,5930,5933,6018,6015,0,5933,5937,6021,6018,0,5937,5941,6025,6021,0,5941,5945,6029,6025,0,5945,5948,6032,6029,0,5948,5951,6035,6032,0,5951,5955,6039,6035,0,5955,5962,6045,6039,0,5962,5970,6053,6045,0,5970,5972,6055,6053,0,5972,5975,6057,6055,0,5975,5976,6058,6057,0,5976,5974,6056,6058,0,5974,5971,6054,6056,0,5971,5969,6051,6054,0,5969,5967,6049,6051,0,5967,5966,6047,6049,0,5966,5964,6043,6047,0,5964,5960,6041,6043,0,5960,5957,6036,6041,0,5957,5952,6031,6036,0,5952,5947,6026,6031,0,5947,5942,6022,6026,0,5942,5938,6017,6022,0,5938,5934,6014,6017,0,5934,5932,6011,6014,0,5932,5921,6001,6011,0,5921,5920,6000,6001,0,6000,6002,6084,6080,0,6002,6013,6094,6084,0,6013,6019,6100,6094,0,6019,6023,6104,6100,0,6023,6028,6109,6104,0,6028,6033,6114,6109,0,6033,6037,6119,6114,0,6037,6042,6123,6119,0,6042,6046,6127,6123,0,6046,6050,6132,6127,0,6050,6052,6134,6132,0,6052,6059,6141,6134,0,6059,6060,6142,6141,0,6060,6061,6143,6142,0,6061,6063,6144,6143,0,6063,6064,6146,6144,0,6064,6066,6148,6146,0,6066,6068,6150,6148,0,6068,6067,6149,6150,0,6067,6065,6147,6149,0,6065,6062,6145,6147,0,6062,6048,6130,6145,0,6048,6044,6126,6130,0,6044,6040,6124,6126,0,6040,6038,6120,6124,0,6038,6034,6116,6120,0,6034,6030,6113,6116,0,6030,6027,6110,6113,0,6027,6024,6106,6110,0,6024,6020,6102,6106,0,6020,6016,6098,6102,0,6016,6012,6095,6098,0,6012,6009,6091,6095,0,6009,6007,6089,6091,0,6007,6005,6087,6089,0,6005,6003,6085,6087,0,6003,5998,6081,6085,0,5998,5996,6079,6081,0,5996,5994,6076,6079,0,5994,5992,6074,6076,0,5992,5990,6072,6074,0,5990,5987,6069,6072,0,5987,5988,6070,6069,0,5988,5989,6071,6070,0,5989,5991,6073,6071,0,5991,5993,6075,6073,0,5993,5995,6077,6075,0,5995,5997,6078,6077,0,5997,5999,6082,6078,0,5999,6004,6086,6082,0,6004,6006,6088,6086,0,6006,6008,6090,6088,0,6008,6010,6093,6090,0,6010,6015,6097,6093,0,6015,6018,6101,6097,0,6018,6021,6105,6101,0,6021,6025,6108,6105,0,6025,6029,6111,6108,0,6029,6032,6115,6111,0,6032,6035,6118,6115,0,6035,6039,6121,6118,0,6039,6045,6128,6121,0,6045,6053,6136,6128,0,6053,6055,6138,6136,0,6055,6057,6140,6138,0,6057,6058,6139,6140,0,6058,6056,6137,6139,0,6056,6054,6135,6137,0,6054,6051,6133,6135,0,6051,6049,6131,6133,0,6049,6047,6129,6131,0,6047,6043,6125,6129,0,6043,6041,6122,6125,0,6041,6036,6117,6122,0,6036,6031,6112,6117,0,6031,6026,6107,6112,0,6026,6022,6103,6107,0,6022,6017,6099,6103,0,6017,6014,6096,6099,0,6014,6011,6092,6096,0,6011,6001,6083,6092,0,6001,6000,6080,6083,0,6080,6084,6164,6162,0,6084,6094,6175,6164,0,6094,6100,6181,6175,0,6100,6104,6186,6181,0,6104,6109,6190,6186,0,6109,6114,6194,6190,0,6114,6119,6199,6194,0,6119,6123,6205,6199,0,6123,6127,6208,6205,0,6127,6132,6212,6208,0,6132,6134,6216,6212,0,6134,6141,6221,6216,0,6141,6142,6224,6221,0,6142,6143,6225,6224,0,6143,6144,6226,6225,0,6144,6146,6228,6226,0,6146,6148,6230,6228,0,6148,6150,6231,6230,0,6150,6149,6232,6231,0,6149,6147,6229,6232,0,6147,6145,6227,6229,0,6145,6130,6214,6227,0,6130,6126,6210,6214,0,6126,6124,6206,6210,0,6124,6120,6204,6206,0,6120,6116,6200,6204,0,6116,6113,6196,6200,0,6113,6110,6192,6196,0,6110,6106,6188,6192,0,6106,6102,6185,6188,0,6102,6098,6182,6185,0,6098,6095,6178,6182,0,6095,6091,6173,6178,0,6091,6089,6171,6173,0,6089,6087,6169,6171,0,6087,6085,6167,6169,0,6085,6081,6165,6167,0,6081,6079,6161,6165,0,6079,6076,6158,6161,0,6076,6074,6156,6158,0,6074,6072,6154,6156,0,6072,6069,6151,6154,0,6069,6070,6152,6151,0,6070,6071,6153,6152,0,6071,6073,6155,6153,0,6073,6075,6157,6155,0,6075,6077,6159,6157,0,6077,6078,6160,6159,0,6078,6082,6166,6160,0,6082,6086,6168,6166,0,6086,6088,6170,6168,0,6088,6090,6172,6170,0,6090,6093,6176,6172,0,6093,6097,6179,6176,0,6097,6101,6183,6179,0,6101,6105,6187,6183,0,6105,6108,6191,6187,0,6108,6111,6195,6191,0,6111,6115,6197,6195,0,6115,6118,6201,6197,0,6118,6121,6202,6201,0,6121,6128,6211,6202,0,6128,6136,6218,6211,0,6136,6138,6220,6218,0,6138,6140,6223,6220,0,6140,6139,6222,6223,0,6139,6137,6219,6222,0,6137,6135,6217,6219,0,6135,6133,6215,6217,0,6133,6131,6213,6215,0,6131,6129,6209,6213,0,6129,6125,6207,6209,0,6125,6122,6203,6207,0,6122,6117,6198,6203,0,6117,6112,6193,6198,0,6112,6107,6189,6193,0,6107,6103,6184,6189,0,6103,6099,6180,6184,0,6099,6096,6177,6180,0,6096,6092,6174,6177,0,6092,6083,6163,6174,0,6083,6080,6162,6163,0,6162,6164,6244,6242,0,6164,6175,6255,6244,0,6175,6181,6259,6255,0,6181,6186,6265,6259,0,6186,6190,6270,6265,0,6190,6194,6274,6270,0,6194,6199,6278,6274,0,6199,6205,6282,6278,0,6205,6208,6288,6282,0,6208,6212,6292,6288,0,6212,6216,6297,6292,0,6216,6221,6300,6297,0,6221,6224,6306,6300,0,6224,6225,6307,6306,0,6225,6226,6308,6307,0,6226,6228,6309,6308,0,6228,6230,6311,6309,0,6230,6231,6313,6311,0,6231,6232,6314,6313,0,6232,6229,6312,6314,0,6229,6227,6310,6312,0,6227,6214,6298,6310,0,6214,6210,6295,6298,0,6210,6206,6291,6295,0,6206,6204,6289,6291,0,6204,6200,6284,6289,0,6200,6196,6280,6284,0,6196,6192,6276,6280,0,6192,6188,6273,6276,0,6188,6185,6269,6273,0,6185,6182,6266,6269,0,6182,6178,6262,6266,0,6178,6173,6258,6262,0,6173,6171,6254,6258,0,6171,6169,6251,6254,0,6169,6167,6249,6251,0,6167,6165,6247,6249,0,6165,6161,6246,6247,0,6161,6158,6240,6246,0,6158,6156,6238,6240,0,6156,6154,6236,6238,0,6154,6151,6233,6236,0,6151,6152,6234,6233,0,6152,6153,6235,6234,0,6153,6155,6237,6235,0,6155,6157,6239,6237,0,6157,6159,6241,6239,0,6159,6160,6245,6241,0,6160,6166,6248,6245,0,6166,6168,6250,6248,0,6168,6170,6252,6250,0,6170,6172,6257,6252,0,6172,6176,6261,6257,0,6176,6179,6263,6261,0,6179,6183,6267,6263,0,6183,6187,6271,6267,0,6187,6191,6275,6271,0,6191,6195,6279,6275,0,6195,6197,6281,6279,0,6197,6201,6285,6281,0,6201,6202,6287,6285,0,6202,6211,6294,6287,0,6211,6218,6302,6294,0,6218,6220,6304,6302,0,6220,6223,6305,6304,0,6223,6222,6303,6305,0,6222,6219,6301,6303,0,6219,6217,6299,6301,0,6217,6215,6296,6299,0,6215,6213,6293,6296,0,6213,6209,6290,6293,0,6209,6207,6286,6290,0,6207,6203,6283,6286,0,6203,6198,6277,6283,0,6198,6193,6272,6277,0,6193,6189,6268,6272,0,6189,6184,6264,6268,0,6184,6180,6260,6264,0,6180,6177,6256,6260,0,6177,6174,6253,6256,0,6174,6163,6243,6253,0,6163,6162,6242,6243,0,6242,6244,6323,6322,0,6244,6255,6335,6323,0,6255,6259,6339,6335,0,6259,6265,6347,6339,0,6265,6270,6353,6347,0,6270,6274,6357,6353,0,6274,6278,6360,6357,0,6278,6282,6365,6360,0,6282,6288,6371,6365,0,6288,6292,6378,6371,0,6292,6297,6385,6378,0,6297,6300,6389,6385,0,6300,6306,6400,6389,0,6306,6307,6401,6400,0,6307,6308,6402,6401,0,6308,6309,6405,6402,0,6309,6311,6406,6405,0,6311,6313,6408,6406,0,6313,6314,6410,6408,0,6314,6312,6409,6410,0,6312,6310,6407,6409,0,6310,6298,6390,6407,0,6298,6295,6386,6390,0,6295,6291,6382,6386,0,6291,6289,6377,6382,0,6289,6284,6374,6377,0,6284,6280,6367,6374,0,6280,6276,6363,6367,0,6276,6273,6359,6363,0,6273,6269,6355,6359,0,6269,6266,6352,6355,0,6266,6262,6348,6352,0,6262,6258,6342,6348,0,6258,6254,6338,6342,0,6254,6251,6334,6338,0,6251,6249,6331,6334,0,6249,6247,6329,6331,0,6247,6246,6328,6329,0,6246,6240,6325,6328,0,6240,6238,6320,6325,0,6238,6236,6318,6320,0,6236,6233,6315,6318,0,6233,6234,6316,6315,0,6234,6235,6317,6316,0,6235,6237,6319,6317,0,6237,6239,6321,6319,0,6239,6241,6326,6321,0,6241,6245,6327,6326,0,6245,6248,6330,6327,0,6248,6250,6332,6330,0,6250,6252,6336,6332,0,6252,6257,6340,6336,0,6257,6261,6344,6340,0,6261,6263,6350,6344,0,6263,6267,6354,6350,0,6267,6271,6358,6354,0,6271,6275,6362,6358,0,6275,6279,6364,6362,0,6279,6281,6368,6364,0,6281,6285,6373,6368,0,6285,6287,6376,6373,0,6287,6294,6384,6376,0,6294,6302,6396,6384,0,6302,6304,6398,6396,0,6304,6305,6399,6398,0,6305,6303,6397,6399,0,6303,6301,6393,6397,0,6301,6299,6388,6393,0,6299,6296,6383,6388,0,6296,6293,6379,6383,0,6293,6290,6375,6379,0,6290,6286,6370,6375,0,6286,6283,6366,6370,0,6283,6277,6361,6366,0,6277,6272,6356,6361,0,6272,6268,6351,6356,0,6268,6264,6346,6351,0,6264,6260,6341,6346,0,6260,6256,6337,6341,0,6256,6253,6333,6337,0,6253,6243,6324,6333,0,6243,6242,6322,6324,0,6322,6323,6391,6387,0,6323,6335,6417,6391,0,6335,6339,6421,6417,0,6339,6347,6427,6421,0,6347,6353,6432,6427,0,6353,6357,6436,6432,0,6357,6360,6439,6436,0,6360,6365,6443,6439,0,6365,6371,6449,6443,0,6371,6378,6454,6449,0,6378,6385,6459,6454,0,6385,6389,6463,6459,0,6389,6400,6470,6463,0,6400,6401,6471,6470,0,6401,6402,6472,6471,0,6402,6405,6473,6472,0,6405,6406,6474,6473,0,6406,6408,6476,6474,0,6408,6410,6478,6476,0,6410,6409,6477,6478,0,6409,6407,6475,6477,0,6407,6390,6464,6475,0,6390,6386,6461,6464,0,6386,6382,6457,6461,0,6382,6377,6455,6457,0,6377,6374,6451,6455,0,6374,6367,6446,6451,0,6367,6363,6442,6446,0,6363,6359,6438,6442,0,6359,6355,6435,6438,0,6355,6352,6431,6435,0,6352,6348,6428,6431,0,6348,6342,6424,6428,0,6342,6338,6420,6424,0,6338,6334,6416,6420,0,6334,6331,6413,6416,0,6331,6329,6411,6413,0,6329,6328,6404,6411,0,6328,6325,6394,6404,0,6325,6320,6380,6394,0,6320,6318,6369,6380,0,6318,6315,6343,6369,0,6315,6316,6345,6343,0,6316,6317,6349,6345,0,6317,6319,6372,6349,0,6319,6321,6381,6372,0,6321,6326,6395,6381,0,6326,6327,6403,6395,0,6327,6330,6412,6403,0,6330,6332,6414,6412,0,6332,6336,6418,6414,0,6336,6340,6423,6418,0,6340,6344,6425,6423,0,6344,6350,6429,6425,0,6350,6354,6433,6429,0,6354,6358,6437,6433,0,6358,6362,6441,6437,0,6362,6364,6444,6441,0,6364,6368,6447,6444,0,6368,6373,6450,6447,0,6373,6376,6453,6450,0,6376,6384,6460,6453,0,6384,6396,6466,6460,0,6396,6398,6468,6466,0,6398,6399,6469,6468,0,6399,6397,6467,6469,0,6397,6393,6465,6467,0,6393,6388,6462,6465,0,6388,6383,6458,6462,0,6383,6379,6456,6458,0,6379,6375,6452,6456,0,6375,6370,6448,6452,0,6370,6366,6445,6448,0,6366,6361,6440,6445,0,6361,6356,6434,6440,0,6356,6351,6430,6434,0,6351,6346,6426,6430,0,6346,6341,6422,6426,0,6341,6337,6419,6422,0,6337,6333,6415,6419,0,6333,6324,6392,6415,0,6324,6322,6387,6392,0,6387,6391,6485,6484,0,6391,6417,6496,6485,0,6417,6421,6501,6496,0,6421,6427,6506,6501,0,6427,6432,6511,6506,0,6432,6436,6515,6511,0,6436,6439,6518,6515,0,6439,6443,6522,6518,0,6443,6449,6527,6522,0,6449,6454,6533,6527,0,6454,6459,6538,6533,0,6459,6463,6543,6538,0,6463,6470,6547,6543,0,6470,6471,6553,6547,0,6471,6472,6554,6553,0,6472,6473,6555,6554,0,6473,6474,6556,6555,0,6474,6476,6557,6556,0,6476,6478,6559,6557,0,6478,6477,6560,6559,0,6477,6475,6558,6560,0,6475,6464,6552,6558,0,6464,6461,6546,6552,0,6461,6457,6544,6546,0,6457,6455,6540,6544,0,6455,6451,6536,6540,0,6451,6446,6532,6536,0,6446,6442,6528,6532,0,6442,6438,6523,6528,0,6438,6435,6520,6523,0,6435,6431,6516,6520,0,6431,6428,6512,6516,0,6428,6424,6508,6512,0,6424,6420,6504,6508,0,6420,6416,6500,6504,0,6416,6413,6497,6500,0,6413,6411,6494,6497,0,6411,6404,6492,6494,0,6404,6394,6490,6492,0,6394,6380,6487,6490,0,6380,6369,6482,6487,0,6369,6343,6479,6482,0,6343,6345,6480,6479,0,6345,6349,6481,6480,0,6349,6372,6483,6481,0,6372,6381,6488,6483,0,6381,6395,6489,6488,0,6395,6403,6491,6489,0,6403,6412,6493,6491,0,6412,6414,6498,6493,0,6414,6418,6503,6498,0,6418,6423,6507,6503,0,6423,6425,6509,6507,0,6425,6429,6513,6509,0,6429,6433,6517,6513,0,6433,6437,6521,6517,0,6437,6441,6525,6521,0,6441,6444,6529,6525,0,6444,6447,6531,6529,0,6447,6450,6534,6531,0,6450,6453,6537,6534,0,6453,6460,6541,6537,0,6460,6466,6549,6541,0,6466,6468,6551,6549,0,6468,6469,6550,6551,0,6469,6467,6548,6550,0,6467,6465,6545,6548,0,6465,6462,6542,6545,0,6462,6458,6539,6542,0,6458,6456,6535,6539,0,6456,6452,6530,6535,0,6452,6448,6526,6530,0,6448,6445,6524,6526,0,6445,6440,6519,6524,0,6440,6434,6514,6519,0,6434,6430,6510,6514,0,6430,6426,6505,6510,0,6426,6422,6502,6505,0,6422,6419,6499,6502,0,6419,6415,6495,6499,0,6415,6392,6486,6495,0,6392,6387,6484,6486,0,6484,6485,6565,6564,0,6485,6496,6576,6565,0,6496,6501,6582,6576,0,6501,6506,6586,6582,0,6506,6511,6591,6586,0,6511,6515,6594,6591,0,6515,6518,6598,6594,0,6518,6522,6602,6598,0,6522,6527,6606,6602,0,6527,6533,6611,6606,0,6533,6538,6617,6611,0,6538,6543,6622,6617,0,6543,6547,6627,6622,0,6547,6553,6634,6627,0,6553,6554,6636,6634,0,6554,6555,6637,6636,0,6555,6556,6638,6637,0,6556,6557,6639,6638,0,6557,6559,6640,6639,0,6559,6560,6642,6640,0,6560,6558,6641,6642,0,6558,6552,6635,6641,0,6552,6546,6633,6635,0,6546,6544,6628,6633,0,6544,6540,6624,6628,0,6540,6536,6621,6624,0,6536,6532,6616,6621,0,6532,6528,6612,6616,0,6528,6523,6608,6612,0,6523,6520,6603,6608,0,6520,6516,6600,6603,0,6516,6512,6596,6600,0,6512,6508,6592,6596,0,6508,6504,6588,6592,0,6504,6500,6584,6588,0,6500,6497,6580,6584,0,6497,6494,6578,6580,0,6494,6492,6574,6578,0,6492,6490,6572,6574,0,6490,6487,6569,6572,0,6487,6482,6566,6569,0,6482,6479,6561,6566,0,6479,6480,6562,6561,0,6480,6481,6563,6562,0,6481,6483,6568,6563,0,6483,6488,6570,6568,0,6488,6489,6571,6570,0,6489,6491,6573,6571,0,6491,6493,6577,6573,0,6493,6498,6581,6577,0,6498,6503,6585,6581,0,6503,6507,6589,6585,0,6507,6509,6593,6589,0,6509,6513,6597,6593,0,6513,6517,6601,6597,0,6517,6521,6605,6601,0,6521,6525,6609,6605,0,6525,6529,6613,6609,0,6529,6531,6615,6613,0,6531,6534,6618,6615,0,6534,6537,6620,6618,0,6537,6541,6625,6620,0,6541,6549,6631,6625,0,6549,6551,6632,6631,0,6551,6550,6630,6632,0,6550,6548,6629,6630,0,6548,6545,6626,6629,0,6545,6542,6623,6626,0,6542,6539,6619,6623,0,6539,6535,6614,6619,0,6535,6530,6610,6614,0,6530,6526,6607,6610,0,6526,6524,6604,6607,0,6524,6519,6599,6604,0,6519,6514,6595,6599,0,6514,6510,6590,6595,0,6510,6505,6587,6590,0,6505,6502,6583,6587,0,6502,6499,6579,6583,0,6499,6495,6575,6579,0,6495,6486,6567,6575,0,6486,6484,6564,6567,0,6564,6565,6647,6646,0,6565,6576,6658,6647,0,6576,6582,6662,6658,0,6582,6586,6667,6662,0,6586,6591,6672,6667,0,6591,6594,6676,6672,0,6594,6598,6680,6676,0,6598,6602,6684,6680,0,6602,6606,6688,6684,0,6606,6611,6693,6688,0,6611,6617,6698,6693,0,6617,6622,6704,6698,0,6622,6627,6709,6704,0,6627,6634,6715,6709,0,6634,6636,6718,6715,0,6636,6637,6719,6718,0,6637,6638,6720,6719,0,6638,6639,6721,6720,0,6639,6640,6722,6721,0,6640,6642,6724,6722,0,6642,6641,6723,6724,0,6641,6635,6717,6723,0,6635,6633,6716,6717,0,6633,6628,6711,6716,0,6628,6624,6706,6711,0,6624,6621,6703,6706,0,6621,6616,6699,6703,0,6616,6612,6695,6699,0,6612,6608,6690,6695,0,6608,6603,6686,6690,0,6603,6600,6682,6686,0,6600,6596,6678,6682,0,6596,6592,6674,6678,0,6592,6588,6670,6674,0,6588,6584,6666,6670,0,6584,6580,6663,6666,0,6580,6578,6661,6663,0,6578,6574,6656,6661,0,6574,6572,6654,6656,0,6572,6569,6651,6654,0,6569,6566,6649,6651,0,6566,6561,6643,6649,0,6561,6562,6644,6643,0,6562,6563,6645,6644,0,6563,6568,6650,6645,0,6568,6570,6652,6650,0,6570,6571,6653,6652,0,6571,6573,6655,6653,0,6573,6577,6659,6655,0,6577,6581,6665,6659,0,6581,6585,6669,6665,0,6585,6589,6673,6669,0,6589,6593,6675,6673,0,6593,6597,6679,6675,0,6597,6601,6683,6679,0,6601,6605,6687,6683,0,6605,6609,6691,6687,0,6609,6613,6694,6691,0,6613,6615,6697,6694,0,6615,6618,6701,6697,0,6618,6620,6702,6701,0,6620,6625,6707,6702,0,6625,6631,6713,6707,0,6631,6632,6714,6713,0,6632,6630,6712,6714,0,6630,6629,6710,6712,0,6629,6626,6708,6710,0,6626,6623,6705,6708,0,6623,6619,6700,6705,0,6619,6614,6696,6700,0,6614,6610,6692,6696,0,6610,6607,6689,6692,0,6607,6604,6685,6689,0,6604,6599,6681,6685,0,6599,6595,6677,6681,0,6595,6590,6671,6677,0,6590,6587,6668,6671,0,6587,6583,6664,6668,0,6583,6579,6660,6664,0,6579,6575,6657,6660,0,6575,6567,6648,6657,0,6567,6564,6646,6648,0,6646,6647,6729,6728,0,6647,6658,6738,6729,0,6658,6662,6742,6738,0,6662,6667,6748,6742,0,6667,6672,6753,6748,0,6672,6676,6756,6753,0,6676,6680,6760,6756,0,6680,6684,6764,6760,0,6684,6688,6768,6764,0,6688,6693,6773,6768,0,6693,6698,6777,6773,0,6698,6704,6782,6777,0,6704,6709,6787,6782,0,6709,6715,6793,6787,0,6715,6718,6798,6793,0,6718,6719,6801,6798,0,6719,6720,6802,6801,0,6720,6721,6803,6802,0,6721,6722,6804,6803,0,6722,6724,6806,6804,0,6724,6723,6805,6806,0,6723,6717,6800,6805,0,6717,6716,6799,6800,0,6716,6711,6797,6799,0,6711,6706,6792,6797,0,6706,6703,6788,6792,0,6703,6699,6783,6788,0,6699,6695,6779,6783,0,6695,6690,6774,6779,0,6690,6686,6770,6774,0,6686,6682,6766,6770,0,6682,6678,6762,6766,0,6678,6674,6758,6762,0,6674,6670,6754,6758,0,6670,6666,6750,6754,0,6666,6663,6746,6750,0,6663,6661,6744,6746,0,6661,6656,6741,6744,0,6656,6654,6736,6741,0,6654,6651,6733,6736,0,6651,6649,6731,6733,0,6649,6643,6725,6731,0,6643,6644,6726,6725,0,6644,6645,6727,6726,0,6645,6650,6732,6727,0,6650,6652,6734,6732,0,6652,6653,6735,6734,0,6653,6655,6739,6735,0,6655,6659,6743,6739,0,6659,6665,6747,6743,0,6665,6669,6751,6747,0,6669,6673,6755,6751,0,6673,6675,6759,6755,0,6675,6679,6763,6759,0,6679,6683,6767,6763,0,6683,6687,6771,6767,0,6687,6691,6775,6771,0,6691,6694,6778,6775,0,6694,6697,6781,6778,0,6697,6701,6785,6781,0,6701,6702,6786,6785,0,6702,6707,6790,6786,0,6707,6713,6795,6790,0,6713,6714,6796,6795,0,6714,6712,6794,6796,0,6712,6710,6791,6794,0,6710,6708,6789,6791,0,6708,6705,6784,6789,0,6705,6700,6780,6784,0,6700,6696,6776,6780,0,6696,6692,6772,6776,0,6692,6689,6769,6772,0,6689,6685,6765,6769,0,6685,6681,6761,6765,0,6681,6677,6757,6761,0,6677,6671,6752,6757,0,6671,6668,6749,6752,0,6668,6664,6745,6749,0,6664,6660,6740,6745,0,6660,6657,6737,6740,0,6657,6648,6730,6737,0,6648,6646,6728,6730,0,6728,6729,6811,6810,0,6729,6738,6819,6811,0,6738,6742,6823,6819,0,6742,6748,6828,6823,0,6748,6753,6832,6828,0,6753,6756,6836,6832,0,6756,6760,6840,6836,0,6760,6764,6844,6840,0,6764,6768,6848,6844,0,6768,6773,6852,6848,0,6773,6777,6857,6852,0,6777,6782,6861,6857,0,6782,6787,6866,6861,0,6787,6793,6872,6866,0,6793,6798,6879,6872,0,6798,6801,6881,6879,0,6801,6802,6883,6881,0,6802,6803,6885,6883,0,6803,6804,6886,6885,0,6804,6806,6887,6886,0,6806,6805,6888,6887,0,6805,6800,6884,6888,0,6800,6799,6882,6884,0,6799,6797,6880,6882,0,6797,6792,6878,6880,0,6792,6788,6874,6878,0,6788,6783,6869,6874,0,6783,6779,6864,6869,0,6779,6774,6859,6864,0,6774,6770,6855,6859,0,6770,6766,6851,6855,0,6766,6762,6847,6851,0,6762,6758,6842,6847,0,6758,6754,6838,6842,0,6754,6750,6834,6838,0,6750,6746,6831,6834,0,6746,6744,6827,6831,0,6744,6741,6824,6827,0,6741,6736,6820,6824,0,6736,6733,6816,6820,0,6733,6731,6813,6816,0,6731,6725,6807,6813,0,6725,6726,6808,6807,0,6726,6727,6809,6808,0,6727,6732,6814,6809,0,6732,6734,6815,6814,0,6734,6735,6818,6815,0,6735,6739,6822,6818,0,6739,6743,6826,6822,0,6743,6747,6830,6826,0,6747,6751,6835,6830,0,6751,6755,6839,6835,0,6755,6759,6843,6839,0,6759,6763,6846,6843,0,6763,6767,6850,6846,0,6767,6771,6854,6850,0,6771,6775,6858,6854,0,6775,6778,6862,6858,0,6778,6781,6865,6862,0,6781,6785,6868,6865,0,6785,6786,6870,6868,0,6786,6790,6873,6870,0,6790,6795,6877,6873,0,6795,6796,6876,6877,0,6796,6794,6875,6876,0,6794,6791,6871,6875,0,6791,6789,6867,6871,0,6789,6784,6863,6867,0,6784,6780,6860,6863,0,6780,6776,6856,6860,0,6776,6772,6853,6856,0,6772,6769,6849,6853,0,6769,6765,6845,6849,0,6765,6761,6841,6845,0,6761,6757,6837,6841,0,6757,6752,6833,6837,0,6752,6749,6829,6833,0,6749,6745,6825,6829,0,6745,6740,6821,6825,0,6740,6737,6817,6821,0,6737,6730,6812,6817,0,6730,6728,6810,6812,0,6810,6811,6893,6892,0,6811,6819,6900,6893,0,6819,6823,6904,6900,0,6823,6828,6908,6904,0,6828,6832,6912,6908,0,6832,6836,6916,6912,0,6836,6840,6920,6916,0,6840,6844,6924,6920,0,6844,6848,6928,6924,0,6848,6852,6932,6928,0,6852,6857,6937,6932,0,6857,6861,6941,6937,0,6861,6866,6946,6941,0,6866,6872,6951,6946,0,6872,6879,6959,6951,0,6879,6881,6962,6959,0,6881,6883,6964,6962,0,6883,6885,6966,6964,0,6885,6886,6968,6966,0,6886,6887,6969,6968,0,6887,6888,6970,6969,0,6888,6884,6967,6970,0,6884,6882,6965,6967,0,6882,6880,6963,6965,0,6880,6878,6961,6963,0,6878,6874,6960,6961,0,6874,6869,6954,6960,0,6869,6864,6947,6954,0,6864,6859,6943,6947,0,6859,6855,6939,6943,0,6855,6851,6935,6939,0,6851,6847,6931,6935,0,6847,6842,6925,6931,0,6842,6838,6922,6925,0,6838,6834,6918,6922,0,6834,6831,6915,6918,0,6831,6827,6911,6915,0,6827,6824,6907,6911,0,6824,6820,6903,6907,0,6820,6816,6898,6903,0,6816,6813,6895,6898,0,6813,6807,6889,6895,0,6807,6808,6890,6889,0,6808,6809,6891,6890,0,6809,6814,6896,6891,0,6814,6815,6897,6896,0,6815,6818,6902,6897,0,6818,6822,6906,6902,0,6822,6826,6910,6906,0,6826,6830,6914,6910,0,6830,6835,6919,6914,0,6835,6839,6923,6919,0,6839,6843,6927,6923,0,6843,6846,6929,6927,0,6846,6850,6934,6929,0,6850,6854,6938,6934,0,6854,6858,6942,6938,0,6858,6862,6945,6942,0,6862,6865,6949,6945,0,6865,6868,6950,6949,0,6868,6870,6953,6950,0,6870,6873,6956,6953,0,6873,6877,6958,6956,0,6877,6876,6957,6958,0,6876,6875,6955,6957,0,6875,6871,6952,6955,0,6871,6867,6948,6952,0,6867,6863,6944,6948,0,6863,6860,6940,6944,0,6860,6856,6936,6940,0,6856,6853,6933,6936,0,6853,6849,6930,6933,0,6849,6845,6926,6930,0,6845,6841,6921,6926,0,6841,6837,6917,6921,0,6837,6833,6913,6917,0,6833,6829,6909,6913,0,6829,6825,6905,6909,0,6825,6821,6901,6905,0,6821,6817,6899,6901,0,6817,6812,6894,6899,0,6812,6810,6892,6894,0,6892,6893,6975,6974,0,6893,6900,6980,6975,0,6900,6904,6985,6980,0,6904,6908,6989,6985,0,6908,6912,6994,6989,0,6912,6916,6998,6994,0,6916,6920,7001,6998,0,6920,6924,7005,7001,0,6924,6928,7010,7005,0,6928,6932,7014,7010,0,6932,6937,7019,7014,0,6937,6941,7023,7019,0,6941,6946,7027,7023,0,6946,6951,7032,7027,0,6951,6959,7040,7032,0,6959,6962,7043,7040,0,6962,6964,7045,7043,0,6964,6966,7047,7045,0,6966,6968,7050,7047,0,6968,6969,7051,7050,0,6969,6970,7052,7051,0,6970,6967,7049,7052,0,6967,6965,7048,7049,0,6965,6963,7046,7048,0,6963,6961,7044,7046,0,6961,6960,7042,7044,0,6960,6954,7037,7042,0,6954,6947,7030,7037,0,6947,6943,7026,7030,0,6943,6939,7022,7026,0,6939,6935,7017,7022,0,6935,6931,7013,7017,0,6931,6925,7008,7013,0,6925,6922,7004,7008,0,6922,6918,7000,7004,0,6918,6915,6997,7000,0,6915,6911,6993,6997,0,6911,6907,6991,6993,0,6907,6903,6986,6991,0,6903,6898,6982,6986,0,6898,6895,6977,6982,0,6895,6889,6971,6977,0,6889,6890,6972,6971,0,6890,6891,6973,6972,0,6891,6896,6978,6973,0,6896,6897,6981,6978,0,6897,6902,6984,6981,0,6902,6906,6988,6984,0,6906,6910,6992,6988,0,6910,6914,6996,6992,0,6914,6919,7002,6996,0,6919,6923,7006,7002,0,6923,6927,7009,7006,0,6927,6929,7012,7009,0,6929,6934,7016,7012,0,6934,6938,7021,7016,0,6938,6942,7024,7021,0,6942,6945,7028,7024,0,6945,6949,7031,7028,0,6949,6950,7034,7031,0,6950,6953,7035,7034,0,6953,6956,7038,7035,0,6956,6958,7041,7038,0,6958,6957,7039,7041,0,6957,6955,7036,7039,0,6955,6952,7033,7036,0,6952,6948,7029,7033,0,6948,6944,7025,7029,0,6944,6940,7020,7025,0,6940,6936,7018,7020,0,6936,6933,7015,7018,0,6933,6930,7011,7015,0,6930,6926,7007,7011,0,6926,6921,7003,7007,0,6921,6917,6999,7003,0,6917,6913,6995,6999,0,6913,6909,6990,6995,0,6909,6905,6987,6990,0,6905,6901,6983,6987,0,6901,6899,6979,6983,0,6899,6894,6976,6979,0,6894,6892,6974,6976,0,6974,6975,7053,7054,0,6975,6980,7059,7053,0,6980,6985,7065,7059,0,6985,6989,7069,7065,0,6989,6994,7073,7069,0,6994,6998,7077,7073,0,6998,7001,7081,7077,0,7001,7005,7084,7081,0,7005,7010,7088,7084,0,7010,7014,7092,7088,0,7014,7019,7097,7092,0,7019,7023,7102,7097,0,7023,7027,7106,7102,0,7027,7032,7110,7106,0,7032,7040,7116,7110,0,7040,7043,7123,7116,0,7043,7045,7125,7123,0,7045,7047,7127,7125,0,7047,7050,7129,7127,0,7050,7051,7131,7129,0,7051,7052,7133,7131,0,7052,7049,7134,7133,0,7049,7048,7132,7134,0,7048,7046,7130,7132,0,7046,7044,7128,7130,0,7044,7042,7126,7128,0,7042,7037,7124,7126,0,7037,7030,7117,7124,0,7030,7026,7111,7117,0,7026,7022,7107,7111,0,7022,7017,7103,7107,0,7017,7013,7099,7103,0,7013,7008,7094,7099,0,7008,7004,7089,7094,0,7004,7000,7085,7089,0,7000,6997,7082,7085,0,6997,6993,7078,7082,0,6993,6991,7074,7078,0,6991,6986,7070,7074,0,6986,6982,7066,7070,0,6982,6977,7062,7066,0,6977,6971,7056,7062,0,6971,6972,7055,7056,0,6972,6973,7058,7055,0,6973,6978,7061,7058,0,6978,6981,7064,7061,0,6981,6984,7068,7064,0,6984,6988,7072,7068,0,6988,6992,7076,7072,0,6992,6996,7080,7076,0,6996,7002,7086,7080,0,7002,7006,7090,7086,0,7006,7009,7093,7090,0,7009,7012,7096,7093,0,7012,7016,7101,7096,0,7016,7021,7105,7101,0,7021,7024,7109,7105,0,7024,7028,7113,7109,0,7028,7031,7115,7113,0,7031,7034,7119,7115,0,7034,7035,7122,7119,0,7035,7038,7121,7122,0,7038,7041,7120,7121,0,7041,7039,7118,7120,0,7039,7036,7114,7118,0,7036,7033,7112,7114,0,7033,7029,7108,7112,0,7029,7025,7104,7108,0,7025,7020,7100,7104,0,7020,7018,7098,7100,0,7018,7015,7095,7098,0,7015,7011,7091,7095,0,7011,7007,7087,7091,0,7007,7003,7083,7087,0,7003,6999,7079,7083,0,6999,6995,7075,7079,0,6995,6990,7071,7075,0,6990,6987,7067,7071,0,6987,6983,7063,7067,0,6983,6979,7060,7063,0,6979,6976,7057,7060,0,6976,6974,7054,7057,0,7054,7053,7135,7136,0,7053,7059,7141,7135,0,7059,7065,7145,7141,0,7065,7069,7150,7145,0,7069,7073,7157,7150,0,7073,7077,7163,7157,0,7077,7081,7167,7163,0,7081,7084,7170,7167,0,7084,7088,7174,7170,0,7088,7092,7180,7174,0,7092,7097,7188,7180,0,7097,7102,7195,7188,0,7102,7106,7203,7195,0,7106,7110,7208,7203,0,7110,7116,7215,7208,0,7116,7123,7222,7215,0,7123,7125,7230,7222,0,7125,7127,7233,7230,0,7127,7129,7237,7233,0,7129,7131,7239,7237,0,7131,7133,7241,7239,0,7133,7134,7245,7241,0,7134,7132,7244,7245,0,7132,7130,7243,7244,0,7130,7128,7240,7243,0,7128,7126,7236,7240,0,7126,7124,7232,7236,0,7124,7117,7227,7232,0,7117,7111,7217,7227,0,7111,7107,7209,7217,0,7107,7103,7204,7209,0,7103,7099,7197,7204,0,7099,7094,7191,7197,0,7094,7089,7182,7191,0,7089,7085,7176,7182,0,7085,7082,7172,7176,0,7082,7078,7168,7172,0,7078,7074,7164,7168,0,7074,7070,7156,7164,0,7070,7066,7149,7156,0,7066,7062,7146,7149,0,7062,7056,7139,7146,0,7056,7055,7138,7139,0,7055,7058,7140,7138,0,7058,7061,7144,7140,0,7061,7064,7148,7144,0,7064,7068,7154,7148,0,7068,7072,7161,7154,0,7072,7076,7166,7161,0,7076,7080,7171,7166,0,7080,7086,7175,7171,0,7086,7090,7184,7175,0,7090,7093,7190,7184,0,7093,7096,7194,7190,0,7096,7101,7202,7194,0,7101,7105,7207,7202,0,7105,7109,7214,7207,0,7109,7113,7218,7214,0,7113,7115,7223,7218,0,7115,7119,7226,7223,0,7119,7122,7228,7226,0,7122,7121,7225,7228,0,7121,7120,7221,7225,0,7120,7118,7219,7221,0,7118,7114,7216,7219,0,7114,7112,7212,7216,0,7112,7108,7205,7212,0,7108,7104,7200,7205,0,7104,7100,7193,7200,0,7100,7098,7189,7193,0,7098,7095,7183,7189,0,7095,7091,7179,7183,0,7091,7087,7173,7179,0,7087,7083,7169,7173,0,7083,7079,7165,7169,0,7079,7075,7158,7165,0,7075,7071,7151,7158,0,7071,7067,7147,7151,0,7067,7063,7143,7147,0,7063,7060,7142,7143,0,7060,7057,7137,7142,0,7057,7054,7136,7137,0,7136,7135,7152,7153,0,7135,7141,7177,7152,0,7141,7145,7185,7177,0,7145,7150,7198,7185,0,7150,7157,7210,7198,0,7157,7163,7224,7210,0,7163,7167,7235,7224,0,7167,7170,7246,7235,0,7170,7174,7250,7246,0,7174,7180,7254,7250,0,7180,7188,7258,7254,0,7188,7195,7263,7258,0,7195,7203,7267,7263,0,7203,7208,7272,7267,0,7208,7215,7276,7272,0,7215,7222,7282,7276,0,7222,7230,7288,7282,0,7230,7233,7290,7288,0,7233,7237,7291,7290,0,7237,7239,7293,7291,0,7239,7241,7295,7293,0,7241,7245,7298,7295,0,7245,7244,7297,7298,0,7244,7243,7296,7297,0,7243,7240,7294,7296,0,7240,7236,7292,7294,0,7236,7232,7289,7292,0,7232,7227,7286,7289,0,7227,7217,7278,7286,0,7217,7209,7273,7278,0,7209,7204,7269,7273,0,7204,7197,7265,7269,0,7197,7191,7261,7265,0,7191,7182,7255,7261,0,7182,7176,7252,7255,0,7176,7172,7248,7252,0,7172,7168,7238,7248,0,7168,7164,7229,7238,0,7164,7156,7211,7229,0,7156,7149,7199,7211,0,7149,7146,7187,7199,0,7146,7139,7160,7187,0,7139,7138,7159,7160,0,7138,7140,7162,7159,0,7140,7144,7186,7162,0,7144,7148,7196,7186,0,7148,7154,7206,7196,0,7154,7161,7220,7206,0,7161,7166,7234,7220,0,7166,7171,7247,7234,0,7171,7175,7251,7247,0,7175,7184,7257,7251,0,7184,7190,7260,7257,0,7190,7194,7264,7260,0,7194,7202,7268,7264,0,7202,7207,7271,7268,0,7207,7214,7275,7271,0,7214,7218,7279,7275,0,7218,7223,7283,7279,0,7223,7226,7285,7283,0,7226,7228,7287,7285,0,7228,7225,7284,7287,0,7225,7221,7281,7284,0,7221,7219,7280,7281,0,7219,7216,7277,7280,0,7216,7212,7274,7277,0,7212,7205,7270,7274,0,7205,7200,7266,7270,0,7200,7193,7262,7266,0,7193,7189,7259,7262,0,7189,7183,7256,7259,0,7183,7179,7253,7256,0,7179,7173,7249,7253,0,7173,7169,7242,7249,0,7169,7165,7231,7242,0,7165,7158,7213,7231,0,7158,7151,7201,7213,0,7151,7147,7192,7201,0,7147,7143,7181,7192,0,7143,7142,7178,7181,0,7142,7137,7155,7178,0,7137,7136,7153,7155,0,7153,7152,7299,7300,0,7152,7177,7305,7299,0,7177,7185,7308,7305,0,7185,7198,7311,7308,0,7198,7210,7316,7311,0,7210,7224,7319,7316,0,7224,7235,7323,7319,0,7235,7246,7326,7323,0,7246,7250,7330,7326,0,7250,7254,7334,7330,0,7254,7258,7338,7334,0,7258,7263,7343,7338,0,7263,7267,7347,7343,0,7267,7272,7351,7347,0,7272,7276,7355,7351,0,7276,7282,7360,7355,0,7282,7288,7365,7360,0,7288,7290,7370,7365,0,7290,7291,7372,7370,0,7291,7293,7374,7372,0,7293,7295,7375,7374,0,7295,7298,7380,7375,0,7298,7297,7379,7380,0,7297,7296,7378,7379,0,7296,7294,7377,7378,0,7294,7292,7376,7377,0,7292,7289,7373,7376,0,7289,7286,7371,7373,0,7286,7278,7366,7371,0,7278,7273,7358,7366,0,7273,7269,7354,7358,0,7269,7265,7349,7354,0,7265,7261,7345,7349,0,7261,7255,7341,7345,0,7255,7252,7337,7341,0,7252,7248,7332,7337,0,7248,7238,7328,7332,0,7238,7229,7324,7328,0,7229,7211,7320,7324,0,7211,7199,7315,7320,0,7199,7187,7312,7315,0,7187,7160,7303,7312,0,7160,7159,7302,7303,0,7159,7162,7304,7302,0,7162,7186,7310,7304,0,7186,7196,7314,7310,0,7196,7206,7318,7314,0,7206,7220,7322,7318,0,7220,7234,7327,7322,0,7234,7247,7331,7327,0,7247,7251,7335,7331,0,7251,7257,7340,7335,0,7257,7260,7344,7340,0,7260,7264,7348,7344,0,7264,7268,7352,7348,0,7268,7271,7356,7352,0,7271,7275,7361,7356,0,7275,7279,7363,7361,0,7279,7283,7367,7363,0,7283,7285,7368,7367,0,7285,7287,7369,7368,0,7287,7284,7364,7369,0,7284,7281,7362,7364,0,7281,7280,7359,7362,0,7280,7277,7357,7359,0,7277,7274,7353,7357,0,7274,7270,7350,7353,0,7270,7266,7346,7350,0,7266,7262,7342,7346,0,7262,7259,7339,7342,0,7259,7256,7336,7339,0,7256,7253,7333,7336,0,7253,7249,7329,7333,0,7249,7242,7325,7329,0,7242,7231,7321,7325,0,7231,7213,7317,7321,0,7213,7201,7313,7317,0,7201,7192,7309,7313,0,7192,7181,7307,7309,0,7181,7178,7306,7307,0,7178,7155,7301,7306,0,7155,7153,7300,7301,0,7300,7299,7381,7382,0,7299,7305,7387,7381,0,7305,7308,7390,7387,0,7308,7311,7392,7390,0,7311,7316,7396,7392,0,7316,7319,7399,7396,0,7319,7323,7403,7399,0,7323,7326,7406,7403,0,7326,7330,7410,7406,0,7330,7334,7414,7410,0,7334,7338,7418,7414,0,7338,7343,7422,7418,0,7343,7347,7426,7422,0,7347,7351,7430,7426,0,7351,7355,7435,7430,0,7355,7360,7438,7435,0,7360,7365,7443,7438,0,7365,7370,7447,7443,0,7370,7372,7453,7447,0,7372,7374,7454,7453,0,7374,7375,7456,7454,0,7375,7380,7461,7456,0,7380,7379,7462,7461,0,7379,7378,7460,7462,0,7378,7377,7459,7460,0,7377,7376,7458,7459,0,7376,7373,7457,7458,0,7373,7371,7455,7457,0,7371,7366,7450,7455,0,7366,7358,7445,7450,0,7358,7354,7439,7445,0,7354,7349,7434,7439,0,7349,7345,7429,7434,0,7345,7341,7425,7429,0,7341,7337,7421,7425,0,7337,7332,7417,7421,0,7332,7328,7413,7417,0,7328,7324,7408,7413,0,7324,7320,7404,7408,0,7320,7315,7400,7404,0,7315,7312,7395,7400,0,7312,7303,7385,7395,0,7303,7302,7384,7385,0,7302,7304,7386,7384,0,7304,7310,7394,7386,0,7310,7314,7398,7394,0,7314,7318,7402,7398,0,7318,7322,7407,7402,0,7322,7327,7411,7407,0,7327,7331,7415,7411,0,7331,7335,7420,7415,0,7335,7340,7424,7420,0,7340,7344,7428,7424,0,7344,7348,7432,7428,0,7348,7352,7436,7432,0,7352,7356,7441,7436,0,7356,7361,7444,7441,0,7361,7363,7448,7444,0,7363,7367,7449,7448,0,7367,7368,7452,7449,0,7368,7369,7451,7452,0,7369,7364,7446,7451,0,7364,7362,7442,7446,0,7362,7359,7440,7442,0,7359,7357,7437,7440,0,7357,7353,7433,7437,0,7353,7350,7431,7433,0,7350,7346,7427,7431,0,7346,7342,7423,7427,0,7342,7339,7419,7423,0,7339,7336,7416,7419,0,7336,7333,7412,7416,0,7333,7329,7409,7412,0,7329,7325,7405,7409,0,7325,7321,7401,7405,0,7321,7317,7397,7401,0,7317,7313,7393,7397,0,7313,7309,7391,7393,0,7309,7307,7389,7391,0,7307,7306,7388,7389,0,7306,7301,7383,7388,0,7301,7300,7382,7383,0,7382,7381,7463,7464,0,7381,7387,7469,7463,0,7387,7390,7472,7469,0,7390,7392,7474,7472,0,7392,7396,7476,7474,0,7396,7399,7480,7476,0,7399,7403,7484,7480,0,7403,7406,7488,7484,0,7406,7410,7491,7488,0,7410,7414,7495,7491,0,7414,7418,7499,7495,0,7418,7422,7503,7499,0,7422,7426,7506,7503,0,7426,7430,7511,7506,0,7430,7435,7516,7511,0,7435,7438,7520,7516,0,7438,7443,7525,7520,0,7443,7447,7529,7525,0,7447,7453,7531,7529,0,7453,7454,7536,7531,0,7454,7456,7538,7536,0,7456,7461,7543,7538,0,7461,7462,7544,7543,0,7462,7460,7542,7544,0,7460,7459,7541,7542,0,7459,7458,7540,7541,0,7458,7457,7539,7540,0,7457,7455,7537,7539,0,7455,7450,7535,7537,0,7450,7445,7528,7535,0,7445,7439,7522,7528,0,7439,7434,7517,7522,0,7434,7429,7513,7517,0,7429,7425,7509,7513,0,7425,7421,7504,7509,0,7421,7417,7500,7504,0,7417,7413,7496,7500,0,7413,7408,7492,7496,0,7408,7404,7487,7492,0,7404,7400,7483,7487,0,7400,7395,7478,7483,0,7395,7385,7467,7478,0,7385,7384,7466,7467,0,7384,7386,7468,7466,0,7386,7394,7477,7468,0,7394,7398,7481,7477,0,7398,7402,7485,7481,0,7402,7407,7489,7485,0,7407,7411,7493,7489,0,7411,7415,7498,7493,0,7415,7420,7502,7498,0,7420,7424,7507,7502,0,7424,7428,7510,7507,0,7428,7432,7514,7510,0,7432,7436,7519,7514,0,7436,7441,7524,7519,0,7441,7444,7526,7524,0,7444,7448,7530,7526,0,7448,7449,7532,7530,0,7449,7452,7534,7532,0,7452,7451,7533,7534,0,7451,7446,7527,7533,0,7446,7442,7523,7527,0,7442,7440,7521,7523,0,7440,7437,7518,7521,0,7437,7433,7515,7518,0,7433,7431,7512,7515,0,7431,7427,7508,7512,0,7427,7423,7505,7508,0,7423,7419,7501,7505,0,7419,7416,7497,7501,0,7416,7412,7494,7497,0,7412,7409,7490,7494,0,7409,7405,7486,7490,0,7405,7401,7482,7486,0,7401,7397,7479,7482,0,7397,7393,7475,7479,0,7393,7391,7473,7475,0,7391,7389,7471,7473,0,7389,7388,7470,7471,0,7388,7383,7465,7470,0,7383,7382,7464,7465,0,7464,7463,7545,7546,0,7463,7469,7549,7545,0,7469,7472,7554,7549,0,7472,7474,7556,7554,0,7474,7476,7558,7556,0,7476,7480,7561,7558,0,7480,7484,7565,7561,0,7484,7488,7568,7565,0,7488,7491,7572,7568,0,7491,7495,7576,7572,0,7495,7499,7580,7576,0,7499,7503,7584,7580,0,7503,7506,7588,7584,0,7506,7511,7591,7588,0,7511,7516,7595,7591,0,7516,7520,7600,7595,0,7520,7525,7605,7600,0,7525,7529,7608,7605,0,7529,7531,7611,7608,0,7531,7536,7616,7611,0,7536,7538,7619,7616,0,7538,7543,7624,7619,0,7543,7544,7626,7624,0,7544,7542,7625,7626,0,7542,7541,7623,7625,0,7541,7540,7622,7623,0,7540,7539,7621,7622,0,7539,7537,7620,7621,0,7537,7535,7618,7620,0,7535,7528,7612,7618,0,7528,7522,7606,7612,0,7522,7517,7601,7606,0,7517,7513,7597,7601,0,7513,7509,7592,7597,0,7509,7504,7587,7592,0,7504,7500,7583,7587,0,7500,7496,7579,7583,0,7496,7492,7575,7579,0,7492,7487,7570,7575,0,7487,7483,7566,7570,0,7483,7478,7562,7566,0,7478,7467,7550,7562,0,7467,7466,7548,7550,0,7466,7468,7551,7548,0,7468,7477,7560,7551,0,7477,7481,7564,7560,0,7481,7485,7569,7564,0,7485,7489,7573,7569,0,7489,7493,7577,7573,0,7493,7498,7582,7577,0,7498,7502,7586,7582,0,7502,7507,7590,7586,0,7507,7510,7594,7590,0,7510,7514,7598,7594,0,7514,7519,7603,7598,0,7519,7524,7607,7603,0,7524,7526,7610,7607,0,7526,7530,7613,7610,0,7530,7532,7615,7613,0,7532,7534,7617,7615,0,7534,7533,7614,7617,0,7533,7527,7609,7614,0,7527,7523,7604,7609,0,7523,7521,7602,7604,0,7521,7518,7599,7602,0,7518,7515,7596,7599,0,7515,7512,7593,7596,0,7512,7508,7589,7593,0,7508,7505,7585,7589,0,7505,7501,7581,7585,0,7501,7497,7578,7581,0,7497,7494,7574,7578,0,7494,7490,7571,7574,0,7490,7486,7567,7571,0,7486,7482,7563,7567,0,7482,7479,7559,7563,0,7479,7475,7557,7559,0,7475,7473,7555,7557,0,7473,7471,7553,7555,0,7471,7470,7552,7553,0,7470,7465,7547,7552,0,7465,7464,7546,7547,0,7546,7545,7627,7628,0,7545,7549,7630,7627,0,7549,7554,7634,7630,0,7554,7556,7638,7634,0,7556,7558,7640,7638,0,7558,7561,7642,7640,0,7561,7565,7645,7642,0,7565,7568,7649,7645,0,7568,7572,7652,7649,0,7572,7576,7656,7652,0,7576,7580,7660,7656,0,7580,7584,7664,7660,0,7584,7588,7667,7664,0,7588,7591,7671,7667,0,7591,7595,7675,7671,0,7595,7600,7680,7675,0,7600,7605,7684,7680,0,7605,7608,7688,7684,0,7608,7611,7690,7688,0,7611,7616,7694,7690,0,7616,7619,7698,7694,0,7619,7624,7706,7698,0,7624,7626,7708,7706,0,7626,7625,7707,7708,0,7625,7623,7705,7707,0,7623,7622,7704,7705,0,7622,7621,7703,7704,0,7621,7620,7702,7703,0,7620,7618,7701,7702,0,7618,7612,7696,7701,0,7612,7606,7692,7696,0,7606,7601,7686,7692,0,7601,7597,7681,7686,0,7597,7592,7677,7681,0,7592,7587,7672,7677,0,7587,7583,7668,7672,0,7583,7579,7663,7668,0,7579,7575,7659,7663,0,7575,7570,7654,7659,0,7570,7566,7650,7654,0,7566,7562,7646,7650,0,7562,7550,7635,7646,0,7550,7548,7633,7635,0,7548,7551,7636,7633,0,7551,7560,7644,7636,0,7560,7564,7648,7644,0,7564,7569,7653,7648,0,7569,7573,7657,7653,0,7573,7577,7661,7657,0,7577,7582,7666,7661,0,7582,7586,7670,7666,0,7586,7590,7674,7670,0,7590,7594,7678,7674,0,7594,7598,7683,7678,0,7598,7603,7687,7683,0,7603,7607,7691,7687,0,7607,7610,7693,7691,0,7610,7613,7695,7693,0,7613,7615,7699,7695,0,7615,7617,7700,7699,0,7617,7614,7697,7700,0,7614,7609,7689,7697,0,7609,7604,7685,7689,0,7604,7602,7682,7685,0,7602,7599,7679,7682,0,7599,7596,7676,7679,0,7596,7593,7673,7676,0,7593,7589,7669,7673,0,7589,7585,7665,7669,0,7585,7581,7662,7665,0,7581,7578,7658,7662,0,7578,7574,7655,7658,0,7574,7571,7651,7655,0,7571,7567,7647,7651,0,7567,7563,7643,7647,0,7563,7559,7641,7643,0,7559,7557,7639,7641,0,7557,7555,7637,7639,0,7555,7553,7632,7637,0,7553,7552,7631,7632,0,7552,7547,7629,7631,0,7547,7546,7628,7629,0,7628,7627,7709,7710,0,7627,7630,7712,7709,0,7630,7634,7715,7712,0,7634,7638,7720,7715,0,7638,7640,7722,7720,0,7640,7642,7724,7722,0,7642,7645,7726,7724,0,7645,7649,7729,7726,0,7649,7652,7733,7729,0,7652,7656,7737,7733,0,7656,7660,7740,7737,0,7660,7664,7744,7740,0,7664,7667,7748,7744,0,7667,7671,7752,7748,0,7671,7675,7755,7752,0,7675,7680,7759,7755,0,7680,7684,7764,7759,0,7684,7688,7768,7764,0,7688,7690,7769,7768,0,7690,7694,7773,7769,0,7694,7698,7776,7773,0,7698,7706,7787,7776,0,7706,7708,7789,7787,0,7708,7707,7790,7789,0,7707,7705,7788,7790,0,7705,7704,7786,7788,0,7704,7703,7785,7786,0,7703,7702,7784,7785,0,7702,7701,7783,7784,0,7701,7696,7782,7783,0,7696,7692,7775,7782,0,7692,7686,7771,7775,0,7686,7681,7766,7771,0,7681,7677,7761,7766,0,7677,7672,7756,7761,0,7672,7668,7751,7756,0,7668,7663,7747,7751,0,7663,7659,7743,7747,0,7659,7654,7738,7743,0,7654,7650,7734,7738,0,7650,7646,7730,7734,0,7646,7635,7718,7730,0,7635,7633,7716,7718,0,7633,7636,7719,7716,0,7636,7644,7727,7719,0,7644,7648,7731,7727,0,7648,7653,7736,7731,0,7653,7657,7741,7736,0,7657,7661,7745,7741,0,7661,7666,7749,7745,0,7666,7670,7754,7749,0,7670,7674,7758,7754,0,7674,7678,7762,7758,0,7678,7683,7767,7762,0,7683,7687,7770,7767,0,7687,7691,7774,7770,0,7691,7693,7777,7774,0,7693,7695,7779,7777,0,7695,7699,7781,7779,0,7699,7700,7780,7781,0,7700,7697,7778,7780,0,7697,7689,7772,7778,0,7689,7685,7765,7772,0,7685,7682,7763,7765,0,7682,7679,7760,7763,0,7679,7676,7757,7760,0,7676,7673,7753,7757,0,7673,7669,7750,7753,0,7669,7665,7746,7750,0,7665,7662,7742,7746,0,7662,7658,7739,7742,0,7658,7655,7735,7739,0,7655,7651,7732,7735,0,7651,7647,7728,7732,0,7647,7643,7725,7728,0,7643,7641,7723,7725,0,7641,7639,7721,7723,0,7639,7637,7717,7721,0,7637,7632,7714,7717,0,7632,7631,7713,7714,0,7631,7629,7711,7713,0,7629,7628,7710,7711,0,7710,7709,7791,7792,0,7709,7712,7794,7791,0,7712,7715,7797,7794,0,7715,7720,7802,7797,0,7720,7722,7804,7802,0,7722,7724,7806,7804,0,7724,7726,7808,7806,0,7726,7729,7810,7808,0,7729,7733,7814,7810,0,7733,7737,7818,7814,0,7737,7740,7822,7818,0,7740,7744,7825,7822,0,7744,7748,7829,7825,0,7748,7752,7833,7829,0,7752,7755,7837,7833,0,7755,7759,7840,7837,0,7759,7764,7845,7840,0,7764,7768,7848,7845,0,7768,7769,7851,7848,0,7769,7773,7855,7851,0,7773,7776,7857,7855,0,7776,7787,7869,7857,0,7787,7789,7871,7869,0,7789,7790,7872,7871,0,7790,7788,7870,7872,0,7788,7786,7868,7870,0,7786,7785,7867,7868,0,7785,7784,7866,7867,0,7784,7783,7865,7866,0,7783,7782,7864,7865,0,7782,7775,7858,7864,0,7775,7771,7854,7858,0,7771,7766,7849,7854,0,7766,7761,7843,7849,0,7761,7756,7839,7843,0,7756,7751,7834,7839,0,7751,7747,7830,7834,0,7747,7743,7826,7830,0,7743,7738,7821,7826,0,7738,7734,7816,7821,0,7734,7730,7812,7816,0,7730,7718,7800,7812,0,7718,7716,7799,7800,0,7716,7719,7801,7799,0,7719,7727,7811,7801,0,7727,7731,7815,7811,0,7731,7736,7819,7815,0,7736,7741,7823,7819,0,7741,7745,7828,7823,0,7745,7749,7832,7828,0,7749,7754,7836,7832,0,7754,7758,7842,7836,0,7758,7762,7846,7842,0,7762,7767,7850,7846,0,7767,7770,7853,7850,0,7770,7774,7856,7853,0,7774,7777,7859,7856,0,7777,7779,7861,7859,0,7779,7781,7863,7861,0,7781,7780,7862,7863,0,7780,7778,7860,7862,0,7778,7772,7852,7860,0,7772,7765,7847,7852,0,7765,7763,7844,7847,0,7763,7760,7841,7844,0,7760,7757,7838,7841,0,7757,7753,7835,7838,0,7753,7750,7831,7835,0,7750,7746,7827,7831,0,7746,7742,7824,7827,0,7742,7739,7820,7824,0,7739,7735,7817,7820,0,7735,7732,7813,7817,0,7732,7728,7809,7813,0,7728,7725,7807,7809,0,7725,7723,7805,7807,0,7723,7721,7803,7805,0,7721,7717,7798,7803,0,7717,7714,7796,7798,0,7714,7713,7795,7796,0,7713,7711,7793,7795,0,7711,7710,7792,7793,0,7792,7791,7873,7874,0,7791,7794,7876,7873,0,7794,7797,7879,7876,0,7797,7802,7881,7879,0,7802,7804,7886,7881,0,7804,7806,7888,7886,0,7806,7808,7890,7888,0,7808,7810,7892,7890,0,7810,7814,7893,7892,0,7814,7818,7898,7893,0,7818,7822,7902,7898,0,7822,7825,7906,7902,0,7825,7829,7909,7906,0,7829,7833,7913,7909,0,7833,7837,7917,7913,0,7837,7840,7920,7917,0,7840,7845,7924,7920,0,7845,7848,7928,7924,0,7848,7851,7931,7928,0,7851,7855,7935,7931,0,7855,7857,7938,7935,0,7857,7869,7950,7938,0,7869,7871,7952,7950,0,7871,7872,7954,7952,0,7872,7870,7953,7954,0,7870,7868,7951,7953,0,7868,7867,7949,7951,0,7867,7866,7948,7949,0,7866,7865,7947,7948,0,7865,7864,7946,7947,0,7864,7858,7940,7946,0,7858,7854,7937,7940,0,7854,7849,7933,7937,0,7849,7843,7929,7933,0,7843,7839,7923,7929,0,7839,7834,7919,7923,0,7834,7830,7914,7919,0,7830,7826,7910,7914,0,7826,7821,7905,7910,0,7821,7816,7900,7905,0,7816,7812,7896,7900,0,7812,7800,7885,7896,0,7800,7799,7883,7885,0,7799,7801,7884,7883,0,7801,7811,7895,7884,0,7811,7815,7899,7895,0,7815,7819,7903,7899,0,7819,7823,7907,7903,0,7823,7828,7912,7907,0,7828,7832,7916,7912,0,7832,7836,7921,7916,0,7836,7842,7926,7921,0,7842,7846,7930,7926,0,7846,7850,7932,7930,0,7850,7853,7936,7932,0,7853,7856,7939,7936,0,7856,7859,7941,7939,0,7859,7861,7944,7941,0,7861,7863,7945,7944,0,7863,7862,7943,7945,0,7862,7860,7942,7943,0,7860,7852,7934,7942,0,7852,7847,7927,7934,0,7847,7844,7925,7927,0,7844,7841,7922,7925,0,7841,7838,7918,7922,0,7838,7835,7915,7918,0,7835,7831,7911,7915,0,7831,7827,7908,7911,0,7827,7824,7904,7908,0,7824,7820,7901,7904,0,7820,7817,7897,7901,0,7817,7813,7894,7897,0,7813,7809,7891,7894,0,7809,7807,7889,7891,0,7807,7805,7887,7889,0,7805,7803,7882,7887,0,7803,7798,7880,7882,0,7798,7796,7878,7880,0,7796,7795,7877,7878,0,7795,7793,7875,7877,0,7793,7792,7874,7875,0,7874,7873,7955,7956,0,7873,7876,7960,7955,0,7876,7879,7964,7960,0,7879,7881,7966,7964,0,7881,7886,7968,7966,0,7886,7888,7975,7968,0,7888,7890,7979,7975,0,7890,7892,7983,7979,0,7892,7893,7985,7983,0,7893,7898,7991,7985,0,7898,7902,7999,7991,0,7902,7906,8004,7999,0,7906,7909,8009,8004,0,7909,7913,8015,8009,0,7913,7917,8022,8015,0,7917,7920,8028,8022,0,7920,7924,8034,8028,0,7924,7928,8040,8034,0,7928,7931,8045,8040,0,7931,7935,8052,8045,0,7935,7938,8056,8052,0,7938,7950,8083,8056,0,7950,7952,8087,8083,0,7952,7954,8089,8087,0,7954,7953,8090,8089,0,7953,7951,8088,8090,0,7951,7949,8084,8088,0,7949,7948,8082,8084,0,7948,7947,8079,8082,0,7947,7946,8075,8079,0,7946,7940,8071,8075,0,7940,7937,8062,8071,0,7937,7933,8057,8062,0,7933,7929,8048,8057,0,7929,7923,8043,8048,0,7923,7919,8033,8043,0,7919,7914,8026,8033,0,7914,7910,8018,8026,0,7910,7905,8010,8018,0,7905,7900,8003,8010,0,7900,7896,7996,8003,0,7896,7885,7974,7996,0,7885,7883,7970,7974,0,7883,7884,7973,7970,0,7884,7895,7995,7973,0,7895,7899,8001,7995,0,7899,7903,8007,8001,0,7903,7907,8013,8007,0,7907,7912,8020,8013,0,7912,7916,8029,8020,0,7916,7921,8038,8029,0,7921,7926,8044,8038,0,7926,7930,8049,8044,0,7930,7932,8055,8049,0,7932,7936,8060,8055,0,7936,7939,8064,8060,0,7939,7941,8066,8064,0,7941,7944,8069,8066,0,7944,7945,8070,8069,0,7945,7943,8067,8070,0,7943,7942,8065,8067,0,7942,7934,8053,8065,0,7934,7927,8039,8053,0,7927,7925,8036,8039,0,7925,7922,8031,8036,0,7922,7918,8024,8031,0,7918,7915,8017,8024,0,7915,7911,8014,8017,0,7911,7908,8008,8014,0,7908,7904,8002,8008,0,7904,7901,7997,8002,0,7901,7897,7990,7997,0,7897,7894,7987,7990,0,7894,7891,7982,7987,0,7891,7889,7978,7982,0,7889,7887,7971,7978,0,7887,7882,7967,7971,0,7882,7880,7965,7967,0,7880,7878,7963,7965,0,7878,7877,7962,7963,0,7877,7875,7957,7962,0,7875,7874,7956,7957,0,7956,7955,7958,7959,0,7955,7960,7969,7958,0,7960,7964,7977,7969,0,7964,7966,7981,7977,0,7966,7968,7986,7981,0,7968,7975,7993,7986,0,7975,7979,8000,7993,0,7979,7983,8006,8000,0,7983,7985,8011,8006,0,7985,7991,8019,8011,0,7991,7999,8027,8019,0,7999,8004,8037,8027,0,8004,8009,8046,8037,0,8009,8015,8054,8046,0,8015,8022,8063,8054,0,8022,8028,8073,8063,0,8028,8034,8077,8073,0,8034,8040,8086,8077,0,8040,8045,8093,8086,0,8045,8052,8096,8093,0,8052,8056,8099,8096,0,8056,8083,8113,8099,0,8083,8087,8115,8113,0,8087,8089,8117,8115,0,8089,8090,8118,8117,0,8090,8088,8116,8118,0,8088,8084,8114,8116,0,8084,8082,8112,8114,0,8082,8079,8111,8112,0,8079,8075,8110,8111,0,8075,8071,8109,8110,0,8071,8062,8102,8109,0,8062,8057,8100,8102,0,8057,8048,8094,8100,0,8048,8043,8091,8094,0,8043,8033,8078,8091,0,8033,8026,8072,8078,0,8026,8018,8059,8072,0,8018,8010,8047,8059,0,8010,8003,8035,8047,0,8003,7996,8023,8035,0,7996,7974,7994,8023,0,7974,7970,7989,7994,0,7970,7973,7992,7989,0,7973,7995,8021,7992,0,7995,8001,8030,8021,0,8001,8007,8041,8030,0,8007,8013,8051,8041,0,8013,8020,8061,8051,0,8020,8029,8074,8061,0,8029,8038,8081,8074,0,8038,8044,8092,8081,0,8044,8049,8095,8092,0,8049,8055,8098,8095,0,8055,8060,8101,8098,0,8060,8064,8103,8101,0,8064,8066,8105,8103,0,8066,8069,8107,8105,0,8069,8070,8108,8107,0,8070,8067,8106,8108,0,8067,8065,8104,8106,0,8065,8053,8097,8104,0,8053,8039,8085,8097,0,8039,8036,8080,8085,0,8036,8031,8076,8080,0,8031,8024,8068,8076,0,8024,8017,8058,8068,0,8017,8014,8050,8058,0,8014,8008,8042,8050,0,8008,8002,8032,8042,0,8002,7997,8025,8032,0,7997,7990,8016,8025,0,7990,7987,8012,8016,0,7987,7982,8005,8012,0,7982,7978,7998,8005,0,7978,7971,7988,7998,0,7971,7967,7984,7988,0,7967,7965,7980,7984,0,7965,7963,7976,7980,0,7963,7962,7972,7976,0,7962,7957,7961,7972,0,7957,7956,7959,7961,0,7959,7958,8119,8120,0,7958,7969,8122,8119,0,7969,7977,8125,8122,0,7977,7981,8127,8125,0,7981,7986,8129,8127,0,7986,7993,8131,8129,0,7993,8000,8136,8131,0,8000,8006,8138,8136,0,8006,8011,8139,8138,0,8011,8019,8141,8139,0,8019,8027,8144,8141,0,8027,8037,8148,8144,0,8037,8046,8152,8148,0,8046,8054,8155,8152,0,8054,8063,8159,8155,0,8063,8073,8163,8159,0,8073,8077,8166,8163,0,8077,8086,8169,8166,0,8086,8093,8173,8169,0,8093,8096,8176,8173,0,8096,8099,8180,8176,0,8099,8113,8194,8180,0,8113,8115,8196,8194,0,8115,8117,8199,8196,0,8117,8118,8200,8199,0,8118,8116,8198,8200,0,8116,8114,8197,8198,0,8114,8112,8195,8197,0,8112,8111,8193,8195,0,8111,8110,8192,8193,0,8110,8109,8191,8192,0,8109,8102,8185,8191,0,8102,8100,8182,8185,0,8100,8094,8178,8182,0,8094,8091,8174,8178,0,8091,8078,8171,8174,0,8078,8072,8165,8171,0,8072,8059,8160,8165,0,8059,8047,8156,8160,0,8047,8035,8151,8156,0,8035,8023,8146,8151,0,8023,7994,8135,8146,0,7994,7989,8132,8135,0,7989,7992,8134,8132,0,7992,8021,8145,8134,0,8021,8030,8149,8145,0,8030,8041,8153,8149,0,8041,8051,8157,8153,0,8051,8061,8162,8157,0,8061,8074,8167,8162,0,8074,8081,8172,8167,0,8081,8092,8175,8172,0,8092,8095,8179,8175,0,8095,8098,8181,8179,0,8098,8101,8183,8181,0,8101,8103,8186,8183,0,8103,8105,8188,8186,0,8105,8107,8190,8188,0,8107,8108,8189,8190,0,8108,8106,8187,8189,0,8106,8104,8184,8187,0,8104,8097,8177,8184,0,8097,8085,8170,8177,0,8085,8080,8168,8170,0,8080,8076,8164,8168,0,8076,8068,8161,8164,0,8068,8058,8158,8161,0,8058,8050,8154,8158,0,8050,8042,8150,8154,0,8042,8032,8147,8150,0,8032,8025,8143,8147,0,8025,8016,8142,8143,0,8016,8012,8140,8142,0,8012,8005,8137,8140,0,8005,7998,8133,8137,0,7998,7988,8130,8133,0,7988,7984,8128,8130,0,7984,7980,8126,8128,0,7980,7976,8124,8126,0,7976,7972,8123,8124,0,7972,7961,8121,8123,0,7961,7959,8120,8121,0,8120,8119,8201,8202,0,8119,8122,8204,8201,0,8122,8125,8207,8204,0,8125,8127,8209,8207,0,8127,8129,8211,8209,0,8129,8131,8213,8211,0,8131,8136,8215,8213,0,8136,8138,8218,8215,0,8138,8139,8221,8218,0,8139,8141,8223,8221,0,8141,8144,8226,8223,0,8144,8148,8228,8226,0,8148,8152,8232,8228,0,8152,8155,8235,8232,0,8155,8159,8239,8235,0,8159,8163,8243,8239,0,8163,8166,8245,8243,0,8166,8169,8249,8245,0,8169,8173,8253,8249,0,8173,8176,8256,8253,0,8176,8180,8258,8256,0,8180,8194,8275,8258,0,8194,8196,8278,8275,0,8196,8199,8280,8278,0,8199,8200,8282,8280,0,8200,8198,8281,8282,0,8198,8197,8279,8281,0,8197,8195,8277,8279,0,8195,8193,8276,8277,0,8193,8192,8274,8276,0,8192,8191,8273,8274,0,8191,8185,8269,8273,0,8185,8182,8264,8269,0,8182,8178,8262,8264,0,8178,8174,8259,8262,0,8174,8171,8254,8259,0,8171,8165,8251,8254,0,8165,8160,8246,8251,0,8160,8156,8240,8246,0,8156,8151,8236,8240,0,8151,8146,8231,8236,0,8146,8135,8220,8231,0,8135,8132,8216,8220,0,8132,8134,8217,8216,0,8134,8145,8229,8217,0,8145,8149,8233,8229,0,8149,8153,8237,8233,0,8153,8157,8241,8237,0,8157,8162,8247,8241,0,8162,8167,8252,8247,0,8167,8172,8255,8252,0,8172,8175,8260,8255,0,8175,8179,8261,8260,0,8179,8181,8263,8261,0,8181,8183,8265,8263,0,8183,8186,8267,8265,0,8186,8188,8271,8267,0,8188,8190,8272,8271,0,8190,8189,8270,8272,0,8189,8187,8268,8270,0,8187,8184,8266,8268,0,8184,8177,8257,8266,0,8177,8170,8250,8257,0,8170,8168,8248,8250,0,8168,8164,8244,8248,0,8164,8161,8242,8244,0,8161,8158,8238,8242,0,8158,8154,8234,8238,0,8154,8150,8230,8234,0,8150,8147,8227,8230,0,8147,8143,8225,8227,0,8143,8142,8224,8225,0,8142,8140,8222,8224,0,8140,8137,8219,8222,0,8137,8133,8214,8219,0,8133,8130,8212,8214,0,8130,8128,8210,8212,0,8128,8126,8208,8210,0,8126,8124,8206,8208,0,8124,8123,8205,8206,0,8123,8121,8203,8205,0,8121,8120,8202,8203,0,8202,8201,8283,8284,0,8201,8204,8286,8283,0,8204,8207,8289,8286,0,8207,8209,8291,8289,0,8209,8211,8293,8291,0,8211,8213,8295,8293,0,8213,8215,8297,8295,0,8215,8218,8298,8297,0,8218,8221,8303,8298,0,8221,8223,8305,8303,0,8223,8226,8308,8305,0,8226,8228,8310,8308,0,8228,8232,8313,8310,0,8232,8235,8317,8313,0,8235,8239,8321,8317,0,8239,8243,8324,8321,0,8243,8245,8327,8324,0,8245,8249,8331,8327,0,8249,8253,8334,8331,0,8253,8256,8336,8334,0,8256,8258,8339,8336,0,8258,8275,8357,8339,0,8275,8278,8359,8357,0,8278,8280,8361,8359,0,8280,8282,8363,8361,0,8282,8281,8364,8363,0,8281,8279,8362,8364,0,8279,8277,8360,8362,0,8277,8276,8358,8360,0,8276,8274,8356,8358,0,8274,8273,8355,8356,0,8273,8269,8353,8355,0,8269,8264,8346,8353,0,8264,8262,8344,8346,0,8262,8259,8341,8344,0,8259,8254,8337,8341,0,8254,8251,8333,8337,0,8251,8246,8329,8333,0,8246,8240,8323,8329,0,8240,8236,8318,8323,0,8236,8231,8314,8318,0,8231,8220,8302,8314,0,8220,8216,8299,8302,0,8216,8217,8301,8299,0,8217,8229,8311,8301,0,8229,8233,8315,8311,0,8233,8237,8320,8315,0,8237,8241,8325,8320,0,8241,8247,8328,8325,0,8247,8252,8335,8328,0,8252,8255,8338,8335,0,8255,8260,8342,8338,0,8260,8261,8343,8342,0,8261,8263,8345,8343,0,8263,8265,8348,8345,0,8265,8267,8350,8348,0,8267,8271,8352,8350,0,8271,8272,8354,8352,0,8272,8270,8351,8354,0,8270,8268,8349,8351,0,8268,8266,8347,8349,0,8266,8257,8340,8347,0,8257,8250,8332,8340,0,8250,8248,8330,8332,0,8248,8244,8326,8330,0,8244,8242,8322,8326,0,8242,8238,8319,8322,0,8238,8234,8316,8319,0,8234,8230,8312,8316,0,8230,8227,8309,8312,0,8227,8225,8307,8309,0,8225,8224,8306,8307,0,8224,8222,8304,8306,0,8222,8219,8300,8304,0,8219,8214,8296,8300,0,8214,8212,8294,8296,0,8212,8210,8292,8294,0,8210,8208,8290,8292,0,8208,8206,8288,8290,0,8206,8205,8287,8288,0,8205,8203,8285,8287,0,8203,8202,8284,8285,0,8284,8283,8365,8366,0,8283,8286,8368,8365,0,8286,8289,8371,8368,0,8289,8291,8373,8371,0,8291,8293,8375,8373,0,8293,8295,8377,8375,0,8295,8297,8379,8377,0,8297,8298,8380,8379,0,8298,8303,8384,8380,0,8303,8305,8387,8384,0,8305,8308,8390,8387,0,8308,8310,8392,8390,0,8310,8313,8394,8392,0,8313,8317,8398,8394,0,8317,8321,8401,8398,0,8321,8324,8405,8401,0,8324,8327,8409,8405,0,8327,8331,8411,8409,0,8331,8334,8415,8411,0,8334,8336,8418,8415,0,8336,8339,8421,8418,0,8339,8357,8439,8421,0,8357,8359,8441,8439,0,8359,8361,8443,8441,0,8361,8363,8445,8443,0,8363,8364,8446,8445,0,8364,8362,8444,8446,0,8362,8360,8442,8444,0,8360,8358,8440,8442,0,8358,8356,8438,8440,0,8356,8355,8437,8438,0,8355,8353,8436,8437,0,8353,8346,8429,8436,0,8346,8344,8426,8429,0,8344,8341,8423,8426,0,8341,8337,8419,8423,0,8337,8333,8416,8419,0,8333,8329,8413,8416,0,8329,8323,8406,8413,0,8323,8318,8402,8406,0,8318,8314,8396,8402,0,8314,8302,8385,8396,0,8302,8299,8382,8385,0,8299,8301,8383,8382,0,8301,8311,8395,8383,0,8311,8315,8399,8395,0,8315,8320,8403,8399,0,8320,8325,8407,8403,0,8325,8328,8412,8407,0,8328,8335,8417,8412,0,8335,8338,8420,8417,0,8338,8342,8424,8420,0,8342,8343,8425,8424,0,8343,8345,8427,8425,0,8345,8348,8430,8427,0,8348,8350,8432,8430,0,8350,8352,8434,8432,0,8352,8354,8435,8434,0,8354,8351,8433,8435,0,8351,8349,8431,8433,0,8349,8347,8428,8431,0,8347,8340,8422,8428,0,8340,8332,8414,8422,0,8332,8330,8410,8414,0,8330,8326,8408,8410,0,8326,8322,8404,8408,0,8322,8319,8400,8404,0,8319,8316,8397,8400,0,8316,8312,8393,8397,0,8312,8309,8391,8393,0,8309,8307,8389,8391,0,8307,8306,8388,8389,0,8306,8304,8386,8388,0,8304,8300,8381,8386,0,8300,8296,8378,8381,0,8296,8294,8376,8378,0,8294,8292,8374,8376,0,8292,8290,8372,8374,0,8290,8288,8370,8372,0,8288,8287,8369,8370,0,8287,8285,8367,8369,0,8285,8284,8366,8367,0,8366,8365,8447,8448,0,8365,8368,8450,8447,0,8368,8371,8453,8450,0,8371,8373,8455,8453,0,8373,8375,8457,8455,0,8375,8377,8459,8457,0,8377,8379,8461,8459,0,8379,8380,8462,8461,0,8380,8384,8464,8462,0,8384,8387,8468,8464,0,8387,8390,8471,8468,0,8390,8392,8474,8471,0,8392,8394,8476,8474,0,8394,8398,8478,8476,0,8398,8401,8482,8478,0,8401,8405,8485,8482,0,8405,8409,8489,8485,0,8409,8411,8492,8489,0,8411,8415,8495,8492,0,8415,8418,8498,8495,0,8418,8421,8501,8498,0,8421,8439,8520,8501,0,8439,8441,8522,8520,0,8441,8443,8524,8522,0,8443,8445,8526,8524,0,8445,8446,8528,8526,0,8446,8444,8527,8528,0,8444,8442,8525,8527,0,8442,8440,8523,8525,0,8440,8438,8521,8523,0,8438,8437,8519,8521,0,8437,8436,8518,8519,0,8436,8429,8513,8518,0,8429,8426,8508,8513,0,8426,8423,8506,8508,0,8423,8419,8504,8506,0,8419,8416,8500,8504,0,8416,8413,8497,8500,0,8413,8406,8491,8497,0,8406,8402,8486,8491,0,8402,8396,8481,8486,0,8396,8385,8470,8481,0,8385,8382,8466,8470,0,8382,8383,8467,8466,0,8383,8395,8479,8467,0,8395,8399,8483,8479,0,8399,8403,8487,8483,0,8403,8407,8493,8487,0,8407,8412,8496,8493,0,8412,8417,8499,8496,0,8417,8420,8503,8499,0,8420,8424,8505,8503,0,8424,8425,8507,8505,0,8425,8427,8510,8507,0,8427,8430,8512,8510,0,8430,8432,8515,8512,0,8432,8434,8517,8515,0,8434,8435,8516,8517,0,8435,8433,8514,8516,0,8433,8431,8511,8514,0,8431,8428,8509,8511,0,8428,8422,8502,8509,0,8422,8414,8494,8502,0,8414,8410,8490,8494,0,8410,8408,8488,8490,0,8408,8404,8484,8488,0,8404,8400,8480,8484,0,8400,8397,8477,8480,0,8397,8393,8475,8477,0,8393,8391,8473,8475,0,8391,8389,8472,8473,0,8389,8388,8469,8472,0,8388,8386,8465,8469,0,8386,8381,8463,8465,0,8381,8378,8460,8463,0,8378,8376,8458,8460,0,8376,8374,8456,8458,0,8374,8372,8454,8456,0,8372,8370,8452,8454,0,8370,8369,8451,8452,0,8369,8367,8449,8451,0,8367,8366,8448,8449,0,8448,8447,8529,8530,0,8447,8450,8532,8529,0,8450,8453,8535,8532,0,8453,8455,8537,8535,0,8455,8457,8539,8537,0,8457,8459,8541,8539,0,8459,8461,8545,8541,0,8461,8462,8547,8545,0,8462,8464,8549,8547,0,8464,8468,8551,8549,0,8468,8471,8557,8551,0,8471,8474,8563,8557,0,8474,8476,8566,8563,0,8476,8478,8569,8566,0,8478,8482,8574,8569,0,8482,8485,8578,8574,0,8485,8489,8583,8578,0,8489,8492,8588,8583,0,8492,8495,8594,8588,0,8495,8498,8595,8594,0,8498,8501,8600,8595,0,8501,8520,8631,8600,0,8520,8522,8633,8631,0,8522,8524,8638,8633,0,8524,8526,8640,8638,0,8526,8528,8642,8640,0,8528,8527,8641,8642,0,8527,8525,8639,8641,0,8525,8523,8637,8639,0,8523,8521,8634,8637,0,8521,8519,8632,8634,0,8519,8518,8629,8632,0,8518,8513,8624,8629,0,8513,8508,8617,8624,0,8508,8506,8614,8617,0,8506,8504,8608,8614,0,8504,8500,8603,8608,0,8500,8497,8598,8603,0,8497,8491,8592,8598,0,8491,8486,8585,8592,0,8486,8481,8577,8585,0,8481,8470,8556,8577,0,8470,8466,8553,8556,0,8466,8467,8555,8553,0,8467,8479,8572,8555,0,8479,8483,8580,8572,0,8483,8487,8586,8580,0,8487,8493,8593,8586,0,8493,8496,8597,8593,0,8496,8499,8601,8597,0,8499,8503,8607,8601,0,8503,8505,8613,8607,0,8505,8507,8615,8613,0,8507,8510,8619,8615,0,8510,8512,8622,8619,0,8512,8515,8625,8622,0,8515,8517,8627,8625,0,8517,8516,8626,8627,0,8516,8514,8623,8626,0,8514,8511,8621,8623,0,8511,8509,8616,8621,0,8509,8502,8602,8616,0,8502,8494,8591,8602,0,8494,8490,8587,8591,0,8490,8488,8584,8587,0,8488,8484,8579,8584,0,8484,8480,8573,8579,0,8480,8477,8568,8573,0,8477,8475,8564,8568,0,8475,8473,8562,8564,0,8473,8472,8558,8562,0,8472,8469,8552,8558,0,8469,8465,8550,8552,0,8465,8463,8548,8550,0,8463,8460,8544,8548,0,8460,8458,8540,8544,0,8458,8456,8538,8540,0,8456,8454,8536,8538,0,8454,8452,8534,8536,0,8452,8451,8533,8534,0,8451,8449,8531,8533,0,8449,8448,8530,8531,0,8530,8529,8542,8543,0,8529,8532,8554,8542,0,8532,8535,8561,8554,0,8535,8537,8567,8561,0,8537,8539,8571,8567,0,8539,8541,8576,8571,0,8541,8545,8582,8576,0,8545,8547,8589,8582,0,8547,8549,8596,8589,0,8549,8551,8604,8596,0,8551,8557,8610,8604,0,8557,8563,8620,8610,0,8563,8566,8630,8620,0,8566,8569,8636,8630,0,8569,8574,8643,8636,0,8574,8578,8647,8643,0,8578,8583,8650,8647,0,8583,8588,8655,8650,0,8588,8594,8658,8655,0,8594,8595,8660,8658,0,8595,8600,8663,8660,0,8600,8631,8683,8663,0,8631,8633,8685,8683,0,8633,8638,8688,8685,0,8638,8640,8690,8688,0,8640,8642,8692,8690,0,8642,8641,8691,8692,0,8641,8639,8689,8691,0,8639,8637,8687,8689,0,8637,8634,8686,8687,0,8634,8632,8684,8686,0,8632,8629,8682,8684,0,8629,8624,8679,8682,0,8624,8617,8673,8679,0,8617,8614,8670,8673,0,8614,8608,8668,8670,0,8608,8603,8666,8668,0,8603,8598,8662,8666,0,8598,8592,8657,8662,0,8592,8585,8652,8657,0,8585,8577,8646,8652,0,8577,8556,8611,8646,0,8556,8553,8606,8611,0,8553,8555,8609,8606,0,8555,8572,8645,8609,0,8572,8580,8649,8645,0,8580,8586,8653,8649,0,8586,8593,8659,8653,0,8593,8597,8661,8659,0,8597,8601,8664,8661,0,8601,8607,8667,8664,0,8607,8613,8669,8667,0,8613,8615,8671,8669,0,8615,8619,8674,8671,0,8619,8622,8676,8674,0,8622,8625,8678,8676,0,8625,8627,8681,8678,0,8627,8626,8680,8681,0,8626,8623,8677,8680,0,8623,8621,8675,8677,0,8621,8616,8672,8675,0,8616,8602,8665,8672,0,8602,8591,8656,8665,0,8591,8587,8654,8656,0,8587,8584,8651,8654,0,8584,8579,8648,8651,0,8579,8573,8644,8648,0,8573,8568,8635,8644,0,8568,8564,8628,8635,0,8564,8562,8618,8628,0,8562,8558,8612,8618,0,8558,8552,8605,8612,0,8552,8550,8599,8605,0,8550,8548,8590,8599,0,8548,8544,8581,8590,0,8544,8540,8575,8581,0,8540,8538,8570,8575,0,8538,8536,8565,8570,0,8536,8534,8560,8565,0,8534,8533,8559,8560,0,8533,8531,8546,8559,0,8531,8530,8543,8546,0,8543,8542,8693,8694,0,8542,8554,8696,8693,0,8554,8561,8698,8696,0,8561,8567,8701,8698,0,8567,8571,8703,8701,0,8571,8576,8705,8703,0,8576,8582,8706,8705,0,8582,8589,8708,8706,0,8589,8596,8710,8708,0,8596,8604,8712,8710,0,8604,8610,8714,8712,0,8610,8620,8718,8714,0,8620,8630,8722,8718,0,8630,8636,8724,8722,0,8636,8643,8725,8724,0,8643,8647,8727,8725,0,8647,8650,8730,8727,0,8650,8655,8734,8730,0,8655,8658,8739,8734,0,8658,8660,8740,8739,0,8660,8663,8743,8740,0,8663,8683,8764,8743,0,8683,8685,8767,8764,0,8685,8688,8769,8767,0,8688,8690,8771,8769,0,8690,8692,8773,8771,0,8692,8691,8774,8773,0,8691,8689,8772,8774,0,8689,8687,8770,8772,0,8687,8686,8768,8770,0,8686,8684,8766,8768,0,8684,8682,8765,8766,0,8682,8679,8763,8765,0,8679,8673,8757,8763,0,8673,8670,8753,8757,0,8670,8668,8750,8753,0,8668,8666,8748,8750,0,8666,8662,8745,8748,0,8662,8657,8742,8745,0,8657,8652,8736,8742,0,8652,8646,8732,8736,0,8646,8611,8720,8732,0,8611,8606,8716,8720,0,8606,8609,8717,8716,0,8609,8645,8729,8717,0,8645,8649,8733,8729,0,8649,8653,8737,8733,0,8653,8659,8741,8737,0,8659,8661,8744,8741,0,8661,8664,8747,8744,0,8664,8667,8749,8747,0,8667,8669,8751,8749,0,8669,8671,8754,8751,0,8671,8674,8756,8754,0,8674,8676,8759,8756,0,8676,8678,8761,8759,0,8678,8681,8762,8761,0,8681,8680,8760,8762,0,8680,8677,8758,8760,0,8677,8675,8755,8758,0,8675,8672,8752,8755,0,8672,8665,8746,8752,0,8665,8656,8738,8746,0,8656,8654,8735,8738,0,8654,8651,8731,8735,0,8651,8648,8728,8731,0,8648,8644,8726,8728,0,8644,8635,8723,8726,0,8635,8628,8721,8723,0,8628,8618,8719,8721,0,8618,8612,8715,8719,0,8612,8605,8713,8715,0,8605,8599,8711,8713,0,8599,8590,8709,8711,0,8590,8581,8707,8709,0,8581,8575,8704,8707,0,8575,8570,8702,8704,0,8570,8565,8700,8702,0,8565,8560,8699,8700,0,8560,8559,8697,8699,0,8559,8546,8695,8697,0,8546,8543,8694,8695,0,8694,8693,8775,8776,0,8693,8696,8778,8775,0,8696,8698,8780,8778,0,8698,8701,8783,8780,0,8701,8703,8785,8783,0,8703,8705,8787,8785,0,8705,8706,8788,8787,0,8706,8708,8790,8788,0,8708,8710,8792,8790,0,8710,8712,8794,8792,0,8712,8714,8796,8794,0,8714,8718,8798,8796,0,8718,8722,8804,8798,0,8722,8724,8805,8804,0,8724,8725,8807,8805,0,8725,8727,8809,8807,0,8727,8730,8811,8809,0,8730,8734,8814,8811,0,8734,8739,8818,8814,0,8739,8740,8822,8818,0,8740,8743,8824,8822,0,8743,8764,8846,8824,0,8764,8767,8848,8846,0,8767,8769,8850,8848,0,8769,8771,8852,8850,0,8771,8773,8854,8852,0,8773,8774,8856,8854,0,8774,8772,8855,8856,0,8772,8770,8853,8855,0,8770,8768,8851,8853,0,8768,8766,8849,8851,0,8766,8765,8847,8849,0,8765,8763,8845,8847,0,8763,8757,8840,8845,0,8757,8753,8835,8840,0,8753,8750,8832,8835,0,8750,8748,8830,8832,0,8748,8745,8828,8830,0,8745,8742,8825,8828,0,8742,8736,8820,8825,0,8736,8732,8815,8820,0,8732,8720,8803,8815,0,8720,8716,8800,8803,0,8716,8717,8801,8800,0,8717,8729,8812,8801,0,8729,8733,8817,8812,0,8733,8737,8821,8817,0,8737,8741,8823,8821,0,8741,8744,8827,8823,0,8744,8747,8829,8827,0,8747,8749,8831,8829,0,8749,8751,8834,8831,0,8751,8754,8836,8834,0,8754,8756,8838,8836,0,8756,8759,8841,8838,0,8759,8761,8843,8841,0,8761,8762,8844,8843,0,8762,8760,8842,8844,0,8760,8758,8839,8842,0,8758,8755,8837,8839,0,8755,8752,8833,8837,0,8752,8746,8826,8833,0,8746,8738,8819,8826,0,8738,8735,8816,8819,0,8735,8731,8813,8816,0,8731,8728,8810,8813,0,8728,8726,8808,8810,0,8726,8723,8806,8808,0,8723,8721,8802,8806,0,8721,8719,8799,8802,0,8719,8715,8797,8799,0,8715,8713,8795,8797,0,8713,8711,8793,8795,0,8711,8709,8791,8793,0,8709,8707,8789,8791,0,8707,8704,8786,8789,0,8704,8702,8784,8786,0,8702,8700,8782,8784,0,8700,8699,8781,8782,0,8699,8697,8779,8781,0,8697,8695,8777,8779,0,8695,8694,8776,8777,0,8776,8775,8857,8858,0,8775,8778,8860,8857,0,8778,8780,8862,8860,0,8780,8783,8865,8862,0,8783,8785,8867,8865,0,8785,8787,8869,8867,0,8787,8788,8870,8869,0,8788,8790,8872,8870,0,8790,8792,8874,8872,0,8792,8794,8876,8874,0,8794,8796,8878,8876,0,8796,8798,8880,8878,0,8798,8804,8885,8880,0,8804,8805,8887,8885,0,8805,8807,8889,8887,0,8807,8809,8891,8889,0,8809,8811,8893,8891,0,8811,8814,8896,8893,0,8814,8818,8900,8896,0,8818,8822,8904,8900,0,8822,8824,8905,8904,0,8824,8846,8928,8905,0,8846,8848,8930,8928,0,8848,8850,8932,8930,0,8850,8852,8934,8932,0,8852,8854,8936,8934,0,8854,8856,8938,8936,0,8856,8855,8937,8938,0,8855,8853,8935,8937,0,8853,8851,8933,8935,0,8851,8849,8931,8933,0,8849,8847,8929,8931,0,8847,8845,8927,8929,0,8845,8840,8922,8927,0,8840,8835,8917,8922,0,8835,8832,8914,8917,0,8832,8830,8912,8914,0,8830,8828,8910,8912,0,8828,8825,8907,8910,0,8825,8820,8902,8907,0,8820,8815,8898,8902,0,8815,8803,8886,8898,0,8803,8800,8882,8886,0,8800,8801,8883,8882,0,8801,8812,8895,8883,0,8812,8817,8899,8895,0,8817,8821,8903,8899,0,8821,8823,8906,8903,0,8823,8827,8909,8906,0,8827,8829,8911,8909,0,8829,8831,8913,8911,0,8831,8834,8916,8913,0,8834,8836,8919,8916,0,8836,8838,8920,8919,0,8838,8841,8923,8920,0,8841,8843,8925,8923,0,8843,8844,8926,8925,0,8844,8842,8924,8926,0,8842,8839,8921,8924,0,8839,8837,8918,8921,0,8837,8833,8915,8918,0,8833,8826,8908,8915,0,8826,8819,8901,8908,0,8819,8816,8897,8901,0,8816,8813,8894,8897,0,8813,8810,8892,8894,0,8810,8808,8890,8892,0,8808,8806,8888,8890,0,8806,8802,8884,8888,0,8802,8799,8881,8884,0,8799,8797,8879,8881,0,8797,8795,8877,8879,0,8795,8793,8875,8877,0,8793,8791,8873,8875,0,8791,8789,8871,8873,0,8789,8786,8868,8871,0,8786,8784,8866,8868,0,8784,8782,8864,8866,0,8782,8781,8863,8864,0,8781,8779,8861,8863,0,8779,8777,8859,8861,0,8777,8776,8858,8859,0,8858,8857,8939,8940,0,8857,8860,8942,8939,0,8860,8862,8944,8942,0,8862,8865,8947,8944,0,8865,8867,8949,8947,0,8867,8869,8951,8949,0,8869,8870,8952,8951,0,8870,8872,8954,8952,0,8872,8874,8956,8954,0,8874,8876,8958,8956,0,8876,8878,8960,8958,0,8878,8880,8962,8960,0,8880,8885,8965,8962,0,8885,8887,8968,8965,0,8887,8889,8971,8968,0,8889,8891,8973,8971,0,8891,8893,8975,8973,0,8893,8896,8977,8975,0,8896,8900,8980,8977,0,8900,8904,8984,8980,0,8904,8905,8987,8984,0,8905,8928,9009,8987,0,8928,8930,9011,9009,0,8930,8932,9013,9011,0,8932,8934,9015,9013,0,8934,8936,9017,9015,0,8936,8938,9019,9017,0,8938,8937,9020,9019,0,8937,8935,9018,9020,0,8935,8933,9016,9018,0,8933,8931,9014,9016,0,8931,8929,9012,9014,0,8929,8927,9010,9012,0,8927,8922,9008,9010,0,8922,8917,9001,9008,0,8917,8914,8997,9001,0,8914,8912,8994,8997,0,8912,8910,8992,8994,0,8910,8907,8990,8992,0,8907,8902,8985,8990,0,8902,8898,8982,8985,0,8898,8886,8969,8982,0,8886,8882,8966,8969,0,8882,8883,8967,8966,0,8883,8895,8978,8967,0,8895,8899,8983,8978,0,8899,8903,8986,8983,0,8903,8906,8988,8986,0,8906,8909,8991,8988,0,8909,8911,8993,8991,0,8911,8913,8995,8993,0,8913,8916,8998,8995,0,8916,8919,9000,8998,0,8919,8920,9003,9000,0,8920,8923,9005,9003,0,8923,8925,9007,9005,0,8925,8926,9006,9007,0,8926,8924,9004,9006,0,8924,8921,9002,9004,0,8921,8918,8999,9002,0,8918,8915,8996,8999,0,8915,8908,8989,8996,0,8908,8901,8981,8989,0,8901,8897,8979,8981,0,8897,8894,8976,8979,0,8894,8892,8974,8976,0,8892,8890,8972,8974,0,8890,8888,8970,8972,0,8888,8884,8964,8970,0,8884,8881,8963,8964,0,8881,8879,8961,8963,0,8879,8877,8959,8961,0,8877,8875,8957,8959,0,8875,8873,8955,8957,0,8873,8871,8953,8955,0,8871,8868,8950,8953,0,8868,8866,8948,8950,0,8866,8864,8946,8948,0,8864,8863,8945,8946,0,8863,8861,8943,8945,0,8861,8859,8941,8943,0,8859,8858,8940,8941,0,8940,8939,9021,9022,0,8939,8942,9024,9021,0,8942,8944,9026,9024,0,8944,8947,9028,9026,0,8947,8949,9031,9028,0,8949,8951,9033,9031,0,8951,8952,9034,9033,0,8952,8954,9036,9034,0,8954,8956,9038,9036,0,8956,8958,9040,9038,0,8958,8960,9042,9040,0,8960,8962,9044,9042,0,8962,8965,9047,9044,0,8965,8968,9049,9047,0,8968,8971,9053,9049,0,8971,8973,9055,9053,0,8973,8975,9057,9055,0,8975,8977,9059,9057,0,8977,8980,9062,9059,0,8980,8984,9065,9062,0,8984,8987,9067,9065,0,8987,9009,9090,9067,0,9009,9011,9093,9090,0,9011,9013,9095,9093,0,9013,9015,9097,9095,0,9015,9017,9099,9097,0,9017,9019,9101,9099,0,9019,9020,9102,9101,0,9020,9018,9100,9102,0,9018,9016,9098,9100,0,9016,9014,9096,9098,0,9014,9012,9094,9096,0,9012,9010,9092,9094,0,9010,9008,9091,9092,0,9008,9001,9084,9091,0,9001,8997,9079,9084,0,8997,8994,9076,9079,0,8994,8992,9074,9076,0,8992,8990,9072,9074,0,8990,8985,9069,9072,0,8985,8982,9064,9069,0,8982,8969,9052,9064,0,8969,8966,9048,9052,0,8966,8967,9051,9048,0,8967,8978,9061,9051,0,8978,8983,9066,9061,0,8983,8986,9068,9066,0,8986,8988,9071,9068,0,8988,8991,9073,9071,0,8991,8993,9075,9073,0,8993,8995,9078,9075,0,8995,8998,9081,9078,0,8998,9000,9082,9081,0,9000,9003,9085,9082,0,9003,9005,9087,9085,0,9005,9007,9089,9087,0,9007,9006,9088,9089,0,9006,9004,9086,9088,0,9004,9002,9083,9086,0,9002,8999,9080,9083,0,8999,8996,9077,9080,0,8996,8989,9070,9077,0,8989,8981,9063,9070,0,8981,8979,9060,9063,0,8979,8976,9058,9060,0,8976,8974,9056,9058,0,8974,8972,9054,9056,0,8972,8970,9050,9054,0,8970,8964,9046,9050,0,8964,8963,9045,9046,0,8963,8961,9043,9045,0,8961,8959,9041,9043,0,8959,8957,9039,9041,0,8957,8955,9037,9039,0,8955,8953,9035,9037,0,8953,8950,9032,9035,0,8950,8948,9030,9032,0,8948,8946,9029,9030,0,8946,8945,9027,9029,0,8945,8943,9025,9027,0,8943,8941,9023,9025,0,8941,8940,9022,9023,0,9022,9021,9103,9104,0,9021,9024,9106,9103,0,9024,9026,9108,9106,0,9026,9028,9110,9108,0,9028,9031,9113,9110,0,9031,9033,9114,9113,0,9033,9034,9116,9114,0,9034,9036,9118,9116,0,9036,9038,9120,9118,0,9038,9040,9122,9120,0,9040,9042,9124,9122,0,9042,9044,9126,9124,0,9044,9047,9128,9126,0,9047,9049,9130,9128,0,9049,9053,9134,9130,0,9053,9055,9137,9134,0,9055,9057,9139,9137,0,9057,9059,9141,9139,0,9059,9062,9143,9141,0,9062,9065,9146,9143,0,9065,9067,9149,9146,0,9067,9090,9171,9149,0,9090,9093,9174,9171,0,9093,9095,9176,9174,0,9095,9097,9178,9176,0,9097,9099,9180,9178,0,9099,9101,9182,9180,0,9101,9102,9184,9182,0,9102,9100,9183,9184,0,9100,9098,9181,9183,0,9098,9096,9179,9181,0,9096,9094,9177,9179,0,9094,9092,9175,9177,0,9092,9091,9173,9175,0,9091,9084,9166,9173,0,9084,9079,9162,9166,0,9079,9076,9159,9162,0,9076,9074,9156,9159,0,9074,9072,9154,9156,0,9072,9069,9151,9154,0,9069,9064,9147,9151,0,9064,9052,9136,9147,0,9052,9048,9132,9136,0,9048,9051,9133,9132,0,9051,9061,9145,9133,0,9061,9066,9148,9145,0,9066,9068,9150,9148,0,9068,9071,9153,9150,0,9071,9073,9155,9153,0,9073,9075,9157,9155,0,9075,9078,9160,9157,0,9078,9081,9163,9160,0,9081,9082,9165,9163,0,9082,9085,9168,9165,0,9085,9087,9170,9168,0,9087,9089,9172,9170,0,9089,9088,9169,9172,0,9088,9086,9167,9169,0,9086,9083,9164,9167,0,9083,9080,9161,9164,0,9080,9077,9158,9161,0,9077,9070,9152,9158,0,9070,9063,9144,9152,0,9063,9060,9142,9144,0,9060,9058,9140,9142,0,9058,9056,9138,9140,0,9056,9054,9135,9138,0,9054,9050,9131,9135,0,9050,9046,9129,9131,0,9046,9045,9127,9129,0,9045,9043,9125,9127,0,9043,9041,9123,9125,0,9041,9039,9121,9123,0,9039,9037,9119,9121,0,9037,9035,9117,9119,0,9035,9032,9115,9117,0,9032,9030,9112,9115,0,9030,9029,9111,9112,0,9029,9027,9109,9111,0,9027,9025,9107,9109,0,9025,9023,9105,9107,0,9023,9022,9104,9105,0,9104,9103,9185,9186,0,9103,9106,9188,9185,0,9106,9108,9190,9188,0,9108,9110,9192,9190,0,9110,9113,9195,9192,0,9113,9114,9196,9195,0,9114,9116,9198,9196,0,9116,9118,9200,9198,0,9118,9120,9202,9200,0,9120,9122,9204,9202,0,9122,9124,9206,9204,0,9124,9126,9208,9206,0,9126,9128,9210,9208,0,9128,9130,9212,9210,0,9130,9134,9214,9212,0,9134,9137,9219,9214,0,9137,9139,9221,9219,0,9139,9141,9223,9221,0,9141,9143,9225,9223,0,9143,9146,9228,9225,0,9146,9149,9229,9228,0,9149,9171,9251,9229,0,9171,9174,9256,9251,0,9174,9176,9258,9256,0,9176,9178,9260,9258,0,9178,9180,9262,9260,0,9180,9182,9264,9262,0,9182,9184,9266,9264,0,9184,9183,9265,9266,0,9183,9181,9263,9265,0,9181,9179,9261,9263,0,9179,9177,9259,9261,0,9177,9175,9257,9259,0,9175,9173,9255,9257,0,9173,9166,9250,9255,0,9166,9162,9244,9250,0,9162,9159,9241,9244,0,9159,9156,9238,9241,0,9156,9154,9236,9238,0,9154,9151,9234,9236,0,9151,9147,9230,9234,0,9147,9136,9218,9230,0,9136,9132,9215,9218,0,9132,9133,9217,9215,0,9133,9145,9227,9217,0,9145,9148,9231,9227,0,9148,9150,9232,9231,0,9150,9153,9235,9232,0,9153,9155,9237,9235,0,9155,9157,9239,9237,0,9157,9160,9242,9239,0,9160,9163,9245,9242,0,9163,9165,9247,9245,0,9165,9168,9249,9247,0,9168,9170,9253,9249,0,9170,9172,9254,9253,0,9172,9169,9252,9254,0,9169,9167,9248,9252,0,9167,9164,9246,9248,0,9164,9161,9243,9246,0,9161,9158,9240,9243,0,9158,9152,9233,9240,0,9152,9144,9226,9233,0,9144,9142,9224,9226,0,9142,9140,9222,9224,0,9140,9138,9220,9222,0,9138,9135,9216,9220,0,9135,9131,9213,9216,0,9131,9129,9211,9213,0,9129,9127,9209,9211,0,9127,9125,9207,9209,0,9125,9123,9205,9207,0,9123,9121,9203,9205,0,9121,9119,9201,9203,0,9119,9117,9199,9201,0,9117,9115,9197,9199,0,9115,9112,9194,9197,0,9112,9111,9193,9194,0,9111,9109,9191,9193,0,9109,9107,9189,9191,0,9107,9105,9187,9189,0,9105,9104,9186,9187,0,9186,9185,9267,9268,0,9185,9188,9270,9267,0,9188,9190,9272,9270,0,9190,9192,9274,9272,0,9192,9195,9277,9274,0,9195,9196,9278,9277,0,9196,9198,9280,9278,0,9198,9200,9282,9280,0,9200,9202,9284,9282,0,9202,9204,9286,9284,0,9204,9206,9288,9286,0,9206,9208,9290,9288,0,9208,9210,9292,9290,0,9210,9212,9294,9292,0,9212,9214,9296,9294,0,9214,9219,9300,9296,0,9219,9221,9303,9300,0,9221,9223,9305,9303,0,9223,9225,9307,9305,0,9225,9228,9309,9307,0,9228,9229,9311,9309,0,9229,9251,9331,9311,0,9251,9256,9337,9331,0,9256,9258,9340,9337,0,9258,9260,9342,9340,0,9260,9262,9343,9342,0,9262,9264,9345,9343,0,9264,9266,9347,9345,0,9266,9265,9348,9347,0,9265,9263,9346,9348,0,9263,9261,9344,9346,0,9261,9259,9341,9344,0,9259,9257,9339,9341,0,9257,9255,9338,9339,0,9255,9250,9334,9338,0,9250,9244,9328,9334,0,9244,9241,9323,9328,0,9241,9238,9320,9323,0,9238,9236,9318,9320,0,9236,9234,9316,9318,0,9234,9230,9312,9316,0,9230,9218,9302,9312,0,9218,9215,9298,9302,0,9215,9217,9299,9298,0,9217,9227,9310,9299,0,9227,9231,9313,9310,0,9231,9232,9315,9313,0,9232,9235,9317,9315,0,9235,9237,9319,9317,0,9237,9239,9321,9319,0,9239,9242,9325,9321,0,9242,9245,9327,9325,0,9245,9247,9329,9327,0,9247,9249,9332,9329,0,9249,9253,9335,9332,0,9253,9254,9336,9335,0,9254,9252,9333,9336,0,9252,9248,9330,9333,0,9248,9246,9326,9330,0,9246,9243,9324,9326,0,9243,9240,9322,9324,0,9240,9233,9314,9322,0,9233,9226,9308,9314,0,9226,9224,9306,9308,0,9224,9222,9304,9306,0,9222,9220,9301,9304,0,9220,9216,9297,9301,0,9216,9213,9295,9297,0,9213,9211,9293,9295,0,9211,9209,9291,9293,0,9209,9207,9289,9291,0,9207,9205,9287,9289,0,9205,9203,9285,9287,0,9203,9201,9283,9285,0,9201,9199,9281,9283,0,9199,9197,9279,9281,0,9197,9194,9276,9279,0,9194,9193,9275,9276,0,9193,9191,9273,9275,0,9191,9189,9271,9273,0,9189,9187,9269,9271,0,9187,9186,9268,9269,0,9268,9267,9349,9350,0,9267,9270,9352,9349,0,9270,9272,9354,9352,0,9272,9274,9356,9354,0,9274,9277,9359,9356,0,9277,9278,9360,9359,0,9278,9280,9362,9360,0,9280,9282,9364,9362,0,9282,9284,9366,9364,0,9284,9286,9368,9366,0,9286,9288,9370,9368,0,9288,9290,9372,9370,0,9290,9292,9374,9372,0,9292,9294,9376,9374,0,9294,9296,9378,9376,0,9296,9300,9380,9378,0,9300,9303,9384,9380,0,9303,9305,9387,9384,0,9305,9307,9389,9387,0,9307,9309,9391,9389,0,9309,9311,9392,9391,0,9311,9331,9411,9392,0,9331,9337,9419,9411,0,9337,9340,9421,9419,0,9340,9342,9424,9421,0,9342,9343,9426,9424,0,9343,9345,9428,9426,0,9345,9347,9430,9428,0,9347,9348,9431,9430,0,9348,9346,9429,9431,0,9346,9344,9427,9429,0,9344,9341,9425,9427,0,9341,9339,9423,9425,0,9339,9338,9420,9423,0,9338,9334,9418,9420,0,9334,9328,9412,9418,0,9328,9323,9406,9412,0,9323,9320,9403,9406,0,9320,9318,9400,9403,0,9318,9316,9398,9400,0,9316,9312,9395,9398,0,9312,9302,9386,9395,0,9302,9298,9382,9386,0,9298,9299,9383,9382,0,9299,9310,9393,9383,0,9310,9313,9394,9393,0,9313,9315,9397,9394,0,9315,9317,9399,9397,0,9317,9319,9401,9399,0,9319,9321,9404,9401,0,9321,9325,9407,9404,0,9325,9327,9409,9407,0,9327,9329,9413,9409,0,9329,9332,9415,9413,0,9332,9335,9417,9415,0,9335,9336,9416,9417,0,9336,9333,9414,9416,0,9333,9330,9410,9414,0,9330,9326,9408,9410,0,9326,9324,9405,9408,0,9324,9322,9402,9405,0,9322,9314,9396,9402,0,9314,9308,9390,9396,0,9308,9306,9388,9390,0,9306,9304,9385,9388,0,9304,9301,9381,9385,0,9301,9297,9379,9381,0,9297,9295,9377,9379,0,9295,9293,9375,9377,0,9293,9291,9373,9375,0,9291,9289,9371,9373,0,9289,9287,9369,9371,0,9287,9285,9367,9369,0,9285,9283,9365,9367,0,9283,9281,9363,9365,0,9281,9279,9361,9363,0,9279,9276,9358,9361,0,9276,9275,9357,9358,0,9275,9273,9355,9357,0,9273,9271,9353,9355,0,9271,9269,9351,9353,0,9269,9268,9350,9351,0,9350,9349,9422,9432,0,9349,9352,9434,9422,0,9352,9354,9436,9434,0,9354,9356,9438,9436,0,9356,9359,9441,9438,0,9359,9360,9442,9441,0,9360,9362,9444,9442,0,9362,9364,9446,9444,0,9364,9366,9448,9446,0,9366,9368,9450,9448,0,9368,9370,9452,9450,0,9370,9372,9454,9452,0,9372,9374,9456,9454,0,9374,9376,9458,9456,0,9376,9378,9460,9458,0,9378,9380,9462,9460,0,9380,9384,9465,9462,0,9384,9387,9469,9465,0,9387,9389,9471,9469,0,9389,9391,9473,9471,0,9391,9392,9474,9473,0,9392,9411,9492,9474,0,9411,9419,9501,9492,0,9419,9421,9503,9501,0,9421,9424,9505,9503,0,9424,9426,9507,9505,0,9426,9428,9509,9507,0,9428,9430,9511,9509,0,9430,9431,9512,9511,0,9431,9429,9510,9512,0,9429,9427,9508,9510,0,9427,9425,9506,9508,0,9425,9423,9504,9506,0,9423,9420,9502,9504,0,9420,9418,9500,9502,0,9418,9412,9494,9500,0,9412,9406,9488,9494,0,9406,9403,9485,9488,0,9403,9400,9482,9485,0,9400,9398,9480,9482,0,9398,9395,9478,9480,0,9395,9386,9468,9478,0,9386,9382,9464,9468,0,9382,9383,9466,9464,0,9383,9393,9475,9466,0,9393,9394,9477,9475,0,9394,9397,9479,9477,0,9397,9399,9481,9479,0,9399,9401,9483,9481,0,9401,9404,9486,9483,0,9404,9407,9489,9486,0,9407,9409,9491,9489,0,9409,9413,9495,9491,0,9413,9415,9497,9495,0,9415,9417,9499,9497,0,9417,9416,9498,9499,0,9416,9414,9496,9498,0,9414,9410,9493,9496,0,9410,9408,9490,9493,0,9408,9405,9487,9490,0,9405,9402,9484,9487,0,9402,9396,9476,9484,0,9396,9390,9472,9476,0,9390,9388,9470,9472,0,9388,9385,9467,9470,0,9385,9381,9463,9467,0,9381,9379,9461,9463,0,9379,9377,9459,9461,0,9377,9375,9457,9459,0,9375,9373,9455,9457,0,9373,9371,9453,9455,0,9371,9369,9451,9453,0,9369,9367,9449,9451,0,9367,9365,9447,9449,0,9365,9363,9445,9447,0,9363,9361,9443,9445,0,9361,9358,9440,9443,0,9358,9357,9439,9440,0,9357,9355,9437,9439,0,9355,9353,9435,9437,0,9353,9351,9433,9435,0,9351,9350,9432,9433,0,9432,9422,9513,9514,0,9422,9434,9516,9513,0,9434,9436,9518,9516,0,9436,9438,9520,9518,0,9438,9441,9523,9520,0,9441,9442,9524,9523,0,9442,9444,9526,9524,0,9444,9446,9528,9526,0,9446,9448,9530,9528,0,9448,9450,9532,9530,0,9450,9452,9534,9532,0,9452,9454,9536,9534,0,9454,9456,9538,9536,0,9456,9458,9540,9538,0,9458,9460,9542,9540,0,9460,9462,9544,9542,0,9462,9465,9546,9544,0,9465,9469,9550,9546,0,9469,9471,9553,9550,0,9471,9473,9555,9553,0,9473,9474,9556,9555,0,9474,9492,9573,9556,0,9492,9501,9582,9573,0,9501,9503,9584,9582,0,9503,9505,9586,9584,0,9505,9507,9588,9586,0,9507,9509,9590,9588,0,9509,9511,9592,9590,0,9511,9512,9594,9592,0,9512,9510,9593,9594,0,9510,9508,9591,9593,0,9508,9506,9589,9591,0,9506,9504,9587,9589,0,9504,9502,9585,9587,0,9502,9500,9583,9585,0,9500,9494,9576,9583,0,9494,9488,9572,9576,0,9488,9485,9567,9572,0,9485,9482,9564,9567,0,9482,9480,9562,9564,0,9480,9478,9560,9562,0,9478,9468,9551,9560,0,9468,9464,9547,9551,0,9464,9466,9548,9547,0,9466,9475,9557,9548,0,9475,9477,9559,9557,0,9477,9479,9561,9559,0,9479,9481,9563,9561,0,9481,9483,9565,9563,0,9483,9486,9568,9565,0,9486,9489,9571,9568,0,9489,9491,9575,9571,0,9491,9495,9577,9575,0,9495,9497,9579,9577,0,9497,9499,9581,9579,0,9499,9498,9580,9581,0,9498,9496,9578,9580,0,9496,9493,9574,9578,0,9493,9490,9570,9574,0,9490,9487,9569,9570,0,9487,9484,9566,9569,0,9484,9476,9558,9566,0,9476,9472,9554,9558,0,9472,9470,9552,9554,0,9470,9467,9549,9552,0,9467,9463,9545,9549,0,9463,9461,9543,9545,0,9461,9459,9541,9543,0,9459,9457,9539,9541,0,9457,9455,9537,9539,0,9455,9453,9535,9537,0,9453,9451,9533,9535,0,9451,9449,9531,9533,0,9449,9447,9529,9531,0,9447,9445,9527,9529,0,9445,9443,9525,9527,0,9443,9440,9522,9525,0,9440,9439,9521,9522,0,9439,9437,9519,9521,0,9437,9435,9517,9519,0,9435,9433,9515,9517,0,9433,9432,9514,9515,0,9514,9513,9595,9596,0,9513,9516,9598,9595,0,9516,9518,9600,9598,0,9518,9520,9602,9600,0,9520,9523,9604,9602,0,9523,9524,9606,9604,0,9524,9526,9608,9606,0,9526,9528,9610,9608,0,9528,9530,9612,9610,0,9530,9532,9614,9612,0,9532,9534,9616,9614,0,9534,9536,9618,9616,0,9536,9538,9620,9618,0,9538,9540,9622,9620,0,9540,9542,9624,9622,0,9542,9544,9627,9624,0,9544,9546,9631,9627,0,9546,9550,9633,9631,0,9550,9553,9637,9633,0,9553,9555,9641,9637,0,9555,9556,9642,9641,0,9556,9573,9669,9642,0,9573,9582,9677,9669,0,9582,9584,9684,9677,0,9584,9586,9687,9684,0,9586,9588,9690,9687,0,9588,9590,9691,9690,0,9590,9592,9693,9691,0,9592,9594,9695,9693,0,9594,9593,9696,9695,0,9593,9591,9694,9696,0,9591,9589,9692,9694,0,9589,9587,9689,9692,0,9587,9585,9686,9689,0,9585,9583,9683,9686,0,9583,9576,9679,9683,0,9576,9572,9672,9679,0,9572,9567,9666,9672,0,9567,9564,9661,9666,0,9564,9562,9656,9661,0,9562,9560,9653,9656,0,9560,9551,9638,9653,0,9551,9547,9634,9638,0,9547,9548,9635,9634,0,9548,9557,9649,9635,0,9557,9559,9650,9649,0,9559,9561,9654,9650,0,9561,9563,9658,9654,0,9563,9565,9662,9658,0,9565,9568,9665,9662,0,9568,9571,9670,9665,0,9571,9575,9674,9670,0,9575,9577,9676,9674,0,9577,9579,9680,9676,0,9579,9581,9681,9680,0,9581,9580,9678,9681,0,9580,9578,9675,9678,0,9578,9574,9671,9675,0,9574,9570,9667,9671,0,9570,9569,9664,9667,0,9569,9566,9659,9664,0,9566,9558,9648,9659,0,9558,9554,9639,9648,0,9554,9552,9636,9639,0,9552,9549,9632,9636,0,9549,9545,9629,9632,0,9545,9543,9626,9629,0,9543,9541,9623,9626,0,9541,9539,9621,9623,0,9539,9537,9619,9621,0,9537,9535,9617,9619,0,9535,9533,9615,9617,0,9533,9531,9613,9615,0,9531,9529,9611,9613,0,9529,9527,9609,9611,0,9527,9525,9607,9609,0,9525,9522,9605,9607,0,9522,9521,9603,9605,0,9521,9519,9601,9603,0,9519,9517,9599,9601,0,9517,9515,9597,9599,0,9515,9514,9596,9597,0,9596,9595,9625,9628,0,9595,9598,9640,9625,0,9598,9600,9644,9640,0,9600,9602,9646,9644,0,9602,9604,9651,9646,0,9604,9606,9655,9651,0,9606,9608,9660,9655,0,9608,9610,9668,9660,0,9610,9612,9682,9668,0,9612,9614,9688,9682,0,9614,9616,9698,9688,0,9616,9618,9700,9698,0,9618,9620,9702,9700,0,9620,9622,9704,9702,0,9622,9624,9706,9704,0,9624,9627,9708,9706,0,9627,9631,9710,9708,0,9631,9633,9712,9710,0,9633,9637,9716,9712,0,9637,9641,9719,9716,0,9641,9642,9720,9719,0,9642,9669,9735,9720,0,9669,9677,9742,9735,0,9677,9684,9748,9742,0,9684,9687,9749,9748,0,9687,9690,9751,9749,0,9690,9691,9753,9751,0,9691,9693,9755,9753,0,9693,9695,9757,9755,0,9695,9696,9758,9757,0,9696,9694,9756,9758,0,9694,9692,9754,9756,0,9692,9689,9752,9754,0,9689,9686,9750,9752,0,9686,9683,9747,9750,0,9683,9679,9745,9747,0,9679,9672,9738,9745,0,9672,9666,9733,9738,0,9666,9661,9729,9733,0,9661,9656,9726,9729,0,9656,9653,9724,9726,0,9653,9638,9717,9724,0,9638,9634,9713,9717,0,9634,9635,9715,9713,0,9635,9649,9722,9715,0,9649,9650,9723,9722,0,9650,9654,9725,9723,0,9654,9658,9727,9725,0,9658,9662,9730,9727,0,9662,9665,9732,9730,0,9665,9670,9736,9732,0,9670,9674,9739,9736,0,9674,9676,9741,9739,0,9676,9680,9744,9741,0,9680,9681,9746,9744,0,9681,9678,9743,9746,0,9678,9675,9740,9743,0,9675,9671,9737,9740,0,9671,9667,9734,9737,0,9667,9664,9731,9734,0,9664,9659,9728,9731,0,9659,9648,9721,9728,0,9648,9639,9718,9721,0,9639,9636,9714,9718,0,9636,9632,9711,9714,0,9632,9629,9709,9711,0,9629,9626,9707,9709,0,9626,9623,9705,9707,0,9623,9621,9703,9705,0,9621,9619,9701,9703,0,9619,9617,9699,9701,0,9617,9615,9697,9699,0,9615,9613,9685,9697,0,9613,9611,9673,9685,0,9611,9609,9663,9673,0,9609,9607,9657,9663,0,9607,9605,9652,9657,0,9605,9603,9647,9652,0,9603,9601,9645,9647,0,9601,9599,9643,9645,0,9599,9597,9630,9643,0,9597,9596,9628,9630,0,9628,9625,9759,9760,0,9625,9640,9762,9759,0,9640,9644,9764,9762,0,9644,9646,9766,9764,0,9646,9651,9768,9766,0,9651,9655,9770,9768,0,9655,9660,9772,9770,0,9660,9668,9774,9772,0,9668,9682,9776,9774,0,9682,9688,9778,9776,0,9688,9698,9780,9778,0,9698,9700,9782,9780,0,9700,9702,9784,9782,0,9702,9704,9786,9784,0,9704,9706,9788,9786,0,9706,9708,9790,9788,0,9708,9710,9792,9790,0,9710,9712,9794,9792,0,9712,9716,9797,9794,0,9716,9719,9801,9797,0,9719,9720,9802,9801,0,9720,9735,9817,9802,0,9735,9742,9823,9817,0,9742,9748,9829,9823,0,9748,9749,9831,9829,0,9749,9751,9833,9831,0,9751,9753,9835,9833,0,9753,9755,9837,9835,0,9755,9757,9839,9837,0,9757,9758,9840,9839,0,9758,9756,9838,9840,0,9756,9754,9836,9838,0,9754,9752,9834,9836,0,9752,9750,9832,9834,0,9750,9747,9830,9832,0,9747,9745,9828,9830,0,9745,9738,9820,9828,0,9738,9733,9816,9820,0,9733,9729,9811,9816,0,9729,9726,9808,9811,0,9726,9724,9806,9808,0,9724,9717,9800,9806,0,9717,9713,9796,9800,0,9713,9715,9798,9796,0,9715,9722,9804,9798,0,9722,9723,9805,9804,0,9723,9725,9807,9805,0,9725,9727,9809,9807,0,9727,9730,9812,9809,0,9730,9732,9814,9812,0,9732,9736,9818,9814,0,9736,9739,9821,9818,0,9739,9741,9824,9821,0,9741,9744,9826,9824,0,9744,9746,9827,9826,0,9746,9743,9825,9827,0,9743,9740,9822,9825,0,9740,9737,9819,9822,0,9737,9734,9815,9819,0,9734,9731,9813,9815,0,9731,9728,9810,9813,0,9728,9721,9803,9810,0,9721,9718,9799,9803,0,9718,9714,9795,9799,0,9714,9711,9793,9795,0,9711,9709,9791,9793,0,9709,9707,9789,9791,0,9707,9705,9787,9789,0,9705,9703,9785,9787,0,9703,9701,9783,9785,0,9701,9699,9781,9783,0,9699,9697,9779,9781,0,9697,9685,9777,9779,0,9685,9673,9775,9777,0,9673,9663,9773,9775,0,9663,9657,9771,9773,0,9657,9652,9769,9771,0,9652,9647,9767,9769,0,9647,9645,9765,9767,0,9645,9643,9763,9765,0,9643,9630,9761,9763,0,9630,9628,9760,9761,0,9760,9759,9841,9842,0,9759,9762,9844,9841,0,9762,9764,9845,9844,0,9764,9766,9848,9845,0,9766,9768,9850,9848,0,9768,9770,9852,9850,0,9770,9772,9854,9852,0,9772,9774,9856,9854,0,9774,9776,9858,9856,0,9776,9778,9860,9858,0,9778,9780,9862,9860,0,9780,9782,9864,9862,0,9782,9784,9866,9864,0,9784,9786,9868,9866,0,9786,9788,9870,9868,0,9788,9790,9872,9870,0,9790,9792,9874,9872,0,9792,9794,9876,9874,0,9794,9797,9878,9876,0,9797,9801,9882,9878,0,9801,9802,9884,9882,0,9802,9817,9897,9884,0,9817,9823,9902,9897,0,9823,9829,9911,9902,0,9829,9831,9912,9911,0,9831,9833,9914,9912,0,9833,9835,9916,9914,0,9835,9837,9918,9916,0,9837,9839,9920,9918,0,9839,9840,9922,9920,0,9840,9838,9921,9922,0,9838,9836,9919,9921,0,9836,9834,9917,9919,0,9834,9832,9915,9917,0,9832,9830,9913,9915,0,9830,9828,9910,9913,0,9828,9820,9904,9910,0,9820,9816,9899,9904,0,9816,9811,9894,9899,0,9811,9808,9890,9894,0,9808,9806,9888,9890,0,9806,9800,9883,9888,0,9800,9796,9880,9883,0,9796,9798,9881,9880,0,9798,9804,9886,9881,0,9804,9805,9887,9886,0,9805,9807,9889,9887,0,9807,9809,9892,9889,0,9809,9812,9895,9892,0,9812,9814,9898,9895,0,9814,9818,9901,9898,0,9818,9821,9905,9901,0,9821,9824,9907,9905,0,9824,9826,9909,9907,0,9826,9827,9908,9909,0,9827,9825,9906,9908,0,9825,9822,9903,9906,0,9822,9819,9900,9903,0,9819,9815,9896,9900,0,9815,9813,9893,9896,0,9813,9810,9891,9893,0,9810,9803,9885,9891,0,9803,9799,9879,9885,0,9799,9795,9877,9879,0,9795,9793,9875,9877,0,9793,9791,9873,9875,0,9791,9789,9871,9873,0,9789,9787,9869,9871,0,9787,9785,9867,9869,0,9785,9783,9865,9867,0,9783,9781,9863,9865,0,9781,9779,9861,9863,0,9779,9777,9859,9861,0,9777,9775,9857,9859,0,9775,9773,9855,9857,0,9773,9771,9853,9855,0,9771,9769,9851,9853,0,9769,9767,9849,9851,0,9767,9765,9847,9849,0,9765,9763,9846,9847,0,9763,9761,9843,9846,0,9761,9760,9842,9843,0,9842,9841,9923,9924,0,9841,9844,9926,9923,0,9844,9845,9927,9926,0,9845,9848,9930,9927,0,9848,9850,9932,9930,0,9850,9852,9934,9932,0,9852,9854,9936,9934,0,9854,9856,9939,9936,0,9856,9858,9942,9939,0,9858,9860,9945,9942,0,9860,9862,9947,9945,0,9862,9864,9950,9947,0,9864,9866,9955,9950,0,9866,9868,9959,9955,0,9868,9870,9963,9959,0,9870,9872,9967,9963,0,9872,9874,9971,9967,0,9874,9876,9974,9971,0,9876,9878,9978,9974,0,9878,9882,9982,9978,0,9882,9884,9986,9982,0,9884,9897,10012,9986,0,9897,9902,10018,10012,0,9902,9911,10028,10018,0,9911,9912,10031,10028,0,9912,9914,10034,10031,0,9914,9916,10036,10034,0,9916,9918,10039,10036,0,9918,9920,10041,10039,0,9920,9922,10044,10041,0,9922,9921,10042,10044,0,9921,9919,10040,10042,0,9919,9917,10037,10040,0,9917,9915,10035,10037,0,9915,9913,10033,10035,0,9913,9910,10029,10033,0,9910,9904,10023,10029,0,9904,9899,10016,10023,0,9899,9894,10008,10016,0,9894,9890,10004,10008,0,9890,9888,9999,10004,0,9888,9883,9988,9999,0,9883,9880,9983,9988,0,9880,9881,9984,9983,0,9881,9886,9995,9984,0,9886,9887,9998,9995,0,9887,9889,10001,9998,0,9889,9892,10005,10001,0,9892,9895,10009,10005,0,9895,9898,10014,10009,0,9898,9901,10017,10014,0,9901,9905,10022,10017,0,9905,9907,10025,10022,0,9907,9909,10027,10025,0,9909,9908,10026,10027,0,9908,9906,10024,10026,0,9906,9903,10019,10024,0,9903,9900,10015,10019,0,9900,9896,10011,10015,0,9896,9893,10007,10011,0,9893,9891,10002,10007,0,9891,9885,9992,10002,0,9885,9879,9980,9992,0,9879,9877,9977,9980,0,9877,9875,9973,9977,0,9875,9873,9969,9973,0,9873,9871,9965,9969,0,9871,9869,9961,9965,0,9869,9867,9957,9961,0,9867,9865,9953,9957,0,9865,9863,9949,9953,0,9863,9861,9946,9949,0,9861,9859,9944,9946,0,9859,9857,9940,9944,0,9857,9855,9937,9940,0,9855,9853,9935,9937,0,9853,9851,9933,9935,0,9851,9849,9931,9933,0,9849,9847,9929,9931,0,9847,9846,9928,9929,0,9846,9843,9925,9928,0,9843,9842,9924,9925,0,9924,9923,9938,9941,0,9923,9926,9948,9938,0,9926,9927,9951,9948,0,9927,9930,9956,9951,0,9930,9932,9960,9956,0,9932,9934,9964,9960,0,9934,9936,9968,9964,0,9936,9939,9972,9968,0,9939,9942,9976,9972,0,9942,9945,9981,9976,0,9945,9947,9987,9981,0,9947,9950,9990,9987,0,9950,9955,9993,9990,0,9955,9959,9996,9993,0,9959,9963,10000,9996,0,9963,9967,10006,10000,0,9967,9971,10013,10006,0,9971,9974,10021,10013,0,9974,9978,10032,10021,0,9978,9982,10043,10032,0,9982,9986,10047,10043,0,9986,10012,10061,10047,0,10012,10018,10066,10061,0,10018,10028,10074,10066,0,10028,10031,10076,10074,0,10031,10034,10078,10076,0,10034,10036,10080,10078,0,10036,10039,10082,10080,0,10039,10041,10084,10082,0,10041,10044,10086,10084,0,10044,10042,10085,10086,0,10042,10040,10083,10085,0,10040,10037,10081,10083,0,10037,10035,10079,10081,0,10035,10033,10077,10079,0,10033,10029,10075,10077,0,10029,10023,10069,10075,0,10023,10016,10064,10069,0,10016,10008,10058,10064,0,10008,10004,10055,10058,0,10004,9999,10052,10055,0,9999,9988,10048,10052,0,9988,9983,10045,10048,0,9983,9984,10046,10045,0,9984,9995,10050,10046,0,9995,9998,10051,10050,0,9998,10001,10053,10051,0,10001,10005,10056,10053,0,10005,10009,10059,10056,0,10009,10014,10062,10059,0,10014,10017,10065,10062,0,10017,10022,10068,10065,0,10022,10025,10071,10068,0,10025,10027,10073,10071,0,10027,10026,10072,10073,0,10026,10024,10070,10072,0,10024,10019,10067,10070,0,10019,10015,10063,10067,0,10015,10011,10060,10063,0,10011,10007,10057,10060,0,10007,10002,10054,10057,0,10002,9992,10049,10054,0,9992,9980,10038,10049,0,9980,9977,10030,10038,0,9977,9973,10020,10030,0,9973,9969,10010,10020,0,9969,9965,10003,10010,0,9965,9961,9997,10003,0,9961,9957,9994,9997,0,9957,9953,9991,9994,0,9953,9949,9989,9991,0,9949,9946,9985,9989,0,9946,9944,9979,9985,0,9944,9940,9975,9979,0,9940,9937,9970,9975,0,9937,9935,9966,9970,0,9935,9933,9962,9966,0,9933,9931,9958,9962,0,9931,9929,9954,9958,0,9929,9928,9952,9954,0,9928,9925,9943,9952,0,9925,9924,9941,9943,0,9941,9938,10087,10088,0,9938,9948,10090,10087,0,9948,9951,10091,10090,0,9951,9956,10094,10091,0,9956,9960,10096,10094,0,9960,9964,10098,10096,0,9964,9968,10100,10098,0,9968,9972,10102,10100,0,9972,9976,10104,10102,0,9976,9981,10106,10104,0,9981,9987,10108,10106,0,9987,9990,10110,10108,0,9990,9993,10112,10110,0,9993,9996,10114,10112,0,9996,10000,10116,10114,0,10000,10006,10118,10116,0,10006,10013,10120,10118,0,10013,10021,10122,10120,0,10021,10032,10124,10122,0,10032,10043,10126,10124,0,10043,10047,10128,10126,0,10047,10061,10141,10128,0,10061,10066,10146,10141,0,10066,10074,10154,10146,0,10074,10076,10157,10154,0,10076,10078,10159,10157,0,10078,10080,10161,10159,0,10080,10082,10163,10161,0,10082,10084,10165,10163,0,10084,10086,10167,10165,0,10086,10085,10168,10167,0,10085,10083,10166,10168,0,10083,10081,10164,10166,0,10081,10079,10162,10164,0,10079,10077,10160,10162,0,10077,10075,10158,10160,0,10075,10069,10155,10158,0,10069,10064,10148,10155,0,10064,10058,10143,10148,0,10058,10055,10137,10143,0,10055,10052,10134,10137,0,10052,10048,10130,10134,0,10048,10045,10127,10130,0,10045,10046,10129,10127,0,10046,10050,10132,10129,0,10050,10051,10133,10132,0,10051,10053,10136,10133,0,10053,10056,10139,10136,0,10056,10059,10142,10139,0,10059,10062,10145,10142,0,10062,10065,10149,10145,0,10065,10068,10151,10149,0,10068,10071,10153,10151,0,10071,10073,10156,10153,0,10073,10072,10152,10156,0,10072,10070,10150,10152,0,10070,10067,10147,10150,0,10067,10063,10144,10147,0,10063,10060,10140,10144,0,10060,10057,10138,10140,0,10057,10054,10135,10138,0,10054,10049,10131,10135,0,10049,10038,10125,10131,0,10038,10030,10123,10125,0,10030,10020,10121,10123,0,10020,10010,10119,10121,0,10010,10003,10117,10119,0,10003,9997,10115,10117,0,9997,9994,10113,10115,0,9994,9991,10111,10113,0,9991,9989,10109,10111,0,9989,9985,10107,10109,0,9985,9979,10105,10107,0,9979,9975,10103,10105,0,9975,9970,10101,10103,0,9970,9966,10099,10101,0,9966,9962,10097,10099,0,9962,9958,10095,10097,0,9958,9954,10093,10095,0,9954,9952,10092,10093,0,9952,9943,10089,10092,0,9943,9941,10088,10089,0,10088,10087,10169,10170,0,10087,10090,10172,10169,0,10090,10091,10173,10172,0,10091,10094,10176,10173,0,10094,10096,10178,10176,0,10096,10098,10180,10178,0,10098,10100,10182,10180,0,10100,10102,10184,10182,0,10102,10104,10186,10184,0,10104,10106,10188,10186,0,10106,10108,10190,10188,0,10108,10110,10192,10190,0,10110,10112,10194,10192,0,10112,10114,10196,10194,0,10114,10116,10198,10196,0,10116,10118,10200,10198,0,10118,10120,10202,10200,0,10120,10122,10204,10202,0,10122,10124,10206,10204,0,10124,10126,10208,10206,0,10126,10128,10209,10208,0,10128,10141,10222,10209,0,10141,10146,10227,10222,0,10146,10154,10234,10227,0,10154,10157,10239,10234,0,10157,10159,10241,10239,0,10159,10161,10243,10241,0,10161,10163,10245,10243,0,10163,10165,10247,10245,0,10165,10167,10249,10247,0,10167,10168,10250,10249,0,10168,10166,10248,10250,0,10166,10164,10246,10248,0,10164,10162,10244,10246,0,10162,10160,10242,10244,0,10160,10158,10240,10242,0,10158,10155,10238,10240,0,10155,10148,10230,10238,0,10148,10143,10225,10230,0,10143,10137,10220,10225,0,10137,10134,10216,10220,0,10134,10130,10212,10216,0,10130,10127,10210,10212,0,10127,10129,10211,10210,0,10129,10132,10214,10211,0,10132,10133,10215,10214,0,10133,10136,10218,10215,0,10136,10139,10221,10218,0,10139,10142,10224,10221,0,10142,10145,10228,10224,0,10145,10149,10231,10228,0,10149,10151,10233,10231,0,10151,10153,10236,10233,0,10153,10156,10237,10236,0,10156,10152,10235,10237,0,10152,10150,10232,10235,0,10150,10147,10229,10232,0,10147,10144,10226,10229,0,10144,10140,10223,10226,0,10140,10138,10219,10223,0,10138,10135,10217,10219,0,10135,10131,10213,10217,0,10131,10125,10207,10213,0,10125,10123,10205,10207,0,10123,10121,10203,10205,0,10121,10119,10201,10203,0,10119,10117,10199,10201,0,10117,10115,10197,10199,0,10115,10113,10195,10197,0,10113,10111,10193,10195,0,10111,10109,10191,10193,0,10109,10107,10189,10191,0,10107,10105,10187,10189,0,10105,10103,10185,10187,0,10103,10101,10183,10185,0,10101,10099,10181,10183,0,10099,10097,10179,10181,0,10097,10095,10177,10179,0,10095,10093,10175,10177,0,10093,10092,10174,10175,0,10092,10089,10171,10174,0,10089,10088,10170,10171,0,10170,10169,10251,10252,0,10169,10172,10254,10251,0,10172,10173,10255,10254,0,10173,10176,10258,10255,0,10176,10178,10260,10258,0,10178,10180,10262,10260,0,10180,10182,10264,10262,0,10182,10184,10266,10264,0,10184,10186,10268,10266,0,10186,10188,10270,10268,0,10188,10190,10272,10270,0,10190,10192,10274,10272,0,10192,10194,10276,10274,0,10194,10196,10278,10276,0,10196,10198,10280,10278,0,10198,10200,10282,10280,0,10200,10202,10284,10282,0,10202,10204,10286,10284,0,10204,10206,10287,10286,0,10206,10208,10290,10287,0,10208,10209,10291,10290,0,10209,10222,10304,10291,0,10222,10227,10309,10304,0,10227,10234,10315,10309,0,10234,10239,10321,10315,0,10239,10241,10323,10321,0,10241,10243,10325,10323,0,10243,10245,10327,10325,0,10245,10247,10329,10327,0,10247,10249,10331,10329,0,10249,10250,10332,10331,0,10250,10248,10330,10332,0,10248,10246,10328,10330,0,10246,10244,10326,10328,0,10244,10242,10324,10326,0,10242,10240,10322,10324,0,10240,10238,10320,10322,0,10238,10230,10312,10320,0,10230,10225,10307,10312,0,10225,10220,10302,10307,0,10220,10216,10298,10302,0,10216,10212,10294,10298,0,10212,10210,10292,10294,0,10210,10211,10293,10292,0,10211,10214,10296,10293,0,10214,10215,10297,10296,0,10215,10218,10300,10297,0,10218,10221,10303,10300,0,10221,10224,10306,10303,0,10224,10228,10310,10306,0,10228,10231,10313,10310,0,10231,10233,10316,10313,0,10233,10236,10318,10316,0,10236,10237,10319,10318,0,10237,10235,10317,10319,0,10235,10232,10314,10317,0,10232,10229,10311,10314,0,10229,10226,10308,10311,0,10226,10223,10305,10308,0,10223,10219,10301,10305,0,10219,10217,10299,10301,0,10217,10213,10295,10299,0,10213,10207,10289,10295,0,10207,10205,10288,10289,0,10205,10203,10285,10288,0,10203,10201,10283,10285,0,10201,10199,10281,10283,0,10199,10197,10279,10281,0,10197,10195,10277,10279,0,10195,10193,10275,10277,0,10193,10191,10273,10275,0,10191,10189,10271,10273,0,10189,10187,10269,10271,0,10187,10185,10267,10269,0,10185,10183,10265,10267,0,10183,10181,10263,10265,0,10181,10179,10261,10263,0,10179,10177,10259,10261,0,10177,10175,10257,10259,0,10175,10174,10256,10257,0,10174,10171,10253,10256,0,10171,10170,10252,10253,0,10252,10251,10333,10334,0,10251,10254,10336,10333,0,10254,10255,10337,10336,0,10255,10258,10340,10337,0,10258,10260,10342,10340,0,10260,10262,10344,10342,0,10262,10264,10346,10344,0,10264,10266,10348,10346,0,10266,10268,10350,10348,0,10268,10270,10352,10350,0,10270,10272,10354,10352,0,10272,10274,10356,10354,0,10274,10276,10358,10356,0,10276,10278,10360,10358,0,10278,10280,10362,10360,0,10280,10282,10364,10362,0,10282,10284,10366,10364,0,10284,10286,10368,10366,0,10286,10287,10369,10368,0,10287,10290,10372,10369,0,10290,10291,10373,10372,0,10291,10304,10385,10373,0,10304,10309,10390,10385,0,10309,10315,10396,10390,0,10315,10321,10402,10396,0,10321,10323,10404,10402,0,10323,10325,10406,10404,0,10325,10327,10408,10406,0,10327,10329,10410,10408,0,10329,10331,10412,10410,0,10331,10332,10414,10412,0,10332,10330,10413,10414,0,10330,10328,10411,10413,0,10328,10326,10409,10411,0,10326,10324,10407,10409,0,10324,10322,10405,10407,0,10322,10320,10403,10405,0,10320,10312,10397,10403,0,10312,10307,10391,10397,0,10307,10302,10384,10391,0,10302,10298,10381,10384,0,10298,10294,10377,10381,0,10294,10292,10374,10377,0,10292,10293,10375,10374,0,10293,10296,10378,10375,0,10296,10297,10379,10378,0,10297,10300,10383,10379,0,10300,10303,10387,10383,0,10303,10306,10389,10387,0,10306,10310,10393,10389,0,10310,10313,10395,10393,0,10313,10316,10399,10395,0,10316,10318,10400,10399,0,10318,10319,10401,10400,0,10319,10317,10398,10401,0,10317,10314,10394,10398,0,10314,10311,10392,10394,0,10311,10308,10388,10392,0,10308,10305,10386,10388,0,10305,10301,10382,10386,0,10301,10299,10380,10382,0,10299,10295,10376,10380,0,10295,10289,10371,10376,0,10289,10288,10370,10371,0,10288,10285,10367,10370,0,10285,10283,10365,10367,0,10283,10281,10363,10365,0,10281,10279,10361,10363,0,10279,10277,10359,10361,0,10277,10275,10357,10359,0,10275,10273,10355,10357,0,10273,10271,10353,10355,0,10271,10269,10351,10353,0,10269,10267,10349,10351,0,10267,10265,10347,10349,0,10265,10263,10345,10347,0,10263,10261,10343,10345,0,10261,10259,10341,10343,0,10259,10257,10339,10341,0,10257,10256,10338,10339,0,10256,10253,10335,10338,0,10253,10252,10334,10335,0,10334,10333,10415,10416,0,10333,10336,10418,10415,0,10336,10337,10419,10418,0,10337,10340,10422,10419,0,10340,10342,10424,10422,0,10342,10344,10426,10424,0,10344,10346,10428,10426,0,10346,10348,10430,10428,0,10348,10350,10432,10430,0,10350,10352,10434,10432,0,10352,10354,10436,10434,0,10354,10356,10438,10436,0,10356,10358,10440,10438,0,10358,10360,10442,10440,0,10360,10362,10444,10442,0,10362,10364,10446,10444,0,10364,10366,10448,10446,0,10366,10368,10450,10448,0,10368,10369,10451,10450,0,10369,10372,10454,10451,0,10372,10373,10455,10454,0,10373,10385,10466,10455,0,10385,10390,10472,10466,0,10390,10396,10477,10472,0,10396,10402,10484,10477,0,10402,10404,10486,10484,0,10404,10406,10488,10486,0,10406,10408,10490,10488,0,10408,10410,10492,10490,0,10410,10412,10494,10492,0,10412,10414,10496,10494,0,10414,10413,10495,10496,0,10413,10411,10493,10495,0,10411,10409,10491,10493,0,10409,10407,10489,10491,0,10407,10405,10487,10489,0,10405,10403,10485,10487,0,10403,10397,10479,10485,0,10397,10391,10473,10479,0,10391,10384,10468,10473,0,10384,10381,10463,10468,0,10381,10377,10459,10463,0,10377,10374,10456,10459,0,10374,10375,10457,10456,0,10375,10378,10460,10457,0,10378,10379,10462,10460,0,10379,10383,10465,10462,0,10383,10387,10469,10465,0,10387,10389,10471,10469,0,10389,10393,10475,10471,0,10393,10395,10478,10475,0,10395,10399,10481,10478,0,10399,10400,10482,10481,0,10400,10401,10483,10482,0,10401,10398,10480,10483,0,10398,10394,10476,10480,0,10394,10392,10474,10476,0,10392,10388,10470,10474,0,10388,10386,10467,10470,0,10386,10382,10464,10467,0,10382,10380,10461,10464,0,10380,10376,10458,10461,0,10376,10371,10453,10458,0,10371,10370,10452,10453,0,10370,10367,10449,10452,0,10367,10365,10447,10449,0,10365,10363,10445,10447,0,10363,10361,10443,10445,0,10361,10359,10441,10443,0,10359,10357,10439,10441,0,10357,10355,10437,10439,0,10355,10353,10435,10437,0,10353,10351,10433,10435,0,10351,10349,10431,10433,0,10349,10347,10429,10431,0,10347,10345,10427,10429,0,10345,10343,10425,10427,0,10343,10341,10423,10425,0,10341,10339,10421,10423,0,10339,10338,10420,10421,0,10338,10335,10417,10420,0,10335,10334,10416,10417,0,10416,10415,10497,10498,0,10415,10418,10500,10497,0,10418,10419,10501,10500,0,10419,10422,10504,10501,0,10422,10424,10506,10504,0,10424,10426,10508,10506,0,10426,10428,10510,10508,0,10428,10430,10512,10510,0,10430,10432,10514,10512,0,10432,10434,10516,10514,0,10434,10436,10518,10516,0,10436,10438,10520,10518,0,10438,10440,10522,10520,0,10440,10442,10524,10522,0,10442,10444,10526,10524,0,10444,10446,10528,10526,0,10446,10448,10530,10528,0,10448,10450,10531,10530,0,10450,10451,10533,10531,0,10451,10454,10536,10533,0,10454,10455,10537,10536,0,10455,10466,10548,10537,0,10466,10472,10553,10548,0,10472,10477,10558,10553,0,10477,10484,10566,10558,0,10484,10486,10568,10566,0,10486,10488,10570,10568,0,10488,10490,10572,10570,0,10490,10492,10574,10572,0,10492,10494,10576,10574,0,10494,10496,10578,10576,0,10496,10495,10577,10578,0,10495,10493,10575,10577,0,10493,10491,10573,10575,0,10491,10489,10571,10573,0,10489,10487,10569,10571,0,10487,10485,10567,10569,0,10485,10479,10562,10567,0,10479,10473,10555,10562,0,10473,10468,10550,10555,0,10468,10463,10546,10550,0,10463,10459,10541,10546,0,10459,10456,10538,10541,0,10456,10457,10539,10538,0,10457,10460,10542,10539,0,10460,10462,10544,10542,0,10462,10465,10547,10544,0,10465,10469,10551,10547,0,10469,10471,10554,10551,0,10471,10475,10557,10554,0,10475,10478,10560,10557,0,10478,10481,10563,10560,0,10481,10482,10565,10563,0,10482,10483,10564,10565,0,10483,10480,10561,10564,0,10480,10476,10559,10561,0,10476,10474,10556,10559,0,10474,10470,10552,10556,0,10470,10467,10549,10552,0,10467,10464,10545,10549,0,10464,10461,10543,10545,0,10461,10458,10540,10543,0,10458,10453,10535,10540,0,10453,10452,10534,10535,0,10452,10449,10532,10534,0,10449,10447,10529,10532,0,10447,10445,10527,10529,0,10445,10443,10525,10527,0,10443,10441,10523,10525,0,10441,10439,10521,10523,0,10439,10437,10519,10521,0,10437,10435,10517,10519,0,10435,10433,10515,10517,0,10433,10431,10513,10515,0,10431,10429,10511,10513,0,10429,10427,10509,10511,0,10427,10425,10507,10509,0,10425,10423,10505,10507,0,10423,10421,10503,10505,0,10421,10420,10502,10503,0,10420,10417,10499,10502,0,10417,10416,10498,10499,0,3323,3325,3327,3329,3333,3337,3339,3343,3345,3348,3349,3347,3344,3342,3338,3335,3332,3328,3326,3322,3318,3317,3315,3312,3310,3308,3306,3304,3302,3300,3298,3296,3294,3291,3289,3288,3286,3283,3282,3281,3284,3285,3287,3290,3292,3293,3295,3297,3299,3301,3303,3305,3307,3309,3311,3313,3314,3316,3319,3320,3331,3336,3341,3346,3351,3353,3355,3357,3359,3361,3362,3360,3358,3356,3354,3352,3350,3340,3334,3330,3324,3321,0,10498,10497,10500,10501,10504,10506,10508,10510,10512,10514,10516,10518,10520,10522,10524,10526,10528,10530,10531,10533,10536,10537,10548,10553,10558,10566,10568,10570,10572,10574,10576,10578,10577,10575,10573,10571,10569,10567,10562,10555,10550,10546,10541,10538,10539,10542,10544,10547,10551,10554,10557,10560,10563,10565,10564,10561,10559,10556,10552,10549,10545,10543,10540,10535,10534,10532,10529,10527,10525,10523,10521,10519,10517,10515,10513,10511,10509,10507,10505,10503,10502,10499,0]}} \ No newline at end of file +{ + "indexedMesh": { + "point": [ + [508706.2777792843, 6651140.513853399, 90.64963022028905], + [508706.4851137081, 6651139.940594222, 90.64963022028905], + [508706.4851137081, 6651139.940594222, 90.77963022028906], + [508706.2777792843, 6651140.513853399, 92.47843387928906], + [508706.28490812134, 6651140.49414287, 92.94402456628906], + [508706.30720094504, 6651140.432505418, 93.42129551828906], + [508706.4851129126, 6651139.940596422, 92.47843388028906], + [508706.4866588913, 6651139.936321944, 92.68225516428906], + [508706.34580754495, 6651140.325761987, 93.90419653828906], + [508706.49949579797, 6651139.900829167, 93.09883445228905], + [508706.3859590205, 6651140.214747127, 94.26590252328907], + [508706.5262542289, 6651139.826844751, 93.52316157228907], + [508706.43590831576, 6651140.076642266, 94.62366036928907], + [508706.5678003188, 6651139.711973921, 93.94947192328905], + [508706.4956613969, 6651139.9114309065, 94.97411658428906], + [508706.6246385284, 6651139.554821893, 94.37128078228906], + [508706.5650490394, 6651139.719580937, 95.31386161128906], + [508706.6968373622, 6651139.355199258, 94.78163032528906], + [508706.64372094884, 6651139.502060887, 95.63952872128907], + [508706.78397924855, 6651139.11426056, 95.17341001928907], + [508706.7311476779, 6651139.260334628, 95.94789752928908], + [508706.8586069096, 6651138.907922458, 95.45089187928906], + [508706.8266307387, 6651138.996333408, 96.23599588028905], + [508706.9405642631, 6651138.681318481, 95.71133255228906], + [508707.0291440019, 6651138.436404263, 95.95230219828906], + [508706.9293206465, 6651138.712405968, 96.50119360528906], + [508707.1235197014, 6651138.175464787, 96.17172120428907], + [508707.0382419553, 6651138.411249321, 96.74128205228907], + [508707.1523237469, 6651138.095824449, 96.95453438728906], + [508707.25676979084, 6651137.807041467, 96.42793432728907], + [508707.27043360844, 6651137.769262364, 97.13974328928906], + [508707.3963357616, 6651137.4211553605, 96.64021213628908], + [508707.3914128982, 6651137.4347665915, 97.29623458128906], + [508707.5397992159, 6651137.024493099, 96.80732689328907], + [508707.5141111274, 6651137.095518122, 97.42385734028906], + [508707.68479369435, 6651136.623597706, 96.92948001528907], + [508707.637417504, 6651136.754588186, 97.52295283428906], + [508707.8291136465, 6651136.224567309, 97.00815470828906], + [508707.8009801167, 6651136.302353737, 97.61211748628907], + [508707.97079844604, 6651135.832822851, 97.04589756728906], + [508707.96155622305, 6651135.858376684, 97.65489272728908], + [508708.55362604477, 6651134.221362181, 97.04589756728906], + [508709.14882702165, 6651132.575690342, 97.04589756728906], + [508709.15807004046, 6651132.55013431, 97.65489272728908], + [508709.2905118211, 6651132.183945884, 97.00815470828906], + [508709.4348317733, 6651131.784915489, 96.92948001528907], + [508709.3186461469, 6651132.106157256, 97.61211748628907], + [508710.63451255544, 6651128.467916771, 90.64963022028905], + [508710.63451255544, 6651128.467916771, 90.77963022028906], + [508709.57982625184, 6651131.384020096, 96.80732689328907], + [508709.4822087595, 6651131.653922807, 97.52295283428906], + [508709.723289706, 6651130.9873578325, 96.64021213628908], + [508710.84184697916, 6651127.894657594, 90.64963022028905], + [508709.60551513615, 6651131.31299287, 97.42385734028906], + [508709.86285567685, 6651130.601471727, 96.42793432728907], + [508709.7282133653, 6651130.973744401, 97.29623458128906], + [508710.63451255544, 6651128.467916771, 92.47843387928906], + [508709.9961057662, 6651130.233048406, 96.17172120428907], + [508710.62822240515, 6651128.485308414, 92.88924919128907], + [508709.849192655, 6651130.639248629, 97.13974328928906], + [508710.12069504283, 6651129.888571378, 95.87427873428906], + [508710.6085522666, 6651128.539694401, 93.31037061928907], + [508710.2071537418, 6651129.649521626, 95.62656899428906], + [508709.96730251657, 6651130.312686544, 96.95453438728906], + [508710.5744876195, 6651128.633879782, 93.73645975428906], + [508710.28673993266, 6651129.429473679, 95.36016267928906], + [508710.52533278905, 6651128.769788027, 94.16136625828906], + [508710.381039242, 6651129.168745415, 94.98028187728906], + [508710.84184697916, 6651127.894657594, 92.47843387928906], + [508710.46079327207, 6651128.94823341, 94.57833296028907], + [508710.0813843083, 6651129.997261671, 96.74128205228907], + [508710.83471814217, 6651127.914368123, 92.94402456628906], + [508710.190305617, 6651129.696105025, 96.50119360528906], + [508710.2929955248, 6651129.412177585, 96.23599588028905], + [508710.81242531847, 6651127.976005576, 93.42129551828906], + [508710.3884785856, 6651129.1481763655, 95.94789752928908], + [508710.77381871856, 6651128.082749007, 93.90419653828906], + [508710.47590531467, 6651128.906450105, 95.63952872128907], + [508710.7336672429, 6651128.193763865, 94.26590252328907], + [508710.5545772241, 6651128.688930056, 95.31386161128906], + [508710.6837179477, 6651128.331868728, 94.62366036928907], + [508710.6239648667, 6651128.497080087, 94.97411658428906], + [508714.78237503424, 6651143.589766587, 90.78879207594775], + [508714.9897094581, 6651143.01650741, 90.78879207594775], + [508714.9897094581, 6651143.01650741, 90.91879207594776], + [508714.78237503424, 6651143.589766587, 92.61759573494776], + [508714.78950387135, 6651143.5700560585, 93.08318642194777], + [508714.81179669505, 6651143.508418606, 93.56045737394776], + [508714.98970866256, 6651143.01650961, 92.61759573594777], + [508714.99125464127, 6651143.012235131, 92.82141701994776], + [508714.85040329496, 6651143.401675175, 94.04335839394776], + [508715.0040915479, 6651142.976742355, 93.23799630794775], + [508714.8905547706, 6651143.290660315, 94.40506437894776], + [508715.03084997885, 6651142.90275794, 93.66232342794775], + [508714.94050406583, 6651143.152555454, 94.76282222494775], + [508715.0723960689, 6651142.787887109, 94.08863377894775], + [508715.00025714684, 6651142.987344094, 95.11327843994776], + [508715.12923427834, 6651142.630735081, 94.51044263794776], + [508715.06964478944, 6651142.795494125, 95.45302346694776], + [508715.20143311226, 6651142.431112445, 94.92079218094777], + [508715.6774476409, 6651143.913247264, 90.80304684876648], + [508715.1483166988, 6651142.577974075, 95.77869057694775], + [508715.2885749985, 6651142.190173748, 95.31257187494776], + [508715.23574342794, 6651142.336247816, 96.08705938494776], + [508715.8845032102, 6651143.339887308, 90.80304684876648], + [508715.36320265953, 6651141.983835646, 95.59005373494777], + [508715.8845032102, 6651143.339887308, 90.9330468487665], + [508715.6774476409, 6651143.913247264, 92.63185050776649], + [508715.33122648863, 6651142.072246595, 96.37515773594775], + [508715.44516001304, 6651141.7572316695, 95.85049440794778], + [508715.68456689, 6651143.893533269, 93.0974411947665], + [508715.53373975185, 6651141.512317451, 96.09146405394776], + [508715.4339163965, 6651141.7883191565, 96.64035546094777], + [508715.706829731, 6651143.83188498, 93.57471214676649], + [508715.8845024158, 6651143.339889509, 92.6318505087665], + [508715.8860463153, 6651143.335614278, 92.83567179276649], + [508715.62811545137, 6651141.251377975, 96.31088305994776], + [508715.54283770523, 6651141.48716251, 96.88044390794778], + [508715.7453844069, 6651143.725122785, 94.05761316676649], + [508715.89886595693, 6651143.300115261, 93.25225108076648], + [508715.78548188077, 6651143.614088409, 94.41931915176649], + [508715.92558839906, 6651143.22611784, 93.6765782007665], + [508715.65691949695, 6651141.171737637, 97.09369624294777], + [508715.7613655408, 6651140.882954656, 96.56709618294778], + [508715.83536399674, 6651143.475959268, 94.77707699776649], + [508715.96707861166, 6651143.111226816, 94.10288855176648], + [508715.7750293585, 6651140.845175552, 97.27890514494776], + [508715.9009315116, 6651140.497068549, 96.77937399194776], + [508715.89503671293, 6651143.310718865, 95.1275332127665], + [508716.0238403766, 6651142.95404716, 94.52469741076649], + [508715.89600864815, 6651140.5106797805, 97.43539643694777], + [508715.9643310326, 6651143.11883517, 95.46727823976649], + [508716.04439496587, 6651140.100406287, 96.94648874894776], + [508716.09594210674, 6651142.754389431, 94.93504695376649], + [508716.01870687737, 6651140.1714313105, 97.56301919594776], + [508716.0428971322, 6651142.901276879, 95.7929453497665], + [508716.18938944436, 6651139.699510893, 97.06864187094776], + [508716.18296679156, 6651142.513408378, 95.3268266477665], + [508716.142013254, 6651139.830501375, 97.66211468994776], + [508716.13020627684, 6651142.659508124, 96.10131415776651], + [508716.2574940821, 6651142.307034001, 95.6043085077665], + [508716.3337093965, 6651139.300480497, 97.14731656394775], + [508716.3055758666, 6651139.378266925, 97.75127934194776], + [508716.2255609175, 6651142.395460493, 96.38941250876648], + [508716.33934120706, 6651142.080390187, 95.86474918076651], + [508716.47539419605, 6651138.908736039, 97.18505942294776], + [508716.42780181055, 6651141.835432913, 96.10571882676649], + [508716.3281127127, 6651142.11148314, 96.65461023376649], + [508716.46615197306, 6651138.934289873, 97.79405458294777], + [508716.5220505795, 6651141.574447565, 96.3251378327665], + [508716.4368875277, 6651141.8102735495, 96.8946986807665], + [508716.550815885, 6651141.494793227, 97.10795101576649], + [508716.65512145427, 6651141.2059594765, 96.5813509557665], + [508716.6687668947, 6651141.168173731, 97.29315991776649], + [508716.79449971585, 6651140.820005531, 96.79362876476651], + [508717.05822179484, 6651137.297275369, 97.18505942294776], + [508716.7895834734, 6651140.833619155, 97.44965120976649], + [508716.9377702189, 6651140.423273537, 96.9607435217665], + [508716.9121166796, 6651140.494311047, 97.57727396876649], + [508717.0825696871, 6651140.022307666, 97.0828966437665], + [508717.0352572153, 6651140.153321175, 97.67636946276649], + [508717.22669553617, 6651139.623207121, 97.16157133676649], + [508717.1985998445, 6651139.701007224, 97.7655341147665], + [508717.65342277166, 6651135.65160353, 97.18505942294776], + [508717.3681897767, 6651139.2313937945, 97.19931419576649], + [508717.6626657904, 6651135.626047498, 97.79405458294777], + [508717.7951075712, 6651135.259859072, 97.14731656394775], + [508717.35895998415, 6651139.256952119, 97.80830935576651], + [508717.93942752335, 6651134.860828677, 97.06864187094776], + [508717.82324189687, 6651135.182070444, 97.75127934194776], + [508719.1391083054, 6651131.543829958, 90.78879207594775], + [508719.1391083054, 6651131.543829958, 90.91879207594776], + [508718.0844220018, 6651134.459933283, 96.94648874894776], + [508717.9868045096, 6651134.7298359955, 97.66211468994776], + [508718.227885456, 6651134.063271021, 96.77937399194776], + [508719.34644272923, 6651130.970570781, 90.78879207594775], + [508718.1101108861, 6651134.388906058, 97.56301919594776], + [508718.3674514268, 6651133.677384914, 96.56709618294778], + [508718.23280911526, 6651134.049657589, 97.43539643694777], + [508717.9502335017, 6651137.619649831, 97.19931419576649], + [508719.1391083054, 6651131.543829958, 92.61759573494776], + [508718.5007015163, 6651133.3089615945, 96.31088305994776], + [508719.1328181552, 6651131.561221601, 93.02841104694775], + [508718.3537884051, 6651133.715161817, 97.27890514494776], + [508718.6252907928, 6651132.964484566, 96.01344058994778], + [508719.11314801656, 6651131.61560759, 93.44953247494776], + [508718.7117494918, 6651132.725434814, 95.76573084994776], + [508718.4718982665, 6651133.388599731, 97.09369624294777], + [508719.07908336946, 6651131.70979297, 93.87562160994777], + [508718.7913356826, 6651132.505386867, 95.49932453494776], + [508719.029928539, 6651131.845701215, 94.30052811394776], + [508718.88563499204, 6651132.244658602, 95.11944373294777], + [508719.34644272923, 6651130.970570781, 92.61759573494776], + [508718.9653890221, 6651132.024146597, 94.71749481594776], + [508718.58598005824, 6651133.07317486, 96.88044390794778], + [508719.3393138921, 6651130.990281312, 93.08318642194777], + [508718.694901367, 6651132.772018213, 96.64035546094777], + [508718.7975912748, 6651132.488090773, 96.37515773594775], + [508719.3170210684, 6651131.051918764, 93.56045737394776], + [508718.8930743356, 6651132.224089553, 96.08705938494776], + [508719.2784144686, 6651131.158662194, 94.04335839394776], + [508718.9805010646, 6651131.982363293, 95.77869057694775], + [508719.238262993, 6651131.269677053, 94.40506437894776], + [508719.05917297414, 6651131.764843244, 95.45302346694776], + [508719.18831369776, 6651131.407781915, 94.76282222494775], + [508719.12856061663, 6651131.572993275, 95.11327843994776], + [508718.544633963, 6651135.973688684, 97.19931419576649], + [508718.5538645504, 6651135.94812816, 97.80830935576651], + [508718.6861282035, 6651135.581875358, 97.16157133676649], + [508718.8302540526, 6651135.182774814, 97.0828966437665], + [508718.71422469, 6651135.5040730545, 97.7655341147665], + [508720.02832132427, 6651131.86519297, 90.80304684876648], + [508720.02832132427, 6651131.86519297, 90.9330468487665], + [508718.9750535208, 6651134.7818089435, 96.9607435217665], + [508718.8775673192, 6651135.051759104, 97.67636946276649], + [508719.11832402385, 6651134.385076948, 96.79362876476651], + [508720.23537689366, 6651131.291833014, 90.80304684876648], + [508719.00070785487, 6651134.710769232, 97.57727396876649], + [508719.2577022854, 6651133.999123003, 96.5813509557665], + [508719.12324106105, 6651134.371461123, 97.44965120976649], + [508720.02832132427, 6651131.86519297, 92.63185050776649], + [508719.3907731602, 6651133.630634915, 96.3251378327665], + [508720.02203963394, 6651131.882587671, 93.0426658197665], + [508719.24405763973, 6651134.036906548, 97.29315991776649], + [508719.5151948704, 6651133.286097328, 96.0276953627665], + [508720.0023959507, 6651131.93698322, 93.46378724776649], + [508719.60153728677, 6651133.047005552, 95.77998562276649], + [508719.36200864945, 6651133.710287051, 97.10795101576649], + [508719.9683771189, 6651132.0311851585, 93.88987638276649], + [508719.68101643823, 6651132.82691892, 95.51357930776649], + [508719.91928839916, 6651132.167117296, 94.3147828867665], + [508719.7751889197, 6651132.56614482, 95.1336985057665], + [508720.23537689366, 6651131.291833014, 92.63185050776649], + [508719.8548356846, 6651132.345594048, 94.7317495887665], + [508719.4759370069, 6651133.394806729, 96.8946986807665], + [508720.2282576446, 6651131.311547009, 93.0974411947665], + [508719.58471182187, 6651133.093597139, 96.65461023376649], + [508719.68726361694, 6651132.809619785, 96.38941250876648], + [508720.2059948036, 6651131.373195298, 93.57471214676649], + [508719.78261825774, 6651132.545572154, 96.10131415776651], + [508720.1674401276, 6651131.479957494, 94.05761316676649], + [508719.86992740224, 6651132.303803399, 95.7929453497665], + [508720.1273426537, 6651131.59099187, 94.41931915176649], + [508719.948493502, 6651132.08624511, 95.46727823976649], + [508720.07746053784, 6651131.72912101, 94.77707699776649], + [508720.0177878216, 6651131.894361413, 95.1275332127665], + [508725.32253985456, 6651147.367830913, 90.95204076656832], + [508725.38733578427, 6651147.390846381, 90.9530132307946], + [508725.52659055294, 6651146.793394702, 90.95204076656832], + [508725.52659055294, 6651146.793394702, 91.08204076656834], + [508725.59136629594, 6651146.816403001, 90.9530132307946], + [508725.59136629594, 6651146.816403001, 91.08301323079462], + [508725.32253985456, 6651147.367830913, 92.78084442556833], + [508725.38733578427, 6651147.390846381, 92.78181688979461], + [508725.32955578633, 6651147.348079913, 93.24643511256832], + [508725.3943510221, 6651147.371095134, 93.2474075767946], + [508725.35149554035, 6651147.286315903, 93.72370606456832], + [508725.52658977, 6651146.793396905, 92.78084442656832], + [508725.52811126376, 6651146.789113652, 92.98466571056832], + [508725.41628860554, 6651147.309330354, 93.7246785287946], + [508725.591365513, 6651146.816405204, 92.7818168907946], + [508725.3894906958, 6651147.179353304, 94.20660708456833], + [508725.5407448617, 6651146.753547998, 93.40124499856833], + [508725.5928868563, 6651146.812121895, 92.9856381747946], + [508725.45428000204, 6651147.20236642, 94.20757954879461], + [508725.60551920446, 6651146.7765558, 93.40221746279461], + [508725.4290062595, 6651147.068110505, 94.56831306956832], + [508725.56707949744, 6651146.679411677, 93.82557211856832], + [508725.4937916565, 6651147.091122234, 94.5692855337946], + [508725.6318512348, 6651146.702418552, 93.8265445827946], + [508725.4781644668, 6651146.929722083, 94.92607091556832], + [508725.60796758794, 6651146.56430499, 94.25188246956833], + [508725.5429450006, 6651146.952732083, 94.9270433797946], + [508725.67273528024, 6651146.587310429, 94.25285493379461], + [508725.53697118926, 6651146.764171507, 95.27652713056834], + [508725.6639056041, 6651146.406830293, 94.67369132856832], + [508725.60174590535, 6651146.78717944, 95.27749959479462], + [508725.7286677624, 6651146.429833766, 94.6746637927946], + [508725.60525988275, 6651146.571927624, 95.61627215756833], + [508725.73496096575, 6651146.206797785, 95.08404087156832], + [508725.67002784304, 6651146.59493316, 95.61724462179461], + [508725.7997160946, 6651146.229798762, 95.0850133357946], + [508725.6826858006, 6651146.353960956, 95.94193926756832], + [508725.82072271453, 6651145.965364385, 95.47582056556834], + [508725.74744610104, 6651146.376963769, 95.9429117317946], + [508725.88546935894, 6651145.988362348, 95.47679302979462], + [508725.7687278809, 6651146.111738377, 96.25030807556833], + [508725.894168436, 6651145.758602623, 95.75330242556832], + [508725.8334796691, 6651146.134738167, 96.2512805397946], + [508725.9589078144, 6651145.7815980045, 95.7542748897946], + [508725.86269869795, 6651145.847195102, 96.53840642656833], + [508725.9748277637, 6651145.531533376, 96.01374309856833], + [508725.9274411897, 6651145.87019159, 96.5393788907946], + [508726.03955916245, 6651145.554525924, 96.0147155627946], + [508726.06200459244, 6651145.286116293, 96.25471274456832], + [508725.96376222157, 6651145.562684693, 96.80360415156832], + [508726.1267273669, 6651145.309105776, 96.2556852087946], + [508726.02849471505, 6651145.585677629, 96.8045766157946], + [508726.1548855866, 6651145.024641049, 96.47413175056832], + [508726.07095845405, 6651145.260909703, 97.04369259856833], + [508726.21959917224, 6651145.047627268, 96.4751042147946], + [508726.1356803426, 6651145.283898872, 97.0446650627946], + [508726.1832334388, 6651144.94483719, 97.25694493356833], + [508726.28602528496, 6651144.65546127, 96.73034487356833], + [508726.2479442199, 6651144.967822416, 97.25791739779461], + [508726.35072589695, 6651144.678442883, 96.73131733779461], + [508726.2994726975, 6651144.6176045975, 97.44215383556832], + [508726.423380835, 6651144.268782851, 96.94262268256833], + [508726.3641719791, 6651144.640585736, 97.4431262997946], + [508726.4880678583, 6651144.291759636, 96.9435951467946], + [508726.41853593895, 6651144.2824220285, 97.59864512756832], + [508726.5645721407, 6651143.871306149, 97.10973743956832], + [508726.48322344164, 6651144.305398984, 97.5996175917946], + [508726.53929089557, 6651143.942477004, 97.72626788656834], + [508726.629245196, 6651143.894277973, 97.1107099037946], + [508726.7072702227, 6651143.469587625, 97.23189056156832], + [508726.60396645183, 6651143.965449717, 97.72724035079462], + [508726.6606443679, 6651143.600847059, 97.82536338056833], + [508726.7719291607, 6651143.492554434, 97.2328630257946], + [508726.7253079187, 6651143.623815507, 97.82633584479461], + [508726.8493044613, 6651143.069737928, 97.31056525456833], + [508726.8216165053, 6651143.147684069, 97.91452803256834], + [508726.9139493479, 6651143.092699747, 97.31153771879461], + [508726.9887452824, 6651142.677189128, 97.34830811356832], + [508726.886264131, 6651143.170646861, 97.9155004967946], + [508727.05337637407, 6651142.7001460465, 97.3492805777946], + [508726.97964943614, 6651142.702795427, 97.95730327356833], + [508727.0442814277, 6651142.725752666, 97.95827573779461], + [508727.56234216224, 6651141.062419756, 97.34830811356832], + [508727.62691650784, 6651141.085356518, 97.3492805777946], + [508728.14811645274, 6651139.413368974, 97.34830811356832], + [508728.21263284754, 6651139.436285153, 97.3492805777946], + [508728.15721308225, 6651139.38776047, 97.95730327356833], + [508728.2875572738, 6651139.020820174, 97.31056525456833], + [508728.22172857705, 6651139.4106763275, 97.95827573779461], + [508728.3520598737, 6651139.043731453, 97.31153771879461], + [508728.4295915124, 6651138.620970477, 97.23189056156832], + [508728.3152460131, 6651138.942871828, 97.91452803256834], + [508729.61027196544, 6651135.2971611945, 90.95204076656832], + [508729.61027196544, 6651135.2971611945, 91.08204076656834], + [508728.4940800608, 6651138.643876764, 97.2328630257946], + [508728.3797458737, 6651138.965782133, 97.9155004967946], + [508729.6746437088, 6651135.320025993, 90.9530132307946], + [508728.5722895944, 6651138.219251953, 97.10973743956832], + [508729.6746437088, 6651135.320025993, 91.08301323079462], + [508728.47621815046, 6651138.489708837, 97.82536338056833], + [508728.6367640256, 6651138.242153226, 97.1107099037946], + [508729.8143226638, 6651134.722724985, 90.95204076656832], + [508728.7134809001, 6651137.821775251, 96.94262268256833], + [508728.5407020861, 6651138.5126134865, 97.82633584479461], + [508728.59757162275, 6651138.148078892, 97.72626788656834], + [508729.8786742204, 6651134.745582613, 90.9530132307946], + [508728.7779413633, 6651137.844671562, 96.9435951467946], + [508728.8508364501, 6651137.435096831, 96.73034487356833], + [508728.6620435529, 6651138.170979277, 97.72724035079462], + [508728.7183265793, 6651137.8081338685, 97.59864512756832], + [508729.61027196544, 6651135.2971611945, 92.78084442556833], + [508728.98197614856, 6651137.065917053, 96.47413175056832], + [508728.91528332455, 6651137.457988316, 96.73131733779461], + [508729.6040814375, 6651135.314588548, 93.19165973756832], + [508728.78278656316, 6651137.831030009, 97.5996175917946], + [508728.8373898208, 6651137.4729512995, 97.44215383556832], + [508729.6746437088, 6651135.320025993, 92.78181688979461], + [508729.1045922024, 6651136.720732735, 96.17668928056834], + [508729.584722831, 6651135.369086202, 93.61278116556832], + [508729.04641004937, 6651137.088803929, 96.4751042147946], + [508729.6684537933, 6651135.337453564, 93.1926322017946], + [508729.189681584, 6651136.481192158, 95.92897954056832], + [508728.95362907957, 6651137.145718706, 97.25694493356833], + [508729.55119769374, 6651135.463464968, 94.03887030056832], + [508728.9018380256, 6651137.495843258, 97.4431262997946], + [508729.26800730306, 6651136.260692402, 95.66257322556834], + [508729.50282136863, 6651135.599652262, 94.46377680456833], + [508729.8143226638, 6651134.722724985, 92.78084442556833], + [508729.1690139728, 6651136.743615302, 96.17766174479462], + [508729.36081311695, 6651135.999428803, 95.28269242356832], + [508729.439304017, 6651135.778464034, 94.88074350656832], + [508729.649097102, 6651135.391951898, 93.6137536297946], + [508729.0659040642, 6651136.829646194, 97.04369259856833], + [508729.2540949366, 6651136.504071737, 95.9299520047946], + [508729.01806578477, 6651137.168606578, 97.25791739779461], + [508729.6155752814, 6651135.486331842, 94.0398427647946], + [508729.33241290686, 6651136.283569227, 95.66354568979462], + [508729.807306732, 6651134.742475984, 93.24643511256832], + [508729.56720374216, 6651135.622520837, 94.4647492687946], + [508729.8786742204, 6651134.745582613, 92.78181688979461], + [508729.42520953936, 6651136.022302366, 95.2836648877946], + [508729.1731002968, 6651136.527871204, 96.80360415156832], + [508729.5036926743, 6651135.801334841, 94.8817159707946], + [508729.13032966206, 6651136.852530121, 97.0446650627946], + [508729.7853669781, 6651134.804239994, 93.72370606456832], + [508729.2741638204, 6651136.243360795, 96.53840642656833], + [508729.8716589827, 6651134.765333859, 93.2474075767946], + [508729.2375152897, 6651136.550751365, 96.8045766157946], + [508729.3681346375, 6651135.97881752, 96.25030807556833], + [508729.7473718226, 6651134.911202593, 94.20660708456833], + [508729.45417671767, 6651135.73659494, 95.94193926756832], + [508729.7078562588, 6651135.022445392, 94.56831306956832], + [508729.84972139925, 6651134.827098639, 93.7246785287946], + [508729.6586980516, 6651135.160833814, 94.92607091556832], + [508729.5316026356, 6651135.518628272, 95.61627215756833], + [508729.338568815, 6651136.266237404, 96.5393788907946], + [508729.599891329, 6651135.326384392, 95.27652713056834], + [508729.43253033556, 6651136.001690826, 96.2512805397946], + [508729.81173000264, 6651134.934062573, 94.20757954879461], + [508729.51856390364, 6651135.759465223, 95.9429117317946], + [508729.77221834817, 6651135.04530676, 94.5692855337946], + [508729.72306500416, 6651135.183696911, 94.9270433797946], + [508729.59598216176, 6651135.5414958345, 95.61724462179461], + [508729.66426409944, 6651135.349249553, 95.27749959479462], + [508731.2576440958, 6651149.465347872, 91.03954345236868], + [508731.4598457478, 6651148.890258194, 91.03954345236868], + [508731.4598457478, 6651148.890258194, 91.16954345236869], + [508731.2576440958, 6651149.465347872, 92.86834711136868], + [508731.2645964514, 6651149.445574404, 93.33393779836867], + [508731.45984497207, 6651148.8902604, 92.86834711236867], + [508731.28633739386, 6651149.383740134, 93.81120875036866], + [508731.46135267854, 6651148.885972272, 93.07216839636867], + [508731.32398824865, 6651149.276655856, 94.29410977036868], + [508731.47387179465, 6651148.850366161, 93.48874768436868], + [508731.4999677937, 6651148.776145502, 93.91307480436866], + [508731.3631457341, 6651149.165286509, 94.65581575536866], + [508731.4118584844, 6651149.026740658, 95.01357360136866], + [508731.5404853686, 6651148.660907873, 94.33938515536866], + [508731.47013231803, 6651148.861001753, 95.36402981636869], + [508731.5959164912, 6651148.503254035, 94.76119401436867], + [508731.5378021998, 6651148.668539179, 95.70377484336868], + [508731.66632797045, 6651148.302993974, 95.17154355736866], + [508731.6145265072, 6651148.450324556, 96.02944195336866], + [508731.7513125718, 6651148.061285923, 95.56332325136869], + [508731.6997888998, 6651148.207826428, 96.33781076136867], + [508731.8240927502, 6651147.854288953, 95.84080511136867], + [508731.7929081815, 6651147.942982213, 96.62590911236867], + [508731.9040211672, 6651147.626961395, 96.10124578436867], + [508731.9904080257, 6651147.38126513, 96.34221543036867], + [508731.8930558976, 6651147.65814815, 96.89110683736867], + [508732.08244736, 6651147.119492435, 96.56163443636866], + [508731.99928075, 6651147.356029864, 97.13119528436867], + [508732.1105383324, 6651147.039597794, 97.34444761936867], + [508732.21239870973, 6651146.749892686, 96.81784755936867], + [508732.2257242658, 6651146.711992947, 97.52965652136866], + [508732.3485095847, 6651146.362774386, 97.03012536836867], + [508732.34370859177, 6651146.37642908, 97.68614781336866], + [508732.4884214571, 6651145.964845522, 97.19724012536867], + [508732.46336930303, 6651146.03609734, 97.81377057236868], + [508732.6298264518, 6651145.562670009, 97.31939324736867], + [508732.5836231066, 6651145.694078762, 97.91286606636868], + [508732.77057361865, 6651145.16236545, 97.39806794036868], + [508732.7431365626, 6651145.240400261, 98.00203071836869], + [508732.90875086875, 6651144.769370093, 97.43581079936867], + [508732.89973744634, 6651144.795005524, 98.04480595936867], + [508733.47714998526, 6651143.152763788, 97.43581079936867], + [508734.05761616444, 6651141.501837073, 97.43581079936867], + [508734.066630363, 6651141.476199437, 98.04480595936867], + [508734.19579341455, 6651141.108841715, 97.39806794036868], + [508734.33654058137, 6651140.708537157, 97.31939324736867], + [508735.5065220615, 6651137.380946767, 91.03954345236868], + [508734.22323124675, 6651141.030804697, 98.00203071836869], + [508735.5065220615, 6651137.380946767, 91.16954345236869], + [508734.477945576, 6651140.306361645, 97.19724012536867], + [508734.38274470274, 6651140.577126197, 97.91286606636868], + [508734.433606892, 6651150.578949004, 91.08506430210429], + [508735.7087237135, 6651136.805857087, 91.03954345236868], + [508734.6178574484, 6651139.90843278, 97.03012536836867], + [508734.5029985063, 6651140.23510762, 97.81377057236868], + [508734.75396832346, 6651139.521314481, 96.81784755936867], + [508735.5065220615, 6651137.380946767, 92.86834711136868], + [508734.62265921757, 6651139.89477588, 97.68614781336866], + [508734.6348190917, 6651150.003512391, 91.08506430210429], + [508734.6348190917, 6651150.003512391, 91.2150643021043], + [508734.8839196733, 6651139.151714731, 96.56163443636866], + [508735.5003876302, 6651137.398393943, 93.27916242336866], + [508734.74064354354, 6651139.559212013, 97.52965652136866], + [508735.00542461715, 6651138.806137736, 96.26419196636867], + [508735.4812044456, 6651137.452953594, 93.70028385136867], + [508734.433606892, 6651150.578949004, 92.91386796110429], + [508735.0897429443, 6651138.566324663, 96.01648222636868], + [508735.4479831031, 6651137.547439722, 94.12637298636866], + [508734.85582947696, 6651139.231607164, 97.34444761936867], + [508735.167358899, 6651138.34557407, 95.75007591136868], + [508735.7087237135, 6651136.805857087, 92.86834711136868], + [508735.40004514984, 6651137.683781942, 94.55127949036867], + [508735.2593237343, 6651138.08401326, 95.37019510936867], + [508735.3371033734, 6651137.862797127, 94.96824619236867], + [508734.440525227, 6651150.559163608, 93.37945864810429], + [508734.96708705934, 6651138.915175093, 97.13119528436867], + [508735.70177135797, 6651136.825630555, 93.33393779836867], + [508735.0733119117, 6651138.613056809, 96.89110683736867], + [508735.6800304155, 6651136.887464826, 93.81120875036866], + [508734.63481831976, 6651150.003514597, 92.91386796210429], + [508734.4621597824, 6651150.497292034, 93.85672960010429], + [508735.17345962784, 6651138.328222747, 96.62590911236867], + [508734.63631864847, 6651149.999223883, 93.1176892461043], + [508735.6423795607, 6651136.994549103, 94.29410977036868], + [508735.26657890953, 6651138.0633785315, 96.33781076136867], + [508735.6032220752, 6651137.105918449, 94.65581575536866], + [508735.3518413021, 6651137.820880404, 96.02944195336866], + [508735.55450932495, 6651137.244464301, 95.01357360136866], + [508735.4285656095, 6651137.60266578, 95.70377484336868], + [508735.4962354913, 6651137.4102032045, 95.36402981636869], + [508734.6487765035, 6651149.963596293, 93.53426853410429], + [508734.4996263967, 6651150.390143155, 94.33963062010429], + [508734.6747448047, 6651149.889330859, 93.9585956541043], + [508734.53859226924, 6651150.278706622, 94.7013366051043], + [508734.5870666489, 6651150.1400771905, 95.0590944511043], + [508734.71506411105, 6651149.77402371, 94.38490600510428], + [508734.64505532564, 6651149.974238301, 95.4095506661043], + [508734.7702239873, 6651149.616274762, 94.8067148641043], + [508734.7123940721, 6651149.781659619, 95.74929569310429], + [508734.8402909155, 6651149.415893892, 95.21706440710429], + [508734.7887429372, 6651149.563313353, 96.07496280310428], + [508734.92485965387, 6651149.174040023, 95.6088441011043], + [508734.8735881074, 6651149.320668933, 96.3833316111043], + [508734.9972836901, 6651148.966918178, 95.88632596110429], + [508734.9662517198, 6651149.055664944, 96.67142996210428], + [508735.0768209858, 6651148.73945348, 96.1467666341043], + [508735.1627851194, 6651148.4936089935, 96.3877362801043], + [508735.0659093737, 6651148.770659049, 96.93662768710429], + [508735.25437406905, 6651148.231678378, 96.6071552861043], + [508735.1716144261, 6651148.468358504, 97.1767161341043], + [508735.2823275813, 6651148.151735539, 97.38996846910429], + [508735.3836895157, 6651147.861855659, 96.8633684091043], + [508735.3969498646, 6651147.823933057, 97.5751773711043], + [508735.5191343467, 6651147.474503822, 97.07564621810431], + [508735.51435684675, 6651147.488166753, 97.73166866310429], + [508735.65836157516, 6651147.076334898, 97.24276097510429], + [508735.6334320112, 6651147.1476297, 97.85929142210429], + [508735.7990746194, 6651146.673916763, 97.36491409710429], + [508735.7530973654, 6651146.805404792, 97.95838691610429], + [508735.93913305504, 6651146.273370711, 97.44358879010429], + [508735.91183025925, 6651146.351452599, 98.0475515681043], + [508736.0766341495, 6651145.8801382715, 97.4813316491043], + [508736.0676648333, 6651145.905789166, 98.0903268091043], + [508736.6422518653, 6651144.262556712, 97.4813316491043], + [508737.21987759497, 6651142.610634039, 97.4813316491043], + [508737.2288476835, 6651142.584980935, 98.0903268091043], + [508737.3573786894, 6651142.217401598, 97.44358879010429], + [508738.66169342503, 6651138.487257712, 91.08506430210429], + [508737.49743712496, 6651141.816855546, 97.36491409710429], + [508737.3846822575, 6651142.139317501, 98.0475515681043], + [508738.66169342503, 6651138.487257712, 91.2150643021043], + [508737.6381501692, 6651141.414437412, 97.24276097510429], + [508737.5434151514, 6651141.685365309, 97.95838691610429], + [508738.8629056248, 6651137.911821096, 91.08506430210429], + [508737.77737739775, 6651141.016268489, 97.07564621810431], + [508737.6630805057, 6651141.343140403, 97.85929142210429], + [508737.91282222874, 6651140.628916651, 96.8633684091043], + [508738.66169342503, 6651138.487257712, 92.91386796110429], + [508737.78215567, 6651141.002603349, 97.73166866310429], + [508738.0421376754, 6651140.259093932, 96.6071552861043], + [508738.6555890119, 6651138.504715414, 93.3246832731043], + [508737.8995626522, 6651140.666837046, 97.5751773711043], + [508738.6364996983, 6651138.559307979, 93.7458047011043], + [508738.16304804775, 6651139.91330846, 96.3097128161043], + [508738.2469537721, 6651139.673350713, 96.06200307610429], + [508738.60344092076, 6651138.653851108, 94.17189383610429], + [508738.0141849354, 6651140.339034562, 97.38996846910429], + [508738.3241899215, 6651139.452466948, 95.79559676110429], + [508738.8629056248, 6651137.911821096, 92.91386796110429], + [508738.55573754676, 6651138.790275581, 94.5968003401043], + [508738.41570473666, 6651139.190748346, 95.41571595910429], + [508738.49310376926, 6651138.96939876, 95.0137670421043], + [508738.12489809067, 6651140.022411597, 97.1767161341043], + [508738.85598728986, 6651137.931606493, 93.37945864810429], + [508738.23060314305, 6651139.720111053, 96.93662768710429], + [508738.8343527343, 6651137.993478066, 93.85672960010429], + [508738.33026079694, 6651139.435105157, 96.67142996210428], + [508738.79688612005, 6651138.1006269455, 94.33963062010429], + [508738.42292440933, 6651139.1701011695, 96.3833316111043], + [508738.7579202475, 6651138.212063477, 94.7013366051043], + [508738.50776957953, 6651138.92745675, 96.07496280310428], + [508738.70944586786, 6651138.35069291, 95.0590944511043], + [508738.58411844465, 6651138.7091104835, 95.74929569310429], + [508738.65145719104, 6651138.516531801, 95.4095506661043], + [508747.7847779702, 6651155.193418403, 91.26653404189648], + [508747.9818306922, 6651154.616544179, 91.26653404189648], + [508747.9818306922, 6651154.616544179, 91.39653404189649], + [508747.7847779702, 6651155.193418403, 93.09533770089648], + [508747.7915532887, 6651155.173583576, 93.56092838789648], + [508747.98182993603, 6651154.616546391, 93.09533770189648], + [508747.8127406126, 6651155.11155743, 94.03819933989648], + [508747.98329924984, 6651154.612244957, 93.29915898589648], + [508747.995499575, 6651154.576528358, 93.71573827389648], + [508747.8494327134, 6651155.004140861, 94.52110035989648], + [508748.02093105693, 6651154.502077387, 94.14006539389649], + [508747.88759307977, 6651154.892425927, 94.8828063448965], + [508748.0604168787, 6651154.386482167, 94.56637574489648], + [508747.93506539235, 6651154.753450158, 95.24056419089648], + [508747.99185532174, 6651154.587196954, 95.59102040589649], + [508748.11443648476, 6651154.228339116, 94.98818460389649], + [508748.05780203507, 6651154.3941371525, 95.93076543289648], + [508748.1830549827, 6651154.027457634, 95.39853414689648], + [508748.1325726092, 6651154.175245394, 96.25643254289649], + [508748.265875508, 6651153.784999545, 95.79031384089649], + [508748.21566385194, 6651153.931994775, 96.5648013508965], + [508748.3368023877, 6651153.577360247, 96.06779570089648], + [508748.30641191325, 6651153.666328729, 96.85289970189648], + [508748.41469548084, 6651153.349327276, 96.32823637389649], + [508748.4988825557, 6651153.102868596, 96.56920601989648], + [508748.4040094346, 6651153.380610805, 97.11809742689648], + [508748.58857816976, 6651152.840283602, 96.7886250258965], + [508748.5075293421, 6651153.077555024, 97.35818587389649], + [508748.61595382437, 6651152.760141041, 97.57143820889648], + [508748.7152203951, 6651152.4695369555, 97.04483814889649], + [508748.7282066249, 6651152.431519611, 97.75664711089648], + [508748.84786529763, 6651152.0812174, 97.2571159578965], + [508748.84318655875, 6651152.094914465, 97.91313840289648], + [508748.98421440757, 6651151.682053732, 97.4242307148965], + [508748.9598001899, 6651151.753526649, 98.04076116189648], + [508749.1220186184, 6651151.27863024, 97.5463838368965], + [508749.0769918105, 6651151.410446763, 98.13985665589648], + [508749.2591817526, 6651150.877083505, 97.62505852989648], + [508749.23244336294, 6651150.955360464, 98.22902130789649], + [508749.3938404113, 6651150.482868655, 97.66280138889648], + [508749.38505650964, 6651150.508583633, 98.2717965488965], + [508749.9477656237, 6651148.861245898, 97.66280138889648], + [508750.51345061907, 6651147.205196234, 97.66280138889648], + [508750.5222352771, 6651147.179479042, 98.2717965488965], + [508750.64810927777, 6651146.810981384, 97.62505852989648], + [508751.9254610946, 6651143.071518497, 91.26653404189648], + [508751.9254610946, 6651143.071518497, 91.39653404189649], + [508750.78527241194, 6651146.409434651, 97.5463838368965], + [508750.67484842386, 6651146.73270221, 98.22902130789649], + [508750.92307662277, 6651146.006011156, 97.4242307148965], + [508750.8302999763, 6651146.277615911, 98.13985665589648], + [508752.12251381646, 6651142.494644271, 91.26653404189648], + [508751.05942573276, 6651145.606847488, 97.2571159578965], + [508750.9474915969, 6651145.934536026, 98.04076116189648], + [508751.9254610946, 6651143.071518497, 93.09533770089648], + [508751.19207063527, 6651145.218527934, 97.04483814889649], + [508751.06410522806, 6651145.59314821, 97.91313840289648], + [508751.91948287253, 6651143.0890198145, 93.50615301289649], + [508751.31871286064, 6651144.8477812875, 96.7886250258965], + [508751.1790851619, 6651145.256543064, 97.75664711089648], + [508751.90078817494, 6651143.143748769, 93.9272744408965], + [508751.43712376215, 6651144.501131942, 96.49118255589649], + [508751.86841279175, 6651143.238528093, 94.35336357589648], + [508751.5192949794, 6651144.26057471, 96.24347281589648], + [508752.12251381646, 6651142.494644271, 93.09533770089648], + [508751.2913379624, 6651144.927921632, 97.57143820889648], + [508751.59493449575, 6651144.039139111, 95.97706650089648], + [508751.8216955464, 6651143.375293394, 94.77827007989649], + [508751.6845575079, 6651143.77676666, 95.59718569889648], + [508751.7603565403, 6651143.554864077, 95.1952367818965], + [508751.3997624447, 6651144.61050765, 97.35818587389649], + [508752.11573849805, 6651142.514479098, 93.56092838789648], + [508751.5032823521, 6651144.307451869, 97.11809742689648], + [508752.0945511742, 6651142.576505245, 94.03819933989648], + [508751.6008798735, 6651144.021733946, 96.85289970189648], + [508752.0578590733, 6651142.683921814, 94.52110035989648], + [508751.69162793487, 6651143.7560679, 96.5648013508965], + [508752.01969870704, 6651142.795636747, 94.8828063448965], + [508751.77471917757, 6651143.512817281, 96.25643254289649], + [508751.9722263944, 6651142.934612516, 95.24056419089648], + [508751.8494897516, 6651143.293925522, 95.93076543289648], + [508751.9154364651, 6651143.100865722, 95.59102040589649], + [508753.2566042391, 6651157.053503849, 91.33631063381246], + [508753.45195224613, 6651156.4760501245, 91.33631063381246], + [508753.45195224613, 6651156.4760501245, 91.46631063381247], + [508753.2566042391, 6651157.053503849, 93.16511429281246], + [508753.26332094386, 6651157.033649098, 93.63070497981245], + [508753.45195149665, 6651156.47605234, 93.16511429381245], + [508753.2843249749, 6651156.971560642, 94.10797593181246], + [508753.4534080993, 6651156.471746585, 93.36893557781245], + [508753.4655028787, 6651156.435994107, 93.78551486581246], + [508753.3206996502, 6651156.864036168, 94.59087695181246], + [508753.4907143513, 6651156.361468348, 94.20984198581245], + [508753.358529889, 6651156.752209012, 94.95258293681245], + [508753.529858579, 6651156.245757005, 94.63615233681244], + [508753.40559151577, 6651156.613093634, 95.31034078281245], + [508753.461890152, 6651156.446673419, 95.66079699781247], + [508753.5834108582, 6651156.087455093, 95.05796119581247], + [508753.5272663565, 6651156.253419681, 96.00054202481246], + [508753.65143573337, 6651155.886371815, 95.46831073881245], + [508753.6013900858, 6651156.034308034, 96.32620913481244], + [508753.7335397734, 6651155.643670166, 95.86009043281247], + [508753.6837625013, 6651155.790813059, 96.63457794281246], + [508753.80385306035, 6651155.435822284, 96.13757229281245], + [508753.77372549573, 6651155.524880138, 96.92267629381246], + [508753.8810722957, 6651155.20756024, 96.39801296581246], + [508753.9645310631, 6651154.960853982, 96.63898261181245], + [508753.87047869514, 6651155.238875196, 97.18787401881245], + [508754.0534507151, 6651154.698005208, 96.85840161781245], + [508753.9731030456, 6651154.935514982, 97.42796246581246], + [508754.17899735103, 6651154.32688613, 97.11461474081246], + [508754.0805895413, 6651154.617782141, 97.64121480081245], + [508754.1918712361, 6651154.288830593, 97.82642370281246], + [508754.3104947345, 6651153.938176488, 97.32689254981246], + [508754.30585647165, 6651153.951887311, 97.98291499481245], + [508754.44566428015, 6651153.5386118395, 97.49400730681245], + [508754.4214612713, 6651153.610156555, 98.11053775381247], + [508754.5822763385, 6651153.134783087, 97.61616042881245], + [508754.53763906023, 6651153.266732028, 98.20963324781246], + [508754.7182528663, 6651152.73283298, 97.69483512181246], + [508754.69174579193, 6651152.811188572, 98.29879789981247], + [508754.8517465848, 6651152.338222121, 97.73257798081245], + [508754.8430386732, 6651152.363962931, 98.34157314081246], + [508755.40087975713, 6651150.714970364, 97.73257798081245], + [508755.9616709778, 6651149.05725712, 97.73257798081245], + [508755.9703796392, 6651149.031514091, 98.34157314081246], + [508756.09516469634, 6651148.662646259, 97.69483512181246], + [508757.3614660662, 6651144.919426898, 91.33631063381246], + [508757.3614660662, 6651144.919426898, 91.46631063381247], + [508756.23114122404, 6651148.260696153, 97.61616042881245], + [508756.1216725205, 6651148.58428845, 98.29879789981247], + [508756.36775328236, 6651147.856867401, 97.49400730681245], + [508757.5568140733, 6651144.341973173, 91.33631063381246], + [508756.2757792522, 6651148.128744994, 98.20963324781246], + [508756.502922828, 6651147.457302753, 97.32689254981246], + [508756.3919570411, 6651147.785320468, 98.11053775381247], + [508757.3614660662, 6651144.919426898, 93.16511429281246], + [508756.63442021154, 6651147.068593111, 97.11461474081246], + [508756.50756184076, 6651147.4435897125, 97.98291499481245], + [508757.3555395622, 6651144.936945797, 93.57592960481244], + [508756.7599668474, 6651146.697474032, 96.85840161781245], + [508757.33700659353, 6651144.991729728, 93.99705103281245], + [508756.6215470763, 6651147.106646429, 97.82642370281246], + [508756.87735336926, 6651146.35047646, 96.56095914781245], + [508757.30491129163, 6651145.086604264, 94.42314016781245], + [508756.95881371835, 6651146.109677576, 96.31324940781246], + [508757.5568140733, 6651144.341973173, 93.16511429281246], + [508756.7328287711, 6651146.777694883, 97.64121480081245], + [508757.2585982, 6651145.223506953, 94.84804667181247], + [508757.0337988728, 6651145.888019536, 96.04684309281245], + [508757.1977898413, 6651145.403258021, 95.26501337381245], + [508757.1226465509, 6651145.625383517, 95.66696229081245], + [508757.55009736854, 6651144.361827926, 93.63070497981245], + [508756.84031526675, 6651146.459962042, 97.42796246581246], + [508756.94293961726, 6651146.156601827, 97.18787401881245], + [508757.5290933375, 6651144.423916382, 94.10797593181246], + [508757.0396928167, 6651145.870596886, 96.92267629381246], + [508757.4927186622, 6651144.531440855, 94.59087695181246], + [508757.1296558111, 6651145.604663963, 96.63457794281246], + [508757.45488842344, 6651144.6432680115, 94.95258293681245], + [508757.2120282266, 6651145.361168989, 96.32620913481244], + [508757.40782679664, 6651144.782383389, 95.31034078281245], + [508757.2861519559, 6651145.142057342, 96.00054202481246], + [508757.35152816033, 6651144.948803603, 95.66079699781247], + [508764.36245595507, 6651160.77352044, 91.46976384454798], + [508764.5543440002, 6651160.194907766, 91.46976384454798], + [508764.5543440002, 6651160.194907766, 91.599763844548], + [508764.36245595507, 6651160.77352044, 93.29856750354799], + [508764.36905369506, 6651160.75362584, 93.76415819054799], + [508764.5543432639, 6651160.194909986, 93.29856750454799], + [508764.3896857072, 6651160.691412774, 94.24142914254799], + [508764.5557740675, 6651160.19059559, 93.50238878854799], + [508764.5676546268, 6651160.154771357, 93.91896807654798], + [508764.4254161221, 6651160.583672497, 94.72433016254799], + [508764.5924195593, 6651160.080096022, 94.343295196548], + [508764.4625763197, 6651160.471620903, 95.086036147548], + [508764.63087047276, 6651159.964152448, 94.76960554754798], + [508764.50880440115, 6651160.332226322, 95.443793993548], + [508764.564105888, 6651160.165472102, 95.794250208548], + [508764.6834742455, 6651159.805532824, 95.19141440654799], + [508764.62832416315, 6651159.971830503, 96.13399523554799], + [508764.75029427867, 6651159.604045973, 95.60176394954799], + [508764.70113502897, 6651159.7522791, 96.459662345548], + [508764.83094410953, 6651159.36085722, 95.993543643548], + [508764.78204848187, 6651159.50829543, 96.768031153548], + [508764.9000120227, 6651159.15259219, 96.27102550354799], + [508764.8704180711, 6651159.2418287825, 97.05612950454798], + [508764.97586356755, 6651158.923872025, 96.531466176548], + [508765.0578441312, 6651158.676670627, 96.772435822548], + [508764.9654575986, 6651158.955249829, 97.32132722954799], + [508765.1451888574, 6651158.413294315, 96.991854828548], + [508765.0662642886, 6651158.65128077, 97.561415676548], + [508765.2685118383, 6651158.041430401, 97.248067951548], + [508765.17184700654, 6651158.33291024, 97.77466801154799], + [508765.2811577039, 6651158.003298488, 97.95987691354799], + [508765.3976801684, 6651157.65194062, 97.46034576054801], + [508765.3931240574, 6651157.665678961, 98.11636820554799], + [508765.53045562014, 6651157.251574045, 97.62746051754799], + [508765.5066812897, 6651157.323262351, 98.24399096454799], + [508765.66464803496, 6651156.846934809, 97.74961363954799], + [508765.62080136256, 6651156.979148571, 98.34308645854799], + [508765.7982161757, 6651156.44417799, 97.82828833254798], + [508765.7721785889, 6651156.522690841, 98.432251110548], + [508765.9293454822, 6651156.048775146, 97.866031191548], + [508765.9207918033, 6651156.074567618, 98.475026351548], + [508766.46875252575, 6651154.422265525, 97.866031191548], + [508767.01961113274, 6651152.761225251, 97.866031191548], + [508767.02816554817, 6651152.735430557, 98.475026351548], + [508767.15074043913, 6651152.365822407, 97.82828833254798], + [508768.39461335127, 6651148.615090409, 91.46976384454798], + [508768.39461335127, 6651148.615090409, 91.599763844548], + [508767.28430857987, 6651151.963065587, 97.74961363954799], + [508767.17677876254, 6651152.287307334, 98.432251110548], + [508767.4185009948, 6651151.558426351, 97.62746051754799], + [508768.5865013963, 6651148.036477735, 91.46976384454798], + [508767.3281559888, 6651151.830849605, 98.34308645854799], + [508767.55127644655, 6651151.158059778, 97.46034576054801], + [508767.44227606175, 6651151.4867358245, 98.24399096454799], + [508768.39461335127, 6651148.615090409, 93.29856750354799], + [508767.68044477655, 6651150.768569997, 97.248067951548], + [508768.3887918162, 6651148.632644468, 93.709382815548], + [508767.55583329406, 6651151.144319215, 98.11636820554799], + [508767.80376775743, 6651150.396706083, 96.991854828548], + [508768.3705870994, 6651148.68753835, 94.130504243548], + [508767.66779964755, 6651150.806699689, 97.95987691354799], + [508767.9190751544, 6651150.049012086, 96.69441235854799], + [508768.3390602627, 6651148.782603299, 94.55659337854799], + [508768.5865013963, 6651148.036477735, 93.29856750354799], + [508767.99909269536, 6651149.807729919, 96.44670261854799], + [508768.2935674586, 6651148.919780752, 94.981499882548], + [508768.0727497287, 6651149.585627011, 96.18029630354799], + [508767.7771103449, 6651150.477087936, 97.77466801154799], + [508768.2338361244, 6651149.099892582, 95.398466584548], + [508768.16002375586, 6651149.322463883, 95.80041550154799], + [508768.5799036564, 6651148.056372336, 93.76415819054799], + [508767.8826930628, 6651150.158717405, 97.561415676548], + [508768.5592716442, 6651148.118585402, 94.24142914254799], + [508767.9834997528, 6651149.854748346, 97.32132722954799], + [508768.07853928034, 6651149.5681693945, 97.05612950454798], + [508768.52354122937, 6651148.226325678, 94.72433016254799], + [508768.1669088696, 6651149.301702744, 96.768031153548], + [508768.48638103175, 6651148.338377273, 95.086036147548], + [508768.2478223225, 6651149.057719076, 96.459662345548], + [508768.4401529504, 6651148.477771853, 95.443793993548], + [508768.38485146343, 6651148.644526073, 95.794250208548], + [508768.32063318836, 6651148.838167672, 96.13399523554799], + [508772.1444917337, 6651163.336241752, 91.55678584387401], + [508772.33395533194, 6651162.756830677, 91.55678584387401], + [508772.33395533194, 6651162.756830677, 91.686785843874], + [508772.1444917337, 6651163.336241752, 93.385589502874], + [508772.1510061133, 6651163.316319699, 93.851180189874], + [508772.3339546049, 6651162.7568329, 93.385589503874], + [508772.1713774462, 6651163.254020788, 94.32845114187401], + [508772.33536733076, 6651162.752512552, 93.58941078787402], + [508772.3470977828, 6651162.716638885, 94.005990075874], + [508772.20665641816, 6651163.146131848, 94.811352161874], + [508772.37154981797, 6651162.641860511, 94.430317195874], + [508772.24334710813, 6651163.0339256385, 95.17305814687401], + [508772.4095149159, 6651162.525756951, 94.856627546874], + [508772.2889911118, 6651162.894338713, 95.53081599287401], + [508772.34359388123, 6651162.727354397, 95.881272207874], + [508772.461454056, 6651162.366918456, 95.27843640587402], + [508772.4070007781, 6651162.533445602, 96.221017234874], + [508772.5274298385, 6651162.165153583, 95.688785948874], + [508772.47889170086, 6651162.313591248, 96.546684344874], + [508772.60706068337, 6651161.921629265, 96.080565642874], + [508772.55878283695, 6651162.069270918, 96.855053152874], + [508772.6752559445, 6651161.713076858, 96.358047502874], + [508772.64603590337, 6651161.802436585, 97.143151503874], + [508772.75014912826, 6651161.484041093, 96.618488175874], + [508772.8310938925, 6651161.236498593, 96.85945782187402], + [508772.73987463553, 6651161.5154621955, 97.408349228874], + [508772.9173350447, 6651160.972758862, 97.078876827874], + [508772.83940766373, 6651161.211073703, 97.648437675874], + [508773.0390998774, 6651160.60038183, 97.335089950874], + [508772.9436563763, 6651160.892263868, 97.861690010874], + [508773.0515859663, 6651160.562197301, 98.04689891287401], + [508773.16663620505, 6651160.2103546085, 97.547367759874], + [508773.1621376592, 6651160.224111907, 98.203390204874], + [508773.2977340795, 6651159.809435588, 97.714482516874], + [508773.27426013054, 6651159.881222813, 98.331012963874], + [508773.4302310141, 6651159.40423801, 97.836635638874], + [508773.38693833107, 6651159.536634209, 98.430108457874], + [508773.5621115622, 6651159.000925444, 97.915310331874], + [508773.53640295233, 6651159.079546632, 98.519273109874], + [508773.6915840899, 6651158.604977004, 97.95305319087402], + [508773.683138484, 6651158.630805066, 98.56204835087401], + [508774.22417589, 6651156.976223038, 97.95305319087402], + [508774.7680745667, 6651155.312890771, 97.95305319087402], + [508774.89754709427, 6651154.91694233, 97.915310331874], + [508774.77652089973, 6651155.287060485, 98.56204835087401], + [508776.1257040518, 6651151.161034873, 91.55678584387401], + [508776.1257040518, 6651151.161034873, 91.686785843874], + [508775.0294276423, 6651154.513629765, 97.836635638874], + [508774.9232564314, 6651154.838318918, 98.519273109874], + [508776.31516765006, 6651150.581623798, 91.55678584387401], + [508775.1619245771, 6651154.108432187, 97.714482516874], + [508775.0727210527, 6651154.381231342, 98.430108457874], + [508775.2930224514, 6651153.707513166, 97.547367759874], + [508775.1853992532, 6651154.036642737, 98.331012963874], + [508776.1257040518, 6651151.161034873, 93.385589502874], + [508775.4205587791, 6651153.317485945, 97.335089950874], + [508776.11995607, 6651151.178613153, 93.796404814874], + [508775.29752172454, 6651153.693753643, 98.203390204874], + [508775.54232361173, 6651152.945108913, 97.078876827874], + [508776.10198136437, 6651151.233582781, 94.21752624287402], + [508775.4080734175, 6651153.35566825, 98.04689891287401], + [508775.6561741349, 6651152.59693515, 96.781434357874], + [508776.0708528595, 6651151.328778906, 94.643615377874], + [508776.31516765006, 6651150.581623798, 93.385589502874], + [508775.7351806786, 6651152.355320049, 96.53372461787401], + [508776.0259348432, 6651151.466145642, 95.06852188187402], + [508775.8079070779, 6651152.132910673, 96.267318302874], + [508775.9669581962, 6651151.646506001, 95.485488583874], + [508775.5160030074, 6651153.025601682, 97.861690010874], + [508775.8940784244, 6651151.869384417, 95.887437500874], + [508776.3086532705, 6651150.601545851, 93.851180189874], + [508775.62025171996, 6651152.706791848, 97.648437675874], + [508776.28828193754, 6651150.663844762, 94.32845114187401], + [508775.7197847482, 6651152.402403356, 97.408349228874], + [508776.2530029656, 6651150.771733703, 94.811352161874], + [508775.8136234803, 6651152.1154289665, 97.143151503874], + [508776.2163122756, 6651150.883939912, 95.17305814687401], + [508775.9008765468, 6651151.848594632, 96.855053152874], + [508776.17066827195, 6651151.023526837, 95.53081599287401], + [508775.98076768295, 6651151.604274302, 96.546684344874], + [508776.11606550246, 6651151.190511154, 95.881272207874], + [508776.0526586056, 6651151.384419949, 96.221017234874], + [508780.98935330793, 6651166.2052080715, 91.64923286031915], + [508781.1760613422, 6651165.624903189, 91.64923286031915], + [508781.1760613422, 6651165.624903189, 91.77923286031915], + [508780.98935330793, 6651166.2052080715, 93.47803651931915], + [508780.9957729421, 6651166.185255287, 93.94362720631915], + [508781.17606062576, 6651165.624905415, 93.47803652031915], + [508781.0158479939, 6651166.122860272, 94.42089815831915], + [508781.17745280487, 6651165.620578401, 93.68185780431915], + [508781.1890126489, 6651165.584649395, 94.09843709231914], + [508781.0506138674, 6651166.0148049, 94.90379917831915], + [508781.21310905286, 6651165.509755666, 94.52276421231916], + [508781.0867709269, 6651165.902425601, 95.26550516331916], + [508781.25052198535, 6651165.393473004, 94.94907456331914], + [508781.1317510829, 6651165.7626233455, 95.62326300931916], + [508781.18555970816, 6651165.595381437, 95.97371922431915], + [508781.3017057211, 6651165.234389482, 95.37088342231915], + [508781.2480444133, 6651165.401173515, 96.31346425131915], + [508781.36672195, 6651165.032313361, 95.78123296531915], + [508781.3188897525, 6651165.180980011, 96.63913136131916], + [508781.4451946417, 6651164.78841338, 96.17301265931916], + [508781.39761894965, 6651164.936282787, 96.94750016931917], + [508781.512398069, 6651164.579539256, 96.45049451931915], + [508781.48360300495, 6651164.669036831, 97.23559852031914], + [508781.58620200417, 6651164.350150177, 96.71093519231916], + [508781.66596950544, 6651164.102225814, 96.95190483831915], + [508781.5760769439, 6651164.381619749, 97.50079624531915], + [508781.750956364, 6651163.838079233, 97.17132384431916], + [508781.6741623611, 6651164.076761703, 97.74088469231916], + [508781.8709502454, 6651163.465127764, 97.42753696731916], + [508781.77689487726, 6651163.757460066, 97.95413702731915], + [508781.88325473625, 6651163.426884332, 98.13934592931915], + [508781.9966316811, 6651163.074498882, 97.63981477631917], + [508781.9921985622, 6651163.088277403, 98.29583722131915], + [508782.12582286436, 6651162.672961397, 97.80692953331916], + [508782.1026903211, 6651162.744859362, 98.42345998031915], + [508782.2563927599, 6651162.267138755, 97.92908265531916], + [508782.21372972673, 6651162.399739189, 98.52255547431915], + [508782.3863552335, 6651161.863204031, 98.00775734831915], + [508782.36102053046, 6651161.941946502, 98.61172012631916], + [508782.51394470903, 6651161.466644794, 98.04550020731915], + [508782.50562193635, 6651161.492512698, 98.65449536731917], + [508783.038790479, 6651159.835378285, 98.04550020731915], + [508783.5747786779, 6651158.169480134, 98.04550020731915], + [508784.9126627614, 6651154.011219511, 91.64923286031915], + [508783.7023681535, 6651157.772920896, 98.00775734831915], + [508783.58310216723, 6651158.143610002, 98.65449536731917], + [508784.9126627614, 6651154.011219511, 91.77923286031915], + [508783.8323306271, 6651157.3689861735, 97.92908265531916], + [508783.72770357324, 6651157.694176198, 98.61172012631916], + [508785.09937079577, 6651153.430914629, 91.64923286031915], + [508783.96290052263, 6651156.9631635295, 97.80692953331916], + [508783.8749943768, 6651157.236383512, 98.52255547431915], + [508784.0920917058, 6651156.561626046, 97.63981477631917], + [508784.9126627614, 6651154.011219511, 93.47803651931915], + [508783.9860337824, 6651156.891263337, 98.42345998031915], + [508784.2177731415, 6651156.170997163, 97.42753696731916], + [508784.9069983784, 6651154.028824909, 93.88885183131916], + [508784.09652554145, 6651156.547845297, 98.29583722131915], + [508784.337767023, 6651155.798045695, 97.17132384431916], + [508784.8892850974, 6651154.083879335, 94.30997325931916], + [508784.2054693673, 6651156.209238368, 98.13934592931915], + [508784.8586093265, 6651154.17922231, 94.73606239431915], + [508784.44996170094, 6651155.449334833, 96.87388137431915], + [508785.09937079577, 6651153.430914629, 93.47803651931915], + [508784.52781917126, 6651155.207347013, 96.62617163431915], + [508784.8143445989, 6651154.31680095, 95.16096889831915], + [508784.5994878357, 6651154.984594543, 96.35976531931915], + [508784.75622571004, 6651154.497439536, 95.57793560031917], + [508784.6844059036, 6651154.720661768, 95.97988451731915], + [508784.3118292263, 6651155.878662633, 97.95413702731915], + [508785.0929511615, 6651153.450867412, 93.94362720631915], + [508784.4145617426, 6651155.559360998, 97.74088469231916], + [508785.07287610974, 6651153.513262427, 94.42089815831915], + [508784.5126471597, 6651155.25450295, 97.50079624531915], + [508785.0381102361, 6651153.6213178, 94.90379917831915], + [508784.60512109863, 6651154.967085869, 97.23559852031914], + [508785.0019531767, 6651153.7336971, 95.26550516331916], + [508784.691105154, 6651154.699839912, 96.94750016931917], + [508784.9569730207, 6651153.873499355, 95.62326300931916], + [508784.7698343512, 6651154.455142689, 96.63913136131916], + [508784.9031643955, 6651154.040741263, 95.97371922431915], + [508784.8406796903, 6651154.2349491855, 96.31346425131915], + [508791.0953147082, 6651169.42651253, 91.7464899322843], + [508791.2788742904, 6651168.845204068, 91.7464899322843], + [508791.2788742904, 6651168.845204068, 91.87648993228431], + [508791.0953147082, 6651169.42651253, 93.57529359128431], + [508791.10162608826, 6651169.40652524, 94.0408842782843], + [508791.2788735861, 6651168.845206299, 93.5752935922843], + [508791.121362615, 6651169.34402232, 94.51815523028431], + [508791.2802422889, 6651168.8408718025, 93.7791148762843], + [508791.2916071996, 6651168.804880661, 94.1956941642843], + [508791.15554223274, 6651169.235780076, 95.00105625028431], + [508791.3152972667, 6651168.729857411, 94.62002128428429], + [508791.19108957675, 6651169.123206427, 95.3627622352843], + [508791.352079306, 6651168.61337365, 95.04633163528429], + [508791.23531123373, 6651168.983162398, 95.72052008128429], + [508791.40239993186, 6651168.454015007, 95.46814049428431], + [508791.2882124857, 6651168.815631263, 96.07097629628431], + [508791.34964351315, 6651168.621087477, 96.4107213232843], + [508791.466319794, 6651168.251589417, 95.8784900372843], + [508791.41929418937, 6651168.400513171, 96.73638843328429], + [508791.54346920294, 6651168.007267636, 96.27026973128432], + [508791.4966957784, 6651168.155392769, 97.0447572412843], + [508791.6095393809, 6651167.798032286, 96.5477515912843], + [508791.68209876254, 6651167.5682465015, 96.8081922642843], + [508791.5812298872, 6651167.887684638, 97.3328555922843], + [508791.7605211467, 6651167.319893379, 97.0491619102843], + [508791.67214444076, 6651167.599770498, 97.5980533172843], + [508791.8440748743, 6651167.055289983, 97.2685809162843], + [508791.7685758464, 6651167.29438523, 97.8381417642843], + [508791.9620453025, 6651166.681693533, 97.5247940392843], + [508791.8695759873, 6651166.974531394, 98.0513940992843], + [508791.9741423031, 6651166.643383963, 98.23660300128431], + [508792.08560737595, 6651166.290389098, 97.7370718482843], + [508792.0812490126, 6651166.304191447, 98.39309429328429], + [508792.212620012, 6651165.8881571945, 97.9041866052843], + [508792.1898775523, 6651165.960179501, 98.52071705228431], + [508792.3409881112, 6651165.481632723, 98.0263397272843], + [508792.2990445036, 6651165.614462476, 98.61981254628431], + [508792.4687590315, 6651165.076999436, 98.1050144202843], + [508792.4438515468, 6651165.155878084, 98.70897719828432], + [508792.5941969695, 6651164.679754389, 98.1427572792843], + [508792.5860145435, 6651164.705667031, 98.7517524392843], + [508793.1101922808, 6651163.045666771, 98.1427572792843], + [508793.6371421265, 6651161.376887619, 98.1427572792843], + [508794.9524655103, 6651157.211435708, 91.7464899322843], + [508794.9524655103, 6651157.211435708, 91.87648993228431], + [508793.76258006453, 6651160.979642573, 98.1050144202843], + [508793.64532525715, 6651161.3509727465, 98.7517524392843], + [508793.8903509847, 6651160.575009286, 98.0263397272843], + [508793.7874882538, 6651160.900761694, 98.70897719828432], + [508795.13602509245, 6651156.630127247, 91.7464899322843], + [508794.018719084, 6651160.168484814, 97.9041866052843], + [508793.932295297, 6651160.442177301, 98.61981254628431], + [508794.1457317201, 6651159.766252911, 97.7370718482843], + [508794.9524655103, 6651157.211435708, 93.57529359128431], + [508794.04146224837, 6651160.096460278, 98.52071705228431], + [508794.9468966456, 6651157.229071553, 93.98610890328429], + [508794.2692937934, 6651159.3749484755, 97.5247940392843], + [508794.150090788, 6651159.752448331, 98.39309429328429], + [508794.92948206305, 6651157.284221189, 94.4072303312843], + [508794.3872642216, 6651159.001352027, 97.2685809162843], + [508795.13602509245, 6651156.630127247, 93.57529359128431], + [508794.89932357677, 6651157.379729051, 94.8333194662843], + [508794.49756696407, 6651158.652038105, 96.9711384462843], + [508794.2571974974, 6651159.413255814, 98.23660300128431], + [508794.85580528405, 6651157.51754562, 95.25822597028431], + [508794.57411152613, 6651158.4096317915, 96.72342870628431], + [508794.644571644, 6651158.186494092, 96.4570223912843], + [508794.79866645223, 6651157.6984966, 95.6751926722843], + [508794.7280577411, 6651157.922104873, 96.0771415892843], + [508795.1297137123, 6651156.650114537, 94.0408842782843], + [508794.36176381324, 6651159.082108383, 98.0513940992843], + [508794.4627639542, 6651158.762254546, 97.8381417642843], + [508795.10997718555, 6651156.712617458, 94.51815523028431], + [508794.5591953598, 6651158.456869281, 97.5980533172843], + [508795.07579756796, 6651156.820859702, 95.00105625028431], + [508794.6501099134, 6651158.16895514, 97.3328555922843], + [508795.0402502238, 6651156.93343335, 95.3627622352843], + [508794.73464402213, 6651157.901247009, 97.0447572412843], + [508794.99602856697, 6651157.073477378, 95.72052008128429], + [508794.8120456112, 6651157.656126606, 96.73638843328429], + [508794.94312731485, 6651157.241008515, 96.07097629628431], + [508794.8816962875, 6651157.435552301, 96.4107213232843], + [508797.66414135316, 6651171.488047247, 91.80494108921562], + [508797.8456544565, 6651170.906096526, 91.80494108921562], + [508797.8456544565, 6651170.906096526, 91.93494108921564], + [508797.66414135316, 6651171.488047247, 93.63374474821562], + [508797.6703823686, 6651171.468037874, 94.09933543521562], + [508797.8456537601, 6651170.90609876, 93.63374474921562], + [508797.6898988557, 6651171.405465897, 94.57660638721562], + [508797.8470072035, 6651170.901759473, 93.83756603321562], + [508797.85824540845, 6651170.865728568, 94.25414532121562], + [508797.72369740985, 6651171.2971040625, 95.05950740721562], + [508797.8816713584, 6651170.790622428, 94.67847244121562], + [508797.7588484418, 6651171.1844060365, 95.42121339221562], + [508797.9180433202, 6651170.674009969, 95.10478279221563], + [508797.802577078, 6651171.044207281, 95.77897123821562], + [508797.96780292894, 6651170.514475261, 95.52659165121563], + [508797.85488854174, 6651170.8764910465, 96.12942745321564], + [508797.9156346836, 6651170.68173232, 96.46917248021562], + [508798.0310101579, 6651170.311826021, 95.93694119421562], + [508797.9845088348, 6651170.460914312, 96.79483959021562], + [508798.1072994394, 6651170.0672343, 96.32872088821563], + [508798.0610474849, 6651170.215523088, 97.10320839821563], + [508798.1726330106, 6651169.857767776, 96.60620274821562], + [508798.2443834383, 6651169.627728113, 96.86664342121563], + [508798.1446391353, 6651169.947519179, 97.39130674921562], + [508798.32193150296, 6651169.3791005965, 97.10761306721562], + [508798.23454009584, 6651169.659286938, 97.65650447421564], + [508798.4045537023, 6651169.114204854, 97.32703207321562], + [508798.3298964019, 6651169.353564266, 97.89659292121564], + [508798.52120889554, 6651168.740195637, 97.58324519621564], + [508798.4297705071, 6651169.033357039, 98.10984525621564], + [508798.5331710284, 6651168.701843739, 98.29505415821562], + [508798.64339339343, 6651168.3484588675, 97.79552300521563], + [508798.63908362086, 6651168.362276467, 98.45154545021563], + [508798.76898998435, 6651167.945782559, 97.96263776221562], + [508798.7465010769, 6651168.017884438, 98.57916820921564], + [508798.8959269265, 6651167.538808937, 98.08479088421562], + [508798.8544509421, 6651167.671785448, 98.67826370321563], + [508799.0222733476, 6651167.133728593, 98.16346557721562], + [508798.9976435527, 6651167.212694388, 98.76742835521563], + [508799.1463127965, 6651166.736044649, 98.20120843621562], + [508799.13822159515, 6651166.7619859185, 98.81020359621563], + [508799.65655535174, 6651165.10015161, 98.20120843621562], + [508800.1776303111, 6651163.429528705, 98.20120843621562], + [508801.4782893478, 6651159.259474593, 91.80494108921562], + [508801.4782893478, 6651159.259474593, 91.93494108921564], + [508800.30166975997, 6651163.031844763, 98.16346557721562], + [508800.1857222093, 6651163.403585201, 98.81020359621563], + [508800.428016181, 6651162.626764416, 98.08479088421562], + [508801.65980245115, 6651158.677523874, 91.80494108921562], + [508800.32630025153, 6651162.952876732, 98.76742835521563], + [508800.5549531232, 6651162.219790796, 97.96263776221562], + [508800.46949286223, 6651162.493785672, 98.67826370321563], + [508801.4782893478, 6651159.259474593, 93.63374474821562], + [508800.68054971413, 6651161.817114487, 97.79552300521563], + [508800.5774427274, 6651162.147686682, 98.57916820921564], + [508801.47278256953, 6651159.277129922, 94.04456006021562], + [508800.802734212, 6651161.425377718, 97.58324519621564], + [508801.4555621396, 6651159.33234049, 94.46568148821562], + [508800.68486018345, 6651161.803294654, 98.45154545021563], + [508800.9193894053, 6651161.0513685, 97.32703207321562], + [508801.65980245115, 6651158.677523874, 93.63374474821562], + [508801.42573988595, 6651159.427953876, 94.89177062321563], + [508801.0284623986, 6651160.70166864, 97.02958960321564], + [508800.7907727759, 6651161.463727381, 98.29505415821562], + [508801.38270677225, 6651159.565922711, 95.31667712721563], + [508801.1041535766, 6651160.458994503, 96.78187986321562], + [508801.173828145, 6651160.235610271, 96.51547354821564], + [508801.32620497287, 6651159.747073614, 95.73364382921562], + [508801.2563834678, 6651159.970928941, 96.13559274621562], + [508801.6535614357, 6651158.697533246, 94.09933543521562], + [508800.8941732972, 6651161.1322140815, 98.10984525621564], + [508801.6340449486, 6651158.760105223, 94.57660638721562], + [508800.9940474024, 6651160.812006854, 97.89659292121564], + [508801.0894037084, 6651160.506284182, 97.65650447421564], + [508801.60024639446, 6651158.868467058, 95.05950740721562], + [508801.179304669, 6651160.21805194, 97.39130674921562], + [508801.5650953625, 6651158.981165084, 95.42121339221562], + [508801.2628963195, 6651159.950048032, 97.10320839821563], + [508801.5213667263, 6651159.12136384, 95.77897123821562], + [508801.33943496953, 6651159.704656808, 96.79483959021562], + [508801.46905526257, 6651159.289080073, 96.12942745321564], + [508801.4083091207, 6651159.4838388, 96.46917248021562], + [508810.1071119834, 6651175.323685916, 91.90542289905302], + [508810.2847485534, 6651174.740540226, 91.90542289905302], + [508810.2847485534, 6651174.740540226, 92.03542289905302], + [508810.1071119834, 6651175.323685916, 93.73422655805301], + [508810.1132197108, 6651175.303635455, 94.19981724505301], + [508810.2847478718, 6651174.740542462, 93.73422655905301], + [508810.1323193889, 6651175.240934993, 94.67708819705302], + [508810.28607240994, 6651174.736194265, 93.93804784305303], + [508810.2970706032, 6651174.700089375, 94.35462713105301], + [508810.1653961152, 6651175.132350651, 95.15998921705301], + [508810.31999625056, 6651174.624829014, 94.77895425105301], + [508810.1997964346, 6651175.019421211, 95.52169520205301], + [508810.3555914248, 6651174.507977105, 95.205264602053], + [508810.24259116844, 6651174.878934573, 95.87945304805302], + [508810.40428832907, 6651174.348114808, 95.62707346105303], + [508810.29378542834, 6651174.710873954, 96.22990926305302], + [508810.3532342289, 6651174.515715311, 96.56965429005301], + [508810.46614565584, 6651174.145049451, 96.03742300405301], + [508810.4206374507, 6651174.294443878, 96.895321400053], + [508810.5408056448, 6651173.899955488, 96.42920269805303], + [508810.4955414826, 6651174.048548771, 97.20369020805302], + [508810.60474390205, 6651173.690058848, 96.70668455805301], + [508810.67496197246, 6651173.459546825, 96.96712523105302], + [508810.5773478855, 6651173.779994546, 97.49178855905302], + [508810.750853861, 6651173.21040878, 97.20809487705303], + [508810.665328852, 6651173.491170452, 97.75698628405301], + [508810.8317115172, 6651172.944969103, 97.42751388305301], + [508810.75864865555, 6651173.184820014, 97.99707473105302], + [508810.9458753324, 6651172.5701919, 97.68372700605302], + [508810.85638977255, 6651172.863955278, 98.21032706605301], + [508810.95758199284, 6651172.531761251, 98.39553596805303], + [508811.0654503643, 6651172.177650744, 97.89600481505302], + [508811.0612326346, 6651172.191496716, 98.55202726005301], + [508811.1883646179, 6651171.774147584, 98.06311957205301], + [508811.1663560008, 6651171.846397517, 98.67965001905301], + [508811.3125905971, 6651171.36633829, 98.18527269405301], + [508811.27200040565, 6651171.499587852, 98.77874551305301], + [508811.4362386668, 6651170.960426157, 98.26394738705301], + [508811.41213488486, 6651171.039554101, 98.86791016505303], + [508811.55762903386, 6651170.561925614, 98.30169024605303], + [508811.54971063446, 6651170.587920152, 98.91068540605302], + [508812.056974457, 6651168.922673453, 98.30169024605303], + [508812.5669209389, 6651167.248620112, 98.30169024605303], + [508813.83980210137, 6651163.070003264, 91.90542289905302], + [508813.83980210137, 6651163.070003264, 92.03542289905302], + [508812.68831130594, 6651166.850119569, 98.26394738705301], + [508812.5748400202, 6651167.222623335, 98.91068540605302], + [508814.0174386713, 6651162.486857572, 91.90542289905302], + [508812.8119593757, 6651166.444207436, 98.18527269405301], + [508812.7124157698, 6651166.770989386, 98.86791016505303], + [508812.936185355, 6651166.036398141, 98.06311957205301], + [508812.852550249, 6651166.310955635, 98.77874551305301], + [508813.83980210137, 6651163.070003264, 93.73422655805301], + [508813.05909960857, 6651165.632894982, 97.89600481505302], + [508813.8344129301, 6651163.087694844, 94.145041870053], + [508812.9581946539, 6651165.9641459705, 98.67965001905301], + [508813.1786746405, 6651165.2403538255, 97.68372700605302], + [508813.81756027293, 6651163.143018781, 94.56616329805301], + [508813.0633180202, 6651165.619046772, 98.55202726005301], + [508813.2928384557, 6651164.865576622, 97.42751388305301], + [508814.0174386713, 6651162.486857572, 93.73422655805301], + [508813.7883749262, 6651163.238828498, 94.99225243305301], + [508813.39958200237, 6651164.515158691, 97.13007141305302], + [508813.74626086076, 6651163.377080636, 95.41715893705303], + [508813.1669686618, 6651165.278782236, 98.39553596805303], + [508813.47365666134, 6651164.271986252, 96.88236167305303], + [508813.6909657572, 6651163.558603514, 95.83412563905301], + [508814.0113309439, 6651162.506908032, 94.19981724505301], + [508813.54184320604, 6651164.048143325, 96.61595535805301], + [508813.62263541395, 6651163.782918502, 96.23607455605301], + [508813.26816088223, 6651164.946588212, 98.21032706605301], + [508813.9922312659, 6651162.569608494, 94.67708819705302], + [508813.36590199923, 6651164.625723476, 97.99707473105302], + [508813.9591545395, 6651162.678192838, 95.15998921705301], + [508813.45922180265, 6651164.319373035, 97.75698628405301], + [508813.9247542201, 6651162.791122275, 95.52169520205301], + [508813.5472027692, 6651164.03054894, 97.49178855905302], + [508813.8819594862, 6651162.931608914, 95.87945304805302], + [508813.6290091721, 6651163.761994716, 97.20369020805302], + [508813.8307652264, 6651163.099669534, 96.22990926305302], + [508813.703913204, 6651163.5160996085, 96.895321400053], + [508813.7713164258, 6651163.294828177, 96.56965429005301], + [508814.38548758865, 6651176.62161581, 91.93688853122363], + [508814.5617912562, 6651176.038065758, 91.93688853122363], + [508814.5617912562, 6651176.038065758, 92.06688853122364], + [508814.38548758865, 6651176.62161581, 93.76569219022363], + [508814.39154948655, 6651176.601551446, 94.23128287722363], + [508814.5617905797, 6651176.038067996, 93.76569219122364], + [508814.41050584946, 6651176.538807507, 94.70855382922363], + [508814.56310517923, 6651176.033716784, 93.96951347522364], + [508814.57402084715, 6651175.9975868575, 94.38609276322363], + [508814.4433343833, 6651176.430147869, 95.19145484922363], + [508814.5967744711, 6651175.92227431, 94.81041988322364], + [508814.47747657873, 6651176.317140124, 95.55316083422365], + [508814.6321025556, 6651175.805341372, 95.23673023422363], + [508814.51995020075, 6651176.176556069, 95.91091868022365], + [508814.6804340608, 6651175.645368226, 95.65853909322364], + [508814.5707603226, 6651176.008378915, 96.26137489522364], + [508814.62976304704, 6651175.813084945, 96.60111992222363], + [508814.741827239, 6651175.442162061, 96.06888863622363], + [508814.69666050636, 6651175.59166008, 96.92678703222364], + [508814.815927014, 6651175.196898146, 96.46066833022364], + [508814.77100249304, 6651175.345594465, 97.23515584022365], + [508814.8793855082, 6651174.9868559595, 96.73815019022364], + [508814.9490766948, 6651174.756184096, 96.99859086322364], + [508814.85219505866, 6651175.076854022, 97.52325419122363], + [508815.0243991258, 6651174.506873295, 97.23956050922365], + [508814.93951585685, 6651174.7878296515, 97.78845191622364], + [508815.1046500636, 6651174.241249558, 97.45897951522365], + [508815.0321354318, 6651174.4812667845, 98.02854036322364], + [508815.2179572465, 6651173.866212479, 97.71519263822364], + [508815.1291431448, 6651174.160179555, 98.24179269822363], + [508815.22957606567, 6651173.827755182, 98.42700160022363], + [508815.33663504286, 6651173.473399128, 97.92747044722366], + [508815.332448961, 6651173.487254701, 98.58349289222363], + [508815.4586270048, 6651173.069616174, 98.09458520422365], + [508815.4367835303, 6651173.141916205, 98.71111565122364], + [508815.58192085003, 6651172.661524097, 98.21673832622365], + [508815.5416352285, 6651172.794866056, 98.81021114522363], + [508815.7046411219, 6651172.255330498, 98.29541301922363], + [508815.68071820354, 6651172.33451331, 98.89937579722364], + [508815.825120632, 6651171.85655363, 98.33315587822364], + [508815.8172616486, 6651171.882566192, 98.94215103822366], + [508816.3207191986, 6651170.216164784, 98.33315587822364], + [508816.82683927874, 6651168.540950629, 98.33315587822364], + [508818.0901693312, 6651164.359436262, 91.93688853122363], + [508818.0901693312, 6651164.359436262, 92.06688853122364], + [508816.94731878873, 6651168.142173761, 98.29541301922363], + [508816.8346989389, 6651168.514935827, 98.94215103822366], + [508818.26647299883, 6651163.77588621, 91.93688853122363], + [508817.0700390607, 6651167.7359801615, 98.21673832622365], + [508816.9712423839, 6651168.062988708, 98.89937579722364], + [508817.1933329059, 6651167.327888085, 98.09458520422365], + [508818.0901693312, 6651164.359436262, 93.76569219022363], + [508817.110325359, 6651167.602635962, 98.81021114522363], + [508817.31532486784, 6651166.92410513, 97.92747044722366], + [508818.0848205978, 6651164.377140112, 94.17650750222364], + [508817.2151770572, 6651167.255585814, 98.71111565122364], + [508817.4340026641, 6651166.53129178, 97.71519263822364], + [508818.06809439516, 6651164.432502412, 94.59762893022365], + [508817.31951162644, 6651166.9102473175, 98.58349289222363], + [508818.26647299883, 6651163.77588621, 93.76569219022363], + [508817.5473098471, 6651166.1562547, 97.45897951522365], + [508818.03912804177, 6651164.528378562, 95.02371806522363], + [508817.65325243963, 6651165.805593786, 97.16153704522364], + [508817.99732998066, 6651164.666726568, 95.44862456922364], + [508817.4223845218, 6651166.569746836, 98.42700160022363], + [508817.7267712768, 6651165.562252725, 96.91382730522363], + [508818.2604111008, 6651163.795950573, 94.23128287722363], + [508817.942449786, 6651164.848375316, 95.86559127122365], + [508817.79444618133, 6651165.338254582, 96.64742099022364], + [508817.8746321619, 6651165.072845848, 96.26754018822363], + [508817.52281744266, 6651166.237322463, 98.24179269822363], + [508818.2414547379, 6651163.8586945115, 94.70855382922363], + [508817.6198251556, 6651165.9162352355, 98.02854036322364], + [508818.20862620405, 6651163.96735415, 95.19145484922363], + [508817.71244473057, 6651165.609672367, 97.78845191622364], + [508818.1744840087, 6651164.080361894, 95.55316083422365], + [508817.7997655288, 6651165.320647997, 97.52325419122363], + [508818.1320103867, 6651164.220945949, 95.91091868022365], + [508817.8809580943, 6651165.051907552, 97.23515584022365], + [508818.08120026474, 6651164.389123105, 96.26137489522364], + [508817.9553000812, 6651164.8058419395, 96.92678703222364], + [508818.0221975404, 6651164.584417073, 96.60111992222363], + [508829.1779160704, 6651181.02715162, 92.03358474417486], + [508829.349611245, 6651180.442229048, 92.03358474417486], + [508829.349611245, 6651180.442229048, 92.16358474417487], + [508829.1779160704, 6651181.02715162, 93.86238840317486], + [508829.18381951324, 6651181.007040066, 94.32797909017485], + [508829.3496105863, 6651180.442231293, 93.86238840417485], + [508829.202280366, 6651180.944148551, 94.80525004217485], + [508829.3508908227, 6651180.437869848, 94.06620968817485], + [508829.36152116035, 6651180.401654943, 94.48278897617486], + [508829.23425077775, 6651180.835233344, 95.28815106217486], + [508829.3836800155, 6651180.326165258, 94.90711609617485], + [508829.26750051265, 6651180.721959803, 95.64985704717485], + [508829.4180846409, 6651180.208957293, 95.33342644717486], + [508829.3088638946, 6651180.581045093, 96.00761489317485], + [508829.4651527839, 6651180.048607889, 95.75523530617485], + [508829.35834586434, 6651180.412472383, 96.35807110817487], + [508829.415806286, 6651180.216719079, 96.69781613517486], + [508829.52494117385, 6651179.844923778, 96.16558484917485], + [508829.48095507786, 6651179.9947734205, 97.02348324517484], + [508829.5971040165, 6651179.599082999, 96.55736454317487], + [508829.5533538009, 6651179.748129055, 97.33185205317486], + [508829.6589037362, 6651179.388546792, 96.83484640317485], + [508829.7267732288, 6651179.157332383, 97.09528707617486], + [508829.63242403185, 6651179.478756529, 97.61995040417486], + [508829.80012676766, 6651178.907435199, 97.33625672217485], + [508829.71746230655, 6651179.18905237, 97.88514812917485], + [508829.8782799847, 6651178.641186711, 97.55567572817485], + [508829.80766085035, 6651178.881768462, 98.12523657617486], + [508829.98862537235, 6651178.265267541, 97.81188885117486], + [508829.9021328284, 6651178.559926032, 98.33848891117486], + [508829.9999404811, 6651178.22671979, 98.52369781317485], + [508830.1042009882, 6651177.871530287, 98.02416666017486], + [508830.1001243285, 6651177.885418449, 98.68018910517485], + [508830.2230041391, 6651177.4667976275, 98.19128141717485], + [508830.20173164236, 6651177.53926771, 98.80781186417487], + [508830.3430751425, 6651177.057745712, 98.31343453917485], + [508830.30384256766, 6651177.191401295, 98.90690735817486], + [508830.46258756565, 6651176.650596741, 98.39210923217486], + [508830.4392899808, 6651176.729965792, 98.99607201017487], + [508830.57991779933, 6651176.250881943, 98.42985209117485], + [508830.57226424594, 6651176.276955688, 99.03884725117486], + [508831.15205576975, 6651181.605503514, 92.04507518621509], + [508831.32313591294, 6651181.020400761, 92.04507518621509], + [508831.32313591294, 6651181.020400761, 92.1750751862151], + [508831.06256165804, 6651174.606634879, 98.42985209117485], + [508831.15205576975, 6651181.605503514, 93.87387884521509], + [508831.1579380658, 6651181.585385765, 94.3394695322151], + [508831.32313525653, 6651181.020403006, 93.8738788462151], + [508831.17633278965, 6651181.522474877, 94.81674048421509], + [508831.324410907, 6651181.016040216, 94.07770013021509], + [508831.3350031655, 6651180.979814156, 94.49427941821509], + [508832.78575921635, 6651168.736131243, 92.03358474417486], + [508831.2081886798, 6651181.413526119, 95.29964150421509], + [508832.78575921635, 6651168.736131243, 92.16358474417487], + [508831.555452003, 6651172.927480595, 98.42985209117485], + [508831.3570826452, 6651180.904301217, 94.91860653821509], + [508831.2413193104, 6651181.300217684, 95.66134748921509], + [508831.6727822367, 6651172.5277657965, 98.39210923217486], + [508831.5631062154, 6651172.901404604, 99.03884725117486], + [508832.95745439094, 6651168.151208672, 92.03358474417486], + [508831.3913640293, 6651180.787057147, 95.34491688921509], + [508831.2825345241, 6651181.159259568, 96.01910533521509], + [508831.7922946598, 6651172.120616824, 98.31343453917485], + [508831.6960804805, 6651172.448394501, 98.99607201017487], + [508831.4382635689, 6651180.6266583465, 95.7667257482151], + [508831.91236566316, 6651171.711564909, 98.19128141717485], + [508831.33183924394, 6651180.990634928, 96.3695615502151], + [508832.78575921635, 6651168.736131243, 93.86238840317486], + [508831.83152789366, 6651171.986958997, 98.90690735817486], + [508832.0311688141, 6651171.30683225, 98.02416666017486], + [508832.78055029624, 6651168.753876733, 94.27320371517484], + [508831.3890938358, 6651180.794821326, 96.70930657721509], + [508831.49783779023, 6651180.422911493, 96.1770752912151], + [508831.93363881897, 6651171.639092581, 98.80781186417487], + [508832.7642613085, 6651168.809369245, 94.69432514317485], + [508832.1467444299, 6651170.913094997, 97.81188885117486], + [508832.95745439094, 6651168.151208672, 93.86238840317486], + [508832.73605212156, 6651168.905470898, 95.12041427817485], + [508832.25708981766, 6651170.537175825, 97.55567572817485], + [508832.0352461329, 6651171.292941844, 98.68018910517485], + [508831.4540092573, 6651180.572807295, 97.0349736872151], + [508832.69534664176, 6651169.044144301, 95.54532078217485], + [508832.3602631219, 6651170.18569015, 97.25823325817485], + [508832.9515509481, 6651168.171320227, 94.32797909017485], + [508831.56974213733, 6651180.176994984, 96.5688549852151], + [508832.43186021206, 6651169.941776749, 97.01052351817485], + [508832.6419009889, 6651169.22622029, 95.96228748417485], + [508832.1354299803, 6651170.951640502, 98.52369781317485], + [508832.4977661271, 6651169.717251758, 96.74411720317487], + [508832.5758560848, 6651169.451218779, 96.36423640117485], + [508832.93309009535, 6651168.23421174, 94.80525004217485], + [508832.23323763296, 6651170.618434261, 98.33848891117486], + [508831.52614863997, 6651180.326086953, 97.34334249521511], + [508831.6313204835, 6651179.966393922, 96.8463368452151], + [508832.327709611, 6651170.29659183, 98.12523657617486], + [508832.9011196836, 6651168.343126947, 95.28815106217486], + [508832.4179081549, 6651169.989307922, 97.88514812917485], + [508832.8678699487, 6651168.4564004885, 95.64985704717485], + [508832.5029464295, 6651169.699603763, 97.61995040417486], + [508832.8265065667, 6651168.597315199, 96.00761489317485], + [508832.5820166604, 6651169.430231238, 97.33185205317486], + [508832.777024597, 6651168.76588791, 96.35807110817487], + [508832.65441538347, 6651169.183586872, 97.02348324517484], + [508832.71956417535, 6651168.961641212, 96.69781613517486], + [508831.69894685986, 6651179.735108291, 97.10677751821511], + [508831.60493563255, 6651180.056631449, 97.63144084621509], + [508831.77203763823, 6651179.485134127, 97.3477471642151], + [508831.6896692904, 6651179.766838048, 97.8966385712151], + [508831.84991090157, 6651179.218803623, 97.56716617021509], + [508831.779544733, 6651179.459459483, 98.1367270182151], + [508831.9598610196, 6651178.842768651, 97.82337929321511], + [508831.87367830175, 6651179.137517911, 98.34997935321509], + [508831.9711355964, 6651178.804209027, 98.53518825521509], + [508832.0750226306, 6651178.44891011, 98.0356571022151], + [508832.07096057397, 6651178.462802549, 98.69167954721509], + [508832.1934002152, 6651178.044052775, 98.2027718592151], + [508832.172203919, 6651178.116545183, 98.81930230621509], + [508832.31304111076, 6651177.634874854, 98.3249249812151], + [508832.27394907153, 6651177.768571609, 98.91839780021509], + [508832.4321254269, 6651177.227600462, 98.40359967421509], + [508832.4089112967, 6651177.306993962, 99.0075624522151], + [508832.54903537047, 6651176.827762534, 98.44134253321509], + [508832.54140923294, 6651176.85384431, 99.05033769321511], + [508833.0299503446, 6651175.183008968, 98.44134253321509], + [508834.746975215, 6651169.310696958, 92.04507518621509], + [508834.746975215, 6651169.310696958, 92.1750751862151], + [508833.52107510075, 6651173.503337431, 98.44134253321509], + [508833.63798504433, 6651173.103499503, 98.40359967421509], + [508834.91805535817, 6651168.725594205, 92.04507518621509], + [508833.528701895, 6651173.477253408, 99.05033769321511], + [508833.75706936046, 6651172.696225111, 98.3249249812151], + [508833.66119983123, 6651173.024103756, 99.0075624522151], + [508833.87671025604, 6651172.28704719, 98.2027718592151], + [508834.746975215, 6651169.310696958, 93.87387884521509], + [508833.7961620564, 6651172.5625261115, 98.91839780021509], + [508833.9950878406, 6651171.882189856, 98.0356571022151], + [508834.7417849538, 6651169.328447915, 94.28469415721509], + [508833.89790720894, 6651172.214552538, 98.81930230621509], + [508834.72555431514, 6651169.383957521, 94.70581558521509], + [508834.1102494516, 6651171.488331314, 97.82337929321511], + [508834.91805535817, 6651168.725594205, 93.87387884521509], + [508834.69744617667, 6651169.480088778, 95.13190472021509], + [508834.22019956965, 6651171.112296342, 97.56716617021509], + [508833.9991505539, 6651171.868295171, 98.69167954721509], + [508834.6568865084, 6651169.618804897, 95.5568112242151], + [508834.3230032955, 6651170.760702394, 97.2697237002151], + [508834.91217306204, 6651168.745711955, 94.3394695322151], + [508834.39434391685, 6651170.516713856, 97.02201396021509], + [508834.60363230394, 6651169.800936973, 95.97377792621509], + [508834.0989755315, 6651171.526888691, 98.53518825521509], + [508834.46001374954, 6651170.292119702, 96.7556076452151], + [508834.53782398015, 6651170.026004774, 96.3757268432151], + [508834.8937783383, 6651168.808622842, 94.81674048421509], + [508834.19643282617, 6651171.193579809, 98.34997935321509], + [508834.2905663949, 6651170.871638236, 98.1367270182151], + [508834.8619224481, 6651168.9175716, 95.29964150421509], + [508834.38044183754, 6651170.564259672, 97.8966385712151], + [508834.8287918175, 6651169.030880034, 95.66134748921509], + [508834.46517549537, 6651170.27446627, 97.63144084621509], + [508834.7875766038, 6651169.171838152, 96.01910533521509], + [508834.5439624879, 6651170.005010765, 97.34334249521511], + [508834.738271884, 6651169.340462791, 96.3695615502151], + [508834.61610187055, 6651169.758290425, 97.0349736872151], + [508834.68101729214, 6651169.536276395, 96.70930657721509], + [508847.96250603726, 6651186.439312099, 92.12950105420167], + [508848.12834898476, 6651185.8527034, 92.12950105420167], + [508848.12834898476, 6651185.8527034, 92.25950105420169], + [508847.96250603726, 6651186.439312099, 93.95830471320168], + [508847.9682082613, 6651186.419142568, 94.42389540020167], + [508848.3057533731, 6651186.536319407, 92.13097546765042], + [508848.1283483484, 6651185.852705651, 93.95830471420167], + [508848.129584948, 6651185.848331632, 94.16212599820167], + [508847.9860398761, 6651186.35606976, 94.90116635220167], + [508848.1398529508, 6651185.8120123325, 94.57870528620168], + [508848.4714893839, 6651185.949680488, 92.13097546765042], + [508848.4714893839, 6651185.949680488, 92.26097546765041], + [508848.016920577, 6651186.246840589, 95.38406737220168], + [508848.1612565217, 6651185.736305038, 95.00303240620167], + [508848.0490369952, 6651186.13324052, 95.74577335720167], + [508848.3057533731, 6651186.536319407, 93.9597791266504], + [508848.194488466, 6651185.618759204, 95.42934275720168], + [508848.08899050707, 6651185.991919602, 96.10353120320167], + [508848.31145192037, 6651186.516148837, 94.4253698136504], + [508848.2399522922, 6651185.457947567, 95.85115161620168], + [508848.1367858848, 6651185.822860955, 96.45398741820169], + [508848.471488748, 6651185.949682738, 93.9597791276504], + [508848.4727245503, 6651185.945308494, 94.16360041165042], + [508848.32927203726, 6651186.45307278, 94.90264076565042], + [508848.2977027959, 6651185.253676308, 96.26150115920167], + [508848.1922877689, 6651185.626543365, 96.79373244520168], + [508848.4829859321, 6651185.908987324, 94.5801796996504], + [508848.3601328261, 6651186.343837982, 95.3855417856504], + [508848.50437570194, 6651185.833276128, 95.0045068196504], + [508848.25521596527, 6651185.403957913, 97.11939955520167], + [508848.36740596924, 6651185.007126857, 96.6532808532017], + [508848.3922285353, 6651186.230232061, 95.7472477706504], + [508848.5375862181, 6651185.715724237, 95.4308171706504], + [508848.32514697907, 6651185.15660256, 97.42776836320168], + [508848.42709924665, 6651184.795983747, 96.93076271320167], + [508848.4321562849, 6651186.088903861, 96.1050056166504], + [508848.5830207288, 6651185.554904317, 95.85262602965042], + [508848.4926554087, 6651184.5641028285, 97.19120338620168], + [508848.47992084373, 6651185.919836504, 96.45546183165041], + [508848.4015221026, 6651184.886453527, 97.71586671420168], + [508848.56350869354, 6651184.31348528, 97.43217303220167], + [508848.6407339946, 6651185.350622532, 96.2629755726504], + [508848.53538693994, 6651185.7235088, 96.7952068586504], + [508848.48366184905, 6651184.595914254, 97.98106443920167], + [508848.6389980594, 6651184.046469292, 97.65159203820167], + [508848.59827455983, 6651185.500911881, 97.1208739686504], + [508848.7103922229, 6651185.10406038, 96.65475526665043], + [508848.5707859771, 6651184.287744553, 98.22115288620168], + [508848.66816048155, 6651185.253543783, 97.42924277665041], + [508848.7700470097, 6651184.892906391, 96.9322371266504], + [508848.74558232643, 6651183.669466475, 97.90780516120168], + [508848.6620378794, 6651183.964974364, 98.43440522120169], + [508848.8355609006, 6651184.661013527, 97.19267779965041], + [508848.7444863579, 6651184.983380833, 97.71734112765041], + [508848.85721854947, 6651183.274594216, 98.12008297020168], + [508848.7565117599, 6651183.6308076065, 98.61961412320167], + [508848.90636849875, 6651184.410383065, 97.43364744565042], + [508848.82657314016, 6651184.69282659, 97.9825388526504], + [508848.85328084254, 6651183.288522412, 98.77610541520167], + [508848.97197229695, 6651182.868694855, 98.28719772720167], + [508848.98180918855, 6651184.14335332, 97.6530664516504], + [508848.91364108986, 6651184.384641014, 98.22262729965041], + [508848.9514248729, 6651182.941373844, 98.90372817420169], + [508849.0879506822, 6651182.458463787, 98.40935084920167], + [508849.08832472935, 6651183.766331081, 97.90927957465041], + [508849.0500553491, 6651182.592504652, 99.00282366820169], + [508849.00483415235, 6651184.061854195, 98.4358796346504], + [508849.2033895264, 6651182.050141148, 98.48802554220168], + [508849.1998889686, 6651183.371438478, 98.12155738365041], + [508849.09924711543, 6651183.727670222, 98.62108853665042], + [508849.1808860394, 6651182.129738993, 99.0919883202017], + [508849.3167205611, 6651181.649274113, 98.52576840120167], + [508849.1959538008, 6651183.385367393, 98.7775798286504], + [508849.309327879, 6651181.675423019, 99.13476356120168], + [508849.3145687221, 6651182.965518205, 98.2886721406504], + [508849.2940345472, 6651183.038200939, 98.90520258765041], + [508849.43047232373, 6651182.555266002, 98.4108252626504], + [508849.39260142576, 6651182.689313772, 99.0042980816504], + [508849.5458367322, 6651182.146922327, 98.48949995565042], + [508849.78291351214, 6651180.000287262, 98.52576840120167], + [508849.52334775554, 6651182.226524273, 99.09346273365043], + [508849.6590946902, 6651181.746034639, 98.52724281465042], + [508849.65170677495, 6651181.772184892, 99.13623797465041], + [508851.44737591106, 6651174.112861025, 92.12950105420167], + [508851.44737591106, 6651174.112861025, 92.25950105420169], + [508850.25900369807, 6651178.316292565, 98.52576840120167], + [508850.1249870369, 6651180.096962831, 98.52724281465042], + [508851.61321885866, 6651173.526252328, 92.12950105420167], + [508850.37233473273, 6651177.91542553, 98.48802554220168], + [508850.2663970168, 6651178.290141408, 99.13476356120168], + [508850.48777357704, 6651177.50710289, 98.40935084920167], + [508850.39483885636, 6651177.835825434, 99.0919883202017], + [508851.44737591106, 6651174.112861025, 93.95830471320168], + [508850.6037519623, 6651177.096871823, 98.28719772720167], + [508851.442344537, 6651174.130657669, 94.36912002520167], + [508850.52566954674, 6651177.373059775, 99.00282366820169], + [508850.7185057098, 6651176.690972462, 98.12008297020168], + [508851.7883761792, 6651174.209233276, 92.13097546765042], + [508851.4266107591, 6651174.186310148, 94.79024145320167], + [508851.61321885866, 6651173.526252328, 93.95830471320168], + [508851.7883761792, 6651174.209233276, 92.26097546765041], + [508850.6243000229, 6651177.024190582, 98.90372817420169], + [508850.8301419328, 6651176.296100203, 97.90780516120168], + [508851.3993630818, 6651174.282688828, 95.21633058820167], + [508850.93672619987, 6651175.919097387, 97.65159203820167], + [508850.60077023663, 6651178.412881376, 98.52724281465042], + [508850.7224440532, 6651176.677042015, 98.77610541520167], + [508851.3600450476, 6651174.421761977, 95.64123709220168], + [508851.6075166345, 6651173.546421858, 94.42389540020167], + [508851.0363828438, 6651175.566598503, 97.35414956820169], + [508851.3084210889, 6651174.604362826, 96.05820379420167], + [508851.1055395483, 6651175.321981983, 97.10643982820167], + [508851.24462732434, 6651174.8300099075, 96.46015271120167], + [508851.1691990614, 6651175.096809767, 96.84003351320169], + [508851.95411219, 6651173.622594357, 92.13097546765042], + [508850.8192131359, 6651176.334756819, 98.61961412320167], + [508851.58968501963, 6651173.609494666, 94.90116635220167], + [508850.71402819466, 6651178.0119936885, 98.48949995565042], + [508850.9136870164, 6651176.000590063, 98.43440522120169], + [508850.6081587881, 6651178.386728871, 99.13623797465041], + [508851.55880431883, 6651173.718723837, 95.38406737220168], + [508851.0049389187, 6651175.677819872, 98.22115288620168], + [508851.5266879006, 6651173.832323905, 95.74577335720167], + [508850.82939260313, 6651177.603650013, 98.4108252626504], + [508851.09206304676, 6651175.369650174, 97.98106443920167], + [508851.48673438875, 6651173.973644823, 96.10353120320167], + [508851.1742027932, 6651175.079110898, 97.71586671420168], + [508851.43893901113, 6651174.14270347, 96.45398741820169], + [508850.7365178075, 6651177.932389491, 99.09346273365043], + [508851.25057791674, 6651174.808961867, 97.42776836320168], + [508851.38343712705, 6651174.339021062, 96.79373244520168], + [508851.3205089306, 6651174.561606512, 97.11939955520167], + [508851.7883761792, 6651174.209233276, 93.9597791266504], + [508850.9452962049, 6651177.193397809, 98.2886721406504], + [508851.78334804927, 6651174.227030836, 94.3705944386504], + [508850.8672641373, 6651177.46959999, 99.0042980816504], + [508851.0599759584, 6651176.787477536, 98.12155738365041], + [508851.7676244167, 6651174.282686182, 94.7917158666504], + [508851.95411219, 6651173.622594357, 93.9597791266504], + [508850.9658310159, 6651177.120712824, 98.90520258765041], + [508851.1715401975, 6651176.392584933, 97.90927957465041], + [508851.7403943089, 6651174.3790698275, 95.2178050016504], + [508851.2780557383, 6651176.0155626945, 97.6530664516504], + [508851.06391176226, 6651176.773546371, 98.7775798286504], + [508851.7011016271, 6651174.5181501405, 95.64271150565042], + [508851.9484136427, 6651173.642764926, 94.4253698136504], + [508851.3776481229, 6651175.6630456485, 97.35562398165041], + [508851.6495109559, 6651174.700760398, 96.0596782076504], + [508851.4467602348, 6651175.418416529, 97.10791424165042], + [508851.585758326, 6651174.926419106, 96.4616271246504], + [508851.5103786998, 6651175.1932327105, 96.84150792665041], + [508851.16061844764, 6651176.431243542, 98.62108853665042], + [508851.9305935258, 6651173.705840983, 94.90264076565042], + [508851.2550314107, 6651176.097059567, 98.4358796346504], + [508851.8997327371, 6651173.815075781, 95.3855417856504], + [508851.3462244732, 6651175.774272749, 98.22262729965041], + [508851.86763702775, 6651173.928681702, 95.7472477706504], + [508851.43329242297, 6651175.466087173, 97.9825388526504], + [508851.8277092782, 6651174.070009902, 96.1050056166504], + [508851.5153792052, 6651175.17553293, 97.71734112765041], + [508851.77994471934, 6651174.239077259, 96.45546183165041], + [508851.59170508146, 6651174.905369979, 97.42924277665041], + [508851.72447862325, 6651174.435404963, 96.7952068586504], + [508851.66159100324, 6651174.658001883, 97.1208739686504], + [508864.81549509364, 6651191.122655294, 92.19016613550315], + [508864.97608759283, 6651190.534587528, 92.19016613550315], + [508864.97608759283, 6651190.534587528, 92.32016613550316], + [508864.81549509364, 6651191.122655294, 94.01896979450315], + [508864.8210167901, 6651191.102435596, 94.48456048150315], + [508864.97608697665, 6651190.534589784, 94.01896979550315], + [508864.9772844266, 6651190.530204887, 94.22279107950317], + [508864.8382838711, 6651191.039205907, 94.96183143350316], + [508864.98722735303, 6651190.493795251, 94.63937036750315], + [508864.86818691494, 6651190.929705051, 95.44473245350315], + [508865.0079533049, 6651190.417899649, 95.06369748750315], + [508864.89928655425, 6651190.815822425, 95.80643843850316], + [508865.04013315385, 6651190.300061445, 95.49000783850315], + [508864.9379751715, 6651190.674150002, 96.16419628450316], + [508865.0841576334, 6651190.138849821, 95.91181669750317], + [508864.98425738775, 6651190.504670856, 96.51465249950316], + [508865.14007980475, 6651189.934070479, 96.32216624050315], + [508865.03800212883, 6651190.307864966, 96.85439752650315], + [508865.09893807146, 6651190.084725879, 97.18006463650315], + [508865.2075762342, 6651189.686907787, 96.71394593450316], + [508865.2653796726, 6651189.475239502, 96.99142779450315], + [508865.1666551281, 6651189.83675528, 97.48843344450316], + [508865.3288603816, 6651189.242781829, 97.25186846750316], + [508865.24061227933, 6651189.565934308, 97.77653179550315], + [508865.397470511, 6651188.991540921, 97.49283811350317], + [508865.3201515505, 6651189.274672377, 98.04172952050315], + [508865.470569947, 6651188.723860784, 97.71225711950315], + [508865.4045174018, 6651188.965736169, 98.28181796750316], + [508865.5737798457, 6651188.345920254, 97.96847024250314], + [508865.4928803457, 6651188.642163156, 98.49507030250315], + [508865.68188175966, 6651187.950065832, 98.18074805150316], + [508865.58436326246, 6651188.307165228, 98.68027920450317], + [508865.6780687173, 6651187.96402867, 98.83677049650315], + [508865.79300249997, 6651187.543156879, 98.34786280850315], + [508865.7731055902, 6651187.616016641, 98.96439325550315], + [508865.90530910704, 6651187.131905446, 98.47001593050315], + [508865.86861350836, 6651187.2662797095, 99.06348874950315], + [508866.0170932545, 6651186.722567189, 98.54869062350315], + [508865.99530220893, 6651186.802363017, 99.15265340150316], + [508866.1268363239, 6651186.32070308, 98.58643348250317], + [508866.1196776879, 6651186.346917026, 99.19542864250316], + [508866.5782699979, 6651184.667614714, 98.58643348250317], + [508868.1900369162, 6651178.7655447265, 92.19016613550315], + [508868.1900369162, 6651178.7655447265, 92.32016613550316], + [508868.35062941536, 6651178.17747696, 92.19016613550315], + [508867.0392875687, 6651182.979431431, 98.58643348250317], + [508867.14903063804, 6651182.577567323, 98.54869062350315], + [508867.0464468211, 6651182.953215227, 99.19542864250316], + [508867.2608147855, 6651182.168229065, 98.47001593050315], + [508868.1900369162, 6651178.7655447265, 94.01896979450315], + [508867.1708223001, 6651182.4977692375, 99.15265340150316], + [508867.37312139256, 6651181.756977631, 98.34786280850315], + [508868.1851648311, 6651178.783385635, 94.42978510650315], + [508867.29751100065, 6651182.033852544, 99.06348874950315], + [508867.48424213286, 6651181.35006868, 98.18074805150316], + [508868.1699291714, 6651178.839176537, 94.85090653450317], + [508868.35062941536, 6651178.17747696, 94.01896979450315], + [508868.14354413265, 6651178.935794939, 95.27699566950315], + [508867.5923440468, 6651180.954214257, 97.96847024250314], + [508867.3930189188, 6651181.684115612, 98.96439325550315], + [508868.3451077189, 6651178.197696658, 94.48456048150315], + [508868.10547087435, 6651179.075214003, 95.70190217350317], + [508867.69555394555, 6651180.576273727, 97.71225711950315], + [508867.4880557917, 6651181.336103583, 98.83677049650315], + [508868.05548128684, 6651179.258269035, 96.11886887550315], + [508867.7920555439, 6651180.2228980735, 97.41481464950316], + [508867.85902280535, 6651179.977673122, 97.16710490950317], + [508867.9937071792, 6651179.484477368, 96.52081779250315], + [508867.9206669118, 6651179.751940836, 96.90069859450315], + [508867.48864439264, 6651191.850619145, 92.19759506947767], + [508868.3278406379, 6651178.260926347, 94.96183143350316], + [508867.5817612465, 6651180.992967024, 98.68027920450317], + [508868.29793759406, 6651178.370427203, 95.44473245350315], + [508867.67324416334, 6651180.657969097, 98.49507030250315], + [508868.26683795475, 6651178.484309829, 95.80643843850316], + [508867.76160710707, 6651180.334396084, 98.28181796750316], + [508868.2281493375, 6651178.625982252, 96.16419628450316], + [508867.8459729585, 6651180.025459875, 98.04172952050315], + [508867.64840408805, 6651191.2623245865, 92.19759506947767], + [508868.18186712125, 6651178.795461397, 96.51465249950316], + [508867.9255122297, 6651179.734197945, 97.77653179550315], + [508867.64840408805, 6651191.2623245865, 92.3275950694777], + [508868.1281223802, 6651178.992267287, 96.85439752650315], + [508867.9994693809, 6651179.463376973, 97.48843344450316], + [508868.06718643755, 6651179.215406375, 97.18006463650315], + [508867.48864439264, 6651191.850619145, 94.02639872847767], + [508867.49413745455, 6651191.830391649, 94.49198941547768], + [508867.648403475, 6651191.262326844, 94.02639872947768], + [508867.6495947152, 6651191.257940255, 94.23022001347768], + [508867.5113149915, 6651191.767137576, 94.96926036747767], + [508867.65948607936, 6651191.221516577, 94.64679930147767], + [508867.5410629635, 6651191.657594491, 95.45216138747767], + [508867.6801045502, 6651191.145591706, 95.07112642147767], + [508867.57200132584, 6651191.543667945, 95.81386737247767], + [508867.7121175203, 6651191.027708057, 95.49743677247768], + [508867.6104893109, 6651191.401940885, 96.17162521847767], + [508867.7559136969, 6651190.866434261, 95.91924563147768], + [508867.6565315158, 6651191.232396378, 96.5220814334777], + [508867.81154586584, 6651190.661575945, 96.32959517447769], + [508867.70999754634, 6651191.035514588, 96.86182646047767], + [508867.7706174862, 6651190.812289446, 97.18749357047767], + [508867.8786922711, 6651190.414317933, 96.72137486847768], + [508867.9361959512, 6651190.202568016, 96.99885672847768], + [508867.8379833744, 6651190.564223215, 97.49586237847768], + [508867.9993474607, 6651189.970020695, 97.25929740147768], + [508867.9115569972, 6651190.2932978, 97.78396072947767], + [508868.06760179036, 6651189.718682893, 97.50026704747768], + [508867.99068379204, 6651190.001923541, 98.04915845447769], + [508868.1403221459, 6651189.450899523, 97.71968605347767], + [508868.07461213734, 6651189.69286819, 98.2892469014777], + [508868.24299681664, 6651189.072813236, 97.97589917647767], + [508868.1625168468, 6651189.369170387, 98.50249923647769], + [508868.35053813364, 6651188.67680615, 98.18817698547767], + [508868.2535253497, 6651189.0340432655, 98.68770813847767], + [508868.34674486506, 6651188.690774374, 98.84419943047769], + [508868.46108262177, 6651188.26974027, 98.35529174247768], + [508868.44128889375, 6651188.342628133, 98.97182218947768], + [508868.5728068271, 6651187.858330235, 98.47744486447768], + [508868.53630152514, 6651187.99275632, 99.07091768347767], + [508868.6840112821, 6651187.448834113, 98.55611955747767], + [508868.662333241, 6651187.528660715, 99.16008233547768], + [508868.79318524373, 6651187.046815022, 98.59386241647768], + [508868.786063731, 6651187.073039079, 99.20285757647768], + [508869.2422778641, 6651185.393089131, 98.59386241647768], + [508870.8456864497, 6651179.488742964, 92.19759506947767], + [508870.8456864497, 6651179.488742964, 92.3275950694777], + [508871.0054461452, 6651178.900448406, 92.19759506947767], + [508869.7009046808, 6651183.704254787, 98.59386241647768], + [508869.8100786425, 6651183.302235696, 98.55611955747767], + [508869.70802680677, 6651183.678028474, 99.20285757647768], + [508869.9212830975, 6651182.892739574, 98.47744486447768], + [508870.8456864497, 6651179.488742964, 94.02639872847767], + [508869.83175729687, 6651183.222406836, 99.16008233547768], + [508870.0330073028, 6651182.481329539, 98.35529174247768], + [508870.84083963046, 6651179.506590754, 94.43721404047767], + [508869.95778901275, 6651182.758311231, 99.07091768347767], + [508870.8256829802, 6651179.562403172, 94.85833546847768], + [508870.1435517909, 6651182.074263661, 98.18817698547767], + [508871.0054461452, 6651178.900448406, 94.02639872847767], + [508870.7994347695, 6651179.659058836, 95.28442460347769], + [508870.2510931079, 6651181.678256574, 97.97589917647767], + [508870.0528016441, 6651182.40843942, 98.97182218947768], + [508870.9999530832, 6651178.920675902, 94.49198941547768], + [508870.76155895216, 6651179.798531668, 95.70933110747768], + [508870.3537677787, 6651181.300170287, 97.71968605347767], + [508870.1473456728, 6651182.060293177, 98.84419943047769], + [508870.71182860166, 6651179.981657297, 96.12629780947768], + [508870.44976893713, 6651180.9466583505, 97.4222435834777], + [508870.51638891845, 6651180.701338827, 97.17453384347768], + [508870.65037484345, 6651180.207952868, 96.52824672647768], + [508870.57771334966, 6651180.475519486, 96.90812752847769], + [508870.98277554626, 6651178.983929976, 94.96926036747767], + [508870.24056518805, 6651181.717024285, 98.68770813847767], + [508870.9530275743, 6651179.093473061, 95.45216138747767], + [508870.3315736909, 6651181.381897164, 98.50249923647769], + [508870.922089212, 6651179.207399606, 95.81386737247767], + [508870.41947840044, 6651181.058199363, 98.2892469014777], + [508870.883601227, 6651179.349126668, 96.17162521847767], + [508870.50340674573, 6651180.74914401, 98.04915845447769], + [508870.83755902195, 6651179.5186711745, 96.5220814334777], + [508870.58253354055, 6651180.4577697525, 97.78396072947767], + [508870.7840929915, 6651179.715552963, 96.86182646047767], + [508870.65610716335, 6651180.186844336, 97.49586237847768], + [508870.72347305156, 6651179.938778105, 97.18749357047767], + [508881.7096761964, 6651195.6551588485, 92.22707043011843], + [508881.8650054141, 6651195.06567901, 92.22707043011843], + [508881.8650054141, 6651195.06567901, 92.35707043011844], + [508881.7096761964, 6651195.6551588485, 94.05587408911843], + [508881.715016924, 6651195.6348906, 94.52146477611844], + [508881.8650048182, 6651195.065681271, 94.05587409011844], + [508881.86616302264, 6651195.061285845, 94.25969537411844], + [508881.73171809124, 6651195.571509084, 94.99873572811843], + [508881.87578007823, 6651195.02478878, 94.67627466211843], + [508881.7606410884, 6651195.461745293, 95.48163674811843], + [508881.8958267548, 6651194.948710939, 95.10060178211845], + [508881.7907214638, 6651195.347589212, 95.84334273311845], + [508881.92695193674, 6651194.83058978, 95.52691213311843], + [508881.82814209466, 6651195.205576601, 96.20110057911843], + [508881.9695335517, 6651194.668991054, 95.94872099211844], + [508881.872907451, 6651195.035690501, 96.55155679411844], + [508882.0236229219, 6651194.463719993, 96.35907053511843], + [508881.9248907542, 6651194.83841204, 96.89130182111843], + [508881.98382957355, 6651194.614737148, 97.21696893111844], + [508882.0889072137, 6651194.215963812, 96.75085022911844], + [508882.1448161939, 6651194.003787266, 97.02833208911844], + [508882.04932726175, 6651194.36617112, 97.52533773911846], + [508882.2062163772, 6651193.770771414, 97.28877276211844], + [508882.1208605309, 6651194.09469985, 97.81343609011843], + [508882.27257786837, 6651193.518927223, 97.52974240811844], + [508882.1977929706, 6651193.802738537, 98.07863381511844], + [508882.343281533, 6651193.25060433, 97.74916141411845], + [508882.27939380344, 6651193.493060509, 98.31872226211844], + [508882.4431088159, 6651192.871756284, 98.00537453711844], + [508882.3648607275, 6651193.168710529, 98.53197459711843], + [508882.54766778223, 6651192.4749513315, 98.21765234611843], + [508882.45334537025, 6651192.8329082, 98.71718349911843], + [508882.5439797091, 6651192.488947699, 98.87367479111843], + [508882.65514663554, 6651192.067065306, 98.38476710311845], + [508882.6359018299, 6651192.14010002, 99.00129755011844], + [508882.76377248985, 6651191.654826372, 98.50692022511845], + [508882.728279558, 6651191.789523297, 99.10039304411843], + [508882.8718930078, 6651191.244505207, 98.58559491811843], + [508882.8508161451, 6651191.324492642, 99.18955769611844], + [508882.97803934215, 6651190.841676137, 98.62333777711844], + [508882.97111532424, 6651190.86795303, 99.23233293711846], + [508883.4146776646, 6651189.184618359, 98.62333777711844], + [508884.97362030385, 6651183.268376259, 92.22707043011843], + [508884.97362030385, 6651183.268376259, 92.35707043011844], + [508885.1289495216, 6651182.678896419, 92.22707043011843], + [508883.8605857796, 6651187.492381393, 98.62333777711844], + [508883.966732114, 6651187.089552323, 98.58559491811843], + [508883.8675103937, 6651187.466102239, 99.23233293711846], + [508884.97362030385, 6651183.268376259, 94.05587408911843], + [508884.0748526319, 6651186.679231158, 98.50692022511845], + [508884.9689078972, 6651183.286260009, 94.46668940111844], + [508883.9878095729, 6651187.009562627, 99.18955769611844], + [508884.1834784862, 6651186.266992224, 98.38476710311845], + [508884.95417157316, 6651183.342184876, 94.88781082911845], + [508885.1289495216, 6651182.678896419, 94.05587408911843], + [508884.2909573395, 6651185.859106199, 98.21765234611843], + [508884.1103461601, 6651186.544531973, 99.10039304411843], + [508884.92865128146, 6651183.43903528, 95.31389996411843], + [508885.12360879395, 6651182.699164669, 94.52146477611844], + [508884.39551630587, 6651185.462301247, 98.00537453711844], + [508884.20272388804, 6651186.193955248, 99.00129755011844], + [508884.89182584157, 6651183.578789118, 95.73880646811844], + [508884.49534358876, 6651185.083453201, 97.74916141411845], + [508884.8434746199, 6651183.762283704, 96.15577317011845], + [508884.5886824299, 6651184.729229019, 97.45171894411844], + [508884.2946460089, 6651185.845107568, 98.87367479111843], + [508885.10690762685, 6651182.7625461845, 94.99873572811843], + [508884.7837251057, 6651183.98903521, 96.55772208711844], + [508884.65345489676, 6651184.48341523, 97.20400920411844], + [508884.71307867044, 6651184.257140915, 96.93760288911844], + [508884.38528034784, 6651185.501147067, 98.71718349911843], + [508885.07798462966, 6651182.872309975, 95.48163674811843], + [508884.47376499046, 6651185.16534474, 98.53197459711843], + [508885.04790425417, 6651182.986466058, 95.84334273311845], + [508884.55923191446, 6651184.8409947585, 98.31872226211844], + [508885.01048362325, 6651183.128478666, 96.20110057911843], + [508884.6408327474, 6651184.531316731, 98.07863381511844], + [508884.9657182671, 6651183.298364766, 96.55155679411844], + [508884.7177651871, 6651184.239355418, 97.81343609011843], + [508884.91373496375, 6651183.495643229, 96.89130182111843], + [508884.7892984562, 6651183.967884148, 97.52533773911846], + [508884.8547961444, 6651183.71931812, 97.21696893111844], + [508886.72460393567, 6651196.969500862, 92.23344354966014], + [508886.8783707826, 6651196.379611547, 92.23344354966014], + [508886.8783707826, 6651196.379611547, 92.36344354966016], + [508886.72460393567, 6651196.969500862, 94.06224720866015], + [508886.72989094385, 6651196.949218535, 94.52783789566014], + [508886.87837019254, 6651196.37961381, 94.06224720966014], + [508886.8795167473, 6651196.375215331, 94.26606849366014], + [508886.74642412324, 6651196.88579299, 95.00510884766014], + [508886.8890370702, 6651196.338692915, 94.68264778166015], + [508886.77505619987, 6651196.775952955, 95.48800986766015], + [508886.90888210834, 6651196.262562226, 95.10697490166014], + [508886.8048340134, 6651196.661717575, 95.84971585266014], + [508886.9396942192, 6651196.144359015, 95.53328525266015], + [508886.8418782509, 6651196.519606319, 96.20747369866014], + [508886.98184752936, 6651195.982648036, 95.95509411166015], + [508886.8861933371, 6651196.349602209, 96.55792991366016], + [508887.0353928443, 6651195.777234387, 96.36544365466014], + [508886.93765376904, 6651196.152186709, 96.89767494066015], + [508886.9959997554, 6651195.928356444, 97.22334205066014], + [508887.1000204775, 6651195.529306104, 96.75722334866015], + [508887.15536710015, 6651195.316982173, 97.03470520866014], + [508887.0608386385, 6651195.679617752, 97.53171085866015], + [508887.21614969283, 6651195.083804459, 97.29514588166015], + [508887.13165239384, 6651195.407957908, 97.81980920966014], + [508887.28184369043, 6651194.831785328, 97.53611552766014], + [508887.2078110126, 6651195.115793789, 98.08500693466014], + [508887.35183618596, 6651194.563276047, 97.75553453366014], + [508887.28859106783, 6651194.805900645, 98.32509538166015], + [508887.4506593612, 6651194.184164838, 98.01174765666013], + [508887.37319832726, 6651194.48132536, 98.53834771666016], + [508887.55416662677, 6651193.787084251, 98.22402546566013], + [508887.4607929517, 6651194.14528977, 98.72355661866014], + [508887.55051564984, 6651193.801090341, 98.88004791066015], + [508887.66056440957, 6651193.378914892, 98.39114022266014], + [508887.64151317684, 6651193.452000339, 99.00767066966016], + [508887.7680976564, 6651192.966389601, 98.51329334466014], + [508887.73296172824, 6651193.10118009, 99.10676616366015], + [508887.8751306496, 6651192.555783411, 98.59196803766015], + [508887.8542657875, 6651192.635826407, 99.19593081566015], + [508887.98020931665, 6651192.15267452, 98.62971089666014], + [508887.97335494356, 6651192.178969665, 99.23870605666015], + [508888.41245573515, 6651190.494465686, 98.62971089666014], + [508889.955717831, 6651184.574113935, 92.23344354966014], + [508889.955717831, 6651184.574113935, 92.36344354966016], + [508890.1094846779, 6651183.98422462, 92.23344354966014], + [508888.85387870675, 6651188.801053226, 98.62971089666014], + [508888.95895737363, 6651188.397944337, 98.59196803766015], + [508888.86073366995, 6651188.774755819, 99.23870605666015], + [508889.955717831, 6651184.574113935, 94.06224720866015], + [508889.065990367, 6651187.987338146, 98.51329334466014], + [508889.95105282386, 6651184.592010107, 94.47306252066014], + [508888.97982282605, 6651188.317899075, 99.19593081566015], + [508889.1735236138, 6651187.574812855, 98.39114022266014], + [508890.1094846779, 6651183.98422462, 94.06224720866015], + [508889.93646472436, 6651184.6479738215, 94.89418394866014], + [508889.2799213966, 6651187.166643497, 98.22402546566013], + [508889.10112688533, 6651187.852545393, 99.10676616366015], + [508889.91120112716, 6651184.744891502, 95.32027308366015], + [508890.1041976697, 6651184.004506948, 94.52783789566014], + [508889.383428662, 6651186.769562908, 98.01174765666013], + [508889.87474609405, 6651184.88474242, 95.74517958766015], + [508889.1925754367, 6651187.501725144, 99.00767066966016], + [508889.4822518374, 6651186.3904517, 97.75553453366014], + [508889.8268812106, 6651185.0683644675, 96.16214628966014], + [508890.08766449033, 6651184.067932491, 95.00510884766014], + [508889.5746518346, 6651186.0359814605, 97.45809206366016], + [508889.76773268386, 6651185.295273483, 96.56409520666014], + [508889.28357296373, 6651187.152635143, 98.88004791066015], + [508889.638772791, 6651185.789996919, 97.21038232366014], + [508889.697796842, 6651185.563565425, 96.94397600866016], + [508889.37329566176, 6651186.808435714, 98.72355661866014], + [508890.0590324136, 6651184.177772529, 95.48800986766015], + [508889.46089028625, 6651186.472400124, 98.53834771666016], + [508890.0292546002, 6651184.292007907, 95.84971585266014], + [508889.54549754574, 6651186.147824837, 98.32509538166015], + [508889.99221036263, 6651184.434119165, 96.20747369866014], + [508889.6262776009, 6651185.8379316935, 98.08500693466014], + [508889.94789527636, 6651184.604123275, 96.55792991366016], + [508889.7024362197, 6651185.545767575, 97.81980920966014], + [508889.89643484453, 6651184.801538775, 96.89767494066015], + [508889.77324997506, 6651185.27410773, 97.53171085866015], + [508889.8380888582, 6651185.025369038, 97.22334205066014], + [508898.64369931177, 6651200.036460568, 92.24021393804705], + [508898.7937528355, 6651199.44561576, 92.24021393804705], + [508898.7937528355, 6651199.44561576, 92.37021393804707], + [508898.64369931177, 6651200.036460568, 94.06901759704706], + [508898.6488586437, 6651200.016145387, 94.53460828404705], + [508898.79375225975, 6651199.445618027, 94.06901759804705], + [508898.7948711263, 6651199.441212422, 94.27283888204705], + [508898.66499256244, 6651199.952617109, 95.01187923604705], + [508898.80416154244, 6651199.404630847, 94.68941817004705], + [508898.69293320173, 6651199.8425991535, 95.49478025604706], + [508898.82352734177, 6651199.328376844, 95.11374529004705], + [508898.72199190944, 6651199.728178738, 95.85648624104705], + [508898.85359536944, 6651199.209982169, 95.54005564104706], + [508898.75814156374, 6651199.5858372925, 96.21424408704705], + [508898.8947307171, 6651199.048009254, 95.96186450004706], + [508898.80138648284, 6651199.415557812, 96.56470030204707], + [508898.94698296377, 6651198.84226288, 96.37221404304705], + [508898.8516041942, 6651199.217822542, 96.90444532904706], + [508898.90854118037, 6651198.993629721, 97.23011243904705], + [508899.01004990103, 6651198.593933006, 96.76399373704706], + [508899.06405995536, 6651198.381265156, 97.04147559704705], + [508898.9718142661, 6651198.744488127, 97.53848124704706], + [508899.1233747062, 6651198.147709745, 97.30191627004706], + [508899.04091793665, 6651198.472388252, 97.82657959804705], + [508899.18748225627, 6651197.895282396, 97.54288591604706], + [508899.11523739714, 6651198.17975089, 98.09177732304707], + [508899.2557844996, 6651197.62633819, 97.76230492204705], + [508899.19406669086, 6651197.8693557875, 98.33186577004707], + [508899.35222118907, 6651197.246612903, 98.01851804504705], + [508899.27663076547, 6651197.544254758, 98.54511810504707], + [508899.4532288525, 6651196.848889129, 98.23079585404705], + [508899.362110063, 6651197.207674866, 98.73032700704705], + [508899.4496660433, 6651196.862917906, 98.88681829904706], + [508899.55705723003, 6651196.440058625, 98.39791061104705], + [508899.5384660665, 6651196.513262454, 99.01444105804707], + [508899.66199365124, 6651196.026865132, 98.52006373304705], + [508899.6277062223, 6651196.1618739525, 99.11353655204707], + [508899.7664418994, 6651195.615593849, 98.59873842604705], + [508899.74608090386, 6651195.695766499, 99.20270120404706], + [508899.8689830165, 6651195.21183201, 98.63648128504705], + [508899.86229417, 6651195.2381697465, 99.24547644504706], + [508900.290791095, 6651193.550937236, 98.63648128504705], + [508901.7967848785, 6651187.620995796, 92.24021393804705], + [508901.7967848785, 6651187.620995796, 92.37021393804707], + [508901.9468384022, 6651187.030150988, 92.24021393804705], + [508900.7215541214, 6651191.854781814, 98.63648128504705], + [508900.8240952385, 6651191.451019975, 98.59873842604705], + [508901.7967848785, 6651187.620995796, 94.06901759704706], + [508900.7282435438, 6651191.82844181, 99.24547644504706], + [508900.9285434868, 6651191.039748694, 98.52006373304705], + [508901.7922325268, 6651187.638920956, 94.47983290904705], + [508900.8444568101, 6651191.370845058, 99.20270120404706], + [508901.9468384022, 6651187.030150988, 94.06901759704706], + [508901.77799671615, 6651187.694975321, 94.90095433704705], + [508901.0334799079, 6651190.626555199, 98.39791061104705], + [508901.7533432108, 6651187.792049986, 95.32704347204707], + [508901.13730828546, 6651190.217724695, 98.23079585404705], + [508900.9628314916, 6651190.904737604, 99.11353655204707], + [508901.94167907024, 6651187.05046617, 94.53460828404705], + [508901.717768532, 6651187.932127431, 95.75194997604706], + [508901.23831594887, 6651189.820000922, 98.01851804504705], + [508901.0520716475, 6651190.553349102, 99.01444105804707], + [508901.67105954, 6651188.116046907, 96.16891667804705], + [508901.3347526385, 6651189.440275635, 97.76230492204705], + [508901.92554515146, 6651187.113994448, 95.01187923604705], + [508901.6133393939, 6651188.343323467, 96.57086559504705], + [508901.4249212637, 6651189.08523123, 97.46486245204707], + [508901.48749375984, 6651188.838848249, 97.21715271204705], + [508901.54509243625, 6651188.612049984, 96.95074639704707], + [508901.1408716707, 6651190.203693651, 98.88681829904706], + [508901.8976045122, 6651187.224012404, 95.49478025604706], + [508901.22842765093, 6651189.858936692, 98.73032700704705], + [508901.8685458045, 6651187.338432819, 95.85648624104705], + [508901.3139069485, 6651189.522356797, 98.54511810504707], + [508901.83239615016, 6651187.480774265, 96.21424408704705], + [508901.3964710231, 6651189.197255771, 98.33186577004707], + [508901.7891512311, 6651187.651053744, 96.56470030204707], + [508901.47530031676, 6651188.886860667, 98.09177732304707], + [508901.7389335197, 6651187.848789014, 96.90444532904706], + [508901.54961977724, 6651188.594223305, 97.82657959804705], + [508901.68199653353, 6651188.072981834, 97.23011243904705], + [508901.61872344784, 6651188.32212343, 97.53848124704706], + [508906.01164131216, 6651201.892434828, 92.23852090819406], + [508906.1593993975, 6651201.301011802, 92.23852090819406], + [508906.1593993975, 6651201.301011802, 92.36852090819407], + [508906.01164131216, 6651201.892434828, 94.06732456719406], + [508906.01672171947, 6651201.872099766, 94.53291525419407], + [508906.15939883055, 6651201.30101407, 94.06732456819407], + [508906.16050058126, 6651201.296604154, 94.27114585219407], + [508906.0326088302, 6651201.808509315, 95.01018620619406], + [508906.1696488776, 6651201.25998678, 94.68772514019406], + [508906.0601220485, 6651201.6983836945, 95.49308722619406], + [508906.1887184293, 6651201.183658152, 95.11205226019408], + [508906.08873623156, 6651201.583851304, 95.85479321119408], + [508906.2183264924, 6651201.065147614, 95.53836261119406], + [508906.1243328879, 6651201.441370559, 96.21255105719406], + [508906.25883257366, 6651200.903016187, 95.96017147019407], + [508906.16691626934, 6651201.270924438, 96.56300727219407], + [508906.3102854933, 6651200.697068463, 96.37052101319406], + [508906.21636577713, 6651201.072995658, 96.90275229919406], + [508906.3723876664, 6651200.448495566, 96.76230070719407], + [508906.2724317718, 6651200.848583437, 97.22841940919407], + [508906.4255715039, 6651200.235619593, 97.03978256719408], + [508906.33473693975, 6651200.599198025, 97.53678821719409], + [508906.4839788894, 6651200.001835617, 97.30022324019407], + [508906.40278349933, 6651200.326831865, 97.82488656819406], + [508906.5471057564, 6651199.749161236, 97.54119288619407], + [508906.4759660606, 6651200.033908119, 98.09008429319407], + [508906.61436314863, 6651199.479953834, 97.76061189219408], + [508906.55358946585, 6651199.723209255, 98.33017274019407], + [508906.7093246013, 6651199.099856937, 98.01682501519407], + [508906.63489051955, 6651199.397790073, 98.54342507519407], + [508906.8087871037, 6651198.70174394, 98.22910282419406], + [508906.7190622006, 6651199.060880792, 98.72863397719406], + [508906.8052787963, 6651198.715786445, 98.88512526919406], + [508906.9110271703, 6651198.292513342, 98.39621758119408], + [508906.89272040426, 6651198.36578881, 99.01274802819407], + [508907.0143583303, 6651197.878915487, 98.51837070319408], + [508906.9805954121, 6651198.01405643, 99.11184352219406], + [508907.1172087851, 6651197.467241721, 98.59704539619406], + [508907.21818128304, 6651197.0630847495, 98.63478825519407], + [508907.0971592612, 6651197.547492829, 99.20100817419407], + [508907.211594759, 6651197.089448261, 99.24378341519409], + [508907.6335367675, 6651195.400564576, 98.63478825519407], + [508909.11649266473, 6651189.464819925, 92.23852090819406], + [508909.11649266473, 6651189.464819925, 92.36852090819407], + [508909.26425075, 6651188.873396899, 92.23852090819406], + [508908.05771021196, 6651193.702749248, 98.63478825519407], + [508909.11649266473, 6651189.464819925, 94.06732456719406], + [508908.1586827099, 6651193.298592276, 98.59704539619406], + [508908.06429730315, 6651193.6763834655, 99.24378341519409], + [508909.1120099525, 6651189.482762627, 94.47813987919407], + [508908.2615331648, 6651192.88691851, 98.51837070319408], + [508909.26425075, 6651188.873396899, 94.06732456719406], + [508909.0979919136, 6651189.538871847, 94.89926130719408], + [508908.17873280105, 6651193.2183388965, 99.20100817419407], + [508908.3648643248, 6651192.473320655, 98.39621758119408], + [508909.07371554436, 6651189.636041514, 95.32535044219406], + [508909.25917034276, 6651188.893731961, 94.53291525419407], + [508908.4671043914, 6651192.064090057, 98.22910282419406], + [508908.29529665015, 6651192.751775297, 99.11184352219406], + [508909.0386850681, 6651189.776256042, 95.75025694619407], + [508908.5665668937, 6651191.66597706, 98.01682501519407], + [508908.99269060517, 6651189.960355506, 96.16722364819408], + [508909.24328323203, 6651188.957322411, 95.01018620619406], + [508908.38317165786, 6651192.400042916, 99.01274802819407], + [508908.6615283465, 6651191.285880164, 97.76061189219408], + [508908.9358534309, 6651190.187854486, 96.56917256519407], + [508908.7503176203, 6651190.9304883005, 97.46316942219407], + [508908.86865047866, 6651190.456843985, 96.94905336719407], + [508908.811932916, 6651190.683864202, 97.21545968219407], + [508908.4706132658, 6651192.050045281, 98.88512526919406], + [508909.21577001363, 6651189.067448033, 95.49308722619406], + [508908.55682986166, 6651191.704950933, 98.72863397719406], + [508909.1871558306, 6651189.181980424, 95.85479321119408], + [508908.6410015427, 6651191.368041652, 98.54342507519407], + [508909.1515591743, 6651189.324461169, 96.21255105719406], + [508908.7223025963, 6651191.042622471, 98.33017274019407], + [508909.1089757928, 6651189.494907288, 96.56300727219407], + [508908.7999260017, 6651190.731923607, 98.09008429319407], + [508909.0595262851, 6651189.692836069, 96.90275229919406], + [508908.8731085629, 6651190.438999861, 97.82488656819406], + [508909.0034602904, 6651189.917248291, 97.22841940919407], + [508908.9411551224, 6651190.166633703, 97.53678821719409], + [508915.6162112216, 6651204.266210336, 92.22959665928788], + [508915.76097706036, 6651203.674047774, 92.22959665928788], + [508915.76097706036, 6651203.674047774, 92.35959665928787], + [508915.6162112216, 6651204.266210336, 94.05840031828788], + [508915.6211887457, 6651204.245849845, 94.52399100528787], + [508915.76097650494, 6651203.674050045, 94.05840031928787], + [508915.7620559442, 6651203.669634616, 94.26222160328788], + [508915.63675412675, 6651204.18217988, 95.00126195728788], + [508915.77101897844, 6651203.632971454, 94.67880089128788], + [508915.66371017543, 6651204.071916554, 95.48416297728788], + [508915.78970235295, 6651203.556547381, 95.10312801128786], + [508915.6917448931, 6651203.957240948, 95.84586896228787], + [508915.8187108238, 6651203.437888652, 95.52943836228786], + [508915.72662068217, 6651203.81458204, 96.20362680828786], + [508915.85839661694, 6651203.275554492, 95.95124722128789], + [508915.76834170823, 6651203.643922789, 96.55408302328787], + [508915.90880756435, 6651203.069349243, 96.36159676428787], + [508915.8167898148, 6651203.445746511, 96.89382805028788], + [508915.96965210733, 6651202.820465523, 96.75337645828789], + [508915.871720418, 6651203.221053677, 97.21949516028786], + [508916.0217589198, 6651202.607323363, 97.03085831828787], + [508915.932763845, 6651202.971356425, 97.52786396828787], + [508916.0789834984, 6651202.373247055, 97.29129899128787], + [508915.9994323948, 6651202.69864969, 97.81596231928788], + [508916.14083198435, 6651202.120256723, 97.53226863728787], + [508916.0711329373, 6651202.405359662, 98.08116004428787], + [508916.20672734815, 6651201.850712692, 97.75168764328787], + [508916.14718439226, 6651202.094272289, 98.32124849128788], + [508916.299765738, 6651201.470140509, 98.00790076628786], + [508916.2268390196, 6651201.768446192, 98.53450082628787], + [508916.39721402683, 6651201.071529699, 98.22017857528787], + [508916.3093061413, 6651201.431115628, 98.71970972828788], + [508916.49738363165, 6651200.661787384, 98.38729333228787], + [508916.3937767663, 6651201.085589763, 98.87620102028787], + [508916.4794475957, 6651200.735154479, 99.00382377928788], + [508916.598622234, 6651200.247672351, 98.50944645428787], + [508916.56554304814, 6651200.382982281, 99.10291927328788], + [508916.699389866, 6651199.835483816, 98.58812114728788], + [508916.7983175716, 6651199.430821473, 98.62586400628788], + [508916.6797463646, 6651199.9158352725, 99.19208392528789], + [508916.7918644311, 6651199.45721795, 99.23485916628788], + [508917.20526169904, 6651197.766222427, 98.62586400628788], + [508918.6581862809, 6651191.823055518, 92.22959665928788], + [508918.6581862809, 6651191.823055518, 92.35959665928787], + [508918.8029521197, 6651191.230892957, 92.22959665928788], + [508917.620845214, 6651196.066284092, 98.62586400628788], + [508918.6581862809, 6651191.823055518, 94.05840031828788], + [508917.7197729196, 6651195.6616217485, 98.58812114728788], + [508918.65379434807, 6651191.841020656, 94.46921563028786], + [508917.62729891017, 6651196.039885341, 99.23485916628788], + [508917.8205405517, 6651195.249433213, 98.50944645428787], + [508918.8029521197, 6651191.230892957, 94.05840031828788], + [508918.64006018825, 6651191.897200037, 94.89033705828787], + [508917.73941697675, 6651195.581268019, 99.19208392528789], + [508917.92177915404, 6651194.835318179, 98.38729333228787], + [508918.6162754394, 6651191.9944912065, 95.31642619328787], + [508918.7979745957, 6651191.251253446, 94.52399100528787], + [508918.02194875875, 6651194.425575865, 98.22017857528787], + [508918.5819543646, 6651192.134881065, 95.74133269728789], + [508917.85362029314, 6651195.1141210105, 99.10291927328788], + [508918.11939704756, 6651194.026965055, 98.00790076628786], + [508918.78240921453, 6651191.314923412, 95.00126195728788], + [508918.53689133486, 6651192.319210733, 96.15829939928787], + [508918.2124354374, 6651193.646392873, 97.75168764328787], + [508917.9397157457, 6651194.761948813, 99.00382377928788], + [508918.4812051692, 6651192.546994185, 96.56024831628787], + [508918.2994266412, 6651193.290556616, 97.45424517328787], + [508918.4153631428, 6651192.816320039, 96.94012911828787], + [508918.3597941666, 6651193.04362413, 97.20653543328788], + [508918.75545316585, 6651191.4251867365, 95.48416297728788], + [508918.025386575, 6651194.411513528, 98.87620102028787], + [508918.7274184482, 6651191.539862342, 95.84586896228787], + [508918.1098572, 6651194.065987662, 98.71970972828788], + [508918.6925426591, 6651191.682521251, 96.20362680828786], + [508918.1923243218, 6651193.7286570985, 98.53450082628787], + [508918.65082163305, 6651191.853180503, 96.55408302328787], + [508918.271978949, 6651193.402831002, 98.32124849128788], + [508918.6023735265, 6651192.051356779, 96.89382805028788], + [508918.348030404, 6651193.091743629, 98.08116004428787], + [508918.5474429233, 6651192.276049614, 97.21949516028786], + [508918.4197309465, 6651192.798453601, 97.81596231928788], + [508918.48639949627, 6651192.525746866, 97.52786396828787], + [508925.34776055074, 6651206.618911569, 92.21282714508105], + [508925.48949458316, 6651206.026016037, 92.21282714508105], + [508925.48949458316, 6651206.026016037, 92.34282714508106], + [508925.34776055074, 6651206.618911569, 94.04163080408105], + [508925.3526338313, 6651206.598525876, 94.50722149108107], + [508925.4894940394, 6651206.026018311, 94.04163080508107], + [508925.49055087205, 6651206.021597415, 94.24545208908106], + [508925.36787322926, 6651206.534777101, 94.98449244308105], + [508925.4993261951, 6651205.984888872, 94.66203137708105], + [508925.3942647419, 6651206.424377293, 95.46739346308105], + [508925.51761828695, 6651205.908370203, 95.08635849708105], + [508925.42171233334, 6651206.309559744, 95.82909944808105], + [508925.5460192382, 6651205.789564601, 95.51266884808105], + [508925.4558577247, 6651206.166724255, 96.18685729408105], + [508925.58487389865, 6651205.6270295065, 95.93447770708106], + [508925.4967049945, 6651205.995853763, 96.53731350908106], + [508925.6342290983, 6651205.420569018, 96.34482725008107], + [508925.54413846065, 6651205.797432187, 96.87705853608105], + [508925.69379938435, 6651205.171377234, 96.73660694408106], + [508925.59791866154, 6651205.572461231, 97.20272564608106], + [508925.74481493275, 6651204.957971252, 97.01408880408107], + [508925.65768366656, 6651205.322454908, 97.51109445408107], + [508925.80084106675, 6651204.723605206, 97.27452947708107], + [508925.7229559883, 6651205.049410619, 97.79919280508105], + [508925.8613942703, 6651204.470301725, 97.51549912308106], + [508925.7931549186, 6651204.755757561, 98.06439053008107], + [508925.9259095988, 6651204.200424059, 97.73491812908105], + [508925.867613641, 6651204.44428513, 98.30447897708106], + [508926.0169995016, 6651203.819380809, 97.99113125208108], + [508925.94560007507, 6651204.118055731, 98.51773131208105], + [508926.11240694765, 6651203.420276604, 98.20340906108106], + [508926.02634010196, 6651203.780307623, 98.70294021408105], + [508926.21047871746, 6651203.010027117, 98.37052381808107], + [508926.109041673, 6651203.434354072, 98.85943150608105], + [508926.19291831285, 6651203.083485024, 98.98705426508106], + [508926.30959709705, 6651202.595399497, 98.49267694008107], + [508926.277210683, 6651202.730876911, 99.08614975908105], + [508926.40825436986, 6651202.182700761, 98.57135163308105], + [508926.50511024933, 6651201.777537532, 98.60909449208106], + [508926.38902225887, 6651202.263151676, 99.17531441108106], + [508926.498792256, 6651201.803966682, 99.21808965208108], + [508926.90353181545, 6651200.110878071, 98.60909449208106], + [508928.32602804626, 6651194.160354798, 92.21282714508105], + [508928.32602804626, 6651194.160354798, 92.34282714508106], + [508928.4677620787, 6651193.567459267, 92.21282714508105], + [508927.3104118359, 6651198.408835579, 98.60909449208106], + [508928.32602804626, 6651194.160354798, 94.04163080408105], + [508927.4072677155, 6651198.00367235, 98.57135163308105], + [508928.3217280928, 6651194.178342173, 94.45244611608105], + [508927.3167303734, 6651198.382404151, 99.21808965208108], + [508928.4677620787, 6651193.567459267, 94.04163080408105], + [508927.5059249883, 6651197.590973613, 98.49267694008107], + [508928.3082815652, 6651194.234591092, 94.87356754408106], + [508927.42650037055, 6651197.923219158, 99.17531441108106], + [508927.6050433679, 6651197.176345994, 98.37052381808107], + [508928.2849949362, 6651194.332002687, 95.29965667908105], + [508928.46288879815, 6651193.587844958, 94.50722149108107], + [508927.7031151377, 6651196.766096507, 98.20340906108106], + [508928.25139264186, 6651194.472566318, 95.72456318308106], + [508927.53831194644, 6651197.455493922, 99.08614975908105], + [508928.44764940016, 6651193.651593733, 94.98449244308105], + [508927.7985225836, 6651196.366992301, 97.99113125208108], + [508928.2072733594, 6651194.657124148, 96.14152988508106], + [508927.88961248647, 6651195.985949052, 97.73491812908105], + [508928.1527534197, 6651194.885189546, 96.54347880208107], + [508927.62260431657, 6651197.102885812, 98.98705426508106], + [508927.9747818484, 6651195.629672347, 97.43747565908106], + [508928.08829031157, 6651195.154848767, 96.92335960408106], + [508928.03388510685, 6651195.382434212, 97.18976591908105], + [508928.4212578874, 6651193.76199354, 95.46739346308105], + [508927.7064809564, 6651196.752016763, 98.85943150608105], + [508928.39381029597, 6651193.876811091, 95.82909944808105], + [508927.78918252746, 6651196.406063211, 98.70294021408105], + [508928.3596649047, 6651194.019646581, 96.18685729408105], + [508927.8699225544, 6651196.068315105, 98.51773131208105], + [508928.3188176349, 6651194.190517071, 96.53731350908106], + [508927.9479089884, 6651195.7420857055, 98.30447897708106], + [508928.27138416877, 6651194.388938648, 96.87705853608105], + [508928.0223677109, 6651195.430613273, 98.06439053008107], + [508928.21760396776, 6651194.613909604, 97.20272564608106], + [508928.09256664105, 6651195.136960215, 97.79919280508105], + [508928.15783896286, 6651194.863915928, 97.51109445408107], + [508932.6258556321, 6651208.344070148, 92.19521859384106], + [508932.7653222175, 6651207.750637153, 92.19521859384106], + [508932.7653222175, 6651207.750637153, 92.32521859384107], + [508932.6258556321, 6651208.344070148, 94.02402225284106], + [508932.6306509505, 6651208.323665977, 94.48961293984107], + [508932.7653216824, 6651207.75063943, 94.02402225384107], + [508932.76636160794, 6651207.746214527, 94.22784353784107], + [508932.6456465501, 6651208.259859414, 94.96688389184106], + [508932.7749965442, 6651207.7094727075, 94.64442282584106], + [508932.6716158539, 6651208.149359527, 95.44978491184106], + [508932.7929960009, 6651207.632884675, 95.06874994584108], + [508932.6986243415, 6651208.034437896, 95.81149089684108], + [508932.82094259665, 6651207.513971374, 95.49506029684106], + [508932.73222347815, 6651207.891472924, 96.16924874284108], + [508932.85917566397, 6651207.351288939, 95.91686915584107], + [508932.7724172773, 6651207.7204475375, 96.51970495784107], + [508932.90774128394, 6651207.144641295, 96.32721869884107], + [508932.8190919075, 6651207.521846091, 96.85944998484106], + [508932.9663585705, 6651206.895223618, 96.71899839284107], + [508932.87201173813, 6651207.296671198, 97.18511709484108], + [508933.0165579771, 6651206.68162418, 96.99648025284107], + [508932.93082062836, 6651207.046438242, 97.49348590284107], + [508933.07168781053, 6651206.447045681, 97.25692092584107], + [508932.99504872994, 6651206.773146439, 97.78158425384106], + [508933.13127228996, 6651206.193512579, 97.49789057184108], + [508933.06412462454, 6651206.479227183, 98.04678197884107], + [508933.19475550856, 6651205.9233902665, 97.71730957784108], + [508933.1373921637, 6651206.1674724, 98.28687042584107], + [508933.284388164, 6651205.542001599, 97.97352270084107], + [508933.21413097833, 6651205.840947271, 98.50012276084107], + [508933.37826929096, 6651205.142535604, 98.18580050984109], + [508933.2935793343, 6651205.502892993, 98.68533166284107], + [508933.4747721182, 6651204.731914224, 98.35291526684107], + [508933.37495785364, 6651205.156625833, 98.84182295484106], + [508933.45749264327, 6651204.805438722, 98.96944571384107], + [508933.5723048118, 6651204.316910744, 98.47506838884107], + [508933.5404365123, 6651204.452510969, 99.06854120784106], + [508933.66938377515, 6651203.903837893, 98.55374308184106], + [508933.76469016384, 6651203.498307382, 98.59148594084108], + [508933.65045933763, 6651203.984361737, 99.15770585984107], + [508933.75847324496, 6651203.52476049, 99.20048110084107], + [508935.5564770961, 6651195.874219633, 92.19521859384106], + [508934.15673782077, 6651201.830137085, 98.59148594084108], + [508935.5564770961, 6651195.874219633, 92.32521859384107], + [508935.69594368146, 6651195.280786637, 92.19521859384106], + [508935.5564770961, 6651195.874219633, 94.02402225284106], + [508934.5571086145, 6651200.126551682, 98.59148594084108], + [508935.552245933, 6651195.892223312, 94.43483756484108], + [508934.6524150032, 6651199.721021171, 98.55374308184106], + [508935.69594368146, 6651195.280786637, 94.02402225284106], + [508934.56332606863, 6651200.100096295, 99.20048110084107], + [508935.5390145215, 6651195.948523222, 94.85595899284108], + [508934.7494939665, 6651199.30794832, 98.47506838884107], + [508935.6911483631, 6651195.301190808, 94.48961293984107], + [508935.51610042976, 6651196.046023121, 95.28204812784107], + [508934.84702666, 6651198.892944839, 98.35291526684107], + [508934.6713399761, 6651199.640495048, 99.15770585984107], + [508935.4830357017, 6651196.186714173, 95.70695463184107], + [508934.94352948724, 6651198.482323458, 98.18580050984109], + [508935.6761527636, 6651195.364997372, 94.96688389184106], + [508934.78136280127, 6651199.172345817, 99.06854120784106], + [508935.43962223514, 6651196.371439305, 96.12392133384108], + [508935.0374106143, 6651198.082857464, 97.97352270084107], + [508935.3859745001, 6651196.599711447, 96.52587025084107], + [508935.12704326975, 6651197.7014687965, 97.71730957784108], + [508935.32254266646, 6651196.869615115, 96.90575105284107], + [508934.8643066703, 6651198.819418063, 98.96944571384107], + [508935.6501834597, 6651195.475497258, 95.44978491184106], + [508935.21085010056, 6651197.344869125, 97.41986710784107], + [508935.26900783094, 6651197.097406866, 97.17215736784107], + [508934.94684145995, 6651198.468230952, 98.84182295484106], + [508935.6231749722, 6651195.590418891, 95.81149089684108], + [508935.02821997943, 6651198.121963792, 98.68533166284107], + [508935.58957583545, 6651195.733383862, 96.16924874284108], + [508935.10766833526, 6651197.783909515, 98.50012276084107], + [508935.5493820363, 6651195.904409247, 96.51970495784107], + [508935.50270740606, 6651196.103010694, 96.85944998484106], + [508935.18440715, 6651197.457384387, 98.28687042584107], + [508935.44978757546, 6651196.328185587, 97.18511709484108], + [508935.2576746891, 6651197.145629603, 98.04678197884107], + [508935.39097868523, 6651196.578418543, 97.49348590284107], + [508935.3267505836, 6651196.8517103465, 97.78158425384106], + [508944.7309605982, 6651211.148441953, 92.15636226031798], + [508944.86665591015, 6651210.554135273, 92.15636226031798], + [508944.86665591015, 6651210.554135273, 92.28636226031799], + [508944.7309605982, 6651211.148441953, 93.98516591931798], + [508944.7356262477, 6651211.128007742, 94.45075660631797], + [508944.86665538955, 6651210.554137555, 93.98516592031797], + [508944.86766719486, 6651210.549706136, 94.18898720431797], + [508944.7502163559, 6651211.064107238, 94.92802755831796], + [508944.87606863637, 6651210.512910223, 94.60556649231798], + [508944.77548343176, 6651210.953444668, 95.41092857831798], + [508944.89358137525, 6651210.436209433, 95.02989361231796], + [508944.801761591, 6651210.838353842, 95.77263456331796], + [508944.92077227565, 6651210.3171210615, 95.45620396331798], + [508944.83445218374, 6651210.6951783905, 96.13039240931796], + [508944.95797149424, 6651210.154199116, 95.87801282231797], + [508944.8735591147, 6651210.523901211, 96.48084862431799], + [508945.0052238661, 6651209.947247235, 96.28836236531797], + [508944.9189716305, 6651210.325007372, 96.82059365131798], + [508945.0622561005, 6651209.697462349, 96.68014205931799], + [508944.97046047205, 6651210.099500963, 97.14626076131796], + [508945.1110980803, 6651209.483548438, 96.95762391931797], + [508945.02767912904, 6651209.848899601, 97.45462956931797], + [508945.1647371648, 6651209.248624582, 97.21806459231797], + [508945.09017045813, 6651209.575205442, 97.74272792031798], + [508945.2227104385, 6651208.994718214, 97.45903423831797], + [508945.1573784926, 6651209.2808534615, 98.00792564531797], + [508945.28447702667, 6651208.724198211, 97.67845324431796], + [508945.2286648265, 6651208.968639695, 98.24801409231797], + [508945.3716859529, 6651208.342248043, 97.93466636731796], + [508945.3033285704, 6651208.641633839, 98.46126642731798], + [508945.463028469, 6651207.94219393, 98.14694417631796], + [508945.38062858756, 6651208.303081859, 98.64647532931797], + [508945.5569217928, 6651207.530968011, 98.31405893331797], + [508945.4598065753, 6651207.956304904, 98.80296662131796], + [508945.6518171345, 6651207.115353539, 98.43621205531797], + [508945.5401095668, 6651207.604600755, 98.93058938031798], + [508945.6208105761, 6651207.251153402, 99.02968487431798], + [508945.74627101526, 6651206.701672539, 98.51488674831798], + [508945.839000253, 6651206.295544983, 98.55262960731797], + [508945.7278583078, 6651206.782314935, 99.11884952631799], + [508945.8329514441, 6651206.322037038, 99.16162476731797], + [508947.5823360222, 6651198.660232624, 92.15636226031798], + [508947.5823360222, 6651198.660232624, 92.28636226031799], + [508946.22044666903, 6651204.624918713, 98.55262960731797], + [508947.7180313342, 6651198.065925944, 92.15636226031798], + [508947.5823360222, 6651198.660232624, 93.98516591931798], + [508946.6099911584, 6651202.918825195, 98.55262960731797], + [508947.5782192727, 6651198.678262811, 94.39598123131796], + [508947.7180313342, 6651198.065925944, 93.98516591931798], + [508946.70272039616, 6651202.512697639, 98.51488674831798], + [508947.56534564774, 6651198.734645607, 94.81710265931797], + [508946.61604048836, 6651202.892330859, 99.16162476731797], + [508946.79717427696, 6651202.09901664, 98.43621205531797], + [508947.7133656846, 6651198.086360155, 94.45075660631797], + [508947.54305116896, 6651198.832289051, 95.24319179431797], + [508946.89206961874, 6651201.683402168, 98.31405893331797], + [508946.72113362467, 6651202.4320529625, 99.11884952631799], + [508947.510880534, 6651198.973187237, 95.66809829831797], + [508947.69877557654, 6651198.150260659, 94.92802755831796], + [508946.9859629424, 6651201.272176248, 98.14694417631796], + [508947.4686409979, 6651199.158184332, 96.08506500031797], + [508946.82818135637, 6651201.963214495, 99.02968487431798], + [508947.07730545854, 6651200.872122136, 97.93466636731796], + [508947.41644393484, 6651199.386792549, 96.48701391731797], + [508947.6735085006, 6651198.260923229, 95.41092857831798], + [508947.16451438476, 6651200.490171966, 97.67845324431796], + [508947.3547273421, 6651199.657093584, 96.86689471931798], + [508947.24605502066, 6651200.133047289, 97.38101077431797], + [508947.3026401257, 6651199.885220703, 97.13330103431797], + [508946.90888236556, 6651201.609767142, 98.93058938031798], + [508947.6472303414, 6651198.376014055, 95.77263456331796], + [508946.9891853571, 6651201.258062992, 98.80296662131796], + [508947.6145397487, 6651198.519189507, 96.13039240931796], + [508947.0683633449, 6651200.911286038, 98.64647532931797], + [508947.57543281774, 6651198.690466686, 96.48084862431799], + [508947.14566336205, 6651200.572734058, 98.46126642731798], + [508947.5300203019, 6651198.889360525, 96.82059365131798], + [508947.22032710584, 6651200.245728201, 98.24801409231797], + [508947.4785314604, 6651199.114866933, 97.14626076131796], + [508947.2916134398, 6651199.933514435, 98.00792564531797], + [508947.4213128033, 6651199.365468296, 97.45462956931797], + [508947.3588214742, 6651199.639162456, 97.74272792031798], + [508949.67127328314, 6651212.269714138, 92.13707974170651], + [508949.8054294701, 6651211.675058132, 92.13707974170651], + [508949.8054294701, 6651211.675058132, 92.26707974170652], + [508949.67127328314, 6651212.269714138, 93.96588340070652], + [508949.6758860125, 6651212.249267915, 94.43147408770653], + [508949.8054289554, 6651211.675060415, 93.96588340170653], + [508949.8064292842, 6651211.670626392, 94.16970468570652], + [508949.6903106322, 6651212.185329852, 94.90874503970652], + [508949.81473543245, 6651211.63380885, 94.58628397370651], + [508949.71529111615, 6651212.074602236, 95.39164605970652], + [508949.832049533, 6651211.557062976, 95.01061109370652], + [508949.7412712152, 6651211.959443761, 95.75335204470652], + [508949.8589320203, 6651211.437904607, 95.43692144470651], + [508949.7735910147, 6651211.816184153, 96.11110989070652], + [508949.89570930664, 6651211.274886899, 95.85873030370652], + [508949.8122543749, 6651211.644806298, 96.46156610570652], + [508949.94242571807, 6651211.067813372, 96.26907984670653], + [508949.85715179896, 6651211.445795553, 96.80131113270652], + [508949.998811064, 6651210.817881668, 96.66085954070653], + [508949.9080566281, 6651211.220156594, 97.12697824270653], + [508950.04709905334, 6651210.603842022, 96.93834140070653], + [508949.96462628205, 6651210.969407933, 97.43534705070654], + [508950.10012973606, 6651210.368780077, 97.19878207370654], + [508950.02640880283, 6651210.695552899, 97.72344540170651], + [508950.1574454476, 6651210.114724467, 97.43975171970652], + [508950.0928545297, 6651210.401027903, 97.98864312670652], + [508950.21851144783, 6651209.844045457, 97.65917072570653], + [508950.16333229793, 6651210.088630621, 98.22873157370653], + [508950.30473120627, 6651209.461870784, 97.91538384870653], + [508950.23714916775, 6651209.761432555, 98.44198390870652], + [508950.3950376692, 6651209.061581525, 98.12766165770651], + [508950.313572409, 6651209.422681578, 98.62719281070652], + [508950.4878660074, 6651208.650113892, 98.29477641470653], + [508950.3918523198, 6651209.075700793, 98.78368410270652], + [508950.58168499806, 6651208.234255128, 98.41692953670653], + [508950.47124447423, 6651208.723789916, 98.91130686170652], + [508950.55103013164, 6651208.370134811, 99.01040235570652], + [508950.675067535, 6651207.820330971, 98.49560422970652], + [508950.7667449908, 6651207.413964699, 98.53334708870652], + [508950.6568636737, 6651207.901020768, 99.09956700770653], + [508950.76076479047, 6651207.440472324, 99.14234224870654], + [508952.49030696234, 6651199.774164403, 92.13707974170651], + [508952.49030696234, 6651199.774164403, 92.26707974170652], + [508951.14386484824, 6651205.742356456, 98.53334708870652], + [508952.6244631494, 6651199.179508398, 92.13707974170651], + [508952.49030696234, 6651199.774164403, 93.96588340070652], + [508951.5289909267, 6651204.0352601195, 98.53334708870652], + [508952.486236907, 6651199.792205187, 94.37669871270653], + [508952.6244631494, 6651199.179508398, 93.96588340070652], + [508951.6206683824, 6651203.628893848, 98.49560422970652], + [508952.4735093013, 6651199.848621125, 94.79782014070652], + [508951.53497164196, 6651204.0087502105, 99.14234224870654], + [508952.6198504199, 6651199.19995462, 94.43147408770653], + [508951.71405091946, 6651203.214969691, 98.41692953670653], + [508952.45146769786, 6651199.946321964, 95.22390927570652], + [508951.8078699101, 6651202.799110927, 98.29477641470653], + [508952.4196619585, 6651200.087302967, 95.64881577970652], + [508951.6388727587, 6651203.548201768, 99.09956700770653], + [508952.60542580014, 6651199.263892684, 94.90874503970652], + [508951.90069824824, 6651202.387643293, 98.12766165770651], + [508952.3779015246, 6651200.272408801, 96.06578248170652], + [508951.9910047112, 6651201.987354035, 97.91538384870653], + [508952.3262965071, 6651200.501151389, 96.46773139870653], + [508951.7447063008, 6651203.079087725, 99.01040235570652], + [508952.58044531633, 6651199.374620299, 95.39164605970652], + [508952.07722446957, 6651201.60517936, 97.65917072570653], + [508952.2652799351, 6651200.771611306, 96.84761220070652], + [508952.21378351835, 6651200.999872515, 97.11401851570652], + [508952.1578402302, 6651201.24784477, 97.36172825570652], + [508951.82449195825, 6651202.725432619, 98.91130686170652], + [508952.5544652172, 6651199.489778774, 95.75335204470652], + [508951.9038841126, 6651202.373521742, 98.78368410270652], + [508952.5221454178, 6651199.633038383, 96.11110989070652], + [508951.98216402344, 6651202.026540956, 98.62719281070652], + [508952.4834820575, 6651199.8044162365, 96.46156610570652], + [508952.0585872647, 6651201.68778998, 98.44198390870652], + [508952.43858463346, 6651200.003426982, 96.80131113270652], + [508952.1324041345, 6651201.3605919145, 98.22873157370653], + [508952.38767980435, 6651200.229065941, 97.12697824270653], + [508952.20288190275, 6651201.048194633, 97.98864312670652], + [508952.3311101504, 6651200.479814603, 97.43534705070654], + [508952.2693276296, 6651200.753669637, 97.72344540170651], + [508964.1592355286, 6651215.480557236, 92.06912625390798], + [508964.28887807723, 6651214.884900912, 92.06912625390798], + [508964.28887807723, 6651214.884900912, 92.19912625390799], + [508964.1592355286, 6651215.480557236, 93.89792991290798], + [508964.16369306436, 6651215.460076619, 94.36352059990799], + [508964.2888775799, 6651214.884903196, 93.89792991390799], + [508964.289844253, 6651214.880461715, 94.101751197908], + [508964.17763237277, 6651215.396031001, 94.840791551908], + [508964.2978709437, 6651214.843582242, 94.51833048590798], + [508964.201772397, 6651215.2851171205, 95.32369257190798], + [508964.31460251735, 6651214.766707266, 94.94265760590798], + [508964.2268784046, 6651215.169764928, 95.685398556908], + [508964.3405805528, 6651214.64734845, 95.36896795690798], + [508964.25811081566, 6651215.02626433, 96.043156402908], + [508964.37612048, 6651214.484056517, 95.790776815908], + [508964.2954733606, 6651214.854598189, 96.39361261790799], + [508964.42126513406, 6651214.276634655, 96.20112635890798], + [508964.3388602264, 6651214.655252671, 96.73335764490798], + [508964.47575341456, 6651214.026282521, 96.59290605290799], + [508964.3880523801, 6651214.429234146, 97.05902475490798], + [508964.52241677133, 6651213.811882821, 96.87038791290799], + [508964.44271876774, 6651214.1780636795, 97.36739356290799], + [508964.57366325514, 6651213.57642546, 97.13082858590799], + [508964.5024226372, 6651213.903747972, 97.65549191390798], + [508964.6290505994, 6651213.321942482, 97.371798231908], + [508964.5666328205, 6651213.6087275315, 97.92068963890799], + [508964.6880620553, 6651213.050808142, 97.59121723790798], + [508964.63473938877, 6651213.295804741, 98.16077808590799], + [508964.77138097986, 6651212.66799058, 97.84743036090799], + [508964.7060727157, 6651212.968056269, 98.37403042090799], + [508964.8586491133, 6651212.267027964, 98.059708169908], + [508964.7799247234, 6651212.628735453, 98.559239322908], + [508964.9483542742, 6651211.854868167, 98.22682292690799], + [508964.85557093384, 6651212.281170982, 98.71573061490798], + [508965.0390167575, 6651211.438309852, 98.34897604890799], + [508964.93229196675, 6651211.928668127, 98.84335337390799], + [508965.1292574715, 6651211.023689401, 98.42765074190798], + [508965.00939326355, 6651211.574418111, 98.94244886790798], + [508965.21785047103, 6651210.616639547, 98.465393600908], + [508965.1116660728, 6651211.104514932, 99.03161351990799], + [508965.2120714725, 6651210.643191763, 99.074388760908], + [508966.8834237986, 6651202.963987725, 92.06912625390798], + [508966.8834237986, 6651202.963987725, 92.19912625390799], + [508967.01306634734, 6651202.3683314, 92.06912625390798], + [508965.58228226186, 6651208.942219356, 98.465393600908], + [508966.8834237986, 6651202.963987725, 93.89792991290798], + [508966.8794906789, 6651202.982058856, 94.30874522490798], + [508967.01306634734, 6651202.3683314, 93.89792991290798], + [508965.9544509072, 6651207.232251374, 98.465393600908], + [508966.8671912891, 6651203.038569696, 94.729866652908], + [508966.0430439068, 6651206.825201521, 98.42765074190798], + [508967.0086088116, 6651202.388812016, 94.36352059990799], + [508966.8458912677, 6651203.136434885, 95.15595578790798], + [508965.96023040335, 6651207.2056968715, 99.074388760908], + [508966.1332846207, 6651206.41058107, 98.34897604890799], + [508966.8151556214, 6651203.277653044, 95.580862291908], + [508966.9946695031, 6651202.452857635, 94.840791551908], + [508966.223947104, 6651205.994022755, 98.22682292690799], + [508966.06063580315, 6651206.744373702, 99.03161351990799], + [508966.77480020275, 6651203.463070259, 95.997828993908], + [508966.3136522649, 6651205.58186296, 98.059708169908], + [508966.970529479, 6651202.563771514, 95.32369257190798], + [508966.72493141814, 6651203.692197635, 96.39977791090799], + [508966.40092039836, 6651205.180900342, 97.84743036090799], + [508966.6659677276, 6651203.963112514, 96.77965871290799], + [508966.16290861234, 6651206.274470524, 98.94244886790798], + [508966.4842393229, 6651204.798082781, 97.59121723790798], + [508966.6162038899, 6651204.1917576995, 97.046065027908], + [508966.56214279425, 6651204.440147088, 97.29377476790799], + [508966.9454234713, 6651202.679123707, 95.685398556908], + [508966.2400099091, 6651205.920220507, 98.84335337390799], + [508966.9141910603, 6651202.822624304, 96.043156402908], + [508966.316730942, 6651205.567717653, 98.71573061490798], + [508966.8768285154, 6651202.994290448, 96.39361261790799], + [508966.39237715246, 6651205.220153184, 98.559239322908], + [508966.83344164956, 6651203.193635966, 96.73335764490798], + [508966.46622916026, 6651204.880832368, 98.37403042090799], + [508966.78424949583, 6651203.419654489, 97.05902475490798], + [508966.5375624871, 6651204.553083894, 98.16077808590799], + [508966.72958310816, 6651203.670824957, 97.36739356290799], + [508966.6056690553, 6651204.240161103, 97.92068963890799], + [508966.6698792388, 6651203.945140663, 97.65549191390798], + [508966.7511020551, 6651216.042828602, 92.05518010288448], + [508966.8799371232, 6651215.446997104, 92.05518010288448], + [508966.8799371232, 6651215.446997104, 92.18518010288449], + [508966.7511020551, 6651216.042828602, 93.88398376188448], + [508966.755531827, 6651216.022341961, 94.34957444888448], + [508966.87993662886, 6651215.446999391, 93.88398376288448], + [508966.8808972811, 6651215.442556604, 94.08780504688448], + [508966.7693843142, 6651215.958277508, 94.82684540088448], + [508966.8888739774, 6651215.405666283, 94.50438433488448], + [508966.7933739819, 6651215.84733101, 95.30974642088448], + [508966.90550133825, 6651215.3287687, 94.92871145488448], + [508966.81832361646, 6651215.731944894, 95.67145240588448], + [508966.931317569, 6651215.209374783, 95.35502180588449], + [508966.84936149593, 6651215.588402097, 96.02921025188448], + [508966.9666361353, 6651215.046034829, 95.77683066488449], + [508966.88649132766, 6651215.41668547, 96.3796664668845], + [508967.0114996052, 6651214.838551968, 96.1871802078845], + [508966.9296079578, 6651215.2172813285, 96.71941149388448], + [508967.06564850465, 6651214.588126208, 96.57895990188449], + [508966.9784937174, 6651214.991196336, 97.04507860388448], + [508967.11202121794, 6651214.373663458, 96.85644176188448], + [508967.03281961463, 6651214.739952004, 97.35344741188449], + [508967.1629485123, 6651214.138136854, 97.1168824348845], + [508967.0921516176, 6651214.465555625, 97.64154576288448], + [508967.21799087565, 6651213.883579036, 97.35785208088448], + [508967.1559618669, 6651214.170448423, 97.9067434878845], + [508967.2766347778, 6651213.612364959, 97.57727108688448], + [508967.2236442322, 6651213.857433608, 98.1468319348845], + [508967.35943474923, 6651213.229434817, 97.8334842098845], + [508967.2945332585, 6651213.529588751, 98.3600842698845], + [508967.4461593317, 6651212.828354284, 98.04576201888449], + [508967.36792527785, 6651213.190168145, 98.54529317188448], + [508967.5353057627, 6651212.416073279, 98.21287677588448], + [508967.4431003248, 6651212.842501462, 98.7017844638845], + [508967.6254035534, 6651211.999392463, 98.33502989788448], + [508967.5193434995, 6651212.489894943, 98.82940722288448], + [508967.7150822017, 6651211.584650078, 98.41370459088448], + [508967.5959645697, 6651212.135540748, 98.92850271688448], + [508967.80312339845, 6651211.177480518, 98.45144744988448], + [508967.6976003712, 6651211.665499379, 99.01766736888449], + [508967.79738039436, 6651211.204040544, 99.06044260988449], + [508969.45832267724, 6651203.522578181, 92.05518010288448], + [508969.45832267724, 6651203.522578181, 92.18518010288449], + [508969.5871577454, 6651202.926746684, 92.05518010288448], + [508968.1652853203, 6651209.502567909, 98.45144744988448], + [508969.45832267724, 6651203.522578181, 93.88398376188448], + [508969.4544140551, 6651203.540654628, 94.29479907388448], + [508969.5871577454, 6651202.926746684, 93.88398376188448], + [508968.5351359076, 6651207.792097054, 98.45144744988448], + [508969.44219127216, 6651203.597182088, 94.71592050188448], + [508968.6231771042, 6651207.384927495, 98.41370459088448], + [508969.58272797347, 6651202.947233324, 94.34957444888448], + [508969.42102391826, 6651203.695076056, 95.1420096368845], + [508968.5408794061, 6651207.765534743, 99.06044260988449], + [508968.7128557526, 6651206.97018511, 98.33502989788448], + [508969.3904797095, 6651203.836335745, 95.56691614088449], + [508969.5688754862, 6651203.011297778, 94.82684540088448], + [508968.8029535432, 6651206.553504294, 98.21287677588448], + [508969.3503756451, 6651204.021807489, 95.98388284288448], + [508968.6406594292, 6651207.304075907, 99.01766736888449], + [508968.89209997427, 6651206.141223288, 98.04576201888449], + [508969.5448858186, 6651203.122244275, 95.30974642088448], + [508969.30081746896, 6651204.251002246, 96.3858317598845], + [508968.97882455675, 6651205.740142754, 97.8334842098845], + [508969.24222103466, 6651204.521996795, 96.7657125618845], + [508968.7422952308, 6651206.834034539, 98.92850271688448], + [508969.06162452814, 6651205.357212614, 97.57727108688448], + [508969.19276715175, 6651204.750709222, 97.03211887688448], + [508969.1390427766, 6651204.9991716575, 97.2798286168845], + [508969.51993618405, 6651203.2376303915, 95.67145240588448], + [508968.8189163009, 6651206.479680342, 98.82940722288448], + [508969.4888983046, 6651203.381173189, 96.02921025188448], + [508968.89515947574, 6651206.1270738235, 98.7017844638845], + [508969.4517684728, 6651203.5528898155, 96.3796664668845], + [508968.97033452266, 6651205.77940714, 98.54529317188448], + [508969.40865184274, 6651203.752293957, 96.71941149388448], + [508969.04372654203, 6651205.439986534, 98.3600842698845], + [508969.3597660831, 6651203.97837895, 97.04507860388448], + [508969.1146155682, 6651205.112141677, 98.1468319348845], + [508969.3054401859, 6651204.229623281, 97.35344741188449], + [508969.1822979336, 6651204.799126862, 97.9067434878845], + [508969.24610818294, 6651204.504019661, 97.64154576288448], + [508983.63057475275, 6651219.614809092, 91.95111912584724], + [508983.7541511217, 6651219.0178647665, 91.95111912584724], + [508983.7541511217, 6651219.0178647665, 92.08111912584725], + [508983.8639770783, 6651219.663112026, 91.94951967737245], + [508983.63057475275, 6651219.614809092, 93.77992278484724], + [508983.9874807321, 6651219.066152652, 91.94951967737245], + [508983.6348237134, 6651219.59428419, 94.24551347184725], + [508983.75415064755, 6651219.017867057, 93.77992278584725], + [508983.9874807321, 6651219.066152652, 92.07951967737247], + [508983.75507208856, 6651219.013415971, 93.98374406984725], + [508983.6481107796, 6651219.530100084, 94.72278442384724], + [508983.76272319775, 6651218.976456751, 94.40032335784724], + [508983.6711212539, 6651219.418946372, 95.20568544384724], + [508983.77867187466, 6651218.899415548, 94.82465047784726], + [508983.8639770783, 6651219.663112026, 93.77832333637247], + [508983.6950525118, 6651219.303344752, 95.56739142884726], + [508983.8034343567, 6651218.77979864, 95.25096082884724], + [508983.8682235387, 6651219.642586607, 94.24391402337245], + [508983.9874802582, 6651219.066154941, 93.77832333737246], + [508983.988401157, 6651219.061703744, 93.98214462137246], + [508983.7248235089, 6651219.159533859, 95.92514927484724], + [508983.8815027865, 6651219.578400882, 94.72118497537245], + [508983.8373113146, 6651218.6161536155, 95.67276968784725], + [508983.99604776414, 6651219.024743592, 94.39872390937245], + [508983.7604378013, 6651218.987496519, 96.27560548984725], + [508983.9044997209, 6651219.467244368, 95.20408599537247], + [508983.88034357893, 6651218.408283242, 96.08311923084725], + [508984.01198705647, 6651218.9477004465, 94.82305102937245], + [508983.8017945271, 6651218.787719951, 96.61535051684724], + [508983.92841689714, 6651219.351639832, 95.56579198037245], + [508984.0367349677, 6651218.828080523, 95.24936138037246], + [508983.93228226673, 6651218.157389765, 96.47489892484725], + [508983.8486849023, 6651218.561212704, 96.94101762684726], + [508983.95817037625, 6651219.207825315, 95.92354982637245], + [508983.9767621712, 6651217.9425264625, 96.75238078484726], + [508984.07059199165, 6651218.664431374, 95.67117023937246], + [508983.9007933632, 6651218.309499124, 97.24938643484727], + [508983.9937637125, 6651219.035783638, 96.27400604137247], + [508984.02561075106, 6651217.706559968, 97.01282145784725], + [508984.11359893484, 6651218.4565557595, 96.08151978237245], + [508983.95770359423, 6651218.034590257, 97.53748478584724], + [508984.03509610303, 6651218.836002034, 96.61375106837247], + [508984.078406434, 6651217.451526715, 97.25379110384725], + [508984.01890928164, 6651217.738931888, 97.80268251084725], + [508984.16550706077, 6651218.2056559585, 96.47329947637246], + [508984.13465665065, 6651217.179806095, 97.47321010984726], + [508984.0819588868, 6651218.609489076, 96.93941817837245], + [508984.2099607923, 6651217.99078724, 96.75078133637246], + [508984.08382903587, 6651217.425332457, 98.04277095784725], + [508984.134036686, 6651218.357769151, 97.24778698637246], + [508984.21407695103, 6651216.796160758, 97.72942323284725], + [508984.2587806285, 6651217.754814797, 97.01122200937246], + [508984.1518245636, 6651217.096875287, 98.25602329284725], + [508984.1909134298, 6651218.0828533545, 97.53588533737245], + [508984.29726167064, 6651216.39433113, 97.94170104184724], + [508984.3115452453, 6651217.4997751145, 97.25219165537246], + [508984.22222091927, 6651216.756820748, 98.44123219484725], + [508984.25208310236, 6651217.787187531, 97.80108306237247], + [508984.3827693853, 6651215.981280112, 98.10881579884726], + [508984.367762363, 6651217.228047645, 97.47161066137245], + [508984.294327524, 6651216.408504731, 98.59772348684724], + [508984.3169646564, 6651217.473580196, 98.04117150937248], + [508984.4691896277, 6651215.563821062, 98.23096892084726], + [508984.3674586585, 6651216.055239651, 98.72534624584725], + [508984.44713593076, 6651216.844392635, 97.72782378437245], + [508984.555207836, 6651215.148304069, 98.30964361384724], + [508984.38492017414, 6651217.145114744, 98.25442384437247], + [508984.4409522638, 6651215.700223631, 98.82444173984725], + [508984.5302717025, 6651216.4425528785, 97.94010159337245], + [508984.6396554291, 6651214.740374042, 98.34738647284725], + [508984.45527510694, 6651216.805051634, 98.43963274637245], + [508986.22729394847, 6651207.071174711, 91.95111912584724], + [508984.5384395666, 6651215.2293043705, 98.91360639184725], + [508986.22729394847, 6651207.071174711, 92.08111912584725], + [508984.6157291025, 6651216.029491446, 98.10721635037245], + [508984.52733928256, 6651216.456726837, 98.59612403837247], + [508984.6341468391, 6651214.766983673, 98.95638163284727], + [508986.3508703175, 6651206.474230385, 91.95111912584724], + [508984.7020984934, 6651215.612021874, 98.22936947237245], + [508984.60042738507, 6651216.103452851, 98.72374679737247], + [508984.7880660867, 6651215.196494405, 98.30804416537245], + [508984.673877745, 6651215.748427881, 98.82284229137247], + [508984.98703488056, 6651213.062333213, 98.34738647284725], + [508984.872463989, 6651214.788554094, 98.34578702437246], + [508986.4591683062, 6651207.119161429, 91.94951967737245], + [508984.77130768413, 6651215.277496749, 98.91200694337246], + [508986.22729394847, 6651207.071174711, 93.77992278484724], + [508986.4591683062, 6651207.119161429, 92.07951967737247], + [508984.8669586402, 6651214.815164397, 98.95478218437246], + [508986.5826719601, 6651206.522202054, 91.94951967737245], + [508986.22354486573, 6651207.089284918, 94.19073809684726], + [508986.3508703175, 6651206.474230385, 93.77992278484724], + [508986.21182098374, 6651207.145917953, 94.61185952484726], + [508985.34178916673, 6651211.348667727, 98.34738647284725], + [508986.3466213569, 6651206.494755287, 94.24551347184725], + [508986.191517624, 6651207.243994758, 95.03794865984725], + [508985.2196390345, 6651213.110470964, 98.34578702437246], + [508985.4262367599, 6651210.9407377, 98.30964361384724], + [508986.3333342907, 6651206.558939394, 94.72278442384724], + [508986.16222014715, 6651207.385518276, 95.46285516384725], + [508985.51225496817, 6651210.525220706, 98.23096892084726], + [508985.34729823115, 6651211.322055805, 98.95638163284727], + [508986.1237530224, 6651207.571336425, 95.87982186584726], + [508986.4591683062, 6651207.119161429, 93.77832333637247], + [508985.5986752106, 6651210.107761657, 98.10881579884726], + [508986.31032381643, 6651206.670093105, 95.20568544384724], + [508986.07621767704, 6651207.800959247, 96.28177078284725], + [508985.44300550356, 6651210.859735106, 98.91360639184725], + [508985.68418292527, 6651209.694710638, 97.94170104184724], + [508986.0200129907, 6651208.07245993, 96.66165158484725], + [508986.2863925585, 6651206.785694726, 95.56739142884726], + [508985.76736764493, 6651209.292881011, 97.72942323284725], + [508985.9725776816, 6651208.301599521, 96.92805789984725], + [508986.4554214295, 6651207.137272093, 94.18913864837245], + [508985.8467879453, 6651208.909235673, 97.47321010984726], + [508985.9210461901, 6651208.550526008, 97.17576763984725], + [508986.5826719601, 6651206.522202054, 93.77832333637247], + [508985.54049280647, 6651210.388815845, 98.82444173984725], + [508986.25662156136, 6651206.929505618, 95.92514927484724], + [508985.6139864117, 6651210.033799825, 98.72534624584725], + [508986.22100726893, 6651207.101542958, 96.27560548984725], + [508986.44370444614, 6651207.193906556, 94.61026007637246], + [508985.6871175462, 6651209.6805347465, 98.59772348684724], + [508986.17965054314, 6651207.3013195265, 96.61535051684724], + [508985.5741845753, 6651211.396762278, 98.34578702437246], + [508986.57842549967, 6651206.542727474, 94.24391402337245], + [508985.75922415097, 6651209.332218729, 98.44123219484725], + [508986.132760168, 6651207.527826774, 96.94101762684726], + [508986.4234130333, 6651207.291985833, 95.03634921137247], + [508985.8296205066, 6651208.992164191, 98.25602329284725], + [508986.080651707, 6651207.779540353, 97.24938643484727], + [508985.89761603443, 6651208.663707021, 98.04277095784725], + [508986.02374147606, 6651208.05444922, 97.53748478584724], + [508985.96253578865, 6651208.35010759, 97.80268251084725], + [508985.6585824776, 6651210.988821967, 98.30804416537245], + [508986.5651462519, 6651206.606913199, 94.72118497537245], + [508986.39413279586, 6651207.43351292, 95.46125571537246], + [508985.7445500709, 6651210.573294497, 98.22936947237245], + [508985.5796903981, 6651211.370149684, 98.95478218437246], + [508986.35568830586, 6651207.619335752, 95.87822241737246], + [508985.8309194617, 6651210.155824927, 98.10721635037245], + [508986.54214931745, 6651206.718069713, 95.20408599537247], + [508986.3081809314, 6651207.848964362, 96.28017133437245], + [508985.6753413542, 6651210.907817331, 98.91200694337246], + [508985.9163768618, 6651209.742763494, 97.94010159337245], + [508986.51823214133, 6651206.833674248, 95.56579198037245], + [508986.2520093172, 6651208.120471891, 96.66005213637247], + [508985.99951263354, 6651209.340923736, 97.72782378437245], + [508986.20460192004, 6651208.349617258, 96.92645845137245], + [508986.0788862013, 6651208.957268728, 97.47161066137245], + [508986.1531007509, 6651208.59855002, 97.17416819137247], + [508985.77277129336, 6651210.4368862, 98.82284229137247], + [508986.48847866204, 6651206.977488765, 95.92354982637245], + [508985.8462216534, 6651210.08186123, 98.72374679737247], + [508986.45288532594, 6651207.1495304415, 96.27400604137247], + [508985.91930975585, 6651209.728587244, 98.59612403837247], + [508986.4115529353, 6651207.349312046, 96.61375106837247], + [508985.9913739314, 6651209.380262447, 98.43963274637245], + [508986.36469015153, 6651207.575825005, 96.93941817837245], + [508986.0617288643, 6651209.040199336, 98.25442384437247], + [508986.3126123523, 6651207.827544929, 97.24778698637246], + [508986.129684382, 6651208.711733885, 98.04117150937248], + [508986.2557356087, 6651208.102460726, 97.53588533737245], + [508986.19456593593, 6651208.398126549, 97.80108306237247], + [509001.0085308428, 6651223.13027511, 91.82009846517153], + [509001.1266932131, 6651222.532235561, 91.82009846517153], + [509001.1266932131, 6651222.532235561, 91.95009846517154], + [509001.0085308428, 6651223.13027511, 93.64890212417153], + [509001.12669275975, 6651222.532237856, 93.64890212517152], + [509001.0125936525, 6651223.1097125495, 94.11449281117152], + [509001.1275738315, 6651222.527778604, 93.85272340917152], + [509001.02529859956, 6651223.045410684, 94.59176376317151], + [509001.1348897383, 6651222.490751574, 94.26930269717153], + [509001.04730096296, 6651222.934053037, 95.07466478317153], + [509001.1501396884, 6651222.413569022, 94.69362981717151], + [509001.0701837696, 6651222.818239321, 95.43637076817151], + [509001.17381730245, 6651222.2937326515, 95.11994016817152], + [509001.09865047096, 6651222.6741645755, 95.79412861417151], + [509001.20621007856, 6651222.129787385, 95.54174902717152], + [509001.1327044672, 6651222.501811597, 96.14458482917154], + [509001.2473570583, 6651221.921535629, 95.95209857017151], + [509001.17224931536, 6651222.301668496, 96.48432985617153], + [509001.2970202626, 6651221.670181833, 96.34387826417154], + [509001.2170853785, 6651222.074745672, 96.80999696617151], + [509001.33955146, 6651221.454924319, 96.62136012417152], + [509001.266910918, 6651221.822570269, 97.11836577417152], + [509001.3862599369, 6651221.218524894, 96.88180079717152], + [509001.32132785744, 6651221.547157025, 97.40646412517152], + [509001.43674259057, 6651220.963023727, 97.12277044317152], + [509001.3798520653, 6651221.250956206, 97.67166185017152], + [509001.49052843155, 6651220.690804577, 97.34218944917151], + [509001.4419276231, 6651220.936781408, 97.91175029717152], + [509001.5664692527, 6651220.30645536, 97.59840257217152], + [509001.5069442019, 6651220.607721613, 98.12500263217153], + [509001.64600957034, 6651219.903888489, 97.81068038117152], + [509001.57425642596, 6651220.267043172, 98.31021153417151], + [509001.72777111037, 6651219.4900796395, 97.97779513817152], + [509001.6432039715, 6651219.918088094, 98.46670282617151], + [509001.8104051995, 6651219.071854672, 98.09994826017152], + [509001.71313116123, 6651219.564174876, 98.59432558517153], + [509003.4914852917, 6651210.563626738, 91.82009846517153], + [509001.8926548681, 6651218.655575323, 98.17862295317153], + [509001.7834049415, 6651219.2085075015, 98.69342107917153], + [509003.4914852917, 6651210.563626738, 91.95009846517154], + [509001.9734027315, 6651218.246896861, 98.21636581217152], + [509003.609647662, 6651209.965587189, 91.82009846517153], + [509001.87662123254, 6651218.736724238, 98.78258573117154], + [509001.96813547803, 6651218.273555313, 98.82536097217152], + [509002.3055631575, 6651216.565777306, 98.21636581217152], + [509003.4914852917, 6651210.563626738, 93.64890212417153], + [509003.4879004598, 6651210.581770174, 94.05971743617151], + [509003.609647662, 6651209.965587189, 93.64890212417153], + [509003.47669021226, 6651210.638507114, 94.48083886417152], + [509003.60558485246, 6651209.98614975, 94.11449281117152], + [509003.45727636217, 6651210.736763861, 94.90692799917151], + [509002.6447753198, 6651214.848967734, 98.21636581217152], + [509003.59287990525, 6651210.050451616, 94.59176376317151], + [509003.42926243576, 6651210.878547035, 95.33183450317152], + [509002.7255231832, 6651214.440289271, 98.17862295317153], + [509003.39248059236, 6651211.064706106, 95.74880120517152], + [509003.57087754185, 6651210.161809263, 95.07466478317153], + [509002.8077728518, 6651214.024009922, 98.09994826017152], + [509002.65004302684, 6651214.822306987, 98.82536097217152], + [509003.34702781594, 6651211.294750222, 96.15075012217152], + [509002.8904069409, 6651213.605784956, 97.97779513817152], + [509003.5479947352, 6651210.277622979, 95.43637076817151], + [509003.29328551056, 6651211.56674903, 96.53063092417153], + [509002.9721684809, 6651213.191976106, 97.81068038117152], + [509002.74155727227, 6651214.35913806, 98.78258573117154], + [509003.24792838754, 6651211.796309028, 96.79703723917152], + [509003.0517087985, 6651212.789409236, 97.59840257217152], + [509003.19865454, 6651212.045692224, 97.04474697917152], + [509003.1276496197, 6651212.405060018, 97.34218944917151], + [509003.51952803385, 6651210.421697723, 95.79412861417151], + [509002.83477356343, 6651213.887354798, 98.69342107917153], + [509003.4854740376, 6651210.594050703, 96.14458482917154], + [509002.9050473436, 6651213.5316874245, 98.59432558517153], + [509003.44592918945, 6651210.794193803, 96.48432985617153], + [509002.9749745333, 6651213.177774205, 98.46670282617151], + [509003.4010931264, 6651211.021116628, 96.80999696617151], + [509003.0439220788, 6651212.828819128, 98.31021153417151], + [509003.3512675868, 6651211.27329203, 97.11836577417152], + [509003.1112343029, 6651212.488140686, 98.12500263217153], + [509003.2968506475, 6651211.548705275, 97.40646412517152], + [509003.1762508817, 6651212.15908089, 97.91175029717152], + [509003.2383264395, 6651211.8449060945, 97.67166185017152], + [509003.1429632246, 6651223.550769676, 91.80234087613896], + [509003.2604606253, 6651222.952599125, 91.80234087613896], + [509003.2604606253, 6651222.952599125, 91.93234087613897], + [509003.1429632246, 6651223.550769676, 93.63114453513896], + [509003.2604601744, 6651222.952601421, 93.63114453613898], + [509003.1470031704, 6651223.530202612, 94.09673522213897], + [509003.2613362879, 6651222.948141192, 93.83496582013896], + [509003.1596366192, 6651223.465886662, 94.57400617413896], + [509003.2686110237, 6651222.911106051, 94.25154510813896], + [509003.1815151624, 6651223.3545046225, 95.05690719413896], + [509003.2837751533, 6651222.833906592, 94.67587222813896], + [509003.20426919387, 6651223.238665534, 95.41861317913896], + [509003.30731951946, 6651222.714043971, 95.10218257913895], + [509003.2325756962, 6651223.094559231, 95.77637102513896], + [509003.33953000215, 6651222.550062792, 95.52399143813896], + [509003.2664380505, 6651222.922168497, 96.12682724013897], + [509003.3804454234, 6651222.341765418, 95.93434098113897], + [509003.30576035636, 6651222.721981554, 96.46657226713896], + [509003.42982914345, 6651222.090356562, 96.32612067513897], + [509003.3503441003, 6651222.495009021, 96.79223937713896], + [509003.4721209926, 6651221.875051895, 96.60360253513898], + [509003.399889242, 6651222.24277838, 97.10060818513897], + [509003.5185666132, 6651221.638600685, 96.86404320813898], + [509003.4539999451, 6651221.967304803, 97.38870653613895], + [509003.56876517105, 6651221.383043551, 97.10501285413896], + [509003.5121948025, 6651221.671039101, 97.65390426113898], + [509003.6222483272, 6651221.11076477, 97.32443186013896], + [509003.57392102433, 6651221.356795484, 97.89399270813898], + [509003.6977617845, 6651220.726331361, 97.58064498313898], + [509003.6385717163, 6651221.027663606, 98.10724504313896], + [509003.77685448155, 6651220.323676307, 97.79292279213897], + [509003.7055051346, 6651220.686910538, 98.29245394513896], + [509003.8581559009, 6651219.90977681, 97.96003754913897], + [509003.77406467154, 6651220.337879022, 98.44894523713897], + [509003.9403249591, 6651219.49146023, 98.08219067113896], + [509003.8435983395, 6651219.983888276, 98.57656799613896], + [509005.6119446172, 6651210.981368539, 91.80234087613896], + [509004.02211176, 6651219.075089693, 98.16086536413896], + [509005.6119446172, 6651210.981368539, 91.93234087613897], + [509003.9134766474, 6651219.628142994, 98.67566349013896], + [509004.1024052073, 6651218.666321708, 98.19860822313896], + [509005.7294420178, 6651210.383197987, 91.80234087613896], + [509004.0061683553, 6651219.156256384, 98.76482814213897], + [509004.0971675958, 6651218.692985999, 98.80760338313898], + [509004.43269636977, 6651216.984833899, 98.19860822313896], + [509005.6119446172, 6651210.981368539, 93.63114453513896], + [509005.60837995925, 6651210.999515948, 94.04195984713895], + [509005.7294420178, 6651210.383197987, 93.63114453513896], + [509005.5972327985, 6651211.056265317, 94.46308127513896], + [509005.7254020721, 6651210.403765052, 94.09673522213897], + [509005.5779282015, 6651211.154543589, 94.88917041013897], + [509004.7699995841, 6651215.267648254, 98.19860822313896], + [509005.7127686232, 6651210.468081003, 94.57400617413896], + [509005.55007192615, 6651211.296357821, 95.31407691413897], + [509004.85029303154, 6651214.858880268, 98.16086536413896], + [509005.51349707606, 6651211.482557669, 95.73104361613896], + [509005.6908900801, 6651210.579463043, 95.05690719413896], + [509004.93207983236, 6651214.442509731, 98.08219067113896], + [509004.7752376467, 6651215.2409816645, 98.80760338313898], + [509005.4683000892, 6651211.712652177, 96.13299253313897], + [509005.0142488905, 6651214.024193152, 97.96003754913897], + [509005.66813604854, 6651210.69530213, 95.41861317913896], + [509005.4148602237, 6651211.984710569, 96.51287333513896], + [509005.09555030987, 6651213.610293655, 97.79292279213897], + [509005.3697583521, 6651212.214320851, 96.77927965013896], + [509004.8662368872, 6651214.777711282, 98.76482814213897], + [509005.174643007, 6651213.207638601, 97.58064498313898], + [509005.32076179766, 6651212.463758675, 97.02698939013897], + [509005.6398295462, 6651210.839408435, 95.77637102513896], + [509005.25015646423, 6651212.823205192, 97.32443186013896], + [509004.958928595, 6651214.305824672, 98.67566349013896], + [509005.605967192, 6651211.011799168, 96.12682724013897], + [509005.028806903, 6651213.95007939, 98.57656799613896], + [509005.56664488616, 6651211.211986111, 96.46657226713896], + [509005.0983405709, 6651213.596088643, 98.44894523713897], + [509005.5220611422, 6651211.438958645, 96.79223937713896], + [509005.1669001078, 6651213.247057126, 98.29245394513896], + [509005.4725160005, 6651211.691189285, 97.10060818513897], + [509005.2338335261, 6651212.90630406, 98.10724504313896], + [509005.4184052974, 6651211.9666628605, 97.38870653613895], + [509005.29848421813, 6651212.577172182, 97.89399270813898], + [509005.36021044, 6651212.262928563, 97.65390426113898], + [509018.18339330686, 6651226.444040789, 91.66691646628368], + [509018.296204951, 6651225.844968856, 91.66691646628368], + [509018.296204951, 6651225.844968856, 91.7969164662837], + [509018.18339330686, 6651226.444040789, 93.49572012528368], + [509018.29620451824, 6651225.844971155, 93.49572012628369], + [509018.18727214093, 6651226.423442733, 93.96131081228368], + [509018.29704569257, 6651225.840504205, 93.69954141028369], + [509018.1994017721, 6651226.359029864, 94.43858176428368], + [509018.3040303144, 6651225.803413256, 94.11612069828368], + [509018.3185897037, 6651225.7260974655, 94.54044781828368], + [509018.2204078064, 6651226.247479983, 94.92148278428368], + [509018.2422544149, 6651226.131466338, 95.28318876928368], + [509018.34119512845, 6651225.606054223, 94.9667581692837], + [509018.2694320635, 6651225.98714288, 95.64094661528368], + [509018.3721210681, 6651225.441825942, 95.38856702828369], + [509018.30194399855, 6651225.814492373, 95.9914028302837], + [509018.41140479635, 6651225.233214686, 95.79891657128368], + [509018.3396981443, 6651225.614003768, 96.3311478572837], + [509018.4588191103, 6651224.981426982, 96.19069626528369], + [509018.3825039037, 6651225.386689211, 96.65681496728368], + [509018.4994243749, 6651224.765797873, 96.46817812528369], + [509018.43007320195, 6651225.134078483, 96.96518377528369], + [509018.54401776, 6651224.528990356, 96.72861879828369], + [509018.4820259885, 6651224.858189798, 97.25328212628368], + [509018.5922144164, 6651224.273048123, 96.96958844428369], + [509018.53790005494, 6651224.561477653, 97.5184798512837], + [509018.6435646825, 6651224.000359045, 97.18900745028368], + [509018.597164656, 6651224.246760503, 97.7585682982837], + [509018.71606668865, 6651223.615346335, 97.44522057328368], + [509018.65923710045, 6651223.917132658, 97.9718206332837], + [509018.7920051959, 6651223.212084521, 97.65749838228368], + [509018.72350123676, 6651223.57586611, 98.15702953528368], + [509018.87006434234, 6651222.7975613205, 97.82461313928368], + [509018.7893266425, 6651223.226308638, 98.3135208272837], + [509020.55391256086, 6651213.855698859, 91.66691646628368], + [509020.55391256086, 6651213.855698859, 91.7969164662837], + [509018.9489565264, 6651222.378614381, 97.94676626128368], + [509018.8560873314, 6651222.871784465, 98.4411435862837], + [509020.666724205, 6651213.256626926, 91.66691646628368], + [509019.0274816975, 6651221.961616416, 98.02544095428368], + [509018.9231789163, 6651222.51550311, 98.5402390802837], + [509019.1045730695, 6651221.55223246, 98.06318381328369], + [509019.01217411034, 6651222.042905418, 98.62940373228369], + [509019.0995443321, 6651221.578936933, 98.67217897328369], + [509020.55391256086, 6651213.855698859, 93.49572012528368], + [509019.4216923326, 6651219.868210822, 98.06318381328369], + [509020.55049006024, 6651213.873873615, 93.90653543728368], + [509020.666724205, 6651213.256626926, 93.49572012528368], + [509020.5397874445, 6651213.930708499, 94.32765686528369], + [509020.662845371, 6651213.277224983, 93.96131081228368], + [509020.5212527083, 6651214.029134865, 94.7537460002837], + [509020.65071573976, 6651213.341637852, 94.43858176428368], + [509020.4945073317, 6651214.171162796, 95.17865250428369], + [509019.74554400943, 6651218.148437555, 98.06318381328369], + [509020.6297097055, 6651213.453187733, 94.92148278428368], + [509020.4593910742, 6651214.35764323, 95.59561920628369], + [509019.8226353814, 6651217.7390536, 98.02544095428368], + [509019.9011605525, 6651217.322055635, 97.94676626128368], + [509020.41599652776, 6651214.588084466, 95.99756812328368], + [509020.60786309704, 6651213.569201377, 95.28318876928368], + [509019.75057317986, 6651218.121730783, 98.67217897328369], + [509019.9800527366, 6651216.903108694, 97.82461313928368], + [509020.364687826, 6651214.860552821, 96.3774489252837], + [509020.58068544837, 6651213.713524835, 95.64094661528368], + [509020.3213846017, 6651215.090509103, 96.64385524028368], + [509020.058111883, 6651216.488585494, 97.65749838228368], + [509020.2743420132, 6651215.340322805, 96.8915649802837], + [509020.13405039016, 6651216.08532368, 97.44522057328368], + [509020.2065523964, 6651215.70031097, 97.18900745028368], + [509019.83794340165, 6651217.657762299, 98.62940373228369], + [509020.5481735133, 6651213.886175345, 95.9914028302837], + [509019.9269385956, 6651217.185164605, 98.5402390802837], + [509020.51041936764, 6651214.086663947, 96.3311478572837], + [509019.9940301805, 6651216.828883251, 98.4411435862837], + [509020.4676136083, 6651214.313978504, 96.65681496728368], + [509020.06079086935, 6651216.474359077, 98.3135208272837], + [509020.4200443099, 6651214.5665892325, 96.96518377528369], + [509020.1266162752, 6651216.124801606, 98.15702953528368], + [509020.3680915234, 6651214.842477918, 97.25328212628368], + [509020.1908804115, 6651215.783535059, 97.9718206332837], + [509020.31221745705, 6651215.139190063, 97.5184798512837], + [509020.2529528559, 6651215.453907212, 97.7585682982837], + [509022.6943816497, 6651227.288031666, 91.62279150477926], + [509022.8057879224, 6651226.688696793, 91.62279150477926], + [509022.8057879224, 6651226.688696793, 91.75279150477925], + [509022.6943816497, 6651227.288031666, 93.45159516377925], + [509022.805787495, 6651226.688699093, 93.45159516477925], + [509022.69821216253, 6651227.267424568, 93.91718585077925], + [509022.8066181902, 6651226.684230181, 93.65541644877926], + [509022.71019068663, 6651227.202983428, 94.39445680277926], + [509022.8135157998, 6651226.647122953, 94.07199573677924], + [509022.82789381297, 6651226.569773227, 94.49632285677924], + [509022.7309350344, 6651227.091384585, 94.87735782277925], + [509022.7525094849, 6651226.975320023, 95.23906380777925], + [509022.8502176265, 6651226.449677298, 94.92263320777924], + [509022.77934856294, 6651226.83093322, 95.59682165377924], + [509022.8807583006, 6651226.285376933, 95.34444206677927], + [509022.8114554747, 6651226.658206931, 95.94727786877925], + [509022.91955264466, 6651226.076674115, 95.75479160977925], + [509022.8487392913, 6651226.457630331, 96.28702289577924], + [509022.96637628623, 6651225.824775898, 96.14657130377927], + [509022.8910117901, 6651226.230216002, 96.61269000577924], + [509023.0064757034, 6651225.609052147, 96.42405316377925], + [509022.93798848527, 6651225.977494401, 96.92105881377925], + [509023.0505135583, 6651225.372140692, 96.68449383677925], + [509022.9892940606, 6651225.701484624, 97.20915716477926], + [509023.09810979606, 6651225.1160861235, 96.92546348277926], + [509023.0444720656, 6651225.4046422485, 97.47435488977925], + [509023.1488203569, 6651224.843277358, 97.14488248877925], + [509023.10299836716, 6651225.0897869645, 97.71444333677925], + [509023.2204191562, 6651224.45809566, 97.40109561177925], + [509023.1642975329, 6651224.760014442, 97.92769567177925], + [509023.2954116456, 6651224.054656851, 97.61337342077925], + [509023.22776108695, 6651224.418598108, 98.11290457377926], + [509023.3724983561, 6651223.639951711, 97.78048817777925], + [509025.03536972974, 6651214.694164551, 91.62279150477926], + [509023.2927664609, 6651224.068887212, 98.26939586577925], + [509025.03536972974, 6651214.694164551, 91.75279150477925], + [509023.4504077264, 6651223.220820889, 97.90264129977925], + [509025.1467760023, 6651214.094829679, 91.62279150477926], + [509023.35869546636, 6651223.714207433, 98.39701862477925], + [509023.5279546559, 6651222.803639899, 97.98131599277926], + [509023.4249512456, 6651223.357769702, 98.49611411877925], + [509023.6040856482, 6651222.394076259, 98.01905885177926], + [509023.5128377658, 6651222.88496458, 98.58527877077927], + [509023.5991195571, 6651222.420792453, 98.62805401177926], + [509025.03536972974, 6651214.694164551, 93.45159516377925], + [509023.9172543405, 6651220.7093154825, 98.01905885177926], + [509025.0319898655, 6651214.712347284, 93.86241047577924], + [509025.1467760023, 6651214.094829679, 93.45159516377925], + [509025.02142057946, 6651214.769207114, 94.28353190377925], + [509025.14294548956, 6651214.115436777, 93.91718585077925], + [509025.0031167431, 6651214.86767668, 94.70962103877925], + [509025.1309669654, 6651214.179877915, 94.39445680277926], + [509024.9767045519, 6651215.009766949, 95.13452754277927], + [509024.23707157624, 6651218.988787385, 98.01905885177926], + [509025.11022261763, 6651214.291476759, 94.87735782277925], + [509024.9420257615, 6651215.196329231, 95.55149424477925], + [509024.31320256856, 6651218.579223745, 97.98131599277926], + [509025.08864816726, 6651214.4075413225, 95.23906380777925], + [509024.89917181066, 6651215.426871612, 95.95344316177925], + [509024.39074949804, 6651218.162042755, 97.90264129977925], + [509024.84850229626, 6651215.6994595565, 96.33332396377925], + [509024.2420380949, 6651218.962068891, 98.62805401177926], + [509024.46865886834, 6651217.742911933, 97.78048817777925], + [509025.0618090891, 6651214.551928124, 95.59682165377924], + [509024.80573852983, 6651215.929516769, 96.59973027877926], + [509024.54574557877, 6651217.328206794, 97.61337342077925], + [509024.75928198284, 6651216.179440118, 96.84744001877925], + [509024.62073806825, 6651216.924767983, 97.40109561177925], + [509024.69233686756, 6651216.539586286, 97.14488248877925], + [509025.02970217733, 6651214.724654413, 95.94727786877925], + [509024.32831988623, 6651218.497896764, 98.58527877077927], + [509024.99241836084, 6651214.925231013, 96.28702289577924], + [509024.41620640643, 6651218.025091642, 98.49611411877925], + [509024.95014586195, 6651215.152645342, 96.61269000577924], + [509024.48246218567, 6651217.668653911, 98.39701862477925], + [509024.90316916676, 6651215.405366943, 96.92105881377925], + [509024.54839119123, 6651217.313974132, 98.26939586577925], + [509024.8518635915, 6651215.68137672, 97.20915716477926], + [509024.6133965651, 6651216.964263236, 98.11290457377926], + [509024.79668558645, 6651215.978219096, 97.47435488977925], + [509024.6768601193, 6651216.622846902, 97.92769567177925], + [509024.7381592849, 6651216.29307438, 97.71444333677925], + [509032.4840949547, 6651229.082029021, 91.52147764848303], + [509032.5924513005, 6651228.482135238, 91.52147764848303], + [509032.5924513005, 6651228.482135238, 91.65147764848305], + [509032.4840949547, 6651229.082029021, 93.35028130748304], + [509032.59245088475, 6651228.48213754, 93.35028130848303], + [509032.48782060103, 6651229.061402706, 93.81587199448303], + [509032.5932588384, 6651228.477664462, 93.55410259248303], + [509032.49947119365, 6651228.996901471, 94.29314294648303], + [509032.59996761486, 6651228.44052263, 93.97068188048304], + [509032.61395200656, 6651228.363100773, 94.39500900048303], + [509032.5196476314, 6651228.885198559, 94.77604396648304], + [509032.5406314463, 6651228.769025758, 95.13774995148303], + [509032.6356646696, 6651228.2428928455, 94.82131935148304], + [509032.5667357613, 6651228.624504308, 95.49550779748303], + [509032.66536924336, 6651228.078439265, 95.24312821048304], + [509032.5979636944, 6651228.451616945, 95.84596401248305], + [509032.7031015295, 6651227.869541819, 95.65347775348303], + [509032.63422680617, 6651228.250853297, 96.18570903948304], + [509032.74864329817, 6651227.617408697, 96.04525744748305], + [509032.67534202704, 6651228.0232268935, 96.51137614948303], + [509032.78764492896, 6651227.401483771, 96.32273930748303], + [509032.7210326592, 6651227.7702696165, 96.81974495748304], + [509032.8304771764, 6651227.164351385, 96.58317998048304], + [509032.7709336614, 6651227.494002446, 97.10784330848304], + [509032.87677039014, 6651226.908058032, 96.82414962648303], + [509032.8246010793, 6651227.19688325, 97.37304103348303], + [509032.9260926674, 6651226.634994861, 97.04356863248303], + [509032.8815251288, 6651226.88173435, 97.61312948048304], + [509032.99573133385, 6651226.249453962, 97.29978175548302], + [509032.9411461307, 6651226.551654297, 97.82638181548305], + [509033.0686707826, 6651225.845638924, 97.51205956448302], + [509034.76099470054, 6651216.476417507, 91.52147764848303], + [509033.0028722674, 6651226.209919576, 98.01159071748303], + [509034.76099470054, 6651216.476417507, 91.65147764848305], + [509033.14364711975, 6651225.430547052, 97.67917432148303], + [509034.8693510464, 6651215.876523727, 91.52147764848303], + [509033.066098014, 6651225.859882557, 98.16808200948303], + [509033.21942359506, 6651225.011025371, 97.80132744348303], + [509033.13022210647, 6651225.504872022, 98.29570476848305], + [509033.29484755197, 6651224.59345534, 97.88000213648304], + [509033.19466402655, 6651225.148101895, 98.39480026248305], + [509033.3688943351, 6651224.183509762, 97.91774499548303], + [509033.28014451114, 6651224.674855858, 98.48396491448305], + [509034.76099470054, 6651216.476417507, 93.35028130748304], + [509033.3640641989, 6651224.210250868, 98.52674015548304], + [509034.8693510464, 6651215.876523727, 93.35028130748304], + [509034.7577073656, 6651216.494617197, 93.76109661948303], + [509033.6734895281, 6651222.497177863, 97.91774499548303], + [509034.74742743094, 6651216.551530052, 94.18221804748303], + [509034.8656254, 6651215.89715004, 93.81587199448303], + [509034.7296246917, 6651216.650091445, 94.60830718248303], + [509034.85397480737, 6651215.961651274, 94.29314294648303], + [509034.70393557695, 6651216.792314221, 95.03321368648304], + [509034.8337983696, 6651216.073354189, 94.77604396648304], + [509033.98455125, 6651220.775045289, 97.91774499548303], + [509034.6702061745, 6651216.979050481, 95.45018038848303], + [509034.05859803315, 6651220.3650997095, 97.88000213648304], + [509034.8128145547, 6651216.189526988, 95.13774995148303], + [509034.62852541974, 6651217.209807852, 95.85212930548303], + [509034.13402199006, 6651219.947529678, 97.80132744348303], + [509034.57924306527, 6651217.482650001, 96.23201010748305], + [509034.7867102397, 6651216.33404844, 95.49550779748303], + [509034.20979846537, 6651219.528007996, 97.67917432148303], + [509034.53765002603, 6651217.712921752, 96.49841642248303], + [509033.9893818021, 6651220.748301878, 98.52674015548304], + [509034.49246530223, 6651217.963078165, 96.74612616248305], + [509034.2847748025, 6651219.112916124, 97.51205956448302], + [509034.4273529177, 6651218.323560188, 97.04356863248303], + [509034.7554823066, 6651216.506935802, 95.84596401248305], + [509034.35771425127, 6651218.7091010865, 97.29978175548302], + [509034.0733014899, 6651220.283696888, 98.48396491448305], + [509034.7192191949, 6651216.707699451, 96.18570903948304], + [509034.1587819745, 6651219.810450851, 98.39480026248305], + [509034.678103974, 6651216.935325854, 96.51137614948303], + [509034.2232238946, 6651219.453680726, 98.29570476848305], + [509034.63241334184, 6651217.1882831305, 96.81974495748304], + [509034.287347987, 6651219.098670189, 98.16808200948303], + [509034.58251233964, 6651217.4645503005, 97.10784330848304], + [509034.3505737336, 6651218.7486331705, 98.01159071748303], + [509034.52884492173, 6651217.761669496, 97.37304103348303], + [509034.4122998704, 6651218.406898449, 97.82638181548305], + [509034.47192087234, 6651218.076818396, 97.61312948048304], + [510538.3475552979, 6651106.192133014, 67.73428539412009], + [510538.3807739694, 6651106.800828477, 67.73428539412009], + [510538.3807739694, 6651106.800828477, 67.86428539412009], + [510538.3475552979, 6651106.192133014, 69.5630890531201], + [510538.3486974647, 6651106.213061959, 70.02867974012008], + [510538.3807739694, 6651106.800828477, 69.5630890531201], + [510538.3522691726, 6651106.278509561, 70.5059506921201], + [510538.3817817637, 6651106.819295193, 69.97390436512009], + [510538.3849332706, 6651106.877043078, 70.39502579312008], + [510538.3584546382, 6651106.391851387, 70.9888517121201], + [510538.3903910344, 6651106.977050571, 70.8211149281201], + [510538.36488762056, 6651106.509728681, 71.35055769712011], + [510538.37289038824, 6651106.65637056, 71.70831554312011], + [510538.3982665147, 6651107.121360049, 71.24602143212009], + [510538.38246389723, 6651106.831794538, 72.05877175812009], + [510538.4086068961, 6651107.310836116, 71.66298813412008], + [510538.3935810348, 6651107.035503805, 72.3985167851201], + [510538.42138491385, 6651107.544979176, 72.0649370511201], + [510538.40618567745, 6651107.266469957, 72.72418389512009], + [510538.4364933446, 6651107.82182448, 72.44481785312009], + [510538.4201929983, 6651107.52313864, 73.0325527031201], + [510538.4492444714, 6651108.055474795, 72.71122416812008], + [510538.43549108715, 6651107.80345922, 73.32065105412009], + [510538.4630966966, 6651108.30930152, 72.95893390812009], + [510538.4519438414, 6651108.104937769, 73.58584877912008], + [510538.4830581202, 6651108.675072559, 73.2563763781201], + [510538.4693949772, 6651108.424710556, 73.82593722612009], + [510538.5044071604, 6651109.066270138, 73.51258950112009], + [510538.48767291434, 6651108.759633563, 74.0391895611201], + [510538.52676811744, 6651109.476009977, 73.72486731012009], + [510538.50659622013, 6651109.10638224, 74.2243984631201], + [510538.5497535208, 6651109.897192105, 73.8919820671201], + [510538.5259792594, 6651109.461555026, 74.3808897551201], + [510538.54563770344, 6651109.821774298, 74.50851251412008], + [510538.57298422157, 6651110.322869036, 74.0141351891201], + [510538.5653935836, 6651110.18377898, 74.6076080081201], + [510538.59610685124, 6651110.746565684, 74.0928098821201], + [510538.61880728236, 6651111.16252601, 74.13055274112008], + [510538.5915992306, 6651110.663968514, 74.69677266012009], + [510538.6173263859, 6651111.135390218, 74.7395479011201], + [510539.0455816504, 6651118.982694897, 67.73428539412009], + [510538.71416909155, 6651112.909925829, 74.13055274112008], + [510539.0455816504, 6651118.982694897, 67.86428539412009], + [510539.0788003219, 6651119.59139036, 67.73428539412009], + [510539.0455817779, 6651118.982697234, 69.56308905412008], + [510538.8075484649, 6651114.6209997, 74.13055274112008], + [510539.0453340844, 6651118.978158525, 69.76691033812008], + [510538.83024889615, 6651115.036960028, 74.0928098821201], + [510539.0432773831, 6651118.940471746, 70.18348962612009], + [510539.0788003219, 6651119.59139036, 69.5630890531201], + [510538.8090292339, 6651114.648133156, 74.7395479011201], + [510538.8533715257, 6651115.4606566755, 74.0141351891201], + [510539.0389902054, 6651118.861913948, 70.6078167461201], + [510539.07765815506, 6651119.570461417, 70.02867974012008], + [510538.8766022266, 6651115.886333606, 73.8919820671201], + [510538.83475638926, 6651115.119554861, 74.69677266012009], + [510539.03233378095, 6651118.739942323, 71.03412709712009], + [510538.8995876299, 6651116.307515735, 73.72486731012009], + [510539.02322728635, 6651118.573075869, 71.45593595612009], + [510539.07408644725, 6651119.505013815, 70.5059506921201], + [510538.86096203624, 6651115.599744395, 74.6076080081201], + [510538.92194858694, 6651116.717255572, 73.51258950112009], + [510539.0116597458, 6651118.361113467, 71.8662854991201], + [510538.9432976272, 6651117.108453153, 73.2563763781201], + [510538.99769806187, 6651118.105281029, 72.25806519312009], + [510538.8807179163, 6651115.961749077, 74.50851251412008], + [510538.95841829706, 6651117.385522725, 73.03695737212009], + [510538.98574137996, 6651117.88618804, 72.5355470531201], + [510538.97261035064, 6651117.6455764305, 72.79598772612009], + [510539.06790098164, 6651119.391671988, 70.9888517121201], + [510538.90037636046, 6651116.321968349, 74.3808897551201], + [510539.0614679993, 6651119.273794693, 71.35055769712011], + [510538.9197593997, 6651116.677141135, 74.2243984631201], + [510539.05346523155, 6651119.1271528145, 71.70831554312011], + [510538.9386827055, 6651117.023889812, 74.0391895611201], + [510539.0438917225, 6651118.951728838, 72.05877175812009], + [510538.95696064265, 6651117.358812819, 73.82593722612009], + [510539.032774585, 6651118.7480195705, 72.3985167851201], + [510538.9744117784, 6651117.678585607, 73.58584877912008], + [510539.0201699424, 6651118.517053418, 72.72418389512009], + [510538.9908645327, 6651117.9800641555, 73.32065105412009], + [510539.00616262155, 6651118.260384735, 73.0325527031201], + [510541.804904192, 6651106.006721421, 67.77395593323926], + [510541.83697537443, 6651106.6154784225, 67.77395593323926], + [510541.83697537443, 6651106.6154784225, 67.90395593323927], + [510541.804904192, 6651106.006721421, 69.60275959223927], + [510541.80600690434, 6651106.0276524825, 70.06835027923925], + [510541.83697537443, 6651106.6154784225, 69.60275959223927], + [510541.8094552329, 6651106.0931067, 70.54562123123927], + [510541.837948356, 6651106.6339470055, 70.01357490423926], + [510541.8409909988, 6651106.691700729, 70.43469633223926], + [510541.81542703096, 6651106.206459986, 71.02852225123927], + [510541.8462602324, 6651106.791718332, 70.86078546723928], + [510541.82163779554, 6651106.324349198, 71.39022823623927], + [510541.82936411974, 6651106.471005901, 71.74798608223927], + [510541.85386366607, 6651106.936042399, 71.28569197123926], + [510541.83860692626, 6651106.646447614, 72.09844229723927], + [510541.86384685454, 6651107.125537623, 71.70265867323926], + [510541.849340039, 6651106.850177474, 72.43818732423927], + [510541.87618347484, 6651107.359704352, 72.10460759023925], + [510541.8615092733, 6651107.081166978, 72.76385443423926], + [510541.8907700076, 6651107.636577646, 72.48448839223927], + [510541.8750327323, 6651107.33786161, 73.07222324223926], + [510541.9030806659, 6651107.870251583, 72.75089470723927], + [510541.8898023716, 6651107.61821053, 73.36032159323926], + [510541.91645438684, 6651108.124103969, 72.99860444723927], + [510541.9056867903, 6651107.919719556, 73.62551931823926], + [510541.9357262731, 6651108.4899119865, 73.29604691723927], + [510541.9225351029, 6651108.239524672, 73.86560776523926], + [510541.95633784286, 6651108.881149115, 73.55226004023926], + [510541.9401816561, 6651108.574481541, 74.07886010023927], + [510541.9779263743, 6651109.290930377, 73.76453784923926], + [510541.95845128474, 6651108.921265272, 74.26406900223927], + [510542.00011778146, 6651109.712155086, 73.93165260623927], + [510541.9771647662, 6651109.276473965, 74.42056029423928], + [510541.99614413886, 6651109.636729655, 74.54818305323927], + [510542.0225460126, 6651110.137875052, 74.05380572823927], + [510542.0152175819, 6651109.9987709345, 74.64727854723927], + [510542.0448699058, 6651110.561614534, 74.13248042123926], + [510542.06678618473, 6651110.977616914, 74.17022328023926], + [510542.04051799414, 6651110.4790090155, 74.73644319923926], + [510542.06535644364, 6651110.950478381, 74.77921844023926], + [510542.47881827434, 6651118.798576403, 67.77395593323926], + [510542.1588538637, 6651112.725193391, 74.17022328023926], + [510542.47881827434, 6651118.798576403, 67.90395593323927], + [510542.51088945684, 6651119.407333405, 67.77395593323926], + [510542.47881839745, 6651118.798578739, 69.60275959323926], + [510542.24900758715, 6651114.436440249, 74.17022328023926], + [510542.4785792602, 6651118.794039574, 69.80658087723926], + [510542.27092386613, 6651114.852442629, 74.13248042123926], + [510542.4765936046, 6651118.756348984, 70.22316016523926], + [510542.51088945684, 6651119.407333405, 69.60275959223927], + [510542.25043720513, 6651114.463576447, 74.77921844023926], + [510542.2932477593, 6651115.276182111, 74.05380572823927], + [510542.47245452093, 6651118.677783244, 70.64748728523927], + [510542.50978674454, 6651119.386402345, 70.06835027923925], + [510542.3156759904, 6651115.7019020775, 73.93165260623927], + [510542.2752756546, 6651114.935045811, 74.73644319923926], + [510542.4660280327, 6651118.55579929, 71.07379763623926], + [510542.33786739764, 6651116.123126786, 73.76453784923926], + [510542.45723610825, 6651118.388915964, 71.49560649523926], + [510542.50633841596, 6651119.320948128, 70.54562123123927], + [510542.300576067, 6651115.415283892, 74.64727854723927], + [510542.359455929, 6651116.532908048, 73.55226004023926], + [510542.4460681509, 6651118.176932132, 71.90595603823928], + [510542.3800674989, 6651116.924145179, 73.29604691723927], + [510542.4325887524, 6651117.921073833, 72.29773573223926], + [510542.3946658478, 6651117.201242763, 73.07662791123926], + [510542.3196495099, 6651115.777325171, 74.54818305323927], + [510542.42104509607, 6651117.701958692, 72.57521759223926], + [510542.5003666178, 6651119.207594842, 71.02852225123927], + [510542.40836765827, 6651117.461322758, 72.83565826523926], + [510542.3386288826, 6651116.137580863, 74.42056029423928], + [510542.4941558532, 6651119.089705629, 71.39022823623927], + [510542.35734236403, 6651116.492789555, 74.26406900223927], + [510542.48642952903, 6651118.943048925, 71.74798608223927], + [510542.37561199267, 6651116.8395732865, 74.07886010023927], + [510542.4771867225, 6651118.767607212, 72.09844229723927], + [510542.393258546, 6651117.174530156, 73.86560776523926], + [510542.46645360976, 6651118.5638773525, 72.43818732423927], + [510542.4101068586, 6651117.494335271, 73.62551931823926], + [510542.4542843756, 6651118.332887848, 72.76385443423926], + [510542.42599127715, 6651117.795844297, 73.36032159323926], + [510542.44076091656, 6651118.076193218, 73.07222324223926], + [510545.0497702439, 6651105.838649935, 67.8111848015487], + [510545.0807644602, 6651106.447462719, 67.8111848015487], + [510545.0807644602, 6651106.447462719, 67.94118480154869], + [510545.0497702439, 6651105.838649935, 69.6399884605487], + [510545.05083592667, 6651105.859582913, 70.10557914754868], + [510545.0807644602, 6651106.447462719, 69.6399884605487], + [510545.0541684587, 6651105.925043128, 70.58285009954871], + [510545.0817047684, 6651106.465932993, 70.05080377254869], + [510545.08464523783, 6651106.523692008, 70.4719252005487], + [510545.0599397207, 6651106.038406801, 71.0657511195487], + [510545.08973752795, 6651106.623718777, 70.8980143355487], + [510545.0659419248, 6651106.156306815, 71.4274571045487], + [510545.0734087951, 6651106.302976958, 71.78521495054869], + [510545.09708563454, 6651106.768056069, 71.32292083954869], + [510545.08234122366, 6651106.478434748, 72.13567116554869], + [510545.1067335826, 6651106.957568655, 71.7398875415487], + [510545.09271391307, 6651106.682183276, 72.47541619254869], + [510545.11865593295, 6651107.191756844, 72.14183645854868], + [510545.10447449837, 6651106.913193947, 72.80108330254869], + [510545.1327526427, 6651107.468655508, 72.52171726054868], + [510545.117543833, 6651107.169912099, 73.10945211054869], + [510545.14464990306, 6651107.702350857, 72.78812357554871], + [510545.1318175005, 6651107.450286709, 73.3975504615487], + [510545.15757452766, 6651107.956226505, 73.03583331554869], + [510545.1471685124, 6651107.751823364, 73.66274818654868], + [510545.17619925446, 6651108.322068042, 73.3332757855487], + [510545.16345105023, 6651108.071657784, 73.90283663354869], + [510545.19611867744, 6651108.713341023, 73.58948890854869], + [510545.1805050235, 6651108.406645346, 74.1160889685487], + [510545.2169822552, 6651109.123159834, 73.8017667175487], + [510545.1981611489, 6651108.753460854, 74.30129787054871], + [510545.23842846387, 6651109.5444231415, 73.9688814745487], + [510545.2162462223, 6651109.108702098, 74.45778916254869], + [510545.2345882582, 6651109.468990799, 74.58541192154868], + [510545.2601035439, 6651109.970182119, 74.0910345965487], + [510545.2530212054, 6651109.831065253, 74.6845074155487], + [510545.28167778964, 6651110.393960429, 74.1697092895487], + [510545.30285810895, 6651110.810000929, 74.2074521485487], + [510545.27747201733, 6651110.311347341, 74.77367206754869], + [510545.30147637933, 6651110.7828599075, 74.81644730854869], + [510545.70105395577, 6651118.631677083, 67.8111848015487], + [510545.70105395577, 6651118.631677083, 67.94118480154869], + [510545.39183410944, 6651112.557737542, 74.2074521485487], + [510545.73204817204, 6651119.240489867, 67.8111848015487], + [510545.7010540747, 6651118.631679418, 69.63998846154868], + [510545.4789604259, 6651114.269141209, 74.2074521485487], + [510545.70082296786, 6651118.627139836, 69.84380974554868], + [510545.5001407453, 6651114.685181708, 74.1697092895487], + [510545.69890399143, 6651118.589445793, 70.26038903354869], + [510545.73204817204, 6651119.240489867, 69.6399884605487], + [510545.4803420366, 6651114.296279894, 74.81644730854869], + [510545.521714991, 6651115.1089600185, 74.0910345965487], + [510545.6949039004, 6651118.510872854, 70.68471615354869], + [510545.73098248924, 6651119.219556888, 70.10557914754868], + [510545.54339007096, 6651115.534718996, 73.9688814745487], + [510545.5043463986, 6651114.7677924605, 74.77367206754869], + [510545.6886932168, 6651118.388877721, 71.11102650454869], + [510545.5648362797, 6651115.955982302, 73.8017667175487], + [510545.7276499573, 6651119.154096671, 70.58285009954871], + [510545.6801965295, 6651118.221979103, 71.53283536354868], + [510545.5287972104, 6651115.248074547, 74.6845074155487], + [510545.58569985745, 6651116.365801115, 73.58948890854869], + [510545.6694035978, 6651118.009975847, 71.9431849065487], + [510545.6056192805, 6651116.757074094, 73.3332757855487], + [510545.65637684416, 6651117.754094101, 72.33496460054869], + [510545.7218786951, 6651119.040732999, 71.0657511195487], + [510545.6197274097, 6651117.03419707, 73.1138567795487], + [510545.6452208295, 6651117.534958883, 72.61244646054868], + [510545.54723015777, 6651115.610149001, 74.58541192154868], + [510545.6329691065, 6651117.294300898, 72.87288713354869], + [510545.7158764911, 6651118.9228329845, 71.4274571045487], + [510545.56557219365, 6651115.970437704, 74.45778916254869], + [510545.7084096208, 6651118.776162843, 71.78521495054869], + [510545.58365726704, 6651116.325678945, 74.30129787054871], + [510545.69947719225, 6651118.600705054, 72.13567116554869], + [510545.6013133924, 6651116.672494453, 74.1160889685487], + [510545.6891045028, 6651118.396956524, 72.47541619254869], + [510545.6183673657, 6651117.0074820155, 73.90283663354869], + [510545.6773439175, 6651118.165945854, 72.80108330254869], + [510545.6346499035, 6651117.327316436, 73.66274818654868], + [510545.664274583, 6651117.9092277, 73.10945211054869], + [510545.65000091546, 6651117.628853091, 73.3975504615487], + [510548.45917139295, 6651105.66825618, 67.85029779767426], + [510548.48903403396, 6651106.277125518, 67.85029779767426], + [510548.48903403396, 6651106.277125518, 67.98029779767425], + [510548.45917139295, 6651105.66825618, 69.67910145667426], + [510548.4601981684, 6651105.689191103, 70.14469214367426], + [510548.48903403396, 6651106.277125518, 69.67910145667426], + [510548.46340903227, 6651105.754657399, 70.62196309567426], + [510548.4899400123, 6651106.295597508, 70.08991676867427], + [510548.4927731274, 6651106.353361887, 70.51103819667425], + [510548.4689695899, 6651105.868031602, 71.10486411567426], + [510548.49767950195, 6651106.453397949, 70.93712733167426], + [510548.4747526581, 6651105.985942568, 71.46657010067428], + [510548.4819469187, 6651106.132626335, 71.82432794667427], + [510548.50475933467, 6651106.597748647, 71.36203383567425], + [510548.490553231, 6651106.308100423, 72.17478416167425], + [510548.51405504346, 6651106.787278838, 71.77900053767425], + [510548.5005472215, 6651106.511867878, 72.51452918867426], + [510548.525542118, 6651107.02148878, 72.18094945467426], + [510548.5118784368, 6651106.742900008, 72.84019629867427], + [510548.5391241676, 6651107.298413167, 72.56083025667425], + [510548.5244706198, 6651106.999642007, 73.14856510667427], + [510548.5505870679, 6651107.532130225, 72.82723657167426], + [510548.5382231666, 6651107.28004266, 73.43666345767426], + [510548.5630398244, 6651107.786029454, 73.07494631167425], + [510548.55301372486, 6651107.581607326, 73.70186118267425], + [510548.58098457655, 6651108.151904975, 73.37238878167427], + [510548.5687017996, 6651107.9014714565, 73.94194962967426], + [510548.6001767565, 6651108.543214302, 73.62860190467426], + [510548.5851331453, 6651108.236490136, 74.15520196467426], + [510548.62027862103, 6651108.953071182, 73.84087971367425], + [510548.602144659, 6651108.58333786, 74.34041086667426], + [510548.64094184496, 6651109.374373621, 74.00799447067426], + [510548.61956946005, 6651108.938612102, 74.49690215867426], + [510548.6372418422, 6651109.298934272, 74.62452491767425], + [510548.66182558425, 6651109.800172147, 74.13014759267426], + [510548.6550018166, 6651109.661042361, 74.72362041167426], + [510548.68261217064, 6651110.223989824, 74.20882228567426], + [510548.70301921276, 6651110.64006897, 74.24656514467425], + [510548.6785599479, 6651110.14136906, 74.81278506367426], + [510548.701687929, 6651110.612925427, 74.85556030467427], + [510549.0866772323, 6651118.462471688, 67.85029779767426], + [510549.0866772323, 6651118.462471688, 67.98029779767425], + [510548.78874676715, 6651112.387967932, 74.24656514467425], + [510549.11653987324, 6651119.071341026, 67.85029779767426], + [510549.08667734684, 6651118.462474025, 69.67910145767426], + [510548.87269216817, 6651114.099530574, 74.24656514467425], + [510549.0864546775, 6651118.457934021, 69.88292274167425], + [510548.89309921017, 6651114.51560972, 74.20882228567426], + [510549.08460576157, 6651118.420236477, 70.29950202967426], + [510549.11653987324, 6651119.071341026, 69.67910145667426], + [510548.87402333727, 6651114.126671779, 74.85556030467427], + [510548.91388579656, 6651114.939427396, 74.13014759267426], + [510549.08075171075, 6651118.341656239, 70.72382914967427], + [510549.1155130978, 6651119.050406102, 70.14469214367426], + [510548.93476953596, 6651115.365225922, 74.00799447067426], + [510549.07476777444, 6651118.219649774, 71.15013950067426], + [510548.89715131826, 6651114.598228146, 74.81278506367426], + [510549.112302234, 6651118.984939807, 70.62196309567426], + [510548.9554327599, 6651115.78652836, 73.84087971367425], + [510549.06658129476, 6651118.052735654, 71.57194835967425], + [510548.9207094496, 6651115.078554845, 74.72362041167426], + [510548.9755346243, 6651116.19638524, 73.62860190467426], + [510549.0561824048, 6651117.840712703, 71.98229790267426], + [510548.9947268044, 6651116.587694567, 73.37238878167427], + [510549.043631248, 6651117.584807188, 72.37407759667425], + [510549.1067416763, 6651118.871565604, 71.10486411567426], + [510549.0083198565, 6651116.864843285, 73.15296977567425], + [510549.032882531, 6651117.365651615, 72.65155945667426], + [510549.021078109, 6651117.124971275, 72.91200012967427], + [510548.93846942397, 6651115.4406629335, 74.62452491767425], + [510549.1009586081, 6651118.753654637, 71.46657010067428], + [510548.95614180615, 6651115.8009851035, 74.49690215867426], + [510549.0937643476, 6651118.606970871, 71.82432794667427], + [510548.9735666072, 6651116.156259344, 74.34041086667426], + [510549.0851580352, 6651118.431496782, 72.17478416167425], + [510548.99057812104, 6651116.50310707, 74.15520196467426], + [510549.0751640447, 6651118.227729328, 72.51452918867426], + [510549.00700946664, 6651116.838125749, 73.94194962967426], + [510549.0638328294, 6651117.996697198, 72.84019629867427], + [510549.02269754146, 6651117.157989879, 73.70186118267425], + [510549.0512406464, 6651117.739955198, 73.14856510667427], + [510549.0374880996, 6651117.459554546, 73.43666345767426], + [510558.6812516685, 6651105.195443709, 67.96754571538673], + [510558.707721616, 6651105.804469973, 67.96754571538673], + [510558.707721616, 6651105.804469973, 68.09754571538674], + [510558.6812516685, 6651105.195443709, 69.79634937438674], + [510558.682161792, 6651105.216384027, 70.26194006138672], + [510558.707721616, 6651105.804469973, 69.79634937438674], + [510558.70852466614, 6651105.822946724, 70.20716468638673], + [510558.6850078697, 6651105.281867197, 70.73921101338674], + [510558.7110359112, 6651105.880725991, 70.62828611438673], + [510558.68993669265, 6651105.39527062, 71.22211203338674], + [510558.71538487263, 6651105.980787834, 71.05437524938675], + [510558.69506274664, 6651105.513211976, 71.58381801838674], + [510558.721660366, 6651106.125175738, 71.47928175338673], + [510558.70143966755, 6651105.6599335475, 71.94157586438673], + [510558.70906821714, 6651105.835452861, 72.29203207938674], + [510558.7298999896, 6651106.314754777, 71.89624845538673], + [510558.71792679076, 6651106.039272834, 72.63177710638674], + [510558.740082018, 6651106.549025084, 72.29819737238674], + [510558.7279706671, 6651106.270364508, 72.95744421638673], + [510558.7521210115, 6651106.8260208415, 72.67807817438674], + [510558.7391322528, 6651106.527172679, 73.26581302438673], + [510558.7622816122, 6651107.0597981345, 72.94448448938672], + [510558.7513223732, 6651106.8076456, 73.55391137538673], + [510558.7733196115, 6651107.3137628045, 73.19219422938673], + [510558.76443257666, 6651107.109287989, 73.81910910038673], + [510558.78922566114, 6651107.679732623, 73.48963669938674], + [510558.7783383299, 6651107.42923456, 74.05919754738673], + [510558.8062374183, 6651108.071142804, 73.74584982238673], + [510558.792902911, 6651107.764339584, 74.27244988238674], + [510558.82405551075, 6651108.481105316, 73.95812763138673], + [510558.8079817474, 6651108.111276703, 74.45765878438674], + [510558.84237118665, 6651108.902516339, 74.12524238838674], + [510558.8234269176, 6651108.46664251, 74.61415007638675], + [510558.8608823251, 6651109.328424607, 74.24739551038674], + [510558.839091541, 6651108.827057547, 74.74177283538674], + [510558.85483380547, 6651109.189258963, 74.84086832938674], + [510558.8793073483, 6651109.752351516, 74.32607020338673], + [510558.8973959472, 6651110.168537899, 74.36381306238673], + [510558.87571549846, 6651109.669709458, 74.93003298138673], + [510558.89621591044, 6651110.141387361, 74.97280822238673], + [510559.23746659444, 6651117.99295671, 67.96754571538673], + [510559.23746659444, 6651117.99295671, 68.09754571538674], + [510558.97338399757, 6651111.916887354, 74.36381306238673], + [510559.263936542, 6651118.6019829735, 67.96754571538673], + [510559.237466696, 6651117.992959048, 69.79634937538673], + [510559.23726932413, 6651117.988417874, 70.00017065938673], + [510559.0477923649, 6651113.628891122, 74.36381306238673], + [510559.23563046346, 6651117.950710612, 70.41674994738673], + [510559.263936542, 6651118.6019829735, 69.79634937438674], + [510559.06588096364, 6651114.045077505, 74.32607020338673], + [510559.2322142711, 6651117.872110123, 70.84107706738673], + [510559.0489722999, 6651113.656039322, 74.97280822238673], + [510559.2630264184, 6651118.581042654, 70.26194006138672], + [510559.0843059868, 6651114.469004412, 74.24739551038674], + [510559.22691016964, 6651117.750072213, 71.26738741838673], + [510559.10281712544, 6651114.894912682, 74.12524238838674], + [510559.06947271194, 6651114.127717225, 74.93003298138673], + [510559.2601803408, 6651118.515559485, 70.73921101338674], + [510559.2196537556, 6651117.583115072, 71.68919627738673], + [510559.1211328013, 6651115.316323703, 73.95812763138673], + [510559.21043628315, 6651117.371037477, 72.09954582038675], + [510559.1389508937, 6651115.726286217, 73.74584982238673], + [510559.09035440494, 6651114.60816772, 74.84086832938674], + [510559.2552515178, 6651118.402156062, 71.22211203338674], + [510559.19931106275, 6651117.115066006, 72.49132551438674], + [510559.1559626509, 6651116.117696397, 73.48963669938674], + [510559.18978350697, 6651116.89585395, 72.76880737438674], + [510559.168011397, 6651116.394916545, 73.27021769338673], + [510559.1793201849, 6651116.655111578, 73.02924804738673], + [510559.10609666933, 6651114.970369136, 74.74177283538674], + [510559.2501254637, 6651118.284214707, 71.58381801838674], + [510559.12176129286, 6651115.330784173, 74.61415007638675], + [510559.2437485428, 6651118.1374931345, 71.94157586438673], + [510559.13720646297, 6651115.686149979, 74.45765878438674], + [510559.2361199933, 6651117.961973821, 72.29203207938674], + [510559.1522852993, 6651116.033087098, 74.27244988238674], + [510559.2272614197, 6651117.758153848, 72.63177710638674], + [510559.16684988054, 6651116.368192124, 74.05919754738673], + [510559.21721754334, 6651117.527062175, 72.95744421638673], + [510559.1807556337, 6651116.688138693, 73.81910910038673], + [510559.20605595765, 6651117.270254004, 73.26581302438673], + [510559.1938658371, 6651116.989781082, 73.55391137538673], + [510562.25216679554, 6651105.043722797, 68.00849746456501], + [510562.2774515616, 6651105.652799416, 68.00849746456501], + [510562.2774515616, 6651105.652799416, 68.138497464565], + [510562.25216679554, 6651105.043722797, 69.83730112356503], + [510562.2530361687, 6651105.064664846, 70.302891810565], + [510562.2774515616, 6651105.652799416, 69.83730112356503], + [510562.2782186556, 6651105.671277695, 70.24811643556501], + [510562.25575481437, 6651105.13015343, 70.78016276256501], + [510562.28061746055, 6651105.7290617395, 70.669237863565], + [510562.2604629512, 6651105.24356623, 71.26306378256501], + [510562.284771699, 6651105.829131857, 71.09532699856501], + [510562.2653594882, 6651105.361517337, 71.62476976756501], + [510562.29076620954, 6651105.973531698, 71.52023350256502], + [510562.27145088505, 6651105.50825104, 71.98252761356501], + [510562.2787378692, 6651105.683784867, 72.332983828565], + [510562.2986369073, 6651106.163126413, 71.937200204565], + [510562.28719980374, 6651105.887621691, 72.67272885556503], + [510562.3083630394, 6651106.397416089, 72.33914912156501], + [510562.29679396946, 6651106.118732473, 72.99839596556501], + [510562.31986299163, 6651106.67443475, 72.719029923565], + [510562.3074557995, 6651106.375561878, 73.306764773565], + [510562.3295686555, 6651106.908231372, 72.98543623856501], + [510562.3191001122, 6651106.65605799, 73.59486312456501], + [510562.3401124328, 6651107.162217041, 73.233145978565], + [510562.33162331133, 6651106.957725319, 73.860060849565], + [510562.35530629515, 6651107.528217118, 73.53058844856501], + [510562.34490644, 6651107.277698344, 74.10014929656501], + [510562.3715563576, 6651107.919659661, 73.78680157156501], + [510562.35881889774, 6651107.612831075, 74.31340163156503], + [510562.388576652, 6651108.329656073, 73.99907938056501], + [510562.3732225851, 6651107.959796879, 74.49861053356501], + [510562.4060722507, 6651108.751101937, 74.16619413756501], + [510562.38797620387, 6651108.31519207, 74.65510182556501], + [510562.4237545603, 6651109.177045421, 74.28834725956501], + [510562.40293945, 6651108.675636907, 74.782724584565], + [510562.41797686066, 6651109.037868269, 74.88182007856503], + [510562.44135461026, 6651109.601007381, 74.36702195256501], + [510562.45863329916, 6651110.017228177, 74.404764811565], + [510562.437923584, 6651109.518358491, 74.97098473056502], + [510562.4575060982, 6651109.990075394, 75.01375997156501], + [510562.783477417, 6651117.842293931, 68.00849746456501], + [510562.783477417, 6651117.842293931, 68.138497464565], + [510562.808762183, 6651118.451370551, 68.00849746456501], + [510562.5312190145, 6651111.765722188, 74.404764811565], + [510562.783477514, 6651117.842296268, 69.837301124565], + [510562.7832889794, 6651117.837754719, 70.04112240856502], + [510562.6022957765, 6651113.47786751, 74.404764811565], + [510562.808762183, 6651118.451370551, 69.83730112356503], + [510562.78172349796, 6651117.80004434, 70.45770169656501], + [510562.6195744654, 6651113.894088304, 74.36702195256501], + [510562.7784602643, 6651117.721437353, 70.88202881656501], + [510562.8078928099, 6651118.4304285, 70.302891810565], + [510562.6034228804, 6651113.505017955, 75.01375997156501], + [510562.63717451534, 6651114.318050263, 74.28834725956501], + [510562.773393652, 6651117.59938935, 71.30833916756502], + [510562.654856825, 6651114.743993747, 74.16619413756501], + [510562.80517416424, 6651118.364939917, 70.78016276256501], + [510562.6230053946, 6651113.976734857, 74.97098473056502], + [510562.76646214095, 6651117.432418406, 71.73014802656502], + [510562.6723524237, 6651115.165439613, 73.99907938056501], + [510562.75765737717, 6651117.220323276, 72.14049756956501], + [510562.689372718, 6651115.575436023, 73.78680157156501], + [510562.8004660274, 6651118.2515271185, 71.26306378256501], + [510562.64295211795, 6651114.457225078, 74.88182007856503], + [510562.74703028414, 6651116.964330641, 72.53227726356502], + [510562.70562278054, 6651115.966878566, 73.53058844856501], + [510562.737929321, 6651116.745100459, 72.80975912356502], + [510562.7171320486, 6651116.244121635, 73.311169442565], + [510562.72793449013, 6651116.504338183, 73.070199796565], + [510562.79556949035, 6651118.133576009, 71.62476976756501], + [510562.65798952867, 6651114.819456441, 74.782724584565], + [510562.78947809356, 6651117.986842307, 71.98252761356501], + [510562.67295277474, 6651115.179901279, 74.65510182556501], + [510562.7821911093, 6651117.811308481, 72.332983828565], + [510562.68770639354, 6651115.535296467, 74.49861053356501], + [510562.7737291749, 6651117.607471656, 72.67272885556503], + [510562.7021100809, 6651115.882262272, 74.31340163156503], + [510562.7160225386, 6651116.217395004, 74.10014929656501], + [510562.76413500914, 6651117.376360874, 72.99839596556501], + [510562.7293056672, 6651116.5373680275, 73.860060849565], + [510562.75347317907, 6651117.11953147, 73.306764773565], + [510562.7418288664, 6651116.839035358, 73.59486312456501], + [510568.6902991316, 6651104.7877660515, 68.0823226047824], + [510568.71344709094, 6651105.396927622, 68.0823226047824], + [510568.71344709094, 6651105.396927622, 68.2123226047824], + [510568.6902991316, 6651104.7877660515, 69.9111262637824], + [510568.69109503424, 6651104.808711022, 70.37671695078241], + [510568.71344709094, 6651105.396927622, 69.9111262637824], + [510568.714149358, 6651105.415408478, 70.32194157578242], + [510568.6935839281, 6651104.874208739, 70.8539879027824], + [510568.7163454409, 6651105.473200583, 70.7430630037824], + [510568.69789418206, 6651104.987637357, 71.3368889227824], + [510568.72014860605, 6651105.573284656, 71.16915213878241], + [510568.7023769143, 6651105.105604916, 71.69859490778242], + [510568.7256365227, 6651105.717704638, 71.5940586427824], + [510568.7079535294, 6651105.252359086, 72.0563527537824], + [510568.71462469315, 6651105.427917394, 72.4068089687824], + [510568.7328420705, 6651105.907325796, 72.0110253447824], + [510568.72237151256, 6651105.631782649, 72.7465539957824], + [510568.74174625066, 6651106.14164815, 72.41297426178241], + [510568.7311548786, 6651105.862925665, 73.07222110578242], + [510568.7522743459, 6651106.41870545, 72.7928550637824], + [510568.7409156812, 6651106.119790891, 73.3805899137824], + [510568.7611597876, 6651106.65253468, 73.0592613787824], + [510568.7515759371, 6651106.400326126, 73.6686882647824], + [510568.77081251383, 6651106.906555775, 73.3069711187824], + [510568.7630408052, 6651106.7020355305, 73.93388598978241], + [510568.7847223483, 6651107.2726069, 73.60441358878242], + [510568.77520138124, 6651107.022053183, 74.17397443678242], + [510568.7995991237, 6651107.66410404, 73.86062671178242], + [510568.7879381021, 6651107.357232659, 74.38722677178241], + [510568.815181039, 6651108.074157636, 74.0729045207824], + [510568.80112453894, 6651107.704246856, 74.57243567378241], + [510568.83119809086, 6651108.495662283, 74.24001927778241], + [510568.8146313345, 6651108.0596916145, 74.7289269657824], + [510568.84738607466, 6651108.921665175, 74.36217239978242], + [510568.828330042, 6651108.420186726, 74.8565497247824], + [510568.84209664643, 6651108.782468611, 74.95564521878241], + [510568.8634987506, 6651109.345686267, 74.4408470927824], + [510568.8793172237, 6651109.761965115, 74.4785899517824], + [510568.8603576792, 6651109.263025849, 75.0448098707824], + [510568.87828528194, 6651109.734808546, 75.0875851117824], + [510569.1767088793, 6651117.58812228, 68.0823226047824], + [510569.1767088793, 6651117.58812228, 68.2123226047824], + [510569.19985683874, 6651118.197283852, 68.0823226047824], + [510568.94576874573, 6651111.510703002, 74.4785899517824], + [510569.1767089682, 6651117.588124618, 69.91112626478241], + [510569.1765363666, 6651117.583582436, 70.1149475487824], + [510569.01083883556, 6651113.223087125, 74.4785899517824], + [510569.19985683874, 6651118.197283852, 69.9111262637824], + [510569.1751031835, 6651117.545866797, 70.5315268367824], + [510569.0266573085, 6651113.639365973, 74.4408470927824], + [510569.1721157246, 6651117.467248845, 70.95585395678242], + [510569.199060936, 6651118.17633888, 70.37671695078241], + [510569.0118706883, 6651113.250241357, 75.0875851117824], + [510569.04276998446, 6651114.063387065, 74.36217239978242], + [510569.1674772898, 6651117.34518382, 71.3821643077824], + [510569.1965720421, 6651118.110841163, 70.8539879027824], + [510569.05895796826, 6651114.489389959, 74.24001927778241], + [510569.16113155836, 6651117.178189588, 71.8039731667824], + [510569.02979829104, 6651113.722024052, 75.0448098707824], + [510569.07497502014, 6651114.910894604, 74.0729045207824], + [510569.1530708821, 6651116.966064875, 72.21432270978241], + [510569.1922617883, 6651117.997412547, 71.3368889227824], + [510569.09055693535, 6651115.3209482, 73.86062671178242], + [510569.14334188093, 6651116.710036535, 72.6061024037824], + [510569.0480593238, 6651114.202581291, 74.95564521878241], + [510569.135010037, 6651116.490775776, 72.88358426378241], + [510569.1054337108, 6651115.71244534, 73.60441358878242], + [510569.1258598657, 6651116.249979919, 73.14402493678242], + [510569.11597033474, 6651115.989727079, 73.3849945827824], + [510569.1877790559, 6651117.879444987, 71.69859490778242], + [510569.06182592834, 6651114.564863176, 74.8565497247824], + [510569.18220244086, 6651117.732690817, 72.0563527537824], + [510569.07552463573, 6651114.925358287, 74.7289269657824], + [510569.1755312772, 6651117.557132508, 72.4068089687824], + [510569.0890314314, 6651115.280803045, 74.57243567378241], + [510569.1677844578, 6651117.353267252, 72.7465539957824], + [510569.10221786815, 6651115.627817243, 74.38722677178241], + [510569.1590010916, 6651117.122124237, 73.07222110578242], + [510569.114954589, 6651115.9629967185, 74.17397443678242], + [510569.14924028906, 6651116.86525901, 73.3805899137824], + [510569.12711516506, 6651116.283014371, 73.93388598978241], + [510569.13858003315, 6651116.584723776, 73.6686882647824], + [510575.56434793817, 6651104.539443691, 68.16113549753591], + [510575.5852144108, 6651105.148687679, 68.16113549753591], + [510575.5852144108, 6651105.148687679, 68.2911354975359], + [510575.56434793817, 6651104.539443691, 69.98993915653591], + [510575.56506539584, 6651104.560391497, 70.4555298435359], + [510575.5852144108, 6651105.148687679, 69.98993915653591], + [510575.5858474617, 6651105.167171037, 70.40075446853591], + [510575.56730898184, 6651104.625898075, 70.93280079553591], + [510575.5878270964, 6651105.22497096, 70.8218758965359], + [510575.57119441265, 6651104.739342039, 71.41570181553591], + [510575.5912554177, 6651105.325068575, 71.24796503153591], + [510575.57523532223, 6651104.8573255595, 71.77740780053593], + [510575.5962024395, 6651105.469508097, 71.6728715355359], + [510575.5802623003, 6651105.004099584, 72.13516564653592], + [510575.5862759473, 6651105.179681645, 72.4856218615359], + [510575.60269780125, 6651105.65915491, 72.0898382375359], + [510575.5932592322, 6651105.383574483, 72.82536688853591], + [510575.6107243761, 6651105.893508967, 72.4917871545359], + [510575.6011769008, 6651105.614748772, 73.15103399853591], + [510575.6202148115, 6651106.170603752, 72.8716679565359], + [510575.60997566854, 6651105.871648751, 73.45940280653592], + [510575.62822449487, 6651106.40446462, 73.13807427153591], + [510575.6195852386, 6651106.152221941, 73.74750115753591], + [510575.6369258386, 6651106.65852008, 73.3857840115359], + [510575.6299201175, 6651106.453972166, 74.0126988825359], + [510575.6494647054, 6651107.024620732, 73.68322648153591], + [510575.64088213467, 6651106.774033116, 74.2527873295359], + [510575.6628752105, 6651107.416170841, 73.9394396045359], + [510575.6523635112, 6651107.10925794, 74.46603966453591], + [510575.6769213561, 6651107.826279915, 74.1517174135359], + [510575.66425027914, 6651107.456319088, 74.65124856653591], + [510575.69135975087, 6651108.247841591, 74.31883217053591], + [510575.67642583116, 6651107.811811938, 74.80773985853591], + [510575.7059522304, 6651108.67390212, 74.44098529253591], + [510575.68877437984, 6651108.172355822, 74.9353626175359], + [510575.7204768243, 6651109.097980581, 74.51965998553591], + [510575.70118413365, 6651108.534686725, 75.03445811153591], + [510575.73473621235, 6651109.51431575, 74.5574028445359], + [510575.7176453402, 6651109.01530898, 75.1236227635359], + [510575.73380597995, 6651109.487155505, 75.16639800453592], + [510576.0028166402, 6651117.341531774, 68.16113549753591], + [510576.0028166402, 6651117.341531774, 68.2911354975359], + [510576.02368311293, 6651117.950775762, 68.16113549753591], + [510575.7946382039, 6651111.263290236, 74.5574028445359], + [510576.00281672034, 6651117.341534112, 69.9899391575359], + [510576.00266113045, 6651117.336991314, 70.1937604415359], + [510576.02368311293, 6651117.950775762, 69.98993915653591], + [510576.0013692033, 6651117.299270572, 70.61033972953591], + [510575.8532949188, 6651112.9759060405, 74.5574028445359], + [510575.99867619155, 6651117.220641984, 71.03466684953591], + [510575.86755430675, 6651113.39224121, 74.51965998553591], + [510576.02296565514, 6651117.9298279565, 70.4555298435359], + [510575.9944949256, 6651117.098560444, 71.46097720053591], + [510575.8542250711, 6651113.003063948, 75.16639800453592], + [510575.88207890076, 6651113.816319671, 74.44098529253591], + [510576.0207220692, 6651117.864321377, 70.93280079553591], + [510575.988774636, 6651116.9315436175, 71.8827860595359], + [510575.89667138027, 6651114.242380201, 74.31883217053591], + [510575.87038571085, 6651113.474910473, 75.1236227635359], + [510575.9815084283, 6651116.719390206, 72.29313560253591], + [510575.9111097749, 6651114.663941877, 74.1517174135359], + [510576.0168366384, 6651117.750877414, 71.41570181553591], + [510575.9727383275, 6651116.463327226, 72.6849152965359], + [510575.9251559206, 6651115.074050951, 73.9394396045359], + [510575.9652276787, 6651116.244036801, 72.96239715653591], + [510575.8868469174, 6651113.955532729, 75.03445811153591], + [510575.93856642576, 6651115.46560106, 73.68322648153591], + [510575.95697935775, 6651116.003208364, 73.2228378295359], + [510575.9480645492, 6651115.742920312, 73.4638074755359], + [510576.0127957288, 6651117.632893895, 71.77740780053593], + [510575.8992566711, 6651114.31786363, 74.9353626175359], + [510576.0077687507, 6651117.486119869, 72.13516564653592], + [510575.9116052199, 6651114.6784075145, 74.80773985853591], + [510576.0017551037, 6651117.310537808, 72.4856218615359], + [510575.92378077185, 6651115.033900364, 74.65124856653591], + [510575.99477181886, 6651117.106644969, 72.82536688853591], + [510575.93566753983, 6651115.380961512, 74.46603966453591], + [510575.9868541503, 6651116.875470681, 73.15103399853591], + [510575.94714891637, 6651115.716186337, 74.2527873295359], + [510575.97805538244, 6651116.618570702, 73.45940280653592], + [510575.95811093354, 6651116.036247287, 74.0126988825359], + [510575.96844581235, 6651116.337997512, 73.74750115753591], + [510579.46126029454, 6651104.410116288, 68.20581012757597], + [510579.4808333877, 6651105.0194032, 68.20581012757597], + [510579.4808333877, 6651105.0194032, 68.33581012757597], + [510579.46126029454, 6651104.410116288, 70.03461378657599], + [510579.46193328174, 6651104.431065568, 70.50020447357596], + [510579.4808333877, 6651105.0194032, 70.03461378657599], + [510579.48142719985, 6651105.037887859, 70.44542909857597], + [510579.46403780207, 6651104.496576762, 70.97747542557597], + [510579.48328412964, 6651105.095691853, 70.86655052657596], + [510579.4676823998, 6651104.610028719, 71.46037644557599], + [510579.4864999512, 6651105.195796522, 71.29263966157598], + [510579.4714728392, 6651104.728020551, 71.82208243057597], + [510579.4911403387, 6651105.340246219, 71.71754616557598], + [510579.476188227, 6651104.874804918, 72.17984027657597], + [510579.48182912637, 6651105.050399349, 72.53029649157597], + [510579.49723309436, 6651105.529906395, 72.13451286757596], + [510579.48837956204, 6651105.254306552, 72.87004151857599], + [510579.5047621531, 6651105.764276962, 72.53646178457598], + [510579.4958064648, 6651105.485497128, 73.19570862857597], + [510579.513664337, 6651106.041391268, 72.91634258657596], + [510579.5040598531, 6651105.742415206, 73.50407743657597], + [510579.5211775512, 6651106.275268613, 73.18274890157598], + [510579.5130737873, 6651106.023008165, 73.79217578757597], + [510579.52933955414, 6651106.529341973, 73.43045864157597], + [510579.5227680729, 6651106.324779649, 74.05737351257596], + [510579.54110121663, 6651106.8954684185, 73.72790111157597], + [510579.5330506246, 6651106.644863147, 74.29746195957597], + [510579.55368049006, 6651107.287046113, 73.98411423457597], + [510579.5438203439, 6651106.980111591, 74.51071429457599], + [510579.56685600476, 6651107.697184081, 74.19639204357597], + [510579.554970327, 6651107.327197189, 74.69592319657598], + [510579.5803994555, 6651108.118775458, 74.36350680057598], + [510579.5663911942, 6651107.682715084, 74.85241448857597], + [510579.59408744023, 6651108.544866005, 74.48565992257598], + [510579.5779743351, 6651108.043284371, 74.98003724757596], + [510579.6077117474, 6651108.968974344, 74.56433461557597], + [510579.5896148874, 6651108.4056408005, 75.07913274157599], + [510579.62108728697, 6651109.385338846, 74.60207747457596], + [510579.6050557689, 6651108.886296918, 75.16829739357598], + [510579.87255111965, 6651117.213106325, 68.20581012757597], + [510579.6202147137, 6651109.358176687, 75.21107263457597], + [510579.87255111965, 6651117.213106325, 68.33581012757597], + [510579.89212421275, 6651117.822393238, 68.20581012757597], + [510579.67727633624, 6651111.134436552, 74.60207747457596], + [510579.8725511947, 6651117.213108663, 70.03461378757596], + [510579.8724052489, 6651117.208565545, 70.23843507157598], + [510579.89212421275, 6651117.822393238, 70.03461378657599], + [510579.8711934001, 6651117.1708421465, 70.65501435957597], + [510579.7322972956, 6651112.847173017, 74.60207747457596], + [510579.8686673109, 6651117.092208018, 71.07934147957597], + [510579.8914512257, 6651117.801443957, 70.50020447357596], + [510579.7456728351, 6651113.263537521, 74.56433461557597], + [510579.86474521505, 6651116.970117877, 71.50565183057599], + [510579.7592971423, 6651113.687645858, 74.48565992257598], + [510579.73316979373, 6651112.874332837, 75.21107263457597], + [510579.8893467053, 6651117.735932763, 70.97747542557597], + [510579.8593794896, 6651116.803089285, 71.92746068957598], + [510579.772985127, 6651114.113736405, 74.36350680057598], + [510579.7483287385, 6651113.346212606, 75.16829739357598], + [510579.8525636678, 6651116.590920925, 72.33781023257598], + [510579.88570210757, 6651117.622480806, 71.46037644557599], + [510579.78652857774, 6651114.535327782, 74.19639204357597], + [510579.84433716966, 6651116.334839905, 72.72958992657598], + [510579.79970409244, 6651114.94546575, 73.98411423457597], + [510579.8372920579, 6651116.115534031, 73.00707178657598], + [510579.8122833659, 6651115.337043445, 73.72790111157597], + [510579.8819116681, 6651117.504488974, 71.82208243057597], + [510579.82955499773, 6651115.874688626, 73.26751245957597], + [510579.76376962, 6651113.826868724, 75.07913274157599], + [510579.82119276136, 6651115.614382235, 73.50848210557596], + [510579.8771962804, 6651117.357704608, 72.17984027657597], + [510579.7754101722, 6651114.189225154, 74.98003724757596], + [510579.78699331323, 6651114.549794439, 74.85241448857597], + [510579.87155538093, 6651117.182110176, 72.53029649157597], + [510579.7984141804, 6651114.905312335, 74.69592319657598], + [510579.8650049454, 6651116.978202973, 72.87004151857599], + [510579.8095641635, 6651115.252397935, 74.51071429457599], + [510579.85757804255, 6651116.747012397, 73.19570862857597], + [510579.82033388276, 6651115.587646376, 74.29746195957597], + [510579.8493246542, 6651116.490094319, 73.50407743657597], + [510579.8306164344, 6651115.907729876, 74.05737351257596], + [510579.8403107201, 6651116.209501361, 73.79217578757597], + [510585.5625478138, 6651104.224263366, 68.27574991362977], + [510585.58009589853, 6651104.833611962, 68.27574991362977], + [510585.58009589853, 6651104.833611962, 68.40574991362976], + [510585.5625478138, 6651104.224263366, 70.10455357262977], + [510585.56315117446, 6651104.24521477, 70.57014425962976], + [510585.58009589853, 6651104.833611962, 70.10455357262977], + [510585.58062827564, 6651104.852098494, 70.51536888462977], + [510585.5650379637, 6651104.310732596, 71.04741521162978], + [510585.5822930897, 6651104.909908341, 70.93649031262976], + [510585.5683054958, 6651104.424196037, 71.53031623162977], + [510585.58517620625, 6651105.010023143, 71.36257944762977], + [510585.57170378097, 6651104.542199816, 71.89202221662977], + [510585.589336505, 6651105.154487466, 71.78748595162976], + [510585.5759313205, 6651104.688999041, 72.24978006262978], + [510585.58098861936, 6651104.86461125, 72.60023627762976], + [510585.5947989115, 6651105.344166841, 72.20445265362977], + [510585.58686135476, 6651105.068539097, 72.93998130462977], + [510585.601549023, 6651105.578561137, 72.60640157062977], + [510585.5935198793, 6651105.299753079, 73.26564841462977], + [510585.60953019786, 6651105.855703498, 72.98628237262976], + [510585.6009193821, 6651105.556697167, 73.57401722262978], + [510585.61626610404, 6651106.089604521, 73.25268868762976], + [510585.6090007456, 6651105.837318534, 73.86211557362977], + [510585.623583676, 6651106.343703603, 73.50039842762976], + [510585.6176920723, 6651106.139120569, 74.12731329862976], + [510585.6341284912, 6651106.709867116, 73.79784089762977], + [510585.6269108037, 6651106.459236474, 74.36740174562976], + [510585.64540632843, 6651107.101484454, 74.05405402062976], + [510585.6365663009, 6651106.794518856, 74.58065408062977], + [510585.65721872036, 6651107.511663944, 74.26633182962978], + [510585.6465627204, 6651107.141639595, 74.76586298262978], + [510585.66936098225, 6651107.933298003, 74.43344658662977], + [510585.65680199856, 6651107.497193484, 74.92235427462977], + [510585.6816328247, 6651108.359431689, 74.55559970862977], + [510585.66718676186, 6651107.857799273, 75.04997703362976], + [510585.69384757767, 6651108.783582963, 74.63427440162977], + [510585.67762299674, 6651108.220192387, 75.14907252762977], + [510585.7058393002, 6651109.199989618, 74.67201726062976], + [510585.6914663834, 6651108.7008971665, 75.23823717962976], + [510585.93128699105, 6651117.028549582, 68.27574991362977], + [510585.93128699105, 6651117.028549582, 68.40574991362976], + [510585.70505700225, 6651109.17282471, 75.28101242062978], + [510585.9488350758, 6651117.637898179, 68.27574991362977], + [510585.7562150989, 6651110.949264403, 74.67201726062976], + [510585.9312870584, 6651117.02855192, 70.10455357362976], + [510585.9311562119, 6651117.024008343, 70.30837485762976], + [510585.9488350758, 6651117.637898179, 70.10455357262977], + [510585.9300697396, 6651116.986281125, 70.72495414562977], + [510585.80554365675, 6651112.662174267, 74.67201726062976], + [510585.92780499643, 6651116.907639035, 71.14928126562977], + [510585.9482317151, 6651117.616946777, 70.57014425962976], + [510585.81753537926, 6651113.078580921, 74.63427440162977], + [510585.92428867583, 6651116.785536534, 71.57559161662977], + [510585.9463449259, 6651117.55142895, 71.04741521162978], + [510585.8297501322, 6651113.502732197, 74.55559970862977], + [510585.80632588733, 6651112.689336835, 75.28101242062978], + [510585.9194780818, 6651116.61849103, 71.99740047562976], + [510585.8420219748, 6651113.928865881, 74.43344658662977], + [510585.9133674166, 6651116.406301191, 72.40775001862977], + [510585.94307739375, 6651117.437965508, 71.53031623162977], + [510585.8199165061, 6651113.161264378, 75.23823717962976], + [510585.8541642366, 6651114.350499939, 74.26633182962978], + [510585.90599202196, 6651116.150194245, 72.79952971262976], + [510585.8659766286, 6651114.76067943, 74.05405402062976], + [510585.899675789, 6651115.930866169, 73.07701157262977], + [510585.93967910856, 6651117.319961729, 71.89202221662977], + [510585.8772544657, 6651115.152296768, 73.79784089762977], + [510585.89273919555, 6651115.689996381, 73.33745224562976], + [510585.88524210587, 6651115.429663638, 73.57842189162976], + [510585.8337598928, 6651113.641969157, 75.14907252762977], + [510585.9354515691, 6651117.173162503, 72.24978006262978], + [510585.8441961277, 6651114.004362272, 75.04997703362976], + [510585.93039427034, 6651116.997550295, 72.60023627762976], + [510585.8545808911, 6651114.364968063, 74.92235427462977], + [510585.92452153476, 6651116.793622448, 72.93998130462977], + [510585.86482016917, 6651114.720521951, 74.76586298262978], + [510585.91786301025, 6651116.562408468, 73.26564841462977], + [510585.8748165887, 6651115.067642689, 74.58065408062977], + [510585.9104635074, 6651116.305464378, 73.57401722262978], + [510585.88447208586, 6651115.402925071, 74.36740174562976], + [510585.902382144, 6651116.024843013, 73.86211557362977], + [510585.8936908173, 6651115.723040977, 74.12731329862976], + [510588.92990477174, 6651104.130380348, 68.31382165648704], + [510588.9463352356, 6651104.739760105, 68.31382165648704], + [510588.9463352356, 6651104.739760105, 68.44382165648703], + [510588.92990477174, 6651104.130380348, 70.14262531548704], + [510588.93046970497, 6651104.151332822, 70.60821600248704], + [510588.9463352356, 6651104.739760105, 70.14262531548704], + [510588.9468337061, 6651104.758247582, 70.55344062748705], + [510588.93223632633, 6651104.216853999, 71.08548695448704], + [510588.94839248975, 6651104.816060384, 70.97456205548703], + [510588.9352957525, 6651104.330323244, 71.56838797448704], + [510588.95109198336, 6651104.916180306, 71.40065119048704], + [510588.9384776041, 6651104.448333057, 71.93009395948705], + [510588.9549873166, 6651105.060652016, 71.82555769448703], + [510588.94243589556, 6651104.595139789, 72.28785180548705], + [510588.9471710999, 6651104.770760979, 72.63830802048703], + [510588.96010182763, 6651105.25034109, 72.24252439648703], + [510588.95266980643, 6651104.974699252, 72.97805304748704], + [510588.96642203105, 6651105.484747373, 72.64447331348704], + [510588.9589042558, 6651105.205925057, 73.30372015748704], + [510588.9738948923, 6651105.761903906, 73.02435411548703], + [510588.96583249135, 6651105.462882286, 73.61208896548705], + [510588.9802017951, 6651105.995816889, 73.29076043048704], + [510588.9733991605, 6651105.743518001, 73.90018731648703], + [510588.98705331795, 6651106.249928965, 73.53847017048703], + [510588.9815369448, 6651106.04533547, 74.16538504148703], + [510588.9969265438, 6651106.616111202, 73.83591264048705], + [510588.99016854394, 6651106.365467743, 74.40547348848703], + [510589.00748610625, 6651107.007748566, 74.09212576348703], + [510588.99920909177, 6651106.700767272, 74.61872582348704], + [510589.0185461783, 6651107.417949031, 74.30440357248703], + [510589.0085688487, 6651107.047905761, 74.80393472548704], + [510589.029915111, 6651107.83960465, 74.47151832948704], + [510589.01815599704, 6651107.403477829, 74.96042601748704], + [510589.0414053715, 6651108.265760126, 74.59367145148704], + [510589.02787936473, 6651107.764102059, 75.08804877648703], + [510589.05284217844, 6651108.6899330905, 74.67234614448704], + [510589.03765092575, 6651108.126513705, 75.18714427048704], + [510589.06407015957, 6651109.106361039, 74.71008900348703], + [510589.0506126402, 6651108.607243066, 75.27630892248703], + [510589.2751593013, 6651116.935321324, 68.31382165648704], + [510589.2751593013, 6651116.935321324, 68.44382165648703], + [510589.06333768554, 6651109.079194741, 75.31908416348705], + [510589.2915897653, 6651117.54470108, 68.31382165648704], + [510589.11123757163, 6651110.855725275, 74.71008900348703], + [510589.27515936433, 6651116.935323662, 70.14262531648704], + [510589.2750368514, 6651116.930779853, 70.34644660048703], + [510589.2915897653, 6651117.54470108, 70.14262531548704], + [510589.27401957544, 6651116.893050705, 70.76302588848704], + [510589.1574244405, 6651112.56872273, 74.71008900348703], + [510589.27189907164, 6651116.814404594, 71.18735300848705], + [510589.29102483205, 6651117.523748606, 70.60821600248704], + [510589.1686524216, 6651112.985150678, 74.67234614448704], + [510589.26860670216, 6651116.69229585, 71.61366335948703], + [510589.2892582107, 6651117.45822743, 71.08548695448704], + [510589.18008922855, 6651113.409323642, 74.59367145148704], + [510589.1581568515, 6651112.595886688, 75.31908416348705], + [510589.2641024903, 6651116.525241805, 72.03547221848703], + [510589.19157948904, 6651113.835479118, 74.47151832948704], + [510589.28619878454, 6651117.344758186, 71.56838797448704], + [510589.2583810076, 6651116.313041114, 72.44582176148704], + [510589.1708818968, 6651113.067838362, 75.27630892248703], + [510589.20294842176, 6651114.2571347365, 74.30440357248703], + [510589.25147534476, 6651116.056921072, 72.83760145548703], + [510589.21400849376, 6651114.667335203, 74.09212576348703], + [510589.2830169329, 6651117.226748373, 71.93009395948705], + [510589.2455613867, 6651115.837581779, 73.11508331548704], + [510589.23906657833, 6651115.5966996765, 73.37552398848705], + [510589.22456805623, 6651115.058972565, 73.83591264048705], + [510589.23204697116, 6651115.336353619, 73.61649363448703], + [510589.1838436113, 6651113.548567724, 75.18714427048704], + [510589.27905864135, 6651117.079941641, 72.28785180548705], + [510589.1936151723, 6651113.910979369, 75.08804877648703], + [510589.27432343713, 6651116.904320451, 72.63830802048703], + [510589.2033385399, 6651114.2716036, 74.96042601748704], + [510589.26882473053, 6651116.700382178, 72.97805304748704], + [510589.2129256882, 6651114.627175668, 74.80393472548704], + [510589.26259028114, 6651116.469156371, 73.30372015748704], + [510589.22228544526, 6651114.974314158, 74.61872582348704], + [510589.2556620456, 6651116.212199143, 73.61208896548705], + [510589.23132599297, 6651115.309613685, 74.40547348848703], + [510589.24809537653, 6651115.931563429, 73.90018731648703], + [510589.23995759216, 6651115.62974596, 74.16538504148703], + [510592.45276433567, 6651104.0387768755, 68.35252413432214], + [510592.46802556765, 6651104.648187035, 68.35252413432214], + [510592.46802556765, 6651104.648187035, 68.48252413432213], + [510592.45276433567, 6651104.0387768755, 70.18132779332214], + [510592.4532890668, 6651104.059730395, 70.64691848032213], + [510592.46802556765, 6651104.648187035, 70.18132779332214], + [510592.46848856576, 6651104.6666754335, 70.59214310532214], + [510592.45492997114, 6651104.1252548415, 71.12418943232214], + [510592.46993642254, 6651104.724491121, 71.01326453332213], + [510592.4577716811, 6651104.238729747, 71.60709045232214], + [510592.47244381363, 6651104.824616039, 71.43935366832216], + [510592.4607271044, 6651104.356745446, 71.96879643732214], + [510592.4760619455, 6651104.969094955, 71.86426017232213], + [510592.4644037142, 6651104.503559503, 72.32655428332214], + [510592.4688019497, 6651104.679189454, 72.67701049832213], + [510592.48081249546, 6651105.158793495, 72.28122687432213], + [510592.4739093549, 6651104.883137903, 73.01675552532214], + [510592.48668293766, 6651105.393211472, 72.68317579132213], + [510592.47970014566, 6651105.114375245, 73.34242263532214], + [510592.4936240119, 6651105.670381833, 73.06305659332213], + [510592.4861353511, 6651105.371345293, 73.65079144332213], + [510592.4994821, 6651105.904306487, 73.32946290832214], + [510592.49316355755, 6651105.65199501, 73.93888979432214], + [510592.5058460518, 6651106.158431242, 73.57717264832213], + [510592.50072223734, 6651105.953827537, 74.20408751932213], + [510592.51501667494, 6651106.524631746, 73.87461511832214], + [510592.50873959076, 6651106.273975783, 74.44417596632213], + [510592.52482479316, 6651106.91628865, 74.13082824132213], + [510592.51713679114, 6651106.609292039, 74.65742830132216], + [510592.53509780334, 6651107.326509581, 74.34310605032213], + [510592.525830485, 6651106.956447848, 74.84263720332214], + [510592.54565769504, 6651107.748186238, 74.51022080732214], + [510592.5347353884, 6651107.312037658, 74.99912849532215], + [510592.5563302806, 6651108.174362975, 74.63237392932214], + [510592.5437668175, 6651107.67267988, 75.12675125432214], + [510592.5669532165, 6651108.598557102, 74.71104862232214], + [510592.55284301034, 6651108.0351096075, 75.22584674832214], + [510592.577382187, 6651109.015005826, 74.74879148132213], + [510592.7734497102, 6651116.844356714, 68.35252413432214], + [510592.5648823376, 6651108.515862952, 75.31501140032215], + [510592.7734497102, 6651116.844356714, 68.48252413432213], + [510592.57670183765, 6651108.987838173, 75.35778664132214], + [510592.7887109422, 6651117.453766873, 68.35252413432214], + [510592.6211930509, 6651110.764457343, 74.74879148132213], + [510592.7734497688, 6651116.844359051, 70.18132779432213], + [510592.77333597414, 6651116.839815014, 70.38514907832213], + [510592.7887109422, 6651117.453766873, 70.18132779332214], + [510592.77239108994, 6651116.802083986, 70.80172836632214], + [510592.6640931494, 6651112.477540261, 74.74879148132213], + [510592.7704214864, 6651116.72343395, 71.22605548632214], + [510592.788186211, 6651117.432813353, 70.64691848032213], + [510592.67452212004, 6651112.893988985, 74.71104862232214], + [510592.7673634099, 6651116.601319114, 71.65236583732215], + [510592.78654530674, 6651117.367288907, 71.12418943232214], + [510592.6851450558, 6651113.318183114, 74.63237392932214], + [510592.7631797288, 6651116.434256734, 72.07417469632213], + [510592.6647734403, 6651112.504705574, 75.35778664132214], + [510592.6958176414, 6651113.744359851, 74.51022080732214], + [510592.7837035968, 6651117.253814002, 71.60709045232214], + [510592.7578654008, 6651116.222045456, 72.48452423932214], + [510592.67659294023, 6651112.976680796, 75.31501140032215], + [510592.7063775331, 6651114.166036505, 74.34310605032213], + [510592.7514511618, 6651115.965912636, 72.87630393332215], + [510592.78074817354, 6651117.1357983025, 71.96879643732214], + [510592.7459580553, 6651115.7465624, 73.15378579332213], + [510592.7166505433, 6651114.5762574375, 74.13082824132213], + [510592.7399254335, 6651115.505668278, 73.41422646632213], + [510592.7264586615, 6651114.96791434, 73.87461511832214], + [510592.7334053586, 6651115.245309232, 73.65519611232213], + [510592.6886322676, 6651113.457434141, 75.22584674832214], + [510592.77707156364, 6651116.988984244, 72.32655428332214], + [510592.69770846044, 6651113.819863868, 75.12675125432214], + [510592.7726733281, 6651116.813354294, 72.67701049832213], + [510592.70673988946, 6651114.180506091, 74.99912849532215], + [510592.7675659229, 6651116.609405844, 73.01675552532214], + [510592.7156447929, 6651114.5360958995, 74.84263720332214], + [510592.7617751322, 6651116.378168503, 73.34242263532214], + [510592.7243384867, 6651114.883251709, 74.65742830132216], + [510592.75533992675, 6651116.121198455, 73.65079144332213], + [510592.7327356871, 6651115.218567966, 74.44417596632213], + [510592.7483117203, 6651115.840548739, 73.93888979432214], + [510592.74075304053, 6651115.538716211, 74.20408751932213], + [510596.67553794186, 6651103.937886111, 68.39739721245486], + [510596.6893976416, 6651104.5473297555, 68.39739721245486], + [510596.6893976416, 6651104.5473297555, 68.52739721245487], + [510596.67553794186, 6651103.937886111, 70.22620087145486], + [510596.67601448385, 6651103.958840781, 70.69179155845485], + [510596.6893976416, 6651104.5473297555, 70.22620087145486], + [510596.68981811975, 6651104.56581917, 70.63701618345486], + [510596.6775046939, 6651104.024368827, 71.16906251045486], + [510596.6911330109, 6651104.623638035, 71.05813761145485], + [510596.6800854321, 6651104.137849968, 71.65196353045486], + [510596.6934101329, 6651104.723768453, 71.48422674645488], + [510596.68276944075, 6651104.255872153, 72.01366951545486], + [510596.6966959895, 6651104.868255309, 71.90913325045486], + [510596.68610840506, 6651104.4026942765, 72.37142736145486], + [510596.7010102675, 6651105.057964272, 72.32609995245485], + [510596.6901027237, 6651104.578333879, 72.72188357645487], + [510596.6947410846, 6651104.782293535, 73.06162860345486], + [510596.706341591, 6651105.292395129, 72.72804886945485], + [510596.70000007167, 6651105.013543581, 73.38729571345486], + [510596.71264522395, 6651105.56958072, 73.10792967145487], + [510596.70584429265, 6651105.27052775, 73.69566452145486], + [510596.71796532796, 6651105.803518227, 73.37433598645487], + [510596.712227056, 6651105.551192887, 73.98376287245486], + [510596.72374483914, 6651106.057656946, 73.62204572645486], + [510596.7190915758, 6651105.853041999, 74.24896059745485], + [510596.7320732677, 6651106.423877573, 73.91948819645486], + [510596.72637264675, 6651106.173207836, 74.48904904445486], + [510596.74098064634, 6651106.815555996, 74.17570131945486], + [510596.7339986807, 6651106.508542517, 74.70230137945487], + [510596.7503102232, 6651107.225799468, 74.38797912845486], + [510596.7418939794, 6651106.855717401, 74.88751028145487], + [510596.75990033546, 6651107.647499295, 74.55509388545487], + [510596.74998109107, 6651107.21132675, 75.04400157345488], + [510596.76959279214, 6651108.073699448, 74.67724700745487], + [510596.75818310864, 6651107.571988788, 75.17162433245487], + [510596.7792401587, 6651108.497916885, 74.75592170045486], + [510596.76642577926, 6651107.934438431, 75.27071982645487], + [510596.96677281527, 6651116.744169581, 68.39739721245486], + [510596.78871137305, 6651108.914388492, 74.79366455945485], + [510596.96677281527, 6651116.744169581, 68.52739721245487], + [510596.77735946135, 6651108.415218192, 75.35988447845486], + [510596.98063251487, 6651117.353613226, 68.39739721245486], + [510596.78809350426, 6651108.887219346, 75.40265971945486], + [510596.8284988171, 6651110.663936135, 74.79366455945485], + [510596.9667728685, 6651116.744171919, 70.22620087245485], + [510596.9666695243, 6651116.739627633, 70.43002215645485], + [510596.98063251487, 6651117.353613226, 70.22620087145486], + [510596.96581141464, 6651116.70189453, 70.84660144445486], + [510596.980155973, 6651117.332658556, 70.69179155845485], + [510596.96402269177, 6651116.623240175, 71.27092856445486], + [510596.867459137, 6651112.377113184, 74.79366455945485], + [510596.9612454572, 6651116.501118627, 71.69723891545486], + [510596.8769303513, 6651112.793584791, 74.75592170045486], + [510596.97866576293, 6651117.26713051, 71.16906251045486], + [510596.95744598925, 6651116.334047068, 72.11904777445486], + [510596.8865777179, 6651113.217802227, 74.67724700745487], + [510596.8680769526, 6651112.404279989, 75.40265971945486], + [510596.97608502477, 6651117.153649368, 71.65196353045486], + [510596.9526197084, 6651116.1218241295, 72.52939731745488], + [510596.89627017465, 6651113.644002382, 74.55509388545487], + [510596.9467945282, 6651115.865677235, 72.92117701145486], + [510596.90586028685, 6651114.065702207, 74.38797912845486], + [510596.87881099543, 6651112.876281145, 75.35988447845486], + [510596.973401016, 6651117.0356271835, 72.01366951545486], + [510596.94180588744, 6651115.646314947, 73.19865887145485], + [510596.9151898636, 6651114.4759456795, 74.17570131945486], + [510596.93632727815, 6651115.405407589, 73.45909954445486], + [510596.9240972423, 6651114.867624102, 73.91948819645486], + [510596.93040598166, 6651115.145034237, 73.70006919045485], + [510596.9700620517, 6651116.88880506, 72.37142736145486], + [510596.8897446776, 6651113.3570609065, 75.27071982645487], + [510596.9660677331, 6651116.713165458, 72.72188357645487], + [510596.8979873482, 6651113.719510548, 75.17162433245487], + [510596.96142937226, 6651116.509205802, 73.06162860345486], + [510596.9061893658, 6651114.080172587, 75.04400157345488], + [510596.91427647736, 6651114.435781935, 74.88751028145487], + [510596.9561703852, 6651116.277955756, 73.38729571345486], + [510596.9221717761, 6651114.782956819, 74.70230137945487], + [510596.9503261642, 6651116.020971587, 73.69566452145486], + [510596.9297978101, 6651115.1182915, 74.48904904445486], + [510596.94394340087, 6651115.740306449, 73.98376287245486], + [510596.937078881, 6651115.438457337, 74.24896059745485], + [510609.1755280418, 6651103.696178987, 68.52052626257824], + [510609.18523901305, 6651104.305702854, 68.52052626257824], + [510609.18523901305, 6651104.305702854, 68.65052626257824], + [510609.3450717457, 6651103.693485635, 68.52209666841532], + [510609.3547264457, 6651104.303010396, 68.52209666841532], + [510609.3547264457, 6651104.303010396, 68.65209666841531], + [510609.1755280418, 6651103.696178987, 70.34932992157825], + [510609.18523901305, 6651104.305702854, 70.34932992157825], + [510609.17586193676, 6651103.717136416, 70.81492060857825], + [510609.1855336263, 6651104.324194701, 70.76014523357826], + [510609.176906071, 6651103.782673088, 71.29219156057825], + [510609.3450717457, 6651103.693485635, 70.35090032741533], + [510609.18645492126, 6651104.382021178, 71.18126666157823], + [510609.1787142974, 6651103.896169165, 71.77509258057825], + [510609.3547264457, 6651104.303010396, 70.35090032741533], + [510609.3454037059, 6651103.714443094, 70.8164910144153], + [510609.18805041513, 6651104.482164776, 71.60735579657825], + [510609.18059488165, 6651104.014206886, 72.13679856557826], + [510609.3550193518, 6651104.321502272, 70.76171563941531], + [510609.3464417898, 6651103.779979862, 71.29376196641532], + [510609.19035269157, 6651104.626670651, 72.03226230057824], + [510609.18293436855, 6651104.161048336, 72.49455641157826], + [510609.3559353081, 6651104.379328833, 71.1828370674153], + [510609.3482395383, 6651103.893476107, 71.77666298641533], + [510609.1933755441, 6651104.816404587, 72.44922900257824], + [510609.1857330377, 6651104.336711057, 72.84501262657824], + [510609.3575215568, 6651104.479472578, 71.60892620241532], + [510609.3501092252, 6651104.011514001, 72.13836897141532], + [510609.18898296304, 6651104.540697562, 73.18475765357825], + [510609.19711100246, 6651105.050866302, 72.85117791957825], + [510609.3598104924, 6651104.623978665, 72.03383270641532], + [510609.3524351556, 6651104.158355666, 72.49612681741532], + [510609.1926677378, 6651104.771978049, 73.51042476357824], + [510609.2015277214, 6651105.32808838, 73.23105872157824], + [510609.36281582864, 6651104.813712877, 72.4507994084153], + [510609.35521760763, 6651104.334018646, 72.84658303241531], + [510609.1967625641, 6651105.028996043, 73.81879357157825], + [510609.20525531855, 6651105.56205668, 73.49746503657823], + [510609.3584487009, 6651104.538005449, 73.18632805941533], + [510609.36652964144, 6651105.048174938, 72.85274832541532], + [510609.20123472676, 6651105.309698125, 74.10689192257824], + [510609.20930480503, 6651105.816228851, 73.74517477657824], + [510609.3621121238, 6651104.769286274, 73.51199516941531], + [510609.37092076725, 6651105.325397422, 73.23262912741531], + [510609.2060444381, 6651105.611586971, 74.37208964757824], + [510609.2151402224, 6651106.182497685, 74.04261724657826], + [510609.3661832222, 6651105.026304646, 73.82036397741531], + [510609.3746267645, 6651105.559366065, 73.49903544241532], + [510609.2111460112, 6651105.931794952, 74.61217809457824], + [510609.22138128825, 6651106.5742276665, 74.29883036957824], + [510609.3706294704, 6651105.3070071405, 74.10846232841533], + [510609.37865278573, 6651105.81353861, 73.74674518241531], + [510609.2164892869, 6651106.267173775, 74.82543042957825], + [510609.2279181725, 6651106.984525139, 74.51110817857824], + [510609.37541131146, 6651105.608896428, 74.3736600534153], + [510609.38445438904, 6651106.17980798, 74.04418765241532], + [510609.2220212264, 6651106.6143943565, 75.01063933157825], + [510609.23463760415, 6651107.406280475, 74.67822293557825], + [510609.38048332284, 6651105.92910488, 74.61374850041531], + [510609.22768756194, 6651106.970050516, 75.16713062357825], + [510609.39065929037, 6651106.571538536, 74.30040077541531], + [510609.24142874463, 6651107.832536731, 74.80037605757825], + [510609.3857956364, 6651106.264484194, 74.82700083541532], + [510609.23343440774, 6651107.330760027, 75.29475338257824], + [510609.39715829596, 6651106.98183661, 74.51267858441531], + [510609.3795853851, 6651116.504148172, 68.52052626257824], + [510609.24818829226, 6651108.256810007, 74.87905075057824], + [510609.2392097376, 6651107.693257379, 75.39384887657825], + [510609.3795853851, 6651116.504148172, 68.65052626257824], + [510609.39129552036, 6651106.611705286, 75.01220973741532], + [510609.25482441665, 6651108.673336434, 74.91679360957824], + [510609.403838791, 6651107.403592563, 74.67979334141532], + [510609.3892963563, 6651117.11367204, 68.52052626257824], + [510609.3969290217, 6651106.967361964, 75.16870102941532], + [510609.2468705583, 6651108.174100428, 75.48301352857824], + [510609.4105905796, 6651107.829849445, 74.80194646341532], + [510609.4026425668, 6651107.328072008, 75.29632378841531], + [510609.25439149915, 6651108.646163712, 75.52578876957826], + [510609.5479466559, 6651116.501473606, 68.52209666841532], + [510609.4173109583, 6651108.254123345, 74.88062115641533], + [510609.5479466559, 6651116.501473606, 68.65209666841531], + [510609.4083844308, 6651107.69056989, 75.39541928241533], + [510609.4239086289, 6651108.6706503825, 74.91836401541532], + [510609.5576013559, 6651117.110998366, 68.52209666841532], + [510609.2827019851, 6651110.423114375, 74.91679360957824], + [510609.41600086004, 6651108.171413644, 75.48458393441531], + [510609.37958542234, 6651116.504150511, 70.34932992257825], + [510609.3795130129, 6651116.499605627, 70.55315120657824], + [510609.42347822, 6651108.643477621, 75.52735917541531], + [510609.3892963563, 6651117.11367204, 70.34932992157825], + [510609.3789117677, 6651116.461867557, 70.96973049457824], + [510609.3889624613, 6651117.092714612, 70.81492060857825], + [510609.37765847676, 6651116.383202848, 71.39405761457826], + [510609.45162465767, 6651110.420430889, 74.91836401541532], + [510609.54794669297, 6651116.501475945, 70.3509003284153], + [510609.3100000188, 6651112.1365169315, 74.91679360957824], + [510609.3757125727, 6651116.261065225, 71.82036796557824], + [510609.38791832706, 6651117.027177939, 71.29219156057825], + [510609.54787470313, 6651116.496931053, 70.55472161241532], + [510609.31663614314, 6651112.553043359, 74.87905075057824], + [510609.3730504281, 6651116.093971674, 72.24217682457824], + [510609.5576013559, 6651117.110998366, 70.35090032741533], + [510609.38611010066, 6651116.913681861, 71.77509258057825], + [510609.32339569076, 6651112.977316637, 74.80037605757825], + [510609.5472769419, 6651116.459192928, 70.97130090041533], + [510609.3696688343, 6651115.881720801, 72.65252636757825], + [510609.3104328989, 6651112.163687313, 75.52578876957826], + [510609.3301868313, 6651113.403572893, 74.67822293557825], + [510609.38422951655, 6651116.795644141, 72.13679856557826], + [510609.3655873492, 6651115.625540189, 73.04430606157824], + [510609.3369062629, 6651113.825328227, 74.51110817857824], + [510609.36209199595, 6651115.406149025, 73.32178792157825], + [510609.5572693957, 6651117.090040907, 70.8164910144153], + [510609.3179538399, 6651112.635750599, 75.48301352857824], + [510609.5460309133, 6651116.380528104, 71.39562802041532], + [510609.35825334, 6651115.1652099565, 73.58222859457825], + [510609.3434431472, 6651114.235625701, 74.29883036957824], + [510609.35410450987, 6651114.904802331, 73.82319824057824], + [510609.38189002965, 6651116.64880269, 72.49455641157826], + [510609.349684213, 6651114.627355681, 74.04261724657826], + [510609.4787645098, 6651112.13383596, 74.91836401541532], + [510609.32561466057, 6651113.116593648, 75.39384887657825], + [510609.3790913605, 6651116.47313997, 72.84501262657824], + [510609.54409628507, 6651116.258390302, 71.82193837141531], + [510609.5562313118, 6651117.024504139, 71.29376196641532], + [510609.33138999034, 6651113.479090998, 75.29475338257824], + [510609.3758414351, 6651116.269153465, 73.18475765357825], + [510609.48536218033, 6651112.550362998, 74.88062115641533], + [510609.33713683626, 6651113.8398005115, 75.16713062357825], + [510609.5414495666, 6651116.091296505, 72.24374723041532], + [510609.3721566603, 6651116.0378729785, 73.51042476357824], + [510609.3428031718, 6651114.195456669, 75.01063933157825], + [510609.36806183396, 6651115.780854982, 73.81879357157825], + [510609.5544335634, 6651116.911007894, 71.77666298641533], + [510609.49208255904, 6651112.9746368965, 74.80194646341532], + [510609.34833511116, 6651114.542677253, 74.82543042957825], + [510609.3635896713, 6651115.500152901, 74.10689192257824], + [510609.3536783869, 6651114.8780560745, 74.61217809457824], + [510609.3587799599, 6651115.198264056, 74.37208964757824], + [510609.5380875677, 6651115.879045322, 72.65409677341532], + [510609.47919488157, 6651112.161006381, 75.52735917541531], + [510609.49883434764, 6651113.400893778, 74.67979334141532], + [510609.55256387644, 6651116.792970001, 72.13836897141532], + [510609.5340297333, 6651115.622864335, 73.04587646741531], + [510609.50551484275, 6651113.822649731, 74.51267858441531], + [510609.5305546342, 6651115.403472849, 73.32335832741532], + [510609.4866722416, 6651112.633070359, 75.48458393441531], + [510609.5267382219, 6651115.162533427, 73.58379900041531], + [510609.51201384823, 6651114.232947806, 74.30040077541531], + [510609.52261343255, 6651114.902125418, 73.82476864641532], + [510609.550237946, 6651116.646128335, 72.49612681741532], + [510609.51821874955, 6651114.624678362, 74.04418765241532], + [510609.4942886708, 6651113.113914112, 75.39541928241533], + [510609.54745549406, 6651116.4704653565, 72.84658303241531], + [510609.50003053475, 6651113.476411995, 75.29632378841531], + [510609.54422440066, 6651116.266478554, 73.18632805941533], + [510609.50574408, 6651113.837122037, 75.16870102941532], + [510609.54056097777, 6651116.035197727, 73.51199516941531], + [510609.5113775812, 6651114.192778716, 75.01220973741532], + [510609.53648987936, 6651115.778179355, 73.82036397741531], + [510609.5168774652, 6651114.539999809, 74.82700083541532], + [510609.5320436312, 6651115.497476861, 74.10846232841533], + [510609.52218977874, 6651114.875379123, 74.61374850041531], + [510609.5272617901, 6651115.195587574, 74.3736600534153], + [510613.89348648244, 6651103.627073775, 68.5632313089762], + [510613.9016315702, 6651104.236620578, 68.5632313089762], + [510613.9016315702, 6651104.236620578, 68.69323130897621], + [510613.89348648244, 6651103.627073775, 70.3920349679762], + [510613.9016315702, 6651104.236620578, 70.3920349679762], + [510613.8937665372, 6651103.648031992, 70.85762565497619], + [510613.90187867737, 6651104.255113122, 70.8028502799762], + [510613.89464230597, 6651103.71357113, 71.3348966069762], + [510613.9026514145, 6651104.312941775, 71.22397170797619], + [510613.8961589578, 6651103.82707148, 71.8177976269762], + [510613.90398963675, 6651104.413089141, 71.65006084297622], + [510613.89773629984, 6651103.945113642, 72.1795036119762], + [510613.90592067357, 6651104.5576004535, 72.0749673469762], + [510613.89969854703, 6651104.091960617, 72.5372614579762], + [510613.9084560945, 6651104.747341528, 72.49193404897619], + [510613.9020459338, 6651104.267629948, 72.88771767297621], + [510613.90477181226, 6651104.471624129, 73.2274626999762], + [510613.9115892142, 6651104.981812067, 72.89388296597619], + [510613.9078624212, 6651104.702913318, 73.5531298099762], + [510613.9152937421, 6651105.2590445755, 73.2737637679762], + [510613.91129696125, 6651104.959940986, 73.8614986179762], + [510613.9184202683, 6651105.49302168, 73.5401700829762], + [510613.91504799254, 6651105.240653629, 74.1495969689762], + [510613.92181677953, 6651105.747203415, 73.7878798229762], + [510613.9190821432, 6651105.542553835, 74.41479469397619], + [510613.92671124224, 6651106.113486032, 74.0853222929762], + [510613.92336109316, 6651105.862773865, 74.6548831409762], + [510613.931945943, 6651106.505230753, 74.3415354159762], + [510613.9278427716, 6651106.198165307, 74.8681354759762], + [510613.9374287619, 6651106.915543665, 74.5538132249762], + [510613.9324826919, 6651106.545398956, 75.0533443779762], + [510613.94306469255, 6651107.337314871, 74.7209279819762], + [510613.937235337, 6651106.901068497, 75.20983566997621], + [510613.9487607691, 6651107.763587167, 74.8430811039762], + [510613.94205551024, 6651107.261791583, 75.3374584289762], + [510614.0646398025, 6651116.435524915, 68.5632313089762], + [510614.0646398025, 6651116.435524915, 68.69323130897621], + [510613.9544303471, 6651108.187876408, 74.9217557969762], + [510613.9468995745, 6651107.624302576, 75.4365539229762], + [510614.0727848903, 6651117.045071719, 68.5632313089762], + [510613.9599964036, 6651108.60441851, 74.95949865597619], + [510613.95332509617, 6651108.105163718, 75.5257185749762], + [510613.9596332937, 6651108.577244766, 75.5684938159762], + [510614.06463983376, 6651116.435527254, 70.39203496897619], + [510613.98337874474, 6651110.354262293, 74.95949865597619], + [510614.06457910023, 6651116.4309822, 70.59585625297619], + [510614.0727848903, 6651117.045071719, 70.3920349679762], + [510614.0640748052, 6651116.393242709, 71.0124355409762], + [510614.07250483544, 6651117.024113502, 70.85762565497619], + [510614.063023606, 6651116.314575039, 71.4367626609762], + [510614.06139147695, 6651116.192432822, 71.8630730119762], + [510614.0062750003, 6651112.067729325, 74.95949865597619], + [510614.07162906666, 6651116.958574363, 71.3348966069762], + [510614.01184105687, 6651112.484271425, 74.9217557969762], + [510614.05915860017, 6651116.025332983, 72.28488187097619], + [510614.0701124148, 6651116.845074014, 71.8177976269762], + [510614.01751063485, 6651112.908560668, 74.8430811039762], + [510614.05632228474, 6651115.813074122, 72.69523141397622], + [510614.006638079, 6651112.094900728, 75.5684938159762], + [510614.06853507285, 6651116.727031852, 72.1795036119762], + [510614.0232067114, 6651113.3348329635, 74.7209279819762], + [510614.0528989346, 6651115.556883871, 73.08701110797621], + [510614.0499672032, 6651115.337484452, 73.36449296797619], + [510614.02884264203, 6651113.756604169, 74.5538132249762], + [510614.0467475264, 6651115.096536316, 73.6249336409762], + [510614.0129462765, 6651112.566981778, 75.5257185749762], + [510614.06657282566, 6651116.580184877, 72.5372614579762], + [510614.03432546085, 6651114.166917081, 74.3415354159762], + [510614.0432676906, 6651114.836118892, 73.86590328697619], + [510614.0395601617, 6651114.558661803, 74.0853222929762], + [510614.0642254388, 6651116.404515545, 72.88771767297621], + [510614.01937179815, 6651113.04784292, 75.4365539229762], + [510614.06149956037, 6651116.200521367, 73.2274626999762], + [510614.0242158624, 6651113.41035391, 75.3374584289762], + [510614.0584089515, 6651115.9692321755, 73.5531298099762], + [510614.02903603564, 6651113.771076997, 75.20983566997621], + [510614.05497441144, 6651115.7122045085, 73.8614986179762], + [510614.0337886808, 6651114.126746538, 75.0533443779762], + [510614.05122338014, 6651115.431491864, 74.1495969689762], + [510614.038428601, 6651114.4739801865, 74.8681354759762], + [510614.04718922934, 6651115.12959166, 74.41479469397619], + [510614.0429102794, 6651114.809371629, 74.6548831409762], + [510626.23984072346, 6651103.503599185, 68.66521709454246], + [510626.2438880744, 6651104.11318697, 68.66521709454246], + [510626.2438880744, 6651104.11318697, 68.79521709454245], + [510626.23984072346, 6651103.503599185, 70.49402075354247], + [510626.2438880744, 6651104.11318697, 70.49402075354247], + [510626.23997988465, 6651103.524558811, 70.95961144054245], + [510626.2440108637, 6651104.131680758, 70.90483606554245], + [510626.24041506025, 6651103.590102356, 71.43688239254246], + [510626.2443948422, 6651104.189513296, 71.32595749354245], + [510626.2411686951, 6651103.7036103355, 71.91978341254247], + [510626.2450598141, 6651104.289667396, 71.75204662854246], + [510626.2419524874, 6651103.821660434, 72.28148939754246], + [510626.2460193598, 6651104.434188425, 72.17695313254247], + [510626.24292754167, 6651103.968517283, 72.63924724354246], + [510626.2472792281, 6651104.623942256, 72.59391983454245], + [510626.2440939746, 6651104.144198425, 72.98970345854245], + [510626.24544848263, 6651104.348206319, 73.32944848554247], + [510626.2488360972, 6651104.858428558, 72.99586875154245], + [510626.2469842277, 6651104.579511059, 73.65511559554245], + [510626.2506769029, 6651105.135679706, 73.37574955354245], + [510626.2486908746, 6651104.836556006, 73.96348440354245], + [510626.25223049556, 6651105.369672542, 73.64215586854246], + [510626.2539182457, 6651105.623871366, 73.88986560854245], + [510626.2505547882, 6651105.117287523, 74.25158275454245], + [510626.2525593859, 6651105.419208026, 74.51678047954245], + [510626.2563503383, 6651105.990178609, 74.18730807854246], + [510626.25468562596, 6651105.739449585, 74.75686892654245], + [510626.2589514977, 6651106.381949667, 74.44352120154245], + [510626.2569126032, 6651106.074863577, 74.97012126154247], + [510626.26167594857, 6651106.792290165, 74.65579901054245], + [510626.25921821187, 6651106.422120571, 75.15533016354246], + [510626.2644764818, 6651107.214089728, 74.82291376754246], + [510626.2615798344, 6651106.777814023, 75.31182145554246], + [510626.32488800184, 6651116.312911464, 68.66521709454246], + [510626.32488800184, 6651116.312911464, 68.79521709454245], + [510626.26730690204, 6651107.640390683, 74.94506688954246], + [510626.2639750121, 6651107.138561362, 75.43944421454245], + [510626.32893535285, 6651116.922499247, 68.66521709454246], + [510626.2701241548, 6651108.06470845, 75.02374158254247], + [510626.2663820614, 6651107.501096726, 75.53853970854247], + [510626.2728899672, 6651108.481278556, 75.06148444154246], + [510626.26957494795, 6651107.981990198, 75.62770436054247], + [510626.27270953526, 6651108.454102986, 75.67047960154245], + [510626.3248880174, 6651116.3129138015, 70.49402075454245], + [510626.32485783857, 6651116.308368442, 70.69784203854246], + [510626.2845088155, 6651110.231239986, 75.06148444154246], + [510626.32893535285, 6651116.922499247, 70.49402075354247], + [510626.3246072508, 6651116.270626414, 71.11442132654247], + [510626.3287961916, 6651116.901539621, 70.95961144054245], + [510626.3240849026, 6651116.191953456, 71.53874844654246], + [510626.3232738862, 6651116.0698030265, 71.96505879754247], + [510626.328361016, 6651116.835996076, 71.43688239254246], + [510626.29588612466, 6651111.9448222155, 75.06148444154246], + [510626.32216435426, 6651115.902691952, 72.38686765654246], + [510626.3276073811, 6651116.722488096, 71.91978341254247], + [510626.29865193693, 6651112.361392322, 75.02374158254247], + [510626.32075496926, 6651115.690418822, 72.79721719954246], + [510626.30146918976, 6651112.78571009, 74.94506688954246], + [510626.32682358887, 6651116.6044379985, 72.28148939754246], + [510626.31905388273, 6651115.434211346, 73.18899689354245], + [510626.29606654093, 6651111.971995447, 75.67047960154245], + [510626.30429960997, 6651113.212011044, 74.82291376754246], + [510626.3175970849, 6651115.2147971755, 73.46647875354245], + [510626.3258485345, 6651116.457581149, 72.63924724354246], + [510626.30710014317, 6651113.633810608, 74.65579901054245], + [510626.3159972051, 6651114.973832841, 73.72691942654245], + [510626.3142680504, 6651114.713397908, 73.96788907254245], + [510626.3098245941, 6651114.044151105, 74.44352120154245], + [510626.3124257535, 6651114.435922164, 74.18730807854246], + [510626.2992011283, 6651112.444108235, 75.62770436054247], + [510626.32468210167, 6651116.281900008, 72.98970345854245], + [510626.3233275936, 6651116.0778921135, 73.32944848554247], + [510626.3023940148, 6651112.925001705, 75.53853970854247], + [510626.30480106414, 6651113.28753707, 75.43944421454245], + [510626.3217918486, 6651115.846587373, 73.65511559554245], + [510626.3071962418, 6651113.648284409, 75.31182145554246], + [510626.32008520165, 6651115.589542426, 73.96348440354245], + [510626.3095578643, 6651114.003977861, 75.15533016354246], + [510626.31822128803, 6651115.308810909, 74.25158275454245], + [510626.31186347303, 6651114.351234855, 74.97012126154247], + [510626.31621669047, 6651115.006890406, 74.51678047954245], + [510626.3140904503, 6651114.686648847, 74.75686892654245], + [510629.4247079386, 6651103.4852147475, 68.68923256011365], + [510629.4276982368, 6651104.094808633, 68.68923256011365], + [510629.4276982368, 6651104.094808633, 68.81923256011363], + [510629.4247079386, 6651103.4852147475, 70.51803621911364], + [510629.4276982368, 6651104.094808633, 70.51803621911364], + [510629.4248107548, 6651103.506174582, 70.98362690611363], + [510629.42778895696, 6651104.113302606, 70.92885153111364], + [510629.4251322749, 6651103.571718783, 71.46089785811365], + [510629.4280726512, 6651104.171135723, 71.34997295911364], + [510629.4256890819, 6651103.6852279, 71.94379887811364], + [510629.4285639514, 6651104.271290826, 71.77606209411364], + [510629.4262681699, 6651103.80327918, 72.30550486311364], + [510629.4292728911, 6651104.415813303, 72.20096859811363], + [510629.42698856787, 6651103.950137498, 72.66326270911364], + [510629.4302037177, 6651104.605569031, 72.61793530011364], + [510629.4278503617, 6651104.125820398, 73.01371892411363], + [510629.42885111074, 6651104.3298303345, 73.35346395111364], + [510629.43135397695, 6651104.840057681, 73.01988421711363], + [510629.429985763, 6651104.561137389, 73.67913106111364], + [510629.43271401664, 6651105.117311604, 73.39976501911363], + [510629.43124668236, 6651104.818184911, 73.98749986911363], + [510629.43386185524, 6651105.351306782, 73.66617133411366], + [510629.4351088131, 6651105.6055081505, 73.91388107411363], + [510629.4326237949, 6651105.098919239, 74.27559822011365], + [510629.4341048487, 6651105.400842763, 74.54079594511363], + [510629.43690571235, 6651105.971819059, 74.21132354411364], + [510629.43567577546, 6651105.721087527, 74.78088439211363], + [510629.438827523, 6651106.363594039, 74.46753666711363], + [510629.4373211297, 6651106.056504875, 74.99413672711364], + [510629.440840425, 6651106.773938647, 74.67981447611365], + [510629.4390245791, 6651106.403765346, 75.17934562911366], + [510629.4429095387, 6651107.19574243, 74.84692923311364], + [510629.48754329083, 6651116.294655242, 68.68923256011365], + [510629.44076941314, 6651106.75946236, 75.33583692111364], + [510629.48754329083, 6651116.294655242, 68.81923256011363], + [510629.4450007338, 6651107.622047652, 74.96908235511364], + [510629.4905335889, 6651116.904249128, 68.68923256011365], + [510629.4425390386, 6651107.120213309, 75.46345968011363], + [510629.44708220044, 6651108.046369667, 75.04775704811364], + [510629.4443174352, 6651107.482752302, 75.56255517411364], + [510629.4491256614, 6651108.462943942, 75.08549990711363], + [510629.4466764307, 6651107.963650586, 75.65171982611363], + [510629.44899235317, 6651108.4357680995, 75.69449506711364], + [510629.4875433023, 6651116.294657581, 70.51803622011363], + [510629.48752100527, 6651116.290112174, 70.72185750411363], + [510629.4577099976, 6651110.212922889, 75.08549990711363], + [510629.4905335889, 6651116.904249128, 70.51803621911364], + [510629.4873358639, 6651116.25236977, 71.13843679211364], + [510629.4904307727, 6651116.8832892915, 70.98362690611363], + [510629.4869499381, 6651116.173696023, 71.56276391211364], + [510629.49010925257, 6651116.817745091, 71.46089785811365], + [510629.4863507362, 6651116.05154437, 71.98907426311364], + [510629.4661158777, 6651111.926522272, 75.08549990711363], + [510629.4855309823, 6651115.884431624, 72.41088312211363], + [510631.1135923384, 6651103.4777066065, 68.7015861260573], + [510629.4895524457, 6651116.704235976, 71.94379887811364], + [510629.4681593386, 6651112.343096547, 75.04775704811364], + [510629.48448968853, 6651115.672156369, 72.82123266511364], + [510629.4889733576, 6651116.586184695, 72.30550486311364], + [510629.47024080524, 6651112.767418562, 74.96908235511364], + [510631.1160220983, 6651104.087302984, 68.7015861260573], + [510629.4832328774, 6651115.415946329, 73.21301235911363], + [510631.1160220983, 6651104.087302984, 68.83158612605729], + [510629.46624917444, 6651111.953695774, 75.69449506711364], + [510629.47233200027, 6651113.193723784, 74.84692923311364], + [510629.48215655365, 6651115.196529962, 73.49049421911363], + [510629.4882529597, 6651116.439326376, 72.66326270911364], + [510629.4809745169, 6651114.955563216, 73.75093489211363], + [510629.4744011141, 6651113.615527568, 74.67981447611365], + [510629.4796969681, 6651114.695125677, 73.99190453811364], + [510629.476414016, 6651114.025872175, 74.46753666711363], + [510629.4783358266, 6651114.417647155, 74.21132354411364], + [510629.48739116587, 6651116.263643475, 73.01371892411363], + [510629.4685650968, 6651112.425813288, 75.65171982611363], + [510629.48639041674, 6651116.059633539, 73.35346395111364], + [510629.47092409234, 6651112.906711572, 75.56255517411364], + [510629.4852557645, 6651115.828326484, 73.67913106111364], + [510629.47270248894, 6651113.269250565, 75.46345968011363], + [510629.4839948451, 6651115.571278964, 73.98749986911363], + [510629.4744721144, 6651113.630001515, 75.33583692111364], + [510629.48261773266, 6651115.290544637, 74.27559822011365], + [510629.4762169484, 6651113.985698529, 75.17934562911366], + [510629.48113667883, 6651114.988621112, 74.54079594511363], + [510629.4779203979, 6651114.332958998, 74.99413672711364], + [510629.47956575215, 6651114.668376348, 74.78088439211363], + [510631.1135923384, 6651103.4777066065, 70.5303897850573], + [510631.1160220983, 6651104.087302984, 70.5303897850573], + [510631.1136758815, 6651103.498666528, 70.99598047205728], + [510631.1160958128, 6651104.105797033, 70.9412050970573], + [510631.1139371319, 6651103.564210997, 71.4732514240573], + [510631.11632632784, 6651104.163630388, 71.36232652505728], + [510631.11438956414, 6651103.6777205765, 71.9561524440573], + [510631.11672553275, 6651104.2637859, 71.7884156600573], + [510631.1148601008, 6651103.795772339, 72.3178584290573], + [510631.1173015801, 6651104.408308966, 72.21332216405729], + [510631.11544545845, 6651103.942631259, 72.6756162750573], + [510631.11805792106, 6651104.598065472, 72.63028886605728], + [510631.1161457071, 6651104.118314878, 73.02607249005729], + [510631.1169588634, 6651104.322325647, 73.3658175170573], + [510631.11899256153, 6651104.832555079, 73.0322377830573], + [510631.1178808225, 6651104.553633648, 73.6914846270573], + [510631.1200976588, 6651105.109810137, 73.41211858505729], + [510631.1189053796, 6651104.81068222, 73.99985343505729], + [510631.1210303323, 6651105.3438062705, 73.67852490005728], + [510631.12204354507, 6651105.598008678, 73.9262346400573], + [510631.12002434925, 6651105.091417694, 74.28795178605729], + [510631.12122777617, 6651105.393342453, 74.5531495110573], + [510631.1235036115, 6651105.964321085, 74.22367711005731], + [510631.122504229, 6651105.7135885265, 74.7932379580573], + [510631.12506517424, 6651106.356097667, 74.4798902330573], + [510631.1238411578, 6651106.049007246, 75.0064902930573], + [510631.1267007531, 6651106.766443949, 74.69216804205729], + [510631.12522529176, 6651106.396269136, 75.1916991950573], + [510631.1283820068, 6651107.188249458, 74.85928279905731], + [510631.1646490596, 6651116.287199465, 68.7015861260573], + [510631.1646490596, 6651116.287199465, 68.83158612605729], + [510631.1266430526, 6651106.751967603, 75.3481904870573], + [510631.13008120254, 6651107.614556422, 74.98143592105731], + [510631.1670788195, 6651116.896795843, 68.7015861260573], + [510631.12808095774, 6651107.1127200285, 75.47581324605729], + [510631.1317724935, 6651108.038880172, 75.0601106140573], + [510631.1295259898, 6651107.475260503, 75.5749087400573], + [510631.13343290304, 6651108.455456151, 75.09785347305728], + [510631.13144278625, 6651107.956160753, 75.66407339205729], + [510631.13332458364, 6651108.428280197, 75.70684863305729], + [510631.16464906896, 6651116.287201805, 70.53038978605728], + [510631.16463095153, 6651116.282656379, 70.73421107005728], + [510631.1670788195, 6651116.896795843, 70.5303897850573], + [510631.14040808566, 6651110.205442251, 75.09785347305728], + [510631.1644805153, 6651116.244913819, 71.1507903580573], + [510631.16699527646, 6651116.875835921, 70.99598047205728], + [510631.16416693234, 6651116.1662397515, 71.5751174780573], + [510631.166734026, 6651116.810291452, 71.4732514240573], + [510631.1636800521, 6651116.0440876, 72.00142782905729], + [510631.1472382642, 6651111.919048638, 75.09785347305728], + [510631.16301396297, 6651115.87697417, 72.42323668805729], + [510631.16628159373, 6651116.696781872, 71.9561524440573], + [510631.14889867377, 6651112.335624617, 75.0601106140573], + [510631.1621678622, 6651115.664698048, 72.8335862310573], + [510631.16581105714, 6651116.57873011, 72.3178584290573], + [510631.1505899647, 6651112.759948367, 74.98143592105731], + [510631.1611466431, 6651115.40848696, 73.22536592505729], + [510631.15228916047, 6651113.186255332, 74.85928279905731], + [510631.1602720787, 6651115.189069697, 73.50284778505731], + [510631.14734657423, 6651111.946222252, 75.70684863305729], + [510631.1652256994, 6651116.431871191, 72.6756162750573], + [510631.1593116174, 6651114.948101965, 73.76328845805729], + [510631.153970414, 6651113.6080608405, 74.69216804205729], + [510631.15827354806, 6651114.6876633605, 74.00425810405729], + [510631.15560599294, 6651114.018407123, 74.4798902330573], + [510631.15716755576, 6651114.410183704, 74.22367711005731], + [510631.16452545085, 6651116.256187573, 73.02607249005729], + [510631.14922837156, 6651112.418341696, 75.66407339205729], + [510631.1637122944, 6651116.0521768015, 73.3658175170573], + [510631.15114516806, 6651112.899241946, 75.5749087400573], + [510631.16279033537, 6651115.820868801, 73.6914846270573], + [510631.1525902001, 6651113.261782422, 75.47581324605729], + [510631.1617657782, 6651115.563820231, 73.99985343505729], + [510631.15402810526, 6651113.622534845, 75.3481904870573], + [510631.1606468086, 6651115.283084755, 74.28795178605729], + [510631.1554458661, 6651113.978233313, 75.1916991950573], + [510631.1594433817, 6651114.981159996, 74.5531495110573], + [510631.15683000005, 6651114.325495202, 75.0064902930573], + [510631.1581669288, 6651114.660913923, 74.7932379580573], + [510643.1356416159, 6651103.469133594, 68.78188541270163], + [510643.1340812753, 6651104.0787328165, 68.78188541270163], + [510643.1340812753, 6651104.0787328165, 68.91188541270164], + [510643.1356416159, 6651103.469133594, 70.61068907170163], + [510643.1340812753, 6651104.0787328165, 70.61068907170163], + [510643.1355879663, 6651103.490093613, 71.07627975870162], + [510643.13403393736, 6651104.097226952, 71.02150438370163], + [510643.13542019675, 6651103.555638387, 71.55355071070163], + [510643.1338859055, 6651104.155060575, 71.44262581170162], + [510643.1351296543, 6651103.669148497, 72.03645173070163], + [510643.13362954446, 6651104.255216556, 71.86871494670164], + [510643.1348274856, 6651103.78720081, 72.39815771570163], + [510643.13325961906, 6651104.399740296, 72.29362145070162], + [510643.1344515812, 6651103.934060415, 72.75591556170163], + [510643.13277391274, 6651104.589497688, 72.71058815270162], + [510643.1340018963, 6651104.109744854, 73.10637177670164], + [510643.13217370637, 6651104.823988391, 73.11253706970165], + [510643.1334797045, 6651104.313756577, 73.44611680370163], + [510643.13288764184, 6651104.545065657, 73.77178391370163], + [510643.1314640363, 6651105.101244741, 73.49241787170163], + [510643.13222969277, 6651104.802115428, 74.08015272170162], + [510643.130865093, 6651105.335241968, 73.75882418670162], + [510643.1302144291, 6651105.589445562, 74.00653392670162], + [510643.1315111141, 6651105.082852214, 74.36825107270163], + [510643.1307382987, 6651105.384778381, 74.63344879770162], + [510643.1292768052, 6651105.955759678, 74.30397639670163], + [510643.1299185876, 6651105.705025951, 74.87353724470162], + [510643.12827400246, 6651106.347538088, 74.56018951970162], + [510643.1290600401, 6651106.040446236, 75.08678957970163], + [510643.1272236682, 6651106.757886288, 74.77246732870162], + [510643.1028540657, 6651116.278686242, 68.78188541270163], + [510643.1028540657, 6651116.278686242, 68.91188541270164], + [510643.12817117845, 6651106.387709746, 75.27199848170163], + [510643.10129372514, 6651116.888285465, 68.78188541270163], + [510643.12614400254, 6651107.179693764, 74.93958208570163], + [510643.1272607223, 6651106.743409874, 75.42848977370164], + [510643.1250528149, 6651107.606002719, 75.06173520770163], + [510643.12633733, 6651107.104163982, 75.55611253270163], + [510643.12396670354, 6651108.030328449, 75.14040990070163], + [510643.12540936074, 6651107.466706149, 75.65520802670163], + [510643.1229004235, 6651108.446906372, 75.17815275970162], + [510643.1241784345, 6651107.947608644, 75.74437267870162], + [510643.1028540597, 6651116.278688582, 70.61068907270162], + [510643.1028656944, 6651116.274143135, 70.81451035670162], + [510643.1229699839, 6651108.419730292, 75.78714791970162], + [510643.10129372514, 6651116.888285465, 70.61068907170163], + [510643.1029623013, 6651116.236400399, 71.23108964470163], + [510643.1184211083, 6651110.19690064, 75.17815275970162], + [510643.10134737473, 6651116.867325446, 71.07627975870162], + [510643.10316367773, 6651116.157725964, 71.65541676470163], + [510643.1015151443, 6651116.801780672, 71.55355071070163], + [510643.10347634193, 6651116.035573242, 72.08172711570163], + [510643.10390409036, 6651115.868459034, 72.50353597470162], + [510643.1018056867, 6651116.688270561, 72.03645173070163], + [510643.11403491156, 6651111.910515026, 75.17815275970162], + [510643.10444743844, 6651115.656181919, 72.91388551770164], + [510643.10210785543, 6651116.570218248, 72.39815771570163], + [510643.1129686315, 6651112.32709295, 75.14040990070163], + [510643.10510324384, 6651115.399969636, 73.30566521170162], + [510643.11188252014, 6651112.75141868, 75.06173520770163], + [510643.1024837598, 6651116.423358643, 72.75591556170163], + [510643.1056648706, 6651115.180551348, 73.58314707170163], + [510643.11079133244, 6651113.177727635, 74.93958208570163], + [510643.1062816586, 6651114.939582491, 73.84358774470162], + [510643.11396535713, 6651111.937688768, 75.78714791970162], + [510643.10694828484, 6651114.679142673, 74.08455739070162], + [510643.1097116668, 6651113.599535111, 74.77246732870162], + [510643.1029334447, 6651116.247674204, 73.10637177670164], + [510643.10765852977, 6651114.401661721, 74.30397639670163], + [510643.1086613325, 6651114.009883311, 74.56018951970162], + [510643.10345563653, 6651116.043662482, 73.44611680370163], + [510643.11275690654, 6651112.4098104155, 75.74437267870162], + [510643.1040476992, 6651115.812353401, 73.77178391370163], + [510643.11152598023, 6651112.89071291, 75.65520802670163], + [510643.10470564826, 6651115.55530363, 74.08015272170162], + [510643.11059801106, 6651113.253255077, 75.55611253270163], + [510643.1054242269, 6651115.274566845, 74.36825107270163], + [510643.10967461875, 6651113.614009186, 75.42848977370164], + [510643.1061970423, 6651114.972640678, 74.63344879770162], + [510643.1087641626, 6651113.969709313, 75.27199848170163], + [510643.1070167535, 6651114.652393108, 74.87353724470162], + [510643.1078753009, 6651114.316972823, 75.08678957970163], + [510648.33434174245, 6651103.489797736, 68.81246166369984], + [510648.33105596085, 6651104.099390101, 68.81246166369984], + [510648.33105596085, 6651104.099390101, 68.94246166369982], + [510648.33434174245, 6651103.489797736, 70.64126532269984], + [510648.33105596085, 6651104.099390101, 70.64126532269984], + [510648.33422876644, 6651103.510757518, 71.10685600969981], + [510648.3309562763, 6651104.117884026, 71.05208063469982], + [510648.3338754756, 6651103.576301555, 71.58412696169982], + [510648.330644549, 6651104.175717, 71.47320206269981], + [510648.33326364844, 6651103.689810388, 72.06702798169984], + [510648.33010470145, 6651104.275871852, 71.89929119769982], + [510648.33262733836, 6651103.807861374, 72.42873396669982], + [510648.3293257086, 6651104.420393968, 72.32419770169982], + [510648.331835755, 6651103.9547193255, 72.78649181269982], + [510648.3283029032, 6651104.610149223, 72.74116440369981], + [510648.3308888039, 6651104.130401788, 73.13694802769982], + [510648.3270389823, 6651104.844637289, 73.14311332069983], + [510648.3297891667, 6651104.334411216, 73.47669305469984], + [510648.328542395, 6651104.565717693, 73.80236016469982], + [510648.3255445516, 6651105.12189052, 73.52299412269981], + [510648.32715687907, 6651104.822764572, 74.11072897269982], + [510648.3242832905, 6651105.355885114, 73.78940043769981], + [510648.3229131157, 6651105.610085848, 74.03711017769982], + [510648.3256436886, 6651105.103498199, 74.39882732369983], + [510648.3240162858, 6651105.40542097, 74.66402504869981], + [510648.3209386576, 6651105.976395843, 74.33455264769982], + [510648.3222901295, 6651105.725664936, 74.90411349569982], + [510648.31882694515, 6651106.368169847, 74.59076577069982], + [510648.26529737655, 6651116.299206267, 68.81246166369984], + [510648.3204821912, 6651106.061081448, 75.11736583069982], + [510648.26529737655, 6651116.299206267, 68.94246166369982], + [510648.3166151402, 6651106.778513428, 74.80304357969982], + [510648.26201159507, 6651116.908798631, 68.81246166369984], + [510648.3186104172, 6651106.408341051, 75.30257473269982], + [510648.3143415691, 6651107.200316159, 74.97015833669982], + [510648.31669316906, 6651106.764037178, 75.45906602469982], + [510648.3120437346, 6651107.626620318, 75.09231145869983], + [510648.31474867975, 6651107.124787226, 75.58668878369981], + [510648.3097565898, 6651108.050941274, 75.17098615169984], + [510648.31279455265, 6651107.487325315, 75.68578427769984], + [510648.30751120637, 6651108.46751451, 75.20872901069983], + [510648.265297364, 6651116.299208607, 70.64126532369981], + [510648.31020245526, 6651107.968222399, 75.77494892969982], + [510649.6749830265, 6651103.497513266, 68.81994054909241], + [510648.2653218642, 6651116.294663211, 70.84508660769983], + [510648.26201159507, 6651116.908798631, 70.64126532269984], + [510648.3076576872, 6651108.440338735, 75.81772417069982], + [510649.6712522881, 6651104.10710307, 68.81994054909241], + [510649.6712522881, 6651104.10710307, 68.9499405490924], + [510648.26552530023, 6651116.2569209, 71.26166589569984], + [510648.26212457096, 6651116.887838849, 71.10685600969981], + [510648.29807861743, 6651110.21748909, 75.20872901069983], + [510648.2659493608, 6651116.17824735, 71.68599301569982], + [510648.26247786183, 6651116.822294813, 71.58412696169982], + [510648.26660777227, 6651116.056096002, 72.11230336669982], + [510648.2675085293, 6651115.888983673, 72.53411222569983], + [510648.2630896891, 6651116.708785978, 72.06702798169984], + [510648.2888421186, 6651111.931084196, 75.20872901069983], + [510649.6749830265, 6651103.497513266, 70.64874420809241], + [510648.2686527175, 6651115.676708948, 72.94446176869982], + [510648.2637259991, 6651116.590734993, 72.42873396669982], + [510648.28659673495, 6651112.347657433, 75.17098615169984], + [510648.27003371925, 6651115.420499547, 73.33624146269982], + [510648.26451758243, 6651116.44387704, 72.78649181269982], + [510649.6712522881, 6651104.10710307, 70.64874420809241], + [510648.2843095903, 6651112.771978389, 75.09231145869983], + [510648.27121639886, 6651115.201083728, 73.61372332269983], + [510649.67485475144, 6651103.518472962, 71.1143348950924], + [510648.27251523745, 6651114.960117582, 73.87416399569982], + [510648.28201175586, 6651113.198282547, 74.97015833669982], + [510648.26546453364, 6651116.268194579, 73.13694802769982], + [510648.2739190259, 6651114.6996806925, 74.11513364169983], + [510648.28869565023, 6651111.958257632, 75.81772417069982], + [510648.2797381846, 6651113.6200852785, 74.80304357969982], + [510648.27541466727, 6651114.422202865, 74.33455264769982], + [510648.2775263798, 6651114.03042886, 74.59076577069982], + [510648.2665641708, 6651116.064185151, 73.47669305469984], + [510649.6711391042, 6651104.12559692, 71.0595595200924], + [510648.2861508822, 6651112.430373968, 75.77494892969982], + [510648.2678109425, 6651115.832878673, 73.80236016469982], + [510649.67445361835, 6651103.584016724, 71.59160584709242], + [510648.2835587848, 6651112.911271052, 75.68578427769984], + [510648.26919645845, 6651115.575831794, 74.11072897269982], + [510648.28160465776, 6651113.27380914, 75.58668878369981], + [510648.27070964884, 6651115.295098167, 74.39882732369983], + [510649.67078516324, 6651104.18342965, 71.48068094809241], + [510648.2796601684, 6651113.634559189, 75.45906602469982], + [510648.27233705163, 6651114.993175397, 74.66402504869981], + [510648.2777429203, 6651113.990255317, 75.30257473269982], + [510648.27406320797, 6651114.67293143, 74.90411349569982], + [510648.27587114624, 6651114.337514919, 75.11736583069982], + [510649.67375893815, 6651103.697525079, 72.07450686709241], + [510649.67017221014, 6651104.283584083, 71.90677008309241], + [510649.67303645966, 6651103.81557557, 72.43621285209241], + [510649.6692877269, 6651104.42810559, 72.3316765870924], + [510649.67213768105, 6651103.962432904, 72.79397069809241], + [510649.6681264144, 6651104.617860049, 72.74864328909241], + [510649.67106249486, 6651104.138114629, 73.1444269130924], + [510649.66669133474, 6651104.852347129, 73.1505922060924], + [510649.669813946, 6651104.3421232, 73.48417194009241], + [510649.6683983378, 6651104.573428706, 73.8098390500924], + [510649.66499452986, 6651105.129599195, 73.5304730080924], + [510649.6668251969, 6651104.830474504, 74.1182078580924], + [510649.6635624702, 6651105.363592806, 73.79687932309243], + [510649.66200674785, 6651105.617792473, 74.0445890630924], + [510649.66510709183, 6651105.1112069525, 74.4063062090924], + [510649.6632593081, 6651105.413128455, 74.6715039340924], + [510649.6597649108, 6651105.9841009285, 74.34203153309241], + [510649.6612993976, 6651105.733371076, 74.9115923810924], + [510649.65736723255, 6651106.375873286, 74.5982446560924], + [510649.5965887496, 6651116.306867989, 68.81994054909241], + [510649.6592466303, 6651106.068786178, 75.12484471609241], + [510649.5965887496, 6651116.306867989, 68.9499405490924], + [510649.65485590755, 6651106.786215144, 74.81052246509242], + [510649.5928580111, 6651116.916457793, 68.81994054909241], + [510649.65712138265, 6651106.416044324, 75.31005361809243], + [510649.65227445186, 6651107.208016104, 74.97763722209241], + [510649.65494450304, 6651106.771738955, 75.46654491009241], + [510649.64966544724, 6651107.634318471, 75.09979034409241], + [510649.65273669304, 6651107.132487488, 75.5941676690924], + [510649.64706858, 6651108.058637645, 75.17846503709241], + [510649.6505179403, 6651107.495024054, 75.69326316309241], + [510649.644519129, 6651108.475209132, 75.2162078960924], + [510649.59658873524, 6651116.306870329, 70.6487442090924], + [510649.647574824, 6651107.975919119, 75.7824278150924], + [510649.5966165533, 6651116.302324953, 70.8525654930924], + [510649.5928580111, 6651116.916457793, 70.64874420809241], + [510649.6446854463, 6651108.448033472, 75.8252030560924], + [510649.5968475383, 6651116.2645828, 71.26914478109241], + [510649.5929862861, 6651116.895498098, 71.1143348950924], + [510649.6338091894, 6651110.2251763595, 75.2162078960924], + [510649.59732902475, 6651116.18590958, 71.69347190109241], + [510649.59338741924, 6651116.829954336, 71.59160584709242], + [510649.5980765976, 6651116.063758746, 72.1197822520924], + [510649.5990993341, 6651115.896647119, 72.5415911110924], + [510649.59408209944, 6651116.71644598, 72.07450686709241], + [510649.6233218942, 6651111.938764268, 75.2162078960924], + [510649.600398467, 6651115.684373286, 72.95194065409241], + [510649.59480457794, 6651116.598395491, 72.43621285209241], + [510649.6207724433, 6651112.355335754, 75.17846503709241], + [510649.60196648247, 6651115.42816496, 73.3437203480924], + [510649.59570335655, 6651116.451538155, 72.79397069809241], + [510649.60330931924, 6651115.208750063, 73.6212022080924], + [510649.61817557603, 6651112.7796549285, 75.09979034409241], + [510649.60478404514, 6651114.96778493, 73.8816428810924], + [510649.61556657136, 6651113.205957295, 74.97763722209241], + [510649.59677854273, 6651116.275856432, 73.1444269130924], + [510649.60637793306, 6651114.707349134, 74.1226125270924], + [510649.61298511573, 6651113.627758255, 74.81052246509242], + [510649.6231555913, 6651111.965937588, 75.8252030560924], + [510649.60807611246, 6651114.42987247, 74.34203153309241], + [510649.6104737907, 6651114.038100113, 74.5982446560924], + [510649.59802709153, 6651116.071847861, 73.48417194009241], + [510649.6202662136, 6651112.438051941, 75.7824278150924], + [510649.59944269975, 6651115.840542354, 73.8098390500924], + [510649.61732309737, 6651112.918947006, 75.69326316309241], + [510649.60101584066, 6651115.583496555, 74.1182078580924], + [510649.6151043445, 6651113.281483571, 75.5941676690924], + [510649.60273394577, 6651115.3027641075, 74.4063062090924], + [510649.61289653456, 6651113.642232105, 75.46654491009241], + [510649.6045817295, 6651115.000842605, 74.6715039340924], + [510649.61071965494, 6651113.997926737, 75.31005361809243], + [510649.60654164, 6651114.680599985, 74.9115923810924], + [510649.60859440727, 6651114.345184882, 75.12484471609241], + [510660.03104468284, 6651103.590091781, 68.87210162289652], + [510660.02387678274, 6651104.199650858, 68.87210162289652], + [510660.02387678274, 6651104.199650858, 69.0021016228965], + [510660.03104468284, 6651103.590091781, 70.70090528189651], + [510660.02387678274, 6651104.199650858, 70.70090528189651], + [510660.03079822694, 6651103.6110504195, 71.1664959688965], + [510660.0236593216, 6651104.218143773, 71.11172059389651], + [510660.0300275265, 6651103.676590877, 71.64376692089652], + [510660.02297929185, 6651104.27597359, 71.53284202189651], + [510660.02869283134, 6651103.790093511, 72.12666794089651], + [510660.0218016197, 6651104.376122974, 71.95893115689651], + [510660.0273047272, 6651103.908138051, 72.48837392589651], + [510660.0201022544, 6651104.5206371965, 72.3838376608965], + [510660.0255778959, 6651104.054987984, 72.84613177189651], + [510660.0178710146, 6651104.710382091, 72.80080436289651], + [510660.0235121314, 6651104.230660852, 73.1965879868965], + [510660.0151137835, 6651104.944857352, 73.20275327989651], + [510660.02111328376, 6651104.434659139, 73.53633301389651], + [510660.01839346334, 6651104.665952987, 73.86200012389651], + [510660.0118536976, 6651105.222095443, 73.5826340818965], + [510660.009102269, 6651105.456077259, 73.8490403968965], + [510660.0153709742, 6651104.922985829, 74.1703689318965], + [510660.0061132462, 6651105.710264113, 74.0967501368965], + [510660.01206996397, 6651105.203704126, 74.45846728289652], + [510660.0018059852, 6651106.076554105, 74.39419260689651], + [510660.00851980096, 6651105.505610411, 74.7236650078965], + [510659.8804250786, 6651116.3988008415, 68.87210162289652], + [510660.0047542079, 6651105.82583689, 74.9637534548965], + [510659.8804250786, 6651116.3988008415, 69.0021016228965], + [510659.9971993053, 6651106.468306715, 74.6504057298965], + [510659.8732571785, 6651117.008359918, 68.87210162289652], + [510660.0008102083, 6651106.161235085, 75.17700578989651], + [510659.99237427465, 6651106.878627889, 74.86268353889652], + [510659.9967269516, 6651106.5084757265, 75.36221469189653], + [510659.9874145015, 6651107.300407588, 75.02979829589651], + [510659.9925444938, 6651106.864152429, 75.51870598389651], + [510659.98240179825, 6651107.726688467, 75.15195141789651], + [510659.9883026095, 6651107.22488278, 75.6463287428965], + [510659.97741241456, 6651108.150986253, 75.23062611089651], + [510659.88042505103, 6651116.39880318, 70.7009052828965], + [510659.9840397004, 6651107.587401071, 75.74542423689651], + [510659.97251413245, 6651108.5675367415, 75.2683689698965], + [510659.8804784981, 6651116.394258033, 70.9047265668965], + [510659.8732571785, 6651117.008359918, 70.70090528189651], + [510659.97838506557, 6651108.068271895, 75.8345888888965], + [510659.8809222916, 6651116.356517783, 71.32130585489651], + [510659.97283367923, 6651108.54036245, 75.8773641298965], + [510659.87350363436, 6651116.987401279, 71.1664959688965], + [510659.8818473756, 6651116.27784853, 71.74563297489651], + [510659.95193703263, 6651110.317415762, 75.2683689698965], + [510659.8742743348, 6651116.921860822, 71.64376692089652], + [510659.8832836939, 6651116.155703852, 72.1719433258965], + [510659.87560902996, 6651116.808358188, 72.12666794089651], + [510659.88524868654, 6651115.988600648, 72.5937521848965], + [510659.8877447217, 6651115.776337514, 73.00410172789651], + [510659.8769971341, 6651116.6903136475, 72.48837392589651], + [510659.93178770127, 6651112.030917296, 75.2683689698965], + [510659.8907573635, 6651115.520142104, 73.3958814218965], + [510659.8787239654, 6651116.543463715, 72.84613177189651], + [510659.9268894192, 6651112.447467786, 75.23062611089651], + [510659.8933373674, 6651115.300738267, 73.67336328189651], + [510659.9219000355, 6651112.871765571, 75.15195141789651], + [510659.89617077104, 6651115.0597852785, 73.9338039548965], + [510659.8807897299, 6651116.367790846, 73.1965879868965], + [510659.8992331217, 6651114.79936261, 74.17477360089651], + [510659.9168873323, 6651113.29804645, 75.02979829589651], + [510659.9024958486, 6651114.521899933, 74.39419260689651], + [510659.9119275591, 6651113.71982615, 74.86268353889652], + [510659.9071025285, 6651114.130147324, 74.6504057298965], + [510659.8831885776, 6651116.163792559, 73.53633301389651], + [510659.9314681821, 6651112.058089248, 75.8773641298965], + [510659.8859083979, 6651115.932498712, 73.86200012389651], + [510659.9259167957, 6651112.530179803, 75.8345888888965], + [510659.88893088716, 6651115.67546587, 74.1703689318965], + [510659.9202621609, 6651113.011050627, 75.74542423689651], + [510659.8922318973, 6651115.394747573, 74.45846728289652], + [510659.91599925177, 6651113.373568919, 75.6463287428965], + [510659.8957820603, 6651115.092841287, 74.7236650078965], + [510659.91175736743, 6651113.73429927, 75.51870598389651], + [510659.89954765333, 6651114.772614809, 74.9637534548965], + [510659.90757490974, 6651114.089975973, 75.36221469189653], + [510659.903491653, 6651114.4372166125, 75.17700578989651], + [510665.5542208707, 6651103.663346096, 68.89585792190336], + [510665.54521983647, 6651104.272880859, 68.89585792190336], + [510665.54521983647, 6651104.272880859, 69.02585792190335], + [510665.5542208707, 6651103.663346096, 70.72466158090337], + [510665.54521983647, 6651104.272880859, 70.72466158090337], + [510665.55391138565, 6651103.684303897, 71.19025226790335], + [510665.54494676145, 6651104.291373038, 71.13547689290336], + [510665.55294358457, 6651103.749841741, 71.66752321990336], + [510665.5440928193, 6651104.349200548, 71.55659832090335], + [510665.55126755167, 6651103.86333985, 72.15042423990337], + [510665.5426139668, 6651104.449345936, 71.98268745590336], + [510665.5495244508, 6651103.981379679, 72.51213022490336], + [510665.54048000224, 6651104.593854395, 72.40759395990337], + [510665.54735599604, 6651104.128223756, 72.86988807090336], + [510665.5376781404, 6651104.783591721, 72.82456066190335], + [510665.5447619284, 6651104.303889617, 73.22034428590335], + [510665.5342157692, 6651105.0180576295, 73.22650957890335], + [510665.54174959444, 6651104.507879768, 73.56008931290337], + [510665.5383342014, 6651104.73916439, 73.88575642290336], + [510665.530121942, 6651105.295284663, 73.60639038090335], + [510665.52666685707, 6651105.529257147, 73.87279669590336], + [510665.5345387343, 6651104.99618698, 74.19412523090335], + [510665.5229134153, 6651105.783433863, 74.12050643590335], + [510665.53039351676, 6651105.27689408, 74.48222358190336], + [510665.5175046061, 6651106.149709243, 74.41794890590336], + [510665.5259354275, 6651105.578788322, 74.74742130690335], + [510665.3650814872, 6651116.471544266, 68.89585792190336], + [510665.3650814872, 6651116.471544266, 69.02585792190335], + [510665.356080453, 6651117.081079029, 68.89585792190336], + [510665.52120681363, 6651105.899002029, 74.98750975390335], + [510665.511719804, 6651106.541446228, 74.67416202890335], + [510665.5162541672, 6651106.234386846, 75.20076208890337], + [510665.50566080975, 6651106.9517510375, 74.88643983790335], + [510665.51112664957, 6651106.5816136375, 75.38597099090336], + [510665.4994326136, 6651107.373513913, 75.05355459490336], + [510665.50587456115, 6651106.937276154, 75.54246228290336], + [510665.493137951, 6651107.79977779, 75.17570771690336], + [510665.50054784823, 6651107.297992116, 75.67008504190335], + [510665.36508145276, 6651116.471546603, 70.72466158190335], + [510665.4868725716, 6651108.22405865, 75.25438240990336], + [510665.36514856847, 6651116.467001638, 70.92848286590336], + [510665.4951947337, 6651107.660495948, 75.76918053590337], + [510665.48072159244, 6651108.640592525, 75.29212526890335], + [510665.356080453, 6651117.081079029, 70.72466158090337], + [510665.3657058586, 6651116.429262893, 71.34506215390337], + [510665.4880939705, 6651108.141347594, 75.85834518790337], + [510665.3563899381, 6651117.060121227, 71.19025226790335], + [510665.48112286074, 6651108.613419318, 75.90112042890335], + [510665.3668675256, 6651116.350596778, 71.76938927390336], + [510665.3573577392, 6651116.994583382, 71.66752321990336], + [510665.4548820611, 6651110.390401749, 75.29212526890335], + [510665.368671171, 6651116.228456973, 72.19569962490337], + [510665.35903377214, 6651116.881085275, 72.15042423990337], + [510665.371138695, 6651116.061360433, 72.61750848390336], + [510665.36077687296, 6651116.763045445, 72.51213022490336], + [510665.3742730716, 6651115.849105765, 73.02785802690336], + [510665.4295796968, 6651112.103834938, 75.29212526890335], + [510665.3780561728, 6651115.592920573, 73.41963772090337], + [510665.3629453277, 6651116.616201368, 72.86988807090336], + [510665.3812959923, 6651115.373525488, 73.69711958090335], + [510665.42342871753, 6651112.520368813, 75.25438240990336], + [510665.36553939537, 6651116.440535507, 73.22034428590335], + [510665.3848540167, 6651115.132582111, 73.95756025390335], + [510665.4171633382, 6651112.944649675, 75.17570771690336], + [510665.3886995396, 6651114.87216983, 74.19852989990335], + [510665.41086867556, 6651113.370913551, 75.05355459490336], + [510665.39279668307, 6651114.59471822, 74.41794890590336], + [510665.4046404794, 6651113.792676427, 74.88643983790335], + [510665.3685517293, 6651116.236545356, 73.56008931290337], + [510665.3985814852, 6651114.202981235, 74.67416202890335], + [510665.429178463, 6651112.131005806, 75.90112042890335], + [510665.37196712237, 6651116.005260734, 73.88575642290336], + [510665.42220735323, 6651112.603077531, 75.85834518790337], + [510665.37576258945, 6651115.7482381435, 74.19412523090335], + [510665.41510659, 6651113.0839291755, 75.76918053590337], + [510665.379907807, 6651115.467531043, 74.48222358190336], + [510665.4097534755, 6651113.446433008, 75.67008504190335], + [510665.3843658962, 6651115.165636801, 74.74742130690335], + [510665.4044267626, 6651113.807148971, 75.54246228290336], + [510665.3890945101, 6651114.845423095, 74.98750975390335], + [510665.3991746742, 6651114.162811486, 75.38597099090336], + [510665.39404715656, 6651114.510038278, 75.20076208890337], + [510669.92389173683, 6651103.733073057, 68.91265022951784], + [510669.9134404153, 6651104.342584677, 68.91265022951784], + [510669.9134404153, 6651104.342584677, 69.04265022951783], + [510669.92389173683, 6651103.733073057, 70.74145388851784], + [510669.9134404153, 6651104.342584677, 70.74145388851784], + [510669.92353238614, 6651103.754030063, 71.20704457551783], + [510669.9131233412, 6651104.361076154, 71.15226920051784], + [510669.9224086487, 6651103.819565418, 71.68431552751784], + [510669.9121318081, 6651104.418901469, 71.57339062851783], + [510669.92046256573, 6651103.9330592165, 72.16721654751784], + [510669.910414676, 6651104.519043056, 71.99947976351784], + [510669.9184386086, 6651104.051094566, 72.52892253251784], + [510669.90793687745, 6651104.663546028, 72.42438626751783], + [510669.9159207626, 6651104.197933067, 72.88668037851784], + [510669.90468356706, 6651104.853276151, 72.84135296951783], + [510669.912908727, 6651104.373592258, 73.23713659351785], + [510669.9006633228, 6651105.087733156, 73.24330188651783], + [510669.90941103204, 6651104.577574664, 73.57688162051784], + [510669.90544533543, 6651104.808850504, 73.90254873051784], + [510669.8959098797, 6651105.364949665, 73.62318268851784], + [510669.891898096, 6651105.598913264, 73.88958900351784], + [510669.9010383256, 6651105.065863336, 74.21091753851783], + [510669.88753988256, 6651105.8530803295, 74.13729874351785], + [510669.89622521185, 6651105.34655978, 74.49901588951784], + [510669.7042773602, 6651116.540784936, 68.91265022951784], + [510669.8812595816, 6651106.219341805, 74.43474121351784], + [510669.8910488151, 6651105.64844256, 74.76421361451783], + [510669.7042773602, 6651116.540784936, 69.04265022951783], + [510669.6938260387, 6651117.150296558, 68.91265022951784], + [510669.8855583056, 6651105.968644109, 75.00430206151785], + [510669.87454270595, 6651106.611063915, 74.69095433651783], + [510669.87980766624, 6651106.304016193, 75.21755439651784], + [510669.8675074592, 6651107.021353147, 74.90323214551783], + [510669.8738539799, 6651106.651229801, 75.40276329851784], + [510669.860275748, 6651107.443100009, 75.07034690251785], + [510669.86775565124, 6651107.006878814, 75.55925459051784], + [510669.8529668608, 6651107.869347701, 75.19250002451786], + [510669.7042773201, 6651116.540787275, 70.74145388951783], + [510669.86157067417, 6651107.367581081, 75.68687734951783], + [510669.84569197515, 6651108.293612454, 75.27117471751784], + [510669.7043552498, 6651116.536242481, 70.94527517351783], + [510669.6938260387, 6651117.150296558, 70.74145388851784], + [510669.85535504174, 6651107.730071149, 75.78597284351784], + [510669.8385499224, 6651108.710130515, 75.30891757651783], + [510669.7050023331, 6651116.49850517, 71.36185446151784], + [510669.84711017134, 6651108.210904537, 75.87513749551783], + [510669.6941853894, 6651117.129339551, 71.20704457551783], + [510669.7063511731, 6651116.41984204, 71.78618158151784], + [510669.83901584474, 6651108.682958338, 75.91791273651783], + [510669.69530912687, 6651117.063804195, 71.68431552751784], + [510669.70844543003, 6651116.297706873, 72.21249193251784], + [510669.80854700884, 6651110.459873303, 75.30891757651783], + [510669.69725520985, 6651116.950310396, 72.16721654751784], + [510669.7113105327, 6651116.130616677, 72.63430079151783], + [510669.69927916693, 6651116.832275048, 72.52892253251784], + [510669.7149499342, 6651115.918370069, 73.04465033451785], + [510669.70179701294, 6651116.685436548, 72.88668037851784], + [510669.71934258577, 6651115.662194603, 73.43643002851783], + [510669.779167813, 6651112.173241438, 75.30891757651783], + [510669.7231044197, 6651115.442807847, 73.71391188851783], + [510669.7720257603, 6651112.589759498, 75.27117471751784], + [510669.7048090485, 6651116.509777355, 73.23713659351785], + [510669.72723572917, 6651115.201873618, 73.97435256151783], + [510669.76475087466, 6651113.014024251, 75.19250002451786], + [510669.73170085996, 6651114.941471224, 74.21532220751783], + [510669.75744198746, 6651113.440271944, 75.07034690251785], + [510669.7364581539, 6651114.664030148, 74.43474121351784], + [510669.7083067435, 6651116.305794949, 73.57688162051784], + [510669.75021027616, 6651113.862018806, 74.90323214551783], + [510669.7431750294, 6651114.272308037, 74.69095433651783], + [510669.7787019307, 6651112.200411274, 75.91791273651783], + [510669.7122724401, 6651116.074519108, 73.90254873051784], + [510669.7166794499, 6651115.817506276, 74.21091753851783], + [510669.77060760424, 6651112.672465077, 75.87513749551783], + [510669.72149256367, 6651115.536809834, 74.49901588951784], + [510669.7623627338, 6651113.153298464, 75.78597284351784], + [510669.7266689604, 6651115.2349270545, 74.76421361451783], + [510669.75614710135, 6651113.515788534, 75.68687734951783], + [510669.7321594699, 6651114.914725506, 75.00430206151785], + [510669.7499621243, 6651113.8764908, 75.55925459051784], + [510669.7379101093, 6651114.579353421, 75.21755439651784], + [510669.7438637956, 6651114.232139813, 75.40276329851784], + [510676.9246202175, 6651103.866463508, 68.93586572512353], + [510676.9118453645, 6651104.475930858, 68.93586572512353], + [510676.9118453645, 6651104.475930858, 69.06586572512353], + [510676.9246202175, 6651103.866463508, 70.76466938412354], + [510676.9118453645, 6651104.475930858, 70.76466938412354], + [510676.9241809761, 6651103.887418992, 71.23026007112352], + [510676.9114577986, 6651104.49442099, 71.17548469612353], + [510676.92280740995, 6651103.952949587, 71.70753102312354], + [510676.9102458284, 6651104.552242105, 71.59660612412353], + [510676.920428675, 6651104.066435142, 72.19043204312354], + [510676.90814694465, 6651104.652376419, 72.02269525912354], + [510676.91795475304, 6651104.184461919, 72.55213802812354], + [510676.9051182834, 6651104.796868893, 72.44760176312353], + [510676.914877141, 6651104.331289752, 72.90989587412354], + [510676.90114169894, 6651104.986585236, 72.86456846512353], + [510676.9111954715, 6651104.506936187, 73.26035208912353], + [510676.89622767654, 6651105.221025213, 73.26651738212355], + [510676.9069201711, 6651104.710903775, 73.60009711612354], + [510676.89041745075, 6651105.498221584, 73.64639818412354], + [510676.90207282326, 6651104.942162817, 73.92576422612353], + [510676.88551376964, 6651105.73216819, 73.91280449912352], + [510676.8966860496, 6651105.199156981, 74.23413303412353], + [510676.8801866408, 6651105.9863167945, 74.16051423912354], + [510676.6561813048, 6651116.673245096, 68.93586572512353], + [510676.89080288727, 6651105.479833035, 74.52223138512353], + [510676.6561813048, 6651116.673245096, 69.06586572512353], + [510676.64340645174, 6651117.282712445, 68.93586572512353], + [510676.87251010706, 6651106.352551666, 74.45795670912354], + [510676.88447567704, 6651105.781693889, 74.78742911012354], + [510676.8777645209, 6651106.101872179, 75.02751755712355], + [510676.86429993977, 6651106.744245323, 74.71416983212355], + [510676.8707354028, 6651106.437219903, 75.24076989212354], + [510676.85570062115, 6651107.154504753, 74.92644764112353], + [510676.8634580965, 6651106.784408291, 75.42597879412354], + [510676.8468611602, 6651107.576220981, 75.09356239812355], + [510676.65618125576, 6651116.673247434, 70.76466938512353], + [510676.85600399104, 6651107.140031472, 75.58247008612354], + [510676.8379273656, 6651108.002437714, 75.21571552012355], + [510676.65627651074, 6651116.66870297, 70.96849066912353], + [510676.64340645174, 6651117.282712445, 70.76466938412354], + [510676.84844397375, 6651107.500707538, 75.71009284512353], + [510676.8290351318, 6651108.426671649, 75.29439021312353], + [510676.6570674532, 6651116.630968399, 71.38506995712353], + [510676.84084648546, 6651107.863171278, 75.80918833912354], + [510676.8203052621, 6651108.843159456, 75.33213307212353], + [510676.64384569303, 6651117.26175696, 71.23026007112352], + [510676.6587161665, 6651116.552310984, 71.80939707712353], + [510676.8307686204, 6651108.343969739, 75.89835299112353], + [510676.6452192592, 6651117.196226364, 71.70753102312354], + [510676.8208747682, 6651108.815989254, 75.94112823212353], + [510676.6612760173, 6651116.430184687, 72.23570742812353], + [510676.7836321189, 6651110.592775151, 75.33213307212353], + [510676.6475979941, 6651117.082740809, 72.19043204312354], + [510676.6647780878, 6651116.263106628, 72.65751628712353], + [510676.6500719161, 6651116.9647140335, 72.55213802812354], + [510676.66922659904, 6651116.0508754365, 73.06786583012355], + [510676.65314952814, 6651116.8178862, 72.90989587412354], + [510676.6745958222, 6651115.794718578, 73.45964552412353], + [510676.747721358, 6651112.306018835, 75.33213307212353], + [510676.67919398483, 6651115.575347758, 73.73712738412355], + [510676.6568311977, 6651116.642239766, 73.26035208912353], + [510676.7389914884, 6651112.722506641, 75.29439021312353], + [510676.68424376444, 6651115.334431029, 73.99756805712353], + [510676.68970158044, 6651115.07404755, 74.23853770312353], + [510676.73009925446, 6651113.146740579, 75.21571552012355], + [510676.661106498, 6651116.438272176, 73.60009711612354], + [510676.6955165131, 6651114.7966266265, 74.45795670912354], + [510676.72116545995, 6651113.57295731, 75.09356239812355], + [510676.7037266803, 6651114.404932967, 74.71416983212355], + [510676.712325999, 6651113.994673539, 74.92644764112353], + [510676.6659538459, 6651116.207013135, 73.92576422612353], + [510676.74715190096, 6651112.333186698, 75.94112823212353], + [510676.67134061956, 6651115.950018971, 74.23413303412353], + [510676.73725804867, 6651112.805206212, 75.89835299112353], + [510676.6772237819, 6651115.669342916, 74.52223138512353], + [510676.72718018363, 6651113.286004675, 75.80918833912354], + [510676.6835509921, 6651115.367482063, 74.78742911012354], + [510676.7195826955, 6651113.648468414, 75.71009284512353], + [510676.69026214833, 6651115.047303773, 75.02751755712355], + [510676.7120226781, 6651114.009144481, 75.58247008612354], + [510676.6972912663, 6651114.711956049, 75.24076989212354], + [510676.70456857275, 6651114.364767661, 75.42597879412354], + [510682.7717159758, 6651103.998336429, 68.95177490066979], + [510682.7570004802, 6651104.607760011, 68.95177490066979], + [510682.7570004802, 6651104.607760011, 69.0817749006698], + [510682.7717159758, 6651103.998336429, 70.78057855966979], + [510682.7570004802, 6651104.607760011, 70.78057855966979], + [510682.77121000877, 6651104.019290409, 71.24616924666978], + [510682.75655403873, 6651104.626248816, 71.19139387166979], + [510682.7696277826, 6651104.084816299, 71.72344019866979], + [510682.7551579568, 6651104.684065778, 71.61251529966978], + [510682.76688769134, 6651104.198293704, 72.20634121866979], + [510682.75274022925, 6651104.7841929, 72.03860443466981], + [510682.76403795293, 6651104.316312004, 72.56804720366979], + [510682.7492514806, 6651104.928675001, 72.46351093866978], + [510682.76049281744, 6651104.463129293, 72.92580504966979], + [510682.7446708086, 6651105.118377716, 72.88047764066978], + [510682.7562518612, 6651104.638763113, 73.2762612646698], + [510682.7390102914, 6651105.352800856, 73.2824265576698], + [510682.75132709515, 6651104.842716054, 73.61600629166979], + [510682.7323174276, 6651105.629977323, 73.66230735966978], + [510682.74574338115, 6651105.073958489, 73.94167340166979], + [510682.7266688227, 6651105.863907128, 73.92871367466978], + [510682.73953829653, 6651105.330934196, 74.25004220966979], + [510682.4624982014, 6651116.804198307, 68.95177490066979], + [510682.4624982014, 6651116.804198307, 69.0817749006698], + [510682.7205324437, 6651106.118037479, 74.17642341466978], + [510682.7327614163, 6651105.611590094, 74.53814056066979], + [510682.4477827058, 6651117.413621889, 68.95177490066979], + [510682.711689759, 6651106.484246051, 74.47386588466979], + [510682.7254730324, 6651105.913429269, 74.80333828566978], + [510682.70223237574, 6651106.8759115795, 74.73007900766979], + [510682.7177423767, 6651106.233584566, 75.04342673266979], + [510682.7096454574, 6651106.568908208, 75.25667906766981], + [510682.69232672494, 6651107.286141547, 74.94235681666979], + [510682.70126264717, 6651106.916071664, 75.44188796966979], + [510682.46249814495, 6651116.804200646, 70.78057856066978], + [510682.68214445136, 6651107.70782749, 75.1094715736698], + [510682.4626078702, 6651116.799656509, 70.98439984466978], + [510682.4477827058, 6651117.413621889, 70.78057855966979], + [510682.6926761801, 6651107.271669304, 75.5983792616698], + [510682.67185351375, 6651108.134013615, 75.2316246956698], + [510682.68396771187, 6651107.632319469, 75.7260020206698], + [510682.46351896564, 6651116.761924649, 71.40097913266979], + [510682.6616104506, 6651108.558217084, 75.31029938866979], + [510682.4482886728, 6651117.392667909, 71.24616924666978], + [510682.6515544164, 6651108.97467498, 75.34804224766978], + [510682.6752160805, 6651107.994757179, 75.82509751466979], + [510682.4654181369, 6651116.683272881, 71.82530625266979], + [510682.6636072755, 6651108.475521113, 75.9142621666698], + [510682.4498708989, 6651117.327142019, 71.72344019866979], + [510682.46836685756, 6651116.561155355, 72.2516166036698], + [510682.65221043676, 6651108.94750673, 75.95703740766979], + [510682.45261099027, 6651117.2136646155, 72.20634121866979], + [510682.6093102142, 6651110.724165028, 75.34804224766978], + [510682.4724009316, 6651116.3940892955, 72.67342546266978], + [510682.45546072855, 6651117.095646315, 72.56804720366979], + [510682.4775252212, 6651116.181873344, 73.08377500566979], + [510682.45900586416, 6651116.948829024, 72.92580504966979], + [510682.4837100891, 6651115.925734882, 73.4755546996698], + [510682.48900676396, 6651115.706379815, 73.7530365596698], + [510682.46324682026, 6651116.773195205, 73.2762612646698], + [510682.56794420857, 6651112.437285677, 75.34804224766978], + [510682.49482366134, 6651115.465480388, 74.01347723266979], + [510682.55788817455, 6651112.853743574, 75.31029938866979], + [510682.50111058046, 6651115.205115609, 74.25444687866978], + [510682.46817158634, 6651116.569242263, 73.61600629166979], + [510682.5476451112, 6651113.277947045, 75.2316246956698], + [510682.50780886604, 6651114.927714606, 74.47386588466979], + [510682.5373541738, 6651113.704133168, 75.1094715736698], + [510682.5172662492, 6651114.536049078, 74.73007900766979], + [510682.5271719002, 6651114.12581911, 74.94235681666979], + [510682.47375530045, 6651116.337999829, 73.94167340166979], + [510682.5672882447, 6651112.464451589, 75.95703740766979], + [510682.47996038507, 6651116.081024122, 74.25004220966979], + [510682.48673726525, 6651115.800368224, 74.53814056066979], + [510682.5558914061, 6651112.936437205, 75.9142621666698], + [510682.4940256492, 6651115.49852905, 74.80333828566978], + [510682.5442826011, 6651113.417201139, 75.82509751466979], + [510682.5017563049, 6651115.178373751, 75.04342673266979], + [510682.53553096973, 6651113.779638848, 75.7260020206698], + [510682.5098532241, 6651114.84305011, 75.25667906766981], + [510682.5268225015, 6651114.140289015, 75.5983792616698], + [510682.51823603443, 6651114.4958866555, 75.44188796966979], + [510690.1689726671, 6651104.19186548, 68.96736160139059], + [510690.1518020329, 6651104.801224829, 68.96736160139059], + [510690.1518020329, 6651104.801224829, 69.09736160139059], + [510690.1689726671, 6651104.19186548, 70.79616526039061], + [510690.1518020329, 6651104.801224829, 70.79616526039061], + [510690.16838228446, 6651104.212817251, 71.26175594739058], + [510690.15128110704, 6651104.819711686, 71.20698057239059], + [510690.16653607914, 6651104.278336233, 71.7390268993906], + [510690.1496521023, 6651104.877522553, 71.62810200039058], + [510690.16333882994, 6651104.391801679, 72.22192791939061], + [510690.14683100017, 6651104.977639122, 72.0541911353906], + [510690.16001364024, 6651104.509807539, 72.5836339043906], + [510690.1427601874, 6651105.122105994, 72.4790976393906], + [510690.15587703296, 6651104.6566093555, 72.9413917503906], + [510690.13741527445, 6651105.311788716, 72.89606434139058], + [510690.15092851414, 6651104.832224664, 73.29184796539059], + [510690.13081035455, 6651105.546187148, 73.2980132583906], + [510690.1451820983, 6651105.0361561095, 73.63159299239061], + [510690.1230008509, 6651105.823334401, 73.67789406039059], + [510690.1386667954, 6651105.26737417, 73.95726010239059], + [510689.8081648865, 6651116.996377645, 68.96736160139059], + [510690.1164098307, 6651106.057239551, 73.9443003753906], + [510689.8081648865, 6651116.996377645, 69.09736160139059], + [510690.1314264522, 6651105.524322793, 74.26562891039059], + [510689.7909942523, 6651117.605736995, 68.96736160139059], + [510690.10924965603, 6651106.311343118, 74.19201011539059], + [510690.12351891474, 6651105.80494911, 74.5537272613906], + [510690.0989316545, 6651106.677513091, 74.4894525853906], + [510690.1150145342, 6651106.106756472, 74.81892498639058], + [510690.087896398, 6651107.06913734, 74.74566570839059], + [510690.1059940932, 6651106.426878026, 75.05901343339059], + [510690.0965462809, 6651106.762166326, 75.2722657683906], + [510690.0763380847, 6651107.479324068, 74.95794351739059], + [510689.8081648206, 6651116.996379984, 70.79616526139058], + [510689.80829285254, 6651116.991836326, 70.9999865453906], + [510690.0867648795, 6651107.10929319, 75.4574746703906], + [510689.7909942523, 6651117.605736995, 70.79616526039061], + [510690.06445699686, 6651107.900965568, 75.1250582743906], + [510690.07674584317, 6651107.464853351, 75.6139659623906], + [510690.0524491156, 6651108.327106771, 75.2472113963906], + [510689.80935595545, 6651116.954108442, 71.4165658333906], + [510689.7915846349, 6651117.584785224, 71.26175594739058], + [510690.0404970959, 6651108.751265531, 75.32588608939061], + [510690.06658445083, 6651107.825465506, 75.74158872139058], + [510689.8115719851, 6651116.875464965, 71.8408929533906], + [510690.0287633094, 6651109.167679534, 75.3636289483906], + [510690.05637269415, 6651108.187865014, 75.84068421539061], + [510689.7934308403, 6651117.51926624, 71.7390268993906], + [510689.8150126714, 6651116.75336031, 72.26720330439059], + [510690.04282707185, 6651108.668578276, 75.92984886739059], + [510689.79662808945, 6651117.405800796, 72.22192791939061], + [510690.0295287805, 6651109.140514147, 75.97262410839059], + [510689.8197197918, 6651116.586311859, 72.6890121633906], + [510689.9794710692, 6651110.9169851905, 75.3636289483906], + [510689.79995327914, 6651117.2877949355, 72.5836339043906], + [510689.82569901977, 6651116.374118274, 73.0993617063906], + [510689.8040898864, 6651117.140993119, 72.9413917503906], + [510689.8329157733, 6651116.118006809, 73.49114140039059], + [510689.80903840525, 6651116.965377811, 73.29184796539059], + [510689.8390961473, 6651115.898674862, 73.7686232603906], + [510689.9312035441, 6651112.62992528, 75.3636289483906], + [510689.84588353796, 6651115.657800825, 74.02906393339059], + [510689.81478482106, 6651116.761446366, 73.63159299239061], + [510689.85321936896, 6651115.397463486, 74.2700335793906], + [510689.9194697576, 6651113.046339281, 75.32588608939061], + [510689.861035199, 6651115.120091722, 74.4894525853906], + [510689.9075177379, 6651113.470498042, 75.2472113963906], + [510689.87207045546, 6651114.728467474, 74.74566570839059], + [510689.89550985664, 6651113.8966392465, 75.1250582743906], + [510689.821300124, 6651116.530228306, 73.95726010239059], + [510689.88362876873, 6651114.318280744, 74.95794351739059], + [510689.8285404672, 6651116.273279681, 74.26562891039059], + [510689.9304381389, 6651112.657088327, 75.97262410839059], + [510689.83644800464, 6651115.992653363, 74.5537272613906], + [510689.9171398475, 6651113.129024197, 75.92984886739059], + [510689.8449523852, 6651115.690846002, 74.81892498639058], + [510689.90359422524, 6651113.60973746, 75.84068421539061], + [510689.8539728262, 6651115.37072445, 75.05901343339059], + [510689.89338246855, 6651113.97213697, 75.74158872139058], + [510689.8634206385, 6651115.035436149, 75.2722657683906], + [510689.88322107634, 6651114.332749123, 75.6139659623906], + [510689.8732020399, 6651114.688309285, 75.4574746703906], + [510693.8149386678, 6651104.298225386, 68.97317771938432], + [510693.7965579429, 6651104.907549433, 68.97317771938432], + [510693.7965579429, 6651104.907549433, 69.1031777193843], + [510693.8149386678, 6651104.298225386, 70.80198137838431], + [510693.7965579429, 6651104.907549433, 70.80198137838431], + [510693.8143066783, 6651104.319175944, 71.2675720653843], + [510693.796000305, 6651104.92603522, 71.21279669038431], + [510693.8123303626, 6651104.38469113, 71.74484301738433], + [510693.7942564971, 6651104.983842739, 71.63391811838432], + [510693.8089077892, 6651104.498150002, 72.22774403738431], + [510693.79123657936, 6651105.083953507, 72.06000725338431], + [510693.8053482585, 6651104.616149026, 72.58945002238431], + [510693.7868788784, 6651105.22841201, 72.4849137573843], + [510693.80092012626, 6651104.762942339, 72.94720786838431], + [510693.78115728573, 6651105.418083744, 72.90188045938432], + [510693.7956228634, 6651104.9385474725, 73.2976640833843], + [510693.7740868878, 6651105.6524685975, 73.3038293763843], + [510693.7894714721, 6651105.142467104, 73.63740911038431], + [510693.7657270137, 6651105.9295997955, 73.6837101783843], + [510693.7824970068, 6651105.37367177, 73.96307622038431], + [510693.42870316224, 6651117.1019957755, 68.97317771938432], + [510693.42870316224, 6651117.1019957755, 69.1031777193843], + [510693.7586714951, 6651106.163491393, 73.95011649338433], + [510693.41032243724, 6651117.711319824, 68.97317771938432], + [510693.7747464045, 6651105.630605509, 74.2714450283843], + [510693.7510067111, 6651106.417580241, 74.1978262333843], + [510693.7662815879, 6651105.911215569, 74.55954337938432], + [510693.73996155435, 6651106.783729001, 74.49526870338431], + [510693.7571778659, 6651106.213005447, 74.8247411043843], + [510693.7281485943, 6651107.1753305625, 74.7514818263843], + [510693.7475217143, 6651106.533108455, 75.0648295513843], + [510693.42870309163, 6651117.101998114, 70.8019813793843], + [510693.7157757155, 6651107.58549353, 74.96375963538432], + [510693.7374080728, 6651106.868377331, 75.27808188638431], + [510693.4288401466, 6651117.09745472, 71.0058026633843], + [510693.41032243724, 6651117.711319824, 70.80198137838431], + [510693.72693733266, 6651107.215484087, 75.46329078838433], + [510693.7030573146, 6651108.007110601, 75.13087439238431], + [510693.4299781711, 6651117.059729021, 71.42238195138431], + [510693.7162122104, 6651107.5710236505, 75.61978208038431], + [510693.6902031847, 6651108.433227119, 75.25302751438431], + [510693.4109544268, 6651117.690369266, 71.2675720653843], + [510693.6774088532, 6651108.857361308, 75.33170220738431], + [510693.7053346998, 6651107.931614913, 75.7474048393843], + [510693.43235037423, 6651116.9810901, 71.84670907138431], + [510693.4129307424, 6651117.624854079, 71.74484301738433], + [510693.66484813474, 6651109.273751187, 75.3694450663843], + [510693.6944032752, 6651108.293993428, 75.84650033338431], + [510693.43603354093, 6651116.858992517, 72.27301942238431], + [510693.6799030329, 6651108.774678842, 75.9356649853843], + [510693.4163533159, 6651117.511395209, 72.22774403738431], + [510693.441072393, 6651116.691953744, 72.6948282813843], + [510693.6656675519, 6651109.246587373, 75.97844022638431], + [510693.41991284647, 6651117.393396183, 72.58945002238431], + [510693.6120820515, 6651111.022955503, 75.3694450663843], + [510693.4474730036, 6651116.479772453, 73.10517782438431], + [510693.42434097873, 6651117.2466028705, 72.94720786838431], + [510693.4551983539, 6651116.223675824, 73.4969575183843], + [510693.4296382417, 6651117.070997736, 73.2976640833843], + [510693.4618142862, 6651116.004356583, 73.7744393783843], + [510693.46908001445, 6651115.7634964995, 74.0348800513843], + [510693.5604128998, 6651112.735796362, 75.3694450663843], + [510693.435789633, 6651116.867078106, 73.63740911038431], + [510693.4769328339, 6651115.503174243, 74.27584969738432], + [510693.54785218136, 6651113.152186241, 75.33170220738431], + [510693.48529948015, 6651115.2258185465, 74.49526870338431], + [510693.53505784983, 6651113.576320428, 75.25302751438431], + [510693.4427640982, 6651116.63587344, 73.96307622038431], + [510693.4971124401, 6651114.834216987, 74.7514818263843], + [510693.5222037198, 6651114.002436946, 75.13087439238431], + [510693.5094853191, 6651114.424054019, 74.96375963538432], + [510693.45051470055, 6651116.3789397, 74.2714450283843], + [510693.5595935532, 6651112.762957836, 75.97844022638431], + [510693.4589795171, 6651116.098329641, 74.55954337938432], + [510693.4680832391, 6651115.796539762, 74.8247411043843], + [510693.5453580722, 6651113.234866366, 75.9356649853843], + [510693.4777393907, 6651115.476436754, 75.0648295513843], + [510693.5308578298, 6651113.7155517815, 75.84650033338431], + [510693.48785303225, 6651115.141167878, 75.27808188638431], + [510693.51992640534, 6651114.077930296, 75.7474048393843], + [510693.49832377234, 6651114.794061122, 75.46329078838433], + [510693.5090488947, 6651114.438521558, 75.61978208038431], + [510699.9853135196, 6651104.494739295, 68.98021260000013], + [510699.96488485625, 6651105.103998121, 68.98021260000013], + [510699.96488485625, 6651105.103998121, 69.11021260000012], + [510699.9853135196, 6651104.494739295, 70.80901625900015], + [510699.96488485625, 6651105.103998121, 70.80901625900015], + [510699.9846111152, 6651104.51568761, 71.27460694600012], + [510699.96426508774, 6651105.122481928, 71.21983157100013], + [510699.98241460306, 6651104.581195785, 71.75187789800013], + [510699.9623269887, 6651105.18028326, 71.64095299900012], + [510699.97861069423, 6651104.694642511, 72.23477891800015], + [510699.95897059864, 6651105.280383312, 72.06704213400013], + [510699.9746545689, 6651104.812628905, 72.59648490300013], + [510699.9541273726, 6651105.424826352, 72.49194863800014], + [510699.9697330642, 6651104.9594065035, 72.95424274900013], + [510699.9477682932, 6651105.6144777825, 72.90891534000012], + [510699.96384559234, 6651105.134992841, 73.30469896400012], + [510699.93991012766, 6651105.848837548, 73.31086425700013], + [510699.9570088271, 6651105.338890645, 73.64444399100014], + [510699.5560445367, 6651117.297139156, 68.98021260000013], + [510699.5560445367, 6651117.297139156, 69.11021260000012], + [510699.93061881553, 6651106.12593908, 73.69074505900012], + [510699.94925728295, 6651105.570070563, 73.97011110100013], + [510699.53561587346, 6651117.906397982, 68.98021260000013], + [510699.9227771871, 6651106.359805644, 73.95715137400013], + [510699.9406431262, 6651105.8269767985, 74.27847990900013], + [510699.9142584104, 6651106.613867291, 74.20486111400012], + [510699.9312351791, 6651106.107556822, 74.56657826000014], + [510699.9019826275, 6651106.979976861, 74.50230358400013], + [510699.9211171412, 6651106.409314396, 74.83177598500012], + [510699.8888534946, 6651107.371536504, 74.75851670700013], + [510699.9103851233, 6651106.729383141, 75.07186443200013], + [510699.5560444584, 6651117.297141493, 70.80901626000012], + [510699.55619678367, 6651117.292598586, 71.01283754400013], + [510699.53561587346, 6651117.906397982, 70.80901625900015], + [510699.87510205776, 6651107.781655566, 74.97079451600013], + [510699.8991446429, 6651107.064616129, 75.28511676700013], + [510699.55746160424, 6651117.254876926, 71.42941683200014], + [510699.86096660176, 6651108.203227508, 75.13790927300013], + [510699.88750727684, 6651107.411685729, 75.47032566900013], + [510699.53631827777, 6651117.8854496665, 71.27460694600012], + [510699.8466802941, 6651108.629298414, 75.26006239500013], + [510699.8755871859, 6651107.767187236, 75.62681696100013], + [510699.5600981128, 6651117.176246421, 71.85374395200013], + [510699.53851479, 6651117.819941492, 71.75187789800013], + [510699.83246044745, 6651109.053387202, 75.33873708800014], + [510699.8634977279, 6651108.127739902, 75.75443972000012], + [510699.56419164955, 6651117.054161909, 72.28005430300013], + [510699.81850024237, 6651109.469732512, 75.37647994700013], + [510699.8513483491, 6651108.490079626, 75.85353521400015], + [510699.54231869883, 6651117.706494765, 72.23477891800015], + [510699.56979191897, 6651116.887141016, 72.70186316200014], + [510699.8352325228, 6651108.9707135875, 75.94269986600013], + [510699.5462748242, 6651117.588508373, 72.59648490300013], + [510699.81941095716, 6651109.442571606, 75.98547510700013], + [510699.57690567104, 6651116.674982437, 73.11221270500013], + [510699.7598550827, 6651111.218749591, 75.37647994700013], + [510699.55119632883, 6651117.441730773, 72.95424274900013], + [510699.5854917621, 6651116.418913221, 73.50399239900013], + [510699.5570838006, 6651117.266144436, 73.30469896400012], + [510699.5928448265, 6651116.199617455, 73.78147425900013], + [510699.60092008556, 6651115.958783154, 74.04191493200013], + [510699.56392056594, 6651117.062246632, 73.64444399100014], + [510699.70242907223, 6651112.931407105, 75.37647994700013], + [510699.60964784835, 6651115.698488763, 74.28288457800014], + [510699.6884688672, 6651113.347752413, 75.33873708800014], + [510699.61894668714, 6651115.421162756, 74.50230358400013], + [510699.5716721101, 6651116.831066714, 73.97011110100013], + [510699.6742490205, 6651113.771841201, 75.26006239500013], + [510699.63207582006, 6651115.029603112, 74.75851670700013], + [510699.6599627128, 6651114.197912107, 75.13790927300013], + [510699.6458272569, 6651114.619484049, 74.97079451600013], + [510699.5802862668, 6651116.574160478, 74.27847990900013], + [510699.589694214, 6651116.293580454, 74.56657826000014], + [510699.7015184359, 6651112.958565671, 75.98547510700013], + [510699.59981225186, 6651115.99182288, 74.83177598500012], + [510699.68569687015, 6651113.430423689, 75.94269986600013], + [510699.6105442698, 6651115.671754136, 75.07186443200013], + [510699.66958104394, 6651113.91105765, 75.85353521400015], + [510699.6217847501, 6651115.336521149, 75.28511676700013], + [510699.65743166517, 6651114.273397376, 75.75443972000012], + [510699.6334221162, 6651114.989451547, 75.47032566900013], + [510699.64534220716, 6651114.633950041, 75.62681696100013], + [510710.4077648801, 6651104.8738347655, 68.98407466471348], + [510710.3838770205, 6651105.48296777, 68.98407466471348], + [510710.3838770205, 6651105.48296777, 69.11407466471347], + [510710.4077648801, 6651104.8738347655, 70.81287832371348], + [510710.3838770205, 6651105.48296777, 70.81287832371348], + [510710.7005707575, 6651104.885340882, 68.9840376056788], + [510710.4069435372, 6651104.894778755, 71.27846901071347], + [510710.6765857161, 6651105.494470069, 68.9840376056788], + [510710.3831523062, 6651105.501447761, 71.22369363571347], + [510710.6765857161, 6651105.494470069, 69.11403760567879], + [510710.4043750885, 6651104.960273401, 71.75573996271348], + [510710.3808860278, 6651105.559237155, 71.64481506371347], + [510710.39992706187, 6651105.073696698, 72.23864098271348], + [510710.3769612984, 6651105.659316535, 72.07090419871348], + [510710.39530104364, 6651105.191658726, 72.60034696771348], + [510710.3712979664, 6651105.803729745, 72.49581070271348], + [510710.7005707575, 6651104.885340882, 70.8128412646788], + [510710.389546178, 6651105.338406014, 72.95810481371348], + [510710.6765857161, 6651105.494470069, 70.8128412646788], + [510710.3638621007, 6651105.993342011, 72.91277740471347], + [510710.69974607317, 6651104.906284741, 71.2784319516788], + [510710.38266177743, 6651105.51395609, 73.30856102871347], + [510710.67585805344, 6651105.512949944, 71.2236565766788], + [510709.90580755426, 6651117.6735907355, 68.98407466471348], + [510709.90580755426, 6651117.6735907355, 69.11407466471347], + [510710.3546733078, 6651106.227653377, 73.31472632171347], + [510709.88191969466, 6651118.282723741, 68.98407466471348], + [510710.6971671753, 6651104.971778976, 71.7557029036788], + [510710.3746673391, 6651105.717811785, 73.64830605571348], + [510710.6735825553, 6651105.570738974, 71.64477800467878], + [510710.34380869294, 6651106.504697682, 73.69460712371347], + [510710.3656032218, 6651105.948943961, 73.97397316571347], + [510710.692701053, 6651105.085201563, 72.2386039236788], + [510710.6696418591, 6651105.670817729, 72.0708671396788], + [510710.3346392375, 6651106.73851595, 73.96101343871348], + [510710.3555304255, 6651106.205797142, 74.28234197371347], + [510710.688056215, 6651105.203162851, 72.6003099086788], + [510710.6639554872, 6651105.815230032, 72.49577364367879], + [510710.32467797195, 6651106.9925251305, 74.20872317871347], + [510710.34452942567, 6651106.486319222, 74.57044032471347], + [510710.68227793707, 6651105.349909219, 72.9580677546788], + [510710.3103235241, 6651107.358559091, 74.50616564871348], + [510710.65648937057, 6651106.00484111, 72.91274034567878], + [510709.90580746264, 6651117.673593073, 70.81287832471347], + [510710.33269809507, 6651106.788014479, 74.83563804971347], + [510710.6753655291, 6651105.525458194, 73.30852396967879], + [510709.9059855812, 6651117.669051103, 71.01669960871347], + [510709.88191969466, 6651118.282723741, 70.81287832371348], + [510710.1965713426, 6651117.685016608, 68.9840376056788], + [510710.29497122817, 6651107.750037872, 74.76237877171347], + [510710.320148819, 6651107.108017123, 75.07572649671347], + [510710.1965713426, 6651117.685016608, 69.11403760567879], + [510710.64726319537, 6651106.239151007, 73.3146892626788], + [510710.17258630117, 6651118.294145795, 68.9840376056788], + [510710.6673385674, 6651105.729312612, 73.6482689966788], + [510709.90746457456, 6651117.631337234, 71.43327889671347], + [510709.8827410376, 6651118.261779752, 71.27846901071347], + [510710.2788912533, 6651108.160072238, 74.97465658071347], + [510710.3070049822, 6651107.443180881, 75.2889788317135], + [510710.63635438046, 6651106.516193576, 73.69457006467879], + [510709.91054752446, 6651117.552722968, 71.85760601671348], + [510710.658237575, 6651105.96044334, 73.9739361066788], + [510710.2623622332, 6651108.581557119, 75.14177133771348], + [510710.2933970547, 6651107.790178806, 75.47418773371348], + [510709.8853094863, 6651118.196285105, 71.75573996271348], + [510710.62714762136, 6651106.750010377, 73.96097637967878], + [510710.24565681745, 6651109.007540036, 75.26392445971348], + [510710.27945852856, 6651108.145606897, 75.63067902571348], + [510709.91533422197, 6651117.430663668, 72.28391636771349], + [510710.64812379994, 6651106.217294909, 74.28230491467879], + [510710.2290291166, 6651109.431541244, 75.34259915271348], + [510709.88975751295, 6651118.082861807, 72.23864098271348], + [510710.2653219562, 6651108.5060851015, 75.75830178471347], + [510710.61714583077, 6651107.004017965, 74.20868611967879], + [510710.2127050227, 6651109.847800571, 75.38034201171347], + [510709.921882788, 6651117.263677267, 72.70572522671348], + [510710.6370780453, 6651106.49781523, 74.57040326567879], + [510710.2511153167, 6651108.868349999, 75.85739727871349], + [510709.8943835311, 6651117.96489978, 72.60034696771348], + [510710.6027329855, 6651107.370049632, 74.50612858967881], + [510709.93020111544, 6651117.051562501, 73.11607476971348], + [510710.2322705891, 6651109.348884702, 75.94656193071349], + [510710.19657125056, 6651117.685018945, 70.8128412656788], + [510710.62519858184, 6651106.799508596, 74.8356009906788], + [510709.90013839677, 6651117.818152492, 72.95810481371348], + [510710.2137699493, 6651109.820645273, 75.98933717171347], + [510710.1967500939, 6651117.680477004, 71.01666254967878], + [510710.17258630117, 6651118.294145795, 70.8128412646788], + [510710.1441294474, 6651111.596456451, 75.38034201171347], + [510709.94024109386, 6651116.795546168, 73.50785446371349], + [510710.5873182326, 6651107.761525957, 74.7623417126788], + [510709.9070227973, 6651117.642602418, 73.30856102871347], + [510710.61259825213, 6651107.119509234, 75.0756894376788], + [510709.9488392565, 6651116.57629569, 73.78533632371347], + [510710.19823510404, 6651117.64276337, 71.43324183767879], + [510709.9582819034, 6651116.335511125, 74.04577699671347], + [510709.9150172357, 6651117.4387467215, 73.64830605571348], + [510710.1734109855, 6651118.273201936, 71.2784319516788], + [510710.57117284025, 6651108.171557753, 74.97461952167879], + [510710.5994009429, 6651107.45467089, 75.2889417726788], + [510709.9684875428, 6651116.075270488, 74.28674664271347], + [510710.07697946037, 6651113.308760275, 75.38034201171347], + [510709.92408135295, 6651117.207614545, 73.97397316571347], + [510709.97936095897, 6651115.798001753, 74.50616564871348], + [510710.06065536645, 6651113.725019602, 75.34259915271348], + [510710.2013305962, 6651117.564149599, 71.85756895767881], + [510709.99471325486, 6651115.406522973, 74.76237877171347], + [510710.554576576, 6651108.593039993, 75.14173427867881], + [510710.04402766563, 6651114.149020809, 75.26392445971348], + [510710.585737655, 6651107.80166664, 75.4741506746788], + [510710.0107932298, 6651114.996488606, 74.97465658071347], + [510710.02732224984, 6651114.575003725, 75.14177133771348], + [510709.93415414926, 6651116.950761364, 74.28234197371347], + [510710.17598988337, 6651118.2077077, 71.7557029036788], + [510709.9451551491, 6651116.670239285, 74.57044032471347], + [510710.5378031984, 6651109.019020237, 75.26388740067881], + [510710.5717424233, 6651108.157092503, 75.6306419666788], + [510710.2061367672, 6651117.442091064, 72.28387930867879], + [510709.9569864797, 6651116.368544029, 74.83563804971347], + [510710.0759146255, 6651113.3359132325, 75.98933717171347], + [510710.52110785194, 6651109.443018787, 75.3425620936788], + [510709.96953575587, 6651116.048541383, 75.07572649671347], + [510710.1804560056, 6651118.094285113, 72.2386039236788], + [510710.5575483399, 6651108.517568449, 75.75826472567879], + [510710.05741398566, 6651113.807673804, 75.94656193071349], + [510709.9826795926, 6651115.713377625, 75.2889788317135], + [510710.03856925806, 6651114.288208507, 75.85739727871349], + [510709.99628752004, 6651115.3663797, 75.47418773371348], + [510710.50471734744, 6651109.859275505, 75.38030495267878], + [510710.02436261857, 6651114.650473405, 75.75830178471347], + [510710.0102260462, 6651115.010951609, 75.63067902571348], + [510710.21271197445, 6651117.275105708, 72.70568816767879], + [510710.5432839042, 6651108.879831074, 75.8573602196788], + [510710.18510084366, 6651117.976323825, 72.6003099086788], + [510710.22106414294, 6651117.062992273, 73.1160377106788], + [510710.52436251147, 6651109.3603627635, 75.94652487167879], + [510710.19087912154, 6651117.829577458, 72.9580677546788], + [510710.50578660634, 6651109.832120378, 75.98930011267879], + [510710.4358627894, 6651111.607920422, 75.38030495267878], + [510710.23114496656, 6651116.806977544, 73.50781740467879], + [510710.1977915296, 6651117.654028483, 73.30852396967879], + [510710.2397781086, 6651116.587728441, 73.7852992646788], + [510710.24925917067, 6651116.346945386, 74.0457399376788], + [510710.2058184913, 6651117.450174065, 73.6482689966788], + [510710.2595063292, 6651116.08670638, 74.28670958367879], + [510710.3684396192, 6651113.320213512, 75.38030495267878], + [510710.2149194837, 6651117.219043339, 73.9739361066788], + [510710.2704239811, 6651115.809439384, 74.50612858967881], + [510710.3520491147, 6651113.736470228, 75.3425620936788], + [510710.28583873407, 6651115.417963057, 74.7623417126788], + [510710.3353537682, 6651114.160468778, 75.26388740067881], + [510710.30198412633, 6651115.007931261, 74.97461952167879], + [510710.3185803906, 6651114.586449023, 75.14173427867881], + [510710.2250332587, 6651116.962191767, 74.28230491467879], + [510710.2360790134, 6651116.681671446, 74.57040326567879], + [510710.2479584768, 6651116.379978082, 74.8356009906788], + [510710.3673704523, 6651113.347366299, 75.98930011267879], + [510710.26055880653, 6651116.059977442, 75.0756894376788], + [510710.3487945472, 6651113.8191239135, 75.94652487167879], + [510710.27375611576, 6651115.724815786, 75.2889417726788], + [510710.32987315446, 6651114.299655603, 75.8573602196788], + [510710.28741940367, 6651115.377820036, 75.4741506746788], + [510710.3156087188, 6651114.6619182285, 75.75826472567879], + [510710.3014146353, 6651115.022394176, 75.6306419666788], + [510717.1935003072, 6651105.152511052, 68.98117101989592], + [510717.16736027185, 6651105.7615515655, 68.98117101989592], + [510717.16736027185, 6651105.7615515655, 69.11117101989592], + [510717.1935003072, 6651105.152511052, 70.80997467889593], + [510717.16736027185, 6651105.7615515655, 70.80997467889593], + [510717.19260152715, 6651105.173451861, 71.27556536589593], + [510717.16656723066, 6651105.780028748, 71.22078999089594], + [510717.1897909219, 6651105.238936563, 71.75283631789593], + [510717.1640872849, 6651105.837809368, 71.64191141889592], + [510717.18492353015, 6651105.352342638, 72.23573733789593], + [510717.15979252744, 6651105.937873553, 72.06800055389593], + [510717.1798613654, 6651105.470286753, 72.59744332289593], + [510717.1535952497, 6651106.082264833, 72.49290705789592], + [510717.1735639243, 6651105.6170117585, 72.95520116889593], + [510717.1454583218, 6651106.271848308, 72.90987375989592], + [510716.64421785146, 6651117.950323476, 68.98117101989592], + [510716.64421785146, 6651117.950323476, 69.11117101989592], + [510717.1660304544, 6651105.792535178, 73.30565738389592], + [510716.6180778162, 6651118.559363989, 68.98117101989592], + [510717.13540319866, 6651106.506124095, 73.31182267689593], + [510717.15728229086, 6651105.996359921, 73.64540241089593], + [510717.12351425504, 6651106.783126335, 73.69170347889592], + [510717.147363598, 6651106.227457001, 73.97106952089594], + [510717.11348029255, 6651107.016909098, 73.95810979389591], + [510717.13634112646, 6651106.48427118, 74.27943832889592], + [510717.102579867, 6651107.270879709, 74.20581953389592], + [510717.12430293934, 6651106.764750664, 74.56753667989592], + [510716.64421775116, 6651117.950325814, 70.80997467989593], + [510717.086872065, 6651107.636858092, 74.50326200389594], + [510716.6444126631, 6651117.945784534, 71.01379596389592], + [510716.6180778162, 6651118.559363989, 70.80997467889593], + [510717.1113561369, 6651107.066400111, 74.83273440489593], + [510717.0700723364, 6651108.02827743, 74.75947512689594], + [510716.6460310976, 6651117.90807639, 71.43037525189592], + [510716.6189765963, 6651118.53842318, 71.27556536589593], + [510717.0976237003, 6651107.386354167, 75.07282285189594], + [510717.05247632257, 6651108.438249534, 74.97175293589592], + [510716.6494047117, 6651117.829474061, 71.85470237189594], + [510717.08324064704, 6651107.721467031, 75.28607518689593], + [510716.62178720144, 6651118.472938479, 71.75283631789593], + [510717.0343889269, 6651108.859670416, 75.13886769289594], + [510717.06834974803, 6651108.068412268, 75.47128408889593], + [510716.6546427047, 6651117.707433295, 72.28101272289592], + [510717.0161085048, 6651109.28558865, 75.26102081489594], + [510716.6266545933, 6651118.359532403, 72.23573733789593], + [510717.0530970812, 6651108.423786389, 75.62777538089593], + [510716.9979131247, 6651109.709525476, 75.33969550789593], + [510716.6618086773, 6651117.5404722495, 72.70282158189592], + [510717.03762769606, 6651108.784209859, 75.75539813989592], + [510716.6317167579, 6651118.241588288, 72.59744332289593], + [510716.9800499759, 6651110.125721598, 75.37743836689592], + [510717.0220816379, 6651109.146419749, 75.85449363389593], + [510716.67091126635, 6651117.328389692, 73.11317112489593], + [510716.6380141991, 6651118.094863282, 72.95520116889593], + [510717.001460207, 6651109.626881486, 75.94365828589592], + [510716.68189782585, 6651117.072412233, 73.50495081889592], + [510716.64554766903, 6651117.919339863, 73.30565738389592], + [510716.90500901436, 6651111.874111958, 75.37743836689592], + [510716.98121530504, 6651110.098570424, 75.98643352689592], + [510716.6913066334, 6651116.853195047, 73.78243267889593], + [510716.65429583244, 6651117.71551512, 73.64540241089593], + [510716.7016395442, 6651116.612447043, 74.04287335189593], + [510716.7128073834, 6651116.352245921, 74.28384299789592], + [510716.66421452543, 6651117.484418041, 73.97106952089594], + [510716.7247059581, 6651116.075019288, 74.50326200389594], + [510716.8315280471, 6651113.5861557815, 75.37743836689592], + [510716.7415056866, 6651115.68359995, 74.75947512689594], + [510716.81366489833, 6651114.002351903, 75.33969550789593], + [510716.67523699696, 6651117.227603861, 74.27943832889592], + [510716.7591017005, 6651115.273627844, 74.97175293589592], + [510716.7954695182, 6651114.426288729, 75.26102081489594], + [510716.7771890962, 6651114.852206962, 75.13886769289594], + [510716.6872751841, 6651116.947124376, 74.56753667989592], + [510716.7002219864, 6651116.645474929, 74.83273440489593], + [510716.8303628184, 6651113.613304617, 75.98643352689592], + [510716.71395442315, 6651116.325520874, 75.07282285189594], + [510716.7283374764, 6651115.990408009, 75.28607518689593], + [510716.8101179163, 6651114.084993556, 75.94365828589592], + [510716.7432283754, 6651115.6434627725, 75.47128408889593], + [510716.78949648555, 6651114.565455293, 75.85449363389593], + [510716.7584810422, 6651115.288088651, 75.62777538089593], + [510716.77395042736, 6651114.927665182, 75.75539813989592], + [510727.58008760674, 6651105.627760315, 68.96844538400684], + [510727.5505002783, 6651106.236643095, 68.96844538400684], + [510727.5505002783, 6651106.236643095, 69.09844538400685], + [510727.58008760674, 6651105.627760315, 70.79724904300684], + [510727.5505002783, 6651106.236643095, 70.79724904300684], + [510727.57907029736, 6651105.648695701, 71.26283973000683], + [510727.5496026525, 6651106.255115492, 71.20806435500684], + [510727.57588903554, 6651105.714163442, 71.74011068200684], + [510727.54679565673, 6651106.312881147, 71.62918578300683], + [510727.57037974225, 6651105.827540148, 72.22301170200684], + [510727.5419345156, 6651106.412919416, 72.05527491800686], + [510727.5646499899, 6651105.945453716, 72.58471768700684], + [510727.53491995385, 6651106.557273301, 72.48018142200684], + [510726.9583669315, 6651118.422258254, 68.96844538400684], + [510726.9583669315, 6651118.422258254, 69.09844538400685], + [510726.9287796031, 6651119.0311410315, 68.96844538400684], + [510727.55752205546, 6651106.092140722, 72.94247553300684], + [510727.52570994495, 6651106.746807677, 72.89714812400683], + [510727.5489950873, 6651106.267618683, 73.29293174800685], + [510727.51432877325, 6651106.981022789, 73.29909704100683], + [510727.5390932343, 6651106.471390637, 73.63267677500684], + [510727.50087194075, 6651107.257953289, 73.67897784300683], + [510727.52786648495, 6651106.702427866, 73.95834388500684], + [510727.48951472016, 6651107.491675504, 73.94538415800685], + [510726.95836681797, 6651118.422260589, 70.79724904400683], + [510727.5153903929, 6651106.959175534, 74.26671269300684], + [510726.9287796031, 6651119.0311410315, 70.79724904300684], + [510726.95858743443, 6651118.417720486, 71.00107032800683], + [510727.47717676946, 6651107.74558034, 74.19309389800684], + [510727.50176463503, 6651107.2395823775, 74.55481104400684], + [510726.96041930467, 6651118.380022108, 71.41764961600684], + [510727.4593974553, 6651108.111463937, 74.49053636800684], + [510726.9297969124, 6651119.010205645, 71.26283973000683], + [510727.48711043544, 6651107.5411537, 74.82000876900683], + [510727.4403822138, 6651108.5027819015, 74.74674949100684], + [510726.9642378239, 6651118.301440137, 71.84197673600684], + [510726.93297817436, 6651118.944737904, 71.74011068200684], + [510727.47156699374, 6651107.86102489, 75.06009721600684], + [510727.4204656744, 6651108.912647829, 74.95902730000684], + [510726.97016659245, 6651118.179430978, 72.26828708700685], + [510727.4552871335, 6651108.196050965, 75.27334955100686], + [510726.9384874676, 6651118.831361199, 72.22301170200684], + [510727.39999295096, 6651109.333959568, 75.12614205700685], + [510727.438432454, 6651108.542906347, 75.45855845300684], + [510726.9782775985, 6651118.012513173, 72.69009594600683], + [510727.37930174504, 6651109.759767494, 75.24829517900685], + [510726.94421721995, 6651118.7134476295, 72.58471768700684], + [510727.4211682974, 6651108.89818843, 75.61504974500686], + [510727.35870679637, 6651110.183594526, 75.32696987200684], + [510726.988580618, 6651117.800485543, 73.10044548900684], + [510726.9513451545, 6651118.566760625, 72.94247553300684], + [510727.4036588422, 6651109.258518553, 75.74267250400685], + [510727.33848789294, 6651110.599682856, 75.36471273100683], + [510727.38606260234, 6651109.620634636, 75.84176799800684], + [510727.001016062, 6651117.544574378, 73.49222518300685], + [510726.9598721226, 6651118.391282664, 73.29293174800685], + [510727.0116656833, 6651117.325413967, 73.76970704300683], + [510727.36272166047, 6651110.100971939, 75.93093265000685], + [510727.2535506866, 6651112.347620404, 75.36471273100683], + [510726.9697739755, 6651118.187510709, 73.63267677500684], + [510727.02336127684, 6651117.084728314, 74.03014771600684], + [510727.3398069032, 6651110.572538715, 75.97370789100684], + [510727.0360019072, 6651116.8245945815, 74.27111736200683], + [510726.9810007249, 6651117.956473481, 73.95834388500684], + [510727.04946964094, 6651116.5474397475, 74.49053636800684], + [510726.993476817, 6651117.699725813, 74.26671269300684], + [510727.17037920334, 6651114.059220828, 75.36471273100683], + [510727.0684848825, 6651116.156121782, 74.74674949100684], + [510727.1501602999, 6651114.475309158, 75.32696987200684], + [510727.08840142185, 6651115.746255854, 74.95902730000684], + [510727.12956535124, 6651114.89913619, 75.24829517900685], + [510727.1088741453, 6651115.324944116, 75.12614205700685], + [510727.00710257486, 6651117.41931897, 74.55481104400684], + [510727.02175677445, 6651117.117747648, 74.82000876900683], + [510727.03730021615, 6651116.797876457, 75.06009721600684], + [510727.1690603067, 6651114.086362632, 75.97370789100684], + [510727.0535800763, 6651116.462850382, 75.27334955100686], + [510727.0704347558, 6651116.115995001, 75.45855845300684], + [510727.1461455494, 6651114.557929408, 75.93093265000685], + [510727.0876989125, 6651115.760712918, 75.61504974500686], + [510727.1228046075, 6651115.038266711, 75.84176799800684], + [510727.10520836763, 6651115.400382793, 75.74267250400685], + [510730.6378082029, 6651105.778898019, 68.96278941948812], + [510730.60720602155, 6651106.387730636, 68.96278941948812], + [510730.60720602155, 6651106.387730636, 69.0927894194881], + [510730.6378082029, 6651105.778898019, 70.7915930784881], + [510730.60720602155, 6651106.387730636, 70.7915930784881], + [510730.6367559996, 6651105.799831681, 71.2571837654881], + [510730.6062776069, 6651106.406201512, 71.2024083904881], + [510730.6334656197, 6651105.865294028, 71.73445471748812], + [510730.60337433044, 6651106.463962407, 71.62352981848811], + [510730.59834645095, 6651106.563992436, 72.0496189534881], + [510730.6277673562, 6651105.978661393, 72.21735573748812], + [510729.9947623485, 6651118.572341891, 68.96278941948812], + [510730.62184107193, 6651106.0965652475, 72.5790617224881], + [510730.5910912879, 6651106.708334429, 72.4745254574881], + [510729.9947623485, 6651118.572341891, 69.0927894194881], + [510729.96416016715, 6651119.181174506, 68.96278941948812], + [510730.6144686474, 6651106.243240168, 72.9368195684881], + [510730.58156537334, 6651106.897853188, 72.8914921594881], + [510730.605649202, 6651106.418703673, 73.2872757834881], + [510730.5697938245, 6651107.1320490055, 73.29344107648811], + [510730.595407713, 6651106.622458839, 73.6270208104881], + [510730.5558754192, 6651107.40895669, 73.6733218784881], + [510730.5837958832, 6651106.853477035, 73.9526879204881], + [510729.994762231, 6651118.572344227, 70.7915930794881], + [510730.54412864306, 6651107.642659651, 73.9397281934881], + [510729.96416016715, 6651119.181174506, 70.7915930784881], + [510730.570891858, 6651107.110203549, 74.2610567284881], + [510729.99499041465, 6651118.567804497, 70.9954143634881], + [510730.5313674974, 6651107.89654357, 74.1874379334881], + [510730.5567987331, 6651107.390587292, 74.54915507948812], + [510729.9968851186, 6651118.530109226, 71.41199365148812], + [510729.96521237044, 6651119.160240846, 71.2571837654881], + [510730.5129783483, 6651108.262397023, 74.4848804034881], + [510730.54164189065, 6651107.692133769, 74.8143528044881], + [510730.00083461404, 6651118.451533728, 71.8363207714881], + [510729.96850275033, 6651119.094778499, 71.73445471748812], + [510730.493310879, 6651108.653682749, 74.7410935264881], + [510730.52556530497, 6651108.011978609, 75.0544412514881], + [510730.0069667408, 6651118.32953462, 72.2626311224881], + [510730.4727111972, 6651109.06351491, 74.95337133548811], + [510729.9742010138, 6651118.981411134, 72.21735573748812], + [510730.50872704136, 6651108.346977082, 75.26769358648811], + [510730.451536254, 6651109.484791939, 75.12048609248811], + [510730.0153559565, 6651118.162630567, 72.6844399814881], + [510730.49129424203, 6651108.693803888, 75.4529024884881], + [510729.9801272981, 6651118.863507279, 72.5790617224881], + [510730.4301353345, 6651109.910564785, 75.24263921448811], + [510730.47343792033, 6651109.049056702, 75.6093937804881], + [510730.0260123722, 6651117.950620405, 73.0947895244881], + [510730.4088339738, 6651110.3343569, 75.32131390748812], + [510729.9874997227, 6651118.716832358, 72.9368195684881], + [510730.45532788633, 6651109.40935714, 75.7370165394881], + [510730.3879215568, 6651110.750410953, 75.35905676648811], + [510730.038874355, 6651117.694730324, 73.4865692184881], + [510729.996319168, 6651118.541368853, 73.2872757834881], + [510730.4371280909, 6651109.771443389, 75.8361120334881], + [510730.0498892612, 6651117.475587968, 73.76405107848811], + [510730.41298654873, 6651110.25174112, 75.9252766854881], + [510730.00656065706, 6651118.337613688, 73.6270208104881], + [510730.3000709823, 6651112.498204497, 75.35905676648811], + [510730.0619860166, 6651117.234922144, 74.0244917514881], + [510730.3892858094, 6651110.723269046, 75.9680519264881], + [510730.0750602238, 6651116.974809842, 74.26546139748811], + [510730.0181724868, 6651118.106595492, 73.9526879204881], + [510730.0889899043, 6651116.6976778405, 74.4848804034881], + [510730.031076512, 6651117.8498689765, 74.2610567284881], + [510730.10865737346, 6651116.306392115, 74.7410935264881], + [510730.21404669574, 6651114.209663911, 75.35905676648811], + [510730.12925705523, 6651115.896559953, 74.95337133548811], + [510730.1931342788, 6651114.625717964, 75.32131390748812], + [510730.1504319985, 6651115.475282923, 75.12048609248811], + [510730.171832918, 6651115.049510078, 75.24263921448811], + [510730.04516963696, 6651117.569485234, 74.54915507948812], + [510730.0603264794, 6651117.267938757, 74.8143528044881], + [510730.07640306506, 6651116.948093918, 75.0544412514881], + [510730.09324132866, 6651116.613095444, 75.26769358648811], + [510730.21268256055, 6651114.23680348, 75.9680519264881], + [510730.110674128, 6651116.266268638, 75.4529024884881], + [510730.1889818213, 6651114.708331407, 75.9252766854881], + [510730.1285304497, 6651115.911015824, 75.6093937804881], + [510730.16484027903, 6651115.188629137, 75.8361120334881], + [510730.1466404837, 6651115.550715387, 75.7370165394881], + [510734.3947636187, 6651105.971593879, 68.95465016035759], + [510734.3629145093, 6651106.58036254, 68.95465016035759], + [510734.3629145093, 6651106.58036254, 69.08465016035757], + [510734.3947636187, 6651105.971593879, 70.78345381935759], + [510734.3629145093, 6651106.58036254, 70.78345381935759], + [510734.3936685419, 6651105.992525341, 71.24904450635756], + [510734.3619482651, 6651106.598831477, 71.19426913135757], + [510734.3902440909, 6651106.057980813, 71.72631545835758], + [510734.3589266907, 6651106.656586305, 71.61539055935756], + [510734.35369394324, 6651106.756605824, 72.04147969435758], + [510734.38431364385, 6651106.171336268, 72.20921647835759], + [510733.72551597597, 6651118.763693851, 68.95465016035759], + [510733.72551597597, 6651118.763693851, 69.08465016035757], + [510733.69366686663, 6651119.372462511, 68.95465016035759], + [510734.3781458849, 6651106.289227738, 72.57092246335758], + [510734.34614315873, 6651106.900932655, 72.46638619835758], + [510734.3704730608, 6651106.435887252, 72.92868030935757], + [510734.3362290977, 6651107.090431508, 72.88335290035756], + [510734.361294255, 6651106.611332324, 73.27913652435757], + [510734.3239779009, 6651107.324602722, 73.28530181735758], + [510734.3506354625, 6651106.815066086, 73.61888155135759], + [510734.3094923709, 6651107.601481319, 73.66518261935757], + [510734.3385504927, 6651107.046060014, 73.94454866135757], + [510733.72551585373, 6651118.763696186, 70.78345382035756], + [510733.69366686663, 6651119.372462511, 70.78345381935759], + [510734.29726695624, 6651107.835159731, 73.93158893435758], + [510733.7257533351, 6651118.759156933, 70.98727510435758], + [510734.3251206753, 6651107.302759563, 74.25291746935757], + [510734.28398584016, 6651108.089016979, 74.17929867435757], + [510733.7277252413, 6651118.721465621, 71.40385439235759], + [510733.69476194336, 6651119.351531049, 71.24904450635756], + [510734.3104533066, 6651107.583113851, 74.54101582035759], + [510734.26484739984, 6651108.454832002, 74.47674114435758], + [510733.7318356643, 6651118.642898378, 71.82818151235757], + [510734.29467887775, 6651107.884628652, 74.80621354535756], + [510733.6981863944, 6651119.286075577, 71.72631545835758], + [510734.2443785525, 6651108.8460766245, 74.73295426735757], + [510734.27794722933, 6651108.204439892, 75.04630199235757], + [510733.7382176531, 6651118.520912086, 72.25449186335757], + [510733.7041168414, 6651119.172720123, 72.20921647835759], + [510734.2229395084, 6651109.255865734, 74.94523207635757], + [510734.2604228676, 6651108.539403177, 75.25955432735758], + [510733.74694869894, 6651118.354025566, 72.67630072235758], + [510733.7102846004, 6651119.054828652, 72.57092246335758], + [510734.200901763, 6651109.67709851, 75.11234683335758], + [510734.2422797448, 6651108.886193549, 75.44476322935758], + [510734.1786288335, 6651110.10282663, 75.23449995535758], + [510733.7580393249, 6651118.142037674, 73.08665026535758], + [510733.71795742447, 6651118.908169139, 72.92868030935757], + [510734.2236958428, 6651109.241409045, 75.60125452135757], + [510734.1564595195, 6651110.526574227, 75.31317464835759], + [510734.13469499734, 6651110.942584574, 75.35091750735758], + [510733.77142538695, 6651117.886174472, 73.47842995935757], + [510734.2048478906, 6651109.601671636, 75.72887728035757], + [510733.7271362303, 6651118.732724067, 73.27913652435757], + [510734.18590651936, 6651109.963719849, 75.82797277435759], + [510733.7828891107, 6651117.667055137, 73.75591181935758], + [510733.7377950229, 6651118.528990304, 73.61888155135759], + [510733.79547876486, 6651117.426414593, 74.01635249235757], + [510734.16078129684, 6651110.443967126, 75.91713742635757], + [510734.04326483025, 6651112.69019452, 75.35091750735758], + [510733.7498799926, 6651118.297996378, 73.94454866135757], + [510733.80908569874, 6651117.166329616, 74.25732213835758], + [510734.13611483824, 6651110.91544552, 75.95991266735757], + [510733.8235829632, 6651116.889226725, 74.47674114435758], + [510733.7633098101, 6651118.041296829, 74.25291746935757], + [510733.84405181056, 6651116.497982102, 74.73295426735757], + [510733.9537353658, 6651114.401474153, 75.35091750735758], + [510733.8654908548, 6651116.088192994, 74.94523207635757], + [510733.9319708435, 6651114.817484501, 75.31317464835759], + [510733.7779771788, 6651117.76094254, 74.54101582035759], + [510733.88752860005, 6651115.666960218, 75.11234683335758], + [510733.90980152955, 6651115.241232097, 75.23449995535758], + [510733.79375160753, 6651117.459427739, 74.80621354535756], + [510733.8104832559, 6651117.139616499, 75.04630199235757], + [510733.8280076178, 6651116.804653214, 75.25955432735758], + [510733.952315647, 6651114.428610871, 75.95991266735757], + [510733.84615074046, 6651116.457862841, 75.44476322935758], + [510733.92764918844, 6651114.900089264, 75.91713742635757], + [510733.86473464256, 6651116.102647346, 75.60125452135757], + [510733.8835825948, 6651115.742384755, 75.72887728035757], + [510733.902523966, 6651115.380336542, 75.82797277435759], + [510744.45206085313, 6651106.525420858, 68.92640105436793], + [510744.41687374155, 6651107.134005704, 68.92640105436793], + [510744.41687374155, 6651107.134005704, 69.05640105436792], + [510744.45206085313, 6651106.525420858, 70.75520471336793], + [510744.41687374155, 6651107.134005704, 70.75520471336793], + [510744.4508510049, 6651106.546345999, 71.22079540036792], + [510744.41580622847, 6651107.152469065, 71.16602002536793], + [510744.44706764823, 6651106.611781707, 71.69806635236795], + [510744.4124679726, 6651107.210206454, 71.58714145336793], + [510743.7126715283, 6651119.313658325, 68.92640105436793], + [510743.7126715283, 6651119.313658325, 69.05640105436792], + [510743.6774844167, 6651119.92224317, 68.92640105436793], + [510744.40668679785, 6651107.310195773, 72.01323058836793], + [510744.4405156502, 6651106.725102936, 72.18096737236793], + [510744.4337014684, 6651106.842958809, 72.54267335736793], + [510744.3983446399, 6651107.454479025, 72.43813709236792], + [510744.42522448045, 6651106.989574039, 72.90043120336794], + [510744.38739151816, 6651107.643920658, 72.85510379436793], + [510744.4150836736, 6651107.164966137, 73.25088741836792], + [510744.37385631306, 6651107.878021168, 73.25705271136792], + [510743.71267139324, 6651119.31366066, 70.75520471436792], + [510744.4033077675, 6651107.368638382, 73.59063244536793], + [510743.6774844167, 6651119.92224317, 70.75520471336793], + [510743.7129337642, 6651119.309122778, 70.95902599836792], + [510744.35785260145, 6651108.154816163, 73.63693351336792], + [510744.38995621103, 6651107.599562564, 73.91629955536793], + [510743.6786942649, 6651119.901318029, 71.22079540036792], + [510743.71511233953, 6651119.271442845, 71.37560528636793], + [510744.3443458806, 6651108.388424016, 73.90333982836795], + [510744.3751188579, 6651107.856184602, 74.22466836336794], + [510744.32967281365, 6651108.642204613, 74.15104956836792], + [510743.71965356276, 6651119.192899325, 71.79993240636793], + [510743.6824776216, 6651119.835882322, 71.69806635236795], + [510744.35891424963, 6651108.1364542395, 74.51276671436793], + [510744.3085285353, 6651109.00790918, 74.44849203836793], + [510743.72670442716, 6651119.070949866, 72.22624275736793], + [510744.34148655395, 6651108.437878001, 74.77796443936792], + [510743.6890296196, 6651119.722561093, 72.18096737236793], + [510744.2859144142, 6651109.399035669, 74.70470516136793], + [510743.7363505456, 6651118.904113736, 72.64805161636792], + [510744.3230013157, 6651108.757592674, 75.01805288636793], + [510743.6958438014, 6651119.604705219, 72.54267335736793], + [510744.26222841314, 6651109.808701046, 74.91698297036794], + [510744.3036402822, 6651109.092454818, 75.23130522136793], + [510743.74860354426, 6651118.692189854, 73.05840115936793], + [510743.7043207894, 6651119.45808999, 72.90043120336794], + [510744.23788096296, 6651110.229806632, 75.08409772736793], + [510744.28359563736, 6651109.43914048, 75.41651412336795], + [510744.21327367966, 6651110.655406205, 75.20625084936793], + [510743.7144615962, 6651119.282697892, 73.25088741836792], + [510743.7633925562, 6651118.436403908, 73.45018085336793], + [510744.26306401653, 6651109.794248721, 75.57300541536793], + [510744.1887808716, 6651111.079025854, 75.28492554236793], + [510743.7760577557, 6651118.217350735, 73.72766271336792], + [510744.16473528015, 6651111.49491059, 75.32266840136792], + [510743.7262375024, 6651119.079025646, 73.59063244536793], + [510744.24224067136, 6651110.154402531, 75.70062817436792], + [510743.78996689094, 6651117.976782853, 73.98810338636792], + [510744.2213141163, 6651110.5163414255, 75.79972366836793], + [510743.7395890588, 6651118.848101465, 73.91629955536793], + [510743.8049999236, 6651117.716776405, 74.22907303236792], + [510744.06372261286, 6651113.2419928545, 75.32266840136792], + [510744.1935556005, 6651110.996443695, 75.88888832036793], + [510743.8210165995, 6651117.439757184, 74.44849203836793], + [510743.75442641194, 6651118.591479427, 74.22466836336794], + [510744.1663039301, 6651111.4677797295, 75.93166356136794], + [510743.84363072057, 6651117.048630697, 74.70470516136793], + [510743.7706310202, 6651118.3112097895, 74.51276671436793], + [510743.86731672165, 6651116.63896532, 74.91698297036794], + [510743.96480985463, 6651114.952755776, 75.32266840136792], + [510743.8916641718, 6651116.217859733, 75.08409772736793], + [510743.94076426316, 6651115.36864051, 75.28492554236793], + [510743.9162714551, 6651115.792260159, 75.20625084936793], + [510743.7880587159, 6651118.009786028, 74.77796443936792], + [510743.8065439542, 6651117.690071355, 75.01805288636793], + [510743.82590498775, 6651117.355209211, 75.23130522136793], + [510743.84594963246, 6651117.008523548, 75.41651412336795], + [510743.9632413397, 6651114.979884299, 75.93166356136794], + [510743.8664812533, 6651116.653415308, 75.57300541536793], + [510743.93598966935, 6651115.451220333, 75.88888832036793], + [510743.88730459847, 6651116.293261498, 75.70062817436792], + [510743.9082311535, 6651115.9313226035, 75.79972366836793], + [510750.856643526, 6651106.906945225, 68.9035058657163], + [510750.8193307429, 6651107.515403444, 68.9035058657163], + [510750.8193307429, 6651107.515403444, 69.0335058657163], + [510750.856643526, 6651106.906945225, 70.7323095247163], + [510750.8193307429, 6651107.515403444, 70.7323095247163], + [510750.8553605902, 6651106.927866013, 71.1979002117163], + [510750.8181987407, 6651107.533862962, 71.14312483671631], + [510750.07258730987, 6651119.692521863, 68.9035058657163], + [510750.03527452674, 6651120.30098008, 68.9035058657163], + [510750.07258730987, 6651119.692521863, 69.0335058657163], + [510750.851348679, 6651106.993288105, 71.6751711637163], + [510750.81465881906, 6651107.591588338, 71.56424626471629], + [510750.80852840055, 6651107.691556854, 71.9903353997163], + [510750.84440087137, 6651107.106585755, 72.1580721837163], + [510750.8371750413, 6651107.224417107, 72.51977816871631], + [510750.7996822885, 6651107.835810084, 72.41524190371629], + [510750.82818595413, 6651107.37100183, 72.87753601471631], + [510750.78806748305, 6651108.025212301, 72.83220860571629], + [510750.0725871666, 6651119.692524197, 70.7323095257163], + [510750.817432536, 6651107.546357435, 73.22799222971629], + [510750.03527452674, 6651120.30098008, 70.7323095247163], + [510750.77371460927, 6651108.259264101, 73.2341575227163], + [510750.07286538754, 6651119.687987258, 70.93613080971629], + [510750.8049452412, 6651107.749987303, 73.5677372567163], + [510750.0365574624, 6651120.280059292, 71.1979002117163], + [510750.7567441052, 6651108.536001503, 73.61403832471629], + [510750.07517557184, 6651119.650315166, 71.3527100977163], + [510750.79078711045, 6651107.980863436, 73.8934043667163], + [510751.5875913436, 6651106.951915768, 68.90065002138758], + [510750.74242143636, 6651108.769560751, 73.8804446397163], + [510751.5500359599, 6651107.560359061, 68.90065002138758], + [510750.07999113266, 6651119.57178799, 71.77703721771631], + [510750.04056937364, 6651120.214637199, 71.6751711637163], + [510750.77505342505, 6651108.237432078, 74.20177317471631], + [510751.5500359599, 6651107.560359061, 69.03065002138757], + [510750.72686196177, 6651109.023288545, 74.12815437971629], + [510750.0874679433, 6651119.449863903, 72.2033475687163], + [510750.75786988804, 6651108.5176434005, 74.4898715257163], + [510750.0475171813, 6651120.101339551, 72.1580721837163], + [510750.7044403466, 6651109.38891702, 74.42559684971631], + [510750.7393893763, 6651108.819004444, 74.75506925071629], + [510750.0976967889, 6651119.283062487, 72.62515642771629], + [510750.0547430113, 6651119.9835081985, 72.51977816871631], + [510750.6804600949, 6651109.779962127, 74.6818099727163], + [510750.7197874351, 6651109.1386525985, 74.9951576977163], + [510750.0637320985, 6651119.836923476, 72.87753601471631], + [510750.1106899975, 6651119.071182698, 73.0355059707163], + [510750.65534321027, 6651110.189542265, 74.8940877817163], + [510750.6992567916, 6651109.473445066, 75.2084100327163], + [510750.6295249179, 6651110.610560233, 75.0612025387163], + [510750.07448551664, 6651119.6615678705, 73.22799222971629], + [510750.1263724214, 6651118.815449975, 73.4272856647163], + [510750.67800123943, 6651109.820058594, 75.3936189347163], + [510750.603431096, 6651111.036071253, 75.1833556607163], + [510751.5875913436, 6651106.951915768, 70.72945368038758], + [510750.1398027321, 6651118.596442379, 73.7047675247163], + [510750.08697281143, 6651119.457938003, 73.5677372567163], + [510751.5500359599, 6651107.560359061, 70.72945368038758], + [510750.5774586647, 6651111.45960276, 75.2620303537163], + [510750.6562292928, 6651110.175092947, 75.5501102267163], + [510750.1545521254, 6651118.355924551, 73.96520819771631], + [510750.5519604666, 6651111.875400962, 75.29977321271629], + [510750.63414799864, 6651110.535171822, 75.67773298571629], + [510750.1011309423, 6651119.2270618705, 73.8934043667163], + [510750.17049331125, 6651118.095972205, 74.20617784371629], + [510751.5863000664, 6651106.972836043, 71.19504436738757], + [510751.5488965977, 6651107.578818127, 71.14026899238758], + [510750.6119572596, 6651110.897035409, 75.7768284797163], + [510750.18747756275, 6651117.819010622, 74.42559684971631], + [510750.44484557194, 6651113.6221197145, 75.29977321271629], + [510750.1168646276, 6651118.970493227, 74.20177317471631], + [510750.58252183744, 6651111.377037784, 75.8659931317163], + [510750.7984373454, 6651119.73717877, 68.90065002138758], + [510750.2114578146, 6651117.427965514, 74.6818099727163], + [510750.1340481646, 6651118.690281905, 74.4898715257163], + [510750.55362387956, 6651111.848275747, 75.90876837271631], + [510750.7608819617, 6651120.345622063, 68.90065002138758], + [510750.7984373454, 6651119.73717877, 69.03065002138757], + [510750.2365746992, 6651117.018385376, 74.8940877817163], + [510751.5822620705, 6651107.038256531, 71.67231531938758], + [510751.54533366015, 6651107.636542086, 71.56139042038757], + [510750.3399574428, 6651115.332526679, 75.29977321271629], + [510750.2623929916, 6651116.597367409, 75.0612025387163], + [510750.3144592448, 6651115.748324881, 75.2620303537163], + [510750.2884868135, 6651116.171856388, 75.1833556607163], + [510750.15252867644, 6651118.38892086, 74.75506925071629], + [510750.17213061755, 6651118.069272708, 74.9951576977163], + [510750.1926612611, 6651117.7344802385, 75.2084100327163], + [510751.53916338284, 6651107.73650815, 71.9874795553876], + [510751.5752690896, 6651107.1515514, 72.15521633938758], + [510750.2139168132, 6651117.387866712, 75.3936189347163], + [510750.2356887598, 6651117.032832358, 75.5501102267163], + [510750.33829417307, 6651115.359649558, 75.90876837271631], + [510750.2577700541, 6651116.672753485, 75.67773298571629], + [510750.30939621525, 6651115.830887522, 75.8659931317163], + [510750.27996079304, 6651116.310889898, 75.7768284797163], + [510751.5679962787, 6651107.269379862, 72.51692232438758], + [510751.53025975515, 6651107.880757842, 72.41238605938757], + [510751.5589487461, 6651107.415960989, 72.87468017038758], + [510751.5185694325, 6651108.070155413, 72.82935276138757], + [510750.79843720124, 6651119.737181106, 70.72945368138757], + [510751.54812541127, 6651107.591312292, 73.22513638538757], + [510750.7608819617, 6651120.345622063, 70.72945368038758], + [510751.5041232391, 6651108.304201472, 73.23130167838758], + [510750.7987172311, 6651119.732644279, 70.93327496538757], + [510751.53555692657, 6651107.794937166, 73.56488141238758], + [510750.76217323885, 6651120.324701788, 71.19504436738757], + [510750.8010424357, 6651119.69497311, 71.34985425338758], + [510751.487042396, 6651108.580932085, 73.61118248038757], + [510751.52130674233, 6651108.025807634, 73.89054852238758], + [510751.472626604, 6651108.814485602, 73.87758879538757], + [510750.80588930636, 6651119.6164478585, 71.77418137338758], + [510750.7662112348, 6651120.259281302, 71.67231531938758], + [510751.5054707596, 6651108.282369984, 74.19891733038757], + [510751.4569659648, 6651109.068207172, 74.12529853538757], + [510750.8134147299, 6651119.494526765, 72.20049172438759], + [510751.4881754986, 6651108.562574432, 74.48701568138758], + [510750.77320421574, 6651120.14598643, 72.15521633938758], + [510751.43439856864, 6651109.433826678, 74.42274100538758], + [510750.8237100814, 6651119.32772944, 72.62230058338757], + [510751.4695748301, 6651108.863928085, 74.75221340638757], + [510750.78047702665, 6651120.028157969, 72.51692232438758], + [510751.4102624018, 6651109.824862193, 74.67895412838757], + [510751.44984544086, 6651109.183568395, 74.99230185338757], + [510750.7895245592, 6651119.881576842, 72.87468017038758], + [510750.83678776934, 6651119.115854849, 73.03265012638758], + [510751.3849822121, 6651110.234432285, 74.89123193738757], + [510751.42918131105, 6651109.518352652, 75.2055541883876], + [510750.800347894, 6651119.706225539, 73.22513638538757], + [510751.3589960542, 6651110.655439925, 75.05834669438758], + [510750.85257215734, 6651118.860128398, 73.42442982038759], + [510751.40778755944, 6651109.864957676, 75.39076309038758], + [510751.33273257525, 6651111.080940507, 75.18049981638758], + [510750.8660897893, 6651118.6411261745, 73.70191168038758], + [510750.8129163787, 6651119.502600665, 73.56488141238758], + [510751.3065912763, 6651111.504461624, 75.25917450938758], + [510751.3858740558, 6651110.219983321, 75.54725438238759], + [510750.8809350803, 6651118.400614246, 73.96235235338757], + [510751.2809272938, 6651111.920249627, 75.29691736838757], + [510750.82716656296, 6651119.271730197, 73.89054852238758], + [510751.3636491933, 6651110.580053363, 75.67487714138758], + [510750.8969799127, 6651118.140668276, 74.20332199938757], + [510751.3413141743, 6651110.941908073, 75.77397263538758], + [510750.9140745925, 6651117.863713488, 74.42274100538758], + [510750.84300254576, 6651119.015167847, 74.19891733038757], + [510751.1731159588, 6651113.666925532, 75.29691736838757], + [510751.3116873687, 6651111.421898673, 75.86313728738759], + [510750.93821075937, 6651117.472677973, 74.67895412838757], + [510750.86029780674, 6651118.734963399, 74.48701568138758], + [510751.282601522, 6651111.893125078, 75.90591252838757], + [510750.96349094907, 6651117.063107883, 74.89123193738757], + [510751.0675458673, 6651115.377290539, 75.29691736838757], + [510750.9894771069, 6651116.642100242, 75.05834669438758], + [510751.0418818849, 6651115.793078542, 75.25917450938758], + [510751.0157405858, 6651116.21659966, 75.18049981638758], + [510750.8788984752, 6651118.433609747, 74.75221340638757], + [510750.8986278645, 6651118.113969435, 74.99230185338757], + [510750.9192919943, 6651117.779185179, 75.2055541883876], + [510750.94068574585, 6651117.432580154, 75.39076309038758], + [510750.9625992495, 6651117.077554509, 75.54725438238759], + [510751.06587178336, 6651115.404412754, 75.90591252838757], + [510750.984824112, 6651116.717484468, 75.67487714138758], + [510751.03678593657, 6651115.875639157, 75.86313728738759], + [510751.007159131, 6651116.355629758, 75.77397263538758], + [510761.3150627726, 6651107.578246551, 68.8579046167634], + [510761.2742788554, 6651108.186481965, 68.8579046167634], + [510761.2742788554, 6651108.186481965, 68.98790461676339], + [510761.3150627726, 6651107.578246551, 70.68670827576341], + [510761.2742788554, 6651108.186481965, 70.68670827576341], + [510760.45806736604, 6651120.359141392, 68.8579046167634], + [510760.4172834488, 6651120.967376806, 68.8579046167634], + [510760.45806736604, 6651120.359141392, 68.98790461676339], + [510761.3136604879, 6651107.599159678, 71.15229896276338], + [510761.2730415454, 6651108.204934724, 71.09752358776339], + [510761.2691723118, 6651108.262638962, 71.5186450157634], + [510761.3092753565, 6651107.664557815, 71.6295699147634], + [510761.26247159275, 6651108.362570872, 71.9447341507634], + [510761.30168120813, 6651107.777813977, 72.11247093476341], + [510761.2528025445, 6651108.5067712795, 72.36964065476339], + [510761.2937831736, 6651107.895602181, 72.4741769197634], + [510760.45806720946, 6651120.359143726, 70.68670827676338], + [510760.4172834488, 6651120.967376806, 70.68670827576341], + [510761.28395784943, 6651108.042133229, 72.83193476576339], + [510761.2401072368, 6651108.696104142, 72.78660735676338], + [510760.45837131276, 6651120.354608448, 70.8905295607634], + [510761.2722040622, 6651108.217424622, 73.18239098076339], + [510760.41868573363, 6651120.946463679, 71.15229896276338], + [510760.46089640877, 6651120.316950152, 71.3071088487634], + [510761.2244191437, 6651108.930070237, 73.1885562737634], + [510761.25855509925, 6651108.420979925, 73.52213600776341], + [510760.4661599517, 6651120.2384517295, 71.73143596876339], + [510760.42307086487, 6651120.881065543, 71.6295699147634], + [510761.2058699073, 6651109.206706304, 73.56843707576338], + [510761.24307986564, 6651108.651771516, 73.84780311776339], + [510761.19021482917, 6651109.440180027, 73.83484339076338], + [510760.47433231527, 6651120.116572291, 72.15774631976339], + [510760.43066501326, 6651120.76780938, 72.11247093476341], + [510761.2258825069, 6651108.908246209, 74.15617192576339], + [510761.1732078877, 6651109.693814911, 74.08255313076339], + [510760.48551272985, 6651119.949831951, 72.57955517876339], + [510760.4385630479, 6651120.650021177, 72.4741769197634], + [510761.20710041956, 6651109.188354924, 74.4442702767634], + [510761.14870043425, 6651110.059309501, 74.3799956007634], + [510760.44838837197, 6651120.503490129, 72.83193476576339], + [510760.4997146709, 6651119.73802975, 72.9899047217634], + [510761.1869007026, 6651109.489605617, 74.70946800176338], + [510761.1224893473, 6651110.450211417, 74.63620872376339], + [510760.4601421593, 6651120.328198736, 73.18239098076339], + [510761.16547523177, 6651109.80913672, 74.94955644876339], + [510760.5168559994, 6651119.482390669, 73.38168441576339], + [510761.0950358888, 6651110.859641577, 74.84848653276339], + [510760.5315357052, 6651119.263463269, 73.6591662757634], + [510760.4737911222, 6651120.124643432, 73.52213600776341], + [510761.14303466334, 6651110.143806596, 75.1628087837634], + [510761.0668157721, 6651111.280505376, 75.0156012897634], + [510760.5476572053, 6651119.023033513, 73.91960694876339], + [510761.0382944938, 6651111.705860583, 75.1377544117634], + [510761.1198017494, 6651110.490293201, 75.3480176857634], + [510760.4892663558, 6651119.893851841, 73.84780311776339], + [510761.0099058989, 6651112.129237003, 75.2164291047634], + [510760.5650813679, 6651118.763176355, 74.1605765947634], + [510761.0960044019, 6651110.84519755, 75.5045089777634], + [510760.9820356542, 6651112.5448829485, 75.2541719637634], + [510760.5064637145, 6651119.637377148, 74.15617192576339], + [510760.5836456307, 6651118.486316191, 74.3799956007634], + [510761.07186892885, 6651111.20514457, 75.63213173676338], + [510760.86495607387, 6651114.290962093, 75.2541719637634], + [510760.60985671764, 6651118.095414275, 74.63620872376339], + [510760.5252458018, 6651119.357268432, 74.4442702767634], + [510761.04761382943, 6651111.5668756515, 75.73122723076341], + [510760.6373101761, 6651117.685984117, 74.84848653276339], + [510761.01544008846, 6651112.04670226, 75.82039188276339], + [510760.5454455189, 6651119.056017741, 74.70946800176338], + [510760.6655302927, 6651117.265120316, 75.0156012897634], + [510760.7503104106, 6651116.000742743, 75.2541719637634], + [510760.694051571, 6651116.839765109, 75.1377544117634], + [510760.72244016593, 6651116.416388689, 75.2164291047634], + [510760.9838538111, 6651112.517767667, 75.86316712376339], + [510760.5668709896, 6651118.736486637, 74.94955644876339], + [510760.5893115582, 6651118.40181676, 75.1628087837634], + [510760.61254447204, 6651118.055330155, 75.3480176857634], + [510760.6363418195, 6651117.700425807, 75.5045089777634], + [510760.66047729267, 6651117.340478787, 75.63213173676338], + [510760.7484924103, 6651116.027855691, 75.86316712376339], + [510760.68473239196, 6651116.978747706, 75.73122723076341], + [510760.71690613293, 6651116.498921096, 75.82039188276339], + [510768.77047211194, 6651108.093390549, 68.81917060298551], + [510768.72721375537, 6651108.701454987, 68.81917060298551], + [510768.72721375537, 6651108.701454987, 68.9491706029855], + [510767.86148113036, 6651120.870692668, 68.81917060298551], + [510767.8182227738, 6651121.478757107, 68.81917060298551], + [510768.77047211194, 6651108.093390549, 70.64797426198551], + [510767.86148113036, 6651120.870692668, 68.9491706029855], + [510768.72721375537, 6651108.701454987, 70.64797426198551], + [510768.76898474793, 6651108.114297796, 71.1135649489855], + [510768.7259013753, 6651108.719902559, 71.05878957398552], + [510768.72179738793, 6651108.777590576, 71.4799110019855], + [510768.7643335621, 6651108.17967755, 71.59083590098551], + [510768.7146901231, 6651108.877494394, 71.90600013698551], + [510768.7562786621, 6651108.292901875, 72.07373692098551], + [510767.8614809644, 6651120.870695001, 70.6479742629855], + [510767.8182227738, 6651121.478757107, 70.64797426198551], + [510768.704434435, 6651109.021654268, 72.3309066409855], + [510768.7479014383, 6651108.410656969, 72.43544290598551], + [510767.86180351814, 6651120.866161, 70.8517955469855], + [510768.7374799928, 6651108.557146828, 72.79320075198551], + [510768.6909688783, 6651109.210933909, 72.7478733429855], + [510767.81971013796, 6651121.457849858, 71.1135649489855], + [510767.8644818167, 6651120.828513289, 71.26837483498551], + [510768.72501308034, 6651108.732388945, 73.1436569669855], + [510768.67432895803, 6651109.444834236, 73.1498222599855], + [510767.82436132367, 6651121.3924701065, 71.59083590098551], + [510767.8700647089, 6651120.750036932, 71.69270195498551], + [510768.7105360084, 6651108.935887029, 73.48340199398551], + [510768.65465430357, 6651109.721392539, 73.5297030619855], + [510767.8787329057, 6651120.628191753, 72.1190123059855], + [510767.83241622377, 6651121.279245781, 72.07373692098551], + [510768.69412186235, 6651109.166613744, 73.80906910398552], + [510768.6380494014, 6651109.954800633, 73.7961093769855], + [510767.84079344745, 6651121.161490685, 72.43544290598551], + [510767.8905916578, 6651120.461498286, 72.5408211649855], + [510768.6758811064, 6651109.423016342, 74.1174379119855], + [510768.62001061573, 6651110.20836422, 74.04381911698552], + [510767.8512148931, 6651121.015000829, 72.79320075198551], + [510767.9056552582, 6651120.24975562, 72.95117070798551], + [510768.65595947346, 6651109.703046319, 74.4055362629855], + [510768.5940162476, 6651110.57375607, 74.34126158698552], + [510767.86368180544, 6651120.839758709, 73.1436569669855], + [510768.6345342003, 6651110.004212329, 74.67073398798551], + [510767.9238365844, 6651119.994188401, 73.3429504019855], + [510768.56621488306, 6651110.964548103, 74.59747470998552], + [510767.87815887737, 6651120.636260627, 73.48340199398551], + [510767.9394069364, 6651119.7753225425, 73.6204322619855], + [510768.61180880474, 6651110.323653613, 74.91082243498552], + [510768.53709577, 6651111.37386317, 74.8097525189855], + [510767.9565065591, 6651119.5349603705, 73.8808729349855], + [510767.8945730234, 6651120.405533911, 73.80906910398552], + [510768.5880067233, 6651110.658229413, 75.12407476998551], + [510768.5071634841, 6651111.794608666, 74.97686727598553], + [510767.97498787957, 6651119.275176259, 74.1218425809855], + [510768.4769117645, 6651112.219844305, 75.0990203979855], + [510768.5633642235, 6651111.00461862, 75.30928367198551], + [510767.9128137794, 6651120.149131312, 74.1174379119855], + [510768.4468007783, 6651112.643101713, 75.17769509098551], + [510767.99467847217, 6651118.998393919, 74.34126158698552], + [510768.4172395918, 6651113.05863082, 75.2154379499855], + [510768.5381230447, 6651111.359423203, 75.46577496398551], + [510767.9327354123, 6651119.869101336, 74.4055362629855], + [510768.0224798366, 6651118.607601887, 74.59747470998552], + [510768.5125232256, 6651111.719269044, 75.5933977229855], + [510768.293056566, 6651114.804219138, 75.2154379499855], + [510768.05159894977, 6651118.19828682, 74.8097525189855], + [510767.9541606855, 6651119.567935327, 74.67073398798551], + [510768.4867965223, 6651112.08089844, 75.69249321698551], + [510768.0815312357, 6651117.7775413245, 74.97686727598553], + [510768.1117829553, 6651117.352305684, 75.0990203979855], + [510768.17145512794, 6651116.513519169, 75.2154379499855], + [510768.14189394144, 6651116.9290482765, 75.17769509098551], + [510768.452670738, 6651112.56059017, 75.7816578689855], + [510767.97688608104, 6651119.248494042, 74.91082243498552], + [510768.4191680598, 6651113.031523161, 75.8244331099855], + [510768.00068816246, 6651118.913918243, 75.12407476998551], + [510768.02533066226, 6651118.567529035, 75.30928367198551], + [510768.0505718411, 6651118.212724451, 75.46577496398551], + [510768.07617166016, 6651117.8528786125, 75.5933977229855], + [510768.1018983635, 6651117.491249215, 75.69249321698551], + [510768.16952682595, 6651116.540624496, 75.8244331099855], + [510768.1360241478, 6651117.011557484, 75.7816578689855], + [510771.06181310286, 6651108.257839253, 68.80622400340143], + [510771.01779425354, 6651108.865849112, 68.80622400340143], + [510771.01779425354, 6651108.865849112, 68.93622400340142], + [510770.1368418328, 6651121.0339944735, 68.80622400340143], + [510770.09282298345, 6651121.642004333, 68.80622400340143], + [510770.1368418328, 6651121.0339944735, 68.93622400340142], + [510771.06181310286, 6651108.257839253, 70.63502766240143], + [510771.01779425354, 6651108.865849112, 70.63502766240143], + [510771.0602995905, 6651108.278744626, 71.10061834940143], + [510771.0164588016, 6651108.884295029, 71.04584297440144], + [510771.012282665, 6651108.941977868, 71.46696440240142], + [510771.0555666358, 6651108.34411851, 71.57788930140143], + [510771.0050504527, 6651109.041872717, 71.89305353740141], + [510771.04737012857, 6651108.4573326735, 72.06079032140143], + [510770.13684166386, 6651121.0339968065, 70.63502766340143], + [510770.09282298345, 6651121.642004333, 70.63502766240143], + [510770.9946144671, 6651109.1860196525, 72.31796004140142], + [510770.13716988824, 6651121.029463212, 70.83884894740142], + [510771.03884563124, 6651108.575077197, 72.42249630640144], + [510770.0943364958, 6651121.621098961, 71.10061834940143], + [510771.028240974, 6651108.721553905, 72.78025415240143], + [510770.1398952719, 6651120.991818881, 71.25542823540142], + [510770.98091218254, 6651109.375282303, 72.73492674340142], + [510771.01555489015, 6651108.896780294, 73.13071036740142], + [510770.0990694505, 6651121.555725077, 71.57788930140143], + [510770.14557631285, 6651120.913349567, 71.67975535540144], + [510770.96397972835, 6651109.609161634, 73.13687566040143], + [510771.0008233076, 6651109.1002601115, 73.47045539440143], + [510770.1543968986, 6651120.791515325, 72.10606570640142], + [510770.10726595775, 6651121.442510913, 72.06079032140143], + [510770.9439591885, 6651109.885695116, 73.51675646240142], + [510770.98412059684, 6651109.330966116, 73.79612250440144], + [510770.92706236796, 6651110.119082257, 73.78316277740142], + [510770.1157904552, 6651121.32476639, 72.42249630640144], + [510770.1664641305, 6651120.624836821, 72.52787456540142], + [510770.9655591638, 6651109.587345701, 74.10449131240142], + [510770.908706456, 6651110.372623084, 74.03087251740142], + [510770.1263951124, 6651121.178289681, 72.78025415240143], + [510770.18179255276, 6651120.413113163, 72.93822410840143], + [510770.9452873036, 6651109.86735054, 74.39258966340142], + [510770.8822551003, 6651110.737982137, 74.32831498740144], + [510770.13908119616, 6651121.003063292, 73.13071036740142], + [510770.2002935112, 6651120.157568882, 73.33000380240142], + [510770.92348536884, 6651110.168489519, 74.65778738840143], + [510770.8539649809, 6651111.128739091, 74.58452811040144], + [510770.15381277876, 6651120.799583474, 73.47045539440143], + [510770.21613759396, 6651119.938722669, 73.60748566240143], + [510770.900360455, 6651110.487902128, 74.89787583540142], + [510770.8243339465, 6651111.538017418, 74.79680591940142], + [510770.2335378323, 6651119.698382073, 73.86792633540144], + [510770.1705154896, 6651120.56887747, 73.79612250440144], + [510770.7938754436, 6651111.958725148, 74.96392067640143], + [510770.87613992713, 6651110.822447896, 75.11112817040143], + [510770.252344059, 6651119.43862128, 74.10889598140142], + [510770.76309189113, 6651112.383922617, 75.08607379840143], + [510770.18907692254, 6651120.312497886, 74.10449131240142], + [510770.851064206, 6651111.168806013, 75.29633707240143], + [510770.27238081716, 6651119.161863784, 74.32831498740144], + [510770.7324515464, 6651112.807142033, 75.16474849140143], + [510770.7023706667, 6651113.222633842, 75.20249135040142], + [510770.82537928096, 6651111.523578749, 75.45282836440143], + [510770.20934878284, 6651120.0324930465, 74.39258966340142], + [510770.3006709365, 6651118.771106829, 74.58452811040144], + [510770.7993294106, 6651111.883392287, 75.58045112340142], + [510770.5760044724, 6651114.968065476, 75.20249135040142], + [510770.3303019709, 6651118.361828502, 74.79680591940142], + [510770.2311507176, 6651119.731354068, 74.65778738840143], + [510770.36076047394, 6651117.941120773, 74.96392067640143], + [510770.77315042546, 6651112.244989226, 75.67954661740143], + [510770.3915440263, 6651117.515923304, 75.08607379840143], + [510770.4522652506, 6651116.677212078, 75.20249135040142], + [510770.42218437104, 6651117.092703887, 75.16474849140143], + [510770.25427563133, 6651119.411941458, 74.89787583540142], + [510770.7384247013, 6651112.724637897, 75.76871126940142], + [510770.7043330378, 6651113.195528616, 75.81148651040142], + [510770.2784961593, 6651119.07739569, 75.11112817040143], + [510770.3035718804, 6651118.731037575, 75.29633707240143], + [510770.32925680536, 6651118.3762648385, 75.45282836440143], + [510770.3553066757, 6651118.016451299, 75.58045112340142], + [510770.38148566097, 6651117.654854361, 75.67954661740143], + [510770.45030304865, 6651116.70431497, 75.81148651040142], + [510770.416211385, 6651117.17520569, 75.76871126940142], + [510778.1676664001, 6651108.786148307, 68.76295607119135], + [510778.12128912844, 6651109.39398282, 68.76295607119135], + [510778.12128912844, 6651109.39398282, 68.89295607119135], + [510777.1931374316, 6651121.55861899, 68.76295607119135], + [510777.14676016, 6651122.166453505, 68.76295607119135], + [510777.1931374316, 6651121.55861899, 68.89295607119135], + [510778.1676664001, 6651108.786148307, 70.59175973019136], + [510778.12128912844, 6651109.39398282, 70.59175973019136], + [510778.1660717975, 6651108.807047649, 71.05735041719136], + [510778.11988212616, 6651109.412423416, 71.00257504219137], + [510778.1154822424, 6651109.470089621, 71.42369647019135], + [510778.1610852626, 6651108.87240268, 71.53462136919136], + [510777.1931372536, 6651121.558621322, 70.59175973119136], + [510777.14676016, 6651122.166453505, 70.59175973019136], + [510778.1078625459, 6651109.569955662, 71.84978560519136], + [510777.1934830634, 6651121.554089035, 70.79558101519135], + [510778.1524496065, 6651108.985584193, 72.01752238919136], + [510777.1483547626, 6651122.145554162, 71.05735041719136], + [510778.09686742566, 6651109.7140610255, 72.27469210919135], + [510778.1434683874, 6651109.103294761, 72.37922837419137], + [510777.1963544665, 6651121.516455559, 71.21216030319135], + [510778.1322955586, 6651109.249729227, 72.73698622019135], + [510778.0824310062, 6651109.903269094, 72.69165881119135], + [510777.15334129747, 6651122.080199131, 71.53462136919136], + [510777.20233988366, 6651121.438008877, 71.63648742319137], + [510778.1189297854, 6651109.424905081, 73.08744243519135], + [510778.0645913526, 6651110.137080977, 73.09360772819136], + [510777.21163305483, 6651121.316209772, 72.06279777419135], + [510777.16197695344, 6651121.967017616, 72.01752238919136], + [510778.1034089207, 6651109.628326218, 73.42718746219136], + [510778.04349816113, 6651110.413534708, 73.47348853019135], + [510777.17095817265, 6651121.849307049, 72.37922837419137], + [510777.2243468195, 6651121.149579335, 72.48460663319135], + [510778.08581131947, 6651109.858965688, 73.75285457219137], + [510778.0256960504, 6651110.646854544, 73.73989484519134], + [510777.1821310015, 6651121.702872584, 72.73698622019135], + [510777.2404965012, 6651120.937916735, 72.89495617619136], + [510778.0662554103, 6651110.1152713355, 74.06122338019135], + [510778.00635667343, 6651110.900322251, 73.98760458519135], + [510777.1954967746, 6651121.527696728, 73.08744243519135], + [510777.25998869573, 6651120.682446152, 73.28673587019135], + [510778.0448974334, 6651110.395195425, 74.34932173119135], + [510777.97848811885, 6651111.265575936, 74.28504705519137], + [510777.21101763926, 6651121.324275592, 73.42718746219136], + [510777.2766816656, 6651120.463663052, 73.56421773019136], + [510778.02192740433, 6651110.696247556, 74.61451945619136], + [510777.948682284, 6651111.6562202, 74.54126017819137], + [510777.2950141663, 6651120.2233917685, 73.82465840319136], + [510777.2286152405, 6651121.093636122, 73.75285457219137], + [510777.99756351416, 6651111.01556805, 74.85460790319135], + [510777.9174636914, 6651112.065380495, 74.75353798719135], + [510777.31482798455, 6651119.963705887, 74.06562804919135], + [510777.24817114964, 6651120.837330476, 74.06122338019135], + [510777.8853732962, 6651112.485966895, 74.92065274419136], + [510777.97204530967, 6651111.350017337, 75.06786023819136], + [510777.33593826316, 6651119.687028207, 74.28504705519137], + [510777.8529404364, 6651112.911041741, 75.04280586619134], + [510777.2695291266, 6651120.557406387, 74.34932173119135], + [510777.94562609267, 6651111.696275567, 75.25306914019136], + [510777.3657440979, 6651119.296383943, 74.54126017819137], + [510777.8206584568, 6651113.334139104, 75.12148055919135], + [510777.7889659173, 6651113.74951109, 75.15922341819135], + [510777.29249915574, 6651120.256354256, 74.61451945619136], + [510777.91856503225, 6651112.05094599, 75.40956043219136], + [510777.3969626907, 6651118.887223649, 74.75353798719135], + [510777.6558293313, 6651115.494439354, 75.15922341819135], + [510777.42905308574, 6651118.466637248, 74.92065274419136], + [510777.8911194735, 6651112.410655761, 75.53718319119135], + [510777.3168630458, 6651119.93703376, 74.85460790319135], + [510777.4614859456, 6651118.041562402, 75.04280586619134], + [510777.5254604647, 6651117.203093054, 75.15922341819135], + [510777.4937679251, 6651117.618465039, 75.12148055919135], + [510777.86353788234, 6651112.772148418, 75.63627868519136], + [510777.3423812504, 6651119.602584473, 75.06786023819136], + [510777.8269516389, 6651113.251658762, 75.72544333719135], + [510777.79103342735, 6651113.72241368, 75.76821857819135], + [510777.36880046735, 6651119.256326244, 75.25306914019136], + [510777.39586152777, 6651118.901655821, 75.40956043219136], + [510777.4233070865, 6651118.541946049, 75.53718319119135], + [510777.4508886776, 6651118.180453393, 75.63627868519136], + [510777.5233931327, 6651117.23018813, 75.76821857819135], + [510777.48747492116, 6651117.700943048, 75.72544333719135], + [510785.94189542916, 6651109.395917872, 68.71021190515403], + [510785.8929379023, 6651110.003550005, 68.71021190515403], + [510785.8929379023, 6651110.003550005, 68.84021190515402], + [510784.91314737085, 6651122.164135896, 68.71021190515403], + [510784.86418984405, 6651122.771768029, 68.71021190515403], + [510784.91314737085, 6651122.164135896, 68.84021190515402], + [510785.94189542916, 6651109.395917872, 70.53901556415403], + [510785.8929379023, 6651110.003550005, 70.53901556415403], + [510785.89145261975, 6651110.021984461, 70.94983087615402], + [510785.94021210884, 6651109.416810256, 71.00460625115402], + [510784.91314718296, 6651122.164138228, 70.53901556515402], + [510785.88680794317, 6651110.079631464, 71.37095230415402], + [510784.86418984405, 6651122.771768029, 70.53901556415403], + [510785.9349481421, 6651109.482143528, 71.48187720315403], + [510784.9135122323, 6651122.159607449, 70.74283684915402], + [510785.87876431574, 6651110.179464255, 71.79704143915401], + [510784.8658731642, 6651122.750875643, 71.00460625115402], + [510785.925832031, 6651109.5952873565, 71.96477822315403], + [510784.9165433893, 6651122.121986504, 71.15941613715403], + [510785.86715746875, 6651110.323521638, 72.22194794315402], + [510785.916351131, 6651109.712958732, 72.32648420815403], + [510784.87113713106, 6651122.685542373, 71.48187720315403], + [510784.9228618124, 6651122.04356594, 71.58374325715403], + [510785.8519178618, 6651110.51266671, 72.63891464515402], + [510785.9045566883, 6651109.8593444405, 72.68424205415403], + [510784.88025324215, 6651122.572398544, 71.96477822315403], + [510784.93267202034, 6651121.921807388, 72.01005360815404], + [510785.89044729434, 6651110.03446197, 73.03469826915402], + [510785.8330856775, 6651110.746400744, 73.04086356215402], + [510784.8897341422, 6651122.454727169, 72.32648420815403], + [510784.9460931306, 6651121.755232432, 72.43186246715402], + [510785.8740629077, 6651110.237815375, 73.37444329615403], + [510785.81081894116, 6651111.022762426, 73.42074436415402], + [510784.9015285847, 6651122.30834146, 72.68424205415403], + [510784.9631413191, 6651121.543640307, 72.84221201015403], + [510785.8554862428, 6651110.468378054, 73.70011040615402], + [510785.79202638846, 6651111.2560045775, 73.68715067915402], + [510784.91563797876, 6651122.13322393, 73.03469826915402], + [510784.9837179854, 6651121.288254784, 73.23399170415404], + [510785.77161104215, 6651111.509387892, 73.93486041915402], + [510785.83484231716, 6651110.724598361, 74.00847921415402], + [510784.9320223654, 6651121.929870525, 73.37444329615403], + [510785.0013396887, 6651121.06954453, 73.51147356415402], + [510785.742191987, 6651111.874519964, 74.23230288915403], + [510785.81229606346, 6651111.004429248, 74.29657756515402], + [510784.9505990303, 6651121.699307847, 73.70011040615402], + [510785.02069214004, 6651120.829353245, 73.77191423715402], + [510785.7107278688, 6651112.265034161, 74.48851601215402], + [510785.7880480692, 6651111.305381143, 74.56177529015402], + [510785.04160832387, 6651120.5697538275, 74.01288388315402], + [510784.971242956, 6651121.44308754, 74.00847921415402], + [510785.6777723921, 6651112.674058223, 74.70079382115402], + [510785.7623286649, 6651111.624595318, 74.80186373715402], + [510785.0638930982, 6651120.293168268, 74.23230288915403], + [510784.9937892096, 6651121.163256651, 74.29657756515402], + [510785.6438966093, 6651113.094504588, 74.86790857815402], + [510785.0953572165, 6651119.902654071, 74.48851601215402], + [510785.7353907243, 6651111.958933249, 75.01511607215404], + [510785.60965930833, 6651113.519437904, 74.99006170015403], + [510785.0180372038, 6651120.862304756, 74.56177529015402], + [510785.12831269304, 6651119.493630009, 74.70079382115402], + [510785.57558128214, 6651113.942394393, 75.06873639315403], + [510785.7075016425, 6651112.305076189, 75.20032497415403], + [510785.54212549014, 6651114.357628079, 75.10647925215402], + [510785.16218847584, 6651119.0731836455, 74.86790857815402], + [510785.0437566082, 6651120.543090581, 74.80186373715402], + [510785.40158169024, 6651116.101975361, 75.10647925215402], + [510785.6789350074, 6651112.659628523, 75.35681626615404], + [510785.1964257768, 6651118.64825033, 74.99006170015403], + [510785.230503803, 6651118.225293839, 75.06873639315403], + [510785.2639595951, 6651117.810060155, 75.10647925215402], + [510785.6499624821, 6651113.019218529, 75.48443902515403], + [510785.0706945487, 6651120.20875265, 75.01511607215404], + [510785.62084635603, 6651113.3805908235, 75.58353451915403], + [510785.0985836306, 6651119.8626097115, 75.20032497415403], + [510785.5822245929, 6651113.859941513, 75.67269917115404], + [510785.1271502656, 6651119.508057376, 75.35681626615404], + [510785.54430802853, 6651114.33053969, 75.71547441215402], + [510785.15612279094, 6651119.148467371, 75.48443902515403], + [510785.18523891707, 6651118.787095077, 75.58353451915403], + [510785.22386068024, 6651118.307744387, 75.67269917115404], + [510785.26177724457, 6651117.8371462105, 75.71547441215402], + [510791.2508608473, 6651109.831415902, 68.67094383254415], + [510791.2001412827, 6651110.438903492, 68.67094383254415], + [510791.2001412827, 6651110.438903492, 68.80094383254415], + [510790.18508696026, 6651122.596596671, 68.67094383254415], + [510790.1343673957, 6651123.204084262, 68.67094383254415], + [510790.18508696026, 6651122.596596671, 68.80094383254415], + [510791.2508608473, 6651109.831415902, 70.49974749154416], + [510791.2001412827, 6651110.438903492, 70.49974749154416], + [510791.1986025431, 6651110.457333564, 70.91056280354415], + [510791.2491169424, 6651109.852303315, 70.96533817854414], + [510790.1850867657, 6651122.596599001, 70.49974749254415], + [510790.1343673957, 6651123.204084262, 70.49974749154416], + [510790.18546495354, 6651122.592069301, 70.70356877654415], + [510791.19379069924, 6651110.514966855, 71.33168423154414], + [510791.2436635195, 6651109.917621044, 71.44260913054416], + [510790.1361113005, 6651123.183196848, 70.96533817854414], + [510790.18860520545, 6651122.554457305, 71.12014806454415], + [510791.1854575724, 6651110.614775898, 71.75777336654414], + [510791.234219309, 6651110.030737959, 71.92551015054416], + [510790.1415647235, 6651123.117879118, 71.44260913054416], + [510790.1951510358, 6651122.476055396, 71.54447518454415], + [510791.17343298154, 6651110.758799013, 72.18267987054416], + [510791.2243971805, 6651110.148381343, 72.28721613554416], + [510790.15100893396, 6651123.004762203, 71.92551015054416], + [510790.20531432447, 6651122.354325807, 71.97078553554417], + [510791.15764488355, 6651110.947899089, 72.59964657254415], + [510791.2121782422, 6651110.294732231, 72.64497398154415], + [510790.16083106253, 6651122.88711882, 72.28721613554416], + [510790.21921847604, 6651122.187790476, 72.39259439454416], + [510791.1975610349, 6651110.469808105, 72.99543019654415], + [510791.1381349073, 6651111.181577524, 73.00159548954414], + [510790.1730500008, 6651122.740767932, 72.64497398154415], + [510790.23688024847, 6651121.976248683, 72.80294393754416], + [510791.1805869553, 6651110.673113138, 73.33517522354416], + [510791.1150667654, 6651111.457873467, 73.38147629154415], + [510790.187667208, 6651122.565692058, 72.99543019654415], + [510791.16134169477, 6651110.90362097, 73.66084233354415], + [510790.2581974926, 6651121.720923911, 73.19472363154416], + [510791.09559784713, 6651111.691060135, 73.64788260654416], + [510790.20464128774, 6651122.362387026, 73.33517522354416], + [510791.07444772887, 6651111.944383178, 73.89559234654415], + [510790.27645342145, 6651121.5022656815, 73.47220549154414], + [510791.1399547704, 6651111.159780329, 73.96921114154415], + [510790.22388654825, 6651122.131879194, 73.66084233354415], + [510790.29650238977, 6651121.262131533, 73.73264616454415], + [510791.0439698481, 6651112.309428392, 74.19303481654416], + [510791.1165970511, 6651111.439544652, 74.25730949254415], + [510790.3181713712, 6651121.002593868, 73.97361581054415], + [510790.2452734725, 6651121.875719834, 73.96921114154415], + [510791.01137329993, 6651112.699849695, 74.44924793954415], + [510791.0914763436, 6651111.740424957, 74.52250721754415], + [510790.3412582002, 6651120.726074102, 74.19303481654416], + [510790.26863119187, 6651121.595955512, 74.25730949254415], + [510790.9772317177, 6651113.108776461, 74.66152574854415], + [510791.06483126816, 6651112.059563198, 74.76259566454415], + [510790.3738547484, 6651120.335652799, 74.44924793954415], + [510790.9421367065, 6651113.529122812, 74.82864050554414], + [510790.2937518994, 6651121.295075206, 74.52250721754415], + [510791.03692380013, 6651112.393821598, 74.97584799954417], + [510790.4079963306, 6651119.926726034, 74.66152574854415], + [510790.9066671655, 6651113.953955046, 74.95079362754416], + [510790.8713626319, 6651114.376810925, 75.02946832054415], + [510790.3203969748, 6651120.975936965, 74.76259566454415], + [510790.4430913418, 6651119.506379684, 74.82864050554414], + [510790.83670272736, 6651114.791945835, 75.06721117954415], + [510791.0080309581, 6651112.739882199, 75.16105690154416], + [510790.4785608828, 6651119.08154745, 74.95079362754416], + [510790.69110059395, 6651116.535878179, 75.06721117954415], + [510790.51386541646, 6651118.65869157, 75.02946832054415], + [510790.54852532095, 6651118.24355666, 75.06721117954415], + [510790.3483044428, 6651120.641678565, 74.97584799954417], + [510790.9784361769, 6651113.094350194, 75.31754819354417], + [510790.948420897, 6651113.453854661, 75.44517095254415], + [510790.37719728483, 6651120.295617964, 75.16105690154416], + [510790.9182568479, 6651113.815140994, 75.54426644654416], + [510790.4067920661, 6651119.94114997, 75.31754819354417], + [510790.8782450431, 6651114.294377658, 75.63343109854416], + [510790.436807346, 6651119.581645502, 75.44517095254415], + [510790.8389638178, 6651114.7648638915, 75.67620633954415], + [510790.466971395, 6651119.220359169, 75.54426644654416], + [510790.5069831999, 6651118.741122505, 75.63343109854416], + [510790.5462644252, 6651118.270636272, 75.67620633954415], + [510795.0084456514, 6651110.149023901, 68.64155541765334], + [510794.95647894987, 6651110.756406079, 68.64155541765334], + [510794.95647894987, 6651110.756406079, 68.77155541765335], + [510793.9164655865, 6651122.911989608, 68.64155541765334], + [510793.864498885, 6651123.519371784, 68.64155541765334], + [510793.9164655865, 6651122.911989608, 68.77155541765335], + [510795.0084456514, 6651110.149023901, 70.47035907665334], + [510794.95647894987, 6651110.756406079, 70.47035907665334], + [510793.91646538716, 6651122.911991938, 70.47035907765333], + [510793.864498885, 6651123.519371784, 70.47035907665334], + [510794.95490237436, 6651110.774832951, 70.88117438865333], + [510795.0066588658, 6651110.169907692, 70.93594976365333], + [510793.91685287433, 6651122.9074630225, 70.67418036165333], + [510794.9499722127, 6651110.832456242, 71.30229581665333], + [510793.8662856706, 6651123.498487995, 70.93594976365333], + [510795.00107134925, 6651110.235214085, 71.41322071565334], + [510793.92007034144, 6651122.869857553, 71.09075964965334], + [510794.9414341836, 6651110.932247965, 71.72838495165335], + [510793.8718731871, 6651123.433181599, 71.41322071565334], + [510793.9267771263, 6651122.791469249, 71.51508676965334], + [510794.9913949164, 6651110.348311373, 71.89612173565334], + [510794.92911392177, 6651111.076246088, 72.15329145565333], + [510794.98133127275, 6651110.465934342, 72.25782772065334], + [510793.88154962007, 6651123.320084312, 71.89612173565334], + [510793.9371903188, 6651122.669760783, 71.94139712065333], + [510794.91293761216, 6651111.265313352, 72.57025815765333], + [510794.96881188464, 6651110.612259835, 72.61558556665334], + [510793.89161326364, 6651123.202461343, 72.25782772065334], + [510793.9514363577, 6651122.503254349, 72.36320597965333], + [510794.9538352567, 6651110.787305329, 72.96604178165335], + [510793.90413265175, 6651123.05613585, 72.61558556665334], + [510794.8929479077, 6651111.498951239, 72.97220707465333], + [510793.96953241323, 6651122.291749264, 72.77355552265335], + [510794.93644380354, 6651110.990575083, 73.30578680865334], + [510793.91910927976, 6651122.881090356, 72.96604178165335], + [510794.8693125461, 6651111.775199239, 73.35208787665334], + [510793.9913738244, 6651122.036468796, 73.16533521665333], + [510794.91672532377, 6651111.221042917, 73.63145391865334], + [510794.8493649091, 6651112.008345443, 73.61849419165333], + [510793.93650073285, 6651122.677820602, 73.30578680865334], + [510794.0100786459, 6651121.817848509, 73.44281707665333], + [510794.8276947333, 6651112.261624526, 73.86620393165335], + [510794.8948125191, 6651111.477157826, 73.93982272665333], + [510793.95621921256, 6651122.447352768, 73.63145391865334], + [510794.0306205958, 6651121.5777560305, 73.70325774965333], + [510794.7964674358, 6651112.626606397, 74.16364640165334], + [510794.8708804599, 6651111.756873603, 74.22792107765333], + [510794.0528223931, 6651121.318263401, 73.94422739565333], + [510793.97813201725, 6651122.1912378585, 73.93982272665333], + [510794.0764769012, 6651121.041791618, 74.16364640165334], + [510794.76306937524, 6651113.016959954, 74.41985952465333], + [510794.8451420624, 6651112.057701698, 74.49311880265333], + [510794.00206407654, 6651121.911522082, 74.22792107765333], + [510794.72808829, 6651113.42581576, 74.63213733365333], + [510794.1098749616, 6651120.651438063, 74.41985952465333], + [510794.81784181466, 6651112.376784561, 74.73320724965333], + [510794.02780247387, 6651121.6106939865, 74.49311880265333], + [510794.6921303321, 6651113.846089169, 74.79925209065334], + [510794.1448560469, 6651120.242582257, 74.63213733365333], + [510794.7892481335, 6651112.710984959, 74.94645958465334], + [510794.6557886352, 6651114.270847687, 74.92140521265333], + [510794.05510272173, 6651121.291611123, 74.73320724965333], + [510794.18081400485, 6651119.822308846, 74.79925209065334], + [510794.6196160029, 6651114.693630189, 75.00007990565334], + [510794.5841038503, 6651115.108693064, 75.03782276465333], + [510794.2171557018, 6651119.3975503305, 74.92140521265333], + [510794.75964484905, 6651113.0569855105, 75.13166848665334], + [510794.4349215247, 6651116.852322794, 75.03782276465333], + [510794.2533283341, 6651118.974767827, 75.00007990565334], + [510794.08369640284, 6651120.957410725, 74.94645958465334], + [510794.28884048655, 6651118.559704953, 75.03782276465333], + [510794.7293223656, 6651113.411391997, 75.28815977865335], + [510794.11329968733, 6651120.6114101745, 75.13166848665334], + [510794.6985690438, 6651113.770834081, 75.41578253765334], + [510794.14362217084, 6651120.257003688, 75.28815977865335], + [510794.6676632947, 6651114.132057722, 75.51487803165334], + [510794.1743754926, 6651119.897561604, 75.41578253765334], + [510794.6266676447, 6651114.611211228, 75.60404268365333], + [510794.5864205384, 6651115.08161582, 75.64681792465333], + [510794.2052812416, 6651119.536337962, 75.51487803165334], + [510794.2462768916, 6651119.057184458, 75.60404268365333], + [510794.2865239979, 6651118.5867798645, 75.64681792465333], + [510801.89728471264, 6651124.224541166, 68.5737739278946], + [510801.951937106, 6651123.617394755, 68.5737739278946], + [510803.0456994135, 6651111.4665296525, 68.5737739278946], + [510803.10035180685, 6651110.859383242, 68.5737739278946], + [510801.951937106, 6651123.617394755, 68.70377392789462], + [510803.0456994135, 6651111.4665296525, 68.70377392789462], + [510801.89728471264, 6651124.224541166, 70.40257758689461], + [510801.95193689625, 6651123.617397084, 70.4025775878946], + [510803.0456994135, 6651111.4665296525, 70.40257758689461], + [510803.10035180685, 6651110.859383242, 70.40257758689461], + [510801.95234440913, 6651123.612869927, 70.6063988718946], + [510803.04404135904, 6651111.484949374, 70.8133928988946], + [510801.8991638411, 6651124.203665481, 70.8681682738946], + [510803.0984726784, 6651110.880258927, 70.8681682738946], + [510801.95572815824, 6651123.575279055, 71.0229781598946], + [510803.03885640175, 6651111.542550296, 71.2345143268946], + [510801.90504012606, 6651124.138384436, 71.34543922589461], + [510803.0925963934, 6651110.945539972, 71.34543922589461], + [510801.96278155665, 6651123.496921178, 71.44730527989461], + [510803.0298771186, 6651111.642303282, 71.6606034618946], + [510801.915216647, 6651124.02533105, 71.82834024589461], + [510803.0824198726, 6651111.058593357, 71.82834024589461], + [510801.97373291344, 6651123.375259956, 71.8736156308946], + [510803.016920133, 6651111.786245511, 72.0855099658946], + [510801.9258003898, 6651123.907753739, 72.19004623089461], + [510803.0718361297, 6651111.1761706695, 72.19004623089461], + [510801.9887152021, 6651123.208818156, 72.2954244898946], + [510802.9999078155, 6651111.975239386, 72.5024766678946], + [510801.9389667926, 6651123.761485045, 72.54780407689461], + [510803.0586697269, 6651111.322439362, 72.54780407689461], + [510802.0077464801, 6651122.99739517, 72.70577403289462], + [510801.95471742784, 6651123.586507498, 72.89826029189462], + [510803.04291909165, 6651111.497416909, 72.89826029189462], + [510802.97888502275, 6651112.20878658, 72.9044255848946], + [510802.0307166775, 6651122.742213795, 73.09755372689462], + [510801.97300768894, 6651123.383316647, 73.23800531889461], + [510803.02462883067, 6651111.70060776, 73.23800531889461], + [510802.9540281618, 6651112.484927348, 73.28430638689461], + [510802.05038818304, 6651122.52367837, 73.3750355868946], + [510801.9937452397, 6651123.152938274, 73.5636724288946], + [510802.93304961064, 6651112.717983052, 73.5507127018946], + [510803.0038912799, 6651111.930986134, 73.5636724288946], + [510802.0719917616, 6651122.283679088, 73.6354762598946], + [510802.9102594982, 6651112.971163821, 73.7984224418946], + [510802.0167905203, 6651122.89692278, 73.8720412368946], + [510802.0953409703, 6651122.024287186, 73.8764459058946], + [510802.98084599926, 6651112.187001626, 73.8720412368946], + [510802.12021796743, 6651121.747922719, 74.09586491189461], + [510802.87741834234, 6651113.336004017, 74.09586491189461], + [510802.04195941257, 6651122.617315581, 74.1601395878946], + [510802.95567710686, 6651112.466608825, 74.1601395878946], + [510802.15534207347, 6651121.357720688, 74.3520780348946], + [510802.8422942363, 6651113.726206049, 74.3520780348946], + [510802.06902799645, 6651122.316604258, 74.4253373128946], + [510802.9286085231, 6651112.767320149, 74.4253373128946], + [510802.1921310166, 6651120.949023586, 74.5643558438946], + [510802.80550529313, 6651114.1349031525, 74.5643558438946], + [510802.09773914865, 6651121.997645252, 74.6654257598946], + [510802.89989737084, 6651113.086279154, 74.6654257598946], + [510802.2299473184, 6651120.5289133135, 74.7314706008946], + [510802.7676889914, 6651114.555013424, 74.7314706008946], + [510802.26816719095, 6651120.104319678, 74.85362372289461], + [510802.7294691188, 6651114.979607061, 74.85362372289461], + [510802.12781058036, 6651121.663574581, 74.87867809489461], + [510802.8698259392, 6651113.420349826, 74.87867809489461], + [510802.30620926153, 6651119.681701284, 74.9322984158946], + [510802.6914270481, 6651115.402225453, 74.9322984158946], + [510802.3435567181, 6651119.2667995235, 74.9700412748946], + [510802.49718737236, 6651117.560080119, 74.9700412748946], + [510802.65407959156, 6651115.817127215, 74.9700412748946], + [510802.15894379246, 6651121.317708337, 75.06388699689461], + [510802.83869272703, 6651113.766216071, 75.06388699689461], + [510802.19083337265, 6651120.963439422, 75.22037828889462], + [510802.80680314684, 6651114.120484985, 75.22037828889462], + [510802.2231760573, 6651120.60413686, 75.34800104789461], + [510802.7744604622, 6651114.479787547, 75.34800104789461], + [510802.2556790467, 6651120.243053436, 75.44709654189461], + [510802.7419574728, 6651114.840870972, 75.44709654189461], + [510802.2987933934, 6651119.764085923, 75.5362611938946], + [510802.698843126, 6651115.319838485, 75.5362611938946], + [510802.341120511, 6651119.293863927, 75.5790364348946], + [510802.6565160085, 6651115.790060479, 75.5790364348946], + [510810.1574715679, 6651124.987029978, 68.49766535314345], + [510810.2148856826, 6651124.380138498, 68.49766535314345], + [510810.2148856826, 6651124.380138498, 68.62766535314343], + [510811.36391851935, 6651112.234375359, 68.49766535314345], + [510811.421332634, 6651111.627483879, 68.49766535314345], + [510811.36391851935, 6651112.234375359, 68.62766535314343], + [510810.1574715679, 6651124.987029978, 70.32646901214345], + [510810.2148854623, 6651124.380140827, 70.32646901314342], + [510810.2153135678, 6651124.375615571, 70.53029029714344], + [510811.36391851935, 6651112.234375359, 70.32646901214345], + [510810.1594456534, 6651124.966163059, 70.79205969914342], + [510811.421332634, 6651111.627483879, 70.32646901214345], + [510810.2188683061, 6651124.338040482, 70.94686958514345], + [510811.36217667925, 6651112.252787345, 70.73728432414343], + [510811.4193585485, 6651111.648350798, 70.79205969914342], + [510810.1656188817, 6651124.900909424, 71.26933065114343], + [510810.22627813026, 6651124.259715507, 71.37119670514343], + [510810.56908495084, 6651125.026017172, 68.49370265615114], + [510810.6266366848, 6651124.419138728, 68.49370265615114], + [510811.3567297131, 6651112.3103640815, 71.15840575214342], + [510810.6266366848, 6651124.419138728, 68.62370265615114], + [510811.4131853202, 6651111.713604433, 71.26933065114343], + [510810.1763096474, 6651124.787903508, 71.75223167114345], + [510810.2377828864, 6651124.138105368, 71.79750705614343], + [510811.7784237074, 6651112.273636458, 68.49370265615114], + [510811.8359754414, 6651111.666758015, 68.49370265615114], + [510811.34729668446, 6651112.410075184, 71.58449488714342], + [510811.7784237074, 6651112.273636458, 68.62370265615114], + [510810.18742821325, 6651124.670375564, 72.11393765614343], + [510811.40249455447, 6651111.826610349, 71.75223167114345], + [510810.2535222673, 6651123.971733454, 72.21931591514344], + [510811.3336849502, 6651112.553956972, 72.00940139114343], + [510810.20125994703, 6651124.524168288, 72.47169550214343], + [510811.3913759888, 6651111.944138291, 72.11393765614343], + [510810.2735152431, 6651123.760399242, 72.62966545814344], + [510810.217806501, 6651124.349264212, 72.82215171714343], + [510811.315812958, 6651112.742871491, 72.42636809314342], + [510811.3775442549, 6651112.090345569, 72.47169550214343], + [510810.2976461817, 6651123.505325014, 73.02144515214343], + [510810.23702101444, 6651124.1461586775, 73.16189674414345], + [510811.2937278312, 6651112.9763206225, 72.82831701014342], + [510811.36099770083, 6651112.265249644, 72.82215171714343], + [510810.56908495084, 6651125.026017172, 70.32250631515114], + [510810.626636464, 6651124.419141056, 70.32250631615113], + [510810.3183117374, 6651123.286881349, 73.29892701214342], + [510810.2588064852, 6651123.915877035, 73.48756385414343], + [510810.62706559565, 6651124.414615897, 70.52632760015113], + [510811.3417831874, 6651112.468355179, 73.16189674414345], + [510810.34100699855, 6651123.046982837, 73.55936768514343], + [510811.2676148913, 6651113.252345445, 73.20819781214342], + [510810.5710637681, 6651125.005150702, 70.78809700215113], + [510811.7784237074, 6651112.273636458, 70.32250631515114], + [510811.8359754414, 6651111.666758015, 70.32250631515114], + [510810.28301630117, 6651123.659969039, 73.79593266214343], + [510810.3655361008, 6651122.787699851, 73.80033733114344], + [510811.2455762418, 6651113.485303292, 73.47460412714342], + [510811.31999771675, 6651112.698636821, 73.48756385414343], + [510810.6306288545, 6651124.377041617, 70.94290688815114], + [510810.39167019434, 6651122.511451426, 74.01975633714343], + [510811.2216344883, 6651113.738377754, 73.72231386714343], + [510810.3094570402, 6651123.380479243, 74.08403101314344], + [510811.77667769225, 6651112.292048049, 70.73332162715114], + [510811.29578790074, 6651112.954544818, 73.79593266214343], + [510810.5772517934, 6651124.939898468, 71.26536795415115], + [510811.8339966241, 6651111.687624484, 70.78809700215113], + [510810.42856920895, 6651122.121413235, 74.27596946014343], + [510810.6380564398, 6651124.298718323, 71.36723400815114], + [510811.1871337872, 6651114.103064761, 74.01975633714343], + [510810.337893467, 6651123.079894183, 74.34922873814342], + [510811.2693471617, 6651113.234034614, 74.08403101314344], + [510810.46721718885, 6651121.712887738, 74.48824726914343], + [510811.7712176699, 6651112.349623549, 71.15444305515113], + [510811.1502347726, 6651114.493102952, 74.27596946014343], + [510810.36805546505, 6651122.761069104, 74.58931718514343], + [510811.240910735, 6651113.534619673, 74.34922873814342], + [510810.5879681845, 6651124.826894979, 71.74826897415115], + [510811.8278085988, 6651111.752876718, 71.26536795415115], + [510810.5069444423, 6651121.292953864, 74.65536202614342], + [510810.6495887723, 6651124.177110796, 71.79354435915116], + [510811.1115867927, 6651114.901628448, 74.48824726914343], + [510810.399646481, 6651122.427138704, 74.80256952014344], + [510810.54709566006, 6651120.868538506, 74.77751514814344], + [510811.2107487368, 6651113.853444751, 74.58931718514343], + [510811.07185953925, 6651115.321562323, 74.65536202614342], + [510810.58706009114, 6651120.446097565, 74.85618984114345], + [510811.7617620306, 6651112.449332511, 71.58053219015113], + [510810.62629480753, 6651120.031370016, 74.89393270014344], + [510810.4323529317, 6651122.0814176835, 74.98777842214344], + [510811.0317083214, 6651115.74597768, 74.77751514814344], + [510810.59911340097, 6651124.70936956, 72.10997495915115], + [510810.7876888007, 6651118.3253672365, 74.89393270014344], + [510810.9917438904, 6651116.168418622, 74.85618984114345], + [510811.17915772105, 6651114.1873751525, 74.80256952014344], + [510810.952509174, 6651116.583146171, 74.89393270014344], + [510811.8170922077, 6651111.865880206, 71.74826897415115], + [510810.4658539716, 6651121.72729752, 75.14426971414343], + [510810.66536587983, 6651124.010742455, 72.21535321815114], + [510811.14645127015, 6651114.533096174, 74.98777842214344], + [510810.49983101257, 6651121.368145825, 75.27189247314342], + [510811.7481176696, 6651112.5932112085, 72.00543869415114], + [510810.61297828896, 6651124.563165423, 72.46773280515114], + [510811.11295023025, 6651114.887216336, 75.14426971414343], + [510810.53397645894, 6651121.007214014, 75.37098796714345], + [510811.8059469912, 6651111.983405625, 72.10997495915115], + [510810.57926948083, 6651120.528447612, 75.46015261914343], + [510811.0789731894, 6651115.246368032, 75.27189247314342], + [510810.6237354928, 6651120.058423055, 75.50292786014343], + [510810.68540677807, 6651123.799412782, 72.62570276115115], + [510811.0448277431, 6651115.607299843, 75.37098796714345], + [510810.9995347212, 6651116.086066245, 75.46015261914343], + [510810.9550687091, 6651116.556090802, 75.50292786014343], + [510810.6295645044, 6651124.388265104, 72.81818902015114], + [510811.73020283884, 6651112.78212167, 72.42240539615113], + [510811.79208210326, 6651112.129609763, 72.46773280515114], + [510810.7095955576, 6651123.544344032, 73.01748245515115], + [510810.6488250742, 6651124.185163932, 73.15793404715114], + [510811.70806477504, 6651113.015565787, 72.82435431315113], + [510811.7754958878, 6651112.304510082, 72.81818902015114], + [510810.7303106478, 6651123.3259050585, 73.29496431515113], + [510810.6706627638, 6651123.954887237, 73.48360115715114], + [510811.756235318, 6651112.507611254, 73.15793404715114], + [510810.7530603086, 6651123.0860117, 73.55540498815114], + [510811.6818892434, 6651113.291584682, 73.20423511515114], + [510810.69493060984, 6651123.698984737, 73.79196996515114], + [510810.77764820616, 6651122.826734283, 73.79637463415114], + [510811.65979776817, 6651113.524537525, 73.47064143015113], + [510811.73439762834, 6651112.73788795, 73.48360115715114], + [510810.803844942, 6651122.550491793, 74.01579364015114], + [510810.72143472626, 6651123.419500943, 74.08006831615114], + [510811.6357986272, 6651113.777606551, 73.71835117015114], + [510811.71012978244, 6651112.99379045, 73.79196996515114], + [510810.84083240206, 6651122.160461978, 74.27200676315114], + [510810.7499393139, 6651123.11892234, 74.34526604115113], + [510811.60121522925, 6651114.142285723, 74.01579364015114], + [510811.68362566596, 6651113.273274244, 74.08006831615114], + [510810.8795730196, 6651121.751945255, 74.48428457215114], + [510811.5642277693, 6651114.532315538, 74.27200676315114], + [510810.7801736092, 6651122.800104109, 74.58535448815114], + [510811.65512107825, 6651113.573852846, 74.34526604115113], + [510810.9193954977, 6651121.3320204, 74.65139932915113], + [510811.52548715175, 6651114.94083226, 74.48428457215114], + [510810.8118403474, 6651122.466180881, 74.79860682315116], + [510810.9596429564, 6651120.907614159, 74.77355245115115], + [510811.6248867831, 6651113.892671078, 74.58535448815114], + [510811.48566467356, 6651115.360757115, 74.65139932915113], + [510810.9997031806, 6651120.485182291, 74.85222714415114], + [510811.03903194104, 6651120.07046365, 74.88997000315113], + [510810.84462519427, 6651122.120467287, 74.98381572515115], + [510811.4454172149, 6651115.785163356, 74.77355245115115], + [510811.2008127892, 6651118.3644975135, 74.88997000315113], + [510811.40535699076, 6651116.207595225, 74.85222714415114], + [510811.5932200448, 6651114.226594306, 74.79860682315116], + [510811.36602823023, 6651116.622313866, 74.88997000315113], + [510810.8782065349, 6651121.7663547285, 75.14030701715116], + [510811.56043519796, 6651114.5723079005, 74.98381572515115], + [510810.91226501734, 6651121.407210747, 75.26792977615115], + [510810.9464923089, 6651121.046286688, 75.36702527015115], + [510811.52685385733, 6651114.926420458, 75.14030701715116], + [510810.9918938964, 6651120.56753057, 75.45618992215115], + [510811.4927953749, 6651115.285564439, 75.26792977615115], + [510811.0364664917, 6651120.097516108, 75.49896516315114], + [510811.4585680833, 6651115.646488498, 75.36702527015115], + [510811.41316649574, 6651116.125244617, 75.45618992215115], + [510811.3685939005, 6651116.595259079, 75.49896516315114], + [510818.91601005243, 6651125.836948804, 68.40985667120633], + [510818.976352508, 6651125.230341487, 68.40985667120633], + [510818.976352508, 6651125.230341487, 68.53985667120634], + [510820.1839904423, 6651113.09026532, 68.40985667120633], + [510820.24433289777, 6651112.483658005, 68.40985667120633], + [510820.1839904423, 6651113.09026532, 68.53985667120634], + [510818.91601005243, 6651125.836948804, 70.23866033020633], + [510818.97635227646, 6651125.230343814, 70.23866033120632], + [510818.97680221696, 6651125.225820677, 70.44248161520632], + [510818.91808482393, 6651125.816091655, 70.70425101720632], + [510818.9805382606, 6651125.188263183, 70.85906090320633], + [510820.1839904423, 6651113.09026532, 70.23866033020633], + [510818.92457291065, 6651125.750868574, 71.18152196920633], + [510820.24433289777, 6651112.483658005, 70.23866033020633], + [510818.98832601437, 6651125.109974882, 71.28338802320633], + [510820.18215976167, 6651113.108668686, 70.64947564220633], + [510820.2422581264, 6651112.5045151515, 70.70425101720632], + [510818.93580894655, 6651125.637915569, 71.66442298920633], + [510819.00041755725, 6651124.988421684, 71.70969837420633], + [510820.17643497925, 6651113.166218462, 71.07059707020632], + [510818.94749460195, 6651125.520442656, 72.02612897420633], + [510820.23577003967, 6651112.5697382325, 71.18152196920633], + [510819.0169597072, 6651124.822127669, 72.13150723320632], + [510820.1665208299, 6651113.2658828795, 71.49668620520632], + [510818.96203180746, 6651125.374303838, 72.38388682020633], + [510820.22453400376, 6651112.682691237, 71.66442298920633], + [510819.0379724018, 6651124.610892409, 72.54185677620634], + [510818.9794222994, 6651125.199481656, 72.73434303520634], + [510820.1522148448, 6651113.409697298, 71.92159270920632], + [510820.21284834837, 6651112.800164151, 72.02612897420633], + [510819.0633341111, 6651124.355937613, 72.93363647020632], + [510818.99961682694, 6651124.996471221, 73.07408806220633], + [510820.1334313121, 6651113.598523363, 72.33855941120632], + [510820.19831114286, 6651112.946302971, 72.38388682020633], + [510819.0850536898, 6651124.137596229, 73.21111833020632], + [510819.02251344064, 6651124.766297404, 73.39975517220633], + [510820.11021975894, 6651113.831863187, 72.74050832820632], + [510819.10890649655, 6651123.897810046, 73.47155900320632], + [510820.1809206509, 6651113.1211251505, 72.73434303520634], + [510819.0479580504, 6651124.51050923, 73.70812398020632], + [510819.1346866775, 6651123.6386484625, 73.71252864920632], + [510820.08277495846, 6651114.107758766, 73.12038913020633], + [510820.16072612326, 6651113.324135586, 73.07408806220633], + [510819.1621537104, 6651123.362529384, 73.93194765520633], + [510819.07574736886, 6651124.231150298, 73.99622233120633], + [510820.05961225304, 6651114.340607535, 73.38679544520632], + [510820.1378295097, 6651113.554309403, 73.39975517220633], + [510819.2009347166, 6651122.9726738185, 74.18816077820632], + [510819.10563416284, 6651123.930705981, 74.26142005620632], + [510820.034449378, 6651114.593563502, 73.63450518520634], + [510820.1123848999, 6651113.810097576, 73.70812398020632], + [510819.24155389227, 6651122.564339605, 74.40043858720632], + [510819.137334539, 6651123.612030185, 74.50150850320632], + [510819.99818900827, 6651114.958079752, 73.93194765520633], + [510819.2833073886, 6651122.144602355, 74.56755334420632], + [510820.08459558134, 6651114.089456508, 73.99622233120633], + [510819.17053681816, 6651123.278256139, 74.71476083820633], + [510819.95940800203, 6651115.347935317, 74.18816077820632], + [510819.3255064731, 6651121.720385721, 74.68970646620633], + [510820.0547087875, 6651114.389900825, 74.26142005620632], + [510819.3675092439, 6651121.2981425775, 74.76838115920633], + [510819.2049114239, 6651122.932696994, 74.89996974020633], + [510819.9187888264, 6651115.75626953, 74.40043858720632], + [510819.4087450819, 6651120.883609215, 74.80612401820632], + [510819.87703533005, 6651116.176006781, 74.56755334420632], + [510819.57837078994, 6651119.178405232, 74.80612401820632], + [510819.24012114585, 6651122.57874264, 75.05646103220633], + [510820.02300841134, 6651114.7085766215, 74.50150850320632], + [510819.8348362456, 6651116.600223415, 74.68970646620633], + [510819.79283347464, 6651117.022466558, 74.76838115920633], + [510819.7515976367, 6651117.43699992, 74.80612401820632], + [510819.2758311466, 6651122.219759109, 75.18408379120633], + [510819.98980613204, 6651115.0423506675, 74.71476083820633], + [510819.31171814207, 6651121.858996295, 75.28317928520633], + [510819.9554315264, 6651115.387909813, 74.89996974020633], + [510819.3593212824, 6651121.380454067, 75.37234393720632], + [510819.4060552323, 6651120.910649587, 75.41511917820633], + [510819.92022180447, 6651115.741864166, 75.05646103220633], + [510819.88451180374, 6651116.100847697, 75.18408379120633], + [510819.84862480813, 6651116.461610511, 75.28317928520633], + [510819.8010216678, 6651116.940152741, 75.37234393720632], + [510819.75428771804, 6651117.409957219, 75.41511917820633], + [510827.25910479826, 6651126.686262168, 68.31939778668155], + [510827.32223669457, 6651126.079938812, 68.31939778668155], + [510827.32223669457, 6651126.079938812, 68.44939778668154], + [510828.58569991105, 6651113.945545568, 68.31939778668155], + [510828.64883180737, 6651113.339222212, 68.31939778668155], + [510828.58569991105, 6651113.945545568, 68.44939778668154], + [510827.25910479826, 6651126.686262168, 70.14820144568156], + [510827.3222364523, 6651126.079941139, 70.14820144668154], + [510827.32270719216, 6651126.075420119, 70.35202273068155], + [510827.26127547974, 6651126.665414784, 70.61379213268154], + [510827.32661594136, 6651126.037880206, 70.76860201868156], + [510827.2680634902, 6651126.600222234, 71.09106308468155], + [510827.3347636982, 6651125.959628552, 71.19292913868155], + [510828.58569991105, 6651113.945545568, 70.14820144568156], + [510828.64883180737, 6651113.339222212, 70.14820144568156], + [510827.2798189326, 6651126.487322106, 71.57396410468156], + [510827.347414195, 6651125.838132255, 71.61923948968155], + [510828.5837846038, 6651113.963940319, 70.55901675768155], + [510827.2920447788, 6651126.369904182, 71.93567008968155], + [510828.6466611259, 6651113.360069597, 70.61379213268154], + [510827.36472103617, 6651125.671916084, 72.04104834868156], + [510828.5777951828, 6651114.021463157, 70.98013818568154], + [510827.30725399335, 6651126.223833772, 72.29342793568155], + [510828.63987311535, 6651113.425262147, 71.09106308468155], + [510827.3867050812, 6651125.460779707, 72.45139789168155], + [510827.3254483928, 6651126.049093428, 72.64388415068154], + [510828.5674227337, 6651114.121080917, 71.40622732068155], + [510828.62811767304, 6651113.538162275, 71.57396410468156], + [510827.4132391822, 6651125.20594426, 72.84317758568154], + [510827.3465764494, 6651125.846178025, 72.98362917768156], + [510828.5524554282, 6651114.264828015, 71.83113382468156], + [510827.4359627881, 6651124.987705083, 73.12065944568154], + [510828.61589182675, 6651113.655580199, 71.93567008968155], + [510827.37053150113, 6651125.616111954, 73.30929628768155], + [510828.53280359216, 6651114.453565687, 72.24810052668154], + [510827.46091823484, 6651124.748031147, 73.38110011868154], + [510828.6006826123, 6651113.801650608, 72.29342793568155], + [510827.3971523348, 6651125.360443519, 73.61766509568155], + [510827.4878901519, 6651124.48899088, 73.62206976468156], + [510828.5085190422, 6651114.686796282, 72.65004944368154], + [510828.5824882128, 6651113.976390952, 72.64388415068154], + [510827.42622626555, 6651125.081215358, 73.90576344668155], + [510827.5166268989, 6651124.213001057, 73.84148877068155], + [510828.4798055555, 6651114.962562713, 73.02993024568154], + [510828.5613601561, 6651114.179306355, 72.98362917768156], + [510827.4574946314, 6651124.780911683, 74.17096117168154], + [510827.5572006284, 6651123.8233279865, 74.09770189368155], + [510828.45557211153, 6651115.195302483, 73.29633656068155], + [510828.5374051045, 6651114.409372427, 73.30929628768155], + [510827.4906604157, 6651124.462385063, 74.41104961868155], + [510827.59969750006, 6651123.41518492, 74.30997970268155], + [510828.42924603634, 6651115.448140036, 73.54404630068154], + [510827.64338112855, 6651122.995644155, 74.47709445968155], + [510828.5107842709, 6651114.665040862, 73.61766509568155], + [510827.52539753134, 6651124.12876726, 74.62430195368155], + [510828.3913094644, 6651115.812485652, 73.84148877068155], + [510827.68753094313, 6651122.571626102, 74.59924758168154], + [510827.5613611663, 6651123.783369876, 74.80951085568155], + [510828.4817103401, 6651114.944269022, 73.90576344668155], + [510827.7314753693, 6651122.149580615, 74.67792227468156], + [510828.35073573486, 6651116.202158721, 74.09770189368155], + [510827.7746174096, 6651121.7352413, 74.71566513368155], + [510827.5981985223, 6651123.429581213, 74.96600214768155], + [510828.30823886313, 6651116.610301789, 74.30997970268155], + [510828.4504419742, 6651115.244572698, 74.17096117168154], + [510827.9520843777, 6651120.030835545, 74.71566513368155], + [510827.6355592835, 6651123.070765727, 75.09362490668154], + [510828.26455523475, 6651117.029842554, 74.47709445968155], + [510828.22040542006, 6651117.453860608, 74.59924758168154], + [510828.41727618984, 6651115.563099318, 74.41104961868155], + [510828.1333189536, 6651118.290245407, 74.71566513368155], + [510828.176460994, 6651117.875906092, 74.67792227468156], + [510827.6731052213, 6651122.710171792, 75.19272040068157], + [510827.7229089042, 6651122.231853574, 75.28188505268155], + [510828.38253907434, 6651115.89671712, 74.62430195368155], + [510827.7718032168, 6651121.762269015, 75.32466029368155], + [510828.34657543927, 6651116.242114503, 74.80951085568155], + [510828.3097380833, 6651116.595903168, 74.96600214768155], + [510828.27237732214, 6651116.954718653, 75.09362490668154], + [510828.2348313843, 6651117.3153125895, 75.19272040068157], + [510828.13613338885, 6651118.263215365, 75.32466029368155], + [510828.1850277013, 6651117.793630808, 75.28188505268155], + [510830.15970154497, 6651126.99062476, 68.28638856520544], + [510830.2238032305, 6651126.384403165, 68.28638856520544], + [510830.2238032305, 6651126.384403165, 68.41638856520542], + [510831.50667490816, 6651114.2520464705, 68.28638856520544], + [510831.5707765937, 6651113.645824876, 68.28638856520544], + [510831.50667490816, 6651114.2520464705, 68.41638856520542], + [510830.15970154497, 6651126.99062476, 70.11519222420543], + [510830.22380298446, 6651126.384405491, 70.11519222520542], + [510830.2242809555, 6651126.37988523, 70.31901350920542], + [510830.161905571, 6651126.969780874, 70.58078291120542], + [510830.2282497482, 6651126.342351617, 70.73559279720543], + [510830.16879785416, 6651126.904599266, 71.05805386320544], + [510830.2365226654, 6651126.2641130965, 71.15991991720543], + [510830.1807338756, 6651126.791718086, 71.54095488320543], + [510831.50667490816, 6651114.2520464705, 70.11519222420543], + [510831.5707765937, 6651113.645824876, 70.11519222420543], + [510830.2493674905, 6651126.14263719, 71.58623026820543], + [510830.19314752705, 6651126.67431987, 71.90266086820543], + [510831.5047301793, 6651114.270438133, 70.52600753620543], + [510830.26694018755, 6651125.976448917, 72.00803912720542], + [510831.56857256766, 6651113.666668761, 70.58078291120542], + [510830.20859037514, 6651126.528273975, 72.26041871420543], + [510831.4986487529, 6651114.327951317, 70.94712896420543], + [510830.2892619365, 6651125.765347974, 72.41838867020543], + [510831.56168028445, 6651113.73185037, 71.05805386320544], + [510830.22706426453, 6651126.353562958, 72.61087492920542], + [510831.4881169693, 6651114.427552359, 71.37321809920542], + [510830.3162036363, 6651125.510555296, 72.81016836420542], + [510830.2485168761, 6651126.150681609, 72.95061995620543], + [510831.549744263, 6651113.84473155, 71.54095488320543], + [510831.47291974624, 6651114.571275331, 71.79812460320542], + [510830.33927630686, 6651125.292352748, 73.08765022420542], + [510830.2728399089, 6651125.9206541525, 73.27628706620543], + [510831.53733061155, 6651113.962129766, 71.90266086820543], + [510830.364615102, 6651125.052719036, 73.34809089720542], + [510831.45296603214, 6651114.759981328, 72.21509130520543], + [510830.2998696737, 6651125.665028627, 73.58465587420542], + [510831.5218877635, 6651114.108175661, 72.26041871420543], + [510830.39200134337, 6651124.793722245, 73.58906054320542], + [510831.42830843956, 6651114.99317278, 72.61704022220542], + [510830.32939021837, 6651125.385847329, 73.87275422520543], + [510831.5034138741, 6651114.282886677, 72.61087492920542], + [510830.4211795246, 6651124.517778742, 73.80847954920543], + [510830.36113890755, 6651125.085594055, 74.13795195020542], + [510831.39915387577, 6651115.268892925, 72.99692102420542], + [510830.46237652027, 6651124.128171072, 74.06469267220542], + [510831.48196126265, 6651114.485768025, 72.95061995620543], + [510831.37454817403, 6651115.501593635, 73.26332733920542], + [510830.3948141621, 6651124.767120893, 74.37804039720542], + [510830.50552619994, 6651123.720096505, 74.27697048120544], + [510831.45763822977, 6651114.7157954825, 73.27628706620543], + [510831.34781769564, 6651115.754388754, 73.51103707920542], + [510830.54988086637, 6651123.300626152, 74.44408523820542], + [510830.4300848855, 6651124.433559084, 74.59129273220543], + [510831.43060846505, 6651114.971421009, 73.58465587420542], + [510830.59470888047, 6651122.876679264, 74.56623836020543], + [510831.3092983679, 6651116.118673219, 73.80847954920543], + [510830.46660096943, 6651124.088219669, 74.77650163420545], + [510830.63932835095, 6651122.454704611, 74.64491305320543], + [510831.4010879203, 6651115.250602305, 73.87275422520543], + [510830.6831331099, 6651122.040434836, 74.68265591220542], + [510831.26810137235, 6651116.508280889, 74.06469267220542], + [510830.5040041958, 6651123.734490382, 74.93299292620543], + [510831.2249516927, 6651116.916355457, 74.27697048120544], + [510830.8633262046, 6651120.3363151355, 74.68265591220542], + [510831.36933923105, 6651115.550855581, 74.13795195020542], + [510830.5419388675, 6651123.375735118, 75.06061568520542], + [510831.1805970262, 6651117.33582581, 74.44408523820542], + [510830.58006156044, 6651123.015201701, 75.15971117920543], + [510831.1357690121, 6651117.759772698, 74.56623836020543], + [510831.0473447827, 6651118.596017126, 74.68265591220542], + [510831.09114954167, 6651118.181747352, 74.64491305320543], + [510831.3356639766, 6651115.869328741, 74.37804039720542], + [510830.6306302937, 6651122.53696376, 75.24887583120542], + [510831.30039325304, 6651116.202890552, 74.59129273220543], + [510830.68027568725, 6651122.067458014, 75.29165107220543], + [510831.2638771692, 6651116.548229965, 74.77650163420545], + [510831.22647394286, 6651116.901959253, 74.93299292620543], + [510831.1885392712, 6651117.260714518, 75.06061568520542], + [510831.1504165782, 6651117.621247934, 75.15971117920543], + [510831.05020245136, 6651118.56899162, 75.29165107220543], + [510831.0998478449, 6651118.099485875, 75.24887583120542], + [510835.9188697986, 6651127.608849202, 68.21846013508599], + [510835.9848970118, 6651127.002834307, 68.21846013508599], + [510835.9848970118, 6651127.002834307, 68.34846013508599], + [510837.30630441307, 6651114.874614272, 68.21846013508599], + [510835.9188697986, 6651127.608849202, 70.04726379408599], + [510837.37233162613, 6651114.268599376, 68.21846013508599], + [510837.30630441307, 6651114.874614272, 68.34846013508599], + [510835.9848967584, 6651127.002836633, 70.04726379508598], + [510835.98538908706, 6651126.998317912, 70.25108507908598], + [510835.9211400306, 6651127.588012425, 70.51285448108598], + [510835.9894770969, 6651126.960797097, 70.66766436708599], + [510835.92823934864, 6651127.522853041, 70.990125433086], + [510835.99799852126, 6651126.882585252, 71.09199148708599], + [510835.9405339119, 6651127.410010348, 71.47302645308599], + [510836.0112291874, 6651126.761150765, 71.51830183808599], + [510837.30630441307, 6651114.874614272, 70.04726379408599], + [510835.9533204526, 6651127.29265216, 71.834732438086], + [510837.37233162613, 6651114.268599376, 70.04726379408599], + [510836.02932974446, 6651126.595019154, 71.94011069708598], + [510837.3043012672, 6651114.892999666, 70.45807910608599], + [510835.9692271829, 6651127.1466560615, 72.192490284086], + [510837.3700613941, 6651114.289436154, 70.51285448108598], + [510836.0523220085, 6651126.38399019, 72.350460240086], + [510835.98825600295, 6651126.972004614, 72.54294649908599], + [510837.2980371629, 6651114.950493239, 70.87920053408598], + [510837.36296207603, 6651114.354595538, 70.990125433086], + [510836.0800730003, 6651126.129284386, 72.74223993408599], + [510836.01035302173, 6651126.769192442, 72.88269152608599], + [510837.28718901885, 6651115.050060321, 71.305289669086], + [510836.1038387426, 6651125.911156236, 73.01972179408598], + [510837.35066751274, 6651114.46743823, 71.47302645308599], + [510836.0354066855, 6651126.539243415, 73.20835863608599], + [510837.2715352918, 6651115.193734289, 71.73019617308599], + [510836.1299386808, 6651125.67160423, 73.28016246708599], + [510837.33788097213, 6651114.584796419, 71.834732438086], + [510836.06324838765, 6651126.283705046, 73.516727444086], + [510836.1581475676, 6651125.412695746, 73.52113211308598], + [510837.2509821952, 6651115.382375944, 72.147162875086], + [510837.3219742419, 6651114.730792518, 72.192490284086], + [510836.09365568944, 6651126.00461894, 73.80482579508599], + [510836.1882022218, 6651125.136846331, 73.74055111908599], + [510837.22558392194, 6651115.615487886, 72.54911179208598], + [510837.30294542183, 6651114.9054439645, 72.54294649908599], + [510836.1263580662, 6651125.70446804, 74.07002352008598], + [510836.23063671927, 6651124.747371501, 73.99676424208599], + [510837.19555359473, 6651115.8911140235, 72.92899259408598], + [510836.1610448796, 6651125.386103465, 74.31011196708599], + [510837.280848403, 6651115.108256138, 72.88269152608599], + [510836.27508255665, 6651124.339436072, 74.209042051086], + [510837.17020877113, 6651116.12373539, 73.19539890908598], + [510836.19737508777, 6651125.052655388, 74.523364302086], + [510836.3207695772, 6651123.920108741, 74.376156808086], + [510837.2557947393, 6651115.338205164, 73.20835863608599], + [510837.14267534553, 6651116.376444316, 73.44310864908599], + [510836.3669441639, 6651123.496306403, 74.498309930086], + [510836.23498806515, 6651124.707433719, 74.70857320408601], + [510837.2279530372, 6651115.593743532, 73.516727444086], + [510836.4129039427, 6651123.074475626, 74.57698462308599], + [510837.1029989495, 6651116.740604575, 73.74055111908599], + [510836.45802453713, 6651122.660347102, 74.61472748208598], + [510836.27351483365, 6651124.353825041, 74.86506449608599], + [510837.1975457353, 6651115.872829639, 73.80482579508599], + [510837.060564452, 6651117.130079404, 73.99676424208599], + [510836.3125890114, 6651123.9951920975, 74.99268725508598], + [510836.6436303878, 6651120.95680844, 74.61472748208598], + [510837.0161186146, 6651117.538014834, 74.209042051086], + [510836.3518568583, 6651123.634781609, 75.091782749086], + [510837.1648433586, 6651116.1729805395, 74.07002352008598], + [510836.9704315941, 6651117.957342164, 74.376156808086], + [510836.83317663416, 6651119.2171038035, 74.61472748208598], + [510836.9242570073, 6651118.381144502, 74.498309930086], + [510836.4039446076, 6651123.156706729, 75.18094740108599], + [510836.87829722866, 6651118.802975278, 74.57698462308599], + [510837.1301565452, 6651116.491345114, 74.31011196708599], + [510836.4550812815, 6651122.687361067, 75.223722642086], + [510837.0938263371, 6651116.824793192, 74.523364302086], + [510837.0562133596, 6651117.170014859, 74.70857320408601], + [510837.0176865911, 6651117.523623538, 74.86506449608599], + [510836.97861241334, 6651117.882256482, 74.99268725508598], + [510836.83612014324, 6651119.190087512, 75.223722642086], + [510836.9393445665, 6651118.24266697, 75.091782749086], + [510836.8872568171, 6651118.72074185, 75.18094740108599], + [510843.9331460998, 6651128.499966287, 68.11864080924303], + [510844.00185281615, 6651127.894249328, 68.11864080924303], + [510844.00185281615, 6651127.894249328, 68.24864080924304], + [510843.9331460998, 6651128.499966287, 69.94744446824303], + [510844.0018525525, 6651127.894251651, 69.94744446924302], + [510844.00236486073, 6651127.889735154, 70.15126575324302], + [510845.376885311, 6651115.771991932, 68.11864080924303], + [510843.9355084619, 6651128.479139752, 70.41303515524302], + [510845.4455920274, 6651115.166274973, 68.11864080924303], + [510845.376885311, 6651115.771991932, 68.24864080924304], + [510844.0066187695, 6651127.852232785, 70.56784504124303], + [510843.9428958831, 6651128.414012403, 70.89030610724303], + [510844.01548600866, 6651127.7740593925, 70.99217216124303], + [510843.9556893819, 6651128.301225187, 71.37320712724303], + [510844.029253599, 6651127.652684605, 71.41848251224303], + [510843.9689948234, 6651128.183924696, 71.73491311224304], + [510844.0480887093, 6651127.486634672, 71.84029137124303], + [510845.376885311, 6651115.771991932, 69.94744446824303], + [510843.9855470775, 6651128.038000376, 72.09267095824303], + [510845.4455920274, 6651115.166274973, 69.94744446824303], + [510844.0720140408, 6651127.275709456, 72.25064091424305], + [510845.3748008738, 6651115.790368287, 70.35825978024303], + [510844.0053481213, 6651127.863434792, 72.44312717324304], + [510845.4432296652, 6651115.187101508, 70.41303515524302], + [510844.1008912178, 6651127.021128873, 72.64242060824303], + [510844.0283418769, 6651127.660722328, 72.78287220024303], + [510845.36828256096, 6651115.847833594, 70.77938120824302], + [510845.4358422441, 6651115.252228856, 70.89030610724303], + [510844.1256214168, 6651126.803107962, 72.91990246824302], + [510844.0544122635, 6651127.430886352, 73.10853931024303], + [510845.35699417966, 6651115.947351726, 71.20547034324305], + [510844.15278053755, 6651126.563673728, 73.18034314124303], + [510845.4230487452, 6651115.365016072, 71.37320712724303], + [510844.08338383207, 6651127.1754736155, 73.41690811824303], + [510845.34070519614, 6651116.090955059, 71.63037684724303], + [510844.1821341918, 6651126.3048925325, 73.42131278724302], + [510845.4097433037, 6651115.482316563, 71.73491311224304], + [510844.11502511706, 6651126.896524716, 73.70500646924303], + [510844.21340851806, 6651126.029178733, 73.64073179324303], + [510845.3193180178, 6651116.27950397, 72.04734354924302], + [510844.1490546151, 6651126.596521381, 73.97020419424302], + [510845.3931910496, 6651115.628240884, 72.09267095824303], + [510844.2575650838, 6651125.639895384, 73.89694491624303], + [510845.2928890369, 6651116.512501308, 72.44929246624302], + [510844.1851490819, 6651126.278313325, 74.21029264124303], + [510845.3733900059, 6651115.802806468, 72.44312717324304], + [510844.30381461343, 6651125.232160509, 74.10922272524303], + [510845.2616400249, 6651116.787991937, 72.82917326824304], + [510844.2229536353, 6651125.945029182, 74.42354497624304], + [510844.3513556956, 6651124.813039334, 74.27633748224304], + [510845.3503962502, 6651116.005518931, 72.78287220024303], + [510845.2352666627, 6651117.02049894, 73.09557958324302], + [510844.3994041303, 6651124.3894453505, 74.39849060424302], + [510844.2620930152, 6651125.599977236, 74.60875387824304], + [510845.3243258637, 6651116.235354909, 73.10853931024303], + [510844.4472290397, 6651123.96782196, 74.47716529724303], + [510845.206615881, 6651117.273083625, 73.34328932324304], + [510844.3021832694, 6651125.246542403, 74.76524517024305], + [510844.4941807091, 6651123.553897034, 74.51490815624302], + [510845.295354295, 6651116.490767644, 73.41690811824303], + [510845.16532934527, 6651117.637064851, 73.64073179324303], + [510844.3428431477, 6651124.888085776, 74.89286792924304], + [510844.6873187797, 6651121.851195889, 74.51490815624302], + [510844.3837045546, 6651124.527852477, 74.99196342324304], + [510845.1211727796, 6651118.026348202, 73.89694491624303], + [510845.26371301006, 6651116.769716543, 73.70500646924303], + [510845.07492324995, 6651118.434083077, 74.10922272524303], + [510844.43790611863, 6651124.050012634, 75.08112807524303], + [510845.02738216775, 6651118.85320425, 74.27633748224304], + [510845.22968351207, 6651117.069719879, 73.97020419424302], + [510844.8845571542, 6651120.112346551, 74.51490815624302], + [510844.49111801083, 6651123.580897719, 75.12390331624303], + [510844.9793337331, 6651119.276798235, 74.39849060424302], + [510844.9315088237, 6651119.698421625, 74.47716529724303], + [510845.19358904526, 6651117.3879279345, 74.21029264124303], + [510845.15578449174, 6651117.721212079, 74.42354497624304], + [510845.1166451119, 6651118.066264023, 74.60875387824304], + [510845.0765548578, 6651118.419698858, 74.76524517024305], + [510845.03589497943, 6651118.778155483, 74.89286792924304], + [510844.88762011623, 6651120.085343542, 75.12390331624303], + [510844.9950335726, 6651119.138388783, 74.99196342324304], + [510844.9408320085, 6651119.616228626, 75.08112807524303], + [510850.138625911, 6651129.214625044, 68.03711346873332], + [510850.20940737537, 6651128.609147025, 68.03711346873332], + [510850.20940737537, 6651128.609147025, 68.16711346873333], + [510850.138625911, 6651129.214625044, 69.86591712773333], + [510850.2094071038, 6651128.609149347, 69.86591712873332], + [510850.2099348822, 6651128.6046346305, 70.06973841273332], + [510850.1410596097, 6651129.193806725, 70.33150781473331], + [510851.6259619517, 6651116.491671551, 68.03711346873332], + [510850.21431724686, 6651128.567147057, 70.48631770073332], + [510851.69674341613, 6651115.8861935325, 68.03711346873332], + [510851.6259619517, 6651116.491671551, 68.16711346873333], + [510850.14867011004, 6651129.128705067, 70.80877876673333], + [510850.22345225146, 6651128.489004501, 70.91064482073332], + [510850.16184993624, 6651129.015962344, 71.29167978673333], + [510850.2376355841, 6651128.367677594, 71.33695517173334], + [510850.1755571644, 6651128.898708125, 71.65338577173333], + [510850.25703946134, 6651128.201693161, 71.75876403073332], + [510850.1926092496, 6651128.752841366, 72.01114361773332], + [510851.6259619517, 6651116.491671551, 69.86591712773333], + [510850.2816872699, 6651127.990851151, 72.16911357373333], + [510850.2130082287, 6651128.578344644, 72.36159983273332], + [510851.69674341613, 6651115.8861935325, 69.86591712773333], + [510851.62381457054, 6651116.510040656, 70.27673243973332], + [510850.3114364559, 6651127.736370994, 72.56089326773333], + [510850.2366963306, 6651128.375712145, 72.70134485973333], + [510851.6943097174, 6651115.907011851, 70.33150781473331], + [510850.33691343665, 6651127.518436086, 72.83837512773331], + [510851.61709942314, 6651116.567483295, 70.69785386773331], + [510850.2635539689, 6651128.145966833, 73.02701196973332], + [510851.68669921707, 6651115.972113509, 70.80877876673333], + [510850.36489268584, 6651127.2790963035, 73.09881580073332], + [510850.29340039677, 6651127.890654851, 73.33538077773332], + [510851.6054701646, 6651116.666962169, 71.12394300273331], + [510850.3951327372, 6651127.02041719, 73.33978544673332], + [510851.6735193908, 6651116.084856232, 71.29167978673333], + [510850.32599715865, 6651127.611815992, 73.62347912873332], + [510851.58868930006, 6651116.810508855, 71.54884950673332], + [510850.42735145945, 6651126.744812154, 73.55920445273333], + [510851.6598121627, 6651116.202110451, 71.65338577173333], + [510850.36105425115, 6651127.311930998, 73.88867685373332], + [510851.5666562896, 6651116.998983389, 71.96581620873332], + [510850.4728414283, 6651126.355682366, 73.81541757573332], + [510851.6427600775, 6651116.34797721, 72.01114361773332], + [510850.3982386684, 6651126.993848467, 74.12876530073332], + [510850.52048756246, 6651125.948108331, 74.02769538473332], + [510851.5394292285, 6651117.231888814, 72.36776512573331], + [510850.4371848122, 6651126.660695797, 74.34201763573334], + [510851.6223610983, 6651116.522473931, 72.36159983273332], + [510850.56946425047, 6651125.52915249, 74.19481014173331], + [510851.5072365849, 6651117.50727077, 72.74764592773332], + [510850.4775060903, 6651126.315779965, 74.52722653773333], + [510850.6189636116, 6651125.105725602, 74.31696326373333], + [510851.59867299645, 6651116.725106429, 72.70134485973333], + [510851.48006682197, 6651117.739686054, 73.01405224273331], + [510850.6682326976, 6651124.684268533, 74.39563795673332], + [510850.51880695653, 6651125.962484553, 74.68371782973334], + [510850.7166021744, 6651124.27050689, 74.43338081573332], + [510851.5718153582, 6651116.954851742, 73.02701196973332], + [510851.4505508679, 6651117.992171102, 73.26176198273332], + [510850.56069464784, 6651125.604169328, 74.81134058873333], + [510850.60278995323, 6651125.244078131, 74.91043608273333], + [510851.4080175959, 6651118.356008747, 73.55920445273333], + [510851.54196893034, 6651117.210163725, 73.33538077773332], + [510850.91557246685, 6651122.568477416, 74.43338081573332], + [510850.6586282508, 6651124.766426786, 74.99960073473333], + [510851.3625276271, 6651118.745138534, 73.81541757573332], + [510851.5093721684, 6651117.489002585, 73.62347912873332], + [510850.7134469913, 6651124.297496922, 75.04237597573332], + [510851.3148814928, 6651119.152712569, 74.02769538473332], + [510851.118766881, 6651120.830314009, 74.43338081573332], + [510851.2659048049, 6651119.57166841, 74.19481014173331], + [510851.1671363577, 6651120.416552367, 74.39563795673332], + [510851.2164054438, 6651119.995095297, 74.31696326373333], + [510851.4743150759, 6651117.788887577, 73.88867685373332], + [510851.43713065865, 6651118.106970107, 74.12876530073332], + [510851.39818451484, 6651118.440122779, 74.34201763573334], + [510851.35786323674, 6651118.78503861, 74.52722653773333], + [510851.31656237063, 6651119.138334022, 74.68371782973334], + [510851.12192233576, 6651120.803321653, 75.04237597573332], + [510851.2746746793, 6651119.4966492485, 74.81134058873333], + [510851.1767410762, 6651120.334391791, 74.99960073473333], + [510851.23257937375, 6651119.856740445, 74.91043608273333], + [510852.904369281, 6651129.540086604, 67.99958431955216], + [510852.9760754476, 6651128.934717401, 67.99958431955216], + [510852.9760754476, 6651128.934717401, 68.12958431955215], + [510852.904369281, 6651129.540086604, 69.82838797855216], + [510852.97607517237, 6651128.934719723, 69.82838797955215], + [510852.9766098459, 6651128.930205817, 70.03220926355215], + [510852.90683477395, 6651129.519272028, 70.29397866555215], + [510852.98104946245, 6651128.89272498, 70.44878855155216], + [510854.4111361548, 6651116.819419654, 67.99958431955216], + [510854.48284232145, 6651116.214050449, 67.99958431955216], + [510854.4111361548, 6651116.819419654, 68.12958431955215], + [510852.9145446993, 6651129.454182069, 70.77124961755217], + [510852.99030380853, 6651128.814596468, 70.87311567155216], + [510852.9278967093, 6651129.341459608, 71.25415063755216], + [510853.0046724348, 6651128.693291365, 71.29942602255215], + [510852.9417830112, 6651129.224226462, 71.61585662255216], + [510853.0243298079, 6651128.527336765, 71.72123488155215], + [510852.95905786793, 6651129.0783859175, 71.97361446855217], + [510853.04929962, 6651128.316532645, 72.13158442455216], + [510852.9797233431, 6651128.9039205555, 72.32407068355215], + [510854.4111361548, 6651116.819419654, 69.82838797855216], + [510854.48284232145, 6651116.214050449, 69.82838797855216], + [510853.0794374548, 6651128.062098224, 72.52336411855215], + [510853.00372091075, 6651128.701324473, 72.66381571055216], + [510854.4089607199, 6651116.837785458, 70.23920329055215], + [510854.4803768284, 6651116.2348650275, 70.29397866555215], + [510853.10524727154, 6651127.844202482, 72.80084597855215], + [510853.0309294221, 6651128.471620451, 72.98948282055215], + [510854.40215784457, 6651116.895217773, 70.66032471855216], + [510853.13359204686, 6651127.604905712, 73.06128665155215], + [510854.47266690305, 6651116.299954985, 70.77124961755217], + [510853.06116576924, 6651128.216354353, 73.29785162855217], + [510854.3903766592, 6651116.994678769, 71.08641385355216], + [510853.1642271598, 6651127.346273089, 73.30225629755215], + [510853.09418838134, 6651127.937565605, 73.58594997955215], + [510854.45931489306, 6651116.412677447, 71.25415063755216], + [510853.19686679344, 6651127.070717583, 73.52167530355216], + [510854.37337656633, 6651117.138199658, 71.51132035755215], + [510853.12970346614, 6651127.637734507, 73.85114770455215], + [510854.4454285913, 6651116.529910593, 71.61585662255216], + [510853.24295105156, 6651126.681657729, 73.77788842655215], + [510854.3510557126, 6651117.326640319, 71.92828705955216], + [510853.16737366753, 6651127.319709142, 74.09123615155215], + [510854.4281537344, 6651116.675751138, 71.97361446855217], + [510853.2912196437, 6651126.274156943, 73.99016623555217], + [510854.3234729521, 6651117.559503888, 72.33023597655215], + [510853.2068286109, 6651126.986616343, 74.30448848655216], + [510853.3408361722, 6651125.855276396, 74.15728099255216], + [510854.40748825925, 6651116.850216498, 72.32407068355215], + [510853.2476766537, 6651126.641762501, 74.48969738855217], + [510853.3909822022, 6651125.431925606, 74.27943411455216], + [510854.2908597379, 6651117.834836352, 72.71011677855215], + [510854.3834906916, 6651117.05281258, 72.66381571055216], + [510853.4408949487, 6651125.010544279, 74.35810880755216], + [510853.28951708204, 6651126.288530582, 74.64618868055216], + [510854.2633350242, 6651118.067209868, 72.97652309355215], + [510853.48989633325, 6651124.596856996, 74.39585166655215], + [510853.3319520019, 6651125.930279752, 74.77381143955215], + [510854.35628218023, 6651117.282516602, 72.98948282055215], + [510854.23343346815, 6651118.319649538, 73.22423283355215], + [510853.3745972482, 6651125.570253271, 74.87290693355216], + [510853.6914660104, 6651122.895133409, 74.39585166655215], + [510854.19034453365, 6651118.683421794, 73.52167530355216], + [510854.3260458331, 6651117.537782702, 73.29785162855217], + [510853.43116502755, 6651125.092687767, 74.96207158555215], + [510854.14426027547, 6651119.072481649, 73.77788842655215], + [510853.4866999302, 6651124.62384218, 75.00484682655217], + [510854.29302322096, 6651117.81657145, 73.58594997955215], + [510854.0959916833, 6651119.479982435, 73.99016623555217], + [510853.8973149939, 6651121.157282381, 74.39585166655215], + [510854.0463751548, 6651119.898862982, 74.15728099255216], + [510853.9463163784, 6651120.743595098, 74.35810880755216], + [510853.99622912495, 6651120.322213772, 74.27943411455216], + [510854.2575081362, 6651118.116402546, 73.85114770455215], + [510854.2198379348, 6651118.434427912, 74.09123615155215], + [510854.18038299144, 6651118.767520711, 74.30448848655216], + [510854.13953494874, 6651119.112374554, 74.48969738855217], + [510854.0976945203, 6651119.465606473, 74.64618868055216], + [510853.90051167214, 6651121.130294875, 75.00484682655217], + [510854.05525960046, 6651119.823857303, 74.77381143955215], + [510853.9560465748, 6651120.661449288, 74.96207158555215], + [510854.01261435414, 6651120.183883784, 74.87290693355216], + [510860.58979788143, 6651130.466976043, 67.89143172384466], + [510860.66407360387, 6651129.861916736, 67.89143172384466], + [510860.66407360387, 6651129.861916736, 68.02143172384466], + [510860.58979788143, 6651130.466976043, 69.72023538284466], + [510860.6640733189, 6651129.861919057, 69.72023538384465], + [510860.6646271521, 6651129.857407464, 69.92405666784465], + [510860.59235172416, 6651130.44617212, 70.18582606984465], + [510860.6692258602, 6651129.819945812, 70.34063595584466], + [510860.600337931, 6651130.381115482, 70.66309702184468], + [510860.6788118313, 6651129.741857296, 70.76496307584466], + [510862.15055902017, 6651117.752820987, 67.89143172384466], + [510862.15055902017, 6651117.752820987, 68.02143172384466], + [510862.22483474266, 6651117.147761682, 67.89143172384466], + [510860.61416840367, 6651130.268450725, 71.14599804184466], + [510860.6936953504, 6651129.62061429, 71.19127342684466], + [510860.6285523146, 6651130.151277592, 71.50770402684466], + [510860.714057136, 6651129.4547446435, 71.61308228584465], + [510860.64644620754, 6651130.005511706, 71.86546187284466], + [510860.7399217293, 6651129.244048439, 72.02343182884466], + [510860.66785222, 6651129.831135657, 72.21591808784466], + [510860.69270972896, 6651129.628643286, 72.55566311484466], + [510860.7711395389, 6651128.989744266, 72.41521152284466], + [510862.15055902017, 6651117.752820987, 69.72023538284466], + [510862.22483474266, 6651117.147761682, 69.72023538284466], + [510860.79787423793, 6651128.7719600685, 72.69269338284465], + [510860.7208932442, 6651129.399056852, 72.88133022484466], + [510862.14830562955, 6651117.77117739, 70.13105069484466], + [510862.22228089994, 6651117.168565603, 70.18582606984465], + [510860.82723473455, 6651128.532785799, 72.95313405584466], + [510860.75221309625, 6651129.143921429, 73.18969903284466], + [510862.1412589765, 6651117.828580305, 70.55217212284467], + [510860.8589676421, 6651128.2742855735, 73.19410370184465], + [510862.21429469314, 6651117.233622242, 70.66309702184468], + [510860.78641905775, 6651128.865275396, 73.47779738384466], + [510862.12905561813, 6651117.927990385, 70.97826125784465], + [510860.89277690125, 6651127.998871128, 73.41352270784466], + [510860.8232068085, 6651128.565597787, 73.74299510884465], + [510862.20046422037, 6651117.346286998, 71.14599804184466], + [510860.9405125666, 6651127.610010439, 73.66973583084466], + [510862.11144633504, 6651118.071437803, 71.40316776184466], + [510860.8622269034, 6651128.247735223, 73.98308355584466], + [510862.1860803095, 6651117.463460131, 71.50770402684466], + [510860.99051084055, 6651127.202718259, 73.88201363984467], + [510862.0883256243, 6651118.259781999, 71.82013446384467], + [510860.9030956957, 6651127.91481294, 74.19633589084467], + [510861.04190535337, 6651126.784052142, 74.04912839684465], + [510862.16818641656, 6651117.609226017, 71.86546187284466], + [510860.9454075084, 6651127.5701356325, 74.38154479284468], + [510862.0597544488, 6651118.492526362, 72.22208338084465], + [510861.09384834213, 6651126.360918071, 74.17128151884467], + [510862.14678040403, 6651117.783602066, 72.21591808784466], + [510860.98874726833, 6651127.217084538, 74.53803608484466], + [510861.1455496879, 6651125.939752456, 74.24995621184466], + [510862.02597255574, 6651118.767717878, 72.60196418284465], + [510861.19630701345, 6651125.526276947, 74.28769907084465], + [510861.032702823, 6651126.859017103, 74.66565884384465], + [510862.1219228952, 6651117.986094437, 72.55566311484466], + [510861.99746150716, 6651118.999972439, 72.86837049784465], + [510861.07687624125, 6651126.499174925, 74.76475433784466], + [510861.9664884434, 6651119.252282882, 73.11608023784466], + [510862.09373937984, 6651118.21568087, 72.88133022484466], + [510861.4050998429, 6651123.825424497, 74.28769907084465], + [510861.13547109975, 6651126.021853894, 74.85391898984466], + [510861.9218554377, 6651119.615868919, 73.41352270784466], + [510862.06241952785, 6651118.470816296, 73.18969903284466], + [510861.1929960688, 6651125.553248314, 74.89669423084466], + [510861.8741197723, 6651120.004729606, 73.66973583084466], + [510862.02821356634, 6651118.749462327, 73.47779738384466], + [510861.82412149844, 6651120.412021788, 73.88201363984467], + [510861.6183253255, 6651122.0884631, 74.28769907084465], + [510861.6690826511, 6651121.67498759, 74.24995621184466], + [510861.77272698557, 6651120.830687904, 74.04912839684465], + [510861.7207839968, 6651121.253821974, 74.17128151884467], + [510861.9914258156, 6651119.0491399355, 73.74299510884465], + [510861.95240572066, 6651119.3670025, 73.98308355584466], + [510861.9115369284, 6651119.699924783, 74.19633589084467], + [510861.8692251157, 6651120.0446020905, 74.38154479284468], + [510861.62163655524, 6651122.061489409, 74.89669423084466], + [510861.82588535576, 6651120.397653185, 74.53803608484466], + [510861.67916152434, 6651121.592883831, 74.85391898984466], + [510861.781929801, 6651120.75572062, 74.66565884384465], + [510861.7377563828, 6651121.115562798, 74.76475433784466], + [510869.871015356, 6651131.630491235, 67.75322922458413], + [510869.9483941724, 6651131.02582094, 67.75322922458413], + [510869.9483941724, 6651131.02582094, 67.88322922458413], + [510870.0918160808, 6651131.658760498, 67.74984006371746], + [510870.1692687201, 6651131.054099654, 67.74984006371746], + [510869.871015356, 6651131.630491235, 69.58203288358415], + [510870.1692687201, 6651131.054099654, 67.87984006371745], + [510869.9483938755, 6651131.02582326, 69.58203288458412], + [510869.9489708468, 6651131.021314566, 69.78585416858414], + [510869.87367589324, 6651131.609700689, 70.04762357058412], + [510869.95376168005, 6651130.983877, 70.20243345658415], + [510869.88199574815, 6651131.544685878, 70.52489452258413], + [510869.96374813415, 6651130.905838689, 70.62676057658413], + [510869.8964040309, 6651131.432093557, 71.00779554258415], + [510870.0918160808, 6651131.658760498, 69.57864372271747], + [510871.49698203395, 6651118.9245105, 67.75322922458413], + [510869.97925345745, 6651130.784673636, 71.05307092758413], + [510870.16926842293, 6651131.054101975, 69.57864372371745], + [510871.49698203395, 6651118.9245105, 67.88322922458413], + [510871.57436085044, 6651118.319840205, 67.75322922458413], + [510869.9113888733, 6651131.314995757, 71.36950152758413], + [510870.1698459446, 6651131.049593351, 69.78246500771746], + [510870.0944791564, 6651131.637970276, 70.04423440971745], + [510870.00046591845, 6651130.618910633, 71.47487978658414], + [510869.930030338, 6651131.16932359, 71.72725937358413], + [510870.1746413485, 6651131.01215637, 70.19904429571747], + [510870.10280694877, 6651131.572956482, 70.52150536171746], + [510870.0274110838, 6651130.408349889, 71.88522932958413], + [510869.9523306518, 6651130.995059651, 72.07771558858413], + [510870.1846373302, 6651130.9341192795, 70.62337141571746], + [510869.97822665866, 6651130.79269747, 72.41746061558415], + [510870.11722897773, 6651131.46036592, 71.00440638171747], + [510870.0599331122, 6651130.154209216, 72.27700902358413], + [510870.2001574462, 6651130.812956119, 71.04968176671746], + [510871.7193340025, 6651118.95297837, 67.74984006371746], + [510870.0877847347, 6651129.93656504, 72.55449088358412], + [510870.007587626, 6651130.563258644, 72.74312772558413], + [510871.7193340025, 6651118.95297837, 67.87984006371745], + [510870.1322281163, 6651131.343269952, 71.36611236671746], + [510871.7967866418, 6651118.348317526, 67.74984006371746], + [510871.49698203395, 6651118.9245105, 69.58203288358415], + [510871.57436085044, 6651118.319840205, 69.58203288358415], + [510870.1183718552, 6651129.697544542, 72.81493155658413], + [510870.22139014484, 6651130.647195706, 71.47149062571746], + [510870.04021595995, 6651130.308287255, 73.05149653358413], + [510870.15088736586, 6651131.19760006, 71.72387021271746], + [510871.494634501, 6651118.9428551, 69.99284819558413], + [510870.15143050137, 6651129.439210514, 73.05590120258414], + [510871.5717003131, 6651118.340630752, 70.04762357058412], + [510870.0758509794, 6651130.029820372, 73.33959488458414], + [510870.2483610171, 6651130.436638256, 71.88184016871746], + [510870.17320895504, 6651131.023338846, 72.07432642771745], + [510871.48729345266, 6651119.00022111, 70.41396962358412], + [510870.18665224506, 6651129.163973141, 73.27532020858413], + [510870.11417565023, 6651129.730335435, 73.60479260958412], + [510871.5633804583, 6651118.405645562, 70.52489452258413], + [510870.1991296678, 6651130.820979828, 72.41407145471747], + [510870.28091407294, 6651130.182501554, 72.27361986271745], + [510871.4745802619, 6651119.099567277, 70.84005875858412], + [510870.23638221284, 6651128.775362463, 73.53153333158413], + [510870.15482592816, 6651129.412677235, 73.84488105658413], + [510870.30879226705, 6651129.964860781, 72.55110172271745], + [510870.2884693166, 6651128.368332145, 73.74381114058413], + [510871.5489721755, 6651118.518237885, 71.00779554258415], + [510870.22851864673, 6651130.591544589, 72.73973856471746], + [510871.4562352976, 6651119.242922467, 71.26496526258414], + [510871.7193340025, 6651118.95297837, 69.57864372271747], + [510870.19740213844, 6651129.079968997, 74.05813339158414], + [510871.7967866418, 6651118.348317526, 69.57864372271747], + [510870.3420109914, 6651127.9499352, 73.91092589758412], + [510870.3394085691, 6651129.725844018, 72.81154239571745], + [510871.533987333, 6651118.635335683, 71.36950152758413], + [510870.2611781097, 6651130.3365771845, 73.04810737271745], + [510870.24148165574, 6651128.735513294, 74.24334229358413], + [510871.4321486488, 6651119.431145571, 71.68193196458412], + [510871.71698423, 6651118.971322684, 69.98945903471746], + [510870.39612405637, 6651127.527073177, 74.03307901958414], + [510870.37249875464, 6651129.467514029, 73.05251204171746], + [510871.5153458683, 6651118.7810078515, 71.72725937358413], + [510870.2866320657, 6651128.382689186, 74.39983358558413], + [510871.7941235662, 6651118.369107748, 70.04423440971745], + [510870.44998538285, 6651127.1061783405, 74.11175371258415], + [510870.2968471265, 6651130.058114655, 73.33620572371747], + [510871.4023838256, 6651119.663740294, 72.08388088158412], + [510870.5028632499, 6651126.6929686675, 74.14949657158414], + [510870.33242399734, 6651128.024851964, 74.52745634458412], + [510871.70963617787, 6651119.028687796, 70.41058046271745], + [510870.4077541014, 6651129.192280958, 73.27193104771746], + [510871.49304555455, 6651118.95527179, 72.07771558858413], + [510871.36719059135, 6651119.938754884, 72.46376168358412], + [510870.3784428944, 6651127.66524114, 74.62655183858415], + [510870.3352083607, 6651129.758634399, 73.60140344871745], + [510871.7857957739, 6651118.434121542, 70.52150536171746], + [510871.4671495477, 6651119.157633971, 72.41746061558415], + [510871.33748840715, 6651120.170860121, 72.73016799858414], + [510870.4575315138, 6651128.803676354, 73.52814417071745], + [510871.69691085815, 6651119.12803241, 70.83666959771745], + [510870.4394857311, 6651127.188226991, 74.71571649058413], + [510870.72037903435, 6651124.993209746, 74.14949657158414], + [510870.3758974208, 6651129.440981164, 73.84149189571745], + [510871.30522134947, 6651120.423008345, 72.97787773858413], + [510870.4994139806, 6651126.719922694, 74.75849173158413], + [510871.43778858037, 6651119.387072797, 72.74312772558413], + [510870.5096683109, 6651128.396652397, 73.74042197971745], + [510871.771373745, 6651118.546712104, 71.00440638171747], + [510871.25872366433, 6651120.786360621, 73.27532020858413], + [510871.678548392, 6651119.2713853605, 71.26157610171747], + [510871.4051602464, 6651119.642044187, 73.05149653358413], + [510870.41851425066, 6651129.108278127, 74.05474423071746], + [510871.20899369643, 6651121.174971298, 73.53153333158413], + [510870.94251265936, 6651123.257365095, 74.14949657158414], + [510871.1569065928, 6651121.582001618, 73.74381114058413], + [510870.9953905264, 6651122.8441554215, 74.11175371258415], + [510870.56326106685, 6651127.978261993, 73.90753673671745], + [510871.103364918, 6651122.000398563, 73.91092589758412], + [510871.049251853, 6651122.423260587, 74.03307901958414], + [510871.369525227, 6651119.920511069, 73.33959488458414], + [510871.75637460634, 6651118.663808072, 71.36611236671746], + [510870.46263582166, 6651128.763827808, 74.23995313271746], + [510871.65443876345, 6651119.4596055215, 71.67854280371745], + [510871.33120055613, 6651120.219996005, 73.60479260958412], + [510870.6174257581, 6651127.555406579, 74.02968985871746], + [510870.5078293073, 6651128.411009216, 74.39644442471746], + [510871.73771535687, 6651118.8094779635, 71.72387021271746], + [510871.2905502782, 6651120.537654206, 73.84488105658413], + [510870.6713384706, 6651127.1345183235, 74.10836455171747], + [510871.6246455434, 6651119.692196609, 72.08049172071745], + [510871.2479740679, 6651120.870362443, 74.05813339158414], + [510870.9459622257, 6651123.230408748, 74.75849173158413], + [510871.20389455074, 6651121.214818148, 74.24334229358413], + [510870.72426678555, 6651126.721315107, 74.14610741071746], + [510870.5536649264, 6651128.053177586, 74.52406718371745], + [510871.0058904752, 6651122.762104449, 74.71571649058413], + [510871.15874414064, 6651121.567642254, 74.39983358558413], + [510871.06693331205, 6651122.285090303, 74.62655183858415], + [510871.112952209, 6651121.925479477, 74.52745634458412], + [510871.7153937676, 6651118.983739178, 72.07432642771745], + [510871.58941873326, 6651119.967206899, 72.46037252271745], + [510870.5997277274, 6651127.6935723815, 74.62316267771747], + [510871.68947305484, 6651119.186098197, 72.41407145471747], + [510871.55968821177, 6651120.199308507, 72.72677883771746], + [510870.66082880175, 6651127.216565691, 74.71232732971745], + [510870.94199008954, 6651125.021582756, 74.14610741071746], + [510871.5273903699, 6651120.451452792, 72.97448857771745], + [510870.72081422544, 6651126.748268713, 74.75510257071745], + [510871.6600840759, 6651119.415533436, 72.73973856471746], + [510871.48084832396, 6651120.814799389, 73.27193104771746], + [510871.62742461305, 6651119.67050084, 73.04810737271745], + [510871.4310709115, 6651121.203403992, 73.52814417071745], + [510871.1643356398, 6651123.285765238, 74.14610741071746], + [510871.3789341145, 6651121.610427949, 73.74042197971745], + [510871.21726395475, 6651122.872562024, 74.10836455171747], + [510871.3253413585, 6651122.028818353, 73.90753673671745], + [510871.27117666724, 6651122.451673767, 74.02968985871746], + [510871.5917555961, 6651119.948963369, 73.33620572371747], + [510871.5533943619, 6651120.248443625, 73.60140344871745], + [510871.5127053018, 6651120.56609686, 73.84149189571745], + [510871.470088472, 6651120.898799897, 74.05474423071746], + [510871.1677884973, 6651123.258809312, 74.75510257071745], + [510871.42596690095, 6651121.243250218, 74.23995313271746], + [510871.22777392087, 6651122.790512334, 74.71232732971745], + [510871.3807734153, 6651121.596068809, 74.39644442471746], + [510871.28887499525, 6651122.313505642, 74.62316267771747], + [510871.33493779623, 6651121.953900439, 74.52406718371745], + [510877.22765063925, 6651132.587124988, 67.63777053046715], + [510877.30748908257, 6651131.982774536, 67.63777053046715], + [510877.30748908257, 6651131.982774536, 67.76777053046715], + [510877.22765063925, 6651132.587124988, 69.46657418946717], + [510877.3074887762, 6651131.982776854, 69.46657419046714], + [510877.30808408756, 6651131.9782705465, 69.67039547446716], + [510877.23039574665, 6651132.566345439, 69.93216487646714], + [510877.31302720617, 6651131.940852782, 70.08697476246716], + [510877.2389800633, 6651132.501365018, 70.40943582846715], + [510877.3233310979, 6651131.86285575, 70.51130188246715], + [510877.25384633965, 6651132.3888322525, 70.89233684846717], + [510877.33932928625, 6651131.741754786, 70.93761223346715], + [510877.2693075025, 6651132.271796394, 71.25404283346715], + [510878.90530163253, 6651119.887865121, 67.63777053046715], + [510877.36121602403, 6651131.5760794645, 71.35942109246716], + [510878.90530163253, 6651119.887865121, 67.76777053046715], + [510878.9851400758, 6651119.283514667, 67.63777053046715], + [510877.28854152025, 6651132.126201279, 71.61180067946715], + [510877.3890176905, 6651131.365630099, 71.76977063546715], + [510877.3115506901, 6651131.952029519, 71.96225689446715], + [510877.33826984867, 6651131.749774376, 72.30200192146717], + [510877.42257349094, 6651131.1116238525, 72.16155032946715], + [510877.3685641079, 6651131.520456913, 72.62766903146715], + [510877.45131042786, 6651130.894094801, 72.43903218946714], + [510877.48286981584, 6651130.655200734, 72.69947286246715], + [510877.402229593, 6651131.265620392, 72.93603783946715], + [510878.90530163253, 6651119.887865121, 69.46657418946717], + [510878.9851400758, 6651119.283514667, 69.46657418946717], + [510877.5169792914, 6651130.397003351, 72.94044250846716], + [510877.4389973365, 6651130.987300805, 73.22413619046716], + [510878.90287947905, 6651119.906200016, 69.87738950146715], + [510877.55332062236, 6651130.121911566, 73.15986151446715], + [510878.98239496845, 6651119.3042942155, 69.93216487646714], + [510877.4785402269, 6651130.687974281, 73.48933391546714], + [510878.89530508197, 6651119.963535681, 70.29851092946714], + [510877.6046313479, 6651129.733506445, 73.41607463746715], + [510877.520482648, 6651130.370484107, 73.72942236246715], + [510878.9738106518, 6651119.369274637, 70.40943582846715], + [510878.88218777935, 6651120.0628293, 70.72460006446715], + [510877.65837413515, 6651129.326691425, 73.62835244646715], + [510877.5644122208, 6651130.037951857, 73.94267469746715], + [510878.95894437557, 6651119.481807402, 70.89233684846717], + [510877.7136177298, 6651128.908515794, 73.79546720346715], + [510878.86325968686, 6651120.206108662, 71.14950656846716], + [510877.6098928858, 6651129.693678354, 74.12788359946715], + [510877.7694508771, 6651128.485877444, 73.91762032546714], + [510878.9434832126, 6651119.598843262, 71.25404283346715], + [510877.656478484, 6651129.341040874, 74.28437489146715], + [510878.83840740006, 6651120.394232205, 71.56647327046714], + [510877.8250242841, 6651128.065205242, 73.99629501846717], + [510877.70372599567, 6651128.983392931, 74.41199765046714], + [510877.87958297064, 6651127.652214138, 74.03403787746716], + [510878.9242491949, 6651119.744438377, 71.61180067946715], + [510878.80769644777, 6651120.626703896, 71.96842218746714], + [510877.75120768714, 6651128.623972323, 74.51109314446717], + [510878.90124002506, 6651119.918610138, 71.96225689446715], + [510878.7713845324, 6651120.901573014, 72.34830298946714], + [510877.81419088185, 6651128.147210494, 74.60025779646715], + [510878.10401289066, 6651125.953354308, 74.03403787746716], + [510878.87452086643, 6651120.120865279, 72.30200192146717], + [510878.74073821004, 6651121.133555479, 72.61470930446715], + [510877.8760240599, 6651127.679153906, 74.64303303746715], + [510878.70744548517, 6651121.38557033, 72.86241904446715], + [510878.84422660724, 6651120.350182742, 72.62766903146715], + [510878.6594697863, 6651121.74873041, 73.15986151446715], + [510878.333207438, 6651124.218427839, 74.03403787746716], + [510878.8105611221, 6651120.605019265, 72.93603783946715], + [510878.6081590607, 6651122.137135531, 73.41607463746715], + [510878.38776612456, 6651123.805436733, 73.99629501846717], + [510878.55441627343, 6651122.543950549, 73.62835244646715], + [510878.44333953154, 6651123.384764532, 73.91762032546714], + [510878.49917267886, 6651122.9621261805, 73.79546720346715], + [510878.77379337855, 6651120.88333885, 73.22413619046716], + [510878.7342504882, 6651121.182665374, 73.48933391546714], + [510878.69230806705, 6651121.500155548, 73.72942236246715], + [510878.3367666552, 6651124.191485749, 74.64303303746715], + [510878.64837849437, 6651121.832687799, 73.94267469746715], + [510878.3985998333, 6651123.723429161, 74.60025779646715], + [510878.6028978294, 6651122.176961301, 74.12788359946715], + [510878.5563122312, 6651122.529598781, 74.28437489146715], + [510878.46158302797, 6651123.246667332, 74.51109314446717], + [510878.50906471943, 6651122.887246726, 74.41199765046714], + [510886.817316537, 6651133.879879337, 67.4793948502016], + [510886.9003612012, 6651133.275961105, 67.4793948502016], + [510886.9003612012, 6651133.275961105, 67.60939485020158], + [510886.817316537, 6651133.879879337, 69.3081985092016], + [510886.9003608826, 6651133.275963422, 69.30819851020158], + [510886.900980101, 6651133.271460336, 69.51201979420159], + [510886.82017188467, 6651133.859114649, 69.77378919620158], + [510886.9061217296, 6651133.234069334, 69.9285990822016], + [510886.8291009377, 6651133.794180701, 70.25106014820159], + [510886.9168394139, 6651133.156128082, 70.35292620220159], + [510886.84456422675, 6651133.681728418, 70.7339611682016], + [510886.9334800713, 6651133.0351137305, 70.77923655320159], + [510886.86064629245, 6651133.5647762595, 71.09566715320159], + [510886.9562457555, 6651132.869556895, 71.2010454122016], + [510886.8806527264, 6651133.419285271, 71.45342499920159], + [510888.56234008534, 6651121.189701763, 67.4793948502016], + [510888.56234008534, 6651121.189701763, 67.60939485020158], + [510886.90458591835, 6651133.245238076, 71.80388121420158], + [510886.98516390525, 6651132.65925804, 71.61139495520159], + [510888.6453847495, 6651120.58578353, 67.4793948502016], + [510886.93237808795, 6651133.043127583, 72.1436262412016], + [510887.0200672685, 6651132.4054334555, 72.00317464920158], + [510886.96388893016, 6651132.813974124, 72.46929335120159], + [510887.04995824816, 6651132.188059975, 72.28065650920158], + [510887.08278502524, 6651131.949336761, 72.54109718220158], + [510886.99890638277, 6651132.559319858, 72.77766215920158], + [510887.1182642985, 6651131.6913240375, 72.7820668282016], + [510887.03715067706, 6651132.28119932, 73.0657605102016], + [510888.56234008534, 6651121.189701763, 69.3081985092016], + [510887.15606505604, 6651131.416428993, 73.00148583420159], + [510888.6453847495, 6651120.58578353, 69.3081985092016], + [510887.0782815649, 6651131.98208687, 73.33095823520158], + [510888.5598206608, 6651121.208023545, 69.71901382120159], + [510887.2094363619, 6651131.0283016525, 73.25769895720158], + [510887.121908346, 6651131.664823759, 73.57104668220158], + [510888.6425294018, 6651120.606548218, 69.77378919620158], + [510888.5519420846, 6651121.265318206, 70.14013524920158], + [510887.26533739833, 6651130.62177758, 73.46997676620158], + [510887.1676020804, 6651131.332529331, 73.78429901720159], + [510888.6336003488, 6651120.671482166, 70.25106014820159], + [510888.538298006, 6651121.36454081, 70.56622438420158], + [510887.3227995129, 6651130.203901021, 73.63709152320158], + [510887.2149091972, 6651130.988502046, 73.96950791920159], + [510887.38087485585, 6651129.781564935, 73.75924464520159], + [510887.26336562, 6651130.636116766, 74.12599921120159], + [510888.61813705973, 6651120.78393445, 70.7339611682016], + [510888.5186097829, 6651121.507717702, 70.9911308882016], + [510887.4386800276, 6651129.36119359, 73.8379193382016], + [510887.3125105379, 6651130.278724607, 74.25362197020158], + [510887.49542972894, 6651128.9484978495, 73.87566219720159], + [510888.60205499415, 6651120.900886607, 71.09566715320159], + [510888.49275945657, 6651121.695706701, 71.40809759020158], + [510887.3618990402, 6651129.91956105, 74.3527174642016], + [510888.58204856014, 6651121.0463775955, 71.45342499920159], + [510888.4608151873, 6651121.928012133, 71.81004650720158], + [510887.4274115682, 6651129.443140194, 74.44188211620158], + [510887.7288724993, 6651127.250853017, 73.87566219720159], + [510887.49172789644, 6651128.9754183525, 74.48465735720158], + [510888.5581153682, 6651121.220424791, 71.80388121420158], + [510888.4230450267, 6651122.20268467, 72.18992730920158], + [510888.3911679829, 6651122.434501225, 72.45633362420159], + [510888.53032319853, 6651121.422535284, 72.1436262412016], + [510888.3565382601, 6651122.686335838, 72.70404336420158], + [510888.4988123564, 6651121.651688743, 72.46929335120159], + [510888.3066359117, 6651123.049236191, 73.00148583420159], + [510887.96727123886, 6651125.517167335, 73.87566219720159], + [510888.2532646058, 6651123.437363532, 73.25769895720158], + [510888.02402094007, 6651125.104471595, 73.8379193382016], + [510888.4637949038, 6651121.906343009, 72.77766215920158], + [510888.0818261118, 6651124.684100252, 73.75924464520159], + [510888.1973635694, 6651123.843887605, 73.46997676620158], + [510888.13990145497, 6651124.261764164, 73.63709152320158], + [510888.4255506094, 6651122.184463547, 73.0657605102016], + [510888.3844197216, 6651122.483575998, 73.33095823520158], + [510887.97097339004, 6651125.490244515, 74.48465735720158], + [510888.3407929405, 6651122.8008391075, 73.57104668220158], + [510888.2950992062, 6651123.133133537, 73.78429901720159], + [510888.03528971836, 6651125.022522674, 74.44188211620158], + [510888.2477920894, 6651123.477160821, 73.96950791920159], + [510888.1008022464, 6651124.546101817, 74.3527174642016], + [510888.1993356666, 6651123.829546101, 74.12599921120159], + [510888.1501907486, 6651124.186938261, 74.25362197020158], + [510890.0168465994, 6651134.322734014, 67.42456835018152], + [510890.10096099856, 6651133.718963847, 67.42456835018152], + [510890.10096099856, 6651133.718963847, 67.5545683501815], + [510890.0168465994, 6651134.322734014, 69.2533720091815], + [510890.1009606759, 6651133.718966164, 69.2533720101815], + [510890.1015878706, 6651133.714464181, 69.4571932941815], + [510890.0197387282, 6651134.301974417, 69.71896269618149], + [510890.1067957308, 6651133.677082348, 69.8737725821815], + [510890.02878280025, 6651134.23705639, 70.19623364818152], + [510890.11765147443, 6651133.599160205, 70.2980997021815], + [510890.04444527865, 6651134.124631675, 70.6791346681815], + [510890.1345064874, 6651133.478175522, 70.7244100531815], + [510890.06073450454, 6651134.007708192, 71.0408406531815], + [510890.1575654265, 6651133.312659276, 71.1462189121815], + [510890.0809986501, 6651133.862252874, 71.3985984991815], + [510890.1052401361, 6651133.688248351, 71.7490547141815], + [510891.7843485653, 6651121.635667731, 67.42456835018152], + [510890.18685608363, 6651133.10241198, 71.5565684551815], + [510891.7843485653, 6651121.635667731, 67.5545683501815], + [510891.86846296454, 6651121.0318975635, 67.42456835018152], + [510890.1333903089, 6651133.486187411, 72.0887997411815], + [510890.2222090524, 6651132.8486496275, 71.9483481491815], + [510890.16530705616, 6651133.257090134, 72.4144668511815], + [510890.252485071, 6651132.6313294405, 72.2258300091815], + [510890.28573470435, 6651132.392664757, 72.4862706821815], + [510890.20077558403, 6651133.002498302, 72.7228356591815], + [510890.3216710017, 6651132.134715291, 72.72724032818151], + [510890.23951251997, 6651132.724445951, 73.01093401018151], + [510891.7843485653, 6651121.635667731, 69.2533720091815], + [510890.35995868745, 6651131.859887643, 72.9466593341815], + [510890.2811732329, 6651132.425406835, 73.2761317351815], + [510891.86846296454, 6651121.0318975635, 69.2533720091815], + [510891.78179668705, 6651121.6539850235, 69.6641873211815], + [510890.4140174926, 6651131.471855461, 73.2028724571815], + [510890.32536198973, 6651132.1082215095, 73.5162201821815], + [510891.8655708358, 6651121.052657161, 69.71896269618149], + [510890.4706386151, 6651131.065431057, 73.41515026618151], + [510891.77381662343, 6651121.711265636, 70.08530874918151], + [510890.37164432526, 6651131.776008551, 73.7294725171815], + [510890.5288409244, 6651130.64765695, 73.58226502318149], + [510891.85652676376, 6651121.117575189, 70.19623364818152], + [510890.4195608259, 6651131.432065613, 73.91468141918152], + [510891.7599967895, 6651121.810463914, 70.51139788418149], + [510890.5876643615, 6651130.225424409, 73.7044181451815], + [510890.46864143724, 6651131.079766729, 74.0711727111815], + [510891.7400549536, 6651121.953605702, 70.9363043881815], + [510891.8408642853, 6651121.229999903, 70.6791346681815], + [510890.6462141471, 6651129.805156129, 73.7830928381815], + [510890.51841941255, 6651130.72246219, 74.1987954701815], + [510890.7036948663, 6651129.392561571, 73.8208356971815], + [510891.82457505947, 6651121.346923387, 71.0408406531815], + [510890.56844410993, 6651130.363386692, 74.2978909641815], + [510891.7138716378, 6651122.141548612, 71.35327109018151], + [510890.6348005337, 6651129.88708264, 74.3870556161815], + [510891.8043109138, 6651121.492378703, 71.3985984991815], + [510891.6815158804, 6651122.373797089, 71.75522000718149], + [510890.69994534896, 6651129.4194754725, 74.4298308571815], + [510890.9401447159, 6651127.695332954, 73.8208356971815], + [510891.7800694279, 6651121.666383228, 71.7490547141815], + [510891.6432591857, 6651122.648402283, 72.1351008091815], + [510891.61097151967, 6651122.8801620025, 72.40150712418149], + [510891.751919255, 6651121.868444168, 72.0887997411815], + [510891.57589571615, 6651123.131934875, 72.6492168641815], + [510891.72000250773, 6651122.097541446, 72.4144668511815], + [510891.18161437474, 6651125.962072326, 73.8208356971815], + [510891.5253505536, 6651123.494746254, 72.9466593341815], + [510891.2390950939, 6651125.549477767, 73.7830928381815], + [510891.47129174846, 6651123.882778435, 73.2028724571815], + [510891.29764487955, 6651125.129209487, 73.7044181451815], + [510891.4146706261, 6651124.289202839, 73.41515026618151], + [510891.6845339799, 6651122.352133278, 72.7228356591815], + [510891.35646831675, 6651124.706976946, 73.58226502318149], + [510891.6457970439, 6651122.630185626, 73.01093401018151], + [510891.604136331, 6651122.9292247435, 73.2761317351815], + [510891.185364215, 6651125.935156106, 74.4298308571815], + [510891.55994757416, 6651123.24641007, 73.5162201821815], + [510891.2505090302, 6651125.467548939, 74.3870556161815], + [510891.5136652387, 6651123.5786230285, 73.7294725171815], + [510891.31686545414, 6651124.991244887, 74.2978909641815], + [510891.46574873803, 6651123.922565967, 73.91468141918152], + [510891.36689015134, 6651124.632169387, 74.1987954701815], + [510891.4166681267, 6651124.274864851, 74.0711727111815], + [510893.8452964614, 6651134.860233717, 67.35765722912942], + [510893.93069086946, 6651134.256643257, 67.35765722912942], + [510893.93069086946, 6651134.256643257, 67.48765722912941], + [510893.8452964614, 6651134.860233717, 69.18646088812942], + [510893.93069054175, 6651134.256645573, 69.1864608891294], + [510893.93132728094, 6651134.252144931, 69.3902821731294], + [510893.848232601, 6651134.839480299, 69.6520515751294], + [510893.93661439157, 6651134.214774222, 69.80686146112942], + [510893.857414301, 6651134.7745815925, 70.12932252712942], + [510893.9476353321, 6651134.136875275, 70.23118858112942], + [510893.8733151229, 6651134.662190341, 70.61222354712942], + [510893.9647468358, 6651134.015926601, 70.65749893212941], + [510893.8898522296, 6651134.54530166, 70.97392953212943], + [510893.98815667373, 6651133.850459621, 71.07930779112941], + [510893.9104247444, 6651134.399889637, 71.33168737812943], + [510893.93503512454, 6651134.225936903, 71.68214359312941], + [510894.0178930608, 6651133.640274904, 71.48965733412942], + [510895.6396953445, 6651122.176943657, 67.35765722912942], + [510895.6396953445, 6651122.176943657, 67.48765722912941], + [510893.963613672, 6651134.023936105, 72.02188862012942], + [510895.7250897525, 6651121.573353198, 67.35765722912942], + [510894.05378401256, 6651133.38658808, 71.88143702812941], + [510893.9960161115, 6651133.794907017, 72.34755573012941], + [510894.0845207557, 6651133.16933258, 72.15891888812942], + [510894.11827636434, 6651132.93073893, 72.41935956112941], + [510894.0320243808, 6651133.540390962, 72.65592453812943], + [510894.15475952154, 6651132.672866243, 72.66032920712941], + [510894.0713507951, 6651133.262421373, 72.94402288912941], + [510894.1936298492, 6651132.398120395, 72.87974821312942], + [510894.11364547885, 6651132.963471265, 73.2092206141294], + [510895.6396953445, 6651122.176943657, 69.18646088812942], + [510895.7250897525, 6651121.573353198, 69.18646088812942], + [510894.24851129286, 6651132.010203708, 73.13596133612941], + [510894.1585066771, 6651132.646380346, 73.44930906112941], + [510895.6371046331, 6651122.195255497, 69.59727620012941], + [510894.30599404575, 6651131.603900274, 73.34823914512941], + [510894.20549331285, 6651132.314266268, 73.66256139612942], + [510895.72215361294, 6651121.594106616, 69.6520515751294], + [510895.62900313304, 6651122.252519061, 70.0183976281294], + [510894.3650820473, 6651131.186250514, 73.51535390212942], + [510894.25413898163, 6651131.970425703, 73.84777029812942], + [510895.7129719129, 6651121.659005322, 70.12932252712942], + [510895.61497299606, 6651122.351687812, 70.44448676312942], + [510894.42480062856, 6651130.764143649, 73.63750702412942], + [510894.303966476, 6651131.618231678, 74.00426159012942], + [510894.48424139415, 6651130.344000459, 73.71618171712942], + [510894.35450194636, 6651131.26103349, 74.13188434912941], + [510895.59472769586, 6651122.494786996, 70.86939326712941], + [510895.697071091, 6651121.771396574, 70.61222354712942], + [510894.54259682476, 6651129.931528707, 73.7539245761294], + [510894.4052878933, 6651130.902064868, 74.23097984312942], + [510895.6805339843, 6651121.888285257, 70.97392953212943], + [510895.5681459361, 6651122.682673966, 71.2863599691294], + [510894.47265409434, 6651130.4259025855, 74.32014449512941], + [510895.6599614695, 6651122.03369728, 71.33168737812943], + [510895.53529780573, 6651122.914853315, 71.6883088861294], + [510894.5387902491, 6651129.9584345985, 74.36291973612943], + [510894.7826448441, 6651128.23480526, 73.7539245761294], + [510895.6353510894, 6651122.207650012, 71.68214359312941], + [510895.49645894073, 6651123.189376776, 72.06818968812941], + [510895.46367993794, 6651123.421067513, 72.3345960031294], + [510895.60677254194, 6651122.409650811, 72.02188862012942], + [510895.4280703693, 6651123.672765445, 72.58230574312941], + [510895.02778906137, 6651126.502060527, 73.7539245761294], + [510895.57437010243, 6651122.638679897, 72.34755573012941], + [510895.37675603695, 6651124.035468836, 72.87974821312942], + [510895.086144492, 6651126.0895887725, 73.71618171712942], + [510895.32187459327, 6651124.423385523, 73.13596133612941], + [510895.14558525756, 6651125.669445583, 73.63750702412942], + [510895.2643918404, 6651124.829688958, 73.34823914512941], + [510895.20530383894, 6651125.247338717, 73.51535390212942], + [510895.53836183314, 6651122.893195953, 72.65592453812943], + [510895.49903541885, 6651123.171165542, 72.94402288912941], + [510895.4567407351, 6651123.47011565, 73.2092206141294], + [510895.03159596474, 6651126.4751523165, 74.36291973612943], + [510895.41187953687, 6651123.787206569, 73.44930906112941], + [510895.0977321196, 6651126.0076843295, 74.32014449512941], + [510895.36489290104, 6651124.119320646, 73.66256139612942], + [510895.1650983207, 6651125.531522047, 74.23097984312942], + [510895.31624723226, 6651124.463161212, 73.84777029812942], + [510895.21588426747, 6651125.172553425, 74.13188434912941], + [510895.26641973795, 6651124.815355238, 74.00426159012942], + [510903.7417831255, 6651136.2880531745, 67.17808119638813], + [510903.8304863374, 6651135.684940094, 67.17808119638813], + [510903.8304863374, 6651135.684940094, 67.30808119638813], + [510903.7417831255, 6651136.2880531745, 69.00688485538814], + [510903.830485997, 6651135.684942409, 69.00688485638813], + [510903.8311474081, 6651135.680445326, 69.21070614038813], + [510903.7448330327, 6651136.26731617, 69.47247554238812], + [510903.8366393801, 6651135.643104174, 69.62728542838813], + [510903.754370499, 6651136.202468793, 69.94974649438814], + [510903.8480873526, 6651135.565266836, 70.05161254838814], + [510903.7708874349, 6651136.090166433, 70.43264751438814], + [510903.8658618811, 6651135.444413821, 70.47792289938815], + [510903.7880653101, 6651135.973370197, 70.79435349938814], + [510903.89017878723, 6651135.279077708, 70.89973175838813], + [510903.8094349546, 6651135.82807318, 71.15211134538814], + [510903.83499892085, 6651135.654258027, 71.50256756038813], + [510903.9210673794, 6651135.069059225, 71.31008130138814], + [510903.8646848101, 6651135.45241699, 71.84231258738814], + [510903.95834900916, 6651134.815573043, 71.70186099538815], + [510905.60571014445, 6651123.614794314, 67.17808119638813], + [510905.60571014445, 6651123.614794314, 67.30808119638813], + [510903.89834275714, 6651135.223569042, 72.16797969738813], + [510903.99027671845, 6651134.598489368, 71.97934285538813], + [510905.6944133563, 6651123.011681235, 67.17808119638813], + [510903.93574625015, 6651134.969254282, 72.47634850538813], + [510904.02534026635, 6651134.360084424, 72.23978352838813], + [510904.0632370478, 6651134.102415687, 72.48075317438813], + [510903.9765964573, 6651134.691504541, 72.76444685638813], + [510904.10361349623, 6651133.827887136, 72.70017218038814], + [510904.02052994655, 6651134.39279087, 73.02964458138813], + [510904.16062144836, 6651133.440277252, 72.95638530338813], + [510904.0671293956, 6651134.07595074, 73.26973302838813], + [510905.60571014445, 6651123.614794314, 69.00688485538814], + [510904.2203315035, 6651133.034295163, 73.16866311238813], + [510905.6944133563, 6651123.011681235, 69.00688485538814], + [510904.11593663733, 6651133.74409933, 73.48298536338815], + [510905.60301905, 6651123.633091672, 69.41770016738813], + [510904.28170900635, 6651132.616975722, 73.33577786938812], + [510904.1664671951, 6651133.400530706, 73.66819426538814], + [510905.6913634492, 6651123.032418239, 69.47247554238812], + [510905.5946036386, 6651123.690309946, 69.83882159538813], + [510904.3437415222, 6651132.195202701, 73.45793099138814], + [510904.2182253709, 6651133.048615232, 73.82468555738815], + [510904.4054854578, 6651131.775391801, 73.53660568438814], + [510905.681825983, 6651123.097265616, 69.94974649438814], + [510904.2707189551, 6651132.691699551, 73.95230831638814], + [510905.5800298714, 6651123.789400265, 70.26491073038812], + [510904.4661020046, 6651131.363246271, 73.57434854338813], + [510904.3234727209, 6651132.333014838, 74.05140381038814], + [510905.5590001202, 6651123.932386272, 70.68981723438813], + [510905.665309047, 6651123.209567977, 70.43264751438814], + [510904.3934491813, 6651131.857229152, 74.14056846238815], + [510905.53138838866, 6651124.120124641, 71.10678393638813], + [510905.6481311718, 6651123.326364213, 70.79435349938814], + [510904.46214793436, 6651131.390130883, 74.18334370338813], + [510904.7154512396, 6651129.667864761, 73.57434854338813], + [510905.4972674815, 6651124.352120361, 71.50873285338812], + [510905.6267615274, 6651123.47166123, 71.15211134538814], + [510905.45692371484, 6651124.6264267005, 71.88861365538813], + [510905.601197561, 6651123.645476383, 71.50256756038813], + [510905.4228746138, 6651124.857934194, 72.15501997038814], + [510905.57151167176, 6651123.847317419, 71.84231258738814], + [510904.97009413684, 6651127.936490453, 73.57434854338813], + [510905.38588526996, 6651125.10943306, 72.40272971038813], + [510905.03071068355, 6651127.524344925, 73.53660568438814], + [510905.3325826452, 6651125.471849589, 72.70017218038814], + [510905.5378537247, 6651124.076165368, 72.16797969738813], + [510905.09245461907, 6651127.104534024, 73.45793099138814], + [510905.27557469293, 6651125.859459472, 72.95638530338813], + [510905.15448713506, 6651126.682761002, 73.33577786938812], + [510905.21586463787, 6651126.265441561, 73.16866311238813], + [510905.50045023166, 6651124.330480128, 72.47634850538813], + [510905.4596000245, 6651124.608229869, 72.76444685638813], + [510904.9740485475, 6651127.909603526, 74.18334370338813], + [510905.4156665354, 6651124.90694354, 73.02964458138813], + [510905.04274730064, 6651127.442505258, 74.14056846238815], + [510905.36906708626, 6651125.22378367, 73.26973302838813], + [510905.112723761, 6651126.966719572, 74.05140381038814], + [510905.32025984454, 6651125.555635081, 73.48298536338815], + [510905.1654775269, 6651126.608034858, 73.95230831638814], + [510905.2697292868, 6651125.899203703, 73.66819426538814], + [510905.21797111095, 6651126.251119177, 73.82468555738815], + [510909.9112954335, 6651137.2062217705, 67.0612983281163], + [510910.0020613679, 6651136.603415671, 67.0612983281163], + [510910.0020613679, 6651136.603415671, 67.19129832811629], + [510909.9112954335, 6651137.2062217705, 68.8901019871163], + [510910.00206101965, 6651136.603417983, 68.8901019881163], + [510910.0027378113, 6651136.5989231905, 69.09392327211629], + [510909.9144162638, 6651137.185495321, 69.3556926741163], + [510910.0083574948, 6651136.561601045, 69.5105025601163], + [510909.92417551624, 6651137.12068095, 69.8329636261163], + [510910.02007168066, 6651136.483803324, 69.93482968011631], + [510909.9410765405, 6651137.00843575, 70.3158646461163], + [510910.03825954173, 6651136.363011824, 70.36114003111629], + [510909.9586538735, 6651136.891698964, 70.6775706311163], + [510910.4413291449, 6651137.286109873, 67.0510918198317], + [510910.53227229137, 6651136.683330483, 67.0510918198317], + [510910.0631419182, 6651136.197759866, 70.78294889011629], + [510909.98052045197, 6651136.746475902, 71.0353284771163], + [510910.53227229137, 6651136.683330483, 67.18109181983169], + [510910.0066788879, 6651136.572749219, 71.38578469211629], + [510910.09474880004, 6651135.987848282, 71.1932984331163], + [510910.03705509886, 6651136.371010919, 71.7255297191163], + [510910.1328973843, 6651135.734491124, 71.58507812711629], + [510910.07149573474, 6651136.142279453, 72.05119682911631], + [510910.1655675471, 6651135.517517943, 71.86255998711628], + [510911.818566591, 6651124.539413537, 67.0612983281163], + [510910.4413291449, 6651137.286109873, 68.8798954788317], + [510911.818566591, 6651124.539413537, 67.19129832811629], + [510911.9093325254, 6651123.936607438, 67.0612983281163], + [510910.1097690162, 6651135.888094139, 72.35956563711629], + [510910.2014464698, 6651135.279234346, 72.1230006601163], + [510910.5322719425, 6651136.683332797, 68.8798954798317], + [510910.53295005544, 6651136.678838202, 69.08371676383169], + [510910.4444560683, 6651137.265384341, 69.3454861658317], + [510910.2402245108, 6651135.021696761, 72.36397030611629], + [510910.1515691624, 6651135.61048577, 72.64766398811629], + [510910.28153988137, 6651134.747307943, 72.58338931211631], + [510910.5385807108, 6651136.64151771, 69.5002960518317], + [510910.19652428984, 6651135.311924145, 72.9128617131163], + [510910.45423437475, 6651137.200572843, 69.8227571178317], + [510910.3398735081, 6651134.359895351, 72.8396024351163], + [510910.244207372, 6651134.9952452835, 73.1529501601163], + [510910.55031776766, 6651136.5637234375, 69.92462317183171], + [510910.4711683966, 6651137.088332616, 70.3056581378317], + [510911.818566591, 6651124.539413537, 68.8901019871163], + [510910.400972073, 6651133.954119906, 73.05188024411629], + [510910.2941495873, 6651134.663562784, 73.3662024951163], + [510910.5685411388, 6651136.4429372875, 70.3509335228317], + [510910.48878004774, 6651136.971601002, 70.66736412283171], + [510911.9093325254, 6651123.936607438, 68.8901019871163], + [510910.34585519286, 6651134.320169036, 73.5514113971163], + [510910.46377686074, 6651133.537012877, 73.21899500111631], + [510911.81581291725, 6651124.55770158, 69.3009172991163], + [510910.5934720958, 6651136.277692652, 70.77274238183169], + [510910.5106893187, 6651136.826384375, 71.0251219688317], + [510910.3988169639, 6651133.968432685, 73.7079026891163], + [510910.5272518934, 6651133.115454536, 73.34114812311628], + [510911.9062116951, 6651123.957333889, 69.3556926741163], + [510911.8072018121, 6651124.614890731, 69.72203872711628], + [510910.59043163504, 6651132.695857318, 73.4198228161163], + [510910.4525312445, 6651133.611698673, 73.83552544811629], + [510910.5368988266, 6651136.652665391, 71.37557818383169], + [510910.6251406871, 6651136.0677903695, 71.1830919248317], + [510910.65245777124, 6651132.283921569, 73.45756567511629], + [510911.8964524427, 6651124.022148259, 69.8329636261163], + [510911.79228914366, 6651124.713930614, 70.1481278621163], + [510910.5065117572, 6651133.253196527, 73.9346209421163], + [510910.5781154644, 6651132.777653014, 74.02378559411629], + [510910.56733434444, 6651136.450936031, 71.7153232108317], + [510911.7707703624, 6651124.85684384, 70.57303436611629], + [510911.87955141853, 6651124.134393457, 70.3158646461163], + [510910.66336375306, 6651135.814444437, 71.5748716188317], + [510910.64841175237, 6651132.310792496, 74.06656083511629], + [510911.74251654197, 6651125.044486653, 70.99000106811629], + [510910.90760542435, 6651130.589403001, 73.45756567511629], + [510911.86197408556, 6651124.251130244, 70.6775706311163], + [510910.6018422223, 6651136.222214699, 72.04099032083171], + [510910.69609770126, 6651135.597480871, 71.8523534788317], + [510912.3523240739, 6651124.619862897, 67.0510918198317], + [510911.7076021803, 6651125.276364288, 71.3919499851163], + [510911.8401075071, 6651124.396353305, 71.0353284771163], + [510912.3523240739, 6651124.619862897, 67.18109181983169], + [510910.6401902289, 6651135.968040647, 72.3493591288317], + [510912.4432672205, 6651124.017083507, 67.0510918198317], + [510910.73204667435, 6651135.35920783, 72.11279415183171], + [510911.6663202515, 6651125.550531007, 71.77183078711629], + [510911.81394907105, 6651124.570079989, 71.38578469211629], + [510911.63147936563, 6651125.781920664, 72.03823710211628], + [510911.1681698393, 6651128.858909952, 73.45756567511629], + [510911.78357286006, 6651124.771818289, 71.7255297191163], + [510910.77090042585, 6651135.101681658, 72.35376379783169], + [510911.59362986404, 6651126.033291517, 72.28594684211629], + [510910.682071986, 6651135.690444578, 72.6374574798317], + [510911.2301959755, 6651128.446974205, 73.4198228161163], + [510911.5390877292, 6651126.395523578, 72.58338931211631], + [510911.2933757172, 6651128.027376986, 73.34114812311628], + [510911.7491322243, 6651125.000549755, 72.05119682911631], + [510911.48075410246, 6651126.782936172, 72.8396024351163], + [510911.3568507498, 6651127.605818644, 73.21899500111631], + [510911.4196555375, 6651127.188711617, 73.05188024411629], + [510910.81229646085, 6651134.827304999, 72.57318280383171], + [510911.7108589428, 6651125.254735068, 72.35956563711629], + [510910.7271148843, 6651135.391896181, 72.9026552048317], + [510911.17221620656, 6651128.832036711, 74.06656083511629], + [510911.66905879654, 6651125.532343438, 72.64766398811629], + [510911.2425124945, 6651128.365176194, 74.02378559411629], + [510911.6241036692, 6651125.830905064, 72.9128617131163], + [510910.8707439787, 6651134.439909572, 72.82939592683171], + [510910.7748910632, 6651135.075231353, 73.1427436518317], + [510911.57642058696, 6651126.147583925, 73.1529501601163], + [510911.3141162017, 6651127.88963268, 73.9346209421163], + [510911.52647837176, 6651126.479266424, 73.3662024951163], + [510911.36809671443, 6651127.531130535, 73.83552544811629], + [510911.47477276606, 6651126.822660171, 73.5514113971163], + [510911.42181099503, 6651127.174396523, 73.7079026891163], + [510910.82493078604, 6651134.7435635505, 73.3559959868317], + [510910.9319618329, 6651134.034152106, 73.0416737358317], + [510912.3523240739, 6651124.619862897, 68.8798954788317], + [510912.4432672205, 6651124.017083507, 68.8798954788317], + [510910.8767373421, 6651134.400185017, 73.5412048888317], + [510910.99488924124, 6651133.61706356, 73.2087884928317], + [510912.34956502385, 6651124.638150129, 69.29071079083171], + [510910.9298025161, 6651134.048464252, 73.6976961808317], + [510911.0584882031, 6651133.195523898, 73.33094161483169], + [510912.44014029705, 6651124.037809039, 69.3454861658317], + [510912.34093710635, 6651124.695336746, 69.71183221883169], + [510911.1217912973, 6651132.775945271, 73.4096163078317], + [510910.98362166894, 6651133.691746046, 73.82531893983169], + [510911.1839385339, 6651132.364027774, 73.44735916683169], + [510912.4303619906, 6651124.102620537, 69.8227571178317], + [510911.0377075736, 6651133.333259786, 73.9244144338317], + [510912.32599532226, 6651124.794372239, 70.1379213538317], + [510911.10945108056, 6651132.857737343, 74.0135790858317], + [510912.3044345275, 6651124.937279135, 70.56282785783169], + [510912.4134279686, 6651124.214860763, 70.3056581378317], + [510911.1798846155, 6651132.3908975115, 74.0563543268317], + [510912.2761255442, 6651125.124913633, 70.97979455983169], + [510911.43958433927, 6651130.669584288, 73.44735916683169], + [510912.3958163176, 6651124.331592378, 70.66736412283171], + [510912.2411430154, 6651125.356780993, 71.3817434768317], + [510912.3739070466, 6651124.476809003, 71.0251219688317], + [510912.1997804874, 6651125.630935564, 71.76162427883169], + [510912.3476975387, 6651124.6505279895, 71.37557818383169], + [510912.16487157793, 6651125.862314968, 72.02803059383169], + [510911.70065748226, 6651128.939167919, 73.44735916683169], + [510912.3172620209, 6651124.8522573495, 71.7153232108317], + [510912.1269481787, 6651126.1136746835, 72.27574033383169], + [510911.7628047189, 6651128.527250421, 73.4096163078317], + [510912.07229955535, 6651126.475890695, 72.57318280383171], + [510911.8261078131, 6651128.107671796, 73.33094161483169], + [510912.01385203755, 6651126.863286121, 72.82939592683171], + [510912.282754143, 6651125.080978681, 72.04099032083171], + [510911.889706775, 6651127.686132133, 73.2087884928317], + [510911.95263418334, 6651127.269043588, 73.0416737358317], + [510912.24440613645, 6651125.335152732, 72.3493591288317], + [510911.70471174974, 6651128.912295869, 74.0563543268317], + [510912.2025243793, 6651125.612748801, 72.6374574798317], + [510911.7751452848, 6651128.445456036, 74.0135790858317], + [510912.1574814811, 6651125.911297198, 72.9026552048317], + [510912.109705302, 6651126.227962027, 73.1427436518317], + [510911.8468887916, 6651127.969933594, 73.9244144338317], + [510912.0596655792, 6651126.55962983, 73.3559959868317], + [510911.90097469627, 6651127.611447334, 73.82531893983169], + [510912.0078590231, 6651126.903008361, 73.5412048888317], + [510911.9547938491, 6651127.2547291275, 73.6976961808317], + [510920.64292734413, 6651138.854801047, 66.84928826316256], + [510920.737281306, 6651138.252546136, 66.84928826316256], + [510920.737281306, 6651138.252546136, 66.97928826316257], + [510920.64292734413, 6651138.854801047, 68.67809192216257], + [510920.7372809439, 6651138.252548446, 68.67809192316255], + [510920.6461715426, 6651138.834093549, 69.14368260916255], + [510920.73798448953, 6651138.248057762, 68.88191320716255], + [510920.7438263221, 6651138.210769743, 69.29849249516256], + [510920.6563165837, 6651138.769338443, 69.62095356116257], + [510920.75600357633, 6651138.13304316, 69.72281961516256], + [510920.67388571467, 6651138.657195876, 70.10385458116257], + [510920.7749104135, 6651138.012362106, 70.14912996616256], + [510920.6921578893, 6651138.54056583, 70.46556056616257], + [510920.7148888657, 6651138.395475556, 70.82331841216256], + [510920.80077640404, 6651137.847261251, 70.57093882516256], + [510920.742081359, 6651138.221907725, 71.17377462716257], + [510920.83363272325, 6651137.637541602, 70.98128836816258], + [510920.77365835843, 6651138.020353888, 71.51351965416256], + [510920.87328934215, 6651137.384416107, 71.37306806216256], + [510920.80946045154, 6651137.791831567, 71.83918676416256], + [510920.9072509745, 6651137.16764132, 71.65054992216255], + [510920.84924669686, 6651137.5378786735, 72.14755557216256], + [510920.9445482108, 6651136.9295756025, 71.91099059516256], + [510922.6255939815, 6651126.199574968, 66.84928826316256], + [510922.6255939815, 6651126.199574968, 66.97928826316257], + [510920.8926992259, 6651137.26052414, 72.43565392316256], + [510920.98485916905, 6651136.672273502, 72.15196024116256], + [510922.71994794323, 6651125.597320058, 66.84928826316256], + [510921.02780775895, 6651136.398135577, 72.37137924716257], + [510920.9394314543, 6651136.962235509, 72.70085164816255], + [510921.08844734606, 6651136.011077224, 72.62759237016256], + [510920.988999475, 6651136.64584621, 72.94094009516256], + [510921.04091593355, 6651136.314466992, 73.15419243016257], + [510921.151961171, 6651135.6056728065, 72.83987017916256], + [510921.09466549027, 6651135.9713872345, 73.33940133216257], + [510921.2172486666, 6651135.188947171, 73.00698493616255], + [510922.6255939815, 6651126.199574968, 68.67809192216257], + [510921.1497208692, 6651135.6199725, 73.49589262416256], + [510921.28323290235, 6651134.767774289, 73.12913805816257], + [510922.71994794323, 6651125.597320058, 68.67809192216257], + [510922.62273145345, 6651126.217846289, 69.08890723416256], + [510921.20555850497, 6651135.263564675, 73.62351538316257], + [510921.3489101739, 6651134.348560738, 73.20781275116256], + [510922.71670374484, 6651125.618027556, 69.14368260916255], + [510922.61377994664, 6651126.274983148, 69.51002866216255], + [510921.4133882375, 6651133.937001651, 73.24555561016255], + [510921.2616728971, 6651134.905390334, 73.72261087716257], + [510921.33610713837, 6651134.430281643, 73.81177552916256], + [510922.59827777214, 6651126.3739324715, 69.93611779716255], + [510922.70655870374, 6651125.682782662, 69.62095356116257], + [510921.4091822772, 6651133.963848009, 73.85455077016256], + [510922.5759083416, 6651126.516715024, 70.36102430116256], + [510922.68898957275, 6651125.794925229, 70.10385458116257], + [510921.6786220178, 6651132.2440325, 73.24555561016255], + [510922.5465376321, 6651126.70418626, 70.77799100316255], + [510922.6707173981, 6651125.911555273, 70.46556056616257], + [510922.51024308644, 6651126.935851873, 71.17993992016255], + [510922.6479864217, 6651126.056645547, 70.82331841216256], + [510922.4673292602, 6651127.209767902, 71.55982072216257], + [510921.94948668766, 6651130.5151217645, 73.24555561016255], + [510922.62079392845, 6651126.23021338, 71.17377462716257], + [510922.43111109495, 6651127.440945984, 71.82622703716255], + [510922.0139647514, 6651130.103562677, 73.20781275116256], + [510922.39176538173, 6651127.692086992, 72.07393677716257], + [510922.589216929, 6651126.431767216, 71.51351965416256], + [510922.0796420229, 6651129.684349127, 73.12913805816257], + [510922.33506716625, 6651128.053987837, 72.37137924716257], + [510922.14562625857, 6651129.263176247, 73.00698493616255], + [510922.27442757913, 6651128.441046191, 72.62759237016256], + [510922.2109137543, 6651128.846450608, 72.83987017916256], + [510922.55341483594, 6651126.660289537, 71.83918676416256], + [510921.95369301015, 6651130.488273094, 73.85455077016256], + [510922.5136285905, 6651126.9142424315, 72.14755557216256], + [510922.47017606156, 6651127.191596963, 72.43565392316256], + [510922.0267681491, 6651130.021839462, 73.81177552916256], + [510922.4234438331, 6651127.489885594, 72.70085164816255], + [510922.10120239033, 6651129.546730771, 73.72261087716257], + [510922.37387581245, 6651127.806274893, 72.94094009516256], + [510922.1573167824, 6651129.188556428, 73.62351538316257], + [510922.32195935387, 6651128.137654111, 73.15419243016257], + [510922.2131544181, 6651128.832148603, 73.49589262416256], + [510922.2682097972, 6651128.4807338705, 73.33940133216257], + [510927.01434431603, 6651139.864548177, 66.71807430255812], + [510927.1108285054, 6651139.262630868, 66.71807430255812], + [510927.1108285054, 6651139.262630868, 66.8480743025581], + [510927.01434431603, 6651139.864548177, 68.54687796155812], + [510927.1108281352, 6651139.2626331765, 68.5468779625581], + [510927.01766175864, 6651139.843852287, 69.0124686485581], + [510927.11154756474, 6651139.258145011, 68.75069924655811], + [510927.11752128834, 6651139.220877892, 69.16727853455812], + [510927.02803584404, 6651139.77913348, 69.48973960055811], + [510927.129973468, 6651139.143194879, 69.59160565455811], + [510927.046001633, 6651139.667053777, 69.97264062055812], + [510927.1493071646, 6651139.022581476, 70.0179160055581], + [510927.0646863382, 6651139.550489109, 70.33434660555811], + [510927.0879305114, 6651139.405480167, 70.69210445155811], + [510927.17575713113, 6651138.857573168, 70.43972486455812], + [510927.1157369292, 6651139.23200963, 71.0425606665581], + [510927.20935524686, 6651138.647971082, 70.85007440755811], + [510927.14802684187, 6651139.030568777, 71.38230569355812], + [510927.2499071924, 6651138.394987477, 71.2418541015581], + [510927.18463723816, 6651138.802174556, 71.7079728035581], + [510927.2846355759, 6651138.178334206, 71.5193359615581], + [510927.2253217368, 6651138.548364019, 72.0163416115581], + [510927.32277487125, 6651137.940401938, 71.7797766345581], + [510927.2697552928, 6651138.271164959, 72.30443996255812], + [510927.36399592925, 6651137.683244072, 72.02074628055811], + [510929.0417735806, 6651127.216416116, 66.71807430255812], + [510929.0417735806, 6651127.216416116, 66.8480743025581], + [510927.40791416867, 6651137.409259818, 72.24016528655811], + [510929.1382577701, 6651126.614498805, 66.71807430255812], + [510927.3175425938, 6651137.973043539, 72.5696376875581], + [510927.3682297108, 6651137.656831594, 72.8097261345581], + [510927.4699228147, 6651137.022418435, 72.4963784095581], + [510927.4213182863, 6651137.325638134, 73.02297846955811], + [510927.53487058997, 6651136.61724127, 72.7086562185581], + [510927.4762813457, 6651136.982750693, 73.20818737155811], + [510927.6016320801, 6651136.200749233, 72.87577097555811], + [510927.53257970896, 6651136.6315329475, 73.36467866355811], + [510929.0417735806, 6651127.216416116, 68.54687796155812], + [510927.6691060406, 6651135.779812445, 72.9979240975581], + [510927.5896779899, 6651136.275324911, 73.4923014225581], + [510929.1382577701, 6651126.614498805, 68.54687796155812], + [510927.73626610683, 6651135.360833889, 73.07659879055812], + [510929.03884642536, 6651127.234677196, 68.9576932735581], + [510927.64705927565, 6651135.917351346, 73.59139691655812], + [510927.8021998904, 6651134.949505504, 73.11434164955811], + [510929.1349403274, 6651126.635194695, 69.0124686485581], + [510929.02969282056, 6651127.291782024, 69.3788147015581], + [510927.7231740173, 6651135.442508983, 73.6805615685581], + [510929.0138406538, 6651127.390675882, 69.80490383655811], + [510927.79789897223, 6651134.9763368135, 73.7233368095581], + [510929.124566242, 6651126.699913502, 69.48973960055811], + [510928.0734218488, 6651133.257485365, 73.11434164955811], + [510928.99096618895, 6651127.533378394, 70.22981034055812], + [510929.10660045303, 6651126.811993206, 69.97264062055812], + [510928.96093237755, 6651127.720744543, 70.6467770425581], + [510929.08791574783, 6651126.928557873, 70.33434660555811], + [510928.9238184106, 6651127.952280293, 71.0487259595581], + [510929.0646715746, 6651127.073566816, 70.69210445155811], + [510928.3504018253, 6651131.529543788, 73.11434164955811], + [510928.8799357197, 6651128.226042776, 71.4286067615581], + [510929.03686515684, 6651127.247037352, 71.0425606665581], + [510928.84289985773, 6651128.457091268, 71.69501307655811], + [510928.41633560887, 6651131.118215404, 73.07659879055812], + [510928.80266583705, 6651128.708091495, 71.9427228165581], + [510928.483495675, 6651130.699236848, 72.9979240975581], + [510929.00457524415, 6651127.448478205, 71.38230569355812], + [510928.7446875469, 6651129.069789475, 72.24016528655811], + [510928.5509696356, 6651130.278300061, 72.87577097555811], + [510928.682678901, 6651129.456630859, 72.4963784095581], + [510928.6177311257, 6651129.8618080225, 72.7086562185581], + [510928.96796484786, 6651127.676872426, 71.7079728035581], + [510928.3547031138, 6651131.502710169, 73.7233368095581], + [510928.9272803492, 6651127.930682964, 72.0163416115581], + [510928.42942806875, 6651131.036537999, 73.6805615685581], + [510928.8828467932, 6651128.207882023, 72.30443996255812], + [510928.50554281037, 6651130.561695635, 73.59139691655812], + [510928.83505949215, 6651128.506003444, 72.5696376875581], + [510928.5629240961, 6651130.203722072, 73.4923014225581], + [510928.78437237523, 6651128.822215388, 72.8097261345581], + [510928.62002237706, 6651129.847514034, 73.36467866355811], + [510928.73128379975, 6651129.153408848, 73.02297846955811], + [510928.6763207404, 6651129.496296291, 73.20818737155811], + [510929.77274426864, 6651140.308873249, 66.66002999750813], + [510929.870150705, 6651139.707104495, 66.66002999750813], + [510929.870150705, 6651139.707104495, 66.79002999750811], + [510929.77274426864, 6651140.308873249, 68.48883365650812], + [510929.87015033123, 6651139.7071068045, 68.48883365750811], + [510929.7760934212, 6651140.288182467, 68.95442434350811], + [510929.87087663746, 6651139.702619746, 68.69265494150811], + [510929.8769074611, 6651139.665361826, 69.10923422950813], + [510929.7865666676, 6651140.223479633, 69.43169529550813], + [510929.88947866537, 6651139.587697985, 69.53356134950812], + [510929.804704183, 6651140.111427591, 69.91459631550813], + [510929.9089971635, 6651139.467114348, 69.95987170050812], + [510929.8235674865, 6651139.994891694, 70.27630230050812], + [510929.8470338399, 6651139.84991854, 70.63406014650812], + [510929.9356999528, 6651139.302146767, 70.38168055950811], + [510929.87510604603, 6651139.676490816, 70.98451636150811], + [510929.96961921715, 6651139.092596412, 70.79203010250812], + [510929.9077046028, 6651139.475099679, 71.32426138850812], + [510930.01055877964, 6651138.839675245, 71.18380979650811], + [510929.9446649406, 6651139.246761828, 71.64992849850812], + [510930.04561911547, 6651138.623075444, 71.46129165650811], + [510929.9857383233, 6651138.993013931, 71.95829730650811], + [510930.08412296633, 6651138.385201898, 71.72173232950811], + [510930.03059659875, 6651138.715883288, 72.24639565750813], + [510930.12573803705, 6651138.1281075, 71.96270197550812], + [510931.81955277483, 6651127.6638628105, 66.66002999750813], + [510931.81955277483, 6651127.6638628105, 66.79002999750811], + [510930.17007607024, 6651137.854190868, 72.18212098150812], + [510930.07884067605, 6651138.417835443, 72.51159338250811], + [510931.9169592113, 6651127.062094056, 66.66002999750813], + [510930.13001228723, 6651138.101701542, 72.75168182950812], + [510930.2326774276, 6651137.467444957, 72.43833410450812], + [510930.1836083114, 6651137.770589822, 72.96493416450812], + [510930.2982460081, 6651137.062367794, 72.65061191350811], + [510930.2390967368, 6651137.427787006, 73.15014306650812], + [510930.36564563995, 6651136.645978549, 72.81772667050811], + [510930.2959332297, 6651137.076655945, 73.30663435850812], + [510930.43376455235, 6651136.22514565, 72.93987979250812], + [510931.81955277483, 6651127.6638628105, 68.48883365650812], + [510930.3535772863, 6651136.720535822, 73.43425711750811], + [510930.50156656984, 6651135.8062705, 73.01855448550813], + [510931.9169592113, 6651127.062094056, 68.48883365650812], + [510931.81659764034, 6651127.682119383, 68.89964896850812], + [510930.41150705266, 6651136.362650607, 73.53335261150812], + [510930.5681305835, 6651135.395043635, 73.05629734450812], + [510931.9136100587, 6651127.082784838, 68.95442434350811], + [510931.8073565405, 6651127.739210118, 69.32077039650812], + [510930.48834933934, 6651135.887925437, 73.62251726350812], + [510930.56378855486, 6651135.421868321, 73.66529250450812], + [510931.7913528504, 6651127.838079567, 69.74685953150811], + [510931.9031368123, 6651127.147487671, 69.43169529550813], + [510930.8419450249, 6651133.703441093, 73.05629734450812], + [510931.7682597393, 6651127.980746861, 70.17176603550811], + [510931.8849992968, 6651127.259539713, 69.91459631550813], + [510931.7379388489, 6651128.168066767, 70.58873273750811], + [510931.86613599333, 6651127.376075613, 70.27630230050812], + [510931.70047012705, 6651128.3995453715, 70.99068165450811], + [510931.84266963997, 6651127.521048766, 70.63406014650812], + [510931.12157252245, 6651131.975925981, 73.05629734450812], + [510931.65616798215, 6651128.67324029, 71.37056245650811], + [510931.8145974338, 6651127.69447649, 70.98451636150811], + [510931.18813653616, 6651131.564699115, 73.01855448550813], + [510931.61877811176, 6651128.904231757, 71.63696877150811], + [510931.578159513, 6651129.1551700365, 71.88467851150811], + [510931.25593855366, 6651131.145823965, 72.93987979250812], + [510931.78199887706, 6651127.895867626, 71.32426138850812], + [510931.5196270357, 6651129.516778748, 72.18212098150812], + [510931.32405746606, 6651130.724991065, 72.81772667050811], + [510931.45702567836, 6651129.903524657, 72.43833410450812], + [510931.39145709784, 6651130.308601822, 72.65061191350811], + [510931.74503853923, 6651128.1242054785, 71.64992849850812], + [510931.12591492495, 6651131.949098984, 73.66529250450812], + [510931.7039651566, 6651128.377953374, 71.95829730650811], + [510931.2013541406, 6651131.483041869, 73.62251726350812], + [510931.6591068812, 6651128.655084019, 72.24639565750813], + [510931.2781964273, 6651131.008316698, 73.53335261150812], + [510931.6108628039, 6651128.953131862, 72.51159338250811], + [510931.33612619364, 6651130.650431485, 73.43425711750811], + [510931.55969119264, 6651129.269265763, 72.75168182950812], + [510931.39377025014, 6651130.294311362, 73.30663435850812], + [510931.5060951684, 6651129.600377483, 72.96493416450812], + [510931.450606743, 6651129.943180299, 73.15014306650812], + [510937.5192634639, 6651141.579897319, 66.49301605051268], + [510937.6192598813, 6651140.9785535205, 66.49301605051268], + [510937.6192598813, 6651140.9785535205, 66.62301605051267], + [510937.5192634639, 6651141.579897319, 68.32181970951268], + [510937.6192594977, 6651140.978555827, 68.32181971051267], + [510937.5227016685, 6651141.5592211485, 68.78741039651267], + [510937.6200051159, 6651140.974071938, 68.52564099451267], + [510937.62619629566, 6651140.936840328, 68.94222028251268], + [510937.5334533925, 6651141.494564006, 69.26468134851268], + [510937.639101761, 6651140.859231332, 69.36654740251268], + [510937.55207317404, 6651141.382591093, 69.74758236851268], + [510937.65913924476, 6651140.738732849, 69.79285775351269], + [510937.5714380419, 6651141.26613749, 70.10928835351268], + [510937.595528352, 6651141.121266712, 70.46704619951268], + [510937.68655204587, 6651140.573881765, 70.21466661251267], + [510937.62434698205, 6651140.947961461, 70.81750241451267], + [510937.72137320385, 6651140.364479389, 70.62501615551268], + [510937.6578123157, 6651140.746712541, 71.15724744151268], + [510937.76340132585, 6651140.111736829, 71.01679584951269], + [510937.69575540756, 6651140.518535936, 71.48291455151268], + [510937.79939389566, 6651139.895289987, 71.29427770951267], + [510937.7379209078, 6651140.264967231, 71.79128335951268], + [510937.8389215418, 6651139.657584422, 71.55471838251268], + [510937.78397193894, 6651139.988032291, 72.07938171051268], + [510937.8816431333, 6651139.400671579, 71.79568802851267], + [510937.92716008925, 6651139.126948379, 72.01510703451268], + [510937.8334987985, 6651139.6901949225, 72.34457943551267], + [510939.62049542944, 6651128.943816506, 66.49301605051268], + [510939.62049542944, 6651128.943816506, 66.62301605051267], + [510937.88603103335, 6651139.374284267, 72.58466788251268], + [510939.7204918468, 6651128.342472709, 66.49301605051268], + [510937.9914259807, 6651138.740475582, 72.27132015751268], + [510937.9410521449, 6651139.043406372, 72.7979202175127], + [510938.058737992, 6651138.335684474, 72.48359796651268], + [510937.9980159757, 6651138.7008456355, 72.98312911951268], + [510938.1279297412, 6651137.919589275, 72.65071272351267], + [510938.05636371806, 6651138.349962533, 73.1396204115127], + [510938.19785989623, 6651137.499053558, 72.77286584551268], + [510938.11554049695, 6651137.994093895, 73.26724317051267], + [510939.62049542944, 6651128.943816506, 68.32181970951268], + [510938.2674647303, 6651137.080474208, 72.85154053851268], + [510938.1750105824, 6651137.636461412, 73.36633866451268], + [510938.3357986428, 6651136.669537742, 72.88928339751267], + [510939.7204918468, 6651128.342472709, 68.32181970951268], + [510939.61746171955, 6651128.962060186, 68.73263502151268], + [510938.2538960613, 6651137.162071481, 73.45550331651269], + [510939.7170536422, 6651128.363148879, 68.78741039651267], + [510939.6079749042, 6651129.019110605, 69.15375644951267], + [510938.33134116215, 6651136.696343485, 73.49827855751268], + [510939.59154568514, 6651129.117910235, 69.57984558451267], + [510938.6168936525, 6651134.979129774, 72.88928339751267], + [510939.70630191825, 6651128.427806021, 69.26468134851268], + [510939.5678385415, 6651129.26047678, 70.00475208851269], + [510939.68768213666, 6651128.539778934, 69.74758236851268], + [510939.5367114361, 6651129.447664404, 70.42171879051267], + [510939.6683172688, 6651128.656232538, 70.10928835351268], + [510939.4982464425, 6651129.678979545, 70.82366770751267], + [510938.90395628416, 6651133.252834594, 72.88928339751267], + [510939.6442269587, 6651128.801103313, 70.46704619951268], + [510939.45276632905, 6651129.952481185, 71.20354850951267], + [510938.9722901965, 6651132.8418981265, 72.85154053851268], + [510939.4143822835, 6651130.183309532, 71.46995482451268], + [510939.61540832865, 6651128.974408567, 70.81750241451267], + [510939.0418950307, 6651132.423318778, 72.77286584551268], + [510939.37268365966, 6651130.434070605, 71.71766456451267], + [510939.1118251857, 6651132.002783062, 72.65071272351267], + [510939.31259483757, 6651130.795423956, 72.01510703451268], + [510939.1810169349, 6651131.586687861, 72.48359796651268], + [510939.2483289461, 6651131.181896754, 72.27132015751268], + [510939.581942995, 6651129.175657485, 71.15724744151268], + [510938.90841414867, 6651133.2260265425, 73.49827855751268], + [510939.54399990314, 6651129.40383409, 71.48291455151268], + [510938.98585924954, 6651132.760298545, 73.45550331651269], + [510939.50183440285, 6651129.657402795, 71.79128335951268], + [510939.0647447283, 6651132.285908615, 73.36633866451268], + [510939.45578337176, 6651129.934337736, 72.07938171051268], + [510939.12421481375, 6651131.928276133, 73.26724317051267], + [510939.4062565123, 6651130.232175105, 72.34457943551267], + [510939.18339159264, 6651131.572407492, 73.1396204115127], + [510939.35372427735, 6651130.54808576, 72.58466788251268], + [510939.241739335, 6651131.221524391, 72.98312911951268], + [510939.2987031657, 6651130.878963656, 72.7979202175127], + [510943.5629395488, 6651142.59533044, 66.35860467732431], + [510943.6649566165, 6651141.9943261435, 66.35860467732431], + [510943.6649566165, 6651141.9943261435, 66.4886046773243], + [510943.5629395488, 6651142.59533044, 68.18740833632432], + [510943.66495622514, 6651141.994328449, 68.1874083373243], + [510943.56644723, 6651142.574665943, 68.6529990233243], + [510943.66571691027, 6651141.98984709, 68.39122962132431], + [510943.5774162165, 6651142.510045304, 69.13026997532431], + [510943.67203319655, 6651141.952636503, 68.80780890932432], + [510943.6851994456, 6651141.875071323, 69.23213602932431], + [510943.5964122523, 6651142.398135608, 69.61317099532432], + [510943.70564183145, 6651141.754640868, 69.65844638032432], + [510943.61616843037, 6651142.28174775, 69.97487698032431], + [510943.6407455389, 6651142.136958764, 70.33263482632431], + [510943.73360856925, 6651141.5898828525, 70.08025523932432], + [510943.6701465135, 6651141.963751353, 70.6830910413243], + [510943.76913336624, 6651141.380598699, 70.49060478232431], + [510943.7042880887, 6651141.762616056, 71.02283606832432], + [510943.81201075995, 6651141.127998831, 70.8823844763243], + [510943.7429979053, 6651141.534568272, 71.34850317832431], + [510943.84873063985, 6651140.911674188, 71.1598663363243], + [510943.78601545334, 6651141.281142725, 71.6568719863243], + [510943.88905703014, 6651140.674102826, 71.4203070093243], + [510943.8329970481, 6651141.004364133, 71.9449703373243], + [510943.9326419065, 6651140.417335027, 71.6612766553243], + [510943.9790786339, 6651140.143766365, 71.88069566132431], + [510943.8835247082, 6651140.706694915, 72.2101680623243], + [510945.70663158584, 6651129.966383592, 66.35860467732431], + [510943.9371184739, 6651140.390962614, 72.4502565093243], + [510944.04464316077, 6651139.757511758, 72.1369087843243], + [510945.70663158584, 6651129.966383592, 66.4886046773243], + [510945.8086486536, 6651129.365379294, 66.35860467732431], + [510943.99325140956, 6651140.060271521, 72.66350884432433], + [510944.11331536114, 6651139.352949184, 72.3491865933243], + [510944.0513663213, 6651139.717904185, 72.84871774632431], + [510944.18390528375, 6651138.937088898, 72.51630135032431], + [510944.1108931098, 6651139.367219183, 73.00520903832431], + [510944.2552485334, 6651138.516790605, 72.6384544723243], + [510944.1712656873, 6651139.0115514565, 73.1328317973243], + [510944.3262598882, 6651138.098447572, 72.71712916532432], + [510945.70663158584, 6651129.966383592, 68.18740833632432], + [510944.2319374983, 6651138.654120883, 73.23192729132433], + [510944.39597463945, 6651137.687743109, 72.75487202432431], + [510945.8086486536, 6651129.365379294, 68.18740833632432], + [510944.3124170339, 6651138.179998779, 73.32109194332432], + [510945.70353657304, 6651129.984616972, 68.5982236483243], + [510944.39142708544, 6651137.714533719, 73.3638671843243], + [510945.6938580555, 6651130.041635182, 69.0193450763243], + [510945.80514097237, 6651129.386043793, 68.6529990233243], + [510944.68274979986, 6651135.998289496, 72.75487202432431], + [510945.67709684744, 6651130.140379032, 69.44543421132431], + [510945.7941719858, 6651129.450664431, 69.13026997532431], + [510945.65291064826, 6651130.2828650875, 69.87034071532432], + [510945.7751759502, 6651129.562574126, 69.61317099532432], + [510945.6211545503, 6651130.469947032, 70.2873074173243], + [510945.755419772, 6651129.678961985, 69.97487698032431], + [510944.9756131713, 6651134.272968933, 72.75487202432431], + [510945.58191228594, 6651130.7011315795, 70.6892563343243], + [510945.7308426635, 6651129.82375097, 70.33263482632431], + [510945.04532792256, 6651133.862264468, 72.71712916532432], + [510945.53551314556, 6651130.974478807, 71.0691371363243], + [510945.49635346484, 6651131.205176835, 71.33554345132431], + [510945.1163392775, 6651133.443921437, 72.6384544723243], + [510945.70144168887, 6651129.9969583815, 70.6830910413243], + [510945.45381222747, 6651131.455796335, 71.5832531913243], + [510945.187682527, 6651133.023623142, 72.51630135032431], + [510945.39250917686, 6651131.816945677, 71.88069566132431], + [510945.2582724496, 6651132.607762857, 72.3491865933243], + [510945.3269446499, 6651132.203200284, 72.1369087843243], + [510944.9801611169, 6651134.246176015, 73.3638671843243], + [510945.6673001137, 6651130.19809368, 71.02283606832432], + [510945.62859029707, 6651130.426141462, 71.34850317832431], + [510945.05917116854, 6651133.780710955, 73.32109194332432], + [510945.58557274897, 6651130.679567009, 71.6568719863243], + [510945.1396507041, 6651133.306588852, 73.23192729132433], + [510945.5385911543, 6651130.956345601, 71.9449703373243], + [510945.20032251516, 6651132.949158277, 73.1328317973243], + [510945.48806349415, 6651131.254014821, 72.2101680623243], + [510945.2606950926, 6651132.593490551, 73.00520903832431], + [510945.4344697285, 6651131.56974712, 72.4502565093243], + [510945.32022188103, 6651132.242805549, 72.84871774632431], + [510945.37833679287, 6651131.900438213, 72.66350884432433], + [510949.59877879947, 6651143.630311312, 66.2207633583812], + [510949.70281389734, 6651143.029653051, 66.2207633583812], + [510949.70281389734, 6651143.029653051, 66.3507633583812], + [510949.59877879947, 6651143.630311312, 68.04956701738121], + [510949.70281349815, 6651143.029655356, 68.0495670183812], + [510949.60235586704, 6651143.609658713, 68.5151577043812], + [510949.70358923066, 6651143.025176579, 68.2533883023812], + [510949.61354183446, 6651143.545075281, 68.99242865638121], + [510949.71003046125, 6651142.987987413, 68.6699675903812], + [510949.72345715575, 6651142.910466894, 69.0942947103812], + [510949.63291363645, 6651143.433230017, 69.47532967638121], + [510949.6530606174, 6651143.316909172, 69.83703566138121], + [510949.7443039185, 6651142.790105779, 69.5206050613812], + [510949.6781238931, 6651143.172203549, 70.1947935073812], + [510949.7728238748, 6651142.625442625, 69.9424139203812], + [510949.7081064571, 6651142.999095866, 70.5452497223812], + [510949.8090513985, 6651142.4162789695, 70.35276346338122], + [510949.7429233971, 6651142.7980763735, 70.8849947493812], + [510949.8527769627, 6651142.163824541, 70.7445431573812], + [510949.78239894414, 6651142.570159893, 71.2106618593812], + [510949.8902232096, 6651141.947624451, 71.0220250173812], + [510949.8262674352, 6651142.316880259, 71.5190306673812], + [510949.9313473083, 6651141.7101898715, 71.2824656903812], + [510949.8741783869, 6651142.040261026, 71.8071290183812], + [510949.97579435, 6651141.4535699105, 71.5234353363812], + [510949.9257055497, 6651141.742763194, 72.07232674338121], + [510950.0231496563, 6651141.180158759, 71.74285434238121], + [510949.9803594697, 6651141.427212682, 72.31241519038122], + [510950.09001113474, 6651140.794126544, 71.99906746538122], + [510951.78487584996, 6651131.008635759, 66.2207633583812], + [510951.78487584996, 6651131.008635759, 66.3507633583812], + [510950.0376027878, 6651141.0967119895, 72.52566752538121], + [510950.16004176036, 6651140.389796902, 72.2113452743812], + [510951.88891094783, 6651130.4079775, 66.2207633583812], + [510950.09686728806, 6651140.754541776, 72.71087642738121], + [510950.23202804336, 6651139.974176056, 72.3784600313812], + [510950.1575715937, 6651140.4040586855, 72.8673677193812], + [510950.30478255503, 6651139.554119755, 72.50061315338122], + [510950.2191384192, 6651140.04859574, 72.9949904783812], + [510950.37719860673, 6651139.136017589, 72.5792878463812], + [510950.2810103975, 6651139.691370961, 73.09408597238121], + [510950.4482924064, 6651138.725549594, 72.6170307053812], + [510951.78487584996, 6651131.008635759, 68.04956701738121], + [510950.3630819228, 6651139.217521841, 73.1832506243812], + [510951.88891094783, 6651130.4079775, 68.04956701738121], + [510951.7817196139, 6651131.026858642, 68.4603823293812], + [510950.4436548959, 6651138.7523247795, 73.2260258653812], + [510951.77184964257, 6651131.083844024, 68.8815037573812], + [510951.88533388014, 6651130.428630099, 68.5151577043812], + [510950.7407403521, 6651137.037068709, 72.6170307053812], + [510951.7547568761, 6651131.18253102, 69.30759289238121], + [510951.87414791284, 6651130.493213531, 68.99242865638121], + [510951.7300922425, 6651131.324935039, 69.7324993963812], + [510951.85477611085, 6651130.605058793, 69.47532967638121], + [510951.6977079677, 6651131.511909266, 70.1494660983812], + [510951.0393969415, 6651135.312741524, 72.6170307053812], + [510951.8346291299, 6651130.721379639, 69.83703566138121], + [510951.6576894403, 6651131.742960705, 70.5514150153812], + [510951.1104907411, 6651134.902273528, 72.5792878463812], + [510951.8095658542, 6651130.866085261, 70.1947935073812], + [510951.6103724646, 6651132.01615055, 70.93129581738121], + [510951.18290679285, 6651134.484171363, 72.50061315338122], + [510951.5704381546, 6651132.2467157515, 71.1977021323812], + [510951.7795832901, 6651131.039192946, 70.5452497223812], + [510951.2556613045, 6651134.064115061, 72.3784600313812], + [510951.5270553962, 6651132.497190952, 71.44541187238121], + [510951.3276475875, 6651133.648494214, 72.2113452743812], + [510951.4645396917, 6651132.858132358, 71.74285434238121], + [510951.0440348513, 6651135.285964033, 73.2260258653812], + [510951.39767821325, 6651133.244164573, 71.99906746538122], + [510951.7447663502, 6651131.240212437, 70.8849947493812], + [510951.12460782443, 6651134.82076697, 73.1832506243812], + [510951.70529080316, 6651131.468128918, 71.2106618593812], + [510951.2066793498, 6651134.346917849, 73.09408597238121], + [510951.6614223121, 6651131.7214085525, 71.5190306673812], + [510951.2685513281, 6651133.98969307, 72.9949904783812], + [510951.61351136037, 6651131.998027785, 71.8071290183812], + [510951.3301181535, 6651133.634230126, 72.8673677193812], + [510951.5619841975, 6651132.295525616, 72.07232674338121], + [510951.39082245925, 6651133.283747035, 72.71087642738121], + [510951.50733027747, 6651132.611076129, 72.31241519038122], + [510951.45008695946, 6651132.941576822, 72.52566752538121], + [510954.3693079373, 6651144.463102438, 66.10926455844026], + [510954.4749380199, 6651143.862722614, 66.10926455844026], + [510954.4749380199, 6651143.862722614, 66.23926455844025], + [510954.3693079373, 6651144.463102438, 67.93806821744026], + [510954.4749376146, 6651143.862724918, 67.93806821844025], + [510954.3729398458, 6651144.442459412, 68.40365890444025], + [510954.4757252401, 6651143.858248216, 68.14188950244025], + [510954.38429730764, 6651144.377905917, 68.88092985644026], + [510954.4822652226, 6651143.821076291, 68.55846879044026], + [510954.4958977647, 6651143.743591704, 68.98279591044026], + [510954.4039661029, 6651144.266112501, 69.36383087644026], + [510954.4244219616, 6651144.149845576, 69.72553686144026], + [510954.51706413366, 6651143.623286384, 69.40910626144027], + [510954.4498694878, 6651144.005207032, 70.08329470744026], + [510954.5460213355, 6651143.458699561, 69.83091512044025], + [510954.48031172116, 6651143.832179594, 70.43375092244025], + [510954.58280427137, 6651143.249632864, 70.24126466344026], + [510954.5156624472, 6651143.631253284, 70.77349594944026], + [510954.62720020174, 6651142.99729546, 70.63304435744027], + [510954.55574320245, 6651143.4034424545, 71.09916305944026], + [510954.66522054514, 6651142.781195589, 70.91052621744025], + [510954.60028425086, 6651143.150280228, 71.40753186744026], + [510954.7069751263, 6651142.543871074, 71.17096689044025], + [510954.6489297359, 6651142.873789223, 71.69563021844026], + [510954.75210359547, 6651142.28737007, 71.41193653644025], + [510954.70124687284, 6651142.576429299, 71.96082794344025], + [510954.80018491624, 6651142.01408566, 71.63135554244026], + [510954.75673870405, 6651142.261025059, 72.20091639044026], + [510954.86807146255, 6651141.62823239, 71.88756866544026], + [510954.8148596318, 6651141.930677571, 72.41416872544028], + [510956.58892051806, 6651131.847277692, 66.10926455844026], + [510954.939175743, 6651141.224090176, 72.09984647444026], + [510956.58892051806, 6651131.847277692, 66.23926455844025], + [510956.69455060066, 6651131.246897866, 66.10926455844026], + [510954.875032729, 6651141.5886659715, 72.59937762744026], + [510955.01226566336, 6651140.808661992, 72.26696123144026], + [510954.93666770565, 6651141.238345348, 72.75586891944027], + [510955.0861355904, 6651140.388800407, 72.38911435344025], + [510954.9991784255, 6651140.883047179, 72.88349167844027], + [510955.1596618683, 6651139.970892055, 72.46778904644026], + [510955.0619989766, 6651140.525987992, 72.98258717244026], + [510955.2318456225, 6651139.560614333, 72.50553190544025], + [510956.58892051806, 6651131.847277692, 67.93806821744026], + [510955.14532875834, 6651140.052358526, 73.07175182444027], + [510955.2271370133, 6651139.587377106, 73.11452706544026], + [510956.69455060066, 6651131.246897866, 67.93806821744026], + [510956.5857158929, 6651131.865492125, 68.34888352944026], + [510956.5756946031, 6651131.922451091, 68.77000495744025], + [510955.5287771513, 6651137.872916145, 72.50553190544025], + [510956.69091869215, 6651131.2675408935, 68.40365890444025], + [510956.5583397836, 6651132.021092342, 69.19609409244028], + [510956.6795612303, 6651131.332094387, 68.88092985644026], + [510956.5332970111, 6651132.163430348, 69.62100059644025], + [510956.659892435, 6651131.443887804, 69.36383087644026], + [510956.50041624595, 6651132.350317904, 70.03796729844025], + [510955.8320125099, 6651136.149388276, 72.50553190544025], + [510956.6394365763, 6651131.560154729, 69.72553686144026], + [510956.45978418575, 6651132.581262238, 70.43991621544025], + [510955.9041962641, 6651135.739110555, 72.46778904644026], + [510956.61398905015, 6651131.704793272, 70.08329470744026], + [510956.41174178326, 6651132.854325446, 70.81979701744025], + [510955.9777225421, 6651135.321202202, 72.38911435344025], + [510956.37119523156, 6651133.084783768, 71.08620333244025], + [510956.05159246904, 6651134.90134062, 72.26696123144026], + [510956.32714736264, 6651133.335142861, 71.33391307244025], + [510956.58354681684, 6651131.877820711, 70.43375092244025], + [510955.83672152465, 6651136.122623199, 73.11452706544026], + [510956.1246823895, 6651134.485912433, 72.09984647444026], + [510956.2636732163, 6651133.695916952, 71.63135554244026], + [510956.19578666997, 6651134.081770221, 71.88756866544026], + [510956.54819609073, 6651132.07874702, 70.77349594944026], + [510955.9185297795, 6651135.65764178, 73.07175182444027], + [510956.5081153355, 6651132.30655785, 71.09916305944026], + [510956.00185956137, 6651135.184012312, 72.98258717244026], + [510956.4635742871, 6651132.559720077, 71.40753186744026], + [510956.0646801124, 6651134.826953126, 72.88349167844027], + [510956.41492880206, 6651132.836211082, 71.69563021844026], + [510956.1271908323, 6651134.471654956, 72.75586891944027], + [510956.3626116651, 6651133.133571006, 71.96082794344025], + [510956.18882580893, 6651134.121334333, 72.59937762744026], + [510956.3071198339, 6651133.448975246, 72.20091639044026], + [510956.24899890606, 6651133.779322733, 72.41416872544028], + [510960.08571448433, 6651145.47822558, 65.97268294412484], + [510960.1932557976, 6651144.878185154, 65.97268294412484], + [510960.1932557976, 6651144.878185154, 66.10268294412484], + [510960.08571448433, 6651145.47822558, 67.80148660312486], + [510960.19325538503, 6651144.878187455, 67.80148660412483], + [510960.0894121072, 6651145.457594223, 68.26707729012483], + [510960.1940572614, 6651144.873713284, 68.00530788812485], + [510960.1009750667, 6651145.393077222, 68.74434824212484], + [510960.20071557583, 6651144.836562372, 68.42188717612486], + [510960.21459478, 6651144.759121588, 68.84621429612484], + [510960.1209997416, 6651145.281347002, 69.22724926212486], + [510960.1418257209, 6651145.165145803, 69.58895524712484], + [510960.2361441253, 6651144.638884278, 69.27252464712485], + [510960.16773368506, 6651145.020589026, 69.94671309312484], + [510960.2656252678, 6651144.474390496, 69.69433350612485], + [510960.19872672856, 6651144.847659399, 70.29716930812484], + [510960.30307374004, 6651144.265441985, 70.10468304912484], + [510960.2347170771, 6651144.646846673, 70.63691433512486], + [510960.34827295353, 6651144.013247228, 70.49646274312485], + [510960.2755230384, 6651144.419164628, 70.96258144512484], + [510960.38698122266, 6651143.797269521, 70.77394460312483], + [510960.32086999563, 6651144.166145515, 71.27095025312484], + [510960.42949129536, 6651143.560079167, 71.03438527612484], + [510960.37039565353, 6651143.889810811, 71.55904860412484], + [510960.47543630184, 6651143.303723163, 71.27535492212483], + [510960.42365939694, 6651143.592618984, 71.82424632912483], + [510960.5243875877, 6651143.030593241, 71.49477392812484], + [510960.4801552763, 6651143.277393045, 72.06433477612484], + [510960.5935024474, 6651142.644958097, 71.75098705112484], + [510960.53932782204, 6651142.947232305, 72.27758711112486], + [510960.6658932617, 6651142.241044347, 71.96326486012484], + [510962.3454878923, 6651132.869532619, 65.97268294412484], + [510962.3454878923, 6651132.869532619, 66.10268294412484], + [510960.6005896685, 6651142.605414046, 72.46279601312484], + [510960.7403056434, 6651141.8258510055, 72.13037961712485], + [510962.45302920556, 6651132.269492191, 65.97268294412484], + [510960.663339845, 6651142.255291461, 72.61928730512484], + [510960.81551214476, 6651141.406226771, 72.25253273912483], + [510960.7269816101, 6651141.900194142, 72.74691006412483], + [510960.8903687793, 6651140.988554664, 72.33120743212484], + [510960.79093881237, 6651141.543336804, 72.84600555812486], + [510960.9638585989, 6651140.578508874, 72.36895029112483], + [510960.8757763315, 6651141.069975081, 72.93517021012485], + [510962.3454878923, 6651132.869532619, 67.80148660312486], + [510960.959064794, 6651140.605256519, 72.97794545112484], + [510962.45302920556, 6651132.269492191, 67.80148660312486], + [510962.3422252839, 6651132.887736755, 68.21230191512484], + [510961.266162694, 6651138.891764751, 72.36895029112483], + [510962.3320226727, 6651132.944663522, 68.63342334312483], + [510962.44933158264, 6651132.290123547, 68.26707729012483], + [510962.3143538417, 6651133.043249011, 69.05951247812484], + [510962.4377686233, 6651132.354640549, 68.74434824212484], + [510962.2888579548, 6651133.1855065515, 69.48441898212485], + [510962.4177439483, 6651132.466370769, 69.22724926212486], + [510962.2553822575, 6651133.37228846, 69.90138568412483], + [510961.5748846781, 6651137.1692111995, 72.36895029112483], + [510962.396917969, 6651132.5825719675, 69.58895524712484], + [510961.64837449783, 6651136.75916541, 72.33120743212484], + [510962.2140150162, 6651133.603102241, 70.30333460112483], + [510961.72323113226, 6651136.341493303, 72.25253273912483], + [510962.16510335275, 6651133.876011085, 70.68321540312483], + [510962.37101000483, 6651132.727128746, 69.94671309312484], + [510962.1238231672, 6651134.106339126, 70.94962171812485], + [510961.7984376337, 6651135.92186907, 72.13037961712485], + [510961.579678896, 6651137.142461253, 72.97794545112484], + [510962.0789783129, 6651134.356556691, 71.19733145812484], + [510961.8728500153, 6651135.506675729, 71.96326486012484], + [510962.34001696133, 6651132.900058372, 70.29716930812484], + [510962.01435568935, 6651134.717126833, 71.49477392812484], + [510961.94524082966, 6651135.102761977, 71.75098705112484], + [510961.6629673583, 6651136.67774269, 72.93517021012485], + [510962.3040266128, 6651133.100871096, 70.63691433512486], + [510962.2632206515, 6651133.328553145, 70.96258144512484], + [510961.7478048776, 6651136.204380968, 72.84600555812486], + [510962.21787369426, 6651133.581572256, 71.27095025312484], + [510961.81176207983, 6651135.84752363, 72.74691006412483], + [510961.87540384487, 6651135.492426311, 72.61928730512484], + [510962.1683480363, 6651133.857906959, 71.55904860412484], + [510961.9381540214, 6651135.142303725, 72.46279601312484], + [510962.1150842929, 6651134.155098786, 71.82424632912483], + [510961.99941586785, 6651134.800485467, 72.27758711112486], + [510962.05858841364, 6651134.470324727, 72.06433477612484], + [510969.3869890279, 6651147.170132206, 65.74349841073101], + [510969.49764014105, 6651146.5706574535, 65.74349841073101], + [510969.49764014105, 6651146.5706574535, 65.87349841073102], + [510969.3869890279, 6651147.170132206, 67.57230206973101], + [510969.4976397165, 6651146.570659755, 67.572302070731], + [510969.3907935758, 6651147.149520299, 68.037892756731], + [510969.4984647809, 6651146.5661898, 67.776123354731], + [510969.40269090433, 6651147.08506412, 68.51516370873101], + [510969.5053156356, 6651146.529073913, 68.192702642731], + [510969.5195961883, 6651146.451706133, 68.61702976273101], + [510969.423294638, 6651146.973439231, 68.99806472873101], + [510969.4447228476, 6651146.857347578, 69.35977071373101], + [510969.54176868155, 6651146.331582173, 69.043340113731], + [510969.4713799989, 6651146.712927077, 69.71752855973101], + [510969.57210233784, 6651146.167243464, 69.465148972731], + [510969.5032692763, 6651146.540160476, 70.06798477473102], + [510969.61063371715, 6651145.958491934, 69.87549851573102], + [510969.5403003671, 6651146.339537064, 70.40772980173101], + [510969.657139968, 6651145.70653493, 70.267278209731], + [510969.5822863248, 6651146.112069658, 70.733396911731], + [510969.6969675741, 6651145.490760829, 70.544760069731], + [510969.62894459174, 6651145.859289073, 71.041765719731], + [510969.7407069216, 6651145.253794081, 70.805200742731], + [510969.67990239593, 6651145.583214878, 71.329864070731], + [510969.78798053163, 6651144.99767975, 71.046170388731], + [510969.7347063807, 6651145.286303224, 71.595061795731], + [510969.83834735455, 6651144.724807316, 71.26558939473101], + [510969.7928359659, 6651144.971374456, 71.835150242731], + [510969.90946082654, 6651144.339535721, 71.521802517731], + [510969.8537196195, 6651144.641524966, 72.04840257773101], + [510969.98394498473, 6651143.93600275, 71.734080326731], + [510969.91675299057, 6651144.300028948, 72.23361147973101], + [510970.06050916837, 6651143.521200823, 71.90119508373101], + [510971.7121088866, 6651134.573325796, 65.74349841073101], + [510971.7121088866, 6651134.573325796, 65.87349841073102], + [510969.98131773015, 6651143.950236432, 72.39010277173101], + [510970.13789043564, 6651143.1019721795, 72.023348205731], + [510971.8227599998, 6651133.973851045, 65.74349841073101], + [510970.0467998406, 6651143.595473875, 72.51772553073101], + [510970.2149117187, 6651142.684693824, 72.10202289873101], + [510970.1126065097, 6651143.238952954, 72.61682102473101], + [510970.2905266624, 6651142.275034595, 72.139765757731], + [510970.1998972974, 6651142.766037483, 72.705985676731], + [510970.2855942337, 6651142.301757024, 72.748760917731], + [510971.7121088866, 6651134.573325796, 67.57230206973101], + [510971.70875193266, 6651134.591512773, 67.983117381731], + [510971.8227599998, 6651133.973851045, 67.57230206973101], + [510970.6015725631, 6651140.58988061, 72.139765757731], + [510971.69825428975, 6651134.648385874, 68.404238809731], + [510971.8189554519, 6651133.994462951, 68.037892756731], + [510971.6800745247, 6651134.746878422, 68.83032794473101], + [510971.80705812335, 6651134.058919131, 68.51516370873101], + [510971.6538413666, 6651134.889001855, 69.255234448731], + [510970.91922194045, 6651138.868950957, 72.139765757731], + [510971.78645438957, 6651134.170544021, 68.99806472873101], + [510971.6193976439, 6651135.075607677, 69.672201150731], + [510970.99483688414, 6651138.459291728, 72.10202289873101], + [510971.7650261801, 6651134.286635673, 69.35977071373101], + [510971.5768341755, 6651135.306203864, 70.074150067731], + [510971.0718581673, 6651138.042013371, 72.023348205731], + [510971.52650812076, 6651135.57885543, 70.45403086973101], + [510971.14923943457, 6651137.622784729, 71.90119508373101], + [510970.92415479396, 6651138.842226227, 72.748760917731], + [510971.7383690288, 6651134.431056174, 69.71752855973101], + [510971.48403422546, 6651135.808966334, 70.720437184731], + [510971.22580361826, 6651137.207982802, 71.734080326731], + [510971.4378925809, 6651136.058948012, 70.96814692473102], + [510971.3002877764, 6651136.804449832, 71.521802517731], + [510971.3714012484, 6651136.419178236, 71.26558939473101], + [510971.70647975145, 6651134.603822773, 70.06798477473102], + [510971.00985173025, 6651138.377945767, 72.705985676731], + [510971.6694486605, 6651134.804446187, 70.40772980173101], + [510971.097142518, 6651137.905030296, 72.61682102473101], + [510971.1915795272, 6651147.504162954, 65.69803378696157], + [510971.62746270286, 6651135.0319135925, 70.733396911731], + [510971.1629491871, 6651137.548509375, 72.51772553073101], + [510971.5808044358, 6651135.284694177, 71.041765719731], + [510971.2284312975, 6651137.193746817, 72.39010277173101], + [510971.52984663175, 6651135.560768371, 71.329864070731], + [510971.2929960371, 6651136.843954301, 72.23361147973101], + [510971.4750426469, 6651135.857680027, 71.595061795731], + [510971.3560294081, 6651136.502458286, 72.04840257773101], + [510971.41691306175, 6651136.172608795, 71.835150242731], + [510971.3028339894, 6651146.904799883, 65.69803378696157], + [510971.3028339894, 6651146.904799883, 65.82803378696157], + [510971.1915795272, 6651147.504162954, 67.52683744596158], + [510971.3028335625, 6651146.904802183, 67.52683744696157], + [510971.1954048202, 6651147.483554888, 67.99242813296156], + [510971.30366312584, 6651146.900333062, 67.73065873096157], + [510971.2073670216, 6651147.419110715, 68.46969908496158], + [510971.3105513363, 6651146.863224088, 68.14723801896157], + [510971.3249097568, 6651146.785870722, 68.57156513896157], + [510971.2280831015, 6651147.307506622, 68.95260010496158], + [510971.249628153, 6651147.191436598, 69.31430608996158], + [510971.3472031503, 6651146.66576914, 68.99787548996159], + [510971.2764306582, 6651147.047043002, 69.67206393596157], + [510971.3777022074, 6651146.501461048, 69.41968434896158], + [510971.3084938187, 6651146.874308587, 70.02252015096157], + [510971.41644368746, 6651146.292748408, 69.83003389196158], + [510971.34572682955, 6651146.673722549, 70.36226517796158], + [510971.46320352366, 6651146.04083834, 70.22181358596158], + [510971.3879417248, 6651146.44629752, 70.68793228796157], + [510971.50324829837, 6651145.825104439, 70.49929544596156], + [510971.434854406, 6651146.193564028, 70.99630109596157], + [510971.54722614406, 6651145.588181837, 70.75973611896157], + [510971.48609006853, 6651145.917541265, 71.28439944696157], + [510971.5947575237, 6651145.33211522, 71.00070576496157], + [510971.5411928839, 6651145.620684923, 71.54959717196157], + [510971.64539898257, 6651145.05929362, 71.22012477096158], + [510971.5996394333, 6651145.305814825, 71.78968561896157], + [510971.716900216, 6651144.6740938, 71.47633789396157], + [510971.6608550681, 6651144.976026786, 72.00293795396159], + [510971.7917905152, 6651144.270636006, 71.68861570296157], + [510971.7242321422, 6651144.634594389, 72.18814685596158], + [510971.8687721816, 6651143.855911355, 71.85573045996156], + [510973.5293776037, 6651134.90970329, 65.69803378696157], + [510971.78914893494, 6651144.284867037, 72.34463814796158], + [510973.5293776037, 6651134.90970329, 65.82803378696157], + [510971.94657538686, 6651143.436760813, 71.97788358196158], + [510973.640632066, 6651134.310340218, 65.69803378696157], + [510971.85498810076, 6651143.9301705705, 72.47226090696157], + [510972.02401664515, 6651143.019560195, 72.05655827496157], + [510971.9211535949, 6651143.573716069, 72.57135640096159], + [510972.10004389565, 6651142.609977284, 72.09430113396157], + [510972.0089203545, 6651143.1008887, 72.66052105296158], + [510972.09508457186, 6651142.636694735, 72.70329629396157], + [510973.5293776037, 6651134.90970329, 67.52683744596158], + [510972.4127858412, 6651140.925137239, 72.09430113396157], + [510973.5260023452, 6651134.927886878, 67.93765275796157], + [510973.640632066, 6651134.310340218, 67.52683744596158], + [510973.5154474616, 6651134.984749384, 68.35877418596156], + [510973.63680677285, 6651134.330948285, 67.99242813296156], + [510973.4971685675, 6651135.083223583, 68.78486332096156], + [510973.62484457163, 6651134.395392457, 68.46969908496158], + [510973.4707923675, 6651135.225320538, 69.20976982496158], + [510972.7321672704, 6651139.204528188, 72.09430113396157], + [510973.6041284916, 6651134.5069965515, 68.95260010496158], + [510973.436160833, 6651135.411891597, 69.62673652696157], + [510972.8081945209, 6651138.794945278, 72.05655827496157], + [510973.5825834401, 6651134.623066576, 69.31430608996158], + [510973.3933652781, 6651135.642444826, 70.02868544396156], + [510972.88563577924, 6651138.37774466, 71.97788358196158], + [510973.3427648097, 6651135.915045596, 70.40856624596157], + [510972.73712702125, 6651139.1778084375, 72.70329629396157], + [510972.9634389844, 6651137.958594119, 71.85573045996156], + [510973.5557809349, 6651134.767460172, 69.67206393596157], + [510973.3000593163, 6651136.145113632, 70.67497256096158], + [510973.0404206509, 6651137.5438694665, 71.68861570296157], + [510973.2536660745, 6651136.39504874, 70.92268230096157], + [510973.11531095003, 6651137.140411674, 71.47633789396157], + [510973.1868121835, 6651136.7552118525, 71.22012477096158], + [510973.5237177744, 6651134.940194585, 70.02252015096157], + [510972.82329123863, 6651138.713614472, 72.66052105296158], + [510973.48648476356, 6651135.140780623, 70.36226517796158], + [510972.9110579982, 6651138.240787105, 72.57135640096159], + [510973.4442698683, 6651135.368205653, 70.68793228796157], + [510972.97722349246, 6651137.884332602, 72.47226090696157], + [510973.3973571871, 6651135.620939145, 70.99630109596157], + [510973.04306265817, 6651137.529636135, 72.34463814796158], + [510973.3461215246, 6651135.896961908, 71.28439944696157], + [510973.107979451, 6651137.179908785, 72.18814685596158], + [510973.2910187092, 6651136.19381825, 71.54959717196157], + [510973.171356525, 6651136.838476388, 72.00293795396159], + [510973.2325721599, 6651136.508688348, 71.78968561896157], + [510976.5812709479, 6651148.512989643, 65.56030910294606], + [510976.69432740635, 6651147.913963863, 65.56030910294606], + [510976.69432740635, 6651147.913963863, 65.69030910294606], + [510976.5812709479, 6651148.512989643, 67.38911276194607], + [510976.69432697253, 6651147.913966162, 67.38911276294606], + [510976.58515819954, 6651148.492393172, 67.85470344894605], + [510976.69516997243, 6651147.909499556, 67.59293404694606], + [510976.59731415333, 6651148.427985267, 68.33197440094607], + [510976.7021697517, 6651147.872411465, 68.00951333494606], + [510976.7167607365, 6651147.7951016305, 68.43384045494606], + [510976.6183657731, 6651148.316443979, 68.81487542094607], + [510976.6402597913, 6651148.200439272, 69.17658140594607], + [510976.7394152177, 6651147.675067636, 68.86015080594608], + [510976.6674964185, 6651148.056126935, 69.53433925194607], + [510976.7704082701, 6651147.510852007, 69.28195966494606], + [510976.7000789083, 6651147.883489726, 69.88479546694606], + [510976.8097772486, 6651147.302256822, 69.69230920794607], + [510976.7379149848, 6651147.683016569, 70.22454049394607], + [510976.8572944571, 6651147.050488518, 70.08408890194607], + [510976.78081363766, 6651147.455719523, 70.55020760394606], + [510976.8979878398, 6651146.8348760195, 70.36157076194606], + [510976.8284861669, 6651147.203128258, 70.85857641194606], + [510976.9426779977, 6651146.598086746, 70.62201143494606], + [510976.880551697, 6651146.927260826, 71.14667476294606], + [510976.99097924645, 6651146.342164231, 70.86298108094606], + [510976.93654701643, 6651146.63057154, 71.41187248794606], + [510977.0424409485, 6651146.069496163, 71.08240008694607], + [510976.9959402286, 6651146.315878637, 71.65196093494606], + [510977.11510029243, 6651145.684513113, 71.33861320994606], + [510977.05814737733, 6651145.986276187, 71.86521326994608], + [510977.191203595, 6651145.281282366, 71.55089101894606], + [510977.1225509743, 6651145.64503593, 72.05042217194607], + [510977.26943213877, 6651144.866791102, 71.71800577594607], + [510977.1885192289, 6651145.295505389, 72.20691346394608], + [510978.95693450235, 6651135.925617528, 65.56030910294606], + [510978.95693450235, 6651135.925617528, 65.69030910294606], + [510977.348495528, 6651144.447876438, 71.84015889794605], + [510977.25542479614, 6651144.941008529, 72.33453622294607], + [510979.0699909608, 6651135.326591749, 65.56030910294606], + [510977.42719110777, 6651144.030910599, 71.91883359094606], + [510977.3226619775, 6651144.584754623, 72.43363171694607], + [510977.50444977684, 6651143.621558183, 71.95657644994606], + [510977.4118503014, 6651144.112193339, 72.52279636894608], + [510977.49941012653, 6651143.648260597, 72.56557160994606], + [510978.95693450235, 6651135.925617528, 67.38911276194607], + [510977.82225722546, 6651141.937666283, 71.95657644994606], + [510978.9535045745, 6651135.943790884, 67.79992807394606], + [510979.0699909608, 6651135.326591749, 67.38911276194607], + [510978.9427787328, 6651136.00062139, 68.22104950194606], + [510979.06610370916, 6651135.347188219, 67.85470344894605], + [510978.9242037741, 6651136.099040172, 68.64713863694608], + [510979.05394775525, 6651135.411596125, 68.33197440094607], + [510978.897400357, 6651136.241057161, 69.07204514094606], + [510978.1468116978, 6651140.218025507, 71.95657644994606], + [510979.0328961355, 6651135.523137413, 68.81487542094607], + [510978.8622078931, 6651136.427523228, 69.48901184294606], + [510978.224070367, 6651139.808673091, 71.91883359094606], + [510978.3027659467, 6651139.391707253, 71.84015889794605], + [510978.8187191755, 6651136.657946712, 69.89096075994605], + [510979.01100211736, 6651135.639142118, 69.17658140594607], + [510978.15185178217, 6651140.191320795, 72.56557160994606], + [510978.3818293359, 6651138.972792588, 71.71800577594607], + [510978.7672991279, 6651136.930394076, 70.27084156194606], + [510978.98376549006, 6651135.783454456, 69.53433925194607], + [510978.7239019306, 6651137.160332642, 70.53724787694605], + [510978.4600578797, 6651138.558301324, 71.55089101894606], + [510978.67675725423, 6651137.410127097, 70.78495761694606], + [510978.5361611822, 6651138.155070577, 71.33861320994606], + [510978.60882052616, 6651137.770087529, 71.08240008694607], + [510978.2394116074, 6651139.727388053, 72.52279636894608], + [510978.9511830004, 6651135.956091666, 69.88479546694606], + [510978.32859993115, 6651139.254826769, 72.43363171694607], + [510978.91334692383, 6651136.156564822, 70.22454049394607], + [510978.39583711256, 6651138.898572863, 72.33453622294607], + [510978.870448271, 6651136.383861868, 70.55020760394606], + [510978.4627426798, 6651138.544076003, 72.20691346394608], + [510978.8227757418, 6651136.636453134, 70.85857641194606], + [510978.5287109344, 6651138.194545461, 72.05042217194607], + [510978.7707102118, 6651136.9123205645, 71.14667476294606], + [510978.59311453137, 6651137.853305205, 71.86521326994608], + [510978.7147148922, 6651137.20900985, 71.41187248794606], + [510978.65532168, 6651137.523702754, 71.65196093494606], + [510987.9845994391, 6651150.702811534, 65.25932373606133], + [510988.1014685009, 6651150.104517902, 65.25932373606133], + [510988.1014685009, 6651150.104517902, 65.38932373606133], + [510987.9845994391, 6651150.702811534, 67.08812739506133], + [510988.1014680524, 6651150.104520198, 67.08812739606134], + [510987.9886177805, 6651150.6822402375, 67.55371808206134], + [510988.1023394807, 6651150.100059051, 67.29194868006132], + [510988.00118366966, 6651150.617911053, 68.03098903406134], + [510988.1095753136, 6651150.06301629, 67.70852796806133], + [510988.02294521325, 6651150.506506095, 68.51389005406133], + [510988.1246583503, 6651149.985800946, 68.13285508806135], + [510988.0455775635, 6651150.390643174, 68.87559603906134], + [510988.14807680855, 6651149.865913662, 68.55916543906133], + [510988.0737326916, 6651150.246507218, 69.23335388506133], + [510988.18011503987, 6651149.701898743, 68.98097429806133], + [510988.1074139608, 6651150.074081012, 69.58381010006133], + [510988.2208116584, 6651149.493558507, 69.39132384106134], + [510988.14652598335, 6651149.873852879, 69.92355512706133], + [510988.26993129, 6651149.242097922, 69.78310353506133], + [510988.19087130757, 6651149.646833643, 70.24922223706135], + [510988.31199697574, 6651149.026748953, 70.06058539506134], + [510988.2401514976, 6651149.394551103, 70.55759104506133], + [510988.35819422, 6651148.790249091, 70.32102606806134], + [510988.29397283384, 6651149.119020846, 70.84568939606133], + [510988.4081243318, 6651148.5346393725, 70.56199571406133], + [510988.35185648367, 6651148.822694182, 71.11088712106134], + [510988.4613214771, 6651148.262304568, 70.78141472006135], + [510988.4132526133, 6651148.508385905, 71.35097556806134], + [510988.5364311122, 6651147.877792056, 71.03762784306134], + [510988.4775575738, 6651148.179186306, 71.56422790306134], + [510989.13496955147, 6651150.927905647, 65.22823515455318], + [510988.6151008467, 6651147.47505415, 71.24990565206133], + [510988.5441330535, 6651147.838363124, 71.74943680506134], + [510989.25222322944, 6651150.329687274, 65.22823515455318], + [510988.69596749195, 6651147.061069489, 71.41702040906135], + [510989.25222322944, 6651150.329687274, 65.35823515455317], + [510988.6123259557, 6651147.489259789, 71.90592809706133], + [510988.77769713604, 6651146.642666837, 71.53917353106132], + [510988.68148777966, 6651147.135196205, 72.03355085606132], + [510990.44037750276, 6651138.130824095, 65.25932373606133], + [510990.44037750276, 6651138.130824095, 65.38932373606133], + [510988.859046567, 6651146.226210627, 71.61784822406133], + [510988.7509924007, 6651146.779377723, 72.13264635006134], + [510990.5572465645, 6651137.532530463, 65.25932373606133], + [510988.93891063053, 6651145.817358532, 71.65559108306132], + [510989.13496955147, 6651150.927905647, 67.05703881355318], + [510988.8431884226, 6651146.307394018, 72.22181100206133], + [510988.93370102806, 6651145.844028312, 72.26458624306133], + [510989.25222277956, 6651150.329689568, 67.05703881455317], + [510989.13900111726, 6651150.907336939, 67.52262950055317], + [510989.2530970758, 6651150.325228983, 67.26086009855317], + [510989.1516083608, 6651150.843015845, 67.99990045255318], + [510989.2603567217, 6651150.288190882, 67.67743938655317], + [510989.26743550063, 6651144.135524738, 71.65559108306132], + [510990.44037750276, 6651138.130824095, 67.08812739506133], + [510990.4368319075, 6651138.148975237, 67.49894270706135], + [510989.1734415216, 6651150.7316249, 68.48280147255318], + [510989.2754893967, 6651150.210985251, 68.10176650655318], + [510990.5572465645, 6651137.532530463, 67.08812739506133], + [510990.4257443581, 6651138.205736283, 67.92006413506132], + [510989.1961483549, 6651150.615776552, 68.84450745755318], + [510990.55322822306, 6651137.5531017585, 67.55371808206134], + [510989.2989849252, 6651150.091113046, 68.52807685755319], + [510990.40654299606, 6651138.304034777, 68.34615327006134], + [510989.60293492454, 6651142.417985761, 71.65559108306132], + [510989.22439614165, 6651150.471658727, 69.20226530355318], + [510990.5406623339, 6651137.617430944, 68.03098903406134], + [510990.3788356872, 6651138.445878189, 68.77105977406133], + [510989.33112859423, 6651149.927118758, 68.94988571655317], + [510989.682798988, 6651142.009133668, 71.61784822406133], + [510990.3424564278, 6651138.632116351, 69.18802647606132], + [510990.5189007903, 6651137.728835903, 68.51389005406133], + [510989.764148419, 6651141.592677458, 71.53917353106132], + [510989.25818825583, 6651150.299254212, 69.55272151855317], + [510989.6081449755, 6651142.391313687, 72.26458624306133], + [510990.29750114004, 6651138.862258202, 69.58997539306134], + [510989.8458780631, 6651141.174274803, 71.41702040906135], + [510990.4962684401, 6651137.844698825, 68.87559603906134], + [510989.3719591455, 6651149.71880473, 69.36023525955318], + [510990.24434705405, 6651139.134372573, 69.96985619506133], + [510989.92674470827, 6651140.760290142, 71.24990565206133], + [510990.199486373, 6651139.3640301, 70.23626251006132], + [510989.69865758106, 6651141.9279479785, 72.22181100206133], + [510990.00541444274, 6651140.357552237, 71.03762784306134], + [510990.468113312, 6651137.988834779, 69.23335388506133], + [510990.15075183654, 6651139.61351925, 70.48397225006133], + [510990.08052407793, 6651139.973039726, 70.78141472006135], + [510989.2974289962, 6651150.099051264, 69.89246654555318], + [510990.4344320428, 6651138.161260985, 69.58381010006133], + [510989.7908536029, 6651141.455964274, 72.13264635006134], + [510989.4212404298, 6651149.467375776, 69.75201495355319], + [510990.3953200202, 6651138.361489118, 69.92355512706133], + [510989.86035822396, 6651141.100145792, 72.03355085606132], + [510989.3419202609, 6651149.872060586, 70.21813365555317], + [510990.350974696, 6651138.588508354, 70.24922223706135], + [510989.92952004797, 6651140.746082208, 71.90592809706133], + [510989.99771295016, 6651140.396978874, 71.74943680506134], + [510990.301694506, 6651138.840790896, 70.55759104506133], + [510990.06428842974, 6651140.056155692, 71.56422790306134], + [510990.24787316984, 6651139.116321152, 70.84568939606133], + [510990.1285933904, 6651139.726956091, 71.35097556806134], + [510990.18998952, 6651139.4126478145, 71.11088712106134], + [510989.4634445538, 6651149.252053895, 70.02949681355317], + [510989.3913626321, 6651149.619809779, 70.52650246355317], + [510989.5097938332, 6651149.0155837815, 70.28993748655317], + [510989.4453610943, 6651149.344314179, 70.81460081455317], + [510989.55988826504, 6651148.760006216, 70.53090713255317], + [510989.5034352393, 6651149.04802479, 71.07979853955317], + [510989.61326048215, 6651148.487705667, 70.75032613855318], + [510989.56503342366, 6651148.7337560505, 71.31988698655317], + [510989.6886173032, 6651148.103241523, 71.00653926155317], + [510989.62955001194, 6651148.40459786, 71.5331393215532], + [510989.76754593983, 6651147.700554278, 71.21881707055317], + [510989.69634459156, 6651148.0638175495, 71.71834822355318], + [510989.8486787173, 6651147.286621691, 71.38593182755318], + [510989.76476191665, 6651147.714758128, 71.87483951555319], + [510989.9306773337, 6651146.868271667, 71.50808494955317], + [510989.83415135223, 6651147.360739081, 72.00246227455318], + [510991.5988295832, 6651138.357499615, 65.22823515455318], + [510990.01229448576, 6651146.451867842, 71.58675964255318], + [510991.5988295832, 6651138.357499615, 65.35823515455317], + [510989.903884713, 6651147.0049653575, 72.10155776855318], + [510991.7160832611, 6651137.75928124, 65.22823515455318], + [510990.09242138197, 6651146.043067177, 71.62450250155317], + [510989.99638415215, 6651146.533041022, 72.19072242055319], + [510990.0871946348, 6651146.069733602, 72.23349766155317], + [510990.4220274278, 6651144.361444937, 71.62450250155317], + [510991.5988295832, 6651138.357499615, 67.05703881355318], + [510991.59527231933, 6651138.375648474, 67.46785412555317], + [510991.7160832611, 6651137.75928124, 67.05703881355318], + [510991.5841482809, 6651138.43240238, 67.88897555355317], + [510991.7120516954, 6651137.77984995, 67.52262950055317], + [510991.5648837271, 6651138.530688509, 68.31506468855319], + [510990.7586309806, 6651142.644122006, 71.62450250155317], + [510991.69944445184, 6651137.844171043, 67.99990045255318], + [510991.53708523355, 6651138.672514077, 68.73997119255317], + [510990.83875787683, 6651142.235321341, 71.58675964255318], + [510991.50058624987, 6651138.858728814, 69.15693789455317], + [510991.67761129106, 6651137.955561988, 68.48280147255318], + [510990.9203750289, 6651141.818917517, 71.50808494955317], + [510990.763858178, 6651142.617453287, 72.23349766155317], + [510991.45548301435, 6651139.088841717, 69.55888681155317], + [510991.00237364526, 6651141.400567493, 71.38593182755318], + [510991.6549044578, 6651138.071410335, 68.84450745755318], + [510991.40215399803, 6651139.360921859, 69.93876761355317], + [510991.08350642276, 6651140.986634906, 71.21881707055317], + [510991.35714568046, 6651139.590550498, 70.20517392855317], + [510990.8546686605, 6651142.154145865, 72.19072242055319], + [510991.1624350594, 6651140.583947662, 71.00653926155317], + [510991.30825075856, 6651139.840008264, 70.45288366855317], + [510991.626656671, 6651138.215528159, 69.20226530355318], + [510991.23779188044, 6651140.199483517, 70.75032613855318], + [510991.5928645568, 6651138.387932676, 69.55272151855317], + [510990.94716809964, 6651141.68222153, 72.10155776855318], + [510991.01690146036, 6651141.326447805, 72.00246227455318], + [510991.5536238165, 6651138.588135622, 69.89246654555318], + [510991.08629089594, 6651140.97242876, 71.87483951555319], + [510991.5091325518, 6651138.815126302, 70.21813365555317], + [510991.1547082211, 6651140.623369339, 71.71834822355318], + [510991.4596901806, 6651139.067377109, 70.52650246355317], + [510991.2215028007, 6651140.282589028, 71.5331393215532], + [510991.40569171833, 6651139.342872708, 70.81460081455317], + [510991.286019389, 6651139.953430836, 71.31988698655317], + [510991.3476175734, 6651139.639162097, 71.07979853955317], + [510993.04821306746, 6651151.699365826, 65.12148315381185], + [510993.1667751042, 6651151.101405384, 65.12148315381185], + [510993.1667751042, 6651151.101405384, 65.25148315381185], + [510993.04821306746, 6651151.699365826, 66.95028681281185], + [510993.16677464935, 6651151.101407679, 66.95028681381184], + [510993.0522896189, 6651151.6788059855, 67.41587749981184], + [510993.16765870125, 6651151.096949016, 67.15410809781184], + [510993.06503753865, 6651151.614512626, 67.89314845181185], + [510993.17499935295, 6651151.059926884, 67.57068738581185], + [510993.0871143217, 6651151.503169709, 68.37604947181185], + [510993.1903008838, 6651150.982754541, 67.99501450581185], + [510993.11007452605, 6651151.387371312, 68.73775545681185], + [510993.2140585838, 6651150.862934021, 68.42132485681186], + [510993.13863751176, 6651151.243315625, 69.09551330281185], + [510993.2465609235, 6651150.699010443, 68.84313371581186], + [510993.1728066905, 6651151.070985444, 69.44596951781185], + [510993.28784707683, 6651150.490786231, 69.25348325881185], + [510993.2124852932, 6651150.870868818, 69.78571454481185], + [510993.3376782594, 6651150.239465684, 69.64526295281186], + [510993.2574730075, 6651150.6439760085, 70.11138165481185], + [510993.38035331224, 6651150.024236643, 69.92274481281184], + [510993.30746707454, 6651150.391833963, 70.41975046281185], + [510993.4272197735, 6651149.787868488, 70.18318548581185], + [510993.36206807103, 6651150.116457149, 70.70784881381185], + [510993.47787317715, 6651149.532401118, 70.42415513181184], + [510993.4207902283, 6651149.820295509, 70.97304653881184], + [510993.5318409407, 6651149.260217975, 70.64357413781185], + [510993.4830757473, 6651149.506162272, 71.21313498581185], + [510993.6080386203, 6651148.875919599, 70.89978726081185], + [510993.5483122349, 6651149.177146002, 71.42638732081187], + [510993.6878479711, 6651148.473405978, 71.11206506981185], + [510993.61585213256, 6651148.836512624, 71.61159622281185], + [510993.7698860573, 6651148.059651865, 71.27917982681186], + [510993.6850328828, 6651148.487603704, 71.76808751481185], + [510993.85279964394, 6651147.641482219, 71.40133294881184], + [510993.75519659073, 6651148.133737299, 71.89571027381184], + [510993.93532750953, 6651147.225257933, 71.48000764181185], + [510995.53956573736, 6651139.134379716, 65.12148315381185], + [510993.82570806146, 6651147.778116973, 71.99480576781185], + [510995.53956573736, 6651139.134379716, 65.25148315381185], + [510994.01634849055, 6651146.816633529, 71.51775050081184], + [510995.6581277741, 6651138.536419273, 65.12148315381185], + [510993.91923964274, 6651147.306396114, 72.08397041981186], + [510994.0110634214, 6651146.843288455, 72.12674566081185], + [510994.3496323994, 6651145.135736346, 71.51775050081184], + [510995.53956573736, 6651139.134379716, 66.95028681281185], + [510995.5359687803, 6651139.152520751, 67.36110212481185], + [510995.6581277741, 6651138.536419273, 66.95028681281185], + [510995.52472061577, 6651139.209250186, 67.78222355281184], + [510995.65405122266, 6651138.556979113, 67.41587749981184], + [510995.5052411012, 6651139.307493936, 68.20831268781185], + [510994.68999189587, 6651143.419153865, 71.51775050081184], + [510995.64130330295, 6651138.621272473, 67.89314845181185], + [510995.4771324219, 6651139.449258356, 68.63321919181186], + [510994.77101287694, 6651143.01052946, 71.48000764181185], + [510995.4402261694, 6651139.635392802, 69.05018589381184], + [510994.85354074254, 6651142.594305174, 71.40133294881184], + [510995.6192265198, 6651138.732615391, 68.37604947181185], + [510994.69527742016, 6651143.3924966445, 72.12674566081185], + [510995.39461965574, 6651139.865406488, 69.45213481081184], + [510994.93645432906, 6651142.176135529, 71.27917982681186], + [510995.5962663155, 6651138.848413788, 68.73775545681185], + [510995.34069557517, 6651140.13736932, 69.83201561281184], + [510995.0184924154, 6651141.762381416, 71.11206506981185], + [510994.7871011988, 6651142.929388984, 72.08397041981186], + [510995.29518503847, 6651140.36689895, 70.09842192781186], + [510995.09830176615, 6651141.359867796, 70.89978726081185], + [510995.2457445295, 6651140.61624916, 70.34613166781185], + [510995.17449944577, 6651140.975569419, 70.64357413781185], + [510995.5677033298, 6651138.992469475, 69.09551330281185], + [510994.88063278, 6651142.457668127, 71.99480576781185], + [510995.533534151, 6651139.164799656, 69.44596951781185], + [510994.9511442508, 6651142.102047801, 71.89571027381184], + [510995.4938555483, 6651139.364916282, 69.78571454481185], + [510995.0213079587, 6651141.748181393, 71.76808751481185], + [510995.4488678341, 6651139.591809091, 70.11138165481185], + [510995.090488709, 6651141.399272475, 71.61159622281185], + [510995.3988737671, 6651139.843951136, 70.41975046281185], + [510995.1580286066, 6651141.058639097, 71.42638732081187], + [510995.3442727705, 6651140.11932795, 70.70784881381185], + [510995.2232650942, 6651140.729622828, 71.21313498581185], + [510995.2855506133, 6651140.41548959, 70.97304653881184], + [511004.74689144985, 6651154.058766993, 64.79313440574904], + [511004.8693648376, 6651153.461595396, 64.79313440574904], + [511004.8693648376, 6651153.461595396, 64.92313440574902], + [511004.74689144985, 6651154.058766993, 66.62193806474903], + [511004.75110248633, 6651154.038234276, 67.08752875174902], + [511004.8693643676, 6651153.461597687, 66.62193806574902], + [511004.8702775843, 6651153.457144906, 66.82575934974902], + [511004.7642709587, 6651153.974025734, 67.56479970374905], + [511004.87786040345, 6651153.420171615, 67.24233863774903], + [511004.787076053, 6651153.862829702, 68.04770072374903], + [511004.89366673044, 6651153.34310108, 67.66666575774903], + [511004.81079371244, 6651153.747184069, 68.40940670874903], + [511004.91820819484, 6651153.22343863, 68.09297610874903], + [511004.84029898845, 6651153.603318425, 68.76716455474903], + [511004.9517827839, 6651153.059731303, 68.51478496774902], + [511004.8755954053, 6651153.431215585, 69.11762076974902], + [511004.99443096365, 6651152.851781787, 68.92513451074903], + [511004.91658300156, 6651153.231362958, 69.45736579674903], + [511005.0459060724, 6651152.600792789, 69.31691420474903], + [511004.9630548565, 6651153.004769472, 69.78303290674903], + [511005.08998897136, 6651152.385847684, 69.59439606474902], + [511005.0146982233, 6651152.752960061, 70.09140171474903], + [511005.1384015531, 6651152.149791351, 69.85483673774903], + [511005.07110050175, 6651152.47794653, 70.37950006574903], + [511005.190726008, 6651151.894661001, 70.09580638374902], + [511005.13175989775, 6651152.182175594, 70.64469779074902], + [511005.2464741632, 6651151.622836931, 70.31522538974903], + [511005.1961002104, 6651151.868456769, 70.88478623774903], + [511005.32518559747, 6651151.239045531, 70.57143851274903], + [511005.2634888439, 6651151.539874546, 71.09803857274903], + [511005.4076278515, 6651150.837062916, 70.78371632174904], + [511005.3332568767, 6651151.199690541, 71.28324747474905], + [511005.49237236683, 6651150.423854638, 70.95083107874902], + [511005.40471989376, 6651150.851241913, 71.43973876674903], + [511005.57802126516, 6651150.006236652, 71.07298420074903], + [511005.4771982961, 6651150.497842337, 71.56736152574902], + [511005.66327171767, 6651149.590561462, 71.15165889374903], + [511005.5500359339, 6651150.142691153, 71.66645701974903], + [511005.74696557363, 6651149.182476124, 71.18940175274902], + [511007.3204336206, 6651141.510356942, 64.79313440574904], + [511007.3204336206, 6651141.510356942, 64.92313440574902], + [511005.6466531136, 6651149.6715926025, 71.75562167174903], + [511007.4429070083, 6651140.913185345, 64.79313440574904], + [511005.74150615046, 6651149.209095887, 71.79839691274903], + [511006.09124448866, 6651147.503796426, 71.18940175274902], + [511007.3204336206, 6651141.510356942, 66.62193806474903], + [511007.31671800016, 6651141.528474045, 67.03275337674903], + [511007.4429070083, 6651140.913185345, 66.62193806474903], + [511007.30509875977, 6651141.585128642, 67.45387480474903], + [511007.4386959718, 6651140.933718062, 67.08752875174902], + [511006.44283241435, 6651145.789478505, 71.18940175274902], + [511007.2849766177, 6651141.683242787, 67.87996393974902], + [511006.5265262703, 6651145.381393168, 71.15165889374903], + [511007.4255274994, 6651140.997926604, 67.56479970374905], + [511007.25594063563, 6651141.824820186, 68.30487044374902], + [511006.6117767228, 6651144.965717978, 71.07298420074903], + [511006.4482923077, 6651145.762856451, 71.79839691274903], + [511007.21781684924, 6651142.010709079, 68.72183714574903], + [511007.4027224051, 6651141.109122635, 68.04770072374903], + [511006.69742562115, 6651144.548099992, 70.95083107874902], + [511007.17070578074, 6651142.240419325, 69.12378606274902], + [511006.5431453445, 6651145.300359735, 71.75562167174903], + [511006.7821701364, 6651144.134891714, 70.78371632174904], + [511007.3790047457, 6651141.224768269, 68.40940670874903], + [511007.11500274955, 6651142.512023376, 69.50366686474902], + [511006.8646123905, 6651143.7329091, 70.57143851274903], + [511007.06799082446, 6651142.741250206, 69.77007317974902], + [511006.9433238248, 6651143.349117701, 70.31522538974903], + [511007.0169192775, 6651142.990271466, 70.01778291974902], + [511007.3494994697, 6651141.368633913, 68.76716455474903], + [511006.63976252417, 6651144.829261185, 71.66645701974903], + [511006.7126001621, 6651144.474110001, 71.56736152574902], + [511007.3142030527, 6651141.540736752, 69.11762076974902], + [511006.78507856437, 6651144.120710424, 71.43973876674903], + [511007.2732154565, 6651141.740589378, 69.45736579674903], + [511006.85654158145, 6651143.7722617965, 71.28324747474905], + [511007.22674360155, 6651141.967182864, 69.78303290674903], + [511006.9263096141, 6651143.432077792, 71.09803857274903], + [511007.1751002348, 6651142.218992277, 70.09140171474903], + [511006.99369824765, 6651143.103495568, 70.88478623774903], + [511007.1186979563, 6651142.494005808, 70.37950006574903], + [511007.05803856044, 6651142.789776742, 70.64469779074902], + [511008.84031986113, 6651154.903174839, 64.67497358985594], + [511008.964161851, 6651154.306285562, 64.67497358985594], + [511008.964161851, 6651154.306285562, 64.80497358985593], + [511008.84031986113, 6651154.903174839, 66.50377724885594], + [511008.8445779547, 6651154.88265183, 66.96936793585593], + [511008.9641613757, 6651154.306287853, 66.50377724985593], + [511008.9650847973, 6651154.301837178, 66.70759853385593], + [511008.85789358075, 6651154.818473643, 67.44663888785594], + [511008.9727523522, 6651154.264881366, 67.12417782185594], + [511008.8809535148, 6651154.70733018, 67.92953990785594], + [511008.9887353098, 6651154.187847268, 67.54850494185594], + [511008.9049362116, 6651154.59173922, 68.29124589285595], + [511009.0135510175, 6651154.0682413895, 67.97481529285594], + [511008.93477119994, 6651154.44794159, 68.64900373885595], + [511009.04750079213, 6651153.904611457, 68.39662415185593], + [511009.4851473952, 6651155.037084486, 64.65620509671923], + [511008.9704620434, 6651154.275920116, 68.99945995385593], + [511009.090625552, 6651153.696760253, 68.80697369485594], + [511009.60920497734, 6651154.440239982, 64.65620509671923], + [511009.0119076632, 6651154.07616197, 69.33920498085594], + [511009.60920497734, 6651154.440239982, 64.78620509671923], + [511009.14267587924, 6651153.445889912, 69.19875338885593], + [511009.0588988267, 6651153.84967561, 69.66487209085594], + [511009.18725139095, 6651153.231046424, 69.47623524885593], + [511009.1111192921, 6651153.597985243, 69.97324089885595], + [511009.4851473952, 6651155.037084486, 66.48500875571924], + [511009.2362049682, 6651152.995101691, 69.73667592185593], + [511009.1681518484, 6651153.323101728, 70.26133924985594], + [511009.4894129014, 6651155.016563016, 66.95059944271922], + [511009.6092045014, 6651154.440242271, 66.48500875671922], + [511009.2891141325, 6651152.740091956, 69.97764556785593], + [511009.61012953054, 6651154.435791931, 66.68883004071922], + [511009.2294890943, 6651153.027470623, 70.52653697485593], + [511009.50275170815, 6651154.952389644, 67.42787039471925], + [511009.34548525605, 6651152.468396394, 70.19706457385594], + [511009.6178104335, 6651154.398838891, 67.10540932871923], + [511009.29454839, 6651152.7139001135, 70.76662542185593], + [511009.52585178654, 6651154.841254518, 67.91077141471924], + [511009.4250762661, 6651152.084786436, 70.45327769685593], + [511009.63382121536, 6651154.321810571, 67.52973644871923], + [511009.36269007064, 6651152.385473231, 70.97987775685594], + [511009.5498762341, 6651154.725672228, 68.27247739971924], + [511009.50843978673, 6651151.682993863, 70.66555550585593], + [511009.6586801239, 6651154.202213665, 67.95604679971923], + [511009.4332377394, 6651152.045450052, 71.16508665885596], + [511009.5797631612, 6651154.581885384, 68.63023524571923], + [511009.5941312957, 6651151.269980936, 70.83267026285594], + [511009.6926890006, 6651154.038596005, 68.37785565871923], + [511009.5054993335, 6651151.697166157, 71.32157795085594], + [511009.6155161376, 6651154.409876812, 68.98069146071923], + [511009.68073729385, 6651150.852560385, 70.95482338485594], + [511009.5787876594, 6651151.343933655, 71.44920070985593], + [511009.735888835, 6651153.830760391, 68.78820520171924], + [511009.65703390876, 6651154.210133651, 69.32043648771923], + [511009.76694039366, 6651150.437081708, 71.03349807785594], + [511009.65243923524, 6651150.988950375, 71.54829620385594], + [511009.7880297749, 6651153.579908868, 69.17998489571923], + [511009.8515695024, 6651150.0291893, 71.07124093685593], + [511009.7041068776, 6651153.98366428, 69.64610359771923], + [511009.7501360818, 6651150.518074541, 71.63746085585593], + [511011.44262056565, 6651142.360697208, 64.67497358985594], + [511011.44262056565, 6651142.360697208, 64.80497358985593], + [511009.8326828866, 6651153.365081496, 69.45746675571922], + [511009.84604907193, 6651150.055796476, 71.68023609685595], + [511009.75641825184, 6651153.731992792, 69.95447240571923], + [511011.56646255543, 6651141.763807931, 64.67497358985594], + [511009.8817216855, 6651153.12915446, 69.71790742871923], + [511009.81355009443, 6651153.457129896, 70.24257075671923], + [511009.9347229577, 6651152.874163853, 69.95887707471923], + [511010.1996956273, 6651148.351303216, 71.07124093685593], + [511009.87499412015, 6651153.161520965, 70.50776848171922], + [511009.9911922158, 6651152.60248867, 70.17829608071924], + [511011.44262056565, 6651142.360697208, 66.50377724885594], + [511009.9401666756, 6651152.847973974, 70.74785692871923], + [511010.0709217833, 6651152.218907485, 70.43450920371923], + [511011.4388634244, 6651142.378805746, 66.91459256085594], + [511011.56646255543, 6651141.763807931, 66.50377724885594], + [511010.0084269817, 6651152.519571727, 70.96110926371924], + [511011.42711434263, 6651142.435433558, 67.33571398885593], + [511010.5552124388, 6651146.637795762, 71.07124093685593], + [511010.1544304288, 6651151.817145051, 70.64678701271924], + [511011.5622044619, 6651141.784330942, 66.96936793585593], + [511011.40676734183, 6651142.533501318, 67.76180312385594], + [511010.0790974647, 6651152.179574053, 71.14631816571925], + [511010.6398415475, 6651146.229903353, 71.03349807785594], + [511011.54888883594, 6651141.848509127, 67.44663888785594], + [511011.3774068917, 6651142.675011787, 68.18670962785593], + [511010.2402711152, 6651151.404163103, 70.81390176971922], + [511010.72604464745, 6651145.814424677, 70.95482338485594], + [511010.5607333447, 6651146.611186294, 71.68023609685595], + [511010.15148485656, 6651151.831316282, 71.30280945771923], + [511011.33885708393, 6651142.860812798, 68.60367632985593], + [511010.81265064556, 6651145.397004127, 70.83267026285594], + [511011.5258289018, 6651141.959652589, 67.92953990785594], + [511011.2912195638, 6651143.090414445, 69.00562524685593], + [511010.65664633474, 6651146.1489082305, 71.63746085585593], + [511010.89834215445, 6651144.983991197, 70.66555550585593], + [511010.327027883, 6651150.986773862, 70.93605489171924], + [511010.22490076773, 6651151.478110275, 71.43043221671923], + [511011.23489406856, 6651143.361890092, 69.38550604885593], + [511011.501846205, 6651142.075243549, 68.29124589285595], + [511010.9817056751, 6651144.582198625, 70.45327769685593], + [511011.18735679984, 6651143.5910085505, 69.65191236385593], + [511011.06129668525, 6651144.198588668, 70.19706457385594], + [511011.13571454416, 6651143.839912082, 69.89962210385593], + [511010.75434318144, 6651145.678032395, 71.54829620385594], + [511011.4720112167, 6651142.21904118, 68.64900373885595], + [511010.413381051, 6651150.571326349, 71.01472958471923], + [511010.8279947572, 6651145.323049115, 71.44920070985593], + [511010.29868056107, 6651151.12315362, 71.52952771071924], + [511011.43632037326, 6651142.3910626555, 68.99945995385593], + [511010.9012830832, 6651144.969816613, 71.32157795085594], + [511011.39487475343, 6651142.590820799, 69.33920498085594], + [511010.9735446772, 6651144.621532718, 71.16508665885596], + [511011.34788358986, 6651142.81730716, 69.66487209085594], + [511010.4981574877, 6651150.163464535, 71.05247244371922], + [511011.04409234604, 6651144.281509538, 70.97987775685594], + [511011.2956631246, 6651143.068997527, 69.97324089885595], + [511011.11223402654, 6651143.953082658, 70.76662542185593], + [511011.23863056814, 6651143.343881041, 70.26133924985594], + [511010.39654748497, 6651150.652313107, 71.61869236271923], + [511011.1772933223, 6651143.639512146, 70.52653697485593], + [511012.09197835956, 6651142.495547644, 64.65620509671923], + [511012.09197835956, 6651142.495547644, 64.78620509671923], + [511010.4926274468, 6651150.190069717, 71.66146760371923], + [511012.21603594173, 6651141.898703137, 64.65620509671923], + [511010.8468896539, 6651148.485704308, 71.05247244371922], + [511012.09197835956, 6651142.495547644, 66.48500875571924], + [511012.0882146775, 6651142.5136548225, 66.89582406771923], + [511012.21603594173, 6651141.898703137, 66.48500875571924], + [511012.0764451422, 6651142.5702783875, 67.31694549571924], + [511011.203025373, 6651146.772325381, 71.05247244371922], + [511012.21177043545, 6651141.919224608, 66.95059944271922], + [511012.05606272, 6651142.668338792, 67.74303463071922], + [511011.2878018097, 6651146.364463567, 71.01472958471923], + [511012.19843162876, 6651141.983397981, 67.42787039471925], + [511012.02665115724, 6651142.809838645, 68.16794113471923], + [511011.37415497773, 6651145.949016056, 70.93605489171924], + [511011.20855589, 6651146.745717907, 71.66146760371923], + [511011.98803423933, 6651142.995625719, 68.58490783671924], + [511011.4609117454, 6651145.531626815, 70.81390176971922], + [511012.17533155036, 6651142.094533105, 67.91077141471924], + [511011.94031378865, 6651143.225210145, 68.98685675371922], + [511011.3046358519, 6651146.283474518, 71.61869236271923], + [511011.5467524319, 6651145.118644866, 70.64678701271924], + [511011.8838902381, 6651143.496665428, 69.36673755571923], + [511012.1513071028, 6651142.210115396, 68.27247739971924], + [511011.6302610773, 6651144.716882431, 70.43450920371923], + [511011.83627021336, 6651143.725766703, 69.63314387071922], + [511011.70999064477, 6651144.333301246, 70.17829608071924], + [511011.78453805536, 6651143.974651565, 69.88085361071923], + [511011.4025027757, 6651145.812634004, 71.52952771071924], + [511012.12142017577, 6651142.35390224, 68.63023524571923], + [511011.4762825692, 6651145.457677349, 71.43043221671923], + [511012.08566719934, 6651142.525910812, 68.98069146071923], + [511011.54969848035, 6651145.104471343, 71.30280945771923], + [511012.0441494281, 6651142.725653973, 69.32043648771923], + [511011.6220858723, 6651144.756213572, 71.14631816571925], + [511011.9970764592, 6651142.952123346, 69.64610359771923], + [511011.6927563552, 6651144.416215898, 70.96110926371924], + [511011.94476508506, 6651143.203794833, 69.95447240571923], + [511011.7610166613, 6651144.087813651, 70.74785692871923], + [511011.8876332425, 6651143.478657731, 70.24257075671923], + [511011.82618921663, 6651143.77426666, 70.50776848171922], + [511021.4769820368, 6651157.5717343185, 64.29946579601143], + [511021.6050489842, 6651156.97573725, 64.29946579601143], + [511021.6050489842, 6651156.97573725, 64.42946579601143], + [511021.4769820368, 6651157.5717343185, 66.12826945501143], + [511021.48138539825, 6651157.551241985, 66.59386014201144], + [511021.60504849284, 6651156.975739538, 66.12826945601144], + [511021.60600341763, 6651156.971295516, 66.33209074001142], + [511021.49515529623, 6651157.487159729, 67.07113109401143], + [511021.6139325565, 6651156.9343949435, 66.74867002801143], + [511021.5190019365, 6651157.376182402, 67.55403211401143], + [511021.6304607842, 6651156.857475993, 67.17299714801145], + [511021.54380282003, 6651157.260764223, 67.91573809901143], + [511021.65612309735, 6651156.738048899, 67.59930749901143], + [511021.5746556502, 6651157.117181537, 68.27349594501143], + [511021.6912310927, 6651156.574663554, 68.02111635801143], + [511021.6115641121, 6651156.945417193, 68.62395216001143], + [511021.73582708446, 6651156.3671230385, 68.43146590101144], + [511021.6544236788, 6651156.74595764, 68.96369718701143], + [511021.78965314565, 6651156.116627689, 68.82324559501143], + [511021.70301797934, 6651156.5198098235, 69.28936429701145], + [511021.8357493826, 6651155.9021053435, 69.10072745501142], + [511021.757019983, 6651156.268495674, 69.59773310501143], + [511021.886373046, 6651155.666513291, 69.36116812801144], + [511021.81599824573, 6651155.994023046, 69.88583145601143], + [511021.94108724425, 6651155.411884738, 69.60213777401142], + [511021.8794280553, 6651155.698833841, 70.15102918101144], + [511021.9993815087, 6651155.140595295, 69.82155678001145], + [511021.9467068953, 6651155.385732044, 70.39111762801144], + [511022.08168782276, 6651154.757558744, 70.07776990301144], + [511022.0171732778, 6651155.057796085, 70.60436996301144], + [511022.16789534927, 6651154.356366758, 70.29004771201143], + [511022.0901277305, 6651154.71828116, 70.78957886501144], + [511022.256510285, 6651153.943971187, 70.45716246901142], + [511022.16485458025, 6651154.370517868, 70.94607015701143], + [511022.3460709085, 6651153.527174582, 70.57931559101145], + [511022.24064318964, 6651154.017813366, 71.07369291601142], + [511022.4352148884, 6651153.11231695, 70.65799028401143], + [511022.31680744136, 6651153.663360701, 71.17278841001144], + [511022.5227311794, 6651152.705034244, 70.69573314301142], + [511022.41783728544, 6651153.193188718, 71.26195306201143], + [511024.1680620823, 6651145.048004751, 64.29946579601143], + [511022.5170224155, 6651152.731601651, 71.30472830301143], + [511024.1680620823, 6651145.048004751, 64.42946579601143], + [511024.2961290296, 6651144.452007684, 64.29946579601143], + [511022.88273387484, 6651151.029656208, 70.69573314301142], + [511024.1680620823, 6651145.048004751, 66.12826945501143], + [511024.16417676344, 6651145.066086221, 66.53908476701145], + [511024.2961290296, 6651144.452007684, 66.12826945501143], + [511023.2503793955, 6651149.318710045, 70.69573314301142], + [511024.1520268534, 6651145.122629388, 66.96020619501142], + [511024.2917256682, 6651144.472500016, 66.59386014201144], + [511023.33789568645, 6651148.91142734, 70.65799028401143], + [511024.1309857002, 6651145.220550559, 67.38629533001144], + [511023.4270396664, 6651148.496569707, 70.57931559101145], + [511023.256088651, 6651149.292140353, 71.30472830301143], + [511024.10062359745, 6651145.361849502, 67.81120183401143], + [511024.27795577014, 6651144.536582272, 67.07113109401143], + [511023.51660028985, 6651148.079773102, 70.45716246901142], + [511024.06075863546, 6651145.547372784, 68.22816853601142], + [511023.35527378094, 6651148.830553286, 71.26195306201143], + [511023.60521522554, 6651147.6673775315, 70.29004771201143], + [511024.25410913, 6651144.6475596, 67.55403211401143], + [511024.01149592747, 6651145.776631232, 68.63011745301144], + [511023.69142275205, 6651147.266185545, 70.07776990301144], + [511023.9532488478, 6651146.047701085, 69.00999825501142], + [511023.77372906613, 6651146.883148995, 69.82155678001145], + [511023.90408981126, 6651146.276477067, 69.27640457001142], + [511023.45630362513, 6651148.3603813, 71.17278841001144], + [511024.22930824646, 6651144.762977779, 67.91573809901143], + [511023.8506857434, 6651146.525008547, 69.52411431001143], + [511023.53246787685, 6651148.0059286365, 71.07369291601142], + [511024.19845541625, 6651144.906560465, 68.27349594501143], + [511023.60825648624, 6651147.653224135, 70.94607015701143], + [511024.1615469543, 6651145.078324808, 68.62395216001143], + [511023.6829833359, 6651147.305460841, 70.78957886501144], + [511024.1186873876, 6651145.2777843615, 68.96369718701143], + [511023.7559377887, 6651146.965945918, 70.60436996301144], + [511024.07009308715, 6651145.503932178, 69.28936429701145], + [511023.8264041712, 6651146.638009957, 70.39111762801144], + [511024.01609108347, 6651145.755246326, 69.59773310501143], + [511023.8936830112, 6651146.324908161, 70.15102918101144], + [511023.95711282076, 6651146.029718955, 69.88583145601143], + [511025.8906830187, 6651158.525863193, 64.16447493163774], + [511026.0202256484, 6651157.93018513, 64.16447493163774], + [511026.0202256484, 6651157.93018513, 64.29447493163774], + [511025.8906830187, 6651158.525863193, 65.99327859063776], + [511025.89513711893, 6651158.505381828, 66.45886927763773], + [511026.0202251514, 6651157.930187415, 65.99327859163773], + [511026.02119107946, 6651157.925745773, 66.19709987563775], + [511025.90906568395, 6651158.441333872, 66.93614022963774], + [511026.02921158384, 6651157.888864951, 66.61367916363776], + [511025.9331871027, 6651158.330415945, 67.41904124963776], + [511026.045930262, 6651157.811987172, 67.03800628363774], + [511025.9582737605, 6651158.215059542, 67.78074723463774], + [511026.07188827544, 6651157.692623999, 67.46431663463774], + [511025.98948209995, 6651158.071553708, 68.13850508063774], + [511026.1074008111, 6651157.529326106, 67.88612549363775], + [511026.02681584854, 6651157.899881301, 68.48896129563774], + [511026.15251067106, 6651157.321896676, 68.29647503663774], + [511026.0701692749, 6651157.700528508, 68.82870632263776], + [511026.20695695595, 6651157.071535405, 68.68825473063774], + [511026.119323515, 6651157.474501736, 69.15437343263774], + [511026.25358434796, 6651156.857127881, 68.96573659063773], + [511026.17394776986, 6651157.223322102, 69.46274224063774], + [511026.30479133484, 6651156.621661927, 69.22617726363774], + [511026.2336056238, 6651156.948996385, 69.75084059163775], + [511026.36013599054, 6651156.367169662, 69.46714690963775], + [511026.29776631884, 6651156.653965177, 70.01603831663773], + [511026.4191019648, 6651156.096025426, 69.68656591563774], + [511026.3658203954, 6651156.3410309665, 70.25612676363774], + [511026.50235667324, 6651155.713193893, 69.94277903863774], + [511026.43709874386, 6651156.013270534, 70.46937909863775], + [511026.58955754683, 6651155.312216644, 70.15505684763774], + [511026.51089383196, 6651155.673937333, 70.65458800063774], + [511026.6791935697, 6651154.900041806, 70.32217160463773], + [511026.5864817398, 6651155.326360179, 70.81107929263774], + [511026.76978617697, 6651154.483468289, 70.44432472663775], + [511026.6631436418, 6651154.97384446, 70.93870205163773], + [511026.85995734, 6651154.068832707, 70.52299941963776], + [511026.74018551456, 6651154.619581515, 71.03779754563776], + [511026.94848205865, 6651153.661767998, 70.56074227863775], + [511026.84237949946, 6651154.149661188, 71.12696219763774], + [511026.9427075141, 6651153.688321184, 71.16973743863774], + [511028.6127716849, 6651146.008836894, 64.16447493163774], + [511028.6127716849, 6651146.008836894, 64.29447493163774], + [511028.7423143146, 6651145.413158831, 64.16447493163774], + [511027.31263297226, 6651151.9872867, 70.56074227863775], + [511028.6127716849, 6651146.008836894, 65.99327859063776], + [511028.6088415965, 6651146.026908685, 66.40409390263774], + [511028.7423143146, 6651145.413158831, 65.99327859063776], + [511027.6845147774, 6651150.277256313, 70.56074227863775], + [511028.5965516861, 6651146.083421589, 66.82521533063773], + [511027.773039496, 6651149.870191604, 70.52299941963776], + [511028.7378602144, 6651145.433640195, 66.45886927763773], + [511028.5752680812, 6651146.181290348, 67.25130446563773], + [511027.6902898191, 6651150.250700841, 71.16973743863774], + [511027.86321065895, 6651149.455556022, 70.44432472663775], + [511028.54455612367, 6651146.322513661, 67.67621096963775], + [511028.72393164935, 6651145.497688151, 66.93614022963774], + [511027.9538032663, 6651149.038982505, 70.32217160463773], + [511027.7906178337, 6651149.789360836, 71.12696219763774], + [511028.504231808, 6651146.507937643, 68.09317767163773], + [511028.0434392891, 6651148.626807668, 70.15505684763774], + [511028.69981023046, 6651145.608606079, 67.41904124963776], + [511028.4544014587, 6651146.7370733805, 68.49512658863773], + [511028.1306401627, 6651148.225830417, 69.94277903863774], + [511028.3954832129, 6651147.007998145, 68.87500739063773], + [511027.89281181875, 6651149.319440509, 71.03779754563776], + [511028.2138948712, 6651147.842998885, 69.68656591563774], + [511028.34575772955, 6651147.236651676, 69.14141370563775], + [511028.29173830024, 6651147.48505013, 69.38912344563774], + [511028.6747235727, 6651145.723962481, 67.78074723463774], + [511027.9698536914, 6651148.965177565, 70.93870205163773], + [511028.64351523336, 6651145.867468315, 68.13850508063774], + [511028.04651559336, 6651148.612661846, 70.81107929263774], + [511028.60618148465, 6651146.039140723, 68.48896129563774], + [511028.12210350134, 6651148.265084692, 70.65458800063774], + [511028.56282805826, 6651146.238493515, 68.82870632263776], + [511028.19589858945, 6651147.925751491, 70.46937909863775], + [511028.5136738182, 6651146.464520288, 69.15437343263774], + [511028.2671769378, 6651147.597991058, 70.25612676363774], + [511028.45904956345, 6651146.715699921, 69.46274224063774], + [511028.33523101447, 6651147.285056848, 70.01603831663773], + [511028.39939170936, 6651146.9900256395, 69.75084059163775], + [511028.50064462627, 6651159.095456568, 64.08371371663779], + [511028.6310598739, 6651158.499968944, 64.08371371663779], + [511028.6310598739, 6651158.499968944, 64.21371371663778], + [511028.50064462627, 6651159.095456568, 65.91251737563779], + [511028.5051287299, 6651159.074981753, 66.37810806263779], + [511028.6310593735, 6651158.499971229, 65.9125173766378], + [511028.6320318082, 6651158.495531006, 66.11633866063778], + [511028.51915111975, 6651159.010954272, 66.85537901463779], + [511028.6401063399, 6651158.458661975, 66.53291794863779], + [511028.5434350239, 6651158.900071804, 67.33828003463779], + [511028.6569376374, 6651158.381808774, 66.9572450686378], + [511028.5686906691, 6651158.784752281, 67.6999860196378], + [511028.68307050783, 6651158.262483762, 67.38355541963779], + [511028.60010923236, 6651158.641292327, 68.05774386563779], + [511028.7188222611, 6651158.099238075, 67.80536427863778], + [511028.6376944665, 6651158.469674803, 68.40820008063778], + [511028.7642359875, 6651157.89187496, 68.21571382163779], + [511028.6813399279, 6651158.270385743, 68.74794510763779], + [511028.81904903054, 6651157.641593728, 68.60749351563778], + [511028.73082527803, 6651158.044431232, 69.0736122176378], + [511028.8659905114, 6651157.42725475, 68.8849753756378], + [511028.78581748967, 6651157.793331902, 69.38198102563778], + [511028.91754243587, 6651157.191864077, 69.1454160486378], + [511028.8458772076, 6651157.519093884, 69.67007937663779], + [511028.97325990116, 6651156.937453172, 69.38638569463778], + [511028.9104700983, 6651157.224157, 69.9352771016378], + [511029.03262307873, 6651156.666395621, 69.6058047006378], + [511028.978982597, 6651156.911322834, 70.17536554863779], + [511029.11643860297, 6651156.283686481, 69.8620178236378], + [511029.0507410867, 6651156.583667185, 70.38861788363779], + [511029.2042268743, 6651155.882837423, 70.07429563263779], + [511029.12503326917, 6651156.244442471, 70.57382678563779], + [511029.2944666982, 6651155.470794357, 70.24141038963779], + [511029.20113034814, 6651155.8969764365, 70.73031807763779], + [511029.38566955045, 6651155.054354019, 70.36356351163778], + [511029.2783086558, 6651155.544573417, 70.85794083663778], + [511029.3558694937, 6651155.19042373, 70.95703633063779], + [511029.4764481195, 6651154.639850996, 70.44223820463779], + [511029.56556915335, 6651154.232916427, 70.47998106363778], + [511029.458751872, 6651154.720653636, 71.04620098263779], + [511029.5597557107, 6651154.2594611235, 71.08897622363779], + [511031.2410696749, 6651146.582431968, 64.08371371663779], + [511031.2410696749, 6651146.582431968, 64.21371371663778], + [511031.37148492254, 6651145.986944344, 64.08371371663779], + [511029.9321730401, 6651152.558970461, 70.47998106363778], + [511031.2410696749, 6651146.582431968, 65.91251737563779], + [511031.2371131129, 6651146.600497983, 66.3233326876378], + [511031.37148492254, 6651145.986944344, 65.91251737563779], + [511030.30655989476, 6651150.849486773, 70.47998106363778], + [511031.224740416, 6651146.656992819, 66.74445411563778], + [511030.3956809287, 6651150.442552201, 70.44223820463779], + [511031.36700081883, 6651146.007419161, 66.37810806263779], + [511031.2033134416, 6651146.75483029, 67.17054325063779], + [511030.31237383815, 6651150.822939789, 71.08897622363779], + [511030.48645949777, 6651150.028049178, 70.36356351163778], + [511031.17239460396, 6651146.896008453, 67.59544975463778], + [511031.35297842906, 6651146.071446641, 66.85537901463779], + [511030.5776623499, 6651149.6116088405, 70.24141038963779], + [511030.4133776768, 6651150.361747275, 71.04620098263779], + [511031.1317986578, 6651147.081373155, 68.01241645663778], + [511030.66790217394, 6651149.199565775, 70.07429563263779], + [511031.3286945249, 6651146.182329107, 67.33828003463779], + [511031.08163264394, 6651147.310435638, 68.41436537363779], + [511030.75569044525, 6651148.798716717, 69.8620178236378], + [511030.51626005507, 6651149.891977183, 70.95703633063779], + [511031.02231751644, 6651147.581273788, 68.79424617563778], + [511030.8395059694, 6651148.416007577, 69.6058047006378], + [511030.9722570751, 6651147.809854217, 69.06065249063778], + [511030.91787376313, 6651148.058173259, 69.30836223063778], + [511031.3034388796, 6651146.29764863, 67.6999860196378], + [511030.59382089303, 6651149.5378274955, 70.85794083663778], + [511031.27202031645, 6651146.441108585, 68.05774386563779], + [511030.67099920067, 6651149.185424476, 70.73031807763779], + [511031.2344350823, 6651146.61272611, 68.40820008063778], + [511030.74709627964, 6651148.837958442, 70.57382678563779], + [511031.1907896209, 6651146.812015168, 68.74794510763779], + [511030.8213884621, 6651148.498733727, 70.38861788363779], + [511031.1413042708, 6651147.037969681, 69.0736122176378], + [511030.8931469518, 6651148.171078078, 70.17536554863779], + [511031.08631205914, 6651147.289069012, 69.38198102563778], + [511030.96165945055, 6651147.858243913, 69.9352771016378], + [511031.0262523412, 6651147.563307027, 69.67007937663779], + [511038.1734005084, 6651161.241404697, 63.77831790688605], + [511038.3070497575, 6651160.646634553, 63.77831790688605], + [511038.3070497575, 6651160.646634553, 63.90831790688606], + [511038.1734005084, 6651161.241404697, 65.60712156588606], + [511038.17799580767, 6651161.2209545495, 66.07271225288605], + [511038.3070492447, 6651160.646636833, 65.60712156688605], + [511038.3080457937, 6651160.64220196, 65.81094285088605], + [511038.19236592087, 6651161.157004214, 66.54998320488606], + [511038.3163205552, 6651160.605377353, 66.22752213888606], + [511038.21725201065, 6651161.0462553445, 67.03288422488606], + [511038.33356923074, 6651160.528616747, 66.65184925888606], + [511038.24313393835, 6651160.931074766, 67.39459020988606], + [511038.3603501369, 6651160.409435506, 67.07815960988606], + [511038.2753316105, 6651160.787787661, 67.75234805588606], + [511038.3969884523, 6651160.2463865075, 67.49996846888605], + [511038.31384887296, 6651160.616376911, 68.10280427088607], + [511038.4435283358, 6651160.039273236, 67.91031801188608], + [511038.3585766425, 6651160.417327967, 68.44254929788606], + [511038.4997006175, 6651159.789293559, 68.30209770588606], + [511038.4092891167, 6651160.191645699, 68.76821640788606], + [511038.5478061403, 6651159.575212829, 68.57957956588605], + [511038.4656450101, 6651159.940848907, 69.07658521588606], + [511038.60063643527, 6651159.340105767, 68.84002023888605], + [511038.52719407243, 6651159.666941309, 69.36468356688606], + [511038.657735567, 6651159.086001392, 69.08098988488605], + [511038.5933887199, 6651159.3723597815, 69.62988129188605], + [511038.71857081633, 6651158.815270428, 69.30040889088606], + [511038.66360017273, 6651159.059902538, 69.86996973888606], + [511038.80446477485, 6651158.433022398, 69.55662201388606], + [511038.73713810963, 6651158.732641668, 70.08322207388606], + [511038.89442999556, 6651158.032656307, 69.76889982288606], + [511038.8132725692, 6651158.393825671, 70.26843097588606], + [511038.9869075619, 6651157.621109696, 69.93601457988606], + [511038.89125668263, 6651158.046778286, 70.42492226788607], + [511039.0803720374, 6651157.20517111, 70.05816770188605], + [511038.97034883674, 6651157.694799862, 70.55254502688607], + [511039.049833007, 6651157.341076876, 70.65164052088606], + [511039.1734017084, 6651156.791167505, 70.13684239488606], + [511039.26473274117, 6651156.384723234, 70.17458525388605], + [511039.1552666343, 6651156.871872789, 70.74080517288606], + [511039.2587751383, 6651156.411235948, 70.78358041388606], + [511040.981781864, 6651148.743456536, 63.77831790688605], + [511040.981781864, 6651148.743456536, 63.90831790688606], + [511039.6404275704, 6651154.712794139, 70.17458525388605], + [511041.115431113, 6651148.148686391, 63.77831790688605], + [511040.981781864, 6651148.743456536, 65.60712156588606], + [511040.9777271882, 6651148.761500784, 66.01793687788606], + [511040.02409836726, 6651153.005370137, 70.17458525388605], + [511041.115431113, 6651148.148686391, 65.60712156588606], + [511040.11542940006, 6651152.598925866, 70.13684239488606], + [511040.9650476766, 6651148.8179275505, 66.43905830588605], + [511041.11083581386, 6651148.169136538, 66.07271225288605], + [511040.0300564831, 6651152.978855141, 70.78358041388606], + [511040.2084590711, 6651152.184922261, 70.05816770188605], + [511040.943089362, 6651148.915647141, 66.86514744088608], + [511040.30192354653, 6651151.768983676, 69.93601457988606], + [511040.91140380746, 6651149.056655205, 67.29005394488605], + [511040.1335649872, 6651152.518218298, 70.74080517288606], + [511041.09646570054, 6651148.233086874, 66.54998320488606], + [511040.39440111286, 6651151.357437064, 69.76889982288606], + [511040.86980117427, 6651149.241796569, 67.70702064688605], + [511040.4843663336, 6651150.957070973, 69.55662201388606], + [511040.8183911574, 6651149.470583063, 68.10896956388605], + [511040.23899861454, 6651152.049014212, 70.65164052088606], + [511041.07157961087, 6651148.343835743, 67.03288422488606], + [511040.5702602921, 6651150.574822943, 69.30040889088606], + [511040.7576051497, 6651149.74109489, 68.48885036588607], + [511040.7063033231, 6651149.969399913, 68.75525668088605], + [511040.6505714288, 6651150.217419764, 69.00296642088605], + [511040.3184827848, 6651151.695291226, 70.55254502688607], + [511041.04569768306, 6651148.459016323, 67.39459020988606], + [511040.3975749388, 6651151.343312804, 70.42492226788607], + [511041.013500011, 6651148.602303429, 67.75234805588606], + [511040.4755590523, 6651150.996265417, 70.26843097588606], + [511040.97498274845, 6651148.773714176, 68.10280427088607], + [511040.5516935118, 6651150.65744942, 70.08322207388606], + [511040.93025497894, 6651148.972763121, 68.44254929788606], + [511040.62523144885, 6651150.33018855, 69.86996973888606], + [511040.8795425047, 6651149.198445389, 68.76821640788606], + [511040.69544290163, 6651150.017731307, 69.62988129188605], + [511040.8231866113, 6651149.449242182, 69.07658521588606], + [511040.76163754903, 6651149.723149778, 69.36468356688606], + [511042.263431685, 6651162.165406717, 63.646292658619146], + [511042.39844840026, 6651161.570945504, 63.646292658619146], + [511042.39844840026, 6651161.570945504, 63.776292658619155], + [511042.263431685, 6651162.165406717, 65.47509631761915], + [511042.2680740021, 6651162.144967193, 65.94068700461915], + [511042.3984478822, 6651161.570947786, 65.47509631861915], + [511042.39945462754, 6651161.566515215, 65.67891760261917], + [511042.2825911469, 6651162.081050075, 66.41795795661916], + [511042.4078140545, 6651161.529709735, 66.09549689061915], + [511042.307731865, 6651161.970358729, 66.90085897661915], + [511042.42523921415, 6651161.452989, 66.51982401061915], + [511042.33387861017, 6651161.855237977, 67.26256496161915], + [511042.452294136, 6651161.333869664, 66.94613436161914], + [511042.36640572094, 6651161.712025296, 67.62032280761915], + [511042.48930732557, 6651161.170905354, 67.36794322061917], + [511042.40531708254, 6651161.54070358, 67.97077902261915], + [511042.53632339375, 6651160.96389966, 67.77829276361915], + [511042.4505024956, 6651161.341758025, 68.31052404961915], + [511042.5930704165, 6651160.714049825, 68.17007245761916], + [511042.50173384737, 6651161.116192979, 68.63619115961914], + [511042.6416681431, 6651160.500080292, 68.44755431761915], + [511042.5586663605, 6651160.8655264545, 68.94455996761916], + [511042.69503898453, 6651160.265095349, 68.70799499061916], + [511042.62084517756, 6651160.591761129, 69.23265831861914], + [511042.75272234064, 6651160.011122961, 68.94896463661917], + [511042.68771711236, 6651160.297332611, 69.49785604361915], + [511042.81418004126, 6651159.740532617, 69.16838364261915], + [511042.7586469514, 6651159.985037661, 69.73794449061916], + [511042.9009528455, 6651159.358483133, 69.42459676561916], + [511042.83293731045, 6651159.657946776, 69.95119682561915], + [511042.99183856824, 6651158.958324998, 69.63687457461916], + [511042.90985075914, 6651159.319306764, 70.13640572761916], + [511043.0852623423, 6651158.546992149, 69.80398933161915], + [511042.9886327868, 6651158.972439639, 70.29289701961915], + [511043.17968312325, 6651158.131269607, 69.92614245361915], + [511043.0685341923, 6651158.620644039, 70.42051977861915], + [511043.148831625, 6651158.267104781, 70.51961527261915], + [511043.2736646509, 6651157.717481041, 70.00481714661915], + [511043.36593016033, 6651157.311247882, 70.04256000561917], + [511043.2553440232, 6651157.798144408, 70.60877992461916], + [511043.3599116008, 6651157.337746827, 70.65155516561916], + [511045.10054770694, 6651149.673950167, 63.646292658619146], + [511045.10054770694, 6651149.673950167, 63.776292658619155], + [511043.7454690065, 6651155.640187212, 70.04256000561917], + [511045.23556442215, 6651149.079488954, 63.646292658619146], + [511045.10054770694, 6651149.673950167, 65.47509631761915], + [511044.13306542847, 6651153.933650071, 70.04256000561917], + [511045.0964515448, 6651149.691985042, 65.88591162961914], + [511045.23556442215, 6651149.079488954, 65.47509631761915], + [511044.225330938, 6651153.527416913, 70.00481714661915], + [511045.0836422994, 6651149.7483825, 66.30703305761915], + [511044.1390845064, 6651153.907148846, 70.65155516561916], + [511044.3193124656, 6651153.113628346, 69.92614245361915], + [511045.23092210497, 6651149.09992848, 65.94068700461915], + [511045.06145931274, 6651149.8460513335, 66.73312219261915], + [511044.4137332466, 6651152.697905804, 69.80398933161915], + [511045.0294495594, 6651149.986986156, 67.15802869661917], + [511044.2436520839, 6651153.446751265, 70.60877992461916], + [511045.21640496026, 6651149.163845598, 66.41795795661916], + [511044.5071570207, 6651152.286572957, 69.63687457461916], + [511044.98742125835, 6651150.172031355, 67.57499539861915], + [511044.59804274334, 6651151.886414822, 69.42459676561916], + [511044.35016448214, 6651152.977790889, 70.51961527261915], + [511044.93548522686, 6651150.400699014, 67.97694431561915], + [511045.1912642422, 6651149.274536943, 66.90085897661915], + [511044.6848155476, 6651151.504365336, 69.16838364261915], + [511044.87407727167, 6651150.6710703345, 68.35682511761915], + [511044.8222505375, 6651150.899256771, 68.62323143261916], + [511044.76594840817, 6651151.147147799, 68.87094117261915], + [511044.43046191486, 6651152.624251632, 70.42051977861915], + [511045.1651174969, 6651149.389657696, 67.26256496161915], + [511044.51036332035, 6651152.272456031, 70.29289701961915], + [511045.13259038614, 6651149.5328703765, 67.62032280761915], + [511044.589145348, 6651151.925588907, 70.13640572761916], + [511045.09367902455, 6651149.704192091, 67.97077902261915], + [511044.66605879663, 6651151.586948897, 69.95119682561915], + [511045.04849361157, 6651149.903137647, 68.31052404961915], + [511044.74034915573, 6651151.25985801, 69.73794449061916], + [511044.9972622597, 6651150.128702692, 68.63619115961914], + [511044.8112789948, 6651150.9475630615, 69.49785604361915], + [511044.94032974663, 6651150.379369217, 68.94455996761916], + [511044.8781509296, 6651150.653134543, 69.23265831861914], + [511048.11355399096, 6651163.504241231, 63.45445553490367], + [511048.2505266435, 6651162.910227645, 63.45445553490367], + [511048.2505266435, 6651162.910227645, 63.584455534903675], + [511048.11355399096, 6651163.504241231, 65.28325919390367], + [511048.11826355965, 6651163.483817097, 65.74884988090368], + [511048.2505261179, 6651162.910229924, 65.28325919490368], + [511048.2515474477, 6651162.905800693, 65.48708047890366], + [511048.13299100887, 6651163.4199481085, 66.22612083290367], + [511048.26002797455, 6651162.869022926, 65.90365976690367], + [511048.15849593125, 6651163.309340114, 66.70902185290367], + [511048.277705566, 6651162.792359963, 66.32798688690369], + [511048.18502145476, 6651163.194306046, 67.07072783790368], + [511048.30515242246, 6651162.673330323, 66.75429723790367], + [511048.2180197737, 6651163.051201204, 67.42848568390367], + [511048.3427018085, 6651162.510488725, 67.17610609690367], + [511048.2574948299, 6651162.8800084945, 67.77894189890367], + [511048.3903989811, 6651162.303638905, 67.58645563990368], + [511048.30333482736, 6651162.681212743, 68.11868692590367], + [511048.4479680769, 6651162.053977206, 67.97823533390367], + [511048.3553083488, 6651162.455817548, 68.44435403590369], + [511048.497269821, 6651161.840168792, 68.25571719390368], + [511048.41306562215, 6651162.2053397745, 68.75272284390367], + [511048.5514138261, 6651161.605360792, 68.51615786690368], + [511048.47614520084, 6651161.931780593, 69.04082119490367], + [511048.60993281956, 6651161.351579643, 68.75712751290366], + [511048.5439858846, 6651161.637573778, 69.30601891990368], + [511048.6722808353, 6651161.081193054, 68.97654651890369], + [511048.6159432581, 6651161.325513987, 69.54610736690368], + [511048.7603106852, 6651160.699431251, 69.23275964190368], + [511048.69130983413, 6651160.9986694, 69.75935970190368], + [511048.8525130357, 6651160.299574434, 69.44503745090367], + [511048.76933749946, 6651160.660284384, 69.94456860390368], + [511048.9472902055, 6651159.888551319, 69.61215220790369], + [511048.8492608134, 6651160.313678448, 70.10105989590367], + [511048.93031972094, 6651159.96214775, 70.22868265490368], + [511049.0430788254, 6651159.473141815, 69.73430532990369], + [511049.01178039296, 6651159.608874706, 70.32777814890368], + [511049.13842182886, 6651159.0596648315, 69.81298002290367], + [511049.2320239546, 6651158.6537375655, 69.85072288190366], + [511049.11983579694, 6651159.140267456, 70.41694280090367], + [511049.22591820644, 6651158.680216554, 70.45971804190367], + [511050.99177026504, 6651151.022190713, 63.45445553490367], + [511050.99177026504, 6651151.022190713, 63.584455534903675], + [511049.61706103984, 6651156.983935197, 69.85072288190366], + [511051.1287429177, 6651150.428177127, 63.45445553490367], + [511050.99177026504, 6651151.022190713, 65.28325919390367], + [511050.01027242816, 6651155.278683073, 69.85072288190366], + [511050.9876147634, 6651151.040212006, 65.69407450590369], + [511050.103874554, 6651154.872755808, 69.81298002290367], + [511051.1287429177, 6651150.428177127, 65.28325919390367], + [511050.9746199552, 6651151.0965669975, 66.11519593390366], + [511050.0163787022, 6651155.252201804, 70.45971804190367], + [511050.1992175574, 6651154.459278824, 69.73430532990369], + [511051.12403334887, 6651150.448601262, 65.74884988090368], + [511050.95211561176, 6651151.194162289, 66.54128506890368], + [511050.2950061773, 6651154.043869319, 69.61215220790369], + [511050.1224611116, 6651154.792150903, 70.41694280090367], + [511050.919642145, 6651151.334990987, 66.96619157290367], + [511051.10930589976, 6651150.51247025, 66.22612083290367], + [511050.3897833471, 6651153.632846204, 69.44503745090367], + [511050.8770049955, 6651151.519896845, 67.38315827490366], + [511050.2305165157, 6651154.323543652, 70.32777814890368], + [511050.4819856976, 6651153.232989387, 69.23275964190368], + [511050.82431658584, 6651151.74839232, 67.78510719190368], + [511050.5700155475, 6651152.851227584, 68.97654651890369], + [511051.08380097727, 6651150.623078245, 66.70902185290367], + [511050.7620190362, 6651152.018560051, 68.16498799390367], + [511050.65232374985, 6651152.49427903, 68.67910404890367], + [511050.70944150735, 6651152.2465746645, 68.43139430890366], + [511050.3119771876, 6651153.970270609, 70.22868265490368], + [511051.0572754539, 6651150.738112312, 67.07072783790368], + [511050.39303609525, 6651153.6187399095, 70.10105989590367], + [511051.0242771348, 6651150.881217155, 67.42848568390367], + [511050.47295940906, 6651153.272133974, 69.94456860390368], + [511050.98480207863, 6651151.052409864, 67.77894189890367], + [511050.5509870744, 6651152.933748959, 69.75935970190368], + [511050.9389620813, 6651151.251205615, 68.11868692590367], + [511050.6263536504, 6651152.606904372, 69.54610736690368], + [511050.88698855985, 6651151.476600811, 68.44435403590369], + [511050.69831102394, 6651152.294844581, 69.30601891990368], + [511050.8292312865, 6651151.727078585, 68.75272284390367], + [511050.7661517078, 6651152.000637765, 69.04082119490367] + ], + "pointIndex": [ + 2, + 1, + 83, + 84, + 0, + 1, + 4, + 86, + 83, + 0, + 4, + 5, + 87, + 86, + 0, + 5, + 6, + 88, + 87, + 0, + 6, + 9, + 91, + 88, + 0, + 9, + 11, + 93, + 91, + 0, + 11, + 13, + 95, + 93, + 0, + 13, + 15, + 97, + 95, + 0, + 15, + 17, + 99, + 97, + 0, + 17, + 19, + 102, + 99, + 0, + 19, + 21, + 104, + 102, + 0, + 21, + 23, + 109, + 104, + 0, + 23, + 26, + 113, + 109, + 0, + 26, + 28, + 118, + 113, + 0, + 28, + 29, + 123, + 118, + 0, + 29, + 31, + 127, + 123, + 0, + 31, + 33, + 131, + 127, + 0, + 33, + 35, + 135, + 131, + 0, + 35, + 37, + 139, + 135, + 0, + 37, + 39, + 143, + 139, + 0, + 39, + 41, + 149, + 143, + 0, + 41, + 44, + 166, + 149, + 0, + 44, + 47, + 170, + 166, + 0, + 47, + 51, + 174, + 170, + 0, + 51, + 54, + 177, + 174, + 0, + 54, + 56, + 179, + 177, + 0, + 56, + 60, + 184, + 179, + 0, + 60, + 64, + 188, + 184, + 0, + 64, + 71, + 195, + 188, + 0, + 71, + 73, + 197, + 195, + 0, + 73, + 74, + 198, + 197, + 0, + 74, + 76, + 200, + 198, + 0, + 76, + 78, + 202, + 200, + 0, + 78, + 80, + 204, + 202, + 0, + 80, + 82, + 206, + 204, + 0, + 82, + 81, + 205, + 206, + 0, + 81, + 79, + 203, + 205, + 0, + 79, + 77, + 201, + 203, + 0, + 77, + 75, + 199, + 201, + 0, + 75, + 72, + 196, + 199, + 0, + 72, + 69, + 193, + 196, + 0, + 69, + 53, + 176, + 193, + 0, + 53, + 48, + 171, + 176, + 0, + 48, + 49, + 172, + 171, + 0, + 49, + 57, + 181, + 172, + 0, + 57, + 59, + 183, + 181, + 0, + 59, + 62, + 186, + 183, + 0, + 62, + 65, + 189, + 186, + 0, + 65, + 67, + 191, + 189, + 0, + 67, + 70, + 194, + 191, + 0, + 70, + 68, + 192, + 194, + 0, + 68, + 66, + 190, + 192, + 0, + 66, + 63, + 187, + 190, + 0, + 63, + 61, + 185, + 187, + 0, + 61, + 58, + 182, + 185, + 0, + 58, + 55, + 178, + 182, + 0, + 55, + 52, + 175, + 178, + 0, + 52, + 50, + 173, + 175, + 0, + 50, + 46, + 169, + 173, + 0, + 46, + 45, + 167, + 169, + 0, + 45, + 43, + 164, + 167, + 0, + 43, + 42, + 156, + 164, + 0, + 42, + 40, + 146, + 156, + 0, + 40, + 38, + 142, + 146, + 0, + 38, + 36, + 137, + 142, + 0, + 36, + 34, + 133, + 137, + 0, + 34, + 32, + 128, + 133, + 0, + 32, + 30, + 124, + 128, + 0, + 30, + 27, + 117, + 124, + 0, + 27, + 25, + 112, + 117, + 0, + 25, + 24, + 110, + 112, + 0, + 24, + 22, + 106, + 110, + 0, + 22, + 20, + 103, + 106, + 0, + 20, + 18, + 100, + 103, + 0, + 18, + 16, + 98, + 100, + 0, + 16, + 14, + 96, + 98, + 0, + 14, + 12, + 94, + 96, + 0, + 12, + 10, + 92, + 94, + 0, + 10, + 8, + 90, + 92, + 0, + 8, + 7, + 89, + 90, + 0, + 7, + 3, + 85, + 89, + 0, + 3, + 2, + 84, + 85, + 0, + 84, + 83, + 101, + 105, + 0, + 83, + 86, + 108, + 101, + 0, + 86, + 87, + 111, + 108, + 0, + 87, + 88, + 114, + 111, + 0, + 88, + 91, + 119, + 114, + 0, + 91, + 93, + 121, + 119, + 0, + 93, + 95, + 125, + 121, + 0, + 95, + 97, + 129, + 125, + 0, + 97, + 99, + 132, + 129, + 0, + 99, + 102, + 136, + 132, + 0, + 102, + 104, + 140, + 136, + 0, + 104, + 109, + 144, + 140, + 0, + 109, + 113, + 148, + 144, + 0, + 113, + 118, + 151, + 148, + 0, + 118, + 123, + 152, + 151, + 0, + 123, + 127, + 154, + 152, + 0, + 127, + 131, + 157, + 154, + 0, + 131, + 135, + 159, + 157, + 0, + 135, + 139, + 161, + 159, + 0, + 139, + 143, + 163, + 161, + 0, + 143, + 149, + 168, + 163, + 0, + 149, + 166, + 208, + 168, + 0, + 166, + 170, + 211, + 208, + 0, + 170, + 174, + 215, + 211, + 0, + 174, + 177, + 218, + 215, + 0, + 177, + 179, + 220, + 218, + 0, + 179, + 184, + 224, + 220, + 0, + 184, + 188, + 228, + 224, + 0, + 188, + 195, + 235, + 228, + 0, + 195, + 197, + 237, + 235, + 0, + 197, + 198, + 238, + 237, + 0, + 198, + 200, + 240, + 238, + 0, + 200, + 202, + 242, + 240, + 0, + 202, + 204, + 244, + 242, + 0, + 204, + 206, + 246, + 244, + 0, + 206, + 205, + 245, + 246, + 0, + 205, + 203, + 243, + 245, + 0, + 203, + 201, + 241, + 243, + 0, + 201, + 199, + 239, + 241, + 0, + 199, + 196, + 236, + 239, + 0, + 196, + 193, + 233, + 236, + 0, + 193, + 176, + 217, + 233, + 0, + 176, + 171, + 212, + 217, + 0, + 171, + 172, + 213, + 212, + 0, + 172, + 181, + 221, + 213, + 0, + 181, + 183, + 223, + 221, + 0, + 183, + 186, + 226, + 223, + 0, + 186, + 189, + 229, + 226, + 0, + 189, + 191, + 231, + 229, + 0, + 191, + 194, + 234, + 231, + 0, + 194, + 192, + 232, + 234, + 0, + 192, + 190, + 230, + 232, + 0, + 190, + 187, + 227, + 230, + 0, + 187, + 185, + 225, + 227, + 0, + 185, + 182, + 222, + 225, + 0, + 182, + 178, + 219, + 222, + 0, + 178, + 175, + 216, + 219, + 0, + 175, + 173, + 214, + 216, + 0, + 173, + 169, + 210, + 214, + 0, + 169, + 167, + 209, + 210, + 0, + 167, + 164, + 207, + 209, + 0, + 164, + 156, + 180, + 207, + 0, + 156, + 146, + 165, + 180, + 0, + 146, + 142, + 162, + 165, + 0, + 142, + 137, + 160, + 162, + 0, + 137, + 133, + 158, + 160, + 0, + 133, + 128, + 155, + 158, + 0, + 128, + 124, + 153, + 155, + 0, + 124, + 117, + 150, + 153, + 0, + 117, + 112, + 147, + 150, + 0, + 112, + 110, + 145, + 147, + 0, + 110, + 106, + 141, + 145, + 0, + 106, + 103, + 138, + 141, + 0, + 103, + 100, + 134, + 138, + 0, + 100, + 98, + 130, + 134, + 0, + 98, + 96, + 126, + 130, + 0, + 96, + 94, + 122, + 126, + 0, + 94, + 92, + 120, + 122, + 0, + 92, + 90, + 116, + 120, + 0, + 90, + 89, + 115, + 116, + 0, + 89, + 85, + 107, + 115, + 0, + 85, + 84, + 105, + 107, + 0, + 105, + 101, + 247, + 249, + 0, + 101, + 108, + 253, + 247, + 0, + 108, + 111, + 255, + 253, + 0, + 111, + 114, + 257, + 255, + 0, + 114, + 119, + 262, + 257, + 0, + 119, + 121, + 267, + 262, + 0, + 121, + 125, + 271, + 267, + 0, + 125, + 129, + 275, + 271, + 0, + 129, + 132, + 279, + 275, + 0, + 132, + 136, + 283, + 279, + 0, + 136, + 140, + 287, + 283, + 0, + 140, + 144, + 291, + 287, + 0, + 144, + 148, + 296, + 291, + 0, + 148, + 151, + 300, + 296, + 0, + 151, + 152, + 303, + 300, + 0, + 152, + 154, + 307, + 303, + 0, + 154, + 157, + 311, + 307, + 0, + 157, + 159, + 314, + 311, + 0, + 159, + 161, + 318, + 314, + 0, + 161, + 163, + 322, + 318, + 0, + 163, + 168, + 327, + 322, + 0, + 168, + 208, + 333, + 327, + 0, + 208, + 211, + 338, + 333, + 0, + 211, + 215, + 346, + 338, + 0, + 215, + 218, + 351, + 346, + 0, + 218, + 220, + 356, + 351, + 0, + 220, + 224, + 362, + 356, + 0, + 224, + 228, + 369, + 362, + 0, + 228, + 235, + 379, + 369, + 0, + 235, + 237, + 388, + 379, + 0, + 237, + 238, + 392, + 388, + 0, + 238, + 240, + 395, + 392, + 0, + 240, + 242, + 397, + 395, + 0, + 242, + 244, + 401, + 397, + 0, + 244, + 246, + 403, + 401, + 0, + 246, + 245, + 400, + 403, + 0, + 245, + 243, + 398, + 400, + 0, + 243, + 241, + 396, + 398, + 0, + 241, + 239, + 391, + 396, + 0, + 239, + 236, + 384, + 391, + 0, + 236, + 233, + 374, + 384, + 0, + 233, + 217, + 348, + 374, + 0, + 217, + 212, + 339, + 348, + 0, + 212, + 213, + 340, + 339, + 0, + 213, + 221, + 357, + 340, + 0, + 221, + 223, + 360, + 357, + 0, + 223, + 226, + 365, + 360, + 0, + 226, + 229, + 370, + 365, + 0, + 229, + 231, + 373, + 370, + 0, + 231, + 234, + 377, + 373, + 0, + 234, + 232, + 376, + 377, + 0, + 232, + 230, + 372, + 376, + 0, + 230, + 227, + 368, + 372, + 0, + 227, + 225, + 364, + 368, + 0, + 225, + 222, + 358, + 364, + 0, + 222, + 219, + 354, + 358, + 0, + 219, + 216, + 349, + 354, + 0, + 216, + 214, + 344, + 349, + 0, + 214, + 210, + 337, + 344, + 0, + 210, + 209, + 334, + 337, + 0, + 209, + 207, + 331, + 334, + 0, + 207, + 180, + 329, + 331, + 0, + 180, + 165, + 324, + 329, + 0, + 165, + 162, + 321, + 324, + 0, + 162, + 160, + 316, + 321, + 0, + 160, + 158, + 312, + 316, + 0, + 158, + 155, + 308, + 312, + 0, + 155, + 153, + 304, + 308, + 0, + 153, + 150, + 299, + 304, + 0, + 150, + 147, + 295, + 299, + 0, + 147, + 145, + 292, + 295, + 0, + 145, + 141, + 288, + 292, + 0, + 141, + 138, + 284, + 288, + 0, + 138, + 134, + 280, + 284, + 0, + 134, + 130, + 276, + 280, + 0, + 130, + 126, + 272, + 276, + 0, + 126, + 122, + 268, + 272, + 0, + 122, + 120, + 263, + 268, + 0, + 120, + 116, + 259, + 263, + 0, + 116, + 115, + 258, + 259, + 0, + 115, + 107, + 250, + 258, + 0, + 107, + 105, + 249, + 250, + 0, + 249, + 247, + 248, + 251, + 0, + 247, + 253, + 254, + 248, + 0, + 253, + 255, + 256, + 254, + 0, + 255, + 257, + 260, + 256, + 0, + 257, + 262, + 265, + 260, + 0, + 262, + 267, + 269, + 265, + 0, + 267, + 271, + 273, + 269, + 0, + 271, + 275, + 277, + 273, + 0, + 275, + 279, + 281, + 277, + 0, + 279, + 283, + 285, + 281, + 0, + 283, + 287, + 289, + 285, + 0, + 287, + 291, + 293, + 289, + 0, + 291, + 296, + 298, + 293, + 0, + 296, + 300, + 302, + 298, + 0, + 300, + 303, + 305, + 302, + 0, + 303, + 307, + 309, + 305, + 0, + 307, + 311, + 313, + 309, + 0, + 311, + 314, + 317, + 313, + 0, + 314, + 318, + 320, + 317, + 0, + 318, + 322, + 325, + 320, + 0, + 322, + 327, + 328, + 325, + 0, + 327, + 333, + 335, + 328, + 0, + 333, + 338, + 342, + 335, + 0, + 338, + 346, + 350, + 342, + 0, + 346, + 351, + 355, + 350, + 0, + 351, + 356, + 361, + 355, + 0, + 356, + 362, + 371, + 361, + 0, + 362, + 369, + 381, + 371, + 0, + 369, + 379, + 390, + 381, + 0, + 379, + 388, + 394, + 390, + 0, + 388, + 392, + 402, + 394, + 0, + 392, + 395, + 404, + 402, + 0, + 395, + 397, + 406, + 404, + 0, + 397, + 401, + 409, + 406, + 0, + 401, + 403, + 410, + 409, + 0, + 403, + 400, + 408, + 410, + 0, + 400, + 398, + 407, + 408, + 0, + 398, + 396, + 405, + 407, + 0, + 396, + 391, + 399, + 405, + 0, + 391, + 384, + 393, + 399, + 0, + 384, + 374, + 386, + 393, + 0, + 374, + 348, + 352, + 386, + 0, + 348, + 339, + 343, + 352, + 0, + 339, + 340, + 345, + 343, + 0, + 340, + 357, + 363, + 345, + 0, + 357, + 360, + 367, + 363, + 0, + 360, + 365, + 378, + 367, + 0, + 365, + 370, + 382, + 378, + 0, + 370, + 373, + 385, + 382, + 0, + 373, + 377, + 389, + 385, + 0, + 377, + 376, + 387, + 389, + 0, + 376, + 372, + 383, + 387, + 0, + 372, + 368, + 380, + 383, + 0, + 368, + 364, + 375, + 380, + 0, + 364, + 358, + 366, + 375, + 0, + 358, + 354, + 359, + 366, + 0, + 354, + 349, + 353, + 359, + 0, + 349, + 344, + 347, + 353, + 0, + 344, + 337, + 341, + 347, + 0, + 337, + 334, + 336, + 341, + 0, + 334, + 331, + 332, + 336, + 0, + 331, + 329, + 330, + 332, + 0, + 329, + 324, + 326, + 330, + 0, + 324, + 321, + 323, + 326, + 0, + 321, + 316, + 319, + 323, + 0, + 316, + 312, + 315, + 319, + 0, + 312, + 308, + 310, + 315, + 0, + 308, + 304, + 306, + 310, + 0, + 304, + 299, + 301, + 306, + 0, + 299, + 295, + 297, + 301, + 0, + 295, + 292, + 294, + 297, + 0, + 292, + 288, + 290, + 294, + 0, + 288, + 284, + 286, + 290, + 0, + 284, + 280, + 282, + 286, + 0, + 280, + 276, + 278, + 282, + 0, + 276, + 272, + 274, + 278, + 0, + 272, + 268, + 270, + 274, + 0, + 268, + 263, + 266, + 270, + 0, + 263, + 259, + 264, + 266, + 0, + 259, + 258, + 261, + 264, + 0, + 258, + 250, + 252, + 261, + 0, + 250, + 249, + 251, + 252, + 0, + 251, + 248, + 411, + 412, + 0, + 248, + 254, + 414, + 411, + 0, + 254, + 256, + 415, + 414, + 0, + 256, + 260, + 417, + 415, + 0, + 260, + 265, + 419, + 417, + 0, + 265, + 269, + 422, + 419, + 0, + 269, + 273, + 423, + 422, + 0, + 273, + 277, + 425, + 423, + 0, + 277, + 281, + 427, + 425, + 0, + 281, + 285, + 429, + 427, + 0, + 285, + 289, + 431, + 429, + 0, + 289, + 293, + 433, + 431, + 0, + 293, + 298, + 436, + 433, + 0, + 298, + 302, + 438, + 436, + 0, + 302, + 305, + 439, + 438, + 0, + 305, + 309, + 441, + 439, + 0, + 309, + 313, + 443, + 441, + 0, + 313, + 317, + 445, + 443, + 0, + 317, + 320, + 447, + 445, + 0, + 320, + 325, + 449, + 447, + 0, + 325, + 328, + 451, + 449, + 0, + 328, + 335, + 454, + 451, + 0, + 335, + 342, + 458, + 454, + 0, + 342, + 350, + 461, + 458, + 0, + 350, + 355, + 465, + 461, + 0, + 355, + 361, + 468, + 465, + 0, + 361, + 371, + 473, + 468, + 0, + 371, + 381, + 479, + 473, + 0, + 381, + 390, + 486, + 479, + 0, + 390, + 394, + 488, + 486, + 0, + 394, + 402, + 492, + 488, + 0, + 402, + 404, + 495, + 492, + 0, + 404, + 406, + 497, + 495, + 0, + 406, + 409, + 499, + 497, + 0, + 409, + 410, + 500, + 499, + 0, + 410, + 408, + 498, + 500, + 0, + 408, + 407, + 496, + 498, + 0, + 407, + 405, + 494, + 496, + 0, + 405, + 399, + 489, + 494, + 0, + 399, + 393, + 487, + 489, + 0, + 393, + 386, + 481, + 487, + 0, + 386, + 352, + 463, + 481, + 0, + 352, + 343, + 457, + 463, + 0, + 343, + 345, + 459, + 457, + 0, + 345, + 363, + 467, + 459, + 0, + 363, + 367, + 472, + 467, + 0, + 367, + 378, + 475, + 472, + 0, + 378, + 382, + 478, + 475, + 0, + 382, + 385, + 482, + 478, + 0, + 385, + 389, + 484, + 482, + 0, + 389, + 387, + 483, + 484, + 0, + 387, + 383, + 480, + 483, + 0, + 383, + 380, + 477, + 480, + 0, + 380, + 375, + 474, + 477, + 0, + 375, + 366, + 471, + 474, + 0, + 366, + 359, + 466, + 471, + 0, + 359, + 353, + 464, + 466, + 0, + 353, + 347, + 460, + 464, + 0, + 347, + 341, + 456, + 460, + 0, + 341, + 336, + 455, + 456, + 0, + 336, + 332, + 453, + 455, + 0, + 332, + 330, + 452, + 453, + 0, + 330, + 326, + 450, + 452, + 0, + 326, + 323, + 448, + 450, + 0, + 323, + 319, + 446, + 448, + 0, + 319, + 315, + 444, + 446, + 0, + 315, + 310, + 442, + 444, + 0, + 310, + 306, + 440, + 442, + 0, + 306, + 301, + 437, + 440, + 0, + 301, + 297, + 435, + 437, + 0, + 297, + 294, + 434, + 435, + 0, + 294, + 290, + 432, + 434, + 0, + 290, + 286, + 430, + 432, + 0, + 286, + 282, + 428, + 430, + 0, + 282, + 278, + 426, + 428, + 0, + 278, + 274, + 424, + 426, + 0, + 274, + 270, + 421, + 424, + 0, + 270, + 266, + 420, + 421, + 0, + 266, + 264, + 418, + 420, + 0, + 264, + 261, + 416, + 418, + 0, + 261, + 252, + 413, + 416, + 0, + 252, + 251, + 412, + 413, + 0, + 412, + 411, + 462, + 469, + 0, + 411, + 414, + 476, + 462, + 0, + 414, + 415, + 485, + 476, + 0, + 415, + 417, + 491, + 485, + 0, + 417, + 419, + 502, + 491, + 0, + 419, + 422, + 504, + 502, + 0, + 422, + 423, + 505, + 504, + 0, + 423, + 425, + 507, + 505, + 0, + 425, + 427, + 509, + 507, + 0, + 427, + 429, + 511, + 509, + 0, + 429, + 431, + 513, + 511, + 0, + 431, + 433, + 515, + 513, + 0, + 433, + 436, + 518, + 515, + 0, + 436, + 438, + 520, + 518, + 0, + 438, + 439, + 521, + 520, + 0, + 439, + 441, + 523, + 521, + 0, + 441, + 443, + 525, + 523, + 0, + 443, + 445, + 527, + 525, + 0, + 445, + 447, + 529, + 527, + 0, + 447, + 449, + 531, + 529, + 0, + 449, + 451, + 533, + 531, + 0, + 451, + 454, + 536, + 533, + 0, + 454, + 458, + 540, + 536, + 0, + 458, + 461, + 543, + 540, + 0, + 461, + 465, + 546, + 543, + 0, + 465, + 468, + 549, + 546, + 0, + 468, + 473, + 552, + 549, + 0, + 473, + 479, + 557, + 552, + 0, + 479, + 486, + 563, + 557, + 0, + 486, + 488, + 565, + 563, + 0, + 488, + 492, + 567, + 565, + 0, + 492, + 495, + 569, + 567, + 0, + 495, + 497, + 571, + 569, + 0, + 497, + 499, + 573, + 571, + 0, + 499, + 500, + 574, + 573, + 0, + 500, + 498, + 572, + 574, + 0, + 498, + 496, + 570, + 572, + 0, + 496, + 494, + 568, + 570, + 0, + 494, + 489, + 566, + 568, + 0, + 489, + 487, + 564, + 566, + 0, + 487, + 481, + 559, + 564, + 0, + 481, + 463, + 544, + 559, + 0, + 463, + 457, + 538, + 544, + 0, + 457, + 459, + 541, + 538, + 0, + 459, + 467, + 548, + 541, + 0, + 467, + 472, + 551, + 548, + 0, + 472, + 475, + 553, + 551, + 0, + 475, + 478, + 556, + 553, + 0, + 478, + 482, + 560, + 556, + 0, + 482, + 484, + 562, + 560, + 0, + 484, + 483, + 561, + 562, + 0, + 483, + 480, + 558, + 561, + 0, + 480, + 477, + 555, + 558, + 0, + 477, + 474, + 554, + 555, + 0, + 474, + 471, + 550, + 554, + 0, + 471, + 466, + 547, + 550, + 0, + 466, + 464, + 545, + 547, + 0, + 464, + 460, + 542, + 545, + 0, + 460, + 456, + 539, + 542, + 0, + 456, + 455, + 537, + 539, + 0, + 455, + 453, + 535, + 537, + 0, + 453, + 452, + 534, + 535, + 0, + 452, + 450, + 532, + 534, + 0, + 450, + 448, + 530, + 532, + 0, + 448, + 446, + 528, + 530, + 0, + 446, + 444, + 526, + 528, + 0, + 444, + 442, + 524, + 526, + 0, + 442, + 440, + 522, + 524, + 0, + 440, + 437, + 519, + 522, + 0, + 437, + 435, + 517, + 519, + 0, + 435, + 434, + 516, + 517, + 0, + 434, + 432, + 514, + 516, + 0, + 432, + 430, + 512, + 514, + 0, + 430, + 428, + 510, + 512, + 0, + 428, + 426, + 508, + 510, + 0, + 426, + 424, + 506, + 508, + 0, + 424, + 421, + 503, + 506, + 0, + 421, + 420, + 501, + 503, + 0, + 420, + 418, + 493, + 501, + 0, + 418, + 416, + 490, + 493, + 0, + 416, + 413, + 470, + 490, + 0, + 413, + 412, + 469, + 470, + 0, + 469, + 462, + 575, + 576, + 0, + 462, + 476, + 578, + 575, + 0, + 476, + 485, + 579, + 578, + 0, + 485, + 491, + 581, + 579, + 0, + 491, + 502, + 584, + 581, + 0, + 502, + 504, + 586, + 584, + 0, + 504, + 505, + 588, + 586, + 0, + 505, + 507, + 589, + 588, + 0, + 507, + 509, + 591, + 589, + 0, + 509, + 511, + 593, + 591, + 0, + 511, + 513, + 595, + 593, + 0, + 513, + 515, + 597, + 595, + 0, + 515, + 518, + 600, + 597, + 0, + 518, + 520, + 602, + 600, + 0, + 520, + 521, + 603, + 602, + 0, + 521, + 523, + 605, + 603, + 0, + 523, + 525, + 607, + 605, + 0, + 525, + 527, + 609, + 607, + 0, + 527, + 529, + 611, + 609, + 0, + 529, + 531, + 613, + 611, + 0, + 531, + 533, + 615, + 613, + 0, + 533, + 536, + 618, + 615, + 0, + 536, + 540, + 623, + 618, + 0, + 540, + 543, + 625, + 623, + 0, + 543, + 546, + 628, + 625, + 0, + 546, + 549, + 631, + 628, + 0, + 549, + 552, + 634, + 631, + 0, + 552, + 557, + 640, + 634, + 0, + 557, + 563, + 645, + 640, + 0, + 563, + 565, + 647, + 645, + 0, + 565, + 567, + 649, + 647, + 0, + 567, + 569, + 651, + 649, + 0, + 569, + 571, + 653, + 651, + 0, + 571, + 573, + 655, + 653, + 0, + 573, + 574, + 656, + 655, + 0, + 574, + 572, + 654, + 656, + 0, + 572, + 570, + 652, + 654, + 0, + 570, + 568, + 650, + 652, + 0, + 568, + 566, + 648, + 650, + 0, + 566, + 564, + 646, + 648, + 0, + 564, + 559, + 639, + 646, + 0, + 559, + 544, + 626, + 639, + 0, + 544, + 538, + 620, + 626, + 0, + 538, + 541, + 621, + 620, + 0, + 541, + 548, + 629, + 621, + 0, + 548, + 551, + 632, + 629, + 0, + 551, + 553, + 635, + 632, + 0, + 553, + 556, + 637, + 635, + 0, + 556, + 560, + 642, + 637, + 0, + 560, + 562, + 644, + 642, + 0, + 562, + 561, + 643, + 644, + 0, + 561, + 558, + 641, + 643, + 0, + 558, + 555, + 638, + 641, + 0, + 555, + 554, + 636, + 638, + 0, + 554, + 550, + 633, + 636, + 0, + 550, + 547, + 630, + 633, + 0, + 547, + 545, + 627, + 630, + 0, + 545, + 542, + 624, + 627, + 0, + 542, + 539, + 622, + 624, + 0, + 539, + 537, + 619, + 622, + 0, + 537, + 535, + 617, + 619, + 0, + 535, + 534, + 616, + 617, + 0, + 534, + 532, + 614, + 616, + 0, + 532, + 530, + 612, + 614, + 0, + 530, + 528, + 610, + 612, + 0, + 528, + 526, + 608, + 610, + 0, + 526, + 524, + 606, + 608, + 0, + 524, + 522, + 604, + 606, + 0, + 522, + 519, + 601, + 604, + 0, + 519, + 517, + 599, + 601, + 0, + 517, + 516, + 598, + 599, + 0, + 516, + 514, + 596, + 598, + 0, + 514, + 512, + 594, + 596, + 0, + 512, + 510, + 592, + 594, + 0, + 510, + 508, + 590, + 592, + 0, + 508, + 506, + 587, + 590, + 0, + 506, + 503, + 585, + 587, + 0, + 503, + 501, + 583, + 585, + 0, + 501, + 493, + 582, + 583, + 0, + 493, + 490, + 580, + 582, + 0, + 490, + 470, + 577, + 580, + 0, + 470, + 469, + 576, + 577, + 0, + 576, + 575, + 657, + 658, + 0, + 575, + 578, + 660, + 657, + 0, + 578, + 579, + 661, + 660, + 0, + 579, + 581, + 663, + 661, + 0, + 581, + 584, + 666, + 663, + 0, + 584, + 586, + 668, + 666, + 0, + 586, + 588, + 670, + 668, + 0, + 588, + 589, + 671, + 670, + 0, + 589, + 591, + 673, + 671, + 0, + 591, + 593, + 675, + 673, + 0, + 593, + 595, + 677, + 675, + 0, + 595, + 597, + 679, + 677, + 0, + 597, + 600, + 682, + 679, + 0, + 600, + 602, + 684, + 682, + 0, + 602, + 603, + 686, + 684, + 0, + 603, + 605, + 687, + 686, + 0, + 605, + 607, + 689, + 687, + 0, + 607, + 609, + 691, + 689, + 0, + 609, + 611, + 693, + 691, + 0, + 611, + 613, + 695, + 693, + 0, + 613, + 615, + 697, + 695, + 0, + 615, + 618, + 700, + 697, + 0, + 618, + 623, + 705, + 700, + 0, + 623, + 625, + 708, + 705, + 0, + 625, + 628, + 710, + 708, + 0, + 628, + 631, + 713, + 710, + 0, + 631, + 634, + 717, + 713, + 0, + 634, + 640, + 722, + 717, + 0, + 640, + 645, + 728, + 722, + 0, + 645, + 647, + 729, + 728, + 0, + 647, + 649, + 731, + 729, + 0, + 649, + 651, + 733, + 731, + 0, + 651, + 653, + 735, + 733, + 0, + 653, + 655, + 737, + 735, + 0, + 655, + 656, + 738, + 737, + 0, + 656, + 654, + 736, + 738, + 0, + 654, + 652, + 734, + 736, + 0, + 652, + 650, + 732, + 734, + 0, + 650, + 648, + 730, + 732, + 0, + 648, + 646, + 727, + 730, + 0, + 646, + 639, + 721, + 727, + 0, + 639, + 626, + 707, + 721, + 0, + 626, + 620, + 702, + 707, + 0, + 620, + 621, + 703, + 702, + 0, + 621, + 629, + 711, + 703, + 0, + 629, + 632, + 714, + 711, + 0, + 632, + 635, + 716, + 714, + 0, + 635, + 637, + 719, + 716, + 0, + 637, + 642, + 723, + 719, + 0, + 642, + 644, + 725, + 723, + 0, + 644, + 643, + 726, + 725, + 0, + 643, + 641, + 724, + 726, + 0, + 641, + 638, + 720, + 724, + 0, + 638, + 636, + 718, + 720, + 0, + 636, + 633, + 715, + 718, + 0, + 633, + 630, + 712, + 715, + 0, + 630, + 627, + 709, + 712, + 0, + 627, + 624, + 706, + 709, + 0, + 624, + 622, + 704, + 706, + 0, + 622, + 619, + 701, + 704, + 0, + 619, + 617, + 699, + 701, + 0, + 617, + 616, + 698, + 699, + 0, + 616, + 614, + 696, + 698, + 0, + 614, + 612, + 694, + 696, + 0, + 612, + 610, + 692, + 694, + 0, + 610, + 608, + 690, + 692, + 0, + 608, + 606, + 688, + 690, + 0, + 606, + 604, + 685, + 688, + 0, + 604, + 601, + 683, + 685, + 0, + 601, + 599, + 681, + 683, + 0, + 599, + 598, + 680, + 681, + 0, + 598, + 596, + 678, + 680, + 0, + 596, + 594, + 676, + 678, + 0, + 594, + 592, + 674, + 676, + 0, + 592, + 590, + 672, + 674, + 0, + 590, + 587, + 669, + 672, + 0, + 587, + 585, + 667, + 669, + 0, + 585, + 583, + 665, + 667, + 0, + 583, + 582, + 664, + 665, + 0, + 582, + 580, + 662, + 664, + 0, + 580, + 577, + 659, + 662, + 0, + 577, + 576, + 658, + 659, + 0, + 658, + 657, + 739, + 740, + 0, + 657, + 660, + 742, + 739, + 0, + 660, + 661, + 743, + 742, + 0, + 661, + 663, + 745, + 743, + 0, + 663, + 666, + 748, + 745, + 0, + 666, + 668, + 750, + 748, + 0, + 668, + 670, + 752, + 750, + 0, + 670, + 671, + 753, + 752, + 0, + 671, + 673, + 755, + 753, + 0, + 673, + 675, + 757, + 755, + 0, + 675, + 677, + 759, + 757, + 0, + 677, + 679, + 761, + 759, + 0, + 679, + 682, + 764, + 761, + 0, + 682, + 684, + 766, + 764, + 0, + 684, + 686, + 768, + 766, + 0, + 686, + 687, + 769, + 768, + 0, + 687, + 689, + 771, + 769, + 0, + 689, + 691, + 773, + 771, + 0, + 691, + 693, + 775, + 773, + 0, + 693, + 695, + 777, + 775, + 0, + 695, + 697, + 779, + 777, + 0, + 697, + 700, + 782, + 779, + 0, + 700, + 705, + 787, + 782, + 0, + 705, + 708, + 790, + 787, + 0, + 708, + 710, + 792, + 790, + 0, + 710, + 713, + 796, + 792, + 0, + 713, + 717, + 799, + 796, + 0, + 717, + 722, + 806, + 799, + 0, + 722, + 728, + 810, + 806, + 0, + 728, + 729, + 812, + 810, + 0, + 729, + 731, + 813, + 812, + 0, + 731, + 733, + 815, + 813, + 0, + 733, + 735, + 817, + 815, + 0, + 735, + 737, + 820, + 817, + 0, + 737, + 738, + 819, + 820, + 0, + 738, + 736, + 818, + 819, + 0, + 736, + 734, + 816, + 818, + 0, + 734, + 732, + 814, + 816, + 0, + 732, + 730, + 811, + 814, + 0, + 730, + 727, + 809, + 811, + 0, + 727, + 721, + 802, + 809, + 0, + 721, + 707, + 789, + 802, + 0, + 707, + 702, + 784, + 789, + 0, + 702, + 703, + 785, + 784, + 0, + 703, + 711, + 793, + 785, + 0, + 711, + 714, + 795, + 793, + 0, + 714, + 716, + 798, + 795, + 0, + 716, + 719, + 801, + 798, + 0, + 719, + 723, + 804, + 801, + 0, + 723, + 725, + 807, + 804, + 0, + 725, + 726, + 808, + 807, + 0, + 726, + 724, + 805, + 808, + 0, + 724, + 720, + 803, + 805, + 0, + 720, + 718, + 800, + 803, + 0, + 718, + 715, + 797, + 800, + 0, + 715, + 712, + 794, + 797, + 0, + 712, + 709, + 791, + 794, + 0, + 709, + 706, + 788, + 791, + 0, + 706, + 704, + 786, + 788, + 0, + 704, + 701, + 783, + 786, + 0, + 701, + 699, + 781, + 783, + 0, + 699, + 698, + 780, + 781, + 0, + 698, + 696, + 778, + 780, + 0, + 696, + 694, + 776, + 778, + 0, + 694, + 692, + 774, + 776, + 0, + 692, + 690, + 772, + 774, + 0, + 690, + 688, + 770, + 772, + 0, + 688, + 685, + 767, + 770, + 0, + 685, + 683, + 765, + 767, + 0, + 683, + 681, + 763, + 765, + 0, + 681, + 680, + 762, + 763, + 0, + 680, + 678, + 760, + 762, + 0, + 678, + 676, + 758, + 760, + 0, + 676, + 674, + 756, + 758, + 0, + 674, + 672, + 754, + 756, + 0, + 672, + 669, + 751, + 754, + 0, + 669, + 667, + 749, + 751, + 0, + 667, + 665, + 747, + 749, + 0, + 665, + 664, + 746, + 747, + 0, + 664, + 662, + 744, + 746, + 0, + 662, + 659, + 741, + 744, + 0, + 659, + 658, + 740, + 741, + 0, + 740, + 739, + 821, + 822, + 0, + 739, + 742, + 824, + 821, + 0, + 742, + 743, + 825, + 824, + 0, + 743, + 745, + 827, + 825, + 0, + 745, + 748, + 830, + 827, + 0, + 748, + 750, + 832, + 830, + 0, + 750, + 752, + 834, + 832, + 0, + 752, + 753, + 835, + 834, + 0, + 753, + 755, + 837, + 835, + 0, + 755, + 757, + 839, + 837, + 0, + 757, + 759, + 841, + 839, + 0, + 759, + 761, + 843, + 841, + 0, + 761, + 764, + 846, + 843, + 0, + 764, + 766, + 848, + 846, + 0, + 766, + 768, + 850, + 848, + 0, + 768, + 769, + 851, + 850, + 0, + 769, + 771, + 853, + 851, + 0, + 771, + 773, + 855, + 853, + 0, + 773, + 775, + 857, + 855, + 0, + 775, + 777, + 859, + 857, + 0, + 777, + 779, + 861, + 859, + 0, + 779, + 782, + 865, + 861, + 0, + 782, + 787, + 869, + 865, + 0, + 787, + 790, + 872, + 869, + 0, + 790, + 792, + 874, + 872, + 0, + 792, + 796, + 878, + 874, + 0, + 796, + 799, + 881, + 878, + 0, + 799, + 806, + 889, + 881, + 0, + 806, + 810, + 892, + 889, + 0, + 810, + 812, + 894, + 892, + 0, + 812, + 813, + 896, + 894, + 0, + 813, + 815, + 898, + 896, + 0, + 815, + 817, + 900, + 898, + 0, + 817, + 820, + 902, + 900, + 0, + 820, + 819, + 901, + 902, + 0, + 819, + 818, + 899, + 901, + 0, + 818, + 816, + 897, + 899, + 0, + 816, + 814, + 895, + 897, + 0, + 814, + 811, + 893, + 895, + 0, + 811, + 809, + 891, + 893, + 0, + 809, + 802, + 884, + 891, + 0, + 802, + 789, + 870, + 884, + 0, + 789, + 784, + 866, + 870, + 0, + 784, + 785, + 867, + 866, + 0, + 785, + 793, + 875, + 867, + 0, + 793, + 795, + 877, + 875, + 0, + 795, + 798, + 880, + 877, + 0, + 798, + 801, + 883, + 880, + 0, + 801, + 804, + 886, + 883, + 0, + 804, + 807, + 888, + 886, + 0, + 807, + 808, + 890, + 888, + 0, + 808, + 805, + 887, + 890, + 0, + 805, + 803, + 885, + 887, + 0, + 803, + 800, + 882, + 885, + 0, + 800, + 797, + 879, + 882, + 0, + 797, + 794, + 876, + 879, + 0, + 794, + 791, + 873, + 876, + 0, + 791, + 788, + 871, + 873, + 0, + 788, + 786, + 868, + 871, + 0, + 786, + 783, + 864, + 868, + 0, + 783, + 781, + 863, + 864, + 0, + 781, + 780, + 862, + 863, + 0, + 780, + 778, + 860, + 862, + 0, + 778, + 776, + 858, + 860, + 0, + 776, + 774, + 856, + 858, + 0, + 774, + 772, + 854, + 856, + 0, + 772, + 770, + 852, + 854, + 0, + 770, + 767, + 849, + 852, + 0, + 767, + 765, + 847, + 849, + 0, + 765, + 763, + 845, + 847, + 0, + 763, + 762, + 844, + 845, + 0, + 762, + 760, + 842, + 844, + 0, + 760, + 758, + 840, + 842, + 0, + 758, + 756, + 838, + 840, + 0, + 756, + 754, + 836, + 838, + 0, + 754, + 751, + 833, + 836, + 0, + 751, + 749, + 831, + 833, + 0, + 749, + 747, + 829, + 831, + 0, + 747, + 746, + 828, + 829, + 0, + 746, + 744, + 826, + 828, + 0, + 744, + 741, + 823, + 826, + 0, + 741, + 740, + 822, + 823, + 0, + 822, + 821, + 903, + 904, + 0, + 821, + 824, + 906, + 903, + 0, + 824, + 825, + 907, + 906, + 0, + 825, + 827, + 909, + 907, + 0, + 827, + 830, + 912, + 909, + 0, + 830, + 832, + 914, + 912, + 0, + 832, + 834, + 916, + 914, + 0, + 834, + 835, + 917, + 916, + 0, + 835, + 837, + 919, + 917, + 0, + 837, + 839, + 921, + 919, + 0, + 839, + 841, + 923, + 921, + 0, + 841, + 843, + 925, + 923, + 0, + 843, + 846, + 928, + 925, + 0, + 846, + 848, + 930, + 928, + 0, + 848, + 850, + 932, + 930, + 0, + 850, + 851, + 933, + 932, + 0, + 851, + 853, + 935, + 933, + 0, + 853, + 855, + 937, + 935, + 0, + 855, + 857, + 939, + 937, + 0, + 857, + 859, + 941, + 939, + 0, + 859, + 861, + 943, + 941, + 0, + 861, + 865, + 948, + 943, + 0, + 865, + 869, + 951, + 948, + 0, + 869, + 872, + 954, + 951, + 0, + 872, + 874, + 957, + 954, + 0, + 874, + 878, + 960, + 957, + 0, + 878, + 881, + 963, + 960, + 0, + 881, + 889, + 972, + 963, + 0, + 889, + 892, + 974, + 972, + 0, + 892, + 894, + 976, + 974, + 0, + 894, + 896, + 978, + 976, + 0, + 896, + 898, + 980, + 978, + 0, + 898, + 900, + 982, + 980, + 0, + 900, + 902, + 984, + 982, + 0, + 902, + 901, + 983, + 984, + 0, + 901, + 899, + 981, + 983, + 0, + 899, + 897, + 979, + 981, + 0, + 897, + 895, + 977, + 979, + 0, + 895, + 893, + 975, + 977, + 0, + 893, + 891, + 973, + 975, + 0, + 891, + 884, + 966, + 973, + 0, + 884, + 870, + 952, + 966, + 0, + 870, + 866, + 946, + 952, + 0, + 866, + 867, + 949, + 946, + 0, + 867, + 875, + 956, + 949, + 0, + 875, + 877, + 959, + 956, + 0, + 877, + 880, + 962, + 959, + 0, + 880, + 883, + 964, + 962, + 0, + 883, + 886, + 968, + 964, + 0, + 886, + 888, + 970, + 968, + 0, + 888, + 890, + 971, + 970, + 0, + 890, + 887, + 969, + 971, + 0, + 887, + 885, + 967, + 969, + 0, + 885, + 882, + 965, + 967, + 0, + 882, + 879, + 961, + 965, + 0, + 879, + 876, + 958, + 961, + 0, + 876, + 873, + 955, + 958, + 0, + 873, + 871, + 953, + 955, + 0, + 871, + 868, + 950, + 953, + 0, + 868, + 864, + 947, + 950, + 0, + 864, + 863, + 945, + 947, + 0, + 863, + 862, + 944, + 945, + 0, + 862, + 860, + 942, + 944, + 0, + 860, + 858, + 940, + 942, + 0, + 858, + 856, + 938, + 940, + 0, + 856, + 854, + 936, + 938, + 0, + 854, + 852, + 934, + 936, + 0, + 852, + 849, + 931, + 934, + 0, + 849, + 847, + 929, + 931, + 0, + 847, + 845, + 927, + 929, + 0, + 845, + 844, + 926, + 927, + 0, + 844, + 842, + 924, + 926, + 0, + 842, + 840, + 922, + 924, + 0, + 840, + 838, + 920, + 922, + 0, + 838, + 836, + 918, + 920, + 0, + 836, + 833, + 915, + 918, + 0, + 833, + 831, + 913, + 915, + 0, + 831, + 829, + 911, + 913, + 0, + 829, + 828, + 910, + 911, + 0, + 828, + 826, + 908, + 910, + 0, + 826, + 823, + 905, + 908, + 0, + 823, + 822, + 904, + 905, + 0, + 904, + 903, + 985, + 986, + 0, + 903, + 906, + 988, + 985, + 0, + 906, + 907, + 989, + 988, + 0, + 907, + 909, + 991, + 989, + 0, + 909, + 912, + 994, + 991, + 0, + 912, + 914, + 996, + 994, + 0, + 914, + 916, + 998, + 996, + 0, + 916, + 917, + 1000, + 998, + 0, + 917, + 919, + 1001, + 1000, + 0, + 919, + 921, + 1003, + 1001, + 0, + 921, + 923, + 1005, + 1003, + 0, + 923, + 925, + 1008, + 1005, + 0, + 925, + 928, + 1010, + 1008, + 0, + 928, + 930, + 1012, + 1010, + 0, + 930, + 932, + 1014, + 1012, + 0, + 932, + 933, + 1015, + 1014, + 0, + 933, + 935, + 1017, + 1015, + 0, + 935, + 937, + 1019, + 1017, + 0, + 937, + 939, + 1021, + 1019, + 0, + 939, + 941, + 1023, + 1021, + 0, + 941, + 943, + 1025, + 1023, + 0, + 943, + 948, + 1031, + 1025, + 0, + 948, + 951, + 1033, + 1031, + 0, + 951, + 954, + 1036, + 1033, + 0, + 954, + 957, + 1039, + 1036, + 0, + 957, + 960, + 1042, + 1039, + 0, + 960, + 963, + 1048, + 1042, + 0, + 963, + 972, + 1055, + 1048, + 0, + 972, + 974, + 1056, + 1055, + 0, + 974, + 976, + 1058, + 1056, + 0, + 976, + 978, + 1060, + 1058, + 0, + 978, + 980, + 1062, + 1060, + 0, + 980, + 982, + 1064, + 1062, + 0, + 982, + 984, + 1066, + 1064, + 0, + 984, + 983, + 1065, + 1066, + 0, + 983, + 981, + 1063, + 1065, + 0, + 981, + 979, + 1061, + 1063, + 0, + 979, + 977, + 1059, + 1061, + 0, + 977, + 975, + 1057, + 1059, + 0, + 975, + 973, + 1054, + 1057, + 0, + 973, + 966, + 1045, + 1054, + 0, + 966, + 952, + 1034, + 1045, + 0, + 952, + 946, + 1028, + 1034, + 0, + 946, + 949, + 1029, + 1028, + 0, + 949, + 956, + 1038, + 1029, + 0, + 956, + 959, + 1040, + 1038, + 0, + 959, + 962, + 1043, + 1040, + 0, + 962, + 964, + 1046, + 1043, + 0, + 964, + 968, + 1049, + 1046, + 0, + 968, + 970, + 1052, + 1049, + 0, + 970, + 971, + 1053, + 1052, + 0, + 971, + 969, + 1051, + 1053, + 0, + 969, + 967, + 1050, + 1051, + 0, + 967, + 965, + 1047, + 1050, + 0, + 965, + 961, + 1044, + 1047, + 0, + 961, + 958, + 1041, + 1044, + 0, + 958, + 955, + 1037, + 1041, + 0, + 955, + 953, + 1035, + 1037, + 0, + 953, + 950, + 1032, + 1035, + 0, + 950, + 947, + 1030, + 1032, + 0, + 947, + 945, + 1027, + 1030, + 0, + 945, + 944, + 1026, + 1027, + 0, + 944, + 942, + 1024, + 1026, + 0, + 942, + 940, + 1022, + 1024, + 0, + 940, + 938, + 1020, + 1022, + 0, + 938, + 936, + 1018, + 1020, + 0, + 936, + 934, + 1016, + 1018, + 0, + 934, + 931, + 1013, + 1016, + 0, + 931, + 929, + 1011, + 1013, + 0, + 929, + 927, + 1009, + 1011, + 0, + 927, + 926, + 1007, + 1009, + 0, + 926, + 924, + 1006, + 1007, + 0, + 924, + 922, + 1004, + 1006, + 0, + 922, + 920, + 1002, + 1004, + 0, + 920, + 918, + 999, + 1002, + 0, + 918, + 915, + 997, + 999, + 0, + 915, + 913, + 995, + 997, + 0, + 913, + 911, + 993, + 995, + 0, + 911, + 910, + 992, + 993, + 0, + 910, + 908, + 990, + 992, + 0, + 908, + 905, + 987, + 990, + 0, + 905, + 904, + 986, + 987, + 0, + 986, + 985, + 1067, + 1068, + 0, + 985, + 988, + 1070, + 1067, + 0, + 988, + 989, + 1071, + 1070, + 0, + 989, + 991, + 1073, + 1071, + 0, + 991, + 994, + 1076, + 1073, + 0, + 994, + 996, + 1078, + 1076, + 0, + 996, + 998, + 1080, + 1078, + 0, + 998, + 1000, + 1082, + 1080, + 0, + 1000, + 1001, + 1083, + 1082, + 0, + 1001, + 1003, + 1085, + 1083, + 0, + 1003, + 1005, + 1087, + 1085, + 0, + 1005, + 1008, + 1090, + 1087, + 0, + 1008, + 1010, + 1092, + 1090, + 0, + 1010, + 1012, + 1094, + 1092, + 0, + 1012, + 1014, + 1096, + 1094, + 0, + 1014, + 1015, + 1097, + 1096, + 0, + 1015, + 1017, + 1099, + 1097, + 0, + 1017, + 1019, + 1101, + 1099, + 0, + 1019, + 1021, + 1103, + 1101, + 0, + 1021, + 1023, + 1105, + 1103, + 0, + 1023, + 1025, + 1107, + 1105, + 0, + 1025, + 1031, + 1113, + 1107, + 0, + 1031, + 1033, + 1116, + 1113, + 0, + 1033, + 1036, + 1118, + 1116, + 0, + 1036, + 1039, + 1121, + 1118, + 0, + 1039, + 1042, + 1125, + 1121, + 0, + 1042, + 1048, + 1130, + 1125, + 0, + 1048, + 1055, + 1137, + 1130, + 0, + 1055, + 1056, + 1139, + 1137, + 0, + 1056, + 1058, + 1140, + 1139, + 0, + 1058, + 1060, + 1142, + 1140, + 0, + 1060, + 1062, + 1144, + 1142, + 0, + 1062, + 1064, + 1146, + 1144, + 0, + 1064, + 1066, + 1148, + 1146, + 0, + 1066, + 1065, + 1147, + 1148, + 0, + 1065, + 1063, + 1145, + 1147, + 0, + 1063, + 1061, + 1143, + 1145, + 0, + 1061, + 1059, + 1141, + 1143, + 0, + 1059, + 1057, + 1138, + 1141, + 0, + 1057, + 1054, + 1136, + 1138, + 0, + 1054, + 1045, + 1127, + 1136, + 0, + 1045, + 1034, + 1115, + 1127, + 0, + 1034, + 1028, + 1110, + 1115, + 0, + 1028, + 1029, + 1111, + 1110, + 0, + 1029, + 1038, + 1119, + 1111, + 0, + 1038, + 1040, + 1122, + 1119, + 0, + 1040, + 1043, + 1124, + 1122, + 0, + 1043, + 1046, + 1128, + 1124, + 0, + 1046, + 1049, + 1131, + 1128, + 0, + 1049, + 1052, + 1134, + 1131, + 0, + 1052, + 1053, + 1135, + 1134, + 0, + 1053, + 1051, + 1133, + 1135, + 0, + 1051, + 1050, + 1132, + 1133, + 0, + 1050, + 1047, + 1129, + 1132, + 0, + 1047, + 1044, + 1126, + 1129, + 0, + 1044, + 1041, + 1123, + 1126, + 0, + 1041, + 1037, + 1120, + 1123, + 0, + 1037, + 1035, + 1117, + 1120, + 0, + 1035, + 1032, + 1114, + 1117, + 0, + 1032, + 1030, + 1112, + 1114, + 0, + 1030, + 1027, + 1109, + 1112, + 0, + 1027, + 1026, + 1108, + 1109, + 0, + 1026, + 1024, + 1106, + 1108, + 0, + 1024, + 1022, + 1104, + 1106, + 0, + 1022, + 1020, + 1102, + 1104, + 0, + 1020, + 1018, + 1100, + 1102, + 0, + 1018, + 1016, + 1098, + 1100, + 0, + 1016, + 1013, + 1095, + 1098, + 0, + 1013, + 1011, + 1093, + 1095, + 0, + 1011, + 1009, + 1091, + 1093, + 0, + 1009, + 1007, + 1089, + 1091, + 0, + 1007, + 1006, + 1088, + 1089, + 0, + 1006, + 1004, + 1086, + 1088, + 0, + 1004, + 1002, + 1084, + 1086, + 0, + 1002, + 999, + 1081, + 1084, + 0, + 999, + 997, + 1079, + 1081, + 0, + 997, + 995, + 1077, + 1079, + 0, + 995, + 993, + 1075, + 1077, + 0, + 993, + 992, + 1074, + 1075, + 0, + 992, + 990, + 1072, + 1074, + 0, + 990, + 987, + 1069, + 1072, + 0, + 987, + 986, + 1068, + 1069, + 0, + 1068, + 1067, + 1149, + 1150, + 0, + 1067, + 1070, + 1152, + 1149, + 0, + 1070, + 1071, + 1153, + 1152, + 0, + 1071, + 1073, + 1155, + 1153, + 0, + 1073, + 1076, + 1158, + 1155, + 0, + 1076, + 1078, + 1160, + 1158, + 0, + 1078, + 1080, + 1162, + 1160, + 0, + 1080, + 1082, + 1164, + 1162, + 0, + 1082, + 1083, + 1165, + 1164, + 0, + 1083, + 1085, + 1167, + 1165, + 0, + 1085, + 1087, + 1169, + 1167, + 0, + 1087, + 1090, + 1172, + 1169, + 0, + 1090, + 1092, + 1174, + 1172, + 0, + 1092, + 1094, + 1176, + 1174, + 0, + 1094, + 1096, + 1178, + 1176, + 0, + 1096, + 1097, + 1179, + 1178, + 0, + 1097, + 1099, + 1181, + 1179, + 0, + 1099, + 1101, + 1183, + 1181, + 0, + 1101, + 1103, + 1185, + 1183, + 0, + 1103, + 1105, + 1187, + 1185, + 0, + 1105, + 1107, + 1189, + 1187, + 0, + 1107, + 1113, + 1195, + 1189, + 0, + 1113, + 1116, + 1198, + 1195, + 0, + 1116, + 1118, + 1200, + 1198, + 0, + 1118, + 1121, + 1204, + 1200, + 0, + 1121, + 1125, + 1207, + 1204, + 0, + 1125, + 1130, + 1213, + 1207, + 0, + 1130, + 1137, + 1219, + 1213, + 0, + 1137, + 1139, + 1221, + 1219, + 0, + 1139, + 1140, + 1223, + 1221, + 0, + 1140, + 1142, + 1225, + 1223, + 0, + 1142, + 1144, + 1227, + 1225, + 0, + 1144, + 1146, + 1229, + 1227, + 0, + 1146, + 1148, + 1230, + 1229, + 0, + 1148, + 1147, + 1228, + 1230, + 0, + 1147, + 1145, + 1226, + 1228, + 0, + 1145, + 1143, + 1224, + 1226, + 0, + 1143, + 1141, + 1222, + 1224, + 0, + 1141, + 1138, + 1220, + 1222, + 0, + 1138, + 1136, + 1216, + 1220, + 0, + 1136, + 1127, + 1209, + 1216, + 0, + 1127, + 1115, + 1196, + 1209, + 0, + 1115, + 1110, + 1192, + 1196, + 0, + 1110, + 1111, + 1193, + 1192, + 0, + 1111, + 1119, + 1201, + 1193, + 0, + 1119, + 1122, + 1203, + 1201, + 0, + 1122, + 1124, + 1206, + 1203, + 0, + 1124, + 1128, + 1210, + 1206, + 0, + 1128, + 1131, + 1212, + 1210, + 0, + 1131, + 1134, + 1215, + 1212, + 0, + 1134, + 1135, + 1218, + 1215, + 0, + 1135, + 1133, + 1217, + 1218, + 0, + 1133, + 1132, + 1214, + 1217, + 0, + 1132, + 1129, + 1211, + 1214, + 0, + 1129, + 1126, + 1208, + 1211, + 0, + 1126, + 1123, + 1205, + 1208, + 0, + 1123, + 1120, + 1202, + 1205, + 0, + 1120, + 1117, + 1199, + 1202, + 0, + 1117, + 1114, + 1197, + 1199, + 0, + 1114, + 1112, + 1194, + 1197, + 0, + 1112, + 1109, + 1191, + 1194, + 0, + 1109, + 1108, + 1190, + 1191, + 0, + 1108, + 1106, + 1188, + 1190, + 0, + 1106, + 1104, + 1186, + 1188, + 0, + 1104, + 1102, + 1184, + 1186, + 0, + 1102, + 1100, + 1182, + 1184, + 0, + 1100, + 1098, + 1180, + 1182, + 0, + 1098, + 1095, + 1177, + 1180, + 0, + 1095, + 1093, + 1175, + 1177, + 0, + 1093, + 1091, + 1173, + 1175, + 0, + 1091, + 1089, + 1171, + 1173, + 0, + 1089, + 1088, + 1170, + 1171, + 0, + 1088, + 1086, + 1168, + 1170, + 0, + 1086, + 1084, + 1166, + 1168, + 0, + 1084, + 1081, + 1163, + 1166, + 0, + 1081, + 1079, + 1161, + 1163, + 0, + 1079, + 1077, + 1159, + 1161, + 0, + 1077, + 1075, + 1157, + 1159, + 0, + 1075, + 1074, + 1156, + 1157, + 0, + 1074, + 1072, + 1154, + 1156, + 0, + 1072, + 1069, + 1151, + 1154, + 0, + 1069, + 1068, + 1150, + 1151, + 0, + 1150, + 1149, + 1231, + 1232, + 0, + 1149, + 1152, + 1234, + 1231, + 0, + 1152, + 1153, + 1235, + 1234, + 0, + 1153, + 1155, + 1237, + 1235, + 0, + 1155, + 1158, + 1240, + 1237, + 0, + 1158, + 1160, + 1242, + 1240, + 0, + 1160, + 1162, + 1244, + 1242, + 0, + 1162, + 1164, + 1246, + 1244, + 0, + 1164, + 1165, + 1247, + 1246, + 0, + 1165, + 1167, + 1249, + 1247, + 0, + 1167, + 1169, + 1251, + 1249, + 0, + 1169, + 1172, + 1254, + 1251, + 0, + 1172, + 1174, + 1256, + 1254, + 0, + 1174, + 1176, + 1258, + 1256, + 0, + 1176, + 1178, + 1260, + 1258, + 0, + 1178, + 1179, + 1261, + 1260, + 0, + 1179, + 1181, + 1263, + 1261, + 0, + 1181, + 1183, + 1265, + 1263, + 0, + 1183, + 1185, + 1267, + 1265, + 0, + 1185, + 1187, + 1269, + 1267, + 0, + 1187, + 1189, + 1271, + 1269, + 0, + 1189, + 1195, + 1277, + 1271, + 0, + 1195, + 1198, + 1280, + 1277, + 0, + 1198, + 1200, + 1283, + 1280, + 0, + 1200, + 1204, + 1286, + 1283, + 0, + 1204, + 1207, + 1289, + 1286, + 0, + 1207, + 1213, + 1295, + 1289, + 0, + 1213, + 1219, + 1301, + 1295, + 0, + 1219, + 1221, + 1303, + 1301, + 0, + 1221, + 1223, + 1305, + 1303, + 0, + 1223, + 1225, + 1307, + 1305, + 0, + 1225, + 1227, + 1309, + 1307, + 0, + 1227, + 1229, + 1311, + 1309, + 0, + 1229, + 1230, + 1312, + 1311, + 0, + 1230, + 1228, + 1310, + 1312, + 0, + 1228, + 1226, + 1308, + 1310, + 0, + 1226, + 1224, + 1306, + 1308, + 0, + 1224, + 1222, + 1304, + 1306, + 0, + 1222, + 1220, + 1302, + 1304, + 0, + 1220, + 1216, + 1297, + 1302, + 0, + 1216, + 1209, + 1290, + 1297, + 0, + 1209, + 1196, + 1278, + 1290, + 0, + 1196, + 1192, + 1274, + 1278, + 0, + 1192, + 1193, + 1275, + 1274, + 0, + 1193, + 1201, + 1282, + 1275, + 0, + 1201, + 1203, + 1285, + 1282, + 0, + 1203, + 1206, + 1288, + 1285, + 0, + 1206, + 1210, + 1292, + 1288, + 0, + 1210, + 1212, + 1294, + 1292, + 0, + 1212, + 1215, + 1298, + 1294, + 0, + 1215, + 1218, + 1300, + 1298, + 0, + 1218, + 1217, + 1299, + 1300, + 0, + 1217, + 1214, + 1296, + 1299, + 0, + 1214, + 1211, + 1293, + 1296, + 0, + 1211, + 1208, + 1291, + 1293, + 0, + 1208, + 1205, + 1287, + 1291, + 0, + 1205, + 1202, + 1284, + 1287, + 0, + 1202, + 1199, + 1281, + 1284, + 0, + 1199, + 1197, + 1279, + 1281, + 0, + 1197, + 1194, + 1276, + 1279, + 0, + 1194, + 1191, + 1273, + 1276, + 0, + 1191, + 1190, + 1272, + 1273, + 0, + 1190, + 1188, + 1270, + 1272, + 0, + 1188, + 1186, + 1268, + 1270, + 0, + 1186, + 1184, + 1266, + 1268, + 0, + 1184, + 1182, + 1264, + 1266, + 0, + 1182, + 1180, + 1262, + 1264, + 0, + 1180, + 1177, + 1259, + 1262, + 0, + 1177, + 1175, + 1257, + 1259, + 0, + 1175, + 1173, + 1255, + 1257, + 0, + 1173, + 1171, + 1253, + 1255, + 0, + 1171, + 1170, + 1252, + 1253, + 0, + 1170, + 1168, + 1250, + 1252, + 0, + 1168, + 1166, + 1248, + 1250, + 0, + 1166, + 1163, + 1245, + 1248, + 0, + 1163, + 1161, + 1243, + 1245, + 0, + 1161, + 1159, + 1241, + 1243, + 0, + 1159, + 1157, + 1239, + 1241, + 0, + 1157, + 1156, + 1238, + 1239, + 0, + 1156, + 1154, + 1236, + 1238, + 0, + 1154, + 1151, + 1233, + 1236, + 0, + 1151, + 1150, + 1232, + 1233, + 0, + 1232, + 1231, + 1313, + 1314, + 0, + 1231, + 1234, + 1316, + 1313, + 0, + 1234, + 1235, + 1317, + 1316, + 0, + 1235, + 1237, + 1319, + 1317, + 0, + 1237, + 1240, + 1322, + 1319, + 0, + 1240, + 1242, + 1324, + 1322, + 0, + 1242, + 1244, + 1326, + 1324, + 0, + 1244, + 1246, + 1328, + 1326, + 0, + 1246, + 1247, + 1329, + 1328, + 0, + 1247, + 1249, + 1331, + 1329, + 0, + 1249, + 1251, + 1333, + 1331, + 0, + 1251, + 1254, + 1336, + 1333, + 0, + 1254, + 1256, + 1338, + 1336, + 0, + 1256, + 1258, + 1340, + 1338, + 0, + 1258, + 1260, + 1342, + 1340, + 0, + 1260, + 1261, + 1343, + 1342, + 0, + 1261, + 1263, + 1345, + 1343, + 0, + 1263, + 1265, + 1347, + 1345, + 0, + 1265, + 1267, + 1349, + 1347, + 0, + 1267, + 1269, + 1351, + 1349, + 0, + 1269, + 1271, + 1353, + 1351, + 0, + 1271, + 1277, + 1371, + 1353, + 0, + 1277, + 1280, + 1376, + 1371, + 0, + 1280, + 1283, + 1381, + 1376, + 0, + 1283, + 1286, + 1386, + 1381, + 0, + 1286, + 1289, + 1392, + 1386, + 0, + 1289, + 1295, + 1400, + 1392, + 0, + 1295, + 1301, + 1404, + 1400, + 0, + 1301, + 1303, + 1407, + 1404, + 0, + 1303, + 1305, + 1409, + 1407, + 0, + 1305, + 1307, + 1411, + 1409, + 0, + 1307, + 1309, + 1413, + 1411, + 0, + 1309, + 1311, + 1415, + 1413, + 0, + 1311, + 1312, + 1416, + 1415, + 0, + 1312, + 1310, + 1414, + 1416, + 0, + 1310, + 1308, + 1412, + 1414, + 0, + 1308, + 1306, + 1410, + 1412, + 0, + 1306, + 1304, + 1408, + 1410, + 0, + 1304, + 1302, + 1403, + 1408, + 0, + 1302, + 1297, + 1396, + 1403, + 0, + 1297, + 1290, + 1389, + 1396, + 0, + 1290, + 1278, + 1372, + 1389, + 0, + 1278, + 1274, + 1364, + 1372, + 0, + 1274, + 1275, + 1366, + 1364, + 0, + 1275, + 1282, + 1380, + 1366, + 0, + 1282, + 1285, + 1383, + 1380, + 0, + 1285, + 1288, + 1387, + 1383, + 0, + 1288, + 1292, + 1390, + 1387, + 0, + 1292, + 1294, + 1394, + 1390, + 0, + 1294, + 1298, + 1399, + 1394, + 0, + 1298, + 1300, + 1402, + 1399, + 0, + 1300, + 1299, + 1401, + 1402, + 0, + 1299, + 1296, + 1398, + 1401, + 0, + 1296, + 1293, + 1395, + 1398, + 0, + 1293, + 1291, + 1391, + 1395, + 0, + 1291, + 1287, + 1388, + 1391, + 0, + 1287, + 1284, + 1382, + 1388, + 0, + 1284, + 1281, + 1378, + 1382, + 0, + 1281, + 1279, + 1375, + 1378, + 0, + 1279, + 1276, + 1370, + 1375, + 0, + 1276, + 1273, + 1367, + 1370, + 0, + 1273, + 1272, + 1357, + 1367, + 0, + 1272, + 1270, + 1352, + 1357, + 0, + 1270, + 1268, + 1350, + 1352, + 0, + 1268, + 1266, + 1348, + 1350, + 0, + 1266, + 1264, + 1346, + 1348, + 0, + 1264, + 1262, + 1344, + 1346, + 0, + 1262, + 1259, + 1341, + 1344, + 0, + 1259, + 1257, + 1339, + 1341, + 0, + 1257, + 1255, + 1337, + 1339, + 0, + 1255, + 1253, + 1335, + 1337, + 0, + 1253, + 1252, + 1334, + 1335, + 0, + 1252, + 1250, + 1332, + 1334, + 0, + 1250, + 1248, + 1330, + 1332, + 0, + 1248, + 1245, + 1327, + 1330, + 0, + 1245, + 1243, + 1325, + 1327, + 0, + 1243, + 1241, + 1323, + 1325, + 0, + 1241, + 1239, + 1321, + 1323, + 0, + 1239, + 1238, + 1320, + 1321, + 0, + 1238, + 1236, + 1318, + 1320, + 0, + 1236, + 1233, + 1315, + 1318, + 0, + 1233, + 1232, + 1314, + 1315, + 0, + 1314, + 1313, + 1354, + 1355, + 0, + 1313, + 1316, + 1358, + 1354, + 0, + 1316, + 1317, + 1359, + 1358, + 0, + 1317, + 1319, + 1361, + 1359, + 0, + 1319, + 1322, + 1365, + 1361, + 0, + 1322, + 1324, + 1369, + 1365, + 0, + 1324, + 1326, + 1374, + 1369, + 0, + 1326, + 1328, + 1379, + 1374, + 0, + 1328, + 1329, + 1384, + 1379, + 0, + 1329, + 1331, + 1393, + 1384, + 0, + 1331, + 1333, + 1405, + 1393, + 0, + 1333, + 1336, + 1418, + 1405, + 0, + 1336, + 1338, + 1420, + 1418, + 0, + 1338, + 1340, + 1422, + 1420, + 0, + 1340, + 1342, + 1424, + 1422, + 0, + 1342, + 1343, + 1425, + 1424, + 0, + 1343, + 1345, + 1427, + 1425, + 0, + 1345, + 1347, + 1429, + 1427, + 0, + 1347, + 1349, + 1431, + 1429, + 0, + 1349, + 1351, + 1433, + 1431, + 0, + 1351, + 1353, + 1435, + 1433, + 0, + 1353, + 1371, + 1442, + 1435, + 0, + 1371, + 1376, + 1444, + 1442, + 0, + 1376, + 1381, + 1447, + 1444, + 0, + 1381, + 1386, + 1450, + 1447, + 0, + 1386, + 1392, + 1456, + 1450, + 0, + 1392, + 1400, + 1462, + 1456, + 0, + 1400, + 1404, + 1466, + 1462, + 0, + 1404, + 1407, + 1467, + 1466, + 0, + 1407, + 1409, + 1469, + 1467, + 0, + 1409, + 1411, + 1471, + 1469, + 0, + 1411, + 1413, + 1473, + 1471, + 0, + 1413, + 1415, + 1475, + 1473, + 0, + 1415, + 1416, + 1476, + 1475, + 0, + 1416, + 1414, + 1474, + 1476, + 0, + 1414, + 1412, + 1472, + 1474, + 0, + 1412, + 1410, + 1470, + 1472, + 0, + 1410, + 1408, + 1468, + 1470, + 0, + 1408, + 1403, + 1465, + 1468, + 0, + 1403, + 1396, + 1459, + 1465, + 0, + 1396, + 1389, + 1453, + 1459, + 0, + 1389, + 1372, + 1441, + 1453, + 0, + 1372, + 1364, + 1437, + 1441, + 0, + 1364, + 1366, + 1438, + 1437, + 0, + 1366, + 1380, + 1446, + 1438, + 0, + 1380, + 1383, + 1449, + 1446, + 0, + 1383, + 1387, + 1451, + 1449, + 0, + 1387, + 1390, + 1454, + 1451, + 0, + 1390, + 1394, + 1457, + 1454, + 0, + 1394, + 1399, + 1461, + 1457, + 0, + 1399, + 1402, + 1464, + 1461, + 0, + 1402, + 1401, + 1463, + 1464, + 0, + 1401, + 1398, + 1460, + 1463, + 0, + 1398, + 1395, + 1458, + 1460, + 0, + 1395, + 1391, + 1455, + 1458, + 0, + 1391, + 1388, + 1452, + 1455, + 0, + 1388, + 1382, + 1448, + 1452, + 0, + 1382, + 1378, + 1445, + 1448, + 0, + 1378, + 1375, + 1443, + 1445, + 0, + 1375, + 1370, + 1440, + 1443, + 0, + 1370, + 1367, + 1439, + 1440, + 0, + 1367, + 1357, + 1436, + 1439, + 0, + 1357, + 1352, + 1434, + 1436, + 0, + 1352, + 1350, + 1432, + 1434, + 0, + 1350, + 1348, + 1430, + 1432, + 0, + 1348, + 1346, + 1428, + 1430, + 0, + 1346, + 1344, + 1426, + 1428, + 0, + 1344, + 1341, + 1423, + 1426, + 0, + 1341, + 1339, + 1421, + 1423, + 0, + 1339, + 1337, + 1419, + 1421, + 0, + 1337, + 1335, + 1417, + 1419, + 0, + 1335, + 1334, + 1406, + 1417, + 0, + 1334, + 1332, + 1397, + 1406, + 0, + 1332, + 1330, + 1385, + 1397, + 0, + 1330, + 1327, + 1377, + 1385, + 0, + 1327, + 1325, + 1373, + 1377, + 0, + 1325, + 1323, + 1368, + 1373, + 0, + 1323, + 1321, + 1363, + 1368, + 0, + 1321, + 1320, + 1362, + 1363, + 0, + 1320, + 1318, + 1360, + 1362, + 0, + 1318, + 1315, + 1356, + 1360, + 0, + 1315, + 1314, + 1355, + 1356, + 0, + 1355, + 1354, + 1477, + 1478, + 0, + 1354, + 1358, + 1480, + 1477, + 0, + 1358, + 1359, + 1481, + 1480, + 0, + 1359, + 1361, + 1485, + 1481, + 0, + 1361, + 1365, + 1489, + 1485, + 0, + 1365, + 1369, + 1491, + 1489, + 0, + 1369, + 1374, + 1494, + 1491, + 0, + 1374, + 1379, + 1497, + 1494, + 0, + 1379, + 1384, + 1502, + 1497, + 0, + 1384, + 1393, + 1506, + 1502, + 0, + 1393, + 1405, + 1510, + 1506, + 0, + 1405, + 1418, + 1516, + 1510, + 0, + 1418, + 1420, + 1520, + 1516, + 0, + 1420, + 1422, + 1524, + 1520, + 0, + 1422, + 1424, + 1528, + 1524, + 0, + 1424, + 1425, + 1532, + 1528, + 0, + 1425, + 1427, + 1535, + 1532, + 0, + 1427, + 1429, + 1539, + 1535, + 0, + 1429, + 1431, + 1542, + 1539, + 0, + 1431, + 1433, + 1547, + 1542, + 0, + 1433, + 1435, + 1550, + 1547, + 0, + 1435, + 1442, + 1566, + 1550, + 0, + 1442, + 1444, + 1568, + 1566, + 0, + 1444, + 1447, + 1572, + 1568, + 0, + 1447, + 1450, + 1578, + 1572, + 0, + 1450, + 1456, + 1583, + 1578, + 0, + 1456, + 1462, + 1592, + 1583, + 0, + 1462, + 1466, + 1595, + 1592, + 0, + 1466, + 1467, + 1598, + 1595, + 0, + 1467, + 1469, + 1601, + 1598, + 0, + 1469, + 1471, + 1603, + 1601, + 0, + 1471, + 1473, + 1606, + 1603, + 0, + 1473, + 1475, + 1608, + 1606, + 0, + 1475, + 1476, + 1607, + 1608, + 0, + 1476, + 1474, + 1604, + 1607, + 0, + 1474, + 1472, + 1602, + 1604, + 0, + 1472, + 1470, + 1599, + 1602, + 0, + 1470, + 1468, + 1597, + 1599, + 0, + 1468, + 1465, + 1593, + 1597, + 0, + 1465, + 1459, + 1585, + 1593, + 0, + 1459, + 1453, + 1576, + 1585, + 0, + 1453, + 1441, + 1564, + 1576, + 0, + 1441, + 1437, + 1560, + 1564, + 0, + 1437, + 1438, + 1561, + 1560, + 0, + 1438, + 1446, + 1569, + 1561, + 0, + 1446, + 1449, + 1571, + 1569, + 0, + 1449, + 1451, + 1575, + 1571, + 0, + 1451, + 1454, + 1580, + 1575, + 0, + 1454, + 1457, + 1584, + 1580, + 0, + 1457, + 1461, + 1587, + 1584, + 0, + 1461, + 1464, + 1589, + 1587, + 0, + 1464, + 1463, + 1590, + 1589, + 0, + 1463, + 1460, + 1588, + 1590, + 0, + 1460, + 1458, + 1586, + 1588, + 0, + 1458, + 1455, + 1581, + 1586, + 0, + 1455, + 1452, + 1579, + 1581, + 0, + 1452, + 1448, + 1573, + 1579, + 0, + 1448, + 1445, + 1570, + 1573, + 0, + 1445, + 1443, + 1567, + 1570, + 0, + 1443, + 1440, + 1565, + 1567, + 0, + 1440, + 1439, + 1562, + 1565, + 0, + 1439, + 1436, + 1556, + 1562, + 0, + 1436, + 1434, + 1548, + 1556, + 0, + 1434, + 1432, + 1544, + 1548, + 0, + 1432, + 1430, + 1540, + 1544, + 0, + 1430, + 1428, + 1536, + 1540, + 0, + 1428, + 1426, + 1531, + 1536, + 0, + 1426, + 1423, + 1527, + 1531, + 0, + 1423, + 1421, + 1521, + 1527, + 0, + 1421, + 1419, + 1517, + 1521, + 0, + 1419, + 1417, + 1514, + 1517, + 0, + 1417, + 1406, + 1511, + 1514, + 0, + 1406, + 1397, + 1507, + 1511, + 0, + 1397, + 1385, + 1501, + 1507, + 0, + 1385, + 1377, + 1496, + 1501, + 0, + 1377, + 1373, + 1493, + 1496, + 0, + 1373, + 1368, + 1490, + 1493, + 0, + 1368, + 1363, + 1486, + 1490, + 0, + 1363, + 1362, + 1484, + 1486, + 0, + 1362, + 1360, + 1483, + 1484, + 0, + 1360, + 1356, + 1479, + 1483, + 0, + 1356, + 1355, + 1478, + 1479, + 0, + 1478, + 1477, + 1482, + 1487, + 0, + 1477, + 1480, + 1492, + 1482, + 0, + 1480, + 1481, + 1495, + 1492, + 0, + 1481, + 1485, + 1500, + 1495, + 0, + 1485, + 1489, + 1504, + 1500, + 0, + 1489, + 1491, + 1508, + 1504, + 0, + 1491, + 1494, + 1512, + 1508, + 0, + 1494, + 1497, + 1515, + 1512, + 0, + 1497, + 1502, + 1519, + 1515, + 0, + 1502, + 1506, + 1522, + 1519, + 0, + 1506, + 1510, + 1525, + 1522, + 0, + 1510, + 1516, + 1530, + 1525, + 0, + 1516, + 1520, + 1534, + 1530, + 0, + 1520, + 1524, + 1538, + 1534, + 0, + 1524, + 1528, + 1543, + 1538, + 0, + 1528, + 1532, + 1546, + 1543, + 0, + 1532, + 1535, + 1549, + 1546, + 0, + 1535, + 1539, + 1552, + 1549, + 0, + 1539, + 1542, + 1554, + 1552, + 0, + 1542, + 1547, + 1557, + 1554, + 0, + 1547, + 1550, + 1559, + 1557, + 0, + 1550, + 1566, + 1596, + 1559, + 0, + 1566, + 1568, + 1605, + 1596, + 0, + 1568, + 1572, + 1612, + 1605, + 0, + 1572, + 1578, + 1616, + 1612, + 0, + 1578, + 1583, + 1620, + 1616, + 0, + 1583, + 1592, + 1628, + 1620, + 0, + 1592, + 1595, + 1630, + 1628, + 0, + 1595, + 1598, + 1632, + 1630, + 0, + 1598, + 1601, + 1634, + 1632, + 0, + 1601, + 1603, + 1636, + 1634, + 0, + 1603, + 1606, + 1638, + 1636, + 0, + 1606, + 1608, + 1640, + 1638, + 0, + 1608, + 1607, + 1639, + 1640, + 0, + 1607, + 1604, + 1637, + 1639, + 0, + 1604, + 1602, + 1635, + 1637, + 0, + 1602, + 1599, + 1633, + 1635, + 0, + 1599, + 1597, + 1631, + 1633, + 0, + 1597, + 1593, + 1629, + 1631, + 0, + 1593, + 1585, + 1622, + 1629, + 0, + 1585, + 1576, + 1615, + 1622, + 0, + 1576, + 1564, + 1591, + 1615, + 0, + 1564, + 1560, + 1574, + 1591, + 0, + 1560, + 1561, + 1577, + 1574, + 0, + 1561, + 1569, + 1609, + 1577, + 0, + 1569, + 1571, + 1611, + 1609, + 0, + 1571, + 1575, + 1614, + 1611, + 0, + 1575, + 1580, + 1618, + 1614, + 0, + 1580, + 1584, + 1621, + 1618, + 0, + 1584, + 1587, + 1624, + 1621, + 0, + 1587, + 1589, + 1626, + 1624, + 0, + 1589, + 1590, + 1627, + 1626, + 0, + 1590, + 1588, + 1625, + 1627, + 0, + 1588, + 1586, + 1623, + 1625, + 0, + 1586, + 1581, + 1619, + 1623, + 0, + 1581, + 1579, + 1617, + 1619, + 0, + 1579, + 1573, + 1613, + 1617, + 0, + 1573, + 1570, + 1610, + 1613, + 0, + 1570, + 1567, + 1600, + 1610, + 0, + 1567, + 1565, + 1594, + 1600, + 0, + 1565, + 1562, + 1582, + 1594, + 0, + 1562, + 1556, + 1563, + 1582, + 0, + 1556, + 1548, + 1558, + 1563, + 0, + 1548, + 1544, + 1555, + 1558, + 0, + 1544, + 1540, + 1553, + 1555, + 0, + 1540, + 1536, + 1551, + 1553, + 0, + 1536, + 1531, + 1545, + 1551, + 0, + 1531, + 1527, + 1541, + 1545, + 0, + 1527, + 1521, + 1537, + 1541, + 0, + 1521, + 1517, + 1533, + 1537, + 0, + 1517, + 1514, + 1529, + 1533, + 0, + 1514, + 1511, + 1526, + 1529, + 0, + 1511, + 1507, + 1523, + 1526, + 0, + 1507, + 1501, + 1518, + 1523, + 0, + 1501, + 1496, + 1513, + 1518, + 0, + 1496, + 1493, + 1509, + 1513, + 0, + 1493, + 1490, + 1505, + 1509, + 0, + 1490, + 1486, + 1503, + 1505, + 0, + 1486, + 1484, + 1499, + 1503, + 0, + 1484, + 1483, + 1498, + 1499, + 0, + 1483, + 1479, + 1488, + 1498, + 0, + 1479, + 1478, + 1487, + 1488, + 0, + 1487, + 1482, + 1641, + 1642, + 0, + 1482, + 1492, + 1644, + 1641, + 0, + 1492, + 1495, + 1645, + 1644, + 0, + 1495, + 1500, + 1648, + 1645, + 0, + 1500, + 1504, + 1650, + 1648, + 0, + 1504, + 1508, + 1652, + 1650, + 0, + 1508, + 1512, + 1654, + 1652, + 0, + 1512, + 1515, + 1656, + 1654, + 0, + 1515, + 1519, + 1658, + 1656, + 0, + 1519, + 1522, + 1659, + 1658, + 0, + 1522, + 1525, + 1662, + 1659, + 0, + 1525, + 1530, + 1664, + 1662, + 0, + 1530, + 1534, + 1666, + 1664, + 0, + 1534, + 1538, + 1668, + 1666, + 0, + 1538, + 1543, + 1670, + 1668, + 0, + 1543, + 1546, + 1672, + 1670, + 0, + 1546, + 1549, + 1673, + 1672, + 0, + 1549, + 1552, + 1675, + 1673, + 0, + 1552, + 1554, + 1677, + 1675, + 0, + 1554, + 1557, + 1679, + 1677, + 0, + 1557, + 1559, + 1681, + 1679, + 0, + 1559, + 1596, + 1688, + 1681, + 0, + 1596, + 1605, + 1691, + 1688, + 0, + 1605, + 1612, + 1694, + 1691, + 0, + 1612, + 1616, + 1700, + 1694, + 0, + 1616, + 1620, + 1704, + 1700, + 0, + 1620, + 1628, + 1712, + 1704, + 0, + 1628, + 1630, + 1714, + 1712, + 0, + 1630, + 1632, + 1716, + 1714, + 0, + 1632, + 1634, + 1718, + 1716, + 0, + 1634, + 1636, + 1721, + 1718, + 0, + 1636, + 1638, + 1724, + 1721, + 0, + 1638, + 1640, + 1725, + 1724, + 0, + 1640, + 1639, + 1723, + 1725, + 0, + 1639, + 1637, + 1720, + 1723, + 0, + 1637, + 1635, + 1717, + 1720, + 0, + 1635, + 1633, + 1715, + 1717, + 0, + 1633, + 1631, + 1713, + 1715, + 0, + 1631, + 1629, + 1711, + 1713, + 0, + 1629, + 1622, + 1701, + 1711, + 0, + 1622, + 1615, + 1697, + 1701, + 0, + 1615, + 1591, + 1685, + 1697, + 0, + 1591, + 1574, + 1683, + 1685, + 0, + 1574, + 1577, + 1684, + 1683, + 0, + 1577, + 1609, + 1690, + 1684, + 0, + 1609, + 1611, + 1693, + 1690, + 0, + 1611, + 1614, + 1696, + 1693, + 0, + 1614, + 1618, + 1698, + 1696, + 0, + 1618, + 1621, + 1702, + 1698, + 0, + 1621, + 1624, + 1705, + 1702, + 0, + 1624, + 1626, + 1708, + 1705, + 0, + 1626, + 1627, + 1709, + 1708, + 0, + 1627, + 1625, + 1707, + 1709, + 0, + 1625, + 1623, + 1706, + 1707, + 0, + 1623, + 1619, + 1703, + 1706, + 0, + 1619, + 1617, + 1699, + 1703, + 0, + 1617, + 1613, + 1695, + 1699, + 0, + 1613, + 1610, + 1692, + 1695, + 0, + 1610, + 1600, + 1689, + 1692, + 0, + 1600, + 1594, + 1687, + 1689, + 0, + 1594, + 1582, + 1686, + 1687, + 0, + 1582, + 1563, + 1682, + 1686, + 0, + 1563, + 1558, + 1680, + 1682, + 0, + 1558, + 1555, + 1678, + 1680, + 0, + 1555, + 1553, + 1676, + 1678, + 0, + 1553, + 1551, + 1674, + 1676, + 0, + 1551, + 1545, + 1671, + 1674, + 0, + 1545, + 1541, + 1669, + 1671, + 0, + 1541, + 1537, + 1667, + 1669, + 0, + 1537, + 1533, + 1665, + 1667, + 0, + 1533, + 1529, + 1663, + 1665, + 0, + 1529, + 1526, + 1661, + 1663, + 0, + 1526, + 1523, + 1660, + 1661, + 0, + 1523, + 1518, + 1657, + 1660, + 0, + 1518, + 1513, + 1655, + 1657, + 0, + 1513, + 1509, + 1653, + 1655, + 0, + 1509, + 1505, + 1651, + 1653, + 0, + 1505, + 1503, + 1649, + 1651, + 0, + 1503, + 1499, + 1647, + 1649, + 0, + 1499, + 1498, + 1646, + 1647, + 0, + 1498, + 1488, + 1643, + 1646, + 0, + 1488, + 1487, + 1642, + 1643, + 0, + 1642, + 1641, + 1710, + 1719, + 0, + 1641, + 1644, + 1726, + 1710, + 0, + 1644, + 1645, + 1727, + 1726, + 0, + 1645, + 1648, + 1730, + 1727, + 0, + 1648, + 1650, + 1732, + 1730, + 0, + 1650, + 1652, + 1734, + 1732, + 0, + 1652, + 1654, + 1736, + 1734, + 0, + 1654, + 1656, + 1738, + 1736, + 0, + 1656, + 1658, + 1740, + 1738, + 0, + 1658, + 1659, + 1741, + 1740, + 0, + 1659, + 1662, + 1744, + 1741, + 0, + 1662, + 1664, + 1746, + 1744, + 0, + 1664, + 1666, + 1748, + 1746, + 0, + 1666, + 1668, + 1750, + 1748, + 0, + 1668, + 1670, + 1752, + 1750, + 0, + 1670, + 1672, + 1754, + 1752, + 0, + 1672, + 1673, + 1755, + 1754, + 0, + 1673, + 1675, + 1757, + 1755, + 0, + 1675, + 1677, + 1759, + 1757, + 0, + 1677, + 1679, + 1761, + 1759, + 0, + 1679, + 1681, + 1763, + 1761, + 0, + 1681, + 1688, + 1770, + 1763, + 0, + 1688, + 1691, + 1773, + 1770, + 0, + 1691, + 1694, + 1776, + 1773, + 0, + 1694, + 1700, + 1782, + 1776, + 0, + 1700, + 1704, + 1786, + 1782, + 0, + 1704, + 1712, + 1793, + 1786, + 0, + 1712, + 1714, + 1795, + 1793, + 0, + 1714, + 1716, + 1797, + 1795, + 0, + 1716, + 1718, + 1799, + 1797, + 0, + 1718, + 1721, + 1801, + 1799, + 0, + 1721, + 1724, + 1803, + 1801, + 0, + 1724, + 1725, + 1804, + 1803, + 0, + 1725, + 1723, + 1802, + 1804, + 0, + 1723, + 1720, + 1800, + 1802, + 0, + 1720, + 1717, + 1798, + 1800, + 0, + 1717, + 1715, + 1796, + 1798, + 0, + 1715, + 1713, + 1794, + 1796, + 0, + 1713, + 1711, + 1792, + 1794, + 0, + 1711, + 1701, + 1783, + 1792, + 0, + 1701, + 1697, + 1779, + 1783, + 0, + 1697, + 1685, + 1767, + 1779, + 0, + 1685, + 1683, + 1765, + 1767, + 0, + 1683, + 1684, + 1766, + 1765, + 0, + 1684, + 1690, + 1772, + 1766, + 0, + 1690, + 1693, + 1775, + 1772, + 0, + 1693, + 1696, + 1777, + 1775, + 0, + 1696, + 1698, + 1780, + 1777, + 0, + 1698, + 1702, + 1784, + 1780, + 0, + 1702, + 1705, + 1787, + 1784, + 0, + 1705, + 1708, + 1790, + 1787, + 0, + 1708, + 1709, + 1791, + 1790, + 0, + 1709, + 1707, + 1789, + 1791, + 0, + 1707, + 1706, + 1788, + 1789, + 0, + 1706, + 1703, + 1785, + 1788, + 0, + 1703, + 1699, + 1781, + 1785, + 0, + 1699, + 1695, + 1778, + 1781, + 0, + 1695, + 1692, + 1774, + 1778, + 0, + 1692, + 1689, + 1771, + 1774, + 0, + 1689, + 1687, + 1769, + 1771, + 0, + 1687, + 1686, + 1768, + 1769, + 0, + 1686, + 1682, + 1764, + 1768, + 0, + 1682, + 1680, + 1762, + 1764, + 0, + 1680, + 1678, + 1760, + 1762, + 0, + 1678, + 1676, + 1758, + 1760, + 0, + 1676, + 1674, + 1756, + 1758, + 0, + 1674, + 1671, + 1753, + 1756, + 0, + 1671, + 1669, + 1751, + 1753, + 0, + 1669, + 1667, + 1749, + 1751, + 0, + 1667, + 1665, + 1747, + 1749, + 0, + 1665, + 1663, + 1745, + 1747, + 0, + 1663, + 1661, + 1743, + 1745, + 0, + 1661, + 1660, + 1742, + 1743, + 0, + 1660, + 1657, + 1739, + 1742, + 0, + 1657, + 1655, + 1737, + 1739, + 0, + 1655, + 1653, + 1735, + 1737, + 0, + 1653, + 1651, + 1733, + 1735, + 0, + 1651, + 1649, + 1731, + 1733, + 0, + 1649, + 1647, + 1729, + 1731, + 0, + 1647, + 1646, + 1728, + 1729, + 0, + 1646, + 1643, + 1722, + 1728, + 0, + 1643, + 1642, + 1719, + 1722, + 0, + 1719, + 1710, + 1805, + 1806, + 0, + 1710, + 1726, + 1808, + 1805, + 0, + 1726, + 1727, + 1809, + 1808, + 0, + 1727, + 1730, + 1812, + 1809, + 0, + 1730, + 1732, + 1814, + 1812, + 0, + 1732, + 1734, + 1816, + 1814, + 0, + 1734, + 1736, + 1818, + 1816, + 0, + 1736, + 1738, + 1820, + 1818, + 0, + 1738, + 1740, + 1822, + 1820, + 0, + 1740, + 1741, + 1823, + 1822, + 0, + 1741, + 1744, + 1826, + 1823, + 0, + 1744, + 1746, + 1828, + 1826, + 0, + 1746, + 1748, + 1830, + 1828, + 0, + 1748, + 1750, + 1832, + 1830, + 0, + 1750, + 1752, + 1834, + 1832, + 0, + 1752, + 1754, + 1836, + 1834, + 0, + 1754, + 1755, + 1837, + 1836, + 0, + 1755, + 1757, + 1839, + 1837, + 0, + 1757, + 1759, + 1841, + 1839, + 0, + 1759, + 1761, + 1843, + 1841, + 0, + 1761, + 1763, + 1845, + 1843, + 0, + 1763, + 1770, + 1852, + 1845, + 0, + 1770, + 1773, + 1856, + 1852, + 0, + 1773, + 1776, + 1861, + 1856, + 0, + 1776, + 1782, + 1865, + 1861, + 0, + 1782, + 1786, + 1870, + 1865, + 0, + 1786, + 1793, + 1875, + 1870, + 0, + 1793, + 1795, + 1877, + 1875, + 0, + 1795, + 1797, + 1879, + 1877, + 0, + 1797, + 1799, + 1881, + 1879, + 0, + 1799, + 1801, + 1883, + 1881, + 0, + 1801, + 1803, + 1885, + 1883, + 0, + 1803, + 1804, + 1886, + 1885, + 0, + 1804, + 1802, + 1884, + 1886, + 0, + 1802, + 1800, + 1882, + 1884, + 0, + 1800, + 1798, + 1880, + 1882, + 0, + 1798, + 1796, + 1878, + 1880, + 0, + 1796, + 1794, + 1876, + 1878, + 0, + 1794, + 1792, + 1871, + 1876, + 0, + 1792, + 1783, + 1863, + 1871, + 0, + 1783, + 1779, + 1859, + 1863, + 0, + 1779, + 1767, + 1849, + 1859, + 0, + 1767, + 1765, + 1847, + 1849, + 0, + 1765, + 1766, + 1848, + 1847, + 0, + 1766, + 1772, + 1853, + 1848, + 0, + 1772, + 1775, + 1855, + 1853, + 0, + 1775, + 1777, + 1858, + 1855, + 0, + 1777, + 1780, + 1862, + 1858, + 0, + 1780, + 1784, + 1866, + 1862, + 0, + 1784, + 1787, + 1868, + 1866, + 0, + 1787, + 1790, + 1872, + 1868, + 0, + 1790, + 1791, + 1874, + 1872, + 0, + 1791, + 1789, + 1873, + 1874, + 0, + 1789, + 1788, + 1869, + 1873, + 0, + 1788, + 1785, + 1867, + 1869, + 0, + 1785, + 1781, + 1864, + 1867, + 0, + 1781, + 1778, + 1860, + 1864, + 0, + 1778, + 1774, + 1857, + 1860, + 0, + 1774, + 1771, + 1854, + 1857, + 0, + 1771, + 1769, + 1851, + 1854, + 0, + 1769, + 1768, + 1850, + 1851, + 0, + 1768, + 1764, + 1846, + 1850, + 0, + 1764, + 1762, + 1844, + 1846, + 0, + 1762, + 1760, + 1842, + 1844, + 0, + 1760, + 1758, + 1840, + 1842, + 0, + 1758, + 1756, + 1838, + 1840, + 0, + 1756, + 1753, + 1835, + 1838, + 0, + 1753, + 1751, + 1833, + 1835, + 0, + 1751, + 1749, + 1831, + 1833, + 0, + 1749, + 1747, + 1829, + 1831, + 0, + 1747, + 1745, + 1827, + 1829, + 0, + 1745, + 1743, + 1825, + 1827, + 0, + 1743, + 1742, + 1824, + 1825, + 0, + 1742, + 1739, + 1821, + 1824, + 0, + 1739, + 1737, + 1819, + 1821, + 0, + 1737, + 1735, + 1817, + 1819, + 0, + 1735, + 1733, + 1815, + 1817, + 0, + 1733, + 1731, + 1813, + 1815, + 0, + 1731, + 1729, + 1811, + 1813, + 0, + 1729, + 1728, + 1810, + 1811, + 0, + 1728, + 1722, + 1807, + 1810, + 0, + 1722, + 1719, + 1806, + 1807, + 0, + 1806, + 1805, + 1887, + 1888, + 0, + 1805, + 1808, + 1890, + 1887, + 0, + 1808, + 1809, + 1891, + 1890, + 0, + 1809, + 1812, + 1894, + 1891, + 0, + 1812, + 1814, + 1896, + 1894, + 0, + 1814, + 1816, + 1898, + 1896, + 0, + 1816, + 1818, + 1900, + 1898, + 0, + 1818, + 1820, + 1902, + 1900, + 0, + 1820, + 1822, + 1904, + 1902, + 0, + 1822, + 1823, + 1905, + 1904, + 0, + 1823, + 1826, + 1908, + 1905, + 0, + 1826, + 1828, + 1910, + 1908, + 0, + 1828, + 1830, + 1912, + 1910, + 0, + 1830, + 1832, + 1914, + 1912, + 0, + 1832, + 1834, + 1916, + 1914, + 0, + 1834, + 1836, + 1918, + 1916, + 0, + 1836, + 1837, + 1919, + 1918, + 0, + 1837, + 1839, + 1921, + 1919, + 0, + 1839, + 1841, + 1923, + 1921, + 0, + 1841, + 1843, + 1925, + 1923, + 0, + 1843, + 1845, + 1927, + 1925, + 0, + 1845, + 1852, + 1934, + 1927, + 0, + 1852, + 1856, + 1938, + 1934, + 0, + 1856, + 1861, + 1943, + 1938, + 0, + 1861, + 1865, + 1948, + 1943, + 0, + 1865, + 1870, + 1954, + 1948, + 0, + 1870, + 1875, + 1957, + 1954, + 0, + 1875, + 1877, + 1959, + 1957, + 0, + 1877, + 1879, + 1961, + 1959, + 0, + 1879, + 1881, + 1963, + 1961, + 0, + 1881, + 1883, + 1965, + 1963, + 0, + 1883, + 1885, + 1967, + 1965, + 0, + 1885, + 1886, + 1968, + 1967, + 0, + 1886, + 1884, + 1966, + 1968, + 0, + 1884, + 1882, + 1964, + 1966, + 0, + 1882, + 1880, + 1962, + 1964, + 0, + 1880, + 1878, + 1960, + 1962, + 0, + 1878, + 1876, + 1958, + 1960, + 0, + 1876, + 1871, + 1951, + 1958, + 0, + 1871, + 1863, + 1945, + 1951, + 0, + 1863, + 1859, + 1940, + 1945, + 0, + 1859, + 1849, + 1931, + 1940, + 0, + 1849, + 1847, + 1929, + 1931, + 0, + 1847, + 1848, + 1930, + 1929, + 0, + 1848, + 1853, + 1935, + 1930, + 0, + 1853, + 1855, + 1937, + 1935, + 0, + 1855, + 1858, + 1941, + 1937, + 0, + 1858, + 1862, + 1944, + 1941, + 0, + 1862, + 1866, + 1947, + 1944, + 0, + 1866, + 1868, + 1950, + 1947, + 0, + 1868, + 1872, + 1953, + 1950, + 0, + 1872, + 1874, + 1956, + 1953, + 0, + 1874, + 1873, + 1955, + 1956, + 0, + 1873, + 1869, + 1952, + 1955, + 0, + 1869, + 1867, + 1949, + 1952, + 0, + 1867, + 1864, + 1946, + 1949, + 0, + 1864, + 1860, + 1942, + 1946, + 0, + 1860, + 1857, + 1939, + 1942, + 0, + 1857, + 1854, + 1936, + 1939, + 0, + 1854, + 1851, + 1933, + 1936, + 0, + 1851, + 1850, + 1932, + 1933, + 0, + 1850, + 1846, + 1928, + 1932, + 0, + 1846, + 1844, + 1926, + 1928, + 0, + 1844, + 1842, + 1924, + 1926, + 0, + 1842, + 1840, + 1922, + 1924, + 0, + 1840, + 1838, + 1920, + 1922, + 0, + 1838, + 1835, + 1917, + 1920, + 0, + 1835, + 1833, + 1915, + 1917, + 0, + 1833, + 1831, + 1913, + 1915, + 0, + 1831, + 1829, + 1911, + 1913, + 0, + 1829, + 1827, + 1909, + 1911, + 0, + 1827, + 1825, + 1907, + 1909, + 0, + 1825, + 1824, + 1906, + 1907, + 0, + 1824, + 1821, + 1903, + 1906, + 0, + 1821, + 1819, + 1901, + 1903, + 0, + 1819, + 1817, + 1899, + 1901, + 0, + 1817, + 1815, + 1897, + 1899, + 0, + 1815, + 1813, + 1895, + 1897, + 0, + 1813, + 1811, + 1893, + 1895, + 0, + 1811, + 1810, + 1892, + 1893, + 0, + 1810, + 1807, + 1889, + 1892, + 0, + 1807, + 1806, + 1888, + 1889, + 0, + 1888, + 1887, + 1969, + 1970, + 0, + 1887, + 1890, + 1972, + 1969, + 0, + 1890, + 1891, + 1973, + 1972, + 0, + 1891, + 1894, + 1976, + 1973, + 0, + 1894, + 1896, + 1978, + 1976, + 0, + 1896, + 1898, + 1980, + 1978, + 0, + 1898, + 1900, + 1982, + 1980, + 0, + 1900, + 1902, + 1984, + 1982, + 0, + 1902, + 1904, + 1986, + 1984, + 0, + 1904, + 1905, + 1987, + 1986, + 0, + 1905, + 1908, + 1990, + 1987, + 0, + 1908, + 1910, + 1992, + 1990, + 0, + 1910, + 1912, + 1994, + 1992, + 0, + 1912, + 1914, + 1996, + 1994, + 0, + 1914, + 1916, + 1998, + 1996, + 0, + 1916, + 1918, + 2000, + 1998, + 0, + 1918, + 1919, + 2001, + 2000, + 0, + 1919, + 1921, + 2003, + 2001, + 0, + 1921, + 1923, + 2005, + 2003, + 0, + 1923, + 1925, + 2007, + 2005, + 0, + 1925, + 1927, + 2009, + 2007, + 0, + 1927, + 1934, + 2017, + 2009, + 0, + 1934, + 1938, + 2020, + 2017, + 0, + 1938, + 1943, + 2026, + 2020, + 0, + 1943, + 1948, + 2030, + 2026, + 0, + 1948, + 1954, + 2038, + 2030, + 0, + 1954, + 1957, + 2040, + 2038, + 0, + 1957, + 1959, + 2042, + 2040, + 0, + 1959, + 1961, + 2044, + 2042, + 0, + 1961, + 1963, + 2046, + 2044, + 0, + 1963, + 1965, + 2048, + 2046, + 0, + 1965, + 1967, + 2050, + 2048, + 0, + 1967, + 1968, + 2049, + 2050, + 0, + 1968, + 1966, + 2047, + 2049, + 0, + 1966, + 1964, + 2045, + 2047, + 0, + 1964, + 1962, + 2043, + 2045, + 0, + 1962, + 1960, + 2041, + 2043, + 0, + 1960, + 1958, + 2039, + 2041, + 0, + 1958, + 1951, + 2033, + 2039, + 0, + 1951, + 1945, + 2027, + 2033, + 0, + 1945, + 1940, + 2021, + 2027, + 0, + 1940, + 1931, + 2013, + 2021, + 0, + 1931, + 1929, + 2011, + 2013, + 0, + 1929, + 1930, + 2012, + 2011, + 0, + 1930, + 1935, + 2016, + 2012, + 0, + 1935, + 1937, + 2019, + 2016, + 0, + 1937, + 1941, + 2022, + 2019, + 0, + 1941, + 1944, + 2024, + 2022, + 0, + 1944, + 1947, + 2028, + 2024, + 0, + 1947, + 1950, + 2031, + 2028, + 0, + 1950, + 1953, + 2034, + 2031, + 0, + 1953, + 1956, + 2037, + 2034, + 0, + 1956, + 1955, + 2036, + 2037, + 0, + 1955, + 1952, + 2035, + 2036, + 0, + 1952, + 1949, + 2032, + 2035, + 0, + 1949, + 1946, + 2029, + 2032, + 0, + 1946, + 1942, + 2025, + 2029, + 0, + 1942, + 1939, + 2023, + 2025, + 0, + 1939, + 1936, + 2018, + 2023, + 0, + 1936, + 1933, + 2015, + 2018, + 0, + 1933, + 1932, + 2014, + 2015, + 0, + 1932, + 1928, + 2010, + 2014, + 0, + 1928, + 1926, + 2008, + 2010, + 0, + 1926, + 1924, + 2006, + 2008, + 0, + 1924, + 1922, + 2004, + 2006, + 0, + 1922, + 1920, + 2002, + 2004, + 0, + 1920, + 1917, + 1999, + 2002, + 0, + 1917, + 1915, + 1997, + 1999, + 0, + 1915, + 1913, + 1995, + 1997, + 0, + 1913, + 1911, + 1993, + 1995, + 0, + 1911, + 1909, + 1991, + 1993, + 0, + 1909, + 1907, + 1989, + 1991, + 0, + 1907, + 1906, + 1988, + 1989, + 0, + 1906, + 1903, + 1985, + 1988, + 0, + 1903, + 1901, + 1983, + 1985, + 0, + 1901, + 1899, + 1981, + 1983, + 0, + 1899, + 1897, + 1979, + 1981, + 0, + 1897, + 1895, + 1977, + 1979, + 0, + 1895, + 1893, + 1975, + 1977, + 0, + 1893, + 1892, + 1974, + 1975, + 0, + 1892, + 1889, + 1971, + 1974, + 0, + 1889, + 1888, + 1970, + 1971, + 0, + 1970, + 1969, + 2051, + 2052, + 0, + 1969, + 1972, + 2054, + 2051, + 0, + 1972, + 1973, + 2055, + 2054, + 0, + 1973, + 1976, + 2058, + 2055, + 0, + 1976, + 1978, + 2060, + 2058, + 0, + 1978, + 1980, + 2062, + 2060, + 0, + 1980, + 1982, + 2064, + 2062, + 0, + 1982, + 1984, + 2066, + 2064, + 0, + 1984, + 1986, + 2068, + 2066, + 0, + 1986, + 1987, + 2070, + 2068, + 0, + 1987, + 1990, + 2072, + 2070, + 0, + 1990, + 1992, + 2074, + 2072, + 0, + 1992, + 1994, + 2076, + 2074, + 0, + 1994, + 1996, + 2078, + 2076, + 0, + 1996, + 1998, + 2080, + 2078, + 0, + 1998, + 2000, + 2082, + 2080, + 0, + 2000, + 2001, + 2083, + 2082, + 0, + 2001, + 2003, + 2085, + 2083, + 0, + 2003, + 2005, + 2087, + 2085, + 0, + 2005, + 2007, + 2090, + 2087, + 0, + 2007, + 2009, + 2091, + 2090, + 0, + 2009, + 2017, + 2099, + 2091, + 0, + 2017, + 2020, + 2104, + 2099, + 0, + 2020, + 2026, + 2109, + 2104, + 0, + 2026, + 2030, + 2114, + 2109, + 0, + 2030, + 2038, + 2120, + 2114, + 0, + 2038, + 2040, + 2122, + 2120, + 0, + 2040, + 2042, + 2124, + 2122, + 0, + 2042, + 2044, + 2126, + 2124, + 0, + 2044, + 2046, + 2128, + 2126, + 0, + 2046, + 2048, + 2130, + 2128, + 0, + 2048, + 2050, + 2132, + 2130, + 0, + 2050, + 2049, + 2131, + 2132, + 0, + 2049, + 2047, + 2129, + 2131, + 0, + 2047, + 2045, + 2127, + 2129, + 0, + 2045, + 2043, + 2125, + 2127, + 0, + 2043, + 2041, + 2123, + 2125, + 0, + 2041, + 2039, + 2121, + 2123, + 0, + 2039, + 2033, + 2113, + 2121, + 0, + 2033, + 2027, + 2107, + 2113, + 0, + 2027, + 2021, + 2102, + 2107, + 0, + 2021, + 2013, + 2095, + 2102, + 0, + 2013, + 2011, + 2093, + 2095, + 0, + 2011, + 2012, + 2094, + 2093, + 0, + 2012, + 2016, + 2097, + 2094, + 0, + 2016, + 2019, + 2100, + 2097, + 0, + 2019, + 2022, + 2103, + 2100, + 0, + 2022, + 2024, + 2106, + 2103, + 0, + 2024, + 2028, + 2110, + 2106, + 0, + 2028, + 2031, + 2112, + 2110, + 0, + 2031, + 2034, + 2116, + 2112, + 0, + 2034, + 2037, + 2118, + 2116, + 0, + 2037, + 2036, + 2119, + 2118, + 0, + 2036, + 2035, + 2117, + 2119, + 0, + 2035, + 2032, + 2115, + 2117, + 0, + 2032, + 2029, + 2111, + 2115, + 0, + 2029, + 2025, + 2108, + 2111, + 0, + 2025, + 2023, + 2105, + 2108, + 0, + 2023, + 2018, + 2101, + 2105, + 0, + 2018, + 2015, + 2098, + 2101, + 0, + 2015, + 2014, + 2096, + 2098, + 0, + 2014, + 2010, + 2092, + 2096, + 0, + 2010, + 2008, + 2089, + 2092, + 0, + 2008, + 2006, + 2088, + 2089, + 0, + 2006, + 2004, + 2086, + 2088, + 0, + 2004, + 2002, + 2084, + 2086, + 0, + 2002, + 1999, + 2081, + 2084, + 0, + 1999, + 1997, + 2079, + 2081, + 0, + 1997, + 1995, + 2077, + 2079, + 0, + 1995, + 1993, + 2075, + 2077, + 0, + 1993, + 1991, + 2073, + 2075, + 0, + 1991, + 1989, + 2071, + 2073, + 0, + 1989, + 1988, + 2069, + 2071, + 0, + 1988, + 1985, + 2067, + 2069, + 0, + 1985, + 1983, + 2065, + 2067, + 0, + 1983, + 1981, + 2063, + 2065, + 0, + 1981, + 1979, + 2061, + 2063, + 0, + 1979, + 1977, + 2059, + 2061, + 0, + 1977, + 1975, + 2057, + 2059, + 0, + 1975, + 1974, + 2056, + 2057, + 0, + 1974, + 1971, + 2053, + 2056, + 0, + 1971, + 1970, + 2052, + 2053, + 0, + 2052, + 2051, + 2133, + 2134, + 0, + 2051, + 2054, + 2136, + 2133, + 0, + 2054, + 2055, + 2137, + 2136, + 0, + 2055, + 2058, + 2140, + 2137, + 0, + 2058, + 2060, + 2142, + 2140, + 0, + 2060, + 2062, + 2144, + 2142, + 0, + 2062, + 2064, + 2146, + 2144, + 0, + 2064, + 2066, + 2148, + 2146, + 0, + 2066, + 2068, + 2150, + 2148, + 0, + 2068, + 2070, + 2152, + 2150, + 0, + 2070, + 2072, + 2154, + 2152, + 0, + 2072, + 2074, + 2156, + 2154, + 0, + 2074, + 2076, + 2158, + 2156, + 0, + 2076, + 2078, + 2160, + 2158, + 0, + 2078, + 2080, + 2162, + 2160, + 0, + 2080, + 2082, + 2164, + 2162, + 0, + 2082, + 2083, + 2166, + 2164, + 0, + 2083, + 2085, + 2167, + 2166, + 0, + 2085, + 2087, + 2169, + 2167, + 0, + 2087, + 2090, + 2172, + 2169, + 0, + 2090, + 2091, + 2173, + 2172, + 0, + 2091, + 2099, + 2182, + 2173, + 0, + 2099, + 2104, + 2186, + 2182, + 0, + 2104, + 2109, + 2192, + 2186, + 0, + 2109, + 2114, + 2197, + 2192, + 0, + 2114, + 2120, + 2203, + 2197, + 0, + 2120, + 2122, + 2205, + 2203, + 0, + 2122, + 2124, + 2207, + 2205, + 0, + 2124, + 2126, + 2209, + 2207, + 0, + 2126, + 2128, + 2211, + 2209, + 0, + 2128, + 2130, + 2213, + 2211, + 0, + 2130, + 2132, + 2214, + 2213, + 0, + 2132, + 2131, + 2212, + 2214, + 0, + 2131, + 2129, + 2210, + 2212, + 0, + 2129, + 2127, + 2208, + 2210, + 0, + 2127, + 2125, + 2206, + 2208, + 0, + 2125, + 2123, + 2204, + 2206, + 0, + 2123, + 2121, + 2202, + 2204, + 0, + 2121, + 2113, + 2194, + 2202, + 0, + 2113, + 2107, + 2189, + 2194, + 0, + 2107, + 2102, + 2184, + 2189, + 0, + 2102, + 2095, + 2177, + 2184, + 0, + 2095, + 2093, + 2175, + 2177, + 0, + 2093, + 2094, + 2176, + 2175, + 0, + 2094, + 2097, + 2179, + 2176, + 0, + 2097, + 2100, + 2181, + 2179, + 0, + 2100, + 2103, + 2185, + 2181, + 0, + 2103, + 2106, + 2188, + 2185, + 0, + 2106, + 2110, + 2191, + 2188, + 0, + 2110, + 2112, + 2195, + 2191, + 0, + 2112, + 2116, + 2198, + 2195, + 0, + 2116, + 2118, + 2200, + 2198, + 0, + 2118, + 2119, + 2201, + 2200, + 0, + 2119, + 2117, + 2199, + 2201, + 0, + 2117, + 2115, + 2196, + 2199, + 0, + 2115, + 2111, + 2193, + 2196, + 0, + 2111, + 2108, + 2190, + 2193, + 0, + 2108, + 2105, + 2187, + 2190, + 0, + 2105, + 2101, + 2183, + 2187, + 0, + 2101, + 2098, + 2180, + 2183, + 0, + 2098, + 2096, + 2178, + 2180, + 0, + 2096, + 2092, + 2174, + 2178, + 0, + 2092, + 2089, + 2171, + 2174, + 0, + 2089, + 2088, + 2170, + 2171, + 0, + 2088, + 2086, + 2168, + 2170, + 0, + 2086, + 2084, + 2165, + 2168, + 0, + 2084, + 2081, + 2163, + 2165, + 0, + 2081, + 2079, + 2161, + 2163, + 0, + 2079, + 2077, + 2159, + 2161, + 0, + 2077, + 2075, + 2157, + 2159, + 0, + 2075, + 2073, + 2155, + 2157, + 0, + 2073, + 2071, + 2153, + 2155, + 0, + 2071, + 2069, + 2151, + 2153, + 0, + 2069, + 2067, + 2149, + 2151, + 0, + 2067, + 2065, + 2147, + 2149, + 0, + 2065, + 2063, + 2145, + 2147, + 0, + 2063, + 2061, + 2143, + 2145, + 0, + 2061, + 2059, + 2141, + 2143, + 0, + 2059, + 2057, + 2139, + 2141, + 0, + 2057, + 2056, + 2138, + 2139, + 0, + 2056, + 2053, + 2135, + 2138, + 0, + 2053, + 2052, + 2134, + 2135, + 0, + 2134, + 2133, + 2215, + 2216, + 0, + 2133, + 2136, + 2218, + 2215, + 0, + 2136, + 2137, + 2219, + 2218, + 0, + 2137, + 2140, + 2222, + 2219, + 0, + 2140, + 2142, + 2224, + 2222, + 0, + 2142, + 2144, + 2226, + 2224, + 0, + 2144, + 2146, + 2228, + 2226, + 0, + 2146, + 2148, + 2230, + 2228, + 0, + 2148, + 2150, + 2232, + 2230, + 0, + 2150, + 2152, + 2234, + 2232, + 0, + 2152, + 2154, + 2236, + 2234, + 0, + 2154, + 2156, + 2238, + 2236, + 0, + 2156, + 2158, + 2240, + 2238, + 0, + 2158, + 2160, + 2242, + 2240, + 0, + 2160, + 2162, + 2244, + 2242, + 0, + 2162, + 2164, + 2246, + 2244, + 0, + 2164, + 2166, + 2248, + 2246, + 0, + 2166, + 2167, + 2249, + 2248, + 0, + 2167, + 2169, + 2251, + 2249, + 0, + 2169, + 2172, + 2254, + 2251, + 0, + 2172, + 2173, + 2255, + 2254, + 0, + 2173, + 2182, + 2264, + 2255, + 0, + 2182, + 2186, + 2268, + 2264, + 0, + 2186, + 2192, + 2274, + 2268, + 0, + 2192, + 2197, + 2280, + 2274, + 0, + 2197, + 2203, + 2285, + 2280, + 0, + 2203, + 2205, + 2287, + 2285, + 0, + 2205, + 2207, + 2289, + 2287, + 0, + 2207, + 2209, + 2291, + 2289, + 0, + 2209, + 2211, + 2293, + 2291, + 0, + 2211, + 2213, + 2295, + 2293, + 0, + 2213, + 2214, + 2296, + 2295, + 0, + 2214, + 2212, + 2294, + 2296, + 0, + 2212, + 2210, + 2292, + 2294, + 0, + 2210, + 2208, + 2290, + 2292, + 0, + 2208, + 2206, + 2288, + 2290, + 0, + 2206, + 2204, + 2286, + 2288, + 0, + 2204, + 2202, + 2284, + 2286, + 0, + 2202, + 2194, + 2275, + 2284, + 0, + 2194, + 2189, + 2271, + 2275, + 0, + 2189, + 2184, + 2265, + 2271, + 0, + 2184, + 2177, + 2259, + 2265, + 0, + 2177, + 2175, + 2257, + 2259, + 0, + 2175, + 2176, + 2258, + 2257, + 0, + 2176, + 2179, + 2261, + 2258, + 0, + 2179, + 2181, + 2263, + 2261, + 0, + 2181, + 2185, + 2267, + 2263, + 0, + 2185, + 2188, + 2270, + 2267, + 0, + 2188, + 2191, + 2273, + 2270, + 0, + 2191, + 2195, + 2277, + 2273, + 0, + 2195, + 2198, + 2279, + 2277, + 0, + 2198, + 2200, + 2282, + 2279, + 0, + 2200, + 2201, + 2283, + 2282, + 0, + 2201, + 2199, + 2281, + 2283, + 0, + 2199, + 2196, + 2278, + 2281, + 0, + 2196, + 2193, + 2276, + 2278, + 0, + 2193, + 2190, + 2272, + 2276, + 0, + 2190, + 2187, + 2269, + 2272, + 0, + 2187, + 2183, + 2266, + 2269, + 0, + 2183, + 2180, + 2262, + 2266, + 0, + 2180, + 2178, + 2260, + 2262, + 0, + 2178, + 2174, + 2256, + 2260, + 0, + 2174, + 2171, + 2253, + 2256, + 0, + 2171, + 2170, + 2252, + 2253, + 0, + 2170, + 2168, + 2250, + 2252, + 0, + 2168, + 2165, + 2247, + 2250, + 0, + 2165, + 2163, + 2245, + 2247, + 0, + 2163, + 2161, + 2243, + 2245, + 0, + 2161, + 2159, + 2241, + 2243, + 0, + 2159, + 2157, + 2239, + 2241, + 0, + 2157, + 2155, + 2237, + 2239, + 0, + 2155, + 2153, + 2235, + 2237, + 0, + 2153, + 2151, + 2233, + 2235, + 0, + 2151, + 2149, + 2231, + 2233, + 0, + 2149, + 2147, + 2229, + 2231, + 0, + 2147, + 2145, + 2227, + 2229, + 0, + 2145, + 2143, + 2225, + 2227, + 0, + 2143, + 2141, + 2223, + 2225, + 0, + 2141, + 2139, + 2221, + 2223, + 0, + 2139, + 2138, + 2220, + 2221, + 0, + 2138, + 2135, + 2217, + 2220, + 0, + 2135, + 2134, + 2216, + 2217, + 0, + 2216, + 2215, + 2297, + 2298, + 0, + 2215, + 2218, + 2300, + 2297, + 0, + 2218, + 2219, + 2301, + 2300, + 0, + 2219, + 2222, + 2304, + 2301, + 0, + 2222, + 2224, + 2306, + 2304, + 0, + 2224, + 2226, + 2308, + 2306, + 0, + 2226, + 2228, + 2310, + 2308, + 0, + 2228, + 2230, + 2312, + 2310, + 0, + 2230, + 2232, + 2314, + 2312, + 0, + 2232, + 2234, + 2316, + 2314, + 0, + 2234, + 2236, + 2318, + 2316, + 0, + 2236, + 2238, + 2320, + 2318, + 0, + 2238, + 2240, + 2322, + 2320, + 0, + 2240, + 2242, + 2324, + 2322, + 0, + 2242, + 2244, + 2326, + 2324, + 0, + 2244, + 2246, + 2328, + 2326, + 0, + 2246, + 2248, + 2330, + 2328, + 0, + 2248, + 2249, + 2331, + 2330, + 0, + 2249, + 2251, + 2333, + 2331, + 0, + 2251, + 2254, + 2336, + 2333, + 0, + 2254, + 2255, + 2337, + 2336, + 0, + 2255, + 2264, + 2347, + 2337, + 0, + 2264, + 2268, + 2353, + 2347, + 0, + 2268, + 2274, + 2357, + 2353, + 0, + 2274, + 2280, + 2363, + 2357, + 0, + 2280, + 2285, + 2367, + 2363, + 0, + 2285, + 2287, + 2369, + 2367, + 0, + 2287, + 2289, + 2371, + 2369, + 0, + 2289, + 2291, + 2374, + 2371, + 0, + 2291, + 2293, + 2376, + 2374, + 0, + 2293, + 2295, + 2378, + 2376, + 0, + 2295, + 2296, + 2377, + 2378, + 0, + 2296, + 2294, + 2375, + 2377, + 0, + 2294, + 2292, + 2373, + 2375, + 0, + 2292, + 2290, + 2372, + 2373, + 0, + 2290, + 2288, + 2370, + 2372, + 0, + 2288, + 2286, + 2368, + 2370, + 0, + 2286, + 2284, + 2364, + 2368, + 0, + 2284, + 2275, + 2356, + 2364, + 0, + 2275, + 2271, + 2350, + 2356, + 0, + 2271, + 2265, + 2346, + 2350, + 0, + 2265, + 2259, + 2341, + 2346, + 0, + 2259, + 2257, + 2338, + 2341, + 0, + 2257, + 2258, + 2340, + 2338, + 0, + 2258, + 2261, + 2342, + 2340, + 0, + 2261, + 2263, + 2344, + 2342, + 0, + 2263, + 2267, + 2348, + 2344, + 0, + 2267, + 2270, + 2351, + 2348, + 0, + 2270, + 2273, + 2354, + 2351, + 0, + 2273, + 2277, + 2358, + 2354, + 0, + 2277, + 2279, + 2360, + 2358, + 0, + 2279, + 2282, + 2362, + 2360, + 0, + 2282, + 2283, + 2366, + 2362, + 0, + 2283, + 2281, + 2365, + 2366, + 0, + 2281, + 2278, + 2361, + 2365, + 0, + 2278, + 2276, + 2359, + 2361, + 0, + 2276, + 2272, + 2355, + 2359, + 0, + 2272, + 2269, + 2352, + 2355, + 0, + 2269, + 2266, + 2349, + 2352, + 0, + 2266, + 2262, + 2345, + 2349, + 0, + 2262, + 2260, + 2343, + 2345, + 0, + 2260, + 2256, + 2339, + 2343, + 0, + 2256, + 2253, + 2335, + 2339, + 0, + 2253, + 2252, + 2334, + 2335, + 0, + 2252, + 2250, + 2332, + 2334, + 0, + 2250, + 2247, + 2329, + 2332, + 0, + 2247, + 2245, + 2327, + 2329, + 0, + 2245, + 2243, + 2325, + 2327, + 0, + 2243, + 2241, + 2323, + 2325, + 0, + 2241, + 2239, + 2321, + 2323, + 0, + 2239, + 2237, + 2319, + 2321, + 0, + 2237, + 2235, + 2317, + 2319, + 0, + 2235, + 2233, + 2315, + 2317, + 0, + 2233, + 2231, + 2313, + 2315, + 0, + 2231, + 2229, + 2311, + 2313, + 0, + 2229, + 2227, + 2309, + 2311, + 0, + 2227, + 2225, + 2307, + 2309, + 0, + 2225, + 2223, + 2305, + 2307, + 0, + 2223, + 2221, + 2303, + 2305, + 0, + 2221, + 2220, + 2302, + 2303, + 0, + 2220, + 2217, + 2299, + 2302, + 0, + 2217, + 2216, + 2298, + 2299, + 0, + 2298, + 2297, + 2379, + 2380, + 0, + 2297, + 2300, + 2382, + 2379, + 0, + 2300, + 2301, + 2383, + 2382, + 0, + 2301, + 2304, + 2386, + 2383, + 0, + 2304, + 2306, + 2388, + 2386, + 0, + 2306, + 2308, + 2390, + 2388, + 0, + 2308, + 2310, + 2392, + 2390, + 0, + 2310, + 2312, + 2394, + 2392, + 0, + 2312, + 2314, + 2396, + 2394, + 0, + 2314, + 2316, + 2398, + 2396, + 0, + 2316, + 2318, + 2400, + 2398, + 0, + 2318, + 2320, + 2402, + 2400, + 0, + 2320, + 2322, + 2404, + 2402, + 0, + 2322, + 2324, + 2406, + 2404, + 0, + 2324, + 2326, + 2408, + 2406, + 0, + 2326, + 2328, + 2410, + 2408, + 0, + 2328, + 2330, + 2412, + 2410, + 0, + 2330, + 2331, + 2414, + 2412, + 0, + 2331, + 2333, + 2415, + 2414, + 0, + 2333, + 2336, + 2418, + 2415, + 0, + 2336, + 2337, + 2419, + 2418, + 0, + 2337, + 2347, + 2430, + 2419, + 0, + 2347, + 2353, + 2435, + 2430, + 0, + 2353, + 2357, + 2440, + 2435, + 0, + 2357, + 2363, + 2448, + 2440, + 0, + 2363, + 2367, + 2450, + 2448, + 0, + 2367, + 2369, + 2452, + 2450, + 0, + 2369, + 2371, + 2454, + 2452, + 0, + 2371, + 2374, + 2456, + 2454, + 0, + 2374, + 2376, + 2458, + 2456, + 0, + 2376, + 2378, + 2460, + 2458, + 0, + 2378, + 2377, + 2459, + 2460, + 0, + 2377, + 2375, + 2457, + 2459, + 0, + 2375, + 2373, + 2455, + 2457, + 0, + 2373, + 2372, + 2453, + 2455, + 0, + 2372, + 2370, + 2451, + 2453, + 0, + 2370, + 2368, + 2449, + 2451, + 0, + 2368, + 2364, + 2443, + 2449, + 0, + 2364, + 2356, + 2437, + 2443, + 0, + 2356, + 2350, + 2432, + 2437, + 0, + 2350, + 2346, + 2427, + 2432, + 0, + 2346, + 2341, + 2423, + 2427, + 0, + 2341, + 2338, + 2420, + 2423, + 0, + 2338, + 2340, + 2421, + 2420, + 0, + 2340, + 2342, + 2424, + 2421, + 0, + 2342, + 2344, + 2426, + 2424, + 0, + 2344, + 2348, + 2429, + 2426, + 0, + 2348, + 2351, + 2433, + 2429, + 0, + 2351, + 2354, + 2436, + 2433, + 0, + 2354, + 2358, + 2439, + 2436, + 0, + 2358, + 2360, + 2442, + 2439, + 0, + 2360, + 2362, + 2445, + 2442, + 0, + 2362, + 2366, + 2447, + 2445, + 0, + 2366, + 2365, + 2446, + 2447, + 0, + 2365, + 2361, + 2444, + 2446, + 0, + 2361, + 2359, + 2441, + 2444, + 0, + 2359, + 2355, + 2438, + 2441, + 0, + 2355, + 2352, + 2434, + 2438, + 0, + 2352, + 2349, + 2431, + 2434, + 0, + 2349, + 2345, + 2428, + 2431, + 0, + 2345, + 2343, + 2425, + 2428, + 0, + 2343, + 2339, + 2422, + 2425, + 0, + 2339, + 2335, + 2417, + 2422, + 0, + 2335, + 2334, + 2416, + 2417, + 0, + 2334, + 2332, + 2413, + 2416, + 0, + 2332, + 2329, + 2411, + 2413, + 0, + 2329, + 2327, + 2409, + 2411, + 0, + 2327, + 2325, + 2407, + 2409, + 0, + 2325, + 2323, + 2405, + 2407, + 0, + 2323, + 2321, + 2403, + 2405, + 0, + 2321, + 2319, + 2401, + 2403, + 0, + 2319, + 2317, + 2399, + 2401, + 0, + 2317, + 2315, + 2397, + 2399, + 0, + 2315, + 2313, + 2395, + 2397, + 0, + 2313, + 2311, + 2393, + 2395, + 0, + 2311, + 2309, + 2391, + 2393, + 0, + 2309, + 2307, + 2389, + 2391, + 0, + 2307, + 2305, + 2387, + 2389, + 0, + 2305, + 2303, + 2385, + 2387, + 0, + 2303, + 2302, + 2384, + 2385, + 0, + 2302, + 2299, + 2381, + 2384, + 0, + 2299, + 2298, + 2380, + 2381, + 0, + 2380, + 2379, + 2461, + 2462, + 0, + 2379, + 2382, + 2464, + 2461, + 0, + 2382, + 2383, + 2465, + 2464, + 0, + 2383, + 2386, + 2468, + 2465, + 0, + 2386, + 2388, + 2470, + 2468, + 0, + 2388, + 2390, + 2472, + 2470, + 0, + 2390, + 2392, + 2474, + 2472, + 0, + 2392, + 2394, + 2476, + 2474, + 0, + 2394, + 2396, + 2478, + 2476, + 0, + 2396, + 2398, + 2480, + 2478, + 0, + 2398, + 2400, + 2482, + 2480, + 0, + 2400, + 2402, + 2484, + 2482, + 0, + 2402, + 2404, + 2486, + 2484, + 0, + 2404, + 2406, + 2488, + 2486, + 0, + 2406, + 2408, + 2490, + 2488, + 0, + 2408, + 2410, + 2492, + 2490, + 0, + 2410, + 2412, + 2494, + 2492, + 0, + 2412, + 2414, + 2496, + 2494, + 0, + 2414, + 2415, + 2497, + 2496, + 0, + 2415, + 2418, + 2500, + 2497, + 0, + 2418, + 2419, + 2501, + 2500, + 0, + 2419, + 2430, + 2512, + 2501, + 0, + 2430, + 2435, + 2518, + 2512, + 0, + 2435, + 2440, + 2524, + 2518, + 0, + 2440, + 2448, + 2530, + 2524, + 0, + 2448, + 2450, + 2532, + 2530, + 0, + 2450, + 2452, + 2534, + 2532, + 0, + 2452, + 2454, + 2536, + 2534, + 0, + 2454, + 2456, + 2538, + 2536, + 0, + 2456, + 2458, + 2540, + 2538, + 0, + 2458, + 2460, + 2542, + 2540, + 0, + 2460, + 2459, + 2541, + 2542, + 0, + 2459, + 2457, + 2539, + 2541, + 0, + 2457, + 2455, + 2537, + 2539, + 0, + 2455, + 2453, + 2535, + 2537, + 0, + 2453, + 2451, + 2533, + 2535, + 0, + 2451, + 2449, + 2531, + 2533, + 0, + 2449, + 2443, + 2525, + 2531, + 0, + 2443, + 2437, + 2519, + 2525, + 0, + 2437, + 2432, + 2513, + 2519, + 0, + 2432, + 2427, + 2509, + 2513, + 0, + 2427, + 2423, + 2505, + 2509, + 0, + 2423, + 2420, + 2502, + 2505, + 0, + 2420, + 2421, + 2503, + 2502, + 0, + 2421, + 2424, + 2506, + 2503, + 0, + 2424, + 2426, + 2508, + 2506, + 0, + 2426, + 2429, + 2511, + 2508, + 0, + 2429, + 2433, + 2515, + 2511, + 0, + 2433, + 2436, + 2517, + 2515, + 0, + 2436, + 2439, + 2521, + 2517, + 0, + 2439, + 2442, + 2523, + 2521, + 0, + 2442, + 2445, + 2527, + 2523, + 0, + 2445, + 2447, + 2528, + 2527, + 0, + 2447, + 2446, + 2529, + 2528, + 0, + 2446, + 2444, + 2526, + 2529, + 0, + 2444, + 2441, + 2522, + 2526, + 0, + 2441, + 2438, + 2520, + 2522, + 0, + 2438, + 2434, + 2516, + 2520, + 0, + 2434, + 2431, + 2514, + 2516, + 0, + 2431, + 2428, + 2510, + 2514, + 0, + 2428, + 2425, + 2507, + 2510, + 0, + 2425, + 2422, + 2504, + 2507, + 0, + 2422, + 2417, + 2499, + 2504, + 0, + 2417, + 2416, + 2498, + 2499, + 0, + 2416, + 2413, + 2495, + 2498, + 0, + 2413, + 2411, + 2493, + 2495, + 0, + 2411, + 2409, + 2491, + 2493, + 0, + 2409, + 2407, + 2489, + 2491, + 0, + 2407, + 2405, + 2487, + 2489, + 0, + 2405, + 2403, + 2485, + 2487, + 0, + 2403, + 2401, + 2483, + 2485, + 0, + 2401, + 2399, + 2481, + 2483, + 0, + 2399, + 2397, + 2479, + 2481, + 0, + 2397, + 2395, + 2477, + 2479, + 0, + 2395, + 2393, + 2475, + 2477, + 0, + 2393, + 2391, + 2473, + 2475, + 0, + 2391, + 2389, + 2471, + 2473, + 0, + 2389, + 2387, + 2469, + 2471, + 0, + 2387, + 2385, + 2467, + 2469, + 0, + 2385, + 2384, + 2466, + 2467, + 0, + 2384, + 2381, + 2463, + 2466, + 0, + 2381, + 2380, + 2462, + 2463, + 0, + 2462, + 2461, + 2543, + 2544, + 0, + 2461, + 2464, + 2546, + 2543, + 0, + 2464, + 2465, + 2547, + 2546, + 0, + 2465, + 2468, + 2550, + 2547, + 0, + 2468, + 2470, + 2552, + 2550, + 0, + 2470, + 2472, + 2554, + 2552, + 0, + 2472, + 2474, + 2556, + 2554, + 0, + 2474, + 2476, + 2558, + 2556, + 0, + 2476, + 2478, + 2560, + 2558, + 0, + 2478, + 2480, + 2562, + 2560, + 0, + 2480, + 2482, + 2564, + 2562, + 0, + 2482, + 2484, + 2566, + 2564, + 0, + 2484, + 2486, + 2568, + 2566, + 0, + 2486, + 2488, + 2570, + 2568, + 0, + 2488, + 2490, + 2572, + 2570, + 0, + 2490, + 2492, + 2574, + 2572, + 0, + 2492, + 2494, + 2576, + 2574, + 0, + 2494, + 2496, + 2578, + 2576, + 0, + 2496, + 2497, + 2580, + 2578, + 0, + 2497, + 2500, + 2582, + 2580, + 0, + 2500, + 2501, + 2583, + 2582, + 0, + 2501, + 2512, + 2596, + 2583, + 0, + 2512, + 2518, + 2601, + 2596, + 0, + 2518, + 2524, + 2608, + 2601, + 0, + 2524, + 2530, + 2613, + 2608, + 0, + 2530, + 2532, + 2615, + 2613, + 0, + 2532, + 2534, + 2617, + 2615, + 0, + 2534, + 2536, + 2619, + 2617, + 0, + 2536, + 2538, + 2621, + 2619, + 0, + 2538, + 2540, + 2623, + 2621, + 0, + 2540, + 2542, + 2624, + 2623, + 0, + 2542, + 2541, + 2622, + 2624, + 0, + 2541, + 2539, + 2620, + 2622, + 0, + 2539, + 2537, + 2618, + 2620, + 0, + 2537, + 2535, + 2616, + 2618, + 0, + 2535, + 2533, + 2614, + 2616, + 0, + 2533, + 2531, + 2612, + 2614, + 0, + 2531, + 2525, + 2604, + 2612, + 0, + 2525, + 2519, + 2599, + 2604, + 0, + 2519, + 2513, + 2594, + 2599, + 0, + 2513, + 2509, + 2590, + 2594, + 0, + 2509, + 2505, + 2586, + 2590, + 0, + 2505, + 2502, + 2584, + 2586, + 0, + 2502, + 2503, + 2585, + 2584, + 0, + 2503, + 2506, + 2588, + 2585, + 0, + 2506, + 2508, + 2589, + 2588, + 0, + 2508, + 2511, + 2592, + 2589, + 0, + 2511, + 2515, + 2595, + 2592, + 0, + 2515, + 2517, + 2598, + 2595, + 0, + 2517, + 2521, + 2602, + 2598, + 0, + 2521, + 2523, + 2605, + 2602, + 0, + 2523, + 2527, + 2607, + 2605, + 0, + 2527, + 2528, + 2610, + 2607, + 0, + 2528, + 2529, + 2611, + 2610, + 0, + 2529, + 2526, + 2609, + 2611, + 0, + 2526, + 2522, + 2606, + 2609, + 0, + 2522, + 2520, + 2603, + 2606, + 0, + 2520, + 2516, + 2600, + 2603, + 0, + 2516, + 2514, + 2597, + 2600, + 0, + 2514, + 2510, + 2593, + 2597, + 0, + 2510, + 2507, + 2591, + 2593, + 0, + 2507, + 2504, + 2587, + 2591, + 0, + 2504, + 2499, + 2581, + 2587, + 0, + 2499, + 2498, + 2579, + 2581, + 0, + 2498, + 2495, + 2577, + 2579, + 0, + 2495, + 2493, + 2575, + 2577, + 0, + 2493, + 2491, + 2573, + 2575, + 0, + 2491, + 2489, + 2571, + 2573, + 0, + 2489, + 2487, + 2569, + 2571, + 0, + 2487, + 2485, + 2567, + 2569, + 0, + 2485, + 2483, + 2565, + 2567, + 0, + 2483, + 2481, + 2563, + 2565, + 0, + 2481, + 2479, + 2561, + 2563, + 0, + 2479, + 2477, + 2559, + 2561, + 0, + 2477, + 2475, + 2557, + 2559, + 0, + 2475, + 2473, + 2555, + 2557, + 0, + 2473, + 2471, + 2553, + 2555, + 0, + 2471, + 2469, + 2551, + 2553, + 0, + 2469, + 2467, + 2549, + 2551, + 0, + 2467, + 2466, + 2548, + 2549, + 0, + 2466, + 2463, + 2545, + 2548, + 0, + 2463, + 2462, + 2544, + 2545, + 0, + 2544, + 2543, + 2625, + 2626, + 0, + 2543, + 2546, + 2628, + 2625, + 0, + 2546, + 2547, + 2629, + 2628, + 0, + 2547, + 2550, + 2632, + 2629, + 0, + 2550, + 2552, + 2634, + 2632, + 0, + 2552, + 2554, + 2636, + 2634, + 0, + 2554, + 2556, + 2638, + 2636, + 0, + 2556, + 2558, + 2640, + 2638, + 0, + 2558, + 2560, + 2642, + 2640, + 0, + 2560, + 2562, + 2644, + 2642, + 0, + 2562, + 2564, + 2646, + 2644, + 0, + 2564, + 2566, + 2648, + 2646, + 0, + 2566, + 2568, + 2650, + 2648, + 0, + 2568, + 2570, + 2652, + 2650, + 0, + 2570, + 2572, + 2654, + 2652, + 0, + 2572, + 2574, + 2656, + 2654, + 0, + 2574, + 2576, + 2658, + 2656, + 0, + 2576, + 2578, + 2660, + 2658, + 0, + 2578, + 2580, + 2662, + 2660, + 0, + 2580, + 2582, + 2664, + 2662, + 0, + 2582, + 2583, + 2665, + 2664, + 0, + 2583, + 2596, + 2678, + 2665, + 0, + 2596, + 2601, + 2684, + 2678, + 0, + 2601, + 2608, + 2690, + 2684, + 0, + 2608, + 2613, + 2695, + 2690, + 0, + 2613, + 2615, + 2697, + 2695, + 0, + 2615, + 2617, + 2699, + 2697, + 0, + 2617, + 2619, + 2701, + 2699, + 0, + 2619, + 2621, + 2703, + 2701, + 0, + 2621, + 2623, + 2705, + 2703, + 0, + 2623, + 2624, + 2706, + 2705, + 0, + 2624, + 2622, + 2704, + 2706, + 0, + 2622, + 2620, + 2702, + 2704, + 0, + 2620, + 2618, + 2700, + 2702, + 0, + 2618, + 2616, + 2698, + 2700, + 0, + 2616, + 2614, + 2696, + 2698, + 0, + 2614, + 2612, + 2694, + 2696, + 0, + 2612, + 2604, + 2686, + 2694, + 0, + 2604, + 2599, + 2681, + 2686, + 0, + 2599, + 2594, + 2676, + 2681, + 0, + 2594, + 2590, + 2672, + 2676, + 0, + 2590, + 2586, + 2668, + 2672, + 0, + 2586, + 2584, + 2666, + 2668, + 0, + 2584, + 2585, + 2667, + 2666, + 0, + 2585, + 2588, + 2670, + 2667, + 0, + 2588, + 2589, + 2671, + 2670, + 0, + 2589, + 2592, + 2674, + 2671, + 0, + 2592, + 2595, + 2677, + 2674, + 0, + 2595, + 2598, + 2680, + 2677, + 0, + 2598, + 2602, + 2683, + 2680, + 0, + 2602, + 2605, + 2687, + 2683, + 0, + 2605, + 2607, + 2689, + 2687, + 0, + 2607, + 2610, + 2692, + 2689, + 0, + 2610, + 2611, + 2693, + 2692, + 0, + 2611, + 2609, + 2691, + 2693, + 0, + 2609, + 2606, + 2688, + 2691, + 0, + 2606, + 2603, + 2685, + 2688, + 0, + 2603, + 2600, + 2682, + 2685, + 0, + 2600, + 2597, + 2679, + 2682, + 0, + 2597, + 2593, + 2675, + 2679, + 0, + 2593, + 2591, + 2673, + 2675, + 0, + 2591, + 2587, + 2669, + 2673, + 0, + 2587, + 2581, + 2663, + 2669, + 0, + 2581, + 2579, + 2661, + 2663, + 0, + 2579, + 2577, + 2659, + 2661, + 0, + 2577, + 2575, + 2657, + 2659, + 0, + 2575, + 2573, + 2655, + 2657, + 0, + 2573, + 2571, + 2653, + 2655, + 0, + 2571, + 2569, + 2651, + 2653, + 0, + 2569, + 2567, + 2649, + 2651, + 0, + 2567, + 2565, + 2647, + 2649, + 0, + 2565, + 2563, + 2645, + 2647, + 0, + 2563, + 2561, + 2643, + 2645, + 0, + 2561, + 2559, + 2641, + 2643, + 0, + 2559, + 2557, + 2639, + 2641, + 0, + 2557, + 2555, + 2637, + 2639, + 0, + 2555, + 2553, + 2635, + 2637, + 0, + 2553, + 2551, + 2633, + 2635, + 0, + 2551, + 2549, + 2631, + 2633, + 0, + 2549, + 2548, + 2630, + 2631, + 0, + 2548, + 2545, + 2627, + 2630, + 0, + 2545, + 2544, + 2626, + 2627, + 0, + 2626, + 2625, + 2707, + 2708, + 0, + 2625, + 2628, + 2711, + 2707, + 0, + 2628, + 2629, + 2713, + 2711, + 0, + 2629, + 2632, + 2717, + 2713, + 0, + 2632, + 2634, + 2719, + 2717, + 0, + 2634, + 2636, + 2722, + 2719, + 0, + 2636, + 2638, + 2727, + 2722, + 0, + 2638, + 2640, + 2731, + 2727, + 0, + 2640, + 2642, + 2735, + 2731, + 0, + 2642, + 2644, + 2739, + 2735, + 0, + 2644, + 2646, + 2743, + 2739, + 0, + 2646, + 2648, + 2747, + 2743, + 0, + 2648, + 2650, + 2750, + 2747, + 0, + 2650, + 2652, + 2755, + 2750, + 0, + 2652, + 2654, + 2759, + 2755, + 0, + 2654, + 2656, + 2763, + 2759, + 0, + 2656, + 2658, + 2767, + 2763, + 0, + 2658, + 2660, + 2770, + 2767, + 0, + 2660, + 2662, + 2774, + 2770, + 0, + 2662, + 2664, + 2779, + 2774, + 0, + 2664, + 2665, + 2783, + 2779, + 0, + 2665, + 2678, + 2808, + 2783, + 0, + 2678, + 2684, + 2814, + 2808, + 0, + 2684, + 2690, + 2824, + 2814, + 0, + 2690, + 2695, + 2826, + 2824, + 0, + 2695, + 2697, + 2829, + 2826, + 0, + 2697, + 2699, + 2833, + 2829, + 0, + 2699, + 2701, + 2836, + 2833, + 0, + 2701, + 2703, + 2838, + 2836, + 0, + 2703, + 2705, + 2840, + 2838, + 0, + 2705, + 2706, + 2839, + 2840, + 0, + 2706, + 2704, + 2837, + 2839, + 0, + 2704, + 2702, + 2834, + 2837, + 0, + 2702, + 2700, + 2830, + 2834, + 0, + 2700, + 2698, + 2827, + 2830, + 0, + 2698, + 2696, + 2825, + 2827, + 0, + 2696, + 2694, + 2817, + 2825, + 0, + 2694, + 2686, + 2812, + 2817, + 0, + 2686, + 2681, + 2805, + 2812, + 0, + 2681, + 2676, + 2801, + 2805, + 0, + 2676, + 2672, + 2798, + 2801, + 0, + 2672, + 2668, + 2784, + 2798, + 0, + 2668, + 2666, + 2778, + 2784, + 0, + 2666, + 2667, + 2780, + 2778, + 0, + 2667, + 2670, + 2793, + 2780, + 0, + 2670, + 2671, + 2797, + 2793, + 0, + 2671, + 2674, + 2799, + 2797, + 0, + 2674, + 2677, + 2802, + 2799, + 0, + 2677, + 2680, + 2806, + 2802, + 0, + 2680, + 2683, + 2809, + 2806, + 0, + 2683, + 2687, + 2813, + 2809, + 0, + 2687, + 2689, + 2816, + 2813, + 0, + 2689, + 2692, + 2819, + 2816, + 0, + 2692, + 2693, + 2822, + 2819, + 0, + 2693, + 2691, + 2821, + 2822, + 0, + 2691, + 2688, + 2818, + 2821, + 0, + 2688, + 2685, + 2815, + 2818, + 0, + 2685, + 2682, + 2811, + 2815, + 0, + 2682, + 2679, + 2807, + 2811, + 0, + 2679, + 2675, + 2804, + 2807, + 0, + 2675, + 2673, + 2800, + 2804, + 0, + 2673, + 2669, + 2789, + 2800, + 0, + 2669, + 2663, + 2776, + 2789, + 0, + 2663, + 2661, + 2772, + 2776, + 0, + 2661, + 2659, + 2769, + 2772, + 0, + 2659, + 2657, + 2765, + 2769, + 0, + 2657, + 2655, + 2761, + 2765, + 0, + 2655, + 2653, + 2757, + 2761, + 0, + 2653, + 2651, + 2752, + 2757, + 0, + 2651, + 2649, + 2749, + 2752, + 0, + 2649, + 2647, + 2745, + 2749, + 0, + 2647, + 2645, + 2741, + 2745, + 0, + 2645, + 2643, + 2738, + 2741, + 0, + 2643, + 2641, + 2733, + 2738, + 0, + 2641, + 2639, + 2729, + 2733, + 0, + 2639, + 2637, + 2723, + 2729, + 0, + 2637, + 2635, + 2720, + 2723, + 0, + 2635, + 2633, + 2718, + 2720, + 0, + 2633, + 2631, + 2716, + 2718, + 0, + 2631, + 2630, + 2714, + 2716, + 0, + 2630, + 2627, + 2709, + 2714, + 0, + 2627, + 2626, + 2708, + 2709, + 0, + 2708, + 2707, + 2710, + 2712, + 0, + 2707, + 2711, + 2721, + 2710, + 0, + 2711, + 2713, + 2724, + 2721, + 0, + 2713, + 2717, + 2728, + 2724, + 0, + 2717, + 2719, + 2732, + 2728, + 0, + 2719, + 2722, + 2736, + 2732, + 0, + 2722, + 2727, + 2740, + 2736, + 0, + 2727, + 2731, + 2744, + 2740, + 0, + 2731, + 2735, + 2748, + 2744, + 0, + 2735, + 2739, + 2753, + 2748, + 0, + 2739, + 2743, + 2756, + 2753, + 0, + 2743, + 2747, + 2760, + 2756, + 0, + 2747, + 2750, + 2764, + 2760, + 0, + 2750, + 2755, + 2768, + 2764, + 0, + 2755, + 2759, + 2773, + 2768, + 0, + 2759, + 2763, + 2777, + 2773, + 0, + 2763, + 2767, + 2782, + 2777, + 0, + 2767, + 2770, + 2786, + 2782, + 0, + 2770, + 2774, + 2788, + 2786, + 0, + 2774, + 2779, + 2792, + 2788, + 0, + 2779, + 2783, + 2795, + 2792, + 0, + 2783, + 2808, + 2845, + 2795, + 0, + 2808, + 2814, + 2850, + 2845, + 0, + 2814, + 2824, + 2858, + 2850, + 0, + 2824, + 2826, + 2860, + 2858, + 0, + 2826, + 2829, + 2862, + 2860, + 0, + 2829, + 2833, + 2864, + 2862, + 0, + 2833, + 2836, + 2866, + 2864, + 0, + 2836, + 2838, + 2868, + 2866, + 0, + 2838, + 2840, + 2870, + 2868, + 0, + 2840, + 2839, + 2869, + 2870, + 0, + 2839, + 2837, + 2867, + 2869, + 0, + 2837, + 2834, + 2865, + 2867, + 0, + 2834, + 2830, + 2863, + 2865, + 0, + 2830, + 2827, + 2861, + 2863, + 0, + 2827, + 2825, + 2859, + 2861, + 0, + 2825, + 2817, + 2852, + 2859, + 0, + 2817, + 2812, + 2848, + 2852, + 0, + 2812, + 2805, + 2842, + 2848, + 0, + 2805, + 2801, + 2832, + 2842, + 0, + 2801, + 2798, + 2823, + 2832, + 0, + 2798, + 2784, + 2796, + 2823, + 0, + 2784, + 2778, + 2791, + 2796, + 0, + 2778, + 2780, + 2794, + 2791, + 0, + 2780, + 2793, + 2810, + 2794, + 0, + 2793, + 2797, + 2820, + 2810, + 0, + 2797, + 2799, + 2828, + 2820, + 0, + 2799, + 2802, + 2835, + 2828, + 0, + 2802, + 2806, + 2843, + 2835, + 0, + 2806, + 2809, + 2846, + 2843, + 0, + 2809, + 2813, + 2849, + 2846, + 0, + 2813, + 2816, + 2853, + 2849, + 0, + 2816, + 2819, + 2855, + 2853, + 0, + 2819, + 2822, + 2857, + 2855, + 0, + 2822, + 2821, + 2856, + 2857, + 0, + 2821, + 2818, + 2854, + 2856, + 0, + 2818, + 2815, + 2851, + 2854, + 0, + 2815, + 2811, + 2847, + 2851, + 0, + 2811, + 2807, + 2844, + 2847, + 0, + 2807, + 2804, + 2841, + 2844, + 0, + 2804, + 2800, + 2831, + 2841, + 0, + 2800, + 2789, + 2803, + 2831, + 0, + 2789, + 2776, + 2790, + 2803, + 0, + 2776, + 2772, + 2787, + 2790, + 0, + 2772, + 2769, + 2785, + 2787, + 0, + 2769, + 2765, + 2781, + 2785, + 0, + 2765, + 2761, + 2775, + 2781, + 0, + 2761, + 2757, + 2771, + 2775, + 0, + 2757, + 2752, + 2766, + 2771, + 0, + 2752, + 2749, + 2762, + 2766, + 0, + 2749, + 2745, + 2758, + 2762, + 0, + 2745, + 2741, + 2754, + 2758, + 0, + 2741, + 2738, + 2751, + 2754, + 0, + 2738, + 2733, + 2746, + 2751, + 0, + 2733, + 2729, + 2742, + 2746, + 0, + 2729, + 2723, + 2737, + 2742, + 0, + 2723, + 2720, + 2734, + 2737, + 0, + 2720, + 2718, + 2730, + 2734, + 0, + 2718, + 2716, + 2726, + 2730, + 0, + 2716, + 2714, + 2725, + 2726, + 0, + 2714, + 2709, + 2715, + 2725, + 0, + 2709, + 2708, + 2712, + 2715, + 0, + 2712, + 2710, + 2871, + 2872, + 0, + 2710, + 2721, + 2874, + 2871, + 0, + 2721, + 2724, + 2876, + 2874, + 0, + 2724, + 2728, + 2878, + 2876, + 0, + 2728, + 2732, + 2880, + 2878, + 0, + 2732, + 2736, + 2882, + 2880, + 0, + 2736, + 2740, + 2884, + 2882, + 0, + 2740, + 2744, + 2886, + 2884, + 0, + 2744, + 2748, + 2888, + 2886, + 0, + 2748, + 2753, + 2890, + 2888, + 0, + 2753, + 2756, + 2892, + 2890, + 0, + 2756, + 2760, + 2894, + 2892, + 0, + 2760, + 2764, + 2896, + 2894, + 0, + 2764, + 2768, + 2898, + 2896, + 0, + 2768, + 2773, + 2900, + 2898, + 0, + 2773, + 2777, + 2902, + 2900, + 0, + 2777, + 2782, + 2904, + 2902, + 0, + 2782, + 2786, + 2906, + 2904, + 0, + 2786, + 2788, + 2909, + 2906, + 0, + 2788, + 2792, + 2913, + 2909, + 0, + 2792, + 2795, + 2914, + 2913, + 0, + 2795, + 2845, + 2929, + 2914, + 0, + 2845, + 2850, + 2935, + 2929, + 0, + 2850, + 2858, + 2941, + 2935, + 0, + 2858, + 2860, + 2943, + 2941, + 0, + 2860, + 2862, + 2945, + 2943, + 0, + 2862, + 2864, + 2947, + 2945, + 0, + 2864, + 2866, + 2949, + 2947, + 0, + 2866, + 2868, + 2951, + 2949, + 0, + 2868, + 2870, + 2952, + 2951, + 0, + 2870, + 2869, + 2950, + 2952, + 0, + 2869, + 2867, + 2948, + 2950, + 0, + 2867, + 2865, + 2946, + 2948, + 0, + 2865, + 2863, + 2944, + 2946, + 0, + 2863, + 2861, + 2942, + 2944, + 0, + 2861, + 2859, + 2940, + 2942, + 0, + 2859, + 2852, + 2932, + 2940, + 0, + 2852, + 2848, + 2927, + 2932, + 0, + 2848, + 2842, + 2923, + 2927, + 0, + 2842, + 2832, + 2920, + 2923, + 0, + 2832, + 2823, + 2918, + 2920, + 0, + 2823, + 2796, + 2912, + 2918, + 0, + 2796, + 2791, + 2907, + 2912, + 0, + 2791, + 2794, + 2910, + 2907, + 0, + 2794, + 2810, + 2916, + 2910, + 0, + 2810, + 2820, + 2917, + 2916, + 0, + 2820, + 2828, + 2919, + 2917, + 0, + 2828, + 2835, + 2921, + 2919, + 0, + 2835, + 2843, + 2924, + 2921, + 0, + 2843, + 2846, + 2926, + 2924, + 0, + 2846, + 2849, + 2930, + 2926, + 0, + 2849, + 2853, + 2933, + 2930, + 0, + 2853, + 2855, + 2936, + 2933, + 0, + 2855, + 2857, + 2938, + 2936, + 0, + 2857, + 2856, + 2939, + 2938, + 0, + 2856, + 2854, + 2937, + 2939, + 0, + 2854, + 2851, + 2934, + 2937, + 0, + 2851, + 2847, + 2931, + 2934, + 0, + 2847, + 2844, + 2928, + 2931, + 0, + 2844, + 2841, + 2925, + 2928, + 0, + 2841, + 2831, + 2922, + 2925, + 0, + 2831, + 2803, + 2915, + 2922, + 0, + 2803, + 2790, + 2911, + 2915, + 0, + 2790, + 2787, + 2908, + 2911, + 0, + 2787, + 2785, + 2905, + 2908, + 0, + 2785, + 2781, + 2903, + 2905, + 0, + 2781, + 2775, + 2901, + 2903, + 0, + 2775, + 2771, + 2899, + 2901, + 0, + 2771, + 2766, + 2897, + 2899, + 0, + 2766, + 2762, + 2895, + 2897, + 0, + 2762, + 2758, + 2893, + 2895, + 0, + 2758, + 2754, + 2891, + 2893, + 0, + 2754, + 2751, + 2889, + 2891, + 0, + 2751, + 2746, + 2887, + 2889, + 0, + 2746, + 2742, + 2885, + 2887, + 0, + 2742, + 2737, + 2883, + 2885, + 0, + 2737, + 2734, + 2881, + 2883, + 0, + 2734, + 2730, + 2879, + 2881, + 0, + 2730, + 2726, + 2877, + 2879, + 0, + 2726, + 2725, + 2875, + 2877, + 0, + 2725, + 2715, + 2873, + 2875, + 0, + 2715, + 2712, + 2872, + 2873, + 0, + 2872, + 2871, + 2953, + 2954, + 0, + 2871, + 2874, + 2956, + 2953, + 0, + 2874, + 2876, + 2958, + 2956, + 0, + 2876, + 2878, + 2960, + 2958, + 0, + 2878, + 2880, + 2962, + 2960, + 0, + 2880, + 2882, + 2964, + 2962, + 0, + 2882, + 2884, + 2966, + 2964, + 0, + 2884, + 2886, + 2968, + 2966, + 0, + 2886, + 2888, + 2970, + 2968, + 0, + 2888, + 2890, + 2972, + 2970, + 0, + 2890, + 2892, + 2974, + 2972, + 0, + 2892, + 2894, + 2976, + 2974, + 0, + 2894, + 2896, + 2978, + 2976, + 0, + 2896, + 2898, + 2980, + 2978, + 0, + 2898, + 2900, + 2982, + 2980, + 0, + 2900, + 2902, + 2984, + 2982, + 0, + 2902, + 2904, + 2986, + 2984, + 0, + 2904, + 2906, + 2988, + 2986, + 0, + 2906, + 2909, + 2992, + 2988, + 0, + 2909, + 2913, + 2995, + 2992, + 0, + 2913, + 2914, + 2996, + 2995, + 0, + 2914, + 2929, + 3011, + 2996, + 0, + 2929, + 2935, + 3018, + 3011, + 0, + 2935, + 2941, + 3023, + 3018, + 0, + 2941, + 2943, + 3025, + 3023, + 0, + 2943, + 2945, + 3027, + 3025, + 0, + 2945, + 2947, + 3029, + 3027, + 0, + 2947, + 2949, + 3031, + 3029, + 0, + 2949, + 2951, + 3033, + 3031, + 0, + 2951, + 2952, + 3034, + 3033, + 0, + 2952, + 2950, + 3032, + 3034, + 0, + 2950, + 2948, + 3030, + 3032, + 0, + 2948, + 2946, + 3028, + 3030, + 0, + 2946, + 2944, + 3026, + 3028, + 0, + 2944, + 2942, + 3024, + 3026, + 0, + 2942, + 2940, + 3021, + 3024, + 0, + 2940, + 2932, + 3014, + 3021, + 0, + 2932, + 2927, + 3009, + 3014, + 0, + 2927, + 2923, + 3005, + 3009, + 0, + 2923, + 2920, + 3002, + 3005, + 0, + 2920, + 2918, + 3000, + 3002, + 0, + 2918, + 2912, + 2994, + 3000, + 0, + 2912, + 2907, + 2989, + 2994, + 0, + 2907, + 2910, + 2991, + 2989, + 0, + 2910, + 2916, + 2998, + 2991, + 0, + 2916, + 2917, + 2999, + 2998, + 0, + 2917, + 2919, + 3001, + 2999, + 0, + 2919, + 2921, + 3003, + 3001, + 0, + 2921, + 2924, + 3006, + 3003, + 0, + 2924, + 2926, + 3008, + 3006, + 0, + 2926, + 2930, + 3012, + 3008, + 0, + 2930, + 2933, + 3015, + 3012, + 0, + 2933, + 2936, + 3017, + 3015, + 0, + 2936, + 2938, + 3020, + 3017, + 0, + 2938, + 2939, + 3022, + 3020, + 0, + 2939, + 2937, + 3019, + 3022, + 0, + 2937, + 2934, + 3016, + 3019, + 0, + 2934, + 2931, + 3013, + 3016, + 0, + 2931, + 2928, + 3010, + 3013, + 0, + 2928, + 2925, + 3007, + 3010, + 0, + 2925, + 2922, + 3004, + 3007, + 0, + 2922, + 2915, + 2997, + 3004, + 0, + 2915, + 2911, + 2993, + 2997, + 0, + 2911, + 2908, + 2990, + 2993, + 0, + 2908, + 2905, + 2987, + 2990, + 0, + 2905, + 2903, + 2985, + 2987, + 0, + 2903, + 2901, + 2983, + 2985, + 0, + 2901, + 2899, + 2981, + 2983, + 0, + 2899, + 2897, + 2979, + 2981, + 0, + 2897, + 2895, + 2977, + 2979, + 0, + 2895, + 2893, + 2975, + 2977, + 0, + 2893, + 2891, + 2973, + 2975, + 0, + 2891, + 2889, + 2971, + 2973, + 0, + 2889, + 2887, + 2969, + 2971, + 0, + 2887, + 2885, + 2967, + 2969, + 0, + 2885, + 2883, + 2965, + 2967, + 0, + 2883, + 2881, + 2963, + 2965, + 0, + 2881, + 2879, + 2961, + 2963, + 0, + 2879, + 2877, + 2959, + 2961, + 0, + 2877, + 2875, + 2957, + 2959, + 0, + 2875, + 2873, + 2955, + 2957, + 0, + 2873, + 2872, + 2954, + 2955, + 0, + 2954, + 2953, + 3035, + 3036, + 0, + 2953, + 2956, + 3038, + 3035, + 0, + 2956, + 2958, + 3040, + 3038, + 0, + 2958, + 2960, + 3042, + 3040, + 0, + 2960, + 2962, + 3045, + 3042, + 0, + 2962, + 2964, + 3046, + 3045, + 0, + 2964, + 2966, + 3048, + 3046, + 0, + 2966, + 2968, + 3050, + 3048, + 0, + 2968, + 2970, + 3052, + 3050, + 0, + 2970, + 2972, + 3054, + 3052, + 0, + 2972, + 2974, + 3056, + 3054, + 0, + 2974, + 2976, + 3058, + 3056, + 0, + 2976, + 2978, + 3060, + 3058, + 0, + 2978, + 2980, + 3062, + 3060, + 0, + 2980, + 2982, + 3064, + 3062, + 0, + 2982, + 2984, + 3066, + 3064, + 0, + 2984, + 2986, + 3068, + 3066, + 0, + 2986, + 2988, + 3072, + 3068, + 0, + 2988, + 2992, + 3075, + 3072, + 0, + 2992, + 2995, + 3077, + 3075, + 0, + 2995, + 2996, + 3078, + 3077, + 0, + 2996, + 3011, + 3095, + 3078, + 0, + 3011, + 3018, + 3104, + 3095, + 0, + 3018, + 3023, + 3106, + 3104, + 0, + 3023, + 3025, + 3108, + 3106, + 0, + 3025, + 3027, + 3110, + 3108, + 0, + 3027, + 3029, + 3112, + 3110, + 0, + 3029, + 3031, + 3114, + 3112, + 0, + 3031, + 3033, + 3116, + 3114, + 0, + 3033, + 3034, + 3115, + 3116, + 0, + 3034, + 3032, + 3113, + 3115, + 0, + 3032, + 3030, + 3111, + 3113, + 0, + 3030, + 3028, + 3109, + 3111, + 0, + 3028, + 3026, + 3107, + 3109, + 0, + 3026, + 3024, + 3105, + 3107, + 0, + 3024, + 3021, + 3098, + 3105, + 0, + 3021, + 3014, + 3094, + 3098, + 0, + 3014, + 3009, + 3089, + 3094, + 0, + 3009, + 3005, + 3086, + 3089, + 0, + 3005, + 3002, + 3084, + 3086, + 0, + 3002, + 3000, + 3082, + 3084, + 0, + 3000, + 2994, + 3073, + 3082, + 0, + 2994, + 2989, + 3069, + 3073, + 0, + 2989, + 2991, + 3070, + 3069, + 0, + 2991, + 2998, + 3079, + 3070, + 0, + 2998, + 2999, + 3081, + 3079, + 0, + 2999, + 3001, + 3083, + 3081, + 0, + 3001, + 3003, + 3085, + 3083, + 0, + 3003, + 3006, + 3087, + 3085, + 0, + 3006, + 3008, + 3090, + 3087, + 0, + 3008, + 3012, + 3093, + 3090, + 0, + 3012, + 3015, + 3097, + 3093, + 0, + 3015, + 3017, + 3099, + 3097, + 0, + 3017, + 3020, + 3101, + 3099, + 0, + 3020, + 3022, + 3103, + 3101, + 0, + 3022, + 3019, + 3102, + 3103, + 0, + 3019, + 3016, + 3100, + 3102, + 0, + 3016, + 3013, + 3096, + 3100, + 0, + 3013, + 3010, + 3092, + 3096, + 0, + 3010, + 3007, + 3091, + 3092, + 0, + 3007, + 3004, + 3088, + 3091, + 0, + 3004, + 2997, + 3080, + 3088, + 0, + 2997, + 2993, + 3076, + 3080, + 0, + 2993, + 2990, + 3074, + 3076, + 0, + 2990, + 2987, + 3071, + 3074, + 0, + 2987, + 2985, + 3067, + 3071, + 0, + 2985, + 2983, + 3065, + 3067, + 0, + 2983, + 2981, + 3063, + 3065, + 0, + 2981, + 2979, + 3061, + 3063, + 0, + 2979, + 2977, + 3059, + 3061, + 0, + 2977, + 2975, + 3057, + 3059, + 0, + 2975, + 2973, + 3055, + 3057, + 0, + 2973, + 2971, + 3053, + 3055, + 0, + 2971, + 2969, + 3051, + 3053, + 0, + 2969, + 2967, + 3049, + 3051, + 0, + 2967, + 2965, + 3047, + 3049, + 0, + 2965, + 2963, + 3044, + 3047, + 0, + 2963, + 2961, + 3043, + 3044, + 0, + 2961, + 2959, + 3041, + 3043, + 0, + 2959, + 2957, + 3039, + 3041, + 0, + 2957, + 2955, + 3037, + 3039, + 0, + 2955, + 2954, + 3036, + 3037, + 0, + 3036, + 3035, + 3117, + 3118, + 0, + 3035, + 3038, + 3120, + 3117, + 0, + 3038, + 3040, + 3122, + 3120, + 0, + 3040, + 3042, + 3124, + 3122, + 0, + 3042, + 3045, + 3127, + 3124, + 0, + 3045, + 3046, + 3128, + 3127, + 0, + 3046, + 3048, + 3130, + 3128, + 0, + 3048, + 3050, + 3132, + 3130, + 0, + 3050, + 3052, + 3134, + 3132, + 0, + 3052, + 3054, + 3136, + 3134, + 0, + 3054, + 3056, + 3138, + 3136, + 0, + 3056, + 3058, + 3140, + 3138, + 0, + 3058, + 3060, + 3142, + 3140, + 0, + 3060, + 3062, + 3144, + 3142, + 0, + 3062, + 3064, + 3146, + 3144, + 0, + 3064, + 3066, + 3148, + 3146, + 0, + 3066, + 3068, + 3151, + 3148, + 0, + 3068, + 3072, + 3155, + 3151, + 0, + 3072, + 3075, + 3157, + 3155, + 0, + 3075, + 3077, + 3159, + 3157, + 0, + 3077, + 3078, + 3160, + 3159, + 0, + 3078, + 3095, + 3178, + 3160, + 0, + 3095, + 3104, + 3187, + 3178, + 0, + 3104, + 3106, + 3189, + 3187, + 0, + 3106, + 3108, + 3191, + 3189, + 0, + 3108, + 3110, + 3193, + 3191, + 0, + 3110, + 3112, + 3195, + 3193, + 0, + 3112, + 3114, + 3197, + 3195, + 0, + 3114, + 3116, + 3198, + 3197, + 0, + 3116, + 3115, + 3196, + 3198, + 0, + 3115, + 3113, + 3194, + 3196, + 0, + 3113, + 3111, + 3192, + 3194, + 0, + 3111, + 3109, + 3190, + 3192, + 0, + 3109, + 3107, + 3188, + 3190, + 0, + 3107, + 3105, + 3186, + 3188, + 0, + 3105, + 3098, + 3180, + 3186, + 0, + 3098, + 3094, + 3174, + 3180, + 0, + 3094, + 3089, + 3171, + 3174, + 0, + 3089, + 3086, + 3168, + 3171, + 0, + 3086, + 3084, + 3166, + 3168, + 0, + 3084, + 3082, + 3164, + 3166, + 0, + 3082, + 3073, + 3154, + 3164, + 0, + 3073, + 3069, + 3150, + 3154, + 0, + 3069, + 3070, + 3152, + 3150, + 0, + 3070, + 3079, + 3161, + 3152, + 0, + 3079, + 3081, + 3163, + 3161, + 0, + 3081, + 3083, + 3165, + 3163, + 0, + 3083, + 3085, + 3167, + 3165, + 0, + 3085, + 3087, + 3169, + 3167, + 0, + 3087, + 3090, + 3172, + 3169, + 0, + 3090, + 3093, + 3175, + 3172, + 0, + 3093, + 3097, + 3177, + 3175, + 0, + 3097, + 3099, + 3181, + 3177, + 0, + 3099, + 3101, + 3183, + 3181, + 0, + 3101, + 3103, + 3185, + 3183, + 0, + 3103, + 3102, + 3184, + 3185, + 0, + 3102, + 3100, + 3182, + 3184, + 0, + 3100, + 3096, + 3179, + 3182, + 0, + 3096, + 3092, + 3176, + 3179, + 0, + 3092, + 3091, + 3173, + 3176, + 0, + 3091, + 3088, + 3170, + 3173, + 0, + 3088, + 3080, + 3162, + 3170, + 0, + 3080, + 3076, + 3158, + 3162, + 0, + 3076, + 3074, + 3156, + 3158, + 0, + 3074, + 3071, + 3153, + 3156, + 0, + 3071, + 3067, + 3149, + 3153, + 0, + 3067, + 3065, + 3147, + 3149, + 0, + 3065, + 3063, + 3145, + 3147, + 0, + 3063, + 3061, + 3143, + 3145, + 0, + 3061, + 3059, + 3141, + 3143, + 0, + 3059, + 3057, + 3139, + 3141, + 0, + 3057, + 3055, + 3137, + 3139, + 0, + 3055, + 3053, + 3135, + 3137, + 0, + 3053, + 3051, + 3133, + 3135, + 0, + 3051, + 3049, + 3131, + 3133, + 0, + 3049, + 3047, + 3129, + 3131, + 0, + 3047, + 3044, + 3126, + 3129, + 0, + 3044, + 3043, + 3125, + 3126, + 0, + 3043, + 3041, + 3123, + 3125, + 0, + 3041, + 3039, + 3121, + 3123, + 0, + 3039, + 3037, + 3119, + 3121, + 0, + 3037, + 3036, + 3118, + 3119, + 0, + 3118, + 3117, + 3199, + 3200, + 0, + 3117, + 3120, + 3202, + 3199, + 0, + 3120, + 3122, + 3204, + 3202, + 0, + 3122, + 3124, + 3206, + 3204, + 0, + 3124, + 3127, + 3209, + 3206, + 0, + 3127, + 3128, + 3210, + 3209, + 0, + 3128, + 3130, + 3212, + 3210, + 0, + 3130, + 3132, + 3214, + 3212, + 0, + 3132, + 3134, + 3216, + 3214, + 0, + 3134, + 3136, + 3218, + 3216, + 0, + 3136, + 3138, + 3220, + 3218, + 0, + 3138, + 3140, + 3222, + 3220, + 0, + 3140, + 3142, + 3224, + 3222, + 0, + 3142, + 3144, + 3226, + 3224, + 0, + 3144, + 3146, + 3228, + 3226, + 0, + 3146, + 3148, + 3231, + 3228, + 0, + 3148, + 3151, + 3235, + 3231, + 0, + 3151, + 3155, + 3237, + 3235, + 0, + 3155, + 3157, + 3239, + 3237, + 0, + 3157, + 3159, + 3241, + 3239, + 0, + 3159, + 3160, + 3243, + 3241, + 0, + 3160, + 3178, + 3263, + 3243, + 0, + 3178, + 3187, + 3269, + 3263, + 0, + 3187, + 3189, + 3271, + 3269, + 0, + 3189, + 3191, + 3273, + 3271, + 0, + 3191, + 3193, + 3275, + 3273, + 0, + 3193, + 3195, + 3277, + 3275, + 0, + 3195, + 3197, + 3279, + 3277, + 0, + 3197, + 3198, + 3280, + 3279, + 0, + 3198, + 3196, + 3278, + 3280, + 0, + 3196, + 3194, + 3276, + 3278, + 0, + 3194, + 3192, + 3274, + 3276, + 0, + 3192, + 3190, + 3272, + 3274, + 0, + 3190, + 3188, + 3270, + 3272, + 0, + 3188, + 3186, + 3267, + 3270, + 0, + 3186, + 3180, + 3260, + 3267, + 0, + 3180, + 3174, + 3256, + 3260, + 0, + 3174, + 3171, + 3252, + 3256, + 0, + 3171, + 3168, + 3250, + 3252, + 0, + 3168, + 3166, + 3248, + 3250, + 0, + 3166, + 3164, + 3244, + 3248, + 0, + 3164, + 3154, + 3234, + 3244, + 0, + 3154, + 3150, + 3230, + 3234, + 0, + 3150, + 3152, + 3232, + 3230, + 0, + 3152, + 3161, + 3242, + 3232, + 0, + 3161, + 3163, + 3245, + 3242, + 0, + 3163, + 3165, + 3247, + 3245, + 0, + 3165, + 3167, + 3249, + 3247, + 0, + 3167, + 3169, + 3251, + 3249, + 0, + 3169, + 3172, + 3254, + 3251, + 0, + 3172, + 3175, + 3257, + 3254, + 0, + 3175, + 3177, + 3259, + 3257, + 0, + 3177, + 3181, + 3262, + 3259, + 0, + 3181, + 3183, + 3264, + 3262, + 0, + 3183, + 3185, + 3266, + 3264, + 0, + 3185, + 3184, + 3268, + 3266, + 0, + 3184, + 3182, + 3265, + 3268, + 0, + 3182, + 3179, + 3261, + 3265, + 0, + 3179, + 3176, + 3258, + 3261, + 0, + 3176, + 3173, + 3255, + 3258, + 0, + 3173, + 3170, + 3253, + 3255, + 0, + 3170, + 3162, + 3246, + 3253, + 0, + 3162, + 3158, + 3240, + 3246, + 0, + 3158, + 3156, + 3238, + 3240, + 0, + 3156, + 3153, + 3236, + 3238, + 0, + 3153, + 3149, + 3233, + 3236, + 0, + 3149, + 3147, + 3229, + 3233, + 0, + 3147, + 3145, + 3227, + 3229, + 0, + 3145, + 3143, + 3225, + 3227, + 0, + 3143, + 3141, + 3223, + 3225, + 0, + 3141, + 3139, + 3221, + 3223, + 0, + 3139, + 3137, + 3219, + 3221, + 0, + 3137, + 3135, + 3217, + 3219, + 0, + 3135, + 3133, + 3215, + 3217, + 0, + 3133, + 3131, + 3213, + 3215, + 0, + 3131, + 3129, + 3211, + 3213, + 0, + 3129, + 3126, + 3208, + 3211, + 0, + 3126, + 3125, + 3207, + 3208, + 0, + 3125, + 3123, + 3205, + 3207, + 0, + 3123, + 3121, + 3203, + 3205, + 0, + 3121, + 3119, + 3201, + 3203, + 0, + 3119, + 3118, + 3200, + 3201, + 0, + 3, + 7, + 8, + 10, + 12, + 14, + 16, + 18, + 20, + 22, + 24, + 25, + 27, + 30, + 32, + 34, + 36, + 38, + 40, + 42, + 43, + 45, + 46, + 50, + 52, + 55, + 58, + 61, + 63, + 66, + 68, + 70, + 67, + 65, + 62, + 59, + 57, + 49, + 48, + 53, + 69, + 72, + 75, + 77, + 79, + 81, + 82, + 80, + 78, + 76, + 74, + 73, + 71, + 64, + 60, + 56, + 54, + 51, + 47, + 44, + 41, + 39, + 37, + 35, + 33, + 31, + 29, + 28, + 26, + 23, + 21, + 19, + 17, + 15, + 13, + 11, + 9, + 6, + 5, + 4, + 1, + 2, + 0, + 3200, + 3199, + 3202, + 3204, + 3206, + 3209, + 3210, + 3212, + 3214, + 3216, + 3218, + 3220, + 3222, + 3224, + 3226, + 3228, + 3231, + 3235, + 3237, + 3239, + 3241, + 3243, + 3263, + 3269, + 3271, + 3273, + 3275, + 3277, + 3279, + 3280, + 3278, + 3276, + 3274, + 3272, + 3270, + 3267, + 3260, + 3256, + 3252, + 3250, + 3248, + 3244, + 3234, + 3230, + 3232, + 3242, + 3245, + 3247, + 3249, + 3251, + 3254, + 3257, + 3259, + 3262, + 3264, + 3266, + 3268, + 3265, + 3261, + 3258, + 3255, + 3253, + 3246, + 3240, + 3238, + 3236, + 3233, + 3229, + 3227, + 3225, + 3223, + 3221, + 3219, + 3217, + 3215, + 3213, + 3211, + 3208, + 3207, + 3205, + 3203, + 3201, + 0, + 3321, + 3324, + 3406, + 3403, + 0, + 3324, + 3330, + 3412, + 3406, + 0, + 3330, + 3334, + 3416, + 3412, + 0, + 3334, + 3340, + 3422, + 3416, + 0, + 3340, + 3350, + 3431, + 3422, + 0, + 3350, + 3352, + 3434, + 3431, + 0, + 3352, + 3354, + 3436, + 3434, + 0, + 3354, + 3356, + 3438, + 3436, + 0, + 3356, + 3358, + 3440, + 3438, + 0, + 3358, + 3360, + 3442, + 3440, + 0, + 3360, + 3362, + 3444, + 3442, + 0, + 3362, + 3361, + 3443, + 3444, + 0, + 3361, + 3359, + 3441, + 3443, + 0, + 3359, + 3357, + 3439, + 3441, + 0, + 3357, + 3355, + 3437, + 3439, + 0, + 3355, + 3353, + 3435, + 3437, + 0, + 3353, + 3351, + 3433, + 3435, + 0, + 3351, + 3346, + 3429, + 3433, + 0, + 3346, + 3341, + 3423, + 3429, + 0, + 3341, + 3336, + 3418, + 3423, + 0, + 3336, + 3331, + 3413, + 3418, + 0, + 3331, + 3320, + 3402, + 3413, + 0, + 3320, + 3319, + 3401, + 3402, + 0, + 3319, + 3316, + 3398, + 3401, + 0, + 3316, + 3314, + 3396, + 3398, + 0, + 3314, + 3313, + 3395, + 3396, + 0, + 3313, + 3311, + 3393, + 3395, + 0, + 3311, + 3309, + 3391, + 3393, + 0, + 3309, + 3307, + 3389, + 3391, + 0, + 3307, + 3305, + 3387, + 3389, + 0, + 3305, + 3303, + 3385, + 3387, + 0, + 3303, + 3301, + 3383, + 3385, + 0, + 3301, + 3299, + 3381, + 3383, + 0, + 3299, + 3297, + 3379, + 3381, + 0, + 3297, + 3295, + 3377, + 3379, + 0, + 3295, + 3293, + 3375, + 3377, + 0, + 3293, + 3292, + 3374, + 3375, + 0, + 3292, + 3290, + 3372, + 3374, + 0, + 3290, + 3287, + 3369, + 3372, + 0, + 3287, + 3285, + 3367, + 3369, + 0, + 3285, + 3284, + 3366, + 3367, + 0, + 3284, + 3281, + 3363, + 3366, + 0, + 3281, + 3282, + 3364, + 3363, + 0, + 3282, + 3283, + 3365, + 3364, + 0, + 3283, + 3286, + 3368, + 3365, + 0, + 3286, + 3288, + 3370, + 3368, + 0, + 3288, + 3289, + 3371, + 3370, + 0, + 3289, + 3291, + 3373, + 3371, + 0, + 3291, + 3294, + 3376, + 3373, + 0, + 3294, + 3296, + 3378, + 3376, + 0, + 3296, + 3298, + 3380, + 3378, + 0, + 3298, + 3300, + 3382, + 3380, + 0, + 3300, + 3302, + 3384, + 3382, + 0, + 3302, + 3304, + 3386, + 3384, + 0, + 3304, + 3306, + 3388, + 3386, + 0, + 3306, + 3308, + 3390, + 3388, + 0, + 3308, + 3310, + 3392, + 3390, + 0, + 3310, + 3312, + 3394, + 3392, + 0, + 3312, + 3315, + 3397, + 3394, + 0, + 3315, + 3317, + 3399, + 3397, + 0, + 3317, + 3318, + 3400, + 3399, + 0, + 3318, + 3322, + 3404, + 3400, + 0, + 3322, + 3326, + 3408, + 3404, + 0, + 3326, + 3328, + 3410, + 3408, + 0, + 3328, + 3332, + 3414, + 3410, + 0, + 3332, + 3335, + 3417, + 3414, + 0, + 3335, + 3338, + 3420, + 3417, + 0, + 3338, + 3342, + 3424, + 3420, + 0, + 3342, + 3344, + 3426, + 3424, + 0, + 3344, + 3347, + 3428, + 3426, + 0, + 3347, + 3349, + 3432, + 3428, + 0, + 3349, + 3348, + 3430, + 3432, + 0, + 3348, + 3345, + 3427, + 3430, + 0, + 3345, + 3343, + 3425, + 3427, + 0, + 3343, + 3339, + 3421, + 3425, + 0, + 3339, + 3337, + 3419, + 3421, + 0, + 3337, + 3333, + 3415, + 3419, + 0, + 3333, + 3329, + 3411, + 3415, + 0, + 3329, + 3327, + 3409, + 3411, + 0, + 3327, + 3325, + 3407, + 3409, + 0, + 3325, + 3323, + 3405, + 3407, + 0, + 3323, + 3321, + 3403, + 3405, + 0, + 3403, + 3406, + 3488, + 3485, + 0, + 3406, + 3412, + 3494, + 3488, + 0, + 3412, + 3416, + 3498, + 3494, + 0, + 3416, + 3422, + 3503, + 3498, + 0, + 3422, + 3431, + 3510, + 3503, + 0, + 3431, + 3434, + 3515, + 3510, + 0, + 3434, + 3436, + 3517, + 3515, + 0, + 3436, + 3438, + 3519, + 3517, + 0, + 3438, + 3440, + 3521, + 3519, + 0, + 3440, + 3442, + 3523, + 3521, + 0, + 3442, + 3444, + 3525, + 3523, + 0, + 3444, + 3443, + 3526, + 3525, + 0, + 3443, + 3441, + 3524, + 3526, + 0, + 3441, + 3439, + 3522, + 3524, + 0, + 3439, + 3437, + 3520, + 3522, + 0, + 3437, + 3435, + 3518, + 3520, + 0, + 3435, + 3433, + 3516, + 3518, + 0, + 3433, + 3429, + 3513, + 3516, + 0, + 3429, + 3423, + 3505, + 3513, + 0, + 3423, + 3418, + 3500, + 3505, + 0, + 3418, + 3413, + 3495, + 3500, + 0, + 3413, + 3402, + 3484, + 3495, + 0, + 3402, + 3401, + 3483, + 3484, + 0, + 3401, + 3398, + 3480, + 3483, + 0, + 3398, + 3396, + 3478, + 3480, + 0, + 3396, + 3395, + 3477, + 3478, + 0, + 3395, + 3393, + 3475, + 3477, + 0, + 3393, + 3391, + 3473, + 3475, + 0, + 3391, + 3389, + 3471, + 3473, + 0, + 3389, + 3387, + 3469, + 3471, + 0, + 3387, + 3385, + 3467, + 3469, + 0, + 3385, + 3383, + 3465, + 3467, + 0, + 3383, + 3381, + 3463, + 3465, + 0, + 3381, + 3379, + 3461, + 3463, + 0, + 3379, + 3377, + 3459, + 3461, + 0, + 3377, + 3375, + 3457, + 3459, + 0, + 3375, + 3374, + 3456, + 3457, + 0, + 3374, + 3372, + 3454, + 3456, + 0, + 3372, + 3369, + 3451, + 3454, + 0, + 3369, + 3367, + 3449, + 3451, + 0, + 3367, + 3366, + 3448, + 3449, + 0, + 3366, + 3363, + 3445, + 3448, + 0, + 3363, + 3364, + 3446, + 3445, + 0, + 3364, + 3365, + 3447, + 3446, + 0, + 3365, + 3368, + 3450, + 3447, + 0, + 3368, + 3370, + 3452, + 3450, + 0, + 3370, + 3371, + 3453, + 3452, + 0, + 3371, + 3373, + 3455, + 3453, + 0, + 3373, + 3376, + 3458, + 3455, + 0, + 3376, + 3378, + 3460, + 3458, + 0, + 3378, + 3380, + 3462, + 3460, + 0, + 3380, + 3382, + 3464, + 3462, + 0, + 3382, + 3384, + 3466, + 3464, + 0, + 3384, + 3386, + 3468, + 3466, + 0, + 3386, + 3388, + 3470, + 3468, + 0, + 3388, + 3390, + 3472, + 3470, + 0, + 3390, + 3392, + 3474, + 3472, + 0, + 3392, + 3394, + 3476, + 3474, + 0, + 3394, + 3397, + 3479, + 3476, + 0, + 3397, + 3399, + 3481, + 3479, + 0, + 3399, + 3400, + 3482, + 3481, + 0, + 3400, + 3404, + 3487, + 3482, + 0, + 3404, + 3408, + 3490, + 3487, + 0, + 3408, + 3410, + 3492, + 3490, + 0, + 3410, + 3414, + 3496, + 3492, + 0, + 3414, + 3417, + 3499, + 3496, + 0, + 3417, + 3420, + 3502, + 3499, + 0, + 3420, + 3424, + 3506, + 3502, + 0, + 3424, + 3426, + 3508, + 3506, + 0, + 3426, + 3428, + 3511, + 3508, + 0, + 3428, + 3432, + 3514, + 3511, + 0, + 3432, + 3430, + 3512, + 3514, + 0, + 3430, + 3427, + 3509, + 3512, + 0, + 3427, + 3425, + 3507, + 3509, + 0, + 3425, + 3421, + 3504, + 3507, + 0, + 3421, + 3419, + 3501, + 3504, + 0, + 3419, + 3415, + 3497, + 3501, + 0, + 3415, + 3411, + 3493, + 3497, + 0, + 3411, + 3409, + 3491, + 3493, + 0, + 3409, + 3407, + 3489, + 3491, + 0, + 3407, + 3405, + 3486, + 3489, + 0, + 3405, + 3403, + 3485, + 3486, + 0, + 3485, + 3488, + 3570, + 3567, + 0, + 3488, + 3494, + 3576, + 3570, + 0, + 3494, + 3498, + 3580, + 3576, + 0, + 3498, + 3503, + 3584, + 3580, + 0, + 3503, + 3510, + 3592, + 3584, + 0, + 3510, + 3515, + 3597, + 3592, + 0, + 3515, + 3517, + 3599, + 3597, + 0, + 3517, + 3519, + 3601, + 3599, + 0, + 3519, + 3521, + 3603, + 3601, + 0, + 3521, + 3523, + 3605, + 3603, + 0, + 3523, + 3525, + 3607, + 3605, + 0, + 3525, + 3526, + 3608, + 3607, + 0, + 3526, + 3524, + 3606, + 3608, + 0, + 3524, + 3522, + 3604, + 3606, + 0, + 3522, + 3520, + 3602, + 3604, + 0, + 3520, + 3518, + 3600, + 3602, + 0, + 3518, + 3516, + 3598, + 3600, + 0, + 3516, + 3513, + 3596, + 3598, + 0, + 3513, + 3505, + 3587, + 3596, + 0, + 3505, + 3500, + 3583, + 3587, + 0, + 3500, + 3495, + 3577, + 3583, + 0, + 3495, + 3484, + 3566, + 3577, + 0, + 3484, + 3483, + 3565, + 3566, + 0, + 3483, + 3480, + 3562, + 3565, + 0, + 3480, + 3478, + 3560, + 3562, + 0, + 3478, + 3477, + 3559, + 3560, + 0, + 3477, + 3475, + 3557, + 3559, + 0, + 3475, + 3473, + 3555, + 3557, + 0, + 3473, + 3471, + 3553, + 3555, + 0, + 3471, + 3469, + 3551, + 3553, + 0, + 3469, + 3467, + 3549, + 3551, + 0, + 3467, + 3465, + 3547, + 3549, + 0, + 3465, + 3463, + 3545, + 3547, + 0, + 3463, + 3461, + 3543, + 3545, + 0, + 3461, + 3459, + 3541, + 3543, + 0, + 3459, + 3457, + 3539, + 3541, + 0, + 3457, + 3456, + 3538, + 3539, + 0, + 3456, + 3454, + 3536, + 3538, + 0, + 3454, + 3451, + 3533, + 3536, + 0, + 3451, + 3449, + 3531, + 3533, + 0, + 3449, + 3448, + 3530, + 3531, + 0, + 3448, + 3445, + 3527, + 3530, + 0, + 3445, + 3446, + 3528, + 3527, + 0, + 3446, + 3447, + 3529, + 3528, + 0, + 3447, + 3450, + 3532, + 3529, + 0, + 3450, + 3452, + 3534, + 3532, + 0, + 3452, + 3453, + 3535, + 3534, + 0, + 3453, + 3455, + 3537, + 3535, + 0, + 3455, + 3458, + 3540, + 3537, + 0, + 3458, + 3460, + 3542, + 3540, + 0, + 3460, + 3462, + 3544, + 3542, + 0, + 3462, + 3464, + 3546, + 3544, + 0, + 3464, + 3466, + 3548, + 3546, + 0, + 3466, + 3468, + 3550, + 3548, + 0, + 3468, + 3470, + 3552, + 3550, + 0, + 3470, + 3472, + 3554, + 3552, + 0, + 3472, + 3474, + 3556, + 3554, + 0, + 3474, + 3476, + 3558, + 3556, + 0, + 3476, + 3479, + 3561, + 3558, + 0, + 3479, + 3481, + 3563, + 3561, + 0, + 3481, + 3482, + 3564, + 3563, + 0, + 3482, + 3487, + 3569, + 3564, + 0, + 3487, + 3490, + 3572, + 3569, + 0, + 3490, + 3492, + 3574, + 3572, + 0, + 3492, + 3496, + 3578, + 3574, + 0, + 3496, + 3499, + 3581, + 3578, + 0, + 3499, + 3502, + 3585, + 3581, + 0, + 3502, + 3506, + 3588, + 3585, + 0, + 3506, + 3508, + 3590, + 3588, + 0, + 3508, + 3511, + 3593, + 3590, + 0, + 3511, + 3514, + 3595, + 3593, + 0, + 3514, + 3512, + 3594, + 3595, + 0, + 3512, + 3509, + 3591, + 3594, + 0, + 3509, + 3507, + 3589, + 3591, + 0, + 3507, + 3504, + 3586, + 3589, + 0, + 3504, + 3501, + 3582, + 3586, + 0, + 3501, + 3497, + 3579, + 3582, + 0, + 3497, + 3493, + 3575, + 3579, + 0, + 3493, + 3491, + 3573, + 3575, + 0, + 3491, + 3489, + 3571, + 3573, + 0, + 3489, + 3486, + 3568, + 3571, + 0, + 3486, + 3485, + 3567, + 3568, + 0, + 3567, + 3570, + 3652, + 3649, + 0, + 3570, + 3576, + 3657, + 3652, + 0, + 3576, + 3580, + 3661, + 3657, + 0, + 3580, + 3584, + 3666, + 3661, + 0, + 3584, + 3592, + 3672, + 3666, + 0, + 3592, + 3597, + 3679, + 3672, + 0, + 3597, + 3599, + 3681, + 3679, + 0, + 3599, + 3601, + 3683, + 3681, + 0, + 3601, + 3603, + 3685, + 3683, + 0, + 3603, + 3605, + 3687, + 3685, + 0, + 3605, + 3607, + 3689, + 3687, + 0, + 3607, + 3608, + 3690, + 3689, + 0, + 3608, + 3606, + 3688, + 3690, + 0, + 3606, + 3604, + 3686, + 3688, + 0, + 3604, + 3602, + 3684, + 3686, + 0, + 3602, + 3600, + 3682, + 3684, + 0, + 3600, + 3598, + 3680, + 3682, + 0, + 3598, + 3596, + 3678, + 3680, + 0, + 3596, + 3587, + 3671, + 3678, + 0, + 3587, + 3583, + 3665, + 3671, + 0, + 3583, + 3577, + 3660, + 3665, + 0, + 3577, + 3566, + 3648, + 3660, + 0, + 3566, + 3565, + 3647, + 3648, + 0, + 3565, + 3562, + 3644, + 3647, + 0, + 3562, + 3560, + 3643, + 3644, + 0, + 3560, + 3559, + 3641, + 3643, + 0, + 3559, + 3557, + 3639, + 3641, + 0, + 3557, + 3555, + 3637, + 3639, + 0, + 3555, + 3553, + 3635, + 3637, + 0, + 3553, + 3551, + 3633, + 3635, + 0, + 3551, + 3549, + 3631, + 3633, + 0, + 3549, + 3547, + 3629, + 3631, + 0, + 3547, + 3545, + 3627, + 3629, + 0, + 3545, + 3543, + 3625, + 3627, + 0, + 3543, + 3541, + 3623, + 3625, + 0, + 3541, + 3539, + 3622, + 3623, + 0, + 3539, + 3538, + 3620, + 3622, + 0, + 3538, + 3536, + 3618, + 3620, + 0, + 3536, + 3533, + 3616, + 3618, + 0, + 3533, + 3531, + 3613, + 3616, + 0, + 3531, + 3530, + 3612, + 3613, + 0, + 3530, + 3527, + 3609, + 3612, + 0, + 3527, + 3528, + 3610, + 3609, + 0, + 3528, + 3529, + 3611, + 3610, + 0, + 3529, + 3532, + 3614, + 3611, + 0, + 3532, + 3534, + 3615, + 3614, + 0, + 3534, + 3535, + 3617, + 3615, + 0, + 3535, + 3537, + 3619, + 3617, + 0, + 3537, + 3540, + 3621, + 3619, + 0, + 3540, + 3542, + 3624, + 3621, + 0, + 3542, + 3544, + 3626, + 3624, + 0, + 3544, + 3546, + 3628, + 3626, + 0, + 3546, + 3548, + 3630, + 3628, + 0, + 3548, + 3550, + 3632, + 3630, + 0, + 3550, + 3552, + 3634, + 3632, + 0, + 3552, + 3554, + 3636, + 3634, + 0, + 3554, + 3556, + 3638, + 3636, + 0, + 3556, + 3558, + 3640, + 3638, + 0, + 3558, + 3561, + 3642, + 3640, + 0, + 3561, + 3563, + 3645, + 3642, + 0, + 3563, + 3564, + 3646, + 3645, + 0, + 3564, + 3569, + 3651, + 3646, + 0, + 3569, + 3572, + 3655, + 3651, + 0, + 3572, + 3574, + 3658, + 3655, + 0, + 3574, + 3578, + 3662, + 3658, + 0, + 3578, + 3581, + 3664, + 3662, + 0, + 3581, + 3585, + 3668, + 3664, + 0, + 3585, + 3588, + 3670, + 3668, + 0, + 3588, + 3590, + 3674, + 3670, + 0, + 3590, + 3593, + 3676, + 3674, + 0, + 3593, + 3595, + 3677, + 3676, + 0, + 3595, + 3594, + 3675, + 3677, + 0, + 3594, + 3591, + 3673, + 3675, + 0, + 3591, + 3589, + 3669, + 3673, + 0, + 3589, + 3586, + 3667, + 3669, + 0, + 3586, + 3582, + 3663, + 3667, + 0, + 3582, + 3579, + 3659, + 3663, + 0, + 3579, + 3575, + 3656, + 3659, + 0, + 3575, + 3573, + 3654, + 3656, + 0, + 3573, + 3571, + 3653, + 3654, + 0, + 3571, + 3568, + 3650, + 3653, + 0, + 3568, + 3567, + 3649, + 3650, + 0, + 3649, + 3652, + 3733, + 3731, + 0, + 3652, + 3657, + 3738, + 3733, + 0, + 3657, + 3661, + 3742, + 3738, + 0, + 3661, + 3666, + 3747, + 3742, + 0, + 3666, + 3672, + 3753, + 3747, + 0, + 3672, + 3679, + 3760, + 3753, + 0, + 3679, + 3681, + 3762, + 3760, + 0, + 3681, + 3683, + 3764, + 3762, + 0, + 3683, + 3685, + 3766, + 3764, + 0, + 3685, + 3687, + 3769, + 3766, + 0, + 3687, + 3689, + 3771, + 3769, + 0, + 3689, + 3690, + 3772, + 3771, + 0, + 3690, + 3688, + 3770, + 3772, + 0, + 3688, + 3686, + 3768, + 3770, + 0, + 3686, + 3684, + 3767, + 3768, + 0, + 3684, + 3682, + 3765, + 3767, + 0, + 3682, + 3680, + 3763, + 3765, + 0, + 3680, + 3678, + 3761, + 3763, + 0, + 3678, + 3671, + 3754, + 3761, + 0, + 3671, + 3665, + 3748, + 3754, + 0, + 3665, + 3660, + 3743, + 3748, + 0, + 3660, + 3648, + 3730, + 3743, + 0, + 3648, + 3647, + 3729, + 3730, + 0, + 3647, + 3644, + 3726, + 3729, + 0, + 3644, + 3643, + 3725, + 3726, + 0, + 3643, + 3641, + 3723, + 3725, + 0, + 3641, + 3639, + 3721, + 3723, + 0, + 3639, + 3637, + 3719, + 3721, + 0, + 3637, + 3635, + 3717, + 3719, + 0, + 3635, + 3633, + 3715, + 3717, + 0, + 3633, + 3631, + 3713, + 3715, + 0, + 3631, + 3629, + 3711, + 3713, + 0, + 3629, + 3627, + 3709, + 3711, + 0, + 3627, + 3625, + 3707, + 3709, + 0, + 3625, + 3623, + 3705, + 3707, + 0, + 3623, + 3622, + 3704, + 3705, + 0, + 3622, + 3620, + 3702, + 3704, + 0, + 3620, + 3618, + 3700, + 3702, + 0, + 3618, + 3616, + 3698, + 3700, + 0, + 3616, + 3613, + 3695, + 3698, + 0, + 3613, + 3612, + 3694, + 3695, + 0, + 3612, + 3609, + 3691, + 3694, + 0, + 3609, + 3610, + 3692, + 3691, + 0, + 3610, + 3611, + 3693, + 3692, + 0, + 3611, + 3614, + 3696, + 3693, + 0, + 3614, + 3615, + 3697, + 3696, + 0, + 3615, + 3617, + 3699, + 3697, + 0, + 3617, + 3619, + 3701, + 3699, + 0, + 3619, + 3621, + 3703, + 3701, + 0, + 3621, + 3624, + 3706, + 3703, + 0, + 3624, + 3626, + 3708, + 3706, + 0, + 3626, + 3628, + 3710, + 3708, + 0, + 3628, + 3630, + 3712, + 3710, + 0, + 3630, + 3632, + 3714, + 3712, + 0, + 3632, + 3634, + 3716, + 3714, + 0, + 3634, + 3636, + 3718, + 3716, + 0, + 3636, + 3638, + 3720, + 3718, + 0, + 3638, + 3640, + 3722, + 3720, + 0, + 3640, + 3642, + 3724, + 3722, + 0, + 3642, + 3645, + 3727, + 3724, + 0, + 3645, + 3646, + 3728, + 3727, + 0, + 3646, + 3651, + 3734, + 3728, + 0, + 3651, + 3655, + 3737, + 3734, + 0, + 3655, + 3658, + 3740, + 3737, + 0, + 3658, + 3662, + 3744, + 3740, + 0, + 3662, + 3664, + 3746, + 3744, + 0, + 3664, + 3668, + 3750, + 3746, + 0, + 3668, + 3670, + 3752, + 3750, + 0, + 3670, + 3674, + 3756, + 3752, + 0, + 3674, + 3676, + 3758, + 3756, + 0, + 3676, + 3677, + 3759, + 3758, + 0, + 3677, + 3675, + 3757, + 3759, + 0, + 3675, + 3673, + 3755, + 3757, + 0, + 3673, + 3669, + 3751, + 3755, + 0, + 3669, + 3667, + 3749, + 3751, + 0, + 3667, + 3663, + 3745, + 3749, + 0, + 3663, + 3659, + 3741, + 3745, + 0, + 3659, + 3656, + 3739, + 3741, + 0, + 3656, + 3654, + 3736, + 3739, + 0, + 3654, + 3653, + 3735, + 3736, + 0, + 3653, + 3650, + 3732, + 3735, + 0, + 3650, + 3649, + 3731, + 3732, + 0, + 3731, + 3733, + 3815, + 3813, + 0, + 3733, + 3738, + 3820, + 3815, + 0, + 3738, + 3742, + 3824, + 3820, + 0, + 3742, + 3747, + 3828, + 3824, + 0, + 3747, + 3753, + 3834, + 3828, + 0, + 3753, + 3760, + 3842, + 3834, + 0, + 3760, + 3762, + 3844, + 3842, + 0, + 3762, + 3764, + 3846, + 3844, + 0, + 3764, + 3766, + 3848, + 3846, + 0, + 3766, + 3769, + 3850, + 3848, + 0, + 3769, + 3771, + 3852, + 3850, + 0, + 3771, + 3772, + 3854, + 3852, + 0, + 3772, + 3770, + 3853, + 3854, + 0, + 3770, + 3768, + 3851, + 3853, + 0, + 3768, + 3767, + 3849, + 3851, + 0, + 3767, + 3765, + 3847, + 3849, + 0, + 3765, + 3763, + 3845, + 3847, + 0, + 3763, + 3761, + 3843, + 3845, + 0, + 3761, + 3754, + 3837, + 3843, + 0, + 3754, + 3748, + 3831, + 3837, + 0, + 3748, + 3743, + 3825, + 3831, + 0, + 3743, + 3730, + 3812, + 3825, + 0, + 3730, + 3729, + 3811, + 3812, + 0, + 3729, + 3726, + 3808, + 3811, + 0, + 3726, + 3725, + 3807, + 3808, + 0, + 3725, + 3723, + 3805, + 3807, + 0, + 3723, + 3721, + 3803, + 3805, + 0, + 3721, + 3719, + 3801, + 3803, + 0, + 3719, + 3717, + 3799, + 3801, + 0, + 3717, + 3715, + 3797, + 3799, + 0, + 3715, + 3713, + 3795, + 3797, + 0, + 3713, + 3711, + 3793, + 3795, + 0, + 3711, + 3709, + 3791, + 3793, + 0, + 3709, + 3707, + 3789, + 3791, + 0, + 3707, + 3705, + 3787, + 3789, + 0, + 3705, + 3704, + 3786, + 3787, + 0, + 3704, + 3702, + 3784, + 3786, + 0, + 3702, + 3700, + 3782, + 3784, + 0, + 3700, + 3698, + 3780, + 3782, + 0, + 3698, + 3695, + 3777, + 3780, + 0, + 3695, + 3694, + 3776, + 3777, + 0, + 3694, + 3691, + 3773, + 3776, + 0, + 3691, + 3692, + 3774, + 3773, + 0, + 3692, + 3693, + 3775, + 3774, + 0, + 3693, + 3696, + 3778, + 3775, + 0, + 3696, + 3697, + 3779, + 3778, + 0, + 3697, + 3699, + 3781, + 3779, + 0, + 3699, + 3701, + 3783, + 3781, + 0, + 3701, + 3703, + 3785, + 3783, + 0, + 3703, + 3706, + 3788, + 3785, + 0, + 3706, + 3708, + 3790, + 3788, + 0, + 3708, + 3710, + 3792, + 3790, + 0, + 3710, + 3712, + 3794, + 3792, + 0, + 3712, + 3714, + 3796, + 3794, + 0, + 3714, + 3716, + 3798, + 3796, + 0, + 3716, + 3718, + 3800, + 3798, + 0, + 3718, + 3720, + 3802, + 3800, + 0, + 3720, + 3722, + 3804, + 3802, + 0, + 3722, + 3724, + 3806, + 3804, + 0, + 3724, + 3727, + 3809, + 3806, + 0, + 3727, + 3728, + 3810, + 3809, + 0, + 3728, + 3734, + 3816, + 3810, + 0, + 3734, + 3737, + 3819, + 3816, + 0, + 3737, + 3740, + 3822, + 3819, + 0, + 3740, + 3744, + 3826, + 3822, + 0, + 3744, + 3746, + 3829, + 3826, + 0, + 3746, + 3750, + 3832, + 3829, + 0, + 3750, + 3752, + 3835, + 3832, + 0, + 3752, + 3756, + 3839, + 3835, + 0, + 3756, + 3758, + 3841, + 3839, + 0, + 3758, + 3759, + 3840, + 3841, + 0, + 3759, + 3757, + 3838, + 3840, + 0, + 3757, + 3755, + 3836, + 3838, + 0, + 3755, + 3751, + 3833, + 3836, + 0, + 3751, + 3749, + 3830, + 3833, + 0, + 3749, + 3745, + 3827, + 3830, + 0, + 3745, + 3741, + 3823, + 3827, + 0, + 3741, + 3739, + 3821, + 3823, + 0, + 3739, + 3736, + 3818, + 3821, + 0, + 3736, + 3735, + 3817, + 3818, + 0, + 3735, + 3732, + 3814, + 3817, + 0, + 3732, + 3731, + 3813, + 3814, + 0, + 3813, + 3815, + 3897, + 3895, + 0, + 3815, + 3820, + 3901, + 3897, + 0, + 3820, + 3824, + 3906, + 3901, + 0, + 3824, + 3828, + 3910, + 3906, + 0, + 3828, + 3834, + 3916, + 3910, + 0, + 3834, + 3842, + 3924, + 3916, + 0, + 3842, + 3844, + 3926, + 3924, + 0, + 3844, + 3846, + 3928, + 3926, + 0, + 3846, + 3848, + 3930, + 3928, + 0, + 3848, + 3850, + 3932, + 3930, + 0, + 3850, + 3852, + 3934, + 3932, + 0, + 3852, + 3854, + 3936, + 3934, + 0, + 3854, + 3853, + 3935, + 3936, + 0, + 3853, + 3851, + 3933, + 3935, + 0, + 3851, + 3849, + 3931, + 3933, + 0, + 3849, + 3847, + 3929, + 3931, + 0, + 3847, + 3845, + 3927, + 3929, + 0, + 3845, + 3843, + 3925, + 3927, + 0, + 3843, + 3837, + 3920, + 3925, + 0, + 3837, + 3831, + 3913, + 3920, + 0, + 3831, + 3825, + 3908, + 3913, + 0, + 3825, + 3812, + 3894, + 3908, + 0, + 3812, + 3811, + 3893, + 3894, + 0, + 3811, + 3808, + 3891, + 3893, + 0, + 3808, + 3807, + 3889, + 3891, + 0, + 3807, + 3805, + 3887, + 3889, + 0, + 3805, + 3803, + 3885, + 3887, + 0, + 3803, + 3801, + 3883, + 3885, + 0, + 3801, + 3799, + 3881, + 3883, + 0, + 3799, + 3797, + 3879, + 3881, + 0, + 3797, + 3795, + 3877, + 3879, + 0, + 3795, + 3793, + 3875, + 3877, + 0, + 3793, + 3791, + 3873, + 3875, + 0, + 3791, + 3789, + 3871, + 3873, + 0, + 3789, + 3787, + 3869, + 3871, + 0, + 3787, + 3786, + 3868, + 3869, + 0, + 3786, + 3784, + 3866, + 3868, + 0, + 3784, + 3782, + 3864, + 3866, + 0, + 3782, + 3780, + 3862, + 3864, + 0, + 3780, + 3777, + 3859, + 3862, + 0, + 3777, + 3776, + 3858, + 3859, + 0, + 3776, + 3773, + 3855, + 3858, + 0, + 3773, + 3774, + 3856, + 3855, + 0, + 3774, + 3775, + 3857, + 3856, + 0, + 3775, + 3778, + 3860, + 3857, + 0, + 3778, + 3779, + 3861, + 3860, + 0, + 3779, + 3781, + 3863, + 3861, + 0, + 3781, + 3783, + 3865, + 3863, + 0, + 3783, + 3785, + 3867, + 3865, + 0, + 3785, + 3788, + 3870, + 3867, + 0, + 3788, + 3790, + 3872, + 3870, + 0, + 3790, + 3792, + 3874, + 3872, + 0, + 3792, + 3794, + 3876, + 3874, + 0, + 3794, + 3796, + 3878, + 3876, + 0, + 3796, + 3798, + 3880, + 3878, + 0, + 3798, + 3800, + 3882, + 3880, + 0, + 3800, + 3802, + 3884, + 3882, + 0, + 3802, + 3804, + 3886, + 3884, + 0, + 3804, + 3806, + 3888, + 3886, + 0, + 3806, + 3809, + 3890, + 3888, + 0, + 3809, + 3810, + 3892, + 3890, + 0, + 3810, + 3816, + 3898, + 3892, + 0, + 3816, + 3819, + 3903, + 3898, + 0, + 3819, + 3822, + 3905, + 3903, + 0, + 3822, + 3826, + 3909, + 3905, + 0, + 3826, + 3829, + 3912, + 3909, + 0, + 3829, + 3832, + 3915, + 3912, + 0, + 3832, + 3835, + 3918, + 3915, + 0, + 3835, + 3839, + 3921, + 3918, + 0, + 3839, + 3841, + 3923, + 3921, + 0, + 3841, + 3840, + 3922, + 3923, + 0, + 3840, + 3838, + 3919, + 3922, + 0, + 3838, + 3836, + 3917, + 3919, + 0, + 3836, + 3833, + 3914, + 3917, + 0, + 3833, + 3830, + 3911, + 3914, + 0, + 3830, + 3827, + 3907, + 3911, + 0, + 3827, + 3823, + 3904, + 3907, + 0, + 3823, + 3821, + 3902, + 3904, + 0, + 3821, + 3818, + 3900, + 3902, + 0, + 3818, + 3817, + 3899, + 3900, + 0, + 3817, + 3814, + 3896, + 3899, + 0, + 3814, + 3813, + 3895, + 3896, + 0, + 3895, + 3897, + 3979, + 3976, + 0, + 3897, + 3901, + 3983, + 3979, + 0, + 3901, + 3906, + 3987, + 3983, + 0, + 3906, + 3910, + 3992, + 3987, + 0, + 3910, + 3916, + 3997, + 3992, + 0, + 3916, + 3924, + 4003, + 3997, + 0, + 3924, + 3926, + 4007, + 4003, + 0, + 3926, + 3928, + 4010, + 4007, + 0, + 3928, + 3930, + 4012, + 4010, + 0, + 3930, + 3932, + 4014, + 4012, + 0, + 3932, + 3934, + 4016, + 4014, + 0, + 3934, + 3936, + 4018, + 4016, + 0, + 3936, + 3935, + 4017, + 4018, + 0, + 3935, + 3933, + 4015, + 4017, + 0, + 3933, + 3931, + 4013, + 4015, + 0, + 3931, + 3929, + 4011, + 4013, + 0, + 3929, + 3927, + 4009, + 4011, + 0, + 3927, + 3925, + 4008, + 4009, + 0, + 3925, + 3920, + 4005, + 4008, + 0, + 3920, + 3913, + 3995, + 4005, + 0, + 3913, + 3908, + 3991, + 3995, + 0, + 3908, + 3894, + 3977, + 3991, + 0, + 3894, + 3893, + 3975, + 3977, + 0, + 3893, + 3891, + 3973, + 3975, + 0, + 3891, + 3889, + 3971, + 3973, + 0, + 3889, + 3887, + 3969, + 3971, + 0, + 3887, + 3885, + 3967, + 3969, + 0, + 3885, + 3883, + 3965, + 3967, + 0, + 3883, + 3881, + 3963, + 3965, + 0, + 3881, + 3879, + 3961, + 3963, + 0, + 3879, + 3877, + 3959, + 3961, + 0, + 3877, + 3875, + 3957, + 3959, + 0, + 3875, + 3873, + 3955, + 3957, + 0, + 3873, + 3871, + 3953, + 3955, + 0, + 3871, + 3869, + 3951, + 3953, + 0, + 3869, + 3868, + 3950, + 3951, + 0, + 3868, + 3866, + 3948, + 3950, + 0, + 3866, + 3864, + 3946, + 3948, + 0, + 3864, + 3862, + 3944, + 3946, + 0, + 3862, + 3859, + 3941, + 3944, + 0, + 3859, + 3858, + 3940, + 3941, + 0, + 3858, + 3855, + 3937, + 3940, + 0, + 3855, + 3856, + 3938, + 3937, + 0, + 3856, + 3857, + 3939, + 3938, + 0, + 3857, + 3860, + 3942, + 3939, + 0, + 3860, + 3861, + 3943, + 3942, + 0, + 3861, + 3863, + 3945, + 3943, + 0, + 3863, + 3865, + 3947, + 3945, + 0, + 3865, + 3867, + 3949, + 3947, + 0, + 3867, + 3870, + 3952, + 3949, + 0, + 3870, + 3872, + 3954, + 3952, + 0, + 3872, + 3874, + 3956, + 3954, + 0, + 3874, + 3876, + 3958, + 3956, + 0, + 3876, + 3878, + 3960, + 3958, + 0, + 3878, + 3880, + 3962, + 3960, + 0, + 3880, + 3882, + 3964, + 3962, + 0, + 3882, + 3884, + 3966, + 3964, + 0, + 3884, + 3886, + 3968, + 3966, + 0, + 3886, + 3888, + 3970, + 3968, + 0, + 3888, + 3890, + 3972, + 3970, + 0, + 3890, + 3892, + 3974, + 3972, + 0, + 3892, + 3898, + 3980, + 3974, + 0, + 3898, + 3903, + 3985, + 3980, + 0, + 3903, + 3905, + 3988, + 3985, + 0, + 3905, + 3909, + 3990, + 3988, + 0, + 3909, + 3912, + 3994, + 3990, + 0, + 3912, + 3915, + 3998, + 3994, + 0, + 3915, + 3918, + 4000, + 3998, + 0, + 3918, + 3921, + 4002, + 4000, + 0, + 3921, + 3923, + 4006, + 4002, + 0, + 3923, + 3922, + 4004, + 4006, + 0, + 3922, + 3919, + 4001, + 4004, + 0, + 3919, + 3917, + 3999, + 4001, + 0, + 3917, + 3914, + 3996, + 3999, + 0, + 3914, + 3911, + 3993, + 3996, + 0, + 3911, + 3907, + 3989, + 3993, + 0, + 3907, + 3904, + 3986, + 3989, + 0, + 3904, + 3902, + 3984, + 3986, + 0, + 3902, + 3900, + 3982, + 3984, + 0, + 3900, + 3899, + 3981, + 3982, + 0, + 3899, + 3896, + 3978, + 3981, + 0, + 3896, + 3895, + 3976, + 3978, + 0, + 3976, + 3979, + 4061, + 4058, + 0, + 3979, + 3983, + 4065, + 4061, + 0, + 3983, + 3987, + 4069, + 4065, + 0, + 3987, + 3992, + 4072, + 4069, + 0, + 3992, + 3997, + 4078, + 4072, + 0, + 3997, + 4003, + 4084, + 4078, + 0, + 4003, + 4007, + 4089, + 4084, + 0, + 4007, + 4010, + 4091, + 4089, + 0, + 4010, + 4012, + 4093, + 4091, + 0, + 4012, + 4014, + 4095, + 4093, + 0, + 4014, + 4016, + 4097, + 4095, + 0, + 4016, + 4018, + 4099, + 4097, + 0, + 4018, + 4017, + 4100, + 4099, + 0, + 4017, + 4015, + 4098, + 4100, + 0, + 4015, + 4013, + 4096, + 4098, + 0, + 4013, + 4011, + 4094, + 4096, + 0, + 4011, + 4009, + 4092, + 4094, + 0, + 4009, + 4008, + 4090, + 4092, + 0, + 4008, + 4005, + 4088, + 4090, + 0, + 4005, + 3995, + 4079, + 4088, + 0, + 3995, + 3991, + 4074, + 4079, + 0, + 3991, + 3977, + 4060, + 4074, + 0, + 3977, + 3975, + 4057, + 4060, + 0, + 3975, + 3973, + 4055, + 4057, + 0, + 3973, + 3971, + 4053, + 4055, + 0, + 3971, + 3969, + 4051, + 4053, + 0, + 3969, + 3967, + 4049, + 4051, + 0, + 3967, + 3965, + 4047, + 4049, + 0, + 3965, + 3963, + 4045, + 4047, + 0, + 3963, + 3961, + 4043, + 4045, + 0, + 3961, + 3959, + 4041, + 4043, + 0, + 3959, + 3957, + 4039, + 4041, + 0, + 3957, + 3955, + 4037, + 4039, + 0, + 3955, + 3953, + 4035, + 4037, + 0, + 3953, + 3951, + 4033, + 4035, + 0, + 3951, + 3950, + 4032, + 4033, + 0, + 3950, + 3948, + 4030, + 4032, + 0, + 3948, + 3946, + 4028, + 4030, + 0, + 3946, + 3944, + 4026, + 4028, + 0, + 3944, + 3941, + 4023, + 4026, + 0, + 3941, + 3940, + 4022, + 4023, + 0, + 3940, + 3937, + 4019, + 4022, + 0, + 3937, + 3938, + 4020, + 4019, + 0, + 3938, + 3939, + 4021, + 4020, + 0, + 3939, + 3942, + 4024, + 4021, + 0, + 3942, + 3943, + 4025, + 4024, + 0, + 3943, + 3945, + 4027, + 4025, + 0, + 3945, + 3947, + 4029, + 4027, + 0, + 3947, + 3949, + 4031, + 4029, + 0, + 3949, + 3952, + 4034, + 4031, + 0, + 3952, + 3954, + 4036, + 4034, + 0, + 3954, + 3956, + 4038, + 4036, + 0, + 3956, + 3958, + 4040, + 4038, + 0, + 3958, + 3960, + 4042, + 4040, + 0, + 3960, + 3962, + 4044, + 4042, + 0, + 3962, + 3964, + 4046, + 4044, + 0, + 3964, + 3966, + 4048, + 4046, + 0, + 3966, + 3968, + 4050, + 4048, + 0, + 3968, + 3970, + 4052, + 4050, + 0, + 3970, + 3972, + 4054, + 4052, + 0, + 3972, + 3974, + 4056, + 4054, + 0, + 3974, + 3980, + 4062, + 4056, + 0, + 3980, + 3985, + 4067, + 4062, + 0, + 3985, + 3988, + 4070, + 4067, + 0, + 3988, + 3990, + 4073, + 4070, + 0, + 3990, + 3994, + 4076, + 4073, + 0, + 3994, + 3998, + 4080, + 4076, + 0, + 3998, + 4000, + 4082, + 4080, + 0, + 4000, + 4002, + 4085, + 4082, + 0, + 4002, + 4006, + 4087, + 4085, + 0, + 4006, + 4004, + 4086, + 4087, + 0, + 4004, + 4001, + 4083, + 4086, + 0, + 4001, + 3999, + 4081, + 4083, + 0, + 3999, + 3996, + 4077, + 4081, + 0, + 3996, + 3993, + 4075, + 4077, + 0, + 3993, + 3989, + 4071, + 4075, + 0, + 3989, + 3986, + 4068, + 4071, + 0, + 3986, + 3984, + 4066, + 4068, + 0, + 3984, + 3982, + 4064, + 4066, + 0, + 3982, + 3981, + 4063, + 4064, + 0, + 3981, + 3978, + 4059, + 4063, + 0, + 3978, + 3976, + 4058, + 4059, + 0, + 4058, + 4061, + 4143, + 4140, + 0, + 4061, + 4065, + 4147, + 4143, + 0, + 4065, + 4069, + 4151, + 4147, + 0, + 4069, + 4072, + 4154, + 4151, + 0, + 4072, + 4078, + 4159, + 4154, + 0, + 4078, + 4084, + 4165, + 4159, + 0, + 4084, + 4089, + 4171, + 4165, + 0, + 4089, + 4091, + 4173, + 4171, + 0, + 4091, + 4093, + 4175, + 4173, + 0, + 4093, + 4095, + 4177, + 4175, + 0, + 4095, + 4097, + 4179, + 4177, + 0, + 4097, + 4099, + 4181, + 4179, + 0, + 4099, + 4100, + 4182, + 4181, + 0, + 4100, + 4098, + 4180, + 4182, + 0, + 4098, + 4096, + 4178, + 4180, + 0, + 4096, + 4094, + 4176, + 4178, + 0, + 4094, + 4092, + 4174, + 4176, + 0, + 4092, + 4090, + 4172, + 4174, + 0, + 4090, + 4088, + 4170, + 4172, + 0, + 4088, + 4079, + 4161, + 4170, + 0, + 4079, + 4074, + 4156, + 4161, + 0, + 4074, + 4060, + 4142, + 4156, + 0, + 4060, + 4057, + 4139, + 4142, + 0, + 4057, + 4055, + 4137, + 4139, + 0, + 4055, + 4053, + 4135, + 4137, + 0, + 4053, + 4051, + 4133, + 4135, + 0, + 4051, + 4049, + 4131, + 4133, + 0, + 4049, + 4047, + 4129, + 4131, + 0, + 4047, + 4045, + 4127, + 4129, + 0, + 4045, + 4043, + 4125, + 4127, + 0, + 4043, + 4041, + 4123, + 4125, + 0, + 4041, + 4039, + 4121, + 4123, + 0, + 4039, + 4037, + 4119, + 4121, + 0, + 4037, + 4035, + 4117, + 4119, + 0, + 4035, + 4033, + 4115, + 4117, + 0, + 4033, + 4032, + 4114, + 4115, + 0, + 4032, + 4030, + 4112, + 4114, + 0, + 4030, + 4028, + 4110, + 4112, + 0, + 4028, + 4026, + 4108, + 4110, + 0, + 4026, + 4023, + 4105, + 4108, + 0, + 4023, + 4022, + 4104, + 4105, + 0, + 4022, + 4019, + 4101, + 4104, + 0, + 4019, + 4020, + 4102, + 4101, + 0, + 4020, + 4021, + 4103, + 4102, + 0, + 4021, + 4024, + 4106, + 4103, + 0, + 4024, + 4025, + 4107, + 4106, + 0, + 4025, + 4027, + 4109, + 4107, + 0, + 4027, + 4029, + 4111, + 4109, + 0, + 4029, + 4031, + 4113, + 4111, + 0, + 4031, + 4034, + 4116, + 4113, + 0, + 4034, + 4036, + 4118, + 4116, + 0, + 4036, + 4038, + 4120, + 4118, + 0, + 4038, + 4040, + 4122, + 4120, + 0, + 4040, + 4042, + 4124, + 4122, + 0, + 4042, + 4044, + 4126, + 4124, + 0, + 4044, + 4046, + 4128, + 4126, + 0, + 4046, + 4048, + 4130, + 4128, + 0, + 4048, + 4050, + 4132, + 4130, + 0, + 4050, + 4052, + 4134, + 4132, + 0, + 4052, + 4054, + 4136, + 4134, + 0, + 4054, + 4056, + 4138, + 4136, + 0, + 4056, + 4062, + 4144, + 4138, + 0, + 4062, + 4067, + 4149, + 4144, + 0, + 4067, + 4070, + 4152, + 4149, + 0, + 4070, + 4073, + 4155, + 4152, + 0, + 4073, + 4076, + 4158, + 4155, + 0, + 4076, + 4080, + 4162, + 4158, + 0, + 4080, + 4082, + 4164, + 4162, + 0, + 4082, + 4085, + 4168, + 4164, + 0, + 4085, + 4087, + 4169, + 4168, + 0, + 4087, + 4086, + 4167, + 4169, + 0, + 4086, + 4083, + 4166, + 4167, + 0, + 4083, + 4081, + 4163, + 4166, + 0, + 4081, + 4077, + 4160, + 4163, + 0, + 4077, + 4075, + 4157, + 4160, + 0, + 4075, + 4071, + 4153, + 4157, + 0, + 4071, + 4068, + 4150, + 4153, + 0, + 4068, + 4066, + 4148, + 4150, + 0, + 4066, + 4064, + 4146, + 4148, + 0, + 4064, + 4063, + 4145, + 4146, + 0, + 4063, + 4059, + 4141, + 4145, + 0, + 4059, + 4058, + 4140, + 4141, + 0, + 4140, + 4143, + 4225, + 4221, + 0, + 4143, + 4147, + 4229, + 4225, + 0, + 4147, + 4151, + 4233, + 4229, + 0, + 4151, + 4154, + 4236, + 4233, + 0, + 4154, + 4159, + 4241, + 4236, + 0, + 4159, + 4165, + 4246, + 4241, + 0, + 4165, + 4171, + 4253, + 4246, + 0, + 4171, + 4173, + 4255, + 4253, + 0, + 4173, + 4175, + 4257, + 4255, + 0, + 4175, + 4177, + 4259, + 4257, + 0, + 4177, + 4179, + 4261, + 4259, + 0, + 4179, + 4181, + 4263, + 4261, + 0, + 4181, + 4182, + 4264, + 4263, + 0, + 4182, + 4180, + 4262, + 4264, + 0, + 4180, + 4178, + 4260, + 4262, + 0, + 4178, + 4176, + 4258, + 4260, + 0, + 4176, + 4174, + 4256, + 4258, + 0, + 4174, + 4172, + 4254, + 4256, + 0, + 4172, + 4170, + 4252, + 4254, + 0, + 4170, + 4161, + 4243, + 4252, + 0, + 4161, + 4156, + 4239, + 4243, + 0, + 4156, + 4142, + 4224, + 4239, + 0, + 4142, + 4139, + 4222, + 4224, + 0, + 4139, + 4137, + 4219, + 4222, + 0, + 4137, + 4135, + 4217, + 4219, + 0, + 4135, + 4133, + 4215, + 4217, + 0, + 4133, + 4131, + 4213, + 4215, + 0, + 4131, + 4129, + 4211, + 4213, + 0, + 4129, + 4127, + 4209, + 4211, + 0, + 4127, + 4125, + 4207, + 4209, + 0, + 4125, + 4123, + 4205, + 4207, + 0, + 4123, + 4121, + 4203, + 4205, + 0, + 4121, + 4119, + 4201, + 4203, + 0, + 4119, + 4117, + 4199, + 4201, + 0, + 4117, + 4115, + 4197, + 4199, + 0, + 4115, + 4114, + 4196, + 4197, + 0, + 4114, + 4112, + 4194, + 4196, + 0, + 4112, + 4110, + 4192, + 4194, + 0, + 4110, + 4108, + 4190, + 4192, + 0, + 4108, + 4105, + 4187, + 4190, + 0, + 4105, + 4104, + 4186, + 4187, + 0, + 4104, + 4101, + 4183, + 4186, + 0, + 4101, + 4102, + 4184, + 4183, + 0, + 4102, + 4103, + 4185, + 4184, + 0, + 4103, + 4106, + 4188, + 4185, + 0, + 4106, + 4107, + 4189, + 4188, + 0, + 4107, + 4109, + 4191, + 4189, + 0, + 4109, + 4111, + 4193, + 4191, + 0, + 4111, + 4113, + 4195, + 4193, + 0, + 4113, + 4116, + 4198, + 4195, + 0, + 4116, + 4118, + 4200, + 4198, + 0, + 4118, + 4120, + 4202, + 4200, + 0, + 4120, + 4122, + 4204, + 4202, + 0, + 4122, + 4124, + 4206, + 4204, + 0, + 4124, + 4126, + 4208, + 4206, + 0, + 4126, + 4128, + 4210, + 4208, + 0, + 4128, + 4130, + 4212, + 4210, + 0, + 4130, + 4132, + 4214, + 4212, + 0, + 4132, + 4134, + 4216, + 4214, + 0, + 4134, + 4136, + 4218, + 4216, + 0, + 4136, + 4138, + 4220, + 4218, + 0, + 4138, + 4144, + 4226, + 4220, + 0, + 4144, + 4149, + 4231, + 4226, + 0, + 4149, + 4152, + 4234, + 4231, + 0, + 4152, + 4155, + 4237, + 4234, + 0, + 4155, + 4158, + 4240, + 4237, + 0, + 4158, + 4162, + 4244, + 4240, + 0, + 4162, + 4164, + 4248, + 4244, + 0, + 4164, + 4168, + 4250, + 4248, + 0, + 4168, + 4169, + 4251, + 4250, + 0, + 4169, + 4167, + 4249, + 4251, + 0, + 4167, + 4166, + 4247, + 4249, + 0, + 4166, + 4163, + 4245, + 4247, + 0, + 4163, + 4160, + 4242, + 4245, + 0, + 4160, + 4157, + 4238, + 4242, + 0, + 4157, + 4153, + 4235, + 4238, + 0, + 4153, + 4150, + 4232, + 4235, + 0, + 4150, + 4148, + 4230, + 4232, + 0, + 4148, + 4146, + 4228, + 4230, + 0, + 4146, + 4145, + 4227, + 4228, + 0, + 4145, + 4141, + 4223, + 4227, + 0, + 4141, + 4140, + 4221, + 4223, + 0, + 4221, + 4225, + 4306, + 4302, + 0, + 4225, + 4229, + 4311, + 4306, + 0, + 4229, + 4233, + 4313, + 4311, + 0, + 4233, + 4236, + 4318, + 4313, + 0, + 4236, + 4241, + 4322, + 4318, + 0, + 4241, + 4246, + 4328, + 4322, + 0, + 4246, + 4253, + 4334, + 4328, + 0, + 4253, + 4255, + 4336, + 4334, + 0, + 4255, + 4257, + 4338, + 4336, + 0, + 4257, + 4259, + 4341, + 4338, + 0, + 4259, + 4261, + 4343, + 4341, + 0, + 4261, + 4263, + 4345, + 4343, + 0, + 4263, + 4264, + 4346, + 4345, + 0, + 4264, + 4262, + 4344, + 4346, + 0, + 4262, + 4260, + 4342, + 4344, + 0, + 4260, + 4258, + 4340, + 4342, + 0, + 4258, + 4256, + 4339, + 4340, + 0, + 4256, + 4254, + 4337, + 4339, + 0, + 4254, + 4252, + 4335, + 4337, + 0, + 4252, + 4243, + 4327, + 4335, + 0, + 4243, + 4239, + 4321, + 4327, + 0, + 4239, + 4224, + 4307, + 4321, + 0, + 4224, + 4222, + 4305, + 4307, + 0, + 4222, + 4219, + 4301, + 4305, + 0, + 4219, + 4217, + 4299, + 4301, + 0, + 4217, + 4215, + 4297, + 4299, + 0, + 4215, + 4213, + 4295, + 4297, + 0, + 4213, + 4211, + 4293, + 4295, + 0, + 4211, + 4209, + 4291, + 4293, + 0, + 4209, + 4207, + 4289, + 4291, + 0, + 4207, + 4205, + 4287, + 4289, + 0, + 4205, + 4203, + 4285, + 4287, + 0, + 4203, + 4201, + 4283, + 4285, + 0, + 4201, + 4199, + 4281, + 4283, + 0, + 4199, + 4197, + 4280, + 4281, + 0, + 4197, + 4196, + 4278, + 4280, + 0, + 4196, + 4194, + 4276, + 4278, + 0, + 4194, + 4192, + 4274, + 4276, + 0, + 4192, + 4190, + 4272, + 4274, + 0, + 4190, + 4187, + 4269, + 4272, + 0, + 4187, + 4186, + 4268, + 4269, + 0, + 4186, + 4183, + 4265, + 4268, + 0, + 4183, + 4184, + 4266, + 4265, + 0, + 4184, + 4185, + 4267, + 4266, + 0, + 4185, + 4188, + 4270, + 4267, + 0, + 4188, + 4189, + 4271, + 4270, + 0, + 4189, + 4191, + 4273, + 4271, + 0, + 4191, + 4193, + 4275, + 4273, + 0, + 4193, + 4195, + 4277, + 4275, + 0, + 4195, + 4198, + 4279, + 4277, + 0, + 4198, + 4200, + 4282, + 4279, + 0, + 4200, + 4202, + 4284, + 4282, + 0, + 4202, + 4204, + 4286, + 4284, + 0, + 4204, + 4206, + 4288, + 4286, + 0, + 4206, + 4208, + 4290, + 4288, + 0, + 4208, + 4210, + 4292, + 4290, + 0, + 4210, + 4212, + 4294, + 4292, + 0, + 4212, + 4214, + 4296, + 4294, + 0, + 4214, + 4216, + 4298, + 4296, + 0, + 4216, + 4218, + 4300, + 4298, + 0, + 4218, + 4220, + 4303, + 4300, + 0, + 4220, + 4226, + 4308, + 4303, + 0, + 4226, + 4231, + 4315, + 4308, + 0, + 4231, + 4234, + 4317, + 4315, + 0, + 4234, + 4237, + 4320, + 4317, + 0, + 4237, + 4240, + 4324, + 4320, + 0, + 4240, + 4244, + 4326, + 4324, + 0, + 4244, + 4248, + 4330, + 4326, + 0, + 4248, + 4250, + 4332, + 4330, + 0, + 4250, + 4251, + 4333, + 4332, + 0, + 4251, + 4249, + 4331, + 4333, + 0, + 4249, + 4247, + 4329, + 4331, + 0, + 4247, + 4245, + 4325, + 4329, + 0, + 4245, + 4242, + 4323, + 4325, + 0, + 4242, + 4238, + 4319, + 4323, + 0, + 4238, + 4235, + 4316, + 4319, + 0, + 4235, + 4232, + 4314, + 4316, + 0, + 4232, + 4230, + 4312, + 4314, + 0, + 4230, + 4228, + 4310, + 4312, + 0, + 4228, + 4227, + 4309, + 4310, + 0, + 4227, + 4223, + 4304, + 4309, + 0, + 4223, + 4221, + 4302, + 4304, + 0, + 4302, + 4306, + 4419, + 4412, + 0, + 4306, + 4311, + 4436, + 4419, + 0, + 4311, + 4313, + 4438, + 4436, + 0, + 4313, + 4318, + 4444, + 4438, + 0, + 4318, + 4322, + 4449, + 4444, + 0, + 4322, + 4328, + 4455, + 4449, + 0, + 4328, + 4334, + 4465, + 4455, + 0, + 4334, + 4336, + 4469, + 4465, + 0, + 4336, + 4338, + 4473, + 4469, + 0, + 4338, + 4341, + 4477, + 4473, + 0, + 4341, + 4343, + 4479, + 4477, + 0, + 4343, + 4345, + 4483, + 4479, + 0, + 4345, + 4346, + 4485, + 4483, + 0, + 4346, + 4344, + 4484, + 4485, + 0, + 4344, + 4342, + 4482, + 4484, + 0, + 4342, + 4340, + 4478, + 4482, + 0, + 4340, + 4339, + 4475, + 4478, + 0, + 4339, + 4337, + 4472, + 4475, + 0, + 4337, + 4335, + 4468, + 4472, + 0, + 4335, + 4327, + 4460, + 4468, + 0, + 4327, + 4321, + 4453, + 4460, + 0, + 4321, + 4307, + 4424, + 4453, + 0, + 4307, + 4305, + 4421, + 4424, + 0, + 4305, + 4301, + 4414, + 4421, + 0, + 4301, + 4299, + 4410, + 4414, + 0, + 4299, + 4297, + 4406, + 4410, + 0, + 4297, + 4295, + 4403, + 4406, + 0, + 4295, + 4293, + 4399, + 4403, + 0, + 4293, + 4291, + 4395, + 4399, + 0, + 4291, + 4289, + 4391, + 4395, + 0, + 4289, + 4287, + 4387, + 4391, + 0, + 4287, + 4285, + 4383, + 4387, + 0, + 4285, + 4283, + 4379, + 4383, + 0, + 4283, + 4281, + 4375, + 4379, + 0, + 4281, + 4280, + 4372, + 4375, + 0, + 4280, + 4278, + 4368, + 4372, + 0, + 4278, + 4276, + 4364, + 4368, + 0, + 4276, + 4274, + 4360, + 4364, + 0, + 4274, + 4272, + 4357, + 4360, + 0, + 4272, + 4269, + 4355, + 4357, + 0, + 4269, + 4268, + 4353, + 4355, + 0, + 4268, + 4265, + 4347, + 4353, + 0, + 4265, + 4266, + 4348, + 4347, + 0, + 4266, + 4267, + 4349, + 4348, + 0, + 4267, + 4270, + 4354, + 4349, + 0, + 4270, + 4271, + 4356, + 4354, + 0, + 4271, + 4273, + 4359, + 4356, + 0, + 4273, + 4275, + 4363, + 4359, + 0, + 4275, + 4277, + 4367, + 4363, + 0, + 4277, + 4279, + 4371, + 4367, + 0, + 4279, + 4282, + 4376, + 4371, + 0, + 4282, + 4284, + 4380, + 4376, + 0, + 4284, + 4286, + 4384, + 4380, + 0, + 4286, + 4288, + 4388, + 4384, + 0, + 4288, + 4290, + 4392, + 4388, + 0, + 4290, + 4292, + 4396, + 4392, + 0, + 4292, + 4294, + 4400, + 4396, + 0, + 4294, + 4296, + 4404, + 4400, + 0, + 4296, + 4298, + 4408, + 4404, + 0, + 4298, + 4300, + 4413, + 4408, + 0, + 4300, + 4303, + 4417, + 4413, + 0, + 4303, + 4308, + 4431, + 4417, + 0, + 4308, + 4315, + 4442, + 4431, + 0, + 4315, + 4317, + 4446, + 4442, + 0, + 4317, + 4320, + 4450, + 4446, + 0, + 4320, + 4324, + 4454, + 4450, + 0, + 4324, + 4326, + 4457, + 4454, + 0, + 4326, + 4330, + 4463, + 4457, + 0, + 4330, + 4332, + 4466, + 4463, + 0, + 4332, + 4333, + 4464, + 4466, + 0, + 4333, + 4331, + 4462, + 4464, + 0, + 4331, + 4329, + 4458, + 4462, + 0, + 4329, + 4325, + 4456, + 4458, + 0, + 4325, + 4323, + 4452, + 4456, + 0, + 4323, + 4319, + 4447, + 4452, + 0, + 4319, + 4316, + 4443, + 4447, + 0, + 4316, + 4314, + 4439, + 4443, + 0, + 4314, + 4312, + 4437, + 4439, + 0, + 4312, + 4310, + 4434, + 4437, + 0, + 4310, + 4309, + 4433, + 4434, + 0, + 4309, + 4304, + 4415, + 4433, + 0, + 4304, + 4302, + 4412, + 4415, + 0, + 4412, + 4419, + 4430, + 4425, + 0, + 4419, + 4436, + 4448, + 4430, + 0, + 4436, + 4438, + 4459, + 4448, + 0, + 4438, + 4444, + 4471, + 4459, + 0, + 4444, + 4449, + 4480, + 4471, + 0, + 4449, + 4455, + 4489, + 4480, + 0, + 4455, + 4465, + 4497, + 4489, + 0, + 4465, + 4469, + 4500, + 4497, + 0, + 4469, + 4473, + 4502, + 4500, + 0, + 4473, + 4477, + 4504, + 4502, + 0, + 4477, + 4479, + 4506, + 4504, + 0, + 4479, + 4483, + 4508, + 4506, + 0, + 4483, + 4485, + 4510, + 4508, + 0, + 4485, + 4484, + 4509, + 4510, + 0, + 4484, + 4482, + 4507, + 4509, + 0, + 4482, + 4478, + 4505, + 4507, + 0, + 4478, + 4475, + 4503, + 4505, + 0, + 4475, + 4472, + 4501, + 4503, + 0, + 4472, + 4468, + 4499, + 4501, + 0, + 4468, + 4460, + 4493, + 4499, + 0, + 4460, + 4453, + 4487, + 4493, + 0, + 4453, + 4424, + 4435, + 4487, + 0, + 4424, + 4421, + 4432, + 4435, + 0, + 4421, + 4414, + 4428, + 4432, + 0, + 4414, + 4410, + 4423, + 4428, + 0, + 4410, + 4406, + 4420, + 4423, + 0, + 4406, + 4403, + 4416, + 4420, + 0, + 4403, + 4399, + 4409, + 4416, + 0, + 4399, + 4395, + 4405, + 4409, + 0, + 4395, + 4391, + 4401, + 4405, + 0, + 4391, + 4387, + 4397, + 4401, + 0, + 4387, + 4383, + 4393, + 4397, + 0, + 4383, + 4379, + 4389, + 4393, + 0, + 4379, + 4375, + 4385, + 4389, + 0, + 4375, + 4372, + 4382, + 4385, + 0, + 4372, + 4368, + 4378, + 4382, + 0, + 4368, + 4364, + 4374, + 4378, + 0, + 4364, + 4360, + 4370, + 4374, + 0, + 4360, + 4357, + 4366, + 4370, + 0, + 4357, + 4355, + 4362, + 4366, + 0, + 4355, + 4353, + 4358, + 4362, + 0, + 4353, + 4347, + 4350, + 4358, + 0, + 4347, + 4348, + 4351, + 4350, + 0, + 4348, + 4349, + 4352, + 4351, + 0, + 4349, + 4354, + 4361, + 4352, + 0, + 4354, + 4356, + 4365, + 4361, + 0, + 4356, + 4359, + 4369, + 4365, + 0, + 4359, + 4363, + 4373, + 4369, + 0, + 4363, + 4367, + 4377, + 4373, + 0, + 4367, + 4371, + 4381, + 4377, + 0, + 4371, + 4376, + 4386, + 4381, + 0, + 4376, + 4380, + 4390, + 4386, + 0, + 4380, + 4384, + 4394, + 4390, + 0, + 4384, + 4388, + 4398, + 4394, + 0, + 4388, + 4392, + 4402, + 4398, + 0, + 4392, + 4396, + 4407, + 4402, + 0, + 4396, + 4400, + 4411, + 4407, + 0, + 4400, + 4404, + 4418, + 4411, + 0, + 4404, + 4408, + 4422, + 4418, + 0, + 4408, + 4413, + 4426, + 4422, + 0, + 4413, + 4417, + 4429, + 4426, + 0, + 4417, + 4431, + 4440, + 4429, + 0, + 4431, + 4442, + 4467, + 4440, + 0, + 4442, + 4446, + 4474, + 4467, + 0, + 4446, + 4450, + 4481, + 4474, + 0, + 4450, + 4454, + 4488, + 4481, + 0, + 4454, + 4457, + 4491, + 4488, + 0, + 4457, + 4463, + 4495, + 4491, + 0, + 4463, + 4466, + 4498, + 4495, + 0, + 4466, + 4464, + 4496, + 4498, + 0, + 4464, + 4462, + 4494, + 4496, + 0, + 4462, + 4458, + 4492, + 4494, + 0, + 4458, + 4456, + 4490, + 4492, + 0, + 4456, + 4452, + 4486, + 4490, + 0, + 4452, + 4447, + 4476, + 4486, + 0, + 4447, + 4443, + 4470, + 4476, + 0, + 4443, + 4439, + 4461, + 4470, + 0, + 4439, + 4437, + 4451, + 4461, + 0, + 4437, + 4434, + 4445, + 4451, + 0, + 4434, + 4433, + 4441, + 4445, + 0, + 4433, + 4415, + 4427, + 4441, + 0, + 4415, + 4412, + 4425, + 4427, + 0, + 4425, + 4430, + 4550, + 4546, + 0, + 4430, + 4448, + 4557, + 4550, + 0, + 4448, + 4459, + 4559, + 4557, + 0, + 4459, + 4471, + 4563, + 4559, + 0, + 4471, + 4480, + 4566, + 4563, + 0, + 4480, + 4489, + 4570, + 4566, + 0, + 4489, + 4497, + 4577, + 4570, + 0, + 4497, + 4500, + 4581, + 4577, + 0, + 4500, + 4502, + 4583, + 4581, + 0, + 4502, + 4504, + 4585, + 4583, + 0, + 4504, + 4506, + 4587, + 4585, + 0, + 4506, + 4508, + 4589, + 4587, + 0, + 4508, + 4510, + 4591, + 4589, + 0, + 4510, + 4509, + 4592, + 4591, + 0, + 4509, + 4507, + 4590, + 4592, + 0, + 4507, + 4505, + 4588, + 4590, + 0, + 4505, + 4503, + 4586, + 4588, + 0, + 4503, + 4501, + 4584, + 4586, + 0, + 4501, + 4499, + 4582, + 4584, + 0, + 4499, + 4493, + 4576, + 4582, + 0, + 4493, + 4487, + 4569, + 4576, + 0, + 4487, + 4435, + 4553, + 4569, + 0, + 4435, + 4432, + 4552, + 4553, + 0, + 4432, + 4428, + 4549, + 4552, + 0, + 4428, + 4423, + 4545, + 4549, + 0, + 4423, + 4420, + 4543, + 4545, + 0, + 4420, + 4416, + 4541, + 4543, + 0, + 4416, + 4409, + 4539, + 4541, + 0, + 4409, + 4405, + 4537, + 4539, + 0, + 4405, + 4401, + 4535, + 4537, + 0, + 4401, + 4397, + 4533, + 4535, + 0, + 4397, + 4393, + 4531, + 4533, + 0, + 4393, + 4389, + 4529, + 4531, + 0, + 4389, + 4385, + 4527, + 4529, + 0, + 4385, + 4382, + 4526, + 4527, + 0, + 4382, + 4378, + 4524, + 4526, + 0, + 4378, + 4374, + 4522, + 4524, + 0, + 4374, + 4370, + 4520, + 4522, + 0, + 4370, + 4366, + 4518, + 4520, + 0, + 4366, + 4362, + 4516, + 4518, + 0, + 4362, + 4358, + 4514, + 4516, + 0, + 4358, + 4350, + 4511, + 4514, + 0, + 4350, + 4351, + 4512, + 4511, + 0, + 4351, + 4352, + 4513, + 4512, + 0, + 4352, + 4361, + 4515, + 4513, + 0, + 4361, + 4365, + 4517, + 4515, + 0, + 4365, + 4369, + 4519, + 4517, + 0, + 4369, + 4373, + 4521, + 4519, + 0, + 4373, + 4377, + 4523, + 4521, + 0, + 4377, + 4381, + 4525, + 4523, + 0, + 4381, + 4386, + 4528, + 4525, + 0, + 4386, + 4390, + 4530, + 4528, + 0, + 4390, + 4394, + 4532, + 4530, + 0, + 4394, + 4398, + 4534, + 4532, + 0, + 4398, + 4402, + 4536, + 4534, + 0, + 4402, + 4407, + 4538, + 4536, + 0, + 4407, + 4411, + 4540, + 4538, + 0, + 4411, + 4418, + 4542, + 4540, + 0, + 4418, + 4422, + 4544, + 4542, + 0, + 4422, + 4426, + 4548, + 4544, + 0, + 4426, + 4429, + 4551, + 4548, + 0, + 4429, + 4440, + 4555, + 4551, + 0, + 4440, + 4467, + 4562, + 4555, + 0, + 4467, + 4474, + 4564, + 4562, + 0, + 4474, + 4481, + 4567, + 4564, + 0, + 4481, + 4488, + 4571, + 4567, + 0, + 4488, + 4491, + 4574, + 4571, + 0, + 4491, + 4495, + 4578, + 4574, + 0, + 4495, + 4498, + 4580, + 4578, + 0, + 4498, + 4496, + 4579, + 4580, + 0, + 4496, + 4494, + 4575, + 4579, + 0, + 4494, + 4492, + 4573, + 4575, + 0, + 4492, + 4490, + 4572, + 4573, + 0, + 4490, + 4486, + 4568, + 4572, + 0, + 4486, + 4476, + 4565, + 4568, + 0, + 4476, + 4470, + 4561, + 4565, + 0, + 4470, + 4461, + 4560, + 4561, + 0, + 4461, + 4451, + 4558, + 4560, + 0, + 4451, + 4445, + 4556, + 4558, + 0, + 4445, + 4441, + 4554, + 4556, + 0, + 4441, + 4427, + 4547, + 4554, + 0, + 4427, + 4425, + 4546, + 4547, + 0, + 4546, + 4550, + 4630, + 4626, + 0, + 4550, + 4557, + 4639, + 4630, + 0, + 4557, + 4559, + 4641, + 4639, + 0, + 4559, + 4563, + 4644, + 4641, + 0, + 4563, + 4566, + 4647, + 4644, + 0, + 4566, + 4570, + 4651, + 4647, + 0, + 4570, + 4577, + 4656, + 4651, + 0, + 4577, + 4581, + 4663, + 4656, + 0, + 4581, + 4583, + 4664, + 4663, + 0, + 4583, + 4585, + 4667, + 4664, + 0, + 4585, + 4587, + 4669, + 4667, + 0, + 4587, + 4589, + 4671, + 4669, + 0, + 4589, + 4591, + 4673, + 4671, + 0, + 4591, + 4592, + 4674, + 4673, + 0, + 4592, + 4590, + 4672, + 4674, + 0, + 4590, + 4588, + 4670, + 4672, + 0, + 4588, + 4586, + 4668, + 4670, + 0, + 4586, + 4584, + 4666, + 4668, + 0, + 4584, + 4582, + 4665, + 4666, + 0, + 4582, + 4576, + 4662, + 4665, + 0, + 4576, + 4569, + 4653, + 4662, + 0, + 4569, + 4553, + 4635, + 4653, + 0, + 4553, + 4552, + 4634, + 4635, + 0, + 4552, + 4549, + 4632, + 4634, + 0, + 4549, + 4545, + 4629, + 4632, + 0, + 4545, + 4543, + 4625, + 4629, + 0, + 4543, + 4541, + 4623, + 4625, + 0, + 4541, + 4539, + 4621, + 4623, + 0, + 4539, + 4537, + 4619, + 4621, + 0, + 4537, + 4535, + 4617, + 4619, + 0, + 4535, + 4533, + 4616, + 4617, + 0, + 4533, + 4531, + 4613, + 4616, + 0, + 4531, + 4529, + 4611, + 4613, + 0, + 4529, + 4527, + 4609, + 4611, + 0, + 4527, + 4526, + 4608, + 4609, + 0, + 4526, + 4524, + 4606, + 4608, + 0, + 4524, + 4522, + 4604, + 4606, + 0, + 4522, + 4520, + 4602, + 4604, + 0, + 4520, + 4518, + 4600, + 4602, + 0, + 4518, + 4516, + 4598, + 4600, + 0, + 4516, + 4514, + 4596, + 4598, + 0, + 4514, + 4511, + 4593, + 4596, + 0, + 4511, + 4512, + 4594, + 4593, + 0, + 4512, + 4513, + 4595, + 4594, + 0, + 4513, + 4515, + 4597, + 4595, + 0, + 4515, + 4517, + 4599, + 4597, + 0, + 4517, + 4519, + 4601, + 4599, + 0, + 4519, + 4521, + 4603, + 4601, + 0, + 4521, + 4523, + 4605, + 4603, + 0, + 4523, + 4525, + 4607, + 4605, + 0, + 4525, + 4528, + 4610, + 4607, + 0, + 4528, + 4530, + 4612, + 4610, + 0, + 4530, + 4532, + 4614, + 4612, + 0, + 4532, + 4534, + 4615, + 4614, + 0, + 4534, + 4536, + 4618, + 4615, + 0, + 4536, + 4538, + 4620, + 4618, + 0, + 4538, + 4540, + 4622, + 4620, + 0, + 4540, + 4542, + 4624, + 4622, + 0, + 4542, + 4544, + 4628, + 4624, + 0, + 4544, + 4548, + 4631, + 4628, + 0, + 4548, + 4551, + 4633, + 4631, + 0, + 4551, + 4555, + 4638, + 4633, + 0, + 4555, + 4562, + 4645, + 4638, + 0, + 4562, + 4564, + 4648, + 4645, + 0, + 4564, + 4567, + 4650, + 4648, + 0, + 4567, + 4571, + 4654, + 4650, + 0, + 4571, + 4574, + 4657, + 4654, + 0, + 4574, + 4578, + 4660, + 4657, + 0, + 4578, + 4580, + 4661, + 4660, + 0, + 4580, + 4579, + 4659, + 4661, + 0, + 4579, + 4575, + 4658, + 4659, + 0, + 4575, + 4573, + 4655, + 4658, + 0, + 4573, + 4572, + 4652, + 4655, + 0, + 4572, + 4568, + 4649, + 4652, + 0, + 4568, + 4565, + 4646, + 4649, + 0, + 4565, + 4561, + 4643, + 4646, + 0, + 4561, + 4560, + 4642, + 4643, + 0, + 4560, + 4558, + 4640, + 4642, + 0, + 4558, + 4556, + 4637, + 4640, + 0, + 4556, + 4554, + 4636, + 4637, + 0, + 4554, + 4547, + 4627, + 4636, + 0, + 4547, + 4546, + 4626, + 4627, + 0, + 4626, + 4630, + 4711, + 4707, + 0, + 4630, + 4639, + 4721, + 4711, + 0, + 4639, + 4641, + 4723, + 4721, + 0, + 4641, + 4644, + 4725, + 4723, + 0, + 4644, + 4647, + 4730, + 4725, + 0, + 4647, + 4651, + 4733, + 4730, + 0, + 4651, + 4656, + 4741, + 4733, + 0, + 4656, + 4663, + 4747, + 4741, + 0, + 4663, + 4664, + 4749, + 4747, + 0, + 4664, + 4667, + 4751, + 4749, + 0, + 4667, + 4669, + 4753, + 4751, + 0, + 4669, + 4671, + 4755, + 4753, + 0, + 4671, + 4673, + 4757, + 4755, + 0, + 4673, + 4674, + 4759, + 4757, + 0, + 4674, + 4672, + 4758, + 4759, + 0, + 4672, + 4670, + 4756, + 4758, + 0, + 4670, + 4668, + 4754, + 4756, + 0, + 4668, + 4666, + 4752, + 4754, + 0, + 4666, + 4665, + 4750, + 4752, + 0, + 4665, + 4662, + 4748, + 4750, + 0, + 4662, + 4653, + 4738, + 4748, + 0, + 4653, + 4635, + 4717, + 4738, + 0, + 4635, + 4634, + 4716, + 4717, + 0, + 4634, + 4632, + 4714, + 4716, + 0, + 4632, + 4629, + 4712, + 4714, + 0, + 4629, + 4625, + 4708, + 4712, + 0, + 4625, + 4623, + 4705, + 4708, + 0, + 4623, + 4621, + 4703, + 4705, + 0, + 4621, + 4619, + 4701, + 4703, + 0, + 4619, + 4617, + 4699, + 4701, + 0, + 4617, + 4616, + 4698, + 4699, + 0, + 4616, + 4613, + 4695, + 4698, + 0, + 4613, + 4611, + 4693, + 4695, + 0, + 4611, + 4609, + 4691, + 4693, + 0, + 4609, + 4608, + 4690, + 4691, + 0, + 4608, + 4606, + 4688, + 4690, + 0, + 4606, + 4604, + 4686, + 4688, + 0, + 4604, + 4602, + 4684, + 4686, + 0, + 4602, + 4600, + 4682, + 4684, + 0, + 4600, + 4598, + 4680, + 4682, + 0, + 4598, + 4596, + 4678, + 4680, + 0, + 4596, + 4593, + 4675, + 4678, + 0, + 4593, + 4594, + 4676, + 4675, + 0, + 4594, + 4595, + 4677, + 4676, + 0, + 4595, + 4597, + 4679, + 4677, + 0, + 4597, + 4599, + 4681, + 4679, + 0, + 4599, + 4601, + 4683, + 4681, + 0, + 4601, + 4603, + 4685, + 4683, + 0, + 4603, + 4605, + 4687, + 4685, + 0, + 4605, + 4607, + 4689, + 4687, + 0, + 4607, + 4610, + 4692, + 4689, + 0, + 4610, + 4612, + 4694, + 4692, + 0, + 4612, + 4614, + 4696, + 4694, + 0, + 4614, + 4615, + 4697, + 4696, + 0, + 4615, + 4618, + 4700, + 4697, + 0, + 4618, + 4620, + 4702, + 4700, + 0, + 4620, + 4622, + 4704, + 4702, + 0, + 4622, + 4624, + 4706, + 4704, + 0, + 4624, + 4628, + 4710, + 4706, + 0, + 4628, + 4631, + 4713, + 4710, + 0, + 4631, + 4633, + 4715, + 4713, + 0, + 4633, + 4638, + 4720, + 4715, + 0, + 4638, + 4645, + 4727, + 4720, + 0, + 4645, + 4648, + 4731, + 4727, + 0, + 4648, + 4650, + 4734, + 4731, + 0, + 4650, + 4654, + 4739, + 4734, + 0, + 4654, + 4657, + 4743, + 4739, + 0, + 4657, + 4660, + 4745, + 4743, + 0, + 4660, + 4661, + 4746, + 4745, + 0, + 4661, + 4659, + 4744, + 4746, + 0, + 4659, + 4658, + 4742, + 4744, + 0, + 4658, + 4655, + 4740, + 4742, + 0, + 4655, + 4652, + 4736, + 4740, + 0, + 4652, + 4649, + 4732, + 4736, + 0, + 4649, + 4646, + 4728, + 4732, + 0, + 4646, + 4643, + 4726, + 4728, + 0, + 4643, + 4642, + 4724, + 4726, + 0, + 4642, + 4640, + 4722, + 4724, + 0, + 4640, + 4637, + 4719, + 4722, + 0, + 4637, + 4636, + 4718, + 4719, + 0, + 4636, + 4627, + 4709, + 4718, + 0, + 4627, + 4626, + 4707, + 4709, + 0, + 4707, + 4711, + 4793, + 4789, + 0, + 4711, + 4721, + 4802, + 4793, + 0, + 4721, + 4723, + 4805, + 4802, + 0, + 4723, + 4725, + 4807, + 4805, + 0, + 4725, + 4730, + 4811, + 4807, + 0, + 4730, + 4733, + 4814, + 4811, + 0, + 4733, + 4741, + 4820, + 4814, + 0, + 4741, + 4747, + 4826, + 4820, + 0, + 4747, + 4749, + 4828, + 4826, + 0, + 4749, + 4751, + 4830, + 4828, + 0, + 4751, + 4753, + 4832, + 4830, + 0, + 4753, + 4755, + 4834, + 4832, + 0, + 4755, + 4757, + 4836, + 4834, + 0, + 4757, + 4759, + 4838, + 4836, + 0, + 4759, + 4758, + 4837, + 4838, + 0, + 4758, + 4756, + 4835, + 4837, + 0, + 4756, + 4754, + 4833, + 4835, + 0, + 4754, + 4752, + 4831, + 4833, + 0, + 4752, + 4750, + 4829, + 4831, + 0, + 4750, + 4748, + 4827, + 4829, + 0, + 4748, + 4738, + 4819, + 4827, + 0, + 4738, + 4717, + 4799, + 4819, + 0, + 4717, + 4716, + 4798, + 4799, + 0, + 4716, + 4714, + 4796, + 4798, + 0, + 4714, + 4712, + 4794, + 4796, + 0, + 4712, + 4708, + 4791, + 4794, + 0, + 4708, + 4705, + 4787, + 4791, + 0, + 4705, + 4703, + 4785, + 4787, + 0, + 4703, + 4701, + 4783, + 4785, + 0, + 4701, + 4699, + 4781, + 4783, + 0, + 4699, + 4698, + 4780, + 4781, + 0, + 4698, + 4695, + 4777, + 4780, + 0, + 4695, + 4693, + 4775, + 4777, + 0, + 4693, + 4691, + 4773, + 4775, + 0, + 4691, + 4690, + 4772, + 4773, + 0, + 4690, + 4688, + 4770, + 4772, + 0, + 4688, + 4686, + 4768, + 4770, + 0, + 4686, + 4684, + 4766, + 4768, + 0, + 4684, + 4682, + 4764, + 4766, + 0, + 4682, + 4680, + 4762, + 4764, + 0, + 4680, + 4678, + 4760, + 4762, + 0, + 4678, + 4675, + 4729, + 4760, + 0, + 4675, + 4676, + 4735, + 4729, + 0, + 4676, + 4677, + 4737, + 4735, + 0, + 4677, + 4679, + 4761, + 4737, + 0, + 4679, + 4681, + 4763, + 4761, + 0, + 4681, + 4683, + 4765, + 4763, + 0, + 4683, + 4685, + 4767, + 4765, + 0, + 4685, + 4687, + 4769, + 4767, + 0, + 4687, + 4689, + 4771, + 4769, + 0, + 4689, + 4692, + 4774, + 4771, + 0, + 4692, + 4694, + 4776, + 4774, + 0, + 4694, + 4696, + 4778, + 4776, + 0, + 4696, + 4697, + 4779, + 4778, + 0, + 4697, + 4700, + 4782, + 4779, + 0, + 4700, + 4702, + 4784, + 4782, + 0, + 4702, + 4704, + 4786, + 4784, + 0, + 4704, + 4706, + 4788, + 4786, + 0, + 4706, + 4710, + 4792, + 4788, + 0, + 4710, + 4713, + 4795, + 4792, + 0, + 4713, + 4715, + 4797, + 4795, + 0, + 4715, + 4720, + 4803, + 4797, + 0, + 4720, + 4727, + 4809, + 4803, + 0, + 4727, + 4731, + 4812, + 4809, + 0, + 4731, + 4734, + 4815, + 4812, + 0, + 4734, + 4739, + 4817, + 4815, + 0, + 4739, + 4743, + 4822, + 4817, + 0, + 4743, + 4745, + 4824, + 4822, + 0, + 4745, + 4746, + 4825, + 4824, + 0, + 4746, + 4744, + 4823, + 4825, + 0, + 4744, + 4742, + 4821, + 4823, + 0, + 4742, + 4740, + 4818, + 4821, + 0, + 4740, + 4736, + 4816, + 4818, + 0, + 4736, + 4732, + 4813, + 4816, + 0, + 4732, + 4728, + 4810, + 4813, + 0, + 4728, + 4726, + 4808, + 4810, + 0, + 4726, + 4724, + 4806, + 4808, + 0, + 4724, + 4722, + 4804, + 4806, + 0, + 4722, + 4719, + 4801, + 4804, + 0, + 4719, + 4718, + 4800, + 4801, + 0, + 4718, + 4709, + 4790, + 4800, + 0, + 4709, + 4707, + 4789, + 4790, + 0, + 4789, + 4793, + 4872, + 4869, + 0, + 4793, + 4802, + 4884, + 4872, + 0, + 4802, + 4805, + 4887, + 4884, + 0, + 4805, + 4807, + 4889, + 4887, + 0, + 4807, + 4811, + 4892, + 4889, + 0, + 4811, + 4814, + 4895, + 4892, + 0, + 4814, + 4820, + 4899, + 4895, + 0, + 4820, + 4826, + 4906, + 4899, + 0, + 4826, + 4828, + 4909, + 4906, + 0, + 4828, + 4830, + 4911, + 4909, + 0, + 4830, + 4832, + 4913, + 4911, + 0, + 4832, + 4834, + 4915, + 4913, + 0, + 4834, + 4836, + 4917, + 4915, + 0, + 4836, + 4838, + 4919, + 4917, + 0, + 4838, + 4837, + 4920, + 4919, + 0, + 4837, + 4835, + 4918, + 4920, + 0, + 4835, + 4833, + 4916, + 4918, + 0, + 4833, + 4831, + 4914, + 4916, + 0, + 4831, + 4829, + 4912, + 4914, + 0, + 4829, + 4827, + 4910, + 4912, + 0, + 4827, + 4819, + 4903, + 4910, + 0, + 4819, + 4799, + 4883, + 4903, + 0, + 4799, + 4798, + 4880, + 4883, + 0, + 4798, + 4796, + 4878, + 4880, + 0, + 4796, + 4794, + 4876, + 4878, + 0, + 4794, + 4791, + 4874, + 4876, + 0, + 4791, + 4787, + 4871, + 4874, + 0, + 4787, + 4785, + 4867, + 4871, + 0, + 4785, + 4783, + 4865, + 4867, + 0, + 4783, + 4781, + 4863, + 4865, + 0, + 4781, + 4780, + 4862, + 4863, + 0, + 4780, + 4777, + 4859, + 4862, + 0, + 4777, + 4775, + 4857, + 4859, + 0, + 4775, + 4773, + 4856, + 4857, + 0, + 4773, + 4772, + 4854, + 4856, + 0, + 4772, + 4770, + 4852, + 4854, + 0, + 4770, + 4768, + 4850, + 4852, + 0, + 4768, + 4766, + 4848, + 4850, + 0, + 4766, + 4764, + 4846, + 4848, + 0, + 4764, + 4762, + 4844, + 4846, + 0, + 4762, + 4760, + 4842, + 4844, + 0, + 4760, + 4729, + 4839, + 4842, + 0, + 4729, + 4735, + 4840, + 4839, + 0, + 4735, + 4737, + 4841, + 4840, + 0, + 4737, + 4761, + 4843, + 4841, + 0, + 4761, + 4763, + 4845, + 4843, + 0, + 4763, + 4765, + 4847, + 4845, + 0, + 4765, + 4767, + 4849, + 4847, + 0, + 4767, + 4769, + 4851, + 4849, + 0, + 4769, + 4771, + 4853, + 4851, + 0, + 4771, + 4774, + 4855, + 4853, + 0, + 4774, + 4776, + 4858, + 4855, + 0, + 4776, + 4778, + 4860, + 4858, + 0, + 4778, + 4779, + 4861, + 4860, + 0, + 4779, + 4782, + 4864, + 4861, + 0, + 4782, + 4784, + 4866, + 4864, + 0, + 4784, + 4786, + 4868, + 4866, + 0, + 4786, + 4788, + 4873, + 4868, + 0, + 4788, + 4792, + 4875, + 4873, + 0, + 4792, + 4795, + 4877, + 4875, + 0, + 4795, + 4797, + 4879, + 4877, + 0, + 4797, + 4803, + 4886, + 4879, + 0, + 4803, + 4809, + 4893, + 4886, + 0, + 4809, + 4812, + 4896, + 4893, + 0, + 4812, + 4815, + 4898, + 4896, + 0, + 4815, + 4817, + 4901, + 4898, + 0, + 4817, + 4822, + 4905, + 4901, + 0, + 4822, + 4824, + 4908, + 4905, + 0, + 4824, + 4825, + 4907, + 4908, + 0, + 4825, + 4823, + 4904, + 4907, + 0, + 4823, + 4821, + 4902, + 4904, + 0, + 4821, + 4818, + 4900, + 4902, + 0, + 4818, + 4816, + 4897, + 4900, + 0, + 4816, + 4813, + 4894, + 4897, + 0, + 4813, + 4810, + 4891, + 4894, + 0, + 4810, + 4808, + 4890, + 4891, + 0, + 4808, + 4806, + 4888, + 4890, + 0, + 4806, + 4804, + 4885, + 4888, + 0, + 4804, + 4801, + 4882, + 4885, + 0, + 4801, + 4800, + 4881, + 4882, + 0, + 4800, + 4790, + 4870, + 4881, + 0, + 4790, + 4789, + 4869, + 4870, + 0, + 4869, + 4872, + 4953, + 4949, + 0, + 4872, + 4884, + 4966, + 4953, + 0, + 4884, + 4887, + 4971, + 4966, + 0, + 4887, + 4889, + 4974, + 4971, + 0, + 4889, + 4892, + 4977, + 4974, + 0, + 4892, + 4895, + 4981, + 4977, + 0, + 4895, + 4899, + 4984, + 4981, + 0, + 4899, + 4906, + 4991, + 4984, + 0, + 4906, + 4909, + 4997, + 4991, + 0, + 4909, + 4911, + 5000, + 4997, + 0, + 4911, + 4913, + 5003, + 5000, + 0, + 4913, + 4915, + 5005, + 5003, + 0, + 4915, + 4917, + 5008, + 5005, + 0, + 4917, + 4919, + 5010, + 5008, + 0, + 4919, + 4920, + 5011, + 5010, + 0, + 4920, + 4918, + 5009, + 5011, + 0, + 4918, + 4916, + 5007, + 5009, + 0, + 4916, + 4914, + 5004, + 5007, + 0, + 4914, + 4912, + 5002, + 5004, + 0, + 4912, + 4910, + 4999, + 5002, + 0, + 4910, + 4903, + 4993, + 4999, + 0, + 4903, + 4883, + 4967, + 4993, + 0, + 4883, + 4880, + 4963, + 4967, + 0, + 4880, + 4878, + 4960, + 4963, + 0, + 4878, + 4876, + 4958, + 4960, + 0, + 4876, + 4874, + 4956, + 4958, + 0, + 4874, + 4871, + 4954, + 4956, + 0, + 4871, + 4867, + 4950, + 4954, + 0, + 4867, + 4865, + 4947, + 4950, + 0, + 4865, + 4863, + 4945, + 4947, + 0, + 4863, + 4862, + 4944, + 4945, + 0, + 4862, + 4859, + 4941, + 4944, + 0, + 4859, + 4857, + 4939, + 4941, + 0, + 4857, + 4856, + 4938, + 4939, + 0, + 4856, + 4854, + 4936, + 4938, + 0, + 4854, + 4852, + 4934, + 4936, + 0, + 4852, + 4850, + 4932, + 4934, + 0, + 4850, + 4848, + 4930, + 4932, + 0, + 4848, + 4846, + 4928, + 4930, + 0, + 4846, + 4844, + 4926, + 4928, + 0, + 4844, + 4842, + 4924, + 4926, + 0, + 4842, + 4839, + 4921, + 4924, + 0, + 4839, + 4840, + 4922, + 4921, + 0, + 4840, + 4841, + 4923, + 4922, + 0, + 4841, + 4843, + 4925, + 4923, + 0, + 4843, + 4845, + 4927, + 4925, + 0, + 4845, + 4847, + 4929, + 4927, + 0, + 4847, + 4849, + 4931, + 4929, + 0, + 4849, + 4851, + 4933, + 4931, + 0, + 4851, + 4853, + 4935, + 4933, + 0, + 4853, + 4855, + 4937, + 4935, + 0, + 4855, + 4858, + 4940, + 4937, + 0, + 4858, + 4860, + 4942, + 4940, + 0, + 4860, + 4861, + 4943, + 4942, + 0, + 4861, + 4864, + 4946, + 4943, + 0, + 4864, + 4866, + 4948, + 4946, + 0, + 4866, + 4868, + 4952, + 4948, + 0, + 4868, + 4873, + 4955, + 4952, + 0, + 4873, + 4875, + 4957, + 4955, + 0, + 4875, + 4877, + 4959, + 4957, + 0, + 4877, + 4879, + 4961, + 4959, + 0, + 4879, + 4886, + 4972, + 4961, + 0, + 4886, + 4893, + 4978, + 4972, + 0, + 4893, + 4896, + 4982, + 4978, + 0, + 4896, + 4898, + 4986, + 4982, + 0, + 4898, + 4901, + 4990, + 4986, + 0, + 4901, + 4905, + 4994, + 4990, + 0, + 4905, + 4908, + 4996, + 4994, + 0, + 4908, + 4907, + 4995, + 4996, + 0, + 4907, + 4904, + 4992, + 4995, + 0, + 4904, + 4902, + 4989, + 4992, + 0, + 4902, + 4900, + 4987, + 4989, + 0, + 4900, + 4897, + 4983, + 4987, + 0, + 4897, + 4894, + 4980, + 4983, + 0, + 4894, + 4891, + 4976, + 4980, + 0, + 4891, + 4890, + 4975, + 4976, + 0, + 4890, + 4888, + 4973, + 4975, + 0, + 4888, + 4885, + 4970, + 4973, + 0, + 4885, + 4882, + 4965, + 4970, + 0, + 4882, + 4881, + 4962, + 4965, + 0, + 4881, + 4870, + 4951, + 4962, + 0, + 4870, + 4869, + 4949, + 4951, + 0, + 4949, + 4953, + 5035, + 5031, + 0, + 4953, + 4966, + 5047, + 5035, + 0, + 4966, + 4971, + 5050, + 5047, + 0, + 4971, + 4974, + 5053, + 5050, + 0, + 4974, + 4977, + 5056, + 5053, + 0, + 4977, + 4981, + 5059, + 5056, + 0, + 4981, + 4984, + 5062, + 5059, + 0, + 4984, + 4991, + 5067, + 5062, + 0, + 4991, + 4997, + 5073, + 5067, + 0, + 4997, + 5000, + 5075, + 5073, + 0, + 5000, + 5003, + 5077, + 5075, + 0, + 5003, + 5005, + 5079, + 5077, + 0, + 5005, + 5008, + 5081, + 5079, + 0, + 5008, + 5010, + 5083, + 5081, + 0, + 5010, + 5011, + 5084, + 5083, + 0, + 5011, + 5009, + 5082, + 5084, + 0, + 5009, + 5007, + 5080, + 5082, + 0, + 5007, + 5004, + 5078, + 5080, + 0, + 5004, + 5002, + 5076, + 5078, + 0, + 5002, + 4999, + 5074, + 5076, + 0, + 4999, + 4993, + 5070, + 5074, + 0, + 4993, + 4967, + 5048, + 5070, + 0, + 4967, + 4963, + 5045, + 5048, + 0, + 4963, + 4960, + 5042, + 5045, + 0, + 4960, + 4958, + 5040, + 5042, + 0, + 4958, + 4956, + 5038, + 5040, + 0, + 4956, + 4954, + 5036, + 5038, + 0, + 4954, + 4950, + 5032, + 5036, + 0, + 4950, + 4947, + 5029, + 5032, + 0, + 4947, + 4945, + 5027, + 5029, + 0, + 4945, + 4944, + 5026, + 5027, + 0, + 4944, + 4941, + 5023, + 5026, + 0, + 4941, + 4939, + 5021, + 5023, + 0, + 4939, + 4938, + 5020, + 5021, + 0, + 4938, + 4936, + 5018, + 5020, + 0, + 4936, + 4934, + 5016, + 5018, + 0, + 4934, + 4932, + 5014, + 5016, + 0, + 4932, + 4930, + 5012, + 5014, + 0, + 4930, + 4928, + 5001, + 5012, + 0, + 4928, + 4926, + 4988, + 5001, + 0, + 4926, + 4924, + 4979, + 4988, + 0, + 4924, + 4921, + 4964, + 4979, + 0, + 4921, + 4922, + 4968, + 4964, + 0, + 4922, + 4923, + 4969, + 4968, + 0, + 4923, + 4925, + 4985, + 4969, + 0, + 4925, + 4927, + 4998, + 4985, + 0, + 4927, + 4929, + 5006, + 4998, + 0, + 4929, + 4931, + 5013, + 5006, + 0, + 4931, + 4933, + 5015, + 5013, + 0, + 4933, + 4935, + 5017, + 5015, + 0, + 4935, + 4937, + 5019, + 5017, + 0, + 4937, + 4940, + 5022, + 5019, + 0, + 4940, + 4942, + 5024, + 5022, + 0, + 4942, + 4943, + 5025, + 5024, + 0, + 4943, + 4946, + 5028, + 5025, + 0, + 4946, + 4948, + 5030, + 5028, + 0, + 4948, + 4952, + 5034, + 5030, + 0, + 4952, + 4955, + 5037, + 5034, + 0, + 4955, + 4957, + 5039, + 5037, + 0, + 4957, + 4959, + 5041, + 5039, + 0, + 4959, + 4961, + 5043, + 5041, + 0, + 4961, + 4972, + 5051, + 5043, + 0, + 4972, + 4978, + 5057, + 5051, + 0, + 4978, + 4982, + 5060, + 5057, + 0, + 4982, + 4986, + 5064, + 5060, + 0, + 4986, + 4990, + 5066, + 5064, + 0, + 4990, + 4994, + 5069, + 5066, + 0, + 4994, + 4996, + 5072, + 5069, + 0, + 4996, + 4995, + 5071, + 5072, + 0, + 4995, + 4992, + 5068, + 5071, + 0, + 4992, + 4989, + 5065, + 5068, + 0, + 4989, + 4987, + 5063, + 5065, + 0, + 4987, + 4983, + 5061, + 5063, + 0, + 4983, + 4980, + 5058, + 5061, + 0, + 4980, + 4976, + 5055, + 5058, + 0, + 4976, + 4975, + 5054, + 5055, + 0, + 4975, + 4973, + 5052, + 5054, + 0, + 4973, + 4970, + 5049, + 5052, + 0, + 4970, + 4965, + 5046, + 5049, + 0, + 4965, + 4962, + 5044, + 5046, + 0, + 4962, + 4951, + 5033, + 5044, + 0, + 4951, + 4949, + 5031, + 5033, + 0, + 5031, + 5035, + 5115, + 5111, + 0, + 5035, + 5047, + 5128, + 5115, + 0, + 5047, + 5050, + 5132, + 5128, + 0, + 5050, + 5053, + 5135, + 5132, + 0, + 5053, + 5056, + 5137, + 5135, + 0, + 5056, + 5059, + 5140, + 5137, + 0, + 5059, + 5062, + 5143, + 5140, + 0, + 5062, + 5067, + 5148, + 5143, + 0, + 5067, + 5073, + 5154, + 5148, + 0, + 5073, + 5075, + 5156, + 5154, + 0, + 5075, + 5077, + 5158, + 5156, + 0, + 5077, + 5079, + 5160, + 5158, + 0, + 5079, + 5081, + 5162, + 5160, + 0, + 5081, + 5083, + 5164, + 5162, + 0, + 5083, + 5084, + 5166, + 5164, + 0, + 5084, + 5082, + 5165, + 5166, + 0, + 5082, + 5080, + 5163, + 5165, + 0, + 5080, + 5078, + 5161, + 5163, + 0, + 5078, + 5076, + 5159, + 5161, + 0, + 5076, + 5074, + 5157, + 5159, + 0, + 5074, + 5070, + 5155, + 5157, + 0, + 5070, + 5048, + 5131, + 5155, + 0, + 5048, + 5045, + 5129, + 5131, + 0, + 5045, + 5042, + 5125, + 5129, + 0, + 5042, + 5040, + 5122, + 5125, + 0, + 5040, + 5038, + 5120, + 5122, + 0, + 5038, + 5036, + 5118, + 5120, + 0, + 5036, + 5032, + 5116, + 5118, + 0, + 5032, + 5029, + 5112, + 5116, + 0, + 5029, + 5027, + 5110, + 5112, + 0, + 5027, + 5026, + 5108, + 5110, + 0, + 5026, + 5023, + 5106, + 5108, + 0, + 5023, + 5021, + 5103, + 5106, + 0, + 5021, + 5020, + 5102, + 5103, + 0, + 5020, + 5018, + 5100, + 5102, + 0, + 5018, + 5016, + 5098, + 5100, + 0, + 5016, + 5014, + 5096, + 5098, + 0, + 5014, + 5012, + 5094, + 5096, + 0, + 5012, + 5001, + 5092, + 5094, + 0, + 5001, + 4988, + 5090, + 5092, + 0, + 4988, + 4979, + 5088, + 5090, + 0, + 4979, + 4964, + 5085, + 5088, + 0, + 4964, + 4968, + 5086, + 5085, + 0, + 4968, + 4969, + 5087, + 5086, + 0, + 4969, + 4985, + 5089, + 5087, + 0, + 4985, + 4998, + 5091, + 5089, + 0, + 4998, + 5006, + 5093, + 5091, + 0, + 5006, + 5013, + 5095, + 5093, + 0, + 5013, + 5015, + 5097, + 5095, + 0, + 5015, + 5017, + 5099, + 5097, + 0, + 5017, + 5019, + 5101, + 5099, + 0, + 5019, + 5022, + 5104, + 5101, + 0, + 5022, + 5024, + 5105, + 5104, + 0, + 5024, + 5025, + 5107, + 5105, + 0, + 5025, + 5028, + 5109, + 5107, + 0, + 5028, + 5030, + 5114, + 5109, + 0, + 5030, + 5034, + 5117, + 5114, + 0, + 5034, + 5037, + 5119, + 5117, + 0, + 5037, + 5039, + 5121, + 5119, + 0, + 5039, + 5041, + 5123, + 5121, + 0, + 5041, + 5043, + 5126, + 5123, + 0, + 5043, + 5051, + 5134, + 5126, + 0, + 5051, + 5057, + 5141, + 5134, + 0, + 5057, + 5060, + 5144, + 5141, + 0, + 5060, + 5064, + 5146, + 5144, + 0, + 5064, + 5066, + 5150, + 5146, + 0, + 5066, + 5069, + 5152, + 5150, + 0, + 5069, + 5072, + 5153, + 5152, + 0, + 5072, + 5071, + 5151, + 5153, + 0, + 5071, + 5068, + 5149, + 5151, + 0, + 5068, + 5065, + 5147, + 5149, + 0, + 5065, + 5063, + 5145, + 5147, + 0, + 5063, + 5061, + 5142, + 5145, + 0, + 5061, + 5058, + 5139, + 5142, + 0, + 5058, + 5055, + 5138, + 5139, + 0, + 5055, + 5054, + 5136, + 5138, + 0, + 5054, + 5052, + 5133, + 5136, + 0, + 5052, + 5049, + 5130, + 5133, + 0, + 5049, + 5046, + 5127, + 5130, + 0, + 5046, + 5044, + 5124, + 5127, + 0, + 5044, + 5033, + 5113, + 5124, + 0, + 5033, + 5031, + 5111, + 5113, + 0, + 5111, + 5115, + 5195, + 5193, + 0, + 5115, + 5128, + 5210, + 5195, + 0, + 5128, + 5132, + 5213, + 5210, + 0, + 5132, + 5135, + 5216, + 5213, + 0, + 5135, + 5137, + 5219, + 5216, + 0, + 5137, + 5140, + 5221, + 5219, + 0, + 5140, + 5143, + 5225, + 5221, + 0, + 5143, + 5148, + 5228, + 5225, + 0, + 5148, + 5154, + 5235, + 5228, + 0, + 5154, + 5156, + 5238, + 5235, + 0, + 5156, + 5158, + 5240, + 5238, + 0, + 5158, + 5160, + 5242, + 5240, + 0, + 5160, + 5162, + 5244, + 5242, + 0, + 5162, + 5164, + 5246, + 5244, + 0, + 5164, + 5166, + 5248, + 5246, + 0, + 5166, + 5165, + 5247, + 5248, + 0, + 5165, + 5163, + 5245, + 5247, + 0, + 5163, + 5161, + 5243, + 5245, + 0, + 5161, + 5159, + 5241, + 5243, + 0, + 5159, + 5157, + 5239, + 5241, + 0, + 5157, + 5155, + 5237, + 5239, + 0, + 5155, + 5131, + 5214, + 5237, + 0, + 5131, + 5129, + 5212, + 5214, + 0, + 5129, + 5125, + 5208, + 5212, + 0, + 5125, + 5122, + 5204, + 5208, + 0, + 5122, + 5120, + 5202, + 5204, + 0, + 5120, + 5118, + 5200, + 5202, + 0, + 5118, + 5116, + 5198, + 5200, + 0, + 5116, + 5112, + 5196, + 5198, + 0, + 5112, + 5110, + 5192, + 5196, + 0, + 5110, + 5108, + 5190, + 5192, + 0, + 5108, + 5106, + 5188, + 5190, + 0, + 5106, + 5103, + 5185, + 5188, + 0, + 5103, + 5102, + 5184, + 5185, + 0, + 5102, + 5100, + 5182, + 5184, + 0, + 5100, + 5098, + 5180, + 5182, + 0, + 5098, + 5096, + 5178, + 5180, + 0, + 5096, + 5094, + 5176, + 5178, + 0, + 5094, + 5092, + 5174, + 5176, + 0, + 5092, + 5090, + 5172, + 5174, + 0, + 5090, + 5088, + 5170, + 5172, + 0, + 5088, + 5085, + 5167, + 5170, + 0, + 5085, + 5086, + 5168, + 5167, + 0, + 5086, + 5087, + 5169, + 5168, + 0, + 5087, + 5089, + 5171, + 5169, + 0, + 5089, + 5091, + 5173, + 5171, + 0, + 5091, + 5093, + 5175, + 5173, + 0, + 5093, + 5095, + 5177, + 5175, + 0, + 5095, + 5097, + 5179, + 5177, + 0, + 5097, + 5099, + 5181, + 5179, + 0, + 5099, + 5101, + 5183, + 5181, + 0, + 5101, + 5104, + 5186, + 5183, + 0, + 5104, + 5105, + 5187, + 5186, + 0, + 5105, + 5107, + 5189, + 5187, + 0, + 5107, + 5109, + 5191, + 5189, + 0, + 5109, + 5114, + 5197, + 5191, + 0, + 5114, + 5117, + 5199, + 5197, + 0, + 5117, + 5119, + 5201, + 5199, + 0, + 5119, + 5121, + 5203, + 5201, + 0, + 5121, + 5123, + 5206, + 5203, + 0, + 5123, + 5126, + 5209, + 5206, + 0, + 5126, + 5134, + 5217, + 5209, + 0, + 5134, + 5141, + 5223, + 5217, + 0, + 5141, + 5144, + 5227, + 5223, + 0, + 5144, + 5146, + 5230, + 5227, + 0, + 5146, + 5150, + 5232, + 5230, + 0, + 5150, + 5152, + 5234, + 5232, + 0, + 5152, + 5153, + 5236, + 5234, + 0, + 5153, + 5151, + 5233, + 5236, + 0, + 5151, + 5149, + 5231, + 5233, + 0, + 5149, + 5147, + 5229, + 5231, + 0, + 5147, + 5145, + 5226, + 5229, + 0, + 5145, + 5142, + 5224, + 5226, + 0, + 5142, + 5139, + 5222, + 5224, + 0, + 5139, + 5138, + 5220, + 5222, + 0, + 5138, + 5136, + 5218, + 5220, + 0, + 5136, + 5133, + 5215, + 5218, + 0, + 5133, + 5130, + 5211, + 5215, + 0, + 5130, + 5127, + 5207, + 5211, + 0, + 5127, + 5124, + 5205, + 5207, + 0, + 5124, + 5113, + 5194, + 5205, + 0, + 5113, + 5111, + 5193, + 5194, + 0, + 5193, + 5195, + 5277, + 5273, + 0, + 5195, + 5210, + 5290, + 5277, + 0, + 5210, + 5213, + 5295, + 5290, + 0, + 5213, + 5216, + 5298, + 5295, + 0, + 5216, + 5219, + 5301, + 5298, + 0, + 5219, + 5221, + 5303, + 5301, + 0, + 5221, + 5225, + 5305, + 5303, + 0, + 5225, + 5228, + 5310, + 5305, + 0, + 5228, + 5235, + 5316, + 5310, + 0, + 5235, + 5238, + 5320, + 5316, + 0, + 5238, + 5240, + 5321, + 5320, + 0, + 5240, + 5242, + 5323, + 5321, + 0, + 5242, + 5244, + 5325, + 5323, + 0, + 5244, + 5246, + 5327, + 5325, + 0, + 5246, + 5248, + 5329, + 5327, + 0, + 5248, + 5247, + 5330, + 5329, + 0, + 5247, + 5245, + 5328, + 5330, + 0, + 5245, + 5243, + 5326, + 5328, + 0, + 5243, + 5241, + 5324, + 5326, + 0, + 5241, + 5239, + 5322, + 5324, + 0, + 5239, + 5237, + 5319, + 5322, + 0, + 5237, + 5214, + 5297, + 5319, + 0, + 5214, + 5212, + 5294, + 5297, + 0, + 5212, + 5208, + 5291, + 5294, + 0, + 5208, + 5204, + 5287, + 5291, + 0, + 5204, + 5202, + 5284, + 5287, + 0, + 5202, + 5200, + 5282, + 5284, + 0, + 5200, + 5198, + 5280, + 5282, + 0, + 5198, + 5196, + 5278, + 5280, + 0, + 5196, + 5192, + 5275, + 5278, + 0, + 5192, + 5190, + 5272, + 5275, + 0, + 5190, + 5188, + 5270, + 5272, + 0, + 5188, + 5185, + 5267, + 5270, + 0, + 5185, + 5184, + 5266, + 5267, + 0, + 5184, + 5182, + 5264, + 5266, + 0, + 5182, + 5180, + 5262, + 5264, + 0, + 5180, + 5178, + 5260, + 5262, + 0, + 5178, + 5176, + 5258, + 5260, + 0, + 5176, + 5174, + 5256, + 5258, + 0, + 5174, + 5172, + 5254, + 5256, + 0, + 5172, + 5170, + 5252, + 5254, + 0, + 5170, + 5167, + 5249, + 5252, + 0, + 5167, + 5168, + 5250, + 5249, + 0, + 5168, + 5169, + 5251, + 5250, + 0, + 5169, + 5171, + 5253, + 5251, + 0, + 5171, + 5173, + 5255, + 5253, + 0, + 5173, + 5175, + 5257, + 5255, + 0, + 5175, + 5177, + 5259, + 5257, + 0, + 5177, + 5179, + 5261, + 5259, + 0, + 5179, + 5181, + 5263, + 5261, + 0, + 5181, + 5183, + 5265, + 5263, + 0, + 5183, + 5186, + 5268, + 5265, + 0, + 5186, + 5187, + 5269, + 5268, + 0, + 5187, + 5189, + 5271, + 5269, + 0, + 5189, + 5191, + 5274, + 5271, + 0, + 5191, + 5197, + 5279, + 5274, + 0, + 5197, + 5199, + 5281, + 5279, + 0, + 5199, + 5201, + 5283, + 5281, + 0, + 5201, + 5203, + 5285, + 5283, + 0, + 5203, + 5206, + 5288, + 5285, + 0, + 5206, + 5209, + 5292, + 5288, + 0, + 5209, + 5217, + 5300, + 5292, + 0, + 5217, + 5223, + 5307, + 5300, + 0, + 5223, + 5227, + 5309, + 5307, + 0, + 5227, + 5230, + 5312, + 5309, + 0, + 5230, + 5232, + 5314, + 5312, + 0, + 5232, + 5234, + 5317, + 5314, + 0, + 5234, + 5236, + 5318, + 5317, + 0, + 5236, + 5233, + 5315, + 5318, + 0, + 5233, + 5231, + 5313, + 5315, + 0, + 5231, + 5229, + 5311, + 5313, + 0, + 5229, + 5226, + 5308, + 5311, + 0, + 5226, + 5224, + 5306, + 5308, + 0, + 5224, + 5222, + 5304, + 5306, + 0, + 5222, + 5220, + 5302, + 5304, + 0, + 5220, + 5218, + 5299, + 5302, + 0, + 5218, + 5215, + 5296, + 5299, + 0, + 5215, + 5211, + 5293, + 5296, + 0, + 5211, + 5207, + 5289, + 5293, + 0, + 5207, + 5205, + 5286, + 5289, + 0, + 5205, + 5194, + 5276, + 5286, + 0, + 5194, + 5193, + 5273, + 5276, + 0, + 5273, + 5277, + 5357, + 5354, + 0, + 5277, + 5290, + 5370, + 5357, + 0, + 5290, + 5295, + 5376, + 5370, + 0, + 5295, + 5298, + 5379, + 5376, + 0, + 5298, + 5301, + 5383, + 5379, + 0, + 5301, + 5303, + 5385, + 5383, + 0, + 5303, + 5305, + 5387, + 5385, + 0, + 5305, + 5310, + 5391, + 5387, + 0, + 5310, + 5316, + 5396, + 5391, + 0, + 5316, + 5320, + 5401, + 5396, + 0, + 5320, + 5321, + 5403, + 5401, + 0, + 5321, + 5323, + 5405, + 5403, + 0, + 5323, + 5325, + 5407, + 5405, + 0, + 5325, + 5327, + 5409, + 5407, + 0, + 5327, + 5329, + 5411, + 5409, + 0, + 5329, + 5330, + 5412, + 5411, + 0, + 5330, + 5328, + 5410, + 5412, + 0, + 5328, + 5326, + 5408, + 5410, + 0, + 5326, + 5324, + 5406, + 5408, + 0, + 5324, + 5322, + 5404, + 5406, + 0, + 5322, + 5319, + 5402, + 5404, + 0, + 5319, + 5297, + 5380, + 5402, + 0, + 5297, + 5294, + 5378, + 5380, + 0, + 5294, + 5291, + 5374, + 5378, + 0, + 5291, + 5287, + 5371, + 5374, + 0, + 5287, + 5284, + 5367, + 5371, + 0, + 5284, + 5282, + 5364, + 5367, + 0, + 5282, + 5280, + 5362, + 5364, + 0, + 5280, + 5278, + 5360, + 5362, + 0, + 5278, + 5275, + 5359, + 5360, + 0, + 5275, + 5272, + 5355, + 5359, + 0, + 5272, + 5270, + 5352, + 5355, + 0, + 5270, + 5267, + 5350, + 5352, + 0, + 5267, + 5266, + 5348, + 5350, + 0, + 5266, + 5264, + 5346, + 5348, + 0, + 5264, + 5262, + 5344, + 5346, + 0, + 5262, + 5260, + 5342, + 5344, + 0, + 5260, + 5258, + 5340, + 5342, + 0, + 5258, + 5256, + 5338, + 5340, + 0, + 5256, + 5254, + 5336, + 5338, + 0, + 5254, + 5252, + 5334, + 5336, + 0, + 5252, + 5249, + 5331, + 5334, + 0, + 5249, + 5250, + 5332, + 5331, + 0, + 5250, + 5251, + 5333, + 5332, + 0, + 5251, + 5253, + 5335, + 5333, + 0, + 5253, + 5255, + 5337, + 5335, + 0, + 5255, + 5257, + 5339, + 5337, + 0, + 5257, + 5259, + 5341, + 5339, + 0, + 5259, + 5261, + 5343, + 5341, + 0, + 5261, + 5263, + 5345, + 5343, + 0, + 5263, + 5265, + 5347, + 5345, + 0, + 5265, + 5268, + 5349, + 5347, + 0, + 5268, + 5269, + 5351, + 5349, + 0, + 5269, + 5271, + 5353, + 5351, + 0, + 5271, + 5274, + 5358, + 5353, + 0, + 5274, + 5279, + 5361, + 5358, + 0, + 5279, + 5281, + 5363, + 5361, + 0, + 5281, + 5283, + 5365, + 5363, + 0, + 5283, + 5285, + 5368, + 5365, + 0, + 5285, + 5288, + 5372, + 5368, + 0, + 5288, + 5292, + 5375, + 5372, + 0, + 5292, + 5300, + 5382, + 5375, + 0, + 5300, + 5307, + 5389, + 5382, + 0, + 5307, + 5309, + 5392, + 5389, + 0, + 5309, + 5312, + 5395, + 5392, + 0, + 5312, + 5314, + 5398, + 5395, + 0, + 5314, + 5317, + 5400, + 5398, + 0, + 5317, + 5318, + 5399, + 5400, + 0, + 5318, + 5315, + 5397, + 5399, + 0, + 5315, + 5313, + 5394, + 5397, + 0, + 5313, + 5311, + 5393, + 5394, + 0, + 5311, + 5308, + 5390, + 5393, + 0, + 5308, + 5306, + 5388, + 5390, + 0, + 5306, + 5304, + 5386, + 5388, + 0, + 5304, + 5302, + 5384, + 5386, + 0, + 5302, + 5299, + 5381, + 5384, + 0, + 5299, + 5296, + 5377, + 5381, + 0, + 5296, + 5293, + 5373, + 5377, + 0, + 5293, + 5289, + 5369, + 5373, + 0, + 5289, + 5286, + 5366, + 5369, + 0, + 5286, + 5276, + 5356, + 5366, + 0, + 5276, + 5273, + 5354, + 5356, + 0, + 5354, + 5357, + 5439, + 5435, + 0, + 5357, + 5370, + 5450, + 5439, + 0, + 5370, + 5376, + 5456, + 5450, + 0, + 5376, + 5379, + 5461, + 5456, + 0, + 5379, + 5383, + 5464, + 5461, + 0, + 5383, + 5385, + 5467, + 5464, + 0, + 5385, + 5387, + 5469, + 5467, + 0, + 5387, + 5391, + 5472, + 5469, + 0, + 5391, + 5396, + 5477, + 5472, + 0, + 5396, + 5401, + 5483, + 5477, + 0, + 5401, + 5403, + 5485, + 5483, + 0, + 5403, + 5405, + 5486, + 5485, + 0, + 5405, + 5407, + 5488, + 5486, + 0, + 5407, + 5409, + 5490, + 5488, + 0, + 5409, + 5411, + 5492, + 5490, + 0, + 5411, + 5412, + 5494, + 5492, + 0, + 5412, + 5410, + 5493, + 5494, + 0, + 5410, + 5408, + 5491, + 5493, + 0, + 5408, + 5406, + 5489, + 5491, + 0, + 5406, + 5404, + 5487, + 5489, + 0, + 5404, + 5402, + 5484, + 5487, + 0, + 5402, + 5380, + 5463, + 5484, + 0, + 5380, + 5378, + 5460, + 5463, + 0, + 5378, + 5374, + 5458, + 5460, + 0, + 5374, + 5371, + 5453, + 5458, + 0, + 5371, + 5367, + 5451, + 5453, + 0, + 5367, + 5364, + 5446, + 5451, + 0, + 5364, + 5362, + 5444, + 5446, + 0, + 5362, + 5360, + 5443, + 5444, + 0, + 5360, + 5359, + 5441, + 5443, + 0, + 5359, + 5355, + 5438, + 5441, + 0, + 5355, + 5352, + 5434, + 5438, + 0, + 5352, + 5350, + 5432, + 5434, + 0, + 5350, + 5348, + 5430, + 5432, + 0, + 5348, + 5346, + 5428, + 5430, + 0, + 5346, + 5344, + 5426, + 5428, + 0, + 5344, + 5342, + 5424, + 5426, + 0, + 5342, + 5340, + 5422, + 5424, + 0, + 5340, + 5338, + 5420, + 5422, + 0, + 5338, + 5336, + 5418, + 5420, + 0, + 5336, + 5334, + 5416, + 5418, + 0, + 5334, + 5331, + 5413, + 5416, + 0, + 5331, + 5332, + 5414, + 5413, + 0, + 5332, + 5333, + 5415, + 5414, + 0, + 5333, + 5335, + 5417, + 5415, + 0, + 5335, + 5337, + 5419, + 5417, + 0, + 5337, + 5339, + 5421, + 5419, + 0, + 5339, + 5341, + 5423, + 5421, + 0, + 5341, + 5343, + 5425, + 5423, + 0, + 5343, + 5345, + 5427, + 5425, + 0, + 5345, + 5347, + 5429, + 5427, + 0, + 5347, + 5349, + 5431, + 5429, + 0, + 5349, + 5351, + 5433, + 5431, + 0, + 5351, + 5353, + 5437, + 5433, + 0, + 5353, + 5358, + 5440, + 5437, + 0, + 5358, + 5361, + 5442, + 5440, + 0, + 5361, + 5363, + 5445, + 5442, + 0, + 5363, + 5365, + 5448, + 5445, + 0, + 5365, + 5368, + 5452, + 5448, + 0, + 5368, + 5372, + 5455, + 5452, + 0, + 5372, + 5375, + 5457, + 5455, + 0, + 5375, + 5382, + 5465, + 5457, + 0, + 5382, + 5389, + 5473, + 5465, + 0, + 5389, + 5392, + 5475, + 5473, + 0, + 5392, + 5395, + 5478, + 5475, + 0, + 5395, + 5398, + 5480, + 5478, + 0, + 5398, + 5400, + 5482, + 5480, + 0, + 5400, + 5399, + 5481, + 5482, + 0, + 5399, + 5397, + 5479, + 5481, + 0, + 5397, + 5394, + 5476, + 5479, + 0, + 5394, + 5393, + 5474, + 5476, + 0, + 5393, + 5390, + 5471, + 5474, + 0, + 5390, + 5388, + 5470, + 5471, + 0, + 5388, + 5386, + 5468, + 5470, + 0, + 5386, + 5384, + 5466, + 5468, + 0, + 5384, + 5381, + 5462, + 5466, + 0, + 5381, + 5377, + 5459, + 5462, + 0, + 5377, + 5373, + 5454, + 5459, + 0, + 5373, + 5369, + 5449, + 5454, + 0, + 5369, + 5366, + 5447, + 5449, + 0, + 5366, + 5356, + 5436, + 5447, + 0, + 5356, + 5354, + 5435, + 5436, + 0, + 5435, + 5439, + 5519, + 5515, + 0, + 5439, + 5450, + 5531, + 5519, + 0, + 5450, + 5456, + 5536, + 5531, + 0, + 5456, + 5461, + 5542, + 5536, + 0, + 5461, + 5464, + 5545, + 5542, + 0, + 5464, + 5467, + 5549, + 5545, + 0, + 5467, + 5469, + 5551, + 5549, + 0, + 5469, + 5472, + 5553, + 5551, + 0, + 5472, + 5477, + 5557, + 5553, + 0, + 5477, + 5483, + 5564, + 5557, + 0, + 5483, + 5485, + 5566, + 5564, + 0, + 5485, + 5486, + 5568, + 5566, + 0, + 5486, + 5488, + 5570, + 5568, + 0, + 5488, + 5490, + 5572, + 5570, + 0, + 5490, + 5492, + 5574, + 5572, + 0, + 5492, + 5494, + 5576, + 5574, + 0, + 5494, + 5493, + 5575, + 5576, + 0, + 5493, + 5491, + 5573, + 5575, + 0, + 5491, + 5489, + 5571, + 5573, + 0, + 5489, + 5487, + 5569, + 5571, + 0, + 5487, + 5484, + 5567, + 5569, + 0, + 5484, + 5463, + 5546, + 5567, + 0, + 5463, + 5460, + 5544, + 5546, + 0, + 5460, + 5458, + 5541, + 5544, + 0, + 5458, + 5453, + 5538, + 5541, + 0, + 5453, + 5451, + 5533, + 5538, + 0, + 5451, + 5446, + 5530, + 5533, + 0, + 5446, + 5444, + 5526, + 5530, + 0, + 5444, + 5443, + 5525, + 5526, + 0, + 5443, + 5441, + 5523, + 5525, + 0, + 5441, + 5438, + 5521, + 5523, + 0, + 5438, + 5434, + 5518, + 5521, + 0, + 5434, + 5432, + 5514, + 5518, + 0, + 5432, + 5430, + 5512, + 5514, + 0, + 5430, + 5428, + 5510, + 5512, + 0, + 5428, + 5426, + 5508, + 5510, + 0, + 5426, + 5424, + 5506, + 5508, + 0, + 5424, + 5422, + 5504, + 5506, + 0, + 5422, + 5420, + 5502, + 5504, + 0, + 5420, + 5418, + 5500, + 5502, + 0, + 5418, + 5416, + 5498, + 5500, + 0, + 5416, + 5413, + 5495, + 5498, + 0, + 5413, + 5414, + 5496, + 5495, + 0, + 5414, + 5415, + 5497, + 5496, + 0, + 5415, + 5417, + 5499, + 5497, + 0, + 5417, + 5419, + 5501, + 5499, + 0, + 5419, + 5421, + 5503, + 5501, + 0, + 5421, + 5423, + 5505, + 5503, + 0, + 5423, + 5425, + 5507, + 5505, + 0, + 5425, + 5427, + 5509, + 5507, + 0, + 5427, + 5429, + 5511, + 5509, + 0, + 5429, + 5431, + 5513, + 5511, + 0, + 5431, + 5433, + 5516, + 5513, + 0, + 5433, + 5437, + 5520, + 5516, + 0, + 5437, + 5440, + 5522, + 5520, + 0, + 5440, + 5442, + 5524, + 5522, + 0, + 5442, + 5445, + 5527, + 5524, + 0, + 5445, + 5448, + 5532, + 5527, + 0, + 5448, + 5452, + 5534, + 5532, + 0, + 5452, + 5455, + 5537, + 5534, + 0, + 5455, + 5457, + 5540, + 5537, + 0, + 5457, + 5465, + 5548, + 5540, + 0, + 5465, + 5473, + 5555, + 5548, + 0, + 5473, + 5475, + 5559, + 5555, + 0, + 5475, + 5478, + 5561, + 5559, + 0, + 5478, + 5480, + 5563, + 5561, + 0, + 5480, + 5482, + 5565, + 5563, + 0, + 5482, + 5481, + 5562, + 5565, + 0, + 5481, + 5479, + 5560, + 5562, + 0, + 5479, + 5476, + 5558, + 5560, + 0, + 5476, + 5474, + 5556, + 5558, + 0, + 5474, + 5471, + 5554, + 5556, + 0, + 5471, + 5470, + 5552, + 5554, + 0, + 5470, + 5468, + 5550, + 5552, + 0, + 5468, + 5466, + 5547, + 5550, + 0, + 5466, + 5462, + 5543, + 5547, + 0, + 5462, + 5459, + 5539, + 5543, + 0, + 5459, + 5454, + 5535, + 5539, + 0, + 5454, + 5449, + 5529, + 5535, + 0, + 5449, + 5447, + 5528, + 5529, + 0, + 5447, + 5436, + 5517, + 5528, + 0, + 5436, + 5435, + 5515, + 5517, + 0, + 5515, + 5519, + 5600, + 5597, + 0, + 5519, + 5531, + 5612, + 5600, + 0, + 5531, + 5536, + 5618, + 5612, + 0, + 5536, + 5542, + 5622, + 5618, + 0, + 5542, + 5545, + 5627, + 5622, + 0, + 5545, + 5549, + 5630, + 5627, + 0, + 5549, + 5551, + 5633, + 5630, + 0, + 5551, + 5553, + 5635, + 5633, + 0, + 5553, + 5557, + 5639, + 5635, + 0, + 5557, + 5564, + 5644, + 5639, + 0, + 5564, + 5566, + 5648, + 5644, + 0, + 5566, + 5568, + 5650, + 5648, + 0, + 5568, + 5570, + 5651, + 5650, + 0, + 5570, + 5572, + 5653, + 5651, + 0, + 5572, + 5574, + 5655, + 5653, + 0, + 5574, + 5576, + 5657, + 5655, + 0, + 5576, + 5575, + 5658, + 5657, + 0, + 5575, + 5573, + 5656, + 5658, + 0, + 5573, + 5571, + 5654, + 5656, + 0, + 5571, + 5569, + 5652, + 5654, + 0, + 5569, + 5567, + 5649, + 5652, + 0, + 5567, + 5546, + 5629, + 5649, + 0, + 5546, + 5544, + 5626, + 5629, + 0, + 5544, + 5541, + 5624, + 5626, + 0, + 5541, + 5538, + 5620, + 5624, + 0, + 5538, + 5533, + 5616, + 5620, + 0, + 5533, + 5530, + 5613, + 5616, + 0, + 5530, + 5526, + 5610, + 5613, + 0, + 5526, + 5525, + 5607, + 5610, + 0, + 5525, + 5523, + 5605, + 5607, + 0, + 5523, + 5521, + 5603, + 5605, + 0, + 5521, + 5518, + 5601, + 5603, + 0, + 5518, + 5514, + 5596, + 5601, + 0, + 5514, + 5512, + 5594, + 5596, + 0, + 5512, + 5510, + 5592, + 5594, + 0, + 5510, + 5508, + 5590, + 5592, + 0, + 5508, + 5506, + 5588, + 5590, + 0, + 5506, + 5504, + 5586, + 5588, + 0, + 5504, + 5502, + 5584, + 5586, + 0, + 5502, + 5500, + 5582, + 5584, + 0, + 5500, + 5498, + 5580, + 5582, + 0, + 5498, + 5495, + 5577, + 5580, + 0, + 5495, + 5496, + 5578, + 5577, + 0, + 5496, + 5497, + 5579, + 5578, + 0, + 5497, + 5499, + 5581, + 5579, + 0, + 5499, + 5501, + 5583, + 5581, + 0, + 5501, + 5503, + 5585, + 5583, + 0, + 5503, + 5505, + 5587, + 5585, + 0, + 5505, + 5507, + 5589, + 5587, + 0, + 5507, + 5509, + 5591, + 5589, + 0, + 5509, + 5511, + 5593, + 5591, + 0, + 5511, + 5513, + 5595, + 5593, + 0, + 5513, + 5516, + 5599, + 5595, + 0, + 5516, + 5520, + 5602, + 5599, + 0, + 5520, + 5522, + 5604, + 5602, + 0, + 5522, + 5524, + 5606, + 5604, + 0, + 5524, + 5527, + 5609, + 5606, + 0, + 5527, + 5532, + 5614, + 5609, + 0, + 5532, + 5534, + 5617, + 5614, + 0, + 5534, + 5537, + 5619, + 5617, + 0, + 5537, + 5540, + 5623, + 5619, + 0, + 5540, + 5548, + 5631, + 5623, + 0, + 5548, + 5555, + 5638, + 5631, + 0, + 5555, + 5559, + 5641, + 5638, + 0, + 5559, + 5561, + 5643, + 5641, + 0, + 5561, + 5563, + 5646, + 5643, + 0, + 5563, + 5565, + 5647, + 5646, + 0, + 5565, + 5562, + 5645, + 5647, + 0, + 5562, + 5560, + 5642, + 5645, + 0, + 5560, + 5558, + 5640, + 5642, + 0, + 5558, + 5556, + 5637, + 5640, + 0, + 5556, + 5554, + 5636, + 5637, + 0, + 5554, + 5552, + 5634, + 5636, + 0, + 5552, + 5550, + 5632, + 5634, + 0, + 5550, + 5547, + 5628, + 5632, + 0, + 5547, + 5543, + 5625, + 5628, + 0, + 5543, + 5539, + 5621, + 5625, + 0, + 5539, + 5535, + 5615, + 5621, + 0, + 5535, + 5529, + 5611, + 5615, + 0, + 5529, + 5528, + 5608, + 5611, + 0, + 5528, + 5517, + 5598, + 5608, + 0, + 5517, + 5515, + 5597, + 5598, + 0, + 5597, + 5600, + 5681, + 5677, + 0, + 5600, + 5612, + 5692, + 5681, + 0, + 5612, + 5618, + 5698, + 5692, + 0, + 5618, + 5622, + 5702, + 5698, + 0, + 5622, + 5627, + 5708, + 5702, + 0, + 5627, + 5630, + 5711, + 5708, + 0, + 5630, + 5633, + 5715, + 5711, + 0, + 5633, + 5635, + 5717, + 5715, + 0, + 5635, + 5639, + 5720, + 5717, + 0, + 5639, + 5644, + 5725, + 5720, + 0, + 5644, + 5648, + 5730, + 5725, + 0, + 5648, + 5650, + 5731, + 5730, + 0, + 5650, + 5651, + 5733, + 5731, + 0, + 5651, + 5653, + 5735, + 5733, + 0, + 5653, + 5655, + 5737, + 5735, + 0, + 5655, + 5657, + 5739, + 5737, + 0, + 5657, + 5658, + 5740, + 5739, + 0, + 5658, + 5656, + 5738, + 5740, + 0, + 5656, + 5654, + 5736, + 5738, + 0, + 5654, + 5652, + 5734, + 5736, + 0, + 5652, + 5649, + 5732, + 5734, + 0, + 5649, + 5629, + 5712, + 5732, + 0, + 5629, + 5626, + 5710, + 5712, + 0, + 5626, + 5624, + 5707, + 5710, + 0, + 5624, + 5620, + 5704, + 5707, + 0, + 5620, + 5616, + 5700, + 5704, + 0, + 5616, + 5613, + 5697, + 5700, + 0, + 5613, + 5610, + 5694, + 5697, + 0, + 5610, + 5607, + 5689, + 5694, + 0, + 5607, + 5605, + 5687, + 5689, + 0, + 5605, + 5603, + 5685, + 5687, + 0, + 5603, + 5601, + 5683, + 5685, + 0, + 5601, + 5596, + 5680, + 5683, + 0, + 5596, + 5594, + 5676, + 5680, + 0, + 5594, + 5592, + 5674, + 5676, + 0, + 5592, + 5590, + 5672, + 5674, + 0, + 5590, + 5588, + 5670, + 5672, + 0, + 5588, + 5586, + 5668, + 5670, + 0, + 5586, + 5584, + 5666, + 5668, + 0, + 5584, + 5582, + 5664, + 5666, + 0, + 5582, + 5580, + 5662, + 5664, + 0, + 5580, + 5577, + 5659, + 5662, + 0, + 5577, + 5578, + 5660, + 5659, + 0, + 5578, + 5579, + 5661, + 5660, + 0, + 5579, + 5581, + 5663, + 5661, + 0, + 5581, + 5583, + 5665, + 5663, + 0, + 5583, + 5585, + 5667, + 5665, + 0, + 5585, + 5587, + 5669, + 5667, + 0, + 5587, + 5589, + 5671, + 5669, + 0, + 5589, + 5591, + 5673, + 5671, + 0, + 5591, + 5593, + 5675, + 5673, + 0, + 5593, + 5595, + 5679, + 5675, + 0, + 5595, + 5599, + 5682, + 5679, + 0, + 5599, + 5602, + 5684, + 5682, + 0, + 5602, + 5604, + 5686, + 5684, + 0, + 5604, + 5606, + 5688, + 5686, + 0, + 5606, + 5609, + 5693, + 5688, + 0, + 5609, + 5614, + 5696, + 5693, + 0, + 5614, + 5617, + 5699, + 5696, + 0, + 5617, + 5619, + 5703, + 5699, + 0, + 5619, + 5623, + 5706, + 5703, + 0, + 5623, + 5631, + 5714, + 5706, + 0, + 5631, + 5638, + 5721, + 5714, + 0, + 5638, + 5641, + 5723, + 5721, + 0, + 5641, + 5643, + 5726, + 5723, + 0, + 5643, + 5646, + 5728, + 5726, + 0, + 5646, + 5647, + 5729, + 5728, + 0, + 5647, + 5645, + 5727, + 5729, + 0, + 5645, + 5642, + 5724, + 5727, + 0, + 5642, + 5640, + 5722, + 5724, + 0, + 5640, + 5637, + 5719, + 5722, + 0, + 5637, + 5636, + 5718, + 5719, + 0, + 5636, + 5634, + 5716, + 5718, + 0, + 5634, + 5632, + 5713, + 5716, + 0, + 5632, + 5628, + 5709, + 5713, + 0, + 5628, + 5625, + 5705, + 5709, + 0, + 5625, + 5621, + 5701, + 5705, + 0, + 5621, + 5615, + 5695, + 5701, + 0, + 5615, + 5611, + 5691, + 5695, + 0, + 5611, + 5608, + 5690, + 5691, + 0, + 5608, + 5598, + 5678, + 5690, + 0, + 5598, + 5597, + 5677, + 5678, + 0, + 5677, + 5681, + 5767, + 5764, + 0, + 5681, + 5692, + 5788, + 5767, + 0, + 5692, + 5698, + 5797, + 5788, + 0, + 5698, + 5702, + 5805, + 5797, + 0, + 5702, + 5708, + 5812, + 5805, + 0, + 5708, + 5711, + 5819, + 5812, + 0, + 5711, + 5715, + 5825, + 5819, + 0, + 5715, + 5717, + 5832, + 5825, + 0, + 5717, + 5720, + 5837, + 5832, + 0, + 5720, + 5725, + 5843, + 5837, + 0, + 5725, + 5730, + 5853, + 5843, + 0, + 5730, + 5731, + 5855, + 5853, + 0, + 5731, + 5733, + 5859, + 5855, + 0, + 5733, + 5735, + 5862, + 5859, + 0, + 5735, + 5737, + 5866, + 5862, + 0, + 5737, + 5739, + 5868, + 5866, + 0, + 5739, + 5740, + 5871, + 5868, + 0, + 5740, + 5738, + 5870, + 5871, + 0, + 5738, + 5736, + 5867, + 5870, + 0, + 5736, + 5734, + 5865, + 5867, + 0, + 5734, + 5732, + 5860, + 5865, + 0, + 5732, + 5712, + 5826, + 5860, + 0, + 5712, + 5710, + 5822, + 5826, + 0, + 5710, + 5707, + 5818, + 5822, + 0, + 5707, + 5704, + 5813, + 5818, + 0, + 5704, + 5700, + 5808, + 5813, + 0, + 5700, + 5697, + 5804, + 5808, + 0, + 5697, + 5694, + 5799, + 5804, + 0, + 5694, + 5689, + 5791, + 5799, + 0, + 5689, + 5687, + 5785, + 5791, + 0, + 5687, + 5685, + 5780, + 5785, + 0, + 5685, + 5683, + 5776, + 5780, + 0, + 5683, + 5680, + 5772, + 5776, + 0, + 5680, + 5676, + 5769, + 5772, + 0, + 5676, + 5674, + 5762, + 5769, + 0, + 5674, + 5672, + 5758, + 5762, + 0, + 5672, + 5670, + 5755, + 5758, + 0, + 5670, + 5668, + 5753, + 5755, + 0, + 5668, + 5666, + 5751, + 5753, + 0, + 5666, + 5664, + 5747, + 5751, + 0, + 5664, + 5662, + 5744, + 5747, + 0, + 5662, + 5659, + 5741, + 5744, + 0, + 5659, + 5660, + 5742, + 5741, + 0, + 5660, + 5661, + 5743, + 5742, + 0, + 5661, + 5663, + 5745, + 5743, + 0, + 5663, + 5665, + 5749, + 5745, + 0, + 5665, + 5667, + 5752, + 5749, + 0, + 5667, + 5669, + 5754, + 5752, + 0, + 5669, + 5671, + 5756, + 5754, + 0, + 5671, + 5673, + 5760, + 5756, + 0, + 5673, + 5675, + 5766, + 5760, + 0, + 5675, + 5679, + 5771, + 5766, + 0, + 5679, + 5682, + 5775, + 5771, + 0, + 5682, + 5684, + 5779, + 5775, + 0, + 5684, + 5686, + 5782, + 5779, + 0, + 5686, + 5688, + 5790, + 5782, + 0, + 5688, + 5693, + 5798, + 5790, + 0, + 5693, + 5696, + 5803, + 5798, + 0, + 5696, + 5699, + 5807, + 5803, + 0, + 5699, + 5703, + 5811, + 5807, + 0, + 5703, + 5706, + 5815, + 5811, + 0, + 5706, + 5714, + 5829, + 5815, + 0, + 5714, + 5721, + 5842, + 5829, + 0, + 5721, + 5723, + 5845, + 5842, + 0, + 5723, + 5726, + 5849, + 5845, + 0, + 5726, + 5728, + 5852, + 5849, + 0, + 5728, + 5729, + 5851, + 5852, + 0, + 5729, + 5727, + 5847, + 5851, + 0, + 5727, + 5724, + 5844, + 5847, + 0, + 5724, + 5722, + 5841, + 5844, + 0, + 5722, + 5719, + 5836, + 5841, + 0, + 5719, + 5718, + 5834, + 5836, + 0, + 5718, + 5716, + 5830, + 5834, + 0, + 5716, + 5713, + 5821, + 5830, + 0, + 5713, + 5709, + 5816, + 5821, + 0, + 5709, + 5705, + 5809, + 5816, + 0, + 5705, + 5701, + 5801, + 5809, + 0, + 5701, + 5695, + 5796, + 5801, + 0, + 5695, + 5691, + 5787, + 5796, + 0, + 5691, + 5690, + 5784, + 5787, + 0, + 5690, + 5678, + 5765, + 5784, + 0, + 5678, + 5677, + 5764, + 5765, + 0, + 5764, + 5767, + 5794, + 5789, + 0, + 5767, + 5788, + 5828, + 5794, + 0, + 5788, + 5797, + 5838, + 5828, + 0, + 5797, + 5805, + 5854, + 5838, + 0, + 5805, + 5812, + 5863, + 5854, + 0, + 5812, + 5819, + 5874, + 5863, + 0, + 5819, + 5825, + 5877, + 5874, + 0, + 5825, + 5832, + 5881, + 5877, + 0, + 5832, + 5837, + 5884, + 5881, + 0, + 5837, + 5843, + 5887, + 5884, + 0, + 5843, + 5853, + 5894, + 5887, + 0, + 5853, + 5855, + 5895, + 5894, + 0, + 5855, + 5859, + 5896, + 5895, + 0, + 5859, + 5862, + 5898, + 5896, + 0, + 5862, + 5866, + 5900, + 5898, + 0, + 5866, + 5868, + 5902, + 5900, + 0, + 5868, + 5871, + 5904, + 5902, + 0, + 5871, + 5870, + 5903, + 5904, + 0, + 5870, + 5867, + 5901, + 5903, + 0, + 5867, + 5865, + 5899, + 5901, + 0, + 5865, + 5860, + 5897, + 5899, + 0, + 5860, + 5826, + 5878, + 5897, + 0, + 5826, + 5822, + 5876, + 5878, + 0, + 5822, + 5818, + 5873, + 5876, + 0, + 5818, + 5813, + 5864, + 5873, + 0, + 5813, + 5808, + 5857, + 5864, + 0, + 5808, + 5804, + 5850, + 5857, + 0, + 5804, + 5799, + 5840, + 5850, + 0, + 5799, + 5791, + 5833, + 5840, + 0, + 5791, + 5785, + 5824, + 5833, + 0, + 5785, + 5780, + 5817, + 5824, + 0, + 5780, + 5776, + 5810, + 5817, + 0, + 5776, + 5772, + 5802, + 5810, + 0, + 5772, + 5769, + 5795, + 5802, + 0, + 5769, + 5762, + 5786, + 5795, + 0, + 5762, + 5758, + 5781, + 5786, + 0, + 5758, + 5755, + 5777, + 5781, + 0, + 5755, + 5753, + 5773, + 5777, + 0, + 5753, + 5751, + 5768, + 5773, + 0, + 5751, + 5747, + 5761, + 5768, + 0, + 5747, + 5744, + 5757, + 5761, + 0, + 5744, + 5741, + 5746, + 5757, + 0, + 5741, + 5742, + 5748, + 5746, + 0, + 5742, + 5743, + 5750, + 5748, + 0, + 5743, + 5745, + 5759, + 5750, + 0, + 5745, + 5749, + 5763, + 5759, + 0, + 5749, + 5752, + 5770, + 5763, + 0, + 5752, + 5754, + 5774, + 5770, + 0, + 5754, + 5756, + 5778, + 5774, + 0, + 5756, + 5760, + 5783, + 5778, + 0, + 5760, + 5766, + 5793, + 5783, + 0, + 5766, + 5771, + 5800, + 5793, + 0, + 5771, + 5775, + 5806, + 5800, + 0, + 5775, + 5779, + 5814, + 5806, + 0, + 5779, + 5782, + 5820, + 5814, + 0, + 5782, + 5790, + 5831, + 5820, + 0, + 5790, + 5798, + 5839, + 5831, + 0, + 5798, + 5803, + 5848, + 5839, + 0, + 5803, + 5807, + 5856, + 5848, + 0, + 5807, + 5811, + 5861, + 5856, + 0, + 5811, + 5815, + 5869, + 5861, + 0, + 5815, + 5829, + 5879, + 5869, + 0, + 5829, + 5842, + 5886, + 5879, + 0, + 5842, + 5845, + 5889, + 5886, + 0, + 5845, + 5849, + 5891, + 5889, + 0, + 5849, + 5852, + 5893, + 5891, + 0, + 5852, + 5851, + 5892, + 5893, + 0, + 5851, + 5847, + 5890, + 5892, + 0, + 5847, + 5844, + 5888, + 5890, + 0, + 5844, + 5841, + 5885, + 5888, + 0, + 5841, + 5836, + 5883, + 5885, + 0, + 5836, + 5834, + 5882, + 5883, + 0, + 5834, + 5830, + 5880, + 5882, + 0, + 5830, + 5821, + 5875, + 5880, + 0, + 5821, + 5816, + 5872, + 5875, + 0, + 5816, + 5809, + 5858, + 5872, + 0, + 5809, + 5801, + 5846, + 5858, + 0, + 5801, + 5796, + 5835, + 5846, + 0, + 5796, + 5787, + 5827, + 5835, + 0, + 5787, + 5784, + 5823, + 5827, + 0, + 5784, + 5765, + 5792, + 5823, + 0, + 5765, + 5764, + 5789, + 5792, + 0, + 5789, + 5794, + 5923, + 5920, + 0, + 5794, + 5828, + 5935, + 5923, + 0, + 5828, + 5838, + 5939, + 5935, + 0, + 5838, + 5854, + 5944, + 5939, + 0, + 5854, + 5863, + 5949, + 5944, + 0, + 5863, + 5874, + 5954, + 5949, + 0, + 5874, + 5877, + 5958, + 5954, + 0, + 5877, + 5881, + 5961, + 5958, + 0, + 5881, + 5884, + 5965, + 5961, + 0, + 5884, + 5887, + 5968, + 5965, + 0, + 5887, + 5894, + 5973, + 5968, + 0, + 5894, + 5895, + 5977, + 5973, + 0, + 5895, + 5896, + 5978, + 5977, + 0, + 5896, + 5898, + 5980, + 5978, + 0, + 5898, + 5900, + 5981, + 5980, + 0, + 5900, + 5902, + 5983, + 5981, + 0, + 5902, + 5904, + 5985, + 5983, + 0, + 5904, + 5903, + 5986, + 5985, + 0, + 5903, + 5901, + 5984, + 5986, + 0, + 5901, + 5899, + 5982, + 5984, + 0, + 5899, + 5897, + 5979, + 5982, + 0, + 5897, + 5878, + 5963, + 5979, + 0, + 5878, + 5876, + 5959, + 5963, + 0, + 5876, + 5873, + 5956, + 5959, + 0, + 5873, + 5864, + 5953, + 5956, + 0, + 5864, + 5857, + 5950, + 5953, + 0, + 5857, + 5850, + 5946, + 5950, + 0, + 5850, + 5840, + 5943, + 5946, + 0, + 5840, + 5833, + 5940, + 5943, + 0, + 5833, + 5824, + 5936, + 5940, + 0, + 5824, + 5817, + 5931, + 5936, + 0, + 5817, + 5810, + 5929, + 5931, + 0, + 5810, + 5802, + 5927, + 5929, + 0, + 5802, + 5795, + 5925, + 5927, + 0, + 5795, + 5786, + 5922, + 5925, + 0, + 5786, + 5781, + 5918, + 5922, + 0, + 5781, + 5777, + 5916, + 5918, + 0, + 5777, + 5773, + 5914, + 5916, + 0, + 5773, + 5768, + 5912, + 5914, + 0, + 5768, + 5761, + 5910, + 5912, + 0, + 5761, + 5757, + 5908, + 5910, + 0, + 5757, + 5746, + 5905, + 5908, + 0, + 5746, + 5748, + 5906, + 5905, + 0, + 5748, + 5750, + 5907, + 5906, + 0, + 5750, + 5759, + 5909, + 5907, + 0, + 5759, + 5763, + 5911, + 5909, + 0, + 5763, + 5770, + 5913, + 5911, + 0, + 5770, + 5774, + 5915, + 5913, + 0, + 5774, + 5778, + 5917, + 5915, + 0, + 5778, + 5783, + 5919, + 5917, + 0, + 5783, + 5793, + 5924, + 5919, + 0, + 5793, + 5800, + 5926, + 5924, + 0, + 5800, + 5806, + 5928, + 5926, + 0, + 5806, + 5814, + 5930, + 5928, + 0, + 5814, + 5820, + 5933, + 5930, + 0, + 5820, + 5831, + 5937, + 5933, + 0, + 5831, + 5839, + 5941, + 5937, + 0, + 5839, + 5848, + 5945, + 5941, + 0, + 5848, + 5856, + 5948, + 5945, + 0, + 5856, + 5861, + 5951, + 5948, + 0, + 5861, + 5869, + 5955, + 5951, + 0, + 5869, + 5879, + 5962, + 5955, + 0, + 5879, + 5886, + 5970, + 5962, + 0, + 5886, + 5889, + 5972, + 5970, + 0, + 5889, + 5891, + 5975, + 5972, + 0, + 5891, + 5893, + 5976, + 5975, + 0, + 5893, + 5892, + 5974, + 5976, + 0, + 5892, + 5890, + 5971, + 5974, + 0, + 5890, + 5888, + 5969, + 5971, + 0, + 5888, + 5885, + 5967, + 5969, + 0, + 5885, + 5883, + 5966, + 5967, + 0, + 5883, + 5882, + 5964, + 5966, + 0, + 5882, + 5880, + 5960, + 5964, + 0, + 5880, + 5875, + 5957, + 5960, + 0, + 5875, + 5872, + 5952, + 5957, + 0, + 5872, + 5858, + 5947, + 5952, + 0, + 5858, + 5846, + 5942, + 5947, + 0, + 5846, + 5835, + 5938, + 5942, + 0, + 5835, + 5827, + 5934, + 5938, + 0, + 5827, + 5823, + 5932, + 5934, + 0, + 5823, + 5792, + 5921, + 5932, + 0, + 5792, + 5789, + 5920, + 5921, + 0, + 5920, + 5923, + 6002, + 6000, + 0, + 5923, + 5935, + 6013, + 6002, + 0, + 5935, + 5939, + 6019, + 6013, + 0, + 5939, + 5944, + 6023, + 6019, + 0, + 5944, + 5949, + 6028, + 6023, + 0, + 5949, + 5954, + 6033, + 6028, + 0, + 5954, + 5958, + 6037, + 6033, + 0, + 5958, + 5961, + 6042, + 6037, + 0, + 5961, + 5965, + 6046, + 6042, + 0, + 5965, + 5968, + 6050, + 6046, + 0, + 5968, + 5973, + 6052, + 6050, + 0, + 5973, + 5977, + 6059, + 6052, + 0, + 5977, + 5978, + 6060, + 6059, + 0, + 5978, + 5980, + 6061, + 6060, + 0, + 5980, + 5981, + 6063, + 6061, + 0, + 5981, + 5983, + 6064, + 6063, + 0, + 5983, + 5985, + 6066, + 6064, + 0, + 5985, + 5986, + 6068, + 6066, + 0, + 5986, + 5984, + 6067, + 6068, + 0, + 5984, + 5982, + 6065, + 6067, + 0, + 5982, + 5979, + 6062, + 6065, + 0, + 5979, + 5963, + 6048, + 6062, + 0, + 5963, + 5959, + 6044, + 6048, + 0, + 5959, + 5956, + 6040, + 6044, + 0, + 5956, + 5953, + 6038, + 6040, + 0, + 5953, + 5950, + 6034, + 6038, + 0, + 5950, + 5946, + 6030, + 6034, + 0, + 5946, + 5943, + 6027, + 6030, + 0, + 5943, + 5940, + 6024, + 6027, + 0, + 5940, + 5936, + 6020, + 6024, + 0, + 5936, + 5931, + 6016, + 6020, + 0, + 5931, + 5929, + 6012, + 6016, + 0, + 5929, + 5927, + 6009, + 6012, + 0, + 5927, + 5925, + 6007, + 6009, + 0, + 5925, + 5922, + 6005, + 6007, + 0, + 5922, + 5918, + 6003, + 6005, + 0, + 5918, + 5916, + 5998, + 6003, + 0, + 5916, + 5914, + 5996, + 5998, + 0, + 5914, + 5912, + 5994, + 5996, + 0, + 5912, + 5910, + 5992, + 5994, + 0, + 5910, + 5908, + 5990, + 5992, + 0, + 5908, + 5905, + 5987, + 5990, + 0, + 5905, + 5906, + 5988, + 5987, + 0, + 5906, + 5907, + 5989, + 5988, + 0, + 5907, + 5909, + 5991, + 5989, + 0, + 5909, + 5911, + 5993, + 5991, + 0, + 5911, + 5913, + 5995, + 5993, + 0, + 5913, + 5915, + 5997, + 5995, + 0, + 5915, + 5917, + 5999, + 5997, + 0, + 5917, + 5919, + 6004, + 5999, + 0, + 5919, + 5924, + 6006, + 6004, + 0, + 5924, + 5926, + 6008, + 6006, + 0, + 5926, + 5928, + 6010, + 6008, + 0, + 5928, + 5930, + 6015, + 6010, + 0, + 5930, + 5933, + 6018, + 6015, + 0, + 5933, + 5937, + 6021, + 6018, + 0, + 5937, + 5941, + 6025, + 6021, + 0, + 5941, + 5945, + 6029, + 6025, + 0, + 5945, + 5948, + 6032, + 6029, + 0, + 5948, + 5951, + 6035, + 6032, + 0, + 5951, + 5955, + 6039, + 6035, + 0, + 5955, + 5962, + 6045, + 6039, + 0, + 5962, + 5970, + 6053, + 6045, + 0, + 5970, + 5972, + 6055, + 6053, + 0, + 5972, + 5975, + 6057, + 6055, + 0, + 5975, + 5976, + 6058, + 6057, + 0, + 5976, + 5974, + 6056, + 6058, + 0, + 5974, + 5971, + 6054, + 6056, + 0, + 5971, + 5969, + 6051, + 6054, + 0, + 5969, + 5967, + 6049, + 6051, + 0, + 5967, + 5966, + 6047, + 6049, + 0, + 5966, + 5964, + 6043, + 6047, + 0, + 5964, + 5960, + 6041, + 6043, + 0, + 5960, + 5957, + 6036, + 6041, + 0, + 5957, + 5952, + 6031, + 6036, + 0, + 5952, + 5947, + 6026, + 6031, + 0, + 5947, + 5942, + 6022, + 6026, + 0, + 5942, + 5938, + 6017, + 6022, + 0, + 5938, + 5934, + 6014, + 6017, + 0, + 5934, + 5932, + 6011, + 6014, + 0, + 5932, + 5921, + 6001, + 6011, + 0, + 5921, + 5920, + 6000, + 6001, + 0, + 6000, + 6002, + 6084, + 6080, + 0, + 6002, + 6013, + 6094, + 6084, + 0, + 6013, + 6019, + 6100, + 6094, + 0, + 6019, + 6023, + 6104, + 6100, + 0, + 6023, + 6028, + 6109, + 6104, + 0, + 6028, + 6033, + 6114, + 6109, + 0, + 6033, + 6037, + 6119, + 6114, + 0, + 6037, + 6042, + 6123, + 6119, + 0, + 6042, + 6046, + 6127, + 6123, + 0, + 6046, + 6050, + 6132, + 6127, + 0, + 6050, + 6052, + 6134, + 6132, + 0, + 6052, + 6059, + 6141, + 6134, + 0, + 6059, + 6060, + 6142, + 6141, + 0, + 6060, + 6061, + 6143, + 6142, + 0, + 6061, + 6063, + 6144, + 6143, + 0, + 6063, + 6064, + 6146, + 6144, + 0, + 6064, + 6066, + 6148, + 6146, + 0, + 6066, + 6068, + 6150, + 6148, + 0, + 6068, + 6067, + 6149, + 6150, + 0, + 6067, + 6065, + 6147, + 6149, + 0, + 6065, + 6062, + 6145, + 6147, + 0, + 6062, + 6048, + 6130, + 6145, + 0, + 6048, + 6044, + 6126, + 6130, + 0, + 6044, + 6040, + 6124, + 6126, + 0, + 6040, + 6038, + 6120, + 6124, + 0, + 6038, + 6034, + 6116, + 6120, + 0, + 6034, + 6030, + 6113, + 6116, + 0, + 6030, + 6027, + 6110, + 6113, + 0, + 6027, + 6024, + 6106, + 6110, + 0, + 6024, + 6020, + 6102, + 6106, + 0, + 6020, + 6016, + 6098, + 6102, + 0, + 6016, + 6012, + 6095, + 6098, + 0, + 6012, + 6009, + 6091, + 6095, + 0, + 6009, + 6007, + 6089, + 6091, + 0, + 6007, + 6005, + 6087, + 6089, + 0, + 6005, + 6003, + 6085, + 6087, + 0, + 6003, + 5998, + 6081, + 6085, + 0, + 5998, + 5996, + 6079, + 6081, + 0, + 5996, + 5994, + 6076, + 6079, + 0, + 5994, + 5992, + 6074, + 6076, + 0, + 5992, + 5990, + 6072, + 6074, + 0, + 5990, + 5987, + 6069, + 6072, + 0, + 5987, + 5988, + 6070, + 6069, + 0, + 5988, + 5989, + 6071, + 6070, + 0, + 5989, + 5991, + 6073, + 6071, + 0, + 5991, + 5993, + 6075, + 6073, + 0, + 5993, + 5995, + 6077, + 6075, + 0, + 5995, + 5997, + 6078, + 6077, + 0, + 5997, + 5999, + 6082, + 6078, + 0, + 5999, + 6004, + 6086, + 6082, + 0, + 6004, + 6006, + 6088, + 6086, + 0, + 6006, + 6008, + 6090, + 6088, + 0, + 6008, + 6010, + 6093, + 6090, + 0, + 6010, + 6015, + 6097, + 6093, + 0, + 6015, + 6018, + 6101, + 6097, + 0, + 6018, + 6021, + 6105, + 6101, + 0, + 6021, + 6025, + 6108, + 6105, + 0, + 6025, + 6029, + 6111, + 6108, + 0, + 6029, + 6032, + 6115, + 6111, + 0, + 6032, + 6035, + 6118, + 6115, + 0, + 6035, + 6039, + 6121, + 6118, + 0, + 6039, + 6045, + 6128, + 6121, + 0, + 6045, + 6053, + 6136, + 6128, + 0, + 6053, + 6055, + 6138, + 6136, + 0, + 6055, + 6057, + 6140, + 6138, + 0, + 6057, + 6058, + 6139, + 6140, + 0, + 6058, + 6056, + 6137, + 6139, + 0, + 6056, + 6054, + 6135, + 6137, + 0, + 6054, + 6051, + 6133, + 6135, + 0, + 6051, + 6049, + 6131, + 6133, + 0, + 6049, + 6047, + 6129, + 6131, + 0, + 6047, + 6043, + 6125, + 6129, + 0, + 6043, + 6041, + 6122, + 6125, + 0, + 6041, + 6036, + 6117, + 6122, + 0, + 6036, + 6031, + 6112, + 6117, + 0, + 6031, + 6026, + 6107, + 6112, + 0, + 6026, + 6022, + 6103, + 6107, + 0, + 6022, + 6017, + 6099, + 6103, + 0, + 6017, + 6014, + 6096, + 6099, + 0, + 6014, + 6011, + 6092, + 6096, + 0, + 6011, + 6001, + 6083, + 6092, + 0, + 6001, + 6000, + 6080, + 6083, + 0, + 6080, + 6084, + 6164, + 6162, + 0, + 6084, + 6094, + 6175, + 6164, + 0, + 6094, + 6100, + 6181, + 6175, + 0, + 6100, + 6104, + 6186, + 6181, + 0, + 6104, + 6109, + 6190, + 6186, + 0, + 6109, + 6114, + 6194, + 6190, + 0, + 6114, + 6119, + 6199, + 6194, + 0, + 6119, + 6123, + 6205, + 6199, + 0, + 6123, + 6127, + 6208, + 6205, + 0, + 6127, + 6132, + 6212, + 6208, + 0, + 6132, + 6134, + 6216, + 6212, + 0, + 6134, + 6141, + 6221, + 6216, + 0, + 6141, + 6142, + 6224, + 6221, + 0, + 6142, + 6143, + 6225, + 6224, + 0, + 6143, + 6144, + 6226, + 6225, + 0, + 6144, + 6146, + 6228, + 6226, + 0, + 6146, + 6148, + 6230, + 6228, + 0, + 6148, + 6150, + 6231, + 6230, + 0, + 6150, + 6149, + 6232, + 6231, + 0, + 6149, + 6147, + 6229, + 6232, + 0, + 6147, + 6145, + 6227, + 6229, + 0, + 6145, + 6130, + 6214, + 6227, + 0, + 6130, + 6126, + 6210, + 6214, + 0, + 6126, + 6124, + 6206, + 6210, + 0, + 6124, + 6120, + 6204, + 6206, + 0, + 6120, + 6116, + 6200, + 6204, + 0, + 6116, + 6113, + 6196, + 6200, + 0, + 6113, + 6110, + 6192, + 6196, + 0, + 6110, + 6106, + 6188, + 6192, + 0, + 6106, + 6102, + 6185, + 6188, + 0, + 6102, + 6098, + 6182, + 6185, + 0, + 6098, + 6095, + 6178, + 6182, + 0, + 6095, + 6091, + 6173, + 6178, + 0, + 6091, + 6089, + 6171, + 6173, + 0, + 6089, + 6087, + 6169, + 6171, + 0, + 6087, + 6085, + 6167, + 6169, + 0, + 6085, + 6081, + 6165, + 6167, + 0, + 6081, + 6079, + 6161, + 6165, + 0, + 6079, + 6076, + 6158, + 6161, + 0, + 6076, + 6074, + 6156, + 6158, + 0, + 6074, + 6072, + 6154, + 6156, + 0, + 6072, + 6069, + 6151, + 6154, + 0, + 6069, + 6070, + 6152, + 6151, + 0, + 6070, + 6071, + 6153, + 6152, + 0, + 6071, + 6073, + 6155, + 6153, + 0, + 6073, + 6075, + 6157, + 6155, + 0, + 6075, + 6077, + 6159, + 6157, + 0, + 6077, + 6078, + 6160, + 6159, + 0, + 6078, + 6082, + 6166, + 6160, + 0, + 6082, + 6086, + 6168, + 6166, + 0, + 6086, + 6088, + 6170, + 6168, + 0, + 6088, + 6090, + 6172, + 6170, + 0, + 6090, + 6093, + 6176, + 6172, + 0, + 6093, + 6097, + 6179, + 6176, + 0, + 6097, + 6101, + 6183, + 6179, + 0, + 6101, + 6105, + 6187, + 6183, + 0, + 6105, + 6108, + 6191, + 6187, + 0, + 6108, + 6111, + 6195, + 6191, + 0, + 6111, + 6115, + 6197, + 6195, + 0, + 6115, + 6118, + 6201, + 6197, + 0, + 6118, + 6121, + 6202, + 6201, + 0, + 6121, + 6128, + 6211, + 6202, + 0, + 6128, + 6136, + 6218, + 6211, + 0, + 6136, + 6138, + 6220, + 6218, + 0, + 6138, + 6140, + 6223, + 6220, + 0, + 6140, + 6139, + 6222, + 6223, + 0, + 6139, + 6137, + 6219, + 6222, + 0, + 6137, + 6135, + 6217, + 6219, + 0, + 6135, + 6133, + 6215, + 6217, + 0, + 6133, + 6131, + 6213, + 6215, + 0, + 6131, + 6129, + 6209, + 6213, + 0, + 6129, + 6125, + 6207, + 6209, + 0, + 6125, + 6122, + 6203, + 6207, + 0, + 6122, + 6117, + 6198, + 6203, + 0, + 6117, + 6112, + 6193, + 6198, + 0, + 6112, + 6107, + 6189, + 6193, + 0, + 6107, + 6103, + 6184, + 6189, + 0, + 6103, + 6099, + 6180, + 6184, + 0, + 6099, + 6096, + 6177, + 6180, + 0, + 6096, + 6092, + 6174, + 6177, + 0, + 6092, + 6083, + 6163, + 6174, + 0, + 6083, + 6080, + 6162, + 6163, + 0, + 6162, + 6164, + 6244, + 6242, + 0, + 6164, + 6175, + 6255, + 6244, + 0, + 6175, + 6181, + 6259, + 6255, + 0, + 6181, + 6186, + 6265, + 6259, + 0, + 6186, + 6190, + 6270, + 6265, + 0, + 6190, + 6194, + 6274, + 6270, + 0, + 6194, + 6199, + 6278, + 6274, + 0, + 6199, + 6205, + 6282, + 6278, + 0, + 6205, + 6208, + 6288, + 6282, + 0, + 6208, + 6212, + 6292, + 6288, + 0, + 6212, + 6216, + 6297, + 6292, + 0, + 6216, + 6221, + 6300, + 6297, + 0, + 6221, + 6224, + 6306, + 6300, + 0, + 6224, + 6225, + 6307, + 6306, + 0, + 6225, + 6226, + 6308, + 6307, + 0, + 6226, + 6228, + 6309, + 6308, + 0, + 6228, + 6230, + 6311, + 6309, + 0, + 6230, + 6231, + 6313, + 6311, + 0, + 6231, + 6232, + 6314, + 6313, + 0, + 6232, + 6229, + 6312, + 6314, + 0, + 6229, + 6227, + 6310, + 6312, + 0, + 6227, + 6214, + 6298, + 6310, + 0, + 6214, + 6210, + 6295, + 6298, + 0, + 6210, + 6206, + 6291, + 6295, + 0, + 6206, + 6204, + 6289, + 6291, + 0, + 6204, + 6200, + 6284, + 6289, + 0, + 6200, + 6196, + 6280, + 6284, + 0, + 6196, + 6192, + 6276, + 6280, + 0, + 6192, + 6188, + 6273, + 6276, + 0, + 6188, + 6185, + 6269, + 6273, + 0, + 6185, + 6182, + 6266, + 6269, + 0, + 6182, + 6178, + 6262, + 6266, + 0, + 6178, + 6173, + 6258, + 6262, + 0, + 6173, + 6171, + 6254, + 6258, + 0, + 6171, + 6169, + 6251, + 6254, + 0, + 6169, + 6167, + 6249, + 6251, + 0, + 6167, + 6165, + 6247, + 6249, + 0, + 6165, + 6161, + 6246, + 6247, + 0, + 6161, + 6158, + 6240, + 6246, + 0, + 6158, + 6156, + 6238, + 6240, + 0, + 6156, + 6154, + 6236, + 6238, + 0, + 6154, + 6151, + 6233, + 6236, + 0, + 6151, + 6152, + 6234, + 6233, + 0, + 6152, + 6153, + 6235, + 6234, + 0, + 6153, + 6155, + 6237, + 6235, + 0, + 6155, + 6157, + 6239, + 6237, + 0, + 6157, + 6159, + 6241, + 6239, + 0, + 6159, + 6160, + 6245, + 6241, + 0, + 6160, + 6166, + 6248, + 6245, + 0, + 6166, + 6168, + 6250, + 6248, + 0, + 6168, + 6170, + 6252, + 6250, + 0, + 6170, + 6172, + 6257, + 6252, + 0, + 6172, + 6176, + 6261, + 6257, + 0, + 6176, + 6179, + 6263, + 6261, + 0, + 6179, + 6183, + 6267, + 6263, + 0, + 6183, + 6187, + 6271, + 6267, + 0, + 6187, + 6191, + 6275, + 6271, + 0, + 6191, + 6195, + 6279, + 6275, + 0, + 6195, + 6197, + 6281, + 6279, + 0, + 6197, + 6201, + 6285, + 6281, + 0, + 6201, + 6202, + 6287, + 6285, + 0, + 6202, + 6211, + 6294, + 6287, + 0, + 6211, + 6218, + 6302, + 6294, + 0, + 6218, + 6220, + 6304, + 6302, + 0, + 6220, + 6223, + 6305, + 6304, + 0, + 6223, + 6222, + 6303, + 6305, + 0, + 6222, + 6219, + 6301, + 6303, + 0, + 6219, + 6217, + 6299, + 6301, + 0, + 6217, + 6215, + 6296, + 6299, + 0, + 6215, + 6213, + 6293, + 6296, + 0, + 6213, + 6209, + 6290, + 6293, + 0, + 6209, + 6207, + 6286, + 6290, + 0, + 6207, + 6203, + 6283, + 6286, + 0, + 6203, + 6198, + 6277, + 6283, + 0, + 6198, + 6193, + 6272, + 6277, + 0, + 6193, + 6189, + 6268, + 6272, + 0, + 6189, + 6184, + 6264, + 6268, + 0, + 6184, + 6180, + 6260, + 6264, + 0, + 6180, + 6177, + 6256, + 6260, + 0, + 6177, + 6174, + 6253, + 6256, + 0, + 6174, + 6163, + 6243, + 6253, + 0, + 6163, + 6162, + 6242, + 6243, + 0, + 6242, + 6244, + 6323, + 6322, + 0, + 6244, + 6255, + 6335, + 6323, + 0, + 6255, + 6259, + 6339, + 6335, + 0, + 6259, + 6265, + 6347, + 6339, + 0, + 6265, + 6270, + 6353, + 6347, + 0, + 6270, + 6274, + 6357, + 6353, + 0, + 6274, + 6278, + 6360, + 6357, + 0, + 6278, + 6282, + 6365, + 6360, + 0, + 6282, + 6288, + 6371, + 6365, + 0, + 6288, + 6292, + 6378, + 6371, + 0, + 6292, + 6297, + 6385, + 6378, + 0, + 6297, + 6300, + 6389, + 6385, + 0, + 6300, + 6306, + 6400, + 6389, + 0, + 6306, + 6307, + 6401, + 6400, + 0, + 6307, + 6308, + 6402, + 6401, + 0, + 6308, + 6309, + 6405, + 6402, + 0, + 6309, + 6311, + 6406, + 6405, + 0, + 6311, + 6313, + 6408, + 6406, + 0, + 6313, + 6314, + 6410, + 6408, + 0, + 6314, + 6312, + 6409, + 6410, + 0, + 6312, + 6310, + 6407, + 6409, + 0, + 6310, + 6298, + 6390, + 6407, + 0, + 6298, + 6295, + 6386, + 6390, + 0, + 6295, + 6291, + 6382, + 6386, + 0, + 6291, + 6289, + 6377, + 6382, + 0, + 6289, + 6284, + 6374, + 6377, + 0, + 6284, + 6280, + 6367, + 6374, + 0, + 6280, + 6276, + 6363, + 6367, + 0, + 6276, + 6273, + 6359, + 6363, + 0, + 6273, + 6269, + 6355, + 6359, + 0, + 6269, + 6266, + 6352, + 6355, + 0, + 6266, + 6262, + 6348, + 6352, + 0, + 6262, + 6258, + 6342, + 6348, + 0, + 6258, + 6254, + 6338, + 6342, + 0, + 6254, + 6251, + 6334, + 6338, + 0, + 6251, + 6249, + 6331, + 6334, + 0, + 6249, + 6247, + 6329, + 6331, + 0, + 6247, + 6246, + 6328, + 6329, + 0, + 6246, + 6240, + 6325, + 6328, + 0, + 6240, + 6238, + 6320, + 6325, + 0, + 6238, + 6236, + 6318, + 6320, + 0, + 6236, + 6233, + 6315, + 6318, + 0, + 6233, + 6234, + 6316, + 6315, + 0, + 6234, + 6235, + 6317, + 6316, + 0, + 6235, + 6237, + 6319, + 6317, + 0, + 6237, + 6239, + 6321, + 6319, + 0, + 6239, + 6241, + 6326, + 6321, + 0, + 6241, + 6245, + 6327, + 6326, + 0, + 6245, + 6248, + 6330, + 6327, + 0, + 6248, + 6250, + 6332, + 6330, + 0, + 6250, + 6252, + 6336, + 6332, + 0, + 6252, + 6257, + 6340, + 6336, + 0, + 6257, + 6261, + 6344, + 6340, + 0, + 6261, + 6263, + 6350, + 6344, + 0, + 6263, + 6267, + 6354, + 6350, + 0, + 6267, + 6271, + 6358, + 6354, + 0, + 6271, + 6275, + 6362, + 6358, + 0, + 6275, + 6279, + 6364, + 6362, + 0, + 6279, + 6281, + 6368, + 6364, + 0, + 6281, + 6285, + 6373, + 6368, + 0, + 6285, + 6287, + 6376, + 6373, + 0, + 6287, + 6294, + 6384, + 6376, + 0, + 6294, + 6302, + 6396, + 6384, + 0, + 6302, + 6304, + 6398, + 6396, + 0, + 6304, + 6305, + 6399, + 6398, + 0, + 6305, + 6303, + 6397, + 6399, + 0, + 6303, + 6301, + 6393, + 6397, + 0, + 6301, + 6299, + 6388, + 6393, + 0, + 6299, + 6296, + 6383, + 6388, + 0, + 6296, + 6293, + 6379, + 6383, + 0, + 6293, + 6290, + 6375, + 6379, + 0, + 6290, + 6286, + 6370, + 6375, + 0, + 6286, + 6283, + 6366, + 6370, + 0, + 6283, + 6277, + 6361, + 6366, + 0, + 6277, + 6272, + 6356, + 6361, + 0, + 6272, + 6268, + 6351, + 6356, + 0, + 6268, + 6264, + 6346, + 6351, + 0, + 6264, + 6260, + 6341, + 6346, + 0, + 6260, + 6256, + 6337, + 6341, + 0, + 6256, + 6253, + 6333, + 6337, + 0, + 6253, + 6243, + 6324, + 6333, + 0, + 6243, + 6242, + 6322, + 6324, + 0, + 6322, + 6323, + 6391, + 6387, + 0, + 6323, + 6335, + 6417, + 6391, + 0, + 6335, + 6339, + 6421, + 6417, + 0, + 6339, + 6347, + 6427, + 6421, + 0, + 6347, + 6353, + 6432, + 6427, + 0, + 6353, + 6357, + 6436, + 6432, + 0, + 6357, + 6360, + 6439, + 6436, + 0, + 6360, + 6365, + 6443, + 6439, + 0, + 6365, + 6371, + 6449, + 6443, + 0, + 6371, + 6378, + 6454, + 6449, + 0, + 6378, + 6385, + 6459, + 6454, + 0, + 6385, + 6389, + 6463, + 6459, + 0, + 6389, + 6400, + 6470, + 6463, + 0, + 6400, + 6401, + 6471, + 6470, + 0, + 6401, + 6402, + 6472, + 6471, + 0, + 6402, + 6405, + 6473, + 6472, + 0, + 6405, + 6406, + 6474, + 6473, + 0, + 6406, + 6408, + 6476, + 6474, + 0, + 6408, + 6410, + 6478, + 6476, + 0, + 6410, + 6409, + 6477, + 6478, + 0, + 6409, + 6407, + 6475, + 6477, + 0, + 6407, + 6390, + 6464, + 6475, + 0, + 6390, + 6386, + 6461, + 6464, + 0, + 6386, + 6382, + 6457, + 6461, + 0, + 6382, + 6377, + 6455, + 6457, + 0, + 6377, + 6374, + 6451, + 6455, + 0, + 6374, + 6367, + 6446, + 6451, + 0, + 6367, + 6363, + 6442, + 6446, + 0, + 6363, + 6359, + 6438, + 6442, + 0, + 6359, + 6355, + 6435, + 6438, + 0, + 6355, + 6352, + 6431, + 6435, + 0, + 6352, + 6348, + 6428, + 6431, + 0, + 6348, + 6342, + 6424, + 6428, + 0, + 6342, + 6338, + 6420, + 6424, + 0, + 6338, + 6334, + 6416, + 6420, + 0, + 6334, + 6331, + 6413, + 6416, + 0, + 6331, + 6329, + 6411, + 6413, + 0, + 6329, + 6328, + 6404, + 6411, + 0, + 6328, + 6325, + 6394, + 6404, + 0, + 6325, + 6320, + 6380, + 6394, + 0, + 6320, + 6318, + 6369, + 6380, + 0, + 6318, + 6315, + 6343, + 6369, + 0, + 6315, + 6316, + 6345, + 6343, + 0, + 6316, + 6317, + 6349, + 6345, + 0, + 6317, + 6319, + 6372, + 6349, + 0, + 6319, + 6321, + 6381, + 6372, + 0, + 6321, + 6326, + 6395, + 6381, + 0, + 6326, + 6327, + 6403, + 6395, + 0, + 6327, + 6330, + 6412, + 6403, + 0, + 6330, + 6332, + 6414, + 6412, + 0, + 6332, + 6336, + 6418, + 6414, + 0, + 6336, + 6340, + 6423, + 6418, + 0, + 6340, + 6344, + 6425, + 6423, + 0, + 6344, + 6350, + 6429, + 6425, + 0, + 6350, + 6354, + 6433, + 6429, + 0, + 6354, + 6358, + 6437, + 6433, + 0, + 6358, + 6362, + 6441, + 6437, + 0, + 6362, + 6364, + 6444, + 6441, + 0, + 6364, + 6368, + 6447, + 6444, + 0, + 6368, + 6373, + 6450, + 6447, + 0, + 6373, + 6376, + 6453, + 6450, + 0, + 6376, + 6384, + 6460, + 6453, + 0, + 6384, + 6396, + 6466, + 6460, + 0, + 6396, + 6398, + 6468, + 6466, + 0, + 6398, + 6399, + 6469, + 6468, + 0, + 6399, + 6397, + 6467, + 6469, + 0, + 6397, + 6393, + 6465, + 6467, + 0, + 6393, + 6388, + 6462, + 6465, + 0, + 6388, + 6383, + 6458, + 6462, + 0, + 6383, + 6379, + 6456, + 6458, + 0, + 6379, + 6375, + 6452, + 6456, + 0, + 6375, + 6370, + 6448, + 6452, + 0, + 6370, + 6366, + 6445, + 6448, + 0, + 6366, + 6361, + 6440, + 6445, + 0, + 6361, + 6356, + 6434, + 6440, + 0, + 6356, + 6351, + 6430, + 6434, + 0, + 6351, + 6346, + 6426, + 6430, + 0, + 6346, + 6341, + 6422, + 6426, + 0, + 6341, + 6337, + 6419, + 6422, + 0, + 6337, + 6333, + 6415, + 6419, + 0, + 6333, + 6324, + 6392, + 6415, + 0, + 6324, + 6322, + 6387, + 6392, + 0, + 6387, + 6391, + 6485, + 6484, + 0, + 6391, + 6417, + 6496, + 6485, + 0, + 6417, + 6421, + 6501, + 6496, + 0, + 6421, + 6427, + 6506, + 6501, + 0, + 6427, + 6432, + 6511, + 6506, + 0, + 6432, + 6436, + 6515, + 6511, + 0, + 6436, + 6439, + 6518, + 6515, + 0, + 6439, + 6443, + 6522, + 6518, + 0, + 6443, + 6449, + 6527, + 6522, + 0, + 6449, + 6454, + 6533, + 6527, + 0, + 6454, + 6459, + 6538, + 6533, + 0, + 6459, + 6463, + 6543, + 6538, + 0, + 6463, + 6470, + 6547, + 6543, + 0, + 6470, + 6471, + 6553, + 6547, + 0, + 6471, + 6472, + 6554, + 6553, + 0, + 6472, + 6473, + 6555, + 6554, + 0, + 6473, + 6474, + 6556, + 6555, + 0, + 6474, + 6476, + 6557, + 6556, + 0, + 6476, + 6478, + 6559, + 6557, + 0, + 6478, + 6477, + 6560, + 6559, + 0, + 6477, + 6475, + 6558, + 6560, + 0, + 6475, + 6464, + 6552, + 6558, + 0, + 6464, + 6461, + 6546, + 6552, + 0, + 6461, + 6457, + 6544, + 6546, + 0, + 6457, + 6455, + 6540, + 6544, + 0, + 6455, + 6451, + 6536, + 6540, + 0, + 6451, + 6446, + 6532, + 6536, + 0, + 6446, + 6442, + 6528, + 6532, + 0, + 6442, + 6438, + 6523, + 6528, + 0, + 6438, + 6435, + 6520, + 6523, + 0, + 6435, + 6431, + 6516, + 6520, + 0, + 6431, + 6428, + 6512, + 6516, + 0, + 6428, + 6424, + 6508, + 6512, + 0, + 6424, + 6420, + 6504, + 6508, + 0, + 6420, + 6416, + 6500, + 6504, + 0, + 6416, + 6413, + 6497, + 6500, + 0, + 6413, + 6411, + 6494, + 6497, + 0, + 6411, + 6404, + 6492, + 6494, + 0, + 6404, + 6394, + 6490, + 6492, + 0, + 6394, + 6380, + 6487, + 6490, + 0, + 6380, + 6369, + 6482, + 6487, + 0, + 6369, + 6343, + 6479, + 6482, + 0, + 6343, + 6345, + 6480, + 6479, + 0, + 6345, + 6349, + 6481, + 6480, + 0, + 6349, + 6372, + 6483, + 6481, + 0, + 6372, + 6381, + 6488, + 6483, + 0, + 6381, + 6395, + 6489, + 6488, + 0, + 6395, + 6403, + 6491, + 6489, + 0, + 6403, + 6412, + 6493, + 6491, + 0, + 6412, + 6414, + 6498, + 6493, + 0, + 6414, + 6418, + 6503, + 6498, + 0, + 6418, + 6423, + 6507, + 6503, + 0, + 6423, + 6425, + 6509, + 6507, + 0, + 6425, + 6429, + 6513, + 6509, + 0, + 6429, + 6433, + 6517, + 6513, + 0, + 6433, + 6437, + 6521, + 6517, + 0, + 6437, + 6441, + 6525, + 6521, + 0, + 6441, + 6444, + 6529, + 6525, + 0, + 6444, + 6447, + 6531, + 6529, + 0, + 6447, + 6450, + 6534, + 6531, + 0, + 6450, + 6453, + 6537, + 6534, + 0, + 6453, + 6460, + 6541, + 6537, + 0, + 6460, + 6466, + 6549, + 6541, + 0, + 6466, + 6468, + 6551, + 6549, + 0, + 6468, + 6469, + 6550, + 6551, + 0, + 6469, + 6467, + 6548, + 6550, + 0, + 6467, + 6465, + 6545, + 6548, + 0, + 6465, + 6462, + 6542, + 6545, + 0, + 6462, + 6458, + 6539, + 6542, + 0, + 6458, + 6456, + 6535, + 6539, + 0, + 6456, + 6452, + 6530, + 6535, + 0, + 6452, + 6448, + 6526, + 6530, + 0, + 6448, + 6445, + 6524, + 6526, + 0, + 6445, + 6440, + 6519, + 6524, + 0, + 6440, + 6434, + 6514, + 6519, + 0, + 6434, + 6430, + 6510, + 6514, + 0, + 6430, + 6426, + 6505, + 6510, + 0, + 6426, + 6422, + 6502, + 6505, + 0, + 6422, + 6419, + 6499, + 6502, + 0, + 6419, + 6415, + 6495, + 6499, + 0, + 6415, + 6392, + 6486, + 6495, + 0, + 6392, + 6387, + 6484, + 6486, + 0, + 6484, + 6485, + 6565, + 6564, + 0, + 6485, + 6496, + 6576, + 6565, + 0, + 6496, + 6501, + 6582, + 6576, + 0, + 6501, + 6506, + 6586, + 6582, + 0, + 6506, + 6511, + 6591, + 6586, + 0, + 6511, + 6515, + 6594, + 6591, + 0, + 6515, + 6518, + 6598, + 6594, + 0, + 6518, + 6522, + 6602, + 6598, + 0, + 6522, + 6527, + 6606, + 6602, + 0, + 6527, + 6533, + 6611, + 6606, + 0, + 6533, + 6538, + 6617, + 6611, + 0, + 6538, + 6543, + 6622, + 6617, + 0, + 6543, + 6547, + 6627, + 6622, + 0, + 6547, + 6553, + 6634, + 6627, + 0, + 6553, + 6554, + 6636, + 6634, + 0, + 6554, + 6555, + 6637, + 6636, + 0, + 6555, + 6556, + 6638, + 6637, + 0, + 6556, + 6557, + 6639, + 6638, + 0, + 6557, + 6559, + 6640, + 6639, + 0, + 6559, + 6560, + 6642, + 6640, + 0, + 6560, + 6558, + 6641, + 6642, + 0, + 6558, + 6552, + 6635, + 6641, + 0, + 6552, + 6546, + 6633, + 6635, + 0, + 6546, + 6544, + 6628, + 6633, + 0, + 6544, + 6540, + 6624, + 6628, + 0, + 6540, + 6536, + 6621, + 6624, + 0, + 6536, + 6532, + 6616, + 6621, + 0, + 6532, + 6528, + 6612, + 6616, + 0, + 6528, + 6523, + 6608, + 6612, + 0, + 6523, + 6520, + 6603, + 6608, + 0, + 6520, + 6516, + 6600, + 6603, + 0, + 6516, + 6512, + 6596, + 6600, + 0, + 6512, + 6508, + 6592, + 6596, + 0, + 6508, + 6504, + 6588, + 6592, + 0, + 6504, + 6500, + 6584, + 6588, + 0, + 6500, + 6497, + 6580, + 6584, + 0, + 6497, + 6494, + 6578, + 6580, + 0, + 6494, + 6492, + 6574, + 6578, + 0, + 6492, + 6490, + 6572, + 6574, + 0, + 6490, + 6487, + 6569, + 6572, + 0, + 6487, + 6482, + 6566, + 6569, + 0, + 6482, + 6479, + 6561, + 6566, + 0, + 6479, + 6480, + 6562, + 6561, + 0, + 6480, + 6481, + 6563, + 6562, + 0, + 6481, + 6483, + 6568, + 6563, + 0, + 6483, + 6488, + 6570, + 6568, + 0, + 6488, + 6489, + 6571, + 6570, + 0, + 6489, + 6491, + 6573, + 6571, + 0, + 6491, + 6493, + 6577, + 6573, + 0, + 6493, + 6498, + 6581, + 6577, + 0, + 6498, + 6503, + 6585, + 6581, + 0, + 6503, + 6507, + 6589, + 6585, + 0, + 6507, + 6509, + 6593, + 6589, + 0, + 6509, + 6513, + 6597, + 6593, + 0, + 6513, + 6517, + 6601, + 6597, + 0, + 6517, + 6521, + 6605, + 6601, + 0, + 6521, + 6525, + 6609, + 6605, + 0, + 6525, + 6529, + 6613, + 6609, + 0, + 6529, + 6531, + 6615, + 6613, + 0, + 6531, + 6534, + 6618, + 6615, + 0, + 6534, + 6537, + 6620, + 6618, + 0, + 6537, + 6541, + 6625, + 6620, + 0, + 6541, + 6549, + 6631, + 6625, + 0, + 6549, + 6551, + 6632, + 6631, + 0, + 6551, + 6550, + 6630, + 6632, + 0, + 6550, + 6548, + 6629, + 6630, + 0, + 6548, + 6545, + 6626, + 6629, + 0, + 6545, + 6542, + 6623, + 6626, + 0, + 6542, + 6539, + 6619, + 6623, + 0, + 6539, + 6535, + 6614, + 6619, + 0, + 6535, + 6530, + 6610, + 6614, + 0, + 6530, + 6526, + 6607, + 6610, + 0, + 6526, + 6524, + 6604, + 6607, + 0, + 6524, + 6519, + 6599, + 6604, + 0, + 6519, + 6514, + 6595, + 6599, + 0, + 6514, + 6510, + 6590, + 6595, + 0, + 6510, + 6505, + 6587, + 6590, + 0, + 6505, + 6502, + 6583, + 6587, + 0, + 6502, + 6499, + 6579, + 6583, + 0, + 6499, + 6495, + 6575, + 6579, + 0, + 6495, + 6486, + 6567, + 6575, + 0, + 6486, + 6484, + 6564, + 6567, + 0, + 6564, + 6565, + 6647, + 6646, + 0, + 6565, + 6576, + 6658, + 6647, + 0, + 6576, + 6582, + 6662, + 6658, + 0, + 6582, + 6586, + 6667, + 6662, + 0, + 6586, + 6591, + 6672, + 6667, + 0, + 6591, + 6594, + 6676, + 6672, + 0, + 6594, + 6598, + 6680, + 6676, + 0, + 6598, + 6602, + 6684, + 6680, + 0, + 6602, + 6606, + 6688, + 6684, + 0, + 6606, + 6611, + 6693, + 6688, + 0, + 6611, + 6617, + 6698, + 6693, + 0, + 6617, + 6622, + 6704, + 6698, + 0, + 6622, + 6627, + 6709, + 6704, + 0, + 6627, + 6634, + 6715, + 6709, + 0, + 6634, + 6636, + 6718, + 6715, + 0, + 6636, + 6637, + 6719, + 6718, + 0, + 6637, + 6638, + 6720, + 6719, + 0, + 6638, + 6639, + 6721, + 6720, + 0, + 6639, + 6640, + 6722, + 6721, + 0, + 6640, + 6642, + 6724, + 6722, + 0, + 6642, + 6641, + 6723, + 6724, + 0, + 6641, + 6635, + 6717, + 6723, + 0, + 6635, + 6633, + 6716, + 6717, + 0, + 6633, + 6628, + 6711, + 6716, + 0, + 6628, + 6624, + 6706, + 6711, + 0, + 6624, + 6621, + 6703, + 6706, + 0, + 6621, + 6616, + 6699, + 6703, + 0, + 6616, + 6612, + 6695, + 6699, + 0, + 6612, + 6608, + 6690, + 6695, + 0, + 6608, + 6603, + 6686, + 6690, + 0, + 6603, + 6600, + 6682, + 6686, + 0, + 6600, + 6596, + 6678, + 6682, + 0, + 6596, + 6592, + 6674, + 6678, + 0, + 6592, + 6588, + 6670, + 6674, + 0, + 6588, + 6584, + 6666, + 6670, + 0, + 6584, + 6580, + 6663, + 6666, + 0, + 6580, + 6578, + 6661, + 6663, + 0, + 6578, + 6574, + 6656, + 6661, + 0, + 6574, + 6572, + 6654, + 6656, + 0, + 6572, + 6569, + 6651, + 6654, + 0, + 6569, + 6566, + 6649, + 6651, + 0, + 6566, + 6561, + 6643, + 6649, + 0, + 6561, + 6562, + 6644, + 6643, + 0, + 6562, + 6563, + 6645, + 6644, + 0, + 6563, + 6568, + 6650, + 6645, + 0, + 6568, + 6570, + 6652, + 6650, + 0, + 6570, + 6571, + 6653, + 6652, + 0, + 6571, + 6573, + 6655, + 6653, + 0, + 6573, + 6577, + 6659, + 6655, + 0, + 6577, + 6581, + 6665, + 6659, + 0, + 6581, + 6585, + 6669, + 6665, + 0, + 6585, + 6589, + 6673, + 6669, + 0, + 6589, + 6593, + 6675, + 6673, + 0, + 6593, + 6597, + 6679, + 6675, + 0, + 6597, + 6601, + 6683, + 6679, + 0, + 6601, + 6605, + 6687, + 6683, + 0, + 6605, + 6609, + 6691, + 6687, + 0, + 6609, + 6613, + 6694, + 6691, + 0, + 6613, + 6615, + 6697, + 6694, + 0, + 6615, + 6618, + 6701, + 6697, + 0, + 6618, + 6620, + 6702, + 6701, + 0, + 6620, + 6625, + 6707, + 6702, + 0, + 6625, + 6631, + 6713, + 6707, + 0, + 6631, + 6632, + 6714, + 6713, + 0, + 6632, + 6630, + 6712, + 6714, + 0, + 6630, + 6629, + 6710, + 6712, + 0, + 6629, + 6626, + 6708, + 6710, + 0, + 6626, + 6623, + 6705, + 6708, + 0, + 6623, + 6619, + 6700, + 6705, + 0, + 6619, + 6614, + 6696, + 6700, + 0, + 6614, + 6610, + 6692, + 6696, + 0, + 6610, + 6607, + 6689, + 6692, + 0, + 6607, + 6604, + 6685, + 6689, + 0, + 6604, + 6599, + 6681, + 6685, + 0, + 6599, + 6595, + 6677, + 6681, + 0, + 6595, + 6590, + 6671, + 6677, + 0, + 6590, + 6587, + 6668, + 6671, + 0, + 6587, + 6583, + 6664, + 6668, + 0, + 6583, + 6579, + 6660, + 6664, + 0, + 6579, + 6575, + 6657, + 6660, + 0, + 6575, + 6567, + 6648, + 6657, + 0, + 6567, + 6564, + 6646, + 6648, + 0, + 6646, + 6647, + 6729, + 6728, + 0, + 6647, + 6658, + 6738, + 6729, + 0, + 6658, + 6662, + 6742, + 6738, + 0, + 6662, + 6667, + 6748, + 6742, + 0, + 6667, + 6672, + 6753, + 6748, + 0, + 6672, + 6676, + 6756, + 6753, + 0, + 6676, + 6680, + 6760, + 6756, + 0, + 6680, + 6684, + 6764, + 6760, + 0, + 6684, + 6688, + 6768, + 6764, + 0, + 6688, + 6693, + 6773, + 6768, + 0, + 6693, + 6698, + 6777, + 6773, + 0, + 6698, + 6704, + 6782, + 6777, + 0, + 6704, + 6709, + 6787, + 6782, + 0, + 6709, + 6715, + 6793, + 6787, + 0, + 6715, + 6718, + 6798, + 6793, + 0, + 6718, + 6719, + 6801, + 6798, + 0, + 6719, + 6720, + 6802, + 6801, + 0, + 6720, + 6721, + 6803, + 6802, + 0, + 6721, + 6722, + 6804, + 6803, + 0, + 6722, + 6724, + 6806, + 6804, + 0, + 6724, + 6723, + 6805, + 6806, + 0, + 6723, + 6717, + 6800, + 6805, + 0, + 6717, + 6716, + 6799, + 6800, + 0, + 6716, + 6711, + 6797, + 6799, + 0, + 6711, + 6706, + 6792, + 6797, + 0, + 6706, + 6703, + 6788, + 6792, + 0, + 6703, + 6699, + 6783, + 6788, + 0, + 6699, + 6695, + 6779, + 6783, + 0, + 6695, + 6690, + 6774, + 6779, + 0, + 6690, + 6686, + 6770, + 6774, + 0, + 6686, + 6682, + 6766, + 6770, + 0, + 6682, + 6678, + 6762, + 6766, + 0, + 6678, + 6674, + 6758, + 6762, + 0, + 6674, + 6670, + 6754, + 6758, + 0, + 6670, + 6666, + 6750, + 6754, + 0, + 6666, + 6663, + 6746, + 6750, + 0, + 6663, + 6661, + 6744, + 6746, + 0, + 6661, + 6656, + 6741, + 6744, + 0, + 6656, + 6654, + 6736, + 6741, + 0, + 6654, + 6651, + 6733, + 6736, + 0, + 6651, + 6649, + 6731, + 6733, + 0, + 6649, + 6643, + 6725, + 6731, + 0, + 6643, + 6644, + 6726, + 6725, + 0, + 6644, + 6645, + 6727, + 6726, + 0, + 6645, + 6650, + 6732, + 6727, + 0, + 6650, + 6652, + 6734, + 6732, + 0, + 6652, + 6653, + 6735, + 6734, + 0, + 6653, + 6655, + 6739, + 6735, + 0, + 6655, + 6659, + 6743, + 6739, + 0, + 6659, + 6665, + 6747, + 6743, + 0, + 6665, + 6669, + 6751, + 6747, + 0, + 6669, + 6673, + 6755, + 6751, + 0, + 6673, + 6675, + 6759, + 6755, + 0, + 6675, + 6679, + 6763, + 6759, + 0, + 6679, + 6683, + 6767, + 6763, + 0, + 6683, + 6687, + 6771, + 6767, + 0, + 6687, + 6691, + 6775, + 6771, + 0, + 6691, + 6694, + 6778, + 6775, + 0, + 6694, + 6697, + 6781, + 6778, + 0, + 6697, + 6701, + 6785, + 6781, + 0, + 6701, + 6702, + 6786, + 6785, + 0, + 6702, + 6707, + 6790, + 6786, + 0, + 6707, + 6713, + 6795, + 6790, + 0, + 6713, + 6714, + 6796, + 6795, + 0, + 6714, + 6712, + 6794, + 6796, + 0, + 6712, + 6710, + 6791, + 6794, + 0, + 6710, + 6708, + 6789, + 6791, + 0, + 6708, + 6705, + 6784, + 6789, + 0, + 6705, + 6700, + 6780, + 6784, + 0, + 6700, + 6696, + 6776, + 6780, + 0, + 6696, + 6692, + 6772, + 6776, + 0, + 6692, + 6689, + 6769, + 6772, + 0, + 6689, + 6685, + 6765, + 6769, + 0, + 6685, + 6681, + 6761, + 6765, + 0, + 6681, + 6677, + 6757, + 6761, + 0, + 6677, + 6671, + 6752, + 6757, + 0, + 6671, + 6668, + 6749, + 6752, + 0, + 6668, + 6664, + 6745, + 6749, + 0, + 6664, + 6660, + 6740, + 6745, + 0, + 6660, + 6657, + 6737, + 6740, + 0, + 6657, + 6648, + 6730, + 6737, + 0, + 6648, + 6646, + 6728, + 6730, + 0, + 6728, + 6729, + 6811, + 6810, + 0, + 6729, + 6738, + 6819, + 6811, + 0, + 6738, + 6742, + 6823, + 6819, + 0, + 6742, + 6748, + 6828, + 6823, + 0, + 6748, + 6753, + 6832, + 6828, + 0, + 6753, + 6756, + 6836, + 6832, + 0, + 6756, + 6760, + 6840, + 6836, + 0, + 6760, + 6764, + 6844, + 6840, + 0, + 6764, + 6768, + 6848, + 6844, + 0, + 6768, + 6773, + 6852, + 6848, + 0, + 6773, + 6777, + 6857, + 6852, + 0, + 6777, + 6782, + 6861, + 6857, + 0, + 6782, + 6787, + 6866, + 6861, + 0, + 6787, + 6793, + 6872, + 6866, + 0, + 6793, + 6798, + 6879, + 6872, + 0, + 6798, + 6801, + 6881, + 6879, + 0, + 6801, + 6802, + 6883, + 6881, + 0, + 6802, + 6803, + 6885, + 6883, + 0, + 6803, + 6804, + 6886, + 6885, + 0, + 6804, + 6806, + 6887, + 6886, + 0, + 6806, + 6805, + 6888, + 6887, + 0, + 6805, + 6800, + 6884, + 6888, + 0, + 6800, + 6799, + 6882, + 6884, + 0, + 6799, + 6797, + 6880, + 6882, + 0, + 6797, + 6792, + 6878, + 6880, + 0, + 6792, + 6788, + 6874, + 6878, + 0, + 6788, + 6783, + 6869, + 6874, + 0, + 6783, + 6779, + 6864, + 6869, + 0, + 6779, + 6774, + 6859, + 6864, + 0, + 6774, + 6770, + 6855, + 6859, + 0, + 6770, + 6766, + 6851, + 6855, + 0, + 6766, + 6762, + 6847, + 6851, + 0, + 6762, + 6758, + 6842, + 6847, + 0, + 6758, + 6754, + 6838, + 6842, + 0, + 6754, + 6750, + 6834, + 6838, + 0, + 6750, + 6746, + 6831, + 6834, + 0, + 6746, + 6744, + 6827, + 6831, + 0, + 6744, + 6741, + 6824, + 6827, + 0, + 6741, + 6736, + 6820, + 6824, + 0, + 6736, + 6733, + 6816, + 6820, + 0, + 6733, + 6731, + 6813, + 6816, + 0, + 6731, + 6725, + 6807, + 6813, + 0, + 6725, + 6726, + 6808, + 6807, + 0, + 6726, + 6727, + 6809, + 6808, + 0, + 6727, + 6732, + 6814, + 6809, + 0, + 6732, + 6734, + 6815, + 6814, + 0, + 6734, + 6735, + 6818, + 6815, + 0, + 6735, + 6739, + 6822, + 6818, + 0, + 6739, + 6743, + 6826, + 6822, + 0, + 6743, + 6747, + 6830, + 6826, + 0, + 6747, + 6751, + 6835, + 6830, + 0, + 6751, + 6755, + 6839, + 6835, + 0, + 6755, + 6759, + 6843, + 6839, + 0, + 6759, + 6763, + 6846, + 6843, + 0, + 6763, + 6767, + 6850, + 6846, + 0, + 6767, + 6771, + 6854, + 6850, + 0, + 6771, + 6775, + 6858, + 6854, + 0, + 6775, + 6778, + 6862, + 6858, + 0, + 6778, + 6781, + 6865, + 6862, + 0, + 6781, + 6785, + 6868, + 6865, + 0, + 6785, + 6786, + 6870, + 6868, + 0, + 6786, + 6790, + 6873, + 6870, + 0, + 6790, + 6795, + 6877, + 6873, + 0, + 6795, + 6796, + 6876, + 6877, + 0, + 6796, + 6794, + 6875, + 6876, + 0, + 6794, + 6791, + 6871, + 6875, + 0, + 6791, + 6789, + 6867, + 6871, + 0, + 6789, + 6784, + 6863, + 6867, + 0, + 6784, + 6780, + 6860, + 6863, + 0, + 6780, + 6776, + 6856, + 6860, + 0, + 6776, + 6772, + 6853, + 6856, + 0, + 6772, + 6769, + 6849, + 6853, + 0, + 6769, + 6765, + 6845, + 6849, + 0, + 6765, + 6761, + 6841, + 6845, + 0, + 6761, + 6757, + 6837, + 6841, + 0, + 6757, + 6752, + 6833, + 6837, + 0, + 6752, + 6749, + 6829, + 6833, + 0, + 6749, + 6745, + 6825, + 6829, + 0, + 6745, + 6740, + 6821, + 6825, + 0, + 6740, + 6737, + 6817, + 6821, + 0, + 6737, + 6730, + 6812, + 6817, + 0, + 6730, + 6728, + 6810, + 6812, + 0, + 6810, + 6811, + 6893, + 6892, + 0, + 6811, + 6819, + 6900, + 6893, + 0, + 6819, + 6823, + 6904, + 6900, + 0, + 6823, + 6828, + 6908, + 6904, + 0, + 6828, + 6832, + 6912, + 6908, + 0, + 6832, + 6836, + 6916, + 6912, + 0, + 6836, + 6840, + 6920, + 6916, + 0, + 6840, + 6844, + 6924, + 6920, + 0, + 6844, + 6848, + 6928, + 6924, + 0, + 6848, + 6852, + 6932, + 6928, + 0, + 6852, + 6857, + 6937, + 6932, + 0, + 6857, + 6861, + 6941, + 6937, + 0, + 6861, + 6866, + 6946, + 6941, + 0, + 6866, + 6872, + 6951, + 6946, + 0, + 6872, + 6879, + 6959, + 6951, + 0, + 6879, + 6881, + 6962, + 6959, + 0, + 6881, + 6883, + 6964, + 6962, + 0, + 6883, + 6885, + 6966, + 6964, + 0, + 6885, + 6886, + 6968, + 6966, + 0, + 6886, + 6887, + 6969, + 6968, + 0, + 6887, + 6888, + 6970, + 6969, + 0, + 6888, + 6884, + 6967, + 6970, + 0, + 6884, + 6882, + 6965, + 6967, + 0, + 6882, + 6880, + 6963, + 6965, + 0, + 6880, + 6878, + 6961, + 6963, + 0, + 6878, + 6874, + 6960, + 6961, + 0, + 6874, + 6869, + 6954, + 6960, + 0, + 6869, + 6864, + 6947, + 6954, + 0, + 6864, + 6859, + 6943, + 6947, + 0, + 6859, + 6855, + 6939, + 6943, + 0, + 6855, + 6851, + 6935, + 6939, + 0, + 6851, + 6847, + 6931, + 6935, + 0, + 6847, + 6842, + 6925, + 6931, + 0, + 6842, + 6838, + 6922, + 6925, + 0, + 6838, + 6834, + 6918, + 6922, + 0, + 6834, + 6831, + 6915, + 6918, + 0, + 6831, + 6827, + 6911, + 6915, + 0, + 6827, + 6824, + 6907, + 6911, + 0, + 6824, + 6820, + 6903, + 6907, + 0, + 6820, + 6816, + 6898, + 6903, + 0, + 6816, + 6813, + 6895, + 6898, + 0, + 6813, + 6807, + 6889, + 6895, + 0, + 6807, + 6808, + 6890, + 6889, + 0, + 6808, + 6809, + 6891, + 6890, + 0, + 6809, + 6814, + 6896, + 6891, + 0, + 6814, + 6815, + 6897, + 6896, + 0, + 6815, + 6818, + 6902, + 6897, + 0, + 6818, + 6822, + 6906, + 6902, + 0, + 6822, + 6826, + 6910, + 6906, + 0, + 6826, + 6830, + 6914, + 6910, + 0, + 6830, + 6835, + 6919, + 6914, + 0, + 6835, + 6839, + 6923, + 6919, + 0, + 6839, + 6843, + 6927, + 6923, + 0, + 6843, + 6846, + 6929, + 6927, + 0, + 6846, + 6850, + 6934, + 6929, + 0, + 6850, + 6854, + 6938, + 6934, + 0, + 6854, + 6858, + 6942, + 6938, + 0, + 6858, + 6862, + 6945, + 6942, + 0, + 6862, + 6865, + 6949, + 6945, + 0, + 6865, + 6868, + 6950, + 6949, + 0, + 6868, + 6870, + 6953, + 6950, + 0, + 6870, + 6873, + 6956, + 6953, + 0, + 6873, + 6877, + 6958, + 6956, + 0, + 6877, + 6876, + 6957, + 6958, + 0, + 6876, + 6875, + 6955, + 6957, + 0, + 6875, + 6871, + 6952, + 6955, + 0, + 6871, + 6867, + 6948, + 6952, + 0, + 6867, + 6863, + 6944, + 6948, + 0, + 6863, + 6860, + 6940, + 6944, + 0, + 6860, + 6856, + 6936, + 6940, + 0, + 6856, + 6853, + 6933, + 6936, + 0, + 6853, + 6849, + 6930, + 6933, + 0, + 6849, + 6845, + 6926, + 6930, + 0, + 6845, + 6841, + 6921, + 6926, + 0, + 6841, + 6837, + 6917, + 6921, + 0, + 6837, + 6833, + 6913, + 6917, + 0, + 6833, + 6829, + 6909, + 6913, + 0, + 6829, + 6825, + 6905, + 6909, + 0, + 6825, + 6821, + 6901, + 6905, + 0, + 6821, + 6817, + 6899, + 6901, + 0, + 6817, + 6812, + 6894, + 6899, + 0, + 6812, + 6810, + 6892, + 6894, + 0, + 6892, + 6893, + 6975, + 6974, + 0, + 6893, + 6900, + 6980, + 6975, + 0, + 6900, + 6904, + 6985, + 6980, + 0, + 6904, + 6908, + 6989, + 6985, + 0, + 6908, + 6912, + 6994, + 6989, + 0, + 6912, + 6916, + 6998, + 6994, + 0, + 6916, + 6920, + 7001, + 6998, + 0, + 6920, + 6924, + 7005, + 7001, + 0, + 6924, + 6928, + 7010, + 7005, + 0, + 6928, + 6932, + 7014, + 7010, + 0, + 6932, + 6937, + 7019, + 7014, + 0, + 6937, + 6941, + 7023, + 7019, + 0, + 6941, + 6946, + 7027, + 7023, + 0, + 6946, + 6951, + 7032, + 7027, + 0, + 6951, + 6959, + 7040, + 7032, + 0, + 6959, + 6962, + 7043, + 7040, + 0, + 6962, + 6964, + 7045, + 7043, + 0, + 6964, + 6966, + 7047, + 7045, + 0, + 6966, + 6968, + 7050, + 7047, + 0, + 6968, + 6969, + 7051, + 7050, + 0, + 6969, + 6970, + 7052, + 7051, + 0, + 6970, + 6967, + 7049, + 7052, + 0, + 6967, + 6965, + 7048, + 7049, + 0, + 6965, + 6963, + 7046, + 7048, + 0, + 6963, + 6961, + 7044, + 7046, + 0, + 6961, + 6960, + 7042, + 7044, + 0, + 6960, + 6954, + 7037, + 7042, + 0, + 6954, + 6947, + 7030, + 7037, + 0, + 6947, + 6943, + 7026, + 7030, + 0, + 6943, + 6939, + 7022, + 7026, + 0, + 6939, + 6935, + 7017, + 7022, + 0, + 6935, + 6931, + 7013, + 7017, + 0, + 6931, + 6925, + 7008, + 7013, + 0, + 6925, + 6922, + 7004, + 7008, + 0, + 6922, + 6918, + 7000, + 7004, + 0, + 6918, + 6915, + 6997, + 7000, + 0, + 6915, + 6911, + 6993, + 6997, + 0, + 6911, + 6907, + 6991, + 6993, + 0, + 6907, + 6903, + 6986, + 6991, + 0, + 6903, + 6898, + 6982, + 6986, + 0, + 6898, + 6895, + 6977, + 6982, + 0, + 6895, + 6889, + 6971, + 6977, + 0, + 6889, + 6890, + 6972, + 6971, + 0, + 6890, + 6891, + 6973, + 6972, + 0, + 6891, + 6896, + 6978, + 6973, + 0, + 6896, + 6897, + 6981, + 6978, + 0, + 6897, + 6902, + 6984, + 6981, + 0, + 6902, + 6906, + 6988, + 6984, + 0, + 6906, + 6910, + 6992, + 6988, + 0, + 6910, + 6914, + 6996, + 6992, + 0, + 6914, + 6919, + 7002, + 6996, + 0, + 6919, + 6923, + 7006, + 7002, + 0, + 6923, + 6927, + 7009, + 7006, + 0, + 6927, + 6929, + 7012, + 7009, + 0, + 6929, + 6934, + 7016, + 7012, + 0, + 6934, + 6938, + 7021, + 7016, + 0, + 6938, + 6942, + 7024, + 7021, + 0, + 6942, + 6945, + 7028, + 7024, + 0, + 6945, + 6949, + 7031, + 7028, + 0, + 6949, + 6950, + 7034, + 7031, + 0, + 6950, + 6953, + 7035, + 7034, + 0, + 6953, + 6956, + 7038, + 7035, + 0, + 6956, + 6958, + 7041, + 7038, + 0, + 6958, + 6957, + 7039, + 7041, + 0, + 6957, + 6955, + 7036, + 7039, + 0, + 6955, + 6952, + 7033, + 7036, + 0, + 6952, + 6948, + 7029, + 7033, + 0, + 6948, + 6944, + 7025, + 7029, + 0, + 6944, + 6940, + 7020, + 7025, + 0, + 6940, + 6936, + 7018, + 7020, + 0, + 6936, + 6933, + 7015, + 7018, + 0, + 6933, + 6930, + 7011, + 7015, + 0, + 6930, + 6926, + 7007, + 7011, + 0, + 6926, + 6921, + 7003, + 7007, + 0, + 6921, + 6917, + 6999, + 7003, + 0, + 6917, + 6913, + 6995, + 6999, + 0, + 6913, + 6909, + 6990, + 6995, + 0, + 6909, + 6905, + 6987, + 6990, + 0, + 6905, + 6901, + 6983, + 6987, + 0, + 6901, + 6899, + 6979, + 6983, + 0, + 6899, + 6894, + 6976, + 6979, + 0, + 6894, + 6892, + 6974, + 6976, + 0, + 6974, + 6975, + 7053, + 7054, + 0, + 6975, + 6980, + 7059, + 7053, + 0, + 6980, + 6985, + 7065, + 7059, + 0, + 6985, + 6989, + 7069, + 7065, + 0, + 6989, + 6994, + 7073, + 7069, + 0, + 6994, + 6998, + 7077, + 7073, + 0, + 6998, + 7001, + 7081, + 7077, + 0, + 7001, + 7005, + 7084, + 7081, + 0, + 7005, + 7010, + 7088, + 7084, + 0, + 7010, + 7014, + 7092, + 7088, + 0, + 7014, + 7019, + 7097, + 7092, + 0, + 7019, + 7023, + 7102, + 7097, + 0, + 7023, + 7027, + 7106, + 7102, + 0, + 7027, + 7032, + 7110, + 7106, + 0, + 7032, + 7040, + 7116, + 7110, + 0, + 7040, + 7043, + 7123, + 7116, + 0, + 7043, + 7045, + 7125, + 7123, + 0, + 7045, + 7047, + 7127, + 7125, + 0, + 7047, + 7050, + 7129, + 7127, + 0, + 7050, + 7051, + 7131, + 7129, + 0, + 7051, + 7052, + 7133, + 7131, + 0, + 7052, + 7049, + 7134, + 7133, + 0, + 7049, + 7048, + 7132, + 7134, + 0, + 7048, + 7046, + 7130, + 7132, + 0, + 7046, + 7044, + 7128, + 7130, + 0, + 7044, + 7042, + 7126, + 7128, + 0, + 7042, + 7037, + 7124, + 7126, + 0, + 7037, + 7030, + 7117, + 7124, + 0, + 7030, + 7026, + 7111, + 7117, + 0, + 7026, + 7022, + 7107, + 7111, + 0, + 7022, + 7017, + 7103, + 7107, + 0, + 7017, + 7013, + 7099, + 7103, + 0, + 7013, + 7008, + 7094, + 7099, + 0, + 7008, + 7004, + 7089, + 7094, + 0, + 7004, + 7000, + 7085, + 7089, + 0, + 7000, + 6997, + 7082, + 7085, + 0, + 6997, + 6993, + 7078, + 7082, + 0, + 6993, + 6991, + 7074, + 7078, + 0, + 6991, + 6986, + 7070, + 7074, + 0, + 6986, + 6982, + 7066, + 7070, + 0, + 6982, + 6977, + 7062, + 7066, + 0, + 6977, + 6971, + 7056, + 7062, + 0, + 6971, + 6972, + 7055, + 7056, + 0, + 6972, + 6973, + 7058, + 7055, + 0, + 6973, + 6978, + 7061, + 7058, + 0, + 6978, + 6981, + 7064, + 7061, + 0, + 6981, + 6984, + 7068, + 7064, + 0, + 6984, + 6988, + 7072, + 7068, + 0, + 6988, + 6992, + 7076, + 7072, + 0, + 6992, + 6996, + 7080, + 7076, + 0, + 6996, + 7002, + 7086, + 7080, + 0, + 7002, + 7006, + 7090, + 7086, + 0, + 7006, + 7009, + 7093, + 7090, + 0, + 7009, + 7012, + 7096, + 7093, + 0, + 7012, + 7016, + 7101, + 7096, + 0, + 7016, + 7021, + 7105, + 7101, + 0, + 7021, + 7024, + 7109, + 7105, + 0, + 7024, + 7028, + 7113, + 7109, + 0, + 7028, + 7031, + 7115, + 7113, + 0, + 7031, + 7034, + 7119, + 7115, + 0, + 7034, + 7035, + 7122, + 7119, + 0, + 7035, + 7038, + 7121, + 7122, + 0, + 7038, + 7041, + 7120, + 7121, + 0, + 7041, + 7039, + 7118, + 7120, + 0, + 7039, + 7036, + 7114, + 7118, + 0, + 7036, + 7033, + 7112, + 7114, + 0, + 7033, + 7029, + 7108, + 7112, + 0, + 7029, + 7025, + 7104, + 7108, + 0, + 7025, + 7020, + 7100, + 7104, + 0, + 7020, + 7018, + 7098, + 7100, + 0, + 7018, + 7015, + 7095, + 7098, + 0, + 7015, + 7011, + 7091, + 7095, + 0, + 7011, + 7007, + 7087, + 7091, + 0, + 7007, + 7003, + 7083, + 7087, + 0, + 7003, + 6999, + 7079, + 7083, + 0, + 6999, + 6995, + 7075, + 7079, + 0, + 6995, + 6990, + 7071, + 7075, + 0, + 6990, + 6987, + 7067, + 7071, + 0, + 6987, + 6983, + 7063, + 7067, + 0, + 6983, + 6979, + 7060, + 7063, + 0, + 6979, + 6976, + 7057, + 7060, + 0, + 6976, + 6974, + 7054, + 7057, + 0, + 7054, + 7053, + 7135, + 7136, + 0, + 7053, + 7059, + 7141, + 7135, + 0, + 7059, + 7065, + 7145, + 7141, + 0, + 7065, + 7069, + 7150, + 7145, + 0, + 7069, + 7073, + 7157, + 7150, + 0, + 7073, + 7077, + 7163, + 7157, + 0, + 7077, + 7081, + 7167, + 7163, + 0, + 7081, + 7084, + 7170, + 7167, + 0, + 7084, + 7088, + 7174, + 7170, + 0, + 7088, + 7092, + 7180, + 7174, + 0, + 7092, + 7097, + 7188, + 7180, + 0, + 7097, + 7102, + 7195, + 7188, + 0, + 7102, + 7106, + 7203, + 7195, + 0, + 7106, + 7110, + 7208, + 7203, + 0, + 7110, + 7116, + 7215, + 7208, + 0, + 7116, + 7123, + 7222, + 7215, + 0, + 7123, + 7125, + 7230, + 7222, + 0, + 7125, + 7127, + 7233, + 7230, + 0, + 7127, + 7129, + 7237, + 7233, + 0, + 7129, + 7131, + 7239, + 7237, + 0, + 7131, + 7133, + 7241, + 7239, + 0, + 7133, + 7134, + 7245, + 7241, + 0, + 7134, + 7132, + 7244, + 7245, + 0, + 7132, + 7130, + 7243, + 7244, + 0, + 7130, + 7128, + 7240, + 7243, + 0, + 7128, + 7126, + 7236, + 7240, + 0, + 7126, + 7124, + 7232, + 7236, + 0, + 7124, + 7117, + 7227, + 7232, + 0, + 7117, + 7111, + 7217, + 7227, + 0, + 7111, + 7107, + 7209, + 7217, + 0, + 7107, + 7103, + 7204, + 7209, + 0, + 7103, + 7099, + 7197, + 7204, + 0, + 7099, + 7094, + 7191, + 7197, + 0, + 7094, + 7089, + 7182, + 7191, + 0, + 7089, + 7085, + 7176, + 7182, + 0, + 7085, + 7082, + 7172, + 7176, + 0, + 7082, + 7078, + 7168, + 7172, + 0, + 7078, + 7074, + 7164, + 7168, + 0, + 7074, + 7070, + 7156, + 7164, + 0, + 7070, + 7066, + 7149, + 7156, + 0, + 7066, + 7062, + 7146, + 7149, + 0, + 7062, + 7056, + 7139, + 7146, + 0, + 7056, + 7055, + 7138, + 7139, + 0, + 7055, + 7058, + 7140, + 7138, + 0, + 7058, + 7061, + 7144, + 7140, + 0, + 7061, + 7064, + 7148, + 7144, + 0, + 7064, + 7068, + 7154, + 7148, + 0, + 7068, + 7072, + 7161, + 7154, + 0, + 7072, + 7076, + 7166, + 7161, + 0, + 7076, + 7080, + 7171, + 7166, + 0, + 7080, + 7086, + 7175, + 7171, + 0, + 7086, + 7090, + 7184, + 7175, + 0, + 7090, + 7093, + 7190, + 7184, + 0, + 7093, + 7096, + 7194, + 7190, + 0, + 7096, + 7101, + 7202, + 7194, + 0, + 7101, + 7105, + 7207, + 7202, + 0, + 7105, + 7109, + 7214, + 7207, + 0, + 7109, + 7113, + 7218, + 7214, + 0, + 7113, + 7115, + 7223, + 7218, + 0, + 7115, + 7119, + 7226, + 7223, + 0, + 7119, + 7122, + 7228, + 7226, + 0, + 7122, + 7121, + 7225, + 7228, + 0, + 7121, + 7120, + 7221, + 7225, + 0, + 7120, + 7118, + 7219, + 7221, + 0, + 7118, + 7114, + 7216, + 7219, + 0, + 7114, + 7112, + 7212, + 7216, + 0, + 7112, + 7108, + 7205, + 7212, + 0, + 7108, + 7104, + 7200, + 7205, + 0, + 7104, + 7100, + 7193, + 7200, + 0, + 7100, + 7098, + 7189, + 7193, + 0, + 7098, + 7095, + 7183, + 7189, + 0, + 7095, + 7091, + 7179, + 7183, + 0, + 7091, + 7087, + 7173, + 7179, + 0, + 7087, + 7083, + 7169, + 7173, + 0, + 7083, + 7079, + 7165, + 7169, + 0, + 7079, + 7075, + 7158, + 7165, + 0, + 7075, + 7071, + 7151, + 7158, + 0, + 7071, + 7067, + 7147, + 7151, + 0, + 7067, + 7063, + 7143, + 7147, + 0, + 7063, + 7060, + 7142, + 7143, + 0, + 7060, + 7057, + 7137, + 7142, + 0, + 7057, + 7054, + 7136, + 7137, + 0, + 7136, + 7135, + 7152, + 7153, + 0, + 7135, + 7141, + 7177, + 7152, + 0, + 7141, + 7145, + 7185, + 7177, + 0, + 7145, + 7150, + 7198, + 7185, + 0, + 7150, + 7157, + 7210, + 7198, + 0, + 7157, + 7163, + 7224, + 7210, + 0, + 7163, + 7167, + 7235, + 7224, + 0, + 7167, + 7170, + 7246, + 7235, + 0, + 7170, + 7174, + 7250, + 7246, + 0, + 7174, + 7180, + 7254, + 7250, + 0, + 7180, + 7188, + 7258, + 7254, + 0, + 7188, + 7195, + 7263, + 7258, + 0, + 7195, + 7203, + 7267, + 7263, + 0, + 7203, + 7208, + 7272, + 7267, + 0, + 7208, + 7215, + 7276, + 7272, + 0, + 7215, + 7222, + 7282, + 7276, + 0, + 7222, + 7230, + 7288, + 7282, + 0, + 7230, + 7233, + 7290, + 7288, + 0, + 7233, + 7237, + 7291, + 7290, + 0, + 7237, + 7239, + 7293, + 7291, + 0, + 7239, + 7241, + 7295, + 7293, + 0, + 7241, + 7245, + 7298, + 7295, + 0, + 7245, + 7244, + 7297, + 7298, + 0, + 7244, + 7243, + 7296, + 7297, + 0, + 7243, + 7240, + 7294, + 7296, + 0, + 7240, + 7236, + 7292, + 7294, + 0, + 7236, + 7232, + 7289, + 7292, + 0, + 7232, + 7227, + 7286, + 7289, + 0, + 7227, + 7217, + 7278, + 7286, + 0, + 7217, + 7209, + 7273, + 7278, + 0, + 7209, + 7204, + 7269, + 7273, + 0, + 7204, + 7197, + 7265, + 7269, + 0, + 7197, + 7191, + 7261, + 7265, + 0, + 7191, + 7182, + 7255, + 7261, + 0, + 7182, + 7176, + 7252, + 7255, + 0, + 7176, + 7172, + 7248, + 7252, + 0, + 7172, + 7168, + 7238, + 7248, + 0, + 7168, + 7164, + 7229, + 7238, + 0, + 7164, + 7156, + 7211, + 7229, + 0, + 7156, + 7149, + 7199, + 7211, + 0, + 7149, + 7146, + 7187, + 7199, + 0, + 7146, + 7139, + 7160, + 7187, + 0, + 7139, + 7138, + 7159, + 7160, + 0, + 7138, + 7140, + 7162, + 7159, + 0, + 7140, + 7144, + 7186, + 7162, + 0, + 7144, + 7148, + 7196, + 7186, + 0, + 7148, + 7154, + 7206, + 7196, + 0, + 7154, + 7161, + 7220, + 7206, + 0, + 7161, + 7166, + 7234, + 7220, + 0, + 7166, + 7171, + 7247, + 7234, + 0, + 7171, + 7175, + 7251, + 7247, + 0, + 7175, + 7184, + 7257, + 7251, + 0, + 7184, + 7190, + 7260, + 7257, + 0, + 7190, + 7194, + 7264, + 7260, + 0, + 7194, + 7202, + 7268, + 7264, + 0, + 7202, + 7207, + 7271, + 7268, + 0, + 7207, + 7214, + 7275, + 7271, + 0, + 7214, + 7218, + 7279, + 7275, + 0, + 7218, + 7223, + 7283, + 7279, + 0, + 7223, + 7226, + 7285, + 7283, + 0, + 7226, + 7228, + 7287, + 7285, + 0, + 7228, + 7225, + 7284, + 7287, + 0, + 7225, + 7221, + 7281, + 7284, + 0, + 7221, + 7219, + 7280, + 7281, + 0, + 7219, + 7216, + 7277, + 7280, + 0, + 7216, + 7212, + 7274, + 7277, + 0, + 7212, + 7205, + 7270, + 7274, + 0, + 7205, + 7200, + 7266, + 7270, + 0, + 7200, + 7193, + 7262, + 7266, + 0, + 7193, + 7189, + 7259, + 7262, + 0, + 7189, + 7183, + 7256, + 7259, + 0, + 7183, + 7179, + 7253, + 7256, + 0, + 7179, + 7173, + 7249, + 7253, + 0, + 7173, + 7169, + 7242, + 7249, + 0, + 7169, + 7165, + 7231, + 7242, + 0, + 7165, + 7158, + 7213, + 7231, + 0, + 7158, + 7151, + 7201, + 7213, + 0, + 7151, + 7147, + 7192, + 7201, + 0, + 7147, + 7143, + 7181, + 7192, + 0, + 7143, + 7142, + 7178, + 7181, + 0, + 7142, + 7137, + 7155, + 7178, + 0, + 7137, + 7136, + 7153, + 7155, + 0, + 7153, + 7152, + 7299, + 7300, + 0, + 7152, + 7177, + 7305, + 7299, + 0, + 7177, + 7185, + 7308, + 7305, + 0, + 7185, + 7198, + 7311, + 7308, + 0, + 7198, + 7210, + 7316, + 7311, + 0, + 7210, + 7224, + 7319, + 7316, + 0, + 7224, + 7235, + 7323, + 7319, + 0, + 7235, + 7246, + 7326, + 7323, + 0, + 7246, + 7250, + 7330, + 7326, + 0, + 7250, + 7254, + 7334, + 7330, + 0, + 7254, + 7258, + 7338, + 7334, + 0, + 7258, + 7263, + 7343, + 7338, + 0, + 7263, + 7267, + 7347, + 7343, + 0, + 7267, + 7272, + 7351, + 7347, + 0, + 7272, + 7276, + 7355, + 7351, + 0, + 7276, + 7282, + 7360, + 7355, + 0, + 7282, + 7288, + 7365, + 7360, + 0, + 7288, + 7290, + 7370, + 7365, + 0, + 7290, + 7291, + 7372, + 7370, + 0, + 7291, + 7293, + 7374, + 7372, + 0, + 7293, + 7295, + 7375, + 7374, + 0, + 7295, + 7298, + 7380, + 7375, + 0, + 7298, + 7297, + 7379, + 7380, + 0, + 7297, + 7296, + 7378, + 7379, + 0, + 7296, + 7294, + 7377, + 7378, + 0, + 7294, + 7292, + 7376, + 7377, + 0, + 7292, + 7289, + 7373, + 7376, + 0, + 7289, + 7286, + 7371, + 7373, + 0, + 7286, + 7278, + 7366, + 7371, + 0, + 7278, + 7273, + 7358, + 7366, + 0, + 7273, + 7269, + 7354, + 7358, + 0, + 7269, + 7265, + 7349, + 7354, + 0, + 7265, + 7261, + 7345, + 7349, + 0, + 7261, + 7255, + 7341, + 7345, + 0, + 7255, + 7252, + 7337, + 7341, + 0, + 7252, + 7248, + 7332, + 7337, + 0, + 7248, + 7238, + 7328, + 7332, + 0, + 7238, + 7229, + 7324, + 7328, + 0, + 7229, + 7211, + 7320, + 7324, + 0, + 7211, + 7199, + 7315, + 7320, + 0, + 7199, + 7187, + 7312, + 7315, + 0, + 7187, + 7160, + 7303, + 7312, + 0, + 7160, + 7159, + 7302, + 7303, + 0, + 7159, + 7162, + 7304, + 7302, + 0, + 7162, + 7186, + 7310, + 7304, + 0, + 7186, + 7196, + 7314, + 7310, + 0, + 7196, + 7206, + 7318, + 7314, + 0, + 7206, + 7220, + 7322, + 7318, + 0, + 7220, + 7234, + 7327, + 7322, + 0, + 7234, + 7247, + 7331, + 7327, + 0, + 7247, + 7251, + 7335, + 7331, + 0, + 7251, + 7257, + 7340, + 7335, + 0, + 7257, + 7260, + 7344, + 7340, + 0, + 7260, + 7264, + 7348, + 7344, + 0, + 7264, + 7268, + 7352, + 7348, + 0, + 7268, + 7271, + 7356, + 7352, + 0, + 7271, + 7275, + 7361, + 7356, + 0, + 7275, + 7279, + 7363, + 7361, + 0, + 7279, + 7283, + 7367, + 7363, + 0, + 7283, + 7285, + 7368, + 7367, + 0, + 7285, + 7287, + 7369, + 7368, + 0, + 7287, + 7284, + 7364, + 7369, + 0, + 7284, + 7281, + 7362, + 7364, + 0, + 7281, + 7280, + 7359, + 7362, + 0, + 7280, + 7277, + 7357, + 7359, + 0, + 7277, + 7274, + 7353, + 7357, + 0, + 7274, + 7270, + 7350, + 7353, + 0, + 7270, + 7266, + 7346, + 7350, + 0, + 7266, + 7262, + 7342, + 7346, + 0, + 7262, + 7259, + 7339, + 7342, + 0, + 7259, + 7256, + 7336, + 7339, + 0, + 7256, + 7253, + 7333, + 7336, + 0, + 7253, + 7249, + 7329, + 7333, + 0, + 7249, + 7242, + 7325, + 7329, + 0, + 7242, + 7231, + 7321, + 7325, + 0, + 7231, + 7213, + 7317, + 7321, + 0, + 7213, + 7201, + 7313, + 7317, + 0, + 7201, + 7192, + 7309, + 7313, + 0, + 7192, + 7181, + 7307, + 7309, + 0, + 7181, + 7178, + 7306, + 7307, + 0, + 7178, + 7155, + 7301, + 7306, + 0, + 7155, + 7153, + 7300, + 7301, + 0, + 7300, + 7299, + 7381, + 7382, + 0, + 7299, + 7305, + 7387, + 7381, + 0, + 7305, + 7308, + 7390, + 7387, + 0, + 7308, + 7311, + 7392, + 7390, + 0, + 7311, + 7316, + 7396, + 7392, + 0, + 7316, + 7319, + 7399, + 7396, + 0, + 7319, + 7323, + 7403, + 7399, + 0, + 7323, + 7326, + 7406, + 7403, + 0, + 7326, + 7330, + 7410, + 7406, + 0, + 7330, + 7334, + 7414, + 7410, + 0, + 7334, + 7338, + 7418, + 7414, + 0, + 7338, + 7343, + 7422, + 7418, + 0, + 7343, + 7347, + 7426, + 7422, + 0, + 7347, + 7351, + 7430, + 7426, + 0, + 7351, + 7355, + 7435, + 7430, + 0, + 7355, + 7360, + 7438, + 7435, + 0, + 7360, + 7365, + 7443, + 7438, + 0, + 7365, + 7370, + 7447, + 7443, + 0, + 7370, + 7372, + 7453, + 7447, + 0, + 7372, + 7374, + 7454, + 7453, + 0, + 7374, + 7375, + 7456, + 7454, + 0, + 7375, + 7380, + 7461, + 7456, + 0, + 7380, + 7379, + 7462, + 7461, + 0, + 7379, + 7378, + 7460, + 7462, + 0, + 7378, + 7377, + 7459, + 7460, + 0, + 7377, + 7376, + 7458, + 7459, + 0, + 7376, + 7373, + 7457, + 7458, + 0, + 7373, + 7371, + 7455, + 7457, + 0, + 7371, + 7366, + 7450, + 7455, + 0, + 7366, + 7358, + 7445, + 7450, + 0, + 7358, + 7354, + 7439, + 7445, + 0, + 7354, + 7349, + 7434, + 7439, + 0, + 7349, + 7345, + 7429, + 7434, + 0, + 7345, + 7341, + 7425, + 7429, + 0, + 7341, + 7337, + 7421, + 7425, + 0, + 7337, + 7332, + 7417, + 7421, + 0, + 7332, + 7328, + 7413, + 7417, + 0, + 7328, + 7324, + 7408, + 7413, + 0, + 7324, + 7320, + 7404, + 7408, + 0, + 7320, + 7315, + 7400, + 7404, + 0, + 7315, + 7312, + 7395, + 7400, + 0, + 7312, + 7303, + 7385, + 7395, + 0, + 7303, + 7302, + 7384, + 7385, + 0, + 7302, + 7304, + 7386, + 7384, + 0, + 7304, + 7310, + 7394, + 7386, + 0, + 7310, + 7314, + 7398, + 7394, + 0, + 7314, + 7318, + 7402, + 7398, + 0, + 7318, + 7322, + 7407, + 7402, + 0, + 7322, + 7327, + 7411, + 7407, + 0, + 7327, + 7331, + 7415, + 7411, + 0, + 7331, + 7335, + 7420, + 7415, + 0, + 7335, + 7340, + 7424, + 7420, + 0, + 7340, + 7344, + 7428, + 7424, + 0, + 7344, + 7348, + 7432, + 7428, + 0, + 7348, + 7352, + 7436, + 7432, + 0, + 7352, + 7356, + 7441, + 7436, + 0, + 7356, + 7361, + 7444, + 7441, + 0, + 7361, + 7363, + 7448, + 7444, + 0, + 7363, + 7367, + 7449, + 7448, + 0, + 7367, + 7368, + 7452, + 7449, + 0, + 7368, + 7369, + 7451, + 7452, + 0, + 7369, + 7364, + 7446, + 7451, + 0, + 7364, + 7362, + 7442, + 7446, + 0, + 7362, + 7359, + 7440, + 7442, + 0, + 7359, + 7357, + 7437, + 7440, + 0, + 7357, + 7353, + 7433, + 7437, + 0, + 7353, + 7350, + 7431, + 7433, + 0, + 7350, + 7346, + 7427, + 7431, + 0, + 7346, + 7342, + 7423, + 7427, + 0, + 7342, + 7339, + 7419, + 7423, + 0, + 7339, + 7336, + 7416, + 7419, + 0, + 7336, + 7333, + 7412, + 7416, + 0, + 7333, + 7329, + 7409, + 7412, + 0, + 7329, + 7325, + 7405, + 7409, + 0, + 7325, + 7321, + 7401, + 7405, + 0, + 7321, + 7317, + 7397, + 7401, + 0, + 7317, + 7313, + 7393, + 7397, + 0, + 7313, + 7309, + 7391, + 7393, + 0, + 7309, + 7307, + 7389, + 7391, + 0, + 7307, + 7306, + 7388, + 7389, + 0, + 7306, + 7301, + 7383, + 7388, + 0, + 7301, + 7300, + 7382, + 7383, + 0, + 7382, + 7381, + 7463, + 7464, + 0, + 7381, + 7387, + 7469, + 7463, + 0, + 7387, + 7390, + 7472, + 7469, + 0, + 7390, + 7392, + 7474, + 7472, + 0, + 7392, + 7396, + 7476, + 7474, + 0, + 7396, + 7399, + 7480, + 7476, + 0, + 7399, + 7403, + 7484, + 7480, + 0, + 7403, + 7406, + 7488, + 7484, + 0, + 7406, + 7410, + 7491, + 7488, + 0, + 7410, + 7414, + 7495, + 7491, + 0, + 7414, + 7418, + 7499, + 7495, + 0, + 7418, + 7422, + 7503, + 7499, + 0, + 7422, + 7426, + 7506, + 7503, + 0, + 7426, + 7430, + 7511, + 7506, + 0, + 7430, + 7435, + 7516, + 7511, + 0, + 7435, + 7438, + 7520, + 7516, + 0, + 7438, + 7443, + 7525, + 7520, + 0, + 7443, + 7447, + 7529, + 7525, + 0, + 7447, + 7453, + 7531, + 7529, + 0, + 7453, + 7454, + 7536, + 7531, + 0, + 7454, + 7456, + 7538, + 7536, + 0, + 7456, + 7461, + 7543, + 7538, + 0, + 7461, + 7462, + 7544, + 7543, + 0, + 7462, + 7460, + 7542, + 7544, + 0, + 7460, + 7459, + 7541, + 7542, + 0, + 7459, + 7458, + 7540, + 7541, + 0, + 7458, + 7457, + 7539, + 7540, + 0, + 7457, + 7455, + 7537, + 7539, + 0, + 7455, + 7450, + 7535, + 7537, + 0, + 7450, + 7445, + 7528, + 7535, + 0, + 7445, + 7439, + 7522, + 7528, + 0, + 7439, + 7434, + 7517, + 7522, + 0, + 7434, + 7429, + 7513, + 7517, + 0, + 7429, + 7425, + 7509, + 7513, + 0, + 7425, + 7421, + 7504, + 7509, + 0, + 7421, + 7417, + 7500, + 7504, + 0, + 7417, + 7413, + 7496, + 7500, + 0, + 7413, + 7408, + 7492, + 7496, + 0, + 7408, + 7404, + 7487, + 7492, + 0, + 7404, + 7400, + 7483, + 7487, + 0, + 7400, + 7395, + 7478, + 7483, + 0, + 7395, + 7385, + 7467, + 7478, + 0, + 7385, + 7384, + 7466, + 7467, + 0, + 7384, + 7386, + 7468, + 7466, + 0, + 7386, + 7394, + 7477, + 7468, + 0, + 7394, + 7398, + 7481, + 7477, + 0, + 7398, + 7402, + 7485, + 7481, + 0, + 7402, + 7407, + 7489, + 7485, + 0, + 7407, + 7411, + 7493, + 7489, + 0, + 7411, + 7415, + 7498, + 7493, + 0, + 7415, + 7420, + 7502, + 7498, + 0, + 7420, + 7424, + 7507, + 7502, + 0, + 7424, + 7428, + 7510, + 7507, + 0, + 7428, + 7432, + 7514, + 7510, + 0, + 7432, + 7436, + 7519, + 7514, + 0, + 7436, + 7441, + 7524, + 7519, + 0, + 7441, + 7444, + 7526, + 7524, + 0, + 7444, + 7448, + 7530, + 7526, + 0, + 7448, + 7449, + 7532, + 7530, + 0, + 7449, + 7452, + 7534, + 7532, + 0, + 7452, + 7451, + 7533, + 7534, + 0, + 7451, + 7446, + 7527, + 7533, + 0, + 7446, + 7442, + 7523, + 7527, + 0, + 7442, + 7440, + 7521, + 7523, + 0, + 7440, + 7437, + 7518, + 7521, + 0, + 7437, + 7433, + 7515, + 7518, + 0, + 7433, + 7431, + 7512, + 7515, + 0, + 7431, + 7427, + 7508, + 7512, + 0, + 7427, + 7423, + 7505, + 7508, + 0, + 7423, + 7419, + 7501, + 7505, + 0, + 7419, + 7416, + 7497, + 7501, + 0, + 7416, + 7412, + 7494, + 7497, + 0, + 7412, + 7409, + 7490, + 7494, + 0, + 7409, + 7405, + 7486, + 7490, + 0, + 7405, + 7401, + 7482, + 7486, + 0, + 7401, + 7397, + 7479, + 7482, + 0, + 7397, + 7393, + 7475, + 7479, + 0, + 7393, + 7391, + 7473, + 7475, + 0, + 7391, + 7389, + 7471, + 7473, + 0, + 7389, + 7388, + 7470, + 7471, + 0, + 7388, + 7383, + 7465, + 7470, + 0, + 7383, + 7382, + 7464, + 7465, + 0, + 7464, + 7463, + 7545, + 7546, + 0, + 7463, + 7469, + 7549, + 7545, + 0, + 7469, + 7472, + 7554, + 7549, + 0, + 7472, + 7474, + 7556, + 7554, + 0, + 7474, + 7476, + 7558, + 7556, + 0, + 7476, + 7480, + 7561, + 7558, + 0, + 7480, + 7484, + 7565, + 7561, + 0, + 7484, + 7488, + 7568, + 7565, + 0, + 7488, + 7491, + 7572, + 7568, + 0, + 7491, + 7495, + 7576, + 7572, + 0, + 7495, + 7499, + 7580, + 7576, + 0, + 7499, + 7503, + 7584, + 7580, + 0, + 7503, + 7506, + 7588, + 7584, + 0, + 7506, + 7511, + 7591, + 7588, + 0, + 7511, + 7516, + 7595, + 7591, + 0, + 7516, + 7520, + 7600, + 7595, + 0, + 7520, + 7525, + 7605, + 7600, + 0, + 7525, + 7529, + 7608, + 7605, + 0, + 7529, + 7531, + 7611, + 7608, + 0, + 7531, + 7536, + 7616, + 7611, + 0, + 7536, + 7538, + 7619, + 7616, + 0, + 7538, + 7543, + 7624, + 7619, + 0, + 7543, + 7544, + 7626, + 7624, + 0, + 7544, + 7542, + 7625, + 7626, + 0, + 7542, + 7541, + 7623, + 7625, + 0, + 7541, + 7540, + 7622, + 7623, + 0, + 7540, + 7539, + 7621, + 7622, + 0, + 7539, + 7537, + 7620, + 7621, + 0, + 7537, + 7535, + 7618, + 7620, + 0, + 7535, + 7528, + 7612, + 7618, + 0, + 7528, + 7522, + 7606, + 7612, + 0, + 7522, + 7517, + 7601, + 7606, + 0, + 7517, + 7513, + 7597, + 7601, + 0, + 7513, + 7509, + 7592, + 7597, + 0, + 7509, + 7504, + 7587, + 7592, + 0, + 7504, + 7500, + 7583, + 7587, + 0, + 7500, + 7496, + 7579, + 7583, + 0, + 7496, + 7492, + 7575, + 7579, + 0, + 7492, + 7487, + 7570, + 7575, + 0, + 7487, + 7483, + 7566, + 7570, + 0, + 7483, + 7478, + 7562, + 7566, + 0, + 7478, + 7467, + 7550, + 7562, + 0, + 7467, + 7466, + 7548, + 7550, + 0, + 7466, + 7468, + 7551, + 7548, + 0, + 7468, + 7477, + 7560, + 7551, + 0, + 7477, + 7481, + 7564, + 7560, + 0, + 7481, + 7485, + 7569, + 7564, + 0, + 7485, + 7489, + 7573, + 7569, + 0, + 7489, + 7493, + 7577, + 7573, + 0, + 7493, + 7498, + 7582, + 7577, + 0, + 7498, + 7502, + 7586, + 7582, + 0, + 7502, + 7507, + 7590, + 7586, + 0, + 7507, + 7510, + 7594, + 7590, + 0, + 7510, + 7514, + 7598, + 7594, + 0, + 7514, + 7519, + 7603, + 7598, + 0, + 7519, + 7524, + 7607, + 7603, + 0, + 7524, + 7526, + 7610, + 7607, + 0, + 7526, + 7530, + 7613, + 7610, + 0, + 7530, + 7532, + 7615, + 7613, + 0, + 7532, + 7534, + 7617, + 7615, + 0, + 7534, + 7533, + 7614, + 7617, + 0, + 7533, + 7527, + 7609, + 7614, + 0, + 7527, + 7523, + 7604, + 7609, + 0, + 7523, + 7521, + 7602, + 7604, + 0, + 7521, + 7518, + 7599, + 7602, + 0, + 7518, + 7515, + 7596, + 7599, + 0, + 7515, + 7512, + 7593, + 7596, + 0, + 7512, + 7508, + 7589, + 7593, + 0, + 7508, + 7505, + 7585, + 7589, + 0, + 7505, + 7501, + 7581, + 7585, + 0, + 7501, + 7497, + 7578, + 7581, + 0, + 7497, + 7494, + 7574, + 7578, + 0, + 7494, + 7490, + 7571, + 7574, + 0, + 7490, + 7486, + 7567, + 7571, + 0, + 7486, + 7482, + 7563, + 7567, + 0, + 7482, + 7479, + 7559, + 7563, + 0, + 7479, + 7475, + 7557, + 7559, + 0, + 7475, + 7473, + 7555, + 7557, + 0, + 7473, + 7471, + 7553, + 7555, + 0, + 7471, + 7470, + 7552, + 7553, + 0, + 7470, + 7465, + 7547, + 7552, + 0, + 7465, + 7464, + 7546, + 7547, + 0, + 7546, + 7545, + 7627, + 7628, + 0, + 7545, + 7549, + 7630, + 7627, + 0, + 7549, + 7554, + 7634, + 7630, + 0, + 7554, + 7556, + 7638, + 7634, + 0, + 7556, + 7558, + 7640, + 7638, + 0, + 7558, + 7561, + 7642, + 7640, + 0, + 7561, + 7565, + 7645, + 7642, + 0, + 7565, + 7568, + 7649, + 7645, + 0, + 7568, + 7572, + 7652, + 7649, + 0, + 7572, + 7576, + 7656, + 7652, + 0, + 7576, + 7580, + 7660, + 7656, + 0, + 7580, + 7584, + 7664, + 7660, + 0, + 7584, + 7588, + 7667, + 7664, + 0, + 7588, + 7591, + 7671, + 7667, + 0, + 7591, + 7595, + 7675, + 7671, + 0, + 7595, + 7600, + 7680, + 7675, + 0, + 7600, + 7605, + 7684, + 7680, + 0, + 7605, + 7608, + 7688, + 7684, + 0, + 7608, + 7611, + 7690, + 7688, + 0, + 7611, + 7616, + 7694, + 7690, + 0, + 7616, + 7619, + 7698, + 7694, + 0, + 7619, + 7624, + 7706, + 7698, + 0, + 7624, + 7626, + 7708, + 7706, + 0, + 7626, + 7625, + 7707, + 7708, + 0, + 7625, + 7623, + 7705, + 7707, + 0, + 7623, + 7622, + 7704, + 7705, + 0, + 7622, + 7621, + 7703, + 7704, + 0, + 7621, + 7620, + 7702, + 7703, + 0, + 7620, + 7618, + 7701, + 7702, + 0, + 7618, + 7612, + 7696, + 7701, + 0, + 7612, + 7606, + 7692, + 7696, + 0, + 7606, + 7601, + 7686, + 7692, + 0, + 7601, + 7597, + 7681, + 7686, + 0, + 7597, + 7592, + 7677, + 7681, + 0, + 7592, + 7587, + 7672, + 7677, + 0, + 7587, + 7583, + 7668, + 7672, + 0, + 7583, + 7579, + 7663, + 7668, + 0, + 7579, + 7575, + 7659, + 7663, + 0, + 7575, + 7570, + 7654, + 7659, + 0, + 7570, + 7566, + 7650, + 7654, + 0, + 7566, + 7562, + 7646, + 7650, + 0, + 7562, + 7550, + 7635, + 7646, + 0, + 7550, + 7548, + 7633, + 7635, + 0, + 7548, + 7551, + 7636, + 7633, + 0, + 7551, + 7560, + 7644, + 7636, + 0, + 7560, + 7564, + 7648, + 7644, + 0, + 7564, + 7569, + 7653, + 7648, + 0, + 7569, + 7573, + 7657, + 7653, + 0, + 7573, + 7577, + 7661, + 7657, + 0, + 7577, + 7582, + 7666, + 7661, + 0, + 7582, + 7586, + 7670, + 7666, + 0, + 7586, + 7590, + 7674, + 7670, + 0, + 7590, + 7594, + 7678, + 7674, + 0, + 7594, + 7598, + 7683, + 7678, + 0, + 7598, + 7603, + 7687, + 7683, + 0, + 7603, + 7607, + 7691, + 7687, + 0, + 7607, + 7610, + 7693, + 7691, + 0, + 7610, + 7613, + 7695, + 7693, + 0, + 7613, + 7615, + 7699, + 7695, + 0, + 7615, + 7617, + 7700, + 7699, + 0, + 7617, + 7614, + 7697, + 7700, + 0, + 7614, + 7609, + 7689, + 7697, + 0, + 7609, + 7604, + 7685, + 7689, + 0, + 7604, + 7602, + 7682, + 7685, + 0, + 7602, + 7599, + 7679, + 7682, + 0, + 7599, + 7596, + 7676, + 7679, + 0, + 7596, + 7593, + 7673, + 7676, + 0, + 7593, + 7589, + 7669, + 7673, + 0, + 7589, + 7585, + 7665, + 7669, + 0, + 7585, + 7581, + 7662, + 7665, + 0, + 7581, + 7578, + 7658, + 7662, + 0, + 7578, + 7574, + 7655, + 7658, + 0, + 7574, + 7571, + 7651, + 7655, + 0, + 7571, + 7567, + 7647, + 7651, + 0, + 7567, + 7563, + 7643, + 7647, + 0, + 7563, + 7559, + 7641, + 7643, + 0, + 7559, + 7557, + 7639, + 7641, + 0, + 7557, + 7555, + 7637, + 7639, + 0, + 7555, + 7553, + 7632, + 7637, + 0, + 7553, + 7552, + 7631, + 7632, + 0, + 7552, + 7547, + 7629, + 7631, + 0, + 7547, + 7546, + 7628, + 7629, + 0, + 7628, + 7627, + 7709, + 7710, + 0, + 7627, + 7630, + 7712, + 7709, + 0, + 7630, + 7634, + 7715, + 7712, + 0, + 7634, + 7638, + 7720, + 7715, + 0, + 7638, + 7640, + 7722, + 7720, + 0, + 7640, + 7642, + 7724, + 7722, + 0, + 7642, + 7645, + 7726, + 7724, + 0, + 7645, + 7649, + 7729, + 7726, + 0, + 7649, + 7652, + 7733, + 7729, + 0, + 7652, + 7656, + 7737, + 7733, + 0, + 7656, + 7660, + 7740, + 7737, + 0, + 7660, + 7664, + 7744, + 7740, + 0, + 7664, + 7667, + 7748, + 7744, + 0, + 7667, + 7671, + 7752, + 7748, + 0, + 7671, + 7675, + 7755, + 7752, + 0, + 7675, + 7680, + 7759, + 7755, + 0, + 7680, + 7684, + 7764, + 7759, + 0, + 7684, + 7688, + 7768, + 7764, + 0, + 7688, + 7690, + 7769, + 7768, + 0, + 7690, + 7694, + 7773, + 7769, + 0, + 7694, + 7698, + 7776, + 7773, + 0, + 7698, + 7706, + 7787, + 7776, + 0, + 7706, + 7708, + 7789, + 7787, + 0, + 7708, + 7707, + 7790, + 7789, + 0, + 7707, + 7705, + 7788, + 7790, + 0, + 7705, + 7704, + 7786, + 7788, + 0, + 7704, + 7703, + 7785, + 7786, + 0, + 7703, + 7702, + 7784, + 7785, + 0, + 7702, + 7701, + 7783, + 7784, + 0, + 7701, + 7696, + 7782, + 7783, + 0, + 7696, + 7692, + 7775, + 7782, + 0, + 7692, + 7686, + 7771, + 7775, + 0, + 7686, + 7681, + 7766, + 7771, + 0, + 7681, + 7677, + 7761, + 7766, + 0, + 7677, + 7672, + 7756, + 7761, + 0, + 7672, + 7668, + 7751, + 7756, + 0, + 7668, + 7663, + 7747, + 7751, + 0, + 7663, + 7659, + 7743, + 7747, + 0, + 7659, + 7654, + 7738, + 7743, + 0, + 7654, + 7650, + 7734, + 7738, + 0, + 7650, + 7646, + 7730, + 7734, + 0, + 7646, + 7635, + 7718, + 7730, + 0, + 7635, + 7633, + 7716, + 7718, + 0, + 7633, + 7636, + 7719, + 7716, + 0, + 7636, + 7644, + 7727, + 7719, + 0, + 7644, + 7648, + 7731, + 7727, + 0, + 7648, + 7653, + 7736, + 7731, + 0, + 7653, + 7657, + 7741, + 7736, + 0, + 7657, + 7661, + 7745, + 7741, + 0, + 7661, + 7666, + 7749, + 7745, + 0, + 7666, + 7670, + 7754, + 7749, + 0, + 7670, + 7674, + 7758, + 7754, + 0, + 7674, + 7678, + 7762, + 7758, + 0, + 7678, + 7683, + 7767, + 7762, + 0, + 7683, + 7687, + 7770, + 7767, + 0, + 7687, + 7691, + 7774, + 7770, + 0, + 7691, + 7693, + 7777, + 7774, + 0, + 7693, + 7695, + 7779, + 7777, + 0, + 7695, + 7699, + 7781, + 7779, + 0, + 7699, + 7700, + 7780, + 7781, + 0, + 7700, + 7697, + 7778, + 7780, + 0, + 7697, + 7689, + 7772, + 7778, + 0, + 7689, + 7685, + 7765, + 7772, + 0, + 7685, + 7682, + 7763, + 7765, + 0, + 7682, + 7679, + 7760, + 7763, + 0, + 7679, + 7676, + 7757, + 7760, + 0, + 7676, + 7673, + 7753, + 7757, + 0, + 7673, + 7669, + 7750, + 7753, + 0, + 7669, + 7665, + 7746, + 7750, + 0, + 7665, + 7662, + 7742, + 7746, + 0, + 7662, + 7658, + 7739, + 7742, + 0, + 7658, + 7655, + 7735, + 7739, + 0, + 7655, + 7651, + 7732, + 7735, + 0, + 7651, + 7647, + 7728, + 7732, + 0, + 7647, + 7643, + 7725, + 7728, + 0, + 7643, + 7641, + 7723, + 7725, + 0, + 7641, + 7639, + 7721, + 7723, + 0, + 7639, + 7637, + 7717, + 7721, + 0, + 7637, + 7632, + 7714, + 7717, + 0, + 7632, + 7631, + 7713, + 7714, + 0, + 7631, + 7629, + 7711, + 7713, + 0, + 7629, + 7628, + 7710, + 7711, + 0, + 7710, + 7709, + 7791, + 7792, + 0, + 7709, + 7712, + 7794, + 7791, + 0, + 7712, + 7715, + 7797, + 7794, + 0, + 7715, + 7720, + 7802, + 7797, + 0, + 7720, + 7722, + 7804, + 7802, + 0, + 7722, + 7724, + 7806, + 7804, + 0, + 7724, + 7726, + 7808, + 7806, + 0, + 7726, + 7729, + 7810, + 7808, + 0, + 7729, + 7733, + 7814, + 7810, + 0, + 7733, + 7737, + 7818, + 7814, + 0, + 7737, + 7740, + 7822, + 7818, + 0, + 7740, + 7744, + 7825, + 7822, + 0, + 7744, + 7748, + 7829, + 7825, + 0, + 7748, + 7752, + 7833, + 7829, + 0, + 7752, + 7755, + 7837, + 7833, + 0, + 7755, + 7759, + 7840, + 7837, + 0, + 7759, + 7764, + 7845, + 7840, + 0, + 7764, + 7768, + 7848, + 7845, + 0, + 7768, + 7769, + 7851, + 7848, + 0, + 7769, + 7773, + 7855, + 7851, + 0, + 7773, + 7776, + 7857, + 7855, + 0, + 7776, + 7787, + 7869, + 7857, + 0, + 7787, + 7789, + 7871, + 7869, + 0, + 7789, + 7790, + 7872, + 7871, + 0, + 7790, + 7788, + 7870, + 7872, + 0, + 7788, + 7786, + 7868, + 7870, + 0, + 7786, + 7785, + 7867, + 7868, + 0, + 7785, + 7784, + 7866, + 7867, + 0, + 7784, + 7783, + 7865, + 7866, + 0, + 7783, + 7782, + 7864, + 7865, + 0, + 7782, + 7775, + 7858, + 7864, + 0, + 7775, + 7771, + 7854, + 7858, + 0, + 7771, + 7766, + 7849, + 7854, + 0, + 7766, + 7761, + 7843, + 7849, + 0, + 7761, + 7756, + 7839, + 7843, + 0, + 7756, + 7751, + 7834, + 7839, + 0, + 7751, + 7747, + 7830, + 7834, + 0, + 7747, + 7743, + 7826, + 7830, + 0, + 7743, + 7738, + 7821, + 7826, + 0, + 7738, + 7734, + 7816, + 7821, + 0, + 7734, + 7730, + 7812, + 7816, + 0, + 7730, + 7718, + 7800, + 7812, + 0, + 7718, + 7716, + 7799, + 7800, + 0, + 7716, + 7719, + 7801, + 7799, + 0, + 7719, + 7727, + 7811, + 7801, + 0, + 7727, + 7731, + 7815, + 7811, + 0, + 7731, + 7736, + 7819, + 7815, + 0, + 7736, + 7741, + 7823, + 7819, + 0, + 7741, + 7745, + 7828, + 7823, + 0, + 7745, + 7749, + 7832, + 7828, + 0, + 7749, + 7754, + 7836, + 7832, + 0, + 7754, + 7758, + 7842, + 7836, + 0, + 7758, + 7762, + 7846, + 7842, + 0, + 7762, + 7767, + 7850, + 7846, + 0, + 7767, + 7770, + 7853, + 7850, + 0, + 7770, + 7774, + 7856, + 7853, + 0, + 7774, + 7777, + 7859, + 7856, + 0, + 7777, + 7779, + 7861, + 7859, + 0, + 7779, + 7781, + 7863, + 7861, + 0, + 7781, + 7780, + 7862, + 7863, + 0, + 7780, + 7778, + 7860, + 7862, + 0, + 7778, + 7772, + 7852, + 7860, + 0, + 7772, + 7765, + 7847, + 7852, + 0, + 7765, + 7763, + 7844, + 7847, + 0, + 7763, + 7760, + 7841, + 7844, + 0, + 7760, + 7757, + 7838, + 7841, + 0, + 7757, + 7753, + 7835, + 7838, + 0, + 7753, + 7750, + 7831, + 7835, + 0, + 7750, + 7746, + 7827, + 7831, + 0, + 7746, + 7742, + 7824, + 7827, + 0, + 7742, + 7739, + 7820, + 7824, + 0, + 7739, + 7735, + 7817, + 7820, + 0, + 7735, + 7732, + 7813, + 7817, + 0, + 7732, + 7728, + 7809, + 7813, + 0, + 7728, + 7725, + 7807, + 7809, + 0, + 7725, + 7723, + 7805, + 7807, + 0, + 7723, + 7721, + 7803, + 7805, + 0, + 7721, + 7717, + 7798, + 7803, + 0, + 7717, + 7714, + 7796, + 7798, + 0, + 7714, + 7713, + 7795, + 7796, + 0, + 7713, + 7711, + 7793, + 7795, + 0, + 7711, + 7710, + 7792, + 7793, + 0, + 7792, + 7791, + 7873, + 7874, + 0, + 7791, + 7794, + 7876, + 7873, + 0, + 7794, + 7797, + 7879, + 7876, + 0, + 7797, + 7802, + 7881, + 7879, + 0, + 7802, + 7804, + 7886, + 7881, + 0, + 7804, + 7806, + 7888, + 7886, + 0, + 7806, + 7808, + 7890, + 7888, + 0, + 7808, + 7810, + 7892, + 7890, + 0, + 7810, + 7814, + 7893, + 7892, + 0, + 7814, + 7818, + 7898, + 7893, + 0, + 7818, + 7822, + 7902, + 7898, + 0, + 7822, + 7825, + 7906, + 7902, + 0, + 7825, + 7829, + 7909, + 7906, + 0, + 7829, + 7833, + 7913, + 7909, + 0, + 7833, + 7837, + 7917, + 7913, + 0, + 7837, + 7840, + 7920, + 7917, + 0, + 7840, + 7845, + 7924, + 7920, + 0, + 7845, + 7848, + 7928, + 7924, + 0, + 7848, + 7851, + 7931, + 7928, + 0, + 7851, + 7855, + 7935, + 7931, + 0, + 7855, + 7857, + 7938, + 7935, + 0, + 7857, + 7869, + 7950, + 7938, + 0, + 7869, + 7871, + 7952, + 7950, + 0, + 7871, + 7872, + 7954, + 7952, + 0, + 7872, + 7870, + 7953, + 7954, + 0, + 7870, + 7868, + 7951, + 7953, + 0, + 7868, + 7867, + 7949, + 7951, + 0, + 7867, + 7866, + 7948, + 7949, + 0, + 7866, + 7865, + 7947, + 7948, + 0, + 7865, + 7864, + 7946, + 7947, + 0, + 7864, + 7858, + 7940, + 7946, + 0, + 7858, + 7854, + 7937, + 7940, + 0, + 7854, + 7849, + 7933, + 7937, + 0, + 7849, + 7843, + 7929, + 7933, + 0, + 7843, + 7839, + 7923, + 7929, + 0, + 7839, + 7834, + 7919, + 7923, + 0, + 7834, + 7830, + 7914, + 7919, + 0, + 7830, + 7826, + 7910, + 7914, + 0, + 7826, + 7821, + 7905, + 7910, + 0, + 7821, + 7816, + 7900, + 7905, + 0, + 7816, + 7812, + 7896, + 7900, + 0, + 7812, + 7800, + 7885, + 7896, + 0, + 7800, + 7799, + 7883, + 7885, + 0, + 7799, + 7801, + 7884, + 7883, + 0, + 7801, + 7811, + 7895, + 7884, + 0, + 7811, + 7815, + 7899, + 7895, + 0, + 7815, + 7819, + 7903, + 7899, + 0, + 7819, + 7823, + 7907, + 7903, + 0, + 7823, + 7828, + 7912, + 7907, + 0, + 7828, + 7832, + 7916, + 7912, + 0, + 7832, + 7836, + 7921, + 7916, + 0, + 7836, + 7842, + 7926, + 7921, + 0, + 7842, + 7846, + 7930, + 7926, + 0, + 7846, + 7850, + 7932, + 7930, + 0, + 7850, + 7853, + 7936, + 7932, + 0, + 7853, + 7856, + 7939, + 7936, + 0, + 7856, + 7859, + 7941, + 7939, + 0, + 7859, + 7861, + 7944, + 7941, + 0, + 7861, + 7863, + 7945, + 7944, + 0, + 7863, + 7862, + 7943, + 7945, + 0, + 7862, + 7860, + 7942, + 7943, + 0, + 7860, + 7852, + 7934, + 7942, + 0, + 7852, + 7847, + 7927, + 7934, + 0, + 7847, + 7844, + 7925, + 7927, + 0, + 7844, + 7841, + 7922, + 7925, + 0, + 7841, + 7838, + 7918, + 7922, + 0, + 7838, + 7835, + 7915, + 7918, + 0, + 7835, + 7831, + 7911, + 7915, + 0, + 7831, + 7827, + 7908, + 7911, + 0, + 7827, + 7824, + 7904, + 7908, + 0, + 7824, + 7820, + 7901, + 7904, + 0, + 7820, + 7817, + 7897, + 7901, + 0, + 7817, + 7813, + 7894, + 7897, + 0, + 7813, + 7809, + 7891, + 7894, + 0, + 7809, + 7807, + 7889, + 7891, + 0, + 7807, + 7805, + 7887, + 7889, + 0, + 7805, + 7803, + 7882, + 7887, + 0, + 7803, + 7798, + 7880, + 7882, + 0, + 7798, + 7796, + 7878, + 7880, + 0, + 7796, + 7795, + 7877, + 7878, + 0, + 7795, + 7793, + 7875, + 7877, + 0, + 7793, + 7792, + 7874, + 7875, + 0, + 7874, + 7873, + 7955, + 7956, + 0, + 7873, + 7876, + 7960, + 7955, + 0, + 7876, + 7879, + 7964, + 7960, + 0, + 7879, + 7881, + 7966, + 7964, + 0, + 7881, + 7886, + 7968, + 7966, + 0, + 7886, + 7888, + 7975, + 7968, + 0, + 7888, + 7890, + 7979, + 7975, + 0, + 7890, + 7892, + 7983, + 7979, + 0, + 7892, + 7893, + 7985, + 7983, + 0, + 7893, + 7898, + 7991, + 7985, + 0, + 7898, + 7902, + 7999, + 7991, + 0, + 7902, + 7906, + 8004, + 7999, + 0, + 7906, + 7909, + 8009, + 8004, + 0, + 7909, + 7913, + 8015, + 8009, + 0, + 7913, + 7917, + 8022, + 8015, + 0, + 7917, + 7920, + 8028, + 8022, + 0, + 7920, + 7924, + 8034, + 8028, + 0, + 7924, + 7928, + 8040, + 8034, + 0, + 7928, + 7931, + 8045, + 8040, + 0, + 7931, + 7935, + 8052, + 8045, + 0, + 7935, + 7938, + 8056, + 8052, + 0, + 7938, + 7950, + 8083, + 8056, + 0, + 7950, + 7952, + 8087, + 8083, + 0, + 7952, + 7954, + 8089, + 8087, + 0, + 7954, + 7953, + 8090, + 8089, + 0, + 7953, + 7951, + 8088, + 8090, + 0, + 7951, + 7949, + 8084, + 8088, + 0, + 7949, + 7948, + 8082, + 8084, + 0, + 7948, + 7947, + 8079, + 8082, + 0, + 7947, + 7946, + 8075, + 8079, + 0, + 7946, + 7940, + 8071, + 8075, + 0, + 7940, + 7937, + 8062, + 8071, + 0, + 7937, + 7933, + 8057, + 8062, + 0, + 7933, + 7929, + 8048, + 8057, + 0, + 7929, + 7923, + 8043, + 8048, + 0, + 7923, + 7919, + 8033, + 8043, + 0, + 7919, + 7914, + 8026, + 8033, + 0, + 7914, + 7910, + 8018, + 8026, + 0, + 7910, + 7905, + 8010, + 8018, + 0, + 7905, + 7900, + 8003, + 8010, + 0, + 7900, + 7896, + 7996, + 8003, + 0, + 7896, + 7885, + 7974, + 7996, + 0, + 7885, + 7883, + 7970, + 7974, + 0, + 7883, + 7884, + 7973, + 7970, + 0, + 7884, + 7895, + 7995, + 7973, + 0, + 7895, + 7899, + 8001, + 7995, + 0, + 7899, + 7903, + 8007, + 8001, + 0, + 7903, + 7907, + 8013, + 8007, + 0, + 7907, + 7912, + 8020, + 8013, + 0, + 7912, + 7916, + 8029, + 8020, + 0, + 7916, + 7921, + 8038, + 8029, + 0, + 7921, + 7926, + 8044, + 8038, + 0, + 7926, + 7930, + 8049, + 8044, + 0, + 7930, + 7932, + 8055, + 8049, + 0, + 7932, + 7936, + 8060, + 8055, + 0, + 7936, + 7939, + 8064, + 8060, + 0, + 7939, + 7941, + 8066, + 8064, + 0, + 7941, + 7944, + 8069, + 8066, + 0, + 7944, + 7945, + 8070, + 8069, + 0, + 7945, + 7943, + 8067, + 8070, + 0, + 7943, + 7942, + 8065, + 8067, + 0, + 7942, + 7934, + 8053, + 8065, + 0, + 7934, + 7927, + 8039, + 8053, + 0, + 7927, + 7925, + 8036, + 8039, + 0, + 7925, + 7922, + 8031, + 8036, + 0, + 7922, + 7918, + 8024, + 8031, + 0, + 7918, + 7915, + 8017, + 8024, + 0, + 7915, + 7911, + 8014, + 8017, + 0, + 7911, + 7908, + 8008, + 8014, + 0, + 7908, + 7904, + 8002, + 8008, + 0, + 7904, + 7901, + 7997, + 8002, + 0, + 7901, + 7897, + 7990, + 7997, + 0, + 7897, + 7894, + 7987, + 7990, + 0, + 7894, + 7891, + 7982, + 7987, + 0, + 7891, + 7889, + 7978, + 7982, + 0, + 7889, + 7887, + 7971, + 7978, + 0, + 7887, + 7882, + 7967, + 7971, + 0, + 7882, + 7880, + 7965, + 7967, + 0, + 7880, + 7878, + 7963, + 7965, + 0, + 7878, + 7877, + 7962, + 7963, + 0, + 7877, + 7875, + 7957, + 7962, + 0, + 7875, + 7874, + 7956, + 7957, + 0, + 7956, + 7955, + 7958, + 7959, + 0, + 7955, + 7960, + 7969, + 7958, + 0, + 7960, + 7964, + 7977, + 7969, + 0, + 7964, + 7966, + 7981, + 7977, + 0, + 7966, + 7968, + 7986, + 7981, + 0, + 7968, + 7975, + 7993, + 7986, + 0, + 7975, + 7979, + 8000, + 7993, + 0, + 7979, + 7983, + 8006, + 8000, + 0, + 7983, + 7985, + 8011, + 8006, + 0, + 7985, + 7991, + 8019, + 8011, + 0, + 7991, + 7999, + 8027, + 8019, + 0, + 7999, + 8004, + 8037, + 8027, + 0, + 8004, + 8009, + 8046, + 8037, + 0, + 8009, + 8015, + 8054, + 8046, + 0, + 8015, + 8022, + 8063, + 8054, + 0, + 8022, + 8028, + 8073, + 8063, + 0, + 8028, + 8034, + 8077, + 8073, + 0, + 8034, + 8040, + 8086, + 8077, + 0, + 8040, + 8045, + 8093, + 8086, + 0, + 8045, + 8052, + 8096, + 8093, + 0, + 8052, + 8056, + 8099, + 8096, + 0, + 8056, + 8083, + 8113, + 8099, + 0, + 8083, + 8087, + 8115, + 8113, + 0, + 8087, + 8089, + 8117, + 8115, + 0, + 8089, + 8090, + 8118, + 8117, + 0, + 8090, + 8088, + 8116, + 8118, + 0, + 8088, + 8084, + 8114, + 8116, + 0, + 8084, + 8082, + 8112, + 8114, + 0, + 8082, + 8079, + 8111, + 8112, + 0, + 8079, + 8075, + 8110, + 8111, + 0, + 8075, + 8071, + 8109, + 8110, + 0, + 8071, + 8062, + 8102, + 8109, + 0, + 8062, + 8057, + 8100, + 8102, + 0, + 8057, + 8048, + 8094, + 8100, + 0, + 8048, + 8043, + 8091, + 8094, + 0, + 8043, + 8033, + 8078, + 8091, + 0, + 8033, + 8026, + 8072, + 8078, + 0, + 8026, + 8018, + 8059, + 8072, + 0, + 8018, + 8010, + 8047, + 8059, + 0, + 8010, + 8003, + 8035, + 8047, + 0, + 8003, + 7996, + 8023, + 8035, + 0, + 7996, + 7974, + 7994, + 8023, + 0, + 7974, + 7970, + 7989, + 7994, + 0, + 7970, + 7973, + 7992, + 7989, + 0, + 7973, + 7995, + 8021, + 7992, + 0, + 7995, + 8001, + 8030, + 8021, + 0, + 8001, + 8007, + 8041, + 8030, + 0, + 8007, + 8013, + 8051, + 8041, + 0, + 8013, + 8020, + 8061, + 8051, + 0, + 8020, + 8029, + 8074, + 8061, + 0, + 8029, + 8038, + 8081, + 8074, + 0, + 8038, + 8044, + 8092, + 8081, + 0, + 8044, + 8049, + 8095, + 8092, + 0, + 8049, + 8055, + 8098, + 8095, + 0, + 8055, + 8060, + 8101, + 8098, + 0, + 8060, + 8064, + 8103, + 8101, + 0, + 8064, + 8066, + 8105, + 8103, + 0, + 8066, + 8069, + 8107, + 8105, + 0, + 8069, + 8070, + 8108, + 8107, + 0, + 8070, + 8067, + 8106, + 8108, + 0, + 8067, + 8065, + 8104, + 8106, + 0, + 8065, + 8053, + 8097, + 8104, + 0, + 8053, + 8039, + 8085, + 8097, + 0, + 8039, + 8036, + 8080, + 8085, + 0, + 8036, + 8031, + 8076, + 8080, + 0, + 8031, + 8024, + 8068, + 8076, + 0, + 8024, + 8017, + 8058, + 8068, + 0, + 8017, + 8014, + 8050, + 8058, + 0, + 8014, + 8008, + 8042, + 8050, + 0, + 8008, + 8002, + 8032, + 8042, + 0, + 8002, + 7997, + 8025, + 8032, + 0, + 7997, + 7990, + 8016, + 8025, + 0, + 7990, + 7987, + 8012, + 8016, + 0, + 7987, + 7982, + 8005, + 8012, + 0, + 7982, + 7978, + 7998, + 8005, + 0, + 7978, + 7971, + 7988, + 7998, + 0, + 7971, + 7967, + 7984, + 7988, + 0, + 7967, + 7965, + 7980, + 7984, + 0, + 7965, + 7963, + 7976, + 7980, + 0, + 7963, + 7962, + 7972, + 7976, + 0, + 7962, + 7957, + 7961, + 7972, + 0, + 7957, + 7956, + 7959, + 7961, + 0, + 7959, + 7958, + 8119, + 8120, + 0, + 7958, + 7969, + 8122, + 8119, + 0, + 7969, + 7977, + 8125, + 8122, + 0, + 7977, + 7981, + 8127, + 8125, + 0, + 7981, + 7986, + 8129, + 8127, + 0, + 7986, + 7993, + 8131, + 8129, + 0, + 7993, + 8000, + 8136, + 8131, + 0, + 8000, + 8006, + 8138, + 8136, + 0, + 8006, + 8011, + 8139, + 8138, + 0, + 8011, + 8019, + 8141, + 8139, + 0, + 8019, + 8027, + 8144, + 8141, + 0, + 8027, + 8037, + 8148, + 8144, + 0, + 8037, + 8046, + 8152, + 8148, + 0, + 8046, + 8054, + 8155, + 8152, + 0, + 8054, + 8063, + 8159, + 8155, + 0, + 8063, + 8073, + 8163, + 8159, + 0, + 8073, + 8077, + 8166, + 8163, + 0, + 8077, + 8086, + 8169, + 8166, + 0, + 8086, + 8093, + 8173, + 8169, + 0, + 8093, + 8096, + 8176, + 8173, + 0, + 8096, + 8099, + 8180, + 8176, + 0, + 8099, + 8113, + 8194, + 8180, + 0, + 8113, + 8115, + 8196, + 8194, + 0, + 8115, + 8117, + 8199, + 8196, + 0, + 8117, + 8118, + 8200, + 8199, + 0, + 8118, + 8116, + 8198, + 8200, + 0, + 8116, + 8114, + 8197, + 8198, + 0, + 8114, + 8112, + 8195, + 8197, + 0, + 8112, + 8111, + 8193, + 8195, + 0, + 8111, + 8110, + 8192, + 8193, + 0, + 8110, + 8109, + 8191, + 8192, + 0, + 8109, + 8102, + 8185, + 8191, + 0, + 8102, + 8100, + 8182, + 8185, + 0, + 8100, + 8094, + 8178, + 8182, + 0, + 8094, + 8091, + 8174, + 8178, + 0, + 8091, + 8078, + 8171, + 8174, + 0, + 8078, + 8072, + 8165, + 8171, + 0, + 8072, + 8059, + 8160, + 8165, + 0, + 8059, + 8047, + 8156, + 8160, + 0, + 8047, + 8035, + 8151, + 8156, + 0, + 8035, + 8023, + 8146, + 8151, + 0, + 8023, + 7994, + 8135, + 8146, + 0, + 7994, + 7989, + 8132, + 8135, + 0, + 7989, + 7992, + 8134, + 8132, + 0, + 7992, + 8021, + 8145, + 8134, + 0, + 8021, + 8030, + 8149, + 8145, + 0, + 8030, + 8041, + 8153, + 8149, + 0, + 8041, + 8051, + 8157, + 8153, + 0, + 8051, + 8061, + 8162, + 8157, + 0, + 8061, + 8074, + 8167, + 8162, + 0, + 8074, + 8081, + 8172, + 8167, + 0, + 8081, + 8092, + 8175, + 8172, + 0, + 8092, + 8095, + 8179, + 8175, + 0, + 8095, + 8098, + 8181, + 8179, + 0, + 8098, + 8101, + 8183, + 8181, + 0, + 8101, + 8103, + 8186, + 8183, + 0, + 8103, + 8105, + 8188, + 8186, + 0, + 8105, + 8107, + 8190, + 8188, + 0, + 8107, + 8108, + 8189, + 8190, + 0, + 8108, + 8106, + 8187, + 8189, + 0, + 8106, + 8104, + 8184, + 8187, + 0, + 8104, + 8097, + 8177, + 8184, + 0, + 8097, + 8085, + 8170, + 8177, + 0, + 8085, + 8080, + 8168, + 8170, + 0, + 8080, + 8076, + 8164, + 8168, + 0, + 8076, + 8068, + 8161, + 8164, + 0, + 8068, + 8058, + 8158, + 8161, + 0, + 8058, + 8050, + 8154, + 8158, + 0, + 8050, + 8042, + 8150, + 8154, + 0, + 8042, + 8032, + 8147, + 8150, + 0, + 8032, + 8025, + 8143, + 8147, + 0, + 8025, + 8016, + 8142, + 8143, + 0, + 8016, + 8012, + 8140, + 8142, + 0, + 8012, + 8005, + 8137, + 8140, + 0, + 8005, + 7998, + 8133, + 8137, + 0, + 7998, + 7988, + 8130, + 8133, + 0, + 7988, + 7984, + 8128, + 8130, + 0, + 7984, + 7980, + 8126, + 8128, + 0, + 7980, + 7976, + 8124, + 8126, + 0, + 7976, + 7972, + 8123, + 8124, + 0, + 7972, + 7961, + 8121, + 8123, + 0, + 7961, + 7959, + 8120, + 8121, + 0, + 8120, + 8119, + 8201, + 8202, + 0, + 8119, + 8122, + 8204, + 8201, + 0, + 8122, + 8125, + 8207, + 8204, + 0, + 8125, + 8127, + 8209, + 8207, + 0, + 8127, + 8129, + 8211, + 8209, + 0, + 8129, + 8131, + 8213, + 8211, + 0, + 8131, + 8136, + 8215, + 8213, + 0, + 8136, + 8138, + 8218, + 8215, + 0, + 8138, + 8139, + 8221, + 8218, + 0, + 8139, + 8141, + 8223, + 8221, + 0, + 8141, + 8144, + 8226, + 8223, + 0, + 8144, + 8148, + 8228, + 8226, + 0, + 8148, + 8152, + 8232, + 8228, + 0, + 8152, + 8155, + 8235, + 8232, + 0, + 8155, + 8159, + 8239, + 8235, + 0, + 8159, + 8163, + 8243, + 8239, + 0, + 8163, + 8166, + 8245, + 8243, + 0, + 8166, + 8169, + 8249, + 8245, + 0, + 8169, + 8173, + 8253, + 8249, + 0, + 8173, + 8176, + 8256, + 8253, + 0, + 8176, + 8180, + 8258, + 8256, + 0, + 8180, + 8194, + 8275, + 8258, + 0, + 8194, + 8196, + 8278, + 8275, + 0, + 8196, + 8199, + 8280, + 8278, + 0, + 8199, + 8200, + 8282, + 8280, + 0, + 8200, + 8198, + 8281, + 8282, + 0, + 8198, + 8197, + 8279, + 8281, + 0, + 8197, + 8195, + 8277, + 8279, + 0, + 8195, + 8193, + 8276, + 8277, + 0, + 8193, + 8192, + 8274, + 8276, + 0, + 8192, + 8191, + 8273, + 8274, + 0, + 8191, + 8185, + 8269, + 8273, + 0, + 8185, + 8182, + 8264, + 8269, + 0, + 8182, + 8178, + 8262, + 8264, + 0, + 8178, + 8174, + 8259, + 8262, + 0, + 8174, + 8171, + 8254, + 8259, + 0, + 8171, + 8165, + 8251, + 8254, + 0, + 8165, + 8160, + 8246, + 8251, + 0, + 8160, + 8156, + 8240, + 8246, + 0, + 8156, + 8151, + 8236, + 8240, + 0, + 8151, + 8146, + 8231, + 8236, + 0, + 8146, + 8135, + 8220, + 8231, + 0, + 8135, + 8132, + 8216, + 8220, + 0, + 8132, + 8134, + 8217, + 8216, + 0, + 8134, + 8145, + 8229, + 8217, + 0, + 8145, + 8149, + 8233, + 8229, + 0, + 8149, + 8153, + 8237, + 8233, + 0, + 8153, + 8157, + 8241, + 8237, + 0, + 8157, + 8162, + 8247, + 8241, + 0, + 8162, + 8167, + 8252, + 8247, + 0, + 8167, + 8172, + 8255, + 8252, + 0, + 8172, + 8175, + 8260, + 8255, + 0, + 8175, + 8179, + 8261, + 8260, + 0, + 8179, + 8181, + 8263, + 8261, + 0, + 8181, + 8183, + 8265, + 8263, + 0, + 8183, + 8186, + 8267, + 8265, + 0, + 8186, + 8188, + 8271, + 8267, + 0, + 8188, + 8190, + 8272, + 8271, + 0, + 8190, + 8189, + 8270, + 8272, + 0, + 8189, + 8187, + 8268, + 8270, + 0, + 8187, + 8184, + 8266, + 8268, + 0, + 8184, + 8177, + 8257, + 8266, + 0, + 8177, + 8170, + 8250, + 8257, + 0, + 8170, + 8168, + 8248, + 8250, + 0, + 8168, + 8164, + 8244, + 8248, + 0, + 8164, + 8161, + 8242, + 8244, + 0, + 8161, + 8158, + 8238, + 8242, + 0, + 8158, + 8154, + 8234, + 8238, + 0, + 8154, + 8150, + 8230, + 8234, + 0, + 8150, + 8147, + 8227, + 8230, + 0, + 8147, + 8143, + 8225, + 8227, + 0, + 8143, + 8142, + 8224, + 8225, + 0, + 8142, + 8140, + 8222, + 8224, + 0, + 8140, + 8137, + 8219, + 8222, + 0, + 8137, + 8133, + 8214, + 8219, + 0, + 8133, + 8130, + 8212, + 8214, + 0, + 8130, + 8128, + 8210, + 8212, + 0, + 8128, + 8126, + 8208, + 8210, + 0, + 8126, + 8124, + 8206, + 8208, + 0, + 8124, + 8123, + 8205, + 8206, + 0, + 8123, + 8121, + 8203, + 8205, + 0, + 8121, + 8120, + 8202, + 8203, + 0, + 8202, + 8201, + 8283, + 8284, + 0, + 8201, + 8204, + 8286, + 8283, + 0, + 8204, + 8207, + 8289, + 8286, + 0, + 8207, + 8209, + 8291, + 8289, + 0, + 8209, + 8211, + 8293, + 8291, + 0, + 8211, + 8213, + 8295, + 8293, + 0, + 8213, + 8215, + 8297, + 8295, + 0, + 8215, + 8218, + 8298, + 8297, + 0, + 8218, + 8221, + 8303, + 8298, + 0, + 8221, + 8223, + 8305, + 8303, + 0, + 8223, + 8226, + 8308, + 8305, + 0, + 8226, + 8228, + 8310, + 8308, + 0, + 8228, + 8232, + 8313, + 8310, + 0, + 8232, + 8235, + 8317, + 8313, + 0, + 8235, + 8239, + 8321, + 8317, + 0, + 8239, + 8243, + 8324, + 8321, + 0, + 8243, + 8245, + 8327, + 8324, + 0, + 8245, + 8249, + 8331, + 8327, + 0, + 8249, + 8253, + 8334, + 8331, + 0, + 8253, + 8256, + 8336, + 8334, + 0, + 8256, + 8258, + 8339, + 8336, + 0, + 8258, + 8275, + 8357, + 8339, + 0, + 8275, + 8278, + 8359, + 8357, + 0, + 8278, + 8280, + 8361, + 8359, + 0, + 8280, + 8282, + 8363, + 8361, + 0, + 8282, + 8281, + 8364, + 8363, + 0, + 8281, + 8279, + 8362, + 8364, + 0, + 8279, + 8277, + 8360, + 8362, + 0, + 8277, + 8276, + 8358, + 8360, + 0, + 8276, + 8274, + 8356, + 8358, + 0, + 8274, + 8273, + 8355, + 8356, + 0, + 8273, + 8269, + 8353, + 8355, + 0, + 8269, + 8264, + 8346, + 8353, + 0, + 8264, + 8262, + 8344, + 8346, + 0, + 8262, + 8259, + 8341, + 8344, + 0, + 8259, + 8254, + 8337, + 8341, + 0, + 8254, + 8251, + 8333, + 8337, + 0, + 8251, + 8246, + 8329, + 8333, + 0, + 8246, + 8240, + 8323, + 8329, + 0, + 8240, + 8236, + 8318, + 8323, + 0, + 8236, + 8231, + 8314, + 8318, + 0, + 8231, + 8220, + 8302, + 8314, + 0, + 8220, + 8216, + 8299, + 8302, + 0, + 8216, + 8217, + 8301, + 8299, + 0, + 8217, + 8229, + 8311, + 8301, + 0, + 8229, + 8233, + 8315, + 8311, + 0, + 8233, + 8237, + 8320, + 8315, + 0, + 8237, + 8241, + 8325, + 8320, + 0, + 8241, + 8247, + 8328, + 8325, + 0, + 8247, + 8252, + 8335, + 8328, + 0, + 8252, + 8255, + 8338, + 8335, + 0, + 8255, + 8260, + 8342, + 8338, + 0, + 8260, + 8261, + 8343, + 8342, + 0, + 8261, + 8263, + 8345, + 8343, + 0, + 8263, + 8265, + 8348, + 8345, + 0, + 8265, + 8267, + 8350, + 8348, + 0, + 8267, + 8271, + 8352, + 8350, + 0, + 8271, + 8272, + 8354, + 8352, + 0, + 8272, + 8270, + 8351, + 8354, + 0, + 8270, + 8268, + 8349, + 8351, + 0, + 8268, + 8266, + 8347, + 8349, + 0, + 8266, + 8257, + 8340, + 8347, + 0, + 8257, + 8250, + 8332, + 8340, + 0, + 8250, + 8248, + 8330, + 8332, + 0, + 8248, + 8244, + 8326, + 8330, + 0, + 8244, + 8242, + 8322, + 8326, + 0, + 8242, + 8238, + 8319, + 8322, + 0, + 8238, + 8234, + 8316, + 8319, + 0, + 8234, + 8230, + 8312, + 8316, + 0, + 8230, + 8227, + 8309, + 8312, + 0, + 8227, + 8225, + 8307, + 8309, + 0, + 8225, + 8224, + 8306, + 8307, + 0, + 8224, + 8222, + 8304, + 8306, + 0, + 8222, + 8219, + 8300, + 8304, + 0, + 8219, + 8214, + 8296, + 8300, + 0, + 8214, + 8212, + 8294, + 8296, + 0, + 8212, + 8210, + 8292, + 8294, + 0, + 8210, + 8208, + 8290, + 8292, + 0, + 8208, + 8206, + 8288, + 8290, + 0, + 8206, + 8205, + 8287, + 8288, + 0, + 8205, + 8203, + 8285, + 8287, + 0, + 8203, + 8202, + 8284, + 8285, + 0, + 8284, + 8283, + 8365, + 8366, + 0, + 8283, + 8286, + 8368, + 8365, + 0, + 8286, + 8289, + 8371, + 8368, + 0, + 8289, + 8291, + 8373, + 8371, + 0, + 8291, + 8293, + 8375, + 8373, + 0, + 8293, + 8295, + 8377, + 8375, + 0, + 8295, + 8297, + 8379, + 8377, + 0, + 8297, + 8298, + 8380, + 8379, + 0, + 8298, + 8303, + 8384, + 8380, + 0, + 8303, + 8305, + 8387, + 8384, + 0, + 8305, + 8308, + 8390, + 8387, + 0, + 8308, + 8310, + 8392, + 8390, + 0, + 8310, + 8313, + 8394, + 8392, + 0, + 8313, + 8317, + 8398, + 8394, + 0, + 8317, + 8321, + 8401, + 8398, + 0, + 8321, + 8324, + 8405, + 8401, + 0, + 8324, + 8327, + 8409, + 8405, + 0, + 8327, + 8331, + 8411, + 8409, + 0, + 8331, + 8334, + 8415, + 8411, + 0, + 8334, + 8336, + 8418, + 8415, + 0, + 8336, + 8339, + 8421, + 8418, + 0, + 8339, + 8357, + 8439, + 8421, + 0, + 8357, + 8359, + 8441, + 8439, + 0, + 8359, + 8361, + 8443, + 8441, + 0, + 8361, + 8363, + 8445, + 8443, + 0, + 8363, + 8364, + 8446, + 8445, + 0, + 8364, + 8362, + 8444, + 8446, + 0, + 8362, + 8360, + 8442, + 8444, + 0, + 8360, + 8358, + 8440, + 8442, + 0, + 8358, + 8356, + 8438, + 8440, + 0, + 8356, + 8355, + 8437, + 8438, + 0, + 8355, + 8353, + 8436, + 8437, + 0, + 8353, + 8346, + 8429, + 8436, + 0, + 8346, + 8344, + 8426, + 8429, + 0, + 8344, + 8341, + 8423, + 8426, + 0, + 8341, + 8337, + 8419, + 8423, + 0, + 8337, + 8333, + 8416, + 8419, + 0, + 8333, + 8329, + 8413, + 8416, + 0, + 8329, + 8323, + 8406, + 8413, + 0, + 8323, + 8318, + 8402, + 8406, + 0, + 8318, + 8314, + 8396, + 8402, + 0, + 8314, + 8302, + 8385, + 8396, + 0, + 8302, + 8299, + 8382, + 8385, + 0, + 8299, + 8301, + 8383, + 8382, + 0, + 8301, + 8311, + 8395, + 8383, + 0, + 8311, + 8315, + 8399, + 8395, + 0, + 8315, + 8320, + 8403, + 8399, + 0, + 8320, + 8325, + 8407, + 8403, + 0, + 8325, + 8328, + 8412, + 8407, + 0, + 8328, + 8335, + 8417, + 8412, + 0, + 8335, + 8338, + 8420, + 8417, + 0, + 8338, + 8342, + 8424, + 8420, + 0, + 8342, + 8343, + 8425, + 8424, + 0, + 8343, + 8345, + 8427, + 8425, + 0, + 8345, + 8348, + 8430, + 8427, + 0, + 8348, + 8350, + 8432, + 8430, + 0, + 8350, + 8352, + 8434, + 8432, + 0, + 8352, + 8354, + 8435, + 8434, + 0, + 8354, + 8351, + 8433, + 8435, + 0, + 8351, + 8349, + 8431, + 8433, + 0, + 8349, + 8347, + 8428, + 8431, + 0, + 8347, + 8340, + 8422, + 8428, + 0, + 8340, + 8332, + 8414, + 8422, + 0, + 8332, + 8330, + 8410, + 8414, + 0, + 8330, + 8326, + 8408, + 8410, + 0, + 8326, + 8322, + 8404, + 8408, + 0, + 8322, + 8319, + 8400, + 8404, + 0, + 8319, + 8316, + 8397, + 8400, + 0, + 8316, + 8312, + 8393, + 8397, + 0, + 8312, + 8309, + 8391, + 8393, + 0, + 8309, + 8307, + 8389, + 8391, + 0, + 8307, + 8306, + 8388, + 8389, + 0, + 8306, + 8304, + 8386, + 8388, + 0, + 8304, + 8300, + 8381, + 8386, + 0, + 8300, + 8296, + 8378, + 8381, + 0, + 8296, + 8294, + 8376, + 8378, + 0, + 8294, + 8292, + 8374, + 8376, + 0, + 8292, + 8290, + 8372, + 8374, + 0, + 8290, + 8288, + 8370, + 8372, + 0, + 8288, + 8287, + 8369, + 8370, + 0, + 8287, + 8285, + 8367, + 8369, + 0, + 8285, + 8284, + 8366, + 8367, + 0, + 8366, + 8365, + 8447, + 8448, + 0, + 8365, + 8368, + 8450, + 8447, + 0, + 8368, + 8371, + 8453, + 8450, + 0, + 8371, + 8373, + 8455, + 8453, + 0, + 8373, + 8375, + 8457, + 8455, + 0, + 8375, + 8377, + 8459, + 8457, + 0, + 8377, + 8379, + 8461, + 8459, + 0, + 8379, + 8380, + 8462, + 8461, + 0, + 8380, + 8384, + 8464, + 8462, + 0, + 8384, + 8387, + 8468, + 8464, + 0, + 8387, + 8390, + 8471, + 8468, + 0, + 8390, + 8392, + 8474, + 8471, + 0, + 8392, + 8394, + 8476, + 8474, + 0, + 8394, + 8398, + 8478, + 8476, + 0, + 8398, + 8401, + 8482, + 8478, + 0, + 8401, + 8405, + 8485, + 8482, + 0, + 8405, + 8409, + 8489, + 8485, + 0, + 8409, + 8411, + 8492, + 8489, + 0, + 8411, + 8415, + 8495, + 8492, + 0, + 8415, + 8418, + 8498, + 8495, + 0, + 8418, + 8421, + 8501, + 8498, + 0, + 8421, + 8439, + 8520, + 8501, + 0, + 8439, + 8441, + 8522, + 8520, + 0, + 8441, + 8443, + 8524, + 8522, + 0, + 8443, + 8445, + 8526, + 8524, + 0, + 8445, + 8446, + 8528, + 8526, + 0, + 8446, + 8444, + 8527, + 8528, + 0, + 8444, + 8442, + 8525, + 8527, + 0, + 8442, + 8440, + 8523, + 8525, + 0, + 8440, + 8438, + 8521, + 8523, + 0, + 8438, + 8437, + 8519, + 8521, + 0, + 8437, + 8436, + 8518, + 8519, + 0, + 8436, + 8429, + 8513, + 8518, + 0, + 8429, + 8426, + 8508, + 8513, + 0, + 8426, + 8423, + 8506, + 8508, + 0, + 8423, + 8419, + 8504, + 8506, + 0, + 8419, + 8416, + 8500, + 8504, + 0, + 8416, + 8413, + 8497, + 8500, + 0, + 8413, + 8406, + 8491, + 8497, + 0, + 8406, + 8402, + 8486, + 8491, + 0, + 8402, + 8396, + 8481, + 8486, + 0, + 8396, + 8385, + 8470, + 8481, + 0, + 8385, + 8382, + 8466, + 8470, + 0, + 8382, + 8383, + 8467, + 8466, + 0, + 8383, + 8395, + 8479, + 8467, + 0, + 8395, + 8399, + 8483, + 8479, + 0, + 8399, + 8403, + 8487, + 8483, + 0, + 8403, + 8407, + 8493, + 8487, + 0, + 8407, + 8412, + 8496, + 8493, + 0, + 8412, + 8417, + 8499, + 8496, + 0, + 8417, + 8420, + 8503, + 8499, + 0, + 8420, + 8424, + 8505, + 8503, + 0, + 8424, + 8425, + 8507, + 8505, + 0, + 8425, + 8427, + 8510, + 8507, + 0, + 8427, + 8430, + 8512, + 8510, + 0, + 8430, + 8432, + 8515, + 8512, + 0, + 8432, + 8434, + 8517, + 8515, + 0, + 8434, + 8435, + 8516, + 8517, + 0, + 8435, + 8433, + 8514, + 8516, + 0, + 8433, + 8431, + 8511, + 8514, + 0, + 8431, + 8428, + 8509, + 8511, + 0, + 8428, + 8422, + 8502, + 8509, + 0, + 8422, + 8414, + 8494, + 8502, + 0, + 8414, + 8410, + 8490, + 8494, + 0, + 8410, + 8408, + 8488, + 8490, + 0, + 8408, + 8404, + 8484, + 8488, + 0, + 8404, + 8400, + 8480, + 8484, + 0, + 8400, + 8397, + 8477, + 8480, + 0, + 8397, + 8393, + 8475, + 8477, + 0, + 8393, + 8391, + 8473, + 8475, + 0, + 8391, + 8389, + 8472, + 8473, + 0, + 8389, + 8388, + 8469, + 8472, + 0, + 8388, + 8386, + 8465, + 8469, + 0, + 8386, + 8381, + 8463, + 8465, + 0, + 8381, + 8378, + 8460, + 8463, + 0, + 8378, + 8376, + 8458, + 8460, + 0, + 8376, + 8374, + 8456, + 8458, + 0, + 8374, + 8372, + 8454, + 8456, + 0, + 8372, + 8370, + 8452, + 8454, + 0, + 8370, + 8369, + 8451, + 8452, + 0, + 8369, + 8367, + 8449, + 8451, + 0, + 8367, + 8366, + 8448, + 8449, + 0, + 8448, + 8447, + 8529, + 8530, + 0, + 8447, + 8450, + 8532, + 8529, + 0, + 8450, + 8453, + 8535, + 8532, + 0, + 8453, + 8455, + 8537, + 8535, + 0, + 8455, + 8457, + 8539, + 8537, + 0, + 8457, + 8459, + 8541, + 8539, + 0, + 8459, + 8461, + 8545, + 8541, + 0, + 8461, + 8462, + 8547, + 8545, + 0, + 8462, + 8464, + 8549, + 8547, + 0, + 8464, + 8468, + 8551, + 8549, + 0, + 8468, + 8471, + 8557, + 8551, + 0, + 8471, + 8474, + 8563, + 8557, + 0, + 8474, + 8476, + 8566, + 8563, + 0, + 8476, + 8478, + 8569, + 8566, + 0, + 8478, + 8482, + 8574, + 8569, + 0, + 8482, + 8485, + 8578, + 8574, + 0, + 8485, + 8489, + 8583, + 8578, + 0, + 8489, + 8492, + 8588, + 8583, + 0, + 8492, + 8495, + 8594, + 8588, + 0, + 8495, + 8498, + 8595, + 8594, + 0, + 8498, + 8501, + 8600, + 8595, + 0, + 8501, + 8520, + 8631, + 8600, + 0, + 8520, + 8522, + 8633, + 8631, + 0, + 8522, + 8524, + 8638, + 8633, + 0, + 8524, + 8526, + 8640, + 8638, + 0, + 8526, + 8528, + 8642, + 8640, + 0, + 8528, + 8527, + 8641, + 8642, + 0, + 8527, + 8525, + 8639, + 8641, + 0, + 8525, + 8523, + 8637, + 8639, + 0, + 8523, + 8521, + 8634, + 8637, + 0, + 8521, + 8519, + 8632, + 8634, + 0, + 8519, + 8518, + 8629, + 8632, + 0, + 8518, + 8513, + 8624, + 8629, + 0, + 8513, + 8508, + 8617, + 8624, + 0, + 8508, + 8506, + 8614, + 8617, + 0, + 8506, + 8504, + 8608, + 8614, + 0, + 8504, + 8500, + 8603, + 8608, + 0, + 8500, + 8497, + 8598, + 8603, + 0, + 8497, + 8491, + 8592, + 8598, + 0, + 8491, + 8486, + 8585, + 8592, + 0, + 8486, + 8481, + 8577, + 8585, + 0, + 8481, + 8470, + 8556, + 8577, + 0, + 8470, + 8466, + 8553, + 8556, + 0, + 8466, + 8467, + 8555, + 8553, + 0, + 8467, + 8479, + 8572, + 8555, + 0, + 8479, + 8483, + 8580, + 8572, + 0, + 8483, + 8487, + 8586, + 8580, + 0, + 8487, + 8493, + 8593, + 8586, + 0, + 8493, + 8496, + 8597, + 8593, + 0, + 8496, + 8499, + 8601, + 8597, + 0, + 8499, + 8503, + 8607, + 8601, + 0, + 8503, + 8505, + 8613, + 8607, + 0, + 8505, + 8507, + 8615, + 8613, + 0, + 8507, + 8510, + 8619, + 8615, + 0, + 8510, + 8512, + 8622, + 8619, + 0, + 8512, + 8515, + 8625, + 8622, + 0, + 8515, + 8517, + 8627, + 8625, + 0, + 8517, + 8516, + 8626, + 8627, + 0, + 8516, + 8514, + 8623, + 8626, + 0, + 8514, + 8511, + 8621, + 8623, + 0, + 8511, + 8509, + 8616, + 8621, + 0, + 8509, + 8502, + 8602, + 8616, + 0, + 8502, + 8494, + 8591, + 8602, + 0, + 8494, + 8490, + 8587, + 8591, + 0, + 8490, + 8488, + 8584, + 8587, + 0, + 8488, + 8484, + 8579, + 8584, + 0, + 8484, + 8480, + 8573, + 8579, + 0, + 8480, + 8477, + 8568, + 8573, + 0, + 8477, + 8475, + 8564, + 8568, + 0, + 8475, + 8473, + 8562, + 8564, + 0, + 8473, + 8472, + 8558, + 8562, + 0, + 8472, + 8469, + 8552, + 8558, + 0, + 8469, + 8465, + 8550, + 8552, + 0, + 8465, + 8463, + 8548, + 8550, + 0, + 8463, + 8460, + 8544, + 8548, + 0, + 8460, + 8458, + 8540, + 8544, + 0, + 8458, + 8456, + 8538, + 8540, + 0, + 8456, + 8454, + 8536, + 8538, + 0, + 8454, + 8452, + 8534, + 8536, + 0, + 8452, + 8451, + 8533, + 8534, + 0, + 8451, + 8449, + 8531, + 8533, + 0, + 8449, + 8448, + 8530, + 8531, + 0, + 8530, + 8529, + 8542, + 8543, + 0, + 8529, + 8532, + 8554, + 8542, + 0, + 8532, + 8535, + 8561, + 8554, + 0, + 8535, + 8537, + 8567, + 8561, + 0, + 8537, + 8539, + 8571, + 8567, + 0, + 8539, + 8541, + 8576, + 8571, + 0, + 8541, + 8545, + 8582, + 8576, + 0, + 8545, + 8547, + 8589, + 8582, + 0, + 8547, + 8549, + 8596, + 8589, + 0, + 8549, + 8551, + 8604, + 8596, + 0, + 8551, + 8557, + 8610, + 8604, + 0, + 8557, + 8563, + 8620, + 8610, + 0, + 8563, + 8566, + 8630, + 8620, + 0, + 8566, + 8569, + 8636, + 8630, + 0, + 8569, + 8574, + 8643, + 8636, + 0, + 8574, + 8578, + 8647, + 8643, + 0, + 8578, + 8583, + 8650, + 8647, + 0, + 8583, + 8588, + 8655, + 8650, + 0, + 8588, + 8594, + 8658, + 8655, + 0, + 8594, + 8595, + 8660, + 8658, + 0, + 8595, + 8600, + 8663, + 8660, + 0, + 8600, + 8631, + 8683, + 8663, + 0, + 8631, + 8633, + 8685, + 8683, + 0, + 8633, + 8638, + 8688, + 8685, + 0, + 8638, + 8640, + 8690, + 8688, + 0, + 8640, + 8642, + 8692, + 8690, + 0, + 8642, + 8641, + 8691, + 8692, + 0, + 8641, + 8639, + 8689, + 8691, + 0, + 8639, + 8637, + 8687, + 8689, + 0, + 8637, + 8634, + 8686, + 8687, + 0, + 8634, + 8632, + 8684, + 8686, + 0, + 8632, + 8629, + 8682, + 8684, + 0, + 8629, + 8624, + 8679, + 8682, + 0, + 8624, + 8617, + 8673, + 8679, + 0, + 8617, + 8614, + 8670, + 8673, + 0, + 8614, + 8608, + 8668, + 8670, + 0, + 8608, + 8603, + 8666, + 8668, + 0, + 8603, + 8598, + 8662, + 8666, + 0, + 8598, + 8592, + 8657, + 8662, + 0, + 8592, + 8585, + 8652, + 8657, + 0, + 8585, + 8577, + 8646, + 8652, + 0, + 8577, + 8556, + 8611, + 8646, + 0, + 8556, + 8553, + 8606, + 8611, + 0, + 8553, + 8555, + 8609, + 8606, + 0, + 8555, + 8572, + 8645, + 8609, + 0, + 8572, + 8580, + 8649, + 8645, + 0, + 8580, + 8586, + 8653, + 8649, + 0, + 8586, + 8593, + 8659, + 8653, + 0, + 8593, + 8597, + 8661, + 8659, + 0, + 8597, + 8601, + 8664, + 8661, + 0, + 8601, + 8607, + 8667, + 8664, + 0, + 8607, + 8613, + 8669, + 8667, + 0, + 8613, + 8615, + 8671, + 8669, + 0, + 8615, + 8619, + 8674, + 8671, + 0, + 8619, + 8622, + 8676, + 8674, + 0, + 8622, + 8625, + 8678, + 8676, + 0, + 8625, + 8627, + 8681, + 8678, + 0, + 8627, + 8626, + 8680, + 8681, + 0, + 8626, + 8623, + 8677, + 8680, + 0, + 8623, + 8621, + 8675, + 8677, + 0, + 8621, + 8616, + 8672, + 8675, + 0, + 8616, + 8602, + 8665, + 8672, + 0, + 8602, + 8591, + 8656, + 8665, + 0, + 8591, + 8587, + 8654, + 8656, + 0, + 8587, + 8584, + 8651, + 8654, + 0, + 8584, + 8579, + 8648, + 8651, + 0, + 8579, + 8573, + 8644, + 8648, + 0, + 8573, + 8568, + 8635, + 8644, + 0, + 8568, + 8564, + 8628, + 8635, + 0, + 8564, + 8562, + 8618, + 8628, + 0, + 8562, + 8558, + 8612, + 8618, + 0, + 8558, + 8552, + 8605, + 8612, + 0, + 8552, + 8550, + 8599, + 8605, + 0, + 8550, + 8548, + 8590, + 8599, + 0, + 8548, + 8544, + 8581, + 8590, + 0, + 8544, + 8540, + 8575, + 8581, + 0, + 8540, + 8538, + 8570, + 8575, + 0, + 8538, + 8536, + 8565, + 8570, + 0, + 8536, + 8534, + 8560, + 8565, + 0, + 8534, + 8533, + 8559, + 8560, + 0, + 8533, + 8531, + 8546, + 8559, + 0, + 8531, + 8530, + 8543, + 8546, + 0, + 8543, + 8542, + 8693, + 8694, + 0, + 8542, + 8554, + 8696, + 8693, + 0, + 8554, + 8561, + 8698, + 8696, + 0, + 8561, + 8567, + 8701, + 8698, + 0, + 8567, + 8571, + 8703, + 8701, + 0, + 8571, + 8576, + 8705, + 8703, + 0, + 8576, + 8582, + 8706, + 8705, + 0, + 8582, + 8589, + 8708, + 8706, + 0, + 8589, + 8596, + 8710, + 8708, + 0, + 8596, + 8604, + 8712, + 8710, + 0, + 8604, + 8610, + 8714, + 8712, + 0, + 8610, + 8620, + 8718, + 8714, + 0, + 8620, + 8630, + 8722, + 8718, + 0, + 8630, + 8636, + 8724, + 8722, + 0, + 8636, + 8643, + 8725, + 8724, + 0, + 8643, + 8647, + 8727, + 8725, + 0, + 8647, + 8650, + 8730, + 8727, + 0, + 8650, + 8655, + 8734, + 8730, + 0, + 8655, + 8658, + 8739, + 8734, + 0, + 8658, + 8660, + 8740, + 8739, + 0, + 8660, + 8663, + 8743, + 8740, + 0, + 8663, + 8683, + 8764, + 8743, + 0, + 8683, + 8685, + 8767, + 8764, + 0, + 8685, + 8688, + 8769, + 8767, + 0, + 8688, + 8690, + 8771, + 8769, + 0, + 8690, + 8692, + 8773, + 8771, + 0, + 8692, + 8691, + 8774, + 8773, + 0, + 8691, + 8689, + 8772, + 8774, + 0, + 8689, + 8687, + 8770, + 8772, + 0, + 8687, + 8686, + 8768, + 8770, + 0, + 8686, + 8684, + 8766, + 8768, + 0, + 8684, + 8682, + 8765, + 8766, + 0, + 8682, + 8679, + 8763, + 8765, + 0, + 8679, + 8673, + 8757, + 8763, + 0, + 8673, + 8670, + 8753, + 8757, + 0, + 8670, + 8668, + 8750, + 8753, + 0, + 8668, + 8666, + 8748, + 8750, + 0, + 8666, + 8662, + 8745, + 8748, + 0, + 8662, + 8657, + 8742, + 8745, + 0, + 8657, + 8652, + 8736, + 8742, + 0, + 8652, + 8646, + 8732, + 8736, + 0, + 8646, + 8611, + 8720, + 8732, + 0, + 8611, + 8606, + 8716, + 8720, + 0, + 8606, + 8609, + 8717, + 8716, + 0, + 8609, + 8645, + 8729, + 8717, + 0, + 8645, + 8649, + 8733, + 8729, + 0, + 8649, + 8653, + 8737, + 8733, + 0, + 8653, + 8659, + 8741, + 8737, + 0, + 8659, + 8661, + 8744, + 8741, + 0, + 8661, + 8664, + 8747, + 8744, + 0, + 8664, + 8667, + 8749, + 8747, + 0, + 8667, + 8669, + 8751, + 8749, + 0, + 8669, + 8671, + 8754, + 8751, + 0, + 8671, + 8674, + 8756, + 8754, + 0, + 8674, + 8676, + 8759, + 8756, + 0, + 8676, + 8678, + 8761, + 8759, + 0, + 8678, + 8681, + 8762, + 8761, + 0, + 8681, + 8680, + 8760, + 8762, + 0, + 8680, + 8677, + 8758, + 8760, + 0, + 8677, + 8675, + 8755, + 8758, + 0, + 8675, + 8672, + 8752, + 8755, + 0, + 8672, + 8665, + 8746, + 8752, + 0, + 8665, + 8656, + 8738, + 8746, + 0, + 8656, + 8654, + 8735, + 8738, + 0, + 8654, + 8651, + 8731, + 8735, + 0, + 8651, + 8648, + 8728, + 8731, + 0, + 8648, + 8644, + 8726, + 8728, + 0, + 8644, + 8635, + 8723, + 8726, + 0, + 8635, + 8628, + 8721, + 8723, + 0, + 8628, + 8618, + 8719, + 8721, + 0, + 8618, + 8612, + 8715, + 8719, + 0, + 8612, + 8605, + 8713, + 8715, + 0, + 8605, + 8599, + 8711, + 8713, + 0, + 8599, + 8590, + 8709, + 8711, + 0, + 8590, + 8581, + 8707, + 8709, + 0, + 8581, + 8575, + 8704, + 8707, + 0, + 8575, + 8570, + 8702, + 8704, + 0, + 8570, + 8565, + 8700, + 8702, + 0, + 8565, + 8560, + 8699, + 8700, + 0, + 8560, + 8559, + 8697, + 8699, + 0, + 8559, + 8546, + 8695, + 8697, + 0, + 8546, + 8543, + 8694, + 8695, + 0, + 8694, + 8693, + 8775, + 8776, + 0, + 8693, + 8696, + 8778, + 8775, + 0, + 8696, + 8698, + 8780, + 8778, + 0, + 8698, + 8701, + 8783, + 8780, + 0, + 8701, + 8703, + 8785, + 8783, + 0, + 8703, + 8705, + 8787, + 8785, + 0, + 8705, + 8706, + 8788, + 8787, + 0, + 8706, + 8708, + 8790, + 8788, + 0, + 8708, + 8710, + 8792, + 8790, + 0, + 8710, + 8712, + 8794, + 8792, + 0, + 8712, + 8714, + 8796, + 8794, + 0, + 8714, + 8718, + 8798, + 8796, + 0, + 8718, + 8722, + 8804, + 8798, + 0, + 8722, + 8724, + 8805, + 8804, + 0, + 8724, + 8725, + 8807, + 8805, + 0, + 8725, + 8727, + 8809, + 8807, + 0, + 8727, + 8730, + 8811, + 8809, + 0, + 8730, + 8734, + 8814, + 8811, + 0, + 8734, + 8739, + 8818, + 8814, + 0, + 8739, + 8740, + 8822, + 8818, + 0, + 8740, + 8743, + 8824, + 8822, + 0, + 8743, + 8764, + 8846, + 8824, + 0, + 8764, + 8767, + 8848, + 8846, + 0, + 8767, + 8769, + 8850, + 8848, + 0, + 8769, + 8771, + 8852, + 8850, + 0, + 8771, + 8773, + 8854, + 8852, + 0, + 8773, + 8774, + 8856, + 8854, + 0, + 8774, + 8772, + 8855, + 8856, + 0, + 8772, + 8770, + 8853, + 8855, + 0, + 8770, + 8768, + 8851, + 8853, + 0, + 8768, + 8766, + 8849, + 8851, + 0, + 8766, + 8765, + 8847, + 8849, + 0, + 8765, + 8763, + 8845, + 8847, + 0, + 8763, + 8757, + 8840, + 8845, + 0, + 8757, + 8753, + 8835, + 8840, + 0, + 8753, + 8750, + 8832, + 8835, + 0, + 8750, + 8748, + 8830, + 8832, + 0, + 8748, + 8745, + 8828, + 8830, + 0, + 8745, + 8742, + 8825, + 8828, + 0, + 8742, + 8736, + 8820, + 8825, + 0, + 8736, + 8732, + 8815, + 8820, + 0, + 8732, + 8720, + 8803, + 8815, + 0, + 8720, + 8716, + 8800, + 8803, + 0, + 8716, + 8717, + 8801, + 8800, + 0, + 8717, + 8729, + 8812, + 8801, + 0, + 8729, + 8733, + 8817, + 8812, + 0, + 8733, + 8737, + 8821, + 8817, + 0, + 8737, + 8741, + 8823, + 8821, + 0, + 8741, + 8744, + 8827, + 8823, + 0, + 8744, + 8747, + 8829, + 8827, + 0, + 8747, + 8749, + 8831, + 8829, + 0, + 8749, + 8751, + 8834, + 8831, + 0, + 8751, + 8754, + 8836, + 8834, + 0, + 8754, + 8756, + 8838, + 8836, + 0, + 8756, + 8759, + 8841, + 8838, + 0, + 8759, + 8761, + 8843, + 8841, + 0, + 8761, + 8762, + 8844, + 8843, + 0, + 8762, + 8760, + 8842, + 8844, + 0, + 8760, + 8758, + 8839, + 8842, + 0, + 8758, + 8755, + 8837, + 8839, + 0, + 8755, + 8752, + 8833, + 8837, + 0, + 8752, + 8746, + 8826, + 8833, + 0, + 8746, + 8738, + 8819, + 8826, + 0, + 8738, + 8735, + 8816, + 8819, + 0, + 8735, + 8731, + 8813, + 8816, + 0, + 8731, + 8728, + 8810, + 8813, + 0, + 8728, + 8726, + 8808, + 8810, + 0, + 8726, + 8723, + 8806, + 8808, + 0, + 8723, + 8721, + 8802, + 8806, + 0, + 8721, + 8719, + 8799, + 8802, + 0, + 8719, + 8715, + 8797, + 8799, + 0, + 8715, + 8713, + 8795, + 8797, + 0, + 8713, + 8711, + 8793, + 8795, + 0, + 8711, + 8709, + 8791, + 8793, + 0, + 8709, + 8707, + 8789, + 8791, + 0, + 8707, + 8704, + 8786, + 8789, + 0, + 8704, + 8702, + 8784, + 8786, + 0, + 8702, + 8700, + 8782, + 8784, + 0, + 8700, + 8699, + 8781, + 8782, + 0, + 8699, + 8697, + 8779, + 8781, + 0, + 8697, + 8695, + 8777, + 8779, + 0, + 8695, + 8694, + 8776, + 8777, + 0, + 8776, + 8775, + 8857, + 8858, + 0, + 8775, + 8778, + 8860, + 8857, + 0, + 8778, + 8780, + 8862, + 8860, + 0, + 8780, + 8783, + 8865, + 8862, + 0, + 8783, + 8785, + 8867, + 8865, + 0, + 8785, + 8787, + 8869, + 8867, + 0, + 8787, + 8788, + 8870, + 8869, + 0, + 8788, + 8790, + 8872, + 8870, + 0, + 8790, + 8792, + 8874, + 8872, + 0, + 8792, + 8794, + 8876, + 8874, + 0, + 8794, + 8796, + 8878, + 8876, + 0, + 8796, + 8798, + 8880, + 8878, + 0, + 8798, + 8804, + 8885, + 8880, + 0, + 8804, + 8805, + 8887, + 8885, + 0, + 8805, + 8807, + 8889, + 8887, + 0, + 8807, + 8809, + 8891, + 8889, + 0, + 8809, + 8811, + 8893, + 8891, + 0, + 8811, + 8814, + 8896, + 8893, + 0, + 8814, + 8818, + 8900, + 8896, + 0, + 8818, + 8822, + 8904, + 8900, + 0, + 8822, + 8824, + 8905, + 8904, + 0, + 8824, + 8846, + 8928, + 8905, + 0, + 8846, + 8848, + 8930, + 8928, + 0, + 8848, + 8850, + 8932, + 8930, + 0, + 8850, + 8852, + 8934, + 8932, + 0, + 8852, + 8854, + 8936, + 8934, + 0, + 8854, + 8856, + 8938, + 8936, + 0, + 8856, + 8855, + 8937, + 8938, + 0, + 8855, + 8853, + 8935, + 8937, + 0, + 8853, + 8851, + 8933, + 8935, + 0, + 8851, + 8849, + 8931, + 8933, + 0, + 8849, + 8847, + 8929, + 8931, + 0, + 8847, + 8845, + 8927, + 8929, + 0, + 8845, + 8840, + 8922, + 8927, + 0, + 8840, + 8835, + 8917, + 8922, + 0, + 8835, + 8832, + 8914, + 8917, + 0, + 8832, + 8830, + 8912, + 8914, + 0, + 8830, + 8828, + 8910, + 8912, + 0, + 8828, + 8825, + 8907, + 8910, + 0, + 8825, + 8820, + 8902, + 8907, + 0, + 8820, + 8815, + 8898, + 8902, + 0, + 8815, + 8803, + 8886, + 8898, + 0, + 8803, + 8800, + 8882, + 8886, + 0, + 8800, + 8801, + 8883, + 8882, + 0, + 8801, + 8812, + 8895, + 8883, + 0, + 8812, + 8817, + 8899, + 8895, + 0, + 8817, + 8821, + 8903, + 8899, + 0, + 8821, + 8823, + 8906, + 8903, + 0, + 8823, + 8827, + 8909, + 8906, + 0, + 8827, + 8829, + 8911, + 8909, + 0, + 8829, + 8831, + 8913, + 8911, + 0, + 8831, + 8834, + 8916, + 8913, + 0, + 8834, + 8836, + 8919, + 8916, + 0, + 8836, + 8838, + 8920, + 8919, + 0, + 8838, + 8841, + 8923, + 8920, + 0, + 8841, + 8843, + 8925, + 8923, + 0, + 8843, + 8844, + 8926, + 8925, + 0, + 8844, + 8842, + 8924, + 8926, + 0, + 8842, + 8839, + 8921, + 8924, + 0, + 8839, + 8837, + 8918, + 8921, + 0, + 8837, + 8833, + 8915, + 8918, + 0, + 8833, + 8826, + 8908, + 8915, + 0, + 8826, + 8819, + 8901, + 8908, + 0, + 8819, + 8816, + 8897, + 8901, + 0, + 8816, + 8813, + 8894, + 8897, + 0, + 8813, + 8810, + 8892, + 8894, + 0, + 8810, + 8808, + 8890, + 8892, + 0, + 8808, + 8806, + 8888, + 8890, + 0, + 8806, + 8802, + 8884, + 8888, + 0, + 8802, + 8799, + 8881, + 8884, + 0, + 8799, + 8797, + 8879, + 8881, + 0, + 8797, + 8795, + 8877, + 8879, + 0, + 8795, + 8793, + 8875, + 8877, + 0, + 8793, + 8791, + 8873, + 8875, + 0, + 8791, + 8789, + 8871, + 8873, + 0, + 8789, + 8786, + 8868, + 8871, + 0, + 8786, + 8784, + 8866, + 8868, + 0, + 8784, + 8782, + 8864, + 8866, + 0, + 8782, + 8781, + 8863, + 8864, + 0, + 8781, + 8779, + 8861, + 8863, + 0, + 8779, + 8777, + 8859, + 8861, + 0, + 8777, + 8776, + 8858, + 8859, + 0, + 8858, + 8857, + 8939, + 8940, + 0, + 8857, + 8860, + 8942, + 8939, + 0, + 8860, + 8862, + 8944, + 8942, + 0, + 8862, + 8865, + 8947, + 8944, + 0, + 8865, + 8867, + 8949, + 8947, + 0, + 8867, + 8869, + 8951, + 8949, + 0, + 8869, + 8870, + 8952, + 8951, + 0, + 8870, + 8872, + 8954, + 8952, + 0, + 8872, + 8874, + 8956, + 8954, + 0, + 8874, + 8876, + 8958, + 8956, + 0, + 8876, + 8878, + 8960, + 8958, + 0, + 8878, + 8880, + 8962, + 8960, + 0, + 8880, + 8885, + 8965, + 8962, + 0, + 8885, + 8887, + 8968, + 8965, + 0, + 8887, + 8889, + 8971, + 8968, + 0, + 8889, + 8891, + 8973, + 8971, + 0, + 8891, + 8893, + 8975, + 8973, + 0, + 8893, + 8896, + 8977, + 8975, + 0, + 8896, + 8900, + 8980, + 8977, + 0, + 8900, + 8904, + 8984, + 8980, + 0, + 8904, + 8905, + 8987, + 8984, + 0, + 8905, + 8928, + 9009, + 8987, + 0, + 8928, + 8930, + 9011, + 9009, + 0, + 8930, + 8932, + 9013, + 9011, + 0, + 8932, + 8934, + 9015, + 9013, + 0, + 8934, + 8936, + 9017, + 9015, + 0, + 8936, + 8938, + 9019, + 9017, + 0, + 8938, + 8937, + 9020, + 9019, + 0, + 8937, + 8935, + 9018, + 9020, + 0, + 8935, + 8933, + 9016, + 9018, + 0, + 8933, + 8931, + 9014, + 9016, + 0, + 8931, + 8929, + 9012, + 9014, + 0, + 8929, + 8927, + 9010, + 9012, + 0, + 8927, + 8922, + 9008, + 9010, + 0, + 8922, + 8917, + 9001, + 9008, + 0, + 8917, + 8914, + 8997, + 9001, + 0, + 8914, + 8912, + 8994, + 8997, + 0, + 8912, + 8910, + 8992, + 8994, + 0, + 8910, + 8907, + 8990, + 8992, + 0, + 8907, + 8902, + 8985, + 8990, + 0, + 8902, + 8898, + 8982, + 8985, + 0, + 8898, + 8886, + 8969, + 8982, + 0, + 8886, + 8882, + 8966, + 8969, + 0, + 8882, + 8883, + 8967, + 8966, + 0, + 8883, + 8895, + 8978, + 8967, + 0, + 8895, + 8899, + 8983, + 8978, + 0, + 8899, + 8903, + 8986, + 8983, + 0, + 8903, + 8906, + 8988, + 8986, + 0, + 8906, + 8909, + 8991, + 8988, + 0, + 8909, + 8911, + 8993, + 8991, + 0, + 8911, + 8913, + 8995, + 8993, + 0, + 8913, + 8916, + 8998, + 8995, + 0, + 8916, + 8919, + 9000, + 8998, + 0, + 8919, + 8920, + 9003, + 9000, + 0, + 8920, + 8923, + 9005, + 9003, + 0, + 8923, + 8925, + 9007, + 9005, + 0, + 8925, + 8926, + 9006, + 9007, + 0, + 8926, + 8924, + 9004, + 9006, + 0, + 8924, + 8921, + 9002, + 9004, + 0, + 8921, + 8918, + 8999, + 9002, + 0, + 8918, + 8915, + 8996, + 8999, + 0, + 8915, + 8908, + 8989, + 8996, + 0, + 8908, + 8901, + 8981, + 8989, + 0, + 8901, + 8897, + 8979, + 8981, + 0, + 8897, + 8894, + 8976, + 8979, + 0, + 8894, + 8892, + 8974, + 8976, + 0, + 8892, + 8890, + 8972, + 8974, + 0, + 8890, + 8888, + 8970, + 8972, + 0, + 8888, + 8884, + 8964, + 8970, + 0, + 8884, + 8881, + 8963, + 8964, + 0, + 8881, + 8879, + 8961, + 8963, + 0, + 8879, + 8877, + 8959, + 8961, + 0, + 8877, + 8875, + 8957, + 8959, + 0, + 8875, + 8873, + 8955, + 8957, + 0, + 8873, + 8871, + 8953, + 8955, + 0, + 8871, + 8868, + 8950, + 8953, + 0, + 8868, + 8866, + 8948, + 8950, + 0, + 8866, + 8864, + 8946, + 8948, + 0, + 8864, + 8863, + 8945, + 8946, + 0, + 8863, + 8861, + 8943, + 8945, + 0, + 8861, + 8859, + 8941, + 8943, + 0, + 8859, + 8858, + 8940, + 8941, + 0, + 8940, + 8939, + 9021, + 9022, + 0, + 8939, + 8942, + 9024, + 9021, + 0, + 8942, + 8944, + 9026, + 9024, + 0, + 8944, + 8947, + 9028, + 9026, + 0, + 8947, + 8949, + 9031, + 9028, + 0, + 8949, + 8951, + 9033, + 9031, + 0, + 8951, + 8952, + 9034, + 9033, + 0, + 8952, + 8954, + 9036, + 9034, + 0, + 8954, + 8956, + 9038, + 9036, + 0, + 8956, + 8958, + 9040, + 9038, + 0, + 8958, + 8960, + 9042, + 9040, + 0, + 8960, + 8962, + 9044, + 9042, + 0, + 8962, + 8965, + 9047, + 9044, + 0, + 8965, + 8968, + 9049, + 9047, + 0, + 8968, + 8971, + 9053, + 9049, + 0, + 8971, + 8973, + 9055, + 9053, + 0, + 8973, + 8975, + 9057, + 9055, + 0, + 8975, + 8977, + 9059, + 9057, + 0, + 8977, + 8980, + 9062, + 9059, + 0, + 8980, + 8984, + 9065, + 9062, + 0, + 8984, + 8987, + 9067, + 9065, + 0, + 8987, + 9009, + 9090, + 9067, + 0, + 9009, + 9011, + 9093, + 9090, + 0, + 9011, + 9013, + 9095, + 9093, + 0, + 9013, + 9015, + 9097, + 9095, + 0, + 9015, + 9017, + 9099, + 9097, + 0, + 9017, + 9019, + 9101, + 9099, + 0, + 9019, + 9020, + 9102, + 9101, + 0, + 9020, + 9018, + 9100, + 9102, + 0, + 9018, + 9016, + 9098, + 9100, + 0, + 9016, + 9014, + 9096, + 9098, + 0, + 9014, + 9012, + 9094, + 9096, + 0, + 9012, + 9010, + 9092, + 9094, + 0, + 9010, + 9008, + 9091, + 9092, + 0, + 9008, + 9001, + 9084, + 9091, + 0, + 9001, + 8997, + 9079, + 9084, + 0, + 8997, + 8994, + 9076, + 9079, + 0, + 8994, + 8992, + 9074, + 9076, + 0, + 8992, + 8990, + 9072, + 9074, + 0, + 8990, + 8985, + 9069, + 9072, + 0, + 8985, + 8982, + 9064, + 9069, + 0, + 8982, + 8969, + 9052, + 9064, + 0, + 8969, + 8966, + 9048, + 9052, + 0, + 8966, + 8967, + 9051, + 9048, + 0, + 8967, + 8978, + 9061, + 9051, + 0, + 8978, + 8983, + 9066, + 9061, + 0, + 8983, + 8986, + 9068, + 9066, + 0, + 8986, + 8988, + 9071, + 9068, + 0, + 8988, + 8991, + 9073, + 9071, + 0, + 8991, + 8993, + 9075, + 9073, + 0, + 8993, + 8995, + 9078, + 9075, + 0, + 8995, + 8998, + 9081, + 9078, + 0, + 8998, + 9000, + 9082, + 9081, + 0, + 9000, + 9003, + 9085, + 9082, + 0, + 9003, + 9005, + 9087, + 9085, + 0, + 9005, + 9007, + 9089, + 9087, + 0, + 9007, + 9006, + 9088, + 9089, + 0, + 9006, + 9004, + 9086, + 9088, + 0, + 9004, + 9002, + 9083, + 9086, + 0, + 9002, + 8999, + 9080, + 9083, + 0, + 8999, + 8996, + 9077, + 9080, + 0, + 8996, + 8989, + 9070, + 9077, + 0, + 8989, + 8981, + 9063, + 9070, + 0, + 8981, + 8979, + 9060, + 9063, + 0, + 8979, + 8976, + 9058, + 9060, + 0, + 8976, + 8974, + 9056, + 9058, + 0, + 8974, + 8972, + 9054, + 9056, + 0, + 8972, + 8970, + 9050, + 9054, + 0, + 8970, + 8964, + 9046, + 9050, + 0, + 8964, + 8963, + 9045, + 9046, + 0, + 8963, + 8961, + 9043, + 9045, + 0, + 8961, + 8959, + 9041, + 9043, + 0, + 8959, + 8957, + 9039, + 9041, + 0, + 8957, + 8955, + 9037, + 9039, + 0, + 8955, + 8953, + 9035, + 9037, + 0, + 8953, + 8950, + 9032, + 9035, + 0, + 8950, + 8948, + 9030, + 9032, + 0, + 8948, + 8946, + 9029, + 9030, + 0, + 8946, + 8945, + 9027, + 9029, + 0, + 8945, + 8943, + 9025, + 9027, + 0, + 8943, + 8941, + 9023, + 9025, + 0, + 8941, + 8940, + 9022, + 9023, + 0, + 9022, + 9021, + 9103, + 9104, + 0, + 9021, + 9024, + 9106, + 9103, + 0, + 9024, + 9026, + 9108, + 9106, + 0, + 9026, + 9028, + 9110, + 9108, + 0, + 9028, + 9031, + 9113, + 9110, + 0, + 9031, + 9033, + 9114, + 9113, + 0, + 9033, + 9034, + 9116, + 9114, + 0, + 9034, + 9036, + 9118, + 9116, + 0, + 9036, + 9038, + 9120, + 9118, + 0, + 9038, + 9040, + 9122, + 9120, + 0, + 9040, + 9042, + 9124, + 9122, + 0, + 9042, + 9044, + 9126, + 9124, + 0, + 9044, + 9047, + 9128, + 9126, + 0, + 9047, + 9049, + 9130, + 9128, + 0, + 9049, + 9053, + 9134, + 9130, + 0, + 9053, + 9055, + 9137, + 9134, + 0, + 9055, + 9057, + 9139, + 9137, + 0, + 9057, + 9059, + 9141, + 9139, + 0, + 9059, + 9062, + 9143, + 9141, + 0, + 9062, + 9065, + 9146, + 9143, + 0, + 9065, + 9067, + 9149, + 9146, + 0, + 9067, + 9090, + 9171, + 9149, + 0, + 9090, + 9093, + 9174, + 9171, + 0, + 9093, + 9095, + 9176, + 9174, + 0, + 9095, + 9097, + 9178, + 9176, + 0, + 9097, + 9099, + 9180, + 9178, + 0, + 9099, + 9101, + 9182, + 9180, + 0, + 9101, + 9102, + 9184, + 9182, + 0, + 9102, + 9100, + 9183, + 9184, + 0, + 9100, + 9098, + 9181, + 9183, + 0, + 9098, + 9096, + 9179, + 9181, + 0, + 9096, + 9094, + 9177, + 9179, + 0, + 9094, + 9092, + 9175, + 9177, + 0, + 9092, + 9091, + 9173, + 9175, + 0, + 9091, + 9084, + 9166, + 9173, + 0, + 9084, + 9079, + 9162, + 9166, + 0, + 9079, + 9076, + 9159, + 9162, + 0, + 9076, + 9074, + 9156, + 9159, + 0, + 9074, + 9072, + 9154, + 9156, + 0, + 9072, + 9069, + 9151, + 9154, + 0, + 9069, + 9064, + 9147, + 9151, + 0, + 9064, + 9052, + 9136, + 9147, + 0, + 9052, + 9048, + 9132, + 9136, + 0, + 9048, + 9051, + 9133, + 9132, + 0, + 9051, + 9061, + 9145, + 9133, + 0, + 9061, + 9066, + 9148, + 9145, + 0, + 9066, + 9068, + 9150, + 9148, + 0, + 9068, + 9071, + 9153, + 9150, + 0, + 9071, + 9073, + 9155, + 9153, + 0, + 9073, + 9075, + 9157, + 9155, + 0, + 9075, + 9078, + 9160, + 9157, + 0, + 9078, + 9081, + 9163, + 9160, + 0, + 9081, + 9082, + 9165, + 9163, + 0, + 9082, + 9085, + 9168, + 9165, + 0, + 9085, + 9087, + 9170, + 9168, + 0, + 9087, + 9089, + 9172, + 9170, + 0, + 9089, + 9088, + 9169, + 9172, + 0, + 9088, + 9086, + 9167, + 9169, + 0, + 9086, + 9083, + 9164, + 9167, + 0, + 9083, + 9080, + 9161, + 9164, + 0, + 9080, + 9077, + 9158, + 9161, + 0, + 9077, + 9070, + 9152, + 9158, + 0, + 9070, + 9063, + 9144, + 9152, + 0, + 9063, + 9060, + 9142, + 9144, + 0, + 9060, + 9058, + 9140, + 9142, + 0, + 9058, + 9056, + 9138, + 9140, + 0, + 9056, + 9054, + 9135, + 9138, + 0, + 9054, + 9050, + 9131, + 9135, + 0, + 9050, + 9046, + 9129, + 9131, + 0, + 9046, + 9045, + 9127, + 9129, + 0, + 9045, + 9043, + 9125, + 9127, + 0, + 9043, + 9041, + 9123, + 9125, + 0, + 9041, + 9039, + 9121, + 9123, + 0, + 9039, + 9037, + 9119, + 9121, + 0, + 9037, + 9035, + 9117, + 9119, + 0, + 9035, + 9032, + 9115, + 9117, + 0, + 9032, + 9030, + 9112, + 9115, + 0, + 9030, + 9029, + 9111, + 9112, + 0, + 9029, + 9027, + 9109, + 9111, + 0, + 9027, + 9025, + 9107, + 9109, + 0, + 9025, + 9023, + 9105, + 9107, + 0, + 9023, + 9022, + 9104, + 9105, + 0, + 9104, + 9103, + 9185, + 9186, + 0, + 9103, + 9106, + 9188, + 9185, + 0, + 9106, + 9108, + 9190, + 9188, + 0, + 9108, + 9110, + 9192, + 9190, + 0, + 9110, + 9113, + 9195, + 9192, + 0, + 9113, + 9114, + 9196, + 9195, + 0, + 9114, + 9116, + 9198, + 9196, + 0, + 9116, + 9118, + 9200, + 9198, + 0, + 9118, + 9120, + 9202, + 9200, + 0, + 9120, + 9122, + 9204, + 9202, + 0, + 9122, + 9124, + 9206, + 9204, + 0, + 9124, + 9126, + 9208, + 9206, + 0, + 9126, + 9128, + 9210, + 9208, + 0, + 9128, + 9130, + 9212, + 9210, + 0, + 9130, + 9134, + 9214, + 9212, + 0, + 9134, + 9137, + 9219, + 9214, + 0, + 9137, + 9139, + 9221, + 9219, + 0, + 9139, + 9141, + 9223, + 9221, + 0, + 9141, + 9143, + 9225, + 9223, + 0, + 9143, + 9146, + 9228, + 9225, + 0, + 9146, + 9149, + 9229, + 9228, + 0, + 9149, + 9171, + 9251, + 9229, + 0, + 9171, + 9174, + 9256, + 9251, + 0, + 9174, + 9176, + 9258, + 9256, + 0, + 9176, + 9178, + 9260, + 9258, + 0, + 9178, + 9180, + 9262, + 9260, + 0, + 9180, + 9182, + 9264, + 9262, + 0, + 9182, + 9184, + 9266, + 9264, + 0, + 9184, + 9183, + 9265, + 9266, + 0, + 9183, + 9181, + 9263, + 9265, + 0, + 9181, + 9179, + 9261, + 9263, + 0, + 9179, + 9177, + 9259, + 9261, + 0, + 9177, + 9175, + 9257, + 9259, + 0, + 9175, + 9173, + 9255, + 9257, + 0, + 9173, + 9166, + 9250, + 9255, + 0, + 9166, + 9162, + 9244, + 9250, + 0, + 9162, + 9159, + 9241, + 9244, + 0, + 9159, + 9156, + 9238, + 9241, + 0, + 9156, + 9154, + 9236, + 9238, + 0, + 9154, + 9151, + 9234, + 9236, + 0, + 9151, + 9147, + 9230, + 9234, + 0, + 9147, + 9136, + 9218, + 9230, + 0, + 9136, + 9132, + 9215, + 9218, + 0, + 9132, + 9133, + 9217, + 9215, + 0, + 9133, + 9145, + 9227, + 9217, + 0, + 9145, + 9148, + 9231, + 9227, + 0, + 9148, + 9150, + 9232, + 9231, + 0, + 9150, + 9153, + 9235, + 9232, + 0, + 9153, + 9155, + 9237, + 9235, + 0, + 9155, + 9157, + 9239, + 9237, + 0, + 9157, + 9160, + 9242, + 9239, + 0, + 9160, + 9163, + 9245, + 9242, + 0, + 9163, + 9165, + 9247, + 9245, + 0, + 9165, + 9168, + 9249, + 9247, + 0, + 9168, + 9170, + 9253, + 9249, + 0, + 9170, + 9172, + 9254, + 9253, + 0, + 9172, + 9169, + 9252, + 9254, + 0, + 9169, + 9167, + 9248, + 9252, + 0, + 9167, + 9164, + 9246, + 9248, + 0, + 9164, + 9161, + 9243, + 9246, + 0, + 9161, + 9158, + 9240, + 9243, + 0, + 9158, + 9152, + 9233, + 9240, + 0, + 9152, + 9144, + 9226, + 9233, + 0, + 9144, + 9142, + 9224, + 9226, + 0, + 9142, + 9140, + 9222, + 9224, + 0, + 9140, + 9138, + 9220, + 9222, + 0, + 9138, + 9135, + 9216, + 9220, + 0, + 9135, + 9131, + 9213, + 9216, + 0, + 9131, + 9129, + 9211, + 9213, + 0, + 9129, + 9127, + 9209, + 9211, + 0, + 9127, + 9125, + 9207, + 9209, + 0, + 9125, + 9123, + 9205, + 9207, + 0, + 9123, + 9121, + 9203, + 9205, + 0, + 9121, + 9119, + 9201, + 9203, + 0, + 9119, + 9117, + 9199, + 9201, + 0, + 9117, + 9115, + 9197, + 9199, + 0, + 9115, + 9112, + 9194, + 9197, + 0, + 9112, + 9111, + 9193, + 9194, + 0, + 9111, + 9109, + 9191, + 9193, + 0, + 9109, + 9107, + 9189, + 9191, + 0, + 9107, + 9105, + 9187, + 9189, + 0, + 9105, + 9104, + 9186, + 9187, + 0, + 9186, + 9185, + 9267, + 9268, + 0, + 9185, + 9188, + 9270, + 9267, + 0, + 9188, + 9190, + 9272, + 9270, + 0, + 9190, + 9192, + 9274, + 9272, + 0, + 9192, + 9195, + 9277, + 9274, + 0, + 9195, + 9196, + 9278, + 9277, + 0, + 9196, + 9198, + 9280, + 9278, + 0, + 9198, + 9200, + 9282, + 9280, + 0, + 9200, + 9202, + 9284, + 9282, + 0, + 9202, + 9204, + 9286, + 9284, + 0, + 9204, + 9206, + 9288, + 9286, + 0, + 9206, + 9208, + 9290, + 9288, + 0, + 9208, + 9210, + 9292, + 9290, + 0, + 9210, + 9212, + 9294, + 9292, + 0, + 9212, + 9214, + 9296, + 9294, + 0, + 9214, + 9219, + 9300, + 9296, + 0, + 9219, + 9221, + 9303, + 9300, + 0, + 9221, + 9223, + 9305, + 9303, + 0, + 9223, + 9225, + 9307, + 9305, + 0, + 9225, + 9228, + 9309, + 9307, + 0, + 9228, + 9229, + 9311, + 9309, + 0, + 9229, + 9251, + 9331, + 9311, + 0, + 9251, + 9256, + 9337, + 9331, + 0, + 9256, + 9258, + 9340, + 9337, + 0, + 9258, + 9260, + 9342, + 9340, + 0, + 9260, + 9262, + 9343, + 9342, + 0, + 9262, + 9264, + 9345, + 9343, + 0, + 9264, + 9266, + 9347, + 9345, + 0, + 9266, + 9265, + 9348, + 9347, + 0, + 9265, + 9263, + 9346, + 9348, + 0, + 9263, + 9261, + 9344, + 9346, + 0, + 9261, + 9259, + 9341, + 9344, + 0, + 9259, + 9257, + 9339, + 9341, + 0, + 9257, + 9255, + 9338, + 9339, + 0, + 9255, + 9250, + 9334, + 9338, + 0, + 9250, + 9244, + 9328, + 9334, + 0, + 9244, + 9241, + 9323, + 9328, + 0, + 9241, + 9238, + 9320, + 9323, + 0, + 9238, + 9236, + 9318, + 9320, + 0, + 9236, + 9234, + 9316, + 9318, + 0, + 9234, + 9230, + 9312, + 9316, + 0, + 9230, + 9218, + 9302, + 9312, + 0, + 9218, + 9215, + 9298, + 9302, + 0, + 9215, + 9217, + 9299, + 9298, + 0, + 9217, + 9227, + 9310, + 9299, + 0, + 9227, + 9231, + 9313, + 9310, + 0, + 9231, + 9232, + 9315, + 9313, + 0, + 9232, + 9235, + 9317, + 9315, + 0, + 9235, + 9237, + 9319, + 9317, + 0, + 9237, + 9239, + 9321, + 9319, + 0, + 9239, + 9242, + 9325, + 9321, + 0, + 9242, + 9245, + 9327, + 9325, + 0, + 9245, + 9247, + 9329, + 9327, + 0, + 9247, + 9249, + 9332, + 9329, + 0, + 9249, + 9253, + 9335, + 9332, + 0, + 9253, + 9254, + 9336, + 9335, + 0, + 9254, + 9252, + 9333, + 9336, + 0, + 9252, + 9248, + 9330, + 9333, + 0, + 9248, + 9246, + 9326, + 9330, + 0, + 9246, + 9243, + 9324, + 9326, + 0, + 9243, + 9240, + 9322, + 9324, + 0, + 9240, + 9233, + 9314, + 9322, + 0, + 9233, + 9226, + 9308, + 9314, + 0, + 9226, + 9224, + 9306, + 9308, + 0, + 9224, + 9222, + 9304, + 9306, + 0, + 9222, + 9220, + 9301, + 9304, + 0, + 9220, + 9216, + 9297, + 9301, + 0, + 9216, + 9213, + 9295, + 9297, + 0, + 9213, + 9211, + 9293, + 9295, + 0, + 9211, + 9209, + 9291, + 9293, + 0, + 9209, + 9207, + 9289, + 9291, + 0, + 9207, + 9205, + 9287, + 9289, + 0, + 9205, + 9203, + 9285, + 9287, + 0, + 9203, + 9201, + 9283, + 9285, + 0, + 9201, + 9199, + 9281, + 9283, + 0, + 9199, + 9197, + 9279, + 9281, + 0, + 9197, + 9194, + 9276, + 9279, + 0, + 9194, + 9193, + 9275, + 9276, + 0, + 9193, + 9191, + 9273, + 9275, + 0, + 9191, + 9189, + 9271, + 9273, + 0, + 9189, + 9187, + 9269, + 9271, + 0, + 9187, + 9186, + 9268, + 9269, + 0, + 9268, + 9267, + 9349, + 9350, + 0, + 9267, + 9270, + 9352, + 9349, + 0, + 9270, + 9272, + 9354, + 9352, + 0, + 9272, + 9274, + 9356, + 9354, + 0, + 9274, + 9277, + 9359, + 9356, + 0, + 9277, + 9278, + 9360, + 9359, + 0, + 9278, + 9280, + 9362, + 9360, + 0, + 9280, + 9282, + 9364, + 9362, + 0, + 9282, + 9284, + 9366, + 9364, + 0, + 9284, + 9286, + 9368, + 9366, + 0, + 9286, + 9288, + 9370, + 9368, + 0, + 9288, + 9290, + 9372, + 9370, + 0, + 9290, + 9292, + 9374, + 9372, + 0, + 9292, + 9294, + 9376, + 9374, + 0, + 9294, + 9296, + 9378, + 9376, + 0, + 9296, + 9300, + 9380, + 9378, + 0, + 9300, + 9303, + 9384, + 9380, + 0, + 9303, + 9305, + 9387, + 9384, + 0, + 9305, + 9307, + 9389, + 9387, + 0, + 9307, + 9309, + 9391, + 9389, + 0, + 9309, + 9311, + 9392, + 9391, + 0, + 9311, + 9331, + 9411, + 9392, + 0, + 9331, + 9337, + 9419, + 9411, + 0, + 9337, + 9340, + 9421, + 9419, + 0, + 9340, + 9342, + 9424, + 9421, + 0, + 9342, + 9343, + 9426, + 9424, + 0, + 9343, + 9345, + 9428, + 9426, + 0, + 9345, + 9347, + 9430, + 9428, + 0, + 9347, + 9348, + 9431, + 9430, + 0, + 9348, + 9346, + 9429, + 9431, + 0, + 9346, + 9344, + 9427, + 9429, + 0, + 9344, + 9341, + 9425, + 9427, + 0, + 9341, + 9339, + 9423, + 9425, + 0, + 9339, + 9338, + 9420, + 9423, + 0, + 9338, + 9334, + 9418, + 9420, + 0, + 9334, + 9328, + 9412, + 9418, + 0, + 9328, + 9323, + 9406, + 9412, + 0, + 9323, + 9320, + 9403, + 9406, + 0, + 9320, + 9318, + 9400, + 9403, + 0, + 9318, + 9316, + 9398, + 9400, + 0, + 9316, + 9312, + 9395, + 9398, + 0, + 9312, + 9302, + 9386, + 9395, + 0, + 9302, + 9298, + 9382, + 9386, + 0, + 9298, + 9299, + 9383, + 9382, + 0, + 9299, + 9310, + 9393, + 9383, + 0, + 9310, + 9313, + 9394, + 9393, + 0, + 9313, + 9315, + 9397, + 9394, + 0, + 9315, + 9317, + 9399, + 9397, + 0, + 9317, + 9319, + 9401, + 9399, + 0, + 9319, + 9321, + 9404, + 9401, + 0, + 9321, + 9325, + 9407, + 9404, + 0, + 9325, + 9327, + 9409, + 9407, + 0, + 9327, + 9329, + 9413, + 9409, + 0, + 9329, + 9332, + 9415, + 9413, + 0, + 9332, + 9335, + 9417, + 9415, + 0, + 9335, + 9336, + 9416, + 9417, + 0, + 9336, + 9333, + 9414, + 9416, + 0, + 9333, + 9330, + 9410, + 9414, + 0, + 9330, + 9326, + 9408, + 9410, + 0, + 9326, + 9324, + 9405, + 9408, + 0, + 9324, + 9322, + 9402, + 9405, + 0, + 9322, + 9314, + 9396, + 9402, + 0, + 9314, + 9308, + 9390, + 9396, + 0, + 9308, + 9306, + 9388, + 9390, + 0, + 9306, + 9304, + 9385, + 9388, + 0, + 9304, + 9301, + 9381, + 9385, + 0, + 9301, + 9297, + 9379, + 9381, + 0, + 9297, + 9295, + 9377, + 9379, + 0, + 9295, + 9293, + 9375, + 9377, + 0, + 9293, + 9291, + 9373, + 9375, + 0, + 9291, + 9289, + 9371, + 9373, + 0, + 9289, + 9287, + 9369, + 9371, + 0, + 9287, + 9285, + 9367, + 9369, + 0, + 9285, + 9283, + 9365, + 9367, + 0, + 9283, + 9281, + 9363, + 9365, + 0, + 9281, + 9279, + 9361, + 9363, + 0, + 9279, + 9276, + 9358, + 9361, + 0, + 9276, + 9275, + 9357, + 9358, + 0, + 9275, + 9273, + 9355, + 9357, + 0, + 9273, + 9271, + 9353, + 9355, + 0, + 9271, + 9269, + 9351, + 9353, + 0, + 9269, + 9268, + 9350, + 9351, + 0, + 9350, + 9349, + 9422, + 9432, + 0, + 9349, + 9352, + 9434, + 9422, + 0, + 9352, + 9354, + 9436, + 9434, + 0, + 9354, + 9356, + 9438, + 9436, + 0, + 9356, + 9359, + 9441, + 9438, + 0, + 9359, + 9360, + 9442, + 9441, + 0, + 9360, + 9362, + 9444, + 9442, + 0, + 9362, + 9364, + 9446, + 9444, + 0, + 9364, + 9366, + 9448, + 9446, + 0, + 9366, + 9368, + 9450, + 9448, + 0, + 9368, + 9370, + 9452, + 9450, + 0, + 9370, + 9372, + 9454, + 9452, + 0, + 9372, + 9374, + 9456, + 9454, + 0, + 9374, + 9376, + 9458, + 9456, + 0, + 9376, + 9378, + 9460, + 9458, + 0, + 9378, + 9380, + 9462, + 9460, + 0, + 9380, + 9384, + 9465, + 9462, + 0, + 9384, + 9387, + 9469, + 9465, + 0, + 9387, + 9389, + 9471, + 9469, + 0, + 9389, + 9391, + 9473, + 9471, + 0, + 9391, + 9392, + 9474, + 9473, + 0, + 9392, + 9411, + 9492, + 9474, + 0, + 9411, + 9419, + 9501, + 9492, + 0, + 9419, + 9421, + 9503, + 9501, + 0, + 9421, + 9424, + 9505, + 9503, + 0, + 9424, + 9426, + 9507, + 9505, + 0, + 9426, + 9428, + 9509, + 9507, + 0, + 9428, + 9430, + 9511, + 9509, + 0, + 9430, + 9431, + 9512, + 9511, + 0, + 9431, + 9429, + 9510, + 9512, + 0, + 9429, + 9427, + 9508, + 9510, + 0, + 9427, + 9425, + 9506, + 9508, + 0, + 9425, + 9423, + 9504, + 9506, + 0, + 9423, + 9420, + 9502, + 9504, + 0, + 9420, + 9418, + 9500, + 9502, + 0, + 9418, + 9412, + 9494, + 9500, + 0, + 9412, + 9406, + 9488, + 9494, + 0, + 9406, + 9403, + 9485, + 9488, + 0, + 9403, + 9400, + 9482, + 9485, + 0, + 9400, + 9398, + 9480, + 9482, + 0, + 9398, + 9395, + 9478, + 9480, + 0, + 9395, + 9386, + 9468, + 9478, + 0, + 9386, + 9382, + 9464, + 9468, + 0, + 9382, + 9383, + 9466, + 9464, + 0, + 9383, + 9393, + 9475, + 9466, + 0, + 9393, + 9394, + 9477, + 9475, + 0, + 9394, + 9397, + 9479, + 9477, + 0, + 9397, + 9399, + 9481, + 9479, + 0, + 9399, + 9401, + 9483, + 9481, + 0, + 9401, + 9404, + 9486, + 9483, + 0, + 9404, + 9407, + 9489, + 9486, + 0, + 9407, + 9409, + 9491, + 9489, + 0, + 9409, + 9413, + 9495, + 9491, + 0, + 9413, + 9415, + 9497, + 9495, + 0, + 9415, + 9417, + 9499, + 9497, + 0, + 9417, + 9416, + 9498, + 9499, + 0, + 9416, + 9414, + 9496, + 9498, + 0, + 9414, + 9410, + 9493, + 9496, + 0, + 9410, + 9408, + 9490, + 9493, + 0, + 9408, + 9405, + 9487, + 9490, + 0, + 9405, + 9402, + 9484, + 9487, + 0, + 9402, + 9396, + 9476, + 9484, + 0, + 9396, + 9390, + 9472, + 9476, + 0, + 9390, + 9388, + 9470, + 9472, + 0, + 9388, + 9385, + 9467, + 9470, + 0, + 9385, + 9381, + 9463, + 9467, + 0, + 9381, + 9379, + 9461, + 9463, + 0, + 9379, + 9377, + 9459, + 9461, + 0, + 9377, + 9375, + 9457, + 9459, + 0, + 9375, + 9373, + 9455, + 9457, + 0, + 9373, + 9371, + 9453, + 9455, + 0, + 9371, + 9369, + 9451, + 9453, + 0, + 9369, + 9367, + 9449, + 9451, + 0, + 9367, + 9365, + 9447, + 9449, + 0, + 9365, + 9363, + 9445, + 9447, + 0, + 9363, + 9361, + 9443, + 9445, + 0, + 9361, + 9358, + 9440, + 9443, + 0, + 9358, + 9357, + 9439, + 9440, + 0, + 9357, + 9355, + 9437, + 9439, + 0, + 9355, + 9353, + 9435, + 9437, + 0, + 9353, + 9351, + 9433, + 9435, + 0, + 9351, + 9350, + 9432, + 9433, + 0, + 9432, + 9422, + 9513, + 9514, + 0, + 9422, + 9434, + 9516, + 9513, + 0, + 9434, + 9436, + 9518, + 9516, + 0, + 9436, + 9438, + 9520, + 9518, + 0, + 9438, + 9441, + 9523, + 9520, + 0, + 9441, + 9442, + 9524, + 9523, + 0, + 9442, + 9444, + 9526, + 9524, + 0, + 9444, + 9446, + 9528, + 9526, + 0, + 9446, + 9448, + 9530, + 9528, + 0, + 9448, + 9450, + 9532, + 9530, + 0, + 9450, + 9452, + 9534, + 9532, + 0, + 9452, + 9454, + 9536, + 9534, + 0, + 9454, + 9456, + 9538, + 9536, + 0, + 9456, + 9458, + 9540, + 9538, + 0, + 9458, + 9460, + 9542, + 9540, + 0, + 9460, + 9462, + 9544, + 9542, + 0, + 9462, + 9465, + 9546, + 9544, + 0, + 9465, + 9469, + 9550, + 9546, + 0, + 9469, + 9471, + 9553, + 9550, + 0, + 9471, + 9473, + 9555, + 9553, + 0, + 9473, + 9474, + 9556, + 9555, + 0, + 9474, + 9492, + 9573, + 9556, + 0, + 9492, + 9501, + 9582, + 9573, + 0, + 9501, + 9503, + 9584, + 9582, + 0, + 9503, + 9505, + 9586, + 9584, + 0, + 9505, + 9507, + 9588, + 9586, + 0, + 9507, + 9509, + 9590, + 9588, + 0, + 9509, + 9511, + 9592, + 9590, + 0, + 9511, + 9512, + 9594, + 9592, + 0, + 9512, + 9510, + 9593, + 9594, + 0, + 9510, + 9508, + 9591, + 9593, + 0, + 9508, + 9506, + 9589, + 9591, + 0, + 9506, + 9504, + 9587, + 9589, + 0, + 9504, + 9502, + 9585, + 9587, + 0, + 9502, + 9500, + 9583, + 9585, + 0, + 9500, + 9494, + 9576, + 9583, + 0, + 9494, + 9488, + 9572, + 9576, + 0, + 9488, + 9485, + 9567, + 9572, + 0, + 9485, + 9482, + 9564, + 9567, + 0, + 9482, + 9480, + 9562, + 9564, + 0, + 9480, + 9478, + 9560, + 9562, + 0, + 9478, + 9468, + 9551, + 9560, + 0, + 9468, + 9464, + 9547, + 9551, + 0, + 9464, + 9466, + 9548, + 9547, + 0, + 9466, + 9475, + 9557, + 9548, + 0, + 9475, + 9477, + 9559, + 9557, + 0, + 9477, + 9479, + 9561, + 9559, + 0, + 9479, + 9481, + 9563, + 9561, + 0, + 9481, + 9483, + 9565, + 9563, + 0, + 9483, + 9486, + 9568, + 9565, + 0, + 9486, + 9489, + 9571, + 9568, + 0, + 9489, + 9491, + 9575, + 9571, + 0, + 9491, + 9495, + 9577, + 9575, + 0, + 9495, + 9497, + 9579, + 9577, + 0, + 9497, + 9499, + 9581, + 9579, + 0, + 9499, + 9498, + 9580, + 9581, + 0, + 9498, + 9496, + 9578, + 9580, + 0, + 9496, + 9493, + 9574, + 9578, + 0, + 9493, + 9490, + 9570, + 9574, + 0, + 9490, + 9487, + 9569, + 9570, + 0, + 9487, + 9484, + 9566, + 9569, + 0, + 9484, + 9476, + 9558, + 9566, + 0, + 9476, + 9472, + 9554, + 9558, + 0, + 9472, + 9470, + 9552, + 9554, + 0, + 9470, + 9467, + 9549, + 9552, + 0, + 9467, + 9463, + 9545, + 9549, + 0, + 9463, + 9461, + 9543, + 9545, + 0, + 9461, + 9459, + 9541, + 9543, + 0, + 9459, + 9457, + 9539, + 9541, + 0, + 9457, + 9455, + 9537, + 9539, + 0, + 9455, + 9453, + 9535, + 9537, + 0, + 9453, + 9451, + 9533, + 9535, + 0, + 9451, + 9449, + 9531, + 9533, + 0, + 9449, + 9447, + 9529, + 9531, + 0, + 9447, + 9445, + 9527, + 9529, + 0, + 9445, + 9443, + 9525, + 9527, + 0, + 9443, + 9440, + 9522, + 9525, + 0, + 9440, + 9439, + 9521, + 9522, + 0, + 9439, + 9437, + 9519, + 9521, + 0, + 9437, + 9435, + 9517, + 9519, + 0, + 9435, + 9433, + 9515, + 9517, + 0, + 9433, + 9432, + 9514, + 9515, + 0, + 9514, + 9513, + 9595, + 9596, + 0, + 9513, + 9516, + 9598, + 9595, + 0, + 9516, + 9518, + 9600, + 9598, + 0, + 9518, + 9520, + 9602, + 9600, + 0, + 9520, + 9523, + 9604, + 9602, + 0, + 9523, + 9524, + 9606, + 9604, + 0, + 9524, + 9526, + 9608, + 9606, + 0, + 9526, + 9528, + 9610, + 9608, + 0, + 9528, + 9530, + 9612, + 9610, + 0, + 9530, + 9532, + 9614, + 9612, + 0, + 9532, + 9534, + 9616, + 9614, + 0, + 9534, + 9536, + 9618, + 9616, + 0, + 9536, + 9538, + 9620, + 9618, + 0, + 9538, + 9540, + 9622, + 9620, + 0, + 9540, + 9542, + 9624, + 9622, + 0, + 9542, + 9544, + 9627, + 9624, + 0, + 9544, + 9546, + 9631, + 9627, + 0, + 9546, + 9550, + 9633, + 9631, + 0, + 9550, + 9553, + 9637, + 9633, + 0, + 9553, + 9555, + 9641, + 9637, + 0, + 9555, + 9556, + 9642, + 9641, + 0, + 9556, + 9573, + 9669, + 9642, + 0, + 9573, + 9582, + 9677, + 9669, + 0, + 9582, + 9584, + 9684, + 9677, + 0, + 9584, + 9586, + 9687, + 9684, + 0, + 9586, + 9588, + 9690, + 9687, + 0, + 9588, + 9590, + 9691, + 9690, + 0, + 9590, + 9592, + 9693, + 9691, + 0, + 9592, + 9594, + 9695, + 9693, + 0, + 9594, + 9593, + 9696, + 9695, + 0, + 9593, + 9591, + 9694, + 9696, + 0, + 9591, + 9589, + 9692, + 9694, + 0, + 9589, + 9587, + 9689, + 9692, + 0, + 9587, + 9585, + 9686, + 9689, + 0, + 9585, + 9583, + 9683, + 9686, + 0, + 9583, + 9576, + 9679, + 9683, + 0, + 9576, + 9572, + 9672, + 9679, + 0, + 9572, + 9567, + 9666, + 9672, + 0, + 9567, + 9564, + 9661, + 9666, + 0, + 9564, + 9562, + 9656, + 9661, + 0, + 9562, + 9560, + 9653, + 9656, + 0, + 9560, + 9551, + 9638, + 9653, + 0, + 9551, + 9547, + 9634, + 9638, + 0, + 9547, + 9548, + 9635, + 9634, + 0, + 9548, + 9557, + 9649, + 9635, + 0, + 9557, + 9559, + 9650, + 9649, + 0, + 9559, + 9561, + 9654, + 9650, + 0, + 9561, + 9563, + 9658, + 9654, + 0, + 9563, + 9565, + 9662, + 9658, + 0, + 9565, + 9568, + 9665, + 9662, + 0, + 9568, + 9571, + 9670, + 9665, + 0, + 9571, + 9575, + 9674, + 9670, + 0, + 9575, + 9577, + 9676, + 9674, + 0, + 9577, + 9579, + 9680, + 9676, + 0, + 9579, + 9581, + 9681, + 9680, + 0, + 9581, + 9580, + 9678, + 9681, + 0, + 9580, + 9578, + 9675, + 9678, + 0, + 9578, + 9574, + 9671, + 9675, + 0, + 9574, + 9570, + 9667, + 9671, + 0, + 9570, + 9569, + 9664, + 9667, + 0, + 9569, + 9566, + 9659, + 9664, + 0, + 9566, + 9558, + 9648, + 9659, + 0, + 9558, + 9554, + 9639, + 9648, + 0, + 9554, + 9552, + 9636, + 9639, + 0, + 9552, + 9549, + 9632, + 9636, + 0, + 9549, + 9545, + 9629, + 9632, + 0, + 9545, + 9543, + 9626, + 9629, + 0, + 9543, + 9541, + 9623, + 9626, + 0, + 9541, + 9539, + 9621, + 9623, + 0, + 9539, + 9537, + 9619, + 9621, + 0, + 9537, + 9535, + 9617, + 9619, + 0, + 9535, + 9533, + 9615, + 9617, + 0, + 9533, + 9531, + 9613, + 9615, + 0, + 9531, + 9529, + 9611, + 9613, + 0, + 9529, + 9527, + 9609, + 9611, + 0, + 9527, + 9525, + 9607, + 9609, + 0, + 9525, + 9522, + 9605, + 9607, + 0, + 9522, + 9521, + 9603, + 9605, + 0, + 9521, + 9519, + 9601, + 9603, + 0, + 9519, + 9517, + 9599, + 9601, + 0, + 9517, + 9515, + 9597, + 9599, + 0, + 9515, + 9514, + 9596, + 9597, + 0, + 9596, + 9595, + 9625, + 9628, + 0, + 9595, + 9598, + 9640, + 9625, + 0, + 9598, + 9600, + 9644, + 9640, + 0, + 9600, + 9602, + 9646, + 9644, + 0, + 9602, + 9604, + 9651, + 9646, + 0, + 9604, + 9606, + 9655, + 9651, + 0, + 9606, + 9608, + 9660, + 9655, + 0, + 9608, + 9610, + 9668, + 9660, + 0, + 9610, + 9612, + 9682, + 9668, + 0, + 9612, + 9614, + 9688, + 9682, + 0, + 9614, + 9616, + 9698, + 9688, + 0, + 9616, + 9618, + 9700, + 9698, + 0, + 9618, + 9620, + 9702, + 9700, + 0, + 9620, + 9622, + 9704, + 9702, + 0, + 9622, + 9624, + 9706, + 9704, + 0, + 9624, + 9627, + 9708, + 9706, + 0, + 9627, + 9631, + 9710, + 9708, + 0, + 9631, + 9633, + 9712, + 9710, + 0, + 9633, + 9637, + 9716, + 9712, + 0, + 9637, + 9641, + 9719, + 9716, + 0, + 9641, + 9642, + 9720, + 9719, + 0, + 9642, + 9669, + 9735, + 9720, + 0, + 9669, + 9677, + 9742, + 9735, + 0, + 9677, + 9684, + 9748, + 9742, + 0, + 9684, + 9687, + 9749, + 9748, + 0, + 9687, + 9690, + 9751, + 9749, + 0, + 9690, + 9691, + 9753, + 9751, + 0, + 9691, + 9693, + 9755, + 9753, + 0, + 9693, + 9695, + 9757, + 9755, + 0, + 9695, + 9696, + 9758, + 9757, + 0, + 9696, + 9694, + 9756, + 9758, + 0, + 9694, + 9692, + 9754, + 9756, + 0, + 9692, + 9689, + 9752, + 9754, + 0, + 9689, + 9686, + 9750, + 9752, + 0, + 9686, + 9683, + 9747, + 9750, + 0, + 9683, + 9679, + 9745, + 9747, + 0, + 9679, + 9672, + 9738, + 9745, + 0, + 9672, + 9666, + 9733, + 9738, + 0, + 9666, + 9661, + 9729, + 9733, + 0, + 9661, + 9656, + 9726, + 9729, + 0, + 9656, + 9653, + 9724, + 9726, + 0, + 9653, + 9638, + 9717, + 9724, + 0, + 9638, + 9634, + 9713, + 9717, + 0, + 9634, + 9635, + 9715, + 9713, + 0, + 9635, + 9649, + 9722, + 9715, + 0, + 9649, + 9650, + 9723, + 9722, + 0, + 9650, + 9654, + 9725, + 9723, + 0, + 9654, + 9658, + 9727, + 9725, + 0, + 9658, + 9662, + 9730, + 9727, + 0, + 9662, + 9665, + 9732, + 9730, + 0, + 9665, + 9670, + 9736, + 9732, + 0, + 9670, + 9674, + 9739, + 9736, + 0, + 9674, + 9676, + 9741, + 9739, + 0, + 9676, + 9680, + 9744, + 9741, + 0, + 9680, + 9681, + 9746, + 9744, + 0, + 9681, + 9678, + 9743, + 9746, + 0, + 9678, + 9675, + 9740, + 9743, + 0, + 9675, + 9671, + 9737, + 9740, + 0, + 9671, + 9667, + 9734, + 9737, + 0, + 9667, + 9664, + 9731, + 9734, + 0, + 9664, + 9659, + 9728, + 9731, + 0, + 9659, + 9648, + 9721, + 9728, + 0, + 9648, + 9639, + 9718, + 9721, + 0, + 9639, + 9636, + 9714, + 9718, + 0, + 9636, + 9632, + 9711, + 9714, + 0, + 9632, + 9629, + 9709, + 9711, + 0, + 9629, + 9626, + 9707, + 9709, + 0, + 9626, + 9623, + 9705, + 9707, + 0, + 9623, + 9621, + 9703, + 9705, + 0, + 9621, + 9619, + 9701, + 9703, + 0, + 9619, + 9617, + 9699, + 9701, + 0, + 9617, + 9615, + 9697, + 9699, + 0, + 9615, + 9613, + 9685, + 9697, + 0, + 9613, + 9611, + 9673, + 9685, + 0, + 9611, + 9609, + 9663, + 9673, + 0, + 9609, + 9607, + 9657, + 9663, + 0, + 9607, + 9605, + 9652, + 9657, + 0, + 9605, + 9603, + 9647, + 9652, + 0, + 9603, + 9601, + 9645, + 9647, + 0, + 9601, + 9599, + 9643, + 9645, + 0, + 9599, + 9597, + 9630, + 9643, + 0, + 9597, + 9596, + 9628, + 9630, + 0, + 9628, + 9625, + 9759, + 9760, + 0, + 9625, + 9640, + 9762, + 9759, + 0, + 9640, + 9644, + 9764, + 9762, + 0, + 9644, + 9646, + 9766, + 9764, + 0, + 9646, + 9651, + 9768, + 9766, + 0, + 9651, + 9655, + 9770, + 9768, + 0, + 9655, + 9660, + 9772, + 9770, + 0, + 9660, + 9668, + 9774, + 9772, + 0, + 9668, + 9682, + 9776, + 9774, + 0, + 9682, + 9688, + 9778, + 9776, + 0, + 9688, + 9698, + 9780, + 9778, + 0, + 9698, + 9700, + 9782, + 9780, + 0, + 9700, + 9702, + 9784, + 9782, + 0, + 9702, + 9704, + 9786, + 9784, + 0, + 9704, + 9706, + 9788, + 9786, + 0, + 9706, + 9708, + 9790, + 9788, + 0, + 9708, + 9710, + 9792, + 9790, + 0, + 9710, + 9712, + 9794, + 9792, + 0, + 9712, + 9716, + 9797, + 9794, + 0, + 9716, + 9719, + 9801, + 9797, + 0, + 9719, + 9720, + 9802, + 9801, + 0, + 9720, + 9735, + 9817, + 9802, + 0, + 9735, + 9742, + 9823, + 9817, + 0, + 9742, + 9748, + 9829, + 9823, + 0, + 9748, + 9749, + 9831, + 9829, + 0, + 9749, + 9751, + 9833, + 9831, + 0, + 9751, + 9753, + 9835, + 9833, + 0, + 9753, + 9755, + 9837, + 9835, + 0, + 9755, + 9757, + 9839, + 9837, + 0, + 9757, + 9758, + 9840, + 9839, + 0, + 9758, + 9756, + 9838, + 9840, + 0, + 9756, + 9754, + 9836, + 9838, + 0, + 9754, + 9752, + 9834, + 9836, + 0, + 9752, + 9750, + 9832, + 9834, + 0, + 9750, + 9747, + 9830, + 9832, + 0, + 9747, + 9745, + 9828, + 9830, + 0, + 9745, + 9738, + 9820, + 9828, + 0, + 9738, + 9733, + 9816, + 9820, + 0, + 9733, + 9729, + 9811, + 9816, + 0, + 9729, + 9726, + 9808, + 9811, + 0, + 9726, + 9724, + 9806, + 9808, + 0, + 9724, + 9717, + 9800, + 9806, + 0, + 9717, + 9713, + 9796, + 9800, + 0, + 9713, + 9715, + 9798, + 9796, + 0, + 9715, + 9722, + 9804, + 9798, + 0, + 9722, + 9723, + 9805, + 9804, + 0, + 9723, + 9725, + 9807, + 9805, + 0, + 9725, + 9727, + 9809, + 9807, + 0, + 9727, + 9730, + 9812, + 9809, + 0, + 9730, + 9732, + 9814, + 9812, + 0, + 9732, + 9736, + 9818, + 9814, + 0, + 9736, + 9739, + 9821, + 9818, + 0, + 9739, + 9741, + 9824, + 9821, + 0, + 9741, + 9744, + 9826, + 9824, + 0, + 9744, + 9746, + 9827, + 9826, + 0, + 9746, + 9743, + 9825, + 9827, + 0, + 9743, + 9740, + 9822, + 9825, + 0, + 9740, + 9737, + 9819, + 9822, + 0, + 9737, + 9734, + 9815, + 9819, + 0, + 9734, + 9731, + 9813, + 9815, + 0, + 9731, + 9728, + 9810, + 9813, + 0, + 9728, + 9721, + 9803, + 9810, + 0, + 9721, + 9718, + 9799, + 9803, + 0, + 9718, + 9714, + 9795, + 9799, + 0, + 9714, + 9711, + 9793, + 9795, + 0, + 9711, + 9709, + 9791, + 9793, + 0, + 9709, + 9707, + 9789, + 9791, + 0, + 9707, + 9705, + 9787, + 9789, + 0, + 9705, + 9703, + 9785, + 9787, + 0, + 9703, + 9701, + 9783, + 9785, + 0, + 9701, + 9699, + 9781, + 9783, + 0, + 9699, + 9697, + 9779, + 9781, + 0, + 9697, + 9685, + 9777, + 9779, + 0, + 9685, + 9673, + 9775, + 9777, + 0, + 9673, + 9663, + 9773, + 9775, + 0, + 9663, + 9657, + 9771, + 9773, + 0, + 9657, + 9652, + 9769, + 9771, + 0, + 9652, + 9647, + 9767, + 9769, + 0, + 9647, + 9645, + 9765, + 9767, + 0, + 9645, + 9643, + 9763, + 9765, + 0, + 9643, + 9630, + 9761, + 9763, + 0, + 9630, + 9628, + 9760, + 9761, + 0, + 9760, + 9759, + 9841, + 9842, + 0, + 9759, + 9762, + 9844, + 9841, + 0, + 9762, + 9764, + 9845, + 9844, + 0, + 9764, + 9766, + 9848, + 9845, + 0, + 9766, + 9768, + 9850, + 9848, + 0, + 9768, + 9770, + 9852, + 9850, + 0, + 9770, + 9772, + 9854, + 9852, + 0, + 9772, + 9774, + 9856, + 9854, + 0, + 9774, + 9776, + 9858, + 9856, + 0, + 9776, + 9778, + 9860, + 9858, + 0, + 9778, + 9780, + 9862, + 9860, + 0, + 9780, + 9782, + 9864, + 9862, + 0, + 9782, + 9784, + 9866, + 9864, + 0, + 9784, + 9786, + 9868, + 9866, + 0, + 9786, + 9788, + 9870, + 9868, + 0, + 9788, + 9790, + 9872, + 9870, + 0, + 9790, + 9792, + 9874, + 9872, + 0, + 9792, + 9794, + 9876, + 9874, + 0, + 9794, + 9797, + 9878, + 9876, + 0, + 9797, + 9801, + 9882, + 9878, + 0, + 9801, + 9802, + 9884, + 9882, + 0, + 9802, + 9817, + 9897, + 9884, + 0, + 9817, + 9823, + 9902, + 9897, + 0, + 9823, + 9829, + 9911, + 9902, + 0, + 9829, + 9831, + 9912, + 9911, + 0, + 9831, + 9833, + 9914, + 9912, + 0, + 9833, + 9835, + 9916, + 9914, + 0, + 9835, + 9837, + 9918, + 9916, + 0, + 9837, + 9839, + 9920, + 9918, + 0, + 9839, + 9840, + 9922, + 9920, + 0, + 9840, + 9838, + 9921, + 9922, + 0, + 9838, + 9836, + 9919, + 9921, + 0, + 9836, + 9834, + 9917, + 9919, + 0, + 9834, + 9832, + 9915, + 9917, + 0, + 9832, + 9830, + 9913, + 9915, + 0, + 9830, + 9828, + 9910, + 9913, + 0, + 9828, + 9820, + 9904, + 9910, + 0, + 9820, + 9816, + 9899, + 9904, + 0, + 9816, + 9811, + 9894, + 9899, + 0, + 9811, + 9808, + 9890, + 9894, + 0, + 9808, + 9806, + 9888, + 9890, + 0, + 9806, + 9800, + 9883, + 9888, + 0, + 9800, + 9796, + 9880, + 9883, + 0, + 9796, + 9798, + 9881, + 9880, + 0, + 9798, + 9804, + 9886, + 9881, + 0, + 9804, + 9805, + 9887, + 9886, + 0, + 9805, + 9807, + 9889, + 9887, + 0, + 9807, + 9809, + 9892, + 9889, + 0, + 9809, + 9812, + 9895, + 9892, + 0, + 9812, + 9814, + 9898, + 9895, + 0, + 9814, + 9818, + 9901, + 9898, + 0, + 9818, + 9821, + 9905, + 9901, + 0, + 9821, + 9824, + 9907, + 9905, + 0, + 9824, + 9826, + 9909, + 9907, + 0, + 9826, + 9827, + 9908, + 9909, + 0, + 9827, + 9825, + 9906, + 9908, + 0, + 9825, + 9822, + 9903, + 9906, + 0, + 9822, + 9819, + 9900, + 9903, + 0, + 9819, + 9815, + 9896, + 9900, + 0, + 9815, + 9813, + 9893, + 9896, + 0, + 9813, + 9810, + 9891, + 9893, + 0, + 9810, + 9803, + 9885, + 9891, + 0, + 9803, + 9799, + 9879, + 9885, + 0, + 9799, + 9795, + 9877, + 9879, + 0, + 9795, + 9793, + 9875, + 9877, + 0, + 9793, + 9791, + 9873, + 9875, + 0, + 9791, + 9789, + 9871, + 9873, + 0, + 9789, + 9787, + 9869, + 9871, + 0, + 9787, + 9785, + 9867, + 9869, + 0, + 9785, + 9783, + 9865, + 9867, + 0, + 9783, + 9781, + 9863, + 9865, + 0, + 9781, + 9779, + 9861, + 9863, + 0, + 9779, + 9777, + 9859, + 9861, + 0, + 9777, + 9775, + 9857, + 9859, + 0, + 9775, + 9773, + 9855, + 9857, + 0, + 9773, + 9771, + 9853, + 9855, + 0, + 9771, + 9769, + 9851, + 9853, + 0, + 9769, + 9767, + 9849, + 9851, + 0, + 9767, + 9765, + 9847, + 9849, + 0, + 9765, + 9763, + 9846, + 9847, + 0, + 9763, + 9761, + 9843, + 9846, + 0, + 9761, + 9760, + 9842, + 9843, + 0, + 9842, + 9841, + 9923, + 9924, + 0, + 9841, + 9844, + 9926, + 9923, + 0, + 9844, + 9845, + 9927, + 9926, + 0, + 9845, + 9848, + 9930, + 9927, + 0, + 9848, + 9850, + 9932, + 9930, + 0, + 9850, + 9852, + 9934, + 9932, + 0, + 9852, + 9854, + 9936, + 9934, + 0, + 9854, + 9856, + 9939, + 9936, + 0, + 9856, + 9858, + 9942, + 9939, + 0, + 9858, + 9860, + 9945, + 9942, + 0, + 9860, + 9862, + 9947, + 9945, + 0, + 9862, + 9864, + 9950, + 9947, + 0, + 9864, + 9866, + 9955, + 9950, + 0, + 9866, + 9868, + 9959, + 9955, + 0, + 9868, + 9870, + 9963, + 9959, + 0, + 9870, + 9872, + 9967, + 9963, + 0, + 9872, + 9874, + 9971, + 9967, + 0, + 9874, + 9876, + 9974, + 9971, + 0, + 9876, + 9878, + 9978, + 9974, + 0, + 9878, + 9882, + 9982, + 9978, + 0, + 9882, + 9884, + 9986, + 9982, + 0, + 9884, + 9897, + 10012, + 9986, + 0, + 9897, + 9902, + 10018, + 10012, + 0, + 9902, + 9911, + 10028, + 10018, + 0, + 9911, + 9912, + 10031, + 10028, + 0, + 9912, + 9914, + 10034, + 10031, + 0, + 9914, + 9916, + 10036, + 10034, + 0, + 9916, + 9918, + 10039, + 10036, + 0, + 9918, + 9920, + 10041, + 10039, + 0, + 9920, + 9922, + 10044, + 10041, + 0, + 9922, + 9921, + 10042, + 10044, + 0, + 9921, + 9919, + 10040, + 10042, + 0, + 9919, + 9917, + 10037, + 10040, + 0, + 9917, + 9915, + 10035, + 10037, + 0, + 9915, + 9913, + 10033, + 10035, + 0, + 9913, + 9910, + 10029, + 10033, + 0, + 9910, + 9904, + 10023, + 10029, + 0, + 9904, + 9899, + 10016, + 10023, + 0, + 9899, + 9894, + 10008, + 10016, + 0, + 9894, + 9890, + 10004, + 10008, + 0, + 9890, + 9888, + 9999, + 10004, + 0, + 9888, + 9883, + 9988, + 9999, + 0, + 9883, + 9880, + 9983, + 9988, + 0, + 9880, + 9881, + 9984, + 9983, + 0, + 9881, + 9886, + 9995, + 9984, + 0, + 9886, + 9887, + 9998, + 9995, + 0, + 9887, + 9889, + 10001, + 9998, + 0, + 9889, + 9892, + 10005, + 10001, + 0, + 9892, + 9895, + 10009, + 10005, + 0, + 9895, + 9898, + 10014, + 10009, + 0, + 9898, + 9901, + 10017, + 10014, + 0, + 9901, + 9905, + 10022, + 10017, + 0, + 9905, + 9907, + 10025, + 10022, + 0, + 9907, + 9909, + 10027, + 10025, + 0, + 9909, + 9908, + 10026, + 10027, + 0, + 9908, + 9906, + 10024, + 10026, + 0, + 9906, + 9903, + 10019, + 10024, + 0, + 9903, + 9900, + 10015, + 10019, + 0, + 9900, + 9896, + 10011, + 10015, + 0, + 9896, + 9893, + 10007, + 10011, + 0, + 9893, + 9891, + 10002, + 10007, + 0, + 9891, + 9885, + 9992, + 10002, + 0, + 9885, + 9879, + 9980, + 9992, + 0, + 9879, + 9877, + 9977, + 9980, + 0, + 9877, + 9875, + 9973, + 9977, + 0, + 9875, + 9873, + 9969, + 9973, + 0, + 9873, + 9871, + 9965, + 9969, + 0, + 9871, + 9869, + 9961, + 9965, + 0, + 9869, + 9867, + 9957, + 9961, + 0, + 9867, + 9865, + 9953, + 9957, + 0, + 9865, + 9863, + 9949, + 9953, + 0, + 9863, + 9861, + 9946, + 9949, + 0, + 9861, + 9859, + 9944, + 9946, + 0, + 9859, + 9857, + 9940, + 9944, + 0, + 9857, + 9855, + 9937, + 9940, + 0, + 9855, + 9853, + 9935, + 9937, + 0, + 9853, + 9851, + 9933, + 9935, + 0, + 9851, + 9849, + 9931, + 9933, + 0, + 9849, + 9847, + 9929, + 9931, + 0, + 9847, + 9846, + 9928, + 9929, + 0, + 9846, + 9843, + 9925, + 9928, + 0, + 9843, + 9842, + 9924, + 9925, + 0, + 9924, + 9923, + 9938, + 9941, + 0, + 9923, + 9926, + 9948, + 9938, + 0, + 9926, + 9927, + 9951, + 9948, + 0, + 9927, + 9930, + 9956, + 9951, + 0, + 9930, + 9932, + 9960, + 9956, + 0, + 9932, + 9934, + 9964, + 9960, + 0, + 9934, + 9936, + 9968, + 9964, + 0, + 9936, + 9939, + 9972, + 9968, + 0, + 9939, + 9942, + 9976, + 9972, + 0, + 9942, + 9945, + 9981, + 9976, + 0, + 9945, + 9947, + 9987, + 9981, + 0, + 9947, + 9950, + 9990, + 9987, + 0, + 9950, + 9955, + 9993, + 9990, + 0, + 9955, + 9959, + 9996, + 9993, + 0, + 9959, + 9963, + 10000, + 9996, + 0, + 9963, + 9967, + 10006, + 10000, + 0, + 9967, + 9971, + 10013, + 10006, + 0, + 9971, + 9974, + 10021, + 10013, + 0, + 9974, + 9978, + 10032, + 10021, + 0, + 9978, + 9982, + 10043, + 10032, + 0, + 9982, + 9986, + 10047, + 10043, + 0, + 9986, + 10012, + 10061, + 10047, + 0, + 10012, + 10018, + 10066, + 10061, + 0, + 10018, + 10028, + 10074, + 10066, + 0, + 10028, + 10031, + 10076, + 10074, + 0, + 10031, + 10034, + 10078, + 10076, + 0, + 10034, + 10036, + 10080, + 10078, + 0, + 10036, + 10039, + 10082, + 10080, + 0, + 10039, + 10041, + 10084, + 10082, + 0, + 10041, + 10044, + 10086, + 10084, + 0, + 10044, + 10042, + 10085, + 10086, + 0, + 10042, + 10040, + 10083, + 10085, + 0, + 10040, + 10037, + 10081, + 10083, + 0, + 10037, + 10035, + 10079, + 10081, + 0, + 10035, + 10033, + 10077, + 10079, + 0, + 10033, + 10029, + 10075, + 10077, + 0, + 10029, + 10023, + 10069, + 10075, + 0, + 10023, + 10016, + 10064, + 10069, + 0, + 10016, + 10008, + 10058, + 10064, + 0, + 10008, + 10004, + 10055, + 10058, + 0, + 10004, + 9999, + 10052, + 10055, + 0, + 9999, + 9988, + 10048, + 10052, + 0, + 9988, + 9983, + 10045, + 10048, + 0, + 9983, + 9984, + 10046, + 10045, + 0, + 9984, + 9995, + 10050, + 10046, + 0, + 9995, + 9998, + 10051, + 10050, + 0, + 9998, + 10001, + 10053, + 10051, + 0, + 10001, + 10005, + 10056, + 10053, + 0, + 10005, + 10009, + 10059, + 10056, + 0, + 10009, + 10014, + 10062, + 10059, + 0, + 10014, + 10017, + 10065, + 10062, + 0, + 10017, + 10022, + 10068, + 10065, + 0, + 10022, + 10025, + 10071, + 10068, + 0, + 10025, + 10027, + 10073, + 10071, + 0, + 10027, + 10026, + 10072, + 10073, + 0, + 10026, + 10024, + 10070, + 10072, + 0, + 10024, + 10019, + 10067, + 10070, + 0, + 10019, + 10015, + 10063, + 10067, + 0, + 10015, + 10011, + 10060, + 10063, + 0, + 10011, + 10007, + 10057, + 10060, + 0, + 10007, + 10002, + 10054, + 10057, + 0, + 10002, + 9992, + 10049, + 10054, + 0, + 9992, + 9980, + 10038, + 10049, + 0, + 9980, + 9977, + 10030, + 10038, + 0, + 9977, + 9973, + 10020, + 10030, + 0, + 9973, + 9969, + 10010, + 10020, + 0, + 9969, + 9965, + 10003, + 10010, + 0, + 9965, + 9961, + 9997, + 10003, + 0, + 9961, + 9957, + 9994, + 9997, + 0, + 9957, + 9953, + 9991, + 9994, + 0, + 9953, + 9949, + 9989, + 9991, + 0, + 9949, + 9946, + 9985, + 9989, + 0, + 9946, + 9944, + 9979, + 9985, + 0, + 9944, + 9940, + 9975, + 9979, + 0, + 9940, + 9937, + 9970, + 9975, + 0, + 9937, + 9935, + 9966, + 9970, + 0, + 9935, + 9933, + 9962, + 9966, + 0, + 9933, + 9931, + 9958, + 9962, + 0, + 9931, + 9929, + 9954, + 9958, + 0, + 9929, + 9928, + 9952, + 9954, + 0, + 9928, + 9925, + 9943, + 9952, + 0, + 9925, + 9924, + 9941, + 9943, + 0, + 9941, + 9938, + 10087, + 10088, + 0, + 9938, + 9948, + 10090, + 10087, + 0, + 9948, + 9951, + 10091, + 10090, + 0, + 9951, + 9956, + 10094, + 10091, + 0, + 9956, + 9960, + 10096, + 10094, + 0, + 9960, + 9964, + 10098, + 10096, + 0, + 9964, + 9968, + 10100, + 10098, + 0, + 9968, + 9972, + 10102, + 10100, + 0, + 9972, + 9976, + 10104, + 10102, + 0, + 9976, + 9981, + 10106, + 10104, + 0, + 9981, + 9987, + 10108, + 10106, + 0, + 9987, + 9990, + 10110, + 10108, + 0, + 9990, + 9993, + 10112, + 10110, + 0, + 9993, + 9996, + 10114, + 10112, + 0, + 9996, + 10000, + 10116, + 10114, + 0, + 10000, + 10006, + 10118, + 10116, + 0, + 10006, + 10013, + 10120, + 10118, + 0, + 10013, + 10021, + 10122, + 10120, + 0, + 10021, + 10032, + 10124, + 10122, + 0, + 10032, + 10043, + 10126, + 10124, + 0, + 10043, + 10047, + 10128, + 10126, + 0, + 10047, + 10061, + 10141, + 10128, + 0, + 10061, + 10066, + 10146, + 10141, + 0, + 10066, + 10074, + 10154, + 10146, + 0, + 10074, + 10076, + 10157, + 10154, + 0, + 10076, + 10078, + 10159, + 10157, + 0, + 10078, + 10080, + 10161, + 10159, + 0, + 10080, + 10082, + 10163, + 10161, + 0, + 10082, + 10084, + 10165, + 10163, + 0, + 10084, + 10086, + 10167, + 10165, + 0, + 10086, + 10085, + 10168, + 10167, + 0, + 10085, + 10083, + 10166, + 10168, + 0, + 10083, + 10081, + 10164, + 10166, + 0, + 10081, + 10079, + 10162, + 10164, + 0, + 10079, + 10077, + 10160, + 10162, + 0, + 10077, + 10075, + 10158, + 10160, + 0, + 10075, + 10069, + 10155, + 10158, + 0, + 10069, + 10064, + 10148, + 10155, + 0, + 10064, + 10058, + 10143, + 10148, + 0, + 10058, + 10055, + 10137, + 10143, + 0, + 10055, + 10052, + 10134, + 10137, + 0, + 10052, + 10048, + 10130, + 10134, + 0, + 10048, + 10045, + 10127, + 10130, + 0, + 10045, + 10046, + 10129, + 10127, + 0, + 10046, + 10050, + 10132, + 10129, + 0, + 10050, + 10051, + 10133, + 10132, + 0, + 10051, + 10053, + 10136, + 10133, + 0, + 10053, + 10056, + 10139, + 10136, + 0, + 10056, + 10059, + 10142, + 10139, + 0, + 10059, + 10062, + 10145, + 10142, + 0, + 10062, + 10065, + 10149, + 10145, + 0, + 10065, + 10068, + 10151, + 10149, + 0, + 10068, + 10071, + 10153, + 10151, + 0, + 10071, + 10073, + 10156, + 10153, + 0, + 10073, + 10072, + 10152, + 10156, + 0, + 10072, + 10070, + 10150, + 10152, + 0, + 10070, + 10067, + 10147, + 10150, + 0, + 10067, + 10063, + 10144, + 10147, + 0, + 10063, + 10060, + 10140, + 10144, + 0, + 10060, + 10057, + 10138, + 10140, + 0, + 10057, + 10054, + 10135, + 10138, + 0, + 10054, + 10049, + 10131, + 10135, + 0, + 10049, + 10038, + 10125, + 10131, + 0, + 10038, + 10030, + 10123, + 10125, + 0, + 10030, + 10020, + 10121, + 10123, + 0, + 10020, + 10010, + 10119, + 10121, + 0, + 10010, + 10003, + 10117, + 10119, + 0, + 10003, + 9997, + 10115, + 10117, + 0, + 9997, + 9994, + 10113, + 10115, + 0, + 9994, + 9991, + 10111, + 10113, + 0, + 9991, + 9989, + 10109, + 10111, + 0, + 9989, + 9985, + 10107, + 10109, + 0, + 9985, + 9979, + 10105, + 10107, + 0, + 9979, + 9975, + 10103, + 10105, + 0, + 9975, + 9970, + 10101, + 10103, + 0, + 9970, + 9966, + 10099, + 10101, + 0, + 9966, + 9962, + 10097, + 10099, + 0, + 9962, + 9958, + 10095, + 10097, + 0, + 9958, + 9954, + 10093, + 10095, + 0, + 9954, + 9952, + 10092, + 10093, + 0, + 9952, + 9943, + 10089, + 10092, + 0, + 9943, + 9941, + 10088, + 10089, + 0, + 10088, + 10087, + 10169, + 10170, + 0, + 10087, + 10090, + 10172, + 10169, + 0, + 10090, + 10091, + 10173, + 10172, + 0, + 10091, + 10094, + 10176, + 10173, + 0, + 10094, + 10096, + 10178, + 10176, + 0, + 10096, + 10098, + 10180, + 10178, + 0, + 10098, + 10100, + 10182, + 10180, + 0, + 10100, + 10102, + 10184, + 10182, + 0, + 10102, + 10104, + 10186, + 10184, + 0, + 10104, + 10106, + 10188, + 10186, + 0, + 10106, + 10108, + 10190, + 10188, + 0, + 10108, + 10110, + 10192, + 10190, + 0, + 10110, + 10112, + 10194, + 10192, + 0, + 10112, + 10114, + 10196, + 10194, + 0, + 10114, + 10116, + 10198, + 10196, + 0, + 10116, + 10118, + 10200, + 10198, + 0, + 10118, + 10120, + 10202, + 10200, + 0, + 10120, + 10122, + 10204, + 10202, + 0, + 10122, + 10124, + 10206, + 10204, + 0, + 10124, + 10126, + 10208, + 10206, + 0, + 10126, + 10128, + 10209, + 10208, + 0, + 10128, + 10141, + 10222, + 10209, + 0, + 10141, + 10146, + 10227, + 10222, + 0, + 10146, + 10154, + 10234, + 10227, + 0, + 10154, + 10157, + 10239, + 10234, + 0, + 10157, + 10159, + 10241, + 10239, + 0, + 10159, + 10161, + 10243, + 10241, + 0, + 10161, + 10163, + 10245, + 10243, + 0, + 10163, + 10165, + 10247, + 10245, + 0, + 10165, + 10167, + 10249, + 10247, + 0, + 10167, + 10168, + 10250, + 10249, + 0, + 10168, + 10166, + 10248, + 10250, + 0, + 10166, + 10164, + 10246, + 10248, + 0, + 10164, + 10162, + 10244, + 10246, + 0, + 10162, + 10160, + 10242, + 10244, + 0, + 10160, + 10158, + 10240, + 10242, + 0, + 10158, + 10155, + 10238, + 10240, + 0, + 10155, + 10148, + 10230, + 10238, + 0, + 10148, + 10143, + 10225, + 10230, + 0, + 10143, + 10137, + 10220, + 10225, + 0, + 10137, + 10134, + 10216, + 10220, + 0, + 10134, + 10130, + 10212, + 10216, + 0, + 10130, + 10127, + 10210, + 10212, + 0, + 10127, + 10129, + 10211, + 10210, + 0, + 10129, + 10132, + 10214, + 10211, + 0, + 10132, + 10133, + 10215, + 10214, + 0, + 10133, + 10136, + 10218, + 10215, + 0, + 10136, + 10139, + 10221, + 10218, + 0, + 10139, + 10142, + 10224, + 10221, + 0, + 10142, + 10145, + 10228, + 10224, + 0, + 10145, + 10149, + 10231, + 10228, + 0, + 10149, + 10151, + 10233, + 10231, + 0, + 10151, + 10153, + 10236, + 10233, + 0, + 10153, + 10156, + 10237, + 10236, + 0, + 10156, + 10152, + 10235, + 10237, + 0, + 10152, + 10150, + 10232, + 10235, + 0, + 10150, + 10147, + 10229, + 10232, + 0, + 10147, + 10144, + 10226, + 10229, + 0, + 10144, + 10140, + 10223, + 10226, + 0, + 10140, + 10138, + 10219, + 10223, + 0, + 10138, + 10135, + 10217, + 10219, + 0, + 10135, + 10131, + 10213, + 10217, + 0, + 10131, + 10125, + 10207, + 10213, + 0, + 10125, + 10123, + 10205, + 10207, + 0, + 10123, + 10121, + 10203, + 10205, + 0, + 10121, + 10119, + 10201, + 10203, + 0, + 10119, + 10117, + 10199, + 10201, + 0, + 10117, + 10115, + 10197, + 10199, + 0, + 10115, + 10113, + 10195, + 10197, + 0, + 10113, + 10111, + 10193, + 10195, + 0, + 10111, + 10109, + 10191, + 10193, + 0, + 10109, + 10107, + 10189, + 10191, + 0, + 10107, + 10105, + 10187, + 10189, + 0, + 10105, + 10103, + 10185, + 10187, + 0, + 10103, + 10101, + 10183, + 10185, + 0, + 10101, + 10099, + 10181, + 10183, + 0, + 10099, + 10097, + 10179, + 10181, + 0, + 10097, + 10095, + 10177, + 10179, + 0, + 10095, + 10093, + 10175, + 10177, + 0, + 10093, + 10092, + 10174, + 10175, + 0, + 10092, + 10089, + 10171, + 10174, + 0, + 10089, + 10088, + 10170, + 10171, + 0, + 10170, + 10169, + 10251, + 10252, + 0, + 10169, + 10172, + 10254, + 10251, + 0, + 10172, + 10173, + 10255, + 10254, + 0, + 10173, + 10176, + 10258, + 10255, + 0, + 10176, + 10178, + 10260, + 10258, + 0, + 10178, + 10180, + 10262, + 10260, + 0, + 10180, + 10182, + 10264, + 10262, + 0, + 10182, + 10184, + 10266, + 10264, + 0, + 10184, + 10186, + 10268, + 10266, + 0, + 10186, + 10188, + 10270, + 10268, + 0, + 10188, + 10190, + 10272, + 10270, + 0, + 10190, + 10192, + 10274, + 10272, + 0, + 10192, + 10194, + 10276, + 10274, + 0, + 10194, + 10196, + 10278, + 10276, + 0, + 10196, + 10198, + 10280, + 10278, + 0, + 10198, + 10200, + 10282, + 10280, + 0, + 10200, + 10202, + 10284, + 10282, + 0, + 10202, + 10204, + 10286, + 10284, + 0, + 10204, + 10206, + 10287, + 10286, + 0, + 10206, + 10208, + 10290, + 10287, + 0, + 10208, + 10209, + 10291, + 10290, + 0, + 10209, + 10222, + 10304, + 10291, + 0, + 10222, + 10227, + 10309, + 10304, + 0, + 10227, + 10234, + 10315, + 10309, + 0, + 10234, + 10239, + 10321, + 10315, + 0, + 10239, + 10241, + 10323, + 10321, + 0, + 10241, + 10243, + 10325, + 10323, + 0, + 10243, + 10245, + 10327, + 10325, + 0, + 10245, + 10247, + 10329, + 10327, + 0, + 10247, + 10249, + 10331, + 10329, + 0, + 10249, + 10250, + 10332, + 10331, + 0, + 10250, + 10248, + 10330, + 10332, + 0, + 10248, + 10246, + 10328, + 10330, + 0, + 10246, + 10244, + 10326, + 10328, + 0, + 10244, + 10242, + 10324, + 10326, + 0, + 10242, + 10240, + 10322, + 10324, + 0, + 10240, + 10238, + 10320, + 10322, + 0, + 10238, + 10230, + 10312, + 10320, + 0, + 10230, + 10225, + 10307, + 10312, + 0, + 10225, + 10220, + 10302, + 10307, + 0, + 10220, + 10216, + 10298, + 10302, + 0, + 10216, + 10212, + 10294, + 10298, + 0, + 10212, + 10210, + 10292, + 10294, + 0, + 10210, + 10211, + 10293, + 10292, + 0, + 10211, + 10214, + 10296, + 10293, + 0, + 10214, + 10215, + 10297, + 10296, + 0, + 10215, + 10218, + 10300, + 10297, + 0, + 10218, + 10221, + 10303, + 10300, + 0, + 10221, + 10224, + 10306, + 10303, + 0, + 10224, + 10228, + 10310, + 10306, + 0, + 10228, + 10231, + 10313, + 10310, + 0, + 10231, + 10233, + 10316, + 10313, + 0, + 10233, + 10236, + 10318, + 10316, + 0, + 10236, + 10237, + 10319, + 10318, + 0, + 10237, + 10235, + 10317, + 10319, + 0, + 10235, + 10232, + 10314, + 10317, + 0, + 10232, + 10229, + 10311, + 10314, + 0, + 10229, + 10226, + 10308, + 10311, + 0, + 10226, + 10223, + 10305, + 10308, + 0, + 10223, + 10219, + 10301, + 10305, + 0, + 10219, + 10217, + 10299, + 10301, + 0, + 10217, + 10213, + 10295, + 10299, + 0, + 10213, + 10207, + 10289, + 10295, + 0, + 10207, + 10205, + 10288, + 10289, + 0, + 10205, + 10203, + 10285, + 10288, + 0, + 10203, + 10201, + 10283, + 10285, + 0, + 10201, + 10199, + 10281, + 10283, + 0, + 10199, + 10197, + 10279, + 10281, + 0, + 10197, + 10195, + 10277, + 10279, + 0, + 10195, + 10193, + 10275, + 10277, + 0, + 10193, + 10191, + 10273, + 10275, + 0, + 10191, + 10189, + 10271, + 10273, + 0, + 10189, + 10187, + 10269, + 10271, + 0, + 10187, + 10185, + 10267, + 10269, + 0, + 10185, + 10183, + 10265, + 10267, + 0, + 10183, + 10181, + 10263, + 10265, + 0, + 10181, + 10179, + 10261, + 10263, + 0, + 10179, + 10177, + 10259, + 10261, + 0, + 10177, + 10175, + 10257, + 10259, + 0, + 10175, + 10174, + 10256, + 10257, + 0, + 10174, + 10171, + 10253, + 10256, + 0, + 10171, + 10170, + 10252, + 10253, + 0, + 10252, + 10251, + 10333, + 10334, + 0, + 10251, + 10254, + 10336, + 10333, + 0, + 10254, + 10255, + 10337, + 10336, + 0, + 10255, + 10258, + 10340, + 10337, + 0, + 10258, + 10260, + 10342, + 10340, + 0, + 10260, + 10262, + 10344, + 10342, + 0, + 10262, + 10264, + 10346, + 10344, + 0, + 10264, + 10266, + 10348, + 10346, + 0, + 10266, + 10268, + 10350, + 10348, + 0, + 10268, + 10270, + 10352, + 10350, + 0, + 10270, + 10272, + 10354, + 10352, + 0, + 10272, + 10274, + 10356, + 10354, + 0, + 10274, + 10276, + 10358, + 10356, + 0, + 10276, + 10278, + 10360, + 10358, + 0, + 10278, + 10280, + 10362, + 10360, + 0, + 10280, + 10282, + 10364, + 10362, + 0, + 10282, + 10284, + 10366, + 10364, + 0, + 10284, + 10286, + 10368, + 10366, + 0, + 10286, + 10287, + 10369, + 10368, + 0, + 10287, + 10290, + 10372, + 10369, + 0, + 10290, + 10291, + 10373, + 10372, + 0, + 10291, + 10304, + 10385, + 10373, + 0, + 10304, + 10309, + 10390, + 10385, + 0, + 10309, + 10315, + 10396, + 10390, + 0, + 10315, + 10321, + 10402, + 10396, + 0, + 10321, + 10323, + 10404, + 10402, + 0, + 10323, + 10325, + 10406, + 10404, + 0, + 10325, + 10327, + 10408, + 10406, + 0, + 10327, + 10329, + 10410, + 10408, + 0, + 10329, + 10331, + 10412, + 10410, + 0, + 10331, + 10332, + 10414, + 10412, + 0, + 10332, + 10330, + 10413, + 10414, + 0, + 10330, + 10328, + 10411, + 10413, + 0, + 10328, + 10326, + 10409, + 10411, + 0, + 10326, + 10324, + 10407, + 10409, + 0, + 10324, + 10322, + 10405, + 10407, + 0, + 10322, + 10320, + 10403, + 10405, + 0, + 10320, + 10312, + 10397, + 10403, + 0, + 10312, + 10307, + 10391, + 10397, + 0, + 10307, + 10302, + 10384, + 10391, + 0, + 10302, + 10298, + 10381, + 10384, + 0, + 10298, + 10294, + 10377, + 10381, + 0, + 10294, + 10292, + 10374, + 10377, + 0, + 10292, + 10293, + 10375, + 10374, + 0, + 10293, + 10296, + 10378, + 10375, + 0, + 10296, + 10297, + 10379, + 10378, + 0, + 10297, + 10300, + 10383, + 10379, + 0, + 10300, + 10303, + 10387, + 10383, + 0, + 10303, + 10306, + 10389, + 10387, + 0, + 10306, + 10310, + 10393, + 10389, + 0, + 10310, + 10313, + 10395, + 10393, + 0, + 10313, + 10316, + 10399, + 10395, + 0, + 10316, + 10318, + 10400, + 10399, + 0, + 10318, + 10319, + 10401, + 10400, + 0, + 10319, + 10317, + 10398, + 10401, + 0, + 10317, + 10314, + 10394, + 10398, + 0, + 10314, + 10311, + 10392, + 10394, + 0, + 10311, + 10308, + 10388, + 10392, + 0, + 10308, + 10305, + 10386, + 10388, + 0, + 10305, + 10301, + 10382, + 10386, + 0, + 10301, + 10299, + 10380, + 10382, + 0, + 10299, + 10295, + 10376, + 10380, + 0, + 10295, + 10289, + 10371, + 10376, + 0, + 10289, + 10288, + 10370, + 10371, + 0, + 10288, + 10285, + 10367, + 10370, + 0, + 10285, + 10283, + 10365, + 10367, + 0, + 10283, + 10281, + 10363, + 10365, + 0, + 10281, + 10279, + 10361, + 10363, + 0, + 10279, + 10277, + 10359, + 10361, + 0, + 10277, + 10275, + 10357, + 10359, + 0, + 10275, + 10273, + 10355, + 10357, + 0, + 10273, + 10271, + 10353, + 10355, + 0, + 10271, + 10269, + 10351, + 10353, + 0, + 10269, + 10267, + 10349, + 10351, + 0, + 10267, + 10265, + 10347, + 10349, + 0, + 10265, + 10263, + 10345, + 10347, + 0, + 10263, + 10261, + 10343, + 10345, + 0, + 10261, + 10259, + 10341, + 10343, + 0, + 10259, + 10257, + 10339, + 10341, + 0, + 10257, + 10256, + 10338, + 10339, + 0, + 10256, + 10253, + 10335, + 10338, + 0, + 10253, + 10252, + 10334, + 10335, + 0, + 10334, + 10333, + 10415, + 10416, + 0, + 10333, + 10336, + 10418, + 10415, + 0, + 10336, + 10337, + 10419, + 10418, + 0, + 10337, + 10340, + 10422, + 10419, + 0, + 10340, + 10342, + 10424, + 10422, + 0, + 10342, + 10344, + 10426, + 10424, + 0, + 10344, + 10346, + 10428, + 10426, + 0, + 10346, + 10348, + 10430, + 10428, + 0, + 10348, + 10350, + 10432, + 10430, + 0, + 10350, + 10352, + 10434, + 10432, + 0, + 10352, + 10354, + 10436, + 10434, + 0, + 10354, + 10356, + 10438, + 10436, + 0, + 10356, + 10358, + 10440, + 10438, + 0, + 10358, + 10360, + 10442, + 10440, + 0, + 10360, + 10362, + 10444, + 10442, + 0, + 10362, + 10364, + 10446, + 10444, + 0, + 10364, + 10366, + 10448, + 10446, + 0, + 10366, + 10368, + 10450, + 10448, + 0, + 10368, + 10369, + 10451, + 10450, + 0, + 10369, + 10372, + 10454, + 10451, + 0, + 10372, + 10373, + 10455, + 10454, + 0, + 10373, + 10385, + 10466, + 10455, + 0, + 10385, + 10390, + 10472, + 10466, + 0, + 10390, + 10396, + 10477, + 10472, + 0, + 10396, + 10402, + 10484, + 10477, + 0, + 10402, + 10404, + 10486, + 10484, + 0, + 10404, + 10406, + 10488, + 10486, + 0, + 10406, + 10408, + 10490, + 10488, + 0, + 10408, + 10410, + 10492, + 10490, + 0, + 10410, + 10412, + 10494, + 10492, + 0, + 10412, + 10414, + 10496, + 10494, + 0, + 10414, + 10413, + 10495, + 10496, + 0, + 10413, + 10411, + 10493, + 10495, + 0, + 10411, + 10409, + 10491, + 10493, + 0, + 10409, + 10407, + 10489, + 10491, + 0, + 10407, + 10405, + 10487, + 10489, + 0, + 10405, + 10403, + 10485, + 10487, + 0, + 10403, + 10397, + 10479, + 10485, + 0, + 10397, + 10391, + 10473, + 10479, + 0, + 10391, + 10384, + 10468, + 10473, + 0, + 10384, + 10381, + 10463, + 10468, + 0, + 10381, + 10377, + 10459, + 10463, + 0, + 10377, + 10374, + 10456, + 10459, + 0, + 10374, + 10375, + 10457, + 10456, + 0, + 10375, + 10378, + 10460, + 10457, + 0, + 10378, + 10379, + 10462, + 10460, + 0, + 10379, + 10383, + 10465, + 10462, + 0, + 10383, + 10387, + 10469, + 10465, + 0, + 10387, + 10389, + 10471, + 10469, + 0, + 10389, + 10393, + 10475, + 10471, + 0, + 10393, + 10395, + 10478, + 10475, + 0, + 10395, + 10399, + 10481, + 10478, + 0, + 10399, + 10400, + 10482, + 10481, + 0, + 10400, + 10401, + 10483, + 10482, + 0, + 10401, + 10398, + 10480, + 10483, + 0, + 10398, + 10394, + 10476, + 10480, + 0, + 10394, + 10392, + 10474, + 10476, + 0, + 10392, + 10388, + 10470, + 10474, + 0, + 10388, + 10386, + 10467, + 10470, + 0, + 10386, + 10382, + 10464, + 10467, + 0, + 10382, + 10380, + 10461, + 10464, + 0, + 10380, + 10376, + 10458, + 10461, + 0, + 10376, + 10371, + 10453, + 10458, + 0, + 10371, + 10370, + 10452, + 10453, + 0, + 10370, + 10367, + 10449, + 10452, + 0, + 10367, + 10365, + 10447, + 10449, + 0, + 10365, + 10363, + 10445, + 10447, + 0, + 10363, + 10361, + 10443, + 10445, + 0, + 10361, + 10359, + 10441, + 10443, + 0, + 10359, + 10357, + 10439, + 10441, + 0, + 10357, + 10355, + 10437, + 10439, + 0, + 10355, + 10353, + 10435, + 10437, + 0, + 10353, + 10351, + 10433, + 10435, + 0, + 10351, + 10349, + 10431, + 10433, + 0, + 10349, + 10347, + 10429, + 10431, + 0, + 10347, + 10345, + 10427, + 10429, + 0, + 10345, + 10343, + 10425, + 10427, + 0, + 10343, + 10341, + 10423, + 10425, + 0, + 10341, + 10339, + 10421, + 10423, + 0, + 10339, + 10338, + 10420, + 10421, + 0, + 10338, + 10335, + 10417, + 10420, + 0, + 10335, + 10334, + 10416, + 10417, + 0, + 10416, + 10415, + 10497, + 10498, + 0, + 10415, + 10418, + 10500, + 10497, + 0, + 10418, + 10419, + 10501, + 10500, + 0, + 10419, + 10422, + 10504, + 10501, + 0, + 10422, + 10424, + 10506, + 10504, + 0, + 10424, + 10426, + 10508, + 10506, + 0, + 10426, + 10428, + 10510, + 10508, + 0, + 10428, + 10430, + 10512, + 10510, + 0, + 10430, + 10432, + 10514, + 10512, + 0, + 10432, + 10434, + 10516, + 10514, + 0, + 10434, + 10436, + 10518, + 10516, + 0, + 10436, + 10438, + 10520, + 10518, + 0, + 10438, + 10440, + 10522, + 10520, + 0, + 10440, + 10442, + 10524, + 10522, + 0, + 10442, + 10444, + 10526, + 10524, + 0, + 10444, + 10446, + 10528, + 10526, + 0, + 10446, + 10448, + 10530, + 10528, + 0, + 10448, + 10450, + 10531, + 10530, + 0, + 10450, + 10451, + 10533, + 10531, + 0, + 10451, + 10454, + 10536, + 10533, + 0, + 10454, + 10455, + 10537, + 10536, + 0, + 10455, + 10466, + 10548, + 10537, + 0, + 10466, + 10472, + 10553, + 10548, + 0, + 10472, + 10477, + 10558, + 10553, + 0, + 10477, + 10484, + 10566, + 10558, + 0, + 10484, + 10486, + 10568, + 10566, + 0, + 10486, + 10488, + 10570, + 10568, + 0, + 10488, + 10490, + 10572, + 10570, + 0, + 10490, + 10492, + 10574, + 10572, + 0, + 10492, + 10494, + 10576, + 10574, + 0, + 10494, + 10496, + 10578, + 10576, + 0, + 10496, + 10495, + 10577, + 10578, + 0, + 10495, + 10493, + 10575, + 10577, + 0, + 10493, + 10491, + 10573, + 10575, + 0, + 10491, + 10489, + 10571, + 10573, + 0, + 10489, + 10487, + 10569, + 10571, + 0, + 10487, + 10485, + 10567, + 10569, + 0, + 10485, + 10479, + 10562, + 10567, + 0, + 10479, + 10473, + 10555, + 10562, + 0, + 10473, + 10468, + 10550, + 10555, + 0, + 10468, + 10463, + 10546, + 10550, + 0, + 10463, + 10459, + 10541, + 10546, + 0, + 10459, + 10456, + 10538, + 10541, + 0, + 10456, + 10457, + 10539, + 10538, + 0, + 10457, + 10460, + 10542, + 10539, + 0, + 10460, + 10462, + 10544, + 10542, + 0, + 10462, + 10465, + 10547, + 10544, + 0, + 10465, + 10469, + 10551, + 10547, + 0, + 10469, + 10471, + 10554, + 10551, + 0, + 10471, + 10475, + 10557, + 10554, + 0, + 10475, + 10478, + 10560, + 10557, + 0, + 10478, + 10481, + 10563, + 10560, + 0, + 10481, + 10482, + 10565, + 10563, + 0, + 10482, + 10483, + 10564, + 10565, + 0, + 10483, + 10480, + 10561, + 10564, + 0, + 10480, + 10476, + 10559, + 10561, + 0, + 10476, + 10474, + 10556, + 10559, + 0, + 10474, + 10470, + 10552, + 10556, + 0, + 10470, + 10467, + 10549, + 10552, + 0, + 10467, + 10464, + 10545, + 10549, + 0, + 10464, + 10461, + 10543, + 10545, + 0, + 10461, + 10458, + 10540, + 10543, + 0, + 10458, + 10453, + 10535, + 10540, + 0, + 10453, + 10452, + 10534, + 10535, + 0, + 10452, + 10449, + 10532, + 10534, + 0, + 10449, + 10447, + 10529, + 10532, + 0, + 10447, + 10445, + 10527, + 10529, + 0, + 10445, + 10443, + 10525, + 10527, + 0, + 10443, + 10441, + 10523, + 10525, + 0, + 10441, + 10439, + 10521, + 10523, + 0, + 10439, + 10437, + 10519, + 10521, + 0, + 10437, + 10435, + 10517, + 10519, + 0, + 10435, + 10433, + 10515, + 10517, + 0, + 10433, + 10431, + 10513, + 10515, + 0, + 10431, + 10429, + 10511, + 10513, + 0, + 10429, + 10427, + 10509, + 10511, + 0, + 10427, + 10425, + 10507, + 10509, + 0, + 10425, + 10423, + 10505, + 10507, + 0, + 10423, + 10421, + 10503, + 10505, + 0, + 10421, + 10420, + 10502, + 10503, + 0, + 10420, + 10417, + 10499, + 10502, + 0, + 10417, + 10416, + 10498, + 10499, + 0, + 3323, + 3325, + 3327, + 3329, + 3333, + 3337, + 3339, + 3343, + 3345, + 3348, + 3349, + 3347, + 3344, + 3342, + 3338, + 3335, + 3332, + 3328, + 3326, + 3322, + 3318, + 3317, + 3315, + 3312, + 3310, + 3308, + 3306, + 3304, + 3302, + 3300, + 3298, + 3296, + 3294, + 3291, + 3289, + 3288, + 3286, + 3283, + 3282, + 3281, + 3284, + 3285, + 3287, + 3290, + 3292, + 3293, + 3295, + 3297, + 3299, + 3301, + 3303, + 3305, + 3307, + 3309, + 3311, + 3313, + 3314, + 3316, + 3319, + 3320, + 3331, + 3336, + 3341, + 3346, + 3351, + 3353, + 3355, + 3357, + 3359, + 3361, + 3362, + 3360, + 3358, + 3356, + 3354, + 3352, + 3350, + 3340, + 3334, + 3330, + 3324, + 3321, + 0, + 10498, + 10497, + 10500, + 10501, + 10504, + 10506, + 10508, + 10510, + 10512, + 10514, + 10516, + 10518, + 10520, + 10522, + 10524, + 10526, + 10528, + 10530, + 10531, + 10533, + 10536, + 10537, + 10548, + 10553, + 10558, + 10566, + 10568, + 10570, + 10572, + 10574, + 10576, + 10578, + 10577, + 10575, + 10573, + 10571, + 10569, + 10567, + 10562, + 10555, + 10550, + 10546, + 10541, + 10538, + 10539, + 10542, + 10544, + 10547, + 10551, + 10554, + 10557, + 10560, + 10563, + 10565, + 10564, + 10561, + 10559, + 10556, + 10552, + 10549, + 10545, + 10543, + 10540, + 10535, + 10534, + 10532, + 10529, + 10527, + 10525, + 10523, + 10521, + 10519, + 10517, + 10515, + 10513, + 10511, + 10509, + 10507, + 10505, + 10503, + 10502, + 10499, + 0 + ] + } +} diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureArrayLengthChange.json b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureArrayLengthChange.json index 51abb371113b..52816f9e8179 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureArrayLengthChange.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureArrayLengthChange.json @@ -1,43 +1,25 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0,1.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6666666666666643,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "boundaryType":0 - } - }] - } -} \ No newline at end of file +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0, 1.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6666666666666643, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } +} diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureExtraProperty.json b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureExtraProperty.json index d81bad5561dc..a5448a65de30 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureExtraProperty.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureExtraProperty.json @@ -1,44 +1,26 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6666666666666643,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "extraProperty": 1, - "boundaryType":0 - } - }] - } +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6666666666666643, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "extraProperty": 1, + "boundaryType": 0 + } + } + ] + } } diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureMissingProperty.json b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureMissingProperty.json index e4f777523a33..6d4b32a52583 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureMissingProperty.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructureMissingProperty.json @@ -1,37 +1,24 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }], - "boundaryType":0 - } - }] - } -} \ No newline at end of file +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } +} diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructurePropertyNameChange.json b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructurePropertyNameChange.json index 4cd141acdd47..3f2d178f2c71 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/differentStructurePropertyNameChange.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/differentStructurePropertyNameChange.json @@ -1,43 +1,25 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Pint":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6666666666666643,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "boundaryType":0 - } - }] - } -} \ No newline at end of file +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Pint": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6666666666666643, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } +} diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/original.json b/core/geometry/src/test/data/deepComparisonTestFiles/original.json index 0c857b65d0c5..a7adc5bab859 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/original.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/original.json @@ -1,43 +1,25 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6666666666666643,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "boundaryType":0 - } - }] - } +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6666666666666643, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } } diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureAndValues.json b/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureAndValues.json index 86489a9adfdf..a7adc5bab859 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureAndValues.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureAndValues.json @@ -1,43 +1,25 @@ - -{"Group": - {"Member":[ -{"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6666666666666643,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "boundaryType":0 - } - }] - } +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6666666666666643, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } } diff --git a/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureDifferentValues.json b/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureDifferentValues.json index 1611ecd975bc..6e34203be39b 100644 --- a/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureDifferentValues.json +++ b/core/geometry/src/test/data/deepComparisonTestFiles/sameStructureDifferentValues.json @@ -1,43 +1,25 @@ - -{"Group": - {"Member":[ - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[0.0,0.0,0.0], - [0.0,10.0,0.0], - [10.0,10.0,0.0]] - } - }], - "boundaryType":1 - } - }, - {"DgnCurveVector": - {"Member":[ - {"LineString": - {"Point":[[45.0,5.0,0.0], - [46.0,10.0,0.0]] - } - }, - {"LineString": - {"Point":[[46.0,10.0,0.0], - [48.0,20.0,0.0], - [42.0,10.000000000000002,0.0]] - } - }, - {"LineString": - {"Point":[[42.0,10.000000000000002,0.0], - [40.0,6.6666666666666643,0.0]] - } - }, - {"LineString": - {"Point":[[40.0,6.6664666666666633,0.0], - [39.0,5.0,0.0], - [30.0,5.0,0.0]] - } - }], - "boundaryType":0 - } - }] - } +{ + "Group": { + "Member": [ + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[0.0, 0.0, 0.0], [0.0, 10.0, 0.0], [10.0, 10.0, 0.0]] } } + ], + "boundaryType": 1 + } + }, + { + "DgnCurveVector": { + "Member": [ + { "LineString": { "Point": [[45.0, 5.0, 0.0], [46.0, 10.0, 0.0]] } }, + { "LineString": { "Point": [[46.0, 10.0, 0.0], [48.0, 20.0, 0.0], [42.0, 10.000000000000002, 0.0]] } }, + { "LineString": { "Point": [[42.0, 10.000000000000002, 0.0], [40.0, 6.6666666666666643, 0.0]] } }, + { "LineString": { "Point": [[40.0, 6.6664666666666633, 0.0], [39.0, 5.0, 0.0], [30.0, 5.0, 0.0]] } } + ], + "boundaryType": 0 + } + } + ] + } } diff --git a/core/geometry/src/test/data/synchro/082020B/insertedMesh.json b/core/geometry/src/test/data/synchro/082020B/insertedMesh.json index c653566110ea..280f5990114d 100644 --- a/core/geometry/src/test/data/synchro/082020B/insertedMesh.json +++ b/core/geometry/src/test/data/synchro/082020B/insertedMesh.json @@ -1,4 +1,5 @@ -{ "normal": [ +{ + "normal": [ [ 0, 0, @@ -882,4 +883,4 @@ 48, 0 ] -} \ No newline at end of file +} diff --git a/core/geometry/src/test/data/synchro/082020B/polyface.json b/core/geometry/src/test/data/synchro/082020B/polyface.json index fb4231595158..42d312e96616 100644 --- a/core/geometry/src/test/data/synchro/082020B/polyface.json +++ b/core/geometry/src/test/data/synchro/082020B/polyface.json @@ -1,4 +1,5 @@ -{ "geometryCategory": "polyface", +{ + "geometryCategory": "polyface", "data": { "point": { "_data": { @@ -961,4 +962,4 @@ 96 ], "_facetToFaceData": [] -} \ No newline at end of file +} diff --git a/core/geometry/src/test/data/synchro/082020B/synchromesh.json b/core/geometry/src/test/data/synchro/082020B/synchromesh.json index 744bc27ba718..ad3f76e62c19 100644 --- a/core/geometry/src/test/data/synchro/082020B/synchromesh.json +++ b/core/geometry/src/test/data/synchro/082020B/synchromesh.json @@ -1,4 +1,5 @@ -{ "synchroID": { +{ + "synchroID": { "byte0": 32, "byte1": -11, "byte2": 58, @@ -793,4 +794,4 @@ "y": 0 } ] -} \ No newline at end of file +} diff --git a/core/geometry/src/test/docSnippets/snippet.test.ts b/core/geometry/src/test/docSnippets/snippet.test.ts index 25a9133744cd..3ee3203c3695 100644 --- a/core/geometry/src/test/docSnippets/snippet.test.ts +++ b/core/geometry/src/test/docSnippets/snippet.test.ts @@ -131,8 +131,7 @@ describe("Snippets", () => { const pointB = myRay.fractionToPoint(fractionA); emit(" The ray point at fractionA is ", fractionA); const vectorBtoA = Vector3d.createStartEnd(pointB, pointA); - emit(" Since it is the closest ray point to pointA, ray.direction and vectorBtoA are perpendicular", - vectorBtoA.angleTo(myRay.direction).degrees); + emit(" Since it is the closest ray point to pointA, ray.direction and vectorBtoA are perpendicular", vectorBtoA.angleTo(myRay.direction).degrees); emit(" and the distance from pointA to the ray is ", pointA.distance(pointB)); }); @@ -160,11 +159,19 @@ describe("Snippets", () => { if (fractionOnRayForIntersection === undefined) { emit(" oops -- myRay is parallel to myPlane"); } else { - emit(" The intersection of ", myRay, " with ", myPlane, " is point ", intersectionPoint, " which is at fraction ", - fractionOnRayForIntersection, "along the ray"); + emit( + " The intersection of ", + myRay, + " with ", + myPlane, + " is point ", + intersectionPoint, + " which is at fraction ", + fractionOnRayForIntersection, + "along the ray", + ); emit("The altitude of the intersection point from the plane is 0: ", myPlane.altitude(intersectionPoint)); - emit(" And the intersection point matches the ray at that fraction ", - myRay.fractionToPoint(fractionOnRayForIntersection)); + emit(" And the intersection point matches the ray at that fraction ", myRay.fractionToPoint(fractionOnRayForIntersection)); } const inPlaneVector = myRay.direction.crossProduct(myPlane.getNormalRef()); @@ -173,5 +180,4 @@ describe("Snippets", () => { const fractionOnParallelRay = parallelRay.intersectionWithPlane(myPlane); emit(" so the fractionOnParallelRay is undefined", fractionOnParallelRay); }); - }); diff --git a/core/geometry/src/test/geometry3d/Angle.test.ts b/core/geometry/src/test/geometry3d/Angle.test.ts index 8b7890a48501..bc8c03fa1d24 100644 --- a/core/geometry/src/test/geometry3d/Angle.test.ts +++ b/core/geometry/src/test/geometry3d/Angle.test.ts @@ -18,12 +18,12 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; /* cspell:word isnan */ class AngleTests { - constructor(public noisy: boolean = false) { } + constructor(public noisy: boolean = false) {} public testAlmostEqual(ck: Checker) { const a = 0.5 * Geometry.smallAngleRadians; const b = 8.0 * Geometry.smallAngleRadians; - const c = 1.0; // radians, a nonzero angle + const c = 1.0; // radians, a nonzero angle const degreeCandidates = [0, 2, 56, 89, 90, 180]; const periodCandidates = [0, 1, -1, 4, -6]; let shiftPeriod = 0; @@ -66,9 +66,12 @@ class AngleTests { const theta2 = Angle.createDegreesAdjustSigned180(degrees); if (this.noisy) GeometryCoreTestIO.consoleLog( - "adjust angle:", theta0.degrees, - " positive:", theta1.degrees, - " signed:", theta2.degrees, + "adjust angle:", + theta0.degrees, + " positive:", + theta1.degrees, + " signed:", + theta2.degrees, ); ck.testBoolean(true, theta0.isAlmostEqualAllowPeriodShift(theta1), "adjust positive"); ck.testBoolean(true, theta0.isAlmostEqualAllowPeriodShift(theta2), "adjust signed"); @@ -263,15 +266,27 @@ describe("MiscAngles", () => { const radians = Angle.degreesToRadians(degrees); const radiansPositive = radians > 0 ? radians : Angle.adjustRadians0To2Pi(radians); const alphaTrue = Angle.orientedRadiansBetweenVectorsXYZ( - vectorU.x, vectorU.y, vectorU.z, - vectorV.x, vectorV.y, vectorV.z, - vectorW.x, vectorW.y, vectorW.z, + vectorU.x, + vectorU.y, + vectorU.z, + vectorV.x, + vectorV.y, + vectorV.z, + vectorW.x, + vectorW.y, + vectorW.z, true, ); const alphaFalse = Angle.orientedRadiansBetweenVectorsXYZ( - vectorU.x, vectorU.y, vectorU.z, - vectorV.x, vectorV.y, vectorV.z, - vectorW.x, vectorW.y, vectorW.z, + vectorU.x, + vectorU.y, + vectorU.z, + vectorV.x, + vectorV.y, + vectorV.z, + vectorW.x, + vectorW.y, + vectorW.z, false, ); ck.testCoordinate(alphaTrue, radiansPositive, { degrees, adjust: true }); @@ -548,14 +563,22 @@ describe("MiscAngles", () => { f0 %= period; const a = Angle.createRadians(r); const fPos = sweep.angleToSignedFraction(a, false, emptySweepResult); - ck.testFraction(fPos, sweep.angleToPositivePeriodicFraction(a, emptySweepResult), "!exteriorAngleToNegativeFraction reproduces angleToPositivePeriodicFraction"); + ck.testFraction( + fPos, + sweep.angleToPositivePeriodicFraction(a, emptySweepResult), + "!exteriorAngleToNegativeFraction reproduces angleToPositivePeriodicFraction", + ); const oldCode = oldAngleToSignedPeriodicFraction(sweep, a, emptySweepResult); const newCode = sweep.angleToSignedPeriodicFraction(a, emptySweepResult); ck.testCoordinate(oldCode, newCode, "old and new code for signed periodic sweep fraction is equivalent"); const fNeg = sweep.angleToSignedFraction(a, true, emptySweepResult); if (sweep.isAngleInSweep(a)) { ck.testFraction(fPos, fNeg, "interior angle unchanged by exteriorAngleToNegativeFraction value"); - ck.testFraction(fPos, sweep.fractionToSignedPeriodicFraction(fPos, true), "interior fraction unchanged by fractionToSignedPeriodicFraction"); + ck.testFraction( + fPos, + sweep.fractionToSignedPeriodicFraction(fPos, true), + "interior fraction unchanged by fractionToSignedPeriodicFraction", + ); } else { // exterior angle ck.testFraction(fPos - fNeg, period, Geometry.smallFraction, "sum of pos + neg exterior fractions equals period"); // extremely tiny non-empty intervals suffer from subtractive cancellation. Be generous: tol = 1.0e-5 fails. @@ -747,7 +770,7 @@ describe("Angle.cloneComplement", () => { const startAngle: number = Math.PI / 6; const endAngle: number = Math.PI / 3; const startAngleComplement: number = Math.PI / 6; - const endAngleComplement: number = - 2 * Math.PI + Math.PI / 3; + const endAngleComplement: number = -2 * Math.PI + Math.PI / 3; const angleSweep: AngleSweep = AngleSweep.createStartEndRadians(startAngle, endAngle); const output: AngleSweep = angleSweep.cloneComplement(true); assert.isOk(Angle.isAlmostEqualRadiansNoPeriodShift(output.startAngle.radians, startAngleComplement)); @@ -970,7 +993,7 @@ describe("Angle.dotProductsToHalfAngleTrigValues", () => { const uSeg0 = LineSegment3d.create(arc0.center, arc0.center.plus(arc0.vector0)); const vSeg0 = LineSegment3d.create(arc0.center, arc0.center.plus(arc0.vector90)); const arc0full = arc0.clone(); - arc0full.sweep = AngleSweep.create360(arc0full.sweep.startRadians); // the full ellipse created by c, u, and v + arc0full.sweep = AngleSweep.create360(arc0full.sweep.startRadians); // the full ellipse created by c, u, and v const dotUU = U.dotProduct(U); const dotVV = V.dotProduct(V); const dotUV = U.dotProduct(V); @@ -981,7 +1004,12 @@ describe("Angle.dotProductsToHalfAngleTrigValues", () => { // arc1 is the squared arc (created by 2 perpendicular vector basis). arc1 is same as arc0 but arc1 is // created by the 2 semi-axis (2 perpendicular vector basis) while arc0 is created by 2 random vector basis. // note that toScaledMatrix3d returns unit axis so we have to apply scale (r0 and r90) - const arc1 = Arc3d.create(arc1json.center, arc1json.axes.columnX().scale(arc1json.r0), arc1json.axes.columnY().scale(arc1json.r90), arc1json.sweep); + const arc1 = Arc3d.create( + arc1json.center, + arc1json.axes.columnX().scale(arc1json.r0), + arc1json.axes.columnY().scale(arc1json.r90), + arc1json.sweep, + ); // uSeg0 and vSeg0 are the 2 ellipse semi-axis. note that uSeg1 is same as perpSeg const uSeg1 = LineSegment3d.create(arc1.center, arc1.center.plus(arc1.vector0)); const vSeg1 = LineSegment3d.create(arc1.center, arc1.center.plus(arc1.vector90)); diff --git a/core/geometry/src/test/geometry3d/BarycentricTriangle.test.ts b/core/geometry/src/test/geometry3d/BarycentricTriangle.test.ts index cbaa4df46029..d1baedc36a22 100644 --- a/core/geometry/src/test/geometry3d/BarycentricTriangle.test.ts +++ b/core/geometry/src/test/geometry3d/BarycentricTriangle.test.ts @@ -43,8 +43,7 @@ function verifyTriangle(ck: Checker, triangle: BarycentricTriangle) { const cloneC = cloneB.clone(); const transform = Transform.createFixedPointAndMatrix( Point3d.create(-1, 0.4, 0.2), - Matrix3d.createRotationAroundVector(Vector3d.create(0.2, 3.1, -0.3), - Angle.createDegrees(22))!, + Matrix3d.createRotationAroundVector(Vector3d.create(0.2, 3.1, -0.3), Angle.createDegrees(22))!, ); transform.multiplyPoint3dArray(cloneB.points, cloneB.points); @@ -61,9 +60,17 @@ function verifyTriangle(ck: Checker, triangle: BarycentricTriangle) { const y0 = 1; const z = 2.0; const cloneC1 = BarycentricTriangle.createXYZXYZXYZ( - x0, y0, z, - x0 + 2 * a, y0, z, - x0 + a, y0 + a, z, cloneC); + x0, + y0, + z, + x0 + 2 * a, + y0, + z, + x0 + a, + y0 + a, + z, + cloneC, + ); ck.testCoordinate(a * a, cloneC1.area); ck.testTrue(cloneC === cloneC1, "create into result"); // clone with reversed @@ -71,7 +78,6 @@ function verifyTriangle(ck: Checker, triangle: BarycentricTriangle) { const dotSelf = cloneC1Reverse.dotProductOfCrossProductsFromOrigin(cloneC1Reverse); const dotReverse = cloneC1.dotProductOfCrossProductsFromOrigin(cloneC1Reverse); ck.testCoordinate(dotSelf, -dotReverse, "reversed triangle dots."); - } describe("BarycentricTriangle", () => { @@ -96,7 +102,8 @@ describe("BarycentricTriangle", () => { ck.testTrue(PolygonOps.isConvex([...vertices, vertices[0]]), "triangle with closure point returns true for isConvex"); ck.testFalse(PolygonOps.isConvex([vertices[0], vertices[1]]), "isConvex returns false for degenerate triangle"); ck.testFalse( - PolygonOps.isConvex([vertices[0], vertices[1], vertices[1]]), "isConvex returns false for degenerate triangle", + PolygonOps.isConvex([vertices[0], vertices[1], vertices[1]]), + "isConvex returns false for degenerate triangle", ); ck.testFalse(PolygonOps.isConvex([...vertices, incenter]), "isConvex returns false on chevron"); ck.testCoordinate(Math.sqrt(13) + Math.sqrt(40) + 9, triangle.perimeter, "perimeter as expected"); @@ -106,7 +113,8 @@ describe("BarycentricTriangle", () => { // intersectSegment coverage const centroid = triangle.centroid(); const loc1 = triangle.intersectSegment( - Point3d.create(centroid.x, centroid.y, -10), Point3d.create(centroid.x, centroid.y, 10), + Point3d.create(centroid.x, centroid.y, -10), + Point3d.create(centroid.x, centroid.y, 10), ); ck.testTrue(loc1.isValid, "found intersection of segment"); ck.testPoint3d(centroid, loc1.world, "expected world coords of intersection"); @@ -123,7 +131,9 @@ describe("BarycentricTriangle", () => { // degenerate input coverage ck.testFalse( BarycentricTriangle.create( - vertices[0], vertices[1], vertices[1], + vertices[0], + vertices[1], + vertices[1], ).pointToFraction(incenter).isValid, "invert pt on degenerate triangle", ); @@ -131,10 +141,10 @@ describe("BarycentricTriangle", () => { let loc0 = PolygonOps.closestPointOnBoundary([vertices[0]], incenter); ck.testTrue( loc0.isValid && - loc0.point.isAlmostEqualMetric(vertices[0]) && - loc0.code === PolygonLocation.OnPolygonVertex && - loc0.closestEdgeIndex === 0 && - loc0.closestEdgeParam === 0.0, + loc0.point.isAlmostEqualMetric(vertices[0]) && + loc0.code === PolygonLocation.OnPolygonVertex && + loc0.closestEdgeIndex === 0 && + loc0.closestEdgeParam === 0.0, "1-pt 'polygon' closest point is valid", ); ck.testTrue( @@ -154,9 +164,10 @@ describe("BarycentricTriangle", () => { for (const specialPt of barycentricInsideOn) { ck.testBoolean(specialPt[0].isInsideOrOn, specialPt[1], "special point containment"); ck.testExactNumber( - specialPt[0].classify, specialPt[1] ? - PolygonLocation.InsidePolygonProjectsToEdgeInterior : - PolygonLocation.OutsidePolygonProjectsToEdgeInterior, + specialPt[0].classify, + specialPt[1] ? + PolygonLocation.InsidePolygonProjectsToEdgeInterior : + PolygonLocation.OutsidePolygonProjectsToEdgeInterior, "special point classification", ); ck.testPoint3d( @@ -184,28 +195,47 @@ describe("BarycentricTriangle", () => { if ( ck.testPoint3d(xyz, loc.world, "circle pt is in plane") && ck.testPoint3d( - xyz, triangle.fractionToPoint(loc.local.x, loc.local.y, loc.local.z), "recover circle pt from barycentric", + xyz, + triangle.fractionToPoint(loc.local.x, loc.local.y, loc.local.z), + "recover circle pt from barycentric", ) ) circlePoints.push(loc.local); } // test closest point to triangle from some barycentric locations - for (const b of [ - Point3d.create(0.2, 0.5, 0.3), Point3d.create(0.5, 0.1, 0.4), // inside triangle - Point3d.create(1, 0, 0), Point3d.create(0, 1, 0), Point3d.create(0, 0, 1), // at vertices - Point3d.create(0, 0.4, 0.6), Point3d.create(0.2, 0, 0.8), Point3d.create(0.3, 0.7, 0), // inside edges - Point3d.create(0, -4, 5), Point3d.create(0, -0.5, 1.5), Point3d.create(0, 1.5, -0.5), Point3d.create(0, 5, -4), // on extended edge 0 - Point3d.create(-4, 0, 5), Point3d.create(-0.5, 0, 1.5), Point3d.create(1.5, 0, -0.5), Point3d.create(5, 0, -4), // on extended edge 1 - Point3d.create(-4, 5, 0), Point3d.create(-0.5, 1.5, 0), Point3d.create(1.5, -0.5, 0), Point3d.create(5, -4, 0), // on extended edge 2 - ...specialPoints, - ...circlePoints, - ]) { + for ( + const b of [ + Point3d.create(0.2, 0.5, 0.3), + Point3d.create(0.5, 0.1, 0.4), // inside triangle + Point3d.create(1, 0, 0), + Point3d.create(0, 1, 0), + Point3d.create(0, 0, 1), // at vertices + Point3d.create(0, 0.4, 0.6), + Point3d.create(0.2, 0, 0.8), + Point3d.create(0.3, 0.7, 0), // inside edges + Point3d.create(0, -4, 5), + Point3d.create(0, -0.5, 1.5), + Point3d.create(0, 1.5, -0.5), + Point3d.create(0, 5, -4), // on extended edge 0 + Point3d.create(-4, 0, 5), + Point3d.create(-0.5, 0, 1.5), + Point3d.create(1.5, 0, -0.5), + Point3d.create(5, 0, -4), // on extended edge 1 + Point3d.create(-4, 5, 0), + Point3d.create(-0.5, 1.5, 0), + Point3d.create(1.5, -0.5, 0), + Point3d.create(5, -4, 0), // on extended edge 2 + ...specialPoints, + ...circlePoints, + ] + ) { const pt = triangle.fractionToPoint(b.x, b.y, b.z); const data = triangle.closestPoint(b.x, b.y, b.z); ck.testTrue(data.closestEdgeIndex >= 0, "found projection"); const proj = vertices[data.closestEdgeIndex].interpolate( - data.closestEdgeParam, vertices[Geometry.cyclic3dAxis(data.closestEdgeIndex + 1)], + data.closestEdgeParam, + vertices[Geometry.cyclic3dAxis(data.closestEdgeIndex + 1)], ); GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(pt, proj)); // verify that the projection of a point already on a bounded edge or @@ -220,7 +250,9 @@ describe("BarycentricTriangle", () => { ck.testExactNumber(0.0, data.closestEdgeParam, "vertex hit has expected edge param"); } else if (b.at(j) > 0.0 && b.at(j) < 1.0) { // inside edge ck.testExactNumber( - triangle.pointToFraction(pt).classify, PolygonLocation.OnPolygonEdgeInterior, "edge classify", + triangle.pointToFraction(pt).classify, + PolygonLocation.OnPolygonEdgeInterior, + "edge classify", ); ck.testExactNumber(j, data.closestEdgeIndex, "edge hit has expected edge index"); ck.testExactNumber(1 - b.at(j), data.closestEdgeParam, "edge hit has expected edge param"); @@ -236,7 +268,8 @@ describe("BarycentricTriangle", () => { // compare PolygonOps v. BarycentricTriangle barycentric coords const b2 = PolygonOps.convexBarycentricCoordinates(vertices, pt); ck.testBoolean( - undefined !== b2, BarycentricTriangle.isInsideOrOnTriangle(b.x, b.y, b.z), + undefined !== b2, + BarycentricTriangle.isInsideOrOnTriangle(b.x, b.y, b.z), "found convex barycentric coords iff point inside triangle", ); if (undefined !== b2) { @@ -244,7 +277,10 @@ describe("BarycentricTriangle", () => { ck.testCoordinate(b.y, b2[1], "convex barycentric x equals BarycentricTriangle x"); ck.testCoordinate(b.z, b2[2], "convex barycentric x equals BarycentricTriangle x"); ck.testCoordinateWithToleranceFactor( - 1.0, b.x + b.y + b.z, Geometry.smallFraction, "test barycentric coords sum to 1", + 1.0, + b.x + b.y + b.z, + Geometry.smallFraction, + "test barycentric coords sum to 1", ); } } @@ -290,7 +326,9 @@ describe("BarycentricTriangle.intersectRay3d", () => { expectedIntersectionPoint = Point3d.create(2, 0, 0); if (ck.testBoolean(intersectionPoint.isValid, true)) { ck.testPoint3d( - intersectionPoint.world, expectedIntersectionPoint, "ray intersects triangle at a triangle vertex", + intersectionPoint.world, + expectedIntersectionPoint, + "ray intersects triangle at a triangle vertex", ); } ray.cloneTransformed(rotationTransform, rotatedRay); @@ -312,7 +350,9 @@ describe("BarycentricTriangle.intersectRay3d", () => { expectedIntersectionPoint = Point3d.create(5, 0, 0); if (ck.testBoolean(intersectionPoint.isValid, true)) { ck.testPoint3d( - intersectionPoint.world, expectedIntersectionPoint, "ray intersects triangle on a triangle edge", + intersectionPoint.world, + expectedIntersectionPoint, + "ray intersects triangle on a triangle edge", ); } ray.cloneTransformed(rotationTransform, rotatedRay); diff --git a/core/geometry/src/test/geometry3d/BilinearPatch.test.ts b/core/geometry/src/test/geometry3d/BilinearPatch.test.ts index 39cea0ae1ded..89adbe101793 100644 --- a/core/geometry/src/test/geometry3d/BilinearPatch.test.ts +++ b/core/geometry/src/test/geometry3d/BilinearPatch.test.ts @@ -4,6 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; +import { GeometryQuery } from "../../curve/GeometryQuery"; +import { StrokeOptions } from "../../curve/StrokeOptions"; import { Geometry } from "../../Geometry"; import { Angle } from "../../geometry3d/Angle"; import { BilinearPatch } from "../../geometry3d/BilinearPatch"; @@ -13,14 +15,15 @@ import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { Ray3d } from "../../geometry3d/Ray3d"; import { Transform } from "../../geometry3d/Transform"; +import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { GeometryQuery } from "../../curve/GeometryQuery"; -import { StrokeOptions } from "../../curve/StrokeOptions"; -import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; function verifyPatch(ck: Checker, patch: BilinearPatch) { - const transform = Transform.createOriginAndMatrix(Point3d.create(10, 20, 10), Matrix3d.createRotationAroundVector(Vector3d.create(1, 4, 2), Angle.createDegrees(20))); + const transform = Transform.createOriginAndMatrix( + Point3d.create(10, 20, 10), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 4, 2), Angle.createDegrees(20)), + ); const patch1 = patch.cloneTransformed(transform)!; const range = Range3d.createNull(); patch.extendRange(range); @@ -80,10 +83,13 @@ describe("BilinearPatch", () => { it("IntersectRay", () => { const ck = new Checker(); - for (const patch of [ - BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0), - BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1), - BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1, 1)]) { + for ( + const patch of [ + BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0), + BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1), + BilinearPatch.createXYZ(0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 1, 1), + ] + ) { const uv = Point2d.create(0.2, 0.4); const tangentPlane = patch.uvFractionToPointAndTangents(uv.x, uv.y); const perp = tangentPlane.vectorU.crossProduct(tangentPlane.vectorV); @@ -94,14 +100,15 @@ describe("BilinearPatch", () => { if (intersections) { let numMatch = 0; for (const detail of intersections) { - ck.testPoint3d(ray.fractionToPoint(detail.curveDetail.fraction), - patch.uvFractionToPoint(detail.surfaceDetail.uv.x, detail.surfaceDetail.uv.y)); + ck.testPoint3d( + ray.fractionToPoint(detail.curveDetail.fraction), + patch.uvFractionToPoint(detail.surfaceDetail.uv.x, detail.surfaceDetail.uv.y), + ); if (Geometry.isSameCoordinate(expectedFraction, detail.curveDetail.fraction)) { numMatch++; } } if (!ck.testExactNumber(1, numMatch, "number of ray patch intersections", intersections)) { - GeometryCoreTestIO.consoleLog("\n PATCH", patch); GeometryCoreTestIO.consoleLog("RAY", ray); for (const detail of intersections) @@ -116,5 +123,4 @@ describe("BilinearPatch", () => { ck.checkpoint("BilinearPatch.IntersectRay"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/EllipsoidPatch.test.ts b/core/geometry/src/test/geometry3d/EllipsoidPatch.test.ts index 2b974bc23fcd..280f00c09496 100644 --- a/core/geometry/src/test/geometry3d/EllipsoidPatch.test.ts +++ b/core/geometry/src/test/geometry3d/EllipsoidPatch.test.ts @@ -48,16 +48,33 @@ describe("Ellipsoid", () => { const degreeStep = 22.5; const phiRadiansArray = [-pole, -0.4 * pole, 0.0, 0.2 * pole, pole]; // const phiRadiansArray = [-pole, pole]; - const thetaRadiansArray = [-halfCircle, -0.6 * halfCircle, -0.2 * halfCircle, 0.0, 0.45 * halfCircle, 0.9 * halfCircle, halfCircle, 1.3 * halfCircle, 2.8 * halfCircle]; + const thetaRadiansArray = [ + -halfCircle, + -0.6 * halfCircle, + -0.2 * halfCircle, + 0.0, + 0.45 * halfCircle, + 0.9 * halfCircle, + halfCircle, + 1.3 * halfCircle, + 2.8 * halfCircle, + ]; // const thetaRadiansArray = [-halfCircle, 0.0, halfCircle]; let x0 = 0; const xStep = 4.0 * maxRadius; - for (const ellipsoid of [ - // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), - Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), - Ellipsoid.createCenterMatrixRadii(center, - Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid - radiusX, radiusY, radiusZ)]) { + for ( + const ellipsoid of [ + // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), + Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), + Ellipsoid.createCenterMatrixRadii( + center, + Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid + radiusX, + radiusY, + radiusZ, + ), + ] + ) { let y0 = 0; const yStep = 4.0 * maxRadius; for (const theta0Radians of thetaRadiansArray) { @@ -70,13 +87,12 @@ describe("Ellipsoid", () => { const patch = EllipsoidPatch.createCapture( ellipsoid.clone(), AngleSweep.createStartEndRadians(theta0Radians, theta1Radians), - AngleSweep.createStartEndRadians(phi0Radians, phi1Radians)); + AngleSweep.createStartEndRadians(phi0Radians, phi1Radians), + ); const builder = PolyfaceBuilder.create(); const numU = Geometry.stepCount(degreeStep, patch.longitudeSweep.sweepDegrees, 1, 16); const numV = Geometry.stepCount(degreeStep, patch.latitudeSweep.sweepDegrees, 1, 16); - builder.addUVGridBody(patch, - numU, - numV); + builder.addUVGridBody(patch, numU, numV); const mesh = builder.claimPolyface(); const patchRange = patch.range(); const expandedPatchRange = patchRange.clone(); @@ -85,8 +101,18 @@ describe("Ellipsoid", () => { const pointRange = mesh.range(); const expandedPointRange = pointRange.clone(); expandedPointRange.expandInPlace(0.10 * maxRadius); - const ok1 = ck.testTrue(expandedPatchRange.containsRange(pointRange), "points in patch range", { theta0: theta0Radians, theta1: theta1Radians, phi0: phi0Radians, phi1: phi1Radians }); - const ok2 = ck.testTrue(expandedPointRange.containsRange(patchRange), "patch in expanded point range", { theta0: theta0Radians, theta1: theta1Radians, phi0: phi0Radians, phi1: phi1Radians }); + const ok1 = ck.testTrue(expandedPatchRange.containsRange(pointRange), "points in patch range", { + theta0: theta0Radians, + theta1: theta1Radians, + phi0: phi0Radians, + phi1: phi1Radians, + }); + const ok2 = ck.testTrue(expandedPointRange.containsRange(patchRange), "patch in expanded point range", { + theta0: theta0Radians, + theta1: theta1Radians, + phi0: phi0Radians, + phi1: phi1Radians, + }); if (!ok1 || !ok2) patch.range(); GeometryCoreTestIO.captureGeometry(allGeometry, mesh, x0, y0); @@ -97,7 +123,7 @@ describe("Ellipsoid", () => { } x0 += 2.0 * xStep; } - x0 += 10.0 * xStep; // extra gap per ellipsoid + x0 += 10.0 * xStep; // extra gap per ellipsoid } GeometryCoreTestIO.saveGeometry(allGeometry, "Ellipsoid", "PatchRange"); expect(ck.getNumErrors()).toBe(0); @@ -127,16 +153,32 @@ describe("Ellipsoid", () => { const distantRay = Ray3d.createXYZUVW(12, 0, 1, 0.1, 0.1, 5.0); const nullRay = Ray3d.createXYZUVW(1, 2, 3, 0, 0, 0); const transform2 = Transform.createRowValues( - 1.2, 0, 2, 3, - 0.2, 4, 2, 1, - -0.2, 3, 4, 2); - for (const ellipsoid of [ - // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), - Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), - Ellipsoid.createCenterMatrixRadii(center, - Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid - radiusX, radiusY, radiusZ)]) { - + 1.2, + 0, + 2, + 3, + 0.2, + 4, + 2, + 1, + -0.2, + 3, + 4, + 2, + ); + for ( + const ellipsoid of [ + // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), + Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), + Ellipsoid.createCenterMatrixRadii( + center, + Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid + radiusX, + radiusY, + radiusZ, + ), + ] + ) { // confirm no intersections for distant ray . . . ck.testExactNumber(0, ellipsoid.intersectRay(distantRay, undefined, undefined, undefined), "confirm zero-intersection case"); ck.testExactNumber(0, ellipsoid.intersectRay(nullRay, undefined, undefined, undefined)); @@ -168,13 +210,12 @@ describe("Ellipsoid", () => { const patch = EllipsoidPatch.createCapture( ellipsoid.clone(), AngleSweep.createStartEndRadians(theta0Radians, theta1Radians), - AngleSweep.createStartEndRadians(phi0Radians, phi1Radians)); + AngleSweep.createStartEndRadians(phi0Radians, phi1Radians), + ); const builder = PolyfaceBuilder.create(); const numU = Geometry.stepCount(degreeStep, patch.longitudeSweep.sweepDegrees, 1, 16); const numV = Geometry.stepCount(degreeStep, patch.latitudeSweep.sweepDegrees, 1, 16); - builder.addUVGridBody(patch, - numU, - numV); + builder.addUVGridBody(patch, numU, numV); const mesh = builder.claimPolyface(); const thetaA = Geometry.interpolate(theta0Radians, thetaFractionA, theta1Radians); @@ -185,8 +226,7 @@ describe("Ellipsoid", () => { const pointB = ellipsoid.radiansToPoint(thetaB, phiB); // Create the ray with start/end spread outside the sphere points ..... const rayAB = Ray3d.createStartEnd(pointA.interpolate(-1, pointB), pointA.interpolate(3, pointB)); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineString3d.create(rayAB.fractionToPoint(0.0), rayAB.fractionToPoint(1.0)), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(rayAB.fractionToPoint(0.0), rayAB.fractionToPoint(1.0)), x0, y0); const hits = patch.intersectRay(rayAB, true, true); ck.testExactNumber(2, hits.length, "Expect 2 intersections"); for (const hit of hits) { @@ -204,7 +244,7 @@ describe("Ellipsoid", () => { } x0 += 2.0 * xStep; } - x0 += 10.0 * xStep; // extra gap per ellipsoid + x0 += 10.0 * xStep; // extra gap per ellipsoid } GeometryCoreTestIO.saveGeometry(allGeometry, "Ellipsoid", "IntersectRay"); expect(ck.getNumErrors()).toBe(0); @@ -215,9 +255,17 @@ describe("Ellipsoid", () => { let x0 = 0; let y0 = 0; const center = Point3d.create(19476.688224632293, 9394.94304587366, -6369311.983587892); - const matrix = Matrix3d.createRowValues(2230956.046389774, 4218075.517914913, 4217984.8981983, - -5853439.760676313, 635312.655431714, 2444174.054179583, - 1200294.0430858273, -4741818.686714196, 4079572.590348847); + const matrix = Matrix3d.createRowValues( + 2230956.046389774, + 4218075.517914913, + 4217984.8981983, + -5853439.760676313, + 635312.655431714, + 2444174.054179583, + 1200294.0430858273, + -4741818.686714196, + 4079572.590348847, + ); const referenceSize = matrix.columnXMagnitude(); const markerSizeA = 0.1 * referenceSize; const markerSizeB = 0.2 * referenceSize; @@ -226,13 +274,25 @@ describe("Ellipsoid", () => { 7946521.137480825, 8906977.42125833, -677213.3181646094, ); */ - for (const ray of - [Ray3d.createXYZUVW(38729632.01074491, -5490050.664369064, 12881295.636822795, - 0.09684505394456912, 0.9848250824825425, 0.1440159450884755), - /* */ Ray3d.createXYZUVW(38729632.01074491, -5490050.664369064, 12881295.636822795, - 0.09684505394456912, 0.9848250824825425, 0.1440159450884755)]) { + for ( + const ray of [ + Ray3d.createXYZUVW(38729632.01074491, -5490050.664369064, 12881295.636822795, 0.09684505394456912, 0.9848250824825425, 0.1440159450884755), + /* */ Ray3d.createXYZUVW( + 38729632.01074491, + -5490050.664369064, + 12881295.636822795, + 0.09684505394456912, + 0.9848250824825425, + 0.1440159450884755, + ), + ] + ) { const builder = PolyfaceBuilder.create(); - const patch = EllipsoidPatch.createCapture(Ellipsoid.createCenterMatrixRadii(center, matrix, 1.0, 1.0, 1.0), AngleSweep.create360(), AngleSweep.createFullLatitude()); + const patch = EllipsoidPatch.createCapture( + Ellipsoid.createCenterMatrixRadii(center, matrix, 1.0, 1.0, 1.0), + AngleSweep.create360(), + AngleSweep.createFullLatitude(), + ); builder.addUVGridBody(patch, 32, 32); const mesh = builder.claimPolyface(); for (const rayScale of [1.0, Math.sqrt(referenceSize), referenceSize]) { @@ -242,8 +302,12 @@ describe("Ellipsoid", () => { const ray1 = Ray3d.create(ray.origin.interpolate(placementFraction, center), ray.direction); ray1.direction.scaleInPlace(rayScale); const displayScale = referenceSize / ray1.direction.magnitude(); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineSegment3d.create(ray1.fractionToPoint(-3.0 * displayScale), ray1.fractionToPoint(3.0 * displayScale)), x0, y0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(ray1.fractionToPoint(-3.0 * displayScale), ray1.fractionToPoint(3.0 * displayScale)), + x0, + y0, + ); const hits = patch.intersectRay(ray1, true, true); if (hits.length === 0) { GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, ray1.origin, markerSizeB, x0, y0); @@ -279,23 +343,26 @@ describe("Ellipsoid", () => { const y0 = 0; const thetaFractionB0 = 0.45; const phiFractionB0 = 0.55; - for (const ellipsoid of [ - // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), - // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), - Ellipsoid.createCenterMatrixRadii(center, - Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid - radiusX, radiusY, radiusZ)]) { + for ( + const ellipsoid of [ + // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusX, radiusX), + // Ellipsoid.createCenterMatrixRadii(center, Matrix3d.createIdentity(), radiusX, radiusY, radiusZ), + Ellipsoid.createCenterMatrixRadii( + center, + Matrix3d.createRowValues(1.0, 0.2, 0.3, -0.2, 1.0, 0.4, 0.1, -0.5, 1.2), // true skewed ellipsoid + radiusX, + radiusY, + radiusZ, + ), + ] + ) { // Create a fairly small patch so "outside fractions" do not wrap into the patch . .. - const patch = EllipsoidPatch.createCapture(ellipsoid, - AngleSweep.createStartEndDegrees(-20, 80), - AngleSweep.createStartEndDegrees(-10, 30)); + const patch = EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(-20, 80), AngleSweep.createStartEndDegrees(-10, 30)); const builder = PolyfaceBuilder.create(); const numU = Geometry.stepCount(degreeStep, patch.longitudeSweep.sweepDegrees, 1, 16); const numV = Geometry.stepCount(degreeStep, patch.latitudeSweep.sweepDegrees, 1, 16); - builder.addUVGridBody(patch, - numU, - numV); + builder.addUVGridBody(patch, numU, numV); const mesh = builder.claimPolyface(); GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, x0, y0); @@ -307,12 +374,11 @@ describe("Ellipsoid", () => { const phiFractionB = Geometry.interpolate(phiFractionB0, 0.2, phiFractionA); if (!Geometry.isIn01(thetaFractionB) || !Geometry.isIn01(phiFractionB)) continue; - const pointA = patch.uvFractionToPoint(thetaFractionA, phiFractionA); // OUTSIDE - const pointB = patch.uvFractionToPoint(thetaFractionB, phiFractionB); // INSIDE + const pointA = patch.uvFractionToPoint(thetaFractionA, phiFractionA); // OUTSIDE + const pointB = patch.uvFractionToPoint(thetaFractionB, phiFractionB); // INSIDE // Create the ray with start/end spread outside the sphere points ..... const rayAB = Ray3d.createStartEnd(pointA.interpolate(-0.01, pointB), pointA.interpolate(1.05, pointB)); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineString3d.create(rayAB.fractionToPoint(0.0), rayAB.fractionToPoint(1.0)), x0, y0); + GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(rayAB.fractionToPoint(0.0), rayAB.fractionToPoint(1.0)), x0, y0); const hits = patch.intersectRay(rayAB, true, true); ck.testExactNumber(1, hits.length, "Expect 1 intersections"); for (const hit of hits) { @@ -330,9 +396,19 @@ describe("Ellipsoid", () => { // flatten to the equator. // normal is bad at phi = 0 const flatten = Transform.createRowValues( - 1, 0, 0, 1, - 0, 1, 0, 2, - 0, 0, 0, 3); + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 2, + 0, + 0, + 0, + 3, + ); const ellipsoid = Ellipsoid.create(flatten); const patch = EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(0, 180), AngleSweep.createStartEndDegrees(0, 90)); ck.testUndefined(patch.anglesToUnitNormalRay(LongitudeLatitudeNumber.createDegrees(0, 0, 0))); @@ -368,11 +444,19 @@ describe("Ellipsoid", () => { const polarRadius = 1.0; const center = Point3d.create(1, 2, 3); // Ellipsoid something like the earth -- center at 0, polar declination 23.45, a little fatter at equator than poles. - const earthEllipsoid = Ellipsoid.createCenterMatrixRadii(center, + const earthEllipsoid = Ellipsoid.createCenterMatrixRadii( + center, Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7)), - equatorRadius, equatorRadius, polarRadius); + equatorRadius, + equatorRadius, + polarRadius, + ); // package the whole earth with a bit less than a full octant patch - const earthPatch = EllipsoidPatch.createCapture(earthEllipsoid, AngleSweep.createStartEndDegrees(-10, 70), AngleSweep.createStartEndDegrees(0, 80)); + const earthPatch = EllipsoidPatch.createCapture( + earthEllipsoid, + AngleSweep.createStartEndDegrees(-10, 70), + AngleSweep.createStartEndDegrees(0, 80), + ); // create a grid mesh const builder = PolyfaceBuilder.create(); builder.addUVGridBody(earthPatch, 10, 10); @@ -388,8 +472,7 @@ describe("Ellipsoid", () => { const hits = earthPatch.intersectRay(ray, true, false); GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(ray.fractionToPoint(0), ray.fractionToPoint(1.0))); for (const hit of hits) { - GeometryCoreTestIO.captureGeometry(allGeometry, - Sphere.createCenterRadius(hit.surfaceDetail.point, 0.03)); + GeometryCoreTestIO.captureGeometry(allGeometry, Sphere.createCenterRadius(hit.surfaceDetail.point, 0.03)); } GeometryCoreTestIO.saveGeometry(allGeometry, "Ellipsoid", "EarthLikeExample"); expect(ck.getNumErrors()).toBe(0); @@ -402,12 +485,9 @@ describe("Ellipsoid", () => { const center = Point3d.create(1, 2, 3); const degrees = [0, 10, 45, 80, -85, -60]; // use one set of angle samples -- double it for theta to go all the way around const unitSphere = Ellipsoid.create(); - for (const matrix of [Matrix3d.createIdentity(), - /* */ Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7))]) + for (const matrix of [Matrix3d.createIdentity(), /* */ Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7))]) for (const e of [1.0, 2.0, 0.5]) { - const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, - matrix, - e, e, 1); + const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, matrix, e, e, 1); for (const phiDegrees of degrees) { for (const thetaDegreesA of degrees) { const thetaDegrees = 2.0 * thetaDegreesA; @@ -441,12 +521,9 @@ describe("Ellipsoid", () => { const degrees = [0, 10, 45, 80, -85, -60]; // use one set of angle samples -- double it for theta to go all the way around const fractions = [-0.3, 0.2, 0.8, 1.1]; const frame0 = Transform.createIdentity(); - for (const matrix of [Matrix3d.createIdentity(), - /* */ Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7))]) + for (const matrix of [Matrix3d.createIdentity(), /* */ Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7))]) for (const e of [1.0, 2.0, 0.5]) { - const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, - matrix, - e, e * e, 1); + const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, matrix, e, e * e, 1); for (const phiDegrees of degrees) { for (const thetaDegreesA of degrees) { const thetaDegrees = 2.0 * thetaDegreesA; @@ -484,40 +561,55 @@ describe("Ellipsoid", () => { const center = Point3d.create(0, 0, 0); const fractions = [-0.1, 0, 0.5, 0.9, 1.0, 1.1]; for (const distanceFromSurface of [0.1, 0.2, -0.05]) { - for (const matrix of [ - Matrix3d.createIdentity(), - Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7))]) + for ( + const matrix of [ + Matrix3d.createIdentity(), + Matrix3d.createRotationAroundAxisIndex(0, Angle.createDegrees(23.7)), + ] + ) for (const e of [1.0, 2.0, 0.5]) { - const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, - matrix, - e, e, 1); + const ellipsoid = Ellipsoid.createCenterMatrixRadii(center, matrix, e, e, 1); x0 += 8.0; const builder = PolyfaceBuilder.create(); - const patch = EllipsoidPatch.createCapture(ellipsoid, - AngleSweep.createStartEndDegrees(0, 50), - AngleSweep.createStartEndDegrees(0, 90)); + const patch = EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(0, 50), AngleSweep.createStartEndDegrees(0, 90)); builder.addUVGridBody(patch, 5, 9); GeometryCoreTestIO.captureGeometry(allGeometry, builder.claimPolyface(), x0); - GeometryCoreTestIO.captureGeometry(allGeometry, + GeometryCoreTestIO.captureGeometry( + allGeometry, ellipsoid.constantLatitudeArc( patch.longitudeSweep, - patch.latitudeSweep.startAngle), - x0, y1); - GeometryCoreTestIO.captureGeometry(allGeometry, + patch.latitudeSweep.startAngle, + ), + x0, + y1, + ); + GeometryCoreTestIO.captureGeometry( + allGeometry, ellipsoid.constantLatitudeArc( patch.longitudeSweep, - patch.latitudeSweep.endAngle), - x0, y1); - GeometryCoreTestIO.captureGeometry(allGeometry, + patch.latitudeSweep.endAngle, + ), + x0, + y1, + ); + GeometryCoreTestIO.captureGeometry( + allGeometry, ellipsoid.constantLongitudeArc( patch.longitudeSweep.startAngle, - patch.latitudeSweep), - x0, y1); - GeometryCoreTestIO.captureGeometry(allGeometry, + patch.latitudeSweep, + ), + x0, + y1, + ); + GeometryCoreTestIO.captureGeometry( + allGeometry, ellipsoid.constantLongitudeArc( patch.longitudeSweep.endAngle, - patch.latitudeSweep), - x0, y1); + patch.latitudeSweep, + ), + x0, + y1, + ); // GeometryCoreTestIO.consoleLog({ eccentricity: e }); for (const thetaFraction of fractions) { for (const phiFraction of fractions) { @@ -530,10 +622,17 @@ describe("Ellipsoid", () => { GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(rayA.origin, planeB.origin), x0); const vectorAB = Vector3d.createStartEnd(planeB.origin, rayA.origin); if (!Geometry.isSameCoordinate(0, Math.abs(distanceFromSurface))) { - ck.testPerpendicular(vectorAB, planeB.vectorU, rayA.origin, anglesA.toJSON(), - planeB.origin, anglesB.toJSON()); - ck.testPerpendicular(vectorAB, planeB.vectorV, rayA.origin, anglesA.toJSON(), - planeB.origin, anglesB.toJSON(), planeB.origin, anglesB.toJSON()); + ck.testPerpendicular(vectorAB, planeB.vectorU, rayA.origin, anglesA.toJSON(), planeB.origin, anglesB.toJSON()); + ck.testPerpendicular( + vectorAB, + planeB.vectorV, + rayA.origin, + anglesA.toJSON(), + planeB.origin, + anglesB.toJSON(), + planeB.origin, + anglesB.toJSON(), + ); } ck.testCoordinate(Math.abs(distanceFromSurface), planeB.origin.distance(rayA.origin)); } @@ -575,9 +674,7 @@ describe("Ellipsoid", () => { const xShift = 2.0 * matrix.maxAbs(); x0 += xShift; // shift both before and after let y0 = 0; - const patch = EllipsoidPatch.createCapture(ellipsoid, - AngleSweep.create360(), - AngleSweep.createStartEndDegrees(-89, 89)); + const patch = EllipsoidPatch.createCapture(ellipsoid, AngleSweep.create360(), AngleSweep.createStartEndDegrees(-89, 89)); if (Checker.noisy.ellipsoid) GeometryCoreTestIO.consoleLog(" ELLIPSOID", prettyPrint(ellipsoid)); GeometryCoreTestIO.captureMesh(allGeometry, patch, 48, 16, x0, y0); @@ -632,15 +729,14 @@ describe("Ellipsoid", () => { // LongitudeLatitudeNumber.createDegrees(290, -30), ]; - for (const matrixNamePair of [ - // Matrix3d.createIdentity(), - [Matrix3d.createRowValues(6378136.695200001, 0, 0, - 0, 6378136.695200001, 0, - 0, 0, 6378136.695200001), "Sphere with Earth Equator Radius"], - [Matrix3d.createRowValues(6378136.695200001, 0, 0, - 0, 6378136.695200001, 0, - 0, 0, 6356751.995200001), "Earth no tip"], - [tippedEarthEllipsoidMatrix(), "Tipped earth"]]) { + for ( + const matrixNamePair of [ + // Matrix3d.createIdentity(), + [Matrix3d.createRowValues(6378136.695200001, 0, 0, 0, 6378136.695200001, 0, 0, 0, 6378136.695200001), "Sphere with Earth Equator Radius"], + [Matrix3d.createRowValues(6378136.695200001, 0, 0, 0, 6378136.695200001, 0, 0, 0, 6356751.995200001), "Earth no tip"], + [tippedEarthEllipsoidMatrix(), "Tipped earth"], + ] + ) { const matrix = matrixNamePair[0] as Matrix3d; const name = matrixNamePair[1] as string; if (Checker.noisy.ellipsoid) @@ -648,7 +744,7 @@ describe("Ellipsoid", () => { const y0 = 0.0; const dy = 2.0 * (matrix.columnXMagnitude() + matrix.columnYMagnitude()); const dx = 3.0 * dy; - x0 += dx; // dx shifts both before and after, to catch larger + x0 += dx; // dx shifts both before and after, to catch larger if (Checker.noisy.ellipsoid) { GeometryCoreTestIO.consoleLog(); GeometryCoreTestIO.consoleLog("*****************************************************************"); @@ -662,16 +758,39 @@ describe("Ellipsoid", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "EllipsoidPatch", "GreatArcsFullSizeEarth"); allGeometry.length = 0; x0 = 0; - for (const matrixNamePair of [ - // Matrix3d.createIdentity(), - [Matrix3d.createRowValues( - 1, 0, -0.5, - 0, 1, 0, - 0, 0, 1), "mild x skew"], - [Matrix3d.createRowValues( - 2, 0.1, 0.2, - -0.1, 4, 0.3, - 0.1, 0.2, 3.0), "3-axis Skew"]]) { + for ( + const matrixNamePair of [ + // Matrix3d.createIdentity(), + [ + Matrix3d.createRowValues( + 1, + 0, + -0.5, + 0, + 1, + 0, + 0, + 0, + 1, + ), + "mild x skew", + ], + [ + Matrix3d.createRowValues( + 2, + 0.1, + 0.2, + -0.1, + 4, + 0.3, + 0.1, + 0.2, + 3.0, + ), + "3-axis Skew", + ], + ] + ) { const matrix = matrixNamePair[0] as Matrix3d; const name = matrixNamePair[1] as string; if (Checker.noisy.ellipsoid) @@ -679,7 +798,7 @@ describe("Ellipsoid", () => { const y0 = 0.0; const dy = 2.0 * (matrix.columnXMagnitude() + matrix.columnYMagnitude()); const dx = 3.0 * dy; - x0 += dx; // dx shifts both before and after, to catch larger + x0 += dx; // dx shifts both before and after, to catch larger if (Checker.noisy.ellipsoid) { GeometryCoreTestIO.consoleLog(); GeometryCoreTestIO.consoleLog("*****************************************************************"); @@ -718,13 +837,26 @@ describe("Ellipsoid", () => { } } - for (const matrixNamePair of [ - // Matrix3d.createIdentity(), - [Matrix3d.createIdentity(), "sphere"], - [Matrix3d.createRowValues( - 1, 0, 0, - 0, 1, 0, - 0, 0, 0.25), "4:4:1"]]) { + for ( + const matrixNamePair of [ + // Matrix3d.createIdentity(), + [Matrix3d.createIdentity(), "sphere"], + [ + Matrix3d.createRowValues( + 1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0.25, + ), + "4:4:1", + ], + ] + ) { const matrix = matrixNamePair[0] as Matrix3d; // const name = matrixNamePair[1] as string; const ellipsoid = Ellipsoid.create(matrix); @@ -743,19 +875,23 @@ describe("Ellipsoid", () => { GeometryCoreTestIO.captureGeometry(allGeometry, arc, x0, y0); } for (const fraction of [0, 0.5, 1.0]) { - const arc031 = ellipsoid.createSectionArcPointPointVectorInPlane(angles[0], angles[3], - normal1.direction.interpolate(-fraction, normal2.direction))!; - const arc032 = ellipsoid.createSectionArcPointPointVectorInPlane(angles[0], angles[3], - normal1.direction.interpolate(1.0 + fraction, normal2.direction))!; + const arc031 = ellipsoid.createSectionArcPointPointVectorInPlane( + angles[0], + angles[3], + normal1.direction.interpolate(-fraction, normal2.direction), + )!; + const arc032 = ellipsoid.createSectionArcPointPointVectorInPlane( + angles[0], + angles[3], + normal1.direction.interpolate(1.0 + fraction, normal2.direction), + )!; GeometryCoreTestIO.captureGeometry(allGeometry, [arc031, arc032], x0, y0); } // save the ellipsoid scaled into it towards its center to there is no chatter among strokes of the arc and the ellipsoid mesh const displayScale = 0.99; ellipsoid.transformRef.matrix.scaleColumnsInPlace(displayScale, displayScale, displayScale); // GeometryCoreTestIO.captureMesh(allGeometry, patch, 16, 12, x0, y0); - const patch1 = EllipsoidPatch.createCapture(ellipsoid.clone(), - AngleSweep.create360(), - AngleSweep.createStartEndDegrees(-89.9, 89.9)); + const patch1 = EllipsoidPatch.createCapture(ellipsoid.clone(), AngleSweep.create360(), AngleSweep.createStartEndDegrees(-89.9, 89.9)); GeometryCoreTestIO.captureMesh(allGeometry, patch1, 48, 24, x0, y0); x0 += 10; } @@ -771,10 +907,19 @@ describe("Ellipsoid", () => { const realEyePoint = eyePoint.realPointOrVector(); if (realEyePoint instanceof Point3d) GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, realEyePoint, x0, y0); - for (const ellipsoid of [Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 0, 0), Matrix3d.createIdentity(), 1, 1, 1), - /* */ Ellipsoid.createCenterMatrixRadii(Point3d.create(3, 5, 1), Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 3), Angle.createDegrees(32)), 1, 1.2, 2.0), - /* */ Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 5, 0), Matrix3d.createRowValues(1, 0, 0.2, 0.1, 3, 0.2, -0.3, 0.1, 2), 1, 1, 1), - ]) { + for ( + const ellipsoid of [ + Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 0, 0), Matrix3d.createIdentity(), 1, 1, 1), + /* */ Ellipsoid.createCenterMatrixRadii( + Point3d.create(3, 5, 1), + Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 3), Angle.createDegrees(32)), + 1, + 1.2, + 2.0, + ), + /* */ Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 5, 0), Matrix3d.createRowValues(1, 0, 0.2, 0.1, 3, 0.2, -0.3, 0.1, 2), 1, 1, 1), + ] + ) { GeometryCoreTestIO.captureGeometry(allGeometry, facetEllipsoid(ellipsoid), x0, y0); const arc = ellipsoid.silhouetteArc(eyePoint); if (arc) { @@ -805,9 +950,16 @@ describe("Ellipsoid", () => { const x0 = 0; const y0 = 0; const matrix = Matrix3d.createRowValues( - 2230955.696607988, 4218074.856581404, 4217984.23465426, - -5853438.842941238, 635312.5558238369, 2444173.6696791253, - 1200293.8548970034, -4741817.943265299, 4079571.948578869); + 2230955.696607988, + 4218074.856581404, + 4217984.23465426, + -5853438.842941238, + 635312.5558238369, + 2444173.6696791253, + 1200293.8548970034, + -4741817.943265299, + 4079571.948578869, + ); const eye = Point4d.create(0.3901908903099731, 0.2662862131349449, 0.8813868173585089, 0); const ellipsoid = Ellipsoid.create(matrix); const silhouette = ellipsoid.silhouetteArc(eye); @@ -827,13 +979,20 @@ describe("Ellipsoid", () => { const x0 = 0; const y0 = 0; const matrix = Matrix3d.createRowValues( - 2230955.696607988, 4218074.856581404, 4217984.23465426, - -5853438.842941238, 635312.5558238369, 2444173.6696791253, - 1200293.8548970034, -4741817.943265299, 4079571.948578869); + 2230955.696607988, + 4218074.856581404, + 4217984.23465426, + -5853438.842941238, + 635312.5558238369, + 2444173.6696791253, + 1200293.8548970034, + -4741817.943265299, + 4079571.948578869, + ); const ellipsoid = Ellipsoid.create(matrix); - const pointA = ellipsoid.localToWorld({ x: 0.2, y: 0.5, z: 0.6 }); // definitely inside ! - const pointB = ellipsoid.localToWorld({ x: 1.2, y: 0.5, z: 0.6 }); // definitely outside ! + const pointA = ellipsoid.localToWorld({ x: 0.2, y: 0.5, z: 0.6 }); // definitely inside ! + const pointB = ellipsoid.localToWorld({ x: 1.2, y: 0.5, z: 0.6 }); // definitely outside ! GeometryCoreTestIO.captureGeometry(allGeometry, facetEllipsoid(ellipsoid), x0, y0); expect(ck.getNumErrors()).toBe(0); ck.testTrue(ellipsoid.isPointOnOrInside(pointA)); @@ -877,9 +1036,12 @@ describe("Ellipsoid", () => { const z0 = 0.0; for (const ellipsoidRadius of [1.0, 2.0]) { GeometryCoreTestIO.consoleLog({ "*** ellipsoid radius ": ellipsoidRadius }); - for (const ellipsoid of [ - Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 0, 0), undefined, ellipsoidRadius, ellipsoidRadius, ellipsoidRadius), - Ellipsoid.createCenterMatrixRadii(Point3d.create(3, 1, 0), undefined, ellipsoidRadius, ellipsoidRadius, 0.6 * ellipsoidRadius)]) { + for ( + const ellipsoid of [ + Ellipsoid.createCenterMatrixRadii(Point3d.create(0, 0, 0), undefined, ellipsoidRadius, ellipsoidRadius, ellipsoidRadius), + Ellipsoid.createCenterMatrixRadii(Point3d.create(3, 1, 0), undefined, ellipsoidRadius, ellipsoidRadius, 0.6 * ellipsoidRadius), + ] + ) { GeometryCoreTestIO.captureGeometry(allGeometry, facetEllipsoid(ellipsoid), x0, y0, z0); const announceArc: AnnounceNumberNumberCurvePrimitive = (f0: number, f1: number, arc: CurvePrimitive) => { GeometryCoreTestIO.captureGeometry(allGeometry, arc.clonePartialCurve(f0, f1), x0, y0, z0); @@ -887,12 +1049,14 @@ describe("Ellipsoid", () => { ck.testTrue(ellipsoid.isPointOnOrInside(arc.fractionToPoint(Geometry.interpolate(f0, 0.3, f1)))); }; - for (const arcA of [ - Arc3d.createXY(Point3d.create(2, 0, 0), 1.1), - Arc3d.createXY(Point3d.create(2, 0, 0), 1.5), - Arc3d.createXY(Point3d.create(2, 0, 0), 1.2), - Arc3d.createXYZXYZXYZ(2, 3, 1, 3, 0, 0.24, 0.2, 3, 1), - ]) { + for ( + const arcA of [ + Arc3d.createXY(Point3d.create(2, 0, 0), 1.1), + Arc3d.createXY(Point3d.create(2, 0, 0), 1.5), + Arc3d.createXY(Point3d.create(2, 0, 0), 1.2), + Arc3d.createXYZXYZXYZ(2, 3, 1, 3, 0, 0.24, 0.2, 3, 1), + ] + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, arcA, x0, y0); ellipsoid.announceClippedArcIntervals(arcA, announceArc); } @@ -902,7 +1066,6 @@ describe("Ellipsoid", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "Ellipsoid", "ArcClip"); expect(ck.getNumErrors()).toBe(0); - }); it("EarthClip", () => { const ck = new Checker(); @@ -939,11 +1102,13 @@ describe("Ellipsoid", () => { const ck = new Checker(); const ellipsoid = Ellipsoid.create(tippedEarthEllipsoidMatrix()); // this shares the ellipsoid ... should work fine ... - for (const patch of [ - EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(10, 62), AngleSweep.createStartEndDegrees(-20, 20)), - EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(220, 340), AngleSweep.createStartEndDegrees(-80, -20)), - EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(-180, 180), AngleSweep.createStartEndDegrees(-90, 90)), - ]) { + for ( + const patch of [ + EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(10, 62), AngleSweep.createStartEndDegrees(-20, 20)), + EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(220, 340), AngleSweep.createStartEndDegrees(-80, -20)), + EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(-180, 180), AngleSweep.createStartEndDegrees(-90, 90)), + ] + ) { const range = patch.range(); range.expandInPlace(1.0e-8); const range20 = UVSurfaceOps.sampledRangeOfOffsetPatch(patch, 0.0, 80, 40); @@ -973,11 +1138,13 @@ describe("Ellipsoid", () => { const sphereB = Ellipsoid.create(Matrix3d.createScale(b, b, b)); // patchB is offset. It's range can be directly computed. // offset of patchA is sampled. - for (const patchB of [ - EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(10, 62), AngleSweep.createStartEndDegrees(-20, 20)), - EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(220, 340), AngleSweep.createStartEndDegrees(-80, -20)), - EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(-180, 180), AngleSweep.createStartEndDegrees(-90, 90)), - ]) { + for ( + const patchB of [ + EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(10, 62), AngleSweep.createStartEndDegrees(-20, 20)), + EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(220, 340), AngleSweep.createStartEndDegrees(-80, -20)), + EllipsoidPatch.createCapture(sphereB, AngleSweep.createStartEndDegrees(-180, 180), AngleSweep.createStartEndDegrees(-90, 90)), + ] + ) { const patchA = EllipsoidPatch.createCapture(sphereA, patchB.longitudeSweep, patchB.latitudeSweep); const rangeB = patchB.range(); const rangeA4 = UVSurfaceOps.sampledRangeOfOffsetEllipsoidPatch(patchA, offsetDistance, options4); @@ -997,12 +1164,28 @@ describe("Ellipsoid", () => { }); function tippedEarthEllipsoidMatrix(): Matrix3d { - return Matrix3d.createRowValues(2230956.046389774, 4218075.517914913, 4217984.8981983, - -5853439.760676313, 635312.655431714, 2444174.054179583, - 1200294.0430858273, -4741818.686714196, 4079572.590348847); + return Matrix3d.createRowValues( + 2230956.046389774, + 4218075.517914913, + 4217984.8981983, + -5853439.760676313, + 635312.655431714, + 2444174.054179583, + 1200294.0430858273, + -4741818.686714196, + 4079572.590348847, + ); } -function testEllipsoidPaths(ck: Checker, allGeometry: GeometryQuery[], ellipsoid: Ellipsoid, anglePoints: LongitudeLatitudeNumber[], delta: number, x0: number, y0: number) { +function testEllipsoidPaths( + ck: Checker, + allGeometry: GeometryQuery[], + ellipsoid: Ellipsoid, + anglePoints: LongitudeLatitudeNumber[], + delta: number, + x0: number, + y0: number, +) { const fullCircle = AngleSweep.createStartEndDegrees(-180, 180); const tropic = AngleSweep.createStartEndDegrees(0, 30); const dy = delta; @@ -1010,9 +1193,7 @@ function testEllipsoidPaths(ck: Checker, allGeometry: GeometryQuery[], ellipsoid const optionalResultEllipsoid = Ellipsoid.create(Transform.createIdentity()); const center = ellipsoid.transformRef.getOrigin(); const builder = PolyfaceBuilder.create(); - const patch = EllipsoidPatch.createCapture(ellipsoid, - AngleSweep.createStartEndDegrees(0, 120), - AngleSweep.createStartEndDegrees(0, 85)); + const patch = EllipsoidPatch.createCapture(ellipsoid, AngleSweep.createStartEndDegrees(0, 120), AngleSweep.createStartEndDegrees(0, 85)); ck.testUndefined(ellipsoid.radiansPairToEquatorialEllipsoid(1, 1, 1, 1)); builder.addUVGridBody(patch, 32, 16); GeometryCoreTestIO.captureGeometry(allGeometry, builder.claimPolyface(), x0, y0); @@ -1021,10 +1202,13 @@ function testEllipsoidPaths(ck: Checker, allGeometry: GeometryQuery[], ellipsoid const angleB = anglePoints[i]; const startPoint = patch.ellipsoid.radiansToPoint(angleA.longitudeRadians, angleA.latitudeRadians); const endPoint = patch.ellipsoid.radiansToPoint(angleB.longitudeRadians, angleB.latitudeRadians); - const arc = ellipsoid.radiansPairToGreatArc(angleA.longitudeRadians, angleA.latitudeRadians, - angleB.longitudeRadians, angleB.latitudeRadians); - GeometryCoreTestIO.captureGeometry(allGeometry, - LineString3d.create(center.interpolate(1.4, startPoint), center, center.interpolate(1.4, endPoint)), x0, y0); + const arc = ellipsoid.radiansPairToGreatArc(angleA.longitudeRadians, angleA.latitudeRadians, angleB.longitudeRadians, angleB.latitudeRadians); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineString3d.create(center.interpolate(1.4, startPoint), center, center.interpolate(1.4, endPoint)), + x0, + y0, + ); if (ck.testDefined(arc)) { const arc1 = arc.clone(); arc1.scaleAboutCenterInPlace(1.4); @@ -1033,10 +1217,19 @@ function testEllipsoidPaths(ck: Checker, allGeometry: GeometryQuery[], ellipsoid // arc1.sweep.cloneComplement(false, arc1.sweep); // GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc1, x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc, x0, y0); - const ellipsoid1 = ellipsoid.radiansPairToEquatorialEllipsoid(angleA.longitudeRadians, angleA.latitudeRadians, - angleB.longitudeRadians, angleB.latitudeRadians)!; - ellipsoid.radiansPairToEquatorialEllipsoid(angleA.longitudeRadians, angleA.latitudeRadians, - angleB.longitudeRadians, angleB.latitudeRadians, optionalResultEllipsoid); + const ellipsoid1 = ellipsoid.radiansPairToEquatorialEllipsoid( + angleA.longitudeRadians, + angleA.latitudeRadians, + angleB.longitudeRadians, + angleB.latitudeRadians, + )!; + ellipsoid.radiansPairToEquatorialEllipsoid( + angleA.longitudeRadians, + angleA.latitudeRadians, + angleB.longitudeRadians, + angleB.latitudeRadians, + optionalResultEllipsoid, + ); ck.testTrue(ellipsoid1.isAlmostEqual(optionalResultEllipsoid), "optional ellipsoid"); GeometryCoreTestIO.captureMesh(allGeometry, EllipsoidPatch.createCapture(ellipsoid1, fullCircle, tropic), 32, 4, x0, y1); const arcLength = arc.curveLength(); @@ -1074,9 +1267,18 @@ function testEllipsoidPaths(ck: Checker, allGeometry: GeometryQuery[], ellipsoid GeometryCoreTestIO.captureCloneGeometry(allGeometry, minLengthArcDataA.minLengthArc, x0, y1); const lA = minLengthArcDataA.minLengthArc.curveLength(); if (Checker.noisy.ellipsoid) - GeometryCoreTestIO.consoleLog({ "approximate min section lengthA ": minLengthArcDataA.minLengthArc.curveLength(), "fraction ": minLengthArcDataA.minLengthNormalInterpolationFraction }); - const minLengthArcDataB = GeodesicPathSolver.approximateMinimumLengthSectionArc(ellipsoid, angleA, angleB, numSample, - minLengthArcDataA.minLengthNormalInterpolationFraction - 0.10, minLengthArcDataA.minLengthNormalInterpolationFraction + 0.10); + GeometryCoreTestIO.consoleLog({ + "approximate min section lengthA ": minLengthArcDataA.minLengthArc.curveLength(), + "fraction ": minLengthArcDataA.minLengthNormalInterpolationFraction, + }); + const minLengthArcDataB = GeodesicPathSolver.approximateMinimumLengthSectionArc( + ellipsoid, + angleA, + angleB, + numSample, + minLengthArcDataA.minLengthNormalInterpolationFraction - 0.10, + minLengthArcDataA.minLengthNormalInterpolationFraction + 0.10, + ); if (minLengthArcDataB) { const lB = minLengthArcDataB.minLengthArc.curveLength(); GeometryCoreTestIO.captureCloneGeometry(allGeometry, minLengthArcDataB.minLengthArc, x0, y1); @@ -1099,14 +1301,13 @@ function facetEllipsoid(ellipsoid: Ellipsoid, degreeStep: number = 15.0): Indexe const patch = EllipsoidPatch.createCapture( ellipsoid.clone(), AngleSweep.create360(), - AngleSweep.createFullLatitude()); + AngleSweep.createFullLatitude(), + ); const builder = PolyfaceBuilder.create(); const numU = Geometry.stepCount(degreeStep, patch.longitudeSweep.sweepDegrees, 1, 16); const numV = Geometry.stepCount(degreeStep, patch.latitudeSweep.sweepDegrees, 1, 16); - builder.addUVGridBody(patch, - numU, - numV); + builder.addUVGridBody(patch, numU, numV); const mesh = builder.claimPolyface(); return mesh; } diff --git a/core/geometry/src/test/geometry3d/FrameBuilder.test.ts b/core/geometry/src/test/geometry3d/FrameBuilder.test.ts index f2ca274c8b3a..3397838d41fa 100644 --- a/core/geometry/src/test/geometry3d/FrameBuilder.test.ts +++ b/core/geometry/src/test/geometry3d/FrameBuilder.test.ts @@ -29,23 +29,18 @@ import { prettyPrint } from "../testFunctions"; import { MatrixTests } from "./Matrix3d.test"; describe("FrameBuilder", () => { - it("HelloWorldA", () => { const ck = new Checker(); const builder = new FrameBuilder(); ck.testFalse(builder.hasOrigin, "frameBuilder.hasOrigin at start"); - for (const points of [ - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(0, 1, 0)], - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(1, 1, 0)], - [Point3d.create(1, 2, -1), - Point3d.create(1, 3, 5), - Point3d.create(-2, 1, 7)], - ]) { + for ( + const points of [ + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0)], + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0)], + [Point3d.create(1, 2, -1), Point3d.create(1, 3, 5), Point3d.create(-2, 1, 7)], + ] + ) { builder.clear(); const point0 = points[0]; const point1 = points[1]; @@ -66,8 +61,10 @@ describe("FrameBuilder", () => { builder.announcePoint(point2); ck.testUndefined(builder.getValidatedFrame(true), "frame in progress"); const rFrame = builder.getValidatedFrame(false); - if (ck.testPointer(rFrame, "expect right handed frame") && rFrame - && ck.testBoolean(true, rFrame.matrix.isRigid(), "good frame")) { + if ( + ck.testPointer(rFrame, "expect right handed frame") && rFrame + && ck.testBoolean(true, rFrame.matrix.isRigid(), "good frame") + ) { const inverse = rFrame.inverse(); if (ck.testPointer(inverse, "invertible frame") && inverse) { const product = rFrame.multiplyTransformTransform(inverse); @@ -93,19 +90,13 @@ describe("FrameBuilder", () => { const ck = new Checker(); const builder = new FrameBuilder(); - for (const points of [ - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(0, 1, 0)], - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(1, 1, 0), - Point3d.create(2, 1, 0)], - [Point3d.create(1, 2, -1), - Point3d.create(1, 3, 5), - Point3d.create(2, 4, 3), - Point3d.create(-2, 1, 7)], - ]) { + for ( + const points of [ + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0)], + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(2, 1, 0)], + [Point3d.create(1, 2, -1), Point3d.create(1, 3, 5), Point3d.create(2, 4, 3), Point3d.create(-2, 1, 7)], + ] + ) { builder.clear(); const linestring = LineString3d.create(points); const bcurve = BSplineCurve3d.createUniformKnots(points, 3); @@ -125,19 +116,13 @@ describe("FrameBuilder", () => { it("InterpolationCurve", () => { const ck = new Checker(); const builder = new FrameBuilder(); - for (const points of [ - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(0, 1, 0)], - [Point3d.create(0, 0, 0), - Point3d.create(1, 0, 0), - Point3d.create(1, 1, 0), - Point3d.create(2, 1, 0)], - [Point3d.create(1, 2, -1), - Point3d.create(1, 3, 5), - Point3d.create(2, 4, 3), - Point3d.create(-2, 1, 7)], - ]) { + for ( + const points of [ + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0)], + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(1, 1, 0), Point3d.create(2, 1, 0)], + [Point3d.create(1, 2, -1), Point3d.create(1, 3, 5), Point3d.create(2, 4, 3), Point3d.create(-2, 1, 7)], + ] + ) { builder.clear(); const linestring = LineString3d.create(points); const curve = InterpolationCurve3d.create(InterpolationCurve3dOptions.create({ fitPoints: points })); @@ -179,11 +164,11 @@ describe("FrameBuilder", () => { ck.testExactNumber(0, builder.savedVectorCount()); // loop body assumes each set of points has 3 leading independent vectors - for (const vectors of [ - [Vector3d.create(1, 0, 0), - Vector3d.create(0, 1, 0), - Vector3d.create(0, 0, 1)], - ]) { + for ( + const vectors of [ + [Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), Vector3d.create(0, 0, 1)], + ] + ) { builder.clear(); const vector0 = vectors[0]; const vector1 = vectors[1]; @@ -199,7 +184,6 @@ describe("FrameBuilder", () => { ck.testExactNumber(2, builder.announceVector(vector1.plusScaled(vector0, 2.0))); ck.testExactNumber(3, builder.announceVector(vector2)); - } ck.checkpoint("FrameBuilder"); expect(ck.getNumErrors()).toBe(0); @@ -210,20 +194,22 @@ describe("FrameBuilder", () => { const nullRangeLocalToWorld = FrameBuilder.createLocalToWorldTransformInRange(Range3d.createNull(), AxisScaleSelect.Unit, 0, 0, 0, 2.0); ck.testTransform(Transform.createIdentity(), nullRangeLocalToWorld, "frame in null range"); - for (const range of [Range3d.createXYZXYZ(1, 2, 3, 5, 7, 9)] - ) { - for (const select of [ - AxisScaleSelect.Unit, - AxisScaleSelect.LongestRangeDirection, - AxisScaleSelect.NonUniformRangeContainment]) { + for (const range of [Range3d.createXYZXYZ(1, 2, 3, 5, 7, 9)]) { + for ( + const select of [ + AxisScaleSelect.Unit, + AxisScaleSelect.LongestRangeDirection, + AxisScaleSelect.NonUniformRangeContainment, + ] + ) { const localToWorld = FrameBuilder.createLocalToWorldTransformInRange(range, select, 0, 0, 0, 2.0); if (ck.testPointer(localToWorld)) { MatrixTests.checkProperties( ck, localToWorld.matrix, - select === AxisScaleSelect.Unit, // unit axes in range are identity - select === AxisScaleSelect.Unit, // and of course unitPerpendicular - select === AxisScaleSelect.Unit, // and of course rigid. + select === AxisScaleSelect.Unit, // unit axes in range are identity + select === AxisScaleSelect.Unit, // and of course unitPerpendicular + select === AxisScaleSelect.Unit, // and of course rigid. true, // always invertible true, // always diagonal ); @@ -248,9 +234,13 @@ describe("FrameBuilder", () => { loop.tryAddChild(Arc3d.createCircularStartMiddleEnd( Point3d.create(0, a, 0), Point3d.create(-a / 2, a / 2, zz), - Point3d.create(0, 0, 0))); + Point3d.create(0, 0, 0), + )); ck.testBoolean( - Geometry.isSmallMetricDistance(zz), curvesToPlane(loop) !== undefined, "planarity test"); + Geometry.isSmallMetricDistance(zz), + curvesToPlane(loop) !== undefined, + "planarity test", + ); const rawSums = RegionOps.computeXYAreaMoments(loop)!; GeometryCoreTestIO.consoleLog("curves", prettyPrint(IModelJson.Writer.toIModelJson(loop))); @@ -260,13 +250,11 @@ describe("FrameBuilder", () => { GeometryCoreTestIO.captureGeometry(allGeometry, loop, x0, y0, 0); GeometryCoreTestIO.showMomentData(allGeometry, rawSums, false, x0, y0, 0); x0 += 2.0 * a; - } ck.testDefined(curvesToPlane(LineSegment3d.createXYZXYZ(1, 2, 4, 5, 2, 3)), "test CurvePrimitive input"); GeometryCoreTestIO.saveGeometry(allGeometry, "FrameBuilder", "NonPlanarCurves"); expect(ck.getNumErrors()).toBe(0); }); - }); /** test if a curve collection is planar within tolerance. diff --git a/core/geometry/src/test/geometry3d/FrustumAnimation.test.ts b/core/geometry/src/test/geometry3d/FrustumAnimation.test.ts index d74f8ee3ff5b..76135e4a41cf 100644 --- a/core/geometry/src/test/geometry3d/FrustumAnimation.test.ts +++ b/core/geometry/src/test/geometry3d/FrustumAnimation.test.ts @@ -23,18 +23,31 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; */ function cornersToLineString(corners: Point3d[]): LineString3d { return LineString3d.create( - [corners[0], corners[1], corners[3], corners[2], corners[0], // back rectangle - corners[4], // move to front - corners[5], corners[1], corners[5], // front edge plus move to same back point and double back to front - corners[7], corners[3], corners[7], - corners[6], corners[2], corners[6], - corners[4], - corners[0], - corners[0].interpolate(4.0, corners[4]), // Show z direction - corners[0], - corners[0].interpolate(1.2, corners[1]), // some asymmetric decoration on xy face - corners[0].interpolate(0.5, corners[1]), // some asymmetric decoration on xy face - corners[0].interpolate(0.5, corners[2])]); + [ + corners[0], + corners[1], + corners[3], + corners[2], + corners[0], // back rectangle + corners[4], // move to front + corners[5], + corners[1], + corners[5], // front edge plus move to same back point and double back to front + corners[7], + corners[3], + corners[7], + corners[6], + corners[2], + corners[6], + corners[4], + corners[0], + corners[0].interpolate(4.0, corners[4]), // Show z direction + corners[0], + corners[0].interpolate(1.2, corners[1]), // some asymmetric decoration on xy face + corners[0].interpolate(0.5, corners[1]), // some asymmetric decoration on xy face + corners[0].interpolate(0.5, corners[2]), + ], + ); } /** * Within the given coordinate frame (usually rigid) make the 8 corners of a frustum @@ -53,7 +66,8 @@ function createFrustumPoints(frame: Transform, ax: number, ay: number, az: numbe frame.multiplyXYZ(-fz * ax, -fz * ay, az), frame.multiplyXYZ(fz * ax, -fz * ay, az), frame.multiplyXYZ(-fz * ax, fz * ay, az), - frame.multiplyXYZ(fz * ax, fz * ay, az)]; + frame.multiplyXYZ(fz * ax, fz * ay, az), + ]; } describe("FrustumAnimation", () => { @@ -63,39 +77,93 @@ describe("FrustumAnimation", () => { const c20 = Math.cos(Angle.degreesToRadians(20)); const s20 = Math.sin(Angle.degreesToRadians(20)); let dy = 0.0; - for (const frame0 of [ - Transform.createIdentity(), - Transform.createOriginAndMatrix(Point3d.create(-2, 2, -1), - YawPitchRollAngles.createDegrees(10, 5, 30).toMatrix3d())] + for ( + const frame0 of [ + Transform.createIdentity(), + Transform.createOriginAndMatrix(Point3d.create(-2, 2, -1), YawPitchRollAngles.createDegrees(10, 5, 30).toMatrix3d()), + ] ) { let dx = 0.0; - for (const frame1 of [ - Transform.createTranslationXYZ(1, 2, 15), - // rotate 90 degrees while shifting along the x axis. - Transform.createRowValues( - c20, -s20, 0, 40, - s20, c20, 0, 0, - 0, 0, 1, 0), - // rotate 90 degrees while shifting along the x axis. - Transform.createRowValues( - 0, -1, 0, 40, - 1, 0, 0, 0, - 0, 0, 1, 0), - // rotate 180 degrees z and around center - Transform.createRowValues( - -1, 0, 0, 0, - 0, -1, 0, 0, - 0, 0, 1, 0), - // rotate 180 degrees around z while shifting y - Transform.createRowValues( - -1, 0, 0, 0, - 0, -1, 0, 80, - 0, 0, 1, 0), - // translate the back plane, but re-aim the eye vector (SKEW) - Transform.createRowValues( - 1, 0, 1, 0, - 0, 1, 2, 30, - 0, 0, 3, 0)]) { + for ( + const frame1 of [ + Transform.createTranslationXYZ(1, 2, 15), + // rotate 90 degrees while shifting along the x axis. + Transform.createRowValues( + c20, + -s20, + 0, + 40, + s20, + c20, + 0, + 0, + 0, + 0, + 1, + 0, + ), + // rotate 90 degrees while shifting along the x axis. + Transform.createRowValues( + 0, + -1, + 0, + 40, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + ), + // rotate 180 degrees z and around center + Transform.createRowValues( + -1, + 0, + 0, + 0, + 0, + -1, + 0, + 0, + 0, + 0, + 1, + 0, + ), + // rotate 180 degrees around z while shifting y + Transform.createRowValues( + -1, + 0, + 0, + 0, + 0, + -1, + 0, + 80, + 0, + 0, + 1, + 0, + ), + // translate the back plane, but re-aim the eye vector (SKEW) + Transform.createRowValues( + 1, + 0, + 1, + 0, + 0, + 1, + 2, + 30, + 0, + 0, + 3, + 0, + ), + ] + ) { const cornerA = createFrustumPoints(frame0, 4, 3, 2, 1); const cornerB = createFrustumPoints(frame1, 2, 4, 3, 0.5); GeometryCoreTestIO.captureGeometry(allGeometry, cornersToLineString(cornerA).clone(), dx, dy, 0); @@ -107,7 +175,6 @@ describe("FrustumAnimation", () => { for (const fraction of [0.0, g, 2.0 * g, 0.25, 0.5, 0.75, 1.0 - 2.0 * g, 1.0 - g, 1.0]) { const cornerF = context.fractionToWorldCorners(fraction); GeometryCoreTestIO.captureGeometry(allGeometry, cornersToLineString(cornerF), dx, dy1, 0); - } } dx += 100.0; @@ -128,23 +195,32 @@ describe("FrustumAnimation", () => { const axisLineScale = 10.0; let dy = 0.0; let dx = 0.0; - for (const frame0 of [ - Transform.createIdentity(), - Transform.createOriginAndMatrix(Point3d.create(-2, 2, -1), - YawPitchRollAngles.createDegrees(10, 5, 30).toMatrix3d()), - Transform.createOriginAndMatrix(Point3d.create(5, 2, 0), - YawPitchRollAngles.createDegrees(2, 5, 5).toMatrix3d())] + for ( + const frame0 of [ + Transform.createIdentity(), + Transform.createOriginAndMatrix(Point3d.create(-2, 2, -1), YawPitchRollAngles.createDegrees(10, 5, 30).toMatrix3d()), + Transform.createOriginAndMatrix(Point3d.create(5, 2, 0), YawPitchRollAngles.createDegrees(2, 5, 5).toMatrix3d()), + ] ) { dy = 0.0; for (const degrees of [10, 50, 80, 110]) { for (const axis of [Vector3d.unitZ(), axisA, axisB]) { const ray = Ray3d.create(primaryOrigin, axis); const e = 25.0; - const rotation = Transform.createFixedPointAndMatrix(primaryOrigin, Matrix3d.createRotationAroundVector(axis, Angle.createDegrees(degrees))!); - for (const frustumScale of [1, 3, 8]) { // large scale should get rotation axis inside frustum !!! + const rotation = Transform.createFixedPointAndMatrix( + primaryOrigin, + Matrix3d.createRotationAroundVector(axis, Angle.createDegrees(degrees))!, + ); + for (const frustumScale of [1, 3, 8]) { // large scale should get rotation axis inside frustum !!! const cornerA = createFrustumPoints(frame0, frustumScale * 4, frustumScale * 3, frustumScale * 2, 1); const cornerB = rotation.multiplyPoint3dArray(cornerA); - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(primaryOrigin, primaryOrigin.plusScaled(axis, axisLineScale)), dx, dy, 0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(primaryOrigin, primaryOrigin.plusScaled(axis, axisLineScale)), + dx, + dy, + 0, + ); GeometryCoreTestIO.captureGeometry(allGeometry, cornersToLineString(cornerA).clone(), dx, dy, 0); GeometryCoreTestIO.captureGeometry(allGeometry, cornersToLineString(cornerB).clone(), dx, dy, 0); // we expect that rotationalContext is the true rotation @@ -159,7 +235,13 @@ describe("FrustumAnimation", () => { ck.testPoint3d(originA, projectionA, "animation start is on true axis"); ck.testPoint3d(originB, projectionB, "animation end is on true axis"); const dy1 = dy + 500; - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(primaryOrigin, primaryOrigin.plusScaled(axis, axisLineScale)), dx, dy1, 0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(primaryOrigin, primaryOrigin.plusScaled(axis, axisLineScale)), + dx, + dy1, + 0, + ); for (const fraction of [0.0, 0.25, 0.50, 0.75, 1.0]) { const cornerFA = rotationalContext.fractionToWorldCorners(fraction); GeometryCoreTestIO.captureGeometry(allGeometry, cornersToLineString(cornerFA), dx, dy1, 0); diff --git a/core/geometry/src/test/geometry3d/GrowableArray.test.ts b/core/geometry/src/test/geometry3d/GrowableArray.test.ts index aca5aaab92a9..eedd562f1569 100644 --- a/core/geometry/src/test/geometry3d/GrowableArray.test.ts +++ b/core/geometry/src/test/geometry3d/GrowableArray.test.ts @@ -106,7 +106,6 @@ describe("GrowableFloat64Array.HelloWorld", () => { ck.checkpoint("GrowableArray.move"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("BlockedArray", () => { @@ -122,7 +121,8 @@ describe("BlockedArray", () => { // points on these lines get considered for clusters. const perp = Vector2d.create( ClusterableArray.sortVectorComponent(1), - -ClusterableArray.sortVectorComponent(0)); + -ClusterableArray.sortVectorComponent(0), + ); // these points are distinct ... const xy0 = Point2d.create(1, 2); @@ -176,8 +176,10 @@ describe("BlockedArray", () => { const clusterIndex1 = blocks.getExtraData(k1, 0); ck.testExactNumber(clusterIndex0, clusterIndex1); ck.testLE( - blocks.distanceBetweenBlocks(k0, k1), tolerance, - "confirm cluster tolerance"); + blocks.distanceBetweenBlocks(k0, k1), + tolerance, + "confirm cluster tolerance", + ); // k0, k1 should match each other and the original cluster point ck.testLE(uv0.distance(uv1), tolerance, "query cluster", k0, k1); ck.testLE(uv1.distance(points[clusterIndex1]), tolerance, "original cluster"); @@ -232,14 +234,14 @@ describe("BlockedArray", () => { ck.testExactNumber(numPerBlock, data0.numPerBlock); ck.testExactNumber(0, data0.numBlocks); const blockStep = 10; - const baseBlock = [1, 3, 5, 7, 9]; // all less than blockStep to simplify testing. + const baseBlock = [1, 3, 5, 7, 9]; // all less than blockStep to simplify testing. const numAdd = 9; for (let i = 0; i < numAdd; i++) { const newBlock = []; const blockBaseValue = blockStep * data0.numBlocks; for (const a of baseBlock) newBlock.push(a + blockBaseValue); if (i === 3 || i === 7) - newBlock.push(999); // an extraneous value to test handling of oversize inputs + newBlock.push(999); // an extraneous value to test handling of oversize inputs data0.addBlock(newBlock); } @@ -252,7 +254,6 @@ describe("BlockedArray", () => { ck.checkpoint("GrowableBlockedArray.HelloWorld"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("GrowablePoint3dArray", () => { @@ -360,7 +361,14 @@ describe("GrowablePoint3dArray", () => { for (const origin of [Point3d.create(-b / 2, -h / 2, 0), Point3d.create(1, 1, 0)]) { const polyface = Sample.createTriangularUnitGridPolyface( origin, - Vector3d.create(b, 0, 0), Vector3d.create(0, h, 0), 2, 2, false, false, false); + Vector3d.create(b, 0, 0), + Vector3d.create(0, h, 0), + 2, + 2, + false, + false, + false, + ); const moments = PolyfaceQuery.computePrincipalAreaMoments(polyface); if (Checker.noisy.rectangleMoments) { GeometryCoreTestIO.consoleLog("Rectangle lower left", origin); @@ -389,16 +397,34 @@ describe("GrowablePoint3dArray", () => { ck.testTrue(point.isAlmostEqual(vector)); ck.testPoint3d(point, Point3d.create(4, 5, 6)); - const transform = Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createRowValues( - 2, 1, 0, - 2, 0, 0, - 2, 0, 1, - )); - const noInverseTransform = Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createRowValues( - 1, 6, 4, - 2, 4, -1, - -1, 2, 5, - )); + const transform = Transform.createOriginAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRowValues( + 2, + 1, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + ), + ); + const noInverseTransform = Transform.createOriginAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRowValues( + 1, + 6, + 4, + 2, + 4, + -1, + -1, + 2, + 5, + ), + ); ck.testTrue(arr.tryTransformInverseInPlace(transform)); ck.testFalse(arr.tryTransformInverseInPlace(noInverseTransform)); @@ -417,8 +443,10 @@ describe("GrowablePoint3dArray", () => { it("IndexedXYZCollection", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const frame = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!); + const frame = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!, + ); frame.multiplyPoint3dArrayInPlace(points); const gPoints = new GrowableXYZArray(); @@ -445,15 +473,18 @@ describe("GrowablePoint3dArray", () => { ck.testVector3d(vectorGA, pointIA.vectorTo(pointGB)); ck.testVector3d( iPoints.crossProductIndexIndexIndex(0, i, j)!, - gPoints.crossProductIndexIndexIndex(0, i, j)!); + gPoints.crossProductIndexIndexIndex(0, i, j)!, + ); ck.testVector3d( iPoints.crossProductXYAndZIndexIndex(iOrigin, i, j)!, - gPoints.crossProductXYAndZIndexIndex(gOrigin, i, j)!); + gPoints.crossProductXYAndZIndexIndex(gOrigin, i, j)!, + ); ck.testVector3d( iPoints.getVector3dAtCheckedVectorIndex(i)!, gPoints.getVector3dAtCheckedVectorIndex(i)!, - "atVector3dIndex"); + "atVector3dIndex", + ); ck.testPoint3d(Point3dArray.centroid(iPoints), Point3dArray.centroid(gPoints), "centroid"); } @@ -464,7 +495,7 @@ describe("GrowablePoint3dArray", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const xyzPoints = new GrowableXYZArray(points.length); // just enough so we know the initial capacity. + const xyzPoints = new GrowableXYZArray(points.length); // just enough so we know the initial capacity. for (const p of points) xyzPoints.push(p); @@ -482,7 +513,7 @@ describe("GrowablePoint3dArray", () => { ck.testExactNumber(n1, xyzPoints.length); const n2 = n0 - deltaN; - xyzPoints.resize(n2); // blow away some points. + xyzPoints.resize(n2); // blow away some points. ck.testUndefined(xyzPoints.getVector3dAtCheckedVectorIndex(-4)); ck.testUndefined(xyzPoints.getVector3dAtCheckedVectorIndex(n2)); @@ -532,7 +563,7 @@ describe("GrowablePoint3dArray", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const array0 = new GrowableXYZArray(points.length); // just enough so we know the initial capacity. + const array0 = new GrowableXYZArray(points.length); // just enough so we know the initial capacity. for (const p of points) array0.push(p); const n0 = array0.length; @@ -565,9 +596,13 @@ describe("GrowablePoint3dArray", () => { ck.testUndefined(array1.interpolate(k, 0.3, n0 + 1), "interpolate with bad index"); ck.testUndefined(array1.interpolate(k, 0.3, n0 + 3), "interpolate with bad index"); - const k1 = (2 * k) % n0; // this should be a valid index !!! - if (ck.testTrue(array0.isIndexValid(k1) - && ck.testPointer(array0.interpolate(k, interpolationFraction, k1, resultA)))) { + const k1 = (2 * k) % n0; // this should be a valid index !!! + if ( + ck.testTrue( + array0.isIndexValid(k1) + && ck.testPointer(array0.interpolate(k, interpolationFraction, k1, resultA)), + ) + ) { const k2 = (2 * k + 1) % n0; const point0 = array0.getPoint3dAtUncheckedPointIndex(k); @@ -629,8 +664,7 @@ describe("GrowablePoint3dArray", () => { for (let i = 0; i < dataA.length; i++) { for (let j = 0; j < dataB.length; j++) { - ck.testCoordinate(GrowableXYZArray.distanceBetweenPointsIn2Arrays(dataA, i, dataB, j)!, - testPointI(i).distance(testPointI(2 * j))); + ck.testCoordinate(GrowableXYZArray.distanceBetweenPointsIn2Arrays(dataA, i, dataB, j)!, testPointI(i).distance(testPointI(2 * j))); const pointA2 = dataA.getPoint2dAtCheckedPointIndex(i)!; const pointB2 = dataB.getPoint2dAtUncheckedPointIndex(j); const pointA3 = dataA.getPoint3dAtCheckedPointIndex(i)!; @@ -652,9 +686,16 @@ describe("GrowablePoint3dArray", () => { ck.testFalse(dataA.multiplyAndRenormalizeMatrix3dInverseTransposeInPlace(Matrix3d.createScale(0, 1, 0)), "Singular Matrix should fail"); const matrix = Matrix3d.createRowValues( - 6, -3, 1, - 4, 9, 2, - -1, 4, 8); + 6, + -3, + 1, + 4, + 9, + 2, + -1, + 4, + 8, + ); const matrixTranspose = matrix.transpose(); dataA.pushXYZ(1, 0, 0); ck.testTrue(dataA.multiplyAndRenormalizeMatrix3dInverseTransposeInPlace(matrix), "Normal transform with good data"); @@ -688,7 +729,8 @@ describe("GrowablePoint3dArray", () => { const dataC0 = new GrowableXYZArray(); const points = [ Point3d.create(1, 2, 3), - Point3d.create(2, 4, 10)]; + Point3d.create(2, 4, 10), + ]; /** Assemble the points into GrowableXYZArray with variant input parse ... */ dataA.pushFrom(points); @@ -730,18 +772,50 @@ describe("GrowableArray", () => { const ck = new Checker(); // extend array types so we can cover protected copyData() - class MyGrowableBlockedArray extends GrowableBlockedArray { public callCopyData(source: Float64Array | number[], sourceCount?: number | undefined, destOffset?: number | undefined): { count: number, offset: number } { return this.copyData(source, sourceCount, destOffset); } } - class MyGrowableFloat64Array extends GrowableFloat64Array { public callCopyData(source: Float64Array | number[], sourceCount?: number | undefined, destOffset?: number | undefined): { count: number, offset: number } { return this.copyData(source, sourceCount, destOffset); } } - class MyGrowableXYZArray extends GrowableXYZArray { public callCopyData(source: Float64Array | number[], sourceCount?: number | undefined, destOffset?: number | undefined): { count: number, offset: number } { return this.copyData(source, sourceCount, destOffset); } } - class MyGrowableXYArray extends GrowableXYArray { public callCopyData(source: Float64Array | number[], sourceCount?: number | undefined, destOffset?: number | undefined): { count: number, offset: number } { return this.copyData(source, sourceCount, destOffset); } } + class MyGrowableBlockedArray extends GrowableBlockedArray { + public callCopyData( + source: Float64Array | number[], + sourceCount?: number | undefined, + destOffset?: number | undefined, + ): { count: number, offset: number } { + return this.copyData(source, sourceCount, destOffset); + } + } + class MyGrowableFloat64Array extends GrowableFloat64Array { + public callCopyData( + source: Float64Array | number[], + sourceCount?: number | undefined, + destOffset?: number | undefined, + ): { count: number, offset: number } { + return this.copyData(source, sourceCount, destOffset); + } + } + class MyGrowableXYZArray extends GrowableXYZArray { + public callCopyData( + source: Float64Array | number[], + sourceCount?: number | undefined, + destOffset?: number | undefined, + ): { count: number, offset: number } { + return this.copyData(source, sourceCount, destOffset); + } + } + class MyGrowableXYArray extends GrowableXYArray { + public callCopyData( + source: Float64Array | number[], + sourceCount?: number | undefined, + destOffset?: number | undefined, + ): { count: number, offset: number } { + return this.copyData(source, sourceCount, destOffset); + } + } // NOTE: copyData does not increase number of blocks/floats/points in use! const coverCopyData = (array: MyGrowableBlockedArray | MyGrowableFloat64Array | MyGrowableXYZArray | MyGrowableXYArray) => { const copyValues: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; const a1 = new Float64Array(copyValues); - const args: ((number | undefined)[])[] = [[undefined, undefined], [100, -1], [0, 100], [5, 58], [100, 7]]; // sourceCount, destOffset + const args: ((number | undefined)[])[] = [[undefined, undefined], [100, -1], [0, 100], [5, 58], [100, 7]]; // sourceCount, destOffset for (let i = 0; i < args.length; ++i) { - const myCopyValues = copyValues.map((val) => (i + 1) * val); // copy different values each iteration + const myCopyValues = copyValues.map((val) => (i + 1) * val); // copy different values each iteration let out = array.callCopyData(myCopyValues, args[i][0], args[i][1]); compareContents(array, out.offset, myCopyValues, 0, out.count); out = array.callCopyData(a1, args[i][0], args[i][1]); @@ -750,7 +824,13 @@ describe("GrowableArray", () => { }; // Units of count and offsets are blocks/floats/points - const compareContents = (a0: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, offset0: number, a1: number[] | GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, offset1: number, count: number): boolean => { + const compareContents = ( + a0: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, + offset0: number, + a1: number[] | GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, + offset1: number, + count: number, + ): boolean => { if (count <= 0) return true; // handle a1:number[] by constructing a growable array of same type as a0, and recursing @@ -787,7 +867,13 @@ describe("GrowableArray", () => { return false; for (let iBlock = 0; iBlock < count; ++iBlock) for (let iComponent = 0; iComponent < a0.numPerBlock; ++iComponent) - if (!ck.testExactNumber(a0.component(offset0 + iBlock, iComponent), a1.component(offset1 + iBlock, iComponent), "Original array contents preserved")) + if ( + !ck.testExactNumber( + a0.component(offset0 + iBlock, iComponent), + a1.component(offset1 + iBlock, iComponent), + "Original array contents preserved", + ) + ) return false; } else if (a0 instanceof GrowableFloat64Array && a1 instanceof GrowableFloat64Array) { for (let i = 0; i < count; ++i) @@ -796,12 +882,24 @@ describe("GrowableArray", () => { } else if (a0 instanceof GrowableXYArray && a1 instanceof GrowableXYArray) { for (let iPoint = 0; iPoint < count; ++iPoint) for (let iComponent = 0; iComponent < 2; ++iComponent) - if (!ck.testExactNumber(a0.component(offset0 + iPoint, iComponent), a1.component(offset1 + iPoint, iComponent), "Original array contents preserved")) + if ( + !ck.testExactNumber( + a0.component(offset0 + iPoint, iComponent), + a1.component(offset1 + iPoint, iComponent), + "Original array contents preserved", + ) + ) return false; } else if (a0 instanceof GrowableXYZArray && a1 instanceof GrowableXYZArray) { for (let iPoint = 0; iPoint < count; ++iPoint) for (let iComponent = 0; iComponent < 3; ++iComponent) - if (!ck.testExactNumber(a0.component(offset0 + iPoint, iComponent), a1.component(offset1 + iPoint, iComponent), "Original array contents preserved")) + if ( + !ck.testExactNumber( + a0.component(offset0 + iPoint, iComponent), + a1.component(offset1 + iPoint, iComponent), + "Original array contents preserved", + ) + ) return false; } else { ck.testTrue(false, "Shouldn't get here"); @@ -834,7 +932,11 @@ describe("GrowableArray", () => { return 1; }; - const ensureCapacity = (array: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, newCapacity: number, applyGrowthFactor: boolean) => { + const ensureCapacity = ( + array: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, + newCapacity: number, + applyGrowthFactor: boolean, + ) => { if (array instanceof GrowableBlockedArray) array.ensureBlockCapacity(newCapacity, applyGrowthFactor); else @@ -842,10 +944,13 @@ describe("GrowableArray", () => { }; /** ASSUME: array was constructed with growthFactor */ - const testGrowthFactor = (array: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, growthFactor: number | undefined) => { + const testGrowthFactor = ( + array: GrowableBlockedArray | GrowableFloat64Array | GrowableXYZArray | GrowableXYArray, + growthFactor: number | undefined, + ) => { const caps1: number[] = [4, 7, 15, 33]; for (const newCap of caps1) { - const oldArray = array.clone(); // in general, preserves only active structs + const oldArray = array.clone(); // in general, preserves only active structs const oldCap = getCapacity(array); ensureCapacity(array, newCap, false); if (ck.testExactNumber(Math.max(oldCap, newCap), getCapacity(array), "ensureCapacity without growthFactor yields expected capacity")) { @@ -854,14 +959,20 @@ describe("GrowableArray", () => { } } if (growthFactor === undefined || growthFactor < 1) - growthFactor = 1.5; // the default growth factor in growable arrays + growthFactor = 1.5; // the default growth factor in growable arrays const caps2: number[] = [30, 33, 40, 57]; for (const newCap of caps2) { - const oldArray = array.clone(); // in general, preserves only active structs + const oldArray = array.clone(); // in general, preserves only active structs const oldCap = getCapacity(array); ensureCapacity(array, newCap, true); - if (ck.testExactNumber(newCap <= oldCap ? oldCap : Math.trunc(growthFactor * newCap), getCapacity(array), "ensureCapacity with growthFactor yields expected capacity")) { + if ( + ck.testExactNumber( + newCap <= oldCap ? oldCap : Math.trunc(growthFactor * newCap), + getCapacity(array), + "ensureCapacity with growthFactor yields expected capacity", + ) + ) { if (!compareContents(oldArray, 0, array, 0, oldArray.length)) return; } diff --git a/core/geometry/src/test/geometry3d/GrowableXYArray.test.ts b/core/geometry/src/test/geometry3d/GrowableXYArray.test.ts index eb0d244476cf..ec5cd6ba7179 100644 --- a/core/geometry/src/test/geometry3d/GrowableXYArray.test.ts +++ b/core/geometry/src/test/geometry3d/GrowableXYArray.test.ts @@ -15,9 +15,9 @@ import { Point3dArrayCarrier } from "../../geometry3d/Point3dArrayCarrier"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Range2d } from "../../geometry3d/Range"; import { Transform } from "../../geometry3d/Transform"; +import { XAndY } from "../../geometry3d/XYZProps"; import { Sample } from "../../serialization/GeometrySamples"; import { Checker } from "../Checker"; -import { XAndY } from "../../geometry3d/XYZProps"; describe("GrowableXYArray", () => { it("PointMoments", () => { @@ -74,7 +74,7 @@ describe("GrowableXYArray", () => { const pointBXY = pointAXY.clone(); const pointC = pointAXY.getPoint2dArray(); const pointD = GrowableXYArray.create(pointC); - const eps = 1.0e-16; // ugh .. + const eps = 1.0e-16; // ugh .. ck.testTrue(pointAXY.isAlmostEqual(pointBXY, eps)); ck.testTrue(pointAXY.isAlmostEqual(pointD, eps)); expect(ck.getNumErrors()).toBe(0); @@ -82,7 +82,9 @@ describe("GrowableXYArray", () => { const xyBuffer = pointAXY.float64Data(); for (let i = 0; i < n; i++) { ck.testTrue(Geometry.isSamePoint2d( - pointAXY.getPoint2dAtUncheckedPointIndex(i), Point2d.create(xyBuffer[2 * i], xyBuffer[2 * i + 1]))); + pointAXY.getPoint2dAtUncheckedPointIndex(i), + Point2d.create(xyBuffer[2 * i], xyBuffer[2 * i + 1]), + )); } pointD.clear(); @@ -147,9 +149,19 @@ describe("GrowableXYArray", () => { const rangeA = Range2d.createNull(); pointA.extendRange(rangeA); const transform = Transform.createRowValues( - 1, 2, 4, 3, - 2, 5, 4, -3, - 0.2, 0.3, 0.4, 0.5); + 1, + 2, + 4, + 3, + 2, + 5, + 4, + -3, + 0.2, + 0.3, + 0.4, + 0.5, + ); const rangeB = Range2d.createNull(); const rangeC = Range2d.createNull(); pointB.multiplyTransformInPlace(transform); @@ -237,16 +249,34 @@ describe("GrowableXYArray", () => { ck.testTrue(point.isAlmostEqual(vector)); ck.testPoint2d(point, Point2d.create(4, 5)); - const transform = Transform.createOriginAndMatrix(Point3d.create(0, 0), Matrix3d.createRowValues( - 2, 1, 0, - 2, 0, 0, - 2, 0, 1, - )); - const noInverseTransform = Transform.createOriginAndMatrix(Point3d.create(0, 0), Matrix3d.createRowValues( - 1, 6, 4, - 2, 4, -1, - -1, 2, 5, - )); + const transform = Transform.createOriginAndMatrix( + Point3d.create(0, 0), + Matrix3d.createRowValues( + 2, + 1, + 0, + 2, + 0, + 0, + 2, + 0, + 1, + ), + ); + const noInverseTransform = Transform.createOriginAndMatrix( + Point3d.create(0, 0), + Matrix3d.createRowValues( + 1, + 6, + 4, + 2, + 4, + -1, + -1, + 2, + 5, + ), + ); ck.testTrue(arr.tryTransformInverseInPlace(transform)); ck.testFalse(arr.tryTransformInverseInPlace(noInverseTransform)); @@ -260,8 +290,10 @@ describe("GrowableXYArray", () => { it("IndexedXYCollection", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const frame = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 0), - Matrix3d.createRotationAroundVector(Vector3d.create(0, 0, 1), Angle.createDegrees(15.7))!); + const frame = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 0), + Matrix3d.createRotationAroundVector(Vector3d.create(0, 0, 1), Angle.createDegrees(15.7))!, + ); frame.multiplyPoint3dArrayInPlace(points); const points2d = []; @@ -292,16 +324,18 @@ describe("GrowableXYArray", () => { ck.testVector2d(vectorGA, pointIA.vectorTo(pointGB)); ck.testCoordinate( iPoints.crossProductIndexIndexIndex(0, i, j)!, - gPoints.crossProductIndexIndexIndex(0, i, j)!); + gPoints.crossProductIndexIndexIndex(0, i, j)!, + ); ck.testCoordinate( iPoints.crossProductXAndYIndexIndex(iOrigin, i, j)!, - gPoints.crossProductXAndYIndexIndex(gOrigin, i, j)!); + gPoints.crossProductXAndYIndexIndex(gOrigin, i, j)!, + ); ck.testVector2d( iPoints.getVector2dAtCheckedVectorIndex(i)!, gPoints.getVector2dAtCheckedVectorIndex(i)!, - "atVector2dIndex"); - + "atVector2dIndex", + ); } expect(ck.getNumErrors()).toBe(0); }); @@ -310,7 +344,7 @@ describe("GrowableXYArray", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const xyPoints = new GrowableXYArray(points.length); // just enough so we know the initial capacity. + const xyPoints = new GrowableXYArray(points.length); // just enough so we know the initial capacity. for (const p of points) xyPoints.push(p); @@ -328,7 +362,7 @@ describe("GrowableXYArray", () => { ck.testExactNumber(n1, xyPoints.length); const n2 = n0 - deltaN; - xyPoints.resize(n2); // blow away some points. + xyPoints.resize(n2); // blow away some points. ck.testUndefined(xyPoints.getVector2dAtCheckedVectorIndex(-4)); ck.testUndefined(xyPoints.getVector2dAtCheckedVectorIndex(n2)); @@ -378,7 +412,7 @@ describe("GrowableXYArray", () => { const ck = new Checker(); const points = Sample.createFractalDiamondConvexPattern(1, -0.5); - const array0 = new GrowableXYArray(points.length); // just enough so we know the initial capacity. + const array0 = new GrowableXYArray(points.length); // just enough so we know the initial capacity. for (const p of points) array0.push(p); const n0 = array0.length; @@ -411,9 +445,13 @@ describe("GrowableXYArray", () => { ck.testUndefined(array1.interpolate(k, 0.3, n0 + 1), "interpolate with bad index"); ck.testUndefined(array1.interpolate(k, 0.3, n0 + 3), "interpolate with bad index"); - const k1 = (2 * k) % n0; // this should be a valid index !!! - if (ck.testTrue(array0.isIndexValid(k1) - && ck.testPointer(array0.interpolate(k, interpolationFraction, k1, resultA)))) { + const k1 = (2 * k) % n0; // this should be a valid index !!! + if ( + ck.testTrue( + array0.isIndexValid(k1) + && ck.testPointer(array0.interpolate(k, interpolationFraction, k1, resultA)), + ) + ) { const k2 = (2 * k + 1) % n0; const point0 = array0.getPoint2dAtUncheckedPointIndex(k); @@ -497,7 +535,7 @@ describe("GrowableXYArray", () => { it("removeClosurePoints", () => { const ck = new Checker(); const origin = Point3d.create(1, 2, 3); - const points = Sample.createSquareWave(origin, 2, 1, 3, 3, 5); // This has a single closure point !! + const points = Sample.createSquareWave(origin, 2, 1, 3, 3, 5); // This has a single closure point !! const wrapper = new Point3dArrayCarrier(points); const originalCount = wrapper.length; const originalTrim = originalCount - 1; @@ -569,7 +607,7 @@ describe("GrowableXYArray", () => { ck.testExactNumber(xyzArray.length, 2, "variant XYZ input ctor: outer length"); ck.testExactNumber(xyzArray[0].length, 1, "variant XYZ input ctor: first array length"); ck.testExactNumber(xyzArray[1].length, 2, "variant XYZ input ctor: second array length"); - const a2 = GrowableXYArray.createFromGrowableXYZArray(xyzArray[0], undefined, a0); // clears a0 first + const a2 = GrowableXYArray.createFromGrowableXYZArray(xyzArray[0], undefined, a0); // clears a0 first ck.testTrue(a0 === a2, "create from pre-allocated object returns same object"); if (ck.testExactNumber(a0.length, 1, "create from GrowableXYZArray: count")) { ck.testExactNumber(a0.getXAtUncheckedPointIndex(0), xyzArray[0].getXAtUncheckedPointIndex(0), "create from GrowableXYZArray: x-value"); diff --git a/core/geometry/src/test/geometry3d/IndexedXYZCollectionInterval.test.ts b/core/geometry/src/test/geometry3d/IndexedXYZCollectionInterval.test.ts index 83f6d40492f2..c8d2eebd0146 100644 --- a/core/geometry/src/test/geometry3d/IndexedXYZCollectionInterval.test.ts +++ b/core/geometry/src/test/geometry3d/IndexedXYZCollectionInterval.test.ts @@ -36,7 +36,7 @@ describe("IndexedXYZCollectionInterval", () => { ck.testTrue(intervalB.isValidSubset); ck.testTrue(intervalB.length === 0); - points.length = 5; // oops !! intervals become invalid!! + points.length = 5; // oops !! intervals become invalid!! ck.testFalse(fullInterval.isValidSubset, " subset invalid after trim."); fullInterval.restrictEnd(); fullInterval.advanceEnd(); @@ -44,5 +44,4 @@ describe("IndexedXYZCollectionInterval", () => { ck.testExactNumber(fullInterval.length, points.length, "advanceEnd capped"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/LongitudeLatitudeAltidue.test.ts b/core/geometry/src/test/geometry3d/LongitudeLatitudeAltidue.test.ts index 35478ea3a3d0..7a36be92bcd1 100644 --- a/core/geometry/src/test/geometry3d/LongitudeLatitudeAltidue.test.ts +++ b/core/geometry/src/test/geometry3d/LongitudeLatitudeAltidue.test.ts @@ -10,7 +10,11 @@ describe("LongitudeLatitudeNumber", () => { it("create", () => { const ck = new Checker(); const createAsDegrees = LongitudeLatitudeNumber.createDegrees(10, 40, 5); - const createAsRadians = LongitudeLatitudeNumber.createRadians(createAsDegrees.longitudeRadians, createAsDegrees.latitudeRadians, createAsDegrees.altitude); + const createAsRadians = LongitudeLatitudeNumber.createRadians( + createAsDegrees.longitudeRadians, + createAsDegrees.latitudeRadians, + createAsDegrees.altitude, + ); // "create" clones its angles . . . const createAsAngles = LongitudeLatitudeNumber.create(createAsDegrees.longitudeRef, createAsDegrees.latitudeRef, createAsDegrees.altitude); ck.testTrue(createAsDegrees.isAlmostEqual(createAsRadians), "asDegrees vs asRadians"); @@ -47,5 +51,4 @@ describe("LongitudeLatitudeNumber", () => { ck.testTrue(b.isAlmostEqual(d)); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Matrix3d.test.ts b/core/geometry/src/test/geometry3d/Matrix3d.test.ts index da4236a3470a..39cdf063924a 100644 --- a/core/geometry/src/test/geometry3d/Matrix3d.test.ts +++ b/core/geometry/src/test/geometry3d/Matrix3d.test.ts @@ -19,8 +19,15 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; // cSpell:words XXYZ YXYZ ZXYZ XYZAs Eigen dgnplatform VTAT rigids ATTV export class MatrixTests { - public static checkProperties(ck: bsiChecker.Checker, matrix: Matrix3d, isIdentity: boolean | undefined, - isUnitPerpendicular: boolean, isRigid: boolean, isInvertible: boolean, isDiagonal: boolean | undefined) { + public static checkProperties( + ck: bsiChecker.Checker, + matrix: Matrix3d, + isIdentity: boolean | undefined, + isUnitPerpendicular: boolean, + isRigid: boolean, + isInvertible: boolean, + isDiagonal: boolean | undefined, + ) { if (isIdentity !== undefined) ck.testBoolean(isIdentity, matrix.isIdentity, "isIdentity"); ck.testBoolean(isUnitPerpendicular, matrix.testPerpendicularUnitRowsAndColumns(), "unitPerpendicularMatrix"); @@ -48,24 +55,31 @@ function testCreateProperties(ck: bsiChecker.Checker) { ck.testVector3d( matrix.multiplyVector(vectorA), Vector3d.create(0, 0, 0).plus3Scaled( - matrix.columnX(), vectorA.x, - matrix.columnY(), vectorA.y, - matrix.columnZ(), vectorA.z, + matrix.columnX(), + vectorA.x, + matrix.columnY(), + vectorA.y, + matrix.columnZ(), + vectorA.z, ), "matrix * vector versus column * scalar", ); ck.testVector3d( matrix.multiplyVector(vectorA), Vector3d.create(0, 0, 0).plus2Scaled( - matrix.columnY(), vectorA.y, - matrix.columnZ(), vectorA.z, + matrix.columnY(), + vectorA.y, + matrix.columnZ(), + vectorA.z, ).plusScaled(matrix.columnX(), vectorA.x), "matrix * vector versus column * scalar", ); const frame = Matrix3d.createRigidFromColumns(vectorA, vectorB, AxisOrder.XYZ); - if (ck.testPointer(frame, "PerpendicularColumns") && frame - && ck.testBoolean(true, frame.testPerpendicularUnitRowsAndColumns(), "UnitPerpendicularColumns")) { + if ( + ck.testPointer(frame, "PerpendicularColumns") && frame + && ck.testBoolean(true, frame.testPerpendicularUnitRowsAndColumns(), "UnitPerpendicularColumns") + ) { const matrixT = matrix.transpose(); const frameT = frame.transpose(); for (let i = 0; i < 6; i++) { @@ -104,17 +118,24 @@ function testCreateProperties(ck: bsiChecker.Checker) { let vector; const e = 1.0 / 64.0; - for (vector of [ - Vector3d.create(1, 2, 3), - Vector3d.create(1, 0, 0), - Vector3d.create(0, 1, 0), - Vector3d.create(0, 0, 1), - Vector3d.create(e, e, 3.0), // triggers near-z logic - ]) { + for ( + vector of [ + Vector3d.create(1, 2, 3), + Vector3d.create(1, 0, 0), + Vector3d.create(0, 1, 0), + Vector3d.create(0, 0, 1), + Vector3d.create(e, e, 3.0), // triggers near-z logic + ] + ) { const triad = Matrix3d.createRigidHeadsUp(vector); if (ck.testPointer(triad)) { MatrixTests.checkProperties( - ck, triad, undefined, true, true, true, + ck, + triad, + undefined, + true, + true, + true, // default axis order for createRigidHeadsUp is ZXY so vector goes to the // third column of triad so triad is diagonal only when vector = [0,0,1] vector.isAlmostEqual(Vector3d.unitZ()), @@ -148,9 +169,15 @@ describe("Matrix3d.Inverse", () => { it("Verify matrix is invertible and matrix times inverse is identity", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix3d.createRowValues( - 4, 2, 1, - -1, 5, 3, - 0.5, 0.75, 9, + 4, + 2, + 1, + -1, + 5, + 3, + 0.5, + 0.75, + 9, ); checkInverse(ck, matrixA); ck.checkpoint("Matrix3d.Inverse"); @@ -190,13 +217,13 @@ function checkPointArrays(ck: bsiChecker.Checker, pointsA: Point3d[]) { rangeB.low, rangeC.low, "`scale array and then create a range on the scaled array` is same as " + - "`create range on the array and then scale the range`", + "`create range on the array and then scale the range`", ); ck.testPoint3d( rangeB.high, rangeC.high, "`scale array and then create a range on the scaled array` is same as " + - "`create range on the array and then scale the range`", + "`create range on the array and then scale the range`", ); } @@ -213,14 +240,26 @@ describe("Matrix3d.checkPointArrays", () => { describe("Matrix3d.isAlmostEqualAllowZRotation", () => { it("Matrix3d.isAlmostEqualAllowZRotation", () => { const thisMatrix = Matrix3d.createRowValues( - 1, 1, 0, - 0, 1, 0, - 0, 0, 1, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 1, ); const otherMatrix = Matrix3d.createRowValues( - -1, -1, 0, - 0, -1, 0, - 0, 0, 1, + -1, + -1, + 0, + 0, + -1, + 0, + 0, + 0, + 1, ); // thisMatrix and otherMatrix have the same column Z. Also their column X // and Y are differing only by a rotation of 180 degrees around column Z. @@ -238,9 +277,15 @@ describe("Matrix3d.factorPerpendicularColumns", () => { const f = efg[1]; const g = efg[2]; const matrixA = Matrix3d.createRowValues( - 2, 0, 2, - e, f, -e, - g, 1, 0, + 2, + 0, + 2, + e, + f, + -e, + g, + 1, + 0, ); matrixA.scaleColumns(scale, scale, scale); const matrixB = Matrix3d.createZero(); @@ -250,9 +295,15 @@ describe("Matrix3d.factorPerpendicularColumns", () => { const matrixBTB = matrixB.multiplyMatrixTransposeMatrix(matrixB); if (bsiChecker.Checker.noisy.factorPerpendicularColumns) { GeometryCoreTestIO.consoleLog("A", matrixA); - GeometryCoreTestIO.consoleLog("diagonal elements of BTB: ", - matrixBTB.at(0, 0), " - ", matrixBTB.at(1, 1), " - ", matrixBTB.at(1, 1), - ". error: ", matrixBTB.sumSquares() - matrixBTB.sumDiagonalSquares(), + GeometryCoreTestIO.consoleLog( + "diagonal elements of BTB: ", + matrixBTB.at(0, 0), + " - ", + matrixBTB.at(1, 1), + " - ", + matrixBTB.at(1, 1), + ". error: ", + matrixBTB.sumSquares() - matrixBTB.sumDiagonalSquares(), ); GeometryCoreTestIO.consoleLog("B", matrixB); GeometryCoreTestIO.consoleLog("C", matrixC); @@ -276,12 +327,15 @@ describe("Matrix3d.factorPerpendicularColumns", () => { ck.testCoordinate(0, matrixC.maxDiff(matrixU), "C = U"); if (ck.testCoordinate(0, matrixA.maxDiff(matrixVD.multiplyMatrixMatrix(matrixU)), "A = V*D*U")) ck.testCoordinate(0, matrixB.maxDiff(matrixVD), "B = V*D"); - else // recompute for debugging + // recompute for debugging + else matrixA.maxDiff(matrixVD.multiplyMatrixMatrix(matrixU)); if (ck.testTrue(matrixV.isRigid(true), "V is orthogonal")) { const matrixVU = matrixV.multiplyMatrixMatrix(matrixU); ck.testTrue(matrixVU.isRigid(true), "VU is orthogonal"); - } else // recompute for debugging + } + // recompute for debugging + else matrixV.isRigid(true); } } @@ -294,10 +348,12 @@ describe("Matrix3d.factorPerpendicularColumns", () => { describe("Matrix3d.symmetricEigenvalues", () => { it("Matrix3d.symmetricEigenvalues", () => { const ck = new bsiChecker.Checker(); - for (const lambda0 of [ - Vector3d.create(2, 1, 4), - Vector3d.create(3, 2, -1), - ]) { + for ( + const lambda0 of [ + Vector3d.create(2, 1, 4), + Vector3d.create(3, 2, -1), + ] + ) { for (const matrixM of Sample.createMatrix3dArray()) { if (matrixM.isRigid()) { // matrixA is symmetric because columns of matrixM are perpendicular @@ -331,9 +387,15 @@ describe("Matrix3d.directDots", () => { it("Matrix3d.Matrix3d.directDots", () => { const ck = new bsiChecker.Checker(); const matrix = Matrix3d.createRowValues( - 1, 2, 3, - 0.3, 0.77, 4.2, - -0.02, 5, 9, + 1, + 2, + 3, + 0.3, + 0.77, + 4.2, + -0.02, + 5, + 9, ); const uv = matrix.columnXDotColumnY(); const uw = matrix.columnXDotColumnZ(); @@ -360,9 +422,15 @@ describe("Matrix3d.cachedInverse", () => { it("cachedInverse", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix3d.createRowValues( - 1, 2, 3, - 0.3, 0.77, 4.2, - -0.02, 5, 9, + 1, + 2, + 3, + 0.3, + 0.77, + 4.2, + -0.02, + 5, + 9, ); Matrix3d.numUseCache = 0; Matrix3d.numComputeCache = 0; @@ -435,9 +503,15 @@ describe("Matrix3d.CachedInverse", () => { verifyMatrix3dInverseProperties( ck, Matrix3d.createRowValues( - 10, 1, 2, - 3, 20, 1, - 4, 2, 15, + 10, + 1, + 2, + 3, + 20, + 1, + 4, + 2, + 15, ), ); ck.checkpoint("Matrix3d.CachedInverse"); @@ -525,12 +599,11 @@ describe("Matrix3d.RowAccess", () => { describe("AxisOrder.ShiftAxis", () => { it("AxisOrder.ShiftAxis", () => { const ck = new bsiChecker.Checker(); - for (const axisOrder of - [AxisOrder.XYZ, AxisOrder.YZX, AxisOrder.ZXY, AxisOrder.XZY, AxisOrder.YXZ, AxisOrder.ZYX] - ) { + for (const axisOrder of [AxisOrder.XYZ, AxisOrder.YZX, AxisOrder.ZXY, AxisOrder.XZY, AxisOrder.YXZ, AxisOrder.ZYX]) { if (bsiChecker.Checker.noisy.axisOrderVerify) { GeometryCoreTestIO.consoleLog( - "AxisOrder", axisOrder, + "AxisOrder", + axisOrder, Geometry.axisOrderToAxis(axisOrder, 0), Geometry.axisOrderToAxis(axisOrder, 1), Geometry.axisOrderToAxis(axisOrder, 2), @@ -554,9 +627,7 @@ describe("AxisOrder.ShiftAxis", () => { const vector1 = Vector3d.create(1, 1001, -2); const vector2 = Vector3d.create(-3, 1.234, 1002); const ck = new bsiChecker.Checker(); - for (const axisOrder of - [AxisOrder.XYZ, AxisOrder.YZX, AxisOrder.ZXY, AxisOrder.XZY, AxisOrder.YXZ, AxisOrder.ZYX] - ) { + for (const axisOrder of [AxisOrder.XYZ, AxisOrder.YZX, AxisOrder.ZXY, AxisOrder.XZY, AxisOrder.YXZ, AxisOrder.ZYX]) { const axis0 = Geometry.axisOrderToAxis(axisOrder, 0); const axis1 = Geometry.axisOrderToAxis(axisOrder, 1); const axis2 = Geometry.axisOrderToAxis(axisOrder, 2); @@ -608,9 +679,15 @@ describe("Matrix3d.Factors", () => { it("Matrix3d.Quaternion", () => { const ck = new bsiChecker.Checker(); const rigidScale = Matrix3d.createRowValues( - 0.019908485552297163, -0.0040687348173572974, 0, - 0.0040687348173572974, 0.019908485552297163, 0, - 0, 0, 0.020320000000000008, + 0.019908485552297163, + -0.0040687348173572974, + 0, + 0.0040687348173572974, + 0.019908485552297163, + 0, + 0, + 0, + 0.020320000000000008, ); const result = Matrix3d.createZero(); const data = rigidScale.factorRigidWithSignedScale(result); @@ -696,21 +773,23 @@ describe("Matrix3d.AxisAndAngleOfRotation", () => { // rotation by 180 degrees is a special case to invert. it("Matrix3d.AxisAndAngleOfRotationPI", () => { const ck = new bsiChecker.Checker(); - for (const vector of [ - Vector3d.unitX(), - Vector3d.unitY(), - Vector3d.unitZ(), - Vector3d.create(1, 1, 0), - Vector3d.create(-1, 1, 0), - Vector3d.create(0, 1, 1), - Vector3d.create(0, -1, 1), - Vector3d.create(1, 0, 1), - Vector3d.create(-1, 0, 1), - Vector3d.create(-1, 2, 0), - Vector3d.create(1, 2, 3), - Vector3d.create(-1, 2, 3), - Vector3d.create(1, -2, 3), - Vector3d.create(-1, -2, 3)] + for ( + const vector of [ + Vector3d.unitX(), + Vector3d.unitY(), + Vector3d.unitZ(), + Vector3d.create(1, 1, 0), + Vector3d.create(-1, 1, 0), + Vector3d.create(0, 1, 1), + Vector3d.create(0, -1, 1), + Vector3d.create(1, 0, 1), + Vector3d.create(-1, 0, 1), + Vector3d.create(-1, 2, 0), + Vector3d.create(1, 2, 3), + Vector3d.create(-1, 2, 3), + Vector3d.create(1, -2, 3), + Vector3d.create(-1, -2, 3), + ] ) { for (const scale of [1, -1]) { const vectorA = vector.scale(scale); @@ -726,8 +805,13 @@ describe("Matrix3d.AxisAndAngleOfRotation", () => { }); }); -function generateRotationTransform(eyePoint: Point3d, viewRotation: Matrix3d, yawRateRadiansPerTime: number, - pitchRateRadiansPerTime: number, time: number): Transform { +function generateRotationTransform( + eyePoint: Point3d, + viewRotation: Matrix3d, + yawRateRadiansPerTime: number, + pitchRateRadiansPerTime: number, + time: number, +): Transform { const yawAngle = Angle.createRadians(yawRateRadiansPerTime * time); const pitchAngle = Angle.createRadians(pitchRateRadiansPerTime * time); @@ -792,13 +876,23 @@ describe("Matrix3d.RotateVector", () => { -0.40375557735756828, ), Matrix3d.createRowValues( - 0.99857861707557882, -0.053201794397914448, -0.0032116338935924771, - 0.053107143509079233, 0.99828614780495017, -0.024584515636062437, - 0.004514069974036361, 0.024379010923246527, 0.99969259625080453, + 0.99857861707557882, + -0.053201794397914448, + -0.0032116338935924771, + 0.053107143509079233, + 0.99828614780495017, + -0.024584515636062437, + 0.004514069974036361, + 0.024379010923246527, + 0.99969259625080453, ), ); const transform = generateRotationTransform( - eyePoint, viewRotation, yawRateRadiansPerTime, pitchRateRadiansPerTime, time, + eyePoint, + viewRotation, + yawRateRadiansPerTime, + pitchRateRadiansPerTime, + time, ); ck.testMatrix3d(expectedTransform.matrix, transform.matrix); ck.testXYZ(expectedTransform.origin, transform.origin); @@ -828,14 +922,16 @@ describe("Matrix3d.RotateVector", () => { Vector3d.createZero(), 0.3, Vector3d.unitX(), - ), "rotation with zero vector", + ), + "rotation with zero vector", ); ck.testUndefined( Matrix3d.createPartialRotationVectorToVector( Vector3d.unitX(), 0.2, Vector3d.createZero(), - ), "rotation with zero axis", + ), + "rotation with zero axis", ); const vectorA = Vector3d.create(1, 2, 3); @@ -1258,12 +1354,14 @@ describe("Matrix3d.Multiply", () => { it("Matrix3d.MultiplyXYZToFloat64Array", () => { const ck = new bsiChecker.Checker(); const vectors = Sample.createNonZeroVectors(); - for (const planeNormal of [ - Vector3d.unitX(), - Vector3d.unitY(), - Vector3d.unitZ(), - Vector3d.create(1, 2, 4), - ]) { + for ( + const planeNormal of [ + Vector3d.unitX(), + Vector3d.unitY(), + Vector3d.unitZ(), + Vector3d.create(1, 2, 4), + ] + ) { planeNormal.normalizeInPlace(); // matrix does not have to be generated by createDirectionalScale and can be any matrix. const matrix = Matrix3d.createDirectionalScale(planeNormal, -1.0); @@ -1529,8 +1627,12 @@ describe("Matrix3d.SnapToCube", () => { }); }); -function checkInverseRelationship(ck: bsiChecker.Checker, name: string, matrix: Matrix3d | undefined, - expectedInverseState: InverseMatrixState | undefined) { +function checkInverseRelationship( + ck: bsiChecker.Checker, + name: string, + matrix: Matrix3d | undefined, + expectedInverseState: InverseMatrixState | undefined, +) { if (matrix !== undefined) { if (bsiChecker.Checker.noisy.matrixMultiplyAliasing) { GeometryCoreTestIO.consoleLog("-------------------------------"); @@ -1616,14 +1718,26 @@ describe("Matrix3d.MatrixProduct", () => { it("Matrix3d.MatrixProduct", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix3d.createRowValues( - 10, 1, 2, - -3, 12, 4, - 3, 5, 15, + 10, + 1, + 2, + -3, + 12, + 4, + 3, + 5, + 15, ); const matrixB = Matrix3d.createRowValues( - 9, 0.2, 2.2, - -3.5, 12.5, 4.1, - 3.9, -2.1, 17.8, + 9, + 0.2, + 2.2, + -3.5, + 12.5, + 4.1, + 3.9, + -2.1, + 17.8, ); const matrixAB = matrixA.multiplyMatrixMatrix(matrixB); const matrixABT = matrixA.multiplyMatrixMatrixTranspose(matrixB); @@ -1645,53 +1759,69 @@ describe("Matrix3d.MatrixProduct", () => { ck.testDefined(matrixB.inverseCoffs); testProductCombinations( - ck, matrixA, matrixB, true, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d => - matrixA1.multiplyMatrixMatrix(matrixB1, result1), + ck, + matrixA, + matrixB, + true, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d => matrixA1.multiplyMatrixMatrix(matrixB1, result1), InverseMatrixState.inverseStored, ); testProductCombinations( - ck, matrixA, matrixB, true, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixInverseMatrix(matrixB1, result1), + ck, + matrixA, + matrixB, + true, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixInverseMatrix(matrixB1, result1), InverseMatrixState.inverseStored, ); testProductCombinations( - ck, matrixA, matrixB, true, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixMatrixInverse(matrixB1, result1), + ck, + matrixA, + matrixB, + true, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixMatrixInverse(matrixB1, result1), InverseMatrixState.inverseStored, ); testProductCombinations( - ck, matrixA, matrixB, true, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixTransposeMatrix(matrixB1, result1), + ck, + matrixA, + matrixB, + true, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixTransposeMatrix(matrixB1, result1), InverseMatrixState.inverseStored, ); testProductCombinations( - ck, matrixA, matrixB, true, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixMatrixTranspose(matrixB1, result1), + ck, + matrixA, + matrixB, + true, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixMatrixTranspose(matrixB1, result1), InverseMatrixState.inverseStored, ); const singularMatrix = Matrix3d.createScale(1, 0, 1); testProductCombinations( - ck, matrixA, singularMatrix, false, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d => - matrixA1.multiplyMatrixMatrix(matrixB1, result1), + ck, + matrixA, + singularMatrix, + false, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d => matrixA1.multiplyMatrixMatrix(matrixB1, result1), InverseMatrixState.singular, ); testProductCombinations( - ck, matrixA, singularMatrix, false, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixTransposeMatrix(matrixB1, result1), + ck, + matrixA, + singularMatrix, + false, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixTransposeMatrix(matrixB1, result1), InverseMatrixState.singular, ); testProductCombinations( - ck, matrixA, singularMatrix, false, - (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => - matrixA1.multiplyMatrixMatrixTranspose(matrixB1, result1), + ck, + matrixA, + singularMatrix, + false, + (matrixA1: Matrix3d, matrixB1: Matrix3d, result1?: Matrix3d): Matrix3d | undefined => matrixA1.multiplyMatrixMatrixTranspose(matrixB1, result1), InverseMatrixState.singular, ); ck.testUndefined(matrixA.multiplyMatrixMatrixInverse(singularMatrix), "singular product"); @@ -1780,9 +1910,15 @@ describe("Matrix3d.CloneRigid", () => { it("Matrix3d.CloneRigid", () => { const ck = new bsiChecker.Checker(); const matrix = Matrix3d.createRowValues( - -6.438509378433656e-18, -1.0840344784091856e-18, -0.008851813267008355, - 7.88489990157899e-34, -0.008851813267008355, 1.0840344784091856e-18, - -0.008851813267008355, 0, 6.438509378433656e-18, + -6.438509378433656e-18, + -1.0840344784091856e-18, + -0.008851813267008355, + 7.88489990157899e-34, + -0.008851813267008355, + 1.0840344784091856e-18, + -0.008851813267008355, + 0, + 6.438509378433656e-18, ); const origin = Point3d.create(1, 2, 3); const transform = Transform.createOriginAndMatrix(origin, matrix); @@ -1806,9 +1942,15 @@ describe("Matrix3d.CloneRigid", () => { const eps = 1.0e-10; ck.testUndefined(Matrix3d.createRigidFromMatrix3d(epsMatrix), "expect no rigid from epsilon matrix"); const matrixD = Matrix3d.createRowValues( - 1, 1, 0, - 0, eps, 0, - 0, eps, 1, + 1, + 1, + 0, + 0, + eps, + 0, + 0, + eps, + 1, ); ck.testUndefined(Matrix3d.createRigidFromMatrix3d(matrixD), "expect no rigid from matrix with near-parallel columns"); @@ -1822,9 +1964,15 @@ describe("Matrix3d.SetColumns", () => { const vectorX: Vector3d = Vector3d.create(1, 2, 3); const vectorY: Vector3d = Vector3d.create(4, 5, 6); const expectedMatrix: Matrix3d = Matrix3d.createRowValues( - 1, 4, 0, - 2, 5, 0, - 3, 6, 0, + 1, + 4, + 0, + 2, + 5, + 0, + 3, + 6, + 0, ); const theMatrix = Matrix3d.createIdentity(); theMatrix.setColumns(vectorX, vectorY); @@ -1838,9 +1986,15 @@ describe("Matrix3d.SetRow", () => { const ck = new bsiChecker.Checker(); const vector: Vector3d = Vector3d.create(1, 2, 3); const expectedMatrix: Matrix3d = Matrix3d.createRowValues( - 1, 2, 3, - 0, 1, 0, - 0, 0, 1, + 1, + 2, + 3, + 0, + 1, + 0, + 0, + 0, + 1, ); const theMatrix = Matrix3d.createIdentity(); theMatrix.setRow(0, vector); @@ -1883,4 +2037,3 @@ describe("Matrix3d.createRigidViewAxesZTowardsEye", () => { ck.testCoordinate(point.z, 0); }); }); - diff --git a/core/geometry/src/test/geometry3d/OrderedRotationAngles.test.ts b/core/geometry/src/test/geometry3d/OrderedRotationAngles.test.ts index ddf48502c7b8..a8ed397760f5 100644 --- a/core/geometry/src/test/geometry3d/OrderedRotationAngles.test.ts +++ b/core/geometry/src/test/geometry3d/OrderedRotationAngles.test.ts @@ -14,12 +14,18 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function multiplyMatricesByAxisOrder(xMatrix: Matrix3d, yMatrix: Matrix3d, zMatrix: Matrix3d, axisOrder: AxisOrder): Matrix3d { switch (axisOrder) { - case AxisOrder.XYZ: return zMatrix.multiplyMatrixMatrix(yMatrix.multiplyMatrixMatrix(xMatrix)); - case AxisOrder.XZY: return yMatrix.multiplyMatrixMatrix(zMatrix.multiplyMatrixMatrix(xMatrix)); - case AxisOrder.YXZ: return zMatrix.multiplyMatrixMatrix(xMatrix.multiplyMatrixMatrix(yMatrix)); - case AxisOrder.YZX: return xMatrix.multiplyMatrixMatrix(zMatrix.multiplyMatrixMatrix(yMatrix)); - case AxisOrder.ZXY: return yMatrix.multiplyMatrixMatrix(xMatrix.multiplyMatrixMatrix(zMatrix)); - case AxisOrder.ZYX: return xMatrix.multiplyMatrixMatrix(yMatrix.multiplyMatrixMatrix(zMatrix)); + case AxisOrder.XYZ: + return zMatrix.multiplyMatrixMatrix(yMatrix.multiplyMatrixMatrix(xMatrix)); + case AxisOrder.XZY: + return yMatrix.multiplyMatrixMatrix(zMatrix.multiplyMatrixMatrix(xMatrix)); + case AxisOrder.YXZ: + return zMatrix.multiplyMatrixMatrix(xMatrix.multiplyMatrixMatrix(yMatrix)); + case AxisOrder.YZX: + return xMatrix.multiplyMatrixMatrix(zMatrix.multiplyMatrixMatrix(yMatrix)); + case AxisOrder.ZXY: + return yMatrix.multiplyMatrixMatrix(xMatrix.multiplyMatrixMatrix(zMatrix)); + case AxisOrder.ZYX: + return xMatrix.multiplyMatrixMatrix(yMatrix.multiplyMatrixMatrix(zMatrix)); } } @@ -48,13 +54,16 @@ function testEqualOrderedRotationAngles(ck: Checker, a: OrderedRotationAngles, b function testMultiAngleEquivalence(ck: Checker, xDegrees: number, yDegrees: number, zDegrees: number, treatVectorsAsColumns: boolean) { OrderedRotationAngles.treatVectorsAsColumns = treatVectorsAsColumns; - for (const orderPair of [ - [AxisOrder.XYZ, AxisOrder.ZYX], - [AxisOrder.XZY, AxisOrder.YZX], - [AxisOrder.YXZ, AxisOrder.ZXY], - [AxisOrder.YZX, AxisOrder.XZY], - [AxisOrder.ZXY, AxisOrder.YXZ], - [AxisOrder.ZYX, AxisOrder.XYZ]]) { + for ( + const orderPair of [ + [AxisOrder.XYZ, AxisOrder.ZYX], + [AxisOrder.XZY, AxisOrder.YZX], + [AxisOrder.YXZ, AxisOrder.ZXY], + [AxisOrder.YZX, AxisOrder.XZY], + [AxisOrder.ZXY, AxisOrder.YXZ], + [AxisOrder.ZYX, AxisOrder.XYZ], + ] + ) { const angles = OrderedRotationAngles.createDegrees(xDegrees, yDegrees, zDegrees, orderPair[0]); const angles1 = OrderedRotationAngles.createDegrees(0, 0, 0, orderPair[0]); const angles2 = OrderedRotationAngles.createDegrees(xDegrees, yDegrees, zDegrees, orderPair[0], undefined, angles1); @@ -156,38 +165,40 @@ describe("OrderedRotationAngles", () => { const q = 0.25; const q1 = Math.PI - r; const q2 = primaryRadians * Math.abs(0.7 - factor); - for (const anglesA of [ - // one angle - OrderedRotationAngles.createRadians(r, 0, 0, axisOrder), - OrderedRotationAngles.createRadians(0, r, 0, axisOrder), - OrderedRotationAngles.createRadians(0, 0, r, axisOrder), - // two angles - OrderedRotationAngles.createRadians(r, q, 0, axisOrder), - OrderedRotationAngles.createRadians(q, r, 0, axisOrder), - OrderedRotationAngles.createRadians(0, r, q, axisOrder), - OrderedRotationAngles.createRadians(0, q, r, axisOrder), - OrderedRotationAngles.createRadians(r, 0, q, axisOrder), - OrderedRotationAngles.createRadians(q, 0, r, axisOrder), - OrderedRotationAngles.createRadians(r, q1, 0, axisOrder), - OrderedRotationAngles.createRadians(q1, r, 0, axisOrder), - OrderedRotationAngles.createRadians(0, r, q1, axisOrder), - OrderedRotationAngles.createRadians(0, q1, r, axisOrder), - OrderedRotationAngles.createRadians(q1, 0, r, axisOrder), - OrderedRotationAngles.createRadians(r, 0, q1, axisOrder), - OrderedRotationAngles.createDegrees(0.001, 89.999, 0, axisOrder), - OrderedRotationAngles.createDegrees(89.999, 0.001, 0, axisOrder), - OrderedRotationAngles.createDegrees(0, 0.001, 89.999, axisOrder), - OrderedRotationAngles.createDegrees(0, 89.999, 0.001, axisOrder), - OrderedRotationAngles.createDegrees(0.001, 0, 89.999, axisOrder), - OrderedRotationAngles.createDegrees(89.999, 0, 0.001, axisOrder), - // three angles - OrderedRotationAngles.createRadians(r, q1, q2, axisOrder), - OrderedRotationAngles.createRadians(r, q2, q1, axisOrder), - OrderedRotationAngles.createRadians(q1, r, q2, axisOrder), - OrderedRotationAngles.createRadians(q1, q2, r, axisOrder), - OrderedRotationAngles.createRadians(q2, r, q1, axisOrder), - OrderedRotationAngles.createRadians(q2, q1, r, axisOrder), - ]) { + for ( + const anglesA of [ + // one angle + OrderedRotationAngles.createRadians(r, 0, 0, axisOrder), + OrderedRotationAngles.createRadians(0, r, 0, axisOrder), + OrderedRotationAngles.createRadians(0, 0, r, axisOrder), + // two angles + OrderedRotationAngles.createRadians(r, q, 0, axisOrder), + OrderedRotationAngles.createRadians(q, r, 0, axisOrder), + OrderedRotationAngles.createRadians(0, r, q, axisOrder), + OrderedRotationAngles.createRadians(0, q, r, axisOrder), + OrderedRotationAngles.createRadians(r, 0, q, axisOrder), + OrderedRotationAngles.createRadians(q, 0, r, axisOrder), + OrderedRotationAngles.createRadians(r, q1, 0, axisOrder), + OrderedRotationAngles.createRadians(q1, r, 0, axisOrder), + OrderedRotationAngles.createRadians(0, r, q1, axisOrder), + OrderedRotationAngles.createRadians(0, q1, r, axisOrder), + OrderedRotationAngles.createRadians(q1, 0, r, axisOrder), + OrderedRotationAngles.createRadians(r, 0, q1, axisOrder), + OrderedRotationAngles.createDegrees(0.001, 89.999, 0, axisOrder), + OrderedRotationAngles.createDegrees(89.999, 0.001, 0, axisOrder), + OrderedRotationAngles.createDegrees(0, 0.001, 89.999, axisOrder), + OrderedRotationAngles.createDegrees(0, 89.999, 0.001, axisOrder), + OrderedRotationAngles.createDegrees(0.001, 0, 89.999, axisOrder), + OrderedRotationAngles.createDegrees(89.999, 0, 0.001, axisOrder), + // three angles + OrderedRotationAngles.createRadians(r, q1, q2, axisOrder), + OrderedRotationAngles.createRadians(r, q2, q1, axisOrder), + OrderedRotationAngles.createRadians(q1, r, q2, axisOrder), + OrderedRotationAngles.createRadians(q1, q2, r, axisOrder), + OrderedRotationAngles.createRadians(q2, r, q1, axisOrder), + OrderedRotationAngles.createRadians(q2, q1, r, axisOrder), + ] + ) { const matrixA = anglesA.toMatrix3d(); const anglesB = OrderedRotationAngles.createFromMatrix3d(matrixA, axisOrder); if (ck.testDefined(anglesB)) @@ -223,9 +234,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); let expectedMatrix = Matrix3d.createRowValues( - 1, 0, 0, - 0, angles.xAngle.cos(), -angles.xAngle.sin(), - 0, angles.xAngle.sin(), angles.xAngle.cos(), + 1, + 0, + 0, + 0, + angles.xAngle.cos(), + -angles.xAngle.sin(), + 0, + angles.xAngle.sin(), + angles.xAngle.cos(), ); ck.testMatrix3d(matrix, expectedMatrix); @@ -240,9 +257,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.yAngle.cos(), 0, angles.yAngle.sin(), - 0, 1, 0, - -angles.yAngle.sin(), 0, angles.yAngle.cos(), + angles.yAngle.cos(), + 0, + angles.yAngle.sin(), + 0, + 1, + 0, + -angles.yAngle.sin(), + 0, + angles.yAngle.cos(), ); ck.testMatrix3d(matrix, expectedMatrix); @@ -257,35 +280,59 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.zAngle.cos(), -angles.zAngle.sin(), 0, - angles.zAngle.sin(), angles.zAngle.cos(), 0, - 0, 0, 1, + angles.zAngle.cos(), + -angles.zAngle.sin(), + 0, + angles.zAngle.sin(), + angles.zAngle.cos(), + 0, + 0, + 0, + 1, ); ck.testMatrix3d(matrix, expectedMatrix); // Three Rotations - x = Math.PI / 2, y = 1.16937, z = 0.0349066; // 90, 67, and 2 degrees + x = Math.PI / 2, y = 1.16937, z = 0.0349066; // 90, 67, and 2 degrees // The three classic "base rotation matrixes" (columns-based from) const rX = Matrix3d.createRowValues( - 1, 0, 0, - 0, Math.cos(x), -Math.sin(x), - 0, Math.sin(x), Math.cos(x), + 1, + 0, + 0, + 0, + Math.cos(x), + -Math.sin(x), + 0, + Math.sin(x), + Math.cos(x), ); const rY = Matrix3d.createRowValues( - Math.cos(y), 0, Math.sin(y), - 0, 1, 0, - -Math.sin(y), 0, Math.cos(y), + Math.cos(y), + 0, + Math.sin(y), + 0, + 1, + 0, + -Math.sin(y), + 0, + Math.cos(y), ); const rZ = Matrix3d.createRowValues( - Math.cos(z), -Math.sin(z), 0, - Math.sin(z), Math.cos(z), 0, - 0, 0, 1, + Math.cos(z), + -Math.sin(z), + 0, + Math.sin(z), + Math.cos(z), + 0, + 0, + 0, + 1, ); /** - * Note: for the following checks the AxisOrder is the reverse - * of matrix multiplication because we used columns-based from - */ + * Note: for the following checks the AxisOrder is the reverse + * of matrix multiplication because we used columns-based from + */ // Rotation using XYZ ordering OrderedRotationAngles.createRadians(x, y, z, AxisOrder.XYZ, undefined, angles); angles.toMatrix3d(matrix); @@ -349,9 +396,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); let expectedMatrix = Matrix3d.createRowValues( - 1, 0, 0, - 0, angles.xAngle.cos(), -angles.xAngle.sin(), - 0, angles.xAngle.sin(), angles.xAngle.cos(), + 1, + 0, + 0, + 0, + angles.xAngle.cos(), + -angles.xAngle.sin(), + 0, + angles.xAngle.sin(), + angles.xAngle.cos(), ).transpose(); ck.testMatrix3d(matrix, expectedMatrix); @@ -366,9 +419,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.yAngle.cos(), 0, angles.yAngle.sin(), - 0, 1, 0, - -angles.yAngle.sin(), 0, angles.yAngle.cos(), + angles.yAngle.cos(), + 0, + angles.yAngle.sin(), + 0, + 1, + 0, + -angles.yAngle.sin(), + 0, + angles.yAngle.cos(), ).transpose(); ck.testMatrix3d(matrix, expectedMatrix); @@ -383,35 +442,59 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.zAngle.cos(), -angles.zAngle.sin(), 0, - angles.zAngle.sin(), angles.zAngle.cos(), 0, - 0, 0, 1, + angles.zAngle.cos(), + -angles.zAngle.sin(), + 0, + angles.zAngle.sin(), + angles.zAngle.cos(), + 0, + 0, + 0, + 1, ).transpose(); ck.testMatrix3d(matrix, expectedMatrix); // Three Rotations - x = Math.PI / 4, y = 0.20944, z = 0.436332; // 45, 12, and 25 degrees + x = Math.PI / 4, y = 0.20944, z = 0.436332; // 45, 12, and 25 degrees // The three classic "base rotation matrixes" (column-based from) const rX = Matrix3d.createRowValues( - 1, 0, 0, - 0, Math.cos(x), -Math.sin(x), - 0, Math.sin(x), Math.cos(x), + 1, + 0, + 0, + 0, + Math.cos(x), + -Math.sin(x), + 0, + Math.sin(x), + Math.cos(x), ); const rY = Matrix3d.createRowValues( - Math.cos(y), 0, Math.sin(y), - 0, 1, 0, - -Math.sin(y), 0, Math.cos(y), + Math.cos(y), + 0, + Math.sin(y), + 0, + 1, + 0, + -Math.sin(y), + 0, + Math.cos(y), ); const rZ = Matrix3d.createRowValues( - Math.cos(z), -Math.sin(z), 0, - Math.sin(z), Math.cos(z), 0, - 0, 0, 1, + Math.cos(z), + -Math.sin(z), + 0, + Math.sin(z), + Math.cos(z), + 0, + 0, + 0, + 1, ); /** - * Note: for the following checks the AxisOrder is the reverse - * of matrix multiplication because we used columns-based from - */ + * Note: for the following checks the AxisOrder is the reverse + * of matrix multiplication because we used columns-based from + */ // Rotation using XYZ ordering OrderedRotationAngles.createRadians(x, y, z, AxisOrder.XYZ, undefined, angles); angles.toMatrix3d(matrix); @@ -475,9 +558,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); let expectedMatrix = Matrix3d.createRowValues( - 1, 0, 0, - 0, angles.xAngle.cos(), angles.xAngle.sin(), - 0, -angles.xAngle.sin(), angles.xAngle.cos(), + 1, + 0, + 0, + 0, + angles.xAngle.cos(), + angles.xAngle.sin(), + 0, + -angles.xAngle.sin(), + angles.xAngle.cos(), ); ck.testMatrix3d(matrix, expectedMatrix); @@ -492,9 +581,15 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.yAngle.cos(), 0, -angles.yAngle.sin(), - 0, 1, 0, - angles.yAngle.sin(), 0, angles.yAngle.cos(), + angles.yAngle.cos(), + 0, + -angles.yAngle.sin(), + 0, + 1, + 0, + angles.yAngle.sin(), + 0, + angles.yAngle.cos(), ); ck.testMatrix3d(matrix, expectedMatrix); @@ -509,35 +604,59 @@ describe("OrderedRotationAngles", () => { ); angles.toMatrix3d(matrix); expectedMatrix = Matrix3d.createRowValues( - angles.zAngle.cos(), angles.zAngle.sin(), 0, - -angles.zAngle.sin(), angles.zAngle.cos(), 0, - 0, 0, 1, + angles.zAngle.cos(), + angles.zAngle.sin(), + 0, + -angles.zAngle.sin(), + angles.zAngle.cos(), + 0, + 0, + 0, + 1, ); ck.testMatrix3d(matrix, expectedMatrix); // Three Rotations - x = Math.PI / 3, y = Math.PI, z = 1.91986; // 60, 180, and 110 degrees + x = Math.PI / 3, y = Math.PI, z = 1.91986; // 60, 180, and 110 degrees // Transpose of the three classic "base rotation matrixes" (row-based from) const rX = Matrix3d.createRowValues( - 1, 0, 0, - 0, Math.cos(x), Math.sin(x), - 0, -Math.sin(x), Math.cos(x), + 1, + 0, + 0, + 0, + Math.cos(x), + Math.sin(x), + 0, + -Math.sin(x), + Math.cos(x), ); const rY = Matrix3d.createRowValues( - Math.cos(y), 0, -Math.sin(y), - 0, 1, 0, - Math.sin(y), 0, Math.cos(y), + Math.cos(y), + 0, + -Math.sin(y), + 0, + 1, + 0, + Math.sin(y), + 0, + Math.cos(y), ); const rZ = Matrix3d.createRowValues( - Math.cos(z), Math.sin(z), 0, - -Math.sin(z), Math.cos(z), 0, - 0, 0, 1, + Math.cos(z), + Math.sin(z), + 0, + -Math.sin(z), + Math.cos(z), + 0, + 0, + 0, + 1, ); /** - * Note: for the following checks the AxisOrder is same as - * matrix multiplication because we used columns-based from - */ + * Note: for the following checks the AxisOrder is same as + * matrix multiplication because we used columns-based from + */ // Rotation using XYZ ordering OrderedRotationAngles.createRadians(x, y, z, AxisOrder.XYZ, undefined, angles); angles.toMatrix3d(matrix); @@ -586,12 +705,12 @@ describe("OrderedRotationAngles", () => { const unitY = Vector3d.unitY(); const unitZ = Vector3d.unitZ(); /** - * Confirm that ypr matrix matches OrientedRotationAngles matrix for - * AxisOrder.XYZ - * treatVectorsAsColumns = true - * X = roll, Y = negated pitch, Z = yaw - * xyzRotationIsClockwise = [false, false, false] - */ + * Confirm that ypr matrix matches OrientedRotationAngles matrix for + * AxisOrder.XYZ + * treatVectorsAsColumns = true + * X = roll, Y = negated pitch, Z = yaw + * xyzRotationIsClockwise = [false, false, false] + */ OrderedRotationAngles.treatVectorsAsColumns = true; for (const rollAngle of degreesChoices) { // this is ROLL @@ -599,7 +718,7 @@ describe("OrderedRotationAngles", () => { for (const pitchAngle of degreesChoices) { // this is PITCH const matrixY = Matrix3d.createRotationAroundVector(unitY, pitchAngle)!; - matrixY.transposeInPlace(); // PITCH is NEGATIVE Y + matrixY.transposeInPlace(); // PITCH is NEGATIVE Y for (const yawAngle of degreesChoices) { // this is YAW const matrixZ = Matrix3d.createRotationAroundVector(unitZ, yawAngle)!; @@ -637,12 +756,12 @@ describe("OrderedRotationAngles", () => { const unitY = Vector3d.unitY(); const unitZ = Vector3d.unitZ(); /** - * Confirm that ypr matrix matches OrientedRotationAngles matrix for - * AxisOrder.XYZ - * treatVectorsAsColumns = true - * X = roll, Y = pitch, Z = yaw - * xyzRotationIsClockwise = [false, true, false] - */ + * Confirm that ypr matrix matches OrientedRotationAngles matrix for + * AxisOrder.XYZ + * treatVectorsAsColumns = true + * X = roll, Y = pitch, Z = yaw + * xyzRotationIsClockwise = [false, true, false] + */ OrderedRotationAngles.treatVectorsAsColumns = true; for (const rollAngle of degreesChoices) { // this is ROLL @@ -650,7 +769,7 @@ describe("OrderedRotationAngles", () => { for (const pitchAngle of degreesChoices) { // this is PITCH const matrixY = Matrix3d.createRotationAroundVector(unitY, pitchAngle)!; - matrixY.transposeInPlace(); // PITCH is NEGATIVE Y + matrixY.transposeInPlace(); // PITCH is NEGATIVE Y for (const yawAngle of degreesChoices) { // this is YAW const matrixZ = Matrix3d.createRotationAroundVector(unitZ, yawAngle)!; @@ -700,19 +819,37 @@ describe("OrderedRotationAngles", () => { // The three classic "base rotation matrixes" (column-based from) const rX = Matrix3d.createRowValues( - 1, 0, 0, - 0, Math.cos(x), -Math.sin(x), - 0, Math.sin(x), Math.cos(x), + 1, + 0, + 0, + 0, + Math.cos(x), + -Math.sin(x), + 0, + Math.sin(x), + Math.cos(x), ); const rY = Matrix3d.createRowValues( - Math.cos(y), 0, Math.sin(y), - 0, 1, 0, - -Math.sin(y), 0, Math.cos(y), + Math.cos(y), + 0, + Math.sin(y), + 0, + 1, + 0, + -Math.sin(y), + 0, + Math.cos(y), ); const rZ = Matrix3d.createRowValues( - Math.cos(z), -Math.sin(z), 0, - Math.sin(z), Math.cos(z), 0, - 0, 0, 1, + Math.cos(z), + -Math.sin(z), + 0, + Math.sin(z), + Math.cos(z), + 0, + 0, + 0, + 1, ); // One Rotation (order doesn't matter) @@ -784,19 +921,37 @@ describe("OrderedRotationAngles", () => { // The three classic "base rotation matrixes" (column-based from) const rX = Matrix3d.createRowValues( - 1, 0, 0, - 0, Math.cos(x), -Math.sin(x), - 0, Math.sin(x), Math.cos(x), + 1, + 0, + 0, + 0, + Math.cos(x), + -Math.sin(x), + 0, + Math.sin(x), + Math.cos(x), ); const rY = Matrix3d.createRowValues( - Math.cos(y), 0, Math.sin(y), - 0, 1, 0, - -Math.sin(y), 0, Math.cos(y), + Math.cos(y), + 0, + Math.sin(y), + 0, + 1, + 0, + -Math.sin(y), + 0, + Math.cos(y), ); const rZ = Matrix3d.createRowValues( - Math.cos(z), -Math.sin(z), 0, - Math.sin(z), Math.cos(z), 0, - 0, 0, 1, + Math.cos(z), + -Math.sin(z), + 0, + Math.sin(z), + Math.cos(z), + 0, + 0, + 0, + 1, ); // One Rotation (order doesn't matter) diff --git a/core/geometry/src/test/geometry3d/Plane3dByOriginAndUnitNormal.test.ts b/core/geometry/src/test/geometry3d/Plane3dByOriginAndUnitNormal.test.ts index 0ef6521b1544..fa0af2d65373 100644 --- a/core/geometry/src/test/geometry3d/Plane3dByOriginAndUnitNormal.test.ts +++ b/core/geometry/src/test/geometry3d/Plane3dByOriginAndUnitNormal.test.ts @@ -12,17 +12,20 @@ import { Transform } from "../../geometry3d/Transform"; import { Checker } from "../Checker"; /** Exercise two planes expected to be parallel. */ -function testParallelPair(ck: Checker, +function testParallelPair( + ck: Checker, plane0: Plane3dByOriginAndUnitNormal, planeA: Plane3dByOriginAndUnitNormal, // expected altitude of planeA origin above plane0 origin. - a: number) { + a: number, +) { ck.testParallel(plane0.getNormalRef(), planeA.getNormalRef()); ck.testCoordinate(a, plane0.altitude(planeA.getOriginRef()), "expected altitude"); const f = 0.5; const planeB = Plane3dByOriginAndUnitNormal.create( plane0.getOriginRef().interpolate(f, planeA.getOriginRef()), - plane0.getNormalRef()); + plane0.getNormalRef(), + ); const planeB1 = planeB!.clone(); ck.testCoordinate(planeB1.altitude(plane0.getOriginRef()), -f * a); @@ -31,7 +34,7 @@ function testParallelPair(ck: Checker, ck.testTrue(planeB1.isAlmostEqual(planeB1FromJSON), " clone, json round trip"); const triad = Matrix3d.createRigidHeadsUp(plane0.getNormalRef()); - const pointC = plane0.getOriginRef().plus(triad.multiplyXYZ(2, 4.1, a)); // this should be on planeA but not at its origin. + const pointC = plane0.getOriginRef().plus(triad.multiplyXYZ(2, 4.1, a)); // this should be on planeA but not at its origin. ck.testCoordinate(0, planeA.altitude(pointC)); const pointC0 = plane0.projectPointToPlane(pointC); ck.testCoordinate(0, plane0.altitude(pointC0)); @@ -40,7 +43,6 @@ function testParallelPair(ck: Checker, ck.testCoordinate(0, plane0.velocity(triad.multiplyXY(3, 4)), "in plane vector has zero velocity"); const v = 23.4; ck.testCoordinate(v, plane0.velocity(triad.multiplyXYZ(3, 4, v)), "in plane vector has zero velocity"); - } describe("Plane3dByOriginAndUnitNormal", () => { @@ -104,9 +106,19 @@ describe("Plane3dByOriginAndUnitNormal", () => { ck.testUndefined(failPlane, "plane with null normal"); const plane = Plane3dByOriginAndUnitNormal.createXYPlane(); const plane1 = plane.cloneTransformed(Transform.createRowValues( - 1, 0, 0, 1, - 0, 1, 0, 3, - 0, 0, 0, 1)); + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 3, + 0, + 0, + 0, + 1, + )); ck.testUndefined(plane1, "singular transform of plane"); expect(ck.getNumErrors()).toBe(0); }); @@ -131,5 +143,4 @@ describe("Plane3dByOriginAndUnitNormal", () => { ck.testTrue(planeP.isAlmostEqual(planeB), "createXYAngle into result"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Plane3dByOriginAndVectors.test.ts b/core/geometry/src/test/geometry3d/Plane3dByOriginAndVectors.test.ts index 714d6ba69e33..913ef2bf061a 100644 --- a/core/geometry/src/test/geometry3d/Plane3dByOriginAndVectors.test.ts +++ b/core/geometry/src/test/geometry3d/Plane3dByOriginAndVectors.test.ts @@ -17,37 +17,59 @@ describe("Plane3dByOriginAndVectors", () => { const vectorU = Vector3d.create(5, 2, 1); const vectorV = Vector3d.create(-3, 4, 1); const planeAUV = Plane3dByOriginAndVectors.createOriginAndVectors(pointA, vectorU, vectorV); - const planeAUVR = Plane3dByOriginAndVectors.createOriginAndVectors(pointA, vectorU, vectorV, - Plane3dByOriginAndVectors.createXYPlane()); + const planeAUVR = Plane3dByOriginAndVectors.createOriginAndVectors(pointA, vectorU, vectorV, Plane3dByOriginAndVectors.createXYPlane()); ck.testTrue(planeAUV.isAlmostEqual(planeAUVR), "default create"); const planeX = Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - pointA.x, pointA.y, pointA.z, - vectorU.x, vectorU.y, vectorU.z, - vectorV.x, vectorV.y, vectorV.z); + pointA.x, + pointA.y, + pointA.z, + vectorU.x, + vectorU.y, + vectorU.z, + vectorV.x, + vectorV.y, + vectorV.z, + ); const planeX1 = planeX.clone(); ck.testTrue(planeX1.normalizeInPlace(), "normalizeVectors"); const planeXR = Plane3dByOriginAndVectors.createOriginAndVectorsXYZ( - pointA.x, pointA.y, pointA.z, - vectorU.x, vectorU.y, vectorU.z, - vectorV.x, vectorV.y, vectorV.z, - Plane3dByOriginAndVectors.createXYPlane()); + pointA.x, + pointA.y, + pointA.z, + vectorU.x, + vectorU.y, + vectorU.z, + vectorV.x, + vectorV.y, + vectorV.z, + Plane3dByOriginAndVectors.createXYPlane(), + ); const planeF64 = Plane3dByOriginAndVectors.createOriginAndVectorsArrays( - pointA.toFloat64Array(), vectorU.toFloat64Array(), vectorV.toFloat64Array()); + pointA.toFloat64Array(), + vectorU.toFloat64Array(), + vectorV.toFloat64Array(), + ); const planeF64R = Plane3dByOriginAndVectors.createOriginAndVectorsArrays( - pointA.toFloat64Array(), vectorU.toFloat64Array(), vectorV.toFloat64Array(), - Plane3dByOriginAndVectors.createXYPlane()); + pointA.toFloat64Array(), + vectorU.toFloat64Array(), + vectorV.toFloat64Array(), + Plane3dByOriginAndVectors.createXYPlane(), + ); const planeY = Plane3dByOriginAndVectors.createXYPlane(); planeY.setOriginAndVectors(pointA, vectorU, vectorV); ck.testTrue(planeX.isAlmostEqual(planeY)); - const planeT = Plane3dByOriginAndVectors.createOriginAndTargets(pointA, - pointA.plus(vectorU), pointA.plus(vectorV)); + const planeT = Plane3dByOriginAndVectors.createOriginAndTargets(pointA, pointA.plus(vectorU), pointA.plus(vectorV)); ck.testTrue(planeX.isAlmostEqual(planeT)); - const planeCR = Plane3dByOriginAndVectors.createCapture(pointA.clone(), vectorU.clone(), vectorV.clone(), - Plane3dByOriginAndVectors.createXYPlane()); + const planeCR = Plane3dByOriginAndVectors.createCapture( + pointA.clone(), + vectorU.clone(), + vectorV.clone(), + Plane3dByOriginAndVectors.createXYPlane(), + ); ck.testTrue(planeX.isAlmostEqual(planeCR), "createCapture to result"); ck.testTrue(planeAUV.isAlmostEqual(planeX), "default create"); ck.testTrue(planeX.isAlmostEqual(planeXR)); @@ -71,9 +93,10 @@ describe("Plane3dByOriginAndVectors", () => { ck.testPointer(errorPlane); const errorPlane1 = Plane3dByOriginAndVectors.createOriginAndVectorsWeightedArrays( - new Float64Array([1, 1, 1, 0]), // weight 0 at origin fails !!! + new Float64Array([1, 1, 1, 0]), // weight 0 at origin fails !!! new Float64Array([2, 1, 3, 0]), - new Float64Array([4, 9, 1, 1])); + new Float64Array([4, 9, 1, 1]), + ); ck.testTrue(errorPlane1.isAlmostEqual(Plane3dByOriginAndVectors.createXYPlane())); ck.checkpoint("Plane3dByOriginAndVectors.HelloWorld"); expect(ck.getNumErrors()).toBe(0); @@ -81,10 +104,20 @@ describe("Plane3dByOriginAndVectors", () => { it("CreateFromTransform", () => { const ck = new Checker(); const transform = Transform.createRowValues( - 20, 1, 2, 4, - 3, 10, 5, 9, - -1.5, 0.2, 30, 7); - const plane0 = Plane3dByOriginAndVectors.createXYPlane(); // to be reused. + 20, + 1, + 2, + 4, + 3, + 10, + 5, + 9, + -1.5, + 0.2, + 30, + 7, + ); + const plane0 = Plane3dByOriginAndVectors.createXYPlane(); // to be reused. const a = 1.5; const b = 3.9; const plane1 = Plane3dByOriginAndVectors.createFromTransformColumnsXYAndLengths(transform, a, b); @@ -104,7 +137,6 @@ describe("Plane3dByOriginAndVectors", () => { ck.testVector3d(plane3.vectorU, transform.matrix.columnX()); ck.testVector3d(plane3.vectorV, transform.matrix.columnY()); expect(ck.getNumErrors()).toBe(0); - }); it("Orthogonalize", () => { const ck = new Checker(); @@ -119,7 +151,5 @@ describe("Plane3dByOriginAndVectors", () => { const singularPlane = Plane3dByOriginAndVectors.createOriginAndVectorsXYZ(3, 2, 4, 1, 2, 3, 1, 2, 3); ck.testUndefined(singularPlane.unitNormalRay(), "Singular plane unit normal fails"); expect(ck.getNumErrors()).toBe(0); - }); - }); diff --git a/core/geometry/src/test/geometry3d/PlaneAltitudeEvaluators.test.ts b/core/geometry/src/test/geometry3d/PlaneAltitudeEvaluators.test.ts index 97ce57275124..6182a6a290ce 100644 --- a/core/geometry/src/test/geometry3d/PlaneAltitudeEvaluators.test.ts +++ b/core/geometry/src/test/geometry3d/PlaneAltitudeEvaluators.test.ts @@ -4,16 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { Plane3dByOriginAndVectors } from "../../geometry3d/Plane3dByOriginAndVectors"; +import { ClipPlane } from "../../clipping/ClipPlane"; import { AxisOrder } from "../../Geometry"; import { Matrix3d } from "../../geometry3d/Matrix3d"; +import { Plane3d } from "../../geometry3d/Plane3d"; import { Plane3dByOriginAndUnitNormal } from "../../geometry3d/Plane3dByOriginAndUnitNormal"; +import { Plane3dByOriginAndVectors } from "../../geometry3d/Plane3dByOriginAndVectors"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { Checker } from "../Checker"; -import { Sample } from "../../serialization/GeometrySamples"; import { Point4d } from "../../geometry4d/Point4d"; -import { ClipPlane } from "../../clipping/ClipPlane"; -import { Plane3d } from "../../geometry3d/Plane3d"; +import { Sample } from "../../serialization/GeometrySamples"; +import { Checker } from "../Checker"; /** * Check that planeA and planeB have matched PlaneAltitudeEvaluator results (other than bit loss) @@ -52,9 +52,7 @@ describe("PlaneEvaluator", () => { it("HelloWorld", () => { const ck = new Checker(); const pointA = Point3d.create(1.2, 3); - for (const normal of [Vector3d.createNormalized(0, 0, 1)!, - Vector3d.createNormalized(2, -1, 4)!]) { - + for (const normal of [Vector3d.createNormalized(0, 0, 1)!, Vector3d.createNormalized(2, -1, 4)!]) { const matrix = Matrix3d.createRigidHeadsUp(normal, AxisOrder.ZXY); const vectorU = matrix.columnX(); const vectorV = matrix.columnY(); @@ -92,5 +90,4 @@ describe("PlaneEvaluator", () => { } expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Point2dVector2d.test.ts b/core/geometry/src/test/geometry3d/Point2dVector2d.test.ts index c659fef908ff..6e9630b0567a 100644 --- a/core/geometry/src/test/geometry3d/Point2dVector2d.test.ts +++ b/core/geometry/src/test/geometry3d/Point2dVector2d.test.ts @@ -140,16 +140,17 @@ describe("Point2d", () => { "cross product used consistently for reverse order signed angle", ); /* - * ccw angle is positive and cw is negative. cross product is positive if thumb points up - * in the right hand rule and is negative if thumb points down in the right hand rule. - */ + * ccw angle is positive and cw is negative. cross product is positive if thumb points up + * in the right hand rule and is negative if thumb points down in the right hand rule. + */ ck.testLT(0, vectorI.crossProduct(vectorJ) * signedAngle.radians, "cross product sign agrees with signed angle"); const vectorQ = Vector2d.create(1.2312321, 4.23); const vectorR = Vector2d.create(-0.23428, 1.231); ck.testPoint2d( origin.plus3Scaled(vectorI, s1, vectorJ, s2, vectorQ, s3), - origin.plusScaled(vectorI, s1).plus2Scaled(vectorJ, s2, vectorQ, s3)); + origin.plusScaled(vectorI, s1).plus2Scaled(vectorJ, s2, vectorQ, s3), + ); ck.testVector2d( vectorR.plus3Scaled(vectorI, s1, vectorJ, s2, vectorQ, s3), vectorR.plusScaled(vectorI, s1).plus2Scaled(vectorJ, s2, vectorQ, s3), diff --git a/core/geometry/src/test/geometry3d/Point3dVector3d.test.ts b/core/geometry/src/test/geometry3d/Point3dVector3d.test.ts index 1bf9398e1193..be9260b2c6e5 100644 --- a/core/geometry/src/test/geometry3d/Point3dVector3d.test.ts +++ b/core/geometry/src/test/geometry3d/Point3dVector3d.test.ts @@ -110,11 +110,13 @@ describe("Point3d", () => { ck.testAngleNoShift( vectorI.angleTo(vectorJ), signedAngle, - "cross product used consistently for signed angle"); + "cross product used consistently for signed angle", + ); ck.testCoordinate( vectorJ.angleTo(vectorI).radians, signedAngle.radians, - "cross product used consistently for reverse order signed angle"); + "cross product used consistently for reverse order signed angle", + ); const vectorQ = vectorIJcross.plus(vectorI.scale(0.219)); ck.testVector3d(vectorJ, vectorI.plus(vectorI.vectorTo(vectorJ))); @@ -630,26 +632,14 @@ describe("Geometry", () => { const axisX: AxisIndex = AxisIndex.X; const axisY: AxisIndex = AxisIndex.Y; const axisZ: AxisIndex = AxisIndex.Z; - ck.testExactNumber(AxisOrder.XYZ, - Geometry.axisIndexToRightHandedAxisOrder(axisX), "X==>XYZ", - ); - ck.testExactNumber(AxisOrder.YZX, - Geometry.axisIndexToRightHandedAxisOrder(axisY), "Y==>YZX", - ); - ck.testExactNumber(AxisOrder.ZXY, - Geometry.axisIndexToRightHandedAxisOrder(axisZ), "X==>ZXY", - ); + ck.testExactNumber(AxisOrder.XYZ, Geometry.axisIndexToRightHandedAxisOrder(axisX), "X==>XYZ"); + ck.testExactNumber(AxisOrder.YZX, Geometry.axisIndexToRightHandedAxisOrder(axisY), "Y==>YZX"); + ck.testExactNumber(AxisOrder.ZXY, Geometry.axisIndexToRightHandedAxisOrder(axisZ), "X==>ZXY"); for (const phase of [0, 1, 2, 500, -10, -8, -2, -1]) { - ck.testExactNumber(AxisOrder.XYZ, - Geometry.axisIndexToRightHandedAxisOrder(3 * phase), "X==>XYZ", - ); - ck.testExactNumber(AxisOrder.YZX, - Geometry.axisIndexToRightHandedAxisOrder(3 * phase + 1), "Y==>YZX", - ); - ck.testExactNumber(AxisOrder.ZXY, - Geometry.axisIndexToRightHandedAxisOrder(3 * phase + 2), "X==>ZXY", - ); + ck.testExactNumber(AxisOrder.XYZ, Geometry.axisIndexToRightHandedAxisOrder(3 * phase), "X==>XYZ"); + ck.testExactNumber(AxisOrder.YZX, Geometry.axisIndexToRightHandedAxisOrder(3 * phase + 1), "Y==>YZX"); + ck.testExactNumber(AxisOrder.ZXY, Geometry.axisIndexToRightHandedAxisOrder(3 * phase + 2), "X==>ZXY"); for (const baseAxis of [0, 1, 2]) { const axis = phase * 3 + baseAxis; ck.testExactNumber(baseAxis, Geometry.cyclic3dAxis(axis), "Cyclic axis reduction"); diff --git a/core/geometry/src/test/geometry3d/PointHelper.test.ts b/core/geometry/src/test/geometry3d/PointHelper.test.ts index 9863aad71842..46f1d31b9e76 100644 --- a/core/geometry/src/test/geometry3d/PointHelper.test.ts +++ b/core/geometry/src/test/geometry3d/PointHelper.test.ts @@ -47,10 +47,13 @@ describe("FrameBuilder", () => { const builder = new FrameBuilder(); ck.testFalse(builder.hasOrigin, "frameBuilder.hasOrigin at start"); - for (const points of [ - [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0)], [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), - /* */ Point3d.create(1, 1, 0)], [Point3d.create(1, 2, -1), Point3d.create(1, 3, 5), Point3d.create(-2, 1, 7)], - ]) { + for ( + const points of [ + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 1, 0)], + [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), /* */ Point3d.create(1, 1, 0)], + [Point3d.create(1, 2, -1), Point3d.create(1, 3, 5), Point3d.create(-2, 1, 7)], + ] + ) { builder.clear(); const point0 = points[0]; const point1 = points[1]; @@ -71,8 +74,10 @@ describe("FrameBuilder", () => { builder.announcePoint(point2); ck.testUndefined(builder.getValidatedFrame(true), "frame in progress"); const rFrame = builder.getValidatedFrame(false); - if (ck.testPointer(rFrame, "expect right handed frame") && rFrame - && ck.testBoolean(true, rFrame.matrix.isRigid(), "good frame")) { + if ( + ck.testPointer(rFrame, "expect right handed frame") && rFrame + && ck.testBoolean(true, rFrame.matrix.isRigid(), "good frame") + ) { const inverse = rFrame.inverse(); if (ck.testPointer(inverse, "invertible frame") && inverse) { const product = rFrame.multiplyTransformTransform(inverse); @@ -96,10 +101,20 @@ describe("FrameBuilder", () => { it("createFrameWithCCWPolygon", () => { const ck = new Checker(); - ck.testUndefined(FrameBuilder.createFrameWithCCWPolygon([ - Point3d.create(1, 2, 3)]), "detect incomplete frame data"); - ck.testUndefined(FrameBuilder.createFrameWithCCWPolygon([ - Point3d.create(1, 2, 3), Point3d.create(1, 2, 3), Point3d.create(1, 2, 3)]), "detect singular frame data"); + ck.testUndefined( + FrameBuilder.createFrameWithCCWPolygon([ + Point3d.create(1, 2, 3), + ]), + "detect incomplete frame data", + ); + ck.testUndefined( + FrameBuilder.createFrameWithCCWPolygon([ + Point3d.create(1, 2, 3), + Point3d.create(1, 2, 3), + Point3d.create(1, 2, 3), + ]), + "detect singular frame data", + ); const triangle0 = [Point3d.create(1, 0), Point3d.create(0, 1), Point3d.create(0, 0)]; const triangle1 = Point3dArray.clonePoint3dArray(triangle0); @@ -136,7 +151,6 @@ describe("FrameBuilder", () => { ck.testExactNumber(0, emptyArray.length); expect(ck.getNumErrors()).toBe(0); }); - }); // ASSUME pointsA is planar with at least 3 points, and first turn is left. @@ -158,9 +172,11 @@ function testCentroidNormal(ck: Checker, pointsA: Point3d[], expectedArea: numbe PolygonOps.areaNormalGo(pointsQ, normalQ); ck.testVector3d(normalC, normalQ); const ray = PolygonOps.centroidAreaNormal(pointsB); - if (ck.testParallel(normalB, normalC, "polygon normal", transform) + if ( + ck.testParallel(normalB, normalC, "polygon normal", transform) && ck.testCoordinate(expectedArea, normalC.magnitude()) - && ck.testPointer(ray, "area computed") && ray && ray.a) + && ck.testPointer(ray, "area computed") && ray && ray.a + ) ck.testCoordinate(expectedArea, ray.a); } } @@ -191,10 +207,7 @@ describe("MomentData.HelloWorld", () => { // Test undefined/empty returns const mData = MomentData.pointsToPrincipalAxes([])!; ck.testTrue(mData.origin.isAlmostZero); - const tempMatrix = Matrix4d.createRowValues(1, 1, 1, 0, - 1, 1, 1, 0, - 1, 1, 1, 0, - 1, 1, 1, 0); + const tempMatrix = Matrix4d.createRowValues(1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0); ck.testUndefined(MomentData.inertiaProductsToPrincipalAxes(Point3d.create(1, 2, 3), tempMatrix)); mData.origin = Point3d.create(1, 2, 3); mData.clearSums(); @@ -243,14 +256,15 @@ describe("MomentData.HelloWorld", () => { const principalZ = moments.localToWorldMap.matrix.columnZ(); ck.testTrue(principalZ.isPerpendicularTo(axes0.columnX()), "principal Z perp X"); ck.testTrue(principalZ.isPerpendicularTo(axes0.columnY()), "principal Z perp Z"); - ck.testCoordinate(Math.max(radiusA, radiusB) / Math.min(radiusA, radiusB), + ck.testCoordinate( + Math.max(radiusA, radiusB) / Math.min(radiusA, radiusB), moments.radiusOfGyration.y / moments.radiusOfGyration.x, - "Radii for Symmetric points on ellipse scale as axis lengths"); + "Radii for Symmetric points on ellipse scale as axis lengths", + ); if (Geometry.isAlmostEqualNumber(radiusA, radiusB)) { ck.testCoordinate(radiusA, moments.radiusOfGyration.z, "Circle radius Of gyration is radius"); // extra call for debugger . . . MomentData.pointsToPrincipalAxes(ls.points)!; - } } } @@ -286,7 +300,8 @@ describe("PolygonOps", () => { Point2d.create(ax1, ay), Point2d.create(ax1, 8), Point2d.create(ax0, 8), - Point2d.create(ax0, 0)]; + Point2d.create(ax0, 0), + ]; const points3d = []; for (const p of points) points3d.push(Point3d.create(p.x, p.y)); @@ -380,7 +395,7 @@ describe("PolygonOps", () => { const perpendicularSign = [1, 0, -1]; const perpendicularFraction = 0.01; - for (let node0 = faceSeed; ;) { + for (let node0 = faceSeed;;) { node0 = node0.faceSuccessor; for (const v of perpendicularSign) { const point = node0.fractionAlongAndPerpendicularToPoint2d(0.3, v * perpendicularFraction); @@ -409,7 +424,7 @@ describe("PolygonOps", () => { const perpendicularSign = [1, -1]; const perpendicularFraction = 0.01; - for (let node0 = faceSeed; ;) { + for (let node0 = faceSeed;;) { node0 = node0.faceSuccessor; for (const v of perpendicularSign) { const point = node0.fractionAlongAndPerpendicularToPoint2d(0.3, v * perpendicularFraction); @@ -428,7 +443,7 @@ describe("PolygonOps", () => { const ck = new Checker(); const testPoint = Point3d.createZero(); let points = [Point3d.create(1, 1), Point3d.create(-1, 1), testPoint]; - const rotate = (arr: Array, n = 1) => [...arr.slice(n, arr.length), ...arr.slice(0, n)]; + const rotate = (arr: Array, n = 1) => [...arr.slice(n, arr.length), ...arr.slice(0, n)]; const testVertexHit = (testPt: XAndY, pts: Point3d[]) => { const result = PolygonOps.classifyPointInPolygon(testPt.x, testPt.y, pts); if (ck.testDefined(result, "classification successful")) @@ -495,14 +510,18 @@ describe("Point3dArray", () => { it("MiscArrayOps", () => { const ck = new Checker(); const pointsA = Sample.createFractalDiamondConvexPattern(1, -0.5); - const frame = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!); + const frame = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!, + ); frame.multiplyPoint3dArrayInPlace(pointsA); const map = FrameBuilder.createRightHandedLocalToWorld(pointsA); if (ck.testPointer(map, "Right Handed Map") && map) { const plane = Plane3dByOriginAndUnitNormal.create( - map.getOrigin(), map.matrix.columnZ())!; + map.getOrigin(), + map.matrix.columnZ(), + )!; ck.testTrue(Point3dArray.isCloseToPlane(pointsA, plane), "points in plane of frame"); } @@ -538,8 +557,10 @@ describe("Point3dArray", () => { it("Point4dArray", () => { const ck = new Checker(); const pointsA = Sample.createFractalDiamondConvexPattern(1, -0.5); - const frame = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!); + const frame = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(0.3, -0.2, 1.2), Angle.createDegrees(15.7))!, + ); frame.multiplyPoint3dArrayInPlace(pointsA); const weights = []; const amplitude = 0.25; @@ -613,7 +634,8 @@ describe("Point3dArray", () => { Point2d.create(8, b), Point2d.create(a, b), Point2d.create(a, 6), - Point2d.create(0, 6)]; + Point2d.create(0, 6), + ]; for (const p of polygon) { ck.testExactNumber(0, PolygonOps.classifyPointInPolygon(p.x, p.y, polygon)!); } @@ -634,7 +656,8 @@ describe("Point3dArray", () => { polygon[2], polygon[3], polygon[4], - polygon[5]]; + polygon[5], + ]; ck.testExactNumber(1, PolygonOps.classifyPointInPolygon(pointQ.x, pointQ.y, polygonQ)!); ck.testExactNumber(1, PolygonOps.classifyPointInPolygon(pointQ.x, pointQ.y, polygonQ)!); expect(ck.getNumErrors()).toBe(0); @@ -643,13 +666,28 @@ describe("Point3dArray", () => { it("PolylineLength", () => { const ck = new Checker(); const packedPoints = [ - 0, 0, 0, - 2, 0, 0, - 2, 2, 0, - 2, 2, 2, - 0, 2, 2, - 0, 2, 0, - 0, 0, 0]; + 0, + 0, + 0, + 2, + 0, + 0, + 2, + 2, + 0, + 2, + 2, + 2, + 0, + 2, + 2, + 0, + 2, + 0, + 0, + 0, + 0, + ]; const packed64 = new Float64Array(packedPoints); const points = Point3dArray.unpackNumbersToPoint3dArray(packed64); @@ -801,11 +839,11 @@ describe("Point3dArray", () => { const ck = new Checker(); const pointsA = [Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), Point3d.create(0, 4, 0)]; const pointsC = pointsA.map((xyz: Point3d) => xyz.clone()); - pointsC.push(Point3d.create(0, 2, 0)); // more points, same normal and area!!! - pointsC.push(Point3d.create(0, 1, 0)); // more points, same normal and area!!! + pointsC.push(Point3d.create(0, 2, 0)); // more points, same normal and area!!! + pointsC.push(Point3d.create(0, 1, 0)); // more points, same normal and area!!! const pointsB = Point3dArray.clonePoint3dArray(pointsA); - pointsB.push(pointsB[0].clone()); // degenerate quad !!!! + pointsB.push(pointsB[0].clone()); // degenerate quad !!!! ck.testExactNumber(3, Point2dArray.pointCountExcludingTrailingWraparound(pointsA)); // single point ... @@ -862,7 +900,6 @@ function compareAreaData(ck: Checker, polygonA: Point3d[], polygonB: Point3d[] | } describe("PolygonAreas", () => { - it("TriangleVariants", () => { const ck = new Checker(); const triangle000 = Sample.createTriangleWithSplitEdges(0, 0, 0); @@ -926,24 +963,36 @@ describe("PolygonAreas", () => { ]; const centroidA = PolygonOps.centroidAreaNormal(pointA)!; GeometryCoreTestIO.captureGeometry(allGeometry, Loop.createPolygon(pointA)); - GeometryCoreTestIO.captureGeometry(allGeometry, Arc3d.createCenterNormalRadius(centroidA.origin, centroidA.direction, equivalentCircleRadius(centroidA))); + GeometryCoreTestIO.captureGeometry( + allGeometry, + Arc3d.createCenterNormalRadius(centroidA.origin, centroidA.direction, equivalentCircleRadius(centroidA)), + ); GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(centroidA.origin, centroidA.origin.plus(centroidA.direction))); const a = 2.0; const scaleTransform = Transform.createFixedPointAndMatrix(centroidA.origin, Matrix3d.createScale(a, a, a)); const pointB = scaleTransform.multiplyPoint3dArray(pointA); const centroidB = PolygonOps.centroidAreaNormal(pointB)!; GeometryCoreTestIO.captureGeometry(allGeometry, Loop.createPolygon(pointB)); - GeometryCoreTestIO.captureGeometry(allGeometry, Arc3d.createCenterNormalRadius(centroidB.origin, centroidB.direction, equivalentCircleRadius(centroidB))); + GeometryCoreTestIO.captureGeometry( + allGeometry, + Arc3d.createCenterNormalRadius(centroidB.origin, centroidB.direction, equivalentCircleRadius(centroidB)), + ); ck.testPoint3d(centroidA.origin, centroidB.origin, "origin is invariant after scale around origin"); ck.testVector3d(centroidA.direction, centroidB.direction, "origin is invariant after scale around origin"); ck.testCoordinate(a * a * centroidA.a!, centroidB.a!, "area scales"); - const rotationTransform = Transform.createFixedPointAndMatrix(Point3d.create(0, 1, 3), Matrix3d.createRotationAroundVector(Vector3d.create(2, 3, 1), Angle.createDegrees(45.0))!); + const rotationTransform = Transform.createFixedPointAndMatrix( + Point3d.create(0, 1, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(2, 3, 1), Angle.createDegrees(45.0))!, + ); const pointC = rotationTransform.multiplyPoint3dArray(pointA); const centroidC = PolygonOps.centroidAreaNormal(pointC)!; const centroidC1 = centroidA.cloneTransformed(rotationTransform); GeometryCoreTestIO.captureGeometry(allGeometry, Loop.createPolygon(pointC)); - GeometryCoreTestIO.captureGeometry(allGeometry, Arc3d.createCenterNormalRadius(centroidC.origin, centroidC.direction, equivalentCircleRadius(centroidC))); + GeometryCoreTestIO.captureGeometry( + allGeometry, + Arc3d.createCenterNormalRadius(centroidC.origin, centroidC.direction, equivalentCircleRadius(centroidC)), + ); ck.testPoint3d(centroidC.origin, centroidC1.origin); ck.testVector3d(centroidC.direction, centroidC1.direction); ck.testCoordinate((centroidA as any).a, (centroidC as any).a); @@ -1060,7 +1109,6 @@ describe("PolygonAreas", () => { for (const x of q) ck.testExactNumber(data10[k++], x); } - } const numPerRowB = 4; const leafB = 3; @@ -1172,7 +1220,6 @@ describe("PolygonAreas", () => { } expect(ck.getNumErrors()).toBe(0); }); - }); // coverage missing from other tests @@ -1187,7 +1234,10 @@ describe("PointHelperCoverage", () => { const testXYZPropsArray = (a: XYZProps[]) => { const aNumberArray = Point3dArray.cloneXYZPropsAsNumberArray(a); - ck.testTrue(Array.isArray(aNumberArray) && aNumberArray.length > 0 && Array.isArray(aNumberArray[0]), "cloneXYZPropsAsNumberArray returns a 2d array"); + ck.testTrue( + Array.isArray(aNumberArray) && aNumberArray.length > 0 && Array.isArray(aNumberArray[0]), + "cloneXYZPropsAsNumberArray returns a 2d array", + ); ck.testExactNumber(aNumberArray.length, a.length, "cloneXYZPropsAsNumberArray returns outer array of expected length"); for (let i = 0; i < aNumberArray.length; ++i) { ck.testExactNumber(aNumberArray[i].length, 3, "cloneXYZPropsAsNumberArray returns inner arrays of length 3"); @@ -1206,7 +1256,7 @@ describe("PointHelperCoverage", () => { const indexA = 0; const indexC = xyz.length - 1; const distToUnboundedAC = 5; - const distFromOutlierToBoundedAC = 5 * Math.sqrt(2); // indices 1 and 3 are outliers (project outside bounded AC) + const distFromOutlierToBoundedAC = 5 * Math.sqrt(2); // indices 1 and 3 are outliers (project outside bounded AC) for (const extrapolate of [true, false]) { for (const indexB of [1, 2, 3]) { dist = Point3dArray.distanceIndexedPointBToSegmentAC(xyz, indexA, indexB, indexC, extrapolate); @@ -1221,7 +1271,7 @@ describe("PointHelperCoverage", () => { const hull: Point3d[] = []; const interior: Point3d[] = []; - xyz.push(Point3d.create(1, 1, 1)); // add a (second) point inside the hull + xyz.push(Point3d.create(1, 1, 1)); // add a (second) point inside the hull Point3dArray.computeConvexHullXY(xyz, hull, interior, true); if (ck.testExactNumber(2, interior.length, "computeConvexHullXY returned expected number of interior points")) { ck.testTrue(interior.find((p) => p.isExactEqual(xyz[2])) !== undefined, "computeConvexHullXY returned expected interior point"); @@ -1235,7 +1285,7 @@ describe("PointHelperCoverage", () => { it("Point4dArray", () => { const ck = new Checker(); const data = [0, 1, 2, 3, 4, 5]; - const points = []; // arrays of 2 points + const points = []; // arrays of 2 points points.push([Point3d.create(data[0], data[1], data[2]), Point3d.create(data[3], data[4], data[5])]); points.push(new Float64Array(data)); points.push(data); @@ -1247,7 +1297,7 @@ describe("PointHelperCoverage", () => { weights.push(w); weights.push(new Float64Array(w)); } - const data1 = [0, 1, 2, 1, 3, 4, 5, 1]; // with "weights" + const data1 = [0, 1, 2, 1, 3, 4, 5, 1]; // with "weights" const result = new Float64Array(data1.length); const shortResult = new Float64Array(data1.length - 1); let packed: Float64Array | undefined; @@ -1257,7 +1307,10 @@ describe("PointHelperCoverage", () => { ck.testTrue(NumberArray.isExactEqual(packed, data1), "packPointsAndWeightsToFloat64Array returns expected array"); packed = Point4dArray.packPointsAndWeightsToFloat64Array(pointArray, [1, 1], shortResult); - ck.testTrue(packed !== undefined && packed !== shortResult, "packPointsAndWeightsToFloat64Array with insufficiently allocated result argument returns new array"); + ck.testTrue( + packed !== undefined && packed !== shortResult, + "packPointsAndWeightsToFloat64Array with insufficiently allocated result argument returns new array", + ); ck.testTrue(NumberArray.isExactEqual(packed, data1), "packPointsAndWeightsToFloat64Array returns expected array"); for (const weightArray of weights) { diff --git a/core/geometry/src/test/geometry3d/PolygonOps.test.ts b/core/geometry/src/test/geometry3d/PolygonOps.test.ts index 183486e3ce75..423de040a980 100644 --- a/core/geometry/src/test/geometry3d/PolygonOps.test.ts +++ b/core/geometry/src/test/geometry3d/PolygonOps.test.ts @@ -79,7 +79,6 @@ describe("PolygonOps", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "PolygonOps", "SortOuterAndHoleLoopsXY.DeepNest"); expect(ck.getNumErrors()).toBe(0); - }); it("SortOuterAndHoleLoopsXY.DeepAbuttingNest", () => { @@ -125,7 +124,6 @@ describe("PolygonOps", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "PolygonOps", "SortOuterAndHoleLoopsXY.DeepAbuttingNest"); expect(ck.getNumErrors()).toBe(0); - }); it("SortOuterAndHoleLoopsXY.ManyHoles", () => { @@ -147,7 +145,7 @@ describe("PolygonOps", () => { const holeRange = Range2d.createXYXY(xx, yy, xx + a, yy + a); holeRange.scaleAboutCenterInPlace(0.9); loops.push(makeLoop(holeRange, true)); - const numHoleA = (i % 3); + const numHoleA = i % 3; for (let k = 0; k < numHoleA; k++) { holeRange.scaleAboutCenterInPlace(0.8); loops.push(makeLoop(holeRange, true)); @@ -177,7 +175,6 @@ describe("PolygonOps", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "PolygonOps", "SortOuterAndHoleLoopsXY.ManyHoles"); expect(ck.getNumErrors()).toBe(0); - }); it("SortablePolygon.LoopToPolygon", () => { @@ -230,7 +227,7 @@ describe("PolygonOps", () => { const testPt = Point3d.create(xCoord, yCoord); testPts.push(testPt); const startPt = Point3d.createAdd2Scaled(testPt, 1.0, deltaV, -Geometry.hypotenuseSquaredXY(xCoord, yCoord)); - const endPt = Point3d.createAdd2Scaled(startPt, 1.0, deltaV, 1.0); // segment parameter is arc length + const endPt = Point3d.createAdd2Scaled(startPt, 1.0, deltaV, 1.0); // segment parameter is arc length testSegments.push(LineSegment3d.create(startPt, endPt)); } } @@ -254,8 +251,17 @@ describe("PolygonOps", () => { if (ck.testTrue(loc.isValid, "found ray intersection")) { ck.testPoint3d(testPts[i], loc.point, "intersection point as expected"); ck.testCoordinate(testPts[i].distance(testSegments[i].point0Ref), loc.a, "intersection parameter along ray as expected"); - if (ck.testTrue(loc.closestEdgeIndex >= 0 && loc.closestEdgeIndex < polygon.length && loc.closestEdgeParam >= 0.0 && loc.closestEdgeParam <= 1.0, "found edge projection")) { - const projPt = polygonCarrier.interpolateIndexIndex(loc.closestEdgeIndex, loc.closestEdgeParam, (loc.closestEdgeIndex + 1) % polygon.length)!; + if ( + ck.testTrue( + loc.closestEdgeIndex >= 0 && loc.closestEdgeIndex < polygon.length && loc.closestEdgeParam >= 0.0 && loc.closestEdgeParam <= 1.0, + "found edge projection", + ) + ) { + const projPt = polygonCarrier.interpolateIndexIndex( + loc.closestEdgeIndex, + loc.closestEdgeParam, + (loc.closestEdgeIndex + 1) % polygon.length, + )!; GeometryCoreTestIO.captureCloneGeometry(allGeometry, LineString3d.create([testPts[i], projPt]), x0); } if (isConvex) { @@ -285,14 +291,46 @@ describe("PolygonOps", () => { const allGeometry: GeometryQuery[] = []; const xDelta = 5; - const convexPolygon = [Point3d.create(-2, -1), Point3d.create(-2, 0), Point3d.create(-2, 1), Point3d.create(-1, 2), Point3d.create(0, 2), Point3d.create(1, 2), Point3d.create(2, 2), Point3d.create(1, -1), Point3d.create(0, -2)]; + const convexPolygon = [ + Point3d.create(-2, -1), + Point3d.create(-2, 0), + Point3d.create(-2, 1), + Point3d.create(-1, 2), + Point3d.create(0, 2), + Point3d.create(1, 2), + Point3d.create(2, 2), + Point3d.create(1, -1), + Point3d.create(0, -2), + ]; convexPolygon.push(convexPolygon[0].clone()); // closure point for coverage and display testPolygonRayIntersection(ck, allGeometry, convexPolygon); - const convexPolygonWithDegenerateEdges = [Point3d.create(-2, -1), Point3d.create(-2, -1), Point3d.create(-2, 0), Point3d.create(-2, 0), Point3d.create(-2, 1), Point3d.create(-1, 2), Point3d.create(0, 2), Point3d.create(2, 2), Point3d.create(1, -1), Point3d.create(0, -2)]; + const convexPolygonWithDegenerateEdges = [ + Point3d.create(-2, -1), + Point3d.create(-2, -1), + Point3d.create(-2, 0), + Point3d.create(-2, 0), + Point3d.create(-2, 1), + Point3d.create(-1, 2), + Point3d.create(0, 2), + Point3d.create(2, 2), + Point3d.create(1, -1), + Point3d.create(0, -2), + ]; testPolygonRayIntersection(ck, allGeometry, convexPolygonWithDegenerateEdges); - const nonConvexPolygon = [Point3d.create(-2, -1), Point3d.create(-2, 0), Point3d.create(-2, 1), Point3d.create(-1, 2), Point3d.create(0, 2), Point3d.create(2, 2), Point3d.create(1, 1), Point3d.create(1, -1), Point3d.create(0, -2), Point3d.create(-1, 0)]; + const nonConvexPolygon = [ + Point3d.create(-2, -1), + Point3d.create(-2, 0), + Point3d.create(-2, 1), + Point3d.create(-1, 2), + Point3d.create(0, 2), + Point3d.create(2, 2), + Point3d.create(1, 1), + Point3d.create(1, -1), + Point3d.create(0, -2), + Point3d.create(-1, 0), + ]; testPolygonRayIntersection(ck, allGeometry, nonConvexPolygon, xDelta); const degeneratePolygon = [Point3d.create(-2, -1), Point3d.create(-2, 0), Point3d.create(-2, 1)]; @@ -321,7 +359,13 @@ describe("PolygonOps", () => { const capturePolygonWithClosure = (points: GrowableXYZArray, z0: number = 0) => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, points, x0, y0, z0); if (points.length > 1) - GeometryCoreTestIO.captureCloneGeometry(allGeometry, [points.getPoint3dAtUncheckedPointIndex(0), points.getPoint3dAtUncheckedPointIndex(points.length - 1)], x0, y0, z0); + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, + [points.getPoint3dAtUncheckedPointIndex(0), points.getPoint3dAtUncheckedPointIndex(points.length - 1)], + x0, + y0, + z0, + ); }; // closest approach is from mid edge1 of triangle A to .25 on edge 0 of triangle B. @@ -335,7 +379,7 @@ describe("PolygonOps", () => { const iB1 = Geometry.cyclic3dAxis(iB0 + 1); const iB2 = Geometry.cyclic3dAxis(iB0 + 2); const polygonB = GrowableXYZArray.create([triangleB[iB0], triangleB[iB1], triangleB[iB2]]); - const approach = PolygonOps.closestApproach(polygonA, polygonB); // this test assumes closest approaches at boundaries + const approach = PolygonOps.closestApproach(polygonA, polygonB); // this test assumes closest approaches at boundaries capturePolygonWithClosure(polygonA); capturePolygonWithClosure(polygonB); if (ck.testDefined(approach, "result from polygon approach")) { @@ -387,7 +431,11 @@ describe("PolygonOps", () => { ck.testPoint3d(pldPairB.detailA.point, pldPairC.detailB.point, "PolygonLocationDetailPair.swapDetails A"); ck.testPoint3d(pldPairB.detailB.point, pldPairC.detailA.point, "PolygonLocationDetailPair.swapDetails B"); - ck.testExactNumber(PolygonOps.sumTriangleAreasXY([Point3d.createZero(), Point3d.create(1, 1, 1)]), 0.0, "PolygonOps.sumTriangleAreasXY on degenerate polygon"); + ck.testExactNumber( + PolygonOps.sumTriangleAreasXY([Point3d.createZero(), Point3d.create(1, 1, 1)]), + 0.0, + "PolygonOps.sumTriangleAreasXY on degenerate polygon", + ); let area = PolygonOps.sumTriangleAreasXY(polylineA); ck.testCoordinate(area, 0.5, "PolygonOps.sumTriangleAreasXY on triangle"); const dart = [Point3d.create(0, 0), Point3d.create(-1, 1), Point3d.create(-4, -4), Point3d.create(1, 0)]; @@ -405,7 +453,10 @@ describe("PolygonOps", () => { dart[dart.length - 1].x += Geometry.smallFraction; PolygonOps.forceClosure(dart); ck.testExactNumber(dart.length, 5, "PolygonOps.forceClosure on nearly closed input doesn't push a point"); - ck.testTrue(Geometry.isSamePoint3d(dart[0], dart[dart.length - 1], 0.0), "PolygonOps.forceClosure on nearly closed input sets end point to start point"); + ck.testTrue( + Geometry.isSamePoint3d(dart[0], dart[dart.length - 1], 0.0), + "PolygonOps.forceClosure on nearly closed input sets end point to start point", + ); let closedDart = PolygonOps.ensureClosed(dart); ck.testTrue(Array.isArray(closedDart) && closedDart === dart, "PolygonOps.ensureClosed returns input if closed"); diff --git a/core/geometry/src/test/geometry3d/PolylineCompression.test.ts b/core/geometry/src/test/geometry3d/PolylineCompression.test.ts index 535b47128245..222d93ea7fe5 100644 --- a/core/geometry/src/test/geometry3d/PolylineCompression.test.ts +++ b/core/geometry/src/test/geometry3d/PolylineCompression.test.ts @@ -20,12 +20,18 @@ class PolylineCompressionChecker { public x0 = 0; public y0 = 0; public allGeometry: GeometryQuery[] = []; - public shift(dx: number, dy: number) { this.x0 += dx; this.y0 += dy; } + public shift(dx: number, dy: number) { + this.x0 += dx; + this.y0 += dy; + } - public verifyGlobalChordErrorCompression(numExpected: number, points: Point3d[], + public verifyGlobalChordErrorCompression( + numExpected: number, + points: Point3d[], globalEdgeTolerance: number, areaTolerance = 0.0, - perpendicularDistanceTolerance: number = 0.0) { + perpendicularDistanceTolerance: number = 0.0, + ) { const result = PolylineOps.compressByChordError(points, globalEdgeTolerance); const y0 = this.y0; this.x0 += 2.0 * globalEdgeTolerance; @@ -92,11 +98,13 @@ describe("GlobalCompression", () => { context.verifyGlobalChordErrorCompression(3, point3, 0.5); context.verifyGlobalChordErrorCompression(2, point3, 2.0); for (const depth of [1, 2, 3]) { - for (const fractal of [ - Sample.createFractalHatReversingPattern(depth, 0.25), - Sample.createFractalLReversingPattern(depth, 1.0), - Sample.createFractalHatReversingPattern(depth, 0.05)]) { - + for ( + const fractal of [ + Sample.createFractalHatReversingPattern(depth, 0.25), + Sample.createFractalLReversingPattern(depth, 1.0), + Sample.createFractalHatReversingPattern(depth, 0.05), + ] + ) { const dataRange = Range3d.createFromVariantData(fractal); const qBase = 0.001 * dataRange.diagonal().magnitude(); for (const factor of [1.0, 5.0, 10.0, 50.0, 100.0, 200.0]) { @@ -113,9 +121,11 @@ describe("GlobalCompression", () => { const context = new PolylineCompressionChecker(); for (const depth of [3, 1, 2, 3]) { - for (const fractal of [ - Sample.createFractalHatReversingPattern(depth, 0.05)]) { - + for ( + const fractal of [ + Sample.createFractalHatReversingPattern(depth, 0.05), + ] + ) { const dataRange = Range3d.createFromVariantData(fractal); const qBase = 0.001 * dataRange.diagonal().magnitude(); for (const factor of [1.0, 5.0, 10.0, 50.0, 100.0, 200.0]) { @@ -134,7 +144,7 @@ describe("GlobalCompression", () => { let yy = 0.0; for (let i = 0; i < 3; i++) { points.push(Point3d.create(i, yy, 0)); - yy = 2.0 - yy; // toggle to sharp corner + yy = 2.0 - yy; // toggle to sharp corner const pointsA = PolylineOps.compressShortEdges(points, 1.0); ck.testExactNumber(points.length, pointsA.length, "No Change chord error case"); diff --git a/core/geometry/src/test/geometry3d/Quaternion.test.ts b/core/geometry/src/test/geometry3d/Quaternion.test.ts index 71251790f653..3bcbdfee95ee 100644 --- a/core/geometry/src/test/geometry3d/Quaternion.test.ts +++ b/core/geometry/src/test/geometry3d/Quaternion.test.ts @@ -16,22 +16,25 @@ describe("MatrixQuatMatrix", () => { it("hello", () => { const ck = new bsiChecker.Checker(); - for (const degrees of [ - Vector3d.create(3, 2, 9), - Vector3d.create(6, 2, -40), - Vector3d.create(-9, 14, -2), - Vector3d.create(-25, 8, 2), - Vector3d.create(1, 40, 3), - Vector3d.create(1, -40, 2), - Vector3d.create(10, 0, 0), - Vector3d.create(0, 10, 0), - Vector3d.create(0, 0, 10), - Vector3d.create(90, 0, 0), - Vector3d.create(0, 90, 0), - Vector3d.create(0, 0, 90), - Vector3d.create(89, 0, 0), - Vector3d.create(0, 89, 0), - Vector3d.create(0, 0, 89)]) { + for ( + const degrees of [ + Vector3d.create(3, 2, 9), + Vector3d.create(6, 2, -40), + Vector3d.create(-9, 14, -2), + Vector3d.create(-25, 8, 2), + Vector3d.create(1, 40, 3), + Vector3d.create(1, -40, 2), + Vector3d.create(10, 0, 0), + Vector3d.create(0, 10, 0), + Vector3d.create(0, 0, 10), + Vector3d.create(90, 0, 0), + Vector3d.create(0, 90, 0), + Vector3d.create(0, 0, 90), + Vector3d.create(89, 0, 0), + Vector3d.create(0, 89, 0), + Vector3d.create(0, 0, 89), + ] + ) { const ypr = YawPitchRollAngles.createDegrees(degrees.x, degrees.y, degrees.z); const matrix = ypr.toMatrix3d(); const quaternion = matrix.toQuaternion(); @@ -44,10 +47,13 @@ describe("MatrixQuatMatrix", () => { it("QuatMatrixQuat", () => { const ck = new bsiChecker.Checker(); - for (const xyzw of [ - Point4d.create(1, 0, 0, 0), - Point4d.create(10, 1, 1, 1), - Point4d.create(10, 4, 5, 1)]) { + for ( + const xyzw of [ + Point4d.create(1, 0, 0, 0), + Point4d.create(10, 1, 1, 1), + Point4d.create(10, 4, 5, 1), + ] + ) { let quat = xyzw.clone().normalizeXYZW()!; for (let i = 0; i < 4; i++) { quat = rotatexyzw(quat); @@ -61,5 +67,4 @@ describe("MatrixQuatMatrix", () => { ck.testTrue(matrixA.isIdentity, "0000 quat is identity"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Range1dArray.test.ts b/core/geometry/src/test/geometry3d/Range1dArray.test.ts index 65fd1f876a22..3e9af2b45863 100644 --- a/core/geometry/src/test/geometry3d/Range1dArray.test.ts +++ b/core/geometry/src/test/geometry3d/Range1dArray.test.ts @@ -11,13 +11,17 @@ import { Checker } from "../Checker"; // import { prettyPrint } from "./testFunctions"; /** - * * @param numRange number of ranges * @param firstLow low value of first range * @param rangeSize function which returns the size for range i * @param gapSize function which returns the size for gap i */ -function constructRangesByStepFunction(numRange: number, firstLow: number, rangeSize: (i: number) => number, gapSize: (i: number) => number): Range1d[] { +function constructRangesByStepFunction( + numRange: number, + firstLow: number, + rangeSize: (i: number) => number, + gapSize: (i: number) => number, +): Range1d[] { let a = firstLow; let b = firstLow; const ranges = []; @@ -38,7 +42,12 @@ function constructRangesByStepFunction(numRange: number, firstLow: number, range * @param interiorFraction (optional) internal interpolation fraction to be used in each interval * @param rightDelta (optional) (signed) shift from data[last] to last output point. Positive is to the right!!! */ -function constructGapPoints(data: GrowableFloat64Array, leftDelta: undefined | number, interiorFraction: undefined | number, rightDelta: undefined | number): GrowableFloat64Array { +function constructGapPoints( + data: GrowableFloat64Array, + leftDelta: undefined | number, + interiorFraction: undefined | number, + rightDelta: undefined | number, +): GrowableFloat64Array { const result = new GrowableFloat64Array(); if (data.length > 0) { let a = data.atUncheckedIndex(0); @@ -200,7 +209,6 @@ function range1dSamples(numRange: number, omega: number = 3.0, alpha: number = 0 } describe("Range1dArray", () => { - it("compareRange1dLexicalLowHigh", () => { const ck = new Checker(); ck.testExactNumber(-1, compareRange1dLexicalLowHigh(Range1d.createXX(0, 1), Range1d.createXX(0, 2))); @@ -210,7 +218,6 @@ describe("Range1dArray", () => { ck.testExactNumber(1, compareRange1dLexicalLowHigh(Range1d.createXX(2, 3), Range1d.createXX(0, 2))); ck.testExactNumber(0, compareRange1dLexicalLowHigh(Range1d.createXX(2, 3), Range1d.createXX(2, 3))); expect(ck.getNumErrors()).toBe(0); - }); it("UnionParitySimplification", () => { @@ -285,10 +292,12 @@ describe("Range1dArray", () => { it("UnionParitySimplificationA", () => { const ck = new Checker(); - for (const allRanges of [ - range1dSamples(3, 2.0, 0.5), - range1dSamples(20, 2.94, 0.34234), - ]) { + for ( + const allRanges of [ + range1dSamples(3, 2.0, 0.5), + range1dSamples(20, 2.94, 0.34234), + ] + ) { testUnionSimplify(ck, allRanges); testParitySimplify(ck, allRanges); } @@ -367,9 +376,36 @@ describe("Range1dArray", () => { // -------------------- --------------------- const forwardRangesForUnion = constructRangesByStepFunction(n, 1, (_i: number) => 3, (_i: number) => -1); - const originalMidpoints = Range1dArray.appendFractionalPoints(forwardRangesForUnion, undefined, 0.5, true, undefined, false, undefined, []) as number[]; - const originalOutsidePoints = Range1dArray.appendFractionalPoints(forwardRangesForUnion, -0.5, undefined, true, undefined, false, 1.5, []) as number[]; - const originalGapPoints = Range1dArray.appendFractionalPoints(forwardRangesForUnion, undefined, undefined, true, 0.5, false, undefined, []) as number[]; + const originalMidpoints = Range1dArray.appendFractionalPoints( + forwardRangesForUnion, + undefined, + 0.5, + true, + undefined, + false, + undefined, + [], + ) as number[]; + const originalOutsidePoints = Range1dArray.appendFractionalPoints( + forwardRangesForUnion, + -0.5, + undefined, + true, + undefined, + false, + 1.5, + [], + ) as number[]; + const originalGapPoints = Range1dArray.appendFractionalPoints( + forwardRangesForUnion, + undefined, + undefined, + true, + 0.5, + false, + undefined, + [], + ) as number[]; const forwardRange = Range1dArray.firstLowToLastHigh(forwardRangesForUnion); Range1dArray.simplifySortUnion(forwardRangesForUnion, true); @@ -421,9 +457,7 @@ describe("Range1dArray", () => { const forwardForParityB = constructRangesByStepFunction(n, 1, (_i: number) => 3, (_i: number) => 0); Range1dArray.simplifySortParity(forwardForParityB, true); ck.testExactNumber(1, forwardForParityB.length, "simplifySortParity(true) with abutting intervals compresses to single interval."); - } expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Range3d.test.ts b/core/geometry/src/test/geometry3d/Range3d.test.ts index 9f80f4bb8784..9d3014480e52 100644 --- a/core/geometry/src/test/geometry3d/Range3d.test.ts +++ b/core/geometry/src/test/geometry3d/Range3d.test.ts @@ -29,17 +29,21 @@ function exerciseWithTransformedPoints(ck: Checker, frame: Transform, points: Po const rangeQ = Range3d.createArray(points); const rangeQRoundTrip = Range3d.create(); rangeQRoundTrip.extendInverseTransformedArray(transformedPoints, frame); - ck.testRange3d(rangeQ, rangeQRoundTrip, prettyPrint(frame), + ck.testRange3d( + rangeQ, + rangeQRoundTrip, + prettyPrint(frame), prettyPrint(points.slice(0, 3)), prettyPrint( - transformedPoints.slice(0, 3))); + transformedPoints.slice(0, 3), + ), + ); // const gPoints = GrowableXYZArray.create(points); const hPoints = GrowableXYZArray.create(transformedPoints); const gRangeRoundTrip = Range3d.createInverseTransformedArray(frame, hPoints); const gRangeInverse = Range3d.createTransformedArray(inverseFrame, hPoints); ck.testRange3d(rangeQ, gRangeRoundTrip); ck.testRange3d(rangeQ, gRangeInverse); - } const rangeA1 = Range3d.create(); const rangeB = Range3d.create(); @@ -90,13 +94,13 @@ function exerciseWithTransformedPoints(ck: Checker, frame: Transform, points: Po } const r01 = Range1d.createXX(0, 1); for (const f of [-0.25, 0.0011, 0.4, 0.998, 1.03, 9]) { - ck.testBoolean(r01.containsX(f), - rangeA.containsPoint(rangeA.diagonalFractionToPoint(f)), "points along diagonal"); + ck.testBoolean(r01.containsX(f), rangeA.containsPoint(rangeA.diagonalFractionToPoint(f)), "points along diagonal"); } const diagonal = rangeA.diagonal(); ck.testCoordinate( rangeA.diagonal().magnitude(), - rangeA.fractionToPoint(0, 0, 0).distance(rangeA.fractionToPoint(1, 1, 1))); + rangeA.fractionToPoint(0, 0, 0).distance(rangeA.fractionToPoint(1, 1, 1)), + ); ck.testCoordinate(rangeA.xLength(), diagonal.x); ck.testCoordinate(rangeA.yLength(), diagonal.y); @@ -134,7 +138,8 @@ function exerciseWithPoints(ck: Checker, points: Point3d[]) { for (let i = 0; i < points.length;) { if (i + 3 < points.length) { range6.extendRange( - Range3d.create(points[i], points[i + 1], points[i + 2])); + Range3d.create(points[i], points[i + 1], points[i + 2]), + ); i += 3; } else { range6.extendRange(Range3d.createXYZ(points[i].x, points[i].y, points[i].z)); @@ -144,7 +149,6 @@ function exerciseWithPoints(ck: Checker, points: Point3d[]) { ck.testFalse(RangeBase.isExtremePoint3d(range6.low), "Live range low is not extreme"); ck.testFalse(RangeBase.isExtremePoint3d(range6.high), "live range high is not extreme"); - } describe("Range3d", () => { it("HelloWorld", () => { @@ -164,7 +168,6 @@ describe("Range3d", () => { } const rangeA = Range3d.createTransformedArray(frames[i], lattice2); ck.testRange3d(rangeA, rangeAB, "multistage transform"); - } const rangeQ = Range3d.createNull(); @@ -227,11 +230,11 @@ describe("Range3d", () => { Point3d.create(1, 2, 3), Point3d.create(4, 2, 9), Point3d.create(2, 8, 3), - Point3d.create(-1, 4, -2)]; + Point3d.create(-1, 4, -2), + ]; for (const frame of frames) { const rangeA = Range3d.createTransformedArray(frame, points); - const rangeB = Range3d.createTransformed(frame, - points[0], points[1], points[2], points[3]); + const rangeB = Range3d.createTransformed(frame, points[0], points[1], points[2], points[3]); ck.testRange3d(rangeA, rangeB); } @@ -250,10 +253,11 @@ describe("Range3d", () => { for (const xyz of lattice1) { const d = range.distanceToPoint(xyz); ck.testBoolean(range.containsPoint(xyz), d === 0.0, "distanceToRange agrees with containment"); - ck.testCoordinate(d, - Geometry.hypotenuseXYZ(rangeX.distanceToX(xyz.x), - rangeY.distanceToX(xyz.y), - rangeZ.distanceToX(xyz.z)), "distance to range 3d, 1d"); + ck.testCoordinate( + d, + Geometry.hypotenuseXYZ(rangeX.distanceToX(xyz.x), rangeY.distanceToX(xyz.y), rangeZ.distanceToX(xyz.z)), + "distance to range 3d, 1d", + ); } ck.checkpoint("Range3d.Distance"); @@ -283,7 +287,8 @@ describe("Range3d", () => { Range1d.createX(10), Range1d.createX(15), Range1d.createX(20), - Range1d.createX(30)]; + Range1d.createX(30), + ]; it("ScalarQueries", () => { const ck = new Checker(); @@ -304,10 +309,13 @@ describe("Range3d", () => { ck.testTrue(r2.containsPoint(r2.diagonalFractionToPoint(0.2)), "diagonal point in"); ck.testTrue(r3.containsPoint(r3.diagonalFractionToPoint(0.2)), "diagonal point in"); - const a = 3.2; // greater than 1 expands in all directions - const r1A = r1.clone(); r1A.scaleAboutCenterInPlace(a); - const r2A = r2.clone(); r2A.scaleAboutCenterInPlace(a); - const r3A = r3.clone(); r3A.scaleAboutCenterInPlace(a); + const a = 3.2; // greater than 1 expands in all directions + const r1A = r1.clone(); + r1A.scaleAboutCenterInPlace(a); + const r2A = r2.clone(); + r2A.scaleAboutCenterInPlace(a); + const r3A = r3.clone(); + r3A.scaleAboutCenterInPlace(a); const bx = 0.99; const by = 0.95; const bz = 0.92; @@ -356,7 +364,10 @@ describe("Range3d", () => { ck.testTrue(rangeQ.containsRange(rangeB), "extend acts as union"); ck.testBoolean( - intervalA.containsRange(rangeB), rangeAB.isAlmostEqual(rangeB), "contained range matches operand"); + intervalA.containsRange(rangeB), + rangeAB.isAlmostEqual(rangeB), + "contained range matches operand", + ); ck.testCoordinate(d1, d2, "distance between ranges is symmetric"); if (rangeAB.isNull) ck.testLT(0, d1, "Empty intersection must have nonzero distance"); @@ -372,7 +383,6 @@ describe("Range3d", () => { const rangeN = Range1d.createFrom(rangeB); ck.testTrue(rangeM.isAlmostEqual(rangeB), "setFrom"); ck.testTrue(rangeN.isAlmostEqual(rangeB), "createFrom"); - } ck.checkpoint("Range3d.Containment1d"); expect(ck.getNumErrors()).toBe(0); @@ -381,13 +391,23 @@ describe("Range3d", () => { it("DiagonalContainment3d", () => { const ck = new Checker(); const rangeA = Range3d.createXYZXYZ( - intervalA.low, intervalA.low, intervalA.low, - intervalA.high, intervalA.high, intervalA.high); + intervalA.low, + intervalA.low, + intervalA.low, + intervalA.high, + intervalA.high, + intervalA.high, + ); // GeometryCoreTestIO.consoleLog("rangeA:", JSON.stringify(rangeA)); for (const intervalB of intervalBArray) { const rangeB = Range3d.createXYZXYZOrCorrectToNull( - intervalB.low, intervalB.low, intervalB.low, - intervalB.high, intervalB.high, intervalB.high); + intervalB.low, + intervalB.low, + intervalB.low, + intervalB.high, + intervalB.high, + intervalB.high, + ); const rangeAB = rangeA.intersect(rangeB); const rangeQ = rangeAB.clone(); @@ -398,7 +418,10 @@ describe("Range3d", () => { const d2 = rangeB.distanceToRange(rangeA); ck.testCoordinate(d1, d2, "distance between ranges is symmetric"); ck.testBoolean( - rangeA.containsRange(rangeB), rangeAB.isAlmostEqual(rangeB), "contained range matches operand"); + rangeA.containsRange(rangeB), + rangeAB.isAlmostEqual(rangeB), + "contained range matches operand", + ); if (rangeAB.isNull) ck.testLT(0, d1, "Empty intersection must have nonzero distance"); else @@ -422,13 +445,19 @@ describe("Range3d", () => { it("DiagonalContainment2d", () => { const ck = new Checker(); const rangeA = Range2d.createXYXY( - intervalA.low, intervalA.low, - intervalA.high, intervalA.high); + intervalA.low, + intervalA.low, + intervalA.high, + intervalA.high, + ); // GeometryCoreTestIO.consoleLog("rangeA:", JSON.stringify(rangeA)); for (const intervalB of intervalBArray) { const rangeB = Range2d.createXYXYOrCorrectToNull( - intervalB.low, intervalB.low, - intervalB.high, intervalB.high); + intervalB.low, + intervalB.low, + intervalB.high, + intervalB.high, + ); const rangeAB = rangeA.intersect(rangeB); const rangeQ = rangeAB.clone(); rangeQ.extendRange(rangeB); @@ -440,7 +469,10 @@ describe("Range3d", () => { d1 = rangeA.distanceToRange(rangeB); d2 = rangeB.distanceToRange(rangeA); ck.testBoolean( - rangeA.containsRange(rangeB), rangeAB.isAlmostEqual(rangeB), "contained range matches operand"); + rangeA.containsRange(rangeB), + rangeAB.isAlmostEqual(rangeB), + "contained range matches operand", + ); if (rangeAB.isNull) ck.testLT(0, d1, "Empty intersection must have nonzero distance"); @@ -480,7 +512,8 @@ describe("Range3d", () => { AngleSweep.createStartEndDegrees(degreesA, degreesB + 180), AngleSweep.createStartEndDegrees(degreesA, degreesA + 360), AngleSweep.createStartEndDegrees(degreesA, degreesC), - AngleSweep.createStartEndDegrees(degreesA, degreesA - 360)]; + AngleSweep.createStartEndDegrees(degreesA, degreesA - 360), + ]; for (let theta0 = 0; theta0 < 360; theta0 += 35) { sweeps.push(AngleSweep.createStartSweepDegrees(theta0, 40)); @@ -516,7 +549,7 @@ describe("Range3d", () => { it("MiscRange1d", () => { const ck = new Checker(); const dataA = [4, 5, -1]; - const dataB = [-10, 20, 30]; // ALL are outside range of A + const dataB = [-10, 20, 30]; // ALL are outside range of A const rangeA = Range1d.createArray(dataA); const rangeAB = rangeA.clone(); ck.testFalse(rangeA.isSinglePoint, "A not single point"); @@ -628,7 +661,7 @@ describe("Range3d", () => { rangeA.worldToLocal(xyzA, xyzB); rangeA.localToWorld(xyzB, xyzC); localPoints.push(xyzB.clone()); - localPointsB.push(worldPoint.clone()); // to be transformed as full array + localPointsB.push(worldPoint.clone()); // to be transformed as full array } rangeA.worldToLocalArrayInPlace(localPointsB); diff --git a/core/geometry/src/test/geometry3d/RangeTree.test.ts b/core/geometry/src/test/geometry3d/RangeTree.test.ts index e9d0545a7509..a79fd92327be 100644 --- a/core/geometry/src/test/geometry3d/RangeTree.test.ts +++ b/core/geometry/src/test/geometry3d/RangeTree.test.ts @@ -18,7 +18,10 @@ import { Point3d } from "../../geometry3d/Point3dVector3d"; import { Range3d } from "../../geometry3d/Range"; import { Transform } from "../../geometry3d/Transform"; import { - ConvexFacetLocationDetail, FacetLocationDetail, FacetLocationDetailPair, NonConvexFacetLocationDetail, + ConvexFacetLocationDetail, + FacetLocationDetail, + FacetLocationDetailPair, + NonConvexFacetLocationDetail, } from "../../polyface/FacetLocationDetail"; import { IndexedPolyface } from "../../polyface/Polyface"; import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; @@ -236,16 +239,26 @@ describe("IndexedRangeHeap", () => { let numCase = 0; for (const pointBFactor of [1, 4]) { for (const uz of [0, -3]) { - const distanceSequence: number[] = []; // min-distance for a sequence of searches with differing tree structures. They should all produce the same result! + const distanceSequence: number[] = []; // min-distance for a sequence of searches with differing tree structures. They should all produce the same result! for (const treeFlare of [2, 4, 6]) { // a patch of a sphere, facing along the x axis const pointsA = Sample.createGridPointsOnEllipsoid( Transform.createRowValues( - 5, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 3, 0, + 5, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 3, + 0, ), - 6, 8, + 6, + 8, AngleSweep.createStartEndDegrees(-40, 60), AngleSweep.createStartEndDegrees(-30, 30), ); @@ -256,31 +269,52 @@ describe("IndexedRangeHeap", () => { const pointsB = Sample.createGridPointsOnEllipsoid( Transform.createRowValues( - -1, -1, 0, 8, - 0, 2, 0.5, 1, - -uz, 0, 2, 3 + 1.3 * uz, + -1, + -1, + 0, + 8, + 0, + 2, + 0.5, + 1, + -uz, + 0, + 2, + 3 + 1.3 * uz, ), - pointBFactor * 5, pointBFactor * 7, + pointBFactor * 5, + pointBFactor * 7, AngleSweep.createStartEndDegrees(-40, 80), AngleSweep.createStartEndDegrees(-75, 120), ); const treeA = RangeTreeOps.createByIndexSplits( - ((index: number): Range3d => { return Range3d.create(pointsA[index]); }), + (index: number): Range3d => { + return Range3d.create(pointsA[index]); + }, pointsA, pointsA.length, - treeFlare, treeFlare)!; + treeFlare, + treeFlare, + )!; const treeB = RangeTreeOps.createByIndexSplits( - ((index: number): Range3d => { return Range3d.create(pointsB[index]); }), + (index: number): Range3d => { + return Range3d.create(pointsB[index]); + }, pointsB, pointsB.length, - treeFlare, treeFlare)!; + treeFlare, + treeFlare, + )!; ck.testExactNumber(pointsA.length, RangeTreeOps.getRecursiveAppDataCount(treeA), "point count in range tree"); GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, pointsA, 0.05, x0, 0); GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, 0, pointsB, 0.05, x0, 0); const allRanges: Range3d[] = []; - const rangeAccumulatorFunction = (node: RangeTreeNode): boolean => { allRanges.push(node.getRange()); return true; }; + const rangeAccumulatorFunction = (node: RangeTreeNode): boolean => { + allRanges.push(node.getRange()); + return true; + }; treeA?.recurseIntoTree(rangeAccumulatorFunction); treeB?.recurseIntoTree(rangeAccumulatorFunction); if (numCase === 0) { @@ -331,17 +365,27 @@ describe("IndexedRangeHeap", () => { const pointsA = Sample.createGridPointsOnEllipsoid( Transform.createRowValues( - 5, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 3, 0, + 5, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 3, + 0, ), - 36, 52, + 36, + 52, AngleSweep.createStartEndDegrees(-40, 60), AngleSweep.createStartEndDegrees(-30, 195), ); const path = BezierCurve3d.create([Point3d.create(6, 0, 0), Point3d.create(3, 3, 1), Point3d.create(0, 8, 5), Point3d.create(-1, -6, -2)])!; - const distanceSequence: number[][] = []; // min-distance for a sequence of searches with differing tree structures. They should all produce the same result! + const distanceSequence: number[][] = []; // min-distance for a sequence of searches with differing tree structures. They should all produce the same result! let numCase = 0; for (const treeWidth of [2, 4, 8]) { @@ -383,7 +427,12 @@ describe("IndexedRangeHeap", () => { for (let i = 1; i < distanceSequence.length; i++) for (let j = 0; j < numSearchesPerCase; j++) if (ck.testExactNumber(numSearchesPerCase, distanceSequence[i].length, "same number of searches per test case")) - ck.testExactNumber(distanceSequence[0][j], distanceSequence[i][j], { distance0J: distanceSequence[0][j], i, j, distanceIJ: distanceSequence[i][j] }); + ck.testExactNumber(distanceSequence[0][j], distanceSequence[i][j], { + distance0J: distanceSequence[0][j], + i, + j, + distanceIJ: distanceSequence[i][j], + }); GeometryCoreTestIO.saveGeometry(allGeometry, "IndexedRangeTree", "PointCloudMultiSearch"); expect(ck.getNumErrors()).toBe(0); @@ -397,11 +446,21 @@ describe("IndexedRangeHeap", () => { const pointsA = Sample.createGridPointsOnEllipsoid( Transform.createRowValues( - 5, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 3, 0, + 5, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 3, + 0, ), - 36, 52, + 36, + 52, AngleSweep.createStartEndDegrees(-40, 60), AngleSweep.createStartEndDegrees(-30, 195), ); @@ -479,7 +538,11 @@ describe("IndexedRangeHeap", () => { const localFraction = cld.childDetail.fraction; if (ck.testType(cld.curve, LineString3d, "cld.curve defined") && cld.curve) { ck.testPoint3d(cld.point, cld.curve.fractionToPoint(cld.fraction), "cld.fraction is global linestring param"); - ck.testCoordinate(cld.fraction, cld.curve.segmentIndexAndLocalFractionToGlobalFraction(segmentIndex, localFraction), "cld.childDetail has segment index and param"); + ck.testCoordinate( + cld.fraction, + cld.curve.segmentIndexAndLocalFractionToGlobalFraction(segmentIndex, localFraction), + "cld.childDetail has segment index and param", + ); } const i1 = Math.min(segmentIndex + 4, wavePoints.length); for (let i = Math.max(segmentIndex - 4, 0); i < i1; i++) @@ -579,7 +642,12 @@ describe("IndexedRangeHeap", () => { // 10 looks good for lots of tests. const frankeSize = 20; const polyface = Sample.createMeshFromFrankeSurface(frankeSize, strokeOptions)!; - const path = BezierCurve3d.create([Point3d.create(0, 0, 1), Point3d.create(1.6, 0, 0.2), Point3d.create(1, 0.5, 0.5), Point3d.create(0, 1, 0.5)])!; + const path = BezierCurve3d.create([ + Point3d.create(0, 0, 1), + Point3d.create(1.6, 0, 0.2), + Point3d.create(1, 0.5, 0.5), + Point3d.create(0, 1, 0.5), + ])!; for (const treeWidth of [2, 4, 8]) { const visitor = polyface.createVisitor(0); @@ -609,7 +677,9 @@ describe("IndexedRangeHeap", () => { frankeSize, numFacets: polyface.facetCount, treeWidth, - numRangeTestTrue: searcher.numRangeTestTrue, numRangeTestFalse: searcher.numRangeTestFalse, numPointTest: searcher.numFacetTest, + numRangeTestTrue: searcher.numRangeTestTrue, + numRangeTestFalse: searcher.numRangeTestFalse, + numPointTest: searcher.numFacetTest, searches: searcher.numSearch, searchesTimesPoints: searchesTimesFacets, fraction: searcher.numFacetTest / searchesTimesFacets, @@ -630,7 +700,12 @@ describe("IndexedRangeHeap", () => { strokeOptions.shouldTriangulate = true; const frankeSize = 20; const polyface = Sample.createMeshFromFrankeSurface(frankeSize, strokeOptions)!; - const path = BezierCurve3d.create([Point3d.create(0, 0, 1), Point3d.create(1.6, 0, 0.2), Point3d.create(1, 0.5, 0.5), Point3d.create(0, 1, 0.5)])!; + const path = BezierCurve3d.create([ + Point3d.create(0, 0, 1), + Point3d.create(1.6, 0, 0.2), + Point3d.create(1, 0.5, 0.5), + Point3d.create(0, 1, 0.5), + ])!; // test and cover the trigger arrays const context = PolyfaceRangeTreeContext.createCapture(polyface, undefined, undefined, true); @@ -691,7 +766,11 @@ describe("IndexedRangeHeap", () => { if (ck.testType(polyface1, IndexedPolyface)) { const xyScale = 1.5; const translation = Point3d.create(0.75, 0.75, -1); - let helixPts = Sample.createHelixPoints(5, 60, Transform.createRowValues(xyScale, 0, 0, translation.x, 0, xyScale, 0, translation.y, 0, 0, 1, translation.z)); + let helixPts = Sample.createHelixPoints( + 5, + 60, + Transform.createRowValues(xyScale, 0, 0, translation.x, 0, xyScale, 0, translation.y, 0, 0, 1, translation.z), + ); helixPts = [Point3d.create(0.25, 0.25, -1), ...helixPts, Point3d.create(0.45, 0.45, sweepHeight + 1)]; const curveOptions = InterpolationCurve3dOptions.create({ fitPoints: helixPts }); const helix = InterpolationCurve3d.create(curveOptions); @@ -700,7 +779,7 @@ describe("IndexedRangeHeap", () => { let nonConvexHits = 0; for (const convexFacets of [true, false]) { if (!convexFacets) - polyface1 = PolyfaceQuery.cloneWithMaximalPlanarFacets(polyface1)!; // non-convex top and bottom facets! + polyface1 = PolyfaceQuery.cloneWithMaximalPlanarFacets(polyface1)!; // non-convex top and bottom facets! const context1 = PolyfaceRangeTreeContext.createCapture(polyface1, undefined, undefined, convexFacets); if (ck.testType(context1, PolyfaceRangeTreeContext)) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, [polyface1, helix], x0, y0, z0); @@ -764,9 +843,18 @@ describe("IndexedRangeHeap", () => { const polyfaceA = Sample.createMeshFromFrankeSurface(frankeSizeA, strokeOptions, [0.5, 0.5, 0.5, 1])!; const polyfaceB = Sample.createMeshFromFrankeSurface(frankeSizeB, strokeOptions, [0, 0, 0, 4])!; const transform = Transform.createRowValues( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 1.5, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1.5, ); polyfaceB.tryTransformInPlace(transform); GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyfaceA, x0, y0, z0); @@ -802,9 +890,18 @@ describe("IndexedRangeHeap", () => { const polyfaceA = Sample.createMeshFromFrankeSurface(frankeSizeA, undefined, [0.5, 0.5, 0.5, 1])!; const polyfaceB = Sample.createMeshFromFrankeSurface(frankeSizeB, undefined, [0, 0, 0, 4])!; const transform = Transform.createRowValues( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 1.5, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 1.5, ); polyfaceB.tryTransformInPlace(transform); const contextA = PolyfaceRangeTreeContext.createCapture(polyfaceA.createVisitor(), 3, 3)!; @@ -859,18 +956,42 @@ describe("IndexedRangeHeap", () => { let x0 = 0; const y0 = 0; const z0 = 0; - const pointsA = Sample.createHelixPoints(5.0, 129, + const pointsA = Sample.createHelixPoints( + 5.0, + 129, Transform.createRowValues( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 3, 0, - )); - const pointsB = Sample.createHelixPoints(9.0, 257, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 3, + 0, + ), + ); + const pointsB = Sample.createHelixPoints( + 9.0, + 257, Transform.createRowValues( - 2, 0, -2, 5, - 0, 2, 0, 0, - 1, 0.1, 1, 0, - )); + 2, + 0, + -2, + 5, + 0, + 2, + 0, + 0, + 1, + 0.1, + 1, + 0, + ), + ); const treeWidth = 3; GeometryCoreTestIO.captureCloneGeometry(allGeometry, pointsA, x0, y0, z0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, pointsB, x0, y0, z0); diff --git a/core/geometry/src/test/geometry3d/Ray3d.test.ts b/core/geometry/src/test/geometry3d/Ray3d.test.ts index 9b1fc5d33fe2..6e253915a4a4 100644 --- a/core/geometry/src/test/geometry3d/Ray3d.test.ts +++ b/core/geometry/src/test/geometry3d/Ray3d.test.ts @@ -76,7 +76,6 @@ function createRays(ck: Checker, target?: Ray3d) { const ray2C = Ray3d.fromJSON(); ck.testTrue(ray2.isAlmostEqual(ray2B), "json round trip"); ck.testPointer(ray2C, "expect some default fromJSON"); - } describe("Ray3d", () => { @@ -100,7 +99,7 @@ describe("Ray3d", () => { createRays(ck, undefined); createRays(ck, rayQ0); - const nullRay = Ray3d.createXYZUVW(1, 2, 3, 0, 0, 0); // general origin, zero vector to trigger else branches .. + const nullRay = Ray3d.createXYZUVW(1, 2, 3, 0, 0, 0); // general origin, zero vector to trigger else branches .. nullRay.toRigidZFrame(); nullRay.tryNormalizeInPlaceWithAreaWeight(0.0); nullRay.tryNormalizeInPlaceWithAreaWeight(1.0); @@ -112,7 +111,9 @@ describe("Ray3d", () => { ck.testUndefined( Ray3d.createWeightedDerivative( new Float64Array([1, 2, 3, 0]), - new Float64Array([2, 1, 4, 0]))); + new Float64Array([2, 1, 4, 0]), + ), + ); expect(ck.getNumErrors()).toBe(0); }); it("Ray3d.ClosestApproach", () => { @@ -142,7 +143,6 @@ describe("Ray3d", () => { const approachC = Ray3d.closestApproachRay3dRay3d(rayA, rayC); ck.testExactNumber(approachC.approachType!, CurveCurveApproachType.ParallelGeometry, indexA); ck.testCoordinate(shiftDistance, approachC.detailA.point.distance(approachC.detailB.point)); - } else { ck.testExactNumber(approach.approachType!, CurveCurveApproachType.PerpendicularChord, [indexA, indexB]); const vector = Vector3d.createStartEnd(approach.detailA.point, approach.detailB.point); @@ -157,7 +157,10 @@ describe("Ray3d", () => { // rayE2 at fraction f2 has been moved to rayE1 at fraction f1. Confirm intersection there . . const approachE = Ray3d.closestApproachRay3dRay3d(rayE1, rayE2); ck.testExactNumber( - approachE.approachType!, CurveCurveApproachType.Intersection, "forced intersection", [indexA, indexB], + approachE.approachType!, + CurveCurveApproachType.Intersection, + "forced intersection", + [indexA, indexB], ); ck.testCoordinate(f1, approachE.detailA.fraction); ck.testCoordinate(f2, approachE.detailB.fraction); @@ -203,16 +206,21 @@ describe("Ray3d", () => { const point = ray.fractionToPoint(interval.fractionToPoint(intervalFraction)); if ( !ck.testBoolean( - Geometry.isIn01(intervalFraction), range.containsPoint(point), "fractional point vs range", - intervalFraction, point, prettyPrint(ray), prettyPrint(range), + Geometry.isIn01(intervalFraction), + range.containsPoint(point), + "fractional point vs range", + intervalFraction, + point, + prettyPrint(ray), + prettyPrint(range), ) ) ray.intersectionWithRange3d(range); } const interval1 = ray1.intersectionWithRange3d(range); if (ck.testDefined(interval1, "Expected reversed ray to have related intersection")) { - ck.testCoordinate(interval.low, - interval1.high, "reversed ray"); - ck.testCoordinate(interval.high, - interval1.low, "reversed ray"); + ck.testCoordinate(interval.low, -interval1.high, "reversed ray"); + ck.testCoordinate(interval.high, -interval1.low, "reversed ray"); } } else { numOutside++; @@ -228,15 +236,24 @@ describe("Ray3d", () => { const q = range.fractionToPoint(0.4, 0.2, 0.1); const interval0 = Range1d.createNull(); for (const ray of raySample) { - const ray3 = Ray3d.create(q, ray.direction); // we know this starts inside + const ray3 = Ray3d.create(q, ray.direction); // we know this starts inside const interval = ray3.intersectionWithRange3d(range, interval0); ck.testTrue(interval0 === interval, "Verify reuse result)"); if (ck.testFalse(interval.isNull, "expect real intersection from inside start")) { ck.testTrue(interval.containsX(0.0)); for (const intervalFraction of [0.999999, 0.5, 0.000001, -0.001, 1.001]) { const point = ray3.fractionToPoint(interval.fractionToPoint(intervalFraction)); - if (!ck.testBoolean(Geometry.isIn01(intervalFraction), range.containsPoint(point), "fractional point vs range", intervalFraction, point, - prettyPrint(ray3), prettyPrint(range))) + if ( + !ck.testBoolean( + Geometry.isIn01(intervalFraction), + range.containsPoint(point), + "fractional point vs range", + intervalFraction, + point, + prettyPrint(ray3), + prettyPrint(range), + ) + ) ray.intersectionWithRange3d(range); } } @@ -265,10 +282,14 @@ describe("Ray3d", () => { ck.testUndefined(fractionB, "Detect ray parallel to plane"); // This pair generates aDotN and UDotN both near zero const planeQ = Plane3dByOriginAndUnitNormal.createXYZUVW( - 101.38054428331306, -7.136947376249823, 14.575798896766162, - 1.4069516995683865e-17, 1.0468826690441132e-32, 1)!; - const rayQ = Ray3d.createXYZUVW(95.87780347429201, -7.1369473762498234, 14.575798896766187, - - 1, -4.61132646190051e-31, 4.567684502237405e-15); + 101.38054428331306, + -7.136947376249823, + 14.575798896766162, + 1.4069516995683865e-17, + 1.0468826690441132e-32, + 1, + )!; + const rayQ = Ray3d.createXYZUVW(95.87780347429201, -7.1369473762498234, 14.575798896766187, -1, -4.61132646190051e-31, 4.567684502237405e-15); ck.testUndefined(rayQ.intersectionWithPlane(planeQ)); expect(ck.getNumErrors()).toBe(0); }); @@ -336,7 +357,10 @@ function captureTriangle(allGeometry: GeometryQuery[], triangle: BarycentricTria GeometryCoreTestIO.captureGeometry( allGeometry, LineString3d.create( - rotatedTriangle.points[0], rotatedTriangle.points[1], rotatedTriangle.points[2], rotatedTriangle.points[0], + rotatedTriangle.points[0], + rotatedTriangle.points[1], + rotatedTriangle.points[2], + rotatedTriangle.points[0], ), ); } @@ -379,7 +403,9 @@ describe("Ray3d.IntersectionWithTriangle", () => { ray.cloneTransformed(rotationTransform, rotatedRay); triangle.cloneTransformed(rotationTransform, rotatedTriangle); rotatedIntersectionPoint = rotatedRay.intersectionWithTriangle( - rotatedTriangle.points[0], rotatedTriangle.points[1], rotatedTriangle.points[2], + rotatedTriangle.points[0], + rotatedTriangle.points[1], + rotatedTriangle.points[2], ); rotatedOriginalIntersectionPoint = rotationMatrix.multiplyPoint(intersectionPoint); if (ck.testDefined(rotatedIntersectionPoint)) { @@ -403,7 +429,9 @@ describe("Ray3d.IntersectionWithTriangle", () => { ray.cloneTransformed(rotationTransform, rotatedRay); triangle.cloneTransformed(rotationTransform, rotatedTriangle); rotatedIntersectionPoint = rotatedRay.intersectionWithTriangle( - rotatedTriangle.points[0], rotatedTriangle.points[1], rotatedTriangle.points[2], + rotatedTriangle.points[0], + rotatedTriangle.points[1], + rotatedTriangle.points[2], ); rotatedOriginalIntersectionPoint = rotationMatrix.multiplyPoint(intersectionPoint); if (ck.testDefined(rotatedIntersectionPoint)) { @@ -423,13 +451,17 @@ describe("Ray3d.IntersectionWithTriangle", () => { expectedIntersectionPoint = Point3d.create(5, 0, 0); if (ck.testDefined(intersectionPoint)) { ck.testPoint3d( - intersectionPoint, expectedIntersectionPoint, "ray intersects triangle on a triangle edge", + intersectionPoint, + expectedIntersectionPoint, + "ray intersects triangle on a triangle edge", ); } ray.cloneTransformed(rotationTransform, rotatedRay); triangle.cloneTransformed(rotationTransform, rotatedTriangle); rotatedIntersectionPoint = rotatedRay.intersectionWithTriangle( - rotatedTriangle.points[0], rotatedTriangle.points[1], rotatedTriangle.points[2], + rotatedTriangle.points[0], + rotatedTriangle.points[1], + rotatedTriangle.points[2], ); rotatedOriginalIntersectionPoint = rotationMatrix.multiplyPoint(intersectionPoint); if (ck.testDefined(rotatedIntersectionPoint)) { @@ -525,9 +557,15 @@ describe("Ray3d.IntersectionWithTriangle", () => { for (let i = 0; i < N * N; i++) { triangles.push( BarycentricTriangle.createXYZXYZXYZ( - getRandomNumber(), getRandomNumber(), getRandomNumber(), - getRandomNumber(), getRandomNumber(), getRandomNumber(), - getRandomNumber(), getRandomNumber(), getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), + getRandomNumber(), ), ); } @@ -545,7 +583,9 @@ describe("Ray3d.IntersectionWithTriangle", () => { // shoot ray at triangle using Ray3d class startTime = performance.now(); intersectionPoint1 = ray.intersectionWithTriangle( - triangle.points[0], triangle.points[1], triangle.points[2], + triangle.points[0], + triangle.points[1], + triangle.points[2], ); endTime = performance.now(); timeByRay3d = timeByRay3d + endTime - startTime; @@ -562,22 +602,26 @@ describe("Ray3d.IntersectionWithTriangle", () => { } } } - if (!ck.testExactNumber( - intersectionPoints1.length, - intersectionPoints2.length, - "Ray3d and BarycentricTriangle classes return same number of intersection points", - )) { + if ( + !ck.testExactNumber( + intersectionPoints1.length, + intersectionPoints2.length, + "Ray3d and BarycentricTriangle classes return same number of intersection points", + ) + ) { expect(ck.getNumErrors()).toBe(0); } GeometryCoreTestIO.consoleLog( `${intersectionPoints1.length} intersection happened out of ${rays.length * triangles.length} shoots`, ); for (let i = 0; i < intersectionPoints1.length; i++) { - if (!ck.testPoint3d( - intersectionPoints1[i], - intersectionPoints2[i], - "intersection points calculated by Ray3d and BarycentricTriangle classes are equal", - )) { + if ( + !ck.testPoint3d( + intersectionPoints1[i], + intersectionPoints2[i], + "intersection points calculated by Ray3d and BarycentricTriangle classes are equal", + ) + ) { expect(ck.getNumErrors()).toBe(0); } } @@ -606,27 +650,33 @@ describe("Ray3d.IntersectionWithTriangle", () => { triangle.cloneTransformed(rotationTransform, rotatedTriangle); // shoot rotated ray at rotated triangle rotatedIntersectionPoint = rotatedRay.intersectionWithTriangle( - rotatedTriangle.points[0], rotatedTriangle.points[1], rotatedTriangle.points[2], + rotatedTriangle.points[0], + rotatedTriangle.points[1], + rotatedTriangle.points[2], ); if (rotatedIntersectionPoint !== undefined) { rotatedIntersectionPoints.push(rotatedIntersectionPoint); } } } - if (!ck.testExactNumber( - intersectionPoints1.length, - rotatedIntersectionPoints.length, - "original and rotated shots return same number of intersection points", - )) { + if ( + !ck.testExactNumber( + intersectionPoints1.length, + rotatedIntersectionPoints.length, + "original and rotated shots return same number of intersection points", + ) + ) { expect(ck.getNumErrors()).toBe(0); } for (let i = 0; i < intersectionPoints1.length; i++) { rotatedOriginalIntersectionPoint = rotationMatrix.multiplyPoint(intersectionPoints1[i]); - if (!ck.testPoint3d( - rotatedOriginalIntersectionPoint, - rotatedIntersectionPoints[i], - "rotating original intersection points gives rotated intersection points", - )) { + if ( + !ck.testPoint3d( + rotatedOriginalIntersectionPoint, + rotatedIntersectionPoints[i], + "rotating original intersection points gives rotated intersection points", + ) + ) { expect(ck.getNumErrors()).toBe(0); } } diff --git a/core/geometry/src/test/geometry3d/Segment1d.test.ts b/core/geometry/src/test/geometry3d/Segment1d.test.ts index 6a6be7bae15b..c2d6e00592e3 100644 --- a/core/geometry/src/test/geometry3d/Segment1d.test.ts +++ b/core/geometry/src/test/geometry3d/Segment1d.test.ts @@ -47,5 +47,4 @@ describe("Segment1d", () => { ck.checkpoint("Segment1d.Create"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry3d/Transform.test.ts b/core/geometry/src/test/geometry3d/Transform.test.ts index 96a6bcc38b0b..b5e3a5a7391a 100644 --- a/core/geometry/src/test/geometry3d/Transform.test.ts +++ b/core/geometry/src/test/geometry3d/Transform.test.ts @@ -110,12 +110,14 @@ describe("Transform.CreateOriginAndMatrix", () => { it("Transform.CreateOriginAndMatrix", () => { const ck = new Checker(); const matrixArray = Sample.createMatrix3dArray(); - for (const origin of [ - Point3d.create(0, 0, 0), - Point3d.create(2, 0, 0), - Point3d.create(0, 3, 0), - Point3d.create(0, 0, -2), - ]) { + for ( + const origin of [ + Point3d.create(0, 0, 0), + Point3d.create(2, 0, 0), + Point3d.create(0, 3, 0), + Point3d.create(0, 0, -2), + ] + ) { for (const matrixA of matrixArray) { const transformA = Transform.createOriginAndMatrix(origin, matrixA); const originA = transformA.getOrigin(); @@ -272,9 +274,18 @@ describe("Transform.CloneRigid", () => { it("Transform.CloneRigid", () => { const ck = new Checker(); const singularTransformA = Transform.createRowValues( - 1, 2, 4, 0, - 2, 4, 3, 1, - 3, 6, -10, 1, + 1, + 2, + 4, + 0, + 2, + 4, + 3, + 1, + 3, + 6, + -10, + 1, ); // columns X and Y (or 0 and 1) are dependent so matrix part is singular const points = [Point3d.create(1, 2, 3), Point3d.create(3, 2, 9)]; ck.testFalse(singularTransformA.multiplyInversePoint3dArrayInPlace(points)); @@ -320,7 +331,6 @@ describe("Transform.CreateRigidFromOriginAndColumns", () => { ck.testPerpendicular(vectorU, transform0.matrix.columnY()); ck.testLE(0.0, transform0.matrix.dotColumnX(vectorU)); ck.testLE(0.0, transform0.matrix.dotColumnY(vectorV)); - } ck.testUndefined(Transform.createRigidFromOriginAndColumns(origin, vectorU, vectorU, AxisOrder.XYZ)); expect(ck.getNumErrors()).toBe(0); @@ -358,7 +368,7 @@ describe("Transform.createFlattenAlongVectorToPlane", () => { const spacePoints = Sample.point3d; for (const planeOrigin of spacePoints) { for (const planeNormal of [Vector3d.create(0, 0, 1), Vector3d.create(2, 3, -1)]) { - for (const sweepDirection of ([Vector3d.create(0, 0, 1), Vector3d.create(-2, 3, 1)])) { + for (const sweepDirection of [Vector3d.create(0, 0, 1), Vector3d.create(-2, 3, 1)]) { const transform = Transform.createFlattenAlongVectorToPlane(sweepDirection, planeOrigin, planeNormal); if (ck.testDefined(transform, "expect good transform")) { for (const pointA of spacePoints) { diff --git a/core/geometry/src/test/geometry3d/ViewBox.test.ts b/core/geometry/src/test/geometry3d/ViewBox.test.ts index 0f9dc810c3bd..bc377ebf7a1c 100644 --- a/core/geometry/src/test/geometry3d/ViewBox.test.ts +++ b/core/geometry/src/test/geometry3d/ViewBox.test.ts @@ -26,19 +26,25 @@ function makeViewableGeometry(): GeometryQuery[] { geometry.push(LineSegment3d.create(Point3d.create(0, 0, 0), Point3d.create(0, 1, 0))); geometry.push(LineSegment3d.create(Point3d.create(0, 0, 0), Point3d.create(0, 0, 1.5))); geometry.push(LineString3d.create( - [Point3d.create(-1, -1, -1), - Point3d.create(1, -1, -1), - Point3d.create(1, -1, 1), - Point3d.create(-1, -1, 1), - Point3d.create(-1, -1, -1), - Point3d.create(-1, -1, -1)])); + [ + Point3d.create(-1, -1, -1), + Point3d.create(1, -1, -1), + Point3d.create(1, -1, 1), + Point3d.create(-1, -1, 1), + Point3d.create(-1, -1, -1), + Point3d.create(-1, -1, -1), + ], + )); geometry.push(LineString3d.create( - [Point3d.create(-1, 1, -1), - Point3d.create(1, 1, -1), - Point3d.create(1, 1, 1), - Point3d.create(-1, 1, 1), - Point3d.create(-1, 1, -1), - Point3d.create(-1, 1, -1)])); + [ + Point3d.create(-1, 1, -1), + Point3d.create(1, 1, -1), + Point3d.create(1, 1, 1), + Point3d.create(-1, 1, 1), + Point3d.create(-1, 1, -1), + Point3d.create(-1, 1, -1), + ], + )); geometry.push(LineSegment3d.createXYZXYZ(1, -1, -1, 1, 1, -1)); geometry.push(LineSegment3d.createXYZXYZ(1, -1, 1, 1, 1, 1)); @@ -47,25 +53,39 @@ function makeViewableGeometry(): GeometryQuery[] { geometry.push(LineSegment3d.createXYZXYZ(-1, -1, 1, -1, 1, 1)); const a = 0.5; - geometry.push(Arc3d.create(Point3d.create(0, 0, 0), Vector3d.create(a, 0, 0), Vector3d.create(0, a, 0), AngleSweep.createStartSweepDegrees(0, 105))); + geometry.push( + Arc3d.create(Point3d.create(0, 0, 0), Vector3d.create(a, 0, 0), Vector3d.create(0, a, 0), AngleSweep.createStartSweepDegrees(0, 105)), + ); const b = 0.25; // triangle in xz plane geometry.push(Loop.createPolygon([ Point3d.create(0, 0, 0), Point3d.create(b, 0, 0), - Point3d.create(0, 0, b)])); + Point3d.create(0, 0, b), + ])); // skinnier triangle in yz plane -- to higher z geometry.push(Loop.createPolygon([ Point3d.create(0, 0, 0), Point3d.create(0, b * 0.5, 0), - Point3d.create(0, 0, 1.5 * b)])); + Point3d.create(0, 0, 1.5 * b), + ])); return geometry; } // Gather viewable geometry from MakeViewAbleGeometry // create viewing setup from given vectors local Z, Y rotations. // append the (rotated) geometry to the GeometryQuery[]. // -function collectViewableGeometry(ck: Checker, geometry: GeometryQuery[], rightVector: Vector3d, upVector: Vector3d, leftNoneRight: number, topNoneBottom: number, xShift: number, yShift: number, expectedIndex: StandardViewIndex | 0) { +function collectViewableGeometry( + ck: Checker, + geometry: GeometryQuery[], + rightVector: Vector3d, + upVector: Vector3d, + leftNoneRight: number, + topNoneBottom: number, + xShift: number, + yShift: number, + expectedIndex: StandardViewIndex | 0, +) { const geometry0 = makeViewableGeometry(); const axes0 = Matrix3d.createViewedAxes(rightVector, upVector, leftNoneRight, topNoneBottom)!; if (expectedIndex !== 0) { @@ -84,7 +104,6 @@ function collectViewableGeometry(ck: Checker, geometry: GeometryQuery[], rightVe for (const g of geometry0) { geometry.push(g.cloneTransformed(frame1)!); } - } // Gather viewable geometry from MakeViewAbleGeometry // create viewing setup from given vectors local Z, Y rotations. @@ -104,7 +123,6 @@ function collectViewableGeometryByXYZ(geometry: GeometryQuery[], x: number, y: n for (const g of geometry0) { geometry.push(g.cloneTransformed(frame1)!); } - } class PointLattice { public xCoordinates: number[] = []; @@ -127,7 +145,7 @@ class PointLattice { // if any are exterior, create an IndexedPolyface with the exterior polygons. // REMARK tag is unused -- for future use in tagging the various meshes, e.g. as vertex/edge/face public createMeshOnLatticeCubeExteriorFaces(i0: number, j0: number, k0: number, tag: number): IndexedPolyface | undefined { - if (tag === -1) // tag is unused otherwise .. get by the compiler complaint + if (tag === -1) // tag is unused otherwise .. get by the compiler complaint return undefined; const builder = PolyfaceBuilder.create(); const corners = []; @@ -157,17 +175,15 @@ class PointLattice { return polyface; return undefined; } - } describe("ViewWidget", () => { it("CubeGeometry", () => { const geometry = []; - for (const lattice of [ - new PointLattice([0, 0.2, 0.8, 1.0]), - new PointLattice([0, 0.4, 1.6, 2.0], - [2, 2.2, 2.8, 3.0], - [0, 0.1, 0.4, 0.5]), - ] + for ( + const lattice of [ + new PointLattice([0, 0.2, 0.8, 1.0]), + new PointLattice([0, 0.4, 1.6, 2.0], [2, 2.2, 2.8, 3.0], [0, 0.1, 0.4, 0.5]), + ] ) { // 8 corners geometry.push(lattice.createMeshOnLatticeCubeExteriorFaces(0, 0, 0, 0)!); @@ -202,7 +218,6 @@ describe("ViewWidget", () => { geometry.push(lattice.createMeshOnLatticeCubeExteriorFaces(1, 2, 1, 204)!); geometry.push(lattice.createMeshOnLatticeCubeExteriorFaces(1, 1, 0, 205)!); geometry.push(lattice.createMeshOnLatticeCubeExteriorFaces(1, 1, 2, 206)!); - } if (geometry) GeometryCoreTestIO.saveGeometry(geometry, "ViewWidget", "CubeGeometry"); @@ -214,30 +229,30 @@ describe("ViewWidget", () => { const b = 30; const a = b * 0.5; - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitY(), 0, 0, 0, b, StandardViewIndex.Top); // TOP + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitY(), 0, 0, 0, b, StandardViewIndex.Top); // TOP - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 0, 0, 0, 0, StandardViewIndex.Front); // FRONT + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 0, 0, 0, 0, StandardViewIndex.Front); // FRONT collectViewableGeometry(ck, geometry, Vector3d.unitY(), Vector3d.unitZ(), 0, 0, b, 0, StandardViewIndex.Right); // RIGHT collectViewableGeometry(ck, geometry, Vector3d.unitX(-1), Vector3d.unitZ(), 0, 0, 2 * b, 0, StandardViewIndex.Back); // BACK collectViewableGeometry(ck, geometry, Vector3d.unitY(-1), Vector3d.unitZ(), 0, 0, -b, 0, StandardViewIndex.Left); // LEFT collectViewableGeometry(ck, geometry, Vector3d.unitX(1), Vector3d.unitY(-1), 0, 0, 0, -b, StandardViewIndex.Bottom); // BOTTOM // full iso views - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 1, 1, a, a, StandardViewIndex.RightIso); // RIGHT FRONT ISO (bottom to top) - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), -1, 1, -a, a, StandardViewIndex.Iso); // LEFT FRONT ISO (bottom to top) + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 1, 1, a, a, StandardViewIndex.RightIso); // RIGHT FRONT ISO (bottom to top) + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), -1, 1, -a, a, StandardViewIndex.Iso); // LEFT FRONT ISO (bottom to top) // incremental iso views based on front for (const isoFactor of [0.5, -0.25, 0, 0.25, 0.5]) { - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 1, isoFactor, a, isoFactor * a, 0); // RIGHT FRONT ISO (bottom to top) - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), -1, isoFactor, -a, isoFactor * a, 0); // LEFT FRONT ISO (bottom to top) + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), 1, isoFactor, a, isoFactor * a, 0); // RIGHT FRONT ISO (bottom to top) + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), -1, isoFactor, -a, isoFactor * a, 0); // LEFT FRONT ISO (bottom to top) } for (const cornerFactor of [-0.75, -0.5, -0.25, 0.25, 0.5, 0.75]) { - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, 0, cornerFactor * a, 0, 0); // left to right swings from front + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, 0, cornerFactor * a, 0, 0); // left to right swings from front } for (const cornerFactor of [-3, -1, 1, 3]) { // look in from middle of all vertical edges . . . - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, 0, cornerFactor * a, 0, 0); // swing front to 4 corners. + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, 0, cornerFactor * a, 0, 0); // swing front to 4 corners. // look in down and up from vertical edge collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, 1, cornerFactor * a, a, 0); collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, -1, cornerFactor * a, -a, 0); @@ -245,19 +260,21 @@ describe("ViewWidget", () => { // look in from all horizontal edges const q = Math.PI * 0.25 / Math.atan(Math.sqrt(0.5)); for (const cornerFactor of [-2, 0, 2, 4]) { - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, q, cornerFactor * a, a, 0); // swing front to edges and look down - collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, q, cornerFactor * a, -a, 0); // swing front to edges and look up + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, q, cornerFactor * a, a, 0); // swing front to edges and look down + collectViewableGeometry(ck, geometry, Vector3d.unitX(), Vector3d.unitZ(), cornerFactor, q, cornerFactor * a, -a, 0); // swing front to edges and look up } // lay out the unfolded box - for (const origin of [ - Point3d.create(-a, -3 * a), - Point3d.create(-3 * a, -a), - Point3d.create(-a, -a), - Point3d.create(a, -a), - Point3d.create(3 * a, -a), - Point3d.create(-a, a), - ]) { + for ( + const origin of [ + Point3d.create(-a, -3 * a), + Point3d.create(-3 * a, -a), + Point3d.create(-a, -a), + Point3d.create(a, -a), + Point3d.create(3 * a, -a), + Point3d.create(-a, a), + ] + ) { geometry.push(LineString3d.createRectangleXY(origin, b, b, true)); } diff --git a/core/geometry/src/test/geometry3d/YawPitchRollAngles.test.ts b/core/geometry/src/test/geometry3d/YawPitchRollAngles.test.ts index 9efbbe6d647c..877007567f75 100644 --- a/core/geometry/src/test/geometry3d/YawPitchRollAngles.test.ts +++ b/core/geometry/src/test/geometry3d/YawPitchRollAngles.test.ts @@ -22,22 +22,25 @@ describe("YPR", () => { YawPitchRollAngles.createDegrees(360, -720, 3 * 360).isIdentity(false), "is not Identity if we don't allow period shift", ); - for (const degrees of [ - Vector3d.create(10, 0, 0), - Vector3d.create(0, 10, 0), - Vector3d.create(0, 0, 10), - Vector3d.create(0, 20, 10), - Vector3d.create(10, 20, 0), - Vector3d.create(10, 0, 20), - Vector3d.create(3, 2, 9), - Vector3d.create(6, 2, -40), - Vector3d.create(-9, 14, -2), - Vector3d.create(-25, 8, 2), - Vector3d.create(1, 40, 3), - Vector3d.create(1, -40, 2), - Vector3d.create(90, 0, 0), - Vector3d.create(0, 90, 0), - Vector3d.create(0, 0, 90)]) { + for ( + const degrees of [ + Vector3d.create(10, 0, 0), + Vector3d.create(0, 10, 0), + Vector3d.create(0, 0, 10), + Vector3d.create(0, 20, 10), + Vector3d.create(10, 20, 0), + Vector3d.create(10, 0, 20), + Vector3d.create(3, 2, 9), + Vector3d.create(6, 2, -40), + Vector3d.create(-9, 14, -2), + Vector3d.create(-25, 8, 2), + Vector3d.create(1, 40, 3), + Vector3d.create(1, -40, 2), + Vector3d.create(90, 0, 0), + Vector3d.create(0, 90, 0), + Vector3d.create(0, 0, 90), + ] + ) { const yprA = YawPitchRollAngles.createDegrees(degrees.z, degrees.y, degrees.x); const yawMatrix = Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees.z)); const pitchMatrix = Matrix3d.createRotationAroundAxisIndex(1, Angle.createDegrees(-degrees.y)); @@ -130,29 +133,59 @@ describe("YPR", () => { it("createFromMatrix3dNearRigidMatrices", () => { const ck = new bsiChecker.Checker(); const matrix1 = Matrix3d.createRowValues( - 0.37146947416490494, 7.033246428758867e-16, -0.9284451763712457, - -0.9284452294022093, 2.813991026819455e-16, -0.3714694529472999, - 1.9186788483451994e-23, 1.0000000571180345, 7.575294995656733e-16, + 0.37146947416490494, + 7.033246428758867e-16, + -0.9284451763712457, + -0.9284452294022093, + 2.813991026819455e-16, + -0.3714694529472999, + 1.9186788483451994e-23, + 1.0000000571180345, + 7.575294995656733e-16, ); // from Dovydas const matrix2 = Matrix3d.createRowValues( - 0.707421, -0.415747, -0.571585, - 0, 0.808703, -0.588217, - 0.706792, 0.416117, 0.572094, + 0.707421, + -0.415747, + -0.571585, + 0, + 0.808703, + -0.588217, + 0.706792, + 0.416117, + 0.572094, ); // view matrix received from .css const matrix3 = Matrix3d.createRowValues( - 0.70742, -0.41574, -0.57158, - 0, 0.80870, -0.58821, - 0.70679, 0.41611, 0.57209, + 0.70742, + -0.41574, + -0.57158, + 0, + 0.80870, + -0.58821, + 0.70679, + 0.41611, + 0.57209, ); // drop least significant digit from matrix2 (less rigid) const matrix4 = Matrix3d.createRowValues( - 0.7074, -0.4157, -0.5715, - 0, 0.8087, -0.5882, - 0.7067, 0.4161, 0.5720, + 0.7074, + -0.4157, + -0.5715, + 0, + 0.8087, + -0.5882, + 0.7067, + 0.4161, + 0.5720, ); // drop least significant digit from matrix3 (less rigid) const matrix5 = Matrix3d.createRowValues( - 0.707, -0.415, -0.571, - 0, 0.808, -0.588, - 0.706, 0.416, 0.572, + 0.707, + -0.415, + -0.571, + 0, + 0.808, + -0.588, + 0.706, + 0.416, + 0.572, ); // drop least significant digit from matrix4 (less rigid) const matrices = [ diff --git a/core/geometry/src/test/geometry4d/Geometry4d.test.ts b/core/geometry/src/test/geometry4d/Geometry4d.test.ts index 5cebb1628708..b660436b9e4f 100644 --- a/core/geometry/src/test/geometry4d/Geometry4d.test.ts +++ b/core/geometry/src/test/geometry4d/Geometry4d.test.ts @@ -24,7 +24,6 @@ import { prettyPrint } from "../testFunctions"; /* eslint-disable @typescript-eslint/naming-convention */ /** - * * @param select 0 for transform0, 1 for transform1 * @param geometry array to receive new geometry * @param map map to evaluate @@ -43,15 +42,14 @@ function appendNPC(select: number, geometry: GeometryQuery[], map: Map4d, dx: nu for (const point of xyz) { point.addInPlace(shift); } - geometry.push(LineString3d.create(xyz[0], xyz[1], xyz[3], xyz[2], xyz[0], - xyz[4], xyz[5], xyz[7], xyz[6], xyz[4])); + geometry.push(LineString3d.create(xyz[0], xyz[1], xyz[3], xyz[2], xyz[0], xyz[4], xyz[5], xyz[7], xyz[6], xyz[4])); geometry.push(LineSegment3d.create(xyz[1], xyz[5])); geometry.push(LineSegment3d.create(xyz[2], xyz[6])); geometry.push(LineSegment3d.create(xyz[3], xyz[7])); } class Geometry4dTests { - constructor(public noisy: boolean = false) { } + constructor(public noisy: boolean = false) {} public testSums(ck: bsiChecker.Checker) { const point0 = Point4d.create(1, 2, 3, 4); const point1 = Point4d.create(2, 3, 4, 1); @@ -81,7 +79,6 @@ class Geometry4dTests { ck.testParallel(vector01A, vector01C, "pseudo vector direction"); } public testPoint4d(ck: bsiChecker.Checker) { - const pointZ = Point4d.fromJSON([]); ck.testExactNumber(0, pointZ.maxAbs(), "default fromJSON"); ck.testExactNumber(0, Point4d.fromJSON([4.0]).maxAbs()); @@ -104,8 +101,7 @@ class Geometry4dTests { const pointAMinusC = hPointA.minus(pointC); ck.testCoordinate(pointAMinusC.magnitudeXYZW(), hPointA.distanceXYZW(pointC)); - ck.testCoordinate(pointAMinusC.magnitudeXYZW() * pointAMinusC.magnitudeXYZW(), - hPointA.distanceSquaredXYZW(pointC)); + ck.testCoordinate(pointAMinusC.magnitudeXYZW() * pointAMinusC.magnitudeXYZW(), hPointA.distanceSquaredXYZW(pointC)); } const pointC2 = Point4d.createFromPackedXYZ(cc)!; ck.testExactNumber(pointC.x, pointC2.x, "packed point methods extract the same x"); @@ -115,7 +111,7 @@ class Geometry4dTests { const pointD = Point4d.createZero(); const pointD2 = Point4d.createZero(); - Point4d.create(cc[0], cc[1], cc[2], cc[3], pointD); // create with supplied target. + Point4d.create(cc[0], cc[1], cc[2], cc[3], pointD); // create with supplied target. ck.testPoint4d(pointC, pointD); pointC.clone(pointD2); ck.testPoint4d(pointD2, pointC); @@ -140,7 +136,6 @@ class Geometry4dTests { ck.testPoint4d(point1, Point4d.createFromPointAndWeight(xyz2!, 0.50).normalizeWeight()!); ck.testPointer(xyz1, "simple normalize"); } - } describe("Geometry4d.HelloWorld", () => { it("Geometry4d sums", () => { @@ -170,7 +165,7 @@ describe("Geometry4d.HelloWorld", () => { const ck = new bsiChecker.Checker(); const pointA = Point4d.create(1, 2, 3, 4); const pointZ = Point4d.createZero(); - pointA.set(); // should become zero!!! + pointA.set(); // should become zero!!! ck.testPoint4d(pointA, pointZ, "implicit zero"); ck.checkpoint("Set"); expect(ck.getNumErrors()).toBe(0); @@ -251,8 +246,10 @@ describe("Geometry4d.BoxMap", () => { ck.testTrue(map!.isAlmostEqual(map3!), "verify reused map"); ck.testUndefined(Map4d.createBoxMap(lowA, highA, lowB, lowB)); ck.testUndefined(Map4d.createBoxMap(highA, highA, lowB, highB)); - ck.testUndefined(Map4d.createVectorFrustum(Point3d.create(0, 0, 1), - Vector3d.unitX(), Vector3d.unitY(), Vector3d.unitY(), 0.8), "expect no map from singular axes"); + ck.testUndefined( + Map4d.createVectorFrustum(Point3d.create(0, 0, 1), Vector3d.unitX(), Vector3d.unitY(), Vector3d.unitY(), 0.8), + "expect no map from singular axes", + ); const map4 = Map4d.fromJSON({}); ck.testTrue(map4.isAlmostEqual(Map4d.createIdentity())); if (ck.testPointer(map, "Expect box map") && map) { @@ -288,15 +285,41 @@ describe("Matrix4d", () => { it("Multiply", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix4d.createRowValues( - 10, 2, 3, 4, - 5, 20, 2, 1, - 4, 6, 30, 2, - 3, 2, 1, 30); + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 4, + 6, + 30, + 2, + 3, + 2, + 1, + 30, + ); const matrixB = Matrix4d.createRowValues( - 30, -2, -1, 0.3, - 1, 40, 0.1, 3, - 2, 4, 15, 6, - -0.3, 0.1, 4, 20); + 30, + -2, + -1, + 0.3, + 1, + 40, + 0.1, + 3, + 2, + 4, + 15, + 6, + -0.3, + 0.1, + 4, + 20, + ); const diagonalB = matrixB.diagonal(); const BX = matrixB.columnX(); @@ -322,15 +345,24 @@ describe("Matrix4d", () => { ck.testCoordinate( matrixAB.atIJ(row, col), matrixA.rowDotColumn(row, matrixB, col), - "AB entry", row, col); + "AB entry", + row, + col, + ); ck.testCoordinate( matrixABT.atIJ(row, col), matrixA.rowDotRow(row, matrixB, col), - "ABT entry", row, col); + "ABT entry", + row, + col, + ); ck.testCoordinate( matrixATB.atIJ(row, col), matrixA.columnDotColumn(row, matrixB, col), - "ATB entry", row, col); + "ATB entry", + row, + col, + ); } const CX = matrixAB.columnX(); @@ -366,9 +398,9 @@ describe("Matrix4d", () => { matrixAB.multiplyPoint4dArrayQuietRenormalize(point4dArray, point3dArray1); for (let i = 0; i < point3dArray.length; i++) { const p = point3dArray[i]; - const pointQ = - Point4d.createAdd2Scaled(CX, p.x, CY, p.y).plus( - Point4d.createAdd2Scaled(CZ, p.z, CW, weight)); + const pointQ = Point4d.createAdd2Scaled(CX, p.x, CY, p.y).plus( + Point4d.createAdd2Scaled(CZ, p.z, CW, weight), + ); ck.testPoint4d(pointQ, point4dArray[i]); } @@ -378,10 +410,23 @@ describe("Matrix4d", () => { it("MultiplyAndRenormalize", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix4d.createRowValues( - 10, 2, 3, 4, - 5, 20, 2, 1, - 4, 6, 30, 2, - 3, 2, 1, 30); + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 4, + 6, + 30, + 2, + 3, + 2, + 1, + 30, + ); const pointQ = [Point3d.create(3, 2, 5), Point3d.create(2, 9, -4)]; const pointQ4d = []; const pointAQ4d = []; @@ -402,10 +447,23 @@ describe("Matrix4d", () => { it("addTranslationSandwichInPlace", () => { const ck = new bsiChecker.Checker(); const matrixZ = Matrix4d.createRowValues( - 10, 3, 4, 5, - 6, 30, 1, 1.2, - 8, 3, -15, 2, - 9, 1, 2, 11); + 10, + 3, + 4, + 5, + 6, + 30, + 1, + 1.2, + 8, + 3, + -15, + 2, + 9, + 1, + 2, + 11, + ); const scale = 1.25; const allMatrices = [ Matrix4d.createZero(), @@ -419,10 +477,23 @@ describe("Matrix4d", () => { } } allMatrices.push(Matrix4d.createRowValues( - 10, 2, 3, 4, - 5, 20, 2, 1, - 4, 6, 30, 2, - 3, 2, 1, 30)); + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 4, + 6, + 30, + 2, + 3, + 2, + 1, + 30, + )); for (const matrixB of allMatrices) for (const xyz of [[2, 0, 0], [0, 3, 0], [0, 0, 4]]) { const ax = xyz[0]; @@ -447,10 +518,23 @@ describe("Matrix4d", () => { it("Misc", () => { const ck = new bsiChecker.Checker(); const matrixA = Matrix4d.createRowValues( - 10, 2, 3, 4, - 5, 20, 2, 1, - 4, 6, 30, 2, - 3, 2, 1, 30); + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 4, + 6, + 30, + 2, + 3, + 2, + 1, + 30, + ); const arrayB = matrixA.rowArrays(); const f = 2.9; const arrayC = matrixA.rowArrays((value: number) => f * value); @@ -468,65 +552,204 @@ describe("Matrix4d", () => { it("Inverse", () => { const ck = new bsiChecker.Checker(); - for (const matrixA of [ - Matrix4d.createRowValues( - -0.7180980534975014, 0, 0, 513359.37226204335, - 0, -1.267092311832453, 0, 6221930.288732969, - 0, 0, 0.02752494718615039, 0.00028901194545457914, - 0, 0, 0, 1), // from RBB, failed to invert with matrix.maxAbs() scaling logic - Matrix4d.createRowValues(0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), - Matrix4d.createRowValues( - 1, 0, 0, 0, - 0, 2, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1), - Matrix4d.createRowValues( - 10, 2, 3, 4, - 5, 20, 2, 1, - 4, 6, 30, 2, - 3, 2, 1, 30), - Matrix4d.createRowValues( - -4509.659901029264, -2398.122299764309, 0, 4192.763181336376, - 1705.3435500113474, -6341.664102191739, 0, 312.814982291711, - 0, -0, 179.36736748646942, -118.00864861439914, - 0, -0, 0, 1), - Matrix4d.createRowValues( - -5.199577930106449e-8, 5.5878993626914775e-8, 0, 0.005147466964956382, - - 2.116903271812029e-10, - 7.745682382609335e-10, 0, 0.009886485615341636, - 1.0596550131841224e-8, 3.877244310855186e-8, 1.1236140303104357e-7, 0.00017487220506423595, - 2.119310026368245e-8, 7.754488621710374e-8, 0, 0.010227421860234953), - Matrix4d.createRowValues( - -0.00006936056809344464, 0.00002622893965818147, 0, 0.49974485667496793, - -0.00001813902597199655, -0.00004796736591244489, 0, 0.3652941567347317, - 0, 0, 0.0013814942135607167, 0.3550280429194092, - 0, 0, 0, 1)]) + for ( + const matrixA of [ + Matrix4d.createRowValues( + -0.7180980534975014, + 0, + 0, + 513359.37226204335, + 0, + -1.267092311832453, + 0, + 6221930.288732969, + 0, + 0, + 0.02752494718615039, + 0.00028901194545457914, + 0, + 0, + 0, + 1, + ), // from RBB, failed to invert with matrix.maxAbs() scaling logic + Matrix4d.createRowValues(0.5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), + Matrix4d.createRowValues( + 1, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + ), + Matrix4d.createRowValues( + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 4, + 6, + 30, + 2, + 3, + 2, + 1, + 30, + ), + Matrix4d.createRowValues( + -4509.659901029264, + -2398.122299764309, + 0, + 4192.763181336376, + 1705.3435500113474, + -6341.664102191739, + 0, + 312.814982291711, + 0, + -0, + 179.36736748646942, + -118.00864861439914, + 0, + -0, + 0, + 1, + ), + Matrix4d.createRowValues( + -5.199577930106449e-8, + 5.5878993626914775e-8, + 0, + 0.005147466964956382, + -2.116903271812029e-10, + -7.745682382609335e-10, + 0, + 0.009886485615341636, + 1.0596550131841224e-8, + 3.877244310855186e-8, + 1.1236140303104357e-7, + 0.00017487220506423595, + 2.119310026368245e-8, + 7.754488621710374e-8, + 0, + 0.010227421860234953, + ), + Matrix4d.createRowValues( + -0.00006936056809344464, + 0.00002622893965818147, + 0, + 0.49974485667496793, + -0.00001813902597199655, + -0.00004796736591244489, + 0, + 0.3652941567347317, + 0, + 0, + 0.0013814942135607167, + 0.3550280429194092, + 0, + 0, + 0, + 1, + ), + ] + ) verifyInverse(ck, matrixA, "diagonally dominant"); for (const a33 of [1, 10, 100]) { - verifyInverse(ck, + verifyInverse( + ck, Matrix4d.createRowValues( - 0, 1, 0, 0, - - 0.6643638388299198, 0, 0.7474093186836596, 0, - 0.7474093186836597, 0, 0.6643638388299198, 0, - 0, 0, 0, a33), `David S example with scale ${a33}`); + 0, + 1, + 0, + 0, + -0.6643638388299198, + 0, + 0.7474093186836596, + 0, + 0.7474093186836597, + 0, + 0.6643638388299198, + 0, + 0, + 0, + 0, + a33, + ), + `David S example with scale ${a33}`, + ); } - for (const singularMatrix of [ - Matrix4d.createRowValues( // row 1,2 match - 10, 2, 3, 4, - 5, 20, 2, 1, - 5, 20, 2, 1, - 3, 2, 1, 30), - Matrix4d.createRowValues( // column 2,3 match - 10, 2, 4, 4, - 5, 20, 2, 2, - 4, 6, 2, 2, - 3, 2, 30, 30), - Matrix4d.createRowValues( // row 3 is sum of rows 0,1,2 - 10, 2, 3, 4, - 5, 20, 2, 1, - 5, 20, 2, 1, - 20, 42, 7, 6)]) { + for ( + const singularMatrix of [ + Matrix4d.createRowValues( // row 1,2 match + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 5, + 20, + 2, + 1, + 3, + 2, + 1, + 30, + ), + Matrix4d.createRowValues( // column 2,3 match + 10, + 2, + 4, + 4, + 5, + 20, + 2, + 2, + 4, + 6, + 2, + 2, + 3, + 2, + 30, + 30, + ), + Matrix4d.createRowValues( // row 3 is sum of rows 0,1,2 + 10, + 2, + 3, + 4, + 5, + 20, + 2, + 1, + 5, + 20, + 2, + 1, + 20, + 42, + 7, + 6, + ), + ] + ) { for (const scaleFactor of [1.0, 0.232136936231648, 1.0 / 3.8798797912312, Math.sqrt(2), Math.sqrt(20), Math.sqrt(200)]) { const scaledMatrix = singularMatrix.clone(); scaledMatrix.scaleRowsInPlace(scaleFactor, scaleFactor, scaleFactor, scaleFactor); @@ -535,10 +758,23 @@ describe("Matrix4d", () => { } const matrixB = Matrix4d.createRowValues( - 10, 1, 2, 3, - 0, 10, 3, 4, - 0, 10, 3, 4, // same as row 2 -- this makes it singular!!! - 0, 0, 1, 1); + 10, + 1, + 2, + 3, + 0, + 10, + 3, + 4, + 0, + 10, + 3, + 4, // same as row 2 -- this makes it singular!!! + 0, + 0, + 1, + 1, + ); ck.testUndefined(matrixB.createInverse()); const matrixC = Matrix4d.createRowValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); @@ -560,13 +796,15 @@ describe("Matrix4d", () => { ck.testCoordinate( rows[i].dotProduct(rows[i + 1]), rows[i].dotProductXYZW(rows[i + 1].x, rows[i + 1].y, rows[i + 1].z, rows[i + 1].w), - "dot product scalars"); + "dot product scalars", + ); } for (let i = 0; i < 4; i++) for (let j = 0; j < 4; j++) ck.testCoordinate( matrixD.columnDotColumn(i, matrixC, j), - matrixD.columnDotRow(i, matrixCT, j)); + matrixD.columnDotRow(i, matrixCT, j), + ); ck.checkpoint("Matrix4d.Inverse"); expect(ck.getNumErrors()).toBe(0); }); @@ -578,7 +816,8 @@ describe("Matrix4d", () => { function verify3d4dPlaneMatch( ck: bsiChecker.Checker, planeA: Plane3dByOriginAndVectors, - planeB: PlaneByOriginAndVectors4d) { + planeB: PlaneByOriginAndVectors4d, +) { for (const uv of [[0.4, 0.62], [0, 0], [1, 0], [0, 1]]) { const q3d = planeA.fractionToPoint(uv[0], uv[1]); const q4d = planeB.fractionToPoint(uv[0], uv[1]); @@ -601,13 +840,15 @@ function verify3d4dPlaneMatch( ck.testTrue(planeXY.isAlmostEqual(planeB3), "revert to XY plane"); const planeB4 = PlaneByOriginAndVectors4d.createOriginAndVectors( - planeB.origin, planeB.vectorU, planeB.vectorV); + planeB.origin, + planeB.vectorU, + planeB.vectorV, + ); ck.testTrue(planeB.isAlmostEqual(planeB4)); // reuse planeB3 PlaneByOriginAndVectors4d.createOriginAndVectors(planeB.origin, planeB.vectorU, planeB.vectorV, planeB3); ck.testTrue(planeB.isAlmostEqual(planeB3)); } - } describe("Plane4dByOriginAndVectors", () => { it("Create", () => { @@ -630,25 +871,25 @@ describe("Plane4dByOriginAndVectors", () => { const vectorV = Vector3d.create(-5, 2, 8); const targetU = origin.plus(vectorU); const targetV = origin.plus(vectorV); - const plane0 = PlaneByOriginAndVectors4d.createOriginAndTargets3d(origin, - targetU, targetV); + const plane0 = PlaneByOriginAndVectors4d.createOriginAndTargets3d(origin, targetU, targetV); const plane2 = PlaneByOriginAndVectors4d.createOriginAndVectors( Point4d.createFromPointAndWeight(origin, 1), Point4d.createFromPointAndWeight(vectorU, 0), - Point4d.createFromPointAndWeight(vectorV, 0)); + Point4d.createFromPointAndWeight(vectorV, 0), + ); ck.testPoint4d(plane0.origin, plane2.origin); ck.testPoint4d(plane0.vectorU, plane2.vectorU); ck.testPoint4d(plane0.vectorV, plane2.vectorV); const plane1 = Plane3dByOriginAndVectors.createOriginAndVectors( - origin, vectorU, vectorV); + origin, + vectorU, + vectorV, + ); verify3d4dPlaneMatch(ck, plane1, plane0); - verify3d4dPlaneMatch(ck, - Plane3dByOriginAndVectors.createXYPlane(), - PlaneByOriginAndVectors4d.createXYPlane()); + verify3d4dPlaneMatch(ck, Plane3dByOriginAndVectors.createXYPlane(), PlaneByOriginAndVectors4d.createXYPlane()); expect(ck.getNumErrors()).toBe(0); }); - }); function suppressNearZero(value: number): number { const tol = 1.0e-15; @@ -693,8 +934,7 @@ describe("Map4d", () => { const scaleFactor = 2.5; const scaleTransform = Transform.createScaleAboutPoint(fixedPoint, scaleFactor); const scaleTransform1 = scaleTransform.inverse()!; - ck.testUndefined(Map4d.createTransform(scaleTransform, scaleTransform), - "confirm Map4d constructor rejects mismatch"); + ck.testUndefined(Map4d.createTransform(scaleTransform, scaleTransform), "confirm Map4d constructor rejects mismatch"); const scaleMap = Map4d.createTransform(scaleTransform, scaleTransform1); if (ck.testPointer(scaleMap)) { ck.testFalse(mapI.isAlmostEqual(scaleMap)); @@ -714,7 +954,8 @@ describe("Map4d", () => { Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), Vector3d.create(0, 0, 1), - 1.0)!; + 1.0, + )!; ck.testTrue(mapI.isAlmostEqual(frustumIdentity), "Identity frustum"); const yzxFrustum = Map4d.createVectorFrustum( // YZX frustum, eyepoint at (10,0,0) ?? @@ -722,11 +963,13 @@ describe("Map4d", () => { Vector3d.create(0, 1, 0), Vector3d.create(0, 0, 1), Vector3d.create(1, 0, 0), - 0.9)!; + 0.9, + )!; const rotationTransform = Transform.createFixedPointAndMatrix( Point3d.create(4, 2, 8), - Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 3), Angle.createDegrees(10))!); + Matrix3d.createRotationAroundVector(Vector3d.create(1, 2, 3), Angle.createDegrees(10))!, + ); const rotationMap = Map4d.createTransform(rotationTransform, rotationTransform.inverse())!; verifySandwich(ck, rotationMap, mapI); verifySandwich(ck, mapI, rotationMap); @@ -824,7 +1067,7 @@ describe("Map4d", () => { const ck = new bsiChecker.Checker(); let badFraction: number | undefined; for (const wA0 of [1, 1.1, 1.3]) { - for (const wA1 of [1, 0.4, 1.5]) { // remark wA1=2 creates anomalies with spacePoint 2,4,2,anyW? + for (const wA1 of [1, 0.4, 1.5]) { // remark wA1=2 creates anomalies with spacePoint 2,4,2,anyW? for (const wSpace of [1, 0.9]) { const hA0 = Point4d.create(0, 0, 0, wA0); const hA1 = Point4d.create(3, 1, 0, wA1); @@ -853,13 +1096,33 @@ describe("Map4d", () => { it("CreateMap4dWithUndefinedTransform1", () => { const ck = new bsiChecker.Checker(); const transform1 = Transform.createRowValues( - 10, 1, 1, 0, - 1, 11, 2, 3, - 2, 4, 20, -2); // good transform, but skewed for fun + 10, + 1, + 1, + 0, + 1, + 11, + 2, + 3, + 2, + 4, + 20, + -2, + ); // good transform, but skewed for fun const singularTransform = Transform.createRowValues( - 10, 1, 1, 0, - 10, 1, 1, 0, - 2, 4, 20, -2); // repeated row makes it singular + 10, + 1, + 1, + 0, + 10, + 1, + 1, + 0, + 2, + 4, + 20, + -2, + ); // repeated row makes it singular const map1 = Map4d.createTransform(transform1); const singularMap = Map4d.createTransform(singularTransform); ck.testPointer(map1, "Map4d computed its own inverse"); diff --git a/core/geometry/src/test/geometry4d/MomentData.test.ts b/core/geometry/src/test/geometry4d/MomentData.test.ts index 38c0cdfdb344..d962854f1e38 100644 --- a/core/geometry/src/test/geometry4d/MomentData.test.ts +++ b/core/geometry/src/test/geometry4d/MomentData.test.ts @@ -5,9 +5,9 @@ import { describe, expect, it } from "vitest"; import { BSplineCurve3d } from "../../bspline/BSplineCurve"; import { Arc3d } from "../../curve/Arc3d"; -import { AnyRegion } from "../../curve/CurveTypes"; import { CurveChain, CurveCollection } from "../../curve/CurveCollection"; import { CurvePrimitive } from "../../curve/CurvePrimitive"; +import { AnyRegion } from "../../curve/CurveTypes"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; @@ -74,7 +74,8 @@ describe("MomentData", () => { const regions: AnyRegion[] = []; const regionD0 = Loop.create( LineString3d.create([[1, 4], [0, 4], [0, 0], [1, 0]]), - Arc3d.createCircularStartMiddleEnd(Point3d.create(1, 0), Point3d.create(3, 2), Point3d.create(1, 4))); + Arc3d.createCircularStartMiddleEnd(Point3d.create(1, 0), Point3d.create(3, 2), Point3d.create(1, 4)), + ); const mirrorX = Transform.createFixedPointAndMatrix(undefined, Matrix3d.createScale(-1, 1, 1)); const regionD1 = regionD0.cloneTransformed(mirrorX)!; regions.push(regionD0, regionD1 as Loop); @@ -83,19 +84,39 @@ describe("MomentData", () => { regions.push(regionD0.cloneTransformed(skew)! as AnyRegion); regions.push(regionD1.cloneTransformed(skew)! as AnyRegion); const poles = new Float64Array([ - 1, 0, 0, - 4, 0, 0, - 4, 1, 0, - 1, 1, 0, - 2, 2, 0, - 5, 2, 0, - 6, 3, 0, - 5, 4, 0, - 1, 4, 0]); + 1, + 0, + 0, + 4, + 0, + 0, + 4, + 1, + 0, + 1, + 1, + 0, + 2, + 2, + 0, + 5, + 2, + 0, + 6, + 3, + 0, + 5, + 4, + 0, + 1, + 4, + 0, + ]); for (const order of [3, 4, 5]) { const regionE0 = Loop.create( LineString3d.create([[1, 4], [0, 4], [0, 0], [1, 0]]), - BSplineCurve3d.createUniformKnots(poles, order)!); + BSplineCurve3d.createUniformKnots(poles, order)!, + ); regions.push(regionE0); } for (const r0 of regions) { @@ -190,10 +211,13 @@ describe("MomentData", () => { const strokeOptions = StrokeOptions.createForCurves(); strokeOptions.maxEdgeLength = 0.1; let x0 = 0; - for (const sampleSet of [ - Sample.createSmoothCurvePrimitives(), - Sample.createBsplineCurves(true), - Sample.createSimpleParityRegions()]) { + for ( + const sampleSet of [ + Sample.createSmoothCurvePrimitives(), + Sample.createBsplineCurves(true), + Sample.createSimpleParityRegions(), + ] + ) { for (const g of sampleSet) { const range = g.range(); const dy = range.yLength() * 2.0; @@ -219,5 +243,4 @@ describe("MomentData", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "Moments", "WireMoments"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/geometry4d/Point4d.test.ts b/core/geometry/src/test/geometry4d/Point4d.test.ts index 36e282f43cd0..f39cd8f89e1c 100644 --- a/core/geometry/src/test/geometry4d/Point4d.test.ts +++ b/core/geometry/src/test/geometry4d/Point4d.test.ts @@ -5,10 +5,10 @@ import { describe, expect, it } from "vitest"; import { Geometry } from "../../Geometry"; import { Plane3dByOriginAndUnitNormal } from "../../geometry3d/Plane3dByOriginAndUnitNormal"; +import { Point2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Point4d } from "../../geometry4d/Point4d"; import { Checker } from "../Checker"; -import { Point2d } from "../../geometry3d/Point2dVector2d"; function testExactPoint4dXYZW(ck: Checker, point: Point4d, x: number, y: number, z: number, w: number) { ck.testExactNumber(x, point.x); @@ -31,19 +31,25 @@ describe("Point4d", () => { testExactPoint4dXYZW(ck, pointA, 3, 6, 9, 12); pointA.set(2, 4, 6, 8); testExactPoint4dXYZW(ck, pointA, 2, 4, 6, 8); - pointA.x = 10; testExactPoint4dXYZW(ck, pointA, 10, 4, 6, 8); - pointA.y = 20; testExactPoint4dXYZW(ck, pointA, 10, 20, 6, 8); - pointA.z = 30; testExactPoint4dXYZW(ck, pointA, 10, 20, 30, 8); - pointA.w = 40; testExactPoint4dXYZW(ck, pointA, 10, 20, 30, 40); + pointA.x = 10; + testExactPoint4dXYZW(ck, pointA, 10, 4, 6, 8); + pointA.y = 20; + testExactPoint4dXYZW(ck, pointA, 10, 20, 6, 8); + pointA.z = 30; + testExactPoint4dXYZW(ck, pointA, 10, 20, 30, 8); + pointA.w = 40; + testExactPoint4dXYZW(ck, pointA, 10, 20, 30, 40); const pointB = Point4d.create(-1, -2, -3, -4); - pointB.setFrom(pointA); testExactPoint4dPoint4d(ck, pointA, pointB); - const pointC = pointA.clone(); testExactPoint4dPoint4d(ck, pointB, pointC); + pointB.setFrom(pointA); + testExactPoint4dPoint4d(ck, pointA, pointB); + const pointC = pointA.clone(); + testExactPoint4dPoint4d(ck, pointB, pointC); const dataD = [12, 13, 14, 15]; pointC.setFromJSON(dataD); const pointC2 = Point4d.fromJSON(dataD); testExactPoint4dPoint4d(ck, pointC, pointC2); - const e = 1.0e-14; // well below coordinate tolerance + const e = 1.0e-14; // well below coordinate tolerance ck.testTrue(pointC.isAlmostEqualXYZW(dataD[0], dataD[1], dataD[2], dataD[3])); const q = 1.0 + e; ck.testTrue(pointC.isAlmostEqualXYZW(dataD[0] * q, dataD[1] * q + e, dataD[2] / q, dataD[3] / q + e)); @@ -55,10 +61,18 @@ describe("Point4d", () => { const pointA1 = pointA.clone(); ck.testTrue(pointA1.isAlmostEqual(pointA)); - pointA1.x += f; ck.testFalse(pointA1.isAlmostEqual(pointA)); pointA1.setFrom(pointA); - pointA1.y += f; ck.testFalse(pointA1.isAlmostEqual(pointA)); pointA1.setFrom(pointA); - pointA1.z += f; ck.testFalse(pointA1.isAlmostEqual(pointA)); pointA1.setFrom(pointA); - pointA1.w += f; ck.testFalse(pointA1.isAlmostEqual(pointA)); pointA1.setFrom(pointA); + pointA1.x += f; + ck.testFalse(pointA1.isAlmostEqual(pointA)); + pointA1.setFrom(pointA); + pointA1.y += f; + ck.testFalse(pointA1.isAlmostEqual(pointA)); + pointA1.setFrom(pointA); + pointA1.z += f; + ck.testFalse(pointA1.isAlmostEqual(pointA)); + pointA1.setFrom(pointA); + pointA1.w += f; + ck.testFalse(pointA1.isAlmostEqual(pointA)); + pointA1.setFrom(pointA); pointC.setFromJSON([1]); testExactPoint4dXYZW(ck, pointC, 0, 0, 0, 0); @@ -122,8 +136,7 @@ describe("Point4d", () => { ck.testCoordinate(0.0, pointB.dotProduct(planeABZ)); ck.testCoordinate(0.0, planeABZ.dotProductXYZW(0, 0, 1, 0)); const pointU0 = Point4d.create(3, 7, 11, 0); - ck.testCoordinate(pointB.velocityXYZ(pointU0.x, pointU0.y, pointU0.z), - pointB.dotProductXYZW(pointU0.x, pointU0.y, pointU0.z, 0.0)); + ck.testCoordinate(pointB.velocityXYZ(pointU0.x, pointU0.y, pointU0.z), pointB.dotProductXYZW(pointU0.x, pointU0.y, pointU0.z, 0.0)); const pointC = Point3d.create(1, 2, 9); const pointCH = Point4d.createFromPointAndWeight(pointC, 1.0); @@ -142,7 +155,7 @@ describe("Point4d", () => { const workPlane = Plane3dByOriginAndUnitNormal.createXYPlane(); Plane3dByOriginAndUnitNormal.create(Point3d.createZero(), Vector3d.createZero(), workPlane); const zeroPoint = Point4d.createZero(); - zeroPoint.setComponent(3, 1); // homogeneous "zero" has weight 1 + zeroPoint.setComponent(3, 1); // homogeneous "zero" has weight 1 const testPoint = Point4d.createFromPoint([1, 4, 9, 16]); let workPoint = Point4d.createFromPoint(testPoint); ck.testPoint4d(testPoint, workPoint); @@ -171,11 +184,11 @@ describe("Point4d", () => { const a = Math.sqrt(pt.magnitudeSquaredXYZ()); const direction = Vector3d.create(pt.x, pt.y, pt.z); const w = pt.w; - const divA = Geometry.conditionalDivideFraction(1.0, a); // much tighter than smallMetricTol! + const divA = Geometry.conditionalDivideFraction(1.0, a); // much tighter than smallMetricTol! if (divA !== undefined) { const divASquared = divA * divA; const b = -w * divASquared; - direction.scaleInPlace(divASquared); // wrong, but renormalized later + direction.scaleInPlace(divASquared); // wrong, but renormalized later return Plane3dByOriginAndUnitNormal.create(Point3d.create(pt.x * b, pt.y * b, pt.z * b), direction); } return undefined; @@ -199,15 +212,24 @@ describe("Point4d", () => { for (let count = 0; count < 100; ++count) { const pt = Point4d.create(randomCoordinate(size), randomCoordinate(size), randomCoordinate(size), randomCoordinate(size)); const oldPlane = toPlane3dByOriginAndUnitNormalOrig(pt); - const newPlane = (count % 2) ? pt.toPlane3dByOriginAndUnitNormal(workPlane) : pt.toPlane3dByOriginAndUnitNormal(); // cover both + const newPlane = (count % 2) ? pt.toPlane3dByOriginAndUnitNormal(workPlane) : pt.toPlane3dByOriginAndUnitNormal(); // cover both ck.testTrue((!!oldPlane && !!newPlane) || !oldPlane, "new plane successfully constructed at least as often as oldPlane"); if (oldPlane && newPlane) { - ck.testPoint3d(oldPlane.getOriginRef(), newPlane.getOriginRef(), `for pt = (${pt.x}, ${pt.y}, ${pt.z}, ${pt.w}), plane implementations have same origins`); - ck.testVector3d(oldPlane.getNormalRef(), newPlane.getNormalRef(), `for pt = (${pt.x}, ${pt.y}, ${pt.z}, ${pt.w}), plane implementations have same normals`); - } else if (!!oldPlane && !newPlane) { // error case: recompute to debug + ck.testPoint3d( + oldPlane.getOriginRef(), + newPlane.getOriginRef(), + `for pt = (${pt.x}, ${pt.y}, ${pt.z}, ${pt.w}), plane implementations have same origins`, + ); + ck.testVector3d( + oldPlane.getNormalRef(), + newPlane.getNormalRef(), + `for pt = (${pt.x}, ${pt.y}, ${pt.z}, ${pt.w}), plane implementations have same normals`, + ); + } else if (!!oldPlane && !newPlane) { // error case: recompute to debug const oldPlane1 = toPlane3dByOriginAndUnitNormalOrig(pt); const newPlane1 = pt.toPlane3dByOriginAndUnitNormal(); - ck.testDefined(oldPlane1); ck.testUndefined(newPlane1); // silence linter + ck.testDefined(oldPlane1); + ck.testUndefined(newPlane1); // silence linter } } } @@ -254,8 +276,10 @@ describe("Point4d", () => { const pointB = Point4d.create(-1.1, 0.2, 5.3, 1.4); const xyzA = pointA.normalizeWeight()!; const xyzB = pointB.normalizeWeight()!; - const vectorA = xyzA.clone(); vectorA.w = 0.0; - const vectorB = xyzB.clone(); vectorB.w = 0.0; + const vectorA = xyzA.clone(); + vectorA.w = 0.0; + const vectorB = xyzB.clone(); + vectorB.w = 0.0; ck.testCoordinate(0.0, pointA.realDistanceXY(pointA)!); ck.testCoordinate(pointA.realDistanceXY(pointB)!, xyzA.realDistanceXY(xyzB)!); @@ -266,8 +290,10 @@ describe("Point4d", () => { it("Quaternions", () => { const ck = new Checker(); - const quatA = Point4d.create(3, 6, 9, 12); quatA.normalizeQuaternion(); - const quatB = Point4d.create(-1.1, 0.2, 5.3, 1.4); quatB.normalizeQuaternion(); + const quatA = Point4d.create(3, 6, 9, 12); + quatA.normalizeQuaternion(); + const quatB = Point4d.create(-1.1, 0.2, 5.3, 1.4); + quatB.normalizeQuaternion(); const quat0 = Point4d.interpolateQuaternions(quatA, 0, quatA); const quat1 = Point4d.interpolateQuaternions(quatB, 1.0, quatB); ck.testCoordinate(1.0, quatA.magnitudeXYZW()); @@ -282,15 +308,15 @@ describe("Point4d", () => { // const quatC = Point4d.interpolateQuaternions(quat0, 25, quat80); // ck.testPoint4d(quat20, quatC, "variant path to interpolant"); - const perp20 = Point4d.perpendicularPoint4dPlane(quat0, quat20, quat1); // The three inputs are in a plane. Quat should be zero? - const perp80 = Point4d.perpendicularPoint4dPlane(quat0, quat80, quat1); // The three inputs are in a plane. Quat should be zero? + const perp20 = Point4d.perpendicularPoint4dPlane(quat0, quat20, quat1); // The three inputs are in a plane. Quat should be zero? + const perp80 = Point4d.perpendicularPoint4dPlane(quat0, quat80, quat1); // The three inputs are in a plane. Quat should be zero? ck.testCoordinate(0.0, perp20.magnitudeXYZW(), "coplanar quaternions have 0 cross product."); ck.testCoordinate(0.0, perp80.magnitudeXYZW(), "coplanar quaternions have 0 cross product."); const epsilon = 0.000001; const nearly1 = 1.0 - epsilon; const quatQ0 = Point4d.interpolateQuaternions(quat0, epsilon, quat1); const quatQ1 = Point4d.interpolateQuaternions(quat0, nearly1, quat1); - const quat0Q0 = Point4d.interpolateQuaternions(quat0, 0.8, quatQ0); // nearly parallel !!! + const quat0Q0 = Point4d.interpolateQuaternions(quat0, 0.8, quatQ0); // nearly parallel !!! ck.testLE(quat1.distanceXYZW(quatQ1), epsilon); ck.testLE(quat0.distanceXYZW(quat0Q0), epsilon); diff --git a/core/geometry/src/test/misc/DeepCompare.test.ts b/core/geometry/src/test/misc/DeepCompare.test.ts index 1d066a136df3..317d86d7a3bf 100644 --- a/core/geometry/src/test/misc/DeepCompare.test.ts +++ b/core/geometry/src/test/misc/DeepCompare.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { DeepCompare } from "../../serialization/DeepCompare"; import { Checker } from "../Checker"; @@ -45,5 +45,4 @@ describe("DeepCompare", () => { ck.checkpoint("DeepCompare.BasicTests"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/misc/Geometry.test.ts b/core/geometry/src/test/misc/Geometry.test.ts index 91730dc18dfa..89b44512deb7 100644 --- a/core/geometry/src/test/misc/Geometry.test.ts +++ b/core/geometry/src/test/misc/Geometry.test.ts @@ -80,7 +80,9 @@ describe("Geometry", () => { class GeometryCheck { public ck: Checker; - public constructor() { this.ck = new Checker(); } + public constructor() { + this.ck = new Checker(); + } public testTrigForm(a: number, cosCoff: number, sinCoff: number): void { const rootA = Geometry.solveTrigForm(a, cosCoff, sinCoff); @@ -94,7 +96,6 @@ class GeometryCheck { // no roots. expect trig condition .... this.ck.testCoordinateOrder(Geometry.hypotenuseXY(cosCoff, sinCoff), Math.abs(a), " no-root coff condition"); } - } public testQuadratic(a: number, b: number, c: number): void { const rootA = Degree2PowerPolynomial.solveQuadratic(a, b, c); @@ -106,7 +107,6 @@ class GeometryCheck { } else { this.ck.testCoordinateOrder(b * b - 4 * a * c, 0.0, " no-root coff condition"); } - } } describe("Geometry.solveTrigForm", () => { @@ -114,7 +114,7 @@ describe("Geometry.solveTrigForm", () => { const gc = new GeometryCheck(); gc.testTrigForm(0, 1, 0); gc.testTrigForm(0.2, 0.3, 0.9); - gc.testTrigForm(5, 1, 1); // no solutions !!! + gc.testTrigForm(5, 1, 1); // no solutions !!! expect(gc.ck.getNumErrors()).toBe(0); }); @@ -161,7 +161,6 @@ describe("Geometry.modulo", () => { ck.testAngleAllowShift(theta, theta1, "JSON: simple number (radians)"); theta3.setFromJSON(theta); // typed Angle ck.testAngleAllowShift(theta, theta3, "JSON: strongly typed Angle object"); - } expect(gc.ck.getNumErrors()).toBe(0); }); @@ -227,11 +226,15 @@ describe("GeometryA", () => { // clamping with reversed ends ck.testExactNumber( Geometry.clampToStartEnd(a, 2, 4), - Geometry.clampToStartEnd(a, 4, 2), "Clamp is same result with reversed ends"); + Geometry.clampToStartEnd(a, 4, 2), + "Clamp is same result with reversed ends", + ); // modulo with negated period ck.testCoordinate( Geometry.modulo(a, 4), - -Geometry.modulo(-a, -4), "Modulo with negative period"); + -Geometry.modulo(-a, -4), + "Modulo with negative period", + ); ck.testExactNumber(a, Geometry.modulo(a, 0), "modulo with zero period"); } const q: any[] = [1, 2, 3, 6, 9]; @@ -253,10 +256,12 @@ describe("GeometryA", () => { } // inverse interpolate with huge target and small interval . . . ck.testUndefined( - Geometry.inverseInterpolate(0, 1, 1, 3, 1.0e12)); + Geometry.inverseInterpolate(0, 1, 1, 3, 1.0e12), + ); const e = Geometry.smallAngleRadians; ck.testUndefined( - Geometry.inverseInterpolate(0, 1, 1, 1 + e, 1000)); + Geometry.inverseInterpolate(0, 1, 1, 1 + e, 1000), + ); ck.testExactNumber(Geometry.stepCount(0, 100, 4, 30), 4, "stepSize 0 returns min"); ck.testExactNumber(Geometry.stepCount(200, 100, 4, 30), 4, "stepSize huge returns min"); @@ -292,5 +297,4 @@ describe("GeometryA", () => { ck.testTrue(Number.isFinite(Number.MAX_VALUE)); ck.testFalse(Number.isFinite(Number.NaN)); }); - }); diff --git a/core/geometry/src/test/misc/performance.test.ts b/core/geometry/src/test/misc/performance.test.ts index 959cb18624e4..c244c5f458c5 100644 --- a/core/geometry/src/test/misc/performance.test.ts +++ b/core/geometry/src/test/misc/performance.test.ts @@ -13,9 +13,16 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function inverseCalculationLoop(numTest: number, usingCache: boolean, usingResult: boolean) { const savedFlag = Matrix3d.useCachedInverse; const matrix = Matrix3dOps.createRowValues( - 5, 1, 2, - 3, 8, 2, - 1, -2, 8); + 5, + 1, + 2, + 3, + 8, + 2, + 1, + -2, + 8, + ); // Give result storage a temporary value let inverse: Matrix3d = Matrix3d.createIdentity(); @@ -191,7 +198,7 @@ function arrayCheck(numTest: number, type: number) { const toPush = Point3d.create(1, 2, 3); switch (type) { - case 1: // Normal Javascript array (float) + case 1: // Normal Javascript array (float) name = "Javascript_Float_Array"; arr = [10, 1, 9, 2]; GeometryCoreTestIO.consoleTime(name); @@ -220,10 +227,13 @@ function arrayCheck(numTest: number, type: number) { GeometryCoreTestIO.consoleTimeEnd(name); break; - case 2: // Growable array (float) + case 2: // Growable array (float) name = "Growable_Float_Array"; arr = new GrowableFloat64Array(); - arr.push(10); arr.push(1); arr.push(9); arr.push(2); + arr.push(10); + arr.push(1); + arr.push(9); + arr.push(2); GeometryCoreTestIO.consoleTime(name); for (let i = 0; i < numTest; i++) { // Fetch items @@ -250,7 +260,7 @@ function arrayCheck(numTest: number, type: number) { GeometryCoreTestIO.consoleTimeEnd(name); break; - case 3: // Javascript array (point) + case 3: // Javascript array (point) name = "Javascript_Point_Array"; arr = [Point3d.create(0, 0, 0), Point3d.create(1, 1, 1), Point3d.create(2, 2, 2)]; GeometryCoreTestIO.consoleTime(name); @@ -279,11 +289,13 @@ function arrayCheck(numTest: number, type: number) { GeometryCoreTestIO.consoleTimeEnd(name); break; - case 4: // Growable array (Point) + case 4: // Growable array (Point) name = "Growable_Point_Array"; arr = new GrowableXYZArray(); const result = Point3d.create(); - arr.push(Point3d.create(0, 0, 0)); arr.push(Point3d.create(1, 1, 1)); arr.push(Point3d.create(2, 2, 2)); + arr.push(Point3d.create(0, 0, 0)); + arr.push(Point3d.create(1, 1, 1)); + arr.push(Point3d.create(2, 2, 2)); GeometryCoreTestIO.consoleTime(name); for (let i = 0; i < numTest; i++) { // Fetch items @@ -317,30 +329,30 @@ export class Matrix3dOps extends Matrix3d { public static multiplyMatrixMatrixdirectAssignment(matrixA: Matrix3d, matrixB: Matrix3d, result?: Matrix3d): Matrix3d { // WARNING -- matrixA does not allow result to be the same as one of the inputs . . . result = result ? result : new Matrix3d(); - result.coffs[0] = (matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6]); - result.coffs[1] = (matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7]); - result.coffs[2] = (matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8]); - result.coffs[3] = (matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6]); - result.coffs[4] = (matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7]); - result.coffs[5] = (matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8]); - result.coffs[6] = (matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6]); - result.coffs[7] = (matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7]); - result.coffs[8] = (matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8]); + result.coffs[0] = matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6]; + result.coffs[1] = matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7]; + result.coffs[2] = matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8]; + result.coffs[3] = matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6]; + result.coffs[4] = matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7]; + result.coffs[5] = matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8]; + result.coffs[6] = matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6]; + result.coffs[7] = matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7]; + result.coffs[8] = matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8]; return result; } public static multiplyMatrixMatrixdirectAssignmentN(numReps: number, matrixA: Matrix3d, matrixB: Matrix3d, result?: Matrix3d): Matrix3d { // WARNING -- matrixA does not allow result to be the same as one of the inputs . . . result = result ? result : new Matrix3d(); for (let i = 0; i < numReps; i++) { - result.coffs[0] = (matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6]); - result.coffs[1] = (matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7]); - result.coffs[2] = (matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8]); - result.coffs[3] = (matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6]); - result.coffs[4] = (matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7]); - result.coffs[5] = (matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8]); - result.coffs[6] = (matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6]); - result.coffs[7] = (matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7]); - result.coffs[8] = (matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8]); + result.coffs[0] = matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6]; + result.coffs[1] = matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7]; + result.coffs[2] = matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8]; + result.coffs[3] = matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6]; + result.coffs[4] = matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7]; + result.coffs[5] = matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8]; + result.coffs[6] = matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6]; + result.coffs[7] = matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7]; + result.coffs[8] = matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8]; } return result; @@ -349,20 +361,20 @@ export class Matrix3dOps extends Matrix3d { /** Multiply two matrices */ public static multiplyMatrixMatrix(matrixA: Matrix3d, matrixB: Matrix3d, result?: Matrix3d): Matrix3d { return Matrix3d.createRowValues( - (matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6]), - (matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7]), - (matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8]), - (matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6]), - (matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7]), - (matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8]), - (matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6]), - (matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7]), - (matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8]), - result); + matrixA.coffs[0] * matrixB.coffs[0] + matrixA.coffs[1] * matrixB.coffs[3] + matrixA.coffs[2] * matrixB.coffs[6], + matrixA.coffs[0] * matrixB.coffs[1] + matrixA.coffs[1] * matrixB.coffs[4] + matrixA.coffs[2] * matrixB.coffs[7], + matrixA.coffs[0] * matrixB.coffs[2] + matrixA.coffs[1] * matrixB.coffs[5] + matrixA.coffs[2] * matrixB.coffs[8], + matrixA.coffs[3] * matrixB.coffs[0] + matrixA.coffs[4] * matrixB.coffs[3] + matrixA.coffs[5] * matrixB.coffs[6], + matrixA.coffs[3] * matrixB.coffs[1] + matrixA.coffs[4] * matrixB.coffs[4] + matrixA.coffs[5] * matrixB.coffs[7], + matrixA.coffs[3] * matrixB.coffs[2] + matrixA.coffs[4] * matrixB.coffs[5] + matrixA.coffs[5] * matrixB.coffs[8], + matrixA.coffs[6] * matrixB.coffs[0] + matrixA.coffs[7] * matrixB.coffs[3] + matrixA.coffs[8] * matrixB.coffs[6], + matrixA.coffs[6] * matrixB.coffs[1] + matrixA.coffs[7] * matrixB.coffs[4] + matrixA.coffs[8] * matrixB.coffs[7], + matrixA.coffs[6] * matrixB.coffs[2] + matrixA.coffs[7] * matrixB.coffs[5] + matrixA.coffs[8] * matrixB.coffs[8], + result, + ); } } class TimingTests { - public static runTestA(numTest: number) { GeometryCoreTestIO.consoleLog("\n performance reps ", numTest); const matrixA = Matrix3d.createScale(1, 2, 3); @@ -380,7 +392,6 @@ class TimingTests { for (let k = 0; k < numTest; k++) matrixD = matrixA.multiplyMatrixMatrix(matrixB, matrixD); GeometryCoreTestIO.consoleTimeEnd("multiplyMatrixMatrix(result)"); - } public static runTestB(numTest: number) { const matrixA = Matrix3dOps.createScale(1, 2, 3); diff --git a/core/geometry/src/test/numerics/AnalyticRoots.test.ts b/core/geometry/src/test/numerics/AnalyticRoots.test.ts index e57d1763b798..30a3e8b99667 100644 --- a/core/geometry/src/test/numerics/AnalyticRoots.test.ts +++ b/core/geometry/src/test/numerics/AnalyticRoots.test.ts @@ -13,7 +13,15 @@ import { Point2d, Vector2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { NumberArray } from "../../geometry3d/PointHelpers"; import { Point4d } from "../../geometry4d/Point4d"; -import { AnalyticRoots, BilinearPolynomial, Degree2PowerPolynomial, Degree3PowerPolynomial, PowerPolynomial, SmallSystem, TrigPolynomial } from "../../numerics/Polynomials"; +import { + AnalyticRoots, + BilinearPolynomial, + Degree2PowerPolynomial, + Degree3PowerPolynomial, + PowerPolynomial, + SmallSystem, + TrigPolynomial, +} from "../../numerics/Polynomials"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; @@ -44,7 +52,6 @@ describe("AnalyticRoots.SolveLinear", () => { }); }); describe("AnalyticRoots.SolveQuadric", () => { - it("SolveQuadric.DoubleRoot", () => { const ck = new Checker(); for (let i = 3; i < 8; i += 2) { @@ -73,7 +80,7 @@ describe("AnalyticRoots.SolveQuadric", () => { it("SolveQuadric.TwoSolutions", () => { const ck = new Checker(); - for (const root0 of [1, - 3, 100]) { + for (const root0 of [1, -3, 100]) { for (const root1 of [5.4, 2.3]) { const quadric = Degree2PowerPolynomial.fromRootsAndC2(root0, root1); const roots = new GrowableFloat64Array(); @@ -120,25 +127,50 @@ describe("AnalyticRoots.SolveQuadric", () => { it("SmallSystemFailures", () => { const ck = new Checker(); ck.testUndefined(SmallSystem.linearSystem3d( - 1, 2, 3, - 1, 2, 5, - 1, 2, 0, - 1, 2, 3)); + 1, + 2, + 3, + 1, + 2, + 5, + 1, + 2, + 0, + 1, + 2, + 3, + )); const result = Vector2d.create(); ck.testFalse(SmallSystem.linearSystem2d( - 1, 2, - 1, 2, - 1, 2, result)); + 1, + 2, + 1, + 2, + 1, + 2, + result, + )); ck.testUndefined(SmallSystem.lineSegment3dHXYTransverseIntersectionUnbounded( - Point4d.create(0, 0, 0, 1), Point4d.create(1, 0, 0, 1), - Point4d.create(1, 0, 0, 1), Point4d.create(2, 0, 0, 1))); + Point4d.create(0, 0, 0, 1), + Point4d.create(1, 0, 0, 1), + Point4d.create(1, 0, 0, 1), + Point4d.create(2, 0, 0, 1), + )); ck.testFalse(SmallSystem.lineSegment3dXYTransverseIntersectionUnbounded( - Point3d.create(0, 0, 0), Point3d.create(1, 0, 0), - Point3d.create(1, 0, 0), Point3d.create(2, 0, 0), result)); + Point3d.create(0, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(1, 0, 0), + Point3d.create(2, 0, 0), + result, + )); ck.testFalse(SmallSystem.lineSegment2dXYTransverseIntersectionUnbounded( - Point2d.create(0, 0), Point2d.create(1, 0), - Point2d.create(1, 0), Point2d.create(2, 0), result)); + Point2d.create(0, 0), + Point2d.create(1, 0), + Point2d.create(1, 0), + Point2d.create(2, 0), + result, + )); ck.checkpoint("SmallSystemFailures"); expect(ck.getNumErrors()).toBe(0); }); @@ -151,7 +183,11 @@ describe("AnalyticRoots.SolveQuadric", () => { const r = SmallSystem.lineSegment3dClosestPointUnbounded(pointA, pointB, pointC); if (ck.testDefined(r)) { const pointD = pointA.interpolate(r, pointB); - ck.testPerpendicular(Vector3d.createStartEnd(pointA, pointB), Vector3d.createStartEnd(pointC, pointD), "Closest approach vector is perpendicular"); + ck.testPerpendicular( + Vector3d.createStartEnd(pointA, pointB), + Vector3d.createStartEnd(pointC, pointD), + "Closest approach vector is perpendicular", + ); } ck.checkpoint("lineSegment3dClosestPointUnbounded"); expect(ck.getNumErrors()).toBe(0); @@ -159,16 +195,22 @@ describe("AnalyticRoots.SolveQuadric", () => { it("BilinearSystemXY", () => { const ck = new Checker(); - for (const p of [ - new BilinearPolynomial(0, 1, 0, 0), - new BilinearPolynomial(0, 1, 0, 1), - new BilinearPolynomial(1, 2, 0.2, 3), - BilinearPolynomial.createUnitSquareValues(1, 0, 0, 1)]) { - for (const q of [ - new BilinearPolynomial(0, 0, 1, 0), - new BilinearPolynomial(0, 0, 2, 1), - new BilinearPolynomial(-1, 0.2, 3, -0.5), - BilinearPolynomial.createUnitSquareValues(0, 1, 1.1, 0.5)]) { + for ( + const p of [ + new BilinearPolynomial(0, 1, 0, 0), + new BilinearPolynomial(0, 1, 0, 1), + new BilinearPolynomial(1, 2, 0.2, 3), + BilinearPolynomial.createUnitSquareValues(1, 0, 0, 1), + ] + ) { + for ( + const q of [ + new BilinearPolynomial(0, 0, 1, 0), + new BilinearPolynomial(0, 0, 2, 1), + new BilinearPolynomial(-1, 0.2, 3, -0.5), + BilinearPolynomial.createUnitSquareValues(0, 1, 1.1, 0.5), + ] + ) { for (const uv0 of [Point2d.create(0.1, 0.4), Point2d.create(1, 2)]) { const pValue = p.evaluate(uv0.x, uv0.y); const qValue = q.evaluate(uv0.x, uv0.y); @@ -196,8 +238,11 @@ describe("AnalyticRoots.SolveQuadric", () => { }); it("RowElimination", () => { const ck = new Checker(); - for (const rowA of [ - new Float64Array([4, 3, 4, 5, 6])]) { + for ( + const rowA of [ + new Float64Array([4, 3, 4, 5, 6]), + ] + ) { for (const rowB of [new Float64Array([1, 2, 1, 3, 2])]) { const rowB1 = rowB.slice(); SmallSystem.eliminateFromPivot(rowA, 0, rowB1, -1.0); @@ -212,7 +257,6 @@ describe("AnalyticRoots.SolveQuadric", () => { } expect(ck.getNumErrors()).toBe(0); }); - }); // Cubic and Quartic tests (taken from t_analyticRoots.cpp) -------------------------------- @@ -262,21 +306,19 @@ function newtonStep4(coffs: Float64Array, u: number) { const f = coffs[0] + u * (coffs[1] + u * (coffs[2] + u * (coffs[3] + u * coffs[4]))); const df = coffs[1] + u * (2.0 * coffs[2] + u * (3.0 * coffs[3] + u * 4.0 * coffs[4])); return f / df; - } // check solutions of (x-a) (x^2 + b^2) describe("AnalyticRoots.SolveCubic", () => { - it("SolveCubic.Cubic1", () => { const ck = new Checker(); const b = 100.0; for (let a = 0.0; a < 1000; a = 10.0 * (a + 1.0)) { const coffs = new Float64Array(4); coffs[3] = 1.0; - coffs[2] = - a; + coffs[2] = -a; coffs[1] = b * b; - coffs[0] = - b * b * a; + coffs[0] = -b * b * a; const target: number[] = [a]; const actual = new GrowableFloat64Array(); AnalyticRoots.appendCubicRoots(coffs, actual); @@ -310,9 +352,9 @@ describe("AnalyticRoots.SolveCubic", () => { const coffs = new Float64Array(4); coffs[3] = 1.0; - coffs[2] = - NumberArray.preciseSum([u0, u1, u2]); + coffs[2] = -NumberArray.preciseSum([u0, u1, u2]); coffs[1] = NumberArray.preciseSum([u0 * u1, u1 * u2, u0 * u2]); - coffs[0] = - u0 * u1 * u2; + coffs[0] = -u0 * u1 * u2; const target = [u0, u1, u2]; target.sort(compare); @@ -329,9 +371,19 @@ describe("AnalyticRoots.SolveCubic", () => { // Check::True (eMax < 1.0e-14 * DoubleOps::MaxAbs (target), "root error"); GeometryCoreTestIO.consoleLog("Cubic root variances. These may be expected behavior under extreme origin conditions"); GeometryCoreTestIO.consoleLog(` (known roots ${target[0]} ${target[1]} ${target[2]}) (eMax ${eMax}) (eSafe ${eSafe}`); - GeometryCoreTestIO.consoleLog(` (computed roots ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)}`); - GeometryCoreTestIO.consoleLog(` (correction by newton from computed root ${newtonStep(coffs, actual.atUncheckedIndex(0))} ${newtonStep(coffs, actual.atUncheckedIndex(1))} ${newtonStep(coffs, actual.atUncheckedIndex(2))}`); - GeometryCoreTestIO.consoleLog(` (correction by newton from known root ${newtonStep(coffs, target[0])} ${newtonStep(coffs, target[1])} ${newtonStep(coffs, target[2])}`); + GeometryCoreTestIO.consoleLog( + ` (computed roots ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)}`, + ); + GeometryCoreTestIO.consoleLog( + ` (correction by newton from computed root ${newtonStep(coffs, actual.atUncheckedIndex(0))} ${ + newtonStep(coffs, actual.atUncheckedIndex(1)) + } ${newtonStep(coffs, actual.atUncheckedIndex(2))}`, + ); + GeometryCoreTestIO.consoleLog( + ` (correction by newton from known root ${newtonStep(coffs, target[0])} ${newtonStep(coffs, target[1])} ${ + newtonStep(coffs, target[2]) + }`, + ); } } @@ -409,7 +461,7 @@ describe("AnalyticRoots.SolveCubic", () => { function checkQuartic(u0: number, u1: number, u2: number, u3: number, tolerance: number, ck: Checker) { const coffs = new Float64Array(5); coffs[4] = 1.0; - coffs[3] = - NumberArray.preciseSum([u0, u1, u2, u3]); + coffs[3] = -NumberArray.preciseSum([u0, u1, u2, u3]); const xx: number[] = []; xx[0] = u0 * u1; xx[1] = u0 * u2; @@ -435,21 +487,30 @@ function checkQuartic(u0: number, u1: number, u2: number, u3: number, tolerance: const ok: boolean = ck.testTrue(eMax < tolerance, "quartic root tolerance", eMax, tolerance); // Accurate when compared to multiple of 1.0e-8... any higher negative power likely to fail if (Checker.noisy.quarticRoots) { - GeometryCoreTestIO.consoleLog(` (actual ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)} ${actual.atUncheckedIndex(3)})`); + GeometryCoreTestIO.consoleLog( + ` (actual ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)} ${actual.atUncheckedIndex(3)})`, + ); GeometryCoreTestIO.consoleLog(` (target ${target[0]} ${target[1]} ${target[2]} ${target[3]})`); - } // Additional testing based on NewtonStep for (let step = 0; (step < 10) && (eMax > 1.0e-14); step++) { if (!ok || printAll) { - GeometryCoreTestIO.consoleLog(` (actualDX ${newtonStep4(coffs, actual.atUncheckedIndex(0))} ${newtonStep4(coffs, actual.atUncheckedIndex(1))} ${newtonStep4(coffs, actual.atUncheckedIndex(2))} ${newtonStep4(coffs, actual.atUncheckedIndex(3))} `); + GeometryCoreTestIO.consoleLog( + ` (actualDX ${newtonStep4(coffs, actual.atUncheckedIndex(0))} ${newtonStep4(coffs, actual.atUncheckedIndex(1))} ${ + newtonStep4(coffs, actual.atUncheckedIndex(2)) + } ${newtonStep4(coffs, actual.atUncheckedIndex(3))} `, + ); for (let k = 0; k < actual.length; k++) { actual.reassign(k, actual.atUncheckedIndex(k) - newtonStep4(coffs, actual.atUncheckedIndex(k))); } eMax = matchRoots(target, actual) / uMax; if (!ok || printAll) { - GeometryCoreTestIO.consoleLog(` (actual ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)} ${actual.atUncheckedIndex(3)} (eMax ${eMax}) `); + GeometryCoreTestIO.consoleLog( + ` (actual ${actual.atUncheckedIndex(0)} ${actual.atUncheckedIndex(1)} ${actual.atUncheckedIndex(2)} ${ + actual.atUncheckedIndex(3) + } (eMax ${eMax}) `, + ); } } } @@ -527,7 +588,6 @@ describe("AnalyticRoots.CheckQuartic", () => { ck.testTrue(testRoots4(coff, roots), "Verify quartic roots"); } expect(ck.getNumErrors()).toBe(0); - }); }); // cspell:word bezroot @@ -593,13 +653,14 @@ describe("AnalyticRoots", () => { for (const x2 of [0, 0.5, 0.10]) { if (noisy) GeometryCoreTestIO.consoleLog("*****************"); - const x3 = - (x0 + x1 + x2); + const x3 = -(x0 + x1 + x2); const quarticCoffs = new Float64Array([ x0 * x1 * x2 * x3, -(x0 * x1 * x2 + x0 * x1 * x3 + x0 * x2 * x3 + x1 * x2 * x3), x0 * x1 + x0 * x2 + x0 * x3 + x1 * x2 + x1 * x3 + x2 * x3, - - (x0 + x1 + x2 + x3), - 1.0]); + -(x0 + x1 + x2 + x3), + 1.0, + ]); const quarticRoots0 = new GrowableFloat64Array(4); AnalyticRoots.appendQuarticRoots(quarticCoffs, quarticRoots0); if (noisy) { @@ -620,7 +681,6 @@ describe("AnalyticRoots", () => { } } }); - }); describe("Geometry", () => { it("Curvature", () => { @@ -629,10 +689,20 @@ describe("Geometry", () => { const arc = Arc3d.createXY(Point3d.create(1, 2, 3), 2.123, AngleSweep.create360()); for (const fraction of [0.0, 0.25]) { const derivatives = arc.fractionToPointAnd2Derivatives(fraction); - const curvature = Geometry.curvatureMagnitude(derivatives.vectorU.x, derivatives.vectorU.y, derivatives.vectorU.z, - derivatives.vectorV.x, derivatives.vectorV.y, derivatives.vectorV.z); + const curvature = Geometry.curvatureMagnitude( + derivatives.vectorU.x, + derivatives.vectorU.y, + derivatives.vectorU.z, + derivatives.vectorV.x, + derivatives.vectorV.y, + derivatives.vectorV.z, + ); ck.testCoordinate(1.0 / r, curvature, "circle curvature"); - ck.testExactNumber(0, Geometry.curvatureMagnitude(derivatives.vectorU.x, derivatives.vectorU.y, derivatives.vectorU.z, 0, 0, 0), "line curvature"); + ck.testExactNumber( + 0, + Geometry.curvatureMagnitude(derivatives.vectorU.x, derivatives.vectorU.y, derivatives.vectorU.z, 0, 0, 0), + "line curvature", + ); } ck.testExactNumber(0, Geometry.curvatureMagnitude(0, 0, 0, 1, 2, 3), "curvature with no first derivative"); expect(ck.getNumErrors()).toBe(0); @@ -668,13 +738,12 @@ describe("Geometry", () => { expect(ck.getNumErrors()).toBe(0); }); - }); it("NickelsA", () => { const ck = new Checker(); for (const b of [0, 0.3, -0.3, 5, -5]) { for (const a of [1, -1]) { - for (const c of [1, 0, - 1]) { + for (const c of [1, 0, -1]) { for (const d of [0, 0.2, -0.2, 0.8, -0.8, 1.0, -1.0, 2.0, -2.0]) { const cubic = new Degree3PowerPolynomial(d, c, b, a); const roots = new GrowableFloat64Array(); @@ -712,7 +781,7 @@ it("NickelsThreeRootCases", () => { const a = s; const b = -s * (r0 + r1 + r2); const c = s * (r0 * r1 + r1 * r2 + r0 * r2); - const d = - s * r0 * r1 * r2; + const d = -s * r0 * r1 * r2; const roots = new GrowableFloat64Array(); AnalyticRoots.appendCubicRoots([d, c, b, a], roots); ck.testTrue(findRoot(r0, roots), a, b, c, d); diff --git a/core/geometry/src/test/numerics/BandedSystem.test.ts b/core/geometry/src/test/numerics/BandedSystem.test.ts index f3580a344d88..967e37ac6992 100644 --- a/core/geometry/src/test/numerics/BandedSystem.test.ts +++ b/core/geometry/src/test/numerics/BandedSystem.test.ts @@ -29,7 +29,14 @@ function maxDiff(arrayA: Float64Array, arrayB: Float64Array): number { * @param diagonalBaseValue value for diagonals (varies with "a" effects) * @param a reference value for varying values, to be multiplied by cos(radians0 + i * radiansStep) with i advancing with each step across the rows. */ -function createBandedTestSystem(numRow: number, bw: number, diagonalBaseValue = 1.0, a: number = 0.1, radians0: number = 0.0, radiansStep: number = 0.04): Float64Array { +function createBandedTestSystem( + numRow: number, + bw: number, + diagonalBaseValue = 1.0, + a: number = 0.1, + radians0: number = 0.0, + radiansStep: number = 0.04, +): Float64Array { let radians = radians0; const matrix = new Float64Array(numRow * bw); const halfBand = Math.floor(bw / 2); @@ -54,10 +61,19 @@ describe("BandedSystem", () => { let a0 = 0; for (const a1 of [0, 0.1, 0.05]) { const bandedMatrix = new Float64Array([ - -3333, 2, a1, - a0, 3, a1, - a0, 4, a1, - a0, 5, 1000]); + -3333, + 2, + a1, + a0, + 3, + a1, + a0, + 4, + a1, + a0, + 5, + 1000, + ]); if (Checker.noisy.bandedMatrix) GeometryCoreTestIO.consoleLog("bandedMatrix", bandedMatrix); // const solution0 = new Float64Array([1, 2, 3, 4, 5, 6, 7, 8]); @@ -129,15 +145,21 @@ describe("BandedSystem", () => { allPoints.push(GrowableXYZArray.create([Point3d.create(1, 0, 0), Point3d.create(2, 3, 0), Point3d.create(3, 6, 0), Point3d.create(4, 9, 0)])); for (const yFactor of [1, 1.5, 2]) { for (const yy of [1, 3, 5]) - allPoints.push(GrowableXYZArray.create([Point3d.create(0, 0, 0), Point3d.create(0, yy, 0), Point3d.create(4, yFactor * yy + 1, 0), Point3d.create(5, 0, 0)])); + allPoints.push( + GrowableXYZArray.create([ + Point3d.create(0, 0, 0), + Point3d.create(0, yy, 0), + Point3d.create(4, yFactor * yy + 1, 0), + Point3d.create(5, 0, 0), + ]), + ); } allPoints.push(GrowableXYZArray.create([[0, 0], [0, 1], [1, 1], [1, 0], [2, 0], [2, 1], [3, 1]])); for (const count of [5, 6, 10]) allPoints.push(Sample.createGrowableArrayCirclePoints(3, count, true, 0, 0)); allPoints.push(GrowableXYZArray.create( - Sample.createPointSineWave(undefined, 25, 6.25, - 2.0, AngleSweep.createStartEndDegrees(0, 300), - 0.5, AngleSweep.createStartEndDegrees(0, 200)))); + Sample.createPointSineWave(undefined, 25, 6.25, 2.0, AngleSweep.createStartEndDegrees(0, 300), 0.5, AngleSweep.createStartEndDegrees(0, 200)), + )); for (const points of allPoints) { let y0 = 0; const range = points.getRange(); @@ -157,5 +179,4 @@ describe("BandedSystem", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "BandedSystem", "GrevilleBspline"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/numerics/Bezier.test.ts b/core/geometry/src/test/numerics/Bezier.test.ts index 749d265841bd..e7deec285ed2 100644 --- a/core/geometry/src/test/numerics/Bezier.test.ts +++ b/core/geometry/src/test/numerics/Bezier.test.ts @@ -36,11 +36,21 @@ describe("Bezier", () => { const b5 = new Order5Bezier(1, 16, 31, 46, 61); const scale = 3.4; const a = 7.0; - const b2A = b2.clone(); b2A.scaleInPlace(scale); b2A.addInPlace(a); - const b3A = b3.clone(); b3A.scaleInPlace(scale); b3A.addInPlace(a); - const b4A = b4.clone(); b4A.scaleInPlace(scale); b4A.addInPlace(a); - const b5A = b5.clone(); b5A.scaleInPlace(scale); b5A.addInPlace(a); - const b0A = b0.clone(); b0A.scaleInPlace(scale); b0A.addInPlace(a); + const b2A = b2.clone(); + b2A.scaleInPlace(scale); + b2A.addInPlace(a); + const b3A = b3.clone(); + b3A.scaleInPlace(scale); + b3A.addInPlace(a); + const b4A = b4.clone(); + b4A.scaleInPlace(scale); + b4A.addInPlace(a); + const b5A = b5.clone(); + b5A.scaleInPlace(scale); + b5A.addInPlace(a); + const b0A = b0.clone(); + b0A.scaleInPlace(scale); + b0A.addInPlace(a); for (const f of [0.1, 0.4]) { ck.testCoordinate(b2.evaluate(f), b3.evaluate(f)); ck.testCoordinate(b4.evaluate(f), b5.evaluate(f)); @@ -95,13 +105,13 @@ describe("Bezier", () => { }); }); describe("BezierRoots", () => { - it("Products", () => { const ck = new Checker(); const factors: BezierCoffs[] = [ new Order2Bezier(1, 2), new Order2Bezier(-2, -3), - new Order3Bezier(0.1, 0.5, -0.3)]; + new Order3Bezier(0.1, 0.5, -0.3), + ]; for (let i1 = 0; i1 < factors.length; i1++) { let bezier = factors[0].clone(); for (let i = 1; i <= i1; i++) @@ -167,20 +177,24 @@ describe("BezierRoots", () => { // This creates beziers with various coefficients, and solves by deflation. // It verifies that the deflate-based roots are roots. // It does NOT verify that all roots were found -- other tests start with known roots and do full verification. - for (const coffs of [ - [-a, -a, 1.0 - a], - [1, -4, 1], - [1, 1, -4, -3, 2], - [1, -4, 0.01, -2], - [1, 0.1, 0.1, -0.1, -5, 2]]) { + for ( + const coffs of [ + [-a, -a, 1.0 - a], + [1, -4, 1], + [1, 1, -4, -3, 2], + [1, -4, 0.01, -2], + [1, 0.1, 0.1, -0.1, -5, 2], + ] + ) { const bezier = UnivariateBezier.createCoffs(coffs); const bezier1 = bezier.clone(); const deflationRoots = UnivariateBezier.deflateRoots(bezier); - if (ck.testPointer(deflationRoots, "deflation produces roots", coffs)) + if (ck.testPointer(deflationRoots, "deflation produces roots", coffs)) { for (const r of deflationRoots) { const fOfR = bezier1.evaluate(r); ck.testCoordinate(0, fOfR, "bezier root", r, coffs); } + } // partial check for some other targets . . . for (let target = -0.4; target < 2; target += 0.1054) { const targetRoots = bezier1.roots(target, true); @@ -203,12 +217,15 @@ describe("BezierRoots", () => { for (let i = 0; i < numRoots; i++) baseRoots.push((1 + 2 * i) / (2 * numRoots)); // GeometryCoreTestIO.consoleLog(prettyPrint(baseRoots)); - for (const distributionFunction of [ - (x: number) => x, - (x: number) => Math.cos(x), - (x: number) => (0.1 * x), - (x: number) => (x + 0.001), - (x: number) => (Math.tan(x))]) { + for ( + const distributionFunction of [ + (x: number) => x, + (x: number) => Math.cos(x), + (x: number) => (0.1 * x), + (x: number) => (x + 0.001), + (x: number) => (Math.tan(x)), + ] + ) { const rootsA = []; for (const r of baseRoots) rootsA.push(distributionFunction(r)); let bezier = UnivariateBezier.createCoffs([-rootsA[0], 1 - rootsA[0]]); @@ -261,7 +278,6 @@ describe("BezierRoots", () => { it("DeflateRight", () => { const ck = new Checker(); for (const numZero of [1, 2, 3, 5, 6]) { - for (const numOther of [1, 2, 3, 5]) { const coffs = []; for (let i = 0; i < numOther; i++) @@ -276,7 +292,7 @@ describe("BezierRoots", () => { for (const u of [0, 0.1, 0.35, 0.5, 0.75, 1]) { let factor = 1; for (let i = 0; i < numDeflate; i++) - factor *= (1 - u); + factor *= 1 - u; ck.testCoordinate(bezierA.evaluate(u), factor * bezierB.evaluate(u), "right deflated bezier evaluation"); } } @@ -284,7 +300,6 @@ describe("BezierRoots", () => { } expect(ck.getNumErrors()).toBe(0); }); - }); describe("PascalCoefficients", () => { @@ -294,8 +309,10 @@ describe("PascalCoefficients", () => { for (const row of [1, 2, 3, 4, 5, 6, 7, 10, 9, 8, 12]) { const row0 = PascalCoefficients.getRow(row - 1); const row1 = PascalCoefficients.getRow(row); - if (ck.testExactNumber(row + 1, row1.length, "row1 length") - && ck.testExactNumber(row, row0.length, "row0 length")) { + if ( + ck.testExactNumber(row + 1, row1.length, "row1 length") + && ck.testExactNumber(row, row0.length, "row0 length") + ) { ck.testExactNumber(1, row1[0], row); ck.testExactNumber(1, row1[row], row); for (let i = 0; i + 1 < row; i++) { @@ -345,7 +362,7 @@ describe("PascalCoefficients", () => { const allData = []; for (const order of [1, 2, 3, 4, 5, 9]) { const lineStrings = []; - const subdivisionFactor = 5.0; // number of points between peaks + const subdivisionFactor = 5.0; // number of points between peaks const numValues = subdivisionFactor * 1 + subdivisionFactor * (order - 1); for (let i = 0; i < order; i++) lineStrings.push(LineString3d.create()); @@ -362,11 +379,12 @@ describe("PascalCoefficients", () => { const tic = 0.04; allData.push(LineString3d.createXY([ Point2d.create(-tic, y1), - Point2d.create(0, y1), Point2d.create(0, y0), - Point2d.create(1, y0), Point2d.create(1, y1), + Point2d.create(0, y1), + Point2d.create(0, y0), + Point2d.create(1, y0), + Point2d.create(1, y1), Point2d.create(1 + tic, y1), - ], - 0.0)); + ], 0.0)); y0 += dy; } GeometryCoreTestIO.saveGeometry(allData, "Bezier", "BasisFunctions"); @@ -385,8 +403,7 @@ describe("PascalCoefficients", () => { let x0 = 0.0; y0 += 4.0 * yShift; for (const order of [2, 4, 4, 2, 3, 6, 7, 9]) { - const bezier = Sample.createTwistingBezier(order, x0, y0, r, thetaStepper, phiStepper, - weighted ? Segment1d.create(1.0, 0.8) : undefined)!; + const bezier = Sample.createTwistingBezier(order, x0, y0, r, thetaStepper, phiStepper, weighted ? Segment1d.create(1.0, 0.8) : undefined)!; let transform = Sample.createMessyRigidTransform(Point3d.create(x0, y0, 0)); transform = Transform.createTranslationXYZ(0, yShift).multiplyTransformTransform(transform); x0 += dx; @@ -443,14 +460,17 @@ describe("PascalCoefficients", () => { const a = 10.0; for (let i = 0; i < 10; i++) { polygonX.push(i); - polygonX.push(a - i); // contrived so curve has y = a - x at all points. + polygonX.push(a - i); // contrived so curve has y = a - x at all points. } const polygonY = new Float64Array(polygonX); - for (const bezierA of [ - new Order2Bezier(0, 1), - new Order3Bezier(0, 1, 2), - new Order4Bezier(0, 1, 2, 3), - new Order5Bezier(0, 1, 2, 3, 4)]) { + for ( + const bezierA of [ + new Order2Bezier(0, 1), + new Order3Bezier(0, 1, 2), + new Order4Bezier(0, 1, 2, 3), + new Order5Bezier(0, 1, 2, 3, 4), + ] + ) { // GeometryCoreTestIO.consoleLog(prettyPrint (bezierA)); const bezierB = UnivariateBezier.create(bezierA); for (const u of [0, 0.2, 0.8]) { @@ -464,7 +484,7 @@ describe("PascalCoefficients", () => { const blockB1 = bezierB.sumBasisFunctionDerivatives(u, polygonY, 2); ck.testCoordinate(blockA1[0], blockB1[0]); ck.testCoordinate(blockA1[1], blockB1[1]); - ck.testCoordinate(blockA1[0], - blockA1[1]); + ck.testCoordinate(blockA1[0], -blockA1[1]); } } expect(ck.getNumErrors()).toBe(0); @@ -498,5 +518,4 @@ describe("PascalCoefficients", () => { expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/numerics/Newton.test.ts b/core/geometry/src/test/numerics/Newton.test.ts index 6ee937f316cd..3b4b1672043c 100644 --- a/core/geometry/src/test/numerics/Newton.test.ts +++ b/core/geometry/src/test/numerics/Newton.test.ts @@ -4,7 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { Newton1dUnbounded, Newton1dUnboundedApproximateDerivative, Newton2dUnboundedWithDerivative, NewtonEvaluatorRRtoRRD, NewtonEvaluatorRtoR, NewtonEvaluatorRtoRD, SimpleNewton } from "../../numerics/Newton"; +import { + Newton1dUnbounded, + Newton1dUnboundedApproximateDerivative, + Newton2dUnboundedWithDerivative, + NewtonEvaluatorRRtoRRD, + NewtonEvaluatorRtoR, + NewtonEvaluatorRtoRD, + SimpleNewton, +} from "../../numerics/Newton"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; @@ -58,10 +66,12 @@ describe("Newton", () => { const r1 = 10.0; const l1 = 1.0; const gamma = 1.0 / (40.0 * r1 * r1 * l1 * l1); - for (const f of [ - new HornerEvaluator([0, 1, 0, 0, 0, gamma]), - new ClothoidCosineEvaluator(1.0, r1, l1), - ]) { + for ( + const f of [ + new HornerEvaluator([0, 1, 0, 0, 0, gamma]), + new ClothoidCosineEvaluator(1.0, r1, l1), + ] + ) { const iterator = new Newton1dUnbounded(f); for (const fraction of [0.2, 0.8]) { const x = fraction * l1; @@ -103,9 +113,15 @@ export class Simple1DFunctionEvaluator2 extends NewtonEvaluatorRtoR { export class Simple2DFunctionEvaluator1 extends NewtonEvaluatorRRtoRRD { public evaluate(u: number, v: number): boolean { this.currentF.setOriginAndVectorsXYZ( - u - v + 1, u * u - v + 1, 0.0, // x(u,v), y(u,v), 0 - 1, 2 * u, 0.0, // dx/du, dy/du, 0 - -1, -1, 0.0, // dx/dv, dy/dv, 0 + u - v + 1, + u * u - v + 1, + 0.0, // x(u,v), y(u,v), 0 + 1, + 2 * u, + 0.0, // dx/du, dy/du, 0 + -1, + -1, + 0.0, // dx/dv, dy/dv, 0 ); return true; } @@ -114,9 +130,15 @@ export class Simple2DFunctionEvaluator1 extends NewtonEvaluatorRRtoRRD { export class Simple2DFunctionEvaluator2 extends NewtonEvaluatorRRtoRRD { public evaluate(u: number, v: number): boolean { this.currentF.setOriginAndVectorsXYZ( - u * u + v * v - 5, 3 * u - v - 5, 0.0, // x(u,v), y(u,v), 0 - 2 * u, 3, 0.0, // dx/du, dy/du, 0 - 2 * v, -1, 0.0, // dx/dv, dy/dv, 0 + u * u + v * v - 5, + 3 * u - v - 5, + 0.0, // x(u,v), y(u,v), 0 + 2 * u, + 3, + 0.0, // dx/du, dy/du, 0 + 2 * v, + -1, + 0.0, // dx/dv, dy/dv, 0 ); return true; } @@ -250,8 +272,12 @@ describe("Newton", () => { }); it("SimpleNewton", () => { const ck = new Checker(); - const func = (x: number): number => { return x * x - 2; }; - const derivative = (x: number): number => { return 2 * x; }; + const func = (x: number): number => { + return x * x - 2; + }; + const derivative = (x: number): number => { + return 2 * x; + }; const initialCondition1 = 1; let solution = SimpleNewton.runNewton1D(initialCondition1, func, derivative)!; const expectedSolution1 = Math.sqrt(2); diff --git a/core/geometry/src/test/numerics/PolarData.test.ts b/core/geometry/src/test/numerics/PolarData.test.ts index 732b50af2525..038695fb6cd4 100644 --- a/core/geometry/src/test/numerics/PolarData.test.ts +++ b/core/geometry/src/test/numerics/PolarData.test.ts @@ -22,11 +22,13 @@ function verifyCompletePolarSinglePoint(ck: Checker, partialData: PolarData, dat for (const d of data) verifyCompletePolarSinglePoint(ck, partialData, d, expectGeometry); } else if (partialData.numberOfConstrainedScalars === 2 && expectGeometry) { - if (ck.testTrue(data.state === ConstraintState.singlePoint) + if ( + ck.testTrue(data.state === ConstraintState.singlePoint) && ck.testTrue(data.x !== undefined, "x defined", prettyPrint(data)) && ck.testTrue(data.y !== undefined, "y defined", prettyPrint(data)) && ck.testTrue(data.r !== undefined, "r defined", prettyPrint(data)) - && ck.testTrue(data.theta !== undefined, "theta defined", prettyPrint(data))) { + && ck.testTrue(data.theta !== undefined, "theta defined", prettyPrint(data)) + ) { ck.testCoordinate(data.x!, data.r! * data.theta!.cos(), "x = r cos(theta)"); ck.testCoordinate(data.y!, data.r! * data.theta!.sin(), "y = r sin (theta)"); } else { @@ -35,7 +37,15 @@ function verifyCompletePolarSinglePoint(ck: Checker, partialData: PolarData, dat } } -function verifyPolarConversion(ck: Checker, allGeometry: GeometryQuery[], partialData: PolarData, x: number, y: number, z: number, expectGeometry: boolean = true) { +function verifyPolarConversion( + ck: Checker, + allGeometry: GeometryQuery[], + partialData: PolarData, + x: number, + y: number, + z: number, + expectGeometry: boolean = true, +) { const result = PolarData.solveFromScalars(partialData); const n0 = ck.getNumErrors(); verifyCompletePolarSinglePoint(ck, partialData, result, expectGeometry); @@ -52,7 +62,13 @@ function verifyPolarConversion(ck: Checker, allGeometry: GeometryQuery[], partia if (partialData.r !== undefined) GeometryCoreTestIO.captureGeometry(allGeometry, Arc3d.createXY(Point3d.create(0, 0, ez), partialData.r), x, y, z); if (partialData.theta !== undefined) - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYZXYZ(0, 0, ez, a * partialData.theta.cos(), a * partialData.theta.sin(), ez), x, y, z); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.createXYZXYZ(0, 0, ez, a * partialData.theta.cos(), a * partialData.theta.sin(), ez), + x, + y, + z, + ); for (const r of result) { if (r.state = ConstraintState.singlePoint) GeometryCoreTestIO.captureGeometry(allGeometry, Arc3d.createXY(Point3d.create(r.x, r.y, 0), markerRadius), x, y, z); @@ -77,33 +93,110 @@ describe("PolarData", () => { // Having confirmed on x,y,r,theta combination, we can proceed with all subsets ... verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, q.y, undefined, undefined), 0, dy += 3, 0); verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, q.r, undefined), 0, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, q.theta), 0, dy += 3, 0); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, q.theta), + 0, + dy += 3, + 0, + ); verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, q.r, undefined), 0, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, q.theta), 0, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, q.r, q.theta), 0, dy += 3, 0); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, q.theta), + 0, + dy += 3, + 0, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, q.r, q.theta), + 0, + dy += 3, + 0, + ); // ill-constrained cases . . . const dx = 5.0; dy = 0.0; - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, undefined), dx, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, undefined), dx, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, q.r, undefined), dx, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, undefined, q.theta), dx, dy += 3, 0); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, undefined), + dx, + dy += 3, + 0, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, undefined), + dx, + dy += 3, + 0, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, q.r, undefined), + dx, + dy += 3, + 0, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, undefined, q.theta), + dx, + dy += 3, + 0, + ); // divide by zero cases ... dy = 0.0; - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, Angle.createDegrees(90.0)), dx, dy += 3, 0); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, Angle.createDegrees(0.0)), dx, dy += 3, 0); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, undefined, Angle.createDegrees(90.0)), + dx, + dy += 3, + 0, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, undefined, Angle.createDegrees(0.0)), + dx, + dy += 3, + 0, + ); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, q.x! * 0.5, undefined), dx, dy += 3, 0, false); - verifyPolarConversion(ck, allGeometry, PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, q.y! * 0.5, undefined), dx, dy += 3, 0, false); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, q.x, undefined, q.x! * 0.5, undefined), + dx, + dy += 3, + 0, + false, + ); + verifyPolarConversion( + ck, + allGeometry, + PolarData.createMixedScalars(ConstraintState.unknown, undefined, q.y, q.y! * 0.5, undefined), + dx, + dy += 3, + 0, + false, + ); const nullCase = PolarData.solveFromScalars(PolarData.createMixedScalars(ConstraintState.unknown, undefined, undefined, undefined, undefined)); ck.testExactNumber(0, nullCase.length, "PartialData with 4 undefined returns empty array"); - } ck.testLE(0.00001, PolarData.defaultRadius, "PolarData static defined"); GeometryCoreTestIO.saveGeometry(allGeometry, "PolarData", "ConstraintSolver"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/numerics/Polynomial.test.ts b/core/geometry/src/test/numerics/Polynomial.test.ts index 117d18f3eda0..96470e0ac759 100644 --- a/core/geometry/src/test/numerics/Polynomial.test.ts +++ b/core/geometry/src/test/numerics/Polynomial.test.ts @@ -23,7 +23,14 @@ import { Transform } from "../../geometry3d/Transform"; import { Point4d } from "../../geometry4d/Point4d"; import { BezierCoffs, Order2Bezier, Order3Bezier, Order4Bezier, Order5Bezier, UnivariateBezier } from "../../numerics/BezierPolynomials"; import { - AnalyticRoots, Degree2PowerPolynomial, Degree3PowerPolynomial, Degree4PowerPolynomial, ImplicitLineXY, SmallSystem, SphereImplicit, TorusImplicit, + AnalyticRoots, + Degree2PowerPolynomial, + Degree3PowerPolynomial, + Degree4PowerPolynomial, + ImplicitLineXY, + SmallSystem, + SphereImplicit, + TorusImplicit, TrigPolynomial, } from "../../numerics/Polynomials"; import { Quadrature } from "../../numerics/Quadrature"; @@ -75,7 +82,7 @@ describe("Bezier.HelloWorld", () => { }); it("degenerateCases", () => { const ck = new Checker(); - const nullTorus = new TorusImplicit(0, 0); // DEGENERATE + const nullTorus = new TorusImplicit(0, 0); // DEGENERATE ck.testExactNumber(1.0, nullTorus.implicitFunctionScale()); const data = nullTorus.xyzToThetaPhiDistance(Point3d.create(0, 0, 0)); ck.testFalse(data.safePhi); @@ -93,7 +100,6 @@ describe("Bezier.HelloWorld", () => { ck.checkpoint("Bezier.rootServices"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("Cubic.Solutions", () => { @@ -125,7 +131,6 @@ describe("Cubic.Solutions", () => { const q = a + b * x; ck.testCoordinate(df + q * q, cubic.evaluate(x), "shifted cubic evaluate"); } - } } ck.checkpoint("Cubic3Roots"); @@ -139,12 +144,13 @@ function testQuadrature(ck: Checker, xA: number, xB: number, xx: Float64Array, w for (let p = 0; p < maxDegree + 3; p++) { { const trueIntegral = (Math.pow(xB, p + 1) - Math.pow(xA, p + 1)) / (p + 1.0); - const approximateIntegral = Quadrature.sum1(xx, ww, n, - (x: number): number => Math.pow(x, p)); + const approximateIntegral = Quadrature.sum1(xx, ww, n, (x: number): number => Math.pow(x, p)); const isSame = Geometry.isSameCoordinate(trueIntegral, approximateIntegral); if (Checker.noisy.gaussQuadrature) { if (p === maxDegree + 1) GeometryCoreTestIO.consoleLog(" --------------- end of expected precise integrals"); - GeometryCoreTestIO.consoleLog(` (p ${p}) (absErr ${approximateIntegral - trueIntegral}) (relErr ${(approximateIntegral - trueIntegral) / trueIntegral}`); + GeometryCoreTestIO.consoleLog( + ` (p ${p}) (absErr ${approximateIntegral - trueIntegral}) (relErr ${(approximateIntegral - trueIntegral) / trueIntegral}`, + ); } ck.testBoolean(p <= maxDegree, isSame, "Quadrature Exactness", p, maxDegree, trueIntegral, approximateIntegral); } @@ -187,8 +193,14 @@ describe("TrigPolynomial.DegenerateLinear", () => { const as = 0.9; const a0 = 0.1; TrigPolynomial.solveUnitCircleImplicitQuadricIntersection( - 0, 0, 0, - ac, as, a0, angles); + 0, + 0, + 0, + ac, + as, + a0, + angles, + ); ck.testExactNumber(2, angles.length); for (const theta of angles) { const q = a0 + ac * Math.cos(theta) + as * Math.sin(theta); @@ -240,10 +252,18 @@ describe("Ellipse.Intersection", () => { const vectorU = Point4d.create(majorRadius, 0, 0, 0.2); const vectorV = Point4d.create(0.1, minorRadius, 0, 0.3); TrigPolynomial.solveUnitCircleHomogeneousEllipseIntersection( - center.x, center.y, center.w, - vectorU.x, vectorU.y, vectorU.w, - vectorV.x, vectorV.y, vectorV.w, - ellipseAngles, circleAngles); + center.x, + center.y, + center.w, + vectorU.x, + vectorU.y, + vectorU.w, + vectorV.x, + vectorV.y, + vectorV.w, + ellipseAngles, + circleAngles, + ); if (ck.testExactNumber(ellipseAngles.length, circleAngles.length)) { // verify that all returned values are intersections. This prevents false positives but not false negatives. for (let i = 0; i < ellipseAngles.length; i++) { @@ -273,14 +293,13 @@ describe("ImplicitSurface", () => { ck.testCoordinate(0, sphere.evaluateImplicitFunction(0, r, 0), "evaluate sphere"); ck.testCoordinate(0, sphere.evaluateImplicitFunction(0, 0, r), "evaluate sphere"); - for (const xyz of [Point3d.create(1, 2, 4), - Point3d.create(0, 0, 0), - Point3d.create(r, 0, 0)]) { + for (const xyz of [Point3d.create(1, 2, 4), Point3d.create(0, 0, 0), Point3d.create(r, 0, 0)]) { const w = 4.2; ck.testCoordinate( sphere.evaluateImplicitFunction(xyz.x, xyz.y, xyz.z) * w * w, sphere.evaluateImplicitFunctionXYZW(w * xyz.x, w * xyz.y, w * xyz.z, w), - "weighted implicit function"); + "weighted implicit function", + ); } for (const thetaPhi of [[0, 0], [0.2, 0.4]]) { @@ -297,8 +316,12 @@ describe("ImplicitSurface", () => { ck.testCoordinate(thetaPhi[0], thetaPhiA.thetaRadians, "implicit sphere theta inverse"); ck.testCoordinate(thetaPhi[1], thetaPhiA.phiRadians, "implicit sphere phi inverse"); } - for (const sphereA of [ - new SphereImplicit(0), new SphereImplicit(1)]) { + for ( + const sphereA of [ + new SphereImplicit(0), + new SphereImplicit(1), + ] + ) { const thetaPhiB = sphereA.xyzToThetaPhiR(Point3d.create(0, 0, 0)); const thetaPhiC = sphereA.xyzToThetaPhiR(Point3d.create(0, 0, 1)); ck.testExactNumber(0.0, thetaPhiB.phiRadians); @@ -322,9 +345,7 @@ describe("ImplicitSurface", () => { ck.testCoordinate(0, torus.evaluateImplicitFunctionXYZ(rA, 0, rB), "evaluate torus"); ck.testCoordinate(0, torus.evaluateImplicitFunctionXYZ(rA, 0, -rB), "evaluate torus"); - for (const xyz of [Point3d.create(1, 2, 4), - Point3d.create(0, 0, 9), - Point3d.create(rA, 0, 0)]) { + for (const xyz of [Point3d.create(1, 2, 4), Point3d.create(0, 0, 9), Point3d.create(rA, 0, 0)]) { const w = 2.0; const fOfX = torus.evaluateImplicitFunctionXYZ(xyz.x, xyz.y, xyz.z); const f = torus.evaluateImplicitFunctionPoint(xyz); @@ -332,7 +353,8 @@ describe("ImplicitSurface", () => { ck.testCoordinate( f * w * w * w * w, torus.evaluateImplicitFunctionXYZW(w * xyz.x, w * xyz.y, w * xyz.z, w), - "weighted implicit function"); + "weighted implicit function", + ); } for (const thetaPhi of [[0, 0], [0.2, 0.4]]) { const theta = thetaPhi[0]; @@ -358,7 +380,6 @@ describe("ImplicitSurface", () => { ck.checkpoint("ImplicitSurface.Torus"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("PowerPolynomials", () => { @@ -367,9 +388,9 @@ describe("PowerPolynomials", () => { let quadratic = new Degree2PowerPolynomial(); ck.testUndefined(quadratic.tryGetVertexFactorization(), "000 quadratic vertex factorization fails"); ck.testNumberArray(undefined, quadratic.realRoots(), "Expect no roots for 000 quadratic", quadratic); - quadratic.addSquaredLinearTerm(1.0, -1.0); // (1-x)^2 -- double root at 1. Coefficients are integers, so expect exact double root solution. + quadratic.addSquaredLinearTerm(1.0, -1.0); // (1-x)^2 -- double root at 1. Coefficients are integers, so expect exact double root solution. ck.testNumberArray([1, 1], quadratic.realRoots(), "Expect double root", quadratic); - quadratic.addConstant(1); // This shifts it from double root to no roots. + quadratic.addConstant(1); // This shifts it from double root to no roots. ck.testNumberArray(undefined, quadratic.realRoots(), "expect no roots", quadratic); ck.testNumberArray([0.5], (new Degree2PowerPolynomial(-1, 2, 0)).realRoots(), "degenerate linear quadratic roots"); quadratic = Degree2PowerPolynomial.fromRootsAndC2(3, 4, 5); @@ -384,11 +405,13 @@ describe("PowerPolynomials", () => { it("Degree4PowerPolynomial", () => { const ck = new Checker(); /* equivalent Degree4PowerPolynomial ... */ - for (const roots of [ - [0, 0, 0, 0], - [0.5, 1, 2, 3], - // [0.1, 0.1, 0.5, 0.5] - ]) { + for ( + const roots of [ + [0, 0, 0, 0], + [0.5, 1, 2, 3], + // [0.1, 0.1, 0.5, 0.5] + ] + ) { const power = Degree4PowerPolynomial.fromRootsAndC4(roots[0], roots[1], roots[2], roots[3], 2); const bezier = Order5Bezier.createFromDegree4PowerPolynomial(power); const powerRoots = new GrowableFloat64Array(4); @@ -414,12 +437,15 @@ describe("PowerPolynomials", () => { it("DegenerateDegree4PowerPolynomial", () => { const ck = new Checker(); /* equivalent Degree4PowerPolynomial ... */ - for (const coffs of [ - [0, 0, 0, 0, 0], - [1, 0, 0, 0, 0], - [1, -2, 0, 0, 0], - [1, 2, -3, 0, 0], - [0.5, 1, 2, 3, 0]]) { + for ( + const coffs of [ + [0, 0, 0, 0, 0], + [1, 0, 0, 0, 0], + [1, -2, 0, 0, 0], + [1, 2, -3, 0, 0], + [0.5, 1, 2, 3, 0], + ] + ) { const power = new Degree4PowerPolynomial(coffs[0], coffs[1], coffs[2], coffs[3], coffs[4]); const bezier = Order5Bezier.createFromDegree4PowerPolynomial(power); const powerRoots = new GrowableFloat64Array(4); @@ -437,7 +463,6 @@ describe("PowerPolynomials", () => { const f = bezier.evaluate(r); ck.testCoordinate(0, f); } - } ck.checkpoint("PowerPolynomials.DegenerateDegree4PowerPolynomial"); expect(ck.getNumErrors()).toBe(0); @@ -446,9 +471,12 @@ describe("PowerPolynomials", () => { it("Degree3PowerPolynomial", () => { const ck = new Checker(); /* equivalent Degree4PowerPolynomial ... */ - for (const roots of [ - [0, 0, 0], - [1, 2, 3]]) { + for ( + const roots of [ + [0, 0, 0], + [1, 2, 3], + ] + ) { const power = Degree3PowerPolynomial.fromRootsAndC3(roots[0], roots[1], roots[2], 2); const bezier = Order4Bezier.createFromDegree3PowerPolynomial(power); const powerRoots = new GrowableFloat64Array(4); @@ -475,15 +503,22 @@ describe("Ellipse.Perpendiculars", () => { it("Ellipse.Perpendiculars", () => { const ck = new Checker(); const r0 = 3.0; - for (const spacePoint of [ - Point3d.create(4, 5, 0), - Point3d.create(2, -6, 0), - Point3d.create(0, -6, 0)]) // special point of bezier-mapped trig functions - + for ( + const spacePoint of [ + Point3d.create(4, 5, 0), + Point3d.create(2, -6, 0), + Point3d.create(0, -6, 0), + ] + ) // special point of bezier-mapped trig functions for (const eccentricity of [1.0, 1.01, 1.01, 2.0, 0.5]) { for (const skew of [0, 0.0]) { // GeometryCoreTestIO.consoleLog("eccentricity ", eccentricity, "skew", skew); - const arc = Arc3d.create(Point3d.create(0, 0, 0), Vector3d.create(r0, 0, 0), Vector3d.create(skew, eccentricity * r0, 0), AngleSweep.create360()); + const arc = Arc3d.create( + Point3d.create(0, 0, 0), + Vector3d.create(r0, 0, 0), + Vector3d.create(skew, eccentricity * r0, 0), + AngleSweep.create360(), + ); let angles = arc.allPerpendicularAngles(spacePoint); for (const theta of angles) { const ray = arc.angleToPointAndDerivative(Angle.createRadians(theta)); @@ -528,10 +563,17 @@ describe("LinearSystems", () => { const x = 0.2; const y = 1.1; const result = Vector2d.create(); - if (ck.testTrue(SmallSystem.linearSystem2d( - ux, vx, - uy, vy, - ux * x + vx * y, uy * x + vy * y, result))) { + if ( + ck.testTrue(SmallSystem.linearSystem2d( + ux, + vx, + uy, + vy, + ux * x + vx * y, + uy * x + vy * y, + result, + )) + ) { ck.testCoordinate(x, result.x, "2d linear x part"); ck.testCoordinate(y, result.y, " 2d linear y part"); } @@ -582,7 +624,16 @@ describe("LinearSystems", () => { const halfCircle = Math.PI; const radiansStep = 0.3; const phiRadiansArray = [-pole, -0.4 * pole, 0.0, 0.2 * pole]; - const thetaRadiansArray = [-halfCircle, -0.6 * halfCircle, -0.2 * halfCircle, 0.0, 0.45 * halfCircle, 0.9 * halfCircle, 1.3 * halfCircle, 2.8 * halfCircle]; + const thetaRadiansArray = [ + -halfCircle, + -0.6 * halfCircle, + -0.2 * halfCircle, + 0.0, + 0.45 * halfCircle, + 0.9 * halfCircle, + 1.3 * halfCircle, + 2.8 * halfCircle, + ]; // const phiRadiansArray = [0.0, pole * 0.5]; // const thetaRadiansArray = [0.0, halfCircle]; let y0 = 0; @@ -607,8 +658,18 @@ describe("LinearSystems", () => { const pointRange = Range3d.createArray(points); const expandedPointRange = pointRange.clone(); expandedPointRange.expandInPlace(0.10 * radius); - ck.testTrue(expandedPatchRange.containsRange(pointRange), "points in patch range", { theta0: theta0Radians, theta1: theta1Radians, phi0: phi0Radians, phi1: phi1Radians }); - ck.testTrue(expandedPointRange.containsRange(patchRange), "patch in expanded point range", { theta0: theta0Radians, theta1: theta1Radians, phi0: phi0Radians, phi1: phi1Radians }); + ck.testTrue(expandedPatchRange.containsRange(pointRange), "points in patch range", { + theta0: theta0Radians, + theta1: theta1Radians, + phi0: phi0Radians, + phi1: phi1Radians, + }); + ck.testTrue(expandedPointRange.containsRange(patchRange), "patch in expanded point range", { + theta0: theta0Radians, + theta1: theta1Radians, + phi0: phi0Radians, + phi1: phi1Radians, + }); y0 += yStep; } } @@ -631,10 +692,14 @@ describe("LinearSystems", () => { for (const center of [Point3d.createZero(), Point3d.create(1, 2, 3)]) { y0 = 0; const sphere = Sphere.createCenterRadius(center, radius); - for (const ray0 of [Ray3d.createXAxis(), - Ray3d.create(center, Vector3d.create(1, 2, 3)), - Ray3d.createXYZUVW(1, 2, 3, 0.5, 0.2, 0.8), - Ray3d.createXYZUVW(2, 0, 8, 1, 0, 0.2)]) { + for ( + const ray0 of [ + Ray3d.createXAxis(), + Ray3d.create(center, Vector3d.create(1, 2, 3)), + Ray3d.createXYZUVW(1, 2, 3, 0.5, 0.2, 0.8), + Ray3d.createXYZUVW(2, 0, 8, 1, 0, 0.2), + ] + ) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, sphere, x0, y0); ray0.tryNormalizeInPlaceWithAreaWeight(1); const frame = Transform.createOriginAndMatrix(ray0.origin, Matrix3d.createRigidHeadsUp(ray0.direction)); @@ -646,7 +711,12 @@ describe("LinearSystems", () => { GeometryCoreTestIO.captureGeometry(allGeometry, Sphere.createCenterRadius(xyz, radius * 0.04), x0, y0); const closestPoint = ray.projectPointToRay(center); const d = center.distance(closestPoint); - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(center, center.interpolate(d < radius ? 3.0 : 1.0, closestPoint)), x0, y0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(center, center.interpolate(d < radius ? 3.0 : 1.0, closestPoint)), + x0, + y0, + ); if (Geometry.isSameCoordinate(d, radius)) { // ignore the potential tolerance problems . . . } else if (d < radius) { @@ -710,17 +780,27 @@ function sphereSnakeGridPoints(center: Point3d, radius: number, thetaArray: numb } function captureUnitCircleEllipseIntersections( - allGeometry: any[], ck: any, - cx: number, cy: number, - ux: number, uy: number, - vx: number, vy: number, - dx: number, expectedIntersections: number, + allGeometry: any[], + ck: any, + cx: number, + cy: number, + ux: number, + uy: number, + vx: number, + vy: number, + dx: number, + expectedIntersections: number, ) { const unitCircle = Arc3d.create( - Point3d.create(0, 0), Vector3d.create(1, 0), Vector3d.create(0, 1), AngleSweep.createStartEndDegrees(), + Point3d.create(0, 0), + Vector3d.create(1, 0), + Vector3d.create(0, 1), + AngleSweep.createStartEndDegrees(), ); const arc = Arc3d.create( - Point3d.create(cx, cy), Vector3d.create(ux, uy), Vector3d.create(vx, vy), + Point3d.create(cx, cy), + Vector3d.create(ux, uy), + Vector3d.create(vx, vy), AngleSweep.createStartEndDegrees(), ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, unitCircle, dx); @@ -743,8 +823,8 @@ it("unitCircleEllipseIntersection", () => { let dx = 0; // intersection at lower half of the ellipse let cx = 0, cy = 1.5; // ellipse center - let ux = 2, uy = 0; // ellipse vector0 - let vx = 0, vy = 1; // ellipse vector90 + let ux = 2, uy = 0; // ellipse vector0 + let vx = 0, vy = 1; // ellipse vector90 let expectedIntersections = 2; captureUnitCircleEllipseIntersections(allGeometry, ck, cx, cy, ux, uy, vx, vy, dx, expectedIntersections); // intersection at t = 0 diff --git a/core/geometry/src/test/numerics/TriDiagonalSystem.test.ts b/core/geometry/src/test/numerics/TriDiagonalSystem.test.ts index 49b64d3146c6..1ba66243177e 100644 --- a/core/geometry/src/test/numerics/TriDiagonalSystem.test.ts +++ b/core/geometry/src/test/numerics/TriDiagonalSystem.test.ts @@ -11,7 +11,9 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; class TestFixture { public ck: Checker; - public constructor() { this.ck = new Checker(); } + public constructor() { + this.ck = new Checker(); + } // Tester Methods ------------------------------------------------------------------- public checkX(systemA: TriDiagonalSystem, systemB: TriDiagonalSystem) { @@ -42,7 +44,6 @@ class TestFixture { if (Checker.noisy.tridiagonalSolver) { GeometryCoreTestIO.consoleLog("(1) A X AX"); GeometryCoreTestIO.consoleLog(A); - } const B: TriDiagonalSystem = A.copy(); this.ck.testTrue(A.factorAndBackSubstitute(), "FactorAndBackSubstitute"); @@ -129,7 +130,7 @@ class TestFixture { A.setRow(2, 0.3, -3.1, 0.98); A.setRow(3, 0.43, -3.04, 0); for (let i = 0; i < 4; i++) { - A.setX(i, (1 + i * i)); + A.setX(i, 1 + i * i); } A.multiplyAX(); const B: TriDiagonalSystem = A.copy(); @@ -160,7 +161,7 @@ class TestFixture { for (let i = 1; i < (n - 1); i++) { const u = i / n; const v = u * 0.5; - A.addToRow(i, (1 - v * v), (3.0 + u), (1 + v * v)); + A.addToRow(i, 1 - v * v, 3.0 + u, 1 + v * v); } A.setRow(n - 1, 1.235, 3.99, 0); for (let i = 0; i < n; i++) { @@ -245,5 +246,4 @@ describe("TriDiagonalSystem", () => { tf.testRareConditions(); expect(tf.ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/numerics/UnionFind.test.ts b/core/geometry/src/test/numerics/UnionFind.test.ts index 2c324c102b88..6d33c90688c7 100644 --- a/core/geometry/src/test/numerics/UnionFind.test.ts +++ b/core/geometry/src/test/numerics/UnionFind.test.ts @@ -70,7 +70,7 @@ describe("UnionFind", () => { ck.testExactNumber(numRoot0, numRoot1, "Leaf queries do not change root count"); ck.testLE(numLongPath1, numLongPath0, "Leaf queries can reduce number of long paths"); - ck.testExactNumber(0, numLongPath1, "Leaf queries eliminate long paths"); // is this really certain? + ck.testExactNumber(0, numLongPath1, "Leaf queries eliminate long paths"); // is this really certain? } expect(ck.getNumErrors()).toBe(0); }); diff --git a/core/geometry/src/test/numerics/UsageSums.test.ts b/core/geometry/src/test/numerics/UsageSums.test.ts index 28d78c7395b9..8f8f6f0afaed 100644 --- a/core/geometry/src/test/numerics/UsageSums.test.ts +++ b/core/geometry/src/test/numerics/UsageSums.test.ts @@ -31,7 +31,7 @@ describe("UsageSums", () => { ck.testTrue(usageSumsFromA.isAlmostEqual(cloneA0)); const cloneA1 = usageSumsFromA.clone(); const cloneA2 = usageSumsFromA.clone(); - cloneA0.accumulate(a); // changes count, not sums, not minMax + cloneA0.accumulate(a); // changes count, not sums, not minMax ck.testFalse(usageSumsFromA.isAlmostEqual(cloneA0)); cloneA1.accumulate(a + 1); ck.testFalse(cloneA0.isAlmostEqual(cloneA1), "matched count, minMax, different sums"); diff --git a/core/geometry/src/test/polyface/DrapeLinestring.test.ts b/core/geometry/src/test/polyface/DrapeLinestring.test.ts index a8c9653042c2..416f86c766d6 100644 --- a/core/geometry/src/test/polyface/DrapeLinestring.test.ts +++ b/core/geometry/src/test/polyface/DrapeLinestring.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect, it } from "vitest"; import * as fs from "fs"; +import { expect, it } from "vitest"; import { BSplineCurve3d } from "../../bspline/BSplineCurve"; import { CurvePrimitive } from "../../curve/CurvePrimitive"; import { GeometryQuery } from "../../curve/GeometryQuery"; @@ -49,16 +49,24 @@ it("DrapeLinestringAsPanels", async () => { const wandering = BSplineCurve3d.createUniformKnots(packedWanderingPoints, 3)!; const strokes = LineString3d.create(); wandering.emitStrokes(strokes); - for (const linestring of [ - LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), - LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), - LineString3d.create(wanderingPoints), - strokes]) { - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.create(1.0324, 0, 0.1), Vector3d.create(0, 1.123, 0.5), 8, 8); - mesh.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); - }); + for ( + const linestring of [ + LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), + LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), + LineString3d.create(wanderingPoints), + strokes, + ] + ) { + const mesh = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.create(1.0324, 0, 0.1), + Vector3d.create(0, 1.123, 0.5), + 8, + 8, + ); + mesh.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); + }); const _panels = PolyfaceQuery.sweepLineStringToFacetsXYReturnSweptFacets(linestring.packedPoints, mesh); // GeometryCoreTestIO.captureGeometry(allGeometry, [mesh, linestring, panels], 0, dy, 0); @@ -72,14 +80,7 @@ it("DrapeLinestringAsLines", async () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const wanderingPoints = [[-1, 1, 1], - [1.5, 1, 1], - [2, 3, -1], - [3.5, 3, -2], - [3.5, 6, 1], - [4, 8, -2], - [6, 3, 5], - [8, 3, -2]]; + const wanderingPoints = [[-1, 1, 1], [1.5, 1, 1], [2, 3, -1], [3.5, 3, -2], [3.5, 6, 1], [4, 8, -2], [6, 3, 5], [8, 3, -2]]; const packedWanderingPoints = new GrowableXYZArray(); packedWanderingPoints.pushFrom(wanderingPoints); @@ -89,7 +90,8 @@ it("DrapeLinestringAsLines", async () => { [3, 6, 5], [1, 3, 5], [3, 1, 5], - [0, -1, 5]]; + [0, -1, 5], + ]; const wandering = BSplineCurve3d.createUniformKnots(packedWanderingPoints, 3)!; const strokes = LineString3d.create(); @@ -97,27 +99,42 @@ it("DrapeLinestringAsLines", async () => { let dx = 0.0; const dy = 20.0; let numTest = 0; - for (const linestring of [ - LineString3d.create([[4.2, 3, 0], [4.9, 3, 0]]), - LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), - LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), - LineString3d.create(loopWithHandle), - LineString3d.create(wanderingPoints), - strokes]) { + for ( + const linestring of [ + LineString3d.create([[4.2, 3, 0], [4.9, 3, 0]]), + LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), + LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), + LineString3d.create(loopWithHandle), + LineString3d.create(wanderingPoints), + strokes, + ] + ) { for (const meshMultiplier of [1, 4]) { numTest++; - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.create(1, 0, 0.1), Vector3d.create(0, 2, 0.5), - 8 * meshMultiplier, 4 * meshMultiplier); + const mesh = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.create(1, 0, 0.1), + Vector3d.create(0, 2, 0.5), + 8 * meshMultiplier, + 4 * meshMultiplier, + ); if (numTest > 3) - mesh.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); - }); - const lines = await Promise.resolve(PolyfaceQuery.sweepLineStringToFacets(linestring.packedPoints, mesh, - SweepLineStringToFacetsOptions.create(undefined, undefined, false, true, true, true))); + mesh.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); + }); + const lines = await Promise.resolve( + PolyfaceQuery.sweepLineStringToFacets( + linestring.packedPoints, + mesh, + SweepLineStringToFacetsOptions.create(undefined, undefined, false, true, true, true), + ), + ); // GeometryCoreTestIO.consoleLog({ awaitBlocks: PolyfaceQuery.awaitBlockCount }); - const chains = PolyfaceQuery.sweepLineStringToFacets(linestring.packedPoints, mesh, - SweepLineStringToFacetsOptions.create(undefined, undefined, true, true, true, true)); + const chains = PolyfaceQuery.sweepLineStringToFacets( + linestring.packedPoints, + mesh, + SweepLineStringToFacetsOptions.create(undefined, undefined, true, true, true, true), + ); let lineSum = 0; let chainSum = 0; for (const g of lines) lineSum += g.curveLength(); @@ -137,14 +154,7 @@ it("DrapeLinestringLargeMesh", async () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const w0 = 4.0; - const wanderingPoints = [[-0.01, 0, 1], - [1.5, 1, 1], - [2, 3, -1], - [3.5, 3, -2], - [3.5, 4, 1], - [4, 5, -2], - [6, 3, 5], - [8, 3, -2]]; + const wanderingPoints = [[-0.01, 0, 1], [1.5, 1, 1], [2, 3, -1], [3.5, 3, -2], [3.5, 4, 1], [4, 5, -2], [6, 3, 5], [8, 3, -2]]; for (const p of wanderingPoints) p[2] += w0; const packedWanderingPoints = new GrowableXYZArray(); @@ -156,7 +166,8 @@ it("DrapeLinestringLargeMesh", async () => { [3, 6, 5], [1, 3, 5], [3, 1, 5], - [0, -1, 5]]; + [0, -1, 5], + ]; const wandering = BSplineCurve3d.createUniformKnots(packedWanderingPoints, 3)!; const strokes = LineString3d.create(); @@ -173,14 +184,17 @@ it("DrapeLinestringLargeMesh", async () => { const ay = 10.0; const az = 1.0; const zShift = 0.05; - for (const linestring of [ - // LineString3d.create([[4.2, 3, 0], [4.9, 3, 0]]), - // LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), - // LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), - // LineString3d.create(loopWithHandle), - LineString3d.create(wanderingPoints), - strokes]) { - for (const densityMultiplier of /* [1, 2, 4, 8] */[1, 3, 6]) { + for ( + const linestring of [ + // LineString3d.create([[4.2, 3, 0], [4.9, 3, 0]]), + // LineString3d.create([[4.2, 3, -2], [6, 3, 1]]), + // LineString3d.create([[4.2, 3, -2], [6, 3, 3]]), + // LineString3d.create(loopWithHandle), + LineString3d.create(wanderingPoints), + strokes, + ] + ) { + for (const densityMultiplier of /* [1, 2, 4, 8] */ [1, 3, 6]) { const numX = numX0 * densityMultiplier; const numY = numY0 * densityMultiplier; numTest++; @@ -189,13 +203,19 @@ it("DrapeLinestringLargeMesh", async () => { const _dZdX = az / numX; const _dZdY = az / numY; const mesh = Sample.createTriangularUnitGridPolyface( - Point3d.create(0, 0, 0), Vector3d.create(dx, 0, _dZdX), Vector3d.create(0, dy, _dZdY), numX, numY); + Point3d.create(0, 0, 0), + Vector3d.create(dx, 0, _dZdX), + Vector3d.create(0, dy, _dZdY), + numX, + numY, + ); if (numTest > 0) - mesh.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); - }); - const lines = PolyfaceQuery.sweepLineStringToFacets(linestring.packedPoints, mesh, + mesh.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); + }); + const lines = PolyfaceQuery.sweepLineStringToFacets( + linestring.packedPoints, + mesh, SweepLineStringToFacetsOptions.create(undefined, undefined, false, true, true, true), ); const name = `sweptLineString ${numX * numY} ${linestring.packedPoints.length}`; @@ -212,9 +232,9 @@ it("DrapeLinestringLargeMesh", async () => { if (densityMultiplier < 7) { y0 = 0.0; GeometryCoreTestIO.captureCloneGeometry(allGeometry, [mesh, linestring], x0, y0, 0); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, (await _chains), x0, y0, zShift); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, await _chains, x0, y0, zShift); GeometryCoreTestIO.captureCloneGeometry(allGeometry, lines, x0, y0 += yShift, 0); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, (await _chains), x0, y0 += yShift, 0); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, await _chains, x0, y0 += yShift, 0); } x0 += xShift; } @@ -233,9 +253,11 @@ it("sweepLinestringToFacetsXYZingers", () => { const z0 = 0; const doScale = false; if (Array.isArray(data) && data.length === 3) { - if (ck.testType(data[0], LineString3d, "Expect linestring") + if ( + ck.testType(data[0], LineString3d, "Expect linestring") && ck.testType(data[1], IndexedPolyface, "Expect mesh") - && ck.testType(data[2], IndexedPolyface, "expect mesh")) { + && ck.testType(data[2], IndexedPolyface, "expect mesh") + ) { const linestringA = data[0]; const meshB = data[1]; const meshC = data[2]; @@ -296,7 +318,8 @@ it("sweepLinestringToFacetsXYZVerticalMesh", () => { [-2, 1, zz], [0, 1, zz], [1, 2, zz], - [3, 0, 2]]); + [3, 0, 2], + ]); for (const direction of [Vector3d.create(0, 0, 1), Vector3d.create(1, -3, 1)]) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, x0, y0, z0); @@ -304,8 +327,7 @@ it("sweepLinestringToFacetsXYZVerticalMesh", () => { const options = SweepLineStringToFacetsOptions.create(direction); const linesA = PolyfaceQuery.sweepLineStringToFacets(lineToDrape.packedPoints, mesh, options); for (const p of lineToDrape.points) { - GeometryCoreTestIO.captureCloneGeometry(allGeometry, - [p, p.plusScaled(direction, -2.5)], x0, y0, z0); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, [p, p.plusScaled(direction, -2.5)], x0, y0, z0); } const sumLengths = (curves: CurvePrimitive[]): number => { let s = 0.0; @@ -316,16 +338,17 @@ it("sweepLinestringToFacetsXYZVerticalMesh", () => { const sumA = sumLengths(linesA); GeometryCoreTestIO.captureCloneGeometry(allGeometry, linesA, x0, y0, z0); let sumB = 0.0; - for (const optionsB of [ - SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), true, true, false, false), - SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), true, false, true, false), - SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), false, false, false, true), - ]) { + for ( + const optionsB of [ + SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), true, true, false, false), + SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), true, false, true, false), + SweepLineStringToFacetsOptions.create(direction, Angle.createDegrees(2), false, false, false, true), + ] + ) { x0 += 5.0; const linesB = PolyfaceQuery.sweepLineStringToFacets(lineToDrape.packedPoints, mesh, optionsB); sumB += sumLengths(linesB); GeometryCoreTestIO.captureCloneGeometry(allGeometry, linesB, x0, y0, z0); - } ck.testCoordinate(sumA, sumB, "Same length returned by various combinations."); x0 += 50.0; @@ -338,7 +361,9 @@ it("sweepLinestringToFacetsXYZVerticalMesh", () => { it("drapeLineStringAsLines2", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/data/polyface/sweepLinestringToFacetsXY/drape-linestring-to-meshes.imjs", "utf8"))); + const inputs = IModelJson.Reader.parse( + JSON.parse(fs.readFileSync("./src/test/data/polyface/sweepLinestringToFacetsXY/drape-linestring-to-meshes.imjs", "utf8")), + ); if (Array.isArray(inputs) && 2 === inputs.length && inputs[0] instanceof LineString3d && inputs[1] instanceof IndexedPolyface) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, inputs); const lineString = inputs[0]; diff --git a/core/geometry/src/test/polyface/FacetFaceData.test.ts b/core/geometry/src/test/polyface/FacetFaceData.test.ts index 008a3d8efde5..f47bbb71127e 100644 --- a/core/geometry/src/test/polyface/FacetFaceData.test.ts +++ b/core/geometry/src/test/polyface/FacetFaceData.test.ts @@ -12,7 +12,6 @@ import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; describe("FacetFaceData", () => { - it("HelloWorld", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -20,7 +19,13 @@ describe("FacetFaceData", () => { const polyfaceA = Sample.createTriangularUnitGridPolyface( Point3d.create(0, 0, 0), Vector3d.unitX(2.5), - Vector3d.unitY(4), 2, 3, true, true, true); + Vector3d.unitY(4), + 2, + 3, + true, + true, + true, + ); ffd.setParamDistanceRangeFromNewFaceData(polyfaceA, 0, polyfaceA.facetCount); const paramRange = ffd.paramRange; @@ -56,7 +61,13 @@ describe("FacetFaceData", () => { const polyfaceB = Sample.createTriangularUnitGridPolyface( Point3d.create(0, 0, 0), Vector3d.unitX(), - Vector3d.unitY(), 2, 3, false, false, false); + Vector3d.unitY(), + 2, + 3, + false, + false, + false, + ); // confirm failure if there are no params in the polyface ck.testFalse(ffdB0.setParamDistanceRangeFromNewFaceData(polyfaceB, 2, 3)); diff --git a/core/geometry/src/test/polyface/GreedyTriangulationBetweenLineStrings.test.ts b/core/geometry/src/test/polyface/GreedyTriangulationBetweenLineStrings.test.ts index d6a78e03a91e..597ee93f474d 100644 --- a/core/geometry/src/test/polyface/GreedyTriangulationBetweenLineStrings.test.ts +++ b/core/geometry/src/test/polyface/GreedyTriangulationBetweenLineStrings.test.ts @@ -29,7 +29,7 @@ describe("GreedyTriangulationBetweenLineStrings", () => { let x0 = 0.0; const dx = 8; const dy = 8; - const dz = 0.01; // output stringers a little above and below + const dz = 0.01; // output stringers a little above and below for (const dataB of [dataB0, dataB1]) { for (let nA = 2; nA <= dataA.length; nA++) { const pointA = GrowableXYZArray.create(dataA.slice(0, nA)); @@ -65,7 +65,7 @@ describe("GreedyTriangulationBetweenLineStrings", () => { const dataA = [[0, 0, z0], [1, 0, z0], [2, 0, z0], [2, 1, z0], [3, 1, z0], [3, 2, z0]]; const dataB = [[0, 0, z1], [1, 0, z1], [1.5, 0.05, z1], [2, 0, z1], [2, 1, z1], [3, 1, z1], [3, 2, z1]]; let y0 = 0; - const dz = 0.01; // output stringers a little above and below + const dz = 0.01; // output stringers a little above and below const numDup = 2; const step = 4.0; for (let nA = 0; nA < dataA.length; nA++) { @@ -102,7 +102,7 @@ describe("GreedyTriangulationBetweenLineStrings", () => { const lineStringB = LineString3d.create(dataB); const dx = 8; const dy = 8; - const dz = 0.01; // output stringers a little above and below + const dz = 0.01; // output stringers a little above and below const options = StrokeOptions.createForCurves(); for (const edgeLengthA of [1, 0.55, 0.35, 0.28, 0.22]) { const lineStringA1 = LineString3d.create(); @@ -144,7 +144,7 @@ describe("GreedyTriangulationBetweenLineStrings", () => { const lineStringB = LineString3d.create(dataB); const dx = 8; const dy = 8; - const dz = 0.01; // output stringers a little above and below + const dz = 0.01; // output stringers a little above and below const options = StrokeOptions.createForCurves(); for (const edgeLengthA of [1, 0.55, 0.35, 0.28, 0.22]) { const lineStringA1 = LineString3d.create(); @@ -169,7 +169,6 @@ describe("GreedyTriangulationBetweenLineStrings", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "GreedyTriangulationBetweenLineStrings", "quadStar"); expect(ck.getNumErrors()).toBe(0); }); - }); /** diff --git a/core/geometry/src/test/polyface/GridSample.test.ts b/core/geometry/src/test/polyface/GridSample.test.ts index b3f160f159ad..5f126f4a4f24 100644 --- a/core/geometry/src/test/polyface/GridSample.test.ts +++ b/core/geometry/src/test/polyface/GridSample.test.ts @@ -240,7 +240,6 @@ function buildSampledGrid(points: Point3d[], numLongDirectionEdge: number, templ return grid.createPolyface(); } describe("GridSampling", () => { - it("NearestGridPointMax", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -256,7 +255,8 @@ describe("GridSampling", () => { Point3d.create(4, 7, 0.79), Point3d.create(3.5, 7, 0.79), Point3d.create(4, 2, 0.80), - Point3d.create(2, 3, 0.4)]; + Point3d.create(2, 3, 0.4), + ]; const zScale = 2.0; for (const p of points) p.z *= zScale; @@ -309,5 +309,4 @@ describe("GridSampling", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "GridSampling", "Hello5Points"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/polyface/OffsetMeshContext.test.ts b/core/geometry/src/test/polyface/OffsetMeshContext.test.ts index 5f3a6917249c..fe582d588fd0 100644 --- a/core/geometry/src/test/polyface/OffsetMeshContext.test.ts +++ b/core/geometry/src/test/polyface/OffsetMeshContext.test.ts @@ -3,59 +3,54 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; import { describe, expect, it } from "vitest"; -import { LineString3d } from "../../curve/LineString3d"; import { Arc3d } from "../../curve/Arc3d"; -import { StrokeOptions } from "../../curve/StrokeOptions"; import { GeometryQuery } from "../../curve/GeometryQuery"; -import { Checker } from "../Checker"; -import { IndexedPolyface } from "../../polyface/Polyface"; -import { RFunctions } from "./DrapeLinestring.test"; -import { Sample } from "../../serialization/GeometrySamples"; +import { LineString3d } from "../../curve/LineString3d"; +import { StrokeOptions } from "../../curve/StrokeOptions"; import { Geometry } from "../../Geometry"; import { Angle } from "../../geometry3d/Angle"; -import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "../../topology/Graph"; -import { GraphChecker } from "../topology/Graph.test"; -import { OffsetMeshOptions, PolyfaceQuery } from "../../polyface/PolyfaceQuery"; import { AngleSweep } from "../../geometry3d/AngleSweep"; +import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { OffsetMeshContext } from "../../polyface/multiclip/OffsetMeshContext"; +import { IndexedPolyface } from "../../polyface/Polyface"; +import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; +import { OffsetMeshOptions, PolyfaceQuery } from "../../polyface/PolyfaceQuery"; +import { Sample } from "../../serialization/GeometrySamples"; import { LinearSweep } from "../../solid/LinearSweep"; import { SolidPrimitive } from "../../solid/SolidPrimitive"; +import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "../../topology/Graph"; +import { Checker } from "../Checker"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; +import { GraphChecker } from "../topology/Graph.test"; +import { RFunctions } from "./DrapeLinestring.test"; const globalSeparateFaceEdgeAndVertexOutputs = false; function cleanupZero(a: number, tol: number = 1.0e-12): number { return Math.abs(a) > tol ? a : 0.0; } -function _offsetDebugFunction(message: string, graph: HalfEdgeGraph, - breakMaskA: HalfEdgeMask, - breakMaskB: HalfEdgeMask) { +function _offsetDebugFunction(message: string, graph: HalfEdgeGraph, breakMaskA: HalfEdgeMask, breakMaskB: HalfEdgeMask) { if (Checker.noisy.offsetMesh) { - GeometryCoreTestIO.consoleLog(("")); + GeometryCoreTestIO.consoleLog(""); GeometryCoreTestIO.consoleLog(` DebugGraph ${message}`); - GraphChecker.dumpGraph(graph, - (node: HalfEdge) => { - const xx = node.isMaskSet(HalfEdgeMask.EXTERIOR) ? "X" : " "; - const breakA = node.isMaskSet(breakMaskA) ? "A" : " "; - const breakB = node.isMaskSet(breakMaskB) ? "B" : " "; - const s = `${node.id.toString()}+${xx}${breakA}${breakB}[${cleanupZero(node.x)},${cleanupZero(node.y)}]`; - return s; - }, - (node: HalfEdge) => { - const xx = node.isMaskSet(HalfEdgeMask.EXTERIOR) ? "X" : " "; - const breakA = node.isMaskSet(breakMaskA) ? "A" : " "; - const breakB = node.isMaskSet(breakMaskB) ? "B" : " "; - const s = `[${node.id.toString()}+${xx}${breakA}${breakB}]`; - return s; - }); + GraphChecker.dumpGraph(graph, (node: HalfEdge) => { + const xx = node.isMaskSet(HalfEdgeMask.EXTERIOR) ? "X" : " "; + const breakA = node.isMaskSet(breakMaskA) ? "A" : " "; + const breakB = node.isMaskSet(breakMaskB) ? "B" : " "; + const s = `${node.id.toString()}+${xx}${breakA}${breakB}[${cleanupZero(node.x)},${cleanupZero(node.y)}]`; + return s; + }, (node: HalfEdge) => { + const xx = node.isMaskSet(HalfEdgeMask.EXTERIOR) ? "X" : " "; + const breakA = node.isMaskSet(breakMaskA) ? "A" : " "; + const breakB = node.isMaskSet(breakMaskB) ? "B" : " "; + const s = `[${node.id.toString()}+${xx}${breakA}${breakB}]`; + return s; + }); } } // import { GraphChecker } from "../topology/Graph.test"; describe("OffsetMeshContext", () => { - it("OffsetPyramids", () => { const ck = new Checker(); @@ -68,7 +63,9 @@ describe("OffsetMeshContext", () => { // OffsetMeshContext.graphDebugFunction = _offsetDebugFunction; // Checker.noisy.offsetMesh = true; if (Checker.noisy.offsetMesh) - OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; + OffsetMeshContext.stringDebugFunction = (message: string) => { + GeometryCoreTestIO.consoleLog(message); + }; for (const xScale of [2.0]) { for (const height of [2.0, 0.05, 2.0, 1.0, 3.0, 10.0]) { @@ -77,7 +74,7 @@ describe("OffsetMeshContext", () => { const strokes = LineString3d.create(); for (let i = 0; i < numEdge; i++) { const theta = Angle.createDegrees(i * 360 / numEdge); - const zz = i === 0.0 ? height : 0.0; // make the base non-planar! + const zz = i === 0.0 ? height : 0.0; // make the base non-planar! strokes.addPointXYZ(xScale * radius * theta.cos(), radius * theta.sin(), zz); } strokes.addClosurePoint(); @@ -160,7 +157,7 @@ describe("OffsetMeshContext", () => { const zC = 0.0; // OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; - for (const zCone of [2.0, 0.5, -0.5, 2.0, -2.0, 4.0, -4.0, 10.0]) { // height of cone point. + for (const zCone of [2.0, 0.5, -0.5, 2.0, -2.0, 4.0, -4.0, 10.0]) { // height of cone point. for (const numApronEdges of [8, 2, 4]) { const builder = PolyfaceBuilder.create(options); const arc = Arc3d.createXYZXYZXYZ(0, 0, 0, 0, yB, 0, xC, 0, zC, AngleSweep.createStartEndDegrees(0, 180)); @@ -207,14 +204,20 @@ describe("OffsetMeshContext", () => { const _dZdX = az / numX; const _dZdY = az / numY; const mesh = Sample.createTriangularUnitGridPolyface( - Point3d.create(0, 0, 0), Vector3d.create(dx, 0, _dZdX), Vector3d.create(0, dy, _dZdY), numX, numY); + Point3d.create(0, 0, 0), + Vector3d.create(dx, 0, _dZdX), + Vector3d.create(0, dy, _dZdY), + numX, + numY, + ); if (numTest > 0) - mesh.data.point.mapComponent(2, - (x: number, y: number, _z: number) => { - return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); - }); + mesh.data.point.mapComponent(2, (x: number, y: number, _z: number) => { + return 1.0 * RFunctions.cosineOfMappedAngle(x, 0.0, 5.0) * RFunctions.cosineOfMappedAngle(y, 0.0, 8.0); + }); if (densityMultiplier < 1) - OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; + OffsetMeshContext.stringDebugFunction = (message: string) => { + GeometryCoreTestIO.consoleLog(message); + }; x0 = testOffsets(ck, allGeometry, mesh, [0.10], [1.0], x0, globalSeparateFaceEdgeAndVertexOutputs); OffsetMeshContext.stringDebugFunction = undefined; } @@ -230,7 +233,9 @@ describe("OffsetMeshContext", () => { facetOptions.shouldTriangulate = true; // Checker.noisy.offsetMesh = true; if (Checker.noisy.offsetMesh) - OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; + OffsetMeshContext.stringDebugFunction = (message: string) => { + GeometryCoreTestIO.consoleLog(message); + }; for (const s of closedSweeps) { const builder = PolyfaceBuilder.create(facetOptions); @@ -257,7 +262,9 @@ describe("OffsetMeshContext", () => { facetOptions.shouldTriangulate = true; // Checker.noisy.offsetMesh = true; if (Checker.noisy.offsetMesh) - OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; + OffsetMeshContext.stringDebugFunction = (message: string) => { + GeometryCoreTestIO.consoleLog(message); + }; const optionsA = OffsetMeshOptions.create(); optionsA.chamferAngleBetweenNormals = Angle.createDegrees(150); const optionsB = OffsetMeshOptions.create(); @@ -296,7 +303,9 @@ describe("OffsetMeshContext", () => { facetOptions.shouldTriangulate = true; // Checker.noisy.offsetMesh = true; if (Checker.noisy.offsetMesh) - OffsetMeshContext.stringDebugFunction = (message: string) => { GeometryCoreTestIO.consoleLog(message); }; + OffsetMeshContext.stringDebugFunction = (message: string) => { + GeometryCoreTestIO.consoleLog(message); + }; const optionsA = OffsetMeshOptions.create(); optionsA.chamferAngleBetweenNormals = Angle.createDegrees(150); const optionsB = OffsetMeshOptions.create(); @@ -313,10 +322,12 @@ describe("OffsetMeshContext", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "OffsetMeshContext", "ChamferExample"); expect(ck.getNumErrors()).toBe(0); }); - }); -function testOffsets(_ck: Checker, allGeometry: GeometryQuery[], polyface: IndexedPolyface, +function testOffsets( + _ck: Checker, + allGeometry: GeometryQuery[], + polyface: IndexedPolyface, offsets: number[], signs: number[], xStart: number, @@ -345,15 +356,16 @@ function testOffsets(_ck: Checker, allGeometry: GeometryQuery[], polyface: Index GeometryCoreTestIO.captureCloneGeometry(allGeometry, offsetMeshB, x0, y0); // y0 += yStepC; if (separateFaceEdgeAndVertexOutputs) { - for (const outputSelect of - [ + for ( + const outputSelect of [ { outputOffsetsFromFacesBeforeChamfers: true }, { outputOffsetsFromFaces: true }, { outputOffsetsFromEdges: true }, { outputOffsetsFromVertices: true }, { outputOffsetsFromVerticesBeforeChamfers: true }, undefined, - ]) { + ] + ) { y0 += yStepC; offsetOptions.outputSelector = outputSelect; const offsetMeshA = PolyfaceQuery.cloneOffset(polyface, offsetSign * offset, offsetOptions); @@ -370,7 +382,10 @@ function testOffsets(_ck: Checker, allGeometry: GeometryQuery[], polyface: Index /** * @param originalWithOffsets if true, output the original in situ with each offset. if false, only output the original at start. */ -function displayOffsetsWithOptionExamples(_ck: Checker, allGeometry: GeometryQuery[], polyface: IndexedPolyface, +function displayOffsetsWithOptionExamples( + _ck: Checker, + allGeometry: GeometryQuery[], + polyface: IndexedPolyface, offset: number, optionsArray: OffsetMeshOptions[], xStart: number, diff --git a/core/geometry/src/test/polyface/ParityRegionSweep.test.ts b/core/geometry/src/test/polyface/ParityRegionSweep.test.ts index d33ca2061025..d7a2e47b4c55 100644 --- a/core/geometry/src/test/polyface/ParityRegionSweep.test.ts +++ b/core/geometry/src/test/polyface/ParityRegionSweep.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { CurveCollection } from "../../curve/CurveCollection"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { ParityRegion } from "../../curve/ParityRegion"; @@ -31,11 +31,17 @@ describe("ParityRegionSweep", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const regionC = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/curve/parityRegionSweep/ParityRegionC.imjs", "utf8"))); + "./src/test/data/curve/parityRegionSweep/ParityRegionC.imjs", + "utf8", + ))); const regionA = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/curve/parityRegionSweep/ParityRegionA.imjs", "utf8"))); + "./src/test/data/curve/parityRegionSweep/ParityRegionA.imjs", + "utf8", + ))); let regionB = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/curve/parityRegionSweep/ParityRegionB.imjs", "utf8"))); + "./src/test/data/curve/parityRegionSweep/ParityRegionB.imjs", + "utf8", + ))); if (Array.isArray(regionB)) { const regionB1 = ParityRegion.create(); for (const loop of regionB) { @@ -75,7 +81,12 @@ describe("ParityRegionSweep", () => { const slab = LinearSweep.create(region, sweepDirection, true); let y2 = y1 + diagonal; GeometryCoreTestIO.captureCloneGeometry(allGeometry, slab, x1, y2); - GeometryCoreTestIO.captureCloneGeometry(allGeometry, [rawMomentData.origin, rawMomentData.origin.plusScaled(sweepDirection, 4.0)], x1, y2); + GeometryCoreTestIO.captureCloneGeometry( + allGeometry, + [rawMomentData.origin, rawMomentData.origin.plusScaled(sweepDirection, 4.0)], + x1, + y2, + ); const builder = PolyfaceBuilder.create(); builder.addGeometryQuery(slab!); const polyfaceA = builder.claimPolyface(); @@ -108,16 +119,17 @@ describe("ParityRegionSweep", () => { } for (const dy of [0.1, 0.3]) { let y0 = 0.0; - for (const transform of [ - Transform.createIdentity(), - Transform.createFixedPointAndMatrix(Point3d.create(3.24234898, 1.9798789), - Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(25.69898234))), - ]) { + for ( + const transform of [ + Transform.createIdentity(), + Transform.createFixedPointAndMatrix( + Point3d.create(3.24234898, 1.9798789), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(25.69898234)), + ), + ] + ) { let x0 = x0A; - for (const yShifts of [[dy, dy, dy], - [0, 0, 0], [dy, 0, 0], [0, dy, 0], [dy, dy, 0], - [0, 0, dy], [dy, 0, dy], [0, dy, dy], - ]) { + for (const yShifts of [[dy, dy, dy], [0, 0, 0], [dy, 0, 0], [0, dy, 0], [dy, dy, 0], [0, 0, dy], [dy, 0, dy], [0, dy, dy]]) { const loop1 = GrowableXYZArray.create([ [0, 0, 0], [10, 0, 0], @@ -194,14 +206,16 @@ describe("ParityRegionSweep", () => { const dy = 50; let shiftX = 0; let shiftY = 0; - const inputs = IModelJson.Reader.parse(JSON.parse(fs.readFileSync("./src/test/data/curve/parityRegionSweep/karolisParityRegionSweep.imjs", "utf8"))) as GeometryQuery[]; + const inputs = IModelJson.Reader.parse( + JSON.parse(fs.readFileSync("./src/test/data/curve/parityRegionSweep/karolisParityRegionSweep.imjs", "utf8")), + ) as GeometryQuery[]; ck.testDefined(inputs, "linearSweep imported"); const boundaryEdges: SortableEdgeCluster[] = []; const nullEdges: SortableEdgeCluster[] = []; const otherClusteredEdges: SortableEdgeCluster[] = []; let boundaryEdgeCount = 0, nullEdgeCount = 0, otherClusteredEdgeCount = 0; - const expectedBoundaryEdgeCount = 0, expectedNullEdgeCount = 0, expectedOtherClusteredEdgeCount = 3; // we know there are 3 singular vertices in the parity regions + const expectedBoundaryEdgeCount = 0, expectedNullEdgeCount = 0, expectedOtherClusteredEdgeCount = 3; // we know there are 3 singular vertices in the parity regions for (const input of inputs) { const solid = input as LinearSweep; @@ -235,5 +249,4 @@ describe("ParityRegionSweep", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "ParityRegionSweep", "KarolisRegion"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/polyface/Polyface.test.ts b/core/geometry/src/test/polyface/Polyface.test.ts index 27e256608f5e..3de014e8e5f0 100644 --- a/core/geometry/src/test/polyface/Polyface.test.ts +++ b/core/geometry/src/test/polyface/Polyface.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; +import { CloneFunction, Dictionary, OrderedComparator } from "@itwin/core-bentley"; import { randomInt } from "crypto"; import * as fs from "fs"; -import { CloneFunction, Dictionary, OrderedComparator } from "@itwin/core-bentley"; +import { describe, expect, it } from "vitest"; import { Arc3d } from "../../curve/Arc3d"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineString3d } from "../../curve/LineString3d"; @@ -133,9 +133,14 @@ it("Polyface.HelloWorld", () => { const numX = 3; const numY = 2; const polyface0 = Sample.createTriangularUnitGridPolyface( - origin, Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), - numX, numY, - true, true, true, // params, normals, and colors + origin, + Vector3d.create(1, 0, 0), + Vector3d.create(0, 1, 0), + numX, + numY, + true, + true, + true, // params, normals, and colors ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface0); GeometryCoreTestIO.saveGeometry(allGeometry, "Polyface", "HelloWorld"); @@ -157,7 +162,9 @@ it("Polyface.HelloWorld", () => { ck.testExactNumber(numVertex, polyface0.paramCount, "known param count in grid"); const numFacet = 2 * (numX - 1) * (numY - 1); // 2 triangles per quad ck.testExactNumber( - numFacet * 4, polyface0.zeroTerminatedIndexCount, "zeroTerminatedIndexCount in triangular grid: (A B C 0)", + numFacet * 4, + polyface0.zeroTerminatedIndexCount, + "zeroTerminatedIndexCount in triangular grid: (A B C 0)", ); ck.testExactNumber(numFacet, 2 * polyface0.colorCount, "known color count in one-color-per-quad grid"); ck.testExactNumber(1, polyface0.normalCount, "single normal for planar grid"); @@ -301,8 +308,12 @@ it("Polyface.RaggedBoxVolume", () => { // we expect to detect the mismatched projections in the moments const planeB = Plane3dByOriginAndUnitNormal.createXYZUVW(0, 0, 0, 1, 2, 3)!; const volumeB = PolyfaceQuery.sumVolumeBetweenFacetsAndPlane(polyface, planeB); - ck.testFalse(MomentData.areEquivalentPrincipalAxes( - volumeB.positiveProjectedFacetAreaMoments, volumeB.negativeProjectedFacetAreaMoments), "Expect mismatched moments", + ck.testFalse( + MomentData.areEquivalentPrincipalAxes( + volumeB.positiveProjectedFacetAreaMoments, + volumeB.negativeProjectedFacetAreaMoments, + ), + "Expect mismatched moments", ); expect(ck.getNumErrors()).toBe(0); }); @@ -321,14 +332,16 @@ it("Polyface.RaggedBoxMisMatch", () => { // point with (x,y,q) // q = 0 means do not expect same moments // q = 1 means expect same moments - for (const corner of [ - Point3d.create(ax0, ay, 1), // everything matches - Point3d.create(-ax0, -ay, 1), // everything matches - Point3d.create(ax0 * f, ay / f, 0), // area matches - Point3d.create(ax0 * 2, ay, 0), // same orientation, different radii - Point3d.create(ax0, ay * 0.9, 0), // same orientation, different radii - Point3d.create(ay, ax0, 0), // rotate 90 degrees, same radii - ]) { + for ( + const corner of [ + Point3d.create(ax0, ay, 1), // everything matches + Point3d.create(-ax0, -ay, 1), // everything matches + Point3d.create(ax0 * f, ay / f, 0), // area matches + Point3d.create(ax0 * 2, ay, 0), // same orientation, different radii + Point3d.create(ax0, ay * 0.9, 0), // same orientation, different radii + Point3d.create(ay, ax0, 0), // rotate 90 degrees, same radii + ] + ) { const builder = PolyfaceBuilder.create(); const bx = corner.x; const by = corner.y; @@ -351,7 +364,8 @@ it("Polyface.RaggedBoxMisMatch", () => { ck.testBoolean( expectSameMoments, MomentData.areEquivalentPrincipalAxes( - volumeData.positiveProjectedFacetAreaMoments, volumeData.negativeProjectedFacetAreaMoments, + volumeData.positiveProjectedFacetAreaMoments, + volumeData.negativeProjectedFacetAreaMoments, ), "Expect mismatched moments", ); @@ -395,10 +409,23 @@ function writeMeshes( if (!gRange.isNull) { const corners = gRange.corners(); const ls = LineString3d.create( - corners[0], corners[1], corners[5], corners[1], - corners[3], corners[7], corners[3], corners[2], - corners[6], corners[2], corners[2], corners[0], - corners[4], corners[5], corners[7], corners[6], corners[4], + corners[0], + corners[1], + corners[5], + corners[1], + corners[3], + corners[7], + corners[3], + corners[2], + corners[6], + corners[2], + corners[2], + corners[0], + corners[4], + corners[5], + corners[7], + corners[6], + corners[4], ); ls.tryTransformInPlace(transformForPolyfaceRangeSticks); allMesh.push(ls); @@ -407,7 +434,8 @@ function writeMeshes( const polyface = builder.claimPolyface(); if (polyface) { const rotationTransform = Transform.createFixedPointAndMatrix( - Point3d.create(0.25, 0.25, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(10)), + Point3d.create(0.25, 0.25, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(10)), ); const polyfaceA = polyface.cloneTransformed(rotationTransform); polyfaceA.tryTranslateInPlace(0, 1.5 * (gRange.high.y - gRange.low.y)); @@ -516,9 +544,10 @@ function flattenGeometry(...data: GeometryData[]): GeometryQuery[] { for (const member of data) { if (member instanceof GeometryQuery) result.push(member); - else if (Array.isArray(member)) + else if (Array.isArray(member)) { for (const g of member) result.push(g); + } } return result; } @@ -575,7 +604,12 @@ describe("Polyface.Facets", () => { it("RotationalSweeps", () => { writeAllMeshes( - Sample.createSimpleRotationalSweeps(), "RotationalSweep", true, allOptions, y0RotationalSweep, optionYStep, + Sample.createSimpleRotationalSweeps(), + "RotationalSweep", + true, + allOptions, + y0RotationalSweep, + optionYStep, ); }); it("RuledSweeps", () => { @@ -643,7 +677,6 @@ describe("Polyface.Facets", () => { countsC.push(facetsC.facetCount); if (radius < 80) GeometryCoreTestIO.captureCloneGeometry(allGeometry, facetsC, xC, y0); - } ck.testExactNumber(countsA[0], countsA[1], "angleTol counts not affected by radius"); ck.testExactNumber(countsA[1], countsA[2], "angleTol counts not affected by radius"); @@ -867,7 +900,9 @@ describe("Polyface.Faces", () => { ck.testCoordinate( currentParam.x, Geometry.hypotenuseXYZ( - currentPoint.x - oldPoint.x, currentPoint.y - oldPoint.y, currentPoint.z - oldPoint.z, + currentPoint.x - oldPoint.x, + currentPoint.y - oldPoint.y, + currentPoint.z - oldPoint.z, ), ); ck.testCoordinate(polyface.data.param!.getYAtUncheckedPointIndex(idx), 0); @@ -930,7 +965,7 @@ it("facets from sweep contour with holes", () => { Point3d.create(4, 3, 0), Point3d.create(4, 4, 0), ) as Arc3d; - arc.sweep = (AngleSweep.createStartEndDegrees(0, 360)); + arc.sweep = AngleSweep.createStartEndDegrees(0, 360); const region = ParityRegion.create( Loop.create(LineString3d.createRectangleXY(Point3d.create(0, 0, 0), 5, 5)), Loop.create(LineString3d.createRectangleXY(Point3d.create(1, 1, 0), 1, 1)), @@ -961,7 +996,12 @@ it("facets from sweep contour with holes", () => { }); function createGridMeshByCoordinates( - numXEdge: number, numYEdge: number, xShiftCounter: number, reverseFacets: boolean, needParams: boolean, needNormals: boolean, + numXEdge: number, + numYEdge: number, + xShiftCounter: number, + reverseFacets: boolean, + needParams: boolean, + needNormals: boolean, ): IndexedPolyface { const options = StrokeOptions.createForFacets(); options.needNormals = needNormals; @@ -988,7 +1028,12 @@ function createGridMeshByCoordinates( } function createMeshByUVSurface( - surface: UVSurface, numXEdge: number, numYEdge: number, reverseFacets: boolean, needParams: boolean, needNormals: boolean, + surface: UVSurface, + numXEdge: number, + numYEdge: number, + reverseFacets: boolean, + needParams: boolean, + needNormals: boolean, ): IndexedPolyface { const options = StrokeOptions.createForFacets(); options.needNormals = needNormals; @@ -1047,11 +1092,13 @@ it("SolidPrimitiveBoundary", () => { const delta = 10; const z1 = 10.0; for (const capped of [true, false]) { - for (const solid of [ - Box.createRange(Range3d.createXYZXYZ(0, 0, 0, 1, 2, 3), capped)!, - TorusPipe.createInFrame(Transform.createIdentity(), 2, 1, Angle.createDegrees(180), capped)!, - Cone.createBaseAndTarget(Point3d.create(0, 0, 0), Point3d.create(0, 0, 2), Vector3d.unitX(), Vector3d.unitY(), 2, 1, capped), - ]) { + for ( + const solid of [ + Box.createRange(Range3d.createXYZXYZ(0, 0, 0, 1, 2, 3), capped)!, + TorusPipe.createInFrame(Transform.createIdentity(), 2, 1, Angle.createDegrees(180), capped)!, + Cone.createBaseAndTarget(Point3d.create(0, 0, 0), Point3d.create(0, 0, 2), Vector3d.unitX(), Vector3d.unitY(), 2, 1, capped), + ] + ) { const builder = PolyfaceBuilder.create(); builder.addGeometryQuery(solid); const mesh = builder.claimPolyface(); @@ -1066,12 +1113,15 @@ it("SolidPrimitiveBoundary", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, x0, y0 + 3 * delta); let y1 = y0 + 5 * delta; - for (const angle of [ - undefined, Angle.createDegrees(0.1), - Angle.createDegrees(15), - Angle.createDegrees(30), - Angle.createDegrees(50), - ]) { + for ( + const angle of [ + undefined, + Angle.createDegrees(0.1), + Angle.createDegrees(15), + Angle.createDegrees(30), + Angle.createDegrees(50), + ] + ) { PolyfaceQuery.markPairedEdgesInvisible(mesh, angle); const boundary1 = PolyfaceQuery.boundaryEdges(mesh); GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, x0, y1); @@ -1094,11 +1144,21 @@ it("UVGridSurface", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const surface = new UVSinusoidalSurface( - AngleSweep.createStartEndDegrees(0, 180), AngleSweep.createStartEndDegrees(20, 100), + AngleSweep.createStartEndDegrees(0, 180), + AngleSweep.createStartEndDegrees(20, 100), Transform.createRowValues( - 4, 0, 0, 0, - 0, 4, 0, 0, - 0, 0, 1, 0, + 4, + 0, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 1, + 0, ), ); allGeometry.push(createMeshByUVSurface(surface, 4, 6, false, true, true)); @@ -1118,7 +1178,8 @@ it("AddTriangleFan", () => { const strokes = LineString3d.create(); arc.emitStrokes(strokes, options); ck.testUndefined( - builder.findOrAddPointInLineString(strokes, strokes.numPoints() + 10), " confirm bad index in linestring", + builder.findOrAddPointInLineString(strokes, strokes.numPoints() + 10), + " confirm bad index in linestring", ); ck.testUndefined(builder.findOrAddPointInLineString(strokes, -1), " confirm bad index in linestring"); const coneA = Point3d.create(0, 0, 5); @@ -1255,15 +1316,23 @@ it("AddPolyface", () => { Point3d.create(0, 0, 0), Vector3d.unitX(), Vector3d.unitY(), - 2, 3, - true, true, true, true, + 2, + 3, + true, + true, + true, + true, ); const polyfaceB = Sample.createTriangularUnitGridPolyface( Point3d.create(5, 0, 0), Vector3d.unitX(), Vector3d.unitY(), - 2, 3, - true, true, true, true, + 2, + 3, + true, + true, + true, + true, ); const options = StrokeOptions.createForFacets(); options.needNormals = true; @@ -1287,14 +1356,25 @@ it("AddSweptIndexedPolyface", () => { const size = 10; const seed = 10; const baseMesh = Sample.createTriangularUnitGridPolyface( - Point3d.create(0, 0, 0), Vector3d.unitX(), Vector3d.unitY(), size, size, true, true, true, true, + Point3d.create(0, 0, 0), + Vector3d.unitX(), + Vector3d.unitY(), + size, + size, + true, + true, + true, + true, ); // randomly perturb grid in z, and compute new tri normals const xyz = Point3d.create(); for (let i = 0; i < baseMesh.data.pointCount; ++i) { baseMesh.data.point.getPoint3dAtUncheckedPointIndex(i, xyz); baseMesh.data.point.setXYZAtCheckedPointIndex( - i, xyz.x, xyz.y, xyz.z + (i % 2 ? -1 : 1) * (randomInt(0, seed) / seed) / 2, + i, + xyz.x, + xyz.y, + xyz.z + (i % 2 ? -1 : 1) * (randomInt(0, seed) / seed) / 2, ); } const normal = Vector3d.create(); @@ -1314,7 +1394,8 @@ it("AddSweptIndexedPolyface", () => { const sweptPolyface3 = builder3.claimPolyface(true); const sideFacetCount = 2 * 4 * (size - 1); ck.testExactNumber( - 2 * baseMesh.facetCount + sideFacetCount, sweptPolyface3.facetCount, + 2 * baseMesh.facetCount + sideFacetCount, + sweptPolyface3.facetCount, "Triangulated swept polyface has expected facet count.", ); ck.testBoolean( @@ -1328,7 +1409,9 @@ it("AddSweptIndexedPolyface", () => { const sweptPolyface4 = builder4.claimPolyface(true); ck.testUndefined(sweptPolyface4.data.color, "Swept polyface colors ignored."); ck.testExactNumber( - 2 * baseMesh.facetCount + sideFacetCount / 2, sweptPolyface4.facetCount, "Swept polyface has expected facet count.", + 2 * baseMesh.facetCount + sideFacetCount / 2, + sweptPolyface4.facetCount, + "Swept polyface has expected facet count.", ); ck.testBoolean(true, PolyfaceQuery.isPolyfaceManifold(sweptPolyface4, false), "Swept polyface is closed manifold."); @@ -1360,10 +1443,12 @@ it("EmptyPolyface", () => { }); it("Polyface.VisitorParamQueries", () => { - for (const geom of [ - Cone.createAxisPoints(Point3d.create(0, 0, 0), Point3d.create(0, 0, 5), 1.0, 0.5, true)!, - Sphere.createCenterRadius(Point3d.create(0, 0, 0), 2.0, AngleSweep.createStartEndDegrees(0, 90)), - ]) { + for ( + const geom of [ + Cone.createAxisPoints(Point3d.create(0, 0, 0), Point3d.create(0, 0, 5), 1.0, 0.5, true)!, + Sphere.createCenterRadius(Point3d.create(0, 0, 0), 2.0, AngleSweep.createStartEndDegrees(0, 90)), + ] + ) { const options = new StrokeOptions(); options.needParams = true; options.needNormals = true; @@ -1623,7 +1708,7 @@ function createPolyfaceFromSynchro(geom: any): Polyface { } function enumerateToNumberArray(data: any): number[] { const result = []; - for (let i = 0; ; i++) { + for (let i = 0;; i++) { if (data.hasOwnProperty(i)) { result.push(data[i]); } else break; @@ -1771,7 +1856,9 @@ describe("SphericalMeshData", () => { const inserted = normalToAuxIndex.insert(normal, iAuxData); if (!inserted) ck.testExactNumber( - normalToAuxIndex.get(normal)!, iAuxData, "at a vertex, sectors with same normal have same uv/color", + normalToAuxIndex.get(normal)!, + iAuxData, + "at a vertex, sectors with same normal have same uv/color", ); } } @@ -1841,8 +1928,7 @@ describe("SphericalMeshData", () => { colors = mesh.data.color.slice(); for (const visitor = mesh.createVisitor(); visitor.moveToNextFacet();) ck.testTrue( - normalToColorIndex.insert(visitor.getNormal(0, normal)!, - visitor.colorIndex![0]), + normalToColorIndex.insert(visitor.getNormal(0, normal)!, visitor.colorIndex![0]), "associate normal to color of face", ); } @@ -1875,10 +1961,14 @@ describe("SphericalMeshData", () => { ck.testExactNumber(mesh1.pointCount, mesh.pointCount, "triangulation didn't add any vertices"); ck.testExactNumber(mesh1.facetCount, 54 + mesh.facetCount, "triangulation produced expected facet count"); ck.testExactNumber( - mesh1.data.pointIndex.length, 108 + mesh.data.pointIndex.length, "triangulation produced expected edge count", + mesh1.data.pointIndex.length, + 108 + mesh.data.pointIndex.length, + "triangulation produced expected edge count", ); ck.testExactNumber( - mesh1.pointCount - (mesh1.data.pointIndex.length / 2) + mesh1.facetCount, 2, "triangulation satisfies Euler equation", + mesh1.pointCount - (mesh1.data.pointIndex.length / 2) + mesh1.facetCount, + 2, + "triangulation satisfies Euler equation", ); // reinstall per-facet normals PolyfaceQuery.buildPerFaceNormals(mesh1); @@ -1946,7 +2036,11 @@ describe("PolyfaceVisitor", () => { } const testMesh = ( - mesh: IndexedPolyface, expectedFacetCount: number, compare?: Vector3d, sideAngle?: Angle, numWrap?: number, + mesh: IndexedPolyface, + expectedFacetCount: number, + compare?: Vector3d, + sideAngle?: Angle, + numWrap?: number, ): void => { y0 += delta; const visitor = IndexedPolyfaceSubsetVisitor.createNormalComparison(mesh, compare, sideAngle, numWrap); @@ -1962,17 +2056,23 @@ describe("PolyfaceVisitor", () => { "visitor facet count agrees with general facet count query", ); ck.testExactNumber( - visitor.currentReadIndex(), currReadIndex, "visitorClientFacetCount does not change the read index", + visitor.currentReadIndex(), + currReadIndex, + "visitorClientFacetCount does not change the read index", ); visitor.reset(); // visit first facet ck.testExactNumber( - visitor.point.length - visitor.numEdgesThisFacet, numWrap ?? 0, "visitor has expected numWrap", + visitor.point.length - visitor.numEdgesThisFacet, + numWrap ?? 0, + "visitor has expected numWrap", ); const builder = PolyfaceBuilder.create(); builder.addFacetsFromVisitor(visitor); const subsetMesh = builder.claimPolyface(); ck.testExactNumber( - subsetMesh.facetCount, visitor.getVisitableFacetCount(), "visitor sends all of its facets to the builder", + subsetMesh.facetCount, + visitor.getVisitableFacetCount(), + "visitor sends all of its facets to the builder", ); if (numWrap === undefined) GeometryCoreTestIO.captureCloneGeometry(allGeometry, subsetMesh, x0, y0); @@ -1988,7 +2088,7 @@ describe("PolyfaceVisitor", () => { testMesh(myMesh, 400, undefined, undefined, 1); testMesh(myMesh, 400, undefined, Angle.createDegrees(0.01), undefined); testMesh(myMesh, 0, toBottom, undefined, undefined); - y0 += delta; // skip + y0 += delta; // skip testMesh(myMesh, 126, toFront, undefined, undefined); testMesh(myMesh, 126, toFront, Angle.createDegrees(0.1), undefined); testMesh(myMesh, 278, toIso, undefined, undefined); diff --git a/core/geometry/src/test/polyface/PolyfaceAuxData.test.ts b/core/geometry/src/test/polyface/PolyfaceAuxData.test.ts index 1e27897448cb..584fd9e6deb2 100644 --- a/core/geometry/src/test/polyface/PolyfaceAuxData.test.ts +++ b/core/geometry/src/test/polyface/PolyfaceAuxData.test.ts @@ -25,7 +25,6 @@ import { ImportedSample } from "../ImportedSamples"; /** Create a polyface representing a cantilever beam with [[PolyfaceAuxData]] representing the stress and deflection. */ function createCantileverBeamPolyface(beamRadius: number = 10.0, beamLength: number = 100.0, facetSize: number = 1.0, zScale: number = 1.0) { - const builder = PolyfaceBuilder.create(); const crossSectionArc = Arc3d.create(Point3d.createZero(), Vector3d.create(0.0, beamRadius, 0.0), Vector3d.create(0.0, 0.0, beamRadius)); const strokedCrossSection = LineString3d.create(); @@ -35,7 +34,12 @@ function createCantileverBeamPolyface(beamRadius: number = 10.0, beamLength: num // pack as a singleton path to touch "else" const path = Path.create(strokedCrossSection); for (let x = 0.0; x < beamLength; x += facetSize) - builder.addBetweenTransformedLineStrings(path, Transform.createTranslationXYZ(x, 0.0, 0.0), Transform.createTranslationXYZ(x + facetSize, 0.0, 0.0), true); + builder.addBetweenTransformedLineStrings( + path, + Transform.createTranslationXYZ(x, 0.0, 0.0), + Transform.createTranslationXYZ(x + facetSize, 0.0, 0.0), + true, + ); const polyface = builder.claimPolyface(); const heightData: number[] = []; @@ -87,29 +91,14 @@ describe("PolyfaceAuxData", () => { const data10 = new AuxChannelData(10, [11, 12, 13]); const data20 = new AuxChannelData(20, [21, 22, 25]); const data20B = new AuxChannelData(20, [21, 22, 26]); - const channel0 = new AuxChannel([data00, data10, data20], - AuxChannelDataType.Distance, - "MyDistances", - "MicrometerA"); - - const channelA = new AuxChannel([data00, data10], - AuxChannelDataType.Distance, - "MyDistancesA", - "MicrometerA"); - - const channelB = new AuxChannel([data00, data20, data10], - AuxChannelDataType.Distance, - "MyDistancesB", - "MicrometerA"); - - const channelC = new AuxChannel([data00, data20, data10], - AuxChannelDataType.Distance, - "MyDistancesC", - "MicrometerA"); - const channelD = new AuxChannel([data00, data20B, data10], - AuxChannelDataType.Distance, - "MyDistancesC", - "MicrometerA"); + const channel0 = new AuxChannel([data00, data10, data20], AuxChannelDataType.Distance, "MyDistances", "MicrometerA"); + + const channelA = new AuxChannel([data00, data10], AuxChannelDataType.Distance, "MyDistancesA", "MicrometerA"); + + const channelB = new AuxChannel([data00, data20, data10], AuxChannelDataType.Distance, "MyDistancesB", "MicrometerA"); + + const channelC = new AuxChannel([data00, data20, data10], AuxChannelDataType.Distance, "MyDistancesC", "MicrometerA"); + const channelD = new AuxChannel([data00, data20B, data10], AuxChannelDataType.Distance, "MyDistancesC", "MicrometerA"); const channel1 = channel0.clone(); ck.testTrue(channel0.isAlmostEqual(channel0)); @@ -157,11 +146,20 @@ describe("PolyfaceAuxData", () => { const allGeometry: GeometryQuery[] = []; const mesh = ImportedSample.createPolyhedron62(); if (ck.testType(mesh, IndexedPolyface, "imported mesh")) { - const latitude = mesh.data.point.getPoint3dArray().map((pt: Point3d) => { return pt.z; }); + const latitude = mesh.data.point.getPoint3dArray().map((pt: Point3d) => { + return pt.z; + }); const latitudeChannel = new AuxChannel([new AuxChannelData(0, latitude)], AuxChannelDataType.Distance, "Latitude", "Time"); - const octant = mesh.data.point.getPoint3dArray().map((pt: Point3d) => { return Point3d.create(Geometry.split3Way01(pt.x), Geometry.split3Way01(pt.y), Geometry.split3Way01(pt.z)); }); - const octantChannel = new AuxChannel([new AuxChannelData(0, Point3dArray.packToNumberArray(octant))], AuxChannelDataType.Vector, "Octant", "Time"); + const octant = mesh.data.point.getPoint3dArray().map((pt: Point3d) => { + return Point3d.create(Geometry.split3Way01(pt.x), Geometry.split3Way01(pt.y), Geometry.split3Way01(pt.z)); + }); + const octantChannel = new AuxChannel( + [new AuxChannelData(0, Point3dArray.packToNumberArray(octant))], + AuxChannelDataType.Vector, + "Octant", + "Time", + ); const mesh0 = mesh.clone(); mesh0.data.auxData = new PolyfaceAuxData([latitudeChannel.clone()], mesh0.data.pointIndex.slice()); @@ -198,7 +196,7 @@ describe("PolyfaceAuxData", () => { if (bytes2 && GeometryCoreTestIO.enableSave) { const dir = "PolyfaceAuxData"; const filename = "Compress"; - GeometryCoreTestIO.writeByteArrayToTextFile(bytes2, dir, filename, undefined, "fbjs"); // used for fuzz seed + GeometryCoreTestIO.writeByteArrayToTextFile(bytes2, dir, filename, undefined, "fbjs"); // used for fuzz seed const pathname = GeometryCoreTestIO.makeOutputDir(dir).concat(`/${filename}`).concat(".fb"); GeometryCoreTestIO.writeBytesToFile(bytes2, pathname); const bytes3 = GeometryCoreTestIO.readBytesFromFile(pathname); @@ -264,14 +262,32 @@ describe("PolyfaceAuxData", () => { } // Static Channels - auxChannels.push(new AuxChannel([new AuxChannelData(0.0, radialDisplacementData)], AuxChannelDataType.Vector, "Static Radial Displacement", "Radial: Static")); - auxChannels.push(new AuxChannel([new AuxChannelData(1.0, radialHeightData)], AuxChannelDataType.Distance, "Static Radial Height", "Radial: Static")); - auxChannels.push(new AuxChannel([new AuxChannelData(1.0, radialSlopeData)], AuxChannelDataType.Scalar, "Static Radial Slope", "Radial: Static")); + auxChannels.push( + new AuxChannel([new AuxChannelData(0.0, radialDisplacementData)], AuxChannelDataType.Vector, "Static Radial Displacement", "Radial: Static"), + ); + auxChannels.push( + new AuxChannel([new AuxChannelData(1.0, radialHeightData)], AuxChannelDataType.Distance, "Static Radial Height", "Radial: Static"), + ); + auxChannels.push( + new AuxChannel([new AuxChannelData(1.0, radialSlopeData)], AuxChannelDataType.Scalar, "Static Radial Slope", "Radial: Static"), + ); // Animated Channels - const radialDisplacementDataVector = [new AuxChannelData(0.0, zeroDisplacementData), new AuxChannelData(1.0, radialDisplacementData), new AuxChannelData(2.0, zeroDisplacementData)]; - const radialHeightDataVector = [new AuxChannelData(0.0, zeroScalarData), new AuxChannelData(1.0, radialHeightData), new AuxChannelData(2.0, zeroScalarData)]; - const radialSlopeDataVector = [new AuxChannelData(0.0, zeroScalarData), new AuxChannelData(1.0, radialSlopeData), new AuxChannelData(2.0, zeroScalarData)]; + const radialDisplacementDataVector = [ + new AuxChannelData(0.0, zeroDisplacementData), + new AuxChannelData(1.0, radialDisplacementData), + new AuxChannelData(2.0, zeroDisplacementData), + ]; + const radialHeightDataVector = [ + new AuxChannelData(0.0, zeroScalarData), + new AuxChannelData(1.0, radialHeightData), + new AuxChannelData(2.0, zeroScalarData), + ]; + const radialSlopeDataVector = [ + new AuxChannelData(0.0, zeroScalarData), + new AuxChannelData(1.0, radialSlopeData), + new AuxChannelData(2.0, zeroScalarData), + ]; auxChannels.push(new AuxChannel(radialDisplacementDataVector, AuxChannelDataType.Vector, "Animated Radial Displacement", "Radial: Time")); auxChannels.push(new AuxChannel(radialHeightDataVector, AuxChannelDataType.Distance, "Animated Radial Height", "Radial: Time")); @@ -316,7 +332,7 @@ describe("PolyfaceAuxData", () => { const filename = "indexedMesh-auxData2-new"; const mesh = createFlatMeshWithWaves(); if (ck.testDefined(mesh, "created mesh with auxData")) { - GeometryCoreTestIO.saveGeometry(mesh, dir, filename); // write .imjs file + GeometryCoreTestIO.saveGeometry(mesh, dir, filename); // write .imjs file const bytes = BentleyGeometryFlatBuffer.geometryToBytes(mesh, true); if (ck.testDefined(bytes, "exported mesh to fb bytes")) { const pathname = GeometryCoreTestIO.makeOutputDir(dir).concat(`/${filename}`).concat(".fb"); diff --git a/core/geometry/src/test/polyface/PolyfaceData.test.ts b/core/geometry/src/test/polyface/PolyfaceData.test.ts index b659f13fd03a..a8b148fb51f4 100644 --- a/core/geometry/src/test/polyface/PolyfaceData.test.ts +++ b/core/geometry/src/test/polyface/PolyfaceData.test.ts @@ -60,9 +60,14 @@ describe("PolyfaceData", () => { const numX = 3; const numY = 2; const polyface0 = Sample.createTriangularUnitGridPolyface( - origin, Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), - numX, numY, - true, true, true, // params, normals, and colors + origin, + Vector3d.create(1, 0, 0), + Vector3d.create(0, 1, 0), + numX, + numY, + true, + true, + true, // params, normals, and colors ); ck.testExactNumber(polyface0.data.pointIndex[0], 0); ck.testExactNumber(polyface0.data.pointIndex[1], 1); @@ -120,9 +125,14 @@ describe("PolyfaceData", () => { const numX = 3; const numY = 2; const polyface0 = Sample.createTriangularUnitGridPolyface( - origin, Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), - numX, numY, - true, true, true, // params, normals, and colors + origin, + Vector3d.create(1, 0, 0), + Vector3d.create(0, 1, 0), + numX, + numY, + true, + true, + true, // params, normals, and colors ); ck.testExactNumber(polyface0.data.pointIndex[0], 0); ck.testExactNumber(polyface0.data.pointIndex[1], 1); diff --git a/core/geometry/src/test/polyface/PolyfaceQuery.test.ts b/core/geometry/src/test/polyface/PolyfaceQuery.test.ts index e8e0ceb1624c..fee7acf9642d 100644 --- a/core/geometry/src/test/polyface/PolyfaceQuery.test.ts +++ b/core/geometry/src/test/polyface/PolyfaceQuery.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { Arc3d } from "../../curve/Arc3d"; import { AnyCurve } from "../../curve/CurveTypes"; import { GeometryQuery } from "../../curve/GeometryQuery"; @@ -57,7 +57,7 @@ function addSquareFacet(builder: PolyfaceBuilder, x0: number, y0: number, a: num const normalZ = builder.reversedFlag ? -1 : 1; const pointArray = [Point3d.create(x0, y0), Point3d.create(x1, y0), Point3d.create(x1, y1), Point3d.create(x0, y1)]; const points = GrowableXYZArray.create(pointArray); - const params = GrowableXYArray.create(pointArray); // this ignores z + const params = GrowableXYArray.create(pointArray); // this ignores z const normals = GrowableXYZArray.create([[0, 0, normalZ], [0, 0, normalZ], [0, 0, normalZ], [0, 0, normalZ]]); const colors = [blue1, blue2, red1, green1]; builder.addFacetFromGrowableArrays(points, normals, params, colors); @@ -98,10 +98,11 @@ it("PartitionFacetsByConnectivity", () => { polyface.twoSided = true; const partitionArray = [ PolyfaceQuery.partitionFacetIndicesByVertexConnectedComponent(polyface), - PolyfaceQuery.partitionFacetIndicesByEdgeConnectedComponent(polyface)]; + PolyfaceQuery.partitionFacetIndicesByEdgeConnectedComponent(polyface), + ]; const expectedComponentCountArray = [numVertexConnectedComponents, numEdgeConnectedComponents]; GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface, x0, y0); - y0 = - 2 * numVertexConnectedComponents * a; + y0 = -2 * numVertexConnectedComponents * a; x0 += (numVertexConnectedComponents + 2) * a; for (const selector of [0, 1]) { const partitions = partitionArray[selector]; @@ -114,8 +115,19 @@ it("PartitionFacetsByConnectivity", () => { const range = fragment.range(); range.expandInPlace(expansion); const z1 = 0.01; - GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create( - Point3d.create(range.low.x, range.low.y), Point3d.create(range.high.x, range.low.y), Point3d.create(range.high.x, range.high.y), Point3d.create(range.low.x, range.high.y), Point3d.create(range.low.x, range.low.y)), x0, y0, z1); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineString3d.create( + Point3d.create(range.low.x, range.low.y), + Point3d.create(range.high.x, range.low.y), + Point3d.create(range.high.x, range.high.y), + Point3d.create(range.low.x, range.high.y), + Point3d.create(range.low.x, range.low.y), + ), + x0, + y0, + z1, + ); } y0 += (2 * numVertexConnectedComponents + 3) * a; } @@ -130,7 +142,11 @@ it("ExpandToMaximalPlanarFacetsA", () => { const allGeometry: GeometryQuery[] = []; const builder = PolyfaceBuilder.create(); const linestringA = LineString3d.create( - [0, 0, 0], [1, 0, 0], [2, 0, 0], [3, 0, 1], [4, 0, 0], + [0, 0, 0], + [1, 0, 0], + [2, 0, 0], + [3, 0, 1], + [4, 0, 0], ); const dx = 0; let dy = 1; @@ -191,9 +207,17 @@ function allEdgesAreVisible(mesh: IndexedPolyface, clusters: SortableEdgeCluster * @param expectAllSharpEdgesHidden whether to verify all sharp edges are hidden (default, false: verify all are visible) * @param expectAllOtherEdgesHidden whether to verify all other edges are hidden (default, false: verify all are visible) */ -function verifyEdgeCountsAndVisibilities(ck: Checker, mesh: IndexedPolyface, dihedralAngle: Angle | undefined, - expectedSmoothCount: number, expectedSharpCount: number, expectedOtherCount: number, - expectAllSmoothEdgesHidden?: boolean, expectAllSharpEdgesHidden?: boolean, expectAllOtherEdgesHidden?: boolean): boolean { +function verifyEdgeCountsAndVisibilities( + ck: Checker, + mesh: IndexedPolyface, + dihedralAngle: Angle | undefined, + expectedSmoothCount: number, + expectedSharpCount: number, + expectedOtherCount: number, + expectAllSmoothEdgesHidden?: boolean, + expectAllSharpEdgesHidden?: boolean, + expectAllOtherEdgesHidden?: boolean, +): boolean { const smoothEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh, dihedralAngle); const sharpEdges = PolyfaceQuery.collectEdgesByDihedralAngle(mesh, dihedralAngle, true); const otherEdges: SortableEdgeCluster[] = []; @@ -234,7 +258,7 @@ it("ExpandToMaximalPlanarFacetsWithHole", () => { const maximalPolyface = PolyfaceQuery.cloneWithMaximalPlanarFacets(polyface); if (maximalPolyface) { - verifyEdgeCountsAndVisibilities(ck, maximalPolyface, undefined, 4, 4, 36, true); // smooth edges are hidden because they are bridges + verifyEdgeCountsAndVisibilities(ck, maximalPolyface, undefined, 4, 4, 36, true); // smooth edges are hidden because they are bridges GeometryCoreTestIO.captureCloneGeometry(allGeometry, maximalPolyface, dx, dy += yStep, 0); dx += 20; } @@ -255,7 +279,7 @@ class VisitorSansMesh extends PolyfaceData implements PolyfaceVisitor { if (index < 0 || index >= this._numIndices) return false; this._index = index; - this.pointIndex = [index]; // each "face loop" is a singleton array holding a unique index + this.pointIndex = [index]; // each "face loop" is a singleton array holding a unique index return true; } public currentReadIndex(): number { @@ -333,8 +357,10 @@ it("FillHoles", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface, dx, dy += yStep, 0); dy += yStep; let numChains = 0; - PolyfaceQuery.announceBoundaryChainsAsLineString3d(polyface, - (ls: LineString3d) => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, ls, dx, dy); numChains++; }); + PolyfaceQuery.announceBoundaryChainsAsLineString3d(polyface, (ls: LineString3d) => { + GeometryCoreTestIO.captureCloneGeometry(allGeometry, ls, dx, dy); + numChains++; + }); ck.testExactNumber(3, numChains, "boundary chains"); const options = { includeOriginalMesh: false, upVector: Vector3d.unitZ(), maxPerimeter: 5 }; @@ -382,8 +408,14 @@ it("SimplestTriangulation", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, pointsA, dx, dy, dz); // ( force the linestring branch selectively) if (pointsA.length !== 4) - ck.testBoolean(expected, SpacePolygonTriangulation.triangulateSimplestSpaceLoop( - LineString3d.create(pointsA), announceTriangles), message); + ck.testBoolean( + expected, + SpacePolygonTriangulation.triangulateSimplestSpaceLoop( + LineString3d.create(pointsA), + announceTriangles, + ), + message, + ); else ck.testBoolean(expected, SpacePolygonTriangulation.triangulateSimplestSpaceLoop(pointsA, announceTriangles), message); dx += xStep; @@ -405,7 +437,10 @@ it("SimplestTriangulation", () => { doTest([points[0], points[1], points[1], points[2]], false, [0, 1, 1, 2]); doTest([points[0], pointQ, pointR, points[1]], false, "4 colinear"); doTest([points[0], pointQ, points[1]], false, "3 colinear"); - ck.testFalse(SpacePolygonTriangulation.triangulateSimplestSpaceLoop([points[0], points[1], points[3], points[2]], announceTriangles, 2.0), "perimeter trigger"); + ck.testFalse( + SpacePolygonTriangulation.triangulateSimplestSpaceLoop([points[0], points[1], points[3], points[2]], announceTriangles, 2.0), + "perimeter trigger", + ); GeometryCoreTestIO.saveGeometry(allGeometry, "PolyfaceQuery", "SimplestTriangulation"); expect(ck.getNumErrors()).toBe(0); @@ -453,7 +488,7 @@ it("GreedyEarCutTriangulation", () => { pointB.y += yMove; // hmm.. zz values don't bother it alone. // shifting y does make it fail . . .. - doTest(points, pointB, (yMove === 0), { fraction, zz, yMove }); + doTest(points, pointB, yMove === 0, { fraction, zz, yMove }); } } } @@ -530,7 +565,13 @@ describe("MarkVisibility", () => { const allGeometry: GeometryQuery[] = []; const numX = 4; const numY = 4; - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.create(1.0324, 0, 0.1), Vector3d.create(0, 1.123, 0.5), numX, numY); + const mesh = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.create(1.0324, 0, 0.1), + Vector3d.create(0, 1.123, 0.5), + numX, + numY, + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh, dx, dy, 0); dy += yStep; PolyfaceQuery.markPairedEdgesInvisible(mesh); @@ -588,7 +629,7 @@ describe("ReorientFacets", () => { const builderA = PolyfaceBuilder.create(); builderA.addPolygon([pointA0, pointB0, pointB1, pointA1]); - builderA.addPolygon([pointB0, pointC0, pointC1, pointB1]); // consistent + builderA.addPolygon([pointB0, pointC0, pointC1, pointB1]); // consistent const meshA = builderA.claimPolyface(); GeometryCoreTestIO.captureCloneGeometry(allGeometry, meshA, x0, y0, 0); PolyfaceQuery.reorientVertexOrderAroundFacetsForConsistentOrientation(meshA); @@ -596,7 +637,7 @@ describe("ReorientFacets", () => { x0 += 10; const builderB = PolyfaceBuilder.create(); builderB.addPolygon([pointA0, pointB0, pointB1, pointA1]); - builderB.addPolygon([pointB0, pointB1, pointC1, pointC0]); // consistent + builderB.addPolygon([pointB0, pointB1, pointC1, pointC0]); // consistent const meshB = builderB.claimPolyface(true); GeometryCoreTestIO.captureCloneGeometry(allGeometry, meshB, x0, y0, 0); PolyfaceQuery.reorientVertexOrderAroundFacetsForConsistentOrientation(meshB); @@ -615,7 +656,13 @@ describe("ReorientFacets", () => { const dx = 12.0; const facetsToFlip = [3, 4, 5, 12, 13, 14]; for (let numFlip = 0; numFlip < facetsToFlip.length; numFlip++) { - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.create(1.0324, 0, 0.1), Vector3d.create(0, 1.123, 0.5), 3, 7); + const mesh = Sample.createTriangularUnitGridPolyface( + Point3d.create(0, 0, 0), + Vector3d.create(1.0324, 0, 0.1), + Vector3d.create(0, 1.123, 0.5), + 3, + 7, + ); for (let i = 0; i < numFlip; i++) mesh.reverseSingleFacet(facetsToFlip[i]); ck.testBoolean(numFlip === 0, PolyfaceQuery.isPolyfaceManifold(mesh, true), "initial mesh pairing state"); @@ -675,12 +722,32 @@ describe("ReorientFacets", () => { [0, 0.5, 0.5], ], pointIndex: [ - 1, 2, 4, 3, 0, - 3, 4, 6, 5, 0, - 5, 6, 8, 0, - 5, 8, 7, 0, - 7, 8, 1, 0, - 1, 7, 2, 0, + 1, + 2, + 4, + 3, + 0, + 3, + 4, + 6, + 5, + 0, + 5, + 6, + 8, + 0, + 5, + 8, + 7, + 0, + 7, + 8, + 1, + 0, + 1, + 7, + 2, + 0, ], }, }; @@ -699,17 +766,41 @@ describe("ReorientFacets", () => { [-1, a + b, 1], ], pointIndex: [ - 1, 2, 3, 0, - 1, 3, 4, 0, - - 4, 3, 6, 0, - 6, 5, 4, 0, - - 5, 6, 7, 0, - 5, 7, 8, 0, - - 8, 7, 1, 0, - 8, 1, 2, 0, + 1, + 2, + 3, + 0, + 1, + 3, + 4, + 0, + + 4, + 3, + 6, + 0, + 6, + 5, + 4, + 0, + + 5, + 6, + 7, + 0, + 5, + 7, + 8, + 0, + + 8, + 7, + 1, + 0, + 8, + 1, + 2, + 0, ], }, }; @@ -766,11 +857,30 @@ describe("ReorientFacets", () => { [3, 0, 0], ], pointIndex: [ - 1, 2, 5, 4, 0, - 3, 6, 5, 2, 0, - 7, 4, 5, 8, 0, - 9, 8, 5, 6, 0, - 3, 10, 6, 0, + 1, + 2, + 5, + 4, + 0, + 3, + 6, + 5, + 2, + 0, + 7, + 4, + 5, + 8, + 0, + 9, + 8, + 5, + 6, + 0, + 3, + 10, + 6, + 0, ], }, }; @@ -900,21 +1010,33 @@ describe("ReorientFacets", () => { ck.testBoolean(dihedralA > 0, PolyfaceQuery.isConvexByDihedralAngleCount(meshA), "Dihedral angle counts match closure"); if (dihedralA !== 0) GeometryCoreTestIO.captureCloneGeometry( - allGeometry, [Point3d.create(0, 0, 0), Point3d.create(0, dihedralA * strokeLength, 0)], x0, y0, + allGeometry, + [Point3d.create(0, 0, 0), Point3d.create(0, dihedralA * strokeLength, 0)], + x0, + y0, ); else GeometryCoreTestIO.captureCloneGeometry( - allGeometry, [Point3d.create(0, dxB, 0), Point3d.create(strokeLength, dxB, 0)], x0, y0, + allGeometry, + [Point3d.create(0, dxB, 0), Point3d.create(strokeLength, dxB, 0)], + x0, + y0, ); meshA.reverseIndices(); const dihedralB = PolyfaceQuery.dihedralAngleSummary(meshA); if (dihedralB !== 0) GeometryCoreTestIO.captureCloneGeometry( - allGeometry, [Point3d.create(dxB, 0, 0), Point3d.create(dxB, dihedralB * strokeLength, 0)], x0, y0, + allGeometry, + [Point3d.create(dxB, 0, 0), Point3d.create(dxB, dihedralB * strokeLength, 0)], + x0, + y0, ); else GeometryCoreTestIO.captureCloneGeometry( - allGeometry, [Point3d.create(0, -dxB, 0), Point3d.create(strokeLength, -dxB, 0)], x0, y0, + allGeometry, + [Point3d.create(0, -dxB, 0), Point3d.create(strokeLength, -dxB, 0)], + x0, + y0, ); if (dihedralA === -2) ck.testExactNumber(dihedralA, dihedralB, "both dihedralA and dihedralB should be -2"); @@ -1022,7 +1144,7 @@ describe("ReorientFacets", () => { } if (selector < 2) { ck.testDefined(edges); - } else { // alternate silhouette method, often better results + } else { // alternate silhouette method, often better results const silhouetteEdges = PolyfaceQuery.collectSilhouetteEdges(mesh, viewVector); GeometryCoreTestIO.captureCloneGeometry(allGeometry, silhouetteEdges, x0, y0, 20); } @@ -1054,7 +1176,9 @@ describe("ReorientFacets", () => { const toWorld = Transform.createOriginAndMatrix(undefined, localToWorld); const worldToLocal = localToWorld.transpose(); const toPlane = Transform.createOriginAndMatrix(undefined, worldToLocal); - allEdges.forEach((curve: AnyCurve) => { curve.tryTransformInPlace(toPlane); }); + allEdges.forEach((curve: AnyCurve) => { + curve.tryTransformInPlace(toPlane); + }); const signedLoops = RegionOps.constructAllXYRegionLoops(allEdges); let largestRangeDiagonal = 0; let exteriorLoop: Loop | undefined; @@ -1077,7 +1201,12 @@ describe("ReorientFacets", () => { for (let i = 0; i < surfMesh.pointCount; ++i) { const pt = surfMesh.data.getPoint(i)!; const localPt = toPlane.multiplyPoint3d(pt); - if (!ck.testTrue(-1 < PolygonOps.classifyPointInPolygonXY(localPt.x, localPt.y, offsetPolygon)!, `point (${pt.x},${pt.y}) is in/on the exterior loop`)) + if ( + !ck.testTrue( + -1 < PolygonOps.classifyPointInPolygonXY(localPt.x, localPt.y, offsetPolygon)!, + `point (${pt.x},${pt.y}) is in/on the exterior loop`, + ) + ) GeometryCoreTestIO.captureCloneGeometry(allGeometry, LineSegment3d.create(pt, pt), x0, 30, 0); } } @@ -1093,10 +1222,14 @@ describe("ReorientFacets", () => { }); type LoopOrParityLoops = Point3d[] | Point3d[][]; -function exerciseMultiUnionDiff(ck: Checker, allGeometry: GeometryQuery[], +function exerciseMultiUnionDiff( + ck: Checker, + allGeometry: GeometryQuery[], data: LoopOrParityLoops[], dataB: LoopOrParityLoops[], - x0: number, y0: number) { + x0: number, + y0: number, +) { const rangeA = RegionOps.curveArrayRange(data); const dyA = -1.5 * rangeA.yLength(); for (const g of data) { @@ -1122,7 +1255,6 @@ function exerciseMultiUnionDiff(ck: Checker, allGeometry: GeometryQuery[], const boundaryE = RegionOps.polygonBooleanXYToLoops(data, RegionBinaryOpType.Intersection, dataB); GeometryCoreTestIO.captureCloneGeometry(allGeometry, boundaryE, x0, y0 += yStep); } - } /** * * Restructure mesh data as a polyface. @@ -1135,7 +1267,15 @@ function exerciseMultiUnionDiff(ck: Checker, allGeometry: GeometryQuery[], * @param num2Cluster number of clusters with 2 facets * @param num3Cluster number of clusters with 3 facets */ -function testDuplicateFacetCounts(ck: Checker, title: string, meshData: object, numSingleton: number, numCluster: number, num2Cluster: number, num3Cluster: number) { +function testDuplicateFacetCounts( + ck: Checker, + title: string, + meshData: object, + numSingleton: number, + numCluster: number, + num2Cluster: number, + num3Cluster: number, +) { const mesh = IModelJson.Reader.parse(meshData) as IndexedPolyface | undefined; if (ck.testDefined(mesh, "mesh is valid")) { const dupData0 = PolyfaceQuery.collectDuplicateFacetIndices(mesh, false); @@ -1177,7 +1317,8 @@ describe("Intersections", () => { const opts = new FacetIntersectOptions(); let ints: FacetLocationDetail[]; opts.acceptIntersection = (detail: FacetLocationDetail): boolean => { - ints.push(detail.clone()); return false; + ints.push(detail.clone()); + return false; }; for (const knownPoint of knownPoints) { const ray = Ray3d.create(Point3d.createZero(), knownPoint.vec.normalize()!); @@ -1243,7 +1384,7 @@ describe("Intersections", () => { ck.testTrue(intersects.length <= 2, "expect 1 or 2 intersections of this closed convex mesh, if any"); if (intersects.length === 2) { intersects.sort((d0, d1) => d0.a - d1.a); - loc = intersects[0]; // closer to ray origin + loc = intersects[0]; // closer to ray origin segment = LineSegment3d.create(intersects[0].point, intersects[1].point); } else { segment = LineSegment3d.create(ray.origin, intersects[0].point); @@ -1255,7 +1396,11 @@ describe("Intersections", () => { ck.testBoolean(options.needNormal, undefined !== loc.getNormal(), "normal computed as expected"); ck.testBoolean(options.needParam, undefined !== loc.getParam(), "uv parameter computed as expected"); ck.testBoolean(options.needColor, undefined !== loc.getColor(), "color computed as expected"); - ck.testBoolean(options.needBarycentricCoordinates || options.needNormal || options.needParam || options.needColor, undefined !== loc.getBarycentricCoordinates(), "barycentric coords computed as expected"); + ck.testBoolean( + options.needBarycentricCoordinates || options.needNormal || options.needParam || options.needColor, + undefined !== loc.getBarycentricCoordinates(), + "barycentric coords computed as expected", + ); GeometryCoreTestIO.captureCloneGeometry(allGeometry, segment, x0); } } @@ -1295,7 +1440,12 @@ describe("Intersections", () => { } GeometryCoreTestIO.captureCloneGeometry(allGeometry, mesh0); // fire rays to midpoints of edges - const rays = [Ray3d.createXYZUVW(2, 0, 5, 0, 0, -1), Ray3d.createXYZUVW(4, 2, 5, 0, 0, -1), Ray3d.createXYZUVW(2, 4, 5, 0, 0, -1), Ray3d.createXYZUVW(0, 2, 5, 0, 0, -1)]; + const rays = [ + Ray3d.createXYZUVW(2, 0, 5, 0, 0, -1), + Ray3d.createXYZUVW(4, 2, 5, 0, 0, -1), + Ray3d.createXYZUVW(2, 4, 5, 0, 0, -1), + Ray3d.createXYZUVW(0, 2, 5, 0, 0, -1), + ]; const vertices1: Point3d[] = []; const normals1: Vector3d[] = []; const params1: Point2d[] = []; @@ -1348,7 +1498,11 @@ describe("Intersections", () => { ck.testVector3d(normals1[i], normals0[i].interpolate(0.5, normals0[(i + 1) % normals0.length]), "interpolated normal as expected"); ck.testPoint2d(params1[i], params0[i].interpolate(0.5, params0[(i + 1) % params0.length]), "interpolated uv parameter as expected"); for (let j = 0; j < 4; ++j) - ck.testExactNumber((colors1[i] >>> (j * 8)) & 0xFF, Math.floor(Geometry.interpolate((colors0[i] >>> (j * 8)) & 0xFF, 0.5, (colors0[(i + 1) % normals0.length] >>> (j * 8)) & 0xFF)), "interpolated color as expected"); + ck.testExactNumber( + (colors1[i] >>> (j * 8)) & 0xFF, + Math.floor(Geometry.interpolate((colors0[i] >>> (j * 8)) & 0xFF, 0.5, (colors0[(i + 1) % normals0.length] >>> (j * 8)) & 0xFF)), + "interpolated color as expected", + ); let index = mesh1.addNormal(normals1[i]); mesh1.addNormalIndex(index); index = mesh1.addParam(params1[i]); diff --git a/core/geometry/src/test/polyface/SearchableSetOfRange2d.test.ts b/core/geometry/src/test/polyface/SearchableSetOfRange2d.test.ts index 85e8d1936ac3..cee52224db87 100644 --- a/core/geometry/src/test/polyface/SearchableSetOfRange2d.test.ts +++ b/core/geometry/src/test/polyface/SearchableSetOfRange2d.test.ts @@ -25,29 +25,38 @@ import { Sample } from "../../serialization/GeometrySamples"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -function saveRange(allGeometry: GeometryQuery[], ticFraction: number | undefined, range: Range2d | Range3d, xOrigin: number, yOrigin: number, zOrigin: number = 0) { +function saveRange( + allGeometry: GeometryQuery[], + ticFraction: number | undefined, + range: Range2d | Range3d, + xOrigin: number, + yOrigin: number, + zOrigin: number = 0, +) { const x0 = range.low.x; const y0 = range.low.y; const x1 = range.high.x; const y1 = range.high.y; const points = [ - Point3d.create(x0, y0), Point3d.create(x1, y0), - Point3d.create(x1, y1), Point3d.create(x0, y1), + Point3d.create(x0, y0), + Point3d.create(x1, y0), + Point3d.create(x1, y1), + Point3d.create(x0, y1), Point3d.create(x0, y0), ]; if (ticFraction !== undefined && ticFraction > 0) { const allLines = BagOfCurves.create(); - points.push(points[1]); // 2nd wrap . + points.push(points[1]); // 2nd wrap . for (const i of [1, 2, 3, 4]) { const ticPoints = [ points[i].interpolate(ticFraction, points[i - 1]), points[i], - points[i].interpolate(ticFraction, points[i + 1])]; + points[i].interpolate(ticFraction, points[i + 1]), + ]; allLines.tryAddChild(LineString3d.create(ticPoints)); } GeometryCoreTestIO.captureGeometry(allGeometry, allLines, xOrigin, yOrigin, zOrigin); - } else GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(points), xOrigin, yOrigin, zOrigin); } @@ -90,21 +99,19 @@ describe("LinearSearchRange2dArray", () => { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, testPoint, 0.02, x1, y1); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, testPoint, 0.02, x0, y1); let numHit = 0; - ranges.searchXY(testPoint.x, testPoint.y, - (candidate: Range2d, _tag: number) => { - numHit++; - saveRange(allGeometry, 0.45, candidate, x0, y1); - ck.testTrue(candidate.containsPoint(testPoint)); - return true; - }); + ranges.searchXY(testPoint.x, testPoint.y, (candidate: Range2d, _tag: number) => { + numHit++; + saveRange(allGeometry, 0.45, candidate, x0, y1); + ck.testTrue(candidate.containsPoint(testPoint)); + return true; + }); // search again, but quit after 2nd hit. let numHit1 = 0; - ranges.searchXY(testPoint.x, testPoint.y, - (candidate: Range2d, _tag: number) => { - numHit1++; - saveRange(allGeometry, 0.45, candidate, x1, y1); - return numHit1 < 2; - }); + ranges.searchXY(testPoint.x, testPoint.y, (candidate: Range2d, _tag: number) => { + numHit1++; + saveRange(allGeometry, 0.45, candidate, x1, y1); + return numHit1 < 2; + }); const numHit1A = numHit <= 2 ? numHit : 2; ck.testExactNumber(numHit1A, numHit1, "Quick Exit Count"); @@ -113,33 +120,30 @@ describe("LinearSearchRange2dArray", () => { const testRange = Range2d.createXY(testPoint.x, testPoint.y); testRange.expandInPlace(b); saveRange(allGeometry, undefined, testRange, x2, y1); - ranges.searchRange2d(testRange, - (candidate: Range2d, _tag: number) => { - numHit2++; - saveRange(allGeometry, 0.30, candidate, x2, y1); - ck.testTrue(candidate.intersectsRange(testRange)); - return true; - }); + ranges.searchRange2d(testRange, (candidate: Range2d, _tag: number) => { + numHit2++; + saveRange(allGeometry, 0.30, candidate, x2, y1); + ck.testTrue(candidate.intersectsRange(testRange)); + return true; + }); ck.testLE(numHit, numHit2, "range search count can be larger than point hit"); } // confirm trivial rejects .. - const outsidePoint = totalRange.fractionToPoint(1.3, 0.3); // safely to the right of everything !! + const outsidePoint = totalRange.fractionToPoint(1.3, 0.3); // safely to the right of everything !! let numHitOut = 0; - ranges.searchXY(outsidePoint.x, outsidePoint.y, - (_candidate: Range2d, _tag: number) => { - numHitOut++; - return true; - }); + ranges.searchXY(outsidePoint.x, outsidePoint.y, (_candidate: Range2d, _tag: number) => { + numHitOut++; + return true; + }); ck.testExactNumber(0, numHitOut, "no candidates for outside point"); numHitOut = 0; const outsideRange = Range2d.createXY(outsidePoint.x, outsidePoint.y); outsideRange.expandInPlace(0.01 * totalRange.xLength()); - ranges.searchRange2d(outsideRange, - (_candidate: Range2d, _tag: number) => { - numHitOut++; - return true; - }); + ranges.searchRange2d(outsideRange, (_candidate: Range2d, _tag: number) => { + numHitOut++; + return true; + }); GeometryCoreTestIO.saveGeometry(allGeometry, "LinearSearchRange2dArray", "HelloWorld"); expect(ck.getNumErrors()).toBe(0); @@ -173,7 +177,9 @@ describe("GriddedRaggedRange2dSet", () => { const fraction = i / numRange; const theta = totalTurns * Math.PI * 2 * i; const uvC = Point3d.create( - Geometry.interpolate(-0.01, fraction, 0.99), 0.5 + amplitude * Math.sin(theta)); + Geometry.interpolate(-0.01, fraction, 0.99), + 0.5 + amplitude * Math.sin(theta), + ); const deltaUV = Sample.createRosePoint3d(2.14 * theta * theta, a); deltaUV.x = Geometry.maxXY(0.01, deltaUV.x); deltaUV.y = Geometry.maxXY(0.01, deltaUV.y); @@ -220,45 +226,42 @@ describe("GriddedRaggedRange2dSet", () => { const isInGrid = (rangeArray[i] as any).isInGrid; const targetTag = i; y1 += dy; - saveRange(allGeometry, 0.05, totalRange, x0, y1, -0.0001); // point search in grid only - saveRange(allGeometry, 0.05, totalRange, x1, y1, -0.0001); // point search in two-layer - saveRange(allGeometry, 0.05, totalRange, x2, y1, -0.0001); // range search in two-layer + saveRange(allGeometry, 0.05, totalRange, x0, y1, -0.0001); // point search in grid only + saveRange(allGeometry, 0.05, totalRange, x1, y1, -0.0001); // point search in two-layer + saveRange(allGeometry, 0.05, totalRange, x2, y1, -0.0001); // range search in two-layer GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, testPoint, circleRadius, x0, y1); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, testPoint, circleRadius, x1, y1); let numHit = 0; let numHitAllRanges = 0; let primaryRangeHits = 0; let primaryAllRangeHits = 0; - rangesInGrid.searchXY(testPoint.x, testPoint.y, - (candidate: Range2d, tag: number) => { - numHit++; - saveRange(allGeometry, 0.45, candidate, x0, y1); - ck.testTrue(candidate.containsPoint(testPoint)); - if (tag === targetTag) - primaryRangeHits++; - return true; - }); - allRanges.searchXY(testPoint.x, testPoint.y, - (candidate: Range2d, tag: number) => { - numHitAllRanges++; - saveRange(allGeometry, 0.45, candidate, x1, y1); - ck.testTrue(candidate.containsPoint(testPoint)); - if (tag === targetTag) - primaryAllRangeHits++; - return true; - }); + rangesInGrid.searchXY(testPoint.x, testPoint.y, (candidate: Range2d, tag: number) => { + numHit++; + saveRange(allGeometry, 0.45, candidate, x0, y1); + ck.testTrue(candidate.containsPoint(testPoint)); + if (tag === targetTag) + primaryRangeHits++; + return true; + }); + allRanges.searchXY(testPoint.x, testPoint.y, (candidate: Range2d, tag: number) => { + numHitAllRanges++; + saveRange(allGeometry, 0.45, candidate, x1, y1); + ck.testTrue(candidate.containsPoint(testPoint)); + if (tag === targetTag) + primaryAllRangeHits++; + return true; + }); ck.testExactNumber(isInGrid ? 1 : 0, primaryRangeHits, "primary range hits", i); ck.testExactNumber(1, primaryAllRangeHits, "gridded primary range hits", i); ck.testLE(1, numHitAllRanges, "allRange hits", i); // search again, but quit after 2nd hit. let numHit1 = 0; - rangesInGrid.searchXY(testPoint.x, testPoint.y, - (candidate: Range2d, _tag: number) => { - numHit1++; - saveRange(allGeometry, 0.45, candidate, x1, y1); - return numHit1 < 2; - }); + rangesInGrid.searchXY(testPoint.x, testPoint.y, (candidate: Range2d, _tag: number) => { + numHit1++; + saveRange(allGeometry, 0.45, candidate, x1, y1); + return numHit1 < 2; + }); const numHit1A = numHit <= 2 ? numHit : 2; ck.testExactNumber(numHit1A, numHit1, "Quick Exit Count"); @@ -267,32 +270,29 @@ describe("GriddedRaggedRange2dSet", () => { const testRange = Range2d.createXY(testPoint.x, testPoint.y); testRange.expandInPlace(b); saveRange(allGeometry, undefined, testRange, x2, y1); - allRanges.searchRange2d(testRange, - (candidate: Range2d, _tag: number) => { - numHit2++; - saveRange(allGeometry, 0.30, candidate, x2, y1); - ck.testTrue(candidate.intersectsRange(testRange)); - return true; - }); + allRanges.searchRange2d(testRange, (candidate: Range2d, _tag: number) => { + numHit2++; + saveRange(allGeometry, 0.30, candidate, x2, y1); + ck.testTrue(candidate.intersectsRange(testRange)); + return true; + }); ck.testLE(numHit, numHit2, "range search count can be larger than point hit"); } // confirm trivial rejects .. - const outsidePoint = totalRange.fractionToPoint(1.3, 0.3); // safely to the right of everything !! + const outsidePoint = totalRange.fractionToPoint(1.3, 0.3); // safely to the right of everything !! let numHitOut = 0; - rangesInGrid.searchXY(outsidePoint.x, outsidePoint.y, - (_candidate: Range2d, _tag: number) => { - numHitOut++; - return true; - }); + rangesInGrid.searchXY(outsidePoint.x, outsidePoint.y, (_candidate: Range2d, _tag: number) => { + numHitOut++; + return true; + }); ck.testExactNumber(0, numHitOut, "no candidates for outside point"); numHitOut = 0; const outsideRange = Range2d.createXY(outsidePoint.x, outsidePoint.y); outsideRange.expandInPlace(0.01 * totalRange.xLength()); - rangesInGrid.searchRange2d(outsideRange, - (_candidate: Range2d, _tag: number) => { - numHitOut++; - return true; - }); + rangesInGrid.searchRange2d(outsideRange, (_candidate: Range2d, _tag: number) => { + numHitOut++; + return true; + }); x0 += 40 * totalRange.xLength(); const xLine = -2 * boxHalfSize; GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYXY(xLine, 0, xLine, y1), x0, y0); @@ -330,7 +330,8 @@ describe("GriddedRaggedRange2dSet", () => { Point3d.create(0, 0, 0), Point3d.create(1, 0, -2), Point3d.create(0, 1, 1), - Point3d.create(1, 1, 3)); + Point3d.create(1, 1, 3), + ); for (const p of points) { const uv = fullRange.worldToLocal(Point2d.create(p.x, p.y))!; p.z = patch.uvFractionToPoint(uv.x, uv.y).z; @@ -414,7 +415,6 @@ describe("GriddedRaggedRange2dSet", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "GriddedRaggedRange2dSet", "FacetGrid"); expect(ck.getNumErrors()).toBe(0); }); - }); function createSinSamplePoints(range: Range2d, numPoint: number, totalTurns: number): Point3d[] { const points = []; diff --git a/core/geometry/src/test/polyface/SortableEdgeCluster.test.ts b/core/geometry/src/test/polyface/SortableEdgeCluster.test.ts index bd79ba54508d..f9c995dc495b 100644 --- a/core/geometry/src/test/polyface/SortableEdgeCluster.test.ts +++ b/core/geometry/src/test/polyface/SortableEdgeCluster.test.ts @@ -34,12 +34,12 @@ describe("SortableEdgeCluster", () => { edgeArray.addPath([1, 6, 7, 2], 1); ck.testExactNumber(1, edgeArray.edges[4].facetIndex, "confirm facet index"); const n1 = edgeArray.edges.length; - edgeArray.addPath([], 20); // force null return. + edgeArray.addPath([], 20); // force null return. ck.testExactNumber(n1, edgeArray.edges.length, "confirm no edges added with empty input"); edgeArray.addPath([5, 6, 1, 0], 2); - edgeArray.addPath([6, 9, 8, 5], 3); // Clockwise == creates error case 5>>>6 !!! + edgeArray.addPath([6, 9, 8, 5], 3); // Clockwise == creates error case 5>>>6 !!! edgeArray.addPath([8, 9], 4); - edgeArray.addPath([2, 7, 10, 10, 2], 5, false); // null edge, with explicit closure + edgeArray.addPath([2, 7, 10, 10, 2], 5, false); // null edge, with explicit closure const manifold: SortableEdgeCluster[] = []; const boundary: SortableEdgeCluster[] = []; @@ -74,12 +74,10 @@ describe("SortableEdgeCluster", () => { const edgeArray = new IndexedEdgeMatcher(); // wander around and catch both sides of all the edges in one path !! edgeArray.addPath( - [5, 3, - 5, 7, 1, 3, - 1, 0, 2, 3, - 2, 4, 2, - 0, 6, 0, 1, 7, - 6, 4, 6, 7, 5, 4, 5], 0, false); + [5, 3, 5, 7, 1, 3, 1, 0, 2, 3, 2, 4, 2, 0, 6, 0, 1, 7, 6, 4, 6, 7, 5, 4, 5], + 0, + false, + ); const manifold: SortableEdgeCluster[] = []; const boundary: SortableEdgeCluster[] = []; const compound: SortableEdgeCluster[] = []; diff --git a/core/geometry/src/test/polyface/XYPointBuckets.test.ts b/core/geometry/src/test/polyface/XYPointBuckets.test.ts index b24d654257b7..5cf22398ee5a 100644 --- a/core/geometry/src/test/polyface/XYPointBuckets.test.ts +++ b/core/geometry/src/test/polyface/XYPointBuckets.test.ts @@ -14,7 +14,6 @@ import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; describe("XYPointBuckets", () => { - it("HelloWorld", () => { const ck = new Checker(); ck.testUndefined(XYIndexGrid.createWithEstimatedCounts(Range2d.createNull(), 100, 10), "expect null grid"); @@ -30,15 +29,14 @@ describe("XYPointBuckets", () => { const dy = 3.0; // must be integer to be good point count! const range = Range2d.createXYXY(x0Test, y0Test, x0Test + dx, y0Test + dy); let numHit = 0; - searcher.announcePointsInRange(range, - (i: number, x: number, y: number, z: number) => { - ck.testExactNumber(x, points.getXAtUncheckedPointIndex(i)); - ck.testExactNumber(y, points.getYAtUncheckedPointIndex(i)); - ck.testExactNumber(z, points.getZAtUncheckedPointIndex(i)); - ck.testTrue(range.containsXY(x, y)); - numHit++; - return true; - }); + searcher.announcePointsInRange(range, (i: number, x: number, y: number, z: number) => { + ck.testExactNumber(x, points.getXAtUncheckedPointIndex(i)); + ck.testExactNumber(y, points.getYAtUncheckedPointIndex(i)); + ck.testExactNumber(z, points.getZAtUncheckedPointIndex(i)); + ck.testTrue(range.containsXY(x, y)); + numHit++; + return true; + }); ck.testExactNumber(dx * dy, numHit, "hits in box in grid"); const numXEdge = searcher.indexGrid.numXEdge; const numYEdge = searcher.indexGrid.numYEdge; @@ -80,8 +78,16 @@ describe("XYPointBuckets", () => { if (numY > 8) { const num0 = points.length; for (let i = 0; i < num0; i++) { - const extraPoints = Sample.createStar(points.getXAtUncheckedPointIndex(i), points.getYAtUncheckedPointIndex(i), points.getZAtUncheckedPointIndex(i), - 0.4, undefined, 3 + (i % 3), false, Angle.createDegrees(5 * i)); + const extraPoints = Sample.createStar( + points.getXAtUncheckedPointIndex(i), + points.getYAtUncheckedPointIndex(i), + points.getZAtUncheckedPointIndex(i), + 0.4, + undefined, + 3 + (i % 3), + false, + Angle.createDegrees(5 * i), + ); for (const p of extraPoints) points.push(p); } @@ -94,17 +100,15 @@ describe("XYPointBuckets", () => { const range = Range2d.createXYXY(x0Test, y0Test, x0Test + dx, y0Test + dy); GeometryCoreTestIO.captureRangeEdges(allGeometry, range, x0, y0); GeometryCoreTestIO.createAndCaptureXYMarker(allGeometry, -3, points.getPoint3dArray(), 0.05, x0, y0); - searcher.announcePointsInRange(range, - (_i: number, x: number, y: number, z: number) => { - ck.testTrue(range.containsXY(x, y)); - GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, Point3d.create(x, y, z), 0.1, x0, y0); - return true; - }); + searcher.announcePointsInRange(range, (_i: number, x: number, y: number, z: number) => { + ck.testTrue(range.containsXY(x, y)); + GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, Point3d.create(x, y, z), 0.1, x0, y0); + return true; + }); x0 += numX + 5.0; } GeometryCoreTestIO.saveGeometry(allGeometry, "XYPointBuckets", "MessyGrid"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/polyface/sample.test.ts b/core/geometry/src/test/polyface/sample.test.ts index 08ebd08ac446..c8ad44e7ff8d 100644 --- a/core/geometry/src/test/polyface/sample.test.ts +++ b/core/geometry/src/test/polyface/sample.test.ts @@ -5,20 +5,20 @@ import { describe, it } from "vitest"; // import { Checker } from "../Checker"; -import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; +import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; +import { Arc3d } from "../../curve/Arc3d"; +import { GeometryQuery } from "../../curve/GeometryQuery"; import { Loop } from "../../curve/Loop"; -import { LinearSweep } from "../../solid/LinearSweep"; import { ParityRegion } from "../../curve/ParityRegion"; -import { Arc3d } from "../../curve/Arc3d"; +import { StrokeOptions } from "../../curve/StrokeOptions"; +import { Angle } from "../../geometry3d/Angle"; import { AngleSweep } from "../../geometry3d/AngleSweep"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { GeometryQuery } from "../../curve/GeometryQuery"; +import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; -import { ConvexClipPlaneSet } from "../../clipping/ConvexClipPlaneSet"; -import { PolyfaceQuery } from "../../polyface/PolyfaceQuery"; import { ClippedPolyfaceBuilders, PolyfaceClip } from "../../polyface/PolyfaceClip"; -import { Angle } from "../../geometry3d/Angle"; -import { StrokeOptions } from "../../curve/StrokeOptions"; +import { PolyfaceQuery } from "../../polyface/PolyfaceQuery"; +import { LinearSweep } from "../../solid/LinearSweep"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; describe("MeshConstruction", () => { /** * Example of constructing a plate with holes. @@ -35,8 +35,7 @@ describe("MeshConstruction", () => { const plateBaseWithHoles = ParityRegion.create(plateBaseLoop); const numCircle = 3; for (let i = 0; i < numCircle; i++) { - const arc = Arc3d.createXY(Point3d.create(-0.5 * (i) * a / (numCircle + 1), b / 2), r, - AngleSweep.createStartEndDegrees(180, -180)); + const arc = Arc3d.createXY(Point3d.create(-0.5 * i * a / (numCircle + 1), b / 2), r, AngleSweep.createStartEndDegrees(180, -180)); plateBaseWithHoles.tryAddChild(Loop.create(arc)); } const plateSolidWithHoles = LinearSweep.create(plateBaseWithHoles, Vector3d.create(0, 0, c), true)!; @@ -52,7 +51,8 @@ describe("MeshConstruction", () => { const mesh0 = builder0.claimPolyface(); GeometryCoreTestIO.captureCloneGeometry(geometryToSave, mesh0, x0, y0 += yStep); - x0 += xStep; y0 = 0; + x0 += xStep; + y0 = 0; const plateBlankSolid = LinearSweep.createZSweep(plateBasePoints, 0, c, true)!; const builder = PolyfaceBuilder.create(); builder.addLinearSweep(plateBlankSolid); diff --git a/core/geometry/src/test/serialization/BSIJSON.test.ts b/core/geometry/src/test/serialization/BSIJSON.test.ts index 58f61b0c7dd7..523c92392cc6 100644 --- a/core/geometry/src/test/serialization/BSIJSON.test.ts +++ b/core/geometry/src/test/serialization/BSIJSON.test.ts @@ -49,7 +49,7 @@ Checker.noisy.printJSONFailure = true; /** Compares the constructor references of objects */ function isDifferentTypeName(obj: object, noisy: boolean = false): boolean { - if (!obj.constructor) // Unsure of case in which this would equate to false + if (!obj.constructor) // Unsure of case in which this would equate to false return true; if (obj.constructor) { if (obj.constructor !== previousConstructor) { @@ -75,7 +75,6 @@ function exerciseGo(obj: any, noisy: boolean): number { GeometryCoreTestIO.consoleLog("BSIJSONValues", (obj as BeJSONFunctions).toJSON()); } if (obj instanceof GeometryQuery) { - const clone = obj.clone(); if (!(clone !== undefined && clone instanceof GeometryQuery && clone.isSameGeometryClass(obj))) { errors++; @@ -119,8 +118,10 @@ function exerciseGo(obj: any, noisy: boolean): number { if (!obj.clone) bsiJsonPunchList.push({ noCloneMethod: obj }); - if (!obj.isAlmostEqual - && !(obj.isAlmostEqualRadiansAllowPeriodShift || obj.isAlmostEqualNoPeriodShift)) + if ( + !obj.isAlmostEqual + && !(obj.isAlmostEqualRadiansAllowPeriodShift || obj.isAlmostEqualNoPeriodShift) + ) bsiJsonPunchList.push({ noAlmostEqualMethod: obj }); if (isDifferentTypeName(obj) && Checker.noisy.bsiJSONFirstAppearance) @@ -399,31 +400,37 @@ describe("BSIJSON.ExerciseAllTypes", () => { { const data = Sample.createSimplePaths(true); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } { const data = Sample.createSimpleLoops(); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } { const data = Sample.createSimpleParityRegions(); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } { const data = Sample.createSimpleUnions(); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } { const data = Sample.createBsplineCurves(true); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } { const data = Sample.createSimplePointStrings(); - let d; for (d of data) { exercise(d, false); } + let d; + for (d of data) { exercise(d, false); } } // exercise(CurveChain.createZero()); // exercise(Path.createZero()); @@ -460,15 +467,25 @@ describe("BSIJSONValuesQuick", () => { exerciseBSIJSONValuesQuick("Vector3d", Vector3d.create(1, 2, 3)); exerciseBSIJSONValuesQuick("Angle", Angle.createDegrees(90)); exerciseBSIJSONValuesQuick("AngleSweep", AngleSweep.createStartEndDegrees(45, 90)); - exerciseBSIJSONValuesQuick("Plane3dByOriginAndUnitNormal", Plane3dByOriginAndUnitNormal.create(Point3d.create(1, 2, 3), Vector3d.create(6, 2, 1))); + exerciseBSIJSONValuesQuick( + "Plane3dByOriginAndUnitNormal", + Plane3dByOriginAndUnitNormal.create(Point3d.create(1, 2, 3), Vector3d.create(6, 2, 1)), + ); exerciseBSIJSONValuesQuick("Ray3d", Ray3d.createXYZUVW(1, 2, 3, 10, 5, 9)); - exerciseBSIJSONValuesQuick("Plane3dByOriginAndVectors", Plane3dByOriginAndVectors.createOriginAndVectors - (Point3d.create(1, 2, 3), Vector3d.create(5, 6, 3), Vector3d.create(-6, 5, 1))); + exerciseBSIJSONValuesQuick( + "Plane3dByOriginAndVectors", + Plane3dByOriginAndVectors.createOriginAndVectors(Point3d.create(1, 2, 3), Vector3d.create(5, 6, 3), Vector3d.create(-6, 5, 1)), + ); exerciseBSIJSONValuesQuick("YawPitchRollAngles", YawPitchRollAngles.createDegrees(10, 20, 30)); exerciseBSIJSONValuesQuick("Range3d", Range3d.createXYZXYZ(1, 2, 3, 10, 11, 20)); exerciseBSIJSONValuesQuick("Matrix3d", Matrix3d.createRowValues(1, 2, 3, 4, 5, 6, 7, 8, 9)); - exerciseBSIJSONValuesQuick("Transform", Transform.createOriginAndMatrix( - Point3d.create(10, 20, 30), Matrix3d.createRowValues(1, 2, 3, 4, 5, 6, 7, 8, 9))); + exerciseBSIJSONValuesQuick( + "Transform", + Transform.createOriginAndMatrix( + Point3d.create(10, 20, 30), + Matrix3d.createRowValues(1, 2, 3, 4, 5, 6, 7, 8, 9), + ), + ); exerciseBSIJSONValuesQuick("Matrix4d", Matrix4d.createRowValues(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)); exerciseBSIJSONValuesQuick("Complex", Complex.create(1, 2)); @@ -478,7 +495,9 @@ describe("BSIJSONValuesQuick", () => { }); class TempHandler extends NullGeometryHandler { - public handleLineSegment(_g: LineSegment3d): any { return true; } + public handleLineSegment(_g: LineSegment3d): any { + return true; + } } describe("ExerciseGeometryHandler", () => { @@ -499,8 +518,13 @@ describe("ExerciseGeometryHandler", () => { ck.testUndefined(tempHandler.handleBSplineSurface3dH(Sample.createWeightedXYGridBsplineSurface(4, 3, 3, 2, 1.0, 1.1, 0.9, 1.0)!)); ck.testUndefined(tempHandler.handleIndexedPolyface(IndexedPolyface.create())); ck.testUndefined(tempHandler.handleTransitionSpiral( - IntegratedSpiral3d.createRadiusRadiusBearingBearing(Segment1d.create(0, 1), AngleSweep.create360(), Segment1d.create(0, 1), - Transform.createIdentity())!)); + IntegratedSpiral3d.createRadiusRadiusBearingBearing( + Segment1d.create(0, 1), + AngleSweep.create360(), + Segment1d.create(0, 1), + Transform.createIdentity(), + )!, + )); ck.testUndefined(tempHandler.handleSphere(Sample.createSpheres()[0])); ck.testUndefined(tempHandler.handleCone(Sample.createCones()[0])); ck.testUndefined(tempHandler.handleBox(Sample.createBoxes()[0])); @@ -514,6 +538,5 @@ describe("ExerciseGeometryHandler", () => { ck.testUndefined(tempHandler.handleParityRegion(ParityRegion.create())); ck.testUndefined(tempHandler.handleUnionRegion(UnionRegion.create())); ck.testUndefined(tempHandler.handleBagOfCurves(BagOfCurves.create())); - }); }); diff --git a/core/geometry/src/test/serialization/FlatBuffer.test.ts b/core/geometry/src/test/serialization/FlatBuffer.test.ts index f73cf4530756..6102042ac9e4 100644 --- a/core/geometry/src/test/serialization/FlatBuffer.test.ts +++ b/core/geometry/src/test/serialization/FlatBuffer.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect, it } from "vitest"; import { flatbuffers } from "flatbuffers"; +import { expect, it } from "vitest"; import { AkimaCurve3d } from "../../bspline/AkimaCurve3d"; import { Arc3d } from "../../curve/Arc3d"; import { CurvePrimitive } from "../../curve/CurvePrimitive"; @@ -50,8 +50,12 @@ it("HelloWorld", () => { if (Checker.noisy.flatBuffer) GeometryCoreTestIO.consoleLog({ lineOffset: oLineA, - x0: oSegmentA?.point0X(), y0: oSegmentA?.point0Y(), z0: oSegmentA?.point0Z(), - x1: oSegmentA?.point1X(), y1: oSegmentA?.point1Y(), z1: oSegmentA?.point1Z(), + x0: oSegmentA?.point0X(), + y0: oSegmentA?.point0Y(), + z0: oSegmentA?.point0Z(), + x1: oSegmentA?.point1X(), + y1: oSegmentA?.point1Y(), + z1: oSegmentA?.point1Z(), }); ck.testExactNumber(1, oSegmentA!.point0X()); @@ -80,9 +84,7 @@ it("HelloVariantGeometry", () => { it("HelloCurveVector", () => { const ck = new Checker(); - const cvs = [Sample.createCappedArcPath(3.0, 10, 90), - ...Sample.createSimpleLoops(), - ...Sample.createSimpleParityRegions(false)]; + const cvs = [Sample.createCappedArcPath(3.0, 10, 90), ...Sample.createSimpleLoops(), ...Sample.createSimpleParityRegions(false)]; for (const cv of cvs) { testGeometryQueryRoundTrip(ck, cv); } @@ -114,8 +116,7 @@ it("HelloMesh", () => { it("HelloSubdivisionSurface", () => { const ck = new Checker(); - const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), - Vector3d.unitX(), Vector3d.unitY(), 3, 3); + const mesh = Sample.createTriangularUnitGridPolyface(Point3d.create(0, 0, 0), Vector3d.unitX(), Vector3d.unitY(), 3, 3); mesh.data.taggedNumericData = new TaggedNumericData(-1000, 0); testGeometryQueryRoundTrip(ck, mesh); const tg1 = new TaggedNumericData(-1000, 1); @@ -136,7 +137,8 @@ it("HelloSpirals", () => { AngleSweep.createStartEndDegrees(0, 5), Segment1d.create(0, 1), Transform.createOriginAndMatrix(Point3d.create(1, 2, 3), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(-10))), - "bloss"); + "bloss", + ); testGeometryQueryRoundTrip(ck, clothoid); expect(ck.getNumErrors()).toBe(0); }); @@ -144,7 +146,9 @@ it("HelloSpirals", () => { function compareFlatBuffers(a1: Uint8Array, a2: Uint8Array): boolean { if (a1.length !== a2.length) return false; - return a1.every((entry, i) => { return entry === a2[i]; }); + return a1.every((entry, i) => { + return entry === a2[i]; + }); } /** @@ -181,7 +185,10 @@ function testGeometryQueryRoundTripGo(ck: Checker, g: GeometryQuery | GeometryQu if (ck.testType(justTheBytes, Uint8Array, "to FB with signature") && justTheBytes && bytesWithSignature) { if (ck.testExactNumber(justTheBytes.length + 8, bytesWithSignature.length, "Signature adds 8 bytes")) { const g2 = BentleyGeometryFlatBuffer.bytesToGeometry(bytesWithSignature, true); - if (ck.testTrue(g2 instanceof GeometryQuery && g.isAlmostEqual(g2), "GeometryQuery round-tripped through FB with signature") && g2 instanceof GeometryQuery) { + if ( + ck.testTrue(g2 instanceof GeometryQuery && g.isAlmostEqual(g2), "GeometryQuery round-tripped through FB with signature") && + g2 instanceof GeometryQuery + ) { ck.testUndefined(BentleyGeometryFlatBuffer.bytesToGeometry(justTheBytes, true), "signature state mismatch A"); ck.testUndefined(BentleyGeometryFlatBuffer.bytesToGeometry(bytesWithSignature, false), "signature state mismatch B"); const bytesWithSignature2 = BentleyGeometryFlatBuffer.geometryToBytes(g2, true); @@ -231,8 +238,10 @@ export function testGeometryQueryRoundTrip(ck: Checker, g: GeometryQuery | Geome it("HelloSolidPrimitive", () => { const ck = new Checker(); const solids = Sample.createClosedSolidSampler(true); - const transform = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(4, 3, -1), Angle.createDegrees(17))!); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(4, 3, -1), Angle.createDegrees(17))!, + ); for (const s of solids) { testGeometryQueryRoundTrip(ck, s); s.tryTransformInPlace(transform); @@ -243,10 +252,11 @@ it("HelloSolidPrimitive", () => { it("HelloBSplineSurface", () => { const ck = new Checker(); - const surfaces = [Sample.createXYGridBsplineSurface(6, 5, 4, 2)!, - Sample.createWeightedXYGridBsplineSurface(7, 6, 5, 4, 1.1, 1.2, 1.3, 1.4)!]; - const _transform = Transform.createFixedPointAndMatrix(Point3d.create(1, 2, 3), - Matrix3d.createRotationAroundVector(Vector3d.create(4, 3, -1), Angle.createDegrees(17))!); + const surfaces = [Sample.createXYGridBsplineSurface(6, 5, 4, 2)!, Sample.createWeightedXYGridBsplineSurface(7, 6, 5, 4, 1.1, 1.2, 1.3, 1.4)!]; + const _transform = Transform.createFixedPointAndMatrix( + Point3d.create(1, 2, 3), + Matrix3d.createRotationAroundVector(Vector3d.create(4, 3, -1), Angle.createDegrees(17))!, + ); for (const s of surfaces) { testGeometryQueryRoundTrip(ck, s); // s.tryTransformInPlace(transform); @@ -255,41 +265,1480 @@ it("HelloBSplineSurface", () => { expect(ck.getNumErrors()).toBe(0); }); const arcBytes = new Uint8Array([ - 98, 103, 48, 48, 48, 49, 102, 98, 8, 0, 0, 0, 0, 0, 0, 0, 234, 254, 255, 255, 0, 0, 0, 15, 12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 1, - 0, 0, 124, 0, 0, 0, 16, 0, 0, 0, 0, 0, 10, 0, 12, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 2, 4, 0, 0, 0, 22, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 52, 51, 51, 51, 51, 51, 211, 63, 0, 0, 0, 0, 0, 0, 0, 0, 10, 215, 163, 112, 61, 10, 183, 191, 204, 204, 204, - 204, 204, 204, 236, 63, 0, 0, 0, 0, 0, 0, 0, 0, 135, 68, 231, 74, 24, 87, 230, 191, 99, 10, 144, 136, 95, 164, 21, 64, 138, 255, 255, 255, 0, 0, 0, 2, 12, 0, - 0, 0, 0, 0, 6, 0, 98, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 135, 68, 231, 74, 24, 87, 230, 191, 99, 10, 144, 136, 95, 164, 21, 64, 0, 0, 0, 0, 0, - 0, 10, 0, 14, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 2, 12, 0, 0, 0, 0, 0, 6, 0, 92, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 45, 68, 84, 251, 33, 249, 63]); + 98, + 103, + 48, + 48, + 48, + 49, + 102, + 98, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 234, + 254, + 255, + 255, + 0, + 0, + 0, + 15, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 8, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 124, + 0, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 12, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 4, + 0, + 0, + 0, + 22, + 255, + 255, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 52, + 51, + 51, + 51, + 51, + 51, + 211, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 215, + 163, + 112, + 61, + 10, + 183, + 191, + 204, + 204, + 204, + 204, + 204, + 204, + 236, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 135, + 68, + 231, + 74, + 24, + 87, + 230, + 191, + 99, + 10, + 144, + 136, + 95, + 164, + 21, + 64, + 138, + 255, + 255, + 255, + 0, + 0, + 0, + 2, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 98, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 135, + 68, + 231, + 74, + 24, + 87, + 230, + 191, + 99, + 10, + 144, + 136, + 95, + 164, + 21, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 14, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 92, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, + 45, + 68, + 84, + 251, + 33, + 249, + 63, +]); const singleArcBytes = new Uint8Array([ - 98, 103, 48, 48, 48, 49, 102, 98, 8, 0, 0, 0, 0, 0, 0, 0, 218, 255, 255, 255, 0, 0, 0, 15, 12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 16, - 0, 0, 0, 0, 0, 10, 0, 14, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 2, 12, 0, 0, 0, 0, 0, 6, 0, 92, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 45, 68, 84, 251, 33, 249, 63]); + 98, + 103, + 48, + 48, + 48, + 49, + 102, + 98, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 218, + 255, + 255, + 255, + 0, + 0, + 0, + 15, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 8, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 14, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 92, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, + 45, + 68, + 84, + 251, + 33, + 249, + 63, +]); // lineSegment.fbjs const singleSegmentBytes = new Uint8Array([ - 98, 103, 48, 48, 48, 49, 102, 98, 8, 0, 0, 0, 0, 0, 0, 0, 138, 255, 255, 255, 0, 0, 0, 15, 12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 96, - 0, 0, 0, 4, 0, 0, 0, 178, 255, 255, 255, 0, 0, 0, 1, 12, 0, 0, 0, 0, 0, 6, 0, 58, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 14, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 1, 12, 0, 0, 0, 0, 0, 6, 0, - 52, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + 98, + 103, + 48, + 48, + 48, + 49, + 102, + 98, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 138, + 255, + 255, + 255, + 0, + 0, + 0, + 15, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 8, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 96, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 178, + 255, + 255, + 255, + 0, + 0, + 0, + 1, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 58, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 14, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 52, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +]); const sphereBytes = new Uint8Array( [ - 98, 103, 48, 48, 48, 49, 102, 98, 8, 0, 0, 0, 0, 0, 0, 0, 26, 254, 255, 255, 0, 0, 0, 15, 12, 0, 0, 0, 0, 0, 6, 0, 8, 0, 4, 0, 6, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 208, - 1, 0, 0, 44, 1, 0, 0, 160, 0, 0, 0, 4, 0, 0, 0, 114, 255, 255, 255, 0, 0, 0, 7, 4, 0, 0, 0, 222, 254, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 16, 64, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 24, 45, 68, 84, 251, 33, 233, 191, 24, 45, 68, 84, 251, 33, 249, 63, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 10, 0, 12, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 7, 4, 0, 0, 0, 214, 254, 255, 255, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 8, 64, 24, 45, 68, 84, 251, 33, 233, 191, 138, 173, 132, 250, 10, 116, 1, 64, 1, 0, 0, 0, 0, 0, 0, 0, 106, 255, 255, 255, 0, - 0, 0, 7, 12, 0, 0, 0, 0, 0, 6, 0, 130, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 0, 0, 0, 0, 0, 0, 8, - 64, 24, 45, 68, 84, 251, 33, 249, 191, 24, 45, 68, 84, 251, 33, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 14, 0, 7, 0, 8, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, - 7, 12, 0, 0, 0, 0, 0, 6, 0, 124, 0, 4, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 63, 0, 0, 0, 0, 0, 0, 0, 0, - 24, 45, 68, 84, 251, 33, 249, 191, 24, 45, 68, 84, 251, 33, 9, 64, 0, 0, 0, 0, 0, 0, 0, 0]); + 98, + 103, + 48, + 48, + 48, + 49, + 102, + 98, + 8, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 26, + 254, + 255, + 255, + 0, + 0, + 0, + 15, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 8, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 208, + 1, + 0, + 0, + 44, + 1, + 0, + 0, + 160, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 114, + 255, + 255, + 255, + 0, + 0, + 0, + 7, + 4, + 0, + 0, + 0, + 222, + 254, + 255, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 16, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 16, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 16, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 24, + 45, + 68, + 84, + 251, + 33, + 233, + 191, + 24, + 45, + 68, + 84, + 251, + 33, + 249, + 63, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 12, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 7, + 4, + 0, + 0, + 0, + 214, + 254, + 255, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 24, + 45, + 68, + 84, + 251, + 33, + 233, + 191, + 138, + 173, + 132, + 250, + 10, + 116, + 1, + 64, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 106, + 255, + 255, + 255, + 0, + 0, + 0, + 7, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 130, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 8, + 64, + 24, + 45, + 68, + 84, + 251, + 33, + 249, + 191, + 24, + 45, + 68, + 84, + 251, + 33, + 9, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 10, + 0, + 14, + 0, + 7, + 0, + 8, + 0, + 0, + 0, + 10, + 0, + 0, + 0, + 0, + 0, + 0, + 7, + 12, + 0, + 0, + 0, + 0, + 0, + 6, + 0, + 124, + 0, + 4, + 0, + 6, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 240, + 63, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, + 45, + 68, + 84, + 251, + 33, + 249, + 191, + 24, + 45, + 68, + 84, + 251, + 33, + 9, + 64, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], +); it("HelloNativeBytes", () => { const ck = new Checker(); for (const nativeBytes of [sphereBytes, singleSegmentBytes, singleArcBytes, arcBytes]) { @@ -315,7 +1764,6 @@ it("HelloNativeBytes", () => { } } } - } } expect(ck.getNumErrors()).toBe(0); @@ -332,7 +1780,7 @@ function geometryTypes(g: GeometryQuery | GeometryQuery[] | undefined): any { } else if (g instanceof SolidPrimitive) { return g.solidPrimitiveType; } else { - return typeof (g); + return typeof g; } } function isGeometry(g: GeometryQuery | GeometryQuery[] | undefined): boolean { @@ -343,9 +1791,15 @@ it("PolyfaceAuxData", () => { const polyfaces = Sample.createSimpleIndexedPolyfaces(1.0); for (let i = 0; i < 1; i++) { const p = polyfaces[i]; - Sample.addAuxDataScalarChannel(p.data, 2, - "distance", "time", - 5, 2, 3, AuxChannelDataType.Distance, + Sample.addAuxDataScalarChannel( + p.data, + 2, + "distance", + "time", + 5, + 2, + 3, + AuxChannelDataType.Distance, (t: number, xyz: Point3d) => (t * xyz.x + t * (t - 1) * xyz.y), ); testGeometryQueryRoundTrip(ck, p); diff --git a/core/geometry/src/test/serialization/IModelJson.test.ts b/core/geometry/src/test/serialization/IModelJson.test.ts index db6567f46c1a..a4ff8cbf395d 100644 --- a/core/geometry/src/test/serialization/IModelJson.test.ts +++ b/core/geometry/src/test/serialization/IModelJson.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BSplineCurve3dBase } from "../../bspline/BSplineCurve"; import { Arc3d } from "../../curve/Arc3d"; import { CoordinateXYZ } from "../../curve/CoordinateXYZ"; @@ -114,7 +114,6 @@ function exerciseIModelJSon(ck: Checker, g: any, doParse: boolean = false, noisy } return; } - } function exerciseIModelJSonArray(ck: Checker, g: any[], doParse: boolean = false, noisy: boolean = false) { @@ -180,7 +179,6 @@ describe("CreateIModelJsonSamples", () => { // GeometryCoreTestIO.consoleLog(allIModelJsonSamples); expect(ck.getNumErrors()).toBe(0); - }); // exercise the secondary ArcBy3Points property, with various point formats . .. it("ArcByStartMiddleEnd", () => { @@ -214,7 +212,7 @@ describe("CreateIModelJsonSamples", () => { mesh.data.pointIndex.push(0, 1, 2); mesh.data.edgeVisible.push(true, true, true); mesh.addNormalXYZ(0, 0, 1); - mesh.addNormal(Vector3d.create(0, 0, 1)); // in bug state, this reuses the first normal + mesh.addNormal(Vector3d.create(0, 0, 1)); // in bug state, this reuses the first normal mesh.addNormalXYZ(0, 0, 1); mesh.addNormalIndex(0); mesh.addNormalIndex(1); @@ -235,11 +233,12 @@ describe("CreateIModelJsonSamples", () => { const ck = new Checker(); const compareObj = new DeepCompare(); const skipList = ["xyVectors", "readme", "README"]; - const expectedJsonMismatchList = ["indexedMesh.numPerFace.", // the mesh flips to zero-terminated - "cone.imjs", // cone can change to cylinder - "box.minimal.imjs", // minimal box gets remaining fields populated + const expectedJsonMismatchList = [ + "indexedMesh.numPerFace.", // the mesh flips to zero-terminated + "cone.imjs", // cone can change to cylinder + "box.minimal.imjs", // minimal box gets remaining fields populated ]; - const expectedFBMismatchList = ["point.imjs", // CoordinateXYZ is not implemented in writeGeometryQueryAsFBVariantGeometry... + const expectedFBMismatchList = ["point.imjs" // CoordinateXYZ is not implemented in writeGeometryQueryAsFBVariantGeometry... ]; // read imjs files from various places -- some produced by native, some by core-geometry ... for (const sourceDirectory of [iModelJsonSamplesDirectory, iModelJsonNativeSamplesDirectory]) { @@ -252,7 +251,10 @@ describe("CreateIModelJsonSamples", () => { // skip known non-round-trip files ... let isFiltered = false; for (const candidate of skipList) - if (currFile.lastIndexOf(candidate) >= 0) { isFiltered = true; break; } + if (currFile.lastIndexOf(candidate) >= 0) { + isFiltered = true; + break; + } if (isFiltered) continue; Checker.noisy.printJSONFailure = true; const data = fs.readFileSync(currFile, "utf8"); @@ -277,8 +279,15 @@ describe("CreateIModelJsonSamples", () => { if (deepAlmostEqual(geometryQuery1, geometryQuery3)) { isFiltered = false; for (const candidate of expectedJsonMismatchList) - if (currFile.lastIndexOf(candidate) >= 0) { isFiltered = true; break; } - GeometryCoreTestIO.consoleLog("%s json round trip mismatch (geometry matches):", isFiltered ? "Expected" : "Warning: Unexpected", currFile); + if (currFile.lastIndexOf(candidate) >= 0) { + isFiltered = true; + break; + } + GeometryCoreTestIO.consoleLog( + "%s json round trip mismatch (geometry matches):", + isFiltered ? "Expected" : "Warning: Unexpected", + currFile, + ); if (!isFiltered) { GeometryCoreTestIO.consoleLog("jsonObject1:", prettyPrint(jsonObject1)); GeometryCoreTestIO.consoleLog("jsonObject3:", prettyPrint(jsonObject3)); @@ -287,13 +296,19 @@ describe("CreateIModelJsonSamples", () => { ck.announceError("imjs => GeometryQuery => imjs round trip failure", currFile); GeometryCoreTestIO.consoleLog("jsonObject1:", prettyPrint(jsonObject1)); GeometryCoreTestIO.consoleLog("jsonObject2:", prettyPrint(jsonObject2)); - if (Checker.noisy.printJSONFailure) { GeometryCoreTestIO.consoleLog(`FAIL: ${i}`); GeometryCoreTestIO.consoleLog(compareObj.errorTracker); } + if (Checker.noisy.printJSONFailure) { + GeometryCoreTestIO.consoleLog(`FAIL: ${i}`); + GeometryCoreTestIO.consoleLog(compareObj.errorTracker); + } } } // test geometry roundtrip thru flatbuffer (and IMJS again) isFiltered = false; for (const candidate of expectedFBMismatchList) - if (currFile.lastIndexOf(candidate) >= 0) { isFiltered = true; break; } + if (currFile.lastIndexOf(candidate) >= 0) { + isFiltered = true; + break; + } if (isFiltered) continue; testGeometryQueryRoundTrip(ck, geometryQuery1); } @@ -369,7 +384,13 @@ describe("ParseCurveCollections", () => { GeometryCoreTestIO.captureCloneGeometry(allGeometry, inputs); for (const input of inputs) { ck.testExactNumber(7, input.children.length, "path has expected number of children"); - ck.testExactNumber(3, input.children.filter((child: CurvePrimitive): boolean => { return child instanceof BSplineCurve3dBase; }).length, "path has expected number of B-spline curve children"); + ck.testExactNumber( + 3, + input.children.filter((child: CurvePrimitive): boolean => { + return child instanceof BSplineCurve3dBase; + }).length, + "path has expected number of B-spline curve children", + ); } } GeometryCoreTestIO.saveGeometry(allGeometry, "ParseCurveCollection", "BSplinePathRegression"); diff --git a/core/geometry/src/test/serialization/SerializationHelpers.test.ts b/core/geometry/src/test/serialization/SerializationHelpers.test.ts index fa25bb15d8e2..3ae4b4b2a4a8 100644 --- a/core/geometry/src/test/serialization/SerializationHelpers.test.ts +++ b/core/geometry/src/test/serialization/SerializationHelpers.test.ts @@ -16,17 +16,45 @@ import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function createCurveData(curve: BSplineCurve3dH): SerializationHelpers.BSplineCurveData { - const params: SerializationHelpers.BSplineParams = { numPoles: curve.numPoles, order: curve.order, knots: curve.copyKnots(false), closed: false, wrapMode: curve.getWrappable() }; + const params: SerializationHelpers.BSplineParams = { + numPoles: curve.numPoles, + order: curve.order, + knots: curve.copyKnots(false), + closed: false, + wrapMode: curve.getWrappable(), + }; return { poles: curve.copyXYZFloat64Array(false), dim: 3, weights: NumberArray.create(curve.copyWeightsFloat64Array()), params }; } function createSurfaceData(surface: BSplineSurface3dH): SerializationHelpers.BSplineSurfaceData { - const uParams: SerializationHelpers.BSplineParams = { numPoles: surface.numPolesUV(UVSelect.uDirection), order: surface.orderUV(UVSelect.uDirection), knots: surface.copyKnots(UVSelect.uDirection, false), closed: false, wrapMode: surface.getWrappable(UVSelect.uDirection) }; - const vParams: SerializationHelpers.BSplineParams = { numPoles: surface.numPolesUV(UVSelect.vDirection), order: surface.orderUV(UVSelect.vDirection), knots: surface.copyKnots(UVSelect.vDirection, false), closed: false, wrapMode: surface.getWrappable(UVSelect.vDirection) }; - return { poles: surface.copyXYZToFloat64Array(false), dim: 3, weights: NumberArray.unpack2d(surface.copyWeightsToFloat64Array(), surface.numPolesUV(UVSelect.uDirection)), uParams, vParams }; + const uParams: SerializationHelpers.BSplineParams = { + numPoles: surface.numPolesUV(UVSelect.uDirection), + order: surface.orderUV(UVSelect.uDirection), + knots: surface.copyKnots(UVSelect.uDirection, false), + closed: false, + wrapMode: surface.getWrappable(UVSelect.uDirection), + }; + const vParams: SerializationHelpers.BSplineParams = { + numPoles: surface.numPolesUV(UVSelect.vDirection), + order: surface.orderUV(UVSelect.vDirection), + knots: surface.copyKnots(UVSelect.vDirection, false), + closed: false, + wrapMode: surface.getWrappable(UVSelect.vDirection), + }; + return { + poles: surface.copyXYZToFloat64Array(false), + dim: 3, + weights: NumberArray.unpack2d(surface.copyWeightsToFloat64Array(), surface.numPolesUV(UVSelect.uDirection)), + uParams, + vParams, + }; } -function unpackPoles(poles: Float64Array | number[][] | number[][][], dim: number, weights?: Float64Array | number[][] | number[]): { xyz?: Float64Array, w?: Float64Array } { +function unpackPoles( + poles: Float64Array | number[][] | number[][][], + dim: number, + weights?: Float64Array | number[][] | number[], +): { xyz?: Float64Array, w?: Float64Array } { let xyz: Float64Array | undefined; let w: Float64Array | undefined; if (dim === 3) { @@ -44,7 +72,16 @@ function unpackPoles(poles: Float64Array | number[][] | number[][][], dim: numbe return { xyz, w }; } -function cloneSubArray(a?: Float64Array | number[] | number[][] | number[][][], numRow = 0, numCol = 0, dim = 1, iRow0 = 0, iRow1 = numRow, iCol0 = 0, iCol1 = numCol): Float64Array { +function cloneSubArray( + a?: Float64Array | number[] | number[][] | number[][][], + numRow = 0, + numCol = 0, + dim = 1, + iRow0 = 0, + iRow1 = numRow, + iCol0 = 0, + iCol1 = numCol, +): Float64Array { if (!a || numRow <= 0 || numCol <= 0 || dim <= 0) return new Float64Array(); if (iRow1 < 0) @@ -74,7 +111,10 @@ function almostEqualCurveData(data0: SerializationHelpers.BSplineCurveData, data if (data0.params.order !== data1.params.order) return false; const degree = data0.params.order - 1; - if (Geometry.resolveValue(data0.params.wrapMode, BSplineWrapMode.None) !== Geometry.resolveValue(data1.params.wrapMode, BSplineWrapMode.None)) + if ( + Geometry.resolveValue(data0.params.wrapMode, BSplineWrapMode.None) !== + Geometry.resolveValue(data1.params.wrapMode, BSplineWrapMode.None) + ) return false; const unpacked0 = unpackPoles(data0.poles, data0.dim, data0.weights); const unpacked1 = unpackPoles(data1.poles, data1.dim, data1.weights); @@ -86,18 +126,24 @@ function almostEqualCurveData(data0: SerializationHelpers.BSplineCurveData, data return false; if (!NumberArray.isAlmostEqual(unpacked0.w, unpacked1.w)) return false; - } else { // differing closure means poles/weights should have counts that differ by degree - if (!almostEqualSubArrays(unpacked0.xyz, unpacked1.xyz, 0, -degree * 3) && - !almostEqualSubArrays(unpacked1.xyz, unpacked0.xyz, 0, -degree * 3)) + } else { // differing closure means poles/weights should have counts that differ by degree + if ( + !almostEqualSubArrays(unpacked0.xyz, unpacked1.xyz, 0, -degree * 3) && + !almostEqualSubArrays(unpacked1.xyz, unpacked0.xyz, 0, -degree * 3) + ) return false; - if (!almostEqualSubArrays(unpacked0.w, unpacked1.w, 0, -degree) && - !almostEqualSubArrays(unpacked1.w, unpacked0.w, 0, -degree)) + if ( + !almostEqualSubArrays(unpacked0.w, unpacked1.w, 0, -degree) && + !almostEqualSubArrays(unpacked1.w, unpacked0.w, 0, -degree) + ) return false; } // account for extraneous knots - if (!NumberArray.isAlmostEqual(data0.params.knots, data1.params.knots) && + if ( + !NumberArray.isAlmostEqual(data0.params.knots, data1.params.knots) && !almostEqualSubArrays(data0.params.knots, data1.params.knots, 1, -1) && - !almostEqualSubArrays(data1.params.knots, data0.params.knots, 1, -1)) + !almostEqualSubArrays(data1.params.knots, data0.params.knots, 1, -1) + ) return false; return true; } @@ -112,9 +158,15 @@ function almostEqualSurfaceData(data0: SerializationHelpers.BSplineSurfaceData, return false; const uDegree = data0.uParams.order - 1; const vDegree = data0.vParams.order - 1; - if (Geometry.resolveValue(data0.uParams.wrapMode, BSplineWrapMode.None) !== Geometry.resolveValue(data1.uParams.wrapMode, BSplineWrapMode.None)) + if ( + Geometry.resolveValue(data0.uParams.wrapMode, BSplineWrapMode.None) !== + Geometry.resolveValue(data1.uParams.wrapMode, BSplineWrapMode.None) + ) return false; - if (Geometry.resolveValue(data0.vParams.wrapMode, BSplineWrapMode.None) !== Geometry.resolveValue(data1.vParams.wrapMode, BSplineWrapMode.None)) + if ( + Geometry.resolveValue(data0.vParams.wrapMode, BSplineWrapMode.None) !== + Geometry.resolveValue(data1.vParams.wrapMode, BSplineWrapMode.None) + ) return false; const unpacked0 = unpackPoles(data0.poles, data0.dim, data0.weights); const unpacked1 = unpackPoles(data1.poles, data1.dim, data1.weights); @@ -133,64 +185,124 @@ function almostEqualSurfaceData(data0: SerializationHelpers.BSplineSurfaceData, if (!NumberArray.isAlmostEqual(unpacked0.w, unpacked1.w)) return false; } else if (uClosed0 !== uClosed1 && vClosed0 === vClosed1) { - if ((data0.uParams.numPoles - uDegree !== data1.uParams.numPoles) && - (data0.uParams.numPoles !== data1.uParams.numPoles - uDegree)) + if ( + (data0.uParams.numPoles - uDegree !== data1.uParams.numPoles) && + (data0.uParams.numPoles !== data1.uParams.numPoles - uDegree) + ) return false; if (data0.vParams.numPoles !== data1.vParams.numPoles) return false; const xyzFewerCols0 = cloneSubArray(unpacked0.xyz, data0.vParams.numPoles, data0.uParams.numPoles, 3, undefined, undefined, undefined, -uDegree); const xyzFewerCols1 = cloneSubArray(unpacked1.xyz, data1.vParams.numPoles, data1.uParams.numPoles, 3, undefined, undefined, undefined, -uDegree); - if (!NumberArray.isAlmostEqual(xyzFewerCols0, unpacked1.xyz) && - !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerCols1)) + if ( + !NumberArray.isAlmostEqual(xyzFewerCols0, unpacked1.xyz) && + !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerCols1) + ) return false; const wFewerCols0 = cloneSubArray(unpacked0.w, data0.vParams.numPoles, data0.uParams.numPoles, 1, undefined, undefined, undefined, -uDegree); const wFewerCols1 = cloneSubArray(unpacked1.w, data1.vParams.numPoles, data1.uParams.numPoles, 1, undefined, undefined, undefined, -uDegree); - if (!NumberArray.isAlmostEqual(wFewerCols0, unpacked1.w) && - !NumberArray.isAlmostEqual(unpacked0.w, wFewerCols1)) + if ( + !NumberArray.isAlmostEqual(wFewerCols0, unpacked1.w) && + !NumberArray.isAlmostEqual(unpacked0.w, wFewerCols1) + ) return false; } else if (uClosed0 === uClosed1 && vClosed0 !== vClosed1) { if (data0.uParams.numPoles !== data1.uParams.numPoles) return false; - if ((data0.vParams.numPoles - vDegree !== data1.vParams.numPoles) && - (data0.vParams.numPoles !== data1.vParams.numPoles - vDegree)) + if ( + (data0.vParams.numPoles - vDegree !== data1.vParams.numPoles) && + (data0.vParams.numPoles !== data1.vParams.numPoles - vDegree) + ) return false; const xyzFewerRows0 = cloneSubArray(unpacked0.xyz, data0.vParams.numPoles, data0.uParams.numPoles, 3, undefined, -vDegree); const xyzFewerRows1 = cloneSubArray(unpacked1.xyz, data1.vParams.numPoles, data1.uParams.numPoles, 3, undefined, -vDegree); - if (!NumberArray.isAlmostEqual(xyzFewerRows0, unpacked1.xyz) && - !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerRows1)) + if ( + !NumberArray.isAlmostEqual(xyzFewerRows0, unpacked1.xyz) && + !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerRows1) + ) return false; const wFewerRows0 = cloneSubArray(unpacked0.w, data0.vParams.numPoles, data0.uParams.numPoles, 1, undefined, -vDegree); const wFewerRows1 = cloneSubArray(unpacked1.w, data1.vParams.numPoles, data1.uParams.numPoles, 1, undefined, -vDegree); - if (!NumberArray.isAlmostEqual(wFewerRows0, unpacked1.w) && - !NumberArray.isAlmostEqual(unpacked0.w, wFewerRows1)) + if ( + !NumberArray.isAlmostEqual(wFewerRows0, unpacked1.w) && + !NumberArray.isAlmostEqual(unpacked0.w, wFewerRows1) + ) return false; - } else { // both closures different - if ((data0.uParams.numPoles - uDegree !== data1.uParams.numPoles) && - (data0.uParams.numPoles !== data1.uParams.numPoles - uDegree)) + } else { // both closures different + if ( + (data0.uParams.numPoles - uDegree !== data1.uParams.numPoles) && + (data0.uParams.numPoles !== data1.uParams.numPoles - uDegree) + ) return false; - if ((data0.vParams.numPoles - vDegree !== data1.vParams.numPoles) && - (data0.vParams.numPoles !== data1.vParams.numPoles - vDegree)) + if ( + (data0.vParams.numPoles - vDegree !== data1.vParams.numPoles) && + (data0.vParams.numPoles !== data1.vParams.numPoles - vDegree) + ) return false; - const xyzFewerRowsAndCols0 = cloneSubArray(unpacked0.xyz, data0.vParams.numPoles, data0.uParams.numPoles, 3, undefined, -vDegree, undefined, -uDegree); - const xyzFewerRowsAndCols1 = cloneSubArray(unpacked1.xyz, data1.vParams.numPoles, data1.uParams.numPoles, 3, undefined, -vDegree, undefined, -uDegree); - if (!NumberArray.isAlmostEqual(xyzFewerRowsAndCols0, unpacked1.xyz) && - !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerRowsAndCols1)) + const xyzFewerRowsAndCols0 = cloneSubArray( + unpacked0.xyz, + data0.vParams.numPoles, + data0.uParams.numPoles, + 3, + undefined, + -vDegree, + undefined, + -uDegree, + ); + const xyzFewerRowsAndCols1 = cloneSubArray( + unpacked1.xyz, + data1.vParams.numPoles, + data1.uParams.numPoles, + 3, + undefined, + -vDegree, + undefined, + -uDegree, + ); + if ( + !NumberArray.isAlmostEqual(xyzFewerRowsAndCols0, unpacked1.xyz) && + !NumberArray.isAlmostEqual(unpacked0.xyz, xyzFewerRowsAndCols1) + ) return false; - const wFewerRowsAndCols0 = cloneSubArray(unpacked0.w, data0.vParams.numPoles, data0.uParams.numPoles, 1, undefined, -vDegree, undefined, -uDegree); - const wFewerRowsAndCols1 = cloneSubArray(unpacked1.w, data1.vParams.numPoles, data1.uParams.numPoles, 1, undefined, -vDegree, undefined, -uDegree); - if (!NumberArray.isAlmostEqual(wFewerRowsAndCols0, unpacked1.w) && - !NumberArray.isAlmostEqual(unpacked0.w, wFewerRowsAndCols1)) + const wFewerRowsAndCols0 = cloneSubArray( + unpacked0.w, + data0.vParams.numPoles, + data0.uParams.numPoles, + 1, + undefined, + -vDegree, + undefined, + -uDegree, + ); + const wFewerRowsAndCols1 = cloneSubArray( + unpacked1.w, + data1.vParams.numPoles, + data1.uParams.numPoles, + 1, + undefined, + -vDegree, + undefined, + -uDegree, + ); + if ( + !NumberArray.isAlmostEqual(wFewerRowsAndCols0, unpacked1.w) && + !NumberArray.isAlmostEqual(unpacked0.w, wFewerRowsAndCols1) + ) return false; } // account for extraneous uKnots - if (!NumberArray.isAlmostEqual(data0.uParams.knots, data1.uParams.knots) && + if ( + !NumberArray.isAlmostEqual(data0.uParams.knots, data1.uParams.knots) && !almostEqualSubArrays(data0.uParams.knots, data1.uParams.knots, 1, -1) && - !almostEqualSubArrays(data1.uParams.knots, data0.uParams.knots, 1, -1)) + !almostEqualSubArrays(data1.uParams.knots, data0.uParams.knots, 1, -1) + ) return false; // account for extraneous vKnots - if (!NumberArray.isAlmostEqual(data0.vParams.knots, data1.vParams.knots) && + if ( + !NumberArray.isAlmostEqual(data0.vParams.knots, data1.vParams.knots) && !almostEqualSubArrays(data0.vParams.knots, data1.vParams.knots, 1, -1) && - !almostEqualSubArrays(data1.vParams.knots, data0.vParams.knots, 1, -1)) + !almostEqualSubArrays(data1.vParams.knots, data0.vParams.knots, 1, -1) + ) return false; return true; } @@ -203,16 +315,40 @@ function createTestSurface(uPeriodic: boolean, vPeriodic: boolean): BSplineSurfa let vNumPoles = 4; const vDegree = 3; let poles3d = [ - Point3d.create(5, 0, -2), Point3d.create(0, 5, -2), Point3d.create(-5, 0, -2), Point3d.create(0, -5, -2), - Point3d.create(7, 0, 0), Point3d.create(0, 7, 0), Point3d.create(-7, 0, 0), Point3d.create(0, -7, 0), - Point3d.create(5, 0, 2), Point3d.create(0, 5, 2), Point3d.create(-5, 0, 2), Point3d.create(0, -5, 2), - Point3d.create(3, 0, 0), Point3d.create(0, 3, 0), Point3d.create(-3, 0, 0), Point3d.create(0, -3, 0), + Point3d.create(5, 0, -2), + Point3d.create(0, 5, -2), + Point3d.create(-5, 0, -2), + Point3d.create(0, -5, -2), + Point3d.create(7, 0, 0), + Point3d.create(0, 7, 0), + Point3d.create(-7, 0, 0), + Point3d.create(0, -7, 0), + Point3d.create(5, 0, 2), + Point3d.create(0, 5, 2), + Point3d.create(-5, 0, 2), + Point3d.create(0, -5, 2), + Point3d.create(3, 0, 0), + Point3d.create(0, 3, 0), + Point3d.create(-3, 0, 0), + Point3d.create(0, -3, 0), ]; let weights = [ - 0.4, 0.6, 0.5, 0.7, - 0.6, 0.5, 0.7, 0.4, - 0.5, 0.7, 0.4, 0.6, - 0.7, 0.4, 0.6, 0.5, + 0.4, + 0.6, + 0.5, + 0.7, + 0.6, + 0.5, + 0.7, + 0.4, + 0.5, + 0.7, + 0.4, + 0.6, + 0.7, + 0.4, + 0.6, + 0.5, ]; for (let i = 0; i < poles3d.length; ++i) poles3d[i].scaleInPlace(weights[i]); @@ -223,13 +359,13 @@ function createTestSurface(uPeriodic: boolean, vPeriodic: boolean): BSplineSurfa uKnots = KnotVector.createUniformWrapped(uNumInterval, uDegree, 0, 1); const uWrappedPoles: Point3d[] = []; const uWrappedWeights: number[] = []; - for (let i = 0; i < vNumPoles; ++i) { // #rows + for (let i = 0; i < vNumPoles; ++i) { // #rows const rowStart = i * uNumPoles; - for (let j = 0; j < uNumPoles; ++j) { // copy the row + for (let j = 0; j < uNumPoles; ++j) { // copy the row uWrappedPoles.push(Point3d.createFrom(poles3d[rowStart + j])); uWrappedWeights.push(weights[rowStart + j]); } - for (let k = 0; k < uDegree; ++k) { // append first uDegree entries to this row + for (let k = 0; k < uDegree; ++k) { // append first uDegree entries to this row uWrappedPoles.push(Point3d.createFrom(poles3d[rowStart + k])); uWrappedWeights.push(weights[rowStart + k]); } @@ -245,9 +381,9 @@ function createTestSurface(uPeriodic: boolean, vPeriodic: boolean): BSplineSurfa vKnots = KnotVector.createUniformWrapped(vNumInterval, vDegree, 0, 1); const vWrappedPoles = Point3dArray.clonePoint3dArray(poles3d); const vWrappedWeights = weights.slice(); - for (let i = 0; i < vDegree; ++i) { // append vDegree wraparound rows + for (let i = 0; i < vDegree; ++i) { // append vDegree wraparound rows const rowStart = i * uNumPoles; - for (let j = 0; j < uNumPoles; ++j) { // #cols + for (let j = 0; j < uNumPoles; ++j) { // #cols vWrappedPoles.push(Point3d.createFrom(poles3d[rowStart + j])); vWrappedWeights.push(weights[rowStart + j]); } @@ -284,19 +420,33 @@ describe("SerializationHelpers", () => { // cover Point3d/4dArray.isAlmostEqual/packToFloat64Array let working = new Float64Array(); // wrong size - ck.testTrue(Point3dArray.isAlmostEqual(unweightedPoles3d, Point3dArray.packToFloat64Array(unweightedPoles3d, working)), "cover Point3dArray.isAlmostEqual(points, numbers)"); + ck.testTrue( + Point3dArray.isAlmostEqual(unweightedPoles3d, Point3dArray.packToFloat64Array(unweightedPoles3d, working)), + "cover Point3dArray.isAlmostEqual(points, numbers)", + ); working = new Float64Array(3 * unweightedPoles3d.length); // right size - ck.testTrue(Point3dArray.isAlmostEqual(Point3dArray.packToFloat64Array(unweightedPoles3d, working), unweightedPoles3d), "cover Point3dArray.isAlmostEqual(numbers, points)"); + ck.testTrue( + Point3dArray.isAlmostEqual(Point3dArray.packToFloat64Array(unweightedPoles3d, working), unweightedPoles3d), + "cover Point3dArray.isAlmostEqual(numbers, points)", + ); working = new Float64Array(); // wrong size - ck.testTrue(Point4dArray.isAlmostEqual(poles4d, Point4dArray.packToFloat64Array(poles4d, working)), "cover Point4dArray.isAlmostEqual(points, numbers)"); + ck.testTrue( + Point4dArray.isAlmostEqual(poles4d, Point4dArray.packToFloat64Array(poles4d, working)), + "cover Point4dArray.isAlmostEqual(points, numbers)", + ); working = new Float64Array(4 * poles4d.length); // right size - ck.testTrue(Point4dArray.isAlmostEqual(Point4dArray.packToFloat64Array(poles4d, working), poles4d), "cover Point4dArray.isAlmostEqual(numbers, points)"); + ck.testTrue( + Point4dArray.isAlmostEqual(Point4dArray.packToFloat64Array(poles4d, working), poles4d), + "cover Point4dArray.isAlmostEqual(numbers, points)", + ); // test open and (maximally continuous) periodic curves const openCurve = BSplineCurve3dH.createUniformKnots(poles4d, 4); const closedCurve = BSplineCurve3dH.createPeriodicUniformKnots(poles4d, 3); - if (ck.testType(openCurve, BSplineCurve3dH, "BSplineCurve3dH.createUniformKnots returned a homogeneous curve") && - ck.testType(closedCurve, BSplineCurve3dH, "BSplineCurve3dH.createPeriodicUniformKnots returned a periodic homogeneous curve")) { + if ( + ck.testType(openCurve, BSplineCurve3dH, "BSplineCurve3dH.createUniformKnots returned a homogeneous curve") && + ck.testType(closedCurve, BSplineCurve3dH, "BSplineCurve3dH.createPeriodicUniformKnots returned a periodic homogeneous curve") + ) { for (const curve of [openCurve, closedCurve]) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, curve); const origData = createCurveData(curve); @@ -315,15 +465,39 @@ describe("SerializationHelpers", () => { data = SerializationHelpers.cloneBSplineCurveData(origData); } data.weights = curve.copyWeightsFloat64Array(); - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonPoles: true }), "Export.prepareBSplineCurveData with jsonPoles and Float64Array weights succeeds")) - ck.testTrue(almostEqualCurveData(data, origData), "Export.prepareBSplineCurveData with jsonPoles and Float64Array weights yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonPoles: true }), + "Export.prepareBSplineCurveData with jsonPoles and Float64Array weights succeeds", + ) + ) + ck.testTrue( + almostEqualCurveData(data, origData), + "Export.prepareBSplineCurveData with jsonPoles and Float64Array weights yields equivalent data", + ); data = SerializationHelpers.cloneBSplineCurveData(origData); data.params.knots = curve.knotsRef; - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonKnots: true }), "Export.prepareBSplineCurveData with jsonKnots and Float64Array knots succeeds")) - ck.testTrue(almostEqualCurveData(data, origData), "Export.prepareBSplineCurveData with jsonKnots and Float64Array knots yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonKnots: true }), + "Export.prepareBSplineCurveData with jsonKnots and Float64Array knots succeeds", + ) + ) + ck.testTrue( + almostEqualCurveData(data, origData), + "Export.prepareBSplineCurveData with jsonKnots and Float64Array knots yields equivalent data", + ); data = SerializationHelpers.cloneBSplineCurveData(origData); - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonKnots: false }), "Export.prepareBSplineCurveData with !jsonKnots and number[] knots succeeds")) - ck.testTrue(almostEqualCurveData(data, origData), "Export.prepareBSplineCurveData with !jsonKnots and number[] knots yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineCurveData(data, { jsonKnots: false }), + "Export.prepareBSplineCurveData with !jsonKnots and number[] knots succeeds", + ) + ) + ck.testTrue( + almostEqualCurveData(data, origData), + "Export.prepareBSplineCurveData with !jsonKnots and number[] knots yields equivalent data", + ); } // test Import const importData = SerializationHelpers.cloneBSplineCurveData(exportData); @@ -331,7 +505,12 @@ describe("SerializationHelpers", () => { ck.testTrue(almostEqualCurveData(importData, origData), "Import.prepareBSplineCurveData on valid input yields equivalent data"); if (true) { const data = SerializationHelpers.cloneBSplineCurveData(exportData); - if (ck.testTrue(SerializationHelpers.Import.prepareBSplineCurveData(data, { removeExtraKnots: true }), "Import.prepareBSplineCurveData with removeExtraKnots succeeds")) + if ( + ck.testTrue( + SerializationHelpers.Import.prepareBSplineCurveData(data, { removeExtraKnots: true }), + "Import.prepareBSplineCurveData with removeExtraKnots succeeds", + ) + ) ck.testTrue(almostEqualCurveData(data, exportData), "Import.prepareBSplineCurveData with removeExtraKnots yields equivalent data"); } } @@ -352,7 +531,9 @@ describe("SerializationHelpers", () => { const origData = createSurfaceData(surface); // test Export const exportData = SerializationHelpers.cloneBSplineSurfaceData(origData); - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineSurfaceData(exportData), "Export.prepareBSplineSurfaceData on valid input succeeds")) + if ( + ck.testTrue(SerializationHelpers.Export.prepareBSplineSurfaceData(exportData), "Export.prepareBSplineSurfaceData on valid input succeeds") + ) ck.testTrue(almostEqualSurfaceData(exportData, origData), "Export.prepareBSplineSurfaceData on valid input yields equivalent data"); if (true) { let data = SerializationHelpers.cloneBSplineSurfaceData(origData); @@ -362,33 +543,70 @@ describe("SerializationHelpers", () => { data = SerializationHelpers.cloneBSplineSurfaceData(origData); if (surface.isClosable(UVSelect.uDirection)) { data.uParams.numPoles = 0; - ck.testFalse(SerializationHelpers.Export.prepareBSplineSurfaceData(data), "Export.prepareBSplineSurfaceData with invalid uNumPoles fails"); + ck.testFalse( + SerializationHelpers.Export.prepareBSplineSurfaceData(data), + "Export.prepareBSplineSurfaceData with invalid uNumPoles fails", + ); data = SerializationHelpers.cloneBSplineSurfaceData(origData); } else if (surface.isClosable(UVSelect.vDirection)) { data.vParams.numPoles = 0; - ck.testFalse(SerializationHelpers.Export.prepareBSplineSurfaceData(data), "Export.prepareBSplineSurfaceData with invalid vNumPoles fails"); + ck.testFalse( + SerializationHelpers.Export.prepareBSplineSurfaceData(data), + "Export.prepareBSplineSurfaceData with invalid vNumPoles fails", + ); data = SerializationHelpers.cloneBSplineSurfaceData(origData); } } data.weights = surface.copyWeightsToFloat64Array(); - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonPoles: true }), "Export.prepareBSplineSurfaceData with jsonPoles and Float64Array weights succeeds")) - ck.testTrue(almostEqualSurfaceData(data, origData), "Export.prepareBSplineSurfaceData with jsonPoles and Float64Array weights yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonPoles: true }), + "Export.prepareBSplineSurfaceData with jsonPoles and Float64Array weights succeeds", + ) + ) + ck.testTrue( + almostEqualSurfaceData(data, origData), + "Export.prepareBSplineSurfaceData with jsonPoles and Float64Array weights yields equivalent data", + ); data = SerializationHelpers.cloneBSplineSurfaceData(origData); data.uParams.knots = surface.knots[UVSelect.uDirection].knots; data.vParams.knots = surface.knots[UVSelect.vDirection].knots; - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonKnots: true }), "Export.prepareBSplineSurfaceData with jsonKnots and Float64Array uKnots and vKnots succeeds")) - ck.testTrue(almostEqualSurfaceData(data, origData), "Export.prepareBSplineSurfaceData with jsonKnots and Float64Array uKnots and vKnots yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonKnots: true }), + "Export.prepareBSplineSurfaceData with jsonKnots and Float64Array uKnots and vKnots succeeds", + ) + ) + ck.testTrue( + almostEqualSurfaceData(data, origData), + "Export.prepareBSplineSurfaceData with jsonKnots and Float64Array uKnots and vKnots yields equivalent data", + ); data = SerializationHelpers.cloneBSplineSurfaceData(origData); - if (ck.testTrue(SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonKnots: false }), "Export.prepareBSplineSurfaceData with !jsonKnots and number[] uKnots and vKnots succeeds")) - ck.testTrue(almostEqualSurfaceData(data, origData), "Export.prepareBSplineSurfaceData with !jsonKnots and number[] uKnots and vKnots yields equivalent data"); + if ( + ck.testTrue( + SerializationHelpers.Export.prepareBSplineSurfaceData(data, { jsonKnots: false }), + "Export.prepareBSplineSurfaceData with !jsonKnots and number[] uKnots and vKnots succeeds", + ) + ) + ck.testTrue( + almostEqualSurfaceData(data, origData), + "Export.prepareBSplineSurfaceData with !jsonKnots and number[] uKnots and vKnots yields equivalent data", + ); } // test Import const importData = SerializationHelpers.cloneBSplineSurfaceData(exportData); - if (ck.testTrue(SerializationHelpers.Import.prepareBSplineSurfaceData(importData), "Import.prepareBSplineSurfaceData on valid input succeeds")) + if ( + ck.testTrue(SerializationHelpers.Import.prepareBSplineSurfaceData(importData), "Import.prepareBSplineSurfaceData on valid input succeeds") + ) ck.testTrue(almostEqualSurfaceData(importData, origData), "Import.prepareBSplineSurfaceData on valid input yields equivalent data"); if (true) { const data = SerializationHelpers.cloneBSplineSurfaceData(exportData); - if (ck.testTrue(SerializationHelpers.Import.prepareBSplineSurfaceData(data, { removeExtraKnots: true }), "Import.prepareBSplineSurfaceData with removeExtraKnots succeeds")) + if ( + ck.testTrue( + SerializationHelpers.Import.prepareBSplineSurfaceData(data, { removeExtraKnots: true }), + "Import.prepareBSplineSurfaceData with removeExtraKnots succeeds", + ) + ) ck.testTrue(almostEqualSurfaceData(data, exportData), "Import.prepareBSplineSurfaceData with removeExtraKnots yields equivalent data"); } } diff --git a/core/geometry/src/test/serialization/constructorsAndIModelJson.test.ts b/core/geometry/src/test/serialization/constructorsAndIModelJson.test.ts index 9dde9c9d2353..ea5e7f388c59 100644 --- a/core/geometry/src/test/serialization/constructorsAndIModelJson.test.ts +++ b/core/geometry/src/test/serialization/constructorsAndIModelJson.test.ts @@ -56,7 +56,6 @@ function emitIModelJson(className: string, description: string, g: any) { // 2) An additional "import" directive to obtain an appropriate implementation of "emit". describe("constructorsAndImodelJson", () => { - it("CurvePrimitives", () => { emitCategoryHeader("CurvePrimitive"); const pointA = Point3d.create(0, 0, 0); @@ -78,10 +77,15 @@ describe("constructorsAndImodelJson", () => { // elliptic arc -- larger vector90 . . . emitIModelJson("Arc3d.create", "elliptic arc", Arc3d.create(pointA, vectorAB, vectorAD.scale(2.0), AngleSweep.createStartEndDegrees(-45, 190))); - emitIModelJson("BSplineCurve3d.create", "curve by poles", BSplineCurve3d.create( - [pointA, pointB, pointC, pointD], - [0, 0, 0, 1, 1, 1], 4)!); - + emitIModelJson( + "BSplineCurve3d.create", + "curve by poles", + BSplineCurve3d.create( + [pointA, pointB, pointC, pointD], + [0, 0, 0, 1, 1, 1], + 4, + )!, + ); }); it("constructorsAndIModelJson.CurveCollections", () => { @@ -94,10 +98,15 @@ describe("constructorsAndImodelJson", () => { const vectorAD = pointA.vectorTo(pointD); const upperSemiCircle = Arc3d.create(pointA, vectorAB, vectorAD, AngleSweep.createStartEndDegrees(0, 180)); - emitIModelJson("Path.create", "path with line, arc, line", + emitIModelJson( + "Path.create", + "path with line, arc, line", Path.create( LineSegment3d.create(pointC, upperSemiCircle.fractionToPoint(0)), - upperSemiCircle, LineSegment3d.create(upperSemiCircle.fractionToPoint(1), pointA))); + upperSemiCircle, + LineSegment3d.create(upperSemiCircle.fractionToPoint(1), pointA), + ), + ); const closureSegment = LineSegment3d.create(upperSemiCircle.fractionToPoint(1), upperSemiCircle.fractionToPoint(0)); const semiCircleRegion = Loop.create(upperSemiCircle, closureSegment); @@ -123,7 +132,11 @@ describe("constructorsAndImodelJson", () => { const radiusA = 1.5; const radiusB = 2.0; const capped = true; - emitIModelJson("Cone.createAxisPoints(centerA, centerB, radiusA, radiusB, capped)", "full sphere", Cone.createAxisPoints(centerA, centerB, radiusA, radiusB, capped)!); + emitIModelJson( + "Cone.createAxisPoints(centerA, centerB, radiusA, radiusB, capped)", + "full sphere", + Cone.createAxisPoints(centerA, centerB, radiusA, radiusB, capped)!, + ); } { @@ -133,10 +146,11 @@ describe("constructorsAndImodelJson", () => { const ay = 3.0; const bx = 4.0; const by = 2.0; - emitIModelJson("Box.createDgnBox(cornerA, xVector, yVector, baseX, baseY, topX, topY, capped)", + emitIModelJson( + "Box.createDgnBox(cornerA, xVector, yVector, baseX, baseY, topX, topY, capped)", "box with sides slanting inward", - Box.createDgnBox(cornerA, Vector3d.unitX(), Vector3d.unitY(), - cornerB, ax, ay, bx, by, true) as Box); + Box.createDgnBox(cornerA, Vector3d.unitX(), Vector3d.unitY(), cornerB, ax, ay, bx, by, true) as Box, + ); } { const frame = Transform.createOriginAndMatrix(Point3d.create(1, 1, 1), Matrix3d.createRigidViewAxesZTowardsEye(2, 0, 3)); @@ -144,28 +158,29 @@ describe("constructorsAndImodelJson", () => { const minorRadius = 1.0; const sweep = Angle.createDegrees(90); const capped = true; - emitIModelJson("TorusPipe.createInFrame(frame, majorRadius, minorRadius, sweep, capped)", + emitIModelJson( + "TorusPipe.createInFrame(frame, majorRadius, minorRadius, sweep, capped)", "90 degree elbows", - TorusPipe.createInFrame(frame, majorRadius, minorRadius, sweep, capped)!); + TorusPipe.createInFrame(frame, majorRadius, minorRadius, sweep, capped)!, + ); } { const contour = Loop.create(LineString3d.createRegularPolygonXY(Point3d.create(1, 1, 0), 6, 1.0, true)); const sweepVector = Vector3d.create(0, 0, 4); const capped = true; - emitIModelJson("LinearSweep.create(contour, sweepVector, capped)", - "swept hexagon", - LinearSweep.create(contour, sweepVector, capped)!); + emitIModelJson("LinearSweep.create(contour, sweepVector, capped)", "swept hexagon", LinearSweep.create(contour, sweepVector, capped)!); } { const contour = Loop.create(LineString3d.createRegularPolygonXY(Point3d.create(1, 1, 0), 6, 1.0, true)); const axisOfRotation = Ray3d.create(Point3d.create(-1, 0, 0), Vector3d.create(0, 1, 0)); const sweepAngle = Angle.createDegrees(135); const capped = true; - emitIModelJson("RotationalSweep.create(contour, axisOfRotation, sweepAngle, capped)", + emitIModelJson( + "RotationalSweep.create(contour, axisOfRotation, sweepAngle, capped)", "hexagon rotated", - RotationalSweep.create(contour, axisOfRotation, sweepAngle, capped)!); + RotationalSweep.create(contour, axisOfRotation, sweepAngle, capped)!, + ); } - }); it("constructorsAndImodelJson.Other", () => { emitCategoryHeader("CurveCollections"); @@ -224,7 +239,15 @@ describe("constructorsAndImodelJson", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const tagA = new TaggedNumericData(-1000, 0); - const surface = TorusPipe.createDgnTorusPipe(Point3d.create(0, 0, 0), Vector3d.create(1, 0, 0), Vector3d.create(0, 1, 0), 4, 1, Angle.createDegrees(90), true)!; + const surface = TorusPipe.createDgnTorusPipe( + Point3d.create(0, 0, 0), + Vector3d.create(1, 0, 0), + Vector3d.create(0, 1, 0), + 4, + 1, + Angle.createDegrees(90), + true, + )!; const options = StrokeOptions.createForFacets(); options.angleTol = Angle.createDegrees(90); const builder = PolyfaceBuilder.create(options); diff --git a/core/geometry/src/test/serialization/crossPlatform.test.ts b/core/geometry/src/test/serialization/crossPlatform.test.ts index 565248ddf017..c2b45daf2c29 100644 --- a/core/geometry/src/test/serialization/crossPlatform.test.ts +++ b/core/geometry/src/test/serialization/crossPlatform.test.ts @@ -16,9 +16,17 @@ describe("CrossPlatform", () => { const ck = new Checker(); // fileNames[Platform][FileType] are names of files of given type written by the given platform - interface TestCase { fileNames: string[][][] } - enum Platform { Native = 0, TypeScript = 1 } - enum FileType { FlatBuffer = 0, JSON = 1 } + interface TestCase { + fileNames: string[][][]; + } + enum Platform { + Native = 0, + TypeScript = 1, + } + enum FileType { + FlatBuffer = 0, + JSON = 1, + } const root = "./src/test/data/crossPlatform/"; const nativeRoot = `${root}native/`; @@ -26,17 +34,40 @@ describe("CrossPlatform", () => { const testCases: TestCase[] = []; let testName = "indexedMesh-auxData"; - testCases.push({ fileNames: [[[`${nativeRoot}${testName}.fb`], [`${nativeRoot}${testName}.imjs`]], [[`${typeScriptRoot}${testName}-new.fb`, `${typeScriptRoot}${testName}-old.fb`], [`${typeScriptRoot}${testName}.imjs`]]] }); - testName = "indexedMesh-auxData2"; // inspired by Scientific Visualization sandbox - testCases.push({ fileNames: [[[`${nativeRoot}${testName}.fb`, `${nativeRoot}${testName}-size3.fb`, `${nativeRoot}${testName}-size4.fb`, `${nativeRoot}${testName}-size5.fb`], [`${nativeRoot}${testName}.imjs`, `${nativeRoot}${testName}-size3.imjs`, `${nativeRoot}${testName}-size4.imjs`, `${nativeRoot}${testName}-size5.imjs`]], [[`${typeScriptRoot}${testName}-new.fb`, `${typeScriptRoot}${testName}-old.fb`], [`${typeScriptRoot}${testName}.imjs`]]] }); + testCases.push({ + fileNames: [[[`${nativeRoot}${testName}.fb`], [`${nativeRoot}${testName}.imjs`]], [[ + `${typeScriptRoot}${testName}-new.fb`, + `${typeScriptRoot}${testName}-old.fb`, + ], [`${typeScriptRoot}${testName}.imjs`]]], + }); + testName = "indexedMesh-auxData2"; // inspired by Scientific Visualization sandbox + testCases.push({ + fileNames: [[[ + `${nativeRoot}${testName}.fb`, + `${nativeRoot}${testName}-size3.fb`, + `${nativeRoot}${testName}-size4.fb`, + `${nativeRoot}${testName}-size5.fb`, + ], [ + `${nativeRoot}${testName}.imjs`, + `${nativeRoot}${testName}-size3.imjs`, + `${nativeRoot}${testName}-size4.imjs`, + `${nativeRoot}${testName}-size5.imjs`, + ]], [[`${typeScriptRoot}${testName}-new.fb`, `${typeScriptRoot}${testName}-old.fb`], [`${typeScriptRoot}${testName}.imjs`]]], + }); testName = "indexedMesh-fixedSize"; - testCases.push({ fileNames: [[[`${nativeRoot}${testName}.fb`], [`${nativeRoot}${testName}.imjs`]], [[`${typeScriptRoot}${testName}.fb`], [`${typeScriptRoot}${testName}.imjs`]]] }); + testCases.push({ + fileNames: [[[`${nativeRoot}${testName}.fb`], [`${nativeRoot}${testName}.imjs`]], [[`${typeScriptRoot}${testName}.fb`], [ + `${typeScriptRoot}${testName}.imjs`, + ]]], + }); // TODO: add other test cases const geometry: GeometryQuery[] = []; const pushFirstDeserializedGeom = (fileName: string, fileType: FileType) => { - const geom = FileType.FlatBuffer === fileType ? GeometryCoreTestIO.flatBufferFileToGeometry(fileName) : GeometryCoreTestIO.jsonFileToGeometry(fileName); + const geom = FileType.FlatBuffer === fileType + ? GeometryCoreTestIO.flatBufferFileToGeometry(fileName) + : GeometryCoreTestIO.jsonFileToGeometry(fileName); if (ck.testDefined(geom, `deserialized ${fileName}`)) { let toPush: GeometryQuery | undefined; if (Array.isArray(geom)) { diff --git a/core/geometry/src/test/serialization/fromJSON.test.ts b/core/geometry/src/test/serialization/fromJSON.test.ts index 62bd07d86242..f2de14cdfc36 100644 --- a/core/geometry/src/test/serialization/fromJSON.test.ts +++ b/core/geometry/src/test/serialization/fromJSON.test.ts @@ -276,6 +276,5 @@ describe("SimpleFactory ", () => { ck.testTrue(a.isAlmostEqual(b)); } } - }); }); diff --git a/core/geometry/src/test/solid/PipePath.test.ts b/core/geometry/src/test/solid/PipePath.test.ts index 0c1803f952bb..ebf1cfcf03a2 100644 --- a/core/geometry/src/test/solid/PipePath.test.ts +++ b/core/geometry/src/test/solid/PipePath.test.ts @@ -4,21 +4,21 @@ *--------------------------------------------------------------------------------------------*/ import { describe, expect, it } from "vitest"; -import { Angle } from "../../geometry3d/Angle"; -import { AngleSweep } from "../../geometry3d/AngleSweep"; import { Arc3d } from "../../curve/Arc3d"; -import { Checker } from "../Checker"; import { CurveFactory } from "../../curve/CurveFactory"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineString3d } from "../../curve/LineString3d"; +import { StrokeOptions } from "../../curve/StrokeOptions"; +import { Angle } from "../../geometry3d/Angle"; +import { AngleSweep } from "../../geometry3d/AngleSweep"; import { Matrix3d } from "../../geometry3d/Matrix3d"; +import { Point2d } from "../../geometry3d/Point2dVector2d"; import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; -import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; -import { StrokeOptions } from "../../curve/StrokeOptions"; import { Transform } from "../../geometry3d/Transform"; +import { PolyfaceBuilder } from "../../polyface/PolyfaceBuilder"; import { TorusPipe } from "../../solid/TorusPipe"; -import { Point2d } from "../../geometry3d/Point2dVector2d"; +import { Checker } from "../Checker"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; describe("PipePath", () => { it("TorusPipeAlongArc", () => { @@ -30,7 +30,12 @@ describe("PipePath", () => { let x0 = 0; for (const sweepDegrees of [45, 190, -105]) { - const arc = Arc3d.create(Point3d.create(1, 0, 0), Vector3d.create(0, 2, 0), Vector3d.create(-2, 0, 0), AngleSweep.createStartSweepDegrees(startDegrees, sweepDegrees)); + const arc = Arc3d.create( + Point3d.create(1, 0, 0), + Vector3d.create(0, 2, 0), + Vector3d.create(-2, 0, 0), + AngleSweep.createStartSweepDegrees(startDegrees, sweepDegrees), + ); const pipe = TorusPipe.createAlongArc(arc, minorRadius, false); GeometryCoreTestIO.captureCloneGeometry(allGeometry, pipe, x0, y0); GeometryCoreTestIO.captureCloneGeometry(allGeometry, arc, x0, y0); @@ -60,9 +65,9 @@ describe("PipePath", () => { // test invalid inputs let pipeBad = TorusPipe.createDgnTorusPipe(center, Vector3d.createZero(), vectorY, majorRadius, minorRadius, sweep, capped); - ck.testDefined(pipeBad, "Zero vectorX nevertheless yields defined TorusPipe"); // default vec is used! + ck.testDefined(pipeBad, "Zero vectorX nevertheless yields defined TorusPipe"); // default vec is used! pipeBad = TorusPipe.createDgnTorusPipe(center, vectorX, Vector3d.createZero(), majorRadius, minorRadius, sweep, capped); - ck.testDefined(pipeBad, "Zero vectorY nevertheless yields defined TorusPipe"); // default vec is used! + ck.testDefined(pipeBad, "Zero vectorY nevertheless yields defined TorusPipe"); // default vec is used! pipeBad = TorusPipe.createDgnTorusPipe(center, vectorX, vectorY, 0, minorRadius, sweep, capped); ck.testUndefined(pipeBad, "Zero majorRadius yields undefined TorusPipe"); pipeBad = TorusPipe.createDgnTorusPipe(center, vectorX, vectorY, majorRadius, 0, sweep, capped); @@ -105,9 +110,11 @@ describe("PipePath", () => { const pipeScaledRadii = TorusPipe.createDgnTorusPipe(center, xAxis, yAxis, majorRadius * scale.x, minorRadius * scale.y, sweep, capped); if (!ck.testDefined(pipeScaledRadii)) continue; - if (!ck.testCoordinate(1, pipeScaledRadii.cloneVectorX().magnitude(), "TorusPipe.cloneVectorX returns unit vector") || + if ( + !ck.testCoordinate(1, pipeScaledRadii.cloneVectorX().magnitude(), "TorusPipe.cloneVectorX returns unit vector") || !ck.testCoordinate(1, pipeScaledRadii.cloneVectorY().magnitude(), "TorusPipe.cloneVectorY returns unit vector") || - !ck.testCoordinate(1, pipeScaledRadii.cloneVectorZ().magnitude(), "TorusPipe.cloneVectorZ returns unit vector")) + !ck.testCoordinate(1, pipeScaledRadii.cloneVectorZ().magnitude(), "TorusPipe.cloneVectorZ returns unit vector") + ) continue; let builder = PolyfaceBuilder.create(options); builder.addTorusPipe(pipeScaledRadii, 20, 20); @@ -119,14 +126,19 @@ describe("PipePath", () => { // localToWorld (getConstructiveFrame), and so does v.v. See IModelJsonWriter.handleTorusPipe and IModelJsonReader.parseTorusPipe. // This discrepancy can be seen in output: the pre-conversion mesh exhibits non-uniform scale, but not the post-conversion pipe. const scaleInLocalCoords = Transform.createOriginAndMatrix(Point3d.createZero(), Matrix3d.createScale(scale.x, scale.x, scale.y)); - const scaleInWorldCoords = pipe0.cloneLocalToWorld().multiplyTransformTransform(scaleInLocalCoords.multiplyTransformTransform(pipe0.cloneLocalToWorld().inverse()!)); + const scaleInWorldCoords = pipe0.cloneLocalToWorld().multiplyTransformTransform( + scaleInLocalCoords.multiplyTransformTransform(pipe0.cloneLocalToWorld().inverse()!), + ); const pipeCloneScaled = pipe0.cloneTransformed(scaleInWorldCoords); if (!ck.testDefined(pipeCloneScaled)) continue; builder = PolyfaceBuilder.create(options); builder.addTorusPipe(pipeCloneScaled, 20, 20); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [pipeCloneScaled, builder.claimPolyface()], x0, y0, z0); - ck.testTrue(pipeScaledRadii.isAlmostEqual(pipeCloneScaled), "TorusPipe with scaled radii is equivalent to TorusPipe cloned with scale transform"); + ck.testTrue( + pipeScaledRadii.isAlmostEqual(pipeCloneScaled), + "TorusPipe with scaled radii is equivalent to TorusPipe cloned with scale transform", + ); // Clone radii-scaled TorusPipe with inverse of scale transform, and compare with original. const unScaleInWorldCoords = scaleInWorldCoords.inverse()!; @@ -136,7 +148,10 @@ describe("PipePath", () => { builder = PolyfaceBuilder.create(options); builder.addTorusPipe(pipeCloneUnScaled0, 20, 20); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [pipeCloneUnScaled0, builder.claimPolyface()], x0, y0, z0); - ck.testTrue(pipe0.isAlmostEqual(pipeCloneUnScaled0), "TorusPipe with scaled radii cloned with reciprocal scale transform is equivalent to original"); + ck.testTrue( + pipe0.isAlmostEqual(pipeCloneUnScaled0), + "TorusPipe with scaled radii cloned with reciprocal scale transform is equivalent to original", + ); // Clone scale-transformed TorusPipe with inverse of scale transform, and compare with original. const pipeCloneUnScaled1 = pipeCloneScaled.cloneTransformed(unScaleInWorldCoords); @@ -145,7 +160,10 @@ describe("PipePath", () => { builder = PolyfaceBuilder.create(options); builder.addTorusPipe(pipeCloneUnScaled1, 20, 20); GeometryCoreTestIO.captureCloneGeometry(allGeometry, [pipeCloneUnScaled1, builder.claimPolyface()], x0, y0, z0); - ck.testTrue(pipe0.isAlmostEqual(pipeCloneUnScaled1), "TorusPipe cloned with scale transform then cloned with inverse is equivalent to original"); + ck.testTrue( + pipe0.isAlmostEqual(pipeCloneUnScaled1), + "TorusPipe cloned with scale transform then cloned with inverse is equivalent to original", + ); } y0 += 10; } diff --git a/core/geometry/src/test/solid/Solid.test.ts b/core/geometry/src/test/solid/Solid.test.ts index c8b307c41bc9..cc31640a828b 100644 --- a/core/geometry/src/test/solid/Solid.test.ts +++ b/core/geometry/src/test/solid/Solid.test.ts @@ -81,20 +81,28 @@ function exerciseSolids(ck: Checker, solids: GeometryQuery[], _name: string) { const rangeScaled = Range3d.create(); s.extendRange(rangeScaled, scaleTransform); const rangeScaledExpanded = rangeScaled.clone(); - rangeScaledExpanded.expandInPlace(0.10 * rangeScaledExpanded.diagonal().magnitude()); // HACK -- ranges are not precise. Allow fuzz. + rangeScaledExpanded.expandInPlace(0.10 * rangeScaledExpanded.diagonal().magnitude()); // HACK -- ranges are not precise. Allow fuzz. const range2 = Range3d.create(); s2.extendRange(range2); - if (!ck.testTrue(rangeScaledExpanded.containsRange(range2), "scaled range of solid commutes with range of scaled solid", - rangeScaledExpanded.low.toJSON(), - range2.low.toJSON(), - range2.high.toJSON(), - rangeScaledExpanded.high.toJSON())) { + if ( + !ck.testTrue( + rangeScaledExpanded.containsRange(range2), + "scaled range of solid commutes with range of scaled solid", + rangeScaledExpanded.low.toJSON(), + range2.low.toJSON(), + range2.high.toJSON(), + rangeScaledExpanded.high.toJSON(), + ) + ) { const allGeometry: GeometryQuery[] = []; - GeometryCoreTestIO.captureCloneGeometry(allGeometry, - [s, Box.createRange(range, true)!, - Box.createRange(rangeScaled, true)!, - Box.createRange(rangeScaledExpanded, true)!, - s2, Box.createRange(range2, true)!]); + GeometryCoreTestIO.captureCloneGeometry(allGeometry, [ + s, + Box.createRange(range, true)!, + Box.createRange(rangeScaled, true)!, + Box.createRange(rangeScaledExpanded, true)!, + s2, + Box.createRange(range2, true)!, + ]); GeometryCoreTestIO.saveGeometry(allGeometry, "Solid", "ExerciseSolids"); // compute ranges again to debug failure const myRangeScaled = Range3d.create(); @@ -139,9 +147,12 @@ describe("Solids", () => { // create true cones to allow simple checks ... const ck = new Checker(); - for (const cone of [ - Cone.createAxisPoints(Point3d.create(0, 0, 0), Point3d.create(0, 0, 1), 1, 0, false)!, - Cone.createAxisPoints(Point3d.create(1, 3, 2), Point3d.create(3, 9, 2), 4, 2, false)!]) { + for ( + const cone of [ + Cone.createAxisPoints(Point3d.create(0, 0, 0), Point3d.create(0, 0, 1), 1, 0, false)!, + Cone.createAxisPoints(Point3d.create(1, 3, 2), Point3d.create(3, 9, 2), 4, 2, false)!, + ] + ) { for (const u of [0.0, 0.25, 1.0]) { const plane0 = cone.uvFractionToPointAndTangents(u, 0.0); const plane1 = cone.uvFractionToPointAndTangents(u, 1.0); @@ -223,16 +234,41 @@ describe("Solids", () => { const allGeometry: GeometryQuery[] = []; const origin = Point3d.createZero(); const radius = 2.0; - const spheres = [Sphere.createCenterRadius(origin, radius), Sphere.createCenterRadius(origin, radius, AngleSweep.createStartEndDegrees(0, 45)), Sphere.createCenterRadius(origin, radius, AngleSweep.createStartEndDegrees(0, -45))]; + const spheres = [ + Sphere.createCenterRadius(origin, radius), + Sphere.createCenterRadius(origin, radius, AngleSweep.createStartEndDegrees(0, 45)), + Sphere.createCenterRadius(origin, radius, AngleSweep.createStartEndDegrees(0, -45)), + ]; const options = StrokeOptions.createForFacets(); options.needNormals = true; let x0 = 0; const y0 = 0; for (const sphere of spheres) { transformAndFacet(allGeometry, sphere, Transform.createIdentity(), options, x0, y0); - transformAndFacet(allGeometry, sphere, Transform.createFixedPointAndMatrix(Point3d.create(radius, 0, 0), Matrix3d.createDirectionalScale(Vector3d.unitX(), -1.0)), options, x0, y0); - transformAndFacet(allGeometry, sphere, Transform.createFixedPointAndMatrix(Point3d.create(0, radius, 0), Matrix3d.createDirectionalScale(Vector3d.unitY(), -1.0)), options, x0, y0); - transformAndFacet(allGeometry, sphere, Transform.createFixedPointAndMatrix(Point3d.create(0, 0, radius), Matrix3d.createDirectionalScale(Vector3d.unitZ(), -1.0)), options, x0, y0); + transformAndFacet( + allGeometry, + sphere, + Transform.createFixedPointAndMatrix(Point3d.create(radius, 0, 0), Matrix3d.createDirectionalScale(Vector3d.unitX(), -1.0)), + options, + x0, + y0, + ); + transformAndFacet( + allGeometry, + sphere, + Transform.createFixedPointAndMatrix(Point3d.create(0, radius, 0), Matrix3d.createDirectionalScale(Vector3d.unitY(), -1.0)), + options, + x0, + y0, + ); + transformAndFacet( + allGeometry, + sphere, + Transform.createFixedPointAndMatrix(Point3d.create(0, 0, radius), Matrix3d.createDirectionalScale(Vector3d.unitZ(), -1.0)), + options, + x0, + y0, + ); x0 += 5.0 * radius; } GeometryCoreTestIO.saveGeometry(allGeometry, "Solid", "TransformedSpheres"); @@ -243,7 +279,11 @@ describe("Solids", () => { const ck = new Checker(); const origin = Point3d.createZero(); const radii = Point3d.create(1, 3, 4); - const ellipsoid = Sphere.createEllipsoid(Transform.createFixedPointAndMatrix(origin, Matrix3d.createScale(radii.x, radii.y, radii.z)), AngleSweep.create(), false); + const ellipsoid = Sphere.createEllipsoid( + Transform.createFixedPointAndMatrix(origin, Matrix3d.createScale(radii.x, radii.y, radii.z)), + AngleSweep.create(), + false, + ); testGeometryQueryRoundTrip(ck, ellipsoid); expect(ck.getNumErrors()).toBe(0); }); @@ -302,13 +342,13 @@ describe("Solids", () => { const frameA = Transform.createOriginAndMatrix(Point3d.create(1, 2, 3), Matrix3d.createScale(1, 1, 1)); const frameB = Transform.createOriginAndMatrix(Point3d.create(1, 2, 3), Matrix3d.createScale(1, 1, -1)); // with negative determinant to trigger reversal logic const torusA = TorusPipe.createInFrame(frameA, 3, 1, halfSweep, true); - const torusB = TorusPipe.createInFrame(frameB, 3, 1, halfSweep, true); // z will be reverse so that it matches torusA! + const torusB = TorusPipe.createInFrame(frameB, 3, 1, halfSweep, true); // z will be reverse so that it matches torusA! ck.testPointer(torusA); ck.testPointer(torusB); ck.testTrue(torusA!.isAlmostEqual(torusB!)); const negativeSweep = Angle.createDegrees(-10); const torusC = TorusPipe.createInFrame(frameA, 3, 1, negativeSweep, true)!; - ck.testTrue(torusC.getSweepAngle().degrees > 0.0); // confirm that the angle got reversed + ck.testTrue(torusC.getSweepAngle().degrees > 0.0); // confirm that the angle got reversed expect(ck.getNumErrors()).toBe(0); }); @@ -316,7 +356,12 @@ describe("Solids", () => { it("TorusPipeNonCircular", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const nonCircularArc = Arc3d.create(Point3d.create(-0.003571875), Vector3d.create(-0.001190625, 0.127), Vector3d.create(0.001190625, 0, 0.127), AngleSweep.createStartEndDegrees(0, 90)); + const nonCircularArc = Arc3d.create( + Point3d.create(-0.003571875), + Vector3d.create(-0.001190625, 0.127), + Vector3d.create(0.001190625, 0, 0.127), + AngleSweep.createStartEndDegrees(0, 90), + ); ck.testFalse(nonCircularArc.isCircular, "expect slightly non-circular arc"); const seg0 = LineSegment3d.create(nonCircularArc.center, Point3d.createAdd2Scaled(nonCircularArc.center, 1, nonCircularArc.vector0, 1)); const seg1 = LineSegment3d.create(nonCircularArc.center, Point3d.createAdd2Scaled(nonCircularArc.center, 1, nonCircularArc.vector90, 1)); @@ -325,7 +370,10 @@ describe("Solids", () => { const solid = TorusPipe.createAlongArc(nonCircularArc, diam / 2, true); if (ck.testDefined(solid, "created torus pipe")) { GeometryCoreTestIO.captureCloneGeometry(allGeometry, solid); - ck.testTrue(solid.cloneLocalToWorld().matrix.isRigid(false), "TorusPipe.createAlongArc forced arc circularity by squaring its axes and equating their lengths"); + ck.testTrue( + solid.cloneLocalToWorld().matrix.isRigid(false), + "TorusPipe.createAlongArc forced arc circularity by squaring its axes and equating their lengths", + ); const vec0Near = solid.cloneVectorX().scale(solid.getMajorRadius()).isAlmostEqual(nonCircularArc.vector0); const vec90Near = solid.cloneVectorY().scale(solid.getMajorRadius()).isAlmostEqual(nonCircularArc.vector90, 0.000012); ck.testTrue(vec0Near && vec90Near, "TorusPipe frame is near the original arc's frame"); @@ -358,7 +406,8 @@ describe("Solids", () => { Transform.createTranslationXYZ(0, 20, 0), Transform.createTranslationXYZ(20, 0, 0), // Maybe harder than first pass because dx changes? Transform.createOriginAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createUniformScale(2)), - Transform.createOriginAndMatrix(Point3d.create(0, 10, 0), Matrix3d.createUniformScale(2))]; + Transform.createOriginAndMatrix(Point3d.create(0, 10, 0), Matrix3d.createUniformScale(2)), + ]; const allGeometry: GeometryQuery[] = []; let dy = 0; const unitBox = Sample.createRangeEdges(Range3d.createXYZXYZ(0, 0, 0, 1, 3, 0.25))!; @@ -367,7 +416,7 @@ describe("Solids", () => { GeometryCoreTestIO.captureGeometry(allGeometry, s.clone(), 0, 0); } */ - for (let sampleIndex = 0; sampleIndex < sweeps.length; sampleIndex += 2) { // increment by 2 to skip cap variants + for (let sampleIndex = 0; sampleIndex < sweeps.length; sampleIndex += 2) { // increment by 2 to skip cap variants let dx = 100; const s = sweeps[sampleIndex]; // GeometryCoreTestIO.captureGeometry(allGeometry, s.clone(), 0, 0); @@ -483,12 +532,15 @@ describe("CurveCurve", () => { type AnnouncePolyface = (source: GeometryQuery, polyface: IndexedPolyface) => void; // output the geometry, then its facets shifted vertically. // return the geometry range -function transformAndFacet(allGeometry: GeometryQuery[], +function transformAndFacet( + allGeometry: GeometryQuery[], g: GeometryQuery, transform: Transform | undefined, options: StrokeOptions | undefined, - x0: number, y0: number, - announcePolyface?: AnnouncePolyface): Range3d { + x0: number, + y0: number, + announcePolyface?: AnnouncePolyface, +): Range3d { const g1 = transform ? g.cloneTransformed(transform) : g; if (g1) { const builder = PolyfaceBuilder.create(options); diff --git a/core/geometry/src/test/topology/ChainCollector.test.ts b/core/geometry/src/test/topology/ChainCollector.test.ts index 810280a06529..75c083684554 100644 --- a/core/geometry/src/test/topology/ChainCollector.test.ts +++ b/core/geometry/src/test/topology/ChainCollector.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; -import { AnyCurve } from "../../curve/CurveTypes"; +import { describe, expect, it } from "vitest"; import { BagOfCurves, CurveChain, CurveCollection } from "../../curve/CurveCollection"; import { CurveOps } from "../../curve/CurveOps"; +import { AnyCurve } from "../../curve/CurveTypes"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; @@ -16,26 +16,36 @@ import { JointOptions } from "../../curve/OffsetOptions"; import { Path } from "../../curve/Path"; import { RegionOps } from "../../curve/RegionOps"; import { Geometry } from "../../Geometry"; +import { Vector3d } from "../../geometry3d/Point3dVector3d"; import { PolygonOps } from "../../geometry3d/PolygonOps"; import { PolylineOps } from "../../geometry3d/PolylineOps"; import { Range3d } from "../../geometry3d/Range"; import { Sample, SteppedIndexFunctionFactory } from "../../serialization/GeometrySamples"; import { IModelJson } from "../../serialization/IModelJsonSchema"; +import { ChainMergeContext } from "../../topology/ChainMerge"; import { Checker } from "../Checker"; import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; -import { ChainMergeContext } from "../../topology/ChainMerge"; -import { Vector3d } from "../../geometry3d/Point3dVector3d"; const chainCollectorInputDirectory = "./src/test/data/ChainCollector/"; const noOffset0 = "aecc_alignment"; describe("ChainCollector", () => { - it("OffsetExamples", () => { const ck = new Checker(); let xOut = 0; let y0 = 0; - for (const filename of ["fillet00", "aecc_alignment", "linestring01", "boomerang.incompleteOffset", "boomerang.noOffsetsWithThisOrder", - "boomerang", "rectangle00", "linestrings", "MBDenseCurvesToOffset"]) { + for ( + const filename of [ + "fillet00", + "aecc_alignment", + "linestring01", + "boomerang.incompleteOffset", + "boomerang.noOffsetsWithThisOrder", + "boomerang", + "rectangle00", + "linestrings", + "MBDenseCurvesToOffset", + ] + ) { const allGeometry: GeometryQuery[] = []; const stringData = fs.readFileSync(`${chainCollectorInputDirectory}${filename}.imjs`, "utf8"); if (stringData) { @@ -157,13 +167,16 @@ describe("ChainCollector", () => { const xShift = 20.0; const yShift = 20.0; const offsetDistance = 0.5; - const reversePhase = [8, 5]; // reverse primitives if their index modulo anything here is reverseShift + const reversePhase = [8, 5]; // reverse primitives if their index modulo anything here is reverseShift const reverseShift = 3; for (const numPrimitive of [5, 6, 30, 60]) { let y0 = 0; const shuffledPrimitives = []; - const circlePoints = Sample.createPointsByIndexFunctions(numPrimitive, - SteppedIndexFunctionFactory.createCosine(6.0), SteppedIndexFunctionFactory.createSine(8.0)); + const circlePoints = Sample.createPointsByIndexFunctions( + numPrimitive, + SteppedIndexFunctionFactory.createCosine(6.0), + SteppedIndexFunctionFactory.createSine(8.0), + ); // make primitives in simple order around the ellipse .. const sequentialPrimitives = []; for (let i = 0; i + 1 < circlePoints.length; i++) @@ -247,13 +260,14 @@ describe("ChainMerge", () => { it("ChainMergeVariants", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; - const e = 1; // Really big blob tolerance !!! + const e = 1; // Really big blob tolerance !!! // line segments of a unit square with gap "e" at the beginning of each edge. const segments = [ LineSegment3d.createXYXY(e, 0, 10, 0), LineSegment3d.createXYXY(10, e, 10, 10), LineSegment3d.createXYXY(10 - e, 10, 0, 10), - LineSegment3d.createXYXY(0, 10 - e, 0, 0)]; + LineSegment3d.createXYXY(0, 10 - e, 0, 0), + ]; let dy = 20.0; for (const tol of [0.0001 * e, 2.0 * e]) { // Create the context with the worst possible sort direction -- trigger N^2 search @@ -261,7 +275,8 @@ describe("ChainMerge", () => { { tolerance: tol, primarySortDirection: Vector3d.create(0, 0, 1), - }); + }, + ); chainMergeContext.addLineSegment3dArray(segments); chainMergeContext.clusterAndMergeVerticesXYZ(); const chains = chainMergeContext.collectMaximalChains(); diff --git a/core/geometry/src/test/topology/CurveWireOffset.test.ts b/core/geometry/src/test/topology/CurveWireOffset.test.ts index 42d3cadaa334..d90cb2253994 100644 --- a/core/geometry/src/test/topology/CurveWireOffset.test.ts +++ b/core/geometry/src/test/topology/CurveWireOffset.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { Arc3d } from "../../curve/Arc3d"; -import { AnyCurve } from "../../curve/CurveTypes"; import { CurveChain } from "../../curve/CurveCollection"; +import { AnyCurve } from "../../curve/CurveTypes"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; @@ -30,10 +30,7 @@ import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; * @param distances offset distances * @param distanceFactor factor to apply to distances. */ -function testCurveOffset(allPaths: AnyCurve[], - caseName: string, - distances: number[], - distanceFactor: number) { +function testCurveOffset(allPaths: AnyCurve[], caseName: string, distances: number[], distanceFactor: number) { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; let x0 = 0; @@ -47,11 +44,13 @@ function testCurveOffset(allPaths: AnyCurve[], const yStep = 2.0 * range.yLength() + 1; y0 = 0.0; GeometryCoreTestIO.captureCloneGeometry(allGeometry, path, x0, y0, 0); - for (const options of [ - JointOptions.create(1), - new JointOptions(1.0, 180, 30.0), - new JointOptions(1.0, 1.0, 30.0), - ]) { + for ( + const options of [ + JointOptions.create(1), + new JointOptions(1.0, 180, 30.0), + new JointOptions(1.0, 1.0, 30.0), + ] + ) { let dMax = 0; GeometryCoreTestIO.captureCloneGeometry(allGeometry, path, x0, y0, 0); for (const offsetDistance of distances) { @@ -71,13 +70,14 @@ function testCurveOffset(allPaths: AnyCurve[], } describe("CurveOffset", () => { - it("SimplePaths", () => { let counter = 0; - for (const paths of [ - Sample.createSimplePaths(false), - Sample.createLineArcPaths(), - ]) { + for ( + const paths of [ + Sample.createSimplePaths(false), + Sample.createLineArcPaths(), + ] + ) { const a = paths[0].range().xLength() * 0.02; const offsetDistances = [2 * a, a, -a, -2 * a]; testCurveOffset(paths, `SimplePaths ${counter++}`, offsetDistances, 1.0); @@ -86,9 +86,11 @@ describe("CurveOffset", () => { it("SimpleLoops", () => { let counter = 0; - for (const paths of [ - Sample.createSimpleLoops(), - ]) { + for ( + const paths of [ + Sample.createSimpleLoops(), + ] + ) { const a = paths[0].range().xLength() * 0.02; const offsetDistances = [2 * a, a, -a, -2 * a]; testCurveOffset(paths, `SimpleLoops ${counter++}`, offsetDistances, 1.0); @@ -98,10 +100,13 @@ describe("CurveOffset", () => { it("SawtoothPaths", () => { let counter = 0; const paths = []; - for (const pointPath of [ - Sample.appendVariableSawTooth([], 1, 0, 1, 2, 4, 0.8), - Sample.appendVariableSawTooth([], 1, 0.5, 1, 2, 4, 0.8), - Sample.appendVariableSawTooth([], 3, -0.5, 1, 2, 4, 0.8)]) { + for ( + const pointPath of [ + Sample.appendVariableSawTooth([], 1, 0, 1, 2, 4, 0.8), + Sample.appendVariableSawTooth([], 1, 0.5, 1, 2, 4, 0.8), + Sample.appendVariableSawTooth([], 3, -0.5, 1, 2, 4, 0.8), + ] + ) { paths.push(Path.create(LineString3d.create(pointPath))); } @@ -109,15 +114,17 @@ describe("CurveOffset", () => { const offsetDistances = [2 * a, a, -a, -2 * a]; // const offsetDistances = [a]; testCurveOffset(paths, `SawtoothPaths ${counter++}`, offsetDistances, 1.0); - }); it("FractalPaths", () => { let counter = 0; const paths = []; - for (const pointPath of [ - Sample.createFractalDiamondConvexPattern(1, -0.5), - Sample.createFractalHatReversingPattern(1, 0.25)]) { + for ( + const pointPath of [ + Sample.createFractalDiamondConvexPattern(1, -0.5), + Sample.createFractalHatReversingPattern(1, 0.25), + ] + ) { paths.push(Path.create(LineString3d.create(pointPath))); } @@ -125,7 +132,6 @@ describe("CurveOffset", () => { const offsetDistances = [2 * a, a, -a, -2 * a]; // const offsetDistances = [a]; testCurveOffset(paths, `FractalPaths ${counter++}`, offsetDistances, 1.0); - }); // cspell:word Daumantas it("Daumantas", () => { @@ -141,7 +147,6 @@ describe("CurveOffset", () => { const offsetDistances = [a, -a]; // const offsetDistances = [a]; testCurveOffset([path0], `Daumantas ${counter++}`, offsetDistances, 1.0); - }); it("OffsetGap10", () => { let counter = 10; @@ -151,13 +156,14 @@ describe("CurveOffset", () => { // const offsetDistances = [a]; testCurveOffset([path0], `OffsetGap ${counter++}`, offsetDistances, 1.0); } - }); it("OffsetGap", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const path = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/ChainCollector/gapAtSmallShift.imjs", "utf8")))!; + "./src/test/data/ChainCollector/gapAtSmallShift.imjs", + "utf8", + )))!; if (ck.testType(path, CurveChain)) { const x0 = 0; const y0 = 0; @@ -177,7 +183,7 @@ describe("CurveOffset", () => { const allGeometry: GeometryQuery[] = []; const offset = 0.5; let x0 = 0; - const z1 = 0.04; // to place center geometry above filled loops. + const z1 = 0.04; // to place center geometry above filled loops. const pointA = Point3d.create(0, 0); const pointB = Point3d.create(4, 0); const e = 0.1; @@ -189,12 +195,21 @@ describe("CurveOffset", () => { const arcC = arcA.clonePartialCurve(1.0, 0.0); arcC.tryTransformInPlace(Transform.createFixedPointAndMatrix(arcA.center, Matrix3d.createScale(sC, sC, sC))); const path2 = Loop.create(arcA, arcB); - const path3 = Loop.create(LineString3d.create(pointA, pointB, pointA.interpolatePerpendicularXY(1.0, pointB, -f), - pointA.interpolatePerpendicularXY(0, pointB, -f), pointA)); - const path4 = Loop.create(arcA, + const path3 = Loop.create( + LineString3d.create( + pointA, + pointB, + pointA.interpolatePerpendicularXY(1.0, pointB, -f), + pointA.interpolatePerpendicularXY(0, pointB, -f), + pointA, + ), + ); + const path4 = Loop.create( + arcA, LineSegment3d.create(arcA.endPoint(), arcC.startPoint()), arcC, - LineSegment3d.create(arcC.endPoint(), arcA.startPoint())); + LineSegment3d.create(arcC.endPoint(), arcA.startPoint()), + ); // construct offset for ... // a) primitive (one way only) // b) primitive + reversed primitive @@ -212,5 +227,4 @@ describe("CurveOffset", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "CurveOffset", "TrivialPath"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/topology/Graph.test.ts b/core/geometry/src/test/topology/Graph.test.ts index 2d082ff29d53..c06ebb4f8a6a 100644 --- a/core/geometry/src/test/topology/Graph.test.ts +++ b/core/geometry/src/test/topology/Graph.test.ts @@ -9,19 +9,19 @@ import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; import { Geometry } from "../../Geometry"; import { Angle } from "../../geometry3d/Angle"; -import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Point2d } from "../../geometry3d/Point2dVector2d"; +import { Point3d, Vector3d } from "../../geometry3d/Point3dVector3d"; import { Transform } from "../../geometry3d/Transform"; import { HalfEdge, HalfEdgeGraph, HalfEdgeMask, NodeFunction } from "../../topology/Graph"; import { HalfEdgeGraphSearch } from "../../topology/HalfEdgeGraphSearch"; import { HalfEdgeMaskValidation, HalfEdgePointerInspector } from "../../topology/HalfEdgeGraphValidation"; -import { HalfEdgeGraphMerge } from "../../topology/Merging"; -import { Checker } from "../Checker"; -import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; import { NodeXYZUV } from "../../topology/HalfEdgeNodeXYZUV"; import { HalfEdgePositionDetail, HalfEdgeTopo } from "../../topology/HalfEdgePositionDetail"; import { InsertAndRetriangulateContext } from "../../topology/InsertAndRetriangulateContext"; +import { HalfEdgeGraphMerge } from "../../topology/Merging"; +import { Checker } from "../Checker"; import { OutputManager } from "../clipping/ClipPlanes.test"; +import { GeometryCoreTestIO } from "../GeometryCoreTestIO"; function logGraph(graph: HalfEdgeGraph, title: any): void { GeometryCoreTestIO.consoleLog(` == begin == ${title}`); @@ -33,7 +33,10 @@ function logGraph(graph: HalfEdgeGraph, title: any): void { export class GraphChecker { public static captureAnnotatedGraph( - data: GeometryQuery[], graph: HalfEdgeGraph | undefined, dx: number = 0, dy: number = 0, + data: GeometryQuery[], + graph: HalfEdgeGraph | undefined, + dx: number = 0, + dy: number = 0, ): void { if (graph === undefined) return; @@ -136,7 +139,6 @@ export class GraphChecker { } GeometryCoreTestIO.consoleLog(`**VERTEX LOOPS ${vertices.length}`); GeometryCoreTestIO.consoleLog(vData); - } /** * Test different mask methods. @@ -170,18 +172,26 @@ export class GraphChecker { const numNodesAroundVertex = node.countEdgesAroundVertex(); const numNodesAroundFace = node.countEdgesAroundFace(); ck.testExactNumber( - numNodesAroundVertex, node.countMaskAroundVertex(mask1, false), "count unmasked around vertex", + numNodesAroundVertex, + node.countMaskAroundVertex(mask1, false), + "count unmasked around vertex", ); ck.testExactNumber( - numNodesAroundFace, node.countMaskAroundFace(mask1, false), "count unmasked around face", + numNodesAroundFace, + node.countMaskAroundFace(mask1, false), + "count unmasked around face", ); node.setMaskAroundVertex(mask1); ck.testExactNumber( - numNodesAroundFace - 1, node.countMaskAroundFace(mask1, false), "count unmasked around face after vertex set", + numNodesAroundFace - 1, + node.countMaskAroundFace(mask1, false), + "count unmasked around face after vertex set", ); const nodesAroundVertex = node.collectAroundVertex(); ck.testExactNumber( - numNodesAroundVertex, nodesAroundVertex.length, "count nodes == collected array length", + numNodesAroundVertex, + nodesAroundVertex.length, + "count nodes == collected array length", ); const masksAroundVertex = node.countMaskAroundVertex(mask1); ck.testExactNumber(nodesAroundVertex.length, masksAroundVertex); @@ -286,7 +296,8 @@ export class GraphChecker { result.nearZeroFaces.push(face); else if (area > 0.0) result.positiveFaces.push(face); - else /* strict negative */ + /* strict negative */ + else result.negativeFaces.push(face); result.absAreaSum += Math.abs(area); result.zeroAreaTolerance = 1.0e-12 * result.absAreaSum; @@ -294,7 +305,8 @@ export class GraphChecker { return result; } public static verifySignedFaceCounts( - ck: Checker, graph: HalfEdgeGraph, + ck: Checker, + graph: HalfEdgeGraph, numPositive: number | undefined, numNegative: number | undefined, numNearZero: number | undefined, @@ -362,7 +374,9 @@ describe("VUGraph", () => { GeometryCoreTestIO.saveGeometry(geometry, "Graph", "GridFixup"); const componentsB = HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( - graph, undefined, HalfEdgeMask.EXTERIOR, + graph, + undefined, + HalfEdgeMask.EXTERIOR, ); ck.testTrue( HalfEdgeMaskValidation.isMaskConsistentAroundAllFaces(graph, HalfEdgeMask.EXTERIOR), diff --git a/core/geometry/src/test/topology/HalfEdgeGraphFromIndexedLoopsContext.test.ts b/core/geometry/src/test/topology/HalfEdgeGraphFromIndexedLoopsContext.test.ts index 0cf5049146f0..ac65e464aa85 100644 --- a/core/geometry/src/test/topology/HalfEdgeGraphFromIndexedLoopsContext.test.ts +++ b/core/geometry/src/test/topology/HalfEdgeGraphFromIndexedLoopsContext.test.ts @@ -19,9 +19,11 @@ function checkCounts(ck: Checker, graph: HalfEdgeGraph, message: string, numVert const numVerticesA = graph.countVertexLoops(); const numNodesA = graph.countNodes(); const numFacesA = graph.countFaceLoops(); - if (!ck.testExactNumber(numVertices, numVerticesA, "numVertices") + if ( + !ck.testExactNumber(numVertices, numVerticesA, "numVertices") || !ck.testExactNumber(2 * numEdges, numNodesA, "numEdges") // (There are two nodes per edge) - || !ck.testExactNumber(numFaces, numFacesA, "numFaces")) { + || !ck.testExactNumber(numFaces, numFacesA, "numFaces") + ) { GeometryCoreTestIO.consoleLog(message); GeometryCoreTestIO.consoleLog({ numVerticesA, numNodesA, numFacesA }); GraphChecker.dumpGraph(graph); @@ -34,15 +36,23 @@ describe("HalfEdgeGraphFromIndexedLoopsContext", () => { let expectedFaces = 0; let expectedEdges = 0; let expectedVertices = 0; - builder.insertLoop([1, 2, 3]); expectedFaces += 2; expectedEdges += 3; expectedVertices += 3; + builder.insertLoop([1, 2, 3]); + expectedFaces += 2; + expectedEdges += 3; + expectedVertices += 3; checkCounts(ck, builder.graph, "After first insertLoop", expectedVertices, expectedEdges, expectedFaces); - builder.insertLoop([3, 2, 5]); expectedFaces++; expectedEdges += 2; expectedVertices += 1; + builder.insertLoop([3, 2, 5]); + expectedFaces++; + expectedEdges += 2; + expectedVertices += 1; checkCounts(ck, builder.graph, "After second insertLoop", expectedVertices, expectedEdges, expectedFaces); - builder.insertLoop([5, 2, 1, 6, 7]); expectedFaces++; expectedEdges += 3; expectedVertices += 2; + builder.insertLoop([5, 2, 1, 6, 7]); + expectedFaces++; + expectedEdges += 3; + expectedVertices += 2; if (Checker.noisy.halfEdgeGraphFromIndexedLoops) GraphChecker.dumpGraph(builder.graph, formatNodeForDump); checkCounts(ck, builder.graph, "After third insertLoop", expectedVertices, expectedEdges, expectedFaces); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/topology/HalfEdgeGraphSearch.test.ts b/core/geometry/src/test/topology/HalfEdgeGraphSearch.test.ts index 4d25a39e30ed..7d93a3789e17 100644 --- a/core/geometry/src/test/topology/HalfEdgeGraphSearch.test.ts +++ b/core/geometry/src/test/topology/HalfEdgeGraphSearch.test.ts @@ -55,7 +55,9 @@ describe("HalfEdgeGraphSearch", () => { node11.setMaskAroundFace(HalfEdgeMask.BOUNDARY_EDGE); const connectedComponents = HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( - graph, new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR, + graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, ); ck.testExactNumber(connectedComponents.length, 2); ck.testExactNumber(connectedComponents[0].length, 3); @@ -212,7 +214,7 @@ describe("HalfEdgeGraphSearch", () => { * (boundary edge should have exterior mask on its outer half edge). This will cover * the last break in function HalfEdgeGraphSearch.collectExtendedBoundaryLoopFromSeed. * Without that break code would trap in an infinite loop. - */ + */ // node7.setMask(HalfEdgeMask.EXTERIOR); const node8 = graph.addEdgeXY(3, 1, 1, 1); const node9 = node8.faceSuccessor; diff --git a/core/geometry/src/test/topology/HalfEdgeGraphSpineContext.test.ts b/core/geometry/src/test/topology/HalfEdgeGraphSpineContext.test.ts index 18c3031e78cc..c1d8763acb8d 100644 --- a/core/geometry/src/test/topology/HalfEdgeGraphSpineContext.test.ts +++ b/core/geometry/src/test/topology/HalfEdgeGraphSpineContext.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { Loop } from "../../curve/Loop"; @@ -43,7 +43,6 @@ function loadSpineGraph(context: HalfEdgeGraphSpineContext, data: any) { loadSpineGraph(context, child); } } - } function testSpineLoop(allGeometry: GeometryQuery[], loopPoints: any, x0: number, y0: number) { const range = RegionOps.curveArrayRange(loopPoints); @@ -51,7 +50,12 @@ function testSpineLoop(allGeometry: GeometryQuery[], loopPoints: any, x0: number const yStep = Math.floor(range.yLength()) + 2; GeometryCoreTestIO.captureCloneGeometry(allGeometry, loopPoints, x0, y0, 0); RegularizationContext.announceEdge = (_graph: HalfEdgeGraph, nodeA: HalfEdge, nodeB: HalfEdge, scale: number) => { - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYXY(nodeA.x * scale, nodeA.y * scale, nodeB.x * scale, nodeB.y * scale), x0, y0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.createXYXY(nodeA.x * scale, nodeA.y * scale, nodeB.x * scale, nodeB.y * scale), + x0, + y0, + ); }; const context = new HalfEdgeGraphSpineContext(); loadSpineGraph(context, loopPoints); @@ -71,7 +75,6 @@ function testSpineLoop(allGeometry: GeometryQuery[], loopPoints: any, x0: number } describe("HalfEdgeGraphSpineContext", () => { - it("SmallGraph", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -80,13 +83,14 @@ describe("HalfEdgeGraphSpineContext", () => { const ax = 8; const ay = 4; const bx = 4; - testSpineLoop(allGeometry, + testSpineLoop( + allGeometry, [Point3d.create(0, 0), Point3d.create(ax, 0), Point3d.create(ax, ay), Point3d.create(0, ay), Point3d.create(0, 0)], - x0, 0); + x0, + 0, + ); x0 += ax + 2; - testSpineLoop(allGeometry, - [Point3d.create(0, 0), Point3d.create(ax, 0), Point3d.create(bx, ay), Point3d.create(0, 0)], - x0, 0); + testSpineLoop(allGeometry, [Point3d.create(0, 0), Point3d.create(ax, 0), Point3d.create(bx, ay), Point3d.create(0, 0)], x0, 0); x0 += ax + 2; for (const cornerY of [0, 1, 0.2]) { @@ -119,17 +123,29 @@ describe("HalfEdgeGraphSpineContext", () => { let x0 = 0.0; const allGeometry: GeometryQuery[] = []; const inner = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/inner.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/inner.imjs", + "utf8", + ))); const innerA = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedA.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedA.imjs", + "utf8", + ))); const innerB = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedB.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedB.imjs", + "utf8", + ))); const innerC = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedC.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedC.imjs", + "utf8", + ))); const innerD = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedD.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/innerSimplifiedD.imjs", + "utf8", + ))); const outer = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/MBContainmentBoolean/outer.imjs", "utf8"))); + "./src/test/data/intersections/MBContainmentBoolean/outer.imjs", + "utf8", + ))); for (const data of [innerD, innerC, innerB, inner, outer, innerA, innerB]) { // testSpineLoop(allGeometry, data, x0, 0); const flatData = flattenRegions(data as any[]); @@ -139,7 +155,6 @@ describe("HalfEdgeGraphSpineContext", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "HalfEdgeGraphSpineContext", "XYBoundaryFiles"); }); - }); function flattenRegions(data: any[]): MultiLineStringDataVariant[] { diff --git a/core/geometry/src/test/topology/HalfEdgeMarkSet.test.ts b/core/geometry/src/test/topology/HalfEdgeMarkSet.test.ts index 102e6a6704e7..e6292ade0ec0 100644 --- a/core/geometry/src/test/topology/HalfEdgeMarkSet.test.ts +++ b/core/geometry/src/test/topology/HalfEdgeMarkSet.test.ts @@ -9,7 +9,6 @@ import { AbstractHalfEdgeGraphMarkSet, MarkedEdgeSet, MarkedFaceSet, MarkedHalfE import { Checker } from "../Checker"; describe("HalfEdgeMarkSet", () => { - it("HelloWorld", () => { const ck = new Checker(); const graph = new HalfEdgeGraph(); @@ -125,7 +124,6 @@ describe("HalfEdgeMarkSet", () => { edgeSet.clear(); vertexSet.clear(); faceSet.clear(); - } halfEdgeSet.teardown(); edgeSet.teardown(); @@ -135,7 +133,7 @@ describe("HalfEdgeMarkSet", () => { // Hard to reach lines .. // drain the mask pool in the graph ... - while (graph.grabMask() !== 0) { } + while (graph.grabMask() !== 0) {} // and all the mark set creations will fail ... ck.testUndefined(MarkedHalfEdgeSet.create(graph)); ck.testUndefined(MarkedEdgeSet.create(graph)); @@ -143,7 +141,6 @@ describe("HalfEdgeMarkSet", () => { ck.testUndefined(MarkedVertexSet.create(graph)); expect(ck.getNumErrors()).toBe(0); }); - }); function verifyMarkSetState(ck: Checker, title: string, markSet: AbstractHalfEdgeGraphMarkSet, expectedMaskCount: number, expectedLength: number) { diff --git a/core/geometry/src/test/topology/InsertAndRetriangulateContext.test.ts b/core/geometry/src/test/topology/InsertAndRetriangulateContext.test.ts index deec612362c1..f7542431e54f 100644 --- a/core/geometry/src/test/topology/InsertAndRetriangulateContext.test.ts +++ b/core/geometry/src/test/topology/InsertAndRetriangulateContext.test.ts @@ -32,8 +32,15 @@ import { GraphChecker } from "./Graph.test"; * * Edge: tick mark from edge position into its face. * * At end, copy all data fro newDetail to oldDetail. */ -function showPosition(allGeometry: GeometryQuery[], oldDetail: HalfEdgePositionDetail, newDetail: HalfEdgePositionDetail, markerSize: number, - x0: number, y0: number, z0: number = 0) { +function showPosition( + allGeometry: GeometryQuery[], + oldDetail: HalfEdgePositionDetail, + newDetail: HalfEdgePositionDetail, + markerSize: number, + x0: number, + y0: number, + z0: number = 0, +) { if (!oldDetail.isUnclassified && !newDetail.isUnclassified) { const point0 = oldDetail.clonePoint(); const point1 = newDetail.clonePoint(); @@ -69,7 +76,6 @@ function showPosition(allGeometry: GeometryQuery[], oldDetail: HalfEdgePositionD } describe("InsertAndRetriangulateContext", () => { - it("MoveInGrid", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -90,46 +96,46 @@ describe("InsertAndRetriangulateContext", () => { for (let j = 0; j + 1 < numY; j++) graph.addEdgeXY(i, j, i, j + 1); } - const z1 = 0.05; // draw linework a little above the polyface. + const z1 = 0.05; // draw linework a little above the polyface. HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph); const context = InsertAndRetriangulateContext.create(graph); const position = HalfEdgePositionDetail.create(); const oldPosition = HalfEdgePositionDetail.create(); GraphChecker.captureAnnotatedGraph(allGeometry, graph, x0, y0); - for (const point of [ - Point3d.create(0.5, 1.0), // jump onto an edge - Point3d.create(1.5, 1.0), // move along a grid line, through a vertex to middle of next edge - Point3d.create(3.5, 1.0), // further along the grid line, jumping along an entire edge - Point3d.create(1.5, 0.5), // back cross some edges into a face - Point3d.create(0.5, 1.5), - Point3d.create(1.2, 2.8), - Point3d.create(1.8, 2.0), - Point3d.create(1.8, 1.0), - Point3d.create(2.0, 2.0), - Point3d.create(2.5, 0.5), - Point3d.create(0.2, 0.6), - Point3d.create(0.3, 0.4), - Point3d.create(1.2, 0.4), - Point3d.create(0.5, 1.0), - Point3d.create(2.5, 1.0), - Point3d.create(2.2, 1.0), - Point3d.create(2.8, 1.0), - Point3d.create(2.0, 1.0), - Point3d.create(1.5, 1.0), - Point3d.create(1.0, 1.0), - Point3d.create(0.0, 1.0), - Point3d.create(6.0, 1.0), - - ]) { + for ( + const point of [ + Point3d.create(0.5, 1.0), // jump onto an edge + Point3d.create(1.5, 1.0), // move along a grid line, through a vertex to middle of next edge + Point3d.create(3.5, 1.0), // further along the grid line, jumping along an entire edge + Point3d.create(1.5, 0.5), // back cross some edges into a face + Point3d.create(0.5, 1.5), + Point3d.create(1.2, 2.8), + Point3d.create(1.8, 2.0), + Point3d.create(1.8, 1.0), + Point3d.create(2.0, 2.0), + Point3d.create(2.5, 0.5), + Point3d.create(0.2, 0.6), + Point3d.create(0.3, 0.4), + Point3d.create(1.2, 0.4), + Point3d.create(0.5, 1.0), + Point3d.create(2.5, 1.0), + Point3d.create(2.2, 1.0), + Point3d.create(2.8, 1.0), + Point3d.create(2.0, 1.0), + Point3d.create(1.5, 1.0), + Point3d.create(1.0, 1.0), + Point3d.create(0.0, 1.0), + Point3d.create(6.0, 1.0), + ] + ) { y0 += yStep; const polyface = PolyfaceBuilder.graphToPolyface(graph); GeometryCoreTestIO.captureCloneGeometry(allGeometry, polyface, x0, y0); - context.moveToPoint(position, point, - (positionA: HalfEdgePositionDetail) => { - showPosition(allGeometry, oldPosition, positionA, aa * 0.5, x0, y0, z1); - return true; - }); + context.moveToPoint(position, point, (positionA: HalfEdgePositionDetail) => { + showPosition(allGeometry, oldPosition, positionA, aa * 0.5, x0, y0, z1); + return true; + }); // GraphChecker.captureAnnotatedGraph(allGeometry, graph, x0, y0); showPosition(allGeometry, oldPosition, position, aa, x0, y0, z1); } @@ -152,7 +158,7 @@ describe("InsertAndRetriangulateContext", () => { const graph1 = new HalfEdgeGraph(); const numX = 4; const numY = 4; - let x0 = 10; // keep right to allow side by side with "just move" + let x0 = 10; // keep right to allow side by side with "just move" let y0 = 0; const yStep = numY + 5; const xStep = numX + 5; @@ -184,31 +190,33 @@ describe("InsertAndRetriangulateContext", () => { for (const context of [context1, context2]) { y0 = 0; let numPointsInserted = 0; - for (const point of [ - Point3d.create(0.5, 0.6), // in face - Point3d.create(1.0, 0.6), // move to edge - Point3d.create(1.5, 0.6), // cross one edge into a face - Point3d.create(0.5, 0.7), // back to first face - Point3d.create(0.5, 1.0), // up to an edge - Point3d.create(1, 1), // directly to a vertex - Point3d.create(0.5, 1.0), // back to edge - Point3d.create(1.5, 1.0), // through vertex to mid edge - Point3d.create(0.5, 2.0), // up to a higher edge - Point3d.create(2.5, 2.0), // along edge, through 2 vertices + for ( + const point of [ + Point3d.create(0.5, 0.6), // in face + Point3d.create(1.0, 0.6), // move to edge + Point3d.create(1.5, 0.6), // cross one edge into a face + Point3d.create(0.5, 0.7), // back to first face + Point3d.create(0.5, 1.0), // up to an edge + Point3d.create(1, 1), // directly to a vertex + Point3d.create(0.5, 1.0), // back to edge + Point3d.create(1.5, 1.0), // through vertex to mid edge + Point3d.create(0.5, 2.0), // up to a higher edge + Point3d.create(2.5, 2.0), // along edge, through 2 vertices - Point3d.create(2, 2), // back up to a vertex - Point3d.create(2, 1), // move to another - Point3d.create(1, 1), // and another - Point3d.create(0.5, 1.5), // face interior - Point3d.create(1, 1), // back to vertex - Point3d.create(0.5, 2), // mid edge - Point3d.create(0.5, 2), // sit there again - Point3d.create(0.2, 2), // same edge - Point3d.create(0.5, 1.5), // in face - Point3d.create(0.5, 1.5), // stay - Point3d.create(1.0, 1.0), // at vertex - Point3d.create(1.0, 1.0), // stay - ]) { + Point3d.create(2, 2), // back up to a vertex + Point3d.create(2, 1), // move to another + Point3d.create(1, 1), // and another + Point3d.create(0.5, 1.5), // face interior + Point3d.create(1, 1), // back to vertex + Point3d.create(0.5, 2), // mid edge + Point3d.create(0.5, 2), // sit there again + Point3d.create(0.2, 2), // same edge + Point3d.create(0.5, 1.5), // in face + Point3d.create(0.5, 1.5), // stay + Point3d.create(1.0, 1.0), // at vertex + Point3d.create(1.0, 1.0), // stay + ] + ) { context.insertAndRetriangulate(point, InsertedVertexZOptions.Replace); numPointsInserted++; if (numPointsInserted < 4) { @@ -299,7 +307,6 @@ describe("InsertAndRetriangulateContext", () => { GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(hull), x0, y0); GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, interior, r, x0, y0); y0 += yShiftDisplay; - } GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(hull), x0, y0); @@ -323,5 +330,4 @@ describe("InsertAndRetriangulateContext", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "InsertAndRetriangulateContext", "TriangulateInHull"); expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/topology/MaskManager.test.ts b/core/geometry/src/test/topology/MaskManager.test.ts index edb04d03e551..bbece5dd22ac 100644 --- a/core/geometry/src/test/topology/MaskManager.test.ts +++ b/core/geometry/src/test/topology/MaskManager.test.ts @@ -8,7 +8,6 @@ import { MaskManager } from "../../topology/MaskManager"; import { Checker } from "../Checker"; describe("MaskManager", () => { - it("HelloWorld", () => { const ck = new Checker(); const allFreeMasks = 0x000F0F00; @@ -38,5 +37,4 @@ describe("MaskManager", () => { expect(ck.getNumErrors()).toBe(0); }); - }); diff --git a/core/geometry/src/test/topology/Merge.test.ts b/core/geometry/src/test/topology/Merge.test.ts index 9fba5a5b43c9..5bba9c848e91 100644 --- a/core/geometry/src/test/topology/Merge.test.ts +++ b/core/geometry/src/test/topology/Merge.test.ts @@ -23,7 +23,6 @@ import { prettyPrint } from "../testFunctions"; import { GraphChecker } from "./Graph.test"; describe("GraphMerge", () => { - it("HalfEdgePriorityQueueWithPartnerArray", () => { const ck = new Checker(); const edges = new HalfEdgePriorityQueueWithPartnerArray(); @@ -52,7 +51,6 @@ describe("GraphMerge", () => { ck.testTrue(p.y < q.y, "low y moved to active edges first"); } edges.removeArrayMembersWithY1Below(q.faceSuccessor.y); - } expect(ck.getNumErrors()).toBe(0); }); @@ -68,7 +66,10 @@ describe("GraphMerge", () => { for (const degrees of [10, 0, 1.2, 55]) { const graph = new HalfEdgeGraph(); - const transform = Transform.createFixedPointAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); Triangulator.createFaceLoopFromCoordinates(graph, loop0, true, false); Triangulator.createFaceLoopFromCoordinates(graph, loop1, true, false); graph.transformInPlace(transform); @@ -85,10 +86,22 @@ describe("GraphMerge", () => { HalfEdgeGraphMerge.clusterAndMergeXYTheta(graph); GraphChecker.captureAnnotatedGraph(allGeometry, graph, x0, y0 += dy); - GeometryCoreTestIO.captureGeometry(allGeometry, PolyfaceBuilder.graphToPolyface(graph, undefined, (node) => HalfEdge.testFacePositiveAreaXY(node)), x0, y0 += dy, 0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + PolyfaceBuilder.graphToPolyface(graph, undefined, (node) => HalfEdge.testFacePositiveAreaXY(node)), + x0, + y0 += dy, + 0, + ); Triangulator.triangulateAllPositiveAreaFaces(graph); - GeometryCoreTestIO.captureGeometry(allGeometry, PolyfaceBuilder.graphToPolyface(graph, undefined, (node) => HalfEdge.testFacePositiveAreaXY(node)), x0, y0 += dy, 0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + PolyfaceBuilder.graphToPolyface(graph, undefined, (node) => HalfEdge.testFacePositiveAreaXY(node)), + x0, + y0 += dy, + 0, + ); const summary1 = HalfEdgeGraphSearch.collectFaceAreaSummary(graph, true); ck.testExactNumber(summary1.numNegative, summary1.negativeItemArray!.length, " negative face counts"); diff --git a/core/geometry/src/test/topology/RegionOps.test.ts b/core/geometry/src/test/topology/RegionOps.test.ts index e6a41259c28c..63d4cb55c5ca 100644 --- a/core/geometry/src/test/topology/RegionOps.test.ts +++ b/core/geometry/src/test/topology/RegionOps.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { BezierCurve3d } from "../../bspline/BezierCurve3d"; import { BSplineCurve3dH } from "../../bspline/BSplineCurve3dH"; import { Arc3d } from "../../curve/Arc3d"; @@ -51,30 +51,37 @@ import { GraphChecker } from "./Graph.test"; const diegoPathA = [ { lineSegment: [[9.475113484165819, -13.519605207518564, 0], [13.203035410431951, -14.269123503051588, 0]], - }, { + }, + { arc: { center: [13.005924613981659, -15.249504721722534, 0], vectorX: [0.1971107964502951, 0.9803812186709463, 0], vectorY: [0.9803812186709463, -0.1971107964502951, 0], - sweepStartEnd: - [0, 72.830637847867], + sweepStartEnd: [0, 72.830637847867], }, - }, { lineSegment: [[14.000803020390693, -15.148425760207218, 0], [14.34957401104505, -18.58123435046298, 0]] }, { + }, + { lineSegment: [[14.000803020390693, -15.148425760207218, 0], [14.34957401104505, -18.58123435046298, 0]] }, + { lineSegment: [[14.34957401104505, -18.58123435046298, 0], [12.673764076933416, -20.859772802822125, 0]], - }, { + }, + { arc: { center: [11.868182928857742, -20.2672873482622, 0], vectorX: [0.8055811480756748, -0.5924854545599226, 0], vectorY: [-0.5924854545599226, -0.8055811480756748, 0], sweepStartEnd: [0, 71.45442290504732], }, - }, { + }, + { lineSegment: [ [11.562686951204984, -21.21948071498872, 0], - [8.527182927305319, -20.245587909330848, 0]], - }, { + [8.527182927305319, -20.245587909330848, 0], + ], + }, + { lineSegment: [[8.527182927305319, -20.245587909330848, 0], [7.111360097008944, -16.594638869216595, 0]], - }, { + }, + { arc: { center: [8.043708604295633, -16.2330780016434, 0], vectorX: [-0.9323485072866892, -0.3615608675731971, 0], @@ -84,7 +91,8 @@ const diegoPathA = [ }, { lineSegment: [[7.359620917079077, -15.503678223607576, 0], [9.47511348416582, -13.519605207518566, 0]], - }]; + }, +]; class PolygonBooleanTests { public allGeometry: GeometryQuery[] = []; @@ -102,14 +110,17 @@ class PolygonBooleanTests { this.noisy = noisy; this.debugPersistence = persistence; } - public getNoisy(): number { return this.debugPersistence > 0 ? this.noisy : 0; } + public getNoisy(): number { + return this.debugPersistence > 0 ? this.noisy : 0; + } public endDebugMethod() { if (this.debugPersistence === 1) { RegionOps.setCheckPointFunction(undefined); } - } - public getNumErrors() { return this.ck.getNumErrors(); } + public getNumErrors() { + return this.ck.getNumErrors(); + } public captureAnnotatedGraph(graph: HalfEdgeGraph, dx: number, dy: number) { GraphChecker.captureAnnotatedGraph(this.allGeometry, graph, this.x0 + dx, this.y0 + dy); @@ -123,8 +134,10 @@ class PolygonBooleanTests { const noisy = this.getNoisy(); if (noisy !== 0) RegionOps.setCheckPointFunction((name: string, graph: HalfEdgeGraph, properties: string, _extraData?: any) => { - if (name === "After clusterAndMergeXYTheta" - || noisy > 5) { + if ( + name === "After clusterAndMergeXYTheta" + || noisy > 5 + ) { this.captureAnnotatedGraph(graph, dx1, 0); dx1 += noisyDeltaX; } @@ -137,14 +150,14 @@ class PolygonBooleanTests { GraphChecker.dumpGraph(graph); } } - }); range.extendArray(boundary1); const yStep = 2.0 * range.yLength(); this.y0 = 0.0; GeometryCoreTestIO.captureGeometry(this.allGeometry, LineString3d.create(boundary0), this.x0, this.y0); GeometryCoreTestIO.captureGeometry(this.allGeometry, LineString3d.create(boundary1), this.x0, this.y0); - this.y0 += yStep; dx1 = dx1Start; + this.y0 += yStep; + dx1 = dx1Start; boolOp = "Union"; let unionArea; let differenceAreaBOnly; @@ -155,7 +168,8 @@ class PolygonBooleanTests { unionArea = PolyfaceQuery.sumFacetAreas(unionRegion); GeometryCoreTestIO.captureGeometry(this.allGeometry, unionRegion, this.x0, this.y0); } - this.y0 += yStep; dx1 = dx1Start; + this.y0 += yStep; + dx1 = dx1Start; boolOp = "Intersection"; const intersectionRegion = RegionOps.polygonXYAreaIntersectLoopsToPolyface(boundary0, boundary1); @@ -163,7 +177,8 @@ class PolygonBooleanTests { intersectionArea = PolyfaceQuery.sumFacetAreas(intersectionRegion); GeometryCoreTestIO.captureGeometry(this.allGeometry, intersectionRegion, this.x0, this.y0); } - this.y0 += yStep; dx1 = dx1Start; + this.y0 += yStep; + dx1 = dx1Start; boolOp = "Difference"; const differenceRegionAOnly = RegionOps.polygonXYAreaDifferenceLoopsToPolyface(boundary0, boundary1); @@ -171,7 +186,8 @@ class PolygonBooleanTests { differenceAreaAOnly = PolyfaceQuery.sumFacetAreas(differenceRegionAOnly); GeometryCoreTestIO.captureGeometry(this.allGeometry, differenceRegionAOnly, this.x0, this.y0); } - this.y0 += yStep; dx1 = dx1Start; + this.y0 += yStep; + dx1 = dx1Start; boolOp = "Difference"; const differenceRegionBOnly = RegionOps.polygonXYAreaDifferenceLoopsToPolyface(boundary1, boundary0); @@ -185,7 +201,9 @@ class PolygonBooleanTests { differenceAreaAOnly !== undefined && differenceAreaBOnly !== undefined ) { this.ck.testCoordinate( - unionArea, differenceAreaAOnly + differenceAreaBOnly + intersectionArea, "union = A1 + intersection + B1", + unionArea, + differenceAreaAOnly + differenceAreaBOnly + intersectionArea, + "union = A1 + intersection + B1", ); } this.x0 += 2.0 * range.xLength() + dx1; @@ -201,7 +219,6 @@ class PolygonBooleanTests { } } describe("RegionOps", () => { - it("BooleanRectangles", () => { const context = new PolygonBooleanTests(); context.setDebugControls(10, 1); @@ -233,7 +250,8 @@ describe("RegionOps", () => { const fractalA = Sample.createFractalLMildConcavePatter(2, 1.0); const fractalB = Sample.createFractalHatReversingPattern(1, 0.7); const transform = Transform.createFixedPointAndMatrix( - Point3d.create(0, 0, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(0.1232132132189379)), + Point3d.create(0, 0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(0.1232132132189379)), ); const fractalA1 = transform.multiplyInversePoint3dArray(fractalA)!; const fractalB1 = transform.multiplyInversePoint3dArray(fractalB)!; @@ -256,7 +274,8 @@ describe("RegionOps", () => { Point3d.create(3, 3), Point3d.create(2, 4), Point3d.create(1, 3), - Point3d.create(2, 1)]; + Point3d.create(2, 1), + ]; context.testBooleans(rectangle, splat); context.saveAndReset("RegionOps", "BooleanSplat"); expect(context.getNumErrors()).toBe(0); @@ -285,9 +304,12 @@ describe("RegionOps", () => { const allGeometry: GeometryQuery[] = []; let x0 = 0.0; let y0 = 0.0; - for (const splat of [ - Sample.appendSawTooth([], 1, 0.5, 3, 1, 5), - Sample.appendSawTooth([], 1, 0.5, 1, 1, 3)]) { + for ( + const splat of [ + Sample.appendSawTooth([], 1, 0.5, 3, 1, 5), + Sample.appendSawTooth([], 1, 0.5, 1, 1, 3), + ] + ) { const growableSplat = GrowableXYZArray.create(splat); const data = [growableSplat, rectangle]; const range = Range3d.createFromVariantData(data); @@ -309,18 +331,20 @@ describe("RegionOps", () => { const context = new PolygonBooleanTests(); context.setDebugControls(10, 1); const outerRectangle = Sample.createRectangleXY(0, 0, 10, 6); - for (const innerRectangle of [ - Sample.createRectangleXY(2, 4, -2, 2), - Sample.createRectangleXY(2, 0, 3, 2), - Sample.createRectangleXY(8, 0, 2, 2), - Sample.createRectangleXY(3, 4, 2, 2), - Sample.createRectangleXY(0, 0, 3, 6)]) { + for ( + const innerRectangle of [ + Sample.createRectangleXY(2, 4, -2, 2), + Sample.createRectangleXY(2, 0, 3, 2), + Sample.createRectangleXY(8, 0, 2, 2), + Sample.createRectangleXY(3, 4, 2, 2), + Sample.createRectangleXY(0, 0, 3, 6), + ] + ) { context.testBooleans(outerRectangle, innerRectangle); context.saveAndReset("RegionOps", "BooleanSplat"); } expect(context.getNumErrors()).toBe(0); }); - }); /** * Exercise PolygonWireOffset and output to a file. @@ -330,7 +354,10 @@ describe("RegionOps", () => { * @param distanceFactor factor to apply to distances. */ function testPolygonOffset( - polygons: Point3d[][], caseName: string, distances: number[], distanceFactor: number, + polygons: Point3d[][], + caseName: string, + distances: number[], + distanceFactor: number, ) { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -368,7 +395,10 @@ function testPolygonOffset( * @param distanceFactor factor to apply to distances. */ function testFilteredPolygonOffset( - polygons: Point3d[][], caseName: string, distances: number[], filterFactor: number[], + polygons: Point3d[][], + caseName: string, + distances: number[], + filterFactor: number[], ) { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -426,7 +456,8 @@ describe("PolygonOffset", () => { Point3d.create(5, 5), Point3d.create(5.5, 0), Point3d.create(6, 0), - Point3d.create(6.6, 1)]; + Point3d.create(6.6, 1), + ]; const star1 = Sample.createStar(1, 1, 0, 4, 3, 3, true); const star2 = Sample.createStar(1, 1, 0, 5, 2, 5, true); testPolygonOffset([rectangle0, star1, star2, wPoints], "TestA", [-0.5, 0.5, 1.0, -1.0, -2.0], 1.0); @@ -436,7 +467,12 @@ describe("PolygonOffset", () => { const allPoints = []; for (const upperCount of [2, 1, 2, 3, 8]) { const points = Sample.createInterpolatedPoints( - Point3d.create(0, 1), Point3d.create(2, 3), upperCount, undefined, 0, upperCount, + Point3d.create(0, 1), + Point3d.create(2, 3), + upperCount, + undefined, + 0, + upperCount, ); allPoints.push(points); } @@ -505,7 +541,6 @@ describe("PolygonOffset", () => { const offsetDistances = [0.7]; // testPolygonOffset([points], "SpikeOutside", offsetDistances, 1); testPolygonOffset([points], "TestGouge", offsetDistances, -1); - }); it("TestFractals", () => { @@ -551,8 +586,11 @@ describe("RegionInOut", () => { for (const qe of [-0.4, 0.0, 0.3, 1.0, 1.6]) { for (const uv of [Point2d.create(q01, qe), Point2d.create(qe, q01)]) { const xy = range.fractionToPoint(uv.x, uv.y); - ck.testExactNumber(Geometry.isIn01(qe) ? 0 : -1, - RegionOps.testPointInOnOutRegionXY(geometry, xy.x, xy.y), { case: "InOutEdge", uu: uv.x, vv: uv.y }); + ck.testExactNumber(Geometry.isIn01(qe) ? 0 : -1, RegionOps.testPointInOnOutRegionXY(geometry, xy.x, xy.y), { + case: "InOutEdge", + uu: uv.x, + vv: uv.y, + }); } } } @@ -563,7 +601,8 @@ describe("RegionInOut", () => { it("CircleInOut", () => { const ck = new Checker(); const arc0 = Arc3d.createXYEllipse(Point3d.create(0, 0, 0), 3, 2); - const arc1 = arc0.cloneInRotatedBasis(Angle.createDegrees(15)); Loop; + const arc1 = arc0.cloneInRotatedBasis(Angle.createDegrees(15)); + Loop; for (const arc of [arc0, arc1]) { for (const fraction of [0.0, 0.25, 0.4, 0.5, 0.88, 1.0]) { for (const radialFraction of [0.4, 1.0, 1.2]) { @@ -573,7 +612,9 @@ describe("RegionInOut", () => { const expectedClassify = Geometry.split3WaySign(radialFraction - 1.0, 1.0, 0.0, -1.0); if ( !ck.testExactNumber( - expectedClassify, classify, { arcInOut: arc, fractionAlong: fraction, fractionRadial: radialFraction }, + expectedClassify, + classify, + { arcInOut: arc, fractionAlong: fraction, fractionRadial: radialFraction }, ) ) RegionOps.testPointInOnOutRegionXY(region, xy.x, xy.y); @@ -632,7 +673,10 @@ describe("RegionInOut", () => { if (q !== classify) { RegionOps.testPointInOnOutRegionXY(loop, testPoint.x, testPoint.y); GeometryCoreTestIO.captureGeometry( - allGeometry, LineSegment3d.create(testPoint, testPoint.plus(errorVector)), x0, y0, + allGeometry, + LineSegment3d.create(testPoint, testPoint.plus(errorVector)), + x0, + y0, ); } } @@ -645,7 +689,6 @@ describe("RegionInOut", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "RegionOps", "MixedInOut"); expect(ck.getNumErrors()).toBe(0); }); - }); function curveLength(source: AnyCurve): number { @@ -658,12 +701,17 @@ function curveLength(source: AnyCurve): number { class HasEllipticalArcProcessor extends RecursiveCurveProcessor { private _hasEllipticalArc: boolean; - public constructor() { super(); this._hasEllipticalArc = false; } + public constructor() { + super(); + this._hasEllipticalArc = false; + } public override announceCurvePrimitive(data: CurvePrimitive, _indexInParent = -1): void { if (data instanceof Arc3d && !data.isCircular) this._hasEllipticalArc = true; } - public claimResult(): boolean { return this._hasEllipticalArc; } + public claimResult(): boolean { + return this._hasEllipticalArc; + } } class HasStrokablePrimitiveProcessor extends RecursiveCurveProcessor { @@ -689,7 +737,11 @@ class HasStrokablePrimitiveProcessor extends RecursiveCurveProcessor { // for best geometry capture, baseCurve should be centered at origin function testOffsetSingle( - ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions, + ck: Checker, + allGeometry: GeometryQuery[], + delta: Point2d, + baseCurve: Path | Loop, + options: OffsetOptions, ): void { const offsetCurve = RegionOps.constructCurveXYOffset(baseCurve, options); if (ck.testDefined(offsetCurve, "Offset computed")) { @@ -706,12 +758,14 @@ function testOffsetSingle( const scaledParam = offsetDetail.fraction * (offsetDetail.curve.numPoints() - 1); projectsToVertex = Geometry.isAlmostEqualNumber(scaledParam, Math.trunc(scaledParam)); projectsToVertex = projectsToVertex || - Geometry.isAlmostEqualNumber(scaledParam, 1 + Math.trunc(scaledParam)); // e.g., true for scaledParam === 4.9999999 + Geometry.isAlmostEqualNumber(scaledParam, 1 + Math.trunc(scaledParam)); // e.g., true for scaledParam === 4.9999999 } - if (!projectsToVertex) { // avoid measuring projections to linestring vertices as they usually exceed offset distance + if (!projectsToVertex) { // avoid measuring projections to linestring vertices as they usually exceed offset distance if ( !ck.testCoordinateWithToleranceFactor( - offsetDetail.point.distance(basePt), Math.abs(options.leftOffsetDistance), tolFactor, + offsetDetail.point.distance(basePt), + Math.abs(options.leftOffsetDistance), + tolFactor, ) ) { GeometryCoreTestIO.createAndCaptureXYCircle(allGeometry, basePt, 0.05, delta.x, delta.y); @@ -727,22 +781,30 @@ function testOffsetSingle( } function testOffsetBothSides( - ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions, + ck: Checker, + allGeometry: GeometryQuery[], + delta: Point2d, + baseCurve: Path | Loop, + options: OffsetOptions, ): void { const rangeY = baseCurve.range().yLength(); delta.y += rangeY; GeometryCoreTestIO.captureCloneGeometry(allGeometry, baseCurve, delta.x, delta.y); - testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on given offset + testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on given offset options.leftOffsetDistance *= -1; - testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on other side - options.leftOffsetDistance *= -1; // undo + testOffsetSingle(ck, allGeometry, delta, baseCurve, options); // offset on other side + options.leftOffsetDistance *= -1; // undo delta.y += rangeY; } function testOffset( - ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions, + ck: Checker, + allGeometry: GeometryQuery[], + delta: Point2d, + baseCurve: Path | Loop, + options: OffsetOptions, ): void { testOffsetBothSides(ck, allGeometry, delta, baseCurve, options); // toggle ellipse preservation @@ -783,7 +845,11 @@ function testOffset( } function testOffsetWrapper( - ck: Checker, allGeometry: GeometryQuery[], delta: Point2d, baseCurve: Path | Loop, options: OffsetOptions, + ck: Checker, + allGeometry: GeometryQuery[], + delta: Point2d, + baseCurve: Path | Loop, + options: OffsetOptions, ): void { const rangeX = options.leftOffsetDistance + baseCurve.range().xLength(); delta.x += rangeX; @@ -803,7 +869,9 @@ describe("CloneSplitCurves", () => { const y2 = 0.5; const line010 = LineSegment3d.createCapture(Point3d.create(0, 0, 0), Point3d.create(10, 0, 0)); const arc010 = Arc3d.createCircularStartMiddleEnd( - Point3d.create(0, 0), Point3d.create(5, -y1), Point3d.create(10, 0), + Point3d.create(0, 0), + Point3d.create(5, -y1), + Point3d.create(10, 0), ); // const line1 = LineSegment3d.createCapture(Point3d.create(1, -1, 0), Point3d.create(1, 1, 0)); // const lineString234 = LineString3d.create([2, -1], [3, 1], [4, -1]); @@ -813,15 +881,17 @@ describe("CloneSplitCurves", () => { // const cutters = BagOfCurves.create(line1, arc5, lineString234); const cutters = BagOfCurves.create(arc5); const pathsToCut: AnyCurve[] = [ - line010, // just a line - arc010, // just an arc + line010, // just a line + arc010, // just an arc LineString3d.create([0, 0], [10, 0], [10, y2], [0, y2]), // just a linestring Path.create( - LineSegment3d.create(Point3d.create(0, y2), Point3d.create(0, 0)), line010.clone(), - ), // two lines that will rejoin in output + LineSegment3d.create(Point3d.create(0, y2), Point3d.create(0, 0)), + line010.clone(), + ), // two lines that will rejoin in output Path.create( - line010.clone(), LineSegment3d.create(line010.endPoint(), Point3d.create(0, y2)), - ), // two lines that will rejoin in output + line010.clone(), + LineSegment3d.create(line010.endPoint(), Point3d.create(0, y2)), + ), // two lines that will rejoin in output Path.create( line010.clone(), linestring10, @@ -886,25 +956,32 @@ describe("CloneSplitCurves", () => { const segments = [ LineSegment3d.create( Point3d.createFrom({ x: 22.213935902760078, y: 6.72335636194596, z: 0 }), - Point3d.createFrom({ x: 19.126382295715867, y: 7.030119101735917, z: 0 })), + Point3d.createFrom({ x: 19.126382295715867, y: 7.030119101735917, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 18.480825764734846, y: 3.237105594599584, z: 0 }), - Point3d.createFrom({ x: 22.213935902760074, y: 6.72335636194596, z: 0 })), + Point3d.createFrom({ x: 22.213935902760074, y: 6.72335636194596, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 16.68697627970194, y: 5.084431827079689, z: 0 }), - Point3d.createFrom({ x: 18.48082576473485, y: 3.2371055945995857, z: 0 })), + Point3d.createFrom({ x: 18.48082576473485, y: 3.2371055945995857, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 }), - Point3d.createFrom({ x: 16.68697627970194, y: 5.0844318270796895, z: 0 })), + Point3d.createFrom({ x: 16.68697627970194, y: 5.0844318270796895, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 15.253988532688888, y: 8.496059229639044, z: 0 }), - Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 })), + Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 15.253988532688888, y: 8.496059229639043, z: 0 }), - Point3d.createFrom({ x: 17.707917522590943, y: 9.036828096780024, z: 0 })), + Point3d.createFrom({ x: 17.707917522590943, y: 9.036828096780024, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 19.126382295715864, y: 7.030119101735919, z: 0 }), - Point3d.createFrom({ x: 17.70791752259094, y: 9.03682809678002, z: 0 })), + Point3d.createFrom({ x: 17.70791752259094, y: 9.03682809678002, z: 0 }), + ), ]; GeometryCoreTestIO.captureCloneGeometry(allGeometry, segments, 0, 0, 0); const collector = new ChainCollectorContext(false); @@ -916,7 +993,6 @@ describe("CloneSplitCurves", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "RegionOps", "GeneralChainA"); expect(ck.getNumErrors()).toBe(0); - }); it("GeneralChainB", () => { const allGeometry: GeometryQuery[] = []; @@ -924,25 +1000,32 @@ describe("CloneSplitCurves", () => { const segments = [ LineSegment3d.create( Point3d.createFrom({ x: 22.213935902760078, y: 6.72335636194596, z: 0 }), - Point3d.createFrom({ x: 19.126382295715867, y: 7.030119101735917, z: 0 })), + Point3d.createFrom({ x: 19.126382295715867, y: 7.030119101735917, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 18.480825764734846, y: 3.237105594599584, z: 0 }), - Point3d.createFrom({ x: 22.213935902760074, y: 6.72335636194596, z: 0 })), + Point3d.createFrom({ x: 22.213935902760074, y: 6.72335636194596, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 16.68697627970194, y: 5.084431827079689, z: 0 }), - Point3d.createFrom({ x: 18.48082576473485, y: 3.2371055945995857, z: 0 })), + Point3d.createFrom({ x: 18.48082576473485, y: 3.2371055945995857, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 }), - Point3d.createFrom({ x: 16.68697627970194, y: 5.0844318270796895, z: 0 })), + Point3d.createFrom({ x: 16.68697627970194, y: 5.0844318270796895, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 15.253988532688888, y: 8.496059229639044, z: 0 }), - Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 })), + Point3d.createFrom({ x: 13.954141275010276, y: 6.64077838793302, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 17.707917522590943, y: 9.036828096780024, z: 0 }), - Point3d.createFrom({ x: 15.253988532688888, y: 8.496059229639043, z: 0 })), + Point3d.createFrom({ x: 15.253988532688888, y: 8.496059229639043, z: 0 }), + ), LineSegment3d.create( Point3d.createFrom({ x: 19.126382295715864, y: 7.030119101735919, z: 0 }), - Point3d.createFrom({ x: 17.70791752259094, y: 9.03682809678002, z: 0 })), + Point3d.createFrom({ x: 17.70791752259094, y: 9.03682809678002, z: 0 }), + ), ]; GeometryCoreTestIO.captureCloneGeometry(allGeometry, segments, 0, 0, 0); const collector = new ChainCollectorContext(false); @@ -1009,15 +1092,27 @@ describe("CloneSplitCurves", () => { Point3d.create(5, 3), ]; const mirrorPoles: Point3d[] = []; - poles.forEach((pt) => { mirrorPoles.push(Point3d.create(-pt.x, pt.y)); }); + poles.forEach((pt) => { + mirrorPoles.push(Point3d.create(-pt.x, pt.y)); + }); mirrorPoles.reverse(); const rotatedPoles: Point3d[] = []; - mirrorPoles.forEach((pt) => { rotatedPoles.push(Point3d.create(pt.x, -pt.y)); }); + mirrorPoles.forEach((pt) => { + rotatedPoles.push(Point3d.create(pt.x, -pt.y)); + }); testOffsetWrapper( - ck, allGeometry, delta, Path.create(BezierCurve3d.create(mirrorPoles)!, BezierCurve3d.create(poles)!), options, + ck, + allGeometry, + delta, + Path.create(BezierCurve3d.create(mirrorPoles)!, BezierCurve3d.create(poles)!), + options, ); testOffsetWrapper( - ck, allGeometry, delta, Path.create(BezierCurve3d.create(rotatedPoles)!, BezierCurve3d.create(poles)!), options, + ck, + allGeometry, + delta, + Path.create(BezierCurve3d.create(rotatedPoles)!, BezierCurve3d.create(poles)!), + options, ); // unclamped splines @@ -1046,7 +1141,8 @@ describe("CloneSplitCurves", () => { // save unclamped, clamped, control polygon, start point, end point GeometryCoreTestIO.saveGeometry( [ - curve, curve.clonePartialCurve(0, 1), + curve, + curve.clonePartialCurve(0, 1), LineString3d.create(curve.copyXYZFloat64Array(true)), Arc3d.createXY(curve.startPoint(), 0.5), Arc3d.createXY(curve.endPoint(), 0.5), @@ -1069,7 +1165,9 @@ describe("CloneSplitCurves", () => { // Make a loop with multiple boundary curves . . . const segmentA = LineSegment3d.createXYXY(0, 0, 10, 0); const arcA = Arc3d.createCircularStartMiddleEnd( - Point3d.create(10, 0), Point3d.create(12, 5, 0), Point3d.create(10, 10, 0), + Point3d.create(10, 0), + Point3d.create(12, 5, 0), + Point3d.create(10, 10, 0), ); const stringA = LineString3d.create([10, 10], [0, 10], [0, 0]); const loop = Loop.create(segmentA, arcA, stringA); @@ -1127,12 +1225,16 @@ describe("RectangleRecognizer", () => { for (const degrees of [0, 25.6]) { const points = Sample.createRegularPolygon(0, 0, 0, Angle.createDegrees(degrees), 2, 4, true); for (const requireClosure of [true, false]) { - for (const data of [points, - GrowableXYZArray.create(points), - LineString3d.create(points), - Path.create(LineString3d.create(points)), - Loop.createPolygon(points), - makeSticks(points)]) { + for ( + const data of [ + points, + GrowableXYZArray.create(points), + LineString3d.create(points), + Path.create(LineString3d.create(points)), + Loop.createPolygon(points), + makeSticks(points), + ] + ) { const transform = RegionOps.rectangleEdgeTransform(data, requireClosure); ck.testDefined(transform); if (transform) { @@ -1167,11 +1269,17 @@ describe("RectangleRecognizer", () => { // const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const road = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/WilsonShapes/roadShape.imjs", "utf8"))); + "./src/test/data/intersections/WilsonShapes/roadShape.imjs", + "utf8", + ))); const badShape = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/WilsonShapes/3pointTurnShape_overlaps.imjs", "utf8"))); + "./src/test/data/intersections/WilsonShapes/3pointTurnShape_overlaps.imjs", + "utf8", + ))); const goodShape = IModelJson.Reader.parse(JSON.parse(fs.readFileSync( - "./src/test/data/intersections/WilsonShapes/3pointTurnShape_fits.imjs", "utf8"))); + "./src/test/data/intersections/WilsonShapes/3pointTurnShape_fits.imjs", + "utf8", + ))); if (road instanceof Loop) { const roadRange = road.range(); @@ -1200,7 +1308,6 @@ describe("RectangleRecognizer", () => { } GeometryCoreTestIO.saveGeometry(allGeometry, "RegionOps", "3PointTurnChecks"); }); - }); function makeSticks(points: Point3d[]): Path { @@ -1220,7 +1327,7 @@ describe("RegionOps2", () => { const testCases = [ "./src/test/data/curve/arcGisLoops.imjs", "./src/test/data/curve/loopWithHole.imjs", // aka, split washer polygon - "./src/test/data/curve/michelLoops.imjs", // has a small island in a hole + "./src/test/data/curve/michelLoops.imjs", // has a small island in a hole "./src/test/data/curve/michelLoops2.imjs", // 339 loops ]; const options = new StrokeOptions(); @@ -1344,8 +1451,13 @@ describe("RegionOps.constructPolygonWireXYOffset", () => { [Point3d.create(2, -1), Point3d.create(2, 0), Point3d.create(3, -1)], [Point3d.create(-1, 2), Point3d.create(2, 2), Point3d.create(1, 3), Point3d.create(-2, 3), Point3d.create(-1, 2)], [ - Point3d.create(-1, -2), Point3d.create(1, -2), Point3d.create(0.1, -3), Point3d.create(1, -4), - Point3d.create(-1, -4), Point3d.create(-0.1, -3), Point3d.create(-1, -2), + Point3d.create(-1, -2), + Point3d.create(1, -2), + Point3d.create(0.1, -3), + Point3d.create(1, -4), + Point3d.create(-1, -4), + Point3d.create(-0.1, -3), + Point3d.create(-1, -2), ], ]; const offsetDistances: number[] = [-0.3, -0.1, -0.05, 0.05, 0.1, 0.3]; @@ -1370,8 +1482,13 @@ describe("RegionOps.constructPolygonWireXYOffset", () => { [Point3d.create(2, -1), Point3d.create(2, 0), Point3d.create(3, -1)], [Point3d.create(-1, 2), Point3d.create(2, 2), Point3d.create(1, 3), Point3d.create(-2, 3), Point3d.create(-1, 2)], [ - Point3d.create(-1, -2), Point3d.create(1, -2), Point3d.create(0.1, -3), Point3d.create(1, -4), - Point3d.create(-1, -4), Point3d.create(-0.1, -3), Point3d.create(-1, -2), + Point3d.create(-1, -2), + Point3d.create(1, -2), + Point3d.create(0.1, -3), + Point3d.create(1, -4), + Point3d.create(-1, -4), + Point3d.create(-0.1, -3), + Point3d.create(-1, -2), ], ]; const offsetDistances: number[] = [-0.3, -0.1, -0.05, 0.05, 0.1, 0.3]; @@ -1396,8 +1513,13 @@ describe("RegionOps.constructPolygonWireXYOffset", () => { [Point3d.create(2, -1), Point3d.create(2, 0), Point3d.create(3, -1)], [Point3d.create(-1, 2), Point3d.create(2, 2), Point3d.create(1, 3), Point3d.create(-2, 3), Point3d.create(-1, 2)], [ - Point3d.create(-1, -2), Point3d.create(1, -2), Point3d.create(0.1, -3), Point3d.create(1, -4), - Point3d.create(-1, -4), Point3d.create(-0.1, -3), Point3d.create(-1, -2), + Point3d.create(-1, -2), + Point3d.create(1, -2), + Point3d.create(0.1, -3), + Point3d.create(1, -4), + Point3d.create(-1, -4), + Point3d.create(-0.1, -3), + Point3d.create(-1, -2), ], ]; const offsetDistances: number[] = [-0.3, -0.1, -0.05, 0.05, 0.1, 0.3]; @@ -1409,7 +1531,11 @@ describe("RegionOps.constructPolygonWireXYOffset", () => { const allowSharpestCorners = true; for (let i = 0; i < offsetDistances.length; i++) { jointOptions[i] = new JointOptions( - offsetDistances[i], minArcDegrees, maxChamferDegrees, preserveEllipticalArcs, allowSharpestCorners, + offsetDistances[i], + minArcDegrees, + maxChamferDegrees, + preserveEllipticalArcs, + allowSharpestCorners, ); } @@ -1433,16 +1559,29 @@ describe("RegionOps.constructCurveXYOffset", () => { Path.create([Point3d.create(1, -1), Point3d.create(1, 0), Point3d.create(1.5, 1)]), Path.create([Point3d.create(2, -1), Point3d.create(2, 0), Point3d.create(3, -1)]), Path.create([ - Point3d.create(-1, 2), Point3d.create(2, 2), Point3d.create(1, 3), Point3d.create(-2, 3), Point3d.create(-1, 2), + Point3d.create(-1, 2), + Point3d.create(2, 2), + Point3d.create(1, 3), + Point3d.create(-2, 3), + Point3d.create(-1, 2), ]), Loop.create( LineString3d.create([ - Point3d.create(-1, 4), Point3d.create(2, 4), Point3d.create(1, 5), Point3d.create(-2, 5), Point3d.create(-1, 4), + Point3d.create(-1, 4), + Point3d.create(2, 4), + Point3d.create(1, 5), + Point3d.create(-2, 5), + Point3d.create(-1, 4), ]), ), Path.create([ - Point3d.create(-1, -2), Point3d.create(1, -2), Point3d.create(0.1, -3), Point3d.create(1, -4), - Point3d.create(-1, -4), Point3d.create(-0.1, -3), Point3d.create(-1, -2), + Point3d.create(-1, -2), + Point3d.create(1, -2), + Point3d.create(0.1, -3), + Point3d.create(1, -4), + Point3d.create(-1, -4), + Point3d.create(-0.1, -3), + Point3d.create(-1, -2), ]), ]; const offsetDistances: number[] = [-0.3, -0.1, -0.05, 0.05, 0.1, 0.3]; @@ -1465,16 +1604,29 @@ describe("RegionOps.constructCurveXYOffset", () => { Path.create([Point3d.create(1, -1), Point3d.create(1, 0), Point3d.create(1.5, 1)]), Path.create([Point3d.create(2, -1), Point3d.create(2, 0), Point3d.create(3, -1)]), Path.create([ - Point3d.create(-1, 2), Point3d.create(2, 2), Point3d.create(1, 3), Point3d.create(-2, 3), Point3d.create(-1, 2), + Point3d.create(-1, 2), + Point3d.create(2, 2), + Point3d.create(1, 3), + Point3d.create(-2, 3), + Point3d.create(-1, 2), ]), Loop.create( LineString3d.create([ - Point3d.create(-1, 4), Point3d.create(2, 4), Point3d.create(1, 5), Point3d.create(-2, 5), Point3d.create(-1, 4), + Point3d.create(-1, 4), + Point3d.create(2, 4), + Point3d.create(1, 5), + Point3d.create(-2, 5), + Point3d.create(-1, 4), ]), ), Path.create([ - Point3d.create(-1, -2), Point3d.create(1, -2), Point3d.create(0.1, -3), Point3d.create(1, -4), - Point3d.create(-1, -4), Point3d.create(-0.1, -3), Point3d.create(-1, -2), + Point3d.create(-1, -2), + Point3d.create(1, -2), + Point3d.create(0.1, -3), + Point3d.create(1, -4), + Point3d.create(-1, -4), + Point3d.create(-0.1, -3), + Point3d.create(-1, -2), ]), ]; const offsetDistances: number[] = [-0.3, -0.1, -0.05, 0.05, 0.1, 0.3]; diff --git a/core/geometry/src/test/topology/RegularizeFace.test.ts b/core/geometry/src/test/topology/RegularizeFace.test.ts index df054d49f0b4..5c7b063a8f00 100644 --- a/core/geometry/src/test/topology/RegularizeFace.test.ts +++ b/core/geometry/src/test/topology/RegularizeFace.test.ts @@ -60,13 +60,15 @@ class VerticalStaggerData { public numBottomPeaks: number; public numUpChain: number; public numDownChain: number; - constructor(points: Point3d[], + constructor( + points: Point3d[], numUpEdge: number, numDownEdge: number, numTopPeaks: number, numBottomPeaks: number, numUpChain: number, - numDownChain: number) { + numDownChain: number, + ) { this.points = points; this.numUpEdge = numUpEdge; this.numDownEdge = numDownEdge; @@ -89,23 +91,20 @@ describe("Regularize", () => { const ck = new Checker(); const ax = 6; const ay = 10; - for (const data of [ - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, -2, -2, - 1, ax, ay, 0, 0), - 3, 3, 0, 0, 1, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, 0, -2, - 1, ax, ay, 0, 0), - 4, 2, 0, 0, 1, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, -2, - 1, ax, ay, 0, 0), - 4, 2, 1, 0, 2, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 2, - 1, ax, ay, 0, 0), - 3, 3, 1, 1, 2, 2), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 0, 1, ax, ay, 0, 0), - 3, 3, 1, 0, 2, 1)]) { + for ( + const data of [ + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, -2, -2, -1, ax, ay, 0, 0), 3, 3, 0, 0, 1, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, 0, -2, -1, ax, ay, 0, 0), 4, 2, 0, 0, 1, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, -2, -1, ax, ay, 0, 0), 4, 2, 1, 0, 2, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 2, -1, ax, ay, 0, 0), 3, 3, 1, 1, 2, 2), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 0, 1, ax, ay, 0, 0), 3, 3, 1, 0, 2, 1), + ] + ) { const graph = new HalfEdgeGraph(); const seed = Triangulator.createFaceLoopFromCoordinates(graph, data.points, true, false); const context = new RegularizationContext(graph); context.collectVerticalEventsAroundFace(seed!); data.validateCounts(ck, context); - } expect(ck.getNumErrors()).toBe(0); }); @@ -120,12 +119,15 @@ describe("Regularize", () => { const outputStepY = 15.0; const allGeometry: GeometryQuery[] = []; for (const maxEdgeLength of [4.0, 2.0, 1.2, 20.0]) { - for (const basePoints of [ - Sample.createVerticalStaggerPolygon(1, 0, 0, -2, ax, ay, 0, 0), - Sample.createVerticalStaggerPolygon(-1, -2, -2, - 1, ax, ay, 0, 0), - Sample.createVerticalStaggerPolygon(-1, -2, 0, - 1, ax, ay, 0, 0), - Sample.createVerticalStaggerPolygon(-1, -2, 0, -3, ax, ay, 0, 0), - Sample.createVerticalStaggerPolygon(1, 0, 0, -2, ax, ay, 0, 0)]) { + for ( + const basePoints of [ + Sample.createVerticalStaggerPolygon(1, 0, 0, -2, ax, ay, 0, 0), + Sample.createVerticalStaggerPolygon(-1, -2, -2, -1, ax, ay, 0, 0), + Sample.createVerticalStaggerPolygon(-1, -2, 0, -1, ax, ay, 0, 0), + Sample.createVerticalStaggerPolygon(-1, -2, 0, -3, ax, ay, 0, 0), + Sample.createVerticalStaggerPolygon(1, 0, 0, -2, ax, ay, 0, 0), + ] + ) { const points = Point3dArray.cloneWithMaxEdgeLength(basePoints, maxEdgeLength); const graph = new HalfEdgeGraph(); GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(points), outputX0, outputY0 += outputStepY); @@ -151,12 +153,18 @@ describe("Regularize", () => { const outputStepY = 15.0; const bigStepY = 100.0; let outputY1 = 0.0; - const transform = Transform.createFixedPointAndMatrix(Point3d.create(2, 0, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(145))); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(2, 0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(145)), + ); const allGeometry: GeometryQuery[] = []; for (const numPhase of [2, 4]) { for (const maxEdgeLength of [4.0, 2.0, 1.2, 20.0]) { - for (const basePoints of [ - Sample.createSquareWave(Point3d.create(0, 0, 0), 1, 0.5, 2, numPhase, 1)]) { + for ( + const basePoints of [ + Sample.createSquareWave(Point3d.create(0, 0, 0), 1, 0.5, 2, numPhase, 1), + ] + ) { const points = Point3dArray.cloneWithMaxEdgeLength(basePoints, maxEdgeLength); transform.multiplyPoint3dArray(points, points); const graph = new HalfEdgeGraph(); @@ -202,22 +210,26 @@ describe("Regularize", () => { const dx2Wave = -0.10; const dyB = 0.5; const hardLoopXStep = outputStepX * 0.25; - const transformA = Transform.createFixedPointAndMatrix(Point3d.create(2, 4, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(14.23423))); + const transformA = Transform.createFixedPointAndMatrix( + Point3d.create(2, 4, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(14.23423)), + ); const allGeometry: GeometryQuery[] = []; const hardLoops: GeometryQuery[] = []; - for (const numPhase of [2, 4, 6]) { // [2,4, 6] !! + for (const numPhase of [2, 4, 6]) { // [2,4, 6] !! for (const radians0 of [0, -2, -4]) { // [0, -2] ! outputX0 = outputX1; outputY0 = outputY1; - for (const maxEdgeLength of [0.25]) { // [0.25, 0.35] + for (const maxEdgeLength of [0.25]) { // [0.25, 0.35] for (const s of [1, -1]) { // [1,-1] - for (const basePoints of [ - // Sample.createSquareWave(Point3d.create(radians0, 4, 0), 2 * dx0Wave, 0.5, 2 * dx1Wave, numPhase, 1), - Sample.createSquareWave(Point3d.create(radians0, 4, 0), dx0Wave, 0.5, dx1Wave, numPhase, 1), - Sample.createBidirectionalSawtooth(Point3d.create(radians0, 4, 0), - dx0Wave, dx2Wave, dyB, dx1Wave, 2, 3.0, dx0Wave, dx2Wave, dyB, 0), - Sample.createBidirectionalSawtooth(Point3d.create(radians0, 4, 0), - dx0Wave, dx2Wave, dyB, dx1Wave, 2, 2.0, dx0Wave, dx2Wave, -dyB, 0)]) { + for ( + const basePoints of [ + // Sample.createSquareWave(Point3d.create(radians0, 4, 0), 2 * dx0Wave, 0.5, 2 * dx1Wave, numPhase, 1), + Sample.createSquareWave(Point3d.create(radians0, 4, 0), dx0Wave, 0.5, dx1Wave, numPhase, 1), + Sample.createBidirectionalSawtooth(Point3d.create(radians0, 4, 0), dx0Wave, dx2Wave, dyB, dx1Wave, 2, 3.0, dx0Wave, dx2Wave, dyB, 0), + Sample.createBidirectionalSawtooth(Point3d.create(radians0, 4, 0), dx0Wave, dx2Wave, dyB, dx1Wave, 2, 2.0, dx0Wave, dx2Wave, -dyB, 0), + ] + ) { const pointsRTheta = Point3dArray.cloneWithMaxEdgeLength(basePoints, maxEdgeLength); GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(pointsRTheta), outputX0, outputY0 += outputStepY); const points = mapThetaR(pointsRTheta, s, s); @@ -317,15 +329,21 @@ describe("Regularize", () => { dy = 0.0; let axMax = 0.0; for (const perpendicularFactor of [0.85, -1.0, -0.5]) { - for (const generatorFunction of [ - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor), + ] + ) { for (const degrees of [0, 10, 79]) { const points = generatorFunction(numRecursion, perpendicularFactor); - const transform0 = Transform.createFixedPointAndMatrix(points[0], Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform0 = Transform.createFixedPointAndMatrix( + points[0], + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); transform0.multiplyPoint3dArrayInPlace(points); const range = Range3d.createArray(points); axMax = Geometry.maxXY(axMax, range.xLength()); @@ -352,7 +370,8 @@ function testRegularize( dy: number, points: Point3d[], sweepUp: boolean, - sweepDown: boolean): boolean { + sweepDown: boolean, +): boolean { const graph = new HalfEdgeGraph(); const seed = Triangulator.createFaceLoopFromCoordinates(graph, points, true, false)!; const context = new RegularizationContext(graph); @@ -365,7 +384,13 @@ function testRegularize( GeometryCoreTestIO.captureGeometry(allGeometry, mesh, dx, dy); const monotoneFaces: HalfEdge[] = []; const nonMonotoneFaces: HalfEdge[] = []; - RegularizationContext.collectMappedFaceRepresentatives(graph, true, (_seed) => RegularizationContext.isMonotoneFace(_seed), monotoneFaces, nonMonotoneFaces); + RegularizationContext.collectMappedFaceRepresentatives( + graph, + true, + (_seed) => RegularizationContext.isMonotoneFace(_seed), + monotoneFaces, + nonMonotoneFaces, + ); if (monotoneFaces.length !== 0) { const mesh1 = PolyfaceBuilder.graphFacesToPolyface(monotoneFaces); if (sweepUp && sweepDown) { // With both sweeps it SHOULD be a complete facet set ... @@ -377,7 +402,7 @@ function testRegularize( GeometryCoreTestIO.captureGeometry(allGeometry, mesh1, dx + ax, dy, 0.0); } const r0 = -0.25; - const r1 = 1.25; // fractions for non-monotone face annotation line. + const r1 = 1.25; // fractions for non-monotone face annotation line. if (nonMonotoneFaces.length !== 0) { const mesh1 = PolyfaceBuilder.graphFacesToPolyface(nonMonotoneFaces); @@ -388,17 +413,36 @@ function testRegularize( numBad++; } GeometryCoreTestIO.consoleLog(` nonMonotone faces ${numBad} of ${nonMonotoneFaces.length}`); - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(range.fractionToPoint(r0, r0, 0), range.fractionToPoint(r1, r1, 0)), dx + bx, dy, 0.0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(range.fractionToPoint(r0, r0, 0), range.fractionToPoint(r1, r1, 0)), + dx + bx, + dy, + 0.0, + ); dumpEdges = true; } GeometryCoreTestIO.captureGeometry(allGeometry, mesh1, dx + bx, dy, 0.0); } - if (dumpEdges) + if (dumpEdges) { for (const edge of graph.allHalfEdges) { if (edge.id < edge.edgeMate.id) - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYZXYZ( - edge.x, edge.y, 0, edge.faceSuccessor.x, edge.faceSuccessor.y, 0), dx + ax + bx, dy, 0.0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.createXYZXYZ( + edge.x, + edge.y, + 0, + edge.faceSuccessor.x, + edge.faceSuccessor.y, + 0, + ), + dx + ax + bx, + dy, + 0.0, + ); } + } return monotoneFaces.length > 0 && nonMonotoneFaces.length === 0; } @@ -414,13 +458,18 @@ function testFullGraphRegularize( loops: Point3d[][], sweepUp: boolean, sweepDown: boolean, - showParity: boolean): boolean { + showParity: boolean, +): boolean { const graph = new HalfEdgeGraph(); for (const loop of loops) Triangulator.createFaceLoopFromCoordinatesAndMasks(graph, loop, false, HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR)!; const context = new RegularizationContext(graph); context.regularizeGraph(sweepUp, sweepDown); - HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR); + HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( + graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, + ); const range = HalfEdgeGraphOps.graphRange(graph); const ax = 2.5 * range.xLength(); @@ -430,7 +479,13 @@ function testFullGraphRegularize( GeometryCoreTestIO.captureGeometry(allGeometry, mesh, dx, dy); const monotoneFaces: HalfEdge[] = []; const nonMonotoneFaces: HalfEdge[] = []; - RegularizationContext.collectMappedFaceRepresentatives(graph, true, (_seed) => RegularizationContext.isMonotoneFace(_seed), monotoneFaces, nonMonotoneFaces); + RegularizationContext.collectMappedFaceRepresentatives( + graph, + true, + (_seed) => RegularizationContext.isMonotoneFace(_seed), + monotoneFaces, + nonMonotoneFaces, + ); const interiorMonotone = []; const exteriorMonotone = []; for (const face of monotoneFaces) { @@ -450,7 +505,7 @@ function testFullGraphRegularize( GeometryCoreTestIO.captureGeometry(allGeometry, mesh1.clone(), dx + ax, dy, 0.0); } const r0 = -0.25; - const r1 = 1.25; // fractions for non-monotone face annotation line. + const r1 = 1.25; // fractions for non-monotone face annotation line. if (nonMonotoneFaces.length !== 0) { const mesh1 = PolyfaceBuilder.graphFacesToPolyface(nonMonotoneFaces); @@ -461,19 +516,42 @@ function testFullGraphRegularize( numBad++; } GeometryCoreTestIO.consoleLog(` nonMonotone faces ${numBad} of ${nonMonotoneFaces.length}`); - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.create(range.fractionToPoint(r0, r0, 0), range.fractionToPoint(r1, r1, 0)), dx + bx, dy, 0.0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.create(range.fractionToPoint(r0, r0, 0), range.fractionToPoint(r1, r1, 0)), + dx + bx, + dy, + 0.0, + ); dumpEdges = true; } GeometryCoreTestIO.captureGeometry(allGeometry, mesh1, dx + bx, dy, 0.0); } - if (dumpEdges) + if (dumpEdges) { for (const edge of graph.allHalfEdges) { if (edge.id < edge.edgeMate.id) - GeometryCoreTestIO.captureGeometry(allGeometry, LineSegment3d.createXYZXYZ( - edge.x, edge.y, 0, edge.faceSuccessor.x, edge.faceSuccessor.y, 0), dx + ax + bx, dy, 0.0); + GeometryCoreTestIO.captureGeometry( + allGeometry, + LineSegment3d.createXYZXYZ( + edge.x, + edge.y, + 0, + edge.faceSuccessor.x, + edge.faceSuccessor.y, + 0, + ), + dx + ax + bx, + dy, + 0.0, + ); } + } if (showParity) { - const components = HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR); + const components = HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( + graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, + ); for (const component of components) { const interiorFaces = []; for (const f of component) @@ -514,12 +592,26 @@ it("RegularizeSpiralBand", () => { for (const radians0 of [0, 2, 4]) { // [0, -2] ! outputX0 = outputX1; outputY0 = outputY1; - for (const maxEdgeLength of [0.25]) { // [0.25, 0.35] + for (const maxEdgeLength of [0.25]) { // [0.25, 0.35] const s = 1.0; - for (const basePoints of [ - Sample.createSquareWave(Point3d.create(radians0, 4, 0), dx0Wave, 0.5, dx1Wave, numPhase, 1), - Sample.createBidirectionalSawtooth(Point3d.create(radians0, 4, 0), - dx0Wave, dx2Wave, dyB, dx1Wave, numPhase, 1.2, dx0Wave, dx2Wave, dyB, 0)]) { + for ( + const basePoints of [ + Sample.createSquareWave(Point3d.create(radians0, 4, 0), dx0Wave, 0.5, dx1Wave, numPhase, 1), + Sample.createBidirectionalSawtooth( + Point3d.create(radians0, 4, 0), + dx0Wave, + dx2Wave, + dyB, + dx1Wave, + numPhase, + 1.2, + dx0Wave, + dx2Wave, + dyB, + 0, + ), + ] + ) { const pointsRTheta = Point3dArray.cloneWithMaxEdgeLength(basePoints, maxEdgeLength); GeometryCoreTestIO.captureGeometry(allGeometry, LineString3d.create(pointsRTheta), outputX0, outputY0 += outputStepY); const points = mapThetaRWithPitch(pointsRTheta, s, s, 4.0); @@ -549,7 +641,6 @@ it("RegularizeSpiralBand", () => { expect(ck.getNumErrors()).toBe(0); }); /** - * * @param method (0==>testFullGraphRegularize with various sweep controls) (1==>testFullGraphRegularizeAndTriangulate) * @param filename */ @@ -563,14 +654,19 @@ function testStars(method: number, filename: string) { let outputRowY = 0.0; const allGeometry: GeometryQuery[] = []; for (const degrees of [0, 15, 163.2132121]) { - const transform = Transform.createFixedPointAndMatrix(Point3d.create(0, 0, 0), Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform = Transform.createFixedPointAndMatrix( + Point3d.create(0, 0, 0), + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); for (const numOuterStarPoint of [5, 7]) { - for (const loops of [ - Sample.createStarsInStars(25, 10, numOuterStarPoint, 1, 0.5, 3, 2, 0, true), - Sample.createStarsInStars(25, 10, numOuterStarPoint, 1, 0.5, 3, 2, 1, true), - Sample.createStarsInStars(25, 10, numOuterStarPoint, 0.9, 0.2, 3, 2, 3, true), - Sample.createStarsInStars(25, 10, numOuterStarPoint, 0.9, 0.2, 3, 2, 5, true), - ]) { + for ( + const loops of [ + Sample.createStarsInStars(25, 10, numOuterStarPoint, 1, 0.5, 3, 2, 0, true), + Sample.createStarsInStars(25, 10, numOuterStarPoint, 1, 0.5, 3, 2, 1, true), + Sample.createStarsInStars(25, 10, numOuterStarPoint, 0.9, 0.2, 3, 2, 3, true), + Sample.createStarsInStars(25, 10, numOuterStarPoint, 0.9, 0.2, 3, 2, 5, true), + ] + ) { // GeometryCoreTestIO.consoleLog([outputX0, outputY0]); transform.multiplyPoint3dArrayArrayInPlace(loops); for (const loop of loops) @@ -580,8 +676,8 @@ function testStars(method: number, filename: string) { testFullGraphRegularizeAndTriangulate(ck, allGeometry, outputX0, outputY0 += outputStepY, loops); } else { if (!testFullGraphRegularize(ck, allGeometry, outputX0, outputY0 += outputStepY, loops, true, true, true)) { - if (testFullGraphRegularize(ck, allGeometry, outputX0, outputY0 += outputStepY, loops, true, false, false)) { } - if (testFullGraphRegularize(ck, allGeometry, outputX0, outputY0 += outputStepY, loops, false, true, false)) { } + if (testFullGraphRegularize(ck, allGeometry, outputX0, outputY0 += outputStepY, loops, true, false, false)) {} + if (testFullGraphRegularize(ck, allGeometry, outputX0, outputY0 += outputStepY, loops, false, true, false)) {} } } outputY0 = outputRowY; @@ -597,62 +693,64 @@ function testStars(method: number, filename: string) { expect(ck.getNumErrors()).toBe(0); } -/** - * - */ +/** */ it("FullGraphRegularizeStars", () => { testStars(0, "FullGraphRegularizeStars"); }); -/** - * - */ +/** */ it("FullGraphTriangulateStars", () => { testStars(1, "FullGraphTriangulateStars"); }); -/** - */ +/** */ function testFullGraphRegularizeAndTriangulate( _ck: Checker, allGeometry: GeometryQuery[], dx: number, dy: number, - loops: Point3d[][]): boolean { + loops: Point3d[][], +): boolean { const graph = new HalfEdgeGraph(); for (const loop of loops) Triangulator.createFaceLoopFromCoordinatesAndMasks(graph, loop, true, HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR)!; const context = new RegularizationContext(graph); context.regularizeGraph(true, true); - HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(graph, new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR); + HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( + graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, + ); const range = HalfEdgeGraphOps.graphRange(graph); const by = 2.0 * range.yLength(); const mesh = PolyfaceBuilder.graphToPolyface(graph); GeometryCoreTestIO.captureGeometry(allGeometry, mesh, dx, dy); const monotoneFaces: HalfEdge[] = []; const nonMonotoneFaces: HalfEdge[] = []; - RegularizationContext.collectMappedFaceRepresentatives(graph, true, (_seed) => RegularizationContext.isMonotoneFace(_seed), monotoneFaces, nonMonotoneFaces); + RegularizationContext.collectMappedFaceRepresentatives( + graph, + true, + (_seed) => RegularizationContext.isMonotoneFace(_seed), + monotoneFaces, + nonMonotoneFaces, + ); for (const seed of monotoneFaces) { if (!seed.isMaskSet(HalfEdgeMask.EXTERIOR)) Triangulator.triangulateSingleMonotoneFace(graph, seed); } - const mesh2 = PolyfaceBuilder.graphToPolyface(graph, undefined, - (faceSeed: HalfEdge) => { - return !faceSeed.isMaskSet(HalfEdgeMask.EXTERIOR); - }); + const mesh2 = PolyfaceBuilder.graphToPolyface(graph, undefined, (faceSeed: HalfEdge) => { + return !faceSeed.isMaskSet(HalfEdgeMask.EXTERIOR); + }); GeometryCoreTestIO.captureGeometry(allGeometry, mesh2, dx, dy + by, 0.0); Triangulator.flipTriangles(graph); - const mesh3 = PolyfaceBuilder.graphToPolyface(graph, undefined, - (faceSeed: HalfEdge) => { - return !faceSeed.isMaskSet(HalfEdgeMask.EXTERIOR); - }); + const mesh3 = PolyfaceBuilder.graphToPolyface(graph, undefined, (faceSeed: HalfEdge) => { + return !faceSeed.isMaskSet(HalfEdgeMask.EXTERIOR); + }); GeometryCoreTestIO.captureGeometry(allGeometry, mesh3, dx, dy + 2 * by, 0.0); return true; } -/** - * - */ +/** */ it("SingleFaceTriangulation", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -660,17 +758,15 @@ it("SingleFaceTriangulation", () => { const ay = 10; let dx = 0.0; let dy = 0.0; - for (const data of [ - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, -2, -2, - 1, ax, ay, 0, 0), - 3, 3, 0, 0, 1, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, 0, -2, - 1, ax, ay, 0, 0), - 4, 2, 0, 0, 1, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, -2, - 1, ax, ay, 0, 0), - 4, 2, 1, 0, 2, 1), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 2, - 1, ax, ay, 0, 0), - 3, 3, 1, 1, 2, 2), - new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 0, 1, ax, ay, 0, 0), - 3, 3, 1, 0, 2, 1)]) { + for ( + const data of [ + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, -2, -2, -1, ax, ay, 0, 0), 3, 3, 0, 0, 1, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(-1, 0, -2, -1, ax, ay, 0, 0), 4, 2, 0, 0, 1, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, -2, -1, ax, ay, 0, 0), 4, 2, 1, 0, 2, 1), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 2, -1, ax, ay, 0, 0), 3, 3, 1, 1, 2, 2), + new VerticalStaggerData(Sample.createVerticalStaggerPolygon(1, 0, 0, 1, ax, ay, 0, 0), 3, 3, 1, 0, 2, 1), + ] + ) { testFullGraphRegularizeAndTriangulate(ck, allGeometry, dx, dy, [data.points]); dx += 20.0; dy = 0.0; @@ -679,9 +775,7 @@ it("SingleFaceTriangulation", () => { expect(ck.getNumErrors()).toBe(0); }); -/** - * - */ +/** */ it("SingleFaceTriangulation", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; @@ -716,23 +810,24 @@ it("SingleFaceTriangulation", () => { ]; GeometryCoreTestIO.consoleLog("outerCurvePts = ", outerCurvePts.length / 3); - const innerCurvePts = [Point3d.create(-1515.307337, -125, 55.112819), - Point3d.create(-1528.284271, -125, 63.783729), - Point3d.create(-1536.955181, -125, 76.760663), - Point3d.create(-1540, -125, 92.068), - Point3d.create(-1536.955181, -125, 107.375337), - Point3d.create(-1528.284271, -125, 120.352271), - Point3d.create(-1515.307337, -125, 129.023181), - Point3d.create(-1500, -125, 132.068), - Point3d.create(-1484.692663, -125, 129.023181), - Point3d.create(-1471.715729, -125, 120.352271), - Point3d.create(-1463.044819, -125, 107.375337), - Point3d.create(-1460, -125, 92.068), - Point3d.create(-1463.044819, -125, 76.760663), - Point3d.create(-1471.715729, -125, 63.783729), - Point3d.create(-1484.692663, -125, 55.112819), - Point3d.create(-1500, -125, 52.068), - Point3d.create(-1515.307337, -125, 55.112819), + const innerCurvePts = [ + Point3d.create(-1515.307337, -125, 55.112819), + Point3d.create(-1528.284271, -125, 63.783729), + Point3d.create(-1536.955181, -125, 76.760663), + Point3d.create(-1540, -125, 92.068), + Point3d.create(-1536.955181, -125, 107.375337), + Point3d.create(-1528.284271, -125, 120.352271), + Point3d.create(-1515.307337, -125, 129.023181), + Point3d.create(-1500, -125, 132.068), + Point3d.create(-1484.692663, -125, 129.023181), + Point3d.create(-1471.715729, -125, 120.352271), + Point3d.create(-1463.044819, -125, 107.375337), + Point3d.create(-1460, -125, 92.068), + Point3d.create(-1463.044819, -125, 76.760663), + Point3d.create(-1471.715729, -125, 63.783729), + Point3d.create(-1484.692663, -125, 55.112819), + Point3d.create(-1500, -125, 52.068), + Point3d.create(-1515.307337, -125, 55.112819), ]; // placement points for replicating the hole: diff --git a/core/geometry/src/test/topology/Triangulator.test.ts b/core/geometry/src/test/topology/Triangulator.test.ts index 85db8096cbd2..831ade62d47b 100644 --- a/core/geometry/src/test/topology/Triangulator.test.ts +++ b/core/geometry/src/test/topology/Triangulator.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { describe, expect, it } from "vitest"; import * as fs from "fs"; +import { describe, expect, it } from "vitest"; import { GeometryQuery } from "../../curve/GeometryQuery"; import { LineSegment3d } from "../../curve/LineSegment3d"; import { LineString3d } from "../../curve/LineString3d"; @@ -54,30 +54,51 @@ describe("Triangulation", () => { const dx = 40.0; const dy = 30.0; const allGeometry: GeometryQuery[] = []; - for (const myLoops of [ - [[Point3d.create(1, -1, 0), Point3d.create(2, -1, 0), Point3d.create(2, 1, 0)]], - // outer - [[Point3d.create(0, 0, 0), Point3d.create(3, -2, 0), Point3d.create(6, 2, 0), Point3d.create(5, 5, 0), Point3d.create(4, 2, 0), Point3d.create(1, 3, 0)], - // hole - [Point3d.create(1, 1, 0), Point3d.create(2, 2, 0), Point3d.create(3, 1, 0)]], - // triangle with one hole - [[Point3d.create(0, 0, 0), Point3d.create(5, -5, 0), Point3d.create(5, 5, 0)], - [Point3d.create(2, 1, 0), Point3d.create(3, 1, 0), Point3d.create(3, 0, 0)]], - // triangle with one hole, CCW orientation on the hole (expect it to be corrected) - [[Point3d.create(0, 0, 0), Point3d.create(5, -5, 0), Point3d.create(5, 5, 0)], - [Point3d.create(2, 1, 0), Point3d.create(3, 0, 0), Point3d.create(3, 1, 0)]], - // rectangle with 2 holes - [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], - [Point3d.create(1, 1, 0), Point3d.create(2, 2, 0), Point3d.create(2, 1, 0)], - [Point3d.create(3, 1.5, 0), Point3d.create(4, 3, 0), Point3d.create(4, 1.5, 0)]], - // rectangle with 2 holes, duplicate points here and there - [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], - [Point3d.create(1, 1, 0), Point3d.create(2, 2, 0), Point3d.create(2, 1, 0), Point3d.create(2, 1, 0)], - [Point3d.create(3, 1.5, 0), Point3d.create(4, 3, 0), Point3d.create(4, 1.5, 0), Point3d.create(3, 1.5, 0)]], - Sample.createStarsInStars(11, 8, 5, 2, 1, 4, 3, 3, false), - Sample.createStarsInStars(10, 10, 2, 2, 2, 4, 3, 3, false), - Sample.createStarsInStars(14, 8, 6, 2, 0.4, 5, 3, 4, false)]) { - + for ( + const myLoops of [ + [[Point3d.create(1, -1, 0), Point3d.create(2, -1, 0), Point3d.create(2, 1, 0)]], + // outer + [ + [ + Point3d.create(0, 0, 0), + Point3d.create(3, -2, 0), + Point3d.create(6, 2, 0), + Point3d.create(5, 5, 0), + Point3d.create(4, 2, 0), + Point3d.create(1, 3, 0), + ], // hole + [Point3d.create(1, 1, 0), Point3d.create(2, 2, 0), Point3d.create(3, 1, 0)], + ], + // triangle with one hole + [[Point3d.create(0, 0, 0), Point3d.create(5, -5, 0), Point3d.create(5, 5, 0)], [ + Point3d.create(2, 1, 0), + Point3d.create(3, 1, 0), + Point3d.create(3, 0, 0), + ]], + // triangle with one hole, CCW orientation on the hole (expect it to be corrected) + [[Point3d.create(0, 0, 0), Point3d.create(5, -5, 0), Point3d.create(5, 5, 0)], [ + Point3d.create(2, 1, 0), + Point3d.create(3, 0, 0), + Point3d.create(3, 1, 0), + ]], + // rectangle with 2 holes + [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], [ + Point3d.create(1, 1, 0), + Point3d.create(2, 2, 0), + Point3d.create(2, 1, 0), + ], [Point3d.create(3, 1.5, 0), Point3d.create(4, 3, 0), Point3d.create(4, 1.5, 0)]], + // rectangle with 2 holes, duplicate points here and there + [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], [ + Point3d.create(1, 1, 0), + Point3d.create(2, 2, 0), + Point3d.create(2, 1, 0), + Point3d.create(2, 1, 0), + ], [Point3d.create(3, 1.5, 0), Point3d.create(4, 3, 0), Point3d.create(4, 1.5, 0), Point3d.create(3, 1.5, 0)]], + Sample.createStarsInStars(11, 8, 5, 2, 1, 4, 3, 3, false), + Sample.createStarsInStars(10, 10, 2, 2, 2, 4, 3, 3, false), + Sample.createStarsInStars(14, 8, 6, 2, 0.4, 5, 3, 4, false), + ] + ) { let xShift = 0; for (const loop of myLoops) { const g = LineString3d.create(loop); @@ -129,18 +150,34 @@ describe("Triangulation", () => { const dx = 40.0; const dy = 30.0; const allGeometry: GeometryQuery[] = []; - for (const myLoops of [ - // rectangle with hole not fully contained - [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], - [Point3d.create(1, -1, 0), Point3d.create(2, -1, 0), Point3d.create(2, 1, 0)]], - // Edge-Edge contact from hole to parent along lower edge. - [[Point3d.create(0, 0, 0), Point3d.create(4, 0, 0), Point3d.create(8, 0, 0), Point3d.create(10, 0, 0), Point3d.create(10, 5, 0), Point3d.create(0, 5, 0)], - [Point3d.create(4, 0, 0), Point3d.create(8, 0, 0), Point3d.create(8, 2, 0), Point3d.create(4, 2, 0)]], - // Edge-Edge contact from hole to parent along right edge. - [[Point3d.create(10, 0, 0), Point3d.create(10, 4), Point3d.create(10, 8), Point3d.create(10, 10, 0), Point3d.create(0, 10, 0), Point3d.create(0, 0, 0)], - [Point3d.create(10, 4), Point3d.create(10, 8), Point3d.create(6, 8)]], - ]) { - + for ( + const myLoops of [ + // rectangle with hole not fully contained + [[Point3d.create(0, 0, 0), Point3d.create(5, 0, 0), Point3d.create(5, 5, 0), Point3d.create(0, 5, 0)], [ + Point3d.create(1, -1, 0), + Point3d.create(2, -1, 0), + Point3d.create(2, 1, 0), + ]], + // Edge-Edge contact from hole to parent along lower edge. + [[ + Point3d.create(0, 0, 0), + Point3d.create(4, 0, 0), + Point3d.create(8, 0, 0), + Point3d.create(10, 0, 0), + Point3d.create(10, 5, 0), + Point3d.create(0, 5, 0), + ], [Point3d.create(4, 0, 0), Point3d.create(8, 0, 0), Point3d.create(8, 2, 0), Point3d.create(4, 2, 0)]], + // Edge-Edge contact from hole to parent along right edge. + [[ + Point3d.create(10, 0, 0), + Point3d.create(10, 4), + Point3d.create(10, 8), + Point3d.create(10, 10, 0), + Point3d.create(0, 10, 0), + Point3d.create(0, 0, 0), + ], [Point3d.create(10, 4), Point3d.create(10, 8), Point3d.create(6, 8)]], + ] + ) { let xShift = 0; for (const loop of myLoops) { const g = LineString3d.create(loop); @@ -184,7 +221,8 @@ describe("Triangulation", () => { const yShiftVector = Vector3d.create(0, 2, 0); const rotation = Transform.createFixedPointAndMatrix( Point3d.create(1.5 * numPhase, 0, 0), - Matrix3d.createRotationAroundVector(Vector3d.unitZ(), Angle.createDegrees(degrees)) as Matrix3d); + Matrix3d.createRotationAroundVector(Vector3d.unitZ(), Angle.createDegrees(degrees)) as Matrix3d, + ); const points = Sample.createSquareWave(Point3d.create(0, 0, 0), 1, 0.5, 2, numPhase, 1); rotation.multiplyVector(yShiftVector, yShiftVector); if (degrees !== 0.0) @@ -218,7 +256,14 @@ describe("Triangulation", () => { }); }); -function testGraphFromSegments(ck: Checker, x0: number, segments: LineSegment3d[], expectSingleLoop: boolean, fileName: string, outputAnnotatedGeometry: boolean = true) { +function testGraphFromSegments( + ck: Checker, + x0: number, + segments: LineSegment3d[], + expectSingleLoop: boolean, + fileName: string, + outputAnnotatedGeometry: boolean = true, +) { const theGraph = HalfEdgeGraphMerge.formGraphFromSegments(segments); GraphChecker.verifySignedFaceCounts(ck, theGraph, undefined, 1, undefined); const dx = x0; @@ -241,7 +286,6 @@ function testGraphFromSegments(ck: Checker, x0: number, segments: LineSegment3d[ // } // exportGraph(theGraph, "AfterTriangulation"); GeometryCoreTestIO.saveGeometry(allGeometry, "Graph", fileName); - } describe("MonotoneFaces", () => { // 5 sides -- tall rectangle with upward V at bottom edge. @@ -274,17 +318,19 @@ describe("MonotoneFaces", () => { const ax = 5.0; const ay = 10.0; // const e = 0.1; - for (const loopA of [ - Sample.createVerticalStaggerPolygon(-1, -2, 4, 3, ax, ay, 0, 0), - Sample.createVerticalStaggerPolygon(3, 0, 0, 4, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(3, e, e, 3, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(3, 0, 0, 3, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(-3, 2, 1, 2, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(3, 0, 0, 3, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(3, 0, 0, -3, ax, ay, 0, 0), - // Sample.createVerticalStaggerPolygon(3, 0, 0, -5, ax, ay, -1, 0), - // Sample.createVerticalStaggerPolygon(7, 0, 0, -6, ax, ay, -0.5, 0), - ]) { + for ( + const loopA of [ + Sample.createVerticalStaggerPolygon(-1, -2, 4, 3, ax, ay, 0, 0), + Sample.createVerticalStaggerPolygon(3, 0, 0, 4, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(3, e, e, 3, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(3, 0, 0, 3, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(-3, 2, 1, 2, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(3, 0, 0, 3, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(3, 0, 0, -3, ax, ay, 0, 0), + // Sample.createVerticalStaggerPolygon(3, 0, 0, -5, ax, ay, -1, 0), + // Sample.createVerticalStaggerPolygon(7, 0, 0, -6, ax, ay, -0.5, 0), + ] + ) { const segmentA = Sample.convertPointsToSegments(loopA); testGraphFromSegments(ck, id * 30, segmentA, true, `LoopA${id++}`, false); } @@ -342,7 +388,6 @@ describe("MonotoneFaces", () => { GeometryCoreTestIO.saveGeometry(allGeometry, "Graph", "HashMerge"); expect(ck.getNumErrors()).toBe(0); }); - }); describe("Triangulation", () => { @@ -365,15 +410,21 @@ describe("Triangulation", () => { for (const perpendicularFactor of [0.85, -1.0, -0.5]) { let yMax = 0.0; const baseVectorB = baseVectorA.clone(); - for (const generatorFunction of [ - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor), + ] + ) { for (const degrees of [0, 10, 79]) { const points = generatorFunction(numRecursion, perpendicularFactor); - const transform0 = Transform.createFixedPointAndMatrix(points[0], Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform0 = Transform.createFixedPointAndMatrix( + points[0], + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); transform0.multiplyPoint3dArrayInPlace(points); const range = Range3d.createArray(points); const dy = range.yLength(); @@ -500,7 +551,7 @@ describe("Triangulation", () => { } // run the triangulator with the array rotated to each x-axis point, and one of every numThetaSkip points around the arc. let y0 = 0.0; - for (let rotation = 0; rotation < points.length; rotation += (rotation < numColinear ? 1 : numThetaSkip)) { + for (let rotation = 0; rotation < points.length; rotation += rotation < numColinear ? 1 : numThetaSkip) { const pointsB = rotateArray(points, rotation); const graph = Triangulator.createTriangulatedGraphFromSingleLoop(pointsB); if (graph) { @@ -527,32 +578,34 @@ describe("Triangulation", () => { const r = 1.0; let x0 = 0.0; // promise: all x above x0 is free space. - for (const points of [ - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 2, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 3, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 4, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 6, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 1, 4, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 1, 4, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 90), 2, 5, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 3, 9, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 90), 3, 4, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(-10, 270), 2, 8, false), - Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(-30, 200), 5, 12, false), - Sample.createCutPie(0, 0, 100 * r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), - ]) { + for ( + const points of [ + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 2, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 3, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 4, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 2, 6, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 1, 4, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 1, 4, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 90), 2, 5, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 3, 9, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 90), 3, 4, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(-10, 270), 2, 8, false), + Sample.createCutPie(0, 0, r, AngleSweep.createStartEndDegrees(-30, 200), 5, 12, false), + Sample.createCutPie(0, 0, 100 * r, AngleSweep.createStartEndDegrees(0, 180), 5, 12, false), + ] + ) { // run the triangulator with the array rotated to each x-axis point, and one of every numThetaSkip points around the arc. let y0 = 0.0; const range = Range3d.createArray(points); - const expectedTriangleCount = points.length - 2; // we know that the point array is unclosed !!! + const expectedTriangleCount = points.length - 2; // we know that the point array is unclosed !!! const dx = range.xLength(); const dy = range.yLength(); const ex = x0 - range.low.x; const polygonArea = PolygonOps.areaXY(points); x0 += r; - for (let rotation = 0; rotation < points.length; rotation += (rotation < 4 ? 1 : numThetaSkip)) { + for (let rotation = 0; rotation < points.length; rotation += rotation < 4 ? 1 : numThetaSkip) { const pointsB = rotateArray(points, rotation); GeometryCoreTestIO.captureCloneGeometry(allGeometry, pointsB, x0, y0); Triangulator.clearAndEnableDebugGraphCapture(true); @@ -608,19 +661,19 @@ describe("Triangulation", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; let x = 0; - for (const points of [ - [{ x: 5.36, y: 8.85, z: 23.78 }, - { x: 8.822141987513945, y: 6.843546977282015, z: 23.78 }, - { x: 8.822141987513945, y: 6.843546977282015, z: 23.78 }, - { x: 5.36, y: 8.85, z: 23.78 }, - { x: 5.36, y: 8.85, z: 23.78 }], - [{ x: 0, y: 0, z: 0 }, - { x: 3.4621419875139443, y: -2.0064530227179844, z: 0 }, - { x: 0, y: 0, z: 0 }], - [{ x: 0, y: 0, z: 0 }, - { x: 2.9577539019415324, y: -0.8576720613542541, z: 0 }, - { x: 8.881784197001252e-16, y: 0, z: 0 }], - ]) { + for ( + const points of [ + [ + { x: 5.36, y: 8.85, z: 23.78 }, + { x: 8.822141987513945, y: 6.843546977282015, z: 23.78 }, + { x: 8.822141987513945, y: 6.843546977282015, z: 23.78 }, + { x: 5.36, y: 8.85, z: 23.78 }, + { x: 5.36, y: 8.85, z: 23.78 }, + ], + [{ x: 0, y: 0, z: 0 }, { x: 3.4621419875139443, y: -2.0064530227179844, z: 0 }, { x: 0, y: 0, z: 0 }], + [{ x: 0, y: 0, z: 0 }, { x: 2.9577539019415324, y: -0.8576720613542541, z: 0 }, { x: 8.881784197001252e-16, y: 0, z: 0 }], + ] + ) { const graph = Triangulator.createTriangulatedGraphFromSingleLoop(points); const polyface = graph ? PolyfaceBuilder.graphToPolyface(graph) : undefined; if (!ck.testTrue(graph === undefined || polyface!.facetCount === 0, "degenerate triangle produced no facets.")) { @@ -644,7 +697,8 @@ describe("Triangulation", () => { Point3d.create(6, 2, 0), Point3d.create(a, 4, 0), Point3d.create(4, 3, 0), - Point3d.create(0, 3, 0)]; + Point3d.create(0, 3, 0), + ]; let counter1 = 0; const needParams = true; for (let startIndex = 0; startIndex < basePoints.length; startIndex++) { @@ -661,8 +715,14 @@ describe("Triangulation", () => { sweepContour!.emitFacets(builder, false); const polyface = builder.claimPolyface(true); - if (!ck.testExactNumber(arrowPoints.length - 2, polyface.facetCount, `Triangle count in arrow ${counter0}.${counter1} needParams${needParams}`) - || Checker.noisy.acsArrows) { + if ( + !ck.testExactNumber( + arrowPoints.length - 2, + polyface.facetCount, + `Triangle count in arrow ${counter0}.${counter1} needParams${needParams}`, + ) + || Checker.noisy.acsArrows + ) { GeometryCoreTestIO.consoleLog(` Triangulation From Start index ${startIndex} needParams ${needParams} `); GeometryCoreTestIO.consoleLog(` arrow parameter ${a}`); GeometryCoreTestIO.consoleLog(` Facet Count ${polyface.facetCount} counter0 ${counter0} counter1 ${counter1}`); @@ -690,7 +750,8 @@ describe("Triangulation", () => { Point3d.create(0, 0, 0), Point3d.create(4, 0, 0), Point3d.create(0, a, 0), - Point3d.create(4, a, 0)]; + Point3d.create(4, a, 0), + ]; for (let startIndex = 0; startIndex < basePoints.length; startIndex++) { let dy = 0.0; const shiftedPoints = []; @@ -718,7 +779,8 @@ describe("Triangulation", () => { Point3d.create(0, 0, 0), Point3d.create(4, 0, 0), Point3d.create(4, a, 0), - Point3d.create(3, 1, 0)]; + Point3d.create(3, 1, 0), + ]; for (let startIndex = 0; startIndex < basePoints.length; startIndex++) { let dy = 0.0; const shiftedPoints = []; @@ -753,7 +815,8 @@ describe("Triangulation", () => { { x: 968, y: 3612 + dy14 }, { x: 960, y: 3612 }, { x: 960, y: 3616 }, - { x: 960, y: 3616 }]); + { x: 960, y: 3616 }, + ]); } // multiple pinch points: const x0 = 960; @@ -802,10 +865,17 @@ describe("Triangulation", () => { }); const dartInTriangleOuter = [ - Point3d.create(1, -4), Point3d.create(13, 0), Point3d.create(1, 4), Point3d.create(1, -4), + Point3d.create(1, -4), + Point3d.create(13, 0), + Point3d.create(1, 4), + Point3d.create(1, -4), ]; const dartInTriangleInner = [ - Point3d.create(5, 0), Point3d.create(3, -2), Point3d.create(9, 0), Point3d.create(3, 2), Point3d.create(5, 0), + Point3d.create(5, 0), + Point3d.create(3, -2), + Point3d.create(9, 0), + Point3d.create(3, 2), + Point3d.create(5, 0), ]; it("DartInTriangle", () => { @@ -959,7 +1029,8 @@ describe("Triangulation", () => { [-0.801128 + ex0, -3.712995 + ey0], [-0.806443, -3.737396], - [0, 1.593037e-11]]; + [0, 1.593037e-11], + ]; } const _messyShape = [ { @@ -968,7 +1039,8 @@ describe("Triangulation", () => { trans: [ [0.998765, 0.049683, -1.032365e-16, 532612.092389], [-0.049683, 0.998765, -5.489607e-20, 212337.746743], - [1.031063e-16, 5.183973e-18, 1, 7.41464]], + [1.031063e-16, 5.183973e-18, 1, 7.41464], + ], }, }, ]; @@ -1044,7 +1116,13 @@ describe("Triangulation", () => { * Caller should precede with Triangulator.clearAndEnableDebugGraphCapture(true); * @return whether tests succeeded */ - function tryExpandConvex2(ck: Checker, allGeometry: GeometryQuery[], graph1: HalfEdgeGraph | undefined, graph2: HalfEdgeGraph | undefined, position: Point2d): boolean { + function tryExpandConvex2( + ck: Checker, + allGeometry: GeometryQuery[], + graph1: HalfEdgeGraph | undefined, + graph2: HalfEdgeGraph | undefined, + position: Point2d, + ): boolean { if (ck.testDefined(graph1, "Triangulation failed")) { const range = HalfEdgeGraphOps.graphRange(graph1); const numRemovedEdges1 = tryExpandConvex(ck, allGeometry, graph1, 1, position); @@ -1104,16 +1182,22 @@ describe("Triangulation", () => { const position = Point2d.createZero(); for (const numRecursion of [1, 2, 3]) { for (const perpendicularFactor of [0.85, -1.0, -0.5]) { - for (const generatorFunction of [ - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), - (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor)]) { + for ( + const generatorFunction of [ + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalSquareReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalDiamondConvexPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalHatReversingPattern(_numRecursion, _perpendicularFactor), + (_numRecursion: number, _perpendicularFactor: number) => Sample.createFractalLMildConcavePatter(_numRecursion, _perpendicularFactor), + ] + ) { for (const degrees of [0, 10, 79]) { const points = generatorFunction(numRecursion, perpendicularFactor); let range = Range3d.createArray(points); - const transform = Transform.createFixedPointAndMatrix(range.center, Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees))); + const transform = Transform.createFixedPointAndMatrix( + range.center, + Matrix3d.createRotationAroundAxisIndex(2, Angle.createDegrees(degrees)), + ); transform.multiplyPoint3dArrayInPlace(points); range = Range3d.createArray(points); Triangulator.clearAndEnableDebugGraphCapture(true); @@ -1160,7 +1244,7 @@ describe("Triangulation", () => { const ck = new Checker(); const allGeometry: GeometryQuery[] = []; const skipTranslate = false; // false: non-overlapping output meshes; true: output as-is for debugging - const drawCircles = false; // true: output a circle at each point for debugging + const drawCircles = false; // true: output a circle at each point for debugging const xMargin = 10; const yMargin = 10; let x0 = 0; @@ -1195,7 +1279,7 @@ describe("Triangulation", () => { points: Point3d[]; range: Range3d; name: string; - }; + } const data: Dataset[] = []; // Minimal subset of dtmPointsSmall.imjs that reproduced an infinite loop: @@ -1205,11 +1289,11 @@ describe("Triangulation", () => { // * A and C are skirt points "underneath" the hull const minimumPts = [ Point3d.create(29.38440446735313, -46.664765115079454, 49.58476279246775), // 0 - Point3d.create(78.7791513050385, -46.66476333748565, 47.07249011143456), // 1 - Point3d.create(78.77823641152756, -46.66476229743052, 45.60256502436375), // A - Point3d.create(51.51740469722874, -46.66476418232037, 48.26649267203187), // B - Point3d.create(51.5164898037178, -46.66476314226524, 46.79656758496107), // C - Point3d.create(55.21859962987817, 29.55516271079307, 48.370060922134726), // 2 + Point3d.create(78.7791513050385, -46.66476333748565, 47.07249011143456), // 1 + Point3d.create(78.77823641152756, -46.66476229743052, 45.60256502436375), // A + Point3d.create(51.51740469722874, -46.66476418232037, 48.26649267203187), // B + Point3d.create(51.5164898037178, -46.66476314226524, 46.79656758496107), // C + Point3d.create(55.21859962987817, 29.55516271079307, 48.370060922134726), // 2 Point3d.create(50.334340847282135, -46.66476423327051, 48.33850061288565), // D ]; data.push({ points: minimumPts, range: Range3d.create(...minimumPts), name: "7 points" }); @@ -1229,7 +1313,7 @@ describe("Triangulation", () => { ck.testLE(numSharpEdges, minNumSharpEdges, "larger tolerance should reduce sharp edge count"); minNumSharpEdges = Math.min(numSharpEdges, minNumSharpEdges); if (!skipTranslate) - x0 += datum.range.xLength() + xMargin; // as meshes progress left to right, more skirt points vanish + x0 += datum.range.xLength() + xMargin; // as meshes progress left to right, more skirt points vanish } if (!skipTranslate) { x0 = z0 = 0; diff --git a/core/geometry/src/topology/ChainMerge.ts b/core/geometry/src/topology/ChainMerge.ts index 73b6bc3b4d70..ed0a81c340f5 100644 --- a/core/geometry/src/topology/ChainMerge.ts +++ b/core/geometry/src/topology/ChainMerge.ts @@ -58,7 +58,8 @@ class ChainMergeContextValidatedOptions { return vector.normalizeWithDefault( ChainMergeContextValidatedOptions._defaultPrimarySortDirection.x, ChainMergeContextValidatedOptions._defaultPrimarySortDirection.y, - ChainMergeContextValidatedOptions._defaultPrimarySortDirection.z); + ChainMergeContextValidatedOptions._defaultPrimarySortDirection.z, + ); } /** * PRIVATE constructor -- assumes all inputs are validated in public create method !!!! @@ -101,7 +102,6 @@ class ChainMergeContextValidatedOptions { * @internal */ export class ChainMergeContext { - private _graph: HalfEdgeGraph; private _options: ChainMergeContextValidatedOptions; private _plane?: PlaneAltitudeEvaluator; @@ -111,14 +111,22 @@ export class ChainMergeContext { this._options = options; } /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */ - public set plane(value: PlaneAltitudeEvaluator | undefined) { this._plane = value; } + public set plane(value: PlaneAltitudeEvaluator | undefined) { + this._plane = value; + } /** Property access for the reference plane. */ - public get plane(): PlaneAltitudeEvaluator | undefined { return this._plane; } + public get plane(): PlaneAltitudeEvaluator | undefined { + return this._plane; + } /** Save a reference plane for later use, e.g. in addSegmentsOnPlane */ - public set convexClipper(value: ConvexClipPlaneSet | undefined) { this._convexClipper = value; } + public set convexClipper(value: ConvexClipPlaneSet | undefined) { + this._convexClipper = value; + } /** Property access for the reference plane. */ - public get convexClipper(): ConvexClipPlaneSet | undefined { return this._convexClipper; } + public get convexClipper(): ConvexClipPlaneSet | undefined { + return this._convexClipper; + } /** * * Construct an empty chain merge graph. @@ -154,12 +162,19 @@ export class ChainMergeContext { let a0 = points.evaluateUncheckedIndexPlaneAltitude(i0, plane); let i1 = addClosure ? 0 : 1; let a1; - for (; i1 < points.length; i0 = i1++ , a0 = a1) { + for (; i1 < points.length; i0 = i1++, a0 = a1) { a1 = points.evaluateUncheckedIndexPlaneAltitude(i1, plane); if (Geometry.isSmallMetricDistance(a0) && Geometry.isSmallMetricDistance(a1)) this._graph.createEdgeXYZXYZ( - points.getXAtUncheckedPointIndex(i0), points.getYAtUncheckedPointIndex(i0), points.getZAtUncheckedPointIndex(i0), 0, - points.getXAtUncheckedPointIndex(i1), points.getYAtUncheckedPointIndex(i1), points.getZAtUncheckedPointIndex(i1), 0); + points.getXAtUncheckedPointIndex(i0), + points.getYAtUncheckedPointIndex(i0), + points.getZAtUncheckedPointIndex(i0), + 0, + points.getXAtUncheckedPointIndex(i1), + points.getYAtUncheckedPointIndex(i1), + points.getZAtUncheckedPointIndex(i1), + 0, + ); } } /** @@ -214,7 +229,7 @@ export class ChainMergeContext { break; if (node0.distanceXYZ(node1) <= xyzTolerance) { HalfEdge.pinch(node0, node1); - node1.setXYZFrom(node0); // force true equal coordinates. + node1.setXYZFrom(node0); // force true equal coordinates. } } } @@ -230,7 +245,7 @@ export class ChainMergeContext { if (!node0.isMaskSet(visitMask)) { const ls = LineString3d.create(); ls.addPointXYZ(node0.x, node0.y, node0.z); - for (; ;) { + for (;;) { node0.setMask(visitMask); node0.edgeMate.setMask(visitMask); node0 = node0.faceSuccessor; @@ -250,7 +265,7 @@ export class ChainMergeContext { if (!node0.isMaskSet(visitMask)) { const points = new GrowableXYZArray(); points.pushXYZ(node0.x, node0.y, node0.z); - for (; ;) { + for (;;) { node0.setMask(visitMask); node0.edgeMate.setMask(visitMask); node0 = node0.faceSuccessor; @@ -272,8 +287,10 @@ export class ChainMergeContext { private exciseAndMarkSlingEdges(mask: HalfEdgeMask): number { let n = 0; for (const p of this._graph.allHalfEdges) { - if (p.distanceXYZ(p.edgeMate) < this._options.tolerance - && !p.isMaskSet(mask)) { + if ( + p.distanceXYZ(p.edgeMate) < this._options.tolerance + && !p.isMaskSet(mask) + ) { const q = p.edgeMate; HalfEdge.pinch(p, p.vertexPredecessor); HalfEdge.pinch(q, q.vertexPredecessor); diff --git a/core/geometry/src/topology/Graph.ts b/core/geometry/src/topology/Graph.ts index ed0c037c9ece..190b77fc46c8 100644 --- a/core/geometry/src/topology/Graph.ts +++ b/core/geometry/src/topology/Graph.ts @@ -47,7 +47,7 @@ export enum HalfEdgeMask { * * A boundary edge with interior to one side, exterior to the other, will have EXTERIOR only on the outside. * * An edge inserted "within a purely exterior face" can have EXTERIOR on both sides. * * An interior edge (such as added during triangulation) will have no EXTERIOR bits. - */ + */ // Visualization can be found at geometry/internaldocs/Graph.md EXTERIOR = 0x00000001, /** @@ -221,12 +221,14 @@ export class HalfEdge implements HalfEdgeUserData { */ public faceStepY(numStep: number): number { let node: HalfEdge = this; - if (numStep > 0) + if (numStep > 0) { for (let i = 0; i < numStep; i++) node = node.faceSuccessor; - else if (numStep < 0) + } + else if (numStep < 0) { for (let i = 0; i > numStep; i--) node = node.facePredecessor; + } return node.y; } /** @@ -256,8 +258,14 @@ export class HalfEdge implements HalfEdgeUserData { * @returns the reference to the first half edge created, set with "A" properties. */ public static createHalfEdgePairWithCoordinates( - xA: number = 0, yA: number = 0, zA: number = 0, iA: number = 0, - xB: number = 0, yB: number = 0, zB: number = 0, iB: number = 0, + xA: number = 0, + yA: number = 0, + zA: number = 0, + iA: number = 0, + xB: number = 0, + yB: number = 0, + zB: number = 0, + iB: number = 0, heArray: HalfEdge[] | undefined, ): HalfEdge { const a = HalfEdge.createHalfEdgePair(heArray); @@ -365,7 +373,10 @@ export class HalfEdge implements HalfEdgeUserData { } /** Edge property masks. */ private static _edgePropertyMasks: HalfEdgeMask[] = [ - HalfEdgeMask.BOUNDARY_EDGE, HalfEdgeMask.EXTERIOR, HalfEdgeMask.PRIMARY_EDGE, HalfEdgeMask.NULL_FACE, + HalfEdgeMask.BOUNDARY_EDGE, + HalfEdgeMask.EXTERIOR, + HalfEdgeMask.PRIMARY_EDGE, + HalfEdgeMask.NULL_FACE, ]; /** * Copy "edge based" content of `fromNode` to `toNode`: @@ -700,7 +711,7 @@ export class HalfEdge implements HalfEdgeUserData { return node0; } /** - *"Pinch" is the universal operator for manipulating a node's next and previous pointers. + * "Pinch" is the universal operator for manipulating a node's next and previous pointers. * * It is its own inverse: applying it twice on the same inputs (i.e., `pinch(a,b); pinch(a,b);`) gets back to * where you started. * * If the inputs are in different face loops, the loops join to one face loop after the pinch. @@ -856,22 +867,28 @@ export class HalfEdge implements HalfEdgeUserData { /** Returns 2D cross product of vectors from `base` to `targetA` and from `base` to `targetB`. */ public static crossProductXYToTargets(base: HalfEdge, targetA: HalfEdge, targetB: HalfEdge): number { return Geometry.crossProductXYXY( - targetA.x - base.x, targetA.y - base.y, - targetB.x - base.x, targetB.y - base.y, + targetA.x - base.x, + targetA.y - base.y, + targetB.x - base.x, + targetB.y - base.y, ); } /** Returns 2D dot product of vectors from `baseA` to `targetA` and from `baseB` to `targetB`. */ public static dotProductNodeToNodeVectorsXY(baseA: HalfEdge, targetA: HalfEdge, baseB: HalfEdge, targetB: HalfEdge): number { return Geometry.dotProductXYXY( - targetA.x - baseA.x, targetA.y - baseA.y, - targetB.x - baseB.x, targetB.y - baseB.y, + targetA.x - baseA.x, + targetA.y - baseA.y, + targetB.x - baseB.x, + targetB.y - baseB.y, ); } /** Return 2D cross product of vectors from `nodeA` to `nodeB` and from `nodeB` to `nodeC`. */ public static crossProductXYAlongChain(nodeA: HalfEdge, nodeB: HalfEdge, nodeC: HalfEdge): number { return Geometry.crossProductXYXY( - nodeB.x - nodeA.x, nodeB.y - nodeA.y, - nodeC.x - nodeB.x, nodeC.y - nodeB.y, + nodeB.x - nodeA.x, + nodeB.y - nodeA.y, + nodeC.x - nodeB.x, + nodeC.y - nodeB.y, ); } /** @@ -968,9 +985,15 @@ export class HalfEdge implements HalfEdgeUserData { const suc = node.faceSuccessor; const pred = node.facePredecessor; return Angle.orientedRadiansBetweenVectorsXYZ( - suc.x - node.x, suc.y - node.y, suc.z - node.z, - pred.x - node.x, pred.y - node.y, pred.z - node.z, - normal.x, normal.y, normal.z, + suc.x - node.x, + suc.y - node.y, + suc.z - node.z, + pred.x - node.x, + pred.y - node.y, + pred.z - node.z, + normal.x, + normal.y, + normal.z, true, ); } @@ -1012,7 +1035,9 @@ export class HalfEdge implements HalfEdgeUserData { * @param result optional array to be cleared and receive masked nodes. */ public collectMaskedEdgesAroundVertex( - mask: HalfEdgeMask, value: boolean = true, result?: HalfEdge[], + mask: HalfEdgeMask, + value: boolean = true, + result?: HalfEdge[], ): HalfEdge[] { if (result === undefined) result = []; @@ -1159,7 +1184,9 @@ export class HalfEdge implements HalfEdgeUserData { * @param result optional xy coordinates. */ public fractionAlongAndPerpendicularToPoint2d( - fractionAlong: number, fractionPerpendicular: number, result?: Point2d, + fractionAlong: number, + fractionPerpendicular: number, + result?: Point2d, ): Point2d { const suc = this.faceSuccessor; const dx = suc.x - this.x; @@ -1221,7 +1248,9 @@ export class HalfEdge implements HalfEdgeUserData { * @param result optional preallocated result. */ public static transverseIntersectionFractions( - nodeA0: HalfEdge, nodeB0: HalfEdge, result?: Vector2d, + nodeA0: HalfEdge, + nodeB0: HalfEdge, + result?: Vector2d, ): Vector2d | undefined { const nodeA1 = nodeA0.faceSuccessor; const nodeB1 = nodeB0.faceSuccessor; @@ -1231,12 +1260,17 @@ export class HalfEdge implements HalfEdgeUserData { // (nodeA1.x - nodeA0.x)ta + (nodeB0.x - nodeB1.x)tb = nodeB0.x - nodeA0.x // (nodeA1.y - nodeA0.y)ta + (nodeB0.y - nodeB1.y)tb = nodeB0.y - nodeA0.y // Proof can be found at geometry/internaldocs/Graph.md - if (SmallSystem.linearSystem2d( - nodeA1.x - nodeA0.x, nodeB0.x - nodeB1.x, - nodeA1.y - nodeA0.y, nodeB0.y - nodeB1.y, - nodeB0.x - nodeA0.x, nodeB0.y - nodeA0.y, - result, - )) + if ( + SmallSystem.linearSystem2d( + nodeA1.x - nodeA0.x, + nodeB0.x - nodeB1.x, + nodeA1.y - nodeA0.y, + nodeB0.y - nodeB1.y, + nodeB0.x - nodeA0.x, + nodeB0.y - nodeA0.y, + result, + ) + ) return result; return undefined; } @@ -1286,7 +1320,11 @@ export class HalfEdge implements HalfEdgeUserData { * @param copyFaceData true to copy `faceTag`. */ public copyDataFrom( - source: HalfEdge, copyXYZ: boolean, copyVertexData: boolean, copyEdgeData: boolean, copyFaceData: boolean, + source: HalfEdge, + copyXYZ: boolean, + copyVertexData: boolean, + copyEdgeData: boolean, + copyFaceData: boolean, ): void { if (copyXYZ) { this.x = source.x; @@ -1344,8 +1382,14 @@ export class HalfEdgeGraph { * @returns pointer to the first half edge created. */ public createEdgeXYZXYZ( - xA: number = 0, yA: number = 0, zA: number = 0, iA: number = 0, - xB: number = 0, yB: number = 0, zB: number = 0, iB: number = 0, + xA: number = 0, + yA: number = 0, + zA: number = 0, + iA: number = 0, + xB: number = 0, + yB: number = 0, + zB: number = 0, + iB: number = 0, ): HalfEdge { return HalfEdge.createHalfEdgePairWithCoordinates(xA, yA, zA, iA, xB, yB, zB, iB, this.allHalfEdges); } @@ -1387,7 +1431,15 @@ export class HalfEdgeGraph { public createEdgeHalfEdgeHalfEdge(nodeA: HalfEdge, idA: number, nodeB: HalfEdge, idB: number = 0): HalfEdge { // visualization can be found at geometry/internaldocs/Graph.md const a = HalfEdge.createHalfEdgePairWithCoordinates( - nodeA.x, nodeA.y, nodeA.z, idA, nodeB.x, nodeB.y, nodeB.z, idB, this.allHalfEdges, + nodeA.x, + nodeA.y, + nodeA.z, + idA, + nodeB.x, + nodeB.y, + nodeB.z, + idB, + this.allHalfEdges, ); const b = a.faceSuccessor; HalfEdge.pinch(nodeA, a); @@ -1403,7 +1455,15 @@ export class HalfEdgeGraph { */ public createEdgeXYAndZ(xyz0: XYAndZ, id0: number, xyz1: XYAndZ, id1: number): HalfEdge { return HalfEdge.createHalfEdgePairWithCoordinates( - xyz0.x, xyz0.y, xyz0.z, id0, xyz1.x, xyz1.y, xyz1.z, id1, this.allHalfEdges, + xyz0.x, + xyz0.y, + xyz0.z, + id0, + xyz1.x, + xyz1.y, + xyz1.z, + id1, + this.allHalfEdges, ); } /** @@ -1443,7 +1503,12 @@ export class HalfEdgeGraph { */ public splitEdgeAtFraction(base: HalfEdge, fraction: number): HalfEdge { return HalfEdge.splitEdge( - base, base.fractionToX(fraction), base.fractionToY(fraction), base.fractionToZ(fraction), 0, this.allHalfEdges, + base, + base.fractionToX(fraction), + base.fractionToY(fraction), + base.fractionToZ(fraction), + 0, + this.allHalfEdges, ); } /** diff --git a/core/geometry/src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts b/core/geometry/src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts index 0931114f921c..0684d8ab5198 100644 --- a/core/geometry/src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts +++ b/core/geometry/src/topology/HalfEdgeGraphFromIndexedLoopsContext.ts @@ -18,18 +18,20 @@ import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "./Graph"; * @internal */ export class HalfEdgeGraphFromIndexedLoopsContext { - public constructor(){ - this._unmatchedEdges = new Map (); - this._graph = new HalfEdgeGraph (); + public constructor() { + this._unmatchedEdges = new Map(); + this._graph = new HalfEdgeGraph(); this._halfEdgesAroundCurrentLoop = []; } private _unmatchedEdges: Map; private _graph: HalfEdgeGraph; - public get graph(): HalfEdgeGraph {return this._graph;} + public get graph(): HalfEdgeGraph { + return this._graph; + } // for multiple uses by insert loop. private _halfEdgesAroundCurrentLoop: HalfEdge[]; - private indexPairToString(index0: number, index1: number): string{ + private indexPairToString(index0: number, index1: number): string { return `${index0.toString()},${index1.toString()}`; } /** Create a loop with specified indices at its vertices. @@ -48,33 +50,33 @@ export class HalfEdgeGraphFromIndexedLoopsContext { * @param announceMatedHalfEdges optional function to be called as mated pairs are created. At the call, * the given HalfEdge and its mate will have a pair of successive indices from the array. */ - public insertLoop(indices: number[], announceMatedHalfEdges?: (halfEdge: HalfEdge) => void): HalfEdge | undefined{ + public insertLoop(indices: number[], announceMatedHalfEdges?: (halfEdge: HalfEdge) => void): HalfEdge | undefined { const n = indices.length; if (n > 2) { let index0 = indices[indices.length - 1]; this._halfEdgesAroundCurrentLoop.length = 0; - for (const index1 of indices){ - const insideString = this.indexPairToString (index0, index1); - const halfEdgePreviouslyConstructedFromOppositeSide: HalfEdge | undefined = this._unmatchedEdges.get (insideString); - if (halfEdgePreviouslyConstructedFromOppositeSide === undefined){ + for (const index1 of indices) { + const insideString = this.indexPairToString(index0, index1); + const halfEdgePreviouslyConstructedFromOppositeSide: HalfEdge | undefined = this._unmatchedEdges.get(insideString); + if (halfEdgePreviouslyConstructedFromOppositeSide === undefined) { // This is the first appearance of this edge in either direction. - const outsideString = this.indexPairToString (index1, index0); // string referencing the "other" side of the new edge. - const newHalfEdgeAroundLoop = this._graph.createEdgeIdId (index0, index1); + const outsideString = this.indexPairToString(index1, index0); // string referencing the "other" side of the new edge. + const newHalfEdgeAroundLoop = this._graph.createEdgeIdId(index0, index1); if (announceMatedHalfEdges !== undefined) - announceMatedHalfEdges (newHalfEdgeAroundLoop); - this._unmatchedEdges.set (outsideString, newHalfEdgeAroundLoop.edgeMate); - this._halfEdgesAroundCurrentLoop.push (newHalfEdgeAroundLoop); - newHalfEdgeAroundLoop.edgeMate.setMask (HalfEdgeMask.EXTERIOR); + announceMatedHalfEdges(newHalfEdgeAroundLoop); + this._unmatchedEdges.set(outsideString, newHalfEdgeAroundLoop.edgeMate); + this._halfEdgesAroundCurrentLoop.push(newHalfEdgeAroundLoop); + newHalfEdgeAroundLoop.edgeMate.setMask(HalfEdgeMask.EXTERIOR); } else { - this._halfEdgesAroundCurrentLoop.push (halfEdgePreviouslyConstructedFromOppositeSide); - halfEdgePreviouslyConstructedFromOppositeSide.clearMask (HalfEdgeMask.EXTERIOR); + this._halfEdgesAroundCurrentLoop.push(halfEdgePreviouslyConstructedFromOppositeSide); + halfEdgePreviouslyConstructedFromOppositeSide.clearMask(HalfEdgeMask.EXTERIOR); } index0 = index1; } let halfEdgeA = this._halfEdgesAroundCurrentLoop[this._halfEdgesAroundCurrentLoop.length - 1]; - for (const halfEdgeB of this._halfEdgesAroundCurrentLoop){ + for (const halfEdgeB of this._halfEdgesAroundCurrentLoop) { const halfEdgeC = halfEdgeA.faceSuccessor; - HalfEdge.pinch (halfEdgeB, halfEdgeC); + HalfEdge.pinch(halfEdgeB, halfEdgeC); halfEdgeA = halfEdgeB; } return this._halfEdgesAroundCurrentLoop[0]; diff --git a/core/geometry/src/topology/HalfEdgeGraphSearch.ts b/core/geometry/src/topology/HalfEdgeGraphSearch.ts index 2bf240a1a38f..594186233b3e 100644 --- a/core/geometry/src/topology/HalfEdgeGraphSearch.ts +++ b/core/geometry/src/topology/HalfEdgeGraphSearch.ts @@ -84,7 +84,8 @@ export class HalfEdgeGraphSearch { * @returns node on the negative area face with largest absolute area, or `undefined` if no negative area face. */ public static findMinimumAreaFace( - oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], faceAreaFunction?: NodeToNumberFunction, + oneCandidateNodePerFace: HalfEdgeGraph | HalfEdge[], + faceAreaFunction?: NodeToNumberFunction, ): HalfEdge | undefined { const summary = HalfEdgeGraphSearch.collectFaceAreaSummary(oneCandidateNodePerFace, false, faceAreaFunction); return summary.largestNegativeItem; @@ -137,7 +138,10 @@ export class HalfEdgeGraphSearch { * @param onePerFaceStack array appended with `faceSeed`. */ private static pushAndMaskAllNodesInFace( - faceSeed: HalfEdge, mask: number, allNodeStack: HalfEdge[], onePerFaceStack: HalfEdge[], + faceSeed: HalfEdge, + mask: number, + allNodeStack: HalfEdge[], + onePerFaceStack: HalfEdge[], ): void { onePerFaceStack.push(faceSeed); faceSeed.collectAroundFace((node: HalfEdge) => { @@ -332,8 +336,10 @@ export class HalfEdgeGraphSearch { // Starting all floods at the boundary reduces the chance of ending up with a ring-shaped component at the boundary. const findNextFloodSeed = (index: number) => { for (let i = index; i < graph.countNodes(); ++i) { - if (!graph.allHalfEdges[i].isMaskSet(boundaryMask) - && graph.allHalfEdges[i].edgeMate.isMaskSet(boundaryMask)) { + if ( + !graph.allHalfEdges[i].isMaskSet(boundaryMask) + && graph.allHalfEdges[i].edgeMate.isMaskSet(boundaryMask) + ) { index = i; break; } @@ -368,7 +374,7 @@ export class HalfEdgeGraphSearch { // walk around looking for an accepted node to start the search (seedNode is usually ok) let nodeA = seedNode; let nodeB = seedNode.faceSuccessor; - for (; ; nodeA = nodeB) { + for (;; nodeA = nodeB) { if (context.tryStartEdge(nodeA.x, nodeA.y, nodeB.x, nodeB.y)) break; if (nodeB === seedNode) { @@ -380,7 +386,7 @@ export class HalfEdgeGraphSearch { } // nodeB is the real start node for search, so stop when we revisit it. For each edge, accumulate parity and hits let nodeC = nodeB.faceSuccessor; - for (; ;) { + for (;;) { if (!context.advance(nodeC.x, nodeC.y)) { return context.classifyCounts(); } @@ -411,7 +417,7 @@ export class HalfEdgeGraphSearch { seed.setMask(visitMask); const vertexBase = seed.faceSuccessor; let candidateAroundVertex = vertexBase; - for (; ;) { + for (;;) { if (candidateAroundVertex.getMask(visitMask)) // end of boundary loop return; if (isBoundaryEdge(candidateAroundVertex)) { diff --git a/core/geometry/src/topology/HalfEdgeGraphSpineContext.ts b/core/geometry/src/topology/HalfEdgeGraphSpineContext.ts index 078ac2ce2c57..6feba2f4bdc8 100644 --- a/core/geometry/src/topology/HalfEdgeGraphSpineContext.ts +++ b/core/geometry/src/topology/HalfEdgeGraphSpineContext.ts @@ -6,13 +6,13 @@ * @module Topology */ import { Geometry } from "../Geometry"; -import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "./Graph"; +import { Angle } from "../geometry3d/Angle"; import { Point3d, Vector3d } from "../geometry3d/Point3dVector3d"; +import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "./Graph"; +import { HalfEdgeGraphSearch, HalfEdgeMaskTester } from "./HalfEdgeGraphSearch"; import { HalfEdgeGraphMerge } from "./Merging"; -import { Triangulator } from "./Triangulation"; import { RegularizationContext } from "./RegularizeFace"; -import { HalfEdgeGraphSearch, HalfEdgeMaskTester } from "./HalfEdgeGraphSearch"; -import { Angle } from "../geometry3d/Angle"; +import { Triangulator } from "./Triangulation"; // cSpell:disable // const sSpineRelTol = 1.0e-8; // const sSpineGraphAbsTol = 0.0; @@ -34,13 +34,17 @@ function createNVectors(n: number): Vector3d[] { class NodeSortKey { private _a: number; private _node: HalfEdge; - public get node() { return this._node; } + public get node() { + return this._node; + } public constructor(node: HalfEdge, b: number) { this._node = node; this._a = b; } - public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { return dataA._a - dataB._a; } + public static compareForSort(dataA: NodeSortKey, dataB: NodeSortKey): number { + return dataA._a - dataB._a; + } } /** @@ -77,7 +81,9 @@ export class HalfEdgeGraphSpineContext { /** mask marking edges that have been paired into quads */ private _diagonalMask: HalfEdgeMask; private _boxMask: HalfEdgeMask; - public get graph() { return this._spineGraph; } + public get graph() { + return this._spineGraph; + } /** * Create a context with an empty graph. * * Reserve masks for specialized markup. @@ -106,15 +112,15 @@ export class HalfEdgeGraphSpineContext { xyzOut.push(newArray); } - private getBoxCorners(diagonalNode: HalfEdge, - nodes: HalfEdge[], - points: Point3d[]): boolean { + private getBoxCorners(diagonalNode: HalfEdge, nodes: HalfEdge[], points: Point3d[]): boolean { const diagonalMate = diagonalNode.edgeMate; nodes.length = 0; points.length = 0; - if (!diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE) + if ( + !diagonalNode.getMask(HalfEdgeMask.BOUNDARY_EDGE) && diagonalNode.countEdgesAroundFace() === 3 - && diagonalMate.countEdgesAroundFace() === 3) { + && diagonalMate.countEdgesAroundFace() === 3 + ) { const nodeA = diagonalMate.faceSuccessor; nodes.push(nodeA); nodes.push(nodeA.faceSuccessor); @@ -132,7 +138,6 @@ export class HalfEdgeGraphSpineContext { // function key is the smaller absolute angle between the bisectors. // (pi/2 is max possible value). private diagonalKeyFunc(pDiagonalNode: HalfEdge): number { - const nodes: HalfEdge[] = []; const points: Point3d[] = []; if (this.getBoxCorners(pDiagonalNode, nodes, points)) { @@ -170,10 +175,9 @@ export class HalfEdgeGraphSpineContext { // Select a branch point in a triangle. // This may be the centroid or the midpoint of an edge joining midpoints of a pair of edges. private selectTriangleInteriorPoint(pXYZ: Point3d[]): Point3d { - const xyz = createNPoints(6); - const xyzMid = createNPoints(6); // Midpoints of each edge. - const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2]. + const xyzMid = createNPoints(6); // Midpoints of each edge. + const interiorCandidate = createNPoints(4); // for i in {012}, [i] is midpoint of midpoint[i+1] and midpoint[i+2]. // [3] is centroid. const edgeVector = createNVectors(6); const centroid = Point3d.create(); @@ -187,7 +191,7 @@ export class HalfEdgeGraphSpineContext { for (let i = 0; i < 3; i++) { xyzMid[i] = xyz[i].interpolate(0.5, xyz[i + 1]); xyzMid[i + 3] = xyzMid[i]; - edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound + edgeVector[i] = Vector3d.createStartEnd(xyz[i], xyz[i + 1]); // use wraparound edgeVector[i + 3] = edgeVector[i]; } @@ -222,7 +226,6 @@ export class HalfEdgeGraphSpineContext { } private markBox(pA: HalfEdge): void { - const pB = pA.edgeMate; pA.setMask(this._diagonalMask); pB.setMask(this._diagonalMask); @@ -231,7 +234,6 @@ export class HalfEdgeGraphSpineContext { } private setSortedDiagonalMasks(minA: number): number { - const candidates: NodeSortKey[] = []; let numDiagonal = 0; for (const node of this._spineGraph.allHalfEdges) { @@ -246,8 +248,10 @@ export class HalfEdgeGraphSpineContext { while (undefined !== (key = candidates.pop())) { const pA = key.node; const pB = pA.edgeMate; - if (!pA.getMask(this._boxMask) - && !pB.getMask(this._boxMask)) { + if ( + !pA.getMask(this._boxMask) + && !pB.getMask(this._boxMask) + ) { this.markBox(pA); numDiagonal++; } @@ -257,7 +261,6 @@ export class HalfEdgeGraphSpineContext { /// Vertex whose angle is being split private splitOK(xyzA: Point3d, xyzB: Point3d, xyzQ: Point3d, xyzC: Point3d, minAngle: number): boolean { - const vectorAB = Vector3d.createStartEnd(xyzA, xyzB); const vectorAQ = Vector3d.createStartEnd(xyzA, xyzQ); const vectorAC = Vector3d.createStartEnd(xyzA, xyzC); @@ -273,14 +276,14 @@ export class HalfEdgeGraphSpineContext { // Drop a perpenedicular to that boundary. // return the number of edges added. private addPerpendicularsToBoundaries(minSplitRadians: number, minCandidateRadians: number): number { - let numAdd = 0; for (const pA of this._spineGraph.allHalfEdges) { const pB = pA.faceSuccessor; const pC = pB.faceSuccessor; - if (!pA.getMask(HalfEdgeMask.EXTERIOR) - && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion - && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion + if ( + !pA.getMask(HalfEdgeMask.EXTERIOR) + && !pA.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion + && !pC.getMask(HalfEdgeMask.BOUNDARY_EDGE) // ?? prevent deep recursion && pB.getMask(HalfEdgeMask.BOUNDARY_EDGE) && pC.faceSuccessor === pA ) { @@ -319,8 +322,8 @@ export class HalfEdgeGraphSpineContext { // true to include the edge to boundary when the qued is a dead end. bIncludeFinal: boolean, // true to include the two adjacent edges to boundary if the quad is at a corner. - bIncludeCornerSpokes: boolean): boolean { - + bIncludeCornerSpokes: boolean, + ): boolean { if (pFace.countEdgesAroundFace() !== 4) return false; const pNode: HalfEdge[] = []; @@ -368,8 +371,10 @@ export class HalfEdgeGraphSpineContext { } else { // Block sits as exterior corner. Let the two spines continue to their opposite faces .. for (let i: number = 0; i < 4; i++) - if ((bIsBoundary[i] && bIncludeCornerSpokes) - || (!bIsBoundary[i] && bIncludeInterior)) + if ( + (bIsBoundary[i] && bIncludeCornerSpokes) + || (!bIsBoundary[i] && bIncludeInterior) + ) this.addEdge(xyzOut, midpoint[i], centroid); } } else if (numBoundary === 3) { @@ -382,10 +387,11 @@ export class HalfEdgeGraphSpineContext { } private getSpineEdgesInTriangle( - pFace: HalfEdge, xyzOut: Point3d[][], + pFace: HalfEdge, + xyzOut: Point3d[][], bIncludeInterior: boolean, - bIncludeFinal: boolean): boolean { - + bIncludeFinal: boolean, + ): boolean { if (pFace.countEdgesAroundFace() !== 3) return false; let n = 0; @@ -452,8 +458,15 @@ export class HalfEdgeGraphSpineContext { let pPreviousB, pFirstA; for (let i: number = 1; i < xyzIn.length; i++) { const nodeA = this._spineGraph.createEdgeXYZXYZ( - xyzIn[i - 1].x, xyzIn[i - 1].y, 0, 0, - xyzIn[i].x, xyzIn[i].y, 0, 0); + xyzIn[i - 1].x, + xyzIn[i - 1].y, + 0, + 0, + xyzIn[i].x, + xyzIn[i].y, + 0, + 0, + ); const nodeB = nodeA.faceSuccessor; nodeA.setMask(HalfEdgeMask.BOUNDARY_EDGE); nodeB.setMask(HalfEdgeMask.BOUNDARY_EDGE); @@ -496,7 +509,6 @@ export class HalfEdgeGraphSpineContext { * @param minSplitRadians smallest allowed angle in the split sector that is split. */ public triangulateForSpine(applyParity: boolean = true, minSplitRadians: number = 0.3): void { - const sMaxSplit = 20; const sMinCandidateRadians = 1.0; let numSplit = 0; @@ -508,8 +520,11 @@ export class HalfEdgeGraphSpineContext { const context2 = new RegularizationContext(this.graph); context2.regularizeGraph(false, HalfEdgeGraphSpineContext._regularize2); if (applyParity) { - HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks(this.graph, - new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), HalfEdgeMask.EXTERIOR); + HalfEdgeGraphSearch.collectConnectedComponentsWithExteriorParityMasks( + this.graph, + new HalfEdgeMaskTester(HalfEdgeMask.BOUNDARY_EDGE), + HalfEdgeMask.EXTERIOR, + ); this.purgeNullFaces(HalfEdgeMask.EXTERIOR); } @@ -545,7 +560,8 @@ export class HalfEdgeGraphSpineContext { } } return true; - }); + }, + ); return xyzOut; } @@ -562,11 +578,11 @@ export class HalfEdgeGraphSpineContext { * @param minAngleRadians angle tolerance, as described above. */ public consolidateTrianglesToQuads(bDeleteDiagonals: boolean, minAngle: Angle = Angle.createDegrees(50)): number { - const numDiagonal = this.setSortedDiagonalMasks(minAngle.radians); if (bDeleteDiagonals && numDiagonal > 0) { this.graph.yankAndDeleteEdges( - (node: HalfEdge) => node.getMask(this._diagonalMask)); + (node: HalfEdge) => node.getMask(this._diagonalMask), + ); } return numDiagonal; } diff --git a/core/geometry/src/topology/HalfEdgeMarkSet.ts b/core/geometry/src/topology/HalfEdgeMarkSet.ts index d17a428e9f53..0318f17042cc 100644 --- a/core/geometry/src/topology/HalfEdgeMarkSet.ts +++ b/core/geometry/src/topology/HalfEdgeMarkSet.ts @@ -67,7 +67,9 @@ export abstract class AbstractHalfEdgeGraphMarkSet { return this._candidates.length; } /** Read property accessor: return the graph */ - public get graph(): HalfEdgeGraph { return this._graph; } + public get graph(): HalfEdgeGraph { + return this._graph; + } /** return borrowed assets (the mask!) to the graph. */ public teardown() { @@ -76,7 +78,9 @@ export abstract class AbstractHalfEdgeGraphMarkSet { // this._graph = undefined; } /** (Read property) return the mask used to mark members of the set. */ - public get mask(): HalfEdgeMask { return this._mask; } + public get mask(): HalfEdgeMask { + return this._mask; + } /** pop and return the last node out of the array, without testing if it is still marked. */ protected popAndReturn(): HalfEdge | undefined { @@ -145,7 +149,7 @@ export abstract class AbstractHalfEdgeGraphMarkSet { * * If unmasked HalfEdges are found in the array, they are removed from the array. */ public chooseAndRemoveAny(): HalfEdge | undefined { - for (; ;) { + for (;;) { const candidate = this.popAndReturn(); if (!candidate) return undefined; @@ -171,7 +175,9 @@ export abstract class AbstractHalfEdgeGraphMarkSet { */ public abstract countHalfEdgesAroundCandidate(candidate: HalfEdge | undefined): number; /** Create an iterator over member HalfEdges */ - public [Symbol.iterator](): IterableIterator { return new IterableHalfEdgeMarkSetIterator(this); } + public [Symbol.iterator](): IterableIterator { + return new IterableHalfEdgeMarkSetIterator(this); + } /** * * visit all half edges around face. * * Add each to mark set. @@ -406,5 +412,7 @@ class IterableHalfEdgeMarkSetIterator implements Iterator { return { done: true, value: undefined } as any as IteratorResult; } - public [Symbol.iterator](): IterableIterator { return this; } + public [Symbol.iterator](): IterableIterator { + return this; + } } diff --git a/core/geometry/src/topology/HalfEdgeNodeXYZUV.ts b/core/geometry/src/topology/HalfEdgeNodeXYZUV.ts index 9e7efb1d1d3f..273c01523a28 100644 --- a/core/geometry/src/topology/HalfEdgeNodeXYZUV.ts +++ b/core/geometry/src/topology/HalfEdgeNodeXYZUV.ts @@ -75,7 +75,12 @@ export class NodeXYZUV { } /** Create a `NodeXYZUV` with explicit `node`, xyz, uv. */ public static create( - node: HalfEdge, x: number = 0, y: number = 0, z: number = 0, u: number = 0, v: number = 0, + node: HalfEdge, + x: number = 0, + y: number = 0, + z: number = 0, + u: number = 0, + v: number = 0, ): NodeXYZUV { return new NodeXYZUV(node, x, y, z, u, v); } diff --git a/core/geometry/src/topology/HalfEdgePointInGraphSearch.ts b/core/geometry/src/topology/HalfEdgePointInGraphSearch.ts index 7dfca5591359..574f72fca141 100644 --- a/core/geometry/src/topology/HalfEdgePointInGraphSearch.ts +++ b/core/geometry/src/topology/HalfEdgePointInGraphSearch.ts @@ -65,7 +65,9 @@ export class PointSearchContext { * @return detail closer to the target point. */ public reAimFromEdge( - edgeHit: HalfEdgePositionDetail, ray: Ray3d, targetDistance: number, + edgeHit: HalfEdgePositionDetail, + ray: Ray3d, + targetDistance: number, ): HalfEdgePositionDetail { const nodeA = edgeHit.node!; const dataA = NodeXYZUV.createNodeAndRayOrigin(nodeA, ray); @@ -128,7 +130,9 @@ export class PointSearchContext { * @return detail closer to the target point. */ public reAimFromVertex( - vertexHit: HalfEdgePositionDetail, ray: Ray3d, targetDistance: number, + vertexHit: HalfEdgePositionDetail, + ray: Ray3d, + targetDistance: number, ): HalfEdgePositionDetail { assert(ray.origin.isExactEqual(vertexHit)); const vertexNode = vertexHit.node; diff --git a/core/geometry/src/topology/HalfEdgePositionDetail.ts b/core/geometry/src/topology/HalfEdgePositionDetail.ts index f4a0aa79101a..1c9be27ab1a0 100644 --- a/core/geometry/src/topology/HalfEdgePositionDetail.ts +++ b/core/geometry/src/topology/HalfEdgePositionDetail.ts @@ -24,8 +24,8 @@ export enum HalfEdgeTopo { /** * Exterior point (after hitting barrier edge at fraction). * Fraction is 0 if exterior point "in sweep around exterior corner". - */ - ExteriorFace = 4 + */ + ExteriorFace = 4, } /** * Description of a generalized position within a graph, categorized as: @@ -56,7 +56,9 @@ export class HalfEdgePositionDetail { */ private constructor( node: HalfEdge | undefined, - x: number, y: number, z: number, + x: number, + y: number, + z: number, topo: HalfEdgeTopo, edgeFraction?: number, iTag?: number, @@ -64,7 +66,9 @@ export class HalfEdgePositionDetail { isExteriorTarget?: boolean, ) { this._node = node; - this.x = x; this.y = y; this.z = z; + this.x = x; + this.y = y; + this.z = z; this._topo = topo; this._edgeFraction = edgeFraction; this._iTag = iTag; diff --git a/core/geometry/src/topology/HalfEdgePriorityQueue.ts b/core/geometry/src/topology/HalfEdgePriorityQueue.ts index 6d810b6cd50d..34eb4d89641c 100644 --- a/core/geometry/src/topology/HalfEdgePriorityQueue.ts +++ b/core/geometry/src/topology/HalfEdgePriorityQueue.ts @@ -23,7 +23,8 @@ export class HalfEdgePriorityQueueWithPartnerArray { public priorityQueue: PriorityQueue; public activeEdges: HalfEdge[]; public constructor( - compare: OrderedComparator = (a, b) => HalfEdgeGraphOps.compareNodesYXUp(a, b)) { + compare: OrderedComparator = (a, b) => HalfEdgeGraphOps.compareNodesYXUp(a, b), + ) { this.priorityQueue = new PriorityQueue(compare); this.activeEdges = []; } diff --git a/core/geometry/src/topology/InsertAndRetriangulateContext.ts b/core/geometry/src/topology/InsertAndRetriangulateContext.ts index 295833857305..b589a26ebe7d 100644 --- a/core/geometry/src/topology/InsertAndRetriangulateContext.ts +++ b/core/geometry/src/topology/InsertAndRetriangulateContext.ts @@ -147,7 +147,7 @@ export class InsertAndRetriangulateContext { * Reset the "current" position to a vertex nearest the target point. * @param xyz target point * @param searchEdgesToo reset to nearest vertex or edge - */ + */ public resetSearch(xyz: Point3d, searchEdgesToo: boolean): void { if (searchEdgesToo) this._searcher = this.searchForNearestEdgeOrVertex(xyz); @@ -247,7 +247,7 @@ export class InsertAndRetriangulateContext { // insert point into the graph by splitting its containing edge const newA = this._graph.splitEdgeAtFraction(this._searcher.node, this._searcher.edgeFraction!); const newB = newA.vertexPredecessor; - this.updateZAroundVertex(newA, point, InsertedVertexZOptions.Replace); // always replace + this.updateZAroundVertex(newA, point, InsertedVertexZOptions.Replace); // always replace this.retriangulateFromBaseVertex(newA); this.retriangulateFromBaseVertex(newB); Triangulator.flipTrianglesInEdgeSet(this._graph, this._edgeSet); @@ -318,9 +318,11 @@ export class InsertAndRetriangulateContext { break; } case RayClassification.TargetAfter: { - if (movingPosition.node === lastBefore.node + if ( + movingPosition.node === lastBefore.node && movingPosition.isFace - && (lastBefore.isEdge || lastBefore.isVertex)) { + && (lastBefore.isEdge || lastBefore.isVertex) + ) { trap++; } else { trap = 0; @@ -357,7 +359,10 @@ export class InsertAndRetriangulateContext { } /** Set `position` to a random unmasked edge at the specified fraction. */ function moveToAnyUnmaskedEdge( - graph: HalfEdgeGraph, position: HalfEdgePositionDetail, edgeFraction: number, skipMask: HalfEdgeMask, + graph: HalfEdgeGraph, + position: HalfEdgePositionDetail, + edgeFraction: number, + skipMask: HalfEdgeMask, ): boolean { for (const candidate of graph.allHalfEdges) { if (!candidate.isMaskSet(skipMask)) { diff --git a/core/geometry/src/topology/MaskManager.ts b/core/geometry/src/topology/MaskManager.ts index 2c9e4b9f47e5..c4c0942bd32f 100644 --- a/core/geometry/src/topology/MaskManager.ts +++ b/core/geometry/src/topology/MaskManager.ts @@ -41,7 +41,7 @@ export class MaskManager { firstFree = testBit; break; } - testBit = (testBit << 1); + testBit = testBit << 1; } if (firstFree === 0) return undefined; diff --git a/core/geometry/src/topology/Merging.ts b/core/geometry/src/topology/Merging.ts index 4a53d58c276e..7e1e6dab0e74 100644 --- a/core/geometry/src/topology/Merging.ts +++ b/core/geometry/src/topology/Merging.ts @@ -12,6 +12,7 @@ import { CurveLocationDetail } from "../curve/CurveLocationDetail"; import { LineSegment3d } from "../curve/LineSegment3d"; import { Geometry } from "../Geometry"; import { Angle } from "../geometry3d/Angle"; +import { MultiLineStringDataVariant } from "../geometry3d/IndexedXYZCollection"; import { Point2d, Vector2d } from "../geometry3d/Point2dVector2d"; import { Range3d } from "../geometry3d/Range"; import { ClusterableArray } from "../numerics/ClusterableArray"; @@ -20,7 +21,6 @@ import { HalfEdge, HalfEdgeGraph, HalfEdgeMask } from "./Graph"; import { HalfEdgePriorityQueueWithPartnerArray } from "./HalfEdgePriorityQueue"; import { RegularizationContext } from "./RegularizeFace"; import { Triangulator } from "./Triangulation"; -import { MultiLineStringDataVariant } from "../geometry3d/IndexedXYZCollection"; export class GraphSplitData { public numUpEdge = 0; @@ -55,7 +55,6 @@ export type AnnounceVertexNeighborhoodSortData = (data: VertexNeighborhoodSortDa * @internal */ export class HalfEdgeGraphOps { - /** Compare function for sorting with primary y compare, secondary x compare. */ public static compareNodesYXUp(a: HalfEdge, b: HalfEdge) { // Check y's @@ -108,17 +107,21 @@ export class HalfEdgeGraphOps { // Push the endpoints of each segment onto arr[] in the form {(x, y, theta), Node} for (const segment of segments) { - const node0 = returnGraph.createEdgeXYZXYZ( - segment.point0Ref.x, segment.point0Ref.y, segment.point0Ref.z, + segment.point0Ref.x, + segment.point0Ref.y, + segment.point0Ref.z, idxCounter, - segment.point1Ref.x, segment.point1Ref.y, segment.point1Ref.z, - idxCounter + 1); + segment.point1Ref.x, + segment.point1Ref.y, + segment.point1Ref.z, + idxCounter + 1, + ); const node1 = node0.edgeMate; idxCounter += 2; - node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary + node0.setMaskAroundFace(mask); // Original given coordinates must be part of boundary result.push(node0); result.push(node1); } @@ -174,7 +177,11 @@ export class HalfEdgeGraphOps { * @param barrier edges with this mask (on either side) will not be marked. Defaults to HalfEdgeMask.BOUNDARY_EDGE. * @return number of edges masked (half the number of HalfEdges masked) */ - public static markRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, mark: HalfEdgeMask, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): number { + public static markRemovableEdgesToExpandConvexFaces( + graph: HalfEdgeGraph, + mark: HalfEdgeMask, + barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE, + ): number { if (HalfEdgeMask.NULL_MASK === mark) return 0; const visit = graph.grabMask(true); @@ -184,7 +191,10 @@ export class HalfEdgeGraphOps { if (!node.isMaskSet(barrier) && !node.edgeMate.isMaskSet(barrier)) { // tol based on areas of *original* faces on each side of the edge to be removed const signedAreaTol = Geometry.smallMetricDistanceSquared * (node.signedFaceArea() + node.edgeMate.signedFaceArea()); - if (this.isSectorConvexAfterEdgeRemoval(node, mark, barrier, signedAreaTol) && this.isSectorConvexAfterEdgeRemoval(node.edgeMate, mark, barrier, signedAreaTol)) { + if ( + this.isSectorConvexAfterEdgeRemoval(node, mark, barrier, signedAreaTol) && + this.isSectorConvexAfterEdgeRemoval(node.edgeMate, mark, barrier, signedAreaTol) + ) { node.setMaskAroundEdge(mark); ++numMarked; } @@ -203,7 +213,10 @@ export class HalfEdgeGraphOps { * @param barrier edges with this mask (on either side) will not be collected. Defaults to HalfEdgeMask.BOUNDARY_EDGE. * @return one HalfEdge per removable edge */ - public static collectRemovableEdgesToExpandConvexFaces(graph: HalfEdgeGraph, barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE): HalfEdge[] | undefined { + public static collectRemovableEdgesToExpandConvexFaces( + graph: HalfEdgeGraph, + barrier: HalfEdgeMask = HalfEdgeMask.BOUNDARY_EDGE, + ): HalfEdge[] | undefined { const removable: HalfEdge[] = []; const mark = graph.grabMask(true); if (0 < this.markRemovableEdgesToExpandConvexFaces(graph, mark, barrier)) { @@ -281,7 +294,9 @@ export class HalfEdgeGraphMerge { /** * public property setter for a function to be called with sorted edge data around a vertex. */ - public static set announceVertexNeighborhoodFunction(func: AnnounceVertexNeighborhoodSortData | undefined) { this._announceVertexNeighborhoodFunction = func; } + public static set announceVertexNeighborhoodFunction(func: AnnounceVertexNeighborhoodSortData | undefined) { + this._announceVertexNeighborhoodFunction = func; + } private static doAnnounceVertexNeighborhood(clusters: ClusterableArray, order: Uint32Array, allNodes: HalfEdge[], k0: number, k1: number) { if (this._announceVertexNeighborhoodFunction) { const sortData: VertexNeighborhoodSortData[] = []; @@ -295,7 +310,6 @@ export class HalfEdgeGraphMerge { } this._announceVertexNeighborhoodFunction(sortData); } - } // assumptions about cluster array: // * data order is: x,y,theta,nodeIndex @@ -344,7 +358,8 @@ export class HalfEdgeGraphMerge { } /** Whether the HalfEdge is part of a null face, as marked by [[clusterAndMergeXYTheta]]. */ public static isNullFace(node: HalfEdge): boolean { - return node.isMaskSet(HalfEdgeMask.NULL_FACE) && node.faceSuccessor.isMaskSet(HalfEdgeMask.NULL_FACE) && node === node.faceSuccessor.faceSuccessor; + return node.isMaskSet(HalfEdgeMask.NULL_FACE) && node.faceSuccessor.isMaskSet(HalfEdgeMask.NULL_FACE) && + node === node.faceSuccessor.faceSuccessor; } /** Simplest merge algorithm: * * collect array of (x,y,theta) at all nodes @@ -358,12 +373,12 @@ export class HalfEdgeGraphMerge { const allNodes = graph.allHalfEdges; const numNodes = allNodes.length; graph.clearMask(HalfEdgeMask.NULL_FACE); - const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta,nodeIndex. But theta is not set in first round. + const clusters = new ClusterableArray(2, 2, numNodes); // data order: x,y,theta,nodeIndex. But theta is not set in first round. for (let i = 0; i < numNodes; i++) { const nodeA = allNodes[i]; const xA = nodeA.x; const yA = nodeA.y; - HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop. + HalfEdge.pinch(nodeA, nodeA.vertexSuccessor); // pull it out of its current vertex loop. clusters.addDirect(xA, yA, 0.0, i); } const clusterTol = Geometry.smallMetricDistance; @@ -462,7 +477,7 @@ export class HalfEdgeGraphMerge { if (nodeA1.isEqualXY(nodeB1)) { const cA = this.curvatureSortKey(nodeA); const cB = this.curvatureSortKey(nodeB); - if (Geometry.isSameCoordinate(cA, cB, clusterTol)) { // rule out banana + if (Geometry.isSameCoordinate(cA, cB, clusterTol)) { // rule out banana HalfEdge.pinch(nodeA1, nodeB1); nodeA.setMask(HalfEdgeMask.NULL_FACE); nodeB1.setMask(HalfEdgeMask.NULL_FACE); @@ -483,7 +498,6 @@ export class HalfEdgeGraphMerge { private static buildVerticalSweepPriorityQueue(graph: HalfEdgeGraph): HalfEdgePriorityQueueWithPartnerArray { const sweepHeap = new HalfEdgePriorityQueueWithPartnerArray(); for (const p of graph.allHalfEdges) { - if (HalfEdgeGraphOps.compareNodesYXUp(p, p.faceSuccessor) < 0) { sweepHeap.priorityQueue.push(p); } @@ -495,7 +509,13 @@ export class HalfEdgeGraphMerge { return nodeFraction; return fraction; } - private static computeIntersectionFractionsOnEdges(nodeA0: HalfEdge, nodeB0: HalfEdge, fractions: Vector2d, pointA: Point2d, pointB: Point2d): boolean { + private static computeIntersectionFractionsOnEdges( + nodeA0: HalfEdge, + nodeB0: HalfEdge, + fractions: Vector2d, + pointA: Point2d, + pointB: Point2d, + ): boolean { const nodeA1 = nodeA0.faceSuccessor; const ax0 = nodeA0.x; const ay0 = nodeA0.y; @@ -507,8 +527,7 @@ export class HalfEdgeGraphMerge { const vx = nodeB1.x - bx0; const vy = nodeB1.y - by0; // cspell:word lineSegmentXYUVTransverseIntersectionUnbounded - if (SmallSystem.lineSegmentXYUVTransverseIntersectionUnbounded(ax0, ay0, ux, uy, - bx0, by0, vx, vy, fractions)) { + if (SmallSystem.lineSegmentXYUVTransverseIntersectionUnbounded(ax0, ay0, ux, uy, bx0, by0, vx, vy, fractions)) { pointA.x = ax0 + fractions.x * ux; pointA.y = ay0 + fractions.x * uy; pointB.x = bx0 + fractions.y * vx; @@ -556,12 +575,12 @@ export class HalfEdgeGraphMerge { if (this.computeIntersectionFractionsOnEdges(nodeA0, nodeB0, fractions, pointA, pointB)) { if (fractions.x > smallFraction && fractions.x < largeFraction) { const nodeC0 = graph.splitEdgeAtFraction(nodeA0, fractions.x); - sweepHeap.priorityQueue.push(nodeC0); // The upper portion will be reviewed as a nodeA0 later !!! + sweepHeap.priorityQueue.push(nodeC0); // The upper portion will be reviewed as a nodeA0 later !!! data.numSplit++; } if (fractions.y > smallFraction && fractions.y < largeFraction) { const nodeD0 = graph.splitEdgeAtFraction(nodeB0, fractions.y); - sweepHeap.priorityQueue.push(nodeD0); // The upper portion will be reviewed as a nodeA0 later !!! + sweepHeap.priorityQueue.push(nodeD0); // The upper portion will be reviewed as a nodeA0 later !!! data.numSplit++; } // existing nodeA0 and its shortened edge remain for further intersections @@ -596,7 +615,11 @@ export class HalfEdgeGraphMerge { * * Graph gets full splitEdges, regularize (optional), and triangulate. * @returns graph, or undefined if bad data. */ - public static formGraphFromChains(chains: MultiLineStringDataVariant, regularize: boolean = true, mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE): HalfEdgeGraph | undefined { + public static formGraphFromChains( + chains: MultiLineStringDataVariant, + regularize: boolean = true, + mask: HalfEdgeMask = HalfEdgeMask.PRIMARY_EDGE, + ): HalfEdgeGraph | undefined { if (chains.length < 1) return undefined; const graph = new HalfEdgeGraph(); @@ -612,5 +635,4 @@ export class HalfEdgeGraphMerge { } return graph; } - } diff --git a/core/geometry/src/topology/RegularizeFace.ts b/core/geometry/src/topology/RegularizeFace.ts index 8eda2b6e0322..7837289a9caa 100644 --- a/core/geometry/src/topology/RegularizeFace.ts +++ b/core/geometry/src/topology/RegularizeFace.ts @@ -78,7 +78,6 @@ export class RegularizationContext { else this.topPeaks.push(nodeB); } - } else { // ab is DOWN this.downEdges.push(nodeA); if (bcUp) { @@ -122,7 +121,6 @@ export class RegularizationContext { else this.topPeaks.push(nodeB); } - } else { // ab is DOWN this.downEdges.push(nodeA); if (bcUp) { @@ -136,9 +134,15 @@ export class RegularizationContext { } private swapArrays() { - let save = this.downEdges; this.downEdges = this.upEdges; this.upEdges = save; - save = this.localMax; this.localMax = this.localMin; this.localMin = save; - save = this.topPeaks; this.topPeaks = this.bottomPeaks; this.bottomPeaks = save; + let save = this.downEdges; + this.downEdges = this.upEdges; + this.upEdges = save; + save = this.localMax; + this.localMax = this.localMin; + this.localMin = save; + save = this.topPeaks; + this.topPeaks = this.bottomPeaks; + this.bottomPeaks = save; } /** @@ -150,8 +154,7 @@ export class RegularizationContext { * @param candidates Array of nodes to search * @param nodeComparisonFunction function for lexical comparison. */ - private findTopVisibleEdge(node: HalfEdge, candidates: HalfEdge[], - directionSign: number) { + private findTopVisibleEdge(node: HalfEdge, candidates: HalfEdge[], directionSign: number) { const y0 = node.y; const x0 = node.x; let dx; @@ -179,7 +182,6 @@ export class RegularizationContext { return result; } /** - * * @param downPeak a "bottom" node where the interior CCW loop has a local min * @param downEdgeStart (optional) node at the start (heading downwards!) of an edge that brackets downPeak on the left. * @param upEdgeStart (optional) node at the start (heading up!) of the edge that brackets downPeak on the right. @@ -215,7 +217,11 @@ export class RegularizationContext { return highestPeak; } - private updateMaxNode(maxNode: HalfEdge | undefined, candidate: HalfEdge | undefined, compare: (a: HalfEdge, b: HalfEdge) => number): HalfEdge | undefined { + private updateMaxNode( + maxNode: HalfEdge | undefined, + candidate: HalfEdge | undefined, + compare: (a: HalfEdge, b: HalfEdge) => number, + ): HalfEdge | undefined { if (!maxNode) return candidate; if (!candidate) @@ -373,7 +379,8 @@ export class RegularizationContext { positiveAreaOnly: boolean, mutate: (seed: HalfEdge) => HalfEdge | undefined, mappedEdges: HalfEdge[] | undefined, - unMappedSeeds: HalfEdge[] | undefined) { + unMappedSeeds: HalfEdge[] | undefined, + ) { if (mappedEdges) mappedEdges.length = 0; if (unMappedSeeds) @@ -396,5 +403,4 @@ export class RegularizationContext { } } } - } diff --git a/core/geometry/src/topology/SpaceTriangulation.ts b/core/geometry/src/topology/SpaceTriangulation.ts index 60555ad5d749..0e1512cd9aad 100644 --- a/core/geometry/src/topology/SpaceTriangulation.ts +++ b/core/geometry/src/topology/SpaceTriangulation.ts @@ -11,8 +11,8 @@ import { LineString3d } from "../curve/LineString3d"; import { Geometry } from "../Geometry"; import { Point3d } from "../geometry3d/Point3dVector3d"; import { Point3dArray } from "../geometry3d/PointHelpers"; -import {PolygonOps} from "../geometry3d/PolygonOps"; -import {PolylineOps} from "../geometry3d/PolylineOps"; +import { PolygonOps } from "../geometry3d/PolygonOps"; +import { PolylineOps } from "../geometry3d/PolylineOps"; type AnnounceLoopAndTrianglesFunction = (loop: Point3d[], triangles: Point3d[][]) => void; /** @@ -20,7 +20,6 @@ type AnnounceLoopAndTrianglesFunction = (loop: Point3d[], triangles: Point3d[][] * @public */ export class SpacePolygonTriangulation { - /** * * Return a number which is: * * 0 for collapsed (zero area) triangle @@ -32,10 +31,10 @@ export class SpacePolygonTriangulation { * @param point2 */ public static spaceTriangleAspectRatio(point0: Point3d, point1: Point3d, point2: Point3d): number { - const crossProduct = point0.crossProductToPoints (point1, point2); - const area = 0.5 * crossProduct.magnitude (); - const summedEdgeSquares = point0.distanceSquared (point1) + point1.distanceSquared (point2) + point2.distanceSquared (point0); - return Geometry.safeDivideFraction (area, summedEdgeSquares, 0.0); + const crossProduct = point0.crossProductToPoints(point1, point2); + const area = 0.5 * crossProduct.magnitude(); + const summedEdgeSquares = point0.distanceSquared(point1) + point1.distanceSquared(point2) + point2.distanceSquared(point0); + return Geometry.safeDivideFraction(area, summedEdgeSquares, 0.0); } /** * * Treat a space quad as two triangles with interior diagonal from point0 to point2 @@ -46,30 +45,30 @@ export class SpacePolygonTriangulation { * @param point2 third point (diagonally opposite point0) * @param point3 fourth point */ - public static spaceQuadDiagonalAspectRatio(point0: Point3d, point1: Point3d, point2: Point3d, point3: Point3d): number{ - const q012 = this.spaceTriangleAspectRatio (point0, point1, point2); - const q023 = this.spaceTriangleAspectRatio (point0, point2, point3); - return Math.max (q012, q023); + public static spaceQuadDiagonalAspectRatio(point0: Point3d, point1: Point3d, point2: Point3d, point3: Point3d): number { + const q012 = this.spaceTriangleAspectRatio(point0, point1, point2); + const q023 = this.spaceTriangleAspectRatio(point0, point2, point3); + return Math.max(q012, q023); } /** "Triangulate" by cutting of the ear with best aspect ratio. Reject if successive normals have negative dot product with PolygonOps.AreaNormal */ - public static triangulateGreedyEarCut(points: Point3d[], announceLoopAndTriangles: AnnounceLoopAndTrianglesFunction): boolean{ - const normalA = PolygonOps.areaNormal (points); + public static triangulateGreedyEarCut(points: Point3d[], announceLoopAndTriangles: AnnounceLoopAndTrianglesFunction): boolean { + const normalA = PolygonOps.areaNormal(points); const triangles: Point3d[][] = []; - const myPoints = points.slice (); - PolylineOps.removeClosurePoint (myPoints); + const myPoints = points.slice(); + PolylineOps.removeClosurePoint(myPoints); // first pass deals with entire array. // each pass lops off one point. - for (;myPoints.length > 2;){ + for (; myPoints.length > 2;) { // Find the ear candidate whose cross product vector has largest dot product (large area, best alignment with overall). let bestRatio = -1.0; let bestRatioIndex0 = 0; let i0 = myPoints.length - 2; let i1 = myPoints.length - 1; let i2; - for (i2 = 0; i2 < myPoints.length; i0 = i1, i1 = i2, i2++){ - const ratio = this.spaceTriangleAspectRatio (myPoints[i0], myPoints[i1], myPoints[i2]); - const normalB = myPoints[i0].crossProductToPoints (myPoints[i1], myPoints[i2]); - if (normalB.dotProduct (normalA) > 0 && ratio > bestRatio){ + for (i2 = 0; i2 < myPoints.length; i0 = i1, i1 = i2, i2++) { + const ratio = this.spaceTriangleAspectRatio(myPoints[i0], myPoints[i1], myPoints[i2]); + const normalB = myPoints[i0].crossProductToPoints(myPoints[i1], myPoints[i2]); + if (normalB.dotProduct(normalA) > 0 && ratio > bestRatio) { bestRatio = ratio; bestRatioIndex0 = i0; } @@ -81,44 +80,47 @@ export class SpacePolygonTriangulation { i1 = (i0 + 1) % myPoints.length; i2 = (i1 + 1) % myPoints.length; const t = []; - t.push (myPoints[i0], myPoints[i1], myPoints[i2]); + t.push(myPoints[i0], myPoints[i1], myPoints[i2]); // remove the middle point - myPoints.splice (i1, 1); + myPoints.splice(i1, 1); triangles.push(t); } - announceLoopAndTriangles (points, triangles); + announceLoopAndTriangles(points, triangles); return true; } - private static triangulateSimplestSpaceLoopGo(points: Point3d[], announceLoopAndTriangles: AnnounceLoopAndTrianglesFunction, - maxPerimeter: number | undefined): boolean{ - const n = Point3dArray.countNonDuplicates (points); - if (maxPerimeter !== undefined && Point3dArray.sumEdgeLengths (points, true, n) > maxPerimeter) - return false; - if (n < 3) - return false; - if (n === 3){ - if (this.spaceTriangleAspectRatio (points[0], points[1], points[2]) === 0) + private static triangulateSimplestSpaceLoopGo( + points: Point3d[], + announceLoopAndTriangles: AnnounceLoopAndTrianglesFunction, + maxPerimeter: number | undefined, + ): boolean { + const n = Point3dArray.countNonDuplicates(points); + if (maxPerimeter !== undefined && Point3dArray.sumEdgeLengths(points, true, n) > maxPerimeter) return false; - // already a triangle . . . - announceLoopAndTriangles (points, [points.slice ()]); - return true; - } - if (n === 4){ - const d02 = this.spaceQuadDiagonalAspectRatio (points[0], points[1], points[2], points[3]); - const d13 = this.spaceQuadDiagonalAspectRatio (points[1], points[2], points[3], points[0]); - if (d02 === 0.0 && d13 === 0.0) + if (n < 3) return false; - // announce the two triangles with better aspect ratios .... - if (d02 > d13){ - announceLoopAndTriangles (points, [[points[0], points[1], points[2]], [points[2], points[3], points[0]]]); - return true; - } else { - announceLoopAndTriangles (points, [[points[0], points[1], points[3]], [points[3], points[1], points[2]]]); + if (n === 3) { + if (this.spaceTriangleAspectRatio(points[0], points[1], points[2]) === 0) + return false; + // already a triangle . . . + announceLoopAndTriangles(points, [points.slice()]); return true; } - } - return this.triangulateGreedyEarCut (points, announceLoopAndTriangles); + if (n === 4) { + const d02 = this.spaceQuadDiagonalAspectRatio(points[0], points[1], points[2], points[3]); + const d13 = this.spaceQuadDiagonalAspectRatio(points[1], points[2], points[3], points[0]); + if (d02 === 0.0 && d13 === 0.0) + return false; + // announce the two triangles with better aspect ratios .... + if (d02 > d13) { + announceLoopAndTriangles(points, [[points[0], points[1], points[2]], [points[2], points[3], points[0]]]); + return true; + } else { + announceLoopAndTriangles(points, [[points[0], points[1], points[3]], [points[3], points[1], points[2]]]); + return true; + } + } + return this.triangulateGreedyEarCut(points, announceLoopAndTriangles); } /** * * Emit triangles for a (possibly non-planar) loop for various simple cases: @@ -128,13 +130,14 @@ export class SpacePolygonTriangulation { * * do not complete the triangulation if perimeter is larger than maxPerimeter (i.e. only consider small areas) * * Hence it is expected that the caller will use this as the first attempt, possibly followed by calls to other more adventurous methods. */ - public static triangulateSimplestSpaceLoop(loop: Point3d [] | LineString3d, + public static triangulateSimplestSpaceLoop( + loop: Point3d[] | LineString3d, announceLoopAndTriangles: AnnounceLoopAndTrianglesFunction, - maxPerimeter?: number): boolean{ + maxPerimeter?: number, + ): boolean { if (loop instanceof LineString3d) - return this.triangulateSimplestSpaceLoopGo (loop.points, announceLoopAndTriangles, maxPerimeter); - // (array case by exhaustion) - return this.triangulateSimplestSpaceLoopGo (loop, announceLoopAndTriangles, maxPerimeter); + return this.triangulateSimplestSpaceLoopGo(loop.points, announceLoopAndTriangles, maxPerimeter); + // (array case by exhaustion) + return this.triangulateSimplestSpaceLoopGo(loop, announceLoopAndTriangles, maxPerimeter); } - } diff --git a/core/geometry/src/topology/Triangulation.ts b/core/geometry/src/topology/Triangulation.ts index a2c90cf4b11e..ba461f2dc709 100644 --- a/core/geometry/src/topology/Triangulation.ts +++ b/core/geometry/src/topology/Triangulation.ts @@ -27,7 +27,6 @@ import { InsertAndRetriangulateContext, InsertedVertexZOptions } from "./InsertA * * @internal */ export class Triangulator { - /** Given the six nodes that make up two bordering triangles, "pinch" and relocate the nodes to flip them * * The shared edge mates are c and e. * * (abc) are a triangle in CCW order @@ -96,9 +95,16 @@ export class Triangulator { const ty = vx * vx + vy * vy; const tz = ux * ux + uy * uy; const q = Geometry.tripleProduct( - wx, wy, tx, - vx, vy, ty, - ux, uy, tz); + wx, + wy, + tx, + vx, + vy, + ty, + ux, + uy, + tz, + ); if (q < 0) return false; const denom = Math.abs(wx * vy * tz) + Math.abs(wy * ty * ux) + Math.abs(tx * vx * uy) @@ -134,13 +140,19 @@ export class Triangulator { let numOK = 0; let node; while (undefined !== (node = edgeSet.chooseAndRemoveAny())) { - if (node.isMaskSet(barrierMasks)) // Flip not allowed continue; if (Triangulator.computeInCircleDeterminantIsStrongPositive(node)) { // Flip the triangles - Triangulator.flipEdgeBetweenTriangles(node.edgeMate.faceSuccessor, node.edgeMate.facePredecessor, node.edgeMate, node.faceSuccessor, node, node.facePredecessor); + Triangulator.flipEdgeBetweenTriangles( + node.edgeMate.faceSuccessor, + node.edgeMate.facePredecessor, + node.edgeMate, + node.faceSuccessor, + node, + node.facePredecessor, + ); // keep looking at the 2 faces edgeSet.addAroundFace(node); edgeSet.addAroundFace(node.edgeMate); @@ -207,7 +219,7 @@ export class Triangulator { for (let i = 0; i < loops.length; i++) { let seed = Triangulator.directCreateFaceLoopFromCoordinates(graph, loops[i]); if (seed) { - seed = seed.faceSuccessor; // directCreate returns tail + seed = seed.faceSuccessor; // directCreate returns tail const mate = seed.vertexSuccessor; seed.setMaskAroundFace(mask); mate.setMaskAroundFace(mask); @@ -253,9 +265,10 @@ export class Triangulator { for (const face of seeds) { if (face.countEdgesAroundFace() > 3) { const area = face.signedFaceArea(); - if (area > 0.0) + if (area > 0.0) { if (!Triangulator.triangulateSingleFace(graph, face)) numFail++; + } } } return numFail === 0; @@ -375,7 +388,7 @@ export class Triangulator { * * no masking or other markup is applied. */ public static directCreateFaceLoopFromCoordinates(graph: HalfEdgeGraph, data: LineStringDataVariant): HalfEdge | undefined { - const n = this.getUnwrappedLength(data); // open it up to allow starting at a bridge edge + const n = this.getUnwrappedLength(data); // open it up to allow starting at a bridge edge let baseNode: HalfEdge | undefined; if (data instanceof IndexedXYZCollection) { const xyz = Point3d.create(); @@ -411,9 +424,13 @@ export class Triangulator { * @param maskForOtherSide mask to apply to the "other" side of the loop. * @return the loop's start node or its vertex successor, chosen to be the positive or negative loop per request. */ - private static maskAndOrientNewFaceLoop(_graph: HalfEdgeGraph, base: HalfEdge | undefined, returnPositiveAreaLoop: boolean, + private static maskAndOrientNewFaceLoop( + _graph: HalfEdgeGraph, + base: HalfEdge | undefined, + returnPositiveAreaLoop: boolean, maskForBothSides: HalfEdgeMask, - maskForOtherSide: HalfEdgeMask): HalfEdge | undefined { + maskForOtherSide: HalfEdgeMask, + ): HalfEdge | undefined { // base is the final coordinates if (base) { base = base.faceSuccessor; // because typical construction process leaves the "live" edge at the end of the loop. @@ -443,12 +460,19 @@ export class Triangulator { * * Use [[createFaceLoopFromCoordinatesAndMasks]] for detailed control of masks. */ public static createFaceLoopFromCoordinates( - graph: HalfEdgeGraph, data: LineStringDataVariant, returnPositiveAreaLoop: boolean, markExterior: boolean, + graph: HalfEdgeGraph, + data: LineStringDataVariant, + returnPositiveAreaLoop: boolean, + markExterior: boolean, ): HalfEdge | undefined { const base = Triangulator.directCreateFaceLoopFromCoordinates(graph, data); - return Triangulator.maskAndOrientNewFaceLoop(graph, base, returnPositiveAreaLoop, + return Triangulator.maskAndOrientNewFaceLoop( + graph, + base, + returnPositiveAreaLoop, HalfEdgeMask.BOUNDARY_EDGE | HalfEdgeMask.PRIMARY_EDGE, - markExterior ? HalfEdgeMask.EXTERIOR : HalfEdgeMask.NULL_MASK); + markExterior ? HalfEdgeMask.EXTERIOR : HalfEdgeMask.NULL_MASK, + ); } /** * create a circular doubly linked list of internal and external nodes from polygon points. @@ -459,9 +483,13 @@ export class Triangulator { * @param maskForBothSides mask to apply on both sides. * @param maskForOtherSide mask to apply on the "other" side from the returned loop. */ - public static createFaceLoopFromCoordinatesAndMasks(graph: HalfEdgeGraph, data: LineStringDataVariant, returnPositiveAreaLoop: boolean, + public static createFaceLoopFromCoordinatesAndMasks( + graph: HalfEdgeGraph, + data: LineStringDataVariant, + returnPositiveAreaLoop: boolean, maskForBothSides: HalfEdgeMask, - maskForOtherSide: HalfEdgeMask): HalfEdge | undefined { + maskForOtherSide: HalfEdgeMask, + ): HalfEdge | undefined { const base = Triangulator.directCreateFaceLoopFromCoordinates(graph, data); return Triangulator.maskAndOrientNewFaceLoop(graph, base, returnPositiveAreaLoop, maskForBothSides, maskForOtherSide); } @@ -475,8 +503,15 @@ export class Triangulator { */ private static joinNeighborsOfEar(graph: HalfEdgeGraph, ear: HalfEdge) { const alpha = graph.createEdgeXYZXYZ( - ear.facePredecessor.x, ear.facePredecessor.y, ear.facePredecessor.z, ear.facePredecessor.i, - ear.faceSuccessor.x, ear.faceSuccessor.y, ear.faceSuccessor.z, ear.faceSuccessor.i); + ear.facePredecessor.x, + ear.facePredecessor.y, + ear.facePredecessor.z, + ear.facePredecessor.i, + ear.faceSuccessor.x, + ear.faceSuccessor.y, + ear.faceSuccessor.z, + ear.faceSuccessor.i, + ); const beta = alpha.edgeMate; // Add two nodes alpha and beta and reassign pointers (also mark triangle nodes as part of triangle) @@ -580,7 +615,7 @@ export class Triangulator { const nullOrHoleFace = next2.vertexPredecessor; HalfEdge.pinch(pred.vertexSuccessor, nullOrHoleFace); // keep pred and next2 in their face loop } else { - HalfEdge.pinch(pred, next2); // pred and next2 split into different face loops + HalfEdge.pinch(pred, next2); // pred and next2 split into different face loops ear.setMaskAroundFace(HalfEdgeMask.TRIANGULATED_FACE); } ear = next2; @@ -611,7 +646,7 @@ export class Triangulator { } ear = next; } - return true; // um .. I'm not sure what this state is. + return true; // um .. I'm not sure what this state is. } /** @internal */ private static sDebugGraph: HalfEdgeGraph | undefined; @@ -634,7 +669,9 @@ export class Triangulator { * * If debug graph capture is enabled, save this graph. * * This is called by internal steps at point of failure to preserve the failing graph for unit test examination. * @internal */ - public static setDebugGraph(graph: HalfEdgeGraph | undefined) { if (Triangulator.sEnableDebugGraphCapture) Triangulator.sDebugGraph = graph; } + public static setDebugGraph(graph: HalfEdgeGraph | undefined) { + if (Triangulator.sEnableDebugGraphCapture) Triangulator.sDebugGraph = graph; + } /** * * Clear the debug graph * * Set capture enabled to indicated value. @@ -678,9 +715,11 @@ export class Triangulator { if (area <= 0) return false; // reflex, can't be an ear const planes = this._planes; - if (!Plane3dByOriginAndUnitNormal.createOriginAndTargetXY(a, b, planes[0]) + if ( + !Plane3dByOriginAndUnitNormal.createOriginAndTargetXY(a, b, planes[0]) || !Plane3dByOriginAndUnitNormal.createOriginAndTargetXY(b, c, planes[1]) - || !Plane3dByOriginAndUnitNormal.createOriginAndTargetXY(c, a, planes[2])) + || !Plane3dByOriginAndUnitNormal.createOriginAndTargetXY(c, a, planes[2]) + ) return false; // now make sure we don't have other points inside the potential ear, or edges crossing. @@ -705,15 +744,19 @@ export class Triangulator { if (!edgeInterval.isNull) { if (edgeInterval.low > oneMinus) { // only q touches triangle abc, so b might still be an ear if q lies at a vertex - if (!this.findAroundOrAtVertex(a, q) + if ( + !this.findAroundOrAtVertex(a, q) && !this.findAroundOrAtVertex(b, q) - && !this.findAroundOrAtVertex(c, q)) + && !this.findAroundOrAtVertex(c, q) + ) return false; } else if (edgeInterval.high < zeroPlus) { // only p touches triangle abc, so b might still be an ear if p lies at a vertex - if (!this.findAroundOrAtVertex(a, p) + if ( + !this.findAroundOrAtVertex(a, p) && !this.findAroundOrAtVertex(b, p) - && !this.findAroundOrAtVertex(c, p)) + && !this.findAroundOrAtVertex(c, p) + ) return false; } else if (this.findAroundOrAtVertex(b, q) && this.findAroundOrAtVertex(c, p)) { // edge pq is the back side of bridge edge bc, so b might still be an ear @@ -729,10 +772,8 @@ export class Triangulator { return true; } /** link holeLoopNodes[1], holeLoopNodes[2] etc into the outer loop, producing a single-ring polygon without holes - * */ private static spliceLeftMostNodesOfHoles(graph: HalfEdgeGraph, outerNode: HalfEdge, leftMostHoleLoopNode: HalfEdge[]): HalfEdge | undefined { - leftMostHoleLoopNode.sort((a, b) => Triangulator.compareX(a, b)); let numFail = 0; // process holes from left to right @@ -806,9 +847,10 @@ export class Triangulator { p = m.faceSuccessor; while (p !== stop) { - if (hx >= p.x && p.x >= mx && hx !== p.x && - Triangulator.pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) { - + if ( + hx >= p.x && p.x >= mx && hx !== p.x && + Triangulator.pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y) + ) { tan = Math.abs(hy - p.y) / (hx - p.x); // tangential if ((tan < tanMin || (tan === tanMin && p.x > m.x)) && Triangulator.locallyInside(p, hole)) { @@ -853,13 +895,13 @@ export class Triangulator { /** signed area of a triangle * EDL 2/21 This is negative of usual CCW area. Beware in callers !!! * (This originates in classic earcut code.) - */ + */ private static signedCWTriangleArea(p: HalfEdge, q: HalfEdge, r: HalfEdge) { return 0.5 * ((q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)); } /** signed area of a triangle, with small positive corrected to zero by relTol - */ + */ private static signedTolerancedCCWTriangleArea(p: HalfEdge, q: HalfEdge, r: HalfEdge, relTol: number = 1.0e-12) { const ux = q.x - p.x; const uy = q.y - p.y; @@ -914,9 +956,11 @@ export class Triangulator { let right = start.faceSuccessor; // P0, P1, P2 are successive edges along evolving chain let upperSideOfNewEdge; - while (left !== right + while ( + left !== right && right !== start - && right.faceSuccessor !== left) { + && right.faceSuccessor !== left + ) { /** These should not happen if face is monotone . .. */ if (HalfEdge.crossProductXYAlongChain(left, start, right) <= 0) return false; @@ -939,10 +983,12 @@ export class Triangulator { (following start) is never altered. */ while (P0 !== P2 && P0.belowYX(right)) { - while (P2 !== right + while ( + P2 !== right && P2 !== P0 && P2 !== P1 - && HalfEdge.crossProductXYAlongChain(P0, P1, P2) > 0) { + && HalfEdge.crossProductXYAlongChain(P0, P1, P2) > 0 + ) { upperSideOfNewEdge = Triangulator.splitFace(graph, P0, P2); if (upperSideOfNewEdge === undefined) return false; @@ -980,7 +1026,6 @@ export class Triangulator { start = P0; right = start.faceSuccessor; left = start.facePredecessor; - } else { /* Triangulate to all right side edges that are below left */ @@ -998,10 +1043,12 @@ export class Triangulator { left.faceSuccessor rather than as start. */ while (P0 !== P2 && P2.belowYX(left)) { - while (P0 !== left + while ( + P0 !== left && P2 !== P0 && P2 !== P1 - && HalfEdge.crossProductXYAlongChain(P0, P1, P2) > 0) { + && HalfEdge.crossProductXYAlongChain(P0, P1, P2) > 0 + ) { upperSideOfNewEdge = Triangulator.splitFace(graph, P0, P2); if (upperSideOfNewEdge === undefined) return false; @@ -1043,7 +1090,6 @@ export class Triangulator { } return true; } - } /** diff --git a/core/geometry/src/topology/XYParitySearchContext.ts b/core/geometry/src/topology/XYParitySearchContext.ts index 6acb40915c7a..69ea225c1025 100644 --- a/core/geometry/src/topology/XYParitySearchContext.ts +++ b/core/geometry/src/topology/XYParitySearchContext.ts @@ -44,7 +44,11 @@ export class XYParitySearchContext { public constructor(xTest: number, yTest: number) { this.xTest = xTest; this.yTest = yTest; - this.u0 = this.v0 = this.u1 = this.v1 = 0; // not valid for search; caller must satisfy tryStartEdge + this.u0 = + this.v0 = + this.u1 = + this.v1 = + 0; // not valid for search; caller must satisfy tryStartEdge this.numLeftCrossing = this.numRightCrossing = 0; this.numHit = 0; } @@ -55,7 +59,7 @@ export class XYParitySearchContext { this.v0 = y0 - this.yTest; this.u1 = x1 - this.xTest; this.v1 = y1 - this.yTest; - return true; // we won't need wraparound logic to process the final edge ending at (x0,y0) + return true; // we won't need wraparound logic to process the final edge ending at (x0,y0) } return false; } @@ -93,7 +97,7 @@ export class XYParitySearchContext { const lambda = -this.v1 / (v2 - this.v1); const uCross = this.u1 + lambda * (u2 - this.u1); if (uCross === 0.0) { - this.numHit++; // Current edge crosses at the origin. + this.numHit++; // Current edge crosses at the origin. return false; } if (uCross > 0) @@ -106,7 +110,7 @@ export class XYParitySearchContext { if (v2 === 0.0) { if (this.v1 === 0.0) { if (u2 * this.u1 <= 0.0) { - this.numHit++; // Current edge lies on u-axis and contains the origin. + this.numHit++; // Current edge lies on u-axis and contains the origin. return false; } // Current edge lies on the u-axis to one side of the origin. @@ -116,7 +120,7 @@ export class XYParitySearchContext { return true; } if (u2 === 0.0) { - this.numHit++; // Current edge ends at the origin. + this.numHit++; // Current edge ends at the origin. return false; } // Current edge ends on the u-axis away from the origin. @@ -124,7 +128,7 @@ export class XYParitySearchContext { } // At this point, the current edge starts at the u-axis. if (this.u1 === 0.0) { - this.numHit++; // Current edge starts at the origin. + this.numHit++; // Current edge starts at the origin. return false; } // At this point, the current edge starts on the u-axis away from the origin. diff --git a/core/geometry/vitest.config.mts b/core/geometry/vitest.config.mts index 45ac268abffc..1bb25945f30f 100644 --- a/core/geometry/vitest.config.mts +++ b/core/geometry/vitest.config.mts @@ -1,4 +1,4 @@ -import { coverageConfigDefaults, defineConfig } from 'vitest/config'; +import { coverageConfigDefaults, defineConfig } from "vitest/config"; export default defineConfig({ test: { dir: "src/test", @@ -7,26 +7,26 @@ export default defineConfig({ coverage: { provider: "v8", include: [ - "src/**/*" + "src/**/*", ], exclude: [ ...coverageConfigDefaults.exclude, "src/test/**/*", "**/*.d.ts", - "**/*.d.tsx" + "**/*.d.tsx", ], reporter: [ "text-summary", "lcov", - "cobertura" + "cobertura", ], reportsDirectory: "./lib/cjs/test/coverage", thresholds: { // This should not be in the default config file. branches: 70, statements: 85, functions: 85, - lines: 85 - } + lines: 85, + }, }, deps: { optimizer: { @@ -35,5 +35,5 @@ export default defineConfig({ }, }, }, - } -}) + }, +}); diff --git a/core/hypermodeling/certa.json b/core/hypermodeling/certa.json index 7e5d44843e1a..936f221b80dc 100644 --- a/core/hypermodeling/certa.json +++ b/core/hypermodeling/certa.json @@ -23,4 +23,4 @@ "--no-sandbox" ] } -} \ No newline at end of file +} diff --git a/core/hypermodeling/eslint.config.js b/core/hypermodeling/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/hypermodeling/eslint.config.js +++ b/core/hypermodeling/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/hypermodeling/src/HyperModeling.ts b/core/hypermodeling/src/HyperModeling.ts index 267808121f82..08efa94e1ca9 100644 --- a/core/hypermodeling/src/HyperModeling.ts +++ b/core/hypermodeling/src/HyperModeling.ts @@ -9,10 +9,10 @@ import { assert } from "@itwin/core-bentley"; import { SectionType } from "@itwin/core-common"; import { IModelApp, IModelConnection, ScreenViewport, tryImageElementFromUrl, ViewManip } from "@itwin/core-frontend"; -import { registerTools } from "./Tools"; -import { HyperModelingDecorator } from "./HyperModelingDecorator"; import { HyperModelingConfig, SectionGraphicsConfig, SectionMarkerConfig } from "./HyperModelingConfig"; +import { HyperModelingDecorator } from "./HyperModelingDecorator"; import { SectionMarkerHandler } from "./SectionMarkerHandler"; +import { registerTools } from "./Tools"; /** @internal */ export interface MarkerData { diff --git a/core/hypermodeling/src/HyperModelingDecorator.ts b/core/hypermodeling/src/HyperModelingDecorator.ts index bd6109f5e30d..2bf15e0226ef 100644 --- a/core/hypermodeling/src/HyperModelingDecorator.ts +++ b/core/hypermodeling/src/HyperModelingDecorator.ts @@ -6,17 +6,25 @@ * @module HyperModeling */ -import { Transform, XAndY } from "@itwin/core-geometry"; import type { AbstractToolbarProps } from "@itwin/appui-abstract"; import { - ChangeFlags, DecorateContext, Decorator, IModelApp, IModelConnection, ScreenViewport, SpatialViewState, TiledGraphicsProvider, ViewClipTool, + ChangeFlags, + DecorateContext, + Decorator, + IModelApp, + IModelConnection, + ScreenViewport, + SpatialViewState, + TiledGraphicsProvider, + ViewClipTool, } from "@itwin/core-frontend"; -import { SectionMarker, SectionMarkerSet } from "./SectionMarkers"; -import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; -import { createSectionGraphicsProvider } from "./SectionGraphicsProvider"; -import { PopupToolbarManager, PopupToolbarProvider } from "./PopupToolbar"; +import { Transform, XAndY } from "@itwin/core-geometry"; import { HyperModeling } from "./HyperModeling"; import { SectionMarkerConfig } from "./HyperModelingConfig"; +import { PopupToolbarManager, PopupToolbarProvider } from "./PopupToolbar"; +import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; +import { createSectionGraphicsProvider } from "./SectionGraphicsProvider"; +import { SectionMarker, SectionMarkerSet } from "./SectionMarkers"; async function createMarkers(vp: ScreenViewport): Promise { if (!vp.view.isSpatialView()) diff --git a/core/hypermodeling/src/PopupToolbar.ts b/core/hypermodeling/src/PopupToolbar.ts index dd3d732fbb60..b8b237bd5f2d 100644 --- a/core/hypermodeling/src/PopupToolbar.ts +++ b/core/hypermodeling/src/PopupToolbar.ts @@ -6,9 +6,9 @@ * @module HyperModeling */ -import { XAndY } from "@itwin/core-geometry"; import type { AbstractToolbarProps } from "@itwin/appui-abstract"; import { IModelApp } from "@itwin/core-frontend"; +import { XAndY } from "@itwin/core-geometry"; /** @internal */ export interface PopupToolbarProvider { diff --git a/core/hypermodeling/src/SectionDrawingLocationState.ts b/core/hypermodeling/src/SectionDrawingLocationState.ts index 9e48c647ae58..4eee54ba3522 100644 --- a/core/hypermodeling/src/SectionDrawingLocationState.ts +++ b/core/hypermodeling/src/SectionDrawingLocationState.ts @@ -135,7 +135,7 @@ export class SectionDrawingLocationState { if (str) { try { clip = ClipVector.fromJSON(JSON.parse(str)); - } catch { } + } catch {} } return clip; @@ -170,7 +170,7 @@ export class SectionDrawingLocationState { const view = await this.iModel.views.load(this.drawingViewId); if (view instanceof DrawingViewState) return view; - } catch { } + } catch {} return undefined; } @@ -181,7 +181,7 @@ export class SectionDrawingLocationState { const view = await this.iModel.views.load(this.spatialViewId); if (view instanceof SpatialViewState) return view; - } catch { } + } catch {} return undefined; } @@ -195,7 +195,7 @@ export class SectionDrawingLocationState { const view = await this.iModel.views.load(this.viewAttachment.viewId); if (view instanceof SheetViewState) return view; - } catch { } + } catch {} return undefined; } @@ -204,7 +204,9 @@ export class SectionDrawingLocationState { public static async queryAll(iModel: IModelConnection): Promise { const states: SectionDrawingLocationState[] = []; try { - for await (const row of iModel.createQueryReader(selectSectionDrawingLocationStatesECSql, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) + for await ( + const row of iModel.createQueryReader(selectSectionDrawingLocationStatesECSql, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }) + ) states.push(new SectionDrawingLocationState(row.toRow() as SectionDrawingLocationStateData, iModel)); } catch { // If the iModel contains a version of BisCore schema older than 1.12.0, the query will produce an exception due to missing SectionDrawingLocation class. That's fine. diff --git a/core/hypermodeling/src/SectionGraphicsProvider.ts b/core/hypermodeling/src/SectionGraphicsProvider.ts index aed58f4f408a..7cd09658c17c 100644 --- a/core/hypermodeling/src/SectionGraphicsProvider.ts +++ b/core/hypermodeling/src/SectionGraphicsProvider.ts @@ -7,15 +7,38 @@ */ import { assert, compareBooleans, compareStrings, Id64 } from "@itwin/core-bentley"; -import { ClipShape, ClipVector, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { ColorDef, Placement2d, ViewAttachmentProps, ViewDefinition2dProps, ViewFlagOverrides } from "@itwin/core-common"; import { - CategorySelectorState, DisclosedTileTreeSet, DisplayStyle2dState, DrawingViewState, - FeatureSymbology, GeometricModel2dState, GraphicBranch, HitDetail, IModelApp, IModelConnection, RenderClipVolume, RenderSystem, SheetModelState, Tile, TileContent, TiledGraphicsProvider, TileDrawArgs, - TileLoadPriority, TileRequest, TileRequestChannel, TileTree, TileTreeOwner, TileTreeReference, TileTreeSupplier, Viewport, ViewState2d, + CategorySelectorState, + DisclosedTileTreeSet, + DisplayStyle2dState, + DrawingViewState, + FeatureSymbology, + GeometricModel2dState, + GraphicBranch, + HitDetail, + IModelApp, + IModelConnection, + RenderClipVolume, + RenderSystem, + SheetModelState, + Tile, + TileContent, + TiledGraphicsProvider, + TileDrawArgs, + TileLoadPriority, + TileRequest, + TileRequestChannel, + TileTree, + TileTreeOwner, + TileTreeReference, + TileTreeSupplier, + Viewport, + ViewState2d, } from "@itwin/core-frontend"; -import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; +import { ClipShape, ClipVector, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { HyperModeling } from "./HyperModeling"; +import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; interface ProxyTreeId { state: SectionDrawingLocationState; @@ -126,7 +149,9 @@ class ProxyTreeReference extends TileTreeReference { return true !== HyperModeling.graphicsConfig.ignoreClip ? super.getClipVolume(tree) : undefined; } - public get treeOwner() { return this._owner; } + public get treeOwner() { + return this._owner; + } private get _proxiedRef(): TileTreeReference | undefined { const proxiedTree = this.treeOwner.tileTree as ProxyTree; @@ -184,11 +209,21 @@ abstract class ProxyTree extends TileTree { this._rootTile = new ProxyTile(this, range); } - public get rootTile(): ProxyTile { return this._rootTile; } - public get viewFlagOverrides() { return this._viewFlagOverrides; } - public get is3d() { return false; } - public override get isContentUnbounded() { return false; } - public get maxDepth() { return 1; } + public get rootTile(): ProxyTile { + return this._rootTile; + } + public get viewFlagOverrides() { + return this._viewFlagOverrides; + } + public get is3d() { + return false; + } + public override get isContentUnbounded() { + return false; + } + public get maxDepth() { + return 1; + } protected abstract get isDisplayed(): boolean; @@ -243,7 +278,9 @@ class DrawingProxyTree extends ProxyTree { super(params, location, clipVolume); } - protected get isDisplayed() { return true !== HyperModeling.graphicsConfig.hideSectionGraphics; } + protected get isDisplayed() { + return true !== HyperModeling.graphicsConfig.hideSectionGraphics; + } } class SheetProxyTree extends ProxyTree { @@ -263,7 +300,9 @@ class SheetProxyTree extends ProxyTree { this.symbologyOverrides.ignoreSubCategory = true; } - protected get isDisplayed() { return true !== HyperModeling.graphicsConfig.hideSheetAnnotations; } + protected get isDisplayed() { + return true !== HyperModeling.graphicsConfig.hideSheetAnnotations; + } } /** The single Tile belonging to a ProxyTree, serving as a proxy for all of the proxied tree's tiles. */ @@ -273,13 +312,23 @@ class ProxyTile extends Tile { this.setIsReady(); } - public get hasChildren() { return false; } - public override get hasGraphics() { return true; } + public get hasChildren() { + return false; + } + public override get hasGraphics() { + return true; + } - public get channel(): TileRequestChannel { throw new Error("Proxy tile has no content"); } - public async requestContent(_isCanceled: () => boolean): Promise { return undefined; } - public async readContent(_data: TileRequest.ResponseData, _system: RenderSystem, _isCanceled?: () => boolean): Promise { return {}; } - protected _loadChildren(_resolve: (children: Tile[]) => void, _reject: (error: Error) => void): void { } + public get channel(): TileRequestChannel { + throw new Error("Proxy tile has no content"); + } + public async requestContent(_isCanceled: () => boolean): Promise { + return undefined; + } + public async readContent(_data: TileRequest.ResponseData, _system: RenderSystem, _isCanceled?: () => boolean): Promise { + return {}; + } + protected _loadChildren(_resolve: (children: Tile[]) => void, _reject: (error: Error) => void): void {} public override drawGraphics(args: TileDrawArgs) { const proxyTree = this.tree as ProxyTree; @@ -287,7 +336,16 @@ class ProxyTile extends Tile { const location = proxyTree.iModelTransform.multiplyTransformTransform(sectionTree.iModelTransform); const clipVolume = true === proxyTree.viewFlagOverrides.clipVolume ? proxyTree.clipVolume : undefined; - args = new TileDrawArgs({ context: args.context, location, tree: sectionTree, now: args.now, viewFlagOverrides: proxyTree.viewFlagOverrides, clipVolume, parentsAndChildrenExclusive: args.parentsAndChildrenExclusive, symbologyOverrides: proxyTree.symbologyOverrides }); + args = new TileDrawArgs({ + context: args.context, + location, + tree: sectionTree, + now: args.now, + viewFlagOverrides: proxyTree.viewFlagOverrides, + clipVolume, + parentsAndChildrenExclusive: args.parentsAndChildrenExclusive, + symbologyOverrides: proxyTree.symbologyOverrides, + }); sectionTree.draw(args); const rangeGfx = this.getRangeGraphic(args.context); diff --git a/core/hypermodeling/src/SectionMarkerHandler.ts b/core/hypermodeling/src/SectionMarkerHandler.ts index 9eb931b09c90..16a7a7d4bac1 100644 --- a/core/hypermodeling/src/SectionMarkerHandler.ts +++ b/core/hypermodeling/src/SectionMarkerHandler.ts @@ -6,11 +6,11 @@ * @module HyperModeling */ -import { IModelApp } from "@itwin/core-frontend"; import type { AbstractToolbarProps } from "@itwin/appui-abstract"; -import { SectionMarker } from "./SectionMarkers"; +import { IModelApp } from "@itwin/core-frontend"; import { SectionMarkerConfig } from "./HyperModelingConfig"; import { HyperModelingDecorator } from "./HyperModelingDecorator"; +import { SectionMarker } from "./SectionMarkers"; /** Supplies interactions with [[SectionMarker]]s, including a mini-toolbar displayed when the mouse hovers over a marker and what action occurs when the user clicks a marker. * The base implementation supplies the following interactions: @@ -50,7 +50,7 @@ export class SectionMarkerHandler { itemPriority: 10, label: localization.getLocalizedString("HyperModeling:Message.ApplyView"), icon: "icon-spatial-view-apply", - execute: () => { }, + execute: () => {}, isDisabled: false, }, { @@ -58,7 +58,7 @@ export class SectionMarkerHandler { itemPriority: 20, label: localization.getLocalizedString("HyperModeling:Message.OpenSection"), icon: "icon-plan-drawing", - execute: () => { }, + execute: () => {}, isDisabled: false, }, { @@ -66,7 +66,7 @@ export class SectionMarkerHandler { itemPriority: 30, label: localization.getLocalizedString("HyperModeling:Message.OpenSheet"), icon: "icon-plan-floor", - execute: () => { }, + execute: () => {}, isDisabled: undefined === marker.state.viewAttachment?.viewId, }, ], diff --git a/core/hypermodeling/src/SectionMarkers.ts b/core/hypermodeling/src/SectionMarkers.ts index 9487233323c9..2128b77be258 100644 --- a/core/hypermodeling/src/SectionMarkers.ts +++ b/core/hypermodeling/src/SectionMarkers.ts @@ -7,13 +7,23 @@ */ import { assert, BeEvent, Id64String } from "@itwin/core-bentley"; -import { Point2d, Point3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { IModelReadRpcInterface } from "@itwin/core-common"; import { - BeButton, BeButtonEvent, Cluster, DecorateContext, IModelApp, InputSource, Marker, MarkerImage, MarkerSet, ScreenViewport, ViewClipTool, + BeButton, + BeButtonEvent, + Cluster, + DecorateContext, + IModelApp, + InputSource, + Marker, + MarkerImage, + MarkerSet, + ScreenViewport, + ViewClipTool, } from "@itwin/core-frontend"; -import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; +import { Point2d, Point3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { HyperModeling } from "./HyperModeling"; +import { SectionDrawingLocationState } from "./SectionDrawingLocationState"; const markerSize = Point2d.create(40, 40); @@ -55,7 +65,9 @@ export class SectionMarker extends Marker { } /** @internal */ - public get isHilited(): boolean { return this._isHilited; } + public get isHilited(): boolean { + return this._isHilited; + } /** Returns true if this is the "active" section marker. At most one marker is active at a given time. * @see [[HyperModelingDecorator.activeMarker]]. @@ -88,7 +100,10 @@ export class SectionMarker extends Marker { public override onMouseEnter(ev: BeButtonEvent) { // Lazily load the tooltip. if (undefined === this.title) { - IModelReadRpcInterface.getClientForRouting(this.state.iModel.routingContext.token).getToolTipMessage(this.state.iModel.getRpcProps(), this.state.id).then((tooltipMsg) => { + IModelReadRpcInterface.getClientForRouting(this.state.iModel.routingContext.token).getToolTipMessage( + this.state.iModel.getRpcProps(), + this.state.id, + ).then((tooltipMsg) => { this.title = IModelApp.formatElementToolTip(tooltipMsg); }).catch((_) => { this.title = this.description; @@ -159,7 +174,9 @@ export class SectionMarkerCluster extends Marker { ctx.stroke(); } - public override onMouseButton(_ev: BeButtonEvent): boolean { return true; } // Don't allow clicks to be sent to active tool... + public override onMouseButton(_ev: BeButtonEvent): boolean { + return true; + } // Don't allow clicks to be sent to active tool... } /** A [MarkerSet]($frontend) containing [[SectionMarker]]s identifying [SectionDrawingLocation]($backend)s within a spatial view. diff --git a/core/hypermodeling/src/Tools.ts b/core/hypermodeling/src/Tools.ts index 98ef98d1a15c..ba592fed9952 100644 --- a/core/hypermodeling/src/Tools.ts +++ b/core/hypermodeling/src/Tools.ts @@ -18,17 +18,25 @@ function parseToggle(arg: string | undefined): string | boolean | undefined { return undefined; switch (arg.toLowerCase()) { - case "on": return true; - case "off": return false; - case "toggle": return undefined; - default: return arg; + case "on": + return true; + case "off": + return false; + case "toggle": + return undefined; + default: + return arg; } } class HyperModelingTool extends Tool { public static override toolId = "HyperModeling"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean, vp?: ScreenViewport): Promise { vp = vp ?? IModelApp.viewManager.selectedView; @@ -55,8 +63,12 @@ type Writeable = { -readonly [P in keyof T]: T[P] }; */ class SectionGraphicsConfigTool extends Tool { public static override toolId = "HyperModeling.Graphics.Config"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } public override async run(config?: SectionGraphicsConfig): Promise { if (!config) { @@ -108,8 +120,12 @@ class SectionGraphicsConfigTool extends Tool { } abstract class SectionMarkerConfigTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } protected abstract update(config: SectionMarkerConfig): void; diff --git a/core/hypermodeling/src/test/HyperModeling.test.ts b/core/hypermodeling/src/test/HyperModeling.test.ts index c20dc5a8354d..d7613dfd51ae 100644 --- a/core/hypermodeling/src/test/HyperModeling.test.ts +++ b/core/hypermodeling/src/test/HyperModeling.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { EmptyLocalization, SectionType } from "@itwin/core-common"; import { IModelApp, ParseAndRunResult } from "@itwin/core-frontend"; +import { expect } from "chai"; import { HyperModeling } from "../HyperModeling"; import { HyperModelingConfig, SectionGraphicsConfig, SectionMarkerConfig } from "../HyperModelingConfig"; import { SectionMarkerHandler } from "../SectionMarkerHandler"; @@ -84,7 +84,9 @@ describe("Package configuration", () => { }; test({ markerHandler: new SectionMarkerHandler() }); - test({ markers: { ignoreModelSelector: true, ignoreCategorySelector: undefined, hiddenSectionTypes: [SectionType.Elevation, SectionType.Plan] } }); + test({ + markers: { ignoreModelSelector: true, ignoreCategorySelector: undefined, hiddenSectionTypes: [SectionType.Elevation, SectionType.Plan] }, + }); test({ graphics: { ignoreClip: true, debugClipVolumes: false, hideSectionGraphics: undefined, hideSheetAnnotations: true } }); }); @@ -102,23 +104,36 @@ describe("Package configuration", () => { const handler = new SectionMarkerHandler(); test( { markerHandler: handler }, - { markerHandler: handler }); + { markerHandler: handler }, + ); test( { markers: { ignoreModelSelector: true, hiddenSectionTypes: [SectionType.Elevation] } }, - { markerHandler: handler, markers: { ignoreModelSelector: true, hiddenSectionTypes: [SectionType.Elevation] } }); + { markerHandler: handler, markers: { ignoreModelSelector: true, hiddenSectionTypes: [SectionType.Elevation] } }, + ); test( { markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] } }, - { markerHandler: handler, markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] } }); + { markerHandler: handler, markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] } }, + ); test( { graphics: { ignoreClip: true, debugClipVolumes: false } }, - { markerHandler: handler, markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] }, graphics: { ignoreClip: true, debugClipVolumes: false } }); + { + markerHandler: handler, + markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] }, + graphics: { ignoreClip: true, debugClipVolumes: false }, + }, + ); test( { markerHandler: undefined, markers: {}, graphics: undefined }, - { markerHandler: handler, markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] }, graphics: { ignoreClip: true, debugClipVolumes: false } }); + { + markerHandler: handler, + markers: { ignoreModelSelector: false, ignoreCategorySelector: true, hiddenSectionTypes: [] }, + graphics: { ignoreClip: true, debugClipVolumes: false }, + }, + ); // Reset for subsequent tests... HyperModeling.replaceConfiguration(undefined); diff --git a/core/hypermodeling/src/test/utils/webpack.config.js b/core/hypermodeling/src/test/utils/webpack.config.js index 9ccdbbdc49df..3f3bf581909b 100644 --- a/core/hypermodeling/src/test/utils/webpack.config.js +++ b/core/hypermodeling/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -57,8 +57,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -83,5 +83,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/core/hypermodeling/tsconfig.json b/core/hypermodeling/tsconfig.json index c53ab65dd3e7..c99078e35df3 100644 --- a/core/hypermodeling/tsconfig.json +++ b/core/hypermodeling/tsconfig.json @@ -5,5 +5,5 @@ }, "include": [ "./src/**/*.ts" - ], + ] } diff --git a/core/i18n/certa.json b/core/i18n/certa.json index b77465ca1bf0..096c671ac3cc 100644 --- a/core/i18n/certa.json +++ b/core/i18n/certa.json @@ -22,4 +22,4 @@ "src/test/public" ] } -} \ No newline at end of file +} diff --git a/core/i18n/eslint.config.js b/core/i18n/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/i18n/eslint.config.js +++ b/core/i18n/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/i18n/src/ITwinLocalization.ts b/core/i18n/src/ITwinLocalization.ts index 7a0ac1ea9498..33342f487df2 100644 --- a/core/i18n/src/ITwinLocalization.ts +++ b/core/i18n/src/ITwinLocalization.ts @@ -6,11 +6,11 @@ * @module Localization */ +import { Logger } from "@itwin/core-bentley"; +import type { Localization } from "@itwin/core-common"; import i18next, { i18n, InitOptions, Module, TOptionsBase } from "i18next"; import i18nextBrowserLanguageDetector, { DetectorOptions } from "i18next-browser-languagedetector"; import Backend, { BackendOptions } from "i18next-http-backend"; -import { Logger } from "@itwin/core-bentley"; -import type { Localization } from "@itwin/core-common"; const DEFAULT_MAX_RETRIES: number = 1; // a low number prevents wasted time and potential timeouts when requesting localization files throws an error @@ -69,7 +69,6 @@ export class ITwinLocalization implements Localization { } public async initialize(namespaces: string[]): Promise { - // Also consider namespaces passed into constructor const initNamespaces: string[] = [this._initOptions.ns || []].flat(); const combinedNamespaces: Set = new Set([...namespaces, ...initNamespaces]); // without duplicates @@ -261,9 +260,15 @@ export class ITwinLocalization implements Localization { class TranslationLogger { public static readonly type = "logger"; - public log(args: string[]) { Logger.logInfo("i18n", this.createLogMessage(args)); } - public warn(args: string[]) { Logger.logWarning("i18n", this.createLogMessage(args)); } - public error(args: string[]) { Logger.logError("i18n", this.createLogMessage(args)); } + public log(args: string[]) { + Logger.logInfo("i18n", this.createLogMessage(args)); + } + public warn(args: string[]) { + Logger.logWarning("i18n", this.createLogMessage(args)); + } + public error(args: string[]) { + Logger.logError("i18n", this.createLogMessage(args)); + } private createLogMessage(args: string[]) { let message = args[0]; for (let i = 1; i < args.length; ++i) { diff --git a/core/i18n/src/test/ITwinLocalization.test.ts b/core/i18n/src/test/ITwinLocalization.test.ts index eeb056049a71..4a08a052b705 100644 --- a/core/i18n/src/test/ITwinLocalization.test.ts +++ b/core/i18n/src/test/ITwinLocalization.test.ts @@ -3,17 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Localization } from "@itwin/core-common"; +import { assert } from "chai"; import { ITwinLocalization } from "../ITwinLocalization"; describe("ITwinLocalization", () => { - let localization: Localization; let germanLocalization: Localization; describe("#constructor", () => { - let itwinLocalization: ITwinLocalization; it("set default namespace", async () => { @@ -60,7 +58,6 @@ describe("ITwinLocalization", () => { }); describe("with no default namespace predefined", () => { - before(() => { itwinLocalization = new ITwinLocalization(); }); @@ -106,7 +103,6 @@ describe("ITwinLocalization", () => { }); describe("with default namespace", () => { - before(() => { itwinLocalization = new ITwinLocalization({ initOptions: { defaultNS: "Default" } }); }); @@ -144,7 +140,6 @@ describe("ITwinLocalization", () => { }); describe("#getLocalizedKeys", () => { - before(async () => { localization = new ITwinLocalization(); await localization.initialize(["Default", "Test"]); @@ -158,7 +153,6 @@ describe("ITwinLocalization", () => { }); describe("Default Namespace", () => { - it("first level string", () => { assert.equal(localization.getLocalizedKeys("hi %{FirstTrivial}"), "hi First level string (default)"); assert.equal(germanLocalization.getLocalizedKeys("hi %{FirstTrivial}"), "hi First level string (default german)"); @@ -182,7 +176,10 @@ describe("ITwinLocalization", () => { assert.equal(localization.getLocalizedKeys("%{SecondSubstitution.Test1}"), "Substitute {{varA}} and {{varB}} (default)"); assert.equal(localization.getLocalizedKeys("hi %{SecondSubstitution.Test2}"), "hi Reverse substitute {{varB}} and {{varA}} (default)"); assert.equal(germanLocalization.getLocalizedKeys("%{SecondSubstitution.Test1}"), "Substitute {{varA}} and {{varB}} (default german)"); - assert.equal(germanLocalization.getLocalizedKeys("hi %{SecondSubstitution.Test2}"), "hi Reverse substitute {{varB}} and {{varA}} (default german)"); + assert.equal( + germanLocalization.getLocalizedKeys("hi %{SecondSubstitution.Test2}"), + "hi Reverse substitute {{varB}} and {{varA}} (default german)", + ); }); it("first level missing key doesn't find a value", () => { @@ -197,7 +194,6 @@ describe("ITwinLocalization", () => { }); describe("Given Namespace", () => { - it("first level string", () => { assert.equal(localization.getLocalizedKeys("hi %{Default:FirstTrivial}"), "hi First level string (default)"); assert.equal(localization.getLocalizedKeys("hi %{Test:FirstTrivial}"), "hi First level string (test)"); @@ -219,7 +215,10 @@ describe("ITwinLocalization", () => { it("second level string with keys", () => { assert.equal(localization.getLocalizedKeys("%{Default:SecondSubstitution.Test1}"), "Substitute {{varA}} and {{varB}} (default)"); - assert.equal(localization.getLocalizedKeys("hi %{Default:SecondSubstitution.Test2}"), "hi Reverse substitute {{varB}} and {{varA}} (default)"); + assert.equal( + localization.getLocalizedKeys("hi %{Default:SecondSubstitution.Test2}"), + "hi Reverse substitute {{varB}} and {{varA}} (default)", + ); assert.equal(localization.getLocalizedKeys("%{Test:SecondSubstitution.Test1}"), "Substitute {{varA}} and {{varB}} (test)"); assert.equal(localization.getLocalizedKeys("hi %{Test:SecondSubstitution.Test2}"), "hi Reverse substitute {{varB}} and {{varA}} (test)"); }); @@ -238,7 +237,6 @@ describe("ITwinLocalization", () => { }); describe("Nonexisting Namespace", () => { - it("first level fails", () => { assert.equal(localization.getLocalizedKeys("%{Nonexisting:FirstTrivial}"), "FirstTrivial"); assert.equal(localization.getLocalizedKeys("%{Nonexisting:MissingKeyString}"), "MissingKeyString"); @@ -256,7 +254,6 @@ describe("ITwinLocalization", () => { // basics work through the ITwinLocalization class. // For interpolation options, see: https://www.i18next.com/translation-function/interpolation describe("#getLocalizedString", () => { - before(async () => { localization = new ITwinLocalization(); await localization.initialize(["Default", "Test"]); @@ -266,7 +263,6 @@ describe("ITwinLocalization", () => { }); describe("Default Namespace", () => { - it("first level with no substitution", () => { assert.equal(localization.getLocalizedString("FirstTrivial"), "First level string (default)"); }); @@ -296,23 +292,41 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(localization.getLocalizedString("FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(localization.getLocalizedString("FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(localization.getLocalizedString("FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getLocalizedString("FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); }); it("first level with substitution with fallback keys", () => { assert.equal(localization.getLocalizedString(["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(localization.getLocalizedString(["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(localization.getLocalizedString(["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getLocalizedString(["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); }); it("second level with substitution", () => { - assert.equal(localization.getLocalizedString("SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString("SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(localization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); + assert.equal( + localization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); }); it("first level missing key doesn't find a value", () => { @@ -334,7 +348,6 @@ describe("ITwinLocalization", () => { }); describe("Default Namespace (German)", () => { - it("first level with no substitution", () => { assert.equal(germanLocalization.getLocalizedString("FirstTrivial"), "First level string (default german)"); }); @@ -357,23 +370,47 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default german)"); assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default german)"); + assert.equal( + germanLocalization.getLocalizedString("FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default german)", + ); }); it("first level with substitution with fallback keys", () => { - assert.equal(germanLocalization.getLocalizedString(["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), "First level CUSTOM1 (default german)"); - assert.equal(germanLocalization.getLocalizedString(["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), "First level CUSTOM2 (default german)"); - assert.equal(germanLocalization.getLocalizedString(["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default german)"); + assert.equal( + germanLocalization.getLocalizedString(["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), + "First level CUSTOM1 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString(["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), + "First level CUSTOM2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString(["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default german)", + ); }); it("second level with substitution", () => { - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default german)"); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default german)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(germanLocalization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default german)"); - assert.equal(germanLocalization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default german)"); + assert.equal( + germanLocalization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default german)", + ); }); it("first level missing key doesn't find a value", () => { @@ -391,7 +428,6 @@ describe("ITwinLocalization", () => { }); describe("Given Namespace", () => { - it("first level with no substitution", () => { assert.equal(localization.getLocalizedString("Default:FirstTrivial"), "First level string (default)"); assert.equal(localization.getLocalizedString("Test:FirstTrivial"), "First level string (test)"); @@ -417,28 +453,61 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(localization.getLocalizedString("Default:FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(localization.getLocalizedString("Default:FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(localization.getLocalizedString("Default:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getLocalizedString("Default:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); assert.equal(localization.getLocalizedString("Test:FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (test)"); assert.equal(localization.getLocalizedString("Test:FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getLocalizedString("Test:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + localization.getLocalizedString("Test:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("first level with substitution with fallback keys", () => { - assert.equal(localization.getLocalizedString(["Test:NotExist", "Default:FirstSubstitution1"], { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); - assert.equal(localization.getLocalizedString(["Test:FirstSubstitution1", "Default:NotExist"], { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getLocalizedString(["Test:NotExist", "Default:FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getLocalizedString(["Test:NotExist", "Default:FirstSubstitution1"], { str: "CUSTOM1" }), + "First level CUSTOM1 (default)", + ); + assert.equal( + localization.getLocalizedString(["Test:FirstSubstitution1", "Default:NotExist"], { str: "CUSTOM2" }), + "First level CUSTOM2 (test)", + ); + assert.equal( + localization.getLocalizedString(["Test:NotExist", "Default:FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); }); it("second level with substitution", () => { - assert.equal(localization.getLocalizedString("Default:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString("Default:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); - assert.equal(localization.getLocalizedString("Test:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (test)"); - assert.equal(localization.getLocalizedString("Test:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getLocalizedString("Default:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString("Default:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); + assert.equal( + localization.getLocalizedString("Test:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (test)", + ); + assert.equal( + localization.getLocalizedString("Test:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(localization.getLocalizedString(["Test:NotExist", "Default:SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString(["Test:SecondSubstitution.Test2", "Default:NotExist"], { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getLocalizedString(["Test:NotExist", "Default:SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString(["Test:SecondSubstitution.Test2", "Default:NotExist"], { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("first level missing key doesn't find a value", () => { @@ -457,7 +526,6 @@ describe("ITwinLocalization", () => { }); describe("Given Namespace (German)", () => { - it("first level with no substitution", () => { assert.equal(germanLocalization.getLocalizedString("Default:FirstTrivial"), "First level string (default german)"); assert.equal(germanLocalization.getLocalizedString("Test:FirstTrivial"), "First level string (german)"); @@ -473,17 +541,35 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(germanLocalization.getLocalizedString("Default:FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default german)"); assert.equal(germanLocalization.getLocalizedString("Default:FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("Default:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default german)"); + assert.equal( + germanLocalization.getLocalizedString("Default:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default german)", + ); assert.equal(germanLocalization.getLocalizedString("Test:FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (german)"); assert.equal(germanLocalization.getLocalizedString("Test:FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (german)"); - assert.equal(germanLocalization.getLocalizedString("Test:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (german)"); + assert.equal( + germanLocalization.getLocalizedString("Test:FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (german)", + ); }); it("second level with substitution", () => { - assert.equal(germanLocalization.getLocalizedString("Default:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("Default:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default german)"); - assert.equal(germanLocalization.getLocalizedString("Test:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (german)"); - assert.equal(germanLocalization.getLocalizedString("Test:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (german)"); + assert.equal( + germanLocalization.getLocalizedString("Default:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("Default:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("Test:SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (german)", + ); + assert.equal( + germanLocalization.getLocalizedString("Test:SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (german)", + ); }); it("first level missing key doesn't find a value", () => { @@ -498,7 +584,6 @@ describe("ITwinLocalization", () => { }); describe("Nonexisting Namespace", () => { - it("first level fails", () => { assert.equal(localization.getLocalizedString("Nonexisting:FirstTrivial"), "FirstTrivial"); assert.equal(localization.getLocalizedString("Nonexisting:MissingKeyString"), "MissingKeyString"); @@ -517,7 +602,6 @@ describe("ITwinLocalization", () => { // Test a few options to make sure they get passed through correctly describe("With Options", () => { - it("returnDetails throws error", () => { assert.throws(() => { localization.getLocalizedString("X", { returnDetails: true }); @@ -553,7 +637,6 @@ describe("ITwinLocalization", () => { }); describe("#getLocalizedString with namespace passed in as an option", () => { - before(async () => { localization = new ITwinLocalization(); await localization.initialize(["Default", "Test"]); @@ -563,7 +646,6 @@ describe("ITwinLocalization", () => { }); describe("Keys Without Namespaces", () => { - it("first level with no substitution", () => { assert.equal(localization.getLocalizedString("FirstTrivial", { ns: "Default" }), "First level string (default)"); assert.equal(localization.getLocalizedString("FirstTrivial", { ns: "Test" }), "First level string (test)"); @@ -589,28 +671,61 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(localization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(localization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(localization.getLocalizedString("FirstSubstitution2", { ns: "Default", str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getLocalizedString("FirstSubstitution2", { ns: "Default", str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); assert.equal(localization.getLocalizedString("FirstSubstitution1", { ns: "Test", str: "CUSTOM1" }), "First level CUSTOM1 (test)"); assert.equal(localization.getLocalizedString("FirstSubstitution1", { ns: "Test", str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getLocalizedString("FirstSubstitution2", { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + localization.getLocalizedString("FirstSubstitution2", { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("first level with substitution with fallback keys", () => { - assert.equal(localization.getLocalizedString(["NotExist", "FirstSubstitution1"], { ns: "Default", str: "CUSTOM1" }), "First level CUSTOM1 (default)"); - assert.equal(localization.getLocalizedString(["FirstSubstitution1", "NotExist"], { ns: "Test", str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getLocalizedString(["NotExist", "FirstSubstitution2"], { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + localization.getLocalizedString(["NotExist", "FirstSubstitution1"], { ns: "Default", str: "CUSTOM1" }), + "First level CUSTOM1 (default)", + ); + assert.equal( + localization.getLocalizedString(["FirstSubstitution1", "NotExist"], { ns: "Test", str: "CUSTOM2" }), + "First level CUSTOM2 (test)", + ); + assert.equal( + localization.getLocalizedString(["NotExist", "FirstSubstitution2"], { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("second level with substitution", () => { - assert.equal(localization.getLocalizedString("SecondSubstitution.Test1", { ns: "Default", varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString("SecondSubstitution.Test2", { ns: "Default", varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); - assert.equal(localization.getLocalizedString("SecondSubstitution.Test1", { ns: "Test", varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (test)"); - assert.equal(localization.getLocalizedString("SecondSubstitution.Test2", { ns: "Test", varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test1", { ns: "Default", varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test2", { ns: "Default", varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test1", { ns: "Test", varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (test)", + ); + assert.equal( + localization.getLocalizedString("SecondSubstitution.Test2", { ns: "Test", varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(localization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { ns: "Default", varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { ns: "Test", varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getLocalizedString(["NotExist", "SecondSubstitution.Test1"], { ns: "Default", varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getLocalizedString(["SecondSubstitution.Test2", "NotExist"], { ns: "Test", varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("first level missing key doesn't find a value", () => { @@ -625,7 +740,6 @@ describe("ITwinLocalization", () => { }); describe("Keys Without Namespaces (German)", () => { - it("first level with no substitution", () => { assert.equal(germanLocalization.getLocalizedString("FirstTrivial", { ns: "Default" }), "First level string (default german)"); assert.equal(germanLocalization.getLocalizedString("FirstTrivial", { ns: "Test" }), "First level string (german)"); @@ -639,19 +753,43 @@ describe("ITwinLocalization", () => { }); it("first level with substitution", () => { - assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM1" }), "First level CUSTOM1 (default german)"); - assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM2" }), "First level CUSTOM2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("FirstSubstitution2", { ns: "Default", str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default german)"); + assert.equal( + germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM1" }), + "First level CUSTOM1 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Default", str: "CUSTOM2" }), + "First level CUSTOM2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("FirstSubstitution2", { ns: "Default", str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default german)", + ); assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Test", str: "CUSTOM1" }), "First level CUSTOM1 (german)"); assert.equal(germanLocalization.getLocalizedString("FirstSubstitution1", { ns: "Test", str: "CUSTOM2" }), "First level CUSTOM2 (german)"); - assert.equal(germanLocalization.getLocalizedString("FirstSubstitution2", { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (german)"); + assert.equal( + germanLocalization.getLocalizedString("FirstSubstitution2", { ns: "Test", str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (german)", + ); }); it("second level with substitution", () => { - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test1", { ns: "Default", varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default german)"); - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test2", { ns: "Default", varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default german)"); - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test1", { ns: "Test", varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (german)"); - assert.equal(germanLocalization.getLocalizedString("SecondSubstitution.Test2", { ns: "Test", varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (german)"); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test1", { ns: "Default", varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test2", { ns: "Default", varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default german)", + ); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test1", { ns: "Test", varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (german)", + ); + assert.equal( + germanLocalization.getLocalizedString("SecondSubstitution.Test2", { ns: "Test", varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (german)", + ); }); it("first level missing key doesn't find a value", () => { @@ -666,7 +804,6 @@ describe("ITwinLocalization", () => { }); describe("Keys With Namespaces", () => { - it("key with same namespace works", () => { assert.equal(localization.getLocalizedString("Default:FirstTrivial", { ns: "Default" }), "First level string (default)"); assert.equal(localization.getLocalizedString("Test:SecondTrivial.Test1", { ns: "Test" }), "Second level string 1 (test)"); @@ -678,23 +815,31 @@ describe("ITwinLocalization", () => { }); it("key with same namespace works with fallback keys", () => { - assert.equal(localization.getLocalizedString(["NotExist:FirstTrivial", "Default:FirstTrivial"], { ns: "Default" }), "First level string (default)"); + assert.equal( + localization.getLocalizedString(["NotExist:FirstTrivial", "Default:FirstTrivial"], { ns: "Default" }), + "First level string (default)", + ); assert.equal(localization.getLocalizedString(["NotExist:FirstTrivial", "Test:FirstTrivial"], { ns: "Test" }), "First level string (test)"); }); it("key with different namespace overrides given namespace with fallback keys", () => { assert.equal(localization.getLocalizedString(["NotExist:FirstTrivial", "Test:FirstTrivial"], { ns: "Default" }), "First level string (test)"); - assert.equal(localization.getLocalizedString(["NotExist:FirstTrivial", "Default:FirstTrivial"], { ns: "Test" }), "First level string (default)"); + assert.equal( + localization.getLocalizedString(["NotExist:FirstTrivial", "Default:FirstTrivial"], { ns: "Test" }), + "First level string (default)", + ); }); it("missing key does not find a value", () => { assert.equal(germanLocalization.getLocalizedString("Default:MissingKeyString", { ns: "Default" }), "MissingKeyString"); - assert.equal(germanLocalization.getLocalizedString(["Missing1", "MissingKeyObject.MissingString"], { ns: "Test" }), "MissingKeyObject.MissingString"); + assert.equal( + germanLocalization.getLocalizedString(["Missing1", "MissingKeyObject.MissingString"], { ns: "Test" }), + "MissingKeyObject.MissingString", + ); }); }); describe("Nonexisting Namespace", () => { - it("first level fails", () => { assert.equal(localization.getLocalizedString("FirstTrivial", { ns: "Nonexisting" }), "FirstTrivial"); assert.equal(localization.getLocalizedString("MissingKeyString", { ns: "Nonexisting" }), "MissingKeyString"); @@ -727,7 +872,6 @@ describe("ITwinLocalization", () => { // Test a few options to make sure they get passed through correctly describe("With Options", () => { - it("returnDetails throws error", () => { assert.throws(() => { localization.getLocalizedString("X", { ns: "Default", returnDetails: true }); @@ -758,7 +902,6 @@ describe("ITwinLocalization", () => { }); describe("#getEnglishString", () => { - before(async () => { localization = new ITwinLocalization(); await localization.initialize(["Default", "Test"]); @@ -768,7 +911,6 @@ describe("ITwinLocalization", () => { }); describe("Given Namespace", () => { - it("first level with no substitution", () => { assert.equal(localization.getEnglishString("Default", "FirstTrivial"), "First level string (default)"); assert.equal(localization.getEnglishString("Test", "FirstTrivial"), "First level string (test)"); @@ -794,28 +936,58 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(localization.getEnglishString("Default", "FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(localization.getEnglishString("Default", "FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(localization.getEnglishString("Default", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + localization.getEnglishString("Default", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); assert.equal(localization.getEnglishString("Test", "FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (test)"); assert.equal(localization.getEnglishString("Test", "FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getEnglishString("Test", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + localization.getEnglishString("Test", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("first level with substitution with fallback keys", () => { - assert.equal(localization.getEnglishString("Default", ["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); + assert.equal( + localization.getEnglishString("Default", ["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), + "First level CUSTOM1 (default)", + ); assert.equal(localization.getEnglishString("Test", ["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(localization.getEnglishString("Test", ["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + localization.getEnglishString("Test", ["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("second level with substitution", () => { - assert.equal(localization.getEnglishString("Default", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getEnglishString("Default", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); - assert.equal(localization.getEnglishString("Test", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (test)"); - assert.equal(localization.getEnglishString("Test", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getEnglishString("Default", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getEnglishString("Default", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); + assert.equal( + localization.getEnglishString("Test", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (test)", + ); + assert.equal( + localization.getEnglishString("Test", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(localization.getEnglishString("Default", ["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(localization.getEnglishString("Test", ["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + localization.getEnglishString("Default", ["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + localization.getEnglishString("Test", ["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("first level missing key doesn't find a value", () => { @@ -830,7 +1002,6 @@ describe("ITwinLocalization", () => { }); describe("Given Namespace with German default language returns English strings", () => { - it("first level with no substitution", () => { assert.equal(germanLocalization.getEnglishString("Default", "FirstTrivial"), "First level string (default)"); assert.equal(germanLocalization.getEnglishString("Test", "FirstTrivial"), "First level string (test)"); @@ -856,28 +1027,61 @@ describe("ITwinLocalization", () => { it("first level with substitution", () => { assert.equal(germanLocalization.getEnglishString("Default", "FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); assert.equal(germanLocalization.getEnglishString("Default", "FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (default)"); - assert.equal(germanLocalization.getEnglishString("Default", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (default)"); + assert.equal( + germanLocalization.getEnglishString("Default", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (default)", + ); assert.equal(germanLocalization.getEnglishString("Test", "FirstSubstitution1", { str: "CUSTOM1" }), "First level CUSTOM1 (test)"); assert.equal(germanLocalization.getEnglishString("Test", "FirstSubstitution1", { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(germanLocalization.getEnglishString("Test", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + germanLocalization.getEnglishString("Test", "FirstSubstitution2", { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("first level with substitution with fallback keys", () => { - assert.equal(germanLocalization.getEnglishString("Default", ["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), "First level CUSTOM1 (default)"); - assert.equal(germanLocalization.getEnglishString("Test", ["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), "First level CUSTOM2 (test)"); - assert.equal(germanLocalization.getEnglishString("Test", ["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), "First level CUSTOM1 and CUSTOM2 (test)"); + assert.equal( + germanLocalization.getEnglishString("Default", ["NotExist", "FirstSubstitution1"], { str: "CUSTOM1" }), + "First level CUSTOM1 (default)", + ); + assert.equal( + germanLocalization.getEnglishString("Test", ["FirstSubstitution1", "NotExist"], { str: "CUSTOM2" }), + "First level CUSTOM2 (test)", + ); + assert.equal( + germanLocalization.getEnglishString("Test", ["NotExist", "FirstSubstitution2"], { str1: "CUSTOM1", str2: "CUSTOM2" }), + "First level CUSTOM1 and CUSTOM2 (test)", + ); }); it("second level with substitution", () => { - assert.equal(germanLocalization.getEnglishString("Default", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(germanLocalization.getEnglishString("Default", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (default)"); - assert.equal(germanLocalization.getEnglishString("Test", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (test)"); - assert.equal(germanLocalization.getEnglishString("Test", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + germanLocalization.getEnglishString("Default", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + germanLocalization.getEnglishString("Default", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (default)", + ); + assert.equal( + germanLocalization.getEnglishString("Test", "SecondSubstitution.Test1", { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (test)", + ); + assert.equal( + germanLocalization.getEnglishString("Test", "SecondSubstitution.Test2", { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("second level with substitution with fallback keys", () => { - assert.equal(germanLocalization.getEnglishString("Default", ["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), "Substitute Variable1 and Variable2 (default)"); - assert.equal(germanLocalization.getEnglishString("Test", ["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), "Reverse substitute Variable2 and Variable1 (test)"); + assert.equal( + germanLocalization.getEnglishString("Default", ["NotExist", "SecondSubstitution.Test1"], { varA: "Variable1", varB: "Variable2" }), + "Substitute Variable1 and Variable2 (default)", + ); + assert.equal( + germanLocalization.getEnglishString("Test", ["SecondSubstitution.Test2", "NotExist"], { varA: "Variable1", varB: "Variable2" }), + "Reverse substitute Variable2 and Variable1 (test)", + ); }); it("first level missing key doesn't find a value", () => { @@ -892,7 +1096,6 @@ describe("ITwinLocalization", () => { }); describe("Nonexisting Namespace", () => { - it("first level fails", () => { assert.equal(localization.getEnglishString("Nonexisting", "FirstTrivial"), "FirstTrivial"); assert.equal(localization.getEnglishString("Nonexisting", "MissingKeyString"), "MissingKeyString"); @@ -911,7 +1114,6 @@ describe("ITwinLocalization", () => { // Test a few options to make sure they get passed through correctly describe("With Options", () => { - it("returnDetails throws error", () => { assert.throws(() => { localization.getEnglishString("Default", "X", { returnDetails: true }); @@ -944,7 +1146,6 @@ describe("ITwinLocalization", () => { assert.equal(localization.getEnglishString("Default", "FirstSubstitution1", { str: "CUSTOM1", ns: "Test" }), "First level CUSTOM1 (default)"); }); }); - }); // Returned promises never have anything of substance, being only empty or resolving to null... @@ -974,7 +1175,6 @@ describe("ITwinLocalization", () => { }); describe("#changeLanguage", () => { - it("change from english to another language", async () => { localization = new ITwinLocalization(); await localization.initialize(["Default"]); @@ -1092,5 +1292,4 @@ describe("ITwinLocalization", () => { // unregisterNamespace() isn't used and basically does nothing // describe("#unregisterNamespace", () => { // }); - }); diff --git a/core/i18n/src/test/public/locales/de/Default.json b/core/i18n/src/test/public/locales/de/Default.json index 1de7ff7636ca..889c7a612c55 100644 --- a/core/i18n/src/test/public/locales/de/Default.json +++ b/core/i18n/src/test/public/locales/de/Default.json @@ -14,4 +14,4 @@ "ObjectKey1": "ObjectValue1 (default german)" }, "OnlyGerman": "Hallo" -} \ No newline at end of file +} diff --git a/core/i18n/src/test/public/locales/de/Test.json b/core/i18n/src/test/public/locales/de/Test.json index 74a763c53228..215f99a9508f 100644 --- a/core/i18n/src/test/public/locales/de/Test.json +++ b/core/i18n/src/test/public/locales/de/Test.json @@ -13,4 +13,4 @@ "MyObject": { "ObjectKey1": "ObjectValue1 (german)" } -} \ No newline at end of file +} diff --git a/core/i18n/src/test/public/locales/en-US/Default.json b/core/i18n/src/test/public/locales/en-US/Default.json index 27d3d0b2c77a..46c59f09fd35 100644 --- a/core/i18n/src/test/public/locales/en-US/Default.json +++ b/core/i18n/src/test/public/locales/en-US/Default.json @@ -11,4 +11,4 @@ "Test2": "Reverse substitute {{varB}} and {{varA}} (default)" }, "OnlyEnglishUS": "HelloUS" -} \ No newline at end of file +} diff --git a/core/i18n/src/test/public/locales/en-US/Test.json b/core/i18n/src/test/public/locales/en-US/Test.json index 13f7b11f9c38..d82cda27f7ac 100644 --- a/core/i18n/src/test/public/locales/en-US/Test.json +++ b/core/i18n/src/test/public/locales/en-US/Test.json @@ -13,4 +13,4 @@ "MyObject": { "ObjectKey1": "ObjectValue1" } -} \ No newline at end of file +} diff --git a/core/i18n/src/test/public/locales/en/Default.json b/core/i18n/src/test/public/locales/en/Default.json index 6796e1548f0b..baa7e2ca9254 100644 --- a/core/i18n/src/test/public/locales/en/Default.json +++ b/core/i18n/src/test/public/locales/en/Default.json @@ -11,4 +11,4 @@ "Test2": "Reverse substitute {{varB}} and {{varA}} (default)" }, "OnlyEnglish": "Hello" -} \ No newline at end of file +} diff --git a/core/i18n/src/test/public/locales/en/Test.json b/core/i18n/src/test/public/locales/en/Test.json index 13f7b11f9c38..d82cda27f7ac 100644 --- a/core/i18n/src/test/public/locales/en/Test.json +++ b/core/i18n/src/test/public/locales/en/Test.json @@ -13,4 +13,4 @@ "MyObject": { "ObjectKey1": "ObjectValue1" } -} \ No newline at end of file +} diff --git a/core/i18n/src/test/utils/webpack.config.js b/core/i18n/src/test/utils/webpack.config.js index 9ccdbbdc49df..3f3bf581909b 100644 --- a/core/i18n/src/test/utils/webpack.config.js +++ b/core/i18n/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -57,8 +57,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -83,5 +83,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/core/i18n/tsconfig.json b/core/i18n/tsconfig.json index f1d5a8182214..57c9a3e8c401 100644 --- a/core/i18n/tsconfig.json +++ b/core/i18n/tsconfig.json @@ -6,4 +6,4 @@ "include": [ "./src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/core/markup/certa.json b/core/markup/certa.json index e7bf1bc5cb94..97e7affd5035 100644 --- a/core/markup/certa.json +++ b/core/markup/certa.json @@ -15,11 +15,11 @@ }, "chromeOptions": { "publicDirs": [ - "src/public", + "src/public" ], "args": [ "--disable-web-security", "--no-sandbox" ] } -} \ No newline at end of file +} diff --git a/core/markup/eslint.config.js b/core/markup/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/markup/eslint.config.js +++ b/core/markup/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/markup/src/Markup.ts b/core/markup/src/Markup.ts index 2227e6d99203..a7c82d05b58b 100644 --- a/core/markup/src/Markup.ts +++ b/core/markup/src/Markup.ts @@ -7,10 +7,10 @@ */ import { BentleyError, Logger } from "@itwin/core-bentley"; -import { Point3d, XAndY } from "@itwin/core-geometry"; import { ImageSource, ImageSourceFormat } from "@itwin/core-common"; import { FrontendLoggerCategory, imageElementFromImageSource, IModelApp, ScreenViewport } from "@itwin/core-frontend"; -import { adopt, create, G, Marker, Element as MarkupElement, Matrix, Point, Svg, SVG } from "@svgdotjs/svg.js"; +import { Point3d, XAndY } from "@itwin/core-geometry"; +import { adopt, create, Element as MarkupElement, G, Marker, Matrix, Point, SVG, Svg } from "@svgdotjs/svg.js"; import * as redlineTool from "./RedlineTool"; import { MarkupSelected, SelectTool } from "./SelectTool"; import * as textTool from "./TextEdit"; @@ -118,7 +118,8 @@ export class MarkupApp { width: 6, }, cloud: { - path: "M3.0,2.5 C3.9,.78 5.6,-.4 8.1,1.0 C9.1,0 11.3,-.2 12.5,.5 C14.2,-.5 17,.16 17.9,2.5 C21,3 20.2,7.3 17.6,7.5 C16.5,9.2 14.4,9.8 12.7,8.9 C11.6,10 9.5,10.3 8.1,9.4 C5.7,10.8 3.3,9.4 2.6,7.5 C-.9,7.7 .6,1.7 3.0,2.5z", + path: + "M3.0,2.5 C3.9,.78 5.6,-.4 8.1,1.0 C9.1,0 11.3,-.2 12.5,.5 C14.2,-.5 17,.16 17.9,2.5 C21,3 20.2,7.3 17.6,7.5 C16.5,9.2 14.4,9.8 12.7,8.9 C11.6,10 9.5,10.3 8.1,9.4 C5.7,10.8 3.3,9.4 2.6,7.5 C-.9,7.7 .6,1.7 3.0,2.5z", }, }, /** Values for placing and editing Text. */ @@ -175,7 +176,9 @@ export class MarkupApp { } /** @internal */ - public static getVpToVbMtx(): Matrix { return this.getVpToScreenMtx().lmultiplyO(this.screenToVbMtx()); } + public static getVpToVbMtx(): Matrix { + return this.getVpToScreenMtx().lmultiplyO(this.screenToVbMtx()); + } /** @internal */ public static convertVpToVb(pt: XAndY): Point3d { const pt0 = new Point(pt.x, pt.y); @@ -184,10 +187,14 @@ export class MarkupApp { } /** determine whether there's a markup session currently active */ - public static get isActive() { return undefined !== this.markup; } + public static get isActive() { + return undefined !== this.markup; + } public static markupSelectToolId = "Markup.Select"; - protected static createMarkup(view: ScreenViewport, markupData?: MarkupSvgData) { return new Markup(view, markupData); } + protected static createMarkup(view: ScreenViewport, markupData?: MarkupSvgData) { + return new Markup(view, markupData); + } protected static lockViewportSize(view: ScreenViewport, markupData?: MarkupSvgData) { const parentDiv = view.vpDiv; @@ -207,7 +214,9 @@ export class MarkupApp { } /** @internal */ - public static getActionName(action: string) { return IModelApp.localization.getLocalizedString(`${this.namespace}:actions.${action}`); } + public static getActionName(action: string) { + return IModelApp.localization.getLocalizedString(`${this.namespace}:actions.${action}`); + } /** Start a markup session */ public static async start(view: ScreenViewport, markupData?: MarkupSvgData): Promise { @@ -268,7 +277,7 @@ export class MarkupApp { * calls return the same Promise. */ public static async initialize(): Promise { - if (undefined === this.namespace) { // only need to do this once + if (undefined === this.namespace) { // only need to do this once this.namespace = "MarkupTools"; const namespacePromise = IModelApp.localization.registerNamespace(this.namespace); IModelApp.tools.register(SelectTool, this.namespace); @@ -313,7 +322,7 @@ export class MarkupApp { let svg, image; try { svg = this.readMarkupSvg(); // read the current svg data for the markup - const svgForImage = (svg && result.imprintSvgOnImage ? this.readMarkupSvgForDrawImage() : undefined); + const svgForImage = svg && result.imprintSvgOnImage ? this.readMarkupSvgForDrawImage() : undefined; if (svgForImage) { const svgImage = await imageElementFromImageSource(new ImageSource(svgForImage, ImageSourceFormat.Svg)); canvas.getContext("2d")!.drawImage(svgImage, 0, 0); // draw markup svg onto view's canvas2d @@ -330,7 +339,7 @@ export class MarkupApp { } // return the markup data to be saved by the application. - image = (!result.imageFormat ? undefined : canvas.toDataURL(result.imageFormat)); + image = !result.imageFormat ? undefined : canvas.toDataURL(result.imageFormat); } catch (e) { Logger.logError(`${FrontendLoggerCategory.Package}.markup`, "Error creating image from svg", BentleyError.getErrorProps(e)); } @@ -340,35 +349,65 @@ export class MarkupApp { /** @internal */ public static markupPrefix = "markup-"; /** @internal */ - public static get dropShadowId() { return `${this.markupPrefix}dropShadow`; } // this is referenced in the markup Svg to apply the drop-shadow filter to all markup elements. + public static get dropShadowId() { + return `${this.markupPrefix}dropShadow`; + } // this is referenced in the markup Svg to apply the drop-shadow filter to all markup elements. /** @internal */ - public static get cornerId() { return `${this.markupPrefix}photoCorner`; } + public static get cornerId() { + return `${this.markupPrefix}photoCorner`; + } /** @internal */ - public static get containerClass() { return `${this.markupPrefix}container`; } + public static get containerClass() { + return `${this.markupPrefix}container`; + } /** @internal */ - public static get dynamicsClass() { return `${this.markupPrefix}dynamics`; } + public static get dynamicsClass() { + return `${this.markupPrefix}dynamics`; + } /** @internal */ - public static get decorationsClass() { return `${this.markupPrefix}decorations`; } + public static get decorationsClass() { + return `${this.markupPrefix}decorations`; + } /** @internal */ - public static get markupSvgClass() { return `${this.markupPrefix}svg`; } + public static get markupSvgClass() { + return `${this.markupPrefix}svg`; + } /** @internal */ - public static get boxedTextClass() { return `${this.markupPrefix}boxedText`; } + public static get boxedTextClass() { + return `${this.markupPrefix}boxedText`; + } /** @internal */ - public static get textClass() { return `${this.markupPrefix}text`; } + public static get textClass() { + return `${this.markupPrefix}text`; + } /** @internal */ - public static get stretchHandleClass() { return `${this.markupPrefix}stretchHandle`; } + public static get stretchHandleClass() { + return `${this.markupPrefix}stretchHandle`; + } /** @internal */ - public static get rotateLineClass() { return `${this.markupPrefix}rotateLine`; } + public static get rotateLineClass() { + return `${this.markupPrefix}rotateLine`; + } /** @internal */ - public static get rotateHandleClass() { return `${this.markupPrefix}rotateHandle`; } + public static get rotateHandleClass() { + return `${this.markupPrefix}rotateHandle`; + } /** @internal */ - public static get vertexHandleClass() { return `${this.markupPrefix}vertexHandle`; } + public static get vertexHandleClass() { + return `${this.markupPrefix}vertexHandle`; + } /** @internal */ - public static get moveHandleClass() { return `${this.markupPrefix}moveHandle`; } + public static get moveHandleClass() { + return `${this.markupPrefix}moveHandle`; + } /** @internal */ - public static get textOutlineClass() { return `${this.markupPrefix}textOutline`; } + public static get textOutlineClass() { + return `${this.markupPrefix}textOutline`; + } /** @internal */ - public static get textEditorClass() { return `${this.markupPrefix}textEditor`; } + public static get textEditorClass() { + return `${this.markupPrefix}textEditor`; + } } const removeSvgNamespace = (svg: Svg) => { @@ -407,15 +446,32 @@ export class Markup { // create a new filter, and add it to the Defs of the supplied svg svg.defs() - .add(newSvgElement("filter").id(MarkupApp.dropShadowId) - .add(newSvgElement("feDropShadow").attr(MarkupApp.props.dropShadow.attr))); + .add( + newSvgElement("filter").id(MarkupApp.dropShadowId) + .add(newSvgElement("feDropShadow").attr(MarkupApp.props.dropShadow.attr)), + ); + } + private addNested(className: string): G { + return this.svgContainer!.group().addClass(className); } - private addNested(className: string): G { return this.svgContainer!.group().addClass(className); } private addBorder() { const rect = this.svgContainer!.viewbox(); const inset = MarkupApp.props.borderOutline["stroke-width"]; const cornerSize = inset * 6; - const cornerPts = [0, 0, cornerSize, 0, cornerSize * .7, cornerSize * .3, cornerSize * .3, cornerSize * .3, cornerSize * .3, cornerSize * .7, 0, cornerSize]; + const cornerPts = [ + 0, + 0, + cornerSize, + 0, + cornerSize * .7, + cornerSize * .3, + cornerSize * .3, + cornerSize * .3, + cornerSize * .3, + cornerSize * .7, + 0, + cornerSize, + ]; const decorations = this.svgDecorations!; const photoCorner = decorations.symbol().polygon(cornerPts).attr(MarkupApp.props.borderCorners).id(MarkupApp.cornerId); const cornerGroup = decorations.group(); @@ -442,7 +498,7 @@ export class Markup { if (!this.svgContainer || !this.svgMarkup) // if either isn't present, its not a valid markup return; removeSvgNamespace(this.svgContainer); // the SVG call above adds this - remove it - this.svgMarkup.each(() => { }, true); // create an SVG.Element for each entry in the supplied markup. + this.svgMarkup.each(() => {}, true); // create an SVG.Element for each entry in the supplied markup. } else { // create the container that will be returned as the "svg" data for this markup this.svgContainer = SVG().addTo(this.markupDiv).addClass(MarkupApp.containerClass).viewbox(0, 0, rect.width, rect.height); @@ -463,19 +519,33 @@ export class Markup { } /** Called when the Markup is destroyed */ - public destroy() { this.markupDiv.remove(); } + public destroy() { + this.markupDiv.remove(); + } /** Turn on picking the markup elements in the markup view */ - public enablePick() { this.markupDiv.style.pointerEvents = "auto"; } + public enablePick() { + this.markupDiv.style.pointerEvents = "auto"; + } /** Turn off picking the markup elements in the markup view */ - public disablePick() { this.markupDiv.style.pointerEvents = "none"; } + public disablePick() { + this.markupDiv.style.pointerEvents = "none"; + } /** Change the default cursor for the markup view */ - public setCursor(cursor: string) { this.markupDiv.style.cursor = cursor; } + public setCursor(cursor: string) { + this.markupDiv.style.cursor = cursor; + } /** Delete all the entries in the selection set, then empty it. */ - public deleteSelected() { this.selected.deleteAll(this.undo); } + public deleteSelected() { + this.selected.deleteAll(this.undo); + } /** Bring all the entries in the selection set to the front. */ - public bringToFront() { this.selected.reposition(MarkupApp.getActionName("toFront"), this.undo, (el) => el.front()); } + public bringToFront() { + this.selected.reposition(MarkupApp.getActionName("toFront"), this.undo, (el) => el.front()); + } /** Send all the entries in the selection set to the back. */ - public sendToBack() { this.selected.reposition(MarkupApp.getActionName("toBack"), this.undo, (el) => el.back()); } + public sendToBack() { + this.selected.reposition(MarkupApp.getActionName("toBack"), this.undo, (el) => el.back()); + } /** Group all the entries in the selection set, then select the group. */ public groupSelected() { if (undefined !== this.svgMarkup) diff --git a/core/markup/src/MarkupTool.ts b/core/markup/src/MarkupTool.ts index c2366657f0da..90bb65dc03e0 100644 --- a/core/markup/src/MarkupTool.ts +++ b/core/markup/src/MarkupTool.ts @@ -6,9 +6,9 @@ * @module MarkupTools */ -import { XAndY } from "@itwin/core-geometry"; import { BeButton, BeTouchEvent, CoordinateLockOverrides, EventHandled, IModelApp, PrimitiveTool, Viewport } from "@itwin/core-frontend"; -import { G, LinkedHTMLElement, Element as MarkupElement, Text as MarkupText } from "@svgdotjs/svg.js"; +import { XAndY } from "@itwin/core-geometry"; +import { Element as MarkupElement, G, LinkedHTMLElement, Text as MarkupText } from "@svgdotjs/svg.js"; import { Markup, MarkupApp } from "./Markup"; /** Base class for all tools that operate on Markup elements. @@ -17,8 +17,12 @@ import { Markup, MarkupApp } from "./Markup"; export abstract class MarkupTool extends PrimitiveTool { public markup!: Markup; public static toolKey = "MarkupTools:tools.Markup."; - public override requireWriteableTarget(): boolean { return false; } - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp === IModelApp.toolAdmin.markupView); } + public override requireWriteableTarget(): boolean { + return false; + } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp === IModelApp.toolAdmin.markupView); + } public override async onInstall(): Promise { if (undefined === MarkupApp.markup) return false; @@ -31,15 +35,21 @@ export abstract class MarkupTool extends PrimitiveTool { await super.onPostInstall(); this.setupAndPromptForNextAction(); } - public override async onUnsuspend() { this.showPrompt(); } - public async onRestartTool() { return this.exitTool(); } + public override async onUnsuspend() { + this.showPrompt(); + } + public async onRestartTool() { + return this.exitTool(); + } - protected showPrompt(): void { } + protected showPrompt(): void {} protected setupAndPromptForNextAction(): void { IModelApp.toolAdmin.toolState.coordLockOvr = CoordinateLockOverrides.All; // Don't adjust point to ACS or grid... this.showPrompt(); } - protected outputMarkupPrompt(msg: string) { IModelApp.notifications.outputPromptByKey(MarkupTool.toolKey + msg); } + protected outputMarkupPrompt(msg: string) { + IModelApp.notifications.outputPromptByKey(MarkupTool.toolKey + msg); + } public override async onTouchMoveStart(ev: BeTouchEvent, startEv: BeTouchEvent): Promise { if (startEv.isSingleTouch) @@ -47,9 +57,15 @@ export abstract class MarkupTool extends PrimitiveTool { return EventHandled.Yes; // View tools are not allowed during redlining; use touch events to create markup and don't pass event to IdleTool... } - public override async onTouchMove(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchMoveToMotion(ev); } - public override async onTouchComplete(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev); } - public override async onTouchCancel(ev: BeTouchEvent): Promise { return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, BeButton.Reset); } + public override async onTouchMove(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchMoveToMotion(ev); + } + public override async onTouchComplete(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev); + } + public override async onTouchCancel(ev: BeTouchEvent): Promise { + return IModelApp.toolAdmin.convertTouchEndToButtonUp(ev, BeButton.Reset); + } public override async undoPreviousStep(): Promise { if (await this.onUndoPreviousStep()) // first see if this tool has an "oops" operation. @@ -84,7 +100,9 @@ export abstract class MarkupTool extends PrimitiveTool { element.css({ fill: "none" }); } - protected setCurrentTextStyle(element: MarkupElement): void { element.css(MarkupApp.props.active.text); } + protected setCurrentTextStyle(element: MarkupElement): void { + element.css(MarkupApp.props.active.text); + } /** @internal */ public createBoxedText(g: G, text: MarkupText) { @@ -96,5 +114,4 @@ export abstract class MarkupTool extends PrimitiveTool { text.addTo(boxedText); // make sure the text is on top return boxedText; } - } diff --git a/core/markup/src/RedlineTool.ts b/core/markup/src/RedlineTool.ts index 285254657481..bee7d256ecc7 100644 --- a/core/markup/src/RedlineTool.ts +++ b/core/markup/src/RedlineTool.ts @@ -8,12 +8,21 @@ // cspell:ignore rtmp stmp -import { Point3d, Vector3d } from "@itwin/core-geometry"; import { - BeButtonEvent, CoordinateLockOverrides, CoreTools, EventHandled, IModelApp, QuantityType, ToolAssistance, ToolAssistanceImage, - ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection, + BeButtonEvent, + CoordinateLockOverrides, + CoreTools, + EventHandled, + IModelApp, + QuantityType, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, + ToolAssistanceSection, } from "@itwin/core-frontend"; -import { G, Marker, Element as MarkupElement } from "@svgdotjs/svg.js"; +import { Point3d, Vector3d } from "@itwin/core-geometry"; +import { Element as MarkupElement, G, Marker } from "@svgdotjs/svg.js"; import { MarkupApp } from "./Markup"; import { MarkupTool } from "./MarkupTool"; @@ -31,18 +40,26 @@ export abstract class RedlineTool extends MarkupTool { undo.performOperation(this.keyin, () => undo.onAdded(el)); markup.selected.restart(el); } - protected isComplete(_ev: BeButtonEvent) { return this._points.length >= this._nRequiredPoints; } + protected isComplete(_ev: BeButtonEvent) { + return this._points.length >= this._nRequiredPoints; + } protected override setupAndPromptForNextAction(): void { super.setupAndPromptForNextAction(); this.markup.disablePick(); IModelApp.toolAdmin.setCursor(0 === this._points.length ? IModelApp.viewManager.crossHairCursor : IModelApp.viewManager.dynamicsCursor); } - protected createMarkup(_svgMarkup: G, _ev: BeButtonEvent, _isDynamics: boolean): void { } - protected clearDynamicsMarkup(_isDynamics: boolean): void { this.markup.svgDynamics!.clear(); } + protected createMarkup(_svgMarkup: G, _ev: BeButtonEvent, _isDynamics: boolean): void {} + protected clearDynamicsMarkup(_isDynamics: boolean): void { + this.markup.svgDynamics!.clear(); + } - public override async onRestartTool() { return this.exitTool(); } // Default to single shot and return control to select tool... - public override async onCleanup() { this.clearDynamicsMarkup(false); } + public override async onRestartTool() { + return this.exitTool(); + } // Default to single shot and return control to select tool... + public override async onCleanup() { + this.clearDynamicsMarkup(false); + } public override async onReinitialize() { this.clearDynamicsMarkup(false); @@ -88,7 +105,14 @@ export abstract class RedlineTool extends MarkupTool { const acceptMsg = CoreTools.translate("ElementSet.Inputs.AcceptPoint"); const rejectMsg = CoreTools.translate("ElementSet.Inputs.Exit"); if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(singlePoint ? ToolAssistanceImage.OneTouchTap : ToolAssistanceImage.OneTouchDrag, acceptMsg, false, ToolAssistanceInputMethod.Touch)); + touchInstructions.push( + ToolAssistance.createInstruction( + singlePoint ? ToolAssistanceImage.OneTouchTap : ToolAssistanceImage.OneTouchDrag, + acceptMsg, + false, + ToolAssistanceInputMethod.Touch, + ), + ); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse)); touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, rejectMsg, false, ToolAssistanceInputMethod.Touch)); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, rejectMsg, false, ToolAssistanceInputMethod.Mouse)); @@ -109,7 +133,9 @@ export class LineTool extends RedlineTool { public static override toolId = "Markup.Line"; public static override iconSpec = "icon-line"; - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -130,9 +156,15 @@ export class RectangleTool extends RedlineTool { public static override toolId = "Markup.Rectangle"; public static override iconSpec = "icon-rectangle"; - constructor(protected _cornerRadius?: number) { super(); } // Specify radius to create a rectangle with rounded corners. + constructor(protected _cornerRadius?: number) { + super(); + } // Specify radius to create a rectangle with rounded corners. - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); } + protected override showPrompt(): void { + this.provideToolAssistance( + CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner"), + ); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -161,9 +193,13 @@ export class PolygonTool extends RedlineTool { public static override toolId = "Markup.Polygon"; public static override iconSpec = "icon-polygon"; - constructor(protected _numSides?: number) { super(); } // Specify number of polygon sides. Default if undefined is 5. + constructor(protected _numSides?: number) { + super(); + } // Specify number of polygon sides. Default if undefined is 5. - protected override showPrompt(): void { this.provideToolAssistance(MarkupTool.toolKey + (0 === this._points.length ? "Polygon.Prompts.FirstPoint" : "Polygon.Prompts.NextPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(MarkupTool.toolKey + (0 === this._points.length ? "Polygon.Prompts.FirstPoint" : "Polygon.Prompts.NextPoint")); + } protected getPoints(points: number[], center: Point3d, edge: Point3d, numSides: number, inscribe: boolean): boolean { if (numSides < 3 || numSides > 100) @@ -216,7 +252,11 @@ export class CloudTool extends RedlineTool { public static override iconSpec = "icon-cloud"; protected _cloud?: MarkupElement; - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); } + protected override showPrompt(): void { + this.provideToolAssistance( + CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner"), + ); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -255,7 +295,9 @@ export class CircleTool extends RedlineTool { public static override toolId = "Markup.Circle"; public static override iconSpec = "icon-circle"; - protected override showPrompt(): void { this.provideToolAssistance(MarkupTool.toolKey + (0 === this._points.length ? "Circle.Prompts.FirstPoint" : "Circle.Prompts.NextPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(MarkupTool.toolKey + (0 === this._points.length ? "Circle.Prompts.FirstPoint" : "Circle.Prompts.NextPoint")); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -279,7 +321,11 @@ export class EllipseTool extends RedlineTool { public static override toolId = "Markup.Ellipse"; public static override iconSpec = "icon-ellipse"; - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner")); } + protected override showPrompt(): void { + this.provideToolAssistance( + CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartCorner" : "ElementSet.Prompts.OppositeCorner"), + ); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -309,9 +355,13 @@ export class ArrowTool extends RedlineTool { /** ctor for ArrowTool * @param _arrowPos "start", "end", or "both". If undefined = "end". */ - constructor(protected _arrowPos?: string) { super(); } + constructor(protected _arrowPos?: string) { + super(); + } - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); + } protected getOrCreateArrowMarker(color: string): Marker { const arrowProps = MarkupApp.props.active.arrow; @@ -329,8 +379,8 @@ export class ArrowTool extends RedlineTool { const element = svgMarkup.line(start.x, start.y, end.x, end.y); this.setCurrentStyle(element, false); const marker = this.getOrCreateArrowMarker(element.css("stroke")); - const addToStart = ("start" === this._arrowPos || "both" === this._arrowPos); - const addToEnd = ("end" === this._arrowPos || "both" === this._arrowPos); + const addToStart = "start" === this._arrowPos || "both" === this._arrowPos; + const addToEnd = "end" === this._arrowPos || "both" === this._arrowPos; if (addToStart) element.marker("start", marker); if (addToEnd || !addToStart) @@ -348,7 +398,9 @@ export class DistanceTool extends ArrowTool { public static override iconSpec = "icon-distance"; protected readonly _startPointWorld = new Point3d(); - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); + } protected override setupAndPromptForNextAction(): void { IModelApp.accuSnap.enableSnap(true); IModelApp.toolAdmin.toolState.coordLockOvr = CoordinateLockOverrides.None; @@ -417,7 +469,9 @@ export class SketchTool extends RedlineTool { public static override iconSpec = "icon-draw"; protected _minDistSquared = 100; - protected override showPrompt(): void { this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); } + protected override showPrompt(): void { + this.provideToolAssistance(CoreTools.tools + (0 === this._points.length ? "ElementSet.Prompts.StartPoint" : "ElementSet.Prompts.EndPoint")); + } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { if (this._points.length < (isDynamics ? this._nRequiredPoints - 1 : this._nRequiredPoints)) @@ -434,7 +488,8 @@ export class SketchTool extends RedlineTool { pts.push(evPt.y); } - const isClosed = (this._points.length > 2 && (this._points[0].distanceSquaredXY(isDynamics ? evPt : this._points[this._points.length - 1]) < this._minDistSquared * 2)); + const isClosed = this._points.length > 2 && + (this._points[0].distanceSquaredXY(isDynamics ? evPt : this._points[this._points.length - 1]) < this._minDistSquared * 2); const element = isClosed ? svgMarkup.polygon(pts) : svgMarkup.polyline(pts); this.setCurrentStyle(element, isClosed); if (!isDynamics) @@ -458,7 +513,9 @@ export class SymbolTool extends RedlineTool { public static override iconSpec = "icon-symbol"; protected _symbol?: MarkupElement; - constructor(protected _symbolData?: string, protected _applyCurrentStyle?: boolean) { super(); } + constructor(protected _symbolData?: string, protected _applyCurrentStyle?: boolean) { + super(); + } public override async onInstall(): Promise { if (undefined === this._symbolData) @@ -467,7 +524,10 @@ export class SymbolTool extends RedlineTool { } protected override showPrompt(): void { - this.provideToolAssistance(0 === this._points.length ? (`${MarkupTool.toolKey}Symbol.Prompts.FirstPoint`) : `${CoreTools.tools}ElementSet.Prompts.OppositeCorner`, true); + this.provideToolAssistance( + 0 === this._points.length ? (`${MarkupTool.toolKey}Symbol.Prompts.FirstPoint`) : `${CoreTools.tools}ElementSet.Prompts.OppositeCorner`, + true, + ); } protected override createMarkup(svgMarkup: G, ev: BeButtonEvent, isDynamics: boolean): void { @@ -490,7 +550,7 @@ export class SymbolTool extends RedlineTool { } try { symbol.flatten(symbol); - } catch { } + } catch {} this._symbol = symbol; } else if (!isDynamics) { @@ -508,7 +568,12 @@ export class SymbolTool extends RedlineTool { this._symbol.forElementsOfGroup((child) => { const css = window.getComputedStyle(child.node); const toValue = (val: string | null, newVal: string) => (!val || val === "none") ? "none" : newVal; - child.css({ "fill": toValue(css.fill, active.element.fill), "stroke": toValue(css.stroke, active.element.stroke), "fill-opacity": active.element["fill-opacity"], "stroke-opacity": active.element["stroke-opacity"] }); + child.css({ + "fill": toValue(css.fill, active.element.fill), + "stroke": toValue(css.stroke, active.element.stroke), + "fill-opacity": active.element["fill-opacity"], + "stroke-opacity": active.element["stroke-opacity"], + }); }); } if (!isDynamics) diff --git a/core/markup/src/SelectTool.ts b/core/markup/src/SelectTool.ts index 2eec136f78e1..f977eb4b7232 100644 --- a/core/markup/src/SelectTool.ts +++ b/core/markup/src/SelectTool.ts @@ -7,12 +7,23 @@ */ import { assert, BeEvent } from "@itwin/core-bentley"; -import { Point2d, Point3d, Transform, Vector2d, XAndY } from "@itwin/core-geometry"; import { - BeButton, BeButtonEvent, BeModifierKeys, BeTouchEvent, CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, - ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection, + BeButton, + BeButtonEvent, + BeModifierKeys, + BeTouchEvent, + CoreTools, + EventHandled, + IModelApp, + InputSource, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, + ToolAssistanceSection, } from "@itwin/core-frontend"; -import { ArrayXY, Box, Container, G, Line, Element as MarkupElement, Text as MarkupText, Matrix, Point, Polygon } from "@svgdotjs/svg.js"; +import { Point2d, Point3d, Transform, Vector2d, XAndY } from "@itwin/core-geometry"; +import { ArrayXY, Box, Container, Element as MarkupElement, G, Line, Matrix, Point, Polygon, Text as MarkupText } from "@svgdotjs/svg.js"; import { MarkupApp } from "./Markup"; import { MarkupTool } from "./MarkupTool"; import { EditTextTool } from "./TextEdit"; @@ -27,10 +38,10 @@ import { UndoManager } from "./Undo"; export abstract class ModifyHandle { public vbToStartTrn!: Transform; - constructor(public handles: Handles) { } + constructor(public handles: Handles) {} /** perform the modification given a current mouse position. */ public abstract modify(ev: BeButtonEvent): void; - public async onClick(_ev: BeButtonEvent): Promise { } + public async onClick(_ev: BeButtonEvent): Promise {} /** set the position for this handle on the screen given the current state of the element */ public abstract setPosition(): void; @@ -117,20 +128,20 @@ class StretchHandle extends ModifyHandle { const adjusted = ev.isShiftKey ? { x: diff.x, y: diff.y } : { x: diagVec.x, y: diagVec.y }; let { x, y, h, w } = this.startBox; if (this.posNpc.x === 0) { - x += adjusted.x; // left edge + x += adjusted.x; // left edge w -= adjusted.x; } else if (this.posNpc.x === 1) { - w += adjusted.x; // right edge + w += adjusted.x; // right edge } if (this.posNpc.y === 0) { - y += adjusted.y; // top edge + y += adjusted.y; // top edge h -= adjusted.y; } else if (this.posNpc.y === 1) { - h += adjusted.y; // bottom edge + h += adjusted.y; // bottom edge } const mtx = this.startCtm.inverse().scaleO(this.startBox.w / w, this.startBox.h / h, this.opposite.x, this.opposite.y).inverseO(); const minSize = 10; - if (w > minSize && h > minSize) // don't let element get too small + if (w > minSize && h > minSize) // don't let element get too small this.handles.el.markupStretch(w, h, x, y, mtx); } } @@ -152,8 +163,12 @@ class RotateHandle extends ModifyHandle { this._circle = this.addTouchPadding(this._circle, handles); this.setMouseHandler(this._circle); } - public get centerVb() { return this.handles.npcToVb({ x: .5, y: .5 }); } - public get anchorVb() { return this.handles.npcToVb({ x: .5, y: 0 }); } + public get centerVb() { + return this.handles.npcToVb({ x: .5, y: .5 }); + } + public get anchorVb() { + return this.handles.npcToVb({ x: .5, y: 0 }); + } public setPosition(): void { const anchor = this.anchorVb; const dir = this.centerVb.vectorTo(anchor).normalize()!; @@ -301,8 +316,12 @@ export class Handles { return this.vbToBox(pt, pt); } - public npcToVb(p: XAndY, result?: Point2d): Point2d { return this.npcToVbTrn.multiplyPoint2d(p, result); } - public vbToBox(p: XAndY, result?: Point2d): Point2d { return this.vbToBoxTrn.multiplyPoint2d(p, result); } + public npcToVb(p: XAndY, result?: Point2d): Point2d { + return this.npcToVbTrn.multiplyPoint2d(p, result); + } + public vbToBox(p: XAndY, result?: Point2d): Point2d { + return this.vbToBoxTrn.multiplyPoint2d(p, result); + } public npcToVbArray(pts: Point2d[]): Point2d[] { pts.forEach((pt) => this.npcToVb(pt, pt)); return pts; @@ -385,9 +404,15 @@ export class MarkupSelected { /** Called whenever elements are added or removed from this SelectionSet */ public readonly onChanged = new BeEvent<(selected: MarkupSelected) => void>(); - public get size() { return this.elements.size; } - public get isEmpty() { return this.size === 0; } - public has(el: MarkupElement) { return this.elements.has(el); } + public get size() { + return this.elements.size; + } + public get isEmpty() { + return this.size === 0; + } + public has(el: MarkupElement) { + return this.elements.has(el); + } public emptyAll(): void { this.clearEditors(); if (this.isEmpty) @@ -401,7 +426,7 @@ export class MarkupSelected { if (el) this.add(el); } - public constructor(public svg: G) { } + public constructor(public svg: G) {} public clearEditors() { if (this.handles) { this.handles.remove(); @@ -435,10 +460,11 @@ export class MarkupSelected { } public deleteAll(undo: UndoManager) { - undo.performOperation(MarkupApp.getActionName("delete"), () => this.elements.forEach((el) => { - undo.onDelete(el); - el.remove(); - })); + undo.performOperation(MarkupApp.getActionName("delete"), () => + this.elements.forEach((el) => { + undo.onDelete(el); + el.remove(); + })); this.emptyAll(); } @@ -496,12 +522,13 @@ export class MarkupSelected { /** Move all of the entries to a new position in the DOM via a callback. */ public reposition(cmdName: string, undo: UndoManager, fn: (el: MarkupElement) => void) { - undo.performOperation(cmdName, () => this.elements.forEach((el) => { - const oldParent = el.parent() as MarkupElement; - const oldPos = el.position(); - fn(el); - undo.onRepositioned(el, oldPos, oldParent); - })); + undo.performOperation(cmdName, () => + this.elements.forEach((el) => { + const oldParent = el.parent() as MarkupElement; + const oldPos = el.position(); + fn(el); + undo.onRepositioned(el, oldPos, oldParent); + })); this.sizeChanged(); } } @@ -517,7 +544,9 @@ export class SelectTool extends MarkupTool { private _anchorPt!: Point3d; private _isBoxSelect = false; - public get flashedElement(): MarkupElement | undefined { return this._flashedElement; } + public get flashedElement(): MarkupElement | undefined { + return this._flashedElement; + } public set flashedElement(el: MarkupElement | undefined) { if (el === this._flashedElement) return; @@ -544,16 +573,23 @@ export class SelectTool extends MarkupTool { this.cancelDrag(); this.markup.selected.emptyAll(); } - public override async onCleanup() { this.clearSelect(); } + public override async onCleanup() { + this.clearSelect(); + } public override async onPostInstall() { this.initSelect(); return super.onPostInstall(); } - public override async onRestartTool() { this.initSelect(); } + public override async onRestartTool() { + this.initSelect(); + } protected override showPrompt(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Select.Prompts.IdentifyMarkup`)); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Select.Prompts.IdentifyMarkup`), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; @@ -561,13 +597,50 @@ export class SelectTool extends MarkupTool { touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, acceptMsg, false, ToolAssistanceInputMethod.Touch)); mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, acceptMsg, false, ToolAssistanceInputMethod.Mouse)); - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchDrag, CoreTools.translate("ElementSet.Inputs.BoxCorners"), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.BoxCorners"), false, ToolAssistanceInputMethod.Mouse)); - - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.shiftKey, ToolAssistanceImage.LeftClickDrag, CoreTools.translate("ElementSet.Inputs.OverlapSelection"), false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createModifierKeyInstruction(ToolAssistance.ctrlKey, ToolAssistanceImage.LeftClick, CoreTools.translate("ElementSet.Inputs.InvertSelection"), false, ToolAssistanceInputMethod.Mouse)); - - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.CursorClick, CoreTools.translate("ElementSet.Inputs.ClearSelection"), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.OneTouchDrag, + CoreTools.translate("ElementSet.Inputs.BoxCorners"), + false, + ToolAssistanceInputMethod.Touch, + ), + ); + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.BoxCorners"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.shiftKey, + ToolAssistanceImage.LeftClickDrag, + CoreTools.translate("ElementSet.Inputs.OverlapSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + mouseInstructions.push( + ToolAssistance.createModifierKeyInstruction( + ToolAssistance.ctrlKey, + ToolAssistanceImage.LeftClick, + CoreTools.translate("ElementSet.Inputs.InvertSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); + + mouseInstructions.push( + ToolAssistance.createInstruction( + ToolAssistanceImage.CursorClick, + CoreTools.translate("ElementSet.Inputs.ClearSelection"), + false, + ToolAssistanceInputMethod.Mouse, + ), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -664,18 +737,33 @@ export class SelectTool extends MarkupTool { const height = Math.abs(vec.y); if (width < 1 || height < 1) return true; - const rightToLeft = (start.x > end.x); - const overlapMode = (ev.isShiftKey ? !rightToLeft : rightToLeft); // Shift inverts inside/overlap selection... + const rightToLeft = start.x > end.x; + const overlapMode = ev.isShiftKey ? !rightToLeft : rightToLeft; // Shift inverts inside/overlap selection... const offset = Point3d.create(vec.x < 0 ? end.x : start.x, vec.y < 0 ? end.y : start.y); // define location by corner points... this.markup.svgDynamics!.clear(); - this.markup.svgDynamics!.rect(width, height).move(offset.x, offset.y).css({ "stroke-width": 1, "stroke": "black", "stroke-opacity": 0.5, "fill": "lightBlue", "fill-opacity": 0.2 }); - const selectBox = this.markup.svgDynamics!.rect(width, height).move(offset.x, offset.y).css({ "stroke-width": 1, "stroke": "white", "stroke-opacity": 1.0, "stroke-dasharray": overlapMode ? "5" : "2", "fill": "none" }); + this.markup.svgDynamics!.rect(width, height).move(offset.x, offset.y).css({ + "stroke-width": 1, + "stroke": "black", + "stroke-opacity": 0.5, + "fill": "lightBlue", + "fill-opacity": 0.2, + }); + const selectBox = this.markup.svgDynamics!.rect(width, height).move(offset.x, offset.y).css({ + "stroke-width": 1, + "stroke": "white", + "stroke-opacity": 1.0, + "stroke-dasharray": overlapMode ? "5" : "2", + "fill": "none", + }); const outlinesG = isDynamics ? this.markup.svgDynamics!.group() : undefined; const selectRect = selectBox.node.getBoundingClientRect(); this.markup.svgMarkup!.forElementsOfGroup((child) => { const childRect = child.node.getBoundingClientRect(); - const inside = (childRect.left >= selectRect.left && childRect.top >= selectRect.top && childRect.right <= selectRect.right && childRect.bottom <= selectRect.bottom); - const overlap = !inside && (childRect.left < selectRect.right && childRect.right > selectRect.left && childRect.bottom > selectRect.top && childRect.top < selectRect.bottom); + const inside = childRect.left >= selectRect.left && childRect.top >= selectRect.top && childRect.right <= selectRect.right && + childRect.bottom <= selectRect.bottom; + const overlap = !inside && + (childRect.left < selectRect.right && childRect.right > selectRect.left && childRect.bottom > selectRect.top && + childRect.top < selectRect.bottom); const accept = inside || (overlap && overlapMode); if (undefined !== outlinesG) { if (inside || overlap) { @@ -713,7 +801,7 @@ export class SelectTool extends MarkupTool { selected.restart(flashed); // we clicked on an element not in the selection set, replace current selection with just this element selected.clearEditors(); - this._anchorPt = MarkupApp.convertVpToVb(ev.viewPoint); // save the starting point. This is the point where the "down" occurred. + this._anchorPt = MarkupApp.convertVpToVb(ev.viewPoint); // save the starting point. This is the point where the "down" occurred. this.cancelDrag(); selected.elements.forEach((el) => { // add all selected elements to the "dragging" set @@ -738,7 +826,7 @@ export class SelectTool extends MarkupTool { if (this.boxSelect(ev, true)) return; if (InputSource.Touch !== ev.inputSource) - this.flashedElement = this.pickElement(ev.viewPoint); // if we're not dragging, try to find an element under the cursor + this.flashedElement = this.pickElement(ev.viewPoint); // if we're not dragging, try to find an element under the cursor return; } @@ -754,7 +842,7 @@ export class SelectTool extends MarkupTool { const markup = this.markup; const selected = markup.selected; const handles = selected.handles; - if (handles && handles.dragging) // if we have handles up, and if they're in the "dragging" state, send the event to them + if (handles && handles.dragging) // if we have handles up, and if they're in the "dragging" state, send the event to them return handles.endDrag(markup.undo); if (this._dragging.length === 0) @@ -767,18 +855,19 @@ export class SelectTool extends MarkupTool { selected.emptyAll(); // move or copy all of the elements in dragged set - undo.performOperation(MarkupApp.getActionName("copy"), () => this._dragging.forEach((el) => { - el.translate(delta.x, delta.y); // move to final location - const original = el.originalEl!; // save original element - el.originalEl = undefined; // clear original element - if (ev.isShiftKey) { - selected.add(el); - undo.onAdded(el); // shift key means copy element - } else { - original.replace(el); - undo.onModified(el, original); - } - })); + undo.performOperation(MarkupApp.getActionName("copy"), () => + this._dragging.forEach((el) => { + el.translate(delta.x, delta.y); // move to final location + const original = el.originalEl!; // save original element + el.originalEl = undefined; // clear original element + if (ev.isShiftKey) { + selected.add(el); + undo.onAdded(el); // shift key means copy element + } else { + original.replace(el); + undo.onModified(el, original); + } + })); this._dragging.length = 0; // empty dragging set selected.sizeChanged(); // notify that size of selection set changed diff --git a/core/markup/src/SvgJsExt.ts b/core/markup/src/SvgJsExt.ts index 73685f081b94..62d9cf5338b3 100644 --- a/core/markup/src/SvgJsExt.ts +++ b/core/markup/src/SvgJsExt.ts @@ -7,7 +7,7 @@ */ import { Transform } from "@itwin/core-geometry"; -import { Box, extend, G, Element as MarkupElement, Matrix, nodeOrNew, Rect, register, Svg, Text } from "@svgdotjs/svg.js"; +import { Box, Element as MarkupElement, extend, G, Matrix, nodeOrNew, Rect, register, Svg, Text } from "@svgdotjs/svg.js"; import { MarkupApp } from "./Markup"; // cspell:ignore lmultiply matrixify dmove @@ -92,7 +92,10 @@ extend(MarkupElement, { forElementsOfGroup(fn: (child: MarkupElement) => void): void { const me = this as MarkupElement; if (me instanceof G) - me.each((i, children) => { const child = children[i]; if (child instanceof MarkupElement) fn(child); }, false); + me.each((i, children) => { + const child = children[i]; + if (child instanceof MarkupElement) fn(child); + }, false); }, cloneMarkup(): MarkupElement { const me = this as MarkupElement; @@ -121,11 +124,32 @@ extend(MarkupElement, { me.css(oldColor).data(OLDCOLOR, null); // change to old color and remove data object me.forElementsOfGroup((child) => child.resetColor()); }, - hilite() { const me = this as MarkupElement; if (!me.inSelection) { me.overrideColor(MarkupApp.props.hilite.color); me.inSelection = true; } }, - unHilite() { const me = this as MarkupElement; if (me.inSelection) { me.resetColor(); me.inSelection = undefined; } }, - flash() { const me = this as MarkupElement; if (!me.inSelection) me.overrideColor(MarkupApp.props.hilite.flash); }, - unFlash() { const me = this as MarkupElement; if (!me.inSelection) me.resetColor(); }, - markupStretch(w: number, h: number, x: number, y: number, _mtx: Matrix) { const me = this as MarkupElement; me.size(w, h).move(x, y); }, + hilite() { + const me = this as MarkupElement; + if (!me.inSelection) { + me.overrideColor(MarkupApp.props.hilite.color); + me.inSelection = true; + } + }, + unHilite() { + const me = this as MarkupElement; + if (me.inSelection) { + me.resetColor(); + me.inSelection = undefined; + } + }, + flash() { + const me = this as MarkupElement; + if (!me.inSelection) me.overrideColor(MarkupApp.props.hilite.flash); + }, + unFlash() { + const me = this as MarkupElement; + if (!me.inSelection) me.resetColor(); + }, + markupStretch(w: number, h: number, x: number, y: number, _mtx: Matrix) { + const me = this as MarkupElement; + me.size(w, h).move(x, y); + }, isChildOf(svg: Svg) { const parent = (this as MarkupElement).parent(); return (parent === svg) ? true : (parent instanceof MarkupElement) ? parent.isChildOf(svg) : false; @@ -156,11 +180,18 @@ extend(MarkupElement, { }); extend(G, { - markupStretch(_w: number, _h: number, _x: number, _y: number, mtx: Matrix) { (this as G).attr("transform", mtx); }, + markupStretch(_w: number, _h: number, _x: number, _y: number, mtx: Matrix) { + (this as G).attr("transform", mtx); + }, }); extend(Text, { - getFontSize(): number { const me = this as Text; return parseFloat(window.getComputedStyle(me.node).fontSize); }, - markupStretch(_w: number, _h: number, _x: number, _y: number, mtx: Matrix) { (this as Text).attr("transform", mtx); }, + getFontSize(): number { + const me = this as Text; + return parseFloat(window.getComputedStyle(me.node).fontSize); + }, + markupStretch(_w: number, _h: number, _x: number, _y: number, mtx: Matrix) { + (this as Text).attr("transform", mtx); + }, getMarkup() { const node = (this as Text).node; let text = ""; @@ -235,18 +266,31 @@ extend(Matrix, { * @internal */ export class Title extends MarkupElement { - constructor(node: any) { super(nodeOrNew("title", node)); } - public override scale() { return this; } - public override size() { return this; } - public override move() { return this; } - public override dmove() { return this; } - public override bbox() { return new Box(); } - public override screenCTM() { return new Matrix(); } - + constructor(node: any) { + super(nodeOrNew("title", node)); + } + public override scale() { + return this; + } + public override size() { + return this; + } + public override move() { + return this; + } + public override dmove() { + return this; + } + public override bbox() { + return new Box(); + } + public override screenCTM() { + return new Matrix(); + } } register(Title, "Title"); /** only for tests * @internal */ -export function initSvgExt() { } +export function initSvgExt() {} diff --git a/core/markup/src/TextEdit.ts b/core/markup/src/TextEdit.ts index 9d06e46164ab..fa9114f10be2 100644 --- a/core/markup/src/TextEdit.ts +++ b/core/markup/src/TextEdit.ts @@ -7,8 +7,16 @@ */ import { - BeButtonEvent, CoreTools, EventHandled, IModelApp, InputSource, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, - ToolAssistanceInstruction, ToolAssistanceSection, + BeButtonEvent, + CoreTools, + EventHandled, + IModelApp, + InputSource, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, + ToolAssistanceSection, } from "@itwin/core-frontend"; import { G, Text as MarkupText } from "@svgdotjs/svg.js"; import { MarkupApp } from "./Markup"; @@ -32,7 +40,9 @@ export class PlaceTextTool extends RedlineTool { return super.onPostInstall(); } - protected override showPrompt(): void { this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); } + protected override showPrompt(): void { + this.provideToolAssistance(`${MarkupTool.toolKey}Text.Place.Prompts.FirstPoint`, true); + } protected override async createMarkup(svg: G, ev: BeButtonEvent, isDynamics: boolean): Promise { if (isDynamics && InputSource.Touch === ev.inputSource) @@ -63,10 +73,15 @@ export class EditTextTool extends MarkupTool { public editor?: HTMLTextAreaElement; public editDiv?: HTMLDivElement; public boxed?: G; - constructor(public text?: MarkupText | G, private _fromPlaceTool = false) { super(); } + constructor(public text?: MarkupText | G, private _fromPlaceTool = false) { + super(); + } protected override showPrompt(): void { - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`)); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + IModelApp.localization.getLocalizedString(`${MarkupTool.toolKey}Text.Edit.Prompts.FirstPoint`), + ); const mouseInstructions: ToolAssistanceInstruction[] = []; const touchInstructions: ToolAssistanceInstruction[] = []; @@ -122,14 +137,17 @@ export class EditTextTool extends MarkupTool { editor.wrap = "off"; // so we don't send these events to the ToolAdmin and process them by tools. We want default handling const mouseListener = (ev: Event) => (ev.stopPropagation(), true); - (editor as any).onselectstart = editor.oncontextmenu = editor.onmousedown = editor.onmouseup = mouseListener; // enable default handling for these events + (editor as any).onselectstart = + editor.oncontextmenu = + editor.onmousedown = + editor.onmouseup = + mouseListener; // enable default handling for these events // Tab, Escape, ctrl-enter, or shift-enter all end the editor editor.onkeydown = async (ev: KeyboardEvent) => { if (ev.key === "Tab" || ev.key === "Escape" || (ev.key === "Enter" && (ev.shiftKey || ev.ctrlKey))) this.exitTool(); // eslint-disable-line @typescript-eslint/no-floating-promises ev.stopPropagation(); - }; const textElStyle = window.getComputedStyle(text.node); diff --git a/core/markup/src/Undo.ts b/core/markup/src/Undo.ts index 9875d3c72862..96f1286bde51 100644 --- a/core/markup/src/Undo.ts +++ b/core/markup/src/Undo.ts @@ -15,7 +15,7 @@ abstract class UndoAction { public cmdId: number = 0; public abstract reverse(): void; public abstract reinstate(): void; - constructor(public cmdName: string) { } + constructor(public cmdName: string) {} } /** created when a new element is added to the markup @@ -30,7 +30,9 @@ class AddAction extends UndoAction { assert(this._parent !== undefined); this._index = _elem.position(); } - public reinstate() { this._parent.add(this._elem, this._index); } + public reinstate() { + this._parent.add(this._elem, this._index); + } public reverse() { MarkupApp.markup!.selected.drop(this._elem); this._elem.remove(); @@ -49,7 +51,9 @@ class DeleteAction extends UndoAction { assert(this._parent !== undefined); this._index = _elem.position(); } - public reverse() { this._parent.add(this._elem, this._index); } + public reverse() { + this._parent.add(this._elem, this._index); + } public reinstate() { MarkupApp.markup!.selected.drop(this._elem); this._elem.remove(); @@ -118,7 +122,9 @@ export class UndoManager { } /** @internal */ - public get size() { return this._stack.length; } + public get size() { + return this._stack.length; + } private startCommand() { if (0 === this._grouped) ++this._currentCmd; @@ -129,7 +135,9 @@ export class UndoManager { ++this._grouped; } - private endGroup() { --this._grouped; } + private endGroup() { + --this._grouped; + } /** Perform a series of changes to markup elements that should all be reversed as a single operation. * @param fn the function that performs the changes to the elements. It must call the onXXX methods of this class to store @@ -144,22 +152,38 @@ export class UndoManager { } /** call this from within a [[performOperation]] function *after* an element has been added to a markup */ - public onAdded(elem: MarkupElement) { this.addAction(new AddAction(this._cmdName, elem)); } + public onAdded(elem: MarkupElement) { + this.addAction(new AddAction(this._cmdName, elem)); + } /** call this from within a [[performOperation]] function *before* an element is about to be deleted from a markup */ - public onDelete(elem: MarkupElement) { this.addAction(new DeleteAction(this._cmdName, elem)); } + public onDelete(elem: MarkupElement) { + this.addAction(new DeleteAction(this._cmdName, elem)); + } /** call this from within a [[performOperation]] function *after* an element has been moved in display order in a markup */ - public onRepositioned(elem: MarkupElement, oldIndex: number, oldParent: MarkupElement) { this.addAction(new RepositionAction(this._cmdName, elem, oldIndex, oldParent)); } + public onRepositioned(elem: MarkupElement, oldIndex: number, oldParent: MarkupElement) { + this.addAction(new RepositionAction(this._cmdName, elem, oldIndex, oldParent)); + } /** call this from within a [[performOperation]] function *after* an element has been modified in a markup */ - public onModified(newElem: MarkupElement, oldElem: MarkupElement) { this.addAction(new ModifyAction(this._cmdName, newElem, oldElem)); } + public onModified(newElem: MarkupElement, oldElem: MarkupElement) { + this.addAction(new ModifyAction(this._cmdName, newElem, oldElem)); + } /** determine whether there are any un-reversed operations */ - public get undoPossible() { return this._currentPos > 0; } + public get undoPossible() { + return this._currentPos > 0; + } /** determine whether there are any reversed operations */ - public get redoPossible() { return this._currentPos < this.size; } + public get redoPossible() { + return this._currentPos < this.size; + } /** the name of the operation that can be undone (or undefined) */ - public get undoString() { return this.undoPossible ? this._stack[this._currentPos - 1].cmdName : undefined; } + public get undoString() { + return this.undoPossible ? this._stack[this._currentPos - 1].cmdName : undefined; + } /** the name of the operation that can be redone (or undefined) */ - public get redoString() { return this.redoPossible ? this._stack[this._currentPos].cmdName : undefined; } + public get redoString() { + return this.redoPossible ? this._stack[this._currentPos].cmdName : undefined; + } /** reverse the most recent operation, if any */ public doUndo() { diff --git a/core/markup/src/test/Markup.test.ts b/core/markup/src/test/Markup.test.ts index 2265ad0b5584..4240dbd382db 100644 --- a/core/markup/src/test/Markup.test.ts +++ b/core/markup/src/test/Markup.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Angle, AxisIndex, Matrix3d, Point3d, Transform } from "@itwin/core-geometry"; -import { Element, G, Matrix, Svg, SVG } from "@svgdotjs/svg.js"; +import { Element, G, Matrix, SVG, Svg } from "@svgdotjs/svg.js"; +import { assert } from "chai"; import { MarkupApp } from "../Markup"; import { initSvgExt } from "../SvgJsExt"; @@ -146,5 +146,4 @@ describe("Markup", () => { e1.replace(clone); checkColor(clone, red, blue, "clone should turn off hilite"); }); - }); diff --git a/core/markup/src/test/utils/webpack.config.js b/core/markup/src/test/utils/webpack.config.js index 9ccdbbdc49df..3f3bf581909b 100644 --- a/core/markup/src/test/utils/webpack.config.js +++ b/core/markup/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -57,8 +57,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -83,5 +83,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/core/mobile/eslint.config.js b/core/mobile/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/mobile/eslint.config.js +++ b/core/mobile/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/mobile/src/backend/MobileFileHandler.ts b/core/mobile/src/backend/MobileFileHandler.ts index 009137aea1de..1493930bb69e 100644 --- a/core/mobile/src/backend/MobileFileHandler.ts +++ b/core/mobile/src/backend/MobileFileHandler.ts @@ -6,13 +6,13 @@ * @module iModelHub */ +import { AccessToken, BentleyError, GetMetaDataFunction, Logger } from "@itwin/core-bentley"; import { Buffer } from "node:buffer"; import * as fs from "node:fs"; import * as https from "node:https"; import * as path from "node:path"; -import { AccessToken, BentleyError, GetMetaDataFunction, Logger } from "@itwin/core-bentley"; -import { ProgressCallback, ProgressInfo, request, RequestOptions } from "./Request"; import { MobileHost } from "./MobileHost"; +import { ProgressCallback, ProgressInfo, request, RequestOptions } from "./Request"; const loggerCategory: string = "mobile.filehandler"; @@ -22,16 +22,16 @@ const defined = (argumentName: string, argument?: any, allowEmpty: boolean = fal }; /** Interface to cancel a request - * @beta - */ + * @beta + */ export interface CancelRequest { /** Returns true if cancel request was acknowledged */ cancel: () => boolean; } /** Error thrown when user cancelled operation - * @internal - */ + * @internal + */ export class UserCancelledError extends BentleyError { public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) { super(errorNumber, message, getMetaData); @@ -40,8 +40,8 @@ export class UserCancelledError extends BentleyError { } /** Error thrown fail to download file. ErrorNumber will correspond to HTTP error code. - * @internal - */ + * @internal + */ export class DownloadFailed extends BentleyError { public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) { super(errorNumber, message, getMetaData); @@ -50,8 +50,8 @@ export class DownloadFailed extends BentleyError { } /** Error thrown when sas-url provided for download has expired - * @internal - */ + * @internal + */ export class SasUrlExpired extends BentleyError { public constructor(errorNumber: number, message: string, getMetaData?: GetMetaDataFunction) { super(errorNumber, message, getMetaData); @@ -123,7 +123,14 @@ export class MobileFileHandler { * @param progressCallback Callback for tracking progress. * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty. */ - public async downloadFile(_accessToken: AccessToken, downloadUrl: string, downloadToPathname: string, fileSize?: number, progressCallback?: ProgressCallback, cancelRequest?: CancelRequest): Promise { + public async downloadFile( + _accessToken: AccessToken, + downloadUrl: string, + downloadToPathname: string, + fileSize?: number, + progressCallback?: ProgressCallback, + cancelRequest?: CancelRequest, + ): Promise { // strip search and hash parameters from download Url for logging purpose const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(downloadUrl); Logger.logInfo(loggerCategory, `Downloading file from ${safeToLogUrl}`); @@ -162,7 +169,13 @@ export class MobileFileHandler { return Buffer.from(blockId.toString(16).padStart(5, "0")).toString("base64"); } - private async uploadChunk(_accessToken: AccessToken, uploadUrlString: string, fileDescriptor: number, blockId: number, callback?: ProgressCallback) { + private async uploadChunk( + _accessToken: AccessToken, + uploadUrlString: string, + fileDescriptor: number, + blockId: number, + callback?: ProgressCallback, + ) { const chunkSize = 4 * 1024 * 1024; let buffer = Buffer.alloc(chunkSize); const bytesRead = fs.readSync(fileDescriptor, buffer, 0, chunkSize, chunkSize * blockId); @@ -195,7 +208,12 @@ export class MobileFileHandler { * @param progressCallback Callback for tracking progress. * @throws [[IModelHubClientError]] with [IModelHubStatus.UndefinedArgumentError]($bentley) if one of the arguments is undefined or empty. */ - public async uploadFile(accessToken: AccessToken, uploadUrlString: string, uploadFromPathname: string, progressCallback?: ProgressCallback): Promise { + public async uploadFile( + accessToken: AccessToken, + uploadUrlString: string, + uploadFromPathname: string, + progressCallback?: ProgressCallback, + ): Promise { const safeToLogUrl = MobileFileHandler.getSafeUrlForLogging(uploadUrlString); Logger.logTrace(loggerCategory, `Uploading file to ${safeToLogUrl}`); defined("uploadUrlString", uploadUrlString); @@ -206,7 +224,7 @@ export class MobileFileHandler { const chunkSize = 4 * 1024 * 1024; try { - let blockList = ''; + let blockList = ''; let i = 0; const callback: ProgressCallback = (progress: ProgressInfo) => { const uploaded = i * chunkSize + progress.loaded; diff --git a/core/mobile/src/backend/MobileHost.ts b/core/mobile/src/backend/MobileHost.ts index 1227ef90ddef..d8eb11a837b0 100644 --- a/core/mobile/src/backend/MobileHost.ts +++ b/core/mobile/src/backend/MobileHost.ts @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { AccessToken, BeEvent, BriefcaseStatus } from "@itwin/core-bentley"; import { IpcHandler, IpcHost, NativeHost, NativeHostOpts } from "@itwin/core-backend"; +import { AccessToken, BeEvent, BriefcaseStatus } from "@itwin/core-bentley"; import { IpcWebSocketBackend, RpcInterfaceDefinition } from "@itwin/core-common"; -import { CancelRequest, DownloadFailed, UserCancelledError } from "./MobileFileHandler"; -import { ProgressCallback } from "./Request"; import { mobileAppStrings } from "../common/MobileAppChannel"; import { BatteryState, DeviceEvents, MobileAppFunctions, MobileNotifications, Orientation } from "../common/MobileAppProps"; import { MobileRpcManager } from "../common/MobileRpcManager"; import { MobileAuthorizationBackend } from "./MobileAuthorizationBackend"; +import { CancelRequest, DownloadFailed, UserCancelledError } from "./MobileFileHandler"; import { setupMobileRpc } from "./MobileRpcServer"; +import { ProgressCallback } from "./Request"; /** @beta */ export type MobileCompletionCallback = (downloadUrl: string, downloadFileUrl: string, cancelled: boolean, err?: string) => void; @@ -64,7 +64,13 @@ export abstract class MobileDevice { public abstract getOrientation(): Orientation; public abstract getBatteryState(): BatteryState; public abstract getBatteryLevel(): number; - public abstract createDownloadTask(downloadUrl: string, isBackground: boolean, downloadTo: string, completion: MobileCompletionCallback, progress?: MobileProgressCallback): number; + public abstract createDownloadTask( + downloadUrl: string, + isBackground: boolean, + downloadTo: string, + completion: MobileCompletionCallback, + progress?: MobileProgressCallback, + ): number; public abstract cancelDownloadTask(cancelId: number): boolean; public abstract getDownloadTasks(): DownloadTask[]; public abstract resumeDownloadInForeground(requestId: number): boolean; @@ -74,7 +80,9 @@ export abstract class MobileDevice { } class MobileAppHandler extends IpcHandler implements MobileAppFunctions { - public get channelName() { return mobileAppStrings.mobileAppChannel; } + public get channelName() { + return mobileAppStrings.mobileAppChannel; + } public async reconnect(connection: number) { MobileHost.reconnect(connection); } @@ -97,7 +105,9 @@ export interface MobileHostOpts extends NativeHostOpts { */ export class MobileHost { private static _device?: MobileDevice; - public static get device() { return this._device!; } + public static get device() { + return this._device!; + } /** * Raised when the mobile OS informs a mobile app that it is running low on memory. * @@ -156,9 +166,13 @@ export class MobileHost { } /** @internal */ - public static async downloadFile(downloadUrl: string, downloadTo: string, progress?: ProgressCallback, cancelRequest?: CancelRequest): Promise { + public static async downloadFile( + downloadUrl: string, + downloadTo: string, + progress?: ProgressCallback, + cancelRequest?: CancelRequest, + ): Promise { return new Promise((resolve, reject) => { - let progressCb: MobileProgressCallback | undefined; let lastReportedOn = Date.now(); const minTimeBeforeReportingProgress = 1000; @@ -176,14 +190,20 @@ export class MobileHost { progress({ total: totalBytesExpectedToWrite, loaded: totalBytesWritten, percent }); }; } - const requestId = this.device.createDownloadTask(downloadUrl, false, downloadTo, (_downloadUrl: string, _downloadFileUrl: string, cancelled: boolean, err?: string) => { - if (cancelled) - reject(new UserCancelledError(BriefcaseStatus.DownloadCancelled, "User cancelled download")); - else if (err) - reject(new DownloadFailed(400, "Download failed")); - else - resolve(); - }, progressCb); + const requestId = this.device.createDownloadTask( + downloadUrl, + false, + downloadTo, + (_downloadUrl: string, _downloadFileUrl: string, cancelled: boolean, err?: string) => { + if (cancelled) + reject(new UserCancelledError(BriefcaseStatus.DownloadCancelled, "User cancelled download")); + else if (err) + reject(new DownloadFailed(400, "Download failed")); + else + resolve(); + }, + progressCb, + ); if (cancelRequest) { // eslint-disable-next-line @typescript-eslint/unbound-method cancelRequest.cancel = () => this.device.cancelDownloadTask(requestId); @@ -191,7 +211,9 @@ export class MobileHost { }); } - public static get isValid() { return undefined !== this._device; } + public static get isValid() { + return undefined !== this._device; + } /** Start the backend of a mobile app. */ public static async startup(opt?: MobileHostOpts): Promise { @@ -207,7 +229,7 @@ export class MobileHost { this.onOrientationChanged.addListener(() => { try { MobileHost.notifyMobileFrontend("notifyOrientationChanged"); - } catch (_ex) { } // Ignore: frontend is not currently connected + } catch (_ex) {} // Ignore: frontend is not currently connected }); this.onWillTerminate.addListener(() => { MobileHost.notifyMobileFrontend("notifyWillTerminate"); diff --git a/core/mobile/src/backend/MobileRpcServer.ts b/core/mobile/src/backend/MobileRpcServer.ts index 0b8468c382a1..a2d5c78f08e5 100644 --- a/core/mobile/src/backend/MobileRpcServer.ts +++ b/core/mobile/src/backend/MobileRpcServer.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as ws from "ws"; +import { ProcessDetector } from "@itwin/core-bentley"; import { BentleyStatus, IModelError } from "@itwin/core-common"; -import { MobileRpcGateway, MobileRpcProtocol } from "../common/MobileRpcProtocol"; +import * as ws from "ws"; import { MobileRpcConfiguration } from "../common/MobileRpcManager"; +import { MobileRpcGateway, MobileRpcProtocol } from "../common/MobileRpcProtocol"; import { MobileHost } from "./MobileHost"; -import { ProcessDetector } from "@itwin/core-bentley"; /* eslint-disable deprecation/deprecation */ @@ -24,9 +24,15 @@ export class MobileRpcServer { private static _nextId = -1; public static interop: MobileRpcGateway = { - handler: (_payload: ArrayBuffer | string) => { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); }, - sendString: (_message: string, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, "No connection."); }, - sendBinary: (_message: Uint8Array, _connectionId: number) => { throw new IModelError(BentleyStatus.ERROR, "No connection."); }, + handler: (_payload: ArrayBuffer | string) => { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + }, + sendString: (_message: string, _connectionId: number) => { + throw new IModelError(BentleyStatus.ERROR, "No connection."); + }, + sendBinary: (_message: Uint8Array, _connectionId: number) => { + throw new IModelError(BentleyStatus.ERROR, "No connection."); + }, port: 0, connectionId: 0, }; @@ -46,7 +52,7 @@ export class MobileRpcServer { * clear the timer. Here we use setInterval() just to make sure otherwise setTimeout() could equally * be effective */ - this._pingTimer = setInterval(() => { }, 5); + this._pingTimer = setInterval(() => {}, 5); this._port = MobileRpcConfiguration.setup.obtainPort(); this._server = new ws.Server({ port: this._port }); this._connectionId = ++MobileRpcServer._nextId; @@ -138,8 +144,8 @@ export class MobileRpcServer { public dispose() { clearInterval(this._pingTimer); if (this._connection) { - MobileRpcServer.interop.sendString = () => { }; - MobileRpcServer.interop.sendBinary = () => { }; + MobileRpcServer.interop.sendString = () => {}; + MobileRpcServer.interop.sendBinary = () => {}; this._connection.close(); } @@ -185,7 +191,7 @@ export function setupMobileRpc() { return; } - retainUvLoop = setInterval(() => { }, 1000); + retainUvLoop = setInterval(() => {}, 1000); server.dispose(); usePendingSender(); server = null; @@ -203,7 +209,7 @@ export function setupMobileRpc() { }); MobileHost.onWillTerminate.addListener(() => { - if (typeof (retainUvLoop) !== "undefined") { + if (typeof retainUvLoop !== "undefined") { clearInterval(retainUvLoop); retainUvLoop = undefined; } diff --git a/core/mobile/src/backend/Request.ts b/core/mobile/src/backend/Request.ts index f71e763da096..0e1f5e9f3d3e 100644 --- a/core/mobile/src/backend/Request.ts +++ b/core/mobile/src/backend/Request.ts @@ -5,10 +5,10 @@ /** @packageDocumentation * @module iTwinServiceClients */ -import * as _ from "lodash"; +import { BentleyError, GetMetaDataFunction, HttpStatus, Logger, LogLevel } from "@itwin/core-bentley"; import * as https from "https"; +import * as _ from "lodash"; import * as sarequest from "superagent"; -import { BentleyError, GetMetaDataFunction, HttpStatus, Logger, LogLevel } from "@itwin/core-bentley"; const loggerCategory: string = "core-mobile-backend.Request"; @@ -316,12 +316,12 @@ export async function request(url: string, options: RequestOptions): Promise Promise; getAccessToken: () => Promise<[AccessToken, string]>; diff --git a/core/mobile/src/common/MobileEventLoop.ts b/core/mobile/src/common/MobileEventLoop.ts index ce22170710f0..12dacb78af3b 100644 --- a/core/mobile/src/common/MobileEventLoop.ts +++ b/core/mobile/src/common/MobileEventLoop.ts @@ -28,5 +28,5 @@ export class MobileEventLoop { } } - private static _idleHandler() { } + private static _idleHandler() {} } diff --git a/core/mobile/src/common/MobileIpc.ts b/core/mobile/src/common/MobileIpc.ts index 53b13fe45a99..513c6a4b359d 100644 --- a/core/mobile/src/common/MobileIpc.ts +++ b/core/mobile/src/common/MobileIpc.ts @@ -7,7 +7,14 @@ */ import { - IpcWebSocket, IpcWebSocketMessage, IpcWebSocketMessageType, IpcWebSocketTransport, RpcInterface, RpcManager, RpcMarshaling, RpcRequestFulfillment, + IpcWebSocket, + IpcWebSocketMessage, + IpcWebSocketMessageType, + IpcWebSocketTransport, + RpcInterface, + RpcManager, + RpcMarshaling, + RpcRequestFulfillment, SerializedRpcRequest, } from "@itwin/core-common"; import { MobileEventLoop } from "./MobileEventLoop"; @@ -19,7 +26,7 @@ const IPC = "__ipc__"; class IpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation public static interfaceName = IPC; public static interfaceVersion = "0.0.0"; - public async send() { } + public async send() {} } /** @internal */ diff --git a/core/mobile/src/common/MobilePush.ts b/core/mobile/src/common/MobilePush.ts index 4eac6798f821..c890a40f6274 100644 --- a/core/mobile/src/common/MobilePush.ts +++ b/core/mobile/src/common/MobilePush.ts @@ -19,7 +19,9 @@ export class MobilePushTransport extends RpcPushTransport { private _protocol: MobileRpcProtocol; private _last: number = -1; - public get last() { return this._last; } + public get last() { + return this._last; + } public constructor(protocol: MobileRpcProtocol) { super(); diff --git a/core/mobile/src/common/MobileRpcManager.ts b/core/mobile/src/common/MobileRpcManager.ts index 031abfc7224a..c0004e4b7c92 100644 --- a/core/mobile/src/common/MobileRpcManager.ts +++ b/core/mobile/src/common/MobileRpcManager.ts @@ -24,7 +24,7 @@ export abstract class MobileRpcConfiguration extends RpcConfiguration { /** @internal */ public static setup = { obtainPort: () => 0, - checkPlatform: () => typeof (process) !== "undefined" && (process.platform as any) === "ios", + checkPlatform: () => typeof process !== "undefined" && (process.platform as any) === "ios", }; public abstract override protocol: MobileRpcProtocol; @@ -46,7 +46,7 @@ export abstract class MobileRpcConfiguration extends RpcConfiguration { } } } - } catch { } + } catch {} return Object.freeze(queryArgs); } private static getMobilePlatform(): RpcMobilePlatform { @@ -73,7 +73,9 @@ export abstract class MobileRpcConfiguration extends RpcConfiguration { } /** Return type of mobile platform using browser userAgent */ - public static get platform(): RpcMobilePlatform { return MobileRpcConfiguration.getMobilePlatform(); } + public static get platform(): RpcMobilePlatform { + return MobileRpcConfiguration.getMobilePlatform(); + } } /** Coordinates usage of RPC interfaces for an Mobile-based application. @@ -116,4 +118,3 @@ export class MobileRpcManager { return MobileRpcManager.performInitialization(interfaces, RpcEndpoint.Backend); } } - diff --git a/core/mobile/src/common/MobileRpcProtocol.ts b/core/mobile/src/common/MobileRpcProtocol.ts index f8873f20c923..9b18f7625bb6 100644 --- a/core/mobile/src/common/MobileRpcProtocol.ts +++ b/core/mobile/src/common/MobileRpcProtocol.ts @@ -8,7 +8,15 @@ import { BentleyStatus } from "@itwin/core-bentley"; import { - IModelError, IpcWebSocket, RpcEndpoint, RpcProtocol, RpcPushChannel, RpcPushConnection, RpcRequest, RpcRequestFulfillment, RpcSerializedValue, + IModelError, + IpcWebSocket, + RpcEndpoint, + RpcProtocol, + RpcPushChannel, + RpcPushConnection, + RpcRequest, + RpcRequestFulfillment, + RpcSerializedValue, SerializedRpcRequest, } from "@itwin/core-common"; import { MobileEventLoop } from "./MobileEventLoop"; @@ -48,7 +56,9 @@ export class MobileRpcProtocol extends RpcProtocol { private _port: number = 0; private _transport?: MobilePushTransport; private _ipc: MobileIpcTransport; - public static obtainInterop(): MobileRpcGateway { throw new IModelError(BentleyStatus.ERROR, "Not implemented."); } + public static obtainInterop(): MobileRpcGateway { + throw new IModelError(BentleyStatus.ERROR, "Not implemented."); + } public static async encodeRequest(request: MobileRpcRequest): Promise { const serialized = await request.protocol.serialize(request); @@ -81,7 +91,7 @@ export class MobileRpcProtocol extends RpcProtocol { } private initializeFrontend() { - if (typeof (WebSocket) === "undefined") { + if (typeof WebSocket === "undefined") { throw new IModelError(BentleyStatus.ERROR, "MobileRpcProtocol on frontend require websocket to work"); } if (!MobileRpcConfiguration.args.port) { @@ -199,7 +209,7 @@ export class MobileRpcProtocol extends RpcProtocol { } private handleMessageFromBackend(data: string | ArrayBuffer) { - if (typeof (data) === "string") { + if (typeof data === "string") { this.handleStringFromBackend(data); } else { this.handleBinaryFromBackend(data); @@ -274,7 +284,7 @@ export class MobileRpcProtocol extends RpcProtocol { } private handleMessageFromFrontend(data: string | ArrayBuffer, connectionId: number) { - if (typeof (data) === "string") { + if (typeof data === "string") { this.handleStringFromFrontend(data, connectionId); } else { this.handleBinaryFromFrontend(data, connectionId); @@ -336,7 +346,7 @@ export class MobileRpcProtocol extends RpcProtocol { const mobilegateway = MobileRpcProtocol.obtainInterop(); for (const chunk of message) { - if (typeof (chunk) === "string") { + if (typeof chunk === "string") { mobilegateway.sendString(chunk, connection || mobilegateway.connectionId); } else { mobilegateway.sendBinary(chunk, connection || mobilegateway.connectionId); diff --git a/core/mobile/src/frontend/MobileApp.ts b/core/mobile/src/frontend/MobileApp.ts index dd254e6033aa..1bfe330032d3 100644 --- a/core/mobile/src/frontend/MobileApp.ts +++ b/core/mobile/src/frontend/MobileApp.ts @@ -16,7 +16,9 @@ export type MobileAppOpts = NativeAppOpts & { iModelApp: { authorizationClient?: /** receive notifications from backend */ class MobileAppNotifyHandler extends NotificationHandler implements MobileNotifications { - public get channelName() { return mobileAppStrings.mobileAppNotify; } + public get channelName() { + return mobileAppStrings.mobileAppNotify; + } public notifyMemoryWarning() { Logger.logWarning("mobileApp", "Low memory warning"); @@ -25,8 +27,12 @@ class MobileAppNotifyHandler extends NotificationHandler implements MobileNotifi } MobileApp.onMemoryWarning.raiseEvent(); } - public notifyOrientationChanged() { MobileApp.onOrientationChanged.raiseEvent(); } - public notifyWillTerminate() { MobileApp.onWillTerminate.raiseEvent(); } + public notifyOrientationChanged() { + MobileApp.onOrientationChanged.raiseEvent(); + } + public notifyWillTerminate() { + MobileApp.onWillTerminate.raiseEvent(); + } public notifyAuthAccessTokenChanged(accessToken: string | undefined, expirationDate: string | undefined) { MobileApp.onAuthAccessTokenChanged.raiseEvent(accessToken, expirationDate); } @@ -45,7 +51,9 @@ export class MobileApp { } private static _isValid = false; - public static get isValid() { return this._isValid; } + public static get isValid() { + return this._isValid; + } /** @beta */ public static async startup(opts?: MobileAppOpts) { attachDirectEventCallbacks(); diff --git a/core/mobile/src/test/ios/MobilePlatform.test.ts b/core/mobile/src/test/ios/MobilePlatform.test.ts index 65b7427dfe21..0f91584125c0 100644 --- a/core/mobile/src/test/ios/MobilePlatform.test.ts +++ b/core/mobile/src/test/ios/MobilePlatform.test.ts @@ -95,5 +95,4 @@ describe("IOS Platform Test", () => { - (NSString*) realpathSync: (JSValue*)path :(JSValue*)options; - (void) closeSync: (JSValue*)fd; - (JSValue*) openSync: (NSString*)path :(NSString*)flags :(JSValue*)mode; */ - }); diff --git a/core/mobile/src/test/ios/config/ignoreTest.js b/core/mobile/src/test/ios/config/ignoreTest.js index 8e1f46cba948..8f6250ca2a70 100644 --- a/core/mobile/src/test/ios/config/ignoreTest.js +++ b/core/mobile/src/test/ios/config/ignoreTest.js @@ -28,5 +28,5 @@ module.exports = [ "read view thumbnail", "should be able to create a snapshot IModel", "should create elements exercising the LinearReferencing domain", - "Create Table, Insert, Select with ECDb" + "Create Table, Insert, Select with ECDb", ]; diff --git a/core/mobile/src/test/ios/config/mobile.webpack.config.js b/core/mobile/src/test/ios/config/mobile.webpack.config.js index 22d8676b5a1f..8c06148fd032 100644 --- a/core/mobile/src/test/ios/config/mobile.webpack.config.js +++ b/core/mobile/src/test/ios/config/mobile.webpack.config.js @@ -42,7 +42,7 @@ function findPackageRootDir(dir = __dirname) { const outputDir = path.resolve(findPackageRootDir(), "lib/test/ios/webpack"); const configFile = path.join(outputDir, "config.json"); const filteredEnv = Object.keys(process.env) - .filter(key => key.match(/^imjs_|^hybrid_test_|^saml_delegation_test_/i)) + .filter((key) => key.match(/^imjs_|^hybrid_test_|^saml_delegation_test_/i)) .reduce((obj, key) => { obj[key] = process.env[key]; return obj; @@ -62,44 +62,35 @@ module.exports = { module: { rules: [{ test: /growl\.js$/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /xunit\.js$/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /bunyan/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /@azure/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /IModelBankCloudEnv\.js$/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /DevTools\.js$/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /OidcDesktopClient\.js$/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /oidc-signin-tool/, - use: 'null-loader' - }, - { + use: "null-loader", + }, { test: /AzCopy\.js$/, - use: 'null-loader' - }, - ] + use: "null-loader", + }], }, node: { - process: false + process: false, }, externals: { "@bentley/imodeljs-native/package.json": "@bentley/imodeljs-native/package.json", @@ -114,11 +105,11 @@ module.exports = { "express": "express", }, stats: { - warnings: false + warnings: false, }, plugins: [ new webpack.DefinePlugin({ "global.location.search": "''" }), new webpack.ProvidePlugin({}), - new webpack.EnvironmentPlugin({}) + new webpack.EnvironmentPlugin({}), ], -} \ No newline at end of file +}; diff --git a/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json b/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d65fd79..c950192fe8ac 100644 --- a/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1,98 @@ { - "images" : [ + "images": [ { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "idiom": "iphone", + "size": "20x20", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "idiom": "iphone", + "size": "20x20", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "idiom": "iphone", + "size": "29x29", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "idiom": "iphone", + "size": "29x29", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "idiom": "iphone", + "size": "40x40", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "idiom": "iphone", + "size": "40x40", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "idiom": "iphone", + "size": "60x60", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "idiom": "iphone", + "size": "60x60", + "scale": "3x" }, { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "idiom": "ipad", + "size": "20x20", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "idiom": "ipad", + "size": "20x20", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "idiom": "ipad", + "size": "29x29", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "idiom": "ipad", + "size": "29x29", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "idiom": "ipad", + "size": "40x40", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "idiom": "ipad", + "size": "40x40", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "idiom": "ipad", + "size": "76x76", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "idiom": "ipad", + "size": "76x76", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "idiom": "ipad", + "size": "83.5x83.5", + "scale": "2x" }, { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" + "idiom": "ios-marketing", + "size": "1024x1024", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/Contents.json b/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/Contents.json index da4a164c9186..97a8662ebdb4 100644 --- a/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/Contents.json +++ b/core/mobile/src/test/ios/imodeljs-backend-test-app/imodeljs-backend-test-app/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/core/mobile/src/test/ios/runMochaTestsDirectly.js b/core/mobile/src/test/ios/runMochaTestsDirectly.js index efc677aed43b..d5ce718f19ad 100644 --- a/core/mobile/src/test/ios/runMochaTestsDirectly.js +++ b/core/mobile/src/test/ios/runMochaTestsDirectly.js @@ -10,7 +10,7 @@ require("mocha"); // puts the symbol "mocha" in global. require("chai"); // puts 'assert', etc. into global const configs = eval('require("./config.json");'); -process.env = {...process.env, ...configs}; +process.env = { ...process.env, ...configs }; const xunit = require("mocha/lib/reporters/xunit"); function MobileReporter(runner) { @@ -20,7 +20,7 @@ function MobileReporter(runner) { var failedTest = []; runner.stats = stats; function indent() { - return Array(indents).join(' '); + return Array(indents).join(" "); } function log(type, msg) { // Following send a event to UI and write the log message in a text view @@ -33,7 +33,7 @@ function MobileReporter(runner) { // remove \n from the front of the string let i = 0; - while (plainMsg[i] === '\n') { + while (plainMsg[i] === "\n") { i++; } plainMsg = plainMsg.substring(i); @@ -43,32 +43,33 @@ function MobileReporter(runner) { process.log("MOCHA ERROR", plainMsg); } } - runner.on('suite', function (suite) { + runner.on("suite", function(suite) { stats.suites = stats.suites || 0; if (suite.root) return; stats.suites++; log("info", `\n${indent()} λ ${suite.title}`); indents++; }); - runner.on('suite end', function (suite) { + runner.on("suite end", function(suite) { indents--; }); - runner.on('pending', function (test) { + runner.on("pending", function(test) { stats.pending++; }); - runner.on('test', function (test) { + runner.on("test", function(test) { }); - runner.on('pass', function (test) { + runner.on("pass", function(test) { stats.passes = stats.passes || 0; var medium = test.slow() / 2; - test.speed = - test.duration > test.slow() - ? 'slow' - : test.duration > medium ? 'medium' : 'fast'; + test.speed = test.duration > test.slow() + ? "slow" + : test.duration > medium + ? "medium" + : "fast"; stats.passes++; log("info", `${indent()} ✔ ${test.title} (${test.speed}) ${test.duration} ms`); }); - runner.on('fail', function (test, err) { + runner.on("fail", function(test, err) { stats.failures++; log("error", `${indent()} ✘ ${test.title}`); test.err = err; @@ -81,10 +82,10 @@ function MobileReporter(runner) { } failedTest.push(test); }); - runner.on('start', function () { - stats.start = new Date() + runner.on("start", function() { + stats.start = new Date(); }); - runner.on('end', function () { + runner.on("end", function() { stats.end = new Date(); stats.duration = (stats.end.getTime() - stats.start.getTime()) / 1000; log("info", `\n${stats.passes} Passes`); @@ -109,14 +110,13 @@ function MobileReporter(runner) { }); } - mocha.setup({ - ui: 'bdd', + ui: "bdd", reporter: MobileReporter, // WIP we need these arg to come from ios launchArguments timeout: 9999999, grep: require("./ignoreTest.js").join("|"), - invert: true + invert: true, }); // puts 'describe', 'it', etc. into global require("./IModelTestUtils.js"); @@ -124,4 +124,4 @@ require("./IModelTestUtils.js"); // following file is generated by npm script require("./ios-test-barrel.js"); -mocha.run(); \ No newline at end of file +mocha.run(); diff --git a/core/mobile/src/test/ios/scripts/checkAppCenterLogs.js b/core/mobile/src/test/ios/scripts/checkAppCenterLogs.js index 579683f96dc6..b7667f5ca9c9 100644 --- a/core/mobile/src/test/ios/scripts/checkAppCenterLogs.js +++ b/core/mobile/src/test/ios/scripts/checkAppCenterLogs.js @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -const https = require('https'); -const fs = require('fs'); -const es = require('event-stream'); -const path = require('path'); -const app_center_host = 'api.appcenter.ms'; +const https = require("https"); +const fs = require("fs"); +const es = require("event-stream"); +const path = require("path"); +const app_center_host = "api.appcenter.ms"; const app_center_api_ver = "v0.1"; const owner_name = process.argv[2]; // app_center_owner; -const app_name = process.argv[3]; //app_center_app; -const api_token = process.argv[4]; // app_center_token; +const app_name = process.argv[3]; // app_center_app; +const api_token = process.argv[4]; // app_center_token; const log_dir = path.join(findPackageRootDir(), "lib/test/ios"); const deviceLogFile = path.join(log_dir, "device.log"); const appLogFile = path.join(log_dir, "app.log"); @@ -61,23 +61,23 @@ async function getTestReportInfo(test_id) { const options = { host: app_center_host, path: `/${app_center_api_ver}/apps/${owner_name}/${app_name}/test_runs/${test_id}/report`, - method: 'GET', + method: "GET", headers: { - 'Content-Type': 'application/json; charset=utf-8', - 'X-API-Token': api_token, + "Content-Type": "application/json; charset=utf-8", + "X-API-Token": api_token, }, }; - const req = https.request(options, function (res) { - res.setEncoding('utf-8'); - let responseString = ''; + const req = https.request(options, function(res) { + res.setEncoding("utf-8"); + let responseString = ""; - res.on('data', (data) => { + res.on("data", (data) => { responseString += data; }); res.on("error", (err) => { reject(err); }); - res.on('end', () => { + res.on("end", () => { const responseObject = JSON.parse(responseString); resolve(responseObject); }); @@ -93,19 +93,19 @@ async function downloadTextFile(url, dest, cb) { console.info(`Downloading device log from app-center ${url}`); if (fs.existsSync(dest)) { // help full in debugging but not required on azure-ci-worker - fs.unlinkSync(dest) + fs.unlinkSync(dest); } const file = fs.createWriteStream(dest); - https.get(url, function (response) { + https.get(url, function(response) { response.pipe(file); - file.on('finish', () => { + file.on("finish", () => { console.info(`Device log saved to ${dest}`); file.close(cb); resolve(); }); - response.on('error', err => { + response.on("error", (err) => { reject(err); - }) + }); }); } catch (err) { reject(err); @@ -121,43 +121,44 @@ async function filterAppLog(loggerTest, inputLogFile, outputLogFile) { console.info(`Filtering out app log and writing it into ${outputLogFile}`); let logEntry = ""; let logPrefix = ""; - const f = fs.createWriteStream(outputLogFile) + const f = fs.createWriteStream(outputLogFile); const s = fs.createReadStream(inputLogFile) .pipe(es.split()) - .pipe(es.mapSync(function (line) { - s.pause(); - //Nov 6 21:50:28 iPad imodeljs-backend-test-app(libiModelJsHostM02.dylib)[235] :" - const m = line.match(/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\w+\s+([^\s]+)\s+[^\s]+:/); - if (m) { - const loggerName = m[2]; - if (loggerName.match(loggerTest)) { - if (logEntry !== "") { - f.write(logEntry + "\n", "utf-8"); + .pipe( + es.mapSync(function(line) { + s.pause(); + // Nov 6 21:50:28 iPad imodeljs-backend-test-app(libiModelJsHostM02.dylib)[235] :" + const m = line.match(/^(\w+\s+\d+\s+\d+:\d+:\d+)\s+\w+\s+([^\s]+)\s+[^\s]+:/); + if (m) { + const loggerName = m[2]; + if (loggerName.match(loggerTest)) { + if (logEntry !== "") { + f.write(logEntry + "\n", "utf-8"); + } } - } - logEntry = m[1] + ':' + line.substring(m[0].length); - logPrefix = " ".repeat(m[1].length + 2); - } else { - if (logEntry !== "") - logEntry += "\n" + logPrefix + line; - else - logEntry = line; - } - - // resume the readstream, possibly from a callback - s.resume(); - }) - .on('error', function (err) { - reject(err); - }) - .on('end', function () { - if (logEntry !== "") { - f.write(logEntry + "\n", "utf-8"); + logEntry = m[1] + ":" + line.substring(m[0].length); + logPrefix = " ".repeat(m[1].length + 2); + } else { + if (logEntry !== "") + logEntry += "\n" + logPrefix + line; + else + logEntry = line; } - f.close(); - resolve(); + + // resume the readstream, possibly from a callback + s.resume(); }) + .on("error", function(err) { + reject(err); + }) + .on("end", function() { + if (logEntry !== "") { + f.write(logEntry + "\n", "utf-8"); + } + f.close(); + resolve(); + }), ); }); } @@ -185,42 +186,43 @@ async function outputMochaLog(inputLogFile) { let loglevel = ""; const s = fs.createReadStream(inputLogFile) .pipe(es.split()) - .pipe(es.mapSync(function (line) { - s.pause(); - //Nov 6 21:50:28: MOCHA ERROR message" - //Nov 8 16:28:32: [MOCHA ERROR] [FAILED] ORed ECEnums + .pipe( + es.mapSync(function(line) { + s.pause(); + // Nov 6 21:50:28: MOCHA ERROR message" + // Nov 8 16:28:32: [MOCHA ERROR] [FAILED] ORed ECEnums - const m = line.match(/^\w+\s+\d+\s+\d+:\d+:\d+\s*:\s*\[MOCHA\s+(\w+)\]/i); - if (m) { - writeToConsole(loglevel, logEntry); - loglevel = m[1].toUpperCase(); - logEntry = line.substring(m[0].length); - } else { - if (line.match(/^\w+\s+\d+\s+\d+:\d+:\d+\s*:/i)) { - // ignore + const m = line.match(/^\w+\s+\d+\s+\d+:\d+:\d+\s*:\s*\[MOCHA\s+(\w+)\]/i); + if (m) { + writeToConsole(loglevel, logEntry); + loglevel = m[1].toUpperCase(); + logEntry = line.substring(m[0].length); } else { - if (logEntry !== "") - logEntry += "\n" + line; - else - logEntry = line; + if (line.match(/^\w+\s+\d+\s+\d+:\d+:\d+\s*:/i)) { + // ignore + } else { + if (logEntry !== "") + logEntry += "\n" + line; + else + logEntry = line; + } } - } - // resume the readstream, possibly from a callback - s.resume(); - }) - .on('error', function (err) { - reject(err); - }) - .on('end', function () { - writeToConsole(loglevel, logEntry); - resolve(); + // resume the readstream, possibly from a callback + s.resume(); }) + .on("error", function(err) { + reject(err); + }) + .on("end", function() { + writeToConsole(loglevel, logEntry); + resolve(); + }), ); }); } -(async function () { +(async function() { const test_id = getTestRunId(path.join(log_dir, "test_run.json")); const testReport = await getTestReportInfo(test_id); console.info(JSON.stringify(testReport, undefined, 2)); diff --git a/core/mobile/src/test/ios/scripts/generateTestBarrel.js b/core/mobile/src/test/ios/scripts/generateTestBarrel.js index 616d3c5a9397..5fe669870144 100644 --- a/core/mobile/src/test/ios/scripts/generateTestBarrel.js +++ b/core/mobile/src/test/ios/scripts/generateTestBarrel.js @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -const fs = require('fs'); -const path = require('path'); +const fs = require("fs"); +const path = require("path"); if (process.argv.length < 3) { console.info(`generateTestBarrel.js `); - process.exit(1);; + process.exit(1); } var testDir = process.argv[2]; -var barrelFile = process.argv[3] -var nTestFileFound = 0 +var barrelFile = process.argv[3]; +var nTestFileFound = 0; if (!fs.existsSync(testDir)) { console.error(`testDir ${testDir} must exist`); process.exit(1); @@ -29,16 +29,16 @@ function populateBarrel(fromDir) { var stat = fs.lstatSync(filename); if (stat.isDirectory()) { fs.appendFileSync(fileId, "\r\n"); - populateBarrel(filename, filter); //recurse + populateBarrel(filename, filter); // recurse } else if (filename.endsWith(filter)) { nTestFileFound++; fs.appendFileSync(fileId, `require("./${path.relative(testDir, filename).replace("\\/g", "/")}")\r\n`); - }; - }; + } + } } -populateBarrel(testDir) +populateBarrel(testDir); fs.appendFileSync(fileId, `\r\n// \r\n`); fs.closeSync(fileId); @@ -48,4 +48,4 @@ if (nTestFileFound < 1) { process.exit(1); } -console.log(`Barrel file created ${barrelFile}`); \ No newline at end of file +console.log(`Barrel file created ${barrelFile}`); diff --git a/core/mobile/src/test/ios/scripts/installIosNativeLib.js b/core/mobile/src/test/ios/scripts/installIosNativeLib.js index 42482d5d0f02..258d528c0743 100644 --- a/core/mobile/src/test/ios/scripts/installIosNativeLib.js +++ b/core/mobile/src/test/ios/scripts/installIosNativeLib.js @@ -41,7 +41,7 @@ function validatePackage() { } const currentPkgVer = require(path.join(currentPkgDir, "package.json")).version; if (semver.eq(currentPkgVer, requiredPkgVer, false)) { - console.log(`Already installed: @bentley/imodeljs-${os}-${platform}@${requiredPkgVer}`) + console.log(`Already installed: @bentley/imodeljs-${os}-${platform}@${requiredPkgVer}`); return true; } console.log(`Removing: @bentley/imodeljs-${os}-${platform}@${currentPkgVer}`); @@ -55,8 +55,8 @@ function validatePackage() { // Install the package if required if (!validatePackage()) { const installCmd = `npm`; - const args = [ `install`, `--no-save`, `--prefix`, `${targetPkgDir}`, `@bentley/imodeljs-${os}-${platform}@${requiredPkgVer}` ]; - console.log(`${installCmd} ${args.join(' ')}`); + const args = [`install`, `--no-save`, `--prefix`, `${targetPkgDir}`, `@bentley/imodeljs-${os}-${platform}@${requiredPkgVer}`]; + console.log(`${installCmd} ${args.join(" ")}`); execFile(installCmd, args, (error, stdout, stderr) => { if (error) throw error; diff --git a/core/orbitgt/eslint.config.js b/core/orbitgt/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/orbitgt/eslint.config.js +++ b/core/orbitgt/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/orbitgt/src/core-orbitgt.ts b/core/orbitgt/src/core-orbitgt.ts index e4a39b5226d0..dca432903cce 100644 --- a/core/orbitgt/src/core-orbitgt.ts +++ b/core/orbitgt/src/core-orbitgt.ts @@ -32,4 +32,4 @@ export * from "./system/runtime/Downloader"; // export * from "./system/runtime/DownloaderNode"; export * from "./system/runtime/DownloaderXhr"; export * from "./system/storage/PageCachedFile"; -export * from "./system/storage/UrlFS"; \ No newline at end of file +export * from "./system/storage/UrlFS"; diff --git a/core/orbitgt/src/pointcloud/format/opc/AttributeMask.ts b/core/orbitgt/src/pointcloud/format/opc/AttributeMask.ts index 36c3e259e287..95fc3b711dfe 100644 --- a/core/orbitgt/src/pointcloud/format/opc/AttributeMask.ts +++ b/core/orbitgt/src/pointcloud/format/opc/AttributeMask.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { AList } from "../../../system/collection/AList"; import { PointAttribute } from "../../model/PointAttribute"; import { AttributeReader } from "./AttributeReader"; @@ -27,35 +26,35 @@ import { FileReader } from "./FileReader"; */ /** @internal */ export class AttributeMask { - /** The definitions of the attributes */ - public attributes: Array; - /** The readers of the attributes */ - public readers: AList; + /** The definitions of the attributes */ + public attributes: Array; + /** The readers of the attributes */ + public readers: AList; - /** - * Create a new mask. - * @param readers the list of attribute readers (can be null). - */ - public constructor(readers: AList) { - /* Clear */ - this.attributes = null; - this.readers = null; - /* Do we have a list of readers? */ - if (readers != null) { - this.attributes = new Array(readers.size()); - for (let i: number = 0; i < this.attributes.length; i++) this.attributes[i] = readers.get(i).getAttribute(); - this.readers = readers; - } + /** + * Create a new mask. + * @param readers the list of attribute readers (can be null). + */ + public constructor(readers: AList) { + /* Clear */ + this.attributes = null; + this.readers = null; + /* Do we have a list of readers? */ + if (readers != null) { + this.attributes = new Array(readers.size()); + for (let i: number = 0; i < this.attributes.length; i++) this.attributes[i] = readers.get(i).getAttribute(); + this.readers = readers; } + } - /** - * Read all embedded attributes of a file. - * @param fileReader the file reader. - * @return the mask. - */ - public static readAllEmbedded(fileReader: FileReader): AttributeMask { - let readers: AList = new AList(); - for (let reader of fileReader.getStaticAttributeReaders()) readers.add(reader); - return new AttributeMask(readers); - } + /** + * Read all embedded attributes of a file. + * @param fileReader the file reader. + * @return the mask. + */ + public static readAllEmbedded(fileReader: FileReader): AttributeMask { + let readers: AList = new AList(); + for (let reader of fileReader.getStaticAttributeReaders()) readers.add(reader); + return new AttributeMask(readers); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/AttributeReader.ts b/core/orbitgt/src/pointcloud/format/opc/AttributeReader.ts index d4ed5267e1e6..1b64feedf257 100644 --- a/core/orbitgt/src/pointcloud/format/opc/AttributeReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/AttributeReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -30,53 +30,69 @@ import { TileReadBuffer } from "./TileReadBuffer"; */ /** @internal */ export abstract class AttributeReader { - /** - * Create a new reader. - */ - public constructor() { - } + /** + * Create a new reader. + */ + public constructor() { + } - /** - * Close the reader. - */ - public abstract close(): void; + /** + * Close the reader. + */ + public abstract close(): void; - /** - * Get the attribute. - * @return the attribute. - */ - public abstract getAttribute(): PointAttribute; + /** + * Get the attribute. + * @return the attribute. + */ + public abstract getAttribute(): PointAttribute; - /** - * Get the minimum value. - * @return the minimum value. - */ - public abstract getMinimumValue(): AttributeValue; + /** + * Get the minimum value. + * @return the minimum value. + */ + public abstract getMinimumValue(): AttributeValue; - /** - * Get the maximum value. - * @return the maximum value. - */ - public abstract getMaximumValue(): AttributeValue; + /** + * Get the maximum value. + * @return the maximum value. + */ + public abstract getMaximumValue(): AttributeValue; - /** - * Read the raw data for a tile. - * @param level the index of the level. - * @param tile the tile. - * @param tileBuffer the buffer to read into. - * @param bufferIndex the index of the attribute in the read buffer. - * @param readRequest the read parameters (contains the result read statistics). - */ - public abstract readTileData2(level: int32, tile: TileIndex, pointOffset: ALong, pointCount: int32, tileBuffer: TileReadBuffer, bufferIndex: int32, readRequest: ReadRequest, fileContents: ContentLoader): void; + /** + * Read the raw data for a tile. + * @param level the index of the level. + * @param tile the tile. + * @param tileBuffer the buffer to read into. + * @param bufferIndex the index of the attribute in the read buffer. + * @param readRequest the read parameters (contains the result read statistics). + */ + public abstract readTileData2( + level: int32, + tile: TileIndex, + pointOffset: ALong, + pointCount: int32, + tileBuffer: TileReadBuffer, + bufferIndex: int32, + readRequest: ReadRequest, + fileContents: ContentLoader, + ): void; - /** - * Get an attribute value. - * @param level the index of the level. - * @param tile the tile. - * @param tileBuffer the buffer that has been read. - * @param bufferIndex the index of the attribute in the read buffer. - * @param pointIndex the index of the point in the tile (starts at 0). - * @param cloudPoint the point to read the attribute of. - */ - public abstract getPointData(level: int32, tile: TileIndex, tileBuffer: TileReadBuffer, bufferIndex: int32, pointIndex: int32, cloudPoint: CloudPoint): void; + /** + * Get an attribute value. + * @param level the index of the level. + * @param tile the tile. + * @param tileBuffer the buffer that has been read. + * @param bufferIndex the index of the attribute in the read buffer. + * @param pointIndex the index of the point in the tile (starts at 0). + * @param cloudPoint the point to read the attribute of. + */ + public abstract getPointData( + level: int32, + tile: TileIndex, + tileBuffer: TileReadBuffer, + bufferIndex: int32, + pointIndex: int32, + cloudPoint: CloudPoint, + ): void; } diff --git a/core/orbitgt/src/pointcloud/format/opc/BlockRecord.ts b/core/orbitgt/src/pointcloud/format/opc/BlockRecord.ts index c71d3a19af50..3e28160ec529 100644 --- a/core/orbitgt/src/pointcloud/format/opc/BlockRecord.ts +++ b/core/orbitgt/src/pointcloud/format/opc/BlockRecord.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -29,69 +29,73 @@ import { GridIndex } from "../../model/GridIndex"; */ /** @internal */ export class BlockRecord { - /** The size of the record in the file */ - public static readonly RECORD_SIZE: int32 = 24; + /** The size of the record in the file */ + public static readonly RECORD_SIZE: int32 = 24; - /** - * No instances. - */ - private constructor() { - } + /** + * No instances. + */ + private constructor() { + } - /** - * Convert a tile grid index to a block grid index. - * @param tileIndex the tile index. - * @param blockSize the block size. - * @return the block index. - */ - public static toBlockIndex1(tileIndex: int32, blockSize: int32): int32 { - if (tileIndex < 0) return Numbers.divInt((tileIndex + 1), blockSize) - 1; - return Numbers.divInt(tileIndex, blockSize); - } + /** + * Convert a tile grid index to a block grid index. + * @param tileIndex the tile index. + * @param blockSize the block size. + * @return the block index. + */ + public static toBlockIndex1(tileIndex: int32, blockSize: int32): int32 { + if (tileIndex < 0) return Numbers.divInt(tileIndex + 1, blockSize) - 1; + return Numbers.divInt(tileIndex, blockSize); + } - /** - * Convert a tile grid index to a block grid index. - * @param tileX the x index of the tile. - * @param tileY the y index of the tile. - * @param tileZ the z index of the tile. - * @param blockSize the block size. - * @return the block index. - */ - public static toBlockIndex(tileX: int32, tileY: int32, tileZ: int32, blockSize: int32): GridIndex { - return new GridIndex(BlockRecord.toBlockIndex1(tileX, blockSize), BlockRecord.toBlockIndex1(tileY, blockSize), BlockRecord.toBlockIndex1(tileZ, blockSize)); - } + /** + * Convert a tile grid index to a block grid index. + * @param tileX the x index of the tile. + * @param tileY the y index of the tile. + * @param tileZ the z index of the tile. + * @param blockSize the block size. + * @return the block index. + */ + public static toBlockIndex(tileX: int32, tileY: int32, tileZ: int32, blockSize: int32): GridIndex { + return new GridIndex( + BlockRecord.toBlockIndex1(tileX, blockSize), + BlockRecord.toBlockIndex1(tileY, blockSize), + BlockRecord.toBlockIndex1(tileZ, blockSize), + ); + } - /** - * Write a record. - * @param output the output stream. - */ - public static write(block: BlockIndex, output: OutStream): void { - let blockX: int32 = block.gridIndex.x; - let blockY: int32 = block.gridIndex.y; - let blockZ: int32 = block.gridIndex.z; - LittleEndian.writeStreamInt(output, blockX); - LittleEndian.writeStreamInt(output, blockY); - LittleEndian.writeStreamInt(output, blockZ); - LittleEndian.writeStreamInt(output, block.tileCount); - LittleEndian.writeStreamLong(output, block.pointCount); - } + /** + * Write a record. + * @param output the output stream. + */ + public static write(block: BlockIndex, output: OutStream): void { + let blockX: int32 = block.gridIndex.x; + let blockY: int32 = block.gridIndex.y; + let blockZ: int32 = block.gridIndex.z; + LittleEndian.writeStreamInt(output, blockX); + LittleEndian.writeStreamInt(output, blockY); + LittleEndian.writeStreamInt(output, blockZ); + LittleEndian.writeStreamInt(output, block.tileCount); + LittleEndian.writeStreamLong(output, block.pointCount); + } - /** - * Read a record. - * @param level the level. - * @param in the input stream from the file. - * @param tileIndex the index of the tile. - * @param pointIndex the index of the first point in the block. - * @return the requested record. - */ - public static readNew(level: int32, input: InStream, blockIndex: int32, tileIndex: int32, pointIndex: ALong): BlockIndex { - /* Read the record */ - let blockX: int32 = LittleEndian.readStreamInt(input); - let blockY: int32 = LittleEndian.readStreamInt(input); - let blockZ: int32 = LittleEndian.readStreamInt(input); - let tileCount: int32 = LittleEndian.readStreamInt(input); - let pointCount: ALong = LittleEndian.readStreamLong(input); - /* Create the record */ - return new BlockIndex(level, blockIndex, new GridIndex(blockX, blockY, blockZ), tileIndex, tileCount, pointIndex, pointCount); - } + /** + * Read a record. + * @param level the level. + * @param in the input stream from the file. + * @param tileIndex the index of the tile. + * @param pointIndex the index of the first point in the block. + * @return the requested record. + */ + public static readNew(level: int32, input: InStream, blockIndex: int32, tileIndex: int32, pointIndex: ALong): BlockIndex { + /* Read the record */ + let blockX: int32 = LittleEndian.readStreamInt(input); + let blockY: int32 = LittleEndian.readStreamInt(input); + let blockZ: int32 = LittleEndian.readStreamInt(input); + let tileCount: int32 = LittleEndian.readStreamInt(input); + let pointCount: ALong = LittleEndian.readStreamLong(input); + /* Create the record */ + return new BlockIndex(level, blockIndex, new GridIndex(blockX, blockY, blockZ), tileIndex, tileCount, pointIndex, pointCount); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/ContainerFile.ts b/core/orbitgt/src/pointcloud/format/opc/ContainerFile.ts index 16bc664df63a..8d6cd9a6413a 100644 --- a/core/orbitgt/src/pointcloud/format/opc/ContainerFile.ts +++ b/core/orbitgt/src/pointcloud/format/opc/ContainerFile.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ABuffer } from "../../../system/buffer/ABuffer"; import { LittleEndian } from "../../../system/buffer/LittleEndian"; import { AList } from "../../../system/collection/AList"; @@ -35,186 +34,186 @@ import { FileAccess } from "./FileAccess"; */ /** @internal */ export class ContainerFile { - /** The name of this module */ - private static readonly MODULE: string = "ContainerFile"; - - /** The name of the file */ - private _fileName: string; - /** The length of the file */ - private _fileLength: ALong; - /** The format */ - private _format: string; - /** The parts in the file */ - private _parts: AList; - - /** - * Create a new container file. - * @param fileName the name of the file. - * @param fileLength the length of the file. - * @param format the format. - * @param parts the parts in the file. - */ - public constructor(fileName: string, fileLength: ALong, format: string, parts: AList) { - this._fileName = fileName; - this._fileLength = fileLength; - this._format = format; - this._parts = parts; + /** The name of this module */ + private static readonly MODULE: string = "ContainerFile"; + + /** The name of the file */ + private _fileName: string; + /** The length of the file */ + private _fileLength: ALong; + /** The format */ + private _format: string; + /** The parts in the file */ + private _parts: AList; + + /** + * Create a new container file. + * @param fileName the name of the file. + * @param fileLength the length of the file. + * @param format the format. + * @param parts the parts in the file. + */ + public constructor(fileName: string, fileLength: ALong, format: string, parts: AList) { + this._fileName = fileName; + this._fileLength = fileLength; + this._format = format; + this._parts = parts; + } + + /** + * Close the container file. + * @param closeFileAccess close all file access? + */ + public close(closeFileAccess: boolean): void { + if (closeFileAccess) { for (let i: number = 0; i < this._parts.size(); i++) this._parts.get(i).getFileAccess().close(); } + this._parts.clear(); + } + + /** + * Get the name of the file. + * @return the name of the file. + */ + public getFileName(): string { + return this._fileName; + } + + /** + * Get the length of the file. + * @return the length of the file. + */ + public getFileLength(): ALong { + return this._fileLength; + } + + /** + * Get the format. + * @return the format. + */ + public getFormat(): string { + return this._format; + } + + /** + * Get the number of parts. + * @return the number of parts. + */ + public getPartCount(): int32 { + return this._parts.size(); + } + + /** + * Get the list of parts. + * @return the list of parts. + */ + public getParts(): AList { + return this._parts; + } + + /** + * Get a part. + * @param name the name of the part. + * @return the part (null if not found). + */ + public getPart(name: string): ContainerFilePart { + /* Check all parts */ + for (let i: number = 0; i < this._parts.size(); i++) { + /* Check the next part */ + let part: ContainerFilePart = this._parts.get(i); + if (Strings.equals(part.getName(), name)) return part; } - - /** - * Close the container file. - * @param closeFileAccess close all file access? - */ - public close(closeFileAccess: boolean): void { - if (closeFileAccess) for (let i: number = 0; i < this._parts.size(); i++) this._parts.get(i).getFileAccess().close(); - this._parts.clear(); + /* Not found */ + return null; + } + + /** + * Check if the magic marker is found. + * @param input the input stream. + * @param format the 4-character identifier of the format. + * @return true if found, false if not. + */ + private static checkMarker(input: InStream, format: string): boolean { + let m0: int32 = LittleEndian.readStreamByte(input); + let m1: int32 = LittleEndian.readStreamByte(input); + let m2: int32 = LittleEndian.readStreamByte(input); + let m3: int32 = LittleEndian.readStreamByte(input); + if (m0 != Strings.getCharAt(format, 0)) return false; + if (m1 != Strings.getCharAt(format, 1)) return false; + if (m2 != Strings.getCharAt(format, 2)) return false; + if (m3 != Strings.getCharAt(format, 3)) return false; + return true; + } + + /** + * Read the parts of a container file. + * @param containerFileName the name of the container file. + * @param format the 4-character identifier of the format. + * @return the container file. + */ + public static async read(fileStorage: FileStorage, containerFileName: string, format: string): Promise { + /* Existing file? */ + Message.print(ContainerFile.MODULE, "Reading container file '" + containerFileName + "'"); + let fileLength: ALong = await fileStorage.getFileLength(containerFileName); + if (fileLength.isNegative()) { + /* Abort */ + Message.printWarning(ContainerFile.MODULE, "File not found"); + return null; } - - /** - * Get the name of the file. - * @return the name of the file. - */ - public getFileName(): string { - return this._fileName; + /* Too short? */ + if (fileLength.subInt(16).isNegative()) { + /* Fail */ + ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (too short)"); } - - /** - * Get the length of the file. - * @return the length of the file. - */ - public getFileLength(): ALong { - return this._fileLength; + /* Read the file header */ + let headerSize: int32 = 60 * 1024; + if (fileLength.subInt(headerSize).isNegative()) headerSize = fileLength.toInt(); + let header: ABuffer = await fileStorage.readFilePart(containerFileName, ALong.ZERO, headerSize); + let headerInput: ABufferInStream = new ABufferInStream(header, 0, header.size()); + /* Check the marker */ + if (ContainerFile.checkMarker(headerInput, format) == false) { + /* Fail */ + headerInput.close(); + ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (header marker)"); } - - /** - * Get the format. - * @return the format. - */ - public getFormat(): string { - return this._format; + /* Check the version */ + let version: int32 = LittleEndian.readStreamByte(headerInput); + if (version != 2) { + /* Fail */ + headerInput.close(); + ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (version " + version + ")"); } - - /** - * Get the number of parts. - * @return the number of parts. - */ - public getPartCount(): int32 { - return this._parts.size(); + /* Reserved */ + let r1: int32 = LittleEndian.readStreamByte(headerInput); + let r2: int32 = LittleEndian.readStreamByte(headerInput); + let r3: int32 = LittleEndian.readStreamByte(headerInput); + /* Get the file count */ + let fileCount: int32 = LittleEndian.readStreamInt(headerInput); + if (fileCount < 0) { + /* Fail */ + headerInput.close(); + ASystem.assert0(false, ContainerFile.MODULE + " : Invalid container file '" + containerFileName + "' (file count " + fileCount + ")"); } - - /** - * Get the list of parts. - * @return the list of parts. - */ - public getParts(): AList { - return this._parts; - } - - /** - * Get a part. - * @param name the name of the part. - * @return the part (null if not found). - */ - public getPart(name: string): ContainerFilePart { - /* Check all parts */ - for (let i: number = 0; i < this._parts.size(); i++) { - /* Check the next part */ - let part: ContainerFilePart = this._parts.get(i); - if (Strings.equals(part.getName(), name)) return part; - } - /* Not found */ - return null; - } - - /** - * Check if the magic marker is found. - * @param input the input stream. - * @param format the 4-character identifier of the format. - * @return true if found, false if not. - */ - private static checkMarker(input: InStream, format: string): boolean { - let m0: int32 = LittleEndian.readStreamByte(input); - let m1: int32 = LittleEndian.readStreamByte(input); - let m2: int32 = LittleEndian.readStreamByte(input); - let m3: int32 = LittleEndian.readStreamByte(input); - if (m0 != Strings.getCharAt(format, 0)) return false; - if (m1 != Strings.getCharAt(format, 1)) return false; - if (m2 != Strings.getCharAt(format, 2)) return false; - if (m3 != Strings.getCharAt(format, 3)) return false; - return true; - } - - /** - * Read the parts of a container file. - * @param containerFileName the name of the container file. - * @param format the 4-character identifier of the format. - * @return the container file. - */ - public static async read(fileStorage: FileStorage, containerFileName: string, format: string): Promise { - /* Existing file? */ - Message.print(ContainerFile.MODULE, "Reading container file '" + containerFileName + "'"); - let fileLength: ALong = await fileStorage.getFileLength(containerFileName); - if (fileLength.isNegative()) { - /* Abort */ - Message.printWarning(ContainerFile.MODULE, "File not found"); - return null; - } - /* Too short? */ - if (fileLength.subInt(16).isNegative()) { - /* Fail */ - ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (too short)"); - } - /* Read the file header */ - let headerSize: int32 = 60 * 1024; - if (fileLength.subInt(headerSize).isNegative()) headerSize = fileLength.toInt(); - let header: ABuffer = await fileStorage.readFilePart(containerFileName, ALong.ZERO, headerSize); - let headerInput: ABufferInStream = new ABufferInStream(header, 0, header.size()); - /* Check the marker */ - if (ContainerFile.checkMarker(headerInput, format) == false) { - /* Fail */ - headerInput.close(); - ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (header marker)"); - } - /* Check the version */ - let version: int32 = LittleEndian.readStreamByte(headerInput); - if (version != 2) { - /* Fail */ - headerInput.close(); - ASystem.assert0(false, "Invalid container file '" + containerFileName + "' (version " + version + ")"); - } - /* Reserved */ - let r1: int32 = LittleEndian.readStreamByte(headerInput); - let r2: int32 = LittleEndian.readStreamByte(headerInput); - let r3: int32 = LittleEndian.readStreamByte(headerInput); - /* Get the file count */ - let fileCount: int32 = LittleEndian.readStreamInt(headerInput); - if (fileCount < 0) { - /* Fail */ - headerInput.close(); - ASystem.assert0(false, ContainerFile.MODULE + " : Invalid container file '" + containerFileName + "' (file count " + fileCount + ")"); - } - /* Define the file access */ - let fileAccess: FileAccess = new FileAccess(fileStorage, containerFileName, fileLength); - /* Read the parts */ - let maxExtent: ALong = ALong.ZERO; - let parts: AList = new AList(); - for (let i: number = 0; i < fileCount; i++) { - /* Read the next file */ - let partOffset: ALong = LittleEndian.readStreamLong(headerInput); - let partLength: ALong = LittleEndian.readStreamLong(headerInput); - let partName: string = LittleEndian.readStreamString(headerInput); - /* Add the part */ - parts.add(new ContainerFilePart(partName, fileAccess, partOffset, partLength)); - Message.print(ContainerFile.MODULE, "Found part '" + partName + "' offset " + partOffset.toDouble() + " size " + partLength.toDouble()); - /* Update the maximum extent */ - let partExtent: ALong = partOffset.add(partLength); - maxExtent = ALong.max(maxExtent, partExtent); - } - /* Done */ - headerInput.close(); - /* Return the container */ - Message.print(ContainerFile.MODULE, "Found " + parts.size() + " parts, header size " + headerInput.getPosition()); - Message.print(ContainerFile.MODULE, "File size is " + fileLength.toDouble() + ", max part extent is " + maxExtent.toDouble()); - return new ContainerFile(containerFileName, fileLength, format, parts); + /* Define the file access */ + let fileAccess: FileAccess = new FileAccess(fileStorage, containerFileName, fileLength); + /* Read the parts */ + let maxExtent: ALong = ALong.ZERO; + let parts: AList = new AList(); + for (let i: number = 0; i < fileCount; i++) { + /* Read the next file */ + let partOffset: ALong = LittleEndian.readStreamLong(headerInput); + let partLength: ALong = LittleEndian.readStreamLong(headerInput); + let partName: string = LittleEndian.readStreamString(headerInput); + /* Add the part */ + parts.add(new ContainerFilePart(partName, fileAccess, partOffset, partLength)); + Message.print(ContainerFile.MODULE, "Found part '" + partName + "' offset " + partOffset.toDouble() + " size " + partLength.toDouble()); + /* Update the maximum extent */ + let partExtent: ALong = partOffset.add(partLength); + maxExtent = ALong.max(maxExtent, partExtent); } + /* Done */ + headerInput.close(); + /* Return the container */ + Message.print(ContainerFile.MODULE, "Found " + parts.size() + " parts, header size " + headerInput.getPosition()); + Message.print(ContainerFile.MODULE, "File size is " + fileLength.toDouble() + ", max part extent is " + maxExtent.toDouble()); + return new ContainerFile(containerFileName, fileLength, format, parts); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/ContainerFilePart.ts b/core/orbitgt/src/pointcloud/format/opc/ContainerFilePart.ts index bbbe4b3ce167..e42b04b948af 100644 --- a/core/orbitgt/src/pointcloud/format/opc/ContainerFilePart.ts +++ b/core/orbitgt/src/pointcloud/format/opc/ContainerFilePart.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ALong } from "../../../system/runtime/ALong"; import { ASystem } from "../../../system/runtime/ASystem"; import { FileAccess } from "./FileAccess"; @@ -26,74 +25,83 @@ import { FileAccess } from "./FileAccess"; */ /** @internal */ export class ContainerFilePart { - /** The name */ - private _name: string; - /** The file access */ - private _fileAccess: FileAccess; - /** The offset */ - private _offset: ALong; - /** The size */ - private _size: ALong; + /** The name */ + private _name: string; + /** The file access */ + private _fileAccess: FileAccess; + /** The offset */ + private _offset: ALong; + /** The size */ + private _size: ALong; - /** - * Create a new part. - * @param name the name of the part. - * @param fileAccess the file access. - * @param offset the offset of the part. - * @param size the size of the part. - */ - public constructor(name: string, fileAccess: FileAccess, offset: ALong, size: ALong) { - this._fileAccess = fileAccess; - this._offset = offset; - this._size = size; - this._name = name; - } + /** + * Create a new part. + * @param name the name of the part. + * @param fileAccess the file access. + * @param offset the offset of the part. + * @param size the size of the part. + */ + public constructor(name: string, fileAccess: FileAccess, offset: ALong, size: ALong) { + this._fileAccess = fileAccess; + this._offset = offset; + this._size = size; + this._name = name; + } - /** - * Get the name of the part. - * @return the name of the part. - */ - public getName(): string { - return this._name; - } + /** + * Get the name of the part. + * @return the name of the part. + */ + public getName(): string { + return this._name; + } - /** - * Get the file access. - * @return the file access. - */ - public getFileAccess(): FileAccess { - return this._fileAccess; - } + /** + * Get the file access. + * @return the file access. + */ + public getFileAccess(): FileAccess { + return this._fileAccess; + } - /** - * Get the offset of the part. - * @return the offset of the part. - */ - public getOffset(): ALong { - return this._offset; - } + /** + * Get the offset of the part. + * @return the offset of the part. + */ + public getOffset(): ALong { + return this._offset; + } - /** - * Get the size of the part. - * @return the size of the part. - */ - public getSize(): ALong { - return this._size; - } + /** + * Get the size of the part. + * @return the size of the part. + */ + public getSize(): ALong { + return this._size; + } - /** - * Do a range check for this part. - * @param checkOffset the offset of the range we want to touch. - * @param checkSize the size of the range we want to touch. - */ - public rangeCheck(checkOffset: ALong, checkSize: ALong): void { - let checkExtent: ALong = checkOffset.add(checkSize); - let extent: ALong = this._offset.add(this._size); - ASystem.assertNot(checkOffset.sub(this._offset).isNegative(), "Range offset " + checkOffset.toString() + " falls before part " + this._offset.toString() + ".." + extent.toString()); - ASystem.assertNot(extent.sub(checkOffset).isNegative(), "Range offset " + checkOffset.toString() + " falls after part " + this._offset.toString() + ".." + extent.toString()); - ASystem.assertNot(checkSize.isNegative(), "Range size " + checkSize.toString() + " is negative"); - ASystem.assertNot(extent.sub(checkExtent).isNegative(), "Range extent " + checkExtent.toString() + " falls after part " + this._offset.toString() + ".." + extent.toString()); - } + /** + * Do a range check for this part. + * @param checkOffset the offset of the range we want to touch. + * @param checkSize the size of the range we want to touch. + */ + public rangeCheck(checkOffset: ALong, checkSize: ALong): void { + let checkExtent: ALong = checkOffset.add(checkSize); + let extent: ALong = this._offset.add(this._size); + ASystem.assertNot( + checkOffset.sub(this._offset).isNegative(), + "Range offset " + checkOffset.toString() + " falls before part " + this._offset.toString() + ".." + extent.toString(), + ); + ASystem.assertNot( + extent.sub(checkOffset).isNegative(), + "Range offset " + checkOffset.toString() + " falls after part " + this._offset.toString() + ".." + extent.toString(), + ); + ASystem.assertNot(checkSize.isNegative(), "Range size " + checkSize.toString() + " is negative"); + ASystem.assertNot( + extent.sub(checkExtent).isNegative(), + "Range extent " + checkExtent.toString() + " falls after part " + this._offset.toString() + ".." + extent.toString(), + ); + } } -//ContainerFilePart.java +// ContainerFilePart.java diff --git a/core/orbitgt/src/pointcloud/format/opc/DirectoryReader.ts b/core/orbitgt/src/pointcloud/format/opc/DirectoryReader.ts index 104177c48204..0c15fa27f709 100644 --- a/core/orbitgt/src/pointcloud/format/opc/DirectoryReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/DirectoryReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -38,164 +38,170 @@ import { TileRecord } from "./TileRecord"; */ /** @internal */ export class DirectoryReader { - /** The file reader */ - private _fileReader: FileReader; - /** The level */ - private _level: int32; + /** The file reader */ + private _fileReader: FileReader; + /** The level */ + private _level: int32; - /** The location of the tile directory */ - private _tileDirPart: ContainerFilePart; - /** The location of the block directory */ - private _blockDirPart: ContainerFilePart; + /** The location of the tile directory */ + private _tileDirPart: ContainerFilePart; + /** The location of the block directory */ + private _blockDirPart: ContainerFilePart; - /** The directory record */ - private _directoryRecord: DirectoryRecord; - /** The blocks (lazy loading) */ - private _blocks: Array; + /** The directory record */ + private _directoryRecord: DirectoryRecord; + /** The blocks (lazy loading) */ + private _blocks: Array; - /** - * Create a new reader. - * @param fileReader the file reader. - * @param level the level. - */ - public constructor(fileReader: FileReader, level: int32) { - /* Store the parameters */ - this._fileReader = fileReader; - this._level = level; - /* Get the tile directory */ - this._tileDirPart = fileReader.getContainer().getPart("" + level + ".tile.directory"); - /* Get the block directory */ - this._blockDirPart = fileReader.getContainer().getPart("" + level + ".block.directory"); - /* Clear */ - this._directoryRecord = null; - this._blocks = new Array(0); - } + /** + * Create a new reader. + * @param fileReader the file reader. + * @param level the level. + */ + public constructor(fileReader: FileReader, level: int32) { + /* Store the parameters */ + this._fileReader = fileReader; + this._level = level; + /* Get the tile directory */ + this._tileDirPart = fileReader.getContainer().getPart("" + level + ".tile.directory"); + /* Get the block directory */ + this._blockDirPart = fileReader.getContainer().getPart("" + level + ".block.directory"); + /* Clear */ + this._directoryRecord = null; + this._blocks = new Array(0); + } - /** - * Get the directory record. - * @return the directory record. - */ - public getDirectoryRecord(): DirectoryRecord { - return this._directoryRecord; - } + /** + * Get the directory record. + * @return the directory record. + */ + public getDirectoryRecord(): DirectoryRecord { + return this._directoryRecord; + } - /** - * Get the blocks. - * @return the blocks. - */ - public getBlocks(): Array { - return this._blocks; - } + /** + * Get the blocks. + * @return the blocks. + */ + public getBlocks(): Array { + return this._blocks; + } - /** - * Load the data. - * @param readBlockList should the list of blocks be read? - * @param fileContents the file content read helper. - * @return the reader. - */ - public loadData(readBlockList: boolean, fileContents: ContentLoader): DirectoryReader { - /* Read the record */ - let directoryPart: ContainerFilePart = this._fileReader.getContainer().getPart("" + this._level + ".directory"); - this._directoryRecord = DirectoryRecord.readNew(directoryPart.getOffset(), directoryPart.getSize(), fileContents); - /* Read the blocks? */ - if (readBlockList) this.readBlocks(this._fileReader.getFileRecord(), fileContents); - /* Return the reader */ - return this; - } + /** + * Load the data. + * @param readBlockList should the list of blocks be read? + * @param fileContents the file content read helper. + * @return the reader. + */ + public loadData(readBlockList: boolean, fileContents: ContentLoader): DirectoryReader { + /* Read the record */ + let directoryPart: ContainerFilePart = this._fileReader.getContainer().getPart("" + this._level + ".directory"); + this._directoryRecord = DirectoryRecord.readNew(directoryPart.getOffset(), directoryPart.getSize(), fileContents); + /* Read the blocks? */ + if (readBlockList) this.readBlocks(this._fileReader.getFileRecord(), fileContents); + /* Return the reader */ + return this; + } - /** - * Read the blocks. - * @param fileRecord the file record. - * @param fileContents the file content read helper. - * @return the blocks. - */ - public readBlocks(fileRecord: FileRecord, fileContents: ContentLoader): Array { - /* Request the data? */ - let fileAccess: FileAccess = this._blockDirPart.getFileAccess(); - if (fileContents.isAvailable() == false) { - /* Add the range */ - fileContents.requestFilePart(this._blockDirPart.getOffset(), this._blockDirPart.getSize().toInt()); - return null; - } - /* Get the data */ - let data: ABuffer = fileContents.getFilePart(this._blockDirPart.getOffset(), this._blockDirPart.getSize().toInt()); - /* Allocate the blocks */ - this._blocks = new Array(this._directoryRecord.getBlockCount()); - /* Read all blocks */ - let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); - let pointIndex: ALong = ALong.ZERO; - let tileIndex: int32 = 0; - for (let i: number = 0; i < this._blocks.length; i++) { - /* Read the next block */ - let blockIndex: BlockIndex = BlockRecord.readNew(this._level, input, i, tileIndex, pointIndex); - this._blocks[i] = blockIndex; - /* Advance */ - tileIndex += blockIndex.tileCount; - pointIndex = pointIndex.add(blockIndex.pointCount); - } - input.close(); - /* We have to match the counts */ - ASystem.assert0(this._directoryRecord.getTileCount() == tileIndex, "Expected " + this._directoryRecord.getTileCount() + " tiles, not " + tileIndex); - ASystem.assert0(pointIndex.same(this._directoryRecord.getPointCount()), "Expected " + this._directoryRecord.getPointCount().toDouble() + " points, not " + pointIndex.toDouble()); - /* Return the blocks */ - return this._blocks; + /** + * Read the blocks. + * @param fileRecord the file record. + * @param fileContents the file content read helper. + * @return the blocks. + */ + public readBlocks(fileRecord: FileRecord, fileContents: ContentLoader): Array { + /* Request the data? */ + let fileAccess: FileAccess = this._blockDirPart.getFileAccess(); + if (fileContents.isAvailable() == false) { + /* Add the range */ + fileContents.requestFilePart(this._blockDirPart.getOffset(), this._blockDirPart.getSize().toInt()); + return null; + } + /* Get the data */ + let data: ABuffer = fileContents.getFilePart(this._blockDirPart.getOffset(), this._blockDirPart.getSize().toInt()); + /* Allocate the blocks */ + this._blocks = new Array(this._directoryRecord.getBlockCount()); + /* Read all blocks */ + let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); + let pointIndex: ALong = ALong.ZERO; + let tileIndex: int32 = 0; + for (let i: number = 0; i < this._blocks.length; i++) { + /* Read the next block */ + let blockIndex: BlockIndex = BlockRecord.readNew(this._level, input, i, tileIndex, pointIndex); + this._blocks[i] = blockIndex; + /* Advance */ + tileIndex += blockIndex.tileCount; + pointIndex = pointIndex.add(blockIndex.pointCount); } + input.close(); + /* We have to match the counts */ + ASystem.assert0( + this._directoryRecord.getTileCount() == tileIndex, + "Expected " + this._directoryRecord.getTileCount() + " tiles, not " + tileIndex, + ); + ASystem.assert0( + pointIndex.same(this._directoryRecord.getPointCount()), + "Expected " + this._directoryRecord.getPointCount().toDouble() + " points, not " + pointIndex.toDouble(), + ); + /* Return the blocks */ + return this._blocks; + } - /** - * Read the tiles of a block. - * @param block the block record. - * @return the tile records. - */ - public readTiles2(block: BlockIndex, fileContents: ContentLoader): Array { - /* Get the tile range */ - let tileIndex: int32 = block.tileIndex; - let tileCount: int32 = block.tileCount; - /* Get the file extent */ - let fileName: string = this._tileDirPart.getFileAccess().getFileName(); - let fileSize: ALong = this._fileReader.getContainer().getFileLength(); - let dataOffset: ALong = ALong.fromInt(TileRecord.RECORD_SIZE).mulInt(tileIndex).add(this._tileDirPart.getOffset()); - let dataSize: int32 = tileCount * TileRecord.RECORD_SIZE; - /* Request the data? */ - if (fileContents.isAvailable() == false) { - /* Add the range */ - fileContents.requestFilePart(dataOffset, dataSize); - return null; - } - /* Get the data */ - let data: ABuffer = fileContents.getFilePart(dataOffset, dataSize); - /* Read the tiles */ - let tiles: Array = new Array(tileCount); - let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); - let pointIndex: ALong = block.pointIndex; - for (let i: number = 0; i < tileCount; i++) { - /* Read the next tile */ - let tile: TileIndex = new TileIndex(this._level, tileIndex, new GridIndex(0, 0, 0), ALong.ZERO, 0); - TileRecord.read(tile, this._level, block.index, input, tileIndex, pointIndex); - tiles[i] = tile; - tileIndex += 1; - pointIndex = pointIndex.addInt(tile.pointCount); - } - input.close(); - /* Return the tiles */ - return tiles; + /** + * Read the tiles of a block. + * @param block the block record. + * @return the tile records. + */ + public readTiles2(block: BlockIndex, fileContents: ContentLoader): Array { + /* Get the tile range */ + let tileIndex: int32 = block.tileIndex; + let tileCount: int32 = block.tileCount; + /* Get the file extent */ + let fileName: string = this._tileDirPart.getFileAccess().getFileName(); + let fileSize: ALong = this._fileReader.getContainer().getFileLength(); + let dataOffset: ALong = ALong.fromInt(TileRecord.RECORD_SIZE).mulInt(tileIndex).add(this._tileDirPart.getOffset()); + let dataSize: int32 = tileCount * TileRecord.RECORD_SIZE; + /* Request the data? */ + if (fileContents.isAvailable() == false) { + /* Add the range */ + fileContents.requestFilePart(dataOffset, dataSize); + return null; + } + /* Get the data */ + let data: ABuffer = fileContents.getFilePart(dataOffset, dataSize); + /* Read the tiles */ + let tiles: Array = new Array(tileCount); + let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); + let pointIndex: ALong = block.pointIndex; + for (let i: number = 0; i < tileCount; i++) { + /* Read the next tile */ + let tile: TileIndex = new TileIndex(this._level, tileIndex, new GridIndex(0, 0, 0), ALong.ZERO, 0); + TileRecord.read(tile, this._level, block.index, input, tileIndex, pointIndex); + tiles[i] = tile; + tileIndex += 1; + pointIndex = pointIndex.addInt(tile.pointCount); } + input.close(); + /* Return the tiles */ + return tiles; + } - /** - * Get all tile indexes at this level. - * @param tileFilter the optional tile filter. - * @param selectionType the type of selection in the pointcloud. - * @return the list of tiles. - */ - public getAllTileIndexes2(fileContents: ContentLoader): AList { - /* Process all blocks */ - let tileList: AList = new AList(); - for (let block of this._blocks) { - /* Read the tiles */ - let tiles: Array = this.readTiles2(block, fileContents); - /* Add all tiles */ - for (let tile of tiles) tileList.add(tile); - } - /* Return the list of tiles */ - return tileList; + /** + * Get all tile indexes at this level. + * @param tileFilter the optional tile filter. + * @param selectionType the type of selection in the pointcloud. + * @return the list of tiles. + */ + public getAllTileIndexes2(fileContents: ContentLoader): AList { + /* Process all blocks */ + let tileList: AList = new AList(); + for (let block of this._blocks) { + /* Read the tiles */ + let tiles: Array = this.readTiles2(block, fileContents); + /* Add all tiles */ + for (let tile of tiles) tileList.add(tile); } + /* Return the list of tiles */ + return tileList; + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/DirectoryRecord.ts b/core/orbitgt/src/pointcloud/format/opc/DirectoryRecord.ts index 58540c737af1..e1e3253f9c7d 100644 --- a/core/orbitgt/src/pointcloud/format/opc/DirectoryRecord.ts +++ b/core/orbitgt/src/pointcloud/format/opc/DirectoryRecord.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -27,86 +27,86 @@ import { ContentLoader } from "../../../system/storage/ContentLoader"; */ /** @internal */ export class DirectoryRecord { - /** The number of points (8 byte) */ - private _pointCount: ALong; - /** The number of tiles (4 byte) */ - private _tileCount: int32; - /** The number of blocks (4 byte) */ - private _blockCount: int32; + /** The number of points (8 byte) */ + private _pointCount: ALong; + /** The number of tiles (4 byte) */ + private _tileCount: int32; + /** The number of blocks (4 byte) */ + private _blockCount: int32; - /** - * Create a new record. - */ - public constructor(pointCount: ALong, tileCount: int32, blockCount: int32) { - this._pointCount = pointCount; - this._tileCount = tileCount; - this._blockCount = blockCount; - } + /** + * Create a new record. + */ + public constructor(pointCount: ALong, tileCount: int32, blockCount: int32) { + this._pointCount = pointCount; + this._tileCount = tileCount; + this._blockCount = blockCount; + } - /** - * Get the number of points. - * @return the number. - */ - public getPointCount(): ALong { - return this._pointCount; - } + /** + * Get the number of points. + * @return the number. + */ + public getPointCount(): ALong { + return this._pointCount; + } - /** - * Get the number of tiles. - * @return the number. - */ - public getTileCount(): int32 { - return this._tileCount; - } + /** + * Get the number of tiles. + * @return the number. + */ + public getTileCount(): int32 { + return this._tileCount; + } - /** - * Get the number of blocks. - * @return the number. - */ - public getBlockCount(): int32 { - return this._blockCount; - } + /** + * Get the number of blocks. + * @return the number. + */ + public getBlockCount(): int32 { + return this._blockCount; + } - /** - * Read a record. - * @param data the record data. - * @return the record. - */ - private static readFromBuffer(data: ABuffer): DirectoryRecord { - /* Get the record fields */ - let pointCount: ALong = LittleEndian.readBufferLong(data, 0); - let tileCount: int32 = LittleEndian.readBufferInt(data, 8); - let blockCount: int32 = LittleEndian.readBufferInt(data, 12); - /* Return the record */ - return new DirectoryRecord(pointCount, tileCount, blockCount); - } + /** + * Read a record. + * @param data the record data. + * @return the record. + */ + private static readFromBuffer(data: ABuffer): DirectoryRecord { + /* Get the record fields */ + let pointCount: ALong = LittleEndian.readBufferLong(data, 0); + let tileCount: int32 = LittleEndian.readBufferInt(data, 8); + let blockCount: int32 = LittleEndian.readBufferInt(data, 12); + /* Return the record */ + return new DirectoryRecord(pointCount, tileCount, blockCount); + } - /** - * Read a record. - * @param offset the file offset to the record. - * @param size the file size to the record. - * @return the record. - */ - public static readNew(offset: ALong, size: ALong, contentLoader: ContentLoader): DirectoryRecord { - /* Request the data? */ - if (contentLoader.isLoaded() == false) { - /* Add the range */ - contentLoader.requestFilePart(offset, size.toInt()); - return null; - } - /* Get the data */ - let data: ABuffer = contentLoader.getFilePart(offset, size.toInt()); - /* Parse the record */ - return DirectoryRecord.readFromBuffer(data); + /** + * Read a record. + * @param offset the file offset to the record. + * @param size the file size to the record. + * @return the record. + */ + public static readNew(offset: ALong, size: ALong, contentLoader: ContentLoader): DirectoryRecord { + /* Request the data? */ + if (contentLoader.isLoaded() == false) { + /* Add the range */ + contentLoader.requestFilePart(offset, size.toInt()); + return null; } + /* Get the data */ + let data: ABuffer = contentLoader.getFilePart(offset, size.toInt()); + /* Parse the record */ + return DirectoryRecord.readFromBuffer(data); + } - /** - * Write the record. - * @param output the output stream. - */ - public write(output: OutStream): void { - LittleEndian.writeStreamLong(output, this._pointCount); - LittleEndian.writeStreamInt(output, this._tileCount); - LittleEndian.writeStreamInt(output, this._blockCount); - } + /** + * Write the record. + * @param output the output stream. + */ + public write(output: OutStream): void { + LittleEndian.writeStreamLong(output, this._pointCount); + LittleEndian.writeStreamInt(output, this._tileCount); + LittleEndian.writeStreamInt(output, this._blockCount); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/EmbeddedAttributeReader.ts b/core/orbitgt/src/pointcloud/format/opc/EmbeddedAttributeReader.ts index 9bdf8b9b9184..0ab5357d8ed3 100644 --- a/core/orbitgt/src/pointcloud/format/opc/EmbeddedAttributeReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/EmbeddedAttributeReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ABuffer } from "../../../system/buffer/ABuffer"; import { LittleEndian } from "../../../system/buffer/LittleEndian"; import { ABufferInStream } from "../../../system/io/ABufferInStream"; @@ -40,203 +39,219 @@ import { TileReadBuffer } from "./TileReadBuffer"; */ /** @internal */ export class EmbeddedAttributeReader extends AttributeReader { - /** The container */ - private _container: ContainerFile; - /** The index */ - private _index: int32; - /** The number of levels */ - private _levelCount: int32; - - /** The definition of the attribute */ - private _attribute: PointAttribute; - /** The value range of the attribute */ - private _minValue: AttributeValue; - private _maxValue: AttributeValue; - /** Is this the legacy color attribute? */ - private _standardColor: boolean; - /** Is this the legacy intensity attribute? */ - private _standardIntensity: boolean; - - /** The point-attribute data parts (one per level) */ - private _pointDataParts: Array; - /** The block-attribute data parts (one per level) */ - private _blockDataParts: Array; - /** The tile-attribute data parts (one per level) */ - private _tileDataParts: Array; - - /** - * Create a new reader. - * @param container the container. - * @param index the index. - * @param levelCount the number of levels. - */ - public constructor(container: ContainerFile, index: int32, levelCount: int32) { - super(); - /* Store the parameters */ - this._container = container; - this._index = index; - this._levelCount = levelCount; - /* Clear */ - this._attribute = null; - this._minValue = null; - this._maxValue = null; - this._standardColor = false; - this._standardIntensity = false; - /* Find the data parts */ - this._pointDataParts = new Array(levelCount); - this._blockDataParts = new Array(levelCount); - this._tileDataParts = new Array(levelCount); - for (let i: number = 0; i < levelCount; i++) this._pointDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".pointdata"); - for (let i: number = 0; i < levelCount; i++) this._blockDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".blockdata"); - for (let i: number = 0; i < levelCount; i++) this._tileDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".tiledata"); - } + /** The container */ + private _container: ContainerFile; + /** The index */ + private _index: int32; + /** The number of levels */ + private _levelCount: int32; - /** - * Read the attribute information. - * @param data the attribute data. - */ - private readAttribute(data: ABuffer): void { - /* Read the definition */ - this._minValue = new AttributeValue(); - this._maxValue = new AttributeValue(); - let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); - this._attribute = EmbeddedAttributeReader.readDefinition(input, this._minValue, this._maxValue); - input.close(); - /* Standard attribute? */ - this._standardColor = (StandardAttributes.COLOR.hasName(this._attribute.getName())); - if (this._standardColor) this._attribute.setStandardAttribute(true); - this._standardIntensity = (StandardAttributes.INTENSITY.hasName(this._attribute.getName())); - if (this._standardIntensity) this._attribute.setStandardAttribute(true); - } + /** The definition of the attribute */ + private _attribute: PointAttribute; + /** The value range of the attribute */ + private _minValue: AttributeValue; + private _maxValue: AttributeValue; + /** Is this the legacy color attribute? */ + private _standardColor: boolean; + /** Is this the legacy intensity attribute? */ + private _standardIntensity: boolean; - /** - * Load the data. - * @return the reader. - */ - public loadData(fileContents: ContentLoader): EmbeddedAttributeReader { - /* Get the part */ - let definitionPart: ContainerFilePart = this._container.getPart("attribute." + this._index + ".definition"); - let fileAccess: FileAccess = definitionPart.getFileAccess(); - /* Request the data? */ - if (fileContents.isAvailable() == false) { - /* Add the range */ - fileContents.requestFilePart(definitionPart.getOffset(), definitionPart.getSize().toInt()); - return null; - } - /* Get the data */ - let data: ABuffer = fileContents.getFilePart(definitionPart.getOffset(), definitionPart.getSize().toInt()); - /* Read the attribute */ - this.readAttribute(data); - /* Return the reader */ - return this; - } + /** The point-attribute data parts (one per level) */ + private _pointDataParts: Array; + /** The block-attribute data parts (one per level) */ + private _blockDataParts: Array; + /** The tile-attribute data parts (one per level) */ + private _tileDataParts: Array; - /** - * AttributeReader abstract method. - * @see AttributeReader#close - */ - public close(): void { - } + /** + * Create a new reader. + * @param container the container. + * @param index the index. + * @param levelCount the number of levels. + */ + public constructor(container: ContainerFile, index: int32, levelCount: int32) { + super(); + /* Store the parameters */ + this._container = container; + this._index = index; + this._levelCount = levelCount; + /* Clear */ + this._attribute = null; + this._minValue = null; + this._maxValue = null; + this._standardColor = false; + this._standardIntensity = false; + /* Find the data parts */ + this._pointDataParts = new Array(levelCount); + this._blockDataParts = new Array(levelCount); + this._tileDataParts = new Array(levelCount); + for (let i: number = 0; i < levelCount; i++) this._pointDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".pointdata"); + for (let i: number = 0; i < levelCount; i++) this._blockDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".blockdata"); + for (let i: number = 0; i < levelCount; i++) this._tileDataParts[i] = container.getPart("" + i + ".attribute." + this._index + ".tiledata"); + } - /** - * Get the container. - * @return the container. - */ - public getContainer(): ContainerFile { - return this._container; - } + /** + * Read the attribute information. + * @param data the attribute data. + */ + private readAttribute(data: ABuffer): void { + /* Read the definition */ + this._minValue = new AttributeValue(); + this._maxValue = new AttributeValue(); + let input: ABufferInStream = new ABufferInStream(data, 0, data.size()); + this._attribute = EmbeddedAttributeReader.readDefinition(input, this._minValue, this._maxValue); + input.close(); + /* Standard attribute? */ + this._standardColor = StandardAttributes.COLOR.hasName(this._attribute.getName()); + if (this._standardColor) this._attribute.setStandardAttribute(true); + this._standardIntensity = StandardAttributes.INTENSITY.hasName(this._attribute.getName()); + if (this._standardIntensity) this._attribute.setStandardAttribute(true); + } - /** - * Get the index. - * @return the index. - */ - public getIndex(): int32 { - return this._index; + /** + * Load the data. + * @return the reader. + */ + public loadData(fileContents: ContentLoader): EmbeddedAttributeReader { + /* Get the part */ + let definitionPart: ContainerFilePart = this._container.getPart("attribute." + this._index + ".definition"); + let fileAccess: FileAccess = definitionPart.getFileAccess(); + /* Request the data? */ + if (fileContents.isAvailable() == false) { + /* Add the range */ + fileContents.requestFilePart(definitionPart.getOffset(), definitionPart.getSize().toInt()); + return null; } + /* Get the data */ + let data: ABuffer = fileContents.getFilePart(definitionPart.getOffset(), definitionPart.getSize().toInt()); + /* Read the attribute */ + this.readAttribute(data); + /* Return the reader */ + return this; + } - /** - * Read the definition of the attribute. - */ - public static readDefinition(input: InStream, minValue: AttributeValue, maxValue: AttributeValue): PointAttribute { - /* Read the definition */ - let name: string = LittleEndian.readStreamString(input); - let description: string = LittleEndian.readStreamString(input); - let type: int32 = LittleEndian.readStreamInt(input); - let defaultValue: AttributeValue = AttributeValue.readFromStream(input, type); - let attribute: PointAttribute = new PointAttribute(name, description, type, defaultValue); - /* Read the value range */ - let minValue2: AttributeValue = AttributeValue.readFromStream(input, type); - minValue2.copyTo(minValue); - let maxValue2: AttributeValue = AttributeValue.readFromStream(input, type); - maxValue2.copyTo(maxValue); - /* Return the attribute */ - return attribute; - } + /** + * AttributeReader abstract method. + * @see AttributeReader#close + */ + public close(): void { + } - /** - * AttributeReader abstract method. - * @see AttributeReader#getAttribute - */ - public getAttribute(): PointAttribute { - return this._attribute; - } + /** + * Get the container. + * @return the container. + */ + public getContainer(): ContainerFile { + return this._container; + } - /** - * AttributeReader abstract method. - * @see AttributeReader#getMinimumValue - */ - public getMinimumValue(): AttributeValue { - return this._minValue; - } + /** + * Get the index. + * @return the index. + */ + public getIndex(): int32 { + return this._index; + } - /** - * AttributeReader abstract method. - * @see AttributeReader#getMaximumValue - */ - public getMaximumValue(): AttributeValue { - return this._maxValue; - } + /** + * Read the definition of the attribute. + */ + public static readDefinition(input: InStream, minValue: AttributeValue, maxValue: AttributeValue): PointAttribute { + /* Read the definition */ + let name: string = LittleEndian.readStreamString(input); + let description: string = LittleEndian.readStreamString(input); + let type: int32 = LittleEndian.readStreamInt(input); + let defaultValue: AttributeValue = AttributeValue.readFromStream(input, type); + let attribute: PointAttribute = new PointAttribute(name, description, type, defaultValue); + /* Read the value range */ + let minValue2: AttributeValue = AttributeValue.readFromStream(input, type); + minValue2.copyTo(minValue); + let maxValue2: AttributeValue = AttributeValue.readFromStream(input, type); + maxValue2.copyTo(maxValue); + /* Return the attribute */ + return attribute; + } - /** - * AttributeReader abstract method. - * @see AttributeReader#readTileData2 - */ - public readTileData2(level: int32, tile: TileIndex, pointOffset: ALong, pointCount: int32, tileBuffer: TileReadBuffer, bufferIndex: int32, readRequest: ReadRequest, fileContents: ContentLoader): void { - /* Get the right part */ - let pointDataPart: ContainerFilePart = this._pointDataParts[level]; - /* Get the file extent */ - let fileName: string = pointDataPart.getFileAccess().getFileName(); - let fileSize: ALong = this._container.getFileLength(); - let offset: ALong = pointDataPart.getOffset().add(this._attribute.getTypeByteSizeForLongCount(tile.pointIndex.add(pointOffset))); - let size: int32 = this._attribute.getTypeByteSizeForCount(pointCount); - pointDataPart.rangeCheck(offset, ALong.fromInt(size)); - /* Request the data? */ - if (fileContents.isAvailable() == false) { - /* Add the range */ - fileContents.requestFilePart(offset, size); - return; - } - /* Add the statistics */ - readRequest.addDataSize(size); - /* Read the content */ - let data: ABuffer = fileContents.getFilePart(offset, size); - tileBuffer.setAttributeBuffer(bufferIndex, data); - } + /** + * AttributeReader abstract method. + * @see AttributeReader#getAttribute + */ + public getAttribute(): PointAttribute { + return this._attribute; + } - /** - * AttributeReader abstract method. - * @see AttributeReader#getPointData - */ - public getPointData(level: int32, tile: TileIndex, tileBuffer: TileReadBuffer, bufferIndex: int32, pointIndex: int32, cloudPoint: CloudPoint): void { - /* Get the buffer */ - let buffer: ABuffer = tileBuffer.getAttributeBuffer(bufferIndex); - let offset: int32 = this._attribute.getTypeByteSizeForCount(pointIndex); - /* Read the value */ - let attribute: PointAttribute = cloudPoint.getAttribute(bufferIndex); - let value: AttributeValue = cloudPoint.getAttributeValue(bufferIndex); - AttributeValue.readFromBufferTo(buffer, offset, attribute.getType(), value); - /* Standard attribute? */ - if (this._standardColor) cloudPoint.setColor(value.getColor()); - if (this._standardIntensity) cloudPoint.setIntensity(value.getInt2()); + /** + * AttributeReader abstract method. + * @see AttributeReader#getMinimumValue + */ + public getMinimumValue(): AttributeValue { + return this._minValue; + } + + /** + * AttributeReader abstract method. + * @see AttributeReader#getMaximumValue + */ + public getMaximumValue(): AttributeValue { + return this._maxValue; + } + + /** + * AttributeReader abstract method. + * @see AttributeReader#readTileData2 + */ + public readTileData2( + level: int32, + tile: TileIndex, + pointOffset: ALong, + pointCount: int32, + tileBuffer: TileReadBuffer, + bufferIndex: int32, + readRequest: ReadRequest, + fileContents: ContentLoader, + ): void { + /* Get the right part */ + let pointDataPart: ContainerFilePart = this._pointDataParts[level]; + /* Get the file extent */ + let fileName: string = pointDataPart.getFileAccess().getFileName(); + let fileSize: ALong = this._container.getFileLength(); + let offset: ALong = pointDataPart.getOffset().add(this._attribute.getTypeByteSizeForLongCount(tile.pointIndex.add(pointOffset))); + let size: int32 = this._attribute.getTypeByteSizeForCount(pointCount); + pointDataPart.rangeCheck(offset, ALong.fromInt(size)); + /* Request the data? */ + if (fileContents.isAvailable() == false) { + /* Add the range */ + fileContents.requestFilePart(offset, size); + return; } + /* Add the statistics */ + readRequest.addDataSize(size); + /* Read the content */ + let data: ABuffer = fileContents.getFilePart(offset, size); + tileBuffer.setAttributeBuffer(bufferIndex, data); + } + + /** + * AttributeReader abstract method. + * @see AttributeReader#getPointData + */ + public getPointData( + level: int32, + tile: TileIndex, + tileBuffer: TileReadBuffer, + bufferIndex: int32, + pointIndex: int32, + cloudPoint: CloudPoint, + ): void { + /* Get the buffer */ + let buffer: ABuffer = tileBuffer.getAttributeBuffer(bufferIndex); + let offset: int32 = this._attribute.getTypeByteSizeForCount(pointIndex); + /* Read the value */ + let attribute: PointAttribute = cloudPoint.getAttribute(bufferIndex); + let value: AttributeValue = cloudPoint.getAttributeValue(bufferIndex); + AttributeValue.readFromBufferTo(buffer, offset, attribute.getType(), value); + /* Standard attribute? */ + if (this._standardColor) cloudPoint.setColor(value.getColor()); + if (this._standardIntensity) cloudPoint.setIntensity(value.getInt2()); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/FileAccess.ts b/core/orbitgt/src/pointcloud/format/opc/FileAccess.ts index 505284646258..9bbb767e4c6e 100644 --- a/core/orbitgt/src/pointcloud/format/opc/FileAccess.ts +++ b/core/orbitgt/src/pointcloud/format/opc/FileAccess.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -24,43 +24,43 @@ import { FileStorage } from "../../../system/storage/FileStorage"; */ /** @internal */ export class FileAccess { - /** The storage of the file */ - private _fileStorage: FileStorage; - /** The name of the file */ - private _fileName: string; - /** The length of the file */ - private _fileLength: ALong; + /** The storage of the file */ + private _fileStorage: FileStorage; + /** The name of the file */ + private _fileName: string; + /** The length of the file */ + private _fileLength: ALong; - /** - * Create a new file access. - * @param fileName the name of the file. - * @param fileLength the length of the file. - */ - public constructor(fileStorage: FileStorage, fileName: string, fileLength: ALong) { - this._fileStorage = fileStorage; - this._fileName = fileName; - this._fileLength = fileLength; - } + /** + * Create a new file access. + * @param fileName the name of the file. + * @param fileLength the length of the file. + */ + public constructor(fileStorage: FileStorage, fileName: string, fileLength: ALong) { + this._fileStorage = fileStorage; + this._fileName = fileName; + this._fileLength = fileLength; + } - /** - * Close the file access. - */ - public close(): void { - } + /** + * Close the file access. + */ + public close(): void { + } - /** - * Get the name of the file. - * @return the name of the file. - */ - public getFileName(): string { - return this._fileName; - } + /** + * Get the name of the file. + * @return the name of the file. + */ + public getFileName(): string { + return this._fileName; + } - /** - * Get the length of the file. - * @return the length of the file. - */ - public getFileLength(): ALong { - return this._fileLength; - } + /** + * Get the length of the file. + * @return the length of the file. + */ + public getFileLength(): ALong { + return this._fileLength; + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/FileReader.ts b/core/orbitgt/src/pointcloud/format/opc/FileReader.ts index 636d6232e323..a143228aec8e 100644 --- a/core/orbitgt/src/pointcloud/format/opc/FileReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/FileReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -38,249 +38,264 @@ import { GeometryReader } from "./GeometryReader"; */ /** @internal */ export class FileReader { - /** The name of this module */ - private static readonly MODULE: string = "FileReader"; + /** The name of this module */ + private static readonly MODULE: string = "FileReader"; - /** The file storage */ - private _fileStorage: FileStorage; - /** The name of the file */ - private _fileName: string; - /** The container */ - private _container: ContainerFile; + /** The file storage */ + private _fileStorage: FileStorage; + /** The name of the file */ + private _fileName: string; + /** The container */ + private _container: ContainerFile; - /** The file record */ - private _fileRecord: FileRecord; - /** The directory readers (1 per level) */ - private _directoryReaders: Array; - /** The geometry readers (1 per level) */ - private _geometryReaders: Array; - /** The attribute readers */ - private _attributeReaders: Array; + /** The file record */ + private _fileRecord: FileRecord; + /** The directory readers (1 per level) */ + private _directoryReaders: Array; + /** The geometry readers (1 per level) */ + private _geometryReaders: Array; + /** The attribute readers */ + private _attributeReaders: Array; - /** - * Create a new reader. - * @param fileName the name of the file. - * @param container the container file. - * @param fileRecord the file record. - */ - private constructor(fileStorage: FileStorage, fileName: string, container: ContainerFile, fileRecord: FileRecord) { - /* Store the parameters */ - this._fileStorage = fileStorage; - this._fileName = fileName; - this._container = container; - this._fileRecord = fileRecord; - /* Clear */ - this._directoryReaders = null; - this._geometryReaders = null; - this._attributeReaders = null; - } + /** + * Create a new reader. + * @param fileName the name of the file. + * @param container the container file. + * @param fileRecord the file record. + */ + private constructor(fileStorage: FileStorage, fileName: string, container: ContainerFile, fileRecord: FileRecord) { + /* Store the parameters */ + this._fileStorage = fileStorage; + this._fileName = fileName; + this._container = container; + this._fileRecord = fileRecord; + /* Clear */ + this._directoryReaders = null; + this._geometryReaders = null; + this._attributeReaders = null; + } - /** - * Open a file. - * @param fileName the name of the file. - * @param lazyLoading avoid early loading to keep a low memory profile? - * @return the reader. - */ - public static async openFile(fileStorage: FileStorage, fileName: string, lazyLoading: boolean): Promise { - /* Open the container file */ - let container: ContainerFile = await ContainerFile.read(fileStorage, fileName, "OPC3"); - /* Read the file record */ - let filePart: ContainerFilePart = container.getPart("file"); - let fileRecord: FileRecord = await FileRecord.readNew(fileStorage, filePart.getFileAccess().getFileName(), filePart.getOffset(), filePart.getSize()); - /* Create a reader */ - let fileReader: FileReader = new FileReader(fileStorage, fileName, container, fileRecord); - /* Open the reader */ - fileReader = await fileReader.open(lazyLoading); - /* Return the reader */ - return fileReader; - } + /** + * Open a file. + * @param fileName the name of the file. + * @param lazyLoading avoid early loading to keep a low memory profile? + * @return the reader. + */ + public static async openFile(fileStorage: FileStorage, fileName: string, lazyLoading: boolean): Promise { + /* Open the container file */ + let container: ContainerFile = await ContainerFile.read(fileStorage, fileName, "OPC3"); + /* Read the file record */ + let filePart: ContainerFilePart = container.getPart("file"); + let fileRecord: FileRecord = await FileRecord.readNew( + fileStorage, + filePart.getFileAccess().getFileName(), + filePart.getOffset(), + filePart.getSize(), + ); + /* Create a reader */ + let fileReader: FileReader = new FileReader(fileStorage, fileName, container, fileRecord); + /* Open the reader */ + fileReader = await fileReader.open(lazyLoading); + /* Return the reader */ + return fileReader; + } - /** - * Open the reader. - * @param lazyLoading avoid early loading to keep a low memory profile? - * @return the reader. - */ - private async open(lazyLoading: boolean): Promise { - /* Log */ - Message.print(FileReader.MODULE, "Opening OPC with " + this._fileRecord.getLevelCount() + " levels (crs " + this._fileRecord.getCRS() + ", lazy? " + lazyLoading + ")"); - Message.print(FileReader.MODULE, "Container has " + this._container.getPartCount() + " parts"); - // for(ContainerFilePart part: this._container.getParts()) Message.print(MODULE,"Part '"+part.getName()+"'"); - /* Define the content we are going to need (dozens of parts) */ - Message.print(FileReader.MODULE, "Loading " + this._fileRecord.getLevelCount() + " levels and " + this._fileRecord.getAttributeCount() + " attributes"); - let fileContents: ContentLoader = new ContentLoader(this._fileStorage, this._fileName); - /* Only read the block list for the top levels? (to save memory) */ - let prefetchLevelIndex: int32 = (this._fileRecord.getLevelCount() - 6); - if (prefetchLevelIndex < 0) prefetchLevelIndex = 0; - if (lazyLoading == false) prefetchLevelIndex = 0; - Message.print(FileReader.MODULE, "Prefetching from level " + prefetchLevelIndex); - /* Read the directory */ - this._directoryReaders = new Array(this._fileRecord.getLevelCount()); - for (let i: number = 0; i < this._directoryReaders.length; i++) { - let directoryReader: DirectoryReader = new DirectoryReader(this, i); - let readBlockList: boolean = (i >= prefetchLevelIndex); - directoryReader.loadData(readBlockList, fileContents); - this._directoryReaders[i] = directoryReader; - } - /* Read the geometry */ - this._geometryReaders = new Array(this._fileRecord.getLevelCount()); - for (let i: number = 0; i < this._geometryReaders.length; i++) { - let geometryReader: GeometryReader = new GeometryReader(this, i); - geometryReader.loadData(fileContents); - this._geometryReaders[i] = geometryReader; - } - /* Read the attributes */ - this._attributeReaders = new Array(this._fileRecord.getAttributeCount()); - for (let i: number = 0; i < this._fileRecord.getAttributeCount(); i++) { - let attributeReader: EmbeddedAttributeReader = new EmbeddedAttributeReader(this._container, i, this._fileRecord.getLevelCount()); - attributeReader.loadData(fileContents); - this._attributeReaders[i] = attributeReader; - } - /* Load all data needed for the structures */ - fileContents = await fileContents.load(); - /* Read the directory */ - for (let i: number = 0; i < this._directoryReaders.length; i++) { - let readBlockList: boolean = (i >= prefetchLevelIndex); - this._directoryReaders[i].loadData(readBlockList, fileContents); - } - /* Read the geometry */ - for (let i: number = 0; i < this._geometryReaders.length; i++) { - this._geometryReaders[i].loadData(fileContents); - } - /* Read the attributes */ - for (let i: number = 0; i < this._fileRecord.getAttributeCount(); i++) { - let attributeReader: EmbeddedAttributeReader = (this._attributeReaders[i]); - attributeReader.loadData(fileContents); - } - /* Log file info */ - Message.print(FileReader.MODULE, "OPC bounds are " + this._geometryReaders[0].getGeometryRecord().getBounds()); - let tileGridSize0: Coordinate = this._geometryReaders[0].getGeometryRecord().getTileGrid().size; - Message.print(FileReader.MODULE, "OPC level0 tile size is (" + tileGridSize0.x + "," + tileGridSize0.y + "," + tileGridSize0.z + ")"); - let totalPointCount: ALong = ALong.ZERO; - let totalTileCount: int32 = 0; - let totalBlockCount: int32 = 0; - for (let i: number = 0; i < this._fileRecord.getLevelCount(); i++) { - let directoryRecord: DirectoryRecord = this._directoryReaders[i].getDirectoryRecord(); - Message.print(FileReader.MODULE, "Level " + i + " has " + directoryRecord.getPointCount() + " points, " + directoryRecord.getTileCount() + " tiles, " + directoryRecord.getBlockCount() + " blocks"); - totalPointCount = totalPointCount.add(directoryRecord.getPointCount()); - totalTileCount += directoryRecord.getTileCount(); - totalBlockCount += directoryRecord.getBlockCount(); - } - Message.print(FileReader.MODULE, "Pointcloud has " + totalPointCount + " points, " + totalTileCount + " tiles, " + totalBlockCount + " blocks"); - /* Get the attributes */ - Message.print(FileReader.MODULE, "Pointcloud has " + this._attributeReaders.length + " static attributes:"); - for (let i: number = 0; i < this._attributeReaders.length; i++) { - Message.print(FileReader.MODULE, "Attribute " + i + ": " + this._attributeReaders[i].getAttribute()); - Message.print(FileReader.MODULE, " min: " + this._attributeReaders[i].getMinimumValue()); - Message.print(FileReader.MODULE, " max: " + this._attributeReaders[i].getMaximumValue()); - } - /* Return the reader */ - return this; + /** + * Open the reader. + * @param lazyLoading avoid early loading to keep a low memory profile? + * @return the reader. + */ + private async open(lazyLoading: boolean): Promise { + /* Log */ + Message.print( + FileReader.MODULE, + "Opening OPC with " + this._fileRecord.getLevelCount() + " levels (crs " + this._fileRecord.getCRS() + ", lazy? " + lazyLoading + ")", + ); + Message.print(FileReader.MODULE, "Container has " + this._container.getPartCount() + " parts"); + // for(ContainerFilePart part: this._container.getParts()) Message.print(MODULE,"Part '"+part.getName()+"'"); + /* Define the content we are going to need (dozens of parts) */ + Message.print( + FileReader.MODULE, + "Loading " + this._fileRecord.getLevelCount() + " levels and " + this._fileRecord.getAttributeCount() + " attributes", + ); + let fileContents: ContentLoader = new ContentLoader(this._fileStorage, this._fileName); + /* Only read the block list for the top levels? (to save memory) */ + let prefetchLevelIndex: int32 = this._fileRecord.getLevelCount() - 6; + if (prefetchLevelIndex < 0) prefetchLevelIndex = 0; + if (lazyLoading == false) prefetchLevelIndex = 0; + Message.print(FileReader.MODULE, "Prefetching from level " + prefetchLevelIndex); + /* Read the directory */ + this._directoryReaders = new Array(this._fileRecord.getLevelCount()); + for (let i: number = 0; i < this._directoryReaders.length; i++) { + let directoryReader: DirectoryReader = new DirectoryReader(this, i); + let readBlockList: boolean = i >= prefetchLevelIndex; + directoryReader.loadData(readBlockList, fileContents); + this._directoryReaders[i] = directoryReader; } - - /** - * Close the file. - */ - public close(): void { - for (let attributeReader of this._attributeReaders) attributeReader.close(); - if (this._container != null) this._container.close(true); - this._container = null; + /* Read the geometry */ + this._geometryReaders = new Array(this._fileRecord.getLevelCount()); + for (let i: number = 0; i < this._geometryReaders.length; i++) { + let geometryReader: GeometryReader = new GeometryReader(this, i); + geometryReader.loadData(fileContents); + this._geometryReaders[i] = geometryReader; } - - /** - * Get the storage of the file. - * @return the storage of the file. - */ - public getFileStorage(): FileStorage { - return this._fileStorage; + /* Read the attributes */ + this._attributeReaders = new Array(this._fileRecord.getAttributeCount()); + for (let i: number = 0; i < this._fileRecord.getAttributeCount(); i++) { + let attributeReader: EmbeddedAttributeReader = new EmbeddedAttributeReader(this._container, i, this._fileRecord.getLevelCount()); + attributeReader.loadData(fileContents); + this._attributeReaders[i] = attributeReader; } - - /** - * Get the name of the file. - * @return the name of the file. - */ - public getFileName(): string { - return this._fileName; + /* Load all data needed for the structures */ + fileContents = await fileContents.load(); + /* Read the directory */ + for (let i: number = 0; i < this._directoryReaders.length; i++) { + let readBlockList: boolean = i >= prefetchLevelIndex; + this._directoryReaders[i].loadData(readBlockList, fileContents); } - - /** - * Get the container file. - * @return the container file. - */ - public getContainer(): ContainerFile { - return this._container; + /* Read the geometry */ + for (let i: number = 0; i < this._geometryReaders.length; i++) { + this._geometryReaders[i].loadData(fileContents); } - - /** - * Get the file record. - * @return the file record. - */ - public getFileRecord(): FileRecord { - return this._fileRecord; + /* Read the attributes */ + for (let i: number = 0; i < this._fileRecord.getAttributeCount(); i++) { + let attributeReader: EmbeddedAttributeReader = (this._attributeReaders[i]); + attributeReader.loadData(fileContents); } - - /** - * Get the number of resolution levels. - * @return the number of resolution levels. - */ - public getLevelCount(): int32 { - return this._fileRecord.getLevelCount(); + /* Log file info */ + Message.print(FileReader.MODULE, "OPC bounds are " + this._geometryReaders[0].getGeometryRecord().getBounds()); + let tileGridSize0: Coordinate = this._geometryReaders[0].getGeometryRecord().getTileGrid().size; + Message.print(FileReader.MODULE, "OPC level0 tile size is (" + tileGridSize0.x + "," + tileGridSize0.y + "," + tileGridSize0.z + ")"); + let totalPointCount: ALong = ALong.ZERO; + let totalTileCount: int32 = 0; + let totalBlockCount: int32 = 0; + for (let i: number = 0; i < this._fileRecord.getLevelCount(); i++) { + let directoryRecord: DirectoryRecord = this._directoryReaders[i].getDirectoryRecord(); + Message.print( + FileReader.MODULE, + "Level " + i + " has " + directoryRecord.getPointCount() + " points, " + directoryRecord.getTileCount() + " tiles, " + + directoryRecord.getBlockCount() + " blocks", + ); + totalPointCount = totalPointCount.add(directoryRecord.getPointCount()); + totalTileCount += directoryRecord.getTileCount(); + totalBlockCount += directoryRecord.getBlockCount(); } - - /** - * Get a directory reader. - * @param level the index of the level. - * @return the directory reader. - */ - public getDirectoryReader(level: int32): DirectoryReader { - return this._directoryReaders[level]; + Message.print(FileReader.MODULE, "Pointcloud has " + totalPointCount + " points, " + totalTileCount + " tiles, " + totalBlockCount + " blocks"); + /* Get the attributes */ + Message.print(FileReader.MODULE, "Pointcloud has " + this._attributeReaders.length + " static attributes:"); + for (let i: number = 0; i < this._attributeReaders.length; i++) { + Message.print(FileReader.MODULE, "Attribute " + i + ": " + this._attributeReaders[i].getAttribute()); + Message.print(FileReader.MODULE, " min: " + this._attributeReaders[i].getMinimumValue()); + Message.print(FileReader.MODULE, " max: " + this._attributeReaders[i].getMaximumValue()); } + /* Return the reader */ + return this; + } - /** - * Get a geometry reader. - * @param level the index of the level. - * @return the geometry reader. - */ - public getGeometryReader(level: int32): GeometryReader { - return this._geometryReaders[level]; - } + /** + * Close the file. + */ + public close(): void { + for (let attributeReader of this._attributeReaders) attributeReader.close(); + if (this._container != null) this._container.close(true); + this._container = null; + } - /** - * Get the static attribute readers. - * @return the static attribute readers. - */ - public getStaticAttributeReaders(): Array { - return this._attributeReaders; - } + /** + * Get the storage of the file. + * @return the storage of the file. + */ + public getFileStorage(): FileStorage { + return this._fileStorage; + } - /** - * Get the attribute readers. - * @return the attribute readers. - */ - public getAttributeReaders(): Array { - return this._attributeReaders; - } + /** + * Get the name of the file. + * @return the name of the file. + */ + public getFileName(): string { + return this._fileName; + } - /** - * Get the attributes. - * @return the attributes. - */ - public getAttributes(): Array { - let list: Array = new Array(this._attributeReaders.length); - for (let i: number = 0; i < this._attributeReaders.length; i++) list[i] = this._attributeReaders[i].getAttribute(); - return list; - } + /** + * Get the container file. + * @return the container file. + */ + public getContainer(): ContainerFile { + return this._container; + } + + /** + * Get the file record. + * @return the file record. + */ + public getFileRecord(): FileRecord { + return this._fileRecord; + } + + /** + * Get the number of resolution levels. + * @return the number of resolution levels. + */ + public getLevelCount(): int32 { + return this._fileRecord.getLevelCount(); + } + + /** + * Get a directory reader. + * @param level the index of the level. + * @return the directory reader. + */ + public getDirectoryReader(level: int32): DirectoryReader { + return this._directoryReaders[level]; + } + + /** + * Get a geometry reader. + * @param level the index of the level. + * @return the geometry reader. + */ + public getGeometryReader(level: int32): GeometryReader { + return this._geometryReaders[level]; + } + + /** + * Get the static attribute readers. + * @return the static attribute readers. + */ + public getStaticAttributeReaders(): Array { + return this._attributeReaders; + } + + /** + * Get the attribute readers. + * @return the attribute readers. + */ + public getAttributeReaders(): Array { + return this._attributeReaders; + } + + /** + * Get the attributes. + * @return the attributes. + */ + public getAttributes(): Array { + let list: Array = new Array(this._attributeReaders.length); + for (let i: number = 0; i < this._attributeReaders.length; i++) list[i] = this._attributeReaders[i].getAttribute(); + return list; + } - /** - * Find an attribute reader. - * @param attributeName the name of the attribute. - * @return the attribute reader (null if not found). - */ - public findAttributeReader(attributeName: string): AttributeReader { - /* Check the static attributes */ - for (let attributeReader of this._attributeReaders) { - if (Strings.equalsIgnoreCase(attributeReader.getAttribute().getName(), attributeName)) return attributeReader; - } - /* Not found */ - return null; + /** + * Find an attribute reader. + * @param attributeName the name of the attribute. + * @return the attribute reader (null if not found). + */ + public findAttributeReader(attributeName: string): AttributeReader { + /* Check the static attributes */ + for (let attributeReader of this._attributeReaders) { + if (Strings.equalsIgnoreCase(attributeReader.getAttribute().getName(), attributeName)) return attributeReader; } + /* Not found */ + return null; + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/FileRecord.ts b/core/orbitgt/src/pointcloud/format/opc/FileRecord.ts index 3395f1903251..71d49885891c 100644 --- a/core/orbitgt/src/pointcloud/format/opc/FileRecord.ts +++ b/core/orbitgt/src/pointcloud/format/opc/FileRecord.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -27,134 +27,142 @@ import { FileStorage } from "../../../system/storage/FileStorage"; */ /** @internal */ export class FileRecord { - /** The optionsALong */ - private _options: int32; - /** The CRS */ - private _crs: string; - /** The number of levels (4 byte) */ - private _levelCount: int32; - /** The number of attributes (4 byte) */ - private _attributeCount: int32; - /** The size of the blocks (4 byte) */ - private _blockSize: int32; - /** The metric level-0 cell size (8 byte) */ - private _metricCellSize: float64; - /** The creation timestamp (8 byte) */ - private _creationTime: ALong; + /** The optionsALong */ + private _options: int32; + /** The CRS */ + private _crs: string; + /** The number of levels (4 byte) */ + private _levelCount: int32; + /** The number of attributes (4 byte) */ + private _attributeCount: int32; + /** The size of the blocks (4 byte) */ + private _blockSize: int32; + /** The metric level-0 cell size (8 byte) */ + private _metricCellSize: float64; + /** The creation timestamp (8 byte) */ + private _creationTime: ALong; - /** - * Create a new record. - */ - public constructor(options: int32, crs: string, levelCount: int32, attributeCount: int32, blockSize: int32, metricCellSize: float64, creationTime: ALong) { - this._options = options; - this._crs = crs; - this._levelCount = levelCount; - this._attributeCount = attributeCount; - this._blockSize = blockSize; - this._metricCellSize = metricCellSize; - this._creationTime = creationTime; - } + /** + * Create a new record. + */ + public constructor( + options: int32, + crs: string, + levelCount: int32, + attributeCount: int32, + blockSize: int32, + metricCellSize: float64, + creationTime: ALong, + ) { + this._options = options; + this._crs = crs; + this._levelCount = levelCount; + this._attributeCount = attributeCount; + this._blockSize = blockSize; + this._metricCellSize = metricCellSize; + this._creationTime = creationTime; + } - /** - * Get the options. - * @return the options. - */ - public getOptions(): int32 { - return this._options; - } + /** + * Get the options. + * @return the options. + */ + public getOptions(): int32 { + return this._options; + } - /** - * Get the CRS. - * @return the CRS. - */ - public getCRS(): string { - return this._crs; - } + /** + * Get the CRS. + * @return the CRS. + */ + public getCRS(): string { + return this._crs; + } - /** - * Get the number of levels. - * @return the number. - */ - public getLevelCount(): int32 { - return this._levelCount; - } + /** + * Get the number of levels. + * @return the number. + */ + public getLevelCount(): int32 { + return this._levelCount; + } - /** - * Get the number of attributes. - * @return the number. - */ - public getAttributeCount(): int32 { - return this._attributeCount; - } + /** + * Get the number of attributes. + * @return the number. + */ + public getAttributeCount(): int32 { + return this._attributeCount; + } - /** - * Get the size of blocks. - * @return the number. - */ - public getBlockSize(): int32 { - return this._blockSize; - } + /** + * Get the size of blocks. + * @return the number. + */ + public getBlockSize(): int32 { + return this._blockSize; + } - /** - * Get the metric cell size. - * @return the metric cell size. - */ - public getMetricCellSize(): float64 { - return this._metricCellSize; - } + /** + * Get the metric cell size. + * @return the metric cell size. + */ + public getMetricCellSize(): float64 { + return this._metricCellSize; + } - /** - * Get the creation timestamp. - * @return the creation timestamp. - */ - public getCreationTime(): ALong { - return this._creationTime; - } + /** + * Get the creation timestamp. + * @return the creation timestamp. + */ + public getCreationTime(): ALong { + return this._creationTime; + } - /** - * Read a record. - * @param data the record data. - * @return the record. - */ - private static readFromBuffer(data: ABuffer): FileRecord { - /* Get the record fields */ - let options: int32 = LittleEndian.readBufferInt(data, 0); - let crs: string = LittleEndian.readBufferString(data, 4); - let dataOffset: int32 = 4 + LittleEndian.getStringByteCount(crs); - let levelCount: int32 = LittleEndian.readBufferInt(data, dataOffset + 0); - let attributeCount: int32 = LittleEndian.readBufferInt(data, dataOffset + 4); - let blockSize: int32 = LittleEndian.readBufferInt(data, dataOffset + 8); - let metricCellSize: float64 = LittleEndian.readBufferDouble(data, dataOffset + 12); - let creationTime: ALong = LittleEndian.readBufferLong(data, dataOffset + 20); - /* Return the record */ - return new FileRecord(options, crs, levelCount, attributeCount, blockSize, metricCellSize, creationTime); - } + /** + * Read a record. + * @param data the record data. + * @return the record. + */ + private static readFromBuffer(data: ABuffer): FileRecord { + /* Get the record fields */ + let options: int32 = LittleEndian.readBufferInt(data, 0); + let crs: string = LittleEndian.readBufferString(data, 4); + let dataOffset: int32 = 4 + LittleEndian.getStringByteCount(crs); + let levelCount: int32 = LittleEndian.readBufferInt(data, dataOffset + 0); + let attributeCount: int32 = LittleEndian.readBufferInt(data, dataOffset + 4); + let blockSize: int32 = LittleEndian.readBufferInt(data, dataOffset + 8); + let metricCellSize: float64 = LittleEndian.readBufferDouble(data, dataOffset + 12); + let creationTime: ALong = LittleEndian.readBufferLong(data, dataOffset + 20); + /* Return the record */ + return new FileRecord(options, crs, levelCount, attributeCount, blockSize, metricCellSize, creationTime); + } - /** - * Read a record. - * @param fileAccess the access to the file. - * @param offset the file offset to the record. - * @param size the file size to the record. - * @return the record. - */ - public static async readNew(fileStorage: FileStorage, fileName: string, offset: ALong, size: ALong): Promise { - /* Read the record */ - let data: ABuffer = await fileStorage.readFilePart(fileName, offset, size.toInt()); - /* Parse the record */ - return FileRecord.readFromBuffer(data); - } + /** + * Read a record. + * @param fileAccess the access to the file. + * @param offset the file offset to the record. + * @param size the file size to the record. + * @return the record. + */ + public static async readNew(fileStorage: FileStorage, fileName: string, offset: ALong, size: ALong): Promise { + /* Read the record */ + let data: ABuffer = await fileStorage.readFilePart(fileName, offset, size.toInt()); + /* Parse the record */ + return FileRecord.readFromBuffer(data); + } - /** - * Write the record. - * @param output the output stream. - */ - public write(output: OutStream): void { - LittleEndian.writeStreamInt(output, this._options); - LittleEndian.writeStreamString(output, this._crs); - LittleEndian.writeStreamInt(output, this._levelCount); - LittleEndian.writeStreamInt(output, this._attributeCount); - LittleEndian.writeStreamInt(output, this._blockSize); - LittleEndian.writeStreamDouble(output, this._metricCellSize); - LittleEndian.writeStreamLong(output, this._creationTime); - } + /** + * Write the record. + * @param output the output stream. + */ + public write(output: OutStream): void { + LittleEndian.writeStreamInt(output, this._options); + LittleEndian.writeStreamString(output, this._crs); + LittleEndian.writeStreamInt(output, this._levelCount); + LittleEndian.writeStreamInt(output, this._attributeCount); + LittleEndian.writeStreamInt(output, this._blockSize); + LittleEndian.writeStreamDouble(output, this._metricCellSize); + LittleEndian.writeStreamLong(output, this._creationTime); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/GeometryReader.ts b/core/orbitgt/src/pointcloud/format/opc/GeometryReader.ts index 2c3944faddb5..2d48204ded0f 100644 --- a/core/orbitgt/src/pointcloud/format/opc/GeometryReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/GeometryReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -38,161 +38,168 @@ import { TileReadBuffer } from "./TileReadBuffer"; */ /** @internal */ export class GeometryReader { - /** The size of the high-resolution record in the file */ - public static readonly RECORD_SIZE_HR: int32 = 6; - /** The size of the low-resolution record in the file */ - public static readonly RECORD_SIZE_LR: int32 = 3; + /** The size of the high-resolution record in the file */ + public static readonly RECORD_SIZE_HR: int32 = 6; + /** The size of the low-resolution record in the file */ + public static readonly RECORD_SIZE_LR: int32 = 3; - /** The number of bins (subdivisions) in a multi-resolution tile */ - public static readonly MR_BIN_COUNT: int32 = 64; + /** The number of bins (subdivisions) in a multi-resolution tile */ + public static readonly MR_BIN_COUNT: int32 = 64; - /** The file reader */ - private _fileReader: FileReader; - /** The level */ - private _level: int32; + /** The file reader */ + private _fileReader: FileReader; + /** The level */ + private _level: int32; - /** The geometry record */ - private _geometryRecord: GeometryRecord; - /** The location of the geometry data */ - private _geometryDataPart: ContainerFilePart; + /** The geometry record */ + private _geometryRecord: GeometryRecord; + /** The location of the geometry data */ + private _geometryDataPart: ContainerFilePart; - /** - * Create a new reader. - * @param opcReader the file reader. - * @param level the level. - */ - public constructor(fileReader: FileReader, level: int32) { - /* Store the parameters */ - this._fileReader = fileReader; - this._level = level; - /* Get the geometry data */ - this._geometryRecord = null; - this._geometryDataPart = fileReader.getContainer().getPart("" + level + ".geometry.data"); - } + /** + * Create a new reader. + * @param opcReader the file reader. + * @param level the level. + */ + public constructor(fileReader: FileReader, level: int32) { + /* Store the parameters */ + this._fileReader = fileReader; + this._level = level; + /* Get the geometry data */ + this._geometryRecord = null; + this._geometryDataPart = fileReader.getContainer().getPart("" + level + ".geometry.data"); + } - /** - * Load the data. - * @return the reader. - */ - public loadData(fileContents: ContentLoader): GeometryReader { - /* Read the record */ - let geometryPart: ContainerFilePart = this._fileReader.getContainer().getPart("" + this._level + ".geometry.definition"); - this._geometryRecord = GeometryRecord.readNew(geometryPart.getOffset(), geometryPart.getSize(), fileContents); - /* Return the reader */ - return this; - } + /** + * Load the data. + * @return the reader. + */ + public loadData(fileContents: ContentLoader): GeometryReader { + /* Read the record */ + let geometryPart: ContainerFilePart = this._fileReader.getContainer().getPart("" + this._level + ".geometry.definition"); + this._geometryRecord = GeometryRecord.readNew(geometryPart.getOffset(), geometryPart.getSize(), fileContents); + /* Return the reader */ + return this; + } - /** - * Get the geometry record. - * @return the geometry record. - */ - public getGeometryRecord(): GeometryRecord { - return this._geometryRecord; - } + /** + * Get the geometry record. + * @return the geometry record. + */ + public getGeometryRecord(): GeometryRecord { + return this._geometryRecord; + } - /** - * Read the raw data for a tile. - * @param tile the tile. - * @param tileBuffer the buffer to read into. - * @param readRequest the read parameters (contains the result read statistics). - */ - public readTileData2(tile: TileIndex, pointOffset: int32, pointCount: int32, tileBuffer: TileReadBuffer, readRequest: ReadRequest, fileContents: ContentLoader): void { - /* What resolution do we have? */ - let lowResolution: boolean = (this._level > 0); - let recordSize: int32 = (lowResolution) ? GeometryReader.RECORD_SIZE_LR : GeometryReader.RECORD_SIZE_HR; - /* Get the file extent */ - let fileSize: ALong = this._fileReader.getContainer().getFileLength(); - let offset: ALong = tile.pointIndex.addInt(pointOffset).mulInt(recordSize).add(this._geometryDataPart.getOffset()); - let size: int32 = pointCount * recordSize; - this._geometryDataPart.rangeCheck(offset, ALong.fromInt(size)); - /* Request the data? */ - if (fileContents.isAvailable() == false) { - /* Add the range */ - fileContents.requestFilePart(offset, size); - return; - } - /* Update the statistics */ - readRequest.addDataSize(size); - /* Read the content */ - let data: ABuffer = fileContents.getFilePart(offset, size); - tileBuffer.setGeometryBuffer(data); + /** + * Read the raw data for a tile. + * @param tile the tile. + * @param tileBuffer the buffer to read into. + * @param readRequest the read parameters (contains the result read statistics). + */ + public readTileData2( + tile: TileIndex, + pointOffset: int32, + pointCount: int32, + tileBuffer: TileReadBuffer, + readRequest: ReadRequest, + fileContents: ContentLoader, + ): void { + /* What resolution do we have? */ + let lowResolution: boolean = this._level > 0; + let recordSize: int32 = lowResolution ? GeometryReader.RECORD_SIZE_LR : GeometryReader.RECORD_SIZE_HR; + /* Get the file extent */ + let fileSize: ALong = this._fileReader.getContainer().getFileLength(); + let offset: ALong = tile.pointIndex.addInt(pointOffset).mulInt(recordSize).add(this._geometryDataPart.getOffset()); + let size: int32 = pointCount * recordSize; + this._geometryDataPart.rangeCheck(offset, ALong.fromInt(size)); + /* Request the data? */ + if (fileContents.isAvailable() == false) { + /* Add the range */ + fileContents.requestFilePart(offset, size); + return; } + /* Update the statistics */ + readRequest.addDataSize(size); + /* Read the content */ + let data: ABuffer = fileContents.getFilePart(offset, size); + tileBuffer.setGeometryBuffer(data); + } - /** - * Convert a low-resolution coordinate to a high-resolution one. - * @param local the low-resolution coordinate. - * @return the high-resolution coordinate. - */ - public static lowToHighResolution(local: int32): int32 { - return (local << 8) + (128); - } + /** + * Convert a low-resolution coordinate to a high-resolution one. + * @param local the low-resolution coordinate. + * @return the high-resolution coordinate. + */ + public static lowToHighResolution(local: int32): int32 { + return (local << 8) + (128); + } - /** - * Get geometry data. - * @param tile the tile. - * @param tileBuffer the buffer that has been read. - * @param pointIndex the index of the point to read. - * @param cloudPoint the point to read the geometry of. - */ - public getPointData(tile: TileIndex, tileBuffer: TileReadBuffer, pointIndex: int32, cloudPoint: CloudPoint): void { - /* What resolution do we have? */ - let lowResolution: boolean = (this._level > 0); - let recordSize: int32 = (lowResolution) ? GeometryReader.RECORD_SIZE_LR : GeometryReader.RECORD_SIZE_HR; - /* Get the buffer */ - let buffer: ABuffer = tileBuffer.getGeometryBuffer(); - let offset: int32 = (pointIndex * recordSize); - /* Read the local position */ - let lx: int32; - let ly: int32; - let lz: int32; - if (lowResolution) { - /* Read the 8-bit local position */ - lx = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); - offset++; - ly = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); - offset++; - lz = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); - } - else { - /* Read the 16-bit local position */ - lx = LittleEndian.readBufferShort(buffer, offset); - offset += 2; - ly = LittleEndian.readBufferShort(buffer, offset); - offset += 2; - lz = LittleEndian.readBufferShort(buffer, offset); - } - /* Get the grid */ - let grid: Grid = this._geometryRecord.getTileGrid(); - /* Get the tile position */ - let tileX0: float64 = grid.p0.x + (tile.gridIndex.x * grid.size.x); - let tileY0: float64 = grid.p0.y + (tile.gridIndex.y * grid.size.y); - let tileZ0: float64 = grid.p0.z + (tile.gridIndex.z * grid.size.z); - /* Get the coordinate scale factors */ - let scaleX: float64 = grid.size.x / 65536.0; - let scaleY: float64 = grid.size.y / 65536.0; - let scaleZ: float64 = grid.size.z / 65536.0; - /* Set the position */ - cloudPoint.setX(tileX0 + scaleX * lx); - cloudPoint.setY(tileY0 + scaleY * ly); - cloudPoint.setZ(tileZ0 + scaleZ * lz); + /** + * Get geometry data. + * @param tile the tile. + * @param tileBuffer the buffer that has been read. + * @param pointIndex the index of the point to read. + * @param cloudPoint the point to read the geometry of. + */ + public getPointData(tile: TileIndex, tileBuffer: TileReadBuffer, pointIndex: int32, cloudPoint: CloudPoint): void { + /* What resolution do we have? */ + let lowResolution: boolean = this._level > 0; + let recordSize: int32 = lowResolution ? GeometryReader.RECORD_SIZE_LR : GeometryReader.RECORD_SIZE_HR; + /* Get the buffer */ + let buffer: ABuffer = tileBuffer.getGeometryBuffer(); + let offset: int32 = pointIndex * recordSize; + /* Read the local position */ + let lx: int32; + let ly: int32; + let lz: int32; + if (lowResolution) { + /* Read the 8-bit local position */ + lx = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); + offset++; + ly = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); + offset++; + lz = GeometryReader.lowToHighResolution(LittleEndian.readBufferByte(buffer, offset)); + } + else { + /* Read the 16-bit local position */ + lx = LittleEndian.readBufferShort(buffer, offset); + offset += 2; + ly = LittleEndian.readBufferShort(buffer, offset); + offset += 2; + lz = LittleEndian.readBufferShort(buffer, offset); } + /* Get the grid */ + let grid: Grid = this._geometryRecord.getTileGrid(); + /* Get the tile position */ + let tileX0: float64 = grid.p0.x + (tile.gridIndex.x * grid.size.x); + let tileY0: float64 = grid.p0.y + (tile.gridIndex.y * grid.size.y); + let tileZ0: float64 = grid.p0.z + (tile.gridIndex.z * grid.size.z); + /* Get the coordinate scale factors */ + let scaleX: float64 = grid.size.x / 65536.0; + let scaleY: float64 = grid.size.y / 65536.0; + let scaleZ: float64 = grid.size.z / 65536.0; + /* Set the position */ + cloudPoint.setX(tileX0 + scaleX * lx); + cloudPoint.setY(tileY0 + scaleY * ly); + cloudPoint.setZ(tileZ0 + scaleZ * lz); + } - /** - * Get geometry data. - * @param tile the tile. - * @param tileBuffer the buffer that has been read. - * @param pointData the point data. - */ - public getPointDataRaw(tile: TileIndex, tileBuffer: TileReadBuffer, pointData: PointDataRaw): void { - /* What resolution do we have? */ - let lowResolution: boolean = (this._level > 0); - if (lowResolution) { - /* Straight copy of the raw buffer */ - pointData.points8 = new Uint8Buffer(tileBuffer.getGeometryBuffer(), 0, 3 * tile.pointCount); - } - else { - /* Straight copy of the raw buffer */ - pointData.points16 = new Uint16Buffer(tileBuffer.getGeometryBuffer(), 0, 3 * tile.pointCount); - } + /** + * Get geometry data. + * @param tile the tile. + * @param tileBuffer the buffer that has been read. + * @param pointData the point data. + */ + public getPointDataRaw(tile: TileIndex, tileBuffer: TileReadBuffer, pointData: PointDataRaw): void { + /* What resolution do we have? */ + let lowResolution: boolean = this._level > 0; + if (lowResolution) { + /* Straight copy of the raw buffer */ + pointData.points8 = new Uint8Buffer(tileBuffer.getGeometryBuffer(), 0, 3 * tile.pointCount); + } + else { + /* Straight copy of the raw buffer */ + pointData.points16 = new Uint16Buffer(tileBuffer.getGeometryBuffer(), 0, 3 * tile.pointCount); } + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/GeometryRecord.ts b/core/orbitgt/src/pointcloud/format/opc/GeometryRecord.ts index deb5ff820ca2..e1f03efc287d 100644 --- a/core/orbitgt/src/pointcloud/format/opc/GeometryRecord.ts +++ b/core/orbitgt/src/pointcloud/format/opc/GeometryRecord.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -30,98 +30,98 @@ import { Grid } from "../../model/Grid"; */ /** @internal */ export class GeometryRecord { - /** The bounds (48 byte) */ - private _bounds: Bounds; - /** The tile grid (48 byte) */ - private _tileGrid: Grid; + /** The bounds (48 byte) */ + private _bounds: Bounds; + /** The tile grid (48 byte) */ + private _tileGrid: Grid; - /** - * Create a new record. - */ - public constructor(bounds: Bounds, tileGrid: Grid) { - this._bounds = bounds; - this._tileGrid = tileGrid; - } + /** + * Create a new record. + */ + public constructor(bounds: Bounds, tileGrid: Grid) { + this._bounds = bounds; + this._tileGrid = tileGrid; + } - /** - * Get the bounds. - * @return the bounds. - */ - public getBounds(): Bounds { - return this._bounds; - } + /** + * Get the bounds. + * @return the bounds. + */ + public getBounds(): Bounds { + return this._bounds; + } - /** - * Get the tile grid. - * @return the tile grid. - */ - public getTileGrid(): Grid { - return this._tileGrid; - } + /** + * Get the tile grid. + * @return the tile grid. + */ + public getTileGrid(): Grid { + return this._tileGrid; + } - /** - * Read a record. - * @param data the record data. - * @return the record. - */ - private static readFromBuffer(data: ABuffer): GeometryRecord { - /* Get the record fields */ - let minX: float64 = LittleEndian.readBufferDouble(data, 0); - let maxX: float64 = LittleEndian.readBufferDouble(data, 8); - let minY: float64 = LittleEndian.readBufferDouble(data, 16); - let maxY: float64 = LittleEndian.readBufferDouble(data, 24); - let minZ: float64 = LittleEndian.readBufferDouble(data, 32); - let maxZ: float64 = LittleEndian.readBufferDouble(data, 40); - let bounds: Bounds = new Bounds(); - bounds.addXYZ(minX, minY, minZ); - bounds.addXYZ(maxX, maxY, maxZ); - let gridX0: float64 = LittleEndian.readBufferDouble(data, 48); - let gridY0: float64 = LittleEndian.readBufferDouble(data, 56); - let gridZ0: float64 = LittleEndian.readBufferDouble(data, 64); - let gridSX: float64 = LittleEndian.readBufferDouble(data, 72); - let gridSY: float64 = LittleEndian.readBufferDouble(data, 80); - let gridSZ: float64 = LittleEndian.readBufferDouble(data, 88); - let tileGrid: Grid = new Grid(new Coordinate(gridX0, gridY0, gridZ0), new Coordinate(gridSX, gridSY, gridSZ)); - /* Return the record */ - return new GeometryRecord(bounds, tileGrid); - } + /** + * Read a record. + * @param data the record data. + * @return the record. + */ + private static readFromBuffer(data: ABuffer): GeometryRecord { + /* Get the record fields */ + let minX: float64 = LittleEndian.readBufferDouble(data, 0); + let maxX: float64 = LittleEndian.readBufferDouble(data, 8); + let minY: float64 = LittleEndian.readBufferDouble(data, 16); + let maxY: float64 = LittleEndian.readBufferDouble(data, 24); + let minZ: float64 = LittleEndian.readBufferDouble(data, 32); + let maxZ: float64 = LittleEndian.readBufferDouble(data, 40); + let bounds: Bounds = new Bounds(); + bounds.addXYZ(minX, minY, minZ); + bounds.addXYZ(maxX, maxY, maxZ); + let gridX0: float64 = LittleEndian.readBufferDouble(data, 48); + let gridY0: float64 = LittleEndian.readBufferDouble(data, 56); + let gridZ0: float64 = LittleEndian.readBufferDouble(data, 64); + let gridSX: float64 = LittleEndian.readBufferDouble(data, 72); + let gridSY: float64 = LittleEndian.readBufferDouble(data, 80); + let gridSZ: float64 = LittleEndian.readBufferDouble(data, 88); + let tileGrid: Grid = new Grid(new Coordinate(gridX0, gridY0, gridZ0), new Coordinate(gridSX, gridSY, gridSZ)); + /* Return the record */ + return new GeometryRecord(bounds, tileGrid); + } - /** - * Read a record. - * @param fileAccess the access to the file. - * @param offset the file offset to the record. - * @param size the file size to the record. - * @return the record. - */ - public static readNew(offset: ALong, size: ALong, contentLoader: ContentLoader): GeometryRecord { - /* Request the data? */ - if (contentLoader.isLoaded() == false) { - /* Add the range */ - contentLoader.requestFilePart(offset, size.toInt()); - return null; - } - /* Get the data */ - let data: ABuffer = contentLoader.getFilePart(offset, size.toInt()); - /* Parse the record */ - return GeometryRecord.readFromBuffer(data); + /** + * Read a record. + * @param fileAccess the access to the file. + * @param offset the file offset to the record. + * @param size the file size to the record. + * @return the record. + */ + public static readNew(offset: ALong, size: ALong, contentLoader: ContentLoader): GeometryRecord { + /* Request the data? */ + if (contentLoader.isLoaded() == false) { + /* Add the range */ + contentLoader.requestFilePart(offset, size.toInt()); + return null; } + /* Get the data */ + let data: ABuffer = contentLoader.getFilePart(offset, size.toInt()); + /* Parse the record */ + return GeometryRecord.readFromBuffer(data); + } - /** - * Write the record. - * @param out the output stream. - */ - public write(output: OutStream): void { - LittleEndian.writeStreamDouble(output, this._bounds.min.x); - LittleEndian.writeStreamDouble(output, this._bounds.max.x); - LittleEndian.writeStreamDouble(output, this._bounds.min.y); - LittleEndian.writeStreamDouble(output, this._bounds.max.y); - LittleEndian.writeStreamDouble(output, this._bounds.min.z); - LittleEndian.writeStreamDouble(output, this._bounds.max.z); - LittleEndian.writeStreamDouble(output, this._tileGrid.p0.x); - LittleEndian.writeStreamDouble(output, this._tileGrid.p0.y); - LittleEndian.writeStreamDouble(output, this._tileGrid.p0.z); - LittleEndian.writeStreamDouble(output, this._tileGrid.size.x); - LittleEndian.writeStreamDouble(output, this._tileGrid.size.y); - LittleEndian.writeStreamDouble(output, this._tileGrid.size.z); - } + /** + * Write the record. + * @param out the output stream. + */ + public write(output: OutStream): void { + LittleEndian.writeStreamDouble(output, this._bounds.min.x); + LittleEndian.writeStreamDouble(output, this._bounds.max.x); + LittleEndian.writeStreamDouble(output, this._bounds.min.y); + LittleEndian.writeStreamDouble(output, this._bounds.max.y); + LittleEndian.writeStreamDouble(output, this._bounds.min.z); + LittleEndian.writeStreamDouble(output, this._bounds.max.z); + LittleEndian.writeStreamDouble(output, this._tileGrid.p0.x); + LittleEndian.writeStreamDouble(output, this._tileGrid.p0.y); + LittleEndian.writeStreamDouble(output, this._tileGrid.p0.z); + LittleEndian.writeStreamDouble(output, this._tileGrid.size.x); + LittleEndian.writeStreamDouble(output, this._tileGrid.size.y); + LittleEndian.writeStreamDouble(output, this._tileGrid.size.z); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/OPCReader.ts b/core/orbitgt/src/pointcloud/format/opc/OPCReader.ts index 280f3d7f96ac..8dab22b616ec 100644 --- a/core/orbitgt/src/pointcloud/format/opc/OPCReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/OPCReader.ts @@ -51,304 +51,320 @@ import { TileReadBuffer } from "./TileReadBuffer"; */ /** @internal */ export class OPCReader extends PointCloudReader { - /** The file reader */ - private _fileReader: FileReader; - /** The index of the first level */ - private _levelOffset: int32; - /** The number of levels */ - private _levelCount: int32; + /** The file reader */ + private _fileReader: FileReader; + /** The index of the first level */ + private _levelOffset: int32; + /** The number of levels */ + private _levelCount: int32; - /** - * Create a new reader for a file. - * @param fileName the name of the file. - * @param lazyLoading avoid early loading of all block indexes to keep a low memory profile? Lazy loading only loads the block indexes of the top 6 levels (see CLOUD-1152 issue) - * @return the reader. - */ - public static async openFile(fileStorage: FileStorage, fileName: string, lazyLoading: boolean): Promise { - /* Open the file */ - const fileReader: FileReader = await FileReader.openFile(fileStorage, fileName, lazyLoading); - /* Create the reader */ - return new OPCReader(fileReader, 0, fileReader.getLevelCount()); - } + /** + * Create a new reader for a file. + * @param fileName the name of the file. + * @param lazyLoading avoid early loading of all block indexes to keep a low memory profile? Lazy loading only loads the block indexes of the top 6 levels (see CLOUD-1152 issue) + * @return the reader. + */ + public static async openFile(fileStorage: FileStorage, fileName: string, lazyLoading: boolean): Promise { + /* Open the file */ + const fileReader: FileReader = await FileReader.openFile(fileStorage, fileName, lazyLoading); + /* Create the reader */ + return new OPCReader(fileReader, 0, fileReader.getLevelCount()); + } - /** - * Create a new reader. - */ - private constructor(fileReader: FileReader, levelOffset: int32, levelCount: int32) { - super(); - this._fileReader = fileReader; - this._levelOffset = levelOffset; - this._levelCount = levelCount; - } + /** + * Create a new reader. + */ + private constructor(fileReader: FileReader, levelOffset: int32, levelCount: int32) { + super(); + this._fileReader = fileReader; + this._levelOffset = levelOffset; + this._levelCount = levelCount; + } - /** - * Get the file reader. - * @return the file reader. - */ - public getFileReader(): FileReader { - return this._fileReader; - } + /** + * Get the file reader. + * @return the file reader. + */ + public getFileReader(): FileReader { + return this._fileReader; + } - /** - * PointCloudReader method. - * @see PointCloudReader#close - */ - public override close(): void { - if (this._fileReader != null) this._fileReader.close(); - this._fileReader = null; - } + /** + * PointCloudReader method. + * @see PointCloudReader#close + */ + public override close(): void { + if (this._fileReader != null) this._fileReader.close(); + this._fileReader = null; + } - /** - * PointCloudReader method. - * @see PointCloudReader#getProperty - */ - public override getProperty(propertyName: string): Object { - if (propertyName == null) return null; - if (Strings.equalsIgnoreCase(propertyName, "metricCellSize")) return new Coordinate(this._fileReader.getFileRecord().getMetricCellSize(), 0.0, 0.0); - return null; - } + /** + * PointCloudReader method. + * @see PointCloudReader#getProperty + */ + public override getProperty(propertyName: string): Object { + if (propertyName == null) return null; + if (Strings.equalsIgnoreCase(propertyName, "metricCellSize")) + return new Coordinate(this._fileReader.getFileRecord().getMetricCellSize(), 0.0, 0.0); + return null; + } - /** - * PointCloudReader method. - * @see PointCloudReader#getFileStorage - */ - public override getFileStorage(): FileStorage { - return this._fileReader.getFileStorage(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getFileStorage + */ + public override getFileStorage(): FileStorage { + return this._fileReader.getFileStorage(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getFileName - */ - public override getFileName(): string { - return this._fileReader.getFileName(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getFileName + */ + public override getFileName(): string { + return this._fileReader.getFileName(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getFileCRS - */ - public override getFileCRS(): string { - return this._fileReader.getFileRecord().getCRS(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getFileCRS + */ + public override getFileCRS(): string { + return this._fileReader.getFileRecord().getCRS(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getFileBounds - */ - public override getFileBounds(): Bounds { - return this._fileReader.getGeometryReader(0).getGeometryRecord().getBounds(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getFileBounds + */ + public override getFileBounds(): Bounds { + return this._fileReader.getGeometryReader(0).getGeometryRecord().getBounds(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getPointAttributes - */ - public override getPointAttributes(): Array { - return this._fileReader.getAttributes(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getPointAttributes + */ + public override getPointAttributes(): Array { + return this._fileReader.getAttributes(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getMinAttributeValue - */ - public override getMinAttributeValue(attribute: PointAttribute): AttributeValue { - for (const reader of this._fileReader.getAttributeReaders()) if (reader.getAttribute().hasName(attribute.getName())) return reader.getMinimumValue(); - return null; - } + /** + * PointCloudReader method. + * @see PointCloudReader#getMinAttributeValue + */ + public override getMinAttributeValue(attribute: PointAttribute): AttributeValue { + for (const reader of this._fileReader.getAttributeReaders()) + if (reader.getAttribute().hasName(attribute.getName())) return reader.getMinimumValue(); + return null; + } - /** - * PointCloudReader method. - * @see PointCloudReader#getMaxAttributeValue - */ - public override getMaxAttributeValue(attribute: PointAttribute): AttributeValue { - for (const reader of this._fileReader.getAttributeReaders()) if (reader.getAttribute().hasName(attribute.getName())) return reader.getMaximumValue(); - return null; - } + /** + * PointCloudReader method. + * @see PointCloudReader#getMaxAttributeValue + */ + public override getMaxAttributeValue(attribute: PointAttribute): AttributeValue { + for (const reader of this._fileReader.getAttributeReaders()) + if (reader.getAttribute().hasName(attribute.getName())) return reader.getMaximumValue(); + return null; + } - /** - * PointCloudReader method. - * @see PointCloudReader#getLevelCount - */ - public override getLevelCount(): int32 { - return this._fileReader.getLevelCount(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getLevelCount + */ + public override getLevelCount(): int32 { + return this._fileReader.getLevelCount(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getLevelPointCount - */ - public override getLevelPointCount(level: int32): ALong { - return this._fileReader.getDirectoryReader(level).getDirectoryRecord().getPointCount(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getLevelPointCount + */ + public override getLevelPointCount(level: int32): ALong { + return this._fileReader.getDirectoryReader(level).getDirectoryRecord().getPointCount(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getLevelPointBounds - */ - public override getLevelPointBounds(level: int32): Bounds { - return this._fileReader.getGeometryReader(level).getGeometryRecord().getBounds(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getLevelPointBounds + */ + public override getLevelPointBounds(level: int32): Bounds { + return this._fileReader.getGeometryReader(level).getGeometryRecord().getBounds(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getLevelBlockGrid - */ - public override getLevelBlockGrid(level: int32): Grid { - return this.getLevelTileGrid(level).scale(this._fileReader.getFileRecord().getBlockSize()); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getLevelBlockGrid + */ + public override getLevelBlockGrid(level: int32): Grid { + return this.getLevelTileGrid(level).scale(this._fileReader.getFileRecord().getBlockSize()); + } - /** - * PointCloudReader method. - * @see PointCloudReader#getLevelTileGrid - */ - public override getLevelTileGrid(level: int32): Grid { - return this._fileReader.getGeometryReader(level).getGeometryRecord().getTileGrid(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#getLevelTileGrid + */ + public override getLevelTileGrid(level: int32): Grid { + return this._fileReader.getGeometryReader(level).getGeometryRecord().getTileGrid(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#peekBlockIndexes - */ - public override peekBlockIndexes(level: int32): Array { - return this._fileReader.getDirectoryReader(level).getBlocks(); - } + /** + * PointCloudReader method. + * @see PointCloudReader#peekBlockIndexes + */ + public override peekBlockIndexes(level: int32): Array { + return this._fileReader.getDirectoryReader(level).getBlocks(); + } - /** - * PointCloudReader method. - * @see PointCloudReader#readBlockIndexes - */ - public override readBlockIndexes(level: int32, fileContents: ContentLoader): Array { - /* Get the directory reader */ - const directoryReader: DirectoryReader = this._fileReader.getDirectoryReader(level); - /* Already read all blocks? */ - const blocks: Array = directoryReader.getBlocks(); - if (blocks.length > 0) return blocks; - /* Delegate to the directory reader */ - return directoryReader.readBlocks(this._fileReader.getFileRecord(), fileContents); - } + /** + * PointCloudReader method. + * @see PointCloudReader#readBlockIndexes + */ + public override readBlockIndexes(level: int32, fileContents: ContentLoader): Array { + /* Get the directory reader */ + const directoryReader: DirectoryReader = this._fileReader.getDirectoryReader(level); + /* Already read all blocks? */ + const blocks: Array = directoryReader.getBlocks(); + if (blocks.length > 0) return blocks; + /* Delegate to the directory reader */ + return directoryReader.readBlocks(this._fileReader.getFileRecord(), fileContents); + } - /** - * PointCloudReader method. - * @see PointCloudReader#readTileIndexes - */ - public override readTileIndexes(block: BlockIndex, fileContents: ContentLoader): Array { - return this._fileReader.getDirectoryReader(block.level).readTiles2(block, fileContents); - } + /** + * PointCloudReader method. + * @see PointCloudReader#readTileIndexes + */ + public override readTileIndexes(block: BlockIndex, fileContents: ContentLoader): Array { + return this._fileReader.getDirectoryReader(block.level).readTiles2(block, fileContents); + } - /** - * Get the attribute mask to use for reading. - * @param parameters the read parameters. - * @return the attribute mask. - */ - private getAttributeMask(parameters: ReadRequest): AttributeMask { - /* Make a list of readers */ - const readers: AList = new AList(); - /* Should we read all attributes? */ - if (parameters.readAllExtraAttributes()) { - /* Read all attributes */ - for (const reader of this._fileReader.getAttributeReaders()) readers.add(reader); - } else { - /* Read color? */ - if (parameters.readColor()) { - const reader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.COLOR.getName()); - if (reader != null) readers.add(reader); - } - /* Read intensity? */ - if (parameters.readIntensity()) { - const reader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.INTENSITY.getName()); - if (reader != null) readers.add(reader); - } - /* Read the extra attributes */ - const extraAttributes: AList = parameters.getExtraAttributes(); - for (let i: number = 0; i < extraAttributes.size(); i++) { - /* Get the name of the extra attribute */ - const extraAttribute: string = extraAttributes.get(i); - /* Did we already add the color? */ - if (parameters.readColor() && Strings.equalsIgnoreCase(extraAttribute, StandardAttributes.COLOR.getName())) continue; - /* Did we already add the intensity? */ - if (parameters.readIntensity() && Strings.equalsIgnoreCase(extraAttribute, StandardAttributes.INTENSITY.getName())) continue; - /* Find the attribute reader */ - const reader: AttributeReader = this._fileReader.findAttributeReader(extraAttribute); - /* Add the reader */ - if (reader != null) readers.add(reader); - } - } - /* Create the mask */ - return new AttributeMask(readers); + /** + * Get the attribute mask to use for reading. + * @param parameters the read parameters. + * @return the attribute mask. + */ + private getAttributeMask(parameters: ReadRequest): AttributeMask { + /* Make a list of readers */ + const readers: AList = new AList(); + /* Should we read all attributes? */ + if (parameters.readAllExtraAttributes()) { + /* Read all attributes */ + for (const reader of this._fileReader.getAttributeReaders()) readers.add(reader); + } else { + /* Read color? */ + if (parameters.readColor()) { + const reader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.COLOR.getName()); + if (reader != null) readers.add(reader); + } + /* Read intensity? */ + if (parameters.readIntensity()) { + const reader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.INTENSITY.getName()); + if (reader != null) readers.add(reader); + } + /* Read the extra attributes */ + const extraAttributes: AList = parameters.getExtraAttributes(); + for (let i: number = 0; i < extraAttributes.size(); i++) { + /* Get the name of the extra attribute */ + const extraAttribute: string = extraAttributes.get(i); + /* Did we already add the color? */ + if (parameters.readColor() && Strings.equalsIgnoreCase(extraAttribute, StandardAttributes.COLOR.getName())) continue; + /* Did we already add the intensity? */ + if (parameters.readIntensity() && Strings.equalsIgnoreCase(extraAttribute, StandardAttributes.INTENSITY.getName())) continue; + /* Find the attribute reader */ + const reader: AttributeReader = this._fileReader.findAttributeReader(extraAttribute); + /* Add the reader */ + if (reader != null) readers.add(reader); + } } + /* Create the mask */ + return new AttributeMask(readers); + } - /** - * PointCloudReader interface method. - * @see PointCloudReader#readPoints - */ - public override readPoints(tileIndex: TileIndex, readRequest: ReadRequest, fileContents: ContentLoader): AList { - /* Create the attribute mask */ - const attributeMask: AttributeMask = this.getAttributeMask(readRequest); - /* Create the read buffer */ - const tileBuffer: TileReadBuffer = new TileReadBuffer(attributeMask.attributes.length); - /* Read the points in the tile */ - const pointOffset: int32 = 0; - const pointCount: int32 = tileIndex.pointCount; - return PointReader.readTilePoints(this.getFileReader(), readRequest, attributeMask, tileIndex.level, tileIndex, pointOffset, pointCount, tileBuffer, fileContents); - } + /** + * PointCloudReader interface method. + * @see PointCloudReader#readPoints + */ + public override readPoints(tileIndex: TileIndex, readRequest: ReadRequest, fileContents: ContentLoader): AList { + /* Create the attribute mask */ + const attributeMask: AttributeMask = this.getAttributeMask(readRequest); + /* Create the read buffer */ + const tileBuffer: TileReadBuffer = new TileReadBuffer(attributeMask.attributes.length); + /* Read the points in the tile */ + const pointOffset: int32 = 0; + const pointCount: int32 = tileIndex.pointCount; + return PointReader.readTilePoints( + this.getFileReader(), + readRequest, + attributeMask, + tileIndex.level, + tileIndex, + pointOffset, + pointCount, + tileBuffer, + fileContents, + ); + } - /** - * PointCloudReader interface method. - * @see PointCloudReader#readPointData - */ - public override readPointData(tileIndex: TileIndex, dataFormat: int32, accessTime: float64, fileContents: ContentLoader): PointData { - /* 16-bit XYZ geometry and 8-bit RGB colors? */ - if (dataFormat == PointDataRaw.TYPE) { - /* Create the attribute mask */ - const readRequest: ReadRequest = ReadRequest.READ_GEOMETRY_AND_COLOR; - const readers: AList = new AList(); - const colorReader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.COLOR.getName()); - if (colorReader != null) readers.add(colorReader); - const attributeMask: AttributeMask = new AttributeMask(readers); - /* Has the data been loaded? */ - let tileBuffer: TileReadBuffer = null; - let pointData: PointDataRaw = null; - if (fileContents.isAvailable()) { - /* Create the read buffer */ - tileBuffer = new TileReadBuffer(attributeMask.attributes.length); - /* Create the point data buffer */ - const tileGrid: Grid = this._fileReader.getGeometryReader(tileIndex.level).getGeometryRecord().getTileGrid(); - const tileBounds: Bounds = tileGrid.getCellBounds(tileIndex.gridIndex); - pointData = new PointDataRaw(tileIndex, tileBounds, null, null, null); - } - /* Fill the point data buffer */ - PointReader.readTilePointsRaw(this.getFileReader(), readRequest, attributeMask, tileIndex, tileBuffer, pointData, fileContents); - /* Missing color channel after data load? */ - if (fileContents.isAvailable() && (pointData.colors == null)) { - /* Define the default RGB color (0xE6C60D) */ - const defaultR: int32 = 230; - const defaultG: int32 = 198; - const defaultB: int32 = 13; - /* Create a default color buffer (BGR sample sequence) */ - pointData.colors = Uint8Buffer.wrap(new ABuffer(3 * tileIndex.pointCount)); - for (let i: number = 0; i < tileIndex.pointCount; i++) { - pointData.colors.set(3 * i + 0, defaultB); - pointData.colors.set(3 * i + 1, defaultG); - pointData.colors.set(3 * i + 2, defaultR); - } - } - return pointData; + /** + * PointCloudReader interface method. + * @see PointCloudReader#readPointData + */ + public override readPointData(tileIndex: TileIndex, dataFormat: int32, accessTime: float64, fileContents: ContentLoader): PointData { + /* 16-bit XYZ geometry and 8-bit RGB colors? */ + if (dataFormat == PointDataRaw.TYPE) { + /* Create the attribute mask */ + const readRequest: ReadRequest = ReadRequest.READ_GEOMETRY_AND_COLOR; + const readers: AList = new AList(); + const colorReader: AttributeReader = this._fileReader.findAttributeReader(StandardAttributes.COLOR.getName()); + if (colorReader != null) readers.add(colorReader); + const attributeMask: AttributeMask = new AttributeMask(readers); + /* Has the data been loaded? */ + let tileBuffer: TileReadBuffer = null; + let pointData: PointDataRaw = null; + if (fileContents.isAvailable()) { + /* Create the read buffer */ + tileBuffer = new TileReadBuffer(attributeMask.attributes.length); + /* Create the point data buffer */ + const tileGrid: Grid = this._fileReader.getGeometryReader(tileIndex.level).getGeometryRecord().getTileGrid(); + const tileBounds: Bounds = tileGrid.getCellBounds(tileIndex.gridIndex); + pointData = new PointDataRaw(tileIndex, tileBounds, null, null, null); + } + /* Fill the point data buffer */ + PointReader.readTilePointsRaw(this.getFileReader(), readRequest, attributeMask, tileIndex, tileBuffer, pointData, fileContents); + /* Missing color channel after data load? */ + if (fileContents.isAvailable() && (pointData.colors == null)) { + /* Define the default RGB color (0xE6C60D) */ + const defaultR: int32 = 230; + const defaultG: int32 = 198; + const defaultB: int32 = 13; + /* Create a default color buffer (BGR sample sequence) */ + pointData.colors = Uint8Buffer.wrap(new ABuffer(3 * tileIndex.pointCount)); + for (let i: number = 0; i < tileIndex.pointCount; i++) { + pointData.colors.set(3 * i + 0, defaultB); + pointData.colors.set(3 * i + 1, defaultG); + pointData.colors.set(3 * i + 2, defaultR); } - /* Unknown format */ - return null; + } + return pointData; } + /* Unknown format */ + return null; + } - /** - * PointCloudReader interface method. - * @see PointCloudReader#clipToLevelRange - */ - public override clipToLevelRange(levelOffset: int32, levelCount: int32): PointCloudReader { - /* Check the parameters */ - ASystem.assert0(levelOffset >= 0, `Invalid level offset ${levelOffset}`); - ASystem.assert0(levelCount > 0, `Invalid level count ${levelCount}`); - ASystem.assert0(levelOffset + levelCount <= this._levelCount, `Level range ${levelOffset}+${levelCount} not possible in ${this._levelCount} levels`); - /* Create a new reader */ - return new OPCReader(this._fileReader, this._levelOffset + levelOffset, levelCount); - } + /** + * PointCloudReader interface method. + * @see PointCloudReader#clipToLevelRange + */ + public override clipToLevelRange(levelOffset: int32, levelCount: int32): PointCloudReader { + /* Check the parameters */ + ASystem.assert0(levelOffset >= 0, `Invalid level offset ${levelOffset}`); + ASystem.assert0(levelCount > 0, `Invalid level count ${levelCount}`); + ASystem.assert0( + levelOffset + levelCount <= this._levelCount, + `Level range ${levelOffset}+${levelCount} not possible in ${this._levelCount} levels`, + ); + /* Create a new reader */ + return new OPCReader(this._fileReader, this._levelOffset + levelOffset, levelCount); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/PointReader.ts b/core/orbitgt/src/pointcloud/format/opc/PointReader.ts index d5906128908c..5fb2faf21bd1 100644 --- a/core/orbitgt/src/pointcloud/format/opc/PointReader.ts +++ b/core/orbitgt/src/pointcloud/format/opc/PointReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ABuffer } from "../../../system/buffer/ABuffer"; import { Uint8Buffer } from "../../../system/buffer/Uint8Buffer"; import { AList } from "../../../system/collection/AList"; @@ -37,134 +36,180 @@ import { TileReadBuffer } from "./TileReadBuffer"; */ /** @internal */ export class PointReader { - /** - * No instances. - */ - private constructor() { } + /** + * No instances. + */ + private constructor() {} - /** - * Read the data of a tile. - * @param reader the file reader. - * @param readRequest the read request parameters. - * @param attributeMask the attribute mask for reading. - * @param level the index of the level to read from. - * @param tileRecord the tile record. - * @param tileBuffer the buffer to help reading. - */ - private static readTileData(reader: FileReader, readRequest: ReadRequest, attributeMask: AttributeMask, level: int32, tileRecord: TileIndex, pointOffset: int32, pointCount: int32, tileBuffer: TileReadBuffer, fileContents: ContentLoader): void { - /* Should we read the geometry? */ - let geometryReader: GeometryReader = null; - if (readRequest.readGeometry()) { - /* Read all geometry data */ - geometryReader = reader.getGeometryReader(level); - geometryReader.readTileData2(tileRecord, pointOffset, pointCount, tileBuffer, readRequest, fileContents); - } - /* Read all attribute data */ - let attributeReaders: AList = attributeMask.readers; - for (let i: number = 0; i < attributeReaders.size(); i++) { - let attributeReader: AttributeReader = attributeReaders.get(i); - attributeReader.readTileData2(level, tileRecord, ALong.fromInt(pointOffset), pointCount, tileBuffer, i, readRequest, fileContents); - } + /** + * Read the data of a tile. + * @param reader the file reader. + * @param readRequest the read request parameters. + * @param attributeMask the attribute mask for reading. + * @param level the index of the level to read from. + * @param tileRecord the tile record. + * @param tileBuffer the buffer to help reading. + */ + private static readTileData( + reader: FileReader, + readRequest: ReadRequest, + attributeMask: AttributeMask, + level: int32, + tileRecord: TileIndex, + pointOffset: int32, + pointCount: int32, + tileBuffer: TileReadBuffer, + fileContents: ContentLoader, + ): void { + /* Should we read the geometry? */ + let geometryReader: GeometryReader = null; + if (readRequest.readGeometry()) { + /* Read all geometry data */ + geometryReader = reader.getGeometryReader(level); + geometryReader.readTileData2(tileRecord, pointOffset, pointCount, tileBuffer, readRequest, fileContents); } - - /** - * Parse the data of a tile. - * @return the parsed tile data. - */ - private static parseTileData(reader: FileReader, readRequest: ReadRequest, attributeMask: AttributeMask, level: int32, tileRecord: TileIndex, pointOffset: int32, pointCount: int32, tileBuffer: TileReadBuffer, fileContents: ContentLoader): AList { - /* We should have the file content */ - if (fileContents.isAvailable() == false) return null; - /* Should we read the geometry? */ - let geometryReader: GeometryReader = null; - if (readRequest.readGeometry()) { - /* Read all geometry data */ - geometryReader = reader.getGeometryReader(level); - } - /* Read all attribute data */ - let attributeReaders: AList = attributeMask.readers; - /* Thinning? */ - let thinning: int32 = readRequest.getThinning(); - if (thinning < 2) thinning = 0; - /* Process all points */ - let cloudPointList: AList = new AList(); - for (let i: number = 0; i < pointCount; i++) { - /* Create a point */ - let cloudPoint: CloudPoint = CloudPoint.createWithAttributes(attributeMask.attributes); - /* Thinning? */ - if ((thinning != 0) && (i % thinning != 0)) { - /* Skip */ - continue; - } - /* Get the point index */ - let pointIndex: ALong = tileRecord.pointIndex.addInt(pointOffset + i); - /* Set the index */ - cloudPoint.setIndex(pointIndex); - /* Set the geometry */ - if (readRequest.readGeometry()) geometryReader.getPointData(tileRecord, tileBuffer, i, cloudPoint); - /* Set the attributes */ - for (let j: number = 0; j < attributeReaders.size(); j++) { - let attributeReader: AttributeReader = attributeReaders.get(j); - attributeReader.getPointData(level, tileRecord, tileBuffer, j, i, cloudPoint); - } - /* Process the point */ - cloudPointList.add(cloudPoint); - } - /* Return the list */ - return cloudPointList; + /* Read all attribute data */ + let attributeReaders: AList = attributeMask.readers; + for (let i: number = 0; i < attributeReaders.size(); i++) { + let attributeReader: AttributeReader = attributeReaders.get(i); + attributeReader.readTileData2(level, tileRecord, ALong.fromInt(pointOffset), pointCount, tileBuffer, i, readRequest, fileContents); } + } - /** - * Read some points of a tile. - * @param reader the file reader. - * @param readRequest the read request parameters. - * @param attributeMask the attribute mask for reading. - * @param level the index of the level to read from. - * @param tileRecord the tile record. - * @param tileBuffer the buffer to help reading. - * @param processor the point processor. - * @param fileContens the file contents. - * @return the tile points. - */ - public static readTilePoints(reader: FileReader, readRequest: ReadRequest, attributeMask: AttributeMask, level: int32, tileRecord: TileIndex, pointOffset: int32, pointCount: int32, tileBuffer: TileReadBuffer, fileContens: ContentLoader): AList { - /* Read the tile data */ - PointReader.readTileData(reader, readRequest, attributeMask, level, tileRecord, pointOffset, pointCount, tileBuffer, fileContens); - /* Parse the tile data */ - return PointReader.parseTileData(reader, readRequest, attributeMask, level, tileRecord, pointOffset, pointCount, tileBuffer, fileContens); + /** + * Parse the data of a tile. + * @return the parsed tile data. + */ + private static parseTileData( + reader: FileReader, + readRequest: ReadRequest, + attributeMask: AttributeMask, + level: int32, + tileRecord: TileIndex, + pointOffset: int32, + pointCount: int32, + tileBuffer: TileReadBuffer, + fileContents: ContentLoader, + ): AList { + /* We should have the file content */ + if (fileContents.isAvailable() == false) return null; + /* Should we read the geometry? */ + let geometryReader: GeometryReader = null; + if (readRequest.readGeometry()) { + /* Read all geometry data */ + geometryReader = reader.getGeometryReader(level); } - - /** - * Parse the data of a tile. - * @return the parsed tile data. - */ - private static parseTileDataRaw(reader: FileReader, readRequest: ReadRequest, attributeMask: AttributeMask, tileRecord: TileIndex, tileBuffer: TileReadBuffer, pointData: PointDataRaw, fileContents: ContentLoader): void { - /* We should have the file content */ - if (fileContents.isAvailable() == false) return; - /* Read the geometry */ - let geometryReader: GeometryReader = reader.getGeometryReader(tileRecord.level); - geometryReader.getPointDataRaw(tileRecord, tileBuffer, pointData); - /* Read the color? */ - if (tileBuffer.getAttributeCount() > 0) { - /* Little-endian encoding makes 24-bit RGB values to be written as BGR byte sequence */ - pointData.colors = new Uint8Buffer(tileBuffer.getAttributeBuffer(0), 0, 3 * tileRecord.pointCount); - } + /* Read all attribute data */ + let attributeReaders: AList = attributeMask.readers; + /* Thinning? */ + let thinning: int32 = readRequest.getThinning(); + if (thinning < 2) thinning = 0; + /* Process all points */ + let cloudPointList: AList = new AList(); + for (let i: number = 0; i < pointCount; i++) { + /* Create a point */ + let cloudPoint: CloudPoint = CloudPoint.createWithAttributes(attributeMask.attributes); + /* Thinning? */ + if ((thinning != 0) && (i % thinning != 0)) { + /* Skip */ + continue; + } + /* Get the point index */ + let pointIndex: ALong = tileRecord.pointIndex.addInt(pointOffset + i); + /* Set the index */ + cloudPoint.setIndex(pointIndex); + /* Set the geometry */ + if (readRequest.readGeometry()) geometryReader.getPointData(tileRecord, tileBuffer, i, cloudPoint); + /* Set the attributes */ + for (let j: number = 0; j < attributeReaders.size(); j++) { + let attributeReader: AttributeReader = attributeReaders.get(j); + attributeReader.getPointData(level, tileRecord, tileBuffer, j, i, cloudPoint); + } + /* Process the point */ + cloudPointList.add(cloudPoint); } + /* Return the list */ + return cloudPointList; + } - /** - * Read some points of a tile. - * @param reader the file reader. - * @param readRequest the read request parameters. - * @param attributeMask the attribute mask for reading. - * @param level the index of the level to read from. - * @param tileRecord the tile record. - * @param tileBuffer the buffer to help reading. - * @param processor the point processor. - * @param fileContens the file contents. - * @return the tile points. - */ - public static readTilePointsRaw(reader: FileReader, readRequest: ReadRequest, attributeMask: AttributeMask, tileRecord: TileIndex, tileBuffer: TileReadBuffer, pointData: PointDataRaw, fileContents: ContentLoader): void { - /* Read the tile data */ - PointReader.readTileData(reader, readRequest, attributeMask, tileRecord.level, tileRecord, 0, tileRecord.pointCount, tileBuffer, fileContents); - /* Parse the tile data */ - PointReader.parseTileDataRaw(reader, readRequest, attributeMask, tileRecord, tileBuffer, pointData, fileContents); + /** + * Read some points of a tile. + * @param reader the file reader. + * @param readRequest the read request parameters. + * @param attributeMask the attribute mask for reading. + * @param level the index of the level to read from. + * @param tileRecord the tile record. + * @param tileBuffer the buffer to help reading. + * @param processor the point processor. + * @param fileContens the file contents. + * @return the tile points. + */ + public static readTilePoints( + reader: FileReader, + readRequest: ReadRequest, + attributeMask: AttributeMask, + level: int32, + tileRecord: TileIndex, + pointOffset: int32, + pointCount: int32, + tileBuffer: TileReadBuffer, + fileContens: ContentLoader, + ): AList { + /* Read the tile data */ + PointReader.readTileData(reader, readRequest, attributeMask, level, tileRecord, pointOffset, pointCount, tileBuffer, fileContens); + /* Parse the tile data */ + return PointReader.parseTileData(reader, readRequest, attributeMask, level, tileRecord, pointOffset, pointCount, tileBuffer, fileContens); + } + + /** + * Parse the data of a tile. + * @return the parsed tile data. + */ + private static parseTileDataRaw( + reader: FileReader, + readRequest: ReadRequest, + attributeMask: AttributeMask, + tileRecord: TileIndex, + tileBuffer: TileReadBuffer, + pointData: PointDataRaw, + fileContents: ContentLoader, + ): void { + /* We should have the file content */ + if (fileContents.isAvailable() == false) return; + /* Read the geometry */ + let geometryReader: GeometryReader = reader.getGeometryReader(tileRecord.level); + geometryReader.getPointDataRaw(tileRecord, tileBuffer, pointData); + /* Read the color? */ + if (tileBuffer.getAttributeCount() > 0) { + /* Little-endian encoding makes 24-bit RGB values to be written as BGR byte sequence */ + pointData.colors = new Uint8Buffer(tileBuffer.getAttributeBuffer(0), 0, 3 * tileRecord.pointCount); } + } + + /** + * Read some points of a tile. + * @param reader the file reader. + * @param readRequest the read request parameters. + * @param attributeMask the attribute mask for reading. + * @param level the index of the level to read from. + * @param tileRecord the tile record. + * @param tileBuffer the buffer to help reading. + * @param processor the point processor. + * @param fileContens the file contents. + * @return the tile points. + */ + public static readTilePointsRaw( + reader: FileReader, + readRequest: ReadRequest, + attributeMask: AttributeMask, + tileRecord: TileIndex, + tileBuffer: TileReadBuffer, + pointData: PointDataRaw, + fileContents: ContentLoader, + ): void { + /* Read the tile data */ + PointReader.readTileData(reader, readRequest, attributeMask, tileRecord.level, tileRecord, 0, tileRecord.pointCount, tileBuffer, fileContents); + /* Parse the tile data */ + PointReader.parseTileDataRaw(reader, readRequest, attributeMask, tileRecord, tileBuffer, pointData, fileContents); + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/TileReadBuffer.ts b/core/orbitgt/src/pointcloud/format/opc/TileReadBuffer.ts index 71c6b9e4e7c1..cfbd024cf597 100644 --- a/core/orbitgt/src/pointcloud/format/opc/TileReadBuffer.ts +++ b/core/orbitgt/src/pointcloud/format/opc/TileReadBuffer.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -23,87 +23,87 @@ import { ABuffer } from "../../../system/buffer/ABuffer"; */ /** @internal */ export class TileReadBuffer { - /** The geometry buffer */ - private _geometryBuffer: ABuffer; - /** The attribute buffers */ - private _attributeBuffers: Array; + /** The geometry buffer */ + private _geometryBuffer: ABuffer; + /** The attribute buffers */ + private _attributeBuffers: Array; - /** - * Create a new buffer. - * @param attributeCount the number of attributes. - */ - public constructor(attributeCount: int32) { - this._geometryBuffer = null; //new ABuffer(1024); - this._attributeBuffers = new Array(attributeCount); - for (let i: number = 0; i < attributeCount; i++) this._attributeBuffers[i] = null; //new ABuffer(1024); - } + /** + * Create a new buffer. + * @param attributeCount the number of attributes. + */ + public constructor(attributeCount: int32) { + this._geometryBuffer = null; // new ABuffer(1024); + this._attributeBuffers = new Array(attributeCount); + for (let i: number = 0; i < attributeCount; i++) this._attributeBuffers[i] = null; // new ABuffer(1024); + } - /** - * Get the geometry buffer. - * @return the buffer. - */ - public getGeometryBuffer(): ABuffer { - return this._geometryBuffer; - } + /** + * Get the geometry buffer. + * @return the buffer. + */ + public getGeometryBuffer(): ABuffer { + return this._geometryBuffer; + } - /** - * Set the geometry buffer. - * @param buffer the buffer. - */ - public setGeometryBuffer(buffer: ABuffer): void { - this._geometryBuffer = buffer; - } + /** + * Set the geometry buffer. + * @param buffer the buffer. + */ + public setGeometryBuffer(buffer: ABuffer): void { + this._geometryBuffer = buffer; + } - /** - * Get the geometry buffer. - * @param size the mimumum size of the buffer. - * @return the buffer. - */ - public getSizedGeometryBuffer(size: int32): ABuffer { - if (this._geometryBuffer.size() < size) { - this._geometryBuffer = new ABuffer(size + 1024); - } - return this._geometryBuffer; + /** + * Get the geometry buffer. + * @param size the mimumum size of the buffer. + * @return the buffer. + */ + public getSizedGeometryBuffer(size: int32): ABuffer { + if (this._geometryBuffer.size() < size) { + this._geometryBuffer = new ABuffer(size + 1024); } + return this._geometryBuffer; + } - /** - * Get the attribute count. - * @return the attribute count. - */ - public getAttributeCount(): int32 { - return this._attributeBuffers.length; - } + /** + * Get the attribute count. + * @return the attribute count. + */ + public getAttributeCount(): int32 { + return this._attributeBuffers.length; + } - /** - * Get an attribute buffer. - * @param attributeIndex the index of the attribute. - * @return the buffer. - */ - public getAttributeBuffer(attributeIndex: int32): ABuffer { - return this._attributeBuffers[attributeIndex]; - } + /** + * Get an attribute buffer. + * @param attributeIndex the index of the attribute. + * @return the buffer. + */ + public getAttributeBuffer(attributeIndex: int32): ABuffer { + return this._attributeBuffers[attributeIndex]; + } - /** - * Get an attribute buffer. - * @param attributeIndex the index of the attribute. - * @param size the mimumum size of the buffer. - * @return the buffer. - */ - public getSizedAttributeBuffer(attributeIndex: int32, size: int32): ABuffer { - let attributeBuffer: ABuffer = this._attributeBuffers[attributeIndex]; - if (attributeBuffer.size() < size) { - attributeBuffer = new ABuffer(size + 1024); - this._attributeBuffers[attributeIndex] = attributeBuffer; - } - return attributeBuffer; + /** + * Get an attribute buffer. + * @param attributeIndex the index of the attribute. + * @param size the mimumum size of the buffer. + * @return the buffer. + */ + public getSizedAttributeBuffer(attributeIndex: int32, size: int32): ABuffer { + let attributeBuffer: ABuffer = this._attributeBuffers[attributeIndex]; + if (attributeBuffer.size() < size) { + attributeBuffer = new ABuffer(size + 1024); + this._attributeBuffers[attributeIndex] = attributeBuffer; } + return attributeBuffer; + } - /** - * Set an attribute buffer. - * @param attributeIndex the index of the attribute. - * @param buffer the buffer. - */ - public setAttributeBuffer(attributeIndex: int32, buffer: ABuffer): void { - this._attributeBuffers[attributeIndex] = buffer; - } + /** + * Set an attribute buffer. + * @param attributeIndex the index of the attribute. + * @param buffer the buffer. + */ + public setAttributeBuffer(attributeIndex: int32, buffer: ABuffer): void { + this._attributeBuffers[attributeIndex] = buffer; + } } diff --git a/core/orbitgt/src/pointcloud/format/opc/TileRecord.ts b/core/orbitgt/src/pointcloud/format/opc/TileRecord.ts index 46f82d12c550..942af3b916de 100644 --- a/core/orbitgt/src/pointcloud/format/opc/TileRecord.ts +++ b/core/orbitgt/src/pointcloud/format/opc/TileRecord.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.format.opc; +// package orbitgt.pointcloud.format.opc; type int8 = number; type int16 = number; @@ -33,139 +33,139 @@ import { TileIndex } from "../../model/TileIndex"; */ /** @internal */ export class TileRecord { - /** The size of the record in the file */ - public static readonly RECORD_SIZE: int32 = 16; + /** The size of the record in the file */ + public static readonly RECORD_SIZE: int32 = 16; - /** - * No instances. - */ - private constructor() { - } + /** + * No instances. + */ + private constructor() { + } - /** - * Check if this tile has a certain index. - * @param tileX the tile x index. - * @param tileY the tile y index. - * @param tileZ the tile Z index. - * @return true if the tile has the index. - */ - public static isTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { - return (tileX == tile.gridIndex.x && tileY == tile.gridIndex.y && tileZ == tile.gridIndex.z); - } + /** + * Check if this tile has a certain index. + * @param tileX the tile x index. + * @param tileY the tile y index. + * @param tileZ the tile Z index. + * @return true if the tile has the index. + */ + public static isTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { + return (tileX == tile.gridIndex.x && tileY == tile.gridIndex.y && tileZ == tile.gridIndex.z); + } - /** - * Check if this tile is located after a certain index. - * @param tileX the tile x index. - * @param tileY the tile y index. - * @param tileZ the tile Z index. - * @return true if the tile is after the index. - */ - public static isAfterTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { - if (tile.gridIndex.x < tileX) return false; - if (tile.gridIndex.x > tileX) return true; - if (tile.gridIndex.y < tileY) return false; - if (tile.gridIndex.y > tileY) return true; - if (tile.gridIndex.z < tileZ) return false; - if (tile.gridIndex.z > tileZ) return true; - return false; - } + /** + * Check if this tile is located after a certain index. + * @param tileX the tile x index. + * @param tileY the tile y index. + * @param tileZ the tile Z index. + * @return true if the tile is after the index. + */ + public static isAfterTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { + if (tile.gridIndex.x < tileX) return false; + if (tile.gridIndex.x > tileX) return true; + if (tile.gridIndex.y < tileY) return false; + if (tile.gridIndex.y > tileY) return true; + if (tile.gridIndex.z < tileZ) return false; + if (tile.gridIndex.z > tileZ) return true; + return false; + } - /** - * Check if this tile is located before a certain index. - * @param tileX the tile x index. - * @param tileY the tile y index. - * @param tileZ the tile Z index. - * @return true if the tile is before the index. - */ - public static isBeforeTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { - if (tile.gridIndex.x < tileX) return true; - if (tile.gridIndex.x > tileX) return false; - if (tile.gridIndex.y < tileY) return true; - if (tile.gridIndex.y > tileY) return false; - if (tile.gridIndex.z < tileZ) return true; - if (tile.gridIndex.z > tileZ) return false; - return false; - } + /** + * Check if this tile is located before a certain index. + * @param tileX the tile x index. + * @param tileY the tile y index. + * @param tileZ the tile Z index. + * @return true if the tile is before the index. + */ + public static isBeforeTile(tile: TileIndex, tileX: int32, tileY: int32, tileZ: int32): boolean { + if (tile.gridIndex.x < tileX) return true; + if (tile.gridIndex.x > tileX) return false; + if (tile.gridIndex.y < tileY) return true; + if (tile.gridIndex.y > tileY) return false; + if (tile.gridIndex.z < tileZ) return true; + if (tile.gridIndex.z > tileZ) return false; + return false; + } - /** - * Write a record. - * @param output the output stream. - */ - public static write(tile: TileIndex, output: OutStream): void { - let tileX: int32 = tile.gridIndex.x; - let tileY: int32 = tile.gridIndex.y; - let tileZ: int32 = tile.gridIndex.z; - LittleEndian.writeStreamInt(output, tileX); - LittleEndian.writeStreamInt(output, tileY); - LittleEndian.writeStreamInt(output, tileZ); - LittleEndian.writeStreamInt(output, tile.pointCount); - } + /** + * Write a record. + * @param output the output stream. + */ + public static write(tile: TileIndex, output: OutStream): void { + let tileX: int32 = tile.gridIndex.x; + let tileY: int32 = tile.gridIndex.y; + let tileZ: int32 = tile.gridIndex.z; + LittleEndian.writeStreamInt(output, tileX); + LittleEndian.writeStreamInt(output, tileY); + LittleEndian.writeStreamInt(output, tileZ); + LittleEndian.writeStreamInt(output, tile.pointCount); + } - /** - * Read a record. - * @param tileGrid the grid. - * @param stream the data stream from the file. - * @param tileIndex the index of the tile. - * @param pointIndex the index of the first point in the tile. - * @return the requested record. - */ - public static readNew(level: int32, tileGrid: Grid, stream: InStream, tileIndex: int32, pointIndex: ALong): TileIndex { - /* Read the record */ - let tileX: int32 = LittleEndian.readStreamInt(stream); - let tileY: int32 = LittleEndian.readStreamInt(stream); - let tileZ: int32 = LittleEndian.readStreamInt(stream); - let pointCount: int32 = LittleEndian.readStreamInt(stream); - /* Create the record */ - return new TileIndex(level, tileIndex, new GridIndex(tileX, tileY, tileZ), pointIndex, pointCount); - } + /** + * Read a record. + * @param tileGrid the grid. + * @param stream the data stream from the file. + * @param tileIndex the index of the tile. + * @param pointIndex the index of the first point in the tile. + * @return the requested record. + */ + public static readNew(level: int32, tileGrid: Grid, stream: InStream, tileIndex: int32, pointIndex: ALong): TileIndex { + /* Read the record */ + let tileX: int32 = LittleEndian.readStreamInt(stream); + let tileY: int32 = LittleEndian.readStreamInt(stream); + let tileZ: int32 = LittleEndian.readStreamInt(stream); + let pointCount: int32 = LittleEndian.readStreamInt(stream); + /* Create the record */ + return new TileIndex(level, tileIndex, new GridIndex(tileX, tileY, tileZ), pointIndex, pointCount); + } - /** - * Read a record. - * @param in the input stream. - * @param tileIndex the index of the tile. - * @param pointIndex the index of the first point in the tile. - */ - public static read(tile: TileIndex, level: int32, blockIndex: int32, stream: InStream, tileIndex: int32, pointIndex: ALong): void { - tile.level = level; - tile.index = tileIndex; - tile.gridIndex.x = LittleEndian.readStreamInt(stream); - tile.gridIndex.y = LittleEndian.readStreamInt(stream); - tile.gridIndex.z = LittleEndian.readStreamInt(stream); - tile.pointCount = LittleEndian.readStreamInt(stream); - tile.pointIndex = pointIndex; - } + /** + * Read a record. + * @param in the input stream. + * @param tileIndex the index of the tile. + * @param pointIndex the index of the first point in the tile. + */ + public static read(tile: TileIndex, level: int32, blockIndex: int32, stream: InStream, tileIndex: int32, pointIndex: ALong): void { + tile.level = level; + tile.index = tileIndex; + tile.gridIndex.x = LittleEndian.readStreamInt(stream); + tile.gridIndex.y = LittleEndian.readStreamInt(stream); + tile.gridIndex.z = LittleEndian.readStreamInt(stream); + tile.pointCount = LittleEndian.readStreamInt(stream); + tile.pointIndex = pointIndex; + } - /** - * Get the squared distance to a grid cell. - * @param reference the reference point. - * @return the squared distance. - */ - public static distanceSq(tile: TileIndex, reference: GridIndex): int32 { - let dx: int32 = (tile.gridIndex.x - reference.x); - let dy: int32 = (tile.gridIndex.y - reference.y); - let dz: int32 = (tile.gridIndex.z - reference.z); - return (dx * dx) + (dy * dy) + (dz * dz); - } + /** + * Get the squared distance to a grid cell. + * @param reference the reference point. + * @return the squared distance. + */ + public static distanceSq(tile: TileIndex, reference: GridIndex): int32 { + let dx: int32 = tile.gridIndex.x - reference.x; + let dy: int32 = tile.gridIndex.y - reference.y; + let dz: int32 = tile.gridIndex.z - reference.z; + return (dx * dx) + (dy * dy) + (dz * dz); + } - /** - * Get a next-level index. - * @param index the index at the current level. - * @return the next-level index. - */ - private static getNextLevelIndex1(index: int32): int32 { - if (index < 0) return Numbers.divInt(index - 1, 2); - return Numbers.divInt(index, 2); - } + /** + * Get a next-level index. + * @param index the index at the current level. + * @return the next-level index. + */ + private static getNextLevelIndex1(index: int32): int32 { + if (index < 0) return Numbers.divInt(index - 1, 2); + return Numbers.divInt(index, 2); + } - /** - * Get a next-level index. - * @param index the index at the current level. - * @return the next-level index. - */ - public static getNextLevelIndex(index: GridIndex): GridIndex { - let nextX: int32 = TileRecord.getNextLevelIndex1(index.x); - let nextY: int32 = TileRecord.getNextLevelIndex1(index.y); - let nextZ: int32 = TileRecord.getNextLevelIndex1(index.z); - return new GridIndex(nextX, nextY, nextZ); - } + /** + * Get a next-level index. + * @param index the index at the current level. + * @return the next-level index. + */ + public static getNextLevelIndex(index: GridIndex): GridIndex { + let nextX: int32 = TileRecord.getNextLevelIndex1(index.x); + let nextY: int32 = TileRecord.getNextLevelIndex1(index.y); + let nextZ: int32 = TileRecord.getNextLevelIndex1(index.z); + return new GridIndex(nextX, nextY, nextZ); + } } diff --git a/core/orbitgt/src/pointcloud/model/AttributeTypes.ts b/core/orbitgt/src/pointcloud/model/AttributeTypes.ts index 1a7965541518..0869f9769a84 100644 --- a/core/orbitgt/src/pointcloud/model/AttributeTypes.ts +++ b/core/orbitgt/src/pointcloud/model/AttributeTypes.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -19,44 +19,44 @@ type float64 = number; */ /** @internal */ export class AttributeTypes { - /** The 1-bit boolean type */ - public static readonly TYPE_BOOLEAN: int32 = 1; - /** The 1-byte integer type */ - public static readonly TYPE_INT1: int32 = 2; - /** The 2-byte integer type */ - public static readonly TYPE_INT2: int32 = 3; - /** The 4-byte integer type */ - public static readonly TYPE_INT4: int32 = 4; - /** The 8-byte integer type */ - public static readonly TYPE_INT8: int32 = 5; - /** The 4-byte float type */ - public static readonly TYPE_FLOAT4: int32 = 6; - /** The 8-byte float type */ - public static readonly TYPE_FLOAT8: int32 = 7; - /** The 3-byte color type */ - public static readonly TYPE_COLOR: int32 = 8; + /** The 1-bit boolean type */ + public static readonly TYPE_BOOLEAN: int32 = 1; + /** The 1-byte integer type */ + public static readonly TYPE_INT1: int32 = 2; + /** The 2-byte integer type */ + public static readonly TYPE_INT2: int32 = 3; + /** The 4-byte integer type */ + public static readonly TYPE_INT4: int32 = 4; + /** The 8-byte integer type */ + public static readonly TYPE_INT8: int32 = 5; + /** The 4-byte float type */ + public static readonly TYPE_FLOAT4: int32 = 6; + /** The 8-byte float type */ + public static readonly TYPE_FLOAT8: int32 = 7; + /** The 3-byte color type */ + public static readonly TYPE_COLOR: int32 = 8; - /** - * No instances. - */ - private constructor() { - } + /** + * No instances. + */ + private constructor() { + } - /** - * Get the name of a type. - * @param type the type of attributes. - * @return the name. - */ - public static getTypeName(type: int32): string { - if (type <= 0) return "none"; - if (type == AttributeTypes.TYPE_BOOLEAN) return "boolean"; - if (type == AttributeTypes.TYPE_INT1) return "int1"; - if (type == AttributeTypes.TYPE_INT2) return "int2"; - if (type == AttributeTypes.TYPE_INT4) return "int4"; - if (type == AttributeTypes.TYPE_INT8) return "int8"; - if (type == AttributeTypes.TYPE_FLOAT4) return "float4"; - if (type == AttributeTypes.TYPE_FLOAT8) return "float8"; - if (type == AttributeTypes.TYPE_COLOR) return "color"; - return "" + type; - } + /** + * Get the name of a type. + * @param type the type of attributes. + * @return the name. + */ + public static getTypeName(type: int32): string { + if (type <= 0) return "none"; + if (type == AttributeTypes.TYPE_BOOLEAN) return "boolean"; + if (type == AttributeTypes.TYPE_INT1) return "int1"; + if (type == AttributeTypes.TYPE_INT2) return "int2"; + if (type == AttributeTypes.TYPE_INT4) return "int4"; + if (type == AttributeTypes.TYPE_INT8) return "int8"; + if (type == AttributeTypes.TYPE_FLOAT4) return "float4"; + if (type == AttributeTypes.TYPE_FLOAT8) return "float8"; + if (type == AttributeTypes.TYPE_COLOR) return "color"; + return "" + type; + } } diff --git a/core/orbitgt/src/pointcloud/model/AttributeValue.ts b/core/orbitgt/src/pointcloud/model/AttributeValue.ts index 0d97b55d549b..ccf9341c1c8d 100644 --- a/core/orbitgt/src/pointcloud/model/AttributeValue.ts +++ b/core/orbitgt/src/pointcloud/model/AttributeValue.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -30,458 +30,482 @@ import { AttributeTypes } from "./AttributeTypes"; */ /** @internal */ export class AttributeValue { - /** The 'false' value */ - public static readonly FALSE: AttributeValue = AttributeValue.createBoolean(false); - /** The 'true' value */ - public static readonly TRUE: AttributeValue = AttributeValue.createBoolean(true); - - /** The type */ - private _type: int32; - /** The value for boolean/int1/int2/int4 types */ - private _valueI4: int32; - /** The value for int8 types */ - private _valueI8: ALong; - /** The value for float4 types */ - private _valueF4: float32; - /** The value for float8 types */ - private _valueF8: float64; - - /** - * Create a new (empty) value. - */ - public constructor() { - this._type = 0; - this._valueI4 = 0; - this._valueI8 = ALong.ZERO; - this._valueF4 = 0.0; - this._valueF8 = 0.0; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createBoolean(value: boolean): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setBoolean(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createInt1(value: int32): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setInt1(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createInt2(value: int32): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setInt2(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createInt4(value: int32): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setInt4(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createInt8(value: ALong): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setInt8(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createFloat4(value: float32): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setFloat4(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createFloat8(value: float64): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setFloat8(value); - return avalue; - } - - /** - * Create a new value. - * @param value the value. - */ - public static createColor(value: int32): AttributeValue { - let avalue: AttributeValue = new AttributeValue(); - avalue.setColor(value); - return avalue; - } - - /** - * Get the type. - * @return the type. - */ - public getType(): int32 { - return this._type; - } - - /** - * Clear the value. - */ - public clear(): void { - this._type = 0; - } - - /** - * Is this an empty value? - * @return true for empty. - */ - public isEmpty(): boolean { - return (this._type == 0); - } - - /** - * Get the value. - * @return the value. - */ - public getBoolean(): boolean { - return (this._valueI4 != 0); - } - - /** - * Get the value. - * @return the value. - */ - public getBooleanAsInt(): int32 { - return this._valueI4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setBoolean(value: boolean): void { - this._type = AttributeTypes.TYPE_BOOLEAN; - if (value) this._valueI4 = 1; - else this._valueI4 = 0; - } - - /** - * Set the value. - * @param value the new value. - */ - public setBooleanFromInt(value: int32): void { - this._type = AttributeTypes.TYPE_BOOLEAN; - if (value == 0) this._valueI4 = 0; - else this._valueI4 = 1; - } - - /** - * Get the value. - * @return the value. - */ - public getInt1(): int32 { - return this._valueI4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setInt1(value: int32): void { - this._type = AttributeTypes.TYPE_INT1; - this._valueI4 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getInt2(): int32 { - return this._valueI4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setInt2(value: int32): void { - this._type = AttributeTypes.TYPE_INT2; - this._valueI4 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getInt4(): int32 { - return this._valueI4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setInt4(value: int32): void { - this._type = AttributeTypes.TYPE_INT4; - this._valueI4 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getInt8(): ALong { - return this._valueI8; - } - - /** - * Set the value. - * @param value the new value. - */ - public setInt8(value: ALong): void { - this._type = AttributeTypes.TYPE_INT8; - this._valueI8 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getFloat4(): float32 { - return this._valueF4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setFloat4(value: float32): void { - this._type = AttributeTypes.TYPE_FLOAT4; - this._valueF4 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getFloat8(): float64 { - return this._valueF8; - } - - /** - * Set the value. - * @param value the new value. - */ - public setFloat8(value: float64): void { - this._type = AttributeTypes.TYPE_FLOAT8; - this._valueF8 = value; - } - - /** - * Get the value. - * @return the value. - */ - public getColor(): int32 { - return this._valueI4; - } - - /** - * Set the value. - * @param value the new value. - */ - public setColor(value: int32): void { - this._type = AttributeTypes.TYPE_COLOR; - this._valueI4 = value; - } - - /** - * Check if the value equals another value. - * @param other the other value. - * @return true if same. - */ - public same(other: AttributeValue): boolean { - /* Check the type */ - if (other._type != this._type) return false; - /* Check the value */ - if (this._type == AttributeTypes.TYPE_BOOLEAN) return (other._valueI4 == this._valueI4); - if (this._type == AttributeTypes.TYPE_INT1) return (other._valueI4 == this._valueI4); - if (this._type == AttributeTypes.TYPE_INT2) return (other._valueI4 == this._valueI4); - if (this._type == AttributeTypes.TYPE_INT4) return (other._valueI4 == this._valueI4); - if (this._type == AttributeTypes.TYPE_INT8) return (other._valueI8.same(this._valueI8)); - if (this._type == AttributeTypes.TYPE_FLOAT4) return (other._valueF4 == this._valueF4); - if (this._type == AttributeTypes.TYPE_FLOAT8) return (other._valueF8 == this._valueF8); - if (this._type == AttributeTypes.TYPE_COLOR) return (other._valueI4 == this._valueI4); - /* Empty value */ - return true; - } - - /** - * Copy to another value. - * @param other the other value to copy to. - */ - public copyTo(other: AttributeValue): void { - /* Copy the type */ - other._type = this._type; - /* Check the value */ - if (this._type == AttributeTypes.TYPE_BOOLEAN) { other._valueI4 = this._valueI4; return; } - if (this._type == AttributeTypes.TYPE_INT1) { other._valueI4 = this._valueI4; return; } - if (this._type == AttributeTypes.TYPE_INT2) { other._valueI4 = this._valueI4; return; } - if (this._type == AttributeTypes.TYPE_INT4) { other._valueI4 = this._valueI4; return; } - if (this._type == AttributeTypes.TYPE_INT8) { other._valueI8 = this._valueI8; return; } - if (this._type == AttributeTypes.TYPE_FLOAT4) { other._valueF4 = this._valueF4; return; } - if (this._type == AttributeTypes.TYPE_FLOAT8) { other._valueF8 = this._valueF8; return; } - if (this._type == AttributeTypes.TYPE_COLOR) { other._valueI4 = this._valueI4; return; } - /* Empty value */ - } - - /** - * Copy the value. - * @return the copied value. - */ - public copy(): AttributeValue { - let copy: AttributeValue = new AttributeValue(); - this.copyTo(copy); - return copy; - } - - /** - * Copy a list of values. - * @return the copied values. - */ - public static copyList(list: Array): Array { - if (list == null) return null; - let list2: Array = new Array(list.length); - for (let i: number = 0; i < list.length; i++) list2[i] = list[i].copy(); - return list2; - } - - /** - * Get the value as a string. - * @return the string. - */ - public asString(): string { - if (this._type == AttributeTypes.TYPE_BOOLEAN) return "" + this.getBoolean(); - else if (this._type == AttributeTypes.TYPE_INT1) return "" + this.getInt1(); - else if (this._type == AttributeTypes.TYPE_INT2) return "" + this.getInt2(); - else if (this._type == AttributeTypes.TYPE_INT4) return "" + this.getInt4(); - else if (this._type == AttributeTypes.TYPE_INT8) return "" + this.getInt8().toString(); - else if (this._type == AttributeTypes.TYPE_FLOAT4) return "" + this.getFloat4(); - else if (this._type == AttributeTypes.TYPE_FLOAT8) return "" + this.getFloat8(); - else if (this._type == AttributeTypes.TYPE_COLOR) return Numbers.rgbToString(this.getColor()); - return ""; - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[AttributeValue:type=" + AttributeTypes.getTypeName(this._type) + ",value=" + this.asString() + "]"; - } - - /** - * Create a default attribute value. - * @param type the type of value. - * @return a default value. - */ - public static createDefault(type: int32): AttributeValue { - if (type == AttributeTypes.TYPE_BOOLEAN) return AttributeValue.createBoolean(false); - if (type == AttributeTypes.TYPE_INT1) return AttributeValue.createInt1(0); - if (type == AttributeTypes.TYPE_INT2) return AttributeValue.createInt2(0); - if (type == AttributeTypes.TYPE_INT4) return AttributeValue.createInt4(0); - if (type == AttributeTypes.TYPE_INT8) return AttributeValue.createInt8(ALong.ZERO); - if (type == AttributeTypes.TYPE_FLOAT4) return AttributeValue.createFloat4(0.0); - if (type == AttributeTypes.TYPE_FLOAT8) return AttributeValue.createFloat8(0.0); - if (type == AttributeTypes.TYPE_COLOR) return AttributeValue.createColor(0); - ASystem.assertNot(true, "Cannot create attribute value of type " + type); - return null; - } - - /** - * Read an attribute value. - * @param buffer the buffer to read from. - * @param bufferOffset the buffer offset to read from. - * @param attributeType the type of the attribute. - * @param the value to read into. - */ - public static readFromBufferTo(buffer: ABuffer, bufferOffset: int32, attributeType: int32, value: AttributeValue): void { - if (attributeType == AttributeTypes.TYPE_BOOLEAN) value.setBoolean(LittleEndian.readBufferByte(buffer, bufferOffset) != 0); - else if (attributeType == AttributeTypes.TYPE_INT1) value.setInt1(LittleEndian.readBufferByte(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_INT2) value.setInt2(LittleEndian.readBufferShort(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_INT4) value.setInt4(LittleEndian.readBufferInt(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_INT8) value.setInt8(LittleEndian.readBufferLong(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_FLOAT4) value.setFloat4(LittleEndian.readBufferFloat(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_FLOAT8) value.setFloat8(LittleEndian.readBufferDouble(buffer, bufferOffset)); - else if (attributeType == AttributeTypes.TYPE_COLOR) value.setColor(LittleEndian.readBufferInt3(buffer, bufferOffset)); - else ASystem.assertNot(true, "Cannot read attribute value type " + attributeType); - } - - /** - * Read an attribute value. - * @param input the input stream to read from. - * @param attributeType the type of the attribute. - * @param the value to read into. - */ - public static readFromStreamTo(stream: InStream, attributeType: int32, value: AttributeValue): void { - if (attributeType == AttributeTypes.TYPE_BOOLEAN) value.setBoolean(LittleEndian.readStreamByte(stream) != 0); - else if (attributeType == AttributeTypes.TYPE_INT1) value.setInt1(LittleEndian.readStreamByte(stream)); - else if (attributeType == AttributeTypes.TYPE_INT2) value.setInt2(LittleEndian.readStreamShort(stream)); - else if (attributeType == AttributeTypes.TYPE_INT4) value.setInt4(LittleEndian.readStreamInt(stream)); - else if (attributeType == AttributeTypes.TYPE_INT8) value.setInt8(LittleEndian.readStreamLong(stream)); - else if (attributeType == AttributeTypes.TYPE_FLOAT4) value.setFloat4(LittleEndian.readStreamFloat(stream)); - else if (attributeType == AttributeTypes.TYPE_FLOAT8) value.setFloat8(LittleEndian.readStreamDouble(stream)); - else if (attributeType == AttributeTypes.TYPE_COLOR) value.setColor(LittleEndian.readStreamInt3(stream)); - else ASystem.assertNot(true, "Cannot read attribute value type " + attributeType); - } - - /** - * Read an attribute value. - * @param input the input stream to read from. - * @param attributeType the type of the attribute. - * @return the value. - */ - public static readFromStream(stream: InStream, attributeType: int32): AttributeValue { - let value: AttributeValue = new AttributeValue(); - AttributeValue.readFromStreamTo(stream, attributeType, value); - return value; - } - - /** - * Write an attribute value. - * @param output the output stream to write to. - * @param attributeType the type of the attribute. - * @param value the value of the attribute. - */ - public static writeToStream(stream: OutStream, attributeType: int32, value: AttributeValue): void { - if (attributeType == AttributeTypes.TYPE_BOOLEAN) LittleEndian.writeStreamByte(stream, value.getBooleanAsInt()); - else if (attributeType == AttributeTypes.TYPE_INT1) LittleEndian.writeStreamByte(stream, value.getInt1()); - else if (attributeType == AttributeTypes.TYPE_INT2) LittleEndian.writeStreamShort(stream, value.getInt2()); - else if (attributeType == AttributeTypes.TYPE_INT4) LittleEndian.writeStreamInt(stream, value.getInt4()); - else if (attributeType == AttributeTypes.TYPE_INT8) LittleEndian.writeStreamLong(stream, value.getInt8()); - else if (attributeType == AttributeTypes.TYPE_FLOAT4) LittleEndian.writeStreamFloat(stream, value.getFloat4()); - else if (attributeType == AttributeTypes.TYPE_FLOAT8) LittleEndian.writeStreamDouble(stream, value.getFloat8()); - else if (attributeType == AttributeTypes.TYPE_COLOR) LittleEndian.writeStreamInt3(stream, value.getColor()); - else ASystem.assertNot(true, "Cannot write attribute value type " + attributeType); - } + /** The 'false' value */ + public static readonly FALSE: AttributeValue = AttributeValue.createBoolean(false); + /** The 'true' value */ + public static readonly TRUE: AttributeValue = AttributeValue.createBoolean(true); + + /** The type */ + private _type: int32; + /** The value for boolean/int1/int2/int4 types */ + private _valueI4: int32; + /** The value for int8 types */ + private _valueI8: ALong; + /** The value for float4 types */ + private _valueF4: float32; + /** The value for float8 types */ + private _valueF8: float64; + + /** + * Create a new (empty) value. + */ + public constructor() { + this._type = 0; + this._valueI4 = 0; + this._valueI8 = ALong.ZERO; + this._valueF4 = 0.0; + this._valueF8 = 0.0; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createBoolean(value: boolean): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setBoolean(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createInt1(value: int32): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setInt1(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createInt2(value: int32): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setInt2(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createInt4(value: int32): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setInt4(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createInt8(value: ALong): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setInt8(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createFloat4(value: float32): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setFloat4(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createFloat8(value: float64): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setFloat8(value); + return avalue; + } + + /** + * Create a new value. + * @param value the value. + */ + public static createColor(value: int32): AttributeValue { + let avalue: AttributeValue = new AttributeValue(); + avalue.setColor(value); + return avalue; + } + + /** + * Get the type. + * @return the type. + */ + public getType(): int32 { + return this._type; + } + + /** + * Clear the value. + */ + public clear(): void { + this._type = 0; + } + + /** + * Is this an empty value? + * @return true for empty. + */ + public isEmpty(): boolean { + return (this._type == 0); + } + + /** + * Get the value. + * @return the value. + */ + public getBoolean(): boolean { + return (this._valueI4 != 0); + } + + /** + * Get the value. + * @return the value. + */ + public getBooleanAsInt(): int32 { + return this._valueI4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setBoolean(value: boolean): void { + this._type = AttributeTypes.TYPE_BOOLEAN; + if (value) this._valueI4 = 1; + else this._valueI4 = 0; + } + + /** + * Set the value. + * @param value the new value. + */ + public setBooleanFromInt(value: int32): void { + this._type = AttributeTypes.TYPE_BOOLEAN; + if (value == 0) this._valueI4 = 0; + else this._valueI4 = 1; + } + + /** + * Get the value. + * @return the value. + */ + public getInt1(): int32 { + return this._valueI4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setInt1(value: int32): void { + this._type = AttributeTypes.TYPE_INT1; + this._valueI4 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getInt2(): int32 { + return this._valueI4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setInt2(value: int32): void { + this._type = AttributeTypes.TYPE_INT2; + this._valueI4 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getInt4(): int32 { + return this._valueI4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setInt4(value: int32): void { + this._type = AttributeTypes.TYPE_INT4; + this._valueI4 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getInt8(): ALong { + return this._valueI8; + } + + /** + * Set the value. + * @param value the new value. + */ + public setInt8(value: ALong): void { + this._type = AttributeTypes.TYPE_INT8; + this._valueI8 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getFloat4(): float32 { + return this._valueF4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setFloat4(value: float32): void { + this._type = AttributeTypes.TYPE_FLOAT4; + this._valueF4 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getFloat8(): float64 { + return this._valueF8; + } + + /** + * Set the value. + * @param value the new value. + */ + public setFloat8(value: float64): void { + this._type = AttributeTypes.TYPE_FLOAT8; + this._valueF8 = value; + } + + /** + * Get the value. + * @return the value. + */ + public getColor(): int32 { + return this._valueI4; + } + + /** + * Set the value. + * @param value the new value. + */ + public setColor(value: int32): void { + this._type = AttributeTypes.TYPE_COLOR; + this._valueI4 = value; + } + + /** + * Check if the value equals another value. + * @param other the other value. + * @return true if same. + */ + public same(other: AttributeValue): boolean { + /* Check the type */ + if (other._type != this._type) return false; + /* Check the value */ + if (this._type == AttributeTypes.TYPE_BOOLEAN) return (other._valueI4 == this._valueI4); + if (this._type == AttributeTypes.TYPE_INT1) return (other._valueI4 == this._valueI4); + if (this._type == AttributeTypes.TYPE_INT2) return (other._valueI4 == this._valueI4); + if (this._type == AttributeTypes.TYPE_INT4) return (other._valueI4 == this._valueI4); + if (this._type == AttributeTypes.TYPE_INT8) return (other._valueI8.same(this._valueI8)); + if (this._type == AttributeTypes.TYPE_FLOAT4) return (other._valueF4 == this._valueF4); + if (this._type == AttributeTypes.TYPE_FLOAT8) return (other._valueF8 == this._valueF8); + if (this._type == AttributeTypes.TYPE_COLOR) return (other._valueI4 == this._valueI4); + /* Empty value */ + return true; + } + + /** + * Copy to another value. + * @param other the other value to copy to. + */ + public copyTo(other: AttributeValue): void { + /* Copy the type */ + other._type = this._type; + /* Check the value */ + if (this._type == AttributeTypes.TYPE_BOOLEAN) { + other._valueI4 = this._valueI4; + return; + } + if (this._type == AttributeTypes.TYPE_INT1) { + other._valueI4 = this._valueI4; + return; + } + if (this._type == AttributeTypes.TYPE_INT2) { + other._valueI4 = this._valueI4; + return; + } + if (this._type == AttributeTypes.TYPE_INT4) { + other._valueI4 = this._valueI4; + return; + } + if (this._type == AttributeTypes.TYPE_INT8) { + other._valueI8 = this._valueI8; + return; + } + if (this._type == AttributeTypes.TYPE_FLOAT4) { + other._valueF4 = this._valueF4; + return; + } + if (this._type == AttributeTypes.TYPE_FLOAT8) { + other._valueF8 = this._valueF8; + return; + } + if (this._type == AttributeTypes.TYPE_COLOR) { + other._valueI4 = this._valueI4; + return; + } + /* Empty value */ + } + + /** + * Copy the value. + * @return the copied value. + */ + public copy(): AttributeValue { + let copy: AttributeValue = new AttributeValue(); + this.copyTo(copy); + return copy; + } + + /** + * Copy a list of values. + * @return the copied values. + */ + public static copyList(list: Array): Array { + if (list == null) return null; + let list2: Array = new Array(list.length); + for (let i: number = 0; i < list.length; i++) list2[i] = list[i].copy(); + return list2; + } + + /** + * Get the value as a string. + * @return the string. + */ + public asString(): string { + if (this._type == AttributeTypes.TYPE_BOOLEAN) return "" + this.getBoolean(); + else if (this._type == AttributeTypes.TYPE_INT1) return "" + this.getInt1(); + else if (this._type == AttributeTypes.TYPE_INT2) return "" + this.getInt2(); + else if (this._type == AttributeTypes.TYPE_INT4) return "" + this.getInt4(); + else if (this._type == AttributeTypes.TYPE_INT8) return "" + this.getInt8().toString(); + else if (this._type == AttributeTypes.TYPE_FLOAT4) return "" + this.getFloat4(); + else if (this._type == AttributeTypes.TYPE_FLOAT8) return "" + this.getFloat8(); + else if (this._type == AttributeTypes.TYPE_COLOR) return Numbers.rgbToString(this.getColor()); + return ""; + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[AttributeValue:type=" + AttributeTypes.getTypeName(this._type) + ",value=" + this.asString() + "]"; + } + + /** + * Create a default attribute value. + * @param type the type of value. + * @return a default value. + */ + public static createDefault(type: int32): AttributeValue { + if (type == AttributeTypes.TYPE_BOOLEAN) return AttributeValue.createBoolean(false); + if (type == AttributeTypes.TYPE_INT1) return AttributeValue.createInt1(0); + if (type == AttributeTypes.TYPE_INT2) return AttributeValue.createInt2(0); + if (type == AttributeTypes.TYPE_INT4) return AttributeValue.createInt4(0); + if (type == AttributeTypes.TYPE_INT8) return AttributeValue.createInt8(ALong.ZERO); + if (type == AttributeTypes.TYPE_FLOAT4) return AttributeValue.createFloat4(0.0); + if (type == AttributeTypes.TYPE_FLOAT8) return AttributeValue.createFloat8(0.0); + if (type == AttributeTypes.TYPE_COLOR) return AttributeValue.createColor(0); + ASystem.assertNot(true, "Cannot create attribute value of type " + type); + return null; + } + + /** + * Read an attribute value. + * @param buffer the buffer to read from. + * @param bufferOffset the buffer offset to read from. + * @param attributeType the type of the attribute. + * @param the value to read into. + */ + public static readFromBufferTo(buffer: ABuffer, bufferOffset: int32, attributeType: int32, value: AttributeValue): void { + if (attributeType == AttributeTypes.TYPE_BOOLEAN) value.setBoolean(LittleEndian.readBufferByte(buffer, bufferOffset) != 0); + else if (attributeType == AttributeTypes.TYPE_INT1) value.setInt1(LittleEndian.readBufferByte(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_INT2) value.setInt2(LittleEndian.readBufferShort(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_INT4) value.setInt4(LittleEndian.readBufferInt(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_INT8) value.setInt8(LittleEndian.readBufferLong(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_FLOAT4) value.setFloat4(LittleEndian.readBufferFloat(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_FLOAT8) value.setFloat8(LittleEndian.readBufferDouble(buffer, bufferOffset)); + else if (attributeType == AttributeTypes.TYPE_COLOR) value.setColor(LittleEndian.readBufferInt3(buffer, bufferOffset)); + else ASystem.assertNot(true, "Cannot read attribute value type " + attributeType); + } + + /** + * Read an attribute value. + * @param input the input stream to read from. + * @param attributeType the type of the attribute. + * @param the value to read into. + */ + public static readFromStreamTo(stream: InStream, attributeType: int32, value: AttributeValue): void { + if (attributeType == AttributeTypes.TYPE_BOOLEAN) value.setBoolean(LittleEndian.readStreamByte(stream) != 0); + else if (attributeType == AttributeTypes.TYPE_INT1) value.setInt1(LittleEndian.readStreamByte(stream)); + else if (attributeType == AttributeTypes.TYPE_INT2) value.setInt2(LittleEndian.readStreamShort(stream)); + else if (attributeType == AttributeTypes.TYPE_INT4) value.setInt4(LittleEndian.readStreamInt(stream)); + else if (attributeType == AttributeTypes.TYPE_INT8) value.setInt8(LittleEndian.readStreamLong(stream)); + else if (attributeType == AttributeTypes.TYPE_FLOAT4) value.setFloat4(LittleEndian.readStreamFloat(stream)); + else if (attributeType == AttributeTypes.TYPE_FLOAT8) value.setFloat8(LittleEndian.readStreamDouble(stream)); + else if (attributeType == AttributeTypes.TYPE_COLOR) value.setColor(LittleEndian.readStreamInt3(stream)); + else ASystem.assertNot(true, "Cannot read attribute value type " + attributeType); + } + + /** + * Read an attribute value. + * @param input the input stream to read from. + * @param attributeType the type of the attribute. + * @return the value. + */ + public static readFromStream(stream: InStream, attributeType: int32): AttributeValue { + let value: AttributeValue = new AttributeValue(); + AttributeValue.readFromStreamTo(stream, attributeType, value); + return value; + } + + /** + * Write an attribute value. + * @param output the output stream to write to. + * @param attributeType the type of the attribute. + * @param value the value of the attribute. + */ + public static writeToStream(stream: OutStream, attributeType: int32, value: AttributeValue): void { + if (attributeType == AttributeTypes.TYPE_BOOLEAN) LittleEndian.writeStreamByte(stream, value.getBooleanAsInt()); + else if (attributeType == AttributeTypes.TYPE_INT1) LittleEndian.writeStreamByte(stream, value.getInt1()); + else if (attributeType == AttributeTypes.TYPE_INT2) LittleEndian.writeStreamShort(stream, value.getInt2()); + else if (attributeType == AttributeTypes.TYPE_INT4) LittleEndian.writeStreamInt(stream, value.getInt4()); + else if (attributeType == AttributeTypes.TYPE_INT8) LittleEndian.writeStreamLong(stream, value.getInt8()); + else if (attributeType == AttributeTypes.TYPE_FLOAT4) LittleEndian.writeStreamFloat(stream, value.getFloat4()); + else if (attributeType == AttributeTypes.TYPE_FLOAT8) LittleEndian.writeStreamDouble(stream, value.getFloat8()); + else if (attributeType == AttributeTypes.TYPE_COLOR) LittleEndian.writeStreamInt3(stream, value.getColor()); + else ASystem.assertNot(true, "Cannot write attribute value type " + attributeType); + } } diff --git a/core/orbitgt/src/pointcloud/model/BlockIndex.ts b/core/orbitgt/src/pointcloud/model/BlockIndex.ts index 373fffb21886..0cbe320ad150 100644 --- a/core/orbitgt/src/pointcloud/model/BlockIndex.ts +++ b/core/orbitgt/src/pointcloud/model/BlockIndex.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ALong } from "../../system/runtime/ALong"; import { GridIndex } from "./GridIndex"; @@ -25,54 +24,54 @@ import { GridIndex } from "./GridIndex"; */ /** @internal */ export class BlockIndex { - /** The level */ - public level: int32; - /** The unique key of the block */ - public key: string; - /** The index of the block in the level */ - public index: int32; - /** The grid index */ - public gridIndex: GridIndex; - /** The index of the first tile in the block (derived) */ - public tileIndex: int32; - /** The tile count */ - public tileCount: int32; - /** The index of the first point in the block (derived) */ - public pointIndex: ALong; - /** The point count */ - public pointCount: ALong; - /** The last access time */ - public accessTime: float64; + /** The level */ + public level: int32; + /** The unique key of the block */ + public key: string; + /** The index of the block in the level */ + public index: int32; + /** The grid index */ + public gridIndex: GridIndex; + /** The index of the first tile in the block (derived) */ + public tileIndex: int32; + /** The tile count */ + public tileCount: int32; + /** The index of the first point in the block (derived) */ + public pointIndex: ALong; + /** The point count */ + public pointCount: ALong; + /** The last access time */ + public accessTime: float64; - /** - * Create a new index. - */ - public constructor(level: int32, index: int32, gridIndex: GridIndex, tileIndex: int32, tileCount: int32, pointIndex: ALong, pointCount: ALong) { - this.level = level; - this.index = index; - this.gridIndex = gridIndex; - this.tileIndex = tileIndex; - this.tileCount = tileCount; - this.pointIndex = pointIndex; - this.pointCount = pointCount; - this.accessTime = 0.0; - this.key = ("L" + this.level + ",B:" + this.index); - } + /** + * Create a new index. + */ + public constructor(level: int32, index: int32, gridIndex: GridIndex, tileIndex: int32, tileCount: int32, pointIndex: ALong, pointCount: ALong) { + this.level = level; + this.index = index; + this.gridIndex = gridIndex; + this.tileIndex = tileIndex; + this.tileCount = tileCount; + this.pointIndex = pointIndex; + this.pointCount = pointCount; + this.accessTime = 0.0; + this.key = "L" + this.level + ",B:" + this.index; + } - /** - * Check if two indexes are the same. - * @param other another index. - * @return true if same. - */ - public same(other: BlockIndex): boolean { - return (other.level == this.level) && (other.index == this.index); - } + /** + * Check if two indexes are the same. + * @param other another index. + * @return true if same. + */ + public same(other: BlockIndex): boolean { + return (other.level == this.level) && (other.index == this.index); + } - /** - * Get the unique key of the block in the pointcloud file. - * @return the unique key (combines level and grid index). - */ - public getKey(): string { - return "B" + this.level + "/" + this.gridIndex.x + "/" + this.gridIndex.y + "/" + this.gridIndex.z; - } + /** + * Get the unique key of the block in the pointcloud file. + * @return the unique key (combines level and grid index). + */ + public getKey(): string { + return "B" + this.level + "/" + this.gridIndex.x + "/" + this.gridIndex.y + "/" + this.gridIndex.z; + } } diff --git a/core/orbitgt/src/pointcloud/model/CloudPoint.ts b/core/orbitgt/src/pointcloud/model/CloudPoint.ts index 1f871c15c488..252400c09135 100644 --- a/core/orbitgt/src/pointcloud/model/CloudPoint.ts +++ b/core/orbitgt/src/pointcloud/model/CloudPoint.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -28,348 +28,351 @@ import { PointAttribute } from "./PointAttribute"; */ /** @internal */ export class CloudPoint { - /** The name of this module */ - private static readonly MODULE: string = "CloudPoint"; - - /** The index */ - private _index: ALong; - /** The x position */ - private _x: float64; - /** The y position */ - private _y: float64; - /** The z position */ - private _z: float64; - /** The ARGB color */ - private _color: int32; - /** The intensity */ - private _intensity: int32; - /** The weight */ - private _weight: int32; - /** Has the point been selected? */ - private _selected: boolean; - - /** The definitions of the extra attributes */ - private _attributes: Array; - /** The values of the extra attributes */ - private _values: Array; - - /** - * Create a new point. - */ - public constructor() { - this._index = ALong.ZERO; - this._x = 0.0; - this._y = 0.0; - this._z = 0.0; - this._color = 0; - this._intensity = 0; - this._weight = 0; - this._selected = false; - this._attributes = null; - this._values = null; - } - - /** - * Create a new point. - * @param index the index of the point. - * @param x the x position. - * @param y the y position. - * @param z the z position. - * @param color the ARGB color. - * @param intensity the intensity. - * @return the new point. - */ - public static create(index: ALong, x: float64, y: float64, z: float64, color: int32, intensity: int32): CloudPoint { - let point: CloudPoint = new CloudPoint(); - point._index = index; - point._x = x; - point._y = y; - point._z = z; - point._color = color; - point._intensity = intensity; - return point; - } - - /** - * Create a new point. - * @param attributes the definitions of the attributes. - * @return the new point. - */ - public static createWithAttributes(attributes: Array): CloudPoint { - let point: CloudPoint = new CloudPoint(); - point._attributes = attributes; - if (attributes != null) { - point._values = new Array(attributes.length); - for (let i: number = 0; i < attributes.length; i++) point._values[i] = new AttributeValue(); - } - return point; - } - - /** - * Clear the point. - */ - public clear(): void { - this._index = ALong.ZERO; - this._x = 0.0; - this._y = 0.0; - this._z = 0.0; - this._color = 0; - this._intensity = 0; - this._weight = 0; - this._selected = false; - } - - /** - * Get the index. - * @return the index. - */ - public getIndex(): ALong { - return this._index; - } - - /** - * Set the index. - * @param index the index. - */ - public setIndex(index: ALong): void { - this._index = index; - } - - /** - * Get the x position. - * @return the x position. - */ - public getX(): float64 { - return this._x; - } - - /** - * Set the x position. - * @param x the new x position. - */ - public setX(x: float64): void { - this._x = x; - } - - /** - * Get the y position. - * @return the y position. - */ - public getY(): float64 { - return this._y; - } - - /** - * Set the y position. - * @param y the new y position. - */ - public setY(y: float64): void { - this._y = y; - } - - /** - * Get the z position. - * @return the z position. - */ - public getZ(): float64 { - return this._z; - } - - /** - * Set the z position. - * @param z the new z position. - */ - public setZ(z: float64): void { - this._z = z; - } - - /** - * Get the ARGB color. - * @return the color. - */ - public getColor(): int32 { - return this._color; - } - - /** - * Set the color. - * @param color the new color. - */ - public setColor(color: int32): void { - this._color = color; - } - - /** - * Get the intensity. - * @return the intensity. - */ - public getIntensity(): int32 { - return this._intensity; - } - - /** - * Set the intensity. - * @param intensity the new intensity. - */ - public setIntensity(intensity: int32): void { - this._intensity = intensity; - } - - /** - * Get the weight. - * @return the weight. - */ - public getWeight(): int32 { - return this._weight; - } - - /** - * Set the weight. - * @param weight the weight. - */ - public setWeight(weight: int32): void { - this._weight = weight; - } - - /** - * Has the point been selected? - * @return true if selected. - */ - public isSelected(): boolean { - return this._selected; - } - - /** - * Select the point. - * @param selected true if the point has been selected. - */ - public setSelected(selected: boolean): void { - this._selected = selected; - } - - /** - * Get the attribute definitions. - * @return the attribute definitions. - */ - public getAttributes(): Array { - return this._attributes; - } - - /** - * Get an attribute definitions. - * @param index the index of the attribute. - * @return an attribute definitions. - */ - public getAttribute(index: int32): PointAttribute { - return this._attributes[index]; - } - - /** - * Get the attribute values. - * @return the attribute values. - */ - public getAttributeValues(): Array { - return this._values; - } - - /** - * Get an attribute value. - * @param index the index of the value. - * @return the value. - */ - public getAttributeValue(index: int32): AttributeValue { - return this._values[index]; - } - - /** - * Get an attribute value. - * @param attributeName the name of the attribute. - * @return the value. - */ - public getNamedAttributeValue(attributeName: string): AttributeValue { - let index: int32 = PointAttribute.indexOfName(this._attributes, attributeName); - return (index < 0) ? (null) : this._values[index]; - } - - /** - * Set the attributes. - * @param attributes the definitions of the attributes. - * @param values the values of the attributes. - */ - public setAttributes(attributes: Array, values: Array): void { - this._attributes = attributes; - this._values = values; - } - - /** - * Copy the values to another point. - * @param other the other point. - */ - public copyTo(other: CloudPoint): void { - other._index = this._index; - other._x = this._x; - other._y = this._y; - other._z = this._z; - other._color = this._color; - other._intensity = this._intensity; - other._weight = this._weight; - other._selected = this._selected; - other._attributes = this._attributes; - other._values = AttributeValue.copyList(this._values); - } - - /** - * Make a copy. - * @return a copy. - */ - public copy(): CloudPoint { - let copy: CloudPoint = new CloudPoint(); - this.copyTo(copy); - return copy; - } - - /** - * Get the distance to another point. - * @param other the other point. - * @return the distance. - */ - public getDistance(other: CloudPoint): float64 { - let dx: float64 = (other._x - this._x); - let dy: float64 = (other._y - this._y); - let dz: float64 = (other._z - this._z); - return Math.sqrt(dx * dx + dy * dy + dz * dz); - } - - /** - * Get the square distance to another point. - * @param other the other point. - * @return the square distance. - */ - public getSquareDistance(other: CloudPoint): float64 { - let dx: float64 = (other._x - this._x); - let dy: float64 = (other._y - this._y); - let dz: float64 = (other._z - this._z); - return (dx * dx + dy * dy + dz * dz); - } - - /** - * Get a coordinate. - * @return a coordinate. - */ - public getCoordinate(): Coordinate { - return new Coordinate(this._x, this._y, this._z); - } - - /** - * Print the point. - */ - public print(): void { - Message.print(CloudPoint.MODULE, "Index: " + this._index); - Message.print(CloudPoint.MODULE, "Position: " + this._x + "," + this._y + "," + this._z); - Message.print(CloudPoint.MODULE, "Color: " + Numbers.rgbToString(this._color)); - Message.print(CloudPoint.MODULE, "Intensity: " + this._intensity); - Message.print(CloudPoint.MODULE, "Weight: " + this._weight); - Message.print(CloudPoint.MODULE, "Selected? " + this._selected); - if (this._attributes != null) for (let i: number = 0; i < this._attributes.length; i++) Message.print(CloudPoint.MODULE, "Attribute '" + this._attributes[i].getName() + "': " + this._values[i]); - } + /** The name of this module */ + private static readonly MODULE: string = "CloudPoint"; + + /** The index */ + private _index: ALong; + /** The x position */ + private _x: float64; + /** The y position */ + private _y: float64; + /** The z position */ + private _z: float64; + /** The ARGB color */ + private _color: int32; + /** The intensity */ + private _intensity: int32; + /** The weight */ + private _weight: int32; + /** Has the point been selected? */ + private _selected: boolean; + + /** The definitions of the extra attributes */ + private _attributes: Array; + /** The values of the extra attributes */ + private _values: Array; + + /** + * Create a new point. + */ + public constructor() { + this._index = ALong.ZERO; + this._x = 0.0; + this._y = 0.0; + this._z = 0.0; + this._color = 0; + this._intensity = 0; + this._weight = 0; + this._selected = false; + this._attributes = null; + this._values = null; + } + + /** + * Create a new point. + * @param index the index of the point. + * @param x the x position. + * @param y the y position. + * @param z the z position. + * @param color the ARGB color. + * @param intensity the intensity. + * @return the new point. + */ + public static create(index: ALong, x: float64, y: float64, z: float64, color: int32, intensity: int32): CloudPoint { + let point: CloudPoint = new CloudPoint(); + point._index = index; + point._x = x; + point._y = y; + point._z = z; + point._color = color; + point._intensity = intensity; + return point; + } + + /** + * Create a new point. + * @param attributes the definitions of the attributes. + * @return the new point. + */ + public static createWithAttributes(attributes: Array): CloudPoint { + let point: CloudPoint = new CloudPoint(); + point._attributes = attributes; + if (attributes != null) { + point._values = new Array(attributes.length); + for (let i: number = 0; i < attributes.length; i++) point._values[i] = new AttributeValue(); + } + return point; + } + + /** + * Clear the point. + */ + public clear(): void { + this._index = ALong.ZERO; + this._x = 0.0; + this._y = 0.0; + this._z = 0.0; + this._color = 0; + this._intensity = 0; + this._weight = 0; + this._selected = false; + } + + /** + * Get the index. + * @return the index. + */ + public getIndex(): ALong { + return this._index; + } + + /** + * Set the index. + * @param index the index. + */ + public setIndex(index: ALong): void { + this._index = index; + } + + /** + * Get the x position. + * @return the x position. + */ + public getX(): float64 { + return this._x; + } + + /** + * Set the x position. + * @param x the new x position. + */ + public setX(x: float64): void { + this._x = x; + } + + /** + * Get the y position. + * @return the y position. + */ + public getY(): float64 { + return this._y; + } + + /** + * Set the y position. + * @param y the new y position. + */ + public setY(y: float64): void { + this._y = y; + } + + /** + * Get the z position. + * @return the z position. + */ + public getZ(): float64 { + return this._z; + } + + /** + * Set the z position. + * @param z the new z position. + */ + public setZ(z: float64): void { + this._z = z; + } + + /** + * Get the ARGB color. + * @return the color. + */ + public getColor(): int32 { + return this._color; + } + + /** + * Set the color. + * @param color the new color. + */ + public setColor(color: int32): void { + this._color = color; + } + + /** + * Get the intensity. + * @return the intensity. + */ + public getIntensity(): int32 { + return this._intensity; + } + + /** + * Set the intensity. + * @param intensity the new intensity. + */ + public setIntensity(intensity: int32): void { + this._intensity = intensity; + } + + /** + * Get the weight. + * @return the weight. + */ + public getWeight(): int32 { + return this._weight; + } + + /** + * Set the weight. + * @param weight the weight. + */ + public setWeight(weight: int32): void { + this._weight = weight; + } + + /** + * Has the point been selected? + * @return true if selected. + */ + public isSelected(): boolean { + return this._selected; + } + + /** + * Select the point. + * @param selected true if the point has been selected. + */ + public setSelected(selected: boolean): void { + this._selected = selected; + } + + /** + * Get the attribute definitions. + * @return the attribute definitions. + */ + public getAttributes(): Array { + return this._attributes; + } + + /** + * Get an attribute definitions. + * @param index the index of the attribute. + * @return an attribute definitions. + */ + public getAttribute(index: int32): PointAttribute { + return this._attributes[index]; + } + + /** + * Get the attribute values. + * @return the attribute values. + */ + public getAttributeValues(): Array { + return this._values; + } + + /** + * Get an attribute value. + * @param index the index of the value. + * @return the value. + */ + public getAttributeValue(index: int32): AttributeValue { + return this._values[index]; + } + + /** + * Get an attribute value. + * @param attributeName the name of the attribute. + * @return the value. + */ + public getNamedAttributeValue(attributeName: string): AttributeValue { + let index: int32 = PointAttribute.indexOfName(this._attributes, attributeName); + return (index < 0) ? (null) : this._values[index]; + } + + /** + * Set the attributes. + * @param attributes the definitions of the attributes. + * @param values the values of the attributes. + */ + public setAttributes(attributes: Array, values: Array): void { + this._attributes = attributes; + this._values = values; + } + + /** + * Copy the values to another point. + * @param other the other point. + */ + public copyTo(other: CloudPoint): void { + other._index = this._index; + other._x = this._x; + other._y = this._y; + other._z = this._z; + other._color = this._color; + other._intensity = this._intensity; + other._weight = this._weight; + other._selected = this._selected; + other._attributes = this._attributes; + other._values = AttributeValue.copyList(this._values); + } + + /** + * Make a copy. + * @return a copy. + */ + public copy(): CloudPoint { + let copy: CloudPoint = new CloudPoint(); + this.copyTo(copy); + return copy; + } + + /** + * Get the distance to another point. + * @param other the other point. + * @return the distance. + */ + public getDistance(other: CloudPoint): float64 { + let dx: float64 = other._x - this._x; + let dy: float64 = other._y - this._y; + let dz: float64 = other._z - this._z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); + } + + /** + * Get the square distance to another point. + * @param other the other point. + * @return the square distance. + */ + public getSquareDistance(other: CloudPoint): float64 { + let dx: float64 = other._x - this._x; + let dy: float64 = other._y - this._y; + let dz: float64 = other._z - this._z; + return (dx * dx + dy * dy + dz * dz); + } + + /** + * Get a coordinate. + * @return a coordinate. + */ + public getCoordinate(): Coordinate { + return new Coordinate(this._x, this._y, this._z); + } + + /** + * Print the point. + */ + public print(): void { + Message.print(CloudPoint.MODULE, "Index: " + this._index); + Message.print(CloudPoint.MODULE, "Position: " + this._x + "," + this._y + "," + this._z); + Message.print(CloudPoint.MODULE, "Color: " + Numbers.rgbToString(this._color)); + Message.print(CloudPoint.MODULE, "Intensity: " + this._intensity); + Message.print(CloudPoint.MODULE, "Weight: " + this._weight); + Message.print(CloudPoint.MODULE, "Selected? " + this._selected); + if (this._attributes != null) { + for (let i: number = 0; i < this._attributes.length; i++) + Message.print(CloudPoint.MODULE, "Attribute '" + this._attributes[i].getName() + "': " + this._values[i]); + } + } } diff --git a/core/orbitgt/src/pointcloud/model/Grid.ts b/core/orbitgt/src/pointcloud/model/Grid.ts index ef8cc06214d8..d30fe4a515be 100644 --- a/core/orbitgt/src/pointcloud/model/Grid.ts +++ b/core/orbitgt/src/pointcloud/model/Grid.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -26,125 +26,126 @@ import { GridIndex } from "./GridIndex"; */ /** @internal */ export class Grid { - /** The x origin */ - public p0: Coordinate; - /** The cell X size */ - public size: Coordinate; + /** The x origin */ + public p0: Coordinate; + /** The cell X size */ + public size: Coordinate; - /** - * Create a new grid. - * @param x0 the x origin. - * @param y0 the y origin. - * @param z0 the z origin. - * @param sizeX the cell X size. - * @param sizeY the cell Y size. - * @param sizeZ the cell Z size. - */ - public constructor(p0: Coordinate, size: Coordinate) { - this.p0 = p0; - this.size = size; - } + /** + * Create a new grid. + * @param x0 the x origin. + * @param y0 the y origin. + * @param z0 the z origin. + * @param sizeX the cell X size. + * @param sizeY the cell Y size. + * @param sizeZ the cell Z size. + */ + public constructor(p0: Coordinate, size: Coordinate) { + this.p0 = p0; + this.size = size; + } - /** - * Get the cell index of an X position. - * @param x the x position. - * @return the cell index. - */ - public getCellX(x: float64): float64 { - return (x - this.p0.x) / this.size.x; - } + /** + * Get the cell index of an X position. + * @param x the x position. + * @return the cell index. + */ + public getCellX(x: float64): float64 { + return (x - this.p0.x) / this.size.x; + } - /** - * Get the cell index of a Y position. - * @param y the y position. - * @return the cell index. - */ - public getCellY(y: float64): float64 { - return (y - this.p0.y) / this.size.y; - } + /** + * Get the cell index of a Y position. + * @param y the y position. + * @return the cell index. + */ + public getCellY(y: float64): float64 { + return (y - this.p0.y) / this.size.y; + } - /** - * Get the cell index of a Z position. - * @param z the z position. - * @return the cell index. - */ - public getCellZ(z: float64): float64 { - return (z - this.p0.z) / this.size.z; - } + /** + * Get the cell index of a Z position. + * @param z the z position. + * @return the cell index. + */ + public getCellZ(z: float64): float64 { + return (z - this.p0.z) / this.size.z; + } - /** - * Get the cell index of a position. - * @param position the position. - * @param cellIndex the cell index. - */ - public getCellIndexTo(position: Coordinate, cellIndex: GridIndex): GridIndex { - cellIndex.x = Numbers.intFloor((position.x - this.p0.x) / this.size.x); - cellIndex.y = Numbers.intFloor((position.y - this.p0.y) / this.size.y); - cellIndex.z = Numbers.intFloor((position.z - this.p0.z) / this.size.z); - return cellIndex; - } + /** + * Get the cell index of a position. + * @param position the position. + * @param cellIndex the cell index. + */ + public getCellIndexTo(position: Coordinate, cellIndex: GridIndex): GridIndex { + cellIndex.x = Numbers.intFloor((position.x - this.p0.x) / this.size.x); + cellIndex.y = Numbers.intFloor((position.y - this.p0.y) / this.size.y); + cellIndex.z = Numbers.intFloor((position.z - this.p0.z) / this.size.z); + return cellIndex; + } - /** - * Get the cell index of a position. - * @param position the position. - * @return the cell index. - */ - public getCellIndex(position: Coordinate): GridIndex { - return this.getCellIndexTo(position, new GridIndex(0, 0, 0)); - } + /** + * Get the cell index of a position. + * @param position the position. + * @return the cell index. + */ + public getCellIndex(position: Coordinate): GridIndex { + return this.getCellIndexTo(position, new GridIndex(0, 0, 0)); + } - /** - * Get the center point of a cell. - * @param cellIndex the index of the cell. - * @return the center point. - */ - public getCellCenter(cellIndex: GridIndex): Coordinate { - let cx: float64 = this.p0.x + (cellIndex.x + 0.5) * this.size.x; - let cy: float64 = this.p0.y + (cellIndex.y + 0.5) * this.size.y; - let cz: float64 = this.p0.z + (cellIndex.z + 0.5) * this.size.z; - return new Coordinate(cx, cy, cz); - } + /** + * Get the center point of a cell. + * @param cellIndex the index of the cell. + * @return the center point. + */ + public getCellCenter(cellIndex: GridIndex): Coordinate { + let cx: float64 = this.p0.x + (cellIndex.x + 0.5) * this.size.x; + let cy: float64 = this.p0.y + (cellIndex.y + 0.5) * this.size.y; + let cz: float64 = this.p0.z + (cellIndex.z + 0.5) * this.size.z; + return new Coordinate(cx, cy, cz); + } - /** - * Get the bounds of a cell. - * @param cellIndex the index of the cell. - * @return the bounds. - */ - public getCellBounds(cellIndex: GridIndex): Bounds { - let x0: float64 = this.p0.x + (cellIndex.x) * this.size.x; - let y0: float64 = this.p0.y + (cellIndex.y) * this.size.y; - let z0: float64 = this.p0.z + (cellIndex.z) * this.size.z; - let bounds: Bounds = new Bounds(); - bounds.addXYZ(x0, y0, z0); - bounds.addXYZ(x0 + this.size.x, y0 + this.size.y, z0 + this.size.z); - return bounds; - } + /** + * Get the bounds of a cell. + * @param cellIndex the index of the cell. + * @return the bounds. + */ + public getCellBounds(cellIndex: GridIndex): Bounds { + let x0: float64 = this.p0.x + (cellIndex.x) * this.size.x; + let y0: float64 = this.p0.y + (cellIndex.y) * this.size.y; + let z0: float64 = this.p0.z + (cellIndex.z) * this.size.z; + let bounds: Bounds = new Bounds(); + bounds.addXYZ(x0, y0, z0); + bounds.addXYZ(x0 + this.size.x, y0 + this.size.y, z0 + this.size.z); + return bounds; + } - /** - * Scale the grid. - * @param scale the scale factor. - * @return the scaled grid. - */ - public scale(scale: float64): Grid { - return new Grid(new Coordinate(this.p0.x, this.p0.y, this.p0.z), new Coordinate(scale * this.size.x, scale * this.size.y, scale * this.size.z)); - } + /** + * Scale the grid. + * @param scale the scale factor. + * @return the scaled grid. + */ + public scale(scale: float64): Grid { + return new Grid(new Coordinate(this.p0.x, this.p0.y, this.p0.z), new Coordinate(scale * this.size.x, scale * this.size.y, scale * this.size.z)); + } - /** - * Move the grid. - * @param dx the x offset. - * @param dy the y offset. - * @param dz the z offset. - * @return the scaled grid. - */ - public scale3(dx: float64, dy: float64, dz: float64): Grid { - return new Grid(new Coordinate(this.p0.x + dx, this.p0.y + dy, this.p0.z + dz), new Coordinate(this.size.x, this.size.y, this.size.z)); - } + /** + * Move the grid. + * @param dx the x offset. + * @param dy the y offset. + * @param dz the z offset. + * @return the scaled grid. + */ + public scale3(dx: float64, dy: float64, dz: float64): Grid { + return new Grid(new Coordinate(this.p0.x + dx, this.p0.y + dy, this.p0.z + dz), new Coordinate(this.size.x, this.size.y, this.size.z)); + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Grid:x0=" + this.p0.x + ",y0=" + this.p0.y + ",z0=" + this.p0.z + ",sx=" + this.size.x + ",sy=" + this.size.y + ",sz=" + this.size.z + "]"; - } + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Grid:x0=" + this.p0.x + ",y0=" + this.p0.y + ",z0=" + this.p0.z + ",sx=" + this.size.x + ",sy=" + this.size.y + ",sz=" + this.size.z + + "]"; + } } diff --git a/core/orbitgt/src/pointcloud/model/GridIndex.ts b/core/orbitgt/src/pointcloud/model/GridIndex.ts index 9f7fc78a72d9..c3e97c3d0c5e 100644 --- a/core/orbitgt/src/pointcloud/model/GridIndex.ts +++ b/core/orbitgt/src/pointcloud/model/GridIndex.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -18,96 +18,96 @@ import { Numbers } from "../../system/runtime/Numbers"; /** @internal */ export class GridIndex { - /** The x index */ - public x: int32; - /** The y index */ - public y: int32; - /** The z index */ - public z: int32; + /** The x index */ + public x: int32; + /** The y index */ + public y: int32; + /** The z index */ + public z: int32; - /** - * Create a new point. - * @param x the x index. - * @param y the y index. - * @param z the z index. - */ - public constructor(x: int32, y: int32, z: int32) { - this.x = x; - this.y = y; - this.z = z; - } + /** + * Create a new point. + * @param x the x index. + * @param y the y index. + * @param z the z index. + */ + public constructor(x: int32, y: int32, z: int32) { + this.x = x; + this.y = y; + this.z = z; + } - /** - * Get the square distance to another cell. - * @param other the other cell. - * @return the square distance. - */ - public distanceSq(other: GridIndex): int32 { - let dx: int32 = (other.x - this.x); - let dy: int32 = (other.y - this.y); - let dz: int32 = (other.z - this.z); - return (dx * dx) + (dy * dy) + (dz * dz); - } + /** + * Get the square distance to another cell. + * @param other the other cell. + * @return the square distance. + */ + public distanceSq(other: GridIndex): int32 { + let dx: int32 = other.x - this.x; + let dy: int32 = other.y - this.y; + let dz: int32 = other.z - this.z; + return (dx * dx) + (dy * dy) + (dz * dz); + } - /** - * Get the distance to another cell. - * @param other the other cell. - * @return the distance. - */ - public distance(other: GridIndex): float64 { - return Numbers.sqrt(this.distanceSq(other)); - } + /** + * Get the distance to another cell. + * @param other the other cell. + * @return the distance. + */ + public distance(other: GridIndex): float64 { + return Numbers.sqrt(this.distanceSq(other)); + } - /** - * Get a next-level index. - * @param index the index at the current level. - * @return the next-level index. - */ - private static getNextLevelIndex1(index: int32): int32 { - if (index < 0) return Numbers.divInt(index - 1, 2); - return Numbers.divInt(index, 2); - } + /** + * Get a next-level index. + * @param index the index at the current level. + * @return the next-level index. + */ + private static getNextLevelIndex1(index: int32): int32 { + if (index < 0) return Numbers.divInt(index - 1, 2); + return Numbers.divInt(index, 2); + } - /** - * Get a next-level index. - * @param nextLevel the index at the next level. - */ - public getNextLevelIndex(nextLevel: GridIndex): void { - nextLevel.x = GridIndex.getNextLevelIndex1(this.x); - nextLevel.y = GridIndex.getNextLevelIndex1(this.y); - nextLevel.z = GridIndex.getNextLevelIndex1(this.z); - } + /** + * Get a next-level index. + * @param nextLevel the index at the next level. + */ + public getNextLevelIndex(nextLevel: GridIndex): void { + nextLevel.x = GridIndex.getNextLevelIndex1(this.x); + nextLevel.y = GridIndex.getNextLevelIndex1(this.y); + nextLevel.z = GridIndex.getNextLevelIndex1(this.z); + } - /** - * Does this point equal another? - * @param other the other point. - * @return true if equal. - */ - public same(other: GridIndex): boolean { - return (other.x == this.x && other.y == this.y && other.z == this.z); - } + /** + * Does this point equal another? + * @param other the other point. + * @return true if equal. + */ + public same(other: GridIndex): boolean { + return (other.x == this.x && other.y == this.y && other.z == this.z); + } - /** - * Create a copy. - * @return a copy. - */ - public copy(): GridIndex { - return new GridIndex(this.x, this.y, this.z); - } + /** + * Create a copy. + * @return a copy. + */ + public copy(): GridIndex { + return new GridIndex(this.x, this.y, this.z); + } - /** - * Get the unique key. - * @return the unique key. - */ - public getKey(): string { - return "{x:" + this.x + ",y:" + this.y + ",z:" + this.z + "}"; - } + /** + * Get the unique key. + * @return the unique key. + */ + public getKey(): string { + return "{x:" + this.x + ",y:" + this.y + ",z:" + this.z + "}"; + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[GridPoint3D:" + this.x + "," + this.y + "," + this.z + "]"; - } + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[GridPoint3D:" + this.x + "," + this.y + "," + this.z + "]"; + } } diff --git a/core/orbitgt/src/pointcloud/model/PointAttribute.ts b/core/orbitgt/src/pointcloud/model/PointAttribute.ts index 280b28f9ab42..6140a6ee5544 100644 --- a/core/orbitgt/src/pointcloud/model/PointAttribute.ts +++ b/core/orbitgt/src/pointcloud/model/PointAttribute.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -28,345 +28,345 @@ import { AttributeValue } from "./AttributeValue"; */ /** @internal */ export class PointAttribute { - /** The name of the attribute */ - private _name: string; - /** The description of the attribute */ - private _description: string; - /** The type of the attribute */ - private _type: int32; - /** The default value of the attribute */ - private _defaultValue: AttributeValue; - /** The optional minimum value of the attribute */ - private _minValue: AttributeValue; - /** The optional maximum value of the attribute */ - private _maxValue: AttributeValue; - - /** Is this a standard attribute? (color/intensity/weight)? */ - private _standardAttribute: boolean; - - /** - * Create a new point attribute. - * @param name the name of the attribute. - * @param description the description of the attribute. - * @param type the type of the attribute. - * @param default value the default value of the attribute (use null to create a default value). - */ - public constructor(name: string, description: string, type: int32, defaultValue: AttributeValue) { - if (defaultValue == null) defaultValue = AttributeValue.createDefault(type); - ASystem.assert0(defaultValue.getType() == type, "Default value " + defaultValue + " does not match attribute type " + type); - this._name = name; - this._description = description; - this._type = type; - this._defaultValue = defaultValue; - this._minValue = null; - this._maxValue = null; - this._standardAttribute = false; - } - - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } - - /** - * Set the name. - * @param name the new name. - */ - public setName(name: string): void { - this._name = name; - } - - /** - * Check the name. - * @param name the name to check. - * @return true if equal. - */ - public hasName(name: string): boolean { - if (name == null) return false; - if (Strings.equalsIgnoreCase(name, this._name)) return true; - return false; - } - - /** - * Get the description. - * @return the description. - */ - public getDescription(): string { - return this._description; - } - - /** - * Get the type. - * @return the type. - */ - public getType(): int32 { - return this._type; - } - - /** - * Get the byte-size of the type. - * @return the byte-size of the type. - */ - public getTypeByteSize(): int32 { - return PointAttribute.getByteSize(this._type, 1); - } - - /** - * Get the byte-size of a number of values. - * @param attributeCount the number of values. - * @return the byte-size. - */ - public getTypeByteSizeForCount(attributeCount: int32): int32 { - return PointAttribute.getByteSize(this._type, attributeCount); - } - - /** - * Get the byte-size of a number of values. - * @param attributeCount the number of values. - * @return the byte-size. - */ - public getTypeByteSizeForLongCount(attributeCount: ALong): ALong { - return PointAttribute.getByteSizeForCount(this._type, attributeCount); - } - - /** - * Get the default value. - * @return the default value. - */ - public getDefaultValue(): AttributeValue { - return this._defaultValue; - } - - /** - * Get the optional minimum value. - * @return the optional minimum value. - */ - public getMinValue(): AttributeValue { - return this._minValue; - } - - /** - * Set the optional minimum value. - * @param value the optional minimum value. - */ - public setMinValue(value: AttributeValue): void { - this._minValue = value; - } - - /** - * Get the optional maximum value. - * @return the optional maximum value. - */ - public getMaxValue(): AttributeValue { - return this._maxValue; - } - - /** - * Set the optional maximum value. - * @param value the optional maximum value. - */ - public setMaxValue(value: AttributeValue): void { - this._maxValue = value; - } - - /** - * Set the description of a copy. - * @param description the new description. - * @return the copy. - */ - public setDescription(description: string): PointAttribute { - return new PointAttribute(this._name, description, this._type, this._defaultValue); - } - - /** - * Is this a standard attribute (like color/intensity/weight)? - * @return true for a standard attribute. - */ - public isStandardAttribute(): boolean { - return this._standardAttribute; - } - - /** - * Make this a standard attribute (like color/intensity/weight). - * @param standard true if this is a standard attribute. - * @return this attribute for convenience. - */ - public setStandardAttribute(standard: boolean): PointAttribute { - this._standardAttribute = standard; - return this; - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[PointAttribute:name='" + this._name + "',type=" + PointAttribute.getTypeName(this._type) + ",default=" + this._defaultValue + "]"; - } - - /** - * Get the name of a type. - * @param attributeType the type of attributes. - * @return the name. - */ - public static getTypeName(attributeType: int32): string { - if (attributeType <= 0) return "none"; - if (attributeType == AttributeTypes.TYPE_BOOLEAN) return "boolean"; - if (attributeType == AttributeTypes.TYPE_INT1) return "int1"; - if (attributeType == AttributeTypes.TYPE_INT2) return "int2"; - if (attributeType == AttributeTypes.TYPE_INT4) return "int4"; - if (attributeType == AttributeTypes.TYPE_INT8) return "int8"; - if (attributeType == AttributeTypes.TYPE_FLOAT4) return "float4"; - if (attributeType == AttributeTypes.TYPE_FLOAT8) return "float8"; - if (attributeType == AttributeTypes.TYPE_COLOR) return "color"; - return "" + attributeType; - } - - /** - * Get the bit size for a type. - * @param attributeType the type of attributes. - * @return the number of bits. - */ - public static getBitSize(attributeType: int32): int32 { - if (attributeType == AttributeTypes.TYPE_BOOLEAN) return 1; - if (attributeType == AttributeTypes.TYPE_INT1) return 8; - if (attributeType == AttributeTypes.TYPE_INT2) return 16; - if (attributeType == AttributeTypes.TYPE_INT4) return 32; - if (attributeType == AttributeTypes.TYPE_INT8) return 64; - if (attributeType == AttributeTypes.TYPE_FLOAT4) return 32; - if (attributeType == AttributeTypes.TYPE_FLOAT8) return 64; - if (attributeType == AttributeTypes.TYPE_COLOR) return 24; - return 0; - } - - /** - * Get the byte size for a number of attributes. - * @param attributeType the type of attributes. - * @param attributeCount the number of attributes. - */ - public static getByteSize(attributeType: int32, attributeCount: int32): int32 { - if (attributeCount <= 0) return 0; - if (attributeType == AttributeTypes.TYPE_BOOLEAN) return ((attributeCount - 1) >> 3) + 1; - if (attributeType == AttributeTypes.TYPE_INT1) return (attributeCount); - if (attributeType == AttributeTypes.TYPE_INT2) return (attributeCount << 1); - if (attributeType == AttributeTypes.TYPE_INT4) return (attributeCount << 2); - if (attributeType == AttributeTypes.TYPE_INT8) return (attributeCount << 3); - if (attributeType == AttributeTypes.TYPE_FLOAT4) return (attributeCount << 2); - if (attributeType == AttributeTypes.TYPE_FLOAT8) return (attributeCount << 3); - if (attributeType == AttributeTypes.TYPE_COLOR) return (attributeCount * 3); - return 0; - } - - /** - * Get the byte size for a number of attributes. - * @param attributeType the type of attributes. - * @param attributeCount the number of attributes. - */ - public static getByteSizeForCount(attributeType: int32, attributeCount: ALong): ALong { - if (attributeCount.isPositive() == false) return ALong.ZERO; - if (attributeType == AttributeTypes.TYPE_BOOLEAN) return attributeCount.subInt(1).divInt(8).addInt(1); - if (attributeType == AttributeTypes.TYPE_INT1) return attributeCount.mulInt(1); - if (attributeType == AttributeTypes.TYPE_INT2) return attributeCount.mulInt(2); - if (attributeType == AttributeTypes.TYPE_INT4) return attributeCount.mulInt(4); - if (attributeType == AttributeTypes.TYPE_INT8) return attributeCount.mulInt(8); - if (attributeType == AttributeTypes.TYPE_FLOAT4) return attributeCount.mulInt(4); - if (attributeType == AttributeTypes.TYPE_FLOAT8) return attributeCount.mulInt(8); - if (attributeType == AttributeTypes.TYPE_COLOR) return attributeCount.mulInt(3); - return ALong.ZERO; - } - - /** - * Find the index of an attribute. - * @param attributes the list of attributes. - * @param attributeName the name of an attribute. - * @return the index (negative if not found). - */ - public static indexOfName(attributes: Array, attributeName: string): int32 { - if (attributes == null) return -1; - if (attributeName == null) return -1; - for (let i: number = 0; i < attributes.length; i++) if (attributes[i].hasName(attributeName)) return i; - return -1; - } - - /** - * Find the index of an attribute. - * @param attributes the list of attributes. - * @param attribute the definition of an attribute. - * @return the index (negative if not found). - */ - public static indexOf(attributes: Array, attribute: PointAttribute): int32 { - if (attributes == null) return -1; - if (attribute == null) return -1; - for (let i: number = 0; i < attributes.length; i++) if (attributes[i].hasName(attribute.getName())) return i; - return -1; - } - - /** - * Check if an attribute exists. - * @param attributes the list of attributes. - * @param attributeName the name of an attribute. - * @return true if found. - */ - public static hasAttributeName(attributes: Array, attributeName: string): boolean { - return (PointAttribute.indexOfName(attributes, attributeName) >= 0); - } - - /** - * Check if an attribute exists. - * @param attributes the list of attributes. - * @param attribute the definition of an attribute. - * @return true if found. - */ - public static hasAttribute(attributes: Array, attribute: PointAttribute): boolean { - return (PointAttribute.indexOf(attributes, attribute) >= 0); - } - - /** - * Find the index of an attribute. - * @param attributes the list of attributes. - * @param attributeName the name of an attribute. - * @return the index (negative if not found). - */ - public static listIndexOfName(attributes: AList, attributeName: string): int32 { - if (attributes == null) return -1; - if (attributeName == null) return -1; - for (let i: number = 0; i < attributes.size(); i++) if (attributes.get(i).hasName(attributeName)) return i; - return -1; - } - - /** - * Find the index of an attribute. - * @param attributes the list of attributes. - * @param attribute the definition of an attribute. - * @return the index (negative if not found). - */ - public static listIndexOf(attributes: AList, attribute: PointAttribute): int32 { - if (attributes == null) return -1; - if (attribute == null) return -1; - for (let i: number = 0; i < attributes.size(); i++) if (attributes.get(i).hasName(attribute.getName())) return i; - return -1; - } - - /** - * Check if an attribute exists. - * @param attributes the list of attributes. - * @param attributeName the name of an attribute. - * @return true if found. - */ - public static listHasAttributeName(attributes: AList, attributeName: string): boolean { - return (PointAttribute.listIndexOfName(attributes, attributeName) >= 0); - } - - /** - * Check if an attribute exists. - * @param attributes the list of attributes. - * @param attribute the definition of an attribute. - * @return true if found. - */ - public static listHasAttribute(attributes: AList, attribute: PointAttribute): boolean { - return (PointAttribute.listIndexOf(attributes, attribute) >= 0); - } + /** The name of the attribute */ + private _name: string; + /** The description of the attribute */ + private _description: string; + /** The type of the attribute */ + private _type: int32; + /** The default value of the attribute */ + private _defaultValue: AttributeValue; + /** The optional minimum value of the attribute */ + private _minValue: AttributeValue; + /** The optional maximum value of the attribute */ + private _maxValue: AttributeValue; + + /** Is this a standard attribute? (color/intensity/weight)? */ + private _standardAttribute: boolean; + + /** + * Create a new point attribute. + * @param name the name of the attribute. + * @param description the description of the attribute. + * @param type the type of the attribute. + * @param default value the default value of the attribute (use null to create a default value). + */ + public constructor(name: string, description: string, type: int32, defaultValue: AttributeValue) { + if (defaultValue == null) defaultValue = AttributeValue.createDefault(type); + ASystem.assert0(defaultValue.getType() == type, "Default value " + defaultValue + " does not match attribute type " + type); + this._name = name; + this._description = description; + this._type = type; + this._defaultValue = defaultValue; + this._minValue = null; + this._maxValue = null; + this._standardAttribute = false; + } + + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } + + /** + * Set the name. + * @param name the new name. + */ + public setName(name: string): void { + this._name = name; + } + + /** + * Check the name. + * @param name the name to check. + * @return true if equal. + */ + public hasName(name: string): boolean { + if (name == null) return false; + if (Strings.equalsIgnoreCase(name, this._name)) return true; + return false; + } + + /** + * Get the description. + * @return the description. + */ + public getDescription(): string { + return this._description; + } + + /** + * Get the type. + * @return the type. + */ + public getType(): int32 { + return this._type; + } + + /** + * Get the byte-size of the type. + * @return the byte-size of the type. + */ + public getTypeByteSize(): int32 { + return PointAttribute.getByteSize(this._type, 1); + } + + /** + * Get the byte-size of a number of values. + * @param attributeCount the number of values. + * @return the byte-size. + */ + public getTypeByteSizeForCount(attributeCount: int32): int32 { + return PointAttribute.getByteSize(this._type, attributeCount); + } + + /** + * Get the byte-size of a number of values. + * @param attributeCount the number of values. + * @return the byte-size. + */ + public getTypeByteSizeForLongCount(attributeCount: ALong): ALong { + return PointAttribute.getByteSizeForCount(this._type, attributeCount); + } + + /** + * Get the default value. + * @return the default value. + */ + public getDefaultValue(): AttributeValue { + return this._defaultValue; + } + + /** + * Get the optional minimum value. + * @return the optional minimum value. + */ + public getMinValue(): AttributeValue { + return this._minValue; + } + + /** + * Set the optional minimum value. + * @param value the optional minimum value. + */ + public setMinValue(value: AttributeValue): void { + this._minValue = value; + } + + /** + * Get the optional maximum value. + * @return the optional maximum value. + */ + public getMaxValue(): AttributeValue { + return this._maxValue; + } + + /** + * Set the optional maximum value. + * @param value the optional maximum value. + */ + public setMaxValue(value: AttributeValue): void { + this._maxValue = value; + } + + /** + * Set the description of a copy. + * @param description the new description. + * @return the copy. + */ + public setDescription(description: string): PointAttribute { + return new PointAttribute(this._name, description, this._type, this._defaultValue); + } + + /** + * Is this a standard attribute (like color/intensity/weight)? + * @return true for a standard attribute. + */ + public isStandardAttribute(): boolean { + return this._standardAttribute; + } + + /** + * Make this a standard attribute (like color/intensity/weight). + * @param standard true if this is a standard attribute. + * @return this attribute for convenience. + */ + public setStandardAttribute(standard: boolean): PointAttribute { + this._standardAttribute = standard; + return this; + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[PointAttribute:name='" + this._name + "',type=" + PointAttribute.getTypeName(this._type) + ",default=" + this._defaultValue + "]"; + } + + /** + * Get the name of a type. + * @param attributeType the type of attributes. + * @return the name. + */ + public static getTypeName(attributeType: int32): string { + if (attributeType <= 0) return "none"; + if (attributeType == AttributeTypes.TYPE_BOOLEAN) return "boolean"; + if (attributeType == AttributeTypes.TYPE_INT1) return "int1"; + if (attributeType == AttributeTypes.TYPE_INT2) return "int2"; + if (attributeType == AttributeTypes.TYPE_INT4) return "int4"; + if (attributeType == AttributeTypes.TYPE_INT8) return "int8"; + if (attributeType == AttributeTypes.TYPE_FLOAT4) return "float4"; + if (attributeType == AttributeTypes.TYPE_FLOAT8) return "float8"; + if (attributeType == AttributeTypes.TYPE_COLOR) return "color"; + return "" + attributeType; + } + + /** + * Get the bit size for a type. + * @param attributeType the type of attributes. + * @return the number of bits. + */ + public static getBitSize(attributeType: int32): int32 { + if (attributeType == AttributeTypes.TYPE_BOOLEAN) return 1; + if (attributeType == AttributeTypes.TYPE_INT1) return 8; + if (attributeType == AttributeTypes.TYPE_INT2) return 16; + if (attributeType == AttributeTypes.TYPE_INT4) return 32; + if (attributeType == AttributeTypes.TYPE_INT8) return 64; + if (attributeType == AttributeTypes.TYPE_FLOAT4) return 32; + if (attributeType == AttributeTypes.TYPE_FLOAT8) return 64; + if (attributeType == AttributeTypes.TYPE_COLOR) return 24; + return 0; + } + + /** + * Get the byte size for a number of attributes. + * @param attributeType the type of attributes. + * @param attributeCount the number of attributes. + */ + public static getByteSize(attributeType: int32, attributeCount: int32): int32 { + if (attributeCount <= 0) return 0; + if (attributeType == AttributeTypes.TYPE_BOOLEAN) return ((attributeCount - 1) >> 3) + 1; + if (attributeType == AttributeTypes.TYPE_INT1) return attributeCount; + if (attributeType == AttributeTypes.TYPE_INT2) return (attributeCount << 1); + if (attributeType == AttributeTypes.TYPE_INT4) return (attributeCount << 2); + if (attributeType == AttributeTypes.TYPE_INT8) return (attributeCount << 3); + if (attributeType == AttributeTypes.TYPE_FLOAT4) return (attributeCount << 2); + if (attributeType == AttributeTypes.TYPE_FLOAT8) return (attributeCount << 3); + if (attributeType == AttributeTypes.TYPE_COLOR) return (attributeCount * 3); + return 0; + } + + /** + * Get the byte size for a number of attributes. + * @param attributeType the type of attributes. + * @param attributeCount the number of attributes. + */ + public static getByteSizeForCount(attributeType: int32, attributeCount: ALong): ALong { + if (attributeCount.isPositive() == false) return ALong.ZERO; + if (attributeType == AttributeTypes.TYPE_BOOLEAN) return attributeCount.subInt(1).divInt(8).addInt(1); + if (attributeType == AttributeTypes.TYPE_INT1) return attributeCount.mulInt(1); + if (attributeType == AttributeTypes.TYPE_INT2) return attributeCount.mulInt(2); + if (attributeType == AttributeTypes.TYPE_INT4) return attributeCount.mulInt(4); + if (attributeType == AttributeTypes.TYPE_INT8) return attributeCount.mulInt(8); + if (attributeType == AttributeTypes.TYPE_FLOAT4) return attributeCount.mulInt(4); + if (attributeType == AttributeTypes.TYPE_FLOAT8) return attributeCount.mulInt(8); + if (attributeType == AttributeTypes.TYPE_COLOR) return attributeCount.mulInt(3); + return ALong.ZERO; + } + + /** + * Find the index of an attribute. + * @param attributes the list of attributes. + * @param attributeName the name of an attribute. + * @return the index (negative if not found). + */ + public static indexOfName(attributes: Array, attributeName: string): int32 { + if (attributes == null) return -1; + if (attributeName == null) return -1; + for (let i: number = 0; i < attributes.length; i++) if (attributes[i].hasName(attributeName)) return i; + return -1; + } + + /** + * Find the index of an attribute. + * @param attributes the list of attributes. + * @param attribute the definition of an attribute. + * @return the index (negative if not found). + */ + public static indexOf(attributes: Array, attribute: PointAttribute): int32 { + if (attributes == null) return -1; + if (attribute == null) return -1; + for (let i: number = 0; i < attributes.length; i++) if (attributes[i].hasName(attribute.getName())) return i; + return -1; + } + + /** + * Check if an attribute exists. + * @param attributes the list of attributes. + * @param attributeName the name of an attribute. + * @return true if found. + */ + public static hasAttributeName(attributes: Array, attributeName: string): boolean { + return (PointAttribute.indexOfName(attributes, attributeName) >= 0); + } + + /** + * Check if an attribute exists. + * @param attributes the list of attributes. + * @param attribute the definition of an attribute. + * @return true if found. + */ + public static hasAttribute(attributes: Array, attribute: PointAttribute): boolean { + return (PointAttribute.indexOf(attributes, attribute) >= 0); + } + + /** + * Find the index of an attribute. + * @param attributes the list of attributes. + * @param attributeName the name of an attribute. + * @return the index (negative if not found). + */ + public static listIndexOfName(attributes: AList, attributeName: string): int32 { + if (attributes == null) return -1; + if (attributeName == null) return -1; + for (let i: number = 0; i < attributes.size(); i++) if (attributes.get(i).hasName(attributeName)) return i; + return -1; + } + + /** + * Find the index of an attribute. + * @param attributes the list of attributes. + * @param attribute the definition of an attribute. + * @return the index (negative if not found). + */ + public static listIndexOf(attributes: AList, attribute: PointAttribute): int32 { + if (attributes == null) return -1; + if (attribute == null) return -1; + for (let i: number = 0; i < attributes.size(); i++) if (attributes.get(i).hasName(attribute.getName())) return i; + return -1; + } + + /** + * Check if an attribute exists. + * @param attributes the list of attributes. + * @param attributeName the name of an attribute. + * @return true if found. + */ + public static listHasAttributeName(attributes: AList, attributeName: string): boolean { + return (PointAttribute.listIndexOfName(attributes, attributeName) >= 0); + } + + /** + * Check if an attribute exists. + * @param attributes the list of attributes. + * @param attribute the definition of an attribute. + * @return true if found. + */ + public static listHasAttribute(attributes: AList, attribute: PointAttribute): boolean { + return (PointAttribute.listIndexOf(attributes, attribute) >= 0); + } } diff --git a/core/orbitgt/src/pointcloud/model/PointCloudReader.ts b/core/orbitgt/src/pointcloud/model/PointCloudReader.ts index 29fb8de942b1..6f483cbc8a24 100644 --- a/core/orbitgt/src/pointcloud/model/PointCloudReader.ts +++ b/core/orbitgt/src/pointcloud/model/PointCloudReader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { Bounds } from "../../spatial/geom/Bounds"; import { AList } from "../../system/collection/AList"; import { ALong } from "../../system/runtime/ALong"; @@ -43,186 +42,186 @@ import { TileIndex } from "./TileIndex"; */ /** @internal */ export class PointCloudReader { - /** - * Create a new reader. - */ - public constructor() { - } - - /** - * Close the reader. - */ - public close(): void { - } - - /** - * Get a certain property of the reader. - * @return the value (null if not defined). - */ - public getProperty(propertyName: string): Object { - return null; - } - - /** - * Get the storage of the file. - * @return the storage of the file. - */ - public getFileStorage(): FileStorage { - return null; - } - - /** - * Get the name of the file. - * @return the name of the file. - */ - public getFileName(): string { - return null; - } - - /** - * Get the CRS of the file. - * @return the CRS of the file. - */ - public getFileCRS(): string { - return null; - } - - /** - * Get the spatial bounds of the file. - * @return the spatial bounds of the file. - */ - public getFileBounds(): Bounds { - return null; - } - - /** - * Get the attributes of the points. - * @return the attributes of the points. - */ - public getPointAttributes(): Array { - return null; - } - - /** - * Get the minimum value of an attribute. - * @param attribute the attribute. - * @return the minimum value (null if unknown). - */ - public getMinAttributeValue(attribute: PointAttribute): AttributeValue { - return null; - } - - /** - * Get the maximum value of an attribute. - * @param attribute the attribute. - * @return the maximum value (null if unknown). - */ - public getMaxAttributeValue(attribute: PointAttribute): AttributeValue { - return null; - } - - /** - * Get the number of levels. - * @return the number of levels. - */ - public getLevelCount(): int32 { - return 0; - } - - /** - * Get the number of points. - * @param level the index of the level. - * @return the number of points. - */ - public getLevelPointCount(level: int32): ALong { - return ALong.ZERO; - } - - /** - * Get the bounds of points. - * @param level the index of the level. - * @return the bounds of points. - */ - public getLevelPointBounds(level: int32): Bounds { - return null; - } - - /** - * Get the block grid. - * @param level the index of the level. - * @return the block grid (null if there is no spatial grid). - */ - public getLevelBlockGrid(level: int32): Grid { - return null; - } - - /** - * Get the tile grid. - * @param level the index of the level. - * @return the tile grid (null if there is no spatial grid). - */ - public getLevelTileGrid(level: int32): Grid { - return null; - } - - /** - * Peek at block indexes. - * @param level the index of the level. - * @return the block indexes (zero length if the level has not yet been accessed in case of lazy loading). - */ - public peekBlockIndexes(level: int32): Array { - return null; - } - - /** - * Read block indexes (with a 2-step file content fetching sequence). - * @param level the index of the level. - * @param fileContents the file contents. - * @return the tile indexes. - */ - public readBlockIndexes(level: int32, fileContents: ContentLoader): Array { - return null; - } - - /** - * Read tile indexes (with a 2-step file content fetching sequence). - * @param block the index of the block. - * @param fileContents the file contents. - * @return the tile indexes. - */ - public readTileIndexes(block: BlockIndex, fileContents: ContentLoader): Array { - return null; - } - - /** - * Read the points of a tile (with a 2-step file content fetching sequence). - * @param tileIndex the tile index. - * @param parameters the read parameters (contains the result read statistics). - * @param fileContents the file contents. - * @param processor the point processor. - */ - public readPoints(tileIndex: TileIndex, parameters: ReadRequest, fileContents: ContentLoader): AList { - return null; - } - - /** - * Read the points of a tile (with a 2-step file content fetching sequence). - * @param tileIndex the tile index. - * @param dataFormat the data format. - * @param accessTime the current access time. - * @param fileContents the file contents. - */ - public readPointData(tileIndex: TileIndex, dataFormat: int32, accessTime: float64, fileContents: ContentLoader): PointData { - return null; - } - - /** - * Clip the reader to a certain range of levels. - * @param levelOffset the index of the first level. - * @param levelCount the number of levels. - * @return the clipped pointcloud. - */ - public clipToLevelRange(levelOffset: int32, levelCount: int32): PointCloudReader { - return null; - } + /** + * Create a new reader. + */ + public constructor() { + } + + /** + * Close the reader. + */ + public close(): void { + } + + /** + * Get a certain property of the reader. + * @return the value (null if not defined). + */ + public getProperty(propertyName: string): Object { + return null; + } + + /** + * Get the storage of the file. + * @return the storage of the file. + */ + public getFileStorage(): FileStorage { + return null; + } + + /** + * Get the name of the file. + * @return the name of the file. + */ + public getFileName(): string { + return null; + } + + /** + * Get the CRS of the file. + * @return the CRS of the file. + */ + public getFileCRS(): string { + return null; + } + + /** + * Get the spatial bounds of the file. + * @return the spatial bounds of the file. + */ + public getFileBounds(): Bounds { + return null; + } + + /** + * Get the attributes of the points. + * @return the attributes of the points. + */ + public getPointAttributes(): Array { + return null; + } + + /** + * Get the minimum value of an attribute. + * @param attribute the attribute. + * @return the minimum value (null if unknown). + */ + public getMinAttributeValue(attribute: PointAttribute): AttributeValue { + return null; + } + + /** + * Get the maximum value of an attribute. + * @param attribute the attribute. + * @return the maximum value (null if unknown). + */ + public getMaxAttributeValue(attribute: PointAttribute): AttributeValue { + return null; + } + + /** + * Get the number of levels. + * @return the number of levels. + */ + public getLevelCount(): int32 { + return 0; + } + + /** + * Get the number of points. + * @param level the index of the level. + * @return the number of points. + */ + public getLevelPointCount(level: int32): ALong { + return ALong.ZERO; + } + + /** + * Get the bounds of points. + * @param level the index of the level. + * @return the bounds of points. + */ + public getLevelPointBounds(level: int32): Bounds { + return null; + } + + /** + * Get the block grid. + * @param level the index of the level. + * @return the block grid (null if there is no spatial grid). + */ + public getLevelBlockGrid(level: int32): Grid { + return null; + } + + /** + * Get the tile grid. + * @param level the index of the level. + * @return the tile grid (null if there is no spatial grid). + */ + public getLevelTileGrid(level: int32): Grid { + return null; + } + + /** + * Peek at block indexes. + * @param level the index of the level. + * @return the block indexes (zero length if the level has not yet been accessed in case of lazy loading). + */ + public peekBlockIndexes(level: int32): Array { + return null; + } + + /** + * Read block indexes (with a 2-step file content fetching sequence). + * @param level the index of the level. + * @param fileContents the file contents. + * @return the tile indexes. + */ + public readBlockIndexes(level: int32, fileContents: ContentLoader): Array { + return null; + } + + /** + * Read tile indexes (with a 2-step file content fetching sequence). + * @param block the index of the block. + * @param fileContents the file contents. + * @return the tile indexes. + */ + public readTileIndexes(block: BlockIndex, fileContents: ContentLoader): Array { + return null; + } + + /** + * Read the points of a tile (with a 2-step file content fetching sequence). + * @param tileIndex the tile index. + * @param parameters the read parameters (contains the result read statistics). + * @param fileContents the file contents. + * @param processor the point processor. + */ + public readPoints(tileIndex: TileIndex, parameters: ReadRequest, fileContents: ContentLoader): AList { + return null; + } + + /** + * Read the points of a tile (with a 2-step file content fetching sequence). + * @param tileIndex the tile index. + * @param dataFormat the data format. + * @param accessTime the current access time. + * @param fileContents the file contents. + */ + public readPointData(tileIndex: TileIndex, dataFormat: int32, accessTime: float64, fileContents: ContentLoader): PointData { + return null; + } + + /** + * Clip the reader to a certain range of levels. + * @param levelOffset the index of the first level. + * @param levelCount the number of levels. + * @return the clipped pointcloud. + */ + public clipToLevelRange(levelOffset: int32, levelCount: int32): PointCloudReader { + return null; + } } diff --git a/core/orbitgt/src/pointcloud/model/PointData.ts b/core/orbitgt/src/pointcloud/model/PointData.ts index 9bd1eb68a100..3fa18c268698 100644 --- a/core/orbitgt/src/pointcloud/model/PointData.ts +++ b/core/orbitgt/src/pointcloud/model/PointData.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { Bounds } from "../../spatial/geom/Bounds"; import { TileIndex } from "./TileIndex"; @@ -23,16 +22,16 @@ import { TileIndex } from "./TileIndex"; */ /** @internal */ export class PointData { - // the index of the tile - public tileIndex: TileIndex; - // the spatial bounds of the tile - public bounds: Bounds; + // the index of the tile + public tileIndex: TileIndex; + // the spatial bounds of the tile + public bounds: Bounds; - /** - * Create new point data. - */ - public constructor(tileIndex: TileIndex, bounds: Bounds) { - this.tileIndex = tileIndex; - this.bounds = bounds; - } + /** + * Create new point data. + */ + public constructor(tileIndex: TileIndex, bounds: Bounds) { + this.tileIndex = tileIndex; + this.bounds = bounds; + } } diff --git a/core/orbitgt/src/pointcloud/model/PointDataRaw.ts b/core/orbitgt/src/pointcloud/model/PointDataRaw.ts index 0c13ffd163be..db1565905a94 100644 --- a/core/orbitgt/src/pointcloud/model/PointDataRaw.ts +++ b/core/orbitgt/src/pointcloud/model/PointDataRaw.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -26,69 +26,69 @@ import { TileIndex } from "./TileIndex"; */ /** @internal */ export class PointDataRaw extends PointData { - // the identifier of this data format - public static readonly TYPE: int32 = 1; + // the identifier of this data format + public static readonly TYPE: int32 = 1; - // the 16-bit XYZ geometries (length tileIndex.pointCount) - public points16: Uint16Buffer; - // the 8-bit XYZ geometries (length tileIndex.pointCount) - public points8: Uint8Buffer; - // the 24-bit BGR colors (length tileIndex.pointCount) - public colors: Uint8Buffer; + // the 16-bit XYZ geometries (length tileIndex.pointCount) + public points16: Uint16Buffer; + // the 8-bit XYZ geometries (length tileIndex.pointCount) + public points8: Uint8Buffer; + // the 24-bit BGR colors (length tileIndex.pointCount) + public colors: Uint8Buffer; - /** - * Create new point data. - */ - public constructor(tileIndex: TileIndex, bounds: Bounds, points16: Uint16Buffer, points8: Uint8Buffer, colors: Uint8Buffer) { - super(tileIndex, bounds); - this.bounds = bounds; - this.points16 = points16; - this.points8 = points8; - this.colors = colors; - } + /** + * Create new point data. + */ + public constructor(tileIndex: TileIndex, bounds: Bounds, points16: Uint16Buffer, points8: Uint8Buffer, colors: Uint8Buffer) { + super(tileIndex, bounds); + this.bounds = bounds; + this.points16 = points16; + this.points8 = points8; + this.colors = colors; + } - public getRawX(pointIndex: int32): int32 { - if (this.points16 == null) return this.points8.get(3 * pointIndex + 0); - return this.points16.get(3 * pointIndex + 0); - } + public getRawX(pointIndex: int32): int32 { + if (this.points16 == null) return this.points8.get(3 * pointIndex + 0); + return this.points16.get(3 * pointIndex + 0); + } - public getRawY(pointIndex: int32): int32 { - if (this.points16 == null) return this.points8.get(3 * pointIndex + 1); - return this.points16.get(3 * pointIndex + 1); - } + public getRawY(pointIndex: int32): int32 { + if (this.points16 == null) return this.points8.get(3 * pointIndex + 1); + return this.points16.get(3 * pointIndex + 1); + } - public getRawZ(pointIndex: int32): int32 { - if (this.points16 == null) return this.points8.get(3 * pointIndex + 2); - return this.points16.get(3 * pointIndex + 2); - } + public getRawZ(pointIndex: int32): int32 { + if (this.points16 == null) return this.points8.get(3 * pointIndex + 2); + return this.points16.get(3 * pointIndex + 2); + } - public getX(pointIndex: int32): float64 { - let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; - let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; - return this.bounds.min.x + ((this.getRawX(pointIndex) + bias) / range) * (this.bounds.max.x - this.bounds.min.x); - } + public getX(pointIndex: int32): float64 { + let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; + let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; + return this.bounds.min.x + ((this.getRawX(pointIndex) + bias) / range) * (this.bounds.max.x - this.bounds.min.x); + } - public getY(pointIndex: int32): float64 { - let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; - let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; - return this.bounds.min.y + ((this.getRawY(pointIndex) + bias) / range) * (this.bounds.max.y - this.bounds.min.y); - } + public getY(pointIndex: int32): float64 { + let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; + let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; + return this.bounds.min.y + ((this.getRawY(pointIndex) + bias) / range) * (this.bounds.max.y - this.bounds.min.y); + } - public getZ(pointIndex: int32): float64 { - let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; - let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; - return this.bounds.min.z + ((this.getRawZ(pointIndex) + bias) / range) * (this.bounds.max.z - this.bounds.min.z); - } + public getZ(pointIndex: int32): float64 { + let range: float64 = (this.points16 == null) ? 256.0 : 65536.0; + let bias: float64 = (this.points16 == null) ? 0.5 : 0.0; + return this.bounds.min.z + ((this.getRawZ(pointIndex) + bias) / range) * (this.bounds.max.z - this.bounds.min.z); + } - public getRed(pointIndex: int32): int32 { - return this.colors.get(3 * pointIndex + 2); - } + public getRed(pointIndex: int32): int32 { + return this.colors.get(3 * pointIndex + 2); + } - public getGreen(pointIndex: int32): int32 { - return this.colors.get(3 * pointIndex + 1); - } + public getGreen(pointIndex: int32): int32 { + return this.colors.get(3 * pointIndex + 1); + } - public getBlue(pointIndex: int32): int32 { - return this.colors.get(3 * pointIndex + 0); - } + public getBlue(pointIndex: int32): int32 { + return this.colors.get(3 * pointIndex + 0); + } } diff --git a/core/orbitgt/src/pointcloud/model/ReadRequest.ts b/core/orbitgt/src/pointcloud/model/ReadRequest.ts index 23e489b7babb..516c2c608a12 100644 --- a/core/orbitgt/src/pointcloud/model/ReadRequest.ts +++ b/core/orbitgt/src/pointcloud/model/ReadRequest.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -26,271 +26,271 @@ import { Strings } from "../../system/runtime/Strings"; */ /** @internal */ export class ReadRequest { - /** The request to only read the geometry */ - public static readonly READ_GEOMETRY: ReadRequest = ReadRequest.getGeometry(); - /** The request to only read the geometry and color */ - public static readonly READ_GEOMETRY_AND_COLOR: ReadRequest = ReadRequest.getGeometryAndColor(); - /** The request to read geometry and attributes */ - public static readonly READ_ALL: ReadRequest = ReadRequest.getGeometryAndAttributes(); - - /** Should the geometry be read? */ - private _readGeometryAttribute: boolean; - /** Should the color be read? */ - private _readColorAttribute: boolean; - /** Should the intensity be read? */ - private _readIntensityAttribute: boolean; - /** Should the weight be read? */ - private _readWeightAttribute: boolean; - /** Should thinning be used? */ - private _thinning: int32; - /** The list of extra attributes that should be read */ - private _extraAttributes: AList; - /** Should the deleted points be read as well? */ - private _readDeletedAttribute: boolean; - - /** An optional 2D area to filter */ - private _areaFilter: Bounds; - - /** The number read transactions */ - private _dataTransactions: int32; - /** The number of bytes read for this request */ - private _dataSize: ALong; - /** The number of nanoseconds spent reading data */ - private _dataReadTime: ALong; - - /** - * Create a new request to read all data (geometry and attributes) (except deleted points). - */ - public constructor() { - /* Read the geometry */ - this._readGeometryAttribute = true; - /* Read all standard attributes */ - this._readColorAttribute = true; - this._readIntensityAttribute = true; - this._readWeightAttribute = true; - this._thinning = 0; - /* Read all extra attributes */ - this._extraAttributes = new AList(); - this._extraAttributes.add("*"); - /* Default to not reading deleted points */ - this._readDeletedAttribute = false; - /* Clear */ - this._areaFilter = null; - this._dataTransactions = 0; - this._dataSize = ALong.ZERO; - this._dataReadTime = ALong.ZERO; - } - - /** - * Create a new request. - * @param readColor should the color be read? - * @param readIntensity should the intensity be read? - * @param readWeight should the weight be read? - * @param thinning should thinning be used? - */ - public static create(readColor: boolean, readIntensity: boolean, readWeight: boolean, thinning: int32): ReadRequest { - let request: ReadRequest = new ReadRequest(); - request._readColorAttribute = readColor; - request._readIntensityAttribute = readIntensity; - request._readWeightAttribute = readWeight; - request._thinning = thinning; - request._extraAttributes.clear(); - return request; - } - - /** - * Create the request to only read the geometry. - * @return the request. - */ - public static getGeometry(): ReadRequest { - return ReadRequest.create(false/*color*/, false/*intensity*/, false/*weight*/, 0/*thinning*/); - } - - /** - * Create the request to only read the geometry and colot. - * @return the request. - */ - public static getGeometryAndColor(): ReadRequest { - return ReadRequest.create(true/*color*/, false/*intensity*/, false/*weight*/, 0/*thinning*/); - } - - /** - * Create the request to read the full geometry and all attributes. - * @return the request. - */ - public static getGeometryAndAttributes(): ReadRequest { - return new ReadRequest(); - } - - /** - * Should the geometry be read? - * @return true if it should be read. - */ - public readGeometry(): boolean { - return this._readGeometryAttribute; - } - - /** - * Should the geometry be read? - * @param read true if it should be read. - */ - public setReadGeometry(read: boolean): void { - this._readGeometryAttribute = read; - } - - /** - * Should the color be read? - * @return true if it should be read. - */ - public readColor(): boolean { - return this._readColorAttribute; - } - - /** - * Should the intensity be read? - * @return true if it should be read. - */ - public readIntensity(): boolean { - return this._readIntensityAttribute; - } - - /** - * Should the weight be read? - * @return true if it should be read. - */ - public readWeight(): boolean { - return this._readWeightAttribute; - } - - /** - * Should thinning be used? - * @return the thinning factor. - */ - public getThinning(): int32 { - return this._thinning; - } - - /** - * Should the deleted points be read? - * @return true if they should be read. - */ - public readDeleted(): boolean { - return this._readDeletedAttribute; - } - - /** - * Should the deleted points be read? - * @param read true if they should be read. - */ - public setReadDeleted(read: boolean): void { - this._readDeletedAttribute = read; - } - - /** - * Should all extra attributes be read? - * @return true if all extra attribute should be read. - */ - public readAllExtraAttributes(): boolean { - if (this._extraAttributes.size() != 1) return false; - let extraAttribute: string = this._extraAttributes.get(0); - return Strings.equals(extraAttribute, "*"); - } - - /** - * Get the list of extra attributes to read. - * @return the list of extra attributes to read. - */ - public getExtraAttributes(): AList { - return this._extraAttributes; - } - - /** - * Set the list of extra attributes to read. - * @param list the list of extra attributes to read. - */ - public setExtraAttributes(list: AList): void { - this._extraAttributes = list; - } - - /** - * Add the name of an extra attribute to read. - * @param attributeName the name of the attribute to read. - * @return this request for convenient chaining. - */ - public addExtraAttribute(attributeName: string): ReadRequest { - this._extraAttributes.add(attributeName); - return this; - } - - /** - * Get the area filter. - * @return the area filter. - */ - public getAreaFilter(): Bounds { - return this._areaFilter; - } - - /** - * Set the area filter. - * @param filter the new area filter. - */ - public setAreaFilter(filter: Bounds): void { - this._areaFilter = filter; - } - - /** - * Add a number of bytes to the data size. - * @param size the number of bytes. - */ - public addDataSize(size: int32): void { - this._dataSize = this._dataSize.addInt(size); - this._dataTransactions++; - } - - /** - * Get the data size of the request. - * @return the number of bytes. - */ - public getDataSize(): ALong { - return this._dataSize; - } - - /** - * Clear the data size of the request. - */ - public clearDataSize(): void { - this._dataSize = ALong.ZERO; - this._dataTransactions = 0; - } - - /** - * Get the number of data transactions. - * @return the number of data transactions. - */ - public getDataTransactions(): int32 { - return this._dataTransactions; - } - - /** - * Add a number of nanoseconds to the data read time. - * @param time the number of nanoseconds. - */ - public addDataReadTime(time: ALong): void { - this._dataReadTime = this._dataReadTime.add(time); - } - - /** - * Get the data read time of the request. - * @return the number of nanoseconds. - */ - public getDataReadTime(): ALong { - return this._dataReadTime; - } - - /** - * Clear the data read time of the request. - */ - public clearDataReadTime(): void { - this._dataReadTime = ALong.ZERO; - } + /** The request to only read the geometry */ + public static readonly READ_GEOMETRY: ReadRequest = ReadRequest.getGeometry(); + /** The request to only read the geometry and color */ + public static readonly READ_GEOMETRY_AND_COLOR: ReadRequest = ReadRequest.getGeometryAndColor(); + /** The request to read geometry and attributes */ + public static readonly READ_ALL: ReadRequest = ReadRequest.getGeometryAndAttributes(); + + /** Should the geometry be read? */ + private _readGeometryAttribute: boolean; + /** Should the color be read? */ + private _readColorAttribute: boolean; + /** Should the intensity be read? */ + private _readIntensityAttribute: boolean; + /** Should the weight be read? */ + private _readWeightAttribute: boolean; + /** Should thinning be used? */ + private _thinning: int32; + /** The list of extra attributes that should be read */ + private _extraAttributes: AList; + /** Should the deleted points be read as well? */ + private _readDeletedAttribute: boolean; + + /** An optional 2D area to filter */ + private _areaFilter: Bounds; + + /** The number read transactions */ + private _dataTransactions: int32; + /** The number of bytes read for this request */ + private _dataSize: ALong; + /** The number of nanoseconds spent reading data */ + private _dataReadTime: ALong; + + /** + * Create a new request to read all data (geometry and attributes) (except deleted points). + */ + public constructor() { + /* Read the geometry */ + this._readGeometryAttribute = true; + /* Read all standard attributes */ + this._readColorAttribute = true; + this._readIntensityAttribute = true; + this._readWeightAttribute = true; + this._thinning = 0; + /* Read all extra attributes */ + this._extraAttributes = new AList(); + this._extraAttributes.add("*"); + /* Default to not reading deleted points */ + this._readDeletedAttribute = false; + /* Clear */ + this._areaFilter = null; + this._dataTransactions = 0; + this._dataSize = ALong.ZERO; + this._dataReadTime = ALong.ZERO; + } + + /** + * Create a new request. + * @param readColor should the color be read? + * @param readIntensity should the intensity be read? + * @param readWeight should the weight be read? + * @param thinning should thinning be used? + */ + public static create(readColor: boolean, readIntensity: boolean, readWeight: boolean, thinning: int32): ReadRequest { + let request: ReadRequest = new ReadRequest(); + request._readColorAttribute = readColor; + request._readIntensityAttribute = readIntensity; + request._readWeightAttribute = readWeight; + request._thinning = thinning; + request._extraAttributes.clear(); + return request; + } + + /** + * Create the request to only read the geometry. + * @return the request. + */ + public static getGeometry(): ReadRequest { + return ReadRequest.create(false, /*color*/ false, /*intensity*/ false, /*weight*/ 0 /*thinning*/); + } + + /** + * Create the request to only read the geometry and colot. + * @return the request. + */ + public static getGeometryAndColor(): ReadRequest { + return ReadRequest.create(true, /*color*/ false, /*intensity*/ false, /*weight*/ 0 /*thinning*/); + } + + /** + * Create the request to read the full geometry and all attributes. + * @return the request. + */ + public static getGeometryAndAttributes(): ReadRequest { + return new ReadRequest(); + } + + /** + * Should the geometry be read? + * @return true if it should be read. + */ + public readGeometry(): boolean { + return this._readGeometryAttribute; + } + + /** + * Should the geometry be read? + * @param read true if it should be read. + */ + public setReadGeometry(read: boolean): void { + this._readGeometryAttribute = read; + } + + /** + * Should the color be read? + * @return true if it should be read. + */ + public readColor(): boolean { + return this._readColorAttribute; + } + + /** + * Should the intensity be read? + * @return true if it should be read. + */ + public readIntensity(): boolean { + return this._readIntensityAttribute; + } + + /** + * Should the weight be read? + * @return true if it should be read. + */ + public readWeight(): boolean { + return this._readWeightAttribute; + } + + /** + * Should thinning be used? + * @return the thinning factor. + */ + public getThinning(): int32 { + return this._thinning; + } + + /** + * Should the deleted points be read? + * @return true if they should be read. + */ + public readDeleted(): boolean { + return this._readDeletedAttribute; + } + + /** + * Should the deleted points be read? + * @param read true if they should be read. + */ + public setReadDeleted(read: boolean): void { + this._readDeletedAttribute = read; + } + + /** + * Should all extra attributes be read? + * @return true if all extra attribute should be read. + */ + public readAllExtraAttributes(): boolean { + if (this._extraAttributes.size() != 1) return false; + let extraAttribute: string = this._extraAttributes.get(0); + return Strings.equals(extraAttribute, "*"); + } + + /** + * Get the list of extra attributes to read. + * @return the list of extra attributes to read. + */ + public getExtraAttributes(): AList { + return this._extraAttributes; + } + + /** + * Set the list of extra attributes to read. + * @param list the list of extra attributes to read. + */ + public setExtraAttributes(list: AList): void { + this._extraAttributes = list; + } + + /** + * Add the name of an extra attribute to read. + * @param attributeName the name of the attribute to read. + * @return this request for convenient chaining. + */ + public addExtraAttribute(attributeName: string): ReadRequest { + this._extraAttributes.add(attributeName); + return this; + } + + /** + * Get the area filter. + * @return the area filter. + */ + public getAreaFilter(): Bounds { + return this._areaFilter; + } + + /** + * Set the area filter. + * @param filter the new area filter. + */ + public setAreaFilter(filter: Bounds): void { + this._areaFilter = filter; + } + + /** + * Add a number of bytes to the data size. + * @param size the number of bytes. + */ + public addDataSize(size: int32): void { + this._dataSize = this._dataSize.addInt(size); + this._dataTransactions++; + } + + /** + * Get the data size of the request. + * @return the number of bytes. + */ + public getDataSize(): ALong { + return this._dataSize; + } + + /** + * Clear the data size of the request. + */ + public clearDataSize(): void { + this._dataSize = ALong.ZERO; + this._dataTransactions = 0; + } + + /** + * Get the number of data transactions. + * @return the number of data transactions. + */ + public getDataTransactions(): int32 { + return this._dataTransactions; + } + + /** + * Add a number of nanoseconds to the data read time. + * @param time the number of nanoseconds. + */ + public addDataReadTime(time: ALong): void { + this._dataReadTime = this._dataReadTime.add(time); + } + + /** + * Get the data read time of the request. + * @return the number of nanoseconds. + */ + public getDataReadTime(): ALong { + return this._dataReadTime; + } + + /** + * Clear the data read time of the request. + */ + public clearDataReadTime(): void { + this._dataReadTime = ALong.ZERO; + } } diff --git a/core/orbitgt/src/pointcloud/model/StandardAttributes.ts b/core/orbitgt/src/pointcloud/model/StandardAttributes.ts index 126f0a054e1b..b7e4b4589cea 100644 --- a/core/orbitgt/src/pointcloud/model/StandardAttributes.ts +++ b/core/orbitgt/src/pointcloud/model/StandardAttributes.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -25,32 +25,67 @@ import { PointAttribute } from "./PointAttribute"; */ /** @internal */ export class StandardAttributes { - /** The standard "color" attribute */ - public static readonly COLOR: PointAttribute = new PointAttribute("Color", "The RGB color", AttributeTypes.TYPE_COLOR, AttributeValue.createColor(0)); - /** The standard "intensity" attribute */ - public static readonly INTENSITY: PointAttribute = new PointAttribute("Intensity", "The reflection intensity", AttributeTypes.TYPE_INT2, AttributeValue.createInt2(0)); - /** The standard "gps-time" attribute */ - public static readonly GPS_TIME: PointAttribute = new PointAttribute("GPSTime", "The registration time of the point", AttributeTypes.TYPE_FLOAT8, AttributeValue.createFloat8(0.0)); - /** The standard "weight" attribute */ - public static readonly WEIGHT: PointAttribute = new PointAttribute("Weight", "The weight of a multi-resolution point", AttributeTypes.TYPE_INT4, AttributeValue.createInt4(0)); - /** The standard "clearance" attribute */ - public static readonly CLEARANCE: PointAttribute = new PointAttribute("Clearance", "The vertical clearance of a bridge or road", AttributeTypes.TYPE_FLOAT4, AttributeValue.createFloat4(0.0)); - /** The standard "rutting" attribute */ - public static readonly RUTTING: PointAttribute = new PointAttribute("Rutting", "The road deformation angle", AttributeTypes.TYPE_FLOAT4, AttributeValue.createFloat4(0.0)); // range 0..90 deg - /** The standard "color-by" attribute */ - public static readonly COLOR_BY: PointAttribute = new PointAttribute("ColorBy", "The attribute to modulate the point colors", AttributeTypes.TYPE_FLOAT4, AttributeValue.createFloat4(0.0)); + /** The standard "color" attribute */ + public static readonly COLOR: PointAttribute = new PointAttribute( + "Color", + "The RGB color", + AttributeTypes.TYPE_COLOR, + AttributeValue.createColor(0), + ); + /** The standard "intensity" attribute */ + public static readonly INTENSITY: PointAttribute = new PointAttribute( + "Intensity", + "The reflection intensity", + AttributeTypes.TYPE_INT2, + AttributeValue.createInt2(0), + ); + /** The standard "gps-time" attribute */ + public static readonly GPS_TIME: PointAttribute = new PointAttribute( + "GPSTime", + "The registration time of the point", + AttributeTypes.TYPE_FLOAT8, + AttributeValue.createFloat8(0.0), + ); + /** The standard "weight" attribute */ + public static readonly WEIGHT: PointAttribute = new PointAttribute( + "Weight", + "The weight of a multi-resolution point", + AttributeTypes.TYPE_INT4, + AttributeValue.createInt4(0), + ); + /** The standard "clearance" attribute */ + public static readonly CLEARANCE: PointAttribute = new PointAttribute( + "Clearance", + "The vertical clearance of a bridge or road", + AttributeTypes.TYPE_FLOAT4, + AttributeValue.createFloat4(0.0), + ); + /** The standard "rutting" attribute */ + public static readonly RUTTING: PointAttribute = new PointAttribute( + "Rutting", + "The road deformation angle", + AttributeTypes.TYPE_FLOAT4, + AttributeValue.createFloat4(0.0), + ); // range 0..90 deg + /** The standard "color-by" attribute */ + public static readonly COLOR_BY: PointAttribute = new PointAttribute( + "ColorBy", + "The attribute to modulate the point colors", + AttributeTypes.TYPE_FLOAT4, + AttributeValue.createFloat4(0.0), + ); - /** The default "gps-time" attribute value */ - public static readonly DEFAULT_GPS_TIME: AttributeValue = AttributeValue.createFloat8(0.0); + /** The default "gps-time" attribute value */ + public static readonly DEFAULT_GPS_TIME: AttributeValue = AttributeValue.createFloat8(0.0); - /** The "adjusted" gps time offset (The offset moves the time back to near zero to improve floating point resolution). + /** The "adjusted" gps time offset (The offset moves the time back to near zero to improve floating point resolution). See the "GPS Time Type" field in "LAS SPECIFICATION VERSION 1.3" */ - public static readonly GPS_TIME_OFFSET: float64 = 1.0e9; - /** The number of seconds in a week (7*24*3600) */ - public static readonly GPS_WEEK_SECONDS: float64 = 604800.0; + public static readonly GPS_TIME_OFFSET: float64 = 1.0e9; + /** The number of seconds in a week (7*24*3600) */ + public static readonly GPS_WEEK_SECONDS: float64 = 604800.0; - /** - * No instances. - */ - private constructor() { } + /** + * No instances. + */ + private constructor() {} } diff --git a/core/orbitgt/src/pointcloud/model/TileIndex.ts b/core/orbitgt/src/pointcloud/model/TileIndex.ts index d2ed217b904a..9f1207c9d0a9 100644 --- a/core/orbitgt/src/pointcloud/model/TileIndex.ts +++ b/core/orbitgt/src/pointcloud/model/TileIndex.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.model; +// package orbitgt.pointcloud.model; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ALong } from "../../system/runtime/ALong"; import { GridIndex } from "./GridIndex"; @@ -25,51 +24,51 @@ import { GridIndex } from "./GridIndex"; */ /** @internal */ export class TileIndex { - /** The level */ - public level: int32; - /** The unique key of the block */ - public key: string; - /** The index of the tile in the level */ - public index: int32; - /** The grid index */ - public gridIndex: GridIndex; - /** The index of the first point in the tile (derived) */ - public pointIndex: ALong; - /** The point count */ - public pointCount: int32; - /** The children */ - public children: Array; - /** The last access time */ - public accessTime: float64; + /** The level */ + public level: int32; + /** The unique key of the block */ + public key: string; + /** The index of the tile in the level */ + public index: int32; + /** The grid index */ + public gridIndex: GridIndex; + /** The index of the first point in the tile (derived) */ + public pointIndex: ALong; + /** The point count */ + public pointCount: int32; + /** The children */ + public children: Array; + /** The last access time */ + public accessTime: float64; - /** - * Create a new index. - */ - public constructor(level: int32, index: int32, gridIndex: GridIndex, pointIndex: ALong, pointCount: int32) { - this.level = level; - this.index = index; - this.gridIndex = gridIndex; - this.pointIndex = pointIndex; - this.pointCount = pointCount; - this.children = null; - this.accessTime = 0.0; - this.key = ("L" + this.level + ",T:" + this.index); - } + /** + * Create a new index. + */ + public constructor(level: int32, index: int32, gridIndex: GridIndex, pointIndex: ALong, pointCount: int32) { + this.level = level; + this.index = index; + this.gridIndex = gridIndex; + this.pointIndex = pointIndex; + this.pointCount = pointCount; + this.children = null; + this.accessTime = 0.0; + this.key = "L" + this.level + ",T:" + this.index; + } - /** - * Check if two indexes are the same. - * @param other another index. - * @return true if same. - */ - public same(other: TileIndex): boolean { - return (other.level == this.level) && (other.index == this.index); - } + /** + * Check if two indexes are the same. + * @param other another index. + * @return true if same. + */ + public same(other: TileIndex): boolean { + return (other.level == this.level) && (other.index == this.index); + } - /** - * Get the unique key of the tile in the pointcloud file. - * @return the unique key (combines level and grid index). - */ - public getKey(): string { - return "T" + this.level + "/" + this.gridIndex.x + "/" + this.gridIndex.y + "/" + this.gridIndex.z; - } + /** + * Get the unique key of the tile in the pointcloud file. + * @return the unique key (combines level and grid index). + */ + public getKey(): string { + return "T" + this.level + "/" + this.gridIndex.x + "/" + this.gridIndex.y + "/" + this.gridIndex.z; + } } diff --git a/core/orbitgt/src/pointcloud/render/AViewRequest.ts b/core/orbitgt/src/pointcloud/render/AViewRequest.ts index 813ef504d11e..e33f51542c86 100644 --- a/core/orbitgt/src/pointcloud/render/AViewRequest.ts +++ b/core/orbitgt/src/pointcloud/render/AViewRequest.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -25,30 +25,30 @@ import { Level } from "./Level"; */ /** @internal */ export abstract class AViewRequest { - /** - * Make a new request. - */ - public constructor() { - } + /** + * Make a new request. + */ + public constructor() { + } - /** - * Get the frame time. - * @return the frame time. - */ - public abstract getFrameTime(): float64; + /** + * Get the frame time. + * @return the frame time. + */ + public abstract getFrameTime(): float64; - /** - * Check if bounds are visible. - * @param bounds the bounds (in model space). - * @return true if visible. - */ - public abstract isVisibleBox(bounds: Bounds): boolean; + /** + * Check if bounds are visible. + * @param bounds the bounds (in model space). + * @return true if visible. + */ + public abstract isVisibleBox(bounds: Bounds): boolean; - /** - * Should a tile be split? - * @param level the level of the tile. - * @param tile the tile index. - * @return true if the tile should be split into its children. - */ - public abstract shouldSplit(level: Level, tile: TileIndex): boolean; + /** + * Should a tile be split? + * @param level the level of the tile. + * @param tile the tile index. + * @return true if the tile should be split into its children. + */ + public abstract shouldSplit(level: Level, tile: TileIndex): boolean; } diff --git a/core/orbitgt/src/pointcloud/render/Block.ts b/core/orbitgt/src/pointcloud/render/Block.ts index c3b42f655f49..f11fcb674a05 100644 --- a/core/orbitgt/src/pointcloud/render/Block.ts +++ b/core/orbitgt/src/pointcloud/render/Block.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -29,112 +29,112 @@ import { Level } from "./Level"; */ /** @internal */ export class Block { - /** The index of the block */ - private _index: BlockIndex; - /** The full list of tiles in the block (can be null if the tile-list has not been loaded) */ - private _tileList: Array; - /** The map of tiles in the block */ - private _tileMap: IntMap>>; + /** The index of the block */ + private _index: BlockIndex; + /** The full list of tiles in the block (can be null if the tile-list has not been loaded) */ + private _tileList: Array; + /** The map of tiles in the block */ + private _tileMap: IntMap>>; - /** - * Create a new block. - * @param index the index of the block. - */ - public constructor(index: BlockIndex) { - this._index = index; - this._tileList = null; - this._tileMap = null; - } + /** + * Create a new block. + * @param index the index of the block. + */ + public constructor(index: BlockIndex) { + this._index = index; + this._tileList = null; + this._tileMap = null; + } - /** - * Get the index of the block. - * @return the index of the block. - */ - public getBlockIndex(): BlockIndex { - return this._index; - } + /** + * Get the index of the block. + * @return the index of the block. + */ + public getBlockIndex(): BlockIndex { + return this._index; + } - /** - * Get the spatial bounds of the block. - * @param level the level to which the block belongs. - * @return the spatial bounds of the block. - */ - public getBlockBounds(level: Level): Bounds { - return level.getBlockGrid().getCellBounds(this._index.gridIndex); - } + /** + * Get the spatial bounds of the block. + * @param level the level to which the block belongs. + * @return the spatial bounds of the block. + */ + public getBlockBounds(level: Level): Bounds { + return level.getBlockGrid().getCellBounds(this._index.gridIndex); + } - /** - * Add a block to the list of blocks to load. - * @param blocksToLoad the list of blocks to load. - * @param block the block to add. - */ - private static addToLoadList(blocksToLoad: AList, block: BlockIndex): void { - for (let i: number = 0; i < blocksToLoad.size(); i++) if (blocksToLoad.get(i).same(block)) return; - blocksToLoad.add(block); - } + /** + * Add a block to the list of blocks to load. + * @param blocksToLoad the list of blocks to load. + * @param block the block to add. + */ + private static addToLoadList(blocksToLoad: AList, block: BlockIndex): void { + for (let i: number = 0; i < blocksToLoad.size(); i++) if (blocksToLoad.get(i).same(block)) return; + blocksToLoad.add(block); + } - /** - * Set the tiles in the block. - * @param tileList the list of tiles. - */ - public setTiles(tileList: Array): void { - /* Store the list */ - this._tileList = tileList; - /* Make the map */ - this._tileMap = new IntMap>>(); - for (let tile of this._tileList) { - let tileX: int32 = tile.gridIndex.x; - let yzMap: IntMap> = this._tileMap.get(tileX); - if (yzMap == null) { - yzMap = new IntMap>(); - this._tileMap.set(tileX, yzMap); - } - let tileY: int32 = tile.gridIndex.y; - let zMap: IntMap = yzMap.get(tileY); - if (zMap == null) { - zMap = new IntMap(); - yzMap.set(tileY, zMap); - } - let tileZ: int32 = tile.gridIndex.z; - zMap.set(tileZ, tile); - } - } + /** + * Set the tiles in the block. + * @param tileList the list of tiles. + */ + public setTiles(tileList: Array): void { + /* Store the list */ + this._tileList = tileList; + /* Make the map */ + this._tileMap = new IntMap>>(); + for (let tile of this._tileList) { + let tileX: int32 = tile.gridIndex.x; + let yzMap: IntMap> = this._tileMap.get(tileX); + if (yzMap == null) { + yzMap = new IntMap>(); + this._tileMap.set(tileX, yzMap); + } + let tileY: int32 = tile.gridIndex.y; + let zMap: IntMap = yzMap.get(tileY); + if (zMap == null) { + zMap = new IntMap(); + yzMap.set(tileY, zMap); + } + let tileZ: int32 = tile.gridIndex.z; + zMap.set(tileZ, tile); + } + } - /** - * Have the tiles been set? - * @return true if the tiles have been set. - */ - public hasTiles(): boolean { - return (this._tileList != null); - } + /** + * Have the tiles been set? + * @return true if the tiles have been set. + */ + public hasTiles(): boolean { + return (this._tileList != null); + } - /** - * List all tiles. - * @param blocksToLoad the list of blocks to load. - * @return all tiles (null if tiles are not loaded). - */ - public getTiles(blocksToLoad: AList): Array { - if (this._tileList == null) { - Block.addToLoadList(blocksToLoad, this._index); - return null; - } - return this._tileList; - } + /** + * List all tiles. + * @param blocksToLoad the list of blocks to load. + * @return all tiles (null if tiles are not loaded). + */ + public getTiles(blocksToLoad: AList): Array { + if (this._tileList == null) { + Block.addToLoadList(blocksToLoad, this._index); + return null; + } + return this._tileList; + } - /** - * Find a tile. - * @param tileGridIndex the grid index of the tile. - * @return the tile (null if not found). - */ - public findTile(tileGridIndex: GridIndex): TileIndex { - if (this._tileMap == null) return null; - let tileX: int32 = tileGridIndex.x; - let yzMap: IntMap> = this._tileMap.get(tileX); - if (yzMap == null) return null; - let tileY: int32 = tileGridIndex.y; - let zMap: IntMap = yzMap.get(tileY); - if (zMap == null) return null; - let tileZ: int32 = tileGridIndex.z; - return zMap.get(tileZ); - } + /** + * Find a tile. + * @param tileGridIndex the grid index of the tile. + * @return the tile (null if not found). + */ + public findTile(tileGridIndex: GridIndex): TileIndex { + if (this._tileMap == null) return null; + let tileX: int32 = tileGridIndex.x; + let yzMap: IntMap> = this._tileMap.get(tileX); + if (yzMap == null) return null; + let tileY: int32 = tileGridIndex.y; + let zMap: IntMap = yzMap.get(tileY); + if (zMap == null) return null; + let tileZ: int32 = tileGridIndex.z; + return zMap.get(tileZ); + } } diff --git a/core/orbitgt/src/pointcloud/render/DataManager.ts b/core/orbitgt/src/pointcloud/render/DataManager.ts index ac417cab7af1..ce0b1e4e75a8 100644 --- a/core/orbitgt/src/pointcloud/render/DataManager.ts +++ b/core/orbitgt/src/pointcloud/render/DataManager.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -39,352 +39,363 @@ import { ViewTree } from "./ViewTree"; */ /** @internal */ export class DataManager { - /** The name of this module */ - private static readonly MODULE: string = "DataManager"; + /** The name of this module */ + private static readonly MODULE: string = "DataManager"; - /** The maximum size of a single file-content request */ - private static readonly MAX_FILE_CONTENT_SIZE: int32 = 128 * 1024; - /** The expire time to unload unused point data (seconds) */ - private static readonly POINT_DATA_EXIRE_TIME: float64 = 5 * 60.0; + /** The maximum size of a single file-content request */ + private static readonly MAX_FILE_CONTENT_SIZE: int32 = 128 * 1024; + /** The expire time to unload unused point data (seconds) */ + private static readonly POINT_DATA_EXIRE_TIME: float64 = 5 * 60.0; - /** The reader of the pointcloud */ - private _pointCloudReader: PointCloudReader; - /*** The CRS of the pointcloud */ - private _pointCloudCRS: string; - /** The data format to read */ - private _dataFormat: int32; + /** The reader of the pointcloud */ + private _pointCloudReader: PointCloudReader; + /*** The CRS of the pointcloud */ + private _pointCloudCRS: string; + /** The data format to read */ + private _dataFormat: int32; - /** The spatial index */ - private _fileTileIndex: ViewTree; - /** The data pool */ - private _dataPool: StringMap; - /** The set of levels we requested (index) */ - private _levelsLoading: StringMap; - /** The set of levels we received (index) */ - private _levelsLoaded: StringMap; - /** The set of blocks we requested (key) */ - private _blocksLoading: StringMap; - /** The set of blocks we received (key) */ - private _blocksLoaded: StringMap; - /** The set of tiles we requested (key) */ - private _tilesLoading: StringMap; - /** The set of tiles we received (key) */ - private _tilesLoaded: StringMap; - /** Is new data being loaded? */ - private _loadingData: boolean; - /** The time when the data loading stopped */ - private _loadedDataTime: float64; - /** The total size of data that has been loaded */ - private _dataLoadSize: ALong; + /** The spatial index */ + private _fileTileIndex: ViewTree; + /** The data pool */ + private _dataPool: StringMap; + /** The set of levels we requested (index) */ + private _levelsLoading: StringMap; + /** The set of levels we received (index) */ + private _levelsLoaded: StringMap; + /** The set of blocks we requested (key) */ + private _blocksLoading: StringMap; + /** The set of blocks we received (key) */ + private _blocksLoaded: StringMap; + /** The set of tiles we requested (key) */ + private _tilesLoading: StringMap; + /** The set of tiles we received (key) */ + private _tilesLoaded: StringMap; + /** Is new data being loaded? */ + private _loadingData: boolean; + /** The time when the data loading stopped */ + private _loadedDataTime: float64; + /** The total size of data that has been loaded */ + private _dataLoadSize: ALong; - /** The last garbage collection time */ - private _lastGarbageCollectTime: float64; + /** The last garbage collection time */ + private _lastGarbageCollectTime: float64; - /** - * Create a new data model (to be shared between different views). - * @param pointCloudReader the reader of the pointcloud file. - * @param pointCloudCRS the CRS of the point cloud. - * @param dataFormat the requested data format to load point data (PointDataRaw.TYPE for example). - */ - public constructor(pointCloudReader: PointCloudReader, pointCloudCRS: string, dataFormat: int32) { - /* Store the parameters */ - this._pointCloudReader = pointCloudReader; - this._pointCloudCRS = pointCloudCRS; - this._dataFormat = dataFormat; - /* Initialize */ - if (this._pointCloudCRS == null) this._pointCloudCRS = this._pointCloudReader.getFileCRS(); - /* Clear */ - this._fileTileIndex = this.createSpatialIndex(); - this._dataPool = new StringMap(); - this._levelsLoading = new StringMap(); - this._levelsLoaded = new StringMap(); - this._blocksLoading = new StringMap(); - this._blocksLoaded = new StringMap(); - this._tilesLoading = new StringMap(); - this._tilesLoaded = new StringMap(); - this._loadingData = false; - this._loadedDataTime = 0.0; - this._dataLoadSize = ALong.ZERO; - this._lastGarbageCollectTime = 0.0; - /* Log */ - Message.print(DataManager.MODULE, "Pointcloud CRS is " + this._pointCloudCRS); - } + /** + * Create a new data model (to be shared between different views). + * @param pointCloudReader the reader of the pointcloud file. + * @param pointCloudCRS the CRS of the point cloud. + * @param dataFormat the requested data format to load point data (PointDataRaw.TYPE for example). + */ + public constructor(pointCloudReader: PointCloudReader, pointCloudCRS: string, dataFormat: int32) { + /* Store the parameters */ + this._pointCloudReader = pointCloudReader; + this._pointCloudCRS = pointCloudCRS; + this._dataFormat = dataFormat; + /* Initialize */ + if (this._pointCloudCRS == null) this._pointCloudCRS = this._pointCloudReader.getFileCRS(); + /* Clear */ + this._fileTileIndex = this.createSpatialIndex(); + this._dataPool = new StringMap(); + this._levelsLoading = new StringMap(); + this._levelsLoaded = new StringMap(); + this._blocksLoading = new StringMap(); + this._blocksLoaded = new StringMap(); + this._tilesLoading = new StringMap(); + this._tilesLoaded = new StringMap(); + this._loadingData = false; + this._loadedDataTime = 0.0; + this._dataLoadSize = ALong.ZERO; + this._lastGarbageCollectTime = 0.0; + /* Log */ + Message.print(DataManager.MODULE, "Pointcloud CRS is " + this._pointCloudCRS); + } - /** - * Close the data model. - */ - public close(): void { - if (this._pointCloudReader != null) { - this._pointCloudReader.close(); - this._pointCloudReader = null; - } - this._fileTileIndex = null; - this._dataPool.clear(); - this._levelsLoading.clear(); - this._levelsLoaded.clear(); - this._blocksLoading.clear(); - this._blocksLoaded.clear(); - this._tilesLoading.clear(); - this._tilesLoaded.clear(); - } + /** + * Close the data model. + */ + public close(): void { + if (this._pointCloudReader != null) { + this._pointCloudReader.close(); + this._pointCloudReader = null; + } + this._fileTileIndex = null; + this._dataPool.clear(); + this._levelsLoading.clear(); + this._levelsLoaded.clear(); + this._blocksLoading.clear(); + this._blocksLoaded.clear(); + this._tilesLoading.clear(); + this._tilesLoaded.clear(); + } - /** - * Create a spatial index of a pointcloud. - * @return the spatial index. - */ - private createSpatialIndex(): ViewTree { - /* Create the levels */ - Message.print(DataManager.MODULE, "Creating pointcloud spatial index"); - let levels: Array = new Array(this._pointCloudReader.getLevelCount()); - for (let i: number = 0; i < levels.length; i++) { - /* Get the grids */ - let blockGrid: Grid = this._pointCloudReader.getLevelBlockGrid(i); - let tileGrid: Grid = this._pointCloudReader.getLevelTileGrid(i); - /* Get the blocks */ - let blockIndexes: Array = this._pointCloudReader.peekBlockIndexes(i); - let blockList: Array = new Array(blockIndexes.length); - for (let j: number = 0; j < blockList.length; j++) blockList[j] = new Block(blockIndexes[j]); - /* Create the level */ - levels[i] = new Level(i, blockGrid, tileGrid, blockList); - Message.print(DataManager.MODULE, "Level " + i + " has " + blockList.length + " blocks"); - } - /* Get the data bounds */ - let dataBounds: Bounds = this._pointCloudReader.getFileBounds(); - Message.print(DataManager.MODULE, "The data bounds are " + dataBounds); - /* Return a new spatial index */ - return new ViewTree(this, levels, dataBounds); - } + /** + * Create a spatial index of a pointcloud. + * @return the spatial index. + */ + private createSpatialIndex(): ViewTree { + /* Create the levels */ + Message.print(DataManager.MODULE, "Creating pointcloud spatial index"); + let levels: Array = new Array(this._pointCloudReader.getLevelCount()); + for (let i: number = 0; i < levels.length; i++) { + /* Get the grids */ + let blockGrid: Grid = this._pointCloudReader.getLevelBlockGrid(i); + let tileGrid: Grid = this._pointCloudReader.getLevelTileGrid(i); + /* Get the blocks */ + let blockIndexes: Array = this._pointCloudReader.peekBlockIndexes(i); + let blockList: Array = new Array(blockIndexes.length); + for (let j: number = 0; j < blockList.length; j++) blockList[j] = new Block(blockIndexes[j]); + /* Create the level */ + levels[i] = new Level(i, blockGrid, tileGrid, blockList); + Message.print(DataManager.MODULE, "Level " + i + " has " + blockList.length + " blocks"); + } + /* Get the data bounds */ + let dataBounds: Bounds = this._pointCloudReader.getFileBounds(); + Message.print(DataManager.MODULE, "The data bounds are " + dataBounds); + /* Return a new spatial index */ + return new ViewTree(this, levels, dataBounds); + } - /** - * Get the pointcloud reader. - * @return the pointcloud reader. - */ - public getPointCloudReader(): PointCloudReader { - return this._pointCloudReader; - } + /** + * Get the pointcloud reader. + * @return the pointcloud reader. + */ + public getPointCloudReader(): PointCloudReader { + return this._pointCloudReader; + } - /** - * Get the pointcloud CRS. - * @return the pointcloud CRS. - */ - public getPointCloudCRS(): string { - return this._pointCloudCRS; - } + /** + * Get the pointcloud CRS. + * @return the pointcloud CRS. + */ + public getPointCloudCRS(): string { + return this._pointCloudCRS; + } - /** - * Get the bounds of the data. - * @return the bounds of the data. - */ - public getPointCloudBounds(): Bounds { - return this._pointCloudReader.getFileBounds(); - } + /** + * Get the bounds of the data. + * @return the bounds of the data. + */ + public getPointCloudBounds(): Bounds { + return this._pointCloudReader.getFileBounds(); + } - /** - * Get the spatial index. - * @return the spatial index. - */ - public getViewTree(): ViewTree { - return this._fileTileIndex; - } + /** + * Get the spatial index. + * @return the spatial index. + */ + public getViewTree(): ViewTree { + return this._fileTileIndex; + } - /** - * Check if a tile has been loaded to the data pool. - * @param tileIndex the index of the tile. - * @return the point data if loaded, null otherwise. - */ - public isTileLoaded(tileIndex: TileIndex): PointData { - return this._dataPool.get(tileIndex.key); - } + /** + * Check if a tile has been loaded to the data pool. + * @param tileIndex the index of the tile. + * @return the point data if loaded, null otherwise. + */ + public isTileLoaded(tileIndex: TileIndex): PointData { + return this._dataPool.get(tileIndex.key); + } - /** - * Is the model loading data? - * @return true when loading data. - */ - public isLoadingData(): boolean { - return this._loadingData; - } + /** + * Is the model loading data? + * @return true when loading data. + */ + public isLoadingData(): boolean { + return this._loadingData; + } - /** - * Get the size of the loaded data. - * @return the size of the loaded data. - */ - public getDataLoadSize(): ALong { - return this._dataLoadSize; - } + /** + * Get the size of the loaded data. + * @return the size of the loaded data. + */ + public getDataLoadSize(): ALong { + return this._dataLoadSize; + } - /** - * Filter the list of blocks and tiles that should be loaded. - * @param levelsToLoad the list of levels to load. - * @param blocksToLoad the list of blocks to load. - * @param tilesToLoad the list of tiles to load. - * @param levelList the filtered list of levels to load. - * @param blockList the filtered list of blocks to load. - * @param tileList the filtered list of tiles to load. - */ - public filterLoadList(levelsToLoad: AList, blocksToLoad: AList, tilesToLoad: AList, levelList: AList, blockList: AList, tileList: AList): void { - /* Filter the levels to load */ - for (let i: number = 0; i < levelsToLoad.size(); i++) { - /* Do not request the same level twice */ - let level: Level = levelsToLoad.get(i); - if (this._levelsLoading.contains(level.getKey())) continue; - if (this._levelsLoaded.contains(level.getKey())) continue; - /* Add the level */ - levelList.add(level); - } - levelsToLoad.clear(); - /* Filter the blocks to load */ - for (let i: number = 0; i < blocksToLoad.size(); i++) { - /* Do not request the same block twice */ - let blockIndex: BlockIndex = blocksToLoad.get(i); - if (this._blocksLoading.contains(blockIndex.key)) continue; - if (this._blocksLoaded.contains(blockIndex.key)) continue; - /* Add the block */ - blockList.add(blockIndex); - } - blocksToLoad.clear(); - /* Filter the tiles to load */ - for (let i: number = 0; i < tilesToLoad.size(); i++) { - /* Do not request the same tile twice */ - let tileIndex: TileIndex = tilesToLoad.get(i); - if (this._tilesLoading.contains(tileIndex.key)) continue; - if (this._tilesLoaded.contains(tileIndex.key)) continue; - /* Add the tile */ - tileList.add(tileIndex); - } - tilesToLoad.clear(); - } + /** + * Filter the list of blocks and tiles that should be loaded. + * @param levelsToLoad the list of levels to load. + * @param blocksToLoad the list of blocks to load. + * @param tilesToLoad the list of tiles to load. + * @param levelList the filtered list of levels to load. + * @param blockList the filtered list of blocks to load. + * @param tileList the filtered list of tiles to load. + */ + public filterLoadList( + levelsToLoad: AList, + blocksToLoad: AList, + tilesToLoad: AList, + levelList: AList, + blockList: AList, + tileList: AList, + ): void { + /* Filter the levels to load */ + for (let i: number = 0; i < levelsToLoad.size(); i++) { + /* Do not request the same level twice */ + let level: Level = levelsToLoad.get(i); + if (this._levelsLoading.contains(level.getKey())) continue; + if (this._levelsLoaded.contains(level.getKey())) continue; + /* Add the level */ + levelList.add(level); + } + levelsToLoad.clear(); + /* Filter the blocks to load */ + for (let i: number = 0; i < blocksToLoad.size(); i++) { + /* Do not request the same block twice */ + let blockIndex: BlockIndex = blocksToLoad.get(i); + if (this._blocksLoading.contains(blockIndex.key)) continue; + if (this._blocksLoaded.contains(blockIndex.key)) continue; + /* Add the block */ + blockList.add(blockIndex); + } + blocksToLoad.clear(); + /* Filter the tiles to load */ + for (let i: number = 0; i < tilesToLoad.size(); i++) { + /* Do not request the same tile twice */ + let tileIndex: TileIndex = tilesToLoad.get(i); + if (this._tilesLoading.contains(tileIndex.key)) continue; + if (this._tilesLoaded.contains(tileIndex.key)) continue; + /* Add the tile */ + tileList.add(tileIndex); + } + tilesToLoad.clear(); + } - /** - * Load blocks and tiles. - * @param layer the layer requesting the load. - * @param levelList the filtered list of levels to load. - * @param blockList the filtered list of blocks to load. - * @param tileList the filtered list of tiles to load. - * @return the data model. - */ - public async loadData(frameData: FrameData): Promise { - /* No data to load? */ - if (frameData.hasMissingData() == false) return frameData; - /* Do not make overlapping load requests */ - if (this._loadingData) return frameData; - this._loadingData = true; - /* Log */ - let levelList: AList = frameData.levelsToLoad; - let blockList: AList = frameData.blocksToLoad; - let tileList: AList = frameData.tilesToLoad; - // Message.print(MODULE,"Loading "+levelList.size()+" levels, "+blockList.size()+" blocks and "+tileList.size()+" tiles"); - // Message.print(MODULE,"Already loaded "+this._blocksLoaded.size()+" blocks"); - // Message.print(MODULE,"Already loading "+this._blocksLoading.size()+" blocks"); - // Message.print(MODULE,"Already loaded "+this._tilesLoaded.size()+" tiles"); - // Message.print(MODULE,"Already loading "+this._tilesLoading.size()+" tiles"); - /* Define the content we are going to need */ - let loadTime: float64 = ASystem.time(); - let fileContents: ContentLoader = new ContentLoader(this._pointCloudReader.getFileStorage(), this._pointCloudReader.getFileName()); - /* Prepare the loading of the levels */ - for (let i: number = 0; i < levelList.size(); i++) { - /* Prepare to load the block */ - let level: Level = levelList.get(i); - this._levelsLoading.set(level.getKey(), level); - this._pointCloudReader.readBlockIndexes(level.getIndex(), fileContents); - Message.print(DataManager.MODULE, "Loading level " + level.getIndex()); - } - /* Prepare the loading of the blocks */ - for (let i: number = 0; i < blockList.size(); i++) { - /* Prepare to load the block */ - let blockIndex: BlockIndex = blockList.get(i); - this._blocksLoading.set(blockIndex.key, blockIndex); - this._pointCloudReader.readTileIndexes(blockIndex, fileContents); - } - /* Prepare the loading of the tiles */ - let loadTileCount: int32 = 0; - for (let i: number = 0; i < tileList.size(); i++) { - /* Prepare to load the tile */ - let tileIndex: TileIndex = tileList.get(i); - this._tilesLoading.set(tileIndex.key, tileIndex); - this._pointCloudReader.readPointData(tileIndex, this._dataFormat, loadTime, fileContents); - loadTileCount++; - /* Do not load too many tiles at once */ - if (fileContents.getTotalRequestSize() > DataManager.MAX_FILE_CONTENT_SIZE) { - /* Stop loading tiles */ - Message.print(DataManager.MODULE, "Limited pointcloud content load request to " + fileContents.getTotalRequestSize() + " bytes"); - break; - } - } - /* Log */ - Message.print(DataManager.MODULE, "Loading of " + blockList.size() + " blocks, " + loadTileCount + "/" + tileList.size() + " tiles, " + fileContents.getTotalRequestSize() + " bytes"); - /* Load the data */ - this._dataLoadSize = this._dataLoadSize.addInt(fileContents.getTotalRequestSize()); - fileContents = await fileContents.load(); - //Message.print(MODULE,"Creating "+blockList.size()+" blocks and "+tileList.size()+" tiles"); - /* Load the levels */ - for (let i: number = 0; i < levelList.size(); i++) { - /* Load the block list */ - let level: Level = levelList.get(i); - this._levelsLoaded.set(level.getKey(), level); - this._levelsLoading.remove(level.getKey()); - let blockIndexes: Array = this._pointCloudReader.readBlockIndexes(level.getIndex(), fileContents); - /* Add the blocks */ - this._fileTileIndex.setLevelBlocks(level, blockIndexes); - } - /* Load the blocks */ - for (let i: number = 0; i < blockList.size(); i++) { - /* Load the block */ - let blockIndex: BlockIndex = blockList.get(i); - this._blocksLoaded.set(blockIndex.key, blockIndex); - this._blocksLoading.remove(blockIndex.key); - let tileIndexes: Array = this._pointCloudReader.readTileIndexes(blockIndex, fileContents); - /* Add the block */ - this._fileTileIndex.setBlockTiles(blockIndex, tileIndexes); - } - /* Load the tiles */ - let newTiles: AList = new AList(); - for (let i: number = 0; i < loadTileCount; i++) { - /* Get the next tile */ - let tileIndex: TileIndex = tileList.get(i); - newTiles.add(tileIndex); - /* Load the tile */ - this._tilesLoaded.set(tileIndex.key, tileIndex); - this._tilesLoading.remove(tileIndex.key); - let pointData: PointData = this._pointCloudReader.readPointData(tileIndex, this._dataFormat, loadTime, fileContents); - /* Add the tile */ - this._dataPool.set(tileIndex.key, pointData); - } - /* We stopped loading */ - this._loadingData = false; - this._loadedDataTime = ASystem.time(); - /* Log */ - Message.print(DataManager.MODULE, "Created " + blockList.size() + " blocks and " + loadTileCount + " tiles"); - /* Return the frame data */ - return frameData; - } + /** + * Load blocks and tiles. + * @param layer the layer requesting the load. + * @param levelList the filtered list of levels to load. + * @param blockList the filtered list of blocks to load. + * @param tileList the filtered list of tiles to load. + * @return the data model. + */ + public async loadData(frameData: FrameData): Promise { + /* No data to load? */ + if (frameData.hasMissingData() == false) return frameData; + /* Do not make overlapping load requests */ + if (this._loadingData) return frameData; + this._loadingData = true; + /* Log */ + let levelList: AList = frameData.levelsToLoad; + let blockList: AList = frameData.blocksToLoad; + let tileList: AList = frameData.tilesToLoad; + // Message.print(MODULE,"Loading "+levelList.size()+" levels, "+blockList.size()+" blocks and "+tileList.size()+" tiles"); + // Message.print(MODULE,"Already loaded "+this._blocksLoaded.size()+" blocks"); + // Message.print(MODULE,"Already loading "+this._blocksLoading.size()+" blocks"); + // Message.print(MODULE,"Already loaded "+this._tilesLoaded.size()+" tiles"); + // Message.print(MODULE,"Already loading "+this._tilesLoading.size()+" tiles"); + /* Define the content we are going to need */ + let loadTime: float64 = ASystem.time(); + let fileContents: ContentLoader = new ContentLoader(this._pointCloudReader.getFileStorage(), this._pointCloudReader.getFileName()); + /* Prepare the loading of the levels */ + for (let i: number = 0; i < levelList.size(); i++) { + /* Prepare to load the block */ + let level: Level = levelList.get(i); + this._levelsLoading.set(level.getKey(), level); + this._pointCloudReader.readBlockIndexes(level.getIndex(), fileContents); + Message.print(DataManager.MODULE, "Loading level " + level.getIndex()); + } + /* Prepare the loading of the blocks */ + for (let i: number = 0; i < blockList.size(); i++) { + /* Prepare to load the block */ + let blockIndex: BlockIndex = blockList.get(i); + this._blocksLoading.set(blockIndex.key, blockIndex); + this._pointCloudReader.readTileIndexes(blockIndex, fileContents); + } + /* Prepare the loading of the tiles */ + let loadTileCount: int32 = 0; + for (let i: number = 0; i < tileList.size(); i++) { + /* Prepare to load the tile */ + let tileIndex: TileIndex = tileList.get(i); + this._tilesLoading.set(tileIndex.key, tileIndex); + this._pointCloudReader.readPointData(tileIndex, this._dataFormat, loadTime, fileContents); + loadTileCount++; + /* Do not load too many tiles at once */ + if (fileContents.getTotalRequestSize() > DataManager.MAX_FILE_CONTENT_SIZE) { + /* Stop loading tiles */ + Message.print(DataManager.MODULE, "Limited pointcloud content load request to " + fileContents.getTotalRequestSize() + " bytes"); + break; + } + } + /* Log */ + Message.print( + DataManager.MODULE, + "Loading of " + blockList.size() + " blocks, " + loadTileCount + "/" + tileList.size() + " tiles, " + fileContents.getTotalRequestSize() + + " bytes", + ); + /* Load the data */ + this._dataLoadSize = this._dataLoadSize.addInt(fileContents.getTotalRequestSize()); + fileContents = await fileContents.load(); + // Message.print(MODULE,"Creating "+blockList.size()+" blocks and "+tileList.size()+" tiles"); + /* Load the levels */ + for (let i: number = 0; i < levelList.size(); i++) { + /* Load the block list */ + let level: Level = levelList.get(i); + this._levelsLoaded.set(level.getKey(), level); + this._levelsLoading.remove(level.getKey()); + let blockIndexes: Array = this._pointCloudReader.readBlockIndexes(level.getIndex(), fileContents); + /* Add the blocks */ + this._fileTileIndex.setLevelBlocks(level, blockIndexes); + } + /* Load the blocks */ + for (let i: number = 0; i < blockList.size(); i++) { + /* Load the block */ + let blockIndex: BlockIndex = blockList.get(i); + this._blocksLoaded.set(blockIndex.key, blockIndex); + this._blocksLoading.remove(blockIndex.key); + let tileIndexes: Array = this._pointCloudReader.readTileIndexes(blockIndex, fileContents); + /* Add the block */ + this._fileTileIndex.setBlockTiles(blockIndex, tileIndexes); + } + /* Load the tiles */ + let newTiles: AList = new AList(); + for (let i: number = 0; i < loadTileCount; i++) { + /* Get the next tile */ + let tileIndex: TileIndex = tileList.get(i); + newTiles.add(tileIndex); + /* Load the tile */ + this._tilesLoaded.set(tileIndex.key, tileIndex); + this._tilesLoading.remove(tileIndex.key); + let pointData: PointData = this._pointCloudReader.readPointData(tileIndex, this._dataFormat, loadTime, fileContents); + /* Add the tile */ + this._dataPool.set(tileIndex.key, pointData); + } + /* We stopped loading */ + this._loadingData = false; + this._loadedDataTime = ASystem.time(); + /* Log */ + Message.print(DataManager.MODULE, "Created " + blockList.size() + " blocks and " + loadTileCount + " tiles"); + /* Return the frame data */ + return frameData; + } - /** - * Do a garbage collect (this method can be called often, it throttles itself to once per minute). - * @param time the current time. - */ - public doGarbageCollect(time: float64): void { - /* First call? */ - if (this._lastGarbageCollectTime == 0.0) this._lastGarbageCollectTime = time; - /* Throttle to one per minute */ - if (time < this._lastGarbageCollectTime + 60.0) return; - this._lastGarbageCollectTime = time; - /* Define the expire time */ - let expireTime: float64 = (time - DataManager.POINT_DATA_EXIRE_TIME); - /* Check all loaded tiles */ - let dropCount: int32 = 0; - let dataKeys: AList = this._dataPool.keys(); - for (let i: number = 0; i < dataKeys.size(); i++) { - /* Get the next tile */ - let tileKey: string = dataKeys.get(i); - let pointData: PointData = this._dataPool.get(tileKey); - /* Expired? */ - if (pointData.tileIndex.accessTime < expireTime) { - this._dataPool.remove(tileKey); - this._tilesLoaded.remove(tileKey); - dropCount++; - } - } - /* Log? */ - if (dropCount > 0) Message.print(DataManager.MODULE, "Dropped the point data of " + dropCount + " tiles"); - } + /** + * Do a garbage collect (this method can be called often, it throttles itself to once per minute). + * @param time the current time. + */ + public doGarbageCollect(time: float64): void { + /* First call? */ + if (this._lastGarbageCollectTime == 0.0) this._lastGarbageCollectTime = time; + /* Throttle to one per minute */ + if (time < this._lastGarbageCollectTime + 60.0) return; + this._lastGarbageCollectTime = time; + /* Define the expire time */ + let expireTime: float64 = time - DataManager.POINT_DATA_EXIRE_TIME; + /* Check all loaded tiles */ + let dropCount: int32 = 0; + let dataKeys: AList = this._dataPool.keys(); + for (let i: number = 0; i < dataKeys.size(); i++) { + /* Get the next tile */ + let tileKey: string = dataKeys.get(i); + let pointData: PointData = this._dataPool.get(tileKey); + /* Expired? */ + if (pointData.tileIndex.accessTime < expireTime) { + this._dataPool.remove(tileKey); + this._tilesLoaded.remove(tileKey); + dropCount++; + } + } + /* Log? */ + if (dropCount > 0) Message.print(DataManager.MODULE, "Dropped the point data of " + dropCount + " tiles"); + } } diff --git a/core/orbitgt/src/pointcloud/render/FrameData.ts b/core/orbitgt/src/pointcloud/render/FrameData.ts index 50c640b31a76..63b4437a300f 100644 --- a/core/orbitgt/src/pointcloud/render/FrameData.ts +++ b/core/orbitgt/src/pointcloud/render/FrameData.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { AList } from "../../system/collection/AList"; import { BlockIndex } from "../model/BlockIndex"; import { PointData } from "../model/PointData"; @@ -26,32 +25,32 @@ import { Level } from "./Level"; */ /** @internal */ export class FrameData { - /** The list of tiles that have been loaded and need to be rendered */ - public tilesToRender: AList; - /** The levels of which the block indexes need to be loaded */ - public levelsToLoad: AList; - /** The blocks of which the tile indexes need to be loaded */ - public blocksToLoad: AList; - /** The tiles of which the points need to be loaded */ - public tilesToLoad: AList; + /** The list of tiles that have been loaded and need to be rendered */ + public tilesToRender: AList; + /** The levels of which the block indexes need to be loaded */ + public levelsToLoad: AList; + /** The blocks of which the tile indexes need to be loaded */ + public blocksToLoad: AList; + /** The tiles of which the points need to be loaded */ + public tilesToLoad: AList; - /** - * Create a new frame data holder. - */ - public constructor() { - this.tilesToRender = new AList(); - this.levelsToLoad = new AList(); - this.blocksToLoad = new AList(); - this.tilesToLoad = new AList(); - } + /** + * Create a new frame data holder. + */ + public constructor() { + this.tilesToRender = new AList(); + this.levelsToLoad = new AList(); + this.blocksToLoad = new AList(); + this.tilesToLoad = new AList(); + } - /** - * Is frame data missing? (so a data load is needed). - */ - public hasMissingData(): boolean { - if (this.levelsToLoad.size() > 0) return true; - if (this.blocksToLoad.size() > 0) return true; - if (this.tilesToLoad.size() > 0) return true; - return false; - } + /** + * Is frame data missing? (so a data load is needed). + */ + public hasMissingData(): boolean { + if (this.levelsToLoad.size() > 0) return true; + if (this.blocksToLoad.size() > 0) return true; + if (this.tilesToLoad.size() > 0) return true; + return false; + } } diff --git a/core/orbitgt/src/pointcloud/render/Level.ts b/core/orbitgt/src/pointcloud/render/Level.ts index 1bb2baaff48b..6c03bfc82f17 100644 --- a/core/orbitgt/src/pointcloud/render/Level.ts +++ b/core/orbitgt/src/pointcloud/render/Level.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -28,123 +28,123 @@ import { Block } from "./Block"; */ /** @internal */ export class Level { - /** The index of the level */ - private _index: int32; - /** The unique key of the level */ - private _key: string; - /** The grid of the blocks */ - private _blockGrid: Grid; - /** The grid of the tiles */ - private _tileGrid: Grid; - /** The list of blocks */ - private _blockList: Array; - /** The map of blocks */ - private _blockMap: StringMap; + /** The index of the level */ + private _index: int32; + /** The unique key of the level */ + private _key: string; + /** The grid of the blocks */ + private _blockGrid: Grid; + /** The grid of the tiles */ + private _tileGrid: Grid; + /** The list of blocks */ + private _blockList: Array; + /** The map of blocks */ + private _blockMap: StringMap; - /** - * Create a new level. - * @param index the index of the level. - * @param blockGrid the grid of the blocks. - * @param tileGrid the grid of the tiles. - * @param blockList the list of blocks. - */ - public constructor(index: int32, blockGrid: Grid, tileGrid: Grid, blockList: Array) { - /* Store the parameters */ - this._index = index; - this._key = ("L" + index); - this._blockGrid = blockGrid; - this._tileGrid = tileGrid; - this.setBlockList(blockList); - } + /** + * Create a new level. + * @param index the index of the level. + * @param blockGrid the grid of the blocks. + * @param tileGrid the grid of the tiles. + * @param blockList the list of blocks. + */ + public constructor(index: int32, blockGrid: Grid, tileGrid: Grid, blockList: Array) { + /* Store the parameters */ + this._index = index; + this._key = "L" + index; + this._blockGrid = blockGrid; + this._tileGrid = tileGrid; + this.setBlockList(blockList); + } - /** - * Set the block list. - * @param blockList the list of blocks. - */ - public setBlockList(blockList: Array): void { - this._blockList = blockList; - /* Map the blocks */ - this._blockMap = new StringMap(); - for (let block of this._blockList) this._blockMap.set(block.getBlockIndex().gridIndex.getKey(), block); - } + /** + * Set the block list. + * @param blockList the list of blocks. + */ + public setBlockList(blockList: Array): void { + this._blockList = blockList; + /* Map the blocks */ + this._blockMap = new StringMap(); + for (let block of this._blockList) this._blockMap.set(block.getBlockIndex().gridIndex.getKey(), block); + } - /** - * Get the index of the level. - * @return the index of the level. - */ - public getIndex(): int32 { - return this._index; - } + /** + * Get the index of the level. + * @return the index of the level. + */ + public getIndex(): int32 { + return this._index; + } - /** - * Get the unique key of the level. - * @return the unique key of the level. - */ - public getKey(): string { - return this._key; - } + /** + * Get the unique key of the level. + * @return the unique key of the level. + */ + public getKey(): string { + return this._key; + } - /** - * Get the block grid. - * @return the block grid. - */ - public getBlockGrid(): Grid { - return this._blockGrid; - } + /** + * Get the block grid. + * @return the block grid. + */ + public getBlockGrid(): Grid { + return this._blockGrid; + } - /** - * Get the tile grid. - * @return the tile grid. - */ - public getTileGrid(): Grid { - return this._tileGrid; - } + /** + * Get the tile grid. + * @return the tile grid. + */ + public getTileGrid(): Grid { + return this._tileGrid; + } - /** - * List all blocks. - * @return all blocks. - */ - public getBlocks(): Array { - return this._blockList; - } + /** + * List all blocks. + * @return all blocks. + */ + public getBlocks(): Array { + return this._blockList; + } - /** - * Get the number of blocks. - * @return the number of blocks. - */ - public getBlockCount(): int32 { - return this._blockList.length; - } + /** + * Get the number of blocks. + * @return the number of blocks. + */ + public getBlockCount(): int32 { + return this._blockList.length; + } - /** - * Find a block. - * @param blockIndex the index of the block to find. - * @return the block. - */ - public findBlock(blockIndex: BlockIndex): Block { - for (let block of this._blockList) if (block.getBlockIndex().same(blockIndex)) return block; - return null; - } + /** + * Find a block. + * @param blockIndex the index of the block to find. + * @return the block. + */ + public findBlock(blockIndex: BlockIndex): Block { + for (let block of this._blockList) if (block.getBlockIndex().same(blockIndex)) return block; + return null; + } - /** - * Find a block index. - * @param blockIndex the index of the block to find. - * @return the block (can be null). - */ - public findBlockGridIndex(blockIndex: GridIndex): Block { - return this._blockMap.get(blockIndex.getKey()); - } + /** + * Find a block index. + * @param blockIndex the index of the block to find. + * @return the block (can be null). + */ + public findBlockGridIndex(blockIndex: GridIndex): Block { + return this._blockMap.get(blockIndex.getKey()); + } - /** - * Find the block for a tile. - * @param tileGridIndex the grid index of the tile. - * @return the block (can be null). - */ - public findBlockForTile(tileGridIndex: GridIndex): Block { - /* Get the block index */ - let tileCenter: Coordinate = this._tileGrid.getCellCenter(tileGridIndex); - let blockGridIndex: GridIndex = this._blockGrid.getCellIndex(tileCenter); - /* Try to find the block */ - return this._blockMap.get(blockGridIndex.getKey()); - } + /** + * Find the block for a tile. + * @param tileGridIndex the grid index of the tile. + * @return the block (can be null). + */ + public findBlockForTile(tileGridIndex: GridIndex): Block { + /* Get the block index */ + let tileCenter: Coordinate = this._tileGrid.getCellCenter(tileGridIndex); + let blockGridIndex: GridIndex = this._blockGrid.getCellIndex(tileCenter); + /* Try to find the block */ + return this._blockMap.get(blockGridIndex.getKey()); + } } diff --git a/core/orbitgt/src/pointcloud/render/TileLoadSorter.ts b/core/orbitgt/src/pointcloud/render/TileLoadSorter.ts index 3c85255f8c21..4b9127058d4b 100644 --- a/core/orbitgt/src/pointcloud/render/TileLoadSorter.ts +++ b/core/orbitgt/src/pointcloud/render/TileLoadSorter.ts @@ -9,7 +9,7 @@ // NOTE: this class has been translated from Java. // Do not modify this file, changes will be overwritten. -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -34,8 +34,7 @@ export interface IProjectToViewForSort { * * @internal */ -export class TileLoadSorter implements iComparator -{ +export class TileLoadSorter implements iComparator { /** @ignore */ public static readonly _CLASSNAME_: string = "orbitgt.pointcloud.render.TileLoadSorter"; // the full name of the original java class // the interface implementation markers: @@ -99,7 +98,7 @@ export class TileLoadSorter implements iComparator let tileCenter: Coordinate = this.getTilePosition(tile, 0, 0, 0); if (tileCenter == null) return 0.0; /* Get the angle from the camera boresight (screen center) (the smaller the better) (radians) */ - let angleFromScreenCenter: float64 = Coordinate.getAngleRad(tileCenter, new Coordinate(0.0, 0.0, 1.0)/*forward*/); + let angleFromScreenCenter: float64 = Coordinate.getAngleRad(tileCenter, new Coordinate(0.0, 0.0, 1.0) /*forward*/); /* Get the radius of the tile in the view (camera) space */ let tileRadius: float64 = this.getTileRadius(tile, tileCenter); /* Get the angular extent of the tile (the bigger the better) (radians) */ @@ -112,10 +111,10 @@ export class TileLoadSorter implements iComparator // Comparator interface method public compare(tile1: TileIndex, tile2: TileIndex): int32 { /* Load higher level tiles first (added on 21/03/2017 by LER) */ - let dLevel: int32 = (tile1.level - tile2.level); + let dLevel: int32 = tile1.level - tile2.level; if (dLevel != 0) return (-dLevel); /* Compare the scores inside the level */ - let d: float64 = (this.getScore(tile1) - this.getScore(tile2)); // new scoring method on 02/02/2017 by LER + let d: float64 = this.getScore(tile1) - this.getScore(tile2); // new scoring method on 02/02/2017 by LER return (d > 0.0) ? 1 : (d < 0.0) ? -1 : 0; } } diff --git a/core/orbitgt/src/pointcloud/render/ViewTree.ts b/core/orbitgt/src/pointcloud/render/ViewTree.ts index ec8374634039..20a7f0462010 100644 --- a/core/orbitgt/src/pointcloud/render/ViewTree.ts +++ b/core/orbitgt/src/pointcloud/render/ViewTree.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.pointcloud.render; +// package orbitgt.pointcloud.render; type int8 = number; type int16 = number; @@ -33,331 +33,365 @@ import { Level } from "./Level"; */ /** @internal */ export class ViewTree { - /** The name of this module */ - private static readonly MODULE: string = "ViewTree"; + /** The name of this module */ + private static readonly MODULE: string = "ViewTree"; - /** Debug mode? */ - private static readonly DEBUG: boolean = false; + /** Debug mode? */ + private static readonly DEBUG: boolean = false; - /** The data manager */ - private _dataManager: DataManager; - /** The levels */ - private _levels: Array; - /** The data bounds */ - private _dataBounds: Bounds; - /** The root blocks */ - private _rootBlocks: AList; + /** The data manager */ + private _dataManager: DataManager; + /** The levels */ + private _levels: Array; + /** The data bounds */ + private _dataBounds: Bounds; + /** The root blocks */ + private _rootBlocks: AList; - /** - * Create a new tree. - * @param levels the levels. - * @param dataBounds the data bounds. - */ - public constructor(dataManager: DataManager, levels: Array, dataBounds: Bounds) { - /* Store the parameters */ - this._dataManager = dataManager; - this._levels = levels; - this._dataBounds = dataBounds; - /* Find the root blocks */ - this._rootBlocks = this.findRootBlocks(); - } + /** + * Create a new tree. + * @param levels the levels. + * @param dataBounds the data bounds. + */ + public constructor(dataManager: DataManager, levels: Array, dataBounds: Bounds) { + /* Store the parameters */ + this._dataManager = dataManager; + this._levels = levels; + this._dataBounds = dataBounds; + /* Find the root blocks */ + this._rootBlocks = this.findRootBlocks(); + } - /** - * Find all root blocks (dropping of single-point tiles during pyramid creation can lead to missing branches). - * @return all root blocks. - */ - private findRootBlocks(): AList { - /* Check some levels below the top */ - let startLevel: int32 = (this._levels.length - 6); - if (startLevel < 0) startLevel = 0; - Message.print(ViewTree.MODULE, "Finding root blocks starting at level index " + startLevel + " of " + this._levels.length); - /* Check the levels */ - let rootBlocks: AList = new AList(); - let nextLevelIndex: GridIndex = new GridIndex(0, 0, 0); - for (let i: number = startLevel; i < this._levels.length - 1; i++) { - /* Check all blocks in the level */ - let level: Level = this._levels[i]; - for (let block of level.getBlocks()) { - /* Non-top level? */ - let isRoot: boolean = true; - if (i < this._levels.length - 2) { - /* Do we have a parent block in the next level? */ - block.getBlockIndex().gridIndex.getNextLevelIndex(nextLevelIndex); - isRoot = (this._levels[i + 1].findBlockGridIndex(nextLevelIndex) == null); - if (isRoot) Message.print(ViewTree.MODULE, "Block L" + i + " " + block.getBlockIndex().gridIndex + " is non-top root"); - } - /* Add to the list? */ - if (isRoot) rootBlocks.add(block); - } - } - /* Return the roots */ - Message.print(ViewTree.MODULE, "Found " + rootBlocks.size() + " root blocks"); - return rootBlocks; - } + /** + * Find all root blocks (dropping of single-point tiles during pyramid creation can lead to missing branches). + * @return all root blocks. + */ + private findRootBlocks(): AList { + /* Check some levels below the top */ + let startLevel: int32 = this._levels.length - 6; + if (startLevel < 0) startLevel = 0; + Message.print(ViewTree.MODULE, "Finding root blocks starting at level index " + startLevel + " of " + this._levels.length); + /* Check the levels */ + let rootBlocks: AList = new AList(); + let nextLevelIndex: GridIndex = new GridIndex(0, 0, 0); + for (let i: number = startLevel; i < this._levels.length - 1; i++) { + /* Check all blocks in the level */ + let level: Level = this._levels[i]; + for (let block of level.getBlocks()) { + /* Non-top level? */ + let isRoot: boolean = true; + if (i < this._levels.length - 2) { + /* Do we have a parent block in the next level? */ + block.getBlockIndex().gridIndex.getNextLevelIndex(nextLevelIndex); + isRoot = this._levels[i + 1].findBlockGridIndex(nextLevelIndex) == null; + if (isRoot) Message.print(ViewTree.MODULE, "Block L" + i + " " + block.getBlockIndex().gridIndex + " is non-top root"); + } + /* Add to the list? */ + if (isRoot) rootBlocks.add(block); + } + } + /* Return the roots */ + Message.print(ViewTree.MODULE, "Found " + rootBlocks.size() + " root blocks"); + return rootBlocks; + } - /** - * Get the number of levels. - * @return the number of levels. - */ - public getLevelCount(): int32 { - return this._levels.length; - } + /** + * Get the number of levels. + * @return the number of levels. + */ + public getLevelCount(): int32 { + return this._levels.length; + } - /** - * Get a level. - * @param index the index of the level. - * @return the level. - */ - public getLevel(index: int32): Level { - return this._levels[index]; - } + /** + * Get a level. + * @param index the index of the level. + * @return the level. + */ + public getLevel(index: int32): Level { + return this._levels[index]; + } - /** - * Get the data bounds. - * @return the data bounds. - */ - public getDataBounds(): Bounds { - return this._dataBounds; - } + /** + * Get the data bounds. + * @return the data bounds. + */ + public getDataBounds(): Bounds { + return this._dataBounds; + } - /** - * Set the blocks for a level (after a data load operation). - * @param level the level. - * @param blockIndexes the indexes of the blocks in the level. - */ - public setLevelBlocks(level: Level, blockIndexes: Array): void { - if (blockIndexes == null) return; - let blockList: Array = new Array(blockIndexes.length); - for (let i: number = 0; i < blockIndexes.length; i++) blockList[i] = new Block(blockIndexes[i]); - level.setBlockList(blockList); - Message.print(ViewTree.MODULE, "Loaded " + blockIndexes.length + " blocks for level " + level.getIndex()); - } + /** + * Set the blocks for a level (after a data load operation). + * @param level the level. + * @param blockIndexes the indexes of the blocks in the level. + */ + public setLevelBlocks(level: Level, blockIndexes: Array): void { + if (blockIndexes == null) return; + let blockList: Array = new Array(blockIndexes.length); + for (let i: number = 0; i < blockIndexes.length; i++) blockList[i] = new Block(blockIndexes[i]); + level.setBlockList(blockList); + Message.print(ViewTree.MODULE, "Loaded " + blockIndexes.length + " blocks for level " + level.getIndex()); + } - /** - * Set the tiles for a block (after a data load operation). - * @param blockIndex the index of the block. - * @param tileIndexes the indexes of the tiles in the block. - */ - public setBlockTiles(blockIndex: BlockIndex, tileIndexes: Array): void { - let level: Level = this._levels[blockIndex.level]; - let block: Block = level.findBlock(blockIndex); - block.setTiles(tileIndexes); - } + /** + * Set the tiles for a block (after a data load operation). + * @param blockIndex the index of the block. + * @param tileIndexes the indexes of the tiles in the block. + */ + public setBlockTiles(blockIndex: BlockIndex, tileIndexes: Array): void { + let level: Level = this._levels[blockIndex.level]; + let block: Block = level.findBlock(blockIndex); + block.setTiles(tileIndexes); + } - /** - * Split a tile into lower-level tiles. - * @param level the level of the tile to split. - * @param tile the tile to split. - * @param childLevel the lower level of the tile. - * @param children the list of children to split into. - * @param levelsToLoad the list of levels to load. - * @param blocksToLoad the list of blocks to load. - * @return true if the list of children is complete. - */ - private splitTile(level: Level, tile: TileIndex, childLevel: Level, children: AList, levelsToLoad: AList, blocksToLoad: AList): boolean { - /* Clear the result */ - children.clear(); - /* Already calculated? */ - let childList: Array = tile.children; - if (childList != null) { - /* Return */ - for (let child of childList) children.add(child); - return true; - } - /* Assume we have a complete list of children */ - let complete: boolean = true; - /* Unloaded level? */ - if (childLevel.getBlockCount() == 0) { - /* No need to continue, we need the level block list */ - if (levelsToLoad.contains(childLevel) == false) levelsToLoad.add(childLevel); - return false; - } - /* Check the 8 possible child tiles */ - let index: GridIndex = tile.gridIndex; - let childIndex: GridIndex = new GridIndex(0, 0, 0); - for (let z: number = 0; z < 2; z++) for (let y: number = 0; y < 2; y++) for (let x: number = 0; x < 2; x++) { - /* Get the index of the child */ - childIndex.x = (2 * index.x + x); - childIndex.y = (2 * index.y + y); - childIndex.z = (2 * index.z + z); - /* Find the block */ - let block: Block = childLevel.findBlockForTile(childIndex); - if (block == null) { - /* This should not happen */ - Message.printWarning(ViewTree.MODULE, "Unable to find tile block " + childIndex + " in child level " + childLevel.getIndex() + " (" + childLevel.getBlockCount() + " blocks)"); - complete = false; - continue; - } - /* No tile info in the block? */ - if (block.hasTiles() == false) { - /* Load the block data */ - if (blocksToLoad.contains(block.getBlockIndex()) == false) blocksToLoad.add(block.getBlockIndex()); - complete = false; - } - else { - /* Find the child */ - let child: TileIndex = block.findTile(childIndex); - if (child != null) children.add(child); - } - } - /* Store the result if complete */ - if (complete) { - /* Store */ - let tileChildren: Array = new Array(children.size()); - for (let i: number = 0; i < tileChildren.length; i++) tileChildren[i] = children.get(i); - tile.children = tileChildren; - } - /* Do we have all children? */ - return complete; - } + /** + * Split a tile into lower-level tiles. + * @param level the level of the tile to split. + * @param tile the tile to split. + * @param childLevel the lower level of the tile. + * @param children the list of children to split into. + * @param levelsToLoad the list of levels to load. + * @param blocksToLoad the list of blocks to load. + * @return true if the list of children is complete. + */ + private splitTile( + level: Level, + tile: TileIndex, + childLevel: Level, + children: AList, + levelsToLoad: AList, + blocksToLoad: AList, + ): boolean { + /* Clear the result */ + children.clear(); + /* Already calculated? */ + let childList: Array = tile.children; + if (childList != null) { + /* Return */ + for (let child of childList) children.add(child); + return true; + } + /* Assume we have a complete list of children */ + let complete: boolean = true; + /* Unloaded level? */ + if (childLevel.getBlockCount() == 0) { + /* No need to continue, we need the level block list */ + if (levelsToLoad.contains(childLevel) == false) levelsToLoad.add(childLevel); + return false; + } + /* Check the 8 possible child tiles */ + let index: GridIndex = tile.gridIndex; + let childIndex: GridIndex = new GridIndex(0, 0, 0); + for (let z: number = 0; z < 2; z++) + for (let y: number = 0; y < 2; y++) + for (let x: number = 0; x < 2; x++) { + /* Get the index of the child */ + childIndex.x = 2 * index.x + x; + childIndex.y = 2 * index.y + y; + childIndex.z = 2 * index.z + z; + /* Find the block */ + let block: Block = childLevel.findBlockForTile(childIndex); + if (block == null) { + /* This should not happen */ + Message.printWarning( + ViewTree.MODULE, + "Unable to find tile block " + childIndex + " in child level " + childLevel.getIndex() + " (" + childLevel.getBlockCount() + " blocks)", + ); + complete = false; + continue; + } + /* No tile info in the block? */ + if (block.hasTiles() == false) { + /* Load the block data */ + if (blocksToLoad.contains(block.getBlockIndex()) == false) blocksToLoad.add(block.getBlockIndex()); + complete = false; + } + else { + /* Find the child */ + let child: TileIndex = block.findTile(childIndex); + if (child != null) children.add(child); + } + } + /* Store the result if complete */ + if (complete) { + /* Store */ + let tileChildren: Array = new Array(children.size()); + for (let i: number = 0; i < tileChildren.length; i++) tileChildren[i] = children.get(i); + tile.children = tileChildren; + } + /* Do we have all children? */ + return complete; + } - /** - * Is all tile data available for rendering? - * @param viewRequest the view request. - * @param tiles a list of tiles to check. - * @param missingTiles the list of tiles whose data is missing. - */ - private checkDataAvailable(viewRequest: AViewRequest, tiles: AList, missingTiles: AList): void { - /* Check all tiles */ - missingTiles.clear(); - for (let i: number = 0; i < tiles.size(); i++) { - /* Get the next tile */ - let tile: TileIndex = tiles.get(i); - /* Not available? */ - if (this._dataManager.isTileLoaded(tile) == null) { - /* Request to load the block */ - missingTiles.add(tile); - } - else { - /* Touch the block */ - tile.accessTime = viewRequest.getFrameTime(); - } - } - } + /** + * Is all tile data available for rendering? + * @param viewRequest the view request. + * @param tiles a list of tiles to check. + * @param missingTiles the list of tiles whose data is missing. + */ + private checkDataAvailable(viewRequest: AViewRequest, tiles: AList, missingTiles: AList): void { + /* Check all tiles */ + missingTiles.clear(); + for (let i: number = 0; i < tiles.size(); i++) { + /* Get the next tile */ + let tile: TileIndex = tiles.get(i); + /* Not available? */ + if (this._dataManager.isTileLoaded(tile) == null) { + /* Request to load the block */ + missingTiles.add(tile); + } + else { + /* Touch the block */ + tile.accessTime = viewRequest.getFrameTime(); + } + } + } - /** - * Is all tile data available for rendering? - * @param viewRequest the view request. - * @param tiles a list of tiles to check. - * @return true if the tile data is available. - */ - private isDataAvailable(viewRequest: AViewRequest, tiles: Array): boolean { - /* Check all tiles */ - for (let i: number = 0; i < tiles.length; i++) { - /* Get the next tile */ - let tile: TileIndex = tiles[i]; - /* Not available? */ - if (this._dataManager.isTileLoaded(tile) == null) return false; - } - /* Available */ - return true; - } + /** + * Is all tile data available for rendering? + * @param viewRequest the view request. + * @param tiles a list of tiles to check. + * @return true if the tile data is available. + */ + private isDataAvailable(viewRequest: AViewRequest, tiles: Array): boolean { + /* Check all tiles */ + for (let i: number = 0; i < tiles.length; i++) { + /* Get the next tile */ + let tile: TileIndex = tiles[i]; + /* Not available? */ + if (this._dataManager.isTileLoaded(tile) == null) return false; + } + /* Available */ + return true; + } - /** - * Add visible tiles to the view. - * @param viewRequest the view request. - * @param level the level of the tiles. - * @param tiles the tiles to check. - * @param visibleTiles the list of visible tiles to add to. - */ - private addTilesToView(viewRequest: AViewRequest, level: Level, tiles: Array, levelsToLoad: AList, blocksToLoad: AList, tilesToLoad: AList, tilesToRender: AList): void { - /* No tiles? */ - if (tiles == null) return; - /* Make the lists */ - let childTiles: AList = new AList(); - let missingChildTiles: AList = new AList(); - /* Check all tiles */ - for (let i: number = 0; i < tiles.length; i++) { - /* Get the next tile */ - let tile: TileIndex = tiles[i]; - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Checking tile L" + tile.level + " (" + tile.gridIndex.x + "," + tile.gridIndex.y + "," + tile.gridIndex.z + ")"); - /* Visible? */ - let tileBounds: Bounds = level.getTileGrid().getCellBounds(tile.gridIndex).getIntersection(this._dataBounds); - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "> level " + tile.level); - if (viewRequest.isVisibleBox(tileBounds)) { - /* Has the tile been loaded? */ - let tileData: PointData = this._dataManager.isTileLoaded(tile); - let tileAvailable: boolean = (tileData != null); - tile.accessTime = viewRequest.getFrameTime(); - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > available? " + tileAvailable); - /* We load all intermediate tiles to avoid holes in the coverage */ - if (tileAvailable == false) tilesToLoad.add(tile); - /* Split the tile? */ - let shouldSplit: boolean = (level.getIndex() > 0) && viewRequest.shouldSplit(level, tile); - if (shouldSplit) { - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible, but needs splitting"); - /* Find the children at the lower level */ - let childLevel: Level = this._levels[level.getIndex() - 1]; - let completeChildList: boolean = this.splitTile(level, tile, childLevel, childTiles, levelsToLoad, blocksToLoad); - if (completeChildList == false) { - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > loading child indexes"); - /* Display the tile while we wait for the block-tiles to load */ - if (tileAvailable) tilesToRender.add(tileData); - } - else { - /* Are all children available with their data? */ - this.checkDataAvailable(viewRequest, childTiles, missingChildTiles); - if (missingChildTiles.size() == 0) { - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > rendering children"); - /* Add the children */ - let childTiles2: Array = new Array(childTiles.size()); - for (let j: number = 0; j < childTiles2.length; j++) childTiles2[j] = childTiles.get(j); - this.addTilesToView(viewRequest, childLevel, childTiles2, levelsToLoad, blocksToLoad, tilesToLoad, tilesToRender); - } - else { - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > loading children"); - /* Request for the missing children to be loaded */ - for (let j: number = 0; j < missingChildTiles.size(); j++) tilesToLoad.add(missingChildTiles.get(j)); - /* Display the tile while we wait for the child tiles to load */ - if (tileAvailable) tilesToRender.add(tileData); - } - } - } - else { - /* Display the tile */ - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible"); - if (tileAvailable) tilesToRender.add(tileData); - } - } - else { - /* Log */ - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > not visible"); - } - } - } + /** + * Add visible tiles to the view. + * @param viewRequest the view request. + * @param level the level of the tiles. + * @param tiles the tiles to check. + * @param visibleTiles the list of visible tiles to add to. + */ + private addTilesToView( + viewRequest: AViewRequest, + level: Level, + tiles: Array, + levelsToLoad: AList, + blocksToLoad: AList, + tilesToLoad: AList, + tilesToRender: AList, + ): void { + /* No tiles? */ + if (tiles == null) return; + /* Make the lists */ + let childTiles: AList = new AList(); + let missingChildTiles: AList = new AList(); + /* Check all tiles */ + for (let i: number = 0; i < tiles.length; i++) { + /* Get the next tile */ + let tile: TileIndex = tiles[i]; + if (ViewTree.DEBUG) + Message.print( + ViewTree.MODULE, + "Checking tile L" + tile.level + " (" + tile.gridIndex.x + "," + tile.gridIndex.y + "," + tile.gridIndex.z + ")", + ); + /* Visible? */ + let tileBounds: Bounds = level.getTileGrid().getCellBounds(tile.gridIndex).getIntersection(this._dataBounds); + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "> level " + tile.level); + if (viewRequest.isVisibleBox(tileBounds)) { + /* Has the tile been loaded? */ + let tileData: PointData = this._dataManager.isTileLoaded(tile); + let tileAvailable: boolean = tileData != null; + tile.accessTime = viewRequest.getFrameTime(); + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > available? " + tileAvailable); + /* We load all intermediate tiles to avoid holes in the coverage */ + if (tileAvailable == false) tilesToLoad.add(tile); + /* Split the tile? */ + let shouldSplit: boolean = (level.getIndex() > 0) && viewRequest.shouldSplit(level, tile); + if (shouldSplit) { + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible, but needs splitting"); + /* Find the children at the lower level */ + let childLevel: Level = this._levels[level.getIndex() - 1]; + let completeChildList: boolean = this.splitTile(level, tile, childLevel, childTiles, levelsToLoad, blocksToLoad); + if (completeChildList == false) { + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > loading child indexes"); + /* Display the tile while we wait for the block-tiles to load */ + if (tileAvailable) tilesToRender.add(tileData); + } + else { + /* Are all children available with their data? */ + this.checkDataAvailable(viewRequest, childTiles, missingChildTiles); + if (missingChildTiles.size() == 0) { + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > rendering children"); + /* Add the children */ + let childTiles2: Array = new Array(childTiles.size()); + for (let j: number = 0; j < childTiles2.length; j++) childTiles2[j] = childTiles.get(j); + this.addTilesToView(viewRequest, childLevel, childTiles2, levelsToLoad, blocksToLoad, tilesToLoad, tilesToRender); + } + else { + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > loading children"); + /* Request for the missing children to be loaded */ + for (let j: number = 0; j < missingChildTiles.size(); j++) tilesToLoad.add(missingChildTiles.get(j)); + /* Display the tile while we wait for the child tiles to load */ + if (tileAvailable) tilesToRender.add(tileData); + } + } + } + else { + /* Display the tile */ + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible"); + if (tileAvailable) tilesToRender.add(tileData); + } + } + else { + /* Log */ + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > not visible"); + } + } + } - /** - * Find tile indexes for a 3D view. - * @param viewRequest the request parameters. - * @param visibleTiles the list of visible tiles to add to. - * @param availableTiles the set of available tiles. - * @param visibleAvailableTiles the list if visible and available tiles to add to. - */ - public renderView3D(viewRequest: AViewRequest, levelsToLoad: AList, blocksToLoad: AList, tilesToLoad: AList, tilesToRender: AList): void { - /* Log? */ - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Finding pointcloud tiles to render"); - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > dataBounds: " + this._dataBounds); - //if (DEBUG) Message.print(MODULE," > view: "+viewRequest.getViewProjection()); - //if (DEBUG) Message.print(MODULE," > distance: "+viewRequest.getDistanceRange()); - //if (DEBUG) Message.print(MODULE," > model-transform: "+viewRequest.getModelTransform()); - /* Check all blocks */ - tilesToRender.clear(); - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Checking " + this._rootBlocks.size() + " root blocks"); - for (let i: number = 0; i < this._rootBlocks.size(); i++) // start from the root tiles - { - /* Visible? */ - let block: Block = this._rootBlocks.get(i); - let blockIndex: BlockIndex = block.getBlockIndex(); - let level: Level = this._levels[blockIndex.level]; - /* Visible? */ - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Checking top-level block L" + blockIndex.level + " (" + blockIndex.gridIndex.x + "," + blockIndex.gridIndex.y + "," + blockIndex.gridIndex.z + ")"); - let blockBounds: Bounds = block.getBlockBounds(level).getIntersection(this._dataBounds); - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > blockBounds: " + blockBounds); - if (viewRequest.isVisibleBox(blockBounds)) { - /* Add the tiles */ - if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible"); - this.addTilesToView(viewRequest, level, block.getTiles(blocksToLoad), levelsToLoad, blocksToLoad, tilesToLoad, tilesToRender); - } - } - } + /** + * Find tile indexes for a 3D view. + * @param viewRequest the request parameters. + * @param visibleTiles the list of visible tiles to add to. + * @param availableTiles the set of available tiles. + * @param visibleAvailableTiles the list if visible and available tiles to add to. + */ + public renderView3D( + viewRequest: AViewRequest, + levelsToLoad: AList, + blocksToLoad: AList, + tilesToLoad: AList, + tilesToRender: AList, + ): void { + /* Log? */ + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Finding pointcloud tiles to render"); + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > dataBounds: " + this._dataBounds); + // if (DEBUG) Message.print(MODULE," > view: "+viewRequest.getViewProjection()); + // if (DEBUG) Message.print(MODULE," > distance: "+viewRequest.getDistanceRange()); + // if (DEBUG) Message.print(MODULE," > model-transform: "+viewRequest.getModelTransform()); + /* Check all blocks */ + tilesToRender.clear(); + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, "Checking " + this._rootBlocks.size() + " root blocks"); + for (let i: number = 0; i < this._rootBlocks.size(); i++) { // start from the root tiles + /* Visible? */ + let block: Block = this._rootBlocks.get(i); + let blockIndex: BlockIndex = block.getBlockIndex(); + let level: Level = this._levels[blockIndex.level]; + /* Visible? */ + if (ViewTree.DEBUG) + Message.print( + ViewTree.MODULE, + "Checking top-level block L" + blockIndex.level + " (" + blockIndex.gridIndex.x + "," + blockIndex.gridIndex.y + "," + + blockIndex.gridIndex.z + ")", + ); + let blockBounds: Bounds = block.getBlockBounds(level).getIntersection(this._dataBounds); + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > blockBounds: " + blockBounds); + if (viewRequest.isVisibleBox(blockBounds)) { + /* Add the tiles */ + if (ViewTree.DEBUG) Message.print(ViewTree.MODULE, " > visible"); + this.addTilesToView(viewRequest, level, block.getTiles(blocksToLoad), levelsToLoad, blocksToLoad, tilesToLoad, tilesToRender); + } + } + } } diff --git a/core/orbitgt/src/spatial/crs/CRSEngine.ts b/core/orbitgt/src/spatial/crs/CRSEngine.ts index 860a30e2a540..ef45a40bc85e 100644 --- a/core/orbitgt/src/spatial/crs/CRSEngine.ts +++ b/core/orbitgt/src/spatial/crs/CRSEngine.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.crs; +// package orbitgt.spatial.crs; type int8 = number; type int16 = number; @@ -22,84 +22,84 @@ import { Coordinate } from "../geom/Coordinate"; */ /** @internal */ export class CRSEngine { - /** - * Create a new engine. - */ - public constructor() { - } + /** + * Create a new engine. + */ + public constructor() { + } - /** - * Prepare a CRS for making transforms in a certain area. - * @param crs the CRS to prepare. - * @param area the area to prepare for (can be invalid to prepare only for the crs). - */ - public async prepareForArea(crs: string, area: Bounds): Promise { - // subclasses should override this method if they need to download some part of a grid correction file, or the CRS declaration - return area; - } + /** + * Prepare a CRS for making transforms in a certain area. + * @param crs the CRS to prepare. + * @param area the area to prepare for (can be invalid to prepare only for the crs). + */ + public async prepareForArea(crs: string, area: Bounds): Promise { + // subclasses should override this method if they need to download some part of a grid correction file, or the CRS declaration + return area; + } - /** - * Transform a coordinate from one CRS to another. - * @param point the point coordinate. - * @param sourceCRS the source CRS. - * @param targetCRS the target CRS. - * @return the transformed coordinate. - */ - public transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { - // subclasses should override this method - return point; - } + /** + * Transform a coordinate from one CRS to another. + * @param point the point coordinate. + * @param sourceCRS the source CRS. + * @param targetCRS the target CRS. + * @return the transformed coordinate. + */ + public transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { + // subclasses should override this method + return point; + } - /** - * Check if a CRS is geocentric. - * @param crs the CRS to check. - * @return true if geocentric. - */ - public isGeocentricCRS(crs: string): boolean { - // subclasses should override this method - return false; - } + /** + * Check if a CRS is geocentric. + * @param crs the CRS to check. + * @return true if geocentric. + */ + public isGeocentricCRS(crs: string): boolean { + // subclasses should override this method + return false; + } - /** - * Check if a CRS is geographic. - * @param crs the CRS to check. - * @return true if geocentric. - */ - public isGeographicCRS(crs: string): boolean { - // subclasses should override this method - return false; - } + /** + * Check if a CRS is geographic. + * @param crs the CRS to check. + * @return true if geocentric. + */ + public isGeographicCRS(crs: string): boolean { + // subclasses should override this method + return false; + } - /** - * Check if a CRS is projected. - * @param crs the CRS to check. - * @return true if geocentric. - */ - public isProjectedCRS(crs: string): boolean { - // subclasses should override this method - return false; - } + /** + * Check if a CRS is projected. + * @param crs the CRS to check. + * @return true if geocentric. + */ + public isProjectedCRS(crs: string): boolean { + // subclasses should override this method + return false; + } - /** - * Transform spatial bounds from one CRS to another. - * @param point the point coordinate. - * @param sourceCRS the source CRS. - * @param targetCRS the target CRS. - * @return the transformed bounds. - */ - public transformBounds(bounds: Bounds, sourceCRS: string, targetCRS: string): Bounds { - // no real need to override this method in subclasses - /* Create new bounds */ - let targetBounds: Bounds = new Bounds(); - if (bounds.isValid()) { - /* Transform all 8 corners */ - let corner: Coordinate = Coordinate.create(); - for (let i: number = 0; i < 8; i++) { - bounds.getCorner(i, corner); - targetBounds.add(this.transformPoint(corner, sourceCRS, targetCRS)); - } - } - /* Return the target bounds */ - return targetBounds; + /** + * Transform spatial bounds from one CRS to another. + * @param point the point coordinate. + * @param sourceCRS the source CRS. + * @param targetCRS the target CRS. + * @return the transformed bounds. + */ + public transformBounds(bounds: Bounds, sourceCRS: string, targetCRS: string): Bounds { + // no real need to override this method in subclasses + /* Create new bounds */ + let targetBounds: Bounds = new Bounds(); + if (bounds.isValid()) { + /* Transform all 8 corners */ + let corner: Coordinate = Coordinate.create(); + for (let i: number = 0; i < 8; i++) { + bounds.getCorner(i, corner); + targetBounds.add(this.transformPoint(corner, sourceCRS, targetCRS)); + } } + /* Return the target bounds */ + return targetBounds; + } } diff --git a/core/orbitgt/src/spatial/crs/CRSManager.ts b/core/orbitgt/src/spatial/crs/CRSManager.ts index 2705922ab971..1506ec66f87b 100644 --- a/core/orbitgt/src/spatial/crs/CRSManager.ts +++ b/core/orbitgt/src/spatial/crs/CRSManager.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.crs; +// package orbitgt.spatial.crs; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { Strings } from "../../system/runtime/Strings"; import { Bounds } from "../geom/Bounds"; import { Coordinate } from "../geom/Coordinate"; @@ -26,89 +25,89 @@ import { CRSEngine } from "./CRSEngine"; */ /** @internal */ export class CRSManager { - /** The main instance of the CRS engine. This needs to be set by the application on startup. */ - public static ENGINE: CRSEngine = null; + /** The main instance of the CRS engine. This needs to be set by the application on startup. */ + public static ENGINE: CRSEngine = null; - /** - * Allow no instances, all methods are static. - */ - private constructor() { - } + /** + * Allow no instances, all methods are static. + */ + private constructor() { + } - /** - * Prepare a CRS for making transforms in a certain area. - * @param crs the CRS to prepare. - * @param area the area to prepare for (can be invalid to prepare only for the crs). - */ - public static async prepareForArea(crs: string, area: Bounds): Promise { - if (CRSManager.ENGINE == null) return area; - return CRSManager.ENGINE.prepareForArea(crs, area); - } + /** + * Prepare a CRS for making transforms in a certain area. + * @param crs the CRS to prepare. + * @param area the area to prepare for (can be invalid to prepare only for the crs). + */ + public static async prepareForArea(crs: string, area: Bounds): Promise { + if (CRSManager.ENGINE == null) return area; + return CRSManager.ENGINE.prepareForArea(crs, area); + } - /** - * Transform a coordinate from one CRS to another. - * @param point the point coordinate. - * @param sourceCRS the source CRS. - * @param targetCRS the target CRS. - * @return the transformed coordinate. - */ - public static transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { - if (CRSManager.ENGINE == null) return point; - return CRSManager.ENGINE.transformPoint(point, sourceCRS, targetCRS); - } + /** + * Transform a coordinate from one CRS to another. + * @param point the point coordinate. + * @param sourceCRS the source CRS. + * @param targetCRS the target CRS. + * @return the transformed coordinate. + */ + public static transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { + if (CRSManager.ENGINE == null) return point; + return CRSManager.ENGINE.transformPoint(point, sourceCRS, targetCRS); + } - /** - * Transform spatial bounds from one CRS to another. - * @param point the point coordinate. - * @param sourceCRS the source CRS. - * @param targetCRS the target CRS. - * @return the transformed bounds. - */ - public static transformBounds(bounds: Bounds, sourceCRS: string, targetCRS: string): Bounds { - if (CRSManager.ENGINE == null) return bounds; - return CRSManager.ENGINE.transformBounds(bounds, sourceCRS, targetCRS); - } + /** + * Transform spatial bounds from one CRS to another. + * @param point the point coordinate. + * @param sourceCRS the source CRS. + * @param targetCRS the target CRS. + * @return the transformed bounds. + */ + public static transformBounds(bounds: Bounds, sourceCRS: string, targetCRS: string): Bounds { + if (CRSManager.ENGINE == null) return bounds; + return CRSManager.ENGINE.transformBounds(bounds, sourceCRS, targetCRS); + } - /** - * Create an approximate 3D transformation from a source to a target CRS. - * @param sourceCRS the source CRS. - * @param sourcePoint the origin point in the source CRS. - * @param targetCRS the target CRS. - * @return the transform. - */ - public static createTransform(sourceCRS: string, sourcePoint: Coordinate, targetCRS: string): Transform { - /* Check */ - let transform: Transform = new Transform(); - if (CRSManager.ENGINE == null) return transform; - if (sourceCRS == null) return transform; - if (targetCRS == null) return transform; - if (sourcePoint == null) return transform; - /* Same? */ - if (Strings.equals(targetCRS, sourceCRS)) return transform; - /* Transform X and Y at 100 meter distance (assume Z is metric) */ - let sizeXY: float64 = 100.0; - if (CRSManager.ENGINE.isGeographicCRS(sourceCRS)) sizeXY = (sizeXY / 40000000.0 * 360.0); - let sizeZ: float64 = 100.0; - /* Create the frame */ - let p0: Coordinate = sourcePoint.copy(); - let pX: Coordinate = p0.copy(); - pX.add0(new Coordinate(sizeXY, 0.0, 0.0)); - let pY: Coordinate = p0.copy(); - pY.add0(new Coordinate(0.0, sizeXY, 0.0)); - let pZ: Coordinate = p0.copy(); - pZ.add0(new Coordinate(0.0, 0.0, sizeZ)); - /* Transform the frame */ - p0 = CRSManager.ENGINE.transformPoint(p0, sourceCRS, targetCRS); - pX = CRSManager.ENGINE.transformPoint(pX, sourceCRS, targetCRS); - pY = CRSManager.ENGINE.transformPoint(pY, sourceCRS, targetCRS); - pZ = CRSManager.ENGINE.transformPoint(pZ, sourceCRS, targetCRS); - /* Get the columns */ - let colX: Coordinate = pX.subtract(p0).scale(1.0 / sizeXY); - let colY: Coordinate = pY.subtract(p0).scale(1.0 / sizeXY); - let colZ: Coordinate = pZ.subtract(p0).scale(1.0 / sizeZ); - /* Create the transform */ - transform = Transform.createWithColumns(colX, colY, colZ, p0); - transform.translate(-sourcePoint.getX(), -sourcePoint.getY(), -sourcePoint.getZ()); - return transform; - } + /** + * Create an approximate 3D transformation from a source to a target CRS. + * @param sourceCRS the source CRS. + * @param sourcePoint the origin point in the source CRS. + * @param targetCRS the target CRS. + * @return the transform. + */ + public static createTransform(sourceCRS: string, sourcePoint: Coordinate, targetCRS: string): Transform { + /* Check */ + let transform: Transform = new Transform(); + if (CRSManager.ENGINE == null) return transform; + if (sourceCRS == null) return transform; + if (targetCRS == null) return transform; + if (sourcePoint == null) return transform; + /* Same? */ + if (Strings.equals(targetCRS, sourceCRS)) return transform; + /* Transform X and Y at 100 meter distance (assume Z is metric) */ + let sizeXY: float64 = 100.0; + if (CRSManager.ENGINE.isGeographicCRS(sourceCRS)) sizeXY = sizeXY / 40000000.0 * 360.0; + let sizeZ: float64 = 100.0; + /* Create the frame */ + let p0: Coordinate = sourcePoint.copy(); + let pX: Coordinate = p0.copy(); + pX.add0(new Coordinate(sizeXY, 0.0, 0.0)); + let pY: Coordinate = p0.copy(); + pY.add0(new Coordinate(0.0, sizeXY, 0.0)); + let pZ: Coordinate = p0.copy(); + pZ.add0(new Coordinate(0.0, 0.0, sizeZ)); + /* Transform the frame */ + p0 = CRSManager.ENGINE.transformPoint(p0, sourceCRS, targetCRS); + pX = CRSManager.ENGINE.transformPoint(pX, sourceCRS, targetCRS); + pY = CRSManager.ENGINE.transformPoint(pY, sourceCRS, targetCRS); + pZ = CRSManager.ENGINE.transformPoint(pZ, sourceCRS, targetCRS); + /* Get the columns */ + let colX: Coordinate = pX.subtract(p0).scale(1.0 / sizeXY); + let colY: Coordinate = pY.subtract(p0).scale(1.0 / sizeXY); + let colZ: Coordinate = pZ.subtract(p0).scale(1.0 / sizeZ); + /* Create the transform */ + transform = Transform.createWithColumns(colX, colY, colZ, p0); + transform.translate(-sourcePoint.getX(), -sourcePoint.getY(), -sourcePoint.getZ()); + return transform; + } } diff --git a/core/orbitgt/src/spatial/ecrs/Axis.ts b/core/orbitgt/src/spatial/ecrs/Axis.ts index 4f78d5595d2d..4f0b5b647231 100644 --- a/core/orbitgt/src/spatial/ecrs/Axis.ts +++ b/core/orbitgt/src/spatial/ecrs/Axis.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -28,91 +28,92 @@ type float64 = number; */ /** @internal */ export class Axis { - /** The code */ - private _code: int32; - /** The axis name */ - private _axisName: string; - /** The axis orientation */ - private _axisOrientation: string; - /** The abbreviation */ - private _abbreviation: string; - /** The unit-of-measurement code */ - private _unitCode: int32; - /** The axis order */ - private _order: int32; + /** The code */ + private _code: int32; + /** The axis name */ + private _axisName: string; + /** The axis orientation */ + private _axisOrientation: string; + /** The abbreviation */ + private _abbreviation: string; + /** The unit-of-measurement code */ + private _unitCode: int32; + /** The axis order */ + private _order: int32; - /** - * Create a new axis. - * @param code the code. - * @param axisName the name of the axis. - * @param axisOrientation the orientation of the axis. - * @param abbreviation the abbreviation. - * @param unitCode the unit-of-measurement code. - * @param order the axis order. - */ - public constructor(code: int32, axisName: string, axisOrientation: string, abbreviation: string, unitCode: int32, order: int32) { - /* Store parameters */ - this._code = code; - this._axisName = axisName; - this._axisOrientation = axisOrientation; - this._abbreviation = abbreviation; - this._unitCode = unitCode; - this._order = order; - } + /** + * Create a new axis. + * @param code the code. + * @param axisName the name of the axis. + * @param axisOrientation the orientation of the axis. + * @param abbreviation the abbreviation. + * @param unitCode the unit-of-measurement code. + * @param order the axis order. + */ + public constructor(code: int32, axisName: string, axisOrientation: string, abbreviation: string, unitCode: int32, order: int32) { + /* Store parameters */ + this._code = code; + this._axisName = axisName; + this._axisOrientation = axisOrientation; + this._abbreviation = abbreviation; + this._unitCode = unitCode; + this._order = order; + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the axis name. - * @return the axis name. - */ - public getAxisName(): string { - return this._axisName; - } + /** + * Get the axis name. + * @return the axis name. + */ + public getAxisName(): string { + return this._axisName; + } - /** - * Get the axis orientation. - * @return the axis orientation. - */ - public getAxisOrientation(): string { - return this._axisOrientation; - } + /** + * Get the axis orientation. + * @return the axis orientation. + */ + public getAxisOrientation(): string { + return this._axisOrientation; + } - /** - * Get the abbreviation. - * @return the abbreviation. - */ - public getAbbreviation(): string { - return this._abbreviation; - } + /** + * Get the abbreviation. + * @return the abbreviation. + */ + public getAbbreviation(): string { + return this._abbreviation; + } - /** - * Get the unit-of-measurement code. - * @return the unit-of-measurement code. - */ - public getUnitCode(): int32 { - return this._unitCode; - } + /** + * Get the unit-of-measurement code. + * @return the unit-of-measurement code. + */ + public getUnitCode(): int32 { + return this._unitCode; + } - /** - * Get the axis order. - * @return the axis order. - */ - public getOrder(): int32 { - return this._order; - } + /** + * Get the axis order. + * @return the axis order. + */ + public getOrder(): int32 { + return this._order; + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Axis:code=" + this._code + ",name='" + this._axisName + "',orientation='" + this._axisOrientation + "',abbreviation='" + this._abbreviation + "',unit=" + this._unitCode + ",order=" + this._order + "]"; - } + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Axis:code=" + this._code + ",name='" + this._axisName + "',orientation='" + this._axisOrientation + "',abbreviation='" + + this._abbreviation + "',unit=" + this._unitCode + ",order=" + this._order + "]"; + } } diff --git a/core/orbitgt/src/spatial/ecrs/CRS.ts b/core/orbitgt/src/spatial/ecrs/CRS.ts index 7363792774dd..b1c64582e67e 100644 --- a/core/orbitgt/src/spatial/ecrs/CRS.ts +++ b/core/orbitgt/src/spatial/ecrs/CRS.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -45,947 +45,980 @@ import { VerticalModel } from "./VerticalModel"; */ /** @internal */ export class CRS { - /** The type of a compound CRS */ - public static readonly COMPOUND: int32 = 1; - /** The type of a engineering CRS */ - public static readonly ENGINEERING: int32 = 2; - /** The type of a geocentric CRS */ - public static readonly GEOCENTRIC: int32 = 3; - /** The type of a geographic-2D CRS */ - public static readonly GEOGRAPHIC_2D: int32 = 4; - /** The type of a geographic-3D CRS */ - public static readonly GEOGRAPHIC_3D: int32 = 5; - /** The type of a projected CRS */ - public static readonly PROJECTED: int32 = 6; - /** The type of a vertical CRS */ - public static readonly VERTICAL: int32 = 7; - - /** The identification code of the WGS 84 geocentric reference system */ - public static readonly WGS84_GEOCENTRIC_CRS_CODE: int32 = 4978; - /** The identification code of the WGS 84 3D coordinate reference system */ - public static readonly WGS84_3D_CRS_CODE: int32 = 4979; - /** The identification code of the WGS 84 2D coordinate reference system */ - public static readonly WGS84_2D_CRS_CODE: int32 = 4326; - /** The identification code of the WGS 84 datum */ - private static readonly WGS84_DATUM_CODE: int32 = 6326; - - /** The identification code of the WGS 84 geocentric coordinate reference system */ - public static readonly CRS_WGS84_GEOCENTRIC: string = "4978"; - /** The identification code of the WGS 84 geographic coordinate reference system */ - public static readonly CRS_WGS84_3D: string = "4979"; - /** The identification code of the WGS 84 2D coordinate reference system */ - public static readonly CRS_WGS84_2D: string = "4326"; - - /** The cache of the WGS 84 geocentric coordinate reference system (4978) */ - private static _CACHE_WGS84_GEOCENTRIC: CRS = null; - /** The cache of the WGS 84 geographic coordinate reference system (4979) */ - private static _CACHE_WGS84_3D: CRS = null; - /** The cache of the WGS 84 2D coordinate reference system (4326) */ - private static _CACHE_WGS84_2D: CRS = null; - - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The area of use */ - private _area: int32; - /** The type (PROJECTED,GEOGRAPHIC_2D,GEOGRAPHIC_3D,GEOCENTRIC,VERTICAL,COMPOUND,...) */ - private _type: int32; - - /** The coordinate-system code */ - private _csCode: int32; - /** The coordinate axes (defined by the csCode) */ - private _axes: AList; - /** The coordinate system (can be null) */ - private _coordinateSystem: CoordinateSystem; - /** The datum */ - private _datum: Datum; - - /** The base geographic CRS */ - private _baseCRS: CRS; - /** The projection (from the base CRS to this CRS) */ - private _projection: Operation; - - /** The transformations from the base geocentric CRS to the geocentric WGS (CRS 4326) */ - private _transformationsToWGS: AList; - /** The default transformation from the base geocentric CRS to the geocentric WGS (CRS 4326) */ - private _transformationToWGS: Operation; - - /** The horizontal CRS (type COMPOUND) */ - private _horizontalComponent: CRS; - /** The vertical CRS (type COMPOUND) */ - private _verticalComponent: CRS; - /** The vertical model (type VERTICAL) */ - private _verticalModel: VerticalModel; - - /** The text information (WKT) of the CRS */ - private _textForm: string; - - /** The access time of the CRS (for garbage collecting the dynamic CRS) */ - private _accessTime: float64; - - /** - * Create a new CRS. - * @param code the code. - * @param name the name. - * @param area the area of use. - * @param type the type. - * @param csCode the coordinate-system code. - * @param datum the datum. - * @param baseCRS the base geographic CRS. - * @param projection the projection (from the base CRS to this CRS). - * @param transformationsToWGS the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). - */ - public constructor(code: int32, name: string, area: int32, type: int32, csCode: int32, datum: Datum, baseCRS: CRS, projection: Operation, transformationsToWGS: AList) { - /* Store the parameters */ - this._code = code; - this._name = name; - this._area = area; - this._type = type; - this._csCode = csCode; - this._axes = null; - this._coordinateSystem = null; - this._datum = datum; - this._baseCRS = baseCRS; - this._projection = projection; - this._transformationsToWGS = transformationsToWGS; - /* Get the default transform */ - this._transformationToWGS = Operation.getLatestTransformation(transformationsToWGS); - /* Clear */ - this._horizontalComponent = null; - this._verticalComponent = null; - this._verticalModel = null; - this._textForm = null; - this._accessTime = 0.0; + /** The type of a compound CRS */ + public static readonly COMPOUND: int32 = 1; + /** The type of a engineering CRS */ + public static readonly ENGINEERING: int32 = 2; + /** The type of a geocentric CRS */ + public static readonly GEOCENTRIC: int32 = 3; + /** The type of a geographic-2D CRS */ + public static readonly GEOGRAPHIC_2D: int32 = 4; + /** The type of a geographic-3D CRS */ + public static readonly GEOGRAPHIC_3D: int32 = 5; + /** The type of a projected CRS */ + public static readonly PROJECTED: int32 = 6; + /** The type of a vertical CRS */ + public static readonly VERTICAL: int32 = 7; + + /** The identification code of the WGS 84 geocentric reference system */ + public static readonly WGS84_GEOCENTRIC_CRS_CODE: int32 = 4978; + /** The identification code of the WGS 84 3D coordinate reference system */ + public static readonly WGS84_3D_CRS_CODE: int32 = 4979; + /** The identification code of the WGS 84 2D coordinate reference system */ + public static readonly WGS84_2D_CRS_CODE: int32 = 4326; + /** The identification code of the WGS 84 datum */ + private static readonly WGS84_DATUM_CODE: int32 = 6326; + + /** The identification code of the WGS 84 geocentric coordinate reference system */ + public static readonly CRS_WGS84_GEOCENTRIC: string = "4978"; + /** The identification code of the WGS 84 geographic coordinate reference system */ + public static readonly CRS_WGS84_3D: string = "4979"; + /** The identification code of the WGS 84 2D coordinate reference system */ + public static readonly CRS_WGS84_2D: string = "4326"; + + /** The cache of the WGS 84 geocentric coordinate reference system (4978) */ + private static _CACHE_WGS84_GEOCENTRIC: CRS = null; + /** The cache of the WGS 84 geographic coordinate reference system (4979) */ + private static _CACHE_WGS84_3D: CRS = null; + /** The cache of the WGS 84 2D coordinate reference system (4326) */ + private static _CACHE_WGS84_2D: CRS = null; + + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The area of use */ + private _area: int32; + /** The type (PROJECTED,GEOGRAPHIC_2D,GEOGRAPHIC_3D,GEOCENTRIC,VERTICAL,COMPOUND,...) */ + private _type: int32; + + /** The coordinate-system code */ + private _csCode: int32; + /** The coordinate axes (defined by the csCode) */ + private _axes: AList; + /** The coordinate system (can be null) */ + private _coordinateSystem: CoordinateSystem; + /** The datum */ + private _datum: Datum; + + /** The base geographic CRS */ + private _baseCRS: CRS; + /** The projection (from the base CRS to this CRS) */ + private _projection: Operation; + + /** The transformations from the base geocentric CRS to the geocentric WGS (CRS 4326) */ + private _transformationsToWGS: AList; + /** The default transformation from the base geocentric CRS to the geocentric WGS (CRS 4326) */ + private _transformationToWGS: Operation; + + /** The horizontal CRS (type COMPOUND) */ + private _horizontalComponent: CRS; + /** The vertical CRS (type COMPOUND) */ + private _verticalComponent: CRS; + /** The vertical model (type VERTICAL) */ + private _verticalModel: VerticalModel; + + /** The text information (WKT) of the CRS */ + private _textForm: string; + + /** The access time of the CRS (for garbage collecting the dynamic CRS) */ + private _accessTime: float64; + + /** + * Create a new CRS. + * @param code the code. + * @param name the name. + * @param area the area of use. + * @param type the type. + * @param csCode the coordinate-system code. + * @param datum the datum. + * @param baseCRS the base geographic CRS. + * @param projection the projection (from the base CRS to this CRS). + * @param transformationsToWGS the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). + */ + public constructor( + code: int32, + name: string, + area: int32, + type: int32, + csCode: int32, + datum: Datum, + baseCRS: CRS, + projection: Operation, + transformationsToWGS: AList, + ) { + /* Store the parameters */ + this._code = code; + this._name = name; + this._area = area; + this._type = type; + this._csCode = csCode; + this._axes = null; + this._coordinateSystem = null; + this._datum = datum; + this._baseCRS = baseCRS; + this._projection = projection; + this._transformationsToWGS = transformationsToWGS; + /* Get the default transform */ + this._transformationToWGS = Operation.getLatestTransformation(transformationsToWGS); + /* Clear */ + this._horizontalComponent = null; + this._verticalComponent = null; + this._verticalModel = null; + this._textForm = null; + this._accessTime = 0.0; + } + + /** + * Create a compound CRS. + * @param code the code. + * @param name the name. + * @param area the area of use. + * @param horizontalCRS the horizontal CRS. + * @param verticalCRS the vertical CRS. + * @return the compound CRS. + */ + public static createCompound(code: int32, name: string, area: int32, horizontalCRS: CRS, verticalCRS: CRS): CRS { + /* Check the parameters */ + ASystem.assertNot(horizontalCRS == null, "No horizontal CRS"); + ASystem.assertNot(verticalCRS == null, "No vertical CRS"); + ASystem.assertNot(horizontalCRS.isVertical(), "CRS is not horizontal: " + horizontalCRS); + ASystem.assertNot(verticalCRS.isVertical() == false, "CRS is not vertical: " + verticalCRS); + /* Make the CRS */ + let crs: CRS = new CRS( + code, + name, + area, + CRS.COMPOUND, + 0, /*csCode*/ + null, /*datum*/ + null, /*baseCRS*/ + null, /*projection*/ + null, /*transformationsToWGS*/ + ); + crs._horizontalComponent = horizontalCRS; + crs._verticalComponent = verticalCRS; + /* Return the CRS */ + return crs; + } + + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } + + /** + * Get the string code. + * @return the string code. + */ + public getStringCode(): string { + return "" + this._code; + } + + /** + * Check if a code matches the CRS code. + * @param code the code. + * @return true if the code matches. + */ + public hasStringCode(code: string): boolean { + return Strings.equals(code, this.getStringCode()); + } + + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } + + /** + * Get the area of use. + * @return the area. + */ + public getArea(): int32 { + return this._area; + } + + /** + * Get the type. + * @return the type. + */ + public getType(): int32 { + return this._type; + } + + /** + * Get the type label. + * @return the type label. + */ + public getTypeLabel(): string { + return CRS.labelCRSType(this._type); + } + + /** + * Is this a geocentric CRS? + * @return true for a geocentric CRS. + */ + public isGeoCentric(): boolean { + return (this._type == CRS.GEOCENTRIC); + } + + /** + * Is this a geographic CRS? + * @return true for a projected CRS. + */ + public isGeoGraphic(): boolean { + return (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D); + } + + /** + * Is this a geographic 2D CRS? + * @return true for a projected 2D CRS. + */ + public isGeoGraphic2D(): boolean { + return (this._type == CRS.GEOGRAPHIC_2D); + } + + /** + * Is this a geographic 3D CRS? + * @return true for a projected 3D CRS. + */ + public isGeoGraphic3D(): boolean { + return (this._type == CRS.GEOGRAPHIC_3D); + } + + /** + * Is this a projected CRS? + * @return true for a projected CRS. + */ + public isProjectedType(): boolean { + return (this._type == CRS.PROJECTED); + } + + /** + * Is this a projected CRS? + * @return true for a projected CRS. + */ + public isProjected(): boolean { + if (this._type == CRS.COMPOUND) return this._horizontalComponent.isProjected(); + return (this._type == CRS.PROJECTED); + } + + /** + * Is this a vertical CRS? + * @return true for a vertical CRS. + */ + public isVertical(): boolean { + return (this._type == CRS.VERTICAL); + } + + /** + * Is this a compound CRS? + * @return true for a compound CRS. + */ + public isCompound(): boolean { + return (this._type == CRS.COMPOUND); + } + + /** + * Get the coordinate-system code. + * @return the coordinate-system code. + */ + public getCoordinateSystemCode(): int32 { + return this._csCode; + } + + /** + * Get the coordinate system. + * @return the coordinate system (can be null if standard). + */ + public getCoordinateSystem(): CoordinateSystem { + return this._coordinateSystem; + } + + /** + * Get the datum. + * @return the datum. + */ + public getDatum(): Datum { + if (this._datum != null) return this._datum; + if (this._baseCRS != null) return this._baseCRS.getDatum(); + return null; + } + + /** + * Get the code of the datum. + * @return the code of the datum (0 if there is no datum). + */ + public getDatumCode(): int32 { + let datum: Datum = this.getDatum(); + return (datum == null) ? 0 : datum.getCode(); + } + + /** + * Set the datum. + * @param datum the new datum (if null check the base CRS). + */ + public setDatum(datum: Datum): void { + this._datum = datum; + } + + /** + * Get the ellipsoid. + * @return the ellipsoid. + */ + public getEllipsoid(): Ellipsoid { + return this.getDatum().getEllipsoid(); + } + + /** + * Get the base geographic CRS. + * @return the base geographic CRS. + */ + public getBaseCRS(): CRS { + return this._baseCRS; + } + + /** + * Set the base geographic CRS. + * @param baseCRS the new base geographic CRS. + */ + public setBaseCRS(baseCRS: CRS): void { + this._baseCRS = baseCRS; + } + + /** + * Get the coordinate axis of the CRS. + * @return the coordinate axis of the CRS. + */ + public getAxes(): AList { + return this._axes; + } + + /** + * Set the coordinate axis of the CRS. + * @param axis the coordinate axis of the CRS. + */ + public setAxes(axes: AList): void { + /* Store the parameters */ + this._axes = axes; + /* Update the coordinate system */ + this._coordinateSystem = CoordinateSystem.create(this._type, this._csCode, this._axes); + } + + /** + * Get the unit code of the first coordinate axis of the CRS. + * @return the unit code (defaults to METER). + */ + public getFirstAxisUnitCode(): int32 { + if (this._type == CRS.COMPOUND) return this._horizontalComponent.getFirstAxisUnitCode(); + if (this._axes == null) return Unit.METER; + if (this._axes.size() == 0) return Unit.METER; + return this._axes.get(0).getUnitCode(); + } + + /** + * Get the projection (from the base CRS to this CRS). + * @return the projection. + */ + public getProjection(): Operation { + return this._projection; + } + + /** + * Set the projection (from the base CRS to this CRS). + * @param projection the projection. + */ + public setProjection(projection: Operation): void { + this._projection = projection; + } + + /** + * Get the projection method (from the base CRS to this CRS). + * @return the projection method. + */ + public getProjectionMethod(): OperationMethod { + if (this._projection == null) return null; + return this._projection.getMethod(); + } + + /** + * Get the horizontal component of a compound CRS. + * @return the horizontal component of a compound CRS. + */ + public getHorizontalComponent(): CRS { + /* Check the type */ + ASystem.assertNot(this._type != CRS.COMPOUND, "CRS " + this._code + " is not compound"); + /* Return the component */ + return this._horizontalComponent; + } + + /** + * Check if there is a vertical component (only for type COMPOUND). + * @return true if there is a vertical component. + */ + public hasVerticalComponent(): boolean { + /* Check the type */ + if (this._type != CRS.COMPOUND) return false; + /* Check the component */ + return (this._verticalComponent != null); + } + + /** + * Get the vertical component of a compound CRS. + * @return the vertical component of a compound CRS. + */ + public getVerticalComponent(): CRS { + /* Check the type */ + ASystem.assertNot(this._type != CRS.COMPOUND, "CRS " + this._code + " is not compound"); + /* Return the component */ + return this._verticalComponent; + } + + /** + * Get the vertical model (only for type VERTICAL). + * @return the vertical model. + */ + public getVerticalModel(): VerticalModel { + return this._verticalModel; + } + + /** + * Set the vertical model (only for type VERTICAL). + * @param verticalModel the vertical model. + */ + public setVerticalModel(verticalModel: VerticalModel): void { + this._verticalModel = verticalModel; + } + + /** + * Peek at the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). + * @return the transformations. + */ + public peekTransformationsToWGS(): AList { + return this._transformationsToWGS; + } + + /** + * Get the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). + * @return the transformations. + */ + public getTransformationsToWGS(): AList { + if ((this._transformationsToWGS != null) && (this._transformationsToWGS.size() > 0)) return this._transformationsToWGS; + if (this._baseCRS != null) return this._baseCRS.getTransformationsToWGS(); + return new AList(); + } + + /** + * Set the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). + * @param transformations the transformations. + */ + public setTransformationsToWGS(transformations: AList): void { + this._transformationsToWGS = transformations; + } + + /** + * Get the default transformation from the base geographic CRS to the WGS 84 datum (of CRS 4326). + * @return a transformation (null if not available). + */ + public getTransformationToWGS(): Operation { + if (this._transformationToWGS != null) return this._transformationToWGS; + if (this._baseCRS != null) return this._baseCRS.getTransformationToWGS(); + return null; + } + + /** + * Set the default transformation from the base geographic CRS to the WGS 84 datum (of CRS 4326). + * @param transformation a transformation (null if not available). + */ + public setTransformationToWGS(transformation: Operation): void { + this._transformationToWGS = transformation; + } + + /** + * Convert to a geocentric coordinate. + * @param local the coordinate in this CRS. + * @return the geocentric coordinate. + */ + public toGeoCentric(local: Coordinate): Coordinate { + /* Projection ? */ + if (this._type == CRS.PROJECTED) { + /* We need a geographic base CRS */ + ASystem.assertNot( + this._baseCRS.isGeoGraphic() == false, + "Projected CRS '" + this._code + "' needs a geographic base CRS '" + this._baseCRS.getCode() + "', not '" + this._baseCRS.getTypeLabel() + + "'", + ); + /* Convert to standard units */ + let projected: Coordinate = local.copy(); + if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected, projected); + /* Inverse the projection to get geographic (lon,lat) coordinates (radians) */ + let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._projection.reverse(geographic, projected); + /* The geographic coordinates are in degrees */ + geographic.setX(geographic.getX() / Math.PI * 180.0); + geographic.setY(geographic.getY() / Math.PI * 180.0); + /* Let the base CRS calculate the geocentric coordinates */ + return this._baseCRS.toGeoCentric(geographic); } - - /** - * Create a compound CRS. - * @param code the code. - * @param name the name. - * @param area the area of use. - * @param horizontalCRS the horizontal CRS. - * @param verticalCRS the vertical CRS. - * @return the compound CRS. - */ - public static createCompound(code: int32, name: string, area: int32, horizontalCRS: CRS, verticalCRS: CRS): CRS { - /* Check the parameters */ - ASystem.assertNot(horizontalCRS == null, "No horizontal CRS"); - ASystem.assertNot(verticalCRS == null, "No vertical CRS"); - ASystem.assertNot(horizontalCRS.isVertical(), "CRS is not horizontal: " + horizontalCRS); - ASystem.assertNot(verticalCRS.isVertical() == false, "CRS is not vertical: " + verticalCRS); - /* Make the CRS */ - let crs: CRS = new CRS(code, name, area, CRS.COMPOUND, 0/*csCode*/, null/*datum*/, null/*baseCRS*/, null/*projection*/, null/*transformationsToWGS*/); - crs._horizontalComponent = horizontalCRS; - crs._verticalComponent = verticalCRS; - /* Return the CRS */ - return crs; - } - - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } - - /** - * Get the string code. - * @return the string code. - */ - public getStringCode(): string { - return "" + this._code; - } - - /** - * Check if a code matches the CRS code. - * @param code the code. - * @return true if the code matches. - */ - public hasStringCode(code: string): boolean { - return Strings.equals(code, this.getStringCode()); - } - - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } - - /** - * Get the area of use. - * @return the area. - */ - public getArea(): int32 { - return this._area; - } - - /** - * Get the type. - * @return the type. - */ - public getType(): int32 { - return this._type; - } - - /** - * Get the type label. - * @return the type label. - */ - public getTypeLabel(): string { - return CRS.labelCRSType(this._type); - } - - /** - * Is this a geocentric CRS? - * @return true for a geocentric CRS. - */ - public isGeoCentric(): boolean { - return (this._type == CRS.GEOCENTRIC); - } - - /** - * Is this a geographic CRS? - * @return true for a projected CRS. - */ - public isGeoGraphic(): boolean { - return (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D); - } - - /** - * Is this a geographic 2D CRS? - * @return true for a projected 2D CRS. - */ - public isGeoGraphic2D(): boolean { - return (this._type == CRS.GEOGRAPHIC_2D); - } - - /** - * Is this a geographic 3D CRS? - * @return true for a projected 3D CRS. - */ - public isGeoGraphic3D(): boolean { - return (this._type == CRS.GEOGRAPHIC_3D); - } - - /** - * Is this a projected CRS? - * @return true for a projected CRS. - */ - public isProjectedType(): boolean { - return (this._type == CRS.PROJECTED); - } - - /** - * Is this a projected CRS? - * @return true for a projected CRS. - */ - public isProjected(): boolean { - if (this._type == CRS.COMPOUND) return this._horizontalComponent.isProjected(); - return (this._type == CRS.PROJECTED); - } - - /** - * Is this a vertical CRS? - * @return true for a vertical CRS. - */ - public isVertical(): boolean { - return (this._type == CRS.VERTICAL); - } - - /** - * Is this a compound CRS? - * @return true for a compound CRS. - */ - public isCompound(): boolean { - return (this._type == CRS.COMPOUND); - } - - /** - * Get the coordinate-system code. - * @return the coordinate-system code. - */ - public getCoordinateSystemCode(): int32 { - return this._csCode; - } - - /** - * Get the coordinate system. - * @return the coordinate system (can be null if standard). - */ - public getCoordinateSystem(): CoordinateSystem { - return this._coordinateSystem; - } - - /** - * Get the datum. - * @return the datum. - */ - public getDatum(): Datum { - if (this._datum != null) return this._datum; - if (this._baseCRS != null) return this._baseCRS.getDatum(); - return null; - } - - /** - * Get the code of the datum. - * @return the code of the datum (0 if there is no datum). - */ - public getDatumCode(): int32 { - let datum: Datum = this.getDatum(); - return (datum == null) ? 0 : datum.getCode(); - } - - /** - * Set the datum. - * @param datum the new datum (if null check the base CRS). - */ - public setDatum(datum: Datum): void { - this._datum = datum; - } - - /** - * Get the ellipsoid. - * @return the ellipsoid. - */ - public getEllipsoid(): Ellipsoid { - return this.getDatum().getEllipsoid(); - } - - /** - * Get the base geographic CRS. - * @return the base geographic CRS. - */ - public getBaseCRS(): CRS { - return this._baseCRS; - } - - /** - * Set the base geographic CRS. - * @param baseCRS the new base geographic CRS. - */ - public setBaseCRS(baseCRS: CRS): void { - this._baseCRS = baseCRS; - } - - /** - * Get the coordinate axis of the CRS. - * @return the coordinate axis of the CRS. - */ - public getAxes(): AList { - return this._axes; - } - - /** - * Set the coordinate axis of the CRS. - * @param axis the coordinate axis of the CRS. - */ - public setAxes(axes: AList): void { - /* Store the parameters */ - this._axes = axes; - /* Update the coordinate system */ - this._coordinateSystem = CoordinateSystem.create(this._type, this._csCode, this._axes); - } - - /** - * Get the unit code of the first coordinate axis of the CRS. - * @return the unit code (defaults to METER). - */ - public getFirstAxisUnitCode(): int32 { - if (this._type == CRS.COMPOUND) return this._horizontalComponent.getFirstAxisUnitCode(); - if (this._axes == null) return Unit.METER; - if (this._axes.size() == 0) return Unit.METER; - return this._axes.get(0).getUnitCode(); - } - - /** - * Get the projection (from the base CRS to this CRS). - * @return the projection. - */ - public getProjection(): Operation { - return this._projection; - } - - /** - * Set the projection (from the base CRS to this CRS). - * @param projection the projection. - */ - public setProjection(projection: Operation): void { - this._projection = projection; - } - - /** - * Get the projection method (from the base CRS to this CRS). - * @return the projection method. - */ - public getProjectionMethod(): OperationMethod { - if (this._projection == null) return null; - return this._projection.getMethod(); - } - - /** - * Get the horizontal component of a compound CRS. - * @return the horizontal component of a compound CRS. - */ - public getHorizontalComponent(): CRS { - /* Check the type */ - ASystem.assertNot(this._type != CRS.COMPOUND, "CRS " + this._code + " is not compound"); - /* Return the component */ - return this._horizontalComponent; + /* Geocentric ? */ + if (this._type == CRS.GEOCENTRIC) { + /* Already geocentric */ + return local.copy(); } - - /** - * Check if there is a vertical component (only for type COMPOUND). - * @return true if there is a vertical component. - */ - public hasVerticalComponent(): boolean { - /* Check the type */ - if (this._type != CRS.COMPOUND) return false; - /* Check the component */ - return (this._verticalComponent != null); + /* Geographic ? */ + if (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D) { + /* All geographic coordinates are in degrees */ + let geographic: Coordinate = local.copy(); + geographic.setX(geographic.getX() / 180.0 * Math.PI); + geographic.setY(geographic.getY() / 180.0 * Math.PI); + /* Convert from geographic (radians) to geocentric */ + let geocentric: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._datum.getEllipsoid().toGeoCentric(geographic, geocentric); + /* Return the geocentric coordinates */ + return geocentric; } - - /** - * Get the vertical component of a compound CRS. - * @return the vertical component of a compound CRS. - */ - public getVerticalComponent(): CRS { - /* Check the type */ - ASystem.assertNot(this._type != CRS.COMPOUND, "CRS " + this._code + " is not compound"); - /* Return the component */ - return this._verticalComponent; + /* We cannot transform */ + ASystem.assertNot(true, "No geocentric transform for " + this); + return null; + } + + /** + * Convert from a geocentric coordinate. + * @param geocentric the geocentric coordinate. + * @return the coordinate in this CRS. + */ + public fromGeoCentric(geocentric: Coordinate): Coordinate { + /* Projection ? */ + if (this._type == CRS.PROJECTED) { + /* We need a geographic base CRS */ + ASystem.assertNot( + this._baseCRS.isGeoGraphic() == false, + "Projected CRS '" + this._code + "' needs a geographic base CRS '" + this._baseCRS.getCode() + "', not '" + this._baseCRS.getTypeLabel() + + "'", + ); + /* Get the geographic coordinate */ + let geographic: Coordinate = this._baseCRS.fromGeoCentric(geocentric); + /* The geographic coordinates are in degrees */ + geographic.setX(geographic.getX() / 180.0 * Math.PI); + geographic.setY(geographic.getY() / 180.0 * Math.PI); + /* Make the projection */ + let projected: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._projection.forward(geographic, projected); + /* Convert to local units */ + if (this._coordinateSystem != null) this._coordinateSystem.standardToLocal(projected, projected); + /* Return the projected coordinate */ + return projected; } - - /** - * Get the vertical model (only for type VERTICAL). - * @return the vertical model. - */ - public getVerticalModel(): VerticalModel { - return this._verticalModel; + /* Geocentric ? */ + if (this._type == CRS.GEOCENTRIC) { + /* Already geocentric */ + return geocentric.copy(); } - - /** - * Set the vertical model (only for type VERTICAL). - * @param verticalModel the vertical model. - */ - public setVerticalModel(verticalModel: VerticalModel): void { - this._verticalModel = verticalModel; + /* Geographic ? */ + if (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D) { + /* Convert from geocentric to geographic (radians) */ + let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._datum.getEllipsoid().toGeoGraphic(geocentric, geographic); + /* All geographic coordinates need to be in degrees */ + geographic.setX(geographic.getX() / Math.PI * 180.0); + geographic.setY(geographic.getY() / Math.PI * 180.0); + /* Return the geographic coordinate */ + return geographic; } - - /** - * Peek at the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). - * @return the transformations. - */ - public peekTransformationsToWGS(): AList { - return this._transformationsToWGS; - } - - /** - * Get the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). - * @return the transformations. - */ - public getTransformationsToWGS(): AList { - if ((this._transformationsToWGS != null) && (this._transformationsToWGS.size() > 0)) return this._transformationsToWGS; - if (this._baseCRS != null) return this._baseCRS.getTransformationsToWGS(); - return new AList(); + /* We cannot transform */ + ASystem.assertNot(true, "No geocentric transform for " + this); + return null; + } + + /** + * Check if this CRS is a projection of another CRS. + * @param geographic the geographic CRS to check. + * @return true if this is a projection of the geographic CRS. + */ + public isProjectionOf(geographic: CRS): boolean { + /* This has to be a projection */ + if (this._type != CRS.PROJECTED) return false; + if (this._projection == null) return false; + if (this._baseCRS == null) return false; + /* We need a geographic system */ + if (geographic._type != CRS.GEOGRAPHIC_2D && geographic._type != CRS.GEOGRAPHIC_3D) return false; + /* Is this our base CRS? */ + return (this._baseCRS.isCompatible(geographic)); + } + + /** + * Convert from a geographic coordinate to a projected coordinate. + * @param geographic the source geographic coordinate (in degrees). + * @param projected the target projected coordinate (use null to create a new coordinate). + * @return the projected coordinate. + */ + public toProjected(geographic: Coordinate, projected: Coordinate): Coordinate { + /* Create target? */ + if (projected == null) projected = new Coordinate(0.0, 0.0, 0.0); + /* The geographic coordinates are kept in degrees */ + projected.setX(geographic.getX() / 180.0 * Math.PI); + projected.setY(geographic.getY() / 180.0 * Math.PI); + projected.setZ(geographic.getZ()); + /* Make the projection */ + this._projection.forward(projected, projected); + /* Convert to local units */ + if (this._coordinateSystem != null) this._coordinateSystem.standardToLocal(projected, projected); + /* Return the result */ + return projected; + } + + /** + * Convert from a projected coordinate to a geographic coordinate. + * @param projected the source projected coordinate. + * @param geographic the target geographic coordinate (in degrees) (use null to create a new coordinate). + * @return the geographic coordinate. + */ + public fromProjected(projected: Coordinate, geographic: Coordinate): Coordinate { + /* Create target? */ + if (geographic == null) geographic = new Coordinate(0.0, 0.0, 0.0); + /* Convert to standard units */ + let projected2: Coordinate = projected.copy(); + if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected2, projected2); + /* Inverse the projection to get the geographic (lon,lat) coordinates (radians) */ + this._projection.reverse(geographic, projected2); + /* The geographic coordinates are kept in degrees */ + geographic.setX(geographic.getX() / Math.PI * 180.0); + geographic.setY(geographic.getY() / Math.PI * 180.0); + /* Return the result */ + return geographic; + } + + /** + * Get the WGS 84 2D geocentric reference system. + * @return the WGS 84 2D geocentric reference system. + */ + private static getWGS84_GeoCentric(): CRS { + if (CRS._CACHE_WGS84_GEOCENTRIC == null) CRS._CACHE_WGS84_GEOCENTRIC = Registry.getCRS2(CRS.CRS_WGS84_GEOCENTRIC); + return CRS._CACHE_WGS84_GEOCENTRIC; + } + + /** + * Get the WGS 84 2D geographic reference system. + * @return the WGS 84 2D geographic reference system. + */ + private static getWGS84_3D(): CRS { + if (CRS._CACHE_WGS84_3D == null) CRS._CACHE_WGS84_3D = Registry.getCRS2(CRS.CRS_WGS84_3D); + return CRS._CACHE_WGS84_3D; + } + + /** + * Get the WGS 84 2D coordinate reference system. + * @return the WGS 84 2D coordinate reference system. + */ + private static getWGS84_2D(): CRS { + if (CRS._CACHE_WGS84_2D == null) CRS._CACHE_WGS84_2D = Registry.getCRS2(CRS.CRS_WGS84_2D); + return CRS._CACHE_WGS84_2D; + } + + /** + * Is a conversion to and from the WGS 84 coordinate system possible? + * @return true if possible. + */ + public isWGSCompatible(): boolean { + /* Already in WGS ? */ + if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) return true; + /* Get the transformation from the local datum to the WGS datum */ + let localToWGS: Operation = this.getTransformationToWGS(); + if (localToWGS == null) return false; + /* Compatible */ + return true; + } + + /** + * Convert a coordinate to the WGS 84 (geographic 2D) coordinate system. + * @param source the coordinates in this CRS. + * @param wgsTransformationIndex the index of the WGS transformation to use (negative for the default transformation). + * @return the WGS 84 coordinate, x is longitude(-180..+180), y is latitude(-90..+90) and z is height (the z height is the same as the local height). + */ + public toWGSi(source: Coordinate, wgsTransformationIndex: int32): Coordinate { + /* Already in the WGS datum ? */ + if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) { + /* Geocentric ? */ + if (this._type == CRS.GEOCENTRIC) { + /* Convert from geocentric to geographic coordinates */ + let ageographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._datum.getEllipsoid().toGeoGraphic(source, /*geocentric*/ ageographic); + /* The WGS coordinates need to be in degrees */ + ageographic.setX(ageographic.getX() / Math.PI * 180.0); + ageographic.setY(ageographic.getY() / Math.PI * 180.0); + /* Return the WGS coordinates */ + return ageographic; + } + /* Projected ? */ + if (this._projection != null) { + /* Convert to standard units */ + let projected: Coordinate = source.copy(); + if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected, projected); + /* Inverse the projection to go from projected to geographic (lon,lat) coordinates */ + let ageographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._projection.reverse(ageographic, projected); + /* The WGS coordinates need to be in degrees */ + ageographic.setX(ageographic.getX() / Math.PI * 180.0); + ageographic.setY(ageographic.getY() / Math.PI * 180.0); + /* Return the WGS coordinates */ + return ageographic; + } + /* Geographic */ + return new Coordinate(source.getX(), source.getY(), source.getZ()); } - - /** - * Set the transformations from the base geographic CRS to the WGS 84 datum (of CRS 4326). - * @param transformations the transformations. - */ - public setTransformationsToWGS(transformations: AList): void { - this._transformationsToWGS = transformations; + /* Get the transformation from the local datum to the WGS datum */ + let localToWGS: Operation = (wgsTransformationIndex < 0) + ? this.getTransformationToWGS() + : this.getTransformationsToWGS().get(wgsTransformationIndex); + // if (localToWGS==null) + // { + // /* We cannot transform */ + // ASystem.assert(false,"No datum transformation from "+this+" to WGS"); + // } + /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ + let geocentric: Coordinate; + if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { + /* Start with the projected coordinate */ + geocentric = new Coordinate(source.getX(), source.getY(), source.getZ()); } - - /** - * Get the default transformation from the base geographic CRS to the WGS 84 datum (of CRS 4326). - * @return a transformation (null if not available). - */ - public getTransformationToWGS(): Operation { - if (this._transformationToWGS != null) return this._transformationToWGS; - if (this._baseCRS != null) return this._baseCRS.getTransformationToWGS(); - return null; + else { + /* Calculate the geocentric coordinate */ + geocentric = this.toGeoCentric(new Coordinate(source.getX(), source.getY(), source.getZ())); } - - /** - * Set the default transformation from the base geographic CRS to the WGS 84 datum (of CRS 4326). - * @param transformation a transformation (null if not available). - */ - public setTransformationToWGS(transformation: Operation): void { - this._transformationToWGS = transformation; + /* Apply the transform to the WGS datum */ + if (localToWGS != null) localToWGS.forward(geocentric, geocentric); + /* Get the geographic coordinate */ + let geographic: Coordinate = CRS.getWGS84_2D().fromGeoCentric(geocentric); + /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ + if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { + /* Assume we have the right Z */ } - - /** - * Convert to a geocentric coordinate. - * @param local the coordinate in this CRS. - * @return the geocentric coordinate. - */ - public toGeoCentric(local: Coordinate): Coordinate { - /* Projection ? */ - if (this._type == CRS.PROJECTED) { - /* We need a geographic base CRS */ - ASystem.assertNot(this._baseCRS.isGeoGraphic() == false, "Projected CRS '" + this._code + "' needs a geographic base CRS '" + this._baseCRS.getCode() + "', not '" + this._baseCRS.getTypeLabel() + "'"); - /* Convert to standard units */ - let projected: Coordinate = local.copy(); - if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected, projected); - /* Inverse the projection to get geographic (lon,lat) coordinates (radians) */ - let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._projection.reverse(geographic, projected); - /* The geographic coordinates are in degrees */ - geographic.setX(geographic.getX() / Math.PI * 180.0); - geographic.setY(geographic.getY() / Math.PI * 180.0); - /* Let the base CRS calculate the geocentric coordinates */ - return this._baseCRS.toGeoCentric(geographic); - } - /* Geocentric ? */ - if (this._type == CRS.GEOCENTRIC) { - /* Already geocentric */ - return local.copy(); - } - /* Geographic ? */ - if (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D) { - /* All geographic coordinates are in degrees */ - let geographic: Coordinate = local.copy(); - geographic.setX(geographic.getX() / 180.0 * Math.PI); - geographic.setY(geographic.getY() / 180.0 * Math.PI); - /* Convert from geographic (radians) to geocentric */ - let geocentric: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._datum.getEllipsoid().toGeoCentric(geographic, geocentric); - /* Return the geocentric coordinates */ - return geocentric; - } - /* We cannot transform */ - ASystem.assertNot(true, "No geocentric transform for " + this); - return null; - } - - /** - * Convert from a geocentric coordinate. - * @param geocentric the geocentric coordinate. - * @return the coordinate in this CRS. - */ - public fromGeoCentric(geocentric: Coordinate): Coordinate { - /* Projection ? */ - if (this._type == CRS.PROJECTED) { - /* We need a geographic base CRS */ - ASystem.assertNot(this._baseCRS.isGeoGraphic() == false, "Projected CRS '" + this._code + "' needs a geographic base CRS '" + this._baseCRS.getCode() + "', not '" + this._baseCRS.getTypeLabel() + "'"); - /* Get the geographic coordinate */ - let geographic: Coordinate = this._baseCRS.fromGeoCentric(geocentric); - /* The geographic coordinates are in degrees */ - geographic.setX(geographic.getX() / 180.0 * Math.PI); - geographic.setY(geographic.getY() / 180.0 * Math.PI); - /* Make the projection */ - let projected: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._projection.forward(geographic, projected); - /* Convert to local units */ - if (this._coordinateSystem != null) this._coordinateSystem.standardToLocal(projected, projected); - /* Return the projected coordinate */ - return projected; - } - /* Geocentric ? */ - if (this._type == CRS.GEOCENTRIC) { - /* Already geocentric */ - return geocentric.copy(); - } - /* Geographic ? */ - if (this._type == CRS.GEOGRAPHIC_2D || this._type == CRS.GEOGRAPHIC_3D) { - /* Convert from geocentric to geographic (radians) */ - let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._datum.getEllipsoid().toGeoGraphic(geocentric, geographic); - /* All geographic coordinates need to be in degrees */ - geographic.setX(geographic.getX() / Math.PI * 180.0); - geographic.setY(geographic.getY() / Math.PI * 180.0); - /* Return the geographic coordinate */ - return geographic; - } - /* We cannot transform */ - ASystem.assertNot(true, "No geocentric transform for " + this); - return null; + else { + /* Restore the original Z (is this allowed??) */ + geographic.setZ(source.getZ()); } - - /** - * Check if this CRS is a projection of another CRS. - * @param geographic the geographic CRS to check. - * @return true if this is a projection of the geographic CRS. - */ - public isProjectionOf(geographic: CRS): boolean { - /* This has to be a projection */ - if (this._type != CRS.PROJECTED) return false; - if (this._projection == null) return false; - if (this._baseCRS == null) return false; - /* We need a geographic system */ - if (geographic._type != CRS.GEOGRAPHIC_2D && geographic._type != CRS.GEOGRAPHIC_3D) return false; - /* Is this our base CRS? */ - return (this._baseCRS.isCompatible(geographic)); - } - - /** - * Convert from a geographic coordinate to a projected coordinate. - * @param geographic the source geographic coordinate (in degrees). - * @param projected the target projected coordinate (use null to create a new coordinate). - * @return the projected coordinate. - */ - public toProjected(geographic: Coordinate, projected: Coordinate): Coordinate { - /* Create target? */ - if (projected == null) projected = new Coordinate(0.0, 0.0, 0.0); - /* The geographic coordinates are kept in degrees */ - projected.setX(geographic.getX() / 180.0 * Math.PI); - projected.setY(geographic.getY() / 180.0 * Math.PI); - projected.setZ(geographic.getZ()); - /* Make the projection */ - this._projection.forward(projected, projected); + /* Return the WGS geographic coordinates */ + return geographic; + } + + /** + * Convert a coordinate to the WGS 84 (geographic 2D) coordinate system. + * @param source the coordinates in this CRS. + * @return the WGS 84 coordinate, x is longitude(-180..+180), y is latitude(-90..+90) and z is height (the z height is the same as the local height). + */ + public toWGS(source: Coordinate): Coordinate { + return this.toWGSi(source, -1); + } + + /** + * Convert from the WGS 84 (geographic 2D) coordinate system to this coordinate system. + * @param source the coordinates in the WGS 84 coordinate system, where x is longitude(-180..+180), y is latitude(-90..+90) and z is height. + * @param wgsTransformationIndex the index of the WGS transformation to use (negative for the default transformation). + * @return the coordinates in this CRS (the z height is the same as the WGS height). + */ + public fromWGSi(source: Coordinate, wgsTransformationIndex: int32): Coordinate { + /* Already in the WGS datum ? */ + if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) { + /* Geocentric ? */ + if (this._type == CRS.GEOCENTRIC) { + /* Convert to radians */ + let lon: float64 = source.getX() / 180.0 * Math.PI; + let lat: float64 = source.getY() / 180.0 * Math.PI; + let geographic: Coordinate = new Coordinate(lon, lat, source.getZ()); + /* Convert from geographic to geocentric coordinates */ + let geocentric: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._datum.getEllipsoid().toGeoCentric(geographic, geocentric); + /* Return the geocentric coordinates */ + return geocentric; + } + /* Projected ? */ + if (this._projection != null) { + /* Convert to radians */ + let lon: float64 = source.getX() / 180.0 * Math.PI; + let lat: float64 = source.getY() / 180.0 * Math.PI; + let geographic: Coordinate = new Coordinate(lon, lat, source.getZ()); + /* Use the projection to go from geographic (lon,lat) coordinates to projected coordinates */ + let projected: Coordinate = new Coordinate(0.0, 0.0, 0.0); + this._projection.forward(geographic, projected); /* Convert to local units */ if (this._coordinateSystem != null) this._coordinateSystem.standardToLocal(projected, projected); - /* Return the result */ + /* Return the projected coordinates */ return projected; + } + /* Geographic */ + return new Coordinate(source.getX(), source.getY(), source.getZ()); } - - /** - * Convert from a projected coordinate to a geographic coordinate. - * @param projected the source projected coordinate. - * @param geographic the target geographic coordinate (in degrees) (use null to create a new coordinate). - * @return the geographic coordinate. - */ - public fromProjected(projected: Coordinate, geographic: Coordinate): Coordinate { - /* Create target? */ - if (geographic == null) geographic = new Coordinate(0.0, 0.0, 0.0); - /* Convert to standard units */ - let projected2: Coordinate = projected.copy(); - if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected2, projected2); - /* Inverse the projection to get the geographic (lon,lat) coordinates (radians) */ - this._projection.reverse(geographic, projected2); - /* The geographic coordinates are kept in degrees */ - geographic.setX(geographic.getX() / Math.PI * 180.0); - geographic.setY(geographic.getY() / Math.PI * 180.0); - /* Return the result */ - return geographic; - } - - /** - * Get the WGS 84 2D geocentric reference system. - * @return the WGS 84 2D geocentric reference system. - */ - private static getWGS84_GeoCentric(): CRS { - if (CRS._CACHE_WGS84_GEOCENTRIC == null) CRS._CACHE_WGS84_GEOCENTRIC = Registry.getCRS2(CRS.CRS_WGS84_GEOCENTRIC); - return CRS._CACHE_WGS84_GEOCENTRIC; - } - - /** - * Get the WGS 84 2D geographic reference system. - * @return the WGS 84 2D geographic reference system. - */ - private static getWGS84_3D(): CRS { - if (CRS._CACHE_WGS84_3D == null) CRS._CACHE_WGS84_3D = Registry.getCRS2(CRS.CRS_WGS84_3D); - return CRS._CACHE_WGS84_3D; - } - - /** - * Get the WGS 84 2D coordinate reference system. - * @return the WGS 84 2D coordinate reference system. - */ - private static getWGS84_2D(): CRS { - if (CRS._CACHE_WGS84_2D == null) CRS._CACHE_WGS84_2D = Registry.getCRS2(CRS.CRS_WGS84_2D); - return CRS._CACHE_WGS84_2D; - } - - /** - * Is a conversion to and from the WGS 84 coordinate system possible? - * @return true if possible. - */ - public isWGSCompatible(): boolean { - /* Already in WGS ? */ - if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) return true; - /* Get the transformation from the local datum to the WGS datum */ - let localToWGS: Operation = this.getTransformationToWGS(); - if (localToWGS == null) return false; - /* Compatible */ - return true; + /* Get the transformation from the local datum to the WGS datum */ + let localToWGS: Operation = (wgsTransformationIndex < 0) + ? this.getTransformationToWGS() + : this.getTransformationsToWGS().get(wgsTransformationIndex); + // if (localToWGS==null) + // { + // /* We cannot transform */ + // ASystem.assert(false,"No datum transformation from "+this+" to WGS"); + // } + /* Transform from the WGS datum to the local datum */ + let localGeocentric: Coordinate = CRS.getWGS84_2D().toGeoCentric(source /*geographic*/); + if (localToWGS != null) localToWGS.reverse(localGeocentric, localGeocentric); + /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ + if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { + /* We already have the result */ + return localGeocentric; } - - /** - * Convert a coordinate to the WGS 84 (geographic 2D) coordinate system. - * @param source the coordinates in this CRS. - * @param wgsTransformationIndex the index of the WGS transformation to use (negative for the default transformation). - * @return the WGS 84 coordinate, x is longitude(-180..+180), y is latitude(-90..+90) and z is height (the z height is the same as the local height). - */ - public toWGSi(source: Coordinate, wgsTransformationIndex: int32): Coordinate { - /* Already in the WGS datum ? */ - if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) { - /* Geocentric ? */ - if (this._type == CRS.GEOCENTRIC) { - /* Convert from geocentric to geographic coordinates */ - let ageographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._datum.getEllipsoid().toGeoGraphic(source/*geocentric*/, ageographic); - /* The WGS coordinates need to be in degrees */ - ageographic.setX(ageographic.getX() / Math.PI * 180.0); - ageographic.setY(ageographic.getY() / Math.PI * 180.0); - /* Return the WGS coordinates */ - return ageographic; - } - /* Projected ? */ - if (this._projection != null) { - /* Convert to standard units */ - let projected: Coordinate = source.copy(); - if (this._coordinateSystem != null) this._coordinateSystem.localToStandard(projected, projected); - /* Inverse the projection to go from projected to geographic (lon,lat) coordinates */ - let ageographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._projection.reverse(ageographic, projected); - /* The WGS coordinates need to be in degrees */ - ageographic.setX(ageographic.getX() / Math.PI * 180.0); - ageographic.setY(ageographic.getY() / Math.PI * 180.0); - /* Return the WGS coordinates */ - return ageographic; - } - /* Geographic */ - return new Coordinate(source.getX(), source.getY(), source.getZ()); - } - /* Get the transformation from the local datum to the WGS datum */ - let localToWGS: Operation = (wgsTransformationIndex < 0) ? this.getTransformationToWGS() : this.getTransformationsToWGS().get(wgsTransformationIndex); - // if (localToWGS==null) - // { - // /* We cannot transform */ - // ASystem.assert(false,"No datum transformation from "+this+" to WGS"); - // } - /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ - let geocentric: Coordinate; - if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { - /* Start with the projected coordinate */ - geocentric = new Coordinate(source.getX(), source.getY(), source.getZ()); - } - else { - /* Calculate the geocentric coordinate */ - geocentric = this.toGeoCentric(new Coordinate(source.getX(), source.getY(), source.getZ())); - } - /* Apply the transform to the WGS datum */ - if (localToWGS != null) localToWGS.forward(geocentric, geocentric); - /* Get the geographic coordinate */ - let geographic: Coordinate = CRS.getWGS84_2D().fromGeoCentric(geocentric); - /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ - if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { - /* Assume we have the right Z */ - } - else { - /* Restore the original Z (is this allowed??) */ - geographic.setZ(source.getZ()); - } - /* Return the WGS geographic coordinates */ - return geographic; + else { + /* Convert from geocentric to local coordinates */ + let local: Coordinate = this.fromGeoCentric(localGeocentric); + /* Restore the original Z (is this allowed??) */ + local.setZ(source.getZ()); + /* Return the local coordinates */ + return local; } - - /** - * Convert a coordinate to the WGS 84 (geographic 2D) coordinate system. - * @param source the coordinates in this CRS. - * @return the WGS 84 coordinate, x is longitude(-180..+180), y is latitude(-90..+90) and z is height (the z height is the same as the local height). - */ - public toWGS(source: Coordinate): Coordinate { - return this.toWGSi(source, -1); + } + + /** + * Convert from the WGS 84 (geographic 2D) coordinate system to this coordinate system. + * @param source the coordinates in the WGS 84 coordinate system, where x is longitude(-180..+180), y is latitude(-90..+90) and z is height. + * @return the coordinates in this CRS (the z height is the same as the WGS height). + */ + public fromWGS(source: Coordinate): Coordinate { + return this.fromWGSi(source, -1); + } + + /** + * Check if another CRS is compatible with this one. + * @param other the other CRS. + * @return true if compatible. + */ + public isCompatible(other: CRS): boolean { + /* Check the base parameters */ + if (other._code == this._code) return true; + if (other._type != this._type) return false; + if (other._csCode != this._csCode) return false; + /* Geographic? */ + if (this.isGeoCentric() || this.isGeoGraphic()) { + /* Same datum? */ + if (Datum.areCompatible(other.getDatum(), this.getDatum()) == false) return false; + /* We need the same transformation to WGS (check CRS 2039 for example: wgs compatible datum, but with geocentric translation to wgs) */ + if (Operation.isCompatibleOperation(other.getTransformationToWGS(), this.getTransformationToWGS()) == false) return false; + return true; } - - /** - * Convert from the WGS 84 (geographic 2D) coordinate system to this coordinate system. - * @param source the coordinates in the WGS 84 coordinate system, where x is longitude(-180..+180), y is latitude(-90..+90) and z is height. - * @param wgsTransformationIndex the index of the WGS transformation to use (negative for the default transformation). - * @return the coordinates in this CRS (the z height is the same as the WGS height). - */ - public fromWGSi(source: Coordinate, wgsTransformationIndex: int32): Coordinate { - /* Already in the WGS datum ? */ - if (this.getDatum().getCode() == CRS.WGS84_DATUM_CODE) { - /* Geocentric ? */ - if (this._type == CRS.GEOCENTRIC) { - /* Convert to radians */ - let lon: float64 = source.getX() / 180.0 * Math.PI; - let lat: float64 = source.getY() / 180.0 * Math.PI; - let geographic: Coordinate = new Coordinate(lon, lat, source.getZ()); - /* Convert from geographic to geocentric coordinates */ - let geocentric: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._datum.getEllipsoid().toGeoCentric(geographic, geocentric); - /* Return the geocentric coordinates */ - return geocentric; - } - /* Projected ? */ - if (this._projection != null) { - /* Convert to radians */ - let lon: float64 = source.getX() / 180.0 * Math.PI; - let lat: float64 = source.getY() / 180.0 * Math.PI; - let geographic: Coordinate = new Coordinate(lon, lat, source.getZ()); - /* Use the projection to go from geographic (lon,lat) coordinates to projected coordinates */ - let projected: Coordinate = new Coordinate(0.0, 0.0, 0.0); - this._projection.forward(geographic, projected); - /* Convert to local units */ - if (this._coordinateSystem != null) this._coordinateSystem.standardToLocal(projected, projected); - /* Return the projected coordinates */ - return projected; - } - /* Geographic */ - return new Coordinate(source.getX(), source.getY(), source.getZ()); - } - /* Get the transformation from the local datum to the WGS datum */ - let localToWGS: Operation = (wgsTransformationIndex < 0) ? this.getTransformationToWGS() : this.getTransformationsToWGS().get(wgsTransformationIndex); - // if (localToWGS==null) - // { - // /* We cannot transform */ - // ASystem.assert(false,"No datum transformation from "+this+" to WGS"); - // } - /* Transform from the WGS datum to the local datum */ - let localGeocentric: Coordinate = CRS.getWGS84_2D().toGeoCentric(source/*geographic*/); - if (localToWGS != null) localToWGS.reverse(localGeocentric, localGeocentric); - /* Does the transform work on the projected coordinates (like the OSTN02 grid correction)? */ - if ((localToWGS != null) && localToWGS.getSourceCRS().isProjected()) { - /* We already have the result */ - return localGeocentric; - } - else { - /* Convert from geocentric to local coordinates */ - let local: Coordinate = this.fromGeoCentric(localGeocentric); - /* Restore the original Z (is this allowed??) */ - local.setZ(source.getZ()); - /* Return the local coordinates */ - return local; - } + /* Projected? */ + else if (this.isProjected()) { + /* Same projection? */ + if (Operation.isCompatibleOperation(other._projection, this._projection) == false) return false; + /* Has base CRS? */ + if (other._baseCRS == null || this._baseCRS == null) return false; + /* Same base? */ + return (other._baseCRS.isCompatible(this._baseCRS)); } - - /** - * Convert from the WGS 84 (geographic 2D) coordinate system to this coordinate system. - * @param source the coordinates in the WGS 84 coordinate system, where x is longitude(-180..+180), y is latitude(-90..+90) and z is height. - * @return the coordinates in this CRS (the z height is the same as the WGS height). - */ - public fromWGS(source: Coordinate): Coordinate { - return this.fromWGSi(source, -1); + /* Vertical? */ + else if (this.isVertical()) { + /* Same datum? */ + if (Datum.areCompatible(other.getDatum(), this.getDatum()) == false) return false; + return true; } - - /** - * Check if another CRS is compatible with this one. - * @param other the other CRS. - * @return true if compatible. - */ - public isCompatible(other: CRS): boolean { - /* Check the base parameters */ - if (other._code == this._code) return true; - if (other._type != this._type) return false; - if (other._csCode != this._csCode) return false; - /* Geographic? */ - if (this.isGeoCentric() || this.isGeoGraphic()) { - /* Same datum? */ - if (Datum.areCompatible(other.getDatum(), this.getDatum()) == false) return false; - /* We need the same transformation to WGS (check CRS 2039 for example: wgs compatible datum, but with geocentric translation to wgs) */ - if (Operation.isCompatibleOperation(other.getTransformationToWGS(), this.getTransformationToWGS()) == false) return false; - return true; - } - /* Projected? */ - else if (this.isProjected()) { - /* Same projection? */ - if (Operation.isCompatibleOperation(other._projection, this._projection) == false) return false; - /* Has base CRS? */ - if (other._baseCRS == null || this._baseCRS == null) return false; - /* Same base? */ - return (other._baseCRS.isCompatible(this._baseCRS)); - } - /* Vertical? */ - else if (this.isVertical()) { - /* Same datum? */ - if (Datum.areCompatible(other.getDatum(), this.getDatum()) == false) return false; - return true; - } - /* Compound? */ - else if (this.isCompound()) { - /* Same components? */ - if (CRS.areCompatible(other._horizontalComponent, this._horizontalComponent) == false) return false; - if (CRS.areCompatible(other._verticalComponent, this._verticalComponent) == false) return false; - return true; - } - /* Other */ - else { - return false; - } - } - - /** - * Check if two CRSs are compatible. - * @param crs1 the first CRS. - * @param crs2 the second CRS. - * @return true if compatible. - */ - public static areCompatible(crs1: CRS, crs2: CRS): boolean { - if (crs1 == null) return (crs2 == null); - if (crs2 == null) return false; - return crs1.isCompatible(crs2); + /* Compound? */ + else if (this.isCompound()) { + /* Same components? */ + if (CRS.areCompatible(other._horizontalComponent, this._horizontalComponent) == false) return false; + if (CRS.areCompatible(other._verticalComponent, this._verticalComponent) == false) return false; + return true; } - - /** - * Get the text form of the CRS. - * @return the text form of the CRS. - */ - public getTextForm(): string { - return this._textForm; - } - - /** - * Set the text form of the CRS. - * @param textForm the text form of the CRS. - */ - public setTextForm(textForm: string): void { - this._textForm = textForm; - } - - /** - * Get the access time. - * @return the access time. - */ - public getAccessTime(): float64 { - return this._accessTime; - } - - /** - * Set the access time. - * @param time the access time. - */ - public setAccessTime(time: float64): void { - this._accessTime = time; - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[CRS:code=" + this._code + ",name='" + this._name + "',area=" + this._area + ",type='" + CRS.labelCRSType(this._type) + "',datum=" + this._datum + ",baseCRS=" + this._baseCRS + ",wgs-transform=" + (this._transformationToWGS != null) + "]"; - } - - /** - * Get the type of a CRS. - * @param crsKind the type of CRS. - * @return a parsed type. - */ - public static parseCRSType(crsKind: string): int32 { - if (Strings.equalsIgnoreCase(crsKind, "compound")) return CRS.COMPOUND; - if (Strings.equalsIgnoreCase(crsKind, "engineering")) return CRS.ENGINEERING; - if (Strings.equalsIgnoreCase(crsKind, "geocentric")) return CRS.GEOCENTRIC; - if (Strings.equalsIgnoreCase(crsKind, "geographic 2D")) return CRS.GEOGRAPHIC_2D; - if (Strings.equalsIgnoreCase(crsKind, "geographic 3D")) return CRS.GEOGRAPHIC_3D; - if (Strings.equalsIgnoreCase(crsKind, "projected")) return CRS.PROJECTED; - if (Strings.equalsIgnoreCase(crsKind, "vertical")) return CRS.VERTICAL; - ASystem.assert0(false, "CRS kind '" + crsKind + "' not found"); - return 0; - } - - /** - * Get the label of a type of a CRS. - * @param crsType the type of CRS. - * @return a label. - */ - public static labelCRSType(crsType: int32): string { - if (crsType == CRS.COMPOUND) return "compound"; - if (crsType == CRS.ENGINEERING) return "engineering"; - if (crsType == CRS.GEOCENTRIC) return "geocentric"; - if (crsType == CRS.GEOGRAPHIC_2D) return "geographic 2D"; - if (crsType == CRS.GEOGRAPHIC_3D) return "geographic 3D"; - if (crsType == CRS.PROJECTED) return "projected"; - if (crsType == CRS.VERTICAL) return "vertical"; - ASystem.assert0(false, "CRS type '" + crsType + "' not found"); - return null; + /* Other */ + else { + return false; } + } + + /** + * Check if two CRSs are compatible. + * @param crs1 the first CRS. + * @param crs2 the second CRS. + * @return true if compatible. + */ + public static areCompatible(crs1: CRS, crs2: CRS): boolean { + if (crs1 == null) return (crs2 == null); + if (crs2 == null) return false; + return crs1.isCompatible(crs2); + } + + /** + * Get the text form of the CRS. + * @return the text form of the CRS. + */ + public getTextForm(): string { + return this._textForm; + } + + /** + * Set the text form of the CRS. + * @param textForm the text form of the CRS. + */ + public setTextForm(textForm: string): void { + this._textForm = textForm; + } + + /** + * Get the access time. + * @return the access time. + */ + public getAccessTime(): float64 { + return this._accessTime; + } + + /** + * Set the access time. + * @param time the access time. + */ + public setAccessTime(time: float64): void { + this._accessTime = time; + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[CRS:code=" + this._code + ",name='" + this._name + "',area=" + this._area + ",type='" + CRS.labelCRSType(this._type) + "',datum=" + + this._datum + ",baseCRS=" + this._baseCRS + ",wgs-transform=" + (this._transformationToWGS != null) + "]"; + } + + /** + * Get the type of a CRS. + * @param crsKind the type of CRS. + * @return a parsed type. + */ + public static parseCRSType(crsKind: string): int32 { + if (Strings.equalsIgnoreCase(crsKind, "compound")) return CRS.COMPOUND; + if (Strings.equalsIgnoreCase(crsKind, "engineering")) return CRS.ENGINEERING; + if (Strings.equalsIgnoreCase(crsKind, "geocentric")) return CRS.GEOCENTRIC; + if (Strings.equalsIgnoreCase(crsKind, "geographic 2D")) return CRS.GEOGRAPHIC_2D; + if (Strings.equalsIgnoreCase(crsKind, "geographic 3D")) return CRS.GEOGRAPHIC_3D; + if (Strings.equalsIgnoreCase(crsKind, "projected")) return CRS.PROJECTED; + if (Strings.equalsIgnoreCase(crsKind, "vertical")) return CRS.VERTICAL; + ASystem.assert0(false, "CRS kind '" + crsKind + "' not found"); + return 0; + } + + /** + * Get the label of a type of a CRS. + * @param crsType the type of CRS. + * @return a label. + */ + public static labelCRSType(crsType: int32): string { + if (crsType == CRS.COMPOUND) return "compound"; + if (crsType == CRS.ENGINEERING) return "engineering"; + if (crsType == CRS.GEOCENTRIC) return "geocentric"; + if (crsType == CRS.GEOGRAPHIC_2D) return "geographic 2D"; + if (crsType == CRS.GEOGRAPHIC_3D) return "geographic 3D"; + if (crsType == CRS.PROJECTED) return "projected"; + if (crsType == CRS.VERTICAL) return "vertical"; + ASystem.assert0(false, "CRS type '" + crsType + "' not found"); + return null; + } } diff --git a/core/orbitgt/src/spatial/ecrs/CoordinateSystem.ts b/core/orbitgt/src/spatial/ecrs/CoordinateSystem.ts index 007964ad1bed..a069a9af0afe 100644 --- a/core/orbitgt/src/spatial/ecrs/CoordinateSystem.ts +++ b/core/orbitgt/src/spatial/ecrs/CoordinateSystem.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -30,306 +30,318 @@ import { Unit } from "./Unit"; */ /** @internal */ export class CoordinateSystem { - /** The name of this module */ - private static readonly MODULE: string = "CoordinateSystem"; + /** The name of this module */ + private static readonly MODULE: string = "CoordinateSystem"; - /** The type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...) */ - private _type: int32; - /** The coordinate-system code */ - private _csCode: int32; - /** The coordinate axes (defined by the csCode) */ - private _axes: AList; + /** The type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...) */ + private _type: int32; + /** The coordinate-system code */ + private _csCode: int32; + /** The coordinate axes (defined by the csCode) */ + private _axes: AList; - /** The X axis (derived) */ - private _xAxis: Axis; - /** The Y axis (derived) */ - private _yAxis: Axis; - /** The Z axis (derived) */ - private _zAxis: Axis; - /** The X unit (derived) */ - private _xUnit: Unit; - /** The Y unit (derived) */ - private _yUnit: Unit; - /** The Z unit (derived) */ - private _zUnit: Unit; + /** The X axis (derived) */ + private _xAxis: Axis; + /** The Y axis (derived) */ + private _yAxis: Axis; + /** The Z axis (derived) */ + private _zAxis: Axis; + /** The X unit (derived) */ + private _xUnit: Unit; + /** The Y unit (derived) */ + private _yUnit: Unit; + /** The Z unit (derived) */ + private _zUnit: Unit; - /** - * Check if easting-northing axis order is swapped? - * @param csCode the code of the coordinate-system. - * @return true for swapped CRS. - */ - public static isSwappedEN(csCode: int32): boolean { - if (csCode == 1029) return true; - // if (csCode==4400) return true; // this used to be swapped in the EPSG database, but not anymore - if (csCode == 4498) return true; - if (csCode == 4500) return true; - if (csCode == 4532) return true; - return false; - } + /** + * Check if easting-northing axis order is swapped? + * @param csCode the code of the coordinate-system. + * @return true for swapped CRS. + */ + public static isSwappedEN(csCode: int32): boolean { + if (csCode == 1029) return true; + // if (csCode==4400) return true; // this used to be swapped in the EPSG database, but not anymore + if (csCode == 4498) return true; + if (csCode == 4500) return true; + if (csCode == 4532) return true; + return false; + } - /** - * Create a coordinate system. - * @param type the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). - * @param csCode the coordinate-system code. - * @param axes the (sorted on order) coordinate axes. - * @return the coordinate system (null for an identify system). - */ - public static create(type: int32, csCode: int32, axes: AList): CoordinateSystem { - let coordinateSystem: CoordinateSystem = new CoordinateSystem(type, csCode, axes); - if (coordinateSystem.isIdentity()) return null; - return coordinateSystem; - } + /** + * Create a coordinate system. + * @param type the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). + * @param csCode the coordinate-system code. + * @param axes the (sorted on order) coordinate axes. + * @return the coordinate system (null for an identify system). + */ + public static create(type: int32, csCode: int32, axes: AList): CoordinateSystem { + let coordinateSystem: CoordinateSystem = new CoordinateSystem(type, csCode, axes); + if (coordinateSystem.isIdentity()) return null; + return coordinateSystem; + } - /** - * Create a new coordinate system. - * @param type the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). - * @param csCode the coordinate-system code. - * @param axes the (sorted on order) coordinate axes. - */ - public constructor(type: int32, csCode: int32, axes: AList) { - /* Store the parameters */ - this._type = type; - this._csCode = csCode; - this._axes = axes; - /* Clear */ - this._xAxis = null; - this._yAxis = null; - this._zAxis = null; - this._xUnit = null; - this._yUnit = null; - this._zUnit = null; - /* Projection? */ - if (type == CRS.PROJECTED) this.parseProjection(); - /* Log? */ - if (this.isIdentity() == false) { - /* Log */ - Message.print(CoordinateSystem.MODULE, "Created coordinate system " + this._csCode); - if (this._xAxis != null) Message.print(CoordinateSystem.MODULE, "X axis '" + this._xAxis.getAbbreviation() + "'/'" + this._xAxis.getAxisName() + "' (" + this._xAxis.getOrder() + ")"); - if (this._yAxis != null) Message.print(CoordinateSystem.MODULE, "Y axis '" + this._yAxis.getAbbreviation() + "'/'" + this._yAxis.getAxisName() + "' (" + this._yAxis.getOrder() + ")"); - if (this._zAxis != null) Message.print(CoordinateSystem.MODULE, "Z axis '" + this._zAxis.getAbbreviation() + "'/'" + this._zAxis.getAxisName() + "' (" + this._zAxis.getOrder() + ")"); - if (this._xUnit != null) Message.print(CoordinateSystem.MODULE, "X unit '" + this._xUnit.getName() + "'"); - if (this._yUnit != null) Message.print(CoordinateSystem.MODULE, "Y unit '" + this._yUnit.getName() + "'"); - if (this._zUnit != null) Message.print(CoordinateSystem.MODULE, "Z unit '" + this._zUnit.getName() + "'"); - } + /** + * Create a new coordinate system. + * @param type the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). + * @param csCode the coordinate-system code. + * @param axes the (sorted on order) coordinate axes. + */ + public constructor(type: int32, csCode: int32, axes: AList) { + /* Store the parameters */ + this._type = type; + this._csCode = csCode; + this._axes = axes; + /* Clear */ + this._xAxis = null; + this._yAxis = null; + this._zAxis = null; + this._xUnit = null; + this._yUnit = null; + this._zUnit = null; + /* Projection? */ + if (type == CRS.PROJECTED) this.parseProjection(); + /* Log? */ + if (this.isIdentity() == false) { + /* Log */ + Message.print(CoordinateSystem.MODULE, "Created coordinate system " + this._csCode); + if (this._xAxis != null) + Message.print( + CoordinateSystem.MODULE, + "X axis '" + this._xAxis.getAbbreviation() + "'/'" + this._xAxis.getAxisName() + "' (" + this._xAxis.getOrder() + ")", + ); + if (this._yAxis != null) + Message.print( + CoordinateSystem.MODULE, + "Y axis '" + this._yAxis.getAbbreviation() + "'/'" + this._yAxis.getAxisName() + "' (" + this._yAxis.getOrder() + ")", + ); + if (this._zAxis != null) + Message.print( + CoordinateSystem.MODULE, + "Z axis '" + this._zAxis.getAbbreviation() + "'/'" + this._zAxis.getAxisName() + "' (" + this._zAxis.getOrder() + ")", + ); + if (this._xUnit != null) Message.print(CoordinateSystem.MODULE, "X unit '" + this._xUnit.getName() + "'"); + if (this._yUnit != null) Message.print(CoordinateSystem.MODULE, "Y unit '" + this._yUnit.getName() + "'"); + if (this._zUnit != null) Message.print(CoordinateSystem.MODULE, "Z unit '" + this._zUnit.getName() + "'"); } + } - /** - * Get the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). - * @return the type. - */ - public getType(): int32 { - return this._type; - } + /** + * Get the type of coordinate reference system (PROJECTED,GEOGRAPHIC_2D,...). + * @return the type. + */ + public getType(): int32 { + return this._type; + } - /** - * Get the code of the coordinate system. - * @return the code of the coordinate system. - */ - public getCode(): int32 { - return this._csCode; - } + /** + * Get the code of the coordinate system. + * @return the code of the coordinate system. + */ + public getCode(): int32 { + return this._csCode; + } - /** - * Get the coordinate axes. - * @return the coordinate axes. - */ - public getAxes(): AList { - return this._axes; - } + /** + * Get the coordinate axes. + * @return the coordinate axes. + */ + public getAxes(): AList { + return this._axes; + } - /** - * Do we have an identity transformation between local and standard forms? - * @return true for an identity transform. - */ - public isIdentity(): boolean { - /* Check the axis */ - if ((this._xAxis != null) && (this._xAxis.getOrder() != 1)) return false; - if ((this._yAxis != null) && (this._yAxis.getOrder() != 2)) return false; - if ((this._zAxis != null) && (this._zAxis.getOrder() != 3)) return false; - /* Check the units */ - if (this._xUnit != null) return false; - if (this._yUnit != null) return false; - if (this._zUnit != null) return false; - /* We have identity */ - return true; - } + /** + * Do we have an identity transformation between local and standard forms? + * @return true for an identity transform. + */ + public isIdentity(): boolean { + /* Check the axis */ + if ((this._xAxis != null) && (this._xAxis.getOrder() != 1)) return false; + if ((this._yAxis != null) && (this._yAxis.getOrder() != 2)) return false; + if ((this._zAxis != null) && (this._zAxis.getOrder() != 3)) return false; + /* Check the units */ + if (this._xUnit != null) return false; + if (this._yUnit != null) return false; + if (this._zUnit != null) return false; + /* We have identity */ + return true; + } - /** - * Get the X axis. - * @return the X axis. - */ - public getXAxis(): Axis { - return this._xAxis; - } + /** + * Get the X axis. + * @return the X axis. + */ + public getXAxis(): Axis { + return this._xAxis; + } - /** - * Get the Y axis. - * @return the Y axis. - */ - public getYAxis(): Axis { - return this._yAxis; - } + /** + * Get the Y axis. + * @return the Y axis. + */ + public getYAxis(): Axis { + return this._yAxis; + } - /** - * Get the Z axis. - * @return the Z axis. - */ - public getZAxis(): Axis { - return this._zAxis; - } + /** + * Get the Z axis. + * @return the Z axis. + */ + public getZAxis(): Axis { + return this._zAxis; + } - /** - * Get the unit of the first axis. - * @return the unit of the first axis (null for the default unit). - */ - public getXUnit(): Unit { - return this._xUnit; - } + /** + * Get the unit of the first axis. + * @return the unit of the first axis (null for the default unit). + */ + public getXUnit(): Unit { + return this._xUnit; + } - /** - * Get the unit of the second axis. - * @return the unit of the second axis (null for the default unit). - */ - public getYUnit(): Unit { - return this._yUnit; - } + /** + * Get the unit of the second axis. + * @return the unit of the second axis (null for the default unit). + */ + public getYUnit(): Unit { + return this._yUnit; + } - /** - * Get the unit of the third axis. - * @return the unit of the third axis (null for the default unit). - */ - public getZUnit(): Unit { - return this._zUnit; - } + /** + * Get the unit of the third axis. + * @return the unit of the third axis (null for the default unit). + */ + public getZUnit(): Unit { + return this._zUnit; + } - /** - * Parse a projection type coordinate system. - */ - private parseProjection(): void { - /* Get the abbreviations */ - let name1: string = this._axes.get(0).getAbbreviation(); - let name2: string = this._axes.get(1).getAbbreviation(); - // /* Get the axis names */ - // String aname1 = this._axis[0].getAxisName(); - // String aname2 = this._axis[1].getAxisName(); - // /* Special cases */ - // if (aname1.equalsIgnoreCase("Northing") && aname2.equalsIgnoreCase("Easting")) - // { - // /* Coordinate system 4531, used by CRS 2180: ETRS89 / Poland CS92 */ - // name1 = "N"; - // name2 = "E"; - // } - /* Check the various combinations */ - let xy1: boolean = (Strings.equalsIgnoreCase(name1, "X") && Strings.equalsIgnoreCase(name2, "Y")); - let xy2: boolean = (Strings.equalsIgnoreCase(name1, "E") && Strings.equalsIgnoreCase(name2, "N")); - let xy3: boolean = (Strings.equalsIgnoreCase(name1, "E(X)") && Strings.equalsIgnoreCase(name2, "N(Y)")); - let xy4: boolean = (Strings.equalsIgnoreCase(name1, "M") && Strings.equalsIgnoreCase(name2, "P")); // csCode 1024, Portuguese - let yx1: boolean = (Strings.equalsIgnoreCase(name1, "Y") && Strings.equalsIgnoreCase(name2, "X")); - let yx2: boolean = (Strings.equalsIgnoreCase(name1, "N") && Strings.equalsIgnoreCase(name2, "E")); - /* XY sequence? */ - if (xy1 || xy2 || xy3 || xy4) { - this._xAxis = this._axes.get(0); - this._yAxis = this._axes.get(1); - } - /* YX sequence */ - else if (yx1 || yx2) { - this._xAxis = this._axes.get(1); - this._yAxis = this._axes.get(0); - } - /* Default */ - else { - this._xAxis = this._axes.get(0); - this._yAxis = this._axes.get(1); - /* Log */ - Message.printWarning(CoordinateSystem.MODULE, "Invalid projected axis '" + name1 + "','" + name2 + "'"); - } - /* Do we have a Z axis? */ - if (this._axes.size() >= 3) { - this._zAxis = this._axes.get(2); - } - /* Get the units */ - if ((this._xAxis != null) && this._xAxis.getUnitCode() != Unit.METER) this._xUnit = Registry.getUnit(this._xAxis.getUnitCode()); - if ((this._yAxis != null) && this._yAxis.getUnitCode() != Unit.METER) this._yUnit = Registry.getUnit(this._yAxis.getUnitCode()); - if ((this._zAxis != null) && this._zAxis.getUnitCode() != Unit.METER) this._zUnit = Registry.getUnit(this._zAxis.getUnitCode()); + /** + * Parse a projection type coordinate system. + */ + private parseProjection(): void { + /* Get the abbreviations */ + let name1: string = this._axes.get(0).getAbbreviation(); + let name2: string = this._axes.get(1).getAbbreviation(); + // /* Get the axis names */ + // String aname1 = this._axis[0].getAxisName(); + // String aname2 = this._axis[1].getAxisName(); + // /* Special cases */ + // if (aname1.equalsIgnoreCase("Northing") && aname2.equalsIgnoreCase("Easting")) + // { + // /* Coordinate system 4531, used by CRS 2180: ETRS89 / Poland CS92 */ + // name1 = "N"; + // name2 = "E"; + // } + /* Check the various combinations */ + let xy1: boolean = Strings.equalsIgnoreCase(name1, "X") && Strings.equalsIgnoreCase(name2, "Y"); + let xy2: boolean = Strings.equalsIgnoreCase(name1, "E") && Strings.equalsIgnoreCase(name2, "N"); + let xy3: boolean = Strings.equalsIgnoreCase(name1, "E(X)") && Strings.equalsIgnoreCase(name2, "N(Y)"); + let xy4: boolean = Strings.equalsIgnoreCase(name1, "M") && Strings.equalsIgnoreCase(name2, "P"); // csCode 1024, Portuguese + let yx1: boolean = Strings.equalsIgnoreCase(name1, "Y") && Strings.equalsIgnoreCase(name2, "X"); + let yx2: boolean = Strings.equalsIgnoreCase(name1, "N") && Strings.equalsIgnoreCase(name2, "E"); + /* XY sequence? */ + if (xy1 || xy2 || xy3 || xy4) { + this._xAxis = this._axes.get(0); + this._yAxis = this._axes.get(1); } - - /** - * Get a local coordinate. - * @param local the coordinate. - * @param axis the standard axis to retrieve. - * @param order the default order. - * @return the coordinate. - */ - private static getLocalCoordinate(local: Coordinate, axis: Axis, order: int32): float64 { - /* Do we have an axis? */ - if (axis != null) order = axis.getOrder(); - /* Return the request coordinate */ - if (order == 1) return local.getX(); - if (order == 2) return local.getY(); - if (order == 3) return local.getZ(); - return 0.0; + /* YX sequence */ + else if (yx1 || yx2) { + this._xAxis = this._axes.get(1); + this._yAxis = this._axes.get(0); } - - /** - * Convert a coordinate from the local to the standard form. - * @param local the local coordinate (input). - * @param standard the standard coordinate (can be same as local) (output). - */ - public localToStandard(local: Coordinate, standard: Coordinate): void { - /* Get X */ - let x: float64 = CoordinateSystem.getLocalCoordinate(local, this._xAxis, 1); - if (this._xUnit != null) x = this._xUnit.toStandard(x); - /* Get Y */ - let y: float64 = CoordinateSystem.getLocalCoordinate(local, this._yAxis, 2); - if (this._yUnit != null) y = this._yUnit.toStandard(y); - /* Get Z */ - let z: float64 = CoordinateSystem.getLocalCoordinate(local, this._zAxis, 3); - if (this._zUnit != null) z = this._zUnit.toStandard(z); - /* Set */ - standard.setX(x); - standard.setY(y); - standard.setZ(z); + /* Default */ + else { + this._xAxis = this._axes.get(0); + this._yAxis = this._axes.get(1); + /* Log */ + Message.printWarning(CoordinateSystem.MODULE, "Invalid projected axis '" + name1 + "','" + name2 + "'"); } - - /** - * Get a standard coordinate. - * @param x the standard x coordinate. - * @param y the standard y coordinate. - * @param z the standard z coordinate. - * @param axis the local axis to consider. - * @param index the default index. - * @return the coordinate. - */ - private getStandardCoordinate(x: float64, y: float64, z: float64, axis: Axis, index: int32): float64 { - /* Check the standard index of the axis */ - if (axis == this._xAxis) index = 1; - else if (axis == this._yAxis) index = 2; - else if (axis == this._zAxis) index = 3; - /* Return the coordinate */ - if (index == 1) return x; - if (index == 2) return y; - if (index == 3) return z; - return 0.0; + /* Do we have a Z axis? */ + if (this._axes.size() >= 3) { + this._zAxis = this._axes.get(2); } + /* Get the units */ + if ((this._xAxis != null) && this._xAxis.getUnitCode() != Unit.METER) this._xUnit = Registry.getUnit(this._xAxis.getUnitCode()); + if ((this._yAxis != null) && this._yAxis.getUnitCode() != Unit.METER) this._yUnit = Registry.getUnit(this._yAxis.getUnitCode()); + if ((this._zAxis != null) && this._zAxis.getUnitCode() != Unit.METER) this._zUnit = Registry.getUnit(this._zAxis.getUnitCode()); + } - /** - * Convert a coordinate from the standard to the local form. - * @param standard the standard coordinate (input). - * @param local the local coordinate (can be same as standard) (output). - */ - public standardToLocal(standard: Coordinate, local: Coordinate): void { - /* Get X */ - let x: float64 = standard.getX(); - if (this._xUnit != null) x = this._xUnit.fromStandard(x); - /* Get Y */ - let y: float64 = standard.getY(); - if (this._yUnit != null) y = this._yUnit.fromStandard(y); - /* Get Z */ - let z: float64 = standard.getZ(); - if (this._zUnit != null) z = this._zUnit.fromStandard(z); - /* Set */ - local.setX(this.getStandardCoordinate(x, y, z, this._axes.get(0), 1)); - local.setY(this.getStandardCoordinate(x, y, z, this._axes.get(1), 2)); - if (this._axes.size() >= 3) local.setZ(this.getStandardCoordinate(x, y, z, this._axes.get(2), 3)); - } + /** + * Get a local coordinate. + * @param local the coordinate. + * @param axis the standard axis to retrieve. + * @param order the default order. + * @return the coordinate. + */ + private static getLocalCoordinate(local: Coordinate, axis: Axis, order: int32): float64 { + /* Do we have an axis? */ + if (axis != null) order = axis.getOrder(); + /* Return the request coordinate */ + if (order == 1) return local.getX(); + if (order == 2) return local.getY(); + if (order == 3) return local.getZ(); + return 0.0; + } + + /** + * Convert a coordinate from the local to the standard form. + * @param local the local coordinate (input). + * @param standard the standard coordinate (can be same as local) (output). + */ + public localToStandard(local: Coordinate, standard: Coordinate): void { + /* Get X */ + let x: float64 = CoordinateSystem.getLocalCoordinate(local, this._xAxis, 1); + if (this._xUnit != null) x = this._xUnit.toStandard(x); + /* Get Y */ + let y: float64 = CoordinateSystem.getLocalCoordinate(local, this._yAxis, 2); + if (this._yUnit != null) y = this._yUnit.toStandard(y); + /* Get Z */ + let z: float64 = CoordinateSystem.getLocalCoordinate(local, this._zAxis, 3); + if (this._zUnit != null) z = this._zUnit.toStandard(z); + /* Set */ + standard.setX(x); + standard.setY(y); + standard.setZ(z); + } + + /** + * Get a standard coordinate. + * @param x the standard x coordinate. + * @param y the standard y coordinate. + * @param z the standard z coordinate. + * @param axis the local axis to consider. + * @param index the default index. + * @return the coordinate. + */ + private getStandardCoordinate(x: float64, y: float64, z: float64, axis: Axis, index: int32): float64 { + /* Check the standard index of the axis */ + if (axis == this._xAxis) index = 1; + else if (axis == this._yAxis) index = 2; + else if (axis == this._zAxis) index = 3; + /* Return the coordinate */ + if (index == 1) return x; + if (index == 2) return y; + if (index == 3) return z; + return 0.0; + } + + /** + * Convert a coordinate from the standard to the local form. + * @param standard the standard coordinate (input). + * @param local the local coordinate (can be same as standard) (output). + */ + public standardToLocal(standard: Coordinate, local: Coordinate): void { + /* Get X */ + let x: float64 = standard.getX(); + if (this._xUnit != null) x = this._xUnit.fromStandard(x); + /* Get Y */ + let y: float64 = standard.getY(); + if (this._yUnit != null) y = this._yUnit.fromStandard(y); + /* Get Z */ + let z: float64 = standard.getZ(); + if (this._zUnit != null) z = this._zUnit.fromStandard(z); + /* Set */ + local.setX(this.getStandardCoordinate(x, y, z, this._axes.get(0), 1)); + local.setY(this.getStandardCoordinate(x, y, z, this._axes.get(1), 2)); + if (this._axes.size() >= 3) local.setZ(this.getStandardCoordinate(x, y, z, this._axes.get(2), 3)); + } } diff --git a/core/orbitgt/src/spatial/ecrs/DataFileUnit.ts b/core/orbitgt/src/spatial/ecrs/DataFileUnit.ts index 7f6b911634ab..dbc6bf650476 100644 --- a/core/orbitgt/src/spatial/ecrs/DataFileUnit.ts +++ b/core/orbitgt/src/spatial/ecrs/DataFileUnit.ts @@ -6,8 +6,8 @@ * @module OrbitGT */ -//generated data file, do not edit -//package orbitgt.spatial.ecrs; +// generated data file, do not edit +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -18,93 +18,93 @@ import { AList } from "../../system/collection/AList"; /** @internal */ export class DataFileUnit { - private static DATA_LINES: AList = null; - private static addPart0(l: AList): void { - l.add("UOM_CODE UNIT_OF_MEAS_NAME UNIT_OF_MEAS_TYPE TARGET_UOM_CODE FACTOR_B FACTOR_C ABBREVIATION"); - l.add("1024 bin scale 9201 1 1 bin"); - l.add("1025 millimetre length 9001 1 1000 millimetre"); - l.add("1026 metre per second length 1026 1 1 metre per second"); - l.add("1027 millimetres per year length 1026 1 31556925445 mm/a"); - l.add("1028 parts per billion scale 9201 1 1000000000 ppb"); - l.add("1029 year time 1040 31556925.445 1 year"); - l.add("1030 parts per billion per year scale 1036 1 3.1556925445E+16 ppb/a"); - l.add("1031 milliarc-second angle 9101 3.14159265358979 648000000 msec"); - l.add("1032 milliarc-seconds per year angle 1035 3.14159265358979 2.044888768836E+16 msec/a"); - l.add("1033 centimetre length 9001 1 100 centimetre"); - l.add("1034 centimetres per year length 1026 1 3155692544.5 cm/a"); - l.add("1035 radian per second angle 1035 1 1 radian per second"); - l.add("1036 unity per second scale 1036 1 1 unity per second"); - l.add("1040 second time 1040 1 1 second"); - l.add("1041 parts per million per year scale 1036 1 31556925445000 ppm/a"); - l.add("1042 metres per year length 1026 1 31556925.445 m/a"); - l.add("1043 arc-seconds per year angle 1035 3.14159265358979 20448887688360 sec/a"); - l.add("9001 metre length 9001 1 1 metre"); - l.add("9002 foot length 9001 0.3048 1 foot"); - l.add("9003 US survey foot length 9001 12 39.37 ftUS"); - l.add("9005 Clarke's foot length 9001 0.3047972654 1 ftCla"); - l.add("9014 fathom length 9001 1.8288 1 f"); - l.add("9030 nautical mile length 9001 1852 1 NM"); - l.add("9031 German legal metre length 9001 1.0000135965 1 GLM"); - l.add("9033 US survey chain length 9001 792 39.37 chUS"); - l.add("9034 US survey link length 9001 7.92 39.37 lkUS"); - l.add("9035 US survey mile length 9001 63360 39.37 miUS"); - l.add("9036 kilometre length 9001 1000 1 kilometre"); - l.add("9037 Clarke's yard length 9001 0.9143917962 1 ydCla"); - l.add("9038 Clarke's chain length 9001 20.1166195164 1 chCla"); - l.add("9039 Clarke's link length 9001 0.201166195164 1 lkCla"); - l.add("9040 British yard (Sears 1922) length 9001 36 39.370147 ydSe"); - l.add("9041 British foot (Sears 1922) length 9001 12 39.370147 ftSe"); - l.add("9042 British chain (Sears 1922) length 9001 792 39.370147 chSe"); - l.add("9043 British link (Sears 1922) length 9001 7.92 39.370147 lkSe"); - l.add("9050 British yard (Benoit 1895 A) length 9001 0.9143992 1 ydBnA"); - l.add("9051 British foot (Benoit 1895 A) length 9001 0.9143992 3 ftBnA"); - l.add("9052 British chain (Benoit 1895 A) length 9001 20.1167824 1 chBnA"); - l.add("9053 British link (Benoit 1895 A) length 9001 0.201167824 1 lkBnA"); - l.add("9060 British yard (Benoit 1895 B) length 9001 36 39.370113 ydBnB"); - l.add("9061 British foot (Benoit 1895 B) length 9001 12 39.370113 ftBnB"); - l.add("9062 British chain (Benoit 1895 B) length 9001 792 39.370113 chBnB"); - l.add("9063 British link (Benoit 1895 B) length 9001 7.92 39.370113 lkBnB"); - l.add("9070 British foot (1865) length 9001 0.9144025 3 ftBr(65)"); - l.add("9080 Indian foot length 9001 12 39.370142 ftInd"); - l.add("9081 Indian foot (1937) length 9001 0.30479841 1 ftInd(37)"); - l.add("9082 Indian foot (1962) length 9001 0.3047996 1 ftInd(62)"); - l.add("9083 Indian foot (1975) length 9001 0.3047995 1 ftInd(75)"); - l.add("9084 Indian yard length 9001 36 39.370142 ydInd"); - l.add("9085 Indian yard (1937) length 9001 0.91439523 1 ydInd(37)"); - l.add("9086 Indian yard (1962) length 9001 0.9143988 1 ydInd(62)"); - l.add("9087 Indian yard (1975) length 9001 0.9143985 1 ydInd(75)"); - l.add("9093 Statute mile length 9001 1609.344 1 Statute mile"); - l.add("9094 Gold Coast foot length 9001 6378300 20926201 ftGC"); - l.add("9095 British foot (1936) length 9001 0.3048007491 1 ftBr(36)"); - l.add("9096 yard length 9001 0.9144 1 yard"); - l.add("9097 chain length 9001 20.1168 1 ch"); - l.add("9098 link length 9001 20.1168 100 lk"); - l.add("9099 British yard (Sears 1922 truncated) length 9001 0.914398 1 ydSe(T)"); - l.add("9101 radian angle 9101 1 1 radian"); - l.add("9102 degree angle 9101 3.14159265358979 180 deg"); - l.add("9103 arc-minute angle 9101 3.14159265358979 10800 min"); - l.add("9104 arc-second angle 9101 3.14159265358979 648000 sec"); - l.add("9105 grad angle 9101 3.14159265358979 200 gr"); - l.add("9109 microradian angle 9101 1 1000000 \u00b5rad"); - l.add("9110 sexagesimal DMS angle 9102 DDD.MMSSsss"); - l.add("9111 sexagesimal DM angle 9102 DDD.MMm"); - l.add("9112 centesimal minute angle 9101 3.14159265358979 20000 c"); - l.add("9113 centesimal second angle 9101 3.14159265358979 2000000 cc"); - l.add("9114 mil_6400 angle 9101 3.14159265358979 3200 mil_6400"); - l.add("9122 degree (supplier to define representation) angle 9101 3.14159265358979 180 deg"); - l.add("9201 unity scale 9201 1 1 unity"); - l.add("9202 parts per million scale 9201 1 1000000 parts per million"); - l.add("9203 coefficient scale 9201 1 1 coefficient"); - l.add("9300 British foot (Sears 1922 truncated) length 9001 0.914398 3 ftSe(T)"); - l.add("9301 British chain (Sears 1922 truncated) length 9001 20.116756 1 chSe(T)"); - l.add("9302 British link (Sears 1922 truncated) length 9001 20.116756 100 lkSe(T)"); - } - public static getDataLines(): AList { - if (DataFileUnit.DATA_LINES == null) { - let lines: AList = new AList(78); - DataFileUnit.addPart0(lines); - DataFileUnit.DATA_LINES = lines; - } - return DataFileUnit.DATA_LINES; + private static DATA_LINES: AList = null; + private static addPart0(l: AList): void { + l.add("UOM_CODE UNIT_OF_MEAS_NAME UNIT_OF_MEAS_TYPE TARGET_UOM_CODE FACTOR_B FACTOR_C ABBREVIATION"); + l.add("1024 bin scale 9201 1 1 bin"); + l.add("1025 millimetre length 9001 1 1000 millimetre"); + l.add("1026 metre per second length 1026 1 1 metre per second"); + l.add("1027 millimetres per year length 1026 1 31556925445 mm/a"); + l.add("1028 parts per billion scale 9201 1 1000000000 ppb"); + l.add("1029 year time 1040 31556925.445 1 year"); + l.add("1030 parts per billion per year scale 1036 1 3.1556925445E+16 ppb/a"); + l.add("1031 milliarc-second angle 9101 3.14159265358979 648000000 msec"); + l.add("1032 milliarc-seconds per year angle 1035 3.14159265358979 2.044888768836E+16 msec/a"); + l.add("1033 centimetre length 9001 1 100 centimetre"); + l.add("1034 centimetres per year length 1026 1 3155692544.5 cm/a"); + l.add("1035 radian per second angle 1035 1 1 radian per second"); + l.add("1036 unity per second scale 1036 1 1 unity per second"); + l.add("1040 second time 1040 1 1 second"); + l.add("1041 parts per million per year scale 1036 1 31556925445000 ppm/a"); + l.add("1042 metres per year length 1026 1 31556925.445 m/a"); + l.add("1043 arc-seconds per year angle 1035 3.14159265358979 20448887688360 sec/a"); + l.add("9001 metre length 9001 1 1 metre"); + l.add("9002 foot length 9001 0.3048 1 foot"); + l.add("9003 US survey foot length 9001 12 39.37 ftUS"); + l.add("9005 Clarke's foot length 9001 0.3047972654 1 ftCla"); + l.add("9014 fathom length 9001 1.8288 1 f"); + l.add("9030 nautical mile length 9001 1852 1 NM"); + l.add("9031 German legal metre length 9001 1.0000135965 1 GLM"); + l.add("9033 US survey chain length 9001 792 39.37 chUS"); + l.add("9034 US survey link length 9001 7.92 39.37 lkUS"); + l.add("9035 US survey mile length 9001 63360 39.37 miUS"); + l.add("9036 kilometre length 9001 1000 1 kilometre"); + l.add("9037 Clarke's yard length 9001 0.9143917962 1 ydCla"); + l.add("9038 Clarke's chain length 9001 20.1166195164 1 chCla"); + l.add("9039 Clarke's link length 9001 0.201166195164 1 lkCla"); + l.add("9040 British yard (Sears 1922) length 9001 36 39.370147 ydSe"); + l.add("9041 British foot (Sears 1922) length 9001 12 39.370147 ftSe"); + l.add("9042 British chain (Sears 1922) length 9001 792 39.370147 chSe"); + l.add("9043 British link (Sears 1922) length 9001 7.92 39.370147 lkSe"); + l.add("9050 British yard (Benoit 1895 A) length 9001 0.9143992 1 ydBnA"); + l.add("9051 British foot (Benoit 1895 A) length 9001 0.9143992 3 ftBnA"); + l.add("9052 British chain (Benoit 1895 A) length 9001 20.1167824 1 chBnA"); + l.add("9053 British link (Benoit 1895 A) length 9001 0.201167824 1 lkBnA"); + l.add("9060 British yard (Benoit 1895 B) length 9001 36 39.370113 ydBnB"); + l.add("9061 British foot (Benoit 1895 B) length 9001 12 39.370113 ftBnB"); + l.add("9062 British chain (Benoit 1895 B) length 9001 792 39.370113 chBnB"); + l.add("9063 British link (Benoit 1895 B) length 9001 7.92 39.370113 lkBnB"); + l.add("9070 British foot (1865) length 9001 0.9144025 3 ftBr(65)"); + l.add("9080 Indian foot length 9001 12 39.370142 ftInd"); + l.add("9081 Indian foot (1937) length 9001 0.30479841 1 ftInd(37)"); + l.add("9082 Indian foot (1962) length 9001 0.3047996 1 ftInd(62)"); + l.add("9083 Indian foot (1975) length 9001 0.3047995 1 ftInd(75)"); + l.add("9084 Indian yard length 9001 36 39.370142 ydInd"); + l.add("9085 Indian yard (1937) length 9001 0.91439523 1 ydInd(37)"); + l.add("9086 Indian yard (1962) length 9001 0.9143988 1 ydInd(62)"); + l.add("9087 Indian yard (1975) length 9001 0.9143985 1 ydInd(75)"); + l.add("9093 Statute mile length 9001 1609.344 1 Statute mile"); + l.add("9094 Gold Coast foot length 9001 6378300 20926201 ftGC"); + l.add("9095 British foot (1936) length 9001 0.3048007491 1 ftBr(36)"); + l.add("9096 yard length 9001 0.9144 1 yard"); + l.add("9097 chain length 9001 20.1168 1 ch"); + l.add("9098 link length 9001 20.1168 100 lk"); + l.add("9099 British yard (Sears 1922 truncated) length 9001 0.914398 1 ydSe(T)"); + l.add("9101 radian angle 9101 1 1 radian"); + l.add("9102 degree angle 9101 3.14159265358979 180 deg"); + l.add("9103 arc-minute angle 9101 3.14159265358979 10800 min"); + l.add("9104 arc-second angle 9101 3.14159265358979 648000 sec"); + l.add("9105 grad angle 9101 3.14159265358979 200 gr"); + l.add("9109 microradian angle 9101 1 1000000 \u00b5rad"); + l.add("9110 sexagesimal DMS angle 9102 DDD.MMSSsss"); + l.add("9111 sexagesimal DM angle 9102 DDD.MMm"); + l.add("9112 centesimal minute angle 9101 3.14159265358979 20000 c"); + l.add("9113 centesimal second angle 9101 3.14159265358979 2000000 cc"); + l.add("9114 mil_6400 angle 9101 3.14159265358979 3200 mil_6400"); + l.add("9122 degree (supplier to define representation) angle 9101 3.14159265358979 180 deg"); + l.add("9201 unity scale 9201 1 1 unity"); + l.add("9202 parts per million scale 9201 1 1000000 parts per million"); + l.add("9203 coefficient scale 9201 1 1 coefficient"); + l.add("9300 British foot (Sears 1922 truncated) length 9001 0.914398 3 ftSe(T)"); + l.add("9301 British chain (Sears 1922 truncated) length 9001 20.116756 1 chSe(T)"); + l.add("9302 British link (Sears 1922 truncated) length 9001 20.116756 100 lkSe(T)"); + } + public static getDataLines(): AList { + if (DataFileUnit.DATA_LINES == null) { + let lines: AList = new AList(78); + DataFileUnit.addPart0(lines); + DataFileUnit.DATA_LINES = lines; } + return DataFileUnit.DATA_LINES; + } } diff --git a/core/orbitgt/src/spatial/ecrs/Datum.ts b/core/orbitgt/src/spatial/ecrs/Datum.ts index f04533f44a01..78951698ccf2 100644 --- a/core/orbitgt/src/spatial/ecrs/Datum.ts +++ b/core/orbitgt/src/spatial/ecrs/Datum.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -35,163 +35,163 @@ import { PrimeMeridian } from "./PrimeMeridian"; */ /** @internal */ export class Datum { - /** The type of a geodetic datum */ - public static readonly TYPE_GEODETIC: string = "geodetic"; - /** The type of a vertical datum */ - public static readonly TYPE_VERTICAL: string = "vertical"; - - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The type */ - private _type: string; - /** The ellipsoid */ - private _ellipsoid: Ellipsoid; - /** The prime meridian */ - private _primeMeridian: PrimeMeridian; - - /** An optional preferred transformation to the WGS84 datum */ - private _toWGS84: OperationMethod; - - /** - * Create a new datum. - * @param code the code. - * @param name the name. - * @param type the type. - * @param ellipsoid the ellipsoid. - * @param primeMeridian the prime meridian. - */ - public constructor(code: int32, name: string, type: string, ellipsoid: Ellipsoid, primeMeridian: PrimeMeridian) { - /* Check the parameters */ - ASystem.assertNot(name == null, "A datum needs a name"); - ASystem.assertNot(type == null, "A datum needs a type"); - /* Store the parameters */ - this._code = code; - this._name = name; - this._type = type; - this._ellipsoid = ellipsoid; - this._primeMeridian = primeMeridian; - this._toWGS84 = null; - /* Check the parameters */ - if (this.isTypeGeodetic()) { - /* Check ellipsoid and prime meridian */ - ASystem.assertNot(ellipsoid == null, "A geodetic datum needs an ellipsoid"); - ASystem.assertNot(primeMeridian == null, "A geodetic datum needs a prime meridian"); - } - else if (this.isTypeVertical()) { - /* No ellipsoid and prime meridian */ - ASystem.assertNot(ellipsoid != null, "A vertical datum does not have an ellipsoid"); - ASystem.assertNot(primeMeridian != null, "A vertical datum does not have a prime meridian"); - } - else { - /* Invalid type */ - ASystem.assertNot(true, "Invalid datum type '" + type + "'"); - } + /** The type of a geodetic datum */ + public static readonly TYPE_GEODETIC: string = "geodetic"; + /** The type of a vertical datum */ + public static readonly TYPE_VERTICAL: string = "vertical"; + + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The type */ + private _type: string; + /** The ellipsoid */ + private _ellipsoid: Ellipsoid; + /** The prime meridian */ + private _primeMeridian: PrimeMeridian; + + /** An optional preferred transformation to the WGS84 datum */ + private _toWGS84: OperationMethod; + + /** + * Create a new datum. + * @param code the code. + * @param name the name. + * @param type the type. + * @param ellipsoid the ellipsoid. + * @param primeMeridian the prime meridian. + */ + public constructor(code: int32, name: string, type: string, ellipsoid: Ellipsoid, primeMeridian: PrimeMeridian) { + /* Check the parameters */ + ASystem.assertNot(name == null, "A datum needs a name"); + ASystem.assertNot(type == null, "A datum needs a type"); + /* Store the parameters */ + this._code = code; + this._name = name; + this._type = type; + this._ellipsoid = ellipsoid; + this._primeMeridian = primeMeridian; + this._toWGS84 = null; + /* Check the parameters */ + if (this.isTypeGeodetic()) { + /* Check ellipsoid and prime meridian */ + ASystem.assertNot(ellipsoid == null, "A geodetic datum needs an ellipsoid"); + ASystem.assertNot(primeMeridian == null, "A geodetic datum needs a prime meridian"); } - - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } - - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } - - /** - * Get the type. - * @return the type. - */ - public getType(): string { - return this._type; - } - - /** - * Is this a geodetic datum? - * @return true for a geodetic datum. - */ - public isTypeGeodetic(): boolean { - return (Strings.equalsIgnoreCase(this._type, Datum.TYPE_GEODETIC)); - } - - /** - * Is this a vertical datum? - * @return true for a vertical datum. - */ - public isTypeVertical(): boolean { - return (Strings.equalsIgnoreCase(this._type, Datum.TYPE_VERTICAL)); - } - - /** - * Get the ellipsoid. - * @return the ellipsoid. - */ - public getEllipsoid(): Ellipsoid { - return this._ellipsoid; + else if (this.isTypeVertical()) { + /* No ellipsoid and prime meridian */ + ASystem.assertNot(ellipsoid != null, "A vertical datum does not have an ellipsoid"); + ASystem.assertNot(primeMeridian != null, "A vertical datum does not have a prime meridian"); } - - /** - * Get the prime meridian. - * @return the prime meridian. - */ - public getPrimeMeridian(): PrimeMeridian { - return this._primeMeridian; - } - - /** - * Get the optional toWGS84 datum transformation. - * @return the optional toWGS84 datum transformation. - */ - public getToWGS84(): OperationMethod { - return this._toWGS84; - } - - /** - * Set the optional toWGS84 datum transformation. - * @param toWGS84 the optional toWGS84 datum transformation. - */ - public setToWGS84(toWGS84: OperationMethod): void { - this._toWGS84 = toWGS84; - } - - /** - * Check if another datum is compatible with this one. - * @param other the other datum. - * @return true if compatible. - */ - public isCompatible(other: Datum): boolean { - if (other._code == this._code) return true; - if (Strings.equalsIgnoreCase(other._type, this._type) == false) return false; - if (other._ellipsoid.isCompatible(this._ellipsoid) == false) return false; - if (other._primeMeridian.isCompatible(this._primeMeridian) == false) return false; - return true; - } - - /** - * Check if two datums are compatible. - * @param datum1 the first datum. - * @param datum2 the second datum. - * @return true if compatible. - */ - public static areCompatible(datum1: Datum, datum2: Datum): boolean { - if (datum1 == null) return (datum2 == null); - if (datum2 == null) return false; - return (datum1.isCompatible(datum2)); - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Datum:code=" + this._code + ",name='" + this._name + "',ellipsoid=" + this._ellipsoid + ",primeMeridian=" + this._primeMeridian + "]"; + else { + /* Invalid type */ + ASystem.assertNot(true, "Invalid datum type '" + type + "'"); } + } + + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } + + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } + + /** + * Get the type. + * @return the type. + */ + public getType(): string { + return this._type; + } + + /** + * Is this a geodetic datum? + * @return true for a geodetic datum. + */ + public isTypeGeodetic(): boolean { + return (Strings.equalsIgnoreCase(this._type, Datum.TYPE_GEODETIC)); + } + + /** + * Is this a vertical datum? + * @return true for a vertical datum. + */ + public isTypeVertical(): boolean { + return (Strings.equalsIgnoreCase(this._type, Datum.TYPE_VERTICAL)); + } + + /** + * Get the ellipsoid. + * @return the ellipsoid. + */ + public getEllipsoid(): Ellipsoid { + return this._ellipsoid; + } + + /** + * Get the prime meridian. + * @return the prime meridian. + */ + public getPrimeMeridian(): PrimeMeridian { + return this._primeMeridian; + } + + /** + * Get the optional toWGS84 datum transformation. + * @return the optional toWGS84 datum transformation. + */ + public getToWGS84(): OperationMethod { + return this._toWGS84; + } + + /** + * Set the optional toWGS84 datum transformation. + * @param toWGS84 the optional toWGS84 datum transformation. + */ + public setToWGS84(toWGS84: OperationMethod): void { + this._toWGS84 = toWGS84; + } + + /** + * Check if another datum is compatible with this one. + * @param other the other datum. + * @return true if compatible. + */ + public isCompatible(other: Datum): boolean { + if (other._code == this._code) return true; + if (Strings.equalsIgnoreCase(other._type, this._type) == false) return false; + if (other._ellipsoid.isCompatible(this._ellipsoid) == false) return false; + if (other._primeMeridian.isCompatible(this._primeMeridian) == false) return false; + return true; + } + + /** + * Check if two datums are compatible. + * @param datum1 the first datum. + * @param datum2 the second datum. + * @return true if compatible. + */ + public static areCompatible(datum1: Datum, datum2: Datum): boolean { + if (datum1 == null) return (datum2 == null); + if (datum2 == null) return false; + return (datum1.isCompatible(datum2)); + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Datum:code=" + this._code + ",name='" + this._name + "',ellipsoid=" + this._ellipsoid + ",primeMeridian=" + this._primeMeridian + "]"; + } } diff --git a/core/orbitgt/src/spatial/ecrs/Ellipsoid.ts b/core/orbitgt/src/spatial/ecrs/Ellipsoid.ts index 64a16ab30a42..a8c48d19ecc3 100644 --- a/core/orbitgt/src/spatial/ecrs/Ellipsoid.ts +++ b/core/orbitgt/src/spatial/ecrs/Ellipsoid.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -36,344 +36,344 @@ import { Unit } from "./Unit"; */ /** @internal */ export class Ellipsoid { - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The code of the unit of measure */ - private _unitCode: int32; - /** Semi-major axis (meter) */ - private _a: float64; - /** Semi-minor axis (meter) (derived) */ - private _b: float64; - /** Flattening (derived) */ - private _f: float64; - /** Inverse flattening */ - private _invF: float64; - /** Eccentricity (derived) */ - private _e: float64; - /** Eccentricity squared (derived) */ - private _e2: float64; + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The code of the unit of measure */ + private _unitCode: int32; + /** Semi-major axis (meter) */ + private _a: float64; + /** Semi-minor axis (meter) (derived) */ + private _b: float64; + /** Flattening (derived) */ + private _f: float64; + /** Inverse flattening */ + private _invF: float64; + /** Eccentricity (derived) */ + private _e: float64; + /** Eccentricity squared (derived) */ + private _e2: float64; - /** - * Create a new ellipsoid. - * @param code the code. - * @param name the name. - * @param unitCode the code of the unit of measure. - * @param a the semi-major axis. - * @param invF the inverse flattening (value like 300, not like 1/300). - * @param b the semi-minor axis. - */ - public constructor(code: int32, name: string, unitCode: int32, a: float64, invF: float64, b: float64) { - /* Store parameters */ - this._code = code; - this._name = name; - this._unitCode = unitCode; - this._a = (unitCode == Unit.METER) ? a : Registry.getUnit(this._unitCode).toStandard(a); - this._invF = invF; - this._b = (unitCode == Unit.METER) ? b : Registry.getUnit(this._unitCode).toStandard(b); - /* Derive parameters */ - if (this._invF == 0.0) this._invF = a / (a - b); - this._f = (1.0 / this._invF); - if (this._b == 0.0) this._b = this._a * (1.0 - this._f); - this._e = Math.sqrt(2.0 * this._f - this._f * this._f); - this._e2 = this._e * this._e; // or = (a*a-b*b)/(a*a); - } + /** + * Create a new ellipsoid. + * @param code the code. + * @param name the name. + * @param unitCode the code of the unit of measure. + * @param a the semi-major axis. + * @param invF the inverse flattening (value like 300, not like 1/300). + * @param b the semi-minor axis. + */ + public constructor(code: int32, name: string, unitCode: int32, a: float64, invF: float64, b: float64) { + /* Store parameters */ + this._code = code; + this._name = name; + this._unitCode = unitCode; + this._a = (unitCode == Unit.METER) ? a : Registry.getUnit(this._unitCode).toStandard(a); + this._invF = invF; + this._b = (unitCode == Unit.METER) ? b : Registry.getUnit(this._unitCode).toStandard(b); + /* Derive parameters */ + if (this._invF == 0.0) this._invF = a / (a - b); + this._f = 1.0 / this._invF; + if (this._b == 0.0) this._b = this._a * (1.0 - this._f); + this._e = Math.sqrt(2.0 * this._f - this._f * this._f); + this._e2 = this._e * this._e; // or = (a*a-b*b)/(a*a); + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the code of the unit of measure. - * @return the code of the unit of measure. - */ - public getUnitCode(): int32 { - return this._unitCode; - } + /** + * Get the code of the unit of measure. + * @return the code of the unit of measure. + */ + public getUnitCode(): int32 { + return this._unitCode; + } - /** - * Get the semi-major axis (in meter). - * @return the semi-major axis. - */ - public getA(): float64 { - return this._a; - } + /** + * Get the semi-major axis (in meter). + * @return the semi-major axis. + */ + public getA(): float64 { + return this._a; + } - /** - * Get the semi-minor axis (in meter). - * @return the semi-minor axis. - */ - public getB(): float64 { - return this._b; - } + /** + * Get the semi-minor axis (in meter). + * @return the semi-minor axis. + */ + public getB(): float64 { + return this._b; + } - /** - * Get the flattening. - * @return the flattening. - */ - public getF(): float64 { - return this._f; - } + /** + * Get the flattening. + * @return the flattening. + */ + public getF(): float64 { + return this._f; + } - /** - * Get the inverse flattening. - * @return the inverse flattening. - */ - public getInvF(): float64 { - return this._invF; - } + /** + * Get the inverse flattening. + * @return the inverse flattening. + */ + public getInvF(): float64 { + return this._invF; + } - /** - * Get the eccentricity. - * @return the eccentricity. - */ - public getE(): float64 { - return this._e; - } + /** + * Get the eccentricity. + * @return the eccentricity. + */ + public getE(): float64 { + return this._e; + } - /** - * Get the radius of curvature of the ellipsoid in the plane of the meridian at a given latitude (how latitude curves). - * @param lat the latitude (in radians). - * @return a radius (in meter). - */ - public getMeridianRadius(lat: float64): float64 { - // Formula: see http://en.wikipedia.org/wiki/Latitude - let t: float64 = this._e * Math.sin(lat); - return this._a * (1.0 - this._e2) / Math.pow(1.0 - t * t, 3.5); - } + /** + * Get the radius of curvature of the ellipsoid in the plane of the meridian at a given latitude (how latitude curves). + * @param lat the latitude (in radians). + * @return a radius (in meter). + */ + public getMeridianRadius(lat: float64): float64 { + // Formula: see http://en.wikipedia.org/wiki/Latitude + let t: float64 = this._e * Math.sin(lat); + return this._a * (1.0 - this._e2) / Math.pow(1.0 - t * t, 3.5); + } - /** - * Get the radius of the circle defined by all points at a certain latitude (a circle of latitude, also called a parallel) (a at latitude 0, 0 at latitude 90) (how longitude curves). - * @param lat the latitude (in radians). - * @return a radius (in meter). - */ - public getParallelRadius(lat: float64): float64 { - // Formula: see http://en.wikipedia.org/wiki/Longitude - let t: float64 = this._e * Math.sin(lat); - return this._a * Math.cos(lat) / Math.sqrt(1.0 - t * t); - } + /** + * Get the radius of the circle defined by all points at a certain latitude (a circle of latitude, also called a parallel) (a at latitude 0, 0 at latitude 90) (how longitude curves). + * @param lat the latitude (in radians). + * @return a radius (in meter). + */ + public getParallelRadius(lat: float64): float64 { + // Formula: see http://en.wikipedia.org/wiki/Longitude + let t: float64 = this._e * Math.sin(lat); + return this._a * Math.cos(lat) / Math.sqrt(1.0 - t * t); + } - /** - * Get the radius of curvature of the ellipsoid perpendicular to the meridian at a given latitude (a at latitude 0, a*a/b at latitude 90). - * @param lat the latitude (in radians). - * @return a radius (in meter). - */ - public getPrimeVerticalRadius(lat: float64): float64 { - let t: float64 = this._e * Math.sin(lat); - return this._a / Math.sqrt(1.0 - t * t); - } + /** + * Get the radius of curvature of the ellipsoid perpendicular to the meridian at a given latitude (a at latitude 0, a*a/b at latitude 90). + * @param lat the latitude (in radians). + * @return a radius (in meter). + */ + public getPrimeVerticalRadius(lat: float64): float64 { + let t: float64 = this._e * Math.sin(lat); + return this._a / Math.sqrt(1.0 - t * t); + } - /** - * Get the radius of curvature of the ellipsoid perpendicular to the meridian at a given latitude (a at latitude 0, a*a/b at latitude 90). - * @param lat the latitude (in radians). - * @param sinLat the sinus of the latitude. - * @return a radius (in meter). - */ - private getPrimeVerticalRadius2(lat: float64, sinLat: float64): float64 { - let t: float64 = this._e * sinLat; - return this._a / Math.sqrt(1.0 - t * t); - } + /** + * Get the radius of curvature of the ellipsoid perpendicular to the meridian at a given latitude (a at latitude 0, a*a/b at latitude 90). + * @param lat the latitude (in radians). + * @param sinLat the sinus of the latitude. + * @return a radius (in meter). + */ + private getPrimeVerticalRadius2(lat: float64, sinLat: float64): float64 { + let t: float64 = this._e * sinLat; + return this._a / Math.sqrt(1.0 - t * t); + } - /** - * Get the number of meter per radian of longitude. - * @param lat the latitude (in radians). - * @return the number of meter per radian. - */ - public getMeterPerRadOfLon(lat: float64): float64 { - return this.getParallelRadius(lat); - } + /** + * Get the number of meter per radian of longitude. + * @param lat the latitude (in radians). + * @return the number of meter per radian. + */ + public getMeterPerRadOfLon(lat: float64): float64 { + return this.getParallelRadius(lat); + } - /** - * Get the number of meter per degree of longitude. - * @param lat the latitude (in radians). - * @return the number of meter per degree. - */ - public getMeterPerDegreeOfLon(lat: float64): float64 { - return this.getMeterPerRadOfLon(lat) * Math.PI / 180.0; - } + /** + * Get the number of meter per degree of longitude. + * @param lat the latitude (in radians). + * @return the number of meter per degree. + */ + public getMeterPerDegreeOfLon(lat: float64): float64 { + return this.getMeterPerRadOfLon(lat) * Math.PI / 180.0; + } - /** - * Get the number of meter per radian of latitude. - * @param lat the latitude (in radians). - * @return the number of meter per radian. - */ - public getMeterPerRadOfLat(lat: float64): float64 { - return this.getMeridianRadius(lat); - } + /** + * Get the number of meter per radian of latitude. + * @param lat the latitude (in radians). + * @return the number of meter per radian. + */ + public getMeterPerRadOfLat(lat: float64): float64 { + return this.getMeridianRadius(lat); + } - /** - * Get the number of meter per degree of latitude. - * @param lat the latitude (in radians). - * @return the number of meter per degree. - */ - public getMeterPerDegreeOfLat(lat: float64): float64 { - return this.getMeterPerRadOfLat(lat) * Math.PI / 180.0; - } + /** + * Get the number of meter per degree of latitude. + * @param lat the latitude (in radians). + * @return the number of meter per degree. + */ + public getMeterPerDegreeOfLat(lat: float64): float64 { + return this.getMeterPerRadOfLat(lat) * Math.PI / 180.0; + } - /** - * Calculate the secant. - * @param v an angle (in radians). - * @return the secant. - */ - private static sec(v: float64): float64 { - return 1.0 / Math.cos(v); - } + /** + * Calculate the secant. + * @param v an angle (in radians). + * @return the secant. + */ + private static sec(v: float64): float64 { + return 1.0 / Math.cos(v); + } - /** - * Convert 3D geographic coordinates to 3D geocentric coordinates. - * See the EPSG Guidance Note, 2.2.1 - * @param geographic the geographic coordinates (lon(x) and lat(y) in radians, height(z) in meter). - * @param geocentric the new geocentric coordinates (in meter) (the result object). - */ - public toGeoCentric(geographic: Coordinate, geocentric: Coordinate): void { - /* Get the parameters */ - let lon: float64 = geographic.getX(); - let lat: float64 = geographic.getY(); - let h: float64 = geographic.getZ(); - /* Calculate */ - let sinLat: float64 = Math.sin(lat); - let v: float64 = this.getPrimeVerticalRadius2(lat, sinLat); - let s: float64 = (v + h) * Math.cos(lat); - let x: float64 = s * Math.cos(lon); - let y: float64 = s * Math.sin(lon); - let z: float64 = ((1.0 - this._e2) * v + h) * sinLat; - /* Store the new coordinates */ - geocentric.setX(x); - geocentric.setY(y); - geocentric.setZ(z); - } + /** + * Convert 3D geographic coordinates to 3D geocentric coordinates. + * See the EPSG Guidance Note, 2.2.1 + * @param geographic the geographic coordinates (lon(x) and lat(y) in radians, height(z) in meter). + * @param geocentric the new geocentric coordinates (in meter) (the result object). + */ + public toGeoCentric(geographic: Coordinate, geocentric: Coordinate): void { + /* Get the parameters */ + let lon: float64 = geographic.getX(); + let lat: float64 = geographic.getY(); + let h: float64 = geographic.getZ(); + /* Calculate */ + let sinLat: float64 = Math.sin(lat); + let v: float64 = this.getPrimeVerticalRadius2(lat, sinLat); + let s: float64 = (v + h) * Math.cos(lat); + let x: float64 = s * Math.cos(lon); + let y: float64 = s * Math.sin(lon); + let z: float64 = ((1.0 - this._e2) * v + h) * sinLat; + /* Store the new coordinates */ + geocentric.setX(x); + geocentric.setY(y); + geocentric.setZ(z); + } - /** - * Convert 3D geographic coordinates to 3D geocentric coordinates. - * See the EPSG Guidance Note, 2.2.1 - * @param geographic the geographic coordinates (lon(x) and lat(y) in degrees, height(z) in meter). - * @param geocentric the new geocentric coordinates (in meter) (the result object). - */ - public toGeoCentricDeg(geographic: Coordinate, geocentric: Coordinate): void { - /* Get the parameters */ - let lon: float64 = geographic.getX() / 180.0 * Math.PI; - let lat: float64 = geographic.getY() / 180.0 * Math.PI; - let h: float64 = geographic.getZ(); - /* Calculate */ - let sinLat: float64 = Math.sin(lat); - let v: float64 = this.getPrimeVerticalRadius2(lat, sinLat); - let s: float64 = (v + h) * Math.cos(lat); - let x: float64 = s * Math.cos(lon); - let y: float64 = s * Math.sin(lon); - let z: float64 = ((1.0 - this._e2) * v + h) * sinLat; - /* Store the new coordinates */ - geocentric.setX(x); - geocentric.setY(y); - geocentric.setZ(z); - } + /** + * Convert 3D geographic coordinates to 3D geocentric coordinates. + * See the EPSG Guidance Note, 2.2.1 + * @param geographic the geographic coordinates (lon(x) and lat(y) in degrees, height(z) in meter). + * @param geocentric the new geocentric coordinates (in meter) (the result object). + */ + public toGeoCentricDeg(geographic: Coordinate, geocentric: Coordinate): void { + /* Get the parameters */ + let lon: float64 = geographic.getX() / 180.0 * Math.PI; + let lat: float64 = geographic.getY() / 180.0 * Math.PI; + let h: float64 = geographic.getZ(); + /* Calculate */ + let sinLat: float64 = Math.sin(lat); + let v: float64 = this.getPrimeVerticalRadius2(lat, sinLat); + let s: float64 = (v + h) * Math.cos(lat); + let x: float64 = s * Math.cos(lon); + let y: float64 = s * Math.sin(lon); + let z: float64 = ((1.0 - this._e2) * v + h) * sinLat; + /* Store the new coordinates */ + geocentric.setX(x); + geocentric.setY(y); + geocentric.setZ(z); + } - /** - * Convert 3D geocentric coordinates to 3D geographic coordinates. - * See the EPSG Guidance Note, 2.2.1 - * @param geocentric the geocentric coordinates (in meter). - * @param geographic the new geographic coordinates (lon(x) and lat(y) in radians, height(z) in meter) (the result object). - */ - public toGeoGraphic(geocentric: Coordinate, geographic: Coordinate): void { - /* Get the parameters */ - let x: float64 = geocentric.getX(); - let y: float64 = geocentric.getY(); - let z: float64 = geocentric.getZ(); - /* Calculate */ - let r: float64 = Math.sqrt(x * x + y * y); - let ir: float64 = (1.0 / r); - let lat: float64 = Math.atan(z * ir); - for (let i: number = 0; i < 7; i++) { - let sinLat: float64 = Math.sin(lat); - let vi: float64 = this.getPrimeVerticalRadius2(lat, sinLat); - lat = Math.atan((z + this._e2 * vi * sinLat) * ir); - } - let lon: float64 = Math.atan2(y, x); - let v: float64 = this.getPrimeVerticalRadius(lat); - let h: float64 = x * Ellipsoid.sec(lon) * Ellipsoid.sec(lat) - v; - /* Store the new coordinates */ - geographic.setX(lon); - geographic.setY(lat); - geographic.setZ(h); - // - // loop lat error: - // - // i=0: 0.0031239393816600014 // km level - // i=1: 6.753891540589585E-6 // m level - // i=2: 1.4568768968992174E-8 // mm level - // i=3: 3.1426083957342144E-11 // um level - // i=4: 6.783462680459706E-14 // nm level - // i=5: 1.1102230246251565E-16 // atomic level - // i=6: 0.0 - // - // EPSG example for the WGS84 datum/ellipsoid: - // X = 3771793.97; - // Y = 140253.34; - // Z = 5124304.35; - // lat = 53.8093944; (degrees) - // lon = 2.12955; (degrees) - // h = 73.001873; + /** + * Convert 3D geocentric coordinates to 3D geographic coordinates. + * See the EPSG Guidance Note, 2.2.1 + * @param geocentric the geocentric coordinates (in meter). + * @param geographic the new geographic coordinates (lon(x) and lat(y) in radians, height(z) in meter) (the result object). + */ + public toGeoGraphic(geocentric: Coordinate, geographic: Coordinate): void { + /* Get the parameters */ + let x: float64 = geocentric.getX(); + let y: float64 = geocentric.getY(); + let z: float64 = geocentric.getZ(); + /* Calculate */ + let r: float64 = Math.sqrt(x * x + y * y); + let ir: float64 = 1.0 / r; + let lat: float64 = Math.atan(z * ir); + for (let i: number = 0; i < 7; i++) { + let sinLat: float64 = Math.sin(lat); + let vi: float64 = this.getPrimeVerticalRadius2(lat, sinLat); + lat = Math.atan((z + this._e2 * vi * sinLat) * ir); } + let lon: float64 = Math.atan2(y, x); + let v: float64 = this.getPrimeVerticalRadius(lat); + let h: float64 = x * Ellipsoid.sec(lon) * Ellipsoid.sec(lat) - v; + /* Store the new coordinates */ + geographic.setX(lon); + geographic.setY(lat); + geographic.setZ(h); + // + // loop lat error: + // + // i=0: 0.0031239393816600014 // km level + // i=1: 6.753891540589585E-6 // m level + // i=2: 1.4568768968992174E-8 // mm level + // i=3: 3.1426083957342144E-11 // um level + // i=4: 6.783462680459706E-14 // nm level + // i=5: 1.1102230246251565E-16 // atomic level + // i=6: 0.0 + // + // EPSG example for the WGS84 datum/ellipsoid: + // X = 3771793.97; + // Y = 140253.34; + // Z = 5124304.35; + // lat = 53.8093944; (degrees) + // lon = 2.12955; (degrees) + // h = 73.001873; + } - /** - * Convert 3D geocentric coordinates to 3D geographic coordinates. - * See the EPSG Guidance Note, 2.2.1 - * @param geocentric the geocentric coordinates (in meter). - * @param geographic the new geographic coordinates (lon(x) and lat(y) in degrees, height(z) in meter) (the result object). - */ - public toGeoGraphicDeg(geocentric: Coordinate, geographic: Coordinate): void { - /* Get the parameters */ - let x: float64 = geocentric.getX(); - let y: float64 = geocentric.getY(); - let z: float64 = geocentric.getZ(); - /* Calculate */ - let r: float64 = Math.sqrt(x * x + y * y); - let ir: float64 = (1.0 / r); - let lat: float64 = Math.atan(z * ir); - for (let i: number = 0; i < 7; i++) { - let sinLat: float64 = Math.sin(lat); - let vi: float64 = this.getPrimeVerticalRadius2(lat, sinLat); - lat = Math.atan((z + this._e2 * vi * sinLat) * ir); - } - let lon: float64 = Math.atan2(y, x); - let v: float64 = this.getPrimeVerticalRadius(lat); - let h: float64 = x * Ellipsoid.sec(lon) * Ellipsoid.sec(lat) - v; - /* Store the new coordinates */ - geographic.setX(lon / Math.PI * 180.0); - geographic.setY(lat / Math.PI * 180.0); - geographic.setZ(h); + /** + * Convert 3D geocentric coordinates to 3D geographic coordinates. + * See the EPSG Guidance Note, 2.2.1 + * @param geocentric the geocentric coordinates (in meter). + * @param geographic the new geographic coordinates (lon(x) and lat(y) in degrees, height(z) in meter) (the result object). + */ + public toGeoGraphicDeg(geocentric: Coordinate, geographic: Coordinate): void { + /* Get the parameters */ + let x: float64 = geocentric.getX(); + let y: float64 = geocentric.getY(); + let z: float64 = geocentric.getZ(); + /* Calculate */ + let r: float64 = Math.sqrt(x * x + y * y); + let ir: float64 = 1.0 / r; + let lat: float64 = Math.atan(z * ir); + for (let i: number = 0; i < 7; i++) { + let sinLat: float64 = Math.sin(lat); + let vi: float64 = this.getPrimeVerticalRadius2(lat, sinLat); + lat = Math.atan((z + this._e2 * vi * sinLat) * ir); } + let lon: float64 = Math.atan2(y, x); + let v: float64 = this.getPrimeVerticalRadius(lat); + let h: float64 = x * Ellipsoid.sec(lon) * Ellipsoid.sec(lat) - v; + /* Store the new coordinates */ + geographic.setX(lon / Math.PI * 180.0); + geographic.setY(lat / Math.PI * 180.0); + geographic.setZ(h); + } - /** - * Check if another ellipsoid is compatible with this one. - * @param other the other ellipsoid. - * @return true if compatible. - */ - public isCompatible(other: Ellipsoid): boolean { - if (other._code == this._code) return true; - if (other._unitCode != this._unitCode) return false; - if (Math.abs(other._a - this._a) > 0.001) return false; - if (Math.abs(other._b - this._b) > 0.001) return false; - return true; - } + /** + * Check if another ellipsoid is compatible with this one. + * @param other the other ellipsoid. + * @return true if compatible. + */ + public isCompatible(other: Ellipsoid): boolean { + if (other._code == this._code) return true; + if (other._unitCode != this._unitCode) return false; + if (Math.abs(other._a - this._a) > 0.001) return false; + if (Math.abs(other._b - this._b) > 0.001) return false; + return true; + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Ellipsoid:code=" + this._code + ",name='" + this._name + "']"; - } + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Ellipsoid:code=" + this._code + ",name='" + this._name + "']"; + } } diff --git a/core/orbitgt/src/spatial/ecrs/OnlineEngine.ts b/core/orbitgt/src/spatial/ecrs/OnlineEngine.ts index eea89bfe742b..f517d7d5a189 100644 --- a/core/orbitgt/src/spatial/ecrs/OnlineEngine.ts +++ b/core/orbitgt/src/spatial/ecrs/OnlineEngine.ts @@ -28,90 +28,90 @@ import { Transform } from "./Transform"; */ /** @internal */ export class OnlineEngine extends CRSEngine { - /** The optional online registry */ - private _onlineRegistry: OnlineRegistry; + /** The optional online registry */ + private _onlineRegistry: OnlineRegistry; - /** - * Create a new online engine. - * @return the new engine. - */ - public static async create(): Promise { - const engine: OnlineEngine = new OnlineEngine(); - await engine.setOnlineRegistry(OnlineRegistry.openOrbitGT()); - return engine; - } + /** + * Create a new online engine. + * @return the new engine. + */ + public static async create(): Promise { + const engine: OnlineEngine = new OnlineEngine(); + await engine.setOnlineRegistry(OnlineRegistry.openOrbitGT()); + return engine; + } - /** - * Create a new engine. - */ - private constructor() { - super(); - this._onlineRegistry = null; - } + /** + * Create a new engine. + */ + private constructor() { + super(); + this._onlineRegistry = null; + } - /** - * Set the online registry to the engine. - * @param onlineRegistry the registry to add. - */ - private async setOnlineRegistry(onlineRegistry: OnlineRegistry): Promise { - this._onlineRegistry = onlineRegistry; - await this._onlineRegistry.getCRS(4326); // WGS84, lon-lat - await this._onlineRegistry.getCRS(4978); // WGS84, geocentric - await this._onlineRegistry.getCRS(3395); // World Mercator - return this; - } + /** + * Set the online registry to the engine. + * @param onlineRegistry the registry to add. + */ + private async setOnlineRegistry(onlineRegistry: OnlineRegistry): Promise { + this._onlineRegistry = onlineRegistry; + await this._onlineRegistry.getCRS(4326); // WGS84, lon-lat + await this._onlineRegistry.getCRS(4978); // WGS84, geocentric + await this._onlineRegistry.getCRS(3395); // World Mercator + return this; + } - /** - * CRSEngine method. - */ - public override async prepareForArea(crs: string, area: Bounds): Promise { - /* Online registry? */ - if (this._onlineRegistry != null) { - /* Load the CRS */ - const areaCRS: CRS = await this._onlineRegistry.getCRS(Numbers.getInteger(crs, 0)); - } - /* Download small grid corrections for the area ... */ - /* Return the area */ - return area; + /** + * CRSEngine method. + */ + public override async prepareForArea(crs: string, area: Bounds): Promise { + /* Online registry? */ + if (this._onlineRegistry != null) { + /* Load the CRS */ + const areaCRS: CRS = await this._onlineRegistry.getCRS(Numbers.getInteger(crs, 0)); } + /* Download small grid corrections for the area ... */ + /* Return the area */ + return area; + } - /** - * CRSEngine method. - */ - public override transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { - if (Registry.getCRS2(sourceCRS) == null) - return point; - if (Registry.getCRS2(targetCRS) == null) - return point; - const targetPoint: Coordinate = Coordinate.create(); - Transform.transform(sourceCRS, point, targetCRS, targetPoint); - return targetPoint; - } + /** + * CRSEngine method. + */ + public override transformPoint(point: Coordinate, sourceCRS: string, targetCRS: string): Coordinate { + if (Registry.getCRS2(sourceCRS) == null) + return point; + if (Registry.getCRS2(targetCRS) == null) + return point; + const targetPoint: Coordinate = Coordinate.create(); + Transform.transform(sourceCRS, point, targetCRS, targetPoint); + return targetPoint; + } - /** - * CRSEngine method. - */ - public override isGeocentricCRS(crs: string): boolean { - const acrs: CRS = Registry.getCRS2(crs); - if (acrs != null) return acrs.isGeoCentric(); - return false; - } + /** + * CRSEngine method. + */ + public override isGeocentricCRS(crs: string): boolean { + const acrs: CRS = Registry.getCRS2(crs); + if (acrs != null) return acrs.isGeoCentric(); + return false; + } - /** - * CRSEngine method. - */ - public override isGeographicCRS(crs: string): boolean { - const acrs: CRS = Registry.getCRS2(crs); - if (acrs != null) return acrs.isGeoGraphic(); - return false; - } + /** + * CRSEngine method. + */ + public override isGeographicCRS(crs: string): boolean { + const acrs: CRS = Registry.getCRS2(crs); + if (acrs != null) return acrs.isGeoGraphic(); + return false; + } - /** - * CRSEngine method. - */ - public override isProjectedCRS(crs: string): boolean { - const acrs: CRS = Registry.getCRS2(crs); - if (acrs != null) return acrs.isProjected(); - return false; - } + /** + * CRSEngine method. + */ + public override isProjectedCRS(crs: string): boolean { + const acrs: CRS = Registry.getCRS2(crs); + if (acrs != null) return acrs.isProjected(); + return false; + } } diff --git a/core/orbitgt/src/spatial/ecrs/OnlineRegistry.ts b/core/orbitgt/src/spatial/ecrs/OnlineRegistry.ts index 188ccda23905..0e03ed49c902 100644 --- a/core/orbitgt/src/spatial/ecrs/OnlineRegistry.ts +++ b/core/orbitgt/src/spatial/ecrs/OnlineRegistry.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -28,56 +28,62 @@ import { WellKnownText } from "./WellKnownText"; */ /** @internal */ export class OnlineRegistry { - /** The name of this module */ - private static readonly MODULE: string = "OnlineRegistry"; + /** The name of this module */ + private static readonly MODULE: string = "OnlineRegistry"; - /** The template URL */ - private _urlTemplate: string; - /** The dialect of WKT to parse */ - private _dialect: string; + /** The template URL */ + private _urlTemplate: string; + /** The dialect of WKT to parse */ + private _dialect: string; - /** - * Open the OrbitGT online registry, see https://spatialreference.org/. - * @return the registry. - */ - public static openOrbitGT(): OnlineRegistry { - return new OnlineRegistry("https://ogtcrsregistry.blob.core.windows.net/registry/crs/[epsgCode].prj", WellKnownText.TYPE_GENERIC); - } + /** + * Open the OrbitGT online registry, see https://spatialreference.org/. + * @return the registry. + */ + public static openOrbitGT(): OnlineRegistry { + return new OnlineRegistry("https://ogtcrsregistry.blob.core.windows.net/registry/crs/[epsgCode].prj", WellKnownText.TYPE_GENERIC); + } - /** - * Create a new online registry. - * @param urlTemplate the template URL in which [epsgCode] will be replaced by the EPSG CRS code. - * @param dialect the dialect of WKT to parse. - */ - private constructor(urlTemplate: string, dialect: string) { - this._urlTemplate = urlTemplate; - this._dialect = dialect; - } + /** + * Create a new online registry. + * @param urlTemplate the template URL in which [epsgCode] will be replaced by the EPSG CRS code. + * @param dialect the dialect of WKT to parse. + */ + private constructor(urlTemplate: string, dialect: string) { + this._urlTemplate = urlTemplate; + this._dialect = dialect; + } - /** - * Get a CRS. - * @param epsgCode the EPSG code of the CRS to get. - * @return the CRS. - */ - public async getCRS(epsgCode: int32): Promise { - /* Invalid code? */ - if (epsgCode == 0) return null; - /* Already downloaded? */ - let crs: CRS = Registry.getCRS(epsgCode); - if (crs != null) return crs; - /* Download the declaration */ - Message.print(OnlineRegistry.MODULE, "Requesting online crs '" + epsgCode + "'"); - let downloadURL: string = Strings.replace(this._urlTemplate, "[epsgCode]", "" + epsgCode); - let wkt: string = await Downloader.INSTANCE.downloadText2(downloadURL); - if (wkt == null) { Message.print(OnlineRegistry.MODULE, "No WKT response"); return null; } - /* Try to parse the WKT */ - crs = WellKnownText.parseSpatialReferenceSystem(epsgCode, wkt, this._dialect); - if (crs == null) { Message.print(OnlineRegistry.MODULE, "The WKT could not be parsed"); return null; } - crs.setTextForm(wkt); - /* Keep in memory */ - Message.print(OnlineRegistry.MODULE, "Created online CRS " + crs); - Registry.setCRS(epsgCode, crs); - /* Return */ - return crs; + /** + * Get a CRS. + * @param epsgCode the EPSG code of the CRS to get. + * @return the CRS. + */ + public async getCRS(epsgCode: int32): Promise { + /* Invalid code? */ + if (epsgCode == 0) return null; + /* Already downloaded? */ + let crs: CRS = Registry.getCRS(epsgCode); + if (crs != null) return crs; + /* Download the declaration */ + Message.print(OnlineRegistry.MODULE, "Requesting online crs '" + epsgCode + "'"); + let downloadURL: string = Strings.replace(this._urlTemplate, "[epsgCode]", "" + epsgCode); + let wkt: string = await Downloader.INSTANCE.downloadText2(downloadURL); + if (wkt == null) { + Message.print(OnlineRegistry.MODULE, "No WKT response"); + return null; + } + /* Try to parse the WKT */ + crs = WellKnownText.parseSpatialReferenceSystem(epsgCode, wkt, this._dialect); + if (crs == null) { + Message.print(OnlineRegistry.MODULE, "The WKT could not be parsed"); + return null; } + crs.setTextForm(wkt); + /* Keep in memory */ + Message.print(OnlineRegistry.MODULE, "Created online CRS " + crs); + Registry.setCRS(epsgCode, crs); + /* Return */ + return crs; + } } diff --git a/core/orbitgt/src/spatial/ecrs/Operation.ts b/core/orbitgt/src/spatial/ecrs/Operation.ts index 508634c35511..49e650097487 100644 --- a/core/orbitgt/src/spatial/ecrs/Operation.ts +++ b/core/orbitgt/src/spatial/ecrs/Operation.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -34,344 +34,345 @@ import { Registry } from "./Registry"; */ /** @internal */ export class Operation { - /** The type of a concatenated operation */ - public static readonly CONCATENATED: int32 = 1; - /** The type of a conversion operation (projected to geographic) */ - public static readonly CONVERSION: int32 = 2; - /** The type of a transformation operation (geocentric to geocentric) */ - public static readonly TRANSFORMATION: int32 = 3; + /** The type of a concatenated operation */ + public static readonly CONCATENATED: int32 = 1; + /** The type of a conversion operation (projected to geographic) */ + public static readonly CONVERSION: int32 = 2; + /** The type of a transformation operation (geocentric to geocentric) */ + public static readonly TRANSFORMATION: int32 = 3; - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The type */ - private _type: int32; - /** The code of the source CRS */ - private _sourceCRScode: int32; - /** The code of the target CRS */ - private _targetCRScode: int32; - /** The area on which the operation has been defined (0 if unknown) */ - private _areaOfUse: int32; - /** The method */ - private _method: OperationMethod; + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The type */ + private _type: int32; + /** The code of the source CRS */ + private _sourceCRScode: int32; + /** The code of the target CRS */ + private _targetCRScode: int32; + /** The area on which the operation has been defined (0 if unknown) */ + private _areaOfUse: int32; + /** The method */ + private _method: OperationMethod; - /** Have we been initialised ? */ - private _initialised: boolean; - /** The source coordinate reference system */ - private _sourceCRS: CRS; - /** The target coordinate reference system */ - private _targetCRS: CRS; - /** The concatenated operations */ - private _concatenatedOperations: AList; + /** Have we been initialised ? */ + private _initialised: boolean; + /** The source coordinate reference system */ + private _sourceCRS: CRS; + /** The target coordinate reference system */ + private _targetCRS: CRS; + /** The concatenated operations */ + private _concatenatedOperations: AList; - /** - * Create a new coordinate operation. - * @param code the code. - * @param name the name. - * @param type the type (CONCATENATED, CONVERSION or TRANSFORMATION). - * @param sourceCRScode the code of the source CRS. - * @param targetCRScode the code of the target CRS. - * @param areaOfUse the area on which the operation has been defined (0 if unknown). - * @param method the method (null for concatenated operations). - */ - public constructor(code: int32, name: string, type: int32, sourceCRScode: int32, targetCRScode: int32, areaOfUse: int32, method: OperationMethod) { - /* Store the parameters */ - this._code = code; - this._name = name; - this._type = type; - this._sourceCRScode = sourceCRScode; - this._targetCRScode = targetCRScode; - this._areaOfUse = areaOfUse; - this._method = method; - /* Clear */ - this._initialised = false; - this._sourceCRS = null; - this._targetCRS = null; - this._concatenatedOperations = null; - } + /** + * Create a new coordinate operation. + * @param code the code. + * @param name the name. + * @param type the type (CONCATENATED, CONVERSION or TRANSFORMATION). + * @param sourceCRScode the code of the source CRS. + * @param targetCRScode the code of the target CRS. + * @param areaOfUse the area on which the operation has been defined (0 if unknown). + * @param method the method (null for concatenated operations). + */ + public constructor(code: int32, name: string, type: int32, sourceCRScode: int32, targetCRScode: int32, areaOfUse: int32, method: OperationMethod) { + /* Store the parameters */ + this._code = code; + this._name = name; + this._type = type; + this._sourceCRScode = sourceCRScode; + this._targetCRScode = targetCRScode; + this._areaOfUse = areaOfUse; + this._method = method; + /* Clear */ + this._initialised = false; + this._sourceCRS = null; + this._targetCRS = null; + this._concatenatedOperations = null; + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the type (CONCATENATED, CONVERSION or TRANSFORMATION). - * @return the type. - */ - public getType(): int32 { - return this._type; - } + /** + * Get the type (CONCATENATED, CONVERSION or TRANSFORMATION). + * @return the type. + */ + public getType(): int32 { + return this._type; + } - /** - * Get the code of the source CRS. - * @return the code of the source CRS. - */ - public getSourceCRScode(): int32 { - return this._sourceCRScode; - } + /** + * Get the code of the source CRS. + * @return the code of the source CRS. + */ + public getSourceCRScode(): int32 { + return this._sourceCRScode; + } - /** - * Get the code of the target CRS. - * @return the code of the target CRS. - */ - public getTargetCRScode(): int32 { - return this._targetCRScode; - } + /** + * Get the code of the target CRS. + * @return the code of the target CRS. + */ + public getTargetCRScode(): int32 { + return this._targetCRScode; + } - /** - * Get the area on which the operation has been defined. - * @return the area on which the operation has been defined (0 if unknown). - */ - public getAreaOfUse(): int32 { - return this._areaOfUse; - } + /** + * Get the area on which the operation has been defined. + * @return the area on which the operation has been defined (0 if unknown). + */ + public getAreaOfUse(): int32 { + return this._areaOfUse; + } - /** - * Get the method (null for concatenated operations). - * @return the method. - */ - public getMethod(): OperationMethod { - return this._method; - } + /** + * Get the method (null for concatenated operations). + * @return the method. + */ + public getMethod(): OperationMethod { + return this._method; + } - /** - * Set the method. - * @param method the new method (null for concatenated operations). - */ - public setMethod(method: OperationMethod): void { - this._method = method; - } + /** + * Set the method. + * @param method the new method (null for concatenated operations). + */ + public setMethod(method: OperationMethod): void { + this._method = method; + } - /** - * Get the concatenated operations. - * @return the concatenated operations (null for a method). - */ - public getConcatenatedOperations(): AList { - return this._concatenatedOperations; - } + /** + * Get the concatenated operations. + * @return the concatenated operations (null for a method). + */ + public getConcatenatedOperations(): AList { + return this._concatenatedOperations; + } - /** - * Set the concatenated operations. - * @param concatenatedOperations the concatenated operations (null for a method). - */ - public setConcatenatedOperations(concatenatedOperations: AList): void { - this._concatenatedOperations = concatenatedOperations; - } + /** + * Set the concatenated operations. + * @param concatenatedOperations the concatenated operations (null for a method). + */ + public setConcatenatedOperations(concatenatedOperations: AList): void { + this._concatenatedOperations = concatenatedOperations; + } - /** - * Initialise the operation. - */ - public initialise(): void { - /* Initialize the systems */ - if (this._sourceCRS == null) this._sourceCRS = Registry.getCRS(this._sourceCRScode); - if (this._targetCRS == null) this._targetCRS = Registry.getCRS(this._targetCRScode); - /* Already done ? */ - if (this._initialised) return; - this._initialised = true; - /* Concatenated operations ? */ - if (this._type == Operation.CONCATENATED) { - /* Create the list of operations */ - this._concatenatedOperations = new AList(); //Registry.readConcatenatedOperations(this.code); - } - else { - /* Initialise the method ? */ - this._method.initialize(this); - } + /** + * Initialise the operation. + */ + public initialise(): void { + /* Initialize the systems */ + if (this._sourceCRS == null) this._sourceCRS = Registry.getCRS(this._sourceCRScode); + if (this._targetCRS == null) this._targetCRS = Registry.getCRS(this._targetCRScode); + /* Already done ? */ + if (this._initialised) return; + this._initialised = true; + /* Concatenated operations ? */ + if (this._type == Operation.CONCATENATED) { + /* Create the list of operations */ + this._concatenatedOperations = new AList(); // Registry.readConcatenatedOperations(this.code); } - - /** - * Get the source CRS. - * @return the source CRS. - */ - public getSourceCRS(): CRS { - if (this._sourceCRS == null) this.initialise(); - return this._sourceCRS; + else { + /* Initialise the method ? */ + this._method.initialize(this); } + } - /** - * Set the source CRS. - * @param sourceCRS the source CRS. - */ - public setSourceCRS(sourceCRS: CRS): void { - this._sourceCRS = sourceCRS; - } + /** + * Get the source CRS. + * @return the source CRS. + */ + public getSourceCRS(): CRS { + if (this._sourceCRS == null) this.initialise(); + return this._sourceCRS; + } - /** - * Get the target CRS. - * @return the target CRS. - */ - public getTargetCRS(): CRS { - if (this._targetCRS == null) this.initialise(); - return this._targetCRS; - } + /** + * Set the source CRS. + * @param sourceCRS the source CRS. + */ + public setSourceCRS(sourceCRS: CRS): void { + this._sourceCRS = sourceCRS; + } - /** - * Set the target CRS. - * @param targetCRS the target CRS. - */ - public setTargetCRS(targetCRS: CRS): void { - this._targetCRS = targetCRS; - } + /** + * Get the target CRS. + * @return the target CRS. + */ + public getTargetCRS(): CRS { + if (this._targetCRS == null) this.initialise(); + return this._targetCRS; + } - /** - * Convert a source coordinate to a target coordinate. - * @param source the coordinates in the source CRS. - * @param target the coordinates in the target CRS (this is the result object). - */ - public forward(source: Coordinate, target: Coordinate): void { - this.initialise(); - /* Concatenated operations ? */ - if (this._type == Operation.CONCATENATED) { - /* Run all operations */ - for (let i: number = 0; i < this._concatenatedOperations.size(); i++) { - this._concatenatedOperations.get(i).forward(source, target); - source = target; - } - } - else { - /* Let the method do it */ - this._method.forward(this._sourceCRS, source, this._targetCRS, target); - } - } + /** + * Set the target CRS. + * @param targetCRS the target CRS. + */ + public setTargetCRS(targetCRS: CRS): void { + this._targetCRS = targetCRS; + } - /** - * Convert a target coordinate to a source coordinate. - * @param source the coordinates in the source CRS (this is the result object). - * @param target the coordinates in the target CRS. - */ - public reverse(source: Coordinate, target: Coordinate): void { - this.initialise(); - /* Concatenated operations ? */ - if (this._type == Operation.CONCATENATED) { - /* Run all operations */ - for (let i: number = 0; i < this._concatenatedOperations.size(); i++) { - this._concatenatedOperations.get(this._concatenatedOperations.size() - 1 - i).reverse(source, target); - target = source; - } - } - else { - /* Let the method do it */ - this._method.reverse(this._sourceCRS, source, this._targetCRS, target); - } + /** + * Convert a source coordinate to a target coordinate. + * @param source the coordinates in the source CRS. + * @param target the coordinates in the target CRS (this is the result object). + */ + public forward(source: Coordinate, target: Coordinate): void { + this.initialise(); + /* Concatenated operations ? */ + if (this._type == Operation.CONCATENATED) { + /* Run all operations */ + for (let i: number = 0; i < this._concatenatedOperations.size(); i++) { + this._concatenatedOperations.get(i).forward(source, target); + source = target; + } } - - /** - * Check if another operation is compatible with this one. - * @param other the other operation. - * @return true if compatible. - */ - public isCompatible(other: Operation): boolean { - if (other._code == this._code) return true; // all operations should have unique identifiers - if (other._type != this._type) return false; - if (other._sourceCRScode != this._sourceCRScode) return false; - if (other._targetCRScode != this._targetCRScode) return false; - if (other._method.isCompatible(this._method) == false) return false; - if (Operation.areCompatibleOperations(other._concatenatedOperations, this._concatenatedOperations) == false) return false; - return true; + else { + /* Let the method do it */ + this._method.forward(this._sourceCRS, source, this._targetCRS, target); } + } - /** - * Check if two operations are compatible. - * @param operation1 the first operation. - * @param operation2 the second operation. - * @return true if compatible. - */ - public static isCompatibleOperation(operation1: Operation, operation2: Operation): boolean { - if (operation1 == null) return (operation2 == null); - if (operation2 == null) return false; - return (operation1.isCompatible(operation2)); + /** + * Convert a target coordinate to a source coordinate. + * @param source the coordinates in the source CRS (this is the result object). + * @param target the coordinates in the target CRS. + */ + public reverse(source: Coordinate, target: Coordinate): void { + this.initialise(); + /* Concatenated operations ? */ + if (this._type == Operation.CONCATENATED) { + /* Run all operations */ + for (let i: number = 0; i < this._concatenatedOperations.size(); i++) { + this._concatenatedOperations.get(this._concatenatedOperations.size() - 1 - i).reverse(source, target); + target = source; + } } - - /** - * Check if a list of operations is compatible with another one. - * @param list1 the first list. - * @param list2 the second list. - * @return true if compatible. - */ - private static areCompatibleOperations(list1: AList, list2: AList): boolean { - if (list1 == null) return (list2 == null); - if (list2 == null) return false; - if (list2.size() != list1.size()) return false; - for (let i: number = 0; i < list2.size(); i++) if (list2.get(i).isCompatible(list1.get(i)) == false) return false; - return true; + else { + /* Let the method do it */ + this._method.reverse(this._sourceCRS, source, this._targetCRS, target); } + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Operation:code=" + this._code + ",name='" + this._name + "',type=" + this._type + ",sourceCRS=" + this._sourceCRScode + ",targetCRS=" + this._targetCRScode + ",area=" + this._areaOfUse + ",method=" + this._method + "]"; - } + /** + * Check if another operation is compatible with this one. + * @param other the other operation. + * @return true if compatible. + */ + public isCompatible(other: Operation): boolean { + if (other._code == this._code) return true; // all operations should have unique identifiers + if (other._type != this._type) return false; + if (other._sourceCRScode != this._sourceCRScode) return false; + if (other._targetCRScode != this._targetCRScode) return false; + if (other._method.isCompatible(this._method) == false) return false; + if (Operation.areCompatibleOperations(other._concatenatedOperations, this._concatenatedOperations) == false) return false; + return true; + } - /** - * Find an operation by name. - * @param operations the list of operations. - * @param name the name of the operation. - * @return the index of the operation. - */ - public static findByName(operations: Array, name: string): int32 { - /* No list ? */ - if (operations == null) return -1; - /* Check */ - for (let i: number = 0; i < operations.length; i++) if (Strings.equalsIgnoreCase(operations[i].getName(), name)) return i; - /* Not found */ - return -1; - } + /** + * Check if two operations are compatible. + * @param operation1 the first operation. + * @param operation2 the second operation. + * @return true if compatible. + */ + public static isCompatibleOperation(operation1: Operation, operation2: Operation): boolean { + if (operation1 == null) return (operation2 == null); + if (operation2 == null) return false; + return (operation1.isCompatible(operation2)); + } - /** - * Get the version of a transformation. - * @param transformationName the name of the transformation. - * @return the version (0 if not found). - */ - private static getTransformationVersion(transformationName: string): int32 { - /* Find the (...) sequence */ - let index0: int32 = Strings.lastIndexOf(transformationName, "("); - if (index0 < 0) return 0; - let index1: int32 = Strings.lastIndexOf(transformationName, ")"); - if ((index1 < 0) || (index1 < index0)) return 0; - /* Parse the version */ - let version: string = Strings.substring(transformationName, index0 + 1, index1); - return Numbers.getInteger(version, 0); - } + /** + * Check if a list of operations is compatible with another one. + * @param list1 the first list. + * @param list2 the second list. + * @return true if compatible. + */ + private static areCompatibleOperations(list1: AList, list2: AList): boolean { + if (list1 == null) return (list2 == null); + if (list2 == null) return false; + if (list2.size() != list1.size()) return false; + for (let i: number = 0; i < list2.size(); i++) if (list2.get(i).isCompatible(list1.get(i)) == false) return false; + return true; + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Operation:code=" + this._code + ",name='" + this._name + "',type=" + this._type + ",sourceCRS=" + this._sourceCRScode + ",targetCRS=" + + this._targetCRScode + ",area=" + this._areaOfUse + ",method=" + this._method + "]"; + } + + /** + * Find an operation by name. + * @param operations the list of operations. + * @param name the name of the operation. + * @return the index of the operation. + */ + public static findByName(operations: Array, name: string): int32 { + /* No list ? */ + if (operations == null) return -1; + /* Check */ + for (let i: number = 0; i < operations.length; i++) if (Strings.equalsIgnoreCase(operations[i].getName(), name)) return i; + /* Not found */ + return -1; + } + + /** + * Get the version of a transformation. + * @param transformationName the name of the transformation. + * @return the version (0 if not found). + */ + private static getTransformationVersion(transformationName: string): int32 { + /* Find the (...) sequence */ + let index0: int32 = Strings.lastIndexOf(transformationName, "("); + if (index0 < 0) return 0; + let index1: int32 = Strings.lastIndexOf(transformationName, ")"); + if ((index1 < 0) || (index1 < index0)) return 0; + /* Parse the version */ + let version: string = Strings.substring(transformationName, index0 + 1, index1); + return Numbers.getInteger(version, 0); + } - /** - * Get the latest transform from a set of transformations. - * @param transformations the set of transformations. - * @return the latest transform. - */ - public static getLatestTransformation(transformations: AList): Operation { - /* We need at least two transforms */ - if (transformations == null) return null; - if (transformations.size() == 0) return null; - if (transformations.size() == 1) return transformations.get(0); - /* Start with the first transform */ - let bestIndex: int32 = 0; - let bestVersion: int32 = Operation.getTransformationVersion(transformations.get(bestIndex).getName()); - /* Check for better versions */ - for (let i: number = 1; i < transformations.size(); i++) { - /* Check */ - let version: int32 = Operation.getTransformationVersion(transformations.get(i).getName()); - if (version > bestVersion) { - /* This one is later */ - bestIndex = i; - bestVersion = version; - } - } - /* Return the best transform */ - return transformations.get(bestIndex); + /** + * Get the latest transform from a set of transformations. + * @param transformations the set of transformations. + * @return the latest transform. + */ + public static getLatestTransformation(transformations: AList): Operation { + /* We need at least two transforms */ + if (transformations == null) return null; + if (transformations.size() == 0) return null; + if (transformations.size() == 1) return transformations.get(0); + /* Start with the first transform */ + let bestIndex: int32 = 0; + let bestVersion: int32 = Operation.getTransformationVersion(transformations.get(bestIndex).getName()); + /* Check for better versions */ + for (let i: number = 1; i < transformations.size(); i++) { + /* Check */ + let version: int32 = Operation.getTransformationVersion(transformations.get(i).getName()); + if (version > bestVersion) { + /* This one is later */ + bestIndex = i; + bestVersion = version; + } } + /* Return the best transform */ + return transformations.get(bestIndex); + } } diff --git a/core/orbitgt/src/spatial/ecrs/OperationMethod.ts b/core/orbitgt/src/spatial/ecrs/OperationMethod.ts index bab1029eb587..f19becd477eb 100644 --- a/core/orbitgt/src/spatial/ecrs/OperationMethod.ts +++ b/core/orbitgt/src/spatial/ecrs/OperationMethod.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -27,85 +27,85 @@ import { ParameterValueList } from "./ParameterValueList"; */ /** @internal */ export abstract class OperationMethod { - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The parameter list */ - private _parameters: ParameterValueList; + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The parameter list */ + private _parameters: ParameterValueList; - /** - * Create a new method. - * @param code the code. - * @param name the name. - */ - public constructor(code: int32, name: string, parameters: ParameterValueList) { - this._code = code; - this._name = name; - this._parameters = parameters; - } + /** + * Create a new method. + * @param code the code. + * @param name the name. + */ + public constructor(code: int32, name: string, parameters: ParameterValueList) { + this._code = code; + this._name = name; + this._parameters = parameters; + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the parameter list. - * @return the parameter list. - */ - public getParameterList(): ParameterValueList { - return this._parameters; - } + /** + * Get the parameter list. + * @return the parameter list. + */ + public getParameterList(): ParameterValueList { + return this._parameters; + } - /** - * Check if another method is compatible with this one. - * @param other the other method. - * @return true if compatible. - */ - public isCompatible(other: OperationMethod): boolean { - // if (other.getClass()!=this.getClass()) return false; - if (Strings.equals(other.getName(), this.getName()) == false) return false; - if (other._parameters == null) return false; - if (this._parameters == null) return false; - if (other._parameters.isCompatible(this._parameters) == false) return false; - return true; - } + /** + * Check if another method is compatible with this one. + * @param other the other method. + * @return true if compatible. + */ + public isCompatible(other: OperationMethod): boolean { + // if (other.getClass()!=this.getClass()) return false; + if (Strings.equals(other.getName(), this.getName()) == false) return false; + if (other._parameters == null) return false; + if (this._parameters == null) return false; + if (other._parameters.isCompatible(this._parameters) == false) return false; + return true; + } - /** - * Initialize the method before making forward and reverse transforms. - * @param operation the operation that is using this method. - */ - public initialize(operation: Operation): void { - /* Override when necessary */ - } + /** + * Initialize the method before making forward and reverse transforms. + * @param operation the operation that is using this method. + */ + public initialize(operation: Operation): void { + /* Override when necessary */ + } - /** - * Convert a source coordinate to a target coordinate. - * @param sourceCRS the source CRS. - * @param source the coordinates in the source CRS. - * @param targetCRS the target CRS. - * @param target the coordinates in the target CRS. - */ - public abstract forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void; + /** + * Convert a source coordinate to a target coordinate. + * @param sourceCRS the source CRS. + * @param source the coordinates in the source CRS. + * @param targetCRS the target CRS. + * @param target the coordinates in the target CRS. + */ + public abstract forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void; - /** - * Convert a target coordinate to a source coordinate. - * @param sourceCRS the source CRS. - * @param source the coordinates in the source CRS. - * @param targetCRS the target CRS. - * @param target the coordinates in the target CRS. - */ - public abstract reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void; + /** + * Convert a target coordinate to a source coordinate. + * @param sourceCRS the source CRS. + * @param source the coordinates in the source CRS. + * @param targetCRS the target CRS. + * @param target the coordinates in the target CRS. + */ + public abstract reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void; } diff --git a/core/orbitgt/src/spatial/ecrs/ParameterValue.ts b/core/orbitgt/src/spatial/ecrs/ParameterValue.ts index abbe0e9c921c..6804f541f0bf 100644 --- a/core/orbitgt/src/spatial/ecrs/ParameterValue.ts +++ b/core/orbitgt/src/spatial/ecrs/ParameterValue.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -23,58 +23,58 @@ import { Unit } from "./Unit"; */ /** @internal */ export class ParameterValue { - /** The identification code of the parameter */ - private _parameterCode: int32; - /** The value of the parameter */ - private _parameterValue: float64; - /** The unit of measure */ - private _unit: Unit; + /** The identification code of the parameter */ + private _parameterCode: int32; + /** The value of the parameter */ + private _parameterValue: float64; + /** The unit of measure */ + private _unit: Unit; - /** - * Create a new value. - * @param parameterCode the identification code of the parameter. - * @param parameterValue the value of the parameter. - * @param unit the unit of measure. - */ - public constructor(parameterCode: int32, parameterValue: float64, unit: Unit) { - this._parameterCode = parameterCode; - this._parameterValue = parameterValue; - this._unit = unit; - } + /** + * Create a new value. + * @param parameterCode the identification code of the parameter. + * @param parameterValue the value of the parameter. + * @param unit the unit of measure. + */ + public constructor(parameterCode: int32, parameterValue: float64, unit: Unit) { + this._parameterCode = parameterCode; + this._parameterValue = parameterValue; + this._unit = unit; + } - /** - * Get the identification code of the parameter. - * @return the code. - */ - public getParameterCode(): int32 { - return this._parameterCode; - } + /** + * Get the identification code of the parameter. + * @return the code. + */ + public getParameterCode(): int32 { + return this._parameterCode; + } - /** - * Get the value of the parameter. - * @return the value. - */ - public getParameterValue(): float64 { - return this._parameterValue; - } + /** + * Get the value of the parameter. + * @return the value. + */ + public getParameterValue(): float64 { + return this._parameterValue; + } - /** - * Get the unit of measure. - * @return the unit. - */ - public getUnit(): Unit { - return this._unit; - } + /** + * Get the unit of measure. + * @return the unit. + */ + public getUnit(): Unit { + return this._unit; + } - /** - * Check if another parameter value is compatible with this one. - * @param other the other parameter value. - * @return true if compatible. - */ - public isCompatible(other: ParameterValue): boolean { - if (other._parameterCode != this._parameterCode) return false; - if (other._parameterValue != this._parameterValue) return false; - if (other._unit.isCompatible(this._unit) == false) return false; - return true; - } + /** + * Check if another parameter value is compatible with this one. + * @param other the other parameter value. + * @return true if compatible. + */ + public isCompatible(other: ParameterValue): boolean { + if (other._parameterCode != this._parameterCode) return false; + if (other._parameterValue != this._parameterValue) return false; + if (other._unit.isCompatible(this._unit) == false) return false; + return true; + } } diff --git a/core/orbitgt/src/spatial/ecrs/ParameterValueList.ts b/core/orbitgt/src/spatial/ecrs/ParameterValueList.ts index d2454ea598d4..e418efd26297 100644 --- a/core/orbitgt/src/spatial/ecrs/ParameterValueList.ts +++ b/core/orbitgt/src/spatial/ecrs/ParameterValueList.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -24,108 +24,108 @@ import { ParameterValue } from "./ParameterValue"; */ /** @internal */ export class ParameterValueList { - /** The list */ - private _list: AList; + /** The list */ + private _list: AList; - /** - * Create a new list. - */ - public constructor() { - this._list = new AList(); - } + /** + * Create a new list. + */ + public constructor() { + this._list = new AList(); + } - /** - * Get the number of parameter values. - * @return the number of parameter values. - */ - public size(): int32 { - return this._list.size(); - } + /** + * Get the number of parameter values. + * @return the number of parameter values. + */ + public size(): int32 { + return this._list.size(); + } - /** - * Get a certain parameter value. - * @param index the index of the parameter value. - * @return the requested parameter value. - */ - public get(index: int32): ParameterValue { - return this._list.get(index); - } + /** + * Get a certain parameter value. + * @param index the index of the parameter value. + * @return the requested parameter value. + */ + public get(index: int32): ParameterValue { + return this._list.get(index); + } - /** - * Add a parameter value. - * @param value the parameter value to add. - */ - public add(value: ParameterValue): void { - this._list.add(value); - } + /** + * Add a parameter value. + * @param value the parameter value to add. + */ + public add(value: ParameterValue): void { + this._list.add(value); + } - /** - * Remove a parameter value. - * @param value the parameter value to remove. - * @return true if the value was removed, false if not. - */ - public remove(value: ParameterValue): boolean { - let index: int32 = this._list.indexOf(value); - if (index < 0) return false; - this._list.remove(index); - return true; - } + /** + * Remove a parameter value. + * @param value the parameter value to remove. + * @return true if the value was removed, false if not. + */ + public remove(value: ParameterValue): boolean { + let index: int32 = this._list.indexOf(value); + if (index < 0) return false; + this._list.remove(index); + return true; + } - /** - * Clear the parameter list. - */ - public clear(): void { - this._list.clear(); - } + /** + * Clear the parameter list. + */ + public clear(): void { + this._list.clear(); + } - /** - * Find a parameter. - * @param parameterCode the identification code of the parameter. - * @return a parameter value (null if not found). - */ - public find(parameterCode: int32): ParameterValue { - /* Check all values */ - for (let i: number = 0; i < this._list.size(); i++) { - /* Check the next value */ - let value: ParameterValue = this._list.get(i); - if (value.getParameterCode() == parameterCode) return value; - } - /* Parameter not found */ - return null; + /** + * Find a parameter. + * @param parameterCode the identification code of the parameter. + * @return a parameter value (null if not found). + */ + public find(parameterCode: int32): ParameterValue { + /* Check all values */ + for (let i: number = 0; i < this._list.size(); i++) { + /* Check the next value */ + let value: ParameterValue = this._list.get(i); + if (value.getParameterCode() == parameterCode) return value; } + /* Parameter not found */ + return null; + } - /** - * Get the value of a parameter. - * @param parameterCode the identification code of the parameter. - * @return the (standard) value of the parameter. - */ - public getValue(parameterCode: int32): float64 { - let value: ParameterValue = this.find(parameterCode); - if (value.getUnit() == null) return value.getParameterValue(); - return value.getUnit().toStandard(value.getParameterValue()); - } + /** + * Get the value of a parameter. + * @param parameterCode the identification code of the parameter. + * @return the (standard) value of the parameter. + */ + public getValue(parameterCode: int32): float64 { + let value: ParameterValue = this.find(parameterCode); + if (value.getUnit() == null) return value.getParameterValue(); + return value.getUnit().toStandard(value.getParameterValue()); + } - /** - * Get the value of a parameter. - * @param parameterCode the identification code of the parameter. - * @param defaultValue the default value in case the parameter is not found. - * @return the (standard) value of the parameter. - */ - public getValue2(parameterCode: int32, defaultValue: float64): float64 { - let value: ParameterValue = this.find(parameterCode); - if (value == null) return defaultValue; - if (value.getUnit() == null) return value.getParameterValue(); - return value.getUnit().toStandard(value.getParameterValue()); - } + /** + * Get the value of a parameter. + * @param parameterCode the identification code of the parameter. + * @param defaultValue the default value in case the parameter is not found. + * @return the (standard) value of the parameter. + */ + public getValue2(parameterCode: int32, defaultValue: float64): float64 { + let value: ParameterValue = this.find(parameterCode); + if (value == null) return defaultValue; + if (value.getUnit() == null) return value.getParameterValue(); + return value.getUnit().toStandard(value.getParameterValue()); + } - /** - * Check if another parameter value list is compatible with this one. - * @param other the other parameter value list (same parameter value sequence is assumed). - * @return true if compatible. - */ - public isCompatible(other: ParameterValueList): boolean { - if (other.size() != this.size()) return false; - for (let i: number = 0; i < this.size(); i++) if (other.get(i).isCompatible(this.get(i)) == false) return false; - return true; - } + /** + * Check if another parameter value list is compatible with this one. + * @param other the other parameter value list (same parameter value sequence is assumed). + * @return true if compatible. + */ + public isCompatible(other: ParameterValueList): boolean { + if (other.size() != this.size()) return false; + for (let i: number = 0; i < this.size(); i++) if (other.get(i).isCompatible(this.get(i)) == false) return false; + return true; + } } diff --git a/core/orbitgt/src/spatial/ecrs/PrimeMeridian.ts b/core/orbitgt/src/spatial/ecrs/PrimeMeridian.ts index dab976c83f0a..08b358e97488 100644 --- a/core/orbitgt/src/spatial/ecrs/PrimeMeridian.ts +++ b/core/orbitgt/src/spatial/ecrs/PrimeMeridian.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -31,97 +31,97 @@ import { Unit } from "./Unit"; */ /** @internal */ export class PrimeMeridian { - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The longitude from Greenwich */ - private _lonFromGreenwich: float64; - /** The code of the unit of longitude */ - private _unitCode: int32; + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The longitude from Greenwich */ + private _lonFromGreenwich: float64; + /** The code of the unit of longitude */ + private _unitCode: int32; - /** - * Create a new prime meridian. - * @param code the code. - * @param name the name. - * @param lonFromGreenwich the longitude from Greenwich. - * @param unitCode the code of the unit of longitude. - */ - public constructor(code: int32, name: string, lonFromGreenwich: float64, unitCode: int32) { - /* Store parameters */ - this._code = code; - this._name = name; - this._lonFromGreenwich = lonFromGreenwich; - this._unitCode = unitCode; - } + /** + * Create a new prime meridian. + * @param code the code. + * @param name the name. + * @param lonFromGreenwich the longitude from Greenwich. + * @param unitCode the code of the unit of longitude. + */ + public constructor(code: int32, name: string, lonFromGreenwich: float64, unitCode: int32) { + /* Store parameters */ + this._code = code; + this._name = name; + this._lonFromGreenwich = lonFromGreenwich; + this._unitCode = unitCode; + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the longitude from Greenwich. - * @return the longitude from Greenwich. - */ - public getLonFromGreenwich(): float64 { - return this._lonFromGreenwich; - } + /** + * Get the longitude from Greenwich. + * @return the longitude from Greenwich. + */ + public getLonFromGreenwich(): float64 { + return this._lonFromGreenwich; + } - /** - * Get the longitude from Greenwich in radians. - * @return the longitude from Greenwich in radians. - */ - public getLonFromGreenwichRad(): float64 { - let unit: Unit = Registry.getUnit(this._unitCode); - return unit.toStandard(this._lonFromGreenwich); - } + /** + * Get the longitude from Greenwich in radians. + * @return the longitude from Greenwich in radians. + */ + public getLonFromGreenwichRad(): float64 { + let unit: Unit = Registry.getUnit(this._unitCode); + return unit.toStandard(this._lonFromGreenwich); + } - /** - * Get the longitude from Greenwich in degrees. - * @return the longitude from Greenwich in degrees. - */ - public getLonFromGreenwichDeg(): float64 { - if (this._unitCode == Unit.DEGREE) return this._lonFromGreenwich; - return this.getLonFromGreenwichRad() / Math.PI * 180.0; - } + /** + * Get the longitude from Greenwich in degrees. + * @return the longitude from Greenwich in degrees. + */ + public getLonFromGreenwichDeg(): float64 { + if (this._unitCode == Unit.DEGREE) return this._lonFromGreenwich; + return this.getLonFromGreenwichRad() / Math.PI * 180.0; + } - /** - * Get the code of the unit of longitude. - * @return the code of the unit of longitude. - */ - public getUnitCode(): int32 { - return this._unitCode; - } + /** + * Get the code of the unit of longitude. + * @return the code of the unit of longitude. + */ + public getUnitCode(): int32 { + return this._unitCode; + } - /** - * Check if another prime meridian is compatible with this one. - * @param other the other prime meridian. - * @return true if compatible. - */ - public isCompatible(other: PrimeMeridian): boolean { - if (other._code == this._code) return true; - if (other._unitCode != this._unitCode) return false; - if (other._lonFromGreenwich != this._lonFromGreenwich) return false; - return true; - } + /** + * Check if another prime meridian is compatible with this one. + * @param other the other prime meridian. + * @return true if compatible. + */ + public isCompatible(other: PrimeMeridian): boolean { + if (other._code == this._code) return true; + if (other._unitCode != this._unitCode) return false; + if (other._lonFromGreenwich != this._lonFromGreenwich) return false; + return true; + } - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[PrimeMeridian:code=" + this._code + ",name='" + this._name + "']"; - } + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[PrimeMeridian:code=" + this._code + ",name='" + this._name + "']"; + } } diff --git a/core/orbitgt/src/spatial/ecrs/Registry.ts b/core/orbitgt/src/spatial/ecrs/Registry.ts index 5ada161c1fbc..4bf5ec1d4751 100644 --- a/core/orbitgt/src/spatial/ecrs/Registry.ts +++ b/core/orbitgt/src/spatial/ecrs/Registry.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -31,183 +31,183 @@ import { Unit } from "./Unit"; */ /** @internal */ export class Registry { - /** The name of the unit table */ - private static readonly _TABLE_UNIT: string = "unit"; - - // Unit columns: UOM_CODE UNIT_OF_MEAS_NAME UNIT_OF_MEAS_TYPE TARGET_UOM_CODE FACTOR_B FACTOR_C ABBREVIATION - private static readonly _COL_COUNT_UNIT: int32 = 7; - private static readonly _COL_UNIT_CODE: int32 = 0; - private static readonly _COL_UNIT_NAME: int32 = 1; - private static readonly _COL_UNIT_TYPE: int32 = 2; - private static readonly _COL_UNIT_TARGET_CODE: int32 = 3; - private static readonly _COL_UNIT_FACTOR_B: int32 = 4; - private static readonly _COL_UNIT_FACTOR_C: int32 = 5; - private static readonly _COL_UNIT_ABBREVIATION: int32 = 6; - - /** The map for preferred transformation between CRSs */ - private static _PREFERRED_TRANSFORMATIONS: StringMap = new StringMap(); - /** Define the list of all units */ - private static _UNIT_LIST: AList = null; - /** Define the map of CRS instances that have been read */ - private static _CRS_MAP: StringMap = new StringMap(); - - /** - * No instances. - */ - private constructor() { } - - /** - * Get the UTM CRS code at a certain location. - * @param lon the WGS84 (CRS 4326) longitude (degrees). - * @param lat the WGS84 (CRS 4326) latitude (degrees). - * @return the CRS code. - */ - public static getUTMCRSCodeAt(lon: float64, lat: float64): int32 { - /* Normalize longitude */ - while (lon < -180.0) lon += 360.0; - while (lon > 180.0) lon -= 360.0; - /* Get the zone identifier */ - let zoneId: int32 = Math.round((lon + 183.0) / 6.0); - if (zoneId < 1) zoneId = 1; - if (zoneId > 60) zoneId = 60; - /* Get the CRS code */ - return (lat >= 0.0) ? (32600 + zoneId) : (32700 + zoneId); - } - - /** - * Get a preferred transformation (to WGS84). - * @param crs the crs. - * @return the preferred transformation (can be null). - */ - public static getPreferredTransformation(crs: string): Operation { - return Registry._PREFERRED_TRANSFORMATIONS.get(crs); - } - - /** - * Set a preferred transformation (to WGS84). - * @param crs the crs. - * @param transformation the preferred transformation (can be null). - */ - public static setPreferredTransformation(crs: string, transformation: Operation): void { - Registry._PREFERRED_TRANSFORMATIONS.put(crs, transformation); - } - - /** - * Open a table. - * @param tableName the name of the table. - * @return the table. - */ - private static openTable(tableName: string): AList { - if (Strings.equals(tableName, Registry._TABLE_UNIT)) return DataFileUnit.getDataLines(); - return new AList(); - } - - /** - * Read all units. - * @return all units. - */ - private static readAllUnits(): AList { - /* Make the list */ - let units: AList = new AList(); - /* Open the table */ - let tableReader: AList = Registry.openTable(Registry._TABLE_UNIT); - let headerLine: string = tableReader.get(0); - /* Process the table */ - for (let i: number = 1; i < tableReader.size(); i++) { - /* Read the next line */ - let line: string = tableReader.get(i); - /* Get the columns */ - let parts: AList = Strings.splitAsList(line, Strings.TAB); - if (parts.size() != Registry._COL_COUNT_UNIT) continue; - /* Get the parameters */ - let code: int32 = Numbers.getInteger(parts.get(Registry._COL_UNIT_CODE), 0); - let name: string = parts.get(Registry._COL_UNIT_NAME); - let type: string = parts.get(Registry._COL_UNIT_TYPE); - let targetUnitCode: int32 = Numbers.getInteger(parts.get(Registry._COL_UNIT_TARGET_CODE), 0); - let b: float64 = Numbers.getDouble(parts.get(Registry._COL_UNIT_FACTOR_B), 0.0); - let c: float64 = Numbers.getDouble(parts.get(Registry._COL_UNIT_FACTOR_C), 0.0); - let abbreviation: string = parts.get(Registry._COL_UNIT_ABBREVIATION); - /* Add a new unit */ - let unit: Unit = new Unit(code, name, abbreviation, type, targetUnitCode, b, c); - units.add(unit); - } - /* Return the units */ - return units; - } - - /** - * List all units. - * @return all units. - */ - public static listUnits(): AList { - if (Registry._UNIT_LIST == null) Registry._UNIT_LIST = Registry.readAllUnits(); - return Registry._UNIT_LIST; - } - - /** - * Find a unit. - * @param unitCode the identification code of the unit. - * @return a unit (null if not found). - */ - public static findUnit(unitCode: int32): Unit { - let unitList: AList = Registry.listUnits(); - for (let unit of unitList) if (unit.getCode() == unitCode) return unit; - return null; - } - - /** - * Get a unit. - * @param unitCode the identification code of the unit. - * @return a unit (not null). - */ - public static getUnit(unitCode: int32): Unit { - let unit: Unit = Registry.findUnit(unitCode); - ASystem.assertNot(unit == null, "Unit '" + unitCode + "' not found"); - return unit; - } - - /** - * Find a unit by name. - * @param unitName the name (or abbreviation or code) of the unit. - * @return a unit (null if not found). - */ - public static findUnitName(unitName: string): Unit { - if (unitName == null) return null; - let unitList: AList = Registry.listUnits(); - for (let unit of unitList) if (Strings.equalsIgnoreCase(unitName, unit.getName())) return unit; - for (let unit of unitList) if (Strings.equalsIgnoreCase(unitName, unit.getAbbreviation())) return unit; - for (let unit of unitList) if (Strings.equals(unitName, "" + unit.getCode())) return unit; - return null; - } - - /** - * Get a CRS. - * @param crsCode the identification code of the CRS. - * @return the CRS (null if not found). - */ - public static getCRS(crsCode: int32): CRS { - return Registry._CRS_MAP.get("" + crsCode); - } - - /** - * Get a CRS. - * @param crsCode the identification code of the CRS. - * @return the CRS (null if not found). - */ - public static getCRS2(crsCode: string): CRS { - return Registry._CRS_MAP.get(crsCode); - } - - /** - * Set a CRS. - * @param crsCode the identification code of the CRS. - * @param the CRS. - */ - public static setCRS(crsCode: int32, crs: CRS): void { - /* Register the CRS */ - Registry._CRS_MAP.set("" + crsCode, crs); - /* Register the base CRS as well */ - let baseCRS: CRS = crs.getBaseCRS(); - if (baseCRS != null) Registry.setCRS(baseCRS.getCode(), baseCRS); + /** The name of the unit table */ + private static readonly _TABLE_UNIT: string = "unit"; + + // Unit columns: UOM_CODE UNIT_OF_MEAS_NAME UNIT_OF_MEAS_TYPE TARGET_UOM_CODE FACTOR_B FACTOR_C ABBREVIATION + private static readonly _COL_COUNT_UNIT: int32 = 7; + private static readonly _COL_UNIT_CODE: int32 = 0; + private static readonly _COL_UNIT_NAME: int32 = 1; + private static readonly _COL_UNIT_TYPE: int32 = 2; + private static readonly _COL_UNIT_TARGET_CODE: int32 = 3; + private static readonly _COL_UNIT_FACTOR_B: int32 = 4; + private static readonly _COL_UNIT_FACTOR_C: int32 = 5; + private static readonly _COL_UNIT_ABBREVIATION: int32 = 6; + + /** The map for preferred transformation between CRSs */ + private static _PREFERRED_TRANSFORMATIONS: StringMap = new StringMap(); + /** Define the list of all units */ + private static _UNIT_LIST: AList = null; + /** Define the map of CRS instances that have been read */ + private static _CRS_MAP: StringMap = new StringMap(); + + /** + * No instances. + */ + private constructor() {} + + /** + * Get the UTM CRS code at a certain location. + * @param lon the WGS84 (CRS 4326) longitude (degrees). + * @param lat the WGS84 (CRS 4326) latitude (degrees). + * @return the CRS code. + */ + public static getUTMCRSCodeAt(lon: float64, lat: float64): int32 { + /* Normalize longitude */ + while (lon < -180.0) lon += 360.0; + while (lon > 180.0) lon -= 360.0; + /* Get the zone identifier */ + let zoneId: int32 = Math.round((lon + 183.0) / 6.0); + if (zoneId < 1) zoneId = 1; + if (zoneId > 60) zoneId = 60; + /* Get the CRS code */ + return (lat >= 0.0) ? (32600 + zoneId) : (32700 + zoneId); + } + + /** + * Get a preferred transformation (to WGS84). + * @param crs the crs. + * @return the preferred transformation (can be null). + */ + public static getPreferredTransformation(crs: string): Operation { + return Registry._PREFERRED_TRANSFORMATIONS.get(crs); + } + + /** + * Set a preferred transformation (to WGS84). + * @param crs the crs. + * @param transformation the preferred transformation (can be null). + */ + public static setPreferredTransformation(crs: string, transformation: Operation): void { + Registry._PREFERRED_TRANSFORMATIONS.put(crs, transformation); + } + + /** + * Open a table. + * @param tableName the name of the table. + * @return the table. + */ + private static openTable(tableName: string): AList { + if (Strings.equals(tableName, Registry._TABLE_UNIT)) return DataFileUnit.getDataLines(); + return new AList(); + } + + /** + * Read all units. + * @return all units. + */ + private static readAllUnits(): AList { + /* Make the list */ + let units: AList = new AList(); + /* Open the table */ + let tableReader: AList = Registry.openTable(Registry._TABLE_UNIT); + let headerLine: string = tableReader.get(0); + /* Process the table */ + for (let i: number = 1; i < tableReader.size(); i++) { + /* Read the next line */ + let line: string = tableReader.get(i); + /* Get the columns */ + let parts: AList = Strings.splitAsList(line, Strings.TAB); + if (parts.size() != Registry._COL_COUNT_UNIT) continue; + /* Get the parameters */ + let code: int32 = Numbers.getInteger(parts.get(Registry._COL_UNIT_CODE), 0); + let name: string = parts.get(Registry._COL_UNIT_NAME); + let type: string = parts.get(Registry._COL_UNIT_TYPE); + let targetUnitCode: int32 = Numbers.getInteger(parts.get(Registry._COL_UNIT_TARGET_CODE), 0); + let b: float64 = Numbers.getDouble(parts.get(Registry._COL_UNIT_FACTOR_B), 0.0); + let c: float64 = Numbers.getDouble(parts.get(Registry._COL_UNIT_FACTOR_C), 0.0); + let abbreviation: string = parts.get(Registry._COL_UNIT_ABBREVIATION); + /* Add a new unit */ + let unit: Unit = new Unit(code, name, abbreviation, type, targetUnitCode, b, c); + units.add(unit); } + /* Return the units */ + return units; + } + + /** + * List all units. + * @return all units. + */ + public static listUnits(): AList { + if (Registry._UNIT_LIST == null) Registry._UNIT_LIST = Registry.readAllUnits(); + return Registry._UNIT_LIST; + } + + /** + * Find a unit. + * @param unitCode the identification code of the unit. + * @return a unit (null if not found). + */ + public static findUnit(unitCode: int32): Unit { + let unitList: AList = Registry.listUnits(); + for (let unit of unitList) if (unit.getCode() == unitCode) return unit; + return null; + } + + /** + * Get a unit. + * @param unitCode the identification code of the unit. + * @return a unit (not null). + */ + public static getUnit(unitCode: int32): Unit { + let unit: Unit = Registry.findUnit(unitCode); + ASystem.assertNot(unit == null, "Unit '" + unitCode + "' not found"); + return unit; + } + + /** + * Find a unit by name. + * @param unitName the name (or abbreviation or code) of the unit. + * @return a unit (null if not found). + */ + public static findUnitName(unitName: string): Unit { + if (unitName == null) return null; + let unitList: AList = Registry.listUnits(); + for (let unit of unitList) if (Strings.equalsIgnoreCase(unitName, unit.getName())) return unit; + for (let unit of unitList) if (Strings.equalsIgnoreCase(unitName, unit.getAbbreviation())) return unit; + for (let unit of unitList) if (Strings.equals(unitName, "" + unit.getCode())) return unit; + return null; + } + + /** + * Get a CRS. + * @param crsCode the identification code of the CRS. + * @return the CRS (null if not found). + */ + public static getCRS(crsCode: int32): CRS { + return Registry._CRS_MAP.get("" + crsCode); + } + + /** + * Get a CRS. + * @param crsCode the identification code of the CRS. + * @return the CRS (null if not found). + */ + public static getCRS2(crsCode: string): CRS { + return Registry._CRS_MAP.get(crsCode); + } + + /** + * Set a CRS. + * @param crsCode the identification code of the CRS. + * @param the CRS. + */ + public static setCRS(crsCode: int32, crs: CRS): void { + /* Register the CRS */ + Registry._CRS_MAP.set("" + crsCode, crs); + /* Register the base CRS as well */ + let baseCRS: CRS = crs.getBaseCRS(); + if (baseCRS != null) Registry.setCRS(baseCRS.getCode(), baseCRS); + } } diff --git a/core/orbitgt/src/spatial/ecrs/Transform.ts b/core/orbitgt/src/spatial/ecrs/Transform.ts index 4e4b46736e7e..795495058db4 100644 --- a/core/orbitgt/src/spatial/ecrs/Transform.ts +++ b/core/orbitgt/src/spatial/ecrs/Transform.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -28,366 +28,366 @@ import { VerticalModel } from "./VerticalModel"; */ /** @internal */ export class Transform { - /** The name of this module */ - private static readonly MODULE: string = "Transform"; + /** The name of this module */ + private static readonly MODULE: string = "Transform"; - /** Define the different paths a CRS transformation can take */ - private static readonly _SAME_CRS: int32 = 1; - private static readonly _FORWARD_PROJECTION: int32 = 2; - private static readonly _INVERSE_PROJECTION: int32 = 3; - private static readonly _TWO_PROJECTIONS: int32 = 4; - private static readonly _TO_WGS: int32 = 6; - private static readonly _FROM_WGS: int32 = 7; - private static readonly _FULL_TRANSFORM: int32 = 8; - private static readonly _VERTICAL: int32 = 9; + /** Define the different paths a CRS transformation can take */ + private static readonly _SAME_CRS: int32 = 1; + private static readonly _FORWARD_PROJECTION: int32 = 2; + private static readonly _INVERSE_PROJECTION: int32 = 3; + private static readonly _TWO_PROJECTIONS: int32 = 4; + private static readonly _TO_WGS: int32 = 6; + private static readonly _FROM_WGS: int32 = 7; + private static readonly _FULL_TRANSFORM: int32 = 8; + private static readonly _VERTICAL: int32 = 9; - /** - * Prevent instantiation. - */ - private constructor() { } + /** + * Prevent instantiation. + */ + private constructor() {} - /** - * Is a conversion between two coordinate systems possible/needed? - * @param sourceCRS the name/code of the source reference system. - * @param targetCRS the name/code of the target reference system. - * @return true if a conversion is possible/needed. - */ - public static canTransform(sourceCRS: string, targetCRS: string): boolean { - /* We need two CRSs */ - if (sourceCRS == null || Strings.getLength(sourceCRS) == 0) return false; - if (targetCRS == null || Strings.getLength(targetCRS) == 0) return false; - /* Same CRS ? */ - if (Strings.equalsIgnoreCase(targetCRS, sourceCRS)) return true; - /* Get the two CRSs */ - let source: CRS = Registry.getCRS2(sourceCRS); - let target: CRS = Registry.getCRS2(targetCRS); - /* We need two CRSs */ - if (source == null) return false; - if (target == null) return false; - /* Vertical transform ? */ - if (source.hasVerticalComponent() || target.hasVerticalComponent()) { - /* Get the horizontal components */ - let sourceHor: CRS = (source.hasVerticalComponent()) ? source.getHorizontalComponent() : source; - let targetHor: CRS = (target.hasVerticalComponent()) ? target.getHorizontalComponent() : target; - /* Check transform in the horizontal CRS */ - return Transform.canTransform("" + sourceHor.getCode(), "" + targetHor.getCode()); - } - /* Same datum ? */ - if (source.getDatum().isCompatible(target.getDatum())) return true; - /* Chained transform ? */ - if ((source.getCode() != CRS.WGS84_2D_CRS_CODE) && (target.getCode() != CRS.WGS84_2D_CRS_CODE)) { - /* Use WGS as in-between */ - if (source.isWGSCompatible() == false) return false; - if (target.isWGSCompatible() == false) return false; - /* Possible */ - return true; - } - /* To WGS ? */ - if (target.getCode() == CRS.WGS84_2D_CRS_CODE) { - /* Use WGS */ - if (source.isWGSCompatible() == false) return false; - /* Possible */ - return true; - } - /* From WGS ? */ - if (source.getCode() == CRS.WGS84_2D_CRS_CODE) { - /* Use WGS */ - if (target.isWGSCompatible() == false) return false; - /* Possible */ - return true; - } - /* Not possible */ - return false; + /** + * Is a conversion between two coordinate systems possible/needed? + * @param sourceCRS the name/code of the source reference system. + * @param targetCRS the name/code of the target reference system. + * @return true if a conversion is possible/needed. + */ + public static canTransform(sourceCRS: string, targetCRS: string): boolean { + /* We need two CRSs */ + if (sourceCRS == null || Strings.getLength(sourceCRS) == 0) return false; + if (targetCRS == null || Strings.getLength(targetCRS) == 0) return false; + /* Same CRS ? */ + if (Strings.equalsIgnoreCase(targetCRS, sourceCRS)) return true; + /* Get the two CRSs */ + let source: CRS = Registry.getCRS2(sourceCRS); + let target: CRS = Registry.getCRS2(targetCRS); + /* We need two CRSs */ + if (source == null) return false; + if (target == null) return false; + /* Vertical transform ? */ + if (source.hasVerticalComponent() || target.hasVerticalComponent()) { + /* Get the horizontal components */ + let sourceHor: CRS = (source.hasVerticalComponent()) ? source.getHorizontalComponent() : source; + let targetHor: CRS = (target.hasVerticalComponent()) ? target.getHorizontalComponent() : target; + /* Check transform in the horizontal CRS */ + return Transform.canTransform("" + sourceHor.getCode(), "" + targetHor.getCode()); } - - /** - * Do a vertical transform. - * @param horizontalCRS the horizontal CRS. - * @param fromVerticalCRS the vertical CRS to convert from. - * @param from the coordinate to convert from. - * @param toVerticalCRS the vertical CRS to convert to. - * @param to the coordinate to convert to. - */ - public static transformVertical(horizontalCRS: CRS, fromVerticalCRS: CRS, from: Coordinate, toVerticalCRS: CRS, to: Coordinate): void { - /* 1: From 'ellipsoid' to 'ellipsoid' height ? */ - if ((fromVerticalCRS == null) && (toVerticalCRS == null)) { - /* Straight copy */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(from.getZ()); - //Message.print(MODULE,"_VERTICAL: ellipsoid->ellipsoid: "+from.getZ()); - } - /* 2: From 'ellipsoid' to 'local' height ? */ - else if ((fromVerticalCRS == null) && (toVerticalCRS != null)) { - /* Get the geoid separation */ - let geoidModel: VerticalModel = toVerticalCRS.getVerticalModel(); - let toZ: float64 = from.getZ(); - if (geoidModel != null) toZ = geoidModel.toLocalHeight(horizontalCRS, from); - else Message.printWarning(Transform.MODULE, "Target vertical CRS " + toVerticalCRS + " does not have a height model"); - //Message.print(MODULE,"_VERTICAL: ellipsoid->local: "+from.getZ()+"->"+toZ); - /* Substract the separation */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(toZ); - } - /* 3: From 'local' to 'ellipsoid' height ? */ - else if ((fromVerticalCRS != null) && (toVerticalCRS == null)) { - /* Get the geoid separation */ - let geoidModel: VerticalModel = fromVerticalCRS.getVerticalModel(); - let toZ: float64 = from.getZ(); - if (geoidModel != null) toZ = geoidModel.toEllipsoidHeight(horizontalCRS, from); - else Message.printWarning(Transform.MODULE, "Source vertical CRS " + fromVerticalCRS + " does not have a height model"); - //Message.print(MODULE,"_VERTICAL: local->ellipsoid: "+from.getZ()+"->"+toZ); - /* Add the separation */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(toZ); - } - /* 4: From 'local1' to 'local2' */ - else { - /* Same ? */ - if (fromVerticalCRS.getCode() == toVerticalCRS.getCode()) { - /* Straight copy */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(from.getZ()); - //Message.print(MODULE,"_VERTICAL: local->local same: "+from.getZ()); - } - else { - /* Get the 'from' ellipsoid height */ - let fromGeoidModel: VerticalModel = fromVerticalCRS.getVerticalModel(); - let fromZ: float64 = from.getZ(); - if (fromGeoidModel != null) fromZ = fromGeoidModel.toEllipsoidHeight(horizontalCRS, from); - else Message.printWarning(Transform.MODULE, "Source vertical CRS " + fromVerticalCRS + " does not have a height model"); - /* Copy */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(fromZ); - /* Get the 'to' local height */ - let toGeoidModel: VerticalModel = toVerticalCRS.getVerticalModel(); - let toZ: float64 = to.getZ(); - if (toGeoidModel != null) toZ = toGeoidModel.toLocalHeight(horizontalCRS, to); - else Message.printWarning(Transform.MODULE, "Target vertical CRS " + toVerticalCRS + " does not have a height model"); - //Message.print(MODULE,"_VERTICAL: local->local: "+from.getZ()+"->"+fromZ+"->"+toZ); - /* Copy */ - to.setZ(toZ); - } - } + /* Same datum ? */ + if (source.getDatum().isCompatible(target.getDatum())) return true; + /* Chained transform ? */ + if ((source.getCode() != CRS.WGS84_2D_CRS_CODE) && (target.getCode() != CRS.WGS84_2D_CRS_CODE)) { + /* Use WGS as in-between */ + if (source.isWGSCompatible() == false) return false; + if (target.isWGSCompatible() == false) return false; + /* Possible */ + return true; + } + /* To WGS ? */ + if (target.getCode() == CRS.WGS84_2D_CRS_CODE) { + /* Use WGS */ + if (source.isWGSCompatible() == false) return false; + /* Possible */ + return true; + } + /* From WGS ? */ + if (source.getCode() == CRS.WGS84_2D_CRS_CODE) { + /* Use WGS */ + if (target.isWGSCompatible() == false) return false; + /* Possible */ + return true; } + /* Not possible */ + return false; + } - /** - * Get the transformation path from one CRS to another CRS. - * @param sourceCRS the source reference system. - * @param targetCRS the target reference system. - * @return the transformation path. - */ - public static getTransformPath(sourceCRS: CRS, targetCRS: CRS): int32 { - /* Same CRS ? */ - if (targetCRS.getCode() == sourceCRS.getCode()) { - return Transform._SAME_CRS; - } - /* Compatible CRS ? */ - if (targetCRS.isCompatible(sourceCRS)) { - return Transform._SAME_CRS; - } - /* Vertical transform ? */ - if (sourceCRS.hasVerticalComponent() || targetCRS.hasVerticalComponent()) { - return Transform._VERTICAL; - } - /* Same datum/ellipsoid ? (added on 24/11/2011) */ - if (sourceCRS.getDatum().isCompatible(targetCRS.getDatum())) { - /* Is the target a projection of the source ? (added on 05/12/2011) */ - if (targetCRS.isProjectionOf(sourceCRS)) { - return Transform._FORWARD_PROJECTION; - } - /* Is the source a projection of the target ? (added on 05/12/2011) */ - if (sourceCRS.isProjectionOf(targetCRS)) { - return Transform._INVERSE_PROJECTION; - } - /* Two projections of the same base? */ - if (sourceCRS.isProjected() && targetCRS.isProjected() && (targetCRS.getBaseCRS().isCompatible(sourceCRS.getBaseCRS()))) { - return Transform._TWO_PROJECTIONS; - } - } - /* To WGS ? */ - if (targetCRS.getCode() == CRS.WGS84_2D_CRS_CODE) { - return Transform._TO_WGS; - } - /* From WGS ? */ - if (sourceCRS.getCode() == CRS.WGS84_2D_CRS_CODE) { - return Transform._FROM_WGS; - } - /* Use WGS as in-between (slowest path) */ - return Transform._FULL_TRANSFORM; + /** + * Do a vertical transform. + * @param horizontalCRS the horizontal CRS. + * @param fromVerticalCRS the vertical CRS to convert from. + * @param from the coordinate to convert from. + * @param toVerticalCRS the vertical CRS to convert to. + * @param to the coordinate to convert to. + */ + public static transformVertical(horizontalCRS: CRS, fromVerticalCRS: CRS, from: Coordinate, toVerticalCRS: CRS, to: Coordinate): void { + /* 1: From 'ellipsoid' to 'ellipsoid' height ? */ + if ((fromVerticalCRS == null) && (toVerticalCRS == null)) { + /* Straight copy */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(from.getZ()); + // Message.print(MODULE,"_VERTICAL: ellipsoid->ellipsoid: "+from.getZ()); + } + /* 2: From 'ellipsoid' to 'local' height ? */ + else if ((fromVerticalCRS == null) && (toVerticalCRS != null)) { + /* Get the geoid separation */ + let geoidModel: VerticalModel = toVerticalCRS.getVerticalModel(); + let toZ: float64 = from.getZ(); + if (geoidModel != null) toZ = geoidModel.toLocalHeight(horizontalCRS, from); + else Message.printWarning(Transform.MODULE, "Target vertical CRS " + toVerticalCRS + " does not have a height model"); + // Message.print(MODULE,"_VERTICAL: ellipsoid->local: "+from.getZ()+"->"+toZ); + /* Substract the separation */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(toZ); + } + /* 3: From 'local' to 'ellipsoid' height ? */ + else if ((fromVerticalCRS != null) && (toVerticalCRS == null)) { + /* Get the geoid separation */ + let geoidModel: VerticalModel = fromVerticalCRS.getVerticalModel(); + let toZ: float64 = from.getZ(); + if (geoidModel != null) toZ = geoidModel.toEllipsoidHeight(horizontalCRS, from); + else Message.printWarning(Transform.MODULE, "Source vertical CRS " + fromVerticalCRS + " does not have a height model"); + // Message.print(MODULE,"_VERTICAL: local->ellipsoid: "+from.getZ()+"->"+toZ); + /* Add the separation */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(toZ); } + /* 4: From 'local1' to 'local2' */ + else { + /* Same ? */ + if (fromVerticalCRS.getCode() == toVerticalCRS.getCode()) { + /* Straight copy */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(from.getZ()); + // Message.print(MODULE,"_VERTICAL: local->local same: "+from.getZ()); + } + else { + /* Get the 'from' ellipsoid height */ + let fromGeoidModel: VerticalModel = fromVerticalCRS.getVerticalModel(); + let fromZ: float64 = from.getZ(); + if (fromGeoidModel != null) fromZ = fromGeoidModel.toEllipsoidHeight(horizontalCRS, from); + else Message.printWarning(Transform.MODULE, "Source vertical CRS " + fromVerticalCRS + " does not have a height model"); + /* Copy */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(fromZ); + /* Get the 'to' local height */ + let toGeoidModel: VerticalModel = toVerticalCRS.getVerticalModel(); + let toZ: float64 = to.getZ(); + if (toGeoidModel != null) toZ = toGeoidModel.toLocalHeight(horizontalCRS, to); + else Message.printWarning(Transform.MODULE, "Target vertical CRS " + toVerticalCRS + " does not have a height model"); + // Message.print(MODULE,"_VERTICAL: local->local: "+from.getZ()+"->"+fromZ+"->"+toZ); + /* Copy */ + to.setZ(toZ); + } + } + } - /** - * Convert between two coordinate reference systems. - * @param sourceCRS the source reference system. - * @param from the coordinate to convert from. - * @param targetCRS the target reference system. - * @param to the coordinate to convert to. - */ - public static transformWithPath(path: int32, sourceCRS: CRS, from: Coordinate, targetCRS: CRS, to: Coordinate): void { - //Message.print(MODULE,"---------->>>"); - //Message.print(MODULE,"TRANSFORM: sourceCRS = "+sourceCRS.getCode()); - //Message.print(MODULE,"TRANSFORM: targetCRS = "+targetCRS.getCode()); - //Message.print(MODULE,"TRANSFORM: from = "+from); - //Message.print(MODULE,"TRANSFORM: path = "+path); - /* Same CRS ? */ - if (path == Transform._SAME_CRS) { - //Message.print(MODULE,"TRANSFORM: _SAME_CRS"); - /* Straight copy */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(from.getZ()); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* Is the target a projection of the source ? (added on 05/12/2011) */ - if (path == Transform._FORWARD_PROJECTION) { - //Message.print(MODULE,"TRANSFORM: _FORWARD_PROJECTION"); - /* Apply the projection */ - targetCRS.toProjected(from, to); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* Is the source a projection of the target ? (added on 05/12/2011) */ - if (path == Transform._INVERSE_PROJECTION) { - //Message.print(MODULE,"TRANSFORM: _INVERSE_PROJECTION"); - /* Reverse the projection */ - sourceCRS.fromProjected(from, to); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* Two projections of the same base? */ - if (path == Transform._TWO_PROJECTIONS) { - //Message.print(MODULE,"TRANSFORM: _TWO_PROJECTIONS"); - /* Reverse the projection */ - sourceCRS.fromProjected(from, to); - /* Apply the projection */ - targetCRS.toProjected(to, to); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* To WGS ? */ - if (path == Transform._TO_WGS) { - //Message.print(MODULE,"TRANSFORM: _TO_WGS"); - /* Use WGS */ - let toWGS: Coordinate = sourceCRS.toWGS(from); - /* Set the target */ - to.setX(toWGS.getX()); - to.setY(toWGS.getY()); - to.setZ(toWGS.getZ()); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* From WGS ? */ - if (path == Transform._FROM_WGS) { - //Message.print(MODULE,"TRANSFORM: _FROM_WGS"); - /* Use WGS */ - let fromWGS: Coordinate = targetCRS.fromWGS(from); - /* Set the target */ - to.setX(fromWGS.getX()); - to.setY(fromWGS.getY()); - to.setZ(fromWGS.getZ()); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* Full transform ? */ - if (path == Transform._FULL_TRANSFORM) { - //Message.print(MODULE,"TRANSFORM: _FULL_TRANSFORM"); - /* Use WGS as in-between */ - let toWGS: Coordinate = sourceCRS.toWGS(from); - let fromWGS: Coordinate = targetCRS.fromWGS(toWGS); - /* Set the target */ - to.setX(fromWGS.getX()); - to.setY(fromWGS.getY()); - to.setZ(fromWGS.getZ()); - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - /* Vertical transform ? */ - if (path == Transform._VERTICAL) { - //Message.print(MODULE,"TRANSFORM: _VERTICAL"); - /* Get the horizontal components */ - let sourceHorCRS: CRS = (sourceCRS.hasVerticalComponent()) ? sourceCRS.getHorizontalComponent() : sourceCRS; - let targetHorCRS: CRS = (targetCRS.hasVerticalComponent()) ? targetCRS.getHorizontalComponent() : targetCRS; - /* Get the vertical components */ - let sourceVerCRS: CRS = (sourceCRS.hasVerticalComponent()) ? sourceCRS.getVerticalComponent() : null; - let targetVerCRS: CRS = (targetCRS.hasVerticalComponent()) ? targetCRS.getVerticalComponent() : null; - /* Put the source coordinate in the ellipsoid height */ - if (sourceVerCRS != null) { - /* Move to the default 'ellipsoid' height */ - //Message.print(MODULE,"TRANSFORM: source to ellipsoidZ"); - Transform.transformVertical(sourceHorCRS, sourceVerCRS, from, null, to); - from = to; - //Message.print(MODULE,"TRANSFORM: source ellipsoidZ = "+to); - } - /* Get the ellipsoid height */ - let ellipsoidZ: float64 = from.getZ(); - if (sourceHorCRS.isGeoCentric()) { - /* Calculate the ellipsoid height */ - let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); - sourceHorCRS.getEllipsoid().toGeoGraphic(from, geographic); - ellipsoidZ = geographic.getZ(); - } - /* Transform in the horizontal CRS (keep the WGS Z (and not the Bessel Z) for transform from WGS to RD-NAP) */ - //Message.print(MODULE,"TRANSFORM: ellipsoidZ = "+ellipsoidZ); - //Message.print(MODULE,"TRANSFORM: horizontal "+sourceHorCRS.getCode()+" -> "+targetHorCRS.getCode()); - Transform.transformCRS(sourceHorCRS, from, targetHorCRS, to); - /* Is the target CRS horizontal? */ - if (targetHorCRS.isGeoCentric() == false) { - /* Keep the ellipsoid height after the horizontal transform */ - to.setZ(ellipsoidZ); - } - from = to; - //Message.print(MODULE,"TRANSFORM: intermediate = "+from); - /* Put the target coordinate in the vertical CRS */ - if (targetVerCRS != null) { - /* Move from the default 'ellipsoid' height */ - Transform.transformVertical(targetHorCRS, null, from, targetVerCRS, to); - from = to; - //Message.print(MODULE,"TRANSFORM: target vtransf = "+to); - } - /* Done */ - //Message.print(MODULE,"TRANSFORMED: to = "+to); - return; - } - //Message.print(MODULE,"TRANSFORMED: UNKNOWN!"); + /** + * Get the transformation path from one CRS to another CRS. + * @param sourceCRS the source reference system. + * @param targetCRS the target reference system. + * @return the transformation path. + */ + public static getTransformPath(sourceCRS: CRS, targetCRS: CRS): int32 { + /* Same CRS ? */ + if (targetCRS.getCode() == sourceCRS.getCode()) { + return Transform._SAME_CRS; + } + /* Compatible CRS ? */ + if (targetCRS.isCompatible(sourceCRS)) { + return Transform._SAME_CRS; + } + /* Vertical transform ? */ + if (sourceCRS.hasVerticalComponent() || targetCRS.hasVerticalComponent()) { + return Transform._VERTICAL; + } + /* Same datum/ellipsoid ? (added on 24/11/2011) */ + if (sourceCRS.getDatum().isCompatible(targetCRS.getDatum())) { + /* Is the target a projection of the source ? (added on 05/12/2011) */ + if (targetCRS.isProjectionOf(sourceCRS)) { + return Transform._FORWARD_PROJECTION; + } + /* Is the source a projection of the target ? (added on 05/12/2011) */ + if (sourceCRS.isProjectionOf(targetCRS)) { + return Transform._INVERSE_PROJECTION; + } + /* Two projections of the same base? */ + if (sourceCRS.isProjected() && targetCRS.isProjected() && (targetCRS.getBaseCRS().isCompatible(sourceCRS.getBaseCRS()))) { + return Transform._TWO_PROJECTIONS; + } + } + /* To WGS ? */ + if (targetCRS.getCode() == CRS.WGS84_2D_CRS_CODE) { + return Transform._TO_WGS; } + /* From WGS ? */ + if (sourceCRS.getCode() == CRS.WGS84_2D_CRS_CODE) { + return Transform._FROM_WGS; + } + /* Use WGS as in-between (slowest path) */ + return Transform._FULL_TRANSFORM; + } - /** - * Convert between two coordinate reference systems. - * @param sourceCRS the source reference system. - * @param from the coordinate to convert from. - * @param targetCRS the target reference system. - * @param to the coordinate to convert to. - */ - public static transformCRS(sourceCRS: CRS, from: Coordinate, targetCRS: CRS, to: Coordinate): void { - Transform.transformWithPath(Transform.getTransformPath(sourceCRS, targetCRS), sourceCRS, from, targetCRS, to); + /** + * Convert between two coordinate reference systems. + * @param sourceCRS the source reference system. + * @param from the coordinate to convert from. + * @param targetCRS the target reference system. + * @param to the coordinate to convert to. + */ + public static transformWithPath(path: int32, sourceCRS: CRS, from: Coordinate, targetCRS: CRS, to: Coordinate): void { + // Message.print(MODULE,"---------->>>"); + // Message.print(MODULE,"TRANSFORM: sourceCRS = "+sourceCRS.getCode()); + // Message.print(MODULE,"TRANSFORM: targetCRS = "+targetCRS.getCode()); + // Message.print(MODULE,"TRANSFORM: from = "+from); + // Message.print(MODULE,"TRANSFORM: path = "+path); + /* Same CRS ? */ + if (path == Transform._SAME_CRS) { + // Message.print(MODULE,"TRANSFORM: _SAME_CRS"); + /* Straight copy */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(from.getZ()); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* Is the target a projection of the source ? (added on 05/12/2011) */ + if (path == Transform._FORWARD_PROJECTION) { + // Message.print(MODULE,"TRANSFORM: _FORWARD_PROJECTION"); + /* Apply the projection */ + targetCRS.toProjected(from, to); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* Is the source a projection of the target ? (added on 05/12/2011) */ + if (path == Transform._INVERSE_PROJECTION) { + // Message.print(MODULE,"TRANSFORM: _INVERSE_PROJECTION"); + /* Reverse the projection */ + sourceCRS.fromProjected(from, to); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* Two projections of the same base? */ + if (path == Transform._TWO_PROJECTIONS) { + // Message.print(MODULE,"TRANSFORM: _TWO_PROJECTIONS"); + /* Reverse the projection */ + sourceCRS.fromProjected(from, to); + /* Apply the projection */ + targetCRS.toProjected(to, to); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* To WGS ? */ + if (path == Transform._TO_WGS) { + // Message.print(MODULE,"TRANSFORM: _TO_WGS"); + /* Use WGS */ + let toWGS: Coordinate = sourceCRS.toWGS(from); + /* Set the target */ + to.setX(toWGS.getX()); + to.setY(toWGS.getY()); + to.setZ(toWGS.getZ()); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; } + /* From WGS ? */ + if (path == Transform._FROM_WGS) { + // Message.print(MODULE,"TRANSFORM: _FROM_WGS"); + /* Use WGS */ + let fromWGS: Coordinate = targetCRS.fromWGS(from); + /* Set the target */ + to.setX(fromWGS.getX()); + to.setY(fromWGS.getY()); + to.setZ(fromWGS.getZ()); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* Full transform ? */ + if (path == Transform._FULL_TRANSFORM) { + // Message.print(MODULE,"TRANSFORM: _FULL_TRANSFORM"); + /* Use WGS as in-between */ + let toWGS: Coordinate = sourceCRS.toWGS(from); + let fromWGS: Coordinate = targetCRS.fromWGS(toWGS); + /* Set the target */ + to.setX(fromWGS.getX()); + to.setY(fromWGS.getY()); + to.setZ(fromWGS.getZ()); + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + /* Vertical transform ? */ + if (path == Transform._VERTICAL) { + // Message.print(MODULE,"TRANSFORM: _VERTICAL"); + /* Get the horizontal components */ + let sourceHorCRS: CRS = (sourceCRS.hasVerticalComponent()) ? sourceCRS.getHorizontalComponent() : sourceCRS; + let targetHorCRS: CRS = (targetCRS.hasVerticalComponent()) ? targetCRS.getHorizontalComponent() : targetCRS; + /* Get the vertical components */ + let sourceVerCRS: CRS = (sourceCRS.hasVerticalComponent()) ? sourceCRS.getVerticalComponent() : null; + let targetVerCRS: CRS = (targetCRS.hasVerticalComponent()) ? targetCRS.getVerticalComponent() : null; + /* Put the source coordinate in the ellipsoid height */ + if (sourceVerCRS != null) { + /* Move to the default 'ellipsoid' height */ + // Message.print(MODULE,"TRANSFORM: source to ellipsoidZ"); + Transform.transformVertical(sourceHorCRS, sourceVerCRS, from, null, to); + from = to; + // Message.print(MODULE,"TRANSFORM: source ellipsoidZ = "+to); + } + /* Get the ellipsoid height */ + let ellipsoidZ: float64 = from.getZ(); + if (sourceHorCRS.isGeoCentric()) { + /* Calculate the ellipsoid height */ + let geographic: Coordinate = new Coordinate(0.0, 0.0, 0.0); + sourceHorCRS.getEllipsoid().toGeoGraphic(from, geographic); + ellipsoidZ = geographic.getZ(); + } + /* Transform in the horizontal CRS (keep the WGS Z (and not the Bessel Z) for transform from WGS to RD-NAP) */ + // Message.print(MODULE,"TRANSFORM: ellipsoidZ = "+ellipsoidZ); + // Message.print(MODULE,"TRANSFORM: horizontal "+sourceHorCRS.getCode()+" -> "+targetHorCRS.getCode()); + Transform.transformCRS(sourceHorCRS, from, targetHorCRS, to); + /* Is the target CRS horizontal? */ + if (targetHorCRS.isGeoCentric() == false) { + /* Keep the ellipsoid height after the horizontal transform */ + to.setZ(ellipsoidZ); + } + from = to; + // Message.print(MODULE,"TRANSFORM: intermediate = "+from); + /* Put the target coordinate in the vertical CRS */ + if (targetVerCRS != null) { + /* Move from the default 'ellipsoid' height */ + Transform.transformVertical(targetHorCRS, null, from, targetVerCRS, to); + from = to; + // Message.print(MODULE,"TRANSFORM: target vtransf = "+to); + } + /* Done */ + // Message.print(MODULE,"TRANSFORMED: to = "+to); + return; + } + // Message.print(MODULE,"TRANSFORMED: UNKNOWN!"); + } + + /** + * Convert between two coordinate reference systems. + * @param sourceCRS the source reference system. + * @param from the coordinate to convert from. + * @param targetCRS the target reference system. + * @param to the coordinate to convert to. + */ + public static transformCRS(sourceCRS: CRS, from: Coordinate, targetCRS: CRS, to: Coordinate): void { + Transform.transformWithPath(Transform.getTransformPath(sourceCRS, targetCRS), sourceCRS, from, targetCRS, to); + } - /** - * Convert between two coordinate reference systems. - * @param sourceCRS the name/code of the source reference system. - * @param from the coordinate to convert from. - * @param targetCRS the name/code of the target reference system. - * @param to the coordinate to convert to. - */ - public static transform(sourceCRS: string, from: Coordinate, targetCRS: string, to: Coordinate): void { - /* Same CRS ? */ - if (Strings.equalsIgnoreCase(targetCRS, sourceCRS)) { - /* Straight copy */ - to.setX(from.getX()); - to.setY(from.getY()); - to.setZ(from.getZ()); - return; - } - /* Get the two CRSs */ - let source: CRS = Registry.getCRS2(sourceCRS); - let target: CRS = Registry.getCRS2(targetCRS); - /* Transform */ - Transform.transformCRS(source, from, target, to); + /** + * Convert between two coordinate reference systems. + * @param sourceCRS the name/code of the source reference system. + * @param from the coordinate to convert from. + * @param targetCRS the name/code of the target reference system. + * @param to the coordinate to convert to. + */ + public static transform(sourceCRS: string, from: Coordinate, targetCRS: string, to: Coordinate): void { + /* Same CRS ? */ + if (Strings.equalsIgnoreCase(targetCRS, sourceCRS)) { + /* Straight copy */ + to.setX(from.getX()); + to.setY(from.getY()); + to.setZ(from.getZ()); + return; } + /* Get the two CRSs */ + let source: CRS = Registry.getCRS2(sourceCRS); + let target: CRS = Registry.getCRS2(targetCRS); + /* Transform */ + Transform.transformCRS(source, from, target, to); + } } diff --git a/core/orbitgt/src/spatial/ecrs/Unit.ts b/core/orbitgt/src/spatial/ecrs/Unit.ts index 8809ba54b5d2..ac8507b92fb9 100644 --- a/core/orbitgt/src/spatial/ecrs/Unit.ts +++ b/core/orbitgt/src/spatial/ecrs/Unit.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -25,330 +25,336 @@ import { Registry } from "./Registry"; */ /** @internal */ export class Unit { - /** The "meter" unit code (length) */ - public static readonly METER: int32 = 9001; - /** The "foot" unit code (length) */ - public static readonly FOOT: int32 = 9002; - /** The "footUS" unit code (length) */ - public static readonly FOOT_US: int32 = 9003; - /** The "radian" unit code (angle) */ - public static readonly RADIAN: int32 = 9101; - /** The "degree" unit code (angle) */ - public static readonly DEGREE: int32 = 9102; - /** The "unity" unit code (scale) */ - public static readonly UNITY: int32 = 9201; + /** The "meter" unit code (length) */ + public static readonly METER: int32 = 9001; + /** The "foot" unit code (length) */ + public static readonly FOOT: int32 = 9002; + /** The "footUS" unit code (length) */ + public static readonly FOOT_US: int32 = 9003; + /** The "radian" unit code (angle) */ + public static readonly RADIAN: int32 = 9101; + /** The "degree" unit code (angle) */ + public static readonly DEGREE: int32 = 9102; + /** The "unity" unit code (scale) */ + public static readonly UNITY: int32 = 9201; - /** Define the custom unit 'sexagesimal DMS' (9110) */ - private static readonly _UNIT_DMS: int32 = 9110; - /** Define the custom unit 'sexagesimal DM' (9111) */ - private static readonly _UNIT_DM: int32 = 9111; + /** Define the custom unit 'sexagesimal DMS' (9110) */ + private static readonly _UNIT_DMS: int32 = 9110; + /** Define the custom unit 'sexagesimal DM' (9111) */ + private static readonly _UNIT_DM: int32 = 9111; - /** The type of units for angles */ - private static readonly _TYPE_ANGLE: string = "angle"; - /** The type of units for length */ - private static readonly _TYPE_LENGTH: string = "length"; - /** The type of units for time */ - private static readonly _TYPE_TIME: string = "time"; - /** The type of units for scale */ - private static readonly _TYPE_SCALE: string = "scale"; + /** The type of units for angles */ + private static readonly _TYPE_ANGLE: string = "angle"; + /** The type of units for length */ + private static readonly _TYPE_LENGTH: string = "length"; + /** The type of units for time */ + private static readonly _TYPE_TIME: string = "time"; + /** The type of units for scale */ + private static readonly _TYPE_SCALE: string = "scale"; - /** The code */ - private _code: int32; - /** The name */ - private _name: string; - /** The abbreviation */ - private _abbreviation: string; - /** The type */ - private _type: string; - /** The target unit code */ - private _targetUnitCode: int32; - /** The B factor */ - private _b: float64; - /** The C factor */ - private _c: float64; + /** The code */ + private _code: int32; + /** The name */ + private _name: string; + /** The abbreviation */ + private _abbreviation: string; + /** The type */ + private _type: string; + /** The target unit code */ + private _targetUnitCode: int32; + /** The B factor */ + private _b: float64; + /** The C factor */ + private _c: float64; - /** The target unit */ - private _target: Unit; + /** The target unit */ + private _target: Unit; - /** - * Create a new unit. - * @param code the code. - * @param name the name. - * @param abbreviation the abbreviation. - * @param type the type (LENGTH, ANGLE or SCALE). - * @param targetUnitCode the target unit code. - * @param b the B factor. - * @param c the C factor. - */ - public constructor(code: int32, name: string, abbreviation: string, type: string, targetUnitCode: int32, b: float64, c: float64) { - /* Store the parameters */ - this._code = code; - this._name = name; - this._abbreviation = abbreviation; - this._type = type; - this._targetUnitCode = targetUnitCode; - this._b = b; - this._c = c; - /* Clear */ - this._target = null; - } + /** + * Create a new unit. + * @param code the code. + * @param name the name. + * @param abbreviation the abbreviation. + * @param type the type (LENGTH, ANGLE or SCALE). + * @param targetUnitCode the target unit code. + * @param b the B factor. + * @param c the C factor. + */ + public constructor(code: int32, name: string, abbreviation: string, type: string, targetUnitCode: int32, b: float64, c: float64) { + /* Store the parameters */ + this._code = code; + this._name = name; + this._abbreviation = abbreviation; + this._type = type; + this._targetUnitCode = targetUnitCode; + this._b = b; + this._c = c; + /* Clear */ + this._target = null; + } - /** - * Get the code. - * @return the code. - */ - public getCode(): int32 { - return this._code; - } + /** + * Get the code. + * @return the code. + */ + public getCode(): int32 { + return this._code; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the abbreviation. - * @return the abbreviation. - */ - public getAbbreviation(): string { - return this._abbreviation; - } + /** + * Get the abbreviation. + * @return the abbreviation. + */ + public getAbbreviation(): string { + return this._abbreviation; + } - /** - * Get the type (LENGTH, ANGLE or SCALE). - * @return the type. - */ - public getType(): string { - return this._type; - } + /** + * Get the type (LENGTH, ANGLE or SCALE). + * @return the type. + */ + public getType(): string { + return this._type; + } - /** - * Check is this is an angle type. - * @return true for an angle type. - */ - public isTypeAngle(): boolean { - return (this._type === Unit._TYPE_ANGLE); - } + /** + * Check is this is an angle type. + * @return true for an angle type. + */ + public isTypeAngle(): boolean { + return (this._type === Unit._TYPE_ANGLE); + } - /** - * Check is this is a length type. - * @return true for a length type. - */ - public isTypeLength(): boolean { - return (this._type === Unit._TYPE_LENGTH); - } + /** + * Check is this is a length type. + * @return true for a length type. + */ + public isTypeLength(): boolean { + return (this._type === Unit._TYPE_LENGTH); + } - /** - * Get the target unit code. - * @return the target unit code. - */ - public getTargetUnitCode(): int32 { - return this._targetUnitCode; - } + /** + * Get the target unit code. + * @return the target unit code. + */ + public getTargetUnitCode(): int32 { + return this._targetUnitCode; + } - /** - * Get the B factor. - * @return the B factor. - */ - public getB(): float64 { - return this._b; - } + /** + * Get the B factor. + * @return the B factor. + */ + public getB(): float64 { + return this._b; + } - /** - * Get the C factor. - * @return the C factor. - */ - public getC(): float64 { - return this._c; - } + /** + * Get the C factor. + * @return the C factor. + */ + public getC(): float64 { + return this._c; + } - /** - * Check if another unit is compatible with this one. - * @param other the other unit. - * @return true if compatible. - */ - public isCompatible(other: Unit): boolean { - if (other._code == this._code) return true; - if (other._targetUnitCode != this._targetUnitCode) return false; - if (other._b != this._b) return false; - if (other._c != this._c) return false; - return true; - } + /** + * Check if another unit is compatible with this one. + * @param other the other unit. + * @return true if compatible. + */ + public isCompatible(other: Unit): boolean { + if (other._code == this._code) return true; + if (other._targetUnitCode != this._targetUnitCode) return false; + if (other._b != this._b) return false; + if (other._c != this._c) return false; + return true; + } - /** - * Convert to the standard unit. - * @param value the value. - * @return the standard value. - */ - public toStandard(value: float64): float64 { - /* Get the target unit */ - if (this._target == null) this._target = Registry.getUnit(this._targetUnitCode); - /* Already standard ? */ - if (this._code == this._targetUnitCode) return value; - /* Check for a custom unit */ - else if (this._code == Unit._UNIT_DMS) return this._target.toStandard(Unit.dmsToDeg(value)); - else if (this._code == Unit._UNIT_DM) return this._target.toStandard(Unit.dmToDeg(value)); - /* Default to scale */ - else return this._target.toStandard(value * this._b / this._c); - } + /** + * Convert to the standard unit. + * @param value the value. + * @return the standard value. + */ + public toStandard(value: float64): float64 { + /* Get the target unit */ + if (this._target == null) this._target = Registry.getUnit(this._targetUnitCode); + /* Already standard ? */ + if (this._code == this._targetUnitCode) return value; + /* Check for a custom unit */ + else if (this._code == Unit._UNIT_DMS) return this._target.toStandard(Unit.dmsToDeg(value)); + else if (this._code == Unit._UNIT_DM) return this._target.toStandard(Unit.dmToDeg(value)); + /* Default to scale */ + else return this._target.toStandard(value * this._b / this._c); + } - /** - * Convert to the standard unit. - * @param value the value. - * @return the standard value. - */ - public to(value: float64): float64 { - return this.toStandard(value); - } + /** + * Convert to the standard unit. + * @param value the value. + * @return the standard value. + */ + public to(value: float64): float64 { + return this.toStandard(value); + } - /** - * Convert from the standard unit. - * @param value the standard value. - * @return the value. - */ - public fromStandard(value: float64): float64 { - /* Get the target unit */ - if (this._target == null) this._target = Registry.getUnit(this._targetUnitCode); - /* Already standard ? */ - if (this._code == this._targetUnitCode) return value; - /* Check for a custom unit */ - else if (this._code == Unit._UNIT_DMS) return Unit.degToDms(this._target.fromStandard(value)); - else if (this._code == Unit._UNIT_DM) return Unit.degToDm(this._target.fromStandard(value)); - /* Default to scale */ - else return this._target.fromStandard(value) * this._c / this._b; - } + /** + * Convert from the standard unit. + * @param value the standard value. + * @return the value. + */ + public fromStandard(value: float64): float64 { + /* Get the target unit */ + if (this._target == null) this._target = Registry.getUnit(this._targetUnitCode); + /* Already standard ? */ + if (this._code == this._targetUnitCode) return value; + /* Check for a custom unit */ + else if (this._code == Unit._UNIT_DMS) return Unit.degToDms(this._target.fromStandard(value)); + else if (this._code == Unit._UNIT_DM) return Unit.degToDm(this._target.fromStandard(value)); + /* Default to scale */ + else return this._target.fromStandard(value) * this._c / this._b; + } - /** - * Convert from the standard unit. - * @param value the standard value. - * @return the value. - */ - public from(value: float64): float64 { - return this.fromStandard(value); - } + /** + * Convert from the standard unit. + * @param value the standard value. + * @return the value. + */ + public from(value: float64): float64 { + return this.fromStandard(value); + } - /** - * Convert a sexagesimal DMS value to fractional degrees. - * @param dms the sexagesimal DMS value. - * @return the fractional degrees. - */ - public static dmsToDeg(dms: float64): float64 { - /* Make sure we have an non-negative number */ - let neg: boolean = (dms < 0.0); - if (neg) dms *= -1.0; - /* Get the seconds */ - let seconds: float64 = (10000.0 * dms); - let iseconds: int32 = Math.floor(seconds); - let fraction: float64 = (seconds - iseconds); - /* Catch rounding errors (like 6.1000 to 6.099999999999999) */ - if (Math.abs(fraction - 1.0) < 1.0e-4) { iseconds++; fraction = 0.0; } - /* Get the degrees */ - let deg: int32 = Numbers.divInt(iseconds, 10000); - ASystem.assertNot((deg < -360) || (deg > 360), "Invalid deg (" + deg + ") in DMS " + dms); - iseconds -= (deg * 10000); - /* Get the minutes */ - let min: int32 = Numbers.divInt(iseconds, 100); - ASystem.assertNot((min < 0) || (min > 59), "Invalid min (" + min + ") in DMS " + dms); - iseconds -= (min * 100); - /* Get the seconds */ - let sec: int32 = (iseconds); - ASystem.assertNot((sec < 0) || (sec > 59), "Invalid sec (" + sec + ") in DMS " + dms); - /* Check the fraction */ - ASystem.assertNot((fraction < 0.0) || (fraction >= 1.0), "Invalid fraction (" + fraction + ") in DMS " + dms); - /* Convert to fractional degrees */ - let fdeg: float64 = deg + (min / 60.0) + (sec / 3600.0) + (fraction / 3600.0); - if (neg) fdeg *= -1.0; - /* Return the degrees */ - return fdeg; + /** + * Convert a sexagesimal DMS value to fractional degrees. + * @param dms the sexagesimal DMS value. + * @return the fractional degrees. + */ + public static dmsToDeg(dms: float64): float64 { + /* Make sure we have an non-negative number */ + let neg: boolean = dms < 0.0; + if (neg) dms *= -1.0; + /* Get the seconds */ + let seconds: float64 = 10000.0 * dms; + let iseconds: int32 = Math.floor(seconds); + let fraction: float64 = seconds - iseconds; + /* Catch rounding errors (like 6.1000 to 6.099999999999999) */ + if (Math.abs(fraction - 1.0) < 1.0e-4) { + iseconds++; + fraction = 0.0; } + /* Get the degrees */ + let deg: int32 = Numbers.divInt(iseconds, 10000); + ASystem.assertNot((deg < -360) || (deg > 360), "Invalid deg (" + deg + ") in DMS " + dms); + iseconds -= deg * 10000; + /* Get the minutes */ + let min: int32 = Numbers.divInt(iseconds, 100); + ASystem.assertNot((min < 0) || (min > 59), "Invalid min (" + min + ") in DMS " + dms); + iseconds -= min * 100; + /* Get the seconds */ + let sec: int32 = iseconds; + ASystem.assertNot((sec < 0) || (sec > 59), "Invalid sec (" + sec + ") in DMS " + dms); + /* Check the fraction */ + ASystem.assertNot((fraction < 0.0) || (fraction >= 1.0), "Invalid fraction (" + fraction + ") in DMS " + dms); + /* Convert to fractional degrees */ + let fdeg: float64 = deg + (min / 60.0) + (sec / 3600.0) + (fraction / 3600.0); + if (neg) fdeg *= -1.0; + /* Return the degrees */ + return fdeg; + } - /** - * Convert a sexagesimal DMS value to fractional radians. - * @param dms the sexagesimal DMS value. - * @return the fractional radians. - */ - public static dmsToRad(dms: float64): float64 { - return Unit.dmsToDeg(dms) * Math.PI / 180.0; - } + /** + * Convert a sexagesimal DMS value to fractional radians. + * @param dms the sexagesimal DMS value. + * @return the fractional radians. + */ + public static dmsToRad(dms: float64): float64 { + return Unit.dmsToDeg(dms) * Math.PI / 180.0; + } - /** - * Convert fractional degrees to a sexagesimal DMS value. - * @param deg the fractional degrees. - * @return the sexagesimal DMS value. - */ - public static degToDms(deg: float64): float64 { - /* Make sure we have an non-negative number */ - let neg: boolean = (deg < 0.0); - if (neg) deg *= -1.0; - /* Get the integer degrees */ - let ideg: float64 = Math.floor(deg); - deg -= ideg; - /* Get the minutes */ - deg *= 60.0; - let min: float64 = Math.floor(deg); - deg -= min; - /* Get the seconds */ - deg *= 60.0; - let sec: float64 = deg; - /* Convert to DMS */ - let dms: float64 = ideg + (min / 100.0) + (sec / 10000.0); - if (neg) dms *= -1.0; - /* Return the DMS */ - return dms; - } + /** + * Convert fractional degrees to a sexagesimal DMS value. + * @param deg the fractional degrees. + * @return the sexagesimal DMS value. + */ + public static degToDms(deg: float64): float64 { + /* Make sure we have an non-negative number */ + let neg: boolean = deg < 0.0; + if (neg) deg *= -1.0; + /* Get the integer degrees */ + let ideg: float64 = Math.floor(deg); + deg -= ideg; + /* Get the minutes */ + deg *= 60.0; + let min: float64 = Math.floor(deg); + deg -= min; + /* Get the seconds */ + deg *= 60.0; + let sec: float64 = deg; + /* Convert to DMS */ + let dms: float64 = ideg + (min / 100.0) + (sec / 10000.0); + if (neg) dms *= -1.0; + /* Return the DMS */ + return dms; + } - /** - * Convert a sexagesimal DM value to fractional degrees. - * @param dm the sexagesimal DM value. - * @return the fractional degrees. - */ - public static dmToDeg(dm: float64): float64 { - /* Make sure we have an non-negative number */ - let neg: boolean = (dm < 0.0); - if (neg) dm *= -1.0; - /* Get the seconds */ - let minutes: float64 = (100.0 * dm); - let iminutes: int32 = Math.floor(minutes); - let fraction: float64 = (minutes - iminutes); - /* Catch rounding errors (like 6.1000 to 6.099999999999999) */ - if (Math.abs(fraction - 1.0) < 1.0e-4) { iminutes++; fraction = 0.0; } - /* Get the degrees */ - let deg: int32 = Numbers.divInt(iminutes, 100); - ASystem.assertNot((deg < -180) || (deg > 180), "Invalid deg (" + deg + ") in DM " + dm); - /* Get the minutes */ - let min: int32 = (iminutes) % 100; - ASystem.assertNot((min < 0) || (min > 59), "Invalid min (" + min + ") in DM " + dm); - /* Check the fraction */ - ASystem.assertNot((fraction < 0.0) || (fraction >= 1.0), "Invalid fraction (" + fraction + ") in DM " + dm); - /* Convert to fractional degrees */ - let fdeg: float64 = deg + (min / 60.0) + (fraction / 60.0); - if (neg) fdeg *= -1.0; - /* Return the degrees */ - return fdeg; + /** + * Convert a sexagesimal DM value to fractional degrees. + * @param dm the sexagesimal DM value. + * @return the fractional degrees. + */ + public static dmToDeg(dm: float64): float64 { + /* Make sure we have an non-negative number */ + let neg: boolean = dm < 0.0; + if (neg) dm *= -1.0; + /* Get the seconds */ + let minutes: float64 = 100.0 * dm; + let iminutes: int32 = Math.floor(minutes); + let fraction: float64 = minutes - iminutes; + /* Catch rounding errors (like 6.1000 to 6.099999999999999) */ + if (Math.abs(fraction - 1.0) < 1.0e-4) { + iminutes++; + fraction = 0.0; } + /* Get the degrees */ + let deg: int32 = Numbers.divInt(iminutes, 100); + ASystem.assertNot((deg < -180) || (deg > 180), "Invalid deg (" + deg + ") in DM " + dm); + /* Get the minutes */ + let min: int32 = iminutes % 100; + ASystem.assertNot((min < 0) || (min > 59), "Invalid min (" + min + ") in DM " + dm); + /* Check the fraction */ + ASystem.assertNot((fraction < 0.0) || (fraction >= 1.0), "Invalid fraction (" + fraction + ") in DM " + dm); + /* Convert to fractional degrees */ + let fdeg: float64 = deg + (min / 60.0) + (fraction / 60.0); + if (neg) fdeg *= -1.0; + /* Return the degrees */ + return fdeg; + } - /** - * Convert fractional degrees to a sexagesimal DM value. - * @param deg the fractional degrees. - * @return the sexagesimal DM value. - */ - public static degToDm(deg: float64): float64 { - /* Make sure we have an non-negative number */ - let neg: boolean = (deg < 0.0); - if (neg) deg *= -1.0; - /* Get the integer degrees */ - let ideg: float64 = Math.floor(deg); - deg -= ideg; - /* Get the minutes */ - deg *= 60.0; - let min: float64 = deg; - /* Convert to DMS */ - let dms: float64 = ideg + (min / 100.0); - if (neg) dms *= -1.0; - /* Return the DMS */ - return dms; - } + /** + * Convert fractional degrees to a sexagesimal DM value. + * @param deg the fractional degrees. + * @return the sexagesimal DM value. + */ + public static degToDm(deg: float64): float64 { + /* Make sure we have an non-negative number */ + let neg: boolean = deg < 0.0; + if (neg) deg *= -1.0; + /* Get the integer degrees */ + let ideg: float64 = Math.floor(deg); + deg -= ideg; + /* Get the minutes */ + deg *= 60.0; + let min: float64 = deg; + /* Convert to DMS */ + let dms: float64 = ideg + (min / 100.0); + if (neg) dms *= -1.0; + /* Return the DMS */ + return dms; + } } diff --git a/core/orbitgt/src/spatial/ecrs/VerticalModel.ts b/core/orbitgt/src/spatial/ecrs/VerticalModel.ts index 3ec95858d4f4..2d1e07d55121 100644 --- a/core/orbitgt/src/spatial/ecrs/VerticalModel.ts +++ b/core/orbitgt/src/spatial/ecrs/VerticalModel.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -25,81 +25,81 @@ import { CRS } from "./CRS"; */ /** @internal */ export class VerticalModel { - /** - * Create a new vertical model. - */ - public constructor() { - } + /** + * Create a new vertical model. + */ + public constructor() { + } - /** - * Is the model available (often support files are needed on disk)? - * @return true if available. - */ - public isAvailable(): boolean { - return false; - } + /** + * Is the model available (often support files are needed on disk)? + * @return true if available. + */ + public isAvailable(): boolean { + return false; + } - /** - * List the vertical CRS EPSG codes this model implements. - * @return the list of vertical CRS codes. - */ - public getVerticalCRSCodes(): Int32Array { - return null; - } + /** + * List the vertical CRS EPSG codes this model implements. + * @return the list of vertical CRS codes. + */ + public getVerticalCRSCodes(): Int32Array { + return null; + } - /** - * List the horizontal CRS EPSG codes in which the vertical model is supported. - * @return the list of horizontal CRS codes. - */ - public getHorizontalCRSCodes(): Int32Array { - return null; - } + /** + * List the horizontal CRS EPSG codes in which the vertical model is supported. + * @return the list of horizontal CRS codes. + */ + public getHorizontalCRSCodes(): Int32Array { + return null; + } - /** - * Check if the vertical model implements a certain vertical datum. - * @param datum the EPSG code of the vertical datum. - * @return true if the datum is implemented. - */ - public supportsVerticalDatum(datum: int32): boolean { - return false; - } + /** + * Check if the vertical model implements a certain vertical datum. + * @param datum the EPSG code of the vertical datum. + * @return true if the datum is implemented. + */ + public supportsVerticalDatum(datum: int32): boolean { + return false; + } - /** - * Check if the vertical model can be applied to a certain horizontal CRS. - * @param crs the horizontal CRS. - * @return true if the model can be applied. - */ - public isValid(crs: CRS): boolean { - return false; - } + /** + * Check if the vertical model can be applied to a certain horizontal CRS. + * @param crs the horizontal CRS. + * @return true if the model can be applied. + */ + public isValid(crs: CRS): boolean { + return false; + } - /** - * Prepare the model for a certain working area. - * @param crs the CRS of the working area to prepare for. - * @param area the working area to prepare for. - * @return the working area. - */ - public prepareForArea(crs: string, area: Bounds): Bounds { - return area; - } + /** + * Prepare the model for a certain working area. + * @param crs the CRS of the working area to prepare for. + * @param area the working area to prepare for. + * @return the working area. + */ + public prepareForArea(crs: string, area: Bounds): Bounds { + return area; + } - /** - * Convert from an ellipsoid height to a local height. - * @param crs the horizontal CRS. - * @param position the position in the horizontal CRS. - * @return the local height. - */ - public toLocalHeight(crs: CRS, position: Coordinate): float64 { - return position.getZ(); - } + /** + * Convert from an ellipsoid height to a local height. + * @param crs the horizontal CRS. + * @param position the position in the horizontal CRS. + * @return the local height. + */ + public toLocalHeight(crs: CRS, position: Coordinate): float64 { + return position.getZ(); + } - /** - * Convert from a local height to an ellipsoid height. - * @param crs the horizontal CRS. - * @param position the position in the horizontal CRS. - * @return the ellipsoid height. - */ - public toEllipsoidHeight(crs: CRS, position: Coordinate): float64 { - return position.getZ(); - } + /** + * Convert from a local height to an ellipsoid height. + * @param crs the horizontal CRS. + * @param position the position in the horizontal CRS. + * @return the ellipsoid height. + */ + public toEllipsoidHeight(crs: CRS, position: Coordinate): float64 { + return position.getZ(); + } } diff --git a/core/orbitgt/src/spatial/ecrs/WellKnownText.ts b/core/orbitgt/src/spatial/ecrs/WellKnownText.ts index 63edc2b6c463..53d46b6a0afc 100644 --- a/core/orbitgt/src/spatial/ecrs/WellKnownText.ts +++ b/core/orbitgt/src/spatial/ecrs/WellKnownText.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -48,412 +48,434 @@ import { WellKnownTextNode } from "./WellKnownTextNode"; */ /** @internal */ export class WellKnownText { - /** The name of this module */ - private static readonly MODULE: string = "WellKnownText"; + /** The name of this module */ + private static readonly MODULE: string = "WellKnownText"; - /** The dialect type in case of generic WKT */ - public static readonly TYPE_GENERIC: string = "generic"; + /** The dialect type in case of generic WKT */ + public static readonly TYPE_GENERIC: string = "generic"; - /** The conversion ratio from "arc-sec" to "radian" */ - private static readonly _ARC_SEC_TO_RAD: float64 = (1.0 / 3600.0 * Math.PI / 180.0); + /** The conversion ratio from "arc-sec" to "radian" */ + private static readonly _ARC_SEC_TO_RAD: float64 = (1.0 / 3600.0 * Math.PI / 180.0); - /** The counter for creating unique codes */ - private static _CODES: int32 = 100000; + /** The counter for creating unique codes */ + private static _CODES: int32 = 100000; - /** - * No instances. - */ - private constructor() { } + /** + * No instances. + */ + private constructor() {} - /** - * Unquote a name. - * @param name the name. - * @return the unquoted name. - */ - private static unquote(name: string): string { - name = Strings.trim(name); - ASystem.assert0(Strings.startsWith(name, "\""), "Name '" + name + "' does not start with a quote"); - ASystem.assert0(Strings.endsWith(name, "\""), "Name '" + name + "' does not end with a quote"); - return Strings.substring(name, 1, Strings.getLength(name) - 1); - } + /** + * Unquote a name. + * @param name the name. + * @return the unquoted name. + */ + private static unquote(name: string): string { + name = Strings.trim(name); + ASystem.assert0(Strings.startsWith(name, '"'), "Name '" + name + "' does not start with a quote"); + ASystem.assert0(Strings.endsWith(name, '"'), "Name '" + name + "' does not end with a quote"); + return Strings.substring(name, 1, Strings.getLength(name) - 1); + } - /** - * Get a number. - * @param value the string value. - * @return the number. - */ - private static getInteger(value: string): int32 { - return Numbers.getInteger(value, 0); - } + /** + * Get a number. + * @param value the string value. + * @return the number. + */ + private static getInteger(value: string): int32 { + return Numbers.getInteger(value, 0); + } - /** - * Get a number. - * @param value the string value. - * @return the number. - */ - private static getDouble(value: string): float64 { - return Numbers.getDouble(value, 0.0); - } + /** + * Get a number. + * @param value the string value. + * @return the number. + */ + private static getDouble(value: string): float64 { + return Numbers.getDouble(value, 0.0); + } - /** - * Get a number. - * @param value the node value. - * @return the number. - */ - private static getNodeDouble(value: WellKnownTextNode): float64 { - if (value == null) return 0.0; - return Numbers.getDouble(value.getName(), 0.0); - } + /** + * Get a number. + * @param value the node value. + * @return the number. + */ + private static getNodeDouble(value: WellKnownTextNode): float64 { + if (value == null) return 0.0; + return Numbers.getDouble(value.getName(), 0.0); + } - /** - * Get an EPSG code for an element. - * @param authority the authority for the element. - * @param dialect the dialect of WKT to parse. - * @return the EPSG code (zero if not found). - */ - private static getEPSGCode(authority: WellKnownTextNode, dialect: string): int32 { - // example: AUTHORITY["EPSG","2320"] - if (authority == null) return 0; - let name: string = WellKnownText.unquote(authority.getArgument(0).getName()); - let code: string = WellKnownText.unquote(authority.getArgument(1).getName()); - if (Strings.equalsIgnoreCase(name, "EPSG") == false) return 0; - let epsgCode: int32 = Numbers.getInteger(code, 0); - return epsgCode; // Enabled on 06/06/2014 - } + /** + * Get an EPSG code for an element. + * @param authority the authority for the element. + * @param dialect the dialect of WKT to parse. + * @return the EPSG code (zero if not found). + */ + private static getEPSGCode(authority: WellKnownTextNode, dialect: string): int32 { + // example: AUTHORITY["EPSG","2320"] + if (authority == null) return 0; + let name: string = WellKnownText.unquote(authority.getArgument(0).getName()); + let code: string = WellKnownText.unquote(authority.getArgument(1).getName()); + if (Strings.equalsIgnoreCase(name, "EPSG") == false) return 0; + let epsgCode: int32 = Numbers.getInteger(code, 0); + return epsgCode; // Enabled on 06/06/2014 + } - /** - * Parse a linear unit. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the unit. - */ - private static parseLinearUnit(node: WellKnownTextNode, dialect: string): Unit { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let conversionFactor: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; - /* Return the unit */ - return new Unit(code, name, name/*abbreviation*/, "length", Unit.METER/*targetUnitCode*/, conversionFactor, 1.0); - } + /** + * Parse a linear unit. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the unit. + */ + private static parseLinearUnit(node: WellKnownTextNode, dialect: string): Unit { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let conversionFactor: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; + /* Return the unit */ + return new Unit(code, name, name, /*abbreviation*/ "length", Unit.METER, /*targetUnitCode*/ conversionFactor, 1.0); + } - /** - * Parse an angular unit. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the unit. - */ - private static parseAngularUnit(node: WellKnownTextNode, dialect: string): Unit { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let conversionFactor: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; - /* Return the unit */ - return new Unit(code, name, name/*abbreviation*/, "angle", Unit.RADIAN/*targetUnitCode*/, conversionFactor, 1.0); - } + /** + * Parse an angular unit. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the unit. + */ + private static parseAngularUnit(node: WellKnownTextNode, dialect: string): Unit { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let conversionFactor: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; + /* Return the unit */ + return new Unit(code, name, name, /*abbreviation*/ "angle", Unit.RADIAN, /*targetUnitCode*/ conversionFactor, 1.0); + } - /** - * Parse a spheroid. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the ellipsoid. - */ - private static parseSpheroid(crsCode: int32, node: WellKnownTextNode, dialect: string): Ellipsoid { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let semiMajorAxis: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); - let invFlattening: float64 = WellKnownText.getDouble(node.getArgument(2).getName()); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; - /* Return the ellipsoid */ - return new Ellipsoid(code, name, Unit.METER, semiMajorAxis, invFlattening, 0.0); - } + /** + * Parse a spheroid. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the ellipsoid. + */ + private static parseSpheroid(crsCode: int32, node: WellKnownTextNode, dialect: string): Ellipsoid { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let semiMajorAxis: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); + let invFlattening: float64 = WellKnownText.getDouble(node.getArgument(2).getName()); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; + /* Return the ellipsoid */ + return new Ellipsoid(code, name, Unit.METER, semiMajorAxis, invFlattening, 0.0); + } - /** - * Parse a prime-meridian. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the prime-meridian. - */ - private static parsePrimeMeridian(crsCode: int32, node: WellKnownTextNode, dialect: string): PrimeMeridian { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let longitude: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; - /* Return the prime-meridian */ - return new PrimeMeridian(code, name, longitude/*lonFromGreenwich*/, Unit.DEGREE/*?*/); - } + /** + * Parse a prime-meridian. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the prime-meridian. + */ + private static parsePrimeMeridian(crsCode: int32, node: WellKnownTextNode, dialect: string): PrimeMeridian { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let longitude: float64 = WellKnownText.getDouble(node.getArgument(1).getName()); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; + /* Return the prime-meridian */ + return new PrimeMeridian(code, name, longitude, /*lonFromGreenwich*/ Unit.DEGREE /*?*/); + } - /** - * Parse a to-wgs84 transform. - * @param node the well-known-text node (method position vector). - * @param dialect the dialect of WKT to parse. - * @return the transform. - */ - public static parseToWGS84(node: WellKnownTextNode, dialect: string): OperationMethod { - /* No transform ? */ - if (node == null) return null; - /* Get the parameters */ - let dx: float64 = WellKnownText.getNodeDouble(node.getArgument(0)); // meter - let dy: float64 = WellKnownText.getNodeDouble(node.getArgument(1)); - let dz: float64 = WellKnownText.getNodeDouble(node.getArgument(2)); - let rx: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(3)); // arc-second - let ry: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(4)); - let rz: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(5)); - let ppm: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(6)); // parts-per-million - /* Return the transform */ - return PositionVector.create(dx, dy, dz, rx * WellKnownText._ARC_SEC_TO_RAD, ry * WellKnownText._ARC_SEC_TO_RAD, rz * WellKnownText._ARC_SEC_TO_RAD, ppm / 1.0e6); - } + /** + * Parse a to-wgs84 transform. + * @param node the well-known-text node (method position vector). + * @param dialect the dialect of WKT to parse. + * @return the transform. + */ + public static parseToWGS84(node: WellKnownTextNode, dialect: string): OperationMethod { + /* No transform ? */ + if (node == null) return null; + /* Get the parameters */ + let dx: float64 = WellKnownText.getNodeDouble(node.getArgument(0)); // meter + let dy: float64 = WellKnownText.getNodeDouble(node.getArgument(1)); + let dz: float64 = WellKnownText.getNodeDouble(node.getArgument(2)); + let rx: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(3)); // arc-second + let ry: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(4)); + let rz: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(5)); + let ppm: float64 = WellKnownText.getNodeDouble(node.getOptionalArgument(6)); // parts-per-million + /* Return the transform */ + return PositionVector.create( + dx, + dy, + dz, + rx * WellKnownText._ARC_SEC_TO_RAD, + ry * WellKnownText._ARC_SEC_TO_RAD, + rz * WellKnownText._ARC_SEC_TO_RAD, + ppm / 1.0e6, + ); + } - /** - * Parse a datum. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param primeMeridian the prime meridian. - * @param dialect the dialect of WKT to parse. - * @return the datum (with optional embedded datum transformation to WGS84). - */ - private static parseDatum(crsCode: int32, node: WellKnownTextNode, primeMeridian: PrimeMeridian, dialect: string): Datum { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let spheroid: Ellipsoid = WellKnownText.parseSpheroid(crsCode, node.getArgumentByName("SPHEROID"), dialect); - let toWGS84: OperationMethod = WellKnownText.parseToWGS84(node.getArgumentByName("TOWGS84"), dialect); - if (toWGS84 == null) toWGS84 = PositionVector.create(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // default (identity) transform added on 19/06/2013 to allow ViewTransform creation. - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; - /* Return the datum */ - let datum: Datum = new Datum(code, name, Datum.TYPE_GEODETIC, spheroid, primeMeridian); - datum.setToWGS84(toWGS84); - return datum; - } + /** + * Parse a datum. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param primeMeridian the prime meridian. + * @param dialect the dialect of WKT to parse. + * @return the datum (with optional embedded datum transformation to WGS84). + */ + private static parseDatum(crsCode: int32, node: WellKnownTextNode, primeMeridian: PrimeMeridian, dialect: string): Datum { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let spheroid: Ellipsoid = WellKnownText.parseSpheroid(crsCode, node.getArgumentByName("SPHEROID"), dialect); + let toWGS84: OperationMethod = WellKnownText.parseToWGS84(node.getArgumentByName("TOWGS84"), dialect); + if (toWGS84 == null) toWGS84 = PositionVector.create(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); // default (identity) transform added on 19/06/2013 to allow ViewTransform creation. + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? WellKnownText._CODES++ : epsgCode; + /* Return the datum */ + let datum: Datum = new Datum(code, name, Datum.TYPE_GEODETIC, spheroid, primeMeridian); + datum.setToWGS84(toWGS84); + return datum; + } - /** - * Parse a projection method. - * @param projection the well-known-text projection node. - * @param parameters the well-known-text parameter nodes. - * @param dialect the dialect of WKT to parse. - * @return the projection method. - */ - private static parseProjectionMethod(projection: WellKnownTextNode, parameters: AList, dialect: string): OperationMethod { - // See: http://www.remotesensing.org/geotiff/proj_list/ - // for method names and parameter names and units - // - /* Get the projection name */ - let projectionName: string = WellKnownText.unquote(projection.getArgument(0).getName()); - /* Get the standard units */ - let DEG: Unit = Registry.getUnit(Unit.DEGREE); - let METER: Unit = Registry.getUnit(Unit.METER); - let SCALE: Unit = Registry.getUnit(Unit.UNITY); - /* Convert to standard parameters */ - let parameterList: ParameterValueList = new ParameterValueList(); - for (let i: number = 0; i < parameters.size(); i++) { - /* Get the parameter name and value */ - let parameter: WellKnownTextNode = parameters.get(i); - let parameterName: string = WellKnownText.unquote(parameter.getArgument(0).getName()); - let parameterValue: float64 = WellKnownText.getDouble(parameter.getArgument(1).getName()); - /* Hotine_Oblique_Mercator */ - if (Strings.equalsIgnoreCase(projectionName, "Hotine_Oblique_Mercator")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8812, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(8813, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "rectified_grid_angle")) parameterList.add(new ParameterValue(8814, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8815, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); - } - /* Krovak */ - if (Strings.equalsIgnoreCase(projectionName, "Krovak") || Strings.equalsIgnoreCase(projectionName, "KrovakEN")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8833, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(1036, parameterValue, DEG)); // changed from 8813 to 1036 on 31/08/2017 - if (Strings.equalsIgnoreCase(parameterName, "pseudo_standard_parallel_1")) parameterList.add(new ParameterValue(8818, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8819, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); - } - /* Lambert_Conformal_Conic_1SP */ - if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_1SP")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); - } - /* Lambert_Conformal_Conic_2SP / Lambert_Conformal_Conic_2SP_Belgium / Lambert_Conformal_Conic */ - if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP") || Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP_Belgium") || Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8821, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8822, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "standard_parallel_1")) parameterList.add(new ParameterValue(8823, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "standard_parallel_2")) parameterList.add(new ParameterValue(8824, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8826, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8827, parameterValue, METER)); - // if (Strings.equalsIgnoreCase(parameterName,"scale_factor")) {if (parameterValue!=1.0) throw new IllegalArgumentException(MODULE+" : Invalid parameter '"+parameterName+"' with value "+parameterValue);} - } - /* Mercator_1SP */ - if (Strings.equalsIgnoreCase(projectionName, "Mercator_1SP")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); - } - /* Oblique_Mercator */ - if (Strings.equalsIgnoreCase(projectionName, "Oblique_Mercator")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8812, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(8813, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "rectified_grid_angle")) parameterList.add(new ParameterValue(8814, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8815, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8816, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8817, parameterValue, METER)); - } - /* Oblique_Stereographic /Transverse_Mercator */ - if (Strings.equalsIgnoreCase(projectionName, "Oblique_Stereographic") || Strings.equalsIgnoreCase(projectionName, "Transverse_Mercator")) { - if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); - if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); - if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); - if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); - } - } - /* Create the right method */ - if (Strings.equalsIgnoreCase(projectionName, "Hotine_Oblique_Mercator")) return new HotineObliqueMercator(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Krovak")) return new KrovakObliqueConformalConic(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "KrovakEN")) return new KrovakObliqueConformalConicEN(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_1SP")) return new LambertConical1SP(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP")) return new LambertConical2SP(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic")) return new LambertConical2SP(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Mercator_1SP")) return new Mercator1SP(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Oblique_Mercator")) return new ObliqueMercator(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Oblique_Stereographic")) return new ObliqueStereographic(parameterList); - if (Strings.equalsIgnoreCase(projectionName, "Transverse_Mercator")) return new TransverseMercator(parameterList); - ASystem.assert0(false, "Unknown projection type '" + projectionName + "'"); - return null; + /** + * Parse a projection method. + * @param projection the well-known-text projection node. + * @param parameters the well-known-text parameter nodes. + * @param dialect the dialect of WKT to parse. + * @return the projection method. + */ + private static parseProjectionMethod(projection: WellKnownTextNode, parameters: AList, dialect: string): OperationMethod { + // See: http://www.remotesensing.org/geotiff/proj_list/ + // for method names and parameter names and units + // + /* Get the projection name */ + let projectionName: string = WellKnownText.unquote(projection.getArgument(0).getName()); + /* Get the standard units */ + let DEG: Unit = Registry.getUnit(Unit.DEGREE); + let METER: Unit = Registry.getUnit(Unit.METER); + let SCALE: Unit = Registry.getUnit(Unit.UNITY); + /* Convert to standard parameters */ + let parameterList: ParameterValueList = new ParameterValueList(); + for (let i: number = 0; i < parameters.size(); i++) { + /* Get the parameter name and value */ + let parameter: WellKnownTextNode = parameters.get(i); + let parameterName: string = WellKnownText.unquote(parameter.getArgument(0).getName()); + let parameterValue: float64 = WellKnownText.getDouble(parameter.getArgument(1).getName()); + /* Hotine_Oblique_Mercator */ + if (Strings.equalsIgnoreCase(projectionName, "Hotine_Oblique_Mercator")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8812, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(8813, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "rectified_grid_angle")) parameterList.add(new ParameterValue(8814, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8815, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); + } + /* Krovak */ + if (Strings.equalsIgnoreCase(projectionName, "Krovak") || Strings.equalsIgnoreCase(projectionName, "KrovakEN")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8833, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(1036, parameterValue, DEG)); // changed from 8813 to 1036 on 31/08/2017 + if (Strings.equalsIgnoreCase(parameterName, "pseudo_standard_parallel_1")) parameterList.add(new ParameterValue(8818, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8819, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); + } + /* Lambert_Conformal_Conic_1SP */ + if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_1SP")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); + } + /* Lambert_Conformal_Conic_2SP / Lambert_Conformal_Conic_2SP_Belgium / Lambert_Conformal_Conic */ + if ( + Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP") || + Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP_Belgium") || + Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic") + ) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8821, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8822, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "standard_parallel_1")) parameterList.add(new ParameterValue(8823, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "standard_parallel_2")) parameterList.add(new ParameterValue(8824, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8826, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8827, parameterValue, METER)); + // if (Strings.equalsIgnoreCase(parameterName,"scale_factor")) {if (parameterValue!=1.0) throw new IllegalArgumentException(MODULE+" : Invalid parameter '"+parameterName+"' with value "+parameterValue);} + } + /* Mercator_1SP */ + if (Strings.equalsIgnoreCase(projectionName, "Mercator_1SP")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); + } + /* Oblique_Mercator */ + if (Strings.equalsIgnoreCase(projectionName, "Oblique_Mercator")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_center")) parameterList.add(new ParameterValue(8811, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "longitude_of_center")) parameterList.add(new ParameterValue(8812, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "azimuth")) parameterList.add(new ParameterValue(8813, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "rectified_grid_angle")) parameterList.add(new ParameterValue(8814, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8815, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8816, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8817, parameterValue, METER)); + } + /* Oblique_Stereographic /Transverse_Mercator */ + if (Strings.equalsIgnoreCase(projectionName, "Oblique_Stereographic") || Strings.equalsIgnoreCase(projectionName, "Transverse_Mercator")) { + if (Strings.equalsIgnoreCase(parameterName, "latitude_of_origin")) parameterList.add(new ParameterValue(8801, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "central_meridian")) parameterList.add(new ParameterValue(8802, parameterValue, DEG)); + if (Strings.equalsIgnoreCase(parameterName, "scale_factor")) parameterList.add(new ParameterValue(8805, parameterValue, SCALE)); + if (Strings.equalsIgnoreCase(parameterName, "false_easting")) parameterList.add(new ParameterValue(8806, parameterValue, METER)); + if (Strings.equalsIgnoreCase(parameterName, "false_northing")) parameterList.add(new ParameterValue(8807, parameterValue, METER)); + } } + /* Create the right method */ + if (Strings.equalsIgnoreCase(projectionName, "Hotine_Oblique_Mercator")) return new HotineObliqueMercator(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Krovak")) return new KrovakObliqueConformalConic(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "KrovakEN")) return new KrovakObliqueConformalConicEN(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_1SP")) return new LambertConical1SP(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic_2SP")) return new LambertConical2SP(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Lambert_Conformal_Conic")) return new LambertConical2SP(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Mercator_1SP")) return new Mercator1SP(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Oblique_Mercator")) return new ObliqueMercator(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Oblique_Stereographic")) return new ObliqueStereographic(parameterList); + if (Strings.equalsIgnoreCase(projectionName, "Transverse_Mercator")) return new TransverseMercator(parameterList); + ASystem.assert0(false, "Unknown projection type '" + projectionName + "'"); + return null; + } - /** - * Parse a geocentric CRS. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the CRS. - */ - private static parseGeocentric(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let primeMeridian: PrimeMeridian = WellKnownText.parsePrimeMeridian(crsCode, node.getArgumentByName("PRIMEM"), dialect); - let datum: Datum = WellKnownText.parseDatum(crsCode, node.getArgumentByName("DATUM"), primeMeridian, dialect); - let toWGS84m: OperationMethod = datum.getToWGS84(); - let toWGS84s: AList = new AList(); - let linearUnit: Unit = WellKnownText.parseLinearUnit(node.getArgumentByName("UNIT"), dialect); - let axis: AList = node.getArgumentsByName("AXIS"); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; - /* Return the CRS */ - if (toWGS84m != null) toWGS84s.add(new Operation(0/*code*/, ""/*name*/, Operation.TRANSFORMATION, code, CRS.WGS84_2D_CRS_CODE, 0/*area*/, toWGS84m)); - return new CRS(code, name, 0/*area*/, CRS.GEOCENTRIC, 0/*csCode*/, datum, null/*baseCRS*/, null/*projection*/, toWGS84s); - } + /** + * Parse a geocentric CRS. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the CRS. + */ + private static parseGeocentric(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let primeMeridian: PrimeMeridian = WellKnownText.parsePrimeMeridian(crsCode, node.getArgumentByName("PRIMEM"), dialect); + let datum: Datum = WellKnownText.parseDatum(crsCode, node.getArgumentByName("DATUM"), primeMeridian, dialect); + let toWGS84m: OperationMethod = datum.getToWGS84(); + let toWGS84s: AList = new AList(); + let linearUnit: Unit = WellKnownText.parseLinearUnit(node.getArgumentByName("UNIT"), dialect); + let axis: AList = node.getArgumentsByName("AXIS"); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; + /* Return the CRS */ + if (toWGS84m != null) + toWGS84s.add(new Operation(0, /*code*/ "", /*name*/ Operation.TRANSFORMATION, code, CRS.WGS84_2D_CRS_CODE, 0, /*area*/ toWGS84m)); + return new CRS(code, name, 0, /*area*/ CRS.GEOCENTRIC, 0, /*csCode*/ datum, null, /*baseCRS*/ null, /*projection*/ toWGS84s); + } - /** - * Parse a geographic CRS. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the CRS. - */ - private static parseGeographic(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let primeMeridian: PrimeMeridian = WellKnownText.parsePrimeMeridian(crsCode, node.getArgumentByName("PRIMEM"), dialect); - let datum: Datum = WellKnownText.parseDatum(crsCode, node.getArgumentByName("DATUM"), primeMeridian, dialect); - let toWGS84m: OperationMethod = datum.getToWGS84(); - let toWGS84s: AList = new AList(); - let angularUnit: Unit = WellKnownText.parseAngularUnit(node.getArgumentByName("UNIT"), dialect); - let axis: AList = node.getArgumentsByName("AXIS"); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; - /* Return the CRS */ - if (toWGS84m != null) toWGS84s.add(new Operation(0/*code*/, ""/*name*/, Operation.TRANSFORMATION, code, CRS.WGS84_2D_CRS_CODE, 0/*area*/, toWGS84m)); - return new CRS(code, name, 0/*area*/, CRS.GEOGRAPHIC_2D, 0/*csCode*/, datum, null/*baseCRS*/, null/*projection*/, toWGS84s); - } + /** + * Parse a geographic CRS. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the CRS. + */ + private static parseGeographic(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let primeMeridian: PrimeMeridian = WellKnownText.parsePrimeMeridian(crsCode, node.getArgumentByName("PRIMEM"), dialect); + let datum: Datum = WellKnownText.parseDatum(crsCode, node.getArgumentByName("DATUM"), primeMeridian, dialect); + let toWGS84m: OperationMethod = datum.getToWGS84(); + let toWGS84s: AList = new AList(); + let angularUnit: Unit = WellKnownText.parseAngularUnit(node.getArgumentByName("UNIT"), dialect); + let axis: AList = node.getArgumentsByName("AXIS"); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; + /* Return the CRS */ + if (toWGS84m != null) + toWGS84s.add(new Operation(0, /*code*/ "", /*name*/ Operation.TRANSFORMATION, code, CRS.WGS84_2D_CRS_CODE, 0, /*area*/ toWGS84m)); + return new CRS(code, name, 0, /*area*/ CRS.GEOGRAPHIC_2D, 0, /*csCode*/ datum, null, /*baseCRS*/ null, /*projection*/ toWGS84s); + } - /** - * Parse a projected CRS. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the CRS. - */ - private static parseProjection(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let baseCRS: CRS = WellKnownText.parseGeographic(-crsCode, node.getArgumentByName("GEOGCS"), dialect); - let projection: WellKnownTextNode = node.getArgumentByName("PROJECTION"); - let parameters: AList = node.getArgumentsByName("PARAMETER"); - let projectionMethod: OperationMethod = WellKnownText.parseProjectionMethod(projection, parameters, dialect); - let linearUnit: Unit = WellKnownText.parseLinearUnit(node.getArgumentByName("UNIT"), dialect); - let axis: AList = node.getArgumentsByName("AXIS"); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; - /* Return the CRS */ - let projectionOperation: Operation = new Operation(0/*code*/, ""/*name*/, Operation.CONVERSION, code, baseCRS.getCode(), 0/*area*/, projectionMethod); - return new CRS(code, name, 0/*area*/, CRS.PROJECTED, 0/*csCode*/, null/*datum*/, baseCRS, projectionOperation, null/*toWGS84*/); - } + /** + * Parse a projected CRS. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the CRS. + */ + private static parseProjection(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let baseCRS: CRS = WellKnownText.parseGeographic(-crsCode, node.getArgumentByName("GEOGCS"), dialect); + let projection: WellKnownTextNode = node.getArgumentByName("PROJECTION"); + let parameters: AList = node.getArgumentsByName("PARAMETER"); + let projectionMethod: OperationMethod = WellKnownText.parseProjectionMethod(projection, parameters, dialect); + let linearUnit: Unit = WellKnownText.parseLinearUnit(node.getArgumentByName("UNIT"), dialect); + let axis: AList = node.getArgumentsByName("AXIS"); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; + /* Return the CRS */ + let projectionOperation: Operation = new Operation( + 0, /*code*/ + "", /*name*/ + Operation.CONVERSION, + code, + baseCRS.getCode(), + 0, /*area*/ + projectionMethod, + ); + return new CRS(code, name, 0, /*area*/ CRS.PROJECTED, 0, /*csCode*/ null, /*datum*/ baseCRS, projectionOperation, null /*toWGS84*/); + } - /** - * Parse a vertical CRS. - * @param crsCode the code of the CRS. - * @param node the well-known-text node. - * @param dialect the dialect of WKT to parse. - * @return the CRS. - */ - private static parseVertical(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { - /* Get the parameters */ - let name: string = WellKnownText.unquote(node.getArgument(0).getName()); - let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); - /* Do we have an EPGS code ? */ - let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); - let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; - /* Create the datum */ - let datum: Datum = new Datum(code, name, Datum.TYPE_VERTICAL, null/*spheroid*/, null/*primeMeridian*/); - /* Return the CRS */ - return new CRS(code, name, 0/*area*/, CRS.VERTICAL, 6499/*csCode*/, datum, null/*baseCRS*/, null/*projectionOperation*/, null/*toWGS84*/); - } + /** + * Parse a vertical CRS. + * @param crsCode the code of the CRS. + * @param node the well-known-text node. + * @param dialect the dialect of WKT to parse. + * @return the CRS. + */ + private static parseVertical(crsCode: int32, node: WellKnownTextNode, dialect: string): CRS { + /* Get the parameters */ + let name: string = WellKnownText.unquote(node.getArgument(0).getName()); + let authority: WellKnownTextNode = node.getArgumentByName("AUTHORITY"); + /* Do we have an EPGS code ? */ + let epsgCode: int32 = WellKnownText.getEPSGCode(authority, dialect); + let code: int32 = (epsgCode == 0) ? crsCode : epsgCode; + /* Create the datum */ + let datum: Datum = new Datum(code, name, Datum.TYPE_VERTICAL, null, /*spheroid*/ null /*primeMeridian*/); + /* Return the CRS */ + return new CRS(code, name, 0, /*area*/ CRS.VERTICAL, 6499, /*csCode*/ datum, null, /*baseCRS*/ null, /*projectionOperation*/ null /*toWGS84*/); + } - /** - * Parse a CRS well-known-text. - * @param crsCode the code of the CRS. - * @param text the well-known-text. - * @param dialect the dialect of WKT to parse. - * @return the CRS (null if unable to parse). - */ - public static parseSpatialReferenceSystem(crsCode: int32, text: string, dialect: string): CRS { - let node: WellKnownTextNode = WellKnownTextNode.parse(text); - if (Strings.equalsIgnoreCase(node.getName(), "GEOCCS")) return WellKnownText.parseGeocentric(crsCode, node, dialect); - if (Strings.equalsIgnoreCase(node.getName(), "GEOGCS")) return WellKnownText.parseGeographic(crsCode, node, dialect); - if (Strings.equalsIgnoreCase(node.getName(), "PROJCS")) return WellKnownText.parseProjection(crsCode, node, dialect); - if (Strings.equalsIgnoreCase(node.getName(), "VERTCS")) return WellKnownText.parseVertical(crsCode, node, dialect); - Message.printWarning(WellKnownText.MODULE, "Invalid spatial reference system WKT '" + text + "'"); - return null; - } + /** + * Parse a CRS well-known-text. + * @param crsCode the code of the CRS. + * @param text the well-known-text. + * @param dialect the dialect of WKT to parse. + * @return the CRS (null if unable to parse). + */ + public static parseSpatialReferenceSystem(crsCode: int32, text: string, dialect: string): CRS { + let node: WellKnownTextNode = WellKnownTextNode.parse(text); + if (Strings.equalsIgnoreCase(node.getName(), "GEOCCS")) return WellKnownText.parseGeocentric(crsCode, node, dialect); + if (Strings.equalsIgnoreCase(node.getName(), "GEOGCS")) return WellKnownText.parseGeographic(crsCode, node, dialect); + if (Strings.equalsIgnoreCase(node.getName(), "PROJCS")) return WellKnownText.parseProjection(crsCode, node, dialect); + if (Strings.equalsIgnoreCase(node.getName(), "VERTCS")) return WellKnownText.parseVertical(crsCode, node, dialect); + Message.printWarning(WellKnownText.MODULE, "Invalid spatial reference system WKT '" + text + "'"); + return null; + } } diff --git a/core/orbitgt/src/spatial/ecrs/WellKnownTextNode.ts b/core/orbitgt/src/spatial/ecrs/WellKnownTextNode.ts index 9c6ab93d7068..2ae865ee71de 100644 --- a/core/orbitgt/src/spatial/ecrs/WellKnownTextNode.ts +++ b/core/orbitgt/src/spatial/ecrs/WellKnownTextNode.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs; +// package orbitgt.spatial.ecrs; type int8 = number; type int16 = number; @@ -25,114 +25,115 @@ import { Strings } from "../../system/runtime/Strings"; */ /** @internal */ export class WellKnownTextNode { - /** Get the name */ - private _name: string; - /** Get the arguments */ - private _argumentList: AList; + /** Get the name */ + private _name: string; + /** Get the arguments */ + private _argumentList: AList; - /** - * Create a new node. - * @param name the name. - * @param argumentList the arguments. - */ - public constructor(name: string, argumentList: AList) { - if (argumentList == null) argumentList = new AList(); - this._name = name; - this._argumentList = argumentList; - } + /** + * Create a new node. + * @param name the name. + * @param argumentList the arguments. + */ + public constructor(name: string, argumentList: AList) { + if (argumentList == null) argumentList = new AList(); + this._name = name; + this._argumentList = argumentList; + } - /** - * Get the name. - * @return the name. - */ - public getName(): string { - return this._name; - } + /** + * Get the name. + * @return the name. + */ + public getName(): string { + return this._name; + } - /** - * Get the arguments. - * @return the arguments. - */ - public getArguments(): AList { - return this._argumentList; - } + /** + * Get the arguments. + * @return the arguments. + */ + public getArguments(): AList { + return this._argumentList; + } - /** - * Add an argument. - * @param argument the argument to add. - */ - public addArgument(argument: WellKnownTextNode): void { - this._argumentList.add(argument); - } + /** + * Add an argument. + * @param argument the argument to add. + */ + public addArgument(argument: WellKnownTextNode): void { + this._argumentList.add(argument); + } - /** - * Get an argument. - * @param index the index of the argument. - * @return the argument. - */ - public getArgument(index: int32): WellKnownTextNode { - return this._argumentList.get(index); - } + /** + * Get an argument. + * @param index the index of the argument. + * @return the argument. + */ + public getArgument(index: int32): WellKnownTextNode { + return this._argumentList.get(index); + } - /** - * Get an optional argument. - * @param index the index of the argument. - * @return the argument. - */ - public getOptionalArgument(index: int32): WellKnownTextNode { - if (index < this._argumentList.size()) return this.getArgument(index); - return null; - } + /** + * Get an optional argument. + * @param index the index of the argument. + * @return the argument. + */ + public getOptionalArgument(index: int32): WellKnownTextNode { + if (index < this._argumentList.size()) return this.getArgument(index); + return null; + } - /** - * Get arguments by name. - * @param name the name of the arguments. - * @return the arguments. - */ - public getArgumentsByName(name: string): AList { - let list: AList = new AList(); - for (let argument of this._argumentList) if (Strings.equalsIgnoreCase(argument.getName(), name)) list.add(argument); - return list; - } + /** + * Get arguments by name. + * @param name the name of the arguments. + * @return the arguments. + */ + public getArgumentsByName(name: string): AList { + let list: AList = new AList(); + for (let argument of this._argumentList) if (Strings.equalsIgnoreCase(argument.getName(), name)) list.add(argument); + return list; + } - /** - * Get an argument by name. - * @param name the name of the argument. - * @return the argument (null if not found). - */ - public getArgumentByName(name: string): WellKnownTextNode { - let list: AList = this.getArgumentsByName(name); - return (list.size() == 0) ? null : list.get(0); - } + /** + * Get an argument by name. + * @param name the name of the argument. + * @return the argument (null if not found). + */ + public getArgumentByName(name: string): WellKnownTextNode { + let list: AList = this.getArgumentsByName(name); + return (list.size() == 0) ? null : list.get(0); + } - /** - * Parse an expression. - * @param expression the expression. - * @return the parsed expression. - */ - public static parse(expression: string): WellKnownTextNode { - /* Literal ? */ - if ((Strings.getLength(expression) >= 2) && Strings.startsWith(expression, "\"") && Strings.endsWith(expression, "\"")) return new WellKnownTextNode(expression, null); - /* Get the start of the argument list */ - let index1: int32 = Strings.indexOf(expression, "["); - if (index1 < 0) index1 = Strings.indexOf(expression, "("); - /* No arguments ? */ - if (index1 < 0) return new WellKnownTextNode(expression, null); - /* Get the end of the argument list */ - let index2: int32 = Strings.lastIndexOf(expression, "]"); - if (index2 < 0) index2 = Strings.lastIndexOf(expression, ")"); - /* Check */ - ASystem.assertNot(index2 < 0, "Invalid well-known-text '" + expression + "' (missing closing bracket)"); - ASystem.assertNot(index2 < index1, "Invalid well-known-text '" + expression + "' (wrong bracket sequence)"); - /* Get the argument list */ - let argumentList: string = Strings.substring(expression, index1 + 1, index2); - let arguments1: AList = Strings.splitAdvanced(argumentList, ","/*separators*/, "[("/*opens*/, "])"/*closes*/, "\""/*literals*/); - /* Parse the arguments */ - let arguments2: AList = new AList(); - for (let i: number = 0; i < arguments1.size(); i++) arguments2.add(WellKnownTextNode.parse(Strings.trim(arguments1.get(i)))); - /* Get the node name */ - let name: string = Strings.trim(Strings.substring(expression, 0, index1)); - /* Return the node */ - return new WellKnownTextNode(name, arguments2); - } + /** + * Parse an expression. + * @param expression the expression. + * @return the parsed expression. + */ + public static parse(expression: string): WellKnownTextNode { + /* Literal ? */ + if ((Strings.getLength(expression) >= 2) && Strings.startsWith(expression, '"') && Strings.endsWith(expression, '"')) + return new WellKnownTextNode(expression, null); + /* Get the start of the argument list */ + let index1: int32 = Strings.indexOf(expression, "["); + if (index1 < 0) index1 = Strings.indexOf(expression, "("); + /* No arguments ? */ + if (index1 < 0) return new WellKnownTextNode(expression, null); + /* Get the end of the argument list */ + let index2: int32 = Strings.lastIndexOf(expression, "]"); + if (index2 < 0) index2 = Strings.lastIndexOf(expression, ")"); + /* Check */ + ASystem.assertNot(index2 < 0, "Invalid well-known-text '" + expression + "' (missing closing bracket)"); + ASystem.assertNot(index2 < index1, "Invalid well-known-text '" + expression + "' (wrong bracket sequence)"); + /* Get the argument list */ + let argumentList: string = Strings.substring(expression, index1 + 1, index2); + let arguments1: AList = Strings.splitAdvanced(argumentList, ",", /*separators*/ "[(", /*opens*/ "])", /*closes*/ '"' /*literals*/); + /* Parse the arguments */ + let arguments2: AList = new AList(); + for (let i: number = 0; i < arguments1.size(); i++) arguments2.add(WellKnownTextNode.parse(Strings.trim(arguments1.get(i)))); + /* Get the node name */ + let name: string = Strings.trim(Strings.substring(expression, 0, index1)); + /* Return the node */ + return new WellKnownTextNode(name, arguments2); + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/HotineObliqueMercator.ts b/core/orbitgt/src/spatial/ecrs/projection/HotineObliqueMercator.ts index beb64a2fd88b..2b84a496c0cf 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/HotineObliqueMercator.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/HotineObliqueMercator.ts @@ -40,174 +40,175 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class HotineObliqueMercator extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9812; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9812; - /** Latitude of the projection center */ - private _latC: float64; - /** Longitude of the projection center */ - private _lonC: float64; - /** Azimuth of the initial line passing through the projection center */ - private _aziC: float64; - /** Angle from the recified grid to the skew (oblique) grid */ - private _gamC: float64; - /** Scale factor on the initial line of projection */ - private _kC: float64; - /** False easting at the natural origin */ - private _fe: float64; - /** False northing at the natural origin */ - private _fn: float64; + /** Latitude of the projection center */ + private _latC: float64; + /** Longitude of the projection center */ + private _lonC: float64; + /** Azimuth of the initial line passing through the projection center */ + private _aziC: float64; + /** Angle from the recified grid to the skew (oblique) grid */ + private _gamC: float64; + /** Scale factor on the initial line of projection */ + private _kC: float64; + /** False easting at the natural origin */ + private _fe: float64; + /** False northing at the natural origin */ + private _fn: float64; - /** Forward calculation parameters */ - private _a: float64; - private _e: float64; - private _e2: float64; - private _B: float64; - private _A: float64; - private _tO: float64; - private _D: float64; - private _F: float64; - private _H: float64; - private _G: float64; - private _latO: float64; - private _lonO: float64; - private _vC: float64; - private _uC: float64; - /** Reverse calculation parameters */ - private _rev1: float64; - private _rev2: float64; - private _rev3: float64; - private _rev4: float64; + /** Forward calculation parameters */ + private _a: float64; + private _e: float64; + private _e2: float64; + private _B: float64; + private _A: float64; + private _tO: float64; + private _D: float64; + private _F: float64; + private _H: float64; + private _G: float64; + private _latO: float64; + private _lonO: float64; + private _vC: float64; + private _uC: float64; + /** Reverse calculation parameters */ + private _rev1: float64; + private _rev2: float64; + private _rev3: float64; + private _rev4: float64; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(HotineObliqueMercator.METHOD_CODE, "Hotine Oblique Mercator", parameters); - /* Store the parameters */ - this._latC = parameters.getValue(8811); - this._lonC = parameters.getValue(8812); - this._aziC = parameters.getValue(8813); - this._gamC = parameters.getValue(8814); - this._kC = parameters.getValue(8815); - this._fe = parameters.getValue(8806); - this._fn = parameters.getValue(8807); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(HotineObliqueMercator.METHOD_CODE, "Hotine Oblique Mercator", parameters); + /* Store the parameters */ + this._latC = parameters.getValue(8811); + this._lonC = parameters.getValue(8812); + this._aziC = parameters.getValue(8813); + this._gamC = parameters.getValue(8814); + this._kC = parameters.getValue(8815); + this._fe = parameters.getValue(8806); + this._fn = parameters.getValue(8807); + } - /** - * Get the sign of a number. - */ - private static sign(v: float64): float64 { - return (v < 0.0) ? (-1.0) : (1.0); - } + /** + * Get the sign of a number. + */ + private static sign(v: float64): float64 { + return (v < 0.0) ? (-1.0) : (1.0); + } - /** - * Get the power of a number (must be able to handle negative 'n' values). - */ - private static pow(n: float64, e: int32): float64 { - let p: float64 = 1.0; - for (let i: number = 0; i < e; i++) p *= n; - return p; - } + /** + * Get the power of a number (must be able to handle negative 'n' values). + */ + private static pow(n: float64, e: int32): float64 { + let p: float64 = 1.0; + for (let i: number = 0; i < e; i++) p *= n; + return p; + } - /** - * Initialize the projection. - * @param ellipsoid the ellipsoid to use. - * @return this projection (for convenience). - */ - public initializeProjection(ellipsoid: Ellipsoid): HotineObliqueMercator { - /* Prepare the forward parameters */ - this._a = ellipsoid.getA(); - this._e = ellipsoid.getE(); - this._e2 = this._e * this._e; - this._B = Math.sqrt(1.0 + (this._e2 * HotineObliqueMercator.pow(Math.cos(this._latC), 4) / (1.0 - this._e2))); - const esinLatC: float64 = this._e * Math.sin(this._latC); - this._A = this._a * this._B * this._kC * Math.sqrt(1.0 - this._e2) / (1.0 - HotineObliqueMercator.pow(esinLatC, 2)); - this._tO = Math.tan(Math.PI / 4.0 - this._latC / 2.0) / Math.pow((1.0 - esinLatC) / (1.0 + esinLatC), this._e / 2.0); - this._D = this._B * Math.sqrt(1.0 - this._e2) / (Math.cos(this._latC) * Math.sqrt(1.0 - HotineObliqueMercator.pow(esinLatC, 2))); - const D2: float64 = (this._D < 1.0) ? (1.0) : (this._D * this._D); - this._F = this._D + Math.sqrt(D2 - 1.0) * HotineObliqueMercator.sign(this._latC); - this._H = this._F * Math.pow(this._tO, this._B); - this._G = (this._F - 1.0 / this._F) / 2.0; - this._latO = Math.asin(Math.sin(this._aziC) / this._D); - this._lonO = this._lonC - Math.asin(this._G * Math.tan(this._latO)) / this._B; - this._vC = 0.0; - if (Math.abs(this._aziC - 0.5 * Math.PI) < 0.00001) this._uC = this._A * (this._lonC - this._lonO); // special case Hungary, Switzerland - else this._uC = (this._A / this._B) * Math.atan(Math.sqrt(D2 - 1.0) / Math.cos(this._aziC)) * HotineObliqueMercator.sign(this._latC); - /* Prepare the reverse parameters */ - const e4: float64 = this._e2 * this._e2; - const e6: float64 = e4 * this._e2; - const e8: float64 = e4 * e4; - this._rev1 = (this._e2 / 2 + 5 * e4 / 24 + e6 / 12 + 13 * e8 / 360); - this._rev2 = (7 * e4 / 48 + 29 * e6 / 240 + 811 * e8 / 11520); - this._rev3 = (7 * e6 / 120 + 81 * e8 / 1120); - this._rev4 = (4279 * e8 / 161280); - /* Return the projection */ - return this; - } + /** + * Initialize the projection. + * @param ellipsoid the ellipsoid to use. + * @return this projection (for convenience). + */ + public initializeProjection(ellipsoid: Ellipsoid): HotineObliqueMercator { + /* Prepare the forward parameters */ + this._a = ellipsoid.getA(); + this._e = ellipsoid.getE(); + this._e2 = this._e * this._e; + this._B = Math.sqrt(1.0 + (this._e2 * HotineObliqueMercator.pow(Math.cos(this._latC), 4) / (1.0 - this._e2))); + const esinLatC: float64 = this._e * Math.sin(this._latC); + this._A = this._a * this._B * this._kC * Math.sqrt(1.0 - this._e2) / (1.0 - HotineObliqueMercator.pow(esinLatC, 2)); + this._tO = Math.tan(Math.PI / 4.0 - this._latC / 2.0) / Math.pow((1.0 - esinLatC) / (1.0 + esinLatC), this._e / 2.0); + this._D = this._B * Math.sqrt(1.0 - this._e2) / (Math.cos(this._latC) * Math.sqrt(1.0 - HotineObliqueMercator.pow(esinLatC, 2))); + const D2: float64 = (this._D < 1.0) ? (1.0) : (this._D * this._D); + this._F = this._D + Math.sqrt(D2 - 1.0) * HotineObliqueMercator.sign(this._latC); + this._H = this._F * Math.pow(this._tO, this._B); + this._G = (this._F - 1.0 / this._F) / 2.0; + this._latO = Math.asin(Math.sin(this._aziC) / this._D); + this._lonO = this._lonC - Math.asin(this._G * Math.tan(this._latO)) / this._B; + this._vC = 0.0; + if (Math.abs(this._aziC - 0.5 * Math.PI) < 0.00001) this._uC = this._A * (this._lonC - this._lonO); // special case Hungary, Switzerland + else this._uC = (this._A / this._B) * Math.atan(Math.sqrt(D2 - 1.0) / Math.cos(this._aziC)) * HotineObliqueMercator.sign(this._latC); + /* Prepare the reverse parameters */ + const e4: float64 = this._e2 * this._e2; + const e6: float64 = e4 * this._e2; + const e8: float64 = e4 * e4; + this._rev1 = this._e2 / 2 + 5 * e4 / 24 + e6 / 12 + 13 * e8 / 360; + this._rev2 = 7 * e4 / 48 + 29 * e6 / 240 + 811 * e8 / 11520; + this._rev3 = 7 * e6 / 120 + 81 * e8 / 1120; + this._rev4 = 4279 * e8 / 161280; + /* Return the projection */ + return this; + } - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - this.initializeProjection(operation.getSourceCRS().getEllipsoid()); - } + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + this.initializeProjection(operation.getSourceCRS().getEllipsoid()); + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - /* Make the calculation */ - const esinLat: float64 = this._e * Math.sin(lat); - const t: float64 = Math.tan(Math.PI / 4.0 - lat / 2.0) / Math.pow((1.0 - esinLat) / (1.0 + esinLat), this._e / 2.0); - const Q: float64 = this._H / Math.pow(t, this._B); - const S: float64 = (Q - 1.0 / Q) / 2.0; - const T: float64 = (Q + 1.0 / Q) / 2.0; - const V: float64 = Math.sin(this._B * (lon - this._lonO)); - const U: float64 = (-V * Math.cos(this._latO) + S * Math.sin(this._latO)) / T; - const v: float64 = this._A * Math.log((1.0 - U) / (1.0 + U)) / (2.0 * this._B); - const u: float64 = (this._A * Math.atan((S * Math.cos(this._latO) + V * Math.sin(this._latO)) / Math.cos(this._B * (lon - this._lonO))) / this._B); // possibly related to method 9815 atan2 problem? (LER 15/06/2018) - const sinGamC: float64 = Math.sin(this._gamC); - const cosGamC: float64 = Math.cos(this._gamC); - const E: float64 = v * cosGamC + u * sinGamC + this._fe; - const N: float64 = u * cosGamC - v * sinGamC + this._fn; - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + /* Make the calculation */ + const esinLat: float64 = this._e * Math.sin(lat); + const t: float64 = Math.tan(Math.PI / 4.0 - lat / 2.0) / Math.pow((1.0 - esinLat) / (1.0 + esinLat), this._e / 2.0); + const Q: float64 = this._H / Math.pow(t, this._B); + const S: float64 = (Q - 1.0 / Q) / 2.0; + const T: float64 = (Q + 1.0 / Q) / 2.0; + const V: float64 = Math.sin(this._B * (lon - this._lonO)); + const U: float64 = (-V * Math.cos(this._latO) + S * Math.sin(this._latO)) / T; + const v: float64 = this._A * Math.log((1.0 - U) / (1.0 + U)) / (2.0 * this._B); + const u: float64 = this._A * Math.atan((S * Math.cos(this._latO) + V * Math.sin(this._latO)) / Math.cos(this._B * (lon - this._lonO))) / this._B; // possibly related to method 9815 atan2 problem? (LER 15/06/2018) + const sinGamC: float64 = Math.sin(this._gamC); + const cosGamC: float64 = Math.cos(this._gamC); + const E: float64 = v * cosGamC + u * sinGamC + this._fe; + const N: float64 = u * cosGamC - v * sinGamC + this._fn; + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Make the calculation */ - const sinGamC: float64 = Math.sin(this._gamC); - const cosGamC: float64 = Math.cos(this._gamC); - const v: float64 = (E - this._fe) * cosGamC - (N - this._fn) * sinGamC; - const u: float64 = (N - this._fn) * cosGamC + (E - this._fe) * sinGamC; - const Q: float64 = Math.exp(-this._B * v / this._A); - const S: float64 = (Q - 1.0 / Q) / 2.0; - const T: float64 = (Q + 1.0 / Q) / 2.0; - const V: float64 = Math.sin(this._B * u / this._A); - const U: float64 = (V * Math.cos(this._latO) + S * Math.sin(this._latO)) / T; - const t: float64 = Math.pow(this._H / Math.sqrt((1.0 + U) / (1.0 - U)), 1.0 / this._B); - const chi: float64 = Math.PI / 2.0 - 2.0 * Math.atan(t); - const lat: float64 = chi + Math.sin(2.0 * chi) * this._rev1 + Math.sin(4.0 * chi) * this._rev2 + Math.sin(6.0 * chi) * this._rev3 + Math.sin(8.0 * chi) * this._rev4; - const lon: float64 = this._lonO - Math.atan((S * cosGamC - V * sinGamC) / Math.cos(this._B * u / this._A)) / this._B; // possibly related to method 9815 atan2 problem? (LER 15/06/2018) - /* Save the position */ - source.setX(lon); - source.setY(lat); - source.setZ(target.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Make the calculation */ + const sinGamC: float64 = Math.sin(this._gamC); + const cosGamC: float64 = Math.cos(this._gamC); + const v: float64 = (E - this._fe) * cosGamC - (N - this._fn) * sinGamC; + const u: float64 = (N - this._fn) * cosGamC + (E - this._fe) * sinGamC; + const Q: float64 = Math.exp(-this._B * v / this._A); + const S: float64 = (Q - 1.0 / Q) / 2.0; + const T: float64 = (Q + 1.0 / Q) / 2.0; + const V: float64 = Math.sin(this._B * u / this._A); + const U: float64 = (V * Math.cos(this._latO) + S * Math.sin(this._latO)) / T; + const t: float64 = Math.pow(this._H / Math.sqrt((1.0 + U) / (1.0 - U)), 1.0 / this._B); + const chi: float64 = Math.PI / 2.0 - 2.0 * Math.atan(t); + const lat: float64 = chi + Math.sin(2.0 * chi) * this._rev1 + Math.sin(4.0 * chi) * this._rev2 + Math.sin(6.0 * chi) * this._rev3 + + Math.sin(8.0 * chi) * this._rev4; + const lon: float64 = this._lonO - Math.atan((S * cosGamC - V * sinGamC) / Math.cos(this._B * u / this._A)) / this._B; // possibly related to method 9815 atan2 problem? (LER 15/06/2018) + /* Save the position */ + source.setX(lon); + source.setY(lat); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConic.ts b/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConic.ts index a6c9e2b77724..b80c7db084c2 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConic.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConic.ts @@ -42,123 +42,131 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class KrovakObliqueConformalConic extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9819; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9819; - /** Latitude of projection center */ - private _latC: float64; - /** Longitude of origin */ - private _lonO: float64; - /** Azimuth of initial line through the projection center */ - private _aziC: float64; - /** Latitude of pseudo standard parallel */ - private _latP: float64; - /** Scale factor on pseudo standard parallel */ - private _kP: float64; - /** Easting at grid origin */ - private _FE: float64; - /** Northing at grid origin */ - private _FN: float64; + /** Latitude of projection center */ + private _latC: float64; + /** Longitude of origin */ + private _lonO: float64; + /** Azimuth of initial line through the projection center */ + private _aziC: float64; + /** Latitude of pseudo standard parallel */ + private _latP: float64; + /** Scale factor on pseudo standard parallel */ + private _kP: float64; + /** Easting at grid origin */ + private _FE: float64; + /** Northing at grid origin */ + private _FN: float64; - /** The constants */ - private _A: float64; - private _B: float64; - private _gO: float64; - private _tO: float64; - private _n: float64; - private _rO: float64; + /** The constants */ + private _A: float64; + private _B: float64; + private _gO: float64; + private _tO: float64; + private _n: float64; + private _rO: float64; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(KrovakObliqueConformalConic.METHOD_CODE, "Krovak Oblique Conic Conformal", parameters); - /* Store the parameters */ - this._latC = parameters.getValue(8811); - this._lonO = parameters.getValue(8833); - this._aziC = parameters.getValue(1036); // Parameter 8813 has been changed to 1036 for method 9819 in EPSG version 7.7. updated on 31/08/2017. - this._latP = parameters.getValue(8818); - this._kP = parameters.getValue(8819); - this._FE = parameters.getValue(8806); - this._FN = parameters.getValue(8807); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(KrovakObliqueConformalConic.METHOD_CODE, "Krovak Oblique Conic Conformal", parameters); + /* Store the parameters */ + this._latC = parameters.getValue(8811); + this._lonO = parameters.getValue(8833); + this._aziC = parameters.getValue(1036); // Parameter 8813 has been changed to 1036 for method 9819 in EPSG version 7.7. updated on 31/08/2017. + this._latP = parameters.getValue(8818); + this._kP = parameters.getValue(8819); + this._FE = parameters.getValue(8806); + this._FN = parameters.getValue(8807); + } - /** - * Get the square of a number. - */ - private static sqr(v: float64): float64 { - return (v * v); - } + /** + * Get the square of a number. + */ + private static sqr(v: float64): float64 { + return (v * v); + } - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - /* Prepare the parameters */ - const ellipsoid: Ellipsoid = operation.getSourceCRS().getEllipsoid(); - const a: float64 = ellipsoid.getA(); - const e: float64 = ellipsoid.getE(); - const e2: float64 = e * e; - this._A = a * Math.sqrt(1.0 - e2) / (1.0 - KrovakObliqueConformalConic.sqr(e * Math.sin(this._latC))); - this._B = Math.sqrt(1.0 + e2 * Math.pow(Math.cos(this._latC), 4) / (1.0 - e2)); - this._gO = Math.asin(Math.sin(this._latC) / this._B); - this._tO = Math.tan(Math.PI / 4 + this._gO / 2) * Math.pow((1 + e * Math.sin(this._latC)) / (1 - e * Math.sin(this._latC)), e * this._B / 2) / Math.pow(Math.tan(Math.PI / 4 + this._latC / 2), this._B); - this._n = Math.sin(this._latP); - this._rO = this._kP * this._A / Math.tan(this._latP); - } + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + /* Prepare the parameters */ + const ellipsoid: Ellipsoid = operation.getSourceCRS().getEllipsoid(); + const a: float64 = ellipsoid.getA(); + const e: float64 = ellipsoid.getE(); + const e2: float64 = e * e; + this._A = a * Math.sqrt(1.0 - e2) / (1.0 - KrovakObliqueConformalConic.sqr(e * Math.sin(this._latC))); + this._B = Math.sqrt(1.0 + e2 * Math.pow(Math.cos(this._latC), 4) / (1.0 - e2)); + this._gO = Math.asin(Math.sin(this._latC) / this._B); + this._tO = Math.tan(Math.PI / 4 + this._gO / 2) * Math.pow((1 + e * Math.sin(this._latC)) / (1 - e * Math.sin(this._latC)), e * this._B / 2) / + Math.pow(Math.tan(Math.PI / 4 + this._latC / 2), this._B); + this._n = Math.sin(this._latP); + this._rO = this._kP * this._A / Math.tan(this._latP); + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - /* Calculate easting and northing */ - const e: float64 = sourceCRS.getEllipsoid().getE(); - const U: float64 = 2 * (Math.atan(this._tO * Math.pow(Math.tan(lat / 2 + Math.PI / 4), this._B) / Math.pow((1 + e * Math.sin(lat)) / (1 - e * Math.sin(lat)), e * this._B / 2)) - Math.PI / 4); - const V: float64 = this._B * (this._lonO - lon); - const S: float64 = Math.asin(Math.cos(this._aziC) * Math.sin(U) + Math.sin(this._aziC) * Math.cos(U) * Math.cos(V)); - const D: float64 = Math.asin(Math.cos(U) * Math.sin(V) / Math.cos(S)); - const theta: float64 = this._n * D; - const r: float64 = this._rO * Math.pow(Math.tan(Math.PI / 4 + this._latP / 2), this._n) / Math.pow(Math.tan(S / 2 + Math.PI / 4), this._n); - const E: float64 = this._FE + r * Math.cos(theta); - const N: float64 = this._FN + r * Math.sin(theta); - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + /* Calculate easting and northing */ + const e: float64 = sourceCRS.getEllipsoid().getE(); + const U: float64 = 2 * + (Math.atan( + this._tO * Math.pow(Math.tan(lat / 2 + Math.PI / 4), this._B) / Math.pow((1 + e * Math.sin(lat)) / (1 - e * Math.sin(lat)), e * this._B / 2), + ) - Math.PI / 4); + const V: float64 = this._B * (this._lonO - lon); + const S: float64 = Math.asin(Math.cos(this._aziC) * Math.sin(U) + Math.sin(this._aziC) * Math.cos(U) * Math.cos(V)); + const D: float64 = Math.asin(Math.cos(U) * Math.sin(V) / Math.cos(S)); + const theta: float64 = this._n * D; + const r: float64 = this._rO * Math.pow(Math.tan(Math.PI / 4 + this._latP / 2), this._n) / Math.pow(Math.tan(S / 2 + Math.PI / 4), this._n); + const E: float64 = this._FE + r * Math.cos(theta); + const N: float64 = this._FN + r * Math.sin(theta); + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the easting and northing */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Get the ellipsoid parameters */ - const e: float64 = sourceCRS.getEllipsoid().getE(); - /* Calculate longitude and latitude */ - const r: float64 = Math.sqrt(KrovakObliqueConformalConic.sqr(E - this._FE) + KrovakObliqueConformalConic.sqr(N - this._FN)); - const theta: float64 = Math.atan2((N - this._FN), (E - this._FE)); - const D: float64 = theta / Math.sin(this._latP); - const S: float64 = 2 * (Math.atan(Math.pow(this._rO / r, 1 / this._n) * Math.tan(Math.PI / 4 + this._latP / 2)) - Math.PI / 4); - const U: float64 = Math.asin(Math.cos(this._aziC) * Math.sin(S) - Math.sin(this._aziC) * Math.cos(S) * Math.cos(D)); - const V: float64 = Math.asin(Math.cos(S) * Math.sin(D) / Math.cos(U)); - /* Iterate */ - let lat: float64 = U; - for (let i: number = 1; i < 5; i++) { - lat = 2 * (Math.atan(Math.pow(this._tO, -1 / this._B) * Math.pow(Math.tan(U / 2 + Math.PI / 4), 1 / this._B) * Math.pow((1 + e * Math.sin(lat)) / (1 - e * Math.sin(lat)), e / 2)) - Math.PI / 4); - } - const lon: float64 = this._lonO - V / this._B; - /* Save the position */ - source.setX(lon); - source.setY(lat); - source.setZ(target.getZ()); // Keep the Z value + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the easting and northing */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Get the ellipsoid parameters */ + const e: float64 = sourceCRS.getEllipsoid().getE(); + /* Calculate longitude and latitude */ + const r: float64 = Math.sqrt(KrovakObliqueConformalConic.sqr(E - this._FE) + KrovakObliqueConformalConic.sqr(N - this._FN)); + const theta: float64 = Math.atan2(N - this._FN, E - this._FE); + const D: float64 = theta / Math.sin(this._latP); + const S: float64 = 2 * (Math.atan(Math.pow(this._rO / r, 1 / this._n) * Math.tan(Math.PI / 4 + this._latP / 2)) - Math.PI / 4); + const U: float64 = Math.asin(Math.cos(this._aziC) * Math.sin(S) - Math.sin(this._aziC) * Math.cos(S) * Math.cos(D)); + const V: float64 = Math.asin(Math.cos(S) * Math.sin(D) / Math.cos(U)); + /* Iterate */ + let lat: float64 = U; + for (let i: number = 1; i < 5; i++) { + lat = 2 * + (Math.atan( + Math.pow(this._tO, -1 / this._B) * Math.pow(Math.tan(U / 2 + Math.PI / 4), 1 / this._B) * + Math.pow((1 + e * Math.sin(lat)) / (1 - e * Math.sin(lat)), e / 2), + ) - Math.PI / 4); } + const lon: float64 = this._lonO - V / this._B; + /* Save the position */ + source.setX(lon); + source.setY(lat); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConicEN.ts b/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConicEN.ts index 737ed8ea36da..0b1ce140642a 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConicEN.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/KrovakObliqueConformalConicEN.ts @@ -33,58 +33,58 @@ import { KrovakObliqueConformalConic } from "./KrovakObliqueConformalConic"; */ /** @internal */ export class KrovakObliqueConformalConicEN extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 1041; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 1041; - /** The original projection */ - private projection: KrovakObliqueConformalConic; + /** The original projection */ + private projection: KrovakObliqueConformalConic; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(KrovakObliqueConformalConicEN.METHOD_CODE, "Krovak Oblique Conic Conformal East-North", parameters); - /* Create the projection */ - this.projection = new KrovakObliqueConformalConic(parameters); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(KrovakObliqueConformalConicEN.METHOD_CODE, "Krovak Oblique Conic Conformal East-North", parameters); + /* Create the projection */ + this.projection = new KrovakObliqueConformalConic(parameters); + } - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - /* Prepare the projection */ - this.projection.initialize(operation); - } + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + /* Prepare the projection */ + this.projection.initialize(operation); + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Do the forward projection */ - this.projection.forward(sourceCRS, source, targetCRS, target); - /* Get the original position */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Swap */ - target.setX(-N); - target.setY(-E); - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Do the forward projection */ + this.projection.forward(sourceCRS, source, targetCRS, target); + /* Get the original position */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Swap */ + target.setX(-N); + target.setY(-E); + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the swapped position */ - const N: float64 = -target.getX(); - const E: float64 = -target.getY(); - /* Swap (leave the target coordinate untouched) */ - source.setX(E); - source.setY(N); - /* Do the reverse projection */ - this.projection.reverse(sourceCRS, source, targetCRS, source/* target*/); - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the swapped position */ + const N: float64 = -target.getX(); + const E: float64 = -target.getY(); + /* Swap (leave the target coordinate untouched) */ + source.setX(E); + source.setY(N); + /* Do the reverse projection */ + this.projection.reverse(sourceCRS, source, targetCRS, source /* target*/); + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/LambertConical1SP.ts b/core/orbitgt/src/spatial/ecrs/projection/LambertConical1SP.ts index d257d588b8de..2bbca9b81ff7 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/LambertConical1SP.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/LambertConical1SP.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs.projection; +// package orbitgt.spatial.ecrs.projection; type int8 = number; type int16 = number; @@ -38,117 +38,118 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class LambertConical1SP extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9801; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9801; - /** Latitude of natural origin */ - private _latN: float64; - /** Longitude of natural origin (the central meridian) */ - private _lonN: float64; - /** Scale factor at natural origin */ - private _k0: float64; - /** False easting */ - private _fE: float64; - /** False northing */ - private _fN: float64; + /** Latitude of natural origin */ + private _latN: float64; + /** Longitude of natural origin (the central meridian) */ + private _lonN: float64; + /** Scale factor at natural origin */ + private _k0: float64; + /** False easting */ + private _fE: float64; + /** False northing */ + private _fN: float64; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(LambertConical1SP.METHOD_CODE, "Lambert Conic Conformal (1SP)", parameters); - /* Store the parameters */ - this._latN = parameters.getValue(8801); - this._lonN = parameters.getValue(8802); - this._k0 = parameters.getValue(8805); - this._fE = parameters.getValue(8806); - this._fN = parameters.getValue(8807); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(LambertConical1SP.METHOD_CODE, "Lambert Conic Conformal (1SP)", parameters); + /* Store the parameters */ + this._latN = parameters.getValue(8801); + this._lonN = parameters.getValue(8802); + this._k0 = parameters.getValue(8805); + this._fE = parameters.getValue(8806); + this._fN = parameters.getValue(8807); + } - /** - * Get the sign of a number. - */ - private static sign(v: float64): float64 { - return (v < 0.0) ? (-1.0) : (1.0); - } + /** + * Get the sign of a number. + */ + private static sign(v: float64): float64 { + return (v < 0.0) ? (-1.0) : (1.0); + } - /** - * Calculate M. - */ - private static calcM(e: float64, lat: float64): float64 { - return Math.cos(lat) / Math.pow(1.0 - Math.pow(e * Math.sin(lat), 2.0), 0.5); - } + /** + * Calculate M. + */ + private static calcM(e: float64, lat: float64): float64 { + return Math.cos(lat) / Math.pow(1.0 - Math.pow(e * Math.sin(lat), 2.0), 0.5); + } - /** - * Calculate T. - */ - private static calcT(e: float64, lat: float64): float64 { - return Math.tan(Math.PI * 0.25 - lat * 0.5) / Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5); - } + /** + * Calculate T. + */ + private static calcT(e: float64, lat: float64): float64 { + return Math.tan(Math.PI * 0.25 - lat * 0.5) / Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5); + } - /** - * Calculate R. - */ - private static calcR(a: float64, F: float64, t: float64, n: float64, k0: float64): float64 { - if (Math.abs(t) < 1.0e-6) return 0.0; - return a * F * Math.pow(t, n) * k0; - } + /** + * Calculate R. + */ + private static calcR(a: float64, F: float64, t: float64, n: float64, k0: float64): float64 { + if (Math.abs(t) < 1.0e-6) return 0.0; + return a * F * Math.pow(t, n) * k0; + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - let lon: float64 = source.getX(); - let lat: float64 = source.getY(); - /* Get the ellipsoid parameters */ - let e: float64 = sourceCRS.getEllipsoid().getE(); - let a: float64 = sourceCRS.getEllipsoid().getA(); - /* Make the calculation */ - let m0: float64 = LambertConical1SP.calcM(e, this._latN); - let t0: float64 = LambertConical1SP.calcT(e, this._latN); - let n: float64 = Math.sin(this._latN); - let F: float64 = m0 / (n * Math.pow(t0, n)); - let r0: float64 = LambertConical1SP.calcR(a, F, t0, n, this._k0); - let t: float64 = LambertConical1SP.calcT(e, lat); - let r: float64 = LambertConical1SP.calcR(a, F, t, n, this._k0); - let theta: float64 = n * (lon - this._lonN); - let E: float64 = this._fE + r * Math.sin(theta); - let N: float64 = this._fN + r0 - r * Math.cos(theta); - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + let lon: float64 = source.getX(); + let lat: float64 = source.getY(); + /* Get the ellipsoid parameters */ + let e: float64 = sourceCRS.getEllipsoid().getE(); + let a: float64 = sourceCRS.getEllipsoid().getA(); + /* Make the calculation */ + let m0: float64 = LambertConical1SP.calcM(e, this._latN); + let t0: float64 = LambertConical1SP.calcT(e, this._latN); + let n: float64 = Math.sin(this._latN); + let F: float64 = m0 / (n * Math.pow(t0, n)); + let r0: float64 = LambertConical1SP.calcR(a, F, t0, n, this._k0); + let t: float64 = LambertConical1SP.calcT(e, lat); + let r: float64 = LambertConical1SP.calcR(a, F, t, n, this._k0); + let theta: float64 = n * (lon - this._lonN); + let E: float64 = this._fE + r * Math.sin(theta); + let N: float64 = this._fN + r0 - r * Math.cos(theta); + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - let E: float64 = target.getX(); - let N: float64 = target.getY(); - /* Get the ellipsoid parameters */ - let e: float64 = sourceCRS.getEllipsoid().getE(); - let a: float64 = sourceCRS.getEllipsoid().getA(); - /* Make the calculation */ - let m0: float64 = LambertConical1SP.calcM(e, this._latN); - let t0: float64 = LambertConical1SP.calcT(e, this._latN); - let n: float64 = Math.sin(this._latN); - let F: float64 = m0 / (n * Math.pow(t0, n)); - let r0: float64 = LambertConical1SP.calcR(a, F, t0, n, this._k0); - let r_: float64 = LambertConical1SP.sign(n) * Math.pow(Math.pow(E - this._fE, 2.0) + Math.pow(r0 - (N - this._fN), 2.0), 0.5); - let t_: float64 = Math.pow(r_ / (a * this._k0 * F), 1.0 / n); - let theta_: float64 = Math.atan((E - this._fE) / (r0 - (N - this._fN))); - let lat: float64 = Math.PI * 0.5 - 2.0 * Math.atan(t_); - for (let i: number = 0; i < 7; i++) lat = Math.PI * 0.5 - 2.0 * Math.atan(t_ * Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5)); // recursive formula - let lon: float64 = (theta_) / n + this._lonN; - /* Save the position */ - source.setX(lon); - source.setY(lat); - source.setZ(target.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + let E: float64 = target.getX(); + let N: float64 = target.getY(); + /* Get the ellipsoid parameters */ + let e: float64 = sourceCRS.getEllipsoid().getE(); + let a: float64 = sourceCRS.getEllipsoid().getA(); + /* Make the calculation */ + let m0: float64 = LambertConical1SP.calcM(e, this._latN); + let t0: float64 = LambertConical1SP.calcT(e, this._latN); + let n: float64 = Math.sin(this._latN); + let F: float64 = m0 / (n * Math.pow(t0, n)); + let r0: float64 = LambertConical1SP.calcR(a, F, t0, n, this._k0); + let r_: float64 = LambertConical1SP.sign(n) * Math.pow(Math.pow(E - this._fE, 2.0) + Math.pow(r0 - (N - this._fN), 2.0), 0.5); + let t_: float64 = Math.pow(r_ / (a * this._k0 * F), 1.0 / n); + let theta_: float64 = Math.atan((E - this._fE) / (r0 - (N - this._fN))); + let lat: float64 = Math.PI * 0.5 - 2.0 * Math.atan(t_); + for (let i: number = 0; i < 7; i++) + lat = Math.PI * 0.5 - 2.0 * Math.atan(t_ * Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5)); // recursive formula + let lon: float64 = theta_ / n + this._lonN; + /* Save the position */ + source.setX(lon); + source.setY(lat); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/LambertConical2SP.ts b/core/orbitgt/src/spatial/ecrs/projection/LambertConical2SP.ts index 7179d0748069..56def2150b50 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/LambertConical2SP.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/LambertConical2SP.ts @@ -40,188 +40,188 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class LambertConical2SP extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9802; - - /** The value of PI */ - private static readonly PI: float64 = Math.PI; - /** The half value of PI */ - private static readonly hPI: float64 = 0.5 * Math.PI; - - /** Latitude of false origin */ - private _latF: float64; - /** Longitude of false origin (the central meridian) */ - private _lonF: float64; - /** Latitude of first standard parallel */ - private _lat1: float64; - /** Latitude of second standard parallel */ - private _lat2: float64; - /** Easting at false origin */ - private _eF: float64; - /** Northing at false origin */ - private _nF: float64; - - /* Calculation parameters */ - private _e: float64; - private _a: float64; - private _m1: float64; - private _m2: float64; - private _t1: float64; - private _t2: float64; - private _tF: float64; - private _n: float64; - private _F: float64; - private _rF: float64; - - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(LambertConical2SP.METHOD_CODE, "Lambert Conic Conformal (2SP)", parameters); - /* Store the parameters */ - this._latF = parameters.getValue(8821); - this._lonF = parameters.getValue(8822); - this._lat1 = parameters.getValue(8823); - this._lat2 = parameters.getValue(8824); - this._eF = parameters.getValue(8826); - this._nF = parameters.getValue(8827); - } - - /** - * Get the sign of a number. - */ - private static sign(v: float64): float64 { - return (v < 0.0) ? (-1.0) : (1.0); - } - - /** - * Get the square of a number. - */ - private static square(v: float64): float64 { - return (v * v); - } - - /** - * Calculate M. - */ - private static calcM(e: float64, lat: float64): float64 { - return Math.cos(lat) / Math.sqrt(1.0 - LambertConical2SP.square(e * Math.sin(lat))); - } - - /** - * Calculate T. - */ - private static calcT(e: float64, lat: float64): float64 { - return Math.tan(Math.PI * 0.25 - lat * 0.5) / Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5); - } - - /** - * Calculate R. - */ - private static calcR(a: float64, F: float64, t: float64, n: float64): float64 { - if (Math.abs(t) < 1.0e-6) return 0.0; - return a * F * Math.pow(t, n); - } - - /** - * Initialize the projection. - * @param ellipsoid the ellipsoid to use. - * @return this projection (for convenience). - */ - public initializeProjection(ellipsoid: Ellipsoid): LambertConical2SP { - /* Get the ellipsoid parameters */ - this._e = ellipsoid.getE(); - this._a = ellipsoid.getA(); - /* Make the calculation */ - this._m1 = LambertConical2SP.calcM(this._e, this._lat1); - this._m2 = LambertConical2SP.calcM(this._e, this._lat2); - this._t1 = LambertConical2SP.calcT(this._e, this._lat1); - this._t2 = LambertConical2SP.calcT(this._e, this._lat2); - this._tF = LambertConical2SP.calcT(this._e, this._latF); - this._n = (Math.log(this._m1) - Math.log(this._m2)) / (Math.log(this._t1) - Math.log(this._t2)); - this._F = this._m1 / (this._n * Math.pow(this._t1, this._n)); - this._rF = LambertConical2SP.calcR(this._a, this._F, this._tF, this._n); - /* Return the projection */ - return this; - } - - /** - * Do the projection. - * @param lon the longitude (radians). - * @param lat the latitude (radians). - * @param projected the target projected coordinate (X and Y will be set). - */ - public toProjection(lon: float64, lat: float64, projected: Coordinate): void { - /* Make the calculation */ - const t: float64 = LambertConical2SP.calcT(this._e, lat); - const r: float64 = LambertConical2SP.calcR(this._a, this._F, t, this._n); - const theta: float64 = this._n * (lon - this._lonF); - const E: float64 = this._eF + r * Math.sin(theta); - const N: float64 = this._nF + this._rF - r * Math.cos(theta); - /* Save the position */ - projected.setX(E); - projected.setY(N); - } - - /** - * Do the inverse projection. - * @param x the easting. - * @param y the northing. - * @param geographic the target geographic coordinate (X/Lon and Y/Lat will be set) (radians). - */ - public toGeoGraphic(x: float64, y: float64, geographic: Coordinate): void { - /* Get the parameters */ - const E: float64 = x; - const N: float64 = y; - /* Make the calculation */ - const r_: float64 = LambertConical2SP.sign(this._n) * Math.sqrt(LambertConical2SP.square(E - this._eF) + LambertConical2SP.square(this._rF - (N - this._nF))); - const t_: float64 = Math.pow(r_ / (this._a * this._F), 1.0 / this._n); - const theta_: float64 = Math.atan((E - this._eF) / (this._rF - (N - this._nF))); - let lat: float64 = LambertConical2SP.PI * 0.5 - 2.0 * Math.atan(t_); - const he: float64 = 0.5 * this._e; - for (let i: number = 0; i < 7; i++) // double-checked iteration count. LER, 24/11/2011 - { - const eSin: float64 = this._e * Math.sin(lat); - lat = LambertConical2SP.hPI - 2.0 * Math.atan(t_ * Math.pow((1.0 - eSin) / (1.0 + eSin), he)); // recursive formula - } - const lon: float64 = (theta_) / this._n + this._lonF; - /* Save the position */ - geographic.setX(lon); - geographic.setY(lat); - } - - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - this.initializeProjection(operation.getSourceCRS().getEllipsoid()); - } - - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - /* Do the projection */ - this.toProjection(lon, lat, target); - target.setZ(source.getZ()); // Keep the Z value - } - - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Do the inverse projection */ - this.toGeoGraphic(E, N, source); - source.setZ(target.getZ()); // Keep the Z value + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9802; + + /** The value of PI */ + private static readonly PI: float64 = Math.PI; + /** The half value of PI */ + private static readonly hPI: float64 = 0.5 * Math.PI; + + /** Latitude of false origin */ + private _latF: float64; + /** Longitude of false origin (the central meridian) */ + private _lonF: float64; + /** Latitude of first standard parallel */ + private _lat1: float64; + /** Latitude of second standard parallel */ + private _lat2: float64; + /** Easting at false origin */ + private _eF: float64; + /** Northing at false origin */ + private _nF: float64; + + /* Calculation parameters */ + private _e: float64; + private _a: float64; + private _m1: float64; + private _m2: float64; + private _t1: float64; + private _t2: float64; + private _tF: float64; + private _n: float64; + private _F: float64; + private _rF: float64; + + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(LambertConical2SP.METHOD_CODE, "Lambert Conic Conformal (2SP)", parameters); + /* Store the parameters */ + this._latF = parameters.getValue(8821); + this._lonF = parameters.getValue(8822); + this._lat1 = parameters.getValue(8823); + this._lat2 = parameters.getValue(8824); + this._eF = parameters.getValue(8826); + this._nF = parameters.getValue(8827); + } + + /** + * Get the sign of a number. + */ + private static sign(v: float64): float64 { + return (v < 0.0) ? (-1.0) : (1.0); + } + + /** + * Get the square of a number. + */ + private static square(v: float64): float64 { + return (v * v); + } + + /** + * Calculate M. + */ + private static calcM(e: float64, lat: float64): float64 { + return Math.cos(lat) / Math.sqrt(1.0 - LambertConical2SP.square(e * Math.sin(lat))); + } + + /** + * Calculate T. + */ + private static calcT(e: float64, lat: float64): float64 { + return Math.tan(Math.PI * 0.25 - lat * 0.5) / Math.pow((1.0 - e * Math.sin(lat)) / (1.0 + e * Math.sin(lat)), e * 0.5); + } + + /** + * Calculate R. + */ + private static calcR(a: float64, F: float64, t: float64, n: float64): float64 { + if (Math.abs(t) < 1.0e-6) return 0.0; + return a * F * Math.pow(t, n); + } + + /** + * Initialize the projection. + * @param ellipsoid the ellipsoid to use. + * @return this projection (for convenience). + */ + public initializeProjection(ellipsoid: Ellipsoid): LambertConical2SP { + /* Get the ellipsoid parameters */ + this._e = ellipsoid.getE(); + this._a = ellipsoid.getA(); + /* Make the calculation */ + this._m1 = LambertConical2SP.calcM(this._e, this._lat1); + this._m2 = LambertConical2SP.calcM(this._e, this._lat2); + this._t1 = LambertConical2SP.calcT(this._e, this._lat1); + this._t2 = LambertConical2SP.calcT(this._e, this._lat2); + this._tF = LambertConical2SP.calcT(this._e, this._latF); + this._n = (Math.log(this._m1) - Math.log(this._m2)) / (Math.log(this._t1) - Math.log(this._t2)); + this._F = this._m1 / (this._n * Math.pow(this._t1, this._n)); + this._rF = LambertConical2SP.calcR(this._a, this._F, this._tF, this._n); + /* Return the projection */ + return this; + } + + /** + * Do the projection. + * @param lon the longitude (radians). + * @param lat the latitude (radians). + * @param projected the target projected coordinate (X and Y will be set). + */ + public toProjection(lon: float64, lat: float64, projected: Coordinate): void { + /* Make the calculation */ + const t: float64 = LambertConical2SP.calcT(this._e, lat); + const r: float64 = LambertConical2SP.calcR(this._a, this._F, t, this._n); + const theta: float64 = this._n * (lon - this._lonF); + const E: float64 = this._eF + r * Math.sin(theta); + const N: float64 = this._nF + this._rF - r * Math.cos(theta); + /* Save the position */ + projected.setX(E); + projected.setY(N); + } + + /** + * Do the inverse projection. + * @param x the easting. + * @param y the northing. + * @param geographic the target geographic coordinate (X/Lon and Y/Lat will be set) (radians). + */ + public toGeoGraphic(x: float64, y: float64, geographic: Coordinate): void { + /* Get the parameters */ + const E: float64 = x; + const N: float64 = y; + /* Make the calculation */ + const r_: float64 = LambertConical2SP.sign(this._n) * + Math.sqrt(LambertConical2SP.square(E - this._eF) + LambertConical2SP.square(this._rF - (N - this._nF))); + const t_: float64 = Math.pow(r_ / (this._a * this._F), 1.0 / this._n); + const theta_: float64 = Math.atan((E - this._eF) / (this._rF - (N - this._nF))); + let lat: float64 = LambertConical2SP.PI * 0.5 - 2.0 * Math.atan(t_); + const he: float64 = 0.5 * this._e; + for (let i: number = 0; i < 7; i++) { // double-checked iteration count. LER, 24/11/2011 + const eSin: float64 = this._e * Math.sin(lat); + lat = LambertConical2SP.hPI - 2.0 * Math.atan(t_ * Math.pow((1.0 - eSin) / (1.0 + eSin), he)); // recursive formula } + const lon: float64 = theta_ / this._n + this._lonF; + /* Save the position */ + geographic.setX(lon); + geographic.setY(lat); + } + + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + this.initializeProjection(operation.getSourceCRS().getEllipsoid()); + } + + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + /* Do the projection */ + this.toProjection(lon, lat, target); + target.setZ(source.getZ()); // Keep the Z value + } + + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Do the inverse projection */ + this.toGeoGraphic(E, N, source); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/Mercator1SP.ts b/core/orbitgt/src/spatial/ecrs/projection/Mercator1SP.ts index 169fab98adc7..9e6227b6ea4a 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/Mercator1SP.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/Mercator1SP.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs.projection; +// package orbitgt.spatial.ecrs.projection; type int8 = number; type int16 = number; @@ -42,96 +42,96 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class Mercator1SP extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9804; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9804; - /** The value of PI/4 */ - private static readonly QPI: float64 = Math.PI / 4.0; + /** The value of PI/4 */ + private static readonly QPI: float64 = Math.PI / 4.0; - /** Latitude of natural origin */ - private _latN: float64; - /** Longitude of natural origin (the central meridian) */ - private _lonN: float64; - /** Scale factor at natural origin */ - private _k0: float64; - /** False easting */ - private _fE: float64; - /** False northing */ - private _fN: float64; + /** Latitude of natural origin */ + private _latN: float64; + /** Longitude of natural origin (the central meridian) */ + private _lonN: float64; + /** Scale factor at natural origin */ + private _k0: float64; + /** False easting */ + private _fE: float64; + /** False northing */ + private _fN: float64; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(Mercator1SP.METHOD_CODE, "Mercator (1SP)", parameters); - /* Store the parameters */ - this._latN = (parameters != null) ? parameters.getValue2(8801, 0.0) : 0.0; - this._lonN = (parameters != null) ? parameters.getValue2(8802, 0.0) : 0.0; - this._k0 = (parameters != null) ? parameters.getValue2(8805, 1.0) : 1.0; - this._fE = (parameters != null) ? parameters.getValue2(8806, 0.0) : 0.0; - this._fN = (parameters != null) ? parameters.getValue2(8807, 0.0) : 0.0; - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(Mercator1SP.METHOD_CODE, "Mercator (1SP)", parameters); + /* Store the parameters */ + this._latN = (parameters != null) ? parameters.getValue2(8801, 0.0) : 0.0; + this._lonN = (parameters != null) ? parameters.getValue2(8802, 0.0) : 0.0; + this._k0 = (parameters != null) ? parameters.getValue2(8805, 1.0) : 1.0; + this._fE = (parameters != null) ? parameters.getValue2(8806, 0.0) : 0.0; + this._fN = (parameters != null) ? parameters.getValue2(8807, 0.0) : 0.0; + } - /** - * Create a new projection. - * @param latN latitude of natural origin. - * @param lonN longitude of natural origin (the central meridian). - * @param k0 scale factor at natural origin. - * @param fE false easting. - * @param fN false northing. - * @return the projection. - */ - public static create(latN: float64, lonN: float64, k0: float64, fE: float64, fN: float64): Mercator1SP { - let projection: Mercator1SP = new Mercator1SP(null); - projection._latN = latN; - projection._lonN = lonN; - projection._k0 = k0; - projection._fE = fE; - projection._fN = fN; - return projection; - } + /** + * Create a new projection. + * @param latN latitude of natural origin. + * @param lonN longitude of natural origin (the central meridian). + * @param k0 scale factor at natural origin. + * @param fE false easting. + * @param fN false northing. + * @return the projection. + */ + public static create(latN: float64, lonN: float64, k0: float64, fE: float64, fN: float64): Mercator1SP { + let projection: Mercator1SP = new Mercator1SP(null); + projection._latN = latN; + projection._lonN = lonN; + projection._k0 = k0; + projection._fE = fE; + projection._fN = fN; + return projection; + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the geographic parameters (radians) */ - let lon: float64 = source.getX(); - let lat: float64 = source.getY(); - /* Get the radius of the sphere */ - let R: float64 = sourceCRS.getEllipsoid().getA(); - /* Calculate easting */ - let E: float64 = this._fE + R * (lon - this._lonN); - /* Calculate northing */ - let sin: float64 = Math.sin(lat); - let N: float64 = this._fN + 0.5 * R * Math.log((1.0 + sin) / (1.0 - sin)); - // double N = this._fN+R*Math.log(Math.tan(QPI+0.5*lat)); - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the geographic parameters (radians) */ + let lon: float64 = source.getX(); + let lat: float64 = source.getY(); + /* Get the radius of the sphere */ + let R: float64 = sourceCRS.getEllipsoid().getA(); + /* Calculate easting */ + let E: float64 = this._fE + R * (lon - this._lonN); + /* Calculate northing */ + let sin: float64 = Math.sin(lat); + let N: float64 = this._fN + 0.5 * R * Math.log((1.0 + sin) / (1.0 - sin)); + // double N = this._fN+R*Math.log(Math.tan(QPI+0.5*lat)); + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - let E: float64 = target.getX(); - let N: float64 = target.getY(); - /* Get the radius of the sphere */ - let R: float64 = sourceCRS.getEllipsoid().getA(); - /* Calculate longitude */ - let lon: float64 = ((E - this._fE) / R) + this._lonN; - /* Calculate latitude */ - let D: float64 = (this._fN - N) / R; - let lat: float64 = 2.0 * (Mercator1SP.QPI - Math.atan(Math.exp(D))); - /* Save the position */ - source.setX(lon); - source.setY(lat); - source.setZ(target.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + let E: float64 = target.getX(); + let N: float64 = target.getY(); + /* Get the radius of the sphere */ + let R: float64 = sourceCRS.getEllipsoid().getA(); + /* Calculate longitude */ + let lon: float64 = ((E - this._fE) / R) + this._lonN; + /* Calculate latitude */ + let D: float64 = (this._fN - N) / R; + let lat: float64 = 2.0 * (Mercator1SP.QPI - Math.atan(Math.exp(D))); + /* Save the position */ + source.setX(lon); + source.setY(lat); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/ObliqueMercator.ts b/core/orbitgt/src/spatial/ecrs/projection/ObliqueMercator.ts index b366132359db..185c71b40365 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/ObliqueMercator.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/ObliqueMercator.ts @@ -39,181 +39,183 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class ObliqueMercator extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9815; // Hotine Variant B + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9815; // Hotine Variant B - /** The value of PI */ - private static readonly PI: float64 = Math.PI; + /** The value of PI */ + private static readonly PI: float64 = Math.PI; - /** Latitude of the projection center */ - private _latC: float64; - /** Longitude of the projection center */ - private _lonC: float64; - /** Azimuth of the initial line passing through the projection center */ - private _aziC: float64; - /** Angle from the recified grid to the skew (oblique) grid */ - private _gamC: float64; - /** Scale factor on the initial line of projection */ - private _kC: float64; - /** False easting at the center of projection */ - private _eC: float64; - /** False northing at the center of projection */ - private _nC: float64; + /** Latitude of the projection center */ + private _latC: float64; + /** Longitude of the projection center */ + private _lonC: float64; + /** Azimuth of the initial line passing through the projection center */ + private _aziC: float64; + /** Angle from the recified grid to the skew (oblique) grid */ + private _gamC: float64; + /** Scale factor on the initial line of projection */ + private _kC: float64; + /** False easting at the center of projection */ + private _eC: float64; + /** False northing at the center of projection */ + private _nC: float64; - /** Forward calculation parameters */ - private _a: float64; - private _e: float64; - private _e2: float64; - private _B: float64; - private _A: float64; - private _tO: float64; - private _D: float64; - private _F: float64; - private _H: float64; - private _G: float64; - private _gamO: float64; - private _lonO: float64; - private _vC: float64; - private _uC: float64; - /** Reverse calculation parameters */ - private _rev1: float64; - private _rev2: float64; - private _rev3: float64; - private _rev4: float64; + /** Forward calculation parameters */ + private _a: float64; + private _e: float64; + private _e2: float64; + private _B: float64; + private _A: float64; + private _tO: float64; + private _D: float64; + private _F: float64; + private _H: float64; + private _G: float64; + private _gamO: float64; + private _lonO: float64; + private _vC: float64; + private _uC: float64; + /** Reverse calculation parameters */ + private _rev1: float64; + private _rev2: float64; + private _rev3: float64; + private _rev4: float64; - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(ObliqueMercator.METHOD_CODE, "Oblique Mercator", parameters); - /* Store the parameters */ - this._latC = parameters.getValue(8811); - this._lonC = parameters.getValue(8812); - this._aziC = parameters.getValue(8813); - this._gamC = parameters.getValue(8814); - this._kC = parameters.getValue(8815); - this._eC = parameters.getValue(8816); - this._nC = parameters.getValue(8817); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(ObliqueMercator.METHOD_CODE, "Oblique Mercator", parameters); + /* Store the parameters */ + this._latC = parameters.getValue(8811); + this._lonC = parameters.getValue(8812); + this._aziC = parameters.getValue(8813); + this._gamC = parameters.getValue(8814); + this._kC = parameters.getValue(8815); + this._eC = parameters.getValue(8816); + this._nC = parameters.getValue(8817); + } - /** - * Get the sign of a number. - */ - private static sign(v: float64): float64 { - return (v < 0.0) ? (-1.0) : (1.0); - } + /** + * Get the sign of a number. + */ + private static sign(v: float64): float64 { + return (v < 0.0) ? (-1.0) : (1.0); + } - /** - * Get the power of a number (must be able to handle negative 'n' values). - */ - private static pow(n: float64, e: int32): float64 { - let p: float64 = 1.0; - for (let i: number = 0; i < e; i++) p *= n; - return p; - } + /** + * Get the power of a number (must be able to handle negative 'n' values). + */ + private static pow(n: float64, e: int32): float64 { + let p: float64 = 1.0; + for (let i: number = 0; i < e; i++) p *= n; + return p; + } - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - /* Get the ellipsoid */ - const sourceCRS: CRS = operation.getSourceCRS(); - /* Prepare the forward parameters */ - this._a = sourceCRS.getEllipsoid().getA(); - this._e = sourceCRS.getEllipsoid().getE(); - this._e2 = this._e * this._e; - this._B = Math.sqrt(1.0 + (this._e2 * ObliqueMercator.pow(Math.cos(this._latC), 4) / (1.0 - this._e2))); - const esinLatC: float64 = this._e * Math.sin(this._latC); - this._A = this._a * this._B * this._kC * Math.sqrt(1.0 - this._e2) / (1.0 - ObliqueMercator.pow(esinLatC, 2)); - this._tO = Math.tan(ObliqueMercator.PI / 4.0 - this._latC / 2.0) / Math.pow((1.0 - esinLatC) / (1.0 + esinLatC), this._e / 2.0); - this._D = this._B * Math.sqrt(1.0 - this._e2) / (Math.cos(this._latC) * Math.sqrt(1.0 - ObliqueMercator.pow(esinLatC, 2))); - const D2: float64 = (this._D < 1.0) ? (1.0) : (this._D * this._D); - this._F = this._D + Math.sqrt(D2 - 1.0) * ObliqueMercator.sign(this._latC); - this._H = this._F * Math.pow(this._tO, this._B); - this._G = (this._F - 1.0 / this._F) / 2.0; - this._gamO = Math.asin(Math.sin(this._aziC) / this._D); - // fix for Switzerland CRS 2056 projection error. LER, 19/06/2018 - let w: float64 = this._G * Math.tan(this._gamO); - if (Math.abs(1.0 - w) < 1.0e-13) w = 1.0; // Math.asin(0.9999999999999999) gives a 1.49e-8 difference from the asin(1.0) value, which leads to a 19 cm projection error - // this._lonO = lonC-Math.asin(G*Math.tan(gamO))/B; - this._lonO = this._lonC - Math.asin(w) / this._B; - // end of fix - this._vC = 0.0; - if (Math.abs(this._aziC - 0.5 * ObliqueMercator.PI) < 1.0e-12) this._uC = this._A * (this._lonC - this._lonO); // special case aziC==90 (Hungary, Switzerland) - else this._uC = (this._A / this._B) * Math.atan(Math.sqrt(D2 - 1.0) / Math.cos(this._aziC)) * ObliqueMercator.sign(this._latC); - /* Prepare the reverse parameters */ - const e4: float64 = this._e2 * this._e2; - const e6: float64 = e4 * this._e2; - const e8: float64 = e4 * e4; - this._rev1 = (this._e2 / 2.0 + 5.0 * e4 / 24.0 + e6 / 12.0 + 13.0 * e8 / 360.0); - this._rev2 = (7.0 * e4 / 48.0 + 29.0 * e6 / 240.0 + 811.0 * e8 / 11520.0); - this._rev3 = (7.0 * e6 / 120.0 + 81.0 * e8 / 1120.0); - this._rev4 = (4279.0 * e8 / 161280.0); - } + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + /* Get the ellipsoid */ + const sourceCRS: CRS = operation.getSourceCRS(); + /* Prepare the forward parameters */ + this._a = sourceCRS.getEllipsoid().getA(); + this._e = sourceCRS.getEllipsoid().getE(); + this._e2 = this._e * this._e; + this._B = Math.sqrt(1.0 + (this._e2 * ObliqueMercator.pow(Math.cos(this._latC), 4) / (1.0 - this._e2))); + const esinLatC: float64 = this._e * Math.sin(this._latC); + this._A = this._a * this._B * this._kC * Math.sqrt(1.0 - this._e2) / (1.0 - ObliqueMercator.pow(esinLatC, 2)); + this._tO = Math.tan(ObliqueMercator.PI / 4.0 - this._latC / 2.0) / Math.pow((1.0 - esinLatC) / (1.0 + esinLatC), this._e / 2.0); + this._D = this._B * Math.sqrt(1.0 - this._e2) / (Math.cos(this._latC) * Math.sqrt(1.0 - ObliqueMercator.pow(esinLatC, 2))); + const D2: float64 = (this._D < 1.0) ? (1.0) : (this._D * this._D); + this._F = this._D + Math.sqrt(D2 - 1.0) * ObliqueMercator.sign(this._latC); + this._H = this._F * Math.pow(this._tO, this._B); + this._G = (this._F - 1.0 / this._F) / 2.0; + this._gamO = Math.asin(Math.sin(this._aziC) / this._D); + // fix for Switzerland CRS 2056 projection error. LER, 19/06/2018 + let w: float64 = this._G * Math.tan(this._gamO); + if (Math.abs(1.0 - w) < 1.0e-13) w = 1.0; // Math.asin(0.9999999999999999) gives a 1.49e-8 difference from the asin(1.0) value, which leads to a 19 cm projection error + // this._lonO = lonC-Math.asin(G*Math.tan(gamO))/B; + this._lonO = this._lonC - Math.asin(w) / this._B; + // end of fix + this._vC = 0.0; + if (Math.abs(this._aziC - 0.5 * ObliqueMercator.PI) < 1.0e-12) this._uC = this._A * (this._lonC - this._lonO); // special case aziC==90 (Hungary, Switzerland) + else this._uC = (this._A / this._B) * Math.atan(Math.sqrt(D2 - 1.0) / Math.cos(this._aziC)) * ObliqueMercator.sign(this._latC); + /* Prepare the reverse parameters */ + const e4: float64 = this._e2 * this._e2; + const e6: float64 = e4 * this._e2; + const e8: float64 = e4 * e4; + this._rev1 = this._e2 / 2.0 + 5.0 * e4 / 24.0 + e6 / 12.0 + 13.0 * e8 / 360.0; + this._rev2 = 7.0 * e4 / 48.0 + 29.0 * e6 / 240.0 + 811.0 * e8 / 11520.0; + this._rev3 = 7.0 * e6 / 120.0 + 81.0 * e8 / 1120.0; + this._rev4 = 4279.0 * e8 / 161280.0; + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters (radians) */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - /* Make the calculation */ - const esinLat: float64 = this._e * Math.sin(lat); - const t: float64 = Math.tan(ObliqueMercator.PI / 4.0 - lat / 2.0) / Math.pow((1.0 - esinLat) / (1.0 + esinLat), this._e / 2.0); - const Q: float64 = this._H / Math.pow(t, this._B); - const S: float64 = (Q - 1.0 / Q) / 2.0; - const T: float64 = (Q + 1.0 / Q) / 2.0; - const V: float64 = Math.sin(this._B * (lon - this._lonO)); - const U: float64 = (-V * Math.cos(this._gamO) + S * Math.sin(this._gamO)) / T; - const v: float64 = this._A * Math.log((1.0 - U) / (1.0 + U)) / (2.0 * this._B); - let u: float64; - if (Math.abs(this._aziC - 0.5 * ObliqueMercator.PI) < 1.0e-12) // aziC==90? new in guidance note 2 version 8.5. LER, 21/09/2016 - { - if (lon == this._lonC) u = 0.0; - else u = (this._A * Math.atan((S * Math.cos(this._gamO) + V * Math.sin(this._gamO)) / Math.cos(this._B * (lon - this._lonO))) / this._B) - (Math.abs(this._uC) * ObliqueMercator.sign(this._latC) * ObliqueMercator.sign(this._lonC - lon)); - } else { - u = (this._A * Math.atan((S * Math.cos(this._gamO) + V * Math.sin(this._gamO)) / Math.cos(this._B * (lon - this._lonO))) / this._B) - (Math.abs(this._uC) * ObliqueMercator.sign(this._latC)); - } - const sinGamC: float64 = Math.sin(this._gamC); - const cosGamC: float64 = Math.cos(this._gamC); - const E: float64 = v * cosGamC + u * sinGamC + this._eC; - const N: float64 = u * cosGamC - v * sinGamC + this._nC; - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters (radians) */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + /* Make the calculation */ + const esinLat: float64 = this._e * Math.sin(lat); + const t: float64 = Math.tan(ObliqueMercator.PI / 4.0 - lat / 2.0) / Math.pow((1.0 - esinLat) / (1.0 + esinLat), this._e / 2.0); + const Q: float64 = this._H / Math.pow(t, this._B); + const S: float64 = (Q - 1.0 / Q) / 2.0; + const T: float64 = (Q + 1.0 / Q) / 2.0; + const V: float64 = Math.sin(this._B * (lon - this._lonO)); + const U: float64 = (-V * Math.cos(this._gamO) + S * Math.sin(this._gamO)) / T; + const v: float64 = this._A * Math.log((1.0 - U) / (1.0 + U)) / (2.0 * this._B); + let u: float64; + if (Math.abs(this._aziC - 0.5 * ObliqueMercator.PI) < 1.0e-12) { // aziC==90? new in guidance note 2 version 8.5. LER, 21/09/2016 + if (lon == this._lonC) u = 0.0; + else u = (this._A * Math.atan((S * Math.cos(this._gamO) + V * Math.sin(this._gamO)) / Math.cos(this._B * (lon - this._lonO))) / this._B) - + (Math.abs(this._uC) * ObliqueMercator.sign(this._latC) * ObliqueMercator.sign(this._lonC - lon)); + } else { + u = (this._A * Math.atan((S * Math.cos(this._gamO) + V * Math.sin(this._gamO)) / Math.cos(this._B * (lon - this._lonO))) / this._B) - + (Math.abs(this._uC) * ObliqueMercator.sign(this._latC)); } + const sinGamC: float64 = Math.sin(this._gamC); + const cosGamC: float64 = Math.cos(this._gamC); + const E: float64 = v * cosGamC + u * sinGamC + this._eC; + const N: float64 = u * cosGamC - v * sinGamC + this._nC; + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Make the calculation */ - const sinGamC: float64 = Math.sin(this._gamC); - const cosGamC: float64 = Math.cos(this._gamC); - const v: float64 = (E - this._eC) * cosGamC - (N - this._nC) * sinGamC; - const u: float64 = (N - this._nC) * cosGamC + (E - this._eC) * sinGamC + (Math.abs(this._uC) * ObliqueMercator.sign(this._latC)); - const Q: float64 = Math.exp(-this._B * v / this._A); - const S: float64 = (Q - 1.0 / Q) / 2.0; - const T: float64 = (Q + 1.0 / Q) / 2.0; - const V: float64 = Math.sin(this._B * u / this._A); - const U: float64 = (V * Math.cos(this._gamO) + S * Math.sin(this._gamO)) / T; - const t: float64 = Math.pow(this._H / Math.sqrt((1.0 + U) / (1.0 - U)), 1.0 / this._B); - const chi: float64 = ObliqueMercator.PI / 2.0 - 2.0 * Math.atan(t); - const lat: float64 = chi + Math.sin(2.0 * chi) * this._rev1 + Math.sin(4.0 * chi) * this._rev2 + Math.sin(6.0 * chi) * this._rev3 + Math.sin(8.0 * chi) * this._rev4; - // double lon = lonO-Math.atan((S*Math.cos(gamO)-V*Math.sin(gamO))/Math.cos(B*u/A))/B; - const lon: float64 = this._lonO - Math.atan2((S * Math.cos(this._gamO) - V * Math.sin(this._gamO)), Math.cos(this._B * u / this._A)) / this._B; // replaced atan(y/x) by atan2(y,x). LER, 23/05/2017 - /* Save the position */ - source.setX(lon); - source.setY(lat); - source.setZ(target.getZ()); // Keep the Z value - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Make the calculation */ + const sinGamC: float64 = Math.sin(this._gamC); + const cosGamC: float64 = Math.cos(this._gamC); + const v: float64 = (E - this._eC) * cosGamC - (N - this._nC) * sinGamC; + const u: float64 = (N - this._nC) * cosGamC + (E - this._eC) * sinGamC + (Math.abs(this._uC) * ObliqueMercator.sign(this._latC)); + const Q: float64 = Math.exp(-this._B * v / this._A); + const S: float64 = (Q - 1.0 / Q) / 2.0; + const T: float64 = (Q + 1.0 / Q) / 2.0; + const V: float64 = Math.sin(this._B * u / this._A); + const U: float64 = (V * Math.cos(this._gamO) + S * Math.sin(this._gamO)) / T; + const t: float64 = Math.pow(this._H / Math.sqrt((1.0 + U) / (1.0 - U)), 1.0 / this._B); + const chi: float64 = ObliqueMercator.PI / 2.0 - 2.0 * Math.atan(t); + const lat: float64 = chi + Math.sin(2.0 * chi) * this._rev1 + Math.sin(4.0 * chi) * this._rev2 + Math.sin(6.0 * chi) * this._rev3 + + Math.sin(8.0 * chi) * this._rev4; + // double lon = lonO-Math.atan((S*Math.cos(gamO)-V*Math.sin(gamO))/Math.cos(B*u/A))/B; + const lon: float64 = this._lonO - Math.atan2(S * Math.cos(this._gamO) - V * Math.sin(this._gamO), Math.cos(this._B * u / this._A)) / this._B; // replaced atan(y/x) by atan2(y,x). LER, 23/05/2017 + /* Save the position */ + source.setX(lon); + source.setY(lat); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/ObliqueStereographic.ts b/core/orbitgt/src/spatial/ecrs/projection/ObliqueStereographic.ts index 5eba7fe4de47..309bd769b849 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/ObliqueStereographic.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/ObliqueStereographic.ts @@ -40,216 +40,224 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class ObliqueStereographic extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9809; - - /** The value of PI */ - private static readonly PI: float64 = Math.PI; - - /** Latitude of false origin */ - private _lat0: float64; - /** Longitude of false origin */ - private _lon0: float64; - /** Scale factor at natural origin */ - private _k0: float64; - /** False easting */ - private _fe: float64; - /** False northing */ - private _fn: float64; - - /** The parameters for the conformal sphere */ - private _e: float64; - private _e2: float64; - private _R: float64; - private _n: float64; - private _c: float64; - private _chi0: float64; - private _lambda0: float64; - private _g: float64; - private _h: float64; - - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(ObliqueStereographic.METHOD_CODE, "Oblique Stereographic", parameters); - /* Store the parameters */ - this._lat0 = (parameters != null) ? parameters.getValue(8801) : 0.0; - this._lon0 = (parameters != null) ? parameters.getValue(8802) : 0.0; - this._k0 = (parameters != null) ? parameters.getValue(8805) : 0.0; - this._fe = (parameters != null) ? parameters.getValue(8806) : 0.0; - this._fn = (parameters != null) ? parameters.getValue(8807) : 0.0; - } + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9809; - /** - * Create a new projection. - * @param lat0 latitude of natural origin (radians). - * @param lon0 longitude of natural origin (radians). - * @param k0 scale factor at natural origin. - * @param fe false easting. - * @param fn false northing. - */ - public static create(lat0: float64, lon0: float64, k0: float64, fe: float64, fn: float64): ObliqueStereographic { - const projection: ObliqueStereographic = new ObliqueStereographic(null); - projection._lat0 = lat0; - projection._lon0 = lon0; - projection._k0 = k0; - projection._fe = fe; - projection._fn = fn; - return projection; - } + /** The value of PI */ + private static readonly PI: float64 = Math.PI; - /** - * Get the power of a number. - */ - private static pow(n: float64, e: float64): float64 { - return Math.exp(e * Math.log(n)); - } + /** Latitude of false origin */ + private _lat0: float64; + /** Longitude of false origin */ + private _lon0: float64; + /** Scale factor at natural origin */ + private _k0: float64; + /** False easting */ + private _fe: float64; + /** False northing */ + private _fn: float64; - /** - * Calculate sinus. - */ - private static sin(a: float64): float64 { - return Math.sin(a); - } + /** The parameters for the conformal sphere */ + private _e: float64; + private _e2: float64; + private _R: float64; + private _n: float64; + private _c: float64; + private _chi0: float64; + private _lambda0: float64; + private _g: float64; + private _h: float64; - /** - * Calculate cosinus. - */ - private static cos(a: float64): float64 { - return Math.cos(a); - } + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(ObliqueStereographic.METHOD_CODE, "Oblique Stereographic", parameters); + /* Store the parameters */ + this._lat0 = (parameters != null) ? parameters.getValue(8801) : 0.0; + this._lon0 = (parameters != null) ? parameters.getValue(8802) : 0.0; + this._k0 = (parameters != null) ? parameters.getValue(8805) : 0.0; + this._fe = (parameters != null) ? parameters.getValue(8806) : 0.0; + this._fn = (parameters != null) ? parameters.getValue(8807) : 0.0; + } - /** - * Calculate tangent. - */ - private static tan(a: float64): float64 { - return Math.tan(a); - } + /** + * Create a new projection. + * @param lat0 latitude of natural origin (radians). + * @param lon0 longitude of natural origin (radians). + * @param k0 scale factor at natural origin. + * @param fe false easting. + * @param fn false northing. + */ + public static create(lat0: float64, lon0: float64, k0: float64, fe: float64, fn: float64): ObliqueStereographic { + const projection: ObliqueStereographic = new ObliqueStereographic(null); + projection._lat0 = lat0; + projection._lon0 = lon0; + projection._k0 = k0; + projection._fe = fe; + projection._fn = fn; + return projection; + } - /** - * Calculate arcsinus. - */ - private static asin(v: float64): float64 { - return Math.asin(v); - } + /** + * Get the power of a number. + */ + private static pow(n: float64, e: float64): float64 { + return Math.exp(e * Math.log(n)); + } - /** - * Calculate arctangent. - */ - private static atan(v: float64): float64 { - return Math.atan(v); - } + /** + * Calculate sinus. + */ + private static sin(a: float64): float64 { + return Math.sin(a); + } - /** - * Calculate log. - */ - private static log(v: float64): float64 { - return Math.log(v); - } + /** + * Calculate cosinus. + */ + private static cos(a: float64): float64 { + return Math.cos(a); + } - /** - * Calculate exp. - */ - private static exp(v: float64): float64 { - return Math.exp(v); - } + /** + * Calculate tangent. + */ + private static tan(a: float64): float64 { + return Math.tan(a); + } - /** - * Initialize the projection. - * @param ellipsoid the ellipsoid to use. - * @return this projection (for convenience). - */ - public initializeProjection(ellipsoid: Ellipsoid): ObliqueStereographic { - /* Get the ellipsoid parameters */ - const a: float64 = ellipsoid.getA(); - this._e = ellipsoid.getE(); - /* Calculate conformat latitude (chi0) and longitude (lambda0) */ - this._e2 = this._e * this._e; - const sinLat0: float64 = ObliqueStereographic.sin(this._lat0); - const t0: float64 = 1.0 - this._e2 * sinLat0 * sinLat0; - const rho0: float64 = a * (1 - this._e2) / ObliqueStereographic.pow(t0, 1.5); - const nu0: float64 = a / ObliqueStereographic.pow(t0, 0.5); - this._R = ObliqueStereographic.pow(rho0 * nu0, 0.5); - this._n = ObliqueStereographic.pow(1.0 + (this._e2 * ObliqueStereographic.pow(ObliqueStereographic.cos(this._lat0), 4)) / (1.0 - this._e2), 0.5); - const S1: float64 = (1.0 + sinLat0) / (1.0 - sinLat0); - const S2: float64 = (1.0 - this._e * sinLat0) / (1.0 + this._e * sinLat0); - const w1: float64 = ObliqueStereographic.pow(S1 * ObliqueStereographic.pow(S2, this._e), this._n); - const sinChi0: float64 = (w1 - 1.0) / (w1 + 1.0); - this._c = (this._n + sinLat0) * (1.0 - sinChi0) / ((this._n - sinLat0) * (1.0 + sinChi0)); - const w2: float64 = this._c * w1; - this._chi0 = ObliqueStereographic.asin((w2 - 1.0) / (w2 + 1.0)); - this._lambda0 = this._lon0; - /* For reverse calculation */ - this._g = 2.0 * this._R * this._k0 * ObliqueStereographic.tan(ObliqueStereographic.PI / 4.0 - this._chi0 / 2.0); - this._h = 4.0 * this._R * this._k0 * ObliqueStereographic.tan(this._chi0) + this._g; - /* Return the projection */ - return this; - } + /** + * Calculate arcsinus. + */ + private static asin(v: float64): float64 { + return Math.asin(v); + } - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - this.initializeProjection(operation.getSourceCRS().getEllipsoid()); - } + /** + * Calculate arctangent. + */ + private static atan(v: float64): float64 { + return Math.atan(v); + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - const sinLat: float64 = ObliqueStereographic.sin(lat); - /* Calculate conformal latitude and longitude */ - const lambda: float64 = this._n * (lon - this._lambda0) + this._lambda0; - const Sa: float64 = (1.0 + sinLat) / (1.0 - sinLat); - const Sb: float64 = (1.0 - this._e * sinLat) / (1.0 + this._e * sinLat); - const w: float64 = this._c * ObliqueStereographic.pow(Sa * ObliqueStereographic.pow(Sb, this._e), this._n); - const chi: float64 = ObliqueStereographic.asin((w - 1.0) / (w + 1.0)); - /* Calculate easting and northing */ - const B: float64 = 1.0 + ObliqueStereographic.sin(chi) * ObliqueStereographic.sin(this._chi0) + ObliqueStereographic.cos(chi) * ObliqueStereographic.cos(this._chi0) * ObliqueStereographic.cos(lambda - this._lambda0); - const E: float64 = this._fe + 2.0 * this._R * this._k0 * ObliqueStereographic.cos(chi) * ObliqueStereographic.sin(lambda - this._lambda0) / B; - const N: float64 = this._fn + 2.0 * this._R * this._k0 * (ObliqueStereographic.sin(chi) * ObliqueStereographic.cos(this._chi0) - ObliqueStereographic.cos(chi) * ObliqueStereographic.sin(this._chi0) * ObliqueStereographic.cos(lambda - this._lambda0)) / B; - /* Save the position */ - target.setX(E); - target.setY(N); - target.setZ(source.getZ()); // Keep the Z value - } + /** + * Calculate log. + */ + private static log(v: float64): float64 { + return Math.log(v); + } + + /** + * Calculate exp. + */ + private static exp(v: float64): float64 { + return Math.exp(v); + } + + /** + * Initialize the projection. + * @param ellipsoid the ellipsoid to use. + * @return this projection (for convenience). + */ + public initializeProjection(ellipsoid: Ellipsoid): ObliqueStereographic { + /* Get the ellipsoid parameters */ + const a: float64 = ellipsoid.getA(); + this._e = ellipsoid.getE(); + /* Calculate conformat latitude (chi0) and longitude (lambda0) */ + this._e2 = this._e * this._e; + const sinLat0: float64 = ObliqueStereographic.sin(this._lat0); + const t0: float64 = 1.0 - this._e2 * sinLat0 * sinLat0; + const rho0: float64 = a * (1 - this._e2) / ObliqueStereographic.pow(t0, 1.5); + const nu0: float64 = a / ObliqueStereographic.pow(t0, 0.5); + this._R = ObliqueStereographic.pow(rho0 * nu0, 0.5); + this._n = ObliqueStereographic.pow(1.0 + (this._e2 * ObliqueStereographic.pow(ObliqueStereographic.cos(this._lat0), 4)) / (1.0 - this._e2), 0.5); + const S1: float64 = (1.0 + sinLat0) / (1.0 - sinLat0); + const S2: float64 = (1.0 - this._e * sinLat0) / (1.0 + this._e * sinLat0); + const w1: float64 = ObliqueStereographic.pow(S1 * ObliqueStereographic.pow(S2, this._e), this._n); + const sinChi0: float64 = (w1 - 1.0) / (w1 + 1.0); + this._c = (this._n + sinLat0) * (1.0 - sinChi0) / ((this._n - sinLat0) * (1.0 + sinChi0)); + const w2: float64 = this._c * w1; + this._chi0 = ObliqueStereographic.asin((w2 - 1.0) / (w2 + 1.0)); + this._lambda0 = this._lon0; + /* For reverse calculation */ + this._g = 2.0 * this._R * this._k0 * ObliqueStereographic.tan(ObliqueStereographic.PI / 4.0 - this._chi0 / 2.0); + this._h = 4.0 * this._R * this._k0 * ObliqueStereographic.tan(this._chi0) + this._g; + /* Return the projection */ + return this; + } + + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + this.initializeProjection(operation.getSourceCRS().getEllipsoid()); + } + + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + const sinLat: float64 = ObliqueStereographic.sin(lat); + /* Calculate conformal latitude and longitude */ + const lambda: float64 = this._n * (lon - this._lambda0) + this._lambda0; + const Sa: float64 = (1.0 + sinLat) / (1.0 - sinLat); + const Sb: float64 = (1.0 - this._e * sinLat) / (1.0 + this._e * sinLat); + const w: float64 = this._c * ObliqueStereographic.pow(Sa * ObliqueStereographic.pow(Sb, this._e), this._n); + const chi: float64 = ObliqueStereographic.asin((w - 1.0) / (w + 1.0)); + /* Calculate easting and northing */ + const B: float64 = 1.0 + ObliqueStereographic.sin(chi) * ObliqueStereographic.sin(this._chi0) + + ObliqueStereographic.cos(chi) * ObliqueStereographic.cos(this._chi0) * ObliqueStereographic.cos(lambda - this._lambda0); + const E: float64 = this._fe + 2.0 * this._R * this._k0 * ObliqueStereographic.cos(chi) * ObliqueStereographic.sin(lambda - this._lambda0) / B; + const N: float64 = this._fn + + 2.0 * this._R * this._k0 * + (ObliqueStereographic.sin(chi) * ObliqueStereographic.cos(this._chi0) - + ObliqueStereographic.cos(chi) * ObliqueStereographic.sin(this._chi0) * ObliqueStereographic.cos(lambda - this._lambda0)) / + B; + /* Save the position */ + target.setX(E); + target.setY(N); + target.setZ(source.getZ()); // Keep the Z value + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const E: float64 = target.getX() - this._fe; - const N: float64 = target.getY() - this._fn; - /* Calculate conformal latitude and longitude */ - const i: float64 = ObliqueStereographic.atan(E / (this._h + N)); - const j: float64 = ObliqueStereographic.atan(E / (this._g - N)) - i; - const chi: float64 = this._chi0 + 2.0 * ObliqueStereographic.atan((N - E * ObliqueStereographic.tan(j / 2.0)) / (2.0 * this._R * this._k0)); - const lambda: float64 = j + 2.0 * i + this._lambda0; - const lon: float64 = (lambda - this._lambda0) / this._n + this._lambda0; - /* Iterate to get isometric (psi) and geodetic (phi) latitude */ - const sinChi: float64 = ObliqueStereographic.sin(chi); - const psi: float64 = 0.5 * ObliqueStereographic.log((1.0 + sinChi) / (this._c * (1.0 - sinChi))) / this._n; - let phiK: float64 = 2.0 * ObliqueStereographic.atan(ObliqueStereographic.exp(psi)) - ObliqueStereographic.PI / 2.0; - for (let k: number = 1; k < 8; k++) { - const esinPhi: float64 = this._e * ObliqueStereographic.sin(phiK); - const psiK: float64 = ObliqueStereographic.log(ObliqueStereographic.tan(phiK / 2.0 + ObliqueStereographic.PI / 4.0) * ObliqueStereographic.pow((1.0 - esinPhi) / (1.0 + esinPhi), this._e / 2.0)); - const phiNextK: float64 = phiK - (psiK - psi) * ObliqueStereographic.cos(phiK) * (1.0 - esinPhi * esinPhi) / (1.0 - this._e2); - const change: float64 = Math.abs(phiNextK - phiK); - phiK = phiNextK; - if (change < 1.0e-12) break; // normally after 4 iterations - } - /* Save the position */ - source.setX(lon); - source.setY(phiK); - source.setZ(target.getZ()); // Keep the Z value + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const E: float64 = target.getX() - this._fe; + const N: float64 = target.getY() - this._fn; + /* Calculate conformal latitude and longitude */ + const i: float64 = ObliqueStereographic.atan(E / (this._h + N)); + const j: float64 = ObliqueStereographic.atan(E / (this._g - N)) - i; + const chi: float64 = this._chi0 + 2.0 * ObliqueStereographic.atan((N - E * ObliqueStereographic.tan(j / 2.0)) / (2.0 * this._R * this._k0)); + const lambda: float64 = j + 2.0 * i + this._lambda0; + const lon: float64 = (lambda - this._lambda0) / this._n + this._lambda0; + /* Iterate to get isometric (psi) and geodetic (phi) latitude */ + const sinChi: float64 = ObliqueStereographic.sin(chi); + const psi: float64 = 0.5 * ObliqueStereographic.log((1.0 + sinChi) / (this._c * (1.0 - sinChi))) / this._n; + let phiK: float64 = 2.0 * ObliqueStereographic.atan(ObliqueStereographic.exp(psi)) - ObliqueStereographic.PI / 2.0; + for (let k: number = 1; k < 8; k++) { + const esinPhi: float64 = this._e * ObliqueStereographic.sin(phiK); + const psiK: float64 = ObliqueStereographic.log( + ObliqueStereographic.tan(phiK / 2.0 + ObliqueStereographic.PI / 4.0) * + ObliqueStereographic.pow((1.0 - esinPhi) / (1.0 + esinPhi), this._e / 2.0), + ); + const phiNextK: float64 = phiK - (psiK - psi) * ObliqueStereographic.cos(phiK) * (1.0 - esinPhi * esinPhi) / (1.0 - this._e2); + const change: float64 = Math.abs(phiNextK - phiK); + phiK = phiNextK; + if (change < 1.0e-12) break; // normally after 4 iterations } + /* Save the position */ + source.setX(lon); + source.setY(phiK); + source.setZ(target.getZ()); // Keep the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/projection/TransverseMercator.ts b/core/orbitgt/src/spatial/ecrs/projection/TransverseMercator.ts index e8552708534a..120114db48a4 100644 --- a/core/orbitgt/src/spatial/ecrs/projection/TransverseMercator.ts +++ b/core/orbitgt/src/spatial/ecrs/projection/TransverseMercator.ts @@ -40,190 +40,198 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class TransverseMercator extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9807; - - /** The value of PI */ - private static readonly PI: float64 = Math.PI; - - /** Latitude of natural origin (radians) */ - private _latN: float64; - /** Longitude of natural origin (the central meridian) (radians) */ - private _lonN: float64; - /** The scale factor at the natural origin */ - private _k0: float64; - /** False easting */ - private _fE: float64; - /** False northing */ - private _fN: float64; - - /** Forward calculation parameters */ - private _a: float64; - private _e: float64; - private _e2: float64; - private _e4: float64; - private _e6: float64; - private _e_2: float64; - private _m0: float64; - /** Reverse calculation parameters */ - private _e1: float64; - private _R1: float64; - private _R2: float64; - private _R3: float64; - private _R4: float64; - - /** - * Create a new projection. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(TransverseMercator.METHOD_CODE, "Transverse Mercator", parameters); - /* Store the parameters */ - this._latN = parameters.getValue(8801); - this._lonN = parameters.getValue(8802); - this._k0 = parameters.getValue(8805); - this._fE = parameters.getValue(8806); - this._fN = parameters.getValue(8807); - } - - /** - * Get the power of a number (must be able to handle negative 'n' values). - */ - private static pow(n: float64, e: int32): float64 { - let p: float64 = 1.0; - for (let i: number = 0; i < e; i++) p *= n; - return p; - } - - /** - * Calculate M. - */ - private calcM(lat: float64): float64 { - const M: float64 = lat * (1.0 - this._e2 / 4 - 3 * this._e4 / 64 - 5 * this._e6 / 256) - Math.sin(2.0 * lat) * (3 * this._e2 / 8 + 3 * this._e4 / 32 + 45 * this._e6 / 1024) + Math.sin(4.0 * lat) * (15 * this._e4 / 256 + 45 * this._e6 / 1024) - Math.sin(6.0 * lat) * (35 * this._e6 / 3072); - return this._a * M; - } - - /** - * Initialize the projection. - * @param ellipsoid the ellipsoid to use. - * @return this projection (for convenience). - */ - public initializeProjection(ellipsoid: Ellipsoid): TransverseMercator { - /* Prepare the forward parameters */ - this._a = ellipsoid.getA(); - this._e = ellipsoid.getE(); - this._e2 = this._e * this._e; - this._e4 = this._e2 * this._e2; - this._e6 = this._e2 * this._e4; - this._e_2 = this._e2 / (1.0 - this._e2); - this._m0 = this.calcM(this._latN); - /* Prepare the reverse parameters */ - const temp: float64 = Math.sqrt(1 - this._e2); - this._e1 = (1.0 - temp) / (1.0 + temp); - const e1_2: float64 = this._e1 * this._e1; - const e1_3: float64 = this._e1 * e1_2; - const e1_4: float64 = e1_2 * e1_2; - this._R1 = (3 * this._e1 / 2 - 27 * e1_3 / 32); - this._R2 = (21 * e1_2 / 16 - 55 * e1_4 / 32); - this._R3 = (151 * e1_3 / 96); - this._R4 = (1097 * e1_4 / 512); - /* Return the projection */ - return this; - } - - /** - * Do the projection. - * @param lon the longitude (radians). - * @param lat the latitude (radians). - * @param projected the target projected coordinate (X and Y will be set). - */ - public toProjection(lon: float64, lat: float64, projected: Coordinate): void { - /* Calculate parameters */ - const tan: float64 = Math.tan(lat); - const T: float64 = tan * tan; - const cos: float64 = Math.cos(lat); - const C: float64 = this._e2 * cos * cos / (1.0 - this._e2); - const A: float64 = (lon - this._lonN) * cos; - const eSin: float64 = this._e * Math.sin(lat); - const v: float64 = this._a / Math.sqrt(1.0 - eSin * eSin); - const m: float64 = this.calcM(lat); - /* Make the calculation */ - const temp1: float64 = A + (1.0 - T + C) * TransverseMercator.pow(A, 3) / 6 + (5 - 18 * T + T * T + 72 * C - 58 * this._e_2) * TransverseMercator.pow(A, 5) / 120.0; - const E: float64 = this._fE + this._k0 * v * (temp1); - const temp2: float64 = m - this._m0 + v * tan * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * TransverseMercator.pow(A, 4) / 24.0 + (61 - 58 * T + T * T + 600 * C - 330 * this._e_2) * TransverseMercator.pow(A, 6) / 720.0); - const N: float64 = this._fN + this._k0 * (temp2); - /* Save the position */ - projected.setX(E); - projected.setY(N); - } - - /** - * Do the inverse projection. - * @param x the easting. - * @param y the northing. - * @param geographic the target geographic coordinate (X/Lon and Y/Lat will be set) (radians). - */ - public toGeoGraphic(x: float64, y: float64, geographic: Coordinate): void { - /* Get the parameters */ - const E: float64 = x; - const N: float64 = y; - /* Calculate parameters */ - const m1: float64 = this._m0 + (N - this._fN) / this._k0; - const u1: float64 = m1 / (this._a * (1.0 - this._e2 / 4 - 3 * this._e4 / 64 - 5 * this._e6 / 256)); - const lat1: float64 = u1 + this._R1 * Math.sin(2 * u1) + this._R2 * Math.sin(4 * u1) + this._R3 * Math.sin(6 * u1) + this._R4 * Math.sin(8 * u1); - const eSin1: float64 = this._e * Math.sin(lat1); - const temp: float64 = Math.sqrt(1.0 - eSin1 * eSin1); - const v1: float64 = this._a / temp; - const rho1: float64 = this._a * (1.0 - this._e2) / TransverseMercator.pow(temp, 3); - const tan: float64 = Math.tan(lat1); - const T1: float64 = tan * tan; - const T1_2: float64 = T1 * T1; - const cos: float64 = Math.cos(lat1); - const C1: float64 = this._e_2 * cos * cos; - const C1_2: float64 = C1 * C1; - const D: float64 = (E - this._fE) / (v1 * this._k0); - const D_2: float64 = D * D; - /* Make the calculation */ - const temp1: float64 = D_2 / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1_2 - 9 * this._e_2) * TransverseMercator.pow(D, 4) / 24.0 + (61 + 90 * T1 + 298 * C1 + 45 * T1_2 - 252 * this._e_2 - 3 * C1_2) * TransverseMercator.pow(D, 6) / 720.0; - const lat: float64 = lat1 - (v1 * tan / rho1) * (temp1); - const temp2: float64 = D - (1 + 2 * T1 + C1) * TransverseMercator.pow(D, 3) / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1_2 + 8 * this._e_2 + 24 * T1_2) * TransverseMercator.pow(D, 5) / 120; - const lon: float64 = this._lonN + (temp2) / cos; - /* Save the position */ - geographic.setX(lon); - geographic.setY(lat); - } - - /** - * OperationMethod method. - * @see OperationMethod#initialize - */ - public override initialize(operation: Operation): void { - this.initializeProjection(operation.getSourceCRS().getEllipsoid()); // should this use getTargetCRS? (while testing OSTN15 RoI) - } - - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const lon: float64 = source.getX(); - const lat: float64 = source.getY(); - /* Do the projection */ - this.toProjection(lon, lat, target); - target.setZ(source.getZ()); // Copy the Z value - } - - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - /* Get the parameters */ - const E: float64 = target.getX(); - const N: float64 = target.getY(); - /* Do the inverse projection */ - this.toGeoGraphic(E, N, source); - source.setZ(target.getZ()); // Copy the Z value - } + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9807; + + /** The value of PI */ + private static readonly PI: float64 = Math.PI; + + /** Latitude of natural origin (radians) */ + private _latN: float64; + /** Longitude of natural origin (the central meridian) (radians) */ + private _lonN: float64; + /** The scale factor at the natural origin */ + private _k0: float64; + /** False easting */ + private _fE: float64; + /** False northing */ + private _fN: float64; + + /** Forward calculation parameters */ + private _a: float64; + private _e: float64; + private _e2: float64; + private _e4: float64; + private _e6: float64; + private _e_2: float64; + private _m0: float64; + /** Reverse calculation parameters */ + private _e1: float64; + private _R1: float64; + private _R2: float64; + private _R3: float64; + private _R4: float64; + + /** + * Create a new projection. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(TransverseMercator.METHOD_CODE, "Transverse Mercator", parameters); + /* Store the parameters */ + this._latN = parameters.getValue(8801); + this._lonN = parameters.getValue(8802); + this._k0 = parameters.getValue(8805); + this._fE = parameters.getValue(8806); + this._fN = parameters.getValue(8807); + } + + /** + * Get the power of a number (must be able to handle negative 'n' values). + */ + private static pow(n: float64, e: int32): float64 { + let p: float64 = 1.0; + for (let i: number = 0; i < e; i++) p *= n; + return p; + } + + /** + * Calculate M. + */ + private calcM(lat: float64): float64 { + const M: float64 = lat * (1.0 - this._e2 / 4 - 3 * this._e4 / 64 - 5 * this._e6 / 256) - + Math.sin(2.0 * lat) * (3 * this._e2 / 8 + 3 * this._e4 / 32 + 45 * this._e6 / 1024) + + Math.sin(4.0 * lat) * (15 * this._e4 / 256 + 45 * this._e6 / 1024) - Math.sin(6.0 * lat) * (35 * this._e6 / 3072); + return this._a * M; + } + + /** + * Initialize the projection. + * @param ellipsoid the ellipsoid to use. + * @return this projection (for convenience). + */ + public initializeProjection(ellipsoid: Ellipsoid): TransverseMercator { + /* Prepare the forward parameters */ + this._a = ellipsoid.getA(); + this._e = ellipsoid.getE(); + this._e2 = this._e * this._e; + this._e4 = this._e2 * this._e2; + this._e6 = this._e2 * this._e4; + this._e_2 = this._e2 / (1.0 - this._e2); + this._m0 = this.calcM(this._latN); + /* Prepare the reverse parameters */ + const temp: float64 = Math.sqrt(1 - this._e2); + this._e1 = (1.0 - temp) / (1.0 + temp); + const e1_2: float64 = this._e1 * this._e1; + const e1_3: float64 = this._e1 * e1_2; + const e1_4: float64 = e1_2 * e1_2; + this._R1 = 3 * this._e1 / 2 - 27 * e1_3 / 32; + this._R2 = 21 * e1_2 / 16 - 55 * e1_4 / 32; + this._R3 = 151 * e1_3 / 96; + this._R4 = 1097 * e1_4 / 512; + /* Return the projection */ + return this; + } + + /** + * Do the projection. + * @param lon the longitude (radians). + * @param lat the latitude (radians). + * @param projected the target projected coordinate (X and Y will be set). + */ + public toProjection(lon: float64, lat: float64, projected: Coordinate): void { + /* Calculate parameters */ + const tan: float64 = Math.tan(lat); + const T: float64 = tan * tan; + const cos: float64 = Math.cos(lat); + const C: float64 = this._e2 * cos * cos / (1.0 - this._e2); + const A: float64 = (lon - this._lonN) * cos; + const eSin: float64 = this._e * Math.sin(lat); + const v: float64 = this._a / Math.sqrt(1.0 - eSin * eSin); + const m: float64 = this.calcM(lat); + /* Make the calculation */ + const temp1: float64 = A + (1.0 - T + C) * TransverseMercator.pow(A, 3) / 6 + + (5 - 18 * T + T * T + 72 * C - 58 * this._e_2) * TransverseMercator.pow(A, 5) / 120.0; + const E: float64 = this._fE + this._k0 * v * temp1; + const temp2: float64 = m - this._m0 + + v * tan * + (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * TransverseMercator.pow(A, 4) / 24.0 + + (61 - 58 * T + T * T + 600 * C - 330 * this._e_2) * TransverseMercator.pow(A, 6) / 720.0); + const N: float64 = this._fN + this._k0 * temp2; + /* Save the position */ + projected.setX(E); + projected.setY(N); + } + + /** + * Do the inverse projection. + * @param x the easting. + * @param y the northing. + * @param geographic the target geographic coordinate (X/Lon and Y/Lat will be set) (radians). + */ + public toGeoGraphic(x: float64, y: float64, geographic: Coordinate): void { + /* Get the parameters */ + const E: float64 = x; + const N: float64 = y; + /* Calculate parameters */ + const m1: float64 = this._m0 + (N - this._fN) / this._k0; + const u1: float64 = m1 / (this._a * (1.0 - this._e2 / 4 - 3 * this._e4 / 64 - 5 * this._e6 / 256)); + const lat1: float64 = u1 + this._R1 * Math.sin(2 * u1) + this._R2 * Math.sin(4 * u1) + this._R3 * Math.sin(6 * u1) + this._R4 * Math.sin(8 * u1); + const eSin1: float64 = this._e * Math.sin(lat1); + const temp: float64 = Math.sqrt(1.0 - eSin1 * eSin1); + const v1: float64 = this._a / temp; + const rho1: float64 = this._a * (1.0 - this._e2) / TransverseMercator.pow(temp, 3); + const tan: float64 = Math.tan(lat1); + const T1: float64 = tan * tan; + const T1_2: float64 = T1 * T1; + const cos: float64 = Math.cos(lat1); + const C1: float64 = this._e_2 * cos * cos; + const C1_2: float64 = C1 * C1; + const D: float64 = (E - this._fE) / (v1 * this._k0); + const D_2: float64 = D * D; + /* Make the calculation */ + const temp1: float64 = D_2 / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1_2 - 9 * this._e_2) * TransverseMercator.pow(D, 4) / 24.0 + + (61 + 90 * T1 + 298 * C1 + 45 * T1_2 - 252 * this._e_2 - 3 * C1_2) * TransverseMercator.pow(D, 6) / 720.0; + const lat: float64 = lat1 - (v1 * tan / rho1) * temp1; + const temp2: float64 = D - (1 + 2 * T1 + C1) * TransverseMercator.pow(D, 3) / 6 + + (5 - 2 * C1 + 28 * T1 - 3 * C1_2 + 8 * this._e_2 + 24 * T1_2) * TransverseMercator.pow(D, 5) / 120; + const lon: float64 = this._lonN + temp2 / cos; + /* Save the position */ + geographic.setX(lon); + geographic.setY(lat); + } + + /** + * OperationMethod method. + * @see OperationMethod#initialize + */ + public override initialize(operation: Operation): void { + this.initializeProjection(operation.getSourceCRS().getEllipsoid()); // should this use getTargetCRS? (while testing OSTN15 RoI) + } + + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const lon: float64 = source.getX(); + const lat: float64 = source.getY(); + /* Do the projection */ + this.toProjection(lon, lat, target); + target.setZ(source.getZ()); // Copy the Z value + } + + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + /* Get the parameters */ + const E: float64 = target.getX(); + const N: float64 = target.getY(); + /* Do the inverse projection */ + this.toGeoGraphic(E, N, source); + source.setZ(target.getZ()); // Copy the Z value + } } diff --git a/core/orbitgt/src/spatial/ecrs/transformation/PositionVector.ts b/core/orbitgt/src/spatial/ecrs/transformation/PositionVector.ts index 2f3cfef1b302..fd11d3374174 100644 --- a/core/orbitgt/src/spatial/ecrs/transformation/PositionVector.ts +++ b/core/orbitgt/src/spatial/ecrs/transformation/PositionVector.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.ecrs.transformation; +// package orbitgt.spatial.ecrs.transformation; type int8 = number; type int16 = number; @@ -38,120 +38,120 @@ import { ParameterValueList } from "../ParameterValueList"; */ /** @internal */ export class PositionVector extends OperationMethod { - /** The code of this method */ - public static readonly METHOD_CODE: int32 = 9606; + /** The code of this method */ + public static readonly METHOD_CODE: int32 = 9606; - /** The translation vector */ - private _dX: float64; - private _dY: float64; - private _dZ: float64; - /** The rotations (radians) */ - private _rX: float64; - private _rY: float64; - private _rZ: float64; - /** The scale factor (offset from 1.0) */ - private _dS: float64; + /** The translation vector */ + private _dX: float64; + private _dY: float64; + private _dZ: float64; + /** The rotations (radians) */ + private _rX: float64; + private _rY: float64; + private _rZ: float64; + /** The scale factor (offset from 1.0) */ + private _dS: float64; - /** - * Create a new transformation. - * @param parameters the values of the parameters. - */ - public constructor(parameters: ParameterValueList) { - super(PositionVector.METHOD_CODE, "Position Vector 7-param. transformation", parameters); - /* Store the parameters */ - this._dX = parameters.getValue(8605); - this._dY = parameters.getValue(8606); - this._dZ = parameters.getValue(8607); - this._rX = parameters.getValue(8608); - this._rY = parameters.getValue(8609); - this._rZ = parameters.getValue(8610); - this._dS = parameters.getValue(8611); - } + /** + * Create a new transformation. + * @param parameters the values of the parameters. + */ + public constructor(parameters: ParameterValueList) { + super(PositionVector.METHOD_CODE, "Position Vector 7-param. transformation", parameters); + /* Store the parameters */ + this._dX = parameters.getValue(8605); + this._dY = parameters.getValue(8606); + this._dZ = parameters.getValue(8607); + this._rX = parameters.getValue(8608); + this._rY = parameters.getValue(8609); + this._rZ = parameters.getValue(8610); + this._dS = parameters.getValue(8611); + } - /** - * Create a new transformation. - * @param dX the translation vector x. - * @param dY the translation vector y. - * @param dZ the translation vector z. - * @param rX the first rotation (radians). - * @param rY the second rotation (radians). - * @param rZ the third rotation (radians). - * @param dS the scale factor (offset from 1.0) (normal units, not ppm). - * @return the new transformation. - */ - public static create(dX: float64, dY: float64, dZ: float64, rX: float64, rY: float64, rZ: float64, dS: float64): PositionVector { - let parameters: ParameterValueList = new ParameterValueList(); - parameters.add(new ParameterValue(8605, dX, null)); - parameters.add(new ParameterValue(8606, dY, null)); - parameters.add(new ParameterValue(8607, dZ, null)); - parameters.add(new ParameterValue(8608, rX, null)); - parameters.add(new ParameterValue(8609, rY, null)); - parameters.add(new ParameterValue(8610, rZ, null)); - parameters.add(new ParameterValue(8611, dS, null)); - return new PositionVector(parameters); - } + /** + * Create a new transformation. + * @param dX the translation vector x. + * @param dY the translation vector y. + * @param dZ the translation vector z. + * @param rX the first rotation (radians). + * @param rY the second rotation (radians). + * @param rZ the third rotation (radians). + * @param dS the scale factor (offset from 1.0) (normal units, not ppm). + * @return the new transformation. + */ + public static create(dX: float64, dY: float64, dZ: float64, rX: float64, rY: float64, rZ: float64, dS: float64): PositionVector { + let parameters: ParameterValueList = new ParameterValueList(); + parameters.add(new ParameterValue(8605, dX, null)); + parameters.add(new ParameterValue(8606, dY, null)); + parameters.add(new ParameterValue(8607, dZ, null)); + parameters.add(new ParameterValue(8608, rX, null)); + parameters.add(new ParameterValue(8609, rY, null)); + parameters.add(new ParameterValue(8610, rZ, null)); + parameters.add(new ParameterValue(8611, dS, null)); + return new PositionVector(parameters); + } - /** - * Get the 7 parameters of the method. - * @return the parameters of the method {dX,dY,dZ,rX,rY,rZ,dS} in units {meter,meter,meter, radian,radian,radian, scale_offset-1}. - */ - public getParameters(): Float64Array { - let parameters: Float64Array = new Float64Array(7); - parameters[0] = this._dX; - parameters[1] = this._dY; - parameters[2] = this._dZ; - parameters[3] = this._rX; - parameters[4] = this._rY; - parameters[5] = this._rZ; - parameters[6] = this._dS; - return parameters; - } + /** + * Get the 7 parameters of the method. + * @return the parameters of the method {dX,dY,dZ,rX,rY,rZ,dS} in units {meter,meter,meter, radian,radian,radian, scale_offset-1}. + */ + public getParameters(): Float64Array { + let parameters: Float64Array = new Float64Array(7); + parameters[0] = this._dX; + parameters[1] = this._dY; + parameters[2] = this._dZ; + parameters[3] = this._rX; + parameters[4] = this._rY; + parameters[5] = this._rZ; + parameters[6] = this._dS; + return parameters; + } - /** - * Make a forward transformation. - * @param source the source coordinate (the coordinate to transform). - * @param target the target coordinate (holds the result). - */ - public transformForward(source: Coordinate, target: Coordinate): void { - let x: float64 = source.getX(); - let y: float64 = source.getY(); - let z: float64 = source.getZ(); - let m: float64 = (1.0 + this._dS); - target.setX(m * (1.0 * x - this._rZ * y + this._rY * z) + this._dX); - target.setY(m * (this._rZ * x + 1.0 * y - this._rX * z) + this._dY); - target.setZ(m * (-this._rY * x + this._rX * y + 1.0 * z) + this._dZ); - } + /** + * Make a forward transformation. + * @param source the source coordinate (the coordinate to transform). + * @param target the target coordinate (holds the result). + */ + public transformForward(source: Coordinate, target: Coordinate): void { + let x: float64 = source.getX(); + let y: float64 = source.getY(); + let z: float64 = source.getZ(); + let m: float64 = 1.0 + this._dS; + target.setX(m * (1.0 * x - this._rZ * y + this._rY * z) + this._dX); + target.setY(m * (this._rZ * x + 1.0 * y - this._rX * z) + this._dY); + target.setZ(m * (-this._rY * x + this._rX * y + 1.0 * z) + this._dZ); + } - /** - * Make a reverse transformation. - * @param source the source coordinate (holds the result). - * @param target the target coordinate (the coordinate to transform). - */ - public transformReverse(source: Coordinate, target: Coordinate): void { - this.createInverse().transformForward(target, source); - } + /** + * Make a reverse transformation. + * @param source the source coordinate (holds the result). + * @param target the target coordinate (the coordinate to transform). + */ + public transformReverse(source: Coordinate, target: Coordinate): void { + this.createInverse().transformForward(target, source); + } - /** - * OperationMethod interface method. - * @see OperationMethod#forward - */ - public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - this.transformForward(source, target); - } + /** + * OperationMethod interface method. + * @see OperationMethod#forward + */ + public forward(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + this.transformForward(source, target); + } - /** - * OperationMethod interface method. - * @see OperationMethod#reverse - */ - public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { - this.transformReverse(source, target); - } + /** + * OperationMethod interface method. + * @see OperationMethod#reverse + */ + public reverse(sourceCRS: CRS, source: Coordinate, targetCRS: CRS, target: Coordinate): void { + this.transformReverse(source, target); + } - /** - * Create an inverse transformation. - * @return the inverse transformation. - */ - public createInverse(): PositionVector { - return PositionVector.create(-this._dX, -this._dY, -this._dZ, -this._rX, -this._rY, -this._rZ, -this._dS); - } + /** + * Create an inverse transformation. + * @return the inverse transformation. + */ + public createInverse(): PositionVector { + return PositionVector.create(-this._dX, -this._dY, -this._dZ, -this._rX, -this._rY, -this._rZ, -this._dS); + } } diff --git a/core/orbitgt/src/spatial/geom/Bounds.ts b/core/orbitgt/src/spatial/geom/Bounds.ts index cfcfee50f053..cb2428a4088e 100644 --- a/core/orbitgt/src/spatial/geom/Bounds.ts +++ b/core/orbitgt/src/spatial/geom/Bounds.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.geom; +// package orbitgt.spatial.geom; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { Coordinate } from "./Coordinate"; /** @@ -22,140 +21,142 @@ import { Coordinate } from "./Coordinate"; */ /** @internal */ export class Bounds { - public valid: boolean; - public min: Coordinate; - public max: Coordinate; - - public constructor() { - this.valid = false; - this.min = Coordinate.create(); - this.max = Coordinate.create(); - } - - public clear(): void { - this.valid = false; - this.min.clear(); - this.max.clear(); - } - - public isValid(): boolean { - return this.valid; - } - - public getMinX(): float64 { - return this.min.x; - } - - public getMinY(): float64 { - return this.min.y; - } - - public getMinZ(): float64 { - return this.min.z; - } - - public getMaxX(): float64 { - return this.max.x; - } - - public getMaxY(): float64 { - return this.max.y; - } - - public getMaxZ(): float64 { - return this.max.z; - } - - public addXYZ(x: float64, y: float64, z: float64): Bounds { - if (this.valid == false) { - this.min.x = x; - this.min.y = y; - this.min.z = z; - this.max.x = x; - this.max.y = y; - this.max.z = z; - this.valid = true; - } - else { - if (x < this.min.x) this.min.x = x; - if (y < this.min.y) this.min.y = y; - if (z < this.min.z) this.min.z = z; - if (x > this.max.x) this.max.x = x; - if (y > this.max.y) this.max.y = y; - if (z > this.max.z) this.max.z = z; - } - return this; - } - - public add(c: Coordinate): Bounds { - return this.addXYZ(c.x, c.y, c.z); - } - - public containsXYZ(x: float64, y: float64, z: float64): boolean { - if (this.valid == false) return false; - if (x < this.min.x) return false; - if (y < this.min.y) return false; - if (z < this.min.z) return false; - if (x > this.max.x) return false; - if (y > this.max.y) return false; - if (z > this.max.z) return false; - return true; - } - - public contains(c: Coordinate): boolean { - return this.containsXYZ(c.x, c.y, c.z); - } - - public hasOverlapXYZ(x1: float64, y1: float64, z1: float64, x2: float64, y2: float64, z2: float64): boolean { - if (this.valid == false) return false; - let minX: float64 = Math.min(x1, x2); - let minY: float64 = Math.min(y1, y2); - let minZ: float64 = Math.min(z1, z2); - let maxX: float64 = Math.max(x1, x2); - let maxY: float64 = Math.max(y1, y2); - let maxZ: float64 = Math.max(z1, z2); - return ((maxX >= this.min.x) && (minX <= this.max.x) && (maxY >= this.min.y) && (minY <= this.max.y) && (maxZ >= this.min.z) && (minZ <= this.max.z)); - } - - public getCorner(index: int32, point: Coordinate): void { - point.setX(((index & 1) == 0) ? this.min.x : this.max.x); - point.setY(((index & 2) == 0) ? this.min.y : this.max.y); - point.setZ(((index & 4) == 0) ? this.min.z : this.max.z); - } - - public getIntersection(other: Bounds): Bounds { - /* Define the intersection */ - let intersection: Bounds = new Bounds(); - /* Both boxes should be valid */ - if (this.valid == false) return intersection; - if (other.valid == false) return intersection; - /* Intersect X */ - let minX: float64 = Math.max(this.min.x, other.min.x); - let maxX: float64 = Math.min(this.max.x, other.max.x); - if (minX > maxX) return intersection; - /* Intersect Y */ - let minY: float64 = Math.max(this.min.y, other.min.y); - let maxY: float64 = Math.min(this.max.y, other.max.y); - if (minY > maxY) return intersection; - /* Intersect Z */ - let minZ: float64 = Math.max(this.min.z, other.min.z); - let maxZ: float64 = Math.min(this.max.z, other.max.z); - if (minZ > maxZ) return intersection; - /* Empty? */ - if ((minX == maxX) && (minY == maxY) && (minZ == maxZ)) return intersection; - /* Return the intersection */ - intersection.valid = true; - intersection.min.x = minX; - intersection.max.x = maxX; - intersection.min.y = minY; - intersection.max.y = maxY; - intersection.min.z = minZ; - intersection.max.z = maxZ; - return intersection; - } - - public toString(): string { - if (this.valid) return "(min:" + this.min.x + "," + this.min.y + "," + this.min.z + ",max:" + this.max.x + "," + this.max.y + "," + this.max.z + ")"; - else return "(invalid)"; - } + public valid: boolean; + public min: Coordinate; + public max: Coordinate; + + public constructor() { + this.valid = false; + this.min = Coordinate.create(); + this.max = Coordinate.create(); + } + + public clear(): void { + this.valid = false; + this.min.clear(); + this.max.clear(); + } + + public isValid(): boolean { + return this.valid; + } + + public getMinX(): float64 { + return this.min.x; + } + + public getMinY(): float64 { + return this.min.y; + } + + public getMinZ(): float64 { + return this.min.z; + } + + public getMaxX(): float64 { + return this.max.x; + } + + public getMaxY(): float64 { + return this.max.y; + } + + public getMaxZ(): float64 { + return this.max.z; + } + + public addXYZ(x: float64, y: float64, z: float64): Bounds { + if (this.valid == false) { + this.min.x = x; + this.min.y = y; + this.min.z = z; + this.max.x = x; + this.max.y = y; + this.max.z = z; + this.valid = true; + } + else { + if (x < this.min.x) this.min.x = x; + if (y < this.min.y) this.min.y = y; + if (z < this.min.z) this.min.z = z; + if (x > this.max.x) this.max.x = x; + if (y > this.max.y) this.max.y = y; + if (z > this.max.z) this.max.z = z; + } + return this; + } + + public add(c: Coordinate): Bounds { + return this.addXYZ(c.x, c.y, c.z); + } + + public containsXYZ(x: float64, y: float64, z: float64): boolean { + if (this.valid == false) return false; + if (x < this.min.x) return false; + if (y < this.min.y) return false; + if (z < this.min.z) return false; + if (x > this.max.x) return false; + if (y > this.max.y) return false; + if (z > this.max.z) return false; + return true; + } + + public contains(c: Coordinate): boolean { + return this.containsXYZ(c.x, c.y, c.z); + } + + public hasOverlapXYZ(x1: float64, y1: float64, z1: float64, x2: float64, y2: float64, z2: float64): boolean { + if (this.valid == false) return false; + let minX: float64 = Math.min(x1, x2); + let minY: float64 = Math.min(y1, y2); + let minZ: float64 = Math.min(z1, z2); + let maxX: float64 = Math.max(x1, x2); + let maxY: float64 = Math.max(y1, y2); + let maxZ: float64 = Math.max(z1, z2); + return ((maxX >= this.min.x) && (minX <= this.max.x) && (maxY >= this.min.y) && (minY <= this.max.y) && (maxZ >= this.min.z) && + (minZ <= this.max.z)); + } + + public getCorner(index: int32, point: Coordinate): void { + point.setX(((index & 1) == 0) ? this.min.x : this.max.x); + point.setY(((index & 2) == 0) ? this.min.y : this.max.y); + point.setZ(((index & 4) == 0) ? this.min.z : this.max.z); + } + + public getIntersection(other: Bounds): Bounds { + /* Define the intersection */ + let intersection: Bounds = new Bounds(); + /* Both boxes should be valid */ + if (this.valid == false) return intersection; + if (other.valid == false) return intersection; + /* Intersect X */ + let minX: float64 = Math.max(this.min.x, other.min.x); + let maxX: float64 = Math.min(this.max.x, other.max.x); + if (minX > maxX) return intersection; + /* Intersect Y */ + let minY: float64 = Math.max(this.min.y, other.min.y); + let maxY: float64 = Math.min(this.max.y, other.max.y); + if (minY > maxY) return intersection; + /* Intersect Z */ + let minZ: float64 = Math.max(this.min.z, other.min.z); + let maxZ: float64 = Math.min(this.max.z, other.max.z); + if (minZ > maxZ) return intersection; + /* Empty? */ + if ((minX == maxX) && (minY == maxY) && (minZ == maxZ)) return intersection; + /* Return the intersection */ + intersection.valid = true; + intersection.min.x = minX; + intersection.max.x = maxX; + intersection.min.y = minY; + intersection.max.y = maxY; + intersection.min.z = minZ; + intersection.max.z = maxZ; + return intersection; + } + + public toString(): string { + if (this.valid) + return "(min:" + this.min.x + "," + this.min.y + "," + this.min.z + ",max:" + this.max.x + "," + this.max.y + "," + this.max.z + ")"; + else return "(invalid)"; + } } diff --git a/core/orbitgt/src/spatial/geom/Coordinate.ts b/core/orbitgt/src/spatial/geom/Coordinate.ts index 9fa16ecf429e..5261c770caf3 100644 --- a/core/orbitgt/src/spatial/geom/Coordinate.ts +++ b/core/orbitgt/src/spatial/geom/Coordinate.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.geom; +// package orbitgt.spatial.geom; type int8 = number; type int16 = number; @@ -19,196 +19,196 @@ type float64 = number; */ /** @internal */ export class Coordinate { - public x: float64; - public y: float64; - public z: float64; - - public constructor(x: float64, y: float64, z: float64) { - this.x = x; - this.y = y; - this.z = z; - } - - public static create(): Coordinate { - return new Coordinate(0.0, 0.0, 0.0); - } - - public static fromXY(x: float64, y: float64): Coordinate { - return new Coordinate(x, y, 0.0); - } - - public static fromXYZ(x: float64, y: float64, z: float64): Coordinate { - return new Coordinate(x, y, z); - } - - public getX(): float64 { - return this.x; - } - - public setX(x: float64): void { - this.x = x; - } - - public getY(): float64 { - return this.y; - } - - public setY(y: float64): void { - this.y = y; - } - - public getZ(): float64 { - return this.z; - } - - public setZ(z: float64): void { - this.z = z; - } - - public set(point: Coordinate): void { - this.x = point.x; - this.y = point.y; - this.z = point.z; - } - - public setXYZ(x: float64, y: float64, z: float64): void { - this.x = x; - this.y = y; - this.z = z; - } - - public clear(): void { - this.x = 0.0; - this.y = 0.0; - this.z = 0.0; - } - - public isZero(): boolean { - return (this.x == 0.0) && (this.y == 0.0) && (this.z == 0.0); - } - - public isNonZero(): boolean { - return (this.isZero() == false); - } - - public same(other: Coordinate): boolean { - if (other.x != this.x) return false; - if (other.y != this.y) return false; - if (other.z != this.z) return false; - return true; - } - - public same2D(other: Coordinate): boolean { - if (other.x != this.x) return false; - if (other.y != this.y) return false; - return true; - } - - public distance3D(other: Coordinate): float64 { - let dx: float64 = (other.x - this.x); - let dy: float64 = (other.y - this.y); - let dz: float64 = (other.z - this.z); - return Math.sqrt(dx * dx + dy * dy + dz * dz); - } - - public distance2D(other: Coordinate): float64 { - let dx: float64 = (other.x - this.x); - let dy: float64 = (other.y - this.y); - return Math.sqrt(dx * dx + dy * dy); - } - - public getLength(): float64 { - return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); - } - - public normalize0(): Coordinate { - let len: float64 = this.getLength(); - if (len == 0.0) return this; - return this.scale0(1.0 / len); - } - public normalize(): Coordinate { - return this.copy().normalize0(); - } - - public copy(): Coordinate { - return new Coordinate(this.x, this.y, this.z); - } - - public add0(point: Coordinate): Coordinate { - this.x += point.x; - this.y += point.y; - this.z += point.z; - return this; - } - public add(point: Coordinate): Coordinate { - return this.copy().add0(point); - } - - public subtract0(point: Coordinate): Coordinate { - this.x -= point.x; - this.y -= point.y; - this.z -= point.z; - return this; - } - public subtract(point: Coordinate): Coordinate { - return this.copy().subtract0(point); - } - - public scale0(f: float64): Coordinate { - this.x *= f; - this.y *= f; - this.z *= f; - return this; - } - public scale(f: float64): Coordinate { - return this.copy().scale0(f); - } - - public crossProduct0(point: Coordinate): Coordinate { - let cx: float64 = (this.y * point.z) - (this.z * point.y); - let cy: float64 = (this.z * point.x) - (this.x * point.z); - let cz: float64 = (this.x * point.y) - (this.y * point.x); - this.x = cx; - this.y = cy; - this.z = cz; - return this; - } - public crossProduct(point: Coordinate): Coordinate { - return this.copy().crossProduct0(point); - } - - public dotProduct(point: Coordinate): float64 { - return (this.x * point.x) + (this.y * point.y) + (this.z * point.z); - } - - public toString(): string { - return "(" + this.x + "," + this.y + "," + this.z + ")"; - } - - /** - * Get the angle between two directions. - * @param direction1 the first direction. - * @param direction2 the second direction. - * @return the angle between the directions, in radians from 0.0 to PI (never negative). - */ - public static getAngleRad(direction1: Coordinate, direction2: Coordinate): float64 { - let length1: float64 = direction1.getLength(); - if (length1 == 0.0) return 0.0; - let length2: float64 = direction2.getLength(); - if (length2 == 0.0) return 0.0; - let cos: float64 = direction1.dotProduct(direction2) / length1 / length2; - if (cos >= 1.0) return 0.0; // avoid rounding issues like acos(1.0000000000000002) = NaN - if (cos <= -1.0) return Math.PI; - return Math.acos(cos); - } - - /** - * Get the angle between two directions. - * @param direction1 the first direction. - * @param direction2 the second direction. - * @return the angle between the directions, in degrees from 0.0 to 180.0 (never negative). - */ - public static getAngleDeg(direction1: Coordinate, direction2: Coordinate): float64 { - return Coordinate.getAngleRad(direction1, direction2) / Math.PI * 180.0; - } + public x: float64; + public y: float64; + public z: float64; + + public constructor(x: float64, y: float64, z: float64) { + this.x = x; + this.y = y; + this.z = z; + } + + public static create(): Coordinate { + return new Coordinate(0.0, 0.0, 0.0); + } + + public static fromXY(x: float64, y: float64): Coordinate { + return new Coordinate(x, y, 0.0); + } + + public static fromXYZ(x: float64, y: float64, z: float64): Coordinate { + return new Coordinate(x, y, z); + } + + public getX(): float64 { + return this.x; + } + + public setX(x: float64): void { + this.x = x; + } + + public getY(): float64 { + return this.y; + } + + public setY(y: float64): void { + this.y = y; + } + + public getZ(): float64 { + return this.z; + } + + public setZ(z: float64): void { + this.z = z; + } + + public set(point: Coordinate): void { + this.x = point.x; + this.y = point.y; + this.z = point.z; + } + + public setXYZ(x: float64, y: float64, z: float64): void { + this.x = x; + this.y = y; + this.z = z; + } + + public clear(): void { + this.x = 0.0; + this.y = 0.0; + this.z = 0.0; + } + + public isZero(): boolean { + return (this.x == 0.0) && (this.y == 0.0) && (this.z == 0.0); + } + + public isNonZero(): boolean { + return (this.isZero() == false); + } + + public same(other: Coordinate): boolean { + if (other.x != this.x) return false; + if (other.y != this.y) return false; + if (other.z != this.z) return false; + return true; + } + + public same2D(other: Coordinate): boolean { + if (other.x != this.x) return false; + if (other.y != this.y) return false; + return true; + } + + public distance3D(other: Coordinate): float64 { + let dx: float64 = other.x - this.x; + let dy: float64 = other.y - this.y; + let dz: float64 = other.z - this.z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); + } + + public distance2D(other: Coordinate): float64 { + let dx: float64 = other.x - this.x; + let dy: float64 = other.y - this.y; + return Math.sqrt(dx * dx + dy * dy); + } + + public getLength(): float64 { + return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); + } + + public normalize0(): Coordinate { + let len: float64 = this.getLength(); + if (len == 0.0) return this; + return this.scale0(1.0 / len); + } + public normalize(): Coordinate { + return this.copy().normalize0(); + } + + public copy(): Coordinate { + return new Coordinate(this.x, this.y, this.z); + } + + public add0(point: Coordinate): Coordinate { + this.x += point.x; + this.y += point.y; + this.z += point.z; + return this; + } + public add(point: Coordinate): Coordinate { + return this.copy().add0(point); + } + + public subtract0(point: Coordinate): Coordinate { + this.x -= point.x; + this.y -= point.y; + this.z -= point.z; + return this; + } + public subtract(point: Coordinate): Coordinate { + return this.copy().subtract0(point); + } + + public scale0(f: float64): Coordinate { + this.x *= f; + this.y *= f; + this.z *= f; + return this; + } + public scale(f: float64): Coordinate { + return this.copy().scale0(f); + } + + public crossProduct0(point: Coordinate): Coordinate { + let cx: float64 = (this.y * point.z) - (this.z * point.y); + let cy: float64 = (this.z * point.x) - (this.x * point.z); + let cz: float64 = (this.x * point.y) - (this.y * point.x); + this.x = cx; + this.y = cy; + this.z = cz; + return this; + } + public crossProduct(point: Coordinate): Coordinate { + return this.copy().crossProduct0(point); + } + + public dotProduct(point: Coordinate): float64 { + return (this.x * point.x) + (this.y * point.y) + (this.z * point.z); + } + + public toString(): string { + return "(" + this.x + "," + this.y + "," + this.z + ")"; + } + + /** + * Get the angle between two directions. + * @param direction1 the first direction. + * @param direction2 the second direction. + * @return the angle between the directions, in radians from 0.0 to PI (never negative). + */ + public static getAngleRad(direction1: Coordinate, direction2: Coordinate): float64 { + let length1: float64 = direction1.getLength(); + if (length1 == 0.0) return 0.0; + let length2: float64 = direction2.getLength(); + if (length2 == 0.0) return 0.0; + let cos: float64 = direction1.dotProduct(direction2) / length1 / length2; + if (cos >= 1.0) return 0.0; // avoid rounding issues like acos(1.0000000000000002) = NaN + if (cos <= -1.0) return Math.PI; + return Math.acos(cos); + } + + /** + * Get the angle between two directions. + * @param direction1 the first direction. + * @param direction2 the second direction. + * @return the angle between the directions, in degrees from 0.0 to 180.0 (never negative). + */ + public static getAngleDeg(direction1: Coordinate, direction2: Coordinate): float64 { + return Coordinate.getAngleRad(direction1, direction2) / Math.PI * 180.0; + } } diff --git a/core/orbitgt/src/spatial/geom/Line.ts b/core/orbitgt/src/spatial/geom/Line.ts index 550cb84e2595..c71224224f52 100644 --- a/core/orbitgt/src/spatial/geom/Line.ts +++ b/core/orbitgt/src/spatial/geom/Line.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.geom; +// package orbitgt.spatial.geom; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ASystem } from "../../system/runtime/ASystem"; import { Coordinate } from "./Coordinate"; @@ -25,447 +24,447 @@ import { Coordinate } from "./Coordinate"; */ /** @internal */ export class Line { - /** The start point */ - public p0: Coordinate; - /** The end point */ - public p1: Coordinate; - - /** - * Create a new line. - * @param p0 the start point. - * @param p1 the end point. - */ - public constructor(p0: Coordinate, p1: Coordinate) { - /* Store the points */ - this.p0 = p0; - this.p1 = p1; - } - - /** - * Create a new line. - * @return a new line. - */ - public static create(): Line { - return new Line(Coordinate.create(), Coordinate.create()); - } - - /** - * Create a new line. - * @param p0 the start point. - * @param p1 the end point. - */ - public static fromPoints(p0: Coordinate, p1: Coordinate): Line { - return new Line(p0, p1); - } - - /** - * Create a new line. - * @param x0 the x of the start point. - * @param y0 the y of the start point. - * @param z0 the z of the start point. - * @param x1 the x of the end point. - * @param y1 the y of the end point. - * @param z1 the z of the end point. - */ - public static fromXYZ(x0: float64, y0: float64, z0: float64, x1: float64, y1: float64, z1: float64): Line { - return new Line(new Coordinate(x0, y0, z0), new Coordinate(x1, y1, z1)); - } - - /** - * Get the start point. - * @return the start point. - */ - public getPoint0(): Coordinate { - return this.p0; - } - - /** - * Get the end point. - * @return the end point. - */ - public getPoint1(): Coordinate { - return this.p1; - } - - /** - * Get a point along the line. - * @param t the position of the point (0.0 at start and 1.0 at end). - * @return a point. - */ - public getPoint(t: float64): Coordinate { - /* Avoid rounding errors */ - if (t == 0.0) return this.p0; - if (t == 1.0) return this.p1; - /* Calculate a new point */ - let x: float64 = this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); - let y: float64 = this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); - let z: float64 = this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); - return new Coordinate(x, y, z); - } - - /** - * Get a point along the line. - * @param t the position of the point (0.0 at start and 1.0 at end). - * @param point the result point (must be mutable). - */ - public getPointTo(t: float64, point: Coordinate): void { - /* Start point? */ - if (t == 0.0) { - /* Copy */ - point.setXYZ(this.p0.getX(), this.p0.getY(), this.p0.getZ()); - } - /* End point? */ - else if (t == 1.0) { - /* Copy */ - point.setXYZ(this.p1.getX(), this.p1.getY(), this.p1.getZ()); - } - /* Intermediate point */ - else { - /* Calculate a new point */ - let x: float64 = this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); - let y: float64 = this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); - let z: float64 = this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); - point.setXYZ(x, y, z); - } - } - - /** - * Get the X coordinate of a point along the line. - * @param t the position of the point (0.0 at start and 1.0 at end). - * @return the coordinate. - */ - public getPointX(t: float64): float64 { - /* Start point? */ - if (t == 0.0) { - /* Copy */ - return this.p0.getX(); - } - /* End point? */ - else if (t == 1.0) { - /* Copy */ - return this.p1.getX(); - } - /* Intermediate point */ - else { - /* Calculate a new point */ - return this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); - } - } - - /** - * Get the Y coordinate of a point along the line. - * @param t the position of the point (0.0 at start and 1.0 at end). - * @return the coordinate. - */ - public getPointY(t: float64): float64 { - /* Start point? */ - if (t == 0.0) { - /* Copy */ - return this.p0.getY(); - } - /* End point? */ - else if (t == 1.0) { - /* Copy */ - return this.p1.getY(); - } - /* Intermediate point */ - else { - /* Calculate a new point */ - return this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); - } - } - - /** - * Get the Z coordinate of a point along the line. - * @param t the position of the point (0.0 at start and 1.0 at end). - * @return the coordinate. - */ - public getPointZ(t: float64): float64 { - /* Start point? */ - if (t == 0.0) { - /* Copy */ - return this.p0.getZ(); - } - /* End point? */ - else if (t == 1.0) { - /* Copy */ - return this.p1.getZ(); - } - /* Intermediate point */ - else { - /* Calculate a new point */ - return this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); - } - } - - /** - * Get a point along the line. - * @param d the distance of the point (0.0 at start). - * @return a point. - */ - public getPointAtDistance(d: float64): Coordinate { - return this.getPoint(d / this.getLength()); - } - - /** - * Get a point along the line. - * @param d the distance of the point (0.0 at start). - * @param point the result point (must be mutable). - */ - public getPointAtDistanceTo(d: float64, point: Coordinate): void { - this.getPointTo(d / this.getLength(), point); - } - - /** - * Get the position for a fixed x value. - * @param x the x value. - * @return the position on the line. - */ - public getPointAtX(x: float64): float64 { - return (x - this.p0.getX()) / (this.p1.getX() - this.p0.getX()); - } - - /** - * Get a point along the line. - * @param x the x value. - * @param point the result point (must be mutable). - */ - public getPointAtXTo(x: float64, point: Coordinate): void { - this.getPointTo(this.getPointAtX(x), point); - point.setX(x); - } - - /** - * Get the position for a fixed y value. - * @param y the y value. - * @return the position on the line. - */ - public getPointAtY(y: float64): float64 { - return (y - this.p0.getY()) / (this.p1.getY() - this.p0.getY()); - } - - /** - * Get a point along the line. - * @param y the y value. - * @param point the result point (must be mutable). - */ - public getPointAtYTo(y: float64, point: Coordinate): void { - this.getPointTo(this.getPointAtY(y), point); - point.setY(y); - } - - /** - * Get the position for a fixed z value. - * @param z the z value. - * @return the position on the line. - */ - public getPointAtZ(z: float64): float64 { - return (z - this.p0.getZ()) / (this.p1.getZ() - this.p0.getZ()); - } - - /** - * Get a point along the line. - * @param z the z value. - * @param point the result point (must be mutable). - */ - public getPointAtZTo(z: float64, point: Coordinate): void { - this.getPointTo(this.getPointAtZ(z), point); - point.setZ(z); - } - - /** - * Get the direction vector (P1-P0). - * @return the direction vector. - */ - public getDirection(): Coordinate { - /* Return the direction */ - return this.p1.subtract(this.p0); - } - - /** - * Get the direction vector (P1-P0). - * @param direction the result direction vector. - */ - public getDirectionTo(direction: Coordinate): void { - /* Return the direction */ - direction.set(this.p1); - direction.subtract0(this.p0); - } - - /** - * Get the direction vector (P1-P0). - * @return the direction vector. - */ - public getDifference(): Coordinate { - return this.getDirection(); - } - - /** - * Swap the orientation of the line (create a line from point1 to point0). - * @return a new line. - */ - public swapDirection(): Line { - return new Line(this.p1, this.p0); - } - - /** - * Get the squared length of the segment. - * @return the squared length of the segment. - */ - public getSquaredLength(): float64 { - /* Get the direction */ - let dx: float64 = (this.p1.getX() - this.p0.getX()); - let dy: float64 = (this.p1.getY() - this.p0.getY()); - let dz: float64 = (this.p1.getZ() - this.p0.getZ()); - /* Return the length */ - return (dx * dx + dy * dy + dz * dz); - } - - /** - * Get the length of the segment. - * @return the length of the segment. - */ - public getLength(): float64 { - return Math.sqrt(this.getSquaredLength()); - } - - /** - * Project a point on the segment. - * @param point the point to project. - * @return the position of the projected point. - */ - public getProjection(point: Coordinate): float64 { - /* Get the direction of the point */ - let pdx: float64 = (point.getX() - this.p0.getX()); - let pdy: float64 = (point.getY() - this.p0.getY()); - let pdz: float64 = (point.getZ() - this.p0.getZ()); - /* Get the direction */ - let dx: float64 = (this.p1.getX() - this.p0.getX()); - let dy: float64 = (this.p1.getY() - this.p0.getY()); - let dz: float64 = (this.p1.getZ() - this.p0.getZ()); - /* Return the value */ - return (pdx * dx + pdy * dy + pdz * dz) / this.getSquaredLength(); - } - - /** - * Project a point on the segment. - * @param point the point to project. - * @return the projected point. - */ - public getProjectionPoint(point: Coordinate): Coordinate { - return this.getPoint(this.getProjection(point)); - } - - /** - * Get the distance from a point to the line. - * @param point the point. - * @return the distance. - */ - public getDistance(point: Coordinate): float64 { - /* Project the point */ - let projected: Coordinate = this.getPoint(this.getProjection(point)); - /* Return the square distance */ - return projected.distance3D(point); - } - - /** - * Get the distance from a point to the segment between point 0 and point 1. - * @param point the point. - * @return the distance. - */ - public getSegmentDistance(point: Coordinate): float64 { - /* Clip the projection */ - let t: float64 = this.getProjection(point); - if (t < 0.0) t = 0.0; else if (t > 1.0) t = 1.0; - /* Return the distance */ - let closest: Coordinate = this.getPoint(t); - return closest.distance3D(point); - } - - /** - * Check if the denominator of an intersection is zero (parallel lines). - * @param value the denominator value. - * @return true if zero (like -7.105427357601002E-15, -3.8944125702045085E-10 or -3.808708481679941E-9 for perfectly parallel lines). - */ - public static isZero(value: float64): boolean { - if (value == 0.0) return true; - return (Math.abs(value) < 1.0e-6); - } - - /** - * Check if the lines is parallel with another line. - * @param line the other line. - * @return true if the lines are parallel. - */ - public isParallel(line: Line): boolean { - /* Get the direction vectors */ - let u: Coordinate = this.getDifference(); - let v: Coordinate = line.getDifference(); - /* Get the parameters for the equation */ - let a: float64 = u.dotProduct(u); - let b: float64 = u.dotProduct(v); - let c: float64 = v.dotProduct(v); - /* Solve the equation */ - return (Line.isZero(a * c - b * b)); - } - - /** - * Intersect with another line. - * The two lines should not be parallel, check with 'isParallel' first ! - * @param line the line the intersect with. - * @return the position of the intersection point. - */ - public getIntersection(line: Line): float64 { - // Algorithm copied from: - // http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm - // - /* Get the direction vectors */ - let u: Coordinate = this.getDifference(); - let v: Coordinate = line.getDifference(); - /* Get the translation vector */ - let w0: Coordinate = this.p0.subtract(line.p0); - /* Get the parameters for the equation */ - let a: float64 = u.dotProduct(u); - let b: float64 = u.dotProduct(v); - let c: float64 = v.dotProduct(v); - let d: float64 = u.dotProduct(w0); - let e: float64 = v.dotProduct(w0); - /* Parallel */ - let denominator: float64 = (a * c - b * b); - ASystem.assert0(Line.isZero(denominator) == false, "Lines " + this + " and " + line + " are parallel when intersecting"); - /* Solve the equation */ - return (b * e - c * d) / denominator; - } - - /** - * Intersect with another line. - * @param line the line the intersect with. - * @return the intersection point (null if the lines are parallell). - */ - public getIntersectionPoint(line: Line): Coordinate { - if (this.isParallel(line)) return null; - return this.getPoint(this.getIntersection(line)); - } - - /** - * Interpolate a point. - * @param point1 the first point on the line. - * @param point2 the second point on the line. - * @param t the point parameter. - * @param point the target point. - */ - public static interpolate(point1: Coordinate, point2: Coordinate, t: float64, point: Coordinate): void { - let x: float64 = point1.getX() + t * (point2.getX() - point1.getX()); - let y: float64 = point1.getY() + t * (point2.getY() - point1.getY()); - let z: float64 = point1.getZ() + t * (point2.getZ() - point1.getZ()); - point.setXYZ(x, y, z); - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Line:p0=" + this.p0 + ",p1=" + this.p1 + "]"; - } + /** The start point */ + public p0: Coordinate; + /** The end point */ + public p1: Coordinate; + + /** + * Create a new line. + * @param p0 the start point. + * @param p1 the end point. + */ + public constructor(p0: Coordinate, p1: Coordinate) { + /* Store the points */ + this.p0 = p0; + this.p1 = p1; + } + + /** + * Create a new line. + * @return a new line. + */ + public static create(): Line { + return new Line(Coordinate.create(), Coordinate.create()); + } + + /** + * Create a new line. + * @param p0 the start point. + * @param p1 the end point. + */ + public static fromPoints(p0: Coordinate, p1: Coordinate): Line { + return new Line(p0, p1); + } + + /** + * Create a new line. + * @param x0 the x of the start point. + * @param y0 the y of the start point. + * @param z0 the z of the start point. + * @param x1 the x of the end point. + * @param y1 the y of the end point. + * @param z1 the z of the end point. + */ + public static fromXYZ(x0: float64, y0: float64, z0: float64, x1: float64, y1: float64, z1: float64): Line { + return new Line(new Coordinate(x0, y0, z0), new Coordinate(x1, y1, z1)); + } + + /** + * Get the start point. + * @return the start point. + */ + public getPoint0(): Coordinate { + return this.p0; + } + + /** + * Get the end point. + * @return the end point. + */ + public getPoint1(): Coordinate { + return this.p1; + } + + /** + * Get a point along the line. + * @param t the position of the point (0.0 at start and 1.0 at end). + * @return a point. + */ + public getPoint(t: float64): Coordinate { + /* Avoid rounding errors */ + if (t == 0.0) return this.p0; + if (t == 1.0) return this.p1; + /* Calculate a new point */ + let x: float64 = this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); + let y: float64 = this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); + let z: float64 = this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); + return new Coordinate(x, y, z); + } + + /** + * Get a point along the line. + * @param t the position of the point (0.0 at start and 1.0 at end). + * @param point the result point (must be mutable). + */ + public getPointTo(t: float64, point: Coordinate): void { + /* Start point? */ + if (t == 0.0) { + /* Copy */ + point.setXYZ(this.p0.getX(), this.p0.getY(), this.p0.getZ()); + } + /* End point? */ + else if (t == 1.0) { + /* Copy */ + point.setXYZ(this.p1.getX(), this.p1.getY(), this.p1.getZ()); + } + /* Intermediate point */ + else { + /* Calculate a new point */ + let x: float64 = this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); + let y: float64 = this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); + let z: float64 = this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); + point.setXYZ(x, y, z); + } + } + + /** + * Get the X coordinate of a point along the line. + * @param t the position of the point (0.0 at start and 1.0 at end). + * @return the coordinate. + */ + public getPointX(t: float64): float64 { + /* Start point? */ + if (t == 0.0) { + /* Copy */ + return this.p0.getX(); + } + /* End point? */ + else if (t == 1.0) { + /* Copy */ + return this.p1.getX(); + } + /* Intermediate point */ + else { + /* Calculate a new point */ + return this.p0.getX() + t * (this.p1.getX() - this.p0.getX()); + } + } + + /** + * Get the Y coordinate of a point along the line. + * @param t the position of the point (0.0 at start and 1.0 at end). + * @return the coordinate. + */ + public getPointY(t: float64): float64 { + /* Start point? */ + if (t == 0.0) { + /* Copy */ + return this.p0.getY(); + } + /* End point? */ + else if (t == 1.0) { + /* Copy */ + return this.p1.getY(); + } + /* Intermediate point */ + else { + /* Calculate a new point */ + return this.p0.getY() + t * (this.p1.getY() - this.p0.getY()); + } + } + + /** + * Get the Z coordinate of a point along the line. + * @param t the position of the point (0.0 at start and 1.0 at end). + * @return the coordinate. + */ + public getPointZ(t: float64): float64 { + /* Start point? */ + if (t == 0.0) { + /* Copy */ + return this.p0.getZ(); + } + /* End point? */ + else if (t == 1.0) { + /* Copy */ + return this.p1.getZ(); + } + /* Intermediate point */ + else { + /* Calculate a new point */ + return this.p0.getZ() + t * (this.p1.getZ() - this.p0.getZ()); + } + } + + /** + * Get a point along the line. + * @param d the distance of the point (0.0 at start). + * @return a point. + */ + public getPointAtDistance(d: float64): Coordinate { + return this.getPoint(d / this.getLength()); + } + + /** + * Get a point along the line. + * @param d the distance of the point (0.0 at start). + * @param point the result point (must be mutable). + */ + public getPointAtDistanceTo(d: float64, point: Coordinate): void { + this.getPointTo(d / this.getLength(), point); + } + + /** + * Get the position for a fixed x value. + * @param x the x value. + * @return the position on the line. + */ + public getPointAtX(x: float64): float64 { + return (x - this.p0.getX()) / (this.p1.getX() - this.p0.getX()); + } + + /** + * Get a point along the line. + * @param x the x value. + * @param point the result point (must be mutable). + */ + public getPointAtXTo(x: float64, point: Coordinate): void { + this.getPointTo(this.getPointAtX(x), point); + point.setX(x); + } + + /** + * Get the position for a fixed y value. + * @param y the y value. + * @return the position on the line. + */ + public getPointAtY(y: float64): float64 { + return (y - this.p0.getY()) / (this.p1.getY() - this.p0.getY()); + } + + /** + * Get a point along the line. + * @param y the y value. + * @param point the result point (must be mutable). + */ + public getPointAtYTo(y: float64, point: Coordinate): void { + this.getPointTo(this.getPointAtY(y), point); + point.setY(y); + } + + /** + * Get the position for a fixed z value. + * @param z the z value. + * @return the position on the line. + */ + public getPointAtZ(z: float64): float64 { + return (z - this.p0.getZ()) / (this.p1.getZ() - this.p0.getZ()); + } + + /** + * Get a point along the line. + * @param z the z value. + * @param point the result point (must be mutable). + */ + public getPointAtZTo(z: float64, point: Coordinate): void { + this.getPointTo(this.getPointAtZ(z), point); + point.setZ(z); + } + + /** + * Get the direction vector (P1-P0). + * @return the direction vector. + */ + public getDirection(): Coordinate { + /* Return the direction */ + return this.p1.subtract(this.p0); + } + + /** + * Get the direction vector (P1-P0). + * @param direction the result direction vector. + */ + public getDirectionTo(direction: Coordinate): void { + /* Return the direction */ + direction.set(this.p1); + direction.subtract0(this.p0); + } + + /** + * Get the direction vector (P1-P0). + * @return the direction vector. + */ + public getDifference(): Coordinate { + return this.getDirection(); + } + + /** + * Swap the orientation of the line (create a line from point1 to point0). + * @return a new line. + */ + public swapDirection(): Line { + return new Line(this.p1, this.p0); + } + + /** + * Get the squared length of the segment. + * @return the squared length of the segment. + */ + public getSquaredLength(): float64 { + /* Get the direction */ + let dx: float64 = this.p1.getX() - this.p0.getX(); + let dy: float64 = this.p1.getY() - this.p0.getY(); + let dz: float64 = this.p1.getZ() - this.p0.getZ(); + /* Return the length */ + return (dx * dx + dy * dy + dz * dz); + } + + /** + * Get the length of the segment. + * @return the length of the segment. + */ + public getLength(): float64 { + return Math.sqrt(this.getSquaredLength()); + } + + /** + * Project a point on the segment. + * @param point the point to project. + * @return the position of the projected point. + */ + public getProjection(point: Coordinate): float64 { + /* Get the direction of the point */ + let pdx: float64 = point.getX() - this.p0.getX(); + let pdy: float64 = point.getY() - this.p0.getY(); + let pdz: float64 = point.getZ() - this.p0.getZ(); + /* Get the direction */ + let dx: float64 = this.p1.getX() - this.p0.getX(); + let dy: float64 = this.p1.getY() - this.p0.getY(); + let dz: float64 = this.p1.getZ() - this.p0.getZ(); + /* Return the value */ + return (pdx * dx + pdy * dy + pdz * dz) / this.getSquaredLength(); + } + + /** + * Project a point on the segment. + * @param point the point to project. + * @return the projected point. + */ + public getProjectionPoint(point: Coordinate): Coordinate { + return this.getPoint(this.getProjection(point)); + } + + /** + * Get the distance from a point to the line. + * @param point the point. + * @return the distance. + */ + public getDistance(point: Coordinate): float64 { + /* Project the point */ + let projected: Coordinate = this.getPoint(this.getProjection(point)); + /* Return the square distance */ + return projected.distance3D(point); + } + + /** + * Get the distance from a point to the segment between point 0 and point 1. + * @param point the point. + * @return the distance. + */ + public getSegmentDistance(point: Coordinate): float64 { + /* Clip the projection */ + let t: float64 = this.getProjection(point); + if (t < 0.0) t = 0.0; else if (t > 1.0) t = 1.0; + /* Return the distance */ + let closest: Coordinate = this.getPoint(t); + return closest.distance3D(point); + } + + /** + * Check if the denominator of an intersection is zero (parallel lines). + * @param value the denominator value. + * @return true if zero (like -7.105427357601002E-15, -3.8944125702045085E-10 or -3.808708481679941E-9 for perfectly parallel lines). + */ + public static isZero(value: float64): boolean { + if (value == 0.0) return true; + return (Math.abs(value) < 1.0e-6); + } + + /** + * Check if the lines is parallel with another line. + * @param line the other line. + * @return true if the lines are parallel. + */ + public isParallel(line: Line): boolean { + /* Get the direction vectors */ + let u: Coordinate = this.getDifference(); + let v: Coordinate = line.getDifference(); + /* Get the parameters for the equation */ + let a: float64 = u.dotProduct(u); + let b: float64 = u.dotProduct(v); + let c: float64 = v.dotProduct(v); + /* Solve the equation */ + return (Line.isZero(a * c - b * b)); + } + + /** + * Intersect with another line. + * The two lines should not be parallel, check with 'isParallel' first ! + * @param line the line the intersect with. + * @return the position of the intersection point. + */ + public getIntersection(line: Line): float64 { + // Algorithm copied from: + // http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm + // + /* Get the direction vectors */ + let u: Coordinate = this.getDifference(); + let v: Coordinate = line.getDifference(); + /* Get the translation vector */ + let w0: Coordinate = this.p0.subtract(line.p0); + /* Get the parameters for the equation */ + let a: float64 = u.dotProduct(u); + let b: float64 = u.dotProduct(v); + let c: float64 = v.dotProduct(v); + let d: float64 = u.dotProduct(w0); + let e: float64 = v.dotProduct(w0); + /* Parallel */ + let denominator: float64 = a * c - b * b; + ASystem.assert0(Line.isZero(denominator) == false, "Lines " + this + " and " + line + " are parallel when intersecting"); + /* Solve the equation */ + return (b * e - c * d) / denominator; + } + + /** + * Intersect with another line. + * @param line the line the intersect with. + * @return the intersection point (null if the lines are parallell). + */ + public getIntersectionPoint(line: Line): Coordinate { + if (this.isParallel(line)) return null; + return this.getPoint(this.getIntersection(line)); + } + + /** + * Interpolate a point. + * @param point1 the first point on the line. + * @param point2 the second point on the line. + * @param t the point parameter. + * @param point the target point. + */ + public static interpolate(point1: Coordinate, point2: Coordinate, t: float64, point: Coordinate): void { + let x: float64 = point1.getX() + t * (point2.getX() - point1.getX()); + let y: float64 = point1.getY() + t * (point2.getY() - point1.getY()); + let z: float64 = point1.getZ() + t * (point2.getZ() - point1.getZ()); + point.setXYZ(x, y, z); + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Line:p0=" + this.p0 + ",p1=" + this.p1 + "]"; + } } diff --git a/core/orbitgt/src/spatial/geom/Transform.ts b/core/orbitgt/src/spatial/geom/Transform.ts index 9777af72ec60..e2d6c53e69f1 100644 --- a/core/orbitgt/src/spatial/geom/Transform.ts +++ b/core/orbitgt/src/spatial/geom/Transform.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.spatial.geom; +// package orbitgt.spatial.geom; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { Bounds } from "./Bounds"; import { Coordinate } from "./Coordinate"; @@ -25,753 +24,776 @@ import { Coordinate } from "./Coordinate"; */ /** @internal */ export class Transform { - /** The 16 elements (row major order) */ - private _elements: Float64Array; - - /** - * Create a new (identity) transform. - */ - public constructor() { - this._elements = new Float64Array(16); - this._elements[0] = 1.0; // m00 - this._elements[1] = 0.0; // m01 - this._elements[2] = 0.0; // m02 - this._elements[3] = 0.0; // m03 - this._elements[4] = 0.0; // m10 - this._elements[5] = 1.0; // m11 - this._elements[6] = 0.0; // m12 - this._elements[7] = 0.0; // m13 - this._elements[8] = 0.0; // m20 - this._elements[9] = 0.0; // m21 - this._elements[10] = 1.0; // m22 - this._elements[11] = 0.0; // m23 - this._elements[12] = 0.0; // m30 - this._elements[13] = 0.0; // m31 - this._elements[14] = 0.0; // m32 - this._elements[15] = 1.0; // m33 - } - - /** - * Create a new (identity) transform. - */ - public static create(): Transform { - return new Transform(); - } - - /** - * Create a transformation from elements. - * @param elements the 16 matrix elements (row major order). - * @return the transformation. - */ - public static fromRowMajor(elements: Float64Array): Transform { - if (elements == null) return null; - if (elements.length == 0) return null; - let transform: Transform = new Transform(); - let index: int32 = 0; - for (let r: number = 0; r < 4; r++) for (let c: number = 0; c < 4; c++) transform.setElement(r, c, elements[index++]); - return transform; - } - - /** - * Create a transformation from elements. - * @param elements the 16 matrix elements (column major order). - * @return the transformation. - */ - public static fromColumnMajor(elements: Float64Array): Transform { - if (elements == null) return null; - if (elements.length == 0) return null; - let transform: Transform = new Transform(); - let index: int32 = 0; - for (let c: number = 0; c < 4; c++) for (let r: number = 0; r < 4; r++) transform.setElement(r, c, elements[index++]); - return transform; - } - - /** - * Create a transformation from elements. - * @param elements the 9 matrix elements (row major order). - * @return the transformation. - */ - public static fromRotationElements(m00: float64, m01: float64, m02: float64, m10: float64, m11: float64, m12: float64, m20: float64, m21: float64, m22: float64): Transform { - let transform: Transform = new Transform(); - transform.setElement(0, 0, m00); - transform.setElement(0, 1, m01); - transform.setElement(0, 2, m02); - transform.setElement(1, 0, m10); - transform.setElement(1, 1, m11); - transform.setElement(1, 2, m12); - transform.setElement(2, 0, m20); - transform.setElement(2, 1, m21); - transform.setElement(2, 2, m22); - return transform; - } - - /** - * Create a transformation from elements. - * @param elements the 16 matrix elements (row major order). - * @return the transformation. - */ - public static fromElements(m00: float64, m01: float64, m02: float64, m03: float64, m10: float64, m11: float64, m12: float64, m13: float64, m20: float64, m21: float64, m22: float64, m23: float64): Transform { - let transform: Transform = Transform.fromRotationElements(m00, m01, m02, m10, m11, m12, m20, m21, m22); - transform.setElement(0, 3, m03); - transform.setElement(1, 3, m13); - transform.setElement(2, 3, m23); - return transform; - } - - /** - * Get an element. - * @param index the index of the element. - * @return the element. - */ - public get(index: int32): float64 { - return this._elements[index]; - } - - /** - * Set an element. - * @param index the index of the element. - * @param value the value. - */ - public set(index: int32, value: float64): void { - this._elements[index] = value; - } - - /** - * Get an element. - * @param row the row index. - * @param col the column index. - * @return the element. - */ - public getElement(row: int32, col: int32): float64 { - return this._elements[row * 4 + col]; - } - - /** - * Set an element. - * @param row the row index. - * @param col the column index. - * @param value the value. - */ - public setElement(row: int32, col: int32, value: float64): void { - this._elements[row * 4 + col] = value; - } - - /** - * Get the elements. - * @return the elements (row major order). - */ - public getElements(): Float64Array { - return this._elements; - } - - /** - * Set the elements. - * @param elements the elements (row major order). - */ - public setElements(elements: Float64Array): void { - for (let i: number = 0; i < this._elements.length; i++) this._elements[i] = elements[i]; - } - - /** - * Get the X column. - * @return the X column. - */ - public getColumnX(): Coordinate { - return new Coordinate(this.getElement(0, 0), this.getElement(1, 0), this.getElement(2, 0)); - } - - /** - * Get the Y column. - * @return the Y column. - */ - public getColumnY(): Coordinate { - return new Coordinate(this.getElement(0, 1), this.getElement(1, 1), this.getElement(2, 1)); - } - - /** - * Get the Z column. - * @return the Z column. - */ - public getColumnZ(): Coordinate { - return new Coordinate(this.getElement(0, 2), this.getElement(1, 2), this.getElement(2, 2)); - } - - /** - * Get the translation column. - * @return the translation column. - */ - public getTranslation(): Coordinate { - return new Coordinate(this.getElement(0, 3), this.getElement(1, 3), this.getElement(2, 3)); - } - - /** - * Set the translation. - * @param tx the x position of the translation. - * @param ty the y position of the translation. - * @param tz the z position of the translation. - * @return the tranformation. - */ - public setTranslation(tx: float64, ty: float64, tz: float64): Transform { - this.setElement(0, 3, tx); - this.setElement(1, 3, ty); - this.setElement(2, 3, tz); - return this; - } - - /** - * Clear the translation. - * @return the tranformation. - */ - public clearTranslation(): Transform { - this.setElement(0, 3, 0.0); - this.setElement(1, 3, 0.0); - this.setElement(2, 3, 0.0); - return this; - } - - /** - * Swap two rows. - * @param row1 the first row. - * @param row2 the second row. - */ - public swapRows(row1: int32, row2: int32): void { - for (let i: number = 0; i < 4; i++) { - let e1: float64 = this.getElement(row1, i); - let e2: float64 = this.getElement(row2, i); - this.setElement(row1, i, e2); - this.setElement(row2, i, e1); - } - } - - /** - * Swap two columns. - * @param col1 the first column. - * @param col2 the second column. - */ - public swapColumns(col1: int32, col2: int32): void { - for (let i: number = 0; i < 4; i++) { - let e1: float64 = this.getElement(i, col1); - let e2: float64 = this.getElement(i, col2); - this.setElement(i, col1, e2); - this.setElement(i, col2, e1); - } - } - - /** - * Swap the YZ coordinates. - */ - public swapYZ(): void { - let result: Transform = Transform.multiply2(this, Transform.createSwapYZ()); - this.setElements(result.getElements()); - } - - /** - * Calculate the cosine of an angle. - * @param angle the angle (in degrees). - * @return the cosine. - */ - public static cos(angle: float64): float64 { - /* One? */ - if (angle == 0.0) return 1.0; - if (angle == 360.0) return 1.0; - /* Minus one? */ - if (angle == 180.0) return -1.0; - if (angle == -180.0) return -1.0; - /* Zero? */ - if (angle == 90.0) return 0.0; - if (angle == -90.0) return 0.0; - if (angle == 270.0) return 0.0; - /* Calculate */ - return Math.cos(angle / 180.0 * Math.PI); - } - - /** - * Calculate the sine of an angle. - * @param angle the angle (in degrees). - * @return the sine. - */ - public static sin(angle: float64): float64 { - /* One? */ - if (angle == 90.0) return 1.0; - /* Minus one? */ - if (angle == -90.0) return -1.0; - if (angle == 270.0) return -1.0; - /* Zero? */ - if (angle == 0.0) return 0.0; - if (angle == 360.0) return 0.0; - if (angle == 180.0) return 0.0; - if (angle == -180.0) return 0.0; - /* Calculate */ - return Math.sin(angle / 180.0 * Math.PI); - } - - /** - * Rotate around the X axis. - * @param angle the rotation angle (degree). - */ - public rotateX(angle: float64): void { - if (angle == 0.0) return; - let result: Transform = Transform.multiply2(this, Transform.createRotationX(angle)); - this.setElements(result.getElements()); - } - - /** - * Apply a rotation around X axis. - * @param point the (mutable) point to rotate. - * @param rotation the (Y->Z,counterclockwise) rotation (degrees). - */ - public static rotatePointX(point: Coordinate, rotation: float64): void { - if (rotation == 0.0) return; - let a: float64 = rotation; - let dcos: float64 = Transform.cos(a); - let dsin: float64 = Transform.sin(a); - let ny: float64 = dcos * point.getY() - dsin * point.getZ(); - let nz: float64 = dsin * point.getY() + dcos * point.getZ(); - point.setXYZ(point.getX(), ny, nz); - } - - /** - * Rotate around the Y axis. - * @param angle the rotation angle (degree). - */ - public rotateY(angle: float64): void { - if (angle == 0.0) return; - let result: Transform = Transform.multiply2(this, Transform.createRotationY(angle)); - this.setElements(result.getElements()); - } - - /** - * Apply a rotation around Y axis. - * @param point the (mutable) point to rotate. - * @param rotation the (Z->X,counterclockwise) rotation (degrees). - */ - public static rotatePointY(point: Coordinate, rotation: float64): void { - if (rotation == 0.0) return; - let a: float64 = -rotation; // swapped orientation to CCW on 09/03/2012 - let dcos: float64 = Transform.cos(a); - let dsin: float64 = Transform.sin(a); - let nx: float64 = dcos * point.getX() - dsin * point.getZ(); - let nz: float64 = dsin * point.getX() + dcos * point.getZ(); - point.setXYZ(nx, point.getY(), nz); - } - - /** - * Rotate around the Z axis. - * @param angle the rotation angle (degree). - */ - public rotateZ(angle: float64): void { - if (angle == 0.0) return; - let result: Transform = Transform.multiply2(this, Transform.createRotationZ(angle)); - this.setElements(result.getElements()); - } - - /** - * Apply a rotation around Z axis. - * @param point the (mutable) point to rotate. - * @param rotation the (X->Y,counterclockwise) rotation (degrees). - */ - public static rotatePointZ(point: Coordinate, rotation: float64): void { - if (rotation == 0.0) return; - let a: float64 = rotation; - let dcos: float64 = Transform.cos(a); - let dsin: float64 = Transform.sin(a); - let nx: float64 = dcos * point.getX() - dsin * point.getY(); - let ny: float64 = dsin * point.getX() + dcos * point.getY(); - point.setXYZ(nx, ny, point.getZ()); - } - - /** - * Multiply two matrices. - * @param a the first transform. - * @param b the second transform. - * @return the result transform (a x b). - */ - public static multiply2(a: Transform, b: Transform): Transform { - /* Allow nulls */ - if (a == null) a = new Transform(); - if (b == null) b = new Transform(); - /* Fill the destination transform "d" */ - let d: Transform = new Transform(); - for (let i: number = 0; i < 4; i++) { - /* Get the next row from "a" */ - let ai0: float64 = a.getElement(i, 0); - let ai1: float64 = a.getElement(i, 1); - let ai2: float64 = a.getElement(i, 2); - let ai3: float64 = a.getElement(i, 3); - /* Set the target row in "d" */ - d.setElement(i, 0, ai0 * b.getElement(0, 0) + ai1 * b.getElement(1, 0) + ai2 * b.getElement(2, 0) + ai3 * b.getElement(3, 0)); // multiply by column(0) of "b" - d.setElement(i, 1, ai0 * b.getElement(0, 1) + ai1 * b.getElement(1, 1) + ai2 * b.getElement(2, 1) + ai3 * b.getElement(3, 1)); // multiply by column(1) of "b" - d.setElement(i, 2, ai0 * b.getElement(0, 2) + ai1 * b.getElement(1, 2) + ai2 * b.getElement(2, 2) + ai3 * b.getElement(3, 2)); // multiply by column(2) of "b" - d.setElement(i, 3, ai0 * b.getElement(0, 3) + ai1 * b.getElement(1, 3) + ai2 * b.getElement(2, 3) + ai3 * b.getElement(3, 3)); // multiply by column(3) of "b" - } - /* Return the transform */ - return d; - } - - /** - * Concatenate a transform. - * @param transform the transform to concatenate. - * @return the combined transformation. - */ - public concat(transform: Transform): Transform { - return Transform.multiply2(this, transform); - } - - /** - * Multiply. - * @param transform the transform to multiply with. - */ - public multiply(transform: Transform): void { - let result: Transform = Transform.multiply2(this, transform); - this.setElements(result.getElements()); - } - - /** - * Translate. - * @param tx the x translation. - * @param ty the y translation. - * @param tz the z translation. - */ - public translate(tx: float64, ty: float64, tz: float64): void { - let result: Transform = Transform.multiply2(this, Transform.createTranslation(tx, ty, tz)); - this.setElements(result.getElements()); - } - - /** - * Translate. - * @param point the xyz translation. - */ - public translatePoint(point: Coordinate): void { - this.translate(point.getX(), point.getY(), point.getZ()); - } - - /** - * Scale. - * @param sx the x scale. - * @param sy the y scale. - * @param sz the z scale. - */ - public scale(sx: float64, sy: float64, sz: float64): void { - let result: Transform = Transform.multiply2(this, Transform.createScale(sx, sy, sz)); - this.setElements(result.getElements()); - } - - /** - * Scale XYZ. - * @param s the scale. - */ - public scale3(s: float64): void { - this.scale(s, s, s); - } - - /** - * Create the inverse transform. - * @return the inverse transform. - */ - public createInverse(): Transform { - /* Get the 3x3 elements */ - let a: float64 = this.getElement(0, 0); - let b: float64 = this.getElement(0, 1); - let c: float64 = this.getElement(0, 2); - let d: float64 = this.getElement(1, 0); - let e: float64 = this.getElement(1, 1); - let f: float64 = this.getElement(1, 2); - let g: float64 = this.getElement(2, 0); - let h: float64 = this.getElement(2, 1); - let i: float64 = this.getElement(2, 2); - /* Invert the 3x3 matrix */ - let idet: float64 = 1.0 / (a * (e * i - h * f) - b * (d * i - g * f) + c * (d * h - g * e)); - let inverse: Transform = new Transform(); - inverse.setElement(0, 0, (e * i - f * h) * idet); - inverse.setElement(0, 1, -(b * i - c * h) * idet); - inverse.setElement(0, 2, (b * f - c * e) * idet); - inverse.setElement(1, 0, -(d * i - f * g) * idet); - inverse.setElement(1, 1, (a * i - c * g) * idet); - inverse.setElement(1, 2, -(a * f - c * d) * idet); - inverse.setElement(2, 0, (d * h - e * g) * idet); - inverse.setElement(2, 1, -(a * h - b * g) * idet); - inverse.setElement(2, 2, (a * e - b * d) * idet); - /* Invert the translation */ - let t: Coordinate = new Coordinate(this.getElement(0, 3), this.getElement(1, 3), this.getElement(2, 3)); - inverse.transformTo(t, t); - inverse.setElement(0, 3, -t.getX()); - inverse.setElement(1, 3, -t.getY()); - inverse.setElement(2, 3, -t.getZ()); - /* Done */ - return inverse; - } - - /** - * Invert. - */ - public invert(): void { - let result: Transform = this.createInverse(); - this.setElements(result.getElements()); - } - - /** - * Create a copy. - * @return a copy. - */ - public copy(): Transform { - let copy: Transform = new Transform(); - for (let i: number = 0; i < 16; i++) copy._elements[i] = this._elements[i]; - return copy; - } - - /** - * Create an identity transform. - * @return the transform. - */ - public static createIdentity(): Transform { - return new Transform(); - } - - /** - * Create a translation transform. - * @param tx the x translation. - * @param ty the y translation. - * @param tz the z translation. - * @return the transform. - */ - public static createTranslation(tx: float64, ty: float64, tz: float64): Transform { - let transform: Transform = Transform.createIdentity(); - transform.setElement(0, 3, tx); - transform.setElement(1, 3, ty); - transform.setElement(2, 3, tz); - return transform; - } - - /** - * Create a translation transform. - * @param position the translation. - * @return the transform. - */ - public static createTranslation2(position: Coordinate): Transform { - return Transform.createTranslation(position.getX(), position.getY(), position.getZ()); - } - - /** - * Create a scale transform. - * @param sx the x translation. - * @param sy the y translation. - * @param sz the z translation. - * @return the transform. - */ - public static createScale(sx: float64, sy: float64, sz: float64): Transform { - let transform: Transform = Transform.createIdentity(); - transform.setElement(0, 0, sx); - transform.setElement(1, 1, sy); - transform.setElement(2, 2, sz); - return transform; - } - - /** - * Create a rotation-round-X transform. - * @param angle the rotation angle (degree). - * @return the transform. - */ - public static createRotationX(angle: float64): Transform { - let rad: float64 = (angle / 180.0 * Math.PI); - let sin: float64 = (angle == 90.0) ? 1.0 : Math.sin(rad); - let cos: float64 = (angle == 90.0) ? 0.0 : Math.cos(rad); - let transform: Transform = Transform.createIdentity(); - transform.setElement(1, 1, cos); - transform.setElement(2, 1, sin); - transform.setElement(1, 2, -sin); - transform.setElement(2, 2, cos); - return transform; - } - - /** - * Create a rotation-round-Y transform. - * @param angle the rotation angle (degree). - * @return the transform. - */ - public static createRotationY(angle: float64): Transform { - let rad: float64 = (angle / 180.0 * Math.PI); - let sin: float64 = Math.sin(rad); - let cos: float64 = Math.cos(rad); - let transform: Transform = Transform.createIdentity(); - transform.setElement(0, 0, cos); - transform.setElement(2, 0, -sin); - transform.setElement(0, 2, sin); - transform.setElement(2, 2, cos); - return transform; - } - - /** - * Create a rotation-round-Z transform. - * @param angle the rotation angle (degree). - * @return the transform. - */ - public static createRotationZ(angle: float64): Transform { - let rad: float64 = (angle / 180.0 * Math.PI); - let sin: float64 = Math.sin(rad); - let cos: float64 = Math.cos(rad); - let transform: Transform = Transform.createIdentity(); - transform.setElement(0, 0, cos); - transform.setElement(1, 0, sin); - transform.setElement(0, 1, -sin); - transform.setElement(1, 1, cos); - return transform; - } - - /** - * Create a swap YZ transform. - * @return the transform. - */ - public static createSwapYZ(): Transform { - let transform: Transform = Transform.createIdentity(); - transform.setElement(1, 1, 0.0); - transform.setElement(1, 2, 1.0); - transform.setElement(2, 1, 1.0); - transform.setElement(2, 2, 0.0); - return transform; - } - - /** - * Create a transformation from elements. - * @param elements the elements (row major order) - * @return the transformation. - */ - public static createWithElements(elements: Float64Array): Transform { - let transform: Transform = Transform.createIdentity(); - transform.setElements(elements); - return transform; - } - - /** - * Create a transformation from columns. - * @param col0 the first column. - * @param col1 the second column. - * @param col2 the third column. - * @param col3 the fourth column (considered zero if null). - * @return the transformation. - */ - public static createWithColumns(col0: Coordinate, col1: Coordinate, col2: Coordinate, col3: Coordinate): Transform { - let transform: Transform = Transform.createIdentity(); - transform.setElement(0, 0, col0.getX()); - transform.setElement(1, 0, col0.getY()); - transform.setElement(2, 0, col0.getZ()); - transform.setElement(0, 1, col1.getX()); - transform.setElement(1, 1, col1.getY()); - transform.setElement(2, 1, col1.getZ()); - transform.setElement(0, 2, col2.getX()); - transform.setElement(1, 2, col2.getY()); - transform.setElement(2, 2, col2.getZ()); - if (col3 != null) { - transform.setElement(0, 3, col3.getX()); - transform.setElement(1, 3, col3.getY()); - transform.setElement(2, 3, col3.getZ()); - } - return transform; - } - - /** - * Create an orthogonal rotation from a quaternion. - * @param a the first quaternion element (q1). - * @param b the second quaternion element (q2). - * @param c the third quaternion element (q3). - * @param d the fourth quaternion element (q4). - * @return the rotation matrix. - */ - public static fromQuaternion(a: float64, b: float64, c: float64, d: float64): Transform { - // See "Quaternions and spatial rotation" section "From a quaternion to an orthogonal matrix" - // at https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation - // - /* We should have a unit quaternion */ - let len: float64 = (a * a + b * b + c * c + d * d); - /* First row */ - let m00: float64 = a * a + b * b - c * c - d * d; - let m01: float64 = 2.0 * b * c - 2.0 * a * d; - let m02: float64 = 2.0 * b * d + 2.0 * a * c; - /* Second row */ - let m10: float64 = 2.0 * b * c + 2.0 * a * d; - let m11: float64 = a * a - b * b + c * c - d * d; - let m12: float64 = 2.0 * c * d - 2.0 * a * b; - /* Third row */ - let m20: float64 = 2.0 * b * d - 2.0 * a * c; - let m21: float64 = 2.0 * c * d + 2.0 * a * b; - let m22: float64 = a * a - b * b - c * c + d * d; - /* Return the rotation */ - let transform: Transform = new Transform(); - transform.setElement(0, 0, m00); - transform.setElement(0, 1, m01); - transform.setElement(0, 2, m02); - transform.setElement(1, 0, m10); - transform.setElement(1, 1, m11); - transform.setElement(1, 2, m12); - transform.setElement(2, 0, m20); - transform.setElement(2, 1, m21); - transform.setElement(2, 2, m22); - return transform; - } - - /** - * Transform a point. - * @param source the source point. - * @param target the target point (can be same as source). - * @return the target point. - */ - public transformTo(source: Coordinate, target: Coordinate): Coordinate { - let sx: float64 = source.getX(); - let sy: float64 = source.getY(); - let sz: float64 = source.getZ(); - target.x = this._elements[0] * sx + this._elements[1] * sy + this._elements[2] * sz + this._elements[3]; - target.y = this._elements[4] * sx + this._elements[5] * sy + this._elements[6] * sz + this._elements[7]; - target.z = this._elements[8] * sx + this._elements[9] * sy + this._elements[10] * sz + this._elements[11]; - return target; - } - - /** - * Transform a point. - * @param source the source point. - * @return the target point. - */ - public transform(source: Coordinate): Coordinate { - return this.transformTo(source, Coordinate.create()); - } - - /** - * Transform bounds. - * @param bounds the bounds. - * @return the transformed bounds. - */ - public transformBounds(bounds: Bounds): Bounds { - /* Not valid? */ - if (bounds.isValid() == false) return bounds; - /* Transform all corners */ - let nbounds: Bounds = new Bounds(); - let point: Coordinate = Coordinate.create(); - for (let i: number = 0; i < 8; i++) { - /* Transform the next corner */ - bounds.getCorner(i, point); - this.transformTo(point, point); - nbounds.add(point); - } - /* Return the new bounds */ - return nbounds; - } - - /** - * Check if the transform matches another transform. - * @param other the other transform. - * @return true if same. - */ - public same(other: Transform): boolean { - for (let i: number = 0; i < 16; i++) if (this._elements[i] != other._elements[i]) return false; - return true; - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return "[Transform:m00=" + this._elements[0] + ",m10=" + this._elements[4] + ",m20=" + this._elements[8] + - ",m01=" + this._elements[1] + ",m11=" + this._elements[5] + ",m21=" + this._elements[9] + - ",m02=" + this._elements[2] + ",m12=" + this._elements[6] + ",m22=" + this._elements[10] + - ",m03=" + this._elements[3] + ",m13=" + this._elements[7] + ",m23=" + this._elements[11] + "]"; - } + /** The 16 elements (row major order) */ + private _elements: Float64Array; + + /** + * Create a new (identity) transform. + */ + public constructor() { + this._elements = new Float64Array(16); + this._elements[0] = 1.0; // m00 + this._elements[1] = 0.0; // m01 + this._elements[2] = 0.0; // m02 + this._elements[3] = 0.0; // m03 + this._elements[4] = 0.0; // m10 + this._elements[5] = 1.0; // m11 + this._elements[6] = 0.0; // m12 + this._elements[7] = 0.0; // m13 + this._elements[8] = 0.0; // m20 + this._elements[9] = 0.0; // m21 + this._elements[10] = 1.0; // m22 + this._elements[11] = 0.0; // m23 + this._elements[12] = 0.0; // m30 + this._elements[13] = 0.0; // m31 + this._elements[14] = 0.0; // m32 + this._elements[15] = 1.0; // m33 + } + + /** + * Create a new (identity) transform. + */ + public static create(): Transform { + return new Transform(); + } + + /** + * Create a transformation from elements. + * @param elements the 16 matrix elements (row major order). + * @return the transformation. + */ + public static fromRowMajor(elements: Float64Array): Transform { + if (elements == null) return null; + if (elements.length == 0) return null; + let transform: Transform = new Transform(); + let index: int32 = 0; + for (let r: number = 0; r < 4; r++) for (let c: number = 0; c < 4; c++) transform.setElement(r, c, elements[index++]); + return transform; + } + + /** + * Create a transformation from elements. + * @param elements the 16 matrix elements (column major order). + * @return the transformation. + */ + public static fromColumnMajor(elements: Float64Array): Transform { + if (elements == null) return null; + if (elements.length == 0) return null; + let transform: Transform = new Transform(); + let index: int32 = 0; + for (let c: number = 0; c < 4; c++) for (let r: number = 0; r < 4; r++) transform.setElement(r, c, elements[index++]); + return transform; + } + + /** + * Create a transformation from elements. + * @param elements the 9 matrix elements (row major order). + * @return the transformation. + */ + public static fromRotationElements( + m00: float64, + m01: float64, + m02: float64, + m10: float64, + m11: float64, + m12: float64, + m20: float64, + m21: float64, + m22: float64, + ): Transform { + let transform: Transform = new Transform(); + transform.setElement(0, 0, m00); + transform.setElement(0, 1, m01); + transform.setElement(0, 2, m02); + transform.setElement(1, 0, m10); + transform.setElement(1, 1, m11); + transform.setElement(1, 2, m12); + transform.setElement(2, 0, m20); + transform.setElement(2, 1, m21); + transform.setElement(2, 2, m22); + return transform; + } + + /** + * Create a transformation from elements. + * @param elements the 16 matrix elements (row major order). + * @return the transformation. + */ + public static fromElements( + m00: float64, + m01: float64, + m02: float64, + m03: float64, + m10: float64, + m11: float64, + m12: float64, + m13: float64, + m20: float64, + m21: float64, + m22: float64, + m23: float64, + ): Transform { + let transform: Transform = Transform.fromRotationElements(m00, m01, m02, m10, m11, m12, m20, m21, m22); + transform.setElement(0, 3, m03); + transform.setElement(1, 3, m13); + transform.setElement(2, 3, m23); + return transform; + } + + /** + * Get an element. + * @param index the index of the element. + * @return the element. + */ + public get(index: int32): float64 { + return this._elements[index]; + } + + /** + * Set an element. + * @param index the index of the element. + * @param value the value. + */ + public set(index: int32, value: float64): void { + this._elements[index] = value; + } + + /** + * Get an element. + * @param row the row index. + * @param col the column index. + * @return the element. + */ + public getElement(row: int32, col: int32): float64 { + return this._elements[row * 4 + col]; + } + + /** + * Set an element. + * @param row the row index. + * @param col the column index. + * @param value the value. + */ + public setElement(row: int32, col: int32, value: float64): void { + this._elements[row * 4 + col] = value; + } + + /** + * Get the elements. + * @return the elements (row major order). + */ + public getElements(): Float64Array { + return this._elements; + } + + /** + * Set the elements. + * @param elements the elements (row major order). + */ + public setElements(elements: Float64Array): void { + for (let i: number = 0; i < this._elements.length; i++) this._elements[i] = elements[i]; + } + + /** + * Get the X column. + * @return the X column. + */ + public getColumnX(): Coordinate { + return new Coordinate(this.getElement(0, 0), this.getElement(1, 0), this.getElement(2, 0)); + } + + /** + * Get the Y column. + * @return the Y column. + */ + public getColumnY(): Coordinate { + return new Coordinate(this.getElement(0, 1), this.getElement(1, 1), this.getElement(2, 1)); + } + + /** + * Get the Z column. + * @return the Z column. + */ + public getColumnZ(): Coordinate { + return new Coordinate(this.getElement(0, 2), this.getElement(1, 2), this.getElement(2, 2)); + } + + /** + * Get the translation column. + * @return the translation column. + */ + public getTranslation(): Coordinate { + return new Coordinate(this.getElement(0, 3), this.getElement(1, 3), this.getElement(2, 3)); + } + + /** + * Set the translation. + * @param tx the x position of the translation. + * @param ty the y position of the translation. + * @param tz the z position of the translation. + * @return the tranformation. + */ + public setTranslation(tx: float64, ty: float64, tz: float64): Transform { + this.setElement(0, 3, tx); + this.setElement(1, 3, ty); + this.setElement(2, 3, tz); + return this; + } + + /** + * Clear the translation. + * @return the tranformation. + */ + public clearTranslation(): Transform { + this.setElement(0, 3, 0.0); + this.setElement(1, 3, 0.0); + this.setElement(2, 3, 0.0); + return this; + } + + /** + * Swap two rows. + * @param row1 the first row. + * @param row2 the second row. + */ + public swapRows(row1: int32, row2: int32): void { + for (let i: number = 0; i < 4; i++) { + let e1: float64 = this.getElement(row1, i); + let e2: float64 = this.getElement(row2, i); + this.setElement(row1, i, e2); + this.setElement(row2, i, e1); + } + } + + /** + * Swap two columns. + * @param col1 the first column. + * @param col2 the second column. + */ + public swapColumns(col1: int32, col2: int32): void { + for (let i: number = 0; i < 4; i++) { + let e1: float64 = this.getElement(i, col1); + let e2: float64 = this.getElement(i, col2); + this.setElement(i, col1, e2); + this.setElement(i, col2, e1); + } + } + + /** + * Swap the YZ coordinates. + */ + public swapYZ(): void { + let result: Transform = Transform.multiply2(this, Transform.createSwapYZ()); + this.setElements(result.getElements()); + } + + /** + * Calculate the cosine of an angle. + * @param angle the angle (in degrees). + * @return the cosine. + */ + public static cos(angle: float64): float64 { + /* One? */ + if (angle == 0.0) return 1.0; + if (angle == 360.0) return 1.0; + /* Minus one? */ + if (angle == 180.0) return -1.0; + if (angle == -180.0) return -1.0; + /* Zero? */ + if (angle == 90.0) return 0.0; + if (angle == -90.0) return 0.0; + if (angle == 270.0) return 0.0; + /* Calculate */ + return Math.cos(angle / 180.0 * Math.PI); + } + + /** + * Calculate the sine of an angle. + * @param angle the angle (in degrees). + * @return the sine. + */ + public static sin(angle: float64): float64 { + /* One? */ + if (angle == 90.0) return 1.0; + /* Minus one? */ + if (angle == -90.0) return -1.0; + if (angle == 270.0) return -1.0; + /* Zero? */ + if (angle == 0.0) return 0.0; + if (angle == 360.0) return 0.0; + if (angle == 180.0) return 0.0; + if (angle == -180.0) return 0.0; + /* Calculate */ + return Math.sin(angle / 180.0 * Math.PI); + } + + /** + * Rotate around the X axis. + * @param angle the rotation angle (degree). + */ + public rotateX(angle: float64): void { + if (angle == 0.0) return; + let result: Transform = Transform.multiply2(this, Transform.createRotationX(angle)); + this.setElements(result.getElements()); + } + + /** + * Apply a rotation around X axis. + * @param point the (mutable) point to rotate. + * @param rotation the (Y->Z,counterclockwise) rotation (degrees). + */ + public static rotatePointX(point: Coordinate, rotation: float64): void { + if (rotation == 0.0) return; + let a: float64 = rotation; + let dcos: float64 = Transform.cos(a); + let dsin: float64 = Transform.sin(a); + let ny: float64 = dcos * point.getY() - dsin * point.getZ(); + let nz: float64 = dsin * point.getY() + dcos * point.getZ(); + point.setXYZ(point.getX(), ny, nz); + } + + /** + * Rotate around the Y axis. + * @param angle the rotation angle (degree). + */ + public rotateY(angle: float64): void { + if (angle == 0.0) return; + let result: Transform = Transform.multiply2(this, Transform.createRotationY(angle)); + this.setElements(result.getElements()); + } + + /** + * Apply a rotation around Y axis. + * @param point the (mutable) point to rotate. + * @param rotation the (Z->X,counterclockwise) rotation (degrees). + */ + public static rotatePointY(point: Coordinate, rotation: float64): void { + if (rotation == 0.0) return; + let a: float64 = -rotation; // swapped orientation to CCW on 09/03/2012 + let dcos: float64 = Transform.cos(a); + let dsin: float64 = Transform.sin(a); + let nx: float64 = dcos * point.getX() - dsin * point.getZ(); + let nz: float64 = dsin * point.getX() + dcos * point.getZ(); + point.setXYZ(nx, point.getY(), nz); + } + + /** + * Rotate around the Z axis. + * @param angle the rotation angle (degree). + */ + public rotateZ(angle: float64): void { + if (angle == 0.0) return; + let result: Transform = Transform.multiply2(this, Transform.createRotationZ(angle)); + this.setElements(result.getElements()); + } + + /** + * Apply a rotation around Z axis. + * @param point the (mutable) point to rotate. + * @param rotation the (X->Y,counterclockwise) rotation (degrees). + */ + public static rotatePointZ(point: Coordinate, rotation: float64): void { + if (rotation == 0.0) return; + let a: float64 = rotation; + let dcos: float64 = Transform.cos(a); + let dsin: float64 = Transform.sin(a); + let nx: float64 = dcos * point.getX() - dsin * point.getY(); + let ny: float64 = dsin * point.getX() + dcos * point.getY(); + point.setXYZ(nx, ny, point.getZ()); + } + + /** + * Multiply two matrices. + * @param a the first transform. + * @param b the second transform. + * @return the result transform (a x b). + */ + public static multiply2(a: Transform, b: Transform): Transform { + /* Allow nulls */ + if (a == null) a = new Transform(); + if (b == null) b = new Transform(); + /* Fill the destination transform "d" */ + let d: Transform = new Transform(); + for (let i: number = 0; i < 4; i++) { + /* Get the next row from "a" */ + let ai0: float64 = a.getElement(i, 0); + let ai1: float64 = a.getElement(i, 1); + let ai2: float64 = a.getElement(i, 2); + let ai3: float64 = a.getElement(i, 3); + /* Set the target row in "d" */ + d.setElement(i, 0, ai0 * b.getElement(0, 0) + ai1 * b.getElement(1, 0) + ai2 * b.getElement(2, 0) + ai3 * b.getElement(3, 0)); // multiply by column(0) of "b" + d.setElement(i, 1, ai0 * b.getElement(0, 1) + ai1 * b.getElement(1, 1) + ai2 * b.getElement(2, 1) + ai3 * b.getElement(3, 1)); // multiply by column(1) of "b" + d.setElement(i, 2, ai0 * b.getElement(0, 2) + ai1 * b.getElement(1, 2) + ai2 * b.getElement(2, 2) + ai3 * b.getElement(3, 2)); // multiply by column(2) of "b" + d.setElement(i, 3, ai0 * b.getElement(0, 3) + ai1 * b.getElement(1, 3) + ai2 * b.getElement(2, 3) + ai3 * b.getElement(3, 3)); // multiply by column(3) of "b" + } + /* Return the transform */ + return d; + } + + /** + * Concatenate a transform. + * @param transform the transform to concatenate. + * @return the combined transformation. + */ + public concat(transform: Transform): Transform { + return Transform.multiply2(this, transform); + } + + /** + * Multiply. + * @param transform the transform to multiply with. + */ + public multiply(transform: Transform): void { + let result: Transform = Transform.multiply2(this, transform); + this.setElements(result.getElements()); + } + + /** + * Translate. + * @param tx the x translation. + * @param ty the y translation. + * @param tz the z translation. + */ + public translate(tx: float64, ty: float64, tz: float64): void { + let result: Transform = Transform.multiply2(this, Transform.createTranslation(tx, ty, tz)); + this.setElements(result.getElements()); + } + + /** + * Translate. + * @param point the xyz translation. + */ + public translatePoint(point: Coordinate): void { + this.translate(point.getX(), point.getY(), point.getZ()); + } + + /** + * Scale. + * @param sx the x scale. + * @param sy the y scale. + * @param sz the z scale. + */ + public scale(sx: float64, sy: float64, sz: float64): void { + let result: Transform = Transform.multiply2(this, Transform.createScale(sx, sy, sz)); + this.setElements(result.getElements()); + } + + /** + * Scale XYZ. + * @param s the scale. + */ + public scale3(s: float64): void { + this.scale(s, s, s); + } + + /** + * Create the inverse transform. + * @return the inverse transform. + */ + public createInverse(): Transform { + /* Get the 3x3 elements */ + let a: float64 = this.getElement(0, 0); + let b: float64 = this.getElement(0, 1); + let c: float64 = this.getElement(0, 2); + let d: float64 = this.getElement(1, 0); + let e: float64 = this.getElement(1, 1); + let f: float64 = this.getElement(1, 2); + let g: float64 = this.getElement(2, 0); + let h: float64 = this.getElement(2, 1); + let i: float64 = this.getElement(2, 2); + /* Invert the 3x3 matrix */ + let idet: float64 = 1.0 / (a * (e * i - h * f) - b * (d * i - g * f) + c * (d * h - g * e)); + let inverse: Transform = new Transform(); + inverse.setElement(0, 0, (e * i - f * h) * idet); + inverse.setElement(0, 1, -(b * i - c * h) * idet); + inverse.setElement(0, 2, (b * f - c * e) * idet); + inverse.setElement(1, 0, -(d * i - f * g) * idet); + inverse.setElement(1, 1, (a * i - c * g) * idet); + inverse.setElement(1, 2, -(a * f - c * d) * idet); + inverse.setElement(2, 0, (d * h - e * g) * idet); + inverse.setElement(2, 1, -(a * h - b * g) * idet); + inverse.setElement(2, 2, (a * e - b * d) * idet); + /* Invert the translation */ + let t: Coordinate = new Coordinate(this.getElement(0, 3), this.getElement(1, 3), this.getElement(2, 3)); + inverse.transformTo(t, t); + inverse.setElement(0, 3, -t.getX()); + inverse.setElement(1, 3, -t.getY()); + inverse.setElement(2, 3, -t.getZ()); + /* Done */ + return inverse; + } + + /** + * Invert. + */ + public invert(): void { + let result: Transform = this.createInverse(); + this.setElements(result.getElements()); + } + + /** + * Create a copy. + * @return a copy. + */ + public copy(): Transform { + let copy: Transform = new Transform(); + for (let i: number = 0; i < 16; i++) copy._elements[i] = this._elements[i]; + return copy; + } + + /** + * Create an identity transform. + * @return the transform. + */ + public static createIdentity(): Transform { + return new Transform(); + } + + /** + * Create a translation transform. + * @param tx the x translation. + * @param ty the y translation. + * @param tz the z translation. + * @return the transform. + */ + public static createTranslation(tx: float64, ty: float64, tz: float64): Transform { + let transform: Transform = Transform.createIdentity(); + transform.setElement(0, 3, tx); + transform.setElement(1, 3, ty); + transform.setElement(2, 3, tz); + return transform; + } + + /** + * Create a translation transform. + * @param position the translation. + * @return the transform. + */ + public static createTranslation2(position: Coordinate): Transform { + return Transform.createTranslation(position.getX(), position.getY(), position.getZ()); + } + + /** + * Create a scale transform. + * @param sx the x translation. + * @param sy the y translation. + * @param sz the z translation. + * @return the transform. + */ + public static createScale(sx: float64, sy: float64, sz: float64): Transform { + let transform: Transform = Transform.createIdentity(); + transform.setElement(0, 0, sx); + transform.setElement(1, 1, sy); + transform.setElement(2, 2, sz); + return transform; + } + + /** + * Create a rotation-round-X transform. + * @param angle the rotation angle (degree). + * @return the transform. + */ + public static createRotationX(angle: float64): Transform { + let rad: float64 = angle / 180.0 * Math.PI; + let sin: float64 = (angle == 90.0) ? 1.0 : Math.sin(rad); + let cos: float64 = (angle == 90.0) ? 0.0 : Math.cos(rad); + let transform: Transform = Transform.createIdentity(); + transform.setElement(1, 1, cos); + transform.setElement(2, 1, sin); + transform.setElement(1, 2, -sin); + transform.setElement(2, 2, cos); + return transform; + } + + /** + * Create a rotation-round-Y transform. + * @param angle the rotation angle (degree). + * @return the transform. + */ + public static createRotationY(angle: float64): Transform { + let rad: float64 = angle / 180.0 * Math.PI; + let sin: float64 = Math.sin(rad); + let cos: float64 = Math.cos(rad); + let transform: Transform = Transform.createIdentity(); + transform.setElement(0, 0, cos); + transform.setElement(2, 0, -sin); + transform.setElement(0, 2, sin); + transform.setElement(2, 2, cos); + return transform; + } + + /** + * Create a rotation-round-Z transform. + * @param angle the rotation angle (degree). + * @return the transform. + */ + public static createRotationZ(angle: float64): Transform { + let rad: float64 = angle / 180.0 * Math.PI; + let sin: float64 = Math.sin(rad); + let cos: float64 = Math.cos(rad); + let transform: Transform = Transform.createIdentity(); + transform.setElement(0, 0, cos); + transform.setElement(1, 0, sin); + transform.setElement(0, 1, -sin); + transform.setElement(1, 1, cos); + return transform; + } + + /** + * Create a swap YZ transform. + * @return the transform. + */ + public static createSwapYZ(): Transform { + let transform: Transform = Transform.createIdentity(); + transform.setElement(1, 1, 0.0); + transform.setElement(1, 2, 1.0); + transform.setElement(2, 1, 1.0); + transform.setElement(2, 2, 0.0); + return transform; + } + + /** + * Create a transformation from elements. + * @param elements the elements (row major order) + * @return the transformation. + */ + public static createWithElements(elements: Float64Array): Transform { + let transform: Transform = Transform.createIdentity(); + transform.setElements(elements); + return transform; + } + + /** + * Create a transformation from columns. + * @param col0 the first column. + * @param col1 the second column. + * @param col2 the third column. + * @param col3 the fourth column (considered zero if null). + * @return the transformation. + */ + public static createWithColumns(col0: Coordinate, col1: Coordinate, col2: Coordinate, col3: Coordinate): Transform { + let transform: Transform = Transform.createIdentity(); + transform.setElement(0, 0, col0.getX()); + transform.setElement(1, 0, col0.getY()); + transform.setElement(2, 0, col0.getZ()); + transform.setElement(0, 1, col1.getX()); + transform.setElement(1, 1, col1.getY()); + transform.setElement(2, 1, col1.getZ()); + transform.setElement(0, 2, col2.getX()); + transform.setElement(1, 2, col2.getY()); + transform.setElement(2, 2, col2.getZ()); + if (col3 != null) { + transform.setElement(0, 3, col3.getX()); + transform.setElement(1, 3, col3.getY()); + transform.setElement(2, 3, col3.getZ()); + } + return transform; + } + + /** + * Create an orthogonal rotation from a quaternion. + * @param a the first quaternion element (q1). + * @param b the second quaternion element (q2). + * @param c the third quaternion element (q3). + * @param d the fourth quaternion element (q4). + * @return the rotation matrix. + */ + public static fromQuaternion(a: float64, b: float64, c: float64, d: float64): Transform { + // See "Quaternions and spatial rotation" section "From a quaternion to an orthogonal matrix" + // at https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation + // + /* We should have a unit quaternion */ + let len: float64 = a * a + b * b + c * c + d * d; + /* First row */ + let m00: float64 = a * a + b * b - c * c - d * d; + let m01: float64 = 2.0 * b * c - 2.0 * a * d; + let m02: float64 = 2.0 * b * d + 2.0 * a * c; + /* Second row */ + let m10: float64 = 2.0 * b * c + 2.0 * a * d; + let m11: float64 = a * a - b * b + c * c - d * d; + let m12: float64 = 2.0 * c * d - 2.0 * a * b; + /* Third row */ + let m20: float64 = 2.0 * b * d - 2.0 * a * c; + let m21: float64 = 2.0 * c * d + 2.0 * a * b; + let m22: float64 = a * a - b * b - c * c + d * d; + /* Return the rotation */ + let transform: Transform = new Transform(); + transform.setElement(0, 0, m00); + transform.setElement(0, 1, m01); + transform.setElement(0, 2, m02); + transform.setElement(1, 0, m10); + transform.setElement(1, 1, m11); + transform.setElement(1, 2, m12); + transform.setElement(2, 0, m20); + transform.setElement(2, 1, m21); + transform.setElement(2, 2, m22); + return transform; + } + + /** + * Transform a point. + * @param source the source point. + * @param target the target point (can be same as source). + * @return the target point. + */ + public transformTo(source: Coordinate, target: Coordinate): Coordinate { + let sx: float64 = source.getX(); + let sy: float64 = source.getY(); + let sz: float64 = source.getZ(); + target.x = this._elements[0] * sx + this._elements[1] * sy + this._elements[2] * sz + this._elements[3]; + target.y = this._elements[4] * sx + this._elements[5] * sy + this._elements[6] * sz + this._elements[7]; + target.z = this._elements[8] * sx + this._elements[9] * sy + this._elements[10] * sz + this._elements[11]; + return target; + } + + /** + * Transform a point. + * @param source the source point. + * @return the target point. + */ + public transform(source: Coordinate): Coordinate { + return this.transformTo(source, Coordinate.create()); + } + + /** + * Transform bounds. + * @param bounds the bounds. + * @return the transformed bounds. + */ + public transformBounds(bounds: Bounds): Bounds { + /* Not valid? */ + if (bounds.isValid() == false) return bounds; + /* Transform all corners */ + let nbounds: Bounds = new Bounds(); + let point: Coordinate = Coordinate.create(); + for (let i: number = 0; i < 8; i++) { + /* Transform the next corner */ + bounds.getCorner(i, point); + this.transformTo(point, point); + nbounds.add(point); + } + /* Return the new bounds */ + return nbounds; + } + + /** + * Check if the transform matches another transform. + * @param other the other transform. + * @return true if same. + */ + public same(other: Transform): boolean { + for (let i: number = 0; i < 16; i++) if (this._elements[i] != other._elements[i]) return false; + return true; + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return "[Transform:m00=" + this._elements[0] + ",m10=" + this._elements[4] + ",m20=" + this._elements[8] + + ",m01=" + this._elements[1] + ",m11=" + this._elements[5] + ",m21=" + this._elements[9] + + ",m02=" + this._elements[2] + ",m12=" + this._elements[6] + ",m22=" + this._elements[10] + + ",m03=" + this._elements[3] + ",m13=" + this._elements[7] + ",m23=" + this._elements[11] + "]"; + } } diff --git a/core/orbitgt/src/system/buffer/ABuffer.ts b/core/orbitgt/src/system/buffer/ABuffer.ts index 8692ea561d28..01474e2ce2b2 100644 --- a/core/orbitgt/src/system/buffer/ABuffer.ts +++ b/core/orbitgt/src/system/buffer/ABuffer.ts @@ -17,85 +17,85 @@ type float64 = number; */ /** @internal */ export class ABuffer { - /** The content of the buffer */ - private _content: ArrayBuffer; - /** The byte view of the content of the buffer */ - private _contentBytes: Uint8Array; + /** The content of the buffer */ + private _content: ArrayBuffer; + /** The byte view of the content of the buffer */ + private _contentBytes: Uint8Array; - /** - * Create a new buffer. - */ - public constructor(size: int32) { - this._content = (size < 0) ? null : new ArrayBuffer(size); - this._contentBytes = (size < 0) ? null : new Uint8Array(this._content); - } + /** + * Create a new buffer. + */ + public constructor(size: int32) { + this._content = (size < 0) ? null : new ArrayBuffer(size); + this._contentBytes = (size < 0) ? null : new Uint8Array(this._content); + } - /** - * Wrap an existing buffer. - */ - public static wrap(buffer: ArrayBuffer): ABuffer { - let wrapper: ABuffer = new ABuffer(-1); - wrapper._content = buffer; - wrapper._contentBytes = new Uint8Array(wrapper._content); - return wrapper; - } + /** + * Wrap an existing buffer. + */ + public static wrap(buffer: ArrayBuffer): ABuffer { + let wrapper: ABuffer = new ABuffer(-1); + wrapper._content = buffer; + wrapper._contentBytes = new Uint8Array(wrapper._content); + return wrapper; + } - /** - * Wrap an existing buffer. - */ - public static wrapRange(buffer: ArrayBuffer, offset: int32, size: int32): ABuffer { - /* The whole buffer? */ - if ((offset == 0) && (size == buffer.byteLength)) return ABuffer.wrap(buffer); - /* Copy the range */ - let original: ABuffer = ABuffer.wrap(buffer); - let wrapper: ABuffer = new ABuffer(size); - ABuffer.arrayCopy(original, offset, wrapper, 0, size); - return wrapper; - } + /** + * Wrap an existing buffer. + */ + public static wrapRange(buffer: ArrayBuffer, offset: int32, size: int32): ABuffer { + /* The whole buffer? */ + if ((offset == 0) && (size == buffer.byteLength)) return ABuffer.wrap(buffer); + /* Copy the range */ + let original: ABuffer = ABuffer.wrap(buffer); + let wrapper: ABuffer = new ABuffer(size); + ABuffer.arrayCopy(original, offset, wrapper, 0, size); + return wrapper; + } - /** - * Return the content as a native buffer - */ - public toNativeBuffer(): ArrayBuffer { - return this._content; - } + /** + * Return the content as a native buffer + */ + public toNativeBuffer(): ArrayBuffer { + return this._content; + } - /** - * Get the size of the buffer. - */ - public size(): int32 { - return this._contentBytes.byteLength; - } + /** + * Get the size of the buffer. + */ + public size(): int32 { + return this._contentBytes.byteLength; + } - /** - * Get a byte (0..255). - */ - public get(index: int32): int32 { - return this._contentBytes[index]; - } + /** + * Get a byte (0..255). + */ + public get(index: int32): int32 { + return this._contentBytes[index]; + } - /** - * Set a byte. - */ - public set(index: int32, value: int32): void { - this._contentBytes[index] = value; - } + /** + * Set a byte. + */ + public set(index: int32, value: int32): void { + this._contentBytes[index] = value; + } - /** - * Slice a part of the buffer. - */ - public slice(begin: int32, end: int32): ABuffer { - if (begin < 0) begin += this._content.byteLength; - if (end < 0) end += this._content.byteLength; - let result: ABuffer = new ABuffer(end - begin); - for (let i: number = 0; i < result._content.byteLength; i++) result.set(i, this.get(begin + i)); - return result; - } + /** + * Slice a part of the buffer. + */ + public slice(begin: int32, end: int32): ABuffer { + if (begin < 0) begin += this._content.byteLength; + if (end < 0) end += this._content.byteLength; + let result: ABuffer = new ABuffer(end - begin); + for (let i: number = 0; i < result._content.byteLength; i++) result.set(i, this.get(begin + i)); + return result; + } - /** - * Copy data from a source to a target buffer. - */ - public static arrayCopy(source: ABuffer, sourceIndex: int32, target: ABuffer, targetIndex: int32, count: int32): void { - for (let i: number = 0; i < count; i++) target.set(targetIndex++, source.get(sourceIndex++)); - } + /** + * Copy data from a source to a target buffer. + */ + public static arrayCopy(source: ABuffer, sourceIndex: int32, target: ABuffer, targetIndex: int32, count: int32): void { + for (let i: number = 0; i < count; i++) target.set(targetIndex++, source.get(sourceIndex++)); + } } diff --git a/core/orbitgt/src/system/buffer/Float32Buffer.ts b/core/orbitgt/src/system/buffer/Float32Buffer.ts index 7266e4aaf940..d346cb971e1f 100644 --- a/core/orbitgt/src/system/buffer/Float32Buffer.ts +++ b/core/orbitgt/src/system/buffer/Float32Buffer.ts @@ -21,58 +21,58 @@ import { LittleEndian } from "./LittleEndian"; */ /** @internal */ export class Float32Buffer { - /** The number of bytes per element */ - public static readonly BYTES_PER_ELEMENT: int32 = 4; + /** The number of bytes per element */ + public static readonly BYTES_PER_ELEMENT: int32 = 4; - /** The underlying buffer */ - private _buffer: ABuffer; - /** The byte offset of the first element */ - private _offset: int32; - /** The number of elements */ - private _count: int32; + /** The underlying buffer */ + private _buffer: ABuffer; + /** The byte offset of the first element */ + private _offset: int32; + /** The number of elements */ + private _count: int32; - /** - * Create a new typed buffer. - */ - public constructor(buffer: ABuffer, offset: int32, size: int32) { - this._buffer = buffer; - this._offset = offset; - this._count = size; - } + /** + * Create a new typed buffer. + */ + public constructor(buffer: ABuffer, offset: int32, size: int32) { + this._buffer = buffer; + this._offset = offset; + this._count = size; + } - /** - * Wrap a raw buffer. - */ - public static wrap(buffer: ABuffer): Float32Buffer { - return new Float32Buffer(buffer, 0, Numbers.divInt(buffer.size(), 4)); - } + /** + * Wrap a raw buffer. + */ + public static wrap(buffer: ABuffer): Float32Buffer { + return new Float32Buffer(buffer, 0, Numbers.divInt(buffer.size(), 4)); + } - /** - * Get the underlying buffer. - * @return the underlying buffer. - */ - public getBuffer(): ABuffer { - return this._buffer; - } + /** + * Get the underlying buffer. + * @return the underlying buffer. + */ + public getBuffer(): ABuffer { + return this._buffer; + } - /** - * Get the length. - */ - public size(): int32 { - return this._count; - } + /** + * Get the length. + */ + public size(): int32 { + return this._count; + } - /** - * Get an element. - */ - public get(index: int32): float32 { - return LittleEndian.readBufferFloat(this._buffer, this._offset + 4 * index); - } + /** + * Get an element. + */ + public get(index: int32): float32 { + return LittleEndian.readBufferFloat(this._buffer, this._offset + 4 * index); + } - /** - * Set an element. - */ - public set(index: int32, value: float32): void { - LittleEndian.writeBufferFloat(this._buffer, this._offset + 4 * index, value); - } + /** + * Set an element. + */ + public set(index: int32, value: float32): void { + LittleEndian.writeBufferFloat(this._buffer, this._offset + 4 * index, value); + } } diff --git a/core/orbitgt/src/system/buffer/LittleEndian.ts b/core/orbitgt/src/system/buffer/LittleEndian.ts index 0ff506d91961..b94835670bc2 100644 --- a/core/orbitgt/src/system/buffer/LittleEndian.ts +++ b/core/orbitgt/src/system/buffer/LittleEndian.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.buffer; +// package orbitgt.system.buffer; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { InStream } from "../io/InStream"; import { OutStream } from "../io/OutStream"; import { ALong } from "../runtime/ALong"; @@ -27,312 +26,312 @@ import { ABuffer } from "./ABuffer"; */ /** @internal */ export class LittleEndian { - /** - * This class has static methods only. - */ - private constructor() { - } - - /** - * Read an unsigned 8-bit integer. - */ - public static readBufferByte(buffer: ABuffer, offset: int32): int32 { - let b0: int32 = buffer.get(offset); - return (b0); - } - - /** - * Read an unsigned 8-bit integer. - */ - public static readStreamByte(stream: InStream): int32 { - let b0: int32 = stream.read(); - return (b0); - } - - /** - * Write an unsigned 8-bit integer. - */ - public static writeBufferByte(buffer: ABuffer, offset: int32, value: int32): void { - buffer.set(offset, value); - } - - /** - * Write an unsigned 8-bit integer. - */ - public static writeStreamByte(stream: OutStream, value: int32): void { - stream.write(value); - } - - /** - * Read an unsigned 16-bit integer. - */ - public static readBufferShort(buffer: ABuffer, offset: int32): int32 { - let b0: int32 = buffer.get(offset++); - let b1: int32 = buffer.get(offset++); - return (b1 << 8) | (b0); - } - - /** - * Read an unsigned 16-bit integer. - */ - public static readStreamShort(stream: InStream): int32 { - let b0: int32 = stream.read(); - let b1: int32 = stream.read(); - return (b1 << 8) | (b0); - } - - /** - * Write an unsigned 16-bit integer. - */ - public static writeBufferShort(buffer: ABuffer, offset: int32, value: int32): void { - buffer.set(offset++, (value >> 0)); - buffer.set(offset++, (value >> 8)); - } - - /** - * Write an unsigned 16-bit integer. - */ - public static writeStreamShort(stream: OutStream, value: int32): void { - stream.write(value >> 0); - stream.write(value >> 8); - } - - /** - * Read an unsigned 24-bit integer. - */ - public static readBufferInt3(buffer: ABuffer, offset: int32): int32 { - let b0: int32 = buffer.get(offset++); - let b1: int32 = buffer.get(offset++); - let b2: int32 = buffer.get(offset++); - return (b2 << 16) | (b1 << 8) | (b0); - } - - /** - * Read an unsigned 24-bit integer. - */ - public static readStreamInt3(stream: InStream): int32 { - let b0: int32 = stream.read(); - let b1: int32 = stream.read(); - let b2: int32 = stream.read(); - return (b2 << 16) | (b1 << 8) | (b0); - } - - /** - * Write an unsigned 24-bit integer. - */ - public static writeBufferInt3(buffer: ABuffer, offset: int32, value: int32): void { - buffer.set(offset++, (value >> 0)); - buffer.set(offset++, (value >> 8)); - buffer.set(offset++, (value >> 16)); - } - - /** - * Write an unsigned 24-bit integer. - */ - public static writeStreamInt3(stream: OutStream, value: int32): void { - stream.write(value >> 0); - stream.write(value >> 8); - stream.write(value >> 16); - } - - /** - * Read a signed 32-bit integer. - */ - public static readBufferInt(buffer: ABuffer, offset: int32): int32 { - let b0: int32 = buffer.get(offset++); - let b1: int32 = buffer.get(offset++); - let b2: int32 = buffer.get(offset++); - let b3: int32 = buffer.get(offset++); - return (b3 << 24) | (b2 << 16) | (b1 << 8) | (b0); - } - - /** - * Read a signed 32-bit integer. - */ - public static readStreamInt(stream: InStream): int32 { - let b0: int32 = stream.read(); - let b1: int32 = stream.read(); - let b2: int32 = stream.read(); - let b3: int32 = stream.read(); - return (b3 << 24) | (b2 << 16) | (b1 << 8) | (b0); - } - - /** - * Write a signed 32-bit integer. - */ - public static writeBufferInt(buffer: ABuffer, offset: int32, value: int32): void { - buffer.set(offset++, (value >> 0)); - buffer.set(offset++, (value >> 8)); - buffer.set(offset++, (value >> 16)); - buffer.set(offset++, (value >> 24)); - } - - /** - * Write a signed 32-bit integer. - */ - public static writeStreamInt(stream: OutStream, value: int32): void { - stream.write(value >> 0); - stream.write(value >> 8); - stream.write(value >> 16); - stream.write(value >> 24); - } - - /** - * Read a signed 64-bit integer. - */ - public static readBufferLong(buffer: ABuffer, offset: int32): ALong { - let b0: int32 = buffer.get(offset++); - let b1: int32 = buffer.get(offset++); - let b2: int32 = buffer.get(offset++); - let b3: int32 = buffer.get(offset++); - let b4: int32 = buffer.get(offset++); - let b5: int32 = buffer.get(offset++); - let b6: int32 = buffer.get(offset++); - let b7: int32 = buffer.get(offset++); - return ALong.fromBytes(b7, b6, b5, b4, b3, b2, b1, b0); - } - - /** - * Read a signed 64-bit integer. - */ - public static readStreamLong(stream: InStream): ALong { - let b0: int32 = stream.read(); - let b1: int32 = stream.read(); - let b2: int32 = stream.read(); - let b3: int32 = stream.read(); - let b4: int32 = stream.read(); - let b5: int32 = stream.read(); - let b6: int32 = stream.read(); - let b7: int32 = stream.read(); - return ALong.fromBytes(b7, b6, b5, b4, b3, b2, b1, b0); - } - - /** - * Write a signed 64-bit integer. - */ - public static writeBufferLong(buffer: ABuffer, offset: int32, value: ALong): void { - buffer.set(offset++, value.getByte(0)); - buffer.set(offset++, value.getByte(1)); - buffer.set(offset++, value.getByte(2)); - buffer.set(offset++, value.getByte(3)); - buffer.set(offset++, value.getByte(4)); - buffer.set(offset++, value.getByte(5)); - buffer.set(offset++, value.getByte(6)); - buffer.set(offset++, value.getByte(7)); - } - - /** - * Write a signed 64-bit integer. - */ - public static writeStreamLong(stream: OutStream, value: ALong): void { - stream.write(value.getByte(0)); - stream.write(value.getByte(1)); - stream.write(value.getByte(2)); - stream.write(value.getByte(3)); - stream.write(value.getByte(4)); - stream.write(value.getByte(5)); - stream.write(value.getByte(6)); - stream.write(value.getByte(7)); - } - - /** - * Read a signed 32-bit float. - */ - public static readBufferFloat(buffer: ABuffer, offset: int32): float32 { - return Numbers.intBitsToFloat(LittleEndian.readBufferInt(buffer, offset)); - } - - /** - * Read a signed 32-bit float. - */ - public static readStreamFloat(stream: InStream): float32 { - return Numbers.intBitsToFloat(LittleEndian.readStreamInt(stream)); - } - - /** - * Write a signed 32-bit float. - */ - public static writeBufferFloat(buffer: ABuffer, offset: int32, value: float32): void { - LittleEndian.writeBufferInt(buffer, offset, Numbers.floatToIntBits(value)); - } - - /** - * Write a signed 32-bit float. - */ - public static writeStreamFloat(stream: OutStream, value: float32): void { - LittleEndian.writeStreamInt(stream, Numbers.floatToIntBits(value)); - } - - /** - * Read a signed 64-bit float. - */ - public static readBufferDouble(buffer: ABuffer, offset: int32): float64 { - return Numbers.longBitsToDouble(LittleEndian.readBufferLong(buffer, offset)); - } - - /** - * Read a signed 64-bit float. - */ - public static readStreamDouble(stream: InStream): float64 { - return Numbers.longBitsToDouble(LittleEndian.readStreamLong(stream)); - } - - /** - * Write a signed 64-bit float. - */ - public static writeBufferDouble(buffer: ABuffer, offset: int32, value: float64): void { - LittleEndian.writeBufferLong(buffer, offset, Numbers.doubleToLongBits(value)); - } - - /** - * Write a signed 64-bit float. - */ - public static writeStreamDouble(stream: OutStream, value: float64): void { - LittleEndian.writeStreamLong(stream, Numbers.doubleToLongBits(value)); - } - - /** - * Read a string. - */ - public static readBufferString(buffer: ABuffer, offset: int32): string { - let valueLength: int32 = LittleEndian.readBufferInt(buffer, offset); - if (valueLength < 0) return null; - offset += 4; - let value: string = ""; - for (let i: number = 0; i < valueLength; i++) value = Strings.appendChar(value, LittleEndian.readBufferShort(buffer, offset + 2 * i)); - return value; - } - - /** - * Read a string. - */ - public static readStreamString(stream: InStream): string { - let valueLength: int32 = LittleEndian.readStreamInt(stream); - if (valueLength < 0) return null; - let value: string = ""; - for (let i: number = 0; i < valueLength; i++) value = Strings.appendChar(value, LittleEndian.readStreamShort(stream)); - return value; - } - - /** - * Write a string. - */ - public static writeStreamString(stream: OutStream, value: string): void { - if (value == null) { - LittleEndian.writeStreamInt(stream, -1); - } - else { - let valueLength: int32 = Strings.getLength(value); - LittleEndian.writeStreamInt(stream, valueLength); - for (let i: number = 0; i < valueLength; i++) LittleEndian.writeStreamShort(stream, Strings.getCharAt(value, i)); - } - } - - /** - * Get the number of bytes in a string. - */ - public static getStringByteCount(value: string): int32 { - if (value == null) return 4; - else return 4 + 2 * Strings.getLength(value); - } + /** + * This class has static methods only. + */ + private constructor() { + } + + /** + * Read an unsigned 8-bit integer. + */ + public static readBufferByte(buffer: ABuffer, offset: int32): int32 { + let b0: int32 = buffer.get(offset); + return b0; + } + + /** + * Read an unsigned 8-bit integer. + */ + public static readStreamByte(stream: InStream): int32 { + let b0: int32 = stream.read(); + return b0; + } + + /** + * Write an unsigned 8-bit integer. + */ + public static writeBufferByte(buffer: ABuffer, offset: int32, value: int32): void { + buffer.set(offset, value); + } + + /** + * Write an unsigned 8-bit integer. + */ + public static writeStreamByte(stream: OutStream, value: int32): void { + stream.write(value); + } + + /** + * Read an unsigned 16-bit integer. + */ + public static readBufferShort(buffer: ABuffer, offset: int32): int32 { + let b0: int32 = buffer.get(offset++); + let b1: int32 = buffer.get(offset++); + return (b1 << 8) | b0; + } + + /** + * Read an unsigned 16-bit integer. + */ + public static readStreamShort(stream: InStream): int32 { + let b0: int32 = stream.read(); + let b1: int32 = stream.read(); + return (b1 << 8) | b0; + } + + /** + * Write an unsigned 16-bit integer. + */ + public static writeBufferShort(buffer: ABuffer, offset: int32, value: int32): void { + buffer.set(offset++, value >> 0); + buffer.set(offset++, value >> 8); + } + + /** + * Write an unsigned 16-bit integer. + */ + public static writeStreamShort(stream: OutStream, value: int32): void { + stream.write(value >> 0); + stream.write(value >> 8); + } + + /** + * Read an unsigned 24-bit integer. + */ + public static readBufferInt3(buffer: ABuffer, offset: int32): int32 { + let b0: int32 = buffer.get(offset++); + let b1: int32 = buffer.get(offset++); + let b2: int32 = buffer.get(offset++); + return (b2 << 16) | (b1 << 8) | b0; + } + + /** + * Read an unsigned 24-bit integer. + */ + public static readStreamInt3(stream: InStream): int32 { + let b0: int32 = stream.read(); + let b1: int32 = stream.read(); + let b2: int32 = stream.read(); + return (b2 << 16) | (b1 << 8) | b0; + } + + /** + * Write an unsigned 24-bit integer. + */ + public static writeBufferInt3(buffer: ABuffer, offset: int32, value: int32): void { + buffer.set(offset++, value >> 0); + buffer.set(offset++, value >> 8); + buffer.set(offset++, value >> 16); + } + + /** + * Write an unsigned 24-bit integer. + */ + public static writeStreamInt3(stream: OutStream, value: int32): void { + stream.write(value >> 0); + stream.write(value >> 8); + stream.write(value >> 16); + } + + /** + * Read a signed 32-bit integer. + */ + public static readBufferInt(buffer: ABuffer, offset: int32): int32 { + let b0: int32 = buffer.get(offset++); + let b1: int32 = buffer.get(offset++); + let b2: int32 = buffer.get(offset++); + let b3: int32 = buffer.get(offset++); + return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } + + /** + * Read a signed 32-bit integer. + */ + public static readStreamInt(stream: InStream): int32 { + let b0: int32 = stream.read(); + let b1: int32 = stream.read(); + let b2: int32 = stream.read(); + let b3: int32 = stream.read(); + return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; + } + + /** + * Write a signed 32-bit integer. + */ + public static writeBufferInt(buffer: ABuffer, offset: int32, value: int32): void { + buffer.set(offset++, value >> 0); + buffer.set(offset++, value >> 8); + buffer.set(offset++, value >> 16); + buffer.set(offset++, value >> 24); + } + + /** + * Write a signed 32-bit integer. + */ + public static writeStreamInt(stream: OutStream, value: int32): void { + stream.write(value >> 0); + stream.write(value >> 8); + stream.write(value >> 16); + stream.write(value >> 24); + } + + /** + * Read a signed 64-bit integer. + */ + public static readBufferLong(buffer: ABuffer, offset: int32): ALong { + let b0: int32 = buffer.get(offset++); + let b1: int32 = buffer.get(offset++); + let b2: int32 = buffer.get(offset++); + let b3: int32 = buffer.get(offset++); + let b4: int32 = buffer.get(offset++); + let b5: int32 = buffer.get(offset++); + let b6: int32 = buffer.get(offset++); + let b7: int32 = buffer.get(offset++); + return ALong.fromBytes(b7, b6, b5, b4, b3, b2, b1, b0); + } + + /** + * Read a signed 64-bit integer. + */ + public static readStreamLong(stream: InStream): ALong { + let b0: int32 = stream.read(); + let b1: int32 = stream.read(); + let b2: int32 = stream.read(); + let b3: int32 = stream.read(); + let b4: int32 = stream.read(); + let b5: int32 = stream.read(); + let b6: int32 = stream.read(); + let b7: int32 = stream.read(); + return ALong.fromBytes(b7, b6, b5, b4, b3, b2, b1, b0); + } + + /** + * Write a signed 64-bit integer. + */ + public static writeBufferLong(buffer: ABuffer, offset: int32, value: ALong): void { + buffer.set(offset++, value.getByte(0)); + buffer.set(offset++, value.getByte(1)); + buffer.set(offset++, value.getByte(2)); + buffer.set(offset++, value.getByte(3)); + buffer.set(offset++, value.getByte(4)); + buffer.set(offset++, value.getByte(5)); + buffer.set(offset++, value.getByte(6)); + buffer.set(offset++, value.getByte(7)); + } + + /** + * Write a signed 64-bit integer. + */ + public static writeStreamLong(stream: OutStream, value: ALong): void { + stream.write(value.getByte(0)); + stream.write(value.getByte(1)); + stream.write(value.getByte(2)); + stream.write(value.getByte(3)); + stream.write(value.getByte(4)); + stream.write(value.getByte(5)); + stream.write(value.getByte(6)); + stream.write(value.getByte(7)); + } + + /** + * Read a signed 32-bit float. + */ + public static readBufferFloat(buffer: ABuffer, offset: int32): float32 { + return Numbers.intBitsToFloat(LittleEndian.readBufferInt(buffer, offset)); + } + + /** + * Read a signed 32-bit float. + */ + public static readStreamFloat(stream: InStream): float32 { + return Numbers.intBitsToFloat(LittleEndian.readStreamInt(stream)); + } + + /** + * Write a signed 32-bit float. + */ + public static writeBufferFloat(buffer: ABuffer, offset: int32, value: float32): void { + LittleEndian.writeBufferInt(buffer, offset, Numbers.floatToIntBits(value)); + } + + /** + * Write a signed 32-bit float. + */ + public static writeStreamFloat(stream: OutStream, value: float32): void { + LittleEndian.writeStreamInt(stream, Numbers.floatToIntBits(value)); + } + + /** + * Read a signed 64-bit float. + */ + public static readBufferDouble(buffer: ABuffer, offset: int32): float64 { + return Numbers.longBitsToDouble(LittleEndian.readBufferLong(buffer, offset)); + } + + /** + * Read a signed 64-bit float. + */ + public static readStreamDouble(stream: InStream): float64 { + return Numbers.longBitsToDouble(LittleEndian.readStreamLong(stream)); + } + + /** + * Write a signed 64-bit float. + */ + public static writeBufferDouble(buffer: ABuffer, offset: int32, value: float64): void { + LittleEndian.writeBufferLong(buffer, offset, Numbers.doubleToLongBits(value)); + } + + /** + * Write a signed 64-bit float. + */ + public static writeStreamDouble(stream: OutStream, value: float64): void { + LittleEndian.writeStreamLong(stream, Numbers.doubleToLongBits(value)); + } + + /** + * Read a string. + */ + public static readBufferString(buffer: ABuffer, offset: int32): string { + let valueLength: int32 = LittleEndian.readBufferInt(buffer, offset); + if (valueLength < 0) return null; + offset += 4; + let value: string = ""; + for (let i: number = 0; i < valueLength; i++) value = Strings.appendChar(value, LittleEndian.readBufferShort(buffer, offset + 2 * i)); + return value; + } + + /** + * Read a string. + */ + public static readStreamString(stream: InStream): string { + let valueLength: int32 = LittleEndian.readStreamInt(stream); + if (valueLength < 0) return null; + let value: string = ""; + for (let i: number = 0; i < valueLength; i++) value = Strings.appendChar(value, LittleEndian.readStreamShort(stream)); + return value; + } + + /** + * Write a string. + */ + public static writeStreamString(stream: OutStream, value: string): void { + if (value == null) { + LittleEndian.writeStreamInt(stream, -1); + } + else { + let valueLength: int32 = Strings.getLength(value); + LittleEndian.writeStreamInt(stream, valueLength); + for (let i: number = 0; i < valueLength; i++) LittleEndian.writeStreamShort(stream, Strings.getCharAt(value, i)); + } + } + + /** + * Get the number of bytes in a string. + */ + public static getStringByteCount(value: string): int32 { + if (value == null) return 4; + else return 4 + 2 * Strings.getLength(value); + } } diff --git a/core/orbitgt/src/system/buffer/Uint16Buffer.ts b/core/orbitgt/src/system/buffer/Uint16Buffer.ts index e3603b158d53..510333fed3ef 100644 --- a/core/orbitgt/src/system/buffer/Uint16Buffer.ts +++ b/core/orbitgt/src/system/buffer/Uint16Buffer.ts @@ -20,65 +20,65 @@ import { LittleEndian } from "./LittleEndian"; */ /** @internal */ export class Uint16Buffer { - /** The number of bytes per element */ - public static readonly BYTES_PER_ELEMENT: int32 = 2; + /** The number of bytes per element */ + public static readonly BYTES_PER_ELEMENT: int32 = 2; - /** The underlying buffer */ - private _buffer: ABuffer; - /** The byte offset of the first element */ - private _offset: int32; - /** The number of elements */ - private _count: int32; + /** The underlying buffer */ + private _buffer: ABuffer; + /** The byte offset of the first element */ + private _offset: int32; + /** The number of elements */ + private _count: int32; - /** - * Create a new typed buffer. - */ - public constructor(buffer: ABuffer, offset: int32, size: int32) { - this._buffer = buffer; - this._offset = offset; - this._count = size; - } + /** + * Create a new typed buffer. + */ + public constructor(buffer: ABuffer, offset: int32, size: int32) { + this._buffer = buffer; + this._offset = offset; + this._count = size; + } - /** - * Wrap a raw buffer. - */ - public static wrap(buffer: ABuffer): Uint16Buffer { - return new Uint16Buffer(buffer, 0, buffer.size()); - } + /** + * Wrap a raw buffer. + */ + public static wrap(buffer: ABuffer): Uint16Buffer { + return new Uint16Buffer(buffer, 0, buffer.size()); + } - /** - * Return the content as a native buffer - */ - public toNativeBuffer(): Uint16Array { - return new Uint16Array(this._buffer.toNativeBuffer(), this._offset, this._count); - } + /** + * Return the content as a native buffer + */ + public toNativeBuffer(): Uint16Array { + return new Uint16Array(this._buffer.toNativeBuffer(), this._offset, this._count); + } - /** - * Get the underlying buffer. - * @return the underlying buffer. - */ - public getBuffer(): ABuffer { - return this._buffer; - } + /** + * Get the underlying buffer. + * @return the underlying buffer. + */ + public getBuffer(): ABuffer { + return this._buffer; + } - /** - * Get the length. - */ - public size(): int32 { - return this._count; - } + /** + * Get the length. + */ + public size(): int32 { + return this._count; + } - /** - * Get an element. - */ - public get(index: int32): int32 { - return LittleEndian.readBufferShort(this._buffer, this._offset + 2 * index); - } + /** + * Get an element. + */ + public get(index: int32): int32 { + return LittleEndian.readBufferShort(this._buffer, this._offset + 2 * index); + } - /** - * Set an element. - */ - public set(index: int32, value: int32): void { - LittleEndian.writeBufferShort(this._buffer, this._offset + 2 * index, value); - } + /** + * Set an element. + */ + public set(index: int32, value: int32): void { + LittleEndian.writeBufferShort(this._buffer, this._offset + 2 * index, value); + } } diff --git a/core/orbitgt/src/system/buffer/Uint8Buffer.ts b/core/orbitgt/src/system/buffer/Uint8Buffer.ts index 9d97b02e24b7..799234bf375d 100644 --- a/core/orbitgt/src/system/buffer/Uint8Buffer.ts +++ b/core/orbitgt/src/system/buffer/Uint8Buffer.ts @@ -20,65 +20,65 @@ import { LittleEndian } from "./LittleEndian"; */ /** @internal */ export class Uint8Buffer { - /** The number of bytes per element */ - public static readonly BYTES_PER_ELEMENT: int32 = 1; + /** The number of bytes per element */ + public static readonly BYTES_PER_ELEMENT: int32 = 1; - /** The underlying buffer */ - private _buffer: ABuffer; - /** The byte offset of the first element */ - private _offset: int32; - /** The number of elements */ - private _count: int32; + /** The underlying buffer */ + private _buffer: ABuffer; + /** The byte offset of the first element */ + private _offset: int32; + /** The number of elements */ + private _count: int32; - /** - * Create a new typed buffer. - */ - public constructor(buffer: ABuffer, offset: int32, size: int32) { - this._buffer = buffer; - this._offset = offset; - this._count = size; - } + /** + * Create a new typed buffer. + */ + public constructor(buffer: ABuffer, offset: int32, size: int32) { + this._buffer = buffer; + this._offset = offset; + this._count = size; + } - /** - * Wrap a raw buffer. - */ - public static wrap(buffer: ABuffer): Uint8Buffer { - return new Uint8Buffer(buffer, 0, buffer.size()); - } + /** + * Wrap a raw buffer. + */ + public static wrap(buffer: ABuffer): Uint8Buffer { + return new Uint8Buffer(buffer, 0, buffer.size()); + } - /** - * Return the content as a native buffer - */ - public toNativeBuffer(): Uint8Array { - return new Uint8Array(this._buffer.toNativeBuffer(), this._offset, this._count); - } + /** + * Return the content as a native buffer + */ + public toNativeBuffer(): Uint8Array { + return new Uint8Array(this._buffer.toNativeBuffer(), this._offset, this._count); + } - /** - * Get the underlying buffer. - * @return the underlying buffer. - */ - public getBuffer(): ABuffer { - return this._buffer; - } + /** + * Get the underlying buffer. + * @return the underlying buffer. + */ + public getBuffer(): ABuffer { + return this._buffer; + } - /** - * Get the length. - */ - public size(): int32 { - return this._count; - } + /** + * Get the length. + */ + public size(): int32 { + return this._count; + } - /** - * Get an element. - */ - public get(index: int32): int32 { - return LittleEndian.readBufferByte(this._buffer, this._offset + index); - } + /** + * Get an element. + */ + public get(index: int32): int32 { + return LittleEndian.readBufferByte(this._buffer, this._offset + index); + } - /** - * Set an element. - */ - public set(index: int32, value: int32): void { - LittleEndian.writeBufferByte(this._buffer, this._offset + index, value); - } + /** + * Set an element. + */ + public set(index: int32, value: int32): void { + LittleEndian.writeBufferByte(this._buffer, this._offset + index, value); + } } diff --git a/core/orbitgt/src/system/collection/AList.ts b/core/orbitgt/src/system/collection/AList.ts index a772e85a460d..4c25de5f5b4b 100644 --- a/core/orbitgt/src/system/collection/AList.ts +++ b/core/orbitgt/src/system/collection/AList.ts @@ -18,70 +18,71 @@ import { iComparator } from "../runtime/iComparator"; * Class AList defines a typed list of elements. */ /** @internal */ -export class AList -{ - private _elements: Array; +export class AList { + private _elements: Array; - public constructor(capacity: number = 10) { - this._elements = []; - } + public constructor(capacity: number = 10) { + this._elements = []; + } - public size(): int32 { - return this._elements.length; - } + public size(): int32 { + return this._elements.length; + } - public add(element: T): void { - this._elements.push(element); - } + public add(element: T): void { + this._elements.push(element); + } - public addAt(index: number, element: T): void { - this._elements.splice(index, 0, element); - } + public addAt(index: number, element: T): void { + this._elements.splice(index, 0, element); + } - public remove(index: int32): void { - this._elements.splice(index, 1); - } + public remove(index: int32): void { + this._elements.splice(index, 1); + } - public get(index: int32): T { - return this._elements[index]; - } + public get(index: int32): T { + return this._elements[index]; + } - public indexOf(element: T): int32 { - for (let i: number = 0; i < this._elements.length; i++) if (this._elements[i] === element) return i; - return -1; - } + public indexOf(element: T): int32 { + for (let i: number = 0; i < this._elements.length; i++) if (this._elements[i] === element) return i; + return -1; + } - public contains(element: T): boolean { - return (this.indexOf(element) >= 0); - } + public contains(element: T): boolean { + return (this.indexOf(element) >= 0); + } - public clear(): void { - this._elements.splice(0, this._elements.length); - } + public clear(): void { + this._elements.splice(0, this._elements.length); + } - public sort(comparator: iComparator): void { - this._elements.sort(function (o1: T, o2: T) { return comparator.compare(o1, o2); }); - } + public sort(comparator: iComparator): void { + this._elements.sort(function(o1: T, o2: T) { + return comparator.compare(o1, o2); + }); + } - public toArray(holder: any): Array { - return this._elements; - } + public toArray(holder: any): Array { + return this._elements; + } - /** - * Get an iterator to use in "for of" loops. - */ - [Symbol.iterator]() { - let iteratorList: Array = this._elements; - let index: number = 0; - return { - next(): IteratorResult { - if (index < iteratorList.length) { - return { done: false, value: iteratorList[index++] } - } - else { - return { done: true, value: null } - } - } + /** + * Get an iterator to use in "for of" loops. + */ + [Symbol.iterator]() { + let iteratorList: Array = this._elements; + let index: number = 0; + return { + next(): IteratorResult { + if (index < iteratorList.length) { + return { done: false, value: iteratorList[index++] }; } - } + else { + return { done: true, value: null }; + } + }, + }; + } } diff --git a/core/orbitgt/src/system/collection/IntMap.ts b/core/orbitgt/src/system/collection/IntMap.ts index 5546bc64c5e4..e1bbefcdba87 100644 --- a/core/orbitgt/src/system/collection/IntMap.ts +++ b/core/orbitgt/src/system/collection/IntMap.ts @@ -16,31 +16,30 @@ type float64 = number; * Class IntMap defines a map of elements in which the keys are integer numbers. */ /** @internal */ -export class IntMap -{ - private _map: Map; +export class IntMap { + private _map: Map; - public constructor() { - this._map = new Map(); - } + public constructor() { + this._map = new Map(); + } - public size(): int32 { - return this._map.size; - } + public size(): int32 { + return this._map.size; + } - public contains(key: int32): boolean { - return this._map.has(key); - } + public contains(key: int32): boolean { + return this._map.has(key); + } - public get(key: int32): V { - return this._map.get(key); - } + public get(key: int32): V { + return this._map.get(key); + } - public set(key: int32, value: V): void { - this._map.set(key, value); - } + public set(key: int32, value: V): void { + this._map.set(key, value); + } - public clear(): void { - this._map.clear(); - } + public clear(): void { + this._map.clear(); + } } diff --git a/core/orbitgt/src/system/collection/StringMap.ts b/core/orbitgt/src/system/collection/StringMap.ts index fb35401faf25..7e3f940f0f37 100644 --- a/core/orbitgt/src/system/collection/StringMap.ts +++ b/core/orbitgt/src/system/collection/StringMap.ts @@ -18,63 +18,62 @@ import { AList } from "./AList"; * Class StringMap defines a map of elements in which the keys are strings. */ /** @internal */ -export class StringMap -{ - private _map: Map; - - public constructor() { - this._map = new Map(); - } - - public size(): int32 { - return this._map.size; - } - - public contains(key: string): boolean { - return this._map.has(key); - } - - public containsKey(key: string): boolean { - return this._map.has(key); - } - - public get(key: string): V { - return this._map.get(key); - } - - public set(key: string, value: V): void { - this._map.set(key, value); - } - - public put(key: string, value: V): void { - this._map.set(key, value); - } - - public remove(key: string): void { - this._map.delete(key); - } - - public clear(): void { - this._map.clear(); - } - - public keysArray(): Array { - return Array.from(this._map.keys()); - } - - public keys(): AList { - let keys: AList = new AList(); - for (let key of this._map.keys()) keys.add(key); - return keys; - } - - public valuesArray(): Array { - return Array.from(this._map.values()); - } - - public values(): AList { - let values: AList = new AList(); - for (let value of this._map.values()) values.add(value); - return values; - } +export class StringMap { + private _map: Map; + + public constructor() { + this._map = new Map(); + } + + public size(): int32 { + return this._map.size; + } + + public contains(key: string): boolean { + return this._map.has(key); + } + + public containsKey(key: string): boolean { + return this._map.has(key); + } + + public get(key: string): V { + return this._map.get(key); + } + + public set(key: string, value: V): void { + this._map.set(key, value); + } + + public put(key: string, value: V): void { + this._map.set(key, value); + } + + public remove(key: string): void { + this._map.delete(key); + } + + public clear(): void { + this._map.clear(); + } + + public keysArray(): Array { + return Array.from(this._map.keys()); + } + + public keys(): AList { + let keys: AList = new AList(); + for (let key of this._map.keys()) keys.add(key); + return keys; + } + + public valuesArray(): Array { + return Array.from(this._map.values()); + } + + public values(): AList { + let values: AList = new AList(); + for (let value of this._map.values()) values.add(value); + return values; + } } diff --git a/core/orbitgt/src/system/io/ABufferInStream.ts b/core/orbitgt/src/system/io/ABufferInStream.ts index 11734f7bed3f..69218769bbc7 100644 --- a/core/orbitgt/src/system/io/ABufferInStream.ts +++ b/core/orbitgt/src/system/io/ABufferInStream.ts @@ -22,42 +22,42 @@ import { InStream } from "./InStream"; */ /** @internal */ export class ABufferInStream extends InStream { - private _buffer: ABuffer; - private _offset: int32; - private _size: int32; - - private _position: int32; - private _extent: int32; - - /** - * Create a new stream. - */ - public constructor(buffer: ABuffer, offset: int32, size: int32) { - super(); - this._buffer = buffer; - this._offset = offset; - this._size = size; - this._position = this._offset; - this._extent = this._offset + size; - } - - public getOffset(): int32 { - return this._offset; - } - - public getSize(): int32 { - return this._size; - } - - public getPosition(): int32 { - return this._position; - } - - /** - * InStream method override - */ - public override read(): int32 { - if (this._position >= this._extent) return -1; - return this._buffer.get(this._position++); - } + private _buffer: ABuffer; + private _offset: int32; + private _size: int32; + + private _position: int32; + private _extent: int32; + + /** + * Create a new stream. + */ + public constructor(buffer: ABuffer, offset: int32, size: int32) { + super(); + this._buffer = buffer; + this._offset = offset; + this._size = size; + this._position = this._offset; + this._extent = this._offset + size; + } + + public getOffset(): int32 { + return this._offset; + } + + public getSize(): int32 { + return this._size; + } + + public getPosition(): int32 { + return this._position; + } + + /** + * InStream method override + */ + public override read(): int32 { + if (this._position >= this._extent) return -1; + return this._buffer.get(this._position++); + } } diff --git a/core/orbitgt/src/system/io/InStream.ts b/core/orbitgt/src/system/io/InStream.ts index e4d856c60dde..8e0492344e7c 100644 --- a/core/orbitgt/src/system/io/InStream.ts +++ b/core/orbitgt/src/system/io/InStream.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.io; +// package orbitgt.system.io; type int8 = number; type int16 = number; @@ -19,23 +19,23 @@ type float64 = number; */ /** @internal */ export class InStream { - /** - * Create a new stream. - */ - public constructor() { - } + /** + * Create a new stream. + */ + public constructor() { + } - /** - * Read the next byte (range 0..255, or -1 at the end of the stream). - */ - public read(): int32 { - /* Override in subclasses */ - return -1; - } + /** + * Read the next byte (range 0..255, or -1 at the end of the stream). + */ + public read(): int32 { + /* Override in subclasses */ + return -1; + } - /** - * Close the stream - */ - public close(): void { - } + /** + * Close the stream + */ + public close(): void { + } } diff --git a/core/orbitgt/src/system/io/OutStream.ts b/core/orbitgt/src/system/io/OutStream.ts index a8e9f85c2cf4..d704580d8e29 100644 --- a/core/orbitgt/src/system/io/OutStream.ts +++ b/core/orbitgt/src/system/io/OutStream.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.io; +// package orbitgt.system.io; type int8 = number; type int16 = number; @@ -19,22 +19,22 @@ type float64 = number; */ /** @internal */ export class OutStream { - /** - * Create a new stream. - */ - public constructor() { - } + /** + * Create a new stream. + */ + public constructor() { + } - /** - * Write the next byte (0.255) (the stream should only look at the lowest 8 bits of the value and ignore all others). - */ - public write(value: int32): void { - /* Override in subclasses */ - } + /** + * Write the next byte (0.255) (the stream should only look at the lowest 8 bits of the value and ignore all others). + */ + public write(value: int32): void { + /* Override in subclasses */ + } - /** - * Close the stream - */ - public close(): void { - } + /** + * Close the stream + */ + public close(): void { + } } diff --git a/core/orbitgt/src/system/runtime/ALong.ts b/core/orbitgt/src/system/runtime/ALong.ts index f554771ebe50..894082458c9d 100644 --- a/core/orbitgt/src/system/runtime/ALong.ts +++ b/core/orbitgt/src/system/runtime/ALong.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.runtime; +// package orbitgt.system.runtime; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ASystem } from "./ASystem"; import { Numbers } from "./Numbers"; import { Strings } from "./Strings"; @@ -26,680 +25,680 @@ import { Strings } from "./Strings"; */ /** @internal */ export class ALong { - /** The value of a 32 bit unit */ - private static readonly _U32: float64 = 4294967296.0; - /** The value of a 31 bit unit */ - private static readonly _U31: float64 = 2147483648.0; - /** The value of a 24 bit unit */ - private static readonly _U24: float64 = 16777216.0; - /** The value of a 16 bit unit */ - private static readonly _U16: float64 = 65536.0; - /** The value of a 8 bit unit */ - private static readonly _U8: float64 = 256.0; - - /** The integer value 0 */ - public static ZERO: ALong = new ALong(0.0, 0.0); - /** The integer value 1 */ - public static ONE: ALong = new ALong(0.0, 1.0); - /** The integer value 2 */ - public static TWO: ALong = new ALong(0.0, 2.0); - /** The integer value 4 */ - public static FOUR: ALong = new ALong(0.0, 4.0); - /** The integer value 10 */ - public static TEN: ALong = new ALong(0.0, 10.0); - /** The integer value -1 */ - public static MINUS_ONE: ALong = new ALong(ALong._U32 - 1.0, ALong._U32 - 1.0); - /** The maximum positive value of a signed_ 64-bit integer (9223372036854775807) */ - public static MAX_VALUE: ALong = new ALong(ALong._U31 - 1.0, ALong._U32 - 1.0); - /** The minimum negative value of a signed 64-bit integer (-9223372036854775808) */ - public static MIN_VALUE: ALong = new ALong(ALong._U31, 0.0); - - /** The high value (unsigned integer [0..U32[ after normalization, negative i64 if >= U31) */ - private _high: float64; - /** The low value (unsigned integer [0..U32[ after normalization) */ - private _low: float64; - - /** - * Create a new value. - * @param high the 32-bit high part. - * @param low the 32-bit low part. - */ - private constructor(high: float64, low: float64) { - this._high = high; - this._low = low; - } - - /** - * Check if the number is zero. - * @return true if zero. - */ - public isZero(): boolean { - return (this._high == 0.0) && (this._low == 0.0); - } - - /** - * Check if the number is not zero. - * @return true if zero. - */ - public isNonZero(): boolean { - return (this.isZero() == false); - } - - /** - * Check if the number is one. - * @return true if one. - */ - public isOne(): boolean { - return (this._high == 0.0) && (this._low == 1.0); - } - - /** - * Check if the number is positive. - * @return true if positive (false if zero). - */ - public isPositive(): boolean { - return this.isZero() ? false : (this._high < ALong._U31); - } - - /** - * Check if the number is negative. - * @return true if negative (false if zero). - */ - public isNegative(): boolean { - return this.isZero() ? false : (this._high >= ALong._U31); - } - - /** - * Normalize the number. - * @return this number for chaining operations. - */ - private static normalize2(high: float64, low: float64): ALong { - // normalize the low part - let overflowLow: float64 = Numbers.floor(low / ALong._U32); - low = (low - overflowLow * ALong._U32); // inside range [0..U32[ - high += overflowLow; - // normalize the high part - let overflowHigh: float64 = Numbers.floor(high / ALong._U32); - high = (high - overflowHigh * ALong._U32); // inside range [0..U32[ - // return the result - return new ALong(high, low); - } - - /** - * Negate the number. - * @return the result. - */ - public negate(): ALong { - /* Zero? */ - if (this.isZero()) { - /* Return this immutable instance */ - return this; - } - /* Compute */ - let resultHigh: float64 = (ALong._U32 - 1.0 - this._high); - let resultLow: float64 = (ALong._U32 - this._low); - /* Overflow? */ - if (resultLow == ALong._U32) { - resultLow = 0.0; - resultHigh += 1.0; // in case we try to invert ALong.MIN_VALUE we get ALong.MIN_VALUE as a result again - } - /* Return the result */ - return new ALong(resultHigh, resultLow); - } - - /** - * Add a number. - * @param value the value to add. - * @return the result. - */ - public add(value: ALong): ALong { - /* Compute */ - let resultHigh: float64 = (this._high + value._high); - let resultLow: float64 = (this._low + value._low); - /* Return the result */ - return ALong.normalize2(resultHigh, resultLow); - } - - /** - * Add a number. - * @param value the value to add. - * @return the result. - */ - public addInt(value: int32): ALong { - return this.add(ALong.fromInt(value)); - } - - /** - * Increase by one. - * @return the result. - */ - public increase(): ALong { - return this.addInt(1); - } - - /** - * Subtract a number. - * @param value the value to subtract. - * @return the result. - */ - public sub(value: ALong): ALong { - return this.add(value.negate()); - } - - /** - * Subtract a number. - * @param value the value to subtract. - * @return the result. - */ - public subInt(value: int32): ALong { - return this.sub(ALong.fromInt(value)); - } - - /** - * Decrease by one. - * @return the result. - */ - public decrease(): ALong { - return this.subInt(1); - } - - /** - * Multiply two unsigned 32-bit integer values. - * @param v1 the first value. - * @param v2 the second value. - * @param high0 the initial high value of the result. - * @return the unsigned 64-bit product. - */ - private static mul2(v1: ALong, v2: ALong): ALong { - /* Zero? */ - if (v1.isZero()) return v1; - if (v2.isZero()) return v2; - /* Make the values unsigned */ - let neg1: int32 = v1.isNegative() ? 1 : 0; - if (neg1 == 1) v1 = v1.negate(); - let neg2: int32 = v2.isNegative() ? 1 : 0; - if (neg2 == 1) v2 = v2.negate(); - /* Split first low into 16-bit parts */ - let a1: float64 = Numbers.floor(v1._low / ALong._U16);; - let a2: float64 = (v1._low - a1 * ALong._U16); - /* Split second low into 16-bit parts */ - let b1: float64 = Numbers.floor(v2._low / ALong._U16);; - let b2: float64 = (v2._low - b1 * ALong._U16); - /* Compute */ - let resultHigh: float64 = (v1._high * v2._low + v1._low * v2._high) + (a1 * b1); - let resultLow: float64 = (a1 * b2 + a2 * b1) * ALong._U16 + (a2 * b2); - let result: ALong = ALong.normalize2(resultHigh, resultLow); - /* Return the result */ - return (neg1 + neg2 == 1) ? result.negate() : result; - } - - /** - * Multiply by a number. - * @param value the value to multiply. - * @return the result. - */ - public mul(value: ALong): ALong { - return ALong.mul2(this, value); - } - - /** - * Multiply by a number. - * @param value the value to multiply. - * @return the result. - */ - public mulInt(value: int32): ALong { - return this.mul(ALong.fromInt(value)); - } - - /** - * Divide by a number. - * @param value the value to divide by. - * @return the result. - */ - public div(value: ALong): ALong { - /* Division by zero? */ - ASystem.assertNot(value.isZero(), "ALong division by ALong zero"); - /* Division by one? */ - if (value.isOne()) return this; - /* Make the values unsigned */ - let currentValue: ALong = this; - let neg1: boolean = currentValue.isNegative(); - if (neg1) currentValue = currentValue.negate(); - let value2: ALong = value; - let neg2: boolean = value2.isNegative(); - if (neg2) value2.negate(); - let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); - /* Loop until the remainder is smaller than the value */ - let result: ALong = ALong.ZERO; - while (currentValue.isLargerThanOrEqualTo(value2)) { - /* Shift the value as much as possible */ - let test: ALong = value2; - let times: ALong = ALong.ONE; - if (test.isSmallerThan(currentValue)) { - while (test.isSmallerThan(currentValue)) { - test = test.mulInt(2); - times = times.mulInt(2); - } - test = test.divInt(2); - times = times.divInt(2); - } - /* Subtract the shifted value */ - currentValue = currentValue.sub(test); - result = result.add(times); - } - /* Return the result */ - return (neg) ? result.negate() : result; - } - - /** - * Divide by a number. - * @param value the value to divide by. - * @return the result. - */ - public divInt(value: int32): ALong { - /* Division by zero? */ - ASystem.assertNot(value == 0, "ALong division by int zero"); - /* Division by one? */ - if (value == 1) return this; - /* Make the values unsigned */ - let value1: ALong = this; - let neg1: boolean = value1.isNegative(); - if (neg1) value1 = value1.negate(); - let neg2: boolean = (value < 0); - if (neg2) value = -1 * value; - let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); - /* Compute */ - let valueF: float64 = (0.0 + value); - let h1: float64 = Numbers.floor(value1._high / valueF); - let h2: float64 = (value1._high - valueF * h1); - let l1: float64 = Numbers.floor(value1._low / valueF); - let l2: float64 = (value1._low - valueF * l1); - let t: float64 = (h2 * ALong._U32 + l2); - let t1: float64 = Numbers.floor(t / valueF); - let t2: float64 = (t - valueF * t1); // remainder - let result: ALong = ALong.normalize2(h1, l1 + t1); - /* Return the result */ - return (neg) ? result.negate() : result; - } - - /** - * Modulate by a number. - * @param value the value to modulate by. - * @return the result. - */ - public mod(value: ALong): ALong { - /* Division by zero? */ - ASystem.assertNot(value.isZero(), "ALong modulo by ALong zero"); - /* Division by one? */ - if (value.isOne()) return ALong.ZERO; - /* Compute */ - let result: ALong = this.sub(this.div(value).mul(value)); - /* Return the result */ - return result; - } - - /** - * Modulate by a number. - * @param value the value to modulate by. - * @return the modulo value. - */ - public modInt(value: int32): int32 { - /* Division by zero? */ - ASystem.assertNot(value == 0, "ALong modulo by int zero"); - /* Division by one? */ - if (value == 1) return 0; - /* Make the values unsigned */ - let value1: ALong = this; - let neg1: boolean = value1.isNegative(); - if (neg1) value1 = value1.negate(); - let neg2: boolean = (value < 0); - if (neg2) value = -1 * value; - let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); - /* Compute */ - let valueF: float64 = (0.0 + value); - let h1: float64 = Numbers.floor(value1._high / valueF); - let h2: float64 = (value1._high - valueF * h1); - let l1: float64 = Numbers.floor(value1._low / valueF); - let l2: float64 = (value1._low - valueF * l1); - let t: float64 = (h2 * ALong._U32 + l2); - let t1: float64 = Numbers.floor(t / valueF); - let t2: float64 = (t - valueF * t1); // remainder - let result: int32 = Math.trunc(t2); - /* Return the result */ - return result; - } - - /** - * Create a new number. - * @param value the 64-bit float value. - * @return the new number. - */ - public static fromDouble(value: float64): ALong { - /* Make the value unsigned */ - let neg: boolean = (value < 0.0); - if (neg) value = (-1.0 * value); - /* Compute */ - value = Numbers.floor(value); - let high: float64 = Numbers.floor(value / ALong._U32); - let low: float64 = (value - high * ALong._U32); - let result: ALong = ALong.normalize2(high, low); - /* Return the result */ - return (neg) ? result.negate() : result; - } - - /** - * Get a double. - * @return the double value. - */ - public toDouble(): float64 { - /* Make the value unsigned */ - let value: ALong = this; - let neg: boolean = value.isNegative(); - if (neg) value = value.negate(); - /* Compute */ - let result: float64 = (value._high * ALong._U32) + value._low; - if (neg) result *= -1.0; - /* Return the result */ - return result; - } - - /** - * Create a new number. - * @param value the 32-bit integer value. - * @return the new number. - */ - public static fromInt(value: float64): ALong { - return (value < 0.0) ? new ALong(ALong._U32 - 1.0, ALong._U32 + value) : new ALong(0.0, value); - } - - /** - * Get a 32-bit integer. - * @return the integer value. - */ - public toInt(): int32 { - /* Make the value unsigned */ - let value: ALong = this; - let neg: boolean = value.isNegative(); - if (neg) value = value.negate(); - /* Compute */ - let result: float64 = value._low; - if (neg) result *= -1.0; - /* Return the result */ - return Numbers.doubleToInt(result); - } - - /** - * Create a new number. - * @param i1 the 32-bit high part. - * @param i0 the 32-bit low part. - * @return the new number. - */ - public static fromHighLow(i1: float64, i0: float64): ALong { - if (i1 < 0.0) i1 += ALong._U32; // make unsigned - if (i0 < 0.0) i0 += ALong._U32; - return new ALong(i1, i0); - } - - /** - * Get the high part. - * @return the integer value (0..4294967295) - */ - public getHigh(): float64 { - return this._high; - } - - /** - * Get the low part. - * @return the integer value (0..4294967295) - */ - public getLow(): float64 { - return this._low; - } - - /** - * Create a new number. - * @param b7 the most significant 8-bit byte of the high part (0..255). - * @param b6 the most third 8-bit byte of the high part (0..255). - * @param b5 the most second 8-bit byte of the high part (0..255). - * @param b4 the most least 8-bit byte of the high part (0..255). - * @param b3 the most significant 8-bit byte of the low part (0..255). - * @param b2 the most third 8-bit byte of the low part (0..255). - * @param b1 the most second 8-bit byte of the low part (0..255). - * @param b0 the most least 8-bit byte of the low part (0..255). - * @return the new number. - */ - public static fromBytes(b7: float64, b6: float64, b5: float64, b4: float64, b3: float64, b2: float64, b1: float64, b0: float64): ALong { - if (b7 < 0.0) b7 += ALong._U8; // make unsigned - if (b6 < 0.0) b6 += ALong._U8; - if (b5 < 0.0) b5 += ALong._U8; - if (b4 < 0.0) b4 += ALong._U8; - if (b3 < 0.0) b3 += ALong._U8; - if (b2 < 0.0) b2 += ALong._U8; - if (b1 < 0.0) b1 += ALong._U8; - if (b0 < 0.0) b0 += ALong._U8; - let high: float64 = (b7 * ALong._U24 + b6 * ALong._U16 + b5 * ALong._U8 + b4); - let low: float64 = (b3 * ALong._U24 + b2 * ALong._U16 + b1 * ALong._U8 + b0); - return ALong.fromHighLow(high, low); - } - - /** - * Get a byte. - * @param index the index of the byte (0..7 where 0 is low). - * @return the byte value (0..255) - */ - public getByte(index: int32): int32 { - let value: float64 = (index < 4) ? this._low : this._high; // this should be unsigned - let position: int32 = (index < 4) ? index : (index - 4); - for (let i: number = 0; i < position; i++) value = Numbers.floor(value / 256.0); - return Math.trunc(value % 256); - } - - /** - * Check if a number is equal. - * @param value the value to check. - * @return true if equal. - */ - public isEqualTo(value: ALong): boolean { - return (value._high == this._high) && (value._low == this._low); - } - - /** - * Check if a number is not equal. - * @param value the value to check. - * @return true if equal. - */ - public isNotEqualTo(value: ALong): boolean { - return (this.isEqualTo(value) == false); - } - - /** - * Check if a number is equal. - * @param value the value to check. - * @return true if equal. - */ - public same(value: ALong): boolean { - return this.isEqualTo(value); - } - - /** - * Check if a number is equal. - * @param value the value to check. - * @return true if equal. - */ - public equals(value: ALong): boolean { - return this.isEqualTo(value); - } - - /** - * Compare this long to another long. - * @param value the other long. - * @return zero if equal, positive if smaller, or negative if value is larger. - */ - public compareTo(value: ALong): int32 { - let diff: ALong = this.sub(value); - if (diff.isZero()) return 0; - return diff.isNegative() ? -1 : 1; - } - - /** - * Check if a value is larger. - * @param value the value to check. - * @return true if this number is larger than the check value. - */ - public isLargerThan(value: ALong): boolean { - return (this.compareTo(value) > 0); - } - - /** - * Check if a value is larger. - * @param value the value to check. - * @return true if this number is larger than the check value. - */ - public isLargerThanOrEqualTo(value: ALong): boolean { - return (this.compareTo(value) >= 0); - } - - /** - * Check if a value is smaller. - * @param value the value to check. - * @return true if this number is smaller than the check value. - */ - public isSmallerThan(value: ALong): boolean { - return (this.compareTo(value) < 0); - } - - /** - * Check if a value is smaller. - * @param value the value to check. - * @return true if this number is smaller than the check value. - */ - public isSmallerThanOrEqualTo(value: ALong): boolean { - return (this.compareTo(value) <= 0); - } - - /** - * Get the maximum value. - * @param v1 the first value. - * @param v2 the second value. - * @return the maximum value. - */ - public static max(v1: ALong, v2: ALong): ALong { - return (v2.isLargerThan(v1)) ? v2 : v1; - } - - /** - * Get the minimum value. - * @param v1 the first value. - * @param v2 the second value. - * @return the minimum value. - */ - public static min(v1: ALong, v2: ALong): ALong { - return (v2.isSmallerThan(v1)) ? v2 : v1; - } - - /** - * Create a number from a string. - * @param svalue the string value. - * @param radix the radix (2 to 36). - * @return the number. - */ - public static fromRadixString(svalue: string, radix: int32): ALong { - /* Check the radix */ - ASystem.assertNot((radix < 2) || (radix > 36), "Invalid radix: " + radix); - /* Common values? */ - if (Strings.equals(svalue, "0")) return ALong.ZERO; - if (Strings.equals(svalue, "1")) return ALong.ONE; - /* Negative? */ - let neg: boolean = Strings.startsWith(svalue, "-"); - if (neg) svalue = Strings.substringFrom(svalue, 1); - /* Add all digits */ - let result: ALong = ALong.ZERO; - let unit: ALong = ALong.ONE; - let radixHL: ALong = ALong.fromInt(radix); - let slength: int32 = Strings.getLength(svalue); - for (let i: number = 0; i < slength; i++) { - /* Add the next digit */ - let charCode: int32 = Strings.charCodeAt(svalue, slength - 1 - i); - let digit: int32 = (charCode >= 65) ? (charCode - 65 + 10) : (charCode - 48); - if (digit > 0) result = result.add(unit.mulInt(digit)); - unit = unit.mul(radixHL); + /** The value of a 32 bit unit */ + private static readonly _U32: float64 = 4294967296.0; + /** The value of a 31 bit unit */ + private static readonly _U31: float64 = 2147483648.0; + /** The value of a 24 bit unit */ + private static readonly _U24: float64 = 16777216.0; + /** The value of a 16 bit unit */ + private static readonly _U16: float64 = 65536.0; + /** The value of a 8 bit unit */ + private static readonly _U8: float64 = 256.0; + + /** The integer value 0 */ + public static ZERO: ALong = new ALong(0.0, 0.0); + /** The integer value 1 */ + public static ONE: ALong = new ALong(0.0, 1.0); + /** The integer value 2 */ + public static TWO: ALong = new ALong(0.0, 2.0); + /** The integer value 4 */ + public static FOUR: ALong = new ALong(0.0, 4.0); + /** The integer value 10 */ + public static TEN: ALong = new ALong(0.0, 10.0); + /** The integer value -1 */ + public static MINUS_ONE: ALong = new ALong(ALong._U32 - 1.0, ALong._U32 - 1.0); + /** The maximum positive value of a signed_ 64-bit integer (9223372036854775807) */ + public static MAX_VALUE: ALong = new ALong(ALong._U31 - 1.0, ALong._U32 - 1.0); + /** The minimum negative value of a signed 64-bit integer (-9223372036854775808) */ + public static MIN_VALUE: ALong = new ALong(ALong._U31, 0.0); + + /** The high value (unsigned integer [0..U32[ after normalization, negative i64 if >= U31) */ + private _high: float64; + /** The low value (unsigned integer [0..U32[ after normalization) */ + private _low: float64; + + /** + * Create a new value. + * @param high the 32-bit high part. + * @param low the 32-bit low part. + */ + private constructor(high: float64, low: float64) { + this._high = high; + this._low = low; + } + + /** + * Check if the number is zero. + * @return true if zero. + */ + public isZero(): boolean { + return (this._high == 0.0) && (this._low == 0.0); + } + + /** + * Check if the number is not zero. + * @return true if zero. + */ + public isNonZero(): boolean { + return (this.isZero() == false); + } + + /** + * Check if the number is one. + * @return true if one. + */ + public isOne(): boolean { + return (this._high == 0.0) && (this._low == 1.0); + } + + /** + * Check if the number is positive. + * @return true if positive (false if zero). + */ + public isPositive(): boolean { + return this.isZero() ? false : (this._high < ALong._U31); + } + + /** + * Check if the number is negative. + * @return true if negative (false if zero). + */ + public isNegative(): boolean { + return this.isZero() ? false : (this._high >= ALong._U31); + } + + /** + * Normalize the number. + * @return this number for chaining operations. + */ + private static normalize2(high: float64, low: float64): ALong { + // normalize the low part + let overflowLow: float64 = Numbers.floor(low / ALong._U32); + low = low - overflowLow * ALong._U32; // inside range [0..U32[ + high += overflowLow; + // normalize the high part + let overflowHigh: float64 = Numbers.floor(high / ALong._U32); + high = high - overflowHigh * ALong._U32; // inside range [0..U32[ + // return the result + return new ALong(high, low); + } + + /** + * Negate the number. + * @return the result. + */ + public negate(): ALong { + /* Zero? */ + if (this.isZero()) { + /* Return this immutable instance */ + return this; + } + /* Compute */ + let resultHigh: float64 = ALong._U32 - 1.0 - this._high; + let resultLow: float64 = ALong._U32 - this._low; + /* Overflow? */ + if (resultLow == ALong._U32) { + resultLow = 0.0; + resultHigh += 1.0; // in case we try to invert ALong.MIN_VALUE we get ALong.MIN_VALUE as a result again + } + /* Return the result */ + return new ALong(resultHigh, resultLow); + } + + /** + * Add a number. + * @param value the value to add. + * @return the result. + */ + public add(value: ALong): ALong { + /* Compute */ + let resultHigh: float64 = this._high + value._high; + let resultLow: float64 = this._low + value._low; + /* Return the result */ + return ALong.normalize2(resultHigh, resultLow); + } + + /** + * Add a number. + * @param value the value to add. + * @return the result. + */ + public addInt(value: int32): ALong { + return this.add(ALong.fromInt(value)); + } + + /** + * Increase by one. + * @return the result. + */ + public increase(): ALong { + return this.addInt(1); + } + + /** + * Subtract a number. + * @param value the value to subtract. + * @return the result. + */ + public sub(value: ALong): ALong { + return this.add(value.negate()); + } + + /** + * Subtract a number. + * @param value the value to subtract. + * @return the result. + */ + public subInt(value: int32): ALong { + return this.sub(ALong.fromInt(value)); + } + + /** + * Decrease by one. + * @return the result. + */ + public decrease(): ALong { + return this.subInt(1); + } + + /** + * Multiply two unsigned 32-bit integer values. + * @param v1 the first value. + * @param v2 the second value. + * @param high0 the initial high value of the result. + * @return the unsigned 64-bit product. + */ + private static mul2(v1: ALong, v2: ALong): ALong { + /* Zero? */ + if (v1.isZero()) return v1; + if (v2.isZero()) return v2; + /* Make the values unsigned */ + let neg1: int32 = v1.isNegative() ? 1 : 0; + if (neg1 == 1) v1 = v1.negate(); + let neg2: int32 = v2.isNegative() ? 1 : 0; + if (neg2 == 1) v2 = v2.negate(); + /* Split first low into 16-bit parts */ + let a1: float64 = Numbers.floor(v1._low / ALong._U16); + let a2: float64 = v1._low - a1 * ALong._U16; + /* Split second low into 16-bit parts */ + let b1: float64 = Numbers.floor(v2._low / ALong._U16); + let b2: float64 = v2._low - b1 * ALong._U16; + /* Compute */ + let resultHigh: float64 = (v1._high * v2._low + v1._low * v2._high) + (a1 * b1); + let resultLow: float64 = (a1 * b2 + a2 * b1) * ALong._U16 + (a2 * b2); + let result: ALong = ALong.normalize2(resultHigh, resultLow); + /* Return the result */ + return (neg1 + neg2 == 1) ? result.negate() : result; + } + + /** + * Multiply by a number. + * @param value the value to multiply. + * @return the result. + */ + public mul(value: ALong): ALong { + return ALong.mul2(this, value); + } + + /** + * Multiply by a number. + * @param value the value to multiply. + * @return the result. + */ + public mulInt(value: int32): ALong { + return this.mul(ALong.fromInt(value)); + } + + /** + * Divide by a number. + * @param value the value to divide by. + * @return the result. + */ + public div(value: ALong): ALong { + /* Division by zero? */ + ASystem.assertNot(value.isZero(), "ALong division by ALong zero"); + /* Division by one? */ + if (value.isOne()) return this; + /* Make the values unsigned */ + let currentValue: ALong = this; + let neg1: boolean = currentValue.isNegative(); + if (neg1) currentValue = currentValue.negate(); + let value2: ALong = value; + let neg2: boolean = value2.isNegative(); + if (neg2) value2.negate(); + let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); + /* Loop until the remainder is smaller than the value */ + let result: ALong = ALong.ZERO; + while (currentValue.isLargerThanOrEqualTo(value2)) { + /* Shift the value as much as possible */ + let test: ALong = value2; + let times: ALong = ALong.ONE; + if (test.isSmallerThan(currentValue)) { + while (test.isSmallerThan(currentValue)) { + test = test.mulInt(2); + times = times.mulInt(2); } - /* Return the result */ - return (neg) ? result.negate() : result; - } - - /** - * Create a number from a decimal string. - * @param value the string value. - * @return the number. - */ - public static fromString(value: string): ALong { - if (value == null) return null; - return ALong.fromRadixString(value, 10); - } - - /** - * Create a number from a hexadecimal string. - * @param value the string value. - * @return the number. - */ - public static fromHexString(value: string): ALong { - if (value == null) return null; - return ALong.fromRadixString(value, 16); - } - - /** - * Convert the number to a string. - * @param radix the radix (2 to 36). - * @return the string. - */ - public getRadixString(radix: int32): string { - /* Check the radix */ - ASystem.assertNot((radix < 2) || (radix > 36), "Invalid radix: " + radix); - /* Common values? */ - let value: ALong = this; - if (value.isZero()) return "0"; - /* Make the value unsigned */ - let neg: boolean = value.isNegative(); - if (neg) value = value.negate(); - /* Add all digits */ - let result: string = ""; - while (true) { - /* Add the next digit */ - if (value.isZero()) break; - let digit: int32 = value.modInt(radix); - value = value.divInt(radix); - let sdigit: string = (digit < 10) ? Strings.charCodeToString(48 + digit) : Strings.charCodeToString(65 + digit - 10); - result = (sdigit + result); - /* Fail? */ - ASystem.assertNot(Strings.getLength(result) > 20, "Failed to convert longHL to string (radix " + radix + "): " + this._high + ";" + this._low); - } - if (neg) result = ("-" + result); - /* Return the result */ - return result; - } - - /** - * Convert the number to a decimal string. - * @return the string. - */ - public getString(): string { - return this.getRadixString(10); - } - - /** - * Convert the number to a hexadecimal string. - * @return the string. - */ - public getHexString(): string { - return this.getRadixString(16); - } - - /** - * The standard toString method. - * @see Object#toString - */ - public toString(): string { - return this.getString(); - } + test = test.divInt(2); + times = times.divInt(2); + } + /* Subtract the shifted value */ + currentValue = currentValue.sub(test); + result = result.add(times); + } + /* Return the result */ + return neg ? result.negate() : result; + } + + /** + * Divide by a number. + * @param value the value to divide by. + * @return the result. + */ + public divInt(value: int32): ALong { + /* Division by zero? */ + ASystem.assertNot(value == 0, "ALong division by int zero"); + /* Division by one? */ + if (value == 1) return this; + /* Make the values unsigned */ + let value1: ALong = this; + let neg1: boolean = value1.isNegative(); + if (neg1) value1 = value1.negate(); + let neg2: boolean = value < 0; + if (neg2) value = -1 * value; + let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); + /* Compute */ + let valueF: float64 = 0.0 + value; + let h1: float64 = Numbers.floor(value1._high / valueF); + let h2: float64 = value1._high - valueF * h1; + let l1: float64 = Numbers.floor(value1._low / valueF); + let l2: float64 = value1._low - valueF * l1; + let t: float64 = h2 * ALong._U32 + l2; + let t1: float64 = Numbers.floor(t / valueF); + let t2: float64 = t - valueF * t1; // remainder + let result: ALong = ALong.normalize2(h1, l1 + t1); + /* Return the result */ + return neg ? result.negate() : result; + } + + /** + * Modulate by a number. + * @param value the value to modulate by. + * @return the result. + */ + public mod(value: ALong): ALong { + /* Division by zero? */ + ASystem.assertNot(value.isZero(), "ALong modulo by ALong zero"); + /* Division by one? */ + if (value.isOne()) return ALong.ZERO; + /* Compute */ + let result: ALong = this.sub(this.div(value).mul(value)); + /* Return the result */ + return result; + } + + /** + * Modulate by a number. + * @param value the value to modulate by. + * @return the modulo value. + */ + public modInt(value: int32): int32 { + /* Division by zero? */ + ASystem.assertNot(value == 0, "ALong modulo by int zero"); + /* Division by one? */ + if (value == 1) return 0; + /* Make the values unsigned */ + let value1: ALong = this; + let neg1: boolean = value1.isNegative(); + if (neg1) value1 = value1.negate(); + let neg2: boolean = value < 0; + if (neg2) value = -1 * value; + let neg: boolean = (neg1 && !neg2) || (!neg1 && neg2); + /* Compute */ + let valueF: float64 = 0.0 + value; + let h1: float64 = Numbers.floor(value1._high / valueF); + let h2: float64 = value1._high - valueF * h1; + let l1: float64 = Numbers.floor(value1._low / valueF); + let l2: float64 = value1._low - valueF * l1; + let t: float64 = h2 * ALong._U32 + l2; + let t1: float64 = Numbers.floor(t / valueF); + let t2: float64 = t - valueF * t1; // remainder + let result: int32 = Math.trunc(t2); + /* Return the result */ + return result; + } + + /** + * Create a new number. + * @param value the 64-bit float value. + * @return the new number. + */ + public static fromDouble(value: float64): ALong { + /* Make the value unsigned */ + let neg: boolean = value < 0.0; + if (neg) value = -1.0 * value; + /* Compute */ + value = Numbers.floor(value); + let high: float64 = Numbers.floor(value / ALong._U32); + let low: float64 = value - high * ALong._U32; + let result: ALong = ALong.normalize2(high, low); + /* Return the result */ + return neg ? result.negate() : result; + } + + /** + * Get a double. + * @return the double value. + */ + public toDouble(): float64 { + /* Make the value unsigned */ + let value: ALong = this; + let neg: boolean = value.isNegative(); + if (neg) value = value.negate(); + /* Compute */ + let result: float64 = (value._high * ALong._U32) + value._low; + if (neg) result *= -1.0; + /* Return the result */ + return result; + } + + /** + * Create a new number. + * @param value the 32-bit integer value. + * @return the new number. + */ + public static fromInt(value: float64): ALong { + return (value < 0.0) ? new ALong(ALong._U32 - 1.0, ALong._U32 + value) : new ALong(0.0, value); + } + + /** + * Get a 32-bit integer. + * @return the integer value. + */ + public toInt(): int32 { + /* Make the value unsigned */ + let value: ALong = this; + let neg: boolean = value.isNegative(); + if (neg) value = value.negate(); + /* Compute */ + let result: float64 = value._low; + if (neg) result *= -1.0; + /* Return the result */ + return Numbers.doubleToInt(result); + } + + /** + * Create a new number. + * @param i1 the 32-bit high part. + * @param i0 the 32-bit low part. + * @return the new number. + */ + public static fromHighLow(i1: float64, i0: float64): ALong { + if (i1 < 0.0) i1 += ALong._U32; // make unsigned + if (i0 < 0.0) i0 += ALong._U32; + return new ALong(i1, i0); + } + + /** + * Get the high part. + * @return the integer value (0..4294967295) + */ + public getHigh(): float64 { + return this._high; + } + + /** + * Get the low part. + * @return the integer value (0..4294967295) + */ + public getLow(): float64 { + return this._low; + } + + /** + * Create a new number. + * @param b7 the most significant 8-bit byte of the high part (0..255). + * @param b6 the most third 8-bit byte of the high part (0..255). + * @param b5 the most second 8-bit byte of the high part (0..255). + * @param b4 the most least 8-bit byte of the high part (0..255). + * @param b3 the most significant 8-bit byte of the low part (0..255). + * @param b2 the most third 8-bit byte of the low part (0..255). + * @param b1 the most second 8-bit byte of the low part (0..255). + * @param b0 the most least 8-bit byte of the low part (0..255). + * @return the new number. + */ + public static fromBytes(b7: float64, b6: float64, b5: float64, b4: float64, b3: float64, b2: float64, b1: float64, b0: float64): ALong { + if (b7 < 0.0) b7 += ALong._U8; // make unsigned + if (b6 < 0.0) b6 += ALong._U8; + if (b5 < 0.0) b5 += ALong._U8; + if (b4 < 0.0) b4 += ALong._U8; + if (b3 < 0.0) b3 += ALong._U8; + if (b2 < 0.0) b2 += ALong._U8; + if (b1 < 0.0) b1 += ALong._U8; + if (b0 < 0.0) b0 += ALong._U8; + let high: float64 = b7 * ALong._U24 + b6 * ALong._U16 + b5 * ALong._U8 + b4; + let low: float64 = b3 * ALong._U24 + b2 * ALong._U16 + b1 * ALong._U8 + b0; + return ALong.fromHighLow(high, low); + } + + /** + * Get a byte. + * @param index the index of the byte (0..7 where 0 is low). + * @return the byte value (0..255) + */ + public getByte(index: int32): int32 { + let value: float64 = (index < 4) ? this._low : this._high; // this should be unsigned + let position: int32 = (index < 4) ? index : (index - 4); + for (let i: number = 0; i < position; i++) value = Numbers.floor(value / 256.0); + return Math.trunc(value % 256); + } + + /** + * Check if a number is equal. + * @param value the value to check. + * @return true if equal. + */ + public isEqualTo(value: ALong): boolean { + return (value._high == this._high) && (value._low == this._low); + } + + /** + * Check if a number is not equal. + * @param value the value to check. + * @return true if equal. + */ + public isNotEqualTo(value: ALong): boolean { + return (this.isEqualTo(value) == false); + } + + /** + * Check if a number is equal. + * @param value the value to check. + * @return true if equal. + */ + public same(value: ALong): boolean { + return this.isEqualTo(value); + } + + /** + * Check if a number is equal. + * @param value the value to check. + * @return true if equal. + */ + public equals(value: ALong): boolean { + return this.isEqualTo(value); + } + + /** + * Compare this long to another long. + * @param value the other long. + * @return zero if equal, positive if smaller, or negative if value is larger. + */ + public compareTo(value: ALong): int32 { + let diff: ALong = this.sub(value); + if (diff.isZero()) return 0; + return diff.isNegative() ? -1 : 1; + } + + /** + * Check if a value is larger. + * @param value the value to check. + * @return true if this number is larger than the check value. + */ + public isLargerThan(value: ALong): boolean { + return (this.compareTo(value) > 0); + } + + /** + * Check if a value is larger. + * @param value the value to check. + * @return true if this number is larger than the check value. + */ + public isLargerThanOrEqualTo(value: ALong): boolean { + return (this.compareTo(value) >= 0); + } + + /** + * Check if a value is smaller. + * @param value the value to check. + * @return true if this number is smaller than the check value. + */ + public isSmallerThan(value: ALong): boolean { + return (this.compareTo(value) < 0); + } + + /** + * Check if a value is smaller. + * @param value the value to check. + * @return true if this number is smaller than the check value. + */ + public isSmallerThanOrEqualTo(value: ALong): boolean { + return (this.compareTo(value) <= 0); + } + + /** + * Get the maximum value. + * @param v1 the first value. + * @param v2 the second value. + * @return the maximum value. + */ + public static max(v1: ALong, v2: ALong): ALong { + return (v2.isLargerThan(v1)) ? v2 : v1; + } + + /** + * Get the minimum value. + * @param v1 the first value. + * @param v2 the second value. + * @return the minimum value. + */ + public static min(v1: ALong, v2: ALong): ALong { + return (v2.isSmallerThan(v1)) ? v2 : v1; + } + + /** + * Create a number from a string. + * @param svalue the string value. + * @param radix the radix (2 to 36). + * @return the number. + */ + public static fromRadixString(svalue: string, radix: int32): ALong { + /* Check the radix */ + ASystem.assertNot((radix < 2) || (radix > 36), "Invalid radix: " + radix); + /* Common values? */ + if (Strings.equals(svalue, "0")) return ALong.ZERO; + if (Strings.equals(svalue, "1")) return ALong.ONE; + /* Negative? */ + let neg: boolean = Strings.startsWith(svalue, "-"); + if (neg) svalue = Strings.substringFrom(svalue, 1); + /* Add all digits */ + let result: ALong = ALong.ZERO; + let unit: ALong = ALong.ONE; + let radixHL: ALong = ALong.fromInt(radix); + let slength: int32 = Strings.getLength(svalue); + for (let i: number = 0; i < slength; i++) { + /* Add the next digit */ + let charCode: int32 = Strings.charCodeAt(svalue, slength - 1 - i); + let digit: int32 = (charCode >= 65) ? (charCode - 65 + 10) : (charCode - 48); + if (digit > 0) result = result.add(unit.mulInt(digit)); + unit = unit.mul(radixHL); + } + /* Return the result */ + return neg ? result.negate() : result; + } + + /** + * Create a number from a decimal string. + * @param value the string value. + * @return the number. + */ + public static fromString(value: string): ALong { + if (value == null) return null; + return ALong.fromRadixString(value, 10); + } + + /** + * Create a number from a hexadecimal string. + * @param value the string value. + * @return the number. + */ + public static fromHexString(value: string): ALong { + if (value == null) return null; + return ALong.fromRadixString(value, 16); + } + + /** + * Convert the number to a string. + * @param radix the radix (2 to 36). + * @return the string. + */ + public getRadixString(radix: int32): string { + /* Check the radix */ + ASystem.assertNot((radix < 2) || (radix > 36), "Invalid radix: " + radix); + /* Common values? */ + let value: ALong = this; + if (value.isZero()) return "0"; + /* Make the value unsigned */ + let neg: boolean = value.isNegative(); + if (neg) value = value.negate(); + /* Add all digits */ + let result: string = ""; + while (true) { + /* Add the next digit */ + if (value.isZero()) break; + let digit: int32 = value.modInt(radix); + value = value.divInt(radix); + let sdigit: string = (digit < 10) ? Strings.charCodeToString(48 + digit) : Strings.charCodeToString(65 + digit - 10); + result = sdigit + result; + /* Fail? */ + ASystem.assertNot(Strings.getLength(result) > 20, "Failed to convert longHL to string (radix " + radix + "): " + this._high + ";" + this._low); + } + if (neg) result = "-" + result; + /* Return the result */ + return result; + } + + /** + * Convert the number to a decimal string. + * @return the string. + */ + public getString(): string { + return this.getRadixString(10); + } + + /** + * Convert the number to a hexadecimal string. + * @return the string. + */ + public getHexString(): string { + return this.getRadixString(16); + } + + /** + * The standard toString method. + * @see Object#toString + */ + public toString(): string { + return this.getString(); + } } diff --git a/core/orbitgt/src/system/runtime/ASystem.ts b/core/orbitgt/src/system/runtime/ASystem.ts index a509f6ed2f63..fa0def774662 100644 --- a/core/orbitgt/src/system/runtime/ASystem.ts +++ b/core/orbitgt/src/system/runtime/ASystem.ts @@ -11,20 +11,20 @@ */ /** @internal */ export class ASystem { - private static TIME0: number = new Date().getTime(); + private static TIME0: number = new Date().getTime(); - private constructor() { - } + private constructor() { + } - public static assert0(condition: boolean, message: string): void { - if (condition == false) throw new Error("Assert failed: " + message); - } + public static assert0(condition: boolean, message: string): void { + if (condition == false) throw new Error("Assert failed: " + message); + } - public static assertNot(condition: boolean, message: string): void { - if (condition) throw new Error("AssertNot failed: " + message); - } + public static assertNot(condition: boolean, message: string): void { + if (condition) throw new Error("AssertNot failed: " + message); + } - public static time(): number { - return (new Date().getTime() - ASystem.TIME0) / 1000.0; // time in seconds - } + public static time(): number { + return (new Date().getTime() - ASystem.TIME0) / 1000.0; // time in seconds + } } diff --git a/core/orbitgt/src/system/runtime/Downloader.ts b/core/orbitgt/src/system/runtime/Downloader.ts index 0cbe7c29b8a9..dd2224a57022 100644 --- a/core/orbitgt/src/system/runtime/Downloader.ts +++ b/core/orbitgt/src/system/runtime/Downloader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.runtime; +// package orbitgt.system.runtime; type int8 = number; type int16 = number; @@ -22,29 +22,43 @@ import { StringMap } from "../collection/StringMap"; */ /** @internal */ export class Downloader { - /** The default instance of this tool for this runtime. This needs to be set by the host application on startup. */ - public static INSTANCE: Downloader = null; - - // create a new downloader - // - public constructor() { - } - - // download a byte array - // - public async downloadBytes(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return null; - } - - // download a text - // - public async downloadText(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return null; - } - - // download a text without request options - // - public async downloadText2(requestURL: string): Promise { - return null; - } + /** The default instance of this tool for this runtime. This needs to be set by the host application on startup. */ + public static INSTANCE: Downloader = null; + + // create a new downloader + // + public constructor() { + } + + // download a byte array + // + public async downloadBytes( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return null; + } + + // download a text + // + public async downloadText( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return null; + } + + // download a text without request options + // + public async downloadText2(requestURL: string): Promise { + return null; + } } diff --git a/core/orbitgt/src/system/runtime/DownloaderNode.ts b/core/orbitgt/src/system/runtime/DownloaderNode.ts index 7fafbaebce9f..245661066c80 100644 --- a/core/orbitgt/src/system/runtime/DownloaderNode.ts +++ b/core/orbitgt/src/system/runtime/DownloaderNode.ts @@ -17,109 +17,150 @@ import { Downloader } from "./Downloader"; */ /** @internal */ export class DownloaderNode extends Downloader { - // create a new downloader - // - public constructor() { - super(); - } + // create a new downloader + // + public constructor() { + super(); + } - // join the downloaded chunks into the requested response type - // - private static joinChunks(buffers: Array, responseType: string): any { - //console.log("joining "+buffers.length+" downloaded chunks to type '"+responseType+"'"); - let joined: Buffer = Buffer.concat(buffers); - if (responseType === "text") return joined.toString('utf8'); - return ABuffer.wrapRange(joined.buffer, joined.byteOffset, joined.length); - } + // join the downloaded chunks into the requested response type + // + private static joinChunks(buffers: Array, responseType: string): any { + // console.log("joining "+buffers.length+" downloaded chunks to type '"+responseType+"'"); + let joined: Buffer = Buffer.concat(buffers); + if (responseType === "text") return joined.toString("utf8"); + return ABuffer.wrapRange(joined.buffer, joined.byteOffset, joined.length); + } - // make a generic download - // - private download0(method: string, requestURL: string, responseType: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap, callback: (response: any) => void, errorCallback: (err: any) => void): void { - // set the defaults - if (method == null) method = "GET"; - if (requestHeaders == null) requestHeaders = new StringMap(); - // set the options - //console.log("connect method '"+method+"' to '"+requestURL+"'"); - let options: object = {}; - options["method"] = method; - // set the URL - let url: URL = new URL(requestURL); - options["protocol"] = url.protocol; - options["host"] = url.hostname; - options["port"] = url.port; - options["path"] = url.pathname + url.search; - // set the request headers - if (requestHeaders.size() > 0) { - // create the headers object - //console.log("adding request headers"); - let headers: object = {}; - options["headers"] = headers; - // add the header lines - for (let headerName of requestHeaders.keys()) { - let headerValue: string = requestHeaders.get(headerName); - //console.log("setting request header '"+headerName+"' value '"+headerValue+"'"); - headers[headerName] = headerValue; - } + // make a generic download + // + private download0( + method: string, + requestURL: string, + responseType: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + callback: (response: any) => void, + errorCallback: (err: any) => void, + ): void { + // set the defaults + if (method == null) method = "GET"; + if (requestHeaders == null) requestHeaders = new StringMap(); + // set the options + // console.log("connect method '"+method+"' to '"+requestURL+"'"); + let options: object = {}; + options["method"] = method; + // set the URL + let url: URL = new URL(requestURL); + options["protocol"] = url.protocol; + options["host"] = url.hostname; + options["port"] = url.port; + options["path"] = url.pathname + url.search; + // set the request headers + if (requestHeaders.size() > 0) { + // create the headers object + // console.log("adding request headers"); + let headers: object = {}; + options["headers"] = headers; + // add the header lines + for (let headerName of requestHeaders.keys()) { + let headerValue: string = requestHeaders.get(headerName); + // console.log("setting request header '"+headerName+"' value '"+headerValue+"'"); + headers[headerName] = headerValue; + } + } + // make the request + let request: http.ClientRequest; + if (url.protocol === "http:") + request = http.request(options, (response) => { + // console.log("download '"+requestURL+"' response code: "+response.statusCode); + if (responseHeaders != null) { + for (let propertyName in response.headers) { + if (typeof response.headers[propertyName] === "string") responseHeaders.set(propertyName, response.headers[propertyName] as string); + } } - // make the request - let request: http.ClientRequest; - if (url.protocol === "http:") request = http.request(options, (response) => { - //console.log("download '"+requestURL+"' response code: "+response.statusCode); - if (responseHeaders != null) { - for (let propertyName in response.headers) { - if (typeof response.headers[propertyName] === "string") responseHeaders.set(propertyName, response.headers[propertyName] as string); - } - } - // process the incoming download chuncks - let chunks: Array = []; - response.on("data", data => { chunks.push(data); }); - response.on("end", () => { callback(DownloaderNode.joinChunks(chunks, responseType)); }); - response.on("error", () => { errorCallback("error when downloading '" + requestURL + "'"); }); - }) - else request = https.request(options, (response) => { - //console.log("download '"+requestURL+"' response code: "+response.statusCode); - if (responseHeaders != null) { - for (let propertyName in response.headers) { - if (typeof response.headers[propertyName] === "string") responseHeaders.set(propertyName, response.headers[propertyName] as string); - } - } - // process the incoming download chuncks - let chunks: Array = []; - response.on("data", data => { chunks.push(data); }); - response.on("end", () => { callback(DownloaderNode.joinChunks(chunks, responseType)); }); - response.on("error", () => { errorCallback("error when downloading '" + requestURL + "'"); }); + // process the incoming download chuncks + let chunks: Array = []; + response.on("data", (data) => { + chunks.push(data); }); - // post text? - if (postText != null) { - // send the request to the server - //console.log("posting text '"+postText+"'"); - request.write(postText); // encoding argument is optional, defaults to 'utf8' - } - // post data? - else if (postData != null) { - // send the request to the server - //console.log("posting binary data, size "+postData.size()); - request.write(Buffer.from(postData.toNativeBuffer())); + response.on("end", () => { + callback(DownloaderNode.joinChunks(chunks, responseType)); + }); + response.on("error", () => { + errorCallback("error when downloading '" + requestURL + "'"); + }); + }); + else request = https.request(options, (response) => { + // console.log("download '"+requestURL+"' response code: "+response.statusCode); + if (responseHeaders != null) { + for (let propertyName in response.headers) { + if (typeof response.headers[propertyName] === "string") responseHeaders.set(propertyName, response.headers[propertyName] as string); + } } - // send the request - request.end(); + // process the incoming download chuncks + let chunks: Array = []; + response.on("data", (data) => { + chunks.push(data); + }); + response.on("end", () => { + callback(DownloaderNode.joinChunks(chunks, responseType)); + }); + response.on("error", () => { + errorCallback("error when downloading '" + requestURL + "'"); + }); + }); + // post text? + if (postText != null) { + // send the request to the server + // console.log("posting text '"+postText+"'"); + request.write(postText); // encoding argument is optional, defaults to 'utf8' } - - // Downloader base class method override - // - public override async downloadBytes(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return new Promise((resolve, reject) => { this.download0(method, requestURL, "arraybuffer"/*responseType*/, requestHeaders, postText, postData, responseHeaders, resolve, reject); }); + // post data? + else if (postData != null) { + // send the request to the server + // console.log("posting binary data, size "+postData.size()); + request.write(Buffer.from(postData.toNativeBuffer())); } + // send the request + request.end(); + } - // Downloader base class method override - // - public override async downloadText(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return new Promise((resolve, reject) => { this.download0(method, requestURL, "text"/*responseType*/, requestHeaders, postText, postData, responseHeaders, resolve, reject); }); - } + // Downloader base class method override + // + public override async downloadBytes( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return new Promise((resolve, reject) => { + this.download0(method, requestURL, "arraybuffer", /*responseType*/ requestHeaders, postText, postData, responseHeaders, resolve, reject); + }); + } - // Downloader base class method override - // - public override async downloadText2(requestURL: string): Promise { - return await this.downloadText("GET", requestURL, null, null, null, null); - } + // Downloader base class method override + // + public override async downloadText( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return new Promise((resolve, reject) => { + this.download0(method, requestURL, "text", /*responseType*/ requestHeaders, postText, postData, responseHeaders, resolve, reject); + }); + } + + // Downloader base class method override + // + public override async downloadText2(requestURL: string): Promise { + return await this.downloadText("GET", requestURL, null, null, null, null); + } } diff --git a/core/orbitgt/src/system/runtime/DownloaderXhr.ts b/core/orbitgt/src/system/runtime/DownloaderXhr.ts index 36aa13dd9a3a..00eeed478ff4 100644 --- a/core/orbitgt/src/system/runtime/DownloaderXhr.ts +++ b/core/orbitgt/src/system/runtime/DownloaderXhr.ts @@ -15,108 +15,136 @@ import { Downloader } from "./Downloader"; */ /** @internal */ export class DownloaderXhr extends Downloader { - // create a new downloader - // - public constructor() { - super(); - } + // create a new downloader + // + public constructor() { + super(); + } - // read the response headers - // - private static readResponseHeaders(request: XMLHttpRequest, responseHeaders: StringMap): void { - // console.log("reading response headers"); - const headerLines: Array = request.getAllResponseHeaders().trim().split(/[\r\n]+/); - for (const headerLine of headerLines) { - const parts: Array = headerLine.split(": "); - const name: string = parts[0]; - const value: string = request.getResponseHeader(name); - responseHeaders.set(name, value); - // console.log("response header '"+name+"' value '"+value+"'"); - } - } + // read the response headers + // + private static readResponseHeaders(request: XMLHttpRequest, responseHeaders: StringMap): void { + // console.log("reading response headers"); + const headerLines: Array = request.getAllResponseHeaders().trim().split(/[\r\n]+/); + for (const headerLine of headerLines) { + const parts: Array = headerLine.split(": "); + const name: string = parts[0]; + const value: string = request.getResponseHeader(name); + responseHeaders.set(name, value); + // console.log("response header '"+name+"' value '"+value+"'"); + } + } - // make a generic download - // - private download0(method: string, requestURL: string, responseType: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap, callback: (response: any) => void, errorCallback: (err: any) => void): void { - // set the defaults - if (method == null) method = "GET"; - if (requestHeaders == null) requestHeaders = new StringMap(); - // create the request - // console.log("connect method '"+method+"' to '"+requestURL+"'"); - const request: XMLHttpRequest = new XMLHttpRequest(); - request.open(method, requestURL); - // set the request headers - for (const headerName of requestHeaders.keys()) { - const headerValue: string = requestHeaders.get(headerName); - request.setRequestHeader(headerName, headerValue); - // console.log("setting request header '"+headerName+"' value '"+headerValue+"'"); - } - // set the response type? - if (responseType != null) { - // either "arraybuffer" or "blob" or "document" or "json" or "text" - if (responseType == "bytes") request.responseType = "arraybuffer"; - if (responseType == "arraybuffer") request.responseType = "arraybuffer"; - if (responseType == "blob") request.responseType = "blob"; - if (responseType == "json") request.responseType = "json"; - if (responseType == "text") request.responseType = "text"; - // console.log("response type '"+request.responseType+"'"); - } - // set the response handler - request.onload = function () { - // valid response? - // console.log("download '"+requestURL+"' response code: "+this.status); - if (this.status >= 200 && this.status < 400) { - // read the response headers? - if (responseHeaders != null) DownloaderXhr.readResponseHeaders(this, responseHeaders); - // read the reponse body - if (this.responseType == "arraybuffer") callback(ABuffer.wrap(this.response)); - else callback(this.responseText); - } else { - // invalid response - // console.log("> error code, so no response"); - callback(null); - } - }; - // set the error handler - request.onerror = function (err) { - console.error(`download '${requestURL}' error: ${err}`); - errorCallback(err); - }; - // post text? - if (postText != null) { - // send the request to the server - // console.log("posting text '"+postText+"'"); - request.setRequestHeader("Content-Type", "text/plain"); - request.send(postText); - } - // post data? - else if (postData != null) { - // send the request to the server - // console.log("posting binary data, size "+postData.size()); - request.setRequestHeader("Content-Type", "application/octet-stream"); - request.send(postData.toNativeBuffer()); - } else { - // send the request to the server - // console.log("sending request"); - request.send(null); - } - } + // make a generic download + // + private download0( + method: string, + requestURL: string, + responseType: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + callback: (response: any) => void, + errorCallback: (err: any) => void, + ): void { + // set the defaults + if (method == null) method = "GET"; + if (requestHeaders == null) requestHeaders = new StringMap(); + // create the request + // console.log("connect method '"+method+"' to '"+requestURL+"'"); + const request: XMLHttpRequest = new XMLHttpRequest(); + request.open(method, requestURL); + // set the request headers + for (const headerName of requestHeaders.keys()) { + const headerValue: string = requestHeaders.get(headerName); + request.setRequestHeader(headerName, headerValue); + // console.log("setting request header '"+headerName+"' value '"+headerValue+"'"); + } + // set the response type? + if (responseType != null) { + // either "arraybuffer" or "blob" or "document" or "json" or "text" + if (responseType == "bytes") request.responseType = "arraybuffer"; + if (responseType == "arraybuffer") request.responseType = "arraybuffer"; + if (responseType == "blob") request.responseType = "blob"; + if (responseType == "json") request.responseType = "json"; + if (responseType == "text") request.responseType = "text"; + // console.log("response type '"+request.responseType+"'"); + } + // set the response handler + request.onload = function() { + // valid response? + // console.log("download '"+requestURL+"' response code: "+this.status); + if (this.status >= 200 && this.status < 400) { + // read the response headers? + if (responseHeaders != null) DownloaderXhr.readResponseHeaders(this, responseHeaders); + // read the reponse body + if (this.responseType == "arraybuffer") callback(ABuffer.wrap(this.response)); + else callback(this.responseText); + } else { + // invalid response + // console.log("> error code, so no response"); + callback(null); + } + }; + // set the error handler + request.onerror = function(err) { + console.error(`download '${requestURL}' error: ${err}`); + errorCallback(err); + }; + // post text? + if (postText != null) { + // send the request to the server + // console.log("posting text '"+postText+"'"); + request.setRequestHeader("Content-Type", "text/plain"); + request.send(postText); + } + // post data? + else if (postData != null) { + // send the request to the server + // console.log("posting binary data, size "+postData.size()); + request.setRequestHeader("Content-Type", "application/octet-stream"); + request.send(postData.toNativeBuffer()); + } else { + // send the request to the server + // console.log("sending request"); + request.send(null); + } + } - // Downloader base class method override - // - public override async downloadBytes(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return new Promise((resolve, reject) => { this.download0(method, requestURL, "arraybuffer"/* responseType*/, requestHeaders, postText, postData, responseHeaders, resolve, reject); }); - } + // Downloader base class method override + // + public override async downloadBytes( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return new Promise((resolve, reject) => { + this.download0(method, requestURL, "arraybuffer", /* responseType*/ requestHeaders, postText, postData, responseHeaders, resolve, reject); + }); + } - // Downloader base class method override - // - public override async downloadText(method: string, requestURL: string, requestHeaders: StringMap, postText: string, postData: ABuffer, responseHeaders: StringMap): Promise { - return new Promise((resolve, reject) => { this.download0(method, requestURL, "text"/* responseType*/, requestHeaders, postText, postData, responseHeaders, resolve, reject); }); - } + // Downloader base class method override + // + public override async downloadText( + method: string, + requestURL: string, + requestHeaders: StringMap, + postText: string, + postData: ABuffer, + responseHeaders: StringMap, + ): Promise { + return new Promise((resolve, reject) => { + this.download0(method, requestURL, "text", /* responseType*/ requestHeaders, postText, postData, responseHeaders, resolve, reject); + }); + } - // Downloader base class method override - // - public override async downloadText2(requestURL: string): Promise { - return await this.downloadText("GET", requestURL, null, null, null, null); - } + // Downloader base class method override + // + public override async downloadText2(requestURL: string): Promise { + return await this.downloadText("GET", requestURL, null, null, null, null); + } } diff --git a/core/orbitgt/src/system/runtime/Message.ts b/core/orbitgt/src/system/runtime/Message.ts index 3b00b60f13bd..fc99a5d9e8c6 100644 --- a/core/orbitgt/src/system/runtime/Message.ts +++ b/core/orbitgt/src/system/runtime/Message.ts @@ -11,26 +11,26 @@ */ /** @internal */ export class Message { - /** Disabled by default, enable to see all messages */ - public static DISPLAY: boolean = false; + /** Disabled by default, enable to see all messages */ + public static DISPLAY: boolean = false; - private constructor() { - } + private constructor() { + } - public static log(message: string): void { - if (Message.DISPLAY) console.log(message); - } + public static log(message: string): void { + if (Message.DISPLAY) console.log(message); + } - public static print(module: string, message: string): void { - if (Message.DISPLAY) console.log(module + " : " + message); - } + public static print(module: string, message: string): void { + if (Message.DISPLAY) console.log(module + " : " + message); + } - public static printWarning(module: string, message: string): void { - if (Message.DISPLAY) console.log("WARNING: " + module + " : " + message); - } + public static printWarning(module: string, message: string): void { + if (Message.DISPLAY) console.log("WARNING: " + module + " : " + message); + } - public static printError(module: string, exception: any, message: string): void { - if (Message.DISPLAY) console.log("ERROR: " + module + " : " + message); - if ((Message.DISPLAY) && (exception != null)) console.log("" + exception); - } + public static printError(module: string, exception: any, message: string): void { + if (Message.DISPLAY) console.log("ERROR: " + module + " : " + message); + if ((Message.DISPLAY) && (exception != null)) console.log("" + exception); + } } diff --git a/core/orbitgt/src/system/runtime/Numbers.ts b/core/orbitgt/src/system/runtime/Numbers.ts index 481ada79a03a..f2034403e6c9 100644 --- a/core/orbitgt/src/system/runtime/Numbers.ts +++ b/core/orbitgt/src/system/runtime/Numbers.ts @@ -19,81 +19,81 @@ import { ALong } from "./ALong"; */ /** @internal */ export class Numbers { - /** The static byte buffer for number format conversions */ - private static readonly BUFFER1: ArrayBuffer = new ArrayBuffer(8); - private static readonly I8_BUFFER1: Int8Array = new Int8Array(Numbers.BUFFER1); - private static readonly I32_BUFFER1: Int32Array = new Int32Array(Numbers.BUFFER1); - private static readonly F32_BUFFER1: Float32Array = new Float32Array(Numbers.BUFFER1); - private static readonly F64_BUFFER1: Float64Array = new Float64Array(Numbers.BUFFER1); - - private constructor() { - } - - public static sqrt(value: float64): float64 { - return Math.sqrt(value); - } - - public static floor(value: float64): float64 { - return Math.floor(value); - } - - public static intFloor(value: float64): int32 { - return Math.floor(value); - } - - public static divInt(value1: int32, value2: int32): int32 { - return Math.trunc(value1 / value2); - } - - public static intBitsToFloat(value: int32): float32 { - Numbers.I32_BUFFER1[0] = value; - return Numbers.F32_BUFFER1[0]; - } - - public static floatToIntBits(value: float32): int32 { - Numbers.F32_BUFFER1[0] = value; - return Numbers.I32_BUFFER1[0]; - } - - public static longBitsToDouble(value: ALong): float64 { - Numbers.I32_BUFFER1[0] = value.getLow(); - Numbers.I32_BUFFER1[1] = value.getHigh(); - return Numbers.F64_BUFFER1[0]; - } - - public static doubleToLongBits(value: float64): ALong { - Numbers.F64_BUFFER1[0] = value; - return ALong.fromHighLow(Numbers.I32_BUFFER1[1], Numbers.I32_BUFFER1[0]); - } - - public static intToDouble(value: int32): float64 { - return value; - } - - public static doubleToInt(value: float64): int32 { - return Math.floor(value); - } - - public static getInteger(value: string, defaultValue: int32): int32 { - if (value == undefined) return defaultValue; - if (value == null) return defaultValue; - if (value.length == 0) return defaultValue; - let parsed: int32 = parseInt(value); - return (Number.isNaN(parsed)) ? defaultValue : parsed; - } - - public static getDouble(value: string, defaultValue: float64): float64 { - if (value == undefined) return defaultValue; - if (value == null) return defaultValue; - if (value.length == 0) return defaultValue; - let parsed: float64 = parseFloat(value); - return (Number.isNaN(parsed)) ? defaultValue : parsed; - } - - public static rgbToString(color: int32): string { - let r: int32 = (color >> 16) & 0xFF; - let g: int32 = (color >> 8) & 0xFF; - let b: int32 = (color >> 0) & 0xFF; - return "" + r + "." + g + "." + b; - } + /** The static byte buffer for number format conversions */ + private static readonly BUFFER1: ArrayBuffer = new ArrayBuffer(8); + private static readonly I8_BUFFER1: Int8Array = new Int8Array(Numbers.BUFFER1); + private static readonly I32_BUFFER1: Int32Array = new Int32Array(Numbers.BUFFER1); + private static readonly F32_BUFFER1: Float32Array = new Float32Array(Numbers.BUFFER1); + private static readonly F64_BUFFER1: Float64Array = new Float64Array(Numbers.BUFFER1); + + private constructor() { + } + + public static sqrt(value: float64): float64 { + return Math.sqrt(value); + } + + public static floor(value: float64): float64 { + return Math.floor(value); + } + + public static intFloor(value: float64): int32 { + return Math.floor(value); + } + + public static divInt(value1: int32, value2: int32): int32 { + return Math.trunc(value1 / value2); + } + + public static intBitsToFloat(value: int32): float32 { + Numbers.I32_BUFFER1[0] = value; + return Numbers.F32_BUFFER1[0]; + } + + public static floatToIntBits(value: float32): int32 { + Numbers.F32_BUFFER1[0] = value; + return Numbers.I32_BUFFER1[0]; + } + + public static longBitsToDouble(value: ALong): float64 { + Numbers.I32_BUFFER1[0] = value.getLow(); + Numbers.I32_BUFFER1[1] = value.getHigh(); + return Numbers.F64_BUFFER1[0]; + } + + public static doubleToLongBits(value: float64): ALong { + Numbers.F64_BUFFER1[0] = value; + return ALong.fromHighLow(Numbers.I32_BUFFER1[1], Numbers.I32_BUFFER1[0]); + } + + public static intToDouble(value: int32): float64 { + return value; + } + + public static doubleToInt(value: float64): int32 { + return Math.floor(value); + } + + public static getInteger(value: string, defaultValue: int32): int32 { + if (value == undefined) return defaultValue; + if (value == null) return defaultValue; + if (value.length == 0) return defaultValue; + let parsed: int32 = parseInt(value); + return (Number.isNaN(parsed)) ? defaultValue : parsed; + } + + public static getDouble(value: string, defaultValue: float64): float64 { + if (value == undefined) return defaultValue; + if (value == null) return defaultValue; + if (value.length == 0) return defaultValue; + let parsed: float64 = parseFloat(value); + return (Number.isNaN(parsed)) ? defaultValue : parsed; + } + + public static rgbToString(color: int32): string { + let r: int32 = (color >> 16) & 0xFF; + let g: int32 = (color >> 8) & 0xFF; + let b: int32 = (color >> 0) & 0xFF; + return "" + r + "." + g + "." + b; + } } diff --git a/core/orbitgt/src/system/runtime/Strings.ts b/core/orbitgt/src/system/runtime/Strings.ts index 20d903a6e458..54d7c00901c0 100644 --- a/core/orbitgt/src/system/runtime/Strings.ts +++ b/core/orbitgt/src/system/runtime/Strings.ts @@ -19,181 +19,181 @@ import { AList } from "../collection/AList"; */ /** @internal */ export class Strings { - /** The 'infinity' character */ - public static INFINITY: string = "\u221E"; - /** The 'double-quote' character */ - public static DQUOTE: string = "\""; - /** The 'single-quote' character */ - public static SQUOTE: string = "'"; - /** The 'tab' character */ - public static TAB: string = String.fromCharCode(9); - /** The 'carriage return' character */ - public static CR: string = String.fromCharCode(13); - /** The 'newline' (linux line terminator) character */ - public static NL: string = String.fromCharCode(10); - /** The 'carriage return+newline' (dos line terminator) character sequence */ - public static CR_NL: string = String.fromCharCode(13) + String.fromCharCode(10); - - private constructor() { - } - - public static getLength(value: string): int32 { - return value.length; - } - - public static getCharAt(value: string, index: int32): int16 { - return value.charCodeAt(index); - } - - public static appendChar(value: string, charCode: int16): string { - return value + String.fromCharCode(charCode); - } - - public static prependChar(value: string, charCode: int16): string { - return String.fromCharCode(charCode) + value; - } - - public static equals(value1: string, value2: string): boolean { - if (value1 == null) return (value2 == null); - if (value2 == null) return false; - return (value1 === value2); - } - - public static equalsIgnoreCase(value1: string, value2: string): boolean { - if (value1 == null) return (value2 == null); - if (value2 == null) return false; - return (value1.toLowerCase() === value2.toLowerCase()); - } - - public static startsWith(value: string, prefix: string): boolean { - return value.startsWith(prefix); - } - - public static endsWith(value: string, suffix: string): boolean { - return value.endsWith(suffix); - } - - public static substring(value: string, index0: int32, index1: int32): string { - return value.substring(index0, index1); - } - - public static substringFrom(value: string, index: int32): string { - return value.substring(index); - } - - public static charCodeAt(value: string, index: int32): int32 { - return value.charCodeAt(index); - } - - public static charCodeToString(code: int32): string { - return String.fromCharCode(code); - } - - public static indexOf(value: string, part: string): int32 { - return value.indexOf(part); - } - - public static lastIndexOf(value: string, part: string): int32 { - return value.lastIndexOf(part); - } - - public static indexOfFrom(value: string, part: string, index: int32): int32 { - return value.indexOf(part, index); - } - - public static compareTo(value1: string, value2: string): int32 { - if (value1 === value2) return 0; - return (value1 < value2) ? -1 : 1; - } - - public static compareToIgnoreCase(value1: string, value2: string): int32 { - return Strings.compareTo(value1.toLowerCase(), value2.toLowerCase()); - } - - public static splitAsList(value: string, separators: string): AList { - /* Null? */ - if (value == null) return null; - /* Make a list of parts */ - let parts: AList = new AList(); - /* Fast-out */ - if (value.length == 0) return parts; - /* Make a list of parts */ - while (true) { - /* Get the index of the next separator */ - let index: int32 = value.length; - for (let i: int32 = 0; i < separators.length; i++) { - let nextIndex: int32 = value.indexOf(separators.charAt(i)); - if ((nextIndex >= 0) && (nextIndex < index)) index = nextIndex; - } - /* None remaining ? */ - if (index == value.length) { - /* Done */ - parts.add(value); - break; - } - else { - /* Add a substring */ - parts.add(value.substring(0, index)); - value = value.substring(index + 1); - } - } - /* Return the parts */ - return parts; - } - - public static splitAdvanced(value: string, separators: string, opens: string, closes: string, literals: string): AList { - /* Check the value */ - if (value == null) return null; - /* Check the parameters */ - if (separators == null) separators = ""; - if (opens == null) opens = ""; - if (closes == null) closes = ""; - if (literals == null) literals = ""; - /* Make a list of parts */ - let parts: AList = new AList(); - /* Check all characters in the value */ - let level: int32 = 0; - let start: int32 = 0; - let literal: string = null; - for (let i: int32 = 0; i < value.length; i++) { - /* Get the next character */ - let c: string = value.substring(i, i + 1); - /* Escaped character ? */ - if ((i > 0) && (value.substring(i - 1, i) === "\\")) continue; - /* Quote bound ? */ - if (literal != null ? literal === c : ((literals.length > 0) && (literals.indexOf(c) >= 0))) { - /* Toggle */ - literal = literal == null ? c : null; - continue; - } - /* Ignore this character ? */ - if (literal != null) continue; - /* Separator ? */ - if ((separators.indexOf(c) >= 0) && (level == 0)) { - /* Get the part */ - parts.add(value.substring(start, i)); - start = i + 1; - } - /* Open ? */ - else if (opens.indexOf(c) >= 0) { - level += 1; - } - /* Close ? */ - else if (closes.indexOf(c) >= 0) { - level -= 1; - } - } - /* Add the last part */ - parts.add(value.substring(start)); - /* Return the parts */ - return parts; - } - - public static trim(value: string): string { - return value.trim(); - } - - public static replace(line: string, key: string, value: string): string { - return line.replace(key, value); - } + /** The 'infinity' character */ + public static INFINITY: string = "\u221E"; + /** The 'double-quote' character */ + public static DQUOTE: string = '"'; + /** The 'single-quote' character */ + public static SQUOTE: string = "'"; + /** The 'tab' character */ + public static TAB: string = String.fromCharCode(9); + /** The 'carriage return' character */ + public static CR: string = String.fromCharCode(13); + /** The 'newline' (linux line terminator) character */ + public static NL: string = String.fromCharCode(10); + /** The 'carriage return+newline' (dos line terminator) character sequence */ + public static CR_NL: string = String.fromCharCode(13) + String.fromCharCode(10); + + private constructor() { + } + + public static getLength(value: string): int32 { + return value.length; + } + + public static getCharAt(value: string, index: int32): int16 { + return value.charCodeAt(index); + } + + public static appendChar(value: string, charCode: int16): string { + return value + String.fromCharCode(charCode); + } + + public static prependChar(value: string, charCode: int16): string { + return String.fromCharCode(charCode) + value; + } + + public static equals(value1: string, value2: string): boolean { + if (value1 == null) return (value2 == null); + if (value2 == null) return false; + return (value1 === value2); + } + + public static equalsIgnoreCase(value1: string, value2: string): boolean { + if (value1 == null) return (value2 == null); + if (value2 == null) return false; + return (value1.toLowerCase() === value2.toLowerCase()); + } + + public static startsWith(value: string, prefix: string): boolean { + return value.startsWith(prefix); + } + + public static endsWith(value: string, suffix: string): boolean { + return value.endsWith(suffix); + } + + public static substring(value: string, index0: int32, index1: int32): string { + return value.substring(index0, index1); + } + + public static substringFrom(value: string, index: int32): string { + return value.substring(index); + } + + public static charCodeAt(value: string, index: int32): int32 { + return value.charCodeAt(index); + } + + public static charCodeToString(code: int32): string { + return String.fromCharCode(code); + } + + public static indexOf(value: string, part: string): int32 { + return value.indexOf(part); + } + + public static lastIndexOf(value: string, part: string): int32 { + return value.lastIndexOf(part); + } + + public static indexOfFrom(value: string, part: string, index: int32): int32 { + return value.indexOf(part, index); + } + + public static compareTo(value1: string, value2: string): int32 { + if (value1 === value2) return 0; + return (value1 < value2) ? -1 : 1; + } + + public static compareToIgnoreCase(value1: string, value2: string): int32 { + return Strings.compareTo(value1.toLowerCase(), value2.toLowerCase()); + } + + public static splitAsList(value: string, separators: string): AList { + /* Null? */ + if (value == null) return null; + /* Make a list of parts */ + let parts: AList = new AList(); + /* Fast-out */ + if (value.length == 0) return parts; + /* Make a list of parts */ + while (true) { + /* Get the index of the next separator */ + let index: int32 = value.length; + for (let i: int32 = 0; i < separators.length; i++) { + let nextIndex: int32 = value.indexOf(separators.charAt(i)); + if ((nextIndex >= 0) && (nextIndex < index)) index = nextIndex; + } + /* None remaining ? */ + if (index == value.length) { + /* Done */ + parts.add(value); + break; + } + else { + /* Add a substring */ + parts.add(value.substring(0, index)); + value = value.substring(index + 1); + } + } + /* Return the parts */ + return parts; + } + + public static splitAdvanced(value: string, separators: string, opens: string, closes: string, literals: string): AList { + /* Check the value */ + if (value == null) return null; + /* Check the parameters */ + if (separators == null) separators = ""; + if (opens == null) opens = ""; + if (closes == null) closes = ""; + if (literals == null) literals = ""; + /* Make a list of parts */ + let parts: AList = new AList(); + /* Check all characters in the value */ + let level: int32 = 0; + let start: int32 = 0; + let literal: string = null; + for (let i: int32 = 0; i < value.length; i++) { + /* Get the next character */ + let c: string = value.substring(i, i + 1); + /* Escaped character ? */ + if ((i > 0) && (value.substring(i - 1, i) === "\\")) continue; + /* Quote bound ? */ + if (literal != null ? literal === c : ((literals.length > 0) && (literals.indexOf(c) >= 0))) { + /* Toggle */ + literal = literal == null ? c : null; + continue; + } + /* Ignore this character ? */ + if (literal != null) continue; + /* Separator ? */ + if ((separators.indexOf(c) >= 0) && (level == 0)) { + /* Get the part */ + parts.add(value.substring(start, i)); + start = i + 1; + } + /* Open ? */ + else if (opens.indexOf(c) >= 0) { + level += 1; + } + /* Close ? */ + else if (closes.indexOf(c) >= 0) { + level -= 1; + } + } + /* Add the last part */ + parts.add(value.substring(start)); + /* Return the parts */ + return parts; + } + + public static trim(value: string): string { + return value.trim(); + } + + public static replace(line: string, key: string, value: string): string { + return line.replace(key, value); + } } diff --git a/core/orbitgt/src/system/runtime/iComparator.ts b/core/orbitgt/src/system/runtime/iComparator.ts index 0e6599966faa..5a2c9e760ee3 100644 --- a/core/orbitgt/src/system/runtime/iComparator.ts +++ b/core/orbitgt/src/system/runtime/iComparator.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.runtime; +// package orbitgt.system.runtime; type int8 = number; type int16 = number; @@ -19,5 +19,5 @@ type float64 = number; */ /** @internal */ export interface iComparator { - compare(value1: T, value2: T): int32; + compare(value1: T, value2: T): int32; } diff --git a/core/orbitgt/src/system/storage/CacheList.ts b/core/orbitgt/src/system/storage/CacheList.ts index 539aa2155d8d..8a9aecbc9750 100644 --- a/core/orbitgt/src/system/storage/CacheList.ts +++ b/core/orbitgt/src/system/storage/CacheList.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -23,77 +23,76 @@ import { CachedItem } from "./CachedItem"; * Class CacheList caches a list of items based on last-recently-used order. */ /** @internal */ -export class CacheList -{ - /** The optional maximum number of entries in the list (no maximum if zero) */ - private _maxEntries: int32; - /** The list of entries (most used at the back) */ - private _entries: AList>; - /** The number of times a requested item was found in the cache */ - public hitCount: int32; - /** The number of times a requested item was not found in the cache */ - public missCount: int32; +export class CacheList { + /** The optional maximum number of entries in the list (no maximum if zero) */ + private _maxEntries: int32; + /** The list of entries (most used at the back) */ + private _entries: AList>; + /** The number of times a requested item was found in the cache */ + public hitCount: int32; + /** The number of times a requested item was not found in the cache */ + public missCount: int32; - /** - * Create a new cache, with an optional non-zero maximum number of entries. - */ - public constructor(maxEntries: int32) { - this._maxEntries = maxEntries; - this._entries = new AList>(); - this.hitCount = 0; - this.missCount = 0; - } + /** + * Create a new cache, with an optional non-zero maximum number of entries. + */ + public constructor(maxEntries: int32) { + this._maxEntries = maxEntries; + this._entries = new AList>(); + this.hitCount = 0; + this.missCount = 0; + } - /** - * Get the number of entries in the cache. - */ - public size(): int32 { - return this._entries.size(); - } + /** + * Get the number of entries in the cache. + */ + public size(): int32 { + return this._entries.size(); + } - /** - * Clear all entries. - */ - public clear(): void { - this._entries.clear(); - this.hitCount = 0; - this.missCount = 0; - } + /** + * Clear all entries. + */ + public clear(): void { + this._entries.clear(); + this.hitCount = 0; + this.missCount = 0; + } - /** - * Find an entry in the cache, or return null if not found. - */ - public findEntry(key: string): T { - /* Check all entries */ - for (let i: number = 0; i < this._entries.size(); i++) { - /* Search back (most used) to front (least used) */ - let entryIndex: int32 = (this._entries.size() - 1 - i); - /* Is this the requested entry? */ - let entry: CachedItem = this._entries.get(entryIndex); - if (Strings.equals(entry.key, key)) { - /* Move the latest-used entry to the back of the list */ - if (entryIndex < this._entries.size() - 1) { - this._entries.remove(entryIndex); - this._entries.add(entry); - } - /* Update the access time */ - entry.accessTime = ASystem.time(); - /* The entry was found */ - this.hitCount++; - return entry.element; - } - } - /* No entry was found */ - this.missCount++; - return null; - } + /** + * Find an entry in the cache, or return null if not found. + */ + public findEntry(key: string): T { + /* Check all entries */ + for (let i: number = 0; i < this._entries.size(); i++) { + /* Search back (most used) to front (least used) */ + let entryIndex: int32 = this._entries.size() - 1 - i; + /* Is this the requested entry? */ + let entry: CachedItem = this._entries.get(entryIndex); + if (Strings.equals(entry.key, key)) { + /* Move the latest-used entry to the back of the list */ + if (entryIndex < this._entries.size() - 1) { + this._entries.remove(entryIndex); + this._entries.add(entry); + } + /* Update the access time */ + entry.accessTime = ASystem.time(); + /* The entry was found */ + this.hitCount++; + return entry.element; + } + } + /* No entry was found */ + this.missCount++; + return null; + } - /** - * Add an entry to the cache, pushing out the oldest entry if the cache is full. - */ - public addEntry(key: string, element: T): void { - /* Add a new entry to the back of the list */ - this._entries.add(new CachedItem(key, element, ASystem.time())); - if ((this._maxEntries > 0) && (this._entries.size() > this._maxEntries)) this._entries.remove(0); - } + /** + * Add an entry to the cache, pushing out the oldest entry if the cache is full. + */ + public addEntry(key: string, element: T): void { + /* Add a new entry to the back of the list */ + this._entries.add(new CachedItem(key, element, ASystem.time())); + if ((this._maxEntries > 0) && (this._entries.size() > this._maxEntries)) this._entries.remove(0); + } } diff --git a/core/orbitgt/src/system/storage/CachedItem.ts b/core/orbitgt/src/system/storage/CachedItem.ts index f21d6cb4edf3..944ee9b4d049 100644 --- a/core/orbitgt/src/system/storage/CachedItem.ts +++ b/core/orbitgt/src/system/storage/CachedItem.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -18,21 +18,20 @@ type float64 = number; * Class CachedItem stores a single entry in a cache of items. */ /** @internal */ -export class CachedItem -{ - /** The unique key of the item */ - public key: string; - /** The item to cache */ - public element: T; - /** The latest access time of the item */ - public accessTime: float64; +export class CachedItem { + /** The unique key of the item */ + public key: string; + /** The item to cache */ + public element: T; + /** The latest access time of the item */ + public accessTime: float64; - /** - * Create a new item. - */ - public constructor(key: string, element: T, accessTime: float64) { - this.key = key; - this.element = element; - this.accessTime = accessTime; - } + /** + * Create a new item. + */ + public constructor(key: string, element: T, accessTime: float64) { + this.key = key; + this.element = element; + this.accessTime = accessTime; + } } diff --git a/core/orbitgt/src/system/storage/ContentLoader.ts b/core/orbitgt/src/system/storage/ContentLoader.ts index e9a34ad8924d..f2dc87decae3 100644 --- a/core/orbitgt/src/system/storage/ContentLoader.ts +++ b/core/orbitgt/src/system/storage/ContentLoader.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -14,7 +14,6 @@ type int32 = number; type float32 = number; type float64 = number; - import { ABuffer } from "../buffer/ABuffer"; import { AList } from "../collection/AList"; import { ALong } from "../runtime/ALong"; @@ -28,101 +27,104 @@ import { FileStorage } from "./FileStorage"; */ /** @internal */ export class ContentLoader { - /** The name of this module */ - private static readonly MODULE: string = "ContentLoader"; - - /** The storage space of the file */ - private _fileStorage: FileStorage; - /** The name of the file */ - private _fileName: string; - - /** The list of requests */ - private _requests: AList; - /** Has loading started? */ - private _loading: boolean; - /** Has loading stopped? */ - private _loaded: boolean; - /** The list of responses */ - private _responses: AList; - - /** - * Create a new content loader. - */ - public constructor(fileStorage: FileStorage, fileName: string) { - this._fileStorage = fileStorage; - this._fileName = fileName; - this.clear(); - } - - /** - * Clear the content loader for reuse. - */ - public clear(): void { - this._requests = new AList(); - this._loading = false; - this._loaded = false; - this._responses = null; - } - - /** - * Add a request to load a content range. - */ - public requestFilePart(offset: ALong, size: int32): ContentLoader { - this._requests.add(new FileRange(offset, size)); - return this; - } - - /** - * Get the total size of the data to be loaded. - */ - public getTotalRequestSize(): int32 { - let totalSize: int32 = 0; - for (let i: number = 0; i < this._requests.size(); i++) totalSize += this._requests.get(i).size; - return totalSize; - } - - /** - * Print info. - */ - public printInfo(): void { - Message.print(ContentLoader.MODULE, "Requesting " + this._requests.size() + " parts from '" + this._fileName + "' with total size " + this.getTotalRequestSize()); - } - - /** - * Has all content been loaded? - */ - public isLoaded(): boolean { - return this._loaded; - } - - /** - * Has all content been loaded? - */ - public isAvailable(): boolean { - return this.isLoaded(); - } - - /** - * Load all content from storage. - */ - public async load(): Promise { - this._loading = true; - this.printInfo(); - this._responses = await this._fileStorage.readFileParts(this._fileName, this._requests); - this._loaded = true; - return this; - } - - /** - * Get a content range that has been loaded. - */ - public getFilePart(offset: ALong, size: int32): ABuffer { - for (let i: number = 0; i < this._responses.size(); i++) { - let response: FileContent = this._responses.get(i); - if (response.offset.same(offset) && (response.content.size() == size)) { - return response.content; - } - } - return null; + /** The name of this module */ + private static readonly MODULE: string = "ContentLoader"; + + /** The storage space of the file */ + private _fileStorage: FileStorage; + /** The name of the file */ + private _fileName: string; + + /** The list of requests */ + private _requests: AList; + /** Has loading started? */ + private _loading: boolean; + /** Has loading stopped? */ + private _loaded: boolean; + /** The list of responses */ + private _responses: AList; + + /** + * Create a new content loader. + */ + public constructor(fileStorage: FileStorage, fileName: string) { + this._fileStorage = fileStorage; + this._fileName = fileName; + this.clear(); + } + + /** + * Clear the content loader for reuse. + */ + public clear(): void { + this._requests = new AList(); + this._loading = false; + this._loaded = false; + this._responses = null; + } + + /** + * Add a request to load a content range. + */ + public requestFilePart(offset: ALong, size: int32): ContentLoader { + this._requests.add(new FileRange(offset, size)); + return this; + } + + /** + * Get the total size of the data to be loaded. + */ + public getTotalRequestSize(): int32 { + let totalSize: int32 = 0; + for (let i: number = 0; i < this._requests.size(); i++) totalSize += this._requests.get(i).size; + return totalSize; + } + + /** + * Print info. + */ + public printInfo(): void { + Message.print( + ContentLoader.MODULE, + "Requesting " + this._requests.size() + " parts from '" + this._fileName + "' with total size " + this.getTotalRequestSize(), + ); + } + + /** + * Has all content been loaded? + */ + public isLoaded(): boolean { + return this._loaded; + } + + /** + * Has all content been loaded? + */ + public isAvailable(): boolean { + return this.isLoaded(); + } + + /** + * Load all content from storage. + */ + public async load(): Promise { + this._loading = true; + this.printInfo(); + this._responses = await this._fileStorage.readFileParts(this._fileName, this._requests); + this._loaded = true; + return this; + } + + /** + * Get a content range that has been loaded. + */ + public getFilePart(offset: ALong, size: int32): ABuffer { + for (let i: number = 0; i < this._responses.size(); i++) { + let response: FileContent = this._responses.get(i); + if (response.offset.same(offset) && (response.content.size() == size)) { + return response.content; + } } + return null; + } } diff --git a/core/orbitgt/src/system/storage/FileContent.ts b/core/orbitgt/src/system/storage/FileContent.ts index 60b46294e84f..40a02b231471 100644 --- a/core/orbitgt/src/system/storage/FileContent.ts +++ b/core/orbitgt/src/system/storage/FileContent.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -22,16 +22,16 @@ import { ALong } from "../runtime/ALong"; */ /** @internal */ export class FileContent { - /** The (integer) offset of the content range */ - public offset: ALong; - /** The content */ - public content: ABuffer; + /** The (integer) offset of the content range */ + public offset: ALong; + /** The content */ + public content: ABuffer; - /** - * Create a new content holder. - */ - public constructor(offset: ALong, content: ABuffer) { - this.offset = offset; - this.content = content; - } + /** + * Create a new content holder. + */ + public constructor(offset: ALong, content: ABuffer) { + this.offset = offset; + this.content = content; + } } diff --git a/core/orbitgt/src/system/storage/FileRange.ts b/core/orbitgt/src/system/storage/FileRange.ts index 7cf73ef2e4f5..264d07fbeed5 100644 --- a/core/orbitgt/src/system/storage/FileRange.ts +++ b/core/orbitgt/src/system/storage/FileRange.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -21,16 +21,16 @@ import { ALong } from "../runtime/ALong"; */ /** @internal */ export class FileRange { - /** The (integer) offset of the content range */ - public offset: ALong; - /** The size of the content range */ - public size: int32; + /** The (integer) offset of the content range */ + public offset: ALong; + /** The size of the content range */ + public size: int32; - /** - * Create a new content range. - */ - public constructor(offset: ALong, size: int32) { - this.offset = offset; - this.size = size; - } + /** + * Create a new content range. + */ + public constructor(offset: ALong, size: int32) { + this.offset = offset; + this.size = size; + } } diff --git a/core/orbitgt/src/system/storage/FileStorage.ts b/core/orbitgt/src/system/storage/FileStorage.ts index 58a6acac7ab8..37c78d0a1801 100644 --- a/core/orbitgt/src/system/storage/FileStorage.ts +++ b/core/orbitgt/src/system/storage/FileStorage.ts @@ -6,7 +6,7 @@ * @module OrbitGT */ -//package orbitgt.system.storage; +// package orbitgt.system.storage; type int8 = number; type int16 = number; @@ -25,54 +25,54 @@ import { FileRange } from "./FileRange"; */ /** @internal */ export class FileStorage { - /** - * Create new storage. - */ - public constructor() { - } + /** + * Create new storage. + */ + public constructor() { + } - /** - * Close the storage. - */ - public close(): void { - /* Override if needed */ - } + /** + * Close the storage. + */ + public close(): void { + /* Override if needed */ + } - /** - * Print (and optionally clear) file access statistics. - */ - public printStatistics(clear: boolean): void { - /* Override if needed */ - } + /** + * Print (and optionally clear) file access statistics. + */ + public printStatistics(clear: boolean): void { + /* Override if needed */ + } - /** - * Get the length of a file (returns -1 if the file is not found). - */ - public async getFileLength(fileName: string): Promise { - /* Override this method */ - return ALong.MINUS_ONE; - } + /** + * Get the length of a file (returns -1 if the file is not found). + */ + public async getFileLength(fileName: string): Promise { + /* Override this method */ + return ALong.MINUS_ONE; + } - /** - * Read some parts of a file. - */ - public async readFileParts(fileName: string, ranges: AList): Promise> { - /* Override this method */ - return null; - } + /** + * Read some parts of a file. + */ + public async readFileParts(fileName: string, ranges: AList): Promise> { + /* Override this method */ + return null; + } - /** - * Read a part of a file. - */ - public async readFilePart(fileName: string, offset: ALong, size: int32): Promise { - /* Override this method */ - return null; - } + /** + * Read a part of a file. + */ + public async readFilePart(fileName: string, offset: ALong, size: int32): Promise { + /* Override this method */ + return null; + } - /** - * Write a file. - */ - public async writeFile(fileName: string, fileContent: ABuffer): Promise { - /* Override this method */ - } + /** + * Write a file. + */ + public async writeFile(fileName: string, fileContent: ABuffer): Promise { + /* Override this method */ + } } diff --git a/core/orbitgt/src/system/storage/NodeFS.ts b/core/orbitgt/src/system/storage/NodeFS.ts index 1e60ab4100e1..a5c309e76b93 100644 --- a/core/orbitgt/src/system/storage/NodeFS.ts +++ b/core/orbitgt/src/system/storage/NodeFS.ts @@ -26,64 +26,67 @@ type float64 = number; */ /** @internal */ export class NodeFS extends FileStorage { - /** - * Create new storage. - */ - public constructor() { - super(); - } + /** + * Create new storage. + */ + public constructor() { + super(); + } - /** - * FileStorage method. - */ - public override close(): void { - } + /** + * FileStorage method. + */ + public override close(): void { + } - /** - * FileStorage method. - */ - public override async getFileLength(fileName: string): Promise { - const fileStats: fs.Stats = fs.statSync(fileName); - return ALong.fromDouble(fileStats.size); - } + /** + * FileStorage method. + */ + public override async getFileLength(fileName: string): Promise { + const fileStats: fs.Stats = fs.statSync(fileName); + return ALong.fromDouble(fileStats.size); + } - /** - * FileStorage method. - */ - public override async readFilePart(fileName: string, offset: ALong, size: int32): Promise { - const rawBuffer: ArrayBuffer = new ArrayBuffer(size); - const buffer: Uint8Array = new Uint8Array(rawBuffer); - const fd: number = fs.openSync(fileName, "r"); - const bytesRead: number = fs.readSync(fd, buffer, 0, size, offset.toDouble()); - fs.closeSync(fd); - ASystem.assert0(bytesRead == size, `Expected ${size} bytes read, not ${bytesRead} from file '${fileName}' offset ${offset.toDouble()}`); - return ABuffer.wrap(rawBuffer); - } + /** + * FileStorage method. + */ + public override async readFilePart(fileName: string, offset: ALong, size: int32): Promise { + const rawBuffer: ArrayBuffer = new ArrayBuffer(size); + const buffer: Uint8Array = new Uint8Array(rawBuffer); + const fd: number = fs.openSync(fileName, "r"); + const bytesRead: number = fs.readSync(fd, buffer, 0, size, offset.toDouble()); + fs.closeSync(fd); + ASystem.assert0(bytesRead == size, `Expected ${size} bytes read, not ${bytesRead} from file '${fileName}' offset ${offset.toDouble()}`); + return ABuffer.wrap(rawBuffer); + } - /** - * FileStorage method. - */ - public override async readFileParts(fileName: string, ranges: AList): Promise> { - const buffers: AList = new AList(); - const fd: number = fs.openSync(fileName, "r"); - for (let i: number = 0; i < ranges.size(); i++) { - const range: FileRange = ranges.get(i); - const rawBuffer: ArrayBuffer = new ArrayBuffer(range.size); - const buffer: Uint8Array = new Uint8Array(rawBuffer); - const bytesRead: number = fs.readSync(fd, buffer, 0, range.size, range.offset.toDouble()); - ASystem.assert0(bytesRead == range.size, `Expected ${range.size} bytes read, not ${bytesRead} from file '${fileName}' offset ${range.offset.toDouble()}`); - buffers.add(new FileContent(range.offset, ABuffer.wrap(rawBuffer))); - } - fs.closeSync(fd); - return buffers; + /** + * FileStorage method. + */ + public override async readFileParts(fileName: string, ranges: AList): Promise> { + const buffers: AList = new AList(); + const fd: number = fs.openSync(fileName, "r"); + for (let i: number = 0; i < ranges.size(); i++) { + const range: FileRange = ranges.get(i); + const rawBuffer: ArrayBuffer = new ArrayBuffer(range.size); + const buffer: Uint8Array = new Uint8Array(rawBuffer); + const bytesRead: number = fs.readSync(fd, buffer, 0, range.size, range.offset.toDouble()); + ASystem.assert0( + bytesRead == range.size, + `Expected ${range.size} bytes read, not ${bytesRead} from file '${fileName}' offset ${range.offset.toDouble()}`, + ); + buffers.add(new FileContent(range.offset, ABuffer.wrap(rawBuffer))); } + fs.closeSync(fd); + return buffers; + } - /** - * FileStorage method. - */ - public override async writeFile(fileName: string, fileContent: ABuffer): Promise { - const fd: number = fs.openSync(fileName, "w"); - fs.writeSync(fd, new Uint8Array(fileContent.toNativeBuffer())); - fs.closeSync(fd); - } + /** + * FileStorage method. + */ + public override async writeFile(fileName: string, fileContent: ABuffer): Promise { + const fd: number = fs.openSync(fileName, "w"); + fs.writeSync(fd, new Uint8Array(fileContent.toNativeBuffer())); + fs.closeSync(fd); + } } diff --git a/core/orbitgt/src/system/storage/PageCachedFile.ts b/core/orbitgt/src/system/storage/PageCachedFile.ts index c81b1fd76a38..7c257903c7eb 100644 --- a/core/orbitgt/src/system/storage/PageCachedFile.ts +++ b/core/orbitgt/src/system/storage/PageCachedFile.ts @@ -30,154 +30,154 @@ import { FileStorage } from "./FileStorage"; */ /** @internal */ export class PageCachedFile extends FileStorage { - private _fileStorage: FileStorage; - private _fileName: string; - private _fileSize: ALong; - private _pageSize: int32; - private _pageCount: int32; + private _fileStorage: FileStorage; + private _fileName: string; + private _fileSize: ALong; + private _pageSize: int32; + private _pageCount: int32; - private _contentCache: CacheList; - private _requestCount: int32; - private _requestSize: int32; + private _contentCache: CacheList; + private _requestCount: int32; + private _requestSize: int32; - /** - * Create a new cached file. - * @param fileStorage the underlying file storage. - * @param fileName the name of the file to cache. - * @param fileSize the length of the file to cache. - * @param pageSize the byte size of a cache page (common sizes are 32768, 65536, 131072 or 262144). - * @param maxPageCount the maximum number of pages to cache (the oldest pages are purged when the cache is full). - */ - public constructor(fileStorage: FileStorage, fileName: string, fileSize: ALong, pageSize: int32, maxPageCount: int32) { - super(); - this._fileStorage = fileStorage; - this._fileName = fileName; - this._fileSize = fileSize; - this._pageSize = pageSize; - this._pageCount = fileSize.subInt(1).divInt(this._pageSize).addInt(1).toInt(); - this._contentCache = new CacheList(maxPageCount); - this._requestCount = 0; - this._requestSize = 0; - } + /** + * Create a new cached file. + * @param fileStorage the underlying file storage. + * @param fileName the name of the file to cache. + * @param fileSize the length of the file to cache. + * @param pageSize the byte size of a cache page (common sizes are 32768, 65536, 131072 or 262144). + * @param maxPageCount the maximum number of pages to cache (the oldest pages are purged when the cache is full). + */ + public constructor(fileStorage: FileStorage, fileName: string, fileSize: ALong, pageSize: int32, maxPageCount: int32) { + super(); + this._fileStorage = fileStorage; + this._fileName = fileName; + this._fileSize = fileSize; + this._pageSize = pageSize; + this._pageCount = fileSize.subInt(1).divInt(this._pageSize).addInt(1).toInt(); + this._contentCache = new CacheList(maxPageCount); + this._requestCount = 0; + this._requestSize = 0; + } - /** - * FileStorage method. - */ - public override close(): void { - this._fileStorage.close(); // deep close - } + /** + * FileStorage method. + */ + public override close(): void { + this._fileStorage.close(); // deep close + } - /** - * FileStorage method. - */ - public override async getFileLength(fileName: string): Promise { - return this._fileSize; - } + /** + * FileStorage method. + */ + public override async getFileLength(fileName: string): Promise { + return this._fileSize; + } - /** - * FileStorage method. - */ - public override async readFileParts(fileName: string, ranges: AList): Promise> { - /* Define the set of pages we need to fulfill the request */ - const pageMap: StringMap = new StringMap(); - /* Create a list of missing pages */ - const missingPages: AList = new AList(); - const missingKeys: AList = new AList(); - for (let r: number = 0; r < ranges.size(); r++) { - /* Scan the needed pages of the next range */ - const range: FileRange = ranges.get(r); - const page0: int32 = range.offset.divInt(this._pageSize).toInt(); - const page1: int32 = range.offset.addInt(range.size - 1).divInt(this._pageSize).toInt() + 1; // exclusive - for (let i: number = page0; i < page1; i++) { - /* Try to get the page from the cache */ - const pageKey: string = (`${i}`); - const page: ABuffer = this._contentCache.findEntry(pageKey); - if (page == null) { - /* Do not request the same page twice */ - if (missingKeys.contains(pageKey) == false) { - /* Add a request to read the missing page */ - const pageOffset0: ALong = ALong.fromInt(this._pageSize).mulInt(i); - const pageOffset1: ALong = ALong.min(pageOffset0.addInt(this._pageSize), this._fileSize); - const pageSize: int32 = pageOffset1.sub(pageOffset0).toInt(); - missingPages.add(new FileRange(pageOffset0, pageSize)); - missingKeys.add(pageKey); - } - } else { - /* Keep */ - pageMap.set(pageKey, page); - } - } - } - /* Do we have to load missing pages? */ - if (missingPages.size() > 0) { - /* Load all missing pages with one call to the storage */ - Message.log(`Requesting ${missingPages.size()} missing cache pages for '${this._fileName}'`); - const loadedPages: AList = await this._fileStorage.readFileParts(fileName, missingPages); - /* Add to the cache for reuse */ - for (let i: number = 0; i < loadedPages.size(); i++) { - const pageKey: string = missingKeys.get(i); - const pageContent: FileContent = loadedPages.get(i); - this._contentCache.addEntry(pageKey, pageContent.content); - pageMap.set(pageKey, pageContent.content); - } - } - /* Create the responses from the cached content */ - const responseList: AList = new AList(); - for (let r: number = 0; r < ranges.size(); r++) { - /* Create the response for the next range */ - const range: FileRange = ranges.get(r); - const rangeExtent: ALong = range.offset.addInt(range.size); - const response: ABuffer = new ABuffer(range.size); - let responseOffset: int32 = 0; - this._requestCount++; - this._requestSize += range.size; - /* Scan the needed pages */ - const page0: int32 = range.offset.divInt(this._pageSize).toInt(); - const page1: int32 = range.offset.addInt(range.size - 1).divInt(this._pageSize).toInt() + 1; // exclusive - for (let i: number = page0; i < page1; i++) { - /* Get the next page from the cache */ - const pageKey: string = (`${i}`); - const page: ABuffer = pageMap.get(pageKey); - ASystem.assertNot(page == null, `Missing cache page ${pageKey}`); - /* Get the extent of the page */ - const pageOffset0: ALong = ALong.fromInt(this._pageSize).mulInt(i); - const pageOffset1: ALong = ALong.min(pageOffset0.addInt(this._pageSize), this._fileSize); - /* Copy the overlapping part of the page to the response */ - const currentOffset: ALong = range.offset.addInt(responseOffset); - const copyOffset: int32 = currentOffset.sub(pageOffset0).toInt(); - const copySize: int32 = ALong.min(pageOffset1, rangeExtent).sub(currentOffset).toInt(); - ABuffer.arrayCopy(page, copyOffset, response, responseOffset, copySize); - responseOffset += copySize; - } - /* Add the response to the list */ - ASystem.assertNot(responseOffset != range.size, `Expected ${range.size} response size, not ${responseOffset}`); - responseList.add(new FileContent(range.offset, response)); - } - return responseList; - } + /** + * FileStorage method. + */ + public override async readFileParts(fileName: string, ranges: AList): Promise> { + /* Define the set of pages we need to fulfill the request */ + const pageMap: StringMap = new StringMap(); + /* Create a list of missing pages */ + const missingPages: AList = new AList(); + const missingKeys: AList = new AList(); + for (let r: number = 0; r < ranges.size(); r++) { + /* Scan the needed pages of the next range */ + const range: FileRange = ranges.get(r); + const page0: int32 = range.offset.divInt(this._pageSize).toInt(); + const page1: int32 = range.offset.addInt(range.size - 1).divInt(this._pageSize).toInt() + 1; // exclusive + for (let i: number = page0; i < page1; i++) { + /* Try to get the page from the cache */ + const pageKey: string = `${i}`; + const page: ABuffer = this._contentCache.findEntry(pageKey); + if (page == null) { + /* Do not request the same page twice */ + if (missingKeys.contains(pageKey) == false) { + /* Add a request to read the missing page */ + const pageOffset0: ALong = ALong.fromInt(this._pageSize).mulInt(i); + const pageOffset1: ALong = ALong.min(pageOffset0.addInt(this._pageSize), this._fileSize); + const pageSize: int32 = pageOffset1.sub(pageOffset0).toInt(); + missingPages.add(new FileRange(pageOffset0, pageSize)); + missingKeys.add(pageKey); + } + } else { + /* Keep */ + pageMap.set(pageKey, page); + } + } + } + /* Do we have to load missing pages? */ + if (missingPages.size() > 0) { + /* Load all missing pages with one call to the storage */ + Message.log(`Requesting ${missingPages.size()} missing cache pages for '${this._fileName}'`); + const loadedPages: AList = await this._fileStorage.readFileParts(fileName, missingPages); + /* Add to the cache for reuse */ + for (let i: number = 0; i < loadedPages.size(); i++) { + const pageKey: string = missingKeys.get(i); + const pageContent: FileContent = loadedPages.get(i); + this._contentCache.addEntry(pageKey, pageContent.content); + pageMap.set(pageKey, pageContent.content); + } + } + /* Create the responses from the cached content */ + const responseList: AList = new AList(); + for (let r: number = 0; r < ranges.size(); r++) { + /* Create the response for the next range */ + const range: FileRange = ranges.get(r); + const rangeExtent: ALong = range.offset.addInt(range.size); + const response: ABuffer = new ABuffer(range.size); + let responseOffset: int32 = 0; + this._requestCount++; + this._requestSize += range.size; + /* Scan the needed pages */ + const page0: int32 = range.offset.divInt(this._pageSize).toInt(); + const page1: int32 = range.offset.addInt(range.size - 1).divInt(this._pageSize).toInt() + 1; // exclusive + for (let i: number = page0; i < page1; i++) { + /* Get the next page from the cache */ + const pageKey: string = `${i}`; + const page: ABuffer = pageMap.get(pageKey); + ASystem.assertNot(page == null, `Missing cache page ${pageKey}`); + /* Get the extent of the page */ + const pageOffset0: ALong = ALong.fromInt(this._pageSize).mulInt(i); + const pageOffset1: ALong = ALong.min(pageOffset0.addInt(this._pageSize), this._fileSize); + /* Copy the overlapping part of the page to the response */ + const currentOffset: ALong = range.offset.addInt(responseOffset); + const copyOffset: int32 = currentOffset.sub(pageOffset0).toInt(); + const copySize: int32 = ALong.min(pageOffset1, rangeExtent).sub(currentOffset).toInt(); + ABuffer.arrayCopy(page, copyOffset, response, responseOffset, copySize); + responseOffset += copySize; + } + /* Add the response to the list */ + ASystem.assertNot(responseOffset != range.size, `Expected ${range.size} response size, not ${responseOffset}`); + responseList.add(new FileContent(range.offset, response)); + } + return responseList; + } - /** - * FileStorage method. - */ - public override async readFilePart(fileName: string, offset: ALong, size: int32): Promise { - const ranges: AList = new AList(); - ranges.add(new FileRange(offset, size)); - const reponses: AList = await this.readFileParts(fileName, ranges); - const reponse: FileContent = reponses.get(0); - return reponse.content; - } + /** + * FileStorage method. + */ + public override async readFilePart(fileName: string, offset: ALong, size: int32): Promise { + const ranges: AList = new AList(); + ranges.add(new FileRange(offset, size)); + const reponses: AList = await this.readFileParts(fileName, ranges); + const reponse: FileContent = reponses.get(0); + return reponse.content; + } - /** - * FileStorage method. - */ - public override printStatistics(clear: boolean): void { - Message.log(`Page cache of file '${this._fileName}':`); - Message.log(`Request count is ${this._requestCount}`); - Message.log(`Request size is ${this._requestSize}`); - Message.log(`Cache hit count is ${this._contentCache.hitCount}`); - Message.log(`Cache miss count is ${this._contentCache.missCount}`); - if (clear) this._contentCache.hitCount = 0; - if (clear) this._contentCache.missCount = 0; - this._fileStorage.printStatistics(clear); - } + /** + * FileStorage method. + */ + public override printStatistics(clear: boolean): void { + Message.log(`Page cache of file '${this._fileName}':`); + Message.log(`Request count is ${this._requestCount}`); + Message.log(`Request size is ${this._requestSize}`); + Message.log(`Cache hit count is ${this._contentCache.hitCount}`); + Message.log(`Cache miss count is ${this._contentCache.missCount}`); + if (clear) this._contentCache.hitCount = 0; + if (clear) this._contentCache.missCount = 0; + this._fileStorage.printStatistics(clear); + } } diff --git a/core/orbitgt/src/system/storage/UrlFS.ts b/core/orbitgt/src/system/storage/UrlFS.ts index 697c4b3d4d13..36b9c064b9c7 100644 --- a/core/orbitgt/src/system/storage/UrlFS.ts +++ b/core/orbitgt/src/system/storage/UrlFS.ts @@ -27,105 +27,112 @@ import { FileStorage } from "./FileStorage"; */ /** @internal */ export class UrlFS extends FileStorage { - // the downloader to the file - private _downloader: Downloader; + // the downloader to the file + private _downloader: Downloader; - // the number of requests that have been made to access the content of the file - public requestCount: number; - // the number of content bytes downloaded - public responseSize: number; + // the number of requests that have been made to access the content of the file + public requestCount: number; + // the number of content bytes downloaded + public responseSize: number; - /** - * Create the URL to access a blob file in an Azure storage account. - * @param accountName the name of the Azure storage account. - * @param containerName the name of the container that stores the blob file. - * @param blobName the name of the blob (should start with a forward slash). - * @param sasToken the SAS (shared access signature) of the blob or container (the part after the '?' character of the URL). - * @return the URL. - */ - public static getAzureBlobSasUrl(accountName: string, containerName: string, blobName: string, sasToken: string): string { - let blobURL: string = `https://${accountName}.blob.core.windows.net/${containerName}${blobName}`; - if (sasToken != null) blobURL += `?${sasToken}`; - return blobURL; - } + /** + * Create the URL to access a blob file in an Azure storage account. + * @param accountName the name of the Azure storage account. + * @param containerName the name of the container that stores the blob file. + * @param blobName the name of the blob (should start with a forward slash). + * @param sasToken the SAS (shared access signature) of the blob or container (the part after the '?' character of the URL). + * @return the URL. + */ + public static getAzureBlobSasUrl(accountName: string, containerName: string, blobName: string, sasToken: string): string { + let blobURL: string = `https://${accountName}.blob.core.windows.net/${containerName}${blobName}`; + if (sasToken != null) blobURL += `?${sasToken}`; + return blobURL; + } - /** - * Create a new instance. - */ - public constructor() { - super(); - this._downloader = Downloader.INSTANCE; - this.requestCount = 0; - this.responseSize = 0; - } + /** + * Create a new instance. + */ + public constructor() { + super(); + this._downloader = Downloader.INSTANCE; + this.requestCount = 0; + this.responseSize = 0; + } - /** - * FileStorage method. - */ - public override close(): void { - } + /** + * FileStorage method. + */ + public override close(): void { + } - /** - * FileStorage method. - */ - public override async getFileLength(url: string): Promise { - const requestHeaders: StringMap = null; - const responseHeaders: StringMap = new StringMap(); - await this._downloader.downloadBytes("HEAD"/* method*/, url, requestHeaders, null/* postText*/, null/* postData*/, responseHeaders); - const fileLength: number = parseInt(responseHeaders.get("content-length")); - return ALong.fromDouble(fileLength); - } + /** + * FileStorage method. + */ + public override async getFileLength(url: string): Promise { + const requestHeaders: StringMap = null; + const responseHeaders: StringMap = new StringMap(); + await this._downloader.downloadBytes("HEAD", /* method*/ url, requestHeaders, null, /* postText*/ null, /* postData*/ responseHeaders); + const fileLength: number = parseInt(responseHeaders.get("content-length")); + return ALong.fromDouble(fileLength); + } - /** - * FileStorage method. - */ - public override async readFilePart(url: string, offset: ALong, size: int32): Promise { - const extent: ALong = offset.addInt(size - 1); - const range: string = `bytes=${offset.toString()}-${extent.toString()}`; - const requestHeaders: StringMap = new StringMap(); - requestHeaders.set("Range", range); - // requestHeaders.set("x-ms-range",range); // https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-the-range-header-for-file-service-operations - const responseHeaders: StringMap = new StringMap(); - const content: ABuffer = await this._downloader.downloadBytes("GET"/* method*/, url, requestHeaders, null/* postText*/, null/* postData*/, responseHeaders); - const contentLength: number = parseInt(responseHeaders.get("content-length")); - ASystem.assertNot(contentLength != size, `Expected ${size} bytes of content, not ${contentLength}`); - ASystem.assertNot(content.size() != size, `Expected content buffer size ${size}, not ${content}`); - this.requestCount++; - this.responseSize += size; - return content; - } + /** + * FileStorage method. + */ + public override async readFilePart(url: string, offset: ALong, size: int32): Promise { + const extent: ALong = offset.addInt(size - 1); + const range: string = `bytes=${offset.toString()}-${extent.toString()}`; + const requestHeaders: StringMap = new StringMap(); + requestHeaders.set("Range", range); + // requestHeaders.set("x-ms-range",range); // https://docs.microsoft.com/en-us/rest/api/storageservices/specifying-the-range-header-for-file-service-operations + const responseHeaders: StringMap = new StringMap(); + const content: ABuffer = await this._downloader.downloadBytes( + "GET", /* method*/ + url, + requestHeaders, + null, /* postText*/ + null, /* postData*/ + responseHeaders, + ); + const contentLength: number = parseInt(responseHeaders.get("content-length")); + ASystem.assertNot(contentLength != size, `Expected ${size} bytes of content, not ${contentLength}`); + ASystem.assertNot(content.size() != size, `Expected content buffer size ${size}, not ${content}`); + this.requestCount++; + this.responseSize += size; + return content; + } - /** - * FileStorage method. - */ - public override async readFileParts(url: string, ranges: AList): Promise> { - /* Request all file parts in parallel */ - const contentFetchers: Array> = []; - for (let i: number = 0; i < ranges.size(); i++) { - const range: FileRange = ranges.get(i); - const contentFetcher: Promise = this.readFilePart(url, range.offset, range.size); - contentFetchers.push(contentFetcher); - } - /* Await all requests at once */ - const contentResponses: Array = await Promise.all(contentFetchers); - /* Create the result list */ - const contentParts: AList = new AList(); - for (let i: number = 0; i < ranges.size(); i++) { - const range: FileRange = ranges.get(i); - const contentResponse: ABuffer = contentResponses[i]; - contentParts.add(new FileContent(range.offset, contentResponse)); - } - return contentParts; + /** + * FileStorage method. + */ + public override async readFileParts(url: string, ranges: AList): Promise> { + /* Request all file parts in parallel */ + const contentFetchers: Array> = []; + for (let i: number = 0; i < ranges.size(); i++) { + const range: FileRange = ranges.get(i); + const contentFetcher: Promise = this.readFilePart(url, range.offset, range.size); + contentFetchers.push(contentFetcher); } - - /** - * FileStorage method. - */ - public override printStatistics(clear: boolean): void { - console.log("File url access statistics:"); - console.log(`Request count ${this.requestCount}`); - console.log(`Response size ${this.responseSize}`); - if (clear) this.requestCount = 0; - if (clear) this.responseSize = 0; + /* Await all requests at once */ + const contentResponses: Array = await Promise.all(contentFetchers); + /* Create the result list */ + const contentParts: AList = new AList(); + for (let i: number = 0; i < ranges.size(); i++) { + const range: FileRange = ranges.get(i); + const contentResponse: ABuffer = contentResponses[i]; + contentParts.add(new FileContent(range.offset, contentResponse)); } + return contentParts; + } + + /** + * FileStorage method. + */ + public override printStatistics(clear: boolean): void { + console.log("File url access statistics:"); + console.log(`Request count ${this.requestCount}`); + console.log(`Response size ${this.responseSize}`); + if (clear) this.requestCount = 0; + if (clear) this.responseSize = 0; + } } diff --git a/core/orbitgt/src/test/CrsEngine.test.ts b/core/orbitgt/src/test/CrsEngine.test.ts index 35c4409a4688..725dbf57c851 100644 --- a/core/orbitgt/src/test/CrsEngine.test.ts +++ b/core/orbitgt/src/test/CrsEngine.test.ts @@ -11,7 +11,6 @@ import { Downloader } from "../system/runtime/Downloader"; import { DownloaderNode } from "../system/runtime/DownloaderNode"; describe("CRS engine tests", () => { - it("crs transform of a position", async () => { Downloader.INSTANCE = new DownloaderNode(); CRSManager.ENGINE = await OnlineEngine.create(); @@ -24,5 +23,4 @@ describe("CRS engine tests", () => { const expectedPosition: Coordinate = new Coordinate(4004726.217, 280783.407, 4939653.828); assert.isTrue(targetPosition.distance3D(expectedPosition) < 0.25, "found position " + targetPosition + ", expected " + expectedPosition); }); - }); diff --git a/core/orbitgt/src/test/OpcReader.test.ts b/core/orbitgt/src/test/OpcReader.test.ts index 723fd7448c52..dd5c7c8a7132 100644 --- a/core/orbitgt/src/test/OpcReader.test.ts +++ b/core/orbitgt/src/test/OpcReader.test.ts @@ -10,11 +10,10 @@ import { ALong } from "../system/runtime/ALong"; import { NodeFS } from "../system/storage/NodeFS"; describe("OPC reader tests", () => { - it("should open a point cloud file", async () => { let opcFileName: string = path.join(__dirname, "assets", "pointcloud.opc"); let nodeFS: NodeFS = new NodeFS(); - let fileReader: PointCloudReader = await OPCReader.openFile(nodeFS, opcFileName, true/*lazyLoading*/); + let fileReader: PointCloudReader = await OPCReader.openFile(nodeFS, opcFileName, true /*lazyLoading*/); let levelCount: number = fileReader.getLevelCount(); let pointCount: ALong = fileReader.getLevelPointCount(0); fileReader.close(); @@ -23,5 +22,4 @@ describe("OPC reader tests", () => { assert.isTrue(levelCount == expectedLevelCount, "found " + levelCount + " levels, expected " + expectedLevelCount); assert.isTrue(pointCount.same(expectedPointCount), "found " + pointCount + " points, expected " + expectedPointCount); }); - }); diff --git a/core/quantity/eslint.config.js b/core/quantity/eslint.config.js index 628f1d4b27a0..849e7479dee5 100644 --- a/core/quantity/eslint.config.js +++ b/core/quantity/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/core/quantity/src/Formatter/Format.ts b/core/quantity/src/Formatter/Format.ts index 183732dc22d7..b8f238c9d3ae 100644 --- a/core/quantity/src/Formatter/Format.ts +++ b/core/quantity/src/Formatter/Format.ts @@ -10,10 +10,24 @@ import { QuantityConstants } from "../Constants"; import { QuantityError, QuantityStatus } from "../Exception"; import { UnitProps, UnitsProvider } from "../Interfaces"; import { - DecimalPrecision, FormatTraits, formatTraitsToArray, FormatType, formatTypeToString, FractionalPrecision, - getTraitString, parseFormatTrait, parseFormatType, parsePrecision, parseRatioType, parseScientificType, parseShowSignOption, - RatioType, ScientificType, scientificTypeToString, - ShowSignOption, showSignOptionToString, + DecimalPrecision, + FormatTraits, + formatTraitsToArray, + FormatType, + formatTypeToString, + FractionalPrecision, + getTraitString, + parseFormatTrait, + parseFormatType, + parsePrecision, + parseRatioType, + parseScientificType, + parseShowSignOption, + RatioType, + ScientificType, + scientificTypeToString, + ShowSignOption, + showSignOptionToString, } from "./FormatEnums"; import { CloneOptions, CustomFormatProps, FormatProps, isCustomFormatProps } from "./Interfaces"; @@ -50,70 +64,156 @@ export class BaseFormat { this._name = name; } - public get name(): string { return this._name; } + public get name(): string { + return this._name; + } - public get roundFactor(): number { return this._roundFactor; } - public set roundFactor(roundFactor: number) { this._roundFactor = roundFactor; } + public get roundFactor(): number { + return this._roundFactor; + } + public set roundFactor(roundFactor: number) { + this._roundFactor = roundFactor; + } - public get type(): FormatType { return this._type; } - public set type(formatType: FormatType) { this._type = formatType; } + public get type(): FormatType { + return this._type; + } + public set type(formatType: FormatType) { + this._type = formatType; + } - public get precision(): DecimalPrecision | FractionalPrecision { return this._precision; } - public set precision(precision: DecimalPrecision | FractionalPrecision) { this._precision = precision; } + public get precision(): DecimalPrecision | FractionalPrecision { + return this._precision; + } + public set precision(precision: DecimalPrecision | FractionalPrecision) { + this._precision = precision; + } - public get minWidth(): number | undefined { return this._minWidth; } - public set minWidth(minWidth: number | undefined) { this._minWidth = minWidth; } + public get minWidth(): number | undefined { + return this._minWidth; + } + public set minWidth(minWidth: number | undefined) { + this._minWidth = minWidth; + } - public get scientificType(): ScientificType | undefined { return this._scientificType; } - public set scientificType(scientificType: ScientificType | undefined) { this._scientificType = scientificType; } + public get scientificType(): ScientificType | undefined { + return this._scientificType; + } + public set scientificType(scientificType: ScientificType | undefined) { + this._scientificType = scientificType; + } - public get ratioType(): RatioType | undefined { return this._ratioType; } - public set ratioType(ratioType: RatioType | undefined) { this._ratioType = ratioType; } + public get ratioType(): RatioType | undefined { + return this._ratioType; + } + public set ratioType(ratioType: RatioType | undefined) { + this._ratioType = ratioType; + } - public get showSignOption(): ShowSignOption { return this._showSignOption; } - public set showSignOption(showSignOption: ShowSignOption) { this._showSignOption = showSignOption; } + public get showSignOption(): ShowSignOption { + return this._showSignOption; + } + public set showSignOption(showSignOption: ShowSignOption) { + this._showSignOption = showSignOption; + } - public get decimalSeparator(): string { return this._decimalSeparator; } - public set decimalSeparator(decimalSeparator: string) { this._decimalSeparator = decimalSeparator; } + public get decimalSeparator(): string { + return this._decimalSeparator; + } + public set decimalSeparator(decimalSeparator: string) { + this._decimalSeparator = decimalSeparator; + } - public get thousandSeparator(): string { return this._thousandSeparator; } - public set thousandSeparator(thousandSeparator: string) { this._thousandSeparator = thousandSeparator; } + public get thousandSeparator(): string { + return this._thousandSeparator; + } + public set thousandSeparator(thousandSeparator: string) { + this._thousandSeparator = thousandSeparator; + } - public get uomSeparator(): string { return this._uomSeparator; } - public set uomSeparator(uomSeparator: string) { this._uomSeparator = uomSeparator; } + public get uomSeparator(): string { + return this._uomSeparator; + } + public set uomSeparator(uomSeparator: string) { + this._uomSeparator = uomSeparator; + } - public get stationSeparator(): string { return this._stationSeparator; } - public set stationSeparator(stationSeparator: string) { this._stationSeparator = stationSeparator; } + public get stationSeparator(): string { + return this._stationSeparator; + } + public set stationSeparator(stationSeparator: string) { + this._stationSeparator = stationSeparator; + } - public get stationOffsetSize(): number | undefined { return this._stationOffsetSize; } - public set stationOffsetSize(stationOffsetSize: number | undefined) { stationOffsetSize = this._stationOffsetSize = stationOffsetSize; } + public get stationOffsetSize(): number | undefined { + return this._stationOffsetSize; + } + public set stationOffsetSize(stationOffsetSize: number | undefined) { + stationOffsetSize = this._stationOffsetSize = stationOffsetSize; + } - public get allowMathematicOperations(): boolean { return this._allowMathematicOperations; } - public set allowMathematicOperations(allowMathematicOperations: boolean) { this._allowMathematicOperations = allowMathematicOperations; } + public get allowMathematicOperations(): boolean { + return this._allowMathematicOperations; + } + public set allowMathematicOperations(allowMathematicOperations: boolean) { + this._allowMathematicOperations = allowMathematicOperations; + } - public get formatTraits(): FormatTraits { return this._formatTraits; } - public set formatTraits(formatTraits: FormatTraits) { this._formatTraits = formatTraits; } + public get formatTraits(): FormatTraits { + return this._formatTraits; + } + public set formatTraits(formatTraits: FormatTraits) { + this._formatTraits = formatTraits; + } - public get spacer(): string | undefined { return this._spacer; } - public set spacer(spacer: string | undefined) { this._spacer = spacer ?? this._spacer; } - public get spacerOrDefault(): string { return this._spacer ?? " "; } + public get spacer(): string | undefined { + return this._spacer; + } + public set spacer(spacer: string | undefined) { + this._spacer = spacer ?? this._spacer; + } + public get spacerOrDefault(): string { + return this._spacer ?? " "; + } - public get includeZero(): boolean | undefined { return this._includeZero; } - public set includeZero(includeZero: boolean | undefined) { this._includeZero = includeZero ?? this._includeZero; } + public get includeZero(): boolean | undefined { + return this._includeZero; + } + public set includeZero(includeZero: boolean | undefined) { + this._includeZero = includeZero ?? this._includeZero; + } // default "north" is applied by the formatter (quarter rotation counter clockwise from east, the value depends on the units used) - public get azimuthBase(): number | undefined { return this._azimuthBase; } - public set azimuthBase(azimuthBase: number | undefined) { this._azimuthBase = azimuthBase; } + public get azimuthBase(): number | undefined { + return this._azimuthBase; + } + public set azimuthBase(azimuthBase: number | undefined) { + this._azimuthBase = azimuthBase; + } - public get azimuthBaseUnit(): UnitProps | undefined { return this._azimuthBaseUnit; } - public set azimuthBaseUnit(azimuthBaseUnit: UnitProps | undefined) { this._azimuthBaseUnit = azimuthBaseUnit; } + public get azimuthBaseUnit(): UnitProps | undefined { + return this._azimuthBaseUnit; + } + public set azimuthBaseUnit(azimuthBaseUnit: UnitProps | undefined) { + this._azimuthBaseUnit = azimuthBaseUnit; + } - public get azimuthCounterClockwise(): boolean | undefined { return this._azimuthCounterClockwise; } - public set azimuthCounterClockwise(azimuthCounterClockwise: boolean | undefined) { this._azimuthCounterClockwise = azimuthCounterClockwise; } - public get azimuthClockwiseOrDefault(): boolean { return !this._azimuthCounterClockwise; } + public get azimuthCounterClockwise(): boolean | undefined { + return this._azimuthCounterClockwise; + } + public set azimuthCounterClockwise(azimuthCounterClockwise: boolean | undefined) { + this._azimuthCounterClockwise = azimuthCounterClockwise; + } + public get azimuthClockwiseOrDefault(): boolean { + return !this._azimuthCounterClockwise; + } - public get revolutionUnit(): UnitProps | undefined { return this._revolutionUnit; } - public set revolutionUnit(revolutionUnit: UnitProps | undefined) { this._revolutionUnit = revolutionUnit; } + public get revolutionUnit(): UnitProps | undefined { + return this._revolutionUnit; + } + public set revolutionUnit(revolutionUnit: UnitProps | undefined) { + this._revolutionUnit = revolutionUnit; + } /** This method parses input string that is typically extracted for persisted JSON data and validates that the string is a valid FormatType. Throws exception if not valid. */ public parseFormatTraits(formatTraitsFromJson: string | string[]) { @@ -140,35 +240,53 @@ export class BaseFormat { } if (this.type === FormatType.Scientific) { if (undefined === formatProps.scientificType) // if format type is scientific and scientific type is undefined, throw - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} is 'Scientific' type therefore the attribute 'scientificType' is required.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} is 'Scientific' type therefore the attribute 'scientificType' is required.`, + ); this._scientificType = parseScientificType(formatProps.scientificType, this.name); } - if (this.type === FormatType.Ratio){ + if (this.type === FormatType.Ratio) { if (undefined === formatProps.ratioType) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} is 'Ratio' type therefore the attribute 'ratioType' is required.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} is 'Ratio' type therefore the attribute 'ratioType' is required.`, + ); this._ratioType = parseRatioType(formatProps.ratioType, this.name); } if (undefined !== formatProps.roundFactor) { // optional; default is 0.0 if (typeof (formatProps.roundFactor) !== "number") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'roundFactor' attribute. It should be of type 'number'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'roundFactor' attribute. It should be of type 'number'.`, + ); if (formatProps.roundFactor !== this.roundFactor) // if roundFactor isn't default value of 0.0, reassign roundFactor variable this._roundFactor = formatProps.roundFactor; } if (undefined !== formatProps.minWidth) { // optional if (!Number.isInteger(formatProps.minWidth) || formatProps.minWidth < 0) // must be a positive int - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'minWidth' attribute. It should be a positive integer.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); this._minWidth = formatProps.minWidth; } if (FormatType.Station === this.type) { if (undefined === formatProps.stationOffsetSize) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} is 'Station' type therefore the attribute 'stationOffsetSize' is required.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} is 'Station' type therefore the attribute 'stationOffsetSize' is required.`, + ); if (!Number.isInteger(formatProps.stationOffsetSize) || formatProps.stationOffsetSize < 0) // must be a positive int > 0 - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationOffsetSize' attribute. It should be a positive integer.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'stationOffsetSize' attribute. It should be a positive integer.`, + ); this._stationOffsetSize = formatProps.stationOffsetSize; } @@ -178,56 +296,92 @@ export class BaseFormat { if (undefined !== formatProps.formatTraits && formatProps.formatTraits.length !== 0) { // FormatTraits is optional if (!Array.isArray(formatProps.formatTraits) && typeof (formatProps.formatTraits) !== "string") // must be either an array of strings or a string - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'formatTraits' attribute. It should be of type 'string' or 'string[]'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'formatTraits' attribute. It should be of type 'string' or 'string[]'.`, + ); this.parseFormatTraits(formatProps.formatTraits); // check that all of the options for formatTraits are valid. If now, throw } if (undefined !== formatProps.decimalSeparator) { // optional if (typeof (formatProps.decimalSeparator) !== "string") // not a string or not a one character string - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It should be of type 'string'.`, + ); if (formatProps.decimalSeparator.length > 1) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`, + ); this._decimalSeparator = formatProps.decimalSeparator; } if (undefined !== formatProps.thousandSeparator) { // optional if (typeof (formatProps.thousandSeparator) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It should be of type 'string'.`, + ); if (formatProps.thousandSeparator.length > 1) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`, + ); this._thousandSeparator = formatProps.thousandSeparator; } if (undefined !== formatProps.uomSeparator) { // optional; default is " " if (typeof (formatProps.uomSeparator) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'uomSeparator' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'uomSeparator' attribute. It should be of type 'string'.`, + ); if (formatProps.uomSeparator.length < 0 || formatProps.uomSeparator.length > 1) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`, + ); this._uomSeparator = formatProps.uomSeparator; } if (undefined !== formatProps.stationSeparator) { // optional; default is "+" if (typeof (formatProps.stationSeparator) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationSeparator' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'stationSeparator' attribute. It should be of type 'string'.`, + ); if (formatProps.stationSeparator.length > 1) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`, + ); this._stationSeparator = formatProps.stationSeparator; } if (undefined !== formatProps.azimuthBase) { // optional; default is a quarter rotation (90 degrees) which represents north if (typeof (formatProps.azimuthBase) !== "number") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'azimuthBase' attribute. It should be of type 'number'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'azimuthBase' attribute. It should be of type 'number'.`, + ); this._azimuthBase = formatProps.azimuthBase; } if (undefined !== formatProps.azimuthCounterClockwise) { // optional; default is false if (typeof (formatProps.azimuthCounterClockwise) !== "boolean") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'azimuthCounterClockwise' attribute. It should be of type 'boolean'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'azimuthCounterClockwise' attribute. It should be of type 'boolean'.`, + ); this._azimuthCounterClockwise = formatProps.azimuthCounterClockwise; } if (undefined !== formatProps.allowMathematicOperations) { // optional; default is false if (typeof (formatProps.allowMathematicOperations) !== "boolean") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'allowMathematicOperations' attribute. It should be of type 'boolean'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'allowMathematicOperations' attribute. It should be of type 'boolean'.`, + ); this._allowMathematicOperations = formatProps.allowMathematicOperations; } } @@ -238,7 +392,7 @@ export class BaseFormat { */ export class Format extends BaseFormat { protected _units?: Array<[UnitProps, string | undefined]>; - protected _customProps?: any; // used by custom formatters and parsers + protected _customProps?: any; // used by custom formatters and parsers /** Constructor * @param name The name of a format specification. TODO: make optional or remove @@ -247,9 +401,15 @@ export class Format extends BaseFormat { super(name); } - public get units(): Array<[UnitProps, string | undefined]> | undefined { return this._units; } - public get hasUnits(): boolean { return this._units !== undefined && this._units.length > 0; } - public get customProps(): any { return this._customProps; } + public get units(): Array<[UnitProps, string | undefined]> | undefined { + return this._units; + } + public get hasUnits(): boolean { + return this._units !== undefined && this._units.length > 0; + } + public get customProps(): any { + return this._customProps; + } public static isFormatTraitSetInProps(formatProps: FormatProps, trait: FormatTraits) { if (!formatProps.formatTraits) @@ -260,7 +420,7 @@ export class Format extends BaseFormat { } private async createUnit(unitsProvider: UnitsProvider, name: string, label?: string): Promise { - if (name === undefined || typeof (name) !== "string" || (label !== undefined && typeof (label) !== "string")) // throws if name is undefined or name isn't a string or if label is defined and isn't a string + if (name === undefined || typeof name !== "string" || (label !== undefined && typeof label !== "string")) // throws if name is undefined or name isn't a string or if label is defined and isn't a string throw new QuantityError(QuantityStatus.InvalidJson, `This Composite has a unit with an invalid 'name' or 'label' attribute.`); for (const unit of this.units!) { const unitObj = unit[0].name; @@ -345,19 +505,31 @@ export class Format extends BaseFormat { this._units = new Array<[UnitProps, string | undefined]>(); if (jsonObj.composite.includeZero !== undefined) { if (typeof (jsonObj.composite.includeZero) !== "boolean") // includeZero must be a boolean IF it is defined - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'includeZero' attribute. It should be of type 'boolean'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has a Composite with an invalid 'includeZero' attribute. It should be of type 'boolean'.`, + ); this._includeZero = jsonObj.composite.includeZero; } - if (jsonObj.composite.spacer !== undefined) { // spacer must be a string IF it is defined + if (jsonObj.composite.spacer !== undefined) { // spacer must be a string IF it is defined if (typeof (jsonObj.composite.spacer) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It must be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It must be of type 'string'.`, + ); if (jsonObj.composite.spacer.length > 1) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It should be an empty or one character string.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has a Composite with an invalid 'spacer' attribute. It should be an empty or one character string.`, + ); this._spacer = jsonObj.composite.spacer; } if (jsonObj.composite.units !== undefined) { // if composite is defined, it must be an array with 1-4 units if (!Array.isArray(jsonObj.composite.units)) { // must be an array - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with an invalid 'units' attribute. It must be of type 'array'`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has a Composite with an invalid 'units' attribute. It must be of type 'array'`, + ); } if (jsonObj.composite.units.length > 0 && jsonObj.composite.units.length <= 4) { // Composite requires 1-4 units try { @@ -376,35 +548,53 @@ export class Format extends BaseFormat { throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has a Composite with no valid 'units'`); } - if(this.type === FormatType.Azimuth || this.type === FormatType.Bearing) { + if (this.type === FormatType.Azimuth || this.type === FormatType.Bearing) { // these units cannot be loaded from loadFormatProperties() because they require an async call, and the method signature is already public if (undefined !== jsonObj.azimuthBaseUnit) { if (typeof (jsonObj.azimuthBaseUnit) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'azimuthBaseUnit' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'azimuthBaseUnit' attribute. It should be of type 'string'.`, + ); const baseUnit: UnitProps = await unitsProvider.findUnitByName(jsonObj.azimuthBaseUnit); if (!baseUnit || !baseUnit.isValid) - throw new QuantityError(QuantityStatus.InvalidJson, `Invalid unit name '${jsonObj.azimuthBaseUnit}' for azimuthBaseUnit in Format '${this.name}'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `Invalid unit name '${jsonObj.azimuthBaseUnit}' for azimuthBaseUnit in Format '${this.name}'.`, + ); this._azimuthBaseUnit = baseUnit; } if (undefined !== jsonObj.revolutionUnit) { if (typeof (jsonObj.revolutionUnit) !== "string") - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an invalid 'revolutionUnit' attribute. It should be of type 'string'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an invalid 'revolutionUnit' attribute. It should be of type 'string'.`, + ); const revolutionUnit: UnitProps = await unitsProvider.findUnitByName(jsonObj.revolutionUnit); if (!revolutionUnit || !revolutionUnit.isValid) - throw new QuantityError(QuantityStatus.InvalidJson, `Invalid unit name '${jsonObj.revolutionUnit}' for revolutionUnit in Format '${this.name}'.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `Invalid unit name '${jsonObj.revolutionUnit}' for revolutionUnit in Format '${this.name}'.`, + ); this._revolutionUnit = revolutionUnit; } if (this._revolutionUnit === undefined) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} is 'Azimuth' or 'Bearing' type therefore the attribute 'revolutionUnit' is required.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} is 'Azimuth' or 'Bearing' type therefore the attribute 'revolutionUnit' is required.`, + ); if (this._azimuthBase !== undefined && this._azimuthBaseUnit === undefined) - throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${this.name} has an 'azimuthBase' attribute therefore the attribute 'azimuthBaseUnit' is required.`); + throw new QuantityError( + QuantityStatus.InvalidJson, + `The Format ${this.name} has an 'azimuthBase' attribute therefore the attribute 'azimuthBaseUnit' is required.`, + ); } } diff --git a/core/quantity/src/Formatter/FormatEnums.ts b/core/quantity/src/Formatter/FormatEnums.ts index 6fffb8789821..e363f6f48dd5 100644 --- a/core/quantity/src/Formatter/FormatEnums.ts +++ b/core/quantity/src/Formatter/FormatEnums.ts @@ -25,7 +25,8 @@ import { QuantityError, QuantityStatus } from "../Exception"; * - Grabs the unit name, `|` and label separately * @internal */ -export const formatStringRgx = /([\w.:]+)(\(([^\)]+)\))?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?/; +export const formatStringRgx = + /([\w.:]+)(\(([^\)]+)\))?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?(\[([^\|\]]+)([\|])?([^\]]+)?\])?/; /** @internal */ export function* getItemNamesFromFormatString(formatString: string): Iterable { @@ -157,8 +158,10 @@ export enum ShowSignOption { export function parseScientificType(scientificType: string, formatName: string): ScientificType { switch (scientificType.toLowerCase()) { - case "normalized": return ScientificType.Normalized; - case "zeronormalized": return ScientificType.ZeroNormalized; + case "normalized": + return ScientificType.Normalized; + case "zeronormalized": + return ScientificType.ZeroNormalized; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'scientificType' attribute.`); } @@ -186,10 +189,14 @@ export function parseRatioType(ratioType: string, formatName: string): RatioType /** @beta */ export function parseShowSignOption(showSignOption: string, formatName: string): ShowSignOption { switch (showSignOption.toLowerCase()) { - case "nosign": return ShowSignOption.NoSign; - case "onlynegative": return ShowSignOption.OnlyNegative; - case "signalways": return ShowSignOption.SignAlways; - case "negativeparentheses": return ShowSignOption.NegativeParentheses; + case "nosign": + return ShowSignOption.NoSign; + case "onlynegative": + return ShowSignOption.OnlyNegative; + case "signalways": + return ShowSignOption.SignAlways; + case "negativeparentheses": + return ShowSignOption.NegativeParentheses; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'showSignOption' attribute.`); } @@ -198,26 +205,40 @@ export function parseShowSignOption(showSignOption: string, formatName: string): /** @beta */ export function showSignOptionToString(showSign: ShowSignOption): string { switch (showSign) { - case ShowSignOption.NegativeParentheses: return "NegativeParentheses"; - case ShowSignOption.NoSign: return "NoSign"; - case ShowSignOption.OnlyNegative: return "OnlyNegative"; - case ShowSignOption.SignAlways: return "SignAlways"; + case ShowSignOption.NegativeParentheses: + return "NegativeParentheses"; + case ShowSignOption.NoSign: + return "NoSign"; + case ShowSignOption.OnlyNegative: + return "OnlyNegative"; + case ShowSignOption.SignAlways: + return "SignAlways"; } } /** @beta */ export function parseFormatTrait(formatTraitsString: string, formatName: string): FormatTraits { switch (formatTraitsString.toLowerCase()) { - case "trailzeroes": return FormatTraits.TrailZeroes; - case "keepsinglezero": return FormatTraits.KeepSingleZero; - case "zeroempty": return FormatTraits.ZeroEmpty; - case "keepdecimalpoint": return FormatTraits.KeepDecimalPoint; - case "applyrounding": return FormatTraits.ApplyRounding; - case "fractiondash": return FormatTraits.FractionDash; - case "showunitlabel": return FormatTraits.ShowUnitLabel; - case "prependunitlabel": return FormatTraits.PrependUnitLabel; - case "use1000separator": return FormatTraits.Use1000Separator; - case "exponentonlynegative": return FormatTraits.ExponentOnlyNegative; + case "trailzeroes": + return FormatTraits.TrailZeroes; + case "keepsinglezero": + return FormatTraits.KeepSingleZero; + case "zeroempty": + return FormatTraits.ZeroEmpty; + case "keepdecimalpoint": + return FormatTraits.KeepDecimalPoint; + case "applyrounding": + return FormatTraits.ApplyRounding; + case "fractiondash": + return FormatTraits.FractionDash; + case "showunitlabel": + return FormatTraits.ShowUnitLabel; + case "prependunitlabel": + return FormatTraits.PrependUnitLabel; + case "use1000separator": + return FormatTraits.Use1000Separator; + case "exponentonlynegative": + return FormatTraits.ExponentOnlyNegative; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'formatTraits' attribute.`); } @@ -279,13 +300,20 @@ export function formatTraitsToArray(currentFormatTrait: FormatTraits): string[] /** @beta */ export function parseFormatType(jsonObjType: string, formatName: string): FormatType { switch (jsonObjType.toLowerCase()) { - case "decimal": return FormatType.Decimal; - case "scientific": return FormatType.Scientific; - case "station": return FormatType.Station; - case "fractional": return FormatType.Fractional; - case "bearing": return FormatType.Bearing; - case "azimuth": return FormatType.Azimuth; - case "ratio": return FormatType.Ratio; + case "decimal": + return FormatType.Decimal; + case "scientific": + return FormatType.Scientific; + case "station": + return FormatType.Station; + case "fractional": + return FormatType.Fractional; + case "bearing": + return FormatType.Bearing; + case "azimuth": + return FormatType.Azimuth; + case "ratio": + return FormatType.Ratio; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'type' attribute.`); } @@ -294,32 +322,52 @@ export function parseFormatType(jsonObjType: string, formatName: string): Format /** @beta */ export function formatTypeToString(type: FormatType): string { switch (type) { - case FormatType.Decimal: return "Decimal"; - case FormatType.Scientific: return "Scientific"; - case FormatType.Station: return "Station"; - case FormatType.Fractional: return "Fractional"; - case FormatType.Bearing: return "Bearing"; - case FormatType.Azimuth: return "Azimuth"; - case FormatType.Ratio: return "Ratio"; + case FormatType.Decimal: + return "Decimal"; + case FormatType.Scientific: + return "Scientific"; + case FormatType.Station: + return "Station"; + case FormatType.Fractional: + return "Fractional"; + case FormatType.Bearing: + return "Bearing"; + case FormatType.Azimuth: + return "Azimuth"; + case FormatType.Ratio: + return "Ratio"; } } /** @beta */ export function parseDecimalPrecision(jsonObjPrecision: number, formatName: string): DecimalPrecision { switch (jsonObjPrecision) { - case 0: return DecimalPrecision.Zero; - case 1: return DecimalPrecision.One; - case 2: return DecimalPrecision.Two; - case 3: return DecimalPrecision.Three; - case 4: return DecimalPrecision.Four; - case 5: return DecimalPrecision.Five; - case 6: return DecimalPrecision.Six; - case 7: return DecimalPrecision.Seven; - case 8: return DecimalPrecision.Eight; - case 9: return DecimalPrecision.Nine; - case 10: return DecimalPrecision.Ten; - case 11: return DecimalPrecision.Eleven; - case 12: return DecimalPrecision.Twelve; + case 0: + return DecimalPrecision.Zero; + case 1: + return DecimalPrecision.One; + case 2: + return DecimalPrecision.Two; + case 3: + return DecimalPrecision.Three; + case 4: + return DecimalPrecision.Four; + case 5: + return DecimalPrecision.Five; + case 6: + return DecimalPrecision.Six; + case 7: + return DecimalPrecision.Seven; + case 8: + return DecimalPrecision.Eight; + case 9: + return DecimalPrecision.Nine; + case 10: + return DecimalPrecision.Ten; + case 11: + return DecimalPrecision.Eleven; + case 12: + return DecimalPrecision.Twelve; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'precision' attribute.`); } @@ -328,15 +376,24 @@ export function parseDecimalPrecision(jsonObjPrecision: number, formatName: stri /** @beta validates the input value, that is typically extracted for persisted JSON data, is a valid FractionalPrecision */ export function parseFractionalPrecision(jsonObjPrecision: number, formatName: string): FractionalPrecision { switch (jsonObjPrecision) { - case 1: return FractionalPrecision.One; - case 2: return FractionalPrecision.Two; - case 4: return FractionalPrecision.Four; - case 8: return FractionalPrecision.Eight; - case 16: return FractionalPrecision.Sixteen; - case 32: return FractionalPrecision.ThirtyTwo; - case 64: return FractionalPrecision.SixtyFour; - case 128: return FractionalPrecision.OneHundredTwentyEight; - case 256: return FractionalPrecision.TwoHundredFiftySix; + case 1: + return FractionalPrecision.One; + case 2: + return FractionalPrecision.Two; + case 4: + return FractionalPrecision.Four; + case 8: + return FractionalPrecision.Eight; + case 16: + return FractionalPrecision.Sixteen; + case 32: + return FractionalPrecision.ThirtyTwo; + case 64: + return FractionalPrecision.SixtyFour; + case 128: + return FractionalPrecision.OneHundredTwentyEight; + case 256: + return FractionalPrecision.TwoHundredFiftySix; default: throw new QuantityError(QuantityStatus.InvalidJson, `The Format ${formatName} has an invalid 'precision' attribute.`); } diff --git a/core/quantity/src/Formatter/Formatter.ts b/core/quantity/src/Formatter/Formatter.ts index b0a9a8045587..469084abfc3e 100644 --- a/core/quantity/src/Formatter/Formatter.ts +++ b/core/quantity/src/Formatter/Formatter.ts @@ -8,9 +8,9 @@ import { QuantityConstants } from "../Constants"; import { QuantityError, QuantityStatus } from "../Exception"; -import { FormatterSpec } from "./FormatterSpec"; -import { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision, RatioType, ScientificType, ShowSignOption } from "./FormatEnums"; import { applyConversion, Quantity } from "../Quantity"; +import { DecimalPrecision, FormatTraits, FormatType, FractionalPrecision, RatioType, ScientificType, ShowSignOption } from "./FormatEnums"; +import { FormatterSpec } from "./FormatterSpec"; /** rounding additive * @internal @@ -60,9 +60,15 @@ class FractionalNumeric { return (numerator < 0) ? -numerator : numerator; } - public get greatestCommonFactor(): number { return this._greatestCommonFactor; } - public get hasFractionPart(): boolean { return this._textParts.length > 0; } - public get isZero(): boolean { return 0 === this._numerator; } + public get greatestCommonFactor(): number { + return this._greatestCommonFactor; + } + public get hasFractionPart(): boolean { + return this._textParts.length > 0; + } + public get isZero(): boolean { + return 0 === this._numerator; + } public getIntegralString(): string { if (this._textParts.length > 0) @@ -109,7 +115,9 @@ export class Formatter { // eslint-disable-next-line @typescript-eslint/naming-convention private static FPV_MINTHRESHOLD = 1.0e-14; - private static isNegligible(value: number): boolean { return (Math.abs(value) < Formatter.FPV_MINTHRESHOLD); } + private static isNegligible(value: number): boolean { + return (Math.abs(value) < Formatter.FPV_MINTHRESHOLD); + } /** Return floating point value rounded by specific rounding factor. * @param value Value to be rounded. @@ -180,7 +188,7 @@ export class Formatter { let componentText = ""; if (!isLastPart) { componentText = Formatter.integerPartToText(compositeValue, spec); - if(spec.format.minWidth) { // integerPartToText does not do this padding + if (spec.format.minWidth) { // integerPartToText does not do this padding componentText = this.countAndPad(componentText, spec.format.minWidth); } } else { @@ -215,9 +223,12 @@ export class Formatter { throw new QuantityError(QuantityStatus.InvalidCompositeFormat, `The Format ${spec.format.name} has a invalid unit specification..`); let unitValue = 0.0; - if (spec.format.type === FormatType.Ratio){ + if (spec.format.type === FormatType.Ratio) { if (1 !== spec.format.units!.length) - throw new QuantityError(QuantityStatus.InvalidCompositeFormat, `The Format ${spec.format.name} has an invalid unit specification, we require single presentation unit when using format type 'ratio'`); + throw new QuantityError( + QuantityStatus.InvalidCompositeFormat, + `The Format ${spec.format.name} has an invalid unit specification, we require single presentation unit when using format type 'ratio'`, + ); try { unitValue = applyConversion(posMagnitude, unitConversion) + this.FPV_MINTHRESHOLD; @@ -236,7 +247,7 @@ export class Formatter { unitValue = applyConversion(posMagnitude, unitConversion) + this.FPV_MINTHRESHOLD; if (0 === i) { - const precisionScale = Math.pow(10, 8); // use a fixed round off precision of 8 to avoid loss of precision in actual magnitude + const precisionScale = Math.pow(10, 8); // use a fixed round off precision of 8 to avoid loss of precision in actual magnitude unitValue = Math.floor(unitValue * precisionScale + FPV_ROUNDFACTOR) / precisionScale; if ((Math.abs(unitValue) < 0.0001) && spec.format.hasFormatTraitSet(FormatTraits.ZeroEmpty)) return ""; @@ -267,9 +278,11 @@ export class Formatter { if (spec.format.hasFormatTraitSet(FormatTraits.ApplyRounding)) posMagnitude = Math.abs(Formatter.roundDouble(magnitude, spec.format.roundFactor)); - const isSci = ((posMagnitude > 1.0e12) || spec.format.type === FormatType.Scientific); - const isDecimal = (isSci || spec.format.type === FormatType.Decimal || spec.format.type === FormatType.Bearing || spec.format.type === FormatType.Azimuth) || spec.format.type === FormatType.Ratio; - const isFractional = (!isDecimal && spec.format.type === FormatType.Fractional); + const isSci = (posMagnitude > 1.0e12) || spec.format.type === FormatType.Scientific; + const isDecimal = + (isSci || spec.format.type === FormatType.Decimal || spec.format.type === FormatType.Bearing || spec.format.type === FormatType.Azimuth) || + spec.format.type === FormatType.Ratio; + const isFractional = !isDecimal && spec.format.type === FormatType.Fractional; /* const usesStops = spec.format.type === FormatType.Station; */ const isPrecisionZero = spec.format.precision === DecimalPrecision.Zero; const isKeepSingleZero = spec.format.hasFormatTraitSet(FormatTraits.KeepSingleZero); @@ -348,11 +361,11 @@ export class Formatter { const fractionString = `${fn.getNumeratorString()}/${fn.getDenominatorString()}`; formattedValue = formattedValue + wholeFractionSeparator + fractionString; } - } else /* if (usesStops)*/ { + } /* if (usesStops)*/ else { // we assume that stopping value is always positive posMagnitude = Math.floor(posMagnitude * precisionScale + FPV_ROUNDFACTOR) / precisionScale; - const denominator = (Math.pow(10, spec.format.stationOffsetSize!)); + const denominator = Math.pow(10, spec.format.stationOffsetSize!); const tVal = Math.floor(posMagnitude); // this is the integer part only const hiPart = Math.floor(tVal / denominator); const lowPart = tVal - hiPart * denominator; @@ -361,7 +374,7 @@ export class Formatter { const stationString = hiPart.toFixed(0) + spec.format.stationSeparator + lowPart.toFixed(0).padStart(spec.format.stationOffsetSize!, "0"); let fractionString = ""; if (fractionPart > 0) { - fractionString = (fractionPart/precisionScale).toFixed(spec.format.precision); + fractionString = (fractionPart / precisionScale).toFixed(spec.format.precision); // remove leading "0." fractionString = fractionString.substring(2).padEnd(spec.format.precision, "0"); if (!isKeepTrailingZeroes) @@ -377,7 +390,7 @@ export class Formatter { } } - if(spec.format.minWidth) { + if (spec.format.minWidth) { formattedValue = this.countAndPad(formattedValue, spec.format.minWidth); } @@ -403,7 +416,7 @@ export class Formatter { let prefix = ""; let suffix = ""; let formattedValue = ""; - if(spec.format.type === FormatType.Bearing || spec.format.type === FormatType.Azimuth) { + if (spec.format.type === FormatType.Bearing || spec.format.type === FormatType.Azimuth) { const result = this.processBearingAndAzimuth(magnitude, spec); magnitude = result.magnitude; prefix = result.prefix ?? ""; @@ -460,10 +473,10 @@ export class Formatter { return formattedValue; } - private static processBearingAndAzimuth(magnitude: number, spec: FormatterSpec): {magnitude: number, prefix?: string, suffix?: string} { + private static processBearingAndAzimuth(magnitude: number, spec: FormatterSpec): { magnitude: number, prefix?: string, suffix?: string } { const type = spec.format.type; if (type !== FormatType.Bearing && type !== FormatType.Azimuth) - return {magnitude}; + return { magnitude }; const revolution = this.getRevolution(spec); magnitude = this.normalizeAngle(magnitude, revolution); @@ -501,23 +514,26 @@ export class Formatter { if (quadrant === 2 && spec.unitConversions.length > 0) { // To determine if value is small, we need to convert it to the smallest unit presented and use the provided precision on it const unitConversion = spec.unitConversions[spec.unitConversions.length - 1].conversion; - const smallestFormattedDelta = applyConversion((quarterRevolution - magnitude), unitConversion) + this.FPV_MINTHRESHOLD; + const smallestFormattedDelta = applyConversion(quarterRevolution - magnitude, unitConversion) + this.FPV_MINTHRESHOLD; const precisionScale = Math.pow(10.0, spec.format.precision); - const floor = Math.floor((smallestFormattedDelta) * precisionScale + FPV_ROUNDFACTOR) / precisionScale; - if(floor === 0) { + const floor = Math.floor(smallestFormattedDelta * precisionScale + FPV_ROUNDFACTOR) / precisionScale; + if (floor === 0) { prefix = "N"; } } - return {magnitude, prefix, suffix: suffix!}; + return { magnitude, prefix, suffix: suffix! }; } if (type === FormatType.Azimuth) { let azimuthBase = 0; // default base is North if (spec.format.azimuthBase !== undefined) { if (spec.azimuthBaseConversion === undefined) { - throw new QuantityError(QuantityStatus.MissingRequiredProperty, `Missing azimuth base conversion for interpreting ${spec.name}'s azimuth base.`); + throw new QuantityError( + QuantityStatus.MissingRequiredProperty, + `Missing azimuth base conversion for interpreting ${spec.name}'s azimuth base.`, + ); } const azBaseQuantity: Quantity = new Quantity(spec.format.azimuthBaseUnit, spec.format.azimuthBase); const azBaseConverted = azBaseQuantity.convertTo(spec.persistenceUnit, spec.azimuthBaseConversion); @@ -528,12 +544,12 @@ export class Formatter { } if (azimuthBase === 0.0 && spec.format.azimuthClockwiseOrDefault) - return {magnitude}; // no conversion necessary, the input is already using the result parameters (north base and clockwise) + return { magnitude }; // no conversion necessary, the input is already using the result parameters (north base and clockwise) // subtract the base from the actual value magnitude -= azimuthBase; if (spec.format.azimuthClockwiseOrDefault) - return {magnitude: this.normalizeAngle(magnitude, revolution)}; + return { magnitude: this.normalizeAngle(magnitude, revolution) }; // turn it into a counter-clockwise angle magnitude = revolution - magnitude; @@ -541,7 +557,7 @@ export class Formatter { magnitude = this.normalizeAngle(magnitude, revolution); } - return {magnitude}; + return { magnitude }; } private static normalizeAngle(magnitude: number, revolution: number): number { @@ -555,7 +571,10 @@ export class Formatter { private static getRevolution(spec: FormatterSpec): number { if (spec.revolutionConversion === undefined) { - throw new QuantityError(QuantityStatus.MissingRequiredProperty, `Missing revolution unit conversion for calculating ${spec.name}'s revolution.`); + throw new QuantityError( + QuantityStatus.MissingRequiredProperty, + `Missing revolution unit conversion for calculating ${spec.name}'s revolution.`, + ); } const revolution: Quantity = new Quantity(spec.format.revolutionUnit, 1.0); @@ -578,7 +597,7 @@ export class Formatter { if (magnitude === 0.0) return "0:1"; else - reciprocal = 1.0/magnitude; + reciprocal = 1.0 / magnitude; switch (spec.format.ratioType) { case RatioType.OneToN: @@ -591,7 +610,7 @@ export class Formatter { else return `1:${this.formatMagnitude(reciprocal, spec)}`; case RatioType.UseGreatestCommonDivisor: - magnitude = Math.round(magnitude * precisionScale)/precisionScale; + magnitude = Math.round(magnitude * precisionScale) / precisionScale; let numerator = magnitude * precisionScale; let denominator = precisionScale; diff --git a/core/quantity/src/Formatter/FormatterSpec.ts b/core/quantity/src/Formatter/FormatterSpec.ts index 982d75bfc1d5..371deb500b51 100644 --- a/core/quantity/src/Formatter/FormatterSpec.ts +++ b/core/quantity/src/Formatter/FormatterSpec.ts @@ -19,7 +19,7 @@ import { Formatter } from "./Formatter"; */ export class FormatterSpec { protected _name: string; - protected _conversions: UnitConversionSpec[] = []; // max four entries + protected _conversions: UnitConversionSpec[] = []; // max four entries protected _format: Format; protected _persistenceUnit: UnitProps; protected _azimuthBaseConversion?: UnitConversionProps; // converts azimuth base unit to persistence unit @@ -33,7 +33,14 @@ export class FormatterSpec { * @param azimuthBaseConversion The conversion used to interpret azimuth base values. * @param revolutionConversion The conversion used to determine a revolution value (used for bearing and azimuth). */ - constructor(name: string, format: Format, conversions?: UnitConversionSpec[], persistenceUnit?: UnitProps, azimuthBaseConversion?: UnitConversionProps, revolutionConversion?: UnitConversionProps) { + constructor( + name: string, + format: Format, + conversions?: UnitConversionSpec[], + persistenceUnit?: UnitProps, + azimuthBaseConversion?: UnitConversionProps, + revolutionConversion?: UnitConversionProps, + ) { if (!persistenceUnit) { if (format.units) { const [props] = format.units[0]; @@ -52,13 +59,25 @@ export class FormatterSpec { this._revolutionConversion = revolutionConversion; } - public get name(): string { return this._name; } + public get name(): string { + return this._name; + } /** Returns an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */ - public get unitConversions(): UnitConversionSpec[] { return this._conversions; } - public get format(): Format { return this._format; } - public get persistenceUnit(): UnitProps { return this._persistenceUnit; } - public get azimuthBaseConversion(): UnitConversionProps | undefined { return this._azimuthBaseConversion; } - public get revolutionConversion(): UnitConversionProps | undefined { return this._revolutionConversion; } + public get unitConversions(): UnitConversionSpec[] { + return this._conversions; + } + public get format(): Format { + return this._format; + } + public get persistenceUnit(): UnitProps { + return this._persistenceUnit; + } + public get azimuthBaseConversion(): UnitConversionProps | undefined { + return this._azimuthBaseConversion; + } + public get revolutionConversion(): UnitConversionProps | undefined { + return this._revolutionConversion; + } /** Get an array of UnitConversionSpecs, one for each unit that is to be shown in the formatted quantity string. */ public static async getUnitConversions(format: Format, unitsProvider: UnitsProvider, inputUnit?: UnitProps): Promise { @@ -91,7 +110,12 @@ export class FormatterSpec { } else { // if format is only numeric and a input unit is defined set spec to use the input unit as the format unit if (inputUnit) { - const spec: UnitConversionSpec = { name: inputUnit.name, label: inputUnit.label, system: inputUnit.system, conversion: { factor: 1.0, offset: 0.0 } }; + const spec: UnitConversionSpec = { + name: inputUnit.name, + label: inputUnit.label, + system: inputUnit.system, + conversion: { factor: 1.0, offset: 0.0 }, + }; conversions.push(spec); } } diff --git a/core/quantity/src/Interfaces.ts b/core/quantity/src/Interfaces.ts index 1e3fe5e4398f..22aee50731aa 100644 --- a/core/quantity/src/Interfaces.ts +++ b/core/quantity/src/Interfaces.ts @@ -62,7 +62,7 @@ export enum UnitConversionInvert { /** Invert value before applying the other conversion steps (the from-unit is the inverted unit) */ InvertPreConversion = "InvertPreConversion", /** Invert value after applying the other conversion steps (the to-unit is the inverted unit) */ - InvertPostConversion = "InvertPostConversion" + InvertPostConversion = "InvertPostConversion", } /** This interface defines the properties required to convert a quantity value from one unit to another such as from meters to feet diff --git a/core/quantity/src/Parser.ts b/core/quantity/src/Parser.ts index 1f568caa2d2f..dace05344a72 100644 --- a/core/quantity/src/Parser.ts +++ b/core/quantity/src/Parser.ts @@ -10,7 +10,15 @@ import { QuantityConstants } from "./Constants"; import { QuantityError, QuantityStatus } from "./Exception"; import { Format } from "./Formatter/Format"; import { FormatTraits, FormatType } from "./Formatter/FormatEnums"; -import { AlternateUnitLabelsProvider, PotentialParseUnit, QuantityProps, UnitConversionProps, UnitConversionSpec, UnitProps, UnitsProvider } from "./Interfaces"; +import { + AlternateUnitLabelsProvider, + PotentialParseUnit, + QuantityProps, + UnitConversionProps, + UnitConversionSpec, + UnitProps, + UnitsProvider, +} from "./Interfaces"; import { ParserSpec } from "./ParserSpec"; import { applyConversion, Quantity } from "./Quantity"; @@ -54,7 +62,7 @@ enum Operator { } function isOperator(char: number | string): boolean { - if(typeof char === "number"){ + if (typeof char === "number") { // Convert the CharCode to string. char = String.fromCharCode(char); } @@ -75,16 +83,20 @@ class ParseToken { public isOperator: boolean = false; constructor(value: string | number | Operator) { - if (typeof value === "string"){ + if (typeof value === "string") { this.value = value.trim(); this.isOperator = isOperator(this.value); - } else{ + } else { this.value = value; } } - public get isString(): boolean { return !this.isOperator && typeof this.value === "string"; } - public get isNumber(): boolean { return typeof this.value === "number"; } + public get isString(): boolean { + return !this.isOperator && typeof this.value === "string"; + } + public get isNumber(): boolean { + return typeof this.value === "number"; + } } /** A ScientificToken holds an index and string representing the exponent. @@ -136,7 +148,9 @@ export class Parser { for (; i < stringToParse.length; i++) { const charCode = stringToParse.charCodeAt(i); - if (Parser.isDigit(charCode) || ((charCode === QuantityConstants.CHAR_MINUS || charCode === QuantityConstants.CHAR_PLUS) && (i === (index + 1)))) { + if ( + Parser.isDigit(charCode) || ((charCode === QuantityConstants.CHAR_MINUS || charCode === QuantityConstants.CHAR_PLUS) && (i === (index + 1))) + ) { exponentString = exponentString.concat(stringToParse[i]); } else { i = uomSeparatorToIgnore === charCode ? i : i - 1; @@ -144,7 +158,11 @@ export class Parser { } } - if (exponentString.length > 1 || ((exponentString.length === 1) && (exponentString.charCodeAt(0) !== QuantityConstants.CHAR_MINUS) && (exponentString.charCodeAt(0) !== QuantityConstants.CHAR_PLUS))) + if ( + exponentString.length > 1 || + ((exponentString.length === 1) && (exponentString.charCodeAt(0) !== QuantityConstants.CHAR_MINUS) && + (exponentString.charCodeAt(0) !== QuantityConstants.CHAR_PLUS)) + ) return new ScientificToken(i, exponentString); return new ScientificToken(index); @@ -169,7 +187,11 @@ export class Parser { denominatorToken = denominatorToken.concat(stringToParse[i]); } } else { - if (processingNumerator && (charCode === QuantityConstants.CHAR_SLASH || charCode === QuantityConstants.CHAR_DIVISION_SLASH || charCode === QuantityConstants.CHAR_DIVISION_SLASH)) { + if ( + processingNumerator && + (charCode === QuantityConstants.CHAR_SLASH || charCode === QuantityConstants.CHAR_DIVISION_SLASH || + charCode === QuantityConstants.CHAR_DIVISION_SLASH) + ) { processingNumerator = false; } else { if (uomSeparatorToIgnore !== charCode) @@ -242,7 +264,10 @@ export class Parser { wipToken = wipToken.concat(charToAdd); } else { if (processingNumber) { - if (charCode === QuantityConstants.CHAR_SLASH || charCode === QuantityConstants.CHAR_FRACTION_SLASH || charCode === QuantityConstants.CHAR_DIVISION_SLASH) { + if ( + charCode === QuantityConstants.CHAR_SLASH || charCode === QuantityConstants.CHAR_FRACTION_SLASH || + charCode === QuantityConstants.CHAR_DIVISION_SLASH + ) { const fractSymbol = Parser.checkForFractions(i + 1, str, uomSeparatorToIgnore, wipToken); let fraction = fractSymbol.fraction; i = fractSymbol.index; @@ -303,13 +328,13 @@ export class Parser { } } - if (format.type === FormatType.Station && charCode === format.stationSeparator.charCodeAt(0)){ - if(!isStationSeparatorAdded){ + if (format.type === FormatType.Station && charCode === format.stationSeparator.charCodeAt(0)) { + if (!isStationSeparatorAdded) { isStationSeparatorAdded = true; continue; } isStationSeparatorAdded = false; - } else if (skipCodes.findIndex((ref) => ref === charCode) !== -1){ + } else if (skipCodes.findIndex((ref) => ref === charCode) !== -1) { // ignore any codes in skipCodes continue; } @@ -324,14 +349,14 @@ export class Parser { wipToken = (i < str.length) ? str[i] : ""; processingNumber = false; - if(wipToken.length === 1 && isOperator(wipToken)){ + if (wipToken.length === 1 && isOperator(wipToken)) { tokens.push(new ParseToken(wipToken)); // Push operator token. wipToken = ""; } } else { // not processing a number if (isOperator(charCode)) { - if(wipToken.length > 0){ + if (wipToken.length > 0) { // There is a token is progress, process it now, before adding the new operator token. tokens.push(new ParseToken(wipToken)); wipToken = ""; @@ -341,7 +366,7 @@ export class Parser { continue; } - if(wipToken.length === 0 && charCode === QuantityConstants.CHAR_SPACE){ + if (wipToken.length === 0 && charCode === QuantityConstants.CHAR_SPACE) { // Don't add space when the wip token is empty. continue; } @@ -366,11 +391,11 @@ export class Parser { return tokens; } - private static isMathematicOperation(tokens: ParseToken[]){ - if(tokens.length > 1){ + private static isMathematicOperation(tokens: ParseToken[]) { + if (tokens.length > 1) { // The loop starts at one because the first token can be a operator without it being maths. Ex: "-5FT" - for(let i = 1; i < tokens.length; i++){ - if(tokens[i].isOperator) + for (let i = 1; i < tokens.length; i++) { + if (tokens[i].isOperator) // Operator found, it's a math operation. return true; } @@ -378,7 +403,12 @@ export class Parser { return false; } - private static async lookupUnitByLabel(unitLabel: string, format: Format, unitsProvider: UnitsProvider, altUnitLabelsProvider?: AlternateUnitLabelsProvider) { + private static async lookupUnitByLabel( + unitLabel: string, + format: Format, + unitsProvider: UnitsProvider, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ) { const defaultUnit = format.units && format.units.length > 0 ? format.units[0][0] : undefined; const labelToFind = unitLabel.toLowerCase(); @@ -399,7 +429,11 @@ export class Parser { } // now try to find a unit from the same family and system - let foundUnit = await unitsProvider.findUnit(unitLabel, defaultUnit ? defaultUnit.phenomenon : undefined, defaultUnit ? defaultUnit.system : undefined); + let foundUnit = await unitsProvider.findUnit( + unitLabel, + defaultUnit ? defaultUnit.phenomenon : undefined, + defaultUnit ? defaultUnit.system : undefined, + ); // if nothing found yet just limit to family if (!foundUnit.isValid && defaultUnit) @@ -410,28 +444,33 @@ export class Parser { /** * Get the output unit and all the conversion specs required to parse a given list of tokens. */ - private static async getRequiredUnitsConversionsToParseTokens(tokens: ParseToken[], format: Format, unitsProvider: UnitsProvider, altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise<{ + private static async getRequiredUnitsConversionsToParseTokens( + tokens: ParseToken[], + format: Format, + unitsProvider: UnitsProvider, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise<{ outUnit?: UnitProps; specs: UnitConversionSpec[]; }> { - let outUnit = (format.units && format.units.length > 0 ? format.units[0][0] : undefined); + let outUnit = format.units && format.units.length > 0 ? format.units[0][0] : undefined; const unitConversions: UnitConversionSpec[] = []; const uniqueUnitLabels = [...new Set(tokens.filter((token) => token.isString).map((token) => token.value as string))]; - for(const label of uniqueUnitLabels){ + for (const label of uniqueUnitLabels) { const unitProps = await this.lookupUnitByLabel(label, format, unitsProvider, altUnitLabelsProvider); - if(!outUnit){ + if (!outUnit) { // No default unit, assume that the first unit found is the desired output unit. outUnit = unitProps; } let spec = unitConversions.find((specB) => specB.name === unitProps.name); - if(spec){ + if (spec) { // Already in the list, just add the label. spec.parseLabels?.push(label.toLocaleLowerCase()); } else { // Add new conversion to the list. const conversion = await unitsProvider.getConversion(unitProps, outUnit); - if(conversion){ + if (conversion) { spec = { conversion, label: unitProps.label, @@ -444,17 +483,27 @@ export class Parser { } } - return {outUnit, specs: unitConversions}; + return { outUnit, specs: unitConversions }; } /** * Get the units information asynchronously, then convert the tokens into quantity using the synchronous tokens -> value. */ - private static async createQuantityFromParseTokens(tokens: ParseToken[], format: Format, unitsProvider: UnitsProvider, altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise { + private static async createQuantityFromParseTokens( + tokens: ParseToken[], + format: Format, + unitsProvider: UnitsProvider, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise { const unitConversionInfos = await this.getRequiredUnitsConversionsToParseTokens(tokens, format, unitsProvider, altUnitLabelsProvider); - if(unitConversionInfos.outUnit){ - const value = Parser.getQuantityValueFromParseTokens(tokens, format, unitConversionInfos.specs, await unitsProvider.getConversion(unitConversionInfos.outUnit, unitConversionInfos.outUnit)); - if(value.ok){ + if (unitConversionInfos.outUnit) { + const value = Parser.getQuantityValueFromParseTokens( + tokens, + format, + unitConversionInfos.specs, + await unitsProvider.getConversion(unitConversionInfos.outUnit, unitConversionInfos.outUnit), + ); + if (value.ok) { return new Quantity(unitConversionInfos.outUnit, value.value); } } @@ -467,7 +516,12 @@ export class Parser { * @param format Defines the likely format of inString. * @param unitsProvider required to look up units that may be specified in inString */ - public static async parseIntoQuantity(inString: string, format: Format, unitsProvider: UnitsProvider, altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise { + public static async parseIntoQuantity( + inString: string, + format: Format, + unitsProvider: UnitsProvider, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise { const tokens: ParseToken[] = Parser.parseQuantitySpecification(inString, format); if (tokens.length === 0 || (!format.allowMathematicOperations && Parser.isMathematicOperation(tokens))) return new Quantity(); @@ -476,7 +530,11 @@ export class Parser { } /** method to get the Unit Conversion given a unit label */ - private static tryFindUnitConversion(unitLabel: string, unitsConversions: UnitConversionSpec[], preferredUnit?: UnitProps): UnitConversionProps | undefined { + private static tryFindUnitConversion( + unitLabel: string, + unitsConversions: UnitConversionSpec[], + preferredUnit?: UnitProps, + ): UnitConversionProps | undefined { if (unitsConversions.length > 0) { const label = unitLabel.toLocaleLowerCase(); @@ -520,14 +578,14 @@ export class Parser { /** * Get what the unit conversion is for a unitless value. */ - private static getDefaultUnitConversion(tokens: ParseToken[], unitsConversions: UnitConversionSpec[], defaultUnit?: UnitProps){ + private static getDefaultUnitConversion(tokens: ParseToken[], unitsConversions: UnitConversionSpec[], defaultUnit?: UnitProps) { let unitConversion = defaultUnit ? Parser.tryFindUnitConversion(defaultUnit.label, unitsConversions, defaultUnit) : undefined; - if(!unitConversion){ + if (!unitConversion) { // No default unit conversion, take the first valid unit. const uniqueUnitLabels = [...new Set(tokens.filter((token) => token.isString).map((token) => token.value as string))]; - for(const label of uniqueUnitLabels){ + for (const label of uniqueUnitLabels) { unitConversion = Parser.tryFindUnitConversion(label, unitsConversions, defaultUnit); - if(unitConversion !== undefined) + if (unitConversion !== undefined) return unitConversion; } } @@ -536,7 +594,7 @@ export class Parser { // Get the next token pair to parse into a quantity. private static getNextTokenPair(index: number, tokens: ParseToken[]): ParseToken[] | undefined { - if(index >= tokens.length) + if (index >= tokens.length) return; // 6 possible combination of token pair. @@ -557,10 +615,10 @@ export class Parser { // Check if the token pair is valid. If not, try again by removing the last token util empty. // Ex: ['5', 'FT', '7'] invalid => ['5', 'FT'] valid returned - for(let i = currentCombination.length - 1; i >= 0; i--){ - if(validCombinations.includes(JSON.stringify(currentCombination))){ + for (let i = currentCombination.length - 1; i >= 0; i--) { + if (validCombinations.includes(JSON.stringify(currentCombination))) { break; - } else{ + } else { currentCombination.pop(); tokenPair.pop(); } @@ -572,7 +630,12 @@ export class Parser { /** * Accumulate the given list of tokens into a single quantity value. Formatting the tokens along the way. */ - private static getQuantityValueFromParseTokens(tokens: ParseToken[], format: Format, unitsConversions: UnitConversionSpec[], defaultUnitConversion?: UnitConversionProps ): QuantityParseResult { + private static getQuantityValueFromParseTokens( + tokens: ParseToken[], + format: Format, + unitsConversions: UnitConversionSpec[], + defaultUnitConversion?: UnitConversionProps, + ): QuantityParseResult { const defaultUnit = format.units && format.units.length > 0 ? format.units[0][0] : undefined; defaultUnitConversion = defaultUnitConversion ? defaultUnitConversion : Parser.getDefaultUnitConversion(tokens, unitsConversions, defaultUnit); @@ -585,30 +648,30 @@ export class Parser { let compositeUnitIndex = 0; for (let i = 0; i < tokens.length; i = i + increment) { tokenPair = this.getNextTokenPair(i, tokens); - if(!tokenPair || tokenPair.length === 0){ + if (!tokenPair || tokenPair.length === 0) { return { ok: false, error: ParseError.UnableToConvertParseTokensToQuantity }; } increment = tokenPair.length; // Keep the sign so its applied to the next tokens. - if(tokenPair[0].isOperator){ + if (tokenPair[0].isOperator) { sign = tokenPair[0].value === Operator.addition ? 1 : -1; tokenPair.shift(); compositeUnitIndex = 0; // Reset the composite unit index, the following tokens begin from start. } // unit specification comes before value (like currency) - if(tokenPair.length === 2 && tokenPair[0].isString){ + if (tokenPair.length === 2 && tokenPair[0].isString) { // Invert it so the currency sign comes second. tokenPair = [tokenPair[1], tokenPair[0]]; } - if(tokenPair[0].isNumber){ + if (tokenPair[0].isNumber) { let value = sign * (tokenPair[0].value as number); let conversion: UnitConversionProps | undefined; - if(tokenPair.length === 2 && tokenPair[1].isString){ + if (tokenPair.length === 2 && tokenPair[1].isString) { const spacer = format.spacerOrDefault; - if(tokenPair[1].value !== spacer){ // ignore spacer + if (tokenPair[1].value !== spacer) { // ignore spacer conversion = Parser.tryFindUnitConversion(tokenPair[1].value as string, unitsConversions, defaultUnit); } } @@ -629,7 +692,7 @@ export class Parser { } else { // only the unit label was specified so assume magnitude of 0 const conversion = Parser.tryFindUnitConversion(tokenPair[0].value as string, unitsConversions, defaultUnit); - if (conversion === undefined){ + if (conversion === undefined) { // Unknown unit label return { ok: false, error: ParseError.NoValueOrUnitFoundInString }; } @@ -693,9 +756,12 @@ export class Parser { }); } - if(format.type === FormatType.Bearing || format.type === FormatType.Azimuth || format.type === FormatType.Ratio) { + if (format.type === FormatType.Bearing || format.type === FormatType.Azimuth || format.type === FormatType.Ratio) { // throw error indicating to call parseQuantityString instead - throw new QuantityError(QuantityStatus.UnsupportedUnit, `Bearing, Azimuth or Ratio format must be parsed using a ParserSpec. Call parseQuantityString instead.`); + throw new QuantityError( + QuantityStatus.UnsupportedUnit, + `Bearing, Azimuth or Ratio format must be parsed using a ParserSpec. Call parseQuantityString instead.`, + ); } return this.parseAndProcessTokens(inString, format, unitsConversions); @@ -707,7 +773,7 @@ export class Parser { North = "N", South = "S", East = "E", - West = "W" + West = "W", } let matchedPrefix: DirectionLabel | null = null; let matchedSuffix: DirectionLabel | null = null; @@ -735,7 +801,7 @@ export class Parser { } const parsedResult = this.parseAndProcessTokens(inString, spec.format, spec.unitConversions); - if(this.isParseError(parsedResult) || !parsedResult.ok) { + if (this.isParseError(parsedResult) || !parsedResult.ok) { return parsedResult; } @@ -761,7 +827,7 @@ export class Parser { private static parseAzimuthFormat(inString: string, spec: ParserSpec): QuantityParseResult { const parsedResult = this.parseAndProcessTokens(inString, spec.format, spec.unitConversions); - if(this.isParseError(parsedResult) || !parsedResult.ok) { + if (this.isParseError(parsedResult) || !parsedResult.ok) { return parsedResult; } @@ -772,7 +838,10 @@ export class Parser { let azimuthBase = 0.0; if (spec.format.azimuthBase !== undefined) { if (spec.azimuthBaseConversion === undefined) { - throw new QuantityError(QuantityStatus.MissingRequiredProperty, `Missing azimuth base conversion for interpreting ${spec.format.name}'s azimuth base.`); + throw new QuantityError( + QuantityStatus.MissingRequiredProperty, + `Missing azimuth base conversion for interpreting ${spec.format.name}'s azimuth base.`, + ); } const azBaseQuantity: Quantity = new Quantity(spec.format.azimuthBaseUnit, spec.format.azimuthBase); const azBaseConverted = azBaseQuantity.convertTo(spec.outUnit, spec.azimuthBaseConversion); @@ -783,7 +852,7 @@ export class Parser { } const inputIsClockwise = spec.format.azimuthClockwiseOrDefault; - if(inputIsClockwise && azimuthBase === 0) { + if (inputIsClockwise && azimuthBase === 0) { // parsed result already has the same base and orientation as our desired output return parsedResult; } @@ -824,7 +893,7 @@ export class Parser { throw new QuantityError(QuantityStatus.MissingRequiredProperty, `Missing input unit or unit conversion for interpreting ${spec.format.name}.`); } - if (denominator === 0){ + if (denominator === 0) { if (unitConversion.inversion && numerator === 1) return { ok: true, value: 0.0 }; else @@ -841,15 +910,18 @@ export class Parser { let converted: Quantity | undefined; try { converted = quantity.convertTo(spec.outUnit, unitConversion); - } catch (err){ + } catch (err) { // for input of "0:N" with reversed unit - if (err instanceof QuantityError && err.errorNumber === QuantityStatus.InvertingZero){ + if (err instanceof QuantityError && err.errorNumber === QuantityStatus.InvertingZero) { return { ok: false, error: ParseError.MathematicOperationFoundButIsNotAllowed }; } } if (converted === undefined || !converted.isValid) { - throw new QuantityError(QuantityStatus.UnsupportedUnit, `Failed to convert from ${spec.format.units[0][0].name} to ${spec.outUnit.name} On format ${spec.format.name}.`); + throw new QuantityError( + QuantityStatus.UnsupportedUnit, + `Failed to convert from ${spec.format.units[0][0].name} to ${spec.outUnit.name} On format ${spec.format.name}.`, + ); } return { ok: true, value: converted.magnitude }; @@ -867,13 +939,19 @@ export class Parser { private static getRevolution(spec: ParserSpec): number { if (spec.revolutionConversion === undefined) { - throw new QuantityError(QuantityStatus.MissingRequiredProperty, `Missing revolution unit conversion for calculating ${spec.format.name}'s revolution.`); + throw new QuantityError( + QuantityStatus.MissingRequiredProperty, + `Missing revolution unit conversion for calculating ${spec.format.name}'s revolution.`, + ); } const revolution: Quantity = new Quantity(spec.format.revolutionUnit, 1.0); const converted = revolution.convertTo(spec.outUnit, spec.revolutionConversion); if (converted === undefined || !converted.isValid) { - throw new QuantityError(QuantityStatus.UnsupportedUnit, `Failed to convert revolution unit to ${spec.outUnit.name} On format ${spec.format.name}.`); + throw new QuantityError( + QuantityStatus.UnsupportedUnit, + `Failed to convert revolution unit to ${spec.outUnit.name} On format ${spec.format.name}.`, + ); } return converted.magnitude; @@ -884,7 +962,7 @@ export class Parser { if (tokens.length === 0) return { ok: false, error: ParseError.UnableToGenerateParseTokens }; - if(!format.allowMathematicOperations && Parser.isMathematicOperation(tokens)){ + if (!format.allowMathematicOperations && Parser.isMathematicOperation(tokens)) { return { ok: false, error: ParseError.MathematicOperationFoundButIsNotAllowed }; } @@ -902,7 +980,11 @@ export class Parser { } /** Async Method used to create an array of UnitConversionSpec entries that can be used in synchronous calls to parse units. */ - public static async createUnitConversionSpecsForUnit(unitsProvider: UnitsProvider, outUnit: UnitProps, altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise { + public static async createUnitConversionSpecsForUnit( + unitsProvider: UnitsProvider, + outUnit: UnitProps, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise { const unitConversionSpecs: UnitConversionSpec[] = []; const familyUnits = await unitsProvider.getUnitsByFamily(outUnit.phenomenon); @@ -931,7 +1013,12 @@ export class Parser { } /** Async Method used to create an array of UnitConversionSpec entries that can be used in synchronous calls to parse units. */ - public static async createUnitConversionSpecs(unitsProvider: UnitsProvider, outUnitName: string, potentialParseUnits: PotentialParseUnit[], altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise { + public static async createUnitConversionSpecs( + unitsProvider: UnitsProvider, + outUnitName: string, + potentialParseUnits: PotentialParseUnit[], + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise { const unitConversionSpecs: UnitConversionSpec[] = []; const outUnit = await unitsProvider.findUnitByName(outUnitName); diff --git a/core/quantity/src/ParserSpec.ts b/core/quantity/src/ParserSpec.ts index 402e7387b0d0..d8b8ce4cb247 100644 --- a/core/quantity/src/ParserSpec.ts +++ b/core/quantity/src/ParserSpec.ts @@ -15,7 +15,7 @@ import { Parser, QuantityParseResult } from "./Parser"; */ export class ParserSpec { private _outUnit: UnitProps; - private _conversions: UnitConversionSpec[] = []; // max four entries + private _conversions: UnitConversionSpec[] = []; // max four entries private _format: Format; protected _azimuthBaseConversion?: UnitConversionProps; // converts azimuth base unit to persistence unit protected _revolutionConversion?: UnitConversionProps; // converts revolution unit to persistence unit @@ -32,11 +32,21 @@ export class ParserSpec { } /** Returns an array of UnitConversionSpecs for each unit label that may be used in the input string. */ - public get unitConversions(): UnitConversionSpec[] { return this._conversions; } - public get format(): Format { return this._format; } - public get outUnit(): UnitProps { return this._outUnit; } - public get azimuthBaseConversion(): UnitConversionProps | undefined { return this._azimuthBaseConversion; } - public get revolutionConversion(): UnitConversionProps | undefined { return this._revolutionConversion; } + public get unitConversions(): UnitConversionSpec[] { + return this._conversions; + } + public get format(): Format { + return this._format; + } + public get outUnit(): UnitProps { + return this._outUnit; + } + public get azimuthBaseConversion(): UnitConversionProps | undefined { + return this._azimuthBaseConversion; + } + public get revolutionConversion(): UnitConversionProps | undefined { + return this._revolutionConversion; + } /** Static async method to create a ParserSpec given the format and unit of the quantity that will be passed to the Parser. The input unit will * be used to generate conversion information for each unit specified in the Format. This method is async due to the fact that the units provider must make @@ -45,7 +55,12 @@ export class ParserSpec { * @param unitsProvider The units provider is used to look up unit definitions and provide conversion information for converting between units. * @param outUnit The unit the value to be formatted. This unit is often referred to as persistence unit. */ - public static async create(format: Format, unitsProvider: UnitsProvider, outUnit: UnitProps, altUnitLabelsProvider?: AlternateUnitLabelsProvider): Promise { + public static async create( + format: Format, + unitsProvider: UnitsProvider, + outUnit: UnitProps, + altUnitLabelsProvider?: AlternateUnitLabelsProvider, + ): Promise { const conversions = await Parser.createUnitConversionSpecsForUnit(unitsProvider, outUnit, altUnitLabelsProvider); const spec = new ParserSpec(outUnit, format, conversions); if (format.azimuthBaseUnit !== undefined) { @@ -70,4 +85,3 @@ export class ParserSpec { return Parser.parseQuantityString(inString, this); } } - diff --git a/core/quantity/src/Quantity.ts b/core/quantity/src/Quantity.ts index 152e9ea17c1d..9f9710837ead 100644 --- a/core/quantity/src/Quantity.ts +++ b/core/quantity/src/Quantity.ts @@ -32,9 +32,15 @@ export class Quantity implements QuantityProps { protected _unit: UnitProps; protected _isValid: boolean = false; - public get unit(): UnitProps { return this._unit; } - public get magnitude(): number { return this._magnitude; } - public get isValid(): boolean { return this._isValid; } + public get unit(): UnitProps { + return this._unit; + } + public get magnitude(): number { + return this._magnitude; + } + public get isValid(): boolean { + return this._isValid; + } /** Constructor. The Quantity will only be set as valid if a unit is specified. * @param unit Defines the quantity's unit. diff --git a/core/quantity/src/test/BearingAzimuth.test.ts b/core/quantity/src/test/BearingAzimuth.test.ts index 1301a5900b9d..86841ff5a109 100644 --- a/core/quantity/src/test/BearingAzimuth.test.ts +++ b/core/quantity/src/test/BearingAzimuth.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; +import { FormatProps, Parser, ParserSpec, QuantityError, UnitProps, UnitsProvider } from "../core-quantity"; import { Format } from "../Formatter/Format"; -import { FormatterSpec } from "../Formatter/FormatterSpec"; import { Formatter } from "../Formatter/Formatter"; +import { FormatterSpec } from "../Formatter/FormatterSpec"; import { TestUnitsProvider } from "./TestUtils/TestHelper"; -import { FormatProps, Parser, ParserSpec, QuantityError, UnitProps, UnitsProvider } from "../core-quantity"; describe("Bearing format tests:", () => { it("Roundtrip persisted radian to and from bearing", async () => { @@ -42,7 +42,7 @@ describe("Bearing format tests:", () => { units: [ { name: "Units.ARC_DEG", label: "°" }, { name: "Units.ARC_MINUTE", label: "'" }, - { name: "Units.ARC_SECOND", label: "\"" }, + { name: "Units.ARC_SECOND", label: '"' }, ], }, }; @@ -64,15 +64,15 @@ describe("Bearing format tests:", () => { }; const bearingDMS = new Format("BearingDMS"); - await bearingDMS.fromJSON(unitsProvider, bearingDMSJson).catch(() => { }); + await bearingDMS.fromJSON(unitsProvider, bearingDMSJson).catch(() => {}); assert.isTrue(bearingDMS.hasUnits); const bearingDMSWithLabel = new Format("BearingDMSWithLabel"); - await bearingDMSWithLabel.fromJSON(unitsProvider, bearingDMSWithLabelJson).catch(() => { }); + await bearingDMSWithLabel.fromJSON(unitsProvider, bearingDMSWithLabelJson).catch(() => {}); assert.isTrue(bearingDMSWithLabel.hasUnits); const bearingDecimal = new Format("BearingDecimal"); - await bearingDecimal.fromJSON(unitsProvider, bearingDecimalJson).catch(() => { }); + await bearingDecimal.fromJSON(unitsProvider, bearingDecimalJson).catch(() => {}); assert.isTrue(bearingDecimal.hasUnits); const rad: UnitProps = await unitsProvider.findUnitByName("Units.RAD"); @@ -95,22 +95,22 @@ describe("Bearing format tests:", () => { const degreesToRadians = (degrees: number): number => degrees * (Math.PI / 180); const testData: TestData[] = [ - { input: 0.0, unit: rad, dms: "N00:00:00E", dmsWithLabel: "N00°00'00\"E", decimal: "N00.000°E" }, - { input: 5.0, unit: rad, dms: "N05:00:00E", dmsWithLabel: "N05°00'00\"E", decimal: "N05.000°E" }, - { input: 45.0, unit: rad, dms: "N45:00:00E", dmsWithLabel: "N45°00'00\"E", decimal: "N45.000°E" }, + { input: 0.0, unit: rad, dms: "N00:00:00E", dmsWithLabel: "N00°00'00\"E", decimal: "N00.000°E" }, + { input: 5.0, unit: rad, dms: "N05:00:00E", dmsWithLabel: "N05°00'00\"E", decimal: "N05.000°E" }, + { input: 45.0, unit: rad, dms: "N45:00:00E", dmsWithLabel: "N45°00'00\"E", decimal: "N45.000°E" }, { input: 45.5028, unit: rad, dms: "N45:30:10E", dmsWithLabel: "N45°30'10\"E", decimal: "N45.503°E" }, - { input: 90.0, unit: rad, dms: "N90:00:00E", dmsWithLabel: "N90°00'00\"E", decimal: "N90.000°E" }, - { input: 135.0, unit: rad, dms: "S45:00:00E", dmsWithLabel: "S45°00'00\"E", decimal: "S45.000°E" }, - { input: 180.0, unit: rad, dms: "S00:00:00E", dmsWithLabel: "S00°00'00\"E", decimal: "S00.000°E" }, - { input: 225.0, unit: rad, dms: "S45:00:00W", dmsWithLabel: "S45°00'00\"W", decimal: "S45.000°W" }, - { input: 234.4972,unit: rad, dms: "S54:29:50W", dmsWithLabel: "S54°29'50\"W", decimal: "S54.497°W" }, - { input: 270.0, unit: rad, dms: "N90:00:00W", dmsWithLabel: "N90°00'00\"W", decimal: "N90.000°W" }, - { input: 315.0, unit: rad, dms: "N45:00:00W", dmsWithLabel: "N45°00'00\"W", decimal: "N45.000°W" }, - { input: 0.0, unit: rad, dms: "N00:00:00E", dmsWithLabel: "N00°00'00\"E", decimal: "N00.000°E" }, - { input: 52.0, unit: rad, dms: "N52:00:00E", dmsWithLabel: "N52°00'00\"E", decimal: "N52.000°E" }, - { input: 110.0, unit: rad, dms: "S70:00:00E", dmsWithLabel: "S70°00'00\"E", decimal: "S70.000°E" }, - { input: 580.0, unit: rad, dms: "S40:00:00W", dmsWithLabel: "S40°00'00\"W", decimal: "S40.000°W" }, - { input: 1000.0, unit: rad, dms: "N80:00:00W", dmsWithLabel: "N80°00'00\"W", decimal: "N80.000°W" }, + { input: 90.0, unit: rad, dms: "N90:00:00E", dmsWithLabel: "N90°00'00\"E", decimal: "N90.000°E" }, + { input: 135.0, unit: rad, dms: "S45:00:00E", dmsWithLabel: "S45°00'00\"E", decimal: "S45.000°E" }, + { input: 180.0, unit: rad, dms: "S00:00:00E", dmsWithLabel: "S00°00'00\"E", decimal: "S00.000°E" }, + { input: 225.0, unit: rad, dms: "S45:00:00W", dmsWithLabel: "S45°00'00\"W", decimal: "S45.000°W" }, + { input: 234.4972, unit: rad, dms: "S54:29:50W", dmsWithLabel: "S54°29'50\"W", decimal: "S54.497°W" }, + { input: 270.0, unit: rad, dms: "N90:00:00W", dmsWithLabel: "N90°00'00\"W", decimal: "N90.000°W" }, + { input: 315.0, unit: rad, dms: "N45:00:00W", dmsWithLabel: "N45°00'00\"W", decimal: "N45.000°W" }, + { input: 0.0, unit: rad, dms: "N00:00:00E", dmsWithLabel: "N00°00'00\"E", decimal: "N00.000°E" }, + { input: 52.0, unit: rad, dms: "N52:00:00E", dmsWithLabel: "N52°00'00\"E", decimal: "N52.000°E" }, + { input: 110.0, unit: rad, dms: "S70:00:00E", dmsWithLabel: "S70°00'00\"E", decimal: "S70.000°E" }, + { input: 580.0, unit: rad, dms: "S40:00:00W", dmsWithLabel: "S40°00'00\"W", decimal: "S40.000°W" }, + { input: 1000.0, unit: rad, dms: "N80:00:00W", dmsWithLabel: "N80°00'00\"W", decimal: "N80.000°W" }, ]; for (const entry of testData) { @@ -131,7 +131,10 @@ describe("Bearing format tests:", () => { if (!Parser.isParsedQuantity(parseBearingDMSWithLabelResult)) { assert.fail(`Expected a parsed from bearing DMS with label input string ${resultBearingDMSWithLabel}`); } - expect(parseBearingDMSWithLabelResult.value, `Parsed result for ${normalizedAngle} from formatted ${resultBearingDMSWithLabel}`).closeTo(normalizedAngle, 0.0001); + expect(parseBearingDMSWithLabelResult.value, `Parsed result for ${normalizedAngle} from formatted ${resultBearingDMSWithLabel}`).closeTo( + normalizedAngle, + 0.0001, + ); const resultBearingDecimal = Formatter.formatQuantity(radians, bearingDecimalFormatter); expect(resultBearingDecimal).to.be.eql(entry.decimal); @@ -139,13 +142,15 @@ describe("Bearing format tests:", () => { if (!Parser.isParsedQuantity(parseBearingDecimalResult)) { assert.fail(`Expected a parsed from bearing decimal input string ${resultBearingDecimal}`); } - expect(parseBearingDecimalResult.value, `Parsed result for ${normalizedAngle} from formatted ${resultBearingDecimal}`).closeTo(normalizedAngle, 0.0001); + expect(parseBearingDecimalResult.value, `Parsed result for ${normalizedAngle} from formatted ${resultBearingDecimal}`).closeTo( + normalizedAngle, + 0.0001, + ); } }); }); describe("Azimuth format tests:", () => { - it("Format radian as azimuth", async () => { const unitsProvider = new TestUnitsProvider(); @@ -182,11 +187,11 @@ describe("Azimuth format tests:", () => { }; const azimuthDMS = new Format("azimuthDMS"); - await azimuthDMS.fromJSON(unitsProvider, azimuthDMSJson).catch(() => { }); + await azimuthDMS.fromJSON(unitsProvider, azimuthDMSJson).catch(() => {}); assert.isTrue(azimuthDMS.hasUnits); const azimuthDecimal = new Format("azimuthDecimal"); - await azimuthDecimal.fromJSON(unitsProvider, azimuthDecimalJson).catch(() => { }); + await azimuthDecimal.fromJSON(unitsProvider, azimuthDecimalJson).catch(() => {}); assert.isTrue(azimuthDecimal.hasUnits); const rad: UnitProps = await unitsProvider.findUnitByName("Units.RAD"); @@ -203,22 +208,22 @@ describe("Azimuth format tests:", () => { const degreesToRadians = (degrees: number): number => degrees * (Math.PI / 180); const testData: TestData[] = [ - { input: 0.0, unit: rad, dms: "00:00:00", decimal: "00.000°"}, - { input: 5.0, unit: rad, dms: "05:00:00", decimal: "05.000°"}, - { input: 45.0, unit: rad, dms: "45:00:00", decimal: "45.000°"}, - { input: 45.5028, unit: rad, dms: "45:30:10", decimal: "45.503°"}, - { input: 90.0, unit: rad, dms: "90:00:00", decimal: "90.000°"}, - { input: 135.0, unit: rad, dms: "135:00:00", decimal: "135.000°"}, - { input: 180.0, unit: rad, dms: "180:00:00", decimal: "180.000°"}, - { input: 225.0, unit: rad, dms: "225:00:00", decimal: "225.000°"}, - { input: 234.4972,unit: rad, dms: "234:29:50", decimal: "234.497°"}, - { input: 270.0, unit: rad, dms: "270:00:00", decimal: "270.000°"}, - { input: 315.0, unit: rad, dms: "315:00:00", decimal: "315.000°"}, - { input: 0.0, unit: rad, dms: "00:00:00", decimal: "00.000°"}, - { input: 52.0, unit: rad, dms: "52:00:00", decimal: "52.000°"}, - { input: 110.0, unit: rad, dms: "110:00:00", decimal: "110.000°"}, - { input: 580.0, unit: rad, dms: "220:00:00", decimal: "220.000°"}, - { input: 1000.0, unit: rad, dms: "280:00:00", decimal: "280.000°"}, + { input: 0.0, unit: rad, dms: "00:00:00", decimal: "00.000°" }, + { input: 5.0, unit: rad, dms: "05:00:00", decimal: "05.000°" }, + { input: 45.0, unit: rad, dms: "45:00:00", decimal: "45.000°" }, + { input: 45.5028, unit: rad, dms: "45:30:10", decimal: "45.503°" }, + { input: 90.0, unit: rad, dms: "90:00:00", decimal: "90.000°" }, + { input: 135.0, unit: rad, dms: "135:00:00", decimal: "135.000°" }, + { input: 180.0, unit: rad, dms: "180:00:00", decimal: "180.000°" }, + { input: 225.0, unit: rad, dms: "225:00:00", decimal: "225.000°" }, + { input: 234.4972, unit: rad, dms: "234:29:50", decimal: "234.497°" }, + { input: 270.0, unit: rad, dms: "270:00:00", decimal: "270.000°" }, + { input: 315.0, unit: rad, dms: "315:00:00", decimal: "315.000°" }, + { input: 0.0, unit: rad, dms: "00:00:00", decimal: "00.000°" }, + { input: 52.0, unit: rad, dms: "52:00:00", decimal: "52.000°" }, + { input: 110.0, unit: rad, dms: "110:00:00", decimal: "110.000°" }, + { input: 580.0, unit: rad, dms: "220:00:00", decimal: "220.000°" }, + { input: 1000.0, unit: rad, dms: "280:00:00", decimal: "280.000°" }, ]; for (const entry of testData) { @@ -290,24 +295,24 @@ describe("Azimuth format tests:", () => { } const testData: TestData[] = [ - { input: 0.0, base: 0.0, counterClockwise: false, result: "00.0°" }, + { input: 0.0, base: 0.0, counterClockwise: false, result: "00.0°" }, { input: 260.0, base: 180.0, counterClockwise: false, result: "80.0°" }, { input: 0.0, base: 175.0, counterClockwise: false, result: "185.0°" }, { input: 0.0, base: 175.0, counterClockwise: true, result: "175.0°" }, - { input: 0.0, base: 185.0, counterClockwise: true, result: "185.0°" }, - { input: 0.0, base: 95.0, counterClockwise: false, result: "265.0°" }, - { input: 0.0, base: 85.0, counterClockwise: false, result: "275.0°" }, + { input: 0.0, base: 185.0, counterClockwise: true, result: "185.0°" }, + { input: 0.0, base: 95.0, counterClockwise: false, result: "265.0°" }, + { input: 0.0, base: 85.0, counterClockwise: false, result: "275.0°" }, { input: 0.0, base: 270.0, counterClockwise: false, result: "90.0°" }, - { input: 0.0, base: 270.0, counterClockwise: true, result: "270.0°" }, - { input: 90.0, base: 0.0, counterClockwise: false, result: "90.0°" }, - { input: 90.0, base: 180.0, counterClockwise: false, result: "270.0°" }, - { input: 90.0, base: 175.0, counterClockwise: false, result: "275.0°" }, + { input: 0.0, base: 270.0, counterClockwise: true, result: "270.0°" }, + { input: 90.0, base: 0.0, counterClockwise: false, result: "90.0°" }, + { input: 90.0, base: 180.0, counterClockwise: false, result: "270.0°" }, + { input: 90.0, base: 175.0, counterClockwise: false, result: "275.0°" }, { input: 80.0, base: 175.0, counterClockwise: false, result: "265.0°" }, - { input: 90.0, base: 185.0, counterClockwise: true, result: "95.0°" }, - { input: 90.0, base: 95.0, counterClockwise: false, result: "355.0°" }, - { input: 90.0, base: 85.0, counterClockwise: false, result: "05.0°" }, - { input: 90.0, base: 270.0, counterClockwise: false, result: "180.0°" }, - { input: 90.0, base: 270.0, counterClockwise: true, result: "180.0°" }, + { input: 90.0, base: 185.0, counterClockwise: true, result: "95.0°" }, + { input: 90.0, base: 95.0, counterClockwise: false, result: "355.0°" }, + { input: 90.0, base: 85.0, counterClockwise: false, result: "05.0°" }, + { input: 90.0, base: 270.0, counterClockwise: false, result: "180.0°" }, + { input: 90.0, base: 270.0, counterClockwise: true, result: "180.0°" }, ]; for (const entry of testData) { @@ -320,7 +325,10 @@ describe("Azimuth format tests:", () => { if (!Parser.isParsedQuantity(parseResult)) { assert.fail("Expected a parsed quantity"); } - expect(parseResult.value, `Parsed result for ${entry.input} with base ${entry.base} ccw: ${entry.counterClockwise}`).closeTo(entry.input, 0.0001); + expect(parseResult.value, `Parsed result for ${entry.input} with base ${entry.base} ccw: ${entry.counterClockwise}`).closeTo( + entry.input, + 0.0001, + ); } }); @@ -476,7 +484,10 @@ describe("Azimuth and Revolution formatting that throws error:", () => { await testFormatWithAzimuthType.fromJSON(unitsProvider, jsonObj); expect.fail("Expected error was not thrown"); } catch (e: any) { - assert.strictEqual(e.message, "The Format testAzimuthFormat is 'Azimuth' or 'Bearing' type therefore the attribute 'revolutionUnit' is required."); + assert.strictEqual( + e.message, + "The Format testAzimuthFormat is 'Azimuth' or 'Bearing' type therefore the attribute 'revolutionUnit' is required.", + ); assert.instanceOf(e, QuantityError); } }); @@ -489,7 +500,10 @@ describe("Azimuth and Revolution formatting that throws error:", () => { await testFormatWithAzimuthType.fromJSON(unitsProvider, { type: "azimuth" }); expect.fail("Expected error was not thrown"); } catch (e: any) { - assert.strictEqual(e.message, "The Format testAzimuthFormat has an 'azimuthBase' attribute therefore the attribute 'azimuthBaseUnit' is required."); + assert.strictEqual( + e.message, + "The Format testAzimuthFormat has an 'azimuthBase' attribute therefore the attribute 'azimuthBaseUnit' is required.", + ); assert.instanceOf(e, QuantityError); } }); diff --git a/core/quantity/src/test/CompositeFormats.test.ts b/core/quantity/src/test/CompositeFormats.test.ts index 1116292e57b9..34d2b586e8ac 100644 --- a/core/quantity/src/test/CompositeFormats.test.ts +++ b/core/quantity/src/test/CompositeFormats.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; +import { FormatTraits } from "../core-quantity"; import { Format } from "../Formatter/Format"; -import { FormatterSpec } from "../Formatter/FormatterSpec"; import { Formatter } from "../Formatter/Formatter"; +import { FormatterSpec } from "../Formatter/FormatterSpec"; import { BasicUnit } from "../Unit"; import { TestUnitsProvider } from "./TestUtils/TestHelper"; -import { FormatTraits } from "../core-quantity"; describe("Composite Formats tests:", () => { it("Bad Composite unit order", async () => { @@ -20,7 +20,7 @@ describe("Composite Formats tests:", () => { spacer: "", units: [ { - label: "\"", + label: '"', name: "Units.IN", }, { @@ -37,7 +37,7 @@ describe("Composite Formats tests:", () => { try { const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testEntry = { magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "12:6 1/2" }; @@ -65,7 +65,7 @@ describe("Composite Formats tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.BOGUS.IN", }, ], @@ -78,11 +78,13 @@ describe("Composite Formats tests:", () => { try { const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testEntry = { - magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "12:6 1/2", + magnitude: 12.5416666666667, + unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, + result: "12:6 1/2", }; const unit = new BasicUnit(testEntry.unit.name, testEntry.unit.label, testEntry.unit.contextId); @@ -118,7 +120,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -204,10 +206,18 @@ describe("Composite Formats tests:", () => { formatData.formatTraits.push("trailZeroes"); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits, `Test case number ${testEntry.testCaseNum} failed`); - assert.equal(format.hasFormatTraitSet(FormatTraits.KeepSingleZero), testEntry.keepSingleZero, `Test case number ${testEntry.testCaseNum} failed`); - assert.equal(format.hasFormatTraitSet(FormatTraits.KeepDecimalPoint), testEntry.keepDecimalPoint, `Test case number ${testEntry.testCaseNum} failed`); + assert.equal( + format.hasFormatTraitSet(FormatTraits.KeepSingleZero), + testEntry.keepSingleZero, + `Test case number ${testEntry.testCaseNum} failed`, + ); + assert.equal( + format.hasFormatTraitSet(FormatTraits.KeepDecimalPoint), + testEntry.keepDecimalPoint, + `Test case number ${testEntry.testCaseNum} failed`, + ); assert.equal(format.hasFormatTraitSet(FormatTraits.TrailZeroes), testEntry.trailZeroes, `Test case number ${testEntry.testCaseNum} failed`); const spec = await FormatterSpec.create("test", format, unitsProvider, new BasicUnit(unit.name, unit.label, unit.contextId)); @@ -230,7 +240,7 @@ describe("Composite Formats tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -242,7 +252,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -279,7 +289,7 @@ describe("Composite Formats tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -291,7 +301,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -324,7 +334,7 @@ describe("Composite Formats tests:", () => { spacer: "", units: [ { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -336,16 +346,16 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ - { magnitude: -12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "-150 1/2\"" }, - { magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "150 1/2\"" }, - { magnitude: 1.05000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "12 5/8\"" }, - { magnitude: 12345789, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "148149468\"" }, - { magnitude: 0.00000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "0\"" }, - { magnitude: 11.9999999999, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "144\"" }, + { magnitude: -12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '-150 1/2"' }, + { magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '150 1/2"' }, + { magnitude: 1.05000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '12 5/8"' }, + { magnitude: 12345789, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '148149468"' }, + { magnitude: 0.00000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '0"' }, + { magnitude: 11.9999999999, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '144"' }, ]; for (const testEntry of testQuantityData) { @@ -380,7 +390,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -412,7 +422,7 @@ describe("Composite Formats tests:", () => { spacer: "", units: [ { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -424,16 +434,16 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ - { magnitude: -12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "-150.5\"" }, - { magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "150.5\"" }, - { magnitude: 1.05000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "12.6\"" }, - { magnitude: 12345789, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "148149468\"" }, + { magnitude: -12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '-150.5"' }, + { magnitude: 12.5416666666667, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '150.5"' }, + { magnitude: 1.05000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '12.6"' }, + { magnitude: 12345789, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '148149468"' }, { magnitude: 0.00000, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "" }, - { magnitude: 11.9999999999, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: "144\"" }, + { magnitude: 11.9999999999, unit: { name: "Units.FT", label: "ft", contextId: "Units.LENGTH" }, result: '144"' }, ]; for (const testEntry of testQuantityData) { @@ -459,7 +469,7 @@ describe("Composite Formats tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -471,7 +481,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -506,7 +516,7 @@ describe("Composite Formats tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -518,7 +528,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -561,7 +571,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -601,7 +611,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -637,7 +647,7 @@ describe("Composite Formats tests:", () => { name: "Units.ARC_MINUTE", }, { - label: "\"", + label: '"', name: "Units.ARC_SECOND", }, ], @@ -649,7 +659,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -684,7 +694,7 @@ describe("Composite Formats tests:", () => { name: "Units.ARC_MINUTE", }, { - label: "\"", + label: '"', name: "Units.ARC_SECOND", }, ], @@ -696,7 +706,7 @@ describe("Composite Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const testQuantityData = [ @@ -727,7 +737,7 @@ describe("Composite Formats tests:", () => { composite: { includeZero: true, spacer: "", - units: [{name: "Units.KM"},{name: "Units.M", label: ""},{name: "Units.CM", label: "CM"},{name: "Units.MM", label: "'"}], + units: [{ name: "Units.KM" }, { name: "Units.M", label: "" }, { name: "Units.CM", label: "CM" }, { name: "Units.MM", label: "'" }], }, formatTraits: ["keepSingleZero", "applyRounding"], precision: 4, @@ -737,7 +747,9 @@ describe("Composite Formats tests:", () => { const format = new Format("test"); assert.isDefined(format); - await format.fromJSON(unitsProvider, compositeFormat).catch(() => { }); - expect(JSON.stringify(format.toJSON().composite)).to.eql(`{"spacer":"","includeZero":true,"units":[{"name":"Units.KM"},{"name":"Units.M","label":""},{"name":"Units.CM","label":"CM"},{"name":"Units.MM","label":"'"}]}`); + await format.fromJSON(unitsProvider, compositeFormat).catch(() => {}); + expect(JSON.stringify(format.toJSON().composite)).to.eql( + `{"spacer":"","includeZero":true,"units":[{"name":"Units.KM"},{"name":"Units.M","label":""},{"name":"Units.CM","label":"CM"},{"name":"Units.MM","label":"'"}]}`, + ); }); }); diff --git a/core/quantity/src/test/Formatting.test.ts b/core/quantity/src/test/Formatting.test.ts index 29c596e74c88..4a2a06753e67 100644 --- a/core/quantity/src/test/Formatting.test.ts +++ b/core/quantity/src/test/Formatting.test.ts @@ -134,7 +134,7 @@ describe("Formatting tests:", () => { }; const testFormat = new Format("test"); - await testFormat.fromJSON(unitsProvider, json).catch(() => { }); + await testFormat.fromJSON(unitsProvider, json).catch(() => {}); }); it("Good default round factor", async () => { @@ -149,7 +149,7 @@ describe("Formatting tests:", () => { }; const testFormat = new Format("test"); - await testFormat.fromJSON(unitsProvider, json).catch(() => { }); + await testFormat.fromJSON(unitsProvider, json).catch(() => {}); }); it("Bad minWidth value", async () => { @@ -165,7 +165,9 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'minWidth' attribute. It should be a positive integer.`); + assert.isTrue( + err instanceof QuantityError && err.message === `The Format test has an invalid 'minWidth' attribute. It should be a positive integer.`, + ); }); }); @@ -198,7 +200,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has an invalid 'decimalSeparator' attribute. It should be an empty or one character string.`, + ); }); }); @@ -230,7 +235,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has an invalid 'thousandSeparator' attribute. It should be an empty or one character string.`, + ); }); }); @@ -261,7 +269,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has an invalid 'uomSeparator' attribute. It should be an empty or one character string.`, + ); }); }); @@ -293,7 +304,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has an invalid 'stationSeparator' attribute. It should be an empty or one character string.`, + ); }); }); @@ -326,7 +340,9 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test is 'Scientific' type therefore the attribute 'scientificType' is required.`); + assert.isTrue( + err instanceof QuantityError && err.message === `The Format test is 'Scientific' type therefore the attribute 'scientificType' is required.`, + ); }); }); @@ -435,7 +451,9 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test is 'Station' type therefore the attribute 'stationOffsetSize' is required.`); + assert.isTrue( + err instanceof QuantityError && err.message === `The Format test is 'Station' type therefore the attribute 'stationOffsetSize' is required.`, + ); }); }); @@ -452,7 +470,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has an invalid 'stationOffsetSize' attribute. It should be a positive integer.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has an invalid 'stationOffsetSize' attribute. It should be a positive integer.`, + ); }); }); @@ -469,7 +490,7 @@ describe("Formatting tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -482,7 +503,10 @@ describe("Formatting tests:", () => { const testFormat = new Format("test"); await testFormat.fromJSON(unitsProvider, json).catch((err) => { - assert.isTrue(err instanceof QuantityError && err.message === `The Format test has a Composite with an invalid 'spacer' attribute. It should be an empty or one character string.`); + assert.isTrue( + err instanceof QuantityError && + err.message === `The Format test has a Composite with an invalid 'spacer' attribute. It should be an empty or one character string.`, + ); }); }); @@ -490,7 +514,18 @@ describe("Formatting tests:", () => { const unitsProvider = new TestUnitsProvider(); const json = { - formatTraits: ["trailZeroes", "keepSingleZero", "zeroEmpty", "keepDecimalPoint", "applyRounding", "fractionDash", "showUnitLabel", "prependUnitLabel", "use1000Separator", "exponentOnlyNegative"], + formatTraits: [ + "trailZeroes", + "keepSingleZero", + "zeroEmpty", + "keepDecimalPoint", + "applyRounding", + "fractionDash", + "showUnitLabel", + "prependUnitLabel", + "use1000Separator", + "exponentOnlyNegative", + ], precision: 8, type: "Decimal", uomSeparator: " ", @@ -711,7 +746,7 @@ describe("Formatting tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], @@ -724,7 +759,7 @@ describe("Formatting tests:", () => { for (const formatData of formatDataArray) { const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); if (formatData.hasOwnProperty("precision")) assert.isTrue(format.precision === formatData.precision); assert.isTrue(formatTypeToString(format.type).toUpperCase() === formatData.type.toUpperCase()); @@ -800,7 +835,8 @@ describe("Formatting tests:", () => { it("show old/optional trait format works properly", () => { const formatProps: FormatProps = { type: "decimal", - formatTraits: "trailZeroes,keepSingleZero,zeroEmpty,keepDecimalPoint,applyRounding,fractionDash,showUnitLabel,prependUnitLabel,use1000Separator,exponentOnlyNegative", + formatTraits: + "trailZeroes,keepSingleZero,zeroEmpty,keepDecimalPoint,applyRounding,fractionDash,showUnitLabel,prependUnitLabel,use1000Separator,exponentOnlyNegative", }; assert.isTrue(Format.isFormatTraitSetInProps(formatProps, FormatTraits.ApplyRounding)); @@ -857,7 +893,6 @@ describe("Formatting tests:", () => { uomSeparator: " ", }, { - formatTraits: ["KeepSingleZero", "KeepDecimalPoint", "ShowUnitLabel"], precision: 8, type: "Fractional", @@ -871,7 +906,7 @@ describe("Formatting tests:", () => { name: "Units.FT", }, { - label: "\"", + label: '"', name: "Units.IN", }, ], diff --git a/core/quantity/src/test/NumericFormat.test.ts b/core/quantity/src/test/NumericFormat.test.ts index 1187579daf6a..d39f2f9279c0 100644 --- a/core/quantity/src/test/NumericFormat.test.ts +++ b/core/quantity/src/test/NumericFormat.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert } from "chai"; +import { FormatTraits, FormatType } from "../core-quantity"; import { Format } from "../Formatter/Format"; -import { FormatterSpec } from "../Formatter/FormatterSpec"; +import { DecimalPrecision } from "../Formatter/FormatEnums"; import { Formatter } from "../Formatter/Formatter"; +import { FormatterSpec } from "../Formatter/FormatterSpec"; +import { UnitProps } from "../Interfaces"; import { BasicUnit } from "../Unit"; import { TestUnitsProvider } from "./TestUtils/TestHelper"; -import { FormatTraits, FormatType } from "../core-quantity"; -import { DecimalPrecision } from "../Formatter/FormatEnums"; -import { UnitProps } from "../Interfaces"; describe("Numeric Formats tests:", () => { it("Feet to 4 Decimal places w/trailing zeros ", async () => { @@ -26,7 +26,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -64,7 +64,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -102,7 +102,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const clonedFormat = format.clone({ @@ -143,7 +143,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -177,7 +177,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -210,7 +210,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -245,7 +245,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -277,7 +277,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -310,7 +310,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -343,7 +343,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -374,7 +374,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -408,7 +408,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -441,7 +441,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -473,7 +473,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -500,7 +500,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -533,7 +533,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -566,7 +566,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -598,7 +598,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const testQuantityData = [ @@ -634,7 +634,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const clonedFormat = format.clone({ @@ -676,7 +676,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const clonedFormat = format.clone({ @@ -718,7 +718,7 @@ describe("Numeric Formats tests:", () => { }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); const primaryUnit: UnitProps = { diff --git a/core/quantity/src/test/Parsing.test.ts b/core/quantity/src/test/Parsing.test.ts index 0ace09cc6587..bb46d4835244 100644 --- a/core/quantity/src/test/Parsing.test.ts +++ b/core/quantity/src/test/Parsing.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; import { Format } from "../Formatter/Format"; -import { FormatterSpec } from "../Formatter/FormatterSpec"; import { Formatter } from "../Formatter/Formatter"; +import { FormatterSpec } from "../Formatter/FormatterSpec"; import { UnitProps } from "../Interfaces"; import { ParseError, Parser } from "../Parser"; import { ParserSpec } from "../ParserSpec"; @@ -44,12 +44,16 @@ describe("Parsing tests:", () => { it("Convert units", async () => { const expectedConversionResults = [ - { label: "FT", unitContext: "", cvtTo: [{ label: "\"", factor: 12.0 }] }, - { label: "yd", unitContext: "", cvtTo: [{ label: "\'", factor: 3.0 }, { label: "\"", factor: 36.0 }] }, - { label: "mi", unitContext: "", cvtTo: [{ label: "yrd", factor: 1760.0 }, { label: "\'", factor: 5280.0 }, { label: "\"", factor: 63360.0 }] }, - { label: "°", unitContext: "Units.ANGLE", cvtTo: [{ label: "deg", factor: 1.0 }, { label: "min", factor: 60.0 }, { label: "sec", factor: 3600.0 }] }, + { label: "FT", unitContext: "", cvtTo: [{ label: '"', factor: 12.0 }] }, + { label: "yd", unitContext: "", cvtTo: [{ label: "'", factor: 3.0 }, { label: '"', factor: 36.0 }] }, + { label: "mi", unitContext: "", cvtTo: [{ label: "yrd", factor: 1760.0 }, { label: "'", factor: 5280.0 }, { label: '"', factor: 63360.0 }] }, + { + label: "°", + unitContext: "Units.ANGLE", + cvtTo: [{ label: "deg", factor: 1.0 }, { label: "min", factor: 60.0 }, { label: "sec", factor: 3600.0 }], + }, { label: "'", unitContext: "Units.ANGLE", cvtTo: [{ label: "min", factor: 1.0 }, { label: "sec", factor: 60.0 }] }, - { label: "\"", unitContext: "Units.ANGLE", cvtTo: [{ label: "sec", factor: 1.0 }] }, + { label: '"', unitContext: "Units.ANGLE", cvtTo: [{ label: "sec", factor: 1.0 }] }, ]; const unitsProvider = new TestUnitsProvider(); @@ -66,29 +70,33 @@ describe("Parsing tests:", () => { }); it("Generate Parse Tokens", async () => { - const format = new Format("test"); const tests = [ - {input: "", expectedTokens: []}, - {input: "0/1", expectedTokens: [{ value: 0 }]}, - {input: "1/0", expectedTokens: [{ value: 1 }]}, - {input: "1/2", expectedTokens: [{ value: 0.5 }]}, - {input: "-1/2", expectedTokens: [{value: "-", isOperand: true}, { value: 0.5 }]}, - {input: "+1/2", expectedTokens: [{value: "+", isOperand: true}, { value: 0.5 }]}, - {input: "2 /", expectedTokens: [{ value: 2 }]}, - {input: "1.616252eggs", expectedTokens: [{ value: 1.616252 }, { value: "eggs" }]}, - {input: "1.616252E-35eggs", expectedTokens: [{ value: 1.616252e-35 }, { value: "eggs" }]}, - {input: "-1.616252E-35eggs", expectedTokens: [{value: "-", isOperand: true}, { value: 1.616252e-35 }, { value: "eggs" }]}, - {input: "756345.345", expectedTokens: [{ value: 756345.345 }]}, - {input: "12,345.345", expectedTokens: [{ value: 12345.345 }]}, - {input: "3.6252e3 Miles", expectedTokens: [{ value: 3625.2 }, { value: "Miles" }]}, - {input: "-1 1/2 FT", expectedTokens: [{value: "-", isOperand: true}, { value: 1.5 }, { value: "FT" }]}, - {input: "+1 1/2 FT", expectedTokens: [{value: "+", isOperand: true}, { value: 1.5 }, { value: "FT" }]}, - {input: "-135°11'30.5\"", expectedTokens: [{value: "-", isOperand: true}, { value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: "\"" }]}, - {input: "-2FT 6IN", expectedTokens: [{value: "-", isOperand: true}, { value: 2 }, { value: "FT" }, { value: 6 }, { value: "IN" }]}, - {input: "135°11'30.5\"", expectedTokens: [{ value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: "\"" }]}, - {input: "2FT 6IN", expectedTokens: [{ value: 2 }, { value: "FT" }, { value: 6 }, { value: "IN" }]}, - {input: "1 1/2 FT", expectedTokens: [{ value: 1.5 }, { value: "FT" }]}, + { input: "", expectedTokens: [] }, + { input: "0/1", expectedTokens: [{ value: 0 }] }, + { input: "1/0", expectedTokens: [{ value: 1 }] }, + { input: "1/2", expectedTokens: [{ value: 0.5 }] }, + { input: "-1/2", expectedTokens: [{ value: "-", isOperand: true }, { value: 0.5 }] }, + { input: "+1/2", expectedTokens: [{ value: "+", isOperand: true }, { value: 0.5 }] }, + { input: "2 /", expectedTokens: [{ value: 2 }] }, + { input: "1.616252eggs", expectedTokens: [{ value: 1.616252 }, { value: "eggs" }] }, + { input: "1.616252E-35eggs", expectedTokens: [{ value: 1.616252e-35 }, { value: "eggs" }] }, + { input: "-1.616252E-35eggs", expectedTokens: [{ value: "-", isOperand: true }, { value: 1.616252e-35 }, { value: "eggs" }] }, + { input: "756345.345", expectedTokens: [{ value: 756345.345 }] }, + { input: "12,345.345", expectedTokens: [{ value: 12345.345 }] }, + { input: "3.6252e3 Miles", expectedTokens: [{ value: 3625.2 }, { value: "Miles" }] }, + { input: "-1 1/2 FT", expectedTokens: [{ value: "-", isOperand: true }, { value: 1.5 }, { value: "FT" }] }, + { input: "+1 1/2 FT", expectedTokens: [{ value: "+", isOperand: true }, { value: 1.5 }, { value: "FT" }] }, + { + input: "-135°11'30.5\"", + expectedTokens: [{ value: "-", isOperand: true }, { value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { + value: '"', + }], + }, + { input: "-2FT 6IN", expectedTokens: [{ value: "-", isOperand: true }, { value: 2 }, { value: "FT" }, { value: 6 }, { value: "IN" }] }, + { input: "135°11'30.5\"", expectedTokens: [{ value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: '"' }] }, + { input: "2FT 6IN", expectedTokens: [{ value: 2 }, { value: "FT" }, { value: 6 }, { value: "IN" }] }, + { input: "1 1/2 FT", expectedTokens: [{ value: 1.5 }, { value: "FT" }] }, ]; let i = 0; @@ -106,14 +114,19 @@ describe("Parsing tests:", () => { it("Generate Parse Tokens given different decimal and thousand separators", async () => { const tests = [ - {input: "1,616252eggs", expectedTokens: [{ value: 1.616252 }, { value: "eggs" }]}, - {input: "1,616252E-35eggs", expectedTokens: [{ value: 1.616252e-35 }, { value: "eggs" }]}, - {input: "-1,616252E-35eggs", expectedTokens: [{value: "-", isOperand: true}, { value: 1.616252e-35 }, { value: "eggs" }]}, - {input: "756345,345", expectedTokens: [{ value: 756345.345 }]}, - {input: "12.345,345", expectedTokens: [{ value: 12345.345 }]}, - {input: "3,6252e3 Miles", expectedTokens: [{ value: 3625.2 }, { value: "Miles" }]}, - {input: "-135°11'30,5\"", expectedTokens: [{value: "-", isOperand: true}, { value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: "\"" }]}, - {input: "135°11'30,5\"", expectedTokens: [{ value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: "\"" }]}, + { input: "1,616252eggs", expectedTokens: [{ value: 1.616252 }, { value: "eggs" }] }, + { input: "1,616252E-35eggs", expectedTokens: [{ value: 1.616252e-35 }, { value: "eggs" }] }, + { input: "-1,616252E-35eggs", expectedTokens: [{ value: "-", isOperand: true }, { value: 1.616252e-35 }, { value: "eggs" }] }, + { input: "756345,345", expectedTokens: [{ value: 756345.345 }] }, + { input: "12.345,345", expectedTokens: [{ value: 12345.345 }] }, + { input: "3,6252e3 Miles", expectedTokens: [{ value: 3625.2 }, { value: "Miles" }] }, + { + input: "-135°11'30,5\"", + expectedTokens: [{ value: "-", isOperand: true }, { value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { + value: '"', + }], + }, + { input: "135°11'30,5\"", expectedTokens: [{ value: 135 }, { value: "°" }, { value: 11 }, { value: "'" }, { value: 30.5 }, { value: '"' }] }, ]; const formatData = { @@ -123,7 +136,7 @@ describe("Parsing tests:", () => { }; const format = new Format("test"); const unitsProvider = new TestUnitsProvider(); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); let i = 0; for (const test of tests) { @@ -144,12 +157,12 @@ describe("Parsing tests:", () => { { label: "FT", name: "Units.FT", unitContext: "" }, { label: "'", name: "Units.FT", unitContext: "Units.LENGTH" }, { label: "ft", name: "Units.FT", unitContext: "" }, - { label: "\"", name: "Units.IN", unitContext: "Units.LENGTH" }, + { label: '"', name: "Units.IN", unitContext: "Units.LENGTH" }, { label: "in", name: "Units.IN", unitContext: "" }, { label: "IN", name: "Units.IN", unitContext: "" }, { label: "°", name: "Units.ARC_DEG", unitContext: "Units.ANGLE" }, { label: "'", name: "Units.ARC_MINUTE", unitContext: "Units.ANGLE" }, - { label: "\"", name: "Units.ARC_SECOND", unitContext: "Units.ANGLE" }, + { label: '"', name: "Units.ARC_SECOND", unitContext: "Units.ANGLE" }, ]; const unitProvider = new TestUnitsProvider(); @@ -162,12 +175,16 @@ describe("Parsing tests:", () => { it("Convert units", async () => { const expectedConversionResults = [ - { label: "FT", unitContext: "", cvtTo: [{ label: "\"", factor: 12.0 }] }, - { label: "yd", unitContext: "", cvtTo: [{ label: "\'", factor: 3.0 }, { label: "\"", factor: 36.0 }] }, - { label: "mi", unitContext: "", cvtTo: [{ label: "yrd", factor: 1760.0 }, { label: "\'", factor: 5280.0 }, { label: "\"", factor: 63360.0 }] }, - { label: "°", unitContext: "Units.ANGLE", cvtTo: [{ label: "deg", factor: 1.0 }, { label: "min", factor: 60.0 }, { label: "sec", factor: 3600.0 }] }, + { label: "FT", unitContext: "", cvtTo: [{ label: '"', factor: 12.0 }] }, + { label: "yd", unitContext: "", cvtTo: [{ label: "'", factor: 3.0 }, { label: '"', factor: 36.0 }] }, + { label: "mi", unitContext: "", cvtTo: [{ label: "yrd", factor: 1760.0 }, { label: "'", factor: 5280.0 }, { label: '"', factor: 63360.0 }] }, + { + label: "°", + unitContext: "Units.ANGLE", + cvtTo: [{ label: "deg", factor: 1.0 }, { label: "min", factor: 60.0 }, { label: "sec", factor: 3600.0 }], + }, { label: "'", unitContext: "Units.ANGLE", cvtTo: [{ label: "min", factor: 1.0 }, { label: "sec", factor: 60.0 }] }, - { label: "\"", unitContext: "Units.ANGLE", cvtTo: [{ label: "sec", factor: 1.0 }] }, + { label: '"', unitContext: "Units.ANGLE", cvtTo: [{ label: "sec", factor: 1.0 }] }, ]; const unitsProvider = new TestUnitsProvider(); @@ -214,12 +231,11 @@ describe("Parsing tests:", () => { { value: "-3IN", quantity: { magnitude: -0.25, unitName: "Units.FT" } }, // Test with invalid unit specifier -- should default to -3 ft { value: "-3 ABCDEF", quantity: { magnitude: -3, unitName: "Units.FT" } }, - ]; const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); for (const testEntry of testData) { @@ -253,7 +269,7 @@ describe("Parsing tests:", () => { const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); for (const testEntry of testData) { const quantityProps = await Parser.parseIntoQuantity(testEntry.value, format, unitsProvider); @@ -295,7 +311,7 @@ describe("Parsing tests:", () => { const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); for (const testEntry of testData) { @@ -336,7 +352,7 @@ describe("Parsing tests:", () => { ]; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); for (const testEntry of testData) { @@ -361,7 +377,7 @@ describe("Parsing tests:", () => { name: "Units.ARC_MINUTE", }, { - label: "\"", + label: '"', name: "Units.ARC_SECOND", }, ], @@ -382,7 +398,7 @@ describe("Parsing tests:", () => { const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); for (const testEntry of testData) { @@ -413,7 +429,7 @@ describe("Parsing tests:", () => { const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(!format.hasUnits); for (const testEntry of testData) { @@ -437,21 +453,21 @@ describe("Parsing tests:", () => { }; const testData = [ - { value: "1000 usft", magnitude: 304.8006096012192 }, // label should match the label in the Format so it will use SURVEY_FT - { value: "1000 ft (US Survey)", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label + { value: "1000 usft", magnitude: 304.8006096012192 }, // label should match the label in the Format so it will use SURVEY_FT + { value: "1000 ft (US Survey)", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label { value: "1000 USF", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label - { value: "1000 ft", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label + { value: "1000 ft", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label { value: "1000 USF", magnitude: 304.8006096012192 }, // label should match a valid SURVEY_FT label or alternate label - { value: "1000", magnitude: 304.8006096012192 }, // no label should default to SURVEY_FT from Format - { value: "1000 ABCDEF", magnitude: 304.8006096012192 }, // invalid label, should default to SURVEY_FT from Format since the unit is provided - { value: "1000 f", magnitude: 304.8 }, // "f" is only valid for Units.FT so convert based on feet - { value: "1000'", magnitude: 304.8 }, // "'" is only valid for Units.FT so convert based on feet - { value: "1100 usft - 100", magnitude: 304.8006096012192 }, // label should match the label in the Format so it will use SURVEY_FT + { value: "1000", magnitude: 304.8006096012192 }, // no label should default to SURVEY_FT from Format + { value: "1000 ABCDEF", magnitude: 304.8006096012192 }, // invalid label, should default to SURVEY_FT from Format since the unit is provided + { value: "1000 f", magnitude: 304.8 }, // "f" is only valid for Units.FT so convert based on feet + { value: "1000'", magnitude: 304.8 }, // "'" is only valid for Units.FT so convert based on feet + { value: "1100 usft - 100", magnitude: 304.8006096012192 }, // label should match the label in the Format so it will use SURVEY_FT ]; const unitsAndAltLabelsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsAndAltLabelsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsAndAltLabelsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); const persistenceUnit = await unitsAndAltLabelsProvider.findUnitByName("Units.M"); @@ -480,20 +496,20 @@ describe("Parsing tests:", () => { }; const testData = [ - { value: "1000 usft", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match the label in the Format so it will use SURVEY_FT - { value: "1000 ft (US Survey)", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label + { value: "1000 usft", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match the label in the Format so it will use SURVEY_FT + { value: "1000 ft (US Survey)", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label { value: "1000 USF", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label - { value: "1000 ft", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label + { value: "1000 ft", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label { value: "1000 USF", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match a valid SURVEY_FT label or alternate label - { value: "1000", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // no label should default to SURVEY_FT from Format - { value: "1000 f", quantity: { magnitude: 999.998, unitName: "Units.US_SURVEY_FT" } }, // "f" is only valid for Units.FT so convert based on feet - { value: "1000'", quantity: { magnitude: 999.998, unitName: "Units.US_SURVEY_FT" } }, // "'" is only valid for Units.FT so convert based on feet - { value: "1100 usft - 100", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match the label in the Format so it will use SURVEY_FT + { value: "1000", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // no label should default to SURVEY_FT from Format + { value: "1000 f", quantity: { magnitude: 999.998, unitName: "Units.US_SURVEY_FT" } }, // "f" is only valid for Units.FT so convert based on feet + { value: "1000'", quantity: { magnitude: 999.998, unitName: "Units.US_SURVEY_FT" } }, // "'" is only valid for Units.FT so convert based on feet + { value: "1100 usft - 100", quantity: { magnitude: 1000, unitName: "Units.US_SURVEY_FT" } }, // label should match the label in the Format so it will use SURVEY_FT ]; const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); assert.isTrue(format.hasUnits); for (const testEntry of testData) { @@ -523,25 +539,25 @@ describe("Parsing tests:", () => { const testData = [ // When unitless, the format unit is used to determine unit. (The unit the user is working on.) - { value: "12,345.345 - 1", quantity: { magnitude: 12344.345, unitName: "Units.M" }}, - { value: "1yd + 2", quantity: { magnitude: 0.9144 + 2, unitName: "Units.M" }}, - { value: "1yd + 1m + 2", quantity: { magnitude: 0.9144 + 3, unitName: "Units.M" }}, - { value: "1 FT + 6IN", quantity: { magnitude: 0.45720000000000005, unitName: "Units.M" }}, - { value: "-1-1", quantity: { magnitude: -2, unitName: "Units.M" }}, - { value: "1 ' + 1 FT", quantity: { magnitude: 0.6096, unitName: "Units.M" }}, - { value: "-1 FT + 1", quantity: { magnitude: -0.3048 + 1, unitName: "Units.M" }}, - { value: "1 F + 1.5", quantity: { magnitude: 0.3048 + 1.5, unitName: "Units.M" }}, - { value: "-2FT 6IN + 6IN", quantity: { magnitude: -0.6096, unitName: "Units.M" }}, - { value: "1 1/2FT + 1/2IN", quantity: { magnitude: 0.45720000000000005 + 0.0127, unitName: "Units.M" }}, - { value: "2' 6\"-0.5", quantity: { magnitude: 0.762 - 0.5, unitName: "Units.M" }}, - { value: "1 yd + 1FT 6IN", quantity: { magnitude: 1.3716, unitName: "Units.M" }}, - { value: "1 m -1FT +6IN", quantity: { magnitude: 1 - 0.1524, unitName: "Units.M" }}, - { value: "-1m 1CM 1mm - 1 FT + 6IN + 1yd", quantity: { magnitude: -0.24899999999999978, unitName: "Units.M" }}, + { value: "12,345.345 - 1", quantity: { magnitude: 12344.345, unitName: "Units.M" } }, + { value: "1yd + 2", quantity: { magnitude: 0.9144 + 2, unitName: "Units.M" } }, + { value: "1yd + 1m + 2", quantity: { magnitude: 0.9144 + 3, unitName: "Units.M" } }, + { value: "1 FT + 6IN", quantity: { magnitude: 0.45720000000000005, unitName: "Units.M" } }, + { value: "-1-1", quantity: { magnitude: -2, unitName: "Units.M" } }, + { value: "1 ' + 1 FT", quantity: { magnitude: 0.6096, unitName: "Units.M" } }, + { value: "-1 FT + 1", quantity: { magnitude: -0.3048 + 1, unitName: "Units.M" } }, + { value: "1 F + 1.5", quantity: { magnitude: 0.3048 + 1.5, unitName: "Units.M" } }, + { value: "-2FT 6IN + 6IN", quantity: { magnitude: -0.6096, unitName: "Units.M" } }, + { value: "1 1/2FT + 1/2IN", quantity: { magnitude: 0.45720000000000005 + 0.0127, unitName: "Units.M" } }, + { value: "2' 6\"-0.5", quantity: { magnitude: 0.762 - 0.5, unitName: "Units.M" } }, + { value: "1 yd + 1FT 6IN", quantity: { magnitude: 1.3716, unitName: "Units.M" } }, + { value: "1 m -1FT +6IN", quantity: { magnitude: 1 - 0.1524, unitName: "Units.M" } }, + { value: "-1m 1CM 1mm - 1 FT + 6IN + 1yd", quantity: { magnitude: -0.24899999999999978, unitName: "Units.M" } }, ]; const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); for (const testEntry of testData) { const quantityProps = await Parser.parseIntoQuantity(testEntry.value, format, unitsProvider); @@ -587,7 +603,7 @@ describe("Parsing tests:", () => { const unitsProvider = new TestUnitsProvider(); const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); for (const testEntry of testData) { const quantityProps = await Parser.parseIntoQuantity(testEntry, format, unitsProvider); @@ -595,7 +611,6 @@ describe("Parsing tests:", () => { expect(quantityProps.magnitude).to.eql(0); } }); - }); describe("Synchronous Parsing tests:", async () => { @@ -615,7 +630,7 @@ describe("Synchronous Parsing tests:", async () => { composite: { includeZero: true, spacer: "-", - units: [{ label: "'", name: "Units.FT" }, { label: "\"", name: "Units.IN" }], + units: [{ label: "'", name: "Units.FT" }, { label: '"', name: "Units.IN" }], }, formatTraits: ["keepSingleZero", "showUnitLabel"], precision: 8, @@ -624,7 +639,7 @@ describe("Synchronous Parsing tests:", async () => { allowMathematicOperations: true, }; const format = new Format("test"); - await format.fromJSON(unitsProvider, formatData).catch(() => { }); + await format.fromJSON(unitsProvider, formatData).catch(() => {}); const parserSpec = await ParserSpec.create(format, unitsProvider, outUnit, unitsProvider); const formatSpec = await FormatterSpec.create("test", format, unitsProvider, outUnit); @@ -643,7 +658,7 @@ describe("Synchronous Parsing tests:", async () => { name: "Units.ARC_MINUTE", }, { - label: "\"", + label: '"', name: "Units.ARC_SECOND", }, ], @@ -656,7 +671,7 @@ describe("Synchronous Parsing tests:", async () => { }; const angleFormat = new Format("testAngle"); - await angleFormat.fromJSON(unitsProvider, angleFormatData).catch(() => { }); + await angleFormat.fromJSON(unitsProvider, angleFormatData).catch(() => {}); const outAngleUnit = await unitsProvider.findUnitByName("Units.ARC_DEG"); const angleParserSpec = await ParserSpec.create(angleFormat, unitsProvider, outAngleUnit, unitsProvider); const angleFormatSpec = await FormatterSpec.create("test", angleFormat, unitsProvider, outAngleUnit); @@ -664,9 +679,9 @@ describe("Synchronous Parsing tests:", async () => { it("Parse mathematic operations into quantity synchronously", () => { const testData = [ // When unitless, the format unit is used to determine unit. - { value: "12,345.345 - 1", magnitude: 3762.861156 - 0.3048}, - { value: "1yd + 2", magnitude: 0.9144 + 0.6096}, - { value: "1yd + 1m + 2", magnitude: 0.9144 + 1 + 0.6096}, + { value: "12,345.345 - 1", magnitude: 3762.861156 - 0.3048 }, + { value: "1yd + 2", magnitude: 0.9144 + 0.6096 }, + { value: "1yd + 1m + 2", magnitude: 0.9144 + 1 + 0.6096 }, { value: "1 FT + 6IN", magnitude: 0.45720000000000005 }, { value: "-1-1", magnitude: -0.6096 }, { value: "1 ' + 1 FT", magnitude: 0.6096 }, @@ -710,7 +725,7 @@ describe("Synchronous Parsing tests:", async () => { allowMathematicOperations: false, }; const formatMathNotAllowed = new Format("test"); - await formatMathNotAllowed.fromJSON(unitsProvider, formatDataMathNotAllowed).catch(() => { }); + await formatMathNotAllowed.fromJSON(unitsProvider, formatDataMathNotAllowed).catch(() => {}); const testData = [ "12,345.345 - 1", @@ -760,12 +775,12 @@ describe("Synchronous Parsing tests:", async () => { allowMathematicOperations: true, }; const formatUnitless = new Format("test"); - await formatUnitless.fromJSON(unitsProvider, formatDataUnitless).catch(() => { }); + await formatUnitless.fromJSON(unitsProvider, formatDataUnitless).catch(() => {}); const testData = [ - { value: "12,345.345 - 1", magnitude: 12345.345 - 1}, // unitless - { value: "1m + 1FT + 1", magnitude: 1 + 0.3048 + 1}, // default to meters - { value: "1FT + 1m + 1", magnitude: 0.3048 + 1 + 0.3048}, // default to feet + { value: "12,345.345 - 1", magnitude: 12345.345 - 1 }, // unitless + { value: "1m + 1FT + 1", magnitude: 1 + 0.3048 + 1 }, // default to meters + { value: "1FT + 1m + 1", magnitude: 0.3048 + 1 + 0.3048 }, // default to feet { value: "1 + 1 FT + 1m", magnitude: 0.3048 + 0.3048 + 1 }, // default to feet ]; @@ -927,5 +942,4 @@ describe("Synchronous Parsing tests:", async () => { } } }); - }); diff --git a/core/quantity/src/test/Ratio.test.ts b/core/quantity/src/test/Ratio.test.ts index c1940b33128d..dece90213872 100644 --- a/core/quantity/src/test/Ratio.test.ts +++ b/core/quantity/src/test/Ratio.test.ts @@ -2,9 +2,9 @@ import { assert, expect } from "chai"; import { Format } from "../Formatter/Format"; import { Formatter } from "../Formatter/Formatter"; +import { FormatProps, ParseError, Parser, ParserSpec, Quantity, QuantityError, UnitProps } from "../core-quantity"; import { FormatterSpec } from "../Formatter/FormatterSpec"; import { TestUnitsProvider } from "./TestUtils/TestHelper"; -import { FormatProps, ParseError, Parser, ParserSpec, Quantity, QuantityError, UnitProps } from "../core-quantity"; describe("Ratio format tests", () => { const vHUnitName = "Units.VERTICAL_PER_HORIZONTAL"; @@ -17,7 +17,12 @@ describe("Ratio format tests", () => { parseError?: ParseError; } - async function testRatioType(ratioType: string, testData: TestData[], presentationUnitStr: string = vHUnitName, persistenceUnitStr: string = vHUnitName) { + async function testRatioType( + ratioType: string, + testData: TestData[], + presentationUnitStr: string = vHUnitName, + persistenceUnitStr: string = vHUnitName, + ) { const defaultPrecision = 3; const ratioJson: FormatProps = { @@ -55,9 +60,15 @@ describe("Ratio format tests", () => { } if (null != entry.precision) - expect(parserRatioResult.value, `Parsed result for ${entry.ratio} from formatted ${entry.magnitude}`).closeTo(entry.magnitude, 4.999 * (0.1 ** entry.precision)); + expect(parserRatioResult.value, `Parsed result for ${entry.ratio} from formatted ${entry.magnitude}`).closeTo( + entry.magnitude, + 4.999 * (0.1 ** entry.precision), + ); else - expect(parserRatioResult.value, `Parsed result for ${entry.ratio} from formatted ${entry.magnitude}`).closeTo(entry.magnitude, 4.999 * (0.1 ** defaultPrecision)); + expect(parserRatioResult.value, `Parsed result for ${entry.ratio} from formatted ${entry.magnitude}`).closeTo( + entry.magnitude, + 4.999 * (0.1 ** defaultPrecision), + ); } } @@ -116,7 +127,6 @@ describe("Ratio format tests", () => { { magnitude: 0.2857, ratio: "143:500" }, { magnitude: 0.25, ratio: "1:4" }, { magnitude: 0.6667, ratio: "667:1000" }, - ]; await testRatioType("UseGreatestCommonDivisor", testData); }); @@ -132,11 +142,11 @@ describe("Ratio format tests", () => { { magnitude: 3, ratio: "1:0.333", precision: 3 }, { magnitude: 3, ratio: "1:0.3333", precision: 4 }, - { magnitude: 0.667, ratio: "1:1.49925", precision: 5}, - { magnitude: 0.667, ratio: "1:1.4993", precision: 4}, - { magnitude: 0.667, ratio: "1:1.499", precision: 3}, - { magnitude: 0.667, ratio: "1:1.5", precision: 2}, - { magnitude: 0.667, ratio: "1:1.5", precision: 1}, + { magnitude: 0.667, ratio: "1:1.49925", precision: 5 }, + { magnitude: 0.667, ratio: "1:1.4993", precision: 4 }, + { magnitude: 0.667, ratio: "1:1.499", precision: 3 }, + { magnitude: 0.667, ratio: "1:1.5", precision: 2 }, + { magnitude: 0.667, ratio: "1:1.5", precision: 1 }, ]; await testRatioType("OneToN", testData); }); @@ -160,7 +170,6 @@ describe("Ratio format tests", () => { ]; await testRatioType("ValueBased", testData); }); - }); describe("ratio formatting that should throw an error", () => { @@ -180,7 +189,7 @@ describe("Ratio format tests", () => { try { await ratioFormat.fromJSON(unitsProvider, ratioJson); expect.fail("Expected error was not thrown"); - } catch (e: any){ + } catch (e: any) { assert.strictEqual(e.message, "The Format Ratio is 'Ratio' type therefore the attribute 'ratioType' is required."); assert.instanceOf(e, QuantityError); } @@ -203,12 +212,11 @@ describe("Ratio format tests", () => { try { await ratioFormat.fromJSON(unitsProvider, ratioJson); expect.fail("Expected error was not thrown"); - } catch (e: any){ + } catch (e: any) { assert.strictEqual(e.message, "The Format Ratio has an invalid 'ratioType' attribute."); assert.instanceOf(e, QuantityError); } }); - }); describe("RatioType Tests with special values", () => { @@ -250,8 +258,8 @@ describe("Ratio format tests", () => { const testData: TestData[] = [ { magnitude: 1.0 / 7, ratio: "143:1000" }, { magnitude: 2.0 / 7, ratio: "143:500" }, // comes down from 286:1000 - { magnitude: 1.0 / 7, ratio: "1429:10000", precision: 4}, - { magnitude: 2.0 / 7, ratio: "2857:10000", precision: 4}, + { magnitude: 1.0 / 7, ratio: "1429:10000", precision: 4 }, + { magnitude: 2.0 / 7, ratio: "2857:10000", precision: 4 }, ]; await testRatioType("useGreatestCommonDivisor", testData); }); @@ -259,9 +267,10 @@ describe("Ratio format tests", () => { describe("specific parse ratio string tests", () => { async function testRatioParser( - testData: TestData[], presentationUnitStr: string = vHUnitName, persistenceUnitStr: string = vHUnitName, + testData: TestData[], + presentationUnitStr: string = vHUnitName, + persistenceUnitStr: string = vHUnitName, ) { - const ratioJson: FormatProps = { type: "Ratio", ratioType: "NToOne", @@ -296,7 +305,6 @@ describe("Ratio format tests", () => { expect(parserRatioResult.error).to.equal(entry.parseError); else assert.fail(`Expected parse error for input ratio string ${entry.ratio}`); - } else { if (!Parser.isParsedQuantity(parserRatioResult)) assert.fail(`Expected a parsed from ratio string ${entry.ratio}`); @@ -330,14 +338,13 @@ describe("Ratio format tests", () => { { magnitude: 1.0, ratio: "10:0", parseError: ParseError.MathematicOperationFoundButIsNotAllowed }, { magnitude: 1.0, ratio: "", parseError: ParseError.NoValueOrUnitFoundInString }, - { magnitude: 1.0, ratio: "1:", parseError: ParseError.NoValueOrUnitFoundInString}, - { magnitude: 1.0, ratio: "1:A", parseError: ParseError.NoValueOrUnitFoundInString}, + { magnitude: 1.0, ratio: "1:", parseError: ParseError.NoValueOrUnitFoundInString }, + { magnitude: 1.0, ratio: "1:A", parseError: ParseError.NoValueOrUnitFoundInString }, - { magnitude: 1.0, ratio: "1:2:3", parseError: ParseError.UnableToConvertParseTokensToQuantity}, + { magnitude: 1.0, ratio: "1:2:3", parseError: ParseError.UnableToConvertParseTokensToQuantity }, ]; await testRatioParser(testData); }); - }); describe("inverted unit tests", () => { @@ -403,10 +410,10 @@ describe("Ratio format tests", () => { const hV: UnitProps = await unitsProvider.findUnitByName("Units.HORIZONTAL_PER_VERTICAL"); assert.isTrue(hV.isValid); - const vphToVphFormatter = await FormatterSpec.create("vph_to_vph_formatter", vphRatioFormat, unitsProvider,vH); - const hpvToVphFormatter = await FormatterSpec.create("hvp_to_vph_formatter", vphRatioFormat, unitsProvider,hV); - const vphToHpvFormatter = await FormatterSpec.create("vph_to_hpv_formatter", hvpRatioFormat, unitsProvider,vH); - const hpvToHpvFormatter = await FormatterSpec.create("hpv_to_hpv_formatter", hvpRatioFormat, unitsProvider,hV); + const vphToVphFormatter = await FormatterSpec.create("vph_to_vph_formatter", vphRatioFormat, unitsProvider, vH); + const hpvToVphFormatter = await FormatterSpec.create("hvp_to_vph_formatter", vphRatioFormat, unitsProvider, hV); + const vphToHpvFormatter = await FormatterSpec.create("vph_to_hpv_formatter", hvpRatioFormat, unitsProvider, vH); + const hpvToHpvFormatter = await FormatterSpec.create("hpv_to_hpv_formatter", hvpRatioFormat, unitsProvider, hV); const vphToVphParser = await ParserSpec.create(vphRatioFormat, unitsProvider, vH); const hpvToVphParser = await ParserSpec.create(vphRatioFormat, unitsProvider, hV); diff --git a/core/quantity/src/test/TestUtils/TestHelper.ts b/core/quantity/src/test/TestUtils/TestHelper.ts index b7433300fc52..b3f352cb67e4 100644 --- a/core/quantity/src/test/TestUtils/TestHelper.ts +++ b/core/quantity/src/test/TestUtils/TestHelper.ts @@ -24,56 +24,344 @@ interface UnitDefinition { // cSpell:ignore MILLIINCH, MICROINCH, MILLIFOOT const unitData: UnitDefinition[] = [ // Angles ( base unit radian ) - { name: "Units.RAD", phenomenon: "Units.ANGLE", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "rad", altDisplayLabels: ["radian"] }, - { name: "Units.REVOLUTION", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 1.0, denominator: 6.283185307179586, offset: 0.0 }, displayLabel: "r", altDisplayLabels: ["rev"] }, + { + name: "Units.RAD", + phenomenon: "Units.ANGLE", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "rad", + altDisplayLabels: ["radian"], + }, + { + name: "Units.REVOLUTION", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 1.0, denominator: 6.283185307179586, offset: 0.0 }, + displayLabel: "r", + altDisplayLabels: ["rev"], + }, // 1 rad = 180.0/PI ° - { name: "Units.ARC_DEG", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 180.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "°", altDisplayLabels: ["deg", "^"] }, - { name: "Units.ARC_MINUTE", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 10800.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "'", altDisplayLabels: ["min"] }, - { name: "Units.ARC_SECOND", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 648000.0, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: '"', altDisplayLabels: ["sec"] }, - { name: "Units.GRAD", phenomenon: "Units.ANGLE", system: "Units.METRIC", conversion: { numerator: 200, denominator: 3.141592653589793, offset: 0.0 }, displayLabel: "grad", altDisplayLabels: ["gd"] }, + { + name: "Units.ARC_DEG", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 180.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "°", + altDisplayLabels: ["deg", "^"], + }, + { + name: "Units.ARC_MINUTE", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 10800.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "'", + altDisplayLabels: ["min"], + }, + { + name: "Units.ARC_SECOND", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 648000.0, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: '"', + altDisplayLabels: ["sec"], + }, + { + name: "Units.GRAD", + phenomenon: "Units.ANGLE", + system: "Units.METRIC", + conversion: { numerator: 200, denominator: 3.141592653589793, offset: 0.0 }, + displayLabel: "grad", + altDisplayLabels: ["gd"], + }, // Time ( base unit second ) - { name: "Units.S", phenomenon: "Units.TIME", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "s", altDisplayLabels: ["sec"] }, - { name: "Units.MIN", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 60.0, offset: 0.0 }, displayLabel: "min", altDisplayLabels: [] }, - { name: "Units.HR", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 3600.0, offset: 0.0 }, displayLabel: "h", altDisplayLabels: ["hr"] }, - { name: "Units.DAY", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 86400.0, offset: 0.0 }, displayLabel: "days", altDisplayLabels: ["day"] }, - { name: "Units.WEEK", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 604800.0, offset: 0.0 }, displayLabel: "weeks", altDisplayLabels: ["week"] }, + { + name: "Units.S", + phenomenon: "Units.TIME", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "s", + altDisplayLabels: ["sec"], + }, + { + name: "Units.MIN", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 60.0, offset: 0.0 }, + displayLabel: "min", + altDisplayLabels: [], + }, + { + name: "Units.HR", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 3600.0, offset: 0.0 }, + displayLabel: "h", + altDisplayLabels: ["hr"], + }, + { + name: "Units.DAY", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 86400.0, offset: 0.0 }, + displayLabel: "days", + altDisplayLabels: ["day"], + }, + { + name: "Units.WEEK", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 604800.0, offset: 0.0 }, + displayLabel: "weeks", + altDisplayLabels: ["week"], + }, // 1 sec = 1/31536000.0 yr - { name: "Units.YR", phenomenon: "Units.TIME", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 31536000.0, offset: 0.0 }, displayLabel: "years", altDisplayLabels: ["year"] }, + { + name: "Units.YR", + phenomenon: "Units.TIME", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 31536000.0, offset: 0.0 }, + displayLabel: "years", + altDisplayLabels: ["year"], + }, // conversion => specified unit to base unit of m - { name: "Units.M", phenomenon: "Units.LENGTH", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m", altDisplayLabels: ["meter"] }, - { name: "Units.MM", phenomenon: "Units.LENGTH", system: "Units.INTERNATIONAL", conversion: { numerator: 1000.0, denominator: 1.0, offset: 0.0 }, displayLabel: "mm", altDisplayLabels: ["MM"] }, - { name: "Units.CM", phenomenon: "Units.LENGTH", system: "Units.INTERNATIONAL", conversion: { numerator: 100.0, denominator: 1.0, offset: 0.0 }, displayLabel: "cm", altDisplayLabels: ["CM"] }, - { name: "Units.DM", phenomenon: "Units.LENGTH", system: "Units.INTERNATIONAL", conversion: { numerator: 10.0, denominator: 1.0, offset: 0.0 }, displayLabel: "dm", altDisplayLabels: ["DM"] }, - { name: "Units.KM", phenomenon: "Units.LENGTH", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 1000.0, offset: 0.0 }, displayLabel: "km", altDisplayLabels: ["KM"] }, - { name: "Units.UM", phenomenon: "Units.LENGTH", system: "Units.INTERNATIONAL", conversion: { numerator: 1000000.0, denominator: 1.0, offset: 0.0 }, displayLabel: "µm", altDisplayLabels: [] }, - { name: "Units.MILLIINCH", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "mil", altDisplayLabels: [] }, - { name: "Units.MICROINCH", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000000.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "µin", altDisplayLabels: [] }, - { name: "Units.MILLIFOOT", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1000.0, denominator: 0.3048, offset: 0.0 }, displayLabel: "mft", altDisplayLabels: [] }, - { name: "Units.IN", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.0 }, displayLabel: "in", altDisplayLabels: ["IN", "\""] }, - { name: "Units.FT", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.3048, offset: 0.0 }, displayLabel: "ft", altDisplayLabels: ["F", "FT", "'"] }, - { name: "Units.CHAIN", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 66.0 * 0.3048, offset: 0.0 }, displayLabel: "chain", altDisplayLabels: ["CHAIN"] }, - { name: "Units.YRD", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.9144, offset: 0.0 }, displayLabel: "yd", altDisplayLabels: ["YRD", "yrd"] }, - { name: "Units.MILE", phenomenon: "Units.LENGTH", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 1609.344, offset: 0.0 }, displayLabel: "mi", altDisplayLabels: ["mile", "Miles", "Mile"] }, - - { name: "Units.BOGUS.IN", phenomenon: "Units.LENGTH", system: "Units.BOBUS", conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.025 }, displayLabel: "bi", altDisplayLabels: [] }, - - { name: "Units.US_SURVEY_FT", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 1200.0, offset: 0.0 }, displayLabel: "ft (US Survey)", altDisplayLabels: ["ft", "SF", "USF", "ft (US Survey)"] }, - { name: "Units.US_SURVEY_YRD", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 3.0 * 1200.0, offset: 0.0 }, displayLabel: "yrd (US Survey)", altDisplayLabels: ["USY", "yards (US Survey)"] }, - { name: "Units.US_SURVEY_IN", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 100.0, offset: 0.0 }, displayLabel: "in (US Survey)", altDisplayLabels: ["USI", "inches (US Survey)"] }, - { name: "Units.US_SURVEY_MILE", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 3937.0, denominator: 5280.0 * 1200.0, offset: 0.0 }, displayLabel: "mi (US Survey)", altDisplayLabels: ["miles (US Survey)", "mile (US Survey)", "USM"] }, - { name: "Units.US_SURVEY_CHAIN", phenomenon: "Units.LENGTH", system: "Units.USSURVEY", conversion: { numerator: 1.0, denominator: 20.11684, offset: 0.0 }, displayLabel: "chain (US Survey)", altDisplayLabels: ["chains (US Survey)"] }, + { + name: "Units.M", + phenomenon: "Units.LENGTH", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m", + altDisplayLabels: ["meter"], + }, + { + name: "Units.MM", + phenomenon: "Units.LENGTH", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1000.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "mm", + altDisplayLabels: ["MM"], + }, + { + name: "Units.CM", + phenomenon: "Units.LENGTH", + system: "Units.INTERNATIONAL", + conversion: { numerator: 100.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "cm", + altDisplayLabels: ["CM"], + }, + { + name: "Units.DM", + phenomenon: "Units.LENGTH", + system: "Units.INTERNATIONAL", + conversion: { numerator: 10.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "dm", + altDisplayLabels: ["DM"], + }, + { + name: "Units.KM", + phenomenon: "Units.LENGTH", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 1000.0, offset: 0.0 }, + displayLabel: "km", + altDisplayLabels: ["KM"], + }, + { + name: "Units.UM", + phenomenon: "Units.LENGTH", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1000000.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "µm", + altDisplayLabels: [], + }, + { + name: "Units.MILLIINCH", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "mil", + altDisplayLabels: [], + }, + { + name: "Units.MICROINCH", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000000.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "µin", + altDisplayLabels: [], + }, + { + name: "Units.MILLIFOOT", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1000.0, denominator: 0.3048, offset: 0.0 }, + displayLabel: "mft", + altDisplayLabels: [], + }, + { + name: "Units.IN", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.0 }, + displayLabel: "in", + altDisplayLabels: ["IN", '"'], + }, + { + name: "Units.FT", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.3048, offset: 0.0 }, + displayLabel: "ft", + altDisplayLabels: ["F", "FT", "'"], + }, + { + name: "Units.CHAIN", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 66.0 * 0.3048, offset: 0.0 }, + displayLabel: "chain", + altDisplayLabels: ["CHAIN"], + }, + { + name: "Units.YRD", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.9144, offset: 0.0 }, + displayLabel: "yd", + altDisplayLabels: ["YRD", "yrd"], + }, + { + name: "Units.MILE", + phenomenon: "Units.LENGTH", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 1609.344, offset: 0.0 }, + displayLabel: "mi", + altDisplayLabels: ["mile", "Miles", "Mile"], + }, + + { + name: "Units.BOGUS.IN", + phenomenon: "Units.LENGTH", + system: "Units.BOBUS", + conversion: { numerator: 1.0, denominator: 0.0254, offset: 0.025 }, + displayLabel: "bi", + altDisplayLabels: [], + }, + + { + name: "Units.US_SURVEY_FT", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 1200.0, offset: 0.0 }, + displayLabel: "ft (US Survey)", + altDisplayLabels: ["ft", "SF", "USF", "ft (US Survey)"], + }, + { + name: "Units.US_SURVEY_YRD", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 3.0 * 1200.0, offset: 0.0 }, + displayLabel: "yrd (US Survey)", + altDisplayLabels: ["USY", "yards (US Survey)"], + }, + { + name: "Units.US_SURVEY_IN", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 100.0, offset: 0.0 }, + displayLabel: "in (US Survey)", + altDisplayLabels: ["USI", "inches (US Survey)"], + }, + { + name: "Units.US_SURVEY_MILE", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 3937.0, denominator: 5280.0 * 1200.0, offset: 0.0 }, + displayLabel: "mi (US Survey)", + altDisplayLabels: ["miles (US Survey)", "mile (US Survey)", "USM"], + }, + { + name: "Units.US_SURVEY_CHAIN", + phenomenon: "Units.LENGTH", + system: "Units.USSURVEY", + conversion: { numerator: 1.0, denominator: 20.11684, offset: 0.0 }, + displayLabel: "chain (US Survey)", + altDisplayLabels: ["chains (US Survey)"], + }, // conversion => specified unit to base unit of m² - { name: "Units.SQ_FT", phenomenon: "Units.AREA", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: .09290304, offset: 0.0 }, displayLabel: "ft²", altDisplayLabels: ["sf"] }, - { name: "Units.SQ_US_SURVEY_FT", phenomenon: "Units.AREA", system: "Units.USCUSTOM", conversion: { numerator: 15499969.0, denominator: 1440000, offset: 0.0 }, displayLabel: "ft² (US Survey)", altDisplayLabels: ["sussf"] }, - { name: "Units.SQ_M", phenomenon: "Units.AREA", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m²", altDisplayLabels: ["sm"] }, + { + name: "Units.SQ_FT", + phenomenon: "Units.AREA", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: .09290304, offset: 0.0 }, + displayLabel: "ft²", + altDisplayLabels: ["sf"], + }, + { + name: "Units.SQ_US_SURVEY_FT", + phenomenon: "Units.AREA", + system: "Units.USCUSTOM", + conversion: { numerator: 15499969.0, denominator: 1440000, offset: 0.0 }, + displayLabel: "ft² (US Survey)", + altDisplayLabels: ["sussf"], + }, + { + name: "Units.SQ_M", + phenomenon: "Units.AREA", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m²", + altDisplayLabels: ["sm"], + }, // conversion => specified unit to base unit m³ - { name: "Units.CUB_FT", phenomenon: "Units.VOLUME", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.028316847, offset: 0.0 }, displayLabel: "ft³", altDisplayLabels: ["cf"] }, - { name: "Units.CUB_US_SURVEY_FT", phenomenon: "Units.VOLUME", system: "Units.USSURVEY", conversion: { numerator: 1, denominator: 0.0283170164937591, offset: 0.0 }, displayLabel: "ft³", altDisplayLabels: ["cf"] }, - { name: "Units.CUB_YRD", phenomenon: "Units.VOLUME", system: "Units.USCUSTOM", conversion: { numerator: 1.0, denominator: 0.76455486, offset: 0.0 }, displayLabel: "yd³", altDisplayLabels: ["cy"] }, - { name: "Units.CUB_M", phenomenon: "Units.VOLUME", system: "Units.SI", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "m³", altDisplayLabels: ["cm"] }, + { + name: "Units.CUB_FT", + phenomenon: "Units.VOLUME", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.028316847, offset: 0.0 }, + displayLabel: "ft³", + altDisplayLabels: ["cf"], + }, + { + name: "Units.CUB_US_SURVEY_FT", + phenomenon: "Units.VOLUME", + system: "Units.USSURVEY", + conversion: { numerator: 1, denominator: 0.0283170164937591, offset: 0.0 }, + displayLabel: "ft³", + altDisplayLabels: ["cf"], + }, + { + name: "Units.CUB_YRD", + phenomenon: "Units.VOLUME", + system: "Units.USCUSTOM", + conversion: { numerator: 1.0, denominator: 0.76455486, offset: 0.0 }, + displayLabel: "yd³", + altDisplayLabels: ["cy"], + }, + { + name: "Units.CUB_M", + phenomenon: "Units.VOLUME", + system: "Units.SI", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "m³", + altDisplayLabels: ["cm"], + }, - { name: "Units.VERTICAL_PER_HORIZONTAL", phenomenon: "Units.SLOPE", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, displayLabel: "ft/ft", altDisplayLabels: ["ft/ft"] }, - { name: "Units.HORIZONTAL_PER_VERTICAL", phenomenon: "Units.SLOPE", system: "Units.INTERNATIONAL", conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, isInverted: true, displayLabel: "m/m", altDisplayLabels: ["m/m"] }, + { + name: "Units.VERTICAL_PER_HORIZONTAL", + phenomenon: "Units.SLOPE", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + displayLabel: "ft/ft", + altDisplayLabels: ["ft/ft"], + }, + { + name: "Units.HORIZONTAL_PER_VERTICAL", + phenomenon: "Units.SLOPE", + system: "Units.INTERNATIONAL", + conversion: { numerator: 1.0, denominator: 1.0, offset: 0.0 }, + isInverted: true, + displayLabel: "m/m", + altDisplayLabels: ["m/m"], + }, ]; export class ConversionData implements UnitConversionProps { @@ -176,5 +464,4 @@ export class TestUnitsProvider implements UnitsProvider, AlternateUnitLabelsProv const unitDefinition = this.findUnitDefinition(unit.name); return unitDefinition?.altDisplayLabels; } - } diff --git a/core/telemetry/certa.json b/core/telemetry/certa.json index 46719abb220e..7027377b08d1 100644 --- a/core/telemetry/certa.json +++ b/core/telemetry/certa.json @@ -21,4 +21,4 @@ "--no-sandbox" ] } -} \ No newline at end of file +} diff --git a/core/telemetry/eslint.config.js b/core/telemetry/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/telemetry/eslint.config.js +++ b/core/telemetry/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/telemetry/src/TelemetryClient.ts b/core/telemetry/src/TelemetryClient.ts index 898d71eee3e3..35cb0dfeb9b7 100644 --- a/core/telemetry/src/TelemetryClient.ts +++ b/core/telemetry/src/TelemetryClient.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. diff --git a/core/webgl-compatibility/certa.json b/core/webgl-compatibility/certa.json index e96220d5beee..d0166c15d178 100644 --- a/core/webgl-compatibility/certa.json +++ b/core/webgl-compatibility/certa.json @@ -16,11 +16,11 @@ "chromeOptions": { "publicDirs": [ "src/public", - "src/test/public", + "src/test/public" ], "args": [ "--disable-web-security", "--no-sandbox" ] } -} \ No newline at end of file +} diff --git a/core/webgl-compatibility/eslint.config.js b/core/webgl-compatibility/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/core/webgl-compatibility/eslint.config.js +++ b/core/webgl-compatibility/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/core/webgl-compatibility/src/Capabilities.ts b/core/webgl-compatibility/src/Capabilities.ts index 9caf46a96e2f..ca545a98842f 100644 --- a/core/webgl-compatibility/src/Capabilities.ts +++ b/core/webgl-compatibility/src/Capabilities.ts @@ -7,16 +7,28 @@ */ import { ProcessDetector } from "@itwin/core-bentley"; -import { - GraphicsDriverBugs, WebGLContext, WebGLFeature, WebGLRenderCompatibilityInfo, WebGLRenderCompatibilityStatus, -} from "./RenderCompatibility"; +import { GraphicsDriverBugs, WebGLContext, WebGLFeature, WebGLRenderCompatibilityInfo, WebGLRenderCompatibilityStatus } from "./RenderCompatibility"; /** @internal */ export type WebGLExtensionName = - "WEBGL_draw_buffers" | "OES_element_index_uint" | "OES_texture_float" | "OES_texture_float_linear" | - "OES_texture_half_float" | "OES_texture_half_float_linear" | "EXT_texture_filter_anisotropic" | "WEBGL_depth_texture" | - "EXT_color_buffer_float" | "EXT_shader_texture_lod" | "ANGLE_instanced_arrays" | "OES_vertex_array_object" | "WEBGL_lose_context" | - "EXT_frag_depth" | "EXT_disjoint_timer_query" | "EXT_disjoint_timer_query_webgl2" | "OES_standard_derivatives" | "EXT_float_blend"; + | "WEBGL_draw_buffers" + | "OES_element_index_uint" + | "OES_texture_float" + | "OES_texture_float_linear" + | "OES_texture_half_float" + | "OES_texture_half_float_linear" + | "EXT_texture_filter_anisotropic" + | "WEBGL_depth_texture" + | "EXT_color_buffer_float" + | "EXT_shader_texture_lod" + | "ANGLE_instanced_arrays" + | "OES_vertex_array_object" + | "WEBGL_lose_context" + | "EXT_frag_depth" + | "EXT_disjoint_timer_query" + | "EXT_disjoint_timer_query_webgl2" + | "OES_standard_derivatives" + | "EXT_float_blend"; const knownExtensions: WebGLExtensionName[] = [ "WEBGL_draw_buffers", @@ -54,11 +66,11 @@ export enum RenderType { * @internal */ export enum DepthType { - RenderBufferUnsignedShort16, // core to WebGL1 + RenderBufferUnsignedShort16, // core to WebGL1 // TextureUnsignedShort16, // core to WebGL2; available to WebGL1 via WEBGL_depth_texture // TextureUnsignedInt24, // core to WebGL2 - TextureUnsignedInt24Stencil8, // core to WebGL2; available to WebGL1 via WEBGL_depth_texture - TextureUnsignedInt32, // core to WebGL2; available to WebGL1 via WEBGL_depth_texture + TextureUnsignedInt24Stencil8, // core to WebGL2; available to WebGL1 via WEBGL_depth_texture + TextureUnsignedInt32, // core to WebGL2; available to WebGL1 via WEBGL_depth_texture // TextureFloat32, // core to WebGL2 // TextureFloat32Stencil8, // core to WeBGL2 } @@ -87,7 +99,7 @@ const integratedIntelGpuMatchers = [ /Iris/, ]; -function isIntegratedGraphics(args: {unmaskedVendor?: string, unmaskedRenderer?: string}): boolean { +function isIntegratedGraphics(args: { unmaskedVendor?: string, unmaskedRenderer?: string }): boolean { if (args.unmaskedRenderer && args.unmaskedRenderer.includes("Intel") && integratedIntelGpuMatchers.some((x) => x.test(args.unmaskedRenderer!))) return true; @@ -124,49 +136,118 @@ export class Capabilities { private _isMobile: boolean = false; private _driverBugs: GraphicsDriverBugs = {}; - public get maxRenderType(): RenderType { return this._maxRenderType; } - public get maxDepthType(): DepthType { return this._maxDepthType; } - public get maxTextureSize(): number { return this._maxTextureSize; } - public get maxTexSizeAllow(): number { return this._maxTexSizeAllow; } - public get supportsCreateImageBitmap(): boolean { return this._supportsCreateImageBitmap; } - public get maxColorAttachments(): number { return this._maxColorAttachments; } - public get maxDrawBuffers(): number { return this._maxDrawBuffers; } - public get maxFragTextureUnits(): number { return this._maxFragTextureUnits; } - public get maxVertTextureUnits(): number { return this._maxVertTextureUnits; } - public get maxVertAttribs(): number { return this._maxVertAttribs; } - public get maxVertUniformVectors(): number { return this._maxVertUniformVectors; } - public get maxVaryingVectors(): number { return this._maxVaryingVectors; } - public get maxFragUniformVectors(): number { return this._maxFragUniformVectors; } - public get maxAntialiasSamples(): number { return this._maxAntialiasSamples; } - public get isWebGL2(): boolean { return this._isWebGL2; } - public get driverBugs(): GraphicsDriverBugs { return this._driverBugs; } + public get maxRenderType(): RenderType { + return this._maxRenderType; + } + public get maxDepthType(): DepthType { + return this._maxDepthType; + } + public get maxTextureSize(): number { + return this._maxTextureSize; + } + public get maxTexSizeAllow(): number { + return this._maxTexSizeAllow; + } + public get supportsCreateImageBitmap(): boolean { + return this._supportsCreateImageBitmap; + } + public get maxColorAttachments(): number { + return this._maxColorAttachments; + } + public get maxDrawBuffers(): number { + return this._maxDrawBuffers; + } + public get maxFragTextureUnits(): number { + return this._maxFragTextureUnits; + } + public get maxVertTextureUnits(): number { + return this._maxVertTextureUnits; + } + public get maxVertAttribs(): number { + return this._maxVertAttribs; + } + public get maxVertUniformVectors(): number { + return this._maxVertUniformVectors; + } + public get maxVaryingVectors(): number { + return this._maxVaryingVectors; + } + public get maxFragUniformVectors(): number { + return this._maxFragUniformVectors; + } + public get maxAntialiasSamples(): number { + return this._maxAntialiasSamples; + } + public get isWebGL2(): boolean { + return this._isWebGL2; + } + public get driverBugs(): GraphicsDriverBugs { + return this._driverBugs; + } /** These getters check for existence of extension objects to determine availability of features. In WebGL2, could just return true for some. */ - public get supportsNonPowerOf2Textures(): boolean { return false; } - public get supportsDrawBuffers(): boolean { return this._isWebGL2 || this.queryExtensionObject("WEBGL_draw_buffers") !== undefined; } - public get supportsInstancing(): boolean { return this._isWebGL2 || this.queryExtensionObject("ANGLE_instanced_arrays") !== undefined; } - public get supports32BitElementIndex(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_element_index_uint") !== undefined; } - public get supportsTextureFloat(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_texture_float") !== undefined; } - public get supportsTextureFloatLinear(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_texture_float_linear") !== undefined; } - public get supportsTextureHalfFloat(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_texture_half_float") !== undefined; } - public get supportsTextureHalfFloatLinear(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_texture_half_float_linear") !== undefined; } - public get supportsTextureFilterAnisotropic(): boolean { return this.queryExtensionObject("EXT_texture_filter_anisotropic") !== undefined; } - public get supportsShaderTextureLOD(): boolean { return this._isWebGL2 || this.queryExtensionObject("EXT_shader_texture_lod") !== undefined; } - public get supportsVertexArrayObjects(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_vertex_array_object") !== undefined; } - public get supportsFragDepth(): boolean { return this._isWebGL2 || this.queryExtensionObject("EXT_frag_depth") !== undefined; } - public get supportsDisjointTimerQuery(): boolean { return (this._isWebGL2 && this.queryExtensionObject("EXT_disjoint_timer_query_webgl2") !== undefined) || this.queryExtensionObject("EXT_disjoint_timer_query") !== undefined; } - public get supportsStandardDerivatives(): boolean { return this._isWebGL2 || this.queryExtensionObject("OES_standard_derivatives") !== undefined; } - - public get supportsMRTTransparency(): boolean { return this.maxColorAttachments >= 2; } - public get supportsMRTPickShaders(): boolean { return this.maxColorAttachments >= 3; } + public get supportsNonPowerOf2Textures(): boolean { + return false; + } + public get supportsDrawBuffers(): boolean { + return this._isWebGL2 || this.queryExtensionObject("WEBGL_draw_buffers") !== undefined; + } + public get supportsInstancing(): boolean { + return this._isWebGL2 || this.queryExtensionObject("ANGLE_instanced_arrays") !== undefined; + } + public get supports32BitElementIndex(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_element_index_uint") !== undefined; + } + public get supportsTextureFloat(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_texture_float") !== undefined; + } + public get supportsTextureFloatLinear(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_texture_float_linear") !== undefined; + } + public get supportsTextureHalfFloat(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_texture_half_float") !== undefined; + } + public get supportsTextureHalfFloatLinear(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_texture_half_float_linear") !== undefined; + } + public get supportsTextureFilterAnisotropic(): boolean { + return this.queryExtensionObject("EXT_texture_filter_anisotropic") !== undefined; + } + public get supportsShaderTextureLOD(): boolean { + return this._isWebGL2 || this.queryExtensionObject("EXT_shader_texture_lod") !== undefined; + } + public get supportsVertexArrayObjects(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_vertex_array_object") !== undefined; + } + public get supportsFragDepth(): boolean { + return this._isWebGL2 || this.queryExtensionObject("EXT_frag_depth") !== undefined; + } + public get supportsDisjointTimerQuery(): boolean { + return (this._isWebGL2 && this.queryExtensionObject("EXT_disjoint_timer_query_webgl2") !== undefined) || + this.queryExtensionObject("EXT_disjoint_timer_query") !== undefined; + } + public get supportsStandardDerivatives(): boolean { + return this._isWebGL2 || this.queryExtensionObject("OES_standard_derivatives") !== undefined; + } + + public get supportsMRTTransparency(): boolean { + return this.maxColorAttachments >= 2; + } + public get supportsMRTPickShaders(): boolean { + return this.maxColorAttachments >= 3; + } public get supportsShadowMaps(): boolean { return this.supportsTextureFloat || this.supportsTextureHalfFloat; } - public get supportsAntiAliasing(): boolean { return this._isWebGL2 && this.maxAntialiasSamples > 1; } + public get supportsAntiAliasing(): boolean { + return this._isWebGL2 && this.maxAntialiasSamples > 1; + } - public get isMobile(): boolean { return this._isMobile; } + public get isMobile(): boolean { + return this._isMobile; + } private findExtension(name: WebGLExtensionName): any { const ext = this._extensionMap[name]; @@ -194,7 +275,9 @@ export class Capabilities { WebGLFeature.MinimalTextureUnits, ]; - private get _hasRequiredTextureUnits(): boolean { return this.maxFragTextureUnits >= 4 && this.maxVertTextureUnits >= 5; } + private get _hasRequiredTextureUnits(): boolean { + return this.maxFragTextureUnits >= 4 && this.maxVertTextureUnits >= 5; + } /** Return an array containing any features not supported by the system as compared to the input array. */ private _findMissingFeatures(featuresToSeek: WebGLFeature[]): WebGLFeature[] { @@ -305,8 +388,7 @@ export class Capabilities { } // Determine the maximum color-renderable attachment type. - const allowFloatRender = - (undefined === disabledExtensions || -1 === disabledExtensions.indexOf("OES_texture_float")) + const allowFloatRender = (undefined === disabledExtensions || -1 === disabledExtensions.indexOf("OES_texture_float")) // iOS>=15 allows full-float rendering. However, it does not actually work on non-M1 devices. // Because of this, for now we disallow full float rendering on iOS devices. // ###TODO: Re-assess this after future iOS updates. @@ -320,15 +402,21 @@ export class Capabilities { if (allowFloatRender && undefined !== this.queryExtensionObject("EXT_float_blend") && this.isTextureRenderable(gl, gl.FLOAT)) { this._maxRenderType = RenderType.TextureFloat; } else if (this.isWebGL2) { - this._maxRenderType = (this.isTextureRenderable(gl, (gl as WebGL2RenderingContext).HALF_FLOAT)) ? RenderType.TextureHalfFloat : RenderType.TextureUnsignedByte; + this._maxRenderType = (this.isTextureRenderable(gl, (gl as WebGL2RenderingContext).HALF_FLOAT)) + ? RenderType.TextureHalfFloat + : RenderType.TextureUnsignedByte; } else { const hfExt: OES_texture_half_float | undefined = this.queryExtensionObject("OES_texture_half_float"); - this._maxRenderType = (hfExt !== undefined && this.isTextureRenderable(gl, hfExt.HALF_FLOAT_OES)) ? RenderType.TextureHalfFloat : RenderType.TextureUnsignedByte; + this._maxRenderType = (hfExt !== undefined && this.isTextureRenderable(gl, hfExt.HALF_FLOAT_OES)) + ? RenderType.TextureHalfFloat + : RenderType.TextureUnsignedByte; } // Determine the maximum depth attachment type. // this._maxDepthType = this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt32 : DepthType.RenderBufferUnsignedShort16; - this._maxDepthType = this._isWebGL2 || this.queryExtensionObject("WEBGL_depth_texture") !== undefined ? DepthType.TextureUnsignedInt24Stencil8 : DepthType.RenderBufferUnsignedShort16; + this._maxDepthType = this._isWebGL2 || this.queryExtensionObject("WEBGL_depth_texture") !== undefined + ? DepthType.TextureUnsignedInt24Stencil8 + : DepthType.RenderBufferUnsignedShort16; this._presentFeatures = this._gatherFeatures(); const missingRequiredFeatures = this._findMissingFeatures(Capabilities.requiredFeatures); @@ -340,7 +428,7 @@ export class Capabilities { missingOptionalFeatures, unmaskedRenderer, unmaskedVendor, - usingIntegratedGraphics: isIntegratedGraphics({unmaskedVendor, unmaskedRenderer}), + usingIntegratedGraphics: isIntegratedGraphics({ unmaskedVendor, unmaskedRenderer }), driverBugs: { ...this._driverBugs }, userAgent: navigator.userAgent, createdContext: gl, @@ -350,7 +438,10 @@ export class Capabilities { public static create(gl: WebGLContext, disabledExtensions?: WebGLExtensionName[]): Capabilities | undefined { const caps = new Capabilities(); const compatibility = caps.init(gl, disabledExtensions); - if (WebGLRenderCompatibilityStatus.CannotCreateContext === compatibility.status || WebGLRenderCompatibilityStatus.MissingRequiredFeatures === compatibility.status) + if ( + WebGLRenderCompatibilityStatus.CannotCreateContext === compatibility.status || + WebGLRenderCompatibilityStatus.MissingRequiredFeatures === compatibility.status + ) return undefined; return caps; } diff --git a/core/webgl-compatibility/src/RenderCompatibility.ts b/core/webgl-compatibility/src/RenderCompatibility.ts index 1ca4b846dae4..dbb3cc158da8 100644 --- a/core/webgl-compatibility/src/RenderCompatibility.ts +++ b/core/webgl-compatibility/src/RenderCompatibility.ts @@ -129,7 +129,11 @@ export interface WebGLRenderCompatibilityInfo { /** A function that creates and returns a WebGLContext given an HTMLCanvasElement, a boolean specifying whether to use WebGL2, and a WebGLContextAttributes object describing the desired context attributes. * @public */ -export type ContextCreator = (canvas: HTMLCanvasElement, useWebGL2: boolean, inputContextAttributes?: WebGLContextAttributes) => WebGLContext | undefined; +export type ContextCreator = ( + canvas: HTMLCanvasElement, + useWebGL2: boolean, + inputContextAttributes?: WebGLContextAttributes, +) => WebGLContext | undefined; function createDefaultContext(canvas: HTMLCanvasElement, useWebGL2: boolean = true, attributes?: WebGLContextAttributes): WebGLContext | undefined { let context = useWebGL2 ? canvas.getContext("webgl2", attributes) : canvas.getContext("webgl", attributes); @@ -148,7 +152,13 @@ function createDefaultContext(canvas: HTMLCanvasElement, useWebGL2: boolean = tr export function queryRenderCompatibility(useWebGL2: boolean, createContext?: ContextCreator): WebGLRenderCompatibilityInfo { const canvas = document.createElement("canvas"); if (null === canvas) - return { status: WebGLRenderCompatibilityStatus.CannotCreateContext, missingOptionalFeatures: [], missingRequiredFeatures: [], userAgent: navigator.userAgent, driverBugs: { } }; + return { + status: WebGLRenderCompatibilityStatus.CannotCreateContext, + missingOptionalFeatures: [], + missingRequiredFeatures: [], + userAgent: navigator.userAgent, + driverBugs: {}, + }; let errorMessage: string | undefined; canvas.addEventListener("webglcontextcreationerror", (event) => { diff --git a/core/webgl-compatibility/src/test/Compatibility.test.ts b/core/webgl-compatibility/src/test/Compatibility.test.ts index 1e10142adc54..1a7aca68de92 100644 --- a/core/webgl-compatibility/src/test/Compatibility.test.ts +++ b/core/webgl-compatibility/src/test/Compatibility.test.ts @@ -4,9 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { Capabilities } from "../Capabilities"; -import { - queryRenderCompatibility, WebGLContext, WebGLFeature, WebGLRenderCompatibilityStatus, -} from "../RenderCompatibility"; +import { queryRenderCompatibility, WebGLContext, WebGLFeature, WebGLRenderCompatibilityStatus } from "../RenderCompatibility"; let createContext = (canvas: HTMLCanvasElement, useWebGL2: boolean, contextAttributes?: WebGLContextAttributes): WebGLContext | undefined => { let context = useWebGL2 ? canvas.getContext("webgl2", contextAttributes) : canvas.getContext("webgl", contextAttributes); @@ -156,43 +154,43 @@ describe("Render Compatibility", () => { it("detects early Z culling driver bug", () => { const renderers = [ - [ "ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel(R) HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", false ], + ["ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel(R) HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel(R) UHD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", false], // Bug only confirmed on 620 and 630 - [ "ANGLE (Intel(R) HD Graphics 610 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) HD Graphics 610 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) HD Graphics 615 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) HD Graphics 500 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) UHD Graphics 520 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) UHD Graphics 615 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) UHD Graphics 500 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "ANGLE (Intel(R) UHD Graphics 520 Direct3D11 vs_5_0 ps_5_0)", false ], + ["ANGLE (Intel(R) HD Graphics 610 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) HD Graphics 610 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) HD Graphics 615 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) HD Graphics 500 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) UHD Graphics 520 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) UHD Graphics 615 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) UHD Graphics 500 Direct3D11 vs_5_0 ps_5_0)", false], + ["ANGLE (Intel(R) UHD Graphics 520 Direct3D11 vs_5_0 ps_5_0)", false], // Bug only confirmed for Direct3D11; if Direct3D11 not present, we're not on Windows or using a different renderer. - [ "ANGLE (Intel(R) HD Graphics 630)", false ], - [ "ANGLE (Intel(R) UHD Graphics 630)", false ], - [ "ANGLE (Intel(R) HD Graphics 620)", false ], - [ "ANGLE (Intel(R) UHD Graphics 620)", false ], - [ "ANGLE (Intel HD Graphics 620)", false ], - [ "ANGLE (Intel(R) UHD Graphics 610)", false ], + ["ANGLE (Intel(R) HD Graphics 630)", false], + ["ANGLE (Intel(R) UHD Graphics 630)", false], + ["ANGLE (Intel(R) HD Graphics 620)", false], + ["ANGLE (Intel(R) UHD Graphics 620)", false], + ["ANGLE (Intel HD Graphics 620)", false], + ["ANGLE (Intel(R) UHD Graphics 610)", false], // Bug only confirmed on Windows; if ANGLE not present, we're not running on Windows. - [ "Intel(R) HD Graphics 630", false ], - [ "Intel(R) UHD Graphics 630", false ], - [ "Intel(R) HD Graphics 620", false ], - [ "Intel(R) UHD Graphics 620", false ], - [ "Intel HD Graphics 620", false ], - [ "Intel(R) UHD Graphics 610", false ], + ["Intel(R) HD Graphics 630", false], + ["Intel(R) UHD Graphics 630", false], + ["Intel(R) HD Graphics 620", false], + ["Intel(R) UHD Graphics 620", false], + ["Intel HD Graphics 620", false], + ["Intel(R) UHD Graphics 610", false], - [ "ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false ], + ["ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false], // Around October 2021 slightly different unmasked renderer strings began showing up, containing "Intel, Intel(R)" instead of just "Intel(R)". - [ "ANGLE (Intel, Intel(R) HD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11-27.20.100.8681)", true ], - [ "ANGLE (Intel, Intel(R) UHD Graphics 630 Direct3D11", true ], + ["ANGLE (Intel, Intel(R) HD Graphics 620 Direct3D11 vs_5_0 ps_5_0, D3D11-27.20.100.8681)", true], + ["ANGLE (Intel, Intel(R) UHD Graphics 630 Direct3D11", true], ]; for (const renderer of renderers) { @@ -218,11 +216,11 @@ describe("Render Compatibility", () => { it("detects integrated and dedicated graphics", () => { const renderers = [ - [ "ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true ], - [ "Intel(R) Iris(TM) Graphics 6100", true ], - [ "ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false ], + ["ANGLE (Intel(R) HD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel(R) UHD Graphics 630 Direct3D11 vs_5_0 ps_5_0)", true], + ["ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", true], + ["Intel(R) Iris(TM) Graphics 6100", true], + ["ANGLE (NVIDIA GeForce GTX 970 Direct3D11 vs_5_0 ps_5_0)", false], ]; for (const renderer of renderers) { @@ -244,11 +242,11 @@ describe("Render Compatibility", () => { it("detects MSAA hang bug", () => { const renderers = [ - [ "Mali-G71", true ], - [ "Mali-G72", true ], - [ "Mali-G76", true ], - [ "ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", false ], - [ "Mali-G79", false ], + ["Mali-G71", true], + ["Mali-G72", true], + ["Mali-G76", true], + ["ANGLE (Intel HD Graphics 620 Direct3D11 vs_5_0 ps_5_0)", false], + ["Mali-G79", false], ]; for (const renderer of renderers) { diff --git a/core/webgl-compatibility/src/test/utils/webpack.config.js b/core/webgl-compatibility/src/test/utils/webpack.config.js index 610da9019688..db7dc0c1cb1b 100644 --- a/core/webgl-compatibility/src/test/utils/webpack.config.js +++ b/core/webgl-compatibility/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, plugins: [ // Makes some environment variables available to the JS code, for example: @@ -54,8 +54,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -80,5 +80,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/docs/bis/.vscode/settings.json b/docs/bis/.vscode/settings.json index dc0cac8d714d..c935f8dc7c1f 100644 --- a/docs/bis/.vscode/settings.json +++ b/docs/bis/.vscode/settings.json @@ -1,17 +1,17 @@ { - "cSpell.words": [ - "NADs", - "Pricelist", - "STAAD", - "Struct", - "customattribute", - "elementaspect", - "gridlines", - "kindof", - "mixins", - "srpp", - "underbars", - "unitsystem", - "workgroup" - ] -} \ No newline at end of file + "cSpell.words": [ + "NADs", + "Pricelist", + "STAAD", + "Struct", + "customattribute", + "elementaspect", + "gridlines", + "kindof", + "mixins", + "srpp", + "underbars", + "unitsystem", + "workgroup" + ] +} diff --git a/domains/analytical/backend/eslint.config.js b/domains/analytical/backend/eslint.config.js index 26fcf8009893..259628a4f04a 100644 --- a/domains/analytical/backend/eslint.config.js +++ b/domains/analytical/backend/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/domains/analytical/backend/src/AnalyticalElements.ts b/domains/analytical/backend/src/AnalyticalElements.ts index c9a1f65f8f5b..fcbc77d40a8c 100644 --- a/domains/analytical/backend/src/AnalyticalElements.ts +++ b/domains/analytical/backend/src/AnalyticalElements.ts @@ -17,7 +17,9 @@ import { GeometricElement3dProps, TypeDefinitionElementProps } from "@itwin/core */ export class AnalyticalPartition extends InformationPartitionElement { /** @internal */ - public static override get className(): string { return "AnalyticalPartition"; } + public static override get className(): string { + return "AnalyticalPartition"; + } } /** Spatially located, simulating zero or more SpatialLocationElement or PhysicalElement instances in light of a specialized analytical perspective. @@ -25,9 +27,13 @@ export class AnalyticalPartition extends InformationPartitionElement { */ export abstract class AnalyticalElement extends GeometricElement3d { /** @internal */ - public static override get className(): string { return "AnalyticalElement"; } + public static override get className(): string { + return "AnalyticalElement"; + } /** @internal */ - public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } /** Defines a shared set of properties (the 'type') that can be associated with an AnalyticalElement. @@ -36,7 +42,11 @@ export abstract class AnalyticalElement extends GeometricElement3d { */ export abstract class AnalyticalType extends TypeDefinitionElement { /** @internal */ - public static override get className(): string { return "AnalyticalType"; } + public static override get className(): string { + return "AnalyticalType"; + } /** @internal */ - constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + constructor(props: TypeDefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } diff --git a/domains/analytical/backend/src/AnalyticalModels.ts b/domains/analytical/backend/src/AnalyticalModels.ts index 5d6b0b71ce64..ecf45f97cd21 100644 --- a/domains/analytical/backend/src/AnalyticalModels.ts +++ b/domains/analytical/backend/src/AnalyticalModels.ts @@ -13,5 +13,7 @@ import { GeometricModel3d } from "@itwin/core-backend"; */ export abstract class AnalyticalModel extends GeometricModel3d { /** @internal */ - public static override get className(): string { return "AnalyticalModel"; } + public static override get className(): string { + return "AnalyticalModel"; + } } diff --git a/domains/analytical/backend/src/AnalyticalRelationships.ts b/domains/analytical/backend/src/AnalyticalRelationships.ts index 1e2bc38bdb6a..86d424447707 100644 --- a/domains/analytical/backend/src/AnalyticalRelationships.ts +++ b/domains/analytical/backend/src/AnalyticalRelationships.ts @@ -13,5 +13,7 @@ import { ElementRefersToElements } from "@itwin/core-backend"; */ export class AnalyticalSimulatesSpatialElement extends ElementRefersToElements { /** @internal */ - public static override get className(): string { return "AnalyticalSimulatesSpatialElement"; } + public static override get className(): string { + return "AnalyticalSimulatesSpatialElement"; + } } diff --git a/domains/analytical/backend/src/AnalyticalSchema.ts b/domains/analytical/backend/src/AnalyticalSchema.ts index 6ea30dfa4d9e..9713874fc8f0 100644 --- a/domains/analytical/backend/src/AnalyticalSchema.ts +++ b/domains/analytical/backend/src/AnalyticalSchema.ts @@ -6,8 +6,8 @@ * @module Analytical */ -import * as path from "path"; import { ClassRegistry, KnownLocations, Schema, Schemas } from "@itwin/core-backend"; +import * as path from "path"; import * as elementsModule from "./AnalyticalElements"; import * as modelsModule from "./AnalyticalModels"; import * as relationshipsModule from "./AnalyticalRelationships"; @@ -16,8 +16,12 @@ import * as relationshipsModule from "./AnalyticalRelationships"; * @beta */ export class AnalyticalSchema extends Schema { - public static override get schemaName(): string { return "Analytical"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", "Analytical.ecschema.xml"); } + public static override get schemaName(): string { + return "Analytical"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", "Analytical.ecschema.xml"); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); diff --git a/domains/analytical/backend/src/test/AnalyticalSchema.test.ts b/domains/analytical/backend/src/test/AnalyticalSchema.test.ts index 1693f34b6633..62a54b4c9d75 100644 --- a/domains/analytical/backend/src/test/AnalyticalSchema.test.ts +++ b/domains/analytical/backend/src/test/AnalyticalSchema.test.ts @@ -3,23 +3,48 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import * as semver from "semver"; -import { Guid, Id64, Id64String } from "@itwin/core-bentley"; import { - _nativeDb, BisCoreSchema, ClassRegistry, GenericSchema, GeometricElement3d, IModelDb, IModelHost, IModelJsFs, KnownLocations, PhysicalPartition, Schema, - Schemas, SnapshotDb, SpatialCategory, SubjectOwnsPartitionElements, + _nativeDb, + BisCoreSchema, + ClassRegistry, + GenericSchema, + GeometricElement3d, + IModelDb, + IModelHost, + IModelJsFs, + KnownLocations, + PhysicalPartition, + Schema, + Schemas, + SnapshotDb, + SpatialCategory, + SubjectOwnsPartitionElements, } from "@itwin/core-backend"; +import { Guid, Id64, Id64String } from "@itwin/core-bentley"; import { - CategoryProps, Code, ColorDef, GeometricElement3dProps, IModel, InformationPartitionElementProps, ModelProps, PropertyMetaData, RelatedElement, + CategoryProps, + Code, + ColorDef, + GeometricElement3dProps, + IModel, + InformationPartitionElementProps, + ModelProps, + PropertyMetaData, + RelatedElement, TypeDefinitionElementProps, } from "@itwin/core-common"; +import { assert } from "chai"; +import * as path from "path"; +import * as semver from "semver"; import { AnalyticalElement, AnalyticalModel, AnalyticalPartition, AnalyticalSchema } from "../analytical-backend"; class TestAnalyticalSchema extends Schema { - public static override get schemaName(): string { return "TestAnalytical"; } - public static get schemaFilePath(): string { return path.join(__dirname, "assets", "TestAnalytical.ecschema.xml"); } + public static override get schemaName(): string { + return "TestAnalytical"; + } + public static get schemaFilePath(): string { + return path.join(__dirname, "assets", "TestAnalytical.ecschema.xml"); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); @@ -32,16 +57,24 @@ class TestAnalyticalSchema extends Schema { } class TestAnalyticalPartition extends AnalyticalPartition { - public static override get className(): string { return "Partition"; } + public static override get className(): string { + return "Partition"; + } } class TestAnalyticalElement extends AnalyticalElement { - public static override get className(): string { return "Element"; } - public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Element"; + } + public constructor(props: GeometricElement3dProps, iModel: IModelDb) { + super(props, iModel); + } } class TestAnalyticalModel extends AnalyticalModel { - public static override get className(): string { return "Model"; } + public static override get className(): string { + return "Model"; + } } describe("AnalyticalSchema", () => { diff --git a/domains/linear-referencing/backend/eslint.config.js b/domains/linear-referencing/backend/eslint.config.js index 26fcf8009893..259628a4f04a 100644 --- a/domains/linear-referencing/backend/eslint.config.js +++ b/domains/linear-referencing/backend/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/domains/linear-referencing/backend/src/LinearReferencingElementAspects.ts b/domains/linear-referencing/backend/src/LinearReferencingElementAspects.ts index efe17bd2ba5d..10d62453896d 100644 --- a/domains/linear-referencing/backend/src/LinearReferencingElementAspects.ts +++ b/domains/linear-referencing/backend/src/LinearReferencingElementAspects.ts @@ -6,14 +6,18 @@ * @module LinearReferencing */ -import { Id64String, JsonUtils } from "@itwin/core-bentley"; import { ElementMultiAspect, IModelDb } from "@itwin/core-backend"; +import { Id64String, JsonUtils } from "@itwin/core-bentley"; import { RelatedElement } from "@itwin/core-common"; import { - DistanceExpressionProps, LinearlyReferencedAtLocationAspectProps, LinearlyReferencedFromToLocationAspectProps, + DistanceExpressionProps, + LinearlyReferencedAtLocationAspectProps, + LinearlyReferencedFromToLocationAspectProps, } from "@itwin/linear-referencing-common"; import { - LinearlyReferencedAtPositionRefersToReferent, LinearlyReferencedFromPositionRefersToReferent, LinearlyReferencedToPositionRefersToReferent, + LinearlyReferencedAtPositionRefersToReferent, + LinearlyReferencedFromPositionRefersToReferent, + LinearlyReferencedToPositionRefersToReferent, } from "./LinearReferencingRelationships"; /** Core structure carrying linearly-referenced information. @@ -32,7 +36,9 @@ export class DistanceExpression implements DistanceExpressionProps { this.distanceAlongFromReferent = JsonUtils.asDouble(props.distanceAlongFromReferent); } - public static fromJSON(json: DistanceExpressionProps): DistanceExpression { return new DistanceExpression(json); } + public static fromJSON(json: DistanceExpressionProps): DistanceExpression { + return new DistanceExpression(json); + } } /** Base class for multi-aspects carrying linearly-referenced locations. @@ -40,7 +46,9 @@ export class DistanceExpression implements DistanceExpressionProps { */ export class LinearlyReferencedLocation extends ElementMultiAspect { /** @internal */ - public static override get className(): string { return "LinearlyReferencedLocation"; } + public static override get className(): string { + return "LinearlyReferencedLocation"; + } } /** Concrete multi-aspect class carrying 'at' linearly-referenced positions along a Linear-Element. @@ -48,7 +56,9 @@ export class LinearlyReferencedLocation extends ElementMultiAspect { */ export class LinearlyReferencedAtLocation extends LinearlyReferencedLocation { /** @internal */ - public static override get className(): string { return "LinearlyReferencedAtLocation"; } + public static override get className(): string { + return "LinearlyReferencedAtLocation"; + } public atPosition: DistanceExpression; public fromReferent?: LinearlyReferencedAtPositionRefersToReferent; @@ -70,13 +80,16 @@ export class LinearlyReferencedAtLocation extends LinearlyReferencedLocation { return props; } - public static create(iModel: IModelDb, locatedElementId: Id64String, - at: DistanceExpression, fromReferentId?: Id64String): LinearlyReferencedAtLocation { + public static create( + iModel: IModelDb, + locatedElementId: Id64String, + at: DistanceExpression, + fromReferentId?: Id64String, + ): LinearlyReferencedAtLocation { return new LinearlyReferencedAtLocation(this.toProps(locatedElementId, at, fromReferentId), iModel); } - public static insert(iModel: IModelDb, locatedElementId: Id64String, - at: DistanceExpression, fromReferentId?: Id64String): void { + public static insert(iModel: IModelDb, locatedElementId: Id64String, at: DistanceExpression, fromReferentId?: Id64String): void { iModel.elements.insertAspect(this.toProps(locatedElementId, at, fromReferentId)); } } @@ -86,7 +99,9 @@ export class LinearlyReferencedAtLocation extends LinearlyReferencedLocation { */ export class LinearlyReferencedFromToLocation extends LinearlyReferencedLocation { /** @internal */ - public static override get className(): string { return "LinearlyReferencedFromToLocation"; } + public static override get className(): string { + return "LinearlyReferencedFromToLocation"; + } public fromPosition: DistanceExpression; public fromPositionFromReferent?: LinearlyReferencedFromPositionRefersToReferent; @@ -101,8 +116,13 @@ export class LinearlyReferencedFromToLocation extends LinearlyReferencedLocation this.toPositionFromReferent = RelatedElement.fromJSON(props.toPositionFromReferent); } - private static toProps(locatedElementId: Id64String, - from: DistanceExpression, to: DistanceExpression, fromReferentId?: Id64String, toReferentId?: Id64String): LinearlyReferencedFromToLocationAspectProps { + private static toProps( + locatedElementId: Id64String, + from: DistanceExpression, + to: DistanceExpression, + fromReferentId?: Id64String, + toReferentId?: Id64String, + ): LinearlyReferencedFromToLocationAspectProps { const props: LinearlyReferencedFromToLocationAspectProps = { classFullName: LinearlyReferencedFromToLocation.classFullName, element: { id: locatedElementId }, @@ -115,13 +135,25 @@ export class LinearlyReferencedFromToLocation extends LinearlyReferencedLocation return props; } - public static create(iModel: IModelDb, locatedElementId: Id64String, - from: DistanceExpression, to: DistanceExpression, fromReferentId?: Id64String, toReferentId?: Id64String): LinearlyReferencedFromToLocation { + public static create( + iModel: IModelDb, + locatedElementId: Id64String, + from: DistanceExpression, + to: DistanceExpression, + fromReferentId?: Id64String, + toReferentId?: Id64String, + ): LinearlyReferencedFromToLocation { return new LinearlyReferencedFromToLocation(this.toProps(locatedElementId, from, to, fromReferentId, toReferentId), iModel); } - public static insert(iModel: IModelDb, locatedElementId: Id64String, - from: DistanceExpression, to: DistanceExpression, fromReferentId?: Id64String, toReferentId?: Id64String): void { + public static insert( + iModel: IModelDb, + locatedElementId: Id64String, + from: DistanceExpression, + to: DistanceExpression, + fromReferentId?: Id64String, + toReferentId?: Id64String, + ): void { iModel.elements.insertAspect(this.toProps(locatedElementId, from, to, fromReferentId, toReferentId)); } } diff --git a/domains/linear-referencing/backend/src/LinearReferencingElements.ts b/domains/linear-referencing/backend/src/LinearReferencingElements.ts index 1ad713a7d166..b4de318e755d 100644 --- a/domains/linear-referencing/backend/src/LinearReferencingElements.ts +++ b/domains/linear-referencing/backend/src/LinearReferencingElements.ts @@ -6,17 +6,27 @@ * @module LinearReferencing */ -import { assert, DbResult, Id64String } from "@itwin/core-bentley"; import { ECSqlStatement, ElementAspect, IModelDb, PhysicalElement, SpatialLocationElement } from "@itwin/core-backend"; +import { assert, DbResult, Id64String } from "@itwin/core-bentley"; import { Code, ElementProps, GeometricElement3dProps, IModelError, PhysicalElementProps, RelatedElement } from "@itwin/core-common"; import { - ComparisonOption, LinearLocationReference, LinearlyLocatedAttributionProps, LinearlyReferencedAtLocationAspectProps, - LinearlyReferencedAtLocationProps, LinearlyReferencedFromToLocationAspectProps, LinearlyReferencedFromToLocationProps, - LinearlyReferencedLocationType, QueryParams, ReferentElementProps, + ComparisonOption, + LinearLocationReference, + LinearlyLocatedAttributionProps, + LinearlyReferencedAtLocationAspectProps, + LinearlyReferencedAtLocationProps, + LinearlyReferencedFromToLocationAspectProps, + LinearlyReferencedFromToLocationProps, + LinearlyReferencedLocationType, + QueryParams, + ReferentElementProps, } from "@itwin/linear-referencing-common"; import { LinearlyReferencedAtLocation, LinearlyReferencedFromToLocation } from "./LinearReferencingElementAspects"; import { - ILinearLocationLocatesElement, ILinearlyLocatedAlongILinearElement, ILinearlyLocatedAttributesElement, IReferentReferencesElement, + ILinearLocationLocatesElement, + ILinearlyLocatedAlongILinearElement, + ILinearlyLocatedAttributesElement, + IReferentReferencesElement, } from "./LinearReferencingRelationships"; /** Base class for Spatial Location Element subclasses representing properties whose value is located along a Linear-Element and only applies to a portion of an Element. @@ -24,7 +34,9 @@ import { */ export abstract class LinearlyLocatedAttribution extends SpatialLocationElement { /** @internal */ - public static override get className(): string { return "LinearlyLocatedAttribution"; } + public static override get className(): string { + return "LinearlyLocatedAttribution"; + } public attributedElement?: ILinearlyLocatedAttributesElement; @@ -43,7 +55,9 @@ export abstract class LinearlyLocatedAttribution extends SpatialLocationElement */ export abstract class LinearLocationElement extends SpatialLocationElement implements LinearlyLocatedBase { /** @internal */ - public static override get className(): string { return "LinearLocationElement"; } + public static override get className(): string { + return "LinearLocationElement"; + } public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); @@ -59,7 +73,9 @@ export abstract class LinearLocationElement extends SpatialLocationElement imple */ export class LinearLocation extends LinearLocationElement implements LinearlyLocatedBase { /** @internal */ - public static override get className(): string { return "LinearLocation"; } + public static override get className(): string { + return "LinearLocation"; + } public constructor(props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } @@ -79,8 +95,14 @@ export class LinearLocation extends LinearLocationElement implements LinearlyLoc return new LinearLocation(this.toProps(modelId, categoryId), iModel); } - public static insertFromTo(iModel: IModelDb, modelId: Id64String, categoryId: Id64String, linearElementId: Id64String, - fromToPosition: LinearlyReferencedFromToLocationProps, locatedElementId: Id64String): Id64String { + public static insertFromTo( + iModel: IModelDb, + modelId: Id64String, + categoryId: Id64String, + linearElementId: Id64String, + fromToPosition: LinearlyReferencedFromToLocationProps, + locatedElementId: Id64String, + ): Id64String { const newId = LinearlyLocated.insertFromTo(iModel, this.toProps(modelId, categoryId), linearElementId, fromToPosition); ILinearLocationLocatesElement.insert(iModel, newId, locatedElementId); @@ -88,7 +110,12 @@ export class LinearLocation extends LinearLocationElement implements LinearlyLoc return newId; } - public insertFromTo(iModel: IModelDb, linearElementId: Id64String, fromToPosition: LinearlyReferencedFromToLocationProps, locatedElementId: Id64String): Id64String { + public insertFromTo( + iModel: IModelDb, + linearElementId: Id64String, + fromToPosition: LinearlyReferencedFromToLocationProps, + locatedElementId: Id64String, + ): Id64String { const newId = LinearlyLocated.insertFromTo(iModel, this.toJSON(), linearElementId, fromToPosition); ILinearLocationLocatesElement.insert(iModel, newId, locatedElementId); @@ -96,8 +123,14 @@ export class LinearLocation extends LinearLocationElement implements LinearlyLoc return newId; } - public static insertAt(iModel: IModelDb, modelId: Id64String, categoryId: Id64String, linearElementId: Id64String, - atPosition: LinearlyReferencedAtLocationProps, locatedElementId: Id64String): Id64String { + public static insertAt( + iModel: IModelDb, + modelId: Id64String, + categoryId: Id64String, + linearElementId: Id64String, + atPosition: LinearlyReferencedAtLocationProps, + locatedElementId: Id64String, + ): Id64String { const newId = LinearlyLocated.insertAt(iModel, this.toProps(modelId, categoryId), linearElementId, atPosition); ILinearLocationLocatesElement.insert(iModel, newId, locatedElementId); @@ -105,7 +138,12 @@ export class LinearLocation extends LinearLocationElement implements LinearlyLoc return newId; } - public insertAt(iModel: IModelDb, linearElementId: Id64String, atPosition: LinearlyReferencedAtLocationProps, locatedElementId: Id64String): Id64String { + public insertAt( + iModel: IModelDb, + linearElementId: Id64String, + atPosition: LinearlyReferencedAtLocationProps, + locatedElementId: Id64String, + ): Id64String { const newId = LinearlyLocated.insertAt(iModel, this.toJSON(), linearElementId, atPosition); ILinearLocationLocatesElement.insert(iModel, newId, locatedElementId); @@ -119,7 +157,9 @@ export class LinearLocation extends LinearLocationElement implements LinearlyLoc */ export abstract class LinearPhysicalElement extends PhysicalElement { /** @internal */ - public static override get className(): string { return "LinearPhysicalElement"; } + public static override get className(): string { + return "LinearPhysicalElement"; + } public constructor(props: PhysicalElementProps, iModel: IModelDb) { super(props, iModel); @@ -131,7 +171,9 @@ export abstract class LinearPhysicalElement extends PhysicalElement { */ export abstract class ReferentElement extends SpatialLocationElement implements LinearlyLocatedBase { /** @internal */ - public static override get className(): string { return "ReferentElement"; } + public static override get className(): string { + return "ReferentElement"; + } public referencedElement?: IReferentReferencesElement; @@ -150,7 +192,9 @@ export abstract class ReferentElement extends SpatialLocationElement implements */ export class Referent extends ReferentElement { /** @internal */ - public static override get className(): string { return "Referent"; } + public static override get className(): string { + return "Referent"; + } public constructor(props: ReferentElementProps, iModel: IModelDb) { super(props, iModel); } @@ -171,8 +215,14 @@ export class Referent extends ReferentElement { return new Referent(this.toProps(modelId, categoryId, referencedElementId), iModel); } - public static insertAt(iModel: IModelDb, modelId: Id64String, categoryId: Id64String, linearElementId: Id64String, - atPosition: LinearlyReferencedAtLocationProps, referencedElementId: Id64String): Id64String { + public static insertAt( + iModel: IModelDb, + modelId: Id64String, + categoryId: Id64String, + linearElementId: Id64String, + atPosition: LinearlyReferencedAtLocationProps, + referencedElementId: Id64String, + ): Id64String { return LinearlyLocated.insertAt(iModel, this.toProps(modelId, categoryId, referencedElementId), linearElementId, atPosition); } @@ -379,7 +429,8 @@ class QueryLinearLocationsECSQLGen { if (impl.selectDistinct()) select += "DISTINCT "; - select += "LinearlyLocated.InstanceId LinearlyLocatedId, printf('%s:%s', meta.ECSchemaDef.Name, meta.ECClassDef.Name) LinearlyLocatedClassFullName, "; + select += + "LinearlyLocated.InstanceId LinearlyLocatedId, printf('%s:%s', meta.ECSchemaDef.Name, meta.ECClassDef.Name) LinearlyLocatedClassFullName, "; select += impl.genSelect(); this._ecSql += select; @@ -402,7 +453,7 @@ class QueryLinearLocationsECSQLGen { "WHERE Along.TargetECInstanceId = ?) LinearlyLocated ON meta.ECClassDef.ECInstanceId = LinearlyLocated.ClassId "; } - private _addFromClause(impl: ECSQLGenImpl/* bvector& bindVals */): void { + private _addFromClause(impl: ECSQLGenImpl /* bvector& bindVals */): void { let from = "FROM "; from += this._genLinearlyLocated(); from += impl.genFromJoin(); @@ -416,11 +467,12 @@ class QueryLinearLocationsECSQLGen { where += impl.genWhere( bindVals, this._params.fromDistanceAlong, - (this._params.fromComparisonOption === undefined || - this._params.fromComparisonOption === ComparisonOption.Inclusive), + this._params.fromComparisonOption === undefined || + this._params.fromComparisonOption === ComparisonOption.Inclusive, this._params.toDistanceAlong, - (this._params.toComparisonOption === undefined || - this._params.toComparisonOption === ComparisonOption.Inclusive)); + this._params.toComparisonOption === undefined || + this._params.toComparisonOption === ComparisonOption.Inclusive, + ); if (this._params.linearlyLocatedClassFullNames !== undefined) { if (where.length > 6) @@ -462,8 +514,10 @@ class QueryLinearLocationsECSQLGen { } private _createImpl(): ECSQLGenImpl { - if (this._params.linearlyReferencedLocationTypeFilter === undefined || - this._params.linearlyReferencedLocationTypeFilter === LinearlyReferencedLocationType.Any) { + if ( + this._params.linearlyReferencedLocationTypeFilter === undefined || + this._params.linearlyReferencedLocationTypeFilter === LinearlyReferencedLocationType.Any + ) { return new AtAndFromToECSQLGenImpl(); } else if (this._params.linearlyReferencedLocationTypeFilter === LinearlyReferencedLocationType.FromTo) { return new FromToECSQLGenImpl(); @@ -498,8 +552,7 @@ export class LinearlyLocated { private static insertBasic(iModel: IModelDb, elProps: ElementProps, linearElementId: Id64String): Id64String { const newId = iModel.elements.insertElement(elProps); - const linearlyLocatedAlongLinearElement = - ILinearlyLocatedAlongILinearElement.create(iModel, newId, linearElementId); + const linearlyLocatedAlongLinearElement = ILinearlyLocatedAlongILinearElement.create(iModel, newId, linearElementId); linearlyLocatedAlongLinearElement.insert(); return newId; @@ -513,12 +566,20 @@ export class LinearlyLocated { * @returns The newly inserted element's Id. * @throws [[IModelError]] if unable to insert the element. */ - public static insertAt(iModel: IModelDb, elProps: ElementProps, linearElementId: Id64String, - atPosition: LinearlyReferencedAtLocationProps): Id64String { + public static insertAt( + iModel: IModelDb, + elProps: ElementProps, + linearElementId: Id64String, + atPosition: LinearlyReferencedAtLocationProps, + ): Id64String { const newId: Id64String = this.insertBasic(iModel, elProps, linearElementId); - LinearlyReferencedAtLocation.insert(iModel, newId, atPosition.atPosition, - (atPosition.fromReferent === undefined) ? undefined : atPosition.fromReferent.id); + LinearlyReferencedAtLocation.insert( + iModel, + newId, + atPosition.atPosition, + (atPosition.fromReferent === undefined) ? undefined : atPosition.fromReferent.id, + ); return newId; } @@ -531,21 +592,28 @@ export class LinearlyLocated { * @returns The newly inserted element's Id. * @throws [[IModelError]] if unable to insert the element. */ - public static insertFromTo(iModel: IModelDb, elProps: ElementProps, linearElementId: Id64String, - fromToPosition: LinearlyReferencedFromToLocationProps): Id64String { + public static insertFromTo( + iModel: IModelDb, + elProps: ElementProps, + linearElementId: Id64String, + fromToPosition: LinearlyReferencedFromToLocationProps, + ): Id64String { const newId: Id64String = this.insertBasic(iModel, elProps, linearElementId); - LinearlyReferencedFromToLocation.insert(iModel, newId, - fromToPosition.fromPosition, fromToPosition.toPosition, + LinearlyReferencedFromToLocation.insert( + iModel, + newId, + fromToPosition.fromPosition, + fromToPosition.toPosition, (fromToPosition.fromPositionFromReferent === undefined) ? undefined : fromToPosition.fromPositionFromReferent.id, - (fromToPosition.toPositionFromReferent === undefined) ? undefined : fromToPosition.toPositionFromReferent.id); + (fromToPosition.toPositionFromReferent === undefined) ? undefined : fromToPosition.toPositionFromReferent.id, + ); return newId; } private static getLinearLocations(iModel: IModelDb, linearlyLocatedElementId: Id64String, fullClassName: string): T[] { - const aspects: ElementAspect[] = - iModel.elements.getAspects(linearlyLocatedElementId, fullClassName); + const aspects: ElementAspect[] = iModel.elements.getAspects(linearlyLocatedElementId, fullClassName); if (aspects.length === 0) return []; @@ -562,12 +630,11 @@ export class LinearlyLocated { private static queryFirstLinearLocationAspectId(iModel: IModelDb, linearlyLocatedElementId: Id64String, className: string): Id64String | undefined { let aspectId: Id64String | undefined; - iModel.withPreparedStatement(`SELECT ECInstanceId FROM LinearReferencing.${className} WHERE Element.Id=? LIMIT 1`, - (stmt: ECSqlStatement) => { - stmt.bindId(1, linearlyLocatedElementId); - if (stmt.step() === DbResult.BE_SQLITE_ROW) - aspectId = stmt.getValue(0).getId(); - }); + iModel.withPreparedStatement(`SELECT ECInstanceId FROM LinearReferencing.${className} WHERE Element.Id=? LIMIT 1`, (stmt: ECSqlStatement) => { + stmt.bindId(1, linearlyLocatedElementId); + if (stmt.step() === DbResult.BE_SQLITE_ROW) + aspectId = stmt.getValue(0).getId(); + }); return aspectId; } @@ -580,7 +647,10 @@ export class LinearlyLocated { */ public static getAtLocations(iModel: IModelDb, linearlyLocatedElementId: Id64String): LinearlyReferencedAtLocation[] { return this.getLinearLocations( - iModel, linearlyLocatedElementId, "LinearReferencing:LinearlyReferencedAtLocation"); + iModel, + linearlyLocatedElementId, + "LinearReferencing:LinearlyReferencedAtLocation", + ); } /** Query for the single LinearlyReferenced AtLocation aspect owned by the specified LinearlyLocated Element. If more than one aspect is expected, use [[getAtLocations]] instead. @@ -606,8 +676,12 @@ export class LinearlyLocated { * @param aspectId The Id of the aspect to update. If not known, the first aspectId will be looked-up. * @throws [[IModelError]] */ - public static updateAtLocation(iModel: IModelDb, linearlyLocatedElementId: Id64String, linearLocationProps: LinearlyReferencedAtLocationProps, - aspectId?: Id64String): void { + public static updateAtLocation( + iModel: IModelDb, + linearlyLocatedElementId: Id64String, + linearLocationProps: LinearlyReferencedAtLocationProps, + aspectId?: Id64String, + ): void { let linearLocAspectId: Id64String; if (aspectId !== undefined) linearLocAspectId = aspectId; @@ -633,8 +707,12 @@ export class LinearlyLocated { * @param aspectId The Id of the aspect to update. If not known, the first aspectId will be looked-up. * @throws [[IModelError]] */ - public static updateFromToLocation(iModel: IModelDb, linearlyLocatedElementId: Id64String, linearLocationProps: LinearlyReferencedFromToLocationProps, - aspectId?: Id64String): void { + public static updateFromToLocation( + iModel: IModelDb, + linearlyLocatedElementId: Id64String, + linearLocationProps: LinearlyReferencedFromToLocationProps, + aspectId?: Id64String, + ): void { let linearLocAspectId: Id64String; if (aspectId !== undefined) linearLocAspectId = aspectId; @@ -671,7 +749,8 @@ export class LinearlyLocated { linearElementId = stmt.getValue(0).getId(); else linearElementId = undefined; - }); + }, + ); return linearElementId; } @@ -684,7 +763,10 @@ export class LinearlyLocated { */ public static getFromToLocations(iModel: IModelDb, linearlyLocatedElementId: Id64String): LinearlyReferencedFromToLocation[] { return this.getLinearLocations( - iModel, linearlyLocatedElementId, "LinearReferencing:LinearlyReferencedFromToLocation"); + iModel, + linearlyLocatedElementId, + "LinearReferencing:LinearlyReferencedFromToLocation", + ); } /** Query for the single LinearlyReferenced FromToLocation aspect owned by the specified LinearlyLocated Element. If more than one aspect is expected, use [[getFromToLocations]] instead. diff --git a/domains/linear-referencing/backend/src/LinearReferencingRelationships.ts b/domains/linear-referencing/backend/src/LinearReferencingRelationships.ts index 9399cd59a79f..8822042e59fb 100644 --- a/domains/linear-referencing/backend/src/LinearReferencingRelationships.ts +++ b/domains/linear-referencing/backend/src/LinearReferencingRelationships.ts @@ -6,8 +6,8 @@ * @module LinearReferencing */ -import { Id64String } from "@itwin/core-bentley"; import { ElementRefersToElements } from "@itwin/core-backend"; +import { Id64String } from "@itwin/core-bentley"; import { RelatedElement } from "@itwin/core-common"; /** Relationship indicating the Linear-Element along which concrete instances mixing-in ILinearlyLocated are located. @@ -15,7 +15,9 @@ import { RelatedElement } from "@itwin/core-common"; */ export class ILinearlyLocatedAlongILinearElement extends ElementRefersToElements { /** @internal */ - public static override get className(): string { return "ILinearlyLocatedAlongILinearElement"; } + public static override get className(): string { + return "ILinearlyLocatedAlongILinearElement"; + } } /** Relationship indicating bis:Element being linearly-located by a concrete instance mixing-in ILinearLocationElement. @@ -23,7 +25,9 @@ export class ILinearlyLocatedAlongILinearElement extends ElementRefersToElements */ export class ILinearLocationLocatesElement extends ElementRefersToElements { /** @internal */ - public static override get className(): string { return "ILinearLocationLocatesElement"; } + public static override get className(): string { + return "ILinearLocationLocatesElement"; + } } /** Relationship associating Linear-Elements with the elements they came from. diff --git a/domains/linear-referencing/backend/src/LinearReferencingSchema.ts b/domains/linear-referencing/backend/src/LinearReferencingSchema.ts index c935daf53085..02e0f733cdb2 100644 --- a/domains/linear-referencing/backend/src/LinearReferencingSchema.ts +++ b/domains/linear-referencing/backend/src/LinearReferencingSchema.ts @@ -6,8 +6,8 @@ * @module LinearReferencing */ -import * as path from "path"; import { ClassRegistry, KnownLocations, Schema, Schemas } from "@itwin/core-backend"; +import * as path from "path"; import * as aspectsModule from "./LinearReferencingElementAspects"; import * as elementsModule from "./LinearReferencingElements"; import * as relationshipsModule from "./LinearReferencingRelationships"; @@ -17,8 +17,12 @@ import * as relationshipsModule from "./LinearReferencingRelationships"; * @beta */ export class LinearReferencingSchema extends Schema { - public static override get schemaName(): string { return "LinearReferencing"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", "LinearReferencing.ecschema.xml"); } + public static override get schemaName(): string { + return "LinearReferencing"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", "LinearReferencing.ecschema.xml"); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); diff --git a/domains/linear-referencing/backend/src/test/LinearReferencingSchema.test.ts b/domains/linear-referencing/backend/src/test/LinearReferencingSchema.test.ts index b331eb76763f..2ad8c3d19490 100644 --- a/domains/linear-referencing/backend/src/test/LinearReferencingSchema.test.ts +++ b/domains/linear-referencing/backend/src/test/LinearReferencingSchema.test.ts @@ -3,24 +3,40 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import { Guid, Id64, Id64String } from "@itwin/core-bentley"; import { - ClassRegistry, IModelDb, IModelHost, IModelJsFs, PhysicalModel, PhysicalPartition, Schema, Schemas, SnapshotDb, SpatialCategory, + ClassRegistry, + IModelDb, + IModelHost, + IModelJsFs, + PhysicalModel, + PhysicalPartition, + Schema, + Schemas, + SnapshotDb, + SpatialCategory, SubjectOwnsPartitionElements, } from "@itwin/core-backend"; -import { - CategoryProps, Code, GeometricElement3dProps, IModel, InformationPartitionElementProps, PhysicalElementProps, -} from "@itwin/core-common"; +import { Guid, Id64, Id64String } from "@itwin/core-bentley"; +import { CategoryProps, Code, GeometricElement3dProps, IModel, InformationPartitionElementProps, PhysicalElementProps } from "@itwin/core-common"; import { ILinearElementProps, LinearlyLocatedAttributionProps, LinearlyReferencedFromToLocationProps } from "@itwin/linear-referencing-common"; +import { assert } from "chai"; +import * as path from "path"; import { - LinearElement, LinearlyLocated, LinearlyLocatedAttribution, LinearlyLocatedSingleFromTo, LinearlyReferencedFromToLocation, LinearReferencingSchema, + LinearElement, + LinearlyLocated, + LinearlyLocatedAttribution, + LinearlyLocatedSingleFromTo, + LinearlyReferencedFromToLocation, + LinearReferencingSchema, } from "../linear-referencing-backend"; class TestLinearReferencingSchema extends Schema { - public static override get schemaName(): string { return "TestLinearReferencing"; } - public static get schemaFilePath(): string { return path.join(__dirname, "assets", "TestLinearReferencing.ecschema.xml"); } + public static override get schemaName(): string { + return "TestLinearReferencing"; + } + public static get schemaFilePath(): string { + return path.join(__dirname, "assets", "TestLinearReferencing.ecschema.xml"); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { Schemas.unregisterSchema(this.schemaName); @@ -32,7 +48,9 @@ class TestLinearReferencingSchema extends Schema { } class TestLinearlyLocatedAttribution extends LinearlyLocatedAttribution implements LinearlyLocatedSingleFromTo { - public static override get className(): string { return "TestLinearlyLocatedAttribution"; } + public static override get className(): string { + return "TestLinearlyLocatedAttribution"; + } public constructor(props: LinearlyLocatedAttributionProps, iModel: IModelDb) { super(props, iModel); @@ -58,8 +76,14 @@ class TestLinearlyLocatedAttribution extends LinearlyLocatedAttribution implemen LinearlyLocated.updateFromToLocation(this.iModel, this.id, linearLocation, aspectId); } - public static insertFromTo(iModel: IModelDb, modelId: Id64String, categoryId: Id64String, linearElementId: Id64String, - fromToPosition: LinearlyReferencedFromToLocationProps, attributedElementId: Id64String): Id64String { + public static insertFromTo( + iModel: IModelDb, + modelId: Id64String, + categoryId: Id64String, + linearElementId: Id64String, + fromToPosition: LinearlyReferencedFromToLocationProps, + attributedElementId: Id64String, + ): Id64String { return LinearlyLocated.insertFromTo(iModel, this.toProps(modelId, categoryId, attributedElementId), linearElementId, fromToPosition); } } @@ -150,7 +174,13 @@ describe("LinearReferencing Domain", () => { }; const linearlyLocatedAttributionId = TestLinearlyLocatedAttribution.insertFromTo( - iModelDb, physicalModelId, spatialCategoryId, linearElementId, linearFromToPosition, linearFeatureElementId); + iModelDb, + physicalModelId, + spatialCategoryId, + linearElementId, + linearFromToPosition, + linearFeatureElementId, + ); assert.isTrue(Id64.isValidId64(linearlyLocatedAttributionId)); assert.equal(linearElementId, LinearlyLocated.getLinearElementId(iModelDb, linearlyLocatedAttributionId)); @@ -192,14 +222,17 @@ describe("LinearReferencing Domain", () => { toPosition: { distanceAlongFromStart: 60.0 }, }; - const linearPhysicalElementId: Id64String = - LinearlyLocated.insertFromTo(iModelDb, testPhysicalLinearProps, linearElementId, linearFromToPosition); + const linearPhysicalElementId: Id64String = LinearlyLocated.insertFromTo( + iModelDb, + testPhysicalLinearProps, + linearElementId, + linearFromToPosition, + ); assert.isTrue(Id64.isValidId64(linearPhysicalElementId)); assert.equal(linearElementId, LinearlyLocated.getLinearElementId(iModelDb, linearPhysicalElementId)); // Query for linearly located elements via the queryLinearLocations API - let linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, - { fromDistanceAlong: 10.0, toDistanceAlong: 70.0 }); + let linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, { fromDistanceAlong: 10.0, toDistanceAlong: 70.0 }); assert.equal(linearLocationRefs.length, 2); assert.equal(linearLocationRefs[0].linearlyLocatedId, linearlyLocatedAttributionId); assert.equal(linearLocationRefs[0].linearlyLocatedClassFullName, "TestLinearReferencing:TestLinearlyLocatedAttribution"); @@ -211,16 +244,15 @@ describe("LinearReferencing Domain", () => { assert.equal(linearLocationRefs[1].startDistanceAlong, 30.0); assert.equal(linearLocationRefs[1].stopDistanceAlong, 60.0); - linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, - { linearlyLocatedClassFullNames: ["TestLinearReferencing:TestLinearlyLocatedAttribution"] }); + linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, { + linearlyLocatedClassFullNames: ["TestLinearReferencing:TestLinearlyLocatedAttribution"], + }); assert.equal(linearLocationRefs.length, 1); assert.equal(linearLocationRefs[0].linearlyLocatedId, linearlyLocatedAttributionId); - linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, - { - linearlyLocatedClassFullNames: ["TestLinearReferencing:TestLinearlyLocatedAttribution", - "TestLinearReferencing:TestLinearPhysicalElement"], - }); + linearLocationRefs = LinearElement.queryLinearLocations(iModelDb, linearElementId, { + linearlyLocatedClassFullNames: ["TestLinearReferencing:TestLinearlyLocatedAttribution", "TestLinearReferencing:TestLinearPhysicalElement"], + }); assert.equal(linearLocationRefs.length, 2); assert.equal(linearLocationRefs[0].linearlyLocatedId, linearlyLocatedAttributionId); assert.equal(linearLocationRefs[1].linearlyLocatedId, linearPhysicalElementId); diff --git a/domains/linear-referencing/common/eslint.config.js b/domains/linear-referencing/common/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/domains/linear-referencing/common/eslint.config.js +++ b/domains/linear-referencing/common/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/domains/linear-referencing/common/src/LinearReferencingCommon.ts b/domains/linear-referencing/common/src/LinearReferencingCommon.ts index 93949695ff90..b07a3a69f4c4 100644 --- a/domains/linear-referencing/common/src/LinearReferencingCommon.ts +++ b/domains/linear-referencing/common/src/LinearReferencingCommon.ts @@ -22,12 +22,19 @@ export interface LinearLocationReference { /** Enum capturing range-comparison options for from/to distanceAlong in QueryParams * @beta */ -export enum ComparisonOption { Inclusive, Exclusive } +export enum ComparisonOption { + Inclusive, + Exclusive, +} /** Enum enabling LinearElement.queryLinearLocations performance optimization when the target Linearly-Located classes are all either At or FromTo. * @beta */ -export enum LinearlyReferencedLocationType { At, FromTo, Any } +export enum LinearlyReferencedLocationType { + At, + FromTo, + Any, +} /** Interface capturing various parameters for the execution of LinearElement.queryLinearLocations API * @beta diff --git a/domains/physical-material/backend/eslint.config.js b/domains/physical-material/backend/eslint.config.js index 26fcf8009893..259628a4f04a 100644 --- a/domains/physical-material/backend/eslint.config.js +++ b/domains/physical-material/backend/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/domains/physical-material/backend/src/PhysicalMaterialElements.ts b/domains/physical-material/backend/src/PhysicalMaterialElements.ts index 83d6df4e205d..deb7c4ba82e2 100644 --- a/domains/physical-material/backend/src/PhysicalMaterialElements.ts +++ b/domains/physical-material/backend/src/PhysicalMaterialElements.ts @@ -15,8 +15,12 @@ import { DefinitionElementProps } from "@itwin/core-common"; */ export class Aggregate extends PhysicalMaterial { /** @internal */ - public static override get className(): string { return "Aggregate"; } - public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Aggregate"; + } + public constructor(props: DefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Aluminum is a bis:PhysicalMaterial representing aluminum (atomic symbol Al) or one of its alloys. @@ -24,8 +28,12 @@ export class Aggregate extends PhysicalMaterial { */ export class Aluminum extends PhysicalMaterial { /** @internal */ - public static override get className(): string { return "Aluminum"; } - public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Aluminum"; + } + public constructor(props: DefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Asphalt is a bis:PhysicalMaterial representing a mixture of a bituminous binder and aggregates. Asphalt is typically used for roadway surfacing. @@ -33,8 +41,12 @@ export class Aluminum extends PhysicalMaterial { */ export class Asphalt extends PhysicalMaterial { /** @internal */ - public static override get className(): string { return "Asphalt"; } - public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Asphalt"; + } + public constructor(props: DefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Concrete is a bis:PhysicalMaterial representing a mixture of hydraulic cement, aggregates, water and optionally other materials. @@ -42,8 +54,12 @@ export class Asphalt extends PhysicalMaterial { */ export class Concrete extends PhysicalMaterial { /** @internal */ - public static override get className(): string { return "Concrete"; } - public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Concrete"; + } + public constructor(props: DefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } /** Steel is a bis:PhysicalMaterial representing an alloy of iron, carbon and other elements. @@ -51,6 +67,10 @@ export class Concrete extends PhysicalMaterial { */ export class Steel extends PhysicalMaterial { /** @internal */ - public static override get className(): string { return "Steel"; } - public constructor(props: DefinitionElementProps, iModel: IModelDb) { super(props, iModel); } + public static override get className(): string { + return "Steel"; + } + public constructor(props: DefinitionElementProps, iModel: IModelDb) { + super(props, iModel); + } } diff --git a/domains/physical-material/backend/src/PhysicalMaterialSchema.ts b/domains/physical-material/backend/src/PhysicalMaterialSchema.ts index 8062bc694b74..8be7f63203ba 100644 --- a/domains/physical-material/backend/src/PhysicalMaterialSchema.ts +++ b/domains/physical-material/backend/src/PhysicalMaterialSchema.ts @@ -6,8 +6,8 @@ * @module PhysicalMaterial */ -import * as path from "path"; import { ClassRegistry, KnownLocations, Schema, Schemas } from "@itwin/core-backend"; +import * as path from "path"; import * as elementsModule from "./PhysicalMaterialElements"; /** The PhysicalMaterialSchema contains standard physical material classes. @@ -16,8 +16,12 @@ import * as elementsModule from "./PhysicalMaterialElements"; * @public */ export class PhysicalMaterialSchema extends Schema { - public static override get schemaName(): string { return "PhysicalMaterial"; } - public static get schemaFilePath(): string { return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", `${PhysicalMaterialSchema.schemaName}.ecschema.xml`); } + public static override get schemaName(): string { + return "PhysicalMaterial"; + } + public static get schemaFilePath(): string { + return path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "Domain", `${PhysicalMaterialSchema.schemaName}.ecschema.xml`); + } public static registerSchema() { if (this !== Schemas.getRegisteredSchema(this.schemaName)) { diff --git a/domains/physical-material/backend/src/test/PhysicalMaterialSchema.test.ts b/domains/physical-material/backend/src/test/PhysicalMaterialSchema.test.ts index b9e5a426c5ea..302450db12aa 100644 --- a/domains/physical-material/backend/src/test/PhysicalMaterialSchema.test.ts +++ b/domains/physical-material/backend/src/test/PhysicalMaterialSchema.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import { DbResult } from "@itwin/core-bentley"; import { ECSqlStatement, IModelDb, IModelHost, IModelJsFs, PhysicalMaterial, SnapshotDb } from "@itwin/core-backend"; +import { DbResult } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; +import { assert } from "chai"; +import * as path from "path"; import { Aggregate, Aluminum, Asphalt, Concrete, PhysicalMaterialSchema, Steel } from "../physical-material-backend"; describe("PhysicalMaterialSchema", () => { diff --git a/editor/backend/eslint.config.js b/editor/backend/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/editor/backend/eslint.config.js +++ b/editor/backend/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/editor/backend/src/EditBuiltInCommand.ts b/editor/backend/src/EditBuiltInCommand.ts index 4f87395dc2ea..1da462b3cd73 100644 --- a/editor/backend/src/EditBuiltInCommand.ts +++ b/editor/backend/src/EditBuiltInCommand.ts @@ -6,10 +6,23 @@ * @module Editing */ +import { GeometricElement, IModelDb } from "@itwin/core-backend"; import { CompressedId64Set, DbResult, Id64String, IModelStatus } from "@itwin/core-bentley"; +import { + BRepEntity, + EcefLocation, + EcefLocationProps, + ElementGeometry, + ElementGeometryBuilderParams, + ElementGeometryFunction, + ElementGeometryInfo, + ElementGeometryRequest, + FilePropertyProps, + GeometricElementProps, + GeometryPartProps, + IModelError, +} from "@itwin/core-common"; import { Matrix3d, Matrix3dProps, Point3d, Range3d, Range3dProps, Transform, TransformProps } from "@itwin/core-geometry"; -import { GeometricElement, IModelDb } from "@itwin/core-backend"; -import { BRepEntity, EcefLocation, EcefLocationProps, ElementGeometry, ElementGeometryBuilderParams, ElementGeometryFunction, ElementGeometryInfo, ElementGeometryRequest, FilePropertyProps, GeometricElementProps, GeometryPartProps, IModelError } from "@itwin/core-common"; import { BasicManipulationCommandIpc, editorBuiltInCmdIds, FlatBufferGeometryFilter } from "@itwin/editor-common"; import { EditCommand } from "./EditCommand"; @@ -19,9 +32,13 @@ import { EditCommand } from "./EditCommand"; export class BasicManipulationCommand extends EditCommand implements BasicManipulationCommandIpc { public static override commandId = editorBuiltInCmdIds.cmdBasicManipulation; - public constructor(iModel: IModelDb, protected _str: string) { super(iModel); } + public constructor(iModel: IModelDb, protected _str: string) { + super(iModel); + } - public override async onStart() { return BasicManipulationCommand.commandId; } + public override async onStart() { + return BasicManipulationCommand.commandId; + } public async addAllowedChannel(channelKey: string): Promise { this.iModel.channels.addAllowedChannel(channelKey); diff --git a/editor/backend/src/EditCommand.ts b/editor/backend/src/EditCommand.ts index 82fe09889d25..485940a974b0 100644 --- a/editor/backend/src/EditCommand.ts +++ b/editor/backend/src/EditCommand.ts @@ -6,8 +6,8 @@ * @module Editing */ -import { IModelStatus } from "@itwin/core-bentley"; import { IModelDb, IpcHandler, IpcHost } from "@itwin/core-backend"; +import { IModelStatus } from "@itwin/core-bentley"; import { BackendError, IModelError } from "@itwin/core-common"; import { EditCommandIpc, EditorIpc, editorIpcStrings } from "@itwin/editor-common"; @@ -51,14 +51,14 @@ export class EditCommand implements EditCommandIpc { return this.constructor as EditCommandType; } - public async onStart(): Promise { } + public async onStart(): Promise {} public async ping(): Promise<{ commandId: string, version: string, [propName: string]: any }> { return { version: this.ctor.version, commandId: this.ctor.commandId }; } // This is only temporary to find subclasses that used to implement this method. It was made async and renamed `requestFinish`. - private onFinish() { } + private onFinish() {} /** * Called when another EditCommand wishes to become the active EditCommand. @@ -66,14 +66,16 @@ export class EditCommand implements EditCommandIpc { * If it is not currently possible to finish, return any string other than "done" and the other EditCommand will have to wait and retry, * potentially showing the returned string to the user. */ - public async requestFinish(): Promise<"done" | string> { // eslint-disable-line @typescript-eslint/no-redundant-type-constituents + public async requestFinish(): Promise<"done" | string> { // eslint-disable-line @typescript-eslint/no-redundant-type-constituents this.onFinish(); // TODO: temporary, remove return "done"; } } class EditorAppHandler extends IpcHandler implements EditorIpc { - public get channelName() { return editorIpcStrings.channel; } + public get channelName() { + return editorIpcStrings.channel; + } public async startCommand(commandId: string, iModelKey: string, ...args: any[]) { await EditCommandAdmin.finishCommand(); @@ -112,7 +114,9 @@ export class EditCommandAdmin { private static _activeCommand?: EditCommand; private static _isInitialized = false; - public static get activeCommand() { return this._activeCommand; } + public static get activeCommand() { + return this._activeCommand; + } /** If any command is currently active, wait for it to finish. * Afterward, no command will be active. @@ -168,7 +172,7 @@ export class EditCommandAdmin { */ public static registerModule(moduleObj: any) { let foundOne = false; - for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in + for (const thisMember in moduleObj) { // eslint-disable-line guard-for-in const thisCmd = moduleObj[thisMember]; if (thisCmd.prototype instanceof EditCommand) { foundOne = true; diff --git a/editor/common/eslint.config.js b/editor/common/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/editor/common/eslint.config.js +++ b/editor/common/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/editor/common/src/EditorBuiltInIpc.ts b/editor/common/src/EditorBuiltInIpc.ts index 906873cfb360..259f8eaa5093 100644 --- a/editor/common/src/EditorBuiltInIpc.ts +++ b/editor/common/src/EditorBuiltInIpc.ts @@ -7,8 +7,15 @@ */ import { CompressedId64Set, Id64String, IModelStatus } from "@itwin/core-bentley"; +import { + EcefLocationProps, + ElementGeometryBuilderParams, + ElementGeometryInfo, + ElementGeometryOpcode, + GeometricElementProps, + GeometryPartProps, +} from "@itwin/core-common"; import { Matrix3dProps, Range3dProps, TransformProps } from "@itwin/core-geometry"; -import { EcefLocationProps, ElementGeometryBuilderParams, ElementGeometryInfo, ElementGeometryOpcode, GeometricElementProps, GeometryPartProps } from "@itwin/core-common"; import { EditCommandIpc } from "./EditorIpc"; /** Command ids for built in EditCommandIpc classes. diff --git a/editor/common/src/EditorIpc.ts b/editor/common/src/EditorIpc.ts index 4663f72a89f2..e7d25087156e 100644 --- a/editor/common/src/EditorIpc.ts +++ b/editor/common/src/EditorIpc.ts @@ -17,7 +17,6 @@ export const editorIpcStrings = { * @beta */ export interface EditorIpc { - /** Start a new instance of an `EditCommand` on the backend, and then call its `onStart` method. * @param commandId the Id of a registered `EditCommand` on the backend. If commandId === "", the current command is * requested to finish but no new EditCommand is started. diff --git a/editor/frontend/eslint.config.js b/editor/frontend/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/editor/frontend/eslint.config.js +++ b/editor/frontend/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/editor/frontend/src/CreateElementTool.ts b/editor/frontend/src/CreateElementTool.ts index 3114f9745860..aaa22ea6b2b4 100644 --- a/editor/frontend/src/CreateElementTool.ts +++ b/editor/frontend/src/CreateElementTool.ts @@ -8,9 +8,36 @@ */ import { Id64, Id64String, IModelStatus } from "@itwin/core-bentley"; +import { + DynamicGraphicsRequest2dProps, + DynamicGraphicsRequest3dProps, + FlatBufferGeometryStream, + GeometricElementProps, + IModelError, + isPlacement3dProps, + JsonGeometryStream, + PlacementProps, +} from "@itwin/core-common"; +import { + BeButtonEvent, + CoordSystem, + CoreTools, + DynamicsContext, + EventHandled, + GraphicBranch, + IModelApp, + IModelConnection, + PrimitiveTool, + readElementGraphics, + RenderGraphicOwner, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, + ToolAssistanceSection, + Viewport, +} from "@itwin/core-frontend"; import { Constant, Point3d, Range3d, Transform, Vector3d } from "@itwin/core-geometry"; -import { DynamicGraphicsRequest2dProps, DynamicGraphicsRequest3dProps, FlatBufferGeometryStream, GeometricElementProps, IModelError, isPlacement3dProps, JsonGeometryStream, PlacementProps } from "@itwin/core-common"; -import { BeButtonEvent, CoordSystem, CoreTools, DynamicsContext, EventHandled, GraphicBranch, IModelApp, IModelConnection, PrimitiveTool, readElementGraphics, RenderGraphicOwner, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection, Viewport } from "@itwin/core-frontend"; function computeChordToleranceFromPointAndRadius(vp: Viewport, center: Point3d, radius: number): number { if (vp.view.is3d() && vp.view.isCameraOn) { @@ -35,7 +62,9 @@ function computeChordToleranceFromPointAndRadius(vp: Viewport, center: Point3d, const viewPt = vp.worldToViewMap.transform0.multiplyPoint3dQuietNormalize(center); const viewPt2 = new Point3d(viewPt.x + 1.0, viewPt.y, viewPt.z); - const pixelSize = vp.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance(vp.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2)); + const pixelSize = vp.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt).distance( + vp.worldToViewMap.transform1.multiplyPoint3dQuietNormalize(viewPt2), + ); // Return size of a physical pixel in meters. return (0.0 !== pixelSize ? vp.target.adjustPixelSizeForLOD(pixelSize) : 0.001); @@ -76,10 +105,18 @@ export class DynamicGraphicsProvider { this.prefix = prefix; } - private getRequestId(id: Id64String): string { return `${this.prefix}-${id}`; } - private getToleranceLog10(): number { return Math.floor(Math.log10(this.chordTolerance)); } + private getRequestId(id: Id64String): string { + return `${this.prefix}-${id}`; + } + private getToleranceLog10(): number { + return Math.floor(Math.log10(this.chordTolerance)); + } - private async createRequest(categoryId: Id64String, placement: PlacementProps, geometry: JsonGeometryStream | FlatBufferGeometryStream): Promise { + private async createRequest( + categoryId: Id64String, + placement: PlacementProps, + geometry: JsonGeometryStream | FlatBufferGeometryStream, + ): Promise { let graphicData; let is3d; @@ -113,7 +150,10 @@ export class DynamicGraphicsProvider { if (undefined === graphicData) return; - const graphic = await readElementGraphics(graphicData, this.iModel, this.modelId ? this.modelId : Id64.invalid, is3d, { noFlash: true, noHilite: true }); + const graphic = await readElementGraphics(graphicData, this.iModel, this.modelId ? this.modelId : Id64.invalid, is3d, { + noFlash: true, + noHilite: true, + }); if (undefined === graphic) return; @@ -123,7 +163,11 @@ export class DynamicGraphicsProvider { /** Call to request a RenderGraphic for the supplied geometry and placement. * @see [[cleanupGraphic]] Must be called when the tool exits. */ - public async createGraphic(categoryId: Id64String, placement: PlacementProps, geometry: JsonGeometryStream | FlatBufferGeometryStream): Promise { + public async createGraphic( + categoryId: Id64String, + placement: PlacementProps, + geometry: JsonGeometryStream | FlatBufferGeometryStream, + ): Promise { try { const graphic = await this.createRequest(categoryId, placement, geometry); this.cleanupGraphic(); @@ -137,7 +181,12 @@ export class DynamicGraphicsProvider { * @note May be useful to update a dynamic preview outside of normal button and motion events, ex. modifier key change. * @see [[cleanupGraphic]] Must be called when the tool exits. */ - public createGraphicAndUpdateDynamics(ev: BeButtonEvent, categoryId: Id64String, placement: PlacementProps, geometry: JsonGeometryStream | FlatBufferGeometryStream): void { + public createGraphicAndUpdateDynamics( + ev: BeButtonEvent, + categoryId: Id64String, + placement: PlacementProps, + geometry: JsonGeometryStream | FlatBufferGeometryStream, + ): void { const promise = this._graphicPromise = this.createGraphic(categoryId, placement, geometry); promise.then(() => { @@ -145,7 +194,7 @@ export class DynamicGraphicsProvider { return; // abandoned this request... IModelApp.toolAdmin.updateDynamics(ev); - }).catch((_) => { }); + }).catch((_) => {}); } /** Call to dispose of [[RenderGraphic]] held by [[RenderGraphicOwner]]. @@ -205,17 +254,23 @@ export abstract class CreateElementTool extends PrimitiveTool { /** Whether [[setupAndPromptForNextAction]] should call [[AccuSnap.enableSnap]] for current tool phase. * @return true to enable snapping to elements. */ - protected get wantAccuSnap(): boolean { return false; } + protected get wantAccuSnap(): boolean { + return false; + } /** Whether to automatically start element dynamics on button event. * @return true if tool will implement [[InteractiveTool.onDynamicFrame]] to show element dynamics. */ - protected get wantDynamics(): boolean { return false; } + protected get wantDynamics(): boolean { + return false; + } /** Whether tool is ready to insert the new element. * @return true to call [[createElement]]. */ - protected isComplete(_ev: BeButtonEvent): boolean { return false; } + protected isComplete(_ev: BeButtonEvent): boolean { + return false; + } /** Insert new element and call [[saveChanges]] */ protected abstract createElement(): Promise; @@ -277,11 +332,19 @@ export abstract class CreateElementTool extends PrimitiveTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse), + ); + + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse), + ); if (undefined !== additionalInstr) { for (const instr of additionalInstr) { @@ -296,7 +359,10 @@ export abstract class CreateElementTool extends PrimitiveTool { sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); sections.push(ToolAssistance.createSection(touchInstructions, ToolAssistance.inputsLabel)); - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, undefined !== mainInstrText ? mainInstrText : CoreTools.translate(mainMsg)); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + undefined !== mainInstrText ? mainInstrText : CoreTools.translate(mainMsg), + ); const instructions = ToolAssistance.createInstructions(mainInstruction, sections); IModelApp.notifications.setToolAssistance(instructions); } @@ -323,8 +389,12 @@ export abstract class CreateElementTool extends PrimitiveTool { export abstract class CreateElementWithDynamicsTool extends CreateElementTool { protected _graphicsProvider?: DynamicGraphicsProvider; - protected override get wantAccuSnap(): boolean { return true; } - protected override get wantDynamics(): boolean { return true; } + protected override get wantAccuSnap(): boolean { + return true; + } + protected override get wantDynamics(): boolean { + return true; + } protected clearGraphics(): void { if (undefined === this._graphicsProvider) @@ -435,7 +505,7 @@ export abstract class CreateElementWithDynamicsTool extends CreateElementTool { /** Intended to be used to setupAccuSnap. Is called by [[setupAndPromptForNextAction]]. * @note Has not checked for [[wantAccuSnap]] at this point. Directly, *after* this method is called in [[setupAndPromptForNextAction]], AccuSnap will be enabled/disabled based on [[wantAccuSnap]]. */ - protected setupAccuDraw(): void { } + protected setupAccuDraw(): void {} protected override setupAndPromptForNextAction(): void { this.setupAccuDraw(); @@ -464,12 +534,14 @@ export abstract class CreateElementWithDynamicsTool extends CreateElementTool { /** Called by [[onResetButtonUp]]. * @returns return `false` if the event has been handled. */ - protected async cancelPoint(_ev: BeButtonEvent): Promise { return true; } + protected async cancelPoint(_ev: BeButtonEvent): Promise { + return true; + } /** Invoked when the reset button is released. * Propagates event to [[cancelPoint]]. * @caution Subclasses typically don't override this. - */ + */ public override async onResetButtonUp(ev: BeButtonEvent): Promise { if (!await this.cancelPoint(ev)) return EventHandled.Yes; diff --git a/editor/frontend/src/EditTool.ts b/editor/frontend/src/EditTool.ts index 100ba994f6c6..ffea4d07b5b4 100644 --- a/editor/frontend/src/EditTool.ts +++ b/editor/frontend/src/EditTool.ts @@ -10,9 +10,9 @@ import { BeDuration } from "@itwin/core-bentley"; import { _callIpcChannel, IModelApp, IpcApp } from "@itwin/core-frontend"; import { editorIpcStrings } from "@itwin/editor-common"; -import * as UndoRedoTools from "./UndoRedoTool"; import * as ProjectLocation from "./ProjectLocation/ProjectExtentsDecoration"; import * as ProjectGeoLocation from "./ProjectLocation/ProjectGeolocation"; +import * as UndoRedoTools from "./UndoRedoTool"; /** @beta */ export namespace EditTools { @@ -42,7 +42,13 @@ export class EditTools { let attempt = 0; while (true) { try { - return await (IpcApp[_callIpcChannel](editorIpcStrings.channel, "startCommand", startArg.commandId, startArg.iModelKey, ...cmdArgs) as Promise); + return await (IpcApp[_callIpcChannel]( + editorIpcStrings.channel, + "startCommand", + startArg.commandId, + startArg.iModelKey, + ...cmdArgs, + ) as Promise); } catch (e: any) { if (e.name !== editorIpcStrings.commandBusy) throw e; // unknown backend error diff --git a/editor/frontend/src/EditToolIpc.ts b/editor/frontend/src/EditToolIpc.ts index 87c1d14b62a0..a94a853127e2 100644 --- a/editor/frontend/src/EditToolIpc.ts +++ b/editor/frontend/src/EditToolIpc.ts @@ -22,4 +22,3 @@ export function makeEditToolIpc(): PickAsyncMethods * @internal */ export const basicManipulationIpc = makeEditToolIpc(); - diff --git a/editor/frontend/src/ModifyElementTool.ts b/editor/frontend/src/ModifyElementTool.ts index 4e1a1c279740..54958c21d08d 100644 --- a/editor/frontend/src/ModifyElementTool.ts +++ b/editor/frontend/src/ModifyElementTool.ts @@ -9,7 +9,19 @@ import { Id64, Id64Arg, Id64Array, Id64String } from "@itwin/core-bentley"; import { FeatureAppearance, FlatBufferGeometryStream, GeometricElementProps, JsonGeometryStream } from "@itwin/core-common"; -import { BeButtonEvent, DynamicsContext, ElementSetTool, FeatureOverrideProvider, FeatureSymbology, HitDetail, IModelApp, LocateResponse, SelectionMethod, SelectionSet, Viewport } from "@itwin/core-frontend"; +import { + BeButtonEvent, + DynamicsContext, + ElementSetTool, + FeatureOverrideProvider, + FeatureSymbology, + HitDetail, + IModelApp, + LocateResponse, + SelectionMethod, + SelectionSet, + Viewport, +} from "@itwin/core-frontend"; import { Point3d } from "@itwin/core-geometry"; import { computeChordToleranceFromPoint, DynamicGraphicsProvider } from "./CreateElementTool"; @@ -19,12 +31,20 @@ import { computeChordToleranceFromPoint, DynamicGraphicsProvider } from "./Creat export abstract class ModifyElementTool extends ElementSetTool { protected readonly _checkedIds = new Map(); - protected allowView(_vp: Viewport) { return true; } - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); } + protected allowView(_vp: Viewport) { + return true; + } + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && this.allowView(vp)); + } - protected onGeometryFilterChanged(): void { this._checkedIds.clear(); } + protected onGeometryFilterChanged(): void { + this._checkedIds.clear(); + } - protected async doAcceptElementForOperation(_id: Id64String): Promise { return false; } + protected async doAcceptElementForOperation(_id: Id64String): Promise { + return false; + } protected async acceptElementForOperation(id: Id64String): Promise { if (Id64.isInvalid(id) || Id64.isTransient(id)) @@ -69,11 +89,17 @@ export abstract class ModifyElementTool extends ElementSetTool { return this.postFilterIds(await super.getSelectionSetCandidates(ss)); } - protected override async getDragSelectCandidates(vp: Viewport, origin: Point3d, corner: Point3d, method: SelectionMethod, overlap: boolean): Promise { + protected override async getDragSelectCandidates( + vp: Viewport, + origin: Point3d, + corner: Point3d, + method: SelectionMethod, + overlap: boolean, + ): Promise { return this.postFilterIds(await super.getDragSelectCandidates(vp, origin, corner, method, overlap)); } - protected setupAccuDraw(): void { } + protected setupAccuDraw(): void {} protected override setupAndPromptForNextAction(): void { this.setupAccuDraw(); @@ -83,7 +109,9 @@ export abstract class ModifyElementTool extends ElementSetTool { protected abstract getGeometryProps(ev: BeButtonEvent, isAccept: boolean): JsonGeometryStream | FlatBufferGeometryStream | undefined; protected abstract getElementProps(ev: BeButtonEvent): GeometricElementProps | undefined; - protected async doUpdateElement(_props: GeometricElementProps): Promise { return false; } + protected async doUpdateElement(_props: GeometricElementProps): Promise { + return false; + } protected async applyAgendaOperation(ev: BeButtonEvent): Promise { const geometry = this.getGeometryProps(ev, true); @@ -117,8 +145,12 @@ export abstract class ModifyElementWithDynamicsTool extends ModifyElementTool im protected _agendaAppearanceDefault?: FeatureAppearance; protected _agendaAppearanceDynamic?: FeatureAppearance; - protected override get wantAccuSnap(): boolean { return true; } - protected override get wantDynamics(): boolean { return true; } + protected override get wantAccuSnap(): boolean { + return true; + } + protected override get wantDynamics(): boolean { + return true; + } protected agendaAppearance(isDynamics: boolean): FeatureAppearance { if (isDynamics) { @@ -134,7 +166,9 @@ export abstract class ModifyElementWithDynamicsTool extends ModifyElementTool im return this._agendaAppearanceDefault; } - protected get wantAgendaAppearanceOverride(): boolean { return false; } + protected get wantAgendaAppearanceOverride(): boolean { + return false; + } public addFeatureOverrides(overrides: FeatureSymbology.Overrides, _vp: Viewport): void { if (this.agenda.isEmpty) diff --git a/editor/frontend/src/ProjectLocation/ProjectExtentsDecoration.ts b/editor/frontend/src/ProjectLocation/ProjectExtentsDecoration.ts index 1a25ae1cac01..03c26d87a0e1 100644 --- a/editor/frontend/src/ProjectLocation/ProjectExtentsDecoration.ts +++ b/editor/frontend/src/ProjectLocation/ProjectExtentsDecoration.ts @@ -9,13 +9,48 @@ import { BeDuration, BeEvent, BentleyError } from "@itwin/core-bentley"; import { Cartographic, ColorDef, EcefLocation, EcefLocationProps } from "@itwin/core-common"; import { - BeButton, BeButtonEvent, BriefcaseConnection, CoreTools, DecorateContext, EditManipulator, EventHandled, GraphicType, HitDetail, IModelApp, - IModelConnection, MessageBoxIconType, MessageBoxType, MessageBoxValue, NotifyMessageDetails, OutputMessagePriority, QuantityType, ScreenViewport, - Tool, ViewClipControlArrow, ViewClipDecorationProvider, ViewClipShapeModifyTool, ViewClipTool, Viewport, + BeButton, + BeButtonEvent, + BriefcaseConnection, + CoreTools, + DecorateContext, + EditManipulator, + EventHandled, + GraphicType, + HitDetail, + IModelApp, + IModelConnection, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + NotifyMessageDetails, + OutputMessagePriority, + QuantityType, + ScreenViewport, + Tool, + ViewClipControlArrow, + ViewClipDecorationProvider, + ViewClipShapeModifyTool, + ViewClipTool, + Viewport, } from "@itwin/core-frontend"; import { - Angle, Arc3d, AxisIndex, AxisOrder, ClipShape, ClipVector, Constant, Matrix3d, Point3d, PolygonOps, Range1d, Range3d, Range3dProps, Ray3d, - Transform, Vector3d, + Angle, + Arc3d, + AxisIndex, + AxisOrder, + ClipShape, + ClipVector, + Constant, + Matrix3d, + Point3d, + PolygonOps, + Range1d, + Range3d, + Range3dProps, + Ray3d, + Transform, + Vector3d, } from "@itwin/core-geometry"; import { editorBuiltInCmdIds } from "@itwin/editor-common"; import { EditTools } from "../EditTool"; @@ -159,7 +194,11 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider } private getClipData(): boolean { - this._clip = this._clipShape = this._clipShapeExtents = this._clipRange = undefined; + this._clip = + this._clipShape = + this._clipShapeExtents = + this._clipRange = + undefined; const clip = this.viewport.view.getViewClip(); if (undefined === clip) return false; @@ -220,12 +259,19 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider const faceNormal = edgeTangent.crossProduct(shapeArea.direction); faceNormal.normalizeInPlace(); this._controls[i] = new ProjectExtentsControlArrow(faceCenter, faceNormal, 0.75); - this._controls[i].extentValid = (faceNormal.isParallelTo(Vector3d.unitX(), true) ? this._extentsLengthValid : this._extentsWidthValid); + this._controls[i].extentValid = faceNormal.isParallelTo(Vector3d.unitX(), true) ? this._extentsLengthValid : this._extentsWidthValid; } const zFillColor = ColorDef.from(150, 150, 250); this._controls[numControls - 2] = new ProjectExtentsControlArrow(shapeArea.origin, Vector3d.unitZ(-1.0), 0.75, zFillColor, undefined, "zLow"); - this._controls[numControls - 1] = new ProjectExtentsControlArrow(shapeArea.origin.plusScaled(Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), Vector3d.unitZ(), 0.75, zFillColor, undefined, "zHigh"); + this._controls[numControls - 1] = new ProjectExtentsControlArrow( + shapeArea.origin.plusScaled(Vector3d.unitZ(), shapePtsLo[0].distance(shapePtsHi[0])), + Vector3d.unitZ(), + 0.75, + zFillColor, + undefined, + "zHigh", + ); this._controls[numControls - 2].extentValid = this._extentsHeightValid; this._controls[numControls - 1].extentValid = this._extentsHeightValid; @@ -233,10 +279,14 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider } /** Allow project extents for map projections to be larger since curvature of the earth is accounted for. */ - protected get maxExtentLength(): number { return ((this._allowEcefLocationChange ? 20 : 350) * Constant.oneKilometer); } + protected get maxExtentLength(): number { + return ((this._allowEcefLocationChange ? 20 : 350) * Constant.oneKilometer); + } /** Impose some reasonable height limit for project extents. */ - protected get maxExtentHeight(): number { return (2 * Constant.oneKilometer); } + protected get maxExtentHeight(): number { + return (2 * Constant.oneKilometer); + } protected hasValidGCS(): boolean { if (!this.iModel.isGeoLocated || this.iModel.noGcsDefined) @@ -247,9 +297,9 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider return false; // A valid GCS ought to have horizontalCR defined... // Check for approximate GCS (such as from MicroStation's "From Placemark" tool) and allow it to be replaced... - const hasValidId = (undefined !== gcs.horizontalCRS.id && 0 !== gcs.horizontalCRS.id.length); - const hasValidDescr = (undefined !== gcs.horizontalCRS.description && 0 !== gcs.horizontalCRS.description.length); - const hasValidProjection = (undefined !== gcs.horizontalCRS.projection && "AzimuthalEqualArea" !== gcs.horizontalCRS.projection.method); + const hasValidId = undefined !== gcs.horizontalCRS.id && 0 !== gcs.horizontalCRS.id.length; + const hasValidDescr = undefined !== gcs.horizontalCRS.description && 0 !== gcs.horizontalCRS.description.length; + const hasValidProjection = undefined !== gcs.horizontalCRS.projection && "AzimuthalEqualArea" !== gcs.horizontalCRS.projection.method; return hasValidId || hasValidDescr || hasValidProjection; } @@ -262,9 +312,9 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider this._allowEcefLocationChange = !this.hasValidGCS(); if (undefined !== this._clipRange) { - this._extentsLengthValid = (this._clipRange.xLength() < this.maxExtentLength); - this._extentsWidthValid = (this._clipRange.yLength() < this.maxExtentLength); - this._extentsHeightValid = (this._clipRange.zLength() < this.maxExtentHeight); + this._extentsLengthValid = this._clipRange.xLength() < this.maxExtentLength; + this._extentsWidthValid = this._clipRange.yLength() < this.maxExtentLength; + this._extentsHeightValid = this._clipRange.zLength() < this.maxExtentHeight; } // Show controls if only range box and it's controls are selected, selection set doesn't include any other elements... @@ -306,9 +356,13 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider return this._suspendDecorator; } - protected override async onRightClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { return EventHandled.No; } + protected override async onRightClick(_hit: HitDetail, _ev: BeButtonEvent): Promise { + return EventHandled.No; + } - protected override async onTouchTap(hit: HitDetail, ev: BeButtonEvent): Promise { return (hit.sourceId === this._clipId ? EventHandled.No : super.onTouchTap(hit, ev)); } + protected override async onTouchTap(hit: HitDetail, ev: BeButtonEvent): Promise { + return (hit.sourceId === this._clipId ? EventHandled.No : super.onTouchTap(hit, ev)); + } public override async onDecorationButtonEvent(hit: HitDetail, ev: BeButtonEvent): Promise { if (hit.sourceId === this._monumentId) { @@ -361,7 +415,6 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider toolTipHtml += `${translateCoreMeasureBold("LatLong") + formattedLat + latDir}, ${formattedLong}${longDir}
    `; toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedHeight}
    `; } - } else if (hit.sourceId === this._northId) { toolTipHtml += `${translateMessage("ModifyNorthDirection")}
    `; @@ -370,9 +423,8 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider const formattedAngle = quantityFormatter.formatQuantity(this.getClockwiseAngleToNorth().radians, angleFormatterSpec); toolTipHtml += `${translateMessageBold("Angle") + formattedAngle}
    `; } - } else if (hit.sourceId === this._clipId) { - const extentsValid = (this._extentsLengthValid && this._extentsWidthValid && this._extentsHeightValid); + const extentsValid = this._extentsLengthValid && this._extentsWidthValid && this._extentsHeightValid; toolTipHtml += `${translateMessage(extentsValid ? "ProjectExtents" : "LargeProjectExtents")}
    `; const distanceFormatterSpec = quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Length); @@ -384,7 +436,6 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider toolTipHtml += `${translateMessageBold("Width") + formattedWidth}
    `; toolTipHtml += `${translateMessageBold("Height") + formattedHeight}
    `; } - } else { const arrowIndex = this._controlIds.indexOf(hit.sourceId); if (-1 !== arrowIndex) { @@ -414,9 +465,11 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider if (!this._extentsHeightValid) arrowLengthMax = this.maxExtentHeight; - const coordFormatterSpec = (this.iModel.isGeoLocated ? quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Coordinate) : undefined); + const coordFormatterSpec = this.iModel.isGeoLocated + ? quantityFormatter.findFormatterSpecByQuantityType(QuantityType.Coordinate) + : undefined; if (undefined !== coordFormatterSpec) { - const heightPt = ("zLow" === arrowControl.name ? this._clipRange.low : this._clipRange.high); + const heightPt = "zLow" === arrowControl.name ? this._clipRange.low : this._clipRange.high; const cartographic = this.iModel.spatialToCartographicFromEcef(heightPt); const formattedAltitude = quantityFormatter.formatQuantity(cartographic.height, coordFormatterSpec); toolTipHtml += `${translateCoreMeasureBold("Altitude") + formattedAltitude}
    `; @@ -438,8 +491,12 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider return toolTip; } - public testDecorationHit(id: string): boolean { return (id === this._monumentId || id === this._northId || id === this._clipId || this._controlIds.includes(id)); } - protected override updateDecorationListener(_add: boolean): void { super.updateDecorationListener(undefined !== this._clipId); } // Decorator isn't just for resize controls... + public testDecorationHit(id: string): boolean { + return (id === this._monumentId || id === this._northId || id === this._clipId || this._controlIds.includes(id)); + } + protected override updateDecorationListener(_add: boolean): void { + super.updateDecorationListener(undefined !== this._clipId); + } // Decorator isn't just for resize controls... public getMonumentPoint(): Point3d { const origin = Point3d.createZero(); @@ -458,12 +515,12 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider } public getNorthAngle(): Angle { - const northDirection = (undefined !== this._northDirection ? this._northDirection : this.getNorthDirection()); + const northDirection = undefined !== this._northDirection ? this._northDirection : this.getNorthDirection(); return northDirection.direction.angleToXY(Vector3d.unitY()); } public getNorthDirection(refOrigin?: Point3d): Ray3d { - const origin = (undefined !== refOrigin ? refOrigin : this.iModel.projectExtents.center); + const origin = undefined !== refOrigin ? refOrigin : this.iModel.projectExtents.center; if (!this.iModel.isGeoLocated) return Ray3d.create(origin, Vector3d.unitY()); @@ -614,7 +671,6 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider ctx.moveTo(0, (sizePixels * 0.3) + 4); ctx.lineTo(0, (sizePixels * 0.3) + 4.5); ctx.stroke(); - }; context.addCanvasDecoration({ position, drawDecoration }); } @@ -640,7 +696,14 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider if (!this.suspendGeolocationDecorations && undefined !== this._monumentPoint && this._allowEcefLocationChange) this.drawMonumentPoint(context, this._monumentPoint, 1.0, this._monumentId); - ViewClipTool.drawClipShape(context, this._clipShape, this._clipShapeExtents!, ColorDef.white.adjustedForContrast(context.viewport.view.backgroundColor), 3, this._clipId); + ViewClipTool.drawClipShape( + context, + this._clipShape, + this._clipShapeExtents!, + ColorDef.white.adjustedForContrast(context.viewport.view.backgroundColor), + 3, + this._clipId, + ); this.drawAreaTooLargeIndicator(context); if (!this._isActive) @@ -657,7 +720,11 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider if (0.0 === sizeInches) continue; - const anchorRay = ViewClipTool.getClipRayTransformed(this._controls[iFace].origin, this._controls[iFace].direction, undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined); + const anchorRay = ViewClipTool.getClipRayTransformed( + this._controls[iFace].origin, + this._controls[iFace].direction, + undefined !== this._clipShape ? this._clipShape.transformFromClip : undefined, + ); const transform = EditManipulator.HandleUtils.getArrowTransform(vp, anchorRay.origin, anchorRay.direction, sizeInches); if (undefined === transform) continue; @@ -742,7 +809,7 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider if (!this._allowEcefLocationChange) return false; - const newEcefLocation = EcefLocation.createFromCartographicOrigin(origin, point, (undefined !== angle ? angle : this.getNorthAngle())); // Preserve modified north direction... + const newEcefLocation = EcefLocation.createFromCartographicOrigin(origin, point, undefined !== angle ? angle : this.getNorthAngle()); // Preserve modified north direction... const ecefLocation = this.iModel.ecefLocation; if (undefined !== ecefLocation && ecefLocation.isAlmostEqual(newEcefLocation)) return false; @@ -762,7 +829,7 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider if (!this._allowEcefLocationChange || !this.iModel.isGeoLocated) return false; - const point = (undefined !== this._monumentPoint ? this._monumentPoint : this.getMonumentPoint()); // Preserve modified monument point... + const point = undefined !== this._monumentPoint ? this._monumentPoint : this.getMonumentPoint(); // Preserve modified monument point... const origin = this.iModel.spatialToCartographicFromEcef(point); const saveDirection = this._northDirection; @@ -845,7 +912,9 @@ export class ProjectExtentsClipDecoration extends EditManipulator.HandleProvider ViewClipTool.setViewClip(vp, deco._clip); } if (undefined === deco._removeManipulatorToolListener) { - deco._removeManipulatorToolListener = IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => deco.onManipulatorToolEvent(tool, event)); + deco._removeManipulatorToolListener = IModelApp.toolAdmin.manipulatorToolEvent.addListener((tool, event) => + deco.onManipulatorToolEvent(tool, event) + ); deco.start(); deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Show); } @@ -950,7 +1019,10 @@ export class ProjectLocationSaveTool extends Tool { return true; // NOTE: Default if openMessageBox isn't implemented is MessageBoxValue.Ok, so we'll check No instead of Yes... - if (MessageBoxValue.No === await IModelApp.notifications.openMessageBox(MessageBoxType.YesNo, translateMessage("RestartTxn"), MessageBoxIconType.Question)) + if ( + MessageBoxValue.No === + await IModelApp.notifications.openMessageBox(MessageBoxType.YesNo, translateMessage("RestartTxn"), MessageBoxIconType.Question) + ) return false; return true; @@ -975,7 +1047,9 @@ export class ProjectLocationSaveTool extends Tool { await deco.iModel.saveChanges(this.toolId); await deco.iModel.txns.restartTxnSession(); } catch (err) { - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred.")); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."), + ); } deco.onChanged.raiseEvent(deco.iModel, ProjectLocationChanged.Save); diff --git a/editor/frontend/src/ProjectLocation/ProjectGeolocation.ts b/editor/frontend/src/ProjectLocation/ProjectGeolocation.ts index 1378395dd31b..0ed3a7cbe5da 100644 --- a/editor/frontend/src/ProjectLocation/ProjectGeolocation.ts +++ b/editor/frontend/src/ProjectLocation/ProjectGeolocation.ts @@ -6,12 +6,30 @@ * @module Editing */ -import { AccuDrawHintBuilder, AngleDescription, BeButtonEvent, CanvasDecoration, CoreTools, DecorateContext, EventHandled, GraphicType, IModelApp, LengthDescription, PrimitiveTool, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, ToolAssistanceSection, Viewport } from "@itwin/core-frontend"; -import { Angle, Matrix3d, Point3d, Ray3d, Vector3d, XYAndZ } from "@itwin/core-geometry"; -import { Cartographic, ColorDef, LinePixels } from "@itwin/core-common"; -import { ProjectExtentsClipDecoration } from "./ProjectExtentsDecoration"; import { DialogItem, DialogProperty, DialogPropertySyncItem } from "@itwin/appui-abstract"; +import { Cartographic, ColorDef, LinePixels } from "@itwin/core-common"; +import { + AccuDrawHintBuilder, + AngleDescription, + BeButtonEvent, + CanvasDecoration, + CoreTools, + DecorateContext, + EventHandled, + GraphicType, + IModelApp, + LengthDescription, + PrimitiveTool, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, + ToolAssistanceSection, + Viewport, +} from "@itwin/core-frontend"; +import { Angle, Matrix3d, Point3d, Ray3d, Vector3d, XYAndZ } from "@itwin/core-geometry"; import { EditTools } from "../EditTool"; +import { ProjectExtentsClipDecoration } from "./ProjectExtentsDecoration"; function translatePrompt(key: string) { return EditTools.translate(`ProjectLocation:Prompts.${key}`); @@ -72,8 +90,12 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { public static override toolId = "ProjectLocation.Geolocation.Point"; public static override iconSpec = "icon-globe"; // <== Tool button should use whatever icon you have here... - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } // latitude, longitude, altitude, north direction... + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } // latitude, longitude, altitude, north direction... protected _haveToolSettings = false; protected _cartographicFromArgs = false; @@ -83,9 +105,15 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { protected _origin?: Point3d; protected _labelDeco?: LabelDecoration; - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); } - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } // Allow snapping to terrain, etc. outside project extents... - public override requireWriteableTarget(): boolean { return false; } // Tool doesn't modify the imodel... + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); + } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } // Allow snapping to terrain, etc. outside project extents... + public override requireWriteableTarget(): boolean { + return false; + } // Tool doesn't modify the imodel... public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); @@ -96,8 +124,12 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { this.unsuspendDecorations(); } - public async onRestartTool() { return this.exitTool(); } - public override async onUnsuspend() { this.provideToolAssistance(); } + public async onRestartTool() { + return this.exitTool(); + } + public override async onUnsuspend() { + this.provideToolAssistance(); + } private _latitudeProperty: DialogProperty | undefined; public get latitudeProperty() { @@ -106,8 +138,12 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { return this._latitudeProperty; } - public get latitude(): number { return this.latitudeProperty.value; } - public set latitude(value: number) { this.latitudeProperty.value = value; } + public get latitude(): number { + return this.latitudeProperty.value; + } + public set latitude(value: number) { + this.latitudeProperty.value = value; + } private _longitudeProperty: DialogProperty | undefined; public get longitudeProperty() { @@ -116,8 +152,12 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { return this._longitudeProperty; } - public get longitude(): number { return this.longitudeProperty.value; } - public set longitude(value: number) { this.longitudeProperty.value = value; } + public get longitude(): number { + return this.longitudeProperty.value; + } + public set longitude(value: number) { + this.longitudeProperty.value = value; + } private _altitudeProperty: DialogProperty | undefined; public get altitudeProperty() { @@ -126,8 +166,12 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { return this._altitudeProperty; } - public get altitude(): number { return this.altitudeProperty.value; } - public set altitude(value: number) { this.altitudeProperty.value = value; } + public get altitude(): number { + return this.altitudeProperty.value; + } + public set altitude(value: number) { + this.altitudeProperty.value = value; + } private _northProperty: DialogProperty | undefined; public get northProperty() { @@ -136,11 +180,20 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { return this._northProperty; } - public get north(): number { return this.northProperty.value; } - public set north(value: number) { this.northProperty.value = value; } + public get north(): number { + return this.northProperty.value; + } + public set north(value: number) { + this.northProperty.value = value; + } private syncToolSettingsCoordinates(): void { - this.syncToolSettingsProperties([this.latitudeProperty.syncItem, this.longitudeProperty.syncItem, this.altitudeProperty.syncItem, this.northProperty.syncItem]); + this.syncToolSettingsProperties([ + this.latitudeProperty.syncItem, + this.longitudeProperty.syncItem, + this.altitudeProperty.syncItem, + this.northProperty.syncItem, + ]); } public override async applyToolSettingPropertyChange(updatedValue: DialogPropertySyncItem): Promise { @@ -160,7 +213,10 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { protected provideToolAssistance(): void { const acceptMsg = CoreTools.translate(undefined === this._origin ? "ElementSet.Inputs.AcceptPoint" : "ElementSet.Inputs.Accept"); const rejectMsg = CoreTools.translate("ElementSet.Inputs.Cancel"); - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, translatePrompt(undefined === this._origin ? "IdentifyKnownLocation" : "ConfirmCoordinates")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + translatePrompt(undefined === this._origin ? "IdentifyKnownLocation" : "ConfirmCoordinates"), + ); const sections: ToolAssistanceSection[] = []; const mouseInstructions: ToolAssistanceInstruction[] = []; @@ -346,7 +402,9 @@ export class ProjectGeolocationPointTool extends PrimitiveTool { return this.run(); } - public static async startTool(): Promise { return new ProjectGeolocationPointTool().run(); } + public static async startTool(): Promise { + return new ProjectGeolocationPointTool().run(); + } } /** Change or update geolocation direction to true north. @@ -358,9 +416,15 @@ export class ProjectGeolocationNorthTool extends PrimitiveTool { protected _origin?: Point3d; protected _northDir?: Ray3d; - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); } - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } // Allow snapping to terrain, etc. outside project extents... - public override requireWriteableTarget(): boolean { return false; } // Tool doesn't modify the imodel... + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); + } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } // Allow snapping to terrain, etc. outside project extents... + public override requireWriteableTarget(): boolean { + return false; + } // Tool doesn't modify the imodel... public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); @@ -369,13 +433,20 @@ export class ProjectGeolocationNorthTool extends PrimitiveTool { await super.onCleanup(); this.unsuspendDecorations(); } - public async onRestartTool() { return this.exitTool(); } - public override async onUnsuspend() { this.provideToolAssistance(); } + public async onRestartTool() { + return this.exitTool(); + } + public override async onUnsuspend() { + this.provideToolAssistance(); + } protected provideToolAssistance(): void { const acceptMsg = CoreTools.translate("ElementSet.Inputs.AcceptPoint"); const rejectMsg = CoreTools.translate("ElementSet.Inputs.Cancel"); - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, translatePrompt(undefined === this._origin ? "IdentifyRefPoint" : "DefineAngle")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + translatePrompt(undefined === this._origin ? "IdentifyRefPoint" : "DefineAngle"), + ); const sections: ToolAssistanceSection[] = []; const mouseInstructions: ToolAssistanceInstruction[] = []; @@ -489,9 +560,13 @@ export class ProjectGeolocationNorthTool extends PrimitiveTool { return EventHandled.No; } - public override async onInstall(): Promise { return ProjectExtentsClipDecoration.allowEcefLocationChange(true); } + public override async onInstall(): Promise { + return ProjectExtentsClipDecoration.allowEcefLocationChange(true); + } - public static async startTool() { return new ProjectGeolocationNorthTool().run(); } + public static async startTool() { + return new ProjectGeolocationNorthTool().run(); + } } /** Move a geolocated model by specifying two points to define the offset. @@ -503,9 +578,15 @@ export class ProjectGeolocationMoveTool extends PrimitiveTool { protected _origin?: Point3d; protected _current?: Point3d; - public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); } - public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { return true; } // Allow snapping to terrain, etc. outside project extents... - public override requireWriteableTarget(): boolean { return false; } // Tool doesn't modify the imodel... + public override isCompatibleViewport(vp: Viewport | undefined, isSelectedViewChange: boolean): boolean { + return (super.isCompatibleViewport(vp, isSelectedViewChange) && undefined !== vp && vp.view.isSpatialView()); + } + public override isValidLocation(_ev: BeButtonEvent, _isButtonEvent: boolean): boolean { + return true; + } // Allow snapping to terrain, etc. outside project extents... + public override requireWriteableTarget(): boolean { + return false; + } // Tool doesn't modify the imodel... public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); @@ -520,12 +601,17 @@ export class ProjectGeolocationMoveTool extends PrimitiveTool { return this.exitTool(); } - public override async onUnsuspend() { this.provideToolAssistance(); } + public override async onUnsuspend() { + this.provideToolAssistance(); + } protected provideToolAssistance(): void { const acceptMsg = CoreTools.translate("ElementSet.Inputs.AcceptPoint"); const rejectMsg = CoreTools.translate("ElementSet.Inputs.Cancel"); - const mainInstruction = ToolAssistance.createInstruction(this.iconSpec, translatePrompt(undefined === this._origin ? "IdentifyRefPoint" : "DefineOffset")); + const mainInstruction = ToolAssistance.createInstruction( + this.iconSpec, + translatePrompt(undefined === this._origin ? "IdentifyRefPoint" : "DefineOffset"), + ); const sections: ToolAssistanceSection[] = []; const mouseInstructions: ToolAssistanceInstruction[] = []; @@ -637,8 +723,11 @@ export class ProjectGeolocationMoveTool extends PrimitiveTool { return EventHandled.No; } - public override async onInstall(): Promise { return ProjectExtentsClipDecoration.allowEcefLocationChange(true); } + public override async onInstall(): Promise { + return ProjectExtentsClipDecoration.allowEcefLocationChange(true); + } - public static async startTool() { return new ProjectGeolocationMoveTool().run(); } + public static async startTool() { + return new ProjectGeolocationMoveTool().run(); + } } - diff --git a/editor/frontend/src/TransformElementsTool.ts b/editor/frontend/src/TransformElementsTool.ts index bd297a6841be..b75c4f54cb14 100644 --- a/editor/frontend/src/TransformElementsTool.ts +++ b/editor/frontend/src/TransformElementsTool.ts @@ -8,8 +8,31 @@ */ import { BentleyError, Id64, Id64Arg, Id64String } from "@itwin/core-bentley"; -import { GeometricElementProps, IModelStatus, isPlacement2dProps, PersistentGraphicsRequestProps, Placement, Placement2d, Placement3d } from "@itwin/core-common"; -import { AccuDrawHintBuilder, BeButtonEvent, DynamicsContext, ElementSetTool, GraphicBranch, IModelApp, IModelConnection, IpcApp, ModifyElementSource, NotifyMessageDetails, OutputMessagePriority, readElementGraphics, RenderGraphic, RenderGraphicOwner } from "@itwin/core-frontend"; +import { + GeometricElementProps, + IModelStatus, + isPlacement2dProps, + PersistentGraphicsRequestProps, + Placement, + Placement2d, + Placement3d, +} from "@itwin/core-common"; +import { + AccuDrawHintBuilder, + BeButtonEvent, + DynamicsContext, + ElementSetTool, + GraphicBranch, + IModelApp, + IModelConnection, + IpcApp, + ModifyElementSource, + NotifyMessageDetails, + OutputMessagePriority, + readElementGraphics, + RenderGraphic, + RenderGraphicOwner, +} from "@itwin/core-frontend"; import { Transform } from "@itwin/core-geometry"; import { editorBuiltInCmdIds } from "@itwin/editor-common"; import { EditTools } from "./EditTool"; @@ -42,8 +65,12 @@ export class TransformGraphicsProvider { this.pending = new Map(); } - private getRequestId(id: Id64String): string { return `${this.prefix}-${id}`; } - private getToleranceLog10(): number { return Math.floor(Math.log10(this.chordTolerance)); } + private getRequestId(id: Id64String): string { + return `${this.prefix}-${id}`; + } + private getToleranceLog10(): number { + return Math.floor(Math.log10(this.chordTolerance)); + } private async createRequest(id: Id64String): Promise { const elementProps = (await this.iModel.elements.getProps(id)) as GeometricElementProps[]; @@ -98,8 +125,8 @@ export class TransformGraphicsProvider { } /** Call to request a RenderGraphic for the supplied element id. - * @see [[cleanupGraphics]] Must be called when the tool exits. - */ + * @see [[cleanupGraphics]] Must be called when the tool exits. + */ public async createSingleGraphic(id: Id64String): Promise { try { const info = await this.createRequest(id); @@ -139,7 +166,7 @@ export class TransformGraphicsProvider { this.data.push(info); }); } - } catch { } + } catch {} } /** Call to dispose of [[RenderGraphic]] held by [[RenderGraphicOwner]] and cancel requests that are still pending. @@ -189,14 +216,30 @@ export class TransformGraphicsProvider { * @beta */ export abstract class TransformElementsTool extends ElementSetTool { - protected override get allowSelectionSet(): boolean { return true; } - protected override get allowGroups(): boolean { return true; } - protected override get allowDragSelect(): boolean { return true; } - protected override get controlKeyContinuesSelection(): boolean { return true; } - protected override get wantAccuSnap(): boolean { return true; } - protected override get wantDynamics(): boolean { return true; } - protected get wantMakeCopy(): boolean { return false; } - protected get wantRepeatOperation(): boolean { return this.wantMakeCopy && !this.agenda.isEmpty; } + protected override get allowSelectionSet(): boolean { + return true; + } + protected override get allowGroups(): boolean { + return true; + } + protected override get allowDragSelect(): boolean { + return true; + } + protected override get controlKeyContinuesSelection(): boolean { + return true; + } + protected override get wantAccuSnap(): boolean { + return true; + } + protected override get wantDynamics(): boolean { + return true; + } + protected get wantMakeCopy(): boolean { + return false; + } + protected get wantRepeatOperation(): boolean { + return this.wantMakeCopy && !this.agenda.isEmpty; + } protected _graphicsProvider?: TransformGraphicsProvider; protected _startedCmd?: string; @@ -299,7 +342,9 @@ export abstract class TransformElementsTool extends ElementSetTool { if (IModelStatus.Success === await basicManipulationIpc.transformPlacement(this.agenda.compressIds(), transform.toJSON())) await this.saveChanges(); } catch (err) { - IModelApp.notifications.outputMessage(new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred.")); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails(OutputMessagePriority.Error, BentleyError.getErrorMessage(err) || "An unknown error occurred."), + ); } } @@ -327,4 +372,3 @@ export abstract class TransformElementsTool extends ElementSetTool { return super.onCleanup(); } } - diff --git a/editor/frontend/src/UndoRedoTool.ts b/editor/frontend/src/UndoRedoTool.ts index d38f15f3b66e..a79632dc47f5 100644 --- a/editor/frontend/src/UndoRedoTool.ts +++ b/editor/frontend/src/UndoRedoTool.ts @@ -45,4 +45,3 @@ export class RedoTool extends Tool { return true; } } - diff --git a/editor/frontend/src/public/locales/en/Editor.json b/editor/frontend/src/public/locales/en/Editor.json index 65f02d75770a..3bac3a1e37c5 100644 --- a/editor/frontend/src/public/locales/en/Editor.json +++ b/editor/frontend/src/public/locales/en/Editor.json @@ -77,4 +77,4 @@ } } } -} \ No newline at end of file +} diff --git a/example-code/app/RobotWorldEngine.config.json b/example-code/app/RobotWorldEngine.config.json index c3b23a07a9ff..944abf99a2cd 100644 --- a/example-code/app/RobotWorldEngine.config.json +++ b/example-code/app/RobotWorldEngine.config.json @@ -1 +1,20 @@ -{"loggerConfig":{"defaultLevel":"${ROBOT-WORLD-DEFAULT-LOG-LEVEL}","categoryLevels":[{"category":"ROBOT-WORLD","logLevel":"Trace"},{"category":"imodeljs-rpc","logLevel":"Trace"},{"category":"imodeljs-backend.AutoPush","logLevel":"Trace"},{"category":"ECPresentation","logLevel":"None"},{"category":"Diagnostics.ECSqlStatement","logLevel":"None"},{"category":"ECObjectsNative","logLevel":"None"},{"category":"UnitsNative","logLevel":"None"},{"category":"BeSQLite","logLevel":"None"}]},"seq":{"hostURL":"${ROBOT-WORLD-SEQ-URL}","port":"${ROBOT-WORLD-SEQ-PORT}"},"features":{"imodel":{"readwrite":"${ROBOT-WORLD-FEATURE-READWRITE}"},"experimental":{"methods":"${ROBOT-WORLD-FEATURE-EXPERIMENTAL-METHODS}"}}} \ No newline at end of file +{ + "loggerConfig": { + "defaultLevel": "${ROBOT-WORLD-DEFAULT-LOG-LEVEL}", + "categoryLevels": [ + { "category": "ROBOT-WORLD", "logLevel": "Trace" }, + { "category": "imodeljs-rpc", "logLevel": "Trace" }, + { "category": "imodeljs-backend.AutoPush", "logLevel": "Trace" }, + { "category": "ECPresentation", "logLevel": "None" }, + { "category": "Diagnostics.ECSqlStatement", "logLevel": "None" }, + { "category": "ECObjectsNative", "logLevel": "None" }, + { "category": "UnitsNative", "logLevel": "None" }, + { "category": "BeSQLite", "logLevel": "None" } + ] + }, + "seq": { "hostURL": "${ROBOT-WORLD-SEQ-URL}", "port": "${ROBOT-WORLD-SEQ-PORT}" }, + "features": { + "imodel": { "readwrite": "${ROBOT-WORLD-FEATURE-READWRITE}" }, + "experimental": { "methods": "${ROBOT-WORLD-FEATURE-EXPERIMENTAL-METHODS}" } + } +} diff --git a/example-code/app/eslint.config.js b/example-code/app/eslint.config.js index e626e3b08ba4..849e7479dee5 100644 --- a/example-code/app/eslint.config.js +++ b/example-code/app/eslint.config.js @@ -6,5 +6,5 @@ module.exports = [ files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, - ...eslintBaseConfig -]; \ No newline at end of file + ...eslintBaseConfig, +]; diff --git a/example-code/app/src/backend/BarrierElement.ts b/example-code/app/src/backend/BarrierElement.ts index 7d2eed90d869..81e29adab89c 100644 --- a/example-code/app/src/backend/BarrierElement.ts +++ b/example-code/app/src/backend/BarrierElement.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { LineSegment3d, Point3d } from "@itwin/core-geometry"; import { IModelDb, SpatialCategory, SpatialLocationElement } from "@itwin/core-backend"; import { GeometryStreamBuilder, GeometryStreamProps } from "@itwin/core-common"; +import { LineSegment3d, Point3d } from "@itwin/core-geometry"; import { RobotWorld } from "./RobotWorldSchema"; /** @@ -15,17 +15,19 @@ import { RobotWorld } from "./RobotWorldSchema"; */ export class Barrier extends SpatialLocationElement { /** @internal */ - public static override get className(): string { return "Barrier"; } + public static override get className(): string { + return "Barrier"; + } // Define the properties added by this subclass - public length: number = 1.0; // The length of the barrier - public angle: number = 0.0; // The orientation angle of the barrier + public length: number = 1.0; // The length of the barrier + public angle: number = 0.0; // The orientation angle of the barrier // Note: Do not re-define the constructor. You must not interfere with the constructor that is // already defined by the base Element class. // You can provide handy methods for creating new Robots public static generateGeometry(length: number): GeometryStreamProps { - const builder = new GeometryStreamBuilder(); // I know what graphics represent a robot. + const builder = new GeometryStreamBuilder(); // I know what graphics represent a robot. const p1 = Point3d.createZero(); const p2 = Point3d.createFrom({ x: length, y: 0.0, z: 0.0 }); const circle = LineSegment3d.create(p1, p2); diff --git a/example-code/app/src/backend/GeometryStreamBuilder.ts b/example-code/app/src/backend/GeometryStreamBuilder.ts index 834f17ba447b..b47a58305e0c 100644 --- a/example-code/app/src/backend/GeometryStreamBuilder.ts +++ b/example-code/app/src/backend/GeometryStreamBuilder.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Arc3d, Point3d } from "@itwin/core-geometry"; import { GeometryStreamBuilder, GeometryStreamProps } from "@itwin/core-common"; +import { Arc3d, Point3d } from "@itwin/core-geometry"; // __PUBLISH_EXTRACT_START__ GeometryStreamBuilder.example-code // Simple example of using GeometryStreamBuilder. Note how the building works with diff --git a/example-code/app/src/backend/RobotElement.ts b/example-code/app/src/backend/RobotElement.ts index 4894b7bc08d4..9ef90475bf80 100644 --- a/example-code/app/src/backend/RobotElement.ts +++ b/example-code/app/src/backend/RobotElement.ts @@ -15,16 +15,18 @@ import { RobotWorld } from "./RobotWorldSchema"; * In this example, a "robot" is represented as a circle in the X-Y plane. */ export class Robot extends SpatialLocationElement { - public static override get className(): string { return "Robot"; } + public static override get className(): string { + return "Robot"; + } // Define the properties added by this subclass - public radius: number = 0.1; // The girth of the robot + public radius: number = 0.1; // The girth of the robot // Note: Do not redefine the constructor. You must not interfere with the constructor that is // already defined by the base Element class. // You can provide handy methods for creating new Robots public static generateGeometry(radius: number = 0.1): GeometryStreamProps { - const builder = new GeometryStreamBuilder(); // I know what graphics represent a robot. + const builder = new GeometryStreamBuilder(); // I know what graphics represent a robot. const circle = Arc3d.createXY(Point3d.createZero(), radius); builder.appendGeometry(circle); return builder.geometryStream; diff --git a/example-code/app/src/backend/RobotWorldEngine.ts b/example-code/app/src/backend/RobotWorldEngine.ts index 3d5e22aa1975..b7340c19eba2 100644 --- a/example-code/app/src/backend/RobotWorldEngine.ts +++ b/example-code/app/src/backend/RobotWorldEngine.ts @@ -2,13 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; +import { BriefcaseDb, ECSqlStatement, Element, IModelDb, IModelHost } from "@itwin/core-backend"; import { DbResult, Id64String } from "@itwin/core-bentley"; +import { Code, IModelReadRpcInterface, RpcInterfaceDefinition, RpcManager, TestRpcManager } from "@itwin/core-common"; import { Angle, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; -import { BriefcaseDb, ECSqlStatement, Element, IModelDb, IModelHost } from "@itwin/core-backend"; -import { - Code, IModelReadRpcInterface, RpcInterfaceDefinition, RpcManager, TestRpcManager, -} from "@itwin/core-common"; +import * as path from "path"; import { RobotWorldReadRpcInterface, RobotWorldWriteRpcInterface } from "../common/RobotWorldRpcInterface"; import { Barrier } from "./BarrierElement"; import { Robot } from "./RobotElement"; @@ -22,7 +20,6 @@ import { RobotWorld } from "./RobotWorldSchema"; // The service exposes APIs to manage robots and barriers and to query their state. // In particular, the service does collision detection between robots and obstacles. export class RobotWorldEngine { - private static _exposeWriteInterface = false; public static countRobotsInArray(iModelDb: IModelDb, elemIds: Id64String[]): number { @@ -92,19 +89,19 @@ export class RobotWorldEngine { const props = { model: modelId, code: Code.createEmpty(), - classFullName: RobotWorld.Class.Robot, // In this example, I know what class and category to use. + classFullName: RobotWorld.Class.Robot, // In this example, I know what class and category to use. category: Robot.getCategory(iModelDb).id, - geom: Robot.generateGeometry(radius), // In this example, I know how to generate geometry, and I know that the placement is empty. + geom: Robot.generateGeometry(radius), // In this example, I know how to generate geometry, and I know that the placement is empty. placement: { origin: location, angles: new YawPitchRollAngles() }, userLabel: name, - radius, // Add extra, Robot-specific properties. Be sure to spell them correctly, as the compiler won't help you here. + radius, // Add extra, Robot-specific properties. Be sure to spell them correctly, as the compiler won't help you here. }; return iModelDb.elements.insertElement(props); } // __PUBLISH_EXTRACT_END__ public static insertBarrier(iModelDb: IModelDb, modelId: Id64String, location: Point3d, angle: Angle, length: number): Id64String { - const props = { // I know what class and category to use. + const props = { // I know what class and category to use. model: modelId, code: Code.createEmpty(), classFullName: RobotWorld.Class.Barrier, diff --git a/example-code/app/src/backend/RobotWorldRpcImpl.ts b/example-code/app/src/backend/RobotWorldRpcImpl.ts index 68e0ffba3349..053fe98f33cb 100644 --- a/example-code/app/src/backend/RobotWorldRpcImpl.ts +++ b/example-code/app/src/backend/RobotWorldRpcImpl.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ // __PUBLISH_EXTRACT_START__ RpcInterface.implementation -import { IModelRpcProps, RpcInterface, RpcInterfaceDefinition } from "@itwin/core-common"; -import { Id64String } from "@itwin/core-bentley"; import { IModelDb } from "@itwin/core-backend"; -import { RobotWorldEngine } from "./RobotWorldEngine"; +import { Id64String } from "@itwin/core-bentley"; +import { IModelRpcProps, RpcInterface, RpcInterfaceDefinition } from "@itwin/core-common"; import { RobotWorldReadRpcInterface } from "../common/RobotWorldRpcInterface"; +import { RobotWorldEngine } from "./RobotWorldEngine"; // Implement RobotWorldReadRpcInterface export class RobotWorldReadRpcImpl extends RpcInterface implements RobotWorldReadRpcInterface { // eslint-disable-line deprecation/deprecation @@ -28,7 +28,8 @@ export class RobotWorldReadRpcImpl extends RpcInterface implements RobotWorldRea } // __PUBLISH_EXTRACT_END__ -/* eslint-disable no-duplicate-imports */ // Disable this because it is intentionally separated. +/* eslint-disable no-duplicate-imports */ +// Disable this because it is intentionally separated. import { Angle, AngleProps, Point3d, XYZProps } from "@itwin/core-geometry"; import { RobotWorldWriteRpcInterface } from "../common/RobotWorldRpcInterface"; @@ -42,7 +43,13 @@ export class RobotWorldWriteRpcImpl extends RpcInterface implements RobotWorldWr RobotWorldEngine.moveRobot(IModelDb.findByKey(tokenProps.key), id, Point3d.fromJSON(location)); } - public async insertBarrier(tokenProps: IModelRpcProps, modelId: Id64String, location: XYZProps, angle: AngleProps, length: number): Promise { + public async insertBarrier( + tokenProps: IModelRpcProps, + modelId: Id64String, + location: XYZProps, + angle: AngleProps, + length: number, + ): Promise { return RobotWorldEngine.insertBarrier(IModelDb.findByKey(tokenProps.key), modelId, Point3d.fromJSON(location), Angle.fromJSON(angle), length); } } diff --git a/example-code/app/src/backend/RobotWorldSchema.ts b/example-code/app/src/backend/RobotWorldSchema.ts index 90dd40ad7d8b..0a51495847bb 100644 --- a/example-code/app/src/backend/RobotWorldSchema.ts +++ b/example-code/app/src/backend/RobotWorldSchema.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import { ClassRegistry, IModelDb, IModelHost, Schema, Schemas, SpatialCategory } from "@itwin/core-backend"; import { ColorByName, IModelError, IModelStatus, SubCategoryAppearance } from "@itwin/core-common"; +import * as path from "path"; import * as _schemaNames from "../common/RobotWorldSchema"; import * as obstacles from "./BarrierElement"; @@ -23,10 +23,11 @@ import * as robots from "./RobotElement"; * definition. You would then edit the generated TypeScript class to add methods. */ export class RobotWorld extends Schema { - public static override get schemaName(): string { return "RobotWorld"; } + public static override get schemaName(): string { + return "RobotWorld"; + } /** An app must call this to register the RobotWorld schema prior to using it. */ public static registerSchema() { - // Make sure that this Schema is registered. // An app may call this more than once. Make sure that's harmless. if (this !== Schemas.getRegisteredSchema(RobotWorld.name)) { diff --git a/example-code/app/src/backend/assets/RobotWorldEngine.config.json b/example-code/app/src/backend/assets/RobotWorldEngine.config.json index 733c881cacc3..700de1933d23 100644 --- a/example-code/app/src/backend/assets/RobotWorldEngine.config.json +++ b/example-code/app/src/backend/assets/RobotWorldEngine.config.json @@ -58,4 +58,4 @@ "val": "${ROBOT-WORLD-FEATURE-EXPERIMENTAL-METHODS}" } ] -} \ No newline at end of file +} diff --git a/example-code/app/src/backend/test/KnownTestLocations.ts b/example-code/app/src/backend/test/KnownTestLocations.ts index e6e35a902654..c9d0c7e5d34f 100644 --- a/example-code/app/src/backend/test/KnownTestLocations.ts +++ b/example-code/app/src/backend/test/KnownTestLocations.ts @@ -2,12 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { join } from "path"; -import { tmpdir } from "os"; import { ProcessDetector } from "@itwin/core-bentley"; +import { tmpdir } from "os"; +import { join } from "path"; export class KnownTestLocations { - /** The directory where test assets are stored. Keep in mind that the test is playing the role of the app. */ public static get assetsDir(): string { return join(__dirname, "assets"); diff --git a/example-code/app/src/backend/test/RobotWorld.test.ts b/example-code/app/src/backend/test/RobotWorld.test.ts index af18c8f8eda8..b56f103bdc97 100644 --- a/example-code/app/src/backend/test/RobotWorld.test.ts +++ b/example-code/app/src/backend/test/RobotWorld.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { Id64String, OpenMode } from "@itwin/core-bentley"; -import { Angle, Point3d } from "@itwin/core-geometry"; import { IModelJsFs, PhysicalModel, StandaloneDb } from "@itwin/core-backend"; +import { Id64String, OpenMode } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; +import { Angle, Point3d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { Barrier } from "../BarrierElement"; import { Robot } from "../RobotElement"; import { RobotWorldEngine } from "../RobotWorldEngine"; diff --git a/example-code/app/src/backend/test/RobotWorldRpc.test.ts b/example-code/app/src/backend/test/RobotWorldRpc.test.ts index 1d921823bbfa..28fe96949846 100644 --- a/example-code/app/src/backend/test/RobotWorldRpc.test.ts +++ b/example-code/app/src/backend/test/RobotWorldRpc.test.ts @@ -2,16 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { Id64, Id64String, OpenMode, ProcessDetector } from "@itwin/core-bentley"; -import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; -import { Angle, Point3d } from "@itwin/core-geometry"; import { IModelJsFs, PhysicalModel, StandaloneDb } from "@itwin/core-backend"; +import { Id64, Id64String, OpenMode, ProcessDetector } from "@itwin/core-bentley"; import { - BentleyCloudRpcManager, BentleyCloudRpcParams, EmptyLocalization, GeometricElement3dProps, IModel, IModelReadRpcInterface, - RpcInterfaceDefinition, SnapshotIModelRpcInterface, TestRpcManager, + BentleyCloudRpcManager, + BentleyCloudRpcParams, + EmptyLocalization, + GeometricElement3dProps, + IModel, + IModelReadRpcInterface, + RpcInterfaceDefinition, + SnapshotIModelRpcInterface, + TestRpcManager, } from "@itwin/core-common"; +import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { BriefcaseConnection, NullRenderSystem } from "@itwin/core-frontend"; +import { Angle, Point3d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { RobotWorldReadRpcInterface, RobotWorldWriteRpcInterface } from "../../common/RobotWorldRpcInterface"; import { RobotWorldEngine } from "../RobotWorldEngine"; import { RobotWorld } from "../RobotWorldSchema"; @@ -41,12 +48,11 @@ async function setUpTest() { if (ProcessDetector.isElectronAppFrontend) { describe("RobotWorldRpc", () => { - it("should run robotWorld through Ipc as a client", async () => { // Simulate the deployment of the backend server await simulateBackendDeployment(); - await setUpTest(); // tricky: do this after simulateBackendDeployment, as that function has the side effect of initializing IModelHost + await setUpTest(); // tricky: do this after simulateBackendDeployment, as that function has the side effect of initializing IModelHost await ElectronApp.startup({ iModelApp: { @@ -56,7 +62,7 @@ if (ProcessDetector.isElectronAppFrontend) { }); // expose interfaces using a direct call mechanism - TestRpcManager.initialize([SnapshotIModelRpcInterface, IModelReadRpcInterface, RobotWorldReadRpcInterface, RobotWorldWriteRpcInterface]);// eslint-disable-line deprecation/deprecation + TestRpcManager.initialize([SnapshotIModelRpcInterface, IModelReadRpcInterface, RobotWorldReadRpcInterface, RobotWorldWriteRpcInterface]); // eslint-disable-line deprecation/deprecation const roWrite = RobotWorldWriteRpcInterface.getClient(); const roRead = RobotWorldReadRpcInterface.getClient(); diff --git a/example-code/app/src/backend/test/Utils.ts b/example-code/app/src/backend/test/Utils.ts index f3191d04e874..e683016c39ce 100644 --- a/example-code/app/src/backend/test/Utils.ts +++ b/example-code/app/src/backend/test/Utils.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { IModelJsFs } from "@itwin/core-backend"; import { assert } from "chai"; import * as path from "path"; -import { IModelJsFs } from "@itwin/core-backend"; export class KnownTestLocations { /** The directory where test assets are stored. Keep in mind that the test is playing the role of the app. */ diff --git a/example-code/app/src/common/RobotWorldRpcInterface.ts b/example-code/app/src/common/RobotWorldRpcInterface.ts index 3e84cf7ecf57..ee0f1e665e71 100644 --- a/example-code/app/src/common/RobotWorldRpcInterface.ts +++ b/example-code/app/src/common/RobotWorldRpcInterface.ts @@ -3,17 +3,25 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ // __PUBLISH_EXTRACT_START__ RpcInterface.definition -import { IModelRpcProps, RpcInterface, RpcManager } from "@itwin/core-common"; import { Id64String } from "@itwin/core-bentley"; +import { IModelRpcProps, RpcInterface, RpcManager } from "@itwin/core-common"; // The RPC query interface that may be exposed by the RobotWorldEngine. export abstract class RobotWorldReadRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation public static readonly interfaceName = "RobotWorldReadRpcInterface"; // The immutable name of the interface - public static interfaceVersion = "1.0.0"; // The API version of the interface - public static getClient() { return RpcManager.getClientForInterface(this); } - public async countRobotsInArray(_iModelToken: IModelRpcProps, _elemIds: Id64String[]): Promise { return this.forward(arguments); } - public async countRobots(_iModelToken: IModelRpcProps): Promise { return this.forward(arguments); } - public async queryObstaclesHitByRobot(_iModelToken: IModelRpcProps, _rid: Id64String): Promise { return this.forward(arguments); } + public static interfaceVersion = "1.0.0"; // The API version of the interface + public static getClient() { + return RpcManager.getClientForInterface(this); + } + public async countRobotsInArray(_iModelToken: IModelRpcProps, _elemIds: Id64String[]): Promise { + return this.forward(arguments); + } + public async countRobots(_iModelToken: IModelRpcProps): Promise { + return this.forward(arguments); + } + public async queryObstaclesHitByRobot(_iModelToken: IModelRpcProps, _rid: Id64String): Promise { + return this.forward(arguments); + } } // __PUBLISH_EXTRACT_END__ @@ -23,8 +31,22 @@ import { AngleProps, XYZProps } from "@itwin/core-geometry"; export abstract class RobotWorldWriteRpcInterface extends RpcInterface { // eslint-disable-line deprecation/deprecation public static readonly interfaceName = "RobotWorldWriteRpcInterface"; // The immutable name of the interface public static interfaceVersion = "1.0.0"; // The API version of the interface - public static getClient() { return RpcManager.getClientForInterface(this); } - public async insertRobot(_iModelToken: IModelRpcProps, _modelId: Id64String, _name: string, _location: XYZProps): Promise { return this.forward(arguments); } - public async moveRobot(_iModelToken: IModelRpcProps, _id: Id64String, _location: XYZProps): Promise { return this.forward(arguments); } - public async insertBarrier(_iModelToken: IModelRpcProps, _modelId: Id64String, _location: XYZProps, _angle: AngleProps, _length: number): Promise { return this.forward(arguments); } + public static getClient() { + return RpcManager.getClientForInterface(this); + } + public async insertRobot(_iModelToken: IModelRpcProps, _modelId: Id64String, _name: string, _location: XYZProps): Promise { + return this.forward(arguments); + } + public async moveRobot(_iModelToken: IModelRpcProps, _id: Id64String, _location: XYZProps): Promise { + return this.forward(arguments); + } + public async insertBarrier( + _iModelToken: IModelRpcProps, + _modelId: Id64String, + _location: XYZProps, + _angle: AngleProps, + _length: number, + ): Promise { + return this.forward(arguments); + } } diff --git a/example-code/app/src/frontend/BlankConnection.ts b/example-code/app/src/frontend/BlankConnection.ts index 736410cfd18b..4e1a8330ac3b 100644 --- a/example-code/app/src/frontend/BlankConnection.ts +++ b/example-code/app/src/frontend/BlankConnection.ts @@ -2,12 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Range3d } from "@itwin/core-geometry"; import { Cartographic, ColorDef } from "@itwin/core-common"; import { BlankConnection, IModelConnection, SpatialViewState } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; export class BlankConnectionExample { - // __PUBLISH_EXTRACT_START__ BlankConnection.open // create a new blank connection centered on Exton PA @@ -16,7 +15,7 @@ export class BlankConnectionExample { // call this connection "Exton PA" name: "Exton PA", // put the center of the connection near Exton, Pennsylvania (Bentley's HQ) - location: Cartographic.fromDegrees({longitude: -75.686694, latitude: 40.065757, height: 0}), + location: Cartographic.fromDegrees({ longitude: -75.686694, latitude: 40.065757, height: 0 }), // create the area-of-interest to be 2000 x 2000 x 200 meters, centered around 0,0.0 extents: new Range3d(-1000, -1000, -100, 1000, 1000, 100), }); diff --git a/example-code/app/src/frontend/RobotWorldUI.ts b/example-code/app/src/frontend/RobotWorldUI.ts index c5389a8396b1..7a34ebd6dc4e 100644 --- a/example-code/app/src/frontend/RobotWorldUI.ts +++ b/example-code/app/src/frontend/RobotWorldUI.ts @@ -6,7 +6,6 @@ import { Id64String } from "@itwin/core-bentley"; import { DrawingViewState, IModelApp, IModelConnection, ScreenViewport, SpatialViewState, ViewState } from "@itwin/core-frontend"; export class RobotWorldApp { - private static _iModel: IModelConnection; // __PUBLISH_EXTRACT_START__ IModelConnection.Views.getSpatialViewList @@ -75,5 +74,4 @@ export class RobotWorldApp { IModelApp.viewManager.addViewport(viewPort); } // __PUBLISH_EXTRACT_END__ - } diff --git a/example-code/snippets/eslint.config.js b/example-code/snippets/eslint.config.js index e626e3b08ba4..849e7479dee5 100644 --- a/example-code/snippets/eslint.config.js +++ b/example-code/snippets/eslint.config.js @@ -6,5 +6,5 @@ module.exports = [ files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, - ...eslintBaseConfig -]; \ No newline at end of file + ...eslintBaseConfig, +]; diff --git a/example-code/snippets/src/backend/AzuriteTest.ts b/example-code/snippets/src/backend/AzuriteTest.ts index 2b677bc6bfbf..0d1857d9768c 100644 --- a/example-code/snippets/src/backend/AzuriteTest.ts +++ b/example-code/snippets/src/backend/AzuriteTest.ts @@ -3,25 +3,26 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { emptyDirSync, mkdirsSync } from "fs-extra"; -import { join } from "path"; import * as azureBlob from "@azure/storage-blob"; import { BlobContainer, CloudSqlite, IModelHost, SettingsContainer } from "@itwin/core-backend"; import { AccessToken, Guid } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; +import { expect } from "chai"; +import { emptyDirSync, mkdirsSync } from "fs-extra"; +import { join } from "path"; // spell:ignore imodelid itwinid mkdirs devstoreaccount racwdl export namespace AzuriteTest { - export const storageType = "azure" as const; export const httpAddr = "127.0.0.1:10001"; export const accountName = "devstoreaccount1"; export const baseUri = `http://${httpAddr}/${accountName}`; export const getContainerUri = (id: string) => `${baseUri}/${id}`; - const pipeline = azureBlob.newPipeline(new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")); + const pipeline = azureBlob.newPipeline( + new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="), + ); export const createAzClient = (id: string) => new azureBlob.ContainerClient(getContainerUri(id), pipeline); export let userToken: AccessToken; @@ -74,7 +75,12 @@ export namespace AzuriteTest { emptyDirSync(name); }; - export interface TestContainerProps { containerId: string, logId?: string, isPublic?: boolean, writeable?: boolean } + export interface TestContainerProps { + containerId: string; + logId?: string; + isPublic?: boolean; + writeable?: boolean; + } export const makeContainer = async (arg: TestContainerProps): Promise => { const containerProps = { ...arg, writeable: true, baseUri, storageType }; @@ -95,7 +101,6 @@ export namespace AzuriteTest { const cacheDir = join(IModelHost.cacheDir, cacheName); makeEmptyDir(cacheDir); return CloudSqlite.CloudCaches.getCache({ cacheName, cacheDir }); - }; export const makeCaches = (names: string[]) => { const caches = []; @@ -104,7 +109,12 @@ export namespace AzuriteTest { return caches; }; - export const uploadFile = async (container: CloudSqlite.CloudContainer, cache: CloudSqlite.CloudCache, dbName: string, localFileName: LocalFileName) => { + export const uploadFile = async ( + container: CloudSqlite.CloudContainer, + cache: CloudSqlite.CloudCache, + dbName: string, + localFileName: LocalFileName, + ) => { expect(container.isConnected).false; container.connect(cache); expect(container.isConnected); diff --git a/example-code/snippets/src/backend/DumpIModel.test.ts b/example-code/snippets/src/backend/DumpIModel.test.ts index 4393265363a9..63221c3873ca 100644 --- a/example-code/snippets/src/backend/DumpIModel.test.ts +++ b/example-code/snippets/src/backend/DumpIModel.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECSqlStatement, Element, IModelDb, Model, SnapshotDb } from "@itwin/core-backend"; +import { DbResult, Id64String } from "@itwin/core-bentley"; import { assert } from "chai"; import * as fs from "fs-extra"; import * as path from "path"; -import { DbResult, Id64String } from "@itwin/core-bentley"; -import { ECSqlStatement, Element, IModelDb, Model, SnapshotDb } from "@itwin/core-backend"; import { IModelTestUtils } from "./IModelTestUtils"; // __PUBLISH_EXTRACT_START__ WireFormat_DumpIModel.code diff --git a/example-code/snippets/src/backend/ECSQL-queries.test.ts b/example-code/snippets/src/backend/ECSQL-queries.test.ts index ab8ae49f2083..ecc07501db14 100644 --- a/example-code/snippets/src/backend/ECSQL-queries.test.ts +++ b/example-code/snippets/src/backend/ECSQL-queries.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { DbResult, Id64Set, Id64String } from "@itwin/core-bentley"; import { ECSqlStatement, Element, IModelDb, PhysicalPartition, SnapshotDb, Subject } from "@itwin/core-backend"; +import { DbResult, Id64Set, Id64String } from "@itwin/core-bentley"; +import { assert } from "chai"; import { IModelTestUtils } from "./IModelTestUtils"; /** Useful ECSQL queries organized as tests to make sure that they build and run successfully. */ @@ -30,7 +30,8 @@ describe("Useful ECSQL queries", () => { // You could write the following query to find it. This query specifies that the // element you want is a PhysicalPartition, it has a code value of "Physical", // and it is a child of a Subject named "Subject1". - const partitionIds: Id64Set = iModel.withPreparedStatement(` + const partitionIds: Id64Set = iModel.withPreparedStatement( + ` select [partition].ecinstanceid from @@ -38,14 +39,16 @@ describe("Useful ECSQL queries", () => { (select ecinstanceid from ${Subject.classFullName} where CodeValue=:parentName) as parent where [partition].codevalue=:partitionName and [partition].parent.id = parent.ecinstanceid; - `, (stmt: ECSqlStatement) => { - stmt.bindValue("parentName", "Subject1"); - stmt.bindValue("partitionName", "Physical"); - const ids: Id64Set = new Set(); - while (stmt.step() === DbResult.BE_SQLITE_ROW) - ids.add(stmt.getValue(0).getId()); - return ids; - }); + `, + (stmt: ECSqlStatement) => { + stmt.bindValue("parentName", "Subject1"); + stmt.bindValue("partitionName", "Physical"); + const ids: Id64Set = new Set(); + while (stmt.step() === DbResult.BE_SQLITE_ROW) + ids.add(stmt.getValue(0).getId()); + return ids; + }, + ); assert.isNotEmpty(partitionIds); assert.equal(partitionIds.size, 1); @@ -81,12 +84,15 @@ describe("Useful ECSQL queries", () => { it("should select all top-level elements in a model", () => { // __PUBLISH_EXTRACT_START__ ECSQL-backend-queries.select-top-level-elements-in-model const modelId: Id64String = IModelDb.repositoryModelId; - iModel.withPreparedStatement(`SELECT ECInstanceId AS id FROM ${Element.classFullName} WHERE Model.Id=:modelId AND Parent.Id IS NULL`, (statement: ECSqlStatement) => { - statement.bindId("modelId", modelId); - while (DbResult.BE_SQLITE_ROW === statement.step()) { - // do something with each row - } - }); + iModel.withPreparedStatement( + `SELECT ECInstanceId AS id FROM ${Element.classFullName} WHERE Model.Id=:modelId AND Parent.Id IS NULL`, + (statement: ECSqlStatement) => { + statement.bindId("modelId", modelId); + while (DbResult.BE_SQLITE_ROW === statement.step()) { + // do something with each row + } + }, + ); // __PUBLISH_EXTRACT_END__ }); @@ -101,5 +107,4 @@ describe("Useful ECSQL queries", () => { }); // __PUBLISH_EXTRACT_END__ }); - }); diff --git a/example-code/snippets/src/backend/ECSQL-spatial-queries.test.ts b/example-code/snippets/src/backend/ECSQL-spatial-queries.test.ts index 4b7b62ffb06e..9b44ffd935ce 100644 --- a/example-code/snippets/src/backend/ECSQL-spatial-queries.test.ts +++ b/example-code/snippets/src/backend/ECSQL-spatial-queries.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { ECSqlStatement, Element, GeometricElement3d, PhysicalPartition, SnapshotDb } from "@itwin/core-backend"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; import { Range3d, Range3dProps } from "@itwin/core-geometry"; -import { ECSqlStatement, Element, GeometricElement3d, PhysicalPartition, SnapshotDb } from "@itwin/core-backend"; +import { assert } from "chai"; import { IModelTestUtils } from "./IModelTestUtils"; /** Example code organized as tests to make sure that it builds and runs successfully. */ @@ -32,25 +32,29 @@ describe("Useful ECSQL spatial queries", () => { // __PUBLISH_EXTRACT_START__ EcsqlGeometryFunctions.iModel_bbox_areaxy // Compute the largest element area in the X-Y plane. let maxArea: number = 0; - iModel.withPreparedStatement(`SELECT iModel_bbox_areaxy(iModel_bbox(BBoxLow.X,BBoxLow.Y,BBoxLow.Z,BBoxHigh.X,BBoxHigh.Y,BBoxHigh.Z)) FROM ${GeometricElement3d.classFullName}`, + iModel.withPreparedStatement( + `SELECT iModel_bbox_areaxy(iModel_bbox(BBoxLow.X,BBoxLow.Y,BBoxLow.Z,BBoxHigh.X,BBoxHigh.Y,BBoxHigh.Z)) FROM ${GeometricElement3d.classFullName}`, (stmt: ECSqlStatement) => { while (stmt.step() === DbResult.BE_SQLITE_ROW) { const thisArea: number = stmt.getValue(0).getDouble(); if (thisArea > maxArea) maxArea = thisArea; } - }); + }, + ); // Report the result reportArea(maxArea); // Use the standard SUM operator to accumulate the results of the iModel_bbox_areaxy function. This shows that // ECSQL treats the built-in geometry functions as normal expressions. - const areaSum: number = iModel.withPreparedStatement(`SELECT SUM(iModel_bbox_areaxy(iModel_bbox(BBoxLow.X,BBoxLow.Y,BBoxLow.Z,BBoxHigh.X,BBoxHigh.Y,BBoxHigh.Z))) FROM ${GeometricElement3d.classFullName}`, + const areaSum: number = iModel.withPreparedStatement( + `SELECT SUM(iModel_bbox_areaxy(iModel_bbox(BBoxLow.X,BBoxLow.Y,BBoxLow.Z,BBoxHigh.X,BBoxHigh.Y,BBoxHigh.Z))) FROM ${GeometricElement3d.classFullName}`, (stmt: ECSqlStatement) => { if (stmt.step() !== DbResult.BE_SQLITE_ROW) return 0; // ? return stmt.getValue(0).getDouble(); - }); + }, + ); // Report the result reportArea(areaSum); @@ -73,29 +77,29 @@ describe("Useful ECSQL spatial queries", () => { WHERE e.model.id=? AND e.ecinstanceid=g.ecinstanceid `; - const rangeSum: Range3dProps = iModel.withPreparedStatement(bboxUnionStmtECSQL, - (stmt: ECSqlStatement) => { - stmt.bindId(1, modelId!); - if (stmt.step() !== DbResult.BE_SQLITE_ROW) - return {} as Range3dProps; - // Note that the the ECSQL value is a blob. Its data must be extracted and interpreted as a Range3d. - return Range3d.fromArrayBuffer(stmt.getValue(0).getBlob().buffer as ArrayBuffer); - }); + const rangeSum: Range3dProps = iModel.withPreparedStatement(bboxUnionStmtECSQL, (stmt: ECSqlStatement) => { + stmt.bindId(1, modelId!); + if (stmt.step() !== DbResult.BE_SQLITE_ROW) + return {} as Range3dProps; + // Note that the the ECSQL value is a blob. Its data must be extracted and interpreted as a Range3d. + return Range3d.fromArrayBuffer(stmt.getValue(0).getBlob().buffer as ArrayBuffer); + }); reportRange(rangeSum); // __PUBLISH_EXTRACT_END__ // This is an example of passing the WRONG TYPE of object to iModel_bbox_areaxy and getting an error. // This statement is wrong, because iModel_placement_angles returns a iModel_angles object, while iModel_bbox_areaxy expects a DGN_bbox object. // Note that the error is detected when you try to step the statement, not when you prepare it. - iModel.withPreparedStatement(`SELECT iModel_bbox_areaxy(iModel_angles(Yaw,Pitch,Roll)) FROM ${GeometricElement3d.classFullName}`, + iModel.withPreparedStatement( + `SELECT iModel_bbox_areaxy(iModel_angles(Yaw,Pitch,Roll)) FROM ${GeometricElement3d.classFullName}`, (stmt: ECSqlStatement) => { // TODO: I expect an exception here: while (stmt.step() === DbResult.BE_SQLITE_ROW) { // ... } - }); + }, + ); }); - }); function reportArea(a: number) { diff --git a/example-code/snippets/src/backend/ExampleCode.test.ts b/example-code/snippets/src/backend/ExampleCode.test.ts index d710689dac2f..0db4834aba33 100644 --- a/example-code/snippets/src/backend/ExampleCode.test.ts +++ b/example-code/snippets/src/backend/ExampleCode.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { AccessToken, Guid, Id64, Id64String } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { BisCoreSchema, BriefcaseDb, ClassRegistry, CodeService, Element, PhysicalModel, StandaloneDb, Subject } from "@itwin/core-backend"; +import { AccessToken, Guid, Id64, Id64String } from "@itwin/core-bentley"; import { Code, CodeScopeSpec, CodeSpec, CodeSpecProperties, IModel } from "@itwin/core-common"; +import { Range3d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { IModelTestUtils } from "./IModelTestUtils"; /** Example code organized as tests to make sure that it builds and runs successfully. */ @@ -93,13 +93,10 @@ describe("Example Code", () => { assert.deepEqual(codeSpec2Id, codeSpec2.id); assert.notDeepEqual(codeSpec2Id, codeSpecId); // __PUBLISH_EXTRACT_END__ - }); it("CodeService", async () => { - if (false) { // this will compile but it will not run, because the root element has no federationGuid -- waiting for a fix - // __PUBLISH_EXTRACT_START__ CodeService.reserveInternalCodeForNewElement const code = Subject.createCode(iModel, IModel.rootSubjectId, "main transfer pump"); // an example a code that an app might use @@ -153,15 +150,16 @@ describe("Example Code", () => { // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ CodeService.findCode - const existingCodeGuid = iModel.codeService?.internalCodes?.reader.findCode({ value: code.value, ...CodeService.makeScopeAndSpec(iModel, code) }); + const existingCodeGuid = iModel.codeService?.internalCodes?.reader.findCode({ + value: code.value, + ...CodeService.makeScopeAndSpec(iModel, code), + }); if (existingCodeGuid !== undefined) { /* the code has already been reserved and may be in use */ } // __PUBLISH_EXTRACT_END__ } - }); - }); namespace Snippets { diff --git a/example-code/snippets/src/backend/ExampleOpenIModel.ts b/example-code/snippets/src/backend/ExampleOpenIModel.ts index a3d01521b123..19dbe2dbcc46 100644 --- a/example-code/snippets/src/backend/ExampleOpenIModel.ts +++ b/example-code/snippets/src/backend/ExampleOpenIModel.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { AccessToken, OpenMode } from "@itwin/core-bentley"; import { BriefcaseDb } from "@itwin/core-backend"; +import { AccessToken, OpenMode } from "@itwin/core-bentley"; import { IModelError, IModelStatus, OpenBriefcaseProps } from "@itwin/core-common"; import { TestUserCredentials, TestUtility } from "@itwin/oidc-signin-tool"; diff --git a/example-code/snippets/src/backend/ExecutingECSQL.ts b/example-code/snippets/src/backend/ExecutingECSQL.ts index 8f076f64f90f..f13b6661bad8 100644 --- a/example-code/snippets/src/backend/ExecutingECSQL.ts +++ b/example-code/snippets/src/backend/ExecutingECSQL.ts @@ -2,55 +2,65 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { DbResult, Id64String } from "@itwin/core-bentley"; import { ECSqlStatement, ECSqlValue, IModelDb, SnapshotDb } from "@itwin/core-backend"; +import { DbResult, Id64String } from "@itwin/core-bentley"; import { NavigationValue } from "@itwin/core-common"; /* eslint-disable no-console, @typescript-eslint/naming-convention */ function executeECSql_Binding(iModel: IModelDb) { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_ByParameter_Positional - iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", (stmt: ECSqlStatement) => { - stmt.bindString(1, "MyCode"); - stmt.bindDateTime(2, "2018-01-01T12:00:00"); + iModel.withPreparedStatement( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", + (stmt: ECSqlStatement) => { + stmt.bindString(1, "MyCode"); + stmt.bindDateTime(2, "2018-01-01T12:00:00"); - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - // do something with the query result - } - }); + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + // do something with the query result + } + }, + ); // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_ByParameter_Named - iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", (stmt: ECSqlStatement) => { - stmt.bindString("code", "MyCode"); - stmt.bindDateTime("lastmod", "2018-01-01T12:00:00Z"); + iModel.withPreparedStatement( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", + (stmt: ECSqlStatement) => { + stmt.bindString("code", "MyCode"); + stmt.bindDateTime("lastmod", "2018-01-01T12:00:00Z"); - while (stmt.step() === DbResult.BE_SQLITE_ROW) { - // do something with the query result - } - }); + while (stmt.step() === DbResult.BE_SQLITE_ROW) { + // do something with the query result + } + }, + ); // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ ExecuteECSql_BindValues_Positional - iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", + iModel.withPreparedStatement( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", (stmt: ECSqlStatement) => { stmt.bindValues(["MyCode", "2018-01-01T12:00:00Z"]); while (stmt.step() === DbResult.BE_SQLITE_ROW) { // do something with the query result } - }); + }, + ); // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ ExecuteECSql_BindValues_Named - iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", + iModel.withPreparedStatement( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", (stmt: ECSqlStatement) => { stmt.bindValues({ code: "MyCode", lastmod: "2018-01-01T12:00:00Z" }); while (stmt.step() === DbResult.BE_SQLITE_ROW) { // do something with the query result } - }); + }, + ); // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Navigation_ByParameter @@ -128,7 +138,6 @@ function executeECSql_Binding(iModel: IModelDb) { function executeECSql_QueryResult(iModel: IModelDb) { // __PUBLISH_EXTRACT_START__ ExecuteECSql_GetRow_IllustrateRowFormat iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE Model.Id=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, "0x113"); while (stmt.step() === DbResult.BE_SQLITE_ROW) { @@ -140,7 +149,6 @@ function executeECSql_QueryResult(iModel: IModelDb) { // __PUBLISH_EXTRACT_START__ ExecuteECSql_GetRow iModel.withPreparedStatement("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE Model.Id=?", (stmt: ECSqlStatement) => { - stmt.bindId(1, "0x113"); console.log("ECInstanceId | ClassName | Parent Id | Parent RelClassName | LastMod"); diff --git a/example-code/snippets/src/backend/IModelBranchingOperations.test.ts b/example-code/snippets/src/backend/IModelBranchingOperations.test.ts index 99f4c2567627..fa23075224de 100644 --- a/example-code/snippets/src/backend/IModelBranchingOperations.test.ts +++ b/example-code/snippets/src/backend/IModelBranchingOperations.test.ts @@ -3,16 +3,27 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import * as path from "path"; import { - BriefcaseDb, BriefcaseManager, ExternalSource, ExternalSourceIsInRepository, HubMock, IModelDb, IModelHost, PhysicalModel, PhysicalObject, - PhysicalPartition, RepositoryLink, SnapshotDb, SpatialCategory, + BriefcaseDb, + BriefcaseManager, + ExternalSource, + ExternalSourceIsInRepository, + HubMock, + IModelDb, + IModelHost, + PhysicalModel, + PhysicalObject, + PhysicalPartition, + RepositoryLink, + SnapshotDb, + SpatialCategory, } from "@itwin/core-backend"; -import { IModelTestUtils as BackendTestUtils, HubWrappers, TestUserType } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; +import { HubWrappers, IModelTestUtils as BackendTestUtils, TestUserType } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; import { AccessToken } from "@itwin/core-bentley"; import { Code, ExternalSourceProps, IModel, PhysicalElementProps, RepositoryLinkProps, SubCategoryAppearance } from "@itwin/core-common"; import { Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import * as fs from "fs"; +import * as path from "path"; process.env.TRANSFORMER_NO_STRICT_DEP_CHECK = "1"; // allow this monorepo's dev versions of core libs in transformer import { IModelTransformer, ProcessChangesOptions } from "@itwin/imodel-transformer"; import { KnownTestLocations } from "./IModelTestUtils"; diff --git a/example-code/snippets/src/backend/IModelExporter.test.ts b/example-code/snippets/src/backend/IModelExporter.test.ts index 0c0ee51fd36b..eacadde33f6a 100644 --- a/example-code/snippets/src/backend/IModelExporter.test.ts +++ b/example-code/snippets/src/backend/IModelExporter.test.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ // __PUBLISH_EXTRACT_START__ IModelExporter_CodeExporter.code +import { Element, IModelDb, IModelJsFs as fs, SnapshotDb } from "@itwin/core-backend"; import { Code, CodeSpec } from "@itwin/core-common"; -import { Element, IModelJsFs as fs, IModelDb, SnapshotDb } from "@itwin/core-backend"; process.env.TRANSFORMER_NO_STRICT_DEP_CHECK = "1"; // allow this monorepo's dev versions of core libs in transformer import { IModelExporter, IModelExportHandler } from "@itwin/imodel-transformer"; diff --git a/example-code/snippets/src/backend/IModelTestUtils.ts b/example-code/snippets/src/backend/IModelTestUtils.ts index 9175db507b0f..ed1f8f7533ca 100644 --- a/example-code/snippets/src/backend/IModelTestUtils.ts +++ b/example-code/snippets/src/backend/IModelTestUtils.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import { OpenMode } from "@itwin/core-bentley"; -import { ITwinsAccessClient } from "@itwin/itwins-client"; import { IModelHost, IModelJsFs, IModelJsFsStats, KnownLocations, SnapshotDb, StandaloneDb } from "@itwin/core-backend"; +import { OpenMode } from "@itwin/core-bentley"; import { IModelReadRpcInterface, RpcManager } from "@itwin/core-common"; +import { ITwinsAccessClient } from "@itwin/itwins-client"; +import { assert } from "chai"; +import * as path from "path"; RpcManager.initializeInterface(IModelReadRpcInterface); @@ -16,7 +16,6 @@ export interface IModelTestUtilsOpenOptions { } export class KnownTestLocations { - /** The directory where test assets are stored. Keep in mind that the test is playing the role of the app. */ public static get assetsDir(): string { // Assume that we are running in nodejs @@ -28,7 +27,6 @@ export class KnownTestLocations { // Assume that we are running in nodejs return path.join(__dirname, "output"); } - } export class IModelTestUtils { @@ -55,7 +53,7 @@ export class IModelTestUtils { IModelJsFs.mkdirSync(destPath); const srcName = path.join(KnownTestLocations.assetsDir, filename); - const dbName = path.join(destPath, (opts.copyFilename ? opts.copyFilename : filename)); + const dbName = path.join(destPath, opts.copyFilename ? opts.copyFilename : filename); const srcStat = IModelTestUtils.getStat(srcName); const destStat = IModelTestUtils.getStat(dbName); if (!srcStat || !destStat || srcStat.mtimeMs !== destStat.mtimeMs) diff --git a/example-code/snippets/src/backend/LoadAndEditiModelSchemas.test.ts b/example-code/snippets/src/backend/LoadAndEditiModelSchemas.test.ts index 77c6d10244d5..bcf430d17753 100644 --- a/example-code/snippets/src/backend/LoadAndEditiModelSchemas.test.ts +++ b/example-code/snippets/src/backend/LoadAndEditiModelSchemas.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { IModelTestUtils } from "./IModelTestUtils"; -import { ECClassModifier, PrimitiveType, SchemaLoader } from "@itwin/ecschema-metadata"; -import { SchemaXml } from "@itwin/ecschema-locaters"; -import { SchemaContextEditor } from "@itwin/ecschema-editing"; import { StandaloneDb } from "@itwin/core-backend"; import { Guid } from "@itwin/core-bentley"; +import { SchemaContextEditor } from "@itwin/ecschema-editing"; +import { SchemaXml } from "@itwin/ecschema-locaters"; +import { ECClassModifier, PrimitiveType, SchemaLoader } from "@itwin/ecschema-metadata"; +import { IModelTestUtils } from "./IModelTestUtils"; describe("SchemaLoadAndEdit", () => { let iModelDb: StandaloneDb; @@ -36,12 +36,17 @@ describe("SchemaLoadAndEdit", () => { // __PUBLISH_EXTRACT_END__ // __PUBLISH_EXTRACT_START__ IModelSchemas.editSchemas - const schemaKey = await editor.createSchema("PipingSchema", "PS", 1,0,42); + const schemaKey = await editor.createSchema("PipingSchema", "PS", 1, 0, 42); const bisSchema = loader.getSchema("BisCore"); await editor.addSchemaReference(schemaKey, bisSchema); - const elementKey = await editor.entities.createElement(schemaKey, "Pipe", ECClassModifier.None, bisSchema.getSchemaItemKey("BisCore.PhysicalElement")); + const elementKey = await editor.entities.createElement( + schemaKey, + "Pipe", + ECClassModifier.None, + bisSchema.getSchemaItemKey("BisCore.PhysicalElement"), + ); await editor.entities.createProperty(elementKey, "Diameter", PrimitiveType.Double, "cgk"); @@ -55,6 +60,5 @@ describe("SchemaLoadAndEdit", () => { const schemaXml = await SchemaXml.writeString(pipingSchema); await iModelDb.importSchemaStrings([schemaXml]); // __PUBLISH_EXTRACT_END__ - }); }); diff --git a/example-code/snippets/src/backend/SchemaXmlFileLocater.test.ts b/example-code/snippets/src/backend/SchemaXmlFileLocater.test.ts index 0f66bb13e26b..8b16d8edf1a5 100644 --- a/example-code/snippets/src/backend/SchemaXmlFileLocater.test.ts +++ b/example-code/snippets/src/backend/SchemaXmlFileLocater.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { SchemaContext, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; -import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; import { KnownLocations } from "@itwin/core-backend"; -import path from "path"; +import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; +import { SchemaContext, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; import { assert } from "chai"; import * as fs from "fs-extra"; +import path from "path"; describe("SchemaXmlFileLocater - locate standard schema", () => { it("Schema path is less than 260 character long", async () => { @@ -36,9 +36,9 @@ describe("SchemaXmlFileLocater - locate standard schema", () => { longSchemaPath = path.join(longSchemaPath, "ThisIsA35CharacterLongSubFolderName"); } if (!fs.existsSync(longSchemaPath)) { - fs.mkdirSync(longSchemaPath, {recursive: true}); + fs.mkdirSync(longSchemaPath, { recursive: true }); } - fs.copySync(oldSchemaPath, longSchemaPath, {recursive: true}); + fs.copySync(oldSchemaPath, longSchemaPath, { recursive: true }); assert.isTrue(longSchemaPath.length > 260); assert.isTrue(longSchemaPath.length < 1024); loc.addSchemaSearchPath(longSchemaPath); @@ -49,7 +49,7 @@ describe("SchemaXmlFileLocater - locate standard schema", () => { assert.isDefined(schema); assert.strictEqual(schema?.name, "Units"); if (fs.existsSync(path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "StandardCopy"))) { - fs.rmSync(path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "StandardCopy"), {recursive: true}); + fs.rmSync(path.join(KnownLocations.nativeAssetsDir, "ECSchemas", "StandardCopy"), { recursive: true }); } }); }); diff --git a/example-code/snippets/src/backend/SerializingXmlSchemas.ts b/example-code/snippets/src/backend/SerializingXmlSchemas.ts index 91b25540a02b..167515fb543d 100644 --- a/example-code/snippets/src/backend/SerializingXmlSchemas.ts +++ b/example-code/snippets/src/backend/SerializingXmlSchemas.ts @@ -3,14 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ // __PUBLISH_EXTRACT_START__ Serialize_Schema_To_XML_Imports -import * as fs from "fs-extra"; // file system api -import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; // XML support -import { SchemaContext } from "@itwin/ecschema-metadata"; import { SchemaContextEditor } from "@itwin/ecschema-editing"; // For creating a small sample Schema for this tutorial +import { SchemaContext } from "@itwin/ecschema-metadata"; +import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; // XML support +import * as fs from "fs-extra"; // file system api // __PUBLISH_EXTRACT_END__ export class SchemaXmlSerializer { - public async serializeSchemaToXmlSample() { // __PUBLISH_EXTRACT_START__ Serialize_Schema_To_XML_Create const context = new SchemaContext(); diff --git a/example-code/snippets/src/backend/WireFormat.test.ts b/example-code/snippets/src/backend/WireFormat.test.ts index 31f9a10b698e..e56331af9c94 100644 --- a/example-code/snippets/src/backend/WireFormat.test.ts +++ b/example-code/snippets/src/backend/WireFormat.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { Id64 } from "@itwin/core-bentley"; -import { Angle, AngleSweep, Arc3d, LineString3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; import { SnapshotDb } from "@itwin/core-backend"; +import { Id64 } from "@itwin/core-bentley"; import { Code, GeometricElement3dProps, GeometryStreamBuilder, IModel, Placement3dProps } from "@itwin/core-common"; +import { Angle, AngleSweep, Arc3d, LineString3d, Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { IModelTestUtils } from "./IModelTestUtils"; /** Example code organized as tests to make sure that it builds and runs successfully. @@ -33,20 +33,18 @@ describe("Wire Format Snippets", () => { /* eslint-disable */ const expectedProps = - // __PUBLISH_EXTRACT_START__ WireFormat_RootSubject.json - { - "classFullName": "BisCore:Subject", - "code": { - "scope": "0x1", - "spec": "0x1f", - "value": "DgnDbTestUtils" - }, - "description": "", - "id": "0x1", - "model": "0x1" - } - // __PUBLISH_EXTRACT_END__ - ; + // __PUBLISH_EXTRACT_START__ WireFormat_RootSubject.json + { + "classFullName": "BisCore:Subject", + "code": { + "scope": "0x1", + "spec": "0x1f", + "value": "DgnDbTestUtils", + }, + "description": "", + "id": "0x1", + "model": "0x1", + }; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(json)).deep.eq(expectedProps); @@ -61,22 +59,20 @@ describe("Wire Format Snippets", () => { /* eslint-disable */ const expectedProps = - // __PUBLISH_EXTRACT_START__ WireFormat_RepositoryModel.json - { - "classFullName": "BisCore:RepositoryModel", - "id": "0x1", - "isPrivate": false, - "isTemplate": false, - "jsonProperties": {}, - "modeledElement": { + // __PUBLISH_EXTRACT_START__ WireFormat_RepositoryModel.json + { + "classFullName": "BisCore:RepositoryModel", "id": "0x1", - "relClassName": "BisCore:ModelModelsElement", - }, - "parentModel": "0x1", - "name": "DgnDbTestUtils" - } - // __PUBLISH_EXTRACT_END__ - ; + "isPrivate": false, + "isTemplate": false, + "jsonProperties": {}, + "modeledElement": { + "id": "0x1", + "relClassName": "BisCore:ModelModelsElement", + }, + "parentModel": "0x1", + "name": "DgnDbTestUtils", + }; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(json)).deep.eq(expectedProps); @@ -129,56 +125,51 @@ describe("Wire Format Snippets", () => { /* eslint-disable */ const expectedArcJson = - // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Arc.json - { - "center": [ - 0, - 0, - 0 - ], - "sweep": [ - 90, - 180 - ], - "vector0": [ - 1, - 0, - 0 - ], - "vector90": [ - 0, - 1, - 0 - ] - } - // __PUBLISH_EXTRACT_END__ - ; + // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Arc.json + { + "center": [ + 0, + 0, + 0, + ], + "sweep": [ + 90, + 180, + ], + "vector0": [ + 1, + 0, + 0, + ], + "vector90": [ + 0, + 1, + 0, + ], + }; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(arcJson)).deep.eq(expectedArcJson); /* eslint-disable */ const expectedLineStringJson = // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_LineString.json - [ [ 0, 0, - 0 + 0, ], [ 1, 2, - 0 + 0, ], [ 1, 2, - 4 - ] - ] - // __PUBLISH_EXTRACT_END__ - ; + 4, + ], + ]; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(lineStringJson)).deep.eq(expectedLineStringJson); @@ -191,138 +182,131 @@ describe("Wire Format Snippets", () => { "center": [ 0, 0, - 0 + 0, ], "vectorX": [ 1, 0, - 0 + 0, ], "vectorY": [ 0, 1, - 0 + 0, ], "sweepStartEnd": [ 90, - 180 - ] - } + 180, + ], + }, }, { "lineString": [ [ 0, 0, - 0 + 0, ], [ 1, 2, - 0 + 0, ], [ 1, 2, - 4 - ] - ] - } - ] - // __PUBLISH_EXTRACT_END__ - ; + 4, + ], + ], + }, + ]; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(geometryStreamJson)).deep.eq(expectedGeomStreamJson); /* eslint-disable */ const expectedPlacementJson = - // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Placement.json - { - "origin": [ - 100, - 100, - 0 - ], - "angles": { - "pitch": 90 - } - } - // __PUBLISH_EXTRACT_END__ - ; - /* eslint-enable */ - expect(JSON.parse(placementJson)).deep.eq(expectedPlacementJson); - - /* eslint-disable */ - const expectedElementJson = - // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Element.json - { - "classFullName": "Generic:PhysicalObject", - "model": "0", - "code": { - "spec": "0x1", - "scope": "0x1", - "value": "" - }, - "category": "0", - "placement": { + // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Placement.json + { "origin": [ 100, 100, - 0 + 0, ], "angles": { - "pitch": 90 - } - }, - "geom": [ - { - "arc": { - "center": [ - 0, - 0, - 0 - ], - "vectorX": [ - 1, - 0, - 0 - ], - "vectorY": [ - 0, - 1, - 0 - ], - "sweepStartEnd": [ - 90, - 180 - ] - } + "pitch": 90, }, - { - "lineString": [ - [ - 0, - 0, - 0 - ], - [ - 1, - 2, - 0 + }; // __PUBLISH_EXTRACT_END__ + /* eslint-enable */ + expect(JSON.parse(placementJson)).deep.eq(expectedPlacementJson); + + /* eslint-disable */ + const expectedElementJson = + // __PUBLISH_EXTRACT_START__ WireFormat_GeometricElement3d_Element.json + { + "classFullName": "Generic:PhysicalObject", + "model": "0", + "code": { + "spec": "0x1", + "scope": "0x1", + "value": "", + }, + "category": "0", + "placement": { + "origin": [ + 100, + 100, + 0, + ], + "angles": { + "pitch": 90, + }, + }, + "geom": [ + { + "arc": { + "center": [ + 0, + 0, + 0, + ], + "vectorX": [ + 1, + 0, + 0, + ], + "vectorY": [ + 0, + 1, + 0, + ], + "sweepStartEnd": [ + 90, + 180, + ], + }, + }, + { + "lineString": [ + [ + 0, + 0, + 0, + ], + [ + 1, + 2, + 0, + ], + [ + 1, + 2, + 4, + ], ], - [ - 1, - 2, - 4 - ] - ] - } - ] - } - // __PUBLISH_EXTRACT_END__ - ; + }, + ], + }; // __PUBLISH_EXTRACT_END__ /* eslint-enable */ expect(JSON.parse(elementPropsJson)).deep.eq(expectedElementJson); }); - }); diff --git a/example-code/snippets/src/backend/WorkspaceExamples.test.ts b/example-code/snippets/src/backend/WorkspaceExamples.test.ts index 97dbe135ec94..18aa49045bc5 100644 --- a/example-code/snippets/src/backend/WorkspaceExamples.test.ts +++ b/example-code/snippets/src/backend/WorkspaceExamples.test.ts @@ -3,14 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { IModelTestUtils } from "./IModelTestUtils"; import { - EditableWorkspaceContainer, EditableWorkspaceDb, IModelHost, SettingGroupSchema, SettingsContainer, - SettingsDictionaryProps, SettingsPriority, StandaloneDb, Workspace, WorkspaceDb, WorkspaceEditor, + EditableWorkspaceContainer, + EditableWorkspaceDb, + IModelHost, + SettingGroupSchema, + SettingsContainer, + SettingsDictionaryProps, + SettingsPriority, + StandaloneDb, + Workspace, + WorkspaceDb, + WorkspaceEditor, } from "@itwin/core-backend"; import { assert, Guid, OpenMode } from "@itwin/core-bentley"; +import { expect } from "chai"; import { AzuriteTest } from "./AzuriteTest"; +import { IModelTestUtils } from "./IModelTestUtils"; /** Example code organized as tests to make sure that it builds and runs successfully. */ describe("Workspace Examples", () => { @@ -422,7 +431,11 @@ describe("Workspace Examples", () => { // __PUBLISH_EXTRACT_END__ expect(allTrees.map((x) => x.commonName)).to.deep.equal([ - "Pagoda Dogwood", "Roughleaf Dogwood", "Northern Swamp Dogwood", "Pacific Silver Fir", "Balsam Fir", + "Pagoda Dogwood", + "Roughleaf Dogwood", + "Northern Swamp Dogwood", + "Pacific Silver Fir", + "Balsam Fir", ]); expect(iModelTrees.map((x) => x.commonName)).to.deep.equal(["Pagoda Dogwood", "Northern Swamp Dogwood", "Balsam Fir"]); diff --git a/example-code/snippets/src/extensions/SmartDeviceDecorator.ts b/example-code/snippets/src/extensions/SmartDeviceDecorator.ts index 215b9428cccc..ef38cf754afb 100644 --- a/example-code/snippets/src/extensions/SmartDeviceDecorator.ts +++ b/example-code/snippets/src/extensions/SmartDeviceDecorator.ts @@ -5,14 +5,7 @@ /* eslint-disable @typescript-eslint/naming-convention, no-console */ // __PUBLISH_EXTRACT_START__ ExtensionSample-SmartDeviceDecorator.example-code -import { - DecorateContext, - Decorator, - IModelConnection, - Marker, - QueryRowFormat, - ScreenViewport, -} from "@itwin/core-extension"; +import { DecorateContext, Decorator, IModelConnection, Marker, QueryRowFormat, ScreenViewport } from "@itwin/core-extension"; import { SmartDeviceMarker } from "./SmartDeviceMarker"; export class SmartDeviceDecorator implements Decorator { diff --git a/example-code/snippets/src/extensions/SmartDeviceMarker.ts b/example-code/snippets/src/extensions/SmartDeviceMarker.ts index 9c787aa8b014..fbb9e68268f0 100644 --- a/example-code/snippets/src/extensions/SmartDeviceMarker.ts +++ b/example-code/snippets/src/extensions/SmartDeviceMarker.ts @@ -5,12 +5,7 @@ /* eslint-disable @typescript-eslint/naming-convention, no-console */ // __PUBLISH_EXTRACT_START__ ExtensionSample-SmartDeviceMarker.example-code -import { - BeButtonEvent, - ExtensionHost, - Marker, - StandardViewId, -} from "@itwin/core-extension"; +import { BeButtonEvent, ExtensionHost, Marker, StandardViewId } from "@itwin/core-extension"; import { XAndY, XYAndZ } from "@itwin/core-geometry"; import Bed from "../assets/Bed.png"; diff --git a/example-code/snippets/src/frontend/ContourDisplay.ts b/example-code/snippets/src/frontend/ContourDisplay.ts index 2e64a466638b..225a03a8657a 100644 --- a/example-code/snippets/src/frontend/ContourDisplay.ts +++ b/example-code/snippets/src/frontend/ContourDisplay.ts @@ -38,7 +38,7 @@ export function setupContourDisplay(viewport: Viewport): boolean { minorInterval: 2, majorIntervalCount: 8, }, - subCategories: CompressedId64Set.sortAndCompress([ "0x5b", "0x5a" ]), + subCategories: CompressedId64Set.sortAndCompress(["0x5b", "0x5a"]), }, { contourDef: { @@ -56,7 +56,7 @@ export function setupContourDisplay(viewport: Viewport): boolean { minorInterval: 1, majorIntervalCount: 7, }, - subCategories: CompressedId64Set.sortAndCompress([ "0x5c", "0x6a" ]), + subCategories: CompressedId64Set.sortAndCompress(["0x5c", "0x6a"]), }, ], }; diff --git a/example-code/snippets/src/frontend/ExecutingECSQL.ts b/example-code/snippets/src/frontend/ExecutingECSQL.ts index 62023460b280..2c3013e31cf6 100644 --- a/example-code/snippets/src/frontend/ExecutingECSQL.ts +++ b/example-code/snippets/src/frontend/ExecutingECSQL.ts @@ -62,7 +62,11 @@ async function executeECSql_HandlingRows(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_QueryRowFormat_UseECSqlPropertyIndexes - for await (const row of iModel.createQueryReader("SELECT ECInstanceId, ECClassId, Parent, LastMod FROM bis.Element WHERE Model.Id=?", QueryBinder.from(["0x10"]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT ECInstanceId, ECClassId, Parent, LastMod FROM bis.Element WHERE Model.Id=?", + QueryBinder.from(["0x10"]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`ECInstanceId is ${row[0]}`); console.log(`ECClassId is ${row[1]}`); console.log(`Parent is ${row[2]}`); @@ -129,7 +147,11 @@ async function executeECSql_QueryRowFormat(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Positional - for await (const row of iModel.createQueryReader("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", - QueryBinder.from(["MyCode", "2018-01-01T12:00:00Z"]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=? AND LastMod>=?", + QueryBinder.from(["MyCode", "2018-01-01T12:00:00Z"]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`${row.id}, ${row.className}, ${row.parent}, ${row.lastMod}`); } // __PUBLISH_EXTRACT_END__ - } { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Named - for await (const row of iModel.createQueryReader("SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", - QueryBinder.from({ code: "MyCode", lastmod: "2018-01-01T12:00:00Z" }), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT ECInstanceId,ECClassId,Parent,LastMod FROM bis.Element WHERE CodeValue=:code AND LastMod>=:lastmod", + QueryBinder.from({ code: "MyCode", lastmod: "2018-01-01T12:00:00Z" }), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`${row.id}, ${row.className}, ${row.parent}, ${row.lastMod}`); } // __PUBLISH_EXTRACT_END__ @@ -196,7 +247,11 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Navigation - for await (const row of iModel.createQueryReader("SELECT ECInstanceId FROM bis.Element WHERE Parent=?", QueryBinder.from([{ id: "0x132" }]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT ECInstanceId FROM bis.Element WHERE Parent=?", QueryBinder.from([{ id: "0x132" }]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { console.log(`${row.id}`); } // __PUBLISH_EXTRACT_END__ @@ -204,7 +259,11 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_NavigationId - for await (const row of iModel.createQueryReader("SELECT ECInstanceId FROM bis.Element WHERE Parent.Id=?", QueryBinder.from(["0x132"]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader("SELECT ECInstanceId FROM bis.Element WHERE Parent.Id=?", QueryBinder.from(["0x132"]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { console.log(`${row.id}`); } // __PUBLISH_EXTRACT_END__ @@ -212,7 +271,13 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Struct - for await (const row of iModel.createQueryReader("SELECT Name FROM myschema.Company WHERE Location=?", QueryBinder.from([{ street: "7123 Main Street", zip: 30211 }]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT Name FROM myschema.Company WHERE Location=?", + QueryBinder.from([{ street: "7123 Main Street", zip: 30211 }]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`${row.name}`); } // __PUBLISH_EXTRACT_END__ @@ -220,7 +285,13 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_StructMembers - for await (const row of iModel.createQueryReader("SELECT Name FROM myschema.Company WHERE Location.Street=? AND Location.Zip=?", QueryBinder.from(["7123 Main Street", 32443]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT Name FROM myschema.Company WHERE Location.Street=? AND Location.Zip=?", + QueryBinder.from(["7123 Main Street", 32443]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`${row.name}`); } // __PUBLISH_EXTRACT_END__ @@ -228,7 +299,13 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { { // __PUBLISH_EXTRACT_START__ ExecuteECSql_Binding_Array - for await (const row of iModel.createQueryReader("SELECT Name FROM myschema.Company WHERE PhoneNumbers=?", QueryBinder.from([["+16134584201", "+16134584202", "+16134584222"]]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT Name FROM myschema.Company WHERE PhoneNumbers=?", + QueryBinder.from([["+16134584201", "+16134584202", "+16134584222"]]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { console.log(`${row.name}`); } // __PUBLISH_EXTRACT_END__ @@ -236,7 +313,7 @@ async function executeECSql_Binding(iModel: IModelConnection): Promise { } const dummyIModel: IModelConnection = {} as IModelConnection; -executeECSql_ECSqlReaderIteration(dummyIModel).catch(() => { }); -executeECSql_HandlingRows(dummyIModel).catch(() => { }); -executeECSql_QueryRowFormat(dummyIModel).catch(() => { }); -executeECSql_Binding(dummyIModel).catch(() => { }); +executeECSql_ECSqlReaderIteration(dummyIModel).catch(() => {}); +executeECSql_HandlingRows(dummyIModel).catch(() => {}); +executeECSql_QueryRowFormat(dummyIModel).catch(() => {}); +executeECSql_Binding(dummyIModel).catch(() => {}); diff --git a/example-code/snippets/src/frontend/InteractiveTools.ts b/example-code/snippets/src/frontend/InteractiveTools.ts index ef32deb8eb19..32c0f6e07c09 100644 --- a/example-code/snippets/src/frontend/InteractiveTools.ts +++ b/example-code/snippets/src/frontend/InteractiveTools.ts @@ -2,12 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Point3d, Vector3d } from "@itwin/core-geometry"; import { ColorDef } from "@itwin/core-common"; import { - AccuDrawHintBuilder, BeButtonEvent, DynamicsContext, EventHandled, HitDetail, IModelApp, LocateFilterStatus, LocateResponse, PrimitiveTool, + AccuDrawHintBuilder, + BeButtonEvent, + DynamicsContext, + EventHandled, + HitDetail, + IModelApp, + LocateFilterStatus, + LocateResponse, + PrimitiveTool, Viewport, } from "@itwin/core-frontend"; +import { Point3d, Vector3d } from "@itwin/core-geometry"; export class SamplePrimitiveTool extends PrimitiveTool { public static override toolId = "Sample.Run"; @@ -74,12 +82,16 @@ export class SampleSnapTool extends PrimitiveTool { } // __PUBLISH_EXTRACT_END__ - public async onRestartTool() { return this.exitTool(); } + public async onRestartTool() { + return this.exitTool(); + } } export class SampleLocateTool extends PrimitiveTool { public static override toolId = "Sample.Locate"; - public async onRestartTool() { return this.exitTool(); } + public async onRestartTool() { + return this.exitTool(); + } // __PUBLISH_EXTRACT_START__ PrimitiveTool_Locate public override async filterHit(hit: HitDetail, _out?: LocateResponse): Promise { diff --git a/example-code/snippets/src/frontend/RealityMeshParamsBuilder.ts b/example-code/snippets/src/frontend/RealityMeshParamsBuilder.ts index 952b2753975a..0f6212eadc58 100644 --- a/example-code/snippets/src/frontend/RealityMeshParamsBuilder.ts +++ b/example-code/snippets/src/frontend/RealityMeshParamsBuilder.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Range3d } from "@itwin/core-geometry"; import { RealityMeshParams, RealityMeshParamsBuilder } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; // __PUBLISH_EXTRACT_START__ Build_Reality_Mesh_Params export function buildRealityMeshParams(): RealityMeshParams { @@ -18,10 +18,10 @@ export function buildRealityMeshParams(): RealityMeshParams { }); // Add the 4 corners of the rectangle. - builder.addVertex({x:0, y:0, z:0}, {x:0, y:0}); - builder.addVertex({x:10, y:0, z:0}, {x:1, y:0}); - builder.addVertex({x:10, y:5, z:0}, {x:1, y:1}); - builder.addVertex({x:0, y:5, z:0}, {x:0, y:1}); + builder.addVertex({ x: 0, y: 0, z: 0 }, { x: 0, y: 0 }); + builder.addVertex({ x: 10, y: 0, z: 0 }, { x: 1, y: 0 }); + builder.addVertex({ x: 10, y: 5, z: 0 }, { x: 1, y: 1 }); + builder.addVertex({ x: 0, y: 5, z: 0 }, { x: 0, y: 1 }); // Add the two triangles describing the rectangle. builder.addTriangle(0, 1, 2); diff --git a/example-code/snippets/src/frontend/ViewDecorations.ts b/example-code/snippets/src/frontend/ViewDecorations.ts index bd67105c6e4c..876887abf9d1 100644 --- a/example-code/snippets/src/frontend/ViewDecorations.ts +++ b/example-code/snippets/src/frontend/ViewDecorations.ts @@ -3,12 +3,28 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Id64String, Logger } from "@itwin/core-bentley"; -import { AngleSweep, Arc3d, Point2d, Point3d, Transform, XAndY, XYAndZ } from "@itwin/core-geometry"; import { AxisAlignedBox3d, ColorByName, ColorDef, NpcCenter } from "@itwin/core-common"; import { - BeButton, BeButtonEvent, Cluster, DecorateContext, Decorator, GraphicBranch, GraphicType, HitDetail, imageElementFromUrl, - IModelApp, IModelConnection, Marker, MarkerImage, MarkerSet, MessageBoxIconType, MessageBoxType, readGltfGraphics, RenderGraphic, + BeButton, + BeButtonEvent, + Cluster, + DecorateContext, + Decorator, + GraphicBranch, + GraphicType, + HitDetail, + imageElementFromUrl, + IModelApp, + IModelConnection, + Marker, + MarkerImage, + MarkerSet, + MessageBoxIconType, + MessageBoxType, + readGltfGraphics, + RenderGraphic, } from "@itwin/core-frontend"; +import { AngleSweep, Arc3d, Point2d, Point3d, Transform, XAndY, XYAndZ } from "@itwin/core-geometry"; // cSpell:ignore lerp @@ -52,10 +68,14 @@ export class ExamplePickableGraphicDecoration { } /** Return true if supplied Id represents a pickable decoration created by this decorator. */ - public testDecorationHit(id: string): boolean { return id === this._decoId; } + public testDecorationHit(id: string): boolean { + return id === this._decoId; + } /** Return localized tooltip message for the decoration identified by HitDetail.sourceId. */ - public async getDecorationToolTip(_hit: HitDetail): Promise { return "Project Extents"; } + public async getDecorationToolTip(_hit: HitDetail): Promise { + return "Project Extents"; + } // __PUBLISH_EXTRACT_END__ } @@ -111,7 +131,8 @@ class IncidentMarker extends Marker { /** Get a color based on severity by interpolating Green(0) -> Amber(15) -> Red(30) */ public static makeColor(severity: number): ColorDef { - return (severity <= 16 ? ColorDef.green.lerp(this._amber, (severity - 1) / 15.) : + return (severity <= 16 ? + ColorDef.green.lerp(this._amber, (severity - 1) / 15.) : this._amber.lerp(ColorDef.red, (severity - 16) / 14.)); } @@ -227,7 +248,9 @@ export class IncidentMarkerDemo { private static _numMarkers = 500; public static decorator?: IncidentMarkerDemo; // static variable so we can tell if the demo is active. - public get warningSign() { return this._images[0]; } + public get warningSign() { + return this._images[0]; + } // Load one image, logging if there was an error private async loadOne(src: string) { diff --git a/example-code/snippets/src/frontend/Worker.ts b/example-code/snippets/src/frontend/Worker.ts index 243b33d8dcbe..6b35a3102d48 100644 --- a/example-code/snippets/src/frontend/Worker.ts +++ b/example-code/snippets/src/frontend/Worker.ts @@ -5,7 +5,19 @@ import { assert } from "@itwin/core-bentley"; import { ColorDef } from "@itwin/core-common"; -import { createWorkerProxy, GraphicDescription, GraphicDescriptionBuilder, GraphicDescriptionContextProps, GraphicType, IModelApp, IModelConnection, registerWorker, RenderGraphic, WorkerGraphicDescriptionContext, WorkerGraphicDescriptionContextProps } from "@itwin/core-frontend"; +import { + createWorkerProxy, + GraphicDescription, + GraphicDescriptionBuilder, + GraphicDescriptionContextProps, + GraphicType, + IModelApp, + IModelConnection, + registerWorker, + RenderGraphic, + WorkerGraphicDescriptionContext, + WorkerGraphicDescriptionContextProps, +} from "@itwin/core-frontend"; import { Arc3d, Point3d } from "@itwin/core-geometry"; // __PUBLISH_EXTRACT_START__ Worker_CalculatorInterface @@ -89,7 +101,7 @@ async function testCalculator() { // __PUBLISH_EXTRACT_START__ Worker_TerminateCalculatorProxy calculator.terminate(); assert(calculator.isTerminated); -// __PUBLISH_EXTRACT_END__ + // __PUBLISH_EXTRACT_END__ } // __PUBLISH_EXTRACT_START__ Worker_GraphicCreatorInterface @@ -194,7 +206,12 @@ async function testGraphicCreator() { const worker = createWorkerProxy("./graphic-creator.js"); // Create a render graphic from a description of a large number of circles, using a WorkerProxy. - async function createCircleGraphic(xyzRadius: Float64Array, color: Uint32Array, chordTolerance: number, iModel: IModelConnection): Promise { + async function createCircleGraphic( + xyzRadius: Float64Array, + color: Uint32Array, + chordTolerance: number, + iModel: IModelConnection, + ): Promise { // Package up the RenderSystem's context to be sent to the Worker. const workerContext = IModelApp.renderSystem.createWorkerGraphicDescriptionContextProps(iModel); diff --git a/example-code/snippets/src/pcf/DynamicSchema.ts b/example-code/snippets/src/pcf/DynamicSchema.ts index a467726dfc00..924c82d3ef18 100644 --- a/example-code/snippets/src/pcf/DynamicSchema.ts +++ b/example-code/snippets/src/pcf/DynamicSchema.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Schema as MetaSchema, SchemaContext, SchemaLoader, SchemaPropsGetter } from "@itwin/ecschema-metadata"; import { ClassRegistry, Element, ElementAspect, IModelDb, Relationship, Schema, Schemas } from "@itwin/core-backend"; import { AnyDiagnostic, ISchemaChanges, ISchemaCompareReporter, SchemaChanges, SchemaComparer, SchemaContextEditor } from "@itwin/ecschema-editing"; +import { Schema as MetaSchema, SchemaContext, SchemaLoader, SchemaPropsGetter } from "@itwin/ecschema-metadata"; import { MutableSchema } from "@itwin/ecschema-metadata/lib/cjs/Metadata/Schema"; import * as pcf from "./pcf"; @@ -43,7 +43,6 @@ export async function syncDynamicSchema( domainSchemaNames: string[], props: DynamicSchemaProps, ): Promise { - const { schemaName } = props; const existingSchema = await tryGetSchema(db, schemaName); @@ -81,7 +80,6 @@ export async function syncDynamicSchema( // __PUBLISH_EXTRACT_START__ DynamicSchema-registerDynamicSchema.example-code function registerDynamicSchema(props: DynamicSchemaProps) { - const entitiesModule: any = {}; for (const entity of props.dynamicEntityMap.entities) { if (entity.registeredClass) { @@ -122,7 +120,6 @@ async function createDynamicSchema( domainSchemaNames: string[], props: DynamicSchemaProps, ): Promise { - const map = props.dynamicEntityMap; const context = new SchemaContext(); const editor = new SchemaContextEditor(context); @@ -190,8 +187,8 @@ class DynamicSchemaCompareReporter implements ISchemaCompareReporter { this.changes.push(schemaChanges as SchemaChanges); } - public get diagnostics(): AnyDiagnostic [] { - let diagnostics: AnyDiagnostic [] = []; + public get diagnostics(): AnyDiagnostic[] { + let diagnostics: AnyDiagnostic[] = []; for (const changes of this.changes) { diagnostics = diagnostics.concat(changes.allDiagnostics); } diff --git a/example-code/snippets/src/pcf/pcf.ts b/example-code/snippets/src/pcf/pcf.ts index a3814d00cefa..e5f117c3e55b 100644 --- a/example-code/snippets/src/pcf/pcf.ts +++ b/example-code/snippets/src/pcf/pcf.ts @@ -4,12 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { EntityClassProps, RelationshipClassProps } from "@itwin/ecschema-metadata"; -export type ECDynamicEntityClassProps = (EntityClassProps & { name: string, baseClass: string }); -export type ECDynamicElementAspectClassProps = (EntityClassProps & { name: string, baseClass: string }); +export type ECDynamicEntityClassProps = EntityClassProps & { name: string, baseClass: string }; +export type ECDynamicElementAspectClassProps = EntityClassProps & { name: string, baseClass: string }; export type ECDynamicRelationshipClassProps = RelationshipClassProps; export enum ItemState { New, Changed, - Unchanged + Unchanged, } diff --git a/example-code/snippets/tsconfig.json b/example-code/snippets/tsconfig.json index 6c0c3f282cf0..594750339386 100644 --- a/example-code/snippets/tsconfig.json +++ b/example-code/snippets/tsconfig.json @@ -2,7 +2,7 @@ "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", "compilerOptions": { "outDir": "./lib", - "esModuleInterop": true, + "esModuleInterop": true }, "include": ["./src/**/*.ts"] } diff --git a/extensions/frontend-tiles/certa.json b/extensions/frontend-tiles/certa.json index 1df3f8ef1d94..936f221b80dc 100644 --- a/extensions/frontend-tiles/certa.json +++ b/extensions/frontend-tiles/certa.json @@ -24,4 +24,3 @@ ] } } - diff --git a/extensions/frontend-tiles/eslint.config.js b/extensions/frontend-tiles/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/extensions/frontend-tiles/eslint.config.js +++ b/extensions/frontend-tiles/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/extensions/frontend-tiles/src/BatchedModelGroups.ts b/extensions/frontend-tiles/src/BatchedModelGroups.ts index 209ab28e707d..660f7a89bb94 100644 --- a/extensions/frontend-tiles/src/BatchedModelGroups.ts +++ b/extensions/frontend-tiles/src/BatchedModelGroups.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ModelGroupDisplayTransforms } from "./ModelGroupDisplayTransforms"; -import { groupModels, ModelGroup, ModelGroupingContext } from "./ModelGroup"; -import { RenderClipVolume, SpatialViewState } from "@itwin/core-frontend"; import { assert, CompressedId64Set, Id64Set, Id64String } from "@itwin/core-bentley"; import { PlanProjectionSettings, RenderSchedule, ViewFlagOverrides } from "@itwin/core-common"; +import { RenderClipVolume, SpatialViewState } from "@itwin/core-frontend"; import { ModelMetadata } from "./BatchedTilesetReader"; +import { groupModels, ModelGroup, ModelGroupingContext } from "./ModelGroup"; +import { ModelGroupDisplayTransforms } from "./ModelGroupDisplayTransforms"; /** Groups the set of spatial models included in a [[BatchedSpatialTileTreeReferences]] based on their display settings. * This ensures that models are displayed correctly, while using batching to reduce the number of draw calls to a minimum. @@ -34,7 +34,12 @@ export class BatchedModelGroups implements ModelGroupingContext { public groups: ModelGroup[] = []; public modelGroupDisplayTransforms: ModelGroupDisplayTransforms; - public constructor(view: SpatialViewState, script: RenderSchedule.Script | undefined, includedModelIds: Id64Set, metadata: Map) { + public constructor( + view: SpatialViewState, + script: RenderSchedule.Script | undefined, + includedModelIds: Id64Set, + metadata: Map, + ) { this._script = script; this._view = view; this._includedModelIds = includedModelIds; @@ -53,7 +58,9 @@ export class BatchedModelGroups implements ModelGroupingContext { this._scriptValid = false; } - public invalidateTransforms(): void { this._transformsValid = false; } + public invalidateTransforms(): void { + this._transformsValid = false; + } private listenForDisplayStyleEvents(): void { const removeListener = this._view.displayStyle.settings.onPlanProjectionSettingsChanged.addListener(() => this._groupsValid = false); diff --git a/extensions/frontend-tiles/src/BatchedModels.ts b/extensions/frontend-tiles/src/BatchedModels.ts index 10deac9a7e4a..f5891083b47b 100644 --- a/extensions/frontend-tiles/src/BatchedModels.ts +++ b/extensions/frontend-tiles/src/BatchedModels.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Id64, Id64String } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { SpatialViewState } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; import { ModelMetadata } from "./BatchedTilesetReader"; export class BatchedModels { diff --git a/extensions/frontend-tiles/src/BatchedSpatialTileTreeRefs.ts b/extensions/frontend-tiles/src/BatchedSpatialTileTreeRefs.ts index 2f1b4361f5f8..ba7e6a373b35 100644 --- a/extensions/frontend-tiles/src/BatchedSpatialTileTreeRefs.ts +++ b/extensions/frontend-tiles/src/BatchedSpatialTileTreeRefs.ts @@ -7,18 +7,24 @@ import { Id64String, Logger, OrderedId64Iterable } from "@itwin/core-bentley"; import { RenderSchedule } from "@itwin/core-common"; import { AnimationNodeId, - AttachToViewportArgs, createSpatialTileTreeReferences, IModelConnection, SpatialTileTreeReferences, SpatialViewState, - TileTreeLoadStatus, TileTreeOwner, TileTreeReference, + AttachToViewportArgs, + createSpatialTileTreeReferences, + IModelConnection, + SpatialTileTreeReferences, + SpatialViewState, + TileTreeLoadStatus, + TileTreeOwner, + TileTreeReference, Viewport, } from "@itwin/core-frontend"; -import { BatchedTileTreeReference, BatchedTileTreeReferenceArgs } from "./BatchedTileTreeReference"; -import { getBatchedTileTreeOwner } from "./BatchedTileTreeSupplier"; +import { Range3d } from "@itwin/core-geometry"; +import { BatchedModelGroups } from "./BatchedModelGroups"; import { BatchedModels } from "./BatchedModels"; -import { ComputeSpatialTilesetBaseUrl } from "./FrontendTiles"; import { BatchedTilesetSpec } from "./BatchedTilesetReader"; +import { BatchedTileTreeReference, BatchedTileTreeReferenceArgs } from "./BatchedTileTreeReference"; +import { getBatchedTileTreeOwner } from "./BatchedTileTreeSupplier"; +import { ComputeSpatialTilesetBaseUrl } from "./FrontendTiles"; import { loggerCategory } from "./LoggerCategory"; -import { BatchedModelGroups } from "./BatchedModelGroups"; -import { Range3d } from "@itwin/core-geometry"; // Obtains tiles pre-published by mesh export service. class BatchedSpatialTileTreeReferences implements SpatialTileTreeReferences { @@ -76,9 +82,10 @@ class BatchedSpatialTileTreeReferences implements SpatialTileTreeReferences { const currentScript = this._currentScript; this._currentScript = newScript; - if (newScript !== currentScript) + if (newScript !== currentScript) { if (!newScript || !currentScript || !newScript.equals(currentScript)) this._groups.setScript(newScript); + } }; let rmListener = this._view.displayStyle.onScheduleScriptChanged.addListener((newScript) => onScriptChanged(newScript)); @@ -206,7 +213,7 @@ class ProxyTileTreeReference extends TileTreeReference { tileTree: undefined, loadStatus: TileTreeLoadStatus.NotLoaded, load: () => undefined, - dispose: () => { }, + dispose: () => {}, loadTree: async () => Promise.resolve(undefined), }; } @@ -235,15 +242,15 @@ class ProxySpatialTileTreeReferences implements SpatialTileTreeReferences { getSpec.then((spec: BatchedTilesetSpec | null) => { if (spec) { this.setTreeRefs(new BatchedSpatialTileTreeReferences(spec, view)); - } else if(nopFallback) { + } else if (nopFallback) { this.setTreeRefs(new EmptySpatialTileTreeReferences()); - }else { + } else { this.setTreeRefs(createSpatialTileTreeReferences(view)); } }).catch(() => { - if(nopFallback) { + if (nopFallback) { this.setTreeRefs(new EmptySpatialTileTreeReferences()); - }else { + } else { this.setTreeRefs(createSpatialTileTreeReferences(view)); } }); @@ -276,7 +283,7 @@ class ProxySpatialTileTreeReferences implements SpatialTileTreeReferences { this._attachArgs = undefined; } - public setDeactivated(): void { } + public setDeactivated(): void {} public *[Symbol.iterator](): Iterator { if (this._impl) { @@ -321,13 +328,17 @@ async function fetchTilesetSpec(iModel: IModelConnection, computeBaseUrl: Comput class EmptySpatialTileTreeReferences implements SpatialTileTreeReferences { public update(): void {} - public setDeactivated(_modelIds: string | string[] | undefined, _deactivated: boolean | undefined, _refs: "all" | "animated" | "primary" | "section" | number[]): void {} + public setDeactivated( + _modelIds: string | string[] | undefined, + _deactivated: boolean | undefined, + _refs: "all" | "animated" | "primary" | "section" | number[], + ): void {} public attachToViewport(_args: Viewport): void {} public detachFromViewport(): void {} - public collectMaskRefs(_modelIds: OrderedId64Iterable, _maskTreeRefs: TileTreeReference[]): void {}; + public collectMaskRefs(_modelIds: OrderedId64Iterable, _maskTreeRefs: TileTreeReference[]): void {} public getModelsNotInMask(_maskModels: OrderedId64Iterable | undefined, _useVisible: boolean): string[] | undefined { return undefined; @@ -337,7 +348,11 @@ class EmptySpatialTileTreeReferences implements SpatialTileTreeReferences { } /** @internal */ -export function createBatchedSpatialTileTreeReferences(view: SpatialViewState, computeBaseUrl: ComputeSpatialTilesetBaseUrl, nopFallback: boolean = false): SpatialTileTreeReferences { +export function createBatchedSpatialTileTreeReferences( + view: SpatialViewState, + computeBaseUrl: ComputeSpatialTilesetBaseUrl, + nopFallback: boolean = false, +): SpatialTileTreeReferences { const iModel = view.iModel; let entry = iModelToTilesetSpec.get(iModel); if (undefined === entry) { @@ -369,4 +384,3 @@ export function createBatchedSpatialTileTreeReferences(view: SpatialViewState, c return new BatchedSpatialTileTreeReferences(entry, view); } - diff --git a/extensions/frontend-tiles/src/BatchedTile.ts b/extensions/frontend-tiles/src/BatchedTile.ts index efb8efbc24c7..25ce1a2c0e02 100644 --- a/extensions/frontend-tiles/src/BatchedTile.ts +++ b/extensions/frontend-tiles/src/BatchedTile.ts @@ -4,16 +4,30 @@ *--------------------------------------------------------------------------------------------*/ import { assert, BeTimePoint, ByteStream, Logger } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { ColorDef, Tileset3dSchema } from "@itwin/core-common"; import { - GraphicBranch, GraphicBuilder, IModelApp, RealityTileLoader, RenderSystem, Tile, TileBoundingBoxes, TileContent, - TileDrawArgs, TileParams, TileRequest, TileRequestChannel, TileTreeLoadStatus, TileUser, TileVisibility, Viewport, + GraphicBranch, + GraphicBuilder, + IModelApp, + RealityTileLoader, + RenderSystem, + Tile, + TileBoundingBoxes, + TileContent, + TileDrawArgs, + TileParams, + TileRequest, + TileRequestChannel, + TileTreeLoadStatus, + TileUser, + TileVisibility, + Viewport, } from "@itwin/core-frontend"; -import { loggerCategory } from "./LoggerCategory"; +import { Transform } from "@itwin/core-geometry"; import { BatchedTileTree } from "./BatchedTileTree"; import { frontendTilesOptions } from "./FrontendTiles"; import { IndexedDBCache, LocalCache, PassThroughCache } from "./IndexedDBCache"; +import { loggerCategory } from "./LoggerCategory"; /** @internal */ export interface BatchedTileParams extends TileParams { @@ -61,7 +75,6 @@ export class BatchedTile extends Tile { this.transformToRoot.multiplyRange(this.range, this.range); if (this._contentRange) this.transformToRoot.multiplyRange(this._contentRange, this._contentRange); - } private get _batchedChildren(): BatchedTile[] | undefined { @@ -149,7 +162,7 @@ export class BatchedTile extends Tile { public override async readContent(data: TileRequest.ResponseData, system: RenderSystem, isCanceled?: () => boolean): Promise { assert(data instanceof Uint8Array); if (!(data instanceof Uint8Array)) - return { }; + return {}; try { const modelGroups = this.batchedTree.modelGroups; diff --git a/extensions/frontend-tiles/src/BatchedTileContentReader.ts b/extensions/frontend-tiles/src/BatchedTileContentReader.ts index 7a1392a3e558..577617894c1a 100644 --- a/extensions/frontend-tiles/src/BatchedTileContentReader.ts +++ b/extensions/frontend-tiles/src/BatchedTileContentReader.ts @@ -4,11 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { assert, Id64, Id64String } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { Feature, FeatureTable, TileReadStatus } from "@itwin/core-common"; -import { - GltfDataType, GltfMeshPrimitive, GltfReader, GltfReaderArgs, GltfReaderResult, -} from "@itwin/core-frontend"; +import { GltfDataType, GltfMeshPrimitive, GltfReader, GltfReaderArgs, GltfReaderResult } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; interface BatchedTileReaderArgs extends GltfReaderArgs { modelId: Id64String; diff --git a/extensions/frontend-tiles/src/BatchedTileTree.ts b/extensions/frontend-tiles/src/BatchedTileTree.ts index f1552d20a0c8..1821b8380a53 100644 --- a/extensions/frontend-tiles/src/BatchedTileTree.ts +++ b/extensions/frontend-tiles/src/BatchedTileTree.ts @@ -5,9 +5,7 @@ import { BeTimePoint, Id64Set, Id64String } from "@itwin/core-bentley"; import { BatchType, RenderMode, RenderSchedule, ViewFlagOverrides } from "@itwin/core-common"; -import { - acquireImdlDecoder, ImdlDecoder, IModelApp, Tile, TileDrawArgs, TileTree, TileTreeParams, -} from "@itwin/core-frontend"; +import { acquireImdlDecoder, ImdlDecoder, IModelApp, Tile, TileDrawArgs, TileTree, TileTreeParams } from "@itwin/core-frontend"; import { BatchedTile, BatchedTileParams } from "./BatchedTile"; import { BatchedTilesetReader, ModelMetadata } from "./BatchedTilesetReader"; import { frontendTilesOptions } from "./FrontendTiles"; @@ -70,7 +68,7 @@ export class BatchedTileTree extends TileTree { } public override get viewFlagOverrides(): ViewFlagOverrides { - return frontendTilesOptions.enableEdges ?{ } : defaultViewFlags; + return frontendTilesOptions.enableEdges ? {} : defaultViewFlags; } // eslint-disable-next-line @typescript-eslint/naming-convention diff --git a/extensions/frontend-tiles/src/BatchedTileTreeReference.ts b/extensions/frontend-tiles/src/BatchedTileTreeReference.ts index b1871d04abe6..188b72e941c8 100644 --- a/extensions/frontend-tiles/src/BatchedTileTreeReference.ts +++ b/extensions/frontend-tiles/src/BatchedTileTreeReference.ts @@ -4,13 +4,25 @@ *--------------------------------------------------------------------------------------------*/ import { assert, Id64Set } from "@itwin/core-bentley"; -import { Range3d, Transform } from "@itwin/core-geometry"; import { - BatchType, FeatureAppearance, FeatureAppearanceProvider, FeatureAppearanceSource, GeometryClass, ViewFlagOverrides, + BatchType, + FeatureAppearance, + FeatureAppearanceProvider, + FeatureAppearanceSource, + GeometryClass, + ViewFlagOverrides, } from "@itwin/core-common"; import { - formatAnimationBranchId, RenderClipVolume, SceneContext, TileDrawArgs, TileGraphicType, TileTree, TileTreeOwner, TileTreeReference, + formatAnimationBranchId, + RenderClipVolume, + SceneContext, + TileDrawArgs, + TileGraphicType, + TileTree, + TileTreeOwner, + TileTreeReference, } from "@itwin/core-frontend"; +import { Range3d, Transform } from "@itwin/core-geometry"; import { BatchedModels } from "./BatchedModels"; import { ModelGroup, ModelGroupInfo } from "./ModelGroup"; @@ -65,10 +77,13 @@ export class BatchedTileTreeReference extends TileTreeReference implements Featu public getFeatureAppearance( source: FeatureAppearanceSource, - elemLo: number, elemHi: number, - subcatLo: number, subcatHi: number, + elemLo: number, + elemHi: number, + subcatLo: number, + subcatHi: number, geomClass: GeometryClass, - modelLo: number, modelHi: number, + modelLo: number, + modelHi: number, type: BatchType, animationNodeId: number, ): FeatureAppearance | undefined { diff --git a/extensions/frontend-tiles/src/BatchedTileTreeSupplier.ts b/extensions/frontend-tiles/src/BatchedTileTreeSupplier.ts index 6fc45d3bdfa5..0d2ab4213994 100644 --- a/extensions/frontend-tiles/src/BatchedTileTreeSupplier.ts +++ b/extensions/frontend-tiles/src/BatchedTileTreeSupplier.ts @@ -5,12 +5,10 @@ import { comparePossiblyUndefined, compareStrings, CompressedId64Set, Logger } from "@itwin/core-bentley"; import { RenderSchedule } from "@itwin/core-common"; -import { - IModelConnection, TileTree, TileTreeOwner, TileTreeSupplier, -} from "@itwin/core-frontend"; -import { loggerCategory } from "./LoggerCategory"; +import { IModelConnection, TileTree, TileTreeOwner, TileTreeSupplier } from "@itwin/core-frontend"; import { BatchedTilesetReader, BatchedTilesetSpec } from "./BatchedTilesetReader"; import { BatchedTileTree } from "./BatchedTileTree"; +import { loggerCategory } from "./LoggerCategory"; /** @internal */ export interface BatchedTileTreeId { diff --git a/extensions/frontend-tiles/src/BatchedTilesetReader.ts b/extensions/frontend-tiles/src/BatchedTilesetReader.ts index 5958f893d0c0..a85f27174e0c 100644 --- a/extensions/frontend-tiles/src/BatchedTilesetReader.ts +++ b/extensions/frontend-tiles/src/BatchedTilesetReader.ts @@ -4,13 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Id64, Id64Set, Id64String } from "@itwin/core-bentley"; -import { - Matrix3d, Point3d, Range3d, Range3dProps, Transform, Vector3d, -} from "@itwin/core-geometry"; import { Tileset3dSchema as schema, ViewFlagOverrides } from "@itwin/core-common"; import { IModelConnection, RealityModelTileUtils, TileLoadPriority } from "@itwin/core-frontend"; -import { BatchedTileTreeParams } from "./BatchedTileTree"; +import { Matrix3d, Point3d, Range3d, Range3dProps, Transform, Vector3d } from "@itwin/core-geometry"; import { BatchedTile, BatchedTileParams } from "./BatchedTile"; +import { BatchedTileTreeParams } from "./BatchedTileTree"; /** @internal */ export interface ModelMetadataProps { @@ -112,9 +110,15 @@ function rangeFromBoundingVolume(vol: schema.BoundingVolume): Range3d { function transformFromJSON(json: schema.Transform): Transform { const translation = new Point3d(json[12], json[13], json[14]); const matrix = Matrix3d.createRowValues( - json[0], json[4], json[8], - json[1], json[5], json[9], - json[2], json[6], json[10], + json[0], + json[4], + json[8], + json[1], + json[5], + json[9], + json[2], + json[6], + json[10], ); return Transform.createOriginAndMatrix(translation, matrix); @@ -132,7 +136,9 @@ export class BatchedTilesetReader { this._modelGroups = modelGroups; } - public get baseUrl(): URL { return this._spec.baseUrl; } + public get baseUrl(): URL { + return this._spec.baseUrl; + } public readTileParams(json: schema.Tile, parent?: BatchedTile): BatchedTileParams { const content = json.content; diff --git a/extensions/frontend-tiles/src/FrontendTiles.ts b/extensions/frontend-tiles/src/FrontendTiles.ts index 191170cfa867..de75ead6e87e 100644 --- a/extensions/frontend-tiles/src/FrontendTiles.ts +++ b/extensions/frontend-tiles/src/FrontendTiles.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { AccessToken } from "@itwin/core-bentley"; import { IModelApp, IModelConnection, SpatialTileTreeReferences, SpatialViewState } from "@itwin/core-frontend"; import { createBatchedSpatialTileTreeReferences } from "./BatchedSpatialTileTreeRefs"; import { queryGraphicRepresentations } from "./GraphicsProvider/GraphicRepresentationProvider"; -import { AccessToken } from "@itwin/core-bentley"; import { obtainIModelTilesetUrl, ObtainIModelTilesetUrlArgs } from "./GraphicsProvider/GraphicsProvider"; /** A function that can provide the base URL where a tileset representing all of the spatial models in a given iModel are stored. @@ -165,9 +165,9 @@ export interface FrontendTilesOptions { */ enableCDN?: boolean; /** Specifies whether to enable an IndexedDB database for use as a local cache. - * Requested tiles will then first be search for in the database, and if not found, fetched as normal. - * @internal - */ + * Requested tiles will then first be search for in the database, and if not found, fetched as normal. + * @internal + */ useIndexedDBCache?: boolean; /** If true, an empty tile tree will be used as fallback if the tileset is not found or invalid. @@ -200,14 +200,16 @@ export function initializeFrontendTiles(options: FrontendTilesOptions): void { frontendTilesOptions.useIndexedDBCache = true; const computeUrl = options.computeSpatialTilesetBaseUrl ?? ( - async (iModel: IModelConnection) => obtainMeshExportTilesetUrl({ - iTwinId: iModel.iTwinId, - iModelId: iModel.iModelId, - changesetId: iModel.changeset.id, - accessToken: await IModelApp.getAccessToken(), - enableCDN: options.enableCDN, - }) + async (iModel: IModelConnection) => + obtainMeshExportTilesetUrl({ + iTwinId: iModel.iTwinId, + iModelId: iModel.iModelId, + changesetId: iModel.changeset.id, + accessToken: await IModelApp.getAccessToken(), + enableCDN: options.enableCDN, + }) ); - SpatialTileTreeReferences.create = (view: SpatialViewState) => createBatchedSpatialTileTreeReferences(view, computeUrl, options.nopFallback ?? false); + SpatialTileTreeReferences.create = (view: SpatialViewState) => + createBatchedSpatialTileTreeReferences(view, computeUrl, options.nopFallback ?? false); } diff --git a/extensions/frontend-tiles/src/GraphicsProvider/GraphicRepresentationProvider.ts b/extensions/frontend-tiles/src/GraphicsProvider/GraphicRepresentationProvider.ts index 1a728848b233..38fe13bc62de 100644 --- a/extensions/frontend-tiles/src/GraphicsProvider/GraphicRepresentationProvider.ts +++ b/extensions/frontend-tiles/src/GraphicsProvider/GraphicRepresentationProvider.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { AccessToken, Logger } from "@itwin/core-bentley"; -import { loggerCategory } from "../LoggerCategory"; import { IModelApp, ITWINJS_CORE_VERSION } from "@itwin/core-frontend"; +import { loggerCategory } from "../LoggerCategory"; /** The expected format of the Graphic Representation * @beta @@ -40,7 +40,7 @@ export interface DataSource { id: string; /** The unique identifier for a specific version of a DataSource. * For example, if a specific version of an iModel is desired, the iModel's changesetId would be attributed to this value. - */ + */ changeId?: string; /** The type of the data source. For example, a DataSource can be of type "IMODEL" or "RealityData" */ type: string; @@ -51,37 +51,41 @@ export interface DataSource { * @see [[queryGraphicRepresentations]] for its construction as a representation of the data produced by a query of data sources. * @beta */ -export type GraphicRepresentation = { - /** The display name of the Graphic Representation */ - displayName: string; - /** The unique identifier for the Graphic Representation */ - representationId: string; - /** The status of the generation of the Graphic Representation from its Data Source. - * @see [[GraphicRepresentationStatus]] for possible values. - */ - status: GraphicRepresentationStatus; - /** The expected format of the Graphic Representation - * @see [[GraphicRepresentationFormat]] for possible values. - */ - format: GraphicRepresentationFormat; - /** The data source that the representation originates from. - * For example, a GraphicRepresentation in the 3D Tiles format might have a dataSource that is a specific iModel changeset. - */ - dataSource: DataSource; - /** The url of the graphic representation - * @note The url can only be guaranteed to be valid if the status is complete. - * Therefore, the url is optional if the status is not complete, and required if the status is complete. - */ -} & ({ - status: Omit; - url?: string; -} | { - status: GraphicRepresentationStatus.Complete; - url: string; -}); +export type GraphicRepresentation = + & { + /** The display name of the Graphic Representation */ + displayName: string; + /** The unique identifier for the Graphic Representation */ + representationId: string; + /** The status of the generation of the Graphic Representation from its Data Source. + * @see [[GraphicRepresentationStatus]] for possible values. + */ + status: GraphicRepresentationStatus; + /** The expected format of the Graphic Representation + * @see [[GraphicRepresentationFormat]] for possible values. + */ + format: GraphicRepresentationFormat; + /** The data source that the representation originates from. + * For example, a GraphicRepresentation in the 3D Tiles format might have a dataSource that is a specific iModel changeset. + */ + dataSource: DataSource; + /** The url of the graphic representation + * @note The url can only be guaranteed to be valid if the status is complete. + * Therefore, the url is optional if the status is not complete, and required if the status is complete. + */ + } + & ({ + status: Omit; + url?: string; + } | { + status: GraphicRepresentationStatus.Complete; + url: string; + }); /** Creates a URL used to query for Graphic Representations */ -function createGraphicRepresentationsQueryUrl(args: { sourceId: string, sourceType: string, urlPrefix?: string, changeId?: string, enableCDN?: boolean }): string { +function createGraphicRepresentationsQueryUrl( + args: { sourceId: string, sourceType: string, urlPrefix?: string, changeId?: string, enableCDN?: boolean }, +): string { const prefix = args.urlPrefix ?? ""; let url = `https://${prefix}api.bentley.com/mesh-export/?iModelId=${args.sourceId}&$orderBy=date:desc&$top=5`; if (args.changeId) @@ -166,7 +170,13 @@ export async function* queryGraphicRepresentations(args: QueryGraphicRepresentat SessionId: args.sessionId, }; - let url: string | undefined = createGraphicRepresentationsQueryUrl({ sourceId: args.dataSource.id, sourceType: args.dataSource.type, urlPrefix: args.urlPrefix, changeId: args.dataSource.changeId, enableCDN: args.enableCDN }); + let url: string | undefined = createGraphicRepresentationsQueryUrl({ + sourceId: args.dataSource.id, + sourceType: args.dataSource.type, + urlPrefix: args.urlPrefix, + changeId: args.dataSource.changeId, + enableCDN: args.enableCDN, + }); while (url) { let result; try { @@ -178,7 +188,9 @@ export async function* queryGraphicRepresentations(args: QueryGraphicRepresentat break; } - const foundSources = result.exports.filter((x) => x.request.exportType === args.dataSource.type && (args.includeIncomplete || x.status === GraphicRepresentationStatus.Complete)); + const foundSources = result.exports.filter((x) => + x.request.exportType === args.dataSource.type && (args.includeIncomplete || x.status === GraphicRepresentationStatus.Complete) + ); for (const foundSource of foundSources) { const graphicRepresentation: GraphicRepresentation = { displayName: foundSource.displayName, @@ -258,7 +270,10 @@ export async function obtainGraphicRepresentationUrl(args: ObtainGraphicRepresen queryArgs.dataSource.changeId = undefined; for await (const data of queryGraphicRepresentations(queryArgs)) { selectedData = data; - Logger.logInfo(loggerCategory, `No data for Data Source ${args.dataSource.id} for version ${args.dataSource.changeId}; falling back to most recent`); + Logger.logInfo( + loggerCategory, + `No data for Data Source ${args.dataSource.id} for version ${args.dataSource.changeId}; falling back to most recent`, + ); break; } } diff --git a/extensions/frontend-tiles/src/GraphicsProvider/GraphicsProvider.ts b/extensions/frontend-tiles/src/GraphicsProvider/GraphicsProvider.ts index 8421f37c12d3..cd9d4ef0605a 100644 --- a/extensions/frontend-tiles/src/GraphicsProvider/GraphicsProvider.ts +++ b/extensions/frontend-tiles/src/GraphicsProvider/GraphicsProvider.ts @@ -5,8 +5,8 @@ import { AccessToken, Logger } from "@itwin/core-bentley"; import { IModelApp } from "@itwin/core-frontend"; -import { obtainGraphicRepresentationUrl } from "./GraphicRepresentationProvider"; import { loggerCategory } from "../LoggerCategory"; +import { obtainGraphicRepresentationUrl } from "./GraphicRepresentationProvider"; /** Arguments supplied to [[obtainIModelTilesetUrl]]. * @beta @@ -36,8 +36,7 @@ export interface ObtainIModelTilesetUrlArgs { * @returns A URL from which the tileset can be loaded, or `undefined` if no appropriate URL could be obtained. * @beta */ -export async function obtainIModelTilesetUrl(args: ObtainIModelTilesetUrlArgs): -Promise { +export async function obtainIModelTilesetUrl(args: ObtainIModelTilesetUrlArgs): Promise { if (!args.iModelId) { Logger.logInfo(loggerCategory, "Cannot obtain Graphics Data for an iModel with no iModelId"); return undefined; diff --git a/extensions/frontend-tiles/src/GraphicsProvider/url-providers/GeoscienceUrlProvider.ts b/extensions/frontend-tiles/src/GraphicsProvider/url-providers/GeoscienceUrlProvider.ts index 7c9c107a3bf4..f469367a7e0c 100644 --- a/extensions/frontend-tiles/src/GraphicsProvider/url-providers/GeoscienceUrlProvider.ts +++ b/extensions/frontend-tiles/src/GraphicsProvider/url-providers/GeoscienceUrlProvider.ts @@ -67,7 +67,7 @@ export async function getGeoscienceTilesetUrl(args: GetGeoscienceTilesetArgs): P const url = `${baseUrl}/visualization/orgs/${args.organizationId}/workspaces/${args.workspaceId}/geoscience-object/${args.geoscienceObjectId}`; const response = await fetch(url, { headers }); - if(!response.ok) { + if (!response.ok) { Logger.logError(loggerCategory, `Received invalid response from ${baseUrl}, status: ${response.status}, text: ${response.statusText}`); return undefined; } diff --git a/extensions/frontend-tiles/src/IndexedDBCache.ts b/extensions/frontend-tiles/src/IndexedDBCache.ts index e29ac69b16cf..8763c58d391d 100644 --- a/extensions/frontend-tiles/src/IndexedDBCache.ts +++ b/extensions/frontend-tiles/src/IndexedDBCache.ts @@ -21,7 +21,7 @@ export class PassThroughCache implements LocalCache { } /** @internal */ -export class IndexedDBCache implements LocalCache{ +export class IndexedDBCache implements LocalCache { private _db: any; private _dbName: string; private _expirationTime?: number; @@ -31,11 +31,9 @@ export class IndexedDBCache implements LocalCache{ this._expirationTime = expirationTime ?? undefined; } - protected async open(){ - + protected async open() { // need to return a promise so that we can wait for the db to open before using it - return new Promise(function (this: IndexedDBCache, resolve: any) { - + return new Promise(function(this: IndexedDBCache, resolve: any) { // open the db const openDB = window.indexedDB.open(this._dbName, 1); @@ -45,7 +43,6 @@ export class IndexedDBCache implements LocalCache{ // this is the success callback for opening the db, it is called after onupgradeneeded openDB.onsuccess = async (event) => { - const target: any = event.target; if (target) { this._db = target.result; @@ -62,8 +59,8 @@ export class IndexedDBCache implements LocalCache{ this._db = target.result; const initialObjectStore = this._db.createObjectStore("cache", { keyPath: "uniqueId" }); - initialObjectStore.createIndex("content", "content", {unique: false}); - initialObjectStore.createIndex("timeOfStorage", "timeOfStorage", {unique: false}); + initialObjectStore.createIndex("content", "content", { unique: false }); + initialObjectStore.createIndex("timeOfStorage", "timeOfStorage", { unique: false }); }; }.bind(this)); } @@ -80,9 +77,7 @@ export class IndexedDBCache implements LocalCache{ // this is successful if the db was successfully searched - not only if a match was found storedResponse.onsuccess = async () => { - if (storedResponse.result !== undefined) { - // if the content has an expiration time if (this._expirationTime) { // We want to know when the result was stored, and how long it's been since that point @@ -166,7 +161,6 @@ export class IndexedDBCache implements LocalCache{ // If nothing was found in the db, fetch normally, then add that content to the db if (response === undefined) { - // If necessary, use the callback url if (callBackUrl) response = await (await callback(callBackUrl)).arrayBuffer(); @@ -179,4 +173,3 @@ export class IndexedDBCache implements LocalCache{ return response; } } - diff --git a/extensions/frontend-tiles/src/LoggerCategory.ts b/extensions/frontend-tiles/src/LoggerCategory.ts index 458e67157ea1..5ec3e0c0d162 100644 --- a/extensions/frontend-tiles/src/LoggerCategory.ts +++ b/extensions/frontend-tiles/src/LoggerCategory.ts @@ -5,4 +5,3 @@ /** @internal */ export const loggerCategory = "frontend-tiles"; - diff --git a/extensions/frontend-tiles/src/ModelGroupDisplayTransforms.ts b/extensions/frontend-tiles/src/ModelGroupDisplayTransforms.ts index 1dfcb92cb0dc..fb3828b53e96 100644 --- a/extensions/frontend-tiles/src/ModelGroupDisplayTransforms.ts +++ b/extensions/frontend-tiles/src/ModelGroupDisplayTransforms.ts @@ -42,7 +42,9 @@ export class ModelGroupDisplayTransforms { } /** A string uniquely identifying the current grouping. */ - public get guid(): string { return this._state.guid; } + public get guid(): string { + return this._state.guid; + } /** Get the display transform for the specified model. * @note This method is guaranteed to return the same object for all models in the same group, at least between calls to `update`. diff --git a/extensions/frontend-tiles/src/test/FrontendTiles.test.ts b/extensions/frontend-tiles/src/test/FrontendTiles.test.ts index 43a63380a8e8..858b8bad21d5 100644 --- a/extensions/frontend-tiles/src/test/FrontendTiles.test.ts +++ b/extensions/frontend-tiles/src/test/FrontendTiles.test.ts @@ -3,7 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; -import { frontendTilesOptions, FrontendTilesOptions, initializeFrontendTiles } from "../FrontendTiles"; +import { FrontendTilesOptions, frontendTilesOptions, initializeFrontendTiles } from "../FrontendTiles"; describe("FrontendTiles", () => { it("should initialize frontend tiles with default values", () => { diff --git a/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicRepresentationProvider.test.ts b/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicRepresentationProvider.test.ts index 1773951fd136..95efdd5cf8bf 100644 --- a/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicRepresentationProvider.test.ts +++ b/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicRepresentationProvider.test.ts @@ -3,11 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { IModelApp } from "@itwin/core-frontend"; import { expect, use } from "chai"; import * as chaiAsPromised from "chai-as-promised"; import * as sinon from "sinon"; -import { IModelApp } from "@itwin/core-frontend"; -import { obtainGraphicRepresentationUrl, queryGraphicRepresentations, QueryGraphicRepresentationsArgs } from "../../GraphicsProvider/GraphicRepresentationProvider"; +import { + obtainGraphicRepresentationUrl, + queryGraphicRepresentations, + QueryGraphicRepresentationsArgs, +} from "../../GraphicsProvider/GraphicRepresentationProvider"; use(chaiAsPromised); @@ -31,7 +35,7 @@ interface TestJsonResponse { }; } -interface TestJsonResponses{ +interface TestJsonResponses { exports: TestJsonResponse[]; /* eslint-disable-next-line @typescript-eslint/naming-convention */ @@ -81,8 +85,8 @@ function makeSource(props: SourceProps): TestJsonResponse { iModelId: "", changesetId: props.changesetId ?? "", exportType: "srcType", - geometryOptions: { }, - viewDefinitionFilter: { }, + geometryOptions: {}, + viewDefinitionFilter: {}, }, }; @@ -131,13 +135,18 @@ describe("queryGraphicRepresentations", () => { it("returns no results upon error", async () => { await mockFetch( - () => { throw new Error("fetch threw"); }, + () => { + throw new Error("fetch threw"); + }, async () => expectSources([], testArgs), ); await mockFetch( - async () => Promise.resolve(makeResponse( - () => { throw new Error("json threw"); }), - ), + async () => + Promise.resolve(makeResponse( + () => { + throw new Error("json threw"); + }, + )), async () => expectSources([], testArgs), ); }); @@ -160,16 +169,17 @@ describe("queryGraphicRepresentations", () => { return makeSourcesResponse({ exports: [{ id: "c" }, { id: "d" }] }); } }, - async () => expectSources(["a", "b", "c", "d"], testArgs)); + async () => expectSources(["a", "b", "c", "d"], testArgs), + ); }); it("includes only completed Data Sources unless otherwise specified", async () => { await mockFetch( - async () => makeSourcesResponse({ exports: [ { id: "a", status: "Complete" }, { id: "b", status: "Feeling Blessed" } ] }), + async () => makeSourcesResponse({ exports: [{ id: "a", status: "Complete" }, { id: "b", status: "Feeling Blessed" }] }), async () => { await expectSources(["a"], testArgs); await expectSources(["a", "b"], { ...testArgs, includeIncomplete: true }), - await expectSources(["a"], { ...testArgs, includeIncomplete: false }); + await expectSources(["a"], { ...testArgs, includeIncomplete: false }); }, ); }); diff --git a/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicsProvider.test.ts b/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicsProvider.test.ts index bdae343fe879..602db5fc6f91 100644 --- a/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicsProvider.test.ts +++ b/extensions/frontend-tiles/src/test/GraphicsProvider/GraphicsProvider.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Cartographic, EcefLocation } from "@itwin/core-common"; +import { BlankConnection, IModelApp } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; import { expect, use } from "chai"; import * as chaiAsPromised from "chai-as-promised"; import * as sinon from "sinon"; -import { Range3d } from "@itwin/core-geometry"; -import { Cartographic, EcefLocation } from "@itwin/core-common"; -import { BlankConnection, IModelApp } from "@itwin/core-frontend"; import { MeshExport, MeshExports, queryMeshExports } from "../../FrontendTiles"; import { obtainIModelTilesetUrl } from "../../GraphicsProvider/GraphicsProvider"; @@ -20,7 +20,7 @@ class TestConnection extends BlankConnection { super({ rootSubject: { name: "test-subject" }, projectExtents: new Range3d(0, 0, 0, 1, 1, 1), - ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({longitude: -75, latitude: 40, height: 0 })), + ecefLocation: EcefLocation.createFromCartographicOrigin(Cartographic.fromDegrees({ longitude: -75, latitude: 40, height: 0 })), key: "test-key", iTwinId: "test-itwin", iModelId: props.id, @@ -31,7 +31,9 @@ class TestConnection extends BlankConnection { } // BlankConnection overrides to unconditionally return `undefined` and overrides return type to only permit `undefined`. - public override get iModelId(): any { return this._id; } + public override get iModelId(): any { + return this._id; + } } async function mockFetch(mock: typeof window.fetch, fn: () => Promise): Promise { @@ -65,8 +67,8 @@ function makeExport(props: ExportProps): MeshExport { iModelId: "", changesetId: props.changesetId ?? "", exportType: "IMODEL", - geometryOptions: { }, - viewDefinitionFilter: { }, + geometryOptions: {}, + viewDefinitionFilter: {}, }, /* eslint-disable-next-line @typescript-eslint/naming-convention */ _links: { @@ -146,7 +148,7 @@ describe("obtainIModelTilesetUrl", () => { } it("returns undefined if the iModel has no iModelId", async () => { - await expectUrl(undefined, { }); + await expectUrl(undefined, {}); await expectUrl(undefined, { id: "" }); }); diff --git a/extensions/frontend-tiles/src/test/IndexedDBCache.test.ts b/extensions/frontend-tiles/src/test/IndexedDBCache.test.ts index ffcf1d101b78..0c749a91fb57 100644 --- a/extensions/frontend-tiles/src/test/IndexedDBCache.test.ts +++ b/extensions/frontend-tiles/src/test/IndexedDBCache.test.ts @@ -6,8 +6,7 @@ import { expect } from "chai"; import { IndexedDBCache } from "../IndexedDBCache"; // For Testing Only -class TestCache extends IndexedDBCache{ - +class TestCache extends IndexedDBCache { public constructor(dbName: string, expirationTime?: number) { super(dbName, expirationTime); } @@ -21,7 +20,7 @@ class TestCache extends IndexedDBCache{ await this.addContent(uniqueId, content); } - public async testRetrieveContent(uniqueId: string): Promise{ + public async testRetrieveContent(uniqueId: string): Promise { return this.retrieveContent(uniqueId); } @@ -123,8 +122,10 @@ describe("IndexedDBCache", () => { }); it("should fetch content stored with one sasurl by searching with a different sasurl from the same export", async () => { - const sasurl1 = "https://d16xw3k7duz3ee.cloudfront.net/4e90a016-44c3-4360-9221-148c44ff0efe/6-0.imdl?sv=2023-11-03&spr=https&se=2024-05-25T23%3A59%3A59Z&sr=c&sp=rl&sig=0gakAKQ6p4IrI6rQl6yFh8vd5a4GM2kOIGZojnxiZfM%3D&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kMTZ4dzNrN2R1ejNlZS5jbG91ZGZyb250Lm5ldC80ZTkwYTAxNi00NGMzLTQzNjAtOTIyMS0xNDhjNDRmZjBlZmUvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcxNjY4MTU5OX19fV19&Key-Pair-Id=KMU76EBP5WD92&Signature=YnsGpQov96A4vhtbSi6-Xaz7y4fIdTW9Jzu2Hb3gvUW8noS3J8DUGu7A1N--oI3itXkSk-wM~5xUPh-4QEYE8q5vS40UMiOp5HJIUFl0~jDKVDtTak9GSQgA~rKnU1hsFTzia5BmbuWq5OUr2~XET2h1Q8dImceCXzAgxUYYD47PnO8s163vWH6QUpB5e13AdXyHtx9fS6iCWSCf7R-pn-iWUsGNfeEtYSik~RMecBSIP~mcMPDLQ0gFlfoEPNed-ifSwgCWlPhpCa0-YzBCa7JyhA61bWBZeVltnEJpgVjdOzBUZE3ffxwtTVstE1eySLs8YwmPQoMKJuK34ETRsw__"; - const sasurl2 = "https://d16xw3k7duz3ee.cloudfront.net/4e90a016-44c3-4360-9221-148c44ff0efe/6-0.imdl?sv=2023-11-03&spr=https&se=2024-06-01T23%3A59%3A59Z&sr=c&sp=rl&sig=239RE%2BP%2F9yGEVoMKhoHx9nfFb4qUn3lmkkXc5v0P%2FH4%3D&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kMTZ4dzNrN2R1ejNlZS5jbG91ZGZyb250Lm5ldC80ZTkwYTAxNi00NGMzLTQzNjAtOTIyMS0xNDhjNDRmZjBlZmUvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcxNzI4NjM5OX19fV19&Key-Pair-Id=KMU76EBP5WD92&Signature=clm~UkYQW-c3TXOxEtcMqrKo9gAMZoLk6avegh~5xVLmrWxPKSS6jNcapdDc8m3jN6YdI21S-PfXiSKV54IwdCY0mT9dsLLQI3IrD8eVUbNMOefX3wB1jX1c7vQ6EwsVUm3r6bWlmDlHZEDGHz349WxtVxc1Gw3Zmi-qXfK8L~QYM7T8IdeiphRTkLZJMvO7HJUJ1ZfO2hZjk3YYRqqN7ZJiSjV~LjPe-cdONUZc3ZFWunKqWbvubnoroBQomAnbN7BhJnejjsWVFD~DAMEnCOChJnUZTWIHv-ZPqhPVAQuGdjDXn-VdVeDJ0QDCoLpLD2yPHbYQkDjm1~nydszk~Q__"; + const sasurl1 = + "https://d16xw3k7duz3ee.cloudfront.net/4e90a016-44c3-4360-9221-148c44ff0efe/6-0.imdl?sv=2023-11-03&spr=https&se=2024-05-25T23%3A59%3A59Z&sr=c&sp=rl&sig=0gakAKQ6p4IrI6rQl6yFh8vd5a4GM2kOIGZojnxiZfM%3D&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kMTZ4dzNrN2R1ejNlZS5jbG91ZGZyb250Lm5ldC80ZTkwYTAxNi00NGMzLTQzNjAtOTIyMS0xNDhjNDRmZjBlZmUvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcxNjY4MTU5OX19fV19&Key-Pair-Id=KMU76EBP5WD92&Signature=YnsGpQov96A4vhtbSi6-Xaz7y4fIdTW9Jzu2Hb3gvUW8noS3J8DUGu7A1N--oI3itXkSk-wM~5xUPh-4QEYE8q5vS40UMiOp5HJIUFl0~jDKVDtTak9GSQgA~rKnU1hsFTzia5BmbuWq5OUr2~XET2h1Q8dImceCXzAgxUYYD47PnO8s163vWH6QUpB5e13AdXyHtx9fS6iCWSCf7R-pn-iWUsGNfeEtYSik~RMecBSIP~mcMPDLQ0gFlfoEPNed-ifSwgCWlPhpCa0-YzBCa7JyhA61bWBZeVltnEJpgVjdOzBUZE3ffxwtTVstE1eySLs8YwmPQoMKJuK34ETRsw__"; + const sasurl2 = + "https://d16xw3k7duz3ee.cloudfront.net/4e90a016-44c3-4360-9221-148c44ff0efe/6-0.imdl?sv=2023-11-03&spr=https&se=2024-06-01T23%3A59%3A59Z&sr=c&sp=rl&sig=239RE%2BP%2F9yGEVoMKhoHx9nfFb4qUn3lmkkXc5v0P%2FH4%3D&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kMTZ4dzNrN2R1ejNlZS5jbG91ZGZyb250Lm5ldC80ZTkwYTAxNi00NGMzLTQzNjAtOTIyMS0xNDhjNDRmZjBlZmUvKiIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTcxNzI4NjM5OX19fV19&Key-Pair-Id=KMU76EBP5WD92&Signature=clm~UkYQW-c3TXOxEtcMqrKo9gAMZoLk6avegh~5xVLmrWxPKSS6jNcapdDc8m3jN6YdI21S-PfXiSKV54IwdCY0mT9dsLLQI3IrD8eVUbNMOefX3wB1jX1c7vQ6EwsVUm3r6bWlmDlHZEDGHz349WxtVxc1Gw3Zmi-qXfK8L~QYM7T8IdeiphRTkLZJMvO7HJUJ1ZfO2hZjk3YYRqqN7ZJiSjV~LjPe-cdONUZc3ZFWunKqWbvubnoroBQomAnbN7BhJnejjsWVFD~DAMEnCOChJnUZTWIHv-ZPqhPVAQuGdjDXn-VdVeDJ0QDCoLpLD2yPHbYQkDjm1~nydszk~Q__"; const url1 = new URL(sasurl1); const url2 = new URL(sasurl2); diff --git a/extensions/frontend-tiles/src/test/ModelGroup.test.ts b/extensions/frontend-tiles/src/test/ModelGroup.test.ts index c8e44cea91f6..7ea9ef3ddc3b 100644 --- a/extensions/frontend-tiles/src/test/ModelGroup.test.ts +++ b/extensions/frontend-tiles/src/test/ModelGroup.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64Set, Id64String } from "@itwin/core-bentley"; -import { ClipVector, Transform } from "@itwin/core-geometry"; import { PlanProjectionSettings, RenderSchedule, ViewFlagOverrides } from "@itwin/core-common"; -import { ModelDisplayTransform, RenderClipVolume } from "@itwin/core-frontend"; +import { ModelDisplayTransform, RenderClipVolume } from "@itwin/core-frontend"; +import { ClipVector, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { groupModels, ModelGroupingContext } from "../ModelGroup"; import { ModelGroupDisplayTransforms } from "../ModelGroupDisplayTransforms"; @@ -64,7 +64,12 @@ class GroupingContext implements ModelGroupingContext { } } -function expectGrouping(expected: Array, args: GroupingContextArgs, modelIds: Id64String[], expectedNodeIds?: Array): void { +function expectGrouping( + expected: Array, + args: GroupingContextArgs, + modelIds: Id64String[], + expectedNodeIds?: Array, +): void { const modelIdSet = new Set(modelIds); const context = new GroupingContext(args, modelIdSet); const groups = groupModels(context, modelIdSet); @@ -88,7 +93,7 @@ describe("groupModels", () => { it("groups all models together if all settings match", () => { const clip = ClipVector.createEmpty(); - const args: GroupingContextArgs = { }; + const args: GroupingContextArgs = {}; for (const modelId of ["0x1", "0x2", "0x3"]) { args[modelId] = { clip, @@ -102,7 +107,8 @@ describe("groupModels", () => { it("produces one group per unique plan projection settings", () => { expectGrouping( - [["0x1"], ["0x2"], ["0x3"], ["0x4"]], { + [["0x1"], ["0x2"], ["0x3"], ["0x4"]], + { "0x1": { projection: PlanProjectionSettings.fromJSON({ elevation: 1 }) }, "0x2": { projection: PlanProjectionSettings.fromJSON({ elevation: 2 }) }, "0x3": { projection: PlanProjectionSettings.fromJSON({ elevation: 3 }) }, @@ -111,7 +117,8 @@ describe("groupModels", () => { ); expectGrouping( - [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], { + [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], + { "0x1": { projection: PlanProjectionSettings.fromJSON({ elevation: 1 }) }, "0x2": { projection: PlanProjectionSettings.fromJSON({ elevation: 2 }) }, "0x3": { projection: PlanProjectionSettings.fromJSON({ elevation: 1 }) }, @@ -123,9 +130,10 @@ describe("groupModels", () => { it("groups plan projection models that resolve to the same elevation", () => { expectGrouping( - [["0x1"], ["0x2", "0x3"], ["0x4", "0x5"]], { - "0x1": { projection: PlanProjectionSettings.fromJSON({ overlay: true, elevation: 1 })}, - "0x2": { projection: PlanProjectionSettings.fromJSON({ overlay: true, elevation: 2 })}, + [["0x1"], ["0x2", "0x3"], ["0x4", "0x5"]], + { + "0x1": { projection: PlanProjectionSettings.fromJSON({ overlay: true, elevation: 1 }) }, + "0x2": { projection: PlanProjectionSettings.fromJSON({ overlay: true, elevation: 2 }) }, "0x3": { projection: PlanProjectionSettings.fromJSON({ overlay: true }), elevation: 2 }, "0x4": { projection: PlanProjectionSettings.fromJSON({ overlay: true }), elevation: 4 }, "0x5": { projection: PlanProjectionSettings.fromJSON({ overlay: true, elevation: 4 }), elevation: 1 }, @@ -136,7 +144,8 @@ describe("groupModels", () => { it("produces one group per unique display transform", () => { expectGrouping( - [["0x1"], ["0x2"], ["0x3"], ["0x4"]], { + [["0x1"], ["0x2"], ["0x3"], ["0x4"]], + { "0x1": { transform: { transform: Transform.createTranslationXYZ(1) } }, "0x2": { transform: { transform: Transform.createTranslationXYZ(2) } }, "0x3": { transform: { transform: Transform.createTranslationXYZ(3) } }, @@ -145,7 +154,8 @@ describe("groupModels", () => { ); expectGrouping( - [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], { + [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], + { "0x1": { transform: { transform: Transform.createTranslationXYZ(1) } }, "0x2": { transform: { transform: Transform.createTranslationXYZ(2) } }, "0x3": { transform: { transform: Transform.createTranslationXYZ(1) } }, @@ -162,7 +172,8 @@ describe("groupModels", () => { const c3 = ClipVector.createEmpty(); expectGrouping( - [["0x1"], ["0x2"], ["0x3"], ["0x4"]], { + [["0x1"], ["0x2"], ["0x3"], ["0x4"]], + { "0x1": { clip: c1 }, "0x2": { clip: c2 }, "0x3": { clip: c3 }, @@ -171,7 +182,8 @@ describe("groupModels", () => { ); expectGrouping( - [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], { + [["0x1", "0x3"], ["0x2", "0x4"], ["0x5"]], + { "0x1": { clip: c1 }, "0x2": { clip: c2 }, "0x3": { clip: c1 }, @@ -217,27 +229,47 @@ describe("groupModels", () => { }); it("produces a single-model group for every model that has a timeline", () => { - expectGrouping([["0x1"]], { - "0x1": { nodeIds: [1, 2, 3, 4] }, - }, ["0x1"], [[1, 2, 3, 4]]); - - expectGrouping([["0x1"], ["0x2"]], { - "0x1": { nodeIds: [1, 2] }, - "0x2": { nodeIds: [3, 4] }, - }, ["0x1", "0x2"], [[1, 2], [3, 4]]); - - expectGrouping([["0x1", "0x3"], ["0x2"]], { - "0x1": { }, - "0x2": { nodeIds: [3, 4]}, - "0x3": { }, - }, ["0x1", "0x2", "0x3"], [undefined, [3, 4]]); - - expectGrouping([["0x1"], ["0x2"], ["0x3", "0x4"], ["0x5"]], { - "0x1": { nodeIds: [1, 2]}, - "0x2": { nodeIds: [3, 4]}, - "0x3": { }, - "0x4": { }, - "0x5": { transform: { transform: Transform.createTranslationXYZ(5) } }, - }, ["0x1", "0x2", "0x3", "0x4", "0x5"], [[1, 2], [3, 4], undefined, undefined]); + expectGrouping( + [["0x1"]], + { + "0x1": { nodeIds: [1, 2, 3, 4] }, + }, + ["0x1"], + [[1, 2, 3, 4]], + ); + + expectGrouping( + [["0x1"], ["0x2"]], + { + "0x1": { nodeIds: [1, 2] }, + "0x2": { nodeIds: [3, 4] }, + }, + ["0x1", "0x2"], + [[1, 2], [3, 4]], + ); + + expectGrouping( + [["0x1", "0x3"], ["0x2"]], + { + "0x1": {}, + "0x2": { nodeIds: [3, 4] }, + "0x3": {}, + }, + ["0x1", "0x2", "0x3"], + [undefined, [3, 4]], + ); + + expectGrouping( + [["0x1"], ["0x2"], ["0x3", "0x4"], ["0x5"]], + { + "0x1": { nodeIds: [1, 2] }, + "0x2": { nodeIds: [3, 4] }, + "0x3": {}, + "0x4": {}, + "0x5": { transform: { transform: Transform.createTranslationXYZ(5) } }, + }, + ["0x1", "0x2", "0x3", "0x4", "0x5"], + [[1, 2], [3, 4], undefined, undefined], + ); }); }); diff --git a/extensions/frontend-tiles/src/test/ModelGroupDisplayTransforms.test.ts b/extensions/frontend-tiles/src/test/ModelGroupDisplayTransforms.test.ts index 54ce589565e0..29b87688e405 100644 --- a/extensions/frontend-tiles/src/test/ModelGroupDisplayTransforms.test.ts +++ b/extensions/frontend-tiles/src/test/ModelGroupDisplayTransforms.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ModelDisplayTransform, ModelDisplayTransformProvider } from "@itwin/core-frontend"; -import { ModelGroupDisplayTransforms } from "../ModelGroupDisplayTransforms"; import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import { ModelGroupDisplayTransforms } from "../ModelGroupDisplayTransforms"; describe("ModelGroupDisplayTransforms", () => { it("detects whether groupings have changed", () => { @@ -33,7 +33,7 @@ describe("ModelGroupDisplayTransforms", () => { expect(update(undefined)).to.be.false; expect(update(createProvider([]))).to.be.false; - let provider = createProvider([ createTransform("0x1", 1) ]); + let provider = createProvider([createTransform("0x1", 1)]); expect(update(provider)).to.be.true; expect(update(provider)).to.be.false; expect(update(undefined)).to.be.true; diff --git a/extensions/frontend-tiles/src/test/utils/webpack-config.js b/extensions/frontend-tiles/src/test/utils/webpack-config.js index dade3dd49a3d..3f3bf581909b 100644 --- a/extensions/frontend-tiles/src/test/utils/webpack-config.js +++ b/extensions/frontend-tiles/src/test/utils/webpack-config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -27,23 +27,23 @@ function createConfig(shouldInstrument) { // requires for fs that cause it to fail even though the fs dependency // is not used. /draco_decoder_nodejs.js$/, - /draco_encoder_nodejs.js$/ + /draco_encoder_nodejs.js$/, ], rules: [ { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" + use: "null-loader", }, - ] + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, externals: { electron: "commonjs electron", @@ -57,8 +57,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -83,6 +83,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] - + createConfig(true), +]; diff --git a/extensions/frontend-tiles/tsconfig.json b/extensions/frontend-tiles/tsconfig.json index 67be9deac4ee..baa950b82605 100644 --- a/extensions/frontend-tiles/tsconfig.json +++ b/extensions/frontend-tiles/tsconfig.json @@ -3,4 +3,4 @@ "compilerOptions": { "outDir": "./lib" } -} \ No newline at end of file +} diff --git a/extensions/map-layers-auth/eslint.config.js b/extensions/map-layers-auth/eslint.config.js index 628f1d4b27a0..849e7479dee5 100644 --- a/extensions/map-layers-auth/eslint.config.js +++ b/extensions/map-layers-auth/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/extensions/map-layers-auth/src/ArcGis/ArcGisAccessClient.ts b/extensions/map-layers-auth/src/ArcGis/ArcGisAccessClient.ts index 7bf00cca01ec..2879e2b1e40e 100644 --- a/extensions/map-layers-auth/src/ArcGis/ArcGisAccessClient.ts +++ b/extensions/map-layers-auth/src/ArcGis/ArcGisAccessClient.ts @@ -8,8 +8,8 @@ import { assert, BeEvent } from "@itwin/core-bentley"; import { MapLayerAccessClient, MapLayerAccessToken, MapLayerAccessTokenParams, MapLayerTokenEndpoint } from "@itwin/core-frontend"; -import { ArcGisOAuth2Token, ArcGisTokenClientType } from "./ArcGisTokenGenerator"; import { ArcGisOAuth2Endpoint, ArcGisOAuth2EndpointType } from "./ArcGisOAuth2Endpoint"; +import { ArcGisOAuth2Token, ArcGisTokenClientType } from "./ArcGisTokenGenerator"; import { ArcGisTokenManager } from "./ArcGisTokenManager"; import { ArcGisUrl } from "./ArcGisUrl"; @@ -36,7 +36,7 @@ export interface ArcGisOAuthClientIds { * ArcGIS OAuth configurations parameters. * See https://developers.arcgis.com/documentation/mapping-apis-and-services/security/arcgis-identity/serverless-web-apps/ * more details. -*/ + */ export interface ArcGisOAuthConfig { /* URL to which a user is sent once they complete sign in authorization. Must match a URI you define in the developer dashboard, otherwise, the authorization will be rejected. @@ -101,16 +101,14 @@ export class ArcGisAccessClient implements MapLayerAccessClient { const state = JSON.parse(stateStr); stateData = state?.customData; endpointOrigin = state?.endpointOrigin; - } catch { } const expiresIn = Number(expiresInStr); - const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time) + const expiresAt = (expiresIn * 1000) + (+new Date()); // Converts the token expiration delay (seconds) into a timestamp (UNIX time) if (endpointOrigin !== undefined) { ArcGisTokenManager.setOAuth2Token(endpointOrigin, { token, expiresAt, ssl, userName, persist }); eventSuccess = true; } - } } this.onOAuthProcessEnd.raiseEvent(eventSuccess, stateData); @@ -142,7 +140,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { /** @internal */ public static async validateOAuth2Endpoint(endpointUrl: string): Promise { const data = await fetch(endpointUrl, { method: "GET" }); - return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters + return data.status === 400; // Oauth2 API returns 400 (Bad Request) when there are missing parameters } public async getTokenServiceEndPoint(mapLayerUrl: string): Promise { @@ -211,7 +209,6 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } public setEnterpriseClientId(serviceBaseUrl: string, clientId: string) { - if (this._clientIds?.enterpriseClientIds) { const foundIdx = this._clientIds.enterpriseClientIds.findIndex((entry) => entry.serviceBaseUrl === serviceBaseUrl); if (foundIdx !== -1) { @@ -228,11 +225,9 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } public removeEnterpriseClientId(clientId: ArcGisEnterpriseClientId) { - if (this._clientIds?.enterpriseClientIds) { this._clientIds.enterpriseClientIds = this._clientIds?.enterpriseClientIds?.filter((item) => item.serviceBaseUrl !== clientId.serviceBaseUrl); } - } /// ////////// @@ -244,7 +239,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { const oauthEndpointUrl = new URL(oauthEndpoint.getUrl()); return ArcGisTokenManager.getOAuth2Token(oauthEndpointUrl.origin); } - } catch { } + } catch {} return undefined; } @@ -255,19 +250,23 @@ export class ArcGisAccessClient implements MapLayerAccessClient { private _endPointsCache = new Map(); /** - * Get OAuth2 endpoint that must be cause to get the Oauth2 token - * @internal - */ + * Get OAuth2 endpoint that must be cause to get the Oauth2 token + * @internal + */ private cacheEndpoint(url: MapLayerUrl, endpointType: ArcGisOAuth2EndpointType, endPoint: ArcGisOAuth2Endpoint) { - const entry = endpointType === ArcGisOAuth2EndpointType.Authorize ? {authorizeEndpoint: endPoint} : {tokenEndpoint: endPoint}; + const entry = endpointType === ArcGisOAuth2EndpointType.Authorize ? { authorizeEndpoint: endPoint } : { tokenEndpoint: endPoint }; this._endPointsCache.set(url, entry); } /** - * Get OAuth2 endpoint that must be cause to get the Oauth2 token - * @internal - */ - private async createEndpoint(mapLayerUrl: MapLayerUrl, oauthEndpointUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise { + * Get OAuth2 endpoint that must be cause to get the Oauth2 token + * @internal + */ + private async createEndpoint( + mapLayerUrl: MapLayerUrl, + oauthEndpointUrl: string, + endpointType: ArcGisOAuth2EndpointType, + ): Promise { // Validate the URL we just composed const oauthEndpoint = new ArcGisOAuth2Endpoint(oauthEndpointUrl, this.constructLoginUrl(oauthEndpointUrl, false), false); this.cacheEndpoint(mapLayerUrl, endpointType, oauthEndpoint); @@ -275,9 +274,9 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } /** - * Returns whether the ArcGis host is valid - * @internal - */ + * Returns whether the ArcGis host is valid + * @internal + */ private isArcGisHostValid(url: URL): boolean { const allowedHosts = [ "arcgis.com", @@ -287,7 +286,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } private async validateEndpointUrl(url: string) { - let valid: boolean|undefined; + let valid: boolean | undefined; try { valid = await ArcGisAccessClient.validateOAuth2Endpoint(url.toString()); } catch { @@ -299,9 +298,9 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } /** - * Get OAuth2 endpoint that must be cause to get the Oauth2 token - * @internal - */ + * Get OAuth2 endpoint that must be cause to get the Oauth2 token + * @internal + */ private async getOAuth2Endpoint(mapLayerUrl: string, endpointType: ArcGisOAuth2EndpointType): Promise { // Return from cache if available const cachedEndpoint = this._endPointsCache.get(mapLayerUrl); @@ -309,7 +308,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { return (endpointType === ArcGisOAuth2EndpointType.Authorize ? cachedEndpoint.authorizeEndpoint : cachedEndpoint.authorizeEndpoint); } - const endpointStr = (endpointType === ArcGisOAuth2EndpointType.Authorize ? "authorize" : "token"); + const endpointStr = endpointType === ArcGisOAuth2EndpointType.Authorize ? "authorize" : "token"; const urlObj = new URL(mapLayerUrl); @@ -324,7 +323,6 @@ export class ArcGisAccessClient implements MapLayerAccessClient { const oauth2Url = `https://www.arcgis.com/sharing/rest/oauth2/${endpointStr}`; return new ArcGisOAuth2Endpoint(oauth2Url, this.constructLoginUrl(oauth2Url, true), true); } else { - // First attempt: derive the Oauth2 token URL from the 'tokenServicesUrl', exposed by the 'info request' try { const restUrlFromTokenService = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(urlObj); @@ -340,7 +338,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { // Check again the URL we just composed const isValidUrl = await this.validateEndpointUrl(newUrlObj.toString()); - if (isValidUrl === undefined || isValidUrl ) { + if (isValidUrl === undefined || isValidUrl) { const endpoint = await this.createEndpoint(mapLayerUrl, newUrlObj.toString(), endpointType); if (endpoint) return endpoint; @@ -349,7 +347,7 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } else { const oauthEndpointUrl = `${restUrlFromTokenService.toString()}oauth2/${endpointStr}`; const isValidUrl = await this.validateEndpointUrl(oauthEndpointUrl); - if (isValidUrl === undefined || isValidUrl ) { + if (isValidUrl === undefined || isValidUrl) { const endpoint = await this.createEndpoint(mapLayerUrl, oauthEndpointUrl, endpointType); if (endpoint) return endpoint; @@ -360,15 +358,15 @@ export class ArcGisAccessClient implements MapLayerAccessClient { } // If we reach here, we were not successful creating an endpoint - this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests. + this._endPointsCache.set(mapLayerUrl, {}); // Cache an empty entry, and avoid making repeated failing requests. - return undefined; // we could not find any valid oauth2 endpoint + return undefined; // we could not find any valid oauth2 endpoint } /** - * Construct the complete Authorize url to starts the Oauth process - * @internal - */ + * Construct the complete Authorize url to starts the Oauth process + * @internal + */ private constructLoginUrl(url: string, isArcgisOnline: boolean) { const urlObj = new URL(url); @@ -379,7 +377,6 @@ export class ArcGisAccessClient implements MapLayerAccessClient { if (clientId !== undefined) { urlObj.searchParams.set("client_id", clientId); } - } else { const clientId = this.getMatchingEnterpriseClientId(url); assert(clientId !== undefined); @@ -398,5 +395,4 @@ export class ArcGisAccessClient implements MapLayerAccessClient { return urlObj.toString(); } - } diff --git a/extensions/map-layers-auth/src/ArcGis/ArcGisOAuth2Endpoint.ts b/extensions/map-layers-auth/src/ArcGis/ArcGisOAuth2Endpoint.ts index 2ce8ccc2424e..cee969b06594 100644 --- a/extensions/map-layers-auth/src/ArcGis/ArcGisOAuth2Endpoint.ts +++ b/extensions/map-layers-auth/src/ArcGis/ArcGisOAuth2Endpoint.ts @@ -5,7 +5,10 @@ import { MapLayerTokenEndpoint } from "@itwin/core-frontend"; /** @internal */ -export enum ArcGisOAuth2EndpointType {Authorize,Token} +export enum ArcGisOAuth2EndpointType { + Authorize, + Token, +} /** @internal */ export class ArcGisOAuth2Endpoint implements MapLayerTokenEndpoint { @@ -34,15 +37,14 @@ export class ArcGisOAuth2Endpoint implements MapLayerTokenEndpoint { const urlObj = new URL(this._loginUrl); const data = { - endpointOrigin: new URL(this._url).origin, // arcGisOAuth2Callback depends on this - customData: stateData, // caller's data + endpointOrigin: new URL(this._url).origin, // arcGisOAuth2Callback depends on this + customData: stateData, // caller's data }; let stateStr; try { stateStr = JSON.stringify(data); } catch { - } if (stateStr !== undefined) { urlObj.searchParams.set("state", stateStr); @@ -51,6 +53,7 @@ export class ArcGisOAuth2Endpoint implements MapLayerTokenEndpoint { return urlObj.toString(); } - public get isArcgisOnline() {return this._isArcgisOnline;} - + public get isArcgisOnline() { + return this._isArcgisOnline; + } } diff --git a/extensions/map-layers-auth/src/ArcGis/ArcGisTokenGenerator.ts b/extensions/map-layers-auth/src/ArcGis/ArcGisTokenGenerator.ts index 0e1b9646f8be..d4cb54d47119 100644 --- a/extensions/map-layers-auth/src/ArcGis/ArcGisTokenGenerator.ts +++ b/extensions/map-layers-auth/src/ArcGis/ArcGisTokenGenerator.ts @@ -10,7 +10,6 @@ import { MapLayerAccessToken } from "@itwin/core-frontend"; /** @internal */ export interface ArcGisOAuth2Token extends MapLayerAccessToken { - // The expiration time of the token in milliseconds (UNIX time) expiresAt: number; @@ -43,7 +42,6 @@ export enum ArcGisTokenClientType { /** @internal */ export interface ArcGisGenerateTokenOptions { - // The client type that will be granted access to the token. // Users will be able to specify whether the token will be generated for a client application's base URL, // a user-specified IP address, or the IP address that is making the request. @@ -66,7 +64,7 @@ export interface ArcGisGenerateTokenOptions { // Requests for tokens larger than this time will be rejected. // Applications are responsible for renewing expired tokens; // expired tokens will be rejected by the server on subsequent requests that use the token. - expiration?: number; // in minutes, defaults to 60 minutes + expiration?: number; // in minutes, defaults to 60 minutes } /** @internal */ @@ -132,7 +130,7 @@ export class ArcGisTokenGenerator { if (options.client === ArcGisTokenClientType.referer) { let refererStr = ""; if (options.referer === undefined) { - refererStr = encodeURIComponent(location.origin); // default to application origin + refererStr = encodeURIComponent(location.origin); // default to application origin } else { refererStr = encodeURIComponent(options.referer); } @@ -156,7 +154,6 @@ export class ArcGisTokenGenerator { // Check a token was really generated (an error could be part of the body) token = await response.json(); - } catch (_error) { } return token; diff --git a/extensions/map-layers-auth/src/ArcGis/ArcGisTokenManager.ts b/extensions/map-layers-auth/src/ArcGis/ArcGisTokenManager.ts index f1e9edb10ba3..3a7398876295 100644 --- a/extensions/map-layers-auth/src/ArcGis/ArcGisTokenManager.ts +++ b/extensions/map-layers-auth/src/ArcGis/ArcGisTokenManager.ts @@ -16,13 +16,18 @@ interface ArcGisTokenProps { /** @internal */ export class ArcGisTokenManager { - private static readonly tokenExpiryThreshold = 300000; // 5 minutes in milliseconds + private static readonly tokenExpiryThreshold = 300000; // 5 minutes in milliseconds private static _cache = new Map(); private static _oauth2Cache: Map | undefined; private static _generator: ArcGisTokenGenerator | undefined; private static readonly _browserStorageKey = "arcGisOAuth"; - public static async getToken(arcGisRestServiceUrl: string, userName: string, password: string, options: ArcGisGenerateTokenOptions): Promise { + public static async getToken( + arcGisRestServiceUrl: string, + userName: string, + password: string, + options: ArcGisGenerateTokenOptions, + ): Promise { if (!ArcGisTokenManager._generator) ArcGisTokenManager._generator = new ArcGisTokenGenerator(); @@ -48,7 +53,6 @@ export class ArcGisTokenManager { } public static invalidateToken(token: MapLayerAccessToken): boolean { - for (const [key, value] of ArcGisTokenManager._cache) { if (value.token === token.token) return ArcGisTokenManager._cache.delete(key); @@ -75,10 +79,9 @@ export class ArcGisTokenManager { } public static invalidateOAuth2Token(token: MapLayerAccessToken) { - if (ArcGisTokenManager._oauth2Cache) { for (const [key, value] of ArcGisTokenManager._oauth2Cache) { - if (value.token === token.token){ + if (value.token === token.token) { const deleted = ArcGisTokenManager._oauth2Cache.delete(key); ArcGisTokenManager.saveToBrowserStorage(); return deleted; @@ -90,10 +93,8 @@ export class ArcGisTokenManager { } public static setOAuth2Token(key: string, token: ArcGisOAuth2Token) { - if (ArcGisTokenManager._oauth2Cache === undefined) { ArcGisTokenManager._oauth2Cache = new Map(); - } ArcGisTokenManager._oauth2Cache.set(key, token); @@ -121,7 +122,6 @@ export class ArcGisTokenManager { } public static saveToBrowserStorage() { - if (ArcGisTokenManager._oauth2Cache === undefined) { return; } @@ -140,5 +140,4 @@ export class ArcGisTokenManager { window.sessionStorage.setItem(this._browserStorageKey, JSON.stringify(sessionTokens)); window.localStorage.setItem(this._browserStorageKey, JSON.stringify(storageTokens)); } - } diff --git a/extensions/map-layers-auth/src/ArcGis/ArcGisUrl.ts b/extensions/map-layers-auth/src/ArcGis/ArcGisUrl.ts index 12a8c1f99832..2ec4178dd20a 100644 --- a/extensions/map-layers-auth/src/ArcGis/ArcGisUrl.ts +++ b/extensions/map-layers-auth/src/ArcGis/ArcGisUrl.ts @@ -4,14 +4,12 @@ *--------------------------------------------------------------------------------------------*/ /** @internal */ export class ArcGisUrl { - // Extract the sub-url up to '/rest/' public static extractRestBaseUrl(url: URL): URL | undefined { const urlStr = url.toString(); const searchStr = "/rest/"; const restPos = urlStr.indexOf(searchStr); return (restPos === -1 ? undefined : new URL(urlStr.substring(0, restPos + searchStr.length))); - } public static async getRestUrlFromGenerateTokenUrl(url: URL): Promise { @@ -28,7 +26,6 @@ export class ArcGisUrl { try { json = await ArcGisUrl.fetchJson(infoUrl); } catch { - } const tokenServicesUrl = json?.authInfo?.tokenServicesUrl; diff --git a/extensions/map-layers-auth/src/test/ArcGisAccessClient.test.ts b/extensions/map-layers-auth/src/test/ArcGisAccessClient.test.ts index 42b7fc441de0..10582fd0104c 100644 --- a/extensions/map-layers-auth/src/test/ArcGisAccessClient.test.ts +++ b/extensions/map-layers-auth/src/test/ArcGisAccessClient.test.ts @@ -5,9 +5,9 @@ import { expect } from "chai"; +import fetchMock from "fetch-mock"; import * as sinon from "sinon"; import { ArcGisAccessClient, ArcGisOAuth2Endpoint, ArcGisUrl } from "../map-layers-auth"; -import fetchMock from "fetch-mock"; describe("ArcGisUtilities tests", () => { const sandbox = sinon.createSandbox(); @@ -26,12 +26,11 @@ describe("ArcGisUtilities tests", () => { }, }); - fetchMock.mock("*", { + fetchMock.mock("*", { status: 400, - headers: {"Content-Type": "application/json"}, + headers: { "Content-Type": "application/json" }, body: {}, }); - }); afterEach(async () => { @@ -49,7 +48,6 @@ describe("ArcGisUtilities tests", () => { const sampleOnlineAuthorize1 = "https://www.arcgis.com/sharing/rest/oauth2/authorize"; it("should find the matching enterprise client id ", async () => { - let clientId = (fakeAccessClient as any)!.getMatchingEnterpriseClientId(sampleOnPremiseHostName); expect(clientId).to.not.undefined; expect(clientId === fakeAccessClient?.arcGisEnterpriseClientIds![0].clientId); @@ -62,10 +60,8 @@ describe("ArcGisUtilities tests", () => { fakeAccessClient?.setEnterpriseClientId("", "dummy_clientId1"); clientId = (fakeAccessClient as any).getMatchingEnterpriseClientId("https://yyz.com"); expect(clientId === undefined); - }); it("should construct the proper login Url from a enterprise token url", async () => { - const loginURl = (fakeAccessClient as any).constructLoginUrl(sampleOnPremiseMapServerAuthorizeUrl, false); const refLoginUrl = new URL(sampleOnPremiseMapServerAuthorizeUrl); @@ -77,7 +73,6 @@ describe("ArcGisUtilities tests", () => { }); it("should construct the proper login Url from arcgis online token url", async () => { - const loginURl = (fakeAccessClient as any).constructLoginUrl(sampleOnlineAuthorize1, true); const refLoginUrl = new URL(sampleOnlineAuthorize1); @@ -89,7 +84,6 @@ describe("ArcGisUtilities tests", () => { }); it("should build proper OAuth2 enterprise endpoint URL using generateTokenUrl", async () => { - sandbox.stub(ArcGisUrl, "getRestUrlFromGenerateTokenUrl").callsFake(async function _(_url: URL) { return Promise.resolve(new URL(sampleOnPremiseMapServerRestUrl)); }); @@ -105,14 +99,15 @@ describe("ArcGisUtilities tests", () => { expect(acOnPremiseEndpoint).to.not.undefined; expect(acOnPremiseEndpoint?.isArcgisOnline).to.false; expect(acOnPremiseEndpoint?.getUrl()).to.equals(sampleOnPremiseMapServerAuthorizeUrl); - }); it("should only allow URLs with valid host", async () => { const validUrl = new URL("https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyTransportationImprovementProject/MapServer"); expect((fakeAccessClient as any).isArcGisHostValid(validUrl)).to.true; - const invalidUrl = new URL("https://services7.randomurl.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyTransportationImprovementProject/MapServer"); + const invalidUrl = new URL( + "https://services7.randomurl.com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyTransportationImprovementProject/MapServer", + ); expect((fakeAccessClient as any).isArcGisHostValid(invalidUrl)).to.false; const capitalUrl = new URL("https://services7.ArcGis.Com/nZ2Vb4CUwdo9AIiQ/arcgis/rest/services/PhillyTransportationImprovementProject/MapServer"); @@ -120,7 +115,6 @@ describe("ArcGisUtilities tests", () => { }); it("should build proper OAuth2 enterprise endpoint URL if no generateTokenUrl response", async () => { - sandbox.stub(ArcGisUrl, "getRestUrlFromGenerateTokenUrl").callsFake(async function _(_url: URL) { return Promise.resolve(undefined); }); @@ -133,7 +127,5 @@ describe("ArcGisUtilities tests", () => { expect(acOnPremiseEndpoint).to.not.undefined; expect(acOnPremiseEndpoint?.isArcgisOnline).to.false; expect(acOnPremiseEndpoint?.getUrl()).to.equals(sampleOnPremiseMapServerFallbackAuthorizeUrl); - }); - }); diff --git a/extensions/map-layers-auth/src/test/ArcGisTokenGenerator.test.ts b/extensions/map-layers-auth/src/test/ArcGisTokenGenerator.test.ts index 2248ba9a7b0f..b21edae39c04 100644 --- a/extensions/map-layers-auth/src/test/ArcGisTokenGenerator.test.ts +++ b/extensions/map-layers-auth/src/test/ArcGisTokenGenerator.test.ts @@ -18,12 +18,15 @@ describe("ArcGisTokenGenerator", () => { }); it("should make proper info request and extract tokenServicesUrl from response", async () => { - const fetchStub = sandbox.stub(global, "fetch").callsFake(async function (_input, _init) { - - return Promise.resolve((({ - status: 200, - json: async () => {return {authInfo: {isTokenBasedSecurity: true, tokenServicesUrl: sampleGenerateTokenUrl}};}, - } as unknown) as Response)); + const fetchStub = sandbox.stub(global, "fetch").callsFake(async function(_input, _init) { + return Promise.resolve( + ({ + status: 200, + json: async () => { + return { authInfo: { isTokenBasedSecurity: true, tokenServicesUrl: sampleGenerateTokenUrl } }; + }, + } as unknown) as Response, + ); }); const tokenServiceUrl = await ArcGisTokenGenerator.fetchTokenServiceUrl(sampleServiceUrl); @@ -31,6 +34,5 @@ describe("ArcGisTokenGenerator", () => { expect(fetchStub.getCalls()[0].args[0]).to.be.equals(`${sampleBaseRestUrl}info?f=pjson`); expect(sampleGenerateTokenUrl).to.be.equals(tokenServiceUrl); - }); }); diff --git a/extensions/map-layers-auth/src/test/ArcGisUrl.test.ts b/extensions/map-layers-auth/src/test/ArcGisUrl.test.ts index eabc1502c116..e97101a62ef1 100644 --- a/extensions/map-layers-auth/src/test/ArcGisUrl.test.ts +++ b/extensions/map-layers-auth/src/test/ArcGisUrl.test.ts @@ -30,7 +30,6 @@ describe("ArcGisUrl", () => { const sampleUrl3 = new URL("https://dtlgeoarcgis.adtl.com/server/"); const extractedBaseUrl3 = ArcGisUrl.extractRestBaseUrl(sampleUrl3); chai.assert.isTrue(extractedBaseUrl3 === undefined); - }); it("should extract RestUrl From GenerateToken Url", async () => { @@ -44,7 +43,6 @@ describe("ArcGisUrl", () => { try { restUrl = await ArcGisUrl.getRestUrlFromGenerateTokenUrl(new URL(sampleRestUrl)); } catch { - } // The returned URL should match @@ -56,5 +54,4 @@ describe("ArcGisUrl", () => { const urlArg = fetchJsonStub.getCalls()[0].args[0] as URL; chai.expect(urlArg?.toString()).to.equals(`${sampleRestUrl}info?f=json`); }); - }); diff --git a/extensions/map-layers-formats/eslint.config.js b/extensions/map-layers-formats/eslint.config.js index 628f1d4b27a0..849e7479dee5 100644 --- a/extensions/map-layers-formats/eslint.config.js +++ b/extensions/map-layers-formats/eslint.config.js @@ -7,4 +7,4 @@ module.exports = [ ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureFormat.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureFormat.ts index 862e2f08f189..df85730f0e60 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureFormat.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureFormat.ts @@ -3,34 +3,48 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { ImageMapLayerSettings } from "@itwin/core-common"; -import { ArcGisUtilities, ImageryMapLayerFormat, MapLayerImageryProvider, MapLayerSource, MapLayerSourceStatus, MapLayerSourceValidation, ValidateSourceArgs } from "@itwin/core-frontend"; +import { + ArcGisUtilities, + ImageryMapLayerFormat, + MapLayerImageryProvider, + MapLayerSource, + MapLayerSourceStatus, + MapLayerSourceValidation, + ValidateSourceArgs, +} from "@itwin/core-frontend"; import { ArcGisFeatureProvider } from "./ArcGisFeatureProvider"; /** @internal */ export class ArcGisFeatureMapLayerFormat extends ImageryMapLayerFormat { public static override formatId = "ArcGISFeature"; - public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { return new ArcGisFeatureProvider(settings); } - public static override async validateSource(url: string, userName?: string, password?: string, ignoreCache?: boolean): Promise { + public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { + return new ArcGisFeatureProvider(settings); + } + public static override async validateSource( + url: string, + userName?: string, + password?: string, + ignoreCache?: boolean, + ): Promise { const urlValidation = ArcGisUtilities.validateUrl(url, "FeatureServer"); if (urlValidation !== MapLayerSourceStatus.Valid) return { status: urlValidation }; - const source = MapLayerSource.fromJSON({name: "", url, formatId: this.formatId}); + const source = MapLayerSource.fromJSON({ name: "", url, formatId: this.formatId }); if (!source) - return {status: MapLayerSourceStatus.InvalidFormat}; + return { status: MapLayerSourceStatus.InvalidFormat }; source.userName = userName; source.password = password; - return ArcGisUtilities.validateSource({source, capabilitiesFilter: ["query"], ignoreCache}); + return ArcGisUtilities.validateSource({ source, capabilitiesFilter: ["query"], ignoreCache }); } public static override async validate(args: ValidateSourceArgs): Promise { - const urlValidation = ArcGisUtilities.validateUrl(args.source.url, "FeatureServer"); if (urlValidation !== MapLayerSourceStatus.Valid) - return {status: urlValidation}; + return { status: urlValidation }; // Some Map service supporting only tiles don't include the 'Map' capabilities, thus we can't make it mandatory. - return ArcGisUtilities.validateSource({...args, capabilitiesFilter: ["query"]}); + return ArcGisUtilities.validateSource({ ...args, capabilitiesFilter: ["query"] }); } } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureProvider.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureProvider.ts index 10cdf81f3a5c..a79cd5904198 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureProvider.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureProvider.ts @@ -3,39 +3,61 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Cartographic, ImageMapLayerSettings, ImageSource, ImageSourceFormat, ServerError } from "@itwin/core-common"; import { base64StringToUint8Array, IModelStatus, Logger } from "@itwin/core-bentley"; +import { Cartographic, ImageMapLayerSettings, ImageSource, ImageSourceFormat, ServerError } from "@itwin/core-common"; +import { + ArcGisErrorCode, + ArcGISImageryProvider, + ArcGISServiceMetadata, + ArcGisUtilities, + FeatureGraphicsRenderer, + HitDetail, + ImageryMapTileTree, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapLayerImageryProviderStatus, + QuadId, + setRequestTimeout, +} from "@itwin/core-frontend"; import { Matrix4d, Point3d, Range2d, Transform } from "@itwin/core-geometry"; -import { ArcGisErrorCode, ArcGISImageryProvider, ArcGISServiceMetadata, ArcGisUtilities, FeatureGraphicsRenderer, HitDetail, ImageryMapTileTree, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProviderStatus, QuadId, setRequestTimeout } from "@itwin/core-frontend"; -import { ArcGisExtent, ArcGisFeatureFormat, ArcGisFeatureQuery, ArcGisFeatureResultType, ArcGisGeometry, FeatureQueryQuantizationParams } from "./ArcGisFeatureQuery"; -import { ArcGisPbfFeatureReader } from "./ArcGisPbfFeatureReader"; -import { ArcGisJsonFeatureReader } from "./ArcGisJsonFeatureReader"; -import { ArcGisFeatureResponse, ArcGisResponseData } from "./ArcGisFeatureResponse"; +import { + ArcGisExtent, + ArcGisFeatureFormat, + ArcGisFeatureQuery, + ArcGisFeatureResultType, + ArcGisGeometry, + FeatureQueryQuantizationParams, +} from "./ArcGisFeatureQuery"; import { ArcGisFeatureReader } from "./ArcGisFeatureReader"; +import { ArcGisFeatureResponse, ArcGisResponseData } from "./ArcGisFeatureResponse"; +import { ArcGisJsonFeatureReader } from "./ArcGisJsonFeatureReader"; +import { ArcGisPbfFeatureReader } from "./ArcGisPbfFeatureReader"; -import { EsriPMS, EsriRenderer, EsriSFS, EsriSLS, EsriSLSProps, EsriSymbol } from "./EsriSymbology"; -import { FeatureDefaultSymbology } from "../Feature/FeatureSymbology"; import { FeatureCanvasRenderer } from "../Feature/FeatureCanvasRenderer"; +import { FeatureDefaultSymbology } from "../Feature/FeatureSymbology"; import { ArcGisSymbologyCanvasRenderer } from "./ArcGisSymbologyRenderer"; +import { EsriPMS, EsriRenderer, EsriSFS, EsriSLS, EsriSLSProps, EsriSymbol } from "./EsriSymbology"; const loggerCategory = "MapLayersFormats.ArcGISFeature"; /** -* @internal -*/ + * @internal + */ interface ArcGisFeatureUrl { url: string; - envelope?: ArcGisExtent; // envelope representing the current computed URL, required to refine request. + envelope?: ArcGisExtent; // envelope representing the current computed URL, required to refine request. } /** -* @internal -*/ + * @internal + */ export class DefaultArcGiSymbology implements FeatureDefaultSymbology { - public static readonly defaultPMS = EsriPMS.fromJSON( { + public static readonly defaultPMS = EsriPMS.fromJSON({ type: "esriPMS", url: "", contentType: "image/png", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAmBJREFUOE+Nk01IVFEUx//n3jfvOZOaJkMtiiJ7o9RG3LgoqKhFSFJBTS1ahFBBi0ijfJXCIyQr+hBbSIsoW7iQoKKFCw2CkAI3tZAgy8Ei+xhoTCbnje/NPfHGnA816KzuPR+/c8/HJRQJE7o+VUhym0DcCOYGgBQEXjOLlyqo+nHanCkMoaL4rslKjZwOQLT4ek3Mmz3FACFNLB67ut6M1nWphbg8wI6VyJK5KEH0EQFVJRKbwzokAW++p/ErraAYSQK3u47bC3vLnA+ZB9i2gHF0oyQMCfCGNaUa+vauxs71wWz2V18cnBj8gQ8J1/eeBnHUa4sMFQDGdGno+4gwEAoQzjVUon3rqlx1KY9x7+0MWobjAPg3QJ2eZV4tAEyFNCN5FkSXyw2B3j1hRGvLcgBXMV5MptA4MOXr0gT0u5bZnAf0jBsyiSgJPAxqhON1K3FlRxUMvwFAtv7u0Wl0jvwEmJNEuOhakTt5wKEBifr6Oo14BIBRpgt07w6jcVMIngKGY7NofR5HwlF+zDcpsC193vyYB/innvHywCzdZfAR/+onX1segBTAxHzzfPE7/8yzzIPLjJE1LTixHZx5CtCK4gXLzovBiDPUsYxVM7gUkB3nWKlm6DYEnQGzXARxCOK+a1WfKtQXb6LNAvr7iCboCUA1Ocdsdv5KLPe7F6pH/w3wLbc+BwOuc5IZ1wEE/jonQbjptZn24tKKX7BgvR2r0NKZRwDvAqCI+Z30VJPTURv7P4A9psuQcYAUPwAoReBLrmX2Lmls7i8sZ7kWLwuoxA1FVJGxzMPLufi6P2r+2xFbOUjGAAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAmBJREFUOE+Nk01IVFEUx//n3jfvOZOaJkMtiiJ7o9RG3LgoqKhFSFJBTS1ahFBBi0ijfJXCIyQr+hBbSIsoW7iQoKKFCw2CkAI3tZAgy8Ei+xhoTCbnje/NPfHGnA816KzuPR+/c8/HJRQJE7o+VUhym0DcCOYGgBQEXjOLlyqo+nHanCkMoaL4rslKjZwOQLT4ek3Mmz3FACFNLB67ut6M1nWphbg8wI6VyJK5KEH0EQFVJRKbwzokAW++p/ErraAYSQK3u47bC3vLnA+ZB9i2gHF0oyQMCfCGNaUa+vauxs71wWz2V18cnBj8gQ8J1/eeBnHUa4sMFQDGdGno+4gwEAoQzjVUon3rqlx1KY9x7+0MWobjAPg3QJ2eZV4tAEyFNCN5FkSXyw2B3j1hRGvLcgBXMV5MptA4MOXr0gT0u5bZnAf0jBsyiSgJPAxqhON1K3FlRxUMvwFAtv7u0Wl0jvwEmJNEuOhakTt5wKEBifr6Oo14BIBRpgt07w6jcVMIngKGY7NofR5HwlF+zDcpsC193vyYB/innvHywCzdZfAR/+onX1segBTAxHzzfPE7/8yzzIPLjJE1LTixHZx5CtCK4gXLzovBiDPUsYxVM7gUkB3nWKlm6DYEnQGzXARxCOK+a1WfKtQXb6LNAvr7iCboCUA1Ocdsdv5KLPe7F6pH/w3wLbc+BwOuc5IZ1wEE/jonQbjptZn24tKKX7BgvR2r0NKZRwDvAqCI+Z30VJPTURv7P4A9psuQcYAUPwAoReBLrmX2Lmls7i8sZ7kWLwuoxA1FVJGxzMPLufi6P2r+2xFbOUjGAAAAAElFTkSuQmCC", width: 16, height: 16, xoffset: -8, @@ -52,7 +74,7 @@ export class DefaultArcGiSymbology implements FeatureDefaultSymbology { public static readonly defaultSFS = EsriSFS.fromJSON({ type: "esriSFS", - color: [0, 0, 255, 100], // blue fill + color: [0, 0, 255, 100], // blue fill style: "esriSFSSolid", outline: this.defaultSLSProps, }); @@ -76,8 +98,8 @@ export class DefaultArcGiSymbology implements FeatureDefaultSymbology { } /** Provide tiles from a ESRI ArcGIS Feature service -* @internal -*/ + * @internal + */ export class ArcGisFeatureProvider extends ArcGISImageryProvider { // Debug flags, should always be committed to FALSE ! private _drawDebugInfo = false; @@ -94,14 +116,18 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { private _minDepthFromLod = 0; private _defaultSymbol = new DefaultArcGiSymbology(); - private _renderer: EsriRenderer|undefined; - private _symbologyRenderer: ArcGisSymbologyCanvasRenderer|undefined; + private _renderer: EsriRenderer | undefined; + private _symbologyRenderer: ArcGisSymbologyCanvasRenderer | undefined; - private static readonly _nbSubTiles = 2; // Number of subtiles for a single axis + private static readonly _nbSubTiles = 2; // Number of subtiles for a single axis public serviceJson: any; - public override get minimumZoomLevel(): number { return this._minDepthFromLod; } - public override get maximumZoomLevel(): number { return this._maxDepthFromLod; } + public override get minimumZoomLevel(): number { + return this._minDepthFromLod; + } + public override get maximumZoomLevel(): number { + return this._maxDepthFromLod; + } private static _extentCache = new Map(); @@ -118,7 +144,8 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { throw new ServerError(IModelStatus.ValidationFailed, ""); } - if (json?.error?.code === ArcGisErrorCode.TokenRequired + if ( + json?.error?.code === ArcGisErrorCode.TokenRequired || json?.error?.code === ArcGisErrorCode.InvalidToken || json?.error?.code === ArcGisErrorCode.MissingPermissions ) { @@ -154,7 +181,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { // Check layer metadata if (Array.isArray(this.serviceJson.layers) && this.serviceJson.layers.length >= 1) { - const hasDefaultVisibility = Object.keys(this.serviceJson.layers[0]).includes("defaultVisibility"); if (hasDefaultVisibility) { for (const layer of this.serviceJson.layers) { @@ -178,7 +204,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } } } - } else { // There is no layer to publish? Something is off with this server.. throw new ServerError(IModelStatus.ValidationFailed, ""); @@ -187,7 +212,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { // Make sure we cache layer info (i.e. rendering info) if (!this._layerMetadata) { - this._layerMetadata = await this.getLayerMetadata(this._layerId); if (!this._layerMetadata) { Logger.logError(loggerCategory, "Could not layer metadata"); @@ -251,14 +275,14 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } // Check for minScale / max scale - const minScale = this._layerMetadata?.minScale || undefined; // undefined, 0 -> undefined - const maxScale = this._layerMetadata?.maxScale || undefined; // undefined, 0 -> undefined + const minScale = this._layerMetadata?.minScale || undefined; // undefined, 0 -> undefined + const maxScale = this._layerMetadata?.maxScale || undefined; // undefined, 0 -> undefined const scales = ArcGisUtilities.getZoomLevelsScales(this.defaultMaximumZoomLevel, this.tileSize, minScale, maxScale, 1.0); if (scales.minLod) this._minDepthFromLod = scales.minLod; // Some servers advertises a max LOD of 0, it should be interpreted as 'not defined' (otherwise a max lod of 0 would would mean never display anything) - this._maxDepthFromLod = (scales.maxLod ? scales.maxLod : this.defaultMaximumZoomLevel); + this._maxDepthFromLod = scales.maxLod ? scales.maxLod : this.defaultMaximumZoomLevel; try { this._renderer = EsriRenderer.fromJSON(this._layerMetadata?.drawingInfo?.renderer); @@ -317,29 +341,48 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { const url = new URL(this._settings.url); url.pathname = `${url.pathname}/${layerId}`; metadata = await ArcGisUtilities.getServiceJson({ - url: url.toString(), formatId: this._settings.formatId, - userName: this._settings.userName, password: this._settings.password, - queryParams: this._settings.collectQueryParams(), requireToken: this._accessTokenRequired}); + url: url.toString(), + formatId: this._settings.formatId, + userName: this._settings.userName, + password: this._settings.password, + queryParams: this._settings.collectQueryParams(), + requireToken: this._accessTokenRequired, + }); } catch { - } return metadata?.content; } - public override get tileSize(): number { return 512; } - public get format(): ArcGisFeatureFormat | undefined { return this._format; } + public override get tileSize(): number { + return 512; + } + public get format(): ArcGisFeatureFormat | undefined { + return this._format; + } // We don't use this method inside this provider (see constructFeatureUrl), but since this is an abstract method, we need to define something public async constructUrl(_row: number, _column: number, _zoomLevel: number): Promise { return ""; } - public constructFeatureUrl(row: number, column: number, zoomLevel: number, format: ArcGisFeatureFormat, resultType: ArcGisFeatureResultType, geomOverride?: ArcGisGeometry, outFields?: string, tolerance?: number, returnGeometry?: boolean, maxAllowableOffset?: number): ArcGisFeatureUrl | undefined { - + public constructFeatureUrl( + row: number, + column: number, + zoomLevel: number, + format: ArcGisFeatureFormat, + resultType: ArcGisFeatureResultType, + geomOverride?: ArcGisGeometry, + outFields?: string, + tolerance?: number, + returnGeometry?: boolean, + maxAllowableOffset?: number, + ): ArcGisFeatureUrl | undefined { const tileExtent = this.getEPSG3857Extent(row, column, zoomLevel); const tileEnvelope = { - xmin: tileExtent.left, ymin: tileExtent.bottom, - xmax: tileExtent.right, ymax: tileExtent.top, + xmin: tileExtent.left, + ymin: tileExtent.bottom, + xmax: tileExtent.right, + ymax: tileExtent.top, spatialReference: { wkid: 102100, latestWkid: 3857 }, }; @@ -373,14 +416,15 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { geometry, geometryType: "esriGeometryEnvelope", returnExceededLimitFeatures: false, - maxRecordCountFactor: 3, // This was grabbed from the ESRI web viewer request, not sure where this factor come from + maxRecordCountFactor: 3, // This was grabbed from the ESRI web viewer request, not sure where this factor come from resultType, quantizationParameters, outFields, returnGeometry, distance: (tolerance ? tolerance * toleranceWorld : undefined), maxAllowableOffset, - }); + }, + ); let envelope: ArcGisExtent | undefined; if (geomOverride && geomOverride.type === "esriGeometryEnvelope") { @@ -390,11 +434,17 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } return { url: url.toString(), envelope }; - } // Makes an identify request to ESRI MapService , and return it as a list MapLayerFeatureInfo object - public override async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree, hit: HitDetail, options?: MapFeatureInfoOptions): Promise { + public override async getFeatureInfo( + featureInfos: MapLayerFeatureInfo[], + quadId: QuadId, + carto: Cartographic, + _tree: ImageryMapTileTree, + hit: HitDetail, + options?: MapFeatureInfoOptions, + ): Promise { if (!this._querySupported || this.format === undefined) return; @@ -411,14 +461,27 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { const queryEnvelope: ArcGisGeometry = { type: "esriGeometryEnvelope", geom: { - xmin: epsg3857X - toleranceWorld, ymin: epsg3857Y - toleranceWorld, - xmax: epsg3857X + toleranceWorld, ymax: epsg3857Y + toleranceWorld, + xmin: epsg3857X - toleranceWorld, + ymin: epsg3857Y - toleranceWorld, + xmax: epsg3857X + toleranceWorld, + ymax: epsg3857Y + toleranceWorld, spatialReference: { wkid: 102100, latestWkid: 3857 }, - }}; + }, + }; const doFeatureInfoQuery = async (format: ArcGisFeatureFormat, outFields?: string, returnGeometry?: boolean) => { - const infoUrl = this.constructFeatureUrl(quadId.row, quadId.column, quadId.level, format, "standard", queryEnvelope, - outFields, undefined, returnGeometry, tilePixelSize); + const infoUrl = this.constructFeatureUrl( + quadId.row, + quadId.column, + quadId.level, + format, + "standard", + queryEnvelope, + outFields, + undefined, + returnGeometry, + tilePixelSize, + ); if (!infoUrl || infoUrl.url.length === 0) { Logger.logError(loggerCategory, `Could not construct feature info query URL`); @@ -462,9 +525,8 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { const featureReader = new ArcGisJsonFeatureReader(this._settings, this._layerMetadata); - const renderer = new FeatureGraphicsRenderer({viewport: hit.viewport, crs: "webMercator"}); + const renderer = new FeatureGraphicsRenderer({ viewport: hit.viewport, crs: "webMercator" }); await featureReader.readFeatureInfo(responseData, featureInfos, renderer); - } catch (e) { Logger.logError(loggerCategory, `Exception occurred while loading feature info data : ${e}`); return; @@ -478,7 +540,7 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { return undefined; } - const geomOverride: ArcGisGeometry | undefined = (refineEnvelope ? { geom: refineEnvelope, type: "esriGeometryEnvelope" } : undefined); + const geomOverride: ArcGisGeometry | undefined = refineEnvelope ? { geom: refineEnvelope, type: "esriGeometryEnvelope" } : undefined; const fields = this._renderer?.fields; const outFields = fields ? fields.join(",") : undefined; const tileUrl = this.constructFeatureUrl(row, column, zoomLevel, this.format, "tile", geomOverride, outFields); @@ -502,7 +564,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { // Compute transform that provides coordinates in the canvas coordinate system (pixels, origin = top-left) // from coordinate in world (i.e EPSG:3857) protected computeTileWorld2CanvasTransform(row: number, column: number, zoomLevel: number) { - const tileExtentWorld3857 = this.getEPSG3857Extent(row, column, zoomLevel); const worldTileWidth = tileExtentWorld3857.right - tileExtentWorld3857.left; const canvasTileWidth = this.tileSize; @@ -516,7 +577,7 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { const xTranslate = -1 * canvasTileOriginOffset.x; // Canvas origin is uppler left corner, so we need to flip the y axsis - const yTranslate = canvasTileExtentOffset.y; // y-axis flip + const yTranslate = canvasTileExtentOffset.y; // y-axis flip const yWorld2CanvasRatio = -1 * world2CanvasRatio; // y-axis flip const matrix = Matrix4d.createTranslationAndScaleXYZ(xTranslate, yTranslate, 0, world2CanvasRatio, yWorld2CanvasRatio, 1); @@ -524,7 +585,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } public override async loadTile(row: number, column: number, zoomLevel: number): Promise { - if ((this.status === MapLayerImageryProviderStatus.RequireAuth)) { return undefined; } @@ -539,7 +599,6 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } try { - // Compute transform if CoordinatesQuantization is not supported by service let transfo: Transform | undefined; if (!this._supportsCoordinatesQuantization) { @@ -556,7 +615,9 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { } const renderer = new FeatureCanvasRenderer(ctx, this._symbologyRenderer, transfo); - const featureReader: ArcGisFeatureReader = this.format === "PBF" ? new ArcGisPbfFeatureReader(this._settings, this._layerMetadata) : new ArcGisJsonFeatureReader(this._settings, this._layerMetadata); + const featureReader: ArcGisFeatureReader = this.format === "PBF" + ? new ArcGisPbfFeatureReader(this._settings, this._layerMetadata) + : new ArcGisJsonFeatureReader(this._settings, this._layerMetadata); const getSubEnvelopes = (envelope: ArcGisExtent): ArcGisExtent[] => { const dx = (envelope.xmax - envelope.xmin) * 0.5; @@ -565,8 +626,10 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { for (let posX = 0; posX < ArcGisFeatureProvider._nbSubTiles; posX++) { for (let posY = 0; posY < ArcGisFeatureProvider._nbSubTiles; posY++) { subEnvelopes.push({ - xmin: envelope.xmin + (dx * posX), ymin: envelope.ymin + (dy * posY), - xmax: envelope.xmin + (dx * (posX + 1)), ymax: envelope.ymin + (dy * (posY + 1)), + xmin: envelope.xmin + (dx * posX), + ymin: envelope.ymin + (dy * posY), + xmax: envelope.xmin + (dx * (posX + 1)), + ymax: envelope.ymin + (dy * (posY + 1)), spatialReference: { wkid: 102100, latestWkid: 3857 }, }); } @@ -632,6 +695,4 @@ export class ArcGisFeatureProvider extends ArcGISImageryProvider { return undefined; } - } - diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureQuery.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureQuery.ts index f897126d8f44..0664713462e3 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureQuery.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureQuery.ts @@ -8,29 +8,37 @@ export type ArcGisFeatureResultType = "none" | "standard" | "tile"; /** @internal */ export type ArcGisFeatureGeometryType = - "esriGeometryNull" - | "esriGeometryPoint" - | "esriGeometryMultipoint" - | "esriGeometryLine" - | "esriGeometryCircularArc" - | "esriGeometryEllipticArc" - | "esriGeometryBezier3Curve" - | "esriGeometryPath" - | "esriGeometryPolyline" - | "esriGeometryRing" - | "esriGeometryPolygon" - | "esriGeometryEnvelope" - | "esriGeometryAny" - | "esriGeometryBag" - | "esriGeometryMultiPatch" - | "esriGeometryTriangleStrip" - | "esriGeometryTriangeFan" - | "esriGeometryRay" - | "esriGeometrySphere" - | "esriGeometryTriangles"; + | "esriGeometryNull" + | "esriGeometryPoint" + | "esriGeometryMultipoint" + | "esriGeometryLine" + | "esriGeometryCircularArc" + | "esriGeometryEllipticArc" + | "esriGeometryBezier3Curve" + | "esriGeometryPath" + | "esriGeometryPolyline" + | "esriGeometryRing" + | "esriGeometryPolygon" + | "esriGeometryEnvelope" + | "esriGeometryAny" + | "esriGeometryBag" + | "esriGeometryMultiPatch" + | "esriGeometryTriangleStrip" + | "esriGeometryTriangeFan" + | "esriGeometryRay" + | "esriGeometrySphere" + | "esriGeometryTriangles"; /** @internal */ -export type ArcGisFeatureSpatialRel = "esriSpatialRelIntersects" | "esriSpatialRelContains" | "esriSpatialRelCrosses" | "esriSpatialRelEnvelopeIntersects" | "esriSpatialRelIndexIntersects" | "esriSpatialRelOverlaps" | "esriSpatialRelTouches" | "esriSpatialRelWithin"; +export type ArcGisFeatureSpatialRel = + | "esriSpatialRelIntersects" + | "esriSpatialRelContains" + | "esriSpatialRelCrosses" + | "esriSpatialRelEnvelopeIntersects" + | "esriSpatialRelIndexIntersects" + | "esriSpatialRelOverlaps" + | "esriSpatialRelTouches" + | "esriSpatialRelWithin"; /** @internal */ export interface ArcGisGeometry { @@ -75,13 +83,12 @@ export type ArcGisFeatureFormat = "JSON" | "PBF"; // https://developers.arcgis.com/rest/services-reference/query-feature-service-layer-.htm /** @internal */ export interface ArcGisFeatureQueryParams { - /** This option can be used for fetching query results up to the resultRecordCount specified. * When resultOffset is specified but this parameter is not, the map service defaults it to maxRecordCount. * The maximum value for this parameter is the value of the layer's maxRecordCount property. * The minimum value entered for this parameter cannot be below 1. * This parameter only applies if supportsPagination is true. - * */ + */ resultRecordCount?: number; /** This option can be used for fetching query results up to the resultRecordCount specified. @@ -89,7 +96,7 @@ export interface ArcGisFeatureQueryParams { * The maximum value for this parameter is the value of the layer's maxRecordCount property. * The minimum value entered for this parameter cannot be below 1. * This parameter only applies if supportsPagination is true. - * */ + */ resultOffset?: number; /** If true, the result includes the geometry associated with each feature returned. */ @@ -104,16 +111,16 @@ export interface ArcGisFeatureQueryParams { /** Maximum Allowable Offset means the map distance ( usually per pixel) within which two points are considered identical. * It is used to generalize thus reduce the number of points -* */ + */ maxAllowableOffset?: number; /** The list of fields to be included in the returned result set. This list is a comma-delimited list of field names. * You can also specify the wildcard "*" as the value of this parameter. - * */ + */ outFields?: string; /** The buffer distance for the input geometries. - * */ + */ distance?: number; } @@ -160,7 +167,6 @@ export class ArcGisFeatureQuery { this.distance = params.distance; this.maxAllowableOffset = params.maxAllowableOffset; } - } public toString() { @@ -168,46 +174,45 @@ export class ArcGisFeatureQuery { url.searchParams.append("f", this.format); - if ( this.resultRecordCount !== undefined) { + if (this.resultRecordCount !== undefined) { url.searchParams.append("resultRecordCount", `${this.resultRecordCount}`); } - if ( this.resultOffset !== undefined) { - url.searchParams.append( "resultOffset", `${this.resultOffset}`); + if (this.resultOffset !== undefined) { + url.searchParams.append("resultOffset", `${this.resultOffset}`); } - if ( this.returnGeometry !== undefined) { - url.searchParams.append("returnGeometry", this.returnGeometry?"true":"false"); + if (this.returnGeometry !== undefined) { + url.searchParams.append("returnGeometry", this.returnGeometry ? "true" : "false"); } - if ( this.resultType !== undefined) { + if (this.resultType !== undefined) { url.searchParams.append("resultType", this.resultType); } - if ( this.maxRecordCountFactor !== undefined) { - url.searchParams.append( "maxRecordCountFactor", `${this.maxRecordCountFactor}`); + if (this.maxRecordCountFactor !== undefined) { + url.searchParams.append("maxRecordCountFactor", `${this.maxRecordCountFactor}`); } - if ( this.returnExceededLimitFeatures !== undefined) { - url.searchParams.append( "returnExceededLimitFeatures", this.returnExceededLimitFeatures?"true":"false"); + if (this.returnExceededLimitFeatures !== undefined) { + url.searchParams.append("returnExceededLimitFeatures", this.returnExceededLimitFeatures ? "true" : "false"); } - url.searchParams.append( "outSR", `${this.outSR}`); + url.searchParams.append("outSR", `${this.outSR}`); if (this.geometry || this.spatialRel) { - if (this.spatialRel) { - url.searchParams.append( "spatialRel", this.spatialRel); + url.searchParams.append("spatialRel", this.spatialRel); } if (this.geometry) { - url.searchParams.append( "geometryType", this.geometry.type); + url.searchParams.append("geometryType", this.geometry.type); const geomStr = JSON.stringify(this.geometry.geom); - url.searchParams.append( "geometry", geomStr); - url.searchParams.append( "units", "esriSRUnit_Meter"); // required on older server for get feature info + url.searchParams.append("geometry", geomStr); + url.searchParams.append("units", "esriSRUnit_Meter"); // required on older server for get feature info - url.searchParams.append( "inSR", `${this.geometry.geom.spatialReference.wkid}`); + url.searchParams.append("inSR", `${this.geometry.geom.spatialReference.wkid}`); } } else { // No custom params, fetch all geometries @@ -220,7 +225,7 @@ export class ArcGisFeatureQuery { } if (this.outFields) { - url.searchParams.append( "outFields", this.outFields); + url.searchParams.append("outFields", this.outFields); } if (this.distance) { @@ -233,5 +238,4 @@ export class ArcGisFeatureQuery { return url.toString(); } - } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureReader.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureReader.ts index fbf805905518..11d722779064 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureReader.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureReader.ts @@ -5,8 +5,8 @@ import { ImageMapLayerSettings } from "@itwin/core-common"; import { FeatureGeometryRenderer, GraphicsGeometryRenderer, MapLayerFeatureInfo } from "@itwin/core-frontend"; -import { ArcGisResponseData } from "./ArcGisFeatureResponse"; import { FeatureInfoReader } from "../Feature/FeatureInfoReader"; +import { ArcGisResponseData } from "./ArcGisFeatureResponse"; /** Interface defining minimal implementation needed to create an ArcGIS geometry reader, * needed by the [[ArcGisFeatureProvider]]. @@ -21,7 +21,6 @@ export interface ArcGisFeatureReader { * @internal */ export abstract class ArcGisBaseFeatureReader extends FeatureInfoReader implements ArcGisFeatureReader { - protected _settings: ImageMapLayerSettings; protected _layerMetadata: any; @@ -32,6 +31,9 @@ export abstract class ArcGisBaseFeatureReader extends FeatureInfoReader implemen } public abstract readAndRender(response: ArcGisResponseData, renderer: FeatureGeometryRenderer): Promise; - public abstract readFeatureInfo(response: ArcGisResponseData, featureInfos: MapLayerFeatureInfo[], renderer: GraphicsGeometryRenderer): Promise; - + public abstract readFeatureInfo( + response: ArcGisResponseData, + featureInfos: MapLayerFeatureInfo[], + renderer: GraphicsGeometryRenderer, + ): Promise; } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureResponse.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureResponse.ts index 69de07b42084..df8b7537cff7 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureResponse.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisFeatureResponse.ts @@ -14,7 +14,7 @@ export interface ArcGisResponseData { /** @internal */ export type ArcGisFieldType = - "esriFieldTypeInteger" + | "esriFieldTypeInteger" | "esriFieldTypeSmallInteger" | "esriFieldTypeDouble" | "esriFieldTypeSingle" @@ -35,17 +35,17 @@ export class ArcGisFeatureResponse { private _response: Promise; - constructor(format: ArcGisFeatureFormat, response: Promise, envelope?: ArcGisExtent) { + constructor(format: ArcGisFeatureFormat, response: Promise, envelope?: ArcGisExtent) { this.format = format; this._response = response; this.envelope = envelope; } - public async getResponseData(): Promise { + public async getResponseData(): Promise { let data: any; try { const tileResponse = await this._response; - if (tileResponse === undefined || tileResponse.status !== 200 ) + if (tileResponse === undefined || tileResponse.status !== 200) return undefined; if (this.format === "PBF") { @@ -55,17 +55,15 @@ export class ArcGisFeatureResponse { data = esriPBuffer.FeatureCollectionPBuffer.deserialize(byteArray); const collection = data as esriPBuffer.FeatureCollectionPBuffer; - return {data, exceedTransferLimit: collection?.queryResult?.featureResult?.exceededTransferLimit}; - + return { data, exceedTransferLimit: collection?.queryResult?.featureResult?.exceededTransferLimit }; } else { data = await tileResponse.json(); if (data === undefined || data == null) return undefined; - return {data, exceedTransferLimit: data.exceededTransferLimit}; + return { data, exceedTransferLimit: data.exceededTransferLimit }; } - - } catch(_e) { + } catch (_e) { return undefined; } } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisJsonFeatureReader.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisJsonFeatureReader.ts index 82449d5822f4..70d91d3bfd4b 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisJsonFeatureReader.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisJsonFeatureReader.ts @@ -5,7 +5,16 @@ import { PrimitiveValue, PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; import { ImageMapLayerSettings } from "@itwin/core-common"; -import { ArcGisGeometryReaderJSON, FeatureAttributeDrivenSymbology, FeatureGeometryRenderer, GraphicsGeometryRenderer, MapLayerFeature, MapLayerFeatureAttribute, MapLayerFeatureInfo, MapSubLayerFeatureInfo} from "@itwin/core-frontend"; +import { + ArcGisGeometryReaderJSON, + FeatureAttributeDrivenSymbology, + FeatureGeometryRenderer, + GraphicsGeometryRenderer, + MapLayerFeature, + MapLayerFeatureAttribute, + MapLayerFeatureInfo, + MapSubLayerFeatureInfo, +} from "@itwin/core-frontend"; import { Transform } from "@itwin/core-geometry"; import { ArcGisBaseFeatureReader } from "./ArcGisFeatureReader"; import { ArcGisFieldType, ArcGisResponseData } from "./ArcGisFeatureResponse"; @@ -16,14 +25,13 @@ export class ArcGisJsonFeatureReader extends ArcGisBaseFeatureReader { public constructor(settings: ImageMapLayerSettings, layerMetadata: any) { super(settings, layerMetadata); - } private applySymbologyAttributes(attrSymbology: FeatureAttributeDrivenSymbology, feature: any) { if (attrSymbology && feature) { const symbolFields = attrSymbology.rendererFields; if (symbolFields && symbolFields.length > 0 && feature.attributes) { - const featureAttr: {[key: string]: any} = {}; + const featureAttr: { [key: string]: any } = {}; for (const [attrKey, attrValue] of Object.entries(feature.attributes)) if (symbolFields.includes(attrKey)) { featureAttr[attrKey] = attrValue; @@ -80,7 +88,7 @@ export class ArcGisJsonFeatureReader extends ArcGisBaseFeatureReader { }; const getRecordInfo = (fieldName: string, value: any): MapLayerFeatureAttribute => { - const propertyValue: PrimitiveValue = {valueFormat: PropertyValueFormat.Primitive}; + const propertyValue: PrimitiveValue = { valueFormat: PropertyValueFormat.Primitive }; if (value === null) { value = undefined; @@ -111,10 +119,10 @@ export class ArcGisJsonFeatureReader extends ArcGisBaseFeatureReader { const typename = getStandardTypeName(fieldType); propertyValue.displayValue = this.getDisplayValue(typename, propertyValue.value); - return {value: propertyValue, property: { name: fieldName, displayLabel: fieldName, typename }}; + return { value: propertyValue, property: { name: fieldName, displayLabel: fieldName, typename } }; }; - let geomReader: ArcGisGeometryReaderJSON|undefined; + let geomReader: ArcGisGeometryReaderJSON | undefined; if (renderer && responseObj?.geometryType) { geomReader = new ArcGisGeometryReaderJSON(responseObj.geometryType, renderer); } @@ -128,7 +136,7 @@ export class ArcGisJsonFeatureReader extends ArcGisBaseFeatureReader { // Read all features attributes / geometries for (const responseFeature of responseObj.features) { - const feature: MapLayerFeature = {attributes: []}; + const feature: MapLayerFeature = { attributes: [] }; for (const [key, value] of Object.entries(responseFeature.attributes)) feature.attributes?.push(getRecordInfo(key, value)); @@ -137,7 +145,7 @@ export class ArcGisJsonFeatureReader extends ArcGisBaseFeatureReader { await geomReader.readGeometry(responseFeature.geometry); const graphics = renderer.moveGraphics(); feature.geometries = graphics.map((graphic) => { - return {graphic}; + return { graphic }; }); } subLayerInfo.features.push(feature); diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisPbfFeatureReader.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisPbfFeatureReader.ts index b1b18fd724ac..5429eaf5a006 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisPbfFeatureReader.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisPbfFeatureReader.ts @@ -2,14 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { esriPBuffer } from "../ArcGisFeature/esriPBuffer.gen"; -import { FeatureAttributeDrivenSymbology, FeatureGeometryRenderer, GraphicsGeometryRenderer, MapLayerFeature, MapLayerFeatureAttribute, MapLayerFeatureInfo, MapSubLayerFeatureInfo} from "@itwin/core-frontend"; import { PrimitiveValue, PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; +import { Logger } from "@itwin/core-bentley"; import { ImageMapLayerSettings } from "@itwin/core-common"; +import { + FeatureAttributeDrivenSymbology, + FeatureGeometryRenderer, + GraphicsGeometryRenderer, + MapLayerFeature, + MapLayerFeatureAttribute, + MapLayerFeatureInfo, + MapSubLayerFeatureInfo, +} from "@itwin/core-frontend"; +import { esriPBuffer } from "../ArcGisFeature/esriPBuffer.gen"; +import { ArcGisFeatureGeometryType } from "./ArcGisFeatureQuery"; import { ArcGisBaseFeatureReader } from "./ArcGisFeatureReader"; import { ArcGisResponseData } from "./ArcGisFeatureResponse"; -import { Logger } from "@itwin/core-bentley"; -import { ArcGisFeatureGeometryType } from "./ArcGisFeatureQuery"; const esriGeometryType = esriPBuffer.FeatureCollectionPBuffer.GeometryType; const loggerCategory = "MapLayersFormats.ArcGISFeature"; @@ -72,14 +80,15 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { propertyValue.value = undefined; } - return { propertyValue, typename }; + return { propertyValue, typename }; } - public getFeatureAttribute(fieldInfo: PbfFieldInfo, attrValue: esriPBuffer.FeatureCollectionPBuffer.Value): MapLayerFeatureAttribute|undefined { + public getFeatureAttribute(fieldInfo: PbfFieldInfo, attrValue: esriPBuffer.FeatureCollectionPBuffer.Value): MapLayerFeatureAttribute | undefined { let propertyValue: PrimitiveValue = { valueFormat: PropertyValueFormat.Primitive }; let typename = StandardTypeNames.String; - if (fieldInfo.type === esriPBuffer.FeatureCollectionPBuffer.FieldType.esriFieldTypeDouble + if ( + fieldInfo.type === esriPBuffer.FeatureCollectionPBuffer.FieldType.esriFieldTypeDouble || fieldInfo.type === esriPBuffer.FeatureCollectionPBuffer.FieldType.esriFieldTypeInteger || fieldInfo.type === esriPBuffer.FeatureCollectionPBuffer.FieldType.esriFieldTypeSmallInteger || fieldInfo.type === esriPBuffer.FeatureCollectionPBuffer.FieldType.esriFieldTypeOID @@ -131,7 +140,7 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { propertyValue.displayValue = this.getDisplayValue(typename, propertyValue.value); - return {value: propertyValue, property: { name: fieldInfo.name, displayLabel: fieldInfo.name, typename } }; + return { value: propertyValue, property: { name: fieldInfo.name, displayLabel: fieldInfo.name, typename } }; } public async readAndRender(response: ArcGisResponseData, renderer: FeatureGeometryRenderer) { @@ -148,17 +157,15 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { // Fields metadata is stored outside feature results, create dedicated array first const fields: PbfFieldInfo[] = []; for (const field of collection.queryResult.featureResult.fields) - fields.push({name: field.name, type:field.fieldType}); + fields.push({ name: field.name, type: field.fieldType }); const geomType = collection.queryResult.featureResult.geometryType; const stride = (collection.queryResult.featureResult.hasM || collection.queryResult.featureResult.hasZ) ? 3 : 2; const relativeCoords = renderer.transform === undefined; for (const feature of collection.queryResult.featureResult.features) { - // Render geometries if (renderer && feature?.has_geometry) { - if (renderer.hasSymbologyRenderer() && renderer.symbolRenderer.isAttributeDriven()) { // Read attributes if needed (attribute driven symbology) this.applySymbologyAttributes(renderer.symbolRenderer, feature, fields); @@ -167,20 +174,23 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { if (geomType === esriGeometryType.esriGeometryTypePoint || geomType === esriGeometryType.esriGeometryTypeMultipoint) { await renderer.renderPoint(feature.geometry.lengths, feature.geometry.coords, stride, relativeCoords); } else if (geomType === esriGeometryType.esriGeometryTypePolyline || geomType === esriGeometryType.esriGeometryTypePolygon) { - const fill = (geomType === esriGeometryType.esriGeometryTypePolygon); + const fill = geomType === esriGeometryType.esriGeometryTypePolygon; await renderer.renderPath(feature.geometry.lengths, feature.geometry.coords, fill, stride, relativeCoords); } } - } } - private applySymbologyAttributes(attrSymbology: FeatureAttributeDrivenSymbology, feature: esriPBuffer.FeatureCollectionPBuffer.Feature, fields: PbfFieldInfo[]) { + private applySymbologyAttributes( + attrSymbology: FeatureAttributeDrivenSymbology, + feature: esriPBuffer.FeatureCollectionPBuffer.Feature, + fields: PbfFieldInfo[], + ) { if (attrSymbology) { const symbolFields = attrSymbology.rendererFields; if (symbolFields && symbolFields.length > 0 && feature.attributes) { let fieldIdx = 0; - const featureAttr: {[key: string]: any} = {}; + const featureAttr: { [key: string]: any } = {}; for (const attrValue of feature.attributes) { if (fieldIdx > fields.length) { Logger.logError(loggerCategory, "Error while read feature info data: fields metadata missing"); @@ -194,7 +204,6 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { featureAttr[fieldInfo.name] = primitiveValue.value; } } - } attrSymbology.setActiveFeatureAttributes(featureAttr); } @@ -203,7 +212,6 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { public async readFeatureInfo(response: ArcGisResponseData, featureInfos: MapLayerFeatureInfo[], renderer?: GraphicsGeometryRenderer) { if (!(response.data instanceof esriPBuffer.FeatureCollectionPBuffer)) { - Logger.logError(loggerCategory, "Response was not in PBF format"); } @@ -216,7 +224,7 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { // Fields metadata is stored outside feature results, create dedicated array first const fields: PbfFieldInfo[] = []; for (const field of collection.queryResult.featureResult.fields) - fields.push({name: field.name, type:field.fieldType}); + fields.push({ name: field.name, type: field.fieldType }); const geomType = collection.queryResult.featureResult.geometryType; const stride = (collection.queryResult.featureResult.hasM || collection.queryResult.featureResult.hasZ) ? 3 : 2; @@ -229,18 +237,18 @@ export class ArcGisPbfFeatureReader extends ArcGisBaseFeatureReader { // Read feature values for (const featureResponse of collection.queryResult.featureResult.features) { - const feature: MapLayerFeature = { attributes: []}; + const feature: MapLayerFeature = { attributes: [] }; if (renderer && featureResponse?.has_geometry) { if (geomType === esriGeometryType.esriGeometryTypePoint || geomType === esriGeometryType.esriGeometryTypeMultipoint) { await renderer.renderPoint(featureResponse.geometry.lengths, featureResponse.geometry.coords, stride, true); } else if (geomType === esriGeometryType.esriGeometryTypePolyline || geomType === esriGeometryType.esriGeometryTypePolygon) { - const fill = (geomType === esriGeometryType.esriGeometryTypePolygon); + const fill = geomType === esriGeometryType.esriGeometryTypePolygon; await renderer.renderPath(featureResponse.geometry.lengths, featureResponse.geometry.coords, fill, stride, true); } const graphics = renderer.moveGraphics(); feature.geometries = graphics.map((graphic) => { - return {graphic}; + return { graphic }; }); } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisSymbologyRenderer.ts b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisSymbologyRenderer.ts index 1f1e676d139d..ad959f924137 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/ArcGisSymbologyRenderer.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/ArcGisSymbologyRenderer.ts @@ -5,14 +5,25 @@ import { Logger } from "@itwin/core-bentley"; import { ColorDef } from "@itwin/core-common"; -import { EsriClassBreaksRenderer, EsriPMS, EsriRenderer, EsriSFS, EsriSimpleRenderer, EsriSLS, EsriSLSStyle, EsriSMS, EsriSymbol, EsriUniqueValueRenderer } from "./EsriSymbology"; import { FeatureAttributeDrivenSymbology, FeatureSymbologyRenderer } from "@itwin/core-frontend"; import { Angle } from "@itwin/core-geometry"; import { FeatureDefaultSymbology } from "../Feature/FeatureSymbology"; import { ArcGisFeatureGeometryType } from "./ArcGisFeatureQuery"; +import { + EsriClassBreaksRenderer, + EsriPMS, + EsriRenderer, + EsriSFS, + EsriSimpleRenderer, + EsriSLS, + EsriSLSStyle, + EsriSMS, + EsriSymbol, + EsriUniqueValueRenderer, +} from "./EsriSymbology"; /** @internal */ -const loggerCategory = "MapLayersFormats.ArcGISFeature"; +const loggerCategory = "MapLayersFormats.ArcGISFeature"; /** @internal */ export type ArcGisSymbologyRendererType = "simple" | "attributeDriven"; @@ -28,11 +39,10 @@ export interface FeatureSymbologyCanvasRenderer extends FeatureSymbologyRenderer /** @internal */ export abstract class ArcGisSymbologyCanvasRenderer implements FeatureSymbologyCanvasRenderer { - public abstract readonly renderer?: EsriRenderer; public abstract get symbol(): EsriSymbol; - public abstract set symbol(symbol: EsriSymbol|undefined); + public abstract set symbol(symbol: EsriSymbol | undefined); public abstract get defaultSymbol(): EsriSymbol; public activeGeometryType: string = ""; public abstract isAttributeDriven(): this is FeatureAttributeDrivenSymbology; @@ -40,7 +50,11 @@ export abstract class ArcGisSymbologyCanvasRenderer implements FeatureSymbologyC public abstract applyStrokeStyle(context: CanvasRenderingContext2D): void; public abstract drawPoint(context: CanvasRenderingContext2D, ptX: number, ptY: number): void; - public static create(renderer: EsriRenderer|undefined, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType): ArcGisSymbologyCanvasRenderer { + public static create( + renderer: EsriRenderer | undefined, + defaultSymbol: FeatureDefaultSymbology, + geometryType?: ArcGisFeatureGeometryType, + ): ArcGisSymbologyCanvasRenderer { if (renderer?.type === "uniqueValue") { return new ArcGisUniqueValueSymbologyRenderer(renderer as EsriUniqueValueRenderer, defaultSymbol, geometryType); } else if (renderer?.type === "classBreaks") { @@ -68,36 +82,56 @@ export class ArcGisDashLineStyle { private static _shortDotLineLength = 1; private static _shortDotGapLength = 2; public static dashValues = { - esriSLSDash : [this._dashLineLength, this._dashGapLength], - esriSLSDashDot : [this._dashLineLength, this._dotGapLength, this._dotLineLength, this._dotGapLength], - esriSLSDashDotDot : [this._dashLongLineLength, this._dotGapLength, this._dotLineLength, this._dotGapLength, this._dotLineLength, this._dotGapLength], - esriSLSDot : [this._dashLineLength, this._dotGapLength], - esriSLSLongDash : [this._dashLongLineLength, this._dashLongGapLength], - esriSLSLongDashDot : [this._dashLongLineDotDotLength, this._dashGapLength, this._dotLineLength, this._dashGapLength], - esriSLSShortDash : [this._dashShortLineLength, this._dashShortGapLength], - esriSLSShortDashDot : [this._dashShortLineLength, this._dashShortGapLength, this._dotLineLength, this._dashShortGapLength], - esriSLSShortDashDotDot : [this._dashLineLength, this._dashShortGapLength, this._dotLineLength, this._dashGapLength, this._dotLineLength, this._dashShortGapLength], - esriSLSShortDot : [this._shortDotLineLength, this._shortDotGapLength], + esriSLSDash: [this._dashLineLength, this._dashGapLength], + esriSLSDashDot: [this._dashLineLength, this._dotGapLength, this._dotLineLength, this._dotGapLength], + esriSLSDashDotDot: [ + this._dashLongLineLength, + this._dotGapLength, + this._dotLineLength, + this._dotGapLength, + this._dotLineLength, + this._dotGapLength, + ], + esriSLSDot: [this._dashLineLength, this._dotGapLength], + esriSLSLongDash: [this._dashLongLineLength, this._dashLongGapLength], + esriSLSLongDashDot: [this._dashLongLineDotDotLength, this._dashGapLength, this._dotLineLength, this._dashGapLength], + esriSLSShortDash: [this._dashShortLineLength, this._dashShortGapLength], + esriSLSShortDashDot: [this._dashShortLineLength, this._dashShortGapLength, this._dotLineLength, this._dashShortGapLength], + esriSLSShortDashDotDot: [ + this._dashLineLength, + this._dashShortGapLength, + this._dotLineLength, + this._dashGapLength, + this._dotLineLength, + this._dashShortGapLength, + ], + esriSLSShortDot: [this._shortDotLineLength, this._shortDotGapLength], }; - } /** @internal */ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer { - - protected _symbol: EsriSymbol|undefined; + protected _symbol: EsriSymbol | undefined; protected _defaultSymbol: FeatureDefaultSymbology; - public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology {return false;} - public lineWidthScaleFactor = 2; // This is value is empirical, this might need to be adjusted + public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology { + return false; + } + public lineWidthScaleFactor = 2; // This is value is empirical, this might need to be adjusted - public get symbol(): EsriSymbol {return (this._symbol ?? this.defaultSymbol);} - public set symbol(symbol: EsriSymbol|undefined) {this._symbol = symbol;} + public get symbol(): EsriSymbol { + return (this._symbol ?? this.defaultSymbol); + } + public set symbol(symbol: EsriSymbol | undefined) { + this._symbol = symbol; + } - public get defaultSymbol() {return this._defaultSymbol.getSymbology(this.activeGeometryType) as EsriSymbol;} + public get defaultSymbol() { + return this._defaultSymbol.getSymbology(this.activeGeometryType) as EsriSymbol; + } public override readonly renderer?: EsriRenderer; - public constructor(renderer: EsriRenderer|undefined, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType) { + public constructor(renderer: EsriRenderer | undefined, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType) { super(); this._defaultSymbol = defaultSymbol; @@ -132,7 +166,7 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer if (sfs.color) { fillColor = sfs.color; } - } else if (symbol.type === "esriSMS") { + } else if (symbol.type === "esriSMS") { const sms = symbol as EsriSMS; if (sms.color) { fillColor = sms.color; @@ -170,8 +204,7 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer } if (sls) { - - context.lineWidth = (sls.width > 0 ? sls.width : 1); + context.lineWidth = sls.width > 0 ? sls.width : 1; if (symbol.type === "esriSLS") context.lineWidth *= this.lineWidthScaleFactor; if (sls.color) { @@ -183,27 +216,25 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer } else { Logger.logTrace(loggerCategory, `Could not apply stroke style`); } - } /** - * Draw a simple marker - * @param x x-axis coordinate in the destination canvas at which to place the center of the marker - * @param y y-axis coordinate in the destination canvas at which to place the center of the marker - * @param size size of the marker - * @public - */ + * Draw a simple marker + * @param x x-axis coordinate in the destination canvas at which to place the center of the marker + * @param y y-axis coordinate in the destination canvas at which to place the center of the marker + * @param size size of the marker + * @public + */ public drawSimpleMarker(context: CanvasRenderingContext2D, sms: EsriSMS, x: number, y: number, size: number) { const halfSize = sms.size * 0.5; if (sms.angle) { context.save(); - context.translate(x,y); + context.translate(x, y); const angle = Angle.createDegrees(sms.angle); context.rotate(angle.radians); - context.translate(-x,-y); + context.translate(-x, -y); } if (sms.style === "esriSMSSquare") { - const dx = x + (-0.5 * size); const dy = y + (-0.5 * size); if (sms.color) { @@ -214,10 +245,9 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer this.applyStrokeStyle(context); context.strokeRect(dx, dy, size, size); } - } else if (sms.style === "esriSMSCircle") { context.beginPath(); - context.arc(x, y, size*0.5, 0, 2*Math.PI); + context.arc(x, y, size * 0.5, 0, 2 * Math.PI); context.closePath(); if (sms.color) { this.applyFillStyle(context); @@ -229,10 +259,10 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer } } else if (sms.style === "esriSMSCross") { context.beginPath(); - context.moveTo(x-halfSize, y); - context.lineTo(x+halfSize, y); - context.moveTo(x, y-halfSize); - context.lineTo(x, y+halfSize); + context.moveTo(x - halfSize, y); + context.lineTo(x + halfSize, y); + context.moveTo(x, y - halfSize); + context.lineTo(x, y + halfSize); if (sms.outline) { this.applyStrokeStyle(context); } @@ -240,10 +270,10 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer } else if (sms.style === "esriSMSDiamond") { context.beginPath(); - context.moveTo(x, y-halfSize); - context.lineTo(x+halfSize, y); - context.lineTo(x, y+halfSize); - context.lineTo(x-halfSize, y); + context.moveTo(x, y - halfSize); + context.lineTo(x + halfSize, y); + context.lineTo(x, y + halfSize); + context.lineTo(x - halfSize, y); context.closePath(); if (sms.color) { this.applyFillStyle(context); @@ -255,9 +285,9 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer context.stroke(); } else if (sms.style === "esriSMSTriangle") { context.beginPath(); - context.moveTo(x, y-halfSize); - context.lineTo(x+halfSize, y+halfSize); - context.lineTo(x-halfSize, y+halfSize); + context.moveTo(x, y - halfSize); + context.lineTo(x + halfSize, y + halfSize); + context.lineTo(x - halfSize, y + halfSize); context.closePath(); if (sms.color) { @@ -268,12 +298,12 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer this.applyStrokeStyle(context); } context.stroke(); - } else if(sms.style === "esriSMSX") { + } else if (sms.style === "esriSMSX") { context.beginPath(); - context.moveTo(x-halfSize, y-halfSize); - context.lineTo(x+halfSize, y+halfSize); - context.moveTo(x-halfSize, y+halfSize); - context.lineTo(x+halfSize, y-halfSize); + context.moveTo(x - halfSize, y - halfSize); + context.lineTo(x + halfSize, y + halfSize); + context.moveTo(x - halfSize, y + halfSize); + context.lineTo(x + halfSize, y - halfSize); if (sms.outline) { this.applyStrokeStyle(context); } @@ -296,7 +326,7 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer // We scale up a little a bit the size of symbol. // const width = pms.width === undefined ? pms.width : pms.width * 1.25; // const height = pms.height === undefined ? pms.height : pms.height * 1.25; - const width = pms.width; + const width = pms.width; const height = pms.height; let xOffset = 0, yOffset = 0; @@ -332,7 +362,6 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer if (angleDegrees) context.restore(); - } else if (symbol.type === "esriSMS") { const sms = this.symbol as EsriSMS; @@ -352,12 +381,16 @@ export class ArcGisSimpleSymbologyRenderer extends ArcGisSymbologyCanvasRenderer /** @internal */ export class ArcGisUniqueValueSymbologyRenderer extends ArcGisSimpleSymbologyRenderer implements FeatureAttributeDrivenSymbology { - public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology {return true;} - protected _activeFeatureAttributes: {[key: string]: any} | undefined; + public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology { + return true; + } + protected _activeFeatureAttributes: { [key: string]: any } | undefined; protected uvRenderer: EsriUniqueValueRenderer; - private _defaultRenderSymbol: EsriSymbol|undefined; + private _defaultRenderSymbol: EsriSymbol | undefined; - public override get defaultSymbol() {return this._defaultRenderSymbol ?? super.defaultSymbol;} + public override get defaultSymbol() { + return this._defaultRenderSymbol ?? super.defaultSymbol; + } public get rendererFields() { if (this.uvRenderer.field1) @@ -366,10 +399,10 @@ export class ArcGisUniqueValueSymbologyRenderer extends ArcGisSimpleSymbologyRen return undefined; } - public constructor(renderer: EsriUniqueValueRenderer, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType) { + public constructor(renderer: EsriUniqueValueRenderer, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType) { super(renderer, defaultSymbol, geometryType); - this.uvRenderer = (this.renderer as EsriUniqueValueRenderer); + this.uvRenderer = this.renderer as EsriUniqueValueRenderer; this._defaultRenderSymbol = this.uvRenderer.defaultSymbol; } @@ -379,15 +412,14 @@ export class ArcGisUniqueValueSymbologyRenderer extends ArcGisSimpleSymbologyRen let newSymbolApplied = false; if (this._activeFeatureAttributes) { if (this.uvRenderer.field1 && Object.keys(this._activeFeatureAttributes).includes(this.uvRenderer.field1)) { - const queryValue = this._activeFeatureAttributes[this.uvRenderer.field1]; if (queryValue !== null && queryValue !== undefined) { for (const uvi of this.uvRenderer.uniqueValueInfos) { - // Strangely, ArcGIS documentation says 'value' is a string, - // not too sure if a comparison on other types is possible, or its always forced to string properties? - if (uvi.value === queryValue.toString()) { - this.symbol = uvi.symbol ; + // Strangely, ArcGIS documentation says 'value' is a string, + // not too sure if a comparison on other types is possible, or its always forced to string properties? + if (uvi.value === queryValue.toString()) { + this.symbol = uvi.symbol; newSymbolApplied = true; break; } @@ -405,12 +437,16 @@ export class ArcGisUniqueValueSymbologyRenderer extends ArcGisSimpleSymbologyRen /** @internal */ export class ArcGisClassBreaksSymbologyRenderer extends ArcGisSimpleSymbologyRenderer implements FeatureAttributeDrivenSymbology { - public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology {return true;} - protected _activeFeatureAttributes: {[key: string]: any} | undefined; + public override isAttributeDriven(): this is FeatureAttributeDrivenSymbology { + return true; + } + protected _activeFeatureAttributes: { [key: string]: any } | undefined; protected cbRenderer: EsriClassBreaksRenderer; - private _defaultRenderSymbol: EsriSymbol|undefined; + private _defaultRenderSymbol: EsriSymbol | undefined; - public override get defaultSymbol() {return this._defaultRenderSymbol ?? super.defaultSymbol;} + public override get defaultSymbol() { + return this._defaultRenderSymbol ?? super.defaultSymbol; + } public get rendererFields() { if (this.cbRenderer) @@ -422,7 +458,7 @@ export class ArcGisClassBreaksSymbologyRenderer extends ArcGisSimpleSymbologyRen public constructor(renderer: EsriClassBreaksRenderer, defaultSymbol: FeatureDefaultSymbology, geometryType?: ArcGisFeatureGeometryType) { super(renderer, defaultSymbol, geometryType); - this.cbRenderer = (this.renderer as EsriClassBreaksRenderer); + this.cbRenderer = this.renderer as EsriClassBreaksRenderer; this._defaultRenderSymbol = this.cbRenderer.defaultSymbol; } @@ -432,24 +468,25 @@ export class ArcGisClassBreaksSymbologyRenderer extends ArcGisSimpleSymbologyRen const newSymbolApplied = false; if (this._activeFeatureAttributes) { if (Object.keys(this._activeFeatureAttributes).includes(this.cbRenderer.field)) { - const queryValue = this._activeFeatureAttributes[this.cbRenderer.field]; if (queryValue !== null && queryValue !== undefined) { - let currentMinValue: number|undefined; + let currentMinValue: number | undefined; let currentClassIdx = 0; do { const currentClass = this.cbRenderer.classBreakInfos[currentClassIdx]; if (currentClass.classMinValue !== undefined) { currentMinValue = currentClass.classMinValue; } else if (currentClass.classMinValue === undefined && currentClassIdx > 0) { - currentMinValue = this.cbRenderer.classBreakInfos[currentClassIdx-1].classMaxValue; + currentMinValue = this.cbRenderer.classBreakInfos[currentClassIdx - 1].classMaxValue; } else { currentMinValue = this.cbRenderer.minValue; } - if ( queryValue >= currentMinValue - && queryValue <= currentClass.classMaxValue) { + if ( + queryValue >= currentMinValue + && queryValue <= currentClass.classMaxValue + ) { this.symbol = currentClass.symbol; return; } diff --git a/extensions/map-layers-formats/src/ArcGisFeature/EsriSymbology.ts b/extensions/map-layers-formats/src/ArcGisFeature/EsriSymbology.ts index c01e04855b1a..d670b2cb3756 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/EsriSymbology.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/EsriSymbology.ts @@ -30,26 +30,37 @@ export interface EsriSymbolCommonProps { export type EsriSymbolProps = EsriSLSProps | EsriPMSProps | EsriSFSProps | EsriSMSProps; /** @internal */ -export abstract class EsriSymbol extends FeatureSymbology implements EsriSymbolCommonProps { - public readonly abstract type: EsriSymbolPropsType; +export abstract class EsriSymbol extends FeatureSymbology implements EsriSymbolCommonProps { + public abstract readonly type: EsriSymbolPropsType; public static fromJSON(props: EsriSymbolProps) { if (props.type === "esriSFS") { - return EsriSFS.fromJSON(props ); + return EsriSFS.fromJSON(props); } else if (props.type === "esriSLS") { - return EsriSLS.fromJSON(props ); + return EsriSLS.fromJSON(props); } else if (props.type === "esriPMS") { - return EsriPMS.fromJSON(props ); + return EsriPMS.fromJSON(props); } else if (props.type === "esriSMS") { - return EsriSMS.fromJSON(props ); + return EsriSMS.fromJSON(props); } throw new Error(`Unknown ESRI symbology type}`); } } /** @internal */ -export type EsriSLSStyle = "esriSLSDash" | "esriSLSDashDot" | "esriSLSDashDotDot" | "esriSLSDot" | "esriSLSLongDash" | "esriSLSLongDashDot" | -"esriSLSNull" | "esriSLSShortDash" | "esriSLSShortDashDot" | "esriSLSShortDashDotDot" | "esriSLSShortDot" | "esriSLSSolid"; +export type EsriSLSStyle = + | "esriSLSDash" + | "esriSLSDashDot" + | "esriSLSDashDotDot" + | "esriSLSDot" + | "esriSLSLongDash" + | "esriSLSLongDashDot" + | "esriSLSNull" + | "esriSLSShortDash" + | "esriSLSShortDashDot" + | "esriSLSShortDashDotDot" + | "esriSLSShortDot" + | "esriSLSSolid"; /** @internal */ export interface EsriSLSProps extends EsriSymbolCommonProps { @@ -63,10 +74,18 @@ export interface EsriSLSProps extends EsriSymbolCommonProps { export class EsriSLS implements EsriSymbolCommonProps { public readonly props: EsriSLSProps; - public get color() { return colorFromArray(this.props.color); } - public get type() { return this.props.type; } - public get width() { return this.props.width; } - public get style() { return this.props.style; } + public get color() { + return colorFromArray(this.props.color); + } + public get type() { + return this.props.type; + } + public get width() { + return this.props.width; + } + public get style() { + return this.props.style; + } constructor(json: EsriSLSProps) { this.props = json; @@ -93,22 +112,42 @@ export interface EsriPMSProps extends EsriSymbolCommonProps { /** @internal */ export class EsriPMS implements EsriSymbolCommonProps { public readonly props: EsriPMSProps; - private _image: HTMLImageElement|undefined; + private _image: HTMLImageElement | undefined; - public get type() { return this.props.type; } - public get url() { return this.props.url; } - public get imageData() { return this.props.imageData; } - public get imageUrl() { return `data:${this.contentType};base64,${this.imageData}`; } + public get type() { + return this.props.type; + } + public get url() { + return this.props.url; + } + public get imageData() { + return this.props.imageData; + } + public get imageUrl() { + return `data:${this.contentType};base64,${this.imageData}`; + } public get image() { assert(this._image !== undefined); return this._image; } - public get contentType() { return this.props.contentType; } - public get width() { return this.props.width; } - public get height() { return this.props.height; } - public get xoffset() { return this.props.xoffset; } - public get yoffset() { return this.props.yoffset; } - public get angle() { return this.props.angle; } + public get contentType() { + return this.props.contentType; + } + public get width() { + return this.props.width; + } + public get height() { + return this.props.height; + } + public get xoffset() { + return this.props.xoffset; + } + public get yoffset() { + return this.props.yoffset; + } + public get angle() { + return this.props.angle; + } public async loadImage() { if (this._image === undefined) { @@ -154,14 +193,30 @@ export interface EsriSMSProps extends EsriSymbolCommonProps { export class EsriSMS implements EsriSymbolCommonProps { public readonly props: EsriSMSProps; private _outline: EsriSLS | undefined; - public get angle() { return this.props.angle; } - public get color() { return colorFromArray(this.props.color); } - public get outline() { return this._outline; } - public get size() { return this.props.size; } - public get style() { return this.props.style; } - public get type() { return this.props.type; } - public get xoffset() { return this.props.xoffset; } - public get yoffset() { return this.props.yoffset; } + public get angle() { + return this.props.angle; + } + public get color() { + return colorFromArray(this.props.color); + } + public get outline() { + return this._outline; + } + public get size() { + return this.props.size; + } + public get style() { + return this.props.style; + } + public get type() { + return this.props.type; + } + public get xoffset() { + return this.props.xoffset; + } + public get yoffset() { + return this.props.yoffset; + } private constructor(json: EsriSMSProps) { this.props = json; @@ -175,7 +230,15 @@ export class EsriSMS implements EsriSymbolCommonProps { } /** @internal */ -export type EsriSFSStyleProps = "esriSFSBackwardDiagonal" | "esriSFSCross" | "esriSFSDiagonalCross" | "esriSFSForwardDiagonal" | "esriSFSHorizontal" | "esriSFSNull" | "esriSFSSolid" | "esriSFSVertical"; +export type EsriSFSStyleProps = + | "esriSFSBackwardDiagonal" + | "esriSFSCross" + | "esriSFSDiagonalCross" + | "esriSFSForwardDiagonal" + | "esriSFSHorizontal" + | "esriSFSNull" + | "esriSFSSolid" + | "esriSFSVertical"; /** @internal */ export interface EsriSFSProps extends EsriSymbolCommonProps { @@ -190,10 +253,18 @@ export class EsriSFS implements EsriSymbolCommonProps { public readonly props: EsriSFSProps; private _outline: EsriSLS | undefined; - public get color() { return colorFromArray(this.props.color); } - public get type() { return this.props.type; } - public get style() { return this.props.style; } - public get outline() { return this._outline; } + public get color() { + return colorFromArray(this.props.color); + } + public get type() { + return this.props.type; + } + public get style() { + return this.props.style; + } + public get outline() { + return this._outline; + } constructor(json: EsriSFSProps) { this.props = json; if (json.outline) @@ -214,11 +285,10 @@ export interface EsriUniqueValueInfoProps { } /** @internal */ -export class EsriUniqueValueInfo { - +export class EsriUniqueValueInfo { public readonly value: string; - public readonly label: string|undefined; - public readonly description: string|undefined; + public readonly label: string | undefined; + public readonly description: string | undefined; public readonly symbol: EsriSymbol; private constructor(json: EsriUniqueValueInfoProps) { @@ -243,12 +313,11 @@ export interface EsriClassBreaksInfoProps { } /** @internal */ -export class EsriClassBreaksValueInfo { - +export class EsriClassBreaksValueInfo { public readonly classMaxValue: number; public readonly classMinValue?: number; - public readonly label: string|undefined; - public readonly description: string|undefined; + public readonly label: string | undefined; + public readonly description: string | undefined; public readonly symbol: EsriSymbol; private constructor(json: EsriClassBreaksInfoProps) { @@ -284,7 +353,13 @@ export interface EsriUniqueValueRendererProps extends EsriRendererBaseProps { } /** @internal */ -export type EsriClassificationMethodType = "esriClassifyDefinedInterval" | "esriClassifyEqualInterval" | "esriClassifyManual" | "esriClassifyNaturalBreaks" | "esriClassifyQuantile" | "esriClassifyStandardDeviation"; +export type EsriClassificationMethodType = + | "esriClassifyDefinedInterval" + | "esriClassifyEqualInterval" + | "esriClassifyManual" + | "esriClassifyNaturalBreaks" + | "esriClassifyQuantile" + | "esriClassifyStandardDeviation"; /** @internal */ export interface EsriClassBreaksRendererProps extends EsriRendererBaseProps { @@ -299,13 +374,15 @@ export interface EsriClassBreaksRendererProps extends EsriRendererBaseProps { export type EsriRendererType = "simple" | "uniqueValue" | "classBreaks"; /** @internal */ -export type EsriRendererProps = EsriSimpleRendererProps | EsriUniqueValueRendererProps | EsriClassBreaksRendererProps; +export type EsriRendererProps = EsriSimpleRendererProps | EsriUniqueValueRendererProps | EsriClassBreaksRendererProps; /** @internal */ export abstract class EsriRenderer { - public readonly abstract type: EsriRendererType; + public abstract readonly type: EsriRendererType; public abstract initialize(): Promise; - public get fields(): string[]|undefined {return undefined;} + public get fields(): string[] | undefined { + return undefined; + } public static fromJSON(json: EsriRendererProps): EsriRenderer { if (json.type === "simple") return EsriSimpleRenderer.fromJSON(json as EsriSimpleRendererProps); @@ -360,9 +437,15 @@ export class EsriUniqueValueRenderer extends EsriRenderer { return fields; } - public get field1() { return this._props.field1 ?? undefined; } - public get field2() { return this._props.field2 ?? undefined; } - public get field3() { return this._props.field3 ?? undefined; } + public get field1() { + return this._props.field1 ?? undefined; + } + public get field2() { + return this._props.field2 ?? undefined; + } + public get field3() { + return this._props.field3 ?? undefined; + } protected constructor(json: EsriUniqueValueRendererProps) { super(); @@ -398,7 +481,9 @@ export class EsriClassBreaksRenderer extends EsriRenderer { private _props: EsriClassBreaksRendererProps; public readonly type: EsriRendererType = "classBreaks"; public readonly defaultSymbol?: EsriSymbol; - public get classificationMethod() {return this._props.classificationMethod;} + public get classificationMethod() { + return this._props.classificationMethod; + } public readonly classBreakInfos: EsriClassBreaksValueInfo[] = []; public override get fields() { @@ -408,8 +493,12 @@ export class EsriClassBreaksRenderer extends EsriRenderer { return undefined; } - public get field() { return this._props.field ?? undefined; } - public get minValue() { return this._props.minValue ?? 0; } + public get field() { + return this._props.field ?? undefined; + } + public get minValue() { + return this._props.minValue ?? 0; + } protected constructor(json: EsriClassBreaksRendererProps) { super(); @@ -440,4 +529,3 @@ export class EsriClassBreaksRenderer extends EsriRenderer { return new EsriClassBreaksRenderer(json); } } - diff --git a/extensions/map-layers-formats/src/ArcGisFeature/esriPBuffer.gen.ts b/extensions/map-layers-formats/src/ArcGisFeature/esriPBuffer.gen.ts index 496736eb56bd..a620431ff740 100644 --- a/extensions/map-layers-formats/src/ArcGisFeature/esriPBuffer.gen.ts +++ b/extensions/map-layers-formats/src/ArcGisFeature/esriPBuffer.gen.ts @@ -1,4 +1,3 @@ - /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. @@ -16,97 +15,100 @@ import * as pb_1 from "google-protobuf"; /** @internal */ export namespace esriPBuffer { export class FeatureCollectionPBuffer extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - version?: string; - queryResult?: FeatureCollectionPBuffer.QueryResult; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("version" in data && data.version != undefined) { - this.version = data.version; - } - if ("queryResult" in data && data.queryResult != undefined) { - this.queryResult = data.queryResult; - } - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + version?: string; + queryResult?: FeatureCollectionPBuffer.QueryResult; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("version" in data && data.version != undefined) { + this.version = data.version; } - get version() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set version(value: string) { - pb_1.Message.setField(this, 1, value); - } - get queryResult() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.QueryResult, 2) as FeatureCollectionPBuffer.QueryResult; - } - set queryResult(value: FeatureCollectionPBuffer.QueryResult) { - pb_1.Message.setWrapperField(this, 2, value); - } - get has_queryResult() { - return pb_1.Message.getField(this, 2) != null; - } - static fromObject(data: { - version?: string; - queryResult?: ReturnType; - }): FeatureCollectionPBuffer { - const message = new FeatureCollectionPBuffer({}); - if (data.version != null) { - message.version = data.version; - } - if (data.queryResult != null) { - message.queryResult = FeatureCollectionPBuffer.QueryResult.fromObject(data.queryResult); - } - return message; - } - toObject() { - const data: { - version?: string; - queryResult?: ReturnType; - } = {}; - if (this.version != null) { - data.version = this.version; - } - if (this.queryResult != null) { - data.queryResult = this.queryResult.toObject(); - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.version.length) - writer.writeString(1, this.version); - if (this.has_queryResult) - writer.writeMessage(2, this.queryResult, () => this.queryResult.serialize(writer)); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): FeatureCollectionPBuffer { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new FeatureCollectionPBuffer(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.version = reader.readString(); - break; - case 2: - reader.readMessage(message.queryResult, () => message.queryResult = FeatureCollectionPBuffer.QueryResult.deserialize(reader)); - break; - default: reader.skipField(); - } - } - return message; + if ("queryResult" in data && data.queryResult != undefined) { + this.queryResult = data.queryResult; } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): FeatureCollectionPBuffer { - return FeatureCollectionPBuffer.deserialize(bytes); + } + } + get version() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set version(value: string) { + pb_1.Message.setField(this, 1, value); + } + get queryResult() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.QueryResult, 2) as FeatureCollectionPBuffer.QueryResult; + } + set queryResult(value: FeatureCollectionPBuffer.QueryResult) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_queryResult() { + return pb_1.Message.getField(this, 2) != null; + } + static fromObject(data: { + version?: string; + queryResult?: ReturnType; + }): FeatureCollectionPBuffer { + const message = new FeatureCollectionPBuffer({}); + if (data.version != null) { + message.version = data.version; + } + if (data.queryResult != null) { + message.queryResult = FeatureCollectionPBuffer.QueryResult.fromObject(data.queryResult); + } + return message; + } + toObject() { + const data: { + version?: string; + queryResult?: ReturnType; + } = {}; + if (this.version != null) { + data.version = this.version; + } + if (this.queryResult != null) { + data.queryResult = this.queryResult.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.version.length) + writer.writeString(1, this.version); + if (this.has_queryResult) + writer.writeMessage(2, this.queryResult, () => this.queryResult.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): FeatureCollectionPBuffer { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new FeatureCollectionPBuffer(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.version = reader.readString(); + break; + case 2: + reader.readMessage(message.queryResult, () => message.queryResult = FeatureCollectionPBuffer.QueryResult.deserialize(reader)); + break; + default: + reader.skipField(); } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): FeatureCollectionPBuffer { + return FeatureCollectionPBuffer.deserialize(bytes); + } } export namespace FeatureCollectionPBuffer { export enum GeometryType { @@ -115,7 +117,7 @@ export namespace esriPBuffer { esriGeometryTypePolyline = 2, esriGeometryTypePolygon = 3, esriGeometryTypeMultipatch = 4, - esriGeometryTypeNone = 127 + esriGeometryTypeNone = 127, } export enum FieldType { esriFieldTypeSmallInteger = 0, @@ -130,7 +132,7 @@ export namespace esriPBuffer { esriFieldTypeRaster = 9, esriFieldTypeGUID = 10, esriFieldTypeGlobalID = 11, - esriFieldTypeXML = 12 + esriFieldTypeXML = 12, } export enum SQLType { sqlTypeBigInt = 0, @@ -158,356 +160,371 @@ export namespace esriPBuffer { sqlTypeTimestamp2 = 22, sqlTypeTinyInt = 23, sqlTypeVarbinary = 24, - sqlTypeVarchar = 25 + sqlTypeVarchar = 25, } export enum QuantizeOriginPostion { upperLeft = 0, - lowerLeft = 1 + lowerLeft = 1, } export class SpatialReference extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - wkid?: number; - lastestWkid?: number; - vcsWkid?: number; - latestVcsWkid?: number; - wkt?: string; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("wkid" in data && data.wkid != undefined) { - this.wkid = data.wkid; - } - if ("lastestWkid" in data && data.lastestWkid != undefined) { - this.lastestWkid = data.lastestWkid; - } - if ("vcsWkid" in data && data.vcsWkid != undefined) { - this.vcsWkid = data.vcsWkid; - } - if ("latestVcsWkid" in data && data.latestVcsWkid != undefined) { - this.latestVcsWkid = data.latestVcsWkid; - } - if ("wkt" in data && data.wkt != undefined) { - this.wkt = data.wkt; - } - } - } - get wkid() { - return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; - } - set wkid(value: number) { - pb_1.Message.setField(this, 1, value); - } - get lastestWkid() { - return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; - } - set lastestWkid(value: number) { - pb_1.Message.setField(this, 2, value); - } - get vcsWkid() { - return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; - } - set vcsWkid(value: number) { - pb_1.Message.setField(this, 3, value); - } - get latestVcsWkid() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; - } - set latestVcsWkid(value: number) { - pb_1.Message.setField(this, 4, value); - } - get wkt() { - return pb_1.Message.getFieldWithDefault(this, 5, "") as string; - } - set wkt(value: string) { - pb_1.Message.setField(this, 5, value); - } - static fromObject(data: { - wkid?: number; - lastestWkid?: number; - vcsWkid?: number; - latestVcsWkid?: number; - wkt?: string; - }): SpatialReference { - const message = new SpatialReference({}); - if (data.wkid != null) { - message.wkid = data.wkid; - } - if (data.lastestWkid != null) { - message.lastestWkid = data.lastestWkid; - } - if (data.vcsWkid != null) { - message.vcsWkid = data.vcsWkid; - } - if (data.latestVcsWkid != null) { - message.latestVcsWkid = data.latestVcsWkid; - } - if (data.wkt != null) { - message.wkt = data.wkt; - } - return message; - } - toObject() { - const data: { - wkid?: number; - lastestWkid?: number; - vcsWkid?: number; - latestVcsWkid?: number; - wkt?: string; - } = {}; - if (this.wkid != null) { - data.wkid = this.wkid; - } - if (this.lastestWkid != null) { - data.lastestWkid = this.lastestWkid; - } - if (this.vcsWkid != null) { - data.vcsWkid = this.vcsWkid; - } - if (this.latestVcsWkid != null) { - data.latestVcsWkid = this.latestVcsWkid; - } - if (this.wkt != null) { - data.wkt = this.wkt; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.wkid != 0) - writer.writeUint32(1, this.wkid); - if (this.lastestWkid != 0) - writer.writeUint32(2, this.lastestWkid); - if (this.vcsWkid != 0) - writer.writeUint32(3, this.vcsWkid); - if (this.latestVcsWkid != 0) - writer.writeUint32(4, this.latestVcsWkid); - if (this.wkt.length) - writer.writeString(5, this.wkt); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): SpatialReference { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new SpatialReference(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.wkid = reader.readUint32(); - break; - case 2: - message.lastestWkid = reader.readUint32(); - break; - case 3: - message.vcsWkid = reader.readUint32(); - break; - case 4: - message.latestVcsWkid = reader.readUint32(); - break; - case 5: - message.wkt = reader.readString(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): SpatialReference { - return SpatialReference.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + wkid?: number; + lastestWkid?: number; + vcsWkid?: number; + latestVcsWkid?: number; + wkt?: string; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("wkid" in data && data.wkid != undefined) { + this.wkid = data.wkid; + } + if ("lastestWkid" in data && data.lastestWkid != undefined) { + this.lastestWkid = data.lastestWkid; + } + if ("vcsWkid" in data && data.vcsWkid != undefined) { + this.vcsWkid = data.vcsWkid; + } + if ("latestVcsWkid" in data && data.latestVcsWkid != undefined) { + this.latestVcsWkid = data.latestVcsWkid; + } + if ("wkt" in data && data.wkt != undefined) { + this.wkt = data.wkt; + } + } + } + get wkid() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set wkid(value: number) { + pb_1.Message.setField(this, 1, value); + } + get lastestWkid() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set lastestWkid(value: number) { + pb_1.Message.setField(this, 2, value); + } + get vcsWkid() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set vcsWkid(value: number) { + pb_1.Message.setField(this, 3, value); + } + get latestVcsWkid() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set latestVcsWkid(value: number) { + pb_1.Message.setField(this, 4, value); + } + get wkt() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set wkt(value: string) { + pb_1.Message.setField(this, 5, value); + } + static fromObject(data: { + wkid?: number; + lastestWkid?: number; + vcsWkid?: number; + latestVcsWkid?: number; + wkt?: string; + }): SpatialReference { + const message = new SpatialReference({}); + if (data.wkid != null) { + message.wkid = data.wkid; + } + if (data.lastestWkid != null) { + message.lastestWkid = data.lastestWkid; + } + if (data.vcsWkid != null) { + message.vcsWkid = data.vcsWkid; + } + if (data.latestVcsWkid != null) { + message.latestVcsWkid = data.latestVcsWkid; + } + if (data.wkt != null) { + message.wkt = data.wkt; + } + return message; + } + toObject() { + const data: { + wkid?: number; + lastestWkid?: number; + vcsWkid?: number; + latestVcsWkid?: number; + wkt?: string; + } = {}; + if (this.wkid != null) { + data.wkid = this.wkid; + } + if (this.lastestWkid != null) { + data.lastestWkid = this.lastestWkid; + } + if (this.vcsWkid != null) { + data.vcsWkid = this.vcsWkid; + } + if (this.latestVcsWkid != null) { + data.latestVcsWkid = this.latestVcsWkid; + } + if (this.wkt != null) { + data.wkt = this.wkt; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.wkid != 0) + writer.writeUint32(1, this.wkid); + if (this.lastestWkid != 0) + writer.writeUint32(2, this.lastestWkid); + if (this.vcsWkid != 0) + writer.writeUint32(3, this.vcsWkid); + if (this.latestVcsWkid != 0) + writer.writeUint32(4, this.latestVcsWkid); + if (this.wkt.length) + writer.writeString(5, this.wkt); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): SpatialReference { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new SpatialReference(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.wkid = reader.readUint32(); + break; + case 2: + message.lastestWkid = reader.readUint32(); + break; + case 3: + message.vcsWkid = reader.readUint32(); + break; + case 4: + message.latestVcsWkid = reader.readUint32(); + break; + case 5: + message.wkt = reader.readString(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): SpatialReference { + return SpatialReference.deserialize(bytes); + } } export class Field extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - name?: string; - fieldType?: FeatureCollectionPBuffer.FieldType; - alias?: string; - sqlType?: FeatureCollectionPBuffer.SQLType; - domain?: string; - defaultValue?: string; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("name" in data && data.name != undefined) { - this.name = data.name; - } - if ("fieldType" in data && data.fieldType != undefined) { - this.fieldType = data.fieldType; - } - if ("alias" in data && data.alias != undefined) { - this.alias = data.alias; - } - if ("sqlType" in data && data.sqlType != undefined) { - this.sqlType = data.sqlType; - } - if ("domain" in data && data.domain != undefined) { - this.domain = data.domain; - } - if ("defaultValue" in data && data.defaultValue != undefined) { - this.defaultValue = data.defaultValue; - } - } - } - get name() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set name(value: string) { - pb_1.Message.setField(this, 1, value); - } - get fieldType() { - return pb_1.Message.getFieldWithDefault(this, 2, FeatureCollectionPBuffer.FieldType.esriFieldTypeSmallInteger) as FeatureCollectionPBuffer.FieldType; - } - set fieldType(value: FeatureCollectionPBuffer.FieldType) { - pb_1.Message.setField(this, 2, value); - } - get alias() { - return pb_1.Message.getFieldWithDefault(this, 3, "") as string; - } - set alias(value: string) { - pb_1.Message.setField(this, 3, value); - } - get sqlType() { - return pb_1.Message.getFieldWithDefault(this, 4, FeatureCollectionPBuffer.SQLType.sqlTypeBigInt) as FeatureCollectionPBuffer.SQLType; - } - set sqlType(value: FeatureCollectionPBuffer.SQLType) { - pb_1.Message.setField(this, 4, value); - } - get domain() { - return pb_1.Message.getFieldWithDefault(this, 5, "") as string; - } - set domain(value: string) { - pb_1.Message.setField(this, 5, value); - } - get defaultValue() { - return pb_1.Message.getFieldWithDefault(this, 6, "") as string; - } - set defaultValue(value: string) { - pb_1.Message.setField(this, 6, value); - } - static fromObject(data: { - name?: string; - fieldType?: FeatureCollectionPBuffer.FieldType; - alias?: string; - sqlType?: FeatureCollectionPBuffer.SQLType; - domain?: string; - defaultValue?: string; - }): Field { - const message = new Field({}); - if (data.name != null) { - message.name = data.name; - } - if (data.fieldType != null) { - message.fieldType = data.fieldType; - } - if (data.alias != null) { - message.alias = data.alias; - } - if (data.sqlType != null) { - message.sqlType = data.sqlType; - } - if (data.domain != null) { - message.domain = data.domain; - } - if (data.defaultValue != null) { - message.defaultValue = data.defaultValue; - } - return message; - } - toObject() { - const data: { - name?: string; - fieldType?: FeatureCollectionPBuffer.FieldType; - alias?: string; - sqlType?: FeatureCollectionPBuffer.SQLType; - domain?: string; - defaultValue?: string; - } = {}; - if (this.name != null) { - data.name = this.name; - } - if (this.fieldType != null) { - data.fieldType = this.fieldType; - } - if (this.alias != null) { - data.alias = this.alias; - } - if (this.sqlType != null) { - data.sqlType = this.sqlType; - } - if (this.domain != null) { - data.domain = this.domain; - } - if (this.defaultValue != null) { - data.defaultValue = this.defaultValue; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.name.length) - writer.writeString(1, this.name); - if (this.fieldType != FeatureCollectionPBuffer.FieldType.esriFieldTypeSmallInteger) - writer.writeEnum(2, this.fieldType); - if (this.alias.length) - writer.writeString(3, this.alias); - if (this.sqlType != FeatureCollectionPBuffer.SQLType.sqlTypeBigInt) - writer.writeEnum(4, this.sqlType); - if (this.domain.length) - writer.writeString(5, this.domain); - if (this.defaultValue.length) - writer.writeString(6, this.defaultValue); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Field { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Field(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.name = reader.readString(); - break; - case 2: - message.fieldType = reader.readEnum(); - break; - case 3: - message.alias = reader.readString(); - break; - case 4: - message.sqlType = reader.readEnum(); - break; - case 5: - message.domain = reader.readString(); - break; - case 6: - message.defaultValue = reader.readString(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Field { - return Field.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + name?: string; + fieldType?: FeatureCollectionPBuffer.FieldType; + alias?: string; + sqlType?: FeatureCollectionPBuffer.SQLType; + domain?: string; + defaultValue?: string; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("name" in data && data.name != undefined) { + this.name = data.name; + } + if ("fieldType" in data && data.fieldType != undefined) { + this.fieldType = data.fieldType; + } + if ("alias" in data && data.alias != undefined) { + this.alias = data.alias; + } + if ("sqlType" in data && data.sqlType != undefined) { + this.sqlType = data.sqlType; + } + if ("domain" in data && data.domain != undefined) { + this.domain = data.domain; + } + if ("defaultValue" in data && data.defaultValue != undefined) { + this.defaultValue = data.defaultValue; + } + } + } + get name() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set name(value: string) { + pb_1.Message.setField(this, 1, value); + } + get fieldType() { + return pb_1.Message.getFieldWithDefault( + this, + 2, + FeatureCollectionPBuffer.FieldType.esriFieldTypeSmallInteger, + ) as FeatureCollectionPBuffer.FieldType; + } + set fieldType(value: FeatureCollectionPBuffer.FieldType) { + pb_1.Message.setField(this, 2, value); + } + get alias() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set alias(value: string) { + pb_1.Message.setField(this, 3, value); + } + get sqlType() { + return pb_1.Message.getFieldWithDefault(this, 4, FeatureCollectionPBuffer.SQLType.sqlTypeBigInt) as FeatureCollectionPBuffer.SQLType; + } + set sqlType(value: FeatureCollectionPBuffer.SQLType) { + pb_1.Message.setField(this, 4, value); + } + get domain() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set domain(value: string) { + pb_1.Message.setField(this, 5, value); + } + get defaultValue() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set defaultValue(value: string) { + pb_1.Message.setField(this, 6, value); + } + static fromObject(data: { + name?: string; + fieldType?: FeatureCollectionPBuffer.FieldType; + alias?: string; + sqlType?: FeatureCollectionPBuffer.SQLType; + domain?: string; + defaultValue?: string; + }): Field { + const message = new Field({}); + if (data.name != null) { + message.name = data.name; + } + if (data.fieldType != null) { + message.fieldType = data.fieldType; + } + if (data.alias != null) { + message.alias = data.alias; + } + if (data.sqlType != null) { + message.sqlType = data.sqlType; + } + if (data.domain != null) { + message.domain = data.domain; + } + if (data.defaultValue != null) { + message.defaultValue = data.defaultValue; + } + return message; + } + toObject() { + const data: { + name?: string; + fieldType?: FeatureCollectionPBuffer.FieldType; + alias?: string; + sqlType?: FeatureCollectionPBuffer.SQLType; + domain?: string; + defaultValue?: string; + } = {}; + if (this.name != null) { + data.name = this.name; + } + if (this.fieldType != null) { + data.fieldType = this.fieldType; + } + if (this.alias != null) { + data.alias = this.alias; + } + if (this.sqlType != null) { + data.sqlType = this.sqlType; + } + if (this.domain != null) { + data.domain = this.domain; + } + if (this.defaultValue != null) { + data.defaultValue = this.defaultValue; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.name.length) + writer.writeString(1, this.name); + if (this.fieldType != FeatureCollectionPBuffer.FieldType.esriFieldTypeSmallInteger) + writer.writeEnum(2, this.fieldType); + if (this.alias.length) + writer.writeString(3, this.alias); + if (this.sqlType != FeatureCollectionPBuffer.SQLType.sqlTypeBigInt) + writer.writeEnum(4, this.sqlType); + if (this.domain.length) + writer.writeString(5, this.domain); + if (this.defaultValue.length) + writer.writeString(6, this.defaultValue); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Field { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Field(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.name = reader.readString(); + break; + case 2: + message.fieldType = reader.readEnum(); + break; + case 3: + message.alias = reader.readString(); + break; + case 4: + message.sqlType = reader.readEnum(); + break; + case 5: + message.domain = reader.readString(); + break; + case 6: + message.defaultValue = reader.readString(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Field { + return Field.deserialize(bytes); + } } export class Value extends pb_1.Message { - #one_of_decls: number[][] = [[1, 2, 3, 4, 5, 6, 7, 8, 9]]; - constructor(data?: any[] | ({} & (({ + #one_of_decls: number[][] = [[1, 2, 3, 4, 5, 6, 7, 8, 9]]; + constructor( + data?: + | any[] + | ( + & {} + & (({ string_value?: string; float_value?: never; double_value?: never; @@ -597,1879 +614,1988 @@ export namespace esriPBuffer { uint64_value?: never; sint64_value?: never; bool_value?: boolean; - })))) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("string_value" in data && data.string_value != undefined) { - this.string_value = data.string_value; - } - if ("float_value" in data && data.float_value != undefined) { - this.float_value = data.float_value; - } - if ("double_value" in data && data.double_value != undefined) { - this.double_value = data.double_value; - } - if ("sint_value" in data && data.sint_value != undefined) { - this.sint_value = data.sint_value; - } - if ("uint_value" in data && data.uint_value != undefined) { - this.uint_value = data.uint_value; - } - if ("int64_value" in data && data.int64_value != undefined) { - this.int64_value = data.int64_value; - } - if ("uint64_value" in data && data.uint64_value != undefined) { - this.uint64_value = data.uint64_value; - } - if ("sint64_value" in data && data.sint64_value != undefined) { - this.sint64_value = data.sint64_value; - } - if ("bool_value" in data && data.bool_value != undefined) { - this.bool_value = data.bool_value; - } - } - } - get string_value() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set string_value(value: string) { - pb_1.Message.setOneofField(this, 1, this.#one_of_decls[0], value); - } - get has_string_value() { - return pb_1.Message.getField(this, 1) != null; - } - get float_value() { - return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; - } - set float_value(value: number) { - pb_1.Message.setOneofField(this, 2, this.#one_of_decls[0], value); - } - get has_float_value() { - return pb_1.Message.getField(this, 2) != null; - } - get double_value() { - return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; - } - set double_value(value: number) { - pb_1.Message.setOneofField(this, 3, this.#one_of_decls[0], value); - } - get has_double_value() { - return pb_1.Message.getField(this, 3) != null; - } - get sint_value() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; - } - set sint_value(value: number) { - pb_1.Message.setOneofField(this, 4, this.#one_of_decls[0], value); - } - get has_sint_value() { - return pb_1.Message.getField(this, 4) != null; - } - get uint_value() { - return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; - } - set uint_value(value: number) { - pb_1.Message.setOneofField(this, 5, this.#one_of_decls[0], value); - } - get has_uint_value() { - return pb_1.Message.getField(this, 5) != null; - } - get int64_value() { - return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; - } - set int64_value(value: number) { - pb_1.Message.setOneofField(this, 6, this.#one_of_decls[0], value); - } - get has_int64_value() { - return pb_1.Message.getField(this, 6) != null; - } - get uint64_value() { - return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; - } - set uint64_value(value: number) { - pb_1.Message.setOneofField(this, 7, this.#one_of_decls[0], value); - } - get has_uint64_value() { - return pb_1.Message.getField(this, 7) != null; - } - get sint64_value() { - return pb_1.Message.getFieldWithDefault(this, 8, 0) as number; - } - set sint64_value(value: number) { - pb_1.Message.setOneofField(this, 8, this.#one_of_decls[0], value); - } - get has_sint64_value() { - return pb_1.Message.getField(this, 8) != null; - } - get bool_value() { - return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; - } - set bool_value(value: boolean) { - pb_1.Message.setOneofField(this, 9, this.#one_of_decls[0], value); - } - get has_bool_value() { - return pb_1.Message.getField(this, 9) != null; - } - get value_type() { - const cases: { - [index: number]: "none" | "string_value" | "float_value" | "double_value" | "sint_value" | "uint_value" | "int64_value" | "uint64_value" | "sint64_value" | "bool_value"; - } = { - 0: "none", - 1: "string_value", - 2: "float_value", - 3: "double_value", - 4: "sint_value", - 5: "uint_value", - 6: "int64_value", - 7: "uint64_value", - 8: "sint64_value", - 9: "bool_value", - }; - return cases[pb_1.Message.computeOneofCase(this, [1, 2, 3, 4, 5, 6, 7, 8, 9])]; - } - static fromObject(data: { - string_value?: string; - float_value?: number; - double_value?: number; - sint_value?: number; - uint_value?: number; - int64_value?: number; - uint64_value?: number; - sint64_value?: number; - bool_value?: boolean; - }): Value { - const message = new Value({}); - if (data.string_value != null) { - message.string_value = data.string_value; - } - if (data.float_value != null) { - message.float_value = data.float_value; - } - if (data.double_value != null) { - message.double_value = data.double_value; - } - if (data.sint_value != null) { - message.sint_value = data.sint_value; - } - if (data.uint_value != null) { - message.uint_value = data.uint_value; - } - if (data.int64_value != null) { - message.int64_value = data.int64_value; - } - if (data.uint64_value != null) { - message.uint64_value = data.uint64_value; - } - if (data.sint64_value != null) { - message.sint64_value = data.sint64_value; - } - if (data.bool_value != null) { - message.bool_value = data.bool_value; - } - return message; - } - toObject() { - const data: { - string_value?: string; - float_value?: number; - double_value?: number; - sint_value?: number; - uint_value?: number; - int64_value?: number; - uint64_value?: number; - sint64_value?: number; - bool_value?: boolean; - } = {}; - if (this.string_value != null) { - data.string_value = this.string_value; - } - if (this.float_value != null) { - data.float_value = this.float_value; - } - if (this.double_value != null) { - data.double_value = this.double_value; - } - if (this.sint_value != null) { - data.sint_value = this.sint_value; - } - if (this.uint_value != null) { - data.uint_value = this.uint_value; - } - if (this.int64_value != null) { - data.int64_value = this.int64_value; - } - if (this.uint64_value != null) { - data.uint64_value = this.uint64_value; - } - if (this.sint64_value != null) { - data.sint64_value = this.sint64_value; - } - if (this.bool_value != null) { - data.bool_value = this.bool_value; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.has_string_value) - writer.writeString(1, this.string_value); - if (this.has_float_value) - writer.writeFloat(2, this.float_value); - if (this.has_double_value) - writer.writeDouble(3, this.double_value); - if (this.has_sint_value) - writer.writeSint32(4, this.sint_value); - if (this.has_uint_value) - writer.writeUint32(5, this.uint_value); - if (this.has_int64_value) - writer.writeInt64(6, this.int64_value); - if (this.has_uint64_value) - writer.writeUint64(7, this.uint64_value); - if (this.has_sint64_value) - writer.writeSint64(8, this.sint64_value); - if (this.has_bool_value) - writer.writeBool(9, this.bool_value); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Value { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Value(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.string_value = reader.readString(); - break; - case 2: - message.float_value = reader.readFloat(); - break; - case 3: - message.double_value = reader.readDouble(); - break; - case 4: - message.sint_value = reader.readSint32(); - break; - case 5: - message.uint_value = reader.readUint32(); - break; - case 6: - message.int64_value = reader.readInt64(); - break; - case 7: - message.uint64_value = reader.readUint64(); - break; - case 8: - message.sint64_value = reader.readSint64(); - break; - case 9: - message.bool_value = reader.readBool(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Value { - return Value.deserialize(bytes); - } + })) + ), + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("string_value" in data && data.string_value != undefined) { + this.string_value = data.string_value; + } + if ("float_value" in data && data.float_value != undefined) { + this.float_value = data.float_value; + } + if ("double_value" in data && data.double_value != undefined) { + this.double_value = data.double_value; + } + if ("sint_value" in data && data.sint_value != undefined) { + this.sint_value = data.sint_value; + } + if ("uint_value" in data && data.uint_value != undefined) { + this.uint_value = data.uint_value; + } + if ("int64_value" in data && data.int64_value != undefined) { + this.int64_value = data.int64_value; + } + if ("uint64_value" in data && data.uint64_value != undefined) { + this.uint64_value = data.uint64_value; + } + if ("sint64_value" in data && data.sint64_value != undefined) { + this.sint64_value = data.sint64_value; + } + if ("bool_value" in data && data.bool_value != undefined) { + this.bool_value = data.bool_value; + } + } + } + get string_value() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set string_value(value: string) { + pb_1.Message.setOneofField(this, 1, this.#one_of_decls[0], value); + } + get has_string_value() { + return pb_1.Message.getField(this, 1) != null; + } + get float_value() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set float_value(value: number) { + pb_1.Message.setOneofField(this, 2, this.#one_of_decls[0], value); + } + get has_float_value() { + return pb_1.Message.getField(this, 2) != null; + } + get double_value() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set double_value(value: number) { + pb_1.Message.setOneofField(this, 3, this.#one_of_decls[0], value); + } + get has_double_value() { + return pb_1.Message.getField(this, 3) != null; + } + get sint_value() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set sint_value(value: number) { + pb_1.Message.setOneofField(this, 4, this.#one_of_decls[0], value); + } + get has_sint_value() { + return pb_1.Message.getField(this, 4) != null; + } + get uint_value() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set uint_value(value: number) { + pb_1.Message.setOneofField(this, 5, this.#one_of_decls[0], value); + } + get has_uint_value() { + return pb_1.Message.getField(this, 5) != null; + } + get int64_value() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set int64_value(value: number) { + pb_1.Message.setOneofField(this, 6, this.#one_of_decls[0], value); + } + get has_int64_value() { + return pb_1.Message.getField(this, 6) != null; + } + get uint64_value() { + return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; + } + set uint64_value(value: number) { + pb_1.Message.setOneofField(this, 7, this.#one_of_decls[0], value); + } + get has_uint64_value() { + return pb_1.Message.getField(this, 7) != null; + } + get sint64_value() { + return pb_1.Message.getFieldWithDefault(this, 8, 0) as number; + } + set sint64_value(value: number) { + pb_1.Message.setOneofField(this, 8, this.#one_of_decls[0], value); + } + get has_sint64_value() { + return pb_1.Message.getField(this, 8) != null; + } + get bool_value() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set bool_value(value: boolean) { + pb_1.Message.setOneofField(this, 9, this.#one_of_decls[0], value); + } + get has_bool_value() { + return pb_1.Message.getField(this, 9) != null; + } + get value_type() { + const cases: { + [index: number]: + | "none" + | "string_value" + | "float_value" + | "double_value" + | "sint_value" + | "uint_value" + | "int64_value" + | "uint64_value" + | "sint64_value" + | "bool_value"; + } = { + 0: "none", + 1: "string_value", + 2: "float_value", + 3: "double_value", + 4: "sint_value", + 5: "uint_value", + 6: "int64_value", + 7: "uint64_value", + 8: "sint64_value", + 9: "bool_value", + }; + return cases[pb_1.Message.computeOneofCase(this, [1, 2, 3, 4, 5, 6, 7, 8, 9])]; + } + static fromObject(data: { + string_value?: string; + float_value?: number; + double_value?: number; + sint_value?: number; + uint_value?: number; + int64_value?: number; + uint64_value?: number; + sint64_value?: number; + bool_value?: boolean; + }): Value { + const message = new Value({}); + if (data.string_value != null) { + message.string_value = data.string_value; + } + if (data.float_value != null) { + message.float_value = data.float_value; + } + if (data.double_value != null) { + message.double_value = data.double_value; + } + if (data.sint_value != null) { + message.sint_value = data.sint_value; + } + if (data.uint_value != null) { + message.uint_value = data.uint_value; + } + if (data.int64_value != null) { + message.int64_value = data.int64_value; + } + if (data.uint64_value != null) { + message.uint64_value = data.uint64_value; + } + if (data.sint64_value != null) { + message.sint64_value = data.sint64_value; + } + if (data.bool_value != null) { + message.bool_value = data.bool_value; + } + return message; + } + toObject() { + const data: { + string_value?: string; + float_value?: number; + double_value?: number; + sint_value?: number; + uint_value?: number; + int64_value?: number; + uint64_value?: number; + sint64_value?: number; + bool_value?: boolean; + } = {}; + if (this.string_value != null) { + data.string_value = this.string_value; + } + if (this.float_value != null) { + data.float_value = this.float_value; + } + if (this.double_value != null) { + data.double_value = this.double_value; + } + if (this.sint_value != null) { + data.sint_value = this.sint_value; + } + if (this.uint_value != null) { + data.uint_value = this.uint_value; + } + if (this.int64_value != null) { + data.int64_value = this.int64_value; + } + if (this.uint64_value != null) { + data.uint64_value = this.uint64_value; + } + if (this.sint64_value != null) { + data.sint64_value = this.sint64_value; + } + if (this.bool_value != null) { + data.bool_value = this.bool_value; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_string_value) + writer.writeString(1, this.string_value); + if (this.has_float_value) + writer.writeFloat(2, this.float_value); + if (this.has_double_value) + writer.writeDouble(3, this.double_value); + if (this.has_sint_value) + writer.writeSint32(4, this.sint_value); + if (this.has_uint_value) + writer.writeUint32(5, this.uint_value); + if (this.has_int64_value) + writer.writeInt64(6, this.int64_value); + if (this.has_uint64_value) + writer.writeUint64(7, this.uint64_value); + if (this.has_sint64_value) + writer.writeSint64(8, this.sint64_value); + if (this.has_bool_value) + writer.writeBool(9, this.bool_value); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Value { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Value(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.string_value = reader.readString(); + break; + case 2: + message.float_value = reader.readFloat(); + break; + case 3: + message.double_value = reader.readDouble(); + break; + case 4: + message.sint_value = reader.readSint32(); + break; + case 5: + message.uint_value = reader.readUint32(); + break; + case 6: + message.int64_value = reader.readInt64(); + break; + case 7: + message.uint64_value = reader.readUint64(); + break; + case 8: + message.sint64_value = reader.readSint64(); + break; + case 9: + message.bool_value = reader.readBool(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Value { + return Value.deserialize(bytes); + } } export class Geometry extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - lengths?: number[]; - coords?: number[]; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("lengths" in data && data.lengths != undefined) { - this.lengths = data.lengths; - } - if ("coords" in data && data.coords != undefined) { - this.coords = data.coords; - } - } - } - get lengths() { - return pb_1.Message.getFieldWithDefault(this, 2, []) as number[]; - } - set lengths(value: number[]) { - pb_1.Message.setField(this, 2, value); - } - get coords() { - return pb_1.Message.getFieldWithDefault(this, 3, []) as number[]; - } - set coords(value: number[]) { - pb_1.Message.setField(this, 3, value); - } - static fromObject(data: { - lengths?: number[]; - coords?: number[]; - }): Geometry { - const message = new Geometry({}); - if (data.lengths != null) { - message.lengths = data.lengths; - } - if (data.coords != null) { - message.coords = data.coords; - } - return message; - } - toObject() { - const data: { - lengths?: number[]; - coords?: number[]; - } = {}; - if (this.lengths != null) { - data.lengths = this.lengths; - } - if (this.coords != null) { - data.coords = this.coords; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.lengths.length) - writer.writePackedUint32(2, this.lengths); - if (this.coords.length) - writer.writePackedSint64(3, this.coords); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Geometry { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Geometry(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 2: - message.lengths = reader.readPackedUint32(); - break; - case 3: - message.coords = reader.readPackedSint64(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Geometry { - return Geometry.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + lengths?: number[]; + coords?: number[]; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lengths" in data && data.lengths != undefined) { + this.lengths = data.lengths; + } + if ("coords" in data && data.coords != undefined) { + this.coords = data.coords; + } + } + } + get lengths() { + return pb_1.Message.getFieldWithDefault(this, 2, []) as number[]; + } + set lengths(value: number[]) { + pb_1.Message.setField(this, 2, value); + } + get coords() { + return pb_1.Message.getFieldWithDefault(this, 3, []) as number[]; + } + set coords(value: number[]) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + lengths?: number[]; + coords?: number[]; + }): Geometry { + const message = new Geometry({}); + if (data.lengths != null) { + message.lengths = data.lengths; + } + if (data.coords != null) { + message.coords = data.coords; + } + return message; + } + toObject() { + const data: { + lengths?: number[]; + coords?: number[]; + } = {}; + if (this.lengths != null) { + data.lengths = this.lengths; + } + if (this.coords != null) { + data.coords = this.coords; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lengths.length) + writer.writePackedUint32(2, this.lengths); + if (this.coords.length) + writer.writePackedSint64(3, this.coords); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Geometry { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Geometry(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 2: + message.lengths = reader.readPackedUint32(); + break; + case 3: + message.coords = reader.readPackedSint64(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Geometry { + return Geometry.deserialize(bytes); + } } export class esriShapeBuffer extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - bytes?: Uint8Array; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("bytes" in data && data.bytes != undefined) { - this.bytes = data.bytes; - } - } - } - get bytes() { - return pb_1.Message.getFieldWithDefault(this, 1, new Uint8Array()) as Uint8Array; - } - set bytes(value: Uint8Array) { - pb_1.Message.setField(this, 1, value); - } - static fromObject(data: { - bytes?: Uint8Array; - }): esriShapeBuffer { - const message = new esriShapeBuffer({}); - if (data.bytes != null) { - message.bytes = data.bytes; - } - return message; - } - toObject() { - const data: { - bytes?: Uint8Array; - } = {}; - if (this.bytes != null) { - data.bytes = this.bytes; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.bytes.length) - writer.writeBytes(1, this.bytes); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): esriShapeBuffer { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new esriShapeBuffer(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.bytes = reader.readBytes(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): esriShapeBuffer { - return esriShapeBuffer.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + bytes?: Uint8Array; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("bytes" in data && data.bytes != undefined) { + this.bytes = data.bytes; + } + } + } + get bytes() { + return pb_1.Message.getFieldWithDefault(this, 1, new Uint8Array()) as Uint8Array; + } + set bytes(value: Uint8Array) { + pb_1.Message.setField(this, 1, value); + } + static fromObject(data: { + bytes?: Uint8Array; + }): esriShapeBuffer { + const message = new esriShapeBuffer({}); + if (data.bytes != null) { + message.bytes = data.bytes; + } + return message; + } + toObject() { + const data: { + bytes?: Uint8Array; + } = {}; + if (this.bytes != null) { + data.bytes = this.bytes; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.bytes.length) + writer.writeBytes(1, this.bytes); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): esriShapeBuffer { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new esriShapeBuffer(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.bytes = reader.readBytes(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): esriShapeBuffer { + return esriShapeBuffer.deserialize(bytes); + } } export class Feature extends pb_1.Message { - #one_of_decls: number[][] = [[2, 3]]; - constructor(data?: any[] | ({ + #one_of_decls: number[][] = [[2, 3]]; + constructor( + data?: + | any[] + | ( + & { attributes?: FeatureCollectionPBuffer.Value[]; centroid?: FeatureCollectionPBuffer.Geometry; - } & (({ + } + & (({ geometry?: FeatureCollectionPBuffer.Geometry; shapeBuffer?: never; } | { geometry?: never; shapeBuffer?: FeatureCollectionPBuffer.esriShapeBuffer; - })))) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("attributes" in data && data.attributes != undefined) { - this.attributes = data.attributes; - } - if ("geometry" in data && data.geometry != undefined) { - this.geometry = data.geometry; - } - if ("shapeBuffer" in data && data.shapeBuffer != undefined) { - this.shapeBuffer = data.shapeBuffer; - } - if ("centroid" in data && data.centroid != undefined) { - this.centroid = data.centroid; - } - } - } - get attributes() { - return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Value, 1) as FeatureCollectionPBuffer.Value[]; - } - set attributes(value: FeatureCollectionPBuffer.Value[]) { - pb_1.Message.setRepeatedWrapperField(this, 1, value); - } - get geometry() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Geometry, 2) as FeatureCollectionPBuffer.Geometry; - } - set geometry(value: FeatureCollectionPBuffer.Geometry) { - pb_1.Message.setOneofWrapperField(this, 2, this.#one_of_decls[0], value); - } - get has_geometry() { - return pb_1.Message.getField(this, 2) != null; - } - get shapeBuffer() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.esriShapeBuffer, 3) as FeatureCollectionPBuffer.esriShapeBuffer; - } - set shapeBuffer(value: FeatureCollectionPBuffer.esriShapeBuffer) { - pb_1.Message.setOneofWrapperField(this, 3, this.#one_of_decls[0], value); - } - get has_shapeBuffer() { - return pb_1.Message.getField(this, 3) != null; - } - get centroid() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Geometry, 4) as FeatureCollectionPBuffer.Geometry; - } - set centroid(value: FeatureCollectionPBuffer.Geometry) { - pb_1.Message.setWrapperField(this, 4, value); - } - get has_centroid() { - return pb_1.Message.getField(this, 4) != null; - } - get compressed_geometry() { - const cases: { - [index: number]: "none" | "geometry" | "shapeBuffer"; - } = { - 0: "none", - 2: "geometry", - 3: "shapeBuffer", - }; - return cases[pb_1.Message.computeOneofCase(this, [2, 3])]; - } - static fromObject(data: { - attributes?: ReturnType[]; - geometry?: ReturnType; - shapeBuffer?: ReturnType; - centroid?: ReturnType; - }): Feature { - const message = new Feature({}); - if (data.attributes != null) { - message.attributes = data.attributes.map((item) => FeatureCollectionPBuffer.Value.fromObject(item)); - } - if (data.geometry != null) { - message.geometry = FeatureCollectionPBuffer.Geometry.fromObject(data.geometry); - } - if (data.shapeBuffer != null) { - message.shapeBuffer = FeatureCollectionPBuffer.esriShapeBuffer.fromObject(data.shapeBuffer); - } - if (data.centroid != null) { - message.centroid = FeatureCollectionPBuffer.Geometry.fromObject(data.centroid); - } - return message; - } - toObject() { - const data: { - attributes?: ReturnType[]; - geometry?: ReturnType; - shapeBuffer?: ReturnType; - centroid?: ReturnType; - } = {}; - if (this.attributes != null) { - data.attributes = this.attributes.map((item: FeatureCollectionPBuffer.Value) => item.toObject()); - } - if (this.geometry != null) { - data.geometry = this.geometry.toObject(); - } - if (this.shapeBuffer != null) { - data.shapeBuffer = this.shapeBuffer.toObject(); - } - if (this.centroid != null) { - data.centroid = this.centroid.toObject(); - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.attributes.length) - writer.writeRepeatedMessage(1, this.attributes, (item: FeatureCollectionPBuffer.Value) => item.serialize(writer)); - if (this.has_geometry) - writer.writeMessage(2, this.geometry, () => this.geometry.serialize(writer)); - if (this.has_shapeBuffer) - writer.writeMessage(3, this.shapeBuffer, () => this.shapeBuffer.serialize(writer)); - if (this.has_centroid) - writer.writeMessage(4, this.centroid, () => this.centroid.serialize(writer)); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Feature { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Feature(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - reader.readMessage(message.attributes, () => pb_1.Message.addToRepeatedWrapperField(message, 1, FeatureCollectionPBuffer.Value.deserialize(reader), FeatureCollectionPBuffer.Value)); - break; - case 2: - reader.readMessage(message.geometry, () => message.geometry = FeatureCollectionPBuffer.Geometry.deserialize(reader)); - break; - case 3: - reader.readMessage(message.shapeBuffer, () => message.shapeBuffer = FeatureCollectionPBuffer.esriShapeBuffer.deserialize(reader)); - break; - case 4: - reader.readMessage(message.centroid, () => message.centroid = FeatureCollectionPBuffer.Geometry.deserialize(reader)); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Feature { - return Feature.deserialize(bytes); - } - } - export class UniqueIdField extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - name?: string; - isSystemMaintained?: boolean; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("name" in data && data.name != undefined) { - this.name = data.name; - } - if ("isSystemMaintained" in data && data.isSystemMaintained != undefined) { - this.isSystemMaintained = data.isSystemMaintained; - } - } - } - get name() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set name(value: string) { - pb_1.Message.setField(this, 1, value); - } - get isSystemMaintained() { - return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; - } - set isSystemMaintained(value: boolean) { - pb_1.Message.setField(this, 2, value); - } - static fromObject(data: { - name?: string; - isSystemMaintained?: boolean; - }): UniqueIdField { - const message = new UniqueIdField({}); - if (data.name != null) { - message.name = data.name; - } - if (data.isSystemMaintained != null) { - message.isSystemMaintained = data.isSystemMaintained; - } - return message; - } - toObject() { - const data: { - name?: string; - isSystemMaintained?: boolean; - } = {}; - if (this.name != null) { - data.name = this.name; - } - if (this.isSystemMaintained != null) { - data.isSystemMaintained = this.isSystemMaintained; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.name.length) - writer.writeString(1, this.name); - if (this.isSystemMaintained != false) - writer.writeBool(2, this.isSystemMaintained); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): UniqueIdField { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new UniqueIdField(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.name = reader.readString(); - break; - case 2: - message.isSystemMaintained = reader.readBool(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): UniqueIdField { - return UniqueIdField.deserialize(bytes); - } + })) + ), + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("attributes" in data && data.attributes != undefined) { + this.attributes = data.attributes; + } + if ("geometry" in data && data.geometry != undefined) { + this.geometry = data.geometry; + } + if ("shapeBuffer" in data && data.shapeBuffer != undefined) { + this.shapeBuffer = data.shapeBuffer; + } + if ("centroid" in data && data.centroid != undefined) { + this.centroid = data.centroid; + } + } + } + get attributes() { + return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Value, 1) as FeatureCollectionPBuffer.Value[]; + } + set attributes(value: FeatureCollectionPBuffer.Value[]) { + pb_1.Message.setRepeatedWrapperField(this, 1, value); + } + get geometry() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Geometry, 2) as FeatureCollectionPBuffer.Geometry; + } + set geometry(value: FeatureCollectionPBuffer.Geometry) { + pb_1.Message.setOneofWrapperField(this, 2, this.#one_of_decls[0], value); + } + get has_geometry() { + return pb_1.Message.getField(this, 2) != null; + } + get shapeBuffer() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.esriShapeBuffer, 3) as FeatureCollectionPBuffer.esriShapeBuffer; + } + set shapeBuffer(value: FeatureCollectionPBuffer.esriShapeBuffer) { + pb_1.Message.setOneofWrapperField(this, 3, this.#one_of_decls[0], value); + } + get has_shapeBuffer() { + return pb_1.Message.getField(this, 3) != null; + } + get centroid() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Geometry, 4) as FeatureCollectionPBuffer.Geometry; + } + set centroid(value: FeatureCollectionPBuffer.Geometry) { + pb_1.Message.setWrapperField(this, 4, value); + } + get has_centroid() { + return pb_1.Message.getField(this, 4) != null; + } + get compressed_geometry() { + const cases: { + [index: number]: "none" | "geometry" | "shapeBuffer"; + } = { + 0: "none", + 2: "geometry", + 3: "shapeBuffer", + }; + return cases[pb_1.Message.computeOneofCase(this, [2, 3])]; + } + static fromObject(data: { + attributes?: ReturnType[]; + geometry?: ReturnType; + shapeBuffer?: ReturnType; + centroid?: ReturnType; + }): Feature { + const message = new Feature({}); + if (data.attributes != null) { + message.attributes = data.attributes.map((item) => FeatureCollectionPBuffer.Value.fromObject(item)); + } + if (data.geometry != null) { + message.geometry = FeatureCollectionPBuffer.Geometry.fromObject(data.geometry); + } + if (data.shapeBuffer != null) { + message.shapeBuffer = FeatureCollectionPBuffer.esriShapeBuffer.fromObject(data.shapeBuffer); + } + if (data.centroid != null) { + message.centroid = FeatureCollectionPBuffer.Geometry.fromObject(data.centroid); + } + return message; + } + toObject() { + const data: { + attributes?: ReturnType[]; + geometry?: ReturnType; + shapeBuffer?: ReturnType; + centroid?: ReturnType; + } = {}; + if (this.attributes != null) { + data.attributes = this.attributes.map((item: FeatureCollectionPBuffer.Value) => item.toObject()); + } + if (this.geometry != null) { + data.geometry = this.geometry.toObject(); + } + if (this.shapeBuffer != null) { + data.shapeBuffer = this.shapeBuffer.toObject(); + } + if (this.centroid != null) { + data.centroid = this.centroid.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.attributes.length) + writer.writeRepeatedMessage(1, this.attributes, (item: FeatureCollectionPBuffer.Value) => item.serialize(writer)); + if (this.has_geometry) + writer.writeMessage(2, this.geometry, () => this.geometry.serialize(writer)); + if (this.has_shapeBuffer) + writer.writeMessage(3, this.shapeBuffer, () => this.shapeBuffer.serialize(writer)); + if (this.has_centroid) + writer.writeMessage(4, this.centroid, () => this.centroid.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Feature { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Feature(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage( + message.attributes, + () => + pb_1.Message.addToRepeatedWrapperField( + message, + 1, + FeatureCollectionPBuffer.Value.deserialize(reader), + FeatureCollectionPBuffer.Value, + ), + ); + break; + case 2: + reader.readMessage(message.geometry, () => message.geometry = FeatureCollectionPBuffer.Geometry.deserialize(reader)); + break; + case 3: + reader.readMessage(message.shapeBuffer, () => message.shapeBuffer = FeatureCollectionPBuffer.esriShapeBuffer.deserialize(reader)); + break; + case 4: + reader.readMessage(message.centroid, () => message.centroid = FeatureCollectionPBuffer.Geometry.deserialize(reader)); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Feature { + return Feature.deserialize(bytes); + } + } + export class UniqueIdField extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + name?: string; + isSystemMaintained?: boolean; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("name" in data && data.name != undefined) { + this.name = data.name; + } + if ("isSystemMaintained" in data && data.isSystemMaintained != undefined) { + this.isSystemMaintained = data.isSystemMaintained; + } + } + } + get name() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set name(value: string) { + pb_1.Message.setField(this, 1, value); + } + get isSystemMaintained() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set isSystemMaintained(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + name?: string; + isSystemMaintained?: boolean; + }): UniqueIdField { + const message = new UniqueIdField({}); + if (data.name != null) { + message.name = data.name; + } + if (data.isSystemMaintained != null) { + message.isSystemMaintained = data.isSystemMaintained; + } + return message; + } + toObject() { + const data: { + name?: string; + isSystemMaintained?: boolean; + } = {}; + if (this.name != null) { + data.name = this.name; + } + if (this.isSystemMaintained != null) { + data.isSystemMaintained = this.isSystemMaintained; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.name.length) + writer.writeString(1, this.name); + if (this.isSystemMaintained != false) + writer.writeBool(2, this.isSystemMaintained); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): UniqueIdField { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new UniqueIdField(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.name = reader.readString(); + break; + case 2: + message.isSystemMaintained = reader.readBool(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): UniqueIdField { + return UniqueIdField.deserialize(bytes); + } } export class GeometryProperties extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - shapeAreaFieldName?: string; - shapeLengthFieldName?: string; - units?: string; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("shapeAreaFieldName" in data && data.shapeAreaFieldName != undefined) { - this.shapeAreaFieldName = data.shapeAreaFieldName; - } - if ("shapeLengthFieldName" in data && data.shapeLengthFieldName != undefined) { - this.shapeLengthFieldName = data.shapeLengthFieldName; - } - if ("units" in data && data.units != undefined) { - this.units = data.units; - } - } - } - get shapeAreaFieldName() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set shapeAreaFieldName(value: string) { - pb_1.Message.setField(this, 1, value); - } - get shapeLengthFieldName() { - return pb_1.Message.getFieldWithDefault(this, 2, "") as string; - } - set shapeLengthFieldName(value: string) { - pb_1.Message.setField(this, 2, value); - } - get units() { - return pb_1.Message.getFieldWithDefault(this, 3, "") as string; - } - set units(value: string) { - pb_1.Message.setField(this, 3, value); - } - static fromObject(data: { - shapeAreaFieldName?: string; - shapeLengthFieldName?: string; - units?: string; - }): GeometryProperties { - const message = new GeometryProperties({}); - if (data.shapeAreaFieldName != null) { - message.shapeAreaFieldName = data.shapeAreaFieldName; - } - if (data.shapeLengthFieldName != null) { - message.shapeLengthFieldName = data.shapeLengthFieldName; - } - if (data.units != null) { - message.units = data.units; - } - return message; - } - toObject() { - const data: { - shapeAreaFieldName?: string; - shapeLengthFieldName?: string; - units?: string; - } = {}; - if (this.shapeAreaFieldName != null) { - data.shapeAreaFieldName = this.shapeAreaFieldName; - } - if (this.shapeLengthFieldName != null) { - data.shapeLengthFieldName = this.shapeLengthFieldName; - } - if (this.units != null) { - data.units = this.units; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.shapeAreaFieldName.length) - writer.writeString(1, this.shapeAreaFieldName); - if (this.shapeLengthFieldName.length) - writer.writeString(2, this.shapeLengthFieldName); - if (this.units.length) - writer.writeString(3, this.units); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): GeometryProperties { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new GeometryProperties(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.shapeAreaFieldName = reader.readString(); - break; - case 2: - message.shapeLengthFieldName = reader.readString(); - break; - case 3: - message.units = reader.readString(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): GeometryProperties { - return GeometryProperties.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + shapeAreaFieldName?: string; + shapeLengthFieldName?: string; + units?: string; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("shapeAreaFieldName" in data && data.shapeAreaFieldName != undefined) { + this.shapeAreaFieldName = data.shapeAreaFieldName; + } + if ("shapeLengthFieldName" in data && data.shapeLengthFieldName != undefined) { + this.shapeLengthFieldName = data.shapeLengthFieldName; + } + if ("units" in data && data.units != undefined) { + this.units = data.units; + } + } + } + get shapeAreaFieldName() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set shapeAreaFieldName(value: string) { + pb_1.Message.setField(this, 1, value); + } + get shapeLengthFieldName() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set shapeLengthFieldName(value: string) { + pb_1.Message.setField(this, 2, value); + } + get units() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set units(value: string) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + shapeAreaFieldName?: string; + shapeLengthFieldName?: string; + units?: string; + }): GeometryProperties { + const message = new GeometryProperties({}); + if (data.shapeAreaFieldName != null) { + message.shapeAreaFieldName = data.shapeAreaFieldName; + } + if (data.shapeLengthFieldName != null) { + message.shapeLengthFieldName = data.shapeLengthFieldName; + } + if (data.units != null) { + message.units = data.units; + } + return message; + } + toObject() { + const data: { + shapeAreaFieldName?: string; + shapeLengthFieldName?: string; + units?: string; + } = {}; + if (this.shapeAreaFieldName != null) { + data.shapeAreaFieldName = this.shapeAreaFieldName; + } + if (this.shapeLengthFieldName != null) { + data.shapeLengthFieldName = this.shapeLengthFieldName; + } + if (this.units != null) { + data.units = this.units; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.shapeAreaFieldName.length) + writer.writeString(1, this.shapeAreaFieldName); + if (this.shapeLengthFieldName.length) + writer.writeString(2, this.shapeLengthFieldName); + if (this.units.length) + writer.writeString(3, this.units); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): GeometryProperties { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new GeometryProperties(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.shapeAreaFieldName = reader.readString(); + break; + case 2: + message.shapeLengthFieldName = reader.readString(); + break; + case 3: + message.units = reader.readString(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): GeometryProperties { + return GeometryProperties.deserialize(bytes); + } } export class ServerGens extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - minServerGen?: number; - serverGen?: number; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("minServerGen" in data && data.minServerGen != undefined) { - this.minServerGen = data.minServerGen; - } - if ("serverGen" in data && data.serverGen != undefined) { - this.serverGen = data.serverGen; - } - } - } - get minServerGen() { - return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; - } - set minServerGen(value: number) { - pb_1.Message.setField(this, 1, value); - } - get serverGen() { - return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; - } - set serverGen(value: number) { - pb_1.Message.setField(this, 2, value); - } - static fromObject(data: { - minServerGen?: number; - serverGen?: number; - }): ServerGens { - const message = new ServerGens({}); - if (data.minServerGen != null) { - message.minServerGen = data.minServerGen; - } - if (data.serverGen != null) { - message.serverGen = data.serverGen; - } - return message; - } - toObject() { - const data: { - minServerGen?: number; - serverGen?: number; - } = {}; - if (this.minServerGen != null) { - data.minServerGen = this.minServerGen; - } - if (this.serverGen != null) { - data.serverGen = this.serverGen; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.minServerGen != 0) - writer.writeUint64(1, this.minServerGen); - if (this.serverGen != 0) - writer.writeUint64(2, this.serverGen); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ServerGens { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ServerGens(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.minServerGen = reader.readUint64(); - break; - case 2: - message.serverGen = reader.readUint64(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): ServerGens { - return ServerGens.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + minServerGen?: number; + serverGen?: number; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("minServerGen" in data && data.minServerGen != undefined) { + this.minServerGen = data.minServerGen; + } + if ("serverGen" in data && data.serverGen != undefined) { + this.serverGen = data.serverGen; + } + } + } + get minServerGen() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set minServerGen(value: number) { + pb_1.Message.setField(this, 1, value); + } + get serverGen() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set serverGen(value: number) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + minServerGen?: number; + serverGen?: number; + }): ServerGens { + const message = new ServerGens({}); + if (data.minServerGen != null) { + message.minServerGen = data.minServerGen; + } + if (data.serverGen != null) { + message.serverGen = data.serverGen; + } + return message; + } + toObject() { + const data: { + minServerGen?: number; + serverGen?: number; + } = {}; + if (this.minServerGen != null) { + data.minServerGen = this.minServerGen; + } + if (this.serverGen != null) { + data.serverGen = this.serverGen; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.minServerGen != 0) + writer.writeUint64(1, this.minServerGen); + if (this.serverGen != 0) + writer.writeUint64(2, this.serverGen); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ServerGens { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ServerGens(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.minServerGen = reader.readUint64(); + break; + case 2: + message.serverGen = reader.readUint64(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): ServerGens { + return ServerGens.deserialize(bytes); + } } export class Scale extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - xScale?: number; - yScale?: number; - mScale?: number; - zScale?: number; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("xScale" in data && data.xScale != undefined) { - this.xScale = data.xScale; - } - if ("yScale" in data && data.yScale != undefined) { - this.yScale = data.yScale; - } - if ("mScale" in data && data.mScale != undefined) { - this.mScale = data.mScale; - } - if ("zScale" in data && data.zScale != undefined) { - this.zScale = data.zScale; - } - } - } - get xScale() { - return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; - } - set xScale(value: number) { - pb_1.Message.setField(this, 1, value); - } - get yScale() { - return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; - } - set yScale(value: number) { - pb_1.Message.setField(this, 2, value); - } - get mScale() { - return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; - } - set mScale(value: number) { - pb_1.Message.setField(this, 3, value); - } - get zScale() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; - } - set zScale(value: number) { - pb_1.Message.setField(this, 4, value); - } - static fromObject(data: { - xScale?: number; - yScale?: number; - mScale?: number; - zScale?: number; - }): Scale { - const message = new Scale({}); - if (data.xScale != null) { - message.xScale = data.xScale; - } - if (data.yScale != null) { - message.yScale = data.yScale; - } - if (data.mScale != null) { - message.mScale = data.mScale; - } - if (data.zScale != null) { - message.zScale = data.zScale; - } - return message; - } - toObject() { - const data: { - xScale?: number; - yScale?: number; - mScale?: number; - zScale?: number; - } = {}; - if (this.xScale != null) { - data.xScale = this.xScale; - } - if (this.yScale != null) { - data.yScale = this.yScale; - } - if (this.mScale != null) { - data.mScale = this.mScale; - } - if (this.zScale != null) { - data.zScale = this.zScale; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.xScale != 0) - writer.writeDouble(1, this.xScale); - if (this.yScale != 0) - writer.writeDouble(2, this.yScale); - if (this.mScale != 0) - writer.writeDouble(3, this.mScale); - if (this.zScale != 0) - writer.writeDouble(4, this.zScale); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Scale { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Scale(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.xScale = reader.readDouble(); - break; - case 2: - message.yScale = reader.readDouble(); - break; - case 3: - message.mScale = reader.readDouble(); - break; - case 4: - message.zScale = reader.readDouble(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Scale { - return Scale.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + xScale?: number; + yScale?: number; + mScale?: number; + zScale?: number; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("xScale" in data && data.xScale != undefined) { + this.xScale = data.xScale; + } + if ("yScale" in data && data.yScale != undefined) { + this.yScale = data.yScale; + } + if ("mScale" in data && data.mScale != undefined) { + this.mScale = data.mScale; + } + if ("zScale" in data && data.zScale != undefined) { + this.zScale = data.zScale; + } + } + } + get xScale() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set xScale(value: number) { + pb_1.Message.setField(this, 1, value); + } + get yScale() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set yScale(value: number) { + pb_1.Message.setField(this, 2, value); + } + get mScale() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set mScale(value: number) { + pb_1.Message.setField(this, 3, value); + } + get zScale() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set zScale(value: number) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + xScale?: number; + yScale?: number; + mScale?: number; + zScale?: number; + }): Scale { + const message = new Scale({}); + if (data.xScale != null) { + message.xScale = data.xScale; + } + if (data.yScale != null) { + message.yScale = data.yScale; + } + if (data.mScale != null) { + message.mScale = data.mScale; + } + if (data.zScale != null) { + message.zScale = data.zScale; + } + return message; + } + toObject() { + const data: { + xScale?: number; + yScale?: number; + mScale?: number; + zScale?: number; + } = {}; + if (this.xScale != null) { + data.xScale = this.xScale; + } + if (this.yScale != null) { + data.yScale = this.yScale; + } + if (this.mScale != null) { + data.mScale = this.mScale; + } + if (this.zScale != null) { + data.zScale = this.zScale; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.xScale != 0) + writer.writeDouble(1, this.xScale); + if (this.yScale != 0) + writer.writeDouble(2, this.yScale); + if (this.mScale != 0) + writer.writeDouble(3, this.mScale); + if (this.zScale != 0) + writer.writeDouble(4, this.zScale); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Scale { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Scale(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.xScale = reader.readDouble(); + break; + case 2: + message.yScale = reader.readDouble(); + break; + case 3: + message.mScale = reader.readDouble(); + break; + case 4: + message.zScale = reader.readDouble(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Scale { + return Scale.deserialize(bytes); + } } export class Translate extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - xTranslate?: number; - yTranslate?: number; - mTranslate?: number; - zTranslate?: number; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("xTranslate" in data && data.xTranslate != undefined) { - this.xTranslate = data.xTranslate; - } - if ("yTranslate" in data && data.yTranslate != undefined) { - this.yTranslate = data.yTranslate; - } - if ("mTranslate" in data && data.mTranslate != undefined) { - this.mTranslate = data.mTranslate; - } - if ("zTranslate" in data && data.zTranslate != undefined) { - this.zTranslate = data.zTranslate; - } - } - } - get xTranslate() { - return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; - } - set xTranslate(value: number) { - pb_1.Message.setField(this, 1, value); - } - get yTranslate() { - return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; - } - set yTranslate(value: number) { - pb_1.Message.setField(this, 2, value); - } - get mTranslate() { - return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; - } - set mTranslate(value: number) { - pb_1.Message.setField(this, 3, value); - } - get zTranslate() { - return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; - } - set zTranslate(value: number) { - pb_1.Message.setField(this, 4, value); - } - static fromObject(data: { - xTranslate?: number; - yTranslate?: number; - mTranslate?: number; - zTranslate?: number; - }): Translate { - const message = new Translate({}); - if (data.xTranslate != null) { - message.xTranslate = data.xTranslate; - } - if (data.yTranslate != null) { - message.yTranslate = data.yTranslate; - } - if (data.mTranslate != null) { - message.mTranslate = data.mTranslate; - } - if (data.zTranslate != null) { - message.zTranslate = data.zTranslate; - } - return message; - } - toObject() { - const data: { - xTranslate?: number; - yTranslate?: number; - mTranslate?: number; - zTranslate?: number; - } = {}; - if (this.xTranslate != null) { - data.xTranslate = this.xTranslate; - } - if (this.yTranslate != null) { - data.yTranslate = this.yTranslate; - } - if (this.mTranslate != null) { - data.mTranslate = this.mTranslate; - } - if (this.zTranslate != null) { - data.zTranslate = this.zTranslate; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.xTranslate != 0) - writer.writeDouble(1, this.xTranslate); - if (this.yTranslate != 0) - writer.writeDouble(2, this.yTranslate); - if (this.mTranslate != 0) - writer.writeDouble(3, this.mTranslate); - if (this.zTranslate != 0) - writer.writeDouble(4, this.zTranslate); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Translate { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Translate(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.xTranslate = reader.readDouble(); - break; - case 2: - message.yTranslate = reader.readDouble(); - break; - case 3: - message.mTranslate = reader.readDouble(); - break; - case 4: - message.zTranslate = reader.readDouble(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Translate { - return Translate.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + xTranslate?: number; + yTranslate?: number; + mTranslate?: number; + zTranslate?: number; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("xTranslate" in data && data.xTranslate != undefined) { + this.xTranslate = data.xTranslate; + } + if ("yTranslate" in data && data.yTranslate != undefined) { + this.yTranslate = data.yTranslate; + } + if ("mTranslate" in data && data.mTranslate != undefined) { + this.mTranslate = data.mTranslate; + } + if ("zTranslate" in data && data.zTranslate != undefined) { + this.zTranslate = data.zTranslate; + } + } + } + get xTranslate() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set xTranslate(value: number) { + pb_1.Message.setField(this, 1, value); + } + get yTranslate() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set yTranslate(value: number) { + pb_1.Message.setField(this, 2, value); + } + get mTranslate() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set mTranslate(value: number) { + pb_1.Message.setField(this, 3, value); + } + get zTranslate() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set zTranslate(value: number) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + xTranslate?: number; + yTranslate?: number; + mTranslate?: number; + zTranslate?: number; + }): Translate { + const message = new Translate({}); + if (data.xTranslate != null) { + message.xTranslate = data.xTranslate; + } + if (data.yTranslate != null) { + message.yTranslate = data.yTranslate; + } + if (data.mTranslate != null) { + message.mTranslate = data.mTranslate; + } + if (data.zTranslate != null) { + message.zTranslate = data.zTranslate; + } + return message; + } + toObject() { + const data: { + xTranslate?: number; + yTranslate?: number; + mTranslate?: number; + zTranslate?: number; + } = {}; + if (this.xTranslate != null) { + data.xTranslate = this.xTranslate; + } + if (this.yTranslate != null) { + data.yTranslate = this.yTranslate; + } + if (this.mTranslate != null) { + data.mTranslate = this.mTranslate; + } + if (this.zTranslate != null) { + data.zTranslate = this.zTranslate; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.xTranslate != 0) + writer.writeDouble(1, this.xTranslate); + if (this.yTranslate != 0) + writer.writeDouble(2, this.yTranslate); + if (this.mTranslate != 0) + writer.writeDouble(3, this.mTranslate); + if (this.zTranslate != 0) + writer.writeDouble(4, this.zTranslate); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Translate { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Translate(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.xTranslate = reader.readDouble(); + break; + case 2: + message.yTranslate = reader.readDouble(); + break; + case 3: + message.mTranslate = reader.readDouble(); + break; + case 4: + message.zTranslate = reader.readDouble(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Translate { + return Translate.deserialize(bytes); + } } export class Transform extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; - scale?: FeatureCollectionPBuffer.Scale; - translate?: FeatureCollectionPBuffer.Translate; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("quantizeOriginPostion" in data && data.quantizeOriginPostion != undefined) { - this.quantizeOriginPostion = data.quantizeOriginPostion; - } - if ("scale" in data && data.scale != undefined) { - this.scale = data.scale; - } - if ("translate" in data && data.translate != undefined) { - this.translate = data.translate; - } - } - } - get quantizeOriginPostion() { - return pb_1.Message.getFieldWithDefault(this, 1, FeatureCollectionPBuffer.QuantizeOriginPostion.upperLeft) as FeatureCollectionPBuffer.QuantizeOriginPostion; - } - set quantizeOriginPostion(value: FeatureCollectionPBuffer.QuantizeOriginPostion) { - pb_1.Message.setField(this, 1, value); - } - get scale() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Scale, 2) as FeatureCollectionPBuffer.Scale; - } - set scale(value: FeatureCollectionPBuffer.Scale) { - pb_1.Message.setWrapperField(this, 2, value); - } - get has_scale() { - return pb_1.Message.getField(this, 2) != null; - } - get translate() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Translate, 3) as FeatureCollectionPBuffer.Translate; - } - set translate(value: FeatureCollectionPBuffer.Translate) { - pb_1.Message.setWrapperField(this, 3, value); - } - get has_translate() { - return pb_1.Message.getField(this, 3) != null; - } - static fromObject(data: { - quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; - scale?: ReturnType; - translate?: ReturnType; - }): Transform { - const message = new Transform({}); - if (data.quantizeOriginPostion != null) { - message.quantizeOriginPostion = data.quantizeOriginPostion; - } - if (data.scale != null) { - message.scale = FeatureCollectionPBuffer.Scale.fromObject(data.scale); - } - if (data.translate != null) { - message.translate = FeatureCollectionPBuffer.Translate.fromObject(data.translate); - } - return message; - } - toObject() { - const data: { - quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; - scale?: ReturnType; - translate?: ReturnType; - } = {}; - if (this.quantizeOriginPostion != null) { - data.quantizeOriginPostion = this.quantizeOriginPostion; - } - if (this.scale != null) { - data.scale = this.scale.toObject(); - } - if (this.translate != null) { - data.translate = this.translate.toObject(); - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.quantizeOriginPostion != FeatureCollectionPBuffer.QuantizeOriginPostion.upperLeft) - writer.writeEnum(1, this.quantizeOriginPostion); - if (this.has_scale) - writer.writeMessage(2, this.scale, () => this.scale.serialize(writer)); - if (this.has_translate) - writer.writeMessage(3, this.translate, () => this.translate.serialize(writer)); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Transform { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Transform(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.quantizeOriginPostion = reader.readEnum(); - break; - case 2: - reader.readMessage(message.scale, () => message.scale = FeatureCollectionPBuffer.Scale.deserialize(reader)); - break; - case 3: - reader.readMessage(message.translate, () => message.translate = FeatureCollectionPBuffer.Translate.deserialize(reader)); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): Transform { - return Transform.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; + scale?: FeatureCollectionPBuffer.Scale; + translate?: FeatureCollectionPBuffer.Translate; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("quantizeOriginPostion" in data && data.quantizeOriginPostion != undefined) { + this.quantizeOriginPostion = data.quantizeOriginPostion; + } + if ("scale" in data && data.scale != undefined) { + this.scale = data.scale; + } + if ("translate" in data && data.translate != undefined) { + this.translate = data.translate; + } + } + } + get quantizeOriginPostion() { + return pb_1.Message.getFieldWithDefault( + this, + 1, + FeatureCollectionPBuffer.QuantizeOriginPostion.upperLeft, + ) as FeatureCollectionPBuffer.QuantizeOriginPostion; + } + set quantizeOriginPostion(value: FeatureCollectionPBuffer.QuantizeOriginPostion) { + pb_1.Message.setField(this, 1, value); + } + get scale() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Scale, 2) as FeatureCollectionPBuffer.Scale; + } + set scale(value: FeatureCollectionPBuffer.Scale) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_scale() { + return pb_1.Message.getField(this, 2) != null; + } + get translate() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Translate, 3) as FeatureCollectionPBuffer.Translate; + } + set translate(value: FeatureCollectionPBuffer.Translate) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_translate() { + return pb_1.Message.getField(this, 3) != null; + } + static fromObject(data: { + quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; + scale?: ReturnType; + translate?: ReturnType; + }): Transform { + const message = new Transform({}); + if (data.quantizeOriginPostion != null) { + message.quantizeOriginPostion = data.quantizeOriginPostion; + } + if (data.scale != null) { + message.scale = FeatureCollectionPBuffer.Scale.fromObject(data.scale); + } + if (data.translate != null) { + message.translate = FeatureCollectionPBuffer.Translate.fromObject(data.translate); + } + return message; + } + toObject() { + const data: { + quantizeOriginPostion?: FeatureCollectionPBuffer.QuantizeOriginPostion; + scale?: ReturnType; + translate?: ReturnType; + } = {}; + if (this.quantizeOriginPostion != null) { + data.quantizeOriginPostion = this.quantizeOriginPostion; + } + if (this.scale != null) { + data.scale = this.scale.toObject(); + } + if (this.translate != null) { + data.translate = this.translate.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.quantizeOriginPostion != FeatureCollectionPBuffer.QuantizeOriginPostion.upperLeft) + writer.writeEnum(1, this.quantizeOriginPostion); + if (this.has_scale) + writer.writeMessage(2, this.scale, () => this.scale.serialize(writer)); + if (this.has_translate) + writer.writeMessage(3, this.translate, () => this.translate.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Transform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Transform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.quantizeOriginPostion = reader.readEnum(); + break; + case 2: + reader.readMessage(message.scale, () => message.scale = FeatureCollectionPBuffer.Scale.deserialize(reader)); + break; + case 3: + reader.readMessage(message.translate, () => message.translate = FeatureCollectionPBuffer.Translate.deserialize(reader)); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): Transform { + return Transform.deserialize(bytes); + } } export class FeatureResult extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - objectIdFieldName?: string; - uniqueIdField?: FeatureCollectionPBuffer.UniqueIdField; - globalIdFieldName?: string; - geohashFieldName?: string; - geometryProperties?: FeatureCollectionPBuffer.GeometryProperties; - serverGens?: FeatureCollectionPBuffer.ServerGens; - geometryType?: FeatureCollectionPBuffer.GeometryType; - spatialReference?: FeatureCollectionPBuffer.SpatialReference; - exceededTransferLimit?: boolean; - hasZ?: boolean; - hasM?: boolean; - transform?: FeatureCollectionPBuffer.Transform; - fields?: FeatureCollectionPBuffer.Field[]; - values?: FeatureCollectionPBuffer.Value[]; - features?: FeatureCollectionPBuffer.Feature[]; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [13, 14, 15], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("objectIdFieldName" in data && data.objectIdFieldName != undefined) { - this.objectIdFieldName = data.objectIdFieldName; - } - if ("uniqueIdField" in data && data.uniqueIdField != undefined) { - this.uniqueIdField = data.uniqueIdField; - } - if ("globalIdFieldName" in data && data.globalIdFieldName != undefined) { - this.globalIdFieldName = data.globalIdFieldName; - } - if ("geohashFieldName" in data && data.geohashFieldName != undefined) { - this.geohashFieldName = data.geohashFieldName; - } - if ("geometryProperties" in data && data.geometryProperties != undefined) { - this.geometryProperties = data.geometryProperties; - } - if ("serverGens" in data && data.serverGens != undefined) { - this.serverGens = data.serverGens; - } - if ("geometryType" in data && data.geometryType != undefined) { - this.geometryType = data.geometryType; - } - if ("spatialReference" in data && data.spatialReference != undefined) { - this.spatialReference = data.spatialReference; - } - if ("exceededTransferLimit" in data && data.exceededTransferLimit != undefined) { - this.exceededTransferLimit = data.exceededTransferLimit; - } - if ("hasZ" in data && data.hasZ != undefined) { - this.hasZ = data.hasZ; - } - if ("hasM" in data && data.hasM != undefined) { - this.hasM = data.hasM; - } - if ("transform" in data && data.transform != undefined) { - this.transform = data.transform; - } - if ("fields" in data && data.fields != undefined) { - this.fields = data.fields; - } - if ("values" in data && data.values != undefined) { - this.values = data.values; - } - if ("features" in data && data.features != undefined) { - this.features = data.features; - } - } - } - get objectIdFieldName() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set objectIdFieldName(value: string) { - pb_1.Message.setField(this, 1, value); - } - get uniqueIdField() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.UniqueIdField, 2) as FeatureCollectionPBuffer.UniqueIdField; - } - set uniqueIdField(value: FeatureCollectionPBuffer.UniqueIdField) { - pb_1.Message.setWrapperField(this, 2, value); - } - get has_uniqueIdField() { - return pb_1.Message.getField(this, 2) != null; - } - get globalIdFieldName() { - return pb_1.Message.getFieldWithDefault(this, 3, "") as string; - } - set globalIdFieldName(value: string) { - pb_1.Message.setField(this, 3, value); - } - get geohashFieldName() { - return pb_1.Message.getFieldWithDefault(this, 4, "") as string; - } - set geohashFieldName(value: string) { - pb_1.Message.setField(this, 4, value); - } - get geometryProperties() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.GeometryProperties, 5) as FeatureCollectionPBuffer.GeometryProperties; - } - set geometryProperties(value: FeatureCollectionPBuffer.GeometryProperties) { - pb_1.Message.setWrapperField(this, 5, value); - } - get has_geometryProperties() { - return pb_1.Message.getField(this, 5) != null; - } - get serverGens() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ServerGens, 6) as FeatureCollectionPBuffer.ServerGens; - } - set serverGens(value: FeatureCollectionPBuffer.ServerGens) { - pb_1.Message.setWrapperField(this, 6, value); - } - get has_serverGens() { - return pb_1.Message.getField(this, 6) != null; - } - get geometryType() { - return pb_1.Message.getFieldWithDefault(this, 7, FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint) as FeatureCollectionPBuffer.GeometryType; - } - set geometryType(value: FeatureCollectionPBuffer.GeometryType) { - pb_1.Message.setField(this, 7, value); - } - get spatialReference() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.SpatialReference, 8) as FeatureCollectionPBuffer.SpatialReference; - } - set spatialReference(value: FeatureCollectionPBuffer.SpatialReference) { - pb_1.Message.setWrapperField(this, 8, value); - } - get has_spatialReference() { - return pb_1.Message.getField(this, 8) != null; - } - get exceededTransferLimit() { - return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; - } - set exceededTransferLimit(value: boolean) { - pb_1.Message.setField(this, 9, value); - } - get hasZ() { - return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; - } - set hasZ(value: boolean) { - pb_1.Message.setField(this, 10, value); - } - get hasM() { - return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; - } - set hasM(value: boolean) { - pb_1.Message.setField(this, 11, value); - } - get transform() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Transform, 12) as FeatureCollectionPBuffer.Transform; - } - set transform(value: FeatureCollectionPBuffer.Transform) { - pb_1.Message.setWrapperField(this, 12, value); - } - get has_transform() { - return pb_1.Message.getField(this, 12) != null; - } - get fields() { - return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Field, 13) as FeatureCollectionPBuffer.Field[]; - } - set fields(value: FeatureCollectionPBuffer.Field[]) { - pb_1.Message.setRepeatedWrapperField(this, 13, value); - } - get values() { - return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Value, 14) as FeatureCollectionPBuffer.Value[]; - } - set values(value: FeatureCollectionPBuffer.Value[]) { - pb_1.Message.setRepeatedWrapperField(this, 14, value); - } - get features() { - return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Feature, 15) as FeatureCollectionPBuffer.Feature[]; - } - set features(value: FeatureCollectionPBuffer.Feature[]) { - pb_1.Message.setRepeatedWrapperField(this, 15, value); - } - static fromObject(data: { - objectIdFieldName?: string; - uniqueIdField?: ReturnType; - globalIdFieldName?: string; - geohashFieldName?: string; - geometryProperties?: ReturnType; - serverGens?: ReturnType; - geometryType?: FeatureCollectionPBuffer.GeometryType; - spatialReference?: ReturnType; - exceededTransferLimit?: boolean; - hasZ?: boolean; - hasM?: boolean; - transform?: ReturnType; - fields?: ReturnType[]; - values?: ReturnType[]; - features?: ReturnType[]; - }): FeatureResult { - const message = new FeatureResult({}); - if (data.objectIdFieldName != null) { - message.objectIdFieldName = data.objectIdFieldName; - } - if (data.uniqueIdField != null) { - message.uniqueIdField = FeatureCollectionPBuffer.UniqueIdField.fromObject(data.uniqueIdField); - } - if (data.globalIdFieldName != null) { - message.globalIdFieldName = data.globalIdFieldName; - } - if (data.geohashFieldName != null) { - message.geohashFieldName = data.geohashFieldName; - } - if (data.geometryProperties != null) { - message.geometryProperties = FeatureCollectionPBuffer.GeometryProperties.fromObject(data.geometryProperties); - } - if (data.serverGens != null) { - message.serverGens = FeatureCollectionPBuffer.ServerGens.fromObject(data.serverGens); - } - if (data.geometryType != null) { - message.geometryType = data.geometryType; - } - if (data.spatialReference != null) { - message.spatialReference = FeatureCollectionPBuffer.SpatialReference.fromObject(data.spatialReference); - } - if (data.exceededTransferLimit != null) { - message.exceededTransferLimit = data.exceededTransferLimit; - } - if (data.hasZ != null) { - message.hasZ = data.hasZ; - } - if (data.hasM != null) { - message.hasM = data.hasM; - } - if (data.transform != null) { - message.transform = FeatureCollectionPBuffer.Transform.fromObject(data.transform); - } - if (data.fields != null) { - message.fields = data.fields.map((item) => FeatureCollectionPBuffer.Field.fromObject(item)); - } - if (data.values != null) { - message.values = data.values.map((item) => FeatureCollectionPBuffer.Value.fromObject(item)); - } - if (data.features != null) { - message.features = data.features.map((item) => FeatureCollectionPBuffer.Feature.fromObject(item)); - } - return message; - } - toObject() { - const data: { - objectIdFieldName?: string; - uniqueIdField?: ReturnType; - globalIdFieldName?: string; - geohashFieldName?: string; - geometryProperties?: ReturnType; - serverGens?: ReturnType; - geometryType?: FeatureCollectionPBuffer.GeometryType; - spatialReference?: ReturnType; - exceededTransferLimit?: boolean; - hasZ?: boolean; - hasM?: boolean; - transform?: ReturnType; - fields?: ReturnType[]; - values?: ReturnType[]; - features?: ReturnType[]; - } = {}; - if (this.objectIdFieldName != null) { - data.objectIdFieldName = this.objectIdFieldName; - } - if (this.uniqueIdField != null) { - data.uniqueIdField = this.uniqueIdField.toObject(); - } - if (this.globalIdFieldName != null) { - data.globalIdFieldName = this.globalIdFieldName; - } - if (this.geohashFieldName != null) { - data.geohashFieldName = this.geohashFieldName; - } - if (this.geometryProperties != null) { - data.geometryProperties = this.geometryProperties.toObject(); - } - if (this.serverGens != null) { - data.serverGens = this.serverGens.toObject(); - } - if (this.geometryType != null) { - data.geometryType = this.geometryType; - } - if (this.spatialReference != null) { - data.spatialReference = this.spatialReference.toObject(); - } - if (this.exceededTransferLimit != null) { - data.exceededTransferLimit = this.exceededTransferLimit; - } - if (this.hasZ != null) { - data.hasZ = this.hasZ; - } - if (this.hasM != null) { - data.hasM = this.hasM; - } - if (this.transform != null) { - data.transform = this.transform.toObject(); - } - if (this.fields != null) { - data.fields = this.fields.map((item: FeatureCollectionPBuffer.Field) => item.toObject()); - } - if (this.values != null) { - data.values = this.values.map((item: FeatureCollectionPBuffer.Value) => item.toObject()); - } - if (this.features != null) { - data.features = this.features.map((item: FeatureCollectionPBuffer.Feature) => item.toObject()); - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.objectIdFieldName.length) - writer.writeString(1, this.objectIdFieldName); - if (this.has_uniqueIdField) - writer.writeMessage(2, this.uniqueIdField, () => this.uniqueIdField.serialize(writer)); - if (this.globalIdFieldName.length) - writer.writeString(3, this.globalIdFieldName); - if (this.geohashFieldName.length) - writer.writeString(4, this.geohashFieldName); - if (this.has_geometryProperties) - writer.writeMessage(5, this.geometryProperties, () => this.geometryProperties.serialize(writer)); - if (this.has_serverGens) - writer.writeMessage(6, this.serverGens, () => this.serverGens.serialize(writer)); - if (this.geometryType != FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint) - writer.writeEnum(7, this.geometryType); - if (this.has_spatialReference) - writer.writeMessage(8, this.spatialReference, () => this.spatialReference.serialize(writer)); - if (this.exceededTransferLimit != false) - writer.writeBool(9, this.exceededTransferLimit); - if (this.hasZ != false) - writer.writeBool(10, this.hasZ); - if (this.hasM != false) - writer.writeBool(11, this.hasM); - if (this.has_transform) - writer.writeMessage(12, this.transform, () => this.transform.serialize(writer)); - if (this.fields.length) - writer.writeRepeatedMessage(13, this.fields, (item: FeatureCollectionPBuffer.Field) => item.serialize(writer)); - if (this.values.length) - writer.writeRepeatedMessage(14, this.values, (item: FeatureCollectionPBuffer.Value) => item.serialize(writer)); - if (this.features.length) - writer.writeRepeatedMessage(15, this.features, (item: FeatureCollectionPBuffer.Feature) => item.serialize(writer)); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): FeatureResult { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new FeatureResult(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.objectIdFieldName = reader.readString(); - break; - case 2: - reader.readMessage(message.uniqueIdField, () => message.uniqueIdField = FeatureCollectionPBuffer.UniqueIdField.deserialize(reader)); - break; - case 3: - message.globalIdFieldName = reader.readString(); - break; - case 4: - message.geohashFieldName = reader.readString(); - break; - case 5: - reader.readMessage(message.geometryProperties, () => message.geometryProperties = FeatureCollectionPBuffer.GeometryProperties.deserialize(reader)); - break; - case 6: - reader.readMessage(message.serverGens, () => message.serverGens = FeatureCollectionPBuffer.ServerGens.deserialize(reader)); - break; - case 7: - message.geometryType = reader.readEnum(); - break; - case 8: - reader.readMessage(message.spatialReference, () => message.spatialReference = FeatureCollectionPBuffer.SpatialReference.deserialize(reader)); - break; - case 9: - message.exceededTransferLimit = reader.readBool(); - break; - case 10: - message.hasZ = reader.readBool(); - break; - case 11: - message.hasM = reader.readBool(); - break; - case 12: - reader.readMessage(message.transform, () => message.transform = FeatureCollectionPBuffer.Transform.deserialize(reader)); - break; - case 13: - reader.readMessage(message.fields, () => pb_1.Message.addToRepeatedWrapperField(message, 13, FeatureCollectionPBuffer.Field.deserialize(reader), FeatureCollectionPBuffer.Field)); - break; - case 14: - reader.readMessage(message.values, () => pb_1.Message.addToRepeatedWrapperField(message, 14, FeatureCollectionPBuffer.Value.deserialize(reader), FeatureCollectionPBuffer.Value)); - break; - case 15: - reader.readMessage(message.features, () => pb_1.Message.addToRepeatedWrapperField(message, 15, FeatureCollectionPBuffer.Feature.deserialize(reader), FeatureCollectionPBuffer.Feature)); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): FeatureResult { - return FeatureResult.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + objectIdFieldName?: string; + uniqueIdField?: FeatureCollectionPBuffer.UniqueIdField; + globalIdFieldName?: string; + geohashFieldName?: string; + geometryProperties?: FeatureCollectionPBuffer.GeometryProperties; + serverGens?: FeatureCollectionPBuffer.ServerGens; + geometryType?: FeatureCollectionPBuffer.GeometryType; + spatialReference?: FeatureCollectionPBuffer.SpatialReference; + exceededTransferLimit?: boolean; + hasZ?: boolean; + hasM?: boolean; + transform?: FeatureCollectionPBuffer.Transform; + fields?: FeatureCollectionPBuffer.Field[]; + values?: FeatureCollectionPBuffer.Value[]; + features?: FeatureCollectionPBuffer.Feature[]; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [13, 14, 15], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("objectIdFieldName" in data && data.objectIdFieldName != undefined) { + this.objectIdFieldName = data.objectIdFieldName; + } + if ("uniqueIdField" in data && data.uniqueIdField != undefined) { + this.uniqueIdField = data.uniqueIdField; + } + if ("globalIdFieldName" in data && data.globalIdFieldName != undefined) { + this.globalIdFieldName = data.globalIdFieldName; + } + if ("geohashFieldName" in data && data.geohashFieldName != undefined) { + this.geohashFieldName = data.geohashFieldName; + } + if ("geometryProperties" in data && data.geometryProperties != undefined) { + this.geometryProperties = data.geometryProperties; + } + if ("serverGens" in data && data.serverGens != undefined) { + this.serverGens = data.serverGens; + } + if ("geometryType" in data && data.geometryType != undefined) { + this.geometryType = data.geometryType; + } + if ("spatialReference" in data && data.spatialReference != undefined) { + this.spatialReference = data.spatialReference; + } + if ("exceededTransferLimit" in data && data.exceededTransferLimit != undefined) { + this.exceededTransferLimit = data.exceededTransferLimit; + } + if ("hasZ" in data && data.hasZ != undefined) { + this.hasZ = data.hasZ; + } + if ("hasM" in data && data.hasM != undefined) { + this.hasM = data.hasM; + } + if ("transform" in data && data.transform != undefined) { + this.transform = data.transform; + } + if ("fields" in data && data.fields != undefined) { + this.fields = data.fields; + } + if ("values" in data && data.values != undefined) { + this.values = data.values; + } + if ("features" in data && data.features != undefined) { + this.features = data.features; + } + } + } + get objectIdFieldName() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set objectIdFieldName(value: string) { + pb_1.Message.setField(this, 1, value); + } + get uniqueIdField() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.UniqueIdField, 2) as FeatureCollectionPBuffer.UniqueIdField; + } + set uniqueIdField(value: FeatureCollectionPBuffer.UniqueIdField) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_uniqueIdField() { + return pb_1.Message.getField(this, 2) != null; + } + get globalIdFieldName() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set globalIdFieldName(value: string) { + pb_1.Message.setField(this, 3, value); + } + get geohashFieldName() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set geohashFieldName(value: string) { + pb_1.Message.setField(this, 4, value); + } + get geometryProperties() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.GeometryProperties, 5) as FeatureCollectionPBuffer.GeometryProperties; + } + set geometryProperties(value: FeatureCollectionPBuffer.GeometryProperties) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_geometryProperties() { + return pb_1.Message.getField(this, 5) != null; + } + get serverGens() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ServerGens, 6) as FeatureCollectionPBuffer.ServerGens; + } + set serverGens(value: FeatureCollectionPBuffer.ServerGens) { + pb_1.Message.setWrapperField(this, 6, value); + } + get has_serverGens() { + return pb_1.Message.getField(this, 6) != null; + } + get geometryType() { + return pb_1.Message.getFieldWithDefault( + this, + 7, + FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint, + ) as FeatureCollectionPBuffer.GeometryType; + } + set geometryType(value: FeatureCollectionPBuffer.GeometryType) { + pb_1.Message.setField(this, 7, value); + } + get spatialReference() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.SpatialReference, 8) as FeatureCollectionPBuffer.SpatialReference; + } + set spatialReference(value: FeatureCollectionPBuffer.SpatialReference) { + pb_1.Message.setWrapperField(this, 8, value); + } + get has_spatialReference() { + return pb_1.Message.getField(this, 8) != null; + } + get exceededTransferLimit() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set exceededTransferLimit(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get hasZ() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set hasZ(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get hasM() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set hasM(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get transform() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.Transform, 12) as FeatureCollectionPBuffer.Transform; + } + set transform(value: FeatureCollectionPBuffer.Transform) { + pb_1.Message.setWrapperField(this, 12, value); + } + get has_transform() { + return pb_1.Message.getField(this, 12) != null; + } + get fields() { + return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Field, 13) as FeatureCollectionPBuffer.Field[]; + } + set fields(value: FeatureCollectionPBuffer.Field[]) { + pb_1.Message.setRepeatedWrapperField(this, 13, value); + } + get values() { + return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Value, 14) as FeatureCollectionPBuffer.Value[]; + } + set values(value: FeatureCollectionPBuffer.Value[]) { + pb_1.Message.setRepeatedWrapperField(this, 14, value); + } + get features() { + return pb_1.Message.getRepeatedWrapperField(this, FeatureCollectionPBuffer.Feature, 15) as FeatureCollectionPBuffer.Feature[]; + } + set features(value: FeatureCollectionPBuffer.Feature[]) { + pb_1.Message.setRepeatedWrapperField(this, 15, value); + } + static fromObject(data: { + objectIdFieldName?: string; + uniqueIdField?: ReturnType; + globalIdFieldName?: string; + geohashFieldName?: string; + geometryProperties?: ReturnType; + serverGens?: ReturnType; + geometryType?: FeatureCollectionPBuffer.GeometryType; + spatialReference?: ReturnType; + exceededTransferLimit?: boolean; + hasZ?: boolean; + hasM?: boolean; + transform?: ReturnType; + fields?: ReturnType[]; + values?: ReturnType[]; + features?: ReturnType[]; + }): FeatureResult { + const message = new FeatureResult({}); + if (data.objectIdFieldName != null) { + message.objectIdFieldName = data.objectIdFieldName; + } + if (data.uniqueIdField != null) { + message.uniqueIdField = FeatureCollectionPBuffer.UniqueIdField.fromObject(data.uniqueIdField); + } + if (data.globalIdFieldName != null) { + message.globalIdFieldName = data.globalIdFieldName; + } + if (data.geohashFieldName != null) { + message.geohashFieldName = data.geohashFieldName; + } + if (data.geometryProperties != null) { + message.geometryProperties = FeatureCollectionPBuffer.GeometryProperties.fromObject(data.geometryProperties); + } + if (data.serverGens != null) { + message.serverGens = FeatureCollectionPBuffer.ServerGens.fromObject(data.serverGens); + } + if (data.geometryType != null) { + message.geometryType = data.geometryType; + } + if (data.spatialReference != null) { + message.spatialReference = FeatureCollectionPBuffer.SpatialReference.fromObject(data.spatialReference); + } + if (data.exceededTransferLimit != null) { + message.exceededTransferLimit = data.exceededTransferLimit; + } + if (data.hasZ != null) { + message.hasZ = data.hasZ; + } + if (data.hasM != null) { + message.hasM = data.hasM; + } + if (data.transform != null) { + message.transform = FeatureCollectionPBuffer.Transform.fromObject(data.transform); + } + if (data.fields != null) { + message.fields = data.fields.map((item) => FeatureCollectionPBuffer.Field.fromObject(item)); + } + if (data.values != null) { + message.values = data.values.map((item) => FeatureCollectionPBuffer.Value.fromObject(item)); + } + if (data.features != null) { + message.features = data.features.map((item) => FeatureCollectionPBuffer.Feature.fromObject(item)); + } + return message; + } + toObject() { + const data: { + objectIdFieldName?: string; + uniqueIdField?: ReturnType; + globalIdFieldName?: string; + geohashFieldName?: string; + geometryProperties?: ReturnType; + serverGens?: ReturnType; + geometryType?: FeatureCollectionPBuffer.GeometryType; + spatialReference?: ReturnType; + exceededTransferLimit?: boolean; + hasZ?: boolean; + hasM?: boolean; + transform?: ReturnType; + fields?: ReturnType[]; + values?: ReturnType[]; + features?: ReturnType[]; + } = {}; + if (this.objectIdFieldName != null) { + data.objectIdFieldName = this.objectIdFieldName; + } + if (this.uniqueIdField != null) { + data.uniqueIdField = this.uniqueIdField.toObject(); + } + if (this.globalIdFieldName != null) { + data.globalIdFieldName = this.globalIdFieldName; + } + if (this.geohashFieldName != null) { + data.geohashFieldName = this.geohashFieldName; + } + if (this.geometryProperties != null) { + data.geometryProperties = this.geometryProperties.toObject(); + } + if (this.serverGens != null) { + data.serverGens = this.serverGens.toObject(); + } + if (this.geometryType != null) { + data.geometryType = this.geometryType; + } + if (this.spatialReference != null) { + data.spatialReference = this.spatialReference.toObject(); + } + if (this.exceededTransferLimit != null) { + data.exceededTransferLimit = this.exceededTransferLimit; + } + if (this.hasZ != null) { + data.hasZ = this.hasZ; + } + if (this.hasM != null) { + data.hasM = this.hasM; + } + if (this.transform != null) { + data.transform = this.transform.toObject(); + } + if (this.fields != null) { + data.fields = this.fields.map((item: FeatureCollectionPBuffer.Field) => item.toObject()); + } + if (this.values != null) { + data.values = this.values.map((item: FeatureCollectionPBuffer.Value) => item.toObject()); + } + if (this.features != null) { + data.features = this.features.map((item: FeatureCollectionPBuffer.Feature) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.objectIdFieldName.length) + writer.writeString(1, this.objectIdFieldName); + if (this.has_uniqueIdField) + writer.writeMessage(2, this.uniqueIdField, () => this.uniqueIdField.serialize(writer)); + if (this.globalIdFieldName.length) + writer.writeString(3, this.globalIdFieldName); + if (this.geohashFieldName.length) + writer.writeString(4, this.geohashFieldName); + if (this.has_geometryProperties) + writer.writeMessage(5, this.geometryProperties, () => this.geometryProperties.serialize(writer)); + if (this.has_serverGens) + writer.writeMessage(6, this.serverGens, () => this.serverGens.serialize(writer)); + if (this.geometryType != FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint) + writer.writeEnum(7, this.geometryType); + if (this.has_spatialReference) + writer.writeMessage(8, this.spatialReference, () => this.spatialReference.serialize(writer)); + if (this.exceededTransferLimit != false) + writer.writeBool(9, this.exceededTransferLimit); + if (this.hasZ != false) + writer.writeBool(10, this.hasZ); + if (this.hasM != false) + writer.writeBool(11, this.hasM); + if (this.has_transform) + writer.writeMessage(12, this.transform, () => this.transform.serialize(writer)); + if (this.fields.length) + writer.writeRepeatedMessage(13, this.fields, (item: FeatureCollectionPBuffer.Field) => item.serialize(writer)); + if (this.values.length) + writer.writeRepeatedMessage(14, this.values, (item: FeatureCollectionPBuffer.Value) => item.serialize(writer)); + if (this.features.length) + writer.writeRepeatedMessage(15, this.features, (item: FeatureCollectionPBuffer.Feature) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): FeatureResult { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new FeatureResult(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.objectIdFieldName = reader.readString(); + break; + case 2: + reader.readMessage(message.uniqueIdField, () => message.uniqueIdField = FeatureCollectionPBuffer.UniqueIdField.deserialize(reader)); + break; + case 3: + message.globalIdFieldName = reader.readString(); + break; + case 4: + message.geohashFieldName = reader.readString(); + break; + case 5: + reader.readMessage( + message.geometryProperties, + () => message.geometryProperties = FeatureCollectionPBuffer.GeometryProperties.deserialize(reader), + ); + break; + case 6: + reader.readMessage(message.serverGens, () => message.serverGens = FeatureCollectionPBuffer.ServerGens.deserialize(reader)); + break; + case 7: + message.geometryType = reader.readEnum(); + break; + case 8: + reader.readMessage( + message.spatialReference, + () => message.spatialReference = FeatureCollectionPBuffer.SpatialReference.deserialize(reader), + ); + break; + case 9: + message.exceededTransferLimit = reader.readBool(); + break; + case 10: + message.hasZ = reader.readBool(); + break; + case 11: + message.hasM = reader.readBool(); + break; + case 12: + reader.readMessage(message.transform, () => message.transform = FeatureCollectionPBuffer.Transform.deserialize(reader)); + break; + case 13: + reader.readMessage( + message.fields, + () => + pb_1.Message.addToRepeatedWrapperField( + message, + 13, + FeatureCollectionPBuffer.Field.deserialize(reader), + FeatureCollectionPBuffer.Field, + ), + ); + break; + case 14: + reader.readMessage( + message.values, + () => + pb_1.Message.addToRepeatedWrapperField( + message, + 14, + FeatureCollectionPBuffer.Value.deserialize(reader), + FeatureCollectionPBuffer.Value, + ), + ); + break; + case 15: + reader.readMessage( + message.features, + () => + pb_1.Message.addToRepeatedWrapperField( + message, + 15, + FeatureCollectionPBuffer.Feature.deserialize(reader), + FeatureCollectionPBuffer.Feature, + ), + ); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): FeatureResult { + return FeatureResult.deserialize(bytes); + } } export class CountResult extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - count?: number; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("count" in data && data.count != undefined) { - this.count = data.count; - } - } - } - get count() { - return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; - } - set count(value: number) { - pb_1.Message.setField(this, 1, value); - } - static fromObject(data: { - count?: number; - }): CountResult { - const message = new CountResult({}); - if (data.count != null) { - message.count = data.count; - } - return message; - } - toObject() { - const data: { - count?: number; - } = {}; - if (this.count != null) { - data.count = this.count; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.count != 0) - writer.writeUint64(1, this.count); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): CountResult { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new CountResult(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.count = reader.readUint64(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): CountResult { - return CountResult.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + count?: number; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("count" in data && data.count != undefined) { + this.count = data.count; + } + } + } + get count() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set count(value: number) { + pb_1.Message.setField(this, 1, value); + } + static fromObject(data: { + count?: number; + }): CountResult { + const message = new CountResult({}); + if (data.count != null) { + message.count = data.count; + } + return message; + } + toObject() { + const data: { + count?: number; + } = {}; + if (this.count != null) { + data.count = this.count; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.count != 0) + writer.writeUint64(1, this.count); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): CountResult { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new CountResult(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.count = reader.readUint64(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): CountResult { + return CountResult.deserialize(bytes); + } } export class ObjectIdsResult extends pb_1.Message { - #one_of_decls: number[][] = []; - constructor(data?: any[] | { - objectIdFieldName?: string; - serverGens?: FeatureCollectionPBuffer.ServerGens; - objectIds?: number[]; - }) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("objectIdFieldName" in data && data.objectIdFieldName != undefined) { - this.objectIdFieldName = data.objectIdFieldName; - } - if ("serverGens" in data && data.serverGens != undefined) { - this.serverGens = data.serverGens; - } - if ("objectIds" in data && data.objectIds != undefined) { - this.objectIds = data.objectIds; - } - } - } - get objectIdFieldName() { - return pb_1.Message.getFieldWithDefault(this, 1, "") as string; - } - set objectIdFieldName(value: string) { - pb_1.Message.setField(this, 1, value); - } - get serverGens() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ServerGens, 2) as FeatureCollectionPBuffer.ServerGens; - } - set serverGens(value: FeatureCollectionPBuffer.ServerGens) { - pb_1.Message.setWrapperField(this, 2, value); - } - get has_serverGens() { - return pb_1.Message.getField(this, 2) != null; - } - get objectIds() { - return pb_1.Message.getFieldWithDefault(this, 3, []) as number[]; - } - set objectIds(value: number[]) { - pb_1.Message.setField(this, 3, value); - } - static fromObject(data: { - objectIdFieldName?: string; - serverGens?: ReturnType; - objectIds?: number[]; - }): ObjectIdsResult { - const message = new ObjectIdsResult({}); - if (data.objectIdFieldName != null) { - message.objectIdFieldName = data.objectIdFieldName; - } - if (data.serverGens != null) { - message.serverGens = FeatureCollectionPBuffer.ServerGens.fromObject(data.serverGens); - } - if (data.objectIds != null) { - message.objectIds = data.objectIds; - } - return message; - } - toObject() { - const data: { - objectIdFieldName?: string; - serverGens?: ReturnType; - objectIds?: number[]; - } = {}; - if (this.objectIdFieldName != null) { - data.objectIdFieldName = this.objectIdFieldName; - } - if (this.serverGens != null) { - data.serverGens = this.serverGens.toObject(); - } - if (this.objectIds != null) { - data.objectIds = this.objectIds; - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.objectIdFieldName.length) - writer.writeString(1, this.objectIdFieldName); - if (this.has_serverGens) - writer.writeMessage(2, this.serverGens, () => this.serverGens.serialize(writer)); - if (this.objectIds.length) - writer.writePackedUint64(3, this.objectIds); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ObjectIdsResult { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ObjectIdsResult(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - message.objectIdFieldName = reader.readString(); - break; - case 2: - reader.readMessage(message.serverGens, () => message.serverGens = FeatureCollectionPBuffer.ServerGens.deserialize(reader)); - break; - case 3: - message.objectIds = reader.readPackedUint64(); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): ObjectIdsResult { - return ObjectIdsResult.deserialize(bytes); - } + #one_of_decls: number[][] = []; + constructor( + data?: any[] | { + objectIdFieldName?: string; + serverGens?: FeatureCollectionPBuffer.ServerGens; + objectIds?: number[]; + }, + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("objectIdFieldName" in data && data.objectIdFieldName != undefined) { + this.objectIdFieldName = data.objectIdFieldName; + } + if ("serverGens" in data && data.serverGens != undefined) { + this.serverGens = data.serverGens; + } + if ("objectIds" in data && data.objectIds != undefined) { + this.objectIds = data.objectIds; + } + } + } + get objectIdFieldName() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set objectIdFieldName(value: string) { + pb_1.Message.setField(this, 1, value); + } + get serverGens() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ServerGens, 2) as FeatureCollectionPBuffer.ServerGens; + } + set serverGens(value: FeatureCollectionPBuffer.ServerGens) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_serverGens() { + return pb_1.Message.getField(this, 2) != null; + } + get objectIds() { + return pb_1.Message.getFieldWithDefault(this, 3, []) as number[]; + } + set objectIds(value: number[]) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + objectIdFieldName?: string; + serverGens?: ReturnType; + objectIds?: number[]; + }): ObjectIdsResult { + const message = new ObjectIdsResult({}); + if (data.objectIdFieldName != null) { + message.objectIdFieldName = data.objectIdFieldName; + } + if (data.serverGens != null) { + message.serverGens = FeatureCollectionPBuffer.ServerGens.fromObject(data.serverGens); + } + if (data.objectIds != null) { + message.objectIds = data.objectIds; + } + return message; + } + toObject() { + const data: { + objectIdFieldName?: string; + serverGens?: ReturnType; + objectIds?: number[]; + } = {}; + if (this.objectIdFieldName != null) { + data.objectIdFieldName = this.objectIdFieldName; + } + if (this.serverGens != null) { + data.serverGens = this.serverGens.toObject(); + } + if (this.objectIds != null) { + data.objectIds = this.objectIds; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.objectIdFieldName.length) + writer.writeString(1, this.objectIdFieldName); + if (this.has_serverGens) + writer.writeMessage(2, this.serverGens, () => this.serverGens.serialize(writer)); + if (this.objectIds.length) + writer.writePackedUint64(3, this.objectIds); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ObjectIdsResult { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ObjectIdsResult(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.objectIdFieldName = reader.readString(); + break; + case 2: + reader.readMessage(message.serverGens, () => message.serverGens = FeatureCollectionPBuffer.ServerGens.deserialize(reader)); + break; + case 3: + message.objectIds = reader.readPackedUint64(); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): ObjectIdsResult { + return ObjectIdsResult.deserialize(bytes); + } } export class QueryResult extends pb_1.Message { - #one_of_decls: number[][] = [[1, 2, 3]]; - constructor(data?: any[] | ({} & (({ + #one_of_decls: number[][] = [[1, 2, 3]]; + constructor( + data?: + | any[] + | ( + & {} + & (({ featureResult?: FeatureCollectionPBuffer.FeatureResult; countResult?: never; idsResult?: never; @@ -2481,132 +2607,135 @@ export namespace esriPBuffer { featureResult?: never; countResult?: never; idsResult?: FeatureCollectionPBuffer.ObjectIdsResult; - })))) { - super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); - if (!Array.isArray(data) && typeof data == "object") { - if ("featureResult" in data && data.featureResult != undefined) { - this.featureResult = data.featureResult; - } - if ("countResult" in data && data.countResult != undefined) { - this.countResult = data.countResult; - } - if ("idsResult" in data && data.idsResult != undefined) { - this.idsResult = data.idsResult; - } - } - } - get featureResult() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.FeatureResult, 1) as FeatureCollectionPBuffer.FeatureResult; - } - set featureResult(value: FeatureCollectionPBuffer.FeatureResult) { - pb_1.Message.setOneofWrapperField(this, 1, this.#one_of_decls[0], value); - } - get has_featureResult() { - return pb_1.Message.getField(this, 1) != null; - } - get countResult() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.CountResult, 2) as FeatureCollectionPBuffer.CountResult; - } - set countResult(value: FeatureCollectionPBuffer.CountResult) { - pb_1.Message.setOneofWrapperField(this, 2, this.#one_of_decls[0], value); - } - get has_countResult() { - return pb_1.Message.getField(this, 2) != null; - } - get idsResult() { - return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ObjectIdsResult, 3) as FeatureCollectionPBuffer.ObjectIdsResult; - } - set idsResult(value: FeatureCollectionPBuffer.ObjectIdsResult) { - pb_1.Message.setOneofWrapperField(this, 3, this.#one_of_decls[0], value); - } - get has_idsResult() { - return pb_1.Message.getField(this, 3) != null; - } - get Results() { - const cases: { - [index: number]: "none" | "featureResult" | "countResult" | "idsResult"; - } = { - 0: "none", - 1: "featureResult", - 2: "countResult", - 3: "idsResult", - }; - return cases[pb_1.Message.computeOneofCase(this, [1, 2, 3])]; - } - static fromObject(data: { - featureResult?: ReturnType; - countResult?: ReturnType; - idsResult?: ReturnType; - }): QueryResult { - const message = new QueryResult({}); - if (data.featureResult != null) { - message.featureResult = FeatureCollectionPBuffer.FeatureResult.fromObject(data.featureResult); - } - if (data.countResult != null) { - message.countResult = FeatureCollectionPBuffer.CountResult.fromObject(data.countResult); - } - if (data.idsResult != null) { - message.idsResult = FeatureCollectionPBuffer.ObjectIdsResult.fromObject(data.idsResult); - } - return message; - } - toObject() { - const data: { - featureResult?: ReturnType; - countResult?: ReturnType; - idsResult?: ReturnType; - } = {}; - if (this.featureResult != null) { - data.featureResult = this.featureResult.toObject(); - } - if (this.countResult != null) { - data.countResult = this.countResult.toObject(); - } - if (this.idsResult != null) { - data.idsResult = this.idsResult.toObject(); - } - return data; - } - serialize(): Uint8Array; - serialize(w: pb_1.BinaryWriter): void; - serialize(w?: pb_1.BinaryWriter): Uint8Array | void { - const writer = w || new pb_1.BinaryWriter(); - if (this.has_featureResult) - writer.writeMessage(1, this.featureResult, () => this.featureResult.serialize(writer)); - if (this.has_countResult) - writer.writeMessage(2, this.countResult, () => this.countResult.serialize(writer)); - if (this.has_idsResult) - writer.writeMessage(3, this.idsResult, () => this.idsResult.serialize(writer)); - if (!w) - return writer.getResultBuffer(); - } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): QueryResult { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new QueryResult(); - while (reader.nextField()) { - if (reader.isEndGroup()) - break; - switch (reader.getFieldNumber()) { - case 1: - reader.readMessage(message.featureResult, () => message.featureResult = FeatureCollectionPBuffer.FeatureResult.deserialize(reader)); - break; - case 2: - reader.readMessage(message.countResult, () => message.countResult = FeatureCollectionPBuffer.CountResult.deserialize(reader)); - break; - case 3: - reader.readMessage(message.idsResult, () => message.idsResult = FeatureCollectionPBuffer.ObjectIdsResult.deserialize(reader)); - break; - default: reader.skipField(); - } - } - return message; - } - serializeBinary(): Uint8Array { - return this.serialize(); - } - static override deserializeBinary(bytes: Uint8Array): QueryResult { - return QueryResult.deserialize(bytes); - } + })) + ), + ) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("featureResult" in data && data.featureResult != undefined) { + this.featureResult = data.featureResult; + } + if ("countResult" in data && data.countResult != undefined) { + this.countResult = data.countResult; + } + if ("idsResult" in data && data.idsResult != undefined) { + this.idsResult = data.idsResult; + } + } + } + get featureResult() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.FeatureResult, 1) as FeatureCollectionPBuffer.FeatureResult; + } + set featureResult(value: FeatureCollectionPBuffer.FeatureResult) { + pb_1.Message.setOneofWrapperField(this, 1, this.#one_of_decls[0], value); + } + get has_featureResult() { + return pb_1.Message.getField(this, 1) != null; + } + get countResult() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.CountResult, 2) as FeatureCollectionPBuffer.CountResult; + } + set countResult(value: FeatureCollectionPBuffer.CountResult) { + pb_1.Message.setOneofWrapperField(this, 2, this.#one_of_decls[0], value); + } + get has_countResult() { + return pb_1.Message.getField(this, 2) != null; + } + get idsResult() { + return pb_1.Message.getWrapperField(this, FeatureCollectionPBuffer.ObjectIdsResult, 3) as FeatureCollectionPBuffer.ObjectIdsResult; + } + set idsResult(value: FeatureCollectionPBuffer.ObjectIdsResult) { + pb_1.Message.setOneofWrapperField(this, 3, this.#one_of_decls[0], value); + } + get has_idsResult() { + return pb_1.Message.getField(this, 3) != null; + } + get Results() { + const cases: { + [index: number]: "none" | "featureResult" | "countResult" | "idsResult"; + } = { + 0: "none", + 1: "featureResult", + 2: "countResult", + 3: "idsResult", + }; + return cases[pb_1.Message.computeOneofCase(this, [1, 2, 3])]; + } + static fromObject(data: { + featureResult?: ReturnType; + countResult?: ReturnType; + idsResult?: ReturnType; + }): QueryResult { + const message = new QueryResult({}); + if (data.featureResult != null) { + message.featureResult = FeatureCollectionPBuffer.FeatureResult.fromObject(data.featureResult); + } + if (data.countResult != null) { + message.countResult = FeatureCollectionPBuffer.CountResult.fromObject(data.countResult); + } + if (data.idsResult != null) { + message.idsResult = FeatureCollectionPBuffer.ObjectIdsResult.fromObject(data.idsResult); + } + return message; + } + toObject() { + const data: { + featureResult?: ReturnType; + countResult?: ReturnType; + idsResult?: ReturnType; + } = {}; + if (this.featureResult != null) { + data.featureResult = this.featureResult.toObject(); + } + if (this.countResult != null) { + data.countResult = this.countResult.toObject(); + } + if (this.idsResult != null) { + data.idsResult = this.idsResult.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_featureResult) + writer.writeMessage(1, this.featureResult, () => this.featureResult.serialize(writer)); + if (this.has_countResult) + writer.writeMessage(2, this.countResult, () => this.countResult.serialize(writer)); + if (this.has_idsResult) + writer.writeMessage(3, this.idsResult, () => this.idsResult.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): QueryResult { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new QueryResult(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.featureResult, () => message.featureResult = FeatureCollectionPBuffer.FeatureResult.deserialize(reader)); + break; + case 2: + reader.readMessage(message.countResult, () => message.countResult = FeatureCollectionPBuffer.CountResult.deserialize(reader)); + break; + case 3: + reader.readMessage(message.idsResult, () => message.idsResult = FeatureCollectionPBuffer.ObjectIdsResult.deserialize(reader)); + break; + default: + reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static override deserializeBinary(bytes: Uint8Array): QueryResult { + return QueryResult.deserialize(bytes); + } } } } diff --git a/extensions/map-layers-formats/src/Feature/DefaultMarkerIcon.ts b/extensions/map-layers-formats/src/Feature/DefaultMarkerIcon.ts index bc0c2aa9c64c..61877432fca9 100644 --- a/extensions/map-layers-formats/src/Feature/DefaultMarkerIcon.ts +++ b/extensions/map-layers-formats/src/Feature/DefaultMarkerIcon.ts @@ -27,4 +27,3 @@ export class DefaultMarkerIcon { }; } } - diff --git a/extensions/map-layers-formats/src/Feature/FeatureCanvasRenderer.ts b/extensions/map-layers-formats/src/Feature/FeatureCanvasRenderer.ts index 12229f6f7416..b0cce75ea8a8 100644 --- a/extensions/map-layers-formats/src/Feature/FeatureCanvasRenderer.ts +++ b/extensions/map-layers-formats/src/Feature/FeatureCanvasRenderer.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Transform } from "@itwin/core-geometry"; import { FeatureGeometryBaseRenderer, FeatureSymbolizedRenderer, FeatureSymbologyRenderer } from "@itwin/core-frontend"; +import { Transform } from "@itwin/core-geometry"; import { ArcGisSymbologyCanvasRenderer } from "../ArcGisFeature/ArcGisSymbologyRenderer"; /** @internal */ @@ -12,10 +12,12 @@ export class FeatureCanvasRenderer extends FeatureGeometryBaseRenderer implement private _context: CanvasRenderingContext2D; private _symbol: ArcGisSymbologyCanvasRenderer; - public get symbolRenderer(): FeatureSymbologyRenderer { + public get symbolRenderer(): FeatureSymbologyRenderer { return this._symbol; } - public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer {return true;} + public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer { + return true; + } constructor(context: CanvasRenderingContext2D, symbol: ArcGisSymbologyCanvasRenderer, world2PixelTransform?: Transform) { super(world2PixelTransform); diff --git a/extensions/map-layers-formats/src/Feature/FeatureInfoReader.ts b/extensions/map-layers-formats/src/Feature/FeatureInfoReader.ts index 8cbad6931614..8601fd778a4b 100644 --- a/extensions/map-layers-formats/src/Feature/FeatureInfoReader.ts +++ b/extensions/map-layers-formats/src/Feature/FeatureInfoReader.ts @@ -9,9 +9,8 @@ import { Primitives, StandardTypeNames } from "@itwin/appui-abstract"; * @internal */ export abstract class FeatureInfoReader { - // Optionally you can set the floating precision - public floatPrecision: number|undefined; + public floatPrecision: number | undefined; // Force display value of date to ISO 8601 format. // Turning this ON, will disable display value in end-user's locale @@ -21,15 +20,14 @@ export abstract class FeatureInfoReader { return (this.floatPrecision === undefined ? value : parseFloat(value.toFixed(this.floatPrecision))); }; - protected getDisplayValue = (typename: StandardTypeNames, value: Primitives.Value|undefined) => { + protected getDisplayValue = (typename: StandardTypeNames, value: Primitives.Value | undefined) => { if (value === undefined) { - return ""; - } else if ( typename === StandardTypeNames.DateTime && this.forceDateDisplayValueToIso) { + return ""; + } else if (typename === StandardTypeNames.DateTime && this.forceDateDisplayValueToIso) { return (value as Date).toISOString(); } else { // eslint-disable-next-line @typescript-eslint/no-base-to-string return `${value}`; } }; - } diff --git a/extensions/map-layers-formats/src/Feature/FeatureSymbology.ts b/extensions/map-layers-formats/src/Feature/FeatureSymbology.ts index e41680068b37..faf634a620df 100644 --- a/extensions/map-layers-formats/src/Feature/FeatureSymbology.ts +++ b/extensions/map-layers-formats/src/Feature/FeatureSymbology.ts @@ -5,7 +5,6 @@ /** @internal */ export abstract class FeatureSymbology { - } /** @internal */ diff --git a/extensions/map-layers-formats/src/Feature/RandomMapColor.ts b/extensions/map-layers-formats/src/Feature/RandomMapColor.ts index a0d3f1bce8be..486f9b89d848 100644 --- a/extensions/map-layers-formats/src/Feature/RandomMapColor.ts +++ b/extensions/map-layers-formats/src/Feature/RandomMapColor.ts @@ -8,22 +8,85 @@ import { ColorDef } from "@itwin/core-common"; /** @internal */ export class RandomMapColor { private static readonly randomColorPalette = [ - "#8c510a", "#bf812d", "#dfc27d", "#f6e8c3", "#f5f5f5", "#c7eae5", "#80cdc1", "#35978f", "#01665e", - "#b2182b", "#d6604d", "#f4a582", "#fddbc7", "#f7f7f7", "#d1e5f0", "#92c5de", "#4393c3", "#2166ac", - "#d73027", "#f46d43", "#fdae61", "#fee090", "#ffffbf", "#e0f3f8", "#abd9e9", "#74add1", "#4575b4", - "#a6cee3", "#1f78b4", "#b2df8a", "#33a02c", "#fb9a99", "#e31c2c", "#fdbf6f", "#ff7f00", "#cab2d6", - "#fbb4ae", "#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff2000", "#ffff33", "#a65628", "#999999", - "#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#ffa07a", - "#b15928", "#6a3d9a", "#ffed6f", "#9e0142", "#5e4fa2", "#999900", "#1a9850", "#4d4d4d", "#6baed6", - "#71c671", "#388e8e", "#7d9ec0", "#7171c6", "#8e388e", "#8e8e38", "#00c957", "#cc3333", "#d1dbdd", + "#8c510a", + "#bf812d", + "#dfc27d", + "#f6e8c3", + "#f5f5f5", + "#c7eae5", + "#80cdc1", + "#35978f", + "#01665e", + "#b2182b", + "#d6604d", + "#f4a582", + "#fddbc7", + "#f7f7f7", + "#d1e5f0", + "#92c5de", + "#4393c3", + "#2166ac", + "#d73027", + "#f46d43", + "#fdae61", + "#fee090", + "#ffffbf", + "#e0f3f8", + "#abd9e9", + "#74add1", + "#4575b4", + "#a6cee3", + "#1f78b4", + "#b2df8a", + "#33a02c", + "#fb9a99", + "#e31c2c", + "#fdbf6f", + "#ff7f00", + "#cab2d6", + "#fbb4ae", + "#e41a1c", + "#377eb8", + "#4daf4a", + "#984ea3", + "#ff2000", + "#ffff33", + "#a65628", + "#999999", + "#8dd3c7", + "#ffffb3", + "#bebada", + "#fb8072", + "#80b1d3", + "#fdb462", + "#b3de69", + "#fccde5", + "#ffa07a", + "#b15928", + "#6a3d9a", + "#ffed6f", + "#9e0142", + "#5e4fa2", + "#999900", + "#1a9850", + "#4d4d4d", + "#6baed6", + "#71c671", + "#388e8e", + "#7d9ec0", + "#7171c6", + "#8e388e", + "#8e8e38", + "#00c957", + "#cc3333", + "#d1dbdd", ]; public getColor() { - return RandomMapColor.randomColorPalette[ Math.floor(Math.random() * RandomMapColor.randomColorPalette.length)]; + return RandomMapColor.randomColorPalette[Math.floor(Math.random() * RandomMapColor.randomColorPalette.length)]; } public getColorDef() { return ColorDef.fromString(this.getColor()); } } - diff --git a/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometry.ts b/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometry.ts index eaacfde73ab5..a8b9be97fec1 100644 --- a/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometry.ts +++ b/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometry.ts @@ -7,7 +7,8 @@ import * as GeoJson from "geojson"; /** @internal */ export type Coord = number[]; -/** @internal */ // Array of 2 or 3 numbers +/** @internal */ +// Array of 2 or 3 numbers export type RingCoords = Coord[]; /** @internal */ @@ -21,7 +22,13 @@ export interface MultiPath { /** @internal */ export class GeoJSONGeometryUtils { - public static isRingOrPath(geom: GeoJson.Geometry) {return geom.type === "LineString" || geom.type === "MultiLineString" || geom.type === "Polygon" || geom.type === "MultiPolygon";} - public static isFilled(geom: GeoJson.Geometry) {return geom.type === "Polygon" || geom.type === "MultiPolygon";} - public static isPoint(geom: GeoJson.Geometry) {return geom.type === "Point" || geom.type === "MultiPoint";} + public static isRingOrPath(geom: GeoJson.Geometry) { + return geom.type === "LineString" || geom.type === "MultiLineString" || geom.type === "Polygon" || geom.type === "MultiPolygon"; + } + public static isFilled(geom: GeoJson.Geometry) { + return geom.type === "Polygon" || geom.type === "MultiPolygon"; + } + public static isPoint(geom: GeoJson.Geometry) { + return geom.type === "Point" || geom.type === "MultiPoint"; + } } diff --git a/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometryReader.ts b/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometryReader.ts index d667230e220b..d483fe456e42 100644 --- a/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometryReader.ts +++ b/extensions/map-layers-formats/src/GeoJSON/GeoJSONGeometryReader.ts @@ -5,8 +5,8 @@ import { Logger } from "@itwin/core-bentley"; import { deflateCoordinates, FeatureGeometryRenderer } from "@itwin/core-frontend"; -import { Coord, GeoJSONGeometryUtils, MultiPath, MultiRingCoords, RingCoords } from "./GeoJSONGeometry"; import * as GeoJson from "geojson"; +import { Coord, GeoJSONGeometryUtils, MultiPath, MultiRingCoords, RingCoords } from "./GeoJSONGeometry"; const loggerCategory = "MapLayersFormats.GeoJSONGeometryReader"; @@ -19,18 +19,17 @@ export class GeoJSONGeometryReader { } public async readGeometry(geometry: GeoJson.Geometry) { - if (GeoJSONGeometryUtils.isRingOrPath(geometry)) { await this.readRingsAndPaths(geometry, this._renderer, GeoJSONGeometryUtils.isFilled(geometry), false /* relativeCoords*/); } else if (GeoJSONGeometryUtils.isPoint(geometry)) { - await this.readPoints(geometry, this._renderer, false/* relativeCoords*/); + await this.readPoints(geometry, this._renderer, false /* relativeCoords*/); } else { Logger.logError(loggerCategory, `GeoJSONGeometryReader:readGeometry - Unknown geometry type '${geometry.type}'`); } } private async readRingsAndPaths(geometry: GeoJson.Geometry, renderer: FeatureGeometryRenderer, fill: boolean, relativeCoords: boolean) { - const multiPath: MultiPath = {coords: [], lengths: []}; + const multiPath: MultiPath = { coords: [], lengths: [] }; let polys: MultiPath[] | undefined; const readPath = (ring: RingCoords, offset: number, result: MultiPath) => { @@ -53,7 +52,7 @@ export class GeoJSONGeometryReader { } else if (geometry.type === "MultiPolygon") { polys = []; for (const poly of geometry.coordinates) { - const tmpMultiPath: MultiPath = {coords: [], lengths: [] }; + const tmpMultiPath: MultiPath = { coords: [], lengths: [] }; readMultiPath(poly, tmpMultiPath); polys.push(tmpMultiPath); } @@ -66,11 +65,9 @@ export class GeoJSONGeometryReader { } else { await renderer.renderPath(multiPath.lengths, multiPath.coords, fill, 2, relativeCoords); } - } private async readPoints(geom: GeoJson.Geometry, renderer: FeatureGeometryRenderer, relativeCoords: boolean) { - const lengths: Coord = []; const coords: Coord = []; const readPoint = (coord: Coord) => { diff --git a/extensions/map-layers-formats/src/Icons/MapInfoIcon.ts b/extensions/map-layers-formats/src/Icons/MapInfoIcon.ts index c8355ec715fa..d3c3445e7f13 100644 --- a/extensions/map-layers-formats/src/Icons/MapInfoIcon.ts +++ b/extensions/map-layers-formats/src/Icons/MapInfoIcon.ts @@ -5,5 +5,6 @@ /** @internal */ export const mapInfoIcon = { - dataUri: "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZD0iTTUuODYyIDUuMTYyYTEuNDg4IDEuNDg4IDAgMSAxLTIuOTc1IDAgMS40ODggMS40ODggMCAwIDEgMi45NzUgMFpNMTIgN2MuNzEyIDAgMS4zODcuMTU0IDIgLjQyMlYwaC0xLjA1bC0yLjI3OCA3LjIwMUE0Ljk1IDQuOTUgMCAwIDEgMTIgN1ptLTQuNzkyIDYuMzQ5TDcgMTRIMFYwaDExLjQ2M0w4Ljg3MiA4LjEyOUM3LjczOSA5LjA0NSA3IDEwLjQyOSA3IDEyYzAgLjQ3LjA4Ni45MTcuMjA4IDEuMzQ5Wm0tLjAzMy04LjE4N1Y1LjA5YTIuNzY0IDIuNzY0IDAgMCAwLTIuODcyLTIuNzI4IDIuNzY0IDIuNzY0IDAgMCAwLTIuNzI4IDIuOEE2LjkwMyA2LjkwMyAwIDAgMCAyLjggOC4zMTJjLjQ3NC44NzcgMSAxLjcyNCAxLjU3NSAyLjUzOCAwIDAgLjk2My0xLjQ4OCAxLjU3NS0yLjUzN2E2LjkwMyA2LjkwMyAwIDAgMCAxLjIyNS0zLjE1Wk0xNiAxMmE0IDQgMCAxIDEtOCAwIDQgNCAwIDAgMSA4IDBabS00LjA1LTEuODVhLjQ2OS40NjkgMCAwIDAgLjUuNS42NTUuNjU1IDAgMCAwIC42NS0uNmwtLjAwMi0uMDMyQS40Ni40NiAwIDAgMCAxMi42IDkuNmEuNjE1LjYxNSAwIDAgMC0uNjUuNTVabTEuMTUgMy40NS0uMTUtLjJhMSAxIDAgMCAxLS41NS4zYy0uMSAwLS4xLS4wNS0uMDUtLjNsLjM1LTEuM2MuMTUtLjUuMS0uOC0uMTUtLjhhMy4yNSAzLjI1IDAgMCAwLTEuNjUuOGwuMS4yNWMuMTk4LS4xMjUuNDItLjIxLjY1LS4yNS4wNSAwIC4wNS4wNSAwIC4yNWwtLjMgMS4yYy0uMi43IDAgLjg1LjI1Ljg1YTIuODg1IDIuODg1IDAgMCAwIDEuNS0uOFoiLz48L3N2Zz4=", + dataUri: + "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+PHBhdGggZD0iTTUuODYyIDUuMTYyYTEuNDg4IDEuNDg4IDAgMSAxLTIuOTc1IDAgMS40ODggMS40ODggMCAwIDEgMi45NzUgMFpNMTIgN2MuNzEyIDAgMS4zODcuMTU0IDIgLjQyMlYwaC0xLjA1bC0yLjI3OCA3LjIwMUE0Ljk1IDQuOTUgMCAwIDEgMTIgN1ptLTQuNzkyIDYuMzQ5TDcgMTRIMFYwaDExLjQ2M0w4Ljg3MiA4LjEyOUM3LjczOSA5LjA0NSA3IDEwLjQyOSA3IDEyYzAgLjQ3LjA4Ni45MTcuMjA4IDEuMzQ5Wm0tLjAzMy04LjE4N1Y1LjA5YTIuNzY0IDIuNzY0IDAgMCAwLTIuODcyLTIuNzI4IDIuNzY0IDIuNzY0IDAgMCAwLTIuNzI4IDIuOEE2LjkwMyA2LjkwMyAwIDAgMCAyLjggOC4zMTJjLjQ3NC44NzcgMSAxLjcyNCAxLjU3NSAyLjUzOCAwIDAgLjk2My0xLjQ4OCAxLjU3NS0yLjUzN2E2LjkwMyA2LjkwMyAwIDAgMCAxLjIyNS0zLjE1Wk0xNiAxMmE0IDQgMCAxIDEtOCAwIDQgNCAwIDAgMSA4IDBabS00LjA1LTEuODVhLjQ2OS40NjkgMCAwIDAgLjUuNS42NTUuNjU1IDAgMCAwIC42NS0uNmwtLjAwMi0uMDMyQS40Ni40NiAwIDAgMCAxMi42IDkuNmEuNjE1LjYxNSAwIDAgMC0uNjUuNTVabTEuMTUgMy40NS0uMTUtLjJhMSAxIDAgMCAxLS41NS4zYy0uMSAwLS4xLS4wNS0uMDUtLjNsLjM1LTEuM2MuMTUtLjUuMS0uOC0uMTUtLjhhMy4yNSAzLjI1IDAgMCAwLTEuNjUuOGwuMS4yNWMuMTk4LS4xMjUuNDItLjIxLjY1LS4yNS4wNSAwIC4wNS4wNSAwIC4yNWwtLjMgMS4yYy0uMi43IDAgLjg1LjI1Ljg1YTIuODg1IDIuODg1IDAgMCAwIDEuNS0uOFoiLz48L3N2Zz4=", } as const; diff --git a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesFormat.ts b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesFormat.ts index b8b56825c177..0d299d70bf83 100644 --- a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesFormat.ts +++ b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesFormat.ts @@ -3,21 +3,29 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { ImageMapLayerSettings, MapSubLayerProps } from "@itwin/core-common"; -import { appendQueryParams, ImageryMapLayerFormat, MapLayerImageryProvider, MapLayerSourceStatus, MapLayerSourceValidation, setBasicAuthorization, ValidateSourceArgs } from "@itwin/core-frontend"; +import { + appendQueryParams, + ImageryMapLayerFormat, + MapLayerImageryProvider, + MapLayerSourceStatus, + MapLayerSourceValidation, + setBasicAuthorization, + ValidateSourceArgs, +} from "@itwin/core-frontend"; import { OgcApiFeaturesProvider } from "./OgcApiFeaturesProvider"; /** @internal */ export class OgcApiFeaturesMapLayerFormat extends ImageryMapLayerFormat { public static override formatId = "OgcApiFeatures"; - public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { return new OgcApiFeaturesProvider(settings); } + public static override createImageryProvider(settings: ImageMapLayerSettings): MapLayerImageryProvider | undefined { + return new OgcApiFeaturesProvider(settings); + } public static override async validate(args: ValidateSourceArgs): Promise { - - const {source} = args; + const { source } = args; const { userName, password } = source; let status = MapLayerSourceStatus.InvalidUrl; try { - let headers: Headers | undefined; if (userName && password) { headers = new Headers(); @@ -76,7 +84,7 @@ export class OgcApiFeaturesMapLayerFormat extends ImageryMapLayerFormat { status = MapLayerSourceStatus.Valid; } else if (Array.isArray(json.links)) { // This might be the main landing page - const collectionsLink = json.links.find((link: any)=> link.rel.includes("data") && link.type === "application/json"); + const collectionsLink = json.links.find((link: any) => link.rel.includes("data") && link.type === "application/json"); let collectionsUrl = appendQueryParams(collectionsLink.href, source.savedQueryParams); collectionsUrl = appendQueryParams(collectionsUrl, source.unsavedQueryParams); response = await fetch(collectionsUrl, opts); @@ -85,17 +93,15 @@ export class OgcApiFeaturesMapLayerFormat extends ImageryMapLayerFormat { subLayers = createCollectionsList(json); status = MapLayerSourceStatus.Valid; } - } return { status, subLayers }; - } catch (err: any) { status = MapLayerSourceStatus.InvalidUrl; if (err?.status === 401) { - status = ((userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth); + status = (userName && password) ? MapLayerSourceStatus.InvalidCredentials : MapLayerSourceStatus.RequireAuth; } - return { status}; + return { status }; } } } diff --git a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesProvider.ts b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesProvider.ts index 9526fe9aff6c..f73046fb4aad 100644 --- a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesProvider.ts +++ b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesProvider.ts @@ -3,27 +3,36 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { FeatureGraphicsRenderer, HitDetail, ImageryMapTileTree, MapCartoRectangle, MapFeatureInfoOptions, MapLayerFeatureInfo, MapLayerImageryProvider, QuadId, WGS84Extent } from "@itwin/core-frontend"; -import { EsriPMS, EsriPMSProps, EsriRenderer, EsriSFS, EsriSFSProps, EsriSLS, EsriSLSProps, EsriSymbol } from "../ArcGisFeature/EsriSymbology"; +import { base64StringToUint8Array, IModelStatus, Logger } from "@itwin/core-bentley"; import { Cartographic, ColorDef, ImageMapLayerSettings, ImageSource, ImageSourceFormat, ServerError, SubLayerId } from "@itwin/core-common"; +import { + FeatureGraphicsRenderer, + HitDetail, + ImageryMapTileTree, + MapCartoRectangle, + MapFeatureInfoOptions, + MapLayerFeatureInfo, + MapLayerImageryProvider, + QuadId, + WGS84Extent, +} from "@itwin/core-frontend"; import { Matrix4d, Point3d, Range2d } from "@itwin/core-geometry"; +import * as Geojson from "geojson"; import { ArcGisSymbologyCanvasRenderer } from "../ArcGisFeature/ArcGisSymbologyRenderer"; +import { EsriPMS, EsriPMSProps, EsriRenderer, EsriSFS, EsriSFSProps, EsriSLS, EsriSLSProps, EsriSymbol } from "../ArcGisFeature/EsriSymbology"; +import { DefaultMarkerIcon } from "../Feature/DefaultMarkerIcon"; import { FeatureCanvasRenderer } from "../Feature/FeatureCanvasRenderer"; -import { base64StringToUint8Array, IModelStatus, Logger } from "@itwin/core-bentley"; -import * as Geojson from "geojson"; import { FeatureDefaultSymbology } from "../Feature/FeatureSymbology"; -import { OgcApiFeaturesReader } from "./OgcApiFeaturesReader"; import { RandomMapColor } from "../Feature/RandomMapColor"; -import { DefaultMarkerIcon } from "../Feature/DefaultMarkerIcon"; +import { OgcApiFeaturesReader } from "./OgcApiFeaturesReader"; const loggerCategory = "MapLayersFormats.OgcApiFeatures"; const dataUrlHeaderToken = "base64,"; /** Provide tiles from a ESRI ArcGIS Feature service -* @internal -*/ + * @internal + */ export class DefaultOgcSymbology implements FeatureDefaultSymbology { - private static readonly _defaultPMSProps: Omit = { type: "esriPMS", url: "", @@ -45,7 +54,7 @@ export class DefaultOgcSymbology implements FeatureDefaultSymbology { private static readonly _defaultSFSProps: EsriSFSProps = { type: "esriSFS", - color: [0, 0, 255, 255], // blue fill + color: [0, 0, 255, 255], // blue fill style: "esriSFSSolid", outline: DefaultOgcSymbology._defaultSLSProps, }; @@ -53,7 +62,7 @@ export class DefaultOgcSymbology implements FeatureDefaultSymbology { public constructor(randomColor?: RandomMapColor) { const color = randomColor ? randomColor.getColorDef() : ColorDef.blue; - this._defaultPMS = EsriPMS.fromJSON( { + this._defaultPMS = EsriPMS.fromJSON({ ...DefaultMarkerIcon.getContent(color), type: "esriPMS", url: "", @@ -85,11 +94,11 @@ export class DefaultOgcSymbology implements FeatureDefaultSymbology { } public getSymbology(geometryType: string): EsriSymbol { - if (geometryType === "LineString"|| geometryType === "MultiLineString" ) + if (geometryType === "LineString" || geometryType === "MultiLineString") return this._defaultSLS; - else if (geometryType === "Polygon"|| geometryType === "MultiPolygon" ) + else if (geometryType === "Polygon" || geometryType === "MultiPolygon") return this._defaultSFS; - else if (geometryType === "Point"|| geometryType === "MultiPoint" ) + else if (geometryType === "Point" || geometryType === "MultiPoint") return this._defaultPMS; throw new Error(`Could not get default symbology for geometry type ${geometryType}`); @@ -97,7 +106,6 @@ export class DefaultOgcSymbology implements FeatureDefaultSymbology { } /** @internal */ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { - // Debug flags, should always be committed to FALSE ! private readonly _drawDebugInfo = false; /// //////////////////////////// @@ -109,27 +117,32 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { private readonly _forceTileMode = false; private _spatialIdx: any; private _defaultSymbol = new DefaultOgcSymbology(new RandomMapColor()); - private _renderer: EsriRenderer|undefined; + private _renderer: EsriRenderer | undefined; private _collectionUrl = ""; private _itemsUrl = ""; - private readonly _itemsCrs = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; // Fixed fow now + private readonly _itemsCrs = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; // Fixed fow now private _queryables: any; public serviceJson: any; - private _staticData: Geojson.FeatureCollection|undefined; + private _staticData: Geojson.FeatureCollection | undefined; constructor(settings: ImageMapLayerSettings) { super(settings, true); } - public override get supportsMapFeatureInfo() { return true;} - public override get minimumZoomLevel(): number { return this.staticMode ? super.minimumZoomLevel : this._tiledModeMinLod; } - public get staticMode(): boolean { return !!(this._spatialIdx && this._staticData && !this._forceTileMode); } + public override get supportsMapFeatureInfo() { + return true; + } + public override get minimumZoomLevel(): number { + return this.staticMode ? super.minimumZoomLevel : this._tiledModeMinLod; + } + public get staticMode(): boolean { + return !!(this._spatialIdx && this._staticData && !this._forceTileMode); + } public override async initialize(): Promise { - this._collectionUrl = this._settings.url; - let layerId: SubLayerId|undefined; + let layerId: SubLayerId | undefined; // OGC Feature service request can only serve data for a single feature // so if multiple sub-layer ids are specified, we pick the first one. @@ -138,16 +151,15 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { } const readCollectionsPage = (data: any) => { - const collection = data.collections.find((col: any)=> col.id === layerId); + const collection = data.collections.find((col: any) => col.id === layerId); const collectionLinks = collection?.links; if (!collectionLinks) { const msg = `Missing layer id or matching collection could not be found`; Logger.logError(loggerCategory, msg); throw new Error(msg); } - const collectionLink = collectionLinks.find((link: any)=> link.rel.includes("collection") && link.type === "application/json", - ); - this._collectionUrl = collectionLink.href; + const collectionLink = collectionLinks.find((link: any) => link.rel.includes("collection") && link.type === "application/json"); + this._collectionUrl = collectionLink.href; }; const layerIdMismatch = () => { @@ -160,8 +172,8 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { if (json?.type === "FeatureCollection") { // We landed on the items page, we need to look for the collection metadata url if (Array.isArray(json.links)) { - const collectionLink = json.links.find((link: any)=> link.rel.includes("collection") && link.type === "application/json"); - this._collectionUrl = collectionLink.href; + const collectionLink = json.links.find((link: any) => link.rel.includes("collection") && link.type === "application/json"); + this._collectionUrl = collectionLink.href; } } else if (json.itemType === "feature") { // We landed on a specific collection page. @@ -169,28 +181,27 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { // Check if the collection id matches at least one sub-layer if (this._settings.subLayers && this._settings.subLayers.length > 0) { - const subLayer = this._settings.subLayers.find((s)=>s.id === collectionMetadata.id); + const subLayer = this._settings.subLayers.find((s) => s.id === collectionMetadata.id); if (subLayer) layerId = subLayer.id; } else { // No sub-layers were specified, defaults to collection id. layerId = collectionMetadata.id; } - } else if (Array.isArray(json.collections)) { // We landed in the "Collections" page // Find to find the specified layer id among the available collections readCollectionsPage(json); - } else if (Array.isArray(json.links)) { + } else if (Array.isArray(json.links)) { // This might be the main landing page // We need to find the the "Collections" page - const collectionsLink = json.links.find((link: any)=> link.rel.includes("data") && link.type === "application/json"); + const collectionsLink = json.links.find((link: any) => link.rel.includes("data") && link.type === "application/json"); if (!collectionsLink) { Logger.logError(loggerCategory, "Could not find collections link"); throw new ServerError(IModelStatus.ValidationFailed, ""); } - json = await this.fetchMetadata(collectionsLink.href); + json = await this.fetchMetadata(collectionsLink.href); if (Array.isArray(json.collections)) { readCollectionsPage(json); } @@ -205,26 +216,26 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { } // Read cartographic range - if (Array.isArray(collectionMetadata?.extent?.spatial?.bbox) - && collectionMetadata.extent.spatial.bbox.length > 0 - && collectionMetadata.extent.spatial.crs === this._itemsCrs + if ( + Array.isArray(collectionMetadata?.extent?.spatial?.bbox) + && collectionMetadata.extent.spatial.bbox.length > 0 + && collectionMetadata.extent.spatial.crs === this._itemsCrs ) { const firstBbox = collectionMetadata.extent.spatial?.bbox[0]; this.cartoRange = MapCartoRectangle.fromDegrees(firstBbox[0], firstBbox[1], firstBbox[2], firstBbox[3]); } // Read important links - let queryablesHref: string|undefined; - let itemsHref: string|undefined; + let queryablesHref: string | undefined; + let itemsHref: string | undefined; if (Array.isArray(collectionMetadata?.links)) { // Items links (Mandatory) - const itemsLink = collectionMetadata.links.find((link: any)=> link.rel.includes("items") && link.type === "application/geo+json"); + const itemsLink = collectionMetadata.links.find((link: any) => link.rel.includes("items") && link.type === "application/geo+json"); itemsHref = itemsLink.href; // Queryables link (Optional) - const queryablesLink = collectionMetadata.links.find((link: any)=> link.rel.includes("queryables") && link.type === "application/schema+json"); + const queryablesLink = collectionMetadata.links.find((link: any) => link.rel.includes("queryables") && link.type === "application/schema+json"); queryablesHref = queryablesLink.href; - } if (itemsHref) @@ -271,7 +282,7 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { let json = await response.json(); data = json; // Follow "next" link if any - let nextLink = json.links?.find((link: any)=>link.rel === "next"); + let nextLink = json.links?.find((link: any) => link.rel === "next"); while (nextLink && (Date.now() - fetchBegin) < timeout && success) { tmpUrl = this.appendCustomParams(nextLink.href); response = await this.makeTileRequest(tmpUrl, this._staticModeFetchTimeout); @@ -280,13 +291,13 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { data!.features = this._staticData?.features ? [...this._staticData.features, ...json.features] : json.features; else success = false; - nextLink = json.links?.find((link: any)=>link.rel === "next"); + nextLink = json.links?.find((link: any) => link.rel === "next"); } if (Date.now() - fetchBegin >= this._staticModeFetchTimeout) { // We ran out of time, let switch to tile mode success = false; } - } catch (e) { + } catch (e) { success = false; if (e instanceof DOMException && e.name === "AbortError") { Logger.logInfo(loggerCategory, "Request to fetch all features time out, switching to tile mode."); @@ -307,9 +318,12 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { try { const datasetRange = new Range2d(); const buildPositionRange = (coords: Geojson.Position, range: Range2d) => range.extendXY(coords[0], coords[1]); - const buildPositionArrayRange = (coords: Geojson.Position[], range: Range2d) => coords.forEach((position) => buildPositionRange(position, range) ); - const buildDoublePositionRange = (coords: Geojson.Position[][], range: Range2d) => coords.forEach((position) => buildPositionArrayRange(position, range) ); - const buildTriplePositionRange = (coords: Geojson.Position[][][], range: Range2d) => coords.forEach((position) => buildDoublePositionRange(position, range) ); + const buildPositionArrayRange = (coords: Geojson.Position[], range: Range2d) => + coords.forEach((position) => buildPositionRange(position, range)); + const buildDoublePositionRange = (coords: Geojson.Position[][], range: Range2d) => + coords.forEach((position) => buildPositionArrayRange(position, range)); + const buildTriplePositionRange = (coords: Geojson.Position[][][], range: Range2d) => + coords.forEach((position) => buildDoublePositionRange(position, range)); const readGeomRange = (geom: Geojson.Geometry, range: Range2d) => { if (geom.type === "Point") @@ -318,7 +332,7 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { buildPositionArrayRange(geom.coordinates, range); else if (geom.type === "Polygon" || geom.type === "MultiLineString") buildDoublePositionRange(geom.coordinates, range); - else if (geom.type === "MultiPolygon" ) + else if (geom.type === "MultiPolygon") buildTriplePositionRange(geom.coordinates, range); }; @@ -326,24 +340,25 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { this._spatialIdx = new flatbush(this._staticData.features.length); this._staticData.features.forEach((feature: Geojson.Feature) => { try { - if (feature.geometry.type === "LineString" - || feature.geometry.type === "MultiLineString" - || feature.geometry.type === "Point" - || feature.geometry.type === "MultiPoint" - || feature.geometry.type === "Polygon" - || feature.geometry.type === "MultiPolygon" + if ( + feature.geometry.type === "LineString" + || feature.geometry.type === "MultiLineString" + || feature.geometry.type === "Point" + || feature.geometry.type === "MultiPoint" + || feature.geometry.type === "Polygon" + || feature.geometry.type === "MultiPolygon" ) { readGeomRange(feature.geometry, datasetRange); - this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh,datasetRange. yHigh); + this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh, datasetRange.yHigh); datasetRange.setNull(); } else if (feature.geometry.type === "GeometryCollection") { feature.geometry.geometries.forEach((geom) => { readGeomRange(geom, datasetRange); - this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh,datasetRange. yHigh); + this._spatialIdx?.add(datasetRange.xLow, datasetRange.yLow, datasetRange.xHigh, datasetRange.yHigh); }); datasetRange.setNull(); } - } catch (e: any) { + } catch (e: any) { Logger.logInfo(loggerCategory, `Unknown error occurred indexing feature: ${e.message}`); success = false; } @@ -353,15 +368,16 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { this._spatialIdx.finish(); } } - - } catch (_e) { + } catch (_e) { Logger.logError(loggerCategory, "Unknown error occurred when index static data"); success = false; } return success; } - public override get tileSize(): number { return 512; } + public override get tileSize(): number { + return 512; + } // We don't use this method inside this provider (see constructFeatureUrl), but since this is an abstract method, we need to define something public async constructUrl(_row: number, _column: number, _zoomLevel: number): Promise { @@ -379,7 +395,6 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { // Compute transform that provides coordinates in the canvas coordinate system (pixels, origin = top-left) // from coordinate in world public computeTileWorld2CanvasTransform(row: number, column: number, zoomLevel: number) { - const tileExtentWorld4326 = this.getEPSG4326Extent(row, column, zoomLevel); const worldTileWidth = tileExtentWorld4326.longitudeRight - tileExtentWorld4326.longitudeLeft; const worldTileHeight = tileExtentWorld4326.latitudeTop - tileExtentWorld4326.latitudeBottom; @@ -398,7 +413,7 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { const xTranslate = -1 * canvasTileOriginOffset.x; // Canvas origin is upper left corner, so we need to flip the y axis - const yTranslate = canvasTileExtentOffset.y; // y-axis flip + const yTranslate = canvasTileExtentOffset.y; // y-axis flip const yWorld2CanvasRatio = -1 * world2CanvasRatioY; // y-axis flip const matrix = Matrix4d.createTranslationAndScaleXYZ(xTranslate, yTranslate, 0, world2CanvasRatioX, yWorld2CanvasRatio, 1); @@ -406,19 +421,23 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { } public override async loadTile(row: number, column: number, zoomLevel: number): Promise { - const extent4326 = this.getEPSG4326Extent(row, column, zoomLevel); let data: any; if (this.staticMode) { // Static data mode - const filteredData: Geojson.FeatureCollection = {type: "FeatureCollection", features: []}; + const filteredData: Geojson.FeatureCollection = { type: "FeatureCollection", features: [] }; - this._spatialIdx?.search(extent4326.longitudeLeft, extent4326.latitudeBottom, extent4326.longitudeRight, extent4326.latitudeTop, + this._spatialIdx?.search( + extent4326.longitudeLeft, + extent4326.latitudeBottom, + extent4326.longitudeRight, + extent4326.latitudeTop, (index: number) => { filteredData.features.push(this._staticData!.features[index]); return true; - }); + }, + ); data = filteredData; } else { @@ -469,7 +488,7 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { const symbRenderer = ArcGisSymbologyCanvasRenderer.create(this._renderer, this._defaultSymbol); const renderer = new FeatureCanvasRenderer(ctx, symbRenderer, transfo); - const featureReader = new OgcApiFeaturesReader(); + const featureReader = new OgcApiFeaturesReader(); await featureReader.readAndRender(data, renderer); if (this._drawDebugInfo) @@ -500,7 +519,14 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { return new ImageSource(base64StringToUint8Array(base64Png), format); } - public override async getFeatureInfo(featureInfos: MapLayerFeatureInfo[], quadId: QuadId, carto: Cartographic, _tree: ImageryMapTileTree, hit: HitDetail, options?: MapFeatureInfoOptions): Promise { + public override async getFeatureInfo( + featureInfos: MapLayerFeatureInfo[], + quadId: QuadId, + carto: Cartographic, + _tree: ImageryMapTileTree, + hit: HitDetail, + options?: MapFeatureInfoOptions, + ): Promise { const tileExtent = this.getEPSG4326Extent(quadId.row, quadId.column, quadId.level); const tilePixelSizeX = (tileExtent.longitudeRight - tileExtent.longitudeLeft) / this.tileSize; const tilePixelSizeY = (tileExtent.latitudeTop - tileExtent.latitudeBottom) / this.tileSize; @@ -511,8 +537,10 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { // Note: We used to pass a single point as the query 'geometry' and leverage the 'distance' parameter, turns // out that approach was a lot slower on some server compared to using a single envelope. const bbox: WGS84Extent = { - longitudeLeft: carto.longitudeDegrees - toleranceWorldX, latitudeBottom: carto.latitudeDegrees - toleranceWorldY, - longitudeRight: carto.longitudeDegrees + toleranceWorldX, latitudeTop: carto.latitudeDegrees + toleranceWorldY, + longitudeLeft: carto.longitudeDegrees - toleranceWorldX, + latitudeBottom: carto.latitudeDegrees - toleranceWorldY, + longitudeRight: carto.longitudeDegrees + toleranceWorldX, + latitudeTop: carto.latitudeDegrees + toleranceWorldY, }; const bboxStr = this.getEPSG4326ExtentString(bbox, false); @@ -533,11 +561,10 @@ export class OgcApiFeaturesProvider extends MapLayerImageryProvider { const featureReader = new OgcApiFeaturesReader(); await featureReader.readFeatureInfo({ - collection:data, + collection: data, layerSettings: this._settings, queryables: this._queryables, - geomRenderer: new FeatureGraphicsRenderer({viewport: hit.viewport, crs: "wgs84"})}, - featureInfos ); + geomRenderer: new FeatureGraphicsRenderer({ viewport: hit.viewport, crs: "wgs84" }), + }, featureInfos); } } - diff --git a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesReader.ts b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesReader.ts index cdacf00e9168..5b88d25581c2 100644 --- a/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesReader.ts +++ b/extensions/map-layers-formats/src/OgcApiFeatures/OgcApiFeaturesReader.ts @@ -3,13 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Transform } from "@itwin/core-geometry"; -import { GeoJSONGeometryReader } from "../GeoJSON/GeoJSONGeometryReader"; -import * as Geojson from "geojson"; import { PrimitiveValue, PropertyValueFormat, StandardTypeNames } from "@itwin/appui-abstract"; import { ImageMapLayerSettings } from "@itwin/core-common"; +import { + FeatureAttributeDrivenSymbology, + FeatureGeometryRenderer, + GraphicPrimitive, + GraphicsGeometryRenderer, + MapLayerFeature, + MapLayerFeatureAttribute, + MapLayerFeatureInfo, + MapSubLayerFeatureInfo, +} from "@itwin/core-frontend"; +import { Transform } from "@itwin/core-geometry"; +import * as Geojson from "geojson"; import { FeatureInfoReader } from "../Feature/FeatureInfoReader"; -import { FeatureAttributeDrivenSymbology, FeatureGeometryRenderer, GraphicPrimitive, GraphicsGeometryRenderer, MapLayerFeature, MapLayerFeatureAttribute, MapLayerFeatureInfo, MapSubLayerFeatureInfo } from "@itwin/core-frontend"; +import { GeoJSONGeometryReader } from "../GeoJSON/GeoJSONGeometryReader"; /** @internal */ export type OgcFeaturePropertyType = "string" | "number" | "integer" | "datetime" | "geometry" | "boolean"; @@ -23,7 +32,7 @@ export interface ReadOgcApiFeaturesInfoOptions { } /** @internal */ -export class OgcApiFeaturesReader extends FeatureInfoReader { +export class OgcApiFeaturesReader extends FeatureInfoReader { public transform: Transform | undefined; public constructor() { @@ -34,7 +43,7 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { if (attrSymbology && feature) { const symbolFields = attrSymbology.rendererFields; if (symbolFields && symbolFields.length > 0 && feature.properties) { - const featureAttr: {[key: string]: any} = {}; + const featureAttr: { [key: string]: any } = {}; for (const [attrKey, attrValue] of Object.entries(feature.properties)) if (symbolFields.includes(attrKey)) { featureAttr[attrKey] = attrValue; @@ -47,7 +56,6 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { public async readAndRender(data: Geojson.FeatureCollection, renderer: FeatureGeometryRenderer) { const responseObj = data; if (responseObj.type === "FeatureCollection") { - const geomReader = new GeoJSONGeometryReader(renderer); for (const feature of responseObj.features) { @@ -97,7 +105,7 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { const getRecordInfo = (fieldName: string, value: any): MapLayerFeatureAttribute => { let typename = StandardTypeNames.String; - const propertyValue: PrimitiveValue = {valueFormat: PropertyValueFormat.Primitive}; + const propertyValue: PrimitiveValue = { valueFormat: PropertyValueFormat.Primitive }; if (value === null) { value = undefined; @@ -129,10 +137,10 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { propertyValue.displayValue = strValue; } - return {value: propertyValue, property: { name: fieldName, displayLabel: fieldName, typename }}; + return { value: propertyValue, property: { name: fieldName, displayLabel: fieldName, typename } }; }; - let geomReader: GeoJSONGeometryReader|undefined; + let geomReader: GeoJSONGeometryReader | undefined; if (opts.geomRenderer) { geomReader = new GeoJSONGeometryReader(opts.geomRenderer); } @@ -146,7 +154,7 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { // Read all features attributes / geometries for (const responseFeature of opts.collection.features) { - const feature: MapLayerFeature = {attributes: []}; + const feature: MapLayerFeature = { attributes: [] }; if (responseFeature.properties) { for (const [key, value] of Object.entries(responseFeature.properties)) @@ -157,7 +165,7 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { await geomReader.readGeometry(responseFeature.geometry as any); const graphics = opts.geomRenderer.moveGraphics(); feature.geometries = graphics.map((graphic: GraphicPrimitive) => { - return {graphic}; + return { graphic }; }); } subLayerInfo.features.push(feature); @@ -169,5 +177,4 @@ export class OgcApiFeaturesReader extends FeatureInfoReader { featureInfos.push(layerInfo); } - } diff --git a/extensions/map-layers-formats/src/Tools/GeometryTerrainDraper.ts b/extensions/map-layers-formats/src/Tools/GeometryTerrainDraper.ts index 7815add08b9a..a589cf44f1e0 100644 --- a/extensions/map-layers-formats/src/Tools/GeometryTerrainDraper.ts +++ b/extensions/map-layers-formats/src/Tools/GeometryTerrainDraper.ts @@ -2,12 +2,36 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - CollectTileStatus, DisclosedTileTreeSet, - GeometryTileTreeReference, IModelApp, - Tile, TileGeometryCollector, TileUser, Viewport } from "@itwin/core-frontend"; -import { Angle, ConvexClipPlaneSet, CurvePrimitive, GrowableXYZArray, IndexedPolyface, IndexedPolyfaceSubsetVisitor, Loop, Point3d, Polyface, PolyfaceClip, PolyfaceQuery, PolygonOps, Range3d, Ray3d, SweepLineStringToFacetsOptions, Transform, Vector3d } from "@itwin/core-geometry"; import { Logger } from "@itwin/core-bentley"; +import { + CollectTileStatus, + DisclosedTileTreeSet, + GeometryTileTreeReference, + IModelApp, + Tile, + TileGeometryCollector, + TileUser, + Viewport, +} from "@itwin/core-frontend"; +import { + Angle, + ConvexClipPlaneSet, + CurvePrimitive, + GrowableXYZArray, + IndexedPolyface, + IndexedPolyfaceSubsetVisitor, + Loop, + Point3d, + Polyface, + PolyfaceClip, + PolyfaceQuery, + PolygonOps, + Range3d, + Ray3d, + SweepLineStringToFacetsOptions, + Transform, + Vector3d, +} from "@itwin/core-geometry"; const loggerCategory = "MapLayersFormats.GeometryTerrainDraper"; @@ -34,7 +58,7 @@ class LineSegmentCollector extends TileGeometryCollector { status = "reject"; } - Logger.logTrace(loggerCategory, `collectTile - tile: ${tile.contentId} status: ${status } isReady: ${tile.isReady} status:${tile.loadStatus}`); + Logger.logTrace(loggerCategory, `collectTile - tile: ${tile.contentId} status: ${status} isReady: ${tile.isReady} status:${tile.loadStatus}`); return status; } @@ -45,7 +69,12 @@ class LineSegmentCollector extends TileGeometryCollector { clipper.transformInPlace(this._options.transform); for (let i = 0; i < this._points.length - 1 && !inside; i++) - inside = clipper.announceClippedSegmentIntervals(0, 1, this._points.getPoint3dAtUncheckedPointIndex(i), this._points.getPoint3dAtUncheckedPointIndex(i + 1)); + inside = clipper.announceClippedSegmentIntervals( + 0, + 1, + this._points.getPoint3dAtUncheckedPointIndex(i), + this._points.getPoint3dAtUncheckedPointIndex(i + 1), + ); return inside; } @@ -70,7 +99,9 @@ export class GeometryTerrainDraper implements TileUser { IModelApp.tileAdmin.forgetUser(this); } - public get iModel() { return this.viewport.iModel; } + public get iModel() { + return this.viewport.iModel; + } public onRequestStateChanged() { this.viewport.invalidateDecorations(); @@ -90,11 +121,11 @@ export class GeometryTerrainDraper implements TileUser { const topFacets: number[] = []; const facetNormal = Vector3d.createZero(); - for (const visitor = mesh.createVisitor(0); visitor.moveToNextFacet(); ) { + for (const visitor = mesh.createVisitor(0); visitor.moveToNextFacet();) { if (PolygonOps.unitNormal(visitor.point, facetNormal)) { const theta = facetNormal.angleFromPerpendicular(sweepVector); if (!theta.isMagnitudeLessThanOrEqual(this.sideAngle)) { // skip side facet - if (facetNormal.dotProduct(sweepVector) > 0) // this is a top facet + if (facetNormal.dotProduct(sweepVector) > 0) // this is a top facet topFacets.push(visitor.currentReadIndex()); } } @@ -117,14 +148,14 @@ export class GeometryTerrainDraper implements TileUser { collector.requestMissingTiles(); if (collector.isAllGeometryLoaded && collector.polyfaces.length > 0) { - for (const polyface of collector.polyfaces) { // Use this to serialize (problematic) polyface // console.log (`const polyface = ${JSON.stringify(IModelJson.Writer.toIModelJson(polyface))}`); outStrings.push(...PolyfaceQuery.sweepLineStringToFacets( inPoints, polyface, - SweepLineStringToFacetsOptions.create(Vector3d.unitZ(), this.sideAngle, true, true, false, false))); + SweepLineStringToFacetsOptions.create(Vector3d.unitZ(), this.sideAngle, true, true, false, false), + )); } return "complete"; @@ -170,14 +201,14 @@ export class GeometryTerrainDraper implements TileUser { expandedRange.extendZOnly(-this.maxDistanceZ); expandedRange.extendZOnly(this.maxDistanceZ); - const collector = new TileGeometryCollector({chordTolerance, range: expandedRange, user: this }); + const collector = new TileGeometryCollector({ chordTolerance, range: expandedRange, user: this }); this.treeRef.collectTileGeometry(collector); collector.requestMissingTiles(); if (collector.isAllGeometryLoaded && collector.polyfaces.length > 0) { for (const polyface of collector.polyfaces) { // Im assuming a single polyface here since we are draping a single point - const facetLocation = PolyfaceQuery.intersectRay3d(polyface, Ray3d.create(point, Vector3d.unitZ() )); + const facetLocation = PolyfaceQuery.intersectRay3d(polyface, Ray3d.create(point, Vector3d.unitZ())); if (!facetLocation) continue; outPoint.setFromPoint3d(facetLocation.point); diff --git a/extensions/map-layers-formats/src/Tools/MapFeatureInfoDecorator.ts b/extensions/map-layers-formats/src/Tools/MapFeatureInfoDecorator.ts index 768143d5fa0a..ba6478b4e452 100644 --- a/extensions/map-layers-formats/src/Tools/MapFeatureInfoDecorator.ts +++ b/extensions/map-layers-formats/src/Tools/MapFeatureInfoDecorator.ts @@ -2,16 +2,29 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Logger } from "@itwin/core-bentley"; import { Base64EncodedString, ColorDef } from "@itwin/core-common"; import { - BeButtonEvent, Cluster, DecorateContext, Decorator, - GeometryTileTreeReference, GraphicBuilder, GraphicPrimitive, GraphicType, IModelApp, MapTileTreeReference, Marker, MarkerImage, MarkerSet, + BeButtonEvent, + Cluster, + DecorateContext, + Decorator, + GeometryTileTreeReference, + GraphicBuilder, + GraphicPrimitive, + GraphicType, + IModelApp, + MapTileTreeReference, + Marker, + MarkerImage, + MarkerSet, ScreenViewport, - TileTreeReference, Viewport } from "@itwin/core-frontend"; + TileTreeReference, + Viewport, +} from "@itwin/core-frontend"; import { GrowableXYZArray, LineString3d, Point2d, Point3d, Polyface, Range3d, Transform, XAndY, XYAndZ } from "@itwin/core-geometry"; -import { MapFeatureInfoToolData } from "./MapFeatureInfoTool"; import { GeometryTerrainDraper } from "./GeometryTerrainDraper"; -import { Logger } from "@itwin/core-bentley"; +import { MapFeatureInfoToolData } from "./MapFeatureInfoTool"; const loggerCategory = "MapLayersFormats.MapFeatureInfoDecorator"; /** @internal */ @@ -29,7 +42,9 @@ class PinMarkerCluster extends Marker { constructor(location: XYAndZ, size: XAndY, cluster: Cluster, image: MarkerImage | Promise | undefined) { super(location, size); - this.title = IModelApp.localization.getLocalizedString("mapLayersFormats:Messages.MapFeatureInfoDecorator.clusterZoomIn", { nbInstances: cluster.markers.length}); + this.title = IModelApp.localization.getLocalizedString("mapLayersFormats:Messages.MapFeatureInfoDecorator.clusterZoomIn", { + nbInstances: cluster.markers.length, + }); this.imageOffset = new Point3d(0, size.y * 0.5); this.label = cluster.markers.length.toLocaleString(); @@ -51,7 +66,9 @@ class PinMarkerCluster extends Marker { ctx.stroke(); } - public override onMouseButton(_ev: BeButtonEvent): boolean { return true; } // Don't allow clicks to be sent to active tool... + public override onMouseButton(_ev: BeButtonEvent): boolean { + return true; + } // Don't allow clicks to be sent to active tool... } /** @internal */ @@ -113,7 +130,7 @@ export class MapFeatureInfoDecorator implements Decorator { public readonly useCachedDecorations = true; public readonly disableTerrainDraper = false; public markerSize = new Point2d(32, 32); - public lineWidth = 3; + public lineWidth = 3; // This is the maximum allowed size of a geometry, in pixels, to be draped. // If the value is too large, we will end up downloading tons of terrain tiles, and possibly hang for too long. @@ -124,13 +141,17 @@ export class MapFeatureInfoDecorator implements Decorator { public chordTolerancePixels = 20; private _highlightColor = ColorDef.from(0, 255, 255, 127); - public get highlightColor() { return this._highlightColor;} + public get highlightColor() { + return this._highlightColor; + } public set highlightColor(color: ColorDef) { this.updateMarkerImage(); this._highlightColor = color; } - public get defaultMarkerIconSvgXml() { return ``; } + public get defaultMarkerIconSvgXml() { + return ``; + } private _scratchPoints = new GrowableXYZArray(); @@ -142,7 +163,7 @@ export class MapFeatureInfoDecorator implements Decorator { private _markerSet = new PinMarkerSet(); // Extra markers can be added outside the normal state - public extraMarkers: Point3d[]|undefined; + public extraMarkers: Point3d[] | undefined; private _data: MapFeatureInfoToolData | undefined; @@ -172,22 +193,21 @@ export class MapFeatureInfoDecorator implements Decorator { } private computeChordTolerance(viewport: Viewport, drapeRange: Range3d) { - const drapeSizeWorld = Math.max(drapeRange.xLength(), drapeRange.yLength()); + const drapeSizeWorld = Math.max(drapeRange.xLength(), drapeRange.yLength()); const pixelSize = this.computePixelSize(viewport, true, drapeRange.center); - const maxDrapeRangeSizeRatio = this.maxDrapeSizePixels / (drapeSizeWorld / pixelSize); + const maxDrapeRangeSizeRatio = this.maxDrapeSizePixels / (drapeSizeWorld / pixelSize); if (maxDrapeRangeSizeRatio < 1) { Logger.logWarning(loggerCategory, "Element too large; chord tolerance was adjusted"); - return (pixelSize / maxDrapeRangeSizeRatio)*this.chordTolerancePixels; + return (pixelSize / maxDrapeRangeSizeRatio) * this.chordTolerancePixels; } - return pixelSize*this.chordTolerancePixels; - }; + return pixelSize * this.chordTolerancePixels; + } public clearData = () => { this._data = undefined; }; public setData = (data: MapFeatureInfoToolData) => { - this._drapedPrimitives.clear(); this._allGeomDraped = false; this.hidden = false; @@ -198,7 +218,6 @@ export class MapFeatureInfoDecorator implements Decorator { this._drapeGraphicsStates = []; if (!this.disableTerrainDraper && this._data.mapInfo?.layerInfos && data.hit.viewport.displayStyle.displayTerrain) { - if (data.hit?.modelId) { const drapeTreeRef = this.getGeometryTreeRef(data.hit.viewport); if (drapeTreeRef) { @@ -235,10 +254,10 @@ export class MapFeatureInfoDecorator implements Decorator { return undefined; } - let transform: Transform|undefined; + let transform: Transform | undefined; const groundBias = context.viewport.displayStyle.backgroundMapSettings.groundBias; if (groundBias !== 0) { - transform = Transform.createTranslationXYZ(0, 0 , groundBias); + transform = Transform.createTranslationXYZ(0, 0, groundBias); } const builder = context.createGraphicBuilder(this._graphicType, transform); @@ -258,8 +277,8 @@ export class MapFeatureInfoDecorator implements Decorator { } // Add extra markers if any specified - if ( this.extraMarkers !== undefined) { - this.extraMarkers.forEach((markerPoint)=> { + if (this.extraMarkers !== undefined) { + this.extraMarkers.forEach((markerPoint) => { builder.setSymbology(this.highlightColor, this.highlightColor, this.lineWidth); this._markerSet.markers.add(new PinMarker(markerPoint, this.markerSize, this._markerImage)); }); @@ -282,11 +301,10 @@ export class MapFeatureInfoDecorator implements Decorator { return Range3d.createNull(); }; - for (const layerInfo of this._data?.mapInfo?.layerInfos??[]) { - for (const subLayerInfo of layerInfo?.subLayerInfos??[]) { + for (const layerInfo of this._data?.mapInfo?.layerInfos ?? []) { + for (const subLayerInfo of layerInfo?.subLayerInfos ?? []) { for (const feature of subLayerInfo.features) { - - feature.geometries?.forEach(((geom)=> { + feature.geometries?.forEach((geom) => { const range = getGraphicRange(geom.graphic); this._drapeGraphicsStates.push({ graphic: geom.graphic, @@ -294,7 +312,7 @@ export class MapFeatureInfoDecorator implements Decorator { chordTolerance: this.computeChordTolerance(viewport, range), range, }); - } )); + }); } } } @@ -322,7 +340,7 @@ export class MapFeatureInfoDecorator implements Decorator { state.collectorState = "complete"; } } else if (state.graphic.type === "loop") { - const loop = state.graphic.loop; + const loop = state.graphic.loop; const outMeshes: Polyface[] = []; if ("loading" === this._draper.drapeLoop(outMeshes, loop, state.chordTolerance, state.range)) { hasMissingDrapeGeoms = true; @@ -362,7 +380,9 @@ export class MapFeatureInfoDecorator implements Decorator { if (this._drapedPrimitives.points.length > 0) { for (let i = 0; i < this._drapedPrimitives.points.length; i++) { - this._markerSet.markers.add(new PinMarker(this._drapedPrimitives.points.getPoint3dAtUncheckedPointIndex(i), this.markerSize, this._markerImage)); + this._markerSet.markers.add( + new PinMarker(this._drapedPrimitives.points.getPoint3dAtUncheckedPointIndex(i), this.markerSize, this._markerImage), + ); } } } @@ -384,14 +404,11 @@ export class MapFeatureInfoDecorator implements Decorator { } else { builder.addPrimitive(geom.graphic); } - } } } } - } - } } diff --git a/extensions/map-layers-formats/src/Tools/MapFeatureInfoTool.ts b/extensions/map-layers-formats/src/Tools/MapFeatureInfoTool.ts index 0bfb36c6da85..60c87d462b74 100644 --- a/extensions/map-layers-formats/src/Tools/MapFeatureInfoTool.ts +++ b/extensions/map-layers-formats/src/Tools/MapFeatureInfoTool.ts @@ -6,6 +6,8 @@ * @module MapLayersFormats */ +import { BeEvent } from "@itwin/core-bentley"; +import { ImageMapLayerSettings, MapImageryProps, MapImagerySettings, MapLayerProps } from "@itwin/core-common"; import { BeButtonEvent, EventHandled, @@ -25,10 +27,8 @@ import { ToolAssistanceSection, Viewport, } from "@itwin/core-frontend"; -import { BeEvent } from "@itwin/core-bentley"; -import { ImageMapLayerSettings, MapImageryProps, MapImagerySettings, MapLayerProps } from "@itwin/core-common"; -import { MapFeatureInfoDecorator } from "./MapFeatureInfoDecorator"; import { mapInfoIcon } from "../Icons/MapInfoIcon"; +import { MapFeatureInfoDecorator } from "./MapFeatureInfoDecorator"; /** * Data provided every time [[MapFeatureInfoTool]] retrieves feature information. @@ -41,36 +41,38 @@ export interface MapFeatureInfoToolData { } class ActiveMapLayerState { - private _activeMapLayers: MapLayerInfoFromTileTree[]|undefined; - public get activeMapLayers() {return this._activeMapLayers;} - public set activeMapLayers(active: MapLayerInfoFromTileTree[]|undefined) { + private _activeMapLayers: MapLayerInfoFromTileTree[] | undefined; + public get activeMapLayers() { + return this._activeMapLayers; + } + public set activeMapLayers(active: MapLayerInfoFromTileTree[] | undefined) { this._activeMapLayers = active; this.isVisible = true; this.isInRange = true; this.existsInDisplayStyle = true; - } public isVisible: boolean = true; public isInRange: boolean = true; public existsInDisplayStyle: boolean = true; - public get hasMapLayers() { return (this.activeMapLayers && this.activeMapLayers.length > 0);} + public get hasMapLayers() { + return (this.activeMapLayers && this.activeMapLayers.length > 0); + } public updateWithImagerySettings(imagery: MapImageryProps) { - const result = {exists: false, hidden: false}; + const result = { exists: false, hidden: false }; this.existsInDisplayStyle = false; this.isVisible = false; if (this.hasMapLayers) { - const oldMls = this._activeMapLayers![0]; // consider only first layer for now + const oldMls = this._activeMapLayers![0]; // consider only first layer for now - let newMls: MapLayerProps|undefined; + let newMls: MapLayerProps | undefined; if (oldMls.isBaseLayer) { if (typeof (imagery.backgroundBase) !== "number") { newMls = imagery.backgroundBase; } } else if (oldMls.index?.isOverlay && imagery.overlayLayers && imagery.overlayLayers.length > oldMls.index.index) { newMls = imagery.overlayLayers[oldMls.index.index]; - } else if ((oldMls.index !== undefined) && imagery.backgroundLayers && imagery.backgroundLayers.length > oldMls.index.index) { newMls = imagery.backgroundLayers[oldMls.index.index]; } @@ -79,31 +81,30 @@ class ActiveMapLayerState { // by using the serialized JSON object let tmpNewMls = newMls; if (newMls && newMls.visible !== oldMls.settings.visible) { - tmpNewMls = {...newMls, visible: oldMls.settings.visible}; + tmpNewMls = { ...newMls, visible: oldMls.settings.visible }; } const newJson = tmpNewMls ? JSON.stringify(tmpNewMls) : ""; const oldJson = JSON.stringify(oldMls.settings.toJSON()); - if (newJson === oldJson ) { + if (newJson === oldJson) { // We consider newMls and OldMls to be the same mapLayer instance. this.existsInDisplayStyle = true; this.isVisible = newMls!.visible ? true : false; } - } return result; } public updateWithScaleRangeVisibility(layerIndexes: MapLayerScaleRangeVisibility[]) { if (this.hasMapLayers) { - const currentMls = this.activeMapLayers![0]; // consider only first layer for now + const currentMls = this.activeMapLayers![0]; // consider only first layer for now for (const scaleRangeVisibility of layerIndexes) { if (currentMls.index?.index === scaleRangeVisibility.index) { - this.isInRange = scaleRangeVisibility.visibility === MapTileTreeScaleRangeVisibility.Visible || scaleRangeVisibility.visibility === MapTileTreeScaleRangeVisibility.Partial; + this.isInRange = scaleRangeVisibility.visibility === MapTileTreeScaleRangeVisibility.Visible || + scaleRangeVisibility.visibility === MapTileTreeScaleRangeVisibility.Partial; } } } - } } @@ -115,7 +116,7 @@ class ActiveMapLayerState { */ export class MapFeatureInfoTool extends PrimitiveTool { public readonly onInfoReady = new BeEvent<(data: MapFeatureInfoToolData) => void>(); - public readonly onInfoCleared = new BeEvent(); + public readonly onInfoCleared = new BeEvent(); public static override toolId = "MapFeatureInfoTool"; public static override iconSpec = mapInfoIcon.dataUri; @@ -125,7 +126,7 @@ export class MapFeatureInfoTool extends PrimitiveTool { private _state: ActiveMapLayerState = new ActiveMapLayerState(); private readonly _detachListeners: VoidFunction[] = []; - private _detachOnMapImageryChanged: VoidFunction|undefined; + private _detachOnMapImageryChanged: VoidFunction | undefined; public override requireWriteableTarget(): boolean { return false; @@ -171,7 +172,6 @@ export class MapFeatureInfoTool extends PrimitiveTool { }; this._detachListeners.push(vp.onChangeView.addListener((viewport, _previousViewState) => { - // When a saved view is loaded, 'onMapImageryChanged' events are no longer handled, we have to re-attach. if (this._detachOnMapImageryChanged) { this._detachOnMapImageryChanged(); @@ -192,7 +192,7 @@ export class MapFeatureInfoTool extends PrimitiveTool { this._detachOnMapImageryChanged = vp.displayStyle.settings.onMapImageryChanged.addListener(mapImageryChangeHandler); // Every time a layer goes out of range it, its associated decoration should be hidden (and restore if enter again the range) - this._detachListeners.push(vp.onMapLayerScaleRangeVisibilityChanged.addListener(((layerIndexes: MapLayerScaleRangeVisibility[]) => { + this._detachListeners.push(vp.onMapLayerScaleRangeVisibilityChanged.addListener((layerIndexes: MapLayerScaleRangeVisibility[]) => { if (this._state.hasMapLayers) { this._state.updateWithScaleRangeVisibility(layerIndexes); if (this._state.existsInDisplayStyle && this._state.isVisible) { @@ -201,12 +201,10 @@ export class MapFeatureInfoTool extends PrimitiveTool { } } this._layerSettingsCache.clear(); - }))); - + })); } IModelApp.viewManager.addDecorator(this._decorator); - } public override async onCleanup() { @@ -231,7 +229,9 @@ export class MapFeatureInfoTool extends PrimitiveTool { if (fromCache) { mapLayerFromHit = fromCache; } else if (this.targetView) { - mapLayerFromHit = this.targetView?.mapLayerFromHit(hit).filter(((info) => info.settings instanceof ImageMapLayerSettings && info.provider?.supportsMapFeatureInfo)); + mapLayerFromHit = this.targetView?.mapLayerFromHit(hit).filter( + (info) => info.settings instanceof ImageMapLayerSettings && info.provider?.supportsMapFeatureInfo, + ); this._layerSettingsCache.set(hit.sourceId, mapLayerFromHit); } @@ -271,7 +271,7 @@ export class MapFeatureInfoTool extends PrimitiveTool { try { const aperture = (hit.viewport.pixelsFromInches(IModelApp.locateManager.apertureInches) / 2.0) + 1.5; const pixelRadius = Math.floor(aperture + 0.5); - mapInfo = await hit.viewport.getMapFeatureInfo(hit, {tolerance: pixelRadius}); + mapInfo = await hit.viewport.getMapFeatureInfo(hit, { tolerance: pixelRadius }); if (mapInfo) { this._decorator.setData({ hit, mapInfo }); } else { @@ -305,15 +305,18 @@ export class MapFeatureInfoTool extends PrimitiveTool { /** @internal */ protected showPrompt(): void { - const promptEnterPoint = IModelApp.localization.getLocalizedString("mapLayersFormats:tools.MapFeatureInfoTool.Prompts.EnterPoint"); - const promptClickIdentify= IModelApp.localization.getLocalizedString("mapLayersFormats:tools.MapFeatureInfoTool.Prompts.clickToIdentify"); + const promptClickIdentify = IModelApp.localization.getLocalizedString("mapLayersFormats:tools.MapFeatureInfoTool.Prompts.clickToIdentify"); const promptClickClear = IModelApp.localization.getLocalizedString("mapLayersFormats:tools.MapFeatureInfoTool.Prompts.clickToClear"); // Mouse Instructions const mouseInstructions: ToolAssistanceInstruction[] = []; - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, promptClickIdentify, false, ToolAssistanceInputMethod.Mouse)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, promptClickClear, false, ToolAssistanceInputMethod.Mouse)); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, promptClickIdentify, false, ToolAssistanceInputMethod.Mouse), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, promptClickClear, false, ToolAssistanceInputMethod.Mouse), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); diff --git a/extensions/map-layers-formats/src/mapLayersFormats.ts b/extensions/map-layers-formats/src/mapLayersFormats.ts index 25568d7f38b3..246ff78cd9a8 100644 --- a/extensions/map-layers-formats/src/mapLayersFormats.ts +++ b/extensions/map-layers-formats/src/mapLayersFormats.ts @@ -7,11 +7,11 @@ * @module MapLayersFormats */ import { assert } from "@itwin/core-bentley"; +import { Localization } from "@itwin/core-common"; import { IModelApp } from "@itwin/core-frontend"; import { ArcGisFeatureMapLayerFormat } from "./ArcGisFeature/ArcGisFeatureFormat"; -import { MapFeatureInfoTool } from "./Tools/MapFeatureInfoTool"; -import { Localization } from "@itwin/core-common"; import { OgcApiFeaturesMapLayerFormat } from "./OgcApiFeatures/OgcApiFeaturesFormat"; +import { MapFeatureInfoTool } from "./Tools/MapFeatureInfoTool"; /** Configuration options. * @beta @@ -24,7 +24,6 @@ export interface MapLayersFormatsConfig { * @beta */ export class MapLayersFormats { - private static _defaultNs = "mapLayersFormats"; public static localization: Localization; @@ -52,5 +51,4 @@ export class MapLayersFormats { public static get localizationNamespace(): string { return MapLayersFormats._defaultNs; } - } diff --git a/extensions/map-layers-formats/src/public/locales/en/mapLayersFormats.json b/extensions/map-layers-formats/src/public/locales/en/mapLayersFormats.json index 0ed0866108d3..b9223b58b93b 100644 --- a/extensions/map-layers-formats/src/public/locales/en/mapLayersFormats.json +++ b/extensions/map-layers-formats/src/public/locales/en/mapLayersFormats.json @@ -16,4 +16,4 @@ "clusterZoomIn": "{{nbInstances}} instances found. Zoom in for more granularity." } } -} \ No newline at end of file +} diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureFormats.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureFormats.test.ts index 1918d7d5b86b..0877f8d69ad9 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureFormats.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureFormats.test.ts @@ -5,19 +5,13 @@ *--------------------------------------------------------------------------------------------*/ import { ImageMapLayerSettings } from "@itwin/core-common"; -import { - ArcGisUtilities, - ArcGisValidateSourceArgs, - MapLayerSource, - MapLayerSourceStatus, -} from "@itwin/core-frontend"; +import { ArcGisUtilities, ArcGisValidateSourceArgs, MapLayerSource, MapLayerSourceStatus } from "@itwin/core-frontend"; import { expect } from "chai"; +import * as sinon from "sinon"; import { ArcGisFeatureMapLayerFormat } from "../../ArcGisFeature/ArcGisFeatureFormat"; import { esriFeatureSampleSource } from "./Mocks"; -import * as sinon from "sinon"; describe("ArcGisFeatureFormats", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -30,28 +24,27 @@ describe("ArcGisFeatureFormats", () => { }); it("should validateSource", async () => { - const fakeMethod = async (_args?: ArcGisValidateSourceArgs) => { - return {status: MapLayerSourceStatus.Valid}; - + return { status: MapLayerSourceStatus.Valid }; }; const validateSourceStub = sinon.stub(ArcGisUtilities, "validateSource").callsFake(fakeMethod); const source = MapLayerSource.fromJSON({ name: "dummyFeatureLayer", url: "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/FeatureServer", - formatId: ArcGisFeatureMapLayerFormat.formatId}); + formatId: ArcGisFeatureMapLayerFormat.formatId, + }); if (!source) { chai.assert.fail(); } - source.unsavedQueryParams = {key1_1: "value1_1", key1_2: "value1_2"}; - source.savedQueryParams = { key2_1: "value2_1", key2_2: "value2_2"}; + source.unsavedQueryParams = { key1_1: "value1_1", key1_2: "value1_2" }; + source.savedQueryParams = { key2_1: "value2_1", key2_2: "value2_2" }; source.userName = "username1"; source.password = "password1"; - await ArcGisFeatureMapLayerFormat.validate({source, ignoreCache: true}); + await ArcGisFeatureMapLayerFormat.validate({ source, ignoreCache: true }); expect(validateSourceStub.calledOnce).to.be.true; const firstCall = validateSourceStub.getCalls()[0]; @@ -59,8 +52,7 @@ describe("ArcGisFeatureFormats", () => { expect(JSON.stringify(actualArgs.source)).to.eql(JSON.stringify(source.toJSON())); expect(actualArgs.source.userName).to.equals(source.userName); expect(actualArgs.source.password).to.eql(source.password); - expect(actualArgs.capabilitiesFilter).to.eql(["query"] ); + expect(actualArgs.capabilitiesFilter).to.eql(["query"]); expect(actualArgs.ignoreCache).to.eql(true); }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureProvider.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureProvider.test.ts index 023352d075b7..cd21f778ad3b 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureProvider.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureProvider.test.ts @@ -3,29 +3,46 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { base64StringToUint8Array, Logger } from "@itwin/core-bentley"; import { Cartographic, ImageMapLayerSettings, ImageSourceFormat, ServerError } from "@itwin/core-common"; +import { + ArcGisGetServiceJsonArgs, + ArcGISImageryProvider, + ArcGisUtilities, + FeatureGraphicsRenderer, + HitDetail, + ImageryMapTileTree, + IModelConnection, + MapLayerFeatureInfo, + MapLayerImageryProviderStatus, + QuadId, + ScreenViewport, + ViewState3d, +} from "@itwin/core-frontend"; +import { Angle, Point3d, Transform, XYZProps } from "@itwin/core-geometry"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { ArcGisFeatureMapLayerFormat } from "../../ArcGisFeature/ArcGisFeatureFormat"; +import fetchMock from "fetch-mock"; import * as sinon from "sinon"; -import { ArcGisGetServiceJsonArgs, ArcGISImageryProvider, ArcGisUtilities, FeatureGraphicsRenderer, HitDetail, ImageryMapTileTree, IModelConnection, MapLayerFeatureInfo, MapLayerImageryProviderStatus, QuadId, ScreenViewport, ViewState3d } from "@itwin/core-frontend"; -import { NewYorkDataset } from "./NewYorkDataset"; -import { base64StringToUint8Array, Logger } from "@itwin/core-bentley"; +import * as moq from "typemoq"; +import { ArcGisFeatureMapLayerFormat } from "../../ArcGisFeature/ArcGisFeatureFormat"; +import { ArcGisFeatureProvider, DefaultArcGiSymbology } from "../../ArcGisFeature/ArcGisFeatureProvider"; import { ArcGisExtent, ArcGisFeatureFormat, ArcGisFeatureResultType, ArcGisGeometry } from "../../ArcGisFeature/ArcGisFeatureQuery"; -import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; import { ArcGisFeatureResponse } from "../../ArcGisFeature/ArcGisFeatureResponse"; -import { Angle, Point3d, Transform, XYZProps } from "@itwin/core-geometry"; -import { ArcGisPbfFeatureReader } from "../../ArcGisFeature/ArcGisPbfFeatureReader"; import { ArcGisJsonFeatureReader } from "../../ArcGisFeature/ArcGisJsonFeatureReader"; +import { ArcGisPbfFeatureReader } from "../../ArcGisFeature/ArcGisPbfFeatureReader"; import { EsriPMS } from "../../ArcGisFeature/EsriSymbology"; -import * as moq from "typemoq"; -import { ArcGisFeatureProvider, DefaultArcGiSymbology } from "../../ArcGisFeature/ArcGisFeatureProvider"; -import fetchMock from "fetch-mock"; +import { NewYorkDataset } from "./NewYorkDataset"; +import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; const expect = chai.expect; chai.use(chaiAsPromised); -const esriFeatureSampleSource = {name: "dummyFeatureLayer", url: "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer", formatId: ArcGisFeatureMapLayerFormat.formatId}; +const esriFeatureSampleSource = { + name: "dummyFeatureLayer", + url: "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer", + formatId: ArcGisFeatureMapLayerFormat.formatId, +}; const pngTransparent1x1 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="; const createImodelConnection = () => { @@ -72,28 +89,28 @@ function makeHitDetail(iModel: IModelConnection, viewport: ScreenViewport) { } function stubJsonFetch(json: string) { - fetchMock.mock("*", { + fetchMock.mock("*", { status: 200, - headers: {"Content-Type": "application/json"}, + headers: { "Content-Type": "application/json" }, body: JSON.parse(json), }); } function stubGetLayerMetadata(sandbox: sinon.SinonSandbox) { - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "PBF, JSON", supportsCoordinatesQuantization: true, minScale: 600000, maxScale: 5000, - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; }); } -function stubGetServiceJson(sandbox: sinon.SinonSandbox, json: any ) { +function stubGetServiceJson(sandbox: sinon.SinonSandbox, json: any) { return sandbox.stub(ArcGisUtilities, "getServiceJson").callsFake(async function _(_args: ArcGisGetServiceJsonArgs) { return json; }); @@ -106,20 +123,26 @@ function getDefaultLayerMetadata() { supportsCoordinatesQuantization: true, minScale: 600000, maxScale: 5000, - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; } -async function testGetFeatureInfoGeom(sandbox: sinon.SinonSandbox, fetchStub: any, expectedPrimitiveType: string, hit: HitDetail, dataset: any, nbGraphics: number = 1) { - +async function testGetFeatureInfoGeom( + sandbox: sinon.SinonSandbox, + fetchStub: any, + expectedPrimitiveType: string, + hit: HitDetail, + dataset: any, + nbGraphics: number = 1, +) { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], }); // sandbox.resetBehavior(); // Reset default stub made by 'beforeEach' - fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub + fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub stubGetLayerMetadata(sandbox); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { currentVersion: 11, capabilities: "Query" } }); @@ -128,13 +151,17 @@ async function testGetFeatureInfoGeom(sandbox: sinon.SinonSandbox, fetchStub: an await provider.initialize(); const featureInfos: MapLayerFeatureInfo[] = []; const logErrorSpy = sandbox.spy(Logger, "logError"); - const toSpatialfSpy = sandbox.stub((FeatureGraphicsRenderer.prototype as any), "toSpatial").callsFake(function _(geoPoints: unknown) { + const toSpatialfSpy = sandbox.stub(FeatureGraphicsRenderer.prototype as any, "toSpatial").callsFake(function _(geoPoints: unknown) { return geoPoints; }); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, hit); + (undefined as unknown) as ImageryMapTileTree, + hit, + ); expect(featureInfos.length).to.equals(1); const info = featureInfos[0].subLayerInfos; if (info) { @@ -147,7 +174,6 @@ async function testGetFeatureInfoGeom(sandbox: sinon.SinonSandbox, fetchStub: an expect(geometries.length).to.equals(nbGraphics); expect(geometries[0].graphic.type).to.equals(expectedPrimitiveType); } - } expect(logErrorSpy.calledOnce).to.be.false; expect(toSpatialfSpy.called).to.equals(true); @@ -160,12 +186,14 @@ describe("ArcGisFeatureProvider", () => { beforeEach(async () => { // Make sure no call to fetch is made, other it creates leaks - fetchStub = sandbox.stub((ArcGISImageryProvider.prototype as any), "fetch"); + fetchStub = sandbox.stub(ArcGISImageryProvider.prototype as any, "fetch"); // need to be mocked otherwise tests hangs - sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake(function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { - (listener as any)(); - }); + sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake( + function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { + (listener as any)(); + }, + ); }); afterEach(async () => { @@ -174,7 +202,6 @@ describe("ArcGisFeatureProvider", () => { }); it("should initialize with valid service metadata", async () => { - stubGetServiceJson(sandbox, { accessTokenRequired: false, content: NewYorkDataset.serviceCapabilities }); sandbox.stub(ArcGisFeatureProvider.prototype, "getLayerMetadata" as any).callsFake(async function _(_layerId: unknown) { @@ -190,8 +217,7 @@ describe("ArcGisFeatureProvider", () => { }); it("should initialize and set cartoRange without making extra extent request", async () => { - - stubGetServiceJson(sandbox, {accessTokenRequired: false, content:NewYorkDataset.serviceCapabilities}); + stubGetServiceJson(sandbox, { accessTokenRequired: false, content: NewYorkDataset.serviceCapabilities }); sandbox.stub(ArcGisFeatureProvider.prototype, "getLayerMetadata" as any).callsFake(async function _(_layerId: unknown) { return NewYorkDataset.streetsLayerCapabilities; @@ -211,16 +237,17 @@ describe("ArcGisFeatureProvider", () => { }); it("should make an extra extent request when none available in layer metadata", async () => { - - stubGetServiceJson(sandbox, {accessTokenRequired: false, content:NewYorkDataset.serviceCapabilities}); + stubGetServiceJson(sandbox, { accessTokenRequired: false, content: NewYorkDataset.serviceCapabilities }); const setCartoSpy = sandbox.spy(ArcGisFeatureProvider.prototype, "setCartoRangeFromExtentJson" as any); - const layerExtent = {...NewYorkDataset.streetsLayerCapabilities.extent}; - const fetchLayerExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "fetchLayerExtent" as any).callsFake(async function _(_layerId: unknown) { - return layerExtent; - }); + const layerExtent = { ...NewYorkDataset.streetsLayerCapabilities.extent }; + const fetchLayerExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "fetchLayerExtent" as any).callsFake( + async function _(_layerId: unknown) { + return layerExtent; + }, + ); - const layerCapabilitiesNoExtent = {...NewYorkDataset.streetsLayerCapabilities, extent:null}; + const layerCapabilitiesNoExtent = { ...NewYorkDataset.streetsLayerCapabilities, extent: null }; sandbox.stub(ArcGisFeatureProvider.prototype, "getLayerMetadata" as any).callsFake(async function _(_layerId: unknown) { return layerCapabilitiesNoExtent; }); @@ -235,17 +262,18 @@ describe("ArcGisFeatureProvider", () => { }); it("should make an extra extent request when none available in layer metadata", async () => { - - stubGetServiceJson(sandbox, {accessTokenRequired: false, content:NewYorkDataset.serviceCapabilities}); + stubGetServiceJson(sandbox, { accessTokenRequired: false, content: NewYorkDataset.serviceCapabilities }); const setCartoSpy = sandbox.spy(ArcGisFeatureProvider.prototype, "setCartoRangeFromExtentJson" as any); - const layerExtent = {...NewYorkDataset.streetsLayerCapabilities.extent}; - const fetchLayerExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "fetchLayerExtent" as any).callsFake(async function _(_layerId: unknown) { - return layerExtent; - }); + const layerExtent = { ...NewYorkDataset.streetsLayerCapabilities.extent }; + const fetchLayerExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "fetchLayerExtent" as any).callsFake( + async function _(_layerId: unknown) { + return layerExtent; + }, + ); - const layerExtentBadSrs = {...NewYorkDataset.streetsLayerCapabilities}; + const layerExtentBadSrs = { ...NewYorkDataset.streetsLayerCapabilities }; layerExtentBadSrs.extent.spatialReference.wkid = 1234; layerExtentBadSrs.extent.spatialReference.latestWkid = 1234; sandbox.stub(ArcGisFeatureProvider.prototype, "getLayerMetadata" as any).callsFake(async function _(_layerId: unknown) { @@ -262,7 +290,6 @@ describe("ArcGisFeatureProvider", () => { }); it("should set cartoRange from Extent json", async () => { - const newYorkLayerExtent = NewYorkDataset.streetsLayerCapabilities.extent; const settings = ImageMapLayerSettings.fromJSON(esriFeatureSampleSource); const provider = new ArcGisFeatureProvider(settings); @@ -280,33 +307,32 @@ describe("ArcGisFeatureProvider", () => { expect(provider.cartoRange!.south * Angle.degreesPerRadian).to.approximately(south, delta); expect(provider.cartoRange!.east * Angle.degreesPerRadian).to.approximately(east, delta); expect(provider.cartoRange!.north * Angle.degreesPerRadian).to.approximately(north, delta); - }); it("should compose proper request to get extent", async () => { + fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub + stubGetServiceJson(sandbox, { accessTokenRequired: false, content: NewYorkDataset.serviceCapabilities }); - fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub - stubGetServiceJson(sandbox, {accessTokenRequired: false, content:NewYorkDataset.serviceCapabilities}); - - const layerCapabilitiesNoExtent = {...NewYorkDataset.streetsLayerCapabilities}; + const layerCapabilitiesNoExtent = { ...NewYorkDataset.streetsLayerCapabilities }; sandbox.stub(ArcGisFeatureProvider.prototype, "getLayerMetadata" as any).callsFake(async function _(_layerId: unknown) { return layerCapabilitiesNoExtent; }); - const referenceExtent = {extent: NewYorkDataset.streetsLayerCapabilities.extent}; - const stub = sandbox.stub((ArcGISImageryProvider.prototype as any), "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { + const referenceExtent = { extent: NewYorkDataset.streetsLayerCapabilities.extent }; + const stub = sandbox.stub(ArcGISImageryProvider.prototype as any, "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { const test = { - headers: { "content-type" : "json"}, + headers: { "content-type": "json" }, json: async () => { return referenceExtent; }, status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need - return (test as Response ); + } as unknown; // By using unknown type, I can define parts of Response I really need + return (test as Response); }); let layerId = 0; - let expectedUrl = `https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/${layerId}/query?where=1%3D1&outSR=3857&returnExtentOnly=true&f=json`; + let expectedUrl = + `https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/${layerId}/query?where=1%3D1&outSR=3857&returnExtentOnly=true&f=json`; let cachedExtent = (ArcGisFeatureProvider as any)._extentCache.get(expectedUrl); expect(cachedExtent).to.be.undefined; @@ -330,7 +356,8 @@ describe("ArcGisFeatureProvider", () => { // Force a different layerId, and check a new request has been made layerId = 2; - expectedUrl = `https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/${layerId}/query?where=1%3D1&outSR=3857&returnExtentOnly=true&f=json`; + expectedUrl = + `https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/${layerId}/query?where=1%3D1&outSR=3857&returnExtentOnly=true&f=json`; cachedExtent = (ArcGisFeatureProvider as any)._extentCache.get(expectedUrl); expect(cachedExtent).to.be.undefined; (provider as any)._layerId = layerId; @@ -343,7 +370,6 @@ describe("ArcGisFeatureProvider", () => { cachedExtent = (ArcGisFeatureProvider as any)._extentCache.get(expectedUrl); expect(cachedExtent).to.be.not.undefined; expect(cachedExtent).to.equals(referenceExtent); - }); it("should not initialize with no service metadata", async () => { @@ -352,11 +378,9 @@ describe("ArcGisFeatureProvider", () => { const provider = new ArcGisFeatureProvider(settings); await expect(provider.initialize()).to.be.rejectedWith(ServerError); - }); it("should update status when invalid token error from service", async () => { - stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { error: { code: 499 } } }); const settings = ImageMapLayerSettings.fromJSON(esriFeatureSampleSource); const provider = new ArcGisFeatureProvider(settings); @@ -378,15 +402,14 @@ describe("ArcGisFeatureProvider", () => { it("should pick the first visible sub-layer when multiple visible sub-layers", async () => { stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); const provider = new ArcGisFeatureProvider(settings); (provider as any)._format = "JSON"; await provider.initialize(); @@ -394,14 +417,13 @@ describe("ArcGisFeatureProvider", () => { }); it("should pick sub-layers from service metadata if none provided on layer settings", async () => { - stubGetServiceJson(sandbox, { - accessTokenRequired: false, content: { + accessTokenRequired: false, + content: { capabilities: "Query", layers: [ { id: 0, - }, { id: 1, @@ -410,7 +432,7 @@ describe("ArcGisFeatureProvider", () => { }, }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(id: unknown) { if (id === 1) { return getDefaultLayerMetadata(); } @@ -434,16 +456,14 @@ describe("ArcGisFeatureProvider", () => { }); it("should throw if no layer metadata from service", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return undefined; }); @@ -452,14 +472,12 @@ describe("ArcGisFeatureProvider", () => { }); it("should read supported supported format", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - let getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + let getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); @@ -474,7 +492,7 @@ describe("ArcGisFeatureProvider", () => { getServiceJsonStub = stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { currentVersion: 11, capabilities: "Query" } }); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); @@ -484,24 +502,28 @@ describe("ArcGisFeatureProvider", () => { const layerMetadata = { defaultVisibility: true, - geometryType : "esriGeometryPolygon", - drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo}; + geometryType: "esriGeometryPolygon", + drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, + }; getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, supportedQueryFormats: "JSON"}; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, supportedQueryFormats: "JSON" }; }); getServiceJsonStub.restore(); - getServiceJsonStub = stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { currentVersion: 10.91, capabilities: "Query", supportsCoordinatesQuantization: true } }); + getServiceJsonStub = stubGetServiceJson(sandbox, { + accessTokenRequired: false, + content: { currentVersion: 10.91, capabilities: "Query", supportsCoordinatesQuantization: true }, + }); provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect(provider.format).to.equals("JSON"); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, supportedQueryFormats: ""}; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, supportedQueryFormats: "" }; }); provider = new ArcGisFeatureProvider(settings); @@ -509,14 +531,12 @@ describe("ArcGisFeatureProvider", () => { }); it("should compute minLod/maxLod", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); @@ -530,26 +550,23 @@ describe("ArcGisFeatureProvider", () => { }); it("should construct empty url", async () => { - const settings = ImageMapLayerSettings.fromJSON(esriFeatureSampleSource); const provider = new ArcGisFeatureProvider(settings); const url = await provider.constructUrl(0, 0, 0); expect(url).to.equals(""); - }); it("should construct feature query url", async () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - let getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + let getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "PBF, JSON", - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; }); @@ -570,7 +587,9 @@ describe("ArcGisFeatureProvider", () => { latestWkid: 3857, }, }; - expect(url?.url).to.equals("https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100"); + expect(url?.url).to.equals( + "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100", + ); expect(url?.envelope?.xmin).to.be.closeTo(extent.xmin, 0.01); expect(url?.envelope?.ymin).to.be.closeTo(extent.ymin, 0.01); expect(url?.envelope?.xmax).to.be.closeTo(extent.xmax, 0.01); @@ -580,14 +599,16 @@ describe("ArcGisFeatureProvider", () => { // Now turn ON 'supportsCoordinatesQuantization' to ON getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); const provider2 = new ArcGisFeatureProvider(settings); await provider2.initialize(); url = provider2.constructFeatureUrl(0, 0, 0, "PBF", "tile"); - expect(url?.url).to.equals("https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D"); + expect(url?.url).to.equals( + "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D", + ); expect(url?.envelope?.xmin).to.be.closeTo(extent.xmin, 0.01); expect(url?.envelope?.ymin).to.be.closeTo(extent.ymin, 0.01); expect(url?.envelope?.xmax).to.be.closeTo(extent.xmax, 0.01); @@ -612,7 +633,9 @@ describe("ArcGisFeatureProvider", () => { const provider3 = new ArcGisFeatureProvider(settings); await provider3.initialize(); url = provider3.constructFeatureUrl(0, 0, 0, "PBF", "tile", overrideGeom); - expect(url?.url).to.equals("https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-50%2C%22ymin%22%3A-50%2C%22xmax%22%3A50%2C%22ymax%22%3A50%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D"); + expect(url?.url).to.equals( + "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-50%2C%22ymin%22%3A-50%2C%22xmax%22%3A50%2C%22ymax%22%3A50%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D", + ); expect(url?.envelope?.xmin).to.be.closeTo((overrideGeom.geom as ArcGisExtent).xmin, 0.01); expect(url?.envelope?.ymin).to.be.closeTo((overrideGeom.geom as ArcGisExtent).ymin, 0.01); expect(url?.envelope?.xmax).to.be.closeTo((overrideGeom.geom as ArcGisExtent).xmax, 0.01); @@ -622,76 +645,89 @@ describe("ArcGisFeatureProvider", () => { // Now test with a different tolerance value url = provider3.constructFeatureUrl(0, 0, 0, "PBF", "tile", overrideGeom, undefined, 10); - expect(url?.url).to.equals("https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-50%2C%22ymin%22%3A-50%2C%22xmax%22%3A50%2C%22ymax%22%3A50%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D&distance=782715.16953125"); + expect(url?.url).to.equals( + "https://dummy.com/SomeGuid/ArcGIS/rest/services/SomeService/FeatureServer/0/query?f=PBF&resultType=tile&maxRecordCountFactor=3&returnExceededLimitFeatures=false&outSR=102100&geometryType=esriGeometryEnvelope&geometry=%7B%22xmin%22%3A-50%2C%22ymin%22%3A-50%2C%22xmax%22%3A50%2C%22ymax%22%3A50%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D&units=esriSRUnit_Meter&inSR=102100&quantizationParameters=%7B%22mode%22%3A%22view%22%2C%22originPosition%22%3A%22upperLeft%22%2C%22tolerance%22%3A78271.516953125%2C%22extent%22%3A%7B%22xmin%22%3A-20037508.34%2C%22ymin%22%3A-20037508.339999996%2C%22xmax%22%3A20037508.34%2C%22ymax%22%3A20037508.340000004%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D%7D&distance=782715.16953125", + ); expect(url?.envelope?.xmin).to.be.closeTo((overrideGeom.geom as ArcGisExtent).xmin, 0.01); expect(url?.envelope?.ymin).to.be.closeTo((overrideGeom.geom as ArcGisExtent).ymin, 0.01); expect(url?.envelope?.xmax).to.be.closeTo((overrideGeom.geom as ArcGisExtent).xmax, 0.01); expect(url?.envelope?.ymax).to.be.closeTo((overrideGeom.geom as ArcGisExtent).ymax, 0.01); expect(url?.envelope?.spatialReference.wkid).to.be.equal(overrideGeom.geom.spatialReference.wkid); expect(url?.envelope?.spatialReference.latestWkid).to.be.equal(overrideGeom.geom.spatialReference.latestWkid); - }); it("should log error when getFeatureInfo cannot be performed", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { currentVersion: 11, capabilities: "Query" } }); - sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake(function _(_row: number, _column: number, _zoomLevel: number, _format: ArcGisFeatureFormat, _resultType: ArcGisFeatureResultType, _geomOverride?: ArcGisGeometry, _outFields?: string, _tolerance?: number, _returnGeometry?: boolean) { - return undefined; - }); + sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake( + function _( + _row: number, + _column: number, + _zoomLevel: number, + _format: ArcGisFeatureFormat, + _resultType: ArcGisFeatureResultType, + _geomOverride?: ArcGisGeometry, + _outFields?: string, + _tolerance?: number, + _returnGeometry?: boolean, + ) { + return undefined; + }, + ); const provider = new ArcGisFeatureProvider(settings); await provider.initialize(); const featureInfos: MapLayerFeatureInfo[] = []; const logErrorSpy = sandbox.spy(Logger, "logError"); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object)); + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), + Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), + (undefined as unknown) as ImageryMapTileTree, + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + ); expect(featureInfos.length).to.equals(0); expect(logErrorSpy.called).to.be.true; - }); it("should process data in getFeatureInfo", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "PBF, JSON", supportsCoordinatesQuantization: true, minScale: 600000, maxScale: 5000, - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { currentVersion: 11, capabilities: "Query" } }); - fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub - sandbox.stub((ArcGISImageryProvider.prototype as any), "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { + fetchStub.restore(); // fetch is always stubbed by default, restore and provide our own stub + sandbox.stub(ArcGISImageryProvider.prototype as any, "fetch").callsFake(async function _(_url: unknown, _options?: unknown) { const test = { headers: { "content-type": "application/json" }, json: async () => { return JSON.parse(PhillyLandmarksDataset.phillyAirportGetFeatureInfoQueryJson); }, status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need + } as unknown; // By using unknown type, I can define parts of Response I really need return (test as Response); }); @@ -699,45 +735,72 @@ describe("ArcGisFeatureProvider", () => { await provider.initialize(); const featureInfos: MapLayerFeatureInfo[] = []; const logErrorSpy = sandbox.spy(Logger, "logError"); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object)); + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), + Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), + (undefined as unknown) as ImageryMapTileTree, + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + ); expect(featureInfos.length).to.equals(1); expect(logErrorSpy.calledOnce).to.be.false; - }); it("should process polygon data in getFeatureInfo (GCS)", async () => { - await testGetFeatureInfoGeom(sandbox, fetchStub, "loop", makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), PhillyLandmarksDataset.phillyDoubleRingPolyQueryJson); + await testGetFeatureInfoGeom( + sandbox, + fetchStub, + "loop", + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + PhillyLandmarksDataset.phillyDoubleRingPolyQueryJson, + ); fetchMock.restore(); }); it("should process multi path data in getFeatureInfo (GCS)", async () => { - await testGetFeatureInfoGeom(sandbox, fetchStub, "linestring", makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), PhillyLandmarksDataset.phillyMultiPathQueryJson, 2); + await testGetFeatureInfoGeom( + sandbox, + fetchStub, + "linestring", + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + PhillyLandmarksDataset.phillyMultiPathQueryJson, + 2, + ); fetchMock.restore(); }); it("should process linestring data in getFeatureInfo (GCS)", async () => { - await testGetFeatureInfoGeom(sandbox, fetchStub, "linestring", makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), PhillyLandmarksDataset.phillySimplePathQueryJson); + await testGetFeatureInfoGeom( + sandbox, + fetchStub, + "linestring", + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + PhillyLandmarksDataset.phillySimplePathQueryJson, + ); fetchMock.restore(); }); it("should process pointstring data in getFeatureInfo (GCS)", async () => { - await testGetFeatureInfoGeom(sandbox, fetchStub, "pointstring", makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), PhillyLandmarksDataset.phillySimplePointQueryJson); + await testGetFeatureInfoGeom( + sandbox, + fetchStub, + "pointstring", + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + PhillyLandmarksDataset.phillySimplePointQueryJson, + ); fetchMock.restore(); }); it("should log error when exceed transfer limit", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { return { exceedTransferLimit: true, data: undefined }; }); @@ -746,26 +809,28 @@ describe("ArcGisFeatureProvider", () => { const featureInfos: MapLayerFeatureInfo[] = []; const logErrorSpy = sandbox.spy(Logger, "logError"); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object)); + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), + Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), + (undefined as unknown) as ImageryMapTileTree, + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + ); expect(featureInfos.length).to.equals(0); expect(logErrorSpy.calledOnce).to.be.true; - }); it("should log error when exceed exception thrown limit", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { throw new Error(); }); @@ -774,25 +839,28 @@ describe("ArcGisFeatureProvider", () => { const featureInfos: MapLayerFeatureInfo[] = []; const logErrorSpy = sandbox.spy(Logger, "logError"); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object)); + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), + Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), + (undefined as unknown) as ImageryMapTileTree, + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + ); expect(featureInfos.length).to.equals(0); expect(logErrorSpy.calledOnce).to.be.true; }); it("should debug Feature Geom", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { return { data: { toObject: () => undefined, @@ -806,8 +874,13 @@ describe("ArcGisFeatureProvider", () => { const featureInfos: MapLayerFeatureInfo[] = []; const logInfoSpy = sandbox.spy(Logger, "logInfo"); - await provider.getFeatureInfo(featureInfos, new QuadId(0, 0, 0), Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), - (undefined as unknown) as ImageryMapTileTree, makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object)); + await provider.getFeatureInfo( + featureInfos, + new QuadId(0, 0, 0), + Cartographic.fromDegrees({ latitude: 46, longitude: -71 }), + (undefined as unknown) as ImageryMapTileTree, + makeHitDetail(viewportMock.imodel as IModelConnection, viewportMock.object), + ); expect(featureInfos.length).to.equals(0); expect(logInfoSpy.callCount).to.equals(2); }); @@ -816,20 +889,21 @@ describe("ArcGisFeatureProvider", () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); const worldSize = 100; const canvasSize = 10; const provider = new ArcGisFeatureProvider(settings); - const getEPSG3857ExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "getEPSG3857Extent").callsFake(function (_row: number, _column: number, _zoomLevel: number) { - return { left: 0, right: worldSize, bottom: 0, top: worldSize }; - }); + const getEPSG3857ExtentStub = sandbox.stub(ArcGisFeatureProvider.prototype, "getEPSG3857Extent").callsFake( + function(_row: number, _column: number, _zoomLevel: number) { + return { left: 0, right: worldSize, bottom: 0, top: worldSize }; + }, + ); - sandbox.stub(provider, "tileSize").get(function () { - return canvasSize; // return a size of 10 to simplicity + sandbox.stub(provider, "tileSize").get(function() { + return canvasSize; // return a size of 10 to simplicity }); - let transform = ((provider as any).computeTileWorld2CanvasTransform(0, 0, 0) as Transform | undefined); + let transform = (provider as any).computeTileWorld2CanvasTransform(0, 0, 0) as Transform | undefined; let worldPoint = Point3d.createFrom({ x: worldSize * 0.5, y: worldSize * 0.5, z: 0 }); let transformedPoint = transform?.multiplyPoint3d(worldPoint); @@ -848,31 +922,29 @@ describe("ArcGisFeatureProvider", () => { // Now check translation has been applied (origin shift) getEPSG3857ExtentStub.restore(); - sandbox.stub(ArcGisFeatureProvider.prototype, "getEPSG3857Extent").callsFake(function (_row: number, _column: number, _zoomLevel: number) { + sandbox.stub(ArcGisFeatureProvider.prototype, "getEPSG3857Extent").callsFake(function(_row: number, _column: number, _zoomLevel: number) { return { left: worldSize, right: worldSize * 2, bottom: worldSize, top: worldSize * 2 }; }); worldPoint = Point3d.createFrom({ x: worldSize, y: worldSize, z: 0 }); - transform = ((provider as any).computeTileWorld2CanvasTransform(0, 0, 0) as Transform | undefined); + transform = (provider as any).computeTileWorld2CanvasTransform(0, 0, 0) as Transform | undefined; transformedPoint = transform?.multiplyPoint3d(worldPoint); expect(transformedPoint).to.not.undefined; expect(transformedPoint!.x).to.equals(0); expect(transformedPoint!.y).to.equals(10); expect(transformedPoint!.z).to.equals(0); - }); it("should loadTile from PBF request", async () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "PBF", supportsCoordinatesQuantization: true, - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; }); @@ -886,11 +958,11 @@ describe("ArcGisFeatureProvider", () => { return `data:image/png;base64,${pngTransparent1x1}`; }); - const providerStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "fetchTile").callsFake(async function _() { + const providerStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "fetchTile").callsFake(async function _() { return new ArcGisFeatureResponse("PBF", Promise.resolve({} as Response)); }); - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { return { exceedTransferLimit: false, data: { toObject: () => undefined }, @@ -910,16 +982,14 @@ describe("ArcGisFeatureProvider", () => { expect(providerStub.calledOnce).to.be.true; expect(readAndRenderSpy.calledOnce).to.be.true; expect(computeTransfoSpy.calledOnce).to.be.false; // Should not be called since we have supportsCoordinatesQuantization in layer metadata - }); it("should loadTile from JSON request", async () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return getDefaultLayerMetadata(); }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); @@ -932,11 +1002,11 @@ describe("ArcGisFeatureProvider", () => { return `data:image/png;base64,${pngTransparent1x1}`; }); - const providerStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "fetchTile").callsFake(async function _() { + const providerStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "fetchTile").callsFake(async function _() { return new ArcGisFeatureResponse("JSON", Promise.resolve({} as Response)); }); - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { return { exceedTransferLimit: false, data: { toObject: () => undefined }, @@ -961,13 +1031,12 @@ describe("ArcGisFeatureProvider", () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + }); + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "JSON", - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo, }; }); @@ -982,7 +1051,7 @@ describe("ArcGisFeatureProvider", () => { }); const extentSize = 100; - const fetchTileStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "fetchTile").callsFake(async function _() { + const fetchTileStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "fetchTile").callsFake(async function _() { const envelope: ArcGisExtent = { xmin: 0, ymin: 0, @@ -997,8 +1066,7 @@ describe("ArcGisFeatureProvider", () => { }); let firstCall = true; - sandbox.stub((ArcGisFeatureResponse.prototype as any), "getResponseData").callsFake(async function _() { - + sandbox.stub(ArcGisFeatureResponse.prototype as any, "getResponseData").callsFake(async function _() { const exceed = firstCall === true; firstCall = false; return { @@ -1018,39 +1086,53 @@ describe("ArcGisFeatureProvider", () => { // Calls #2-5: Four calls which represent a call for each sub-envelope (initial extent divided by 4) expect(fetchTileStub.getCalls().length).to.equals(5); expect(fetchTileStub.getCalls()[1].args[3]).to.eqls({ - xmin: 0, ymin: 0, xmax: extentSize * 0.5, ymax: extentSize * 0.5, + xmin: 0, + ymin: 0, + xmax: extentSize * 0.5, + ymax: extentSize * 0.5, spatialReference: { - wkid: 102100, latestWkid: 3857, + wkid: 102100, + latestWkid: 3857, }, }); expect(fetchTileStub.getCalls()[2].args[3]).to.eqls({ - xmin: 0, ymin: extentSize * 0.5, xmax: extentSize * 0.5, ymax: extentSize, + xmin: 0, + ymin: extentSize * 0.5, + xmax: extentSize * 0.5, + ymax: extentSize, spatialReference: { - wkid: 102100, latestWkid: 3857, + wkid: 102100, + latestWkid: 3857, }, }); expect(fetchTileStub.getCalls()[3].args[3]).to.eqls({ - xmin: extentSize * 0.5, ymin: 0, xmax: extentSize, ymax: extentSize * 0.5, + xmin: extentSize * 0.5, + ymin: 0, + xmax: extentSize, + ymax: extentSize * 0.5, spatialReference: { - wkid: 102100, latestWkid: 3857, + wkid: 102100, + latestWkid: 3857, }, }); expect(fetchTileStub.getCalls()[4].args[3]).to.eqls({ - xmin: extentSize * 0.5, ymin: extentSize * 0.5, xmax: extentSize, ymax: extentSize, + xmin: extentSize * 0.5, + ymin: extentSize * 0.5, + xmax: extentSize, + ymax: extentSize, spatialReference: { - wkid: 102100, latestWkid: 3857, + wkid: 102100, + latestWkid: 3857, }, }); expect(readAndRenderSpy.getCalls().length).to.equals(4); }); it("fetchTile should return undefined when to format defined", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); const provider = new ArcGisFeatureProvider(settings); // make a first request with init, should return undefined because of missing format @@ -1059,26 +1141,36 @@ describe("ArcGisFeatureProvider", () => { }); it("fetchTile should call fetch with the proper URL", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "JSON", - geometryType : "esriGeometryPolygon", + geometryType: "esriGeometryPolygon", drawingInfo: PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo, }; }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake(function _(_row: number, _column: number, _zoomLevel: number, _format: ArcGisFeatureFormat, _resultType: ArcGisFeatureResultType, _geomOverride?: ArcGisGeometry, _outFields?: string, _tolerance?: number, _returnGeometry?: boolean) { - return { url: settings.url }; - }); + sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake( + function _( + _row: number, + _column: number, + _zoomLevel: number, + _format: ArcGisFeatureFormat, + _resultType: ArcGisFeatureResultType, + _geomOverride?: ArcGisGeometry, + _outFields?: string, + _tolerance?: number, + _returnGeometry?: boolean, + ) { + return { url: settings.url }; + }, + ); const provider = new ArcGisFeatureProvider(settings); await provider.initialize(); @@ -1087,100 +1179,117 @@ describe("ArcGisFeatureProvider", () => { expect(fetchStub.calledOnce).to.be.true; const test1 = fetchStub.getCall(0).firstArg; expect(test1.toString()).to.equals(new URL(settings.url).toString()); - }); it("should throw when initializing with invalid geometry type", async () => { const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { return { defaultVisibility: true, supportedQueryFormats: "JSON", - geometryType : "esriGeometryAny", + geometryType: "esriGeometryAny", drawingInfo: PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo, }; }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake(function _(_row: number, _column: number, _zoomLevel: number, _format: ArcGisFeatureFormat, _resultType: ArcGisFeatureResultType, _geomOverride?: ArcGisGeometry, _outFields?: string, _tolerance?: number, _returnGeometry?: boolean) { - return { url: settings.url }; - }); + sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake( + function _( + _row: number, + _column: number, + _zoomLevel: number, + _format: ArcGisFeatureFormat, + _resultType: ArcGisFeatureResultType, + _geomOverride?: ArcGisGeometry, + _outFields?: string, + _tolerance?: number, + _returnGeometry?: boolean, + ) { + return { url: settings.url }; + }, + ); const provider = new ArcGisFeatureProvider(settings); - await expect(provider.initialize()).to.be.rejectedWith( Error, "Could not get default symbology for geometry type: 'esriGeometryAny'"); - + await expect(provider.initialize()).to.be.rejectedWith(Error, "Could not get default symbology for geometry type: 'esriGeometryAny'"); }); it("should construct renderer with proper default symbology", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], - }, - ); + }); const layerMetadata = { defaultVisibility: true, supportedQueryFormats: "JSON", - geometryType : "esriGeometryPoint", + geometryType: "esriGeometryPoint", drawingInfo: PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo, }; stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake(function _(_row: number, _column: number, _zoomLevel: number, _format: ArcGisFeatureFormat, _resultType: ArcGisFeatureResultType, _geomOverride?: ArcGisGeometry, _outFields?: string, _tolerance?: number, _returnGeometry?: boolean) { - return { url: settings.url }; - }); + sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake( + function _( + _row: number, + _column: number, + _zoomLevel: number, + _format: ArcGisFeatureFormat, + _resultType: ArcGisFeatureResultType, + _geomOverride?: ArcGisGeometry, + _outFields?: string, + _tolerance?: number, + _returnGeometry?: boolean, + ) { + return { url: settings.url }; + }, + ); - let getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryPoint" }; + let getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryPoint" }; }); let provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect((provider as any)._symbologyRenderer.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryMultipoint" }; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryMultipoint" }; }); provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect((provider as any)._symbologyRenderer.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryPolyline" }; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryPolyline" }; }); provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect((provider as any)._symbologyRenderer.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultSLS); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryLine" }; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryLine" }; }); provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect((provider as any)._symbologyRenderer.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultSLS); getLayerMetadataStub.restore(); - getLayerMetadataStub = sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryPolygon" }; + getLayerMetadataStub = sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryPolygon" }; }); provider = new ArcGisFeatureProvider(settings); await provider.initialize(); expect((provider as any)._symbologyRenderer.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultSFS); - }); it("should apply our own default symbol when no default symbol in metadata", async () => { - const settings = ImageMapLayerSettings.fromJSON({ ...esriFeatureSampleSource, subLayers: [{ id: 0, name: "layer1", visible: true }, { id: 2, name: "layer2", visible: true }], @@ -1190,28 +1299,39 @@ describe("ArcGisFeatureProvider", () => { const layerMetadata = { defaultVisibility: true, supportedQueryFormats: "JSON", - geometryType : "esriGeometryPoint", + geometryType: "esriGeometryPoint", drawingInfo, }; // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - (drawingInfo.renderer.defaultSymbol as any) = null; // Force no default symbology + (drawingInfo.renderer.defaultSymbol as any) = null; // Force no default symbology - sandbox.stub((ArcGisFeatureProvider.prototype as any), "getLayerMetadata").callsFake(async function (_id: unknown) { - return {...layerMetadata, geometryType : "esriGeometryPoint" }; + sandbox.stub(ArcGisFeatureProvider.prototype as any, "getLayerMetadata").callsFake(async function(_id: unknown) { + return { ...layerMetadata, geometryType: "esriGeometryPoint" }; }); stubGetServiceJson(sandbox, { accessTokenRequired: false, content: { capabilities: "Query" } }); - sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake(function _(_row: number, _column: number, _zoomLevel: number, _format: ArcGisFeatureFormat, _resultType: ArcGisFeatureResultType, _geomOverride?: ArcGisGeometry, _outFields?: string, _tolerance?: number, _returnGeometry?: boolean) { - return { url: settings.url }; - }); + sandbox.stub(ArcGisFeatureProvider.prototype, "constructFeatureUrl").callsFake( + function _( + _row: number, + _column: number, + _zoomLevel: number, + _format: ArcGisFeatureFormat, + _resultType: ArcGisFeatureResultType, + _geomOverride?: ArcGisGeometry, + _outFields?: string, + _tolerance?: number, + _returnGeometry?: boolean, + ) { + return { url: settings.url }; + }, + ); - const loadImageSpy = sandbox.spy(EsriPMS.prototype, "loadImage"); + const loadImageSpy = sandbox.spy(EsriPMS.prototype, "loadImage"); const provider = new ArcGisFeatureProvider(settings); await provider.initialize(); const nbMarkerToLoad = layerMetadata.drawingInfo.renderer.uniqueValueInfos.length + 1; // +1 for provider's default symbol - expect (loadImageSpy.getCalls().length).to.equals(nbMarkerToLoad); + expect(loadImageSpy.getCalls().length).to.equals(nbMarkerToLoad); }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureQuery.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureQuery.test.ts index 55b7177ac25c..a74eb1b25115 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureQuery.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureQuery.test.ts @@ -8,7 +8,6 @@ import * as sinon from "sinon"; import { ArcGisExtent, ArcGisFeatureQuery } from "../../ArcGisFeature/ArcGisFeatureQuery"; describe("ArcGisFeatureQuery", () => { - const sandbox = sinon.createSandbox(); beforeEach(async () => { @@ -19,8 +18,7 @@ describe("ArcGisFeatureQuery", () => { }); it("should not apply different switches if not needed", async () => { - - const query = new ArcGisFeatureQuery("https://test.com/rest/",0, "JSON", 3857); + const query = new ArcGisFeatureQuery("https://test.com/rest/", 0, "JSON", 3857); const queryUrl = query.toString(); expect(queryUrl).to.not.contains("resultRecordCount"); expect(queryUrl).to.not.contains("resultOffset"); @@ -36,37 +34,36 @@ describe("ArcGisFeatureQuery", () => { }); it("should not apply different switches if not needed", async () => { - const extentSize = 100; const fakeEnvelope: ArcGisExtent = { - xmin : 0, - ymin : 0, - xmax : extentSize, - ymax : extentSize, - spatialReference : { - wkid : 102100, - latestWkid : 3857, - }}; - const query = new ArcGisFeatureQuery("https://test.com/rest/",0, "JSON", 3857, - { - resultRecordCount: 10, - resultOffset: 11, - returnGeometry: true, - geometry: {type:"esriGeometryEnvelope", geom:fakeEnvelope}, - geometryType: "esriGeometryEnvelope", - spatialRel: "esriSpatialRelIntersects", - resultType: "tile", - maxRecordCountFactor: 1000, - returnExceededLimitFeatures: false, - quantizationParameters: { - mode: "view", - originPosition: "upperLeft", - tolerance: 10, - extent: fakeEnvelope, - }, - outFields: "test", - distance: 100, - }); + xmin: 0, + ymin: 0, + xmax: extentSize, + ymax: extentSize, + spatialReference: { + wkid: 102100, + latestWkid: 3857, + }, + }; + const query = new ArcGisFeatureQuery("https://test.com/rest/", 0, "JSON", 3857, { + resultRecordCount: 10, + resultOffset: 11, + returnGeometry: true, + geometry: { type: "esriGeometryEnvelope", geom: fakeEnvelope }, + geometryType: "esriGeometryEnvelope", + spatialRel: "esriSpatialRelIntersects", + resultType: "tile", + maxRecordCountFactor: 1000, + returnExceededLimitFeatures: false, + quantizationParameters: { + mode: "view", + originPosition: "upperLeft", + tolerance: 10, + extent: fakeEnvelope, + }, + outFields: "test", + distance: 100, + }); const queryUrl = query.toString(); expect(queryUrl).to.contains("resultRecordCount=10"); expect(queryUrl).to.contains("resultOffset=11"); @@ -75,30 +72,30 @@ describe("ArcGisFeatureQuery", () => { expect(queryUrl).to.contains("maxRecordCountFactor=1000"); expect(queryUrl).to.contains("returnExceededLimitFeatures=false"); expect(queryUrl).to.contains("geometryType=esriGeometryEnvelope"); - expect(queryUrl).to.contains(`geometry=%7B%22xmin%22%3A0%2C%22ymin%22%3A0%2C%22xmax%22%3A100%2C%22ymax%22%3A100%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D`); + expect(queryUrl).to.contains( + `geometry=%7B%22xmin%22%3A0%2C%22ymin%22%3A0%2C%22xmax%22%3A100%2C%22ymax%22%3A100%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D`, + ); expect(queryUrl).to.contains("inSR=102100"); expect(queryUrl).to.contains("outFields=test"); expect(queryUrl).to.contains("distance=100"); expect(queryUrl).to.contains("units=esriSRUnit_Meter"); - }); it("should not include geometry only when applicable", async () => { - const extentSize = 100; const fakeEnvelope: ArcGisExtent = { - xmin : 0, - ymin : 0, - xmax : extentSize, - ymax : extentSize, - spatialReference : { - wkid : 102100, - latestWkid : 3857, - }}; - const query = new ArcGisFeatureQuery("https://test.com/rest/",0, "JSON", 3857, - { - spatialRel: "esriSpatialRelIntersects", - }); + xmin: 0, + ymin: 0, + xmax: extentSize, + ymax: extentSize, + spatialReference: { + wkid: 102100, + latestWkid: 3857, + }, + }; + const query = new ArcGisFeatureQuery("https://test.com/rest/", 0, "JSON", 3857, { + spatialRel: "esriSpatialRelIntersects", + }); let queryUrl = query.toString(); expect(queryUrl).to.not.contains("geometryType="); @@ -106,12 +103,12 @@ describe("ArcGisFeatureQuery", () => { expect(queryUrl).to.not.contains("inSR="); query.spatialRel = undefined; - query.geometry = {type:"esriGeometryEnvelope", geom:fakeEnvelope}; + query.geometry = { type: "esriGeometryEnvelope", geom: fakeEnvelope }; queryUrl = query.toString(); expect(queryUrl).to.contains("geometryType=esriGeometryEnvelope"); - expect(queryUrl).to.contains(`geometry=%7B%22xmin%22%3A0%2C%22ymin%22%3A0%2C%22xmax%22%3A100%2C%22ymax%22%3A100%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D`); + expect(queryUrl).to.contains( + `geometry=%7B%22xmin%22%3A0%2C%22ymin%22%3A0%2C%22xmax%22%3A100%2C%22ymax%22%3A100%2C%22spatialReference%22%3A%7B%22wkid%22%3A102100%2C%22latestWkid%22%3A3857%7D%7D`, + ); expect(queryUrl).to.contains("inSR=102100"); - }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureRenderer.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureRenderer.test.ts index 0bfd880dcec7..b80a33c32e36 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureRenderer.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureRenderer.test.ts @@ -3,17 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Point3d, Transform } from "@itwin/core-geometry"; import { expect } from "chai"; import * as sinon from "sinon"; -import { fakeContext } from "./Mocks"; import { ArcGisSimpleSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; +import { FeatureCanvasRenderer } from "../../Feature/FeatureCanvasRenderer"; +import { fakeContext } from "./Mocks"; import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; -import { Point3d, Transform } from "@itwin/core-geometry"; import { TestUtils } from "./TestUtils"; -import { FeatureCanvasRenderer } from "../../Feature/FeatureCanvasRenderer"; describe("FeatureCanvasRenderer", () => { - const sandbox = sinon.createSandbox(); let beginPathSpy: sinon.SinonSpy<[], void>; @@ -37,8 +36,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render simple path, stride = 2", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const coords = [1, 2, 3, 4]; const applyFillStyleSpy = sandbox.spy(symbolRenderer, "applyFillStyle"); @@ -65,8 +66,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render simple filled path", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const coords = [1, 2, 3, 4]; @@ -91,12 +94,13 @@ describe("FeatureCanvasRenderer", () => { expect(applyFillStyleSpy.calledOnce).to.be.true; expect(applyStrokeStyleSpy.calledOnce).to.be.true; - }); it("should render simple Path, stride = 3", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const coords = [1, 2, 3, 4, 5, 6]; @@ -115,12 +119,13 @@ describe("FeatureCanvasRenderer", () => { expect(strokeSpy.calledOnce).to.be.true; expect(fillSpy.called).to.be.false; expect(closePathSpy.called).to.be.false; - }); it("should render multiple Paths, stride = 2", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const coords = [1, 2, 3, 4]; const applyFillStyleSpy = sandbox.spy(symbolRenderer, "applyFillStyle"); @@ -147,8 +152,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should not render invalid with stride value", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const coords = [1, 2, 3, 4]; @@ -164,8 +171,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render Path and apply transform, relativeCoords OFF", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const fakeOffset = 10; const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer, Transform.createTranslation(Point3d.create(fakeOffset, fakeOffset))); @@ -183,12 +192,13 @@ describe("FeatureCanvasRenderer", () => { // IMPORTANT: Only first coord is absolute, following coords are expressed relative to previous coord. expect(lineToSpy.getCalls()[0].args[0]).to.equals(coords[2] + fakeOffset); expect(lineToSpy.getCalls()[0].args[1]).to.equals(coords[3] + fakeOffset); - }); it("should render single Point, no transform, relativeCoords OFF", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); @@ -199,12 +209,13 @@ describe("FeatureCanvasRenderer", () => { expect(drawPointStub.calledOnce).to.be.true; expect(drawPointStub.getCalls()[0].args[1]).to.equals(coords[0]); expect(drawPointStub.getCalls()[0].args[2]).to.equals(coords[1]); - }); it("should render single Point and apply transform, relativeCoords OFF", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const fakeOffset = 10; const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer, Transform.createTranslation(Point3d.create(fakeOffset, fakeOffset))); @@ -216,12 +227,13 @@ describe("FeatureCanvasRenderer", () => { expect(drawPointStub.calledOnce).to.be.true; expect(drawPointStub.getCalls()[0].args[1]).to.equals(coords[0] + fakeOffset); expect(drawPointStub.getCalls()[0].args[2]).to.equals(coords[1] + fakeOffset); - }); it("should render multi Point, transform, relativeCoords OFF", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); @@ -237,8 +249,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render multi Point and apply transform, relativeCoords OFF", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const fakeOffset = 10; const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer, Transform.createTranslation(Point3d.create(fakeOffset, fakeOffset))); @@ -255,8 +269,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render multi Point and apply transform, relativeCoords ON", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const fakeOffset = 10; const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer, Transform.createTranslation(Point3d.create(fakeOffset, fakeOffset))); @@ -273,8 +289,10 @@ describe("FeatureCanvasRenderer", () => { }); it("should render and apply transform, relativeCoords ON", async () => { - - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryLine", PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryLine", + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const fakeOffset = 10; const renderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer, Transform.createTranslation(Point3d.create(fakeOffset, fakeOffset))); @@ -293,5 +311,4 @@ describe("FeatureCanvasRenderer", () => { expect(lineToSpy.getCalls()[0].args[0]).to.equals(coords[0] + coords[2] + fakeOffset); expect(lineToSpy.getCalls()[0].args[1]).to.equals(coords[1] + coords[3] + fakeOffset); }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureResponse.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureResponse.test.ts index b6d38d5081e6..9dd003d7aa8b 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureResponse.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisFeatureResponse.test.ts @@ -12,7 +12,6 @@ import { esriPBuffer } from "../../ArcGisFeature/esriPBuffer.gen"; import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; describe("ArcGisFeatureResponse", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -20,26 +19,28 @@ describe("ArcGisFeatureResponse", () => { }); it("should return undefined if http error", async () => { - const response = new ArcGisFeatureResponse("PBF", Promise.resolve({status: 404} as Response)); + const response = new ArcGisFeatureResponse("PBF", Promise.resolve({ status: 404 } as Response)); const data = await response.getResponseData(); expect(data).to.be.undefined; }); it("should return undefined if invalid PBF data", async () => { - const response = new ArcGisFeatureResponse("PBF", Promise.resolve({ - status: 404, - arrayBuffer: async () => { - return Promise.resolve(undefined); - }, - } as unknown as Response)); + const response = new ArcGisFeatureResponse( + "PBF", + Promise.resolve({ + status: 404, + arrayBuffer: async () => { + return Promise.resolve(undefined); + }, + } as unknown as Response), + ); const data = await response.getResponseData(); expect(data).to.be.undefined; }); it("should create FeatureCollectionPBuffer from PBF data", async () => { - - const fakeResponse = { - headers: { "content-type" : "pbf"}, + const fakeResponse = { + headers: { "content-type": "pbf" }, arrayBuffer: async () => { const byteArray = Base64EncodedString.toUint8Array(PhillyLandmarksDataset.phillyTransportationGetFeatureInfoQueryEncodedPbf); return Promise.resolve(byteArray ? ByteStream.fromUint8Array(byteArray).arrayBuffer : undefined); @@ -54,11 +55,10 @@ describe("ArcGisFeatureResponse", () => { }); it("should report exceededTransferLimit from PBF object", async () => { - const collection = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillyExceededTransferLimitPbf); - const fakeResponse = { - headers: { "content-type" : "pbf"}, + const fakeResponse = { + headers: { "content-type": "pbf" }, arrayBuffer: async () => { const byteArray = collection.serialize(); return Promise.resolve(byteArray ? ByteStream.fromUint8Array(byteArray).arrayBuffer : undefined); @@ -73,37 +73,45 @@ describe("ArcGisFeatureResponse", () => { }); it("should return undefined if invalid JSON", async () => { - const response = new ArcGisFeatureResponse("JSON", Promise.resolve({ - status: 404, - json: async () => { - return undefined; - }, - } as unknown as Response)); + const response = new ArcGisFeatureResponse( + "JSON", + Promise.resolve({ + status: 404, + json: async () => { + return undefined; + }, + } as unknown as Response), + ); const data = await response.getResponseData(); expect(data).to.be.undefined; }); it("should return JSON data", async () => { - const response = new ArcGisFeatureResponse("JSON", Promise.resolve({ - status: 200, - json: async () => { - return {exceededTransferLimit: false}; - }, - } as unknown as Response)); + const response = new ArcGisFeatureResponse( + "JSON", + Promise.resolve({ + status: 200, + json: async () => { + return { exceededTransferLimit: false }; + }, + } as unknown as Response), + ); const data = await response.getResponseData(); expect(data?.data).not.to.be.undefined; expect(data?.exceedTransferLimit).to.be.false; }); it("should report exceededTransferLimit from JSON object", async () => { - const response = new ArcGisFeatureResponse("JSON", Promise.resolve({ - status: 200, - json: async () => { - return {exceededTransferLimit: true}; - }, - } as unknown as Response)); + const response = new ArcGisFeatureResponse( + "JSON", + Promise.resolve({ + status: 200, + json: async () => { + return { exceededTransferLimit: true }; + }, + } as unknown as Response), + ); const data = await response.getResponseData(); expect(data?.exceedTransferLimit).to.be.true; }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisJsonFeatureReader.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisJsonFeatureReader.test.ts index 2f9f688245b6..8918683e49c7 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisJsonFeatureReader.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisJsonFeatureReader.test.ts @@ -5,19 +5,19 @@ import { Logger } from "@itwin/core-bentley"; import { ImageMapLayerSettings } from "@itwin/core-common"; +import { MapLayerFeatureInfo } from "@itwin/core-frontend"; import { assert, expect } from "chai"; import * as sinon from "sinon"; import { ArcGisFeatureMapLayerFormat } from "../../ArcGisFeature/ArcGisFeatureFormat"; -import { ArcGisJsonFeatureReader } from "../../ArcGisFeature/ArcGisJsonFeatureReader"; import { ArcGisFeatureGeometryType } from "../../ArcGisFeature/ArcGisFeatureQuery"; -import { fakeContext } from "./Mocks"; -import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; +import { ArcGisJsonFeatureReader } from "../../ArcGisFeature/ArcGisJsonFeatureReader"; +import { ArcGisUniqueValueSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; +import { EsriSFS } from "../../ArcGisFeature/EsriSymbology"; import { FeatureCanvasRenderer } from "../../Feature/FeatureCanvasRenderer"; +import { fakeContext } from "./Mocks"; import { NeptuneCoastlineDataset } from "./NeptuneCoastlineDataset"; -import { EsriSFS } from "../../ArcGisFeature/EsriSymbology"; +import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; import { TestUtils } from "./TestUtils"; -import { ArcGisUniqueValueSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; -import { MapLayerFeatureInfo } from "@itwin/core-frontend"; const esriFeatureSampleSource = { name: "dummyFeatureLayer", url: "https://dummy.com", formatId: ArcGisFeatureMapLayerFormat.formatId }; @@ -33,7 +33,6 @@ const createFeatureJSON = () => { }; describe("ArcGisJsonFeatureReader", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -46,7 +45,10 @@ describe("ArcGisJsonFeatureReader", () => { // Since I want to use the same output reference for both formats, I force a max precision of 8. featureJson.floatPrecision = 8; const results: MapLayerFeatureInfo[] = []; - await featureJson.readFeatureInfo({ data: PhillyLandmarksDataset.phillyTransportationGetFeatureInfoQueryJson, exceedTransferLimit: false }, results); + await featureJson.readFeatureInfo( + { data: PhillyLandmarksDataset.phillyTransportationGetFeatureInfoQueryJson, exceedTransferLimit: false }, + results, + ); assert.deepEqual(results, PhillyLandmarksDataset.phillyTansportationGetFeatureInfoResultRef); }); @@ -67,7 +69,10 @@ describe("ArcGisJsonFeatureReader", () => { const data = PhillyLandmarksDataset.phillySimplePolyQueryJson; - const symbolRenderer = await TestUtils.createSymbologyRenderer(data.geometryType as ArcGisFeatureGeometryType, PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + data.geometryType as ArcGisFeatureGeometryType, + PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); @@ -76,9 +81,9 @@ describe("ArcGisJsonFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths - expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(true); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords + expect(firstCall.args[2]).to.eql(true); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender multiple ring polygon feature", async () => { @@ -86,7 +91,10 @@ describe("ArcGisJsonFeatureReader", () => { const data = PhillyLandmarksDataset.phillyDoubleRingPolyQueryJson; - const symbolRenderer = await TestUtils.createSymbologyRenderer(data.geometryType as ArcGisFeatureGeometryType, PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + data.geometryType as ArcGisFeatureGeometryType, + PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); @@ -95,34 +103,88 @@ describe("ArcGisJsonFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths - expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(true); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords + expect(firstCall.args[2]).to.eql(true); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender simple path", async () => { const featureJson = createFeatureJSON(); const data = PhillyLandmarksDataset.phillySimplePathQueryJson; - const symbolRenderer = await TestUtils.createSymbologyRenderer(data.geometryType as ArcGisFeatureGeometryType, - PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + data.geometryType as ArcGisFeatureGeometryType, + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); await featureJson.readAndRender({ data, exceedTransferLimit: false }, featureRenderer); expect(renderPathSpy.calledOnce); - const geometryCoords = [360, 491, -2, -1, -1, 0, -1, 0, -1, 0, -1, 1, -4, 1, -10, 2, -15, 3, -1, 0, -1, 0, -2, 0, -1, 0, -1, 0, -1, -1, -1, 0, -2, -1, 0, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0]; + const geometryCoords = [ + 360, + 491, + -2, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 1, + -4, + 1, + -10, + 2, + -15, + 3, + -1, + 0, + -1, + 0, + -2, + 0, + -1, + 0, + -1, + 0, + -1, + -1, + -1, + 0, + -2, + -1, + 0, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + ]; const firstCall = renderPathSpy.getCalls()[0]; - expect(firstCall.args[0]).to.eql([24]); // geometryLengths + expect(firstCall.args[0]).to.eql([24]); // geometryLengths expect(firstCall.args[1]).to.eql(geometryCoords); // geometryCoords - expect(firstCall.args[2]).to.eql(false); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(false); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender multi path", async () => { const featureJson = createFeatureJSON(); const data = PhillyLandmarksDataset.phillyMultiPathQueryJson; - const symbolRenderer = await TestUtils.createSymbologyRenderer(data.geometryType as ArcGisFeatureGeometryType, PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + data.geometryType as ArcGisFeatureGeometryType, + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); @@ -133,8 +195,8 @@ describe("ArcGisJsonFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.features[0].geometry.lengths); expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.features[0].geometry.coords); - expect(firstCall.args[2]).to.eql(false); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(false); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender simple point", async () => { @@ -142,7 +204,8 @@ describe("ArcGisJsonFeatureReader", () => { const data = PhillyLandmarksDataset.phillySimplePointQueryJson; const symbolRenderer = await TestUtils.createSymbologyRenderer( data.geometryType as ArcGisFeatureGeometryType, - PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const spy = sinon.spy(featureRenderer, "renderPoint"); @@ -152,14 +215,17 @@ describe("ArcGisJsonFeatureReader", () => { // Pbf contains already the right output format expect, lets rely on that. const geometryCoords = PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.coords; const firstCall = spy.getCalls()[0]; - expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths + expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths expect(firstCall.args[1]).to.eql(geometryCoords); // geometryCoords - expect(firstCall.args[2]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(2); // stride }); it("should log error when readAndRender / readFeatureInfo is called invalid response Data", async () => { const featureJson = createFeatureJSON(); - const symbolRenderer = await TestUtils.createSymbologyRenderer("esriGeometryPoint", PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + "esriGeometryPoint", + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const logErrorSpy = sandbox.spy(Logger, "logError"); @@ -169,13 +235,15 @@ describe("ArcGisJsonFeatureReader", () => { logErrorSpy.resetHistory(); await featureJson.readFeatureInfo({ data: { test: "test" }, exceedTransferLimit: false }, []); expect(logErrorSpy.calledOnce); - }); it("should call setActiveFeatureAttributes when attribute driven symbology", async () => { const featureJson = createFeatureJSON(); const data = NeptuneCoastlineDataset.singlePolyJson; - const symbolRenderer = await TestUtils.createSymbologyRenderer(data.geometryType as ArcGisFeatureGeometryType, NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + data.geometryType as ArcGisFeatureGeometryType, + NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const spy = sinon.spy(symbolRenderer as ArcGisUniqueValueSymbologyRenderer, "setActiveFeatureAttributes"); await featureJson.readAndRender({ data, exceedTransferLimit: false }, featureRenderer); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisPbfFeatureReader.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisPbfFeatureReader.test.ts index a184d1384cf1..b047cacaf412 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisPbfFeatureReader.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisPbfFeatureReader.test.ts @@ -8,14 +8,14 @@ import { MapLayerFeatureInfo } from "@itwin/core-frontend"; import { assert, expect } from "chai"; import * as sinon from "sinon"; import { ArcGisPbfFeatureReader } from "../../ArcGisFeature/ArcGisPbfFeatureReader"; -import { FeatureCanvasRenderer } from "../../Feature/FeatureCanvasRenderer"; +import { ArcGisUniqueValueSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; import { esriPBuffer } from "../../ArcGisFeature/esriPBuffer.gen"; +import { EsriSFS } from "../../ArcGisFeature/EsriSymbology"; +import { FeatureCanvasRenderer } from "../../Feature/FeatureCanvasRenderer"; import { esriFeatureSampleSource, fakeContext } from "./Mocks"; -import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; import { NeptuneCoastlineDataset } from "./NeptuneCoastlineDataset"; -import { EsriSFS } from "../../ArcGisFeature/EsriSymbology"; +import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; import { TestUtils } from "./TestUtils"; -import { ArcGisUniqueValueSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; const createFeaturePBF = () => { const settings = ImageMapLayerSettings.fromJSON(esriFeatureSampleSource); @@ -29,7 +29,6 @@ const createFeaturePBF = () => { }; describe("ArcGisPbfFeatureReader", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -37,31 +36,35 @@ describe("ArcGisPbfFeatureReader", () => { }); it("should convert pbf geometry type to Esri types", async () => { - expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypeMultipatch)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypeMultipatch), + ) .to.equals("esriGeometryMultiPatch"); expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypeMultipoint)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypeMultipoint), + ) .to.equals("esriGeometryMultipoint"); expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePoint), + ) .to.equals("esriGeometryPoint"); expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePolygon)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePolygon), + ) .to.equals("esriGeometryPolygon"); expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePolyline)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(esriPBuffer.FeatureCollectionPBuffer.GeometryType.esriGeometryTypePolyline), + ) .to.equals("esriGeometryPolyline"); expect( - ArcGisPbfFeatureReader.getArcGisFeatureGeometryType("" as unknown as esriPBuffer.FeatureCollectionPBuffer.GeometryType)) + ArcGisPbfFeatureReader.getArcGisFeatureGeometryType("" as unknown as esriPBuffer.FeatureCollectionPBuffer.GeometryType), + ) .to.equals("esriGeometryNull"); - }); it("should read FeatureInfo in PBF", async () => { @@ -77,11 +80,9 @@ describe("ArcGisPbfFeatureReader", () => { const results: MapLayerFeatureInfo[] = []; await featurePbf.readFeatureInfo({ data: featureCollection, exceedTransferLimit: false }, results); assert.deepEqual(results, PhillyLandmarksDataset.phillyAirportGetFeatureInfoResultRef); - }); it("should read FeatureInfo from PBF (philly transportation)", async () => { - const byteArray = Base64EncodedString.toUint8Array(PhillyLandmarksDataset.phillyTransportationGetFeatureInfoQueryEncodedPbf); const featureCollection = esriPBuffer.FeatureCollectionPBuffer.deserialize(byteArray); const featurePbf = createFeaturePBF(); @@ -92,11 +93,9 @@ describe("ArcGisPbfFeatureReader", () => { const results: MapLayerFeatureInfo[] = []; await featurePbf.readFeatureInfo({ data: featureCollection, exceedTransferLimit: false }, results); assert.deepEqual(results, PhillyLandmarksDataset.phillyTansportationGetFeatureInfoResultRef); - }); it("should read all data types from FeatureInfo ", async () => { - // In this test we use a synthetic PBuffer object to initialize a feature collection object. // The is to ensure we cover correctly all possible attribute value types. const featureCollection = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.fieldsCoveragePbufferCollection); @@ -113,7 +112,9 @@ describe("ArcGisPbfFeatureReader", () => { const featurePbf = createFeaturePBF(); const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillySimplePolyQueryPbf); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.geometryType); + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.geometryType, + ); const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); @@ -123,15 +124,17 @@ describe("ArcGisPbfFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths - expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(true); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillySimplePolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords + expect(firstCall.args[2]).to.eql(true); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender multiple ring polygon feature", async () => { const featurePbf = createFeaturePBF(); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.geometryType); + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.geometryType, + ); const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf); const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, PhillyLandmarksDataset.phillySimplePolyDrawingInfo.drawingInfo.renderer); @@ -143,9 +146,9 @@ describe("ArcGisPbfFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths - expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(true); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyDoubleRingPolyQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords + expect(firstCall.args[2]).to.eql(true); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender simple path", async () => { @@ -153,7 +156,8 @@ describe("ArcGisPbfFeatureReader", () => { const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillySimplePathQueryPbf); const symbolRenderer = await TestUtils.createSymbologyRenderer( ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(PhillyLandmarksDataset.phillySimplePathQueryPbf.queryResult.featureResult.geometryType), - PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); + PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); @@ -162,16 +166,18 @@ describe("ArcGisPbfFeatureReader", () => { const firstCall = renderPathSpy.getCalls()[0]; expect(firstCall).to.not.undefined; - expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePathQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths + expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePathQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillySimplePathQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(false); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(false); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender multi path", async () => { const featurePbf = createFeaturePBF(); const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillyMultiPathQueryPbf); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.geometryType); + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.geometryType, + ); const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, PhillyLandmarksDataset.phillySimpleLineDrawingInfo.drawingInfo.renderer); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const renderPathSpy = sinon.spy(featureRenderer, "renderPath"); @@ -179,17 +185,22 @@ describe("ArcGisPbfFeatureReader", () => { expect(renderPathSpy.calledOnce); const firstCall = renderPathSpy.getCalls()[0]; - expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths + expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths expect(firstCall.args[1]).to.eql(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.features[0].geometry.coords); // geometryCoords - expect(firstCall.args[2]).to.eql(false); // fill - expect(firstCall.args[3]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(false); // fill + expect(firstCall.args[3]).to.eql(2); // stride }); it("should readAndRender simple point", async () => { const featurePbf = createFeaturePBF(); const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(PhillyLandmarksDataset.phillySimplePointQueryPbf); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.geometryType); - const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + PhillyLandmarksDataset.phillyMultiPathQueryPbf.queryResult.featureResult.geometryType, + ); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + geomType, + PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer, + ); const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); const spy = sinon.spy(featureRenderer, "renderPoint"); @@ -199,26 +210,31 @@ describe("ArcGisPbfFeatureReader", () => { // Pbf contains already the right output format expect, lets rely on that. const geometryCoords = PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.coords; const firstCall = spy.getCalls()[0]; - expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths + expect(firstCall.args[0]).to.eql(PhillyLandmarksDataset.phillySimplePointQueryPbf.queryResult.featureResult.features[0].geometry.lengths); // geometryLengths expect(firstCall.args[1]).to.eql(geometryCoords); // geometryCoords - expect(firstCall.args[2]).to.eql(2); // stride + expect(firstCall.args[2]).to.eql(2); // stride }); it("should call setActiveFeatureAttributes when attribute driven symbology", async () => { const featurePbf = createFeaturePBF(); const dataset = NeptuneCoastlineDataset.singlePolyPbf; const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(dataset); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(NeptuneCoastlineDataset.singlePolyPbf.queryResult.featureResult.geometryType); - const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer) as ArcGisUniqueValueSymbologyRenderer; + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + NeptuneCoastlineDataset.singlePolyPbf.queryResult.featureResult.geometryType, + ); + const symbolRenderer = await TestUtils.createSymbologyRenderer( + geomType, + NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer, + ) as ArcGisUniqueValueSymbologyRenderer; const featureRenderer = new FeatureCanvasRenderer(fakeContext, symbolRenderer); - const spy = sinon.spy(symbolRenderer , "setActiveFeatureAttributes"); + const spy = sinon.spy(symbolRenderer, "setActiveFeatureAttributes"); await featurePbf.readAndRender({ data, exceedTransferLimit: false }, featureRenderer); // Make sure 'setActiveFeatureAttributes' was called with the proper argument expect(spy.calledOnce); const firstCall = spy.getCalls()[0]; - const featureAttr: {[key: string]: any} = {}; + const featureAttr: { [key: string]: any } = {}; featureAttr.LU_2014 = "Open Countryside"; expect(firstCall.args[0]).to.eql(featureAttr); }); @@ -228,7 +244,9 @@ describe("ArcGisPbfFeatureReader", () => { const dataset = NeptuneCoastlineDataset.singlePolyPbf; const rendererDef = NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer; const data = esriPBuffer.FeatureCollectionPBuffer.fromObject(dataset); - const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType(NeptuneCoastlineDataset.singlePolyPbf.queryResult.featureResult.geometryType); + const geomType = ArcGisPbfFeatureReader.getArcGisFeatureGeometryType( + NeptuneCoastlineDataset.singlePolyPbf.queryResult.featureResult.geometryType, + ); const symbolRenderer = await TestUtils.createSymbologyRenderer(geomType, rendererDef); const context = fakeContext; @@ -238,5 +256,4 @@ describe("ArcGisPbfFeatureReader", () => { const refSymbol = EsriSFS.fromJSON(rendererDef.uniqueValueInfos[8].symbol as any); expect(context.fillStyle).to.eql(refSymbol.color?.toRgbaString()); }); - }); diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisSymbologyRenderer.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisSymbologyRenderer.test.ts index 5a73b50a9619..5ee6ce6cc19b 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisSymbologyRenderer.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/ArcGisSymbologyRenderer.test.ts @@ -5,20 +5,25 @@ /* eslint-disable @typescript-eslint/naming-convention */ import * as sinon from "sinon"; -import { NewYorkDataset } from "./NewYorkDataset"; -import { ArcGisClassBreaksSymbologyRenderer, ArcGisDashLineStyle, ArcGisSymbologyCanvasRenderer, ArcGisUniqueValueSymbologyRenderer } from "../../ArcGisFeature/ArcGisSymbologyRenderer"; -import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; +import { + ArcGisClassBreaksSymbologyRenderer, + ArcGisDashLineStyle, + ArcGisSymbologyCanvasRenderer, + ArcGisUniqueValueSymbologyRenderer, +} from "../../ArcGisFeature/ArcGisSymbologyRenderer"; +import { EsriPMS, EsriRenderer, EsriSFS, EsriSLS, EsriSMS, EsriUniqueValueRenderer } from "../../ArcGisFeature/EsriSymbology"; import { EarthquakeSince1970Dataset } from "./EarthquakeSince1970Dataset"; -import { EsriPMS, EsriRenderer, EsriSFS, EsriSLS , EsriSMS, EsriUniqueValueRenderer } from "../../ArcGisFeature/EsriSymbology"; import { NeptuneCoastlineDataset } from "./NeptuneCoastlineDataset"; +import { NewYorkDataset } from "./NewYorkDataset"; +import { PhillyLandmarksDataset } from "./PhillyLandmarksDataset"; +import { ColorDef } from "@itwin/core-common"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; -import { TestUtils } from "./TestUtils"; import * as moq from "typemoq"; -import { ArcGisFeatureGeometryType } from "../../ArcGisFeature/ArcGisFeatureQuery"; -import { ColorDef } from "@itwin/core-common"; import { DefaultArcGiSymbology } from "../../ArcGisFeature/ArcGisFeatureProvider"; +import { ArcGisFeatureGeometryType } from "../../ArcGisFeature/ArcGisFeatureQuery"; +import { TestUtils } from "./TestUtils"; const expect = chai.expect; chai.use(chaiAsPromised); @@ -26,7 +31,6 @@ chai.use(chaiAsPromised); const getRefImageSrc = (markerSymbol: any) => `data:${markerSymbol.contentType};base64,${markerSymbol.imageData}`; describe("ArcGisSymbologyRenderer", () => { - const sandbox = sinon.createSandbox(); const contextMock = moq.Mock.ofType(); @@ -47,10 +51,12 @@ describe("ArcGisSymbologyRenderer", () => { }; beforeEach(async () => { - sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake(function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { - // Simple call the listener in order to resolved the wrapping promise (i.e. EsriRenderer.initialize() is non-blocking ) - (listener as any)(); - }); + sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake( + function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { + // Simple call the listener in order to resolved the wrapping promise (i.e. EsriRenderer.initialize() is non-blocking ) + (listener as any)(); + }, + ); }); afterEach(async () => { @@ -68,56 +74,53 @@ describe("ArcGisSymbologyRenderer", () => { }); it("should construct unique value renderer without metadata default symbol (", async () => { - const dataset = NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo; - const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); + const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); const defaultSymb = new DefaultArcGiSymbology(); const symbRender = ArcGisSymbologyCanvasRenderer.create(renderer, defaultSymb); symbRender.activeGeometryType = "esriGeometryPolygon"; - expect (symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultSFS); + expect(symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultSFS); }); it("should construct unique value renderer with default symbol", async () => { const dataset = NewYorkDataset.uniqueValueDrawingInfo; - const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); + const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); const symbRender = ArcGisSymbologyCanvasRenderer.create(renderer, new DefaultArcGiSymbology(), "esriGeometryPoint"); const activeSymbol = symbRender.symbol as EsriPMS; const refSym = EsriPMS.fromJSON(dataset.drawingInfo.renderer.defaultSymbol as any); - expect (activeSymbol.imageUrl).to.deep.equals(refSym.imageUrl); + expect(activeSymbol.imageUrl).to.deep.equals(refSym.imageUrl); }); it("should construct with default symbol if invalid renderer type", async () => { const dataset = structuredClone(NewYorkDataset.uniqueValueDrawingInfo); - const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); + const renderer = EsriUniqueValueRenderer.fromJSON(dataset.drawingInfo.renderer as any); (renderer as any).type = "someBadType"; const symbRender = ArcGisSymbologyCanvasRenderer.create(renderer, new DefaultArcGiSymbology(), "esriGeometryPoint"); - expect (symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); - + expect(symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); }); it("should construct with default symbol if no renderer object", async () => { const symbRender = ArcGisSymbologyCanvasRenderer.create(undefined, new DefaultArcGiSymbology(), "esriGeometryPoint"); - expect (symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); - + expect(symbRender.defaultSymbol).to.deep.equals(DefaultArcGiSymbology.defaultPMS); }); it("should provide fill color using simple renderer definition", async () => { - - const provider = await TestUtils.createSymbologyRenderer("esriGeometryPolygon", PhillyLandmarksDataset.polygonDrawingInfo.drawingInfo.renderer) as ArcGisUniqueValueSymbologyRenderer; + const provider = await TestUtils.createSymbologyRenderer( + "esriGeometryPolygon", + PhillyLandmarksDataset.polygonDrawingInfo.drawingInfo.renderer, + ) as ArcGisUniqueValueSymbologyRenderer; contextMock.setup((x) => x.fillStyle); provider.applyFillStyle(contextMock.object); const refSymbol = EsriSFS.fromJSON(PhillyLandmarksDataset.polygonDrawingInfo.drawingInfo.renderer.symbol as any); contextMock.verify((x) => x.fillStyle = moq.It.isValue(refSymbol.color!.toRgbaString()), moq.Times.once()); - }); it("should apply line dash on poly outline using simple renderer definition", async () => { - - const refRenderer = PhillyLandmarksDataset.polygonDrawingInfo.drawingInfo.renderer; + const refRenderer = PhillyLandmarksDataset.polygonDrawingInfo.drawingInfo.renderer; refRenderer.symbol.outline.style; const provider = await TestUtils.createSymbologyRenderer("esriGeometryPolygon", refRenderer) as ArcGisUniqueValueSymbologyRenderer; @@ -131,7 +134,6 @@ describe("ArcGisSymbologyRenderer", () => { }); it("should provide stroke style using simple renderer definition", async () => { - const refRenderer = PhillyLandmarksDataset.lineDrawingInfo.drawingInfo.renderer; const provider = await TestUtils.createSymbologyRenderer("esriGeometryLine", refRenderer) as ArcGisUniqueValueSymbologyRenderer; @@ -146,19 +148,17 @@ describe("ArcGisSymbologyRenderer", () => { }); it("should provide stroke style using simple renderer definition", async () => { - const refRenderer = PhillyLandmarksDataset.lineDrawingInfo.drawingInfo.renderer; const refColor = EsriSLS.fromJSON(refRenderer.symbol as any); await verifyLineDashes(refRenderer, refRenderer.symbol, refColor.color!, "esriGeometryLine"); - }); it("should apply proper fill color using unique value SFS renderer definition", async () => { const rendererDef = NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer; const provider = await TestUtils.createSymbologyRenderer("esriGeometryPolygon", rendererDef) as ArcGisUniqueValueSymbologyRenderer; - const fakeContext = {fillStyle: ""}; + const fakeContext = { fillStyle: "" }; // Make sure default symbology is applied if 'setActiveFeatureAttributes' has never been called provider.applyFillStyle(fakeContext as CanvasRenderingContext2D); let refSymbol = provider.defaultSymbol as EsriSFS; @@ -166,7 +166,7 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"LU_2014": "Urban/Built-up"}); + provider.setActiveFeatureAttributes({ "LU_2014": "Urban/Built-up" }); provider.applyFillStyle(fakeContext as CanvasRenderingContext2D); refSymbol = EsriSFS.fromJSON(rendererDef.uniqueValueInfos[1].symbol as any); expect(fakeContext.fillStyle).to.eq(refSymbol.color!.toRgbaString()); @@ -183,7 +183,7 @@ describe("ArcGisSymbologyRenderer", () => { const rendererDef = NeptuneCoastlineDataset.uniqueValueSFSDrawingInfo.drawingInfo.renderer; const provider = await TestUtils.createSymbologyRenderer("esriGeometryPolygon", rendererDef) as ArcGisUniqueValueSymbologyRenderer; - const fakeContext = {strokeStyle: ""}; + const fakeContext = { strokeStyle: "" }; // Make sure default symbology is applied if 'setActiveFeatureAttributes' has never been called provider.applyStrokeStyle(fakeContext as CanvasRenderingContext2D); let refSymbol = provider.defaultSymbol as EsriSFS; @@ -191,7 +191,7 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"LU_2014": "Urban/Built-up"}); + provider.setActiveFeatureAttributes({ "LU_2014": "Urban/Built-up" }); provider.applyStrokeStyle(fakeContext as CanvasRenderingContext2D); refSymbol = EsriSFS.fromJSON(rendererDef.uniqueValueInfos[1].symbol as any); expect(fakeContext.strokeStyle).to.eq(refSymbol.outline!.color!.toRgbaString()); @@ -208,7 +208,7 @@ describe("ArcGisSymbologyRenderer", () => { const rendererDef = NeptuneCoastlineDataset.uniqueValueSLSDrawingInfo.drawingInfo.renderer; const provider = await TestUtils.createSymbologyRenderer("esriGeometryLine", rendererDef) as ArcGisUniqueValueSymbologyRenderer; - const fakeContext = {strokeStyle: ""}; + const fakeContext = { strokeStyle: "" }; // Make sure default symbology is applied if 'setActiveFeatureAttributes' has never been called provider.applyStrokeStyle(fakeContext as CanvasRenderingContext2D); let refSymbol = provider.defaultSymbol as any; @@ -216,7 +216,7 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"LU_2014": "Urban/Built-up"}); + provider.setActiveFeatureAttributes({ "LU_2014": "Urban/Built-up" }); provider.applyStrokeStyle(fakeContext as CanvasRenderingContext2D); refSymbol = EsriSFS.fromJSON(rendererDef.uniqueValueInfos[1].symbol as any); expect(fakeContext.strokeStyle).to.eq(refSymbol.color!.toRgbaString()); @@ -244,26 +244,26 @@ describe("ArcGisSymbologyRenderer", () => { const fakeContext = new FakeContext(); // Make sure default symbology is applied if 'setActiveFeatureAttributes' has never been called - provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0 ,0); + provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0, 0); let refSymbol = provider.defaultSymbol; expect(fakeContext.image.src).to.eq(getRefImageSrc(refSymbol)); // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"WEAPON": "gun"}); - provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0 ,0); + provider.setActiveFeatureAttributes({ "WEAPON": "gun" }); + provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0, 0); refSymbol = EsriPMS.fromJSON(rendererDef.uniqueValueInfos[2].symbol as any); expect(fakeContext.image.src).to.eq(getRefImageSrc(refSymbol)); // check that we fallback to default symbology if empty attributes are now set provider.setActiveFeatureAttributes({}); fakeContext.image = undefined; - provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0 ,0); + provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0, 0); refSymbol = provider.defaultSymbol; expect(fakeContext.image.src).to.eq(getRefImageSrc(refSymbol)); }); - it ("should draw rotated marker using simple PMS renderer definition", async () => { + it("should draw rotated marker using simple PMS renderer definition", async () => { // Clone renderer definition and make adjustments for the test purposes. const rendererDef = structuredClone(PhillyLandmarksDataset.phillySimplePointDrawingInfo.drawingInfo.renderer); const angle = 90; @@ -277,17 +277,26 @@ describe("ArcGisSymbologyRenderer", () => { contextMock.setup((x) => x.translate(moq.It.isAnyNumber(), moq.It.isAnyNumber())); // Make sure appropriate context methods are called. - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); const refSymbol = provider.symbol; const pms = refSymbol as EsriPMS; await pms.loadImage(); - contextMock.verify((x) => x.rotate(moq.It.isValue(angle*Math.PI/180)), moq.Times.once()); + contextMock.verify((x) => x.rotate(moq.It.isValue(angle * Math.PI / 180)), moq.Times.once()); contextMock.verify((x) => x.translate(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); - contextMock.verify((x) => x.drawImage(moq.It.is((value: HTMLImageElement) => value.src === pms.image.src), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); - + contextMock.verify( + (x) => + x.drawImage( + moq.It.is((value: HTMLImageElement) => value.src === pms.image.src), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + ), + moq.Times.once(), + ); }); - it ("should draw rotated marker using unique value PMS renderer definition", async () => { + it("should draw rotated marker using unique value PMS renderer definition", async () => { // Clone renderer definition and make adjustments for the test purposes. const rendererDef = structuredClone(NewYorkDataset.uniqueValueDrawingInfo.drawingInfo.renderer); const angle = 90; @@ -303,17 +312,26 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"WEAPON": "gun"}); + provider.setActiveFeatureAttributes({ "WEAPON": "gun" }); // Make sure appropriate context methods are called. - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); const refSymbol = provider.symbol; const pms = refSymbol as EsriPMS; await pms.loadImage(); - contextMock.verify((x) => x.rotate(moq.It.isValue(angle*Math.PI/180)), moq.Times.once()); + contextMock.verify((x) => x.rotate(moq.It.isValue(angle * Math.PI / 180)), moq.Times.once()); contextMock.verify((x) => x.translate(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); - contextMock.verify((x) => x.drawImage(moq.It.is((value: HTMLImageElement) => value.src === pms.image.src), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); - + contextMock.verify( + (x) => + x.drawImage( + moq.It.is((value: HTMLImageElement) => value.src === pms.image.src), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + ), + moq.Times.once(), + ); }); it("should draw rotated marker using simple SMS renderer definition", async () => { @@ -333,11 +351,13 @@ describe("ArcGisSymbologyRenderer", () => { const refSms = refSymbol as EsriSMS; // Make sure appropriate context methods are called. - provider.drawPoint(contextMock.object, 0 ,0); - contextMock.verify((x) => x.rotate(moq.It.isValue(angle*Math.PI/180)), moq.Times.once()); + provider.drawPoint(contextMock.object, 0, 0); + contextMock.verify((x) => x.rotate(moq.It.isValue(angle * Math.PI / 180)), moq.Times.once()); contextMock.verify((x) => x.translate(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); - contextMock.verify((x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isValue(refSms.size*0.5), moq.It.isValue(0), moq.It.isValue(2*Math.PI)), moq.Times.once()); - + contextMock.verify( + (x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isValue(refSms.size * 0.5), moq.It.isValue(0), moq.It.isValue(2 * Math.PI)), + moq.Times.once(), + ); }); it("should draw different markers using unique value SMS renderer definition", async () => { @@ -352,17 +372,27 @@ describe("ArcGisSymbologyRenderer", () => { // Make sure appropriate context methods are called. // Should take default symbology - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); const refDefaultSymbol = rendererDef.defaultSymbol; - contextMock.verify((x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isValue(refDefaultSymbol.size*0.5), moq.It.isValue(0), moq.It.isValue(2*Math.PI)), moq.Times.once()); + contextMock.verify( + (x) => + x.arc( + moq.It.isAnyNumber(), + moq.It.isAnyNumber(), + moq.It.isValue(refDefaultSymbol.size * 0.5), + moq.It.isValue(0), + moq.It.isValue(2 * Math.PI), + ), + moq.Times.once(), + ); // check esriSMSCross contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: " "}); + provider.setActiveFeatureAttributes({ WEAPON: " " }); contextMock.setup((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.beginPath()); - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); contextMock.verify((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); contextMock.verify((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); contextMock.verify((x) => x.beginPath(), moq.Times.once()); @@ -370,12 +400,12 @@ describe("ArcGisSymbologyRenderer", () => { // check esriSMSDiamond contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: "blunt_instrument"}); + provider.setActiveFeatureAttributes({ WEAPON: "blunt_instrument" }); contextMock.setup((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.beginPath()); contextMock.setup((x) => x.closePath()); - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); contextMock.verify((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); contextMock.verify((x) => x.beginPath(), moq.Times.once()); contextMock.verify((x) => x.closePath(), moq.Times.once()); @@ -383,19 +413,19 @@ describe("ArcGisSymbologyRenderer", () => { // check esriSMSSquare contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: "gun"}); + provider.setActiveFeatureAttributes({ WEAPON: "gun" }); contextMock.setup((x) => x.fillRect(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber())); - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); contextMock.verify((x) => x.fillRect(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); // check esriSMSTriangle contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: "knife"}); + provider.setActiveFeatureAttributes({ WEAPON: "knife" }); contextMock.setup((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.beginPath()); contextMock.setup((x) => x.closePath()); - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); contextMock.verify((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); contextMock.verify((x) => x.beginPath(), moq.Times.once()); contextMock.verify((x) => x.closePath(), moq.Times.once()); @@ -403,32 +433,35 @@ describe("ArcGisSymbologyRenderer", () => { // check esriSMSX contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: "other"}); + provider.setActiveFeatureAttributes({ WEAPON: "other" }); contextMock.setup((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber())); contextMock.setup((x) => x.beginPath()); - provider.drawPoint(contextMock.object, 0 ,0); + provider.drawPoint(contextMock.object, 0, 0); contextMock.verify((x) => x.moveTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); contextMock.verify((x) => x.lineTo(moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.exactly(2)); contextMock.verify((x) => x.beginPath(), moq.Times.once()); // check esriSMSCircle contextMock.reset(); - provider.setActiveFeatureAttributes({WEAPON: "dummy"}); + provider.setActiveFeatureAttributes({ WEAPON: "dummy" }); contextMock.setup((x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber())); - provider.drawPoint(contextMock.object, 0 ,0); - contextMock.verify((x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(),moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber()), moq.Times.once()); + provider.drawPoint(contextMock.object, 0, 0); + contextMock.verify( + (x) => x.arc(moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber(), moq.It.isAnyNumber()), + moq.Times.once(), + ); }); it("should apply proper marker using unique value PMS renderer definition", async () => { - const rendererDef = {...NewYorkDataset.uniqueValueDrawingInfo.drawingInfo.renderer, defaultSymbol: null}; + const rendererDef = { ...NewYorkDataset.uniqueValueDrawingInfo.drawingInfo.renderer, defaultSymbol: null }; const provider = await TestUtils.createSymbologyRenderer("esriGeometryPoint", rendererDef); await provider.renderer!.initialize(); // When the renderer definition doesn't include its own default symbol we need to loadimage of the default symbol manually if (!rendererDef.defaultSymbol) - await (provider.defaultSymbol as EsriPMS).loadImage(); // since default symbology is provided by + await (provider.defaultSymbol as EsriPMS).loadImage(); // since default symbology is provided by class FakeContext { public image: any; @@ -439,10 +472,9 @@ describe("ArcGisSymbologyRenderer", () => { const fakeContext = new FakeContext(); // Make sure default symbology is applied if 'setActiveFeatureAttributes' has never been called - provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0 ,0); + provider.drawPoint((fakeContext as unknown) as CanvasRenderingContext2D, 0, 0); const refSymbol = provider.defaultSymbol; expect(fakeContext.image.src).to.eq(getRefImageSrc(refSymbol)); - }); it("should pick the right class based of class breaks", async () => { @@ -452,25 +484,28 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"magnitude": 5.1}); + provider.setActiveFeatureAttributes({ "magnitude": 5.1 }); let pms = provider.symbol as EsriPMS; // Make sure the right image was picked after setting the active feature attributes - expect(pms.props.imageData).to.equals(EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[1].symbol.imageData); + expect(pms.props.imageData).to.equals( + EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[1].symbol.imageData, + ); - provider.setActiveFeatureAttributes({magnitude: 1.7}); + provider.setActiveFeatureAttributes({ magnitude: 1.7 }); pms = provider.symbol as EsriPMS; - expect(pms.props.imageData).to.equals(EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[0].symbol.imageData); + expect(pms.props.imageData).to.equals( + EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[0].symbol.imageData, + ); - provider.setActiveFeatureAttributes({magnitude: 0.5}); + provider.setActiveFeatureAttributes({ magnitude: 0.5 }); pms = provider.symbol as EsriPMS; expect(pms.props.imageData).to.equals((provider.defaultSymbol as EsriPMS).imageData); - provider.setActiveFeatureAttributes({magnitude: 10}); + provider.setActiveFeatureAttributes({ magnitude: 10 }); pms = provider.symbol as EsriPMS; expect(pms.props.imageData).to.equals((provider.defaultSymbol as EsriPMS).imageData); - }); it("should pick the right class based of class breaks (classMinValue defined)", async () => { @@ -481,20 +516,23 @@ describe("ArcGisSymbologyRenderer", () => { // Now set proper attribute // eslint-disable-next-line quote-props, @typescript-eslint/naming-convention - provider.setActiveFeatureAttributes({"magnitude": 5.1}); + provider.setActiveFeatureAttributes({ "magnitude": 5.1 }); let pms = provider.symbol as EsriPMS; // Make sure the right image was picked after setting the active feature attributes - expect(pms.props.imageData).to.equals(EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[1].symbol.imageData); + expect(pms.props.imageData).to.equals( + EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[1].symbol.imageData, + ); - provider.setActiveFeatureAttributes({magnitude: 3.1}); + provider.setActiveFeatureAttributes({ magnitude: 3.1 }); pms = provider.symbol as EsriPMS; - expect(pms.props.imageData).to.equals(EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[0].symbol.imageData); + expect(pms.props.imageData).to.equals( + EarthquakeSince1970Dataset.Earthquakes1970LayerCapabilities.drawingInfo.renderer.classBreakInfos[0].symbol.imageData, + ); - provider.setActiveFeatureAttributes({magnitude: 2}); + provider.setActiveFeatureAttributes({ magnitude: 2 }); pms = provider.symbol as EsriPMS; expect(pms.props.imageData).to.equals((provider.defaultSymbol as EsriPMS).imageData); }); - }); // end test suite diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/EarthquakeSince1970Dataset.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/EarthquakeSince1970Dataset.ts index 9b570cc6c213..ad05bce52729 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/EarthquakeSince1970Dataset.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/EarthquakeSince1970Dataset.ts @@ -6,7 +6,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class EarthquakeSince1970Dataset { - public static Earthquakes1970LayerCapabilities: any = { currentVersion: 10.91, id: 0, @@ -18,7 +17,8 @@ export class EarthquakeSince1970Dataset { maxScale: 0, canScaleSymbols: false, geometryType: "esriGeometryPoint", - description: "Data represented by this map is not updated on a regular basis. This is a sample service hosted by ESRI, powered by ArcGIS Server. ESRI reserves the right to change or remove this service at any time and without notice.\n", + description: + "Data represented by this map is not updated on a regular basis. This is a sample service hosted by ESRI, powered by ArcGIS Server. ESRI reserves the right to change or remove this service at any time and without notice.\n", copyrightText: "", editFieldsInfo: null, ownershipBasedAccessControlForFeatures: null, @@ -78,7 +78,8 @@ export class EarthquakeSince1970Dataset { symbol: { type: "esriPMS", url: "1a5ce93c9ddd121f21789ff08f50b383", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAQ1JREFUOI2d071KA1EQhuF3QzBkJ4XESmwtUouFhaIXIAhqayUEQawkVoLBwh8UsRR7L0Cwt/UevAMJ22RnYAsZC5eFRLM5m6+bYc4z05w6ATGjFcekZTP1aUiaErvzrsqWCDozFEWNM8hWgVPgcibIjCX3rJeXPVWeRPiqDLlzBcR52QIugONKkFl7xT05GGt3zXiMYz6DIffkAYjG5925BvaDIFV2gc0JO/ZU22siyUcpNBgwB9xOuvQ3yR2wUQo1m5wAy+UQ66rsiPD6LzQcsgCcT0HyNG7cs7co4vsPVKvRB+bDoKxjxiHwPAKZ0XHnKAwp0lflRQQtIHfuxy8MyCL51ykeirBdERnJD80TUfp6vTFHAAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAQ1JREFUOI2d071KA1EQhuF3QzBkJ4XESmwtUouFhaIXIAhqayUEQawkVoLBwh8UsRR7L0Cwt/UevAMJ22RnYAsZC5eFRLM5m6+bYc4z05w6ATGjFcekZTP1aUiaErvzrsqWCDozFEWNM8hWgVPgcibIjCX3rJeXPVWeRPiqDLlzBcR52QIugONKkFl7xT05GGt3zXiMYz6DIffkAYjG5925BvaDIFV2gc0JO/ZU22siyUcpNBgwB9xOuvQ3yR2wUQo1m5wAy+UQ66rsiPD6LzQcsgCcT0HyNG7cs7co4vsPVKvRB+bDoKxjxiHwPAKZ0XHnKAwp0lflRQQtIHfuxy8MyCL51ykeirBdERnJD80TUfp6vTFHAAAAAElFTkSuQmCC", contentType: "image/png", width: 13, height: 11, @@ -94,7 +95,8 @@ export class EarthquakeSince1970Dataset { symbol: { type: "esriPMS", url: "065667453660362eb9259f9b624cb128", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAARxJREFUOI2d0z1Lw1AUxvF/QrE06SB1EleHzuLgoOgHEARfNkMGoQjiJHUSLA6+oIijZEtTQXAS3F39Dn4DkSz2Xgwix6E10GjTmz7bOZz7O2e5JQyiH6g6W3TzZkqjkO49jnzyrEJWXB81NmR9lQ8hmcfmADgZC9JtZoSk2S+bKuTW9XkrDInNKYLTL6vYHAN7hSDdqc2JxF6m3dARN47HqzEkEl8DVnZe4AzYNIJUxDqwPGTHhopqC64Xv+RC7wETwMWwS3uJL4GlXKhSYR+YzYdYVB3W3G0e/4U+2kwBRyOQXqR8LkHyZDX4/gPZFi1g0ggiqesKO0AwAOmIusCuGZKmpULuXB+VQgJX2QsNMv37ddKHrsdqQWQgP4w0TSILuEHdAAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAARxJREFUOI2d0z1Lw1AUxvF/QrE06SB1EleHzuLgoOgHEARfNkMGoQjiJHUSLA6+oIijZEtTQXAS3F39Dn4DkSz2Xgwix6E10GjTmz7bOZz7O2e5JQyiH6g6W3TzZkqjkO49jnzyrEJWXB81NmR9lQ8hmcfmADgZC9JtZoSk2S+bKuTW9XkrDInNKYLTL6vYHAN7hSDdqc2JxF6m3dARN47HqzEkEl8DVnZe4AzYNIJUxDqwPGTHhopqC64Xv+RC7wETwMWwS3uJL4GlXKhSYR+YzYdYVB3W3G0e/4U+2kwBRyOQXqR8LkHyZDX4/gPZFi1g0ggiqesKO0AwAOmIusCuGZKmpULuXB+VQgJX2QsNMv37ddKHrsdqQWQgP4w0TSILuEHdAAAAAElFTkSuQmCC", contentType: "image/png", width: 13, height: 11, @@ -110,7 +112,8 @@ export class EarthquakeSince1970Dataset { symbol: { type: "esriPMS", url: "68fc02d60d18137f1c9a2bf2e58fdffb", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAASJJREFUOI2d079Lw0AYxvFvjtJi0kHqJK4OncXBQdG9QsAYcXESRBBdpE6CxcEfKOIo7o4iB3Z29X9w7CaSxd7BYey5xEKjTZM+2/vy3ud9lyuRI7pB1W3TzZopjUK6Ia6NeVE+K55EjQ05ceUIzDyCQ+B0LEhvMmONaSZlU/nceZL3wpA1nAFuUlYRnAB7hSAd1uZsHG2l2ju6wa3b5i03ZOPoBnDS87bMObCeC1IBa/RYHrIjUH5twZPRayb0cUCZDpfDLgVARFfAUiY00WEfmM2EYFH5+J5E/gt9bjCF4RgxggEQlQuLeXbg+w8kvmghmMzBAKauA7Z55H4A0iF1G7ObD0nSo6V8HjyJ6kM25jp9YY5M/36d/kPvidWCyEB+ACGWUwzkvHSJAAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAASJJREFUOI2d079Lw0AYxvFvjtJi0kHqJK4OncXBQdG9QsAYcXESRBBdpE6CxcEfKOIo7o4iB3Z29X9w7CaSxd7BYey5xEKjTZM+2/vy3ud9lyuRI7pB1W3TzZopjUK6Ia6NeVE+K55EjQ05ceUIzDyCQ+B0LEhvMmONaSZlU/nceZL3wpA1nAFuUlYRnAB7hSAd1uZsHG2l2ju6wa3b5i03ZOPoBnDS87bMObCeC1IBa/RYHrIjUH5twZPRayb0cUCZDpfDLgVARFfAUiY00WEfmM2EYFH5+J5E/gt9bjCF4RgxggEQlQuLeXbg+w8kvmghmMzBAKauA7Z55H4A0iF1G7ObD0nSo6V8HjyJ6kM25jp9YY5M/36d/kPvidWCyEB+ACGWUwzkvHSJAAAAAElFTkSuQmCC", contentType: "image/png", width: 13, height: 11, @@ -126,7 +129,8 @@ export class EarthquakeSince1970Dataset { symbol: { type: "esriPMS", url: "21b2e5d7cac48771fdbbbd9f804f664f", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAQRJREFUOI2d071KA1EQBtATCQazKWStxNYitVhYKPoAgqC2VoIIYiWxEgwW/qCIpdj7AIK9re/gG4hsY3ZhC7kWhkiiSTb5uhnmnpnmlhVIRq1Ka9BMeRjSohp4SVmLSMeGSpXKsTxfxBHOxoIy5kKeN9plI+U+4n1kKHCOarus4RQHI0FZHC+EJNnpae9l3FV5KwyFJLlFqXc+cIHtQlDKJlb77NhK43gpSpLXgdAHk7jqdylIkmusDISmOMT8QIjllI2Ip3+hT2ZwMgT5SaVyGfL8ucTXH2iCJqYLQXlez9jFQxeUUQ/sF0J+00x5jEg7UOCm98ICmdX+Op2HEesjIl35BslJQhl9PQgOAAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABIAAAAPCAYAAADphp8SAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAQRJREFUOI2d071KA1EQBtATCQazKWStxNYitVhYKPoAgqC2VoIIYiWxEgwW/qCIpdj7AIK9re/gG4hsY3ZhC7kWhkiiSTb5uhnmnpnmlhVIRq1Ka9BMeRjSohp4SVmLSMeGSpXKsTxfxBHOxoIy5kKeN9plI+U+4n1kKHCOarus4RQHI0FZHC+EJNnpae9l3FV5KwyFJLlFqXc+cIHtQlDKJlb77NhK43gpSpLXgdAHk7jqdylIkmusDISmOMT8QIjllI2Ip3+hT2ZwMgT5SaVyGfL8ucTXH2iCJqYLQXlez9jFQxeUUQ/sF0J+00x5jEg7UOCm98ICmdX+Op2HEesjIl35BslJQhl9PQgOAAAAAElFTkSuQmCC", contentType: "image/png", width: 13, height: 11, @@ -540,6 +544,5 @@ export class EarthquakeSince1970Dataset { tileMaxRecordCount: 8000, standardMaxRecordCountNoGeometry: 32000, maxRecordCountFactor: 1, - }; } diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/EsriSymbology.test.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/EsriSymbology.test.ts index 58bd33d3d22b..1a0d13cd2707 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/EsriSymbology.test.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/EsriSymbology.test.ts @@ -3,14 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import { NeptuneCoastlineDataset } from "./NeptuneCoastlineDataset"; import * as chai from "chai"; +import * as sinon from "sinon"; import { EsriUniqueValueRenderer } from "../../ArcGisFeature/EsriSymbology"; +import { NeptuneCoastlineDataset } from "./NeptuneCoastlineDataset"; const expect = chai.expect; describe("EsriSymbology", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -25,7 +24,7 @@ describe("EsriSymbology", () => { expect(renderer.field3).to.be.undefined; expect(renderer.type).equals(dataset.drawingInfo.renderer.type); expect(renderer.uniqueValueInfos.length).equals(dataset.drawingInfo.renderer.uniqueValueInfos.length); - for (let i = 0 ; i < renderer.uniqueValueInfos.length; i++) { + for (let i = 0; i < renderer.uniqueValueInfos.length; i++) { const lhs = renderer.uniqueValueInfos[i]; const rhs = dataset.drawingInfo.renderer.uniqueValueInfos[i]; expect(lhs.value).equals(rhs.value); @@ -34,5 +33,4 @@ describe("EsriSymbology", () => { expect(lhs.symbol.type).equals(rhs.symbol.type); } }); - }); // end test suite diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/Mocks.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/Mocks.ts index b9bc72323e49..28d939e18893 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/Mocks.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/Mocks.ts @@ -5,15 +5,18 @@ import { ArcGisFeatureMapLayerFormat } from "../../ArcGisFeature/ArcGisFeatureFormat"; -export const fakeContext = ({ +export const fakeContext = { beginPath: () => {}, closePath: () => {}, moveTo: (_x: number, _y: number) => {}, lineTo: (_x: number, _y: number) => {}, - fill: (_fillRule?: CanvasFillRule)=> {}, - stroke: ()=> {}, + fill: (_fillRule?: CanvasFillRule) => {}, + stroke: () => {}, drawImage: (_image: CanvasImageSource, _dx: number, _dy: number) => {}, +} as CanvasRenderingContext2D; -} as CanvasRenderingContext2D); - -export const esriFeatureSampleSource = {name: "dummyFeatureLayer", url: "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/FeatureServer", formatId: ArcGisFeatureMapLayerFormat.formatId}; +export const esriFeatureSampleSource = { + name: "dummyFeatureLayer", + url: "https://services7.arcgis.com/nZ2Vb4CUwdo9AIiQ/ArcGIS/rest/services/PhillyRailLines/FeatureServer", + formatId: ArcGisFeatureMapLayerFormat.formatId, +}; diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/NeptuneCoastlineDataset.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/NeptuneCoastlineDataset.ts index 3acad220cbbd..ecf8e1e29824 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/NeptuneCoastlineDataset.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/NeptuneCoastlineDataset.ts @@ -5,7 +5,6 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class NeptuneCoastlineDataset { - public static singlePolyJson = { objectIdFieldName: "OBJECTID", uniqueIdField: { @@ -134,7 +133,7 @@ export class NeptuneCoastlineDataset { // Note: I updated manually the attributes, to all 'values' to undefined (except for string_value), // otherwise the PBF reader would be confused. I assume this a bug when the response get serialized as JSON. - public static singlePolyPbf = { + public static singlePolyPbf = { version: "", queryResult: { featureResult: { @@ -656,12 +655,10 @@ export class NeptuneCoastlineDataset { label: "Urban/Built-up", description: "", }, - ], }, transparency: 30, labelingInfo: null, }, }; - } diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/NewYorkDataset.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/NewYorkDataset.ts index 77449e4b00ac..0468fcb8d8a3 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/NewYorkDataset.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/NewYorkDataset.ts @@ -6,301 +6,612 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class NewYorkDataset { - - public static serviceCapabilities: any = - { - currentVersion : 10.81, - serviceItemId : "af1ebcf87a9741458b08360b5802a003", - hasChangeTrackingEnabledViews : true, - serviceDescription : "Summary text", - hasVersionedData : false, - supportsDisconnectedEditing : false, - hasStaticData : false, - hasSharedDomains : false, - maxRecordCount : 1000, - supportedQueryFormats : "JSON", - supportsVCSProjection : false, - supportedExportFormats : "csv,shapefile,sqlite,geoPackage,filegdb,featureCollection,geojson,excel", - capabilities : "Query,ChangeTracking", - description : "My Description", - copyrightText : "", - spatialReference : { - wkid : 102100, - latestWkid : 3857, - }, - initialExtent : { - xmin : -8253177.9212990291, - ymin : 4956654.8286338719, - xmax : -8218318.9974145154, - ymax : 4971008.5031745536, - spatialReference : { - wkid : 102100, - latestWkid : 3857, - }, - }, - fullExtent : { - xmin : -8270363.8159049358, - ymin : 4935557.2945022825, - xmax : -8204174.9423192516, - ymax : 5000899.6957413526, - spatialReference : { - wkid : 102100, - latestWkid : 3857, - }, - }, - allowGeometryUpdates : true, - units : "esriMeters", - supportsAppend : true, - supportsSharedDomains : true, - supportsWebHooks : true, - supportsTemporalLayers : true, - layerOverridesEnabled : true, - size : 132923392, - syncEnabled : false, - extractChangesCapabilities : { - supportsReturnIdsOnly : true, - supportsReturnExtentOnly : true, - supportsReturnAttachments : true, - supportsLayerQueries : true, - supportsGeometry : true, - supportsFeatureReturn : true, - supportsReturnHasGeometryUpdates : false, - supportsReturnDeletedFeatures : true, - supportsServerGens : true, - }, - supportsApplyEditsWithGlobalIds : true, - supportsReturnDeleteResults : true, - supportsLayerOverrides : true, - supportsTilesAndBasicQueriesMode : true, - supportsQueryContingentValues : true, - supportedContingentValuesFormats : "JSON, PBF", - supportsContingentValuesJson : 2, - advancedEditingCapabilities : { - supportsSplit : false, - supportsReturnServiceEditsInSourceSR : false, - supportsAsyncApplyEdits : true, - supportsReturnEditResults : true, + public static serviceCapabilities: any = { + currentVersion: 10.81, + serviceItemId: "af1ebcf87a9741458b08360b5802a003", + hasChangeTrackingEnabledViews: true, + serviceDescription: "Summary text", + hasVersionedData: false, + supportsDisconnectedEditing: false, + hasStaticData: false, + hasSharedDomains: false, + maxRecordCount: 1000, + supportedQueryFormats: "JSON", + supportsVCSProjection: false, + supportedExportFormats: "csv,shapefile,sqlite,geoPackage,filegdb,featureCollection,geojson,excel", + capabilities: "Query,ChangeTracking", + description: "My Description", + copyrightText: "", + spatialReference: { + wkid: 102100, + latestWkid: 3857, + }, + initialExtent: { + xmin: -8253177.9212990291, + ymin: 4956654.8286338719, + xmax: -8218318.9974145154, + ymax: 4971008.5031745536, + spatialReference: { + wkid: 102100, + latestWkid: 3857, }, - editorTrackingInfo : { - enableEditorTracking : false, - enableOwnershipAccessControl : false, - allowOthersToQuery : true, - allowOthersToUpdate : true, - allowOthersToDelete : false, - allowAnonymousToQuery : true, - allowAnonymousToUpdate : true, - allowAnonymousToDelete : true, + }, + fullExtent: { + xmin: -8270363.8159049358, + ymin: 4935557.2945022825, + xmax: -8204174.9423192516, + ymax: 5000899.6957413526, + spatialReference: { + wkid: 102100, + latestWkid: 3857, }, - changeTrackingInfo : - { - lastSyncDate : 1637077884618, - layerServerGens : [ + }, + allowGeometryUpdates: true, + units: "esriMeters", + supportsAppend: true, + supportsSharedDomains: true, + supportsWebHooks: true, + supportsTemporalLayers: true, + layerOverridesEnabled: true, + size: 132923392, + syncEnabled: false, + extractChangesCapabilities: { + supportsReturnIdsOnly: true, + supportsReturnExtentOnly: true, + supportsReturnAttachments: true, + supportsLayerQueries: true, + supportsGeometry: true, + supportsFeatureReturn: true, + supportsReturnHasGeometryUpdates: false, + supportsReturnDeletedFeatures: true, + supportsServerGens: true, + }, + supportsApplyEditsWithGlobalIds: true, + supportsReturnDeleteResults: true, + supportsLayerOverrides: true, + supportsTilesAndBasicQueriesMode: true, + supportsQueryContingentValues: true, + supportedContingentValuesFormats: "JSON, PBF", + supportsContingentValuesJson: 2, + advancedEditingCapabilities: { + supportsSplit: false, + supportsReturnServiceEditsInSourceSR: false, + supportsAsyncApplyEdits: true, + supportsReturnEditResults: true, + }, + editorTrackingInfo: { + enableEditorTracking: false, + enableOwnershipAccessControl: false, + allowOthersToQuery: true, + allowOthersToUpdate: true, + allowOthersToDelete: false, + allowAnonymousToQuery: true, + allowAnonymousToUpdate: true, + allowAnonymousToDelete: true, + }, + changeTrackingInfo: { + lastSyncDate: 1637077884618, + layerServerGens: [ { - id : 0, - minServerGen : 498989, - serverGen : 689984, + id: 0, + minServerGen: 498989, + serverGen: 689984, }, { - id : 1, - minServerGen : 498989, - serverGen : 689984, + id: 1, + minServerGen: 498989, + serverGen: 689984, }, { - id : 2, - minServerGen : 498989, - serverGen : 689984, + id: 2, + minServerGen: 498989, + serverGen: 689984, }, { - id : 3, - minServerGen : 498989, - serverGen : 689984, + id: 3, + minServerGen: 498989, + serverGen: 689984, }, { - id : 4, - minServerGen : 498989, - serverGen : 689984, + id: 4, + minServerGen: 498989, + serverGen: 689984, }, { - id : 5, - minServerGen : 498989, - serverGen : 689984, + id: 5, + minServerGen: 498989, + serverGen: 689984, }, { - id : 6, - minServerGen : 498989, - serverGen : 689984, + id: 6, + minServerGen: 498989, + serverGen: 689984, }, { - id : 7, - minServerGen : 498989, - serverGen : 689984, + id: 7, + minServerGen: 498989, + serverGen: 689984, }, { - id : 8, - minServerGen : 498989, - serverGen : 689984, + id: 8, + minServerGen: 498989, + serverGen: 689984, }, { - id : 9, - minServerGen : 498989, - serverGen : 689984, + id: 9, + minServerGen: 498989, + serverGen: 689984, }, ], }, - xssPreventionInfo : { - xssPreventionEnabled : true, - xssPreventionRule : "InputOnly", - xssInputRule : "rejectInvalid", + xssPreventionInfo: { + xssPreventionEnabled: true, + xssPreventionRule: "InputOnly", + xssInputRule: "rejectInvalid", + }, + layers: [ + { + id: 0, + name: "Street", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 150000, + maxScale: 0, + geometryType: "esriGeometryPolyline", }, - layers : [ - { - id : 0, - name : "Street", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 150000, - maxScale : 0, - geometryType : "esriGeometryPolyline", - }, - { - id : 1, - name : "Highway", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 150000, - maxScale : 0, - geometryType : "esriGeometryPolyline", - }, - { - id : 2, - name : "Block", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 150000, - maxScale : 0, - geometryType : "esriGeometryPolyline", - }, - { - id : 3, - name : "Shoreline", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolyline", - }, - { - id : 4, - name : "nyco", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - { - id : 5, - name : "nylh", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - { - id : 6, - name : "nysp", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - { - id : 7, - name : "nysp_sd", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - { - id : 8, - name : "nyzd", - parentLayerId : -1, - defaultVisibility : false, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - { - id : 9, - name : "nyzma", - parentLayerId : -1, - defaultVisibility : true, - subLayerIds : null, - minScale : 0, - maxScale : 0, - geometryType : "esriGeometryPolygon", - }, - ], - tables : [], - }; + { + id: 1, + name: "Highway", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 150000, + maxScale: 0, + geometryType: "esriGeometryPolyline", + }, + { + id: 2, + name: "Block", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 150000, + maxScale: 0, + geometryType: "esriGeometryPolyline", + }, + { + id: 3, + name: "Shoreline", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolyline", + }, + { + id: 4, + name: "nyco", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + { + id: 5, + name: "nylh", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + { + id: 6, + name: "nysp", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + { + id: 7, + name: "nysp_sd", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + { + id: 8, + name: "nyzd", + parentLayerId: -1, + defaultVisibility: false, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + { + id: 9, + name: "nyzma", + parentLayerId: -1, + defaultVisibility: true, + subLayerIds: null, + minScale: 0, + maxScale: 0, + geometryType: "esriGeometryPolygon", + }, + ], + tables: [], + }; public static streetsLayerCapabilities: any = { - currentVersion:10.81,id:0,name:"Street",type:"Feature Layer",serviceItemId:"af1ebcf87a9741458b08360b5802a003",cacheMaxAge:30,displayField:"borough",description:"",copyrightText:"",defaultVisibility:true,serverGens:{minServerGen:498989,serverGen:689763}, - editingInfo:{lastEditDate:1637077888141}, - relationships:[],isDataVersioned:false,hasContingentValuesDefinition:false,supportsAppend:true,supportsCalculate:true,supportsASyncCalculate:true,supportsTruncate:true,supportsAttachmentsByUploadId:true,supportsAttachmentsResizing:true,supportsRollbackOnFailureParameter:true,supportsStatistics:true,supportsExceedsLimitStatistics:true,supportsAdvancedQueries:true,supportsValidateSql:true,supportsCoordinatesQuantization:true,supportsLayerOverrides:true,supportsTilesAndBasicQueriesMode:true,supportsFieldDescriptionProperty:true,supportsQuantizationEditMode:true,supportsApplyEditsWithGlobalIds:true,supportsMultiScaleGeometry:true,supportsReturningQueryGeometry:true,hasGeometryProperties:true,geometryProperties:{shapeLengthFieldName:"Shape__Length",units:"esriMeters"}, - advancedQueryCapabilities:{supportsPagination:true,supportsQueryAttachmentsCountOnly:true,supportsPaginationOnAggregatedQueries:true,supportsQueryRelatedPagination:true,supportsQueryWithDistance:true,supportsReturningQueryExtent:true,supportsStatistics:true,supportsOrderBy:true,supportsDistinct:true,supportsQueryWithResultType:true,supportsSqlExpression:true,supportsAdvancedQueryRelated:true,supportsCountDistinct:true,supportsPercentileStatistics:true,supportsSpatialAggregationStatistics:true,supportedSpatialAggregationStatistics:["EnvelopeAggregate","CentroidAggregate","ConvexHullAggregate"],supportsLod:true,supportsQueryWithLodSR:false,supportedLodTypes:["geohash"],supportsReturningGeometryCentroid:false,supportsReturningGeometryProperties:true,supportsQueryWithDatumTransformation:true,supportsHavingClause:true,supportsOutFieldSQLExpression:true,supportsMaxRecordCountFactor:true,supportsTopFeaturesQuery:true,supportsDisjointSpatialRel:true,supportsQueryWithCacheHint:true,supportedOperationsWithCacheHint:["query","queryTopFilter","queryAnalytics","queryAttachments","queryRelated"],supportsQueryAnalytic:true,supportsDefaultSR:true,supportsFullTextSearch:true}, - advancedQueryAnalyticCapabilities:{supportsLinearRegression:true,supportsAsync:true,supportsPercentileAnalytic:true}, - advancedEditingCapabilities:{supportedSqlFormatsInCalculate:["standard"],supportsAsyncApplyEdits:true,supportsReturnEditResults:true}, - infoInEstimates:["extent","count"],useStandardizedQueries:true,geometryType:"esriGeometryPolyline",minScale:150000,maxScale:0,extent:{xmin:-8266144.7918439023,ymin:4938569.7715200111,xmax:-8204248.7873679493,ymax:4999630.6406602357,spatialReference:{wkid:102100,latestWkid:3857}}, - drawingInfo:{renderer:{type:"simple",symbol:{type:"esriSLS",style:"esriSLSSolid",color:[153,0,5,255],width:1}, - label:"",description:""}, - transparency:0,labelingInfo:null}, - allowGeometryUpdates:true, - hasAttachments:false, - htmlPopupType:"esriServerHTMLPopupTypeAsHTMLText", - hasM:false,hasZ:false,objectIdField:"OBJECTID", - uniqueIdField:{name:"OBJECTID", - isSystemMaintained:true}, - globalIdField:"GlobalID", - typeIdField:"", - fields: - [{name:"borough",type:"esriFieldTypeString",alias:"borough",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"build_stat",type:"esriFieldTypeString",alias:"build_stat",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"cco_st",type:"esriFieldTypeString",alias:"cco_st",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"date_edit_",type:"esriFieldTypeDate",alias:"date_edit_",sqlType:"sqlTypeOther",length:8,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"time_edit_",type:"esriFieldTypeString",alias:"time_edit_",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"feat_statu",type:"esriFieldTypeString",alias:"feat_statu",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"feat_type",type:"esriFieldTypeString",alias:"feat_type",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"honorary_n",type:"esriFieldTypeString",alias:"honorary_n",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"marg_wharf",type:"esriFieldTypeString",alias:"marg_wharf",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"old_st_nm",type:"esriFieldTypeString",alias:"old_st_nm",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"paper_st",type:"esriFieldTypeString",alias:"paper_st",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"record_st",type:"esriFieldTypeString",alias:"record_st",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"roadway_ty",type:"esriFieldTypeString",alias:"roadway_ty",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"route_type",type:"esriFieldTypeString",alias:"route_type",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"stair_st",type:"esriFieldTypeString",alias:"stair_st",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"street_nm",type:"esriFieldTypeString",alias:"street_nm",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"streetwidt",type:"esriFieldTypeString",alias:"streetwidt",sqlType:"sqlTypeOther",length:254,nullable:true,editable:true,domain:null,defaultValue:null}, - {name:"OBJECTID",type:"esriFieldTypeOID",alias:"OBJECTID",sqlType:"sqlTypeOther",nullable:false,editable:false,domain:null,defaultValue:null}, - {name:"Shape__Length",type:"esriFieldTypeDouble",alias:"Shape__Length",sqlType:"sqlTypeDouble",nullable:true,editable:false,domain:null,defaultValue:null}, - {name:"GlobalID",type:"esriFieldTypeGlobalID",alias:"GlobalID",sqlType:"sqlTypeOther",length:38,nullable:false,editable:false,domain:null,defaultValue:"NEWID() WITH VALUES"}],indexes:[{name:"PK__NEWYORK3__F4B70D858AB09618",fields:"OBJECTID",isAscending:true,isUnique:true,description:""}, - {name:"user_70600.NEWYORK3857_STREET_Shape_sidx",fields:"Shape",isAscending:true,isUnique:false,description:""}, - {name:"Shape__Length_Index",fields:"Shape__Length",isAscending:true,isUnique:false,description:""}, - {name:"GlobalID_Index",fields:"GlobalID",isAscending:false,isUnique:true,description:""}],dateFieldsTimeReference:{timeZone:"UTC",respectsDaylightSaving:false}, - preferredTimeReference:null,types:[],templates:[{name:"Street",description:"",drawingTool:"esriFeatureEditToolLine",prototype:{attributes:{streetwidt:null,borough:null,build_stat:null,cco_st:null,date_edit_:null,time_edit_:null,feat_statu:null,feat_type:null,honorary_n:null,marg_wharf:null,old_st_nm:null,paper_st:null,record_st:null,roadway_ty:null,route_type:null,stair_st:null,street_nm:null}}}],supportedQueryFormats:"JSON, geoJSON, PBF",supportedAppendFormats:"sqlite,geoPackage,shapefile,filegdb,featureCollection,geojson,csv,excel",supportedExportFormats:"csv,shapefile,sqlite,geoPackage,filegdb,featureCollection,geojson,excel",supportedSpatialRelationships:["esriSpatialRelIntersects","esriSpatialRelContains","esriSpatialRelCrosses","esriSpatialRelEnvelopeIntersects","esriSpatialRelIndexIntersects","esriSpatialRelOverlaps","esriSpatialRelTouches","esriSpatialRelWithin","esriSpatialRelDisjoint","esriSpatialRelRelation"],supportedContingentValuesFormats:"JSON, PBF",supportedSyncDataOptions:4,hasStaticData:false,maxRecordCount:1000,standardMaxRecordCount:4000,standardMaxRecordCountNoGeometry:32000,tileMaxRecordCount:4000,maxRecordCountFactor:1,capabilities:"Query,ChangeTracking"}; + currentVersion: 10.81, + id: 0, + name: "Street", + type: "Feature Layer", + serviceItemId: "af1ebcf87a9741458b08360b5802a003", + cacheMaxAge: 30, + displayField: "borough", + description: "", + copyrightText: "", + defaultVisibility: true, + serverGens: { minServerGen: 498989, serverGen: 689763 }, + editingInfo: { lastEditDate: 1637077888141 }, + relationships: [], + isDataVersioned: false, + hasContingentValuesDefinition: false, + supportsAppend: true, + supportsCalculate: true, + supportsASyncCalculate: true, + supportsTruncate: true, + supportsAttachmentsByUploadId: true, + supportsAttachmentsResizing: true, + supportsRollbackOnFailureParameter: true, + supportsStatistics: true, + supportsExceedsLimitStatistics: true, + supportsAdvancedQueries: true, + supportsValidateSql: true, + supportsCoordinatesQuantization: true, + supportsLayerOverrides: true, + supportsTilesAndBasicQueriesMode: true, + supportsFieldDescriptionProperty: true, + supportsQuantizationEditMode: true, + supportsApplyEditsWithGlobalIds: true, + supportsMultiScaleGeometry: true, + supportsReturningQueryGeometry: true, + hasGeometryProperties: true, + geometryProperties: { shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, + advancedQueryCapabilities: { + supportsPagination: true, + supportsQueryAttachmentsCountOnly: true, + supportsPaginationOnAggregatedQueries: true, + supportsQueryRelatedPagination: true, + supportsQueryWithDistance: true, + supportsReturningQueryExtent: true, + supportsStatistics: true, + supportsOrderBy: true, + supportsDistinct: true, + supportsQueryWithResultType: true, + supportsSqlExpression: true, + supportsAdvancedQueryRelated: true, + supportsCountDistinct: true, + supportsPercentileStatistics: true, + supportsSpatialAggregationStatistics: true, + supportedSpatialAggregationStatistics: ["EnvelopeAggregate", "CentroidAggregate", "ConvexHullAggregate"], + supportsLod: true, + supportsQueryWithLodSR: false, + supportedLodTypes: ["geohash"], + supportsReturningGeometryCentroid: false, + supportsReturningGeometryProperties: true, + supportsQueryWithDatumTransformation: true, + supportsHavingClause: true, + supportsOutFieldSQLExpression: true, + supportsMaxRecordCountFactor: true, + supportsTopFeaturesQuery: true, + supportsDisjointSpatialRel: true, + supportsQueryWithCacheHint: true, + supportedOperationsWithCacheHint: ["query", "queryTopFilter", "queryAnalytics", "queryAttachments", "queryRelated"], + supportsQueryAnalytic: true, + supportsDefaultSR: true, + supportsFullTextSearch: true, + }, + advancedQueryAnalyticCapabilities: { supportsLinearRegression: true, supportsAsync: true, supportsPercentileAnalytic: true }, + advancedEditingCapabilities: { supportedSqlFormatsInCalculate: ["standard"], supportsAsyncApplyEdits: true, supportsReturnEditResults: true }, + infoInEstimates: ["extent", "count"], + useStandardizedQueries: true, + geometryType: "esriGeometryPolyline", + minScale: 150000, + maxScale: 0, + extent: { + xmin: -8266144.7918439023, + ymin: 4938569.7715200111, + xmax: -8204248.7873679493, + ymax: 4999630.6406602357, + spatialReference: { wkid: 102100, latestWkid: 3857 }, + }, + drawingInfo: { + renderer: { type: "simple", symbol: { type: "esriSLS", style: "esriSLSSolid", color: [153, 0, 5, 255], width: 1 }, label: "", description: "" }, + transparency: 0, + labelingInfo: null, + }, + allowGeometryUpdates: true, + hasAttachments: false, + htmlPopupType: "esriServerHTMLPopupTypeAsHTMLText", + hasM: false, + hasZ: false, + objectIdField: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdField: "GlobalID", + typeIdField: "", + fields: [{ + name: "borough", + type: "esriFieldTypeString", + alias: "borough", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "build_stat", + type: "esriFieldTypeString", + alias: "build_stat", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "cco_st", + type: "esriFieldTypeString", + alias: "cco_st", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "date_edit_", + type: "esriFieldTypeDate", + alias: "date_edit_", + sqlType: "sqlTypeOther", + length: 8, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "time_edit_", + type: "esriFieldTypeString", + alias: "time_edit_", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "feat_statu", + type: "esriFieldTypeString", + alias: "feat_statu", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "feat_type", + type: "esriFieldTypeString", + alias: "feat_type", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "honorary_n", + type: "esriFieldTypeString", + alias: "honorary_n", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "marg_wharf", + type: "esriFieldTypeString", + alias: "marg_wharf", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "old_st_nm", + type: "esriFieldTypeString", + alias: "old_st_nm", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "paper_st", + type: "esriFieldTypeString", + alias: "paper_st", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "record_st", + type: "esriFieldTypeString", + alias: "record_st", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "roadway_ty", + type: "esriFieldTypeString", + alias: "roadway_ty", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "route_type", + type: "esriFieldTypeString", + alias: "route_type", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "stair_st", + type: "esriFieldTypeString", + alias: "stair_st", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "street_nm", + type: "esriFieldTypeString", + alias: "street_nm", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "streetwidt", + type: "esriFieldTypeString", + alias: "streetwidt", + sqlType: "sqlTypeOther", + length: 254, + nullable: true, + editable: true, + domain: null, + defaultValue: null, + }, { + name: "OBJECTID", + type: "esriFieldTypeOID", + alias: "OBJECTID", + sqlType: "sqlTypeOther", + nullable: false, + editable: false, + domain: null, + defaultValue: null, + }, { + name: "Shape__Length", + type: "esriFieldTypeDouble", + alias: "Shape__Length", + sqlType: "sqlTypeDouble", + nullable: true, + editable: false, + domain: null, + defaultValue: null, + }, { + name: "GlobalID", + type: "esriFieldTypeGlobalID", + alias: "GlobalID", + sqlType: "sqlTypeOther", + length: 38, + nullable: false, + editable: false, + domain: null, + defaultValue: "NEWID() WITH VALUES", + }], + indexes: [ + { name: "PK__NEWYORK3__F4B70D858AB09618", fields: "OBJECTID", isAscending: true, isUnique: true, description: "" }, + { name: "user_70600.NEWYORK3857_STREET_Shape_sidx", fields: "Shape", isAscending: true, isUnique: false, description: "" }, + { name: "Shape__Length_Index", fields: "Shape__Length", isAscending: true, isUnique: false, description: "" }, + { name: "GlobalID_Index", fields: "GlobalID", isAscending: false, isUnique: true, description: "" }, + ], + dateFieldsTimeReference: { timeZone: "UTC", respectsDaylightSaving: false }, + preferredTimeReference: null, + types: [], + templates: [{ + name: "Street", + description: "", + drawingTool: "esriFeatureEditToolLine", + prototype: { + attributes: { + streetwidt: null, + borough: null, + build_stat: null, + cco_st: null, + date_edit_: null, + time_edit_: null, + feat_statu: null, + feat_type: null, + honorary_n: null, + marg_wharf: null, + old_st_nm: null, + paper_st: null, + record_st: null, + roadway_ty: null, + route_type: null, + stair_st: null, + street_nm: null, + }, + }, + }], + supportedQueryFormats: "JSON, geoJSON, PBF", + supportedAppendFormats: "sqlite,geoPackage,shapefile,filegdb,featureCollection,geojson,csv,excel", + supportedExportFormats: "csv,shapefile,sqlite,geoPackage,filegdb,featureCollection,geojson,excel", + supportedSpatialRelationships: [ + "esriSpatialRelIntersects", + "esriSpatialRelContains", + "esriSpatialRelCrosses", + "esriSpatialRelEnvelopeIntersects", + "esriSpatialRelIndexIntersects", + "esriSpatialRelOverlaps", + "esriSpatialRelTouches", + "esriSpatialRelWithin", + "esriSpatialRelDisjoint", + "esriSpatialRelRelation", + ], + supportedContingentValuesFormats: "JSON, PBF", + supportedSyncDataOptions: 4, + hasStaticData: false, + maxRecordCount: 1000, + standardMaxRecordCount: 4000, + standardMaxRecordCountNoGeometry: 32000, + tileMaxRecordCount: 4000, + maxRecordCountFactor: 1, + capabilities: "Query,ChangeTracking", + }; public static incompleteDrawingInfo = { drawingInfo: { @@ -323,7 +634,8 @@ export class NewYorkDataset { defaultSymbol: { type: "esriPMS", url: "964f19a3e2aa1123345490e04eb4a09d", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAT9JREFUOI2t1E8rRGEUx/HvMHViIm5ZXGt/3gFlwdKGhYjyAmxs7IassDHFyguwwkbZYJKNslVWJDZT1C3psRv9NMpmJk/Tvc3MHWf3/PuccxbPyfKPkW1wPmBmQ5L6giB4d849Al+tYjNAHpiQ1AHgnAMoA+dhGG5HUfTQCOsCDoGlhCTdwGIURfPVZPtJWCdwBkwntVF3d6+K78Rh+SYhP7bM7FbSjY8FwHqLEEBGUgEY97E5oCcFBjAGDAMvNWwyJVSLKR8L28QG4a/N7zYx+VipTazkY0VgNSVUAa597MrMniWNpMBOAOdjFUlrwAWQaQFywGZt4f+AIrAB7DYJlc1sQdJrHAZQAN6AA6A/STGzp1wut+ycu/f340bQEXAJrACzwCjQC3wAd8CppGNJP/UPk+bZZ7XKQlJ1cfEL1AZaAcKna+kAAAAASUVORK5CYII=", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAT9JREFUOI2t1E8rRGEUx/HvMHViIm5ZXGt/3gFlwdKGhYjyAmxs7IassDHFyguwwkbZYJKNslVWJDZT1C3psRv9NMpmJk/Tvc3MHWf3/PuccxbPyfKPkW1wPmBmQ5L6giB4d849Al+tYjNAHpiQ1AHgnAMoA+dhGG5HUfTQCOsCDoGlhCTdwGIURfPVZPtJWCdwBkwntVF3d6+K78Rh+SYhP7bM7FbSjY8FwHqLEEBGUgEY97E5oCcFBjAGDAMvNWwyJVSLKR8L28QG4a/N7zYx+VipTazkY0VgNSVUAa597MrMniWNpMBOAOdjFUlrwAWQaQFywGZt4f+AIrAB7DYJlc1sQdJrHAZQAN6AA6A/STGzp1wut+ycu/f340bQEXAJrACzwCjQC3wAd8CppGNJP/UPk+bZZ7XKQlJ1cfEL1AZaAcKna+kAAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 15, @@ -337,7 +649,8 @@ export class NewYorkDataset { symbol: { type: "esriPMS", url: "7c83731ca464c53c3e14f4287baaf154", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAk1JREFUOI2t0z9oE1EcB/BvmrTPLkofFYSQwQweLYSCmpRcIqHFDrqI4JJrwFaFSIkUipMdFLzlMkiIAaGmhC7BwQ6xhIAtZGiuIJQ41KEZxIZD3i2+pT3sq3jn1FpC0z+kv/F9f3zefw/OuTxn6O0F8PvcQELIayHE83MBKaU3CCHPGGMvAVgdg4qipHK5XA+AOwA+dgwyxu6l02lUq9WJSqXSGUgpHdrZ2bk0OTmJ+fn5MQAXAOyeCFJKg1NTU96RkZHrhxtqtdptSZK6+vv7MTo66qRSqfeDg4M/9nPbtv9ms9m1paUlA8DmAcg531ZV9ZWqqkPj4+OO1+t17WfhcBgAkEgkSKlUShiGAQDY2NhwKpWKC8AnAI9at7wJYJgQkl5fX384OztrDwwM9B1erSzLkGUZjuNgZWXFyOfzFMALANl2ZyiEENONRuNzNBpdyGQyZjwev+Lx/G+zLAuqqv6cm5vbBXALwNcjz7ClypzzgKZp30OhECRJOgh0XYeu69uc85s44k0ed8u93d3dxO/3w7ZtbG1tOX6/3xUIBOB2u31o8w3bgoqiTMRisS7LspyZmRmzWCxe1jRtO5lM9vl8vh5CSEQIsXqWFSaEEHvBYPCPYRgLQog3mqa9W15eHotEIhcVRXlaKBRODXoXFxev6rpumqapCCGqAMAYe1Aul5/U6/W3kiTdBeAC4JwGvA+g1Gw2HwP41ZLlGWOrnPMPlNIQ5/zLiSCldI1znmszGQA0hBDDlNJrrcGRIOe8fgy2X3uMsW+tg/8ALm/uzGg889IAAAAASUVORK5CYII=", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAk1JREFUOI2t0z9oE1EcB/BvmrTPLkofFYSQwQweLYSCmpRcIqHFDrqI4JJrwFaFSIkUipMdFLzlMkiIAaGmhC7BwQ6xhIAtZGiuIJQ41KEZxIZD3i2+pT3sq3jn1FpC0z+kv/F9f3zefw/OuTxn6O0F8PvcQELIayHE83MBKaU3CCHPGGMvAVgdg4qipHK5XA+AOwA+dgwyxu6l02lUq9WJSqXSGUgpHdrZ2bk0OTmJ+fn5MQAXAOyeCFJKg1NTU96RkZHrhxtqtdptSZK6+vv7MTo66qRSqfeDg4M/9nPbtv9ms9m1paUlA8DmAcg531ZV9ZWqqkPj4+OO1+t17WfhcBgAkEgkSKlUShiGAQDY2NhwKpWKC8AnAI9at7wJYJgQkl5fX384OztrDwwM9B1erSzLkGUZjuNgZWXFyOfzFMALANl2ZyiEENONRuNzNBpdyGQyZjwev+Lx/G+zLAuqqv6cm5vbBXALwNcjz7ClypzzgKZp30OhECRJOgh0XYeu69uc85s44k0ed8u93d3dxO/3w7ZtbG1tOX6/3xUIBOB2u31o8w3bgoqiTMRisS7LspyZmRmzWCxe1jRtO5lM9vl8vh5CSEQIsXqWFSaEEHvBYPCPYRgLQog3mqa9W15eHotEIhcVRXlaKBRODXoXFxev6rpumqapCCGqAMAYe1Aul5/U6/W3kiTdBeAC4JwGvA+g1Gw2HwP41ZLlGWOrnPMPlNIQ5/zLiSCldI1znmszGQA0hBDDlNJrrcGRIOe8fgy2X3uMsW+tg/8ALm/uzGg889IAAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 14, @@ -353,7 +666,8 @@ export class NewYorkDataset { symbol: { type: "esriPMS", url: "92fc1fd63ca93a4167dd03e55a4c54fe", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAepJREFUOI2tk09I1EEUxz9r5kuEwqEgWDzooaVAhEqlLKLIg11C6NK2kP2BIpQgOtWhoL2shwgTgjLCi3jQg4UIFniwFYKwQx30EBVL/PbSu2xLPqP9dXBb9KfrJrtfGIaZ953PzJs3U02FVb0Fby3wq2JAEXlgZrcrAnTOHVLRPjzuAdmygRrVXgapAbqAsbKBeJylH5ihh6kygc65Fv2pu7gEPKcT2AEslQQ651r1hoblpBxcbdC3epoIVewGTuHTyzM5IF8Khhx/GGDOXlkKWCgAVTVDnPsWtxYu4BMmVFh0JN/HECaIWcpWxh/xmSIEvAQuB1NeANpFpN/e20XukmM/9WvyOZpvPvCGFEM44A4wsC7lvMzMbrLINMcY5hFpzrN3jSsLxPkuT2Wpjrrjin7Y8A4DmkRpJsFn2oDIqkgSSJIxtcOGrXuTm1W5lu0ITUAO+IpPEyGagW00UOQbFgdG6eEEVWTxuUWaEfaQIMM16mmgRkQ6zGx2KyeMYSzTym9JybCZPSTBE17TSQc7LWrXecF/A8OM00iStKQlamYzAHicY5KrzPOYCGeAECs1LwnsBib4xhXDfgRiQ3jMoow659pU9V1JoHNuTlUHi2wGsIjRLk72BQMbAlV1fhPYPy17nvcpOPkXnK+o4mU668EAAAAASUVORK5CYII=", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAepJREFUOI2tk09I1EEUxz9r5kuEwqEgWDzooaVAhEqlLKLIg11C6NK2kP2BIpQgOtWhoL2shwgTgjLCi3jQg4UIFniwFYKwQx30EBVL/PbSu2xLPqP9dXBb9KfrJrtfGIaZ953PzJs3U02FVb0Fby3wq2JAEXlgZrcrAnTOHVLRPjzuAdmygRrVXgapAbqAsbKBeJylH5ihh6kygc65Fv2pu7gEPKcT2AEslQQ651r1hoblpBxcbdC3epoIVewGTuHTyzM5IF8Khhx/GGDOXlkKWCgAVTVDnPsWtxYu4BMmVFh0JN/HECaIWcpWxh/xmSIEvAQuB1NeANpFpN/e20XukmM/9WvyOZpvPvCGFEM44A4wsC7lvMzMbrLINMcY5hFpzrN3jSsLxPkuT2Wpjrrjin7Y8A4DmkRpJsFn2oDIqkgSSJIxtcOGrXuTm1W5lu0ITUAO+IpPEyGagW00UOQbFgdG6eEEVWTxuUWaEfaQIMM16mmgRkQ6zGx2KyeMYSzTym9JybCZPSTBE17TSQc7LWrXecF/A8OM00iStKQlamYzAHicY5KrzPOYCGeAECs1LwnsBib4xhXDfgRiQ3jMoow659pU9V1JoHNuTlUHi2wGsIjRLk72BQMbAlV1fhPYPy17nvcpOPkXnK+o4mU668EAAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 14, @@ -369,7 +683,8 @@ export class NewYorkDataset { symbol: { type: "esriPMS", url: "70a0856a4503c38b2efa55447af89dc6", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAhtJREFUOI2tk0tIlFEYhp8xm5MImYcsLxgk1aBgQxcdyiSKXNQmggiaBrILFGEE0aoWBbnRRYQJQRklQbSohYUIXZCyEYSwKAmFibTB/tn0QdmQn6Z/C81yvE3oC4cD3+U55z2XVBZYqf9Rmwb8XDCgMeayqp5bEKC1dpOIOQ3ORSA+b6DkBKuQei+wG3gwbyDi7CVQC59bK3Fa5ge01vqFHxn4j8DbWxXAEmBwTqC1tkTWnsozuTs2Ttrcl1e7WOZLIW055O90WVF106ws+jRR8Gt0hHd17dr3OAp0TwBFZICO6ktKtZ81h1xMnmeiqWjL2LwhZPjQFNJv0fGm9y5Oiwd4BBxNtNwNBIwxtRp9fZgDF0axhZmT/ORuHRu40PssSlODBc4DdVMsj0tV9Qz0POHutkYqrsYoPJiN55+y4Ti8qO43kRuD6ZZyEd5Me4YJagYp5mXNR7JLwfr+ZvrD4IQHVGWz6tQ3Odstp8FiQ0YBuKPwvdclo8BDVjGwKJ8ZvuHMwJxgJb7tKQzHXZ6fjRG5l0V5zQDrT2Ri870mbspUtS15oJcQIzrEnZJhQ7RR0Su01Vwn8rSCVWVLleBJIreTBubR93A1sXDMEAuqautY2NmP03wc6bxGum8P4AHcZID7gCa075jC14RcA+q0oXLfWlsqIh1zAq217SJSP8NiAD2gAWPsusTEtEAR6ZwF9kdDjuN0JQZ/A6rmxvoAREK5AAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAhtJREFUOI2tk0tIlFEYhp8xm5MImYcsLxgk1aBgQxcdyiSKXNQmggiaBrILFGEE0aoWBbnRRYQJQRklQbSohYUIXZCyEYSwKAmFibTB/tn0QdmQn6Z/C81yvE3oC4cD3+U55z2XVBZYqf9Rmwb8XDCgMeayqp5bEKC1dpOIOQ3ORSA+b6DkBKuQei+wG3gwbyDi7CVQC59bK3Fa5ge01vqFHxn4j8DbWxXAEmBwTqC1tkTWnsozuTs2Ttrcl1e7WOZLIW055O90WVF106ws+jRR8Gt0hHd17dr3OAp0TwBFZICO6ktKtZ81h1xMnmeiqWjL2LwhZPjQFNJv0fGm9y5Oiwd4BBxNtNwNBIwxtRp9fZgDF0axhZmT/ORuHRu40PssSlODBc4DdVMsj0tV9Qz0POHutkYqrsYoPJiN55+y4Ti8qO43kRuD6ZZyEd5Me4YJagYp5mXNR7JLwfr+ZvrD4IQHVGWz6tQ3Odstp8FiQ0YBuKPwvdclo8BDVjGwKJ8ZvuHMwJxgJb7tKQzHXZ6fjRG5l0V5zQDrT2Ri870mbspUtS15oJcQIzrEnZJhQ7RR0Su01Vwn8rSCVWVLleBJIreTBubR93A1sXDMEAuqautY2NmP03wc6bxGum8P4AHcZID7gCa075jC14RcA+q0oXLfWlsqIh1zAq217SJSP8NiAD2gAWPsusTEtEAR6ZwF9kdDjuN0JQZ/A6rmxvoAREK5AAAAAElFTkSuQmCC", contentType: "image/png", width: 15, height: 14, @@ -385,7 +700,8 @@ export class NewYorkDataset { symbol: { type: "esriPMS", url: "e109df94cd78c13a6d1bc5c2eda6a9a7", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAeRJREFUOI2tkztoVEEUhr88yDEsGHZAERaDorEQJOL6CAQ7g8QmXEwhEsyiFhaKjVUguGAnqOADBV/Exi0CQUELLQyuBA1Rm4CxEJEY7m08zaKbk2CuxWblcpPNg92/GZj/55tzZs40UmM1riPbDBRrBhSRK2Z2qSZA51wa1QsGl4HfVQN7VM8/hiagGxiuGhhAzyCQh8xotUDnXHtRteUE8BS6gA3A7KpA59yBftVUh8i+aGBC9cgOqE8CnRBm4H6byPeyH8LfhzD22mwamPoPVNXCDchi1n4cws1QV/bSi2svyEvomzED4AuEo6Xcc+B0vOUp4JCIXJ0w638CC22QjFabjsDfwvQjcMAAcHNJy4syM7v4A155MJSFwIMtDZFAEbgGMzmR2UQicdhUPy97hzG9UNhzB77tBXZGjHHgIxTUbD9mS2ZypVduBmQbsAD8hLAV6nYDDbCVCt+wItCDTAfU/4EwC8EIbBqAwilIpqBJRDrNLL+eCvvmYe4ozAciQ2Z2/R7cfQddadjomZ3LwZqBqRHY/h4CFTlpZm8AfOj14ewk3GqFY5RGJlwL0BN45sMZzH7FvAc+5H3IOecOquqHVYHOuTFVvV3hMICvlGZ2V9xYFqiqn1aAlTXn+/5kfPMfWXyn81sSLa0AAAAASUVORK5CYII=", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAeRJREFUOI2tkztoVEEUhr88yDEsGHZAERaDorEQJOL6CAQ7g8QmXEwhEsyiFhaKjVUguGAnqOADBV/Exi0CQUELLQyuBA1Rm4CxEJEY7m08zaKbk2CuxWblcpPNg92/GZj/55tzZs40UmM1riPbDBRrBhSRK2Z2qSZA51wa1QsGl4HfVQN7VM8/hiagGxiuGhhAzyCQh8xotUDnXHtRteUE8BS6gA3A7KpA59yBftVUh8i+aGBC9cgOqE8CnRBm4H6byPeyH8LfhzD22mwamPoPVNXCDchi1n4cws1QV/bSi2svyEvomzED4AuEo6Xcc+B0vOUp4JCIXJ0w638CC22QjFabjsDfwvQjcMAAcHNJy4syM7v4A155MJSFwIMtDZFAEbgGMzmR2UQicdhUPy97hzG9UNhzB77tBXZGjHHgIxTUbD9mS2ZypVduBmQbsAD8hLAV6nYDDbCVCt+wItCDTAfU/4EwC8EIbBqAwilIpqBJRDrNLL+eCvvmYe4ozAciQ2Z2/R7cfQddadjomZ3LwZqBqRHY/h4CFTlpZm8AfOj14ewk3GqFY5RGJlwL0BN45sMZzH7FvAc+5H3IOecOquqHVYHOuTFVvV3hMICvlGZ2V9xYFqiqn1aAlTXn+/5kfPMfWXyn81sSLa0AAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 14, @@ -401,7 +717,8 @@ export class NewYorkDataset { symbol: { type: "esriPMS", url: "56cdb91cb6c2a0327abe9787dcef4868", - imageData: "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAjBJREFUOI2tkz9oU1EUxn8pbd7rUF9zie17KVJSinSIKRg1g7gUO+gSBCcpWNTBQXFxclFwc3BQwUGXTpXiouDikqFJIYtCSaEpFfNafC8QPJSWYG9sfA62JaR/pf3G83387jn3ntvOMav9P7KdwK9jAxqG8VRr/fBYgEqplIjcBx4DtSMDHce5JyJh4Arw/shAEcmkUik8zxv3ff9oQKXUsNbaSiQSFIvFUcAE1g8EKqXOO47TNzAwcLY54HneZcuy2kzTxLbtwLbtNz09Pd+bIo3Z2dkZ13WXgfltoIisiciTubm54f7+/sA0zdCWNzQ0BEAymTQWFhbGVlZWAKhWq4GIhICPwK3WkeeBtGEYzyqVys1MJvMnEolEmruNxWLEYjEAyuXycqlUUsAj4MWOkTeltdYPgM9TU1MTIyMjlcHBQTsU2m6WjY0Ncrncj3K5vK6UuiQiX3e9wxZ9As7k8/lv0WiU5kY9z6Nara5prc9prXfs5H6v3AkY3d3dBEHA6upqYFlWKBqNApxij2+4J9BxnPF4PN5Wr9eDbDZbcV33ZDqdXkskEpGurq5wrVa7qLWePjQwHA6PNRqN+uTk5G9gAnheKBReLy0tjfb29p7o6Oi4u7i4eGhgn+u6cdd1K4Zh3NBaZzfr133fv+P7/kul1FUgBASHAV4DPgC3tdY/W7y3wLSIvFNKXRCRwoFApdSMiLza4zCAEv929nSrsStQRL7sA9tS3ff9YmvxL1UE4IbTTnP+AAAAAElFTkSuQmCC", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAjBJREFUOI2tkz9oU1EUxn8pbd7rUF9zie17KVJSinSIKRg1g7gUO+gSBCcpWNTBQXFxclFwc3BQwUGXTpXiouDikqFJIYtCSaEpFfNafC8QPJSWYG9sfA62JaR/pf3G83387jn3ntvOMav9P7KdwK9jAxqG8VRr/fBYgEqplIjcBx4DtSMDHce5JyJh4Arw/shAEcmkUik8zxv3ff9oQKXUsNbaSiQSFIvFUcAE1g8EKqXOO47TNzAwcLY54HneZcuy2kzTxLbtwLbtNz09Pd+bIo3Z2dkZ13WXgfltoIisiciTubm54f7+/sA0zdCWNzQ0BEAymTQWFhbGVlZWAKhWq4GIhICPwK3WkeeBtGEYzyqVys1MJvMnEolEmruNxWLEYjEAyuXycqlUUsAj4MWOkTeltdYPgM9TU1MTIyMjlcHBQTsU2m6WjY0Ncrncj3K5vK6UuiQiX3e9wxZ9As7k8/lv0WiU5kY9z6Nara5prc9prXfs5H6v3AkY3d3dBEHA6upqYFlWKBqNApxij2+4J9BxnPF4PN5Wr9eDbDZbcV33ZDqdXkskEpGurq5wrVa7qLWePjQwHA6PNRqN+uTk5G9gAnheKBReLy0tjfb29p7o6Oi4u7i4eGhgn+u6cdd1K4Zh3NBaZzfr133fv+P7/kul1FUgBASHAV4DPgC3tdY/W7y3wLSIvFNKXRCRwoFApdSMiLza4zCAEv929nSrsStQRL7sA9tS3ff9YmvxL1UE4IbTTnP+AAAAAElFTkSuQmCC", contentType: "image/png", width: 15, height: 14, diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/PhillyLandmarksDataset.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/PhillyLandmarksDataset.ts index 73806f1bef37..221842927702 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/PhillyLandmarksDataset.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/PhillyLandmarksDataset.ts @@ -5,12 +5,14 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class PhillyLandmarksDataset { - // This is the output of a 'Query' request for a point over the philly airport, result is in PDF (64-based encoded arrayBuffer) - public static phillyAirportGetFeatureInfoQueryPbf = "encoding=base64;Er4GCrsGCgNGSUQSBwoDRklEEAEaCEdsb2JhbElEMggI7dQlEM/PKjgDQgcI1J0GEJEeYigSEgkAqHBF+BsjQBEAqHBF+BsjQBoSCRSuKRKK91/BEY3CM4VRflJBagwKA0ZJRBAGGgNGSURqFAoIT0JKRUNUSUQaCE9CSkVDVElEag4KBE5BTUUQBBoETkFNRWoUCgdBRERSRVNTEAQaB0FERFJFU1NqGAoJRkVBVF9UWVBFEAQaCUZFQVRfVFlQRWoWCghTVUJfVFlQRRAEGghTVUJfVFlQRWoaCgpWQU5JVFlfTkFNEAQaClZBTklUWV9OQU1qGgoKU0VDT05EQVJZXxAEGgpTRUNPTkRBUllfag4KBEJMREcQBBoEQkxER2oaCgpQQVJFTlRfTkFNEAQaClBBUkVOVF9OQU1qGgoKUEFSRU5UX1RZUBAEGgpQQVJFTlRfVFlQahQKB0FDUkVBR0UQAxoHQUNSRUFHRWoaCgpQQVJFTlRfQUNSEAMaClBBUkVOVF9BQ1JqGgoKU2hhcGVfX0FyZRADGgpTaGFwZV9fQXJlahoKClNoYXBlX19MZW4QAxoKU2hhcGVfX0xlbmocCgtTaGFwZV9fQXJlYRADGgtTaGFwZV9fQXJlYWogCg1TaGFwZV9fTGVuZ3RoEAMaDVNoYXBlX19MZW5ndGhqKwoIR2xvYmFsSUQQCxoIR2xvYmFsSUQyE05FV0lEKCkgV0lUSCBWQUxVRVN6jgIKAyjfOAoDILxxCiQKIlBoaWxhZGVscGhpYSBJbnRlcm5hdGlvbmFsIEFpcnBvcnQKFAoSODUwMCBFU1NJTkdUT04gQVZFChAKDkFpcnBvcnQgR3JvdW5kCgMKASAKAwoBIAoDCgEgCgMKAU4KJAoiUGhpbGFkZWxwaGlhIEludGVybmF0aW9uYWwgQWlycG9ydAoQCg5BaXJwb3J0IEdyb3VuZAoJGeDvet1otKBACgkZD3T+N0wMokAKCRn9T3m5zTSWQQoJGdwnoJEWcABBCgkZAAAACZsNbEEKCRks5ZMvzB/qQAomCiQ5ZmZjODk1Yi02NGQxLTRiNDItOTU3Ny1jMTZjNjU0ZDk0Yzc="; - public static phillyAirportGetFeatureInfoQueryJson = `{"objectIdFieldName":"FID","uniqueIdField":{"name":"FID","isSystemMaintained":true},"globalIdFieldName":"GlobalID","geometryProperties":{"shapeAreaFieldName":"Shape__Area","shapeLengthFieldName":"Shape__Length","units":"esriMeters"},"serverGens":{"minServerGen":617069,"serverGen":698323},"geometryType":"esriGeometryPolygon","spatialReference":{"wkid":102100,"latestWkid":3857},"transform":{"originPosition":"upperLeft","scale":[4.7773142671503592,4.7773142671503592],"translate":[-8377498.2988891602,4847942.0812841775]},"fields":[{"name":"FID","type":"esriFieldTypeOID","alias":"FID","sqlType":"sqlTypeInteger","domain":null,"defaultValue":null},{"name":"OBJECTID","type":"esriFieldTypeSmallInteger","alias":"OBJECTID","sqlType":"sqlTypeSmallInt","domain":null,"defaultValue":null},{"name":"NAME","type":"esriFieldTypeString","alias":"NAME","sqlType":"sqlTypeNVarchar","length":110,"domain":null,"defaultValue":null},{"name":"ADDRESS","type":"esriFieldTypeString","alias":"ADDRESS","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"FEAT_TYPE","type":"esriFieldTypeString","alias":"FEAT_TYPE","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"SUB_TYPE","type":"esriFieldTypeString","alias":"SUB_TYPE","sqlType":"sqlTypeNVarchar","length":31,"domain":null,"defaultValue":null},{"name":"VANITY_NAM","type":"esriFieldTypeString","alias":"VANITY_NAM","sqlType":"sqlTypeNVarchar","length":47,"domain":null,"defaultValue":null},{"name":"SECONDARY_","type":"esriFieldTypeString","alias":"SECONDARY_","sqlType":"sqlTypeNVarchar","length":67,"domain":null,"defaultValue":null},{"name":"BLDG","type":"esriFieldTypeString","alias":"BLDG","sqlType":"sqlTypeNVarchar","length":1,"domain":null,"defaultValue":null},{"name":"PARENT_NAM","type":"esriFieldTypeString","alias":"PARENT_NAM","sqlType":"sqlTypeNVarchar","length":63,"domain":null,"defaultValue":null},{"name":"PARENT_TYP","type":"esriFieldTypeString","alias":"PARENT_TYP","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"ACREAGE","type":"esriFieldTypeDouble","alias":"ACREAGE","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"PARENT_ACR","type":"esriFieldTypeDouble","alias":"PARENT_ACR","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Are","type":"esriFieldTypeDouble","alias":"Shape__Are","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Len","type":"esriFieldTypeDouble","alias":"Shape__Len","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Area","type":"esriFieldTypeDouble","alias":"Shape__Area","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Length","type":"esriFieldTypeDouble","alias":"Shape__Length","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"GlobalID","type":"esriFieldTypeGlobalID","alias":"GlobalID","sqlType":"sqlTypeOther","length":38,"domain":null}],"features":[{"attributes":{"FID":7263,"OBJECTID":7262,"NAME":"Philadelphia International Airport","ADDRESS":"8500 ESSINGTON AVE","FEAT_TYPE":"Airport Ground","SUB_TYPE":" ","VANITY_NAM":" ","SECONDARY_":" ","BLDG":"N","PARENT_NAM":"Philadelphia International Airport","PARENT_TYP":"Airport Ground","ACREAGE":2138.20481476,"PARENT_ACR":2310.1488647,"Shape__Are":93139822.3684692,"Shape__Len":134658.821106254,"Shape__Area":14707928.28125,"Shape__Length":53502.3808078266,"GlobalID":"9ffc895b-64d1-4b42-9577-c16c654d94c7"}}]}`; + public static phillyAirportGetFeatureInfoQueryPbf = + "encoding=base64;Er4GCrsGCgNGSUQSBwoDRklEEAEaCEdsb2JhbElEMggI7dQlEM/PKjgDQgcI1J0GEJEeYigSEgkAqHBF+BsjQBEAqHBF+BsjQBoSCRSuKRKK91/BEY3CM4VRflJBagwKA0ZJRBAGGgNGSURqFAoIT0JKRUNUSUQaCE9CSkVDVElEag4KBE5BTUUQBBoETkFNRWoUCgdBRERSRVNTEAQaB0FERFJFU1NqGAoJRkVBVF9UWVBFEAQaCUZFQVRfVFlQRWoWCghTVUJfVFlQRRAEGghTVUJfVFlQRWoaCgpWQU5JVFlfTkFNEAQaClZBTklUWV9OQU1qGgoKU0VDT05EQVJZXxAEGgpTRUNPTkRBUllfag4KBEJMREcQBBoEQkxER2oaCgpQQVJFTlRfTkFNEAQaClBBUkVOVF9OQU1qGgoKUEFSRU5UX1RZUBAEGgpQQVJFTlRfVFlQahQKB0FDUkVBR0UQAxoHQUNSRUFHRWoaCgpQQVJFTlRfQUNSEAMaClBBUkVOVF9BQ1JqGgoKU2hhcGVfX0FyZRADGgpTaGFwZV9fQXJlahoKClNoYXBlX19MZW4QAxoKU2hhcGVfX0xlbmocCgtTaGFwZV9fQXJlYRADGgtTaGFwZV9fQXJlYWogCg1TaGFwZV9fTGVuZ3RoEAMaDVNoYXBlX19MZW5ndGhqKwoIR2xvYmFsSUQQCxoIR2xvYmFsSUQyE05FV0lEKCkgV0lUSCBWQUxVRVN6jgIKAyjfOAoDILxxCiQKIlBoaWxhZGVscGhpYSBJbnRlcm5hdGlvbmFsIEFpcnBvcnQKFAoSODUwMCBFU1NJTkdUT04gQVZFChAKDkFpcnBvcnQgR3JvdW5kCgMKASAKAwoBIAoDCgEgCgMKAU4KJAoiUGhpbGFkZWxwaGlhIEludGVybmF0aW9uYWwgQWlycG9ydAoQCg5BaXJwb3J0IEdyb3VuZAoJGeDvet1otKBACgkZD3T+N0wMokAKCRn9T3m5zTSWQQoJGdwnoJEWcABBCgkZAAAACZsNbEEKCRks5ZMvzB/qQAomCiQ5ZmZjODk1Yi02NGQxLTRiNDItOTU3Ny1jMTZjNjU0ZDk0Yzc="; + public static phillyAirportGetFeatureInfoQueryJson = + `{"objectIdFieldName":"FID","uniqueIdField":{"name":"FID","isSystemMaintained":true},"globalIdFieldName":"GlobalID","geometryProperties":{"shapeAreaFieldName":"Shape__Area","shapeLengthFieldName":"Shape__Length","units":"esriMeters"},"serverGens":{"minServerGen":617069,"serverGen":698323},"geometryType":"esriGeometryPolygon","spatialReference":{"wkid":102100,"latestWkid":3857},"transform":{"originPosition":"upperLeft","scale":[4.7773142671503592,4.7773142671503592],"translate":[-8377498.2988891602,4847942.0812841775]},"fields":[{"name":"FID","type":"esriFieldTypeOID","alias":"FID","sqlType":"sqlTypeInteger","domain":null,"defaultValue":null},{"name":"OBJECTID","type":"esriFieldTypeSmallInteger","alias":"OBJECTID","sqlType":"sqlTypeSmallInt","domain":null,"defaultValue":null},{"name":"NAME","type":"esriFieldTypeString","alias":"NAME","sqlType":"sqlTypeNVarchar","length":110,"domain":null,"defaultValue":null},{"name":"ADDRESS","type":"esriFieldTypeString","alias":"ADDRESS","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"FEAT_TYPE","type":"esriFieldTypeString","alias":"FEAT_TYPE","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"SUB_TYPE","type":"esriFieldTypeString","alias":"SUB_TYPE","sqlType":"sqlTypeNVarchar","length":31,"domain":null,"defaultValue":null},{"name":"VANITY_NAM","type":"esriFieldTypeString","alias":"VANITY_NAM","sqlType":"sqlTypeNVarchar","length":47,"domain":null,"defaultValue":null},{"name":"SECONDARY_","type":"esriFieldTypeString","alias":"SECONDARY_","sqlType":"sqlTypeNVarchar","length":67,"domain":null,"defaultValue":null},{"name":"BLDG","type":"esriFieldTypeString","alias":"BLDG","sqlType":"sqlTypeNVarchar","length":1,"domain":null,"defaultValue":null},{"name":"PARENT_NAM","type":"esriFieldTypeString","alias":"PARENT_NAM","sqlType":"sqlTypeNVarchar","length":63,"domain":null,"defaultValue":null},{"name":"PARENT_TYP","type":"esriFieldTypeString","alias":"PARENT_TYP","sqlType":"sqlTypeNVarchar","length":25,"domain":null,"defaultValue":null},{"name":"ACREAGE","type":"esriFieldTypeDouble","alias":"ACREAGE","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"PARENT_ACR","type":"esriFieldTypeDouble","alias":"PARENT_ACR","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Are","type":"esriFieldTypeDouble","alias":"Shape__Are","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Len","type":"esriFieldTypeDouble","alias":"Shape__Len","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Area","type":"esriFieldTypeDouble","alias":"Shape__Area","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"Shape__Length","type":"esriFieldTypeDouble","alias":"Shape__Length","sqlType":"sqlTypeFloat","domain":null,"defaultValue":null},{"name":"GlobalID","type":"esriFieldTypeGlobalID","alias":"GlobalID","sqlType":"sqlTypeOther","length":38,"domain":null}],"features":[{"attributes":{"FID":7263,"OBJECTID":7262,"NAME":"Philadelphia International Airport","ADDRESS":"8500 ESSINGTON AVE","FEAT_TYPE":"Airport Ground","SUB_TYPE":" ","VANITY_NAM":" ","SECONDARY_":" ","BLDG":"N","PARENT_NAM":"Philadelphia International Airport","PARENT_TYP":"Airport Ground","ACREAGE":2138.20481476,"PARENT_ACR":2310.1488647,"Shape__Are":93139822.3684692,"Shape__Len":134658.821106254,"Shape__Area":14707928.28125,"Shape__Length":53502.3808078266,"GlobalID":"9ffc895b-64d1-4b42-9577-c16c654d94c7"}}]}`; - public static phillyTransportationGetFeatureInfoQueryEncodedPbf = "encoding=base64;EqQ1CqE1CghPQkpFQ1RJRBIMCghPQkpFQ1RJRBABGghHbG9iYWxJRDIICODUJRCFhCtCBwjUnQYQkR5iKBISCQCAcEX4GwNAEQCAcEX4GwNAGhIJmpn1FzXpX8ER9ihfAEOKUkFqFgoIT0JKRUNUSUQQBhoIT0JKRUNUSURqSQofR0lTREFUQVBST0pFQ1RfTE9DQVRJT05fREVUQUlMXxABGiRHSVNEQVRBUFJPSkVDVF9MT0NBVElPTl9ERVRBSUxfUFRGSURqGgoKUFJPSkVDVF9JRBABGgpQUk9KRUNUX0lEaiAKDVBST0pFQ1RfVElUTEUQBBoNUFJPSkVDVF9USVRMRWoiCg5QUk9KRUNUX1NUQVRVUxAEGg5QUk9KRUNUX1NUQVRVU2ogCg1QUk9KRUNUX0NMQVNTEAQaDVBST0pFQ1RfQ0xBU1NqKgoSUFJPSkVDVF9DTEFTU19OQU1FEAQaElBST0pFQ1RfQ0xBU1NfTkFNRWo2ChhQUk9KRUNUX0lNUFJPVkVNRU5UX0RFU0MQBBoYUFJPSkVDVF9JTVBST1ZFTUVOVF9ERVNDajQKF1BST0pFQ1RfU0hPUlRfTkFSUkFUSVZFEAQaF1BST0pFQ1RfU0hPUlRfTkFSUkFUSVZFaiYKEElNUFJPVkVNRU5UX1RZUEUQBBoQSU1QUk9WRU1FTlRfVFlQRWokChBJTVBST1ZFTUVOVF9DT0RFGhBJTVBST1ZFTUVOVF9DT0RFajIKFklNUFJPVkVNRU5UX1NIT1JUX0RFU0MQBBoWSU1QUk9WRU1FTlRfU0hPUlRfREVTQ2okCg9UWVBfRlJTVF9BUFJfRFQQBRoPVFlQX0ZSU1RfQVBSX0RUaioKEk1BSk9SX1BST0pFQ1RfRkxBRxAEGhJNQUpPUl9QUk9KRUNUX0ZMQUdqIgoOVFJBTlNQT1JUX01PREUQBBoOVFJBTlNQT1JUX01PREVqPAobUExBTk5JTkdfUEFSVE5FUl9TSE9SVF9OQU1FEAQaG1BMQU5OSU5HX1BBUlRORVJfU0hPUlRfTkFNRWoyChdSRVNQT05TSUJMRV9ESVNUUklDVF9OTxoXUkVTUE9OU0lCTEVfRElTVFJJQ1RfTk9qJAoQUFJJTUFSWV9TVF9SVF9OTxoQUFJJTUFSWV9TVF9SVF9OT2osChNESVNUUklDVF9TRUNUSU9OX0lEEAQaE0RJU1RSSUNUX1NFQ1RJT05fSURqNgoZUFJJTUFSWV9MT0NBTF9ST0FEX05VTUJFUhoZUFJJTUFSWV9MT0NBTF9ST0FEX05VTUJFUmouChRQUk9KRUNUX1RPVEFMX0xFTkdUSBACGhRQUk9KRUNUX1RPVEFMX0xFTkdUSGoqChJMT0NBTF9QUk9KRUNUX0ZMQUcQBBoSTE9DQUxfUFJPSkVDVF9GTEFHajIKFkxFVF9SRVNQT05TSUJMRV9BR0VOQ1kQBBoWTEVUX1JFU1BPTlNJQkxFX0FHRU5DWWoyChZHRU9HUkFQSElDX0RFU0NSSVBUSU9OEAQaFkdFT0dSQVBISUNfREVTQ1JJUFRJT05qKgoSUFJPSkVDVF9TVEFURV9DT0RFEAQaElBST0pFQ1RfU1RBVEVfQ09ERWo2ChhQUk9KRUNUX1NUQVRVU19DT0RFX0RFU0MQBBoYUFJPSkVDVF9TVEFUVVNfQ09ERV9ERVNDahIKB0NPREVfSUQaB0NPREVfSURqQAodUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFX0ZMQUcQBBodUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFX0ZMQUdqNgoYUE9URU5USUFMX0NPTU1JVFRFRF9ZRUFSEAQaGFBPVEVOVElBTF9DT01NSVRURURfWUVBUmo2ChhQT1RFTlRJQUxfQ09NTUlUVEVEX0RBVEUQBBoYUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFaj4KHEVTVF9DT05TVFJfUEhBU0VfQ09TVF9BTU9VTlQQAhocRVNUX0NPTlNUUl9QSEFTRV9DT1NUX0FNT1VOVGoWCghUWVBfRkxBRxAEGghUWVBfRkxBR2oWCghUSVBfRkxBRxAEGghUSVBfRkxBR2oYCglTVElQX0ZMQUcQBBoJU1RJUF9GTEFHajgKGURFQ0FERV9PRl9JTlZFU1RNRU5UX0ZMQUcQBBoZREVDQURFX09GX0lOVkVTVE1FTlRfRkxBR2ooChFUSVBfUFJPUE9TRURfRkxBRxAEGhFUSVBfUFJPUE9TRURfRkxBR2ooChFUWVBfUFJPUE9TRURfRkxBRxAEGhFUWVBfUFJPUE9TRURfRkxBR2ouChRPQkxJR0FUSU9OX1BMQU5fRkxBRxAEGhRPQkxJR0FUSU9OX1BMQU5fRkxBR2oWCghMRVRfRkxBRxAEGghMRVRfRkxBR2oWCghMRVRfREFURRAEGghMRVRfREFURWomChBMRVRfREFURV9ESVNQTEFZEAQaEExFVF9EQVRFX0RJU1BMQVlqGAoJT1BFTl9GTEFHEAQaCU9QRU5fRkxBR2oYCglPUEVOX0RBVEUQBBoJT1BFTl9EQVRFahYKCE5UUF9GTEFHEAQaCE5UUF9GTEFHahYKCE5UUF9EQVRFEAEaCE5UUF9EQVRFaiQKD0NPTVBMRVRJT05fRkxBRxAEGg9DT01QTEVUSU9OX0ZMQUdqJAoPQ09NUExFVElPTl9EQVRFEAQaD0NPTVBMRVRJT05fREFURWoiCg5GSVNDQUxMWV9SRUFEWRAEGg5GSVNDQUxMWV9SRUFEWWocCgtGSVNDQUxfREFURRAEGgtGSVNDQUxfREFURWomChBQSFlTSUNBTExZX1JFQURZEAQaEFBIWVNJQ0FMTFlfUkVBRFlqIAoNUEhZU0lDQUxfREFURRAEGg1QSFlTSUNBTF9EQVRFaj4KHFBST0pFQ1RfTUFOQUdFUl9DT05UQUNUX05BTUUQBBocUFJPSkVDVF9NQU5BR0VSX0NPTlRBQ1RfTkFNRWowChVQUk9KRUNUX01BTkFHRVJfUEhPTkUQBBoVUFJPSkVDVF9NQU5BR0VSX1BIT05FajAKFVBST0pFQ1RfTUFOQUdFUl9FTUFJTBAEGhVQUk9KRUNUX01BTkFHRVJfRU1BSUxqKgoSVU5ERVJfQ09OU1RSVUNUSU9OEAQaElVOREVSX0NPTlNUUlVDVElPTmoYCglDT01QTEVURUQQBBoJQ09NUExFVEVEaioKEkZVVFVSRV9ERVZFTE9QTUVOVBAEGhJGVVRVUkVfREVWRUxPUE1FTlRqIgoOSU5fREVWRUxPUE1FTlQQBBoOSU5fREVWRUxPUE1FTlRqIAoNUFJPSkVDVF9TVEFHRRAEGg1QUk9KRUNUX1NUQUdFajAKFVBST0pFQ1RfQ1JFQVRJT05fREFURRAFGhVQUk9KRUNUX0NSRUFUSU9OX0RBVEVqLAoTQ0FQSVRBTF9CVURHRVRfWUVBUhAEGhNDQVBJVEFMX0JVREdFVF9ZRUFSaj4KHENBUFRJQUxfQlVER0VUX1JFUVVJUkVEX0ZMQUcQBBocQ0FQVElBTF9CVURHRVRfUkVRVUlSRURfRkxBR2o+ChxDQVBJVEFMX0JVREdFVF9BUFBST1ZFRF9GTEFHEAQaHENBUElUQUxfQlVER0VUX0FQUFJPVkVEX0ZMQUdqMAoVUExBTk5JTkdfUEFSVE5FUl9OQU1FEAQaFVBMQU5OSU5HX1BBUlRORVJfTkFNRWo4ChlSRVNQT05TSUJMRV9ESVNUUklDVF9OQU1FEAQaGVJFU1BPTlNJQkxFX0RJU1RSSUNUX05BTUVqMgoXUkVTUE9OU0lCTEVfQ09VTlRZX0NPREUaF1JFU1BPTlNJQkxFX0NPVU5UWV9DT0RFajQKF1JFU1BPTlNJQkxFX0NPVU5UWV9OQU1FEAQaF1JFU1BPTlNJQkxFX0NPVU5UWV9OQU1Fai4KFFBST0pFQ1RfU1BPTlNPUl9OQU1FEAQaFFBST0pFQ1RfU1BPTlNPUl9OQU1FaiwKE1NEX0JSSURHRV9XT1JLX0ZMQUcQBBoTU0RfQlJJREdFX1dPUktfRkxBR2ouChRPUEVOX1RPX1RSQUZGSUNfREFURRAEGhRPUEVOX1RPX1RSQUZGSUNfREFURWo2ChhPUklHSU5BTF9DT05UUkFDVF9BTU9VTlQQBBoYT1JJR0lOQUxfQ09OVFJBQ1RfQU1PVU5UajQKF0NVUlJFTlRfQ09OVFJBQ1RfQU1PVU5UEAQaF0NVUlJFTlRfQ09OVFJBQ1RfQU1PVU5UaioKEkVTVElNQVRFRF9MRVRfREFURRAEGhJFU1RJTUFURURfTEVUX0RBVEVqFgoIRE9JX0RBVEUQBBoIRE9JX0RBVEVqEgoGRE9JX0lEEAQaBkRPSV9JRGoqChJQUklNQVJZX1BST0pFQ1RfSUQQARoSUFJJTUFSWV9QUk9KRUNUX0lEajQKF1BSSU1BUllfQ09OVFJBQ1RfQU1PVU5UEAQaF1BSSU1BUllfQ09OVFJBQ1RfQU1PVU5Uai4KFFBSSU1BUllfUFJPSkVDVF9GTEFHEAQaFFBSSU1BUllfUFJPSkVDVF9GTEFHajIKFkhBU19DT05TVFJVQ1RJT05fUEhBU0UQBBoWSEFTX0NPTlNUUlVDVElPTl9QSEFTRWoyChZIQVNfRklOQUxfREVTSUdOX1BIQVNFEAQaFkhBU19GSU5BTF9ERVNJR05fUEhBU0VqQgoeSEFTX1BSRUxJTUlOQVJZX0VOR0lORUVSX1BIQVNFEAQaHkhBU19QUkVMSU1JTkFSWV9FTkdJTkVFUl9QSEFTRWpACh1IQVNfUExBTl9SRVNFQVJDSF9BRE1JTl9QSEFTRRAEGh1IQVNfUExBTl9SRVNFQVJDSF9BRE1JTl9QSEFTRWoyChZIQVNfUklHSFRfT0ZfV0FZX1BIQVNFEAQaFkhBU19SSUdIVF9PRl9XQVlfUEhBU0VqJAoPSEFTX1NUVURZX1BIQVNFEAQaD0hBU19TVFVEWV9QSEFTRWooChFIQVNfVVRJTElUWV9QSEFTRRAEGhFIQVNfVVRJTElUWV9QSEFTRWoUCghDVFlfQ09ERRoIQ1RZX0NPREVqFAoIU1RfUlRfTk8aCFNUX1JUX05Pag4KBUpVUklTGgVKVVJJU2oaCgtESVNUUklDVF9OTxoLRElTVFJJQ1RfTk9qEgoHU0VHX0JHThoHU0VHX0JHTmoYCgpPRkZTRVRfQkdOGgpPRkZTRVRfQkdOahIKB1NFR19FTkQaB1NFR19FTkRqGAoKT0ZGU0VUX0VORBoKT0ZGU0VUX0VORGoaCgpTRUdfUFRfQkdOEAEaClNFR19QVF9CR05qGgoKU0VHX1BUX0VORBABGgpTRUdfUFRfRU5EaiIKDlNFR19MTkdUSF9GRUVUEAEaDlNFR19MTkdUSF9GRUVUahIKBk5MRl9JRBABGgZOTEZfSURqFAoIU0lERV9JTkQaCFNJREVfSU5Eah4KDE5MRl9DTlRMX0JHThABGgxOTEZfQ05UTF9CR05qHgoMTkxGX0NOVExfRU5EEAEaDE5MRl9DTlRMX0VORGoiCg5DVU1fT0ZGU0VUX0JHThABGg5DVU1fT0ZGU0VUX0JHTmoiCg5DVU1fT0ZGU0VUX0VORBABGg5DVU1fT0ZGU0VUX0VORGo4ChlDT1VOVFlfTVVOSUNJUEFMSVRZX0NPREVTEAQaGUNPVU5UWV9NVU5JQ0lQQUxJVFlfQ09ERVNqKgoSTVVOSUNJUEFMSVRZX0NPREVTEAQaEk1VTklDSVBBTElUWV9DT0RFU2oqChJNVU5JQ0lQQUxJVFlfTkFNRVMQBBoSTVVOSUNJUEFMSVRZX05BTUVTaiQKD0hPVVNFX0RJU1RSSUNUUxAEGg9IT1VTRV9ESVNUUklDVFNqJgoQU0VOQVRFX0RJU1RSSUNUUxAEGhBTRU5BVEVfRElTVFJJQ1RTaioKEkNPTkdSRVNTX0RJU1RSSUNUUxAEGhJDT05HUkVTU19ESVNUUklDVFNqMgoWSE9VU0VfTEVHSVNMQVRPUl9OQU1FUxAEGhZIT1VTRV9MRUdJU0xBVE9SX05BTUVTajQKF1NFTkFURV9MRUdJU0xBVE9SX05BTUVTEAQaF1NFTkFURV9MRUdJU0xBVE9SX05BTUVTajgKGUNPTkdSRVNTX0xFR0lTTEFUT1JfTkFNRVMQBBoZQ09OR1JFU1NfTEVHSVNMQVRPUl9OQU1FU2ocCgtDT1VOVFlfTkFNRRAEGgtDT1VOVFlfTkFNRWocCgtTVFJFRVRfTkFNRRAEGgtTVFJFRVRfTkFNRWomChBCUklER0VfV09SS19GTEFHEAQaEEJSSURHRV9XT1JLX0ZMQUdqIAoNUkVDT1JEX1VQREFURRABGg1SRUNPUkRfVVBEQVRFah4KDENSRUFURURfREFURRAFGgxDUkVBVEVEX0RBVEVqJgoQTEFTVF9FRElURURfREFURRAFGhBMQVNUX0VESVRFRF9EQVRFaiIKDkdFT01fTEVOR1RIX0ZUEAEaDkdFT01fTEVOR1RIX0ZUaiAKDUdFT01FVFJZX1RZUEUQBBoNR0VPTUVUUllfVFlQRWo4ChlCUklER0VfV09SS19MT0NBVElPTl9GTEFHEAQaGUJSSURHRV9XT1JLX0xPQ0FUSU9OX0ZMQUdqJgoQUFVCTElDX05BUlJBVElWRRAEGhBQVUJMSUNfTkFSUkFUSVZFaiQKD0dJU19VUERBVEVfREFURRAFGg9HSVNfVVBEQVRFX0RBVEVqNgoYR0lTX0dFT01FVFJZX1VQREFURV9EQVRFEAUaGEdJU19HRU9NRVRSWV9VUERBVEVfREFURWomChBTRV9BTk5PX0NBRF9EQVRBEAQaEFNFX0FOTk9fQ0FEX0RBVEFqDgoER1BJRBABGgRHUElEaisKCEdsb2JhbElEEAsaCEdsb2JhbElEMhNORVdJRCgpIFdJVEggVkFMVUVTeukLCgMoqAoKBiDsi8mhBwoEINjCDAobChlIaWdoIEZyaWN0aW9uIFN1cmZhY2VzKEYpCgYKBENBTkQKBgoEU0FGRQoUChJTYWZldHkgSW1wcm92ZW1lbnQKgAEKfkluc3RhbGxpbmcgaGlnaCBmcmljdGlvbiBzdXJmYWNlcyBvbiB0b3Agb2YgZXhpc3Rpbmcgcm9hZHdheSB0byBkZWNyZWFzZSB0aGUgbnVtYmVyIG9mIGNyYXNoZXMgYWxvbmcgaGlnaCBjcmFzaCByb2Fkd2F5IGN1cnZlcwpuCmxIaWdoIEZyaWN0aW9uIFN1cmZhY2VzICBWYXJpb3VzIGhpZ2gtY3Jhc2ggcm9hZHdheSBjdXJ2ZXMgaW4gRDYtMCAgVHJlYXRtbnQgdG8gcmVkdWNlIGNyYXNoZXMgb24gcmR3eSBjdXJ2ZXMKEwoRU3VyZmFjZSBUcmVhdG1lbnQKAiBKChMKEVN1cmZhY2UgVHJlYXRtZW50CgdAgNCHrr5RCgMKAU4KAwoBSAoHCgVEVlJQQwoCIAwKAyCyLwoFCgNIRlMKAiAACgUV16PYQAoDCgFOCgAKMwoxVmFyaW91cyBoaWdoLWNyYXNoIHJvYWR3YXkgY3VydmVzIGluIERpc3RyaWN0IDYtMAoGCgRDQU5ECgsKCUNhbmRpZGF0ZQoCIFYKAAoAChcKFTYvMTIvMjAxNCAxMjowMDowMCBBTQoFFSA7FUoKAwoBTgoDCgFOCgMKAU4KAwoBTgoDCgFOCgMKAU4KAwoBWQoDCgFBCgoKCDIwMTQwNzAzChYKFDcvMy8yMDE0IDEyOjAwOjAwIEFNCgAKAAoDCgFBCgUgpMyaEwoDCgFBCgoKCDIwMTUxMDA3CgAKAAoACgAKHQobR2VvcmdlIER1bmhlaW1lciBBREUgQ09OU1RSCgwKCjYxMDIwNTY2ODAKEwoRZ2R1bmhlaW1lckBwYS5nb3YKAwoBTgoDCgFZCgMKAU4KAwoBTgoLCglDT01QTEVURUQKB0CA4I+irlEKAAoDCgFZCgMKAU4KTQpLRGVsYXdhcmUgVmFsbGV5IFJlZ2lvbmFsIFBsYW5uaW5nIENvbW1pc3Npb24gTVBPICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAKHkRpc3RyaWN0IDYtMCAgICAgICAgICAgICAgICAgIAoCIB4KEAoOQ2hlc3RlciAgICAgICAKCQoHUGVubkRPVAoDCgFOCgAKAAoAChYKFDcvMy8yMDE0IDEyOjAwOjAwIEFNCgAKAAoEINjCDAoACgMKAVkKAwoBVAoDCgFGCgMKAUYKAwoBRgoDCgFGCgMKAUYKAwoBRgoDIIYBCgMgkn0KAiACCgIgDAoDIPQDCgIgAAoDIPQDCgMglC0KBSDAlrECCgUg1MOxAgoDIJQtCgQg9uIECgIgAgoCIAAKAyCULQoDIPxmCgQgkJQBCgcKBTY3MzAxCgUKAzMwMQoPCg1QSElMQURFTFBISUEgCgUKAzE3NQoDCgExChYKFDIvMy8yMDIyIDEyOjAwOjAwIEFNChoKGE1hcnlsb3Vpc2UgSXNhYWNzb24sIChEKQoSChBOaWtpbCBTYXZhbCwgKEQpCigKJkJyZW5kYW4gRi4gQm95bGUgKEQpLCBEd2lnaHQgRXZhbnMgKEQpCg4KDFBISUxBREVMUEhJQQoACgMKAU4KBSDCjaMTCgdA8Nb9/dVaCgdAkPzT8LZeCgMgwE0KBwoFUE9JTlQKAwoBTgpuCmxIaWdoIEZyaWN0aW9uIFN1cmZhY2VzDQpWYXJpb3VzIGhpZ2gtY3Jhc2ggcm9hZHdheSBjdXJ2ZXMgaW4gRDYtMA0KVHJlYXRtbnQgdG8gcmVkdWNlIGNyYXNoZXMgb24gcmR3eSBjdXJ2ZXMKB0CQiOrHqF0KB0CQvKWDnl8KAAoGIOyLyaEHCiYKJDg4YzlhMDA2LTRhZjQtNDdlYi1iZWE2LTU1M2E2MTMwNmNlZQ=="; + public static phillyTransportationGetFeatureInfoQueryEncodedPbf = + "encoding=base64;EqQ1CqE1CghPQkpFQ1RJRBIMCghPQkpFQ1RJRBABGghHbG9iYWxJRDIICODUJRCFhCtCBwjUnQYQkR5iKBISCQCAcEX4GwNAEQCAcEX4GwNAGhIJmpn1FzXpX8ER9ihfAEOKUkFqFgoIT0JKRUNUSUQQBhoIT0JKRUNUSURqSQofR0lTREFUQVBST0pFQ1RfTE9DQVRJT05fREVUQUlMXxABGiRHSVNEQVRBUFJPSkVDVF9MT0NBVElPTl9ERVRBSUxfUFRGSURqGgoKUFJPSkVDVF9JRBABGgpQUk9KRUNUX0lEaiAKDVBST0pFQ1RfVElUTEUQBBoNUFJPSkVDVF9USVRMRWoiCg5QUk9KRUNUX1NUQVRVUxAEGg5QUk9KRUNUX1NUQVRVU2ogCg1QUk9KRUNUX0NMQVNTEAQaDVBST0pFQ1RfQ0xBU1NqKgoSUFJPSkVDVF9DTEFTU19OQU1FEAQaElBST0pFQ1RfQ0xBU1NfTkFNRWo2ChhQUk9KRUNUX0lNUFJPVkVNRU5UX0RFU0MQBBoYUFJPSkVDVF9JTVBST1ZFTUVOVF9ERVNDajQKF1BST0pFQ1RfU0hPUlRfTkFSUkFUSVZFEAQaF1BST0pFQ1RfU0hPUlRfTkFSUkFUSVZFaiYKEElNUFJPVkVNRU5UX1RZUEUQBBoQSU1QUk9WRU1FTlRfVFlQRWokChBJTVBST1ZFTUVOVF9DT0RFGhBJTVBST1ZFTUVOVF9DT0RFajIKFklNUFJPVkVNRU5UX1NIT1JUX0RFU0MQBBoWSU1QUk9WRU1FTlRfU0hPUlRfREVTQ2okCg9UWVBfRlJTVF9BUFJfRFQQBRoPVFlQX0ZSU1RfQVBSX0RUaioKEk1BSk9SX1BST0pFQ1RfRkxBRxAEGhJNQUpPUl9QUk9KRUNUX0ZMQUdqIgoOVFJBTlNQT1JUX01PREUQBBoOVFJBTlNQT1JUX01PREVqPAobUExBTk5JTkdfUEFSVE5FUl9TSE9SVF9OQU1FEAQaG1BMQU5OSU5HX1BBUlRORVJfU0hPUlRfTkFNRWoyChdSRVNQT05TSUJMRV9ESVNUUklDVF9OTxoXUkVTUE9OU0lCTEVfRElTVFJJQ1RfTk9qJAoQUFJJTUFSWV9TVF9SVF9OTxoQUFJJTUFSWV9TVF9SVF9OT2osChNESVNUUklDVF9TRUNUSU9OX0lEEAQaE0RJU1RSSUNUX1NFQ1RJT05fSURqNgoZUFJJTUFSWV9MT0NBTF9ST0FEX05VTUJFUhoZUFJJTUFSWV9MT0NBTF9ST0FEX05VTUJFUmouChRQUk9KRUNUX1RPVEFMX0xFTkdUSBACGhRQUk9KRUNUX1RPVEFMX0xFTkdUSGoqChJMT0NBTF9QUk9KRUNUX0ZMQUcQBBoSTE9DQUxfUFJPSkVDVF9GTEFHajIKFkxFVF9SRVNQT05TSUJMRV9BR0VOQ1kQBBoWTEVUX1JFU1BPTlNJQkxFX0FHRU5DWWoyChZHRU9HUkFQSElDX0RFU0NSSVBUSU9OEAQaFkdFT0dSQVBISUNfREVTQ1JJUFRJT05qKgoSUFJPSkVDVF9TVEFURV9DT0RFEAQaElBST0pFQ1RfU1RBVEVfQ09ERWo2ChhQUk9KRUNUX1NUQVRVU19DT0RFX0RFU0MQBBoYUFJPSkVDVF9TVEFUVVNfQ09ERV9ERVNDahIKB0NPREVfSUQaB0NPREVfSURqQAodUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFX0ZMQUcQBBodUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFX0ZMQUdqNgoYUE9URU5USUFMX0NPTU1JVFRFRF9ZRUFSEAQaGFBPVEVOVElBTF9DT01NSVRURURfWUVBUmo2ChhQT1RFTlRJQUxfQ09NTUlUVEVEX0RBVEUQBBoYUE9URU5USUFMX0NPTU1JVFRFRF9EQVRFaj4KHEVTVF9DT05TVFJfUEhBU0VfQ09TVF9BTU9VTlQQAhocRVNUX0NPTlNUUl9QSEFTRV9DT1NUX0FNT1VOVGoWCghUWVBfRkxBRxAEGghUWVBfRkxBR2oWCghUSVBfRkxBRxAEGghUSVBfRkxBR2oYCglTVElQX0ZMQUcQBBoJU1RJUF9GTEFHajgKGURFQ0FERV9PRl9JTlZFU1RNRU5UX0ZMQUcQBBoZREVDQURFX09GX0lOVkVTVE1FTlRfRkxBR2ooChFUSVBfUFJPUE9TRURfRkxBRxAEGhFUSVBfUFJPUE9TRURfRkxBR2ooChFUWVBfUFJPUE9TRURfRkxBRxAEGhFUWVBfUFJPUE9TRURfRkxBR2ouChRPQkxJR0FUSU9OX1BMQU5fRkxBRxAEGhRPQkxJR0FUSU9OX1BMQU5fRkxBR2oWCghMRVRfRkxBRxAEGghMRVRfRkxBR2oWCghMRVRfREFURRAEGghMRVRfREFURWomChBMRVRfREFURV9ESVNQTEFZEAQaEExFVF9EQVRFX0RJU1BMQVlqGAoJT1BFTl9GTEFHEAQaCU9QRU5fRkxBR2oYCglPUEVOX0RBVEUQBBoJT1BFTl9EQVRFahYKCE5UUF9GTEFHEAQaCE5UUF9GTEFHahYKCE5UUF9EQVRFEAEaCE5UUF9EQVRFaiQKD0NPTVBMRVRJT05fRkxBRxAEGg9DT01QTEVUSU9OX0ZMQUdqJAoPQ09NUExFVElPTl9EQVRFEAQaD0NPTVBMRVRJT05fREFURWoiCg5GSVNDQUxMWV9SRUFEWRAEGg5GSVNDQUxMWV9SRUFEWWocCgtGSVNDQUxfREFURRAEGgtGSVNDQUxfREFURWomChBQSFlTSUNBTExZX1JFQURZEAQaEFBIWVNJQ0FMTFlfUkVBRFlqIAoNUEhZU0lDQUxfREFURRAEGg1QSFlTSUNBTF9EQVRFaj4KHFBST0pFQ1RfTUFOQUdFUl9DT05UQUNUX05BTUUQBBocUFJPSkVDVF9NQU5BR0VSX0NPTlRBQ1RfTkFNRWowChVQUk9KRUNUX01BTkFHRVJfUEhPTkUQBBoVUFJPSkVDVF9NQU5BR0VSX1BIT05FajAKFVBST0pFQ1RfTUFOQUdFUl9FTUFJTBAEGhVQUk9KRUNUX01BTkFHRVJfRU1BSUxqKgoSVU5ERVJfQ09OU1RSVUNUSU9OEAQaElVOREVSX0NPTlNUUlVDVElPTmoYCglDT01QTEVURUQQBBoJQ09NUExFVEVEaioKEkZVVFVSRV9ERVZFTE9QTUVOVBAEGhJGVVRVUkVfREVWRUxPUE1FTlRqIgoOSU5fREVWRUxPUE1FTlQQBBoOSU5fREVWRUxPUE1FTlRqIAoNUFJPSkVDVF9TVEFHRRAEGg1QUk9KRUNUX1NUQUdFajAKFVBST0pFQ1RfQ1JFQVRJT05fREFURRAFGhVQUk9KRUNUX0NSRUFUSU9OX0RBVEVqLAoTQ0FQSVRBTF9CVURHRVRfWUVBUhAEGhNDQVBJVEFMX0JVREdFVF9ZRUFSaj4KHENBUFRJQUxfQlVER0VUX1JFUVVJUkVEX0ZMQUcQBBocQ0FQVElBTF9CVURHRVRfUkVRVUlSRURfRkxBR2o+ChxDQVBJVEFMX0JVREdFVF9BUFBST1ZFRF9GTEFHEAQaHENBUElUQUxfQlVER0VUX0FQUFJPVkVEX0ZMQUdqMAoVUExBTk5JTkdfUEFSVE5FUl9OQU1FEAQaFVBMQU5OSU5HX1BBUlRORVJfTkFNRWo4ChlSRVNQT05TSUJMRV9ESVNUUklDVF9OQU1FEAQaGVJFU1BPTlNJQkxFX0RJU1RSSUNUX05BTUVqMgoXUkVTUE9OU0lCTEVfQ09VTlRZX0NPREUaF1JFU1BPTlNJQkxFX0NPVU5UWV9DT0RFajQKF1JFU1BPTlNJQkxFX0NPVU5UWV9OQU1FEAQaF1JFU1BPTlNJQkxFX0NPVU5UWV9OQU1Fai4KFFBST0pFQ1RfU1BPTlNPUl9OQU1FEAQaFFBST0pFQ1RfU1BPTlNPUl9OQU1FaiwKE1NEX0JSSURHRV9XT1JLX0ZMQUcQBBoTU0RfQlJJREdFX1dPUktfRkxBR2ouChRPUEVOX1RPX1RSQUZGSUNfREFURRAEGhRPUEVOX1RPX1RSQUZGSUNfREFURWo2ChhPUklHSU5BTF9DT05UUkFDVF9BTU9VTlQQBBoYT1JJR0lOQUxfQ09OVFJBQ1RfQU1PVU5UajQKF0NVUlJFTlRfQ09OVFJBQ1RfQU1PVU5UEAQaF0NVUlJFTlRfQ09OVFJBQ1RfQU1PVU5UaioKEkVTVElNQVRFRF9MRVRfREFURRAEGhJFU1RJTUFURURfTEVUX0RBVEVqFgoIRE9JX0RBVEUQBBoIRE9JX0RBVEVqEgoGRE9JX0lEEAQaBkRPSV9JRGoqChJQUklNQVJZX1BST0pFQ1RfSUQQARoSUFJJTUFSWV9QUk9KRUNUX0lEajQKF1BSSU1BUllfQ09OVFJBQ1RfQU1PVU5UEAQaF1BSSU1BUllfQ09OVFJBQ1RfQU1PVU5Uai4KFFBSSU1BUllfUFJPSkVDVF9GTEFHEAQaFFBSSU1BUllfUFJPSkVDVF9GTEFHajIKFkhBU19DT05TVFJVQ1RJT05fUEhBU0UQBBoWSEFTX0NPTlNUUlVDVElPTl9QSEFTRWoyChZIQVNfRklOQUxfREVTSUdOX1BIQVNFEAQaFkhBU19GSU5BTF9ERVNJR05fUEhBU0VqQgoeSEFTX1BSRUxJTUlOQVJZX0VOR0lORUVSX1BIQVNFEAQaHkhBU19QUkVMSU1JTkFSWV9FTkdJTkVFUl9QSEFTRWpACh1IQVNfUExBTl9SRVNFQVJDSF9BRE1JTl9QSEFTRRAEGh1IQVNfUExBTl9SRVNFQVJDSF9BRE1JTl9QSEFTRWoyChZIQVNfUklHSFRfT0ZfV0FZX1BIQVNFEAQaFkhBU19SSUdIVF9PRl9XQVlfUEhBU0VqJAoPSEFTX1NUVURZX1BIQVNFEAQaD0hBU19TVFVEWV9QSEFTRWooChFIQVNfVVRJTElUWV9QSEFTRRAEGhFIQVNfVVRJTElUWV9QSEFTRWoUCghDVFlfQ09ERRoIQ1RZX0NPREVqFAoIU1RfUlRfTk8aCFNUX1JUX05Pag4KBUpVUklTGgVKVVJJU2oaCgtESVNUUklDVF9OTxoLRElTVFJJQ1RfTk9qEgoHU0VHX0JHThoHU0VHX0JHTmoYCgpPRkZTRVRfQkdOGgpPRkZTRVRfQkdOahIKB1NFR19FTkQaB1NFR19FTkRqGAoKT0ZGU0VUX0VORBoKT0ZGU0VUX0VORGoaCgpTRUdfUFRfQkdOEAEaClNFR19QVF9CR05qGgoKU0VHX1BUX0VORBABGgpTRUdfUFRfRU5EaiIKDlNFR19MTkdUSF9GRUVUEAEaDlNFR19MTkdUSF9GRUVUahIKBk5MRl9JRBABGgZOTEZfSURqFAoIU0lERV9JTkQaCFNJREVfSU5Eah4KDE5MRl9DTlRMX0JHThABGgxOTEZfQ05UTF9CR05qHgoMTkxGX0NOVExfRU5EEAEaDE5MRl9DTlRMX0VORGoiCg5DVU1fT0ZGU0VUX0JHThABGg5DVU1fT0ZGU0VUX0JHTmoiCg5DVU1fT0ZGU0VUX0VORBABGg5DVU1fT0ZGU0VUX0VORGo4ChlDT1VOVFlfTVVOSUNJUEFMSVRZX0NPREVTEAQaGUNPVU5UWV9NVU5JQ0lQQUxJVFlfQ09ERVNqKgoSTVVOSUNJUEFMSVRZX0NPREVTEAQaEk1VTklDSVBBTElUWV9DT0RFU2oqChJNVU5JQ0lQQUxJVFlfTkFNRVMQBBoSTVVOSUNJUEFMSVRZX05BTUVTaiQKD0hPVVNFX0RJU1RSSUNUUxAEGg9IT1VTRV9ESVNUUklDVFNqJgoQU0VOQVRFX0RJU1RSSUNUUxAEGhBTRU5BVEVfRElTVFJJQ1RTaioKEkNPTkdSRVNTX0RJU1RSSUNUUxAEGhJDT05HUkVTU19ESVNUUklDVFNqMgoWSE9VU0VfTEVHSVNMQVRPUl9OQU1FUxAEGhZIT1VTRV9MRUdJU0xBVE9SX05BTUVTajQKF1NFTkFURV9MRUdJU0xBVE9SX05BTUVTEAQaF1NFTkFURV9MRUdJU0xBVE9SX05BTUVTajgKGUNPTkdSRVNTX0xFR0lTTEFUT1JfTkFNRVMQBBoZQ09OR1JFU1NfTEVHSVNMQVRPUl9OQU1FU2ocCgtDT1VOVFlfTkFNRRAEGgtDT1VOVFlfTkFNRWocCgtTVFJFRVRfTkFNRRAEGgtTVFJFRVRfTkFNRWomChBCUklER0VfV09SS19GTEFHEAQaEEJSSURHRV9XT1JLX0ZMQUdqIAoNUkVDT1JEX1VQREFURRABGg1SRUNPUkRfVVBEQVRFah4KDENSRUFURURfREFURRAFGgxDUkVBVEVEX0RBVEVqJgoQTEFTVF9FRElURURfREFURRAFGhBMQVNUX0VESVRFRF9EQVRFaiIKDkdFT01fTEVOR1RIX0ZUEAEaDkdFT01fTEVOR1RIX0ZUaiAKDUdFT01FVFJZX1RZUEUQBBoNR0VPTUVUUllfVFlQRWo4ChlCUklER0VfV09SS19MT0NBVElPTl9GTEFHEAQaGUJSSURHRV9XT1JLX0xPQ0FUSU9OX0ZMQUdqJgoQUFVCTElDX05BUlJBVElWRRAEGhBQVUJMSUNfTkFSUkFUSVZFaiQKD0dJU19VUERBVEVfREFURRAFGg9HSVNfVVBEQVRFX0RBVEVqNgoYR0lTX0dFT01FVFJZX1VQREFURV9EQVRFEAUaGEdJU19HRU9NRVRSWV9VUERBVEVfREFURWomChBTRV9BTk5PX0NBRF9EQVRBEAQaEFNFX0FOTk9fQ0FEX0RBVEFqDgoER1BJRBABGgRHUElEaisKCEdsb2JhbElEEAsaCEdsb2JhbElEMhNORVdJRCgpIFdJVEggVkFMVUVTeukLCgMoqAoKBiDsi8mhBwoEINjCDAobChlIaWdoIEZyaWN0aW9uIFN1cmZhY2VzKEYpCgYKBENBTkQKBgoEU0FGRQoUChJTYWZldHkgSW1wcm92ZW1lbnQKgAEKfkluc3RhbGxpbmcgaGlnaCBmcmljdGlvbiBzdXJmYWNlcyBvbiB0b3Agb2YgZXhpc3Rpbmcgcm9hZHdheSB0byBkZWNyZWFzZSB0aGUgbnVtYmVyIG9mIGNyYXNoZXMgYWxvbmcgaGlnaCBjcmFzaCByb2Fkd2F5IGN1cnZlcwpuCmxIaWdoIEZyaWN0aW9uIFN1cmZhY2VzICBWYXJpb3VzIGhpZ2gtY3Jhc2ggcm9hZHdheSBjdXJ2ZXMgaW4gRDYtMCAgVHJlYXRtbnQgdG8gcmVkdWNlIGNyYXNoZXMgb24gcmR3eSBjdXJ2ZXMKEwoRU3VyZmFjZSBUcmVhdG1lbnQKAiBKChMKEVN1cmZhY2UgVHJlYXRtZW50CgdAgNCHrr5RCgMKAU4KAwoBSAoHCgVEVlJQQwoCIAwKAyCyLwoFCgNIRlMKAiAACgUV16PYQAoDCgFOCgAKMwoxVmFyaW91cyBoaWdoLWNyYXNoIHJvYWR3YXkgY3VydmVzIGluIERpc3RyaWN0IDYtMAoGCgRDQU5ECgsKCUNhbmRpZGF0ZQoCIFYKAAoAChcKFTYvMTIvMjAxNCAxMjowMDowMCBBTQoFFSA7FUoKAwoBTgoDCgFOCgMKAU4KAwoBTgoDCgFOCgMKAU4KAwoBWQoDCgFBCgoKCDIwMTQwNzAzChYKFDcvMy8yMDE0IDEyOjAwOjAwIEFNCgAKAAoDCgFBCgUgpMyaEwoDCgFBCgoKCDIwMTUxMDA3CgAKAAoACgAKHQobR2VvcmdlIER1bmhlaW1lciBBREUgQ09OU1RSCgwKCjYxMDIwNTY2ODAKEwoRZ2R1bmhlaW1lckBwYS5nb3YKAwoBTgoDCgFZCgMKAU4KAwoBTgoLCglDT01QTEVURUQKB0CA4I+irlEKAAoDCgFZCgMKAU4KTQpLRGVsYXdhcmUgVmFsbGV5IFJlZ2lvbmFsIFBsYW5uaW5nIENvbW1pc3Npb24gTVBPICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAKHkRpc3RyaWN0IDYtMCAgICAgICAgICAgICAgICAgIAoCIB4KEAoOQ2hlc3RlciAgICAgICAKCQoHUGVubkRPVAoDCgFOCgAKAAoAChYKFDcvMy8yMDE0IDEyOjAwOjAwIEFNCgAKAAoEINjCDAoACgMKAVkKAwoBVAoDCgFGCgMKAUYKAwoBRgoDCgFGCgMKAUYKAwoBRgoDIIYBCgMgkn0KAiACCgIgDAoDIPQDCgIgAAoDIPQDCgMglC0KBSDAlrECCgUg1MOxAgoDIJQtCgQg9uIECgIgAgoCIAAKAyCULQoDIPxmCgQgkJQBCgcKBTY3MzAxCgUKAzMwMQoPCg1QSElMQURFTFBISUEgCgUKAzE3NQoDCgExChYKFDIvMy8yMDIyIDEyOjAwOjAwIEFNChoKGE1hcnlsb3Vpc2UgSXNhYWNzb24sIChEKQoSChBOaWtpbCBTYXZhbCwgKEQpCigKJkJyZW5kYW4gRi4gQm95bGUgKEQpLCBEd2lnaHQgRXZhbnMgKEQpCg4KDFBISUxBREVMUEhJQQoACgMKAU4KBSDCjaMTCgdA8Nb9/dVaCgdAkPzT8LZeCgMgwE0KBwoFUE9JTlQKAwoBTgpuCmxIaWdoIEZyaWN0aW9uIFN1cmZhY2VzDQpWYXJpb3VzIGhpZ2gtY3Jhc2ggcm9hZHdheSBjdXJ2ZXMgaW4gRDYtMA0KVHJlYXRtbnQgdG8gcmVkdWNlIGNyYXNoZXMgb24gcmR3eSBjdXJ2ZXMKB0CQiOrHqF0KB0CQvKWDnl8KAAoGIOyLyaEHCiYKJDg4YzlhMDA2LTRhZjQtNDdlYi1iZWE2LTU1M2E2MTMwNmNlZQ=="; public static phillyTansportationGetFeatureInfoResultRef = [ { @@ -109,8 +111,10 @@ export class PhillyLandmarksDataset { { value: { valueFormat: 0, - value: "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", - displayValue: "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", + value: + "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", + displayValue: + "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", }, property: { name: "PROJECT_IMPROVEMENT_DESC", @@ -1524,68 +1528,1600 @@ export class PhillyLandmarksDataset { }, ]; - public static phillyTransportationGetFeatureInfoQueryJson = { objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", serverGens: { minServerGen: 617056, serverGen: 705029 }, geometryType: "esriGeometryPoint", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [2.3886571335751796, 2.3886571335751796], translate: [-8365268.374365235, 4860172.005808106] }, fields: [{ name: "OBJECTID", type: "esriFieldTypeOID", alias: "OBJECTID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "GISDATAPROJECT_LOCATION_DETAIL_", type: "esriFieldTypeInteger", alias: "GISDATAPROJECT_LOCATION_DETAIL_PTFID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "PROJECT_ID", type: "esriFieldTypeInteger", alias: "PROJECT_ID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "PROJECT_TITLE", type: "esriFieldTypeString", alias: "PROJECT_TITLE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_STATUS", type: "esriFieldTypeString", alias: "PROJECT_STATUS", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_CLASS", type: "esriFieldTypeString", alias: "PROJECT_CLASS", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_CLASS_NAME", type: "esriFieldTypeString", alias: "PROJECT_CLASS_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_IMPROVEMENT_DESC", type: "esriFieldTypeString", alias: "PROJECT_IMPROVEMENT_DESC", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_SHORT_NARRATIVE", type: "esriFieldTypeString", alias: "PROJECT_SHORT_NARRATIVE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "IMPROVEMENT_TYPE", type: "esriFieldTypeString", alias: "IMPROVEMENT_TYPE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "IMPROVEMENT_CODE", type: "esriFieldTypeSmallInteger", alias: "IMPROVEMENT_CODE", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "IMPROVEMENT_SHORT_DESC", type: "esriFieldTypeString", alias: "IMPROVEMENT_SHORT_DESC", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "TYP_FRST_APR_DT", type: "esriFieldTypeDate", alias: "TYP_FRST_APR_DT", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "MAJOR_PROJECT_FLAG", type: "esriFieldTypeString", alias: "MAJOR_PROJECT_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "TRANSPORT_MODE", type: "esriFieldTypeString", alias: "TRANSPORT_MODE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PLANNING_PARTNER_SHORT_NAME", type: "esriFieldTypeString", alias: "PLANNING_PARTNER_SHORT_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "RESPONSIBLE_DISTRICT_NO", type: "esriFieldTypeSmallInteger", alias: "RESPONSIBLE_DISTRICT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "PRIMARY_ST_RT_NO", type: "esriFieldTypeSmallInteger", alias: "PRIMARY_ST_RT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "DISTRICT_SECTION_ID", type: "esriFieldTypeString", alias: "DISTRICT_SECTION_ID", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PRIMARY_LOCAL_ROAD_NUMBER", type: "esriFieldTypeSmallInteger", alias: "PRIMARY_LOCAL_ROAD_NUMBER", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "PROJECT_TOTAL_LENGTH", type: "esriFieldTypeSingle", alias: "PROJECT_TOTAL_LENGTH", sqlType: "sqlTypeReal", domain: null, defaultValue: null }, { name: "LOCAL_PROJECT_FLAG", type: "esriFieldTypeString", alias: "LOCAL_PROJECT_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "LET_RESPONSIBLE_AGENCY", type: "esriFieldTypeString", alias: "LET_RESPONSIBLE_AGENCY", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "GEOGRAPHIC_DESCRIPTION", type: "esriFieldTypeString", alias: "GEOGRAPHIC_DESCRIPTION", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_STATE_CODE", type: "esriFieldTypeString", alias: "PROJECT_STATE_CODE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_STATUS_CODE_DESC", type: "esriFieldTypeString", alias: "PROJECT_STATUS_CODE_DESC", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CODE_ID", type: "esriFieldTypeSmallInteger", alias: "CODE_ID", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "POTENTIAL_COMMITTED_DATE_FLAG", type: "esriFieldTypeString", alias: "POTENTIAL_COMMITTED_DATE_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "POTENTIAL_COMMITTED_YEAR", type: "esriFieldTypeString", alias: "POTENTIAL_COMMITTED_YEAR", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "POTENTIAL_COMMITTED_DATE", type: "esriFieldTypeString", alias: "POTENTIAL_COMMITTED_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "EST_CONSTR_PHASE_COST_AMOUNT", type: "esriFieldTypeSingle", alias: "EST_CONSTR_PHASE_COST_AMOUNT", sqlType: "sqlTypeReal", domain: null, defaultValue: null }, { name: "TYP_FLAG", type: "esriFieldTypeString", alias: "TYP_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "TIP_FLAG", type: "esriFieldTypeString", alias: "TIP_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "STIP_FLAG", type: "esriFieldTypeString", alias: "STIP_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "DECADE_OF_INVESTMENT_FLAG", type: "esriFieldTypeString", alias: "DECADE_OF_INVESTMENT_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "TIP_PROPOSED_FLAG", type: "esriFieldTypeString", alias: "TIP_PROPOSED_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "TYP_PROPOSED_FLAG", type: "esriFieldTypeString", alias: "TYP_PROPOSED_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "OBLIGATION_PLAN_FLAG", type: "esriFieldTypeString", alias: "OBLIGATION_PLAN_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "LET_FLAG", type: "esriFieldTypeString", alias: "LET_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "LET_DATE", type: "esriFieldTypeString", alias: "LET_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "LET_DATE_DISPLAY", type: "esriFieldTypeString", alias: "LET_DATE_DISPLAY", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "OPEN_FLAG", type: "esriFieldTypeString", alias: "OPEN_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "OPEN_DATE", type: "esriFieldTypeString", alias: "OPEN_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "NTP_FLAG", type: "esriFieldTypeString", alias: "NTP_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "NTP_DATE", type: "esriFieldTypeInteger", alias: "NTP_DATE", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "COMPLETION_FLAG", type: "esriFieldTypeString", alias: "COMPLETION_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "COMPLETION_DATE", type: "esriFieldTypeString", alias: "COMPLETION_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "FISCALLY_READY", type: "esriFieldTypeString", alias: "FISCALLY_READY", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "FISCAL_DATE", type: "esriFieldTypeString", alias: "FISCAL_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PHYSICALLY_READY", type: "esriFieldTypeString", alias: "PHYSICALLY_READY", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PHYSICAL_DATE", type: "esriFieldTypeString", alias: "PHYSICAL_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_MANAGER_CONTACT_NAME", type: "esriFieldTypeString", alias: "PROJECT_MANAGER_CONTACT_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_MANAGER_PHONE", type: "esriFieldTypeString", alias: "PROJECT_MANAGER_PHONE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_MANAGER_EMAIL", type: "esriFieldTypeString", alias: "PROJECT_MANAGER_EMAIL", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "UNDER_CONSTRUCTION", type: "esriFieldTypeString", alias: "UNDER_CONSTRUCTION", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "COMPLETED", type: "esriFieldTypeString", alias: "COMPLETED", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "FUTURE_DEVELOPMENT", type: "esriFieldTypeString", alias: "FUTURE_DEVELOPMENT", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "IN_DEVELOPMENT", type: "esriFieldTypeString", alias: "IN_DEVELOPMENT", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_STAGE", type: "esriFieldTypeString", alias: "PROJECT_STAGE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_CREATION_DATE", type: "esriFieldTypeDate", alias: "PROJECT_CREATION_DATE", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "CAPITAL_BUDGET_YEAR", type: "esriFieldTypeString", alias: "CAPITAL_BUDGET_YEAR", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CAPTIAL_BUDGET_REQUIRED_FLAG", type: "esriFieldTypeString", alias: "CAPTIAL_BUDGET_REQUIRED_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CAPITAL_BUDGET_APPROVED_FLAG", type: "esriFieldTypeString", alias: "CAPITAL_BUDGET_APPROVED_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PLANNING_PARTNER_NAME", type: "esriFieldTypeString", alias: "PLANNING_PARTNER_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "RESPONSIBLE_DISTRICT_NAME", type: "esriFieldTypeString", alias: "RESPONSIBLE_DISTRICT_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "RESPONSIBLE_COUNTY_CODE", type: "esriFieldTypeSmallInteger", alias: "RESPONSIBLE_COUNTY_CODE", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "RESPONSIBLE_COUNTY_NAME", type: "esriFieldTypeString", alias: "RESPONSIBLE_COUNTY_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PROJECT_SPONSOR_NAME", type: "esriFieldTypeString", alias: "PROJECT_SPONSOR_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "SD_BRIDGE_WORK_FLAG", type: "esriFieldTypeString", alias: "SD_BRIDGE_WORK_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "OPEN_TO_TRAFFIC_DATE", type: "esriFieldTypeString", alias: "OPEN_TO_TRAFFIC_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "ORIGINAL_CONTRACT_AMOUNT", type: "esriFieldTypeString", alias: "ORIGINAL_CONTRACT_AMOUNT", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CURRENT_CONTRACT_AMOUNT", type: "esriFieldTypeString", alias: "CURRENT_CONTRACT_AMOUNT", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "ESTIMATED_LET_DATE", type: "esriFieldTypeString", alias: "ESTIMATED_LET_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "DOI_DATE", type: "esriFieldTypeString", alias: "DOI_DATE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "DOI_ID", type: "esriFieldTypeString", alias: "DOI_ID", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PRIMARY_PROJECT_ID", type: "esriFieldTypeInteger", alias: "PRIMARY_PROJECT_ID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "PRIMARY_CONTRACT_AMOUNT", type: "esriFieldTypeString", alias: "PRIMARY_CONTRACT_AMOUNT", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PRIMARY_PROJECT_FLAG", type: "esriFieldTypeString", alias: "PRIMARY_PROJECT_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_CONSTRUCTION_PHASE", type: "esriFieldTypeString", alias: "HAS_CONSTRUCTION_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_FINAL_DESIGN_PHASE", type: "esriFieldTypeString", alias: "HAS_FINAL_DESIGN_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_PRELIMINARY_ENGINEER_PHASE", type: "esriFieldTypeString", alias: "HAS_PRELIMINARY_ENGINEER_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_PLAN_RESEARCH_ADMIN_PHASE", type: "esriFieldTypeString", alias: "HAS_PLAN_RESEARCH_ADMIN_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_RIGHT_OF_WAY_PHASE", type: "esriFieldTypeString", alias: "HAS_RIGHT_OF_WAY_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_STUDY_PHASE", type: "esriFieldTypeString", alias: "HAS_STUDY_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HAS_UTILITY_PHASE", type: "esriFieldTypeString", alias: "HAS_UTILITY_PHASE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CTY_CODE", type: "esriFieldTypeSmallInteger", alias: "CTY_CODE", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "ST_RT_NO", type: "esriFieldTypeSmallInteger", alias: "ST_RT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "JURIS", type: "esriFieldTypeSmallInteger", alias: "JURIS", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "DISTRICT_NO", type: "esriFieldTypeSmallInteger", alias: "DISTRICT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "SEG_BGN", type: "esriFieldTypeSmallInteger", alias: "SEG_BGN", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "OFFSET_BGN", type: "esriFieldTypeSmallInteger", alias: "OFFSET_BGN", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "SEG_END", type: "esriFieldTypeSmallInteger", alias: "SEG_END", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "OFFSET_END", type: "esriFieldTypeSmallInteger", alias: "OFFSET_END", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "SEG_PT_BGN", type: "esriFieldTypeInteger", alias: "SEG_PT_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "SEG_PT_END", type: "esriFieldTypeInteger", alias: "SEG_PT_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "SEG_LNGTH_FEET", type: "esriFieldTypeInteger", alias: "SEG_LNGTH_FEET", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "NLF_ID", type: "esriFieldTypeInteger", alias: "NLF_ID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "SIDE_IND", type: "esriFieldTypeSmallInteger", alias: "SIDE_IND", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, { name: "NLF_CNTL_BGN", type: "esriFieldTypeInteger", alias: "NLF_CNTL_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "NLF_CNTL_END", type: "esriFieldTypeInteger", alias: "NLF_CNTL_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "CUM_OFFSET_BGN", type: "esriFieldTypeInteger", alias: "CUM_OFFSET_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "CUM_OFFSET_END", type: "esriFieldTypeInteger", alias: "CUM_OFFSET_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "COUNTY_MUNICIPALITY_CODES", type: "esriFieldTypeString", alias: "COUNTY_MUNICIPALITY_CODES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "MUNICIPALITY_CODES", type: "esriFieldTypeString", alias: "MUNICIPALITY_CODES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "MUNICIPALITY_NAMES", type: "esriFieldTypeString", alias: "MUNICIPALITY_NAMES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HOUSE_DISTRICTS", type: "esriFieldTypeString", alias: "HOUSE_DISTRICTS", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "SENATE_DISTRICTS", type: "esriFieldTypeString", alias: "SENATE_DISTRICTS", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CONGRESS_DISTRICTS", type: "esriFieldTypeString", alias: "CONGRESS_DISTRICTS", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "HOUSE_LEGISLATOR_NAMES", type: "esriFieldTypeString", alias: "HOUSE_LEGISLATOR_NAMES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "SENATE_LEGISLATOR_NAMES", type: "esriFieldTypeString", alias: "SENATE_LEGISLATOR_NAMES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "CONGRESS_LEGISLATOR_NAMES", type: "esriFieldTypeString", alias: "CONGRESS_LEGISLATOR_NAMES", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "COUNTY_NAME", type: "esriFieldTypeString", alias: "COUNTY_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "STREET_NAME", type: "esriFieldTypeString", alias: "STREET_NAME", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "BRIDGE_WORK_FLAG", type: "esriFieldTypeString", alias: "BRIDGE_WORK_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "RECORD_UPDATE", type: "esriFieldTypeInteger", alias: "RECORD_UPDATE", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "CREATED_DATE", type: "esriFieldTypeDate", alias: "CREATED_DATE", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "LAST_EDITED_DATE", type: "esriFieldTypeDate", alias: "LAST_EDITED_DATE", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "GEOM_LENGTH_FT", type: "esriFieldTypeInteger", alias: "GEOM_LENGTH_FT", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "GEOMETRY_TYPE", type: "esriFieldTypeString", alias: "GEOMETRY_TYPE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "BRIDGE_WORK_LOCATION_FLAG", type: "esriFieldTypeString", alias: "BRIDGE_WORK_LOCATION_FLAG", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "PUBLIC_NARRATIVE", type: "esriFieldTypeString", alias: "PUBLIC_NARRATIVE", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "GIS_UPDATE_DATE", type: "esriFieldTypeDate", alias: "GIS_UPDATE_DATE", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "GIS_GEOMETRY_UPDATE_DATE", type: "esriFieldTypeDate", alias: "GIS_GEOMETRY_UPDATE_DATE", sqlType: "sqlTypeTimestamp2", length: 8, domain: null, defaultValue: null }, { name: "SE_ANNO_CAD_DATA", type: "esriFieldTypeString", alias: "SE_ANNO_CAD_DATA", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, { name: "GPID", type: "esriFieldTypeInteger", alias: "GPID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, { name: "GlobalID", type: "esriFieldTypeGlobalID", alias: "GlobalID", sqlType: "sqlTypeOther", length: 38, domain: null }], features: [{ attributes: { OBJECTID: 1320, GISDATAPROJECT_LOCATION_DETAIL_: 974725878, PROJECT_ID: 102572, PROJECT_TITLE: "High Friction Surfaces(F)", PROJECT_STATUS: "CAND", PROJECT_CLASS: "SAFE", PROJECT_CLASS_NAME: "Safety Improvement", PROJECT_IMPROVEMENT_DESC: "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", PROJECT_SHORT_NARRATIVE: "High Friction Surfaces Various high-crash roadway curves in D6-0 Treatmnt to reduce crashes on rdwy curves", IMPROVEMENT_TYPE: "Surface Treatment", IMPROVEMENT_CODE: 37, IMPROVEMENT_SHORT_DESC: "Surface Treatment", TYP_FRST_APR_DT: 1399939200000, MAJOR_PROJECT_FLAG: "N", TRANSPORT_MODE: "H", PLANNING_PARTNER_SHORT_NAME: "DVRPC", RESPONSIBLE_DISTRICT_NO: 6, PRIMARY_ST_RT_NO: 3033, DISTRICT_SECTION_ID: "HFS", PRIMARY_LOCAL_ROAD_NUMBER: 0, PROJECT_TOTAL_LENGTH: 6.77, LOCAL_PROJECT_FLAG: "N", LET_RESPONSIBLE_AGENCY: null, GEOGRAPHIC_DESCRIPTION: "Various high-crash roadway curves in District 6-0", PROJECT_STATE_CODE: "CAND", PROJECT_STATUS_CODE_DESC: "Candidate", CODE_ID: 43, POTENTIAL_COMMITTED_DATE_FLAG: null, POTENTIAL_COMMITTED_YEAR: null, POTENTIAL_COMMITTED_DATE: "6/12/2014 12:00:00 AM", EST_CONSTR_PHASE_COST_AMOUNT: 2445000, TYP_FLAG: "N", TIP_FLAG: "N", STIP_FLAG: "N", DECADE_OF_INVESTMENT_FLAG: "N", TIP_PROPOSED_FLAG: "N", TYP_PROPOSED_FLAG: "N", OBLIGATION_PLAN_FLAG: "Y", LET_FLAG: "A", LET_DATE: "20140703", LET_DATE_DISPLAY: "7/3/2014 12:00:00 AM", OPEN_FLAG: null, OPEN_DATE: null, NTP_FLAG: "A", NTP_DATE: 20140818, COMPLETION_FLAG: "A", COMPLETION_DATE: "20151007", FISCALLY_READY: null, FISCAL_DATE: null, PHYSICALLY_READY: null, PHYSICAL_DATE: null, PROJECT_MANAGER_CONTACT_NAME: "George Dunheimer ADE CONSTR", PROJECT_MANAGER_PHONE: "6102056680", PROJECT_MANAGER_EMAIL: "gdunheimer@pa.gov", UNDER_CONSTRUCTION: "N", COMPLETED: "Y", FUTURE_DEVELOPMENT: "N", IN_DEVELOPMENT: "N", PROJECT_STAGE: "COMPLETED", PROJECT_CREATION_DATE: 1397779200000, CAPITAL_BUDGET_YEAR: null, CAPTIAL_BUDGET_REQUIRED_FLAG: "Y", CAPITAL_BUDGET_APPROVED_FLAG: "N", PLANNING_PARTNER_NAME: "Delaware Valley Regional Planning Commission MPO ", RESPONSIBLE_DISTRICT_NAME: "District 6-0 ", RESPONSIBLE_COUNTY_CODE: 15, RESPONSIBLE_COUNTY_NAME: "Chester ", PROJECT_SPONSOR_NAME: "PennDOT", SD_BRIDGE_WORK_FLAG: "N", OPEN_TO_TRAFFIC_DATE: null, ORIGINAL_CONTRACT_AMOUNT: null, CURRENT_CONTRACT_AMOUNT: null, ESTIMATED_LET_DATE: "7/3/2014 12:00:00 AM", DOI_DATE: null, DOI_ID: null, PRIMARY_PROJECT_ID: 102572, PRIMARY_CONTRACT_AMOUNT: null, PRIMARY_PROJECT_FLAG: "Y", HAS_CONSTRUCTION_PHASE: "T", HAS_FINAL_DESIGN_PHASE: "F", HAS_PRELIMINARY_ENGINEER_PHASE: "F", HAS_PLAN_RESEARCH_ADMIN_PHASE: "F", HAS_RIGHT_OF_WAY_PHASE: "F", HAS_STUDY_PHASE: "F", HAS_UTILITY_PHASE: "F", CTY_CODE: 67, ST_RT_NO: 8009, JURIS: 1, DISTRICT_NO: 6, SEG_BGN: 250, OFFSET_BGN: 0, SEG_END: 250, OFFSET_END: 2890, SEG_PT_BGN: 2500000, SEG_PT_END: 2502890, SEG_LNGTH_FEET: 2890, NLF_ID: 39099, SIDE_IND: 1, NLF_CNTL_BGN: 0, NLF_CNTL_END: 2890, CUM_OFFSET_BGN: 6590, CUM_OFFSET_END: 9480, COUNTY_MUNICIPALITY_CODES: "67301", MUNICIPALITY_CODES: "301", MUNICIPALITY_NAMES: "PHILADELPHIA ", HOUSE_DISTRICTS: "175", SENATE_DISTRICTS: "1", CONGRESS_DISTRICTS: "2/3/2022 12:00:00 AM", HOUSE_LEGISLATOR_NAMES: "Marylouise Isaacson, (D)", SENATE_LEGISLATOR_NAMES: "Nikil Saval, (D)", CONGRESS_LEGISLATOR_NAMES: "Brendan F. Boyle (D), Dwight Evans (D)", COUNTY_NAME: "PHILADELPHIA", STREET_NAME: null, BRIDGE_WORK_FLAG: "N", RECORD_UPDATE: 20210529, CREATED_DATE: 1557728835000, LAST_EDITED_DATE: 1622273589000, GEOM_LENGTH_FT: 4960, GEOMETRY_TYPE: "POINT", BRIDGE_WORK_LOCATION_FLAG: "N", PUBLIC_NARRATIVE: "High Friction Surfaces\r\nVarious high-crash roadway curves in D6-0\r\nTreatmnt to reduce crashes on rdwy curves", GIS_UPDATE_DATE: 1603171861000, GIS_GEOMETRY_UPDATE_DATE: 1636117557000, SE_ANNO_CAD_DATA: null, GPID: 974725878, GlobalID: "88c9a006-4af4-47eb-bea6-553a61306cee" } }] }; + public static phillyTransportationGetFeatureInfoQueryJson = { + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + serverGens: { minServerGen: 617056, serverGen: 705029 }, + geometryType: "esriGeometryPoint", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [2.3886571335751796, 2.3886571335751796], translate: [-8365268.374365235, 4860172.005808106] }, + fields: [ + { name: "OBJECTID", type: "esriFieldTypeOID", alias: "OBJECTID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "GISDATAPROJECT_LOCATION_DETAIL_", + type: "esriFieldTypeInteger", + alias: "GISDATAPROJECT_LOCATION_DETAIL_PTFID", + sqlType: "sqlTypeInteger", + domain: null, + defaultValue: null, + }, + { name: "PROJECT_ID", type: "esriFieldTypeInteger", alias: "PROJECT_ID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "PROJECT_TITLE", + type: "esriFieldTypeString", + alias: "PROJECT_TITLE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_STATUS", + type: "esriFieldTypeString", + alias: "PROJECT_STATUS", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_CLASS", + type: "esriFieldTypeString", + alias: "PROJECT_CLASS", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_CLASS_NAME", + type: "esriFieldTypeString", + alias: "PROJECT_CLASS_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_IMPROVEMENT_DESC", + type: "esriFieldTypeString", + alias: "PROJECT_IMPROVEMENT_DESC", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_SHORT_NARRATIVE", + type: "esriFieldTypeString", + alias: "PROJECT_SHORT_NARRATIVE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "IMPROVEMENT_TYPE", + type: "esriFieldTypeString", + alias: "IMPROVEMENT_TYPE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "IMPROVEMENT_CODE", + type: "esriFieldTypeSmallInteger", + alias: "IMPROVEMENT_CODE", + sqlType: "sqlTypeSmallInt", + domain: null, + defaultValue: null, + }, + { + name: "IMPROVEMENT_SHORT_DESC", + type: "esriFieldTypeString", + alias: "IMPROVEMENT_SHORT_DESC", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "TYP_FRST_APR_DT", + type: "esriFieldTypeDate", + alias: "TYP_FRST_APR_DT", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { + name: "MAJOR_PROJECT_FLAG", + type: "esriFieldTypeString", + alias: "MAJOR_PROJECT_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "TRANSPORT_MODE", + type: "esriFieldTypeString", + alias: "TRANSPORT_MODE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PLANNING_PARTNER_SHORT_NAME", + type: "esriFieldTypeString", + alias: "PLANNING_PARTNER_SHORT_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "RESPONSIBLE_DISTRICT_NO", + type: "esriFieldTypeSmallInteger", + alias: "RESPONSIBLE_DISTRICT_NO", + sqlType: "sqlTypeSmallInt", + domain: null, + defaultValue: null, + }, + { + name: "PRIMARY_ST_RT_NO", + type: "esriFieldTypeSmallInteger", + alias: "PRIMARY_ST_RT_NO", + sqlType: "sqlTypeSmallInt", + domain: null, + defaultValue: null, + }, + { + name: "DISTRICT_SECTION_ID", + type: "esriFieldTypeString", + alias: "DISTRICT_SECTION_ID", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PRIMARY_LOCAL_ROAD_NUMBER", + type: "esriFieldTypeSmallInteger", + alias: "PRIMARY_LOCAL_ROAD_NUMBER", + sqlType: "sqlTypeSmallInt", + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_TOTAL_LENGTH", + type: "esriFieldTypeSingle", + alias: "PROJECT_TOTAL_LENGTH", + sqlType: "sqlTypeReal", + domain: null, + defaultValue: null, + }, + { + name: "LOCAL_PROJECT_FLAG", + type: "esriFieldTypeString", + alias: "LOCAL_PROJECT_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "LET_RESPONSIBLE_AGENCY", + type: "esriFieldTypeString", + alias: "LET_RESPONSIBLE_AGENCY", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "GEOGRAPHIC_DESCRIPTION", + type: "esriFieldTypeString", + alias: "GEOGRAPHIC_DESCRIPTION", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_STATE_CODE", + type: "esriFieldTypeString", + alias: "PROJECT_STATE_CODE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_STATUS_CODE_DESC", + type: "esriFieldTypeString", + alias: "PROJECT_STATUS_CODE_DESC", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "CODE_ID", type: "esriFieldTypeSmallInteger", alias: "CODE_ID", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { + name: "POTENTIAL_COMMITTED_DATE_FLAG", + type: "esriFieldTypeString", + alias: "POTENTIAL_COMMITTED_DATE_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "POTENTIAL_COMMITTED_YEAR", + type: "esriFieldTypeString", + alias: "POTENTIAL_COMMITTED_YEAR", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "POTENTIAL_COMMITTED_DATE", + type: "esriFieldTypeString", + alias: "POTENTIAL_COMMITTED_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "EST_CONSTR_PHASE_COST_AMOUNT", + type: "esriFieldTypeSingle", + alias: "EST_CONSTR_PHASE_COST_AMOUNT", + sqlType: "sqlTypeReal", + domain: null, + defaultValue: null, + }, + { + name: "TYP_FLAG", + type: "esriFieldTypeString", + alias: "TYP_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "TIP_FLAG", + type: "esriFieldTypeString", + alias: "TIP_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "STIP_FLAG", + type: "esriFieldTypeString", + alias: "STIP_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "DECADE_OF_INVESTMENT_FLAG", + type: "esriFieldTypeString", + alias: "DECADE_OF_INVESTMENT_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "TIP_PROPOSED_FLAG", + type: "esriFieldTypeString", + alias: "TIP_PROPOSED_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "TYP_PROPOSED_FLAG", + type: "esriFieldTypeString", + alias: "TYP_PROPOSED_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "OBLIGATION_PLAN_FLAG", + type: "esriFieldTypeString", + alias: "OBLIGATION_PLAN_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "LET_FLAG", + type: "esriFieldTypeString", + alias: "LET_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "LET_DATE", + type: "esriFieldTypeString", + alias: "LET_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "LET_DATE_DISPLAY", + type: "esriFieldTypeString", + alias: "LET_DATE_DISPLAY", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "OPEN_FLAG", + type: "esriFieldTypeString", + alias: "OPEN_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "OPEN_DATE", + type: "esriFieldTypeString", + alias: "OPEN_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "NTP_FLAG", + type: "esriFieldTypeString", + alias: "NTP_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "NTP_DATE", type: "esriFieldTypeInteger", alias: "NTP_DATE", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "COMPLETION_FLAG", + type: "esriFieldTypeString", + alias: "COMPLETION_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "COMPLETION_DATE", + type: "esriFieldTypeString", + alias: "COMPLETION_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "FISCALLY_READY", + type: "esriFieldTypeString", + alias: "FISCALLY_READY", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "FISCAL_DATE", + type: "esriFieldTypeString", + alias: "FISCAL_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PHYSICALLY_READY", + type: "esriFieldTypeString", + alias: "PHYSICALLY_READY", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PHYSICAL_DATE", + type: "esriFieldTypeString", + alias: "PHYSICAL_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_MANAGER_CONTACT_NAME", + type: "esriFieldTypeString", + alias: "PROJECT_MANAGER_CONTACT_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_MANAGER_PHONE", + type: "esriFieldTypeString", + alias: "PROJECT_MANAGER_PHONE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_MANAGER_EMAIL", + type: "esriFieldTypeString", + alias: "PROJECT_MANAGER_EMAIL", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "UNDER_CONSTRUCTION", + type: "esriFieldTypeString", + alias: "UNDER_CONSTRUCTION", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "COMPLETED", + type: "esriFieldTypeString", + alias: "COMPLETED", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "FUTURE_DEVELOPMENT", + type: "esriFieldTypeString", + alias: "FUTURE_DEVELOPMENT", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "IN_DEVELOPMENT", + type: "esriFieldTypeString", + alias: "IN_DEVELOPMENT", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_STAGE", + type: "esriFieldTypeString", + alias: "PROJECT_STAGE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_CREATION_DATE", + type: "esriFieldTypeDate", + alias: "PROJECT_CREATION_DATE", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { + name: "CAPITAL_BUDGET_YEAR", + type: "esriFieldTypeString", + alias: "CAPITAL_BUDGET_YEAR", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "CAPTIAL_BUDGET_REQUIRED_FLAG", + type: "esriFieldTypeString", + alias: "CAPTIAL_BUDGET_REQUIRED_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "CAPITAL_BUDGET_APPROVED_FLAG", + type: "esriFieldTypeString", + alias: "CAPITAL_BUDGET_APPROVED_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PLANNING_PARTNER_NAME", + type: "esriFieldTypeString", + alias: "PLANNING_PARTNER_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "RESPONSIBLE_DISTRICT_NAME", + type: "esriFieldTypeString", + alias: "RESPONSIBLE_DISTRICT_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "RESPONSIBLE_COUNTY_CODE", + type: "esriFieldTypeSmallInteger", + alias: "RESPONSIBLE_COUNTY_CODE", + sqlType: "sqlTypeSmallInt", + domain: null, + defaultValue: null, + }, + { + name: "RESPONSIBLE_COUNTY_NAME", + type: "esriFieldTypeString", + alias: "RESPONSIBLE_COUNTY_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PROJECT_SPONSOR_NAME", + type: "esriFieldTypeString", + alias: "PROJECT_SPONSOR_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "SD_BRIDGE_WORK_FLAG", + type: "esriFieldTypeString", + alias: "SD_BRIDGE_WORK_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "OPEN_TO_TRAFFIC_DATE", + type: "esriFieldTypeString", + alias: "OPEN_TO_TRAFFIC_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "ORIGINAL_CONTRACT_AMOUNT", + type: "esriFieldTypeString", + alias: "ORIGINAL_CONTRACT_AMOUNT", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "CURRENT_CONTRACT_AMOUNT", + type: "esriFieldTypeString", + alias: "CURRENT_CONTRACT_AMOUNT", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "ESTIMATED_LET_DATE", + type: "esriFieldTypeString", + alias: "ESTIMATED_LET_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "DOI_DATE", + type: "esriFieldTypeString", + alias: "DOI_DATE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "DOI_ID", type: "esriFieldTypeString", alias: "DOI_ID", sqlType: "sqlTypeNVarchar", length: 4000, domain: null, defaultValue: null }, + { + name: "PRIMARY_PROJECT_ID", + type: "esriFieldTypeInteger", + alias: "PRIMARY_PROJECT_ID", + sqlType: "sqlTypeInteger", + domain: null, + defaultValue: null, + }, + { + name: "PRIMARY_CONTRACT_AMOUNT", + type: "esriFieldTypeString", + alias: "PRIMARY_CONTRACT_AMOUNT", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PRIMARY_PROJECT_FLAG", + type: "esriFieldTypeString", + alias: "PRIMARY_PROJECT_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_CONSTRUCTION_PHASE", + type: "esriFieldTypeString", + alias: "HAS_CONSTRUCTION_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_FINAL_DESIGN_PHASE", + type: "esriFieldTypeString", + alias: "HAS_FINAL_DESIGN_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_PRELIMINARY_ENGINEER_PHASE", + type: "esriFieldTypeString", + alias: "HAS_PRELIMINARY_ENGINEER_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_PLAN_RESEARCH_ADMIN_PHASE", + type: "esriFieldTypeString", + alias: "HAS_PLAN_RESEARCH_ADMIN_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_RIGHT_OF_WAY_PHASE", + type: "esriFieldTypeString", + alias: "HAS_RIGHT_OF_WAY_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_STUDY_PHASE", + type: "esriFieldTypeString", + alias: "HAS_STUDY_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HAS_UTILITY_PHASE", + type: "esriFieldTypeString", + alias: "HAS_UTILITY_PHASE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "CTY_CODE", type: "esriFieldTypeSmallInteger", alias: "CTY_CODE", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "ST_RT_NO", type: "esriFieldTypeSmallInteger", alias: "ST_RT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "JURIS", type: "esriFieldTypeSmallInteger", alias: "JURIS", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "DISTRICT_NO", type: "esriFieldTypeSmallInteger", alias: "DISTRICT_NO", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "SEG_BGN", type: "esriFieldTypeSmallInteger", alias: "SEG_BGN", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "OFFSET_BGN", type: "esriFieldTypeSmallInteger", alias: "OFFSET_BGN", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "SEG_END", type: "esriFieldTypeSmallInteger", alias: "SEG_END", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "OFFSET_END", type: "esriFieldTypeSmallInteger", alias: "OFFSET_END", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "SEG_PT_BGN", type: "esriFieldTypeInteger", alias: "SEG_PT_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "SEG_PT_END", type: "esriFieldTypeInteger", alias: "SEG_PT_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "SEG_LNGTH_FEET", type: "esriFieldTypeInteger", alias: "SEG_LNGTH_FEET", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "NLF_ID", type: "esriFieldTypeInteger", alias: "NLF_ID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "SIDE_IND", type: "esriFieldTypeSmallInteger", alias: "SIDE_IND", sqlType: "sqlTypeSmallInt", domain: null, defaultValue: null }, + { name: "NLF_CNTL_BGN", type: "esriFieldTypeInteger", alias: "NLF_CNTL_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "NLF_CNTL_END", type: "esriFieldTypeInteger", alias: "NLF_CNTL_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "CUM_OFFSET_BGN", type: "esriFieldTypeInteger", alias: "CUM_OFFSET_BGN", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "CUM_OFFSET_END", type: "esriFieldTypeInteger", alias: "CUM_OFFSET_END", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "COUNTY_MUNICIPALITY_CODES", + type: "esriFieldTypeString", + alias: "COUNTY_MUNICIPALITY_CODES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "MUNICIPALITY_CODES", + type: "esriFieldTypeString", + alias: "MUNICIPALITY_CODES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "MUNICIPALITY_NAMES", + type: "esriFieldTypeString", + alias: "MUNICIPALITY_NAMES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HOUSE_DISTRICTS", + type: "esriFieldTypeString", + alias: "HOUSE_DISTRICTS", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "SENATE_DISTRICTS", + type: "esriFieldTypeString", + alias: "SENATE_DISTRICTS", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "CONGRESS_DISTRICTS", + type: "esriFieldTypeString", + alias: "CONGRESS_DISTRICTS", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "HOUSE_LEGISLATOR_NAMES", + type: "esriFieldTypeString", + alias: "HOUSE_LEGISLATOR_NAMES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "SENATE_LEGISLATOR_NAMES", + type: "esriFieldTypeString", + alias: "SENATE_LEGISLATOR_NAMES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "CONGRESS_LEGISLATOR_NAMES", + type: "esriFieldTypeString", + alias: "CONGRESS_LEGISLATOR_NAMES", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "COUNTY_NAME", + type: "esriFieldTypeString", + alias: "COUNTY_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "STREET_NAME", + type: "esriFieldTypeString", + alias: "STREET_NAME", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "BRIDGE_WORK_FLAG", + type: "esriFieldTypeString", + alias: "BRIDGE_WORK_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "RECORD_UPDATE", type: "esriFieldTypeInteger", alias: "RECORD_UPDATE", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "CREATED_DATE", + type: "esriFieldTypeDate", + alias: "CREATED_DATE", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { + name: "LAST_EDITED_DATE", + type: "esriFieldTypeDate", + alias: "LAST_EDITED_DATE", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { name: "GEOM_LENGTH_FT", type: "esriFieldTypeInteger", alias: "GEOM_LENGTH_FT", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { + name: "GEOMETRY_TYPE", + type: "esriFieldTypeString", + alias: "GEOMETRY_TYPE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "BRIDGE_WORK_LOCATION_FLAG", + type: "esriFieldTypeString", + alias: "BRIDGE_WORK_LOCATION_FLAG", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "PUBLIC_NARRATIVE", + type: "esriFieldTypeString", + alias: "PUBLIC_NARRATIVE", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { + name: "GIS_UPDATE_DATE", + type: "esriFieldTypeDate", + alias: "GIS_UPDATE_DATE", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { + name: "GIS_GEOMETRY_UPDATE_DATE", + type: "esriFieldTypeDate", + alias: "GIS_GEOMETRY_UPDATE_DATE", + sqlType: "sqlTypeTimestamp2", + length: 8, + domain: null, + defaultValue: null, + }, + { + name: "SE_ANNO_CAD_DATA", + type: "esriFieldTypeString", + alias: "SE_ANNO_CAD_DATA", + sqlType: "sqlTypeNVarchar", + length: 4000, + domain: null, + defaultValue: null, + }, + { name: "GPID", type: "esriFieldTypeInteger", alias: "GPID", sqlType: "sqlTypeInteger", domain: null, defaultValue: null }, + { name: "GlobalID", type: "esriFieldTypeGlobalID", alias: "GlobalID", sqlType: "sqlTypeOther", length: 38, domain: null }, + ], + features: [{ + attributes: { + OBJECTID: 1320, + GISDATAPROJECT_LOCATION_DETAIL_: 974725878, + PROJECT_ID: 102572, + PROJECT_TITLE: "High Friction Surfaces(F)", + PROJECT_STATUS: "CAND", + PROJECT_CLASS: "SAFE", + PROJECT_CLASS_NAME: "Safety Improvement", + PROJECT_IMPROVEMENT_DESC: + "Installing high friction surfaces on top of existing roadway to decrease the number of crashes along high crash roadway curves", + PROJECT_SHORT_NARRATIVE: "High Friction Surfaces Various high-crash roadway curves in D6-0 Treatmnt to reduce crashes on rdwy curves", + IMPROVEMENT_TYPE: "Surface Treatment", + IMPROVEMENT_CODE: 37, + IMPROVEMENT_SHORT_DESC: "Surface Treatment", + TYP_FRST_APR_DT: 1399939200000, + MAJOR_PROJECT_FLAG: "N", + TRANSPORT_MODE: "H", + PLANNING_PARTNER_SHORT_NAME: "DVRPC", + RESPONSIBLE_DISTRICT_NO: 6, + PRIMARY_ST_RT_NO: 3033, + DISTRICT_SECTION_ID: "HFS", + PRIMARY_LOCAL_ROAD_NUMBER: 0, + PROJECT_TOTAL_LENGTH: 6.77, + LOCAL_PROJECT_FLAG: "N", + LET_RESPONSIBLE_AGENCY: null, + GEOGRAPHIC_DESCRIPTION: "Various high-crash roadway curves in District 6-0", + PROJECT_STATE_CODE: "CAND", + PROJECT_STATUS_CODE_DESC: "Candidate", + CODE_ID: 43, + POTENTIAL_COMMITTED_DATE_FLAG: null, + POTENTIAL_COMMITTED_YEAR: null, + POTENTIAL_COMMITTED_DATE: "6/12/2014 12:00:00 AM", + EST_CONSTR_PHASE_COST_AMOUNT: 2445000, + TYP_FLAG: "N", + TIP_FLAG: "N", + STIP_FLAG: "N", + DECADE_OF_INVESTMENT_FLAG: "N", + TIP_PROPOSED_FLAG: "N", + TYP_PROPOSED_FLAG: "N", + OBLIGATION_PLAN_FLAG: "Y", + LET_FLAG: "A", + LET_DATE: "20140703", + LET_DATE_DISPLAY: "7/3/2014 12:00:00 AM", + OPEN_FLAG: null, + OPEN_DATE: null, + NTP_FLAG: "A", + NTP_DATE: 20140818, + COMPLETION_FLAG: "A", + COMPLETION_DATE: "20151007", + FISCALLY_READY: null, + FISCAL_DATE: null, + PHYSICALLY_READY: null, + PHYSICAL_DATE: null, + PROJECT_MANAGER_CONTACT_NAME: "George Dunheimer ADE CONSTR", + PROJECT_MANAGER_PHONE: "6102056680", + PROJECT_MANAGER_EMAIL: "gdunheimer@pa.gov", + UNDER_CONSTRUCTION: "N", + COMPLETED: "Y", + FUTURE_DEVELOPMENT: "N", + IN_DEVELOPMENT: "N", + PROJECT_STAGE: "COMPLETED", + PROJECT_CREATION_DATE: 1397779200000, + CAPITAL_BUDGET_YEAR: null, + CAPTIAL_BUDGET_REQUIRED_FLAG: "Y", + CAPITAL_BUDGET_APPROVED_FLAG: "N", + PLANNING_PARTNER_NAME: "Delaware Valley Regional Planning Commission MPO ", + RESPONSIBLE_DISTRICT_NAME: "District 6-0 ", + RESPONSIBLE_COUNTY_CODE: 15, + RESPONSIBLE_COUNTY_NAME: "Chester ", + PROJECT_SPONSOR_NAME: "PennDOT", + SD_BRIDGE_WORK_FLAG: "N", + OPEN_TO_TRAFFIC_DATE: null, + ORIGINAL_CONTRACT_AMOUNT: null, + CURRENT_CONTRACT_AMOUNT: null, + ESTIMATED_LET_DATE: "7/3/2014 12:00:00 AM", + DOI_DATE: null, + DOI_ID: null, + PRIMARY_PROJECT_ID: 102572, + PRIMARY_CONTRACT_AMOUNT: null, + PRIMARY_PROJECT_FLAG: "Y", + HAS_CONSTRUCTION_PHASE: "T", + HAS_FINAL_DESIGN_PHASE: "F", + HAS_PRELIMINARY_ENGINEER_PHASE: "F", + HAS_PLAN_RESEARCH_ADMIN_PHASE: "F", + HAS_RIGHT_OF_WAY_PHASE: "F", + HAS_STUDY_PHASE: "F", + HAS_UTILITY_PHASE: "F", + CTY_CODE: 67, + ST_RT_NO: 8009, + JURIS: 1, + DISTRICT_NO: 6, + SEG_BGN: 250, + OFFSET_BGN: 0, + SEG_END: 250, + OFFSET_END: 2890, + SEG_PT_BGN: 2500000, + SEG_PT_END: 2502890, + SEG_LNGTH_FEET: 2890, + NLF_ID: 39099, + SIDE_IND: 1, + NLF_CNTL_BGN: 0, + NLF_CNTL_END: 2890, + CUM_OFFSET_BGN: 6590, + CUM_OFFSET_END: 9480, + COUNTY_MUNICIPALITY_CODES: "67301", + MUNICIPALITY_CODES: "301", + MUNICIPALITY_NAMES: "PHILADELPHIA ", + HOUSE_DISTRICTS: "175", + SENATE_DISTRICTS: "1", + CONGRESS_DISTRICTS: "2/3/2022 12:00:00 AM", + HOUSE_LEGISLATOR_NAMES: "Marylouise Isaacson, (D)", + SENATE_LEGISLATOR_NAMES: "Nikil Saval, (D)", + CONGRESS_LEGISLATOR_NAMES: "Brendan F. Boyle (D), Dwight Evans (D)", + COUNTY_NAME: "PHILADELPHIA", + STREET_NAME: null, + BRIDGE_WORK_FLAG: "N", + RECORD_UPDATE: 20210529, + CREATED_DATE: 1557728835000, + LAST_EDITED_DATE: 1622273589000, + GEOM_LENGTH_FT: 4960, + GEOMETRY_TYPE: "POINT", + BRIDGE_WORK_LOCATION_FLAG: "N", + PUBLIC_NARRATIVE: "High Friction Surfaces\r\nVarious high-crash roadway curves in D6-0\r\nTreatmnt to reduce crashes on rdwy curves", + GIS_UPDATE_DATE: 1603171861000, + GIS_GEOMETRY_UPDATE_DATE: 1636117557000, + SE_ANNO_CAD_DATA: null, + GPID: 974725878, + GlobalID: "88c9a006-4af4-47eb-bea6-553a61306cee", + }, + }], + }; // Geometry features public static phillySimplePolyQueryJson = { - objectIdFieldName: "FID", uniqueIdField: { name: "FID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, serverGens: { minServerGen: 617069, serverGen: 701173 }, geometryType: "esriGeometryPolygon", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [1.1943285667766759, 1.1943285667766759], translate: [-8366491.366817627, 4858337.5171295125] }, fields: [], features: [{ attributes: {}, geometry: { rings: [[[274, 472], [-3, 18], [-16, -3], [3, -17], [0, -1], [16, 3]]] } }], + objectIdFieldName: "FID", + uniqueIdField: { name: "FID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, + serverGens: { minServerGen: 617069, serverGen: 701173 }, + geometryType: "esriGeometryPolygon", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [1.1943285667766759, 1.1943285667766759], translate: [-8366491.366817627, 4858337.5171295125] }, + fields: [], + features: [{ attributes: {}, geometry: { rings: [[[274, 472], [-3, 18], [-16, -3], [3, -17], [0, -1], [16, 3]]] } }], }; public static phillySimplePolyQueryPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "FID", uniqueIdField: { name: "FID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, serverGens: { minServerGen: 617069, serverGen: 701173 }, geometryType: 3, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: false, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 1.1943285667766759, yScale: 1.1943285667766759, mScale: 0, zScale: 0 }, translate: { xTranslate: -8366491.366817627, yTranslate: 4858337.5171295125, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [6], coords: [274, 472, -3, 18, -16, -3, 3, -17, 0, -1, 16, 3] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "FID", + uniqueIdField: { name: "FID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, + serverGens: { minServerGen: 617069, serverGen: 701173 }, + geometryType: 3, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 1.1943285667766759, yScale: 1.1943285667766759, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8366491.366817627, yTranslate: 4858337.5171295125, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ attributes: [], geometry: { lengths: [6], coords: [274, 472, -3, 18, -16, -3, 3, -17, 0, -1, 16, 3] } }], + }, + }, }; public static phillyDoubleRingPolyQueryJson = { - objectIdFieldName: "FID", uniqueIdField: { name: "FID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, serverGens: { minServerGen: 617069, serverGen: 701173 }, geometryType: "esriGeometryPolygon", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [0.5971642833956139, 0.5971642833956139], translate: [-8365879.870591431, 4857726.020903323] }, fields: [], features: [{ attributes: {}, geometry: { rings: [[[398, 127], [-7, -1], [-18, -3], [-7, -1], [0, -3], [-12, -2], [1, -5], [1, -6], [-18, -3], [-1, 0], [0, -1], [3, -15], [21, 3], [6, -39], [10, 2], [3, 0], [61, 11], [-1, 6], [-8, 43], [-1, 6], [-19, -4], [-2, 12], [-12, -2], [0, 2]], [[417, 109], [3, -16], [-21, -3], [-2, 15], [16, 3], [4, 1]]] } }], + objectIdFieldName: "FID", + uniqueIdField: { name: "FID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, + serverGens: { minServerGen: 617069, serverGen: 701173 }, + geometryType: "esriGeometryPolygon", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [0.5971642833956139, 0.5971642833956139], translate: [-8365879.870591431, 4857726.020903323] }, + fields: [], + features: [{ + attributes: {}, + geometry: { + rings: [[ + [398, 127], + [-7, -1], + [-18, -3], + [-7, -1], + [0, -3], + [-12, -2], + [1, -5], + [1, -6], + [-18, -3], + [-1, 0], + [0, -1], + [3, -15], + [21, 3], + [6, -39], + [10, 2], + [3, 0], + [61, 11], + [-1, 6], + [-8, 43], + [-1, 6], + [-19, -4], + [-2, 12], + [-12, -2], + [0, 2], + ], [[417, 109], [3, -16], [-21, -3], [-2, 15], [16, 3], [4, 1]]], + }, + }], }; public static phillyDoubleRingPolyQueryPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "FID", uniqueIdField: { name: "FID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, serverGens: { minServerGen: 617069, serverGen: 701173 }, geometryType: 3, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: false, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 0.5971642833956139, yScale: 0.5971642833956139, mScale: 0, zScale: 0 }, translate: { xTranslate: -8365879.870591431, yTranslate: 4857726.020903323, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [24, 6], coords: [398, 127, -7, -1, -18, -3, -7, -1, 0, -3, -12, -2, 1, -5, 1, -6, -18, -3, -1, 0, 0, -1, 3, -15, 21, 3, 6, -39, 10, 2, 3, 0, 61, 11, -1, 6, -8, 43, -1, 6, -19, -4, -2, 12, -12, -2, 0, 2, 417, 109, 3, -16, -21, -3, -2, 15, 16, 3, 4, 1] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "FID", + uniqueIdField: { name: "FID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + geometryProperties: { shapeAreaFieldName: "Shape__Area", shapeLengthFieldName: "Shape__Length", units: "esriMeters" }, + serverGens: { minServerGen: 617069, serverGen: 701173 }, + geometryType: 3, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 0.5971642833956139, yScale: 0.5971642833956139, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8365879.870591431, yTranslate: 4857726.020903323, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ + attributes: [], + geometry: { + lengths: [24, 6], + coords: [ + 398, + 127, + -7, + -1, + -18, + -3, + -7, + -1, + 0, + -3, + -12, + -2, + 1, + -5, + 1, + -6, + -18, + -3, + -1, + 0, + 0, + -1, + 3, + -15, + 21, + 3, + 6, + -39, + 10, + 2, + 3, + 0, + 61, + 11, + -1, + 6, + -8, + 43, + -1, + 6, + -19, + -4, + -2, + 12, + -12, + -2, + 0, + 2, + 417, + 109, + 3, + -16, + -21, + -3, + -2, + 15, + 16, + 3, + 4, + 1, + ], + }, + }], + }, + }, }; public static phillySimplePathQueryPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", geometryProperties: { shapeAreaFieldName: "", shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, serverGens: { minServerGen: 617022, serverGen: 701134 }, geometryType: 2, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: false, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 19.10925706863054, yScale: 19.10925706863054, mScale: 0, zScale: 0 }, translate: { xTranslate: -8365268.374365235, yTranslate: 4872401.930332029, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [24], coords: [360, 491, -2, -1, -1, 0, -1, 0, -1, 0, -1, 1, -4, 1, -10, 2, -15, 3, -1, 0, -1, 0, -2, 0, -1, 0, -1, 0, -1, -1, -1, 0, -2, -1, 0, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + geometryProperties: { shapeAreaFieldName: "", shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, + serverGens: { minServerGen: 617022, serverGen: 701134 }, + geometryType: 2, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 19.10925706863054, yScale: 19.10925706863054, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8365268.374365235, yTranslate: 4872401.930332029, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ + attributes: [], + geometry: { + lengths: [24], + coords: [ + 360, + 491, + -2, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 1, + -4, + 1, + -10, + 2, + -15, + 3, + -1, + 0, + -1, + 0, + -2, + 0, + -1, + 0, + -1, + 0, + -1, + -1, + -1, + 0, + -2, + -1, + 0, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + ], + }, + }], + }, + }, }; public static phillySimplePathQueryJson = { - objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geometryProperties: { shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, serverGens: { minServerGen: 617022, serverGen: 701134 }, geometryType: "esriGeometryPolyline", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [19.10925706863054, 19.10925706863054], translate: [-8365268.374365235, 4872401.930332029] }, fields: [], features: [{ attributes: {}, geometry: { paths: [[[360, 491], [-2, -1], [-1, 0], [-1, 0], [-1, 0], [-1, 1], [-4, 1], [-10, 2], [-15, 3], [-1, 0], [-1, 0], [-2, 0], [-1, 0], [-1, 0], [-1, -1], [-1, 0], [-2, -1], [0, -1], [-1, 0], [-1, 0], [-1, 0], [-1, 0], [-1, 0], [-1, 0]]] } }], + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geometryProperties: { shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, + serverGens: { minServerGen: 617022, serverGen: 701134 }, + geometryType: "esriGeometryPolyline", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [19.10925706863054, 19.10925706863054], translate: [-8365268.374365235, 4872401.930332029] }, + fields: [], + features: [{ + attributes: {}, + geometry: { + paths: [[ + [360, 491], + [-2, -1], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 1], + [-4, 1], + [-10, 2], + [-15, 3], + [-1, 0], + [-1, 0], + [-2, 0], + [-1, 0], + [-1, 0], + [-1, -1], + [-1, 0], + [-2, -1], + [0, -1], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 0], + ]], + }, + }], }; public static phillyMultiPathQueryPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", geometryProperties: { shapeAreaFieldName: "", shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, serverGens: { minServerGen: 617022, serverGen: 701134 }, geometryType: 2, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: false, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 19.10925706863054, yScale: 19.10925706863054, mScale: 0, zScale: 0 }, translate: { xTranslate: -8365268.374365235, yTranslate: 4872401.930332029, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [22, 2], coords: [360, 491, -2, -1, -1, 0, -1, 0, -1, 0, -1, 1, -4, 1, -10, 2, -15, 3, -1, 0, -1, 0, -2, 0, -1, 0, -1, 0, -1, -1, -1, 0, -2, -1, 0, -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + geometryProperties: { shapeAreaFieldName: "", shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, + serverGens: { minServerGen: 617022, serverGen: 701134 }, + geometryType: 2, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 19.10925706863054, yScale: 19.10925706863054, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8365268.374365235, yTranslate: 4872401.930332029, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ + attributes: [], + geometry: { + lengths: [22, 2], + coords: [ + 360, + 491, + -2, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 1, + -4, + 1, + -10, + 2, + -15, + 3, + -1, + 0, + -1, + 0, + -2, + 0, + -1, + 0, + -1, + 0, + -1, + -1, + -1, + 0, + -2, + -1, + 0, + -1, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + -1, + 0, + ], + }, + }], + }, + }, }; public static phillyMultiPathQueryJson = { - objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geometryProperties: { shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, serverGens: { minServerGen: 617022, serverGen: 701134 }, geometryType: "esriGeometryPolyline", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [19.10925706863054, 19.10925706863054], translate: [-8365268.374365235, 4872401.930332029] }, fields: [], features: [{ attributes: {}, geometry: { paths: [[[360, 491], [-2, -1], [-1, 0], [-1, 0], [-1, 0], [-1, 1], [-4, 1], [-10, 2], [-15, 3], [-1, 0], [-1, 0], [-2, 0], [-1, 0], [-1, 0], [-1, -1], [-1, 0], [-2, -1], [0, -1], [-1, 0], [-1, 0], [-1, 0], [-1, 0]], [[-1, 0], [-1, 0]]] } }], + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geometryProperties: { shapeLengthFieldName: "Shape__Length_2", units: "esriMeters" }, + serverGens: { minServerGen: 617022, serverGen: 701134 }, + geometryType: "esriGeometryPolyline", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [19.10925706863054, 19.10925706863054], translate: [-8365268.374365235, 4872401.930332029] }, + fields: [], + features: [{ + attributes: {}, + geometry: { + paths: [[ + [360, 491], + [-2, -1], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 1], + [-4, 1], + [-10, 2], + [-15, 3], + [-1, 0], + [-1, 0], + [-2, 0], + [-1, 0], + [-1, 0], + [-1, -1], + [-1, 0], + [-2, -1], + [0, -1], + [-1, 0], + [-1, 0], + [-1, 0], + [-1, 0], + ], [[-1, 0], [-1, 0]]], + }, + }], }; public static phillySimplePointQueryPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", serverGens: { minServerGen: 617056, serverGen: 701159 }, geometryType: 0, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: false, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 4.777314267153997, yScale: 4.777314267153997, mScale: 0, zScale: 0 }, translate: { xTranslate: -8365268.374365235, yTranslate: 4860172.005808106, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [], coords: [88, 488] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + serverGens: { minServerGen: 617056, serverGen: 701159 }, + geometryType: 0, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 4.777314267153997, yScale: 4.777314267153997, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8365268.374365235, yTranslate: 4860172.005808106, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ attributes: [], geometry: { lengths: [], coords: [88, 488] } }], + }, + }, }; public static phillyExceededTransferLimitPbf = { - version: "", queryResult: { featureResult: { objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", geohashFieldName: "", serverGens: { minServerGen: 617056, serverGen: 701159 }, geometryType: 0, spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, exceededTransferLimit: true, hasZ: false, hasM: false, transform: { quantizeOriginPostion: 0, scale: { xScale: 4.777314267153997, yScale: 4.777314267153997, mScale: 0, zScale: 0 }, translate: { xTranslate: -8365268.374365235, yTranslate: 4860172.005808106, mTranslate: 0, zTranslate: 0 } }, fields: [], values: [], features: [{ attributes: [], geometry: { lengths: [], coords: [88, 488] } }] } }, + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + serverGens: { minServerGen: 617056, serverGen: 701159 }, + geometryType: 0, + spatialReference: { wkid: 102100, lastestWkid: 3857, vcsWkid: 0, latestVcsWkid: 0, wkt: "" }, + exceededTransferLimit: true, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { xScale: 4.777314267153997, yScale: 4.777314267153997, mScale: 0, zScale: 0 }, + translate: { xTranslate: -8365268.374365235, yTranslate: 4860172.005808106, mTranslate: 0, zTranslate: 0 }, + }, + fields: [], + values: [], + features: [{ attributes: [], geometry: { lengths: [], coords: [88, 488] } }], + }, + }, }; public static phillySimplePointQueryJson = { - objectIdFieldName: "OBJECTID", uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, globalIdFieldName: "GlobalID", serverGens: { minServerGen: 617056, serverGen: 701159 }, geometryType: "esriGeometryPoint", spatialReference: { wkid: 102100, latestWkid: 3857 }, transform: { originPosition: "upperLeft", scale: [4.777314267153997, 4.777314267153997], translate: [-8365268.374365235, 4860172.005808106] }, fields: [], features: [{ attributes: {}, geometry: { x: 88, y: 488 } }], + objectIdFieldName: "OBJECTID", + uniqueIdField: { name: "OBJECTID", isSystemMaintained: true }, + globalIdFieldName: "GlobalID", + serverGens: { minServerGen: 617056, serverGen: 701159 }, + geometryType: "esriGeometryPoint", + spatialReference: { wkid: 102100, latestWkid: 3857 }, + transform: { originPosition: "upperLeft", scale: [4.777314267153997, 4.777314267153997], translate: [-8365268.374365235, 4860172.005808106] }, + fields: [], + features: [{ attributes: {}, geometry: { x: 88, y: 488 } }], }; // Drawing infos public static phillySimplePolyDrawingInfo = { - drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSFS", style: "esriSFSSolid", color: [76, 129, 205, 191], outline: { type: "esriSLS", style: "esriSLSSolid", color: [0, 0, 0, 255], width: 0.75 } } }, transparency: 0, labelingInfo: null }, + drawingInfo: { + renderer: { + type: "simple", + symbol: { + type: "esriSFS", + style: "esriSFSSolid", + color: [76, 129, 205, 191], + outline: { type: "esriSLS", style: "esriSLSSolid", color: [0, 0, 0, 255], width: 0.75 }, + }, + }, + transparency: 0, + labelingInfo: null, + }, }; public static phillySimpleLineDrawingInfo = { - drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSLS", style: "esriSLSSolid", color: [165, 83, 183, 255], width: 1 } }, transparency: 0, labelingInfo: null }, + drawingInfo: { + renderer: { type: "simple", symbol: { type: "esriSLS", style: "esriSLSSolid", color: [165, 83, 183, 255], width: 1 } }, + transparency: 0, + labelingInfo: null, + }, }; public static phillySimplePointDrawingInfo = { - drawingInfo: { renderer: { type: "simple", symbol: { type: "esriPMS", url: "RedSphere.png", imageData: "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuNS4xTuc4+QAAB3VJREFUeF7tmPlTlEcexnve94U5mANQbgQSbgiHXHINlxpRIBpRI6wHorLERUmIisKCQWM8cqigESVQS1Kx1piNi4mW2YpbcZONrilE140RCTcy3DDAcL/zbJP8CYPDL+9Ufau7uqb7eZ7P+/a8PS8hwkcgIBAQCAgEBAICAYGAQEAgIBAQCAgEBAICAYGAQEAgIBAQCDx/AoowKXFMUhD3lQrioZaQRVRS+fxl51eBTZUTdZ41U1Rox13/0JF9csGJ05Qv4jSz/YPWohtvLmSKN5iTGGqTm1+rc6weICOBRbZs1UVnrv87T1PUeovxyNsUP9P6n5cpHtCxu24cbrmwKLdj+osWiqrVKhI0xzbmZ7m1SpJ+1pFpvE2DPvGTomOxAoNLLKGLscZYvB10cbYYjrJCb7A5mrxleOBqim+cWJRakZY0JfnD/LieI9V1MrKtwokbrAtU4Vm0A3TJnphJD4B+RxD0u0LA7w7FTE4oprOCMbklEGNrfdGf4IqnQTb4wc0MFTYibZqM7JgjO8ZdJkpMln/sKu16pHZGb7IfptIWg389DPp9kcChWODoMuDdBOhL1JgpisbUvghM7AqFbtNiaFP80RLnhbuBdqi0N+1dbUpWGde9gWpuhFi95yL7sS7BA93JAb+Fn8mh4QujgPeTgb9kAZf3Apd2A+fXQ38yHjOHozB1IAJjOSEY2RSIwVUv4dd4X9wJccGHNrJ7CYQ4GGjLeNNfM+dyvgpzQstKf3pbB2A6m97uBRE0/Ergcxr8hyqg7hrwn0vAtRIKIRX6Y2pMl0RhIj8co9nBGFrvh55l3ngU7YObng7IVnFvGS+BYUpmHziY/Ls2zgP9SX50by/G9N5w6I+ogYvpwK1SoOlHQNsGfWcd9Peqof88B/rTyzF9hAIopAByQzC0JQB9ST5oVnvhnt+LOGsprvUhxNIwa0aY7cGR6Cp7tr8+whkjawIxkRWC6YJI6N+lAKq3Qf/Tx+B77oGfaQc/8hB8w2Xwtw9Bf3kzZspXY/JIDEbfpAB2BKLvVV90Jvjgoac9vpRxE8kciTVCBMMkNirJ7k/tRHyjtxwjKV4Yp3t/6s+R4E+/DH3N6+BrS8E314Dvvg2+/Sb4hxfBf5sP/up2TF3ZhonK1zD6dhwGdwail26DzqgX8MRKiq9ZBpkSkmeYOyPM3m9Jjl+1Z9D8AgNtlAq6bZ70qsZi+q+bwV/7I/hbB8D/dAr8Axq89iz474p/G5++koHJy1sx/lkGdBc2YjA3HF0rHNHuboomuQj/5DgclIvOGCGCYRKFFuTMV7YUAD3VDQaLMfyqBcZORGPy01QKYSNm/rYV/Nd/Av9NHvgbueBrsjDzRQamKKDxT9Kgq1iLkbIUDOSHoiNcgnYHgnYZi+9ZExSbiSoMc2eE2flKcuJLa4KGRQz6/U0wlGaP0feiMH4uFpMXEjBVlYjp6lWY+SSZtim0kulYMiYuJEJXuhTDJ9UYPByOvoIwdCxfgE4bAo0Jh39xLAoVpMwIEQyTyFCQvGpLon9sJ0K3J4OBDDcMH1dj9FQsxkrjMPFRPCbOx2GyfLal9VEcxstioTulxjAFNfROJPqLl6Bnfyg6V7ugz5yBhuHwrZjBdiU5YJg7I8wOpifAKoVIW7uQ3rpOBH2b3ekVjYT2WCRG3o+mIGKgO0OrlIaebU/HYOQDNbQnojB4NJyGD0NPfjA0bwTRE6Q7hsUcWhkWN8yZqSQlWWGECAZLmJfJmbrvVSI8taK37xpbdB/wQW8xPee/8xIGjvlj8IQ/hk4G0JbWcX8MHPVDX4kveoq8ocn3xLM33NCZRcPHOGJYZIKfpQyq7JjHS6yJjcHujLHADgkpuC7h8F8zEVqXSNC2awE69lqhs8AamkO26HrbDt2H7dBVQov2NcW26CiwQtu+BWjdY4n2nZboTbfCmKcCnRyDO/YmyLPnDlHvjDH8G6zhS9/wlEnYR7X00fWrFYuWdVI0ZpuhcbcczW/R2qdAcz6t/bRov4mONeaaoYl+p22rHF0bVNAmKtBvweIXGxNcfFH8eNlC4m6wMWMusEnKpn5hyo48pj9gLe4SNG9QoGGLAk8z5XiaJUd99u8122/IpBA2K9BGg2vWWKAvRYVeLzEa7E1R422m2+MsSTem97nSYnfKyN6/mzATv7AUgqcMrUnmaFlLX3ysM0fj+t/b5lQLtK22QEfyAmiSLKFZpUJ7kBRPXKW4HqCYynWVHKSG2LkyZex1uO1mZM9lKem9Tx9jjY5iNEYo0bKMhn7ZAu0r6H5PpLXCAq0rKJClSjSGynE/QIkrQYqBPe6S2X+AJsY2Ped6iWZk6RlL0c2r5szofRsO9R5S1IfQLRCpQL1aifoYFerpsbkuTImaUJXuXIDiH6/Ys8vm3Mg8L2i20YqsO7fItKLcSXyn0kXccclVqv3MS6at9JU/Ox+ouns+SF6Z4cSupz7l8+z1ucs7LF1AQjOdxfGZzmx8Iu1TRcfnrioICAQEAgIBgYBAQCAgEBAICAQEAgIBgYBAQCAgEBAICAQEAv8H44b/6ZiGvGAAAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 15 } } }, + drawingInfo: { + renderer: { + type: "simple", + symbol: { + type: "esriPMS", + url: "RedSphere.png", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuNS4xTuc4+QAAB3VJREFUeF7tmPlTlEcexnve94U5mANQbgQSbgiHXHINlxpRIBpRI6wHorLERUmIisKCQWM8cqigESVQS1Kx1piNi4mW2YpbcZONrilE140RCTcy3DDAcL/zbJP8CYPDL+9Ufau7uqb7eZ7P+/a8PS8hwkcgIBAQCAgEBAICAYGAQEAgIBAQCAgEBAICAYGAQEAgIBAQCDx/AoowKXFMUhD3lQrioZaQRVRS+fxl51eBTZUTdZ41U1Rox13/0JF9csGJ05Qv4jSz/YPWohtvLmSKN5iTGGqTm1+rc6weICOBRbZs1UVnrv87T1PUeovxyNsUP9P6n5cpHtCxu24cbrmwKLdj+osWiqrVKhI0xzbmZ7m1SpJ+1pFpvE2DPvGTomOxAoNLLKGLscZYvB10cbYYjrJCb7A5mrxleOBqim+cWJRakZY0JfnD/LieI9V1MrKtwokbrAtU4Vm0A3TJnphJD4B+RxD0u0LA7w7FTE4oprOCMbklEGNrfdGf4IqnQTb4wc0MFTYibZqM7JgjO8ZdJkpMln/sKu16pHZGb7IfptIWg389DPp9kcChWODoMuDdBOhL1JgpisbUvghM7AqFbtNiaFP80RLnhbuBdqi0N+1dbUpWGde9gWpuhFi95yL7sS7BA93JAb+Fn8mh4QujgPeTgb9kAZf3Apd2A+fXQ38yHjOHozB1IAJjOSEY2RSIwVUv4dd4X9wJccGHNrJ7CYQ4GGjLeNNfM+dyvgpzQstKf3pbB2A6m97uBRE0/Ergcxr8hyqg7hrwn0vAtRIKIRX6Y2pMl0RhIj8co9nBGFrvh55l3ngU7YObng7IVnFvGS+BYUpmHziY/Ls2zgP9SX50by/G9N5w6I+ogYvpwK1SoOlHQNsGfWcd9Peqof88B/rTyzF9hAIopAByQzC0JQB9ST5oVnvhnt+LOGsprvUhxNIwa0aY7cGR6Cp7tr8+whkjawIxkRWC6YJI6N+lAKq3Qf/Tx+B77oGfaQc/8hB8w2Xwtw9Bf3kzZspXY/JIDEbfpAB2BKLvVV90Jvjgoac9vpRxE8kciTVCBMMkNirJ7k/tRHyjtxwjKV4Yp3t/6s+R4E+/DH3N6+BrS8E314Dvvg2+/Sb4hxfBf5sP/up2TF3ZhonK1zD6dhwGdwail26DzqgX8MRKiq9ZBpkSkmeYOyPM3m9Jjl+1Z9D8AgNtlAq6bZ70qsZi+q+bwV/7I/hbB8D/dAr8Axq89iz474p/G5++koHJy1sx/lkGdBc2YjA3HF0rHNHuboomuQj/5DgclIvOGCGCYRKFFuTMV7YUAD3VDQaLMfyqBcZORGPy01QKYSNm/rYV/Nd/Av9NHvgbueBrsjDzRQamKKDxT9Kgq1iLkbIUDOSHoiNcgnYHgnYZi+9ZExSbiSoMc2eE2flKcuJLa4KGRQz6/U0wlGaP0feiMH4uFpMXEjBVlYjp6lWY+SSZtim0kulYMiYuJEJXuhTDJ9UYPByOvoIwdCxfgE4bAo0Jh39xLAoVpMwIEQyTyFCQvGpLon9sJ0K3J4OBDDcMH1dj9FQsxkrjMPFRPCbOx2GyfLal9VEcxstioTulxjAFNfROJPqLl6Bnfyg6V7ugz5yBhuHwrZjBdiU5YJg7I8wOpifAKoVIW7uQ3rpOBH2b3ekVjYT2WCRG3o+mIGKgO0OrlIaebU/HYOQDNbQnojB4NJyGD0NPfjA0bwTRE6Q7hsUcWhkWN8yZqSQlWWGECAZLmJfJmbrvVSI8taK37xpbdB/wQW8xPee/8xIGjvlj8IQ/hk4G0JbWcX8MHPVDX4kveoq8ocn3xLM33NCZRcPHOGJYZIKfpQyq7JjHS6yJjcHujLHADgkpuC7h8F8zEVqXSNC2awE69lqhs8AamkO26HrbDt2H7dBVQov2NcW26CiwQtu+BWjdY4n2nZboTbfCmKcCnRyDO/YmyLPnDlHvjDH8G6zhS9/wlEnYR7X00fWrFYuWdVI0ZpuhcbcczW/R2qdAcz6t/bRov4mONeaaoYl+p22rHF0bVNAmKtBvweIXGxNcfFH8eNlC4m6wMWMusEnKpn5hyo48pj9gLe4SNG9QoGGLAk8z5XiaJUd99u8122/IpBA2K9BGg2vWWKAvRYVeLzEa7E1R422m2+MsSTem97nSYnfKyN6/mzATv7AUgqcMrUnmaFlLX3ysM0fj+t/b5lQLtK22QEfyAmiSLKFZpUJ7kBRPXKW4HqCYynWVHKSG2LkyZex1uO1mZM9lKem9Tx9jjY5iNEYo0bKMhn7ZAu0r6H5PpLXCAq0rKJClSjSGynE/QIkrQYqBPe6S2X+AJsY2Ped6iWZk6RlL0c2r5szofRsO9R5S1IfQLRCpQL1aifoYFerpsbkuTImaUJXuXIDiH6/Ys8vm3Mg8L2i20YqsO7fItKLcSXyn0kXccclVqv3MS6at9JU/Ox+ouns+SF6Z4cSupz7l8+z1ucs7LF1AQjOdxfGZzmx8Iu1TRcfnrioICAQEAgIBgYBAQCAgEBAICAQEAgIBgYBAQCAgEBAICAQEAv8H44b/6ZiGvGAAAAAASUVORK5CYII=", + contentType: "image/png", + width: 15, + height: 15, + }, + }, + }, }; public static phillySimpleSMSDrawingInfo = { - drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSMS", style: "esriSMSCircle", color: [165, 83, 183, 255], size: 2} } }, + drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSMS", style: "esriSMSCircle", color: [165, 83, 183, 255], size: 2 } } }, }; // This is the resulting serializaed MapLayerFeatureInfo objects (i.e expected result) @@ -1924,179 +3460,203 @@ export class PhillyLandmarksDataset { }, ]; - public static fieldsCoveragePbufferCollection = - { - version: "", - queryResult: - { - featureResult: - { - objectIdFieldName: "FID", - uniqueIdField: + public static fieldsCoveragePbufferCollection = { + version: "", + queryResult: { + featureResult: { + objectIdFieldName: "FID", + uniqueIdField: { + name: "FID", + isSystemMaintained: true, + }, + globalIdFieldName: "GlobalID", + geohashFieldName: "", + serverGens: { + minServerGen: 617069, + serverGen: 698319, + }, + geometryType: 3, + spatialReference: { + wkid: 102100, + lastestWkid: 3857, + vcsWkid: 0, + latestVcsWkid: 0, + wkt: "", + }, + exceededTransferLimit: false, + hasZ: false, + hasM: false, + transform: { + quantizeOriginPostion: 0, + scale: { + xScale: 9.554628534318908, + yScale: 9.554628534318908, + mScale: 0, + zScale: 0, + }, + translate: { + xTranslate: -8379944.283793945, + yTranslate: 4847942.0812841775, + mTranslate: 0, + zTranslate: 0, + }, + }, + fields: [ { - name: "FID", - isSystemMaintained: true, + name: "field_SmallInteger", + fieldType: 0, + alias: "field_SmallInteger", + sqlType: 0, + domain: "", + defaultValue: "", }, - globalIdFieldName: "GlobalID", - geohashFieldName: "", - serverGens: { - minServerGen: 617069, - serverGen: 698319, + name: "field_Integer", + fieldType: 1, + alias: "field_Integer", + sqlType: 0, + domain: "", + defaultValue: "", }, - geometryType: 3, - spatialReference: { - wkid: 102100, - lastestWkid: 3857, - vcsWkid: 0, - latestVcsWkid: 0, - wkt: "", + name: "field_Single", + fieldType: 2, + alias: "field_Single", + sqlType: 7, + domain: "", + defaultValue: "", }, - exceededTransferLimit: false, - hasZ: false, - hasM: false, - transform: { - quantizeOriginPostion: 0, - scale: - { - xScale: 9.554628534318908, - yScale: 9.554628534318908, - mScale: 0, - zScale: 0, - }, - translate: - { - xTranslate: -8379944.283793945, - yTranslate: 4847942.0812841775, - mTranslate: 0, - zTranslate: 0, - }, + name: "field_Double", + fieldType: 3, + alias: "field_Double", + sqlType: 6, + domain: "", + defaultValue: "", }, - fields: [ - { - name: "field_SmallInteger", - fieldType: 0, - alias: "field_SmallInteger", - sqlType: 0, - domain: "", - defaultValue: "", - }, - { - name: "field_Integer", - fieldType: 1, - alias: "field_Integer", - sqlType: 0, - domain: "", - defaultValue: "", - }, - { - name: "field_Single", - fieldType: 2, - alias: "field_Single", - sqlType: 7, - domain: "", - defaultValue: "", - }, - { - name: "field_Double", - fieldType: 3, - alias: "field_Double", - sqlType: 6, - domain: "", - defaultValue: "", - }, - { - name: "field_String", - fieldType: 4, - alias: "field_String", - sqlType: 15, - domain: "", - defaultValue: "", - }, - { - name: "field_Date", - fieldType: 5, - alias: "field_Date", - sqlType: 4, - domain: "", - defaultValue: "", - }, - { - name: "field_OID", - fieldType: 6, - alias: "field_OID", - sqlType: 0, - domain: "", - defaultValue: "", - }, - { - name: "field_Geometry", - fieldType: 7, - alias: "field_Geometry", - sqlType: 8, - domain: "", - defaultValue: "", - }, - { - name: "field_Raster", - fieldType: 8, - alias: "field_Raster", - sqlType: 0, - domain: "", - defaultValue: "", - }, - { - name: "field9", - fieldType: 0, - alias: "field9", - sqlType: 0, - domain: "", - defaultValue: "", - }, - ], - values: [], - features: [ - { - attributes: [ - { - sint_value: 1, - }, - { - int64_value: 2, - }, - { - float_value: 3.1, - }, - { - double_value: 4.1, - }, - { - string_value: "field 5", - }, - { - uint_value: 6, - }, - { - bool_value: true, - }, - { - uint64_value: 8, - }, - { - sint64_value: 9, - }, - ], - }, - ], - }, + { + name: "field_String", + fieldType: 4, + alias: "field_String", + sqlType: 15, + domain: "", + defaultValue: "", + }, + { + name: "field_Date", + fieldType: 5, + alias: "field_Date", + sqlType: 4, + domain: "", + defaultValue: "", + }, + { + name: "field_OID", + fieldType: 6, + alias: "field_OID", + sqlType: 0, + domain: "", + defaultValue: "", + }, + { + name: "field_Geometry", + fieldType: 7, + alias: "field_Geometry", + sqlType: 8, + domain: "", + defaultValue: "", + }, + { + name: "field_Raster", + fieldType: 8, + alias: "field_Raster", + sqlType: 0, + domain: "", + defaultValue: "", + }, + { + name: "field9", + fieldType: 0, + alias: "field9", + sqlType: 0, + domain: "", + defaultValue: "", + }, + ], + values: [], + features: [ + { + attributes: [ + { + sint_value: 1, + }, + { + int64_value: 2, + }, + { + float_value: 3.1, + }, + { + double_value: 4.1, + }, + { + string_value: "field 5", + }, + { + uint_value: 6, + }, + { + bool_value: true, + }, + { + uint64_value: 8, + }, + { + sint64_value: 9, + }, + ], + }, + ], }, - }; - - public static polygonDrawingInfo = { drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSFS", style: "esriSFSSolid", color: [76, 129, 205, 191], outline: { type: "esriSLS", style: "esriSLSSolid", color: [0, 0, 0, 255], width: 0.75 } } }, transparency: 0, labelingInfo: null } }; - public static lineDrawingInfo = { drawingInfo: { renderer: { type: "simple", symbol: { type: "esriSLS", style: "esriSLSSolid", color: [165, 83, 183, 255], width: 1 } }, transparency: 0, labelingInfo: null } }; - public static pointDrawingInfo = { drawingInfo: { renderer: { type: "simple", symbol: { type: "esriPMS", url: "RedSphere.png", imageData: "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuNS4xTuc4+QAAB3VJREFUeF7tmPlTlEcexnve94U5mANQbgQSbgiHXHINlxpRIBpRI6wHorLERUmIisKCQWM8cqigESVQS1Kx1piNi4mW2YpbcZONrilE140RCTcy3DDAcL/zbJP8CYPDL+9Ufau7uqb7eZ7P+/a8PS8hwkcgIBAQCAgEBAICAYGAQEAgIBAQCAgEBAICAYGAQEAgIBAQCDx/AoowKXFMUhD3lQrioZaQRVRS+fxl51eBTZUTdZ41U1Rox13/0JF9csGJ05Qv4jSz/YPWohtvLmSKN5iTGGqTm1+rc6weICOBRbZs1UVnrv87T1PUeovxyNsUP9P6n5cpHtCxu24cbrmwKLdj+osWiqrVKhI0xzbmZ7m1SpJ+1pFpvE2DPvGTomOxAoNLLKGLscZYvB10cbYYjrJCb7A5mrxleOBqim+cWJRakZY0JfnD/LieI9V1MrKtwokbrAtU4Vm0A3TJnphJD4B+RxD0u0LA7w7FTE4oprOCMbklEGNrfdGf4IqnQTb4wc0MFTYibZqM7JgjO8ZdJkpMln/sKu16pHZGb7IfptIWg389DPp9kcChWODoMuDdBOhL1JgpisbUvghM7AqFbtNiaFP80RLnhbuBdqi0N+1dbUpWGde9gWpuhFi95yL7sS7BA93JAb+Fn8mh4QujgPeTgb9kAZf3Apd2A+fXQ38yHjOHozB1IAJjOSEY2RSIwVUv4dd4X9wJccGHNrJ7CYQ4GGjLeNNfM+dyvgpzQstKf3pbB2A6m97uBRE0/Ergcxr8hyqg7hrwn0vAtRIKIRX6Y2pMl0RhIj8co9nBGFrvh55l3ngU7YObng7IVnFvGS+BYUpmHziY/Ls2zgP9SX50by/G9N5w6I+ogYvpwK1SoOlHQNsGfWcd9Peqof88B/rTyzF9hAIopAByQzC0JQB9ST5oVnvhnt+LOGsprvUhxNIwa0aY7cGR6Cp7tr8+whkjawIxkRWC6YJI6N+lAKq3Qf/Tx+B77oGfaQc/8hB8w2Xwtw9Bf3kzZspXY/JIDEbfpAB2BKLvVV90Jvjgoac9vpRxE8kciTVCBMMkNirJ7k/tRHyjtxwjKV4Yp3t/6s+R4E+/DH3N6+BrS8E314Dvvg2+/Sb4hxfBf5sP/up2TF3ZhonK1zD6dhwGdwail26DzqgX8MRKiq9ZBpkSkmeYOyPM3m9Jjl+1Z9D8AgNtlAq6bZ70qsZi+q+bwV/7I/hbB8D/dAr8Axq89iz474p/G5++koHJy1sx/lkGdBc2YjA3HF0rHNHuboomuQj/5DgclIvOGCGCYRKFFuTMV7YUAD3VDQaLMfyqBcZORGPy01QKYSNm/rYV/Nd/Av9NHvgbueBrsjDzRQamKKDxT9Kgq1iLkbIUDOSHoiNcgnYHgnYZi+9ZExSbiSoMc2eE2flKcuJLa4KGRQz6/U0wlGaP0feiMH4uFpMXEjBVlYjp6lWY+SSZtim0kulYMiYuJEJXuhTDJ9UYPByOvoIwdCxfgE4bAo0Jh39xLAoVpMwIEQyTyFCQvGpLon9sJ0K3J4OBDDcMH1dj9FQsxkrjMPFRPCbOx2GyfLal9VEcxstioTulxjAFNfROJPqLl6Bnfyg6V7ugz5yBhuHwrZjBdiU5YJg7I8wOpifAKoVIW7uQ3rpOBH2b3ekVjYT2WCRG3o+mIGKgO0OrlIaebU/HYOQDNbQnojB4NJyGD0NPfjA0bwTRE6Q7hsUcWhkWN8yZqSQlWWGECAZLmJfJmbrvVSI8taK37xpbdB/wQW8xPee/8xIGjvlj8IQ/hk4G0JbWcX8MHPVDX4kveoq8ocn3xLM33NCZRcPHOGJYZIKfpQyq7JjHS6yJjcHujLHADgkpuC7h8F8zEVqXSNC2awE69lqhs8AamkO26HrbDt2H7dBVQov2NcW26CiwQtu+BWjdY4n2nZboTbfCmKcCnRyDO/YmyLPnDlHvjDH8G6zhS9/wlEnYR7X00fWrFYuWdVI0ZpuhcbcczW/R2qdAcz6t/bRov4mONeaaoYl+p22rHF0bVNAmKtBvweIXGxNcfFH8eNlC4m6wMWMusEnKpn5hyo48pj9gLe4SNG9QoGGLAk8z5XiaJUd99u8122/IpBA2K9BGg2vWWKAvRYVeLzEa7E1R422m2+MsSTem97nSYnfKyN6/mzATv7AUgqcMrUnmaFlLX3ysM0fj+t/b5lQLtK22QEfyAmiSLKFZpUJ7kBRPXKW4HqCYynWVHKSG2LkyZex1uO1mZM9lKem9Tx9jjY5iNEYo0bKMhn7ZAu0r6H5PpLXCAq0rKJClSjSGynE/QIkrQYqBPe6S2X+AJsY2Ped6iWZk6RlL0c2r5szofRsO9R5S1IfQLRCpQL1aifoYFerpsbkuTImaUJXuXIDiH6/Ys8vm3Mg8L2i20YqsO7fItKLcSXyn0kXccclVqv3MS6at9JU/Ox+ouns+SF6Z4cSupz7l8+z1ucs7LF1AQjOdxfGZzmx8Iu1TRcfnrioICAQEAgIBgYBAQCAgEBAICAQEAgIBgYBAQCAgEBAICAQEAv8H44b/6ZiGvGAAAAAASUVORK5CYII=", contentType: "image/png", width: 15, height: 15 } } } }; + }, + }; + public static polygonDrawingInfo = { + drawingInfo: { + renderer: { + type: "simple", + symbol: { + type: "esriSFS", + style: "esriSFSSolid", + color: [76, 129, 205, 191], + outline: { type: "esriSLS", style: "esriSLSSolid", color: [0, 0, 0, 255], width: 0.75 }, + }, + }, + transparency: 0, + labelingInfo: null, + }, + }; + public static lineDrawingInfo = { + drawingInfo: { + renderer: { type: "simple", symbol: { type: "esriSLS", style: "esriSLSSolid", color: [165, 83, 183, 255], width: 1 } }, + transparency: 0, + labelingInfo: null, + }, + }; + public static pointDrawingInfo = { + drawingInfo: { + renderer: { + type: "simple", + symbol: { + type: "esriPMS", + url: "RedSphere.png", + imageData: + "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGXRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuNS4xTuc4+QAAB3VJREFUeF7tmPlTlEcexnve94U5mANQbgQSbgiHXHINlxpRIBpRI6wHorLERUmIisKCQWM8cqigESVQS1Kx1piNi4mW2YpbcZONrilE140RCTcy3DDAcL/zbJP8CYPDL+9Ufau7uqb7eZ7P+/a8PS8hwkcgIBAQCAgEBAICAYGAQEAgIBAQCAgEBAICAYGAQEAgIBAQCDx/AoowKXFMUhD3lQrioZaQRVRS+fxl51eBTZUTdZ41U1Rox13/0JF9csGJ05Qv4jSz/YPWohtvLmSKN5iTGGqTm1+rc6weICOBRbZs1UVnrv87T1PUeovxyNsUP9P6n5cpHtCxu24cbrmwKLdj+osWiqrVKhI0xzbmZ7m1SpJ+1pFpvE2DPvGTomOxAoNLLKGLscZYvB10cbYYjrJCb7A5mrxleOBqim+cWJRakZY0JfnD/LieI9V1MrKtwokbrAtU4Vm0A3TJnphJD4B+RxD0u0LA7w7FTE4oprOCMbklEGNrfdGf4IqnQTb4wc0MFTYibZqM7JgjO8ZdJkpMln/sKu16pHZGb7IfptIWg389DPp9kcChWODoMuDdBOhL1JgpisbUvghM7AqFbtNiaFP80RLnhbuBdqi0N+1dbUpWGde9gWpuhFi95yL7sS7BA93JAb+Fn8mh4QujgPeTgb9kAZf3Apd2A+fXQ38yHjOHozB1IAJjOSEY2RSIwVUv4dd4X9wJccGHNrJ7CYQ4GGjLeNNfM+dyvgpzQstKf3pbB2A6m97uBRE0/Ergcxr8hyqg7hrwn0vAtRIKIRX6Y2pMl0RhIj8co9nBGFrvh55l3ngU7YObng7IVnFvGS+BYUpmHziY/Ls2zgP9SX50by/G9N5w6I+ogYvpwK1SoOlHQNsGfWcd9Peqof88B/rTyzF9hAIopAByQzC0JQB9ST5oVnvhnt+LOGsprvUhxNIwa0aY7cGR6Cp7tr8+whkjawIxkRWC6YJI6N+lAKq3Qf/Tx+B77oGfaQc/8hB8w2Xwtw9Bf3kzZspXY/JIDEbfpAB2BKLvVV90Jvjgoac9vpRxE8kciTVCBMMkNirJ7k/tRHyjtxwjKV4Yp3t/6s+R4E+/DH3N6+BrS8E314Dvvg2+/Sb4hxfBf5sP/up2TF3ZhonK1zD6dhwGdwail26DzqgX8MRKiq9ZBpkSkmeYOyPM3m9Jjl+1Z9D8AgNtlAq6bZ70qsZi+q+bwV/7I/hbB8D/dAr8Axq89iz474p/G5++koHJy1sx/lkGdBc2YjA3HF0rHNHuboomuQj/5DgclIvOGCGCYRKFFuTMV7YUAD3VDQaLMfyqBcZORGPy01QKYSNm/rYV/Nd/Av9NHvgbueBrsjDzRQamKKDxT9Kgq1iLkbIUDOSHoiNcgnYHgnYZi+9ZExSbiSoMc2eE2flKcuJLa4KGRQz6/U0wlGaP0feiMH4uFpMXEjBVlYjp6lWY+SSZtim0kulYMiYuJEJXuhTDJ9UYPByOvoIwdCxfgE4bAo0Jh39xLAoVpMwIEQyTyFCQvGpLon9sJ0K3J4OBDDcMH1dj9FQsxkrjMPFRPCbOx2GyfLal9VEcxstioTulxjAFNfROJPqLl6Bnfyg6V7ugz5yBhuHwrZjBdiU5YJg7I8wOpifAKoVIW7uQ3rpOBH2b3ekVjYT2WCRG3o+mIGKgO0OrlIaebU/HYOQDNbQnojB4NJyGD0NPfjA0bwTRE6Q7hsUcWhkWN8yZqSQlWWGECAZLmJfJmbrvVSI8taK37xpbdB/wQW8xPee/8xIGjvlj8IQ/hk4G0JbWcX8MHPVDX4kveoq8ocn3xLM33NCZRcPHOGJYZIKfpQyq7JjHS6yJjcHujLHADgkpuC7h8F8zEVqXSNC2awE69lqhs8AamkO26HrbDt2H7dBVQov2NcW26CiwQtu+BWjdY4n2nZboTbfCmKcCnRyDO/YmyLPnDlHvjDH8G6zhS9/wlEnYR7X00fWrFYuWdVI0ZpuhcbcczW/R2qdAcz6t/bRov4mONeaaoYl+p22rHF0bVNAmKtBvweIXGxNcfFH8eNlC4m6wMWMusEnKpn5hyo48pj9gLe4SNG9QoGGLAk8z5XiaJUd99u8122/IpBA2K9BGg2vWWKAvRYVeLzEa7E1R422m2+MsSTem97nSYnfKyN6/mzATv7AUgqcMrUnmaFlLX3ysM0fj+t/b5lQLtK22QEfyAmiSLKFZpUJ7kBRPXKW4HqCYynWVHKSG2LkyZex1uO1mZM9lKem9Tx9jjY5iNEYo0bKMhn7ZAu0r6H5PpLXCAq0rKJClSjSGynE/QIkrQYqBPe6S2X+AJsY2Ped6iWZk6RlL0c2r5szofRsO9R5S1IfQLRCpQL1aifoYFerpsbkuTImaUJXuXIDiH6/Ys8vm3Mg8L2i20YqsO7fItKLcSXyn0kXccclVqv3MS6at9JU/Ox+ouns+SF6Z4cSupz7l8+z1ucs7LF1AQjOdxfGZzmx8Iu1TRcfnrioICAQEAgIBgYBAQCAgEBAICAQEAgIBgYBAQCAgEBAICAQEAv8H44b/6ZiGvGAAAAAASUVORK5CYII=", + contentType: "image/png", + width: 15, + height: 15, + }, + }, + }, + }; } - diff --git a/extensions/map-layers-formats/src/test/ArcGisFeature/TestUtils.ts b/extensions/map-layers-formats/src/test/ArcGisFeature/TestUtils.ts index f9ceabe8b0ae..497945da7dd0 100644 --- a/extensions/map-layers-formats/src/test/ArcGisFeature/TestUtils.ts +++ b/extensions/map-layers-formats/src/test/ArcGisFeature/TestUtils.ts @@ -9,10 +9,9 @@ import { ArcGisSymbologyCanvasRenderer } from "../../ArcGisFeature/ArcGisSymbolo import { EsriRenderer } from "../../ArcGisFeature/EsriSymbology"; /** -* @internal -*/ + * @internal + */ export class TestUtils { - public static async createSymbologyRenderer(geometryType: ArcGisFeatureGeometryType, rendererDef: any) { const defaultSymb = new DefaultArcGiSymbology(); await defaultSymb.initialize(); diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/CountriesDataset.ts b/extensions/map-layers-formats/src/test/OGCFeatures/CountriesDataset.ts index 96e000d80e94..12b2621ee94a 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/CountriesDataset.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/CountriesDataset.ts @@ -5,18 +5,357 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class CountriesDataset { - public static readonly landingPageUrl = "http://localhost:8081"; public static readonly collectionsUrl = "http://localhost:8081/collections"; public static readonly collectionUrl = "http://localhost:8081/collections/public.countries"; public static readonly collectionItemsUrl = "http://localhost:8081/collections/public.countries/items"; public static readonly queryablesUrl = "http://localhost:8081/collections/public.countries/queryables"; - public static readonly landingPage = {title:"TiPg: OGC Features and Tiles API",links:[{href:"http://localhost:8081/",rel:"self",type:"application/json",title:"Landing Page"},{href:"http://localhost:8081/api",rel:"service-desc",type:"application/vnd.oai.openapi+json;version=3.0",title:"the API definition (JSON)"},{href:"http://localhost:8081/api.html",rel:"service-doc",type:"text/html",title:"the API documentation"},{href:"http://localhost:8081/conformance",rel:"conformance",type:"application/json",title:"Conformance"},{href:"http://localhost:8081/collections",rel:"data",type:"application/json",title:"List of Collections"},{href:"http://localhost:8081/collections/{collectionId}",rel:"data",type:"application/json",title:"Collection metadata"},{href:"http://localhost:8081/collections/{collectionId}/queryables",rel:"queryables",type:"application/schema+json",title:"Collection queryables"},{href:"http://localhost:8081/collections/{collectionId}/items",rel:"data",type:"application/geo+json",title:"Collection Features"},{href:"http://localhost:8081/collections/{collectionId}/items/{itemId}",rel:"data",type:"application/geo+json",title:"Collection Feature"},{href:"http://localhost:8081/collections/{collectionId}/tiles/{z}/{x}/{y}",rel:"data",type:"application/vnd.mapbox-vector-tile",title:"Collection Vector Tiles"},{href:"http://localhost:8081/collections/{collectionId}/tiles",rel:"data",type:"application/json",title:"Collection TileSets"},{href:"http://localhost:8081/collections/{collectionId}/tiles/{tileMatrixSetId}",rel:"data",type:"application/json",title:"Collection TileSet"},{href:"http://localhost:8081/tileMatrixSets",rel:"data",type:"application/json",title:"TileMatrixSets"},{href:"http://localhost:8081/tileMatrixSets/{tileMatrixSetId}",rel:"data",type:"application/json",title:"TileMatrixSet"}]}; - public static readonly collections = {links:[{href:"http://localhost:8081/collections",rel:"self",type:"application/json"}],numberMatched:13,numberReturned:13,collections:[{id:"public.landsat_wrs",title:"public.landsat_wrs",links:[{href:"http://localhost:8081/collections/public.landsat_wrs",rel:"collection",type:"application/json"},{href:"http://localhost:8081/collections/public.landsat_wrs/items",rel:"items",type:"application/geo+json"},{href:"http://localhost:8081/collections/public.landsat_wrs/queryables",rel:"queryables",type:"application/schema+json"}],extent:{spatial:{bbox:[[-180.0,-82.64010620117188,180.0,82.64010620117188]],crs:"http://www.opengis.net/def/crs/OGC/1.3/CRS84"}},itemType:"feature",crs:["http://www.opengis.net/def/crs/OGC/1.3/CRS84"]},{id:"public.countries",title:"public.countries",links:[{href:"http://localhost:8081/collections/public.countries",rel:"collection",type:"application/json"},{href:"http://localhost:8081/collections/public.countries/items",rel:"items",type:"application/geo+json"},{href:"http://localhost:8081/collections/public.countries/queryables",rel:"queryables",type:"application/schema+json"}],extent:{spatial:{bbox:[[-180.0,-89.9989318847656,180.0,83.599609375]],crs:"http://www.opengis.net/def/crs/OGC/1.3/CRS84"}},itemType:"feature",crs:["http://www.opengis.net/def/crs/OGC/1.3/CRS84"]}]}; - public static readonly collection = {id:"public.countries",title:"public.countries",links:[{href:"http://localhost:8081/collections/public.countries",rel:"self",type:"application/json"},{href:"http://localhost:8081/collections/public.countries/items",rel:"items",type:"application/geo+json",title:"Items"},{href:"http://localhost:8081/collections/public.countries/items?f=csv",rel:"alternate",type:"text/csv",title:"Items (CSV)"},{href:"http://localhost:8081/collections/public.countries/items?f=geojsonseq",rel:"alternate",type:"application/geo+json-seq",title:"Items (GeoJSONSeq)"},{href:"http://localhost:8081/collections/public.countries/queryables",rel:"queryables",type:"application/schema+json",title:"Queryables"}],extent:{spatial:{bbox:[[-180.0,-89.9989318847656,180.0,83.599609375]],crs:"http://www.opengis.net/def/crs/OGC/1.3/CRS84"}},itemType:"feature",crs:["http://www.opengis.net/def/crs/OGC/1.3/CRS84"]}; - public static readonly queryables = {title:"public.countries",properties:{geom:{$ref:"https://geojson.org/schema/MultiPolygon.json"},abbrev:{name:"abbrev",type:"string"},abbrev_len:{name:"abbrev_len",type:"number"},adm0_a3:{name:"adm0_a3",type:"string"},adm0_a3_is:{name:"adm0_a3_is",type:"string"},adm0_a3_un:{name:"adm0_a3_un",type:"number"},adm0_a3_us:{name:"adm0_a3_us",type:"string"},adm0_a3_wb:{name:"adm0_a3_wb",type:"number"},adm0_dif:{name:"adm0_dif",type:"number"},admin:{name:"admin",type:"string"},brk_a3:{name:"brk_a3",type:"string"},brk_diff:{name:"brk_diff",type:"number"},brk_group:{name:"brk_group",type:"string"},brk_name:{name:"brk_name",type:"string"},continent:{name:"continent",type:"string"},economy:{name:"economy",type:"string"},featurecla:{name:"featurecla",type:"string"},fips_10_:{name:"fips_10_",type:"string"},formal_en:{name:"formal_en",type:"string"},formal_fr:{name:"formal_fr",type:"string"},gdp_md_est:{name:"gdp_md_est",type:"number"},gdp_year:{name:"gdp_year",type:"number"},geou_dif:{name:"geou_dif",type:"number"},geounit:{name:"geounit",type:"string"},gid:{name:"gid",type:"number"},gu_a3:{name:"gu_a3",type:"string"},homepart:{name:"homepart",type:"number"},income_grp:{name:"income_grp",type:"string"},iso_a2:{name:"iso_a2",type:"string"},iso_a3:{name:"iso_a3",type:"string"},iso_a3_eh:{name:"iso_a3_eh",type:"string"},iso_n3:{name:"iso_n3",type:"string"},labelrank:{name:"labelrank",type:"number"},lastcensus:{name:"lastcensus",type:"number"},level:{name:"level",type:"number"},long_len:{name:"long_len",type:"number"},mapcolor13:{name:"mapcolor13",type:"number"},mapcolor7:{name:"mapcolor7",type:"number"},mapcolor8:{name:"mapcolor8",type:"number"},mapcolor9:{name:"mapcolor9",type:"number"},max_label:{name:"max_label",type:"number"},min_label:{name:"min_label",type:"number"},min_zoom:{name:"min_zoom",type:"number"},name:{name:"name",type:"string"},name_alt:{name:"name_alt",type:"string"},name_ar:{name:"name_ar",type:"string"},name_bn:{name:"name_bn",type:"string"},name_ciawf:{name:"name_ciawf",type:"string"},name_de:{name:"name_de",type:"string"},name_el:{name:"name_el",type:"string"},name_en:{name:"name_en",type:"string"},name_es:{name:"name_es",type:"string"},name_fr:{name:"name_fr",type:"string"},name_hi:{name:"name_hi",type:"string"},name_hu:{name:"name_hu",type:"string"},name_id:{name:"name_id",type:"string"},name_it:{name:"name_it",type:"string"},name_ja:{name:"name_ja",type:"string"},name_ko:{name:"name_ko",type:"string"},name_len:{name:"name_len",type:"number"},name_long:{name:"name_long",type:"string"},name_nl:{name:"name_nl",type:"string"},name_pl:{name:"name_pl",type:"string"},name_pt:{name:"name_pt",type:"string"},name_ru:{name:"name_ru",type:"string"},name_sort:{name:"name_sort",type:"string"},name_sv:{name:"name_sv",type:"string"},name_tr:{name:"name_tr",type:"string"},name_vi:{name:"name_vi",type:"string"},name_zh:{name:"name_zh",type:"string"},ne_id:{name:"ne_id",type:"number"},note_adm0:{name:"note_adm0",type:"string"},note_brk:{name:"note_brk",type:"string"},pop_est:{name:"pop_est",type:"number"},pop_rank:{name:"pop_rank",type:"number"},pop_year:{name:"pop_year",type:"number"},postal:{name:"postal",type:"string"},region_un:{name:"region_un",type:"string"},region_wb:{name:"region_wb",type:"string"},scalerank:{name:"scalerank",type:"number"},sov_a3:{name:"sov_a3",type:"string"},sovereignt:{name:"sovereignt",type:"string"},su_a3:{name:"su_a3",type:"string"},su_dif:{name:"su_dif",type:"number"},subregion:{name:"subregion",type:"string"},subunit:{name:"subunit",type:"string"},tiny:{name:"tiny",type:"number"},type:{name:"type",type:"string"},un_a3:{name:"un_a3",type:"string"},wb_a2:{name:"wb_a2",type:"string"},wb_a3:{name:"wb_a3",type:"string"},wikidataid:{name:"wikidataid",type:"string"},wikipedia:{name:"wikipedia",type:"number"},woe_id:{name:"woe_id",type:"number"},woe_id_eh:{name:"woe_id_eh",type:"number"},woe_note:{name:"woe_note",type:"string"}},type:"object",$schema:"https://json-schema.org/draft/2019-09/schema",$id:"http://localhost:8081/collections/public.countries/queryables?f=schemajson"}; - public static readonly singleItem = {type:"FeatureCollection",id:"public.countries",title:"public.countries",description:"public.countries",numberMatched:241,numberReturned:1,links:[{title:"Collection",href:"http://localhost:8081/collections/public.countries",rel:"collection",type:"application/json"},{title:"Items",href:"http://localhost:8081/collections/public.countries/items?limit=1&offset=20&f=geojson",rel:"self",type:"application/geo+json"},{href:"http://localhost:8081/collections/public.countries/items?limit=1&offset=21&f=geojson",rel:"next",type:"application/geo+json",title:"Next page"},{href:"http://localhost:8081/collections/public.countries/items?limit=1&f=geojson&offset=19",rel:"prev",type:"application/geo+json",title:"Previous page"}],features:[{type:"Feature",geometry:{type:"MultiPolygon",coordinates:[[[[-128.290087891,-24.397363281],[-128.3,-24.412597656],[-128.320654297,-24.399707031],[-128.3421875,-24.370703125],[-128.350195312,-24.340234375],[-128.330126953,-24.323242188],[-128.303613281,-24.33359375],[-128.290820312,-24.364648438],[-128.290087891,-24.397363281]]]]},id:21,properties:{abbrev:"Pit. Is.",abbrev_len:8,adm0_a3:"PCN",adm0_a3_is:"PCN",adm0_a3_un:-99,adm0_a3_us:"PCN",adm0_a3_wb:-99,adm0_dif:1,admin:"Pitcairn Islands",brk_a3:"PCN",brk_diff:0,brk_group:null,brk_name:"Pitcairn Is.",continent:"Oceania",economy:"7. Least developed region",featurecla:"Admin-0 country",fips_10_:"PC",formal_en:"Pitcairn, Henderson, Ducie and Oeno Islands",formal_fr:null,gdp_md_est:0.0,gdp_year:2016,geou_dif:0,geounit:"Pitcairn Islands",gid:21,gu_a3:"PCN",homepart:-99,income_grp:"5. Low income",iso_a2:"PN",iso_a3:"PCN",iso_a3_eh:"PCN",iso_n3:"612",labelrank:4,lastcensus:-99,level:2,long_len:16,mapcolor13:3,mapcolor7:6,mapcolor8:6,mapcolor9:6,max_label:9.0,min_label:5.0,min_zoom:0.0,name:"Pitcairn Is.",name_alt:null,name_ar:"جزر بيتكيرن",name_bn:"পীটকেয়ার্ন দ্বীপপুঞ্জ",name_ciawf:"Pitcairn Islands",name_de:"Pitcairninseln",name_el:"Νήσοι Πίτκερν",name_en:"Pitcairn Islands",name_es:"Islas Pitcairn",name_fr:"Îles Pitcairn",name_hi:"पिटकेम द्वीप समूह",name_hu:"Pitcairn-szigetek",name_id:"Kepulauan Pitcairn",name_it:"Isole Pitcairn",name_ja:"ピトケアン諸島",name_ko:"핏케언 제도",name_len:12,name_long:"Pitcairn Islands",name_nl:"Pitcairneilanden",name_pl:"Pitcairn",name_pt:"Ilhas Pitcairn",name_ru:"Острова Питкэрн",name_sort:"Pitcairn Islands",name_sv:"Pitcairnöarna",name_tr:"Pitcairn Adaları",name_vi:"Quần đảo Pitcairn",name_zh:"皮特凯恩群岛",ne_id:1159320729,note_adm0:"U.K.",note_brk:null,pop_est:54,pop_rank:1,pop_year:2016,postal:"PN",region_un:"Oceania",region_wb:"East Asia & Pacific",scalerank:3,sov_a3:"GB1",sovereignt:"United Kingdom",su_a3:"PCN",su_dif:0,subregion:"Polynesia",subunit:"Pitcairn Islands",tiny:-99,type:"Dependency",un_a3:"612",wb_a2:"-99",wb_a3:"-99",wikidataid:"Q35672",wikipedia:-99,woe_id:23424918,woe_id_eh:23424918,woe_note:"Exact WOE match as country"},links:[{title:"Collection",href:"http://localhost:8081/collections/public.countries",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.countries/items/21",rel:"item",type:"application/geo+json"}]}]}; + public static readonly landingPage = { + title: "TiPg: OGC Features and Tiles API", + links: [ + { href: "http://localhost:8081/", rel: "self", type: "application/json", title: "Landing Page" }, + { + href: "http://localhost:8081/api", + rel: "service-desc", + type: "application/vnd.oai.openapi+json;version=3.0", + title: "the API definition (JSON)", + }, + { href: "http://localhost:8081/api.html", rel: "service-doc", type: "text/html", title: "the API documentation" }, + { href: "http://localhost:8081/conformance", rel: "conformance", type: "application/json", title: "Conformance" }, + { href: "http://localhost:8081/collections", rel: "data", type: "application/json", title: "List of Collections" }, + { href: "http://localhost:8081/collections/{collectionId}", rel: "data", type: "application/json", title: "Collection metadata" }, + { + href: "http://localhost:8081/collections/{collectionId}/queryables", + rel: "queryables", + type: "application/schema+json", + title: "Collection queryables", + }, + { href: "http://localhost:8081/collections/{collectionId}/items", rel: "data", type: "application/geo+json", title: "Collection Features" }, + { + href: "http://localhost:8081/collections/{collectionId}/items/{itemId}", + rel: "data", + type: "application/geo+json", + title: "Collection Feature", + }, + { + href: "http://localhost:8081/collections/{collectionId}/tiles/{z}/{x}/{y}", + rel: "data", + type: "application/vnd.mapbox-vector-tile", + title: "Collection Vector Tiles", + }, + { href: "http://localhost:8081/collections/{collectionId}/tiles", rel: "data", type: "application/json", title: "Collection TileSets" }, + { + href: "http://localhost:8081/collections/{collectionId}/tiles/{tileMatrixSetId}", + rel: "data", + type: "application/json", + title: "Collection TileSet", + }, + { href: "http://localhost:8081/tileMatrixSets", rel: "data", type: "application/json", title: "TileMatrixSets" }, + { href: "http://localhost:8081/tileMatrixSets/{tileMatrixSetId}", rel: "data", type: "application/json", title: "TileMatrixSet" }, + ], + }; + public static readonly collections = { + links: [{ href: "http://localhost:8081/collections", rel: "self", type: "application/json" }], + numberMatched: 13, + numberReturned: 13, + collections: [{ + id: "public.landsat_wrs", + title: "public.landsat_wrs", + links: [{ href: "http://localhost:8081/collections/public.landsat_wrs", rel: "collection", type: "application/json" }, { + href: "http://localhost:8081/collections/public.landsat_wrs/items", + rel: "items", + type: "application/geo+json", + }, { href: "http://localhost:8081/collections/public.landsat_wrs/queryables", rel: "queryables", type: "application/schema+json" }], + extent: { spatial: { bbox: [[-180.0, -82.64010620117188, 180.0, 82.64010620117188]], crs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84" } }, + itemType: "feature", + crs: ["http://www.opengis.net/def/crs/OGC/1.3/CRS84"], + }, { + id: "public.countries", + title: "public.countries", + links: [{ href: "http://localhost:8081/collections/public.countries", rel: "collection", type: "application/json" }, { + href: "http://localhost:8081/collections/public.countries/items", + rel: "items", + type: "application/geo+json", + }, { href: "http://localhost:8081/collections/public.countries/queryables", rel: "queryables", type: "application/schema+json" }], + extent: { spatial: { bbox: [[-180.0, -89.9989318847656, 180.0, 83.599609375]], crs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84" } }, + itemType: "feature", + crs: ["http://www.opengis.net/def/crs/OGC/1.3/CRS84"], + }], + }; + public static readonly collection = { + id: "public.countries", + title: "public.countries", + links: [ + { href: "http://localhost:8081/collections/public.countries", rel: "self", type: "application/json" }, + { href: "http://localhost:8081/collections/public.countries/items", rel: "items", type: "application/geo+json", title: "Items" }, + { href: "http://localhost:8081/collections/public.countries/items?f=csv", rel: "alternate", type: "text/csv", title: "Items (CSV)" }, + { + href: "http://localhost:8081/collections/public.countries/items?f=geojsonseq", + rel: "alternate", + type: "application/geo+json-seq", + title: "Items (GeoJSONSeq)", + }, + { + href: "http://localhost:8081/collections/public.countries/queryables", + rel: "queryables", + type: "application/schema+json", + title: "Queryables", + }, + ], + extent: { spatial: { bbox: [[-180.0, -89.9989318847656, 180.0, 83.599609375]], crs: "http://www.opengis.net/def/crs/OGC/1.3/CRS84" } }, + itemType: "feature", + crs: ["http://www.opengis.net/def/crs/OGC/1.3/CRS84"], + }; + public static readonly queryables = { + title: "public.countries", + properties: { + geom: { $ref: "https://geojson.org/schema/MultiPolygon.json" }, + abbrev: { name: "abbrev", type: "string" }, + abbrev_len: { name: "abbrev_len", type: "number" }, + adm0_a3: { name: "adm0_a3", type: "string" }, + adm0_a3_is: { name: "adm0_a3_is", type: "string" }, + adm0_a3_un: { name: "adm0_a3_un", type: "number" }, + adm0_a3_us: { name: "adm0_a3_us", type: "string" }, + adm0_a3_wb: { name: "adm0_a3_wb", type: "number" }, + adm0_dif: { name: "adm0_dif", type: "number" }, + admin: { name: "admin", type: "string" }, + brk_a3: { name: "brk_a3", type: "string" }, + brk_diff: { name: "brk_diff", type: "number" }, + brk_group: { name: "brk_group", type: "string" }, + brk_name: { name: "brk_name", type: "string" }, + continent: { name: "continent", type: "string" }, + economy: { name: "economy", type: "string" }, + featurecla: { name: "featurecla", type: "string" }, + fips_10_: { name: "fips_10_", type: "string" }, + formal_en: { name: "formal_en", type: "string" }, + formal_fr: { name: "formal_fr", type: "string" }, + gdp_md_est: { name: "gdp_md_est", type: "number" }, + gdp_year: { name: "gdp_year", type: "number" }, + geou_dif: { name: "geou_dif", type: "number" }, + geounit: { name: "geounit", type: "string" }, + gid: { name: "gid", type: "number" }, + gu_a3: { name: "gu_a3", type: "string" }, + homepart: { name: "homepart", type: "number" }, + income_grp: { name: "income_grp", type: "string" }, + iso_a2: { name: "iso_a2", type: "string" }, + iso_a3: { name: "iso_a3", type: "string" }, + iso_a3_eh: { name: "iso_a3_eh", type: "string" }, + iso_n3: { name: "iso_n3", type: "string" }, + labelrank: { name: "labelrank", type: "number" }, + lastcensus: { name: "lastcensus", type: "number" }, + level: { name: "level", type: "number" }, + long_len: { name: "long_len", type: "number" }, + mapcolor13: { name: "mapcolor13", type: "number" }, + mapcolor7: { name: "mapcolor7", type: "number" }, + mapcolor8: { name: "mapcolor8", type: "number" }, + mapcolor9: { name: "mapcolor9", type: "number" }, + max_label: { name: "max_label", type: "number" }, + min_label: { name: "min_label", type: "number" }, + min_zoom: { name: "min_zoom", type: "number" }, + name: { name: "name", type: "string" }, + name_alt: { name: "name_alt", type: "string" }, + name_ar: { name: "name_ar", type: "string" }, + name_bn: { name: "name_bn", type: "string" }, + name_ciawf: { name: "name_ciawf", type: "string" }, + name_de: { name: "name_de", type: "string" }, + name_el: { name: "name_el", type: "string" }, + name_en: { name: "name_en", type: "string" }, + name_es: { name: "name_es", type: "string" }, + name_fr: { name: "name_fr", type: "string" }, + name_hi: { name: "name_hi", type: "string" }, + name_hu: { name: "name_hu", type: "string" }, + name_id: { name: "name_id", type: "string" }, + name_it: { name: "name_it", type: "string" }, + name_ja: { name: "name_ja", type: "string" }, + name_ko: { name: "name_ko", type: "string" }, + name_len: { name: "name_len", type: "number" }, + name_long: { name: "name_long", type: "string" }, + name_nl: { name: "name_nl", type: "string" }, + name_pl: { name: "name_pl", type: "string" }, + name_pt: { name: "name_pt", type: "string" }, + name_ru: { name: "name_ru", type: "string" }, + name_sort: { name: "name_sort", type: "string" }, + name_sv: { name: "name_sv", type: "string" }, + name_tr: { name: "name_tr", type: "string" }, + name_vi: { name: "name_vi", type: "string" }, + name_zh: { name: "name_zh", type: "string" }, + ne_id: { name: "ne_id", type: "number" }, + note_adm0: { name: "note_adm0", type: "string" }, + note_brk: { name: "note_brk", type: "string" }, + pop_est: { name: "pop_est", type: "number" }, + pop_rank: { name: "pop_rank", type: "number" }, + pop_year: { name: "pop_year", type: "number" }, + postal: { name: "postal", type: "string" }, + region_un: { name: "region_un", type: "string" }, + region_wb: { name: "region_wb", type: "string" }, + scalerank: { name: "scalerank", type: "number" }, + sov_a3: { name: "sov_a3", type: "string" }, + sovereignt: { name: "sovereignt", type: "string" }, + su_a3: { name: "su_a3", type: "string" }, + su_dif: { name: "su_dif", type: "number" }, + subregion: { name: "subregion", type: "string" }, + subunit: { name: "subunit", type: "string" }, + tiny: { name: "tiny", type: "number" }, + type: { name: "type", type: "string" }, + un_a3: { name: "un_a3", type: "string" }, + wb_a2: { name: "wb_a2", type: "string" }, + wb_a3: { name: "wb_a3", type: "string" }, + wikidataid: { name: "wikidataid", type: "string" }, + wikipedia: { name: "wikipedia", type: "number" }, + woe_id: { name: "woe_id", type: "number" }, + woe_id_eh: { name: "woe_id_eh", type: "number" }, + woe_note: { name: "woe_note", type: "string" }, + }, + type: "object", + $schema: "https://json-schema.org/draft/2019-09/schema", + $id: "http://localhost:8081/collections/public.countries/queryables?f=schemajson", + }; + public static readonly singleItem = { + type: "FeatureCollection", + id: "public.countries", + title: "public.countries", + description: "public.countries", + numberMatched: 241, + numberReturned: 1, + links: [{ title: "Collection", href: "http://localhost:8081/collections/public.countries", rel: "collection", type: "application/json" }, { + title: "Items", + href: "http://localhost:8081/collections/public.countries/items?limit=1&offset=20&f=geojson", + rel: "self", + type: "application/geo+json", + }, { + href: "http://localhost:8081/collections/public.countries/items?limit=1&offset=21&f=geojson", + rel: "next", + type: "application/geo+json", + title: "Next page", + }, { + href: "http://localhost:8081/collections/public.countries/items?limit=1&f=geojson&offset=19", + rel: "prev", + type: "application/geo+json", + title: "Previous page", + }], + features: [{ + type: "Feature", + geometry: { + type: "MultiPolygon", + coordinates: [[[ + [-128.290087891, -24.397363281], + [-128.3, -24.412597656], + [-128.320654297, -24.399707031], + [-128.3421875, -24.370703125], + [-128.350195312, -24.340234375], + [-128.330126953, -24.323242188], + [-128.303613281, -24.33359375], + [-128.290820312, -24.364648438], + [-128.290087891, -24.397363281], + ]]], + }, + id: 21, + properties: { + abbrev: "Pit. Is.", + abbrev_len: 8, + adm0_a3: "PCN", + adm0_a3_is: "PCN", + adm0_a3_un: -99, + adm0_a3_us: "PCN", + adm0_a3_wb: -99, + adm0_dif: 1, + admin: "Pitcairn Islands", + brk_a3: "PCN", + brk_diff: 0, + brk_group: null, + brk_name: "Pitcairn Is.", + continent: "Oceania", + economy: "7. Least developed region", + featurecla: "Admin-0 country", + fips_10_: "PC", + formal_en: "Pitcairn, Henderson, Ducie and Oeno Islands", + formal_fr: null, + gdp_md_est: 0.0, + gdp_year: 2016, + geou_dif: 0, + geounit: "Pitcairn Islands", + gid: 21, + gu_a3: "PCN", + homepart: -99, + income_grp: "5. Low income", + iso_a2: "PN", + iso_a3: "PCN", + iso_a3_eh: "PCN", + iso_n3: "612", + labelrank: 4, + lastcensus: -99, + level: 2, + long_len: 16, + mapcolor13: 3, + mapcolor7: 6, + mapcolor8: 6, + mapcolor9: 6, + max_label: 9.0, + min_label: 5.0, + min_zoom: 0.0, + name: "Pitcairn Is.", + name_alt: null, + name_ar: "جزر بيتكيرن", + name_bn: "পীটকেয়ার্ন দ্বীপপুঞ্জ", + name_ciawf: "Pitcairn Islands", + name_de: "Pitcairninseln", + name_el: "Νήσοι Πίτκερν", + name_en: "Pitcairn Islands", + name_es: "Islas Pitcairn", + name_fr: "Îles Pitcairn", + name_hi: "पिटकेम द्वीप समूह", + name_hu: "Pitcairn-szigetek", + name_id: "Kepulauan Pitcairn", + name_it: "Isole Pitcairn", + name_ja: "ピトケアン諸島", + name_ko: "핏케언 제도", + name_len: 12, + name_long: "Pitcairn Islands", + name_nl: "Pitcairneilanden", + name_pl: "Pitcairn", + name_pt: "Ilhas Pitcairn", + name_ru: "Острова Питкэрн", + name_sort: "Pitcairn Islands", + name_sv: "Pitcairnöarna", + name_tr: "Pitcairn Adaları", + name_vi: "Quần đảo Pitcairn", + name_zh: "皮特凯恩群岛", + ne_id: 1159320729, + note_adm0: "U.K.", + note_brk: null, + pop_est: 54, + pop_rank: 1, + pop_year: 2016, + postal: "PN", + region_un: "Oceania", + region_wb: "East Asia & Pacific", + scalerank: 3, + sov_a3: "GB1", + sovereignt: "United Kingdom", + su_a3: "PCN", + su_dif: 0, + subregion: "Polynesia", + subunit: "Pitcairn Islands", + tiny: -99, + type: "Dependency", + un_a3: "612", + wb_a2: "-99", + wb_a3: "-99", + wikidataid: "Q35672", + wikipedia: -99, + woe_id: 23424918, + woe_id_eh: 23424918, + woe_note: "Exact WOE match as country", + }, + links: [{ title: "Collection", href: "http://localhost:8081/collections/public.countries", rel: "collection", type: "application/json" }, { + title: "Item", + href: "http://localhost:8081/collections/public.countries/items/21", + rel: "item", + type: "application/geo+json", + }], + }], + }; public static readonly urlsContent: { [key: string]: string } = { [CountriesDataset.landingPageUrl]: JSON.stringify(CountriesDataset.landingPage), @@ -26,4 +365,3 @@ export class CountriesDataset { [CountriesDataset.collectionItemsUrl]: JSON.stringify(CountriesDataset.singleItem), }; } - diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/GeoJSONGeometryReader.test.ts b/extensions/map-layers-formats/src/test/OGCFeatures/GeoJSONGeometryReader.test.ts index c347b1cecf56..19d436e371a2 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/GeoJSONGeometryReader.test.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/GeoJSONGeometryReader.test.ts @@ -3,13 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; +import { deflateCoordinates } from "@itwin/core-frontend"; import * as chai from "chai"; +import * as sinon from "sinon"; import { GeoJSONGeometryReader } from "../../GeoJSON/GeoJSONGeometryReader"; import { MockGeometryRenderer } from "./Mocks"; -import { deflateCoordinates } from "@itwin/core-frontend"; describe("GeoJSONGeometryReader", () => { - const sandbox = sinon.createSandbox(); afterEach(async () => { @@ -23,7 +22,7 @@ describe("GeoJSONGeometryReader", () => { const renderPathSpy = sandbox.spy(renderer, "renderPath"); const renderPointSpy = sandbox.spy(renderer, "renderPoint"); const coordinates = [10, -10]; - await reader.readGeometry({type: "Point", coordinates}); + await reader.readGeometry({ type: "Point", coordinates }); const getPointCalls = renderPointSpy.getCalls(); chai.expect(getPointCalls.length).to.be.equals(1); @@ -38,16 +37,16 @@ describe("GeoJSONGeometryReader", () => { const renderPathSpy = sandbox.spy(renderer, "renderPath"); const renderPointSpy = sandbox.spy(renderer, "renderPoint"); - const coordinates = [[10, -10], [11,-11]]; - await reader.readGeometry({type: "MultiPoint", coordinates}); + const coordinates = [[10, -10], [11, -11]]; + await reader.readGeometry({ type: "MultiPoint", coordinates }); const getPointCalls = renderPointSpy.getCalls(); chai.expect(getPointCalls.length).to.be.equals(1); - chai.expect(getPointCalls[0].args[0]).to.eql([1,1]); + chai.expect(getPointCalls[0].args[0]).to.eql([1, 1]); const flatCoords: number[] = []; deflateCoordinates(coordinates, flatCoords, 2, 0); - chai.expect(getPointCalls[0].args[1]).to.eql(flatCoords ); + chai.expect(getPointCalls[0].args[1]).to.eql(flatCoords); chai.expect(renderPathSpy.called).to.be.false; }); @@ -61,9 +60,10 @@ describe("GeoJSONGeometryReader", () => { [-10, -10], [10, -10], [10, 10], - [-10, -10]]; + [-10, -10], + ]; - await reader.readGeometry({type: "LineString", coordinates}); + await reader.readGeometry({ type: "LineString", coordinates }); const getPathsCalls = renderPathSpy.getCalls(); chai.expect(getPathsCalls.length).to.be.equals(1); @@ -95,7 +95,7 @@ describe("GeoJSONGeometryReader", () => { ], ]; - await reader.readGeometry({type: "MultiLineString", coordinates}); + await reader.readGeometry({ type: "MultiLineString", coordinates }); const getPathsCalls = renderPathSpy.getCalls(); chai.expect(getPathsCalls.length).to.be.equals(1); @@ -115,13 +115,15 @@ describe("GeoJSONGeometryReader", () => { await reader.readGeometry({ type: "Polygon", coordinates: [ - [ /* Ring 1 */ + [ + /* Ring 1 */ [-10, -10], [10, -10], [10, 10], [-10, -10], ], - [ /* Ring 2 */ + [ + /* Ring 2 */ [-5, -5], [5, -5], [5, 5], @@ -146,7 +148,8 @@ describe("GeoJSONGeometryReader", () => { await reader.readGeometry({ type: "MultiPolygon", coordinates: [ - [ /* Polygon 1 */ + [ + /* Polygon 1 */ [ [-10.0, -10.0], [10.0, -10.0], @@ -154,7 +157,8 @@ describe("GeoJSONGeometryReader", () => { [-10.0, -10.0], ], ], - [ /* Polygon 2 */ + [ + /* Polygon 2 */ [ [-10.0, -10.0], [10.0, -10.0], diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/Mocks.ts b/extensions/map-layers-formats/src/test/OGCFeatures/Mocks.ts index 484c11ab9ac2..7fde9fa82fe6 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/Mocks.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/Mocks.ts @@ -3,29 +3,39 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { FeatureAttributeDrivenSymbology, FeatureGeometryRenderer, FeatureSymbolizedRenderer, FeatureSymbologyRenderer, GraphicsGeometryRenderer } from "@itwin/core-frontend"; +import { + FeatureAttributeDrivenSymbology, + FeatureGeometryRenderer, + FeatureSymbolizedRenderer, + FeatureSymbologyRenderer, + GraphicsGeometryRenderer, +} from "@itwin/core-frontend"; import { Transform } from "@itwin/core-geometry"; export class MockGeometryRenderer implements FeatureGeometryRenderer { public transform: Transform | undefined; public attributeSymbology?: FeatureAttributeDrivenSymbology; - public hasSymbologyRenderer(): this is FeatureSymbolizedRenderer {return false;} + public hasSymbologyRenderer(): this is FeatureSymbolizedRenderer { + return false; + } public async renderPath(_geometryLengths: number[], _geometryCoords: number[], _fill: boolean, _stride: number, _relativeCoords: boolean) { - } public async renderPoint(_geometryLengths: number[], _geometryCoords: number[], _stride: number, _relativeCoords: boolean) { - } } export class MockGraphicsRenderer extends MockGeometryRenderer implements GraphicsGeometryRenderer { - public moveGraphics() {return [];} + public moveGraphics() { + return []; + } } export class MockFeatureSymbologyRenderer implements FeatureSymbologyRenderer, FeatureAttributeDrivenSymbology { - public isAttributeDriven(): this is FeatureAttributeDrivenSymbology {return true;} + public isAttributeDriven(): this is FeatureAttributeDrivenSymbology { + return true; + } public activeGeometryType = ""; - public activeFeatureAttributes: {[key: string]: any} = {}; + public activeFeatureAttributes: { [key: string]: any } = {}; public rendererFields: string[] = []; public setActiveFeatureAttributes(attributes: { [key: string]: any }) { this.activeFeatureAttributes = attributes; @@ -33,11 +43,12 @@ export class MockFeatureSymbologyRenderer implements FeatureSymbologyRenderer, F } export class FakeSymbGeomRenderer extends MockGeometryRenderer implements FeatureSymbolizedRenderer { - - public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer {return true;} + public override hasSymbologyRenderer(): this is FeatureSymbolizedRenderer { + return true; + } private _symbolRend = new MockFeatureSymbologyRenderer(); - public get symbolRenderer(): FeatureSymbologyRenderer { + public get symbolRenderer(): FeatureSymbologyRenderer { return this._symbolRend; } } diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesProvider.test.ts b/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesProvider.test.ts index 2621f692bb4d..c086743ef1e8 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesProvider.test.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesProvider.test.ts @@ -3,22 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import { DefaultOgcSymbology, OgcApiFeaturesProvider } from "../../OgcApiFeatures/OgcApiFeaturesProvider"; +import { base64StringToUint8Array } from "@itwin/core-bentley"; import { ImageMapLayerSettings, ImageSource, ImageSourceFormat } from "@itwin/core-common"; +import { MapCartoRectangle } from "@itwin/core-frontend"; import { expect } from "chai"; +import * as sinon from "sinon"; +import { DefaultOgcSymbology, OgcApiFeaturesProvider } from "../../OgcApiFeatures/OgcApiFeaturesProvider"; import { CountriesDataset } from "./CountriesDataset"; -import { MapCartoRectangle } from "@itwin/core-frontend"; -import { base64StringToUint8Array } from "@itwin/core-bentley"; - -function stubFetchMetadata(sandbox: sinon.SinonSandbox, urlContent: { [url: string]: string } ) { +function stubFetchMetadata(sandbox: sinon.SinonSandbox, urlContent: { [url: string]: string }) { return sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchMetadata").callsFake(async function _(url: unknown): Promise { return Promise.resolve(JSON.parse(urlContent[url as string])); }); } -const getTestSettings = (url: string, subLayers = [{id: "public.countries", name:"public.countries" }]) => { +const getTestSettings = (url: string, subLayers = [{ id: "public.countries", name: "public.countries" }]) => { return ImageMapLayerSettings.fromJSON({ name: "test", url, @@ -32,9 +31,11 @@ describe("OgcApiFeaturesProvider", () => { beforeEach(async () => { // need to be mocked otherwise tests hangs - sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake(function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { - (listener as any)(); - }); + sandbox.stub(HTMLImageElement.prototype, "addEventListener").callsFake( + function _(_type: string, listener: EventListenerOrEventListenerObject, _options?: boolean | AddEventListenerOptions) { + (listener as any)(); + }, + ); }); afterEach(async () => { @@ -42,7 +43,6 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize with valid collection metadata", async () => { - const settings = getTestSettings(CountriesDataset.collectionUrl, undefined); stubFetchMetadata(sandbox, CountriesDataset.urlsContent); @@ -64,7 +64,8 @@ describe("OgcApiFeaturesProvider", () => { // Check CartoRange is initialized const datasetBbox = CountriesDataset.collection.extent.spatial.bbox[0]; - expect(provider.cartoRange?.distanceToRange(MapCartoRectangle.fromDegrees(datasetBbox[0], datasetBbox[1], datasetBbox[2], datasetBbox[3]))).to.be.lessThan(0.000001); + expect(provider.cartoRange?.distanceToRange(MapCartoRectangle.fromDegrees(datasetBbox[0], datasetBbox[1], datasetBbox[2], datasetBbox[3]))).to.be + .lessThan(0.000001); // FetchAllItems should have been called expect(fetchAllItemsStub.called).to.be.true; @@ -90,11 +91,14 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize when a specific collection URL is passed and multiple subLayer ids are specified", async () => { - const settings = getTestSettings(CountriesDataset.collectionUrl, [{id: "public.countries", name:"public.countries" }, {id: "public.countries2", name:"public.countries2" }]); + const settings = getTestSettings(CountriesDataset.collectionUrl, [{ id: "public.countries", name: "public.countries" }, { + id: "public.countries2", + name: "public.countries2", + }]); const urlContent: { [key: string]: string } = {}; urlContent[CountriesDataset.collectionUrl] = JSON.stringify(CountriesDataset.collection); urlContent[CountriesDataset.queryablesUrl] = JSON.stringify(CountriesDataset.queryables); - stubFetchMetadata(sandbox, urlContent); + stubFetchMetadata(sandbox, urlContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { return false; }); @@ -110,13 +114,13 @@ describe("OgcApiFeaturesProvider", () => { const urlContent: { [key: string]: string } = {}; urlContent[CountriesDataset.collectionUrl] = JSON.stringify(CountriesDataset.collection); urlContent[CountriesDataset.queryablesUrl] = JSON.stringify(CountriesDataset.queryables); - stubFetchMetadata(sandbox, urlContent); + stubFetchMetadata(sandbox, urlContent); sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { return false; }); // Now test with an invalid sublayer Id - const settings = getTestSettings(CountriesDataset.collectionUrl, [{id: "bad", name:"bad" }]); + const settings = getTestSettings(CountriesDataset.collectionUrl, [{ id: "bad", name: "bad" }]); const provider = new OgcApiFeaturesProvider(settings); // Initialize should not throw since subLayer.Id != collection Id @@ -124,8 +128,7 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize with layer url set to items url", async () => { - - const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); + const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { return false; @@ -145,7 +148,6 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize with layer url set to collections url", async () => { - const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -168,18 +170,16 @@ describe("OgcApiFeaturesProvider", () => { }); it("should not initialize with layer url set to a collection url but invalid sub-layer", async () => { - stubFetchMetadata(sandbox, CountriesDataset.urlsContent); // Now test with an invalid sublayer Id - const settings = getTestSettings(CountriesDataset.collectionUrl, [{id: "bad", name:"bad" }]); + const settings = getTestSettings(CountriesDataset.collectionUrl, [{ id: "bad", name: "bad" }]); const provider = new OgcApiFeaturesProvider(settings); await expect(provider.initialize()).to.be.rejectedWith(Error, `Collection metadata and sub-layers id mismatch`); }); it("should initialize with layer url set to a collection url but no sub-layers", async () => { - const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -200,7 +200,6 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize with layer url set to a collection url and single valid sub-layer", async () => { - const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -221,7 +220,6 @@ describe("OgcApiFeaturesProvider", () => { }); it("should initialize with layer url set to landingPage url", async () => { - const stubMetadata = stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const fetchAllItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -242,22 +240,24 @@ describe("OgcApiFeaturesProvider", () => { expect(stubMetadata.getCall(3).args[0]).to.equals(CountriesDataset.queryablesUrl); }); - it("should fetch all items and follow next page links on initialize" , async () => { + it("should fetch all items and follow next page links on initialize", async () => { stubFetchMetadata(sandbox, CountriesDataset.urlsContent); - const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake(async function _(url: string, _timeoutMs?: number ) { - const obj = { - headers: { "content-type": "application/json" }, - json: async () => { - if (url.includes("offset")) - return undefined ; - else - return CountriesDataset.singleItem; - }, - status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need - return (obj as Response); - }); + const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake( + async function _(url: string, _timeoutMs?: number) { + const obj = { + headers: { "content-type": "application/json" }, + json: async () => { + if (url.includes("offset")) + return undefined; + else + return CountriesDataset.singleItem; + }, + status: 200, + } as unknown; // By using unknown type, I can define parts of Response I really need + return (obj as Response); + }, + ); // Now test with an invalid sublayer Id const settings = getTestSettings(CountriesDataset.collectionUrl); @@ -268,7 +268,7 @@ describe("OgcApiFeaturesProvider", () => { expect(tileRequestStub.getCall(1).args[0]).to.equals(CountriesDataset.singleItem.links[2].href); }); - it("should not make tile request in static mode" , async () => { + it("should not make tile request in static mode", async () => { stubFetchMetadata(sandbox, CountriesDataset.urlsContent); sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -278,19 +278,21 @@ describe("OgcApiFeaturesProvider", () => { return true; }); sandbox.stub(OgcApiFeaturesProvider.prototype, "staticMode").get(() => true); - const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake(async function _(url: string, _timeoutMs?: number ) { - const obj = { - headers: { "content-type": "application/json" }, - json: async () => { - if (url.includes("offset")) - return undefined ; - else - return CountriesDataset.singleItem; - }, - status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need - return (obj as Response); - }); + const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake( + async function _(url: string, _timeoutMs?: number) { + const obj = { + headers: { "content-type": "application/json" }, + json: async () => { + if (url.includes("offset")) + return undefined; + else + return CountriesDataset.singleItem; + }, + status: 200, + } as unknown; // By using unknown type, I can define parts of Response I really need + return (obj as Response); + }, + ); sandbox.stub(HTMLCanvasElement.prototype, "getContext").callsFake(function _(_contextId: any, _options?: any) { return {} as RenderingContext; @@ -308,7 +310,7 @@ describe("OgcApiFeaturesProvider", () => { expect(tileRequestStub.called).to.be.false; }); - it("should not make request while loading tile in static mode" , async () => { + it("should not make request while loading tile in static mode", async () => { stubFetchMetadata(sandbox, CountriesDataset.urlsContent); sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchAllItems").callsFake(async function _() { @@ -318,19 +320,21 @@ describe("OgcApiFeaturesProvider", () => { return true; }); sandbox.stub(OgcApiFeaturesProvider.prototype, "staticMode").get(() => true); - const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake(async function _(url: string, _timeoutMs?: number ) { - const obj = { - headers: { "content-type": "application/json" }, - json: async () => { - if (url.includes("offset")) - return undefined ; - else - return CountriesDataset.singleItem; - }, - status: 200, - } as unknown; // By using unknown type, I can define parts of Response I really need - return (obj as Response); - }); + const tileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake( + async function _(url: string, _timeoutMs?: number) { + const obj = { + headers: { "content-type": "application/json" }, + json: async () => { + if (url.includes("offset")) + return undefined; + else + return CountriesDataset.singleItem; + }, + status: 200, + } as unknown; // By using unknown type, I can define parts of Response I really need + return (obj as Response); + }, + ); sandbox.stub(HTMLCanvasElement.prototype, "getContext").callsFake(function _(_contextId: any, _options?: any) { return {} as RenderingContext; @@ -350,7 +354,7 @@ describe("OgcApiFeaturesProvider", () => { expect(indexStaticData.called).to.be.true; }); - it("should not make request while loading tile in non-static mode" , async () => { + it("should not make request while loading tile in non-static mode", async () => { stubFetchMetadata(sandbox, CountriesDataset.urlsContent); // By returning false we force the non-static mode @@ -358,9 +362,11 @@ describe("OgcApiFeaturesProvider", () => { return false; }); - const fetchItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchItems").callsFake(async function _(_url: unknown, _timeoutMs?: unknown ) { - return CountriesDataset.singleItem; - }); + const fetchItemsStub = sandbox.stub(OgcApiFeaturesProvider.prototype as any, "fetchItems").callsFake( + async function _(_url: unknown, _timeoutMs?: unknown) { + return CountriesDataset.singleItem; + }, + ); sandbox.stub(HTMLCanvasElement.prototype, "getContext").callsFake(function _(_contextId: any, _options?: any) { return {} as RenderingContext; @@ -383,7 +389,7 @@ describe("OgcApiFeaturesProvider", () => { expect(fetchItemsStub.getCall(0).args[0]).to.includes("collections/public.countries/items?bbox"); }); - it("should handle exceptions from makeTileRequest" , async () => { + it("should handle exceptions from makeTileRequest", async () => { stubFetchMetadata(sandbox, CountriesDataset.urlsContent); const makeTileRequestStub = sandbox.stub(OgcApiFeaturesProvider.prototype, "makeTileRequest").callsFake(async function _() { @@ -400,14 +406,14 @@ describe("OgcApiFeaturesProvider", () => { expect(makeTileRequestStub.getCalls().length).to.equals(2); }); - it("should create image source from data url" , async () => { + it("should create image source from data url", async () => { // Now test with an invalid sublayer Ida const settings = getTestSettings(CountriesDataset.collectionUrl); const provider = new OgcApiFeaturesProvider(settings); - const base64Png = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAiSURBVDhPY2RgYPgPxGQDJihNNhg1YNQAEBg1YOANYGAAAE1AAR90Oy6aAAAAAElFTkSuQmCC"; + const base64Png = + "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAAiSURBVDhPY2RgYPgPxGQDJihNNhg1YNQAEBg1YOANYGAAAE1AAR90Oy6aAAAAAElFTkSuQmCC"; const sampleDataUrl = `data:image/png;base64,${base64Png}`; const imageSource: ImageSource = (provider as any).createImageSourceFromDataURL(sampleDataUrl, ImageSourceFormat.Png); expect(imageSource.data).to.eql(base64StringToUint8Array(base64Png)); }); - }); diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesReader.test.ts b/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesReader.test.ts index 5552030ce2c6..8f9242fb6a4d 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesReader.test.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/OgcFeaturesReader.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import { expect } from "chai"; +import { ImageMapLayerSettings } from "@itwin/core-common"; import { MapLayerFeatureInfo } from "@itwin/core-frontend"; -import { OgcApiFeaturesReader, ReadOgcApiFeaturesInfoOptions } from "../../OgcApiFeatures/OgcApiFeaturesReader"; -import { PhillyDataset } from "./PhillyDataset"; -import { FakeSymbGeomRenderer, MockFeatureSymbologyRenderer, MockGeometryRenderer, MockGraphicsRenderer } from "./Mocks"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { GeoJSONGeometryReader } from "../../GeoJSON/GeoJSONGeometryReader"; -import { ImageMapLayerSettings } from "@itwin/core-common"; +import { OgcApiFeaturesReader, ReadOgcApiFeaturesInfoOptions } from "../../OgcApiFeatures/OgcApiFeaturesReader"; import { CountriesDataset } from "./CountriesDataset"; +import { FakeSymbGeomRenderer, MockFeatureSymbologyRenderer, MockGeometryRenderer, MockGraphicsRenderer } from "./Mocks"; +import { PhillyDataset } from "./PhillyDataset"; describe("OgcApiFeaturesReader", () => { const sandbox = sinon.createSandbox(); @@ -31,12 +31,10 @@ describe("OgcApiFeaturesReader", () => { }); it("should read multi features", async () => { - const reader = new OgcApiFeaturesReader(); const renderPathSpy = sandbox.spy(GeoJSONGeometryReader.prototype, "readGeometry"); await reader.readAndRender(PhillyDataset.multiItemPoint as any, new MockGeometryRenderer()); expect(renderPathSpy.getCalls().length).to.equals(PhillyDataset.multiItemPoint.features.length); - }); it("should read features and update the symbology renderer", async () => { @@ -46,13 +44,12 @@ describe("OgcApiFeaturesReader", () => { mockSymbRenderer.rendererFields = ["gid", "objectid"]; await reader.readAndRender(PhillyDataset.multiItemPoint as any, fakeGeomRenderer); expect(mockSymbRenderer.activeGeometryType).to.eqls("Point"); - const lastIdx = PhillyDataset.multiItemPoint.features.length -1; + const lastIdx = PhillyDataset.multiItemPoint.features.length - 1; expect(mockSymbRenderer.activeFeatureAttributes.gid).to.eqls(PhillyDataset.multiItemPoint.features[lastIdx].properties.gid); expect(mockSymbRenderer.activeFeatureAttributes.objectid).to.eqls(PhillyDataset.multiItemPoint.features[lastIdx].properties.objectid); }); it("should read features info", async () => { - const reader = new OgcApiFeaturesReader(); const layerSettings = ImageMapLayerSettings.fromJSON({ name: "test", @@ -76,7 +73,6 @@ describe("OgcApiFeaturesReader", () => { }); it("should read features info without geometry renderer", async () => { - const reader = new OgcApiFeaturesReader(); const layerSettings = ImageMapLayerSettings.fromJSON({ name: "test", diff --git a/extensions/map-layers-formats/src/test/OGCFeatures/PhillyDataset.ts b/extensions/map-layers-formats/src/test/OGCFeatures/PhillyDataset.ts index 47f9794cde2e..c32ce09bc066 100644 --- a/extensions/map-layers-formats/src/test/OGCFeatures/PhillyDataset.ts +++ b/extensions/map-layers-formats/src/test/OGCFeatures/PhillyDataset.ts @@ -5,8 +5,109 @@ /* eslint-disable @typescript-eslint/naming-convention */ export class PhillyDataset { - - public static readonly multiItemPoint = {type:"FeatureCollection",id:"public.phillytransportationimprovementproject",title:"public.phillytransportationimprovementproject",description:"public.phillytransportationimprovementproject",numberMatched:5629,numberReturned:5,links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Items",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items?limit=5&f=geojson",rel:"self",type:"application/geo+json"},{href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items?limit=5&f=geojson&offset=5",rel:"next",type:"application/geo+json",title:"Next page"}],features:[{type:"Feature",geometry:{type:"Point",coordinates:[-75.311238833,40.068862363]},id:1,properties:{gid:1,objectid:974619477.0},links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items/1",rel:"item",type:"application/geo+json"}]},{type:"Feature",geometry:{type:"Point",coordinates:[-75.245507088,40.019866491]},id:2,properties:{gid:2,objectid:974619555.0},links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items/2",rel:"item",type:"application/geo+json"}]},{type:"Feature",geometry:{type:"Point",coordinates:[-75.129881757,39.990804092]},id:3,properties:{gid:3,objectid:974619997.0},links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items/3",rel:"item",type:"application/geo+json"}]},{type:"Feature",geometry:{type:"Point",coordinates:[-75.245507088,40.019866491]},id:4,properties:{gid:4,objectid:974623572.0},links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items/4",rel:"item",type:"application/geo+json"}]},{type:"Feature",geometry:{type:"Point",coordinates:[-74.869829744,40.097060198]},id:5,properties:{gid:5,objectid:974624959.0},links:[{title:"Collection",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject",rel:"collection",type:"application/json"},{title:"Item",href:"http://localhost:8081/collections/public.phillytransportationimprovementproject/items/5",rel:"item",type:"application/geo+json"}]}]}; - + public static readonly multiItemPoint = { + type: "FeatureCollection", + id: "public.phillytransportationimprovementproject", + title: "public.phillytransportationimprovementproject", + description: "public.phillytransportationimprovementproject", + numberMatched: 5629, + numberReturned: 5, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Items", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items?limit=5&f=geojson", + rel: "self", + type: "application/geo+json", + }, { + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items?limit=5&f=geojson&offset=5", + rel: "next", + type: "application/geo+json", + title: "Next page", + }], + features: [{ + type: "Feature", + geometry: { type: "Point", coordinates: [-75.311238833, 40.068862363] }, + id: 1, + properties: { gid: 1, objectid: 974619477.0 }, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Item", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items/1", + rel: "item", + type: "application/geo+json", + }], + }, { + type: "Feature", + geometry: { type: "Point", coordinates: [-75.245507088, 40.019866491] }, + id: 2, + properties: { gid: 2, objectid: 974619555.0 }, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Item", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items/2", + rel: "item", + type: "application/geo+json", + }], + }, { + type: "Feature", + geometry: { type: "Point", coordinates: [-75.129881757, 39.990804092] }, + id: 3, + properties: { gid: 3, objectid: 974619997.0 }, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Item", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items/3", + rel: "item", + type: "application/geo+json", + }], + }, { + type: "Feature", + geometry: { type: "Point", coordinates: [-75.245507088, 40.019866491] }, + id: 4, + properties: { gid: 4, objectid: 974623572.0 }, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Item", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items/4", + rel: "item", + type: "application/geo+json", + }], + }, { + type: "Feature", + geometry: { type: "Point", coordinates: [-74.869829744, 40.097060198] }, + id: 5, + properties: { gid: 5, objectid: 974624959.0 }, + links: [{ + title: "Collection", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject", + rel: "collection", + type: "application/json", + }, { + title: "Item", + href: "http://localhost:8081/collections/public.phillytransportationimprovementproject/items/5", + rel: "item", + type: "application/geo+json", + }], + }], + }; } - diff --git a/extensions/test-extension/eslint.config.js b/extensions/test-extension/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/extensions/test-extension/eslint.config.js +++ b/extensions/test-extension/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/extensions/test-extension/package.json b/extensions/test-extension/package.json index 2914906a0743..e32d0beffe26 100644 --- a/extensions/test-extension/package.json +++ b/extensions/test-extension/package.json @@ -44,4 +44,4 @@ "activationEvents": [ "onStartup" ] -} \ No newline at end of file +} diff --git a/extensions/test-extension/src/SelectTool.ts b/extensions/test-extension/src/SelectTool.ts index ae2d92cdc3ae..b41f0fc4134f 100644 --- a/extensions/test-extension/src/SelectTool.ts +++ b/extensions/test-extension/src/SelectTool.ts @@ -5,21 +5,20 @@ /** @packageDocumentation * @module SelectionSet */ -import { - BeButtonEvent, CoordinateLockOverrides, EventHandled, LocateResponse, PrimitiveTool, ExtensionHost -} from "@itwin/core-extension"; +import { BeButtonEvent, CoordinateLockOverrides, EventHandled, ExtensionHost, LocateResponse, PrimitiveTool } from "@itwin/core-extension"; /** Minimalistic extension tool for a user to pick a set of elements of interest */ export class ExtensionSelectTool extends PrimitiveTool { - public static override toolId = "TestExtension.Select"; public static override iconSpec = "icon-cursor"; public static override hidden = false; public static override namespace = "ExampleTools"; - public override requireWriteableTarget(): boolean { return false; } - public override autoLockTarget(): void { } + public override requireWriteableTarget(): boolean { + return false; + } + public override autoLockTarget(): void {} protected provideToolAssistance(): void { // ### TODO: Tool assistance...supply the implementation! @@ -42,13 +41,19 @@ export class ExtensionSelectTool extends PrimitiveTool { return EventHandled.Yes; } - public override async onUnsuspend(): Promise { this.provideToolAssistance(); } - public override async onRestartTool(): Promise { this.exitTool(); } + public override async onUnsuspend(): Promise { + this.provideToolAssistance(); + } + public override async onRestartTool(): Promise { + this.exitTool(); + } public override async onPostInstall(): Promise { super.onPostInstall(); this.initTool(); } - public static async startTool(): Promise { return new ExtensionSelectTool().run(); } -} \ No newline at end of file + public static async startTool(): Promise { + return new ExtensionSelectTool().run(); + } +} diff --git a/extensions/test-extension/src/loader.ts b/extensions/test-extension/src/loader.ts index 465733d41c4a..7dae2a48326b 100644 --- a/extensions/test-extension/src/loader.ts +++ b/extensions/test-extension/src/loader.ts @@ -6,4 +6,4 @@ export default { manifest: import("../package.json"), loader: async () => (await import("./index.js")).default(), -} +}; diff --git a/extensions/test-extension/src/tsconfig.json b/extensions/test-extension/src/tsconfig.json index 605fe7734fbb..ccffa54a847e 100644 --- a/extensions/test-extension/src/tsconfig.json +++ b/extensions/test-extension/src/tsconfig.json @@ -17,4 +17,4 @@ "path": "../" } ] -} \ No newline at end of file +} diff --git a/extensions/test-extension/tsconfig.json b/extensions/test-extension/tsconfig.json index 5715adbcb879..c62df128b15e 100644 --- a/extensions/test-extension/tsconfig.json +++ b/extensions/test-extension/tsconfig.json @@ -9,4 +9,4 @@ "files": [ "package.json" ] -} \ No newline at end of file +} diff --git a/full-stack-tests/backend/eslint.config.js b/full-stack-tests/backend/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/full-stack-tests/backend/eslint.config.js +++ b/full-stack-tests/backend/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/full-stack-tests/backend/src/HubUtility.ts b/full-stack-tests/backend/src/HubUtility.ts index da91c9ecabde..945a8dfb0076 100644 --- a/full-stack-tests/backend/src/HubUtility.ts +++ b/full-stack-tests/backend/src/HubUtility.ts @@ -3,19 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; -import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; import { IModelHost, IModelJsFs, IModelNative, V1CheckpointManager } from "@itwin/core-backend"; import { AccessToken, ChangeSetStatus, GuidString, Logger, OpenMode, PerfLogger } from "@itwin/core-bentley"; import { BriefcaseIdValue, ChangesetFileProps, ChangesetProps } from "@itwin/core-common"; +import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; import { TestUserCredentials, TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; +import * as path from "path"; /** the types of users available for tests */ export enum TestUserType { Regular, Manager, Super, - SuperManager + SuperManager, } /** Utility to work with test iModels in the iModelHub */ @@ -116,7 +116,12 @@ export class HubUtility { const latestChangesetIndex = latestIndex; // Query results include latest specified change set const perfLogger = new PerfLogger("HubUtility.downloadChangesets -> Download Changesets"); - await IModelHost.hubAccess.downloadChangesets({ accessToken, iModelId, range: { first: earliestChangesetIndex, end: latestChangesetIndex }, targetDir: changesetsPath }); + await IModelHost.hubAccess.downloadChangesets({ + accessToken, + iModelId, + range: { first: earliestChangesetIndex, end: latestChangesetIndex }, + targetDir: changesetsPath, + }); perfLogger.dispose(); return changesets; } @@ -124,7 +129,13 @@ export class HubUtility { /** Download an iModel's seed file and changesets from the Hub. * A standard hierarchy of folders is created below the supplied downloadDir */ - public static async downloadIModelById(accessToken: AccessToken, iTwinId: string, iModelId: GuidString, downloadDir: string, reDownload: boolean): Promise { + public static async downloadIModelById( + accessToken: AccessToken, + iTwinId: string, + iModelId: GuidString, + downloadDir: string, + reDownload: boolean, + ): Promise { // Recreate the download folder if necessary if (reDownload) { if (IModelJsFs.existsSync(downloadDir)) @@ -163,7 +174,13 @@ export class HubUtility { /** Download an IModel's seed files and change sets from the Hub. * A standard hierarchy of folders is created below the supplied downloadDir */ - public static async downloadIModelByName(accessToken: AccessToken, iTwinName: string, iModelName: string, downloadDir: string, reDownload: boolean): Promise { + public static async downloadIModelByName( + accessToken: AccessToken, + iTwinName: string, + iModelName: string, + downloadDir: string, + reDownload: boolean, + ): Promise { const iTwinId = await HubUtility.getITwinIdByName(accessToken, iTwinName); const iModelId = await IModelHost.hubAccess.queryIModelByName({ accessToken, iTwinId, iModelName }); @@ -288,13 +305,14 @@ export class HubUtility { return iModelPathname; } - } /** An implementation of TestITwin backed by an iTwin */ class TestITwin { - public get isIModelHub(): boolean { return true; } - public terminate(): void { } + public get isIModelHub(): boolean { + return true; + } + public terminate(): void {} private static _iTwinAccessClient?: ITwinsAccessClient; diff --git a/full-stack-tests/backend/src/integration/ApplyChangeSets.test.ts b/full-stack-tests/backend/src/integration/ApplyChangeSets.test.ts index b801d6011fa6..4cbb4d28fb9a 100644 --- a/full-stack-tests/backend/src/integration/ApplyChangeSets.test.ts +++ b/full-stack-tests/backend/src/integration/ApplyChangeSets.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; import { IModelHost, IModelJsFs, IModelJsNative, IModelNative } from "@itwin/core-backend"; import { AccessToken, ChangeSetStatus, GuidString, Logger, OpenMode, PerfLogger } from "@itwin/core-bentley"; import { ChangesetFileProps, ChangesetType } from "@itwin/core-common"; import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; +import { assert } from "chai"; +import * as path from "path"; import { HubUtility } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -94,7 +94,11 @@ function applyChangesetsToNativeDb(nativeDb: IModelJsNative.DgnDb, changeSets: C let count = 0; for (const changeSet of changeSets) { ++count; - Logger.logInfo(HubUtility.logCategory, `Started applying Changeset: ${count} of ${changeSets.length} (${new Date(Date.now()).toString()})`, () => ({ ...changeSet })); + Logger.logInfo( + HubUtility.logCategory, + `Started applying Changeset: ${count} of ${changeSets.length} (${new Date(Date.now()).toString()})`, + () => ({ ...changeSet }), + ); try { nativeDb.applyChangeset(changeSet); Logger.logInfo(HubUtility.logCategory, "Successfully applied Changeset", () => ({ ...changeSet, status })); diff --git a/full-stack-tests/backend/src/integration/AzuriteTest.ts b/full-stack-tests/backend/src/integration/AzuriteTest.ts index feef4f2add7f..d2128fd5f3da 100644 --- a/full-stack-tests/backend/src/integration/AzuriteTest.ts +++ b/full-stack-tests/backend/src/integration/AzuriteTest.ts @@ -3,26 +3,27 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { emptyDirSync, mkdirsSync } from "fs-extra"; -import { join } from "path"; import * as azureBlob from "@azure/storage-blob"; import { BlobContainer, CloudSqlite, IModelHost, SettingsContainer } from "@itwin/core-backend"; import { AccessToken, Guid } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; +import { expect } from "chai"; import * as crypto from "crypto"; +import { emptyDirSync, mkdirsSync } from "fs-extra"; +import { join } from "path"; // spell:ignore imodelid itwinid mkdirs devstoreaccount racwdl export namespace AzuriteTest { - export const storageType = "azure" as const; export const httpAddr = "127.0.0.1:10000"; export const accountName = "devstoreaccount1"; export const baseUri = `http://${httpAddr}/${accountName}`; export const getContainerUri = (id: string) => `${baseUri}/${id}`; - const pipeline = azureBlob.newPipeline(new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")); + const pipeline = azureBlob.newPipeline( + new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="), + ); export const createAzClient = (id: string) => new azureBlob.ContainerClient(getContainerUri(id), pipeline); export let userToken: AccessToken; @@ -94,7 +95,12 @@ export namespace AzuriteTest { emptyDirSync(name); }; - export interface TestContainerProps { containerId: string, logId?: string, isPublic?: boolean, writeable?: boolean } + export interface TestContainerProps { + containerId: string; + logId?: string; + isPublic?: boolean; + writeable?: boolean; + } export const makeContainer = async (arg: TestContainerProps): Promise => { const containerProps = { ...arg, writeable: true, baseUri, storageType }; @@ -115,7 +121,6 @@ export namespace AzuriteTest { const cacheDir = join(IModelHost.cacheDir, cacheName); makeEmptyDir(cacheDir); return CloudSqlite.CloudCaches.getCache({ cacheName, cacheDir }); - }; export const makeCaches = (names: string[]) => { const caches = []; @@ -124,7 +129,12 @@ export namespace AzuriteTest { return caches; }; - export const uploadFile = async (container: CloudSqlite.CloudContainer, cache: CloudSqlite.CloudCache, dbName: string, localFileName: LocalFileName) => { + export const uploadFile = async ( + container: CloudSqlite.CloudContainer, + cache: CloudSqlite.CloudCache, + dbName: string, + localFileName: LocalFileName, + ) => { expect(container.isConnected).false; container.connect(cache); expect(container.isConnected); @@ -239,7 +249,7 @@ export namespace AzuriteTest { token: sasUrl.split("?")[1], provider: "azure", expiration: expiresOn, - baseUri:azCont.url, + baseUri: azCont.url, }; }, }; diff --git a/full-stack-tests/backend/src/integration/BriefcaseManager.test.ts b/full-stack-tests/backend/src/integration/BriefcaseManager.test.ts index 52ec741ef9dd..109263f003f3 100644 --- a/full-stack-tests/backend/src/integration/BriefcaseManager.test.ts +++ b/full-stack-tests/backend/src/integration/BriefcaseManager.test.ts @@ -3,14 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + BriefcaseDb, + BriefcaseManager, + CheckpointManager, + IModelHost, + IModelJsFs, + RequestNewBriefcaseArg, + V2CheckpointManager, +} from "@itwin/core-backend"; +import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/index"; +import { AccessToken, BriefcaseStatus, GuidString, StopWatch } from "@itwin/core-bentley"; +import { BriefcaseIdValue, BriefcaseProps, IModelError, IModelVersion } from "@itwin/core-common"; import { assert, expect } from "chai"; import * as os from "os"; import * as readline from "readline"; import * as sinon from "sinon"; -import { AccessToken, BriefcaseStatus, GuidString, StopWatch } from "@itwin/core-bentley"; -import { BriefcaseIdValue, BriefcaseProps, IModelError, IModelVersion } from "@itwin/core-common"; -import { BriefcaseDb, BriefcaseManager, CheckpointManager, IModelHost, IModelJsFs, RequestNewBriefcaseArg, V2CheckpointManager } from "@itwin/core-backend"; -import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/index"; import { HubUtility, TestUserType } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -54,7 +62,7 @@ describe("BriefcaseManager", () => { iTwinId: testITwinId, iModelId: testIModelId, briefcaseId: BriefcaseIdValue.Unassigned, - asOf: {afterChangeSetId: changesetId}, + asOf: { afterChangeSetId: changesetId }, }; const props = await BriefcaseManager.downloadBriefcase(args); const iModel = await BriefcaseDb.open({ @@ -78,13 +86,23 @@ describe("BriefcaseManager", () => { }); it("should open and close an iModel from the Hub", async () => { - const iModel = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.first().toJSON(), deleteFirst: true }); + const iModel = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.first().toJSON(), + deleteFirst: true, + }); assert.exists(iModel, "No iModel returned from call to BriefcaseManager.open"); // Validate that the IModelDb is readonly assert(iModel.isReadonly, "iModel not set to Readonly mode"); - const expectedChangeSet = await IModelHost.hubAccess.getChangesetFromVersion({ version: IModelVersion.first(), accessToken, iModelId: readOnlyTestIModelId }); + const expectedChangeSet = await IModelHost.hubAccess.getChangesetFromVersion({ + version: IModelVersion.first(), + accessToken, + iModelId: readOnlyTestIModelId, + }); assert.strictEqual(iModel.changeset.id, expectedChangeSet.id); assert.strictEqual(iModel.changeset.id, expectedChangeSet.id); @@ -97,14 +115,29 @@ describe("BriefcaseManager", () => { }); it("should reuse checkpoints", async () => { - const iModel1 = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.named("FirstVersion").toJSON() }); + const iModel1 = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.named("FirstVersion").toJSON(), + }); assert.exists(iModel1, "No iModel returned from call to BriefcaseManager.open"); - const iModel2 = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.named("FirstVersion").toJSON() }); + const iModel2 = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.named("FirstVersion").toJSON(), + }); assert.exists(iModel2, "No iModel returned from call to BriefcaseManager.open"); assert.equal(iModel1, iModel2, "previously open briefcase was expected to be shared"); - const iModel3 = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.named("SecondVersion").toJSON() }); + const iModel3 = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.named("SecondVersion").toJSON(), + }); assert.exists(iModel3, "No iModel returned from call to BriefcaseManager.open"); assert.notEqual(iModel3, iModel2, "opening two different versions should not cause briefcases to be shared when the older one is open"); @@ -116,11 +149,21 @@ describe("BriefcaseManager", () => { iModel3.close(); assert.isTrue(IModelJsFs.existsSync(pathname3)); - const iModel4 = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.named("FirstVersion").toJSON() }); + const iModel4 = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.named("FirstVersion").toJSON(), + }); assert.exists(iModel4, "No iModel returned from call to BriefcaseManager.open"); assert.equal(iModel4.pathName, pathname2, "previously closed briefcase was expected to be shared"); - const iModel5 = await HubWrappers.openCheckpointUsingRpc({ accessToken, iTwinId: testITwinId, iModelId: readOnlyTestIModelId, asOf: IModelVersion.named("SecondVersion").toJSON() }); + const iModel5 = await HubWrappers.openCheckpointUsingRpc({ + accessToken, + iTwinId: testITwinId, + iModelId: readOnlyTestIModelId, + asOf: IModelVersion.named("SecondVersion").toJSON(), + }); assert.exists(iModel5, "No iModel returned from call to BriefcaseManager.open"); assert.equal(iModel5.pathName, pathname3, "previously closed briefcase was expected to be shared"); @@ -170,7 +213,11 @@ describe("BriefcaseManager", () => { console.log(`download took ${watch.elapsedSeconds} seconds`); const iModel = await BriefcaseDb.open({ fileName: props.fileName }); - await expect(BriefcaseManager.downloadBriefcase(args)).to.be.rejectedWith(IModelError, "already exists", "should not be able to download a briefcase if a file with that name already exists"); + await expect(BriefcaseManager.downloadBriefcase(args)).to.be.rejectedWith( + IModelError, + "already exists", + "should not be able to download a briefcase if a file with that name already exists", + ); await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); assert.isAbove(numProgressCalls, 0, "download progress called"); @@ -207,10 +254,9 @@ describe("BriefcaseManager", () => { const fileName = BriefcaseManager.getFileName(args); await BriefcaseManager.deleteBriefcaseFiles(fileName); sinon.stub(CheckpointManager, "downloadCheckpoint").throws(new Error("testError")); - const downloadPromise = BriefcaseManager.downloadBriefcase({...args, fileName}); + const downloadPromise = BriefcaseManager.downloadBriefcase({ ...args, fileName }); await expect(downloadPromise).to.eventually.be.rejectedWith("testError"); expect(IModelJsFs.existsSync(fileName)).to.be.false; sinon.restore(); }); - }); diff --git a/full-stack-tests/backend/src/integration/ChangeSummary.test.ts b/full-stack-tests/backend/src/integration/ChangeSummary.test.ts index 3a85a99afd9b..ba02138d331c 100644 --- a/full-stack-tests/backend/src/integration/ChangeSummary.test.ts +++ b/full-stack-tests/backend/src/integration/ChangeSummary.test.ts @@ -3,17 +3,32 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import { AccessToken, DbResult, GuidString, Id64, Id64String, PerfLogger } from "@itwin/core-bentley"; -import { - ChangedValueState, ChangeOpCode, ColorDef, IModel, IModelError, IModelVersion, QueryBinder, QueryRowFormat, SubCategoryAppearance, -} from "@itwin/core-common"; import { - BriefcaseDb, BriefcaseManager, ChangeSummary, ChangeSummaryManager, ECSqlStatement, ElementOwnsChildElements, IModelHost, IModelJsFs, + BriefcaseDb, + BriefcaseManager, + ChangeSummary, + ChangeSummaryManager, + ECSqlStatement, + ElementOwnsChildElements, + IModelHost, + IModelJsFs, SpatialCategory, } from "@itwin/core-backend"; import { HubWrappers, IModelTestUtils, KnownTestLocations, TestChangeSetUtility } from "@itwin/core-backend/lib/cjs/test/index"; +import { AccessToken, DbResult, GuidString, Id64, Id64String, PerfLogger } from "@itwin/core-bentley"; +import { + ChangedValueState, + ChangeOpCode, + ColorDef, + IModel, + IModelError, + IModelVersion, + QueryBinder, + QueryRowFormat, + SubCategoryAppearance, +} from "@itwin/core-common"; +import { assert } from "chai"; +import * as path from "path"; import { HubUtility, TestUserType } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -44,22 +59,34 @@ function getChangeSummaryAsJson(iModel: BriefcaseDb, changeSummaryId: string) { switch (instanceChange.opCode) { case ChangeOpCode.Insert: { - const rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterInsert)); + const rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterInsert), + ); assert.equal(rows.length, 1); instanceChange.after = rows[0]; break; } case ChangeOpCode.Update: { - let rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate)); + let rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate), + ); assert.equal(rows.length, 1); instanceChange.before = rows[0]; - rows = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterUpdate)); + rows = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterUpdate), + ); assert.equal(rows.length, 1); instanceChange.after = rows[0]; break; } case ChangeOpCode.Delete: { - const rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeDelete)); + const rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeDelete), + ); assert.equal(rows.length, 1); instanceChange.before = rows[0]; break; @@ -115,26 +142,31 @@ describe("ChangeSummary", () => { rowCount++; const row: any = myStmt.getRow(); assert.equal(row.className, "ECDbChange.ChangeSummary"); - assert.isUndefined(row.extendedProperties, "ChangeSummary.ExtendedProperties is not expected to be populated when change summaries are extracted."); - } - assert.isAtLeast(rowCount, 3); - }); - - iModel.withPreparedStatement("SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", (myStmt) => { - let rowCount: number = 0; - while (myStmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row: any = myStmt.getRow(); - assert.equal(row.className, "IModelChange.ChangeSet"); - assert.equal(row.summary.id, summaryIds[rowCount - 1]); - assert.equal(row.summary.relClassName, "IModelChange.ChangeSummaryIsExtractedFromChangeset"); - assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); - assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); - // the other properties are not used, but using them in the ECSQL is important to verify preparation works + assert.isUndefined( + row.extendedProperties, + "ChangeSummary.ExtendedProperties is not expected to be populated when change summaries are extracted.", + ); } assert.isAtLeast(rowCount, 3); }); + iModel.withPreparedStatement( + "SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", + (myStmt) => { + let rowCount: number = 0; + while (myStmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row: any = myStmt.getRow(); + assert.equal(row.className, "IModelChange.ChangeSet"); + assert.equal(row.summary.id, summaryIds[rowCount - 1]); + assert.equal(row.summary.relClassName, "IModelChange.ChangeSummaryIsExtractedFromChangeset"); + assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); + assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); + // the other properties are not used, but using them in the ECSQL is important to verify preparation works + } + assert.isAtLeast(rowCount, 3); + }, + ); } finally { await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); } @@ -212,36 +244,49 @@ describe("ChangeSummary", () => { const firstChangeSet = changesets[0]; const lastChangeSet = changesets[1]; - const summaryIds = await ChangeSummaryManager.createChangeSummaries({ accessToken, iTwinId, iModelId, range: { first: firstChangeSet.index, end: lastChangeSet.index } }); + const summaryIds = await ChangeSummaryManager.createChangeSummaries({ + accessToken, + iTwinId, + iModelId, + range: { first: firstChangeSet.index, end: lastChangeSet.index }, + }); assert.equal(summaryIds.length, 2); assert.isTrue(IModelJsFs.existsSync(BriefcaseManager.getChangeCachePathName(iModelId))); - const iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken, iTwinId, iModelId, asOf: IModelVersion.asOfChangeSet(lastChangeSet.id).toJSON() }); + const iModel = await HubWrappers.downloadAndOpenBriefcase({ + accessToken, + iTwinId, + iModelId, + asOf: IModelVersion.asOfChangeSet(lastChangeSet.id).toJSON(), + }); try { assert.exists(iModel); ChangeSummaryManager.attachChangeCache(iModel); assert.isTrue(ChangeSummaryManager.isChangeCacheAttached(iModel)); - iModel.withPreparedStatement("SELECT WsgId, Summary, ParentWsgId, Description, PushDate, UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", (myStmt) => { - assert.equal(myStmt.step(), DbResult.BE_SQLITE_ROW); - let row: any = myStmt.getRow(); - assert.isDefined(row.wsgId); - // Change summaries are extracted from end to start, so order is inverse of changesets - assert.equal(row.wsgId, firstChangeSet.id); - assert.isDefined(row.summary); - assert.equal(row.summary.id, summaryIds[0]); - assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); - assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); - // the other properties are not used, but using them in the ECSQL is important to verify preparation works - assert.equal(myStmt.step(), DbResult.BE_SQLITE_ROW); - row = myStmt.getRow(); - assert.isDefined(row.wsgId); - assert.equal(row.wsgId, lastChangeSet.id); - assert.isDefined(row.summary); - assert.equal(row.summary.id, summaryIds[1]); - assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); - assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); - }); + iModel.withPreparedStatement( + "SELECT WsgId, Summary, ParentWsgId, Description, PushDate, UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", + (myStmt) => { + assert.equal(myStmt.step(), DbResult.BE_SQLITE_ROW); + let row: any = myStmt.getRow(); + assert.isDefined(row.wsgId); + // Change summaries are extracted from end to start, so order is inverse of changesets + assert.equal(row.wsgId, firstChangeSet.id); + assert.isDefined(row.summary); + assert.equal(row.summary.id, summaryIds[0]); + assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); + assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); + // the other properties are not used, but using them in the ECSQL is important to verify preparation works + assert.equal(myStmt.step(), DbResult.BE_SQLITE_ROW); + row = myStmt.getRow(); + assert.isDefined(row.wsgId); + assert.equal(row.wsgId, lastChangeSet.id); + assert.isDefined(row.summary); + assert.equal(row.summary.id, summaryIds[1]); + assert.isDefined(row.pushDate, "IModelChange.ChangeSet.PushDate is expected to be set for the changesets used in this test."); + assert.isDefined(row.userCreated, "IModelChange.ChangeSet.UserCreated is expected to be set for the changesets used in this test."); + }, + ); } finally { await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); } @@ -284,7 +329,12 @@ describe("ChangeSummary", () => { // now do second extraction for last changeset const lastChangesetId: string = changesets[changesets.length - 1].id; await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); - iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken, iTwinId, iModelId, asOf: IModelVersion.asOfChangeSet(lastChangesetId).toJSON() }); + iModel = await HubWrappers.downloadAndOpenBriefcase({ + accessToken, + iTwinId, + iModelId, + asOf: IModelVersion.asOfChangeSet(lastChangesetId).toJSON(), + }); // WIP not working yet until cache can be detached. // await iModel.pullChanges(accessToken, IModelVersion.asOfChangeSet(lastChangesetId)); @@ -294,19 +344,22 @@ describe("ChangeSummary", () => { ChangeSummaryManager.attachChangeCache(iModel); assert.isTrue(ChangeSummaryManager.isChangeCacheAttached(iModel)); - iModel.withPreparedStatement("SELECT cset.WsgId changesetId FROM change.ChangeSummary csum JOIN imodelchange.ChangeSet cset ON csum.ECInstanceId=cset.Summary.Id ORDER BY csum.ECInstanceId", (myStmt) => { - let rowCount: number = 0; - while (myStmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row: any = myStmt.getRow(); - assert.isDefined(row.changesetId); - if (rowCount === 1) - assert.equal(row.changesetId, firstChangesetId); - else if (rowCount === 2) - assert.equal(row.changesetId, lastChangesetId); - } - assert.equal(rowCount, 2); - }); + iModel.withPreparedStatement( + "SELECT cset.WsgId changesetId FROM change.ChangeSummary csum JOIN imodelchange.ChangeSet cset ON csum.ECInstanceId=cset.Summary.Id ORDER BY csum.ECInstanceId", + (myStmt) => { + let rowCount: number = 0; + while (myStmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row: any = myStmt.getRow(); + assert.isDefined(row.changesetId); + if (rowCount === 1) + assert.equal(row.changesetId, firstChangesetId); + else if (rowCount === 2) + assert.equal(row.changesetId, lastChangesetId); + } + assert.equal(rowCount, 2); + }, + ); } finally { iModel.close(); } @@ -358,22 +411,34 @@ describe("ChangeSummary", () => { const instanceChange: any = ChangeSummaryManager.queryInstanceChange(iModel, Id64.fromJSON(row.id)); switch (instanceChange.opCode) { case ChangeOpCode.Insert: { - const rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterInsert)); + const rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.AfterInsert), + ); assert.equal(rows.length, 1); instanceChange.after = rows[0]; break; } case ChangeOpCode.Update: { - let rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate)); + let rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate), + ); assert.equal(rows.length, 1); instanceChange.before = rows[0]; - rows = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate)); + rows = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeUpdate), + ); assert.equal(rows.length, 1); instanceChange.after = rows[0]; break; } case ChangeOpCode.Delete: { - const rows: any[] = IModelTestUtils.executeQuery(iModel, ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeDelete)); + const rows: any[] = IModelTestUtils.executeQuery( + iModel, + ChangeSummaryManager.buildPropertyValueChangesECSql(iModel, instanceChange, ChangedValueState.BeforeDelete), + ); assert.equal(rows.length, 1); instanceChange.before = rows[0]; break; @@ -409,9 +474,18 @@ describe("ChangeSummary", () => { // Populate the iModel with 3 elements const iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken: managerRequestContext, iTwinId: testITwinId, iModelId: testIModelId }); - const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(iModel, IModelTestUtils.getUniqueModelCode(iModel, "TestPhysicalModel"), true); + const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( + iModel, + IModelTestUtils.getUniqueModelCode(iModel, "TestPhysicalModel"), + true, + ); iModel.saveChanges("Added test model"); - const categoryId = SpatialCategory.insert(iModel, IModel.dictionaryId, "TestSpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + const categoryId = SpatialCategory.insert( + iModel, + IModel.dictionaryId, + "TestSpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); iModel.saveChanges("Added test category"); const elementId1: Id64String = iModel.elements.insertElement(IModelTestUtils.createPhysicalObject(iModel, modelId, categoryId).toJSON()); const elementId2: Id64String = iModel.elements.insertElement(IModelTestUtils.createPhysicalObject(iModel, modelId, categoryId).toJSON()); @@ -437,7 +511,12 @@ describe("ChangeSummary", () => { // Validate that the second change summary captures the change to the parent correctly try { - const changeSummaryIds = await ChangeSummaryManager.createChangeSummaries({ accessToken, iTwinId: iModel.iTwinId, iModelId, range: { first: 0 }}); + const changeSummaryIds = await ChangeSummaryManager.createChangeSummaries({ + accessToken, + iTwinId: iModel.iTwinId, + iModelId, + range: { first: 0 }, + }); assert.strictEqual(2, changeSummaryIds.length); ChangeSummaryManager.attachChangeCache(iModel); @@ -483,7 +562,11 @@ describe("ChangeSummary", () => { await testUtility.createTestIModel(); // User2 opens the iModel - const iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken: userContext2, iTwinId: testUtility.iTwinId, iModelId: testUtility.iModelId }); + const iModel = await HubWrappers.downloadAndOpenBriefcase({ + accessToken: userContext2, + iTwinId: testUtility.iTwinId, + iModelId: testUtility.iModelId, + }); // Attach change cache ChangeSummaryManager.attachChangeCache(iModel); @@ -495,7 +578,12 @@ describe("ChangeSummary", () => { // User2 applies the change set and extracts the change summary await iModel.pullChanges({ accessToken: userContext2 }); - const changeSummariesIds = await ChangeSummaryManager.createChangeSummaries({ accessToken: userContext2, iTwinId: iModel.iTwinId, iModelId: iModel.iModelId, range: { first: 0 }}); + const changeSummariesIds = await ChangeSummaryManager.createChangeSummaries({ + accessToken: userContext2, + iTwinId: iModel.iTwinId, + iModelId: iModel.iModelId, + range: { first: 0 }, + }); if (changeSummariesIds.length !== 1) throw new Error("ChangeSet summary extraction returned invalid ChangeSet summary IDs."); @@ -518,13 +606,20 @@ describe("ChangeSummary", () => { assert.strictEqual(isModelChange ? ChangeOpCode.Update : ChangeOpCode.Insert, changedInstanceOp); assert.isAbove(changedPropertyValueNames.length, 0); } - }); + }, + ); }); it("Detaching and reattaching change cache", async () => { setupTest(iModelId); const changesets = await IModelHost.hubAccess.queryChangesets({ accessToken, iModelId }); - const iModel = await HubWrappers.downloadAndOpenBriefcase({ accessToken, iTwinId, iModelId, asOf: IModelVersion.first().toJSON(), briefcaseId: 0 }); + const iModel = await HubWrappers.downloadAndOpenBriefcase({ + accessToken, + iTwinId, + iModelId, + asOf: IModelVersion.first().toJSON(), + briefcaseId: 0, + }); try { for (const changeset of changesets) { await iModel.pullChanges({ accessToken, toIndex: changeset.index }); @@ -544,7 +639,13 @@ describe("ChangeSummary", () => { assert.equal(row.summary.id, changeSummaryId); }); - for await (const row of iModel.createQueryReader("SELECT WsgId, Summary FROM imodelchange.ChangeSet WHERE Summary.Id=?", QueryBinder.from([changeSummaryId]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT WsgId, Summary FROM imodelchange.ChangeSet WHERE Summary.Id=?", + QueryBinder.from([changeSummaryId]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { assert.isDefined(row.wsgId); assert.equal(row.wsgId, changeset.id); assert.isDefined(row.summary); @@ -567,7 +668,13 @@ describe("ChangeSummary", () => { assert.equal(row.summary.id, changeSummaryId); }); - for await (const row of iModel.createQueryReader("SELECT WsgId, Summary FROM imodelchange.ChangeSet WHERE Summary.Id=?", QueryBinder.from([changeSummaryId]), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of iModel.createQueryReader( + "SELECT WsgId, Summary FROM imodelchange.ChangeSet WHERE Summary.Id=?", + QueryBinder.from([changeSummaryId]), + { rowFormat: QueryRowFormat.UseJsPropertyNames }, + ) + ) { assert.isDefined(row.wsgId); assert.equal(row.wsgId, changeset.id); assert.isDefined(row.summary); @@ -578,7 +685,6 @@ describe("ChangeSummary", () => { ChangeSummaryManager.detachChangeCache(iModel); assert.isFalse(ChangeSummaryManager.isChangeCacheAttached(iModel)); } - } finally { await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); } @@ -603,18 +709,20 @@ describe("ChangeSummary", () => { assert.isAtLeast(rowCount, 4); }); - iModel.withPreparedStatement("SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", (myStmt) => { - let rowCount: number = 0; - while (myStmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row: any = myStmt.getRow(); - assert.equal(row.className, "IModelChange.ChangeSet"); - assert.equal(row.summary.id, summaryIds[rowCount - 1]); - assert.equal(row.summary.relClassName, "IModelChange.ChangeSummaryIsExtractedFromChangeset"); - } - assert.isAtLeast(rowCount, 4); - }); - + iModel.withPreparedStatement( + "SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", + (myStmt) => { + let rowCount: number = 0; + while (myStmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row: any = myStmt.getRow(); + assert.equal(row.className, "IModelChange.ChangeSet"); + assert.equal(row.summary.id, summaryIds[rowCount - 1]); + assert.equal(row.summary.relClassName, "IModelChange.ChangeSummaryIsExtractedFromChangeset"); + } + assert.isAtLeast(rowCount, 4); + }, + ); } finally { ChangeSummaryManager.detachChangeCache(iModel); await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); @@ -642,17 +750,19 @@ describe("ChangeSummary", () => { assert.strictEqual(rowCount, 1); }); - iModel.withPreparedStatement("SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", (myStmt) => { - let rowCount: number = 0; - while (myStmt.step() === DbResult.BE_SQLITE_ROW) { - rowCount++; - const row: any = myStmt.getRow(); - assert.equal(row.className, "IModelChange.ChangeSet"); - assert.equal(row.summary.id, summaryIds[rowCount - 1]); - } - assert.strictEqual(rowCount, 1); - }); - + iModel.withPreparedStatement( + "SELECT ECClassId,Summary,WsgId,ParentWsgId,Description,PushDate,UserCreated FROM imodelchange.ChangeSet ORDER BY Summary.Id", + (myStmt) => { + let rowCount: number = 0; + while (myStmt.step() === DbResult.BE_SQLITE_ROW) { + rowCount++; + const row: any = myStmt.getRow(); + assert.equal(row.className, "IModelChange.ChangeSet"); + assert.equal(row.summary.id, summaryIds[rowCount - 1]); + } + assert.strictEqual(rowCount, 1); + }, + ); } finally { ChangeSummaryManager.detachChangeCache(iModel); await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); @@ -672,5 +782,4 @@ describe("ChangeSummary", () => { } assert.isTrue(errorThrown); }); - }); diff --git a/full-stack-tests/backend/src/integration/ChangedElements.test.ts b/full-stack-tests/backend/src/integration/ChangedElements.test.ts index 56652942b78b..26871a28ef52 100644 --- a/full-stack-tests/backend/src/integration/ChangedElements.test.ts +++ b/full-stack-tests/backend/src/integration/ChangedElements.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BriefcaseManager, ChangedElementsDb, IModelDb, IModelHost, IModelJsFs, ProcessChangesetOptions, SnapshotDb } from "@itwin/core-backend"; +import { ChangedElementsManager } from "@itwin/core-backend/lib/cjs/ChangedElementsManager"; +import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; import { AccessToken, DbResult, GuidString, OpenMode } from "@itwin/core-bentley"; import { IModelError, IModelVersion } from "@itwin/core-common"; import { Range3d } from "@itwin/core-geometry"; import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; import { assert } from "chai"; -import { BriefcaseManager, ChangedElementsDb, IModelDb, IModelHost, IModelJsFs, ProcessChangesetOptions, SnapshotDb } from "@itwin/core-backend"; -import { ChangedElementsManager } from "@itwin/core-backend/lib/cjs/ChangedElementsManager"; -import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; import { HubUtility } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -33,7 +33,12 @@ describe("ChangedElements", () => { if (IModelJsFs.existsSync(cacheFilePath)) IModelJsFs.removeSync(cacheFilePath); - const iModel = await HubWrappers.downloadAndOpenCheckpoint({ accessToken, iTwinId: testITwinId, iModelId: testIModelId, asOf: IModelVersion.first().toJSON() }); + const iModel = await HubWrappers.downloadAndOpenCheckpoint({ + accessToken, + iTwinId: testITwinId, + iModelId: testIModelId, + asOf: IModelVersion.first().toJSON(), + }); const changesets = await IModelHost.hubAccess.queryChangesets({ accessToken, iModelId: testIModelId }); assert.exists(iModel); @@ -168,7 +173,12 @@ describe("ChangedElements", () => { if (IModelJsFs.existsSync(cacheFilePath)) IModelJsFs.removeSync(cacheFilePath); - const iModel = await HubWrappers.downloadAndOpenCheckpoint({ accessToken, iTwinId: testITwinId, iModelId: testIModelId, asOf: IModelVersion.first().toJSON() }); + const iModel = await HubWrappers.downloadAndOpenCheckpoint({ + accessToken, + iTwinId: testITwinId, + iModelId: testIModelId, + asOf: IModelVersion.first().toJSON(), + }); const changesets = await IModelHost.hubAccess.queryChangesets({ accessToken, iModelId: testIModelId }); assert.exists(iModel); @@ -238,7 +248,12 @@ describe("ChangedElements", () => { if (IModelJsFs.existsSync(cacheFilePath)) IModelJsFs.removeSync(cacheFilePath); - const iModel = await HubWrappers.downloadAndOpenCheckpoint({ accessToken, iTwinId: testITwinId, iModelId: testIModelId, asOf: IModelVersion.first().toJSON() }); + const iModel = await HubWrappers.downloadAndOpenCheckpoint({ + accessToken, + iTwinId: testITwinId, + iModelId: testIModelId, + asOf: IModelVersion.first().toJSON(), + }); const changesets = await IModelHost.hubAccess.queryChangesets({ accessToken, iModelId: testIModelId }); assert.exists(iModel); @@ -308,7 +323,12 @@ describe("ChangedElements", () => { if (IModelJsFs.existsSync(cacheFilePath)) IModelJsFs.removeSync(cacheFilePath); - let iModel: IModelDb = await HubWrappers.downloadAndOpenCheckpoint({ accessToken, iTwinId: testITwinId, iModelId: testIModelId, asOf: IModelVersion.first().toJSON() }); + let iModel: IModelDb = await HubWrappers.downloadAndOpenCheckpoint({ + accessToken, + iTwinId: testITwinId, + iModelId: testIModelId, + asOf: IModelVersion.first().toJSON(), + }); const changesets = await IModelHost.hubAccess.queryChangesets({ accessToken, iModelId: testIModelId }); const startChangesetId = changesets[0].id; const endChangesetId = changesets[changesets.length - 1].id; @@ -352,10 +372,12 @@ describe("ChangedElements", () => { assert.isTrue(models!.modelIds.length !== 0); assert.isTrue(models!.modelIds.length === models!.bboxes.length); // We should be able to find some bounding boxes for geometric models that are not [0,0,0] due to wantBoundingBoxes = true - assert.isTrue(models!.bboxes.filter((bbox) => { - const range = Range3d.fromJSON(bbox); - return !range.isAlmostZeroX || !range.isAlmostZeroY || !range.isAlmostZeroZ; - }).length > 0); + assert.isTrue( + models!.bboxes.filter((bbox) => { + const range = Range3d.fromJSON(bbox); + return !range.isAlmostZeroX || !range.isAlmostZeroY || !range.isAlmostZeroZ; + }).length > 0, + ); // Re-open iModel iModel = SnapshotDb.openFile(iModelPathName); diff --git a/full-stack-tests/backend/src/integration/Checkpoints.test.ts b/full-stack-tests/backend/src/integration/Checkpoints.test.ts index 6fefa91082e8..378997a72e4b 100644 --- a/full-stack-tests/backend/src/integration/Checkpoints.test.ts +++ b/full-stack-tests/backend/src/integration/Checkpoints.test.ts @@ -3,16 +3,27 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + _nativeDb, + CloudSqlite, + IModelDb, + IModelHost, + IModelJsFs, + NativeCloudSqlite, + SettingsPriority, + SnapshotDb, + V2CheckpointAccessProps, + V2CheckpointManager, +} from "@itwin/core-backend"; +import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/KnownTestLocations"; +import { AccessToken, GuidString } from "@itwin/core-bentley"; +import { ChangesetProps, IModelVersion } from "@itwin/core-common"; +import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; import { assert, expect } from "chai"; import { ChildProcess } from "child_process"; import * as fs from "fs-extra"; import * as path from "path"; import * as sinon from "sinon"; -import { _nativeDb, CloudSqlite, IModelDb, IModelHost, IModelJsFs, NativeCloudSqlite, SettingsPriority, SnapshotDb, V2CheckpointAccessProps, V2CheckpointManager } from "@itwin/core-backend"; -import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/KnownTestLocations"; -import { AccessToken, GuidString } from "@itwin/core-bentley"; -import { ChangesetProps, IModelVersion } from "@itwin/core-common"; -import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; import { HubUtility } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -85,7 +96,11 @@ describe("Checkpoints", () => { testITwinId = await HubUtility.getTestITwinId(accessToken); testIModelId = await HubUtility.getTestIModelId(accessToken, HubUtility.testIModelNames.stadium); testChangeSet = await IModelHost.hubAccess.getLatestChangeset({ accessToken, iModelId: testIModelId }); - testChangeSetFirstVersion = await IModelHost.hubAccess.getChangesetFromVersion({ accessToken, iModelId: testIModelId, version: IModelVersion.first() }); + testChangeSetFirstVersion = await IModelHost.hubAccess.getChangesetFromVersion({ + accessToken, + iModelId: testIModelId, + version: IModelVersion.first(), + }); testITwinId2 = await HubUtility.getTestITwinId(accessToken); testIModelId2 = await HubUtility.getTestIModelId(accessToken, HubUtility.testIModelNames.readOnly); testChangeSet2 = await IModelHost.hubAccess.getLatestChangeset({ accessToken, iModelId: testIModelId2 }); @@ -103,7 +118,6 @@ describe("Checkpoints", () => { assert.isDefined(checkpointProps?.accountName, "checkpoint storage account is invalid"); assert.isDefined(checkpointProps?.sasToken, "checkpoint accessToken is invalid"); - }); afterEach(async () => { @@ -406,6 +420,5 @@ describe("Checkpoints", () => { iModel2.close(); iModel3.close(); }).timeout(120000); - }); }); diff --git a/full-stack-tests/backend/src/integration/CloudSqlite.test.ts b/full-stack-tests/backend/src/integration/CloudSqlite.test.ts index 0963ffe055fe..ab806b5b391b 100644 --- a/full-stack-tests/backend/src/integration/CloudSqlite.test.ts +++ b/full-stack-tests/backend/src/integration/CloudSqlite.test.ts @@ -3,14 +3,25 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + _nativeDb, + BlobContainer, + BriefcaseDb, + CloudSqlite, + IModelHost, + IModelJsFs, + KnownLocations, + PropertyStore, + SnapshotDb, + SQLiteDb, +} from "@itwin/core-backend"; +import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test"; +import { assert, BeDuration, DbResult, Guid, GuidString, Logger, LoggingMetaData, LogLevel, OpenMode, StopWatch } from "@itwin/core-bentley"; import { expect, use as useFromChai } from "chai"; import * as chaiAsPromised from "chai-as-promised"; import { existsSync, removeSync } from "fs-extra"; import { join } from "path"; import * as sinon from "sinon"; -import { _nativeDb, BlobContainer, BriefcaseDb, CloudSqlite, IModelHost, IModelJsFs, KnownLocations, PropertyStore, SnapshotDb, SQLiteDb } from "@itwin/core-backend"; -import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test"; -import { assert, BeDuration, DbResult, Guid, GuidString, Logger, LoggingMetaData, LogLevel, OpenMode, StopWatch } from "@itwin/core-bentley"; import { AzuriteTest } from "./AzuriteTest"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -145,7 +156,6 @@ describe("CloudSqlite", () => { }); testContainers[0].disconnect({ detach: true }); - }); it("should pass cloudSqliteLogId through container to database", async () => { @@ -188,10 +198,10 @@ describe("CloudSqlite", () => { container.connect(caches[1]); let writeLockExpiryTimeNoWriteLock = container.writeLockExpires; // Should be empty string when no write lock. expect(writeLockExpiryTimeNoWriteLock).to.equal(""); - await CloudSqlite.withWriteLock({user: "testuser", container}, async () => { + await CloudSqlite.withWriteLock({ user: "testuser", container }, async () => { const firstWriteLockExpiryTime = Date.parse(container.writeLockExpires); await BeDuration.wait(500); // sleep 500ms so we get a new write lock expiry time. - await CloudSqlite.withWriteLock({user: "testuser", container}, async () => { + await CloudSqlite.withWriteLock({ user: "testuser", container }, async () => { const secondWriteLockExpiryTime = Date.parse(container.writeLockExpires); expect(secondWriteLockExpiryTime).to.be.greaterThanOrEqual(firstWriteLockExpiryTime); // subtract 30 minutes and make sure its less than the first write lock expiry time. @@ -204,7 +214,7 @@ describe("CloudSqlite", () => { }); writeLockExpiryTimeNoWriteLock = container.writeLockExpires; // Should be empty string when no write lock. expect(writeLockExpiryTimeNoWriteLock).to.equal(""); - container.disconnect({detach: true}); + container.disconnect({ detach: true }); }); it("should LogLevel.Trace set LogMask to ALL", async () => { @@ -235,7 +245,7 @@ describe("CloudSqlite", () => { sinon.assert.called(logTrace); sinon.assert.called(logInfo); // Check for a dirty block log message - let dirtyBlockLogMsg = logInfo.getCalls().some((call) =>call.args[1].includes("is now dirty block")); + let dirtyBlockLogMsg = logInfo.getCalls().some((call) => call.args[1].includes("is now dirty block")); expect(dirtyBlockLogMsg).to.be.true; // resetHistory is sometimes occurring before all of the logs make it to logTrace and logInfo causing our assert.notCalled to fail. // Looking at the analytics for our pipeline, all the failures are due to the below two log messages. Wait for them to show up before we reset history. @@ -255,7 +265,7 @@ describe("CloudSqlite", () => { sinon.assert.notCalled(logTrace); sinon.assert.notCalled(logInfo); // Check for a dirty block log message(expect nothing) - dirtyBlockLogMsg = logInfo.getCalls().some((call) =>call.args[1].includes("is now dirty block")); + dirtyBlockLogMsg = logInfo.getCalls().some((call) => call.args[1].includes("is now dirty block")); expect(dirtyBlockLogMsg).to.be.false; // clean up logTrace.resetHistory(); @@ -283,7 +293,7 @@ describe("CloudSqlite", () => { }; let stats = container.queryBcvStats(); checkOptionalReturnValues(stats, false); - stats = container.queryBcvStats({addClientInformation: false}); + stats = container.queryBcvStats({ addClientInformation: false }); checkOptionalReturnValues(stats, false); expect(cache.isDaemon).to.be.false; // daemonless is always 0 locked blocks. @@ -307,12 +317,12 @@ describe("CloudSqlite", () => { // Check bcv stats again after prefetching a database. db = container.queryDatabase(dbs[0]); expect(db!.localBlocks).to.equal(db!.totalBlocks); - stats = container.queryBcvStats({addClientInformation: true}); + stats = container.queryBcvStats({ addClientInformation: true }); checkOptionalReturnValues(stats, true); expect(stats.lockedCacheslots).to.equal(0); expect(stats.populatedCacheslots).to.equal(db!.totalBlocks); expect(stats.totalCacheslots).to.equal(tenGb / blockSize); - container.disconnect({detach: true}); + container.disconnect({ detach: true }); }); it("cloud containers", async () => { @@ -362,7 +372,7 @@ describe("CloudSqlite", () => { await expect(BriefcaseDb.open({ fileName: "testBim2", container: contain1 })).rejectedWith("write lock not held"); await CloudSqlite.withWriteLock({ user: user1, container: contain1 }, async () => { expect(contain1.hasWriteLock).to.be.true; - await CloudSqlite.withWriteLock({user: user1, container: contain1 }, async () => { + await CloudSqlite.withWriteLock({ user: user1, container: contain1 }, async () => { expect(contain1.hasWriteLock).to.be.true; }); expect(contain1.hasWriteLock).to.be.true; // Make sure that nested withWriteLocks with the same user don't release the write lock. @@ -418,7 +428,7 @@ describe("CloudSqlite", () => { await azSqlite.setSasToken(contain1, "admin"); // now ask for delete permission contain1.connect(caches[1]); - await CloudSqlite.withWriteLock({ user: user1, container: contain1 }, async () => CloudSqlite.cleanDeletedBlocks(contain1, {nSeconds: 0})); + await CloudSqlite.withWriteLock({ user: user1, container: contain1 }, async () => CloudSqlite.cleanDeletedBlocks(contain1, { nSeconds: 0 })); expect(contain1.garbageBlocks).equals(0); // should successfully purge // should be connected @@ -457,7 +467,7 @@ describe("CloudSqlite", () => { expect(expires.length).greaterThan(0); return ++retries < 5 ? undefined : "stop"; }, - }, async () => { })).rejectedWith("is currently locked"); + }, async () => {})).rejectedWith("is currently locked"); }); expect(retries).equals(5); // retry handler should be called 5 times @@ -564,10 +574,10 @@ describe("CloudSqlite", () => { // Upload dummy block to simulate an orphaned block. const blockName = await azSqlite.uploadDummyBlock(container, 24); // findOrphanedBlocks is false, so we expect to keep our dummy block. - await CloudSqlite.cleanDeletedBlocks(container, {findOrphanedBlocks: false}); + await CloudSqlite.cleanDeletedBlocks(container, { findOrphanedBlocks: false }); await expect(azSqlite.checkBlockExists(container, blockName)).to.eventually.become(true); // findOrphanedBlocks is true, so we expect to remove our dummy block. - await CloudSqlite.cleanDeletedBlocks(container, {findOrphanedBlocks: true}); + await CloudSqlite.cleanDeletedBlocks(container, { findOrphanedBlocks: true }); await expect(azSqlite.checkBlockExists(container, blockName)).to.eventually.become(false); expect(container.garbageBlocks).to.be.equal(garbageBlocksPrev); @@ -576,9 +586,9 @@ describe("CloudSqlite", () => { onProgress.onFirstCall().returns(2); // Faking the interval setup in cleanDeletedBlocks. - const clock = sinon.useFakeTimers({toFake: ["setInterval"], shouldAdvanceTime: true, advanceTimeDelta: 1}); + const clock = sinon.useFakeTimers({ toFake: ["setInterval"], shouldAdvanceTime: true, advanceTimeDelta: 1 }); let resolved = false; - CloudSqlite.cleanDeletedBlocks(container, {nSeconds: 0, findOrphanedBlocks: true, onProgress}).then(() => { + CloudSqlite.cleanDeletedBlocks(container, { nSeconds: 0, findOrphanedBlocks: true, onProgress }).then(() => { resolved = true; }).catch(() => { resolved = true; @@ -601,12 +611,12 @@ describe("CloudSqlite", () => { onProgress.reset(); onProgress.returns(0); // One final clean that we don't interrupt ( because we always return 0 from onProgress) - await CloudSqlite.cleanDeletedBlocks(container, {nSeconds: 0, onProgress}); + await CloudSqlite.cleanDeletedBlocks(container, { nSeconds: 0, onProgress }); container.checkForChanges(); expect(container.garbageBlocks).to.be.equal(0); container.releaseWriteLock(); - container.disconnect({detach: true}); + container.disconnect({ detach: true }); }); /** make sure that the auto-refresh for container tokens happens every hour */ @@ -652,4 +662,3 @@ describe("CloudSqlite", () => { BlobContainer.service = service; }); }); - diff --git a/full-stack-tests/backend/src/integration/CloudWorkspace.test.ts b/full-stack-tests/backend/src/integration/CloudWorkspace.test.ts index 33b87855a8ee..ed44eba365b0 100644 --- a/full-stack-tests/backend/src/integration/CloudWorkspace.test.ts +++ b/full-stack-tests/backend/src/integration/CloudWorkspace.test.ts @@ -4,14 +4,28 @@ *--------------------------------------------------------------------------------------------*/ import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests -import { expect } from "chai"; -import * as fs from "fs-extra"; -import { join } from "path"; import { - CreateNewWorkspaceDbVersionArgs, EditableWorkspaceContainer, EditableWorkspaceDb, IModelHost, IModelJsFs, SettingsContainer, SettingsPriority, StandaloneDb, Workspace, WorkspaceContainerProps, - WorkspaceDbCloudProps, WorkspaceDbLoadError, WorkspaceDbLoadErrors, WorkspaceDbQueryResourcesArgs, WorkspaceEditor, WorkspaceSettingNames, + CreateNewWorkspaceDbVersionArgs, + EditableWorkspaceContainer, + EditableWorkspaceDb, + IModelHost, + IModelJsFs, + SettingsContainer, + SettingsPriority, + StandaloneDb, + Workspace, + WorkspaceContainerProps, + WorkspaceDbCloudProps, + WorkspaceDbLoadError, + WorkspaceDbLoadErrors, + WorkspaceDbQueryResourcesArgs, + WorkspaceEditor, + WorkspaceSettingNames, } from "@itwin/core-backend"; import { assert, Guid } from "@itwin/core-bentley"; +import { expect } from "chai"; +import * as fs from "fs-extra"; +import { join } from "path"; import { AzuriteTest } from "./AzuriteTest"; // cspell:ignore premajor @@ -57,11 +71,31 @@ describe("Cloud workspace containers", () => { IModelHost.authorizationClient = new AzuriteTest.AuthorizationClient(); AzuriteTest.userToken = AzuriteTest.service.userToken.admin; editor = WorkspaceEditor.construct(); - orgContainer = await editor.createNewCloudContainer({ metadata: { label: "orgContainer1", description: "org workspace1" }, scope: { iTwinId: iTwin1Id }, manifest: { workspaceName: orgWsName } }); - itwin2Container = await editor.createNewCloudContainer({ metadata: { label: "orgContainer2", description: "org workspace2" }, scope: { iTwinId: iTwin2Id }, manifest: { workspaceName: itwin2WsName } }); - branchContainer = await editor.createNewCloudContainer({ metadata: { label: "iModel container", description: "imodel workspace" }, scope: { iTwinId: iTwin2Id, iModelId: iModel1 }, manifest: { workspaceName: iModelWsName } }); - styles1 = await editor.createNewCloudContainer({ metadata: { label: "styles 1 container", description: "styles definitions 1" }, scope: { iTwinId: iTwin1Id }, manifest: { workspaceName: "styles 1 ws" } }); - styles2 = await editor.createNewCloudContainer({ metadata: { label: "styles 2 container", description: "styles definitions 2" }, scope: { iTwinId: iTwin1Id }, manifest: { workspaceName: "styles 2 ws" } }); + orgContainer = await editor.createNewCloudContainer({ + metadata: { label: "orgContainer1", description: "org workspace1" }, + scope: { iTwinId: iTwin1Id }, + manifest: { workspaceName: orgWsName }, + }); + itwin2Container = await editor.createNewCloudContainer({ + metadata: { label: "orgContainer2", description: "org workspace2" }, + scope: { iTwinId: iTwin2Id }, + manifest: { workspaceName: itwin2WsName }, + }); + branchContainer = await editor.createNewCloudContainer({ + metadata: { label: "iModel container", description: "imodel workspace" }, + scope: { iTwinId: iTwin2Id, iModelId: iModel1 }, + manifest: { workspaceName: iModelWsName }, + }); + styles1 = await editor.createNewCloudContainer({ + metadata: { label: "styles 1 container", description: "styles definitions 1" }, + scope: { iTwinId: iTwin1Id }, + manifest: { workspaceName: "styles 1 ws" }, + }); + styles2 = await editor.createNewCloudContainer({ + metadata: { label: "styles 2 container", description: "styles definitions 2" }, + scope: { iTwinId: iTwin1Id }, + manifest: { workspaceName: "styles 2 ws" }, + }); AzuriteTest.userToken = AzuriteTest.service.userToken.readWrite; const makeV1 = async (container: EditableWorkspaceContainer) => { @@ -148,7 +182,9 @@ describe("Cloud workspace containers", () => { // Attempting to get a released db version for edit should throw orgContainer.acquireWriteLock(user); - expect(() => orgContainer.getEditableDb({ version: "2.0.0" })).throws("workspace-db:2.0.0 has been published and is not editable. Make a new version first."); + expect(() => orgContainer.getEditableDb({ version: "2.0.0" })).throws( + "workspace-db:2.0.0 has been published and is not editable. Make a new version first.", + ); orgContainer.releaseWriteLock(); // Pre-release dbs can be edited @@ -210,7 +246,12 @@ describe("Cloud workspace containers", () => { Workspace.onSettingsDictionaryLoadedFn = (dict: Workspace.SettingsDictionaryLoaded) => loadedDictionaries.push(dict); const appSettings: SettingsContainer = {}; - appSettings["app1/styles/lineStyleDbs"] = [{ ...orgContainerProps!, loadingHelp: "see org admin for access to org ws", description: "org workspace", version: "^1" }]; + appSettings["app1/styles/lineStyleDbs"] = [{ + ...orgContainerProps!, + loadingHelp: "see org admin for access to org ws", + description: "org workspace", + version: "^1", + }]; IModelHost.appWorkspace.settings.addDictionary({ name: "app settings", priority: SettingsPriority.application }, appSettings); let imodel2 = await StandaloneDb.open({ fileName }); @@ -222,9 +263,26 @@ describe("Cloud workspace containers", () => { expect(loadErrors.length).equal(1); expect(loadErrors[0].wsDb?.version).equal("1.0.0"); - const style1Props: WorkspaceDbCloudProps = { ...styles1.cloudProps!, loadingHelp: "see admin1 for access to style1 workspace", description: "styles 1", version: "^1", prefetch: true }; - const style2Props: WorkspaceDbCloudProps = { ...styles2.cloudProps!, loadingHelp: "see admin2 for access to style2 workspace", description: "styles 2", version: "^1" }; - const style3Props: WorkspaceDbCloudProps = { ...styles2.cloudProps!, containerId: "not there", loadingHelp: "see admin2 for access to style3 workspace", description: "more text styles for branch", version: "^1" }; + const style1Props: WorkspaceDbCloudProps = { + ...styles1.cloudProps!, + loadingHelp: "see admin1 for access to style1 workspace", + description: "styles 1", + version: "^1", + prefetch: true, + }; + const style2Props: WorkspaceDbCloudProps = { + ...styles2.cloudProps!, + loadingHelp: "see admin2 for access to style2 workspace", + description: "styles 2", + version: "^1", + }; + const style3Props: WorkspaceDbCloudProps = { + ...styles2.cloudProps!, + containerId: "not there", + loadingHelp: "see admin2 for access to style3 workspace", + description: "more text styles for branch", + version: "^1", + }; await withPatchVersion(branchContainer, (editDb) => { const branchSettings: SettingsContainer = {}; branchSettings["app1/max1"] = 10; @@ -304,7 +362,9 @@ describe("Cloud workspace containers", () => { problems.length = 0; let lineStyleDbs = await imodel2.workspace.getWorkspaceDbs({ - settingName: "app1/styles/lineStyleDbs", problems, filter: (_dbProps, dict) => { + settingName: "app1/styles/lineStyleDbs", + problems, + filter: (_dbProps, dict) => { return (dict.props.priority === SettingsPriority.branch as number); }, }); @@ -378,6 +438,4 @@ describe("Cloud workspace containers", () => { imodel2.close(); }); - }); - diff --git a/full-stack-tests/backend/src/integration/IModelOpen.test.ts b/full-stack-tests/backend/src/integration/IModelOpen.test.ts index 5cc66263990c..f042f429896a 100644 --- a/full-stack-tests/backend/src/integration/IModelOpen.test.ts +++ b/full-stack-tests/backend/src/integration/IModelOpen.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BriefcaseManager, IModelHost, SnapshotDb } from "@itwin/core-backend"; +import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; import { AccessToken, GuidString, RepositoryStatus } from "@itwin/core-bentley"; import { IModelError, IModelVersion } from "@itwin/core-common"; import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; import { assert, expect } from "chai"; -import { BriefcaseManager, IModelHost, SnapshotDb } from "@itwin/core-backend"; -import { HubWrappers } from "@itwin/core-backend/lib/cjs/test/IModelTestUtils"; import { HubUtility } from "../HubUtility"; import "./StartupShutdown"; // calls startup/shutdown IModelHost before/after all tests @@ -64,9 +64,13 @@ describe("IModelOpen", () => { const numChangeSets = changesets.length; assert.isAbove(numChangeSets, 10); - const iModel = await HubWrappers.downloadAndOpenCheckpoint({ accessToken, iTwinId: testITwinId, iModelId: testIModelId, asOf: IModelVersion.asOfChangeSet(changesets[9].id).toJSON() }); + const iModel = await HubWrappers.downloadAndOpenCheckpoint({ + accessToken, + iTwinId: testITwinId, + iModelId: testIModelId, + asOf: IModelVersion.asOfChangeSet(changesets[9].id).toJSON(), + }); assert.isDefined(iModel); await HubWrappers.closeAndDeleteBriefcaseDb(accessToken, iModel); }); - }); diff --git a/full-stack-tests/backend/src/integration/PropertyStore.test.ts b/full-stack-tests/backend/src/integration/PropertyStore.test.ts index 2c8f447b16fb..1e4578eff48e 100644 --- a/full-stack-tests/backend/src/integration/PropertyStore.test.ts +++ b/full-stack-tests/backend/src/integration/PropertyStore.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { CloudSqlite, IModelHost, PropertyStore } from "@itwin/core-backend"; +import { Guid } from "@itwin/core-bentley"; import { expect } from "chai"; import { Suite } from "mocha"; -import { CloudSqlite, IModelHost, PropertyStore } from "@itwin/core-backend"; import { AzuriteTest } from "./AzuriteTest"; -import { Guid } from "@itwin/core-bentley"; function countProperties(values: any, filter?: PropertyStore.PropertyFilter) { let count = 0; @@ -28,7 +28,7 @@ async function makePropertyStore(user: string) { return propStore; } -describe("PropertyStore", function (this: Suite) { +describe("PropertyStore", function(this: Suite) { this.timeout(0); let ps1: PropertyStore.CloudAccess; @@ -116,4 +116,3 @@ describe("PropertyStore", function (this: Suite) { ps2.close(); }); }); - diff --git a/full-stack-tests/backend/src/integration/SchemaSync.test.ts b/full-stack-tests/backend/src/integration/SchemaSync.test.ts index c569a57e6385..f49c4ac6b1df 100644 --- a/full-stack-tests/backend/src/integration/SchemaSync.test.ts +++ b/full-stack-tests/backend/src/integration/SchemaSync.test.ts @@ -3,16 +3,29 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { Suite } from "mocha"; -import { _nativeDb, BriefcaseDb, BriefcaseManager, ChannelControl, CloudSqlite, DrawingCategory, HubMock, IModelDb, IModelHost, SchemaSync, SnapshotDb, SqliteStatement } from "@itwin/core-backend"; -import { AzuriteTest } from "./AzuriteTest"; +import { + _nativeDb, + BriefcaseDb, + BriefcaseManager, + ChannelControl, + CloudSqlite, + DrawingCategory, + HubMock, + IModelDb, + IModelHost, + SchemaSync, + SnapshotDb, + SqliteStatement, +} from "@itwin/core-backend"; import { HubWrappers, IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test"; import { AccessToken, DbResult, Guid, Id64String, OpenMode } from "@itwin/core-bentley"; -import * as path from "path"; -import { EOL } from "os"; import { ChangesetType, Code, ColorDef, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson, Point3d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import { Suite } from "mocha"; +import { EOL } from "os"; +import * as path from "path"; +import { AzuriteTest } from "./AzuriteTest"; const storageType = "azure" as const; interface TinySchemaRef { name: string; @@ -73,7 +86,9 @@ const tinySchemaToXml = (s: TinySchema) => { const queryPropNames = (b: BriefcaseDb, className: string) => { try { return Object.getOwnPropertyNames(b.getMetaData(className).properties); - } catch { return []; } + } catch { + return []; + } }; const assertChangesetTypeAndDescr = async (b: BriefcaseDb, changesetType: ChangesetType, description: string) => { const cs = await HubMock.getLatestChangeset({ iModelId: b.iModelId }); @@ -107,15 +122,15 @@ async function assertThrowsAsync(test: () => Promise, msg?: string) { return; } throw new Error(`Failed to throw error with message: "${msg}"`); -}; +} async function initializeContainer(containerProps: { containerId: string, isPublic?: boolean, baseUri: string }) { await AzuriteTest.Sqlite.createAzContainer(containerProps); const accessToken = await CloudSqlite.requestToken({ ...containerProps }); await SchemaSync.CloudAccess.initializeDb({ ...containerProps, accessToken, storageType }); return { ...containerProps, accessToken, storageType }; -}; +} -describe("Schema synchronization", function (this: Suite) { +describe("Schema synchronization", function(this: Suite) { this.timeout(0); before(async () => { @@ -363,8 +378,7 @@ describe("Schema synchronization", function (this: Suite) { props: [ { kind: "primitive", name: "p0", type: "string" }, ], - }, - ], + }], }); assert.deepEqual(queryPropNames(b1, "Test1:Pipe1"), ["p0"]); @@ -379,7 +393,8 @@ describe("Schema synchronization", function (this: Suite) { const newContainerProps = await initializeContainer({ baseUri: AzuriteTest.baseUri, containerId: "imodel-sync-itwin-2" }); await assertThrowsAsync( async () => SchemaSync.initializeForIModel({ iModel: b2, containerProps: newContainerProps }), - "Local db already initialized to schema sync (container-id: imodel-sync-itwin-1)"); + "Local db already initialized to schema sync (container-id: imodel-sync-itwin-1)", + ); await SchemaSync.initializeForIModel({ iModel: b2, containerProps: newContainerProps, overrideContainer: true }); assert.equal(querySchemaSyncDataVer(b2), "0x2"); @@ -396,8 +411,7 @@ describe("Schema synchronization", function (this: Suite) { { kind: "primitive", name: "p0", type: "string" }, { kind: "primitive", name: "p1", type: "string" }, /* New property added by B2 using new imodel-sync-itwin-2 */ ], - }, - ], + }], }); assert.equal(querySchemaSyncDataVer(b2), "0x3"); assert.deepEqual(queryPropNames(b2, "Test1:Pipe1"), ["p0", "p1"]); @@ -419,8 +433,7 @@ describe("Schema synchronization", function (this: Suite) { { kind: "primitive", name: "p0", type: "string" }, { kind: "primitive", name: "p2", type: "string" }, /* New property added by B2 using new imodel-sync-itwin-1 */ ], - }, - ], + }], }); assert.equal(querySchemaSyncDataVer(b1), "0x3"); assert.deepEqual(queryPropNames(b1, "Test1:Pipe1"), ["p0", "p2"]); @@ -445,8 +458,7 @@ describe("Schema synchronization", function (this: Suite) { { kind: "primitive", name: "p1", type: "string" }, { kind: "primitive", name: "p2", type: "string" }, /* New property added by B2 using new imodel-sync-itwin-2 */ ], - }, - ], + }], }); assert.equal(querySchemaSyncDataVer(b1), "0x4"); assert.deepEqual(queryPropNames(b1, "Test1:Pipe1"), ["p0", "p1", "p2"]); @@ -494,8 +506,7 @@ describe("Schema synchronization", function (this: Suite) { description: "b1 push", changesType: 65, briefcaseId: 2, - }, - ]; + }]; assert.deepEqual(masterHistory, expectedHistory); [b1, b2, b3].forEach((b) => { @@ -515,7 +526,10 @@ describe("Schema synchronization", function (this: Suite) { HubMock.startup("test", KnownTestLocations.outputDir); // Setup seed file from existing 4.0.0.3 imodel - const testFile = SnapshotDb.openDgnDb({ path: path.join(imodelJsCoreDirname, "core/backend/lib/cjs/test/assets/test_ec_4003.bim") }, OpenMode.ReadWrite); + const testFile = SnapshotDb.openDgnDb( + { path: path.join(imodelJsCoreDirname, "core/backend/lib/cjs/test/assets/test_ec_4003.bim") }, + OpenMode.ReadWrite, + ); const version0 = testFile.getFilePath(); testFile.closeFile(); @@ -550,8 +564,7 @@ describe("Schema synchronization", function (this: Suite) { props: [ { kind: "primitive", name: "p0", type: "string" }, ], - }, - ], + }], }); assert.isUndefined(querySchemaSyncDataVer(b1), "SchemaSync data version should be undefined as its not initialized"); @@ -559,7 +572,8 @@ describe("Schema synchronization", function (this: Suite) { // should fail as there are pending changeset. await assertThrowsAsync( async () => SchemaSync.initializeForIModel({ iModel: b1, containerProps }), - "Enabling SchemaSync for iModel failed. There are unsaved or un-pushed local changes."); + "Enabling SchemaSync for iModel failed. There are unsaved or un-pushed local changes.", + ); // push changes and then retry. await b1.pushChanges({ description: "schema changes" }); @@ -624,20 +638,21 @@ describe("Schema synchronization", function (this: Suite) { assert.equal(querySchemaSyncDataVer(b1), "0x4", "Test1 schema update should change it from 0x3 -> 0x4"); // 6. B2 import new schema but should fail as it does not see SchemaSync enable so it attempt acquire schema lock - await assertThrowsAsync(async () => importSchema(b2, { - name: "Test2", - alias: "ts2", - ver: "01.00.00", - refs: [{ name: "BisCore", ver: "01.00.00", alias: "bis" }], - classes: [{ - type: "entity", - name: "Pipe1", - baseClass: "bis:GeometricElement2d", - props: [ - { kind: "primitive", name: "p0", type: "string" }, - ], - }], - }), "pull is required to obtain lock"); + await assertThrowsAsync(async () => + importSchema(b2, { + name: "Test2", + alias: "ts2", + ver: "01.00.00", + refs: [{ name: "BisCore", ver: "01.00.00", alias: "bis" }], + classes: [{ + type: "entity", + name: "Pipe1", + baseClass: "bis:GeometricElement2d", + props: [ + { kind: "primitive", name: "p0", type: "string" }, + ], + }], + }), "pull is required to obtain lock"); assert.isUndefined(querySchemaSyncDataVer(b2), "should be undefined in B2"); b2.abandonChanges(); @@ -838,8 +853,7 @@ describe("Schema synchronization", function (this: Suite) { description: "final push by b3", changesType: 65, briefcaseId: 4, - }, - ]; + }]; assert.deepEqual(masterHistory, expectedHistory); [b1, b2, b3, b4].forEach((b) => { @@ -880,7 +894,8 @@ describe("Schema synchronization", function (this: Suite) { await SchemaSync.initializeForIModel({ iModel: b1, containerProps }); await b1.pushChanges({ accessToken: user1AccessToken, description: "enable shared schema channel" }); assert.isTrue(b1[_nativeDb].schemaSyncEnabled()); - const sequence = (start: number, stop: number, step: number = 1) => Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + (i * step)); + const sequence = (start: number, stop: number, step: number = 1) => + Array.from({ length: (stop - start) / step + 1 }, (_, i) => start + (i * step)); await importSchema(b1, { name: "Test1", @@ -891,14 +906,18 @@ describe("Schema synchronization", function (this: Suite) { type: "struct", name: "Struct1", props: [ - ...sequence(0, 10).map((i) => { return { kind: "primitive", name: `p${i}`, type: "string" }; }), + ...sequence(0, 10).map((i) => { + return { kind: "primitive", name: `p${i}`, type: "string" }; + }), ], }, { type: "entity", name: "Pipe1", baseClass: "bis:GeometricElement2d", props: [ - ...sequence(0, 1).map((i) => { return { kind: "struct", name: `s${i}`, type: "Struct1" }; }), + ...sequence(0, 1).map((i) => { + return { kind: "struct", name: `s${i}`, type: "Struct1" }; + }), ], }], }); @@ -916,14 +935,18 @@ describe("Schema synchronization", function (this: Suite) { type: "struct", name: "Struct1", props: [ - ...sequence(0, 30).map((i) => { return { kind: "primitive", name: `p${i}`, type: "string" }; }), + ...sequence(0, 30).map((i) => { + return { kind: "primitive", name: `p${i}`, type: "string" }; + }), ], }, { type: "entity", name: "Pipe1", baseClass: "bis:GeometricElement2d", props: [ - ...sequence(0, 1).map((i) => { return { kind: "struct", name: `s${i}`, type: "Struct1" }; }), + ...sequence(0, 1).map((i) => { + return { kind: "struct", name: `s${i}`, type: "Struct1" }; + }), ], }], }); @@ -940,39 +963,48 @@ describe("Schema synchronization", function (this: Suite) { type: "struct", name: "Struct1", props: [ - ...sequence(0, 10).map((i) => { return { kind: "primitive", name: `p${i}`, type: "string" }; }), + ...sequence(0, 10).map((i) => { + return { kind: "primitive", name: `p${i}`, type: "string" }; + }), ], }, { type: "entity", name: "Pipe1", baseClass: "bis:GeometricElement2d", props: [ - ...sequence(0, 1).map((i) => { return { kind: "struct", name: `s${i}`, type: "Struct1" }; }), + ...sequence(0, 1).map((i) => { + return { kind: "struct", name: `s${i}`, type: "Struct1" }; + }), ], }], }); await b3.pullChanges(); - await assertThrowsAsync(async () => importSchema(b3, { - name: "Test2", - alias: "ts2", - ver: "01.00.01", - refs: [{ name: "BisCore", ver: "01.00.00", alias: "bis" }], - classes: [{ - type: "struct", - name: "Struct1", - props: [ - ...sequence(0, 30).map((i) => { return { kind: "primitive", name: `p${i}`, type: "string" }; }), - ], - }, { - type: "entity", - name: "Pipe1", - baseClass: "bis:GeometricElement2d", - props: [ - ...sequence(0, 1).map((i) => { return { kind: "struct", name: `s${i}`, type: "Struct1" }; }), - ], - }], - }), "exclusive lock is already held"); + await assertThrowsAsync(async () => + importSchema(b3, { + name: "Test2", + alias: "ts2", + ver: "01.00.01", + refs: [{ name: "BisCore", ver: "01.00.00", alias: "bis" }], + classes: [{ + type: "struct", + name: "Struct1", + props: [ + ...sequence(0, 30).map((i) => { + return { kind: "primitive", name: `p${i}`, type: "string" }; + }), + ], + }, { + type: "entity", + name: "Pipe1", + baseClass: "bis:GeometricElement2d", + props: [ + ...sequence(0, 1).map((i) => { + return { kind: "struct", name: `s${i}`, type: "Struct1" }; + }), + ], + }], + }), "exclusive lock is already held"); await b1.pushChanges({ description: "schema with 30 props in test1:Pipe1" }); await b3.pullChanges(); @@ -986,14 +1018,18 @@ describe("Schema synchronization", function (this: Suite) { type: "struct", name: "Struct1", props: [ - ...sequence(0, 30).map((i) => { return { kind: "primitive", name: `p${i}`, type: "string" }; }), + ...sequence(0, 30).map((i) => { + return { kind: "primitive", name: `p${i}`, type: "string" }; + }), ], }, { type: "entity", name: "Pipe1", baseClass: "bis:GeometricElement2d", props: [ - ...sequence(0, 1).map((i) => { return { kind: "struct", name: `s${i}`, type: "Struct1" }; }), + ...sequence(0, 1).map((i) => { + return { kind: "struct", name: `s${i}`, type: "Struct1" }; + }), ], }], }); @@ -1075,7 +1111,12 @@ describe("Schema synchronization", function (this: Suite) { const [, drawingModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(b1, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(b1, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(b1, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + b1, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); b1.saveChanges(); await b1.pushChanges({ description: "setup category", accessToken: adminToken }); @@ -1102,7 +1143,7 @@ describe("Schema synchronization", function (this: Suite) { geom: geometryStream, ...args, }; - return b1.elements.insertElement(e1);; + return b1.elements.insertElement(e1); }; const updateEl = async (id: Id64String, args: { [key: string]: any }) => { await b1.locks.acquireLocks({ exclusive: id }); diff --git a/full-stack-tests/backend/src/integration/StartupShutdown.ts b/full-stack-tests/backend/src/integration/StartupShutdown.ts index 127109fb1a09..fb80f723637f 100644 --- a/full-stack-tests/backend/src/integration/StartupShutdown.ts +++ b/full-stack-tests/backend/src/integration/StartupShutdown.ts @@ -6,8 +6,8 @@ import { IModelHost, IModelHostOptions } from "@itwin/core-backend"; import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; import { IModelsClient } from "@itwin/imodels-client-authoring"; -import { emptyDirSync, mkdirsSync } from "fs-extra"; import * as fs from "fs"; +import { emptyDirSync, mkdirsSync } from "fs-extra"; import * as path from "path"; /** Loads the provided `.env` file into process.env */ @@ -29,7 +29,7 @@ loadEnv(path.join(__dirname, "..", "..", "..", ".env")); export async function startupForIntegration(cfg?: IModelHostOptions) { cfg = cfg ?? {}; - cfg.cacheDir = path.join(__dirname, ".cache"); // Set the cache dir to be under the lib directory. + cfg.cacheDir = path.join(__dirname, ".cache"); // Set the cache dir to be under the lib directory. const iModelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); cfg.hubAccess = new BackendIModelsAccess(iModelClient); mkdirsSync(cfg.cacheDir); diff --git a/full-stack-tests/backend/src/integration/TileUpload.test.ts b/full-stack-tests/backend/src/integration/TileUpload.test.ts index 1e1ef6d58a1e..2845ffb69362 100644 --- a/full-stack-tests/backend/src/integration/TileUpload.test.ts +++ b/full-stack-tests/backend/src/integration/TileUpload.test.ts @@ -2,19 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { AzureBlobStorageCredentials, GeometricModel3d, IModelDb, IModelHost, RpcTrace } from "@itwin/core-backend"; +import { HubWrappers } from "@itwin/core-backend/lib/cjs/test"; import { AccessToken, GuidString } from "@itwin/core-bentley"; import { - BatchType, ContentIdProvider, defaultTileOptions, getTileObjectReference, IModelTileRpcInterface, iModelTileTreeIdToString, - RpcManager, RpcRegistry, TileContentSource, + BatchType, + ContentIdProvider, + defaultTileOptions, + getTileObjectReference, + IModelTileRpcInterface, + iModelTileTreeIdToString, + RpcManager, + RpcRegistry, + TileContentSource, } from "@itwin/core-common"; -import { AzureBlobStorageCredentials, GeometricModel3d, IModelDb, IModelHost, RpcTrace } from "@itwin/core-backend"; -import { HubWrappers } from "@itwin/core-backend/lib/cjs/test"; import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; +import { assert } from "chai"; +import { promisify } from "util"; +import { gunzip } from "zlib"; import { HubUtility } from "../HubUtility"; import { startupForIntegration } from "./StartupShutdown"; -import { gunzip } from "zlib"; -import { promisify } from "util"; interface TileContentRequestProps { treeId: string; @@ -124,7 +131,7 @@ describe("TileUpload", () => { const blobProperties = await IModelHost.tileStorage!.storage.getObjectProperties(objectReference); const tileSize = IModelHost.compressCachedTiles - ? (await promisify(gunzip)(blobBuffer) as Buffer).byteLength // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion + ? (await promisify(gunzip)(blobBuffer) as Buffer).byteLength // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion : blobBuffer.byteLength; // Verify metadata in blob properties diff --git a/full-stack-tests/backend/src/integration/ViewStore.test.ts b/full-stack-tests/backend/src/integration/ViewStore.test.ts index 6e7de64a0edd..52336827a86e 100644 --- a/full-stack-tests/backend/src/integration/ViewStore.test.ts +++ b/full-stack-tests/backend/src/integration/ViewStore.test.ts @@ -3,23 +3,65 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { existsSync, mkdirSync, unlinkSync } from "fs-extra"; -import { Suite } from "mocha"; -import { join } from "path"; -import * as sinon from "sinon"; import { - AuxCoordSystem2d, CategorySelector, CloudSqlite, DefinitionModel, DisplayStyle2d, DisplayStyle3d, DocumentListModel, Drawing, DrawingCategory, - DrawingGraphic, DrawingViewDefinition, GroupModel, IModelDb, IModelHost, InformationRecordModel, ModelSelector, OrthographicViewDefinition, - PhysicalModel, RenderMaterialElement, SpatialCategory, SpatialLocationModel, SpatialViewDefinition, StandaloneDb, SubCategory, Subject, ViewStore, + AuxCoordSystem2d, + CategorySelector, + CloudSqlite, + DefinitionModel, + DisplayStyle2d, + DisplayStyle3d, + DocumentListModel, + Drawing, + DrawingCategory, + DrawingGraphic, + DrawingViewDefinition, + GroupModel, + IModelDb, + IModelHost, + InformationRecordModel, + ModelSelector, + OrthographicViewDefinition, + PhysicalModel, + RenderMaterialElement, + SpatialCategory, + SpatialLocationModel, + SpatialViewDefinition, + StandaloneDb, + SubCategory, + Subject, + ViewStore, } from "@itwin/core-backend"; import { CompressedId64Set, Guid, GuidString, Id64, Id64String } from "@itwin/core-bentley"; import { - AuxCoordSystem2dProps, Camera, Code, CodeScopeSpec, ColorByName, ColorDef, DefinitionElementProps, DisplayStyle3dProps, DisplayStyle3dSettingsProps, - Environment, GeometricElement2dProps, GeometryStreamBuilder, GeometryStreamProps, IModel, LocalFileName, PlanProjectionSettings, SkyBoxImageType, - SpatialViewDefinitionProps, SubCategoryAppearance, SubCategoryOverride, ViewDefinition2dProps, ViewDefinitionProps, + AuxCoordSystem2dProps, + Camera, + Code, + CodeScopeSpec, + ColorByName, + ColorDef, + DefinitionElementProps, + DisplayStyle3dProps, + DisplayStyle3dSettingsProps, + Environment, + GeometricElement2dProps, + GeometryStreamBuilder, + GeometryStreamProps, + IModel, + LocalFileName, + PlanProjectionSettings, + SkyBoxImageType, + SpatialViewDefinitionProps, + SubCategoryAppearance, + SubCategoryOverride, + ViewDefinition2dProps, + ViewDefinitionProps, } from "@itwin/core-common"; import { LineString3d, Matrix3d, Point2d, Point3d, Range2d, Range3d, StandardViewIndex, Transform, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; +import { existsSync, mkdirSync, unlinkSync } from "fs-extra"; +import { Suite } from "mocha"; +import { join } from "path"; +import * as sinon from "sinon"; import { AzuriteTest } from "./AzuriteTest"; const iTwinId = Guid.createValue(); @@ -116,7 +158,10 @@ function populateDb(sourceDb: IModelDb) { assert.isTrue(Id64.isValidId64(subCategoryId)); const drawingCategoryId = DrawingCategory.insert(sourceDb, definitionModelId, "DrawingCategory", new SubCategoryAppearance()); assert.isTrue(Id64.isValidId64(drawingCategoryId)); - const spatialCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "SpatialCategories", [spatialCategoryId, sourcePhysicalCategoryId]); + const spatialCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "SpatialCategories", [ + spatialCategoryId, + sourcePhysicalCategoryId, + ]); assert.isTrue(Id64.isValidId64(spatialCategorySelectorId)); const drawingCategorySelectorId = CategorySelector.insert(sourceDb, definitionModelId, "DrawingCategories", [drawingCategoryId]); assert.isTrue(Id64.isValidId64(drawingCategorySelectorId)); @@ -171,14 +216,31 @@ function populateDb(sourceDb: IModelDb) { const displayStyle3dId = displayStyle3d.insert(); assert.isTrue(Id64.isValidId64(displayStyle3dId)); // Insert ViewDefinitions - const viewId = OrthographicViewDefinition.insert(sourceDb, definitionModelId, "Orthographic View", modelSelectorId, spatialCategorySelectorId, displayStyle3dId, projectExtents, StandardViewIndex.Iso); + const viewId = OrthographicViewDefinition.insert( + sourceDb, + definitionModelId, + "Orthographic View", + modelSelectorId, + spatialCategorySelectorId, + displayStyle3dId, + projectExtents, + StandardViewIndex.Iso, + ); assert.isTrue(Id64.isValidId64(viewId)); const drawingViewRange = new Range2d(0, 0, 100, 100); - drawingViewId = DrawingViewDefinition.insert(sourceDb, definitionModelId, "Drawing View", drawingId, drawingCategorySelectorId, displayStyle2dId, drawingViewRange); + drawingViewId = DrawingViewDefinition.insert( + sourceDb, + definitionModelId, + "Drawing View", + drawingId, + drawingCategorySelectorId, + displayStyle2dId, + drawingViewRange, + ); assert.isTrue(Id64.isValidId64(drawingViewId)); } -describe("ViewStore", function (this: Suite) { +describe("ViewStore", function(this: Suite) { this.timeout(0); class FakeGuids { @@ -232,23 +294,20 @@ describe("ViewStore", function (this: Suite) { const displayStyleProps: DisplayStyle3dSettingsProps = { backgroundColor: ColorDef.fromString("rgb(255,20,10)").toJSON(), - subCategoryOvr: - [{ - subCategory: "0x40", - color: ColorByName.fuchsia, - invisible: true, - style: "0xaaa", - weight: 10, - transp: 0.5, - }, - { - subCategory: "0x41", - color: ColorByName.darkBlue, - invisible: false, - style: "0xaa3", - weight: 10, - }, - ], + subCategoryOvr: [{ + subCategory: "0x40", + color: ColorByName.fuchsia, + invisible: true, + style: "0xaaa", + weight: 10, + transp: 0.5, + }, { + subCategory: "0x41", + color: ColorByName.darkBlue, + invisible: false, + style: "0xaa3", + weight: 10, + }], excludedElements: CompressedId64Set.compressArray(["0x8", "0x12", "0x22"]), scheduleScript: [{ @@ -268,7 +327,11 @@ describe("ViewStore", function (this: Suite) { const dsEl = DisplayStyle3d.create(iModel, IModel.dictionaryId, "test style 1", displayStyleProps); const styleProps = dsEl.toJSON() as DisplayStyle3dProps; const dsId = iModel.elements.insertElement(styleProps); - const ds1Row = await vs1locker.addDisplayStyle({ className: dsEl.classFullName, name: dsEl.code.value, settings: styleProps.jsonProperties!.styles! }); + const ds1Row = await vs1locker.addDisplayStyle({ + className: dsEl.classFullName, + name: dsEl.code.value, + settings: styleProps.jsonProperties!.styles!, + }); expect(ds1Row).equals("@1"); expect(Id64.isValid(dsId)).true; @@ -403,7 +466,10 @@ describe("ViewStore", function (this: Suite) { // now test Drawing views. const dv = await iModel.views.getViewStateProps(drawingViewId); // this was added in the populateDb function. const dcs = await vs1locker.addCategorySelector({ selector: { ids: dv.categorySelectorProps.categories } }); - const dds = await vs1locker.addDisplayStyle({ className: dv.displayStyleProps.classFullName, settings: dv.displayStyleProps.jsonProperties!.styles! }); + const dds = await vs1locker.addDisplayStyle({ + className: dv.displayStyleProps.classFullName, + settings: dv.displayStyleProps.jsonProperties!.styles!, + }); dv.viewDefinitionProps.categorySelectorId = dcs; dv.viewDefinitionProps.displayStyleId = dds; const dvId = await vs1locker.addView({ viewDefinition: dv.viewDefinitionProps, owner: "owner1" }); @@ -426,4 +492,3 @@ describe("ViewStore", function (this: Suite) { sinon.restore(); }); }); - diff --git a/full-stack-tests/backend/src/perftest/CRUDConfig.json b/full-stack-tests/backend/src/perftest/CRUDConfig.json index 6bc3f753f2df..216d1c707b1e 100644 --- a/full-stack-tests/backend/src/perftest/CRUDConfig.json +++ b/full-stack-tests/backend/src/perftest/CRUDConfig.json @@ -35,4 +35,4 @@ "PerfElement2dSub3" ] } -} \ No newline at end of file +} diff --git a/full-stack-tests/backend/src/perftest/CSPerfConfig.json b/full-stack-tests/backend/src/perftest/CSPerfConfig.json index 1524bb4da5c3..c5af649d1ee1 100644 --- a/full-stack-tests/backend/src/perftest/CSPerfConfig.json +++ b/full-stack-tests/backend/src/perftest/CSPerfConfig.json @@ -41,4 +41,4 @@ "hierarchy": 4 } } -} \ No newline at end of file +} diff --git a/full-stack-tests/backend/src/perftest/CloseIModalPerformance.test.ts b/full-stack-tests/backend/src/perftest/CloseIModalPerformance.test.ts index 0af3f3022af7..45ff97a34490 100644 --- a/full-stack-tests/backend/src/perftest/CloseIModalPerformance.test.ts +++ b/full-stack-tests/backend/src/perftest/CloseIModalPerformance.test.ts @@ -2,36 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { Id64String, StopWatch } from "@itwin/core-bentley"; -import { - BriefcaseIdValue, - Code, - ColorDef, - GeometricElementProps, - IModel, - SubCategoryAppearance, -} from "@itwin/core-common"; -import { - _nativeDb, - IModelDb, - IModelHost, - IModelHostOptions, - IModelJsFs, - SnapshotDb, - SpatialCategory, -} from "@itwin/core-backend"; +import { _nativeDb, IModelDb, IModelHost, IModelHostOptions, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; -import { IModelsClient } from "@itwin/imodels-client-authoring"; +import { Id64String, StopWatch } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; -import * as path from "path"; +import { IModelsClient } from "@itwin/imodels-client-authoring"; import { Reporter } from "@itwin/perf-tools"; +import { expect } from "chai"; +import * as path from "path"; interface TestElement extends GeometricElementProps { - addresses: [null, {city: "Pune", zip: 28}]; + addresses: [null, { city: "Pune", zip: 28 }]; } -function initElemProps( _iModelName: IModelDb, modId: Id64String, catId: Id64String, autoHandledProp: any): GeometricElementProps { +function initElemProps(_iModelName: IModelDb, modId: Id64String, catId: Id64String, autoHandledProp: any): GeometricElementProps { // Create props const elementProps: GeometricElementProps = { classFullName: "Test:Foo", @@ -83,7 +68,7 @@ describe("CloseIModalTest", () => { const iModelHost: IModelHostOptions = {}; const iModelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); iModelHost.hubAccess = new BackendIModelsAccess(iModelClient); - iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir + iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir await IModelHost.startup(iModelHost); // write schema to disk as we do not have api to import xml directly const testSchemaPath = IModelTestUtils.prepareOutputFile( @@ -125,8 +110,8 @@ describe("CloseIModalTest", () => { const imodel = IModelTestUtils.createSnapshotFromSeed(testFileName, iModelPath); spatialCategoryId = SpatialCategory.queryCategoryIdByName(imodel, IModel.dictionaryId, categoryName); const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(imodel, Code.createEmpty(), true); - const expectedValue = initElemProps( imodel, newModelId, spatialCategoryId!, { - addresses: [null, {city: "Pune", zip: 28}], + const expectedValue = initElemProps(imodel, newModelId, spatialCategoryId!, { + addresses: [null, { city: "Pune", zip: 28 }], }) as TestElement; imodel.elements.createElement(expectedValue); imodel.close(); @@ -152,9 +137,7 @@ describe("CloseIModalTest", () => { ) => { const testModel = SnapshotDb.openFile(fileName); const opTime = await timeOperation(testModel, operation); - const closeTime = await timeOperation(testModel, async (db: IModelDb) => - db.close(), - ); + const closeTime = await timeOperation(testModel, async (db: IModelDb) => db.close()); return { opTime, closeTime }; }; const stat = await withSnapshotDb(testFileName, async () => { diff --git a/full-stack-tests/backend/src/perftest/ConcurrencyQueue.ts b/full-stack-tests/backend/src/perftest/ConcurrencyQueue.ts index 2fe2617378b8..ac9579966e83 100644 --- a/full-stack-tests/backend/src/perftest/ConcurrencyQueue.ts +++ b/full-stack-tests/backend/src/perftest/ConcurrencyQueue.ts @@ -32,7 +32,7 @@ export class ConcurrencyQueue { private async pushPending(pending: Promise): Promise { const wrapped = pending.then((resolvedValue) => { // Remove this promise from the _pending array, and replace it with the next task in the queue. - this._pending = this._pending.filter((p) => p !== wrapped); // eslint-disable-line @typescript-eslint/no-floating-promises + this._pending = this._pending.filter((p) => p !== wrapped); // eslint-disable-line @typescript-eslint/no-floating-promises this.startNextInQueue(); // Need to pass through the task's original return value. @@ -44,13 +44,19 @@ export class ConcurrencyQueue { } /** The number of currently started tasks that are still pending completion. */ - public get pendingCount() { return this._pending.length; } + public get pendingCount() { + return this._pending.length; + } /** The number of queued tasks that have not yet started. */ - public get queuedCount() { return this._queue.length; } + public get queuedCount() { + return this._queue.length; + } /** True if there are no tasks currently pending or queued. */ - public get isEmpty() { return (this.pendingCount === 0 && this.queuedCount === 0); } + public get isEmpty() { + return (this.pendingCount === 0 && this.queuedCount === 0); + } /** * Adds a task to the queue. Tasks are automatically started on a FIFO basis whenever there are less than `maxParallel` currently started/pending. diff --git a/full-stack-tests/backend/src/perftest/ECSqlRow.test.ts b/full-stack-tests/backend/src/perftest/ECSqlRow.test.ts index 9f0b31a659fc..e22845187f63 100644 --- a/full-stack-tests/backend/src/perftest/ECSqlRow.test.ts +++ b/full-stack-tests/backend/src/perftest/ECSqlRow.test.ts @@ -2,16 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { _nativeDb, DrawingCategory, ECSqlStatement, IModelDb, IModelHost, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, -} from "@itwin/core-common"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, DrawingCategory, ECSqlStatement, IModelDb, IModelHost, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; // @ts-expect-error package.json will resolve from the lib/{cjs,esm} dir without copying it into the build output we deliver // eslint-disable-next-line @itwin/import-within-package @@ -24,10 +22,19 @@ const CORE_MAJ_MIN = `${ITWINJS_CORE_VERSION.split(".")[0]}.${ITWINJS_CORE_VERSI /* eslint-disable @typescript-eslint/naming-convention */ const values: any = { - baseStr: "PerfElement - InitValue", baseStr2: "PerfElement - InitValue2", sub1Str: "PerfElementSub1 - InitValue", - sub2Str: "PerfElementSub2 - InitValue", sub3Str: "PerfElementSub3 - InitValue", - baseLong: "0x989680", sub1Long: "0x1312d00", sub2Long: "0x1c9c380", sub3Long: "0x2625a00", - baseDouble: -3.1416, sub1Double: 2.71828, sub2Double: 1.414121, sub3Double: 1.61803398874, + baseStr: "PerfElement - InitValue", + baseStr2: "PerfElement - InitValue2", + sub1Str: "PerfElementSub1 - InitValue", + sub2Str: "PerfElementSub2 - InitValue", + sub3Str: "PerfElementSub3 - InitValue", + baseLong: "0x989680", + sub1Long: "0x1312d00", + sub2Long: "0x1c9c380", + sub3Long: "0x2625a00", + baseDouble: -3.1416, + sub1Double: 2.71828, + sub2Double: 1.414121, + sub3Double: 1.61803398874, }; interface TestElementProps extends GeometricElementProps { @@ -139,7 +146,9 @@ describe("ECSqlRowPerformanceTests", () => { if (IModelJsFs.existsSync(pathname)) continue; - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlRowPerformance", fileName), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlRowPerformance", fileName), { + rootSubject: { name: "PerfTest" }, + }); const testSchemaName = path.join(KnownTestLocations.assetsDir, "PerfTestDomain.ecschema.xml"); await seedIModel.importSchemas([testSchemaName]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); @@ -148,7 +157,12 @@ describe("ECSqlRowPerformanceTests", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let m = 0; m < size; ++m) { const elementProps = createElemProps(name, seedIModel, newModelId, spatialCategoryId); @@ -182,7 +196,11 @@ describe("ECSqlRowPerformanceTests", () => { const perfimodel = IModelTestUtils.createSnapshotFromSeed(testFileName, seedFileName); const elapsedTime = measureGetRowTime(perfimodel, `PerfTestDomain:${name}`); - reporter.addEntry("ECSqlRowPerformanceTests", "GetElements", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("ECSqlRowPerformanceTests", "GetElements", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } @@ -209,7 +227,9 @@ describe("ECSqlRowPerformanceTests2d", () => { if (IModelJsFs.existsSync(pathname)) continue; - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlRowPerformance2d", fileName), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ECSqlRowPerformance2d", fileName), { + rootSubject: { name: "PerfTest" }, + }); const testSchemaName = path.join(KnownTestLocations.assetsDir, "PerfTestDomain.ecschema.xml"); await seedIModel.importSchemas([testSchemaName]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); @@ -220,7 +240,12 @@ describe("ECSqlRowPerformanceTests2d", () => { const [, newModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(seedIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(seedIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + seedIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let m = 0; m < size; ++m) { const elementProps = createElemProps(name, seedIModel, newModelId, drawingCategoryId); @@ -254,7 +279,11 @@ describe("ECSqlRowPerformanceTests2d", () => { const perfimodel = IModelTestUtils.createSnapshotFromSeed(testFileName, seedFileName); const elapsedTime = measureGetRowTime(perfimodel, `PerfTestDomain:${name}`); - reporter.addEntry("ECSqlRowPerformanceTests2d", "GetElements2d", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("ECSqlRowPerformanceTests2d", "GetElements2d", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } diff --git a/full-stack-tests/backend/src/perftest/ECSqlRowConfig.json b/full-stack-tests/backend/src/perftest/ECSqlRowConfig.json index c08b429ff9f6..4b43194b7adc 100644 --- a/full-stack-tests/backend/src/perftest/ECSqlRowConfig.json +++ b/full-stack-tests/backend/src/perftest/ECSqlRowConfig.json @@ -33,4 +33,4 @@ "PerfElement2dSub3" ] } -} \ No newline at end of file +} diff --git a/full-stack-tests/backend/src/perftest/ElementAspect.test.ts b/full-stack-tests/backend/src/perftest/ElementAspect.test.ts index 3fc4f82516db..f47392daffc8 100644 --- a/full-stack-tests/backend/src/perftest/ElementAspect.test.ts +++ b/full-stack-tests/backend/src/perftest/ElementAspect.test.ts @@ -3,27 +3,36 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import "./setup"; -import { assert } from "chai"; -import * as fs from "fs-extra"; -import * as path from "path"; +import { DictionaryModel, ElementAspect, IModelDb, IModelHost, IModelHostOptions, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { HubWrappers, IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { AccessToken, Id64String } from "@itwin/core-bentley"; import { ElementAspectProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; +import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; +import { IModelsClient } from "@itwin/imodels-client-authoring"; import { TestUsers, TestUtility } from "@itwin/oidc-signin-tool"; import { Reporter } from "@itwin/perf-tools"; -import { DictionaryModel, ElementAspect, IModelDb, IModelHost, IModelHostOptions, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { HubWrappers, IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; -import { IModelsClient } from "@itwin/imodels-client-authoring"; -import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; +import { assert } from "chai"; +import * as fs from "fs-extra"; +import * as path from "path"; /* eslint-disable @typescript-eslint/naming-convention */ async function createNewModelAndCategory(rwIModel: IModelDb) { // Create a new physical model. - const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(rwIModel, IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), true); + const [, modelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel( + rwIModel, + IModelTestUtils.getUniqueModelCode(rwIModel, "newPhysicalModel"), + true, + ); // Find or create a SpatialCategory. const dictionary: DictionaryModel = rwIModel.models.getModel(IModel.dictionaryId); const newCategoryCode = IModelTestUtils.getUniqueSpatialCategoryCode(dictionary, "ThisTestSpatialCategory"); - const spatialCategoryId: Id64String = SpatialCategory.insert(rwIModel, IModel.dictionaryId, newCategoryCode.value, new SubCategoryAppearance({ color: 0xff0000 })); + const spatialCategoryId: Id64String = SpatialCategory.insert( + rwIModel, + IModel.dictionaryId, + newCategoryCode.value, + new SubCategoryAppearance({ color: 0xff0000 }), + ); return { modelId, spatialCategoryId }; } @@ -43,7 +52,7 @@ describe("ElementAspectPerformance", () => { const iModelHost: IModelHostOptions = {}; const iModelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); iModelHost.hubAccess = new BackendIModelsAccess(iModelClient); - iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir + iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir await IModelHost.startup(iModelHost); accessToken = await TestUtility.getAccessToken(TestUsers.regular); @@ -105,13 +114,24 @@ describe("ElementAspectPerformance", () => { const endTime3 = new Date().getTime(); const elapsedTime3 = (endTime3 - startTime3) / 1000.0; totalTimeDeleteSimpELeGet = totalTimeDeleteSimpELeGet + elapsedTime3; - } iModelDb.close(); - reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeInsertSimpELeGet, { ElementCount: count1, Operation: "Insert" }); - reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeUpdateSimpELeGet, { ElementCount: count1, Operation: "Update" }); - reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeDeleteSimpELeGet, { ElementCount: count1, Operation: "Delete" }); - reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeReadSimpELeGet, { ElementCount: count1, Operation: "Read" }); + reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeInsertSimpELeGet, { + ElementCount: count1, + Operation: "Insert", + }); + reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeUpdateSimpELeGet, { + ElementCount: count1, + Operation: "Update", + }); + reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeDeleteSimpELeGet, { + ElementCount: count1, + Operation: "Delete", + }); + reporter.addEntry("ElementAspectPerformance", "SimpleElement", "Execution time(s)", totalTimeReadSimpELeGet, { + ElementCount: count1, + Operation: "Read", + }); }); it("UniqueAspectElement-Insert-Update-Delete-Read", async () => { @@ -120,8 +140,12 @@ describe("ElementAspectPerformance", () => { const iModelDb = SnapshotDb.createFrom(iModelDbHub, snapshotPath); assert.exists(iModelDb); - interface TestAspectProps extends ElementAspectProps { testUniqueAspectProperty: string } - class TestAspect extends ElementAspect { public testUniqueAspectProperty: string = ""; } + interface TestAspectProps extends ElementAspectProps { + testUniqueAspectProperty: string; + } + class TestAspect extends ElementAspect { + public testUniqueAspectProperty: string = ""; + } const count1 = 10000; let eleId: Id64String; @@ -181,10 +205,22 @@ describe("ElementAspectPerformance", () => { totalTimeDelete = totalTimeDelete + elapsedTime3; } iModelDb.close(); - reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeInsert, { ElementCount: count1, Operation: "Insert" }); - reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeUpdate, { ElementCount: count1, Operation: "Update" }); - reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeDelete, { ElementCount: count1, Operation: "Delete" }); - reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeRead, { ElementCount: count1, Operation: "Read" }); + reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeInsert, { + ElementCount: count1, + Operation: "Insert", + }); + reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeUpdate, { + ElementCount: count1, + Operation: "Update", + }); + reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeDelete, { + ElementCount: count1, + Operation: "Delete", + }); + reporter.addEntry("ElementAspectPerformance", "UniqueAspectElement", "Execution time(s)", totalTimeRead, { + ElementCount: count1, + Operation: "Read", + }); }); it("MultiAspectElement-Insert-Update-Delete-Read", async () => { @@ -262,9 +298,21 @@ describe("ElementAspectPerformance", () => { totalTimeDelete = totalTimeDelete + elapsedTime3; } iModelDb.close(); - reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeInsert, { ElementCount: count1, Operation: "Insert" }); - reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeUpdate, { ElementCount: count1, Operation: "Update" }); - reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeDelete, { ElementCount: count1, Operation: "Delete" }); - reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeRead, { ElementCount: count1, Operation: "Read" }); + reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeInsert, { + ElementCount: count1, + Operation: "Insert", + }); + reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeUpdate, { + ElementCount: count1, + Operation: "Update", + }); + reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeDelete, { + ElementCount: count1, + Operation: "Delete", + }); + reporter.addEntry("ElementAspectPerformance", "MultiAspectElement", "Execution time(s)", totalTimeRead, { + ElementCount: count1, + Operation: "Read", + }); }); }); diff --git a/full-stack-tests/backend/src/perftest/ElementCRUD.test.ts b/full-stack-tests/backend/src/perftest/ElementCRUD.test.ts index 7b7e32437002..d5a4ddb5a477 100644 --- a/full-stack-tests/backend/src/perftest/ElementCRUD.test.ts +++ b/full-stack-tests/backend/src/perftest/ElementCRUD.test.ts @@ -2,16 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { + _nativeDb, + DrawingCategory, + ECSqlStatement, + Element, + IModelDb, + IModelHost, + IModelJsFs, + SnapshotDb, + SpatialCategory, +} from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, -} from "@itwin/core-common"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, DrawingCategory, ECSqlStatement, Element, IModelDb, IModelHost, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; import { PerfTestUtility } from "./PerfTestUtils"; // @ts-expect-error package.json will resolve from the lib/{cjs,esm} dir without copying it into the build output we deliver @@ -25,10 +33,19 @@ const CORE_MAJ_MIN = `${ITWINJS_CORE_VERSION.split(".")[0]}.${ITWINJS_CORE_VERSI /* eslint-disable @typescript-eslint/naming-convention */ const values: any = { - baseStr: "PerfElement - InitValue", baseStr2: "PerfElement - InitValue2", sub1Str: "PerfElementSub1 - InitValue", - sub2Str: "PerfElementSub2 - InitValue", sub3Str: "PerfElementSub3 - InitValue", - baseLong: "0x989680", sub1Long: "0x1312d00", sub2Long: "0x1c9c380", sub3Long: "0x2625a00", - baseDouble: -3.1416, sub1Double: 2.71828, sub2Double: 1.414121, sub3Double: 1.61803398874, + baseStr: "PerfElement - InitValue", + baseStr2: "PerfElement - InitValue2", + sub1Str: "PerfElementSub1 - InitValue", + sub2Str: "PerfElementSub2 - InitValue", + sub3Str: "PerfElementSub3 - InitValue", + baseLong: "0x989680", + sub1Long: "0x1312d00", + sub2Long: "0x1c9c380", + sub3Long: "0x2625a00", + baseDouble: -3.1416, + sub1Double: 2.71828, + sub2Double: 1.414121, + sub3Double: 1.61803398874, }; interface TestElementProps extends GeometricElementProps { @@ -140,7 +157,9 @@ describe("PerformanceElementsTests", () => { await IModelHost.startup(); - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ElementCRUDPerformance", fileName), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ElementCRUDPerformance", fileName), { + rootSubject: { name: "PerfTest" }, + }); const testSchemaName = path.join(KnownTestLocations.assetsDir, "PerfTestDomain.ecschema.xml"); await seedIModel.importSchemas([testSchemaName]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); @@ -148,7 +167,12 @@ describe("PerformanceElementsTests", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let m = 0; m < size; ++m) { const elementProps = createElemProps(name, seedIModel, newModelId, spatialCategoryId); @@ -182,7 +206,12 @@ describe("PerformanceElementsTests", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(perfimodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(perfimodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + perfimodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); let totalTime = 0.0; for (let m = 0; m < opCount; ++m) { @@ -196,7 +225,12 @@ describe("PerformanceElementsTests", () => { totalTime = totalTime + elapsedTime; } - reporter.addEntry("PerformanceElementsTests", "ElementsInsert", "Execution time(s)", totalTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests", "ElementsInsert", "Execution time(s)", totalTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); assert.equal(getCount(perfimodel, `PerfTestDomain:${name}`), size + opCount); perfimodel.close(); } @@ -228,7 +262,12 @@ describe("PerformanceElementsTests", () => { } const endTime = new Date().getTime(); const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests", "ElementsDelete", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests", "ElementsDelete", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); assert.equal(getCount(perfimodel, `PerfTestDomain:${name}`), size - opCount); perfimodel.close(); } @@ -265,7 +304,12 @@ describe("PerformanceElementsTests", () => { } const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests", "ElementsRead", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests", "ElementsRead", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } @@ -320,7 +364,12 @@ describe("PerformanceElementsTests", () => { assert.equal((elemFound as any).baseStr, "PerfElement - UpdatedValue"); } const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests", "ElementsUpdate", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests", "ElementsUpdate", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } @@ -350,7 +399,9 @@ describe("PerformanceElementsTests2d", () => { await IModelHost.startup(); - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ElementCRUDPerformance2d", fileName), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("ElementCRUDPerformance2d", fileName), { + rootSubject: { name: "PerfTest" }, + }); const testSchemaName = path.join(KnownTestLocations.assetsDir, "PerfTestDomain.ecschema.xml"); await seedIModel.importSchemas([testSchemaName]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); @@ -361,7 +412,12 @@ describe("PerformanceElementsTests2d", () => { const [, newModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(seedIModel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(seedIModel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + seedIModel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let m = 0; m < size; ++m) { const elementProps = createElemProps(name, seedIModel, newModelId, drawingCategoryId); @@ -399,7 +455,12 @@ describe("PerformanceElementsTests2d", () => { const [, newModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(perfimodel, codeProps, true); let drawingCategoryId = DrawingCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MyDrawingCategory"); if (undefined === drawingCategoryId) - drawingCategoryId = DrawingCategory.insert(perfimodel, IModel.dictionaryId, "MyDrawingCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + drawingCategoryId = DrawingCategory.insert( + perfimodel, + IModel.dictionaryId, + "MyDrawingCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); let totalTime = 0.0; for (let m = 0; m < opCount; ++m) { const elementProps = createElemProps(name, perfimodel, newModelId, drawingCategoryId); @@ -412,7 +473,12 @@ describe("PerformanceElementsTests2d", () => { totalTime = totalTime + elapsedTime; } - reporter.addEntry("PerformanceElementsTests2d", "ElementsInsert2d", "Execution time(s)", totalTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests2d", "ElementsInsert2d", "Execution time(s)", totalTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); assert.equal(getCount(perfimodel, `PerfTestDomain:${name}`), size + opCount); perfimodel.close(); } @@ -444,7 +510,12 @@ describe("PerformanceElementsTests2d", () => { } const endTime = new Date().getTime(); const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests2d", "ElementsDelete2d", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests2d", "ElementsDelete2d", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); assert.equal(getCount(perfimodel, `PerfTestDomain:${name}`), size - opCount); perfimodel.close(); } @@ -481,7 +552,12 @@ describe("PerformanceElementsTests2d", () => { } const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests2d", "ElementsRead2d", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests2d", "ElementsRead2d", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } @@ -535,7 +611,12 @@ describe("PerformanceElementsTests2d", () => { assert.equal((elemFound as any).baseStr, "PerfElement - UpdatedValue"); } const elapsedTime = (endTime - startTime) / 1000.0; - reporter.addEntry("PerformanceElementsTests2d", "ElementsUpdate2d", "Execution time(s)", elapsedTime, { ElementClassName: name, InitialCount: size, opCount, CoreVersion: CORE_MAJ_MIN }); + reporter.addEntry("PerformanceElementsTests2d", "ElementsUpdate2d", "Execution time(s)", elapsedTime, { + ElementClassName: name, + InitialCount: size, + opCount, + CoreVersion: CORE_MAJ_MIN, + }); perfimodel.close(); } } diff --git a/full-stack-tests/backend/src/perftest/MixinImpact.test.ts b/full-stack-tests/backend/src/perftest/MixinImpact.test.ts index 4eeb029f9e3a..fc469ea8725b 100644 --- a/full-stack-tests/backend/src/perftest/MixinImpact.test.ts +++ b/full-stack-tests/backend/src/perftest/MixinImpact.test.ts @@ -2,16 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, -} from "@itwin/core-common"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; describe("SchemaDesignPerf Impact of Mixins", () => { const outDir: string = path.join(KnownTestLocations.outputDir, "MixinPerformance"); @@ -20,7 +18,12 @@ describe("SchemaDesignPerf Impact of Mixins", () => { let propCount = 0; const reporter = new Reporter(); - function createElemProps(_imodel: IModelDb, modId: Id64String, catId: Id64String, className: string = "TestPropsSchema:PropElement"): GeometricElementProps { + function createElemProps( + _imodel: IModelDb, + modId: Id64String, + catId: Id64String, + className: string = "TestPropsSchema:PropElement", + ): GeometricElementProps { // add Geometry const geomArray: Arc3d[] = [ Arc3d.createXY(Point3d.create(0, 0), 5), @@ -126,14 +129,21 @@ describe("SchemaDesignPerf Impact of Mixins", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, `mixin_${hCount}.bim`); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("MixinPerformance", `mixin_${hCount}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("MixinPerformance", `mixin_${hCount}.bim`), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel.getMetaData("TestMixinSchema:MixinElement"), "Mixin Class is not present in iModel."); const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); // create base class elements for (let i = 0; i < seedCount; ++i) { let elementProps = createElemProps(seedIModel, newModelId, spatialCategoryId, "TestMixinSchema:propElement"); @@ -161,7 +171,7 @@ describe("SchemaDesignPerf Impact of Mixins", () => { } } seedIModel.saveChanges(); - assert.equal(getCount(seedIModel, "TestMixinSchema:PropElement"), ((2 * seedCount * hCount) + seedCount)); + assert.equal(getCount(seedIModel, "TestMixinSchema:PropElement"), (2 * seedCount * hCount) + seedCount); seedIModel.close(); } } diff --git a/full-stack-tests/backend/src/perftest/PerfTestUtils.ts b/full-stack-tests/backend/src/perftest/PerfTestUtils.ts index 246b7641b861..a75732ad0558 100644 --- a/full-stack-tests/backend/src/perftest/PerfTestUtils.ts +++ b/full-stack-tests/backend/src/perftest/PerfTestUtils.ts @@ -2,15 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; import { IModelTestUtils } from "@itwin/core-backend/lib/cjs/test/index"; import { Id64String } from "@itwin/core-bentley"; import { - BriefcaseIdValue, Code, ColorDef, DbResult, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, + BriefcaseIdValue, + Code, + ColorDef, + DbResult, + GeometricElementProps, + GeometryStreamProps, + IModel, + SubCategoryAppearance, } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point2d, Point3d } from "@itwin/core-geometry"; +import { assert } from "chai"; +import * as path from "path"; export class PerfTestDataMgr { public db: SnapshotDb | undefined; @@ -40,7 +47,12 @@ export class PerfTestDataMgr { this.modelId = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(this.db, Code.createEmpty(), true); this.catId = SpatialCategory.queryCategoryIdByName(this.db, IModel.dictionaryId, "MySpatialCategory"); if (undefined === this.catId) { - this.catId = SpatialCategory.insert(this.db, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + this.catId = SpatialCategory.insert( + this.db, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); } this.db[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); this.db.saveChanges(); @@ -53,10 +65,18 @@ export class PerfTestDataMgr { } const values: any = { - baseStr: "PerfElement - InitValue", sub1Str: "PerfElementSub1 - InitValue", - sub2Str: "PerfElementSub2 - InitValue", sub3Str: "PerfElementSub3 - InitValue", - baseLong: "0x989680", sub1Long: "0x1312d00", sub2Long: "0x1c9c380", sub3Long: "0x2625a00", - baseDouble: -3.1416, sub1Double: 2.71828, sub2Double: 1.414121, sub3Double: 1.61803398874, + baseStr: "PerfElement - InitValue", + sub1Str: "PerfElementSub1 - InitValue", + sub2Str: "PerfElementSub2 - InitValue", + sub3Str: "PerfElementSub3 - InitValue", + baseLong: "0x989680", + sub1Long: "0x1312d00", + sub2Long: "0x1c9c380", + sub3Long: "0x2625a00", + baseDouble: -3.1416, + sub1Double: 2.71828, + sub2Double: 1.414121, + sub3Double: 1.61803398874, }; function camelize(text: string) { @@ -83,7 +103,8 @@ function genPropValue(prop: string): any { return new Point2d(1.034, 2.034); if (prop.toLowerCase().includes("point3d")) return new Point3d(-1.0, 2.3, 3.0001); - else // could not find type + // could not find type + else return undefined; } @@ -130,7 +151,6 @@ export class PerfTestUtility { `; - } else { for (const prop of props) { const propType = prop.split("Test")[0]; diff --git a/full-stack-tests/backend/src/perftest/PolymorphicQuery.test.ts b/full-stack-tests/backend/src/perftest/PolymorphicQuery.test.ts index 34a5f61cd6e4..2f02472c9ee2 100644 --- a/full-stack-tests/backend/src/perftest/PolymorphicQuery.test.ts +++ b/full-stack-tests/backend/src/perftest/PolymorphicQuery.test.ts @@ -2,16 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, -} from "@itwin/core-common"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; describe("SchemaDesignPerf Polymorphic query", () => { const outDir: string = path.join(KnownTestLocations.outputDir, "PolymorphicPerformance"); @@ -22,7 +20,12 @@ describe("SchemaDesignPerf Polymorphic query", () => { let flatHierarchyCounts: never[] = []; const reporter = new Reporter(); - function createElemProps(_imodel: IModelDb, modId: Id64String, catId: Id64String, className: string = "TestPropsSchema:PropElement"): GeometricElementProps { + function createElemProps( + _imodel: IModelDb, + modId: Id64String, + catId: Id64String, + className: string = "TestPropsSchema:PropElement", + ): GeometricElementProps { // add Geometry const geomArray: Arc3d[] = [ Arc3d.createXY(Point3d.create(0, 0), 5), @@ -129,13 +132,20 @@ describe("SchemaDesignPerf Polymorphic query", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, `poly_flat_${hCount}.bim`); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("PolymorphicPerformance", `poly_flat_${hCount}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("PolymorphicPerformance", `poly_flat_${hCount}.bim`), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); // first create Elements and then Relationship const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel.getMetaData("TestPolySchema:TestElement"), "Base Class is not present in iModel."); // create base class elements @@ -156,7 +166,7 @@ describe("SchemaDesignPerf Polymorphic query", () => { assert.isTrue(Id64.isValidId64(id), "insert failed"); } } - assert.equal(getCount(seedIModel, "TestPolySchema:TestElement"), ((hCount + 1) * flatSeedCount)); + assert.equal(getCount(seedIModel, "TestPolySchema:TestElement"), (hCount + 1) * flatSeedCount); seedIModel.saveChanges(); seedIModel.close(); } @@ -166,13 +176,21 @@ describe("SchemaDesignPerf Polymorphic query", () => { assert(IModelJsFs.existsSync(st2)); const seedName2 = path.join(outDir, `poly_multi_${multiHierarchyCount.toString()}.bim`); if (!IModelJsFs.existsSync(seedName2)) { - const seedIModel2 = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("PolymorphicPerformance", `poly_multi_${multiHierarchyCount.toString()}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel2 = SnapshotDb.createEmpty( + IModelTestUtils.prepareOutputFile("PolymorphicPerformance", `poly_multi_${multiHierarchyCount.toString()}.bim`), + { rootSubject: { name: "PerfTest" } }, + ); await seedIModel2.importSchemas([st2]); // first create Elements and then Relationship const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel2, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel2, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel2, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel2, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); seedIModel2[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel2.getMetaData("TestPolySchema:TestElement"), "Base Class is not present in iModel."); // create base class elements @@ -193,7 +211,7 @@ describe("SchemaDesignPerf Polymorphic query", () => { assert.isTrue(Id64.isValidId64(id), "insert failed"); } } - assert.equal(getCount(seedIModel2, "TestPolySchema:TestElement"), ((multiHierarchyCount + 1) * multiSeedCount)); + assert.equal(getCount(seedIModel2, "TestPolySchema:TestElement"), (multiHierarchyCount + 1) * multiSeedCount); seedIModel2.saveChanges(); seedIModel2.close(); } @@ -263,11 +281,18 @@ describe("SchemaDesignPerf Polymorphic query", () => { assert.isTrue(false); } } - reporter.addEntry("PolyPerfTest", "PolymorphicMultiRead", "Execution time(s)", totalTime / (multiHierarchyCount - 1), { sCount: multiSeedCount, hCount: multiHierarchyCount, level: "Child" }); - reporter.addEntry("PolyPerfTest", "PolymorphicMultiRead", "Execution time(s)", parentTime, { sCount: multiSeedCount, hCount: multiHierarchyCount, level: "Base" }); + reporter.addEntry("PolyPerfTest", "PolymorphicMultiRead", "Execution time(s)", totalTime / (multiHierarchyCount - 1), { + sCount: multiSeedCount, + hCount: multiHierarchyCount, + level: "Child", + }); + reporter.addEntry("PolyPerfTest", "PolymorphicMultiRead", "Execution time(s)", parentTime, { + sCount: multiSeedCount, + hCount: multiHierarchyCount, + level: "Base", + }); perfimodel.saveChanges(); perfimodel.close(); }); - }); diff --git a/full-stack-tests/backend/src/perftest/PropertiesImpact.test.ts b/full-stack-tests/backend/src/perftest/PropertiesImpact.test.ts index 752ca8f225ab..ac740bc3a60b 100644 --- a/full-stack-tests/backend/src/perftest/PropertiesImpact.test.ts +++ b/full-stack-tests/backend/src/perftest/PropertiesImpact.test.ts @@ -2,19 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; +import { BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance } from "@itwin/core-common"; import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; -import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, SubCategoryAppearance, -} from "@itwin/core-common"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; import { PerfTestUtility } from "./PerfTestUtils"; -function createElemProps(_imodel: IModelDb, modId: Id64String, catId: Id64String, className: string = "TestPropsSchema:PropElement"): GeometricElementProps { +function createElemProps( + _imodel: IModelDb, + modId: Id64String, + catId: Id64String, + className: string = "TestPropsSchema:PropElement", +): GeometricElementProps { // add Geometry const geomArray: Arc3d[] = [ Arc3d.createXY(Point3d.create(0, 0), 5), @@ -94,14 +97,21 @@ describe("SchemaDesignPerf Impact of Properties", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, `props_${pCount}.bim`); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("PropPerformance", `props_${pCount}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("PropPerformance", `props_${pCount}.bim`), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel.getMetaData("TestPropsSchema:PropElement"), "PropsClass is present in iModel."); const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); // create elements that can be used in tests for (let i = 0; i < seedCount; ++i) { const elementProps = createElemProps(seedIModel, newModelId, spatialCategoryId); @@ -131,7 +141,12 @@ describe("SchemaDesignPerf Impact of Properties", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(perfimodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(perfimodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + perfimodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let i = 0; i < opCount; ++i) { const elementProps = createElemProps(perfimodel, newModelId, spatialCategoryId); @@ -176,7 +191,6 @@ describe("SchemaDesignPerf Impact of Properties", () => { reporter.addEntry("PropPerfTest", "ElementsDelete", "Execution time(s)", elapsedTime, { count: opCount, properties: propCount }); } - }); it("Read", async () => { for (const propCount of propCounts) { @@ -253,7 +267,6 @@ describe("SchemaDesignPerf Impact of Properties", () => { perfimodel.close(); reporter.addEntry("PropPerfTest", "ElementsUpdate", "Execution time(s)", elapsedTime, { count: opCount, properties: propCount }); } - }); }); describe("SchemaDesignPerf Number of Indices", () => { @@ -345,14 +358,21 @@ describe("SchemaDesignPerf Number of Indices", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, `index_${iCount}.bim`); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IndexPerformance", `index_${iCount}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IndexPerformance", `index_${iCount}.bim`), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel.getMetaData("TestIndexSchema:PropElement"), "PropsClass is present in iModel."); const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); // create elements that can be used in tests for (let i = 0; i < seedCount; ++i) { const elementProps = createElemProps(seedIModel, newModelId, spatialCategoryId, "TestIndexSchema:PropElement"); @@ -372,14 +392,21 @@ describe("SchemaDesignPerf Number of Indices", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, `index_perclass_${iCount}.bim`); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IndexPerformance", `index_perclass_${iCount}.bim`), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IndexPerformance", `index_perclass_${iCount}.bim`), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); assert.isDefined(seedIModel.getMetaData("TestIndexSchema:PropElement0"), "PropsClass is present in iModel."); const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); // create elements that can be used in tests for (let i = 0; i < seedCount; ++i) { const elementProps = createElemProps(seedIModel, newModelId, spatialCategoryId, "TestIndexSchema:PropElement0"); @@ -395,7 +422,6 @@ describe("SchemaDesignPerf Number of Indices", () => { seedIModel.close(); } } - }); after(() => { @@ -412,7 +438,12 @@ describe("SchemaDesignPerf Number of Indices", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(perfimodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(perfimodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + perfimodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let i = 0; i < opCount; ++i) { const elementProps = createElemProps(perfimodel, newModelId, spatialCategoryId, "TestIndexSchema:PropElement"); @@ -440,7 +471,12 @@ describe("SchemaDesignPerf Number of Indices", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(perfimodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(perfimodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + perfimodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let i = 0; i < opCount; ++i) { const elementProps = createElemProps(perfimodel, newModelId, spatialCategoryId, "TestIndexSchema:PropElement0"); @@ -508,7 +544,11 @@ describe("SchemaDesignPerf Number of Indices", () => { perfimodel.close(); - reporter.addEntry("IndexPerfTest", "ElementsDelete", "Execution time(s)", elapsedTime, { count: opCount, indices: indexCount, perClass: "Yes" }); + reporter.addEntry("IndexPerfTest", "ElementsDelete", "Execution time(s)", elapsedTime, { + count: opCount, + indices: indexCount, + perClass: "Yes", + }); } }); it("Read", async () => { @@ -648,7 +688,11 @@ describe("SchemaDesignPerf Number of Indices", () => { } const elapsedTime = (endTime - startTime) / 1000.0; perfimodel.close(); - reporter.addEntry("IndexPerfTest", "ElementsUpdate", "Execution time(s)", elapsedTime, { count: opCount, indices: indexCount, perClass: "Yes" }); + reporter.addEntry("IndexPerfTest", "ElementsUpdate", "Execution time(s)", elapsedTime, { + count: opCount, + indices: indexCount, + perClass: "Yes", + }); } }); }); diff --git a/full-stack-tests/backend/src/perftest/RelationshipImpact.test.ts b/full-stack-tests/backend/src/perftest/RelationshipImpact.test.ts index 0a4e494360f1..bd3a6413f991 100644 --- a/full-stack-tests/backend/src/perftest/RelationshipImpact.test.ts +++ b/full-stack-tests/backend/src/perftest/RelationshipImpact.test.ts @@ -2,16 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; +import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; +import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; -import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; import { - BriefcaseIdValue, Code, ColorDef, GeometricElementProps, GeometryStreamProps, IModel, RelatedElement, RelationshipProps, SubCategoryAppearance, + BriefcaseIdValue, + Code, + ColorDef, + GeometricElementProps, + GeometryStreamProps, + IModel, + RelatedElement, + RelationshipProps, + SubCategoryAppearance, } from "@itwin/core-common"; +import { Arc3d, IModelJson as GeomJson, Point3d } from "@itwin/core-geometry"; import { Reporter } from "@itwin/perf-tools"; -import { _nativeDb, ECSqlStatement, IModelDb, IModelJsFs, SnapshotDb, SpatialCategory } from "@itwin/core-backend"; -import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { assert } from "chai"; +import * as path from "path"; import { PerfTestUtility } from "./PerfTestUtils"; describe("SchemaDesignPerf Relationship Comparison", () => { @@ -20,7 +28,12 @@ describe("SchemaDesignPerf Relationship Comparison", () => { let opCount = 0; const reporter = new Reporter(); - function createElemProps(_imodel: IModelDb, modId: Id64String, catId: Id64String, className: string = "TestPropsSchema:PropElement"): GeometricElementProps { + function createElemProps( + _imodel: IModelDb, + modId: Id64String, + catId: Id64String, + className: string = "TestPropsSchema:PropElement", + ): GeometricElementProps { // add Geometry const geomArray: Arc3d[] = [ Arc3d.createXY(Point3d.create(0, 0), 5), @@ -148,14 +161,21 @@ describe("SchemaDesignPerf Relationship Comparison", () => { assert(IModelJsFs.existsSync(st)); const seedName = path.join(outDir, "relationship.bim"); if (!IModelJsFs.existsSync(seedName)) { - const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("RelationshipPerformance", "relationship.bim"), { rootSubject: { name: "PerfTest" } }); + const seedIModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("RelationshipPerformance", "relationship.bim"), { + rootSubject: { name: "PerfTest" }, + }); await seedIModel.importSchemas([st]); seedIModel[_nativeDb].resetBriefcaseId(BriefcaseIdValue.Unassigned); // first create Elements and then Relationship const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(seedIModel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(seedIModel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(seedIModel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + seedIModel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let i = 0; i < seedCount; ++i) { const idC = insertElement(seedIModel, newModelId, spatialCategoryId, "TestRelationSchema:ChildC"); @@ -201,7 +221,12 @@ describe("SchemaDesignPerf Relationship Comparison", () => { const [, newModelId] = IModelTestUtils.createAndInsertPhysicalPartitionAndModel(perfimodel, Code.createEmpty(), true); let spatialCategoryId = SpatialCategory.queryCategoryIdByName(perfimodel, IModel.dictionaryId, "MySpatialCategory"); if (undefined === spatialCategoryId) - spatialCategoryId = SpatialCategory.insert(perfimodel, IModel.dictionaryId, "MySpatialCategory", new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() })); + spatialCategoryId = SpatialCategory.insert( + perfimodel, + IModel.dictionaryId, + "MySpatialCategory", + new SubCategoryAppearance({ color: ColorDef.fromString("rgb(255,0,0)").toJSON() }), + ); for (let i = 0; i < opCount; ++i) { // LinkTable @@ -240,8 +265,16 @@ describe("SchemaDesignPerf Relationship Comparison", () => { verifyCounts(perfimodel, seedCount + opCount); perfimodel.close(); - reporter.addEntry("RelPerfTest", "RelationshipInsert", "Execution time(s)", totalTimeLink, { count: opCount, sCount: seedCount, relType: "LinkTable" }); - reporter.addEntry("RelPerfTest", "RelationshipInsert", "Execution time(s)", totalTimeNav, { count: opCount, sCount: seedCount, relType: "NavProp" }); + reporter.addEntry("RelPerfTest", "RelationshipInsert", "Execution time(s)", totalTimeLink, { + count: opCount, + sCount: seedCount, + relType: "LinkTable", + }); + reporter.addEntry("RelPerfTest", "RelationshipInsert", "Execution time(s)", totalTimeNav, { + count: opCount, + sCount: seedCount, + relType: "NavProp", + }); }); it("Read", async () => { const seedFileName = path.join(outDir, "relationship.bim"); @@ -254,8 +287,11 @@ describe("SchemaDesignPerf Relationship Comparison", () => { const startTime = new Date().getTime(); for (let i = 0; i < opCount; ++i) { try { - const tId: Id64String = Id64.fromLocalAndBriefcaseIds((minId + elementIdIncrement * i), 0); - const query = IModelTestUtils.executeQuery(perfimodel, `SELECT SourceECInstanceId FROM TestRelationSchema.CIsRelatedToD WHERE TargetECInstanceId=${tId}`)[0]; + const tId: Id64String = Id64.fromLocalAndBriefcaseIds(minId + elementIdIncrement * i, 0); + const query = IModelTestUtils.executeQuery( + perfimodel, + `SELECT SourceECInstanceId FROM TestRelationSchema.CIsRelatedToD WHERE TargetECInstanceId=${tId}`, + )[0]; assert.isTrue(Id64.isValidId64(query.sourceId)); } catch (err) { assert.isTrue(false); @@ -269,8 +305,9 @@ describe("SchemaDesignPerf Relationship Comparison", () => { const startTime1 = new Date().getTime(); for (let i = 0; i < opCount; ++i) { try { - const tId: Id64String = Id64.fromLocalAndBriefcaseIds((minId + elementIdIncrement * i), 0); - const query = IModelTestUtils.executeQuery(perfimodel, `SELECT SourceECInstanceId FROM TestRelationSchema.ADrivesB WHERE TargetECInstanceId=${tId}`)[0]; + const tId: Id64String = Id64.fromLocalAndBriefcaseIds(minId + elementIdIncrement * i, 0); + const query = + IModelTestUtils.executeQuery(perfimodel, `SELECT SourceECInstanceId FROM TestRelationSchema.ADrivesB WHERE TargetECInstanceId=${tId}`)[0]; assert.isTrue(Id64.isValidId64(query.sourceId)); } catch (err) { assert.isTrue(false); @@ -282,9 +319,16 @@ describe("SchemaDesignPerf Relationship Comparison", () => { perfimodel.saveChanges(); perfimodel.close(); - reporter.addEntry("RelPerfTest", "RelationshipRead", "Execution time(s)", elapsedTimeLink, { count: opCount, sCount: seedCount, relType: "LinkTable" }); - reporter.addEntry("RelPerfTest", "RelationshipRead", "Execution time(s)", elapsedTimeNav, { count: opCount, sCount: seedCount, relType: "NavProp" }); - + reporter.addEntry("RelPerfTest", "RelationshipRead", "Execution time(s)", elapsedTimeLink, { + count: opCount, + sCount: seedCount, + relType: "LinkTable", + }); + reporter.addEntry("RelPerfTest", "RelationshipRead", "Execution time(s)", elapsedTimeNav, { + count: opCount, + sCount: seedCount, + relType: "NavProp", + }); }); it("Delete", async () => { const seedFileName = path.join(outDir, "relationship.bim"); @@ -297,9 +341,9 @@ describe("SchemaDesignPerf Relationship Comparison", () => { const startTime = new Date().getTime(); for (let i = 0; i < opCount; ++i) { try { - const sId: Id64String = Id64.fromLocalAndBriefcaseIds((minId + elementIdIncrement * i), 0); + const sId: Id64String = Id64.fromLocalAndBriefcaseIds(minId + elementIdIncrement * i, 0); // Need improvement. Currently assuming that they were added one after another so have next Id. - const tId: Id64String = Id64.fromLocalAndBriefcaseIds(((minId + elementIdIncrement * i) + 1), 0); + const tId: Id64String = Id64.fromLocalAndBriefcaseIds((minId + elementIdIncrement * i) + 1, 0); const rel = perfimodel.relationships.getInstance("TestRelationSchema:CIsRelatedToD", { sourceId: sId, targetId: tId }); rel.delete(); } catch (err) { @@ -315,7 +359,7 @@ describe("SchemaDesignPerf Relationship Comparison", () => { const startTime1 = new Date().getTime(); for (let i = 0; i < opCount; ++i) { try { - const elId: Id64String = Id64.fromLocalAndBriefcaseIds((minId + elementIdIncrement * i), 0); + const elId: Id64String = Id64.fromLocalAndBriefcaseIds(minId + elementIdIncrement * i, 0); const editElem: any = perfimodel.elements.getElement(elId); editElem.childB = null; perfimodel.elements.updateElement(editElem); @@ -330,7 +374,15 @@ describe("SchemaDesignPerf Relationship Comparison", () => { perfimodel.saveChanges(); perfimodel.close(); - reporter.addEntry("RelPerfTest", "RelationshipDelete", "Execution time(s)", elapsedTimeLink, { count: opCount, sCount: seedCount, relType: "LinkTable" }); - reporter.addEntry("RelPerfTest", "RelationshipDelete", "Execution time(s)", elapsedTimeNav, { count: opCount, sCount: seedCount, relType: "NavProp" }); + reporter.addEntry("RelPerfTest", "RelationshipDelete", "Execution time(s)", elapsedTimeLink, { + count: opCount, + sCount: seedCount, + relType: "LinkTable", + }); + reporter.addEntry("RelPerfTest", "RelationshipDelete", "Execution time(s)", elapsedTimeNav, { + count: opCount, + sCount: seedCount, + relType: "NavProp", + }); }); }); diff --git a/full-stack-tests/backend/src/perftest/SchemaImport.test.ts b/full-stack-tests/backend/src/perftest/SchemaImport.test.ts index 220b1b3be9a7..4f1b85415021 100644 --- a/full-stack-tests/backend/src/perftest/SchemaImport.test.ts +++ b/full-stack-tests/backend/src/perftest/SchemaImport.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import * as path from "path"; -import { Reporter } from "@itwin/perf-tools"; import { IModelJsFs } from "@itwin/core-backend"; import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { Reporter } from "@itwin/perf-tools"; +import { assert } from "chai"; +import * as path from "path"; import { PerfTestDataMgr } from "./PerfTestUtils"; describe("SchemaDesignPerf Schema Import", () => { @@ -63,6 +63,5 @@ describe("SchemaDesignPerf Schema Import", () => { reporter.addEntry("SchemaImportPerfTest", "ENums", "Execution time(s)", elapsedTime, { enumCount: eCount }); tdm.closeDb(); } - }); }); diff --git a/full-stack-tests/backend/src/perftest/SchemaLoader.test.ts b/full-stack-tests/backend/src/perftest/SchemaLoader.test.ts index af06ea669663..9af916b40c64 100644 --- a/full-stack-tests/backend/src/perftest/SchemaLoader.test.ts +++ b/full-stack-tests/backend/src/perftest/SchemaLoader.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; -import { Reporter } from "@itwin/perf-tools"; import { _nativeDb, IModelHost, IModelJsFs, KnownLocations, StandaloneDb } from "@itwin/core-backend"; import { IModelTestUtils, KnownTestLocations } from "@itwin/core-backend/lib/cjs/test"; -import * as fs from "fs"; import { OpenMode } from "@itwin/core-bentley"; +import { Reporter } from "@itwin/perf-tools"; +import * as fs from "fs"; +import * as path from "path"; describe("SchemaLoaderPerformance", () => { let iModelFilepath: string; @@ -36,7 +36,7 @@ describe("SchemaLoaderPerformance", () => { const bisSchemaPaths = getBisSchemaPaths(); try { - await iModelDb.importSchemas(bisSchemaPaths); // will throw an exception if import fails + await iModelDb.importSchemas(bisSchemaPaths); // will throw an exception if import fails } catch (error) { throw new Error(`Failed to import schemas`); } @@ -92,27 +92,60 @@ describe("SchemaLoaderPerformance", () => { fs.copyFileSync(getSchemaPath("Dgn", "BisCore.ecschema.xml"), path.join(assetDir, "BisCore.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("process-functional-schema", "ProcessFunctional.ecschema.xml"), path.join(assetDir, "ProcessFunctional.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("process-physical-schema", "ProcessPhysical.ecschema.xml"), path.join(assetDir, "ProcessPhysical.ecschema.xml")); + fs.copyFileSync( + getSchemaPathFromPackage("process-functional-schema", "ProcessFunctional.ecschema.xml"), + path.join(assetDir, "ProcessFunctional.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("process-physical-schema", "ProcessPhysical.ecschema.xml"), + path.join(assetDir, "ProcessPhysical.ecschema.xml"), + ); fs.copyFileSync(getSchemaPathFromPackage("cif-bridge-schema", "CifBridge.ecschema.xml"), path.join(assetDir, "CifBridge.ecschema.xml")); fs.copyFileSync(getSchemaPathFromPackage("cif-common-schema", "CifCommon.ecschema.xml"), path.join(assetDir, "CifCommon.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-geometric-rules-schema", "CifGeometricRules.ecschema.xml"), path.join(assetDir, "CifGeometricRules.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-hydraulic-analysis-schema", "CifHydraulicAnalysis.ecschema.xml"), path.join(assetDir, "CifHydraulicAnalysis.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-hydraulic-results-schema", "CifHydraulicResults.ecschema.xml"), path.join(assetDir, "CifHydraulicResults.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-quantity-takeoffs-schema", "CifQuantityTakeoffs.ecschema.xml"), path.join(assetDir, "CifQuantityTakeoffs.ecschema.xml")); + fs.copyFileSync( + getSchemaPathFromPackage("cif-geometric-rules-schema", "CifGeometricRules.ecschema.xml"), + path.join(assetDir, "CifGeometricRules.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("cif-hydraulic-analysis-schema", "CifHydraulicAnalysis.ecschema.xml"), + path.join(assetDir, "CifHydraulicAnalysis.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("cif-hydraulic-results-schema", "CifHydraulicResults.ecschema.xml"), + path.join(assetDir, "CifHydraulicResults.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("cif-quantity-takeoffs-schema", "CifQuantityTakeoffs.ecschema.xml"), + path.join(assetDir, "CifQuantityTakeoffs.ecschema.xml"), + ); fs.copyFileSync(getSchemaPathFromPackage("cif-rail-schema", "CifRail.ecschema.xml"), path.join(assetDir, "CifRail.ecschema.xml")); fs.copyFileSync(getSchemaPathFromPackage("cif-roads-schema", "CifRoads.ecschema.xml"), path.join(assetDir, "CifRoads.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-subsurface-schema", "CifSubsurface.ecschema.xml"), path.join(assetDir, "CifSubsurface.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("cif-subsurface-conflict-analysis-schema", "CifSubsurfaceConflictAnalysis.ecschema.xml"), path.join(assetDir, "CifSubsurfaceConflictAnalysis.ecschema.xml")); + fs.copyFileSync( + getSchemaPathFromPackage("cif-subsurface-schema", "CifSubsurface.ecschema.xml"), + path.join(assetDir, "CifSubsurface.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("cif-subsurface-conflict-analysis-schema", "CifSubsurfaceConflictAnalysis.ecschema.xml"), + path.join(assetDir, "CifSubsurfaceConflictAnalysis.ecschema.xml"), + ); fs.copyFileSync(getSchemaPathFromPackage("cif-units-schema", "CifUnits.ecschema.xml"), path.join(assetDir, "CifUnits.ecschema.xml")); // Copy the required reference schemas fs.copyFileSync(getSchemaPath("Domain", "Functional.ecschema.xml"), path.join(assetDir, "Functional.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("plant-custom-attributes-schema", "PlantCustomAttributes.ecschema.xml"), path.join(assetDir, "PlantCustomAttributes.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("quantity-takeoffs-aspects-schema", "QuantityTakeoffsAspects.ecschema.xml"), path.join(assetDir, "QuantityTakeoffsAspects.ecschema.xml")); + fs.copyFileSync( + getSchemaPathFromPackage("plant-custom-attributes-schema", "PlantCustomAttributes.ecschema.xml"), + path.join(assetDir, "PlantCustomAttributes.ecschema.xml"), + ); + fs.copyFileSync( + getSchemaPathFromPackage("quantity-takeoffs-aspects-schema", "QuantityTakeoffsAspects.ecschema.xml"), + path.join(assetDir, "QuantityTakeoffsAspects.ecschema.xml"), + ); fs.copyFileSync(getSchemaPathFromPackage("aec-units-schema", "AecUnits.ecschema.xml"), path.join(assetDir, "AecUnits.ecschema.xml")); - fs.copyFileSync(getSchemaPathFromPackage("road-rail-units-schema", "RoadRailUnits.ecschema.xml"), path.join(assetDir, "RoadRailUnits.ecschema.xml")); + fs.copyFileSync( + getSchemaPathFromPackage("road-rail-units-schema", "RoadRailUnits.ecschema.xml"), + path.join(assetDir, "RoadRailUnits.ecschema.xml"), + ); } function timeBisSchemasLoading(schemaName: string) { @@ -131,7 +164,7 @@ describe("SchemaLoaderPerformance", () => { const imodel: StandaloneDb = StandaloneDb.openFile(iModelFilepath, OpenMode.Readonly); const startTime: number = new Date().getTime(); - const schemaResult = await imodel[_nativeDb].getSchemaPropsAsync(schemaName); + const schemaResult = await imodel[_nativeDb].getSchemaPropsAsync(schemaName); const endTime: number = new Date().getTime(); if (schemaResult === undefined) { diff --git a/full-stack-tests/backend/src/perftest/SchemaPerfConfig.json b/full-stack-tests/backend/src/perftest/SchemaPerfConfig.json index 18f50ebde341..9e6aa9436cde 100644 --- a/full-stack-tests/backend/src/perftest/SchemaPerfConfig.json +++ b/full-stack-tests/backend/src/perftest/SchemaPerfConfig.json @@ -67,4 +67,4 @@ 4000 ] } -} \ No newline at end of file +} diff --git a/full-stack-tests/backend/src/perftest/Sqlite.test.ts b/full-stack-tests/backend/src/perftest/Sqlite.test.ts index 2bb83ff784f8..d12a58897f8f 100644 --- a/full-stack-tests/backend/src/perftest/Sqlite.test.ts +++ b/full-stack-tests/backend/src/perftest/Sqlite.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ECDb, ECDbOpenMode, SQLiteDb, SqliteStatement } from "@itwin/core-backend"; +import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; +import { DbResult, OpenMode, StopWatch, using } from "@itwin/core-bentley"; import * as fs from "fs"; import * as os from "os"; import * as path from "path"; import * as readline from "readline"; -import { DbResult, OpenMode, StopWatch, using } from "@itwin/core-bentley"; -import { ECDb, ECDbOpenMode, SQLiteDb, SqliteStatement } from "@itwin/core-backend"; -import { KnownTestLocations } from "@itwin/core-backend/lib/cjs/test/index"; function makeRandStr(length: number) { let text = ""; @@ -28,7 +28,7 @@ async function reportProgress(prefix: string, c: number, m: number) { } async function createSeedFile(pathName: string, tbl: string, nCols: number, nRows: number, startId: number) { const kMaxLengthOfString = 11; - await using(new ECDb(), async (ecdb) => { + using(new ECDb(), async (ecdb) => { ecdb.createDb(pathName); const cols = []; for (let i = 0; i < nCols; i++) { @@ -37,7 +37,7 @@ async function createSeedFile(pathName: string, tbl: string, nCols: number, nRow const sp = new StopWatch(undefined, true); process.stdout.write(`Creating seed file ... ${pathName}\n`); ecdb.withPreparedSqliteStatement(`create table [${tbl}](id integer primary key,${cols.join(",")});`, (stmt) => stmt.step()); - await using(ecdb.prepareSqliteStatement(`insert into ${tbl} values(?${",?".repeat(nCols)});`), async (stmt: SqliteStatement) => { + using(ecdb.prepareSqliteStatement(`insert into ${tbl} values(?${",?".repeat(nCols)});`), async (stmt: SqliteStatement) => { for (let i = 0; i < nRows; i++) { stmt.reset(); stmt.clearBindings(); @@ -62,7 +62,13 @@ async function readRow(stmt: SqliteStatement, id: number, nParam: number = 1): P return stmt.step() === DbResult.BE_SQLITE_ROW && stmt.getValue(0).getInteger() === id; } -async function simulateRowRead(stmt: SqliteStatement, probabilityOfConsecutiveReads: number, percentageOfRowToRead: number, startId: number, endId: number) { +async function simulateRowRead( + stmt: SqliteStatement, + probabilityOfConsecutiveReads: number, + percentageOfRowToRead: number, + startId: number, + endId: number, +) { const nRows = endId - startId; const rowsToBeRead = Math.round((percentageOfRowToRead / 100) * nRows); let rowReadSoFar = 0; @@ -158,12 +164,18 @@ async function runReadTest(param: ReadParams) { const result: number[] = []; while (r++ < param.runCount) { process.stdout.write(`Run ... [${r}/${param.runCount}] `); - await using(new ECDb(), async (ecdb: ECDb) => { + using(new ECDb(), async (ecdb: ECDb) => { ecdb.openDb(testFilepath, ECDbOpenMode.Readonly); if (!ecdb.isOpen) throw new Error(`changePageSize() fail to open file ${testFilepath}`); await ecdb.withPreparedSqliteStatement(`select * from ${testTableName} where id=?`, async (stmt: SqliteStatement) => { - const elapsedTime = await simulateRowRead(stmt, param.probabilityOfConsecutiveReads, param.percentageOfRowsToRead, param.startId, param.startId + param.seedRowCount); + const elapsedTime = await simulateRowRead( + stmt, + param.probabilityOfConsecutiveReads, + param.percentageOfRowsToRead, + param.startId, + param.startId + param.seedRowCount, + ); result.push(elapsedTime); }); }); diff --git a/full-stack-tests/backend/tsconfig.json b/full-stack-tests/backend/tsconfig.json index f416c78a6163..ea61c0d4f558 100644 --- a/full-stack-tests/backend/tsconfig.json +++ b/full-stack-tests/backend/tsconfig.json @@ -3,4 +3,4 @@ "include": [ "./src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/full-stack-tests/core/eslint.config.js b/full-stack-tests/core/eslint.config.js index e626e3b08ba4..849e7479dee5 100644 --- a/full-stack-tests/core/eslint.config.js +++ b/full-stack-tests/core/eslint.config.js @@ -6,5 +6,5 @@ module.exports = [ files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, }, - ...eslintBaseConfig -]; \ No newline at end of file + ...eslintBaseConfig, +]; diff --git a/full-stack-tests/core/src/backend/AzuriteTest.ts b/full-stack-tests/core/src/backend/AzuriteTest.ts index 57ce7fd2234e..107aa5a99c0b 100644 --- a/full-stack-tests/core/src/backend/AzuriteTest.ts +++ b/full-stack-tests/core/src/backend/AzuriteTest.ts @@ -3,25 +3,26 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { emptyDirSync, mkdirsSync } from "fs-extra"; -import { join } from "path"; import * as azureBlob from "@azure/storage-blob"; import { BlobContainer, CloudSqlite, IModelHost, SettingsContainer } from "@itwin/core-backend"; import { AccessToken, Guid } from "@itwin/core-bentley"; import { LocalDirName, LocalFileName } from "@itwin/core-common"; +import { expect } from "chai"; +import { emptyDirSync, mkdirsSync } from "fs-extra"; +import { join } from "path"; // spell:ignore imodelid itwinid mkdirs devstoreaccount racwdl export namespace AzuriteTest { - export const storageType = "azure" as const; export const httpAddr = "127.0.0.1:10000"; export const accountName = "devstoreaccount1"; export const baseUri = `http://${httpAddr}/${accountName}`; export const getContainerUri = (id: string) => `${baseUri}/${id}`; - const pipeline = azureBlob.newPipeline(new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")); + const pipeline = azureBlob.newPipeline( + new azureBlob.StorageSharedKeyCredential(accountName, "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="), + ); export const createAzClient = (id: string) => new azureBlob.ContainerClient(getContainerUri(id), pipeline); export let userToken: AccessToken; @@ -74,7 +75,12 @@ export namespace AzuriteTest { emptyDirSync(name); }; - export interface TestContainerProps { containerId: string, logId?: string, isPublic?: boolean, writeable?: boolean } + export interface TestContainerProps { + containerId: string; + logId?: string; + isPublic?: boolean; + writeable?: boolean; + } export const makeContainer = async (arg: TestContainerProps): Promise => { const containerProps = { ...arg, writeable: true, baseUri, storageType }; @@ -95,7 +101,6 @@ export namespace AzuriteTest { const cacheDir = join(IModelHost.cacheDir, cacheName); makeEmptyDir(cacheDir); return CloudSqlite.CloudCaches.getCache({ cacheName, cacheDir }); - }; export const makeCaches = (names: string[]) => { const caches = []; @@ -104,7 +109,12 @@ export namespace AzuriteTest { return caches; }; - export const uploadFile = async (container: CloudSqlite.CloudContainer, cache: CloudSqlite.CloudCache, dbName: string, localFileName: LocalFileName) => { + export const uploadFile = async ( + container: CloudSqlite.CloudContainer, + cache: CloudSqlite.CloudCache, + dbName: string, + localFileName: LocalFileName, + ) => { expect(container.isConnected).false; container.connect(cache); expect(container.isConnected); diff --git a/full-stack-tests/core/src/backend/RpcImpl.ts b/full-stack-tests/core/src/backend/RpcImpl.ts index 7a7cc4fd9b9d..f6e29fe20ca3 100644 --- a/full-stack-tests/core/src/backend/RpcImpl.ts +++ b/full-stack-tests/core/src/backend/RpcImpl.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as nock from "nock"; -import * as path from "path"; import { _nativeDb, CloudSqlite, IModelDb, IModelHost, IModelJsFs, NativeHost, SnapshotDb, StandaloneDb, ViewStore } from "@itwin/core-backend"; import { V1CheckpointManager } from "@itwin/core-backend/lib/cjs/CheckpointManager"; +import { OpenMode } from "@itwin/core-bentley"; import { IModelRpcProps, RpcInterface, RpcManager } from "@itwin/core-common"; +import * as nock from "nock"; +import * as path from "path"; import { AzuriteUsers, TestRpcInterface } from "../common/RpcInterfaces"; import { AzuriteTest } from "./AzuriteTest"; -import { OpenMode } from "@itwin/core-bentley"; const viewContainer = "views-itwin1"; const storageType = "azure" as const; diff --git a/full-stack-tests/core/src/backend/TestEditCommands.ts b/full-stack-tests/core/src/backend/TestEditCommands.ts index 300f8ffc8079..92bf8eb41be2 100644 --- a/full-stack-tests/core/src/backend/TestEditCommands.ts +++ b/full-stack-tests/core/src/backend/TestEditCommands.ts @@ -9,7 +9,9 @@ import { testCmdIds, TestCmdOjb1, TestCmdResult, TestCommandIpc } from "../commo export abstract class TestCommand extends EditCommand implements TestCommandIpc { public count = 4; - public constructor(iModel: IModelDb, protected _str: string) { super(iModel); } + public constructor(iModel: IModelDb, protected _str: string) { + super(iModel); + } public abstract testMethod1(str1: string, str2: string, obj1: TestCmdOjb1): Promise; public override async requestFinish(): Promise { return --this.count >= 0 ? "edit command is busy" : "done"; diff --git a/full-stack-tests/core/src/backend/backend.ts b/full-stack-tests/core/src/backend/backend.ts index 74647b078086..dc04e3d57284 100644 --- a/full-stack-tests/core/src/backend/backend.ts +++ b/full-stack-tests/core/src/backend/backend.ts @@ -6,11 +6,19 @@ import "./RpcImpl"; // Sets up certa to allow a method on the frontend to get an access token import "@itwin/oidc-signin-tool/lib/cjs/certa/certaBackend"; -import * as fs from "fs"; -import * as path from "path"; import { - BriefcaseDb, FileNameResolver, IModelDb, IModelHost, IModelHostOptions, IpcHandler, IpcHost, LocalhostIpcHost, PhysicalModel, PhysicalPartition, - SpatialCategory, SubjectOwnsPartitionElements, + BriefcaseDb, + FileNameResolver, + IModelDb, + IModelHost, + IModelHostOptions, + IpcHandler, + IpcHost, + LocalhostIpcHost, + PhysicalModel, + PhysicalPartition, + SpatialCategory, + SubjectOwnsPartitionElements, } from "@itwin/core-backend"; import { Id64String, Logger, ProcessDetector } from "@itwin/core-bentley"; import { BentleyCloudRpcManager, CodeProps, ElementProps, IModel, RelatedElement, RpcConfiguration, SubCategoryAppearance } from "@itwin/core-common"; @@ -21,6 +29,8 @@ import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; import { WebEditServer } from "@itwin/express-server"; import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; import { IModelsClient } from "@itwin/imodels-client-authoring"; +import * as fs from "fs"; +import * as path from "path"; import { exposeBackendCallbacks } from "../certa/certaBackend"; import { fullstackIpcChannel, FullStackTestIpc } from "../common/FullStackTestIpc"; import { rpcInterfaces } from "../common/RpcInterfaces"; @@ -43,7 +53,9 @@ function loadEnv(envFile: string) { } class FullStackTestIpcHandler extends IpcHandler implements FullStackTestIpc { - public get channelName() { return fullstackIpcChannel; } + public get channelName() { + return fullstackIpcChannel; + } public static async createAndInsertPartition(iModelDb: IModelDb, newModelCode: CodeProps): Promise { const modeledElementProps: ElementProps = { @@ -64,7 +76,12 @@ class FullStackTestIpcHandler extends IpcHandler implements FullStackTestIpc { return iModelDb.models.insertModel(newModel.toJSON()); } - public async createAndInsertSpatialCategory(key: string, scopeModelId: Id64String, categoryName: string, appearance: SubCategoryAppearance.Props): Promise { + public async createAndInsertSpatialCategory( + key: string, + scopeModelId: Id64String, + categoryName: string, + appearance: SubCategoryAppearance.Props, + ): Promise { const iModelDb = IModelDb.findByKey(key); const category = SpatialCategory.create(iModelDb, scopeModelId, categoryName); const categoryId = category.insert(); @@ -85,7 +102,7 @@ async function init() { const iModelHost: IModelHostOptions = {}; const iModelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); iModelHost.hubAccess = new BackendIModelsAccess(iModelClient); - iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir + iModelHost.cacheDir = path.join(__dirname, ".cache"); // Set local cache dir let shutdown: undefined | (() => Promise); @@ -93,7 +110,9 @@ async function init() { exposeBackendCallbacks(); const authClient = new ElectronMainAuthorization({ clientId: process.env.IMJS_OIDC_ELECTRON_TEST_CLIENT_ID ?? "testClientId", - redirectUris: process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI !== undefined ? [process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI] : ["testRedirectUri"], + redirectUris: process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI !== undefined + ? [process.env.IMJS_OIDC_ELECTRON_TEST_REDIRECT_URI] + : ["testRedirectUri"], scopes: process.env.IMJS_OIDC_ELECTRON_TEST_SCOPES ?? "testScope", }); await authClient.signInSilent(); @@ -143,9 +162,12 @@ class BackendTestAssetResolver extends FileNameResolver { // eslint-disable-line /** Resolve a key (for testing FileNameResolver) */ public override tryResolveKey(fileKey: string): string | undefined { switch (fileKey) { - case "test-key": return this.tryResolveFileName("test.bim"); - case "test2-key": return this.tryResolveFileName("test2.bim"); - default: return undefined; + case "test-key": + return this.tryResolveFileName("test.bim"); + case "test2-key": + return this.tryResolveFileName("test2.bim"); + default: + return undefined; } } } diff --git a/full-stack-tests/core/src/certa/certaBackend.ts b/full-stack-tests/core/src/certa/certaBackend.ts index cf3b36b587e6..017be051e793 100644 --- a/full-stack-tests/core/src/certa/certaBackend.ts +++ b/full-stack-tests/core/src/certa/certaBackend.ts @@ -4,15 +4,15 @@ *--------------------------------------------------------------------------------------------*/ import { registerBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; -import { getTokenCallbackName } from "./certaCommon"; -import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; -import { AccessToken } from "@itwin/core-bentley"; import { IModelHost } from "@itwin/core-backend"; +import { AccessToken } from "@itwin/core-bentley"; +import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; import { TestUtility } from "../frontend/TestUtility"; +import { getTokenCallbackName } from "./certaCommon"; // A backend to use within Certa's `backendInitModule` to setup OIDC sign-in -export function exposeBackendCallbacks(){ +export function exposeBackendCallbacks() { registerBackendCallback(getTokenCallbackName, async (user: any): Promise => { const accessToken = await TestUtility.getAccessToken(user, { clientId: process.env.IMJS_OIDC_ELECTRON_TEST_CLIENT_ID ?? "testClientId", diff --git a/full-stack-tests/core/src/certa/certaCommon.ts b/full-stack-tests/core/src/certa/certaCommon.ts index f058ef445b4e..f07a29407f46 100644 --- a/full-stack-tests/core/src/certa/certaCommon.ts +++ b/full-stack-tests/core/src/certa/certaCommon.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { executeBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; -import { TestUserCredentials } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; import { AccessToken } from "@itwin/core-bentley"; +import { TestUserCredentials } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; // Shared by both the frontend and backend side of the tests export const getTokenCallbackName = "setBackendAccessToken"; diff --git a/full-stack-tests/core/src/common/FullStackTestIpc.ts b/full-stack-tests/core/src/common/FullStackTestIpc.ts index 03d1a781cf15..ae7a0cd0ec61 100644 --- a/full-stack-tests/core/src/common/FullStackTestIpc.ts +++ b/full-stack-tests/core/src/common/FullStackTestIpc.ts @@ -3,12 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CodeProps, SubCategoryAppearance } from "@itwin/core-common"; import { Id64String } from "@itwin/core-bentley"; +import { CodeProps, SubCategoryAppearance } from "@itwin/core-common"; export const fullstackIpcChannel = "full-stack-tests/fullStackIpc"; export interface FullStackTestIpc { createAndInsertPhysicalModel(key: string, newModelCode: CodeProps): Promise; - createAndInsertSpatialCategory(key: string, scopeModelId: Id64String, categoryName: string, appearance: SubCategoryAppearance.Props): Promise; + createAndInsertSpatialCategory( + key: string, + scopeModelId: Id64String, + categoryName: string, + appearance: SubCategoryAppearance.Props, + ): Promise; closeAndReopenDb(key: string): Promise; } diff --git a/full-stack-tests/core/src/common/IModelHubUserMgr.ts b/full-stack-tests/core/src/common/IModelHubUserMgr.ts index a571aff6b7f2..0e0dcc26d5e4 100644 --- a/full-stack-tests/core/src/common/IModelHubUserMgr.ts +++ b/full-stack-tests/core/src/common/IModelHubUserMgr.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { AccessToken, BeEvent } from "@itwin/core-bentley"; -import { getAccessTokenFromBackend } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; import { AuthorizationClient } from "@itwin/core-common"; +import { getAccessTokenFromBackend } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; export class IModelHubUserMgr implements AuthorizationClient { private _token: AccessToken = ""; diff --git a/full-stack-tests/core/src/common/ITwinAccessClientWrapper.ts b/full-stack-tests/core/src/common/ITwinAccessClientWrapper.ts index 6e8d4d8638f2..3085a96e2736 100644 --- a/full-stack-tests/core/src/common/ITwinAccessClientWrapper.ts +++ b/full-stack-tests/core/src/common/ITwinAccessClientWrapper.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; import { AccessToken } from "@itwin/core-bentley"; +import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; /** An implementation of TestITwin backed by an iTwin project */ export class ITwinAccessClientWrapper { diff --git a/full-stack-tests/core/src/common/RpcInterfaces.ts b/full-stack-tests/core/src/common/RpcInterfaces.ts index edf75603e0bd..4e40e6cbc5cc 100644 --- a/full-stack-tests/core/src/common/RpcInterfaces.ts +++ b/full-stack-tests/core/src/common/RpcInterfaces.ts @@ -4,7 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { AccessToken, GuidString } from "@itwin/core-bentley"; import { - DevToolsRpcInterface, IModelReadRpcInterface, IModelRpcProps, IModelTileRpcInterface, RpcInterface, RpcManager, SnapshotIModelRpcInterface, + DevToolsRpcInterface, + IModelReadRpcInterface, + IModelRpcProps, + IModelTileRpcInterface, + RpcInterface, + RpcManager, + SnapshotIModelRpcInterface, } from "@itwin/core-common"; import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common"; @@ -56,7 +62,9 @@ export abstract class EventsTestRpcInterface extends RpcInterface { } // Set a event that would be fired from backend and received on frontend. - public async echo(_id: GuidString, _message: string): Promise { return this.forward(arguments); } + public async echo(_id: GuidString, _message: string): Promise { + return this.forward(arguments); + } } export const rpcInterfaces = [ diff --git a/full-stack-tests/core/src/frontend/Editing.ts b/full-stack-tests/core/src/frontend/Editing.ts index c663e928f26a..cd5cadff0dcc 100644 --- a/full-stack-tests/core/src/frontend/Editing.ts +++ b/full-stack-tests/core/src/frontend/Editing.ts @@ -30,7 +30,12 @@ export function makeLineSegment(p1?: Point3d, p2?: Point3d): LineSegment3d { return LineSegment3d.create(p1 || new Point3d(0, 0, 0), p2 || new Point3d(1, 1, 0)); } -export async function insertLineElement(imodel: BriefcaseConnection, model: Id64String, category: Id64String, line?: LineSegment3d): Promise { +export async function insertLineElement( + imodel: BriefcaseConnection, + model: Id64String, + category: Id64String, + line?: LineSegment3d, +): Promise { await startCommand(imodel); line = line ?? makeLineSegment(); @@ -42,11 +47,21 @@ export async function insertLineElement(imodel: BriefcaseConnection, model: Id64 if (!builder.appendGeometry(line)) return Id64.invalid; - const elemProps: PhysicalElementProps = { classFullName: "Generic:PhysicalObject", model, category, code: Code.createEmpty(), placement: { origin, angles }, geom: builder.geometryStream }; + const elemProps: PhysicalElementProps = { + classFullName: "Generic:PhysicalObject", + model, + category, + code: Code.createEmpty(), + placement: { origin, angles }, + geom: builder.geometryStream, + }; return basicManipulationIpc.insertGeometricElement(elemProps); } -export async function insertLineStringElement(imodel: BriefcaseConnection, lineString: { model: Id64String, category: Id64String, points: Point3d[], color?: ColorDef }): Promise { +export async function insertLineStringElement( + imodel: BriefcaseConnection, + lineString: { model: Id64String, category: Id64String, points: Point3d[], color?: ColorDef }, +): Promise { await startCommand(imodel); const builder = new GeometryStreamBuilder(); const origin = lineString.points[0] ?? new Point3d(); diff --git a/full-stack-tests/core/src/frontend/HttpRequestHook.ts b/full-stack-tests/core/src/frontend/HttpRequestHook.ts index dfa0ed1e8418..27c71ada948a 100644 --- a/full-stack-tests/core/src/frontend/HttpRequestHook.ts +++ b/full-stack-tests/core/src/frontend/HttpRequestHook.ts @@ -323,7 +323,7 @@ export interface IHttpHandler { } class HttpHandler implements IHttpHandler { public static handlers: HttpHandler[] = []; - constructor(private _urlRegEx: RegExp | string) { } + constructor(private _urlRegEx: RegExp | string) {} public before?: (input: Request) => Response | undefined | null; public after?: (input: Response) => Response; public canHandle(url: string): boolean { @@ -348,7 +348,6 @@ class HttpHandler implements IHttpHandler { this.handlers.push(handler); return handler; } - } export class HttpRequestHook { public static install() { diff --git a/full-stack-tests/core/src/frontend/TestUtility.ts b/full-stack-tests/core/src/frontend/TestUtility.ts index 139f3d636f2a..6728de411cc2 100644 --- a/full-stack-tests/core/src/frontend/TestUtility.ts +++ b/full-stack-tests/core/src/frontend/TestUtility.ts @@ -2,18 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { AccessToken, GuidString, Logger, ProcessDetector } from "@itwin/core-bentley"; -import { ITwin } from "@itwin/itwins-client"; import { AuthorizationClient } from "@itwin/core-common"; -import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { IModelApp, IModelAppOptions, LocalhostIpcApp, MockRender, NativeApp } from "@itwin/core-frontend"; -import { getAccessTokenFromBackend, TestBrowserAuthorizationClientConfiguration, TestUserCredentials } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; +import { ITwin } from "@itwin/itwins-client"; +import { + getAccessTokenFromBackend, + TestBrowserAuthorizationClientConfiguration, + TestUserCredentials, +} from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { assert } from "chai"; +import { setBackendAccessToken } from "../certa/certaCommon"; import { IModelHubUserMgr } from "../common/IModelHubUserMgr"; import { rpcInterfaces } from "../common/RpcInterfaces"; import { ITwinPlatformAbstraction, ITwinPlatformCloudEnv } from "./hub/ITwinPlatformEnv"; -import { setBackendAccessToken } from "../certa/certaCommon"; export class TestUtility { public static testITwinName = "iModelJsIntegrationTest"; @@ -74,7 +78,6 @@ export class TestUtility { const accessToken = await setBackendAccessToken(user); if ("" === accessToken) throw new Error("no access token"); - } else { authorizationClient = new IModelHubUserMgr(user); IModelApp.authorizationClient = authorizationClient; @@ -128,7 +131,9 @@ export class TestUtility { } public static systemFactory: MockRender.SystemFactory = () => TestUtility.createDefaultRenderSystem(); - private static createDefaultRenderSystem() { return new MockRender.System(); } + private static createDefaultRenderSystem() { + return new MockRender.System(); + } /** Helper around the different startup workflows for different app types. * If running in an Electron render process (via ProcessDetector.isElectronAppFrontend), the ElectronApp.startup is called. diff --git a/full-stack-tests/core/src/frontend/TestViewport.ts b/full-stack-tests/core/src/frontend/TestViewport.ts index 6c1ebfde5454..f128c9bfad7a 100644 --- a/full-stack-tests/core/src/frontend/TestViewport.ts +++ b/full-stack-tests/core/src/frontend/TestViewport.ts @@ -2,12 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64String, SortedArray } from "@itwin/core-bentley"; import { ColorDef, Feature, GeometryClass } from "@itwin/core-common"; import { - IModelApp, IModelConnection, OffScreenViewport, Pixel, ScreenViewport, Tile, TileTreeLoadStatus, Viewport, ViewRect, + IModelApp, + IModelConnection, + OffScreenViewport, + Pixel, + ScreenViewport, + Tile, + TileTreeLoadStatus, + Viewport, + ViewRect, } from "@itwin/core-frontend"; +import { expect } from "chai"; function compareFeatures(lhs?: Feature, rhs?: Feature): number { if (undefined === lhs && undefined === rhs) @@ -40,18 +48,29 @@ export class PixelDataSet extends SortedArray { super((lhs: Pixel.Data, rhs: Pixel.Data) => comparePixelData(lhs, rhs)); } - public get array(): Pixel.Data[] { return this._array; } + public get array(): Pixel.Data[] { + return this._array; + } public containsFeature(elemId?: Id64String, subcatId?: Id64String, geomClass?: GeometryClass) { return this.containsWhere((pxl) => (undefined === elemId || pxl.elementId === elemId) && (undefined === subcatId || pxl.subCategoryId === subcatId) && - (undefined === geomClass || pxl.geometryClass === geomClass)); + (undefined === geomClass || pxl.geometryClass === geomClass) + ); + } + public containsElement(id: Id64String) { + return this.containsWhere((pxl) => pxl.elementId === id); + } + public containsPlanarity(planarity: Pixel.Planarity) { + return this.containsWhere((pxl) => pxl.planarity === planarity); + } + public containsGeometryType(type: Pixel.GeometryType) { + return this.containsWhere((pxl) => pxl.type === type); + } + public containsGeometry(type: Pixel.GeometryType, planarity: Pixel.Planarity) { + return this.containsWhere((pxl) => pxl.type === type && pxl.planarity === planarity); } - public containsElement(id: Id64String) { return this.containsWhere((pxl) => pxl.elementId === id); } - public containsPlanarity(planarity: Pixel.Planarity) { return this.containsWhere((pxl) => pxl.planarity === planarity); } - public containsGeometryType(type: Pixel.GeometryType) { return this.containsWhere((pxl) => pxl.type === type); } - public containsGeometry(type: Pixel.GeometryType, planarity: Pixel.Planarity) { return this.containsWhere((pxl) => pxl.type === type && pxl.planarity === planarity); } public containsWhere(criterion: (pxl: Pixel.Data) => boolean) { for (const pixel of this.array) if (criterion(pixel)) @@ -79,7 +98,9 @@ export class Color { this.a = ((val & 0xff000000) >>> 0x18) >>> 0; } - public static from(val: number) { return new Color(val); } + public static from(val: number) { + return new Color(val); + } public static fromRgba(r: number, g: number, b: number, a: number) { const v = (r | (g << 0x08) | (b << 0x10) | (a << 0x18)) >>> 0; return Color.from(v); @@ -101,8 +122,12 @@ export class Color { } export class ColorSet extends SortedArray { - public constructor() { super((lhs: Color, rhs: Color) => lhs.compare(rhs)); } - public get array(): Color[] { return this._array; } + public constructor() { + super((lhs: Color, rhs: Color) => lhs.compare(rhs)); + } + public get array(): Color[] { + return this._array; + } } // Read depth, geometry type, and feature for each pixel. Return only the unique ones. @@ -201,11 +226,21 @@ export interface TestableViewport { } class OffScreenTestViewport extends OffScreenViewport implements TestableViewport { - public readUniquePixelData(readRect?: ViewRect, excludeNonLocatable = false): PixelDataSet { return readUniquePixelData(this, readRect, excludeNonLocatable); } - public readUniqueColors(readRect?: ViewRect): ColorSet { return readUniqueColors(this, readRect); } - public readColor(x: number, y: number): Color { return readColor(this, x, y); } - public readPixel(x: number, y: number, excludeNonLocatable?: boolean): Pixel.Data { return readPixel(this, x, y, excludeNonLocatable); } - public get areAllTilesLoaded(): boolean { return areAllTilesLoaded(this); } + public readUniquePixelData(readRect?: ViewRect, excludeNonLocatable = false): PixelDataSet { + return readUniquePixelData(this, readRect, excludeNonLocatable); + } + public readUniqueColors(readRect?: ViewRect): ColorSet { + return readUniqueColors(this, readRect); + } + public readColor(x: number, y: number): Color { + return readColor(this, x, y); + } + public readPixel(x: number, y: number, excludeNonLocatable?: boolean): Pixel.Data { + return readPixel(this, x, y, excludeNonLocatable); + } + public get areAllTilesLoaded(): boolean { + return areAllTilesLoaded(this); + } public async waitForAllTilesToRender(): Promise { this.renderFrame(); @@ -223,7 +258,12 @@ class OffScreenTestViewport extends OffScreenViewport implements TestableViewpor return this.waitForAllTilesToRender(); } - public static async createTestViewport(viewId: Id64String, imodel: IModelConnection, width: number, height: number): Promise { + public static async createTestViewport( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, + ): Promise { const view = await imodel.views.load(viewId); const rect = new ViewRect(0, 0, width, height); const vp = this.create({ view, viewRect: rect }) as OffScreenTestViewport; @@ -242,11 +282,21 @@ class OffScreenTestViewport extends OffScreenViewport implements TestableViewpor export class ScreenTestViewport extends ScreenViewport implements TestableViewport { private _frameRendered: boolean = false; - public readUniquePixelData(readRect?: ViewRect, excludeNonLocatable = false): PixelDataSet { return readUniquePixelData(this, readRect, excludeNonLocatable); } - public readUniqueColors(readRect?: ViewRect): ColorSet { return readUniqueColors(this, readRect); } - public readColor(x: number, y: number): Color { return readColor(this, x, y); } - public readPixel(x: number, y: number, excludeNonLocatable?: boolean): Pixel.Data { return readPixel(this, x, y, excludeNonLocatable); } - public get areAllTilesLoaded(): boolean { return areAllTilesLoaded(this); } + public readUniquePixelData(readRect?: ViewRect, excludeNonLocatable = false): PixelDataSet { + return readUniquePixelData(this, readRect, excludeNonLocatable); + } + public readUniqueColors(readRect?: ViewRect): ColorSet { + return readUniqueColors(this, readRect); + } + public readColor(x: number, y: number): Color { + return readColor(this, x, y); + } + public readPixel(x: number, y: number, excludeNonLocatable?: boolean): Pixel.Data { + return readPixel(this, x, y, excludeNonLocatable); + } + public get areAllTilesLoaded(): boolean { + return areAllTilesLoaded(this); + } private async waitForRenderFrame(): Promise { if (this._frameRendered) { @@ -309,12 +359,23 @@ export class ScreenTestViewport extends ScreenViewport implements TestableViewpo export type TestViewport = Viewport & TestableViewport; // Create an off-screen viewport for tests. -export async function createOffScreenTestViewport(viewId: Id64String, imodel: IModelConnection, width: number, height: number): Promise { +export async function createOffScreenTestViewport( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, +): Promise { return OffScreenTestViewport.createTestViewport(viewId, imodel, width, height); } // Create an on-screen viewport for tests. The viewport is added to the ViewManager on construction, and dropped on disposal. -export async function createOnScreenTestViewport(viewId: Id64String, imodel: IModelConnection, width: number, height: number, devicePixelRatio?: number): Promise { +export async function createOnScreenTestViewport( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, + devicePixelRatio?: number, +): Promise { const vp = await ScreenTestViewport.createTestViewport(viewId, imodel, width, height); if (undefined !== devicePixelRatio) { const debugControl = vp.target.debugControl; @@ -325,7 +386,14 @@ export async function createOnScreenTestViewport(viewId: Id64String, imodel: IMo return vp; } -export async function testOnScreenViewport(viewId: Id64String, imodel: IModelConnection, width: number, height: number, test: (vp: ScreenTestViewport) => Promise, devicePixelRatio?: number): Promise { +export async function testOnScreenViewport( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, + test: (vp: ScreenTestViewport) => Promise, + devicePixelRatio?: number, +): Promise { if (!IModelApp.initialized) return; @@ -340,7 +408,13 @@ export async function testOnScreenViewport(viewId: Id64String, imodel: IModelCon } } -export async function testOffScreenViewport(viewId: Id64String, imodel: IModelConnection, width: number, height: number, test: (vp: TestViewport) => Promise): Promise { +export async function testOffScreenViewport( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, + test: (vp: TestViewport) => Promise, +): Promise { if (!IModelApp.initialized) return; @@ -353,7 +427,14 @@ export async function testOffScreenViewport(viewId: Id64String, imodel: IModelCo } // Execute a test against both an off-screen and on-screen viewport. -export async function testViewports(viewId: Id64String, imodel: IModelConnection, width: number, height: number, test: (vp: TestViewport) => Promise, devicePixelRatio?: number): Promise { +export async function testViewports( + viewId: Id64String, + imodel: IModelConnection, + width: number, + height: number, + test: (vp: TestViewport) => Promise, + devicePixelRatio?: number, +): Promise { if (!IModelApp.initialized) return; diff --git a/full-stack-tests/core/src/frontend/ViewportChangedHandler.ts b/full-stack-tests/core/src/frontend/ViewportChangedHandler.ts index 8e1a5773fcf4..3fa440a00901 100644 --- a/full-stack-tests/core/src/frontend/ViewportChangedHandler.ts +++ b/full-stack-tests/core/src/frontend/ViewportChangedHandler.ts @@ -2,11 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration } from "@itwin/core-bentley"; -import { - ChangeFlag, ChangeFlags, MutableChangeFlags, Viewport, -} from "@itwin/core-frontend"; +import { ChangeFlag, ChangeFlags, MutableChangeFlags, Viewport } from "@itwin/core-frontend"; +import { expect } from "chai"; /** Aspects of a Viewport that can become invalidated when its state changes. */ export enum ViewportState { diff --git a/full-stack-tests/core/src/frontend/_Setup.test.ts b/full-stack-tests/core/src/frontend/_Setup.test.ts index 9660346a089e..e9a4cd254f28 100644 --- a/full-stack-tests/core/src/frontend/_Setup.test.ts +++ b/full-stack-tests/core/src/frontend/_Setup.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, Assertion, util } from "chai"; import { ProcessDetector, UnexpectedErrors } from "@itwin/core-bentley"; import { BentleyCloudRpcManager, BentleyCloudRpcParams, RpcConfiguration } from "@itwin/core-common"; -import { rpcInterfaces } from "../common/RpcInterfaces"; import { Geometry } from "@itwin/core-geometry"; +import { assert, Assertion, util } from "chai"; +import { rpcInterfaces } from "../common/RpcInterfaces"; RpcConfiguration.developmentMode = true; RpcConfiguration.disableRoutingValidation = true; @@ -95,10 +95,8 @@ Assertion.addMethod( isDeep ? deepEqualWithFpTolerance(expected, actual, options) : isAlmostEqualNumber(expected, actual, options.tolerance), - `expected ${isDeep ? "deep equality of " : " " - }#{exp} and #{act} with a tolerance of ${options.tolerance}`, - `expected ${isDeep ? "deep inequality of " : " " - }#{exp} and #{act} with a tolerance of ${options.tolerance}`, + `expected ${isDeep ? "deep equality of " : " "}#{exp} and #{act} with a tolerance of ${options.tolerance}`, + `expected ${isDeep ? "deep inequality of " : " "}#{exp} and #{act} with a tolerance of ${options.tolerance}`, expected, actual, ); diff --git a/full-stack-tests/core/src/frontend/app/NativeApp.test.ts b/full-stack-tests/core/src/frontend/app/NativeApp.test.ts index d6f100bdf190..b2e6fe29075c 100644 --- a/full-stack-tests/core/src/frontend/app/NativeApp.test.ts +++ b/full-stack-tests/core/src/frontend/app/NativeApp.test.ts @@ -2,16 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; +import { ProcessDetector } from "@itwin/core-bentley"; import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { NativeApp } from "@itwin/core-frontend"; -import { usingOfflineScope } from "../HttpRequestHook"; +import { assert } from "chai"; import { TestRpcInterface } from "../../common/RpcInterfaces"; -import { ProcessDetector } from "@itwin/core-bentley"; +import { usingOfflineScope } from "../HttpRequestHook"; import { TestUtility } from "../TestUtility"; if (ProcessDetector.isElectronAppFrontend) { - describe("NativeApp startup", () => { before(async () => { await TestUtility.startFrontend(); @@ -106,5 +105,4 @@ if (ProcessDetector.isElectronAppFrontend) { await NativeApp.closeStorage(test1, true); }); }); - } diff --git a/full-stack-tests/core/src/frontend/hub/ExternalTextures.test.ts b/full-stack-tests/core/src/frontend/hub/ExternalTextures.test.ts index 2c8257009a61..5eeed16bc889 100644 --- a/full-stack-tests/core/src/frontend/hub/ExternalTextures.test.ts +++ b/full-stack-tests/core/src/frontend/hub/ExternalTextures.test.ts @@ -2,33 +2,88 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ImageSource, ImageSourceFormat, RenderTexture } from "@itwin/core-common"; import { CheckpointConnection, imageElementFromImageSource, IModelApp, IModelConnection } from "@itwin/core-frontend"; import { ExternalTextureLoader, ExternalTextureRequest, GL, Texture2DHandle } from "@itwin/core-frontend/lib/cjs/webgl"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("external texture requests (#integration)", () => { - let imodel: IModelConnection; const texNames = [ - "0x48", "0x4b", "0x52", "0x54", "0x56", "0x59", + "0x48", + "0x4b", + "0x52", + "0x54", + "0x56", + "0x59", "0x01", // bad request - "0x5e", "0x60", "0x64", "0x66", "0x69", "0x6d", - "0x6f", "0x71", "0x73", "0x75", "0x7c", "0x7f", + "0x5e", + "0x60", + "0x64", + "0x66", + "0x69", + "0x6d", + "0x6f", + "0x71", + "0x73", + "0x75", + "0x7c", + "0x7f", "0x02", // bad request - "0x82", "0x85", "0x8a", "0x8c", "0x8f", "0x91", - "0x94", "0x97", "0x99", "0x9b", "0x9d", "0x9f", + "0x82", + "0x85", + "0x8a", + "0x8c", + "0x8f", + "0x91", + "0x94", + "0x97", + "0x99", + "0x9b", + "0x9d", + "0x9f", "0x03", // bad request - "0xa1", "0xa3", "0xa5"]; + "0xa1", + "0xa3", + "0xa5", + ]; const goodTexNames = [ - "0x48", "0x4b", "0x52", "0x54", "0x56", "0x59", - "0x5e", "0x60", "0x64", "0x66", "0x69", "0x6d", - "0x6f", "0x71", "0x73", "0x75", "0x7c", "0x7f", - "0x82", "0x85", "0x8a", "0x8c", "0x8f", "0x91", - "0x94", "0x97", "0x99", "0x9b", "0x9d", "0x9f", - "0xa1", "0xa3", "0xa5"]; + "0x48", + "0x4b", + "0x52", + "0x54", + "0x56", + "0x59", + "0x5e", + "0x60", + "0x64", + "0x66", + "0x69", + "0x6d", + "0x6f", + "0x71", + "0x73", + "0x75", + "0x7c", + "0x7f", + "0x82", + "0x85", + "0x8a", + "0x8c", + "0x8f", + "0x91", + "0x94", + "0x97", + "0x99", + "0x9b", + "0x9d", + "0x9f", + "0xa1", + "0xa3", + "0xa5", + ]; const numExpectedBadRequests = 3; const finishedTexRequests: Array = []; const extTexLoader = ExternalTextureLoader.instance; diff --git a/full-stack-tests/core/src/frontend/hub/HyperModeling.test.ts b/full-stack-tests/core/src/frontend/hub/HyperModeling.test.ts index 8d069dabbeca..657cbff08407 100644 --- a/full-stack-tests/core/src/frontend/hub/HyperModeling.test.ts +++ b/full-stack-tests/core/src/frontend/hub/HyperModeling.test.ts @@ -2,17 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ProcessDetector } from "@itwin/core-bentley"; import { SectionType } from "@itwin/core-common"; import { CheckpointConnection, IModelApp, IModelConnection, ParseAndRunResult, SnapshotConnection } from "@itwin/core-frontend"; import { Point3d } from "@itwin/core-geometry"; import { - HyperModeling, HyperModelingDecorator, SectionDrawingLocationState, SectionMarker, SectionMarkerConfig, SectionMarkerHandler, + HyperModeling, + HyperModelingDecorator, + SectionDrawingLocationState, + SectionMarker, + SectionMarkerConfig, + SectionMarkerHandler, } from "@itwin/hypermodeling-frontend"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/TestUsers"; -import { testOnScreenViewport } from "../TestViewport"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; +import { testOnScreenViewport } from "../TestViewport"; describe("HyperModeling (#integration)", () => { let imodel: IModelConnection; // An iModel containing no section drawing locations @@ -88,7 +93,8 @@ describe("HyperModeling (#integration)", () => { const actual = states.find((state) => state.id === expected.id && state.sectionType === expected.type && state.userLabel === expected.label && state.placement.origin.isAlmostEqual(expected.origin, 0.001) && state.drawingViewId === expected.sectionViewId && - state.spatialViewId === expected.spatialViewId && state.viewAttachment?.id === expected.viewAttachmentId)!; + state.spatialViewId === expected.spatialViewId && state.viewAttachment?.id === expected.viewAttachmentId + )!; expect(actual).not.to.be.undefined; expect(await actual.tryLoadDrawingView()).not.to.be.undefined; @@ -203,7 +209,7 @@ describe("HyperModeling (#integration)", () => { HyperModeling.replaceConfiguration(); }); - it("adjusts marker display via key-in", async function () { + it("adjusts marker display via key-in", async function() { if (ProcessDetector.isElectronAppFrontend) { // The electron version fails to find/parse the hypermodeling package's JSON file containing its keyins. // The browser version has no such problem. @@ -241,8 +247,10 @@ describe("HyperModeling (#integration)", () => { // Activating/deactivating markers is a no-op class Handler extends SectionMarkerHandler { - public override async activateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { return true; } - public override async deactivateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { } + public override async activateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { + return true; + } + public override async deactivateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) {} } HyperModeling.updateConfiguration({ markerHandler: new Handler() }); @@ -356,8 +364,10 @@ describe("HyperModeling (#integration)", () => { class Handler extends SectionMarkerHandler { public static visible = true; - public override async activateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { return true; } - public override async deactivateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { } + public override async activateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) { + return true; + } + public override async deactivateMarker(_marker: SectionMarker, _decorator: HyperModelingDecorator) {} public override isMarkerVisible(_marker: SectionMarker, _dec: HyperModelingDecorator, _config: SectionMarkerConfig): boolean { return super.isMarkerVisible(_marker, _dec, _config) && Handler.visible; } diff --git a/full-stack-tests/core/src/frontend/hub/IModelConnection.test.ts b/full-stack-tests/core/src/frontend/hub/IModelConnection.test.ts index 8f25a6d139f3..aaae53bba4a4 100644 --- a/full-stack-tests/core/src/frontend/hub/IModelConnection.test.ts +++ b/full-stack-tests/core/src/frontend/hub/IModelConnection.test.ts @@ -2,15 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64, Logger, LogLevel, ProcessDetector } from "@itwin/core-bentley"; import { BisCodeSpec, IModelVersion, QueryBinder, QueryRowFormat, RelatedElement } from "@itwin/core-common"; import { - CategorySelectorState, CheckpointConnection, DisplayStyle2dState, DisplayStyle3dState, DrawingViewState, IModelApp, IModelConnection, - ModelSelectorState, OrthographicViewState, ViewState, + CategorySelectorState, + CheckpointConnection, + DisplayStyle2dState, + DisplayStyle3dState, + DrawingViewState, + IModelApp, + IModelConnection, + ModelSelectorState, + OrthographicViewState, + ViewState, } from "@itwin/core-frontend"; import { Range3d, Transform } from "@itwin/core-geometry"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; async function executeQuery(iModel: IModelConnection, ecsql: string, bindings?: any[] | object): Promise { diff --git a/full-stack-tests/core/src/frontend/hub/ITwinPlatformEnv.ts b/full-stack-tests/core/src/frontend/hub/ITwinPlatformEnv.ts index 3924c79bc96e..7769d5ed76dd 100644 --- a/full-stack-tests/core/src/frontend/hub/ITwinPlatformEnv.ts +++ b/full-stack-tests/core/src/frontend/hub/ITwinPlatformEnv.ts @@ -6,7 +6,17 @@ import { AccessToken, GuidString } from "@itwin/core-bentley"; import { AuthorizationClient, BriefcaseId } from "@itwin/core-common"; import { FrontendHubAccess, IModelIdArg } from "@itwin/core-frontend"; import { AccessTokenAdapter, FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; -import { IModelsClient as AuthorIModelsClient, Briefcase, GetBriefcaseListParams, GetIModelListParams, IModelScopedOperationParams, MinimalIModel, ReleaseBriefcaseParams, SPECIAL_VALUES_ME, toArray } from "@itwin/imodels-client-authoring"; +import { + Briefcase, + GetBriefcaseListParams, + GetIModelListParams, + IModelsClient as AuthorIModelsClient, + IModelScopedOperationParams, + MinimalIModel, + ReleaseBriefcaseParams, + SPECIAL_VALUES_ME, + toArray, +} from "@itwin/imodels-client-authoring"; import { IModelsClient as FrontendIModelsClient } from "@itwin/imodels-client-management"; import { ITwinAccessClientWrapper } from "../../common/ITwinAccessClientWrapper"; @@ -60,7 +70,6 @@ export class TestHubFrontend extends FrontendIModelsAccess { const briefcases: Briefcase[] = await toArray(briefcasesIterator); const briefcaseIds: BriefcaseId[] = briefcases.map((briefcase) => briefcase.briefcaseId); return briefcaseIds; - } public async releaseBriefcase(arg: BriefcaseIdArg): Promise { const releaseBriefcaseParams: ReleaseBriefcaseParams = { @@ -69,7 +78,7 @@ export class TestHubFrontend extends FrontendIModelsAccess { }; // Need to use the IModelsClient from the authoring package to be able to release the briefcase. - const iModelClient = new AuthorIModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels`}}); + const iModelClient = new AuthorIModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); return iModelClient.briefcases.release(releaseBriefcaseParams); } } @@ -88,7 +97,7 @@ export class ITwinPlatformCloudEnv implements ITwinPlatformAbstraction { public readonly authClient?: AuthorizationClient; // This should be the new AuthorizationClient method defined in # public constructor(authClient?: AuthorizationClient) { - const iModelClient = new FrontendIModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels`}}); + const iModelClient = new FrontendIModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); this.hubAccess = new TestHubFrontend(iModelClient); this.authClient = authClient; } diff --git a/full-stack-tests/core/src/frontend/hub/ScheduleScript.test.ts b/full-stack-tests/core/src/frontend/hub/ScheduleScript.test.ts index d4a91c1401ea..6ebd21e08995 100644 --- a/full-stack-tests/core/src/frontend/hub/ScheduleScript.test.ts +++ b/full-stack-tests/core/src/frontend/hub/ScheduleScript.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Code, DisplayStyle3dProps, DisplayStyleProps, ElementProps, RenderSchedule, RenderTimelineProps } from "@itwin/core-common"; import { CheckpointConnection, DisplayStyle3dState, IModelApp, IModelConnection, SpatialViewState, ViewState } from "@itwin/core-frontend"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/TestUsers"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; function countTileTrees(view: ViewState): number { @@ -146,7 +146,9 @@ describe("Schedule script (#integration)", () => { expect(view.displayStyle.scheduleScript).to.be.undefined; expect(countTileTrees(view)).to.equal(1); - const transformTimeline = JSON.parse(`[{"interpolation":2,"time":1526641200,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-17.786201477050781,8.4895801544189453,-3.6213436126708984],"transform":[[1,0,0,0.53248977661132813],[0,1,0,-0.54394721984863281],[0,0,1,0.51640319824218750]]}},{"interpolation":2,"time":1526641260,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-17.78613281250,8.4904203414916992,-3.6213412284851074],"transform":[[1,0,0,0.53255844116210938],[0,1,0,-0.54310703277587891],[0,0,1,0.51640558242797852]]}},{"interpolation":2,"time":1527431880,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-16.876888275146484,19.567762374877930,-3.5913453102111816],"transform":[[1,0,0,1.4418029785156250],[0,1,0,10.534235000610352],[0,0,1,0.54640150070190430]]}},{"interpolation":1,"time":1527850740,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-15.742227554321289,26.631050109863281,-4.1812567710876465],"transform":[[1,0,0,2.5764636993408203],[0,1,0,17.597522735595703],[0,0,1,-0.043509960174560547]]}}]`) as RenderSchedule.TransformEntryProps[]; + const transformTimeline = JSON.parse( + `[{"interpolation":2,"time":1526641200,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-17.786201477050781,8.4895801544189453,-3.6213436126708984],"transform":[[1,0,0,0.53248977661132813],[0,1,0,-0.54394721984863281],[0,0,1,0.51640319824218750]]}},{"interpolation":2,"time":1526641260,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-17.78613281250,8.4904203414916992,-3.6213412284851074],"transform":[[1,0,0,0.53255844116210938],[0,1,0,-0.54310703277587891],[0,0,1,0.51640558242797852]]}},{"interpolation":2,"time":1527431880,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-16.876888275146484,19.567762374877930,-3.5913453102111816],"transform":[[1,0,0,1.4418029785156250],[0,1,0,10.534235000610352],[0,0,1,0.54640150070190430]]}},{"interpolation":1,"time":1527850740,"value":{"orientation":[0,0,0,1],"pivot":[18.318691253662109,-9.0335273742675781,4.1377468109130859],"position":[-15.742227554321289,26.631050109863281,-4.1812567710876465],"transform":[[1,0,0,2.5764636993408203],[0,1,0,17.597522735595703],[0,0,1,-0.043509960174560547]]}}]`, + ) as RenderSchedule.TransformEntryProps[]; const json: RenderSchedule.ModelTimelineProps[] = [{ modelId, diff --git a/full-stack-tests/core/src/frontend/hub/SectionDrawing.test.ts b/full-stack-tests/core/src/frontend/hub/SectionDrawing.test.ts index f8a740ebf82c..cc3e6cf49959 100644 --- a/full-stack-tests/core/src/frontend/hub/SectionDrawing.test.ts +++ b/full-stack-tests/core/src/frontend/hub/SectionDrawing.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CheckpointConnection, DrawingViewState, IModelConnection, SectionDrawingModelState, ViewState3d } from "@itwin/core-frontend"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/TestUsers"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport, TestViewport } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/hub/SheetViewState.test.ts b/full-stack-tests/core/src/frontend/hub/SheetViewState.test.ts index 87a615ece6d7..4b7b90521ee0 100644 --- a/full-stack-tests/core/src/frontend/hub/SheetViewState.test.ts +++ b/full-stack-tests/core/src/frontend/hub/SheetViewState.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CheckpointConnection, SheetViewState, ViewState } from "@itwin/core-frontend"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/TestUsers"; -import { testOnScreenViewport } from "../TestViewport"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; +import { testOnScreenViewport } from "../TestViewport"; describe("Sheet views (#integration)", () => { let imodel: CheckpointConnection; diff --git a/full-stack-tests/core/src/frontend/map/BackgroundMap.test.ts b/full-stack-tests/core/src/frontend/map/BackgroundMap.test.ts index 03fe65625d3b..abd219bdf92f 100644 --- a/full-stack-tests/core/src/frontend/map/BackgroundMap.test.ts +++ b/full-stack-tests/core/src/frontend/map/BackgroundMap.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { BackgroundMapProps, BackgroundMapSettings, ColorDef } from "@itwin/core-common"; import { IModelConnection, Pixel, SnapshotConnection } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport, TestViewport } from "../TestViewport"; @@ -49,7 +49,14 @@ describe("Background map (#integration)", () => { it("obscures model based on settings", async () => { type PixelType = "model" | "bg" | "map"; - async function expectPixelTypes(vp: TestViewport, mapProps: BackgroundMapProps | undefined, expectedCenterColor: PixelType, expectedCornerColor: PixelType, expectedCenterFeature: PixelType, expectedCornerFeature: PixelType): Promise { + async function expectPixelTypes( + vp: TestViewport, + mapProps: BackgroundMapProps | undefined, + expectedCenterColor: PixelType, + expectedCornerColor: PixelType, + expectedCenterFeature: PixelType, + expectedCornerFeature: PixelType, + ): Promise { if (mapProps) { vp.viewFlags = vp.viewFlags.with("backgroundMap", true); vp.backgroundMapSettings = BackgroundMapSettings.fromJSON(mapProps); @@ -105,7 +112,6 @@ describe("Background map (#integration)", () => { [{ groundBias: -10 }, "model", "map", "model", "map"], [{ useDepthBuffer: true, groundBias: 10 }, "map", "map", "map", "map"], [{ useDepthBuffer: true, groundBias: -10 }, "model", "map", "model", "map"], - // ###TODO: Can't test with applyTerrain=true because ApproximateTerrainHeights.json not found... ]; diff --git a/full-stack-tests/core/src/frontend/map/PlanProjection.test.ts b/full-stack-tests/core/src/frontend/map/PlanProjection.test.ts index 1298e34c3df9..7c02b2041e22 100644 --- a/full-stack-tests/core/src/frontend/map/PlanProjection.test.ts +++ b/full-stack-tests/core/src/frontend/map/PlanProjection.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { BackgroundMapSettings, ColorByName, ColorDef, GlobeMode, PlanProjectionSettings, PlanProjectionSettingsProps } from "@itwin/core-common"; import { DisplayStyle3dState, GeometricModel3dState, IModelConnection, Pixel, SnapshotConnection } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/map/PlanarClipMask.test.ts b/full-stack-tests/core/src/frontend/map/PlanarClipMask.test.ts index a543eb4378e9..5243f6d2fa84 100644 --- a/full-stack-tests/core/src/frontend/map/PlanarClipMask.test.ts +++ b/full-stack-tests/core/src/frontend/map/PlanarClipMask.test.ts @@ -2,13 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { CompressedId64Set, Guid, Id64 } from "@itwin/core-bentley"; import { BackgroundMapSettings, ColorDef, PlanarClipMaskMode, PlanarClipMaskPriority, PlanarClipMaskProps } from "@itwin/core-common"; -import { GraphicType, IModelApp, IModelConnection, Pixel, readElementGraphics, SnapshotConnection, TileTreeReference, Viewport } from "@itwin/core-frontend"; +import { + GraphicType, + IModelApp, + IModelConnection, + Pixel, + readElementGraphics, + SnapshotConnection, + TileTreeReference, + Viewport, +} from "@itwin/core-frontend"; +import { Point2d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport } from "../TestViewport"; -import { Point2d } from "@itwin/core-geometry"; // The view used by these tests consists of a white rectangle in the center of a top view - smooth-shaded mode. // Map initially off. Map is coplanar with top of rectangle. @@ -51,7 +60,11 @@ describe("Planar clip mask (#integration)", () => { // dynamic is blue. model is white. background is black. map is multi-colored. type PixelType = "map" | "model" | "bg" | "dynamic"; - async function expectPixels(planarClipMask: PlanarClipMaskProps | undefined, expectedCenter: PixelType, setup?: (vp: Viewport) => void): Promise { + async function expectPixels( + planarClipMask: PlanarClipMaskProps | undefined, + expectedCenter: PixelType, + setup?: (vp: Viewport) => void, + ): Promise { return testOnScreenViewport("0x24", imodel, 100, 100, async (vp) => { vp.viewFlags = vp.viewFlags.copy({ backgroundMap: true, lighting: false }); vp.backgroundMapSettings = BackgroundMapSettings.fromJSON({ @@ -156,7 +169,11 @@ describe("Planar clip mask (#integration)", () => { const maxX = 289160; const maxY = 3803959; builder.addShape2d([ - new Point2d(minX, minY), new Point2d(maxX, minY), new Point2d(maxX, maxY), new Point2d(minX, maxY), new Point2d(minX, minY), + new Point2d(minX, minY), + new Point2d(maxX, minY), + new Point2d(maxX, maxY), + new Point2d(minX, maxY), + new Point2d(minX, minY), ], 10); // put it under the map const treeRef = TileTreeReference.createFromRenderGraphic({ @@ -192,23 +209,31 @@ describe("Planar clip mask (#integration)", () => { modelId: "0x1c", }); - await expectPixels({ - mode: PlanarClipMaskMode.Priority, - priority: PlanarClipMaskPriority.BackgroundMap, - }, "model", (vp) => { - vp.changeViewedModels([]); - vp.addTiledGraphicsProvider({ - forEachTileTreeRef: (_, func) => { - func(treeRef); - }, - }); - }); + await expectPixels( + { + mode: PlanarClipMaskMode.Priority, + priority: PlanarClipMaskPriority.BackgroundMap, + }, + "model", + (vp) => { + vp.changeViewedModels([]); + vp.addTiledGraphicsProvider({ + forEachTileTreeRef: (_, func) => { + func(treeRef); + }, + }); + }, + ); }); it("is masked by priority by dynamic geometry", async () => { - await expectPixels({ - mode: PlanarClipMaskMode.Priority, - priority: PlanarClipMaskPriority.BackgroundMap, - }, "dynamic", addDynamicGeometry); + await expectPixels( + { + mode: PlanarClipMaskMode.Priority, + priority: PlanarClipMaskPriority.BackgroundMap, + }, + "dynamic", + addDynamicGeometry, + ); }); }); diff --git a/full-stack-tests/core/src/frontend/standalone/AttachView.test.ts b/full-stack-tests/core/src/frontend/standalone/AttachView.test.ts index 8648c93db87c..612a970ba08c 100644 --- a/full-stack-tests/core/src/frontend/standalone/AttachView.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/AttachView.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ScreenViewport, SnapshotConnection, SpatialViewState } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("ViewState attached to Viewport", async () => { diff --git a/full-stack-tests/core/src/frontend/standalone/BackgroundMap.test.ts b/full-stack-tests/core/src/frontend/standalone/BackgroundMap.test.ts index 309c80a92af4..b40eadcb407b 100644 --- a/full-stack-tests/core/src/frontend/standalone/BackgroundMap.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/BackgroundMap.test.ts @@ -2,12 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - BackgroundMapProps, BackgroundMapProviderName, BackgroundMapSettings, BackgroundMapType, GlobeMode, PersistentBackgroundMapProps, + BackgroundMapProps, + BackgroundMapProviderName, + BackgroundMapSettings, + BackgroundMapType, + GlobeMode, + PersistentBackgroundMapProps, TerrainHeightOriginMode, } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport, TestViewport } from "../TestViewport"; @@ -73,7 +78,6 @@ describe("Background map", () => { [{ terrainSettings: { exaggeration: 42 } }, true], [{ terrainSettings: { heightOrigin: 21 } }, true], [{ terrainSettings: { heightOriginMode: TerrainHeightOriginMode.Ground } }, true], - // Terrain enabled. /* ###TODO ApproximateTerrainHeights.json supplied by core-frontend is not found... [ { applyTerrain: true }, false ], diff --git a/full-stack-tests/core/src/frontend/standalone/BlankConnection.test.ts b/full-stack-tests/core/src/frontend/standalone/BlankConnection.test.ts index 35cc0c7ff605..c06baa2474fe 100644 --- a/full-stack-tests/core/src/frontend/standalone/BlankConnection.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/BlankConnection.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Guid, GuidString } from "@itwin/core-bentley"; -import { Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; import { Cartographic, ElementProps, IModel } from "@itwin/core-common"; import { BlankConnection, ScreenViewport, SpatialViewState } from "@itwin/core-frontend"; +import { Point3d, Range3d, Vector3d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; function createViewDiv() { diff --git a/full-stack-tests/core/src/frontend/standalone/BriefcaseConnection.test.ts b/full-stack-tests/core/src/frontend/standalone/BriefcaseConnection.test.ts index 15af79c02580..dcf6fb60f56c 100644 --- a/full-stack-tests/core/src/frontend/standalone/BriefcaseConnection.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/BriefcaseConnection.test.ts @@ -29,9 +29,7 @@ class MockAbortSignal implements GenericAbortSignal { } if (ProcessDetector.isElectronAppFrontend) { - describe("BriefcaseConnection (#integration)", async () => { - beforeEach(async () => { await TestUtility.startFrontend(); await TestUtility.initialize(TestUsers.regular); diff --git a/full-stack-tests/core/src/frontend/standalone/BriefcaseTxns.test.ts b/full-stack-tests/core/src/frontend/standalone/BriefcaseTxns.test.ts index 941caa085c4d..10ad988b3f6e 100644 --- a/full-stack-tests/core/src/frontend/standalone/BriefcaseTxns.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/BriefcaseTxns.test.ts @@ -2,12 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as path from "path"; import { Guid, OpenMode, ProcessDetector } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { BriefcaseConnection, TxnEntityChanges, TxnEntityChangeType } from "@itwin/core-frontend"; -import { addAllowedChannel, coreFullStackTestIpc, deleteElements, initializeEditTools, insertLineElement, makeModelCode, transformElements } from "../Editing"; +import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import * as path from "path"; +import { + addAllowedChannel, + coreFullStackTestIpc, + deleteElements, + initializeEditTools, + insertLineElement, + makeModelCode, + transformElements, +} from "../Editing"; import { TestUtility } from "../TestUtility"; describe("BriefcaseTxns", () => { @@ -33,7 +41,15 @@ describe("BriefcaseTxns", () => { afterEach(async () => rwConn.close()); - type TxnEventName = "onElementsChanged" | "onModelsChanged" | "onModelGeometryChanged" | "onCommit" | "onCommitted" | "onChangesApplied" | "onReplayExternalTxns" | "onReplayedExternalTxns"; + type TxnEventName = + | "onElementsChanged" + | "onModelsChanged" + | "onModelGeometryChanged" + | "onCommit" + | "onCommitted" + | "onChangesApplied" + | "onReplayExternalTxns" + | "onReplayedExternalTxns"; type TxnEvent = TxnEventName | "beforeUndo" | "beforeRedo" | "afterUndo" | "afterRedo"; type ExpectEvents = (expected: TxnEvent[]) => Promise; @@ -43,7 +59,14 @@ describe("BriefcaseTxns", () => { iModel.txns.onAfterUndoRedo.addListener((isUndo) => received.push(isUndo ? "afterUndo" : "afterRedo")); const txnEventNames: TxnEventName[] = [ - "onElementsChanged", "onModelsChanged", "onModelGeometryChanged", "onCommit", "onCommitted", "onChangesApplied", "onReplayExternalTxns", "onReplayedExternalTxns", + "onElementsChanged", + "onModelsChanged", + "onModelGeometryChanged", + "onCommit", + "onCommitted", + "onChangesApplied", + "onReplayExternalTxns", + "onReplayedExternalTxns", ]; for (const event of txnEventNames) @@ -131,27 +154,49 @@ describe("BriefcaseTxns", () => { await rwConn.txns.reverseAll(); await expectUndo([ - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", - "onElementsChanged", "onModelsChanged", "onChangesApplied", - "onElementsChanged", "onChangesApplied", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", + "onElementsChanged", + "onModelsChanged", + "onChangesApplied", + "onElementsChanged", + "onChangesApplied", ]); await rwConn.txns.reinstateTxn(); await expectRedo([ - "onElementsChanged", "onChangesApplied", - "onElementsChanged", "onModelsChanged", "onChangesApplied", - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", - "onElementsChanged", "onChangesApplied", "onModelGeometryChanged", + "onElementsChanged", + "onChangesApplied", + "onElementsChanged", + "onModelsChanged", + "onChangesApplied", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", + "onElementsChanged", + "onChangesApplied", + "onModelGeometryChanged", ]); }); it("receives events including entity Id and class name", async () => { type Change = [className: string, type: TxnEntityChangeType]; - async function expectChangedEntities(func: () => Promise, terminalEvent: "onAfterUndoRedo" | "onCommitted", expectedChanges: Change[]): Promise { + async function expectChangedEntities( + func: () => Promise, + terminalEvent: "onAfterUndoRedo" | "onCommitted", + expectedChanges: Change[], + ): Promise { const received: Change[] = []; function receive(changes: TxnEntityChanges): void { received.push(...Array.from(changes).map((change) => [change.metadata.classFullName, change.type] as Change)); @@ -202,12 +247,20 @@ describe("BriefcaseTxns", () => { ]; await expectChangedEntities(async () => rwConn.saveChanges(), "onCommitted", expected); - await expectChangedEntities(async () => { - await rwConn.txns.reverseSingleTxn(); - }, "onAfterUndoRedo", expected.map((x) => [x[0], "deleted"])); - await expectChangedEntities(async () => { - await rwConn.txns.reinstateTxn(); - }, "onAfterUndoRedo", expected); + await expectChangedEntities( + async () => { + await rwConn.txns.reverseSingleTxn(); + }, + "onAfterUndoRedo", + expected.map((x) => [x[0], "deleted"]), + ); + await expectChangedEntities( + async () => { + await rwConn.txns.reinstateTxn(); + }, + "onAfterUndoRedo", + expected, + ); }); }); diff --git a/full-stack-tests/core/src/frontend/standalone/CachedDecorations.test.ts b/full-stack-tests/core/src/frontend/standalone/CachedDecorations.test.ts index 4a2d691de6f2..b6990d7920aa 100644 --- a/full-stack-tests/core/src/frontend/standalone/CachedDecorations.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/CachedDecorations.test.ts @@ -2,15 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - CachedDecoration, CanvasDecoration, DecorateContext, DecorationsCache, Decorator, GraphicType, IModelApp, IModelConnection, ScreenViewport, + CachedDecoration, + CanvasDecoration, + DecorateContext, + DecorationsCache, + Decorator, + GraphicType, + IModelApp, + IModelConnection, + ScreenViewport, SnapshotConnection, } from "@itwin/core-frontend"; +import { Graphic, GraphicOwner } from "@itwin/core-frontend/lib/cjs/webgl"; import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { ScreenTestViewport, testOnScreenViewport } from "../TestViewport"; -import { Graphic, GraphicOwner } from "@itwin/core-frontend/lib/cjs/webgl"; describe("Cached decorations", () => { let imodel: IModelConnection; @@ -28,13 +36,15 @@ describe("Cached decorations", () => { }); class TestCanvasDecoration implements CanvasDecoration { - public drawDecoration(_ctx: CanvasRenderingContext2D): void { } + public drawDecoration(_ctx: CanvasRenderingContext2D): void {} } class TestDecorator implements Decorator { private _type: "graphic" | "html" | "canvas"; private _useCachedDecorations: boolean; - public get useCachedDecorations() { return this._useCachedDecorations ? true : undefined; } + public get useCachedDecorations() { + return this._useCachedDecorations ? true : undefined; + } public decorate(context: DecorateContext) { switch (this._type) { case "graphic": diff --git a/full-stack-tests/core/src/frontend/standalone/CartographicRange.test.ts b/full-stack-tests/core/src/frontend/standalone/CartographicRange.test.ts index 732ec54e421a..b2526f41a8c0 100644 --- a/full-stack-tests/core/src/frontend/standalone/CartographicRange.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/CartographicRange.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { CartographicRange } from "@itwin/core-common"; import { SnapshotConnection } from "@itwin/core-frontend"; import { Range2d } from "@itwin/core-geometry"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; describe("Cartographic range tests", () => { @@ -25,7 +25,10 @@ describe("Cartographic range tests", () => { it("Cartographic range should convert properly", () => { const projectRange = new CartographicRange(imodel.projectExtents, imodel.ecefLocation!.getTransform()); - const expected = Range2d.fromJSON({ low: { x: 2.316129378420503, y: 0.5995855439816498 }, high: { x: 2.316183773897448, y: 0.5996166857950551 } }); + const expected = Range2d.fromJSON({ + low: { x: 2.316129378420503, y: 0.5995855439816498 }, + high: { x: 2.316183773897448, y: 0.5996166857950551 }, + }); const longLatBox = projectRange.getLongitudeLatitudeBoundingBox(); assert.isTrue(longLatBox.isAlmostEqual(expected), "range matches correctly"); }); diff --git a/full-stack-tests/core/src/frontend/standalone/Categories.test.ts b/full-stack-tests/core/src/frontend/standalone/Categories.test.ts index b2c142de6e3e..25b61b4b4d51 100644 --- a/full-stack-tests/core/src/frontend/standalone/Categories.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Categories.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("IModelConnection.Categories", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/CodeSpecs.test.ts b/full-stack-tests/core/src/frontend/standalone/CodeSpecs.test.ts index 3dd96fae2814..a0fb8b0774c8 100644 --- a/full-stack-tests/core/src/frontend/standalone/CodeSpecs.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/CodeSpecs.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { BisCodeSpec, CodeScopeSpec, CodeSpec } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; describe("CodeSpecs", async () => { diff --git a/full-stack-tests/core/src/frontend/standalone/DisplayStyleState.test.ts b/full-stack-tests/core/src/frontend/standalone/DisplayStyleState.test.ts index 5df84a17361d..156f7bd58db4 100644 --- a/full-stack-tests/core/src/frontend/standalone/DisplayStyleState.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/DisplayStyleState.test.ts @@ -2,14 +2,25 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CompressedId64Set } from "@itwin/core-bentley"; import { - Atmosphere, AuthorizationClient, BackgroundMapType, ColorByName, DisplayStyle3dProps, DisplayStyle3dSettingsProps, GroundPlane, PlanarClipMaskMode, - PlanarClipMaskSettings, SkyGradient, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, ThematicDisplayMode, + Atmosphere, + AuthorizationClient, + BackgroundMapType, + ColorByName, + DisplayStyle3dProps, + DisplayStyle3dSettingsProps, + GroundPlane, + PlanarClipMaskMode, + PlanarClipMaskSettings, + SkyGradient, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + ThematicDisplayMode, } from "@itwin/core-common"; import { ContextRealityModelState, DisplayStyle3dState, IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Vector3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { AzuriteUsers, TestRpcInterface } from "../../common/RpcInterfaces"; import { TestUtility } from "../TestUtility"; @@ -28,7 +39,9 @@ describe("DisplayStyle", () => { let userToken = ""; // changes to simulate different levels of ViewStore authorization let azuriteUsers: AzuriteUsers; // valid users (sent from backend) const authorizationClient: AuthorizationClient = { - getAccessToken: async () => { return userToken; }, + getAccessToken: async () => { + return userToken; + }, }; before(async () => { @@ -58,15 +71,21 @@ describe("DisplayStyle", () => { // bad token should be unauthorized userToken = "bad guy"; - await expect(imodel.views.viewStoreWriter.addDisplayStyle({ name: "test", className: style1.classFullName, settings: style1.settings.toJSON() })).rejectedWith("unauthorized"); + await expect(imodel.views.viewStoreWriter.addDisplayStyle({ name: "test", className: style1.classFullName, settings: style1.settings.toJSON() })) + .rejectedWith("unauthorized"); // valid readonly token should fail too userToken = azuriteUsers.readOnly; - await expect(imodel.views.viewStoreWriter.addDisplayStyle({ name: "test", className: style1.classFullName, settings: style1.settings.toJSON() })).rejectedWith("unauthorized"); + await expect(imodel.views.viewStoreWriter.addDisplayStyle({ name: "test", className: style1.classFullName, settings: style1.settings.toJSON() })) + .rejectedWith("unauthorized"); // should save correctly with valid readwrite token userToken = azuriteUsers.readWrite; - const id = await imodel.views.viewStoreWriter.addDisplayStyle({ name: "test", className: style1.classFullName, settings: style1.settings.toJSON() }); + const id = await imodel.views.viewStoreWriter.addDisplayStyle({ + name: "test", + className: style1.classFullName, + settings: style1.settings.toJSON(), + }); expect(id).equal("@1"); userToken = azuriteUsers.readOnly; @@ -186,7 +205,13 @@ describe("DisplayStyle", () => { providerData: { mapType: BackgroundMapType.Street }, applyTerrain: true, terrainSettings: { exaggeration: 0.5, heightOriginMode: 1 }, - planarClipMask: { mode: PlanarClipMaskMode.IncludeSubCategories, modelIds: CompressedId64Set.compressArray(["0x123", "0x456"]), transparency: .5, subCategoryOrElementIds: CompressedId64Set.compressArray(["0x123", "0x456"]), priority: 0 }, + planarClipMask: { + mode: PlanarClipMaskMode.IncludeSubCategories, + modelIds: CompressedId64Set.compressArray(["0x123", "0x456"]), + transparency: .5, + subCategoryOrElementIds: CompressedId64Set.compressArray(["0x123", "0x456"]), + priority: 0, + }, }, }); @@ -215,8 +240,7 @@ describe("DisplayStyle", () => { name: "bing", isActive: true, }], - }, - { + }, { tilesetUrl: "google.com", name: "google", description: "a popular search engine", @@ -232,8 +256,7 @@ describe("DisplayStyle", () => { name: "google", isActive: true, }], - }, - ], + }], }); test({ @@ -285,7 +308,13 @@ describe("DisplayStyle", () => { tilesetUrl: "google.com", name: "google", description: "a popular search engine", - planarClipMask: { mode: PlanarClipMaskMode.IncludeSubCategories, modelIds: CompressedId64Set.compressArray(["0x123", "0x456"]), transparency: .5, subCategoryOrElementIds: CompressedId64Set.compressArray(["0x123", "0x456"]), priority: 1024 }, + planarClipMask: { + mode: PlanarClipMaskMode.IncludeSubCategories, + modelIds: CompressedId64Set.compressArray(["0x123", "0x456"]), + transparency: .5, + subCategoryOrElementIds: CompressedId64Set.compressArray(["0x123", "0x456"]), + priority: 1024, + }, classifiers: [{ modelId: "0x123", expand: 0.5, @@ -314,7 +343,11 @@ describe("DisplayStyle", () => { // Also, while we have one constructed, test creation with reality model and script. const newStyle = new DisplayStyle3dState(style.toJSON(), imodel); userToken = azuriteUsers.readWrite; - const s2 = await imodel.views.viewStoreWriter.addDisplayStyle({ name: "newStyle", className: newStyle.classFullName, settings: newStyle.settings.toJSON() }); + const s2 = await imodel.views.viewStoreWriter.addDisplayStyle({ + name: "newStyle", + className: newStyle.classFullName, + settings: newStyle.settings.toJSON(), + }); expect(s2).not.to.be.undefined; await newStyle.load(); diff --git a/full-stack-tests/core/src/frontend/standalone/ECSqlAst.test.ts b/full-stack-tests/core/src/frontend/standalone/ECSqlAst.test.ts index b3ad786a8ded..a59a726b33a8 100644 --- a/full-stack-tests/core/src/frontend/standalone/ECSqlAst.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ECSqlAst.test.ts @@ -6,11 +6,12 @@ * @module ECSqlExpr */ -import { assert } from "chai"; +import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { AssignmentExpr, BetweenExpr, - BinaryBooleanExpr, BinaryValueExpr, + BinaryBooleanExpr, + BinaryValueExpr, CastExpr, ClassNameExpr, CteBlockExpr, @@ -56,7 +57,7 @@ import { UsingRelationshipJoinExpr, WhereClauseExp, } from "@itwin/ecsql-common"; -import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; describe("ECSql Abstract Syntax Tree", () => { @@ -187,8 +188,7 @@ describe("ECSql Abstract Syntax Tree", () => { { orignalECSql: "select IIF(('Hello, World' LIKE '%World') , 2, 3)", expectedECSql: "SELECT IIF('Hello, World' LIKE '%World', 2, 3)", - } - , + }, { orignalECSql: "select IIF(('Hello, World' NOT LIKE '%World') , 2, 3)", expectedECSql: "SELECT IIF('Hello, World' NOT LIKE '%World', 2, 3)", @@ -208,8 +208,7 @@ describe("ECSql Abstract Syntax Tree", () => { { orignalECSql: "SELECT IIF( 3 IN (1,2,3), 'True', 'False')", expectedECSql: "SELECT IIF(3 IN (1, 2, 3), 'True', 'False')", - } - , + }, { orignalECSql: "SELECT IIF( 3 NOT IN (1,2,3), 'True', 'False')", expectedECSql: "SELECT IIF(3 NOT IN (1, 2, 3), 'True', 'False')", @@ -443,12 +442,15 @@ describe("ECSql Abstract Syntax Tree", () => { expectedECSql: "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1) SELECT [i] FROM [c]", }, { - orignalECSql: "WITH c(i) AS (SELECT 1 UNION SELECT i+1 FROM c WHERE i < 10 ORDER BY 1), d(i) AS (SELECT 1 UNION SELECT i+1 FROM d WHERE i < 100 ORDER BY 1) SELECT * FROM c,d", - expectedECSql: "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1), [d]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [d] WHERE ([i] < 100) ORDER BY 1) SELECT [c].[i], [d].[i] FROM [c], [d]", + orignalECSql: + "WITH c(i) AS (SELECT 1 UNION SELECT i+1 FROM c WHERE i < 10 ORDER BY 1), d(i) AS (SELECT 1 UNION SELECT i+1 FROM d WHERE i < 100 ORDER BY 1) SELECT * FROM c,d", + expectedECSql: + "WITH [c]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [c] WHERE ([i] < 10) ORDER BY 1), [d]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [d] WHERE ([i] < 100) ORDER BY 1) SELECT [c].[i], [d].[i] FROM [c], [d]", }, { orignalECSql: "WITH c(a,b,c) AS (SELECT ECInstanceId, ECClassId, Name FROM meta.ECClassDef) SELECT * FROM c", - expectedECSql: "WITH [c]([a], [b], [c]) AS (SELECT [ECInstanceId], [ECClassId], [Name] FROM [ECDbMeta].[ECClassDef]) SELECT [c].[a], [c].[b], [c].[c] FROM [c]", + expectedECSql: + "WITH [c]([a], [b], [c]) AS (SELECT [ECInstanceId], [ECClassId], [Name] FROM [ECDbMeta].[ECClassDef]) SELECT [c].[a], [c].[b], [c].[c] FROM [c]", }, ]; for (const test of tests) { @@ -521,11 +523,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef INNER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -537,11 +541,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef RIGHT JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef RIGHT OUTER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] RIGHT OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -553,11 +559,13 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT 1 FROM meta.ECClassDef FULL JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, { orignalECSql: "SELECT 1 FROM meta.ECClassDef FULL OUTER JOIN meta.ECPropertyDef ON ECPropertyDef.Class.Id = ECClassDef.ECInstanceId", - expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", + expectedECSql: + "SELECT 1 FROM [ECDbMeta].[ECClassDef] FULL OUTER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId])", }, ]; for (const test of tests) { @@ -569,21 +577,24 @@ describe("ECSql Abstract Syntax Tree", () => { const tests = [ { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a UNION SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a UNION ALL SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION ALL SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] UNION ALL SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a INTERSECT SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] INTERSECT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] INTERSECT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, { orignalECSql: "SELECT a.ECInstanceId FROM meta.ECClassDef a EXCEPT SELECT b.ECInstanceId FROM meta.ECPropertyDef b", - expectedECSql: "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] EXCEPT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", + expectedECSql: + "SELECT [a].[ECInstanceId] FROM [ECDbMeta].[ECClassDef] [a] EXCEPT SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]", }, - ]; for (const test of tests) { assert.equal(test.expectedECSql, await toNormalizeECSql(test.orignalECSql)); @@ -604,7 +615,6 @@ describe("ECSql Abstract Syntax Tree", () => { orignalECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE (SELECT [b].[ECInstanceId] FROM meta.ECPropertyDef b) = 1", expectedECSql: "SELECT 1 FROM [ECDbMeta].[ECClassDef] [a] WHERE ((SELECT [b].[ECInstanceId] FROM [ECDbMeta].[ECPropertyDef] [b]) = 1)", }, - ]; for (const test of tests) { assert.equal(test.expectedECSql, await toNormalizeECSql(test.orignalECSql)); @@ -633,7 +643,6 @@ describe("ECSql Abstract Syntax Tree", () => { orignalECSql: "SELECT 1 FROM +ONLY [ECDbMeta].[ECClassDef]", expectedECSql: "SELECT 1 FROM +ONLY [ECDbMeta].[ECClassDef]", }, - ]; for (const test of tests) { assert.equal(test.expectedECSql, await toNormalizeECSql(test.orignalECSql)); @@ -659,8 +668,10 @@ describe("ECSql Abstract Syntax Tree", () => { it("parse SELECT, WHERE, FROM, GROUP BY, HAVING, ORDER BY, LIMIT & ECSQLOPTIONS", async () => { const tests = [ { - orignalECSql: "select count(*) from bis.element where codevalue lIKE '%s' group by ecclassid having count(*)>0 order by UserLabel limit 1 offset 10 ECSQLOPTIONS x=3", - expectedECSql: "SELECT COUNT(*) FROM [BisCore].[Element] WHERE [codevalue] LIKE '%s' GROUP BY [ecclassid] HAVING (COUNT(*) > 0) ORDER BY [UserLabel] LIMIT 1 OFFSET 10 ECSQLOPTIONS x = 3", + orignalECSql: + "select count(*) from bis.element where codevalue lIKE '%s' group by ecclassid having count(*)>0 order by UserLabel limit 1 offset 10 ECSQLOPTIONS x=3", + expectedECSql: + "SELECT COUNT(*) FROM [BisCore].[Element] WHERE [codevalue] LIKE '%s' GROUP BY [ecclassid] HAVING (COUNT(*) > 0) ORDER BY [UserLabel] LIMIT 1 OFFSET 10 ECSQLOPTIONS x = 3", }, ]; for (const test of tests) { @@ -834,7 +845,8 @@ describe("ECSql Abstract Syntax Tree", () => { ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3 */ - const expected = "WITH RECURSIVE [f0]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [f0] WHERE ([i] < 10) ORDER BY 1), [f1]([i]) AS (SELECT 3.14159265358), [f2]([i]) AS (SELECT IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [i]), [f3]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] FORWARD), [f4]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] BACKWARD), [f5]([i]) AS (SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId]) WHERE ([ECClassDef].[ECInstanceId] = :param1)) SELECT (((1 & 2) | (3 << 4)) >> ((((((5 / 6) * (7 + 8)) + (4 % 9)) + -10) + +20) - ~45)) [c0], TIMESTAMP '2013-02-09T12:00:00' [c1], DATE '2012-01-18' [c2], TIME '13:35:16' [c3], TRUE [c4], FALSE [c5], 3.14159265358 [c6], 314159 [c7], 'Hello, World' [c8], (('Hello' || ',') || 'World') [c9], IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [c10], CASE WHEN (4 > 5) THEN NULL WHEN (1 IS NOT NULL) THEN 'Hello' ELSE 'Bye' END [c11], IIF('Hello, World' LIKE '\\%World' ESCAPE '\\', 2, 3) [c12], IIF('Hello, World' LIKE '%World', 2, 3) [c13], IIF('Hello, World' NOT LIKE '%World', 2, 3) [c14], IIF(3 IN (SELECT 1 [N] UNION SELECT 2), 'True', 'False') [c15], IIF(3 IN (1, 2, 3), 'True', 'False') [c16], IIF(3 NOT IN (1, 2, 3), 'True', 'False') [c17], IIF((NULL IS NULL), 'True', 'False') [c18], IIF((NULL IS NOT NULL), 'True', 'False') [c19], IIF((1 IS NOT NULL), 'True', 'False') [c20], IIF(3 IS (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c21], IIF(3 IS NOT (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c22], IIF((NOT 3), 'True', 'False') [c23], IIF((NOT (NOT (NOT (NOT 3)))), 'True', 'False') [c24], IIF(EXISTS(SELECT 1), 'True', 'False') [c25], IIF((NOT EXISTS(SELECT 1)), 'True', 'False') [c26], CAST(1 AS TEXT) [c27], CAST(1 AS INTEGER) [c28], CAST(1 AS REAL) [c29], CAST(1 AS BLOB) [c30], CAST(1 AS TIMESTAMP) [c31], INSTR('First', 'Second') [c32], [f0].[i] [c33], [f1].[i] [c34], [f2].[i] [c35], [k0].[ECInstanceId] [c36] FROM [f0], [f1], [f2], [f3], [f4], [f5], [ECDbMeta].[ECClassDef] [k0], (SELECT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION SELECT DISTINCT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION ALL SELECT ALL [ECInstanceId] FROM [ECDbMeta].[ECClassDef] EXCEPT SELECT SUM(DISTINCT [ECInstanceId]) FROM [ECDbMeta].[ECClassDef] INTERSECT SELECT SUM([ECInstanceId]) FROM [ECDbMeta].[ECClassDef] GROUP BY [ECClassId] HAVING (COUNT(*) > 1)) [k1] WHERE (([f0].[i] = [f1].[i]) AND ([k0].[ECInstanceId] = (? + 2))) GROUP BY [k0].[ECClassId], [k0].[DisplayLabel] HAVING (COUNT(*) > 1) ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3"; + const expected = + "WITH RECURSIVE [f0]([i]) AS (SELECT 1 UNION SELECT ([i] + 1) FROM [f0] WHERE ([i] < 10) ORDER BY 1), [f1]([i]) AS (SELECT 3.14159265358), [f2]([i]) AS (SELECT IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [i]), [f3]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] FORWARD), [f4]([i]) AS (SELECT 1 FROM [BisCore].[Element] [t0] JOIN [BisCore].[Element] [t1] USING [BisCore].[ElementOwnsChildElements] BACKWARD), [f5]([i]) AS (SELECT 1 FROM [ECDbMeta].[ECClassDef] INNER JOIN [ECDbMeta].[ECPropertyDef] ON ([ECPropertyDef].[Class].[Id] = [ECClassDef].[ECInstanceId]) WHERE ([ECClassDef].[ECInstanceId] = :param1)) SELECT (((1 & 2) | (3 << 4)) >> ((((((5 / 6) * (7 + 8)) + (4 % 9)) + -10) + +20) - ~45)) [c0], TIMESTAMP '2013-02-09T12:00:00' [c1], DATE '2012-01-18' [c2], TIME '13:35:16' [c3], TRUE [c4], FALSE [c5], 3.14159265358 [c6], 314159 [c7], 'Hello, World' [c8], (('Hello' || ',') || 'World') [c9], IIF(((((1 <> 2) OR ((4 = 5) AND (4 > 8))) OR (4 < 5)) OR ((4 <= 5) AND (4 >= 6))), 'True', 'False') [c10], CASE WHEN (4 > 5) THEN NULL WHEN (1 IS NOT NULL) THEN 'Hello' ELSE 'Bye' END [c11], IIF('Hello, World' LIKE '\\%World' ESCAPE '\\', 2, 3) [c12], IIF('Hello, World' LIKE '%World', 2, 3) [c13], IIF('Hello, World' NOT LIKE '%World', 2, 3) [c14], IIF(3 IN (SELECT 1 [N] UNION SELECT 2), 'True', 'False') [c15], IIF(3 IN (1, 2, 3), 'True', 'False') [c16], IIF(3 NOT IN (1, 2, 3), 'True', 'False') [c17], IIF((NULL IS NULL), 'True', 'False') [c18], IIF((NULL IS NOT NULL), 'True', 'False') [c19], IIF((1 IS NOT NULL), 'True', 'False') [c20], IIF(3 IS (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c21], IIF(3 IS NOT (ALL [ECDbMeta].[ECClassDef], ONLY [ECDbMeta].[ECPropertyDef]), 'True', 'False') [c22], IIF((NOT 3), 'True', 'False') [c23], IIF((NOT (NOT (NOT (NOT 3)))), 'True', 'False') [c24], IIF(EXISTS(SELECT 1), 'True', 'False') [c25], IIF((NOT EXISTS(SELECT 1)), 'True', 'False') [c26], CAST(1 AS TEXT) [c27], CAST(1 AS INTEGER) [c28], CAST(1 AS REAL) [c29], CAST(1 AS BLOB) [c30], CAST(1 AS TIMESTAMP) [c31], INSTR('First', 'Second') [c32], [f0].[i] [c33], [f1].[i] [c34], [f2].[i] [c35], [k0].[ECInstanceId] [c36] FROM [f0], [f1], [f2], [f3], [f4], [f5], [ECDbMeta].[ECClassDef] [k0], (SELECT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION SELECT DISTINCT [ECInstanceId] FROM [ECDbMeta].[ECClassDef] UNION ALL SELECT ALL [ECInstanceId] FROM [ECDbMeta].[ECClassDef] EXCEPT SELECT SUM(DISTINCT [ECInstanceId]) FROM [ECDbMeta].[ECClassDef] INTERSECT SELECT SUM([ECInstanceId]) FROM [ECDbMeta].[ECClassDef] GROUP BY [ECClassId] HAVING (COUNT(*) > 1)) [k1] WHERE (([f0].[i] = [f1].[i]) AND ([k0].[ECInstanceId] = (? + 2))) GROUP BY [k0].[ECClassId], [k0].[DisplayLabel] HAVING (COUNT(*) > 1) ORDER BY [k0].[Name] ASC, [k0].[ECInstanceId] DESC LIMIT 33 OFFSET (? + :param2) ECSQLOPTIONS NoECClassIdFilter ReadonlyPropertiesAreUpdatable X = 3"; assert.equal(expected, await toNormalizeECSql(ecsql)); }); describe("test methods", () => { @@ -843,9 +855,12 @@ describe("ECSql Abstract Syntax Tree", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), "ALL", new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -854,7 +869,10 @@ describe("ECSql Abstract Syntax Tree", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new LiteralExpr(LiteralValueType.Raw, "1")))), + new LiteralExpr(LiteralValueType.Raw, "1"), + ), + ), + ), ); const expected = "SELECT ALL [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = 1)"; assert.equal(stmt.toECSql(), expected); @@ -873,9 +891,12 @@ describe("ECSql Abstract Syntax Tree", () => { new SelectExpr( new SelectionClauseExpr([ new DerivedPropertyExpr( - new PropertyNameExpr("ECInstanceId")), + new PropertyNameExpr("ECInstanceId"), + ), new DerivedPropertyExpr( - new PropertyNameExpr("CodeValue"))]), + new PropertyNameExpr("CodeValue"), + ), + ]), undefined, new FromClauseExpr([ new ClassNameExpr("bis", "Element"), @@ -884,7 +905,10 @@ describe("ECSql Abstract Syntax Tree", () => { new BinaryBooleanExpr( "=", new PropertyNameExpr("ECInstanceId"), - new ParameterExpr()))), + new ParameterExpr(), + ), + ), + ), ); const expected = "SELECT [ECInstanceId], [CodeValue] FROM [bis].[Element] WHERE ([ECInstanceId] = ?)"; assert.equal(stmt.toECSql(), expected); @@ -954,10 +978,10 @@ describe("ECSql Abstract Syntax Tree", () => { assert.equal(ExprType.WhereClause, WhereClauseExp.type); }); it.skip("test print tree", async () => { - const ecsql = "select el.ECInstanceId as id, count(*) as instances from bis.element el where el.codevalue lIKE '%s' group by el.ecclassid having count(*)>0 order by el.UserLabel limit 1 offset 10 ECSQLOPTIONS x=3"; + const ecsql = + "select el.ECInstanceId as id, count(*) as instances from bis.element el where el.codevalue lIKE '%s' group by el.ecclassid having count(*)>0 order by el.UserLabel limit 1 offset 10 ECSQLOPTIONS x=3"; const selectStmt = await parseECSql(ecsql); printTree(selectStmt); - }); it("test ClassNameExpr.fromECSql()", async () => { assert.equal(ClassNameExpr.fromECSql("+all Bis.Element").toECSql(), "+ALL [Bis].[Element]"); diff --git a/full-stack-tests/core/src/frontend/standalone/ECSqlQuery.test.ts b/full-stack-tests/core/src/frontend/standalone/ECSqlQuery.test.ts index 69c622f980be..1e7d058f6227 100644 --- a/full-stack-tests/core/src/frontend/standalone/ECSqlQuery.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ECSqlQuery.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { DbResult, ProcessDetector } from "@itwin/core-bentley"; import { QueryBinder, QueryRowFormat } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; function skipIf(cond: () => boolean, skipMsg: string, title: string, callback: Mocha.AsyncFunc | Mocha.Func): Mocha.Test { @@ -174,7 +174,7 @@ describe("ECSql Query", () => { } }); - it("Query with Abbreviated Blobs", async function () { + it("Query with Abbreviated Blobs", async function() { const query1 = "SELECT ECInstanceId, GeometryStream FROM BisCore.GeometryPart LIMIT 1"; const query2 = "SELECT ECInstanceId, GeometryStream FROM BisCore.GeometryPart WHERE ECInstanceId=?"; let row1: any; @@ -183,11 +183,21 @@ describe("ECSql Query", () => { for await (const row of imodel2.createQueryReader(query1, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) row1 = row.toRow(); assert.isNotEmpty(row1.geometryStream); - for await (const row of imodel2.createQueryReader(query2, QueryBinder.from([row1.id]), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs: false })) + for await ( + const row of imodel2.createQueryReader(query2, QueryBinder.from([row1.id]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + abbreviateBlobs: false, + }) + ) row2 = row.toRow(); assert.isNotEmpty(row2.geometryStream); assert.deepEqual(row2.geometryStream, row1.geometryStream); - for await (const row of imodel2.createQueryReader(query2, QueryBinder.from([row1.id]), { rowFormat: QueryRowFormat.UseJsPropertyNames, abbreviateBlobs: true })) + for await ( + const row of imodel2.createQueryReader(query2, QueryBinder.from([row1.id]), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + abbreviateBlobs: true, + }) + ) row3 = row.toRow(); assert.equal(row3.id, row1.id); assert.equal(row1.geometryStream.byteLength, JSON.parse(row3.geometryStream).bytes); diff --git a/full-stack-tests/core/src/frontend/standalone/EditTool.test.ts b/full-stack-tests/core/src/frontend/standalone/EditTool.test.ts index 682dc82ffe6e..4cda75e0a4cd 100644 --- a/full-stack-tests/core/src/frontend/standalone/EditTool.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/EditTool.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; import { ProcessDetector } from "@itwin/core-bentley"; import { IModelApp, PrimitiveTool, SnapshotConnection, Viewport } from "@itwin/core-frontend"; import { EditTools, makeEditToolIpc } from "@itwin/editor-frontend"; +import * as chai from "chai"; +import * as chaiAsPromised from "chai-as-promised"; import { testCmdIds, TestCmdOjb1, TestCmdResult, TestCommandIpc } from "../../common/TestEditCommandIpc"; import { TestUtility } from "../TestUtility"; @@ -22,8 +22,12 @@ let cmdStr: string; class TestEditTool1 extends PrimitiveTool { public static override toolId = "TestEditTool1"; - public override isCompatibleViewport(_vp: Viewport | undefined, _isSelectedViewChange: boolean): boolean { return true; } - public async onRestartTool() { return this.exitTool(); } + public override isCompatibleViewport(_vp: Viewport | undefined, _isSelectedViewChange: boolean): boolean { + return true; + } + public async onRestartTool() { + return this.exitTool(); + } public testIpc = makeEditToolIpc(); @@ -35,7 +39,6 @@ class TestEditTool1 extends PrimitiveTool { if (!ProcessDetector.isMobileAppFrontend) { describe("EditTools", () => { - let busyCalls = 0; before(async () => { await TestUtility.startFrontend(undefined, undefined, true); @@ -48,7 +51,6 @@ if (!ProcessDetector.isMobileAppFrontend) { return 0; }; iModel = await SnapshotConnection.openFile("test.bim"); // relative path resolved by BackendTestAssetResolver - }); after(async () => { @@ -85,8 +87,6 @@ if (!ProcessDetector.isMobileAppFrontend) { busyCalls = 0; await EditTools.startCommand({ commandId: "", iModelKey: "" }); expect(busyCalls).equal(4); - }); - }); } diff --git a/full-stack-tests/core/src/frontend/standalone/Elements.test.ts b/full-stack-tests/core/src/frontend/standalone/Elements.test.ts index b6c934444546..f85b03d6a325 100644 --- a/full-stack-tests/core/src/frontend/standalone/Elements.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Elements.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { GeometricElement2dProps, GeometricElement3dProps, GeometryPartProps, Placement2d, Placement3d } from "@itwin/core-common"; import { SnapshotConnection } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("Elements", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/EmphasizeElements.test.ts b/full-stack-tests/core/src/frontend/standalone/EmphasizeElements.test.ts index da83f1b70583..b6d181feb652 100644 --- a/full-stack-tests/core/src/frontend/standalone/EmphasizeElements.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/EmphasizeElements.test.ts @@ -3,12 +3,18 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { assert as bAssert } from "@itwin/core-bentley"; import { ColorDef, Feature, FeatureAppearance, FeatureAppearanceProps, FeatureOverrideType, LinePixels, RgbColor } from "@itwin/core-common"; import { - EmphasizeElements, FeatureSymbology, IModelConnection, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId, + EmphasizeElements, + FeatureSymbology, + IModelConnection, + ScreenViewport, + SnapshotConnection, + SpatialViewState, + StandardViewId, } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("EmphasizeElements tests", () => { @@ -351,7 +357,10 @@ describe("EmphasizeElements tests", () => { EmphasizeElements.clear(vp); const emph = EmphasizeElements.getOrCreate(vp); - interface ColorEntry { color: ColorDef, overrideType: FeatureOverrideType } + interface ColorEntry { + color: ColorDef; + overrideType: FeatureOverrideType; + } const overrides: ColorEntry[] = []; overrides.push({ color: ColorDef.from(200, 150, 100, 50), overrideType: FeatureOverrideType.ColorOnly }); overrides.push({ color: ColorDef.from(200, 150, 100, 50), overrideType: FeatureOverrideType.AlphaOnly }); diff --git a/full-stack-tests/core/src/frontend/standalone/FeatureOverrideProvider.test.ts b/full-stack-tests/core/src/frontend/standalone/FeatureOverrideProvider.test.ts index b461d03ff10f..a58e00bf0b10 100644 --- a/full-stack-tests/core/src/frontend/standalone/FeatureOverrideProvider.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/FeatureOverrideProvider.test.ts @@ -2,10 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - EmphasizeElements, FeatureOverrideProvider, FeatureSymbology, IModelConnection, MutableChangeFlags, SnapshotConnection, Viewport, + EmphasizeElements, + FeatureOverrideProvider, + FeatureSymbology, + IModelConnection, + MutableChangeFlags, + SnapshotConnection, + Viewport, } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/standalone/FeatureOverrides.test.ts b/full-stack-tests/core/src/frontend/standalone/FeatureOverrides.test.ts index 95d35cfb33c5..4cc5f12a8d42 100644 --- a/full-stack-tests/core/src/frontend/standalone/FeatureOverrides.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/FeatureOverrides.test.ts @@ -2,11 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { Feature, FeatureTable, GeometryClass, PackedFeatureTable } from "@itwin/core-common"; -import { HiliteSet, IModelApp, IModelConnection, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId, Target } from "@itwin/core-frontend"; +import { + HiliteSet, + IModelApp, + IModelConnection, + ScreenViewport, + SnapshotConnection, + SpatialViewState, + StandardViewId, + Target, +} from "@itwin/core-frontend"; import { FeatureOverrides } from "@itwin/core-frontend/lib/cjs/webgl"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; function waitUntilTimeHasPassed() { @@ -27,7 +36,7 @@ describe("FeatureOverrides", () => { viewDiv.style.width = viewDiv.style.height = "1000px"; document.body.appendChild(viewDiv); - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await TestUtility.startFrontend(); imodel = await SnapshotConnection.openFile("test.bim"); // relative path resolved by BackendTestAssetResolver spatialView = await imodel.views.load("0x34") as SpatialViewState; diff --git a/full-stack-tests/core/src/frontend/standalone/FeatureSymbology.test.ts b/full-stack-tests/core/src/frontend/standalone/FeatureSymbology.test.ts index 3ef5f9398fe9..d4cfac19728b 100644 --- a/full-stack-tests/core/src/frontend/standalone/FeatureSymbology.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/FeatureSymbology.test.ts @@ -2,24 +2,45 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { - ColorDef, Feature, FeatureAppearance, FeatureAppearanceProps, GeometryClass, LinePixels, RgbColor, SubCategoryOverride, + ColorDef, + Feature, + FeatureAppearance, + FeatureAppearanceProps, + GeometryClass, + LinePixels, + RgbColor, + SubCategoryOverride, ViewFlags, } from "@itwin/core-common"; import { FeatureSymbology, IModelConnection, SnapshotConnection, SpatialViewState, ViewState } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; class Overrides extends FeatureSymbology.Overrides { - public constructor(view?: ViewState) { super(view); } + public constructor(view?: ViewState) { + super(view); + } - public override get neverDrawn() { return this._neverDrawn; } - public override get alwaysDrawn() { return this._alwaysDrawn; } - public get modelOverrides() { return this._modelOverrides; } - public get elementOverrides() { return this._elementOverrides; } - public get subCategoryOverrides() { return this._subCategoryOverrides; } - public get visibleSubCategories() { return this._visibleSubCategories; } + public override get neverDrawn() { + return this._neverDrawn; + } + public override get alwaysDrawn() { + return this._alwaysDrawn; + } + public get modelOverrides() { + return this._modelOverrides; + } + public get elementOverrides() { + return this._elementOverrides; + } + public get subCategoryOverrides() { + return this._subCategoryOverrides; + } + public get visibleSubCategories() { + return this._visibleSubCategories; + } public expectSubCategory(id: string, expectVisible: boolean): void { expect(this.visibleSubCategories.hasId(id)).to.equal(expectVisible); @@ -110,7 +131,10 @@ describe("FeatureSymbology.Overrides", () => { overrides.isAlwaysDrawnExclusive = true; // doesn't sound right... but this is how it works in the native code - assert.isFalse(overrides.isFeatureVisible(feature), "if alwaysDrawnExclusive flag is set, but element not in always drawn set, feature isn't visible"); + assert.isFalse( + overrides.isFeatureVisible(feature), + "if alwaysDrawnExclusive flag is set, but element not in always drawn set, feature isn't visible", + ); overrides = new Overrides(); overrides.setVisibleSubCategory(subCategoryId); @@ -129,7 +153,13 @@ describe("FeatureSymbology.Overrides", () => { const subCategoryId = Id64.fromString("0x129"); const geometryClass = GeometryClass.Construction; const feature = new Feature(elementId, subCategoryId, geometryClass); - const props = { rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true } as FeatureAppearanceProps; + const props = { + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + } as FeatureAppearanceProps; const modelProps = { ...props, transparency: 200 / 255 } as FeatureAppearanceProps; const badModelProps = { ...props, transparency: 356 / 255 } as FeatureAppearanceProps; const elemProps = { transparency: 200 / 255, linePixels: LinePixels.HiddenLine } as FeatureAppearanceProps; @@ -163,18 +193,25 @@ describe("FeatureSymbology.Overrides", () => { overrides = new Overrides(viewState); overrides.setVisibleSubCategory(subCategoryId); appearance = overrides.getFeatureAppearance(feature, id); - assert.isDefined(appearance, "return true if either elementId is in always drawn set or subCategoryId is visible as well as geometryClass is visible"); + assert.isDefined( + appearance, + "return true if either elementId is in always drawn set or subCategoryId is visible as well as geometryClass is visible", + ); overrides = new Overrides(); appearance = FeatureAppearance.fromJSON(props); appearance = overrides.getFeatureAppearance(feature, id); - assert.isUndefined(appearance, "if neither elementId is in alwaysDrawn set nor subCategoryId in visibleSubCategory set nor id in modelOverrides map, then app is reset"); + assert.isUndefined( + appearance, + "if neither elementId is in alwaysDrawn set nor subCategoryId in visibleSubCategory set nor id in modelOverrides map, then app is reset", + ); overrides = new Overrides(); appearance = FeatureAppearance.fromJSON(props); overrides.setAlwaysDrawn(elementId); appearance = overrides.getFeatureAppearance(feature, id); - const msg = "if elementId in alwaysDrawn set, but id not in ModelOverrides map, nor elementId in elementOverrides map, nor subCategoryId in subCategoryOverrides, then app will be set to default overrides"; + const msg = + "if elementId in alwaysDrawn set, but id not in ModelOverrides map, nor elementId in elementOverrides map, nor subCategoryId in subCategoryOverrides, then app will be set to default overrides"; assert.isTrue(appearance!.equals(overrides.defaultOverrides), msg); overrides = new Overrides(); @@ -182,7 +219,10 @@ describe("FeatureSymbology.Overrides", () => { overrides.setAlwaysDrawn(elementId); overrides.override({ modelId: id, appearance: modelApp }); appearance = overrides.getFeatureAppearance(feature, id); - assert.isTrue(appearance!.equals(modelApp), "if elementId in alwaysDrawn set and overrides has Model corresponding to id, then appearance will be set to the ModelApp"); + assert.isTrue( + appearance!.equals(modelApp), + "if elementId in alwaysDrawn set and overrides has Model corresponding to id, then appearance will be set to the ModelApp", + ); overrides = new Overrides(); appearance = FeatureAppearance.fromJSON(props); @@ -190,7 +230,10 @@ describe("FeatureSymbology.Overrides", () => { overrides.setAlwaysDrawn(elementId); overrides.override({ modelId: id, appearance: modelApp }); appearance = overrides.getFeatureAppearance(feature, id); - assert.isUndefined(appearance, "if appearance is set from model app and that app has an invalid transparency value, then getFeatureAppearance returns false"); + assert.isUndefined( + appearance, + "if appearance is set from model app and that app has an invalid transparency value, then getFeatureAppearance returns false", + ); // NOTE: The above assertion appears to have assumed that getFeatureAppearance() returns undefined because it rejects the "invalid" transparency value. // In reality it detects that transparency is above the threshold considered "fully transparent" and therefore not visible. @@ -199,14 +242,20 @@ describe("FeatureSymbology.Overrides", () => { overrides.override({ elementId, appearance: elemApp }); overrides.setAlwaysDrawn(elementId); appearance = overrides.getFeatureAppearance(feature, id); - assert.isTrue(appearance!.equals(elemApp), "if elementId in alwaysDrawn set and overrides has Element corresponding to id but not Model nor SubCategory, then the app is set to the elemApp"); + assert.isTrue( + appearance!.equals(elemApp), + "if elementId in alwaysDrawn set and overrides has Element corresponding to id but not Model nor SubCategory, then the app is set to the elemApp", + ); overrides = new Overrides(viewState); appearance = FeatureAppearance.fromJSON(props); overrides.setVisibleSubCategory(subCategoryId); overrides.override({ subCategoryId, appearance: subCatApp }); appearance = overrides.getFeatureAppearance(feature, id); - assert.isTrue(appearance!.equals(subCatApp), "if subCategoryId is in visible set and SubCategoryApp is found, absent element or model apps, the result app is equal to the app extended by the subCategoryApp"); + assert.isTrue( + appearance!.equals(subCatApp), + "if subCategoryId is in visible set and SubCategoryApp is found, absent element or model apps, the result app is equal to the app extended by the subCategoryApp", + ); overrides = new Overrides(viewState); appearance = FeatureAppearance.fromJSON(props); @@ -216,7 +265,10 @@ describe("FeatureSymbology.Overrides", () => { overrides.override({ subCategoryId, appearance: subCatApp }); appearance = overrides.getFeatureAppearance(feature, id); let expected = subCatApp.extendAppearance(modelApp); - assert.isTrue(appearance!.equals(expected), "if subCat and modelApp are found then the appearance is the extension of the subCatApp with the ModelApp"); + assert.isTrue( + appearance!.equals(expected), + "if subCat and modelApp are found then the appearance is the extension of the subCatApp with the ModelApp", + ); overrides = new Overrides(viewState); appearance = FeatureAppearance.fromJSON(props); modelApp = FeatureAppearance.fromJSON(modelProps); @@ -248,13 +300,22 @@ describe("FeatureSymbology.Overrides", () => { overrides.setAlwaysDrawn(elementId2); assert.isFalse(overrides.isFeatureVisible(feature), "if elementId is in display style's excludedElements, feature isn't visible"); - assert.isTrue(overrides.isFeatureVisible(feature2), "if elementId is in always drawn set and not in the neverDrawn set and not in display style's excludedElements, feature is visible"); + assert.isTrue( + overrides.isFeatureVisible(feature2), + "if elementId is in always drawn set and not in the neverDrawn set and not in display style's excludedElements, feature is visible", + ); viewState.displayStyle.viewFlags = new ViewFlags({ constructions: true }); overrides = new Overrides(viewState); overrides.setVisibleSubCategory(subCategoryId); - assert.isFalse(overrides.isFeatureVisible(feature), "if elementId is in excludedElements and if geometryClass and subCategory are visible, feature isn't visible"); - assert.isTrue(overrides.isFeatureVisible(feature2), "if elementId is not in excludedElements and if geometryClass and subCategory are visible, feature is visible"); + assert.isFalse( + overrides.isFeatureVisible(feature), + "if elementId is in excludedElements and if geometryClass and subCategory are visible, feature isn't visible", + ); + assert.isTrue( + overrides.isFeatureVisible(feature2), + "if elementId is not in excludedElements and if geometryClass and subCategory are visible, feature is visible", + ); }); it("model appearance overrides work as expected", () => { @@ -265,7 +326,13 @@ describe("FeatureSymbology.Overrides", () => { const subCategoryId = Id64.fromString("0x129"); const geometryClass = GeometryClass.Construction; const feature = new Feature(elementId, subCategoryId, geometryClass); - const modelOverride1 = FeatureAppearance.fromJSON({ rgb: new RgbColor(100, 100, 100), weight: 1, transparency: 100 / 255, linePixels: LinePixels.Solid, ignoresMaterial: true }); + const modelOverride1 = FeatureAppearance.fromJSON({ + rgb: new RgbColor(100, 100, 100), + weight: 1, + transparency: 100 / 255, + linePixels: LinePixels.Solid, + ignoresMaterial: true, + }); const modelOverride2 = FeatureAppearance.fromJSON({ ...modelOverride1, transparency: 200 / 255 }); const displayStyle = viewState.displayStyle; diff --git a/full-stack-tests/core/src/frontend/standalone/GeoCoord.test.ts b/full-stack-tests/core/src/frontend/standalone/GeoCoord.test.ts index 2d4723be7e20..3298bc40da31 100644 --- a/full-stack-tests/core/src/frontend/standalone/GeoCoord.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/GeoCoord.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { GeoCoordinatesResponseProps, GeoCoordStatus, IModelCoordinatesResponseProps } from "@itwin/core-common"; import { GeoConverter, IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Geometry, Point3d, XYZProps } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; // spell-checker: disable @@ -164,33 +164,35 @@ describe("GeoCoord", () => { }); it("should get proper result from Geographic CRS conversion", async () => { - const japanConverter = iModel.geoServices.getConverter({ horizontalCRS: { - id:"JGD2K.CS-I-MOCK", - description : "Mock GCS", - source : "Test", - deprecated : false, - datumId : "JGD2000", + id: "JGD2K.CS-I-MOCK", + description: "Mock GCS", + source: "Test", + deprecated: false, + datumId: "JGD2000", unit: "Meter", - projection : { + projection: { method: "TransverseMercator", centralMeridian: 129.5, latitudeOfOrigin: 33.0, scaleFactor: 0.9999, falseEasting: 0.0, - falseNorthing: 0.0}, + falseNorthing: 0.0, + }, + }, + verticalCRS: { + id: "GEOID", }, - verticalCRS : { - id : "GEOID"}}); + }); const testPoint: XYZProps[] = []; - testPoint.push({x: 170370.718, y: 11572.405, z: 0.0}); + testPoint.push({ x: 170370.718, y: 11572.405, z: 0.0 }); expect(japanConverter !== undefined).to.be.true; const response = await japanConverter!.getGeoCoordinatesFromIModelCoordinates(testPoint); - const expectedPt = Point3d.fromJSON({x: 282707.7064282134, y: -3640811.0118976748, z: -73.01288342685298}); + const expectedPt = Point3d.fromJSON({ x: 282707.7064282134, y: -3640811.0118976748, z: -73.01288342685298 }); const outPt = Point3d.fromJSON(response.geoCoords[0].p); expect(Geometry.isSamePoint3dXY(expectedPt, outPt)).to.be.true; diff --git a/full-stack-tests/core/src/frontend/standalone/GraphicalEditingScope.test.ts b/full-stack-tests/core/src/frontend/standalone/GraphicalEditingScope.test.ts index e1d3a1a47dca..483ef43b5857 100644 --- a/full-stack-tests/core/src/frontend/standalone/GraphicalEditingScope.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/GraphicalEditingScope.test.ts @@ -2,15 +2,32 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BeDuration, compareStrings, DbOpcode, Guid, Id64String, OpenMode, ProcessDetector } from "@itwin/core-bentley"; +import { BatchType, ChangedEntities, ElementGeometryChange, IModelError, RenderSchedule } from "@itwin/core-common"; +import { + BriefcaseConnection, + DynamicIModelTile, + GeometricModel3dState, + GraphicalEditingScope, + IModelTileTree, + IModelTileTreeParams, + OnScreenTarget, + TileLoadPriority, +} from "@itwin/core-frontend"; +import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; import * as chai from "chai"; import * as chaiAsPromised from "chai-as-promised"; import * as path from "path"; -import { BeDuration, compareStrings, DbOpcode, Guid, Id64String, OpenMode, ProcessDetector } from "@itwin/core-bentley"; -import { Point3d, Range3d, Transform } from "@itwin/core-geometry"; -import { BatchType, ChangedEntities, ElementGeometryChange, IModelError, RenderSchedule } from "@itwin/core-common"; import { - BriefcaseConnection, DynamicIModelTile, GeometricModel3dState, GraphicalEditingScope, IModelTileTree, IModelTileTreeParams, OnScreenTarget, TileLoadPriority } from "@itwin/core-frontend"; -import { addAllowedChannel, coreFullStackTestIpc, deleteElements, initializeEditTools, insertLineElement, makeLineSegment, makeModelCode, transformElements } from "../Editing"; + addAllowedChannel, + coreFullStackTestIpc, + deleteElements, + initializeEditTools, + insertLineElement, + makeLineSegment, + makeModelCode, + transformElements, +} from "../Editing"; import { TestUtility } from "../TestUtility"; import { testOnScreenViewport } from "../TestViewport"; @@ -147,7 +164,10 @@ describe("GraphicalEditingScope", () => { it.skip("accumulates geometry changes", async () => { imodel = await openWritable(); - const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel(imodel.key, (await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()))); + const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel( + imodel.key, + await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()), + ); const dictModelId = await imodel.models.getDictionaryModel(); const category = await coreFullStackTestIpc.createAndInsertSpatialCategory(imodel.key, dictModelId, Guid.createValue(), { color: 0 }); await imodel.saveChanges(); @@ -249,7 +269,10 @@ describe("GraphicalEditingScope", () => { imodel = await openWritable(); // Initial geometric model contains one line element. - const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel(imodel.key, (await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()))); + const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel( + imodel.key, + await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()), + ); const dictModelId = await imodel.models.getDictionaryModel(); const category = await coreFullStackTestIpc.createAndInsertSpatialCategory(imodel.key, dictModelId, Guid.createValue(), { color: 0 }); const elem1 = await insertLineElement(imodel, modelId, category, makeLineSegment(new Point3d(0, 0, 0), new Point3d(10, 0, 0))); @@ -295,7 +318,12 @@ describe("GraphicalEditingScope", () => { return new IModelTileTree(params, { edges: false, type: BatchType.Primary }); } - const expectTreeState = async (tree: IModelTileTree | IModelTileTree[], expectedState: "static" | "interactive" | "dynamic" | "disposed", expectedHiddenElementCount: number, expectedRange: Range3d) => { + const expectTreeState = async ( + tree: IModelTileTree | IModelTileTree[], + expectedState: "static" | "interactive" | "dynamic" | "disposed", + expectedHiddenElementCount: number, + expectedRange: Range3d, + ) => { // ###TODO: After we switch from polling for native events, we should not need to wait for changed events to be fetched here... const waitTime = 150; await BeDuration.wait(waitTime); @@ -390,7 +418,10 @@ describe("GraphicalEditingScope", () => { imodel = await openWritable(); // Initial geometric model contains one line element. - const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel(imodel.key, (await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()))); + const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel( + imodel.key, + await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()), + ); const dictModelId = await imodel.models.getDictionaryModel(); const category = await coreFullStackTestIpc.createAndInsertSpatialCategory(imodel.key, dictModelId, Guid.createValue(), { color: 0 }); const elem1 = await insertLineElement(imodel, modelId, category, makeLineSegment(new Point3d(0, 0, 0), new Point3d(4, 4, 4))); @@ -517,7 +548,8 @@ describe("GraphicalEditingScope", () => { green: 0, blue: 0, }, - }], + }, + ], }], }]; @@ -546,5 +578,4 @@ describe("GraphicalEditingScope", () => { await scope.exit(); }); } - }); diff --git a/full-stack-tests/core/src/frontend/standalone/Markup.test.ts b/full-stack-tests/core/src/frontend/standalone/Markup.test.ts index 8275e72a7f41..6ed0d43b5ef4 100644 --- a/full-stack-tests/core/src/frontend/standalone/Markup.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Markup.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { IModelApp, IModelConnection, SnapshotConnection, StandardViewId, StandardViewTool, WindowAreaTool } from "@itwin/core-frontend"; import { EditTextTool, LineTool, MarkupApp, SelectTool } from "@itwin/core-markup"; import { Element, G, LinkedHTMLElement } from "@svgdotjs/svg.js"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; import { createOnScreenTestViewport, ScreenTestViewport } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/standalone/ModelChangeMonitor.test.ts b/full-stack-tests/core/src/frontend/standalone/ModelChangeMonitor.test.ts index 0c6eb0a384e9..2ec7f8b6c406 100644 --- a/full-stack-tests/core/src/frontend/standalone/ModelChangeMonitor.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ModelChangeMonitor.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as path from "path"; import { Guid, OpenMode, ProcessDetector } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { BriefcaseConnection, GeometricModelState } from "@itwin/core-frontend"; +import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import * as path from "path"; import { addAllowedChannel, coreFullStackTestIpc, initializeEditTools, insertLineElement, makeModelCode, transformElements } from "../Editing"; import { TestUtility } from "../TestUtility"; @@ -49,7 +49,10 @@ if (!ProcessDetector.isMobileAppFrontend) { let elemId: string; beforeEach(async () => { - const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel(imodel.key, (await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()))); + const modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel( + imodel.key, + await makeModelCode(imodel, imodel.models.repositoryModelId, Guid.createValue()), + ); const dictId = await imodel.models.getDictionaryModel(); const categoryId = await coreFullStackTestIpc.createAndInsertSpatialCategory(imodel.key, dictId, Guid.createValue(), { color: 0 }); elemId = await insertLineElement(imodel, modelId, categoryId); diff --git a/full-stack-tests/core/src/frontend/standalone/ModelState.test.ts b/full-stack-tests/core/src/frontend/standalone/ModelState.test.ts index 7b2dd2641501..b91ce72543e1 100644 --- a/full-stack-tests/core/src/frontend/standalone/ModelState.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ModelState.test.ts @@ -2,12 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { Code, IModel, ModelSelectorProps } from "@itwin/core-common"; import { - DrawingModelState, GeometricModelState, IModelConnection, ModelSelectorState, SheetModelState, SnapshotConnection, SpatialModelState, + DrawingModelState, + GeometricModelState, + IModelConnection, + ModelSelectorState, + SheetModelState, + SnapshotConnection, + SpatialModelState, } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("ModelState", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/Monochrome.test.ts b/full-stack-tests/core/src/frontend/standalone/Monochrome.test.ts index 027dcba831e1..0153273c1da9 100644 --- a/full-stack-tests/core/src/frontend/standalone/Monochrome.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Monochrome.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef, FeatureAppearance, MonochromeMode, RenderMode } from "@itwin/core-common"; import { FeatureSymbology, IModelConnection, SnapshotConnection, Viewport } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { Color, testOnScreenViewport } from "../TestViewport"; @@ -77,7 +77,7 @@ describe("Monochrome", async () => { expect(colors.contains(Color.fromColorDef(ColorDef.blue))).to.be.true; class ColorOverride { - constructor(public color: ColorDef) { } + constructor(public color: ColorDef) {} public addFeatureOverrides(ovrs: FeatureSymbology.Overrides, _vp: Viewport): void { ovrs.setDefaultOverrides(FeatureAppearance.fromRgb(this.color)); } diff --git a/full-stack-tests/core/src/frontend/standalone/OpenStandalone.test.ts b/full-stack-tests/core/src/frontend/standalone/OpenStandalone.test.ts index 174feca419e4..920694a6fcc5 100644 --- a/full-stack-tests/core/src/frontend/standalone/OpenStandalone.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/OpenStandalone.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import * as path from "path"; import { Guid, OpenMode, ProcessDetector } from "@itwin/core-bentley"; import { IModel, IModelError } from "@itwin/core-common"; import { BriefcaseConnection } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; +import * as path from "path"; import { TestUtility } from "../TestUtility"; if (ProcessDetector.isElectronAppFrontend) { // BriefcaseConnection tests only run on electron @@ -39,7 +39,7 @@ if (ProcessDetector.isElectronAppFrontend) { // BriefcaseConnection tests only r assert.equal(connection.iTwinId, Guid.empty, "standalone imodels have empty iTwinId"); await expect(connection.pushChanges("bad")).to.eventually.be.rejectedWith(IModelError); // standalone imodels can't push changes - await expect(connection.pullChanges()).to.eventually.be.rejectedWith(IModelError);// standalone imodels can't pull changes + await expect(connection.pullChanges()).to.eventually.be.rejectedWith(IModelError); // standalone imodels can't pull changes const elementProps = await connection.elements.getProps(IModel.rootSubjectId); assert.equal(1, elementProps.length); diff --git a/full-stack-tests/core/src/frontend/standalone/PerModelCategoryVisibility.test.ts b/full-stack-tests/core/src/frontend/standalone/PerModelCategoryVisibility.test.ts index 38d230d823ae..f328e34d8c8b 100644 --- a/full-stack-tests/core/src/frontend/standalone/PerModelCategoryVisibility.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/PerModelCategoryVisibility.test.ts @@ -2,13 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64, Id64String } from "@itwin/core-bentley"; import { ColorDef, Feature, FeatureAppearance, SubCategoryOverride } from "@itwin/core-common"; import { - FeatureSymbology, PerModelCategoryVisibility, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId, + FeatureSymbology, + PerModelCategoryVisibility, + ScreenViewport, + SnapshotConnection, + SpatialViewState, + StandardViewId, Viewport, } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; class Overrides extends FeatureSymbology.Overrides { @@ -16,7 +21,9 @@ class Overrides extends FeatureSymbology.Overrides { super(vp); } - public get modelSubCategoryOverrides() { return this._modelSubCategoryOverrides; } + public get modelSubCategoryOverrides() { + return this._modelSubCategoryOverrides; + } public getOverride(modelId: Id64String): Id64.Uint32Set | undefined { return this.modelSubCategoryOverrides.get(Id64.getLowerUint32(modelId), Id64.getUpperUint32(modelId)); @@ -277,7 +284,6 @@ describe("Per-model category visibility overrides with setOverrides function", ( imodel = await SnapshotConnection.openFile("test.bim"); // relative path resolved by BackendTestAssetResolver spatialView = await imodel.views.load("0x34") as SpatialViewState; spatialView.setStandardRotation(StandardViewId.RightIso); - }); beforeEach(() => { @@ -307,8 +313,8 @@ describe("Per-model category visibility overrides with setOverrides function", ( // Turn on category 2f for model 1c, and turn off category 17 for model 1f (latter is no-op because already off). const pmcv = vp.perModelCategoryVisibility; const overrides: PerModelCategoryVisibility.Props[] = []; - overrides.push({modelId: "0x1c", categoryIds: "0x2f", visOverride: show}); - overrides.push({modelId: "0x1f", categoryIds: "0x17", visOverride: hide}); + overrides.push({ modelId: "0x1c", categoryIds: "0x2f", visOverride: show }); + overrides.push({ modelId: "0x1f", categoryIds: "0x17", visOverride: hide }); await pmcv.setOverrides(overrides); expect(pmcv.getOverride("0x1c", "0x2f")).to.equal(show); @@ -346,9 +352,9 @@ describe("Per-model category visibility overrides with setOverrides function", ( // Model 1c turns category 31 off. Model 1f turns category 17 on and category 2d off. const pmcv = vp.perModelCategoryVisibility; const overrides: PerModelCategoryVisibility.Props[] = []; - overrides.push({modelId: "0x1c", categoryIds: ["0x31"], visOverride: hide}); - overrides.push({modelId: "0x1f", categoryIds: ["0x17"], visOverride: show}); - overrides.push({modelId: "0x1f", categoryIds: "0x2d", visOverride: hide}); + overrides.push({ modelId: "0x1c", categoryIds: ["0x31"], visOverride: hide }); + overrides.push({ modelId: "0x1f", categoryIds: ["0x17"], visOverride: show }); + overrides.push({ modelId: "0x1f", categoryIds: "0x2d", visOverride: hide }); await pmcv.setOverrides(overrides); expect(pmcv.getOverride("0x1c", "0x31")).to.equal(hide); expect(pmcv.getOverride("0x1f", "0x17")).to.equal(show); @@ -402,8 +408,8 @@ describe("Per-model category visibility overrides with setOverrides function", ( // vp.perModelCategoryVisibility.setOverride("0x1c", ["0x2f", "0x31", "0x2d"], show); // vp.perModelCategoryVisibility.setOverride("0x1c", "0x17", hide); const overrides: PerModelCategoryVisibility.Props[] = []; - overrides.push({modelId: "0x1c", categoryIds: ["0x2f", "0x31", "0x2d"], visOverride: show}); - overrides.push({modelId: "0x1c", categoryIds: ["0x17"], visOverride: hide}); + overrides.push({ modelId: "0x1c", categoryIds: ["0x2f", "0x31", "0x2d"], visOverride: show }); + overrides.push({ modelId: "0x1c", categoryIds: ["0x17"], visOverride: hide }); await vp.perModelCategoryVisibility.setOverrides(overrides); ovrs = new Overrides(vp); @@ -429,10 +435,10 @@ describe("Per-model category visibility overrides with setOverrides function", ( it("supports iteration", async () => { const pmcv = vp.perModelCategoryVisibility; const overrides: PerModelCategoryVisibility.Props[] = []; - overrides.push({modelId: "0x1c", categoryIds: ["0x2f", "0x31"], visOverride: show}); - overrides.push({modelId: "0x1c", categoryIds: ["0x2d"], visOverride:hide}); - overrides.push({modelId: "0x1d", categoryIds: "0x2d", visOverride: show}); - overrides.push({modelId: "0x1d", categoryIds: ["0x2f", "0x2e"], visOverride: hide}); + overrides.push({ modelId: "0x1c", categoryIds: ["0x2f", "0x31"], visOverride: show }); + overrides.push({ modelId: "0x1c", categoryIds: ["0x2d"], visOverride: hide }); + overrides.push({ modelId: "0x1d", categoryIds: "0x2d", visOverride: show }); + overrides.push({ modelId: "0x1d", categoryIds: ["0x2f", "0x2e"], visOverride: hide }); await pmcv.setOverrides(overrides); let nIterations = 0; diff --git a/full-stack-tests/core/src/frontend/standalone/PrimitiveBuilder.test.ts b/full-stack-tests/core/src/frontend/standalone/PrimitiveBuilder.test.ts index 48605fe480a8..9ba9f2c7d412 100644 --- a/full-stack-tests/core/src/frontend/standalone/PrimitiveBuilder.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/PrimitiveBuilder.test.ts @@ -2,25 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { ColorDef, GraphicParams } from "@itwin/core-common"; -import { - GraphicType, IModelApp, IModelConnection, ScreenViewport, SnapshotConnection, - SpatialViewState, StandardViewId, -} from "@itwin/core-frontend"; -import { PrimitiveBuilder } from "@itwin/core-frontend/lib/cjs/internal/render/PrimitiveBuilder"; +import { GraphicType, IModelApp, IModelConnection, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId } from "@itwin/core-frontend"; import { DisplayParams } from "@itwin/core-frontend/lib/cjs/common/internal/render/DisplayParams"; -import { _accumulator } from "@itwin/core-frontend/lib/cjs/common/internal/Symbols"; import { Geometry } from "@itwin/core-frontend/lib/cjs/common/internal/render/GeometryPrimitives"; +import { _accumulator } from "@itwin/core-frontend/lib/cjs/common/internal/Symbols"; +import { PrimitiveBuilder } from "@itwin/core-frontend/lib/cjs/internal/render/PrimitiveBuilder"; import { Branch } from "@itwin/core-frontend/lib/cjs/webgl"; import { Arc3d, IndexedPolyface, LineString3d, Loop, Path, Point2d, Point3d, Polyface, Range3d, Transform } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("PrimitiveBuilder", () => { let imodel: IModelConnection; let viewport: ScreenViewport; - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await TestUtility.startFrontend(); imodel = await SnapshotConnection.openFile("test.bim"); // relative path resolved by BackendTestAssetResolver diff --git a/full-stack-tests/core/src/frontend/standalone/QuantityFormatter.test.ts b/full-stack-tests/core/src/frontend/standalone/QuantityFormatter.test.ts index 6a68dad75558..4b5a7d57b49c 100644 --- a/full-stack-tests/core/src/frontend/standalone/QuantityFormatter.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/QuantityFormatter.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { IModelConnection, QuantityFormatter, SnapshotConnection } from "@itwin/core-frontend"; -import { TestUtility } from "../TestUtility"; import { SchemaContext, SchemaUnitProvider } from "@itwin/ecschema-metadata"; import { ECSchemaRpcLocater } from "@itwin/ecschema-rpcinterface-common"; import { assert } from "chai"; +import { TestUtility } from "../TestUtility"; describe("QuantityFormatter", () => { let context = new SchemaContext(); diff --git a/full-stack-tests/core/src/frontend/standalone/RealityDataAccess.test.ts b/full-stack-tests/core/src/frontend/standalone/RealityDataAccess.test.ts index a393b897d408..ce255002d352 100644 --- a/full-stack-tests/core/src/frontend/standalone/RealityDataAccess.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/RealityDataAccess.test.ts @@ -2,13 +2,27 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { CheckpointConnection, IModelApp, IModelConnection, RealityDataSource, SpatialModelState, ThreeDTileFormatInterpreter, TileAdmin } from "@itwin/core-frontend"; +import { Id64String } from "@itwin/core-bentley"; +import { EcefLocation, RealityDataFormat, RealityDataProvider, RealityDataSourceKey } from "@itwin/core-common"; +import { + CheckpointConnection, + IModelApp, + IModelConnection, + RealityDataSource, + SpatialModelState, + ThreeDTileFormatInterpreter, + TileAdmin, +} from "@itwin/core-frontend"; import { TestUsers } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { + ITwinRealityData, + RealityDataAccessClient, + RealityDataClientOptions, + RealityDataQueryCriteria, + RealityDataResponse, +} from "@itwin/reality-data-client"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; -import { EcefLocation, RealityDataFormat, RealityDataProvider, RealityDataSourceKey } from "@itwin/core-common"; -import { Id64String } from "@itwin/core-bentley"; -import { ITwinRealityData, RealityDataAccessClient, RealityDataClientOptions, RealityDataQueryCriteria, RealityDataResponse } from "@itwin/reality-data-client"; export interface IRealityDataModelInfo { key: RealityDataSourceKey; @@ -55,31 +69,34 @@ describe("RealityDataAccess (#integration)", () => { await TestUtility.shutdownFrontend(); }); - function getAttachmentURLFromModelProps(modelProps: any): {rdsUrl: string | undefined, blobFilename: string | undefined} { + function getAttachmentURLFromModelProps(modelProps: any): { rdsUrl: string | undefined, blobFilename: string | undefined } { // Special case for OPC file - if (modelProps.tilesetUrl !== undefined && modelProps.tilesetUrl.orbitGtBlob !== undefined ) { - return {rdsUrl: modelProps.tilesetUrl.orbitGtBlob.rdsUrl, blobFilename: modelProps.tilesetUrl.orbitGtBlob.blobFileName}; - } else if (modelProps.orbitGtBlob !== undefined && modelProps.orbitGtBlob.rdsUrl ) { - return {rdsUrl: modelProps.orbitGtBlob.rdsUrl, blobFilename: modelProps.orbitGtBlob.blobFileName }; + if (modelProps.tilesetUrl !== undefined && modelProps.tilesetUrl.orbitGtBlob !== undefined) { + return { rdsUrl: modelProps.tilesetUrl.orbitGtBlob.rdsUrl, blobFilename: modelProps.tilesetUrl.orbitGtBlob.blobFileName }; + } else if (modelProps.orbitGtBlob !== undefined && modelProps.orbitGtBlob.rdsUrl) { + return { rdsUrl: modelProps.orbitGtBlob.rdsUrl, blobFilename: modelProps.orbitGtBlob.blobFileName }; } - return {rdsUrl: modelProps.tilesetUrl, blobFilename: undefined }; + return { rdsUrl: modelProps.tilesetUrl, blobFilename: undefined }; } - async function getAttachedRealityDataModelInfoSet(iModel: IModelConnection): Promise > { + async function getAttachedRealityDataModelInfoSet(iModel: IModelConnection): Promise> { // Get set of RealityDataModelInfo that are directly attached to the model. const modelRealityDataInfos = new Set(); if (iModel) { const query = { from: SpatialModelState.classFullName, wantPrivate: false }; const iModelProps = await iModel.models.queryProps(query); for (const prop of iModelProps) { - if (prop.jsonProperties !== undefined && (prop.jsonProperties.tilesetUrl || prop.jsonProperties.orbitGtBlob) && prop.id !== undefined && prop.name) { + if ( + prop.jsonProperties !== undefined && (prop.jsonProperties.tilesetUrl || prop.jsonProperties.orbitGtBlob) && prop.id !== undefined && + prop.name + ) { const attachmentUrl = getAttachmentURLFromModelProps(prop.jsonProperties); if (attachmentUrl !== undefined && attachmentUrl.rdsUrl !== undefined) { let fileFormat = RealityDataFormat.ThreeDTile; if (prop.jsonProperties.orbitGtBlob) fileFormat = RealityDataFormat.OPC; const key = RealityDataSource.createKeyFromUrl(attachmentUrl.rdsUrl, undefined, fileFormat); - modelRealityDataInfos.add({key, modelId: prop.id, attachmentUrl: attachmentUrl.rdsUrl, attachmentName: prop.name}); + modelRealityDataInfos.add({ key, modelId: prop.id, attachmentUrl: attachmentUrl.rdsUrl, attachmentName: prop.name }); } } } @@ -88,7 +105,7 @@ describe("RealityDataAccess (#integration)", () => { } enum RealityDataType { - REALITYMESH3DTILES = "REALITYMESH3DTILES", + REALITYMESH3DTILES = "REALITYMESH3DTILES", OSMBUILDINGS = "OSMBUILDINGS", OPC = "OPC", TERRAIN3DTILES = "TERRAIN3DTILES", // Terrain3DTiles @@ -139,18 +156,18 @@ describe("RealityDataAccess (#integration)", () => { id: iTwinRealityData.id, }; } - function getOSMBuildingsKey(): RealityDataSourceKey { + function getOSMBuildingsKey(): RealityDataSourceKey { // We don't always have access to url (which is internal) for OSMBuildings, create a special key for it - return {provider: RealityDataProvider.CesiumIonAsset, format: RealityDataFormat.ThreeDTile, id: "OSMBuildings"}; + return { provider: RealityDataProvider.CesiumIonAsset, format: RealityDataFormat.ThreeDTile, id: "OSMBuildings" }; } async function getAllRealityDataFromProject(): Promise { // Initialize on first call and then keep the result for other calls if (allProjectRealityDatas === undefined) { allProjectRealityDatas = []; - let projectRealityDatas: RealityDataResponse = {realityDatas: []}; + let projectRealityDatas: RealityDataResponse = { realityDatas: [] }; let continuationToken: string | undefined; - const top=100; + const top = 100; const criteria: RealityDataQueryCriteria = { getFullRepresentation: true, top, @@ -171,7 +188,7 @@ describe("RealityDataAccess (#integration)", () => { it("should get RealityDataSource for all supported reality data in itwin project", async () => { const realityDatas = await getAllRealityDataFromProject(); for (const rd of realityDatas) { - if (isSupportedType(rd.type)){ + if (isSupportedType(rd.type)) { const keyFromInput: RealityDataSourceKey = createRealityDataListKeyFromITwinRealityData(rd); const rdSource = await RealityDataSource.fromKey(keyFromInput, iTwinId); expect(rdSource).not.undefined; @@ -184,7 +201,7 @@ describe("RealityDataAccess (#integration)", () => { const realityDatas = await getAllRealityDataFromProject(); for (const rd of realityDatas) { // Some types are supported and return by Context Share but required extension to be displayed (e.g: OMR) - if (isSupportedDisplayType(rd.type)){ + if (isSupportedDisplayType(rd.type)) { const keyFromInput: RealityDataSourceKey = createRealityDataListKeyFromITwinRealityData(rd); const rdSource = await RealityDataSource.fromKey(keyFromInput, iTwinId); expect(rdSource).not.undefined; @@ -201,7 +218,7 @@ describe("RealityDataAccess (#integration)", () => { const realityDatas = await getAllRealityDataFromProject(); for (const rd of realityDatas) { // Some types are supported and return by Context Share but required extension to be displayed (e.g: OMR) - if (isSupportedDisplayType(rd.type)){ + if (isSupportedDisplayType(rd.type)) { const keyFromInput: RealityDataSourceKey = createRealityDataListKeyFromITwinRealityData(rd); const rdSource = await RealityDataSource.fromKey(keyFromInput, iTwinId); expect(rdSource).not.undefined; @@ -220,7 +237,7 @@ describe("RealityDataAccess (#integration)", () => { const realityDatas = await getAllRealityDataFromProject(); for (const rd of realityDatas) { // Some types are supported and return by Context Share but required extension to be displayed (e.g: OMR) - if (isSupportedDisplayType(rd.type)){ + if (isSupportedDisplayType(rd.type)) { const keyFromInput: RealityDataSourceKey = createRealityDataListKeyFromITwinRealityData(rd); const rdSource = await RealityDataSource.fromKey(keyFromInput, iTwinId); expect(rdSource).not.undefined; diff --git a/full-stack-tests/core/src/frontend/standalone/RenderTarget.test.ts b/full-stack-tests/core/src/frontend/standalone/RenderTarget.test.ts index 630104ffc3c4..332cfd19c2e3 100644 --- a/full-stack-tests/core/src/frontend/standalone/RenderTarget.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/RenderTarget.test.ts @@ -2,16 +2,36 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ClipStyle, ColorDef, FeatureAppearance, FeatureAppearanceProvider, Hilite, RenderMode, RgbColor } from "@itwin/core-common"; import { - DecorateContext, Decorator, FeatureOverrideProvider, FeatureSymbology, GraphicBranch, GraphicBranchOptions, GraphicType, IModelApp, - IModelConnection, OffScreenViewport, Pixel, RenderSystem, SnapshotConnection, SpatialViewState, Viewport, ViewRect, + DecorateContext, + Decorator, + FeatureOverrideProvider, + FeatureSymbology, + GraphicBranch, + GraphicBranchOptions, + GraphicType, + IModelApp, + IModelConnection, + OffScreenViewport, + Pixel, + RenderSystem, + SnapshotConnection, + SpatialViewState, + Viewport, + ViewRect, } from "@itwin/core-frontend"; import { ClipVector, Point2d, Point3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { - Color, comparePixelData, createOnScreenTestViewport, testOnScreenViewport, TestViewport, testViewports, testViewportsWithDpr, + Color, + comparePixelData, + createOnScreenTestViewport, + testOnScreenViewport, + TestViewport, + testViewports, + testViewportsWithDpr, } from "../TestViewport"; /* eslint-disable @typescript-eslint/unbound-method */ @@ -231,7 +251,12 @@ describe("RenderTarget", () => { await testViewportsWithDpr(imodel, cssRect, async (vp) => { await vp.waitForAllTilesToRender(); - const expectImageDimensions = (readRect: ViewRect | undefined, targetSize: Point2d | undefined, expectedWidth: number, expectedHeight: number) => { + const expectImageDimensions = ( + readRect: ViewRect | undefined, + targetSize: Point2d | undefined, + expectedWidth: number, + expectedHeight: number, + ) => { const img = vp.readImageBuffer({ rect: readRect, size: targetSize })!; expect(img).not.to.be.undefined; expect(img.width).to.equal(Math.floor(expectedWidth)); @@ -250,7 +275,12 @@ describe("RenderTarget", () => { const devHalfWidth = Math.floor(devRect.width / 2); const devQuarterHeight = Math.floor(devRect.height / 4); expectImageDimensions(new ViewRect(0, 0, cssHalfWidth, cssQuarterHeight), undefined, devHalfWidth, devQuarterHeight); - expectImageDimensions(new ViewRect(cssHalfWidth, cssQuarterHeight, cssRect.right, cssRect.bottom), undefined, devRect.width - devHalfWidth, devRect.height - devQuarterHeight); + expectImageDimensions( + new ViewRect(cssHalfWidth, cssQuarterHeight, cssRect.right, cssRect.bottom), + undefined, + devRect.width - devHalfWidth, + devRect.height - devQuarterHeight, + ); expectImageDimensions(new ViewRect(0, 0, cssHalfWidth, cssRect.bottom), undefined, devHalfWidth, devRect.height); // Read full image and resize @@ -366,7 +396,8 @@ describe("RenderTarget", () => { // Set bg color to red, elem color to 50% transparent blue => expect blending vp.view.displayStyle.backgroundColor = ColorDef.red; vp.invalidateRenderPlan(); - ovrProvider.ovrFunc = (ovrs, _) => ovrs.override({ elementId: elemId, appearance: FeatureAppearance.fromJSON({ rgb: new RgbColor(0, 0, 0xff), transparency: 0.5 }) }); + ovrProvider.ovrFunc = (ovrs, _) => + ovrs.override({ elementId: elemId, appearance: FeatureAppearance.fromJSON({ rgb: new RgbColor(0, 0, 0xff), transparency: 0.5 }) }); vp.setFeatureOverrideProviderChanged(); await vp.drawFrame(); colors = vp.readUniqueColors(); @@ -434,7 +465,10 @@ describe("RenderTarget", () => { // - If the child has no symbology overrides: // - It uses its own AppearanceProvider, or its parents if it has none. // - Otherwise, it uses its own AppearanceProvider, or none. - interface OvrAug { ovr?: ColorDef, aug?: ColorDef } + interface OvrAug { + ovr?: ColorDef; + aug?: ColorDef; + } const testNestedBranch = async (parent: OvrAug | undefined, child: OvrAug | undefined, expected: ColorDef) => { const applyOvrs = (branch: GraphicBranch, ovraug?: OvrAug) => { if (ovraug?.ovr) { @@ -507,7 +541,6 @@ describe("RenderTarget", () => { it("should show transparency for polylines", async () => { const rect = new ViewRect(0, 0, 200, 150); await testOnScreenViewport("0x24", imodel, rect.width, rect.height, async (vp) => { - class TestPolylineDecorator implements Decorator { public decorate(context: DecorateContext) { expect(context.viewport === vp); @@ -675,7 +708,13 @@ describe("RenderTarget", () => { const clip = ClipVector.fromJSON([{ shape: { - points: [[-58.57249751634662, -261.9870625343174, 0], [297.4029912650585, -261.9870625343174, 0], [297.4029912650585, 111.24234024435282, 0], [-58.57249751634662, 111.24234024435282, 0], [-58.57249751634662, -261.9870625343174, 0]], + points: [ + [-58.57249751634662, -261.9870625343174, 0], + [297.4029912650585, -261.9870625343174, 0], + [297.4029912650585, 111.24234024435282, 0], + [-58.57249751634662, 111.24234024435282, 0], + [-58.57249751634662, -261.9870625343174, 0], + ], trans: [[1, 0, 0, 289076.52682419703], [0, 1, 0, 3803926.4450675533], [0, 0, 1, 0]], }, }]); diff --git a/full-stack-tests/core/src/frontend/standalone/ScreenSpaceEffects.test.ts b/full-stack-tests/core/src/frontend/standalone/ScreenSpaceEffects.test.ts index 2e46c9ef77b5..ea9df81be134 100644 --- a/full-stack-tests/core/src/frontend/standalone/ScreenSpaceEffects.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ScreenSpaceEffects.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef } from "@itwin/core-common"; import { IModelApp, Pixel, SnapshotConnection, VaryingType } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { Color, TestViewport, testViewports } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/standalone/SnapshotConnection.test.ts b/full-stack-tests/core/src/frontend/standalone/SnapshotConnection.test.ts index deba8cbafdcb..12081d88f88f 100644 --- a/full-stack-tests/core/src/frontend/standalone/SnapshotConnection.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/SnapshotConnection.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { Guid } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; import { SnapshotConnection } from "@itwin/core-frontend"; +import { assert } from "chai"; import { TestUtility } from "../TestUtility"; describe("SnapshotConnection", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/SubCategoriesCache.test.ts b/full-stack-tests/core/src/frontend/standalone/SubCategoriesCache.test.ts index f8fa6d34a4ae..783c0574e2fe 100644 --- a/full-stack-tests/core/src/frontend/standalone/SubCategoriesCache.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/SubCategoriesCache.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, Id64, Id64Arg, Id64Set, Id64String } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection, SubCategoriesCache } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("SubCategoriesCache", () => { @@ -111,10 +111,18 @@ describe("SubCategoriesCache", () => { expectEqualIdSets(subcats!, subcatIds); } - public get current() { return this._current; } - public get next() { return this._next; } - public get request() { return this._request; } - public get disposed() { return this._disposed; } + public get current() { + return this._current; + } + public get next() { + return this._next; + } + public get request() { + return this._request; + } + public get disposed() { + return this._disposed; + } public async waitUntilEmpty(): Promise { while (!this.isEmpty) diff --git a/full-stack-tests/core/src/frontend/standalone/ThematicDisplay.test.ts b/full-stack-tests/core/src/frontend/standalone/ThematicDisplay.test.ts index 4ba584e3308c..fe4b4872882d 100644 --- a/full-stack-tests/core/src/frontend/standalone/ThematicDisplay.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ThematicDisplay.test.ts @@ -2,11 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - ColorDef, RenderMode, ThematicDisplay, ThematicDisplayMode, ThematicDisplayProps, ThematicGradientColorScheme, ThematicGradientMode, + ColorDef, + RenderMode, + ThematicDisplay, + ThematicDisplayMode, + ThematicDisplayProps, + ThematicGradientColorScheme, + ThematicGradientMode, } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection, ViewRect, ViewState3d } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { Color, TestViewport, testViewportsWithDpr } from "../TestViewport"; @@ -110,7 +116,10 @@ describe("Thematic display", () => { const thematicProps: ThematicDisplayProps = { gradientSettings: { colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, range: { low: imodel.projectExtents.xLow, high: imodel.projectExtents.xHigh }, // grab imodel project extents to set range of thematic display axis: [1.0, 0.0, 0.0], @@ -141,7 +150,10 @@ describe("Thematic display", () => { mode: ThematicGradientMode.Stepped, stepCount: 2, colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, range: { low: imodel.projectExtents.xLow - 3.0, high: imodel.projectExtents.xHigh + 3.0 }, // grab imodel project extents to set range of thematic display axis: [1.0, 0.0, 0.0], @@ -171,7 +183,10 @@ describe("Thematic display", () => { gradientSettings: { mode: ThematicGradientMode.IsoLines, colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, range: { low: imodel.projectExtents.xLow, high: imodel.projectExtents.xHigh }, // grab imodel project extents to set range of thematic display axis: [1.0, 0.0, 0.0], @@ -201,7 +216,10 @@ describe("Thematic display", () => { gradientSettings: { mode: ThematicGradientMode.SteppedWithDelimiter, colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, range: { low: imodel.projectExtents.xLow, high: imodel.projectExtents.xHigh }, // grab imodel project extents to set range of thematic display axis: [1.0, 0.0, 0.0], @@ -231,7 +249,10 @@ describe("Thematic display", () => { displayMode: ThematicDisplayMode.InverseDistanceWeightedSensors, gradientSettings: { colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, sensorSettings: { sensors: [ @@ -266,7 +287,10 @@ describe("Thematic display", () => { mode: ThematicGradientMode.Stepped, stepCount: 2, colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, range: { low: 0.0, high: 90.0 }, // range of 0 to 90 degree slopes axis: [1.0, 0.0, 0.0], @@ -298,7 +322,10 @@ describe("Thematic display", () => { mode: ThematicGradientMode.Stepped, stepCount: 2, colorScheme: ThematicGradientColorScheme.Custom, - customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { value: 1.0, color: ColorDef.computeTbgrFromComponents(255, 0, 0) }], + customKeys: [{ value: 0.0, color: ColorDef.computeTbgrFromComponents(0, 0, 255) }, { + value: 1.0, + color: ColorDef.computeTbgrFromComponents(255, 0, 0), + }], }, sunDirection: { x: 0.0, y: 0.0, z: 1.0 }, displayMode: ThematicDisplayMode.HillShade, diff --git a/full-stack-tests/core/src/frontend/standalone/Tool.test.ts b/full-stack-tests/core/src/frontend/standalone/Tool.test.ts index 10053e6a477e..9c3a646cf97f 100644 --- a/full-stack-tests/core/src/frontend/standalone/Tool.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Tool.test.ts @@ -2,11 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { Id64, Id64Arg } from "@itwin/core-bentley"; import { - ElementAgenda, HiliteSet, IModelConnection, ModifyElementSource, SelectionSet, SelectionSetEventType, SnapshotConnection, + ElementAgenda, + HiliteSet, + IModelConnection, + ModifyElementSource, + SelectionSet, + SelectionSetEventType, + SnapshotConnection, } from "@itwin/core-frontend"; +import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; describe("Tools", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/Transparency.test.ts b/full-stack-tests/core/src/frontend/standalone/Transparency.test.ts index edec1c601cd9..64d3fe9c0e34 100644 --- a/full-stack-tests/core/src/frontend/standalone/Transparency.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Transparency.test.ts @@ -2,14 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { - ColorDef, FeatureAppearance, GraphicParams, ImageBuffer, ImageBufferFormat, RenderMaterial, RenderMode, RenderTexture, TextureTransparency, + ColorDef, + FeatureAppearance, + GraphicParams, + ImageBuffer, + ImageBufferFormat, + RenderMaterial, + RenderMode, + RenderTexture, + TextureTransparency, } from "@itwin/core-common"; import { DecorateContext, FeatureSymbology, GraphicType, IModelApp, RenderGraphicOwner, SnapshotConnection, Viewport } from "@itwin/core-frontend"; import { Point3d } from "@itwin/core-geometry"; -import { testOnScreenViewport, TestViewport } from "../TestViewport"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; +import { testOnScreenViewport, TestViewport } from "../TestViewport"; interface GraphicOptions { color: ColorDef; @@ -224,7 +232,7 @@ describe("Transparency", async () => { // Alpha in [0,255]. function createBlueTexture(alpha?: number): RenderTexture { const fmt = undefined !== alpha ? ImageBufferFormat.Rgba : ImageBufferFormat.Rgb; - const bytes = [ 0, 0, 255 ]; + const bytes = [0, 0, 255]; if (undefined !== alpha) bytes.push(alpha); @@ -254,11 +262,11 @@ describe("Transparency", async () => { it("should multiply material alpha with texture if material overrides alpha", async () => { const testCases: Array<[RenderMaterial, number]> = [ - [ createMaterial(1, createBlueTexture(0x7f)), 0x7f ], - [ createMaterial(0.5, createBlueTexture()), 0x7f ], - [ createMaterial(0.5, createBlueTexture(0x7f)), 0xbf ], - [ createMaterial(0, createBlueTexture()), 0xff ], - [ createMaterial(1, createBlueTexture(0)), 0xff ], + [createMaterial(1, createBlueTexture(0x7f)), 0x7f], + [createMaterial(0.5, createBlueTexture()), 0x7f], + [createMaterial(0.5, createBlueTexture(0x7f)), 0xbf], + [createMaterial(0, createBlueTexture()), 0xff], + [createMaterial(1, createBlueTexture(0)), 0xff], ]; for (const testCase of testCases) { @@ -272,16 +280,16 @@ describe("Transparency", async () => { it("should apply texture weight to material color but not alpha", async () => { const testCases: Array<[RenderMaterial, ColorDef]> = [ // Opaque - [ createMaterial(1, createBlueTexture(), 0.5, ColorDef.red), ColorDef.from(0x80, 0, 0x80) ], - [ createMaterial(1, createBlueTexture(), 0.25, ColorDef.red), ColorDef.from(0xc0, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(), 0, ColorDef.red), ColorDef.from(0xff, 0, 0) ], + [createMaterial(1, createBlueTexture(), 0.5, ColorDef.red), ColorDef.from(0x80, 0, 0x80)], + [createMaterial(1, createBlueTexture(), 0.25, ColorDef.red), ColorDef.from(0xc0, 0, 0x40)], + [createMaterial(1, createBlueTexture(), 0, ColorDef.red), ColorDef.from(0xff, 0, 0)], // Translucent - [ createMaterial(0.5, createBlueTexture(), 0.5, ColorDef.red), ColorDef.from(0x40, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(0x80), 0.5, ColorDef.red), ColorDef.from(0x40, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(0x80), 0.75, ColorDef.red), ColorDef.from(0x20, 0, 0x60) ], - [ createMaterial(0.5, createBlueTexture(0x80), 0.5, ColorDef.red), ColorDef.from(0x20, 0, 0x20) ], - [ createMaterial(0.5, createBlueTexture(0x80), 0.25, ColorDef.red), ColorDef.from(0x30, 0, 0x10) ], + [createMaterial(0.5, createBlueTexture(), 0.5, ColorDef.red), ColorDef.from(0x40, 0, 0x40)], + [createMaterial(1, createBlueTexture(0x80), 0.5, ColorDef.red), ColorDef.from(0x40, 0, 0x40)], + [createMaterial(1, createBlueTexture(0x80), 0.75, ColorDef.red), ColorDef.from(0x20, 0, 0x60)], + [createMaterial(0.5, createBlueTexture(0x80), 0.5, ColorDef.red), ColorDef.from(0x20, 0, 0x20)], + [createMaterial(0.5, createBlueTexture(0x80), 0.25, ColorDef.red), ColorDef.from(0x30, 0, 0x10)], ]; for (const testCase of testCases) { @@ -295,16 +303,16 @@ describe("Transparency", async () => { it("should apply texture weight to element color but not alpha if material does not override color", async () => { const testCases: Array<[RenderMaterial, ColorDef]> = [ // Opaque - [ createMaterial(1, createBlueTexture(), 0.5), ColorDef.from(0x80, 0, 0x80) ], - [ createMaterial(1, createBlueTexture(), 0.25), ColorDef.from(0xc0, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(), 0), ColorDef.from(0xff, 0, 0) ], + [createMaterial(1, createBlueTexture(), 0.5), ColorDef.from(0x80, 0, 0x80)], + [createMaterial(1, createBlueTexture(), 0.25), ColorDef.from(0xc0, 0, 0x40)], + [createMaterial(1, createBlueTexture(), 0), ColorDef.from(0xff, 0, 0)], // Translucent - [ createMaterial(0.5, createBlueTexture(), 0.5), ColorDef.from(0x40, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(0x80), 0.5), ColorDef.from(0x40, 0, 0x40) ], - [ createMaterial(1, createBlueTexture(0x80), 0.75), ColorDef.from(0x20, 0, 0x60) ], - [ createMaterial(0.5, createBlueTexture(0x80), 0.5), ColorDef.from(0x20, 0, 0x20) ], - [ createMaterial(0.5, createBlueTexture(0x80), 0.25), ColorDef.from(0x30, 0, 0x10) ], + [createMaterial(0.5, createBlueTexture(), 0.5), ColorDef.from(0x40, 0, 0x40)], + [createMaterial(1, createBlueTexture(0x80), 0.5), ColorDef.from(0x40, 0, 0x40)], + [createMaterial(1, createBlueTexture(0x80), 0.75), ColorDef.from(0x20, 0, 0x60)], + [createMaterial(0.5, createBlueTexture(0x80), 0.5), ColorDef.from(0x20, 0, 0x20)], + [createMaterial(0.5, createBlueTexture(0x80), 0.25), ColorDef.from(0x30, 0, 0x10)], ]; for (const testCase of testCases) { @@ -318,11 +326,11 @@ describe("Transparency", async () => { it("should multiply element alpha with texture if material does not override alpha", async () => { // [Element transparency, material, expected transparency] const testCases: Array<[number, RenderMaterial, number]> = [ - [ 0, createMaterial(undefined, createBlueTexture(0x7f)), 0x7f ], - [ 0x7f, createMaterial(undefined, createBlueTexture()), 0x7f ], - [ 0x7f, createMaterial(undefined, createBlueTexture(0x7f)), 0xbf ], - [ 0xff, createMaterial(undefined, createBlueTexture()), 0xff ], - [ 0, createMaterial(undefined, createBlueTexture(0)), 0xff ], + [0, createMaterial(undefined, createBlueTexture(0x7f)), 0x7f], + [0x7f, createMaterial(undefined, createBlueTexture()), 0x7f], + [0x7f, createMaterial(undefined, createBlueTexture(0x7f)), 0xbf], + [0xff, createMaterial(undefined, createBlueTexture()), 0xff], + [0, createMaterial(undefined, createBlueTexture(0)), 0xff], ]; for (const testCase of testCases) { @@ -408,7 +416,11 @@ describe("Transparency", async () => { await test( (vp) => { - decorator.add(vp, { color: ColorDef.green.withTransparency(0x7f), pickableId, material: createMaterial(undefined, undefined, undefined, ColorDef.red) }); + decorator.add(vp, { + color: ColorDef.green.withTransparency(0x7f), + pickableId, + material: createMaterial(undefined, undefined, undefined, ColorDef.red), + }); decorator.overrideTransparency(pickableId, 0); }, (vp) => expectColor(vp, ColorDef.red), @@ -454,7 +466,7 @@ describe("Transparency", async () => { (vp) => { vp.viewFlags = vp.viewFlags.with("transparency", transp).withRenderMode(renderMode); if (vp.displayStyle.settings.is3d()) - vp.displayStyle.settings.hiddenLineSettings = vp.displayStyle.settings.hiddenLineSettings.override({ transThreshold: 1}); + vp.displayStyle.settings.hiddenLineSettings = vp.displayStyle.settings.hiddenLineSettings.override({ transThreshold: 1 }); decorator.add(vp, { color: ColorDef.green, pickableId, generateEdges: true }); decorator.overrideTransparency(pickableId, 0.5, viewDep); diff --git a/full-stack-tests/core/src/frontend/standalone/ViewCreator3d.test.ts b/full-stack-tests/core/src/frontend/standalone/ViewCreator3d.test.ts index cb3c3ce237ae..c454306cad87 100644 --- a/full-stack-tests/core/src/frontend/standalone/ViewCreator3d.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ViewCreator3d.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { SubCategoryAppearance } from "@itwin/core-common"; -import { IModelConnection, ScreenViewport, SnapshotConnection, ViewCreator3d} from "@itwin/core-frontend"; +import { IModelConnection, ScreenViewport, SnapshotConnection, ViewCreator3d } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import sinon = require("sinon"); @@ -102,4 +102,3 @@ describe("ViewCreator3d", async () => { queryStub.restore(); }); }); - diff --git a/full-stack-tests/core/src/frontend/standalone/ViewState.test.ts b/full-stack-tests/core/src/frontend/standalone/ViewState.test.ts index e53b93188c81..0ce537f07f44 100644 --- a/full-stack-tests/core/src/frontend/standalone/ViewState.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ViewState.test.ts @@ -2,18 +2,40 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; -import { Angle, DeepCompare, Geometry, Matrix3d, Point3d, Range3d, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { Mutable } from "@itwin/core-bentley"; import { - AmbientOcclusion, BackgroundMapType, BaseMapLayerSettings, ColorDef, HiddenLine, RenderMode, SpatialViewDefinitionProps, ViewDefinitionProps, + AmbientOcclusion, + BackgroundMapType, + BaseMapLayerSettings, + ColorDef, + HiddenLine, + RenderMode, + SpatialViewDefinitionProps, + ViewDefinitionProps, } from "@itwin/core-common"; import { - AuxCoordSystemSpatialState, CategorySelectorState, DrawingModelState, DrawingViewState, IModelConnection, LookAtOrthoArgs, MarginPercent, - ModelSelectorState, SheetModelState, SheetViewState, SnapshotConnection, SpatialModelState, SpatialViewState, StandardView, - StandardViewId, ViewState, ViewState3d, ViewStatus, + AuxCoordSystemSpatialState, + CategorySelectorState, + DrawingModelState, + DrawingViewState, + IModelConnection, + LookAtOrthoArgs, + MarginPercent, + ModelSelectorState, + SheetModelState, + SheetViewState, + SnapshotConnection, + SpatialModelState, + SpatialViewState, + StandardView, + StandardViewId, + ViewState, + ViewState3d, + ViewStatus, } from "@itwin/core-frontend"; +import { Angle, DeepCompare, Geometry, Matrix3d, Point3d, Range3d, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { TestRpcInterface } from "../../common/RpcInterfaces"; -import { Mutable } from "@itwin/core-bentley"; import { TestUtility } from "../TestUtility"; describe("ViewState", () => { @@ -60,8 +82,14 @@ describe("ViewState", () => { assert.equal(viewState.displayStyle.id, "0x36", "Display Style Id is 0x36"); assert.equal(viewState.categorySelector.id, "0x37", "Category Id is 0x37"); assert.isFalse(viewState.isCameraOn, "The camera is not turned on"); - assert.isTrue(viewState.extents.isAlmostEqual(new Vector3d(429.6229727570776, 232.24786876266097, 0.1017680889917761)), "View extents as expected"); - assert.isTrue(viewState.origin.isAlmostEqual(new Point3d(-87.73958171815832, -108.96514044887601, -0.0853709702222105)), "View origin as expected"); + assert.isTrue( + viewState.extents.isAlmostEqual(new Vector3d(429.6229727570776, 232.24786876266097, 0.1017680889917761)), + "View extents as expected", + ); + assert.isTrue( + viewState.origin.isAlmostEqual(new Point3d(-87.73958171815832, -108.96514044887601, -0.0853709702222105)), + "View origin as expected", + ); assert.isTrue(viewState.rotation.isIdentity, "View rotation is identity"); assert.equal(viewState.details.gridOrientation, 0, "Grid orientation as expected"); assert.equal(viewState.details.gridSpacing.x, 0.001, "GridSpaceX as expected"); @@ -71,7 +99,10 @@ describe("ViewState", () => { assert.equal(viewState.categorySelector.categories.size, 4); assert.instanceOf(viewState.modelSelector, ModelSelectorState); assert.equal(viewState.modelSelector.models.size, 5); - assert.isTrue(viewState.origin.isAlmostEqual(new Point3d(-87.73958171815832, -108.96514044887601, -0.0853709702222105)), "View origin as expected"); + assert.isTrue( + viewState.origin.isAlmostEqual(new Point3d(-87.73958171815832, -108.96514044887601, -0.0853709702222105)), + "View origin as expected", + ); const v2 = viewState.clone(); compareView(viewState, v2.toJSON(), "v2 clone"); @@ -209,7 +240,11 @@ describe("ViewState", () => { assert.equal(vs0AOSettings.texelStepSize, vs1AOSettings.texelStepSize, "clone should copy displayStyle.ambientOcclusionSettings.texelStepSize"); assert.equal(vs0AOSettings.blurDelta, vs1AOSettings.blurDelta, "clone should copy displayStyle.ambientOcclusionSettings.blurDelta"); assert.equal(vs0AOSettings.blurSigma, vs1AOSettings.blurSigma, "clone should copy displayStyle.ambientOcclusionSettings.blurSigma"); - assert.equal(vs0AOSettings.blurTexelStepSize, vs1AOSettings.blurTexelStepSize, "clone should copy displayStyle.ambientOcclusionSettings.blurTexelStepSize"); + assert.equal( + vs0AOSettings.blurTexelStepSize, + vs1AOSettings.blurTexelStepSize, + "clone should copy displayStyle.ambientOcclusionSettings.blurTexelStepSize", + ); assert.isTrue(vs0BackgroundColor.equals(vs1BackgroundColor), "clone should copy displayStyle.backgroundColor"); const vs0BackgroundBase = vs0.displayStyle.settings.mapImagery.backgroundBase as BaseMapLayerSettings; @@ -223,7 +258,11 @@ describe("ViewState", () => { expect(vs0BackgroundMap.useDepthBuffer).not.to.equal(oldBackgroundMap?.useDepthBuffer ?? false); expect(vs1BackgroundMap.useDepthBuffer).to.equal(vs0BackgroundMap.useDepthBuffer); - assert.equal(vs0HLSettings.transparencyThreshold, vs1HLSettings.transparencyThreshold, "clone should copy displayStyle.hiddenLineSettings.transparencyThreshold"); + assert.equal( + vs0HLSettings.transparencyThreshold, + vs1HLSettings.transparencyThreshold, + "clone should copy displayStyle.hiddenLineSettings.transparencyThreshold", + ); assert.isTrue(vs0MonochromeColor.equals(vs1MonochromeColor), "clone should copy displayStyle.monochromeColor"); }); @@ -346,7 +385,14 @@ describe("ViewState", () => { viewState.setFocusDistance(191); viewState.setEyePoint(Point3d.create(-64, 120, 500)); const cppView: SpatialViewDefinitionProps = await unitTestRpcImp.executeTest(imodel.getRpcProps(), "lookAtUsingLensAngle", testParams); - viewState.lookAt({ eyePoint: testParams.eye, targetPoint: testParams.target, upVector: testParams.up, lensAngle: testParams.lens, frontDistance: testParams.front, backDistance: testParams.back }); + viewState.lookAt({ + eyePoint: testParams.eye, + targetPoint: testParams.target, + upVector: testParams.up, + lensAngle: testParams.lens, + frontDistance: testParams.front, + backDistance: testParams.back, + }); compareToCppView(viewState, cppView, 116.961632, "lookAtUsingLensAngle"); // changing the focus distance shouldn't change the viewing frustum @@ -375,7 +421,14 @@ describe("ViewState", () => { viewState.setEyePoint(Point3d.create(-64, 120, 500)); const viewState2 = viewState.clone(); const viewState3 = viewState.clone(); - viewState.lookAt({ eyePoint: testParams.eye, targetPoint: testParams.target, upVector: testParams.up, lensAngle: testParams.lens, frontDistance: testParams.front, backDistance: testParams.back }); + viewState.lookAt({ + eyePoint: testParams.eye, + targetPoint: testParams.target, + upVector: testParams.up, + lensAngle: testParams.lens, + frontDistance: testParams.front, + backDistance: testParams.back, + }); const extents = viewState.getExtents(); const perspectiveArgs = { diff --git a/full-stack-tests/core/src/frontend/standalone/Viewport.test.ts b/full-stack-tests/core/src/frontend/standalone/Viewport.test.ts index 214c45c9fde4..29bc3c85bf75 100644 --- a/full-stack-tests/core/src/frontend/standalone/Viewport.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/Viewport.test.ts @@ -2,12 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Point3d } from "@itwin/core-geometry"; import { BackgroundMapProps, BackgroundMapSettings, ColorDef, FontMap, FontType } from "@itwin/core-common"; import { - CompassMode, createRenderPlanFromViewport, IModelApp, IModelConnection, PanViewTool, - RenderPlan, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId, TwoWayViewportSync, + CompassMode, + createRenderPlanFromViewport, + IModelApp, + IModelConnection, + PanViewTool, + RenderPlan, + ScreenViewport, + SnapshotConnection, + SpatialViewState, + StandardViewId, + TwoWayViewportSync, } from "@itwin/core-frontend"; +import { Point3d } from "@itwin/core-geometry"; import { assert, expect } from "chai"; import { TestUtility } from "../TestUtility"; @@ -29,7 +38,7 @@ describe("Viewport", () => { const viewDiv = createViewDiv(); const viewDiv2 = createViewDiv(); - before(async () => { // Create a ViewState to load into a Viewport + before(async () => { // Create a ViewState to load into a Viewport await TestUtility.startFrontend(undefined, true); imodel = await SnapshotConnection.openFile("test.bim"); // relative path resolved by BackendTestAssetResolver imodel2 = await SnapshotConnection.openFile("test2.bim"); // relative path resolved by BackendTestAssetResolver @@ -169,17 +178,28 @@ describe("Viewport", () => { }; // Set up baseline values for all properties - test({ groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }, - { groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); + test({ groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }, { + groundBias: 1234.5, + transparency: 0.3, + useDepthBuffer: true, + applyTerrain: true, + }); // Set values to the current values - test({ groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }, - { groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); + test({ groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }, { + groundBias: 1234.5, + transparency: 0.3, + useDepthBuffer: true, + applyTerrain: true, + }); // Undefined values => preserve current name, type, & bias - test({ groundBias: undefined, transparency: undefined, useDepthBuffer: undefined, applyTerrain: undefined }, - { groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); + test({ groundBias: undefined, transparency: undefined, useDepthBuffer: undefined, applyTerrain: undefined }, { + groundBias: 1234.5, + transparency: 0.3, + useDepthBuffer: true, + applyTerrain: true, + }); // Missing values => preserve current name, type, & bias - test({}, - { groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); + test({}, { groundBias: 1234.5, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); // Change groundBias only to int test({ groundBias: 543 }, { groundBias: 543, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); @@ -187,8 +207,7 @@ describe("Viewport", () => { test({ groundBias: -50.3 }, { groundBias: -50.3, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); // Change bias - test({ groundBias: -10 }, - { groundBias: -10, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); + test({ groundBias: -10 }, { groundBias: -10, transparency: 0.3, useDepthBuffer: true, applyTerrain: true }); // Change transparency to a number test({ transparency: 0.0 }, { groundBias: -10, transparency: 0.0, useDepthBuffer: true, applyTerrain: true }); diff --git a/full-stack-tests/core/src/frontend/standalone/ViewportChangedEvents.test.ts b/full-stack-tests/core/src/frontend/standalone/ViewportChangedEvents.test.ts index aa8e7675e90b..221fcd0e8862 100644 --- a/full-stack-tests/core/src/frontend/standalone/ViewportChangedEvents.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/ViewportChangedEvents.test.ts @@ -2,17 +2,36 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, Id64, Id64Arg, Id64String } from "@itwin/core-bentley"; -import { ClipVector, Transform } from "@itwin/core-geometry"; import { - AmbientOcclusion, AnalysisStyle, ClipStyle, ColorDef, FeatureAppearance, ModelClipGroup, ModelClipGroups, MonochromeMode, PlanProjectionSettings, SubCategoryOverride, ThematicDisplay, ViewFlags, + AmbientOcclusion, + AnalysisStyle, + ClipStyle, + ColorDef, + FeatureAppearance, + ModelClipGroup, + ModelClipGroups, + MonochromeMode, + PlanProjectionSettings, + SubCategoryOverride, + ThematicDisplay, + ViewFlags, } from "@itwin/core-common"; import { - ChangeFlag, FeatureSymbology, PerModelCategoryVisibility, ScreenViewport, SnapshotConnection, SpatialViewState, StandardViewId, Viewport, ViewState, + ChangeFlag, + FeatureSymbology, + PerModelCategoryVisibility, + ScreenViewport, + SnapshotConnection, + SpatialViewState, + StandardViewId, + Viewport, + ViewState, } from "@itwin/core-frontend"; -import { ViewportChangedHandler, ViewportState } from "../ViewportChangedHandler"; +import { ClipVector, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; +import { ViewportChangedHandler, ViewportState } from "../ViewportChangedHandler"; describe("Viewport changed events", async () => { // test.bim: @@ -160,7 +179,11 @@ describe("Viewport changed events", async () => { }); // Change ClipStyle - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.RenderPlan, () => vp.clipStyle = ClipStyle.fromJSON({ cutStyle: { appearance: { weight: 12 } } })); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.RenderPlan, + () => vp.clipStyle = ClipStyle.fromJSON({ cutStyle: { appearance: { weight: 12 } } }), + ); // Modify view flags through Viewport's displayStyle property. vp.saveViewUndo(); @@ -174,7 +197,11 @@ describe("Viewport changed events", async () => { // Override subcategories directly on display style without going through Viewport API => produces event const ovr = SubCategoryOverride.fromJSON({ color: ColorDef.green.tbgr }); - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.RenderPlan, () => vp.displayStyle.overrideSubCategory("0x123", ovr)); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.RenderPlan, + () => vp.displayStyle.overrideSubCategory("0x123", ovr), + ); // Override by replacing display style on Viewport vp.saveViewUndo(); @@ -194,7 +221,11 @@ describe("Viewport changed events", async () => { // Apply different override to same subcategory vp.saveViewUndo(); - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.RenderPlan, () => vp.overrideSubCategory("0x123", SubCategoryOverride.fromJSON({ color: ColorDef.red.tbgr }))); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.RenderPlan, + () => vp.overrideSubCategory("0x123", SubCategoryOverride.fromJSON({ color: ColorDef.red.tbgr })), + ); }); }); @@ -205,7 +236,8 @@ describe("Viewport changed events", async () => { ViewportChangedHandler.test(vp, (mon) => { const expectNoChange = (func: () => void) => mon.expect(ChangeFlag.None, undefined, func); const expectChange = (func: () => void) => mon.expect(ChangeFlag.DisplayStyle, ViewportState.RenderPlan, func); - const expectOverrideChange = (func: () => void) => mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.RenderPlan, func); + const expectOverrideChange = (func: () => void) => + mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.RenderPlan, func); expectNoChange(() => view.displayStyle = view.displayStyle); expectOverrideChange(() => view.displayStyle = view.displayStyle.clone()); @@ -234,20 +266,34 @@ describe("Viewport changed events", async () => { expectNoChange(() => settings.analysisFraction = settings.analysisFraction); mon.expect(ChangeFlag.DisplayStyle, ViewportState.AnalysisFraction, () => settings.analysisFraction = 0.123456); - mon.expect(ChangeFlag.DisplayStyle, ViewportState.AnalysisFraction | ViewportState.RenderPlan, () => settings.analysisStyle = AnalysisStyle.fromJSON({ displacement: { channelName: "source" } })); + mon.expect( + ChangeFlag.DisplayStyle, + ViewportState.AnalysisFraction | ViewportState.RenderPlan, + () => settings.analysisStyle = AnalysisStyle.fromJSON({ displacement: { channelName: "source" } }), + ); mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.TimePoint, () => settings.timePoint = 43); expectNoChange(() => settings.timePoint = 43); // eslint-disable-next-line deprecation/deprecation - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.TimePoint | ViewportState.Scene, () => settings.scheduleScriptProps = [{ modelId: "0x123", elementTimelines: [] }]); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.TimePoint | ViewportState.Scene, + () => settings.scheduleScriptProps = [{ modelId: "0x123", elementTimelines: [] }], + ); // eslint-disable-next-line deprecation/deprecation - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.TimePoint | ViewportState.Scene, () => settings.scheduleScriptProps = undefined); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.TimePoint | ViewportState.Scene, + () => settings.scheduleScriptProps = undefined, + ); // If assignment to scheduleScriptProps produces no net change, no event. // eslint-disable-next-line deprecation/deprecation expectNoChange(() => settings.scheduleScriptProps = undefined); - expectChange(() => settings.hiddenLineSettings = settings.hiddenLineSettings.override({ transThreshold: 1.0 - settings.hiddenLineSettings.transThreshold })); + expectChange(() => + settings.hiddenLineSettings = settings.hiddenLineSettings.override({ transThreshold: 1.0 - settings.hiddenLineSettings.transThreshold }) + ); expectNoChange(() => settings.hiddenLineSettings = settings.hiddenLineSettings.override({})); expectNoChange(() => settings.lights = settings.lights.clone()); @@ -275,9 +321,17 @@ describe("Viewport changed events", async () => { ViewportChangedHandler.test(vp, (mon) => { const settings = vp.view.displayStyle.settings; - mon.expect(ChangeFlag.DisplayStyle, ViewportState.Controller, () => settings.applyOverrides({ viewflags: { backgroundMap: !settings.viewFlags.backgroundMap } })); + mon.expect( + ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => settings.applyOverrides({ viewflags: { backgroundMap: !settings.viewFlags.backgroundMap } }), + ); mon.expect(ChangeFlag.DisplayStyle, ViewportState.RenderPlan, () => settings.applyOverrides({ backgroundColor: 0xabcdef })); - mon.expect(ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, ViewportState.TimePoint | ViewportState.Scene, () => settings.applyOverrides({ scheduleScript: [{ modelId: "0x321", elementTimelines: [] }] })); + mon.expect( + ChangeFlag.DisplayStyle | ChangeFlag.FeatureOverrideProvider, + ViewportState.TimePoint | ViewportState.Scene, + () => settings.applyOverrides({ scheduleScript: [{ modelId: "0x321", elementTimelines: [] }] }), + ); }); }); @@ -293,7 +347,11 @@ describe("Viewport changed events", async () => { vf = vf.with("backgroundMap", !vf.backgroundMap); mon.expect(ChangeFlag.DisplayStyle, ViewportState.Controller, () => vp.viewFlags = vf); - mon.expect(ChangeFlag.DisplayStyle, ViewportState.Controller, () => vp.backgroundMapSettings = vp.backgroundMapSettings.clone({ groundBias: 123 })); + mon.expect( + ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => vp.backgroundMapSettings = vp.backgroundMapSettings.clone({ groundBias: 123 }), + ); mon.expect(ChangeFlag.DisplayStyle, ViewportState.Controller, () => vp.changeBackgroundMapProps({ groundBias: 456 })); }); }); @@ -360,11 +418,19 @@ describe("Viewport changed events", async () => { // Switching to a different 2d view of a different model should produce model-changed event // Note: new view also has different categories enabled. const view35 = await testImodel.views.load(id64(0x35)); // views model 0x1e - mon.expect(ChangeFlag.ViewedModels | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle | ChangeFlag.ViewState, ViewportState.Controller, () => changeView(vp, view35)); + mon.expect( + ChangeFlag.ViewedModels | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle | ChangeFlag.ViewState, + ViewportState.Controller, + () => changeView(vp, view35), + ); // Switch back to previous view. // Note: changeView(vp, ) clears undo stack so cannot/needn't test undo/redo here. - mon.expect(ChangeFlag.ViewedModels | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle | ChangeFlag.ViewState, ViewportState.Controller, () => changeView(vp, view20.clone())); + mon.expect( + ChangeFlag.ViewedModels | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle | ChangeFlag.ViewState, + ViewportState.Controller, + () => changeView(vp, view20.clone()), + ); }); }); @@ -453,7 +519,11 @@ describe("Viewport changed events", async () => { // Switching to a different view with different category selector produces event const view17 = await testImodel.views.load(id64(0x17)); - mon.expect(ChangeFlag.ViewState | ChangeFlag.DisplayStyle | ChangeFlag.ViewedCategories, ViewportState.Controller, () => changeView(vp, view17)); + mon.expect( + ChangeFlag.ViewState | ChangeFlag.DisplayStyle | ChangeFlag.ViewedCategories, + ViewportState.Controller, + () => changeView(vp, view17), + ); // Changing category selector, then switching to a view with same categories enabled produces no event. mon.expect(ChangeFlag.ViewedCategories, undefined, () => { @@ -461,7 +531,11 @@ describe("Viewport changed events", async () => { vp.changeCategoryDisplay(view13.categorySelector.categories, true); }); - mon.expect(ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle, ViewportState.Controller, () => changeView(vp, view13)); + mon.expect( + ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => changeView(vp, view13), + ); }); }); @@ -529,7 +603,11 @@ describe("Viewport changed events", async () => { const modelIdList = ["0x1", "0x2", "0x3"]; const catIdList = ["0xa", "0xb"]; - mon.expect(ChangeFlag.ViewedCategoriesPerModel, undefined, () => vis.setOverride(modelIdList, catIdList, PerModelCategoryVisibility.Override.Show)); + mon.expect( + ChangeFlag.ViewedCategoriesPerModel, + undefined, + () => vis.setOverride(modelIdList, catIdList, PerModelCategoryVisibility.Override.Show), + ); for (const modelId of modelIdList) for (const catId of catIdList) expect(vis.getOverride(modelId, catId)).to.equal(PerModelCategoryVisibility.Override.Show); @@ -539,7 +617,11 @@ describe("Viewport changed events", async () => { modelIdList.shift(); // remove "0x1" catIdList.shift(); // remove "0xa" - mon.expect(ChangeFlag.ViewedCategoriesPerModel, undefined, () => vis.setOverride(modelIdList, catIdList, PerModelCategoryVisibility.Override.Hide)); + mon.expect( + ChangeFlag.ViewedCategoriesPerModel, + undefined, + () => vis.setOverride(modelIdList, catIdList, PerModelCategoryVisibility.Override.Hide), + ); expect(vis.getOverride("0x1", "0xa")).to.equal(PerModelCategoryVisibility.Override.Show); expect(vis.getOverride("0x1", "0xb")).to.equal(PerModelCategoryVisibility.Override.Show); expect(vis.getOverride("0x2", "0xa")).to.equal(PerModelCategoryVisibility.Override.Show); @@ -601,10 +683,18 @@ describe("Viewport changed events", async () => { mon.expect(ChangeFlag.ViewState, ViewportState.Controller, () => changeView(vp, view2d20.clone())); // 2d => 2d - mon.expect(ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, ViewportState.Controller, () => changeView(vp, view2d2e.clone())); + mon.expect( + ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => changeView(vp, view2d2e.clone()), + ); // 2d => 3d - mon.expect(ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, ViewportState.Controller, () => changeView(vp, view3d15.clone())); + mon.expect( + ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => changeView(vp, view3d15.clone()), + ); // No effective change mon.expect(ChangeFlag.ViewState, ViewportState.Controller, () => changeView(vp, view3d15.clone())); @@ -613,7 +703,11 @@ describe("Viewport changed events", async () => { mon.expect(ChangeFlag.ViewState | ChangeFlag.ViewedCategories, ViewportState.Controller, () => changeView(vp, view3d17.clone())); // 3d => 2d - mon.expect(ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, ViewportState.Controller, () => changeView(vp, view2d20.clone())); + mon.expect( + ChangeFlag.ViewState | ChangeFlag.ViewedCategories | ChangeFlag.ViewedModels | ChangeFlag.DisplayStyle, + ViewportState.Controller, + () => changeView(vp, view2d20.clone()), + ); // Pass the exact same ViewState reference => no "ViewState changed" event. mon.expect(ChangeFlag.None, undefined, () => changeView(vp, vp.view)); @@ -645,22 +739,27 @@ describe("Viewport changed events", async () => { ViewportChangedHandler.test(vp, (mon) => { const expectChange = (state: ViewportState, func: () => void) => mon.expect(ChangeFlag.None, state, func); - expectChange(ViewportState.RenderPlan, () => view.details.clipVector = ClipVector.fromJSON([{ - shape: { - points: [ - [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 0, 0], - ], - }, - }])); + expectChange(ViewportState.RenderPlan, () => + view.details.clipVector = ClipVector.fromJSON([{ + shape: { + points: [ + [0, 0, 0], + [1, 0, 0], + [1, 1, 0], + [0, 0, 0], + ], + }, + }])); expectChange(ViewportState.Scene, () => view.details.modelClipGroups = new ModelClipGroups([ModelClipGroup.fromJSON({ models: ["0x123"] })])); - expectChange(ViewportState.Scene, () => view.modelDisplayTransformProvider = { - getModelDisplayTransform: () => { - return { - transform: Transform.createIdentity(), - }; - }, - }); + expectChange(ViewportState.Scene, () => + view.modelDisplayTransformProvider = { + getModelDisplayTransform: () => { + return { + transform: Transform.createIdentity(), + }; + }, + }); }); }); diff --git a/full-stack-tests/core/src/frontend/standalone/WaitForSceneCompletion.test.ts b/full-stack-tests/core/src/frontend/standalone/WaitForSceneCompletion.test.ts index c85d0265beb5..41faf7f10080 100644 --- a/full-stack-tests/core/src/frontend/standalone/WaitForSceneCompletion.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/WaitForSceneCompletion.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef, RenderMode } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection, ViewRect } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { Color, TestViewport, testViewportsWithDpr } from "../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/standalone/WatchForChanges.test.ts b/full-stack-tests/core/src/frontend/standalone/WatchForChanges.test.ts index 5779977f6221..df4532580449 100644 --- a/full-stack-tests/core/src/frontend/standalone/WatchForChanges.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/WatchForChanges.test.ts @@ -2,15 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as path from "path"; import { Guid, Id64, OpenMode, ProcessDetector } from "@itwin/core-bentley"; import { ColorDef, ElementAlignedBox3d, PackedFeature, RenderFeatureTable } from "@itwin/core-common"; +import { BriefcaseConnection, GeometricModelState, IModelApp, MockRender, RenderGraphic, TileTree, ViewCreator3d } from "@itwin/core-frontend"; import { Point3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; +import * as path from "path"; import { - BriefcaseConnection, GeometricModelState, IModelApp, MockRender, RenderGraphic, TileTree, ViewCreator3d, -} from "@itwin/core-frontend"; -import { addAllowedChannel, coreFullStackTestIpc, deleteElements, initializeEditTools, insertLineStringElement, makeModelCode, transformElements } from "../Editing"; + addAllowedChannel, + coreFullStackTestIpc, + deleteElements, + initializeEditTools, + insertLineStringElement, + makeModelCode, + transformElements, +} from "../Editing"; import { TestUtility } from "../TestUtility"; class System extends MockRender.System { @@ -60,7 +66,10 @@ for (const watchForChanges of [false, true]) { // Populate the iModel with some initial geometry. rwConn = await BriefcaseConnection.openStandalone(filePath, OpenMode.ReadWrite); await addAllowedChannel(rwConn, "shared"); - modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel(rwConn.key, (await makeModelCode(rwConn, rwConn.models.repositoryModelId, Guid.createValue()))); + modelId = await coreFullStackTestIpc.createAndInsertPhysicalModel( + rwConn.key, + await makeModelCode(rwConn, rwConn.models.repositoryModelId, Guid.createValue()), + ); const dictId = await rwConn.models.getDictionaryModel(); categoryId = await coreFullStackTestIpc.createAndInsertSpatialCategory(rwConn.key, dictId, Guid.createValue(), { color: 0 }); @@ -70,17 +79,24 @@ for (const watchForChanges of [false, true]) { projCenter.z = Math.round(projCenter.z); const point = projCenter.clone(); - elemId = await insertLineStringElement(rwConn, { model: modelId, category: categoryId, color: ColorDef.green, points: [point, new Point3d(point.x, point.y + 2, point.z)] }); + elemId = await insertLineStringElement(rwConn, { + model: modelId, + category: categoryId, + color: ColorDef.green, + points: [point, new Point3d(point.x, point.y + 2, point.z)], + }); expect(Id64.isValid(elemId)).to.be.true; await rwConn.saveChanges(); // Open a second, read-only connection that will monitor for changes made via the read-write connection. - roConn = watchForChanges ? (await BriefcaseConnection.openFile({ - fileName: filePath, - key: Guid.createValue(), - readonly: true, - watchForChanges: true, - })) : rwConn; + roConn = watchForChanges ? + (await BriefcaseConnection.openFile({ + fileName: filePath, + key: Guid.createValue(), + readonly: true, + watchForChanges: true, + })) : + rwConn; }); afterEach(async () => { @@ -158,7 +174,12 @@ for (const watchForChanges of [false, true]) { prevGuid = model.geometryGuid; prevTree = newTree; - const elemId2 = await insertLineStringElement(rwConn, { model: modelId, category: categoryId, color: ColorDef.red, points: [projCenter.clone(), projCenter.plus({ x: 2, y: 0, z: 0 })] }); + const elemId2 = await insertLineStringElement(rwConn, { + model: modelId, + category: categoryId, + color: ColorDef.red, + points: [projCenter.clone(), projCenter.plus({ x: 2, y: 0, z: 0 })], + }); await expectModelChanges(async () => rwConn.saveChanges()); expect(model.geometryGuid).not.to.equal(prevGuid); diff --git a/full-stack-tests/core/src/frontend/standalone/WhiteOnWhiteReversal.test.ts b/full-stack-tests/core/src/frontend/standalone/WhiteOnWhiteReversal.test.ts index e6d4eefd6a61..745a4973ffe0 100644 --- a/full-stack-tests/core/src/frontend/standalone/WhiteOnWhiteReversal.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/WhiteOnWhiteReversal.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ColorDef, FeatureAppearance, RenderMode, ViewFlags, WhiteOnWhiteReversalSettings } from "@itwin/core-common"; import { DecorateContext, FeatureSymbology, GraphicType, IModelApp, IModelConnection, SnapshotConnection, Viewport } from "@itwin/core-frontend"; import { Point3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../TestUtility"; import { Color, testOnScreenViewport } from "../TestViewport"; @@ -22,7 +22,11 @@ describe("White-on-white reversal", async () => { await TestUtility.shutdownFrontend(); }); - async function test(expectedColors: Color[], setup: (vp: Viewport, vf: ViewFlags) => ViewFlags | undefined, cleanup?: (vp: Viewport) => void): Promise { + async function test( + expectedColors: Color[], + setup: (vp: Viewport, vf: ViewFlags) => ViewFlags | undefined, + cleanup?: (vp: Viewport) => void, + ): Promise { await testOnScreenViewport("0x24", imodel, 100, 100, async (vp) => { const vf = vp.viewFlags.copy({ renderMode: RenderMode.Wireframe, acsTriad: false }); const newVf = setup(vp, vf); diff --git a/full-stack-tests/core/src/frontend/standalone/tile/B3dmTileIO.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/B3dmTileIO.test.ts index 55c4586e329a..8896e91a0b85 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/B3dmTileIO.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/B3dmTileIO.test.ts @@ -2,281 +2,4256 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ByteStream } from "@itwin/core-bentley"; -import { Range3d } from "@itwin/core-geometry"; import { RenderTexture } from "@itwin/core-common"; import { B3dmReader, GltfDataType, IModelApp, MockRender, RealityMeshParams, SnapshotConnection } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; /* eslint-disable @typescript-eslint/unbound-method */ const b3dmBytes = new Uint8Array([ - 0x62, 0x33, 0x64, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x90, 0x10, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x42, 0x41, - 0x54, 0x43, 0x48, 0x5f, 0x4c, 0x45, 0x4e, 0x47, 0x54, 0x48, 0x22, 0x3a, 0x31, 0x7d, 0x20, 0x20, - 0x7b, 0x22, 0x62, 0x61, 0x74, 0x63, 0x68, 0x49, 0x64, 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x2c, 0x22, - 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x5b, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x5f, 0x30, 0x22, 0x5d, - 0x7d, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x10, 0x00, 0x00, - 0xe8, 0x08, 0x00, 0x00, 0x4a, 0x53, 0x4f, 0x4e, 0x7b, 0x22, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x6f, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, - 0x65, 0x77, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x35, 0x31, 0x32, 0x35, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x3a, 0x33, 0x30, 0x2c, 0x22, 0x6d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x31, 0x31, 0x2e, - 0x30, 0x5d, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x5d, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x53, 0x43, 0x41, 0x4c, 0x41, 0x52, 0x22, 0x7d, 0x2c, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x35, 0x31, 0x32, 0x36, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, - 0x22, 0x6d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x33, 0x32, 0x39, 0x2e, 0x36, 0x38, 0x36, 0x33, 0x30, - 0x39, 0x38, 0x31, 0x34, 0x34, 0x35, 0x33, 0x2c, 0x2d, 0x31, 0x35, 0x39, 0x2e, 0x36, 0x31, 0x37, - 0x32, 0x36, 0x33, 0x37, 0x39, 0x33, 0x39, 0x34, 0x35, 0x2c, 0x31, 0x34, 0x2e, 0x35, 0x36, 0x38, - 0x36, 0x35, 0x31, 0x31, 0x39, 0x39, 0x33, 0x34, 0x30, 0x38, 0x5d, 0x2c, 0x22, 0x6d, 0x69, 0x6e, - 0x22, 0x3a, 0x5b, 0x33, 0x31, 0x39, 0x2e, 0x38, 0x32, 0x39, 0x38, 0x30, 0x33, 0x34, 0x36, 0x36, - 0x37, 0x39, 0x37, 0x2c, 0x2d, 0x31, 0x37, 0x35, 0x2e, 0x38, 0x37, 0x35, 0x30, 0x34, 0x35, 0x37, - 0x37, 0x36, 0x33, 0x36, 0x37, 0x2c, 0x31, 0x31, 0x2e, 0x35, 0x35, 0x39, 0x31, 0x31, 0x30, 0x36, - 0x34, 0x31, 0x34, 0x37, 0x39, 0x35, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, - 0x56, 0x45, 0x43, 0x33, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x35, 0x31, 0x32, 0x36, 0x2c, 0x22, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x6d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x35, 0x2e, - 0x30, 0x37, 0x35, 0x39, 0x36, 0x38, 0x31, 0x34, 0x37, 0x31, 0x33, 0x39, 0x30, 0x36, 0x65, 0x2d, - 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x34, 0x32, 0x33, 0x34, 0x39, 0x32, 0x35, 0x35, 0x30, 0x38, 0x34, - 0x39, 0x39, 0x31, 0x35, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x22, 0x3a, - 0x5b, 0x2d, 0x30, 0x2e, 0x39, 0x36, 0x36, 0x30, 0x34, 0x37, 0x33, 0x34, 0x36, 0x35, 0x39, 0x31, - 0x39, 0x34, 0x39, 0x2c, 0x2d, 0x30, 0x2e, 0x38, 0x34, 0x31, 0x39, 0x34, 0x39, 0x33, 0x34, 0x33, - 0x36, 0x38, 0x31, 0x33, 0x33, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x39, 0x39, 0x30, 0x32, 0x37, 0x36, - 0x33, 0x33, 0x36, 0x36, 0x36, 0x39, 0x39, 0x32, 0x32, 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x22, 0x56, 0x45, 0x43, 0x33, 0x22, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x6f, - 0x6e, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x35, 0x31, 0x32, 0x36, 0x2c, 0x22, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x6d, 0x61, 0x78, 0x22, 0x3a, - 0x5b, 0x30, 0x2e, 0x37, 0x33, 0x35, 0x35, 0x34, 0x36, 0x39, 0x34, 0x36, 0x35, 0x32, 0x35, 0x35, - 0x37, 0x34, 0x2c, 0x30, 0x2e, 0x37, 0x32, 0x34, 0x30, 0x32, 0x38, 0x38, 0x32, 0x35, 0x37, 0x35, - 0x39, 0x38, 0x38, 0x38, 0x5d, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x31, - 0x33, 0x37, 0x38, 0x30, 0x38, 0x35, 0x30, 0x31, 0x37, 0x32, 0x30, 0x34, 0x32, 0x38, 0x2c, 0x30, - 0x2e, 0x35, 0x30, 0x34, 0x39, 0x32, 0x34, 0x32, 0x39, 0x37, 0x33, 0x33, 0x32, 0x37, 0x36, 0x34, - 0x5d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x56, 0x45, 0x43, 0x32, 0x22, 0x7d, - 0x5d, 0x2c, 0x22, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x67, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x6f, 0x72, 0x22, 0x3a, 0x22, 0x66, 0x61, 0x6e, 0x66, 0x61, 0x6e, 0x22, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x22, 0x32, 0x2e, 0x30, 0x22, 0x7d, - 0x2c, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x5b, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x30, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x74, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, 0x39, 0x36, 0x33, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x34, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x30, 0x2c, 0x22, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x22, 0x3a, 0x33, 0x34, 0x39, 0x36, 0x32, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x31, 0x34, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x32, 0x36, 0x34, 0x2c, 0x22, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, - 0x3a, 0x33, 0x34, 0x39, 0x36, 0x32, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x34, 0x30, 0x38, 0x2c, 0x22, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, - 0x39, 0x36, 0x32, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x35, - 0x35, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x35, - 0x30, 0x34, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x33, 0x33, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, - 0x36, 0x30, 0x2c, 0x22, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, 0x39, 0x36, - 0x32, 0x7d, 0x2c, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x31, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x36, 0x39, - 0x36, 0x2c, 0x22, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, 0x39, 0x36, 0x32, - 0x7d, 0x5d, 0x2c, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x34, 0x38, - 0x7d, 0x5d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x73, - 0x5f, 0x77, 0x65, 0x62, 0x67, 0x6c, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, - 0x6d, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x2c, 0x22, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x22, 0x5d, 0x2c, - 0x22, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x22, 0x3a, 0x30, 0x7d, 0x5d, 0x2c, 0x22, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0x3a, - 0x5b, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x35, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x33, 0x33, 0x7d, 0x2c, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x36, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x33, 0x32, 0x7d, 0x5d, 0x2c, 0x22, 0x74, - 0x65, 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x61, 0x5f, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x69, 0x64, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, - 0x63, 0x22, 0x3a, 0x22, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x49, 0x44, 0x22, 0x2c, 0x22, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x3a, 0x35, 0x31, 0x32, 0x33, 0x7d, 0x2c, 0x22, 0x61, 0x5f, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, - 0x69, 0x63, 0x22, 0x3a, 0x22, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x22, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x36, 0x35, 0x7d, 0x2c, 0x22, 0x61, 0x5f, - 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x6d, - 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, 0x3a, 0x22, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, - 0x5f, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x36, 0x34, - 0x7d, 0x7d, 0x2c, 0x22, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x22, 0x3a, 0x5b, 0x32, 0x38, 0x38, 0x34, 0x2c, 0x32, 0x39, 0x32, 0x39, 0x5d, 0x7d, 0x2c, 0x22, - 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x75, 0x5f, 0x64, 0x69, - 0x66, 0x66, 0x75, 0x73, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, - 0x35, 0x36, 0x37, 0x38, 0x7d, 0x2c, 0x22, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, - 0x65, 0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x6d, 0x61, - 0x6e, 0x74, 0x69, 0x63, 0x22, 0x3a, 0x22, 0x4d, 0x4f, 0x44, 0x45, 0x4c, 0x56, 0x49, 0x45, 0x57, - 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x37, 0x36, 0x7d, 0x2c, - 0x22, 0x75, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x74, - 0x72, 0x69, 0x78, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x6d, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x22, - 0x3a, 0x22, 0x50, 0x52, 0x4f, 0x4a, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x22, 0x2c, 0x22, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x3a, 0x33, 0x35, 0x36, 0x37, 0x36, 0x7d, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, - 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x74, 0x65, 0x63, 0x68, - 0x6e, 0x69, 0x71, 0x75, 0x65, 0x73, 0x5f, 0x77, 0x65, 0x62, 0x67, 0x6c, 0x22, 0x5d, 0x2c, 0x22, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, - 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x73, - 0x5f, 0x77, 0x65, 0x62, 0x67, 0x6c, 0x22, 0x5d, 0x2c, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x73, - 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, - 0x3a, 0x34, 0x2c, 0x22, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x22, 0x69, - 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x78, 0x74, 0x65, - 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x74, 0x65, - 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x73, 0x5f, 0x77, 0x65, 0x62, 0x67, 0x6c, 0x22, 0x3a, - 0x7b, 0x22, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x75, 0x5f, 0x64, 0x69, 0x66, 0x66, - 0x75, 0x73, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x7d, 0x7d, - 0x7d, 0x5d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x70, - 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x4f, 0x52, 0x4d, - 0x41, 0x4c, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x5f, 0x30, 0x22, 0x3a, - 0x33, 0x7d, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6d, 0x6f, 0x64, - 0x65, 0x22, 0x3a, 0x34, 0x7d, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6e, 0x61, 0x6d, - 0x65, 0x22, 0x3a, 0x22, 0x22, 0x7d, 0x5d, 0x2c, 0x22, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, - 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6d, 0x61, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, - 0x3a, 0x39, 0x37, 0x32, 0x39, 0x2c, 0x22, 0x6d, 0x69, 0x6e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x22, 0x3a, 0x39, 0x39, 0x38, 0x36, 0x2c, 0x22, 0x77, 0x72, 0x61, 0x70, 0x53, 0x22, 0x3a, 0x31, - 0x30, 0x34, 0x39, 0x37, 0x2c, 0x22, 0x77, 0x72, 0x61, 0x70, 0x54, 0x22, 0x3a, 0x31, 0x30, 0x34, - 0x39, 0x37, 0x7d, 0x5d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x22, 0x3a, 0x5b, 0x30, 0x5d, 0x7d, 0x5d, 0x2c, 0x22, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, - 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x5d, 0x7d, 0x20, 0x20, - 0x38, 0x07, 0x00, 0x00, 0x42, 0x49, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x39, 0x63, 0xa2, 0x43, 0x44, 0xd3, 0x2d, 0xc3, 0x1e, 0xf3, 0x38, 0x41, 0xa8, 0x38, 0xa4, 0x43, - 0x03, 0xe0, 0x2f, 0xc3, 0x1e, 0xf2, 0x38, 0x41, 0x51, 0x40, 0xa2, 0x43, 0xb1, 0xba, 0x2c, 0xc3, - 0x32, 0x19, 0x69, 0x41, 0xaa, 0xbb, 0xa2, 0x43, 0xe1, 0x94, 0x2a, 0xc3, 0x55, 0xf3, 0x38, 0x41, - 0x51, 0x40, 0xa2, 0x43, 0xb1, 0xba, 0x2c, 0xc3, 0x32, 0x19, 0x69, 0x41, 0xc6, 0xbc, 0xa3, 0x43, - 0x56, 0x27, 0x28, 0xc3, 0x2d, 0xf3, 0x38, 0x41, 0xaa, 0xbb, 0xa2, 0x43, 0xe1, 0x94, 0x2a, 0xc3, - 0x55, 0xf3, 0x38, 0x41, 0xd9, 0xd7, 0xa4, 0x43, 0x11, 0xdf, 0x25, 0xc3, 0xf5, 0xf2, 0x38, 0x41, - 0x37, 0xea, 0x9f, 0x43, 0x53, 0xef, 0x28, 0xc3, 0xae, 0xf4, 0x38, 0x41, 0x62, 0xc7, 0xa3, 0x43, - 0x73, 0xf2, 0x27, 0xc3, 0x2e, 0xf3, 0x38, 0x41, 0x00, 0xb9, 0xa3, 0x43, 0xdc, 0x13, 0x28, 0xc3, - 0x31, 0xf3, 0x38, 0x41, 0x88, 0x87, 0xa2, 0x43, 0x05, 0x9e, 0x1f, 0xc3, 0x96, 0xf4, 0x38, 0x41, - 0xa4, 0x0b, 0x5e, 0xbf, 0x83, 0xb6, 0xf9, 0xbe, 0x00, 0xcf, 0xca, 0x3d, 0x38, 0xed, 0xf0, 0xbe, - 0xfe, 0x89, 0x57, 0xbf, 0xad, 0x2a, 0x87, 0x3e, 0xe1, 0x4e, 0x77, 0xbf, 0x24, 0xf5, 0xf5, 0x3d, - 0x0a, 0x3f, 0x6a, 0x3e, 0x58, 0x66, 0x2a, 0xbf, 0x43, 0x37, 0xa2, 0x3e, 0x63, 0xfa, 0x2c, 0x3f, - 0xe1, 0x4e, 0x77, 0xbf, 0x24, 0xf5, 0xf5, 0x3d, 0x0a, 0x3f, 0x6a, 0x3e, 0x16, 0xff, 0xf1, 0xbe, - 0x04, 0xd4, 0xd8, 0x3e, 0xc8, 0xd7, 0x45, 0x3f, 0x58, 0x66, 0x2a, 0xbf, 0x43, 0x37, 0xa2, 0x3e, - 0x63, 0xfa, 0x2c, 0x3f, 0xc1, 0xc5, 0x95, 0xbd, 0xae, 0x2c, 0x91, 0x3d, 0x36, 0xab, 0x7e, 0x3f, - 0x12, 0xd0, 0x54, 0x38, 0xbf, 0x3c, 0xda, 0xb7, 0x00, 0x00, 0x80, 0x3f, 0x65, 0x57, 0x54, 0x38, - 0x18, 0xd8, 0xd5, 0xb7, 0x00, 0x00, 0x80, 0x3f, 0xd7, 0xdd, 0x53, 0x38, 0x27, 0xbb, 0xd0, 0xb7, - 0x00, 0x00, 0x80, 0x3f, 0xcb, 0xe6, 0x54, 0x38, 0xbe, 0x5a, 0xda, 0xb7, 0x00, 0x00, 0x80, 0x3f, - 0x3f, 0xd4, 0x2e, 0x3f, 0x59, 0x4e, 0x21, 0x3f, 0xce, 0x4c, 0x3c, 0x3f, 0xa7, 0x43, 0x24, 0x3f, - 0xb0, 0x61, 0x2a, 0x3f, 0xf4, 0x59, 0x39, 0x3f, 0x6a, 0x1c, 0x24, 0x3f, 0xff, 0x9b, 0x23, 0x3f, - 0x6c, 0xb5, 0xa3, 0x3e, 0xc6, 0xa0, 0x35, 0x3f, 0xcb, 0x3e, 0x70, 0x3e, 0x2b, 0xa6, 0x27, 0x3f, - 0x9d, 0xf8, 0x90, 0x3e, 0x86, 0x70, 0x24, 0x3f, 0x24, 0xf3, 0x3e, 0x3e, 0x4a, 0x5c, 0x2c, 0x3f, - 0xac, 0x07, 0x9c, 0x3e, 0x3a, 0xf0, 0x01, 0x3f, 0xfd, 0xb7, 0x6c, 0x3e, 0xf6, 0x75, 0x27, 0x3f, - 0xe8, 0x6c, 0x6f, 0x3e, 0xe6, 0x43, 0x27, 0x3f, 0xac, 0x1d, 0x0d, 0x3e, 0xb8, 0x42, 0x01, 0x3f, - 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05, 0x06, 0x05, 0x04, 0x06, - 0x06, 0x05, 0x06, 0x07, 0x07, 0x06, 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e, - 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16, 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, - 0x1b, 0x23, 0x1c, 0x16, 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29, 0x19, 0x1f, - 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29, 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, - 0x13, 0x0a, 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, - 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, - 0x20, 0x00, 0x40, 0x03, 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x01, - 0xa2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, - 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, - 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, - 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, - 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, - 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, - 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, - 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, - 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, - 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, - 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, - 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 0x00, - 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13, - 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, - 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, - 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, - 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, - 0xfa, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0xf9, - 0x52, 0x80, 0x0a, 0x00, 0x5a, 0x2e, 0x01, 0x45, 0xc0, 0x28, 0x00, 0xa0, 0x61, 0x45, 0xc4, 0x25, - 0x00, 0x7d, 0xb5, 0x51, 0x72, 0xec, 0x6a, 0xe8, 0x9d, 0x3f, 0xed, 0xaf, 0xf4, 0xa2, 0xe1, 0x62, - 0x5b, 0x8f, 0xf5, 0xa6, 0xa6, 0xe2, 0xb1, 0x1d, 0x17, 0x0b, 0x1e, 0x73, 0x5d, 0x0d, 0x18, 0xa6, - 0x74, 0x96, 0xff, 0x00, 0xbe, 0xb2, 0x8a, 0x7e, 0x9e, 0x61, 0x23, 0x1e, 0x98, 0xac, 0x99, 0x69, - 0x92, 0x54, 0x26, 0x33, 0xe2, 0xea, 0xd5, 0x01, 0xf5, 0x9d, 0xe7, 0x88, 0xd6, 0xd6, 0x31, 0x05, - 0xac, 0x5e, 0x64, 0xaa, 0x00, 0x2c, 0xdd, 0x01, 0x18, 0xed, 0xdf, 0xbf, 0xa5, 0x30, 0x73, 0x33, - 0xb4, 0xfb, 0x8d, 0x5a, 0xea, 0x5c, 0xc5, 0x7f, 0x71, 0x1e, 0xf6, 0x27, 0xfd, 0x73, 0xa0, 0xcf, - 0xe1, 0x41, 0x0e, 0x46, 0xed, 0xb5, 0x9e, 0xb2, 0xaa, 0x82, 0x6d, 0x6a, 0x5e, 0x0f, 0xcc, 0x02, - 0xef, 0x38, 0xcf, 0xf7, 0xcf, 0x35, 0x0c, 0xb3, 0x40, 0x2b, 0xa2, 0x81, 0x35, 0xc4, 0xb7, 0x07, - 0x39, 0xcc, 0xa4, 0x64, 0x7e, 0x40, 0x54, 0xb0, 0x39, 0xa4, 0x56, 0x91, 0xf6, 0xa0, 0x24, 0x9e, - 0xc0, 0x56, 0xad, 0x92, 0x91, 0xd2, 0xdb, 0x27, 0x93, 0xa7, 0xdb, 0xc2, 0xe4, 0x79, 0x83, 0x24, - 0xe3, 0xb6, 0x6b, 0x26, 0x50, 0xea, 0x48, 0x0f, 0x8b, 0xab, 0x54, 0x07, 0xd2, 0x31, 0xc5, 0x1b, - 0x4b, 0x99, 0x1b, 0x09, 0xe9, 0xeb, 0x4c, 0xca, 0xc7, 0x41, 0xa7, 0x8f, 0x2e, 0xee, 0x2c, 0xe1, - 0x10, 0x7e, 0x43, 0x8a, 0x0a, 0x51, 0x3a, 0x5a, 0x86, 0x58, 0x54, 0xb0, 0x23, 0x8e, 0x34, 0x8f, - 0x25, 0x14, 0x02, 0xe7, 0x24, 0xfa, 0xd1, 0x70, 0x12, 0x4e, 0x4f, 0x14, 0xca, 0x48, 0x2a, 0x51, - 0x27, 0xc5, 0xd5, 0xaa, 0x03, 0xff, 0xd9, 0x00, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, - 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x3b, 0x0a, - 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x3b, - 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, - 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, - 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x5f, 0x62, 0x61, 0x74, 0x63, 0x68, 0x69, - 0x64, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, - 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x6f, 0x69, - 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x28, 0x76, 0x6f, 0x69, 0x64, 0x29, 0x0a, 0x7b, 0x20, 0x20, - 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, - 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, - 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x20, 0x3d, 0x20, 0x75, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, - 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x2a, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, - 0x69, 0x65, 0x77, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x20, 0x2a, 0x20, 0x76, 0x65, 0x63, 0x34, - 0x28, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x31, 0x2e, 0x30, - 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x70, 0x72, 0x65, 0x63, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3b, 0x0a, - 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x76, 0x65, 0x63, 0x32, 0x20, 0x76, 0x5f, 0x74, - 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, - 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x75, 0x5f, 0x64, 0x69, - 0x66, 0x66, 0x75, 0x73, 0x65, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, - 0x28, 0x76, 0x6f, 0x69, 0x64, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, - 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, - 0x65, 0x32, 0x44, 0x28, 0x75, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x75, 0x73, 0x65, 0x2c, 0x20, 0x76, - 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x29, 0x3b, 0x0a, 0x7d, 0x0a, 0x00, + 0x62, + 0x33, + 0x64, + 0x6d, + 0x01, + 0x00, + 0x00, + 0x00, + 0x90, + 0x10, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x42, + 0x41, + 0x54, + 0x43, + 0x48, + 0x5f, + 0x4c, + 0x45, + 0x4e, + 0x47, + 0x54, + 0x48, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x20, + 0x20, + 0x7b, + 0x22, + 0x62, + 0x61, + 0x74, + 0x63, + 0x68, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x6e, + 0x61, + 0x6d, + 0x65, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x30, + 0x22, + 0x5d, + 0x7d, + 0x20, + 0x20, + 0x20, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x10, + 0x00, + 0x00, + 0xe8, + 0x08, + 0x00, + 0x00, + 0x4a, + 0x53, + 0x4f, + 0x4e, + 0x7b, + 0x22, + 0x61, + 0x63, + 0x63, + 0x65, + 0x73, + 0x73, + 0x6f, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x6d, + 0x70, + 0x6f, + 0x6e, + 0x65, + 0x6e, + 0x74, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x35, + 0x31, + 0x32, + 0x35, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x30, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x31, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x53, + 0x43, + 0x41, + 0x4c, + 0x41, + 0x52, + 0x22, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x6d, + 0x70, + 0x6f, + 0x6e, + 0x65, + 0x6e, + 0x74, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x35, + 0x31, + 0x32, + 0x36, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x33, + 0x32, + 0x39, + 0x2e, + 0x36, + 0x38, + 0x36, + 0x33, + 0x30, + 0x39, + 0x38, + 0x31, + 0x34, + 0x34, + 0x35, + 0x33, + 0x2c, + 0x2d, + 0x31, + 0x35, + 0x39, + 0x2e, + 0x36, + 0x31, + 0x37, + 0x32, + 0x36, + 0x33, + 0x37, + 0x39, + 0x33, + 0x39, + 0x34, + 0x35, + 0x2c, + 0x31, + 0x34, + 0x2e, + 0x35, + 0x36, + 0x38, + 0x36, + 0x35, + 0x31, + 0x31, + 0x39, + 0x39, + 0x33, + 0x34, + 0x30, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x33, + 0x31, + 0x39, + 0x2e, + 0x38, + 0x32, + 0x39, + 0x38, + 0x30, + 0x33, + 0x34, + 0x36, + 0x36, + 0x37, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x31, + 0x37, + 0x35, + 0x2e, + 0x38, + 0x37, + 0x35, + 0x30, + 0x34, + 0x35, + 0x37, + 0x37, + 0x36, + 0x33, + 0x36, + 0x37, + 0x2c, + 0x31, + 0x31, + 0x2e, + 0x35, + 0x35, + 0x39, + 0x31, + 0x31, + 0x30, + 0x36, + 0x34, + 0x31, + 0x34, + 0x37, + 0x39, + 0x35, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x56, + 0x45, + 0x43, + 0x33, + 0x22, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x6d, + 0x70, + 0x6f, + 0x6e, + 0x65, + 0x6e, + 0x74, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x35, + 0x31, + 0x32, + 0x36, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x35, + 0x2e, + 0x30, + 0x37, + 0x35, + 0x39, + 0x36, + 0x38, + 0x31, + 0x34, + 0x37, + 0x31, + 0x33, + 0x39, + 0x30, + 0x36, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x34, + 0x32, + 0x33, + 0x34, + 0x39, + 0x32, + 0x35, + 0x35, + 0x30, + 0x38, + 0x34, + 0x39, + 0x39, + 0x31, + 0x35, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x30, + 0x2e, + 0x39, + 0x36, + 0x36, + 0x30, + 0x34, + 0x37, + 0x33, + 0x34, + 0x36, + 0x35, + 0x39, + 0x31, + 0x39, + 0x34, + 0x39, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x38, + 0x34, + 0x31, + 0x39, + 0x34, + 0x39, + 0x33, + 0x34, + 0x33, + 0x36, + 0x38, + 0x31, + 0x33, + 0x33, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x39, + 0x39, + 0x30, + 0x32, + 0x37, + 0x36, + 0x33, + 0x33, + 0x36, + 0x36, + 0x36, + 0x39, + 0x39, + 0x32, + 0x32, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x56, + 0x45, + 0x43, + 0x33, + 0x22, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x6d, + 0x70, + 0x6f, + 0x6e, + 0x65, + 0x6e, + 0x74, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x35, + 0x31, + 0x32, + 0x36, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x37, + 0x33, + 0x35, + 0x35, + 0x34, + 0x36, + 0x39, + 0x34, + 0x36, + 0x35, + 0x32, + 0x35, + 0x35, + 0x37, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x37, + 0x32, + 0x34, + 0x30, + 0x32, + 0x38, + 0x38, + 0x32, + 0x35, + 0x37, + 0x35, + 0x39, + 0x38, + 0x38, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x31, + 0x33, + 0x37, + 0x38, + 0x30, + 0x38, + 0x35, + 0x30, + 0x31, + 0x37, + 0x32, + 0x30, + 0x34, + 0x32, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x35, + 0x30, + 0x34, + 0x39, + 0x32, + 0x34, + 0x32, + 0x39, + 0x37, + 0x33, + 0x33, + 0x32, + 0x37, + 0x36, + 0x34, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x56, + 0x45, + 0x43, + 0x32, + 0x22, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x61, + 0x73, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x67, + 0x65, + 0x6e, + 0x65, + 0x72, + 0x61, + 0x74, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x66, + 0x61, + 0x6e, + 0x66, + 0x61, + 0x6e, + 0x22, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x22, + 0x3a, + 0x22, + 0x32, + 0x2e, + 0x30, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x33, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x30, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x32, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x32, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x30, + 0x38, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x32, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x33, + 0x33, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x36, + 0x30, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x32, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x31, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x74, + 0x61, + 0x72, + 0x67, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x39, + 0x36, + 0x32, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x38, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x73, + 0x5f, + 0x77, + 0x65, + 0x62, + 0x67, + 0x6c, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x6f, + 0x67, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x61, + 0x5f, + 0x70, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x22, + 0x2c, + 0x22, + 0x61, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x66, + 0x72, + 0x61, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x53, + 0x68, + 0x61, + 0x64, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x53, + 0x68, + 0x61, + 0x64, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x73, + 0x68, + 0x61, + 0x64, + 0x65, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x35, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x33, + 0x33, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x61, + 0x5f, + 0x62, + 0x61, + 0x74, + 0x63, + 0x68, + 0x69, + 0x64, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x6d, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x63, + 0x22, + 0x3a, + 0x22, + 0x5f, + 0x42, + 0x41, + 0x54, + 0x43, + 0x48, + 0x49, + 0x44, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x35, + 0x31, + 0x32, + 0x33, + 0x7d, + 0x2c, + 0x22, + 0x61, + 0x5f, + 0x70, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x6d, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x63, + 0x22, + 0x3a, + 0x22, + 0x50, + 0x4f, + 0x53, + 0x49, + 0x54, + 0x49, + 0x4f, + 0x4e, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x36, + 0x35, + 0x7d, + 0x2c, + 0x22, + 0x61, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x6d, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x63, + 0x22, + 0x3a, + 0x22, + 0x54, + 0x45, + 0x58, + 0x43, + 0x4f, + 0x4f, + 0x52, + 0x44, + 0x5f, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x36, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x6f, + 0x67, + 0x72, + 0x61, + 0x6d, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x73, + 0x74, + 0x61, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x61, + 0x62, + 0x6c, + 0x65, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x38, + 0x38, + 0x34, + 0x2c, + 0x32, + 0x39, + 0x32, + 0x39, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x75, + 0x5f, + 0x64, + 0x69, + 0x66, + 0x66, + 0x75, + 0x73, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x37, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x5f, + 0x6d, + 0x6f, + 0x64, + 0x65, + 0x6c, + 0x56, + 0x69, + 0x65, + 0x77, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x6d, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x63, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x4f, + 0x44, + 0x45, + 0x4c, + 0x56, + 0x49, + 0x45, + 0x57, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x37, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x5f, + 0x70, + 0x72, + 0x6f, + 0x6a, + 0x65, + 0x63, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x6d, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x63, + 0x22, + 0x3a, + 0x22, + 0x50, + 0x52, + 0x4f, + 0x4a, + 0x45, + 0x43, + 0x54, + 0x49, + 0x4f, + 0x4e, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x33, + 0x35, + 0x36, + 0x37, + 0x36, + 0x7d, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x52, + 0x65, + 0x71, + 0x75, + 0x69, + 0x72, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x73, + 0x5f, + 0x77, + 0x65, + 0x62, + 0x67, + 0x6c, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x73, + 0x5f, + 0x77, + 0x65, + 0x62, + 0x67, + 0x6c, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x69, + 0x6d, + 0x61, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6d, + 0x65, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x69, + 0x6d, + 0x61, + 0x67, + 0x65, + 0x2f, + 0x6a, + 0x70, + 0x65, + 0x67, + 0x22, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x73, + 0x5f, + 0x77, + 0x65, + 0x62, + 0x67, + 0x6c, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x74, + 0x65, + 0x63, + 0x68, + 0x6e, + 0x69, + 0x71, + 0x75, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x61, + 0x6c, + 0x75, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x75, + 0x5f, + 0x64, + 0x69, + 0x66, + 0x66, + 0x75, + 0x73, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x74, + 0x65, + 0x78, + 0x43, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x7d, + 0x7d, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x4f, + 0x52, + 0x4d, + 0x41, + 0x4c, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x50, + 0x4f, + 0x53, + 0x49, + 0x54, + 0x49, + 0x4f, + 0x4e, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x54, + 0x45, + 0x58, + 0x43, + 0x4f, + 0x4f, + 0x52, + 0x44, + 0x5f, + 0x30, + 0x22, + 0x3a, + 0x33, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6d, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x3a, + 0x34, + 0x7d, + 0x5d, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6e, + 0x61, + 0x6d, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x22, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x73, + 0x61, + 0x6d, + 0x70, + 0x6c, + 0x65, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x6d, + 0x61, + 0x67, + 0x46, + 0x69, + 0x6c, + 0x74, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x39, + 0x37, + 0x32, + 0x39, + 0x2c, + 0x22, + 0x6d, + 0x69, + 0x6e, + 0x46, + 0x69, + 0x6c, + 0x74, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x39, + 0x39, + 0x38, + 0x36, + 0x2c, + 0x22, + 0x77, + 0x72, + 0x61, + 0x70, + 0x53, + 0x22, + 0x3a, + 0x31, + 0x30, + 0x34, + 0x39, + 0x37, + 0x2c, + 0x22, + 0x77, + 0x72, + 0x61, + 0x70, + 0x54, + 0x22, + 0x3a, + 0x31, + 0x30, + 0x34, + 0x39, + 0x37, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x5d, + 0x7d, + 0x5d, + 0x2c, + 0x22, + 0x74, + 0x65, + 0x78, + 0x74, + 0x75, + 0x72, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x73, + 0x61, + 0x6d, + 0x70, + 0x6c, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x73, + 0x6f, + 0x75, + 0x72, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x5d, + 0x7d, + 0x20, + 0x20, + 0x38, + 0x07, + 0x00, + 0x00, + 0x42, + 0x49, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x63, + 0xa2, + 0x43, + 0x44, + 0xd3, + 0x2d, + 0xc3, + 0x1e, + 0xf3, + 0x38, + 0x41, + 0xa8, + 0x38, + 0xa4, + 0x43, + 0x03, + 0xe0, + 0x2f, + 0xc3, + 0x1e, + 0xf2, + 0x38, + 0x41, + 0x51, + 0x40, + 0xa2, + 0x43, + 0xb1, + 0xba, + 0x2c, + 0xc3, + 0x32, + 0x19, + 0x69, + 0x41, + 0xaa, + 0xbb, + 0xa2, + 0x43, + 0xe1, + 0x94, + 0x2a, + 0xc3, + 0x55, + 0xf3, + 0x38, + 0x41, + 0x51, + 0x40, + 0xa2, + 0x43, + 0xb1, + 0xba, + 0x2c, + 0xc3, + 0x32, + 0x19, + 0x69, + 0x41, + 0xc6, + 0xbc, + 0xa3, + 0x43, + 0x56, + 0x27, + 0x28, + 0xc3, + 0x2d, + 0xf3, + 0x38, + 0x41, + 0xaa, + 0xbb, + 0xa2, + 0x43, + 0xe1, + 0x94, + 0x2a, + 0xc3, + 0x55, + 0xf3, + 0x38, + 0x41, + 0xd9, + 0xd7, + 0xa4, + 0x43, + 0x11, + 0xdf, + 0x25, + 0xc3, + 0xf5, + 0xf2, + 0x38, + 0x41, + 0x37, + 0xea, + 0x9f, + 0x43, + 0x53, + 0xef, + 0x28, + 0xc3, + 0xae, + 0xf4, + 0x38, + 0x41, + 0x62, + 0xc7, + 0xa3, + 0x43, + 0x73, + 0xf2, + 0x27, + 0xc3, + 0x2e, + 0xf3, + 0x38, + 0x41, + 0x00, + 0xb9, + 0xa3, + 0x43, + 0xdc, + 0x13, + 0x28, + 0xc3, + 0x31, + 0xf3, + 0x38, + 0x41, + 0x88, + 0x87, + 0xa2, + 0x43, + 0x05, + 0x9e, + 0x1f, + 0xc3, + 0x96, + 0xf4, + 0x38, + 0x41, + 0xa4, + 0x0b, + 0x5e, + 0xbf, + 0x83, + 0xb6, + 0xf9, + 0xbe, + 0x00, + 0xcf, + 0xca, + 0x3d, + 0x38, + 0xed, + 0xf0, + 0xbe, + 0xfe, + 0x89, + 0x57, + 0xbf, + 0xad, + 0x2a, + 0x87, + 0x3e, + 0xe1, + 0x4e, + 0x77, + 0xbf, + 0x24, + 0xf5, + 0xf5, + 0x3d, + 0x0a, + 0x3f, + 0x6a, + 0x3e, + 0x58, + 0x66, + 0x2a, + 0xbf, + 0x43, + 0x37, + 0xa2, + 0x3e, + 0x63, + 0xfa, + 0x2c, + 0x3f, + 0xe1, + 0x4e, + 0x77, + 0xbf, + 0x24, + 0xf5, + 0xf5, + 0x3d, + 0x0a, + 0x3f, + 0x6a, + 0x3e, + 0x16, + 0xff, + 0xf1, + 0xbe, + 0x04, + 0xd4, + 0xd8, + 0x3e, + 0xc8, + 0xd7, + 0x45, + 0x3f, + 0x58, + 0x66, + 0x2a, + 0xbf, + 0x43, + 0x37, + 0xa2, + 0x3e, + 0x63, + 0xfa, + 0x2c, + 0x3f, + 0xc1, + 0xc5, + 0x95, + 0xbd, + 0xae, + 0x2c, + 0x91, + 0x3d, + 0x36, + 0xab, + 0x7e, + 0x3f, + 0x12, + 0xd0, + 0x54, + 0x38, + 0xbf, + 0x3c, + 0xda, + 0xb7, + 0x00, + 0x00, + 0x80, + 0x3f, + 0x65, + 0x57, + 0x54, + 0x38, + 0x18, + 0xd8, + 0xd5, + 0xb7, + 0x00, + 0x00, + 0x80, + 0x3f, + 0xd7, + 0xdd, + 0x53, + 0x38, + 0x27, + 0xbb, + 0xd0, + 0xb7, + 0x00, + 0x00, + 0x80, + 0x3f, + 0xcb, + 0xe6, + 0x54, + 0x38, + 0xbe, + 0x5a, + 0xda, + 0xb7, + 0x00, + 0x00, + 0x80, + 0x3f, + 0x3f, + 0xd4, + 0x2e, + 0x3f, + 0x59, + 0x4e, + 0x21, + 0x3f, + 0xce, + 0x4c, + 0x3c, + 0x3f, + 0xa7, + 0x43, + 0x24, + 0x3f, + 0xb0, + 0x61, + 0x2a, + 0x3f, + 0xf4, + 0x59, + 0x39, + 0x3f, + 0x6a, + 0x1c, + 0x24, + 0x3f, + 0xff, + 0x9b, + 0x23, + 0x3f, + 0x6c, + 0xb5, + 0xa3, + 0x3e, + 0xc6, + 0xa0, + 0x35, + 0x3f, + 0xcb, + 0x3e, + 0x70, + 0x3e, + 0x2b, + 0xa6, + 0x27, + 0x3f, + 0x9d, + 0xf8, + 0x90, + 0x3e, + 0x86, + 0x70, + 0x24, + 0x3f, + 0x24, + 0xf3, + 0x3e, + 0x3e, + 0x4a, + 0x5c, + 0x2c, + 0x3f, + 0xac, + 0x07, + 0x9c, + 0x3e, + 0x3a, + 0xf0, + 0x01, + 0x3f, + 0xfd, + 0xb7, + 0x6c, + 0x3e, + 0xf6, + 0x75, + 0x27, + 0x3f, + 0xe8, + 0x6c, + 0x6f, + 0x3e, + 0xe6, + 0x43, + 0x27, + 0x3f, + 0xac, + 0x1d, + 0x0d, + 0x3e, + 0xb8, + 0x42, + 0x01, + 0x3f, + 0xff, + 0xd8, + 0xff, + 0xe0, + 0x00, + 0x10, + 0x4a, + 0x46, + 0x49, + 0x46, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x00, + 0xff, + 0xdb, + 0x00, + 0x84, + 0x00, + 0x06, + 0x04, + 0x05, + 0x06, + 0x05, + 0x04, + 0x06, + 0x06, + 0x05, + 0x06, + 0x07, + 0x07, + 0x06, + 0x08, + 0x0a, + 0x10, + 0x0a, + 0x0a, + 0x09, + 0x09, + 0x0a, + 0x14, + 0x0e, + 0x0f, + 0x0c, + 0x10, + 0x17, + 0x14, + 0x18, + 0x18, + 0x17, + 0x14, + 0x16, + 0x16, + 0x1a, + 0x1d, + 0x25, + 0x1f, + 0x1a, + 0x1b, + 0x23, + 0x1c, + 0x16, + 0x16, + 0x20, + 0x2c, + 0x20, + 0x23, + 0x26, + 0x27, + 0x29, + 0x2a, + 0x29, + 0x19, + 0x1f, + 0x2d, + 0x30, + 0x2d, + 0x28, + 0x30, + 0x25, + 0x28, + 0x29, + 0x28, + 0x01, + 0x07, + 0x07, + 0x07, + 0x0a, + 0x08, + 0x0a, + 0x13, + 0x0a, + 0x0a, + 0x13, + 0x28, + 0x1a, + 0x16, + 0x1a, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0x28, + 0xff, + 0xc0, + 0x00, + 0x11, + 0x08, + 0x00, + 0x20, + 0x00, + 0x40, + 0x03, + 0x01, + 0x11, + 0x00, + 0x02, + 0x11, + 0x01, + 0x03, + 0x11, + 0x01, + 0xff, + 0xc4, + 0x01, + 0xa2, + 0x00, + 0x00, + 0x01, + 0x05, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0a, + 0x0b, + 0x10, + 0x00, + 0x02, + 0x01, + 0x03, + 0x03, + 0x02, + 0x04, + 0x03, + 0x05, + 0x05, + 0x04, + 0x04, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x01, + 0x02, + 0x03, + 0x00, + 0x04, + 0x11, + 0x05, + 0x12, + 0x21, + 0x31, + 0x41, + 0x06, + 0x13, + 0x51, + 0x61, + 0x07, + 0x22, + 0x71, + 0x14, + 0x32, + 0x81, + 0x91, + 0xa1, + 0x08, + 0x23, + 0x42, + 0xb1, + 0xc1, + 0x15, + 0x52, + 0xd1, + 0xf0, + 0x24, + 0x33, + 0x62, + 0x72, + 0x82, + 0x09, + 0x0a, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1a, + 0x25, + 0x26, + 0x27, + 0x28, + 0x29, + 0x2a, + 0x34, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x3a, + 0x43, + 0x44, + 0x45, + 0x46, + 0x47, + 0x48, + 0x49, + 0x4a, + 0x53, + 0x54, + 0x55, + 0x56, + 0x57, + 0x58, + 0x59, + 0x5a, + 0x63, + 0x64, + 0x65, + 0x66, + 0x67, + 0x68, + 0x69, + 0x6a, + 0x73, + 0x74, + 0x75, + 0x76, + 0x77, + 0x78, + 0x79, + 0x7a, + 0x83, + 0x84, + 0x85, + 0x86, + 0x87, + 0x88, + 0x89, + 0x8a, + 0x92, + 0x93, + 0x94, + 0x95, + 0x96, + 0x97, + 0x98, + 0x99, + 0x9a, + 0xa2, + 0xa3, + 0xa4, + 0xa5, + 0xa6, + 0xa7, + 0xa8, + 0xa9, + 0xaa, + 0xb2, + 0xb3, + 0xb4, + 0xb5, + 0xb6, + 0xb7, + 0xb8, + 0xb9, + 0xba, + 0xc2, + 0xc3, + 0xc4, + 0xc5, + 0xc6, + 0xc7, + 0xc8, + 0xc9, + 0xca, + 0xd2, + 0xd3, + 0xd4, + 0xd5, + 0xd6, + 0xd7, + 0xd8, + 0xd9, + 0xda, + 0xe1, + 0xe2, + 0xe3, + 0xe4, + 0xe5, + 0xe6, + 0xe7, + 0xe8, + 0xe9, + 0xea, + 0xf1, + 0xf2, + 0xf3, + 0xf4, + 0xf5, + 0xf6, + 0xf7, + 0xf8, + 0xf9, + 0xfa, + 0x01, + 0x00, + 0x03, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0a, + 0x0b, + 0x11, + 0x00, + 0x02, + 0x01, + 0x02, + 0x04, + 0x04, + 0x03, + 0x04, + 0x07, + 0x05, + 0x04, + 0x04, + 0x00, + 0x01, + 0x02, + 0x77, + 0x00, + 0x01, + 0x02, + 0x03, + 0x11, + 0x04, + 0x05, + 0x21, + 0x31, + 0x06, + 0x12, + 0x41, + 0x51, + 0x07, + 0x61, + 0x71, + 0x13, + 0x22, + 0x32, + 0x81, + 0x08, + 0x14, + 0x42, + 0x91, + 0xa1, + 0xb1, + 0xc1, + 0x09, + 0x23, + 0x33, + 0x52, + 0xf0, + 0x15, + 0x62, + 0x72, + 0xd1, + 0x0a, + 0x16, + 0x24, + 0x34, + 0xe1, + 0x25, + 0xf1, + 0x17, + 0x18, + 0x19, + 0x1a, + 0x26, + 0x27, + 0x28, + 0x29, + 0x2a, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x3a, + 0x43, + 0x44, + 0x45, + 0x46, + 0x47, + 0x48, + 0x49, + 0x4a, + 0x53, + 0x54, + 0x55, + 0x56, + 0x57, + 0x58, + 0x59, + 0x5a, + 0x63, + 0x64, + 0x65, + 0x66, + 0x67, + 0x68, + 0x69, + 0x6a, + 0x73, + 0x74, + 0x75, + 0x76, + 0x77, + 0x78, + 0x79, + 0x7a, + 0x82, + 0x83, + 0x84, + 0x85, + 0x86, + 0x87, + 0x88, + 0x89, + 0x8a, + 0x92, + 0x93, + 0x94, + 0x95, + 0x96, + 0x97, + 0x98, + 0x99, + 0x9a, + 0xa2, + 0xa3, + 0xa4, + 0xa5, + 0xa6, + 0xa7, + 0xa8, + 0xa9, + 0xaa, + 0xb2, + 0xb3, + 0xb4, + 0xb5, + 0xb6, + 0xb7, + 0xb8, + 0xb9, + 0xba, + 0xc2, + 0xc3, + 0xc4, + 0xc5, + 0xc6, + 0xc7, + 0xc8, + 0xc9, + 0xca, + 0xd2, + 0xd3, + 0xd4, + 0xd5, + 0xd6, + 0xd7, + 0xd8, + 0xd9, + 0xda, + 0xe2, + 0xe3, + 0xe4, + 0xe5, + 0xe6, + 0xe7, + 0xe8, + 0xe9, + 0xea, + 0xf2, + 0xf3, + 0xf4, + 0xf5, + 0xf6, + 0xf7, + 0xf8, + 0xf9, + 0xfa, + 0xff, + 0xda, + 0x00, + 0x0c, + 0x03, + 0x01, + 0x00, + 0x02, + 0x11, + 0x03, + 0x11, + 0x00, + 0x3f, + 0x00, + 0xf9, + 0x52, + 0x80, + 0x0a, + 0x00, + 0x5a, + 0x2e, + 0x01, + 0x45, + 0xc0, + 0x28, + 0x00, + 0xa0, + 0x61, + 0x45, + 0xc4, + 0x25, + 0x00, + 0x7d, + 0xb5, + 0x51, + 0x72, + 0xec, + 0x6a, + 0xe8, + 0x9d, + 0x3f, + 0xed, + 0xaf, + 0xf4, + 0xa2, + 0xe1, + 0x62, + 0x5b, + 0x8f, + 0xf5, + 0xa6, + 0xa6, + 0xe2, + 0xb1, + 0x1d, + 0x17, + 0x0b, + 0x1e, + 0x73, + 0x5d, + 0x0d, + 0x18, + 0xa6, + 0x74, + 0x96, + 0xff, + 0x00, + 0xbe, + 0xb2, + 0x8a, + 0x7e, + 0x9e, + 0x61, + 0x23, + 0x1e, + 0x98, + 0xac, + 0x99, + 0x69, + 0x92, + 0x54, + 0x26, + 0x33, + 0xe2, + 0xea, + 0xd5, + 0x01, + 0xf5, + 0x9d, + 0xe7, + 0x88, + 0xd6, + 0xd6, + 0x31, + 0x05, + 0xac, + 0x5e, + 0x64, + 0xaa, + 0x00, + 0x2c, + 0xdd, + 0x01, + 0x18, + 0xed, + 0xdf, + 0xbf, + 0xa5, + 0x30, + 0x73, + 0x33, + 0xb4, + 0xfb, + 0x8d, + 0x5a, + 0xea, + 0x5c, + 0xc5, + 0x7f, + 0x71, + 0x1e, + 0xf6, + 0x27, + 0xfd, + 0x73, + 0xa0, + 0xcf, + 0xe1, + 0x41, + 0x0e, + 0x46, + 0xed, + 0xb5, + 0x9e, + 0xb2, + 0xaa, + 0x82, + 0x6d, + 0x6a, + 0x5e, + 0x0f, + 0xcc, + 0x02, + 0xef, + 0x38, + 0xcf, + 0xf7, + 0xcf, + 0x35, + 0x0c, + 0xb3, + 0x40, + 0x2b, + 0xa2, + 0x81, + 0x35, + 0xc4, + 0xb7, + 0x07, + 0x39, + 0xcc, + 0xa4, + 0x64, + 0x7e, + 0x40, + 0x54, + 0xb0, + 0x39, + 0xa4, + 0x56, + 0x91, + 0xf6, + 0xa0, + 0x24, + 0x9e, + 0xc0, + 0x56, + 0xad, + 0x92, + 0x91, + 0xd2, + 0xdb, + 0x27, + 0x93, + 0xa7, + 0xdb, + 0xc2, + 0xe4, + 0x79, + 0x83, + 0x24, + 0xe3, + 0xb6, + 0x6b, + 0x26, + 0x50, + 0xea, + 0x48, + 0x0f, + 0x8b, + 0xab, + 0x54, + 0x07, + 0xd2, + 0x31, + 0xc5, + 0x1b, + 0x4b, + 0x99, + 0x1b, + 0x09, + 0xe9, + 0xeb, + 0x4c, + 0xca, + 0xc7, + 0x41, + 0xa7, + 0x8f, + 0x2e, + 0xee, + 0x2c, + 0xe1, + 0x10, + 0x7e, + 0x43, + 0x8a, + 0x0a, + 0x51, + 0x3a, + 0x5a, + 0x86, + 0x58, + 0x54, + 0xb0, + 0x23, + 0x8e, + 0x34, + 0x8f, + 0x25, + 0x14, + 0x02, + 0xe7, + 0x24, + 0xfa, + 0xd1, + 0x70, + 0x12, + 0x4e, + 0x4f, + 0x14, + 0xca, + 0x48, + 0x2a, + 0x51, + 0x27, + 0xc5, + 0xd5, + 0xaa, + 0x03, + 0xff, + 0xd9, + 0x00, + 0x0a, + 0x70, + 0x72, + 0x65, + 0x63, + 0x69, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x20, + 0x68, + 0x69, + 0x67, + 0x68, + 0x70, + 0x20, + 0x66, + 0x6c, + 0x6f, + 0x61, + 0x74, + 0x3b, + 0x0a, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x20, + 0x6d, + 0x61, + 0x74, + 0x34, + 0x20, + 0x75, + 0x5f, + 0x6d, + 0x6f, + 0x64, + 0x65, + 0x6c, + 0x56, + 0x69, + 0x65, + 0x77, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x3b, + 0x0a, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x20, + 0x6d, + 0x61, + 0x74, + 0x34, + 0x20, + 0x75, + 0x5f, + 0x70, + 0x72, + 0x6f, + 0x6a, + 0x65, + 0x63, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x3b, + 0x0a, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x20, + 0x76, + 0x65, + 0x63, + 0x33, + 0x20, + 0x61, + 0x5f, + 0x70, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x3b, + 0x0a, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x20, + 0x76, + 0x65, + 0x63, + 0x32, + 0x20, + 0x61, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x3b, + 0x0a, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x20, + 0x66, + 0x6c, + 0x6f, + 0x61, + 0x74, + 0x20, + 0x61, + 0x5f, + 0x62, + 0x61, + 0x74, + 0x63, + 0x68, + 0x69, + 0x64, + 0x3b, + 0x0a, + 0x76, + 0x61, + 0x72, + 0x79, + 0x69, + 0x6e, + 0x67, + 0x20, + 0x76, + 0x65, + 0x63, + 0x32, + 0x20, + 0x76, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x3b, + 0x0a, + 0x76, + 0x6f, + 0x69, + 0x64, + 0x20, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x28, + 0x76, + 0x6f, + 0x69, + 0x64, + 0x29, + 0x0a, + 0x7b, + 0x20, + 0x20, + 0x20, + 0x0a, + 0x20, + 0x20, + 0x20, + 0x20, + 0x76, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x20, + 0x3d, + 0x20, + 0x61, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x3b, + 0x0a, + 0x20, + 0x20, + 0x20, + 0x20, + 0x67, + 0x6c, + 0x5f, + 0x50, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x20, + 0x3d, + 0x20, + 0x75, + 0x5f, + 0x70, + 0x72, + 0x6f, + 0x6a, + 0x65, + 0x63, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x20, + 0x2a, + 0x20, + 0x75, + 0x5f, + 0x6d, + 0x6f, + 0x64, + 0x65, + 0x6c, + 0x56, + 0x69, + 0x65, + 0x77, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x20, + 0x2a, + 0x20, + 0x76, + 0x65, + 0x63, + 0x34, + 0x28, + 0x61, + 0x5f, + 0x70, + 0x6f, + 0x73, + 0x69, + 0x74, + 0x69, + 0x6f, + 0x6e, + 0x2c, + 0x20, + 0x31, + 0x2e, + 0x30, + 0x29, + 0x3b, + 0x0a, + 0x7d, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x70, + 0x72, + 0x65, + 0x63, + 0x69, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x20, + 0x68, + 0x69, + 0x67, + 0x68, + 0x70, + 0x20, + 0x66, + 0x6c, + 0x6f, + 0x61, + 0x74, + 0x3b, + 0x0a, + 0x76, + 0x61, + 0x72, + 0x79, + 0x69, + 0x6e, + 0x67, + 0x20, + 0x76, + 0x65, + 0x63, + 0x32, + 0x20, + 0x76, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x3b, + 0x0a, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x20, + 0x73, + 0x61, + 0x6d, + 0x70, + 0x6c, + 0x65, + 0x72, + 0x32, + 0x44, + 0x20, + 0x75, + 0x5f, + 0x64, + 0x69, + 0x66, + 0x66, + 0x75, + 0x73, + 0x65, + 0x3b, + 0x0a, + 0x76, + 0x6f, + 0x69, + 0x64, + 0x20, + 0x6d, + 0x61, + 0x69, + 0x6e, + 0x28, + 0x76, + 0x6f, + 0x69, + 0x64, + 0x29, + 0x0a, + 0x7b, + 0x0a, + 0x20, + 0x20, + 0x67, + 0x6c, + 0x5f, + 0x46, + 0x72, + 0x61, + 0x67, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x20, + 0x3d, + 0x20, + 0x74, + 0x65, + 0x78, + 0x74, + 0x75, + 0x72, + 0x65, + 0x32, + 0x44, + 0x28, + 0x75, + 0x5f, + 0x64, + 0x69, + 0x66, + 0x66, + 0x75, + 0x73, + 0x65, + 0x2c, + 0x20, + 0x76, + 0x5f, + 0x74, + 0x65, + 0x78, + 0x63, + 0x6f, + 0x6f, + 0x72, + 0x64, + 0x30, + 0x29, + 0x3b, + 0x0a, + 0x7d, + 0x0a, + 0x00, ]); describe("B3dmReader", () => { @@ -294,9 +4269,13 @@ describe("B3dmReader", () => { it("should locate texture for mesh", async () => { class Texture extends RenderTexture { - public constructor(type: RenderTexture.Type) { super(type); } - public dispose() { } - public get bytesUsed() { return 0; } + public constructor(type: RenderTexture.Type) { + super(type); + } + public dispose() {} + public get bytesUsed() { + return 0; + } } let textureCreated = false; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/Disposable.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/Disposable.test.ts index bab8b571e543..bec25bb179a3 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/Disposable.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/Disposable.test.ts @@ -2,16 +2,42 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert, expect } from "chai"; import { ByteStream, IDisposable } from "@itwin/core-bentley"; -import { ColorByName, ColorDef, ColorIndex, FeatureIndex, FillFlags, ImageBuffer, ImageBufferFormat, QParams3d, QPoint3dList, RenderTexture } from "@itwin/core-common"; import { - Decorations, GraphicList, GraphicType, ImdlReader, IModelApp, IModelConnection, OffScreenViewport, PlanarClassifierMap, PlanarClassifierTarget, - PlanarClipMaskState, RenderMemory, RenderPlanarClassifier, RenderTextureDrape, SceneContext, ScreenViewport, SnapshotConnection, TextureDrapeMap, + ColorByName, + ColorDef, + ColorIndex, + FeatureIndex, + FillFlags, + ImageBuffer, + ImageBufferFormat, + QParams3d, + QPoint3dList, + RenderTexture, +} from "@itwin/core-common"; +import { + Decorations, + GraphicList, + GraphicType, + ImdlReader, + IModelApp, + IModelConnection, + OffScreenViewport, + PlanarClassifierMap, + PlanarClassifierTarget, + PlanarClipMaskState, + RenderMemory, + RenderPlanarClassifier, + RenderTextureDrape, + SceneContext, + ScreenViewport, + SnapshotConnection, + TextureDrapeMap, TileTreeReference, } from "@itwin/core-frontend"; import { Batch, FrameBuffer, OnScreenTarget, Target, TextureHandle, WorldDecorations } from "@itwin/core-frontend/lib/cjs/webgl"; import { Arc3d, Point3d, Range3d } from "@itwin/core-geometry"; +import { assert, expect } from "chai"; import { TestUtility } from "../../TestUtility"; import { testViewports } from "../../TestViewport"; import { TILE_DATA_1_1 } from "./data/TileIO.data.1.1"; @@ -19,7 +45,7 @@ import { FakeGMState, FakeModelProps, FakeREProps } from "./TileIO.test"; let imodel0: IModelConnection; let imodel1: IModelConnection; -const itemsChecked: object[] = []; // Private helper array for storing what objects have already been checked for disposal in isDisposed() +const itemsChecked: object[] = []; // Private helper array for storing what objects have already been checked for disposal in isDisposed() /** * Class holding a RenderTarget that provides getters for all of a Target's typically private members, as well as members that may be set to undefined when disposing. @@ -32,15 +58,33 @@ class ExposedTarget { this.target = target; } - public get decorations(): Decorations | undefined { return (this.target as any)._decorations; } - public get dynamics(): GraphicList | undefined { return (this.target as any)._dynamics; } - public get worldDecorations(): WorldDecorations | undefined { return (this.target as any)._worldDecorations; } - public get clipMask(): TextureHandle | undefined { return (this.target as any)._clipMask; } - public get environmentMap(): TextureHandle | undefined { return (this.target as any)._environmentMap; } - public get diffuseMap(): TextureHandle | undefined { return (this.target as any)._diffuseMap; } - public get batchesClone(): Batch[] { return (this.target as any)._batches.slice(); } - public get planarClassifiers(): PlanarClassifierMap | undefined { return (this.target as any)._planarClassifiers; } - public get textureDrapes(): TextureDrapeMap | undefined { return (this.target as any)._textureDrapes; } + public get decorations(): Decorations | undefined { + return (this.target as any)._decorations; + } + public get dynamics(): GraphicList | undefined { + return (this.target as any)._dynamics; + } + public get worldDecorations(): WorldDecorations | undefined { + return (this.target as any)._worldDecorations; + } + public get clipMask(): TextureHandle | undefined { + return (this.target as any)._clipMask; + } + public get environmentMap(): TextureHandle | undefined { + return (this.target as any)._environmentMap; + } + public get diffuseMap(): TextureHandle | undefined { + return (this.target as any)._diffuseMap; + } + public get batchesClone(): Batch[] { + return (this.target as any)._batches.slice(); + } + public get planarClassifiers(): PlanarClassifierMap | undefined { + return (this.target as any)._planarClassifiers; + } + public get textureDrapes(): TextureDrapeMap | undefined { + return (this.target as any)._textureDrapes; + } public changePlanarClassifiers(map: PlanarClassifierMap | undefined) { // The real implementation takes sole ownership of the map. Tests like to reuse same map. So clone it. @@ -100,29 +144,29 @@ function disposedCheck(disposable: any, ignoredAttribs?: string[]): boolean { if (disposable === undefined || disposable === null) return true; - if (itemsChecked.indexOf(disposable) === -1) // We want to check matching references (skipping primitive types here is okay, since they can't be disposable) + if (itemsChecked.indexOf(disposable) === -1) // We want to check matching references (skipping primitive types here is okay, since they can't be disposable) itemsChecked.push(disposable); else return true; - if (Array.isArray(disposable)) { // Array + if (Array.isArray(disposable)) { // Array itemsChecked.push(disposable); for (const elem of disposable) if (!disposedCheck(elem)) return false; - } else if (disposable.dispose !== undefined) { // Low-level WebGL resource disposable expect(typeof (disposable.dispose)).to.equal("function"); expect(typeof (disposable.isDisposed)).to.equal("boolean"); return disposable.isDisposed; - } else if (typeof disposable === "object") { // High-level rendering object disposable + } else if (typeof disposable === "object") { // High-level rendering object disposable for (const prop in disposable) { if (disposable.hasOwnProperty(prop) && typeof disposable[prop] === "object") { if (ignoredAttribs !== undefined && ignoredAttribs.indexOf(prop) !== -1) continue; - if (Array.isArray(disposable[prop]) || disposable[prop].dispose !== undefined) + if (Array.isArray(disposable[prop]) || disposable[prop].dispose !== undefined) { if (!disposedCheck(disposable[prop])) return false; + } } } } @@ -198,7 +242,7 @@ describe("Disposal of WebGL Resources", () => { const colors = new ColorIndex(); colors.initUniform(ColorByName.tan); - const points = [new Point3d(0, 0, 0), new Point3d(10, 0, 0), new Point3d(0, 10 ,0)]; + const points = [new Point3d(0, 0, 0), new Point3d(10, 0, 0), new Point3d(0, 10, 0)]; const qpoints = new QPoint3dList(QParams3d.fromRange(Range3d.createArray(points))); for (const point of points) qpoints.add(point); @@ -259,7 +303,7 @@ describe("Disposal of WebGL Resources", () => { expect(vp instanceof ScreenViewport || vp instanceof OffScreenViewport).to.be.true; expect(vp.isDisposed).to.be.false; - const target = (vp.target as any); + const target = vp.target as any; let fbo = target._fbo as FrameBuffer; expect(fbo).to.be.undefined; let blitGeom = target._blitGeom; @@ -294,9 +338,11 @@ describe("Disposal of WebGL Resources", () => { class Classifier extends RenderPlanarClassifier { public disposed = false; - public constructor() { super(); } - public collectGraphics(_context: SceneContext, _target: PlanarClassifierTarget): void { } - public setSource(_classifierTreeRef?: TileTreeReference, _planarClipMask?: PlanarClipMaskState): void { } + public constructor() { + super(); + } + public collectGraphics(_context: SceneContext, _target: PlanarClassifierTarget): void {} + public setSource(_classifierTreeRef?: TileTreeReference, _planarClipMask?: PlanarClipMaskState): void {} public dispose(): void { expect(this.disposed).to.be.false; this.disposed = true; @@ -305,9 +351,11 @@ describe("Disposal of WebGL Resources", () => { class Drape extends RenderTextureDrape { public disposed = false; - public constructor() { super(); } - public collectGraphics(_context: SceneContext): void { } - public collectStatistics(_stats: RenderMemory.Statistics): void { } + public constructor() { + super(); + } + public collectGraphics(_context: SceneContext): void {} + public collectStatistics(_stats: RenderMemory.Statistics): void {} public dispose(): void { expect(this.disposed).to.be.false; this.disposed = true; @@ -402,18 +450,24 @@ describe("Disposal of WebGL Resources", () => { it("should manage lifetimes of planar classifiers", async () => { const map = new Map(); - await testClassifiersOrDrapes(map, "planarClassifiers", + await testClassifiersOrDrapes( + map, + "planarClassifiers", () => new Classifier(), (target, id) => target.target.getPlanarClassifier(id) as Classifier, - (target, newMap) => target.changePlanarClassifiers(newMap)); + (target, newMap) => target.changePlanarClassifiers(newMap), + ); }); it("should manage lifetimes of texture drapes", async () => { const map = new Map(); - await testClassifiersOrDrapes(map, "textureDrapes", + await testClassifiersOrDrapes( + map, + "textureDrapes", () => new Drape(), (target, id) => target.target.getTextureDrape(id) as Drape, - (target, newMap) => target.changeTextureDrapes(newMap)); + (target, newMap) => target.changeTextureDrapes(newMap), + ); }); // NB: This rather wacky test disposes of IModelApp.renderSystem. Therefore it must be run last of all of these tests, or subsequent tests expecting @@ -445,7 +499,11 @@ describe("Disposal of WebGL Resources", () => { // eslint-disable-next-line deprecation/deprecation let texture = system.createTextureFromImageBuffer(ImageBuffer.create(getImageBufferData(), ImageBufferFormat.Rgba, 1), imodel0, textureParams); const graphicBuilder = target.renderSystem.createGraphic({ type: GraphicType.Scene, viewport }); - graphicBuilder.addArc(Arc3d.createCircularStartMiddleEnd(new Point3d(-100, 0, 0), new Point3d(0, 100, 0), new Point3d(100, 0, 0)) as Arc3d, false, false); + graphicBuilder.addArc( + Arc3d.createCircularStartMiddleEnd(new Point3d(-100, 0, 0), new Point3d(0, 100, 0), new Point3d(100, 0, 0)) as Arc3d, + false, + false, + ); const graphic = graphicBuilder.finish(); // Pre-disposal @@ -481,12 +539,12 @@ describe("Disposal of WebGL Resources", () => { assert.isTrue(isDisposed(target)); assert.isFalse(isDisposed(texture)); if (batches.length > 0 && !allOverridesSharedWithTarget(target, batches)) - assert.isFalse(isDisposed(batches)); // we did not call getOverrides on any graphics + assert.isFalse(isDisposed(batches)); // we did not call getOverrides on any graphics else assert.isTrue(isDisposed(batches)); // Post-disposal of target (only owned resource checks) - assert.isTrue(isDisposed(target, ["_batches", "_scene"])); // This test claims _batches and _scene are the only disposable target members that are NOT fully owned + assert.isTrue(isDisposed(target, ["_batches", "_scene"])); // This test claims _batches and _scene are the only disposable target members that are NOT fully owned assert.isTrue(isDisposed(exposedTarget.decorations)); assert.isTrue(isDisposed(target.compositor)); assert.isTrue(isDisposed(dynamics)); diff --git a/full-stack-tests/core/src/frontend/standalone/tile/ElementGraphics.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/ElementGraphics.test.ts index 13dc3f337f2b..761740dd3db9 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/ElementGraphics.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/ElementGraphics.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; -import { Transform } from "@itwin/core-geometry"; import { PersistentGraphicsRequestProps } from "@itwin/core-common"; import { IModelApp, MockRender, readElementGraphics, SnapshotConnection } from "@itwin/core-frontend"; +import { Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; describe("requestElementGraphics", () => { @@ -67,7 +67,7 @@ describe("requestElementGraphics", () => { let elemRtc: number[]; before(async () => { - const placement = (await imodel.elements.getPlacements("0x29", {type: "3d"}))[0]; + const placement = (await imodel.elements.getPlacements("0x29", { type: "3d" }))[0]; expect(placement).not.to.be.undefined; const range = placement.calculateRange(); const rangeCenter = range.center; @@ -78,8 +78,7 @@ describe("requestElementGraphics", () => { quantize?: boolean; absolute?: boolean; location?: Transform; - }, expectedRtc: number[] | undefined, - ): Promise { + }, expectedRtc: number[] | undefined): Promise { const requestProps: PersistentGraphicsRequestProps = { elementId: "0x29", id: Guid.createValue(), diff --git a/full-stack-tests/core/src/frontend/standalone/tile/SectionCutTileTree.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/SectionCutTileTree.test.ts index a12a39064f6d..743bc49e2833 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/SectionCutTileTree.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/SectionCutTileTree.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ClipStyle } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection, SpatialViewState, ViewState } from "@itwin/core-frontend"; import { ClipPrimitive, ClipVector, ConvexClipPlaneSet } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; function countTileTrees(view: ViewState): number { @@ -28,7 +28,7 @@ describe("Section-cut tile tree", () => { before(async () => { await TestUtility.startFrontend(); - const imodels = await Promise.all([ SnapshotConnection.openFile("mirukuru.ibim"), SnapshotConnection.openFile("planprojection.bim") ]); + const imodels = await Promise.all([SnapshotConnection.openFile("mirukuru.ibim"), SnapshotConnection.openFile("planprojection.bim")]); testCases.push({ imodel: imodels[0], viewId: "0x24" }); testCases.push({ imodel: imodels[1], viewId: "0x29" }); }); diff --git a/full-stack-tests/core/src/frontend/standalone/tile/TileIO.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/TileIO.test.ts index a6ed9598f5ba..a9398658d08b 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/TileIO.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/TileIO.test.ts @@ -2,21 +2,51 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ByteStream, Id64, Id64String, ProcessDetector } from "@itwin/core-bentley"; import { - BatchType, CurrentImdlVersion, EdgeOptions, EmptyLocalization, ImdlFlags, ImdlHeader, IModelReadRpcInterface, IModelRpcProps, IModelTileRpcInterface, IModelTileTreeId, iModelTileTreeIdToString, - ModelProps, PackedFeatureTable, RelatedElementProps, RenderMode, SnapshotIModelRpcInterface, TileContentSource, TileFormat, TileReadStatus, ViewFlags, + BatchType, + CurrentImdlVersion, + EdgeOptions, + EmptyLocalization, + ImdlFlags, + ImdlHeader, + IModelReadRpcInterface, + IModelRpcProps, + IModelTileRpcInterface, + IModelTileTreeId, + iModelTileTreeIdToString, + ModelProps, + PackedFeatureTable, + RelatedElementProps, + RenderMode, + SnapshotIModelRpcInterface, + TileContentSource, + TileFormat, + TileReadStatus, + ViewFlags, } from "@itwin/core-common"; +import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { - GeometricModelState, ImdlReader, IModelApp, IModelConnection, IModelTileContent, IModelTileTree, iModelTileTreeParamsFromJSON, MockRender, - RenderGraphic, SnapshotConnection, TileAdmin, TileRequest, TileTreeLoadStatus, ViewState, + GeometricModelState, + ImdlReader, + IModelApp, + IModelConnection, + IModelTileContent, + IModelTileTree, + iModelTileTreeParamsFromJSON, + MockRender, + RenderGraphic, + SnapshotConnection, + TileAdmin, + TileRequest, + TileTreeLoadStatus, + ViewState, } from "@itwin/core-frontend"; import { ImdlModel } from "@itwin/core-frontend/lib/cjs/common/imdl/ImdlModel"; import { parseImdlDocument } from "@itwin/core-frontend/lib/cjs/common/imdl/ParseImdlDocument"; import { SurfaceType } from "@itwin/core-frontend/lib/cjs/common/internal/render/SurfaceParams"; import { Batch, GraphicsArray, MeshGraphic, PolylineGeometry, Primitive, RenderOrder } from "@itwin/core-frontend/lib/cjs/webgl"; -import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; import { TileTestCase, TileTestData } from "./data/TileIO.data"; import { TILE_DATA_1_1 } from "./data/TileIO.data.1.1"; @@ -48,23 +78,36 @@ for (let i = 0; i < numBaseTestCases; i++) { } export class FakeGMState extends GeometricModelState { - public get is3d(): boolean { return true; } - public override get is2d(): boolean { return !this.is3d; } - public constructor(props: ModelProps, iModel: IModelConnection) { super(props, iModel); } + public get is3d(): boolean { + return true; + } + public override get is2d(): boolean { + return !this.is3d; + } + public constructor(props: ModelProps, iModel: IModelConnection) { + super(props, iModel); + } } export class FakeModelProps implements ModelProps { public modeledElement: RelatedElementProps; public classFullName: string = "fake"; - public constructor(props: RelatedElementProps) { this.modeledElement = props; } + public constructor(props: RelatedElementProps) { + this.modeledElement = props; + } } export class FakeREProps implements RelatedElementProps { public id: Id64String; - public constructor() { this.id = Id64.invalid; } + public constructor() { + this.id = Id64.invalid; + } } -export function fakeViewState(iModel: IModelConnection, options?: { visibleEdges?: boolean, renderMode?: RenderMode, is2d?: boolean, animationId?: Id64String }): ViewState { +export function fakeViewState( + iModel: IModelConnection, + options?: { visibleEdges?: boolean, renderMode?: RenderMode, is2d?: boolean, animationId?: Id64String }, +): ViewState { return { iModel, is3d: () => true !== options?.is2d, @@ -72,7 +115,7 @@ export function fakeViewState(iModel: IModelConnection, options?: { visibleEdges renderMode: options?.renderMode ?? RenderMode.SmoothShade, visibleEdges: options?.visibleEdges ?? false, }), - displayStyle: { }, + displayStyle: {}, } as unknown as ViewState; } @@ -598,7 +641,9 @@ describe("mirukuru TileTree", () => { } class TestSystem extends MockRender.System { - public override createTarget(canvas: HTMLCanvasElement): TestTarget { return new TestTarget(this, canvas); } + public override createTarget(canvas: HTMLCanvasElement): TestTarget { + return new TestTarget(this, canvas); + } } before(async () => { @@ -613,7 +658,7 @@ describe("mirukuru TileTree", () => { await ElectronApp.startup({ iModelApp: { localization: new EmptyLocalization(), - rpcInterfaces: [ IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface ], + rpcInterfaces: [IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface], tileAdmin, }, }); @@ -777,7 +822,7 @@ describe("TileAdmin", () => { await super.startup({ tileAdmin: props, localization: new EmptyLocalization(), - rpcInterfaces: [ IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface ], + rpcInterfaces: [IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface], }); if (ProcessDetector.isElectronAppFrontend) { @@ -785,7 +830,7 @@ describe("TileAdmin", () => { iModelApp: { tileAdmin: props, localization: new EmptyLocalization(), - rpcInterfaces: [ IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface ], + rpcInterfaces: [IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface], }, }); } @@ -825,7 +870,9 @@ describe("TileAdmin", () => { }) as ImdlModel.Document; expect(typeof document).to.equal("object"); - return document.nodes.some((node) => node.primitives && node.primitives.some((primitive) => primitive.type === "mesh" && undefined !== primitive.params.edges)); + return document.nodes.some((node) => + node.primitives && node.primitives.some((primitive) => primitive.type === "mesh" && undefined !== primitive.params.edges) + ); } public static async test(imodel: IModelConnection) { diff --git a/full-stack-tests/core/src/frontend/standalone/tile/TileRequest.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/TileRequest.test.ts index c5191ed8893d..6cc3cc96ff47 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/TileRequest.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/TileRequest.test.ts @@ -2,16 +2,27 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import * as sinonChai from "sinon-chai"; -import { expect, use } from "chai"; import { BeDuration } from "@itwin/core-bentley"; import { IModelTileRpcInterface, ServerTimeoutError } from "@itwin/core-common"; import { - IModelApp, IModelTile, IModelTileContent, IModelTileTree, IpcApp, RenderGraphic, RenderMemory, SnapshotConnection, Tile, TileLoadStatus, - TileRequestChannel, TileStorage, Viewport, + IModelApp, + IModelTile, + IModelTileContent, + IModelTileTree, + IpcApp, + RenderGraphic, + RenderMemory, + SnapshotConnection, + Tile, + TileLoadStatus, + TileRequestChannel, + TileStorage, + Viewport, } from "@itwin/core-frontend"; import type { FrontendStorage, TransferConfig } from "@itwin/object-storage-core/lib/frontend"; +import { expect, use } from "chai"; +import * as sinon from "sinon"; +import * as sinonChai from "sinon-chai"; import { TestUtility } from "../../TestUtility"; import { TILE_DATA_2_0 } from "./data/TileIO.data.2.0"; import { fakeViewState } from "./TileIO.test"; @@ -52,7 +63,7 @@ describe("IModelTileRequestChannels", () => { const viewport = { viewportId: 12345, iModel: tile.tree.iModel, - invalidateScene: () => { }, + invalidateScene: () => {}, } as Viewport; IModelApp.tileAdmin.requestTiles(viewport, new Set([tile])); diff --git a/full-stack-tests/core/src/frontend/standalone/tile/TileTree.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/TileTree.test.ts index c30076e31ffb..143d3a6b0bf8 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/TileTree.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/TileTree.test.ts @@ -2,14 +2,24 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { compareStrings } from "@itwin/core-bentley"; import { ServerTimeoutError } from "@itwin/core-common"; import { - IModelApp, IModelConnection, overrideRequestTileTreeProps, RenderSystem, SnapshotConnection, Tile, TileContent, TileDrawArgs, TileLoadPriority, - TileRequest, TileRequestChannel, TileTree, + IModelApp, + IModelConnection, + overrideRequestTileTreeProps, + RenderSystem, + SnapshotConnection, + Tile, + TileContent, + TileDrawArgs, + TileLoadPriority, + TileRequest, + TileRequestChannel, + TileTree, } from "@itwin/core-frontend"; import { Range3d, Transform } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; class MockTile extends Tile { @@ -54,18 +64,28 @@ class MockTree extends TileTree { this._rootTile = new MockTile(this); } - public get rootTile() { return this._rootTile; } - public get is3d() { return true; } - public get maxDepth() { return 1; } - public get viewFlagOverrides() { return {}; } - public override get isContentUnbounded() { return false; } + public get rootTile() { + return this._rootTile; + } + public get is3d() { + return true; + } + public get maxDepth() { + return 1; + } + public get viewFlagOverrides() { + return {}; + } + public override get isContentUnbounded() { + return false; + } protected _selectTiles(_args: TileDrawArgs): Tile[] { return []; } - public draw(_args: TileDrawArgs): void { } - public prune(): void { } + public draw(_args: TileDrawArgs): void {} + public prune(): void {} } describe("TileTreeSupplier", () => { diff --git a/full-stack-tests/core/src/frontend/standalone/tile/Tolerance.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/Tolerance.test.ts index 95a7595f60b5..6a2a378d2a81 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/Tolerance.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/Tolerance.test.ts @@ -3,16 +3,31 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ByteStream } from "@itwin/core-bentley"; import { - BatchType, computeChildTileProps, computeTileChordTolerance, ContentIdProvider, defaultTileOptions, ImdlHeader, iModelTileTreeIdToString, - TileMetadata, TileProps, TileTreeMetadata, + BatchType, + computeChildTileProps, + computeTileChordTolerance, + ContentIdProvider, + defaultTileOptions, + ImdlHeader, + iModelTileTreeIdToString, + TileMetadata, + TileProps, + TileTreeMetadata, } from "@itwin/core-common"; import { - GeometricModelState, IModelApp, IModelConnection, IModelTile, IModelTileTree, SnapshotConnection, Tile, TileTreeLoadStatus, + GeometricModelState, + IModelApp, + IModelConnection, + IModelTile, + IModelTileTree, + SnapshotConnection, + Tile, + TileTreeLoadStatus, } from "@itwin/core-frontend"; import { Range3d, Range3dProps } from "@itwin/core-geometry"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; import { fakeViewState } from "./TileIO.test"; @@ -20,7 +35,11 @@ describe("Tile tolerance", () => { let imodel: IModelConnection; const minimumSpatialTolerance = 0.02; const modelId = "0x1c"; - const treeId = iModelTileTreeIdToString(modelId, { type: BatchType.Primary, edges: false }, { ...defaultTileOptions, expandProjectExtents: false, useLargerTiles: false }); + const treeId = iModelTileTreeIdToString(modelId, { type: BatchType.Primary, edges: false }, { + ...defaultTileOptions, + expandProjectExtents: false, + useLargerTiles: false, + }); before(async () => { await TestUtility.startFrontend({ tileAdmin: { expandProjectExtents: false, minimumSpatialTolerance, useLargerTiles: false } }); @@ -46,17 +65,21 @@ describe("Tile tolerance", () => { }; } - function computeTolerance(rangeProps: Range3dProps, arg: { tileScreenSize: number }, sizeMultiplier?: number ): number { + function computeTolerance(rangeProps: Range3dProps, arg: { tileScreenSize: number }, sizeMultiplier?: number): number { const range = new Range3d(); range.setFromJSON(rangeProps); - return computeTileChordTolerance({ - contentRange: range, - isLeaf: false, - sizeMultiplier, - emptySubRangeMask: 0, - contentId: "", - range, - }, true, arg.tileScreenSize); + return computeTileChordTolerance( + { + contentRange: range, + isLeaf: false, + sizeMultiplier, + emptySubRangeMask: 0, + contentId: "", + range, + }, + true, + arg.tileScreenSize, + ); } async function expectTolerance(contentId: string, expectedTolerance: number, epsilon = 0.000001): Promise { diff --git a/full-stack-tests/core/src/frontend/standalone/tile/Unloading.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/Unloading.test.ts index 0abeaf6c1fc3..405428b8ec8a 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/Unloading.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/Unloading.test.ts @@ -3,11 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { BeDuration, BeTimePoint } from "@itwin/core-bentley"; import { - DisclosedTileTreeSet, IModelApp, IModelConnection, IModelTileTree, SnapshotConnection, Tile, TileLoadStatus, TileTree, TileUsageMarker, Viewport, + DisclosedTileTreeSet, + IModelApp, + IModelConnection, + IModelTileTree, + SnapshotConnection, + Tile, + TileLoadStatus, + TileTree, + TileUsageMarker, + Viewport, } from "@itwin/core-frontend"; +import { expect } from "chai"; import { TestUtility } from "../../TestUtility"; import { createOnScreenTestViewport, testOnScreenViewport, TestViewport, testViewports } from "../../TestViewport"; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/VerifyTileVersionInfo.test.ts b/full-stack-tests/core/src/frontend/standalone/tile/VerifyTileVersionInfo.test.ts index 0dc69f463eaa..75e59380f1b2 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/VerifyTileVersionInfo.test.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/VerifyTileVersionInfo.test.ts @@ -2,15 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; -import { CurrentImdlVersion, EmptyLocalization, IModelTileRpcInterface } from "@itwin/core-common"; import { ProcessDetector } from "@itwin/core-bentley"; +import { CurrentImdlVersion, EmptyLocalization, IModelTileRpcInterface } from "@itwin/core-common"; import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; +import { assert } from "chai"; describe("iMdl format version", () => { before(async () => { if (ProcessDetector.isElectronAppFrontend) - await ElectronApp.startup({ iModelApp: { localization: new EmptyLocalization(), rpcInterfaces: [IModelTileRpcInterface] }}); + await ElectronApp.startup({ iModelApp: { localization: new EmptyLocalization(), rpcInterfaces: [IModelTileRpcInterface] } }); }); after(async () => { diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.1.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.1.ts index ebe3f09ca887..f5746745b7b8 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.1.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.1.ts @@ -13,1859 +13,38406 @@ export const TILE_DATA_1_1 = { rectangle: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x01, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, 0x41, - 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, 0x39, 0xb4, - 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, - 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x0a, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0x60, 0x0a, - 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x34, 0x39, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, - 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x35, 0x32, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, - 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x39, 0x36, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, - 0x32, 0x34, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, - 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, - 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, - 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x63, 0x6c, 0x61, 0x73, - 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, - 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, - 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, - 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, - 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, - 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, - 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, - 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, - 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, - 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, - 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, - 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x36, 0x33, - 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, 0x31, 0x31, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x31, 0x35, - 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x32, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, - 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, - 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, - 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x36, 0x2c, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x31, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, - 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, - 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, - 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, - 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, - 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, - 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, - 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, - 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, - 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, 0x00, 0x00, 0xf0, 0x41, 0xfd, 0xff, 0x0b, 0x42, 0x00, 0x00, 0xf0, 0x41, - 0x00, 0x00, 0xf0, 0x41, 0xfd, 0xff, 0x0b, 0x42, 0xfd, 0xff, 0x0b, 0x42, 0xfd, 0xff, 0x0b, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xfd, - 0xff, 0x0b, 0x42, 0xfd, 0xff, 0x0b, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xf2, 0xff, - 0x47, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xf6, 0xff, 0x33, 0x42, 0xf2, 0xff, 0x47, 0x42, 0xf2, 0xff, 0x47, 0x42, 0xf2, 0xff, 0x47, - 0x42, 0xeb, 0xff, 0x6f, 0x42, 0xf2, 0xff, 0x47, 0x42, 0xf2, 0xff, 0x47, 0x42, 0xeb, 0xff, 0x6f, 0x42, 0xeb, 0xff, 0x6f, 0x42, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x01, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd4, + 0x0a, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x32, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0xf0, + 0x41, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0x00, + 0x00, + 0xf0, + 0x41, + 0x00, + 0x00, + 0xf0, + 0x41, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0xfd, + 0xff, + 0x0b, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xf6, + 0xff, + 0x33, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xeb, + 0xff, + 0x6f, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xf2, + 0xff, + 0x47, + 0x42, + 0xeb, + 0xff, + 0x6f, + 0x42, + 0xeb, + 0xff, + 0x6f, + 0x42, ]), }, lineString: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x01, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, 0x62, - 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, 0x55, 0x0e, - 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, - 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0x8c, 0x0c, - 0x00, 0x00, 0xf0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, - 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, - 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, - 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, - 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, - 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, - 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, - 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, - 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, - 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, - 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, - 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, - 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, - 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, - 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, - 0x36, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, - 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, - 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, - 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, - 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, - 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, - 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x03, 0x00, 0xf8, - 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, - 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, - 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, - 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, - 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, - 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, - 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, - 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, - 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, - 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, - 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, - 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xe5, - 0xff, 0x9f, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0x00, 0x00, - 0x00, 0x00, 0xe5, 0xff, 0x9f, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, - 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, - 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0x85, - 0x71, 0xf9, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0x85, 0x71, 0xf9, 0x41, 0x85, 0x71, 0xf9, 0x41, 0xe5, 0xff, - 0x9f, 0x41, 0x85, 0x71, 0xf9, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0x85, 0x71, 0xf9, 0x41, 0x85, 0x71, 0xf9, - 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, - 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0xe5, 0xff, 0x9f, 0x41, 0x85, 0x71, 0xf9, 0x41, 0x94, - 0xb8, 0x24, 0x42, 0x85, 0x71, 0xf9, 0x41, 0x85, 0x71, 0xf9, 0x41, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x85, 0x71, - 0xf9, 0x41, 0x94, 0xb8, 0x24, 0x42, 0x85, 0x71, 0xf9, 0x41, 0x85, 0x71, 0xf9, 0x41, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, - 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, - 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0xd1, - 0x29, 0x7e, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0x94, 0xb8, - 0x24, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, - 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, - 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0x94, 0xb8, 0x24, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, - 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, - 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xf9, 0x14, 0x93, 0x42, 0xd1, 0x29, 0x7e, - 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xf9, 0x14, 0x93, 0x42, 0xf9, 0x14, 0x93, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xf9, 0x14, 0x93, 0x42, - 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xf9, 0x14, 0x93, 0x42, 0xf9, 0x14, 0x93, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, - 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, - 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, 0xd1, 0x29, 0x7e, 0x42, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x01, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x0c, + 0x00, + 0x00, + 0xf0, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0xe5, + 0xff, + 0x9f, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x85, + 0x71, + 0xf9, + 0x41, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0x94, + 0xb8, + 0x24, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xf9, + 0x14, + 0x93, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, + 0xd1, + 0x29, + 0x7e, + 0x42, ]), }, lineStrings: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x01, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, 0x62, - 0x00, 0x1e, 0xc0, 0xab, 0xf1, 0xd2, 0x4d, 0x62, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, 0x55, 0x0e, - 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x3d, 0x40, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, - 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x1e, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, - 0x00, 0x68, 0x1e, 0x00, 0x00, 0xbc, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x34, 0x31, 0x30, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x35, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x32, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, - 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x32, 0x34, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, - 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x31, 0x39, 0x32, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, - 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x32, 0x35, 0x30, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, - 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, - 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, - 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, - 0x39, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, - 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, - 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, - 0x30, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x34, 0x31, 0x37, 0x37, 0x30, 0x36, 0x36, 0x32, 0x33, - 0x32, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, - 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, - 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, - 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, - 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, - 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, - 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, - 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, - 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, - 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, - 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, 0x22, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x31, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x69, - 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, - 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, - 0x31, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, - 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, - 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, - 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, - 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, - 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, - 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, - 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, - 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, - 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, - 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, - 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, - 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x38, - 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, - 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, - 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, - 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, - 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, - 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, - 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, - 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, - 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, - 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, - 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, - 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, - 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, - 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, - 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, - 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, - 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, - 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, - 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, - 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, - 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, - 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, - 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, - 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, - 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, - 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x25, 0x72, 0xf9, 0x41, 0x25, - 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x25, 0x72, - 0xf9, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, - 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, - 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, - 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, - 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, - 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, - 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, - 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, - 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, - 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, - 0x6d, 0x15, 0x93, 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, - 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, - 0x7e, 0x42, 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xa7, 0xaa, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, - 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0xd5, 0xfe, 0x7f, 0x01, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xa7, 0xaa, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, - 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, - 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, - 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, - 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, - 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, - 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, - 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, - 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, - 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, - 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, - 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, - 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, - 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, - 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, - 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, - 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, - 0x05, 0x00, 0x00, 0x0e, 0x07, 0x00, 0x00, 0x1b, 0x06, 0x00, 0x00, 0x39, 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x06, - 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, - 0x00, 0x03, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x51, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, - 0x0c, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0f, - 0x06, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x21, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x60, 0x07, - 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x09, 0x08, 0x00, - 0x00, 0x09, 0x07, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, - 0x0c, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0f, - 0x08, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x60, 0x08, - 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, - 0x00, 0x06, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, - 0x0c, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0f, - 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x60, 0x09, - 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x09, 0x0a, 0x00, - 0x00, 0x09, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x51, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, - 0x0c, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0f, - 0x0a, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0x90, 0x09, - 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x0e, 0x0b, 0x00, - 0x00, 0x21, 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00, - 0x90, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x09, 0x0b, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x90, - 0x0a, 0x00, 0x00, 0x4b, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x60, 0x0b, - 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0x0e, 0x00, 0x00, - 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0xa0, 0x41, - 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, - 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, - 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x25, 0x72, 0xf9, - 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, 0xf9, 0x41, - 0x25, 0x72, 0xf9, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, - 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x85, 0x00, 0xa0, 0x41, 0x25, 0x72, - 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x25, 0x72, 0xf9, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, - 0x42, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, 0x25, 0x72, 0xf9, 0x41, 0x25, 0x72, 0xf9, 0x41, 0x34, 0xb9, 0x24, 0x42, - 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, - 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, - 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, - 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, 0x7e, 0x42, - 0xb9, 0x2a, 0x7e, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, - 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0x34, 0xb9, 0x24, 0x42, 0xb9, 0x2a, - 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, - 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, 0x42, - 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, - 0x15, 0x93, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x6d, 0x15, 0x93, 0x42, 0x6d, 0x15, 0x93, 0x42, 0xb9, 0x2a, - 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, - 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0xb9, 0x2a, 0x7e, 0x42, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xfe, 0x9f, 0x41, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x00, 0x00, 0x00, 0x00, 0xa5, - 0xfe, 0x9f, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, - 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, - 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x45, 0x70, 0xf9, 0x41, - 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x45, 0x70, 0xf9, 0x41, 0x45, 0x70, 0xf9, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x45, - 0x70, 0xf9, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x45, 0x70, 0xf9, 0x41, 0x45, 0x70, 0xf9, 0x41, 0xa5, 0xfe, - 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, - 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0xa5, 0xfe, 0x9f, 0x41, 0x45, 0x70, 0xf9, 0x41, 0x53, 0xb7, 0x24, 0x42, - 0x45, 0x70, 0xf9, 0x41, 0x45, 0x70, 0xf9, 0x41, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x45, 0x70, 0xf9, 0x41, 0x53, - 0xb7, 0x24, 0x42, 0x45, 0x70, 0xf9, 0x41, 0x45, 0x70, 0xf9, 0x41, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, - 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, - 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x02, 0x28, 0x7e, 0x42, - 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x02, - 0x28, 0x7e, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x53, 0xb7, - 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, - 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x53, 0xb7, 0x24, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, - 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, - 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x12, 0x14, 0x93, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, - 0x7e, 0x42, 0x12, 0x14, 0x93, 0x42, 0x12, 0x14, 0x93, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x12, 0x14, 0x93, 0x42, 0x02, 0x28, 0x7e, - 0x42, 0x02, 0x28, 0x7e, 0x42, 0x12, 0x14, 0x93, 0x42, 0x12, 0x14, 0x93, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, - 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, 0x02, - 0x28, 0x7e, 0x42, 0x02, 0x28, 0x7e, 0x42, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x01, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x3e, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x3d, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf4, + 0x1e, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x68, + 0x1e, + 0x00, + 0x00, + 0xbc, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x32, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x31, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x30, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x37, + 0x37, + 0x30, + 0x36, + 0x36, + 0x32, + 0x33, + 0x32, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x07, + 0x00, + 0x00, + 0x1b, + 0x06, + 0x00, + 0x00, + 0x39, + 0x07, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x39, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x51, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x0c, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0f, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x21, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x09, + 0x08, + 0x00, + 0x00, + 0x09, + 0x07, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x39, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x51, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x21, + 0x09, + 0x00, + 0x00, + 0x39, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x51, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0f, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0f, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x21, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x4b, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0f, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x85, + 0x00, + 0xa0, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x25, + 0x72, + 0xf9, + 0x41, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0x34, + 0xb9, + 0x24, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0x6d, + 0x15, + 0x93, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0xb9, + 0x2a, + 0x7e, + 0x42, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0xa5, + 0xfe, + 0x9f, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x45, + 0x70, + 0xf9, + 0x41, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x53, + 0xb7, + 0x24, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x12, + 0x14, + 0x93, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, + 0x02, + 0x28, + 0x7e, + 0x42, ]), }, triangles: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x01, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, 0x62, - 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, 0x55, 0x0e, - 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, - 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0x19, 0x00, 0x00, - 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0x24, 0x19, 0x00, 0x00, 0xb8, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, - 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, - 0x31, 0x30, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x31, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x32, 0x34, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, - 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, 0x32, 0x34, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x36, - 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, - 0x35, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x34, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x38, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x30, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x31, 0x34, 0x38, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, - 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x39, - 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, - 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, - 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x38, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x32, 0x30, 0x35, 0x32, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, - 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, - 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, - 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x32, 0x35, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, - 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, - 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, - 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, - 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x66, 0x69, 0x6c, - 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, - 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, - 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, - 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, - 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, - 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, - 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, - 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, - 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, - 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, - 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, - 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, - 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, - 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x2c, - 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, - 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, - 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, - 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, - 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, - 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, - 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, - 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, - 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, - 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, - 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, - 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, - 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, - 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, - 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, - 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, - 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, - 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xf8, 0xff, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, - 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, - 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, - 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, - 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, - 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, - 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, - 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, - 0x36, 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, - 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, 0x03, - 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, - 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, - 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, - 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, 0x06, - 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x4e, 0x56, 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x56, 0x71, - 0xd1, 0x41, 0x56, 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0xea, 0x70, 0x3d, - 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0xea, 0x70, 0x3d, 0x42, 0xea, 0x70, 0x3d, 0x42, 0xea, 0x70, 0x3d, 0x42, - 0xbe, 0x70, 0x51, 0x42, 0xea, 0x70, 0x3d, 0x42, 0xea, 0x70, 0x3d, 0x42, 0xbe, 0x70, 0x51, 0x42, 0xbe, 0x70, 0x51, 0x42, 0x56, - 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x56, 0x71, 0xd1, 0x41, 0x56, 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, - 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x05, 0x71, 0x3d, - 0x42, 0x05, 0x71, 0x3d, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x15, 0x71, 0x51, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x05, 0x71, 0x3d, 0x42, - 0x15, 0x71, 0x51, 0x42, 0x15, 0x71, 0x51, 0x42, 0x56, 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x56, 0x71, 0xd1, 0x41, 0x56, - 0x71, 0xd1, 0x41, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x7c, 0xb8, - 0x10, 0x42, 0x7c, 0xb8, 0x10, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x15, 0x71, 0x51, - 0x42, 0x05, 0x71, 0x3d, 0x42, 0x05, 0x71, 0x3d, 0x42, 0x15, 0x71, 0x51, 0x42, 0x15, 0x71, 0x51, 0x42, 0xa7, 0xaa, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, - 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, - 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, - 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, - 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, - 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, - 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, - 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, - 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, - 0x00, 0x36, 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, - 0x1e, 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, - 0x03, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, - 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x06, 0x00, - 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, - 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, - 0x06, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x4e, 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0x56, - 0x71, 0xd1, 0x41, 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x81, 0x71, - 0x3d, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x81, 0x71, 0x3d, 0x42, 0x81, 0x71, 0x3d, 0x42, 0x81, 0x71, 0x3d, - 0x42, 0x56, 0x71, 0x51, 0x42, 0x81, 0x71, 0x3d, 0x42, 0x81, 0x71, 0x3d, 0x42, 0x56, 0x71, 0x51, 0x42, 0x56, 0x71, 0x51, 0x42, - 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0x56, 0x71, 0xd1, 0x41, 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0xcc, - 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x9c, 0x71, - 0x3d, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0xad, 0x71, 0x51, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0x9c, 0x71, 0x3d, - 0x42, 0xad, 0x71, 0x51, 0x42, 0xad, 0x71, 0x51, 0x42, 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0x56, 0x71, 0xd1, 0x41, - 0x56, 0x71, 0xd1, 0x41, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0xcc, - 0xb8, 0x10, 0x42, 0xcc, 0xb8, 0x10, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0xad, 0x71, - 0x51, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0x9c, 0x71, 0x3d, 0x42, 0xad, 0x71, 0x51, 0x42, 0xad, 0x71, 0x51, 0x42, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x01, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd4, + 0x19, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x24, + 0x19, + 0x00, + 0x00, + 0xb8, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x30, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x34, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x32, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x38, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x30, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x38, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x35, + 0x32, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0xbe, + 0x70, + 0x51, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0xea, + 0x70, + 0x3d, + 0x42, + 0xbe, + 0x70, + 0x51, + 0x42, + 0xbe, + 0x70, + 0x51, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x7c, + 0xb8, + 0x10, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x05, + 0x71, + 0x3d, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0x15, + 0x71, + 0x51, + 0x42, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x80, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0x56, + 0x71, + 0x51, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0x81, + 0x71, + 0x3d, + 0x42, + 0x56, + 0x71, + 0x51, + 0x42, + 0x56, + 0x71, + 0x51, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x56, + 0x71, + 0xd1, + 0x41, + 0x56, + 0x71, + 0xd1, + 0x41, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0xcc, + 0xb8, + 0x10, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0x9c, + 0x71, + 0x3d, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, + 0xad, + 0x71, + 0x51, + 0x42, ]), }, cylinder: { flags: ImdlFlags.ContainsCurves, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x01, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xd6, 0xc5, 0x6d, 0x34, - 0x00, 0x00, 0xc0, 0x39, 0xd6, 0xc5, 0x6d, 0x34, 0x00, 0x00, 0xc0, 0x56, 0xc1, 0xa8, 0xa4, 0x4e, 0x00, 0x08, 0xc0, 0x8e, 0x53, - 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0xaa, 0x3e, 0x57, 0x5b, 0xb1, 0xff, 0x07, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x45, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x44, - 0x00, 0x00, 0xdc, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x31, 0x33, 0x33, 0x35, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, - 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x34, 0x39, 0x32, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, - 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x33, 0x30, - 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, - 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, - 0x39, 0x30, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x36, - 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, - 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x3a, 0x36, 0x34, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x36, - 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, - 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x31, 0x36, 0x32, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, - 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, - 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x31, 0x36, 0x38, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x31, 0x30, 0x33, 0x32, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, - 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, - 0x22, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, - 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, - 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, - 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, - 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x69, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x30, 0x50, - 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, - 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, - 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, - 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, - 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, - 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, - 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, - 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, - 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x34, 0x36, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, - 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x36, 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, - 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x36, 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, - 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x39, 0x2e, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, - 0x35, 0x35, 0x35, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x37, 0x2c, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x38, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, - 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, - 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, - 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x22, 0x3a, 0x35, 0x38, 0x34, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, - 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, - 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, - 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, - 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, - 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, - 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0x01, - 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, - 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, - 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0xf8, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, - 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, - 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, - 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, - 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, - 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, - 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0x38, - 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, - 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, - 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, - 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, - 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, - 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, - 0xae, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x07, 0xe2, - 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xba, 0xc5, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xfb, - 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xa2, 0xdd, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, - 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, - 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, - 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, 0xba, 0x2d, 0x07, - 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, - 0xba, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0x29, 0x11, - 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x22, 0xa2, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xf5, - 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, - 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, - 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, - 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, - 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, - 0x2f, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0x38, 0x54, - 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x13, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, 0xfe, - 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x93, 0x13, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, - 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, - 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, - 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0x41, 0xf8, 0x38, - 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, - 0x6c, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x22, 0x00, 0x00, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x26, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x26, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2a, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x26, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x26, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x26, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x26, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x26, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3f, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x26, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x26, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x26, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x26, 0x00, 0x00, 0x46, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x26, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x26, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x26, 0x00, 0x00, 0x25, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, - 0x00, 0x4c, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4e, 0x00, - 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x50, 0x00, 0x00, 0x4f, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x52, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, - 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x54, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x56, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, - 0x00, 0x56, 0x00, 0x00, 0x58, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, - 0x00, 0x5a, 0x00, 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5c, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5d, 0x00, - 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x60, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, - 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x64, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, - 0x00, 0x64, 0x00, 0x00, 0x66, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, - 0x00, 0x68, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x6a, 0x00, - 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6b, 0x00, - 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6e, 0x00, - 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x70, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, - 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x72, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, - 0x00, 0x72, 0x00, 0x00, 0x74, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, - 0x00, 0x76, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x79, 0x00, - 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, - 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, - 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, - 0x00, 0x84, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x86, 0x00, - 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, - 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, - 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, - 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, - 0x00, 0x8e, 0x00, 0x00, 0x90, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, - 0x00, 0x4b, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x16, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, - 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, - 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, - 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, - 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, - 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, - 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x03, 0x22, 0x00, - 0x00, 0x00, 0x21, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, - 0x03, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, - 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x1f, - 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, - 0x00, 0x01, 0x1e, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x03, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, - 0x01, 0x1e, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x02, - 0x1d, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x03, 0x1b, 0x00, - 0x00, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, - 0x03, 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x02, - 0x19, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x01, 0x18, - 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, - 0x00, 0x01, 0x17, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, - 0x01, 0x17, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x02, - 0x16, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x03, 0x14, 0x00, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, - 0x03, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x02, - 0x12, 0x00, 0x00, 0x03, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x11, - 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x01, 0x11, 0x00, - 0x00, 0x01, 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, - 0x01, 0x10, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x02, - 0x0f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x03, 0x0d, 0x00, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, - 0x03, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x02, - 0x0b, 0x00, 0x00, 0x03, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x01, 0x0a, - 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, - 0x00, 0x01, 0x09, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, - 0x01, 0x09, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, - 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, - 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, - 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, - 0x01, 0x27, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, - 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x28, 0x00, 0x00, 0x00, 0x27, - 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, 0x03, 0x29, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, - 0x03, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x02, - 0x29, 0x00, 0x00, 0x03, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x01, 0x2a, - 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x03, 0x2c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x00, - 0x00, 0x01, 0x2b, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x03, 0x2d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, - 0x01, 0x2d, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x02, - 0x2e, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x03, 0x30, 0x00, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, - 0x03, 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x02, - 0x30, 0x00, 0x00, 0x03, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x01, 0x31, - 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x01, 0x33, 0x00, - 0x00, 0x01, 0x32, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, - 0x01, 0x34, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x02, - 0x35, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x03, 0x36, 0x00, 0x00, 0x00, 0x35, - 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x03, 0x37, 0x00, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, - 0x03, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x02, - 0x37, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x01, 0x38, - 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x03, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x01, 0x3a, 0x00, - 0x00, 0x01, 0x39, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x03, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, - 0x01, 0x3b, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x02, - 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x03, 0x3e, 0x00, - 0x00, 0x00, 0x3d, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, - 0x03, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x02, - 0x3e, 0x00, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x3f, - 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x01, 0x41, 0x00, - 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, - 0x01, 0x42, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x03, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x02, - 0x43, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x43, - 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x03, 0x45, 0x00, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, - 0x03, 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x02, - 0x45, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x01, 0x46, - 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x01, 0x48, 0x00, - 0x00, 0x01, 0x47, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, - 0x01, 0x49, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x03, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, - 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4c, 0x00, - 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, - 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, - 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, - 0x00, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, - 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5a, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, - 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, - 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, - 0x00, 0x64, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, - 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, - 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, - 0x00, 0x72, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, - 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x76, 0x00, - 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, - 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, - 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, - 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, - 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x84, 0x00, - 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, - 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, - 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, - 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, - 0x00, 0x8e, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, - 0x01, 0x4b, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x00, 0x02, 0x4a, 0x00, 0x00, 0x03, 0x4d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x02, - 0x4d, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x4e, - 0x00, 0x00, 0x02, 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x03, 0x51, 0x00, - 0x00, 0x00, 0x50, 0x00, 0x00, 0x02, 0x51, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x02, 0x50, 0x00, 0x00, - 0x03, 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, - 0x52, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x01, 0x54, - 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x03, 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x02, 0x57, 0x00, 0x00, 0x01, 0x57, 0x00, - 0x00, 0x01, 0x56, 0x00, 0x00, 0x02, 0x56, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, - 0x01, 0x59, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x5b, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x02, - 0x5b, 0x00, 0x00, 0x01, 0x5b, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x00, 0x03, 0x5d, 0x00, 0x00, 0x00, 0x5c, - 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x03, 0x5f, 0x00, - 0x00, 0x00, 0x5e, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, - 0x03, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x02, - 0x60, 0x00, 0x00, 0x03, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x02, 0x63, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, 0x62, - 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x02, 0x65, 0x00, 0x00, 0x01, 0x65, 0x00, - 0x00, 0x01, 0x64, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x03, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, - 0x01, 0x67, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, - 0x69, 0x00, 0x00, 0x01, 0x69, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x00, 0x6a, - 0x00, 0x00, 0x02, 0x6b, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x02, 0x6a, 0x00, 0x00, 0x03, 0x6d, 0x00, - 0x00, 0x00, 0x6c, 0x00, 0x00, 0x02, 0x6d, 0x00, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, - 0x03, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x01, 0x6f, 0x00, 0x00, 0x01, 0x6e, 0x00, 0x00, 0x02, - 0x6e, 0x00, 0x00, 0x03, 0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, 0x70, - 0x00, 0x00, 0x02, 0x70, 0x00, 0x00, 0x03, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x01, 0x73, 0x00, - 0x00, 0x01, 0x72, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x03, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, - 0x01, 0x75, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x02, - 0x77, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x76, 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x01, 0x79, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x03, 0x7b, 0x00, - 0x00, 0x00, 0x7a, 0x00, 0x00, 0x02, 0x7b, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x02, 0x7a, 0x00, 0x00, - 0x03, 0x7d, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x01, 0x7d, 0x00, 0x00, 0x01, 0x7c, 0x00, 0x00, 0x02, - 0x7c, 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x7e, - 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, 0x81, 0x00, 0x00, 0x01, 0x81, 0x00, - 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, - 0x01, 0x83, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x02, 0x82, 0x00, 0x00, 0x03, 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x02, - 0x85, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x86, - 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x01, 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x03, 0x89, 0x00, - 0x00, 0x00, 0x88, 0x00, 0x00, 0x02, 0x89, 0x00, 0x00, 0x01, 0x89, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, - 0x03, 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x02, 0x8b, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x02, - 0x8a, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x01, 0x8d, 0x00, 0x00, 0x01, 0x8c, - 0x00, 0x00, 0x02, 0x8c, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x01, 0x8f, 0x00, - 0x00, 0x01, 0x8e, 0x00, 0x00, 0x02, 0x8e, 0x00, 0x00, 0x03, 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, - 0x01, 0x91, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x03, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, - 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xe4, 0x9a, - 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, - 0xa8, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, - 0xd6, 0xa8, 0xca, 0xb4, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, - 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, - 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, - 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, - 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, - 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x8a, 0xf5, - 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, - 0x75, 0xf5, 0x65, 0xe4, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, - 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, - 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, - 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, - 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x35, 0xb4, 0x29, 0xa8, 0x35, - 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x29, 0xa8, - 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, - 0x9a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, - 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, - 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, - 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, - 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x35, 0x4b, 0x40, 0x40, 0x35, - 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x40, 0x40, - 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, - 0x35, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, - 0x4b, 0x35, 0x57, 0x29, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, - 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, - 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, - 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, - 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, - 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0xa8, 0x29, - 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, - 0x35, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, - 0xb4, 0x35, 0xbf, 0x40, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, - 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, - 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, - 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, - 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, - 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, - 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x22, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x20, 0x00, - 0x00, 0x20, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x1c, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x18, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x15, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x13, 0x00, 0x00, 0x10, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, - 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x24, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x2b, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2c, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2a, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x31, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x32, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x32, 0x00, 0x00, 0x35, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, - 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x33, 0x00, 0x00, 0x36, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x39, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x37, 0x00, 0x00, 0x3a, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x3c, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x40, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3f, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x40, 0x00, 0x00, 0x43, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x44, 0x00, - 0x00, 0x44, 0x00, 0x00, 0x42, 0x00, 0x00, 0x45, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x46, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x44, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x46, 0x00, 0x00, 0x49, 0x00, 0x00, 0x46, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x47, 0x00, 0x00, 0x25, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x24, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x00, 0x1e, 0x24, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x06, 0x23, 0x00, - 0x00, 0x06, 0x24, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x00, 0x1e, 0x23, 0x00, 0x00, 0x36, 0x22, 0x00, 0x00, - 0x06, 0x22, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x4e, 0x21, 0x00, 0x00, 0x1e, 0x22, 0x00, 0x00, 0x36, - 0x21, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x36, 0x22, 0x00, 0x00, 0x4e, 0x20, 0x00, 0x00, 0x1e, 0x21, - 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x36, 0x21, 0x00, 0x00, 0x4e, 0x1f, 0x00, - 0x00, 0x1e, 0x20, 0x00, 0x00, 0x36, 0x1f, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, - 0x4e, 0x1e, 0x00, 0x00, 0x1e, 0x1f, 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x06, 0x1e, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x36, - 0x1f, 0x00, 0x00, 0x4e, 0x1d, 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x36, 0x1d, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x06, 0x1e, - 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x4e, 0x1c, 0x00, 0x00, 0x1e, 0x1d, 0x00, 0x00, 0x36, 0x1c, 0x00, 0x00, 0x06, 0x1c, 0x00, - 0x00, 0x06, 0x1d, 0x00, 0x00, 0x36, 0x1d, 0x00, 0x00, 0x4e, 0x1b, 0x00, 0x00, 0x1e, 0x1c, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, - 0x06, 0x1b, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x36, 0x1c, 0x00, 0x00, 0x4e, 0x1a, 0x00, 0x00, 0x1e, 0x1b, 0x00, 0x00, 0x36, - 0x1a, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x06, 0x1b, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, 0x4e, 0x19, 0x00, 0x00, 0x1e, 0x1a, - 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x06, 0x19, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x36, 0x1a, 0x00, 0x00, 0x4e, 0x18, 0x00, - 0x00, 0x1e, 0x19, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x06, 0x19, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, - 0x4e, 0x17, 0x00, 0x00, 0x1e, 0x18, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, 0x06, 0x17, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x36, - 0x18, 0x00, 0x00, 0x4e, 0x16, 0x00, 0x00, 0x1e, 0x17, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00, 0x06, 0x17, - 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, 0x4e, 0x15, 0x00, 0x00, 0x1e, 0x16, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x06, 0x15, 0x00, - 0x00, 0x06, 0x16, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x4e, 0x14, 0x00, 0x00, 0x1e, 0x15, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, - 0x06, 0x14, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x00, 0x1e, 0x14, 0x00, 0x00, 0x36, - 0x13, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x00, 0x1e, 0x13, - 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x36, 0x13, 0x00, 0x00, 0x4e, 0x11, 0x00, - 0x00, 0x1e, 0x12, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x06, 0x11, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, - 0x4e, 0x10, 0x00, 0x00, 0x1e, 0x11, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, 0x11, 0x00, 0x00, 0x36, - 0x11, 0x00, 0x00, 0x4e, 0x0f, 0x00, 0x00, 0x1e, 0x10, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x06, 0x0f, 0x00, 0x00, 0x06, 0x10, - 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x4e, 0x0e, 0x00, 0x00, 0x1e, 0x0f, 0x00, 0x00, 0x36, 0x0e, 0x00, 0x00, 0x06, 0x0e, 0x00, - 0x00, 0x06, 0x0f, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x4e, 0x0d, 0x00, 0x00, 0x1e, 0x0e, 0x00, 0x00, 0x36, 0x0d, 0x00, 0x00, - 0x06, 0x0d, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x36, 0x0e, 0x00, 0x00, 0x4e, 0x0c, 0x00, 0x00, 0x1e, 0x0d, 0x00, 0x00, 0x36, - 0x0c, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x06, 0x0d, 0x00, 0x00, 0x36, 0x0d, 0x00, 0x00, 0x4e, 0x0b, 0x00, 0x00, 0x1e, 0x0c, - 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, 0x4e, 0x0a, 0x00, - 0x00, 0x1e, 0x0b, 0x00, 0x00, 0x36, 0x0a, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, - 0x4e, 0x09, 0x00, 0x00, 0x1e, 0x0a, 0x00, 0x00, 0x36, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x36, - 0x0a, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, 0x09, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x09, - 0x00, 0x00, 0x36, 0x09, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, - 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, - 0x06, 0x06, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, - 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x05, - 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x4e, 0x03, 0x00, - 0x00, 0x1e, 0x04, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, - 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x02, - 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x27, 0x00, 0x00, 0x1e, 0x25, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x06, 0x27, 0x00, - 0x00, 0x06, 0x25, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x4e, 0x28, 0x00, 0x00, 0x1e, 0x27, 0x00, 0x00, 0x36, 0x28, 0x00, 0x00, - 0x06, 0x28, 0x00, 0x00, 0x06, 0x27, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x4e, 0x29, 0x00, 0x00, 0x1e, 0x28, 0x00, 0x00, 0x36, - 0x29, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x06, 0x28, 0x00, 0x00, 0x36, 0x28, 0x00, 0x00, 0x4e, 0x2a, 0x00, 0x00, 0x1e, 0x29, - 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, 0x06, 0x2a, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x36, 0x29, 0x00, 0x00, 0x4e, 0x2b, 0x00, - 0x00, 0x1e, 0x2a, 0x00, 0x00, 0x36, 0x2b, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x06, 0x2a, 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, - 0x4e, 0x2c, 0x00, 0x00, 0x1e, 0x2b, 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x06, 0x2c, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x36, - 0x2b, 0x00, 0x00, 0x4e, 0x2d, 0x00, 0x00, 0x1e, 0x2c, 0x00, 0x00, 0x36, 0x2d, 0x00, 0x00, 0x06, 0x2d, 0x00, 0x00, 0x06, 0x2c, - 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x4e, 0x2e, 0x00, 0x00, 0x1e, 0x2d, 0x00, 0x00, 0x36, 0x2e, 0x00, 0x00, 0x06, 0x2e, 0x00, - 0x00, 0x06, 0x2d, 0x00, 0x00, 0x36, 0x2d, 0x00, 0x00, 0x4e, 0x2f, 0x00, 0x00, 0x1e, 0x2e, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, - 0x06, 0x2f, 0x00, 0x00, 0x06, 0x2e, 0x00, 0x00, 0x36, 0x2e, 0x00, 0x00, 0x4e, 0x30, 0x00, 0x00, 0x1e, 0x2f, 0x00, 0x00, 0x36, - 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, 0x2f, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, 0x4e, 0x31, 0x00, 0x00, 0x1e, 0x30, - 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, 0x06, 0x31, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x36, 0x30, 0x00, 0x00, 0x4e, 0x32, 0x00, - 0x00, 0x1e, 0x31, 0x00, 0x00, 0x36, 0x32, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x06, 0x31, 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, - 0x4e, 0x33, 0x00, 0x00, 0x1e, 0x32, 0x00, 0x00, 0x36, 0x33, 0x00, 0x00, 0x06, 0x33, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x36, - 0x32, 0x00, 0x00, 0x4e, 0x34, 0x00, 0x00, 0x1e, 0x33, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x06, 0x34, 0x00, 0x00, 0x06, 0x33, - 0x00, 0x00, 0x36, 0x33, 0x00, 0x00, 0x4e, 0x35, 0x00, 0x00, 0x1e, 0x34, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x06, 0x35, 0x00, - 0x00, 0x06, 0x34, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x4e, 0x36, 0x00, 0x00, 0x1e, 0x35, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, - 0x06, 0x36, 0x00, 0x00, 0x06, 0x35, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x4e, 0x37, 0x00, 0x00, 0x1e, 0x36, 0x00, 0x00, 0x36, - 0x37, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x06, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x4e, 0x38, 0x00, 0x00, 0x1e, 0x37, - 0x00, 0x00, 0x36, 0x38, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x36, 0x37, 0x00, 0x00, 0x4e, 0x39, 0x00, - 0x00, 0x1e, 0x38, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x06, 0x39, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x36, 0x38, 0x00, 0x00, - 0x4e, 0x3a, 0x00, 0x00, 0x1e, 0x39, 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x06, 0x3a, 0x00, 0x00, 0x06, 0x39, 0x00, 0x00, 0x36, - 0x39, 0x00, 0x00, 0x4e, 0x3b, 0x00, 0x00, 0x1e, 0x3a, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x06, 0x3b, 0x00, 0x00, 0x06, 0x3a, - 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x4e, 0x3c, 0x00, 0x00, 0x1e, 0x3b, 0x00, 0x00, 0x36, 0x3c, 0x00, 0x00, 0x06, 0x3c, 0x00, - 0x00, 0x06, 0x3b, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x4e, 0x3d, 0x00, 0x00, 0x1e, 0x3c, 0x00, 0x00, 0x36, 0x3d, 0x00, 0x00, - 0x06, 0x3d, 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x36, 0x3c, 0x00, 0x00, 0x4e, 0x3e, 0x00, 0x00, 0x1e, 0x3d, 0x00, 0x00, 0x36, - 0x3e, 0x00, 0x00, 0x06, 0x3e, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x36, 0x3d, 0x00, 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x1e, 0x3e, - 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x06, 0x3e, 0x00, 0x00, 0x36, 0x3e, 0x00, 0x00, 0x4e, 0x40, 0x00, - 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, - 0x4e, 0x41, 0x00, 0x00, 0x1e, 0x40, 0x00, 0x00, 0x36, 0x41, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0x36, - 0x40, 0x00, 0x00, 0x4e, 0x42, 0x00, 0x00, 0x1e, 0x41, 0x00, 0x00, 0x36, 0x42, 0x00, 0x00, 0x06, 0x42, 0x00, 0x00, 0x06, 0x41, - 0x00, 0x00, 0x36, 0x41, 0x00, 0x00, 0x4e, 0x43, 0x00, 0x00, 0x1e, 0x42, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x06, 0x43, 0x00, - 0x00, 0x06, 0x42, 0x00, 0x00, 0x36, 0x42, 0x00, 0x00, 0x4e, 0x44, 0x00, 0x00, 0x1e, 0x43, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, - 0x06, 0x44, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x4e, 0x45, 0x00, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x36, - 0x45, 0x00, 0x00, 0x06, 0x45, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, 0x4e, 0x46, 0x00, 0x00, 0x1e, 0x45, - 0x00, 0x00, 0x36, 0x46, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x06, 0x45, 0x00, 0x00, 0x36, 0x45, 0x00, 0x00, 0x4e, 0x47, 0x00, - 0x00, 0x1e, 0x46, 0x00, 0x00, 0x36, 0x47, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x36, 0x46, 0x00, 0x00, - 0x4e, 0x48, 0x00, 0x00, 0x1e, 0x47, 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x36, - 0x47, 0x00, 0x00, 0x4e, 0x49, 0x00, 0x00, 0x1e, 0x48, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x06, 0x48, - 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x4e, 0x25, 0x00, 0x00, 0x1e, 0x49, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x06, 0x25, 0x00, - 0x00, 0x06, 0x49, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x4e, 0x8c, 0xce, 0x48, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x8c, 0xce, 0x48, - 0x41, 0x8c, 0xce, 0x48, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x55, 0xf6, 0x53, 0x41, - 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x62, - 0x8a, 0x59, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x62, 0x8a, - 0x59, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x60, 0x1e, 0x5f, - 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x42, 0xb2, 0x64, 0x41, - 0x42, 0xb2, 0x64, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x41, - 0x46, 0x6a, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x41, 0x46, - 0x6a, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x4d, 0xda, 0x6f, - 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x16, 0x02, 0x7b, 0x41, - 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, 0x7b, 0x41, 0xfe, - 0x4a, 0x80, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, 0x7b, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0xfe, 0x4a, - 0x80, 0x41, 0x0e, 0x15, 0x83, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0x0e, 0x15, 0x83, 0x41, 0x0e, 0x15, 0x83, - 0x41, 0x0e, 0x15, 0x83, 0x41, 0xf7, 0xde, 0x85, 0x41, 0x0e, 0x15, 0x83, 0x41, 0x0e, 0x15, 0x83, 0x41, 0xf7, 0xde, 0x85, 0x41, - 0xf7, 0xde, 0x85, 0x41, 0xf7, 0xde, 0x85, 0x41, 0x11, 0xa9, 0x88, 0x41, 0xf7, 0xde, 0x85, 0x41, 0xf7, 0xde, 0x85, 0x41, 0x11, - 0xa9, 0x88, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x11, 0xa9, - 0x88, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x02, 0x73, 0x8b, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0x02, 0x73, 0x8b, - 0x41, 0x02, 0x73, 0x8b, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xf5, 0x06, 0x91, 0x41, - 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xe6, - 0xd0, 0x93, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xe6, 0xd0, - 0x93, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xdc, 0x9a, 0x96, - 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xd3, 0x64, 0x99, 0x41, - 0xd3, 0x64, 0x99, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xe2, - 0x2e, 0x9c, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xe2, 0x2e, - 0x9c, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xcb, 0xf8, 0x9e, - 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xc4, 0x8c, 0xa4, 0x41, - 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xcb, - 0x56, 0xa7, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xcb, 0x56, - 0xa7, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xb4, 0x20, 0xaa, - 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xc4, 0xea, 0xac, 0x41, - 0xc4, 0xea, 0xac, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xba, - 0xb4, 0xaf, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xba, 0xb4, - 0xaf, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xb0, 0x7e, 0xb2, - 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa7, 0x12, 0xb8, 0x41, - 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0x94, - 0xdc, 0xba, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x94, 0xdc, - 0xba, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x85, 0xa6, 0xbd, - 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x9f, 0x70, 0xc0, 0x41, - 0x9f, 0x70, 0xc0, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x88, - 0x3a, 0xc3, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x88, 0x3a, - 0xc3, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x8b, 0xce, 0xc8, 0x41, 0x98, 0x04, 0xc6, - 0x41, 0x98, 0x04, 0xc6, 0x41, 0x8b, 0xce, 0xc8, 0x41, 0x8b, 0xce, 0xc8, 0x41, 0x8c, 0xce, 0x48, 0x41, 0x74, 0x62, 0x4e, 0x41, - 0x8c, 0xce, 0x48, 0x41, 0x8c, 0xce, 0x48, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x55, - 0xf6, 0x53, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x74, 0x62, 0x4e, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, - 0x53, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x55, 0xf6, 0x53, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x62, 0x8a, 0x59, - 0x41, 0x62, 0x8a, 0x59, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x62, 0x8a, 0x59, 0x41, 0x60, 0x1e, 0x5f, 0x41, - 0x60, 0x1e, 0x5f, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x60, 0x1e, 0x5f, 0x41, 0x42, - 0xb2, 0x64, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x42, 0xb2, 0x64, 0x41, 0x42, 0xb2, - 0x64, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x41, 0x46, 0x6a, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x41, 0x46, 0x6a, - 0x41, 0x41, 0x46, 0x6a, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x2f, 0x6e, 0x75, 0x41, - 0x4d, 0xda, 0x6f, 0x41, 0x4d, 0xda, 0x6f, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x16, - 0x02, 0x7b, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x2f, 0x6e, 0x75, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, - 0x7b, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0x16, 0x02, 0x7b, 0x41, 0x16, 0x02, 0x7b, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0xfe, 0x4a, 0x80, - 0x41, 0xfe, 0x4a, 0x80, 0x41, 0x0e, 0x15, 0x83, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0xfe, 0x4a, 0x80, 0x41, 0x0e, 0x15, 0x83, 0x41, - 0x0e, 0x15, 0x83, 0x41, 0x0e, 0x15, 0x83, 0x41, 0xf7, 0xde, 0x85, 0x41, 0x0e, 0x15, 0x83, 0x41, 0x0e, 0x15, 0x83, 0x41, 0xf7, - 0xde, 0x85, 0x41, 0xf7, 0xde, 0x85, 0x41, 0xf7, 0xde, 0x85, 0x41, 0x11, 0xa9, 0x88, 0x41, 0xf7, 0xde, 0x85, 0x41, 0xf7, 0xde, - 0x85, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x11, 0xa9, 0x88, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x11, 0xa9, 0x88, - 0x41, 0x11, 0xa9, 0x88, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x02, 0x73, 0x8b, 0x41, 0x02, 0x73, 0x8b, 0x41, 0xef, 0x3c, 0x8e, 0x41, - 0x02, 0x73, 0x8b, 0x41, 0x02, 0x73, 0x8b, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xf5, - 0x06, 0x91, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xef, 0x3c, 0x8e, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, - 0x91, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xf5, 0x06, 0x91, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xe6, 0xd0, 0x93, - 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xe6, 0xd0, 0x93, 0x41, 0xdc, 0x9a, 0x96, 0x41, - 0xdc, 0x9a, 0x96, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xdc, 0x9a, 0x96, 0x41, 0xd3, - 0x64, 0x99, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xd3, 0x64, 0x99, 0x41, 0xd3, 0x64, - 0x99, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xe2, 0x2e, 0x9c, - 0x41, 0xe2, 0x2e, 0x9c, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xd2, 0xc2, 0xa1, 0x41, - 0xcb, 0xf8, 0x9e, 0x41, 0xcb, 0xf8, 0x9e, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xc4, - 0x8c, 0xa4, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xd2, 0xc2, 0xa1, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, - 0xa4, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xc4, 0x8c, 0xa4, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xcb, 0x56, 0xa7, - 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xcb, 0x56, 0xa7, 0x41, 0xb4, 0x20, 0xaa, 0x41, - 0xb4, 0x20, 0xaa, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xb4, 0x20, 0xaa, 0x41, 0xc4, - 0xea, 0xac, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xc4, 0xea, 0xac, 0x41, 0xc4, 0xea, - 0xac, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xba, 0xb4, 0xaf, - 0x41, 0xba, 0xb4, 0xaf, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xa1, 0x48, 0xb5, 0x41, - 0xb0, 0x7e, 0xb2, 0x41, 0xb0, 0x7e, 0xb2, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa7, - 0x12, 0xb8, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa1, 0x48, 0xb5, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, - 0xb8, 0x41, 0x94, 0xdc, 0xba, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0xa7, 0x12, 0xb8, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x94, 0xdc, 0xba, - 0x41, 0x94, 0xdc, 0xba, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x94, 0xdc, 0xba, 0x41, 0x85, 0xa6, 0xbd, 0x41, - 0x85, 0xa6, 0xbd, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x85, 0xa6, 0xbd, 0x41, 0x9f, - 0x70, 0xc0, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x9f, 0x70, 0xc0, 0x41, 0x9f, 0x70, - 0xc0, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x88, 0x3a, 0xc3, - 0x41, 0x88, 0x3a, 0xc3, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x8b, 0xce, 0xc8, 0x41, - 0x98, 0x04, 0xc6, 0x41, 0x98, 0x04, 0xc6, 0x41, 0x8b, 0xce, 0xc8, 0x41, 0x8b, 0xce, 0xc8, 0x41, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x01, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x56, + 0xc1, + 0xa8, + 0xa4, + 0x4e, + 0x00, + 0x08, + 0xc0, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0xaa, + 0x3e, + 0x57, + 0x5b, + 0xb1, + 0xff, + 0x07, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x45, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xd8, + 0x44, + 0x00, + 0x00, + 0xdc, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x33, + 0x35, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x33, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x30, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x36, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x36, + 0x32, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x31, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x30, + 0x33, + 0x32, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6c, + 0x61, + 0x73, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x44, + 0x69, + 0x73, + 0x74, + 0x61, + 0x6e, + 0x63, + 0x65, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x39, + 0x2e, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x35, + 0x38, + 0x34, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x24, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x03, + 0x23, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x03, + 0x22, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x03, + 0x21, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x03, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x03, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x03, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x03, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x03, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x03, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x03, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x03, + 0x19, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x03, + 0x18, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x03, + 0x17, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x03, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x03, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x03, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x03, + 0x13, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x03, + 0x12, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x03, + 0x11, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x03, + 0x10, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x03, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x03, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x03, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x03, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x03, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x03, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x03, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x28, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x03, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x03, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x03, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x03, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x03, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x03, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x03, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x03, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x03, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x03, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x03, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x03, + 0x34, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x03, + 0x35, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x03, + 0x36, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x03, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x03, + 0x38, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x03, + 0x39, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x03, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x03, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x03, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x03, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x03, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x03, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x03, + 0x40, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x03, + 0x41, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x03, + 0x42, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x03, + 0x43, + 0x00, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x03, + 0x44, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x03, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x03, + 0x46, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x03, + 0x47, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x03, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x03, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4a, + 0x00, + 0x00, + 0x03, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4c, + 0x00, + 0x00, + 0x03, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4e, + 0x00, + 0x00, + 0x03, + 0x51, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x02, + 0x51, + 0x00, + 0x00, + 0x01, + 0x51, + 0x00, + 0x00, + 0x01, + 0x50, + 0x00, + 0x00, + 0x02, + 0x50, + 0x00, + 0x00, + 0x03, + 0x53, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x02, + 0x53, + 0x00, + 0x00, + 0x01, + 0x53, + 0x00, + 0x00, + 0x01, + 0x52, + 0x00, + 0x00, + 0x02, + 0x52, + 0x00, + 0x00, + 0x03, + 0x55, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x02, + 0x55, + 0x00, + 0x00, + 0x01, + 0x55, + 0x00, + 0x00, + 0x01, + 0x54, + 0x00, + 0x00, + 0x02, + 0x54, + 0x00, + 0x00, + 0x03, + 0x57, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x02, + 0x57, + 0x00, + 0x00, + 0x01, + 0x57, + 0x00, + 0x00, + 0x01, + 0x56, + 0x00, + 0x00, + 0x02, + 0x56, + 0x00, + 0x00, + 0x03, + 0x59, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x02, + 0x59, + 0x00, + 0x00, + 0x01, + 0x59, + 0x00, + 0x00, + 0x01, + 0x58, + 0x00, + 0x00, + 0x02, + 0x58, + 0x00, + 0x00, + 0x03, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5a, + 0x00, + 0x00, + 0x03, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5c, + 0x00, + 0x00, + 0x03, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5e, + 0x00, + 0x00, + 0x03, + 0x61, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x02, + 0x61, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00, + 0x00, + 0x01, + 0x60, + 0x00, + 0x00, + 0x02, + 0x60, + 0x00, + 0x00, + 0x03, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x02, + 0x63, + 0x00, + 0x00, + 0x01, + 0x63, + 0x00, + 0x00, + 0x01, + 0x62, + 0x00, + 0x00, + 0x02, + 0x62, + 0x00, + 0x00, + 0x03, + 0x65, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x02, + 0x65, + 0x00, + 0x00, + 0x01, + 0x65, + 0x00, + 0x00, + 0x01, + 0x64, + 0x00, + 0x00, + 0x02, + 0x64, + 0x00, + 0x00, + 0x03, + 0x67, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x02, + 0x67, + 0x00, + 0x00, + 0x01, + 0x67, + 0x00, + 0x00, + 0x01, + 0x66, + 0x00, + 0x00, + 0x02, + 0x66, + 0x00, + 0x00, + 0x03, + 0x69, + 0x00, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x02, + 0x69, + 0x00, + 0x00, + 0x01, + 0x69, + 0x00, + 0x00, + 0x01, + 0x68, + 0x00, + 0x00, + 0x02, + 0x68, + 0x00, + 0x00, + 0x03, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6a, + 0x00, + 0x00, + 0x03, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6c, + 0x00, + 0x00, + 0x03, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6e, + 0x00, + 0x00, + 0x03, + 0x71, + 0x00, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x02, + 0x71, + 0x00, + 0x00, + 0x01, + 0x71, + 0x00, + 0x00, + 0x01, + 0x70, + 0x00, + 0x00, + 0x02, + 0x70, + 0x00, + 0x00, + 0x03, + 0x73, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x02, + 0x73, + 0x00, + 0x00, + 0x01, + 0x73, + 0x00, + 0x00, + 0x01, + 0x72, + 0x00, + 0x00, + 0x02, + 0x72, + 0x00, + 0x00, + 0x03, + 0x75, + 0x00, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x02, + 0x75, + 0x00, + 0x00, + 0x01, + 0x75, + 0x00, + 0x00, + 0x01, + 0x74, + 0x00, + 0x00, + 0x02, + 0x74, + 0x00, + 0x00, + 0x03, + 0x77, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x02, + 0x77, + 0x00, + 0x00, + 0x01, + 0x77, + 0x00, + 0x00, + 0x01, + 0x76, + 0x00, + 0x00, + 0x02, + 0x76, + 0x00, + 0x00, + 0x03, + 0x79, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x02, + 0x79, + 0x00, + 0x00, + 0x01, + 0x79, + 0x00, + 0x00, + 0x01, + 0x78, + 0x00, + 0x00, + 0x02, + 0x78, + 0x00, + 0x00, + 0x03, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7a, + 0x00, + 0x00, + 0x03, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7c, + 0x00, + 0x00, + 0x03, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7e, + 0x00, + 0x00, + 0x03, + 0x81, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x02, + 0x81, + 0x00, + 0x00, + 0x01, + 0x81, + 0x00, + 0x00, + 0x01, + 0x80, + 0x00, + 0x00, + 0x02, + 0x80, + 0x00, + 0x00, + 0x03, + 0x83, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x02, + 0x83, + 0x00, + 0x00, + 0x01, + 0x83, + 0x00, + 0x00, + 0x01, + 0x82, + 0x00, + 0x00, + 0x02, + 0x82, + 0x00, + 0x00, + 0x03, + 0x85, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x02, + 0x85, + 0x00, + 0x00, + 0x01, + 0x85, + 0x00, + 0x00, + 0x01, + 0x84, + 0x00, + 0x00, + 0x02, + 0x84, + 0x00, + 0x00, + 0x03, + 0x87, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x02, + 0x87, + 0x00, + 0x00, + 0x01, + 0x87, + 0x00, + 0x00, + 0x01, + 0x86, + 0x00, + 0x00, + 0x02, + 0x86, + 0x00, + 0x00, + 0x03, + 0x89, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x02, + 0x89, + 0x00, + 0x00, + 0x01, + 0x89, + 0x00, + 0x00, + 0x01, + 0x88, + 0x00, + 0x00, + 0x02, + 0x88, + 0x00, + 0x00, + 0x03, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8a, + 0x00, + 0x00, + 0x03, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8c, + 0x00, + 0x00, + 0x03, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8e, + 0x00, + 0x00, + 0x03, + 0x91, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x02, + 0x91, + 0x00, + 0x00, + 0x01, + 0x91, + 0x00, + 0x00, + 0x01, + 0x90, + 0x00, + 0x00, + 0x02, + 0x90, + 0x00, + 0x00, + 0x03, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x23, + 0x00, + 0x00, + 0x1e, + 0x24, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x4e, + 0x22, + 0x00, + 0x00, + 0x1e, + 0x23, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x4e, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x22, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x4e, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x21, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x4e, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x20, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x4e, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x4e, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x4e, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x4e, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x4e, + 0x1a, + 0x00, + 0x00, + 0x1e, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x4e, + 0x19, + 0x00, + 0x00, + 0x1e, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x4e, + 0x18, + 0x00, + 0x00, + 0x1e, + 0x19, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x4e, + 0x17, + 0x00, + 0x00, + 0x1e, + 0x18, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x4e, + 0x16, + 0x00, + 0x00, + 0x1e, + 0x17, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x4e, + 0x15, + 0x00, + 0x00, + 0x1e, + 0x16, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x4e, + 0x14, + 0x00, + 0x00, + 0x1e, + 0x15, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x4e, + 0x13, + 0x00, + 0x00, + 0x1e, + 0x14, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x4e, + 0x12, + 0x00, + 0x00, + 0x1e, + 0x13, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x4e, + 0x11, + 0x00, + 0x00, + 0x1e, + 0x12, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x4e, + 0x10, + 0x00, + 0x00, + 0x1e, + 0x11, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x4e, + 0x0f, + 0x00, + 0x00, + 0x1e, + 0x10, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x4e, + 0x0e, + 0x00, + 0x00, + 0x1e, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x4e, + 0x0d, + 0x00, + 0x00, + 0x1e, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x4e, + 0x0c, + 0x00, + 0x00, + 0x1e, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x4e, + 0x0b, + 0x00, + 0x00, + 0x1e, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x4e, + 0x0a, + 0x00, + 0x00, + 0x1e, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x4e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x09, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x27, + 0x00, + 0x00, + 0x1e, + 0x25, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x4e, + 0x28, + 0x00, + 0x00, + 0x1e, + 0x27, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x4e, + 0x29, + 0x00, + 0x00, + 0x1e, + 0x28, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x4e, + 0x2a, + 0x00, + 0x00, + 0x1e, + 0x29, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x4e, + 0x2b, + 0x00, + 0x00, + 0x1e, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x4e, + 0x2c, + 0x00, + 0x00, + 0x1e, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x4e, + 0x2d, + 0x00, + 0x00, + 0x1e, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x4e, + 0x2e, + 0x00, + 0x00, + 0x1e, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x4e, + 0x2f, + 0x00, + 0x00, + 0x1e, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x4e, + 0x30, + 0x00, + 0x00, + 0x1e, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x4e, + 0x31, + 0x00, + 0x00, + 0x1e, + 0x30, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x4e, + 0x32, + 0x00, + 0x00, + 0x1e, + 0x31, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x4e, + 0x33, + 0x00, + 0x00, + 0x1e, + 0x32, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x4e, + 0x34, + 0x00, + 0x00, + 0x1e, + 0x33, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x4e, + 0x35, + 0x00, + 0x00, + 0x1e, + 0x34, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x4e, + 0x36, + 0x00, + 0x00, + 0x1e, + 0x35, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x4e, + 0x37, + 0x00, + 0x00, + 0x1e, + 0x36, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x4e, + 0x38, + 0x00, + 0x00, + 0x1e, + 0x37, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x4e, + 0x39, + 0x00, + 0x00, + 0x1e, + 0x38, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x4e, + 0x3a, + 0x00, + 0x00, + 0x1e, + 0x39, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x4e, + 0x3b, + 0x00, + 0x00, + 0x1e, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x4e, + 0x3c, + 0x00, + 0x00, + 0x1e, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x4e, + 0x3d, + 0x00, + 0x00, + 0x1e, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x4e, + 0x3e, + 0x00, + 0x00, + 0x1e, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x4e, + 0x3f, + 0x00, + 0x00, + 0x1e, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x4e, + 0x40, + 0x00, + 0x00, + 0x1e, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x4e, + 0x41, + 0x00, + 0x00, + 0x1e, + 0x40, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x4e, + 0x42, + 0x00, + 0x00, + 0x1e, + 0x41, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x4e, + 0x43, + 0x00, + 0x00, + 0x1e, + 0x42, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x4e, + 0x44, + 0x00, + 0x00, + 0x1e, + 0x43, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x4e, + 0x45, + 0x00, + 0x00, + 0x1e, + 0x44, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x4e, + 0x46, + 0x00, + 0x00, + 0x1e, + 0x45, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x4e, + 0x47, + 0x00, + 0x00, + 0x1e, + 0x46, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x4e, + 0x48, + 0x00, + 0x00, + 0x1e, + 0x47, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x4e, + 0x49, + 0x00, + 0x00, + 0x1e, + 0x48, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x4e, + 0x25, + 0x00, + 0x00, + 0x1e, + 0x49, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x4e, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x8c, + 0xce, + 0x48, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x74, + 0x62, + 0x4e, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x55, + 0xf6, + 0x53, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x62, + 0x8a, + 0x59, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x60, + 0x1e, + 0x5f, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x42, + 0xb2, + 0x64, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x41, + 0x46, + 0x6a, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x4d, + 0xda, + 0x6f, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x2f, + 0x6e, + 0x75, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0x16, + 0x02, + 0x7b, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0xfe, + 0x4a, + 0x80, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0x0e, + 0x15, + 0x83, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0xf7, + 0xde, + 0x85, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x11, + 0xa9, + 0x88, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0x02, + 0x73, + 0x8b, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xef, + 0x3c, + 0x8e, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xf5, + 0x06, + 0x91, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xe6, + 0xd0, + 0x93, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xdc, + 0x9a, + 0x96, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xd3, + 0x64, + 0x99, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xe2, + 0x2e, + 0x9c, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xcb, + 0xf8, + 0x9e, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xd2, + 0xc2, + 0xa1, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xc4, + 0x8c, + 0xa4, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xcb, + 0x56, + 0xa7, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xb4, + 0x20, + 0xaa, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xc4, + 0xea, + 0xac, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xba, + 0xb4, + 0xaf, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xb0, + 0x7e, + 0xb2, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa1, + 0x48, + 0xb5, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0xa7, + 0x12, + 0xb8, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x94, + 0xdc, + 0xba, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x85, + 0xa6, + 0xbd, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x9f, + 0x70, + 0xc0, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x88, + 0x3a, + 0xc3, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x98, + 0x04, + 0xc6, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, + 0x8b, + 0xce, + 0xc8, + 0x41, ]), }, }; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.2.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.2.ts index a7e8b8e085ac..c40a2bab07ca 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.2.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.2.ts @@ -13,1684 +13,33150 @@ export const TILE_DATA_1_2 = { rectangle: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x02, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, - 0x41, 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc4, 0x09, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x50, 0x09, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x35, 0x32, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x39, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x32, 0x34, 0x7d, 0x7d, 0x2c, 0x22, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, - 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, - 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, - 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, - 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, - 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, - 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, - 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, - 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, - 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, - 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, - 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, - 0x3a, 0x5b, 0x37, 0x2e, 0x36, 0x33, 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, 0x31, 0x31, - 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x31, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, - 0x39, 0x32, 0x32, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, - 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, - 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x35, - 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, - 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, - 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, - 0x03, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x02, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc4, + 0x09, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x50, + 0x09, + 0x00, + 0x00, + 0x50, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x32, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, ]), }, lineString: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x02, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa0, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, - 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, - 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, - 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, - 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, - 0x35, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, - 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, - 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, - 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, - 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, - 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, - 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, - 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, - 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, - 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, - 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, - 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, - 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x02, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa0, + 0x0a, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x0a, + 0x00, + 0x00, + 0x58, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, ]), }, lineStrings: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x02, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xab, 0xf1, 0xd2, 0x4d, 0x62, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x3d, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0xdc, 0x17, 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x32, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, 0x36, 0x38, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, - 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x37, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x30, - 0x35, 0x32, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, - 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, - 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, - 0x39, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, - 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x34, 0x31, 0x37, 0x37, 0x30, 0x36, 0x36, 0x32, 0x33, 0x32, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, - 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, - 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, - 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, - 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, - 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, - 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, - 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, - 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x69, 0x73, - 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, - 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, - 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, - 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, - 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, - 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x03, 0x00, 0xa7, 0xaa, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xa7, 0xaa, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, - 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, - 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, - 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x07, 0x00, 0x00, 0x1b, 0x06, 0x00, 0x00, 0x39, - 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x60, - 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x51, - 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0e, - 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0f, 0x06, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x21, - 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x90, - 0x07, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x0e, - 0x09, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x39, - 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0f, - 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x60, - 0x09, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x09, - 0x0a, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x51, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0d, - 0x0a, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x0c, - 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0f, - 0x09, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x21, 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x09, - 0x0b, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x4b, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0d, - 0x0b, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x60, - 0x0b, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x02, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x3e, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x3d, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x68, + 0x18, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x17, + 0x00, + 0x00, + 0x88, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x35, + 0x32, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x37, + 0x37, + 0x30, + 0x36, + 0x36, + 0x32, + 0x33, + 0x32, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x07, + 0x00, + 0x00, + 0x1b, + 0x06, + 0x00, + 0x00, + 0x39, + 0x07, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x39, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x51, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x0c, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0f, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x21, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x09, + 0x08, + 0x00, + 0x00, + 0x09, + 0x07, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x39, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x51, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x21, + 0x09, + 0x00, + 0x00, + 0x39, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x51, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0f, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0f, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x21, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x4b, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0f, + 0x0b, + 0x00, + 0x00, + 0x0e, ]), }, triangles: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x02, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x16, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, 0x54, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x31, 0x30, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x34, - 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x35, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, - 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, - 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x39, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x32, 0x30, 0x30, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x38, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x31, 0x38, 0x33, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, - 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, - 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, - 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x32, 0x35, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, - 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, - 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, - 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, - 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, - 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, - 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, - 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, - 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, - 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, - 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, - 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, - 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, - 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, - 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, - 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, - 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, - 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, - 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, - 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, - 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, - 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, - 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, - 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, - 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, - 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, - 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, - 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, - 0x03, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, - 0x05, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, - 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, - 0x08, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, - 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x4e, 0xa7, 0xaa, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0x03, 0x00, - 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, - 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, - 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, - 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, - 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, - 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, - 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, - 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, - 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, - 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, - 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, - 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, - 0x08, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x02, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x16, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x10, + 0x16, + 0x00, + 0x00, + 0x54, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x30, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x30, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x33, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x80, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, ]), }, cylinder: { flags: ImdlFlags.ContainsCurves, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x02, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xd6, 0xc5, 0x6d, - 0x34, 0x00, 0x00, 0xc0, 0x39, 0xd6, 0xc5, 0x6d, 0x34, 0x00, 0x00, 0xc0, 0x56, 0xc1, 0xa8, 0xa4, 0x4e, 0x00, 0x08, 0xc0, - 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0xaa, 0x3e, 0x57, 0x5b, - 0xb1, 0xff, 0x07, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd8, 0x3d, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x64, 0x3d, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x33, 0x33, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x39, 0x32, 0x38, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x33, 0x30, 0x34, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x39, - 0x30, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x33, 0x36, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, - 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x36, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x31, 0x36, 0x32, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, - 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x31, 0x36, 0x38, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x33, 0x32, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, - 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, - 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, - 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, - 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, - 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, - 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, - 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, - 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, - 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, - 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, - 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x34, 0x36, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x36, 0x2e, 0x31, 0x30, - 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x36, 0x2e, 0x31, 0x30, 0x34, - 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x39, 0x2e, 0x31, 0x35, 0x36, 0x37, - 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, - 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, - 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x32, - 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x33, 0x2e, - 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x2c, 0x22, 0x64, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, - 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x22, 0x3a, 0x35, 0x38, 0x34, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, - 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, - 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdd, 0xa2, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, - 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc5, 0xba, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, - 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0xdd, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, - 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, - 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0xd0, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, - 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0xba, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, - 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x13, 0x93, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x13, 0x6c, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, - 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0x45, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, - 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x2f, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, - 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x00, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, - 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0x22, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, - 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc5, 0x45, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, - 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdd, 0x5d, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, - 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x01, 0x00, 0x00, 0x23, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x26, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x26, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x26, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x26, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x26, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x26, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3a, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x26, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x26, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x26, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x26, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x26, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x26, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, - 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x50, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x52, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x54, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, - 0x56, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x58, 0x00, - 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x59, - 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, - 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x60, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, - 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, - 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x64, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, - 0x00, 0x64, 0x00, 0x00, 0x66, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, - 0x00, 0x00, 0x68, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, - 0x6a, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6c, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6d, - 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x70, 0x00, 0x00, 0x6f, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x72, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, - 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, 0x00, 0x00, 0x74, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, - 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, 0x76, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, - 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x78, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, - 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, - 0x7e, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x81, - 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x84, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x86, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, - 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, - 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, - 0x00, 0x8c, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, - 0x00, 0x00, 0x90, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x4b, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, - 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, - 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, - 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, - 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, - 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x03, - 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x02, - 0x22, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, - 0x21, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x03, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x01, - 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, - 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x03, - 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x02, - 0x1d, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x01, - 0x1c, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x01, - 0x1c, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x02, - 0x1b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x03, 0x1a, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x03, - 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x02, - 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, - 0x17, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x01, - 0x17, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x02, - 0x16, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x03, - 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x02, - 0x13, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, - 0x12, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x03, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x01, - 0x12, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, - 0x11, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x03, - 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x02, - 0x0e, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x01, - 0x0d, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x03, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x01, - 0x0d, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x02, - 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x03, 0x0b, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x03, - 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x02, - 0x09, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x03, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, - 0x27, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, - 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x02, - 0x27, 0x00, 0x00, 0x03, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, - 0x28, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x01, - 0x2a, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x03, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x02, - 0x2b, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x03, 0x2c, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x03, - 0x2d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x02, - 0x2c, 0x00, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x01, - 0x2d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x01, - 0x2f, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x02, - 0x30, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x03, - 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x02, - 0x31, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x01, - 0x32, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x01, - 0x34, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x02, - 0x35, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x03, 0x36, 0x00, 0x00, 0x00, - 0x35, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x03, - 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x02, - 0x36, 0x00, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x01, - 0x37, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x03, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x02, - 0x3a, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x03, 0x3b, 0x00, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x03, - 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x02, - 0x3b, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x01, - 0x3c, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x01, - 0x3e, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x02, - 0x3f, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x03, - 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, - 0x40, 0x00, 0x00, 0x03, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, - 0x41, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x03, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x01, - 0x43, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x02, - 0x44, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x03, 0x45, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x03, - 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x02, - 0x45, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x01, - 0x46, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x01, - 0x48, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, - 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x03, 0x4a, 0x00, 0x00, 0x4b, - 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, - 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, - 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, - 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, - 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, - 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, - 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, - 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, - 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, - 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, - 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, - 0x00, 0x00, 0x72, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, - 0x74, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, - 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7a, 0x00, 0x00, - 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, - 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, - 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, - 0x00, 0x00, 0x86, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, - 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8c, - 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8e, 0x00, 0x00, - 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, - 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, 0x01, 0x4b, 0x00, 0x00, 0x01, - 0x4a, 0x00, 0x00, 0x02, 0x4a, 0x00, 0x00, 0x03, 0x4d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x01, - 0x4d, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x02, - 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x03, 0x51, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x02, 0x51, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x02, 0x50, 0x00, 0x00, 0x03, - 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, - 0x52, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x01, - 0x54, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x03, 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x02, 0x57, 0x00, 0x00, 0x01, - 0x57, 0x00, 0x00, 0x01, 0x56, 0x00, 0x00, 0x02, 0x56, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x02, - 0x59, 0x00, 0x00, 0x01, 0x59, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x5b, 0x00, 0x00, 0x00, - 0x5a, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x01, 0x5b, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x00, 0x03, - 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x02, - 0x5c, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x01, - 0x5e, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, 0x03, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x01, - 0x61, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x03, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x02, - 0x63, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x02, 0x65, 0x00, 0x00, 0x01, 0x65, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x03, - 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x01, 0x67, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x02, - 0x66, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x01, 0x69, 0x00, 0x00, 0x01, - 0x68, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x02, 0x6b, 0x00, 0x00, 0x01, - 0x6b, 0x00, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x02, 0x6a, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x02, - 0x6d, 0x00, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x03, 0x6f, 0x00, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x01, 0x6f, 0x00, 0x00, 0x01, 0x6e, 0x00, 0x00, 0x02, 0x6e, 0x00, 0x00, 0x03, - 0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x02, - 0x70, 0x00, 0x00, 0x03, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x01, 0x73, 0x00, 0x00, 0x01, - 0x72, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x03, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x01, - 0x75, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x02, - 0x77, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x76, 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x01, 0x79, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x03, - 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x02, 0x7b, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x02, - 0x7a, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x01, 0x7d, 0x00, 0x00, 0x01, - 0x7c, 0x00, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, - 0x7f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, - 0x81, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x01, 0x83, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x02, 0x82, 0x00, 0x00, 0x03, - 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x02, 0x85, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x02, - 0x84, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x01, - 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x03, 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x02, 0x89, 0x00, 0x00, 0x01, - 0x89, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, 0x03, 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x02, - 0x8b, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x01, 0x8d, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x02, 0x8c, 0x00, 0x00, 0x03, - 0x8f, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00, 0x02, - 0x8e, 0x00, 0x00, 0x03, 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x01, 0x91, 0x00, 0x00, 0x01, - 0x90, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x03, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, - 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xe4, 0x9a, 0xd6, 0xa8, - 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, - 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, - 0xd6, 0xa8, 0xca, 0xb4, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, - 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, - 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, - 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xa8, 0xd6, 0x9a, 0xe4, - 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, - 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, - 0x9a, 0xe4, 0x8a, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, - 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, - 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, - 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x57, 0xd6, 0x4b, 0xca, - 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, - 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, - 0x4b, 0xca, 0x40, 0xbf, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, - 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, - 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, - 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, - 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, - 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, - 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x35, 0x4b, 0x40, 0x40, - 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, - 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, - 0x40, 0x40, 0x4b, 0x35, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, - 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, - 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, - 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, - 0x8a, 0x0a, 0x9a, 0x1b, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, - 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, - 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, - 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xbf, 0x40, 0xca, 0x4b, - 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, - 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, - 0xca, 0x4b, 0xd6, 0x57, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, - 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, - 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, - 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x32, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, - 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, - 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, - 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, - 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, - 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, - 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x22, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1d, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1c, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, - 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x15, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, 0x11, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x13, 0x00, 0x00, 0x10, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x32, 0x00, 0x00, 0x35, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x33, 0x00, 0x00, 0x36, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x39, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x43, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x43, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x46, 0x00, 0x00, 0x49, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x47, 0x00, 0x00, 0x25, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x24, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x00, 0x1e, 0x24, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x06, - 0x23, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x00, 0x1e, 0x23, 0x00, 0x00, 0x36, - 0x22, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x4e, 0x21, 0x00, 0x00, 0x1e, - 0x22, 0x00, 0x00, 0x36, 0x21, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x36, 0x22, 0x00, 0x00, 0x4e, - 0x20, 0x00, 0x00, 0x1e, 0x21, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x36, - 0x21, 0x00, 0x00, 0x4e, 0x1f, 0x00, 0x00, 0x1e, 0x20, 0x00, 0x00, 0x36, 0x1f, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x06, - 0x20, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x4e, 0x1e, 0x00, 0x00, 0x1e, 0x1f, 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x06, - 0x1e, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x36, 0x1f, 0x00, 0x00, 0x4e, 0x1d, 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x36, - 0x1d, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x06, 0x1e, 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x4e, 0x1c, 0x00, 0x00, 0x1e, - 0x1d, 0x00, 0x00, 0x36, 0x1c, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x36, 0x1d, 0x00, 0x00, 0x4e, - 0x1b, 0x00, 0x00, 0x1e, 0x1c, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, 0x06, 0x1b, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x36, - 0x1c, 0x00, 0x00, 0x4e, 0x1a, 0x00, 0x00, 0x1e, 0x1b, 0x00, 0x00, 0x36, 0x1a, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x06, - 0x1b, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, 0x4e, 0x19, 0x00, 0x00, 0x1e, 0x1a, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x06, - 0x19, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x36, 0x1a, 0x00, 0x00, 0x4e, 0x18, 0x00, 0x00, 0x1e, 0x19, 0x00, 0x00, 0x36, - 0x18, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x06, 0x19, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x4e, 0x17, 0x00, 0x00, 0x1e, - 0x18, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, 0x06, 0x17, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x4e, - 0x16, 0x00, 0x00, 0x1e, 0x17, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00, 0x06, 0x17, 0x00, 0x00, 0x36, - 0x17, 0x00, 0x00, 0x4e, 0x15, 0x00, 0x00, 0x1e, 0x16, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x06, - 0x16, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x4e, 0x14, 0x00, 0x00, 0x1e, 0x15, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x06, - 0x14, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x00, 0x1e, 0x14, 0x00, 0x00, 0x36, - 0x13, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x00, 0x1e, - 0x13, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x36, 0x13, 0x00, 0x00, 0x4e, - 0x11, 0x00, 0x00, 0x1e, 0x12, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x06, 0x11, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x36, - 0x12, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x1e, 0x11, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, - 0x11, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x4e, 0x0f, 0x00, 0x00, 0x1e, 0x10, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x06, - 0x0f, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x4e, 0x0e, 0x00, 0x00, 0x1e, 0x0f, 0x00, 0x00, 0x36, - 0x0e, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x06, 0x0f, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x4e, 0x0d, 0x00, 0x00, 0x1e, - 0x0e, 0x00, 0x00, 0x36, 0x0d, 0x00, 0x00, 0x06, 0x0d, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x36, 0x0e, 0x00, 0x00, 0x4e, - 0x0c, 0x00, 0x00, 0x1e, 0x0d, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x06, 0x0d, 0x00, 0x00, 0x36, - 0x0d, 0x00, 0x00, 0x4e, 0x0b, 0x00, 0x00, 0x1e, 0x0c, 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x06, - 0x0c, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, 0x4e, 0x0a, 0x00, 0x00, 0x1e, 0x0b, 0x00, 0x00, 0x36, 0x0a, 0x00, 0x00, 0x06, - 0x0a, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, 0x4e, 0x09, 0x00, 0x00, 0x1e, 0x0a, 0x00, 0x00, 0x36, - 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x36, 0x0a, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, - 0x09, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x36, 0x09, 0x00, 0x00, 0x4e, - 0x07, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, - 0x08, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, - 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, - 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, - 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, - 0x04, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, - 0x02, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x27, 0x00, 0x00, 0x1e, 0x25, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x06, - 0x27, 0x00, 0x00, 0x06, 0x25, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x4e, 0x28, 0x00, 0x00, 0x1e, 0x27, 0x00, 0x00, 0x36, - 0x28, 0x00, 0x00, 0x06, 0x28, 0x00, 0x00, 0x06, 0x27, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x4e, 0x29, 0x00, 0x00, 0x1e, - 0x28, 0x00, 0x00, 0x36, 0x29, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x06, 0x28, 0x00, 0x00, 0x36, 0x28, 0x00, 0x00, 0x4e, - 0x2a, 0x00, 0x00, 0x1e, 0x29, 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, 0x06, 0x2a, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x36, - 0x29, 0x00, 0x00, 0x4e, 0x2b, 0x00, 0x00, 0x1e, 0x2a, 0x00, 0x00, 0x36, 0x2b, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x06, - 0x2a, 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, 0x4e, 0x2c, 0x00, 0x00, 0x1e, 0x2b, 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x06, - 0x2c, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x36, 0x2b, 0x00, 0x00, 0x4e, 0x2d, 0x00, 0x00, 0x1e, 0x2c, 0x00, 0x00, 0x36, - 0x2d, 0x00, 0x00, 0x06, 0x2d, 0x00, 0x00, 0x06, 0x2c, 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x4e, 0x2e, 0x00, 0x00, 0x1e, - 0x2d, 0x00, 0x00, 0x36, 0x2e, 0x00, 0x00, 0x06, 0x2e, 0x00, 0x00, 0x06, 0x2d, 0x00, 0x00, 0x36, 0x2d, 0x00, 0x00, 0x4e, - 0x2f, 0x00, 0x00, 0x1e, 0x2e, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, 0x06, 0x2f, 0x00, 0x00, 0x06, 0x2e, 0x00, 0x00, 0x36, - 0x2e, 0x00, 0x00, 0x4e, 0x30, 0x00, 0x00, 0x1e, 0x2f, 0x00, 0x00, 0x36, 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, - 0x2f, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, 0x4e, 0x31, 0x00, 0x00, 0x1e, 0x30, 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, 0x06, - 0x31, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x36, 0x30, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x00, 0x1e, 0x31, 0x00, 0x00, 0x36, - 0x32, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x06, 0x31, 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, 0x4e, 0x33, 0x00, 0x00, 0x1e, - 0x32, 0x00, 0x00, 0x36, 0x33, 0x00, 0x00, 0x06, 0x33, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x36, 0x32, 0x00, 0x00, 0x4e, - 0x34, 0x00, 0x00, 0x1e, 0x33, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x06, 0x34, 0x00, 0x00, 0x06, 0x33, 0x00, 0x00, 0x36, - 0x33, 0x00, 0x00, 0x4e, 0x35, 0x00, 0x00, 0x1e, 0x34, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x06, 0x35, 0x00, 0x00, 0x06, - 0x34, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x4e, 0x36, 0x00, 0x00, 0x1e, 0x35, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x06, - 0x36, 0x00, 0x00, 0x06, 0x35, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x4e, 0x37, 0x00, 0x00, 0x1e, 0x36, 0x00, 0x00, 0x36, - 0x37, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x06, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x4e, 0x38, 0x00, 0x00, 0x1e, - 0x37, 0x00, 0x00, 0x36, 0x38, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x36, 0x37, 0x00, 0x00, 0x4e, - 0x39, 0x00, 0x00, 0x1e, 0x38, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x06, 0x39, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x36, - 0x38, 0x00, 0x00, 0x4e, 0x3a, 0x00, 0x00, 0x1e, 0x39, 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x06, 0x3a, 0x00, 0x00, 0x06, - 0x39, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x4e, 0x3b, 0x00, 0x00, 0x1e, 0x3a, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x06, - 0x3b, 0x00, 0x00, 0x06, 0x3a, 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x4e, 0x3c, 0x00, 0x00, 0x1e, 0x3b, 0x00, 0x00, 0x36, - 0x3c, 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x06, 0x3b, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x4e, 0x3d, 0x00, 0x00, 0x1e, - 0x3c, 0x00, 0x00, 0x36, 0x3d, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x36, 0x3c, 0x00, 0x00, 0x4e, - 0x3e, 0x00, 0x00, 0x1e, 0x3d, 0x00, 0x00, 0x36, 0x3e, 0x00, 0x00, 0x06, 0x3e, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x36, - 0x3d, 0x00, 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x1e, 0x3e, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x06, - 0x3e, 0x00, 0x00, 0x36, 0x3e, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x06, - 0x40, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, 0x4e, 0x41, 0x00, 0x00, 0x1e, 0x40, 0x00, 0x00, 0x36, - 0x41, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x4e, 0x42, 0x00, 0x00, 0x1e, - 0x41, 0x00, 0x00, 0x36, 0x42, 0x00, 0x00, 0x06, 0x42, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x36, 0x41, 0x00, 0x00, 0x4e, - 0x43, 0x00, 0x00, 0x1e, 0x42, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00, 0x06, 0x42, 0x00, 0x00, 0x36, - 0x42, 0x00, 0x00, 0x4e, 0x44, 0x00, 0x00, 0x1e, 0x43, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x06, - 0x43, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x4e, 0x45, 0x00, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x36, 0x45, 0x00, 0x00, 0x06, - 0x45, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, 0x4e, 0x46, 0x00, 0x00, 0x1e, 0x45, 0x00, 0x00, 0x36, - 0x46, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x06, 0x45, 0x00, 0x00, 0x36, 0x45, 0x00, 0x00, 0x4e, 0x47, 0x00, 0x00, 0x1e, - 0x46, 0x00, 0x00, 0x36, 0x47, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x36, 0x46, 0x00, 0x00, 0x4e, - 0x48, 0x00, 0x00, 0x1e, 0x47, 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x36, - 0x47, 0x00, 0x00, 0x4e, 0x49, 0x00, 0x00, 0x1e, 0x48, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x06, - 0x48, 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x4e, 0x25, 0x00, 0x00, 0x1e, 0x49, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x06, - 0x25, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x02, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x56, + 0xc1, + 0xa8, + 0xa4, + 0x4e, + 0x00, + 0x08, + 0xc0, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0xaa, + 0x3e, + 0x57, + 0x5b, + 0xb1, + 0xff, + 0x07, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd8, + 0x3d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x64, + 0x3d, + 0x00, + 0x00, + 0x28, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x33, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x30, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x36, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x36, + 0x32, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x31, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x30, + 0x33, + 0x32, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x39, + 0x2e, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x35, + 0x38, + 0x34, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x24, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x03, + 0x23, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x03, + 0x22, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x03, + 0x21, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x03, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x03, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x03, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x03, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x03, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x03, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x03, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x03, + 0x19, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x03, + 0x18, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x03, + 0x17, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x03, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x03, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x03, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x03, + 0x13, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x03, + 0x12, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x03, + 0x11, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x03, + 0x10, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x03, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x03, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x03, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x03, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x03, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x03, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x03, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x28, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x03, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x03, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x03, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x03, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x03, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x03, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x03, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x03, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x03, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x03, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x03, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x03, + 0x34, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x03, + 0x35, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x03, + 0x36, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x03, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x03, + 0x38, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x03, + 0x39, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x03, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x03, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x03, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x03, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x03, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x03, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x03, + 0x40, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x03, + 0x41, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x03, + 0x42, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x03, + 0x43, + 0x00, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x03, + 0x44, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x03, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x03, + 0x46, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x03, + 0x47, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x03, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x03, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4a, + 0x00, + 0x00, + 0x03, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4c, + 0x00, + 0x00, + 0x03, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4e, + 0x00, + 0x00, + 0x03, + 0x51, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x02, + 0x51, + 0x00, + 0x00, + 0x01, + 0x51, + 0x00, + 0x00, + 0x01, + 0x50, + 0x00, + 0x00, + 0x02, + 0x50, + 0x00, + 0x00, + 0x03, + 0x53, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x02, + 0x53, + 0x00, + 0x00, + 0x01, + 0x53, + 0x00, + 0x00, + 0x01, + 0x52, + 0x00, + 0x00, + 0x02, + 0x52, + 0x00, + 0x00, + 0x03, + 0x55, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x02, + 0x55, + 0x00, + 0x00, + 0x01, + 0x55, + 0x00, + 0x00, + 0x01, + 0x54, + 0x00, + 0x00, + 0x02, + 0x54, + 0x00, + 0x00, + 0x03, + 0x57, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x02, + 0x57, + 0x00, + 0x00, + 0x01, + 0x57, + 0x00, + 0x00, + 0x01, + 0x56, + 0x00, + 0x00, + 0x02, + 0x56, + 0x00, + 0x00, + 0x03, + 0x59, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x02, + 0x59, + 0x00, + 0x00, + 0x01, + 0x59, + 0x00, + 0x00, + 0x01, + 0x58, + 0x00, + 0x00, + 0x02, + 0x58, + 0x00, + 0x00, + 0x03, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5a, + 0x00, + 0x00, + 0x03, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5c, + 0x00, + 0x00, + 0x03, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5e, + 0x00, + 0x00, + 0x03, + 0x61, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x02, + 0x61, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00, + 0x00, + 0x01, + 0x60, + 0x00, + 0x00, + 0x02, + 0x60, + 0x00, + 0x00, + 0x03, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x02, + 0x63, + 0x00, + 0x00, + 0x01, + 0x63, + 0x00, + 0x00, + 0x01, + 0x62, + 0x00, + 0x00, + 0x02, + 0x62, + 0x00, + 0x00, + 0x03, + 0x65, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x02, + 0x65, + 0x00, + 0x00, + 0x01, + 0x65, + 0x00, + 0x00, + 0x01, + 0x64, + 0x00, + 0x00, + 0x02, + 0x64, + 0x00, + 0x00, + 0x03, + 0x67, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x02, + 0x67, + 0x00, + 0x00, + 0x01, + 0x67, + 0x00, + 0x00, + 0x01, + 0x66, + 0x00, + 0x00, + 0x02, + 0x66, + 0x00, + 0x00, + 0x03, + 0x69, + 0x00, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x02, + 0x69, + 0x00, + 0x00, + 0x01, + 0x69, + 0x00, + 0x00, + 0x01, + 0x68, + 0x00, + 0x00, + 0x02, + 0x68, + 0x00, + 0x00, + 0x03, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6a, + 0x00, + 0x00, + 0x03, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6c, + 0x00, + 0x00, + 0x03, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6e, + 0x00, + 0x00, + 0x03, + 0x71, + 0x00, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x02, + 0x71, + 0x00, + 0x00, + 0x01, + 0x71, + 0x00, + 0x00, + 0x01, + 0x70, + 0x00, + 0x00, + 0x02, + 0x70, + 0x00, + 0x00, + 0x03, + 0x73, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x02, + 0x73, + 0x00, + 0x00, + 0x01, + 0x73, + 0x00, + 0x00, + 0x01, + 0x72, + 0x00, + 0x00, + 0x02, + 0x72, + 0x00, + 0x00, + 0x03, + 0x75, + 0x00, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x02, + 0x75, + 0x00, + 0x00, + 0x01, + 0x75, + 0x00, + 0x00, + 0x01, + 0x74, + 0x00, + 0x00, + 0x02, + 0x74, + 0x00, + 0x00, + 0x03, + 0x77, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x02, + 0x77, + 0x00, + 0x00, + 0x01, + 0x77, + 0x00, + 0x00, + 0x01, + 0x76, + 0x00, + 0x00, + 0x02, + 0x76, + 0x00, + 0x00, + 0x03, + 0x79, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x02, + 0x79, + 0x00, + 0x00, + 0x01, + 0x79, + 0x00, + 0x00, + 0x01, + 0x78, + 0x00, + 0x00, + 0x02, + 0x78, + 0x00, + 0x00, + 0x03, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7a, + 0x00, + 0x00, + 0x03, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7c, + 0x00, + 0x00, + 0x03, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7e, + 0x00, + 0x00, + 0x03, + 0x81, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x02, + 0x81, + 0x00, + 0x00, + 0x01, + 0x81, + 0x00, + 0x00, + 0x01, + 0x80, + 0x00, + 0x00, + 0x02, + 0x80, + 0x00, + 0x00, + 0x03, + 0x83, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x02, + 0x83, + 0x00, + 0x00, + 0x01, + 0x83, + 0x00, + 0x00, + 0x01, + 0x82, + 0x00, + 0x00, + 0x02, + 0x82, + 0x00, + 0x00, + 0x03, + 0x85, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x02, + 0x85, + 0x00, + 0x00, + 0x01, + 0x85, + 0x00, + 0x00, + 0x01, + 0x84, + 0x00, + 0x00, + 0x02, + 0x84, + 0x00, + 0x00, + 0x03, + 0x87, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x02, + 0x87, + 0x00, + 0x00, + 0x01, + 0x87, + 0x00, + 0x00, + 0x01, + 0x86, + 0x00, + 0x00, + 0x02, + 0x86, + 0x00, + 0x00, + 0x03, + 0x89, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x02, + 0x89, + 0x00, + 0x00, + 0x01, + 0x89, + 0x00, + 0x00, + 0x01, + 0x88, + 0x00, + 0x00, + 0x02, + 0x88, + 0x00, + 0x00, + 0x03, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8a, + 0x00, + 0x00, + 0x03, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8c, + 0x00, + 0x00, + 0x03, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8e, + 0x00, + 0x00, + 0x03, + 0x91, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x02, + 0x91, + 0x00, + 0x00, + 0x01, + 0x91, + 0x00, + 0x00, + 0x01, + 0x90, + 0x00, + 0x00, + 0x02, + 0x90, + 0x00, + 0x00, + 0x03, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x23, + 0x00, + 0x00, + 0x1e, + 0x24, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x4e, + 0x22, + 0x00, + 0x00, + 0x1e, + 0x23, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x4e, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x22, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x4e, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x21, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x4e, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x20, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x4e, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x4e, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x4e, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x4e, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x4e, + 0x1a, + 0x00, + 0x00, + 0x1e, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x4e, + 0x19, + 0x00, + 0x00, + 0x1e, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x4e, + 0x18, + 0x00, + 0x00, + 0x1e, + 0x19, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x4e, + 0x17, + 0x00, + 0x00, + 0x1e, + 0x18, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x4e, + 0x16, + 0x00, + 0x00, + 0x1e, + 0x17, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x4e, + 0x15, + 0x00, + 0x00, + 0x1e, + 0x16, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x4e, + 0x14, + 0x00, + 0x00, + 0x1e, + 0x15, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x4e, + 0x13, + 0x00, + 0x00, + 0x1e, + 0x14, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x4e, + 0x12, + 0x00, + 0x00, + 0x1e, + 0x13, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x4e, + 0x11, + 0x00, + 0x00, + 0x1e, + 0x12, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x4e, + 0x10, + 0x00, + 0x00, + 0x1e, + 0x11, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x4e, + 0x0f, + 0x00, + 0x00, + 0x1e, + 0x10, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x4e, + 0x0e, + 0x00, + 0x00, + 0x1e, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x4e, + 0x0d, + 0x00, + 0x00, + 0x1e, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x4e, + 0x0c, + 0x00, + 0x00, + 0x1e, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x4e, + 0x0b, + 0x00, + 0x00, + 0x1e, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x4e, + 0x0a, + 0x00, + 0x00, + 0x1e, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x4e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x09, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x27, + 0x00, + 0x00, + 0x1e, + 0x25, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x4e, + 0x28, + 0x00, + 0x00, + 0x1e, + 0x27, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x4e, + 0x29, + 0x00, + 0x00, + 0x1e, + 0x28, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x4e, + 0x2a, + 0x00, + 0x00, + 0x1e, + 0x29, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x4e, + 0x2b, + 0x00, + 0x00, + 0x1e, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x4e, + 0x2c, + 0x00, + 0x00, + 0x1e, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x4e, + 0x2d, + 0x00, + 0x00, + 0x1e, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x4e, + 0x2e, + 0x00, + 0x00, + 0x1e, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x4e, + 0x2f, + 0x00, + 0x00, + 0x1e, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x4e, + 0x30, + 0x00, + 0x00, + 0x1e, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x4e, + 0x31, + 0x00, + 0x00, + 0x1e, + 0x30, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x4e, + 0x32, + 0x00, + 0x00, + 0x1e, + 0x31, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x4e, + 0x33, + 0x00, + 0x00, + 0x1e, + 0x32, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x4e, + 0x34, + 0x00, + 0x00, + 0x1e, + 0x33, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x4e, + 0x35, + 0x00, + 0x00, + 0x1e, + 0x34, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x4e, + 0x36, + 0x00, + 0x00, + 0x1e, + 0x35, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x4e, + 0x37, + 0x00, + 0x00, + 0x1e, + 0x36, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x4e, + 0x38, + 0x00, + 0x00, + 0x1e, + 0x37, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x4e, + 0x39, + 0x00, + 0x00, + 0x1e, + 0x38, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x4e, + 0x3a, + 0x00, + 0x00, + 0x1e, + 0x39, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x4e, + 0x3b, + 0x00, + 0x00, + 0x1e, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x4e, + 0x3c, + 0x00, + 0x00, + 0x1e, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x4e, + 0x3d, + 0x00, + 0x00, + 0x1e, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x4e, + 0x3e, + 0x00, + 0x00, + 0x1e, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x4e, + 0x3f, + 0x00, + 0x00, + 0x1e, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x4e, + 0x40, + 0x00, + 0x00, + 0x1e, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x4e, + 0x41, + 0x00, + 0x00, + 0x1e, + 0x40, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x4e, + 0x42, + 0x00, + 0x00, + 0x1e, + 0x41, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x4e, + 0x43, + 0x00, + 0x00, + 0x1e, + 0x42, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x4e, + 0x44, + 0x00, + 0x00, + 0x1e, + 0x43, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x4e, + 0x45, + 0x00, + 0x00, + 0x1e, + 0x44, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x4e, + 0x46, + 0x00, + 0x00, + 0x1e, + 0x45, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x4e, + 0x47, + 0x00, + 0x00, + 0x1e, + 0x46, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x4e, + 0x48, + 0x00, + 0x00, + 0x1e, + 0x47, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x4e, + 0x49, + 0x00, + 0x00, + 0x1e, + 0x48, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x4e, + 0x25, + 0x00, + 0x00, + 0x1e, + 0x49, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x4e, ]), }, }; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.3.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.3.ts index e078f35650bf..29267cdf7731 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.3.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.3.ts @@ -13,1684 +13,33150 @@ export const TILE_DATA_1_3 = { rectangle: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x03, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, - 0x41, 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc4, 0x09, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x50, 0x09, 0x00, 0x00, 0x50, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x35, 0x32, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x39, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x32, 0x34, 0x7d, 0x7d, 0x2c, 0x22, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, - 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, - 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, - 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, - 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, - 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, - 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, - 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, - 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, - 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, - 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, - 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, - 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, - 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, - 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, - 0x3a, 0x5b, 0x37, 0x2e, 0x36, 0x33, 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, 0x31, 0x31, - 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x31, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, - 0x39, 0x32, 0x32, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, - 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, - 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x35, - 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, - 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, - 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, - 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, - 0x03, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x03, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc4, + 0x09, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x50, + 0x09, + 0x00, + 0x00, + 0x50, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x32, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, ]), }, lineString: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x03, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa0, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, - 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, - 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, - 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, - 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, - 0x35, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, - 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, - 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, - 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, - 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, - 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, - 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, - 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, - 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, - 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, - 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, - 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, - 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x03, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa0, + 0x0a, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x0a, + 0x00, + 0x00, + 0x58, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, ]), }, lineStrings: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x03, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xab, 0xf1, 0xd2, 0x4d, 0x62, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x3d, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0xdc, 0x17, 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x32, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, 0x36, 0x38, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, - 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x37, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x30, - 0x35, 0x32, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, - 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, - 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, - 0x39, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, - 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x34, 0x31, 0x37, 0x37, 0x30, 0x36, 0x36, 0x32, 0x33, 0x32, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, - 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, - 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, - 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, - 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, - 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, - 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, - 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, - 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x69, 0x73, - 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, - 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, - 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, - 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, - 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, - 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x03, 0x00, 0xa7, 0xaa, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xa7, 0xaa, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, - 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, - 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, - 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x07, 0x00, 0x00, 0x1b, 0x06, 0x00, 0x00, 0x39, - 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x60, - 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x51, - 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0e, - 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0f, 0x06, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x21, - 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x90, - 0x07, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x0e, - 0x09, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x39, - 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0f, - 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x60, - 0x09, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x09, - 0x0a, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x51, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0d, - 0x0a, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x0c, - 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0f, - 0x09, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x21, 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x09, - 0x0b, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x4b, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0d, - 0x0b, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x60, - 0x0b, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x03, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x3e, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x3d, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x68, + 0x18, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x17, + 0x00, + 0x00, + 0x88, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x35, + 0x32, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x37, + 0x37, + 0x30, + 0x36, + 0x36, + 0x32, + 0x33, + 0x32, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x07, + 0x00, + 0x00, + 0x1b, + 0x06, + 0x00, + 0x00, + 0x39, + 0x07, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x39, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x51, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x0c, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0f, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x21, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x09, + 0x08, + 0x00, + 0x00, + 0x09, + 0x07, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x39, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x51, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x21, + 0x09, + 0x00, + 0x00, + 0x39, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x51, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0f, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0f, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x21, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x4b, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0f, + 0x0b, + 0x00, + 0x00, + 0x0e, ]), }, triangles: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x03, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc0, 0x16, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x10, 0x16, 0x00, 0x00, 0x54, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x31, 0x30, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x34, - 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x35, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, - 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, - 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, - 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x39, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x32, 0x30, 0x30, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x38, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x31, 0x38, 0x33, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, - 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, - 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, - 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x32, 0x35, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, - 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, - 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, - 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, - 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, - 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, - 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, - 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, - 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, - 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, - 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, - 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, - 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, - 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, - 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, - 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, - 0x65, 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, - 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, - 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, - 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, - 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, - 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, - 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, - 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, - 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, - 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, - 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, - 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, - 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, - 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, - 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, - 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, - 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, - 0x03, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, - 0x05, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, - 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, - 0x08, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, - 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x4e, 0xa7, 0xaa, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0x03, 0x00, - 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, - 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, - 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, - 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x06, - 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x1e, 0x01, 0x00, 0x00, 0x36, - 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, - 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, - 0x04, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, 0x04, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x06, - 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, - 0x03, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, - 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, - 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, - 0x06, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, - 0x08, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x03, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc0, + 0x16, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x10, + 0x16, + 0x00, + 0x00, + 0x54, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x30, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x39, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x30, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x33, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x80, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, ]), }, cylinder: { flags: ImdlFlags.ContainsCurves, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x03, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xd6, 0xc5, 0x6d, - 0x34, 0x00, 0x00, 0xc0, 0x39, 0xd6, 0xc5, 0x6d, 0x34, 0x00, 0x00, 0xc0, 0x56, 0xc1, 0xa8, 0xa4, 0x4e, 0x00, 0x08, 0xc0, - 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0xaa, 0x3e, 0x57, 0x5b, - 0xb1, 0xff, 0x07, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd8, 0x3d, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x64, 0x3d, 0x00, 0x00, 0x28, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x33, 0x33, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x39, 0x32, 0x38, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x33, 0x30, 0x34, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x39, - 0x30, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x33, 0x36, 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, - 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x36, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x31, 0x36, 0x32, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, - 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, - 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x31, 0x36, 0x38, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, - 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x30, 0x33, 0x32, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, - 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, - 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, - 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, - 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, - 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, - 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, - 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, 0x45, 0x64, 0x67, 0x65, - 0x73, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x50, 0x6f, 0x6c, 0x79, 0x6c, 0x69, 0x6e, 0x65, - 0x45, 0x64, 0x67, 0x65, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, - 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, - 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, - 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, - 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, - 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x34, 0x36, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x36, 0x2e, 0x31, 0x30, - 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x36, 0x2e, 0x31, 0x30, 0x34, - 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x39, 0x2e, 0x31, 0x35, 0x36, 0x37, - 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, - 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, - 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x32, - 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x33, 0x2e, - 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x2c, 0x22, 0x64, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, - 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, - 0x68, 0x22, 0x3a, 0x35, 0x38, 0x34, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, - 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, - 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, - 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdd, 0xa2, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, - 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc5, 0xba, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, - 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0xdd, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, - 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, - 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0xd0, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, - 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0xba, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, - 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x13, 0x93, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x13, 0x6c, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, - 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0x45, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, - 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x2f, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, - 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x00, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, - 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0x22, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, - 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc5, 0x45, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, - 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdd, 0x5d, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, - 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x01, 0x00, 0x00, 0x23, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x26, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x26, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x26, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x26, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x26, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x26, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3a, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x26, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x26, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x26, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x26, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x26, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x26, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, - 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x50, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, - 0x00, 0x50, 0x00, 0x00, 0x52, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, - 0x00, 0x00, 0x54, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, - 0x56, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x58, 0x00, - 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x59, - 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, - 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x60, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, - 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, - 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x64, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, - 0x00, 0x64, 0x00, 0x00, 0x66, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, - 0x00, 0x00, 0x68, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, - 0x6a, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6c, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6d, - 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x70, 0x00, 0x00, 0x6f, 0x00, 0x00, - 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x72, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, - 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, 0x00, 0x00, 0x74, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, - 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, 0x76, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, - 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x78, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, - 0x00, 0x78, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, - 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, - 0x7e, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x81, - 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x84, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x86, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, - 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, - 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, - 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, - 0x00, 0x8c, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, - 0x00, 0x00, 0x90, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, - 0x4b, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, - 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, - 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, - 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, - 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, - 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x03, - 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x02, - 0x22, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, - 0x21, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x03, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x01, - 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, - 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x03, - 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x02, - 0x1d, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x01, - 0x1c, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x01, - 0x1c, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x02, - 0x1b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x03, 0x1a, 0x00, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x03, - 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x02, - 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, - 0x17, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x01, - 0x17, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x02, - 0x16, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x03, - 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x02, - 0x13, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, - 0x12, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x03, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x01, - 0x12, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, - 0x11, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x03, - 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x02, - 0x0e, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x01, - 0x0d, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x03, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x01, - 0x0d, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x02, - 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x03, 0x0b, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x03, - 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x02, - 0x09, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x03, - 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, - 0x27, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, - 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x02, - 0x27, 0x00, 0x00, 0x03, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, - 0x28, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x01, - 0x2a, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x03, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x02, - 0x2b, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x03, 0x2c, 0x00, 0x00, 0x00, - 0x2b, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x03, - 0x2d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x02, - 0x2c, 0x00, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x01, - 0x2d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x01, - 0x2f, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x02, - 0x30, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x03, - 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x02, - 0x31, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x01, - 0x32, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x01, - 0x34, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x02, - 0x35, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x03, 0x36, 0x00, 0x00, 0x00, - 0x35, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x03, - 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x02, - 0x36, 0x00, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x01, - 0x37, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x03, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x02, - 0x3a, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x03, 0x3b, 0x00, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x03, - 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x02, - 0x3b, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x01, - 0x3c, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x01, - 0x3e, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x02, - 0x3f, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x03, - 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, - 0x40, 0x00, 0x00, 0x03, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, - 0x41, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x03, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x01, - 0x43, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x02, - 0x44, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x03, 0x45, 0x00, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x03, - 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x02, - 0x45, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x01, - 0x46, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x01, - 0x48, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, - 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x03, 0x4a, 0x00, 0x00, 0x4b, - 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, - 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, - 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, - 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, - 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, - 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, - 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, - 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, - 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, - 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, - 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, - 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, - 0x00, 0x00, 0x72, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, - 0x74, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, - 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, - 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7a, 0x00, 0x00, - 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, - 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, - 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, - 0x00, 0x00, 0x86, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, - 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8c, - 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8e, 0x00, 0x00, - 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, - 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, 0x01, 0x4b, 0x00, 0x00, 0x01, - 0x4a, 0x00, 0x00, 0x02, 0x4a, 0x00, 0x00, 0x03, 0x4d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x01, - 0x4d, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x02, - 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x03, 0x51, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x02, 0x51, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x02, 0x50, 0x00, 0x00, 0x03, - 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, - 0x52, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x01, - 0x54, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x03, 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x02, 0x57, 0x00, 0x00, 0x01, - 0x57, 0x00, 0x00, 0x01, 0x56, 0x00, 0x00, 0x02, 0x56, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x02, - 0x59, 0x00, 0x00, 0x01, 0x59, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x5b, 0x00, 0x00, 0x00, - 0x5a, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x01, 0x5b, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x00, 0x03, - 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x02, - 0x5c, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x01, - 0x5e, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, 0x03, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x01, - 0x61, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x03, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x02, - 0x63, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x02, 0x65, 0x00, 0x00, 0x01, 0x65, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x03, - 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x01, 0x67, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x02, - 0x66, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x01, 0x69, 0x00, 0x00, 0x01, - 0x68, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x02, 0x6b, 0x00, 0x00, 0x01, - 0x6b, 0x00, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x02, 0x6a, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x02, - 0x6d, 0x00, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x03, 0x6f, 0x00, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x01, 0x6f, 0x00, 0x00, 0x01, 0x6e, 0x00, 0x00, 0x02, 0x6e, 0x00, 0x00, 0x03, - 0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x02, - 0x70, 0x00, 0x00, 0x03, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x01, 0x73, 0x00, 0x00, 0x01, - 0x72, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x03, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x01, - 0x75, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x02, - 0x77, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x76, 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x01, 0x79, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x03, - 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x02, 0x7b, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x02, - 0x7a, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x01, 0x7d, 0x00, 0x00, 0x01, - 0x7c, 0x00, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, - 0x7f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, - 0x81, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x01, 0x83, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x02, 0x82, 0x00, 0x00, 0x03, - 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x02, 0x85, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x02, - 0x84, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x01, - 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x03, 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x02, 0x89, 0x00, 0x00, 0x01, - 0x89, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, 0x03, 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x02, - 0x8b, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x01, 0x8d, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x02, 0x8c, 0x00, 0x00, 0x03, - 0x8f, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00, 0x02, - 0x8e, 0x00, 0x00, 0x03, 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x01, 0x91, 0x00, 0x00, 0x01, - 0x90, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x03, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, - 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xe4, 0x9a, 0xd6, 0xa8, - 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, - 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, - 0xd6, 0xa8, 0xca, 0xb4, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, - 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, - 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, - 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xa8, 0xd6, 0x9a, 0xe4, - 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, - 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, - 0x9a, 0xe4, 0x8a, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, - 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, - 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, - 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x57, 0xd6, 0x4b, 0xca, - 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, - 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, - 0x4b, 0xca, 0x40, 0xbf, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, - 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, - 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, - 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, - 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, - 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, - 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x35, 0x4b, 0x40, 0x40, - 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, - 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, - 0x40, 0x40, 0x4b, 0x35, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, - 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, - 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, - 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, - 0x8a, 0x0a, 0x9a, 0x1b, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, - 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, - 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, - 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xbf, 0x40, 0xca, 0x4b, - 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, - 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, - 0xca, 0x4b, 0xd6, 0x57, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, - 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, - 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, - 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, - 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, - 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, - 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x32, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, - 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, - 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, - 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, - 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, - 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, - 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, - 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, - 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, - 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x22, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1d, - 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1c, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, - 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x15, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, - 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, 0x11, 0x00, 0x00, 0x14, 0x00, - 0x00, 0x14, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x13, 0x00, 0x00, 0x10, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x24, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2d, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2e, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x31, 0x00, - 0x00, 0x31, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x32, 0x00, 0x00, 0x35, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, - 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x33, 0x00, 0x00, 0x36, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x37, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x36, 0x00, 0x00, 0x39, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x38, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x41, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x43, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x42, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x43, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, 0x00, 0x45, 0x00, - 0x00, 0x45, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x46, 0x00, 0x00, 0x49, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x47, 0x00, 0x00, 0x25, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x24, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x00, 0x1e, 0x24, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x06, - 0x23, 0x00, 0x00, 0x06, 0x24, 0x00, 0x00, 0x36, 0x24, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x00, 0x1e, 0x23, 0x00, 0x00, 0x36, - 0x22, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x06, 0x23, 0x00, 0x00, 0x36, 0x23, 0x00, 0x00, 0x4e, 0x21, 0x00, 0x00, 0x1e, - 0x22, 0x00, 0x00, 0x36, 0x21, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x06, 0x22, 0x00, 0x00, 0x36, 0x22, 0x00, 0x00, 0x4e, - 0x20, 0x00, 0x00, 0x1e, 0x21, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x06, 0x21, 0x00, 0x00, 0x36, - 0x21, 0x00, 0x00, 0x4e, 0x1f, 0x00, 0x00, 0x1e, 0x20, 0x00, 0x00, 0x36, 0x1f, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x06, - 0x20, 0x00, 0x00, 0x36, 0x20, 0x00, 0x00, 0x4e, 0x1e, 0x00, 0x00, 0x1e, 0x1f, 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x06, - 0x1e, 0x00, 0x00, 0x06, 0x1f, 0x00, 0x00, 0x36, 0x1f, 0x00, 0x00, 0x4e, 0x1d, 0x00, 0x00, 0x1e, 0x1e, 0x00, 0x00, 0x36, - 0x1d, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x06, 0x1e, 0x00, 0x00, 0x36, 0x1e, 0x00, 0x00, 0x4e, 0x1c, 0x00, 0x00, 0x1e, - 0x1d, 0x00, 0x00, 0x36, 0x1c, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x06, 0x1d, 0x00, 0x00, 0x36, 0x1d, 0x00, 0x00, 0x4e, - 0x1b, 0x00, 0x00, 0x1e, 0x1c, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, 0x06, 0x1b, 0x00, 0x00, 0x06, 0x1c, 0x00, 0x00, 0x36, - 0x1c, 0x00, 0x00, 0x4e, 0x1a, 0x00, 0x00, 0x1e, 0x1b, 0x00, 0x00, 0x36, 0x1a, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x06, - 0x1b, 0x00, 0x00, 0x36, 0x1b, 0x00, 0x00, 0x4e, 0x19, 0x00, 0x00, 0x1e, 0x1a, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x06, - 0x19, 0x00, 0x00, 0x06, 0x1a, 0x00, 0x00, 0x36, 0x1a, 0x00, 0x00, 0x4e, 0x18, 0x00, 0x00, 0x1e, 0x19, 0x00, 0x00, 0x36, - 0x18, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x06, 0x19, 0x00, 0x00, 0x36, 0x19, 0x00, 0x00, 0x4e, 0x17, 0x00, 0x00, 0x1e, - 0x18, 0x00, 0x00, 0x36, 0x17, 0x00, 0x00, 0x06, 0x17, 0x00, 0x00, 0x06, 0x18, 0x00, 0x00, 0x36, 0x18, 0x00, 0x00, 0x4e, - 0x16, 0x00, 0x00, 0x1e, 0x17, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x06, 0x16, 0x00, 0x00, 0x06, 0x17, 0x00, 0x00, 0x36, - 0x17, 0x00, 0x00, 0x4e, 0x15, 0x00, 0x00, 0x1e, 0x16, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x06, - 0x16, 0x00, 0x00, 0x36, 0x16, 0x00, 0x00, 0x4e, 0x14, 0x00, 0x00, 0x1e, 0x15, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x06, - 0x14, 0x00, 0x00, 0x06, 0x15, 0x00, 0x00, 0x36, 0x15, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x00, 0x1e, 0x14, 0x00, 0x00, 0x36, - 0x13, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x06, 0x14, 0x00, 0x00, 0x36, 0x14, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x00, 0x1e, - 0x13, 0x00, 0x00, 0x36, 0x12, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x06, 0x13, 0x00, 0x00, 0x36, 0x13, 0x00, 0x00, 0x4e, - 0x11, 0x00, 0x00, 0x1e, 0x12, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x06, 0x11, 0x00, 0x00, 0x06, 0x12, 0x00, 0x00, 0x36, - 0x12, 0x00, 0x00, 0x4e, 0x10, 0x00, 0x00, 0x1e, 0x11, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x06, - 0x11, 0x00, 0x00, 0x36, 0x11, 0x00, 0x00, 0x4e, 0x0f, 0x00, 0x00, 0x1e, 0x10, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x06, - 0x0f, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00, 0x36, 0x10, 0x00, 0x00, 0x4e, 0x0e, 0x00, 0x00, 0x1e, 0x0f, 0x00, 0x00, 0x36, - 0x0e, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x06, 0x0f, 0x00, 0x00, 0x36, 0x0f, 0x00, 0x00, 0x4e, 0x0d, 0x00, 0x00, 0x1e, - 0x0e, 0x00, 0x00, 0x36, 0x0d, 0x00, 0x00, 0x06, 0x0d, 0x00, 0x00, 0x06, 0x0e, 0x00, 0x00, 0x36, 0x0e, 0x00, 0x00, 0x4e, - 0x0c, 0x00, 0x00, 0x1e, 0x0d, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00, 0x06, 0x0d, 0x00, 0x00, 0x36, - 0x0d, 0x00, 0x00, 0x4e, 0x0b, 0x00, 0x00, 0x1e, 0x0c, 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x06, - 0x0c, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, 0x4e, 0x0a, 0x00, 0x00, 0x1e, 0x0b, 0x00, 0x00, 0x36, 0x0a, 0x00, 0x00, 0x06, - 0x0a, 0x00, 0x00, 0x06, 0x0b, 0x00, 0x00, 0x36, 0x0b, 0x00, 0x00, 0x4e, 0x09, 0x00, 0x00, 0x1e, 0x0a, 0x00, 0x00, 0x36, - 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, 0x0a, 0x00, 0x00, 0x36, 0x0a, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x1e, - 0x09, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x36, 0x09, 0x00, 0x00, 0x4e, - 0x07, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x06, 0x07, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x36, - 0x08, 0x00, 0x00, 0x4e, 0x06, 0x00, 0x00, 0x1e, 0x07, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, - 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x06, - 0x05, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x4e, 0x04, 0x00, 0x00, 0x1e, 0x05, 0x00, 0x00, 0x36, - 0x04, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x36, 0x05, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x00, 0x1e, - 0x04, 0x00, 0x00, 0x36, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x4e, - 0x02, 0x00, 0x00, 0x1e, 0x03, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x36, - 0x03, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x4e, 0x27, 0x00, 0x00, 0x1e, 0x25, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x06, - 0x27, 0x00, 0x00, 0x06, 0x25, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x4e, 0x28, 0x00, 0x00, 0x1e, 0x27, 0x00, 0x00, 0x36, - 0x28, 0x00, 0x00, 0x06, 0x28, 0x00, 0x00, 0x06, 0x27, 0x00, 0x00, 0x36, 0x27, 0x00, 0x00, 0x4e, 0x29, 0x00, 0x00, 0x1e, - 0x28, 0x00, 0x00, 0x36, 0x29, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x06, 0x28, 0x00, 0x00, 0x36, 0x28, 0x00, 0x00, 0x4e, - 0x2a, 0x00, 0x00, 0x1e, 0x29, 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, 0x06, 0x2a, 0x00, 0x00, 0x06, 0x29, 0x00, 0x00, 0x36, - 0x29, 0x00, 0x00, 0x4e, 0x2b, 0x00, 0x00, 0x1e, 0x2a, 0x00, 0x00, 0x36, 0x2b, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x06, - 0x2a, 0x00, 0x00, 0x36, 0x2a, 0x00, 0x00, 0x4e, 0x2c, 0x00, 0x00, 0x1e, 0x2b, 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x06, - 0x2c, 0x00, 0x00, 0x06, 0x2b, 0x00, 0x00, 0x36, 0x2b, 0x00, 0x00, 0x4e, 0x2d, 0x00, 0x00, 0x1e, 0x2c, 0x00, 0x00, 0x36, - 0x2d, 0x00, 0x00, 0x06, 0x2d, 0x00, 0x00, 0x06, 0x2c, 0x00, 0x00, 0x36, 0x2c, 0x00, 0x00, 0x4e, 0x2e, 0x00, 0x00, 0x1e, - 0x2d, 0x00, 0x00, 0x36, 0x2e, 0x00, 0x00, 0x06, 0x2e, 0x00, 0x00, 0x06, 0x2d, 0x00, 0x00, 0x36, 0x2d, 0x00, 0x00, 0x4e, - 0x2f, 0x00, 0x00, 0x1e, 0x2e, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, 0x06, 0x2f, 0x00, 0x00, 0x06, 0x2e, 0x00, 0x00, 0x36, - 0x2e, 0x00, 0x00, 0x4e, 0x30, 0x00, 0x00, 0x1e, 0x2f, 0x00, 0x00, 0x36, 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, - 0x2f, 0x00, 0x00, 0x36, 0x2f, 0x00, 0x00, 0x4e, 0x31, 0x00, 0x00, 0x1e, 0x30, 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, 0x06, - 0x31, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x36, 0x30, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x00, 0x1e, 0x31, 0x00, 0x00, 0x36, - 0x32, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x06, 0x31, 0x00, 0x00, 0x36, 0x31, 0x00, 0x00, 0x4e, 0x33, 0x00, 0x00, 0x1e, - 0x32, 0x00, 0x00, 0x36, 0x33, 0x00, 0x00, 0x06, 0x33, 0x00, 0x00, 0x06, 0x32, 0x00, 0x00, 0x36, 0x32, 0x00, 0x00, 0x4e, - 0x34, 0x00, 0x00, 0x1e, 0x33, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x06, 0x34, 0x00, 0x00, 0x06, 0x33, 0x00, 0x00, 0x36, - 0x33, 0x00, 0x00, 0x4e, 0x35, 0x00, 0x00, 0x1e, 0x34, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x06, 0x35, 0x00, 0x00, 0x06, - 0x34, 0x00, 0x00, 0x36, 0x34, 0x00, 0x00, 0x4e, 0x36, 0x00, 0x00, 0x1e, 0x35, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x06, - 0x36, 0x00, 0x00, 0x06, 0x35, 0x00, 0x00, 0x36, 0x35, 0x00, 0x00, 0x4e, 0x37, 0x00, 0x00, 0x1e, 0x36, 0x00, 0x00, 0x36, - 0x37, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x06, 0x36, 0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x4e, 0x38, 0x00, 0x00, 0x1e, - 0x37, 0x00, 0x00, 0x36, 0x38, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x06, 0x37, 0x00, 0x00, 0x36, 0x37, 0x00, 0x00, 0x4e, - 0x39, 0x00, 0x00, 0x1e, 0x38, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x06, 0x39, 0x00, 0x00, 0x06, 0x38, 0x00, 0x00, 0x36, - 0x38, 0x00, 0x00, 0x4e, 0x3a, 0x00, 0x00, 0x1e, 0x39, 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x06, 0x3a, 0x00, 0x00, 0x06, - 0x39, 0x00, 0x00, 0x36, 0x39, 0x00, 0x00, 0x4e, 0x3b, 0x00, 0x00, 0x1e, 0x3a, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x06, - 0x3b, 0x00, 0x00, 0x06, 0x3a, 0x00, 0x00, 0x36, 0x3a, 0x00, 0x00, 0x4e, 0x3c, 0x00, 0x00, 0x1e, 0x3b, 0x00, 0x00, 0x36, - 0x3c, 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x06, 0x3b, 0x00, 0x00, 0x36, 0x3b, 0x00, 0x00, 0x4e, 0x3d, 0x00, 0x00, 0x1e, - 0x3c, 0x00, 0x00, 0x36, 0x3d, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x06, 0x3c, 0x00, 0x00, 0x36, 0x3c, 0x00, 0x00, 0x4e, - 0x3e, 0x00, 0x00, 0x1e, 0x3d, 0x00, 0x00, 0x36, 0x3e, 0x00, 0x00, 0x06, 0x3e, 0x00, 0x00, 0x06, 0x3d, 0x00, 0x00, 0x36, - 0x3d, 0x00, 0x00, 0x4e, 0x3f, 0x00, 0x00, 0x1e, 0x3e, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x06, - 0x3e, 0x00, 0x00, 0x36, 0x3e, 0x00, 0x00, 0x4e, 0x40, 0x00, 0x00, 0x1e, 0x3f, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x06, - 0x40, 0x00, 0x00, 0x06, 0x3f, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x00, 0x4e, 0x41, 0x00, 0x00, 0x1e, 0x40, 0x00, 0x00, 0x36, - 0x41, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x06, 0x40, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x4e, 0x42, 0x00, 0x00, 0x1e, - 0x41, 0x00, 0x00, 0x36, 0x42, 0x00, 0x00, 0x06, 0x42, 0x00, 0x00, 0x06, 0x41, 0x00, 0x00, 0x36, 0x41, 0x00, 0x00, 0x4e, - 0x43, 0x00, 0x00, 0x1e, 0x42, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x06, 0x43, 0x00, 0x00, 0x06, 0x42, 0x00, 0x00, 0x36, - 0x42, 0x00, 0x00, 0x4e, 0x44, 0x00, 0x00, 0x1e, 0x43, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x06, - 0x43, 0x00, 0x00, 0x36, 0x43, 0x00, 0x00, 0x4e, 0x45, 0x00, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x36, 0x45, 0x00, 0x00, 0x06, - 0x45, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x36, 0x44, 0x00, 0x00, 0x4e, 0x46, 0x00, 0x00, 0x1e, 0x45, 0x00, 0x00, 0x36, - 0x46, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x06, 0x45, 0x00, 0x00, 0x36, 0x45, 0x00, 0x00, 0x4e, 0x47, 0x00, 0x00, 0x1e, - 0x46, 0x00, 0x00, 0x36, 0x47, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x06, 0x46, 0x00, 0x00, 0x36, 0x46, 0x00, 0x00, 0x4e, - 0x48, 0x00, 0x00, 0x1e, 0x47, 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x06, 0x47, 0x00, 0x00, 0x36, - 0x47, 0x00, 0x00, 0x4e, 0x49, 0x00, 0x00, 0x1e, 0x48, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x06, - 0x48, 0x00, 0x00, 0x36, 0x48, 0x00, 0x00, 0x4e, 0x25, 0x00, 0x00, 0x1e, 0x49, 0x00, 0x00, 0x36, 0x25, 0x00, 0x00, 0x06, - 0x25, 0x00, 0x00, 0x06, 0x49, 0x00, 0x00, 0x36, 0x49, 0x00, 0x00, 0x4e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x03, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x56, + 0xc1, + 0xa8, + 0xa4, + 0x4e, + 0x00, + 0x08, + 0xc0, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0xaa, + 0x3e, + 0x57, + 0x5b, + 0xb1, + 0xff, + 0x07, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd8, + 0x3d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x64, + 0x3d, + 0x00, + 0x00, + 0x28, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x33, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x30, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x36, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x31, + 0x36, + 0x32, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x31, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x30, + 0x33, + 0x32, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x50, + 0x6f, + 0x6c, + 0x79, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x45, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x39, + 0x2e, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x35, + 0x38, + 0x34, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x24, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x03, + 0x23, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x03, + 0x22, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x03, + 0x21, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x03, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x03, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x03, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x03, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x03, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x03, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x03, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x03, + 0x19, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x03, + 0x18, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x03, + 0x17, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x03, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x03, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x03, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x03, + 0x13, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x03, + 0x12, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x03, + 0x11, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x03, + 0x10, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x03, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x03, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x03, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x03, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x03, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x03, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x03, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x28, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x03, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x03, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x03, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x03, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x03, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x03, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x03, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x03, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x03, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x03, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x03, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x03, + 0x34, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x03, + 0x35, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x03, + 0x36, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x03, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x03, + 0x38, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x03, + 0x39, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x03, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x03, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x03, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x03, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x03, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x03, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x03, + 0x40, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x03, + 0x41, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x03, + 0x42, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x03, + 0x43, + 0x00, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x03, + 0x44, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x03, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x03, + 0x46, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x03, + 0x47, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x03, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x03, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4a, + 0x00, + 0x00, + 0x03, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4c, + 0x00, + 0x00, + 0x03, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4e, + 0x00, + 0x00, + 0x03, + 0x51, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x02, + 0x51, + 0x00, + 0x00, + 0x01, + 0x51, + 0x00, + 0x00, + 0x01, + 0x50, + 0x00, + 0x00, + 0x02, + 0x50, + 0x00, + 0x00, + 0x03, + 0x53, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x02, + 0x53, + 0x00, + 0x00, + 0x01, + 0x53, + 0x00, + 0x00, + 0x01, + 0x52, + 0x00, + 0x00, + 0x02, + 0x52, + 0x00, + 0x00, + 0x03, + 0x55, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x02, + 0x55, + 0x00, + 0x00, + 0x01, + 0x55, + 0x00, + 0x00, + 0x01, + 0x54, + 0x00, + 0x00, + 0x02, + 0x54, + 0x00, + 0x00, + 0x03, + 0x57, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x02, + 0x57, + 0x00, + 0x00, + 0x01, + 0x57, + 0x00, + 0x00, + 0x01, + 0x56, + 0x00, + 0x00, + 0x02, + 0x56, + 0x00, + 0x00, + 0x03, + 0x59, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x02, + 0x59, + 0x00, + 0x00, + 0x01, + 0x59, + 0x00, + 0x00, + 0x01, + 0x58, + 0x00, + 0x00, + 0x02, + 0x58, + 0x00, + 0x00, + 0x03, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5a, + 0x00, + 0x00, + 0x03, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5c, + 0x00, + 0x00, + 0x03, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5e, + 0x00, + 0x00, + 0x03, + 0x61, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x02, + 0x61, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00, + 0x00, + 0x01, + 0x60, + 0x00, + 0x00, + 0x02, + 0x60, + 0x00, + 0x00, + 0x03, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x02, + 0x63, + 0x00, + 0x00, + 0x01, + 0x63, + 0x00, + 0x00, + 0x01, + 0x62, + 0x00, + 0x00, + 0x02, + 0x62, + 0x00, + 0x00, + 0x03, + 0x65, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x02, + 0x65, + 0x00, + 0x00, + 0x01, + 0x65, + 0x00, + 0x00, + 0x01, + 0x64, + 0x00, + 0x00, + 0x02, + 0x64, + 0x00, + 0x00, + 0x03, + 0x67, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x02, + 0x67, + 0x00, + 0x00, + 0x01, + 0x67, + 0x00, + 0x00, + 0x01, + 0x66, + 0x00, + 0x00, + 0x02, + 0x66, + 0x00, + 0x00, + 0x03, + 0x69, + 0x00, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x02, + 0x69, + 0x00, + 0x00, + 0x01, + 0x69, + 0x00, + 0x00, + 0x01, + 0x68, + 0x00, + 0x00, + 0x02, + 0x68, + 0x00, + 0x00, + 0x03, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6a, + 0x00, + 0x00, + 0x03, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6c, + 0x00, + 0x00, + 0x03, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6e, + 0x00, + 0x00, + 0x03, + 0x71, + 0x00, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x02, + 0x71, + 0x00, + 0x00, + 0x01, + 0x71, + 0x00, + 0x00, + 0x01, + 0x70, + 0x00, + 0x00, + 0x02, + 0x70, + 0x00, + 0x00, + 0x03, + 0x73, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x02, + 0x73, + 0x00, + 0x00, + 0x01, + 0x73, + 0x00, + 0x00, + 0x01, + 0x72, + 0x00, + 0x00, + 0x02, + 0x72, + 0x00, + 0x00, + 0x03, + 0x75, + 0x00, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x02, + 0x75, + 0x00, + 0x00, + 0x01, + 0x75, + 0x00, + 0x00, + 0x01, + 0x74, + 0x00, + 0x00, + 0x02, + 0x74, + 0x00, + 0x00, + 0x03, + 0x77, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x02, + 0x77, + 0x00, + 0x00, + 0x01, + 0x77, + 0x00, + 0x00, + 0x01, + 0x76, + 0x00, + 0x00, + 0x02, + 0x76, + 0x00, + 0x00, + 0x03, + 0x79, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x02, + 0x79, + 0x00, + 0x00, + 0x01, + 0x79, + 0x00, + 0x00, + 0x01, + 0x78, + 0x00, + 0x00, + 0x02, + 0x78, + 0x00, + 0x00, + 0x03, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7a, + 0x00, + 0x00, + 0x03, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7c, + 0x00, + 0x00, + 0x03, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7e, + 0x00, + 0x00, + 0x03, + 0x81, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x02, + 0x81, + 0x00, + 0x00, + 0x01, + 0x81, + 0x00, + 0x00, + 0x01, + 0x80, + 0x00, + 0x00, + 0x02, + 0x80, + 0x00, + 0x00, + 0x03, + 0x83, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x02, + 0x83, + 0x00, + 0x00, + 0x01, + 0x83, + 0x00, + 0x00, + 0x01, + 0x82, + 0x00, + 0x00, + 0x02, + 0x82, + 0x00, + 0x00, + 0x03, + 0x85, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x02, + 0x85, + 0x00, + 0x00, + 0x01, + 0x85, + 0x00, + 0x00, + 0x01, + 0x84, + 0x00, + 0x00, + 0x02, + 0x84, + 0x00, + 0x00, + 0x03, + 0x87, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x02, + 0x87, + 0x00, + 0x00, + 0x01, + 0x87, + 0x00, + 0x00, + 0x01, + 0x86, + 0x00, + 0x00, + 0x02, + 0x86, + 0x00, + 0x00, + 0x03, + 0x89, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x02, + 0x89, + 0x00, + 0x00, + 0x01, + 0x89, + 0x00, + 0x00, + 0x01, + 0x88, + 0x00, + 0x00, + 0x02, + 0x88, + 0x00, + 0x00, + 0x03, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8a, + 0x00, + 0x00, + 0x03, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8c, + 0x00, + 0x00, + 0x03, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8e, + 0x00, + 0x00, + 0x03, + 0x91, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x02, + 0x91, + 0x00, + 0x00, + 0x01, + 0x91, + 0x00, + 0x00, + 0x01, + 0x90, + 0x00, + 0x00, + 0x02, + 0x90, + 0x00, + 0x00, + 0x03, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x23, + 0x00, + 0x00, + 0x1e, + 0x24, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x06, + 0x24, + 0x00, + 0x00, + 0x36, + 0x24, + 0x00, + 0x00, + 0x4e, + 0x22, + 0x00, + 0x00, + 0x1e, + 0x23, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x06, + 0x23, + 0x00, + 0x00, + 0x36, + 0x23, + 0x00, + 0x00, + 0x4e, + 0x21, + 0x00, + 0x00, + 0x1e, + 0x22, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x06, + 0x22, + 0x00, + 0x00, + 0x36, + 0x22, + 0x00, + 0x00, + 0x4e, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x21, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x06, + 0x21, + 0x00, + 0x00, + 0x36, + 0x21, + 0x00, + 0x00, + 0x4e, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x20, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x06, + 0x20, + 0x00, + 0x00, + 0x36, + 0x20, + 0x00, + 0x00, + 0x4e, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x06, + 0x1f, + 0x00, + 0x00, + 0x36, + 0x1f, + 0x00, + 0x00, + 0x4e, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x06, + 0x1e, + 0x00, + 0x00, + 0x36, + 0x1e, + 0x00, + 0x00, + 0x4e, + 0x1c, + 0x00, + 0x00, + 0x1e, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x06, + 0x1d, + 0x00, + 0x00, + 0x36, + 0x1d, + 0x00, + 0x00, + 0x4e, + 0x1b, + 0x00, + 0x00, + 0x1e, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x06, + 0x1c, + 0x00, + 0x00, + 0x36, + 0x1c, + 0x00, + 0x00, + 0x4e, + 0x1a, + 0x00, + 0x00, + 0x1e, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x06, + 0x1b, + 0x00, + 0x00, + 0x36, + 0x1b, + 0x00, + 0x00, + 0x4e, + 0x19, + 0x00, + 0x00, + 0x1e, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x06, + 0x1a, + 0x00, + 0x00, + 0x36, + 0x1a, + 0x00, + 0x00, + 0x4e, + 0x18, + 0x00, + 0x00, + 0x1e, + 0x19, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x06, + 0x19, + 0x00, + 0x00, + 0x36, + 0x19, + 0x00, + 0x00, + 0x4e, + 0x17, + 0x00, + 0x00, + 0x1e, + 0x18, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x06, + 0x18, + 0x00, + 0x00, + 0x36, + 0x18, + 0x00, + 0x00, + 0x4e, + 0x16, + 0x00, + 0x00, + 0x1e, + 0x17, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x06, + 0x17, + 0x00, + 0x00, + 0x36, + 0x17, + 0x00, + 0x00, + 0x4e, + 0x15, + 0x00, + 0x00, + 0x1e, + 0x16, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x06, + 0x16, + 0x00, + 0x00, + 0x36, + 0x16, + 0x00, + 0x00, + 0x4e, + 0x14, + 0x00, + 0x00, + 0x1e, + 0x15, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x06, + 0x15, + 0x00, + 0x00, + 0x36, + 0x15, + 0x00, + 0x00, + 0x4e, + 0x13, + 0x00, + 0x00, + 0x1e, + 0x14, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x06, + 0x14, + 0x00, + 0x00, + 0x36, + 0x14, + 0x00, + 0x00, + 0x4e, + 0x12, + 0x00, + 0x00, + 0x1e, + 0x13, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x06, + 0x13, + 0x00, + 0x00, + 0x36, + 0x13, + 0x00, + 0x00, + 0x4e, + 0x11, + 0x00, + 0x00, + 0x1e, + 0x12, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x06, + 0x12, + 0x00, + 0x00, + 0x36, + 0x12, + 0x00, + 0x00, + 0x4e, + 0x10, + 0x00, + 0x00, + 0x1e, + 0x11, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x06, + 0x11, + 0x00, + 0x00, + 0x36, + 0x11, + 0x00, + 0x00, + 0x4e, + 0x0f, + 0x00, + 0x00, + 0x1e, + 0x10, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x06, + 0x10, + 0x00, + 0x00, + 0x36, + 0x10, + 0x00, + 0x00, + 0x4e, + 0x0e, + 0x00, + 0x00, + 0x1e, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x06, + 0x0f, + 0x00, + 0x00, + 0x36, + 0x0f, + 0x00, + 0x00, + 0x4e, + 0x0d, + 0x00, + 0x00, + 0x1e, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x06, + 0x0e, + 0x00, + 0x00, + 0x36, + 0x0e, + 0x00, + 0x00, + 0x4e, + 0x0c, + 0x00, + 0x00, + 0x1e, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x06, + 0x0d, + 0x00, + 0x00, + 0x36, + 0x0d, + 0x00, + 0x00, + 0x4e, + 0x0b, + 0x00, + 0x00, + 0x1e, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x06, + 0x0c, + 0x00, + 0x00, + 0x36, + 0x0c, + 0x00, + 0x00, + 0x4e, + 0x0a, + 0x00, + 0x00, + 0x1e, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x06, + 0x0b, + 0x00, + 0x00, + 0x36, + 0x0b, + 0x00, + 0x00, + 0x4e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x0a, + 0x00, + 0x00, + 0x36, + 0x0a, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x1e, + 0x09, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x36, + 0x09, + 0x00, + 0x00, + 0x4e, + 0x07, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x4e, + 0x06, + 0x00, + 0x00, + 0x1e, + 0x07, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x06, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x05, + 0x00, + 0x00, + 0x1e, + 0x06, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x06, + 0x06, + 0x00, + 0x00, + 0x36, + 0x06, + 0x00, + 0x00, + 0x4e, + 0x04, + 0x00, + 0x00, + 0x1e, + 0x05, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x06, + 0x05, + 0x00, + 0x00, + 0x36, + 0x05, + 0x00, + 0x00, + 0x4e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x04, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x04, + 0x00, + 0x00, + 0x36, + 0x04, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x1e, + 0x03, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x36, + 0x03, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x4e, + 0x27, + 0x00, + 0x00, + 0x1e, + 0x25, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x4e, + 0x28, + 0x00, + 0x00, + 0x1e, + 0x27, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x06, + 0x27, + 0x00, + 0x00, + 0x36, + 0x27, + 0x00, + 0x00, + 0x4e, + 0x29, + 0x00, + 0x00, + 0x1e, + 0x28, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x06, + 0x28, + 0x00, + 0x00, + 0x36, + 0x28, + 0x00, + 0x00, + 0x4e, + 0x2a, + 0x00, + 0x00, + 0x1e, + 0x29, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x06, + 0x29, + 0x00, + 0x00, + 0x36, + 0x29, + 0x00, + 0x00, + 0x4e, + 0x2b, + 0x00, + 0x00, + 0x1e, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x06, + 0x2a, + 0x00, + 0x00, + 0x36, + 0x2a, + 0x00, + 0x00, + 0x4e, + 0x2c, + 0x00, + 0x00, + 0x1e, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x06, + 0x2b, + 0x00, + 0x00, + 0x36, + 0x2b, + 0x00, + 0x00, + 0x4e, + 0x2d, + 0x00, + 0x00, + 0x1e, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x06, + 0x2c, + 0x00, + 0x00, + 0x36, + 0x2c, + 0x00, + 0x00, + 0x4e, + 0x2e, + 0x00, + 0x00, + 0x1e, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x06, + 0x2d, + 0x00, + 0x00, + 0x36, + 0x2d, + 0x00, + 0x00, + 0x4e, + 0x2f, + 0x00, + 0x00, + 0x1e, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x06, + 0x2e, + 0x00, + 0x00, + 0x36, + 0x2e, + 0x00, + 0x00, + 0x4e, + 0x30, + 0x00, + 0x00, + 0x1e, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x06, + 0x2f, + 0x00, + 0x00, + 0x36, + 0x2f, + 0x00, + 0x00, + 0x4e, + 0x31, + 0x00, + 0x00, + 0x1e, + 0x30, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x06, + 0x30, + 0x00, + 0x00, + 0x36, + 0x30, + 0x00, + 0x00, + 0x4e, + 0x32, + 0x00, + 0x00, + 0x1e, + 0x31, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x06, + 0x31, + 0x00, + 0x00, + 0x36, + 0x31, + 0x00, + 0x00, + 0x4e, + 0x33, + 0x00, + 0x00, + 0x1e, + 0x32, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x06, + 0x32, + 0x00, + 0x00, + 0x36, + 0x32, + 0x00, + 0x00, + 0x4e, + 0x34, + 0x00, + 0x00, + 0x1e, + 0x33, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x06, + 0x33, + 0x00, + 0x00, + 0x36, + 0x33, + 0x00, + 0x00, + 0x4e, + 0x35, + 0x00, + 0x00, + 0x1e, + 0x34, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x06, + 0x34, + 0x00, + 0x00, + 0x36, + 0x34, + 0x00, + 0x00, + 0x4e, + 0x36, + 0x00, + 0x00, + 0x1e, + 0x35, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x06, + 0x35, + 0x00, + 0x00, + 0x36, + 0x35, + 0x00, + 0x00, + 0x4e, + 0x37, + 0x00, + 0x00, + 0x1e, + 0x36, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x06, + 0x36, + 0x00, + 0x00, + 0x36, + 0x36, + 0x00, + 0x00, + 0x4e, + 0x38, + 0x00, + 0x00, + 0x1e, + 0x37, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x06, + 0x37, + 0x00, + 0x00, + 0x36, + 0x37, + 0x00, + 0x00, + 0x4e, + 0x39, + 0x00, + 0x00, + 0x1e, + 0x38, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x06, + 0x38, + 0x00, + 0x00, + 0x36, + 0x38, + 0x00, + 0x00, + 0x4e, + 0x3a, + 0x00, + 0x00, + 0x1e, + 0x39, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x06, + 0x39, + 0x00, + 0x00, + 0x36, + 0x39, + 0x00, + 0x00, + 0x4e, + 0x3b, + 0x00, + 0x00, + 0x1e, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x06, + 0x3a, + 0x00, + 0x00, + 0x36, + 0x3a, + 0x00, + 0x00, + 0x4e, + 0x3c, + 0x00, + 0x00, + 0x1e, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x06, + 0x3b, + 0x00, + 0x00, + 0x36, + 0x3b, + 0x00, + 0x00, + 0x4e, + 0x3d, + 0x00, + 0x00, + 0x1e, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x06, + 0x3c, + 0x00, + 0x00, + 0x36, + 0x3c, + 0x00, + 0x00, + 0x4e, + 0x3e, + 0x00, + 0x00, + 0x1e, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x06, + 0x3d, + 0x00, + 0x00, + 0x36, + 0x3d, + 0x00, + 0x00, + 0x4e, + 0x3f, + 0x00, + 0x00, + 0x1e, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x06, + 0x3e, + 0x00, + 0x00, + 0x36, + 0x3e, + 0x00, + 0x00, + 0x4e, + 0x40, + 0x00, + 0x00, + 0x1e, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x06, + 0x3f, + 0x00, + 0x00, + 0x36, + 0x3f, + 0x00, + 0x00, + 0x4e, + 0x41, + 0x00, + 0x00, + 0x1e, + 0x40, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x06, + 0x40, + 0x00, + 0x00, + 0x36, + 0x40, + 0x00, + 0x00, + 0x4e, + 0x42, + 0x00, + 0x00, + 0x1e, + 0x41, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x06, + 0x41, + 0x00, + 0x00, + 0x36, + 0x41, + 0x00, + 0x00, + 0x4e, + 0x43, + 0x00, + 0x00, + 0x1e, + 0x42, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x06, + 0x42, + 0x00, + 0x00, + 0x36, + 0x42, + 0x00, + 0x00, + 0x4e, + 0x44, + 0x00, + 0x00, + 0x1e, + 0x43, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x06, + 0x43, + 0x00, + 0x00, + 0x36, + 0x43, + 0x00, + 0x00, + 0x4e, + 0x45, + 0x00, + 0x00, + 0x1e, + 0x44, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x06, + 0x44, + 0x00, + 0x00, + 0x36, + 0x44, + 0x00, + 0x00, + 0x4e, + 0x46, + 0x00, + 0x00, + 0x1e, + 0x45, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x06, + 0x45, + 0x00, + 0x00, + 0x36, + 0x45, + 0x00, + 0x00, + 0x4e, + 0x47, + 0x00, + 0x00, + 0x1e, + 0x46, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x06, + 0x46, + 0x00, + 0x00, + 0x36, + 0x46, + 0x00, + 0x00, + 0x4e, + 0x48, + 0x00, + 0x00, + 0x1e, + 0x47, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x06, + 0x47, + 0x00, + 0x00, + 0x36, + 0x47, + 0x00, + 0x00, + 0x4e, + 0x49, + 0x00, + 0x00, + 0x1e, + 0x48, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x06, + 0x48, + 0x00, + 0x00, + 0x36, + 0x48, + 0x00, + 0x00, + 0x4e, + 0x25, + 0x00, + 0x00, + 0x1e, + 0x49, + 0x00, + 0x00, + 0x36, + 0x25, + 0x00, + 0x00, + 0x06, + 0x25, + 0x00, + 0x00, + 0x06, + 0x49, + 0x00, + 0x00, + 0x36, + 0x49, + 0x00, + 0x00, + 0x4e, ]), }, }; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.4.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.4.ts index dffcef030b10..6eb5519fe4e6 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.4.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.1.4.ts @@ -13,1315 +13,25778 @@ export const TILE_DATA_1_4 = { rectangle: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, - 0x41, 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2c, 0x07, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0xb8, 0x06, 0x00, 0x00, 0xa8, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, - 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, - 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, - 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, - 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, - 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, - 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, - 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, - 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, - 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, - 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x34, 0x2c, - 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, - 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x36, - 0x33, 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, 0x31, 0x31, 0x65, 0x2d, 0x30, 0x35, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x31, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x32, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, - 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x32, 0x2e, 0x35, 0x30, 0x30, - 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, - 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, - 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, - 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, - 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, - 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, - 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, - 0x0a, 0x20, 0x20, 0x20, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xf8, 0xff, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x04, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x07, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xb8, + 0x06, + 0x00, + 0x00, + 0xa8, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x20, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, ]), }, lineString: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa0, 0x0a, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x2c, 0x0a, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, - 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, - 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, - 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, - 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, - 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, - 0x35, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, - 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, - 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, - 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, - 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, - 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, - 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, - 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, - 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, - 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, - 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, - 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, - 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, - 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, - 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x04, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa0, + 0x0a, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x0a, + 0x00, + 0x00, + 0x58, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, ]), }, lineStrings: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xab, 0xf1, 0xd2, 0x4d, 0x62, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x3d, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0x18, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x02, 0x00, 0x00, 0x00, 0xdc, 0x17, 0x00, 0x00, 0x88, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x32, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, 0x36, 0x38, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, - 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, - 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, - 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x37, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x30, - 0x35, 0x32, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, - 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, - 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, - 0x39, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, - 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, - 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, - 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, - 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x34, 0x31, 0x37, 0x37, 0x30, 0x36, 0x36, 0x32, 0x33, 0x32, 0x2c, 0x22, 0x6c, 0x69, - 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, - 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, - 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, - 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, - 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, - 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, - 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, - 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, - 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, - 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, - 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, - 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, - 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, - 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, - 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x69, 0x73, - 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, - 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, - 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, - 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, - 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, - 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, - 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, - 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, - 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, - 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x03, 0x00, 0xa7, 0xaa, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xa7, 0xaa, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, - 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, - 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, - 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, - 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, - 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, - 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, - 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x07, 0x00, 0x00, 0x1b, 0x06, 0x00, 0x00, 0x39, - 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x60, - 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x51, - 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0e, - 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0f, 0x06, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x21, - 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x90, - 0x07, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x0e, - 0x09, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x39, - 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x51, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0f, - 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x21, 0x09, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x60, - 0x09, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x09, - 0x0a, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x51, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0d, - 0x0a, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x0c, - 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0f, - 0x09, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x21, 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x09, - 0x0b, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x4b, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0d, - 0x0b, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x60, - 0x0b, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x04, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x3e, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x3d, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x68, + 0x18, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xdc, + 0x17, + 0x00, + 0x00, + 0x88, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x35, + 0x32, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x37, + 0x37, + 0x30, + 0x36, + 0x36, + 0x32, + 0x33, + 0x32, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x07, + 0x00, + 0x00, + 0x1b, + 0x06, + 0x00, + 0x00, + 0x39, + 0x07, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x39, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x51, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x0c, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0f, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x21, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x09, + 0x08, + 0x00, + 0x00, + 0x09, + 0x07, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x39, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x51, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x21, + 0x09, + 0x00, + 0x00, + 0x39, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x51, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0f, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0f, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x21, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x4b, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0f, + 0x0b, + 0x00, + 0x00, + 0x0e, ]), }, triangles: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x0f, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0xf4, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, - 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x35, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x33, 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, - 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x39, 0x31, 0x32, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x38, 0x34, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, - 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, - 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x34, 0x38, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x30, 0x7d, 0x7d, 0x2c, 0x22, - 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, - 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, - 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, - 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, - 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, - 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, - 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, - 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x66, - 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, - 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, - 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, - 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, - 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, - 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, - 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, - 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, - 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, - 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, - 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, - 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, - 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, - 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, - 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, - 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, - 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, - 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, - 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, - 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, - 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, - 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, - 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x65, 0x64, - 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, - 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, - 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, - 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, - 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, - 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, - 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, - 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, - 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x74, 0x72, 0x75, - 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, - 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, - 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, - 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, - 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, - 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, - 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, - 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, - 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, - 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, - 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, - 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, - 0x7d, 0x7d, 0x0a, 0x20, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xa7, 0xaa, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, - 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, - 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, - 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, - 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, - 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, - 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0xa7, 0xaa, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, - 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, - 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, - 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, - 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, - 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x04, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x0f, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0x70, + 0x0e, + 0x00, + 0x00, + 0xf4, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x80, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, ]), }, cylinder: { flags: ImdlFlags.ContainsCurves, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x04, 0x00, 0x01, 0x00, 0x54, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xd6, 0xc5, 0x6d, - 0x34, 0x00, 0x00, 0xc0, 0x39, 0xd6, 0xc5, 0x6d, 0x34, 0x00, 0x00, 0xc0, 0x56, 0xc1, 0xa8, 0xa4, 0x4e, 0x00, 0x08, 0xc0, - 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0xaa, 0x3e, 0x57, 0x5b, - 0xb1, 0xff, 0x07, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x44, 0x2b, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, - 0x02, 0x00, 0x00, 0x00, 0xd0, 0x2a, 0x00, 0x00, 0x74, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, - 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x33, 0x33, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x37, 0x32, 0x38, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x39, 0x32, 0x38, 0x7d, 0x2c, 0x22, - 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, - 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x33, 0x30, 0x34, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x36, 0x33, 0x32, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x34, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x36, - 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, - 0x33, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, - 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x31, 0x36, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, - 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, - 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, - 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, - 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, - 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, - 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x69, - 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, - 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, - 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, - 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, - 0x72, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, - 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, - 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, - 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, - 0x34, 0x36, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, - 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, - 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, - 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, - 0x36, 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, - 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x36, - 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, - 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x39, 0x2e, - 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x65, 0x2d, 0x30, 0x35, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x38, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, - 0x78, 0x22, 0x3a, 0x5b, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x37, 0x2c, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x37, 0x2c, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, - 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, - 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, - 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x7d, 0x2c, 0x22, 0x75, - 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, - 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x35, 0x38, 0x34, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, - 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, - 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, - 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, - 0x7d, 0x7d, 0x0a, 0x20, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x29, 0x11, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, - 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xdd, 0xa2, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, - 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xba, 0xc5, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, - 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa2, 0xdd, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, - 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0xec, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, - 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0xd0, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, - 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2f, 0xae, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, - 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x13, 0x93, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, - 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x5d, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, - 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3a, 0x45, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, - 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0x22, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, - 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0x00, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, - 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xae, 0x2f, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, - 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc5, 0x45, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, - 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xec, 0x6c, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, - 0x00, 0x00, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, - 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x26, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x26, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2a, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x26, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x26, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x26, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x26, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3c, - 0x00, 0x00, 0x3c, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3e, 0x00, 0x00, - 0x3e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x26, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x26, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x26, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x26, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x26, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x26, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x25, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4a, 0x00, 0x00, - 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, - 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x50, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x52, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, - 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x54, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, - 0x00, 0x54, 0x00, 0x00, 0x56, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, - 0x00, 0x00, 0x58, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, - 0x5a, 0x00, 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5c, 0x00, - 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5d, - 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x60, 0x00, 0x00, 0x5f, 0x00, 0x00, - 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x62, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x64, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, - 0x00, 0x00, 0x65, 0x00, 0x00, 0x64, 0x00, 0x00, 0x66, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, - 0x67, 0x00, 0x00, 0x66, 0x00, 0x00, 0x68, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, - 0x00, 0x68, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, - 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, - 0x6e, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x70, 0x00, - 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x72, 0x00, 0x00, 0x71, - 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, 0x00, 0x00, 0x74, 0x00, 0x00, 0x73, 0x00, 0x00, - 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, 0x76, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, - 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x78, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, - 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, - 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, - 0x00, 0x7c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, - 0x00, 0x00, 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, - 0x82, 0x00, 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x84, 0x00, - 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x86, 0x00, 0x00, 0x85, - 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, - 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, - 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, - 0x8f, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x90, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, - 0x00, 0x90, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, - 0x00, 0x21, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, - 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, - 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, - 0x00, 0x17, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, - 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, - 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, - 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, - 0x00, 0x0d, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, - 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, - 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, - 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, - 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, - 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, - 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, - 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, - 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, - 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, - 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, - 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, - 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, - 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, - 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, - 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x02, - 0x23, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x01, - 0x22, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x01, - 0x22, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x03, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, - 0x21, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, - 0x1f, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x03, - 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x02, - 0x1e, 0x00, 0x00, 0x03, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, - 0x1d, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x01, - 0x1d, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x03, 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x02, - 0x1c, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0x00, - 0x1a, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x03, - 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x02, - 0x19, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x01, - 0x18, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x01, - 0x18, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x03, 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x02, - 0x17, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x00, - 0x15, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x03, - 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x01, 0x15, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x02, - 0x14, 0x00, 0x00, 0x03, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x01, - 0x13, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x01, - 0x13, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x03, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x02, - 0x12, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, - 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x02, - 0x0f, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x01, - 0x0e, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x01, - 0x0e, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x03, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x02, - 0x0d, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x03, - 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, - 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01, - 0x09, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x01, - 0x09, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, - 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x00, - 0x25, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, - 0x49, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, - 0x25, 0x00, 0x00, 0x03, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, - 0x27, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, 0x03, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x01, - 0x29, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x03, 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x02, - 0x2a, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x03, 0x2b, 0x00, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x03, - 0x2c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x02, - 0x2b, 0x00, 0x00, 0x03, 0x2d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x01, - 0x2c, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x01, - 0x2e, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x03, 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x02, - 0x2f, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, - 0x2f, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x03, - 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x02, - 0x30, 0x00, 0x00, 0x03, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x01, - 0x31, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x01, - 0x33, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x03, 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x02, - 0x34, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x00, - 0x34, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x03, - 0x36, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x02, - 0x35, 0x00, 0x00, 0x03, 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x01, - 0x36, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x03, 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, - 0x39, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x03, 0x3a, 0x00, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x03, - 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x02, - 0x3a, 0x00, 0x00, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, - 0x3b, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x01, - 0x3d, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x02, - 0x3e, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x03, - 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x02, - 0x3f, 0x00, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01, - 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x42, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x01, - 0x42, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x03, 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x02, - 0x43, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, - 0x43, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x03, - 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x02, - 0x44, 0x00, 0x00, 0x03, 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, - 0x45, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x01, - 0x47, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x03, 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x02, - 0x48, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x03, - 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, - 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, - 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, - 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x54, - 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, - 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, - 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, - 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, - 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, - 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, - 0x00, 0x00, 0x62, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, - 0x64, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, - 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x68, - 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6a, 0x00, 0x00, - 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, - 0x00, 0x6d, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, - 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, - 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, - 0x00, 0x00, 0x76, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, - 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, - 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, - 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, - 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, - 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, - 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, - 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, - 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, 0x00, - 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, 0x01, - 0x4b, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x00, 0x02, 0x4a, 0x00, 0x00, 0x03, 0x4d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x02, - 0x4d, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x02, 0x4c, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x02, 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, 0x4e, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x03, - 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x02, 0x51, 0x00, 0x00, 0x01, 0x51, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x02, - 0x50, 0x00, 0x00, 0x03, 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x02, 0x53, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, - 0x52, 0x00, 0x00, 0x02, 0x52, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x01, - 0x55, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x03, 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x02, - 0x57, 0x00, 0x00, 0x01, 0x57, 0x00, 0x00, 0x01, 0x56, 0x00, 0x00, 0x02, 0x56, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x01, 0x59, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x03, - 0x5b, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x01, 0x5b, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x02, - 0x5a, 0x00, 0x00, 0x03, 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x02, 0x5d, 0x00, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x01, - 0x5c, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, - 0x5f, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, 0x03, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, - 0x61, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x02, 0x60, 0x00, 0x00, 0x03, 0x63, 0x00, 0x00, 0x00, - 0x62, 0x00, 0x00, 0x02, 0x63, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, 0x62, 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x03, - 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x02, 0x65, 0x00, 0x00, 0x01, 0x65, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x02, - 0x64, 0x00, 0x00, 0x03, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x01, 0x67, 0x00, 0x00, 0x01, - 0x66, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x01, - 0x69, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x02, - 0x6b, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x02, 0x6a, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x00, - 0x6c, 0x00, 0x00, 0x02, 0x6d, 0x00, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x03, - 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x01, 0x6f, 0x00, 0x00, 0x01, 0x6e, 0x00, 0x00, 0x02, - 0x6e, 0x00, 0x00, 0x03, 0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, - 0x70, 0x00, 0x00, 0x02, 0x70, 0x00, 0x00, 0x03, 0x73, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x01, - 0x73, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x03, 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x02, - 0x75, 0x00, 0x00, 0x01, 0x75, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x02, 0x74, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x00, - 0x76, 0x00, 0x00, 0x02, 0x77, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, 0x76, 0x00, 0x00, 0x02, 0x76, 0x00, 0x00, 0x03, - 0x79, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x01, 0x79, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x02, - 0x78, 0x00, 0x00, 0x03, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x02, 0x7b, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x01, - 0x7a, 0x00, 0x00, 0x02, 0x7a, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x01, - 0x7d, 0x00, 0x00, 0x01, 0x7c, 0x00, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x02, - 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x02, 0x81, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x03, - 0x83, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x01, 0x83, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x02, - 0x82, 0x00, 0x00, 0x03, 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x02, 0x85, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, - 0x84, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x01, - 0x87, 0x00, 0x00, 0x01, 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x03, 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x02, - 0x89, 0x00, 0x00, 0x01, 0x89, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x02, 0x88, 0x00, 0x00, 0x03, 0x8b, 0x00, 0x00, 0x00, - 0x8a, 0x00, 0x00, 0x02, 0x8b, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x01, 0x8a, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x00, 0x03, - 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x01, 0x8d, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x02, - 0x8c, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x02, 0x8f, 0x00, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x01, - 0x8e, 0x00, 0x00, 0x02, 0x8e, 0x00, 0x00, 0x03, 0x91, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x01, - 0x91, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x03, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xe4, 0x9a, - 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, - 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, - 0xe4, 0x9a, 0xd6, 0xa8, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, - 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, - 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, - 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xb4, 0xca, 0xa8, 0xd6, - 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, - 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, - 0xa8, 0xd6, 0x9a, 0xe4, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, - 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, - 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, - 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x65, 0xe4, 0x57, 0xd6, - 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, - 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, - 0x57, 0xd6, 0x4b, 0xca, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, - 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, - 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, - 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x29, 0xa8, 0x1b, 0x9a, - 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, - 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, - 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x29, 0x57, 0x35, 0x4b, - 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, - 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, - 0x35, 0x4b, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, - 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, - 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, - 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x65, 0x1b, 0x75, 0x0a, - 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, - 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x75, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, - 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, - 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, - 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xb4, 0x35, 0xbf, 0x40, - 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, - 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, - 0xbf, 0x40, 0xca, 0x4b, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, - 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, - 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, - 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x04, + 0x00, + 0x01, + 0x00, + 0x54, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x56, + 0xc1, + 0xa8, + 0xa4, + 0x4e, + 0x00, + 0x08, + 0xc0, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0xaa, + 0x3e, + 0x57, + 0x5b, + 0xb1, + 0xff, + 0x07, + 0x40, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x44, + 0x2b, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x02, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x2a, + 0x00, + 0x00, + 0x74, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x33, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x36, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x31, + 0x36, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x39, + 0x2e, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x35, + 0x38, + 0x34, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x24, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x03, + 0x23, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x03, + 0x22, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x03, + 0x21, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x03, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x03, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x03, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x03, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x03, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x03, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x03, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x03, + 0x19, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x03, + 0x18, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x03, + 0x17, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x03, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x03, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x03, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x03, + 0x13, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x03, + 0x12, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x03, + 0x11, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x03, + 0x10, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x03, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x03, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x03, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x03, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x03, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x03, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x03, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x28, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x03, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x03, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x03, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x03, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x03, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x03, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x03, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x03, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x03, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x03, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x03, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x03, + 0x34, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x03, + 0x35, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x03, + 0x36, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x03, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x03, + 0x38, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x03, + 0x39, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x03, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x03, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x03, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x03, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x03, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x03, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x03, + 0x40, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x03, + 0x41, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x03, + 0x42, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x03, + 0x43, + 0x00, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x03, + 0x44, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x03, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x03, + 0x46, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x03, + 0x47, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x03, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x03, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4a, + 0x00, + 0x00, + 0x03, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4c, + 0x00, + 0x00, + 0x03, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4e, + 0x00, + 0x00, + 0x03, + 0x51, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x02, + 0x51, + 0x00, + 0x00, + 0x01, + 0x51, + 0x00, + 0x00, + 0x01, + 0x50, + 0x00, + 0x00, + 0x02, + 0x50, + 0x00, + 0x00, + 0x03, + 0x53, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x02, + 0x53, + 0x00, + 0x00, + 0x01, + 0x53, + 0x00, + 0x00, + 0x01, + 0x52, + 0x00, + 0x00, + 0x02, + 0x52, + 0x00, + 0x00, + 0x03, + 0x55, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x02, + 0x55, + 0x00, + 0x00, + 0x01, + 0x55, + 0x00, + 0x00, + 0x01, + 0x54, + 0x00, + 0x00, + 0x02, + 0x54, + 0x00, + 0x00, + 0x03, + 0x57, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x02, + 0x57, + 0x00, + 0x00, + 0x01, + 0x57, + 0x00, + 0x00, + 0x01, + 0x56, + 0x00, + 0x00, + 0x02, + 0x56, + 0x00, + 0x00, + 0x03, + 0x59, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x02, + 0x59, + 0x00, + 0x00, + 0x01, + 0x59, + 0x00, + 0x00, + 0x01, + 0x58, + 0x00, + 0x00, + 0x02, + 0x58, + 0x00, + 0x00, + 0x03, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5a, + 0x00, + 0x00, + 0x03, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5c, + 0x00, + 0x00, + 0x03, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5e, + 0x00, + 0x00, + 0x03, + 0x61, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x02, + 0x61, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00, + 0x00, + 0x01, + 0x60, + 0x00, + 0x00, + 0x02, + 0x60, + 0x00, + 0x00, + 0x03, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x02, + 0x63, + 0x00, + 0x00, + 0x01, + 0x63, + 0x00, + 0x00, + 0x01, + 0x62, + 0x00, + 0x00, + 0x02, + 0x62, + 0x00, + 0x00, + 0x03, + 0x65, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x02, + 0x65, + 0x00, + 0x00, + 0x01, + 0x65, + 0x00, + 0x00, + 0x01, + 0x64, + 0x00, + 0x00, + 0x02, + 0x64, + 0x00, + 0x00, + 0x03, + 0x67, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x02, + 0x67, + 0x00, + 0x00, + 0x01, + 0x67, + 0x00, + 0x00, + 0x01, + 0x66, + 0x00, + 0x00, + 0x02, + 0x66, + 0x00, + 0x00, + 0x03, + 0x69, + 0x00, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x02, + 0x69, + 0x00, + 0x00, + 0x01, + 0x69, + 0x00, + 0x00, + 0x01, + 0x68, + 0x00, + 0x00, + 0x02, + 0x68, + 0x00, + 0x00, + 0x03, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6a, + 0x00, + 0x00, + 0x03, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6c, + 0x00, + 0x00, + 0x03, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6e, + 0x00, + 0x00, + 0x03, + 0x71, + 0x00, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x02, + 0x71, + 0x00, + 0x00, + 0x01, + 0x71, + 0x00, + 0x00, + 0x01, + 0x70, + 0x00, + 0x00, + 0x02, + 0x70, + 0x00, + 0x00, + 0x03, + 0x73, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x02, + 0x73, + 0x00, + 0x00, + 0x01, + 0x73, + 0x00, + 0x00, + 0x01, + 0x72, + 0x00, + 0x00, + 0x02, + 0x72, + 0x00, + 0x00, + 0x03, + 0x75, + 0x00, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x02, + 0x75, + 0x00, + 0x00, + 0x01, + 0x75, + 0x00, + 0x00, + 0x01, + 0x74, + 0x00, + 0x00, + 0x02, + 0x74, + 0x00, + 0x00, + 0x03, + 0x77, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x02, + 0x77, + 0x00, + 0x00, + 0x01, + 0x77, + 0x00, + 0x00, + 0x01, + 0x76, + 0x00, + 0x00, + 0x02, + 0x76, + 0x00, + 0x00, + 0x03, + 0x79, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x02, + 0x79, + 0x00, + 0x00, + 0x01, + 0x79, + 0x00, + 0x00, + 0x01, + 0x78, + 0x00, + 0x00, + 0x02, + 0x78, + 0x00, + 0x00, + 0x03, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7a, + 0x00, + 0x00, + 0x03, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7c, + 0x00, + 0x00, + 0x03, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7e, + 0x00, + 0x00, + 0x03, + 0x81, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x02, + 0x81, + 0x00, + 0x00, + 0x01, + 0x81, + 0x00, + 0x00, + 0x01, + 0x80, + 0x00, + 0x00, + 0x02, + 0x80, + 0x00, + 0x00, + 0x03, + 0x83, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x02, + 0x83, + 0x00, + 0x00, + 0x01, + 0x83, + 0x00, + 0x00, + 0x01, + 0x82, + 0x00, + 0x00, + 0x02, + 0x82, + 0x00, + 0x00, + 0x03, + 0x85, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x02, + 0x85, + 0x00, + 0x00, + 0x01, + 0x85, + 0x00, + 0x00, + 0x01, + 0x84, + 0x00, + 0x00, + 0x02, + 0x84, + 0x00, + 0x00, + 0x03, + 0x87, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x02, + 0x87, + 0x00, + 0x00, + 0x01, + 0x87, + 0x00, + 0x00, + 0x01, + 0x86, + 0x00, + 0x00, + 0x02, + 0x86, + 0x00, + 0x00, + 0x03, + 0x89, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x02, + 0x89, + 0x00, + 0x00, + 0x01, + 0x89, + 0x00, + 0x00, + 0x01, + 0x88, + 0x00, + 0x00, + 0x02, + 0x88, + 0x00, + 0x00, + 0x03, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8a, + 0x00, + 0x00, + 0x03, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8c, + 0x00, + 0x00, + 0x03, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8e, + 0x00, + 0x00, + 0x03, + 0x91, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x02, + 0x91, + 0x00, + 0x00, + 0x01, + 0x91, + 0x00, + 0x00, + 0x01, + 0x90, + 0x00, + 0x00, + 0x02, + 0x90, + 0x00, + 0x00, + 0x03, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, ]), }, }; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.2.0.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.2.0.ts index 9bd2a4041ddd..26f7ad456448 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.2.0.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.2.0.ts @@ -13,1332 +13,26102 @@ export const TILE_DATA_2_0 = { rectangle: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x4b, 0x37, 0x89, - 0x41, 0x00, 0x04, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x14, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x03, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x13, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0x83, 0x68, 0x7c, 0x54, 0x31, 0x5d, 0x86, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x58, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0xe0, 0x06, 0x00, 0x00, 0xd0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, - 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x36, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, - 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, - 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, - 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x36, 0x34, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, - 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, - 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, - 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, - 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, - 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, - 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, 0x61, - 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, - 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, - 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, - 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, - 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, 0x7d, - 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, - 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x2c, - 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, - 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, - 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, - 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, - 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, - 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x36, 0x33, 0x30, 0x36, 0x35, 0x35, 0x33, 0x37, 0x34, 0x39, 0x39, 0x30, 0x34, 0x36, - 0x31, 0x31, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x31, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, - 0x38, 0x30, 0x39, 0x32, 0x32, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, - 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, - 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, - 0x3a, 0x5b, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, - 0x2c, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, - 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x35, 0x30, 0x30, 0x33, 0x37, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x36, 0x2c, 0x2d, 0x35, 0x2e, 0x30, 0x30, 0x30, 0x37, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x31, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, - 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, - 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, 0x74, - 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, - 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, 0x73, - 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, - 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, 0x6f, - 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf8, 0xff, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x03, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x04, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x14, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x03, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x13, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x83, + 0x68, + 0x7c, + 0x54, + 0x31, + 0x5d, + 0x86, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x58, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0xe0, + 0x06, + 0x00, + 0x00, + 0xd0, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x36, + 0x33, + 0x30, + 0x36, + 0x35, + 0x35, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x30, + 0x34, + 0x36, + 0x31, + 0x31, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x31, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x32, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x35, + 0x30, + 0x30, + 0x33, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x36, + 0x2c, + 0x2d, + 0x35, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x31, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, ]), }, lineString: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0xb0, 0x45, 0xe5, 0xc2, 0xf5, 0x00, 0x99, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0x58, 0x0a, 0x00, 0x00, 0x84, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, - 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, - 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, - 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, - 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, - 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, - 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, - 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, - 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x22, 0x3a, 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x73, 0x75, - 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, - 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, - 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, - 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, - 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, - 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, - 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, - 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, - 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, - 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, 0x22, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, - 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, - 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, - 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, - 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, - 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, - 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, - 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, - 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, - 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x36, 0x35, 0x35, 0x33, 0x35, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, 0x7d, 0x7d, 0x5d, 0x7d, - 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, 0x6f, - 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, 0x65, - 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, 0x22, - 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, - 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, 0x4e, - 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, - 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, - 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, - 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, - 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, - 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, - 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, - 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, - 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0xb0, + 0x45, + 0xe5, + 0xc2, + 0xf5, + 0x00, + 0x99, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0x58, + 0x0a, + 0x00, + 0x00, + 0x84, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x35, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x20, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, ]), }, lineStrings: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xab, 0xf1, 0xd2, 0x4d, 0x62, 0x00, 0x3e, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x3d, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0xc2, 0x85, 0x9e, 0xdd, 0x8c, 0xed, 0xae, 0x3f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc4, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0x34, 0x18, 0x00, 0x00, 0xe0, 0x09, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, - 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x37, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, - 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x32, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x32, 0x31, 0x36, 0x7d, 0x2c, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, - 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, 0x33, - 0x36, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, - 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, - 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, - 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x34, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, - 0x65, 0x74, 0x22, 0x3a, 0x37, 0x36, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, - 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, - 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x31, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x32, 0x37, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, - 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x34, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x31, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x38, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x32, 0x30, 0x35, 0x32, 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, - 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, - 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, - 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, - 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, - 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x36, 0x37, - 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x73, 0x75, 0x62, 0x43, - 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, 0x22, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x3a, - 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, - 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, - 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, - 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, - 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x31, 0x35, 0x37, 0x39, 0x30, 0x30, 0x38, 0x30, 0x2c, - 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, 0x3a, 0x34, 0x31, 0x37, 0x37, 0x30, 0x36, 0x36, - 0x32, 0x33, 0x32, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x73, - 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, - 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, - 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, - 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, - 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x30, - 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, - 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, - 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, - 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x36, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, - 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, - 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, - 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, 0x2c, - 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, - 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, - 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, - 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, - 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, - 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, - 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, - 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, - 0x3a, 0x31, 0x36, 0x37, 0x31, 0x31, 0x39, 0x33, 0x35, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x38, - 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, - 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, 0x2c, 0x22, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x41, - 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x41, 0x6e, 0x64, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x70, 0x72, 0x65, - 0x76, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x70, 0x72, 0x65, 0x76, 0x49, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x31, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x76, 0x65, 0x72, - 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, - 0x3a, 0x31, 0x32, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, - 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, - 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x33, - 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, - 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x39, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, - 0x39, 0x39, 0x38, 0x38, 0x35, 0x35, 0x35, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, - 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, - 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, - 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, - 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x32, 0x2c, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x33, 0x30, 0x2e, 0x30, 0x30, 0x34, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, - 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x38, 0x7d, 0x7d, 0x5d, - 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, - 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, - 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, - 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, - 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0xac, 0x2a, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xac, 0x2a, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, - 0x01, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, - 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, - 0x01, 0x00, 0x00, 0x36, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, - 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, - 0x03, 0x00, 0x00, 0x1e, 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, - 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, - 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, - 0x02, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, - 0x03, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, - 0x04, 0x00, 0x00, 0x09, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, - 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x0f, 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, - 0x03, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, - 0x04, 0x00, 0x00, 0x33, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, - 0x05, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, - 0x05, 0x00, 0x00, 0x0c, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, - 0x05, 0x00, 0x00, 0x0f, 0x05, 0x00, 0x00, 0x0e, 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0xa7, 0xaa, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x55, 0x55, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x55, 0x55, 0xf8, 0xff, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xa7, 0xaa, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xf8, 0xff, 0x50, 0xd5, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0xff, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, - 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, - 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, - 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x39, 0x01, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x90, - 0x01, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x90, - 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0d, - 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x21, 0x01, 0x00, 0x00, 0x36, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x60, - 0x01, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x09, 0x02, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x4e, - 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0e, - 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x1e, - 0x02, 0x00, 0x00, 0x39, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x39, 0x02, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x51, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x90, - 0x02, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x0d, 0x02, 0x00, 0x00, 0x90, 0x02, 0x00, 0x00, 0x0f, 0x02, 0x00, 0x00, 0x0e, - 0x04, 0x00, 0x00, 0x21, 0x03, 0x00, 0x00, 0x39, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x39, - 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x09, - 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x0c, - 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x00, 0x0d, 0x04, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x0f, - 0x04, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x90, - 0x03, 0x00, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x0d, 0x03, 0x00, 0x00, 0x90, 0x03, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, 0x0e, - 0x05, 0x00, 0x00, 0x21, 0x04, 0x00, 0x00, 0x33, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x33, - 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x90, 0x05, 0x00, 0x00, 0x09, 0x05, 0x00, 0x00, 0x09, - 0x04, 0x00, 0x00, 0x90, 0x04, 0x00, 0x00, 0x4b, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x0c, - 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0e, 0x05, 0x00, 0x00, 0x0d, 0x05, 0x00, 0x00, 0x60, 0x05, 0x00, 0x00, 0x0f, - 0x05, 0x00, 0x00, 0x0e, 0x07, 0x00, 0x00, 0x1b, 0x06, 0x00, 0x00, 0x39, 0x07, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x60, - 0x06, 0x00, 0x00, 0x39, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x03, - 0x07, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x51, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0d, - 0x06, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x90, 0x06, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x0d, 0x06, 0x00, 0x00, 0x90, - 0x06, 0x00, 0x00, 0x0f, 0x06, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x21, 0x07, 0x00, 0x00, 0x36, 0x08, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x36, 0x07, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x90, - 0x08, 0x00, 0x00, 0x09, 0x08, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x4e, 0x08, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0e, 0x08, 0x00, 0x00, 0x0d, - 0x08, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x0e, 0x09, 0x00, 0x00, 0x1e, 0x08, 0x00, 0x00, 0x39, - 0x09, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x39, 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x60, - 0x08, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x06, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x51, - 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0e, - 0x08, 0x00, 0x00, 0x0d, 0x08, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x21, - 0x09, 0x00, 0x00, 0x39, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x39, 0x09, 0x00, 0x00, 0x90, - 0x0a, 0x00, 0x00, 0x60, 0x09, 0x00, 0x00, 0x90, 0x0a, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x09, 0x09, 0x00, 0x00, 0x90, - 0x09, 0x00, 0x00, 0x51, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x0c, 0x0a, 0x00, 0x00, 0x60, - 0x0a, 0x00, 0x00, 0x0e, 0x0a, 0x00, 0x00, 0x0d, 0x0a, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x0e, - 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x0c, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0e, - 0x09, 0x00, 0x00, 0x0d, 0x09, 0x00, 0x00, 0x90, 0x09, 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x21, - 0x0a, 0x00, 0x00, 0x33, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x33, 0x0a, 0x00, 0x00, 0x90, - 0x0b, 0x00, 0x00, 0x60, 0x0a, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00, 0x09, 0x0b, 0x00, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x90, - 0x0a, 0x00, 0x00, 0x4b, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x0c, 0x0b, 0x00, 0x00, 0x60, - 0x0b, 0x00, 0x00, 0x0e, 0x0b, 0x00, 0x00, 0x0d, 0x0b, 0x00, 0x00, 0x60, 0x0b, 0x00, 0x00, 0x0f, 0x0b, 0x00, 0x00, 0x0e, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x3e, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x3d, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0xc2, + 0x85, + 0x9e, + 0xdd, + 0x8c, + 0xed, + 0xae, + 0x3f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc4, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0x34, + 0x18, + 0x00, + 0x00, + 0xe0, + 0x09, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x33, + 0x36, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x34, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x36, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x38, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x30, + 0x35, + 0x32, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x37, + 0x39, + 0x30, + 0x30, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x34, + 0x31, + 0x37, + 0x37, + 0x30, + 0x36, + 0x36, + 0x32, + 0x33, + 0x32, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x37, + 0x31, + 0x31, + 0x39, + 0x33, + 0x35, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x65, + 0x78, + 0x74, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x41, + 0x6e, + 0x64, + 0x50, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x70, + 0x72, + 0x65, + 0x76, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x33, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x39, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x33, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x38, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xac, + 0x2a, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xf8, + 0xff, + 0x50, + 0xd5, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf0, + 0xff, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x39, + 0x01, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x03, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x21, + 0x01, + 0x00, + 0x00, + 0x36, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x36, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x60, + 0x01, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x09, + 0x02, + 0x00, + 0x00, + 0x09, + 0x01, + 0x00, + 0x00, + 0x90, + 0x01, + 0x00, + 0x00, + 0x4e, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x1e, + 0x02, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x39, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x60, + 0x02, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x06, + 0x03, + 0x00, + 0x00, + 0x06, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x51, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x0c, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x02, + 0x00, + 0x00, + 0x0d, + 0x02, + 0x00, + 0x00, + 0x90, + 0x02, + 0x00, + 0x00, + 0x0f, + 0x02, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x21, + 0x03, + 0x00, + 0x00, + 0x39, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x39, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x60, + 0x03, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x09, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x51, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x0c, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x04, + 0x00, + 0x00, + 0x0d, + 0x04, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x0f, + 0x04, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x0c, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x03, + 0x00, + 0x00, + 0x0d, + 0x03, + 0x00, + 0x00, + 0x90, + 0x03, + 0x00, + 0x00, + 0x0f, + 0x03, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x21, + 0x04, + 0x00, + 0x00, + 0x33, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x33, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x60, + 0x04, + 0x00, + 0x00, + 0x90, + 0x05, + 0x00, + 0x00, + 0x09, + 0x05, + 0x00, + 0x00, + 0x09, + 0x04, + 0x00, + 0x00, + 0x90, + 0x04, + 0x00, + 0x00, + 0x4b, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x0c, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x05, + 0x00, + 0x00, + 0x0d, + 0x05, + 0x00, + 0x00, + 0x60, + 0x05, + 0x00, + 0x00, + 0x0f, + 0x05, + 0x00, + 0x00, + 0x0e, + 0x07, + 0x00, + 0x00, + 0x1b, + 0x06, + 0x00, + 0x00, + 0x39, + 0x07, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x39, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x60, + 0x06, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x51, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x0c, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x06, + 0x00, + 0x00, + 0x0d, + 0x06, + 0x00, + 0x00, + 0x90, + 0x06, + 0x00, + 0x00, + 0x0f, + 0x06, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x21, + 0x07, + 0x00, + 0x00, + 0x36, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x36, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x60, + 0x07, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x09, + 0x08, + 0x00, + 0x00, + 0x09, + 0x07, + 0x00, + 0x00, + 0x90, + 0x07, + 0x00, + 0x00, + 0x4e, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x1e, + 0x08, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x39, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x60, + 0x08, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x06, + 0x09, + 0x00, + 0x00, + 0x06, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x51, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x0c, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x08, + 0x00, + 0x00, + 0x0d, + 0x08, + 0x00, + 0x00, + 0x90, + 0x08, + 0x00, + 0x00, + 0x0f, + 0x08, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x21, + 0x09, + 0x00, + 0x00, + 0x39, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x39, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x09, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x51, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x0c, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x0a, + 0x00, + 0x00, + 0x0d, + 0x0a, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x0f, + 0x0a, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x0c, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x09, + 0x00, + 0x00, + 0x0d, + 0x09, + 0x00, + 0x00, + 0x90, + 0x09, + 0x00, + 0x00, + 0x0f, + 0x09, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x21, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x33, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x0a, + 0x00, + 0x00, + 0x90, + 0x0a, + 0x00, + 0x00, + 0x4b, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0e, + 0x0b, + 0x00, + 0x00, + 0x0d, + 0x0b, + 0x00, + 0x00, + 0x60, + 0x0b, + 0x00, + 0x00, + 0x0f, + 0x0b, + 0x00, + 0x00, + 0x0e, ]), }, triangles: { flags: ImdlFlags.None, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xab, 0xf1, 0xd2, 0x4d, - 0x62, 0x00, 0x1e, 0xc0, 0xc7, 0x4b, 0x37, 0x89, 0x41, 0x00, 0x24, 0xc0, 0x00, 0x00, 0xbd, 0x9a, 0xf2, 0xd7, 0x5a, 0xbe, - 0x55, 0x0e, 0x2d, 0xb2, 0x9d, 0xff, 0x1d, 0x40, 0x39, 0xb4, 0xc8, 0x76, 0xbe, 0xff, 0x23, 0x40, 0x00, 0x00, 0xbd, 0x9a, - 0xf2, 0xd7, 0x5a, 0xbe, 0xb0, 0x45, 0xe5, 0xc2, 0xf5, 0x00, 0x99, 0x3f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7c, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0xc8, 0x0e, 0x00, 0x00, 0x4c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x35, 0x36, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x35, 0x36, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, - 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, - 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, - 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, - 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, - 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x22, 0x3a, 0x32, 0x31, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x39, 0x31, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, - 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, - 0x74, 0x68, 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x3a, 0x31, 0x38, 0x34, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, - 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x22, 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x31, - 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, - 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, - 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, - 0x22, 0x3a, 0x31, 0x36, 0x32, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, - 0x34, 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, - 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, - 0x3a, 0x32, 0x37, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x32, 0x30, - 0x7d, 0x7d, 0x2c, 0x22, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, - 0x5b, 0x22, 0x4b, 0x48, 0x52, 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, - 0x57, 0x45, 0x42, 0x33, 0x44, 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, - 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, - 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x66, 0x69, - 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, - 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x35, 0x35, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, - 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, - 0x73, 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, - 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, - 0x6c, 0x31, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, - 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, - 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, - 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, - 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x32, 0x31, 0x33, - 0x30, 0x37, 0x30, 0x36, 0x36, 0x38, 0x37, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, 0x75, - 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, 0x2c, - 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, 0x3a, - 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, 0x69, - 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, - 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, - 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, - 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x7d, 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, - 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x30, 0x22, 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, - 0x3a, 0x30, 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, - 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, - 0x22, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, - 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, - 0x38, 0x39, 0x31, 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, - 0x32, 0x32, 0x36, 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, - 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, - 0x37, 0x34, 0x39, 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, - 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, - 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, - 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, - 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, - 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, - 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, - 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, - 0x3a, 0x33, 0x39, 0x7d, 0x7d, 0x2c, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x73, 0x65, 0x67, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, - 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, - 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, - 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x7d, - 0x7d, 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x6d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x31, 0x22, - 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x31, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x31, 0x22, 0x2c, 0x22, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x39, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x32, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, - 0x63, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3a, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, - 0x3a, 0x31, 0x2c, 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, - 0x22, 0x3a, 0x34, 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x4d, 0x61, 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x32, 0x38, 0x39, 0x31, - 0x39, 0x36, 0x36, 0x31, 0x32, 0x34, 0x39, 0x37, 0x31, 0x33, 0x38, 0x37, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x33, 0x30, 0x35, 0x32, 0x32, 0x36, - 0x32, 0x31, 0x34, 0x39, 0x39, 0x39, 0x36, 0x31, 0x38, 0x34, 0x34, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, - 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x31, 0x2e, 0x35, 0x32, 0x36, 0x31, 0x33, 0x31, 0x30, 0x37, 0x34, 0x39, - 0x39, 0x38, 0x30, 0x39, 0x32, 0x38, 0x65, 0x2d, 0x30, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x37, 0x2e, 0x35, 0x30, - 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, - 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, - 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, - 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x37, 0x2e, 0x35, 0x30, 0x31, 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x31, 0x30, 0x2e, 0x30, 0x30, 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x30, 0x2e, 0x30, 0x30, 0x30, 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x2c, - 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, 0x22, 0x3a, 0x5b, 0x2d, 0x37, 0x2e, 0x35, 0x30, 0x31, - 0x31, 0x32, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x32, 0x2c, 0x2d, 0x31, 0x30, 0x2e, 0x30, 0x30, - 0x31, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x2d, 0x30, 0x2e, 0x30, 0x30, 0x30, - 0x35, 0x30, 0x30, 0x30, 0x37, 0x35, 0x30, 0x5d, 0x7d, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x33, 0x39, - 0x7d, 0x7d, 0x5d, 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, - 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, - 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, - 0x65, 0x22, 0x2c, 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, - 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, - 0x6f, 0x6f, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0xa7, 0xaa, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xf8, 0xff, 0xfe, 0x7f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x55, 0x55, 0xf8, 0xff, 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, - 0xfe, 0x7f, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, - 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xf8, 0xff, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, - 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, - 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, - 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, - 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x03, - 0xa7, 0xaa, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xa7, 0xaa, 0xfe, 0x7f, - 0xfe, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0x03, 0x00, 0xfe, 0x7f, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0xfe, 0x7f, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xa7, 0xaa, 0x03, 0x00, 0xfe, 0x7f, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0x03, 0x00, - 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0x02, 0x00, - 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x55, 0x55, 0x03, 0x00, 0xfe, 0x7f, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, - 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, - 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, - 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01, - 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x03, - 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, - 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, - 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x01, - 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, - 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, - 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, - 0x07, 0x00, 0x00, 0x03, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xab, + 0xf1, + 0xd2, + 0x4d, + 0x62, + 0x00, + 0x1e, + 0xc0, + 0xc7, + 0x4b, + 0x37, + 0x89, + 0x41, + 0x00, + 0x24, + 0xc0, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0x55, + 0x0e, + 0x2d, + 0xb2, + 0x9d, + 0xff, + 0x1d, + 0x40, + 0x39, + 0xb4, + 0xc8, + 0x76, + 0xbe, + 0xff, + 0x23, + 0x40, + 0x00, + 0x00, + 0xbd, + 0x9a, + 0xf2, + 0xd7, + 0x5a, + 0xbe, + 0xb0, + 0x45, + 0xe5, + 0xc2, + 0xf5, + 0x00, + 0x99, + 0x3f, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0xc8, + 0x0e, + 0x00, + 0x00, + 0x4c, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x35, + 0x36, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x31, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x38, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x36, + 0x32, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x34, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x37, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x32, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x35, + 0x35, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x32, + 0x31, + 0x33, + 0x30, + 0x37, + 0x30, + 0x36, + 0x36, + 0x38, + 0x37, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x2c, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x31, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x31, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x39, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x32, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x74, + 0x72, + 0x75, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x32, + 0x38, + 0x39, + 0x31, + 0x39, + 0x36, + 0x36, + 0x31, + 0x32, + 0x34, + 0x39, + 0x37, + 0x31, + 0x33, + 0x38, + 0x37, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x33, + 0x30, + 0x35, + 0x32, + 0x32, + 0x36, + 0x32, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x36, + 0x31, + 0x38, + 0x34, + 0x34, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x35, + 0x32, + 0x36, + 0x31, + 0x33, + 0x31, + 0x30, + 0x37, + 0x34, + 0x39, + 0x39, + 0x38, + 0x30, + 0x39, + 0x32, + 0x38, + 0x65, + 0x2d, + 0x30, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x37, + 0x2e, + 0x35, + 0x30, + 0x31, + 0x31, + 0x32, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x2c, + 0x2d, + 0x31, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x31, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x2d, + 0x30, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x35, + 0x30, + 0x30, + 0x30, + 0x37, + 0x35, + 0x30, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x33, + 0x39, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0x20, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0xff, + 0xff, + 0x00, + 0xff, + 0x00, + 0xff, + 0xff, + 0x00, + 0x00, + 0xff, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xa7, + 0xaa, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x01, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x55, + 0x55, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x02, + 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x80, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x01, + 0x00, + 0x00, + 0x02, + 0x01, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, ]), }, cylinder: { flags: ImdlFlags.ContainsCurves, bytes: new Uint8Array([ - 0x69, 0x4d, 0x64, 0x6c, 0x00, 0x00, 0x02, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0xd6, 0xc5, 0x6d, - 0x34, 0x00, 0x00, 0xc0, 0x39, 0xd6, 0xc5, 0x6d, 0x34, 0x00, 0x00, 0xc0, 0x56, 0xc1, 0xa8, 0xa4, 0x4e, 0x00, 0x08, 0xc0, - 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0x8e, 0x53, 0x74, 0x24, 0x97, 0xff, 0xff, 0x3f, 0xaa, 0x3e, 0x57, 0x5b, - 0xb1, 0xff, 0x07, 0x40, 0xc6, 0x37, 0x3a, 0x87, 0xb1, 0x7e, 0x80, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x67, 0x6c, 0x54, 0x46, 0x01, 0x00, 0x00, 0x00, 0xfc, 0x2a, 0x00, 0x00, 0xa0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x56, 0x69, 0x65, 0x77, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x76, 0x56, - 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x30, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, - 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, - 0x37, 0x32, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x34, 0x39, 0x32, - 0x38, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, - 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, - 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, - 0x36, 0x34, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x37, 0x33, 0x30, 0x34, - 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, - 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, - 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x33, 0x36, - 0x33, 0x32, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, - 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x36, 0x34, 0x38, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x22, 0x3a, 0x36, 0x36, 0x35, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, - 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, - 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x32, 0x39, 0x36, 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x3a, 0x32, 0x33, 0x33, 0x36, 0x7d, 0x2c, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, - 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, - 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3a, 0x22, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, - 0x2c, 0x22, 0x62, 0x79, 0x74, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x3a, 0x38, 0x36, 0x34, 0x2c, 0x22, 0x62, - 0x79, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x3a, 0x38, 0x31, 0x36, 0x38, 0x7d, 0x7d, 0x2c, 0x22, 0x65, - 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4b, 0x48, 0x52, - 0x5f, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x5f, 0x67, 0x6c, 0x54, 0x46, 0x22, 0x2c, 0x22, 0x57, 0x45, 0x42, 0x33, 0x44, - 0x5f, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x22, 0x5d, 0x2c, 0x22, 0x67, 0x6c, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x73, 0x65, - 0x64, 0x22, 0x3a, 0x5b, 0x22, 0x4f, 0x45, 0x53, 0x5f, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, - 0x65, 0x78, 0x5f, 0x75, 0x69, 0x6e, 0x74, 0x22, 0x5d, 0x2c, 0x22, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, - 0x22, 0x3a, 0x7b, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, 0x3a, 0x7b, 0x22, 0x63, 0x61, 0x74, - 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x37, 0x22, 0x2c, 0x22, 0x66, 0x69, 0x6c, - 0x6c, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x46, - 0x6c, 0x61, 0x67, 0x73, 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x4c, 0x69, 0x67, 0x68, 0x74, - 0x69, 0x6e, 0x67, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x22, 0x3a, 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x6c, 0x69, 0x6e, 0x65, 0x57, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x73, - 0x75, 0x62, 0x43, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x22, 0x3a, 0x22, 0x30, 0x78, 0x31, 0x38, 0x22, - 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, 0x7d, 0x7d, 0x2c, 0x22, 0x6d, 0x65, 0x73, 0x68, 0x65, 0x73, 0x22, - 0x3a, 0x7b, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x3a, 0x7b, 0x22, 0x70, 0x72, 0x69, 0x6d, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22, 0x65, 0x64, 0x67, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x73, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, - 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, - 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, - 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, - 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x65, 0x6e, 0x64, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x51, 0x75, - 0x61, 0x64, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, - 0x73, 0x22, 0x2c, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, - 0x63, 0x65, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x2c, 0x22, 0x6e, 0x6f, - 0x72, 0x6d, 0x61, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, - 0x50, 0x61, 0x69, 0x72, 0x73, 0x30, 0x53, 0x69, 0x6c, 0x68, 0x6f, 0x75, 0x65, 0x74, 0x74, 0x65, 0x73, 0x22, 0x7d, 0x7d, - 0x2c, 0x22, 0x69, 0x73, 0x50, 0x6c, 0x61, 0x6e, 0x61, 0x72, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x6d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x22, 0x3a, 0x22, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x30, 0x22, - 0x2c, 0x22, 0x73, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, - 0x22, 0x3a, 0x22, 0x62, 0x76, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x22, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x31, 0x7d, 0x2c, 0x22, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x30, - 0x2c, 0x22, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, - 0x56, 0x69, 0x65, 0x77, 0x22, 0x3a, 0x22, 0x62, 0x76, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x30, 0x22, 0x2c, 0x22, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x3a, 0x31, 0x34, 0x36, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x44, - 0x22, 0x3a, 0x30, 0x2c, 0x22, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, - 0x65, 0x22, 0x3a, 0x31, 0x2c, 0x22, 0x68, 0x61, 0x73, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x75, 0x63, 0x65, 0x6e, 0x63, - 0x79, 0x22, 0x3a, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x22, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3a, 0x31, 0x2c, - 0x22, 0x6e, 0x75, 0x6d, 0x52, 0x67, 0x62, 0x61, 0x50, 0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x22, 0x3a, 0x34, - 0x2c, 0x22, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x4d, 0x61, - 0x74, 0x72, 0x69, 0x78, 0x22, 0x3a, 0x5b, 0x36, 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, - 0x32, 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, - 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x36, 0x2e, 0x31, 0x30, 0x34, 0x35, 0x32, 0x34, 0x32, 0x39, 0x39, 0x39, 0x39, 0x32, - 0x33, 0x37, 0x30, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x30, 0x2e, 0x30, - 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x39, 0x2e, 0x31, 0x35, 0x36, 0x37, 0x38, 0x36, 0x34, 0x34, 0x39, 0x39, 0x38, 0x38, 0x35, - 0x35, 0x35, 0x30, 0x65, 0x2d, 0x30, 0x35, 0x2c, 0x30, 0x2e, 0x30, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x2c, 0x31, 0x2e, 0x30, 0x5d, 0x2c, 0x22, 0x64, 0x65, - 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x61, 0x78, 0x22, 0x3a, 0x5b, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x37, 0x2c, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x38, 0x5d, 0x2c, 0x22, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x4d, 0x69, 0x6e, - 0x22, 0x3a, 0x5b, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x37, 0x2c, 0x2d, 0x32, 0x2e, 0x30, 0x30, 0x30, 0x32, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x37, 0x2c, 0x2d, 0x33, 0x2e, 0x30, 0x30, 0x30, 0x34, 0x34, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, - 0x39, 0x38, 0x5d, 0x7d, 0x2c, 0x22, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x22, 0x3a, - 0x36, 0x35, 0x32, 0x38, 0x30, 0x2c, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3a, 0x35, 0x38, 0x34, 0x7d, 0x7d, 0x5d, - 0x7d, 0x7d, 0x2c, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x4e, 0x6f, 0x64, 0x65, 0x5f, 0x52, 0x6f, - 0x6f, 0x74, 0x22, 0x3a, 0x22, 0x4d, 0x65, 0x73, 0x68, 0x5f, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x7d, 0x2c, 0x22, 0x73, 0x63, - 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x22, 0x2c, - 0x22, 0x73, 0x63, 0x65, 0x6e, 0x65, 0x73, 0x22, 0x3a, 0x7b, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x63, - 0x65, 0x6e, 0x65, 0x22, 0x3a, 0x7b, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x3a, 0x5b, 0x22, 0x72, 0x6f, 0x6f, 0x74, - 0x4e, 0x6f, 0x64, 0x65, 0x22, 0x5d, 0x7d, 0x7d, 0x7d, 0x0a, 0x20, 0x20, 0xf8, 0xff, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, - 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xfe, 0x7f, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x41, 0xd2, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xc5, 0x69, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x29, 0x11, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xbb, 0x07, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x38, 0x54, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0xfb, 0xbf, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, - 0x07, 0xfe, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0xf8, 0xff, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xec, 0x93, 0xcc, 0xcc, 0x07, 0xfe, 0x37, 0x96, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x93, 0xcc, 0xcc, - 0x41, 0xf8, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, 0x41, 0xf8, 0xc3, 0xab, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0xa2, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd0, 0xae, 0xcc, 0xcc, 0xd3, 0xee, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd0, 0xae, 0xcc, 0xcc, 0x07, 0xe2, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, - 0x07, 0xe2, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0xba, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, 0x41, 0xd2, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xba, 0xc5, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xae, 0xd0, 0xcc, 0xcc, 0xfb, 0xbf, 0xd3, 0xee, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0xd0, 0xcc, 0xcc, - 0xc3, 0xab, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, 0xc3, 0xab, 0x41, 0xf8, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0xdd, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x93, 0xec, 0xcc, 0xcc, 0x37, 0x96, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x93, 0xec, 0xcc, 0xcc, 0xfe, 0x7f, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, - 0xfe, 0x7f, 0xf8, 0xff, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, 0xc5, 0x69, 0x07, 0xfe, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6c, 0xec, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5d, 0xdd, 0xcc, 0xcc, 0x38, 0x54, 0x41, 0xf8, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xdd, 0xcc, 0xcc, - 0x01, 0x40, 0xd3, 0xee, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, 0x01, 0x40, 0xd3, 0xee, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0xd0, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x45, 0xc5, 0xcc, 0xcc, 0xba, 0x2d, 0x07, 0xe2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x45, 0xc5, 0xcc, 0xcc, 0xf4, 0x1d, 0x41, 0xd2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, - 0xf4, 0x1d, 0x41, 0xd2, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xba, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0x29, 0x11, 0xfb, 0xbf, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x2f, 0xae, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x22, 0xa2, 0xcc, 0xcc, 0xbb, 0x07, 0xc3, 0xab, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xa2, 0xcc, 0xcc, - 0xf5, 0x01, 0x37, 0x96, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, 0xf5, 0x01, 0x37, 0x96, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x93, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xcc, 0xcc, 0x03, 0x00, 0xfe, 0x7f, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xcc, 0xcc, 0xf5, 0x01, 0xc5, 0x69, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, - 0xf5, 0x01, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x6c, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, 0xbb, 0x07, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x22, 0x5d, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2f, 0x51, 0xcc, 0xcc, 0x29, 0x11, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x51, 0xcc, 0xcc, - 0xf4, 0x1d, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, 0xf4, 0x1d, 0xba, 0x2d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x45, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x45, 0x3a, 0xcc, 0xcc, 0xba, 0x2d, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x45, 0x3a, 0xcc, 0xcc, 0x01, 0x40, 0x29, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, - 0x01, 0x40, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x2f, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0x38, 0x54, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x5d, 0x22, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x6c, 0x13, 0xcc, 0xcc, 0xc5, 0x69, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x13, 0xcc, 0xcc, - 0xfe, 0x7f, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, 0xfe, 0x7f, 0x03, 0x00, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x93, 0x13, 0xcc, 0xcc, 0x37, 0x96, 0xf5, 0x01, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x93, 0x13, 0xcc, 0xcc, 0xc3, 0xab, 0xbb, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, - 0xc3, 0xab, 0xbb, 0x07, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa2, 0x22, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0xfb, 0xbf, 0x29, 0x11, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xae, 0x2f, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xba, 0x3a, 0xcc, 0xcc, 0x41, 0xd2, 0xf4, 0x1d, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0x3a, 0xcc, 0xcc, - 0x07, 0xe2, 0xba, 0x2d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, 0x07, 0xe2, 0xba, 0x2d, - 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x45, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xd0, 0x51, 0xcc, 0xcc, 0xd3, 0xee, 0x01, 0x40, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd0, 0x51, 0xcc, 0xcc, 0x41, 0xf8, 0x38, 0x54, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, - 0x41, 0xf8, 0x38, 0x54, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdd, 0x5d, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, 0x07, 0xfe, 0xc5, 0x69, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x6c, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x09, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00, - 0x00, 0x12, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1b, - 0x00, 0x00, 0x1b, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1d, 0x00, 0x00, - 0x1d, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x01, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x26, 0x00, 0x00, 0x27, 0x00, - 0x00, 0x27, 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x26, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x26, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x30, 0x00, 0x00, 0x26, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x26, 0x00, 0x00, 0x32, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x26, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x26, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x26, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x26, - 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x26, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x26, 0x00, 0x00, - 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3b, 0x00, - 0x00, 0x3b, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, - 0x00, 0x00, 0x26, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x26, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x26, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x26, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x26, 0x00, - 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x26, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x26, 0x00, 0x00, 0x44, - 0x00, 0x00, 0x44, 0x00, 0x00, 0x26, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x26, 0x00, 0x00, 0x46, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x26, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x26, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, - 0x00, 0x26, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x26, 0x00, 0x00, 0x25, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4b, - 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, - 0x4e, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x4f, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x52, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x54, 0x00, 0x00, 0x53, 0x00, 0x00, - 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x56, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, - 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x56, 0x00, 0x00, 0x58, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, - 0x00, 0x00, 0x59, 0x00, 0x00, 0x58, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, - 0x5b, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, - 0x00, 0x5c, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, - 0x00, 0x00, 0x60, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, - 0x62, 0x00, 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x64, 0x00, - 0x00, 0x63, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, 0x64, 0x00, 0x00, 0x66, 0x00, 0x00, 0x65, - 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, 0x00, 0x68, 0x00, 0x00, 0x67, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, - 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, - 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, - 0x6f, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x70, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x72, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, - 0x00, 0x00, 0x74, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, - 0x76, 0x00, 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x78, 0x00, - 0x00, 0x77, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x79, - 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7b, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, - 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x80, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, - 0x00, 0x00, 0x81, 0x00, 0x00, 0x80, 0x00, 0x00, 0x82, 0x00, 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, - 0x83, 0x00, 0x00, 0x82, 0x00, 0x00, 0x84, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, - 0x00, 0x84, 0x00, 0x00, 0x86, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, - 0x00, 0x00, 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, - 0x8a, 0x00, 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8c, 0x00, - 0x00, 0x8b, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8d, - 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x90, 0x00, 0x00, 0x8f, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, - 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, 0x00, 0x00, 0x22, 0x00, - 0x00, 0x23, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00, 0x23, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, - 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x21, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1f, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1e, - 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1d, 0x00, 0x00, - 0x1e, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1d, 0x00, - 0x00, 0x1d, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x1b, 0x00, 0x00, - 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x18, 0x00, - 0x00, 0x19, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x19, 0x00, 0x00, 0x19, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, - 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, - 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x17, 0x00, 0x00, 0x17, 0x00, 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x15, 0x00, - 0x00, 0x15, 0x00, 0x00, 0x16, 0x00, 0x00, 0x16, 0x00, 0x00, 0x14, 0x00, 0x00, 0x15, 0x00, 0x00, 0x14, 0x00, 0x00, 0x14, - 0x00, 0x00, 0x15, 0x00, 0x00, 0x15, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00, 0x13, 0x00, 0x00, 0x13, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x14, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, - 0x00, 0x13, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, - 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0e, 0x00, - 0x00, 0x0f, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, - 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0b, 0x00, - 0x00, 0x0b, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0a, - 0x00, 0x00, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x09, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x09, 0x00, 0x00, 0x09, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x09, 0x00, - 0x00, 0x09, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, - 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x05, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, - 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, - 0x00, 0x25, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, 0x25, 0x00, 0x00, 0x49, 0x00, 0x00, 0x25, 0x00, 0x00, 0x25, - 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, 0x27, 0x00, 0x00, 0x28, 0x00, 0x00, 0x27, 0x00, 0x00, 0x27, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, 0x00, 0x28, 0x00, 0x00, 0x28, 0x00, 0x00, 0x29, 0x00, - 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x29, 0x00, 0x00, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, - 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, - 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, - 0x00, 0x2d, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, - 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, - 0x2e, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x2f, 0x00, - 0x00, 0x2f, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x00, 0x00, 0x30, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x32, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, 0x00, 0x32, 0x00, 0x00, 0x32, 0x00, 0x00, 0x33, 0x00, - 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, - 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x34, 0x00, 0x00, 0x34, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, - 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x35, 0x00, 0x00, 0x35, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, - 0x00, 0x37, 0x00, 0x00, 0x36, 0x00, 0x00, 0x36, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, - 0x00, 0x00, 0x37, 0x00, 0x00, 0x37, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x39, 0x00, - 0x00, 0x39, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x3a, - 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x3b, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3d, 0x00, - 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, - 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, - 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, - 0x00, 0x41, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, - 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, - 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x43, 0x00, - 0x00, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x45, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, - 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, 0x46, 0x00, 0x00, 0x45, 0x00, 0x00, 0x45, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, 0x00, 0x46, 0x00, 0x00, 0x46, 0x00, 0x00, 0x47, 0x00, - 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x47, 0x00, 0x00, 0x47, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, - 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x49, 0x00, 0x00, 0x49, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, 0x24, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x01, - 0x24, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x02, 0x23, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x02, - 0x23, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x03, 0x22, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x02, 0x22, 0x00, 0x00, 0x01, 0x22, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x03, - 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x21, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x02, - 0x20, 0x00, 0x00, 0x03, 0x20, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, - 0x1f, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x03, 0x1f, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x02, 0x1f, 0x00, 0x00, 0x01, - 0x1f, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x02, 0x1e, 0x00, 0x00, 0x03, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x02, - 0x1e, 0x00, 0x00, 0x01, 0x1e, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x03, 0x1d, 0x00, 0x00, 0x00, - 0x1c, 0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x01, 0x1d, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x03, - 0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x01, 0x1c, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x02, - 0x1b, 0x00, 0x00, 0x03, 0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x02, 0x1b, 0x00, 0x00, 0x01, 0x1b, 0x00, 0x00, 0x01, - 0x1a, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x03, 0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x02, 0x1a, 0x00, 0x00, 0x01, - 0x1a, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x02, 0x19, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x02, - 0x19, 0x00, 0x00, 0x01, 0x19, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x03, 0x18, 0x00, 0x00, 0x00, - 0x17, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x03, - 0x17, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x02, - 0x16, 0x00, 0x00, 0x03, 0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x02, 0x16, 0x00, 0x00, 0x01, 0x16, 0x00, 0x00, 0x01, - 0x15, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x03, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x02, 0x15, 0x00, 0x00, 0x01, - 0x15, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x03, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x02, - 0x14, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x03, 0x13, 0x00, 0x00, 0x00, - 0x12, 0x00, 0x00, 0x02, 0x13, 0x00, 0x00, 0x01, 0x13, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x03, - 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x02, - 0x11, 0x00, 0x00, 0x03, 0x11, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x11, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, - 0x10, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x01, - 0x10, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x02, 0x0f, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x02, - 0x0f, 0x00, 0x00, 0x01, 0x0f, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 0x00, - 0x0d, 0x00, 0x00, 0x02, 0x0e, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x03, - 0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x02, 0x0d, 0x00, 0x00, 0x01, 0x0d, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x02, - 0x0c, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x02, 0x0c, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x01, - 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x03, 0x0b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00, 0x01, - 0x0b, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x02, - 0x0a, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x03, 0x09, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x02, 0x09, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x03, - 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x02, - 0x07, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x01, - 0x06, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, - 0x05, 0x00, 0x00, 0x01, 0x05, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x03, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, - 0x02, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x01, - 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, - 0x49, 0x00, 0x00, 0x01, 0x25, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x03, 0x28, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x02, - 0x28, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x01, 0x27, 0x00, 0x00, 0x02, 0x27, 0x00, 0x00, 0x03, 0x29, 0x00, 0x00, 0x00, - 0x28, 0x00, 0x00, 0x02, 0x29, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x01, 0x28, 0x00, 0x00, 0x02, 0x28, 0x00, 0x00, 0x03, - 0x2a, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x01, 0x2a, 0x00, 0x00, 0x01, 0x29, 0x00, 0x00, 0x02, - 0x29, 0x00, 0x00, 0x03, 0x2b, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x01, - 0x2a, 0x00, 0x00, 0x02, 0x2a, 0x00, 0x00, 0x03, 0x2c, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x01, - 0x2c, 0x00, 0x00, 0x01, 0x2b, 0x00, 0x00, 0x02, 0x2b, 0x00, 0x00, 0x03, 0x2d, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x02, - 0x2d, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x03, 0x2e, 0x00, 0x00, 0x00, - 0x2d, 0x00, 0x00, 0x02, 0x2e, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x01, 0x2d, 0x00, 0x00, 0x02, 0x2d, 0x00, 0x00, 0x03, - 0x2f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x01, 0x2f, 0x00, 0x00, 0x01, 0x2e, 0x00, 0x00, 0x02, - 0x2e, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x01, - 0x2f, 0x00, 0x00, 0x02, 0x2f, 0x00, 0x00, 0x03, 0x31, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x01, - 0x31, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, 0x03, 0x32, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x02, - 0x32, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x01, 0x31, 0x00, 0x00, 0x02, 0x31, 0x00, 0x00, 0x03, 0x33, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x02, 0x33, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x01, 0x32, 0x00, 0x00, 0x02, 0x32, 0x00, 0x00, 0x03, - 0x34, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x01, 0x33, 0x00, 0x00, 0x02, - 0x33, 0x00, 0x00, 0x03, 0x35, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x01, - 0x34, 0x00, 0x00, 0x02, 0x34, 0x00, 0x00, 0x03, 0x36, 0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x01, - 0x36, 0x00, 0x00, 0x01, 0x35, 0x00, 0x00, 0x02, 0x35, 0x00, 0x00, 0x03, 0x37, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x02, - 0x37, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x02, 0x36, 0x00, 0x00, 0x03, 0x38, 0x00, 0x00, 0x00, - 0x37, 0x00, 0x00, 0x02, 0x38, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x01, 0x37, 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x03, - 0x39, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x01, 0x39, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x02, - 0x38, 0x00, 0x00, 0x03, 0x3a, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x01, - 0x39, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x03, 0x3b, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x01, - 0x3b, 0x00, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x02, 0x3a, 0x00, 0x00, 0x03, 0x3c, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x02, - 0x3c, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x01, 0x3b, 0x00, 0x00, 0x02, 0x3b, 0x00, 0x00, 0x03, 0x3d, 0x00, 0x00, 0x00, - 0x3c, 0x00, 0x00, 0x02, 0x3d, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x03, - 0x3e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x01, 0x3e, 0x00, 0x00, 0x01, 0x3d, 0x00, 0x00, 0x02, - 0x3d, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x01, - 0x3e, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x03, 0x40, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x01, - 0x40, 0x00, 0x00, 0x01, 0x3f, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x03, 0x41, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, - 0x41, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x03, 0x42, 0x00, 0x00, 0x00, - 0x41, 0x00, 0x00, 0x02, 0x42, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x01, 0x41, 0x00, 0x00, 0x02, 0x41, 0x00, 0x00, 0x03, - 0x43, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x01, 0x43, 0x00, 0x00, 0x01, 0x42, 0x00, 0x00, 0x02, - 0x42, 0x00, 0x00, 0x03, 0x44, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, - 0x43, 0x00, 0x00, 0x02, 0x43, 0x00, 0x00, 0x03, 0x45, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x01, - 0x45, 0x00, 0x00, 0x01, 0x44, 0x00, 0x00, 0x02, 0x44, 0x00, 0x00, 0x03, 0x46, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x02, - 0x46, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x01, 0x45, 0x00, 0x00, 0x02, 0x45, 0x00, 0x00, 0x03, 0x47, 0x00, 0x00, 0x00, - 0x46, 0x00, 0x00, 0x02, 0x47, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x01, 0x46, 0x00, 0x00, 0x02, 0x46, 0x00, 0x00, 0x03, - 0x48, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x01, 0x47, 0x00, 0x00, 0x02, - 0x47, 0x00, 0x00, 0x03, 0x49, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, 0x49, 0x00, 0x00, 0x01, 0x49, 0x00, 0x00, 0x01, - 0x48, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x03, 0x4a, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x4a, 0x00, 0x00, - 0x4b, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x4d, 0x00, - 0x00, 0x4d, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x4f, - 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x00, 0x00, 0x51, 0x00, 0x00, 0x51, 0x00, 0x00, - 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x52, 0x00, 0x00, 0x52, 0x00, 0x00, 0x53, 0x00, 0x00, 0x53, 0x00, 0x00, 0x54, 0x00, - 0x00, 0x55, 0x00, 0x00, 0x54, 0x00, 0x00, 0x54, 0x00, 0x00, 0x55, 0x00, 0x00, 0x55, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, - 0x00, 0x00, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, 0x57, 0x00, 0x00, 0x57, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, - 0x58, 0x00, 0x00, 0x58, 0x00, 0x00, 0x59, 0x00, 0x00, 0x59, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5a, 0x00, - 0x00, 0x5a, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5b, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x5c, - 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5d, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x5e, 0x00, 0x00, - 0x5f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x61, 0x00, - 0x00, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x62, 0x00, 0x00, 0x62, 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, - 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x64, 0x00, 0x00, 0x64, 0x00, 0x00, 0x65, 0x00, 0x00, 0x65, 0x00, 0x00, - 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0x67, 0x00, 0x00, 0x67, 0x00, 0x00, 0x68, 0x00, - 0x00, 0x69, 0x00, 0x00, 0x68, 0x00, 0x00, 0x68, 0x00, 0x00, 0x69, 0x00, 0x00, 0x69, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, - 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, - 0x6c, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6e, 0x00, - 0x00, 0x6e, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x70, 0x00, 0x00, 0x71, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, - 0x00, 0x00, 0x71, 0x00, 0x00, 0x71, 0x00, 0x00, 0x72, 0x00, 0x00, 0x73, 0x00, 0x00, 0x72, 0x00, 0x00, 0x72, 0x00, 0x00, - 0x73, 0x00, 0x00, 0x73, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, 0x00, 0x74, 0x00, 0x00, 0x74, 0x00, 0x00, 0x75, 0x00, - 0x00, 0x75, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x76, 0x00, 0x00, 0x76, 0x00, 0x00, 0x77, 0x00, 0x00, 0x77, - 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0x79, 0x00, 0x00, 0x79, 0x00, 0x00, - 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7b, 0x00, 0x00, 0x7c, 0x00, - 0x00, 0x7d, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x81, 0x00, 0x00, 0x81, 0x00, 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x82, 0x00, - 0x00, 0x82, 0x00, 0x00, 0x83, 0x00, 0x00, 0x83, 0x00, 0x00, 0x84, 0x00, 0x00, 0x85, 0x00, 0x00, 0x84, 0x00, 0x00, 0x84, - 0x00, 0x00, 0x85, 0x00, 0x00, 0x85, 0x00, 0x00, 0x86, 0x00, 0x00, 0x87, 0x00, 0x00, 0x86, 0x00, 0x00, 0x86, 0x00, 0x00, - 0x87, 0x00, 0x00, 0x87, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, 0x00, 0x88, 0x00, 0x00, 0x88, 0x00, 0x00, 0x89, 0x00, - 0x00, 0x89, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x8b, - 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x8d, 0x00, 0x00, 0x8d, 0x00, 0x00, - 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x90, 0x00, - 0x00, 0x91, 0x00, 0x00, 0x90, 0x00, 0x00, 0x90, 0x00, 0x00, 0x91, 0x00, 0x00, 0x91, 0x00, 0x00, 0x4b, 0x00, 0x00, 0x00, - 0x4a, 0x00, 0x00, 0x02, 0x4b, 0x00, 0x00, 0x01, 0x4b, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x00, 0x02, 0x4a, 0x00, 0x00, 0x03, - 0x4d, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x02, 0x4d, 0x00, 0x00, 0x01, 0x4d, 0x00, 0x00, 0x01, 0x4c, 0x00, 0x00, 0x02, - 0x4c, 0x00, 0x00, 0x03, 0x4f, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x02, 0x4f, 0x00, 0x00, 0x01, 0x4f, 0x00, 0x00, 0x01, - 0x4e, 0x00, 0x00, 0x02, 0x4e, 0x00, 0x00, 0x03, 0x51, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x02, 0x51, 0x00, 0x00, 0x01, - 0x51, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x02, 0x50, 0x00, 0x00, 0x03, 0x53, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x02, - 0x53, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x01, 0x52, 0x00, 0x00, 0x02, 0x52, 0x00, 0x00, 0x03, 0x55, 0x00, 0x00, 0x00, - 0x54, 0x00, 0x00, 0x02, 0x55, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x03, - 0x57, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00, 0x02, 0x57, 0x00, 0x00, 0x01, 0x57, 0x00, 0x00, 0x01, 0x56, 0x00, 0x00, 0x02, - 0x56, 0x00, 0x00, 0x03, 0x59, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x02, 0x59, 0x00, 0x00, 0x01, 0x59, 0x00, 0x00, 0x01, - 0x58, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x03, 0x5b, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x01, - 0x5b, 0x00, 0x00, 0x01, 0x5a, 0x00, 0x00, 0x02, 0x5a, 0x00, 0x00, 0x03, 0x5d, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x02, - 0x5d, 0x00, 0x00, 0x01, 0x5d, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x00, 0x02, 0x5c, 0x00, 0x00, 0x03, 0x5f, 0x00, 0x00, 0x00, - 0x5e, 0x00, 0x00, 0x02, 0x5f, 0x00, 0x00, 0x01, 0x5f, 0x00, 0x00, 0x01, 0x5e, 0x00, 0x00, 0x02, 0x5e, 0x00, 0x00, 0x03, - 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x02, 0x61, 0x00, 0x00, 0x01, 0x61, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x02, - 0x60, 0x00, 0x00, 0x03, 0x63, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x02, 0x63, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x01, - 0x62, 0x00, 0x00, 0x02, 0x62, 0x00, 0x00, 0x03, 0x65, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x02, 0x65, 0x00, 0x00, 0x01, - 0x65, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x03, 0x67, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x02, - 0x67, 0x00, 0x00, 0x01, 0x67, 0x00, 0x00, 0x01, 0x66, 0x00, 0x00, 0x02, 0x66, 0x00, 0x00, 0x03, 0x69, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x02, 0x69, 0x00, 0x00, 0x01, 0x69, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00, 0x02, 0x68, 0x00, 0x00, 0x03, - 0x6b, 0x00, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x02, 0x6b, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6a, 0x00, 0x00, 0x02, - 0x6a, 0x00, 0x00, 0x03, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x02, 0x6d, 0x00, 0x00, 0x01, 0x6d, 0x00, 0x00, 0x01, - 0x6c, 0x00, 0x00, 0x02, 0x6c, 0x00, 0x00, 0x03, 0x6f, 0x00, 0x00, 0x00, 0x6e, 0x00, 0x00, 0x02, 0x6f, 0x00, 0x00, 0x01, - 0x6f, 0x00, 0x00, 0x01, 0x6e, 0x00, 0x00, 0x02, 0x6e, 0x00, 0x00, 0x03, 0x71, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x02, - 0x71, 0x00, 0x00, 0x01, 0x71, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x02, 0x70, 0x00, 0x00, 0x03, 0x73, 0x00, 0x00, 0x00, - 0x72, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x01, 0x73, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00, 0x02, 0x72, 0x00, 0x00, 0x03, - 0x75, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x02, 0x75, 0x00, 0x00, 0x01, 0x75, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x02, - 0x74, 0x00, 0x00, 0x03, 0x77, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x02, 0x77, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, - 0x76, 0x00, 0x00, 0x02, 0x76, 0x00, 0x00, 0x03, 0x79, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x02, 0x79, 0x00, 0x00, 0x01, - 0x79, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x02, 0x78, 0x00, 0x00, 0x03, 0x7b, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x00, 0x02, - 0x7b, 0x00, 0x00, 0x01, 0x7b, 0x00, 0x00, 0x01, 0x7a, 0x00, 0x00, 0x02, 0x7a, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x00, - 0x7c, 0x00, 0x00, 0x02, 0x7d, 0x00, 0x00, 0x01, 0x7d, 0x00, 0x00, 0x01, 0x7c, 0x00, 0x00, 0x02, 0x7c, 0x00, 0x00, 0x03, - 0x7f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x01, 0x7f, 0x00, 0x00, 0x01, 0x7e, 0x00, 0x00, 0x02, - 0x7e, 0x00, 0x00, 0x03, 0x81, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, 0x81, 0x00, 0x00, 0x01, 0x81, 0x00, 0x00, 0x01, - 0x80, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x03, 0x83, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00, 0x01, - 0x83, 0x00, 0x00, 0x01, 0x82, 0x00, 0x00, 0x02, 0x82, 0x00, 0x00, 0x03, 0x85, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x02, - 0x85, 0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x02, 0x84, 0x00, 0x00, 0x03, 0x87, 0x00, 0x00, 0x00, - 0x86, 0x00, 0x00, 0x02, 0x87, 0x00, 0x00, 0x01, 0x87, 0x00, 0x00, 0x01, 0x86, 0x00, 0x00, 0x02, 0x86, 0x00, 0x00, 0x03, - 0x89, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x02, 0x89, 0x00, 0x00, 0x01, 0x89, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x02, - 0x88, 0x00, 0x00, 0x03, 0x8b, 0x00, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x02, 0x8b, 0x00, 0x00, 0x01, 0x8b, 0x00, 0x00, 0x01, - 0x8a, 0x00, 0x00, 0x02, 0x8a, 0x00, 0x00, 0x03, 0x8d, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x02, 0x8d, 0x00, 0x00, 0x01, - 0x8d, 0x00, 0x00, 0x01, 0x8c, 0x00, 0x00, 0x02, 0x8c, 0x00, 0x00, 0x03, 0x8f, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x02, - 0x8f, 0x00, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x01, 0x8e, 0x00, 0x00, 0x02, 0x8e, 0x00, 0x00, 0x03, 0x91, 0x00, 0x00, 0x00, - 0x90, 0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x01, 0x91, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x02, 0x90, 0x00, 0x00, 0x03, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, - 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, - 0xf5, 0x8a, 0xe4, 0x9a, 0xf5, 0x8a, 0xe4, 0x9a, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, - 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xe4, 0x9a, 0xd6, 0xa8, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, - 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xd6, 0xa8, 0xca, 0xb4, 0xca, 0xb4, 0xbf, 0xbf, - 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, 0xca, 0xb4, 0xbf, 0xbf, - 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, 0xbf, 0xbf, 0xb4, 0xca, - 0xbf, 0xbf, 0xb4, 0xca, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, - 0xb4, 0xca, 0xa8, 0xd6, 0xb4, 0xca, 0xa8, 0xd6, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, - 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0xa8, 0xd6, 0x9a, 0xe4, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, - 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x9a, 0xe4, 0x8a, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, - 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, 0x8a, 0xf5, 0x75, 0xf5, - 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, 0x75, 0xf5, 0x65, 0xe4, - 0x75, 0xf5, 0x65, 0xe4, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, - 0x65, 0xe4, 0x57, 0xd6, 0x65, 0xe4, 0x57, 0xd6, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, - 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x57, 0xd6, 0x4b, 0xca, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, - 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x4b, 0xca, 0x40, 0xbf, 0x40, 0xbf, 0x35, 0xb4, - 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, 0x40, 0xbf, 0x35, 0xb4, - 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, 0x35, 0xb4, 0x29, 0xa8, - 0x35, 0xb4, 0x29, 0xa8, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, - 0x29, 0xa8, 0x1b, 0x9a, 0x29, 0xa8, 0x1b, 0x9a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, - 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x1b, 0x9a, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, - 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x75, 0x1b, 0x65, - 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, 0x0a, 0x75, 0x1b, 0x65, - 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, 0x1b, 0x65, 0x29, 0x57, - 0x1b, 0x65, 0x29, 0x57, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, - 0x29, 0x57, 0x35, 0x4b, 0x29, 0x57, 0x35, 0x4b, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, - 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x35, 0x4b, 0x40, 0x40, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, - 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x40, 0x40, 0x4b, 0x35, 0x4b, 0x35, 0x57, 0x29, - 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, 0x4b, 0x35, 0x57, 0x29, - 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, 0x57, 0x29, 0x65, 0x1b, - 0x57, 0x29, 0x65, 0x1b, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, - 0x65, 0x1b, 0x75, 0x0a, 0x65, 0x1b, 0x75, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, - 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x75, 0x0a, 0x8a, 0x0a, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, - 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x8a, 0x0a, 0x9a, 0x1b, 0x9a, 0x1b, 0xa8, 0x29, - 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, 0x9a, 0x1b, 0xa8, 0x29, - 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, 0xa8, 0x29, 0xb4, 0x35, - 0xa8, 0x29, 0xb4, 0x35, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, - 0xb4, 0x35, 0xbf, 0x40, 0xb4, 0x35, 0xbf, 0x40, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, - 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xbf, 0x40, 0xca, 0x4b, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, - 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xca, 0x4b, 0xd6, 0x57, 0xd6, 0x57, 0xe4, 0x65, - 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, 0xd6, 0x57, 0xe4, 0x65, - 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, 0xe4, 0x65, 0xf5, 0x75, - 0xe4, 0x65, 0xf5, 0x75, + 0x69, + 0x4d, + 0x64, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x00, + 0x58, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x39, + 0xd6, + 0xc5, + 0x6d, + 0x34, + 0x00, + 0x00, + 0xc0, + 0x56, + 0xc1, + 0xa8, + 0xa4, + 0x4e, + 0x00, + 0x08, + 0xc0, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0x8e, + 0x53, + 0x74, + 0x24, + 0x97, + 0xff, + 0xff, + 0x3f, + 0xaa, + 0x3e, + 0x57, + 0x5b, + 0xb1, + 0xff, + 0x07, + 0x40, + 0xc6, + 0x37, + 0x3a, + 0x87, + 0xb1, + 0x7e, + 0x80, + 0x3f, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x74, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x01, + 0x00, + 0x00, + 0x00, + 0xfc, + 0x2a, + 0x00, + 0x00, + 0xa0, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x37, + 0x32, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x34, + 0x39, + 0x32, + 0x38, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x37, + 0x33, + 0x30, + 0x34, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x33, + 0x36, + 0x33, + 0x32, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x36, + 0x34, + 0x38, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x36, + 0x36, + 0x35, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x32, + 0x39, + 0x36, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x32, + 0x33, + 0x33, + 0x36, + 0x7d, + 0x2c, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4c, + 0x65, + 0x6e, + 0x67, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x38, + 0x36, + 0x34, + 0x2c, + 0x22, + 0x62, + 0x79, + 0x74, + 0x65, + 0x4f, + 0x66, + 0x66, + 0x73, + 0x65, + 0x74, + 0x22, + 0x3a, + 0x38, + 0x31, + 0x36, + 0x38, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x65, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4b, + 0x48, + 0x52, + 0x5f, + 0x62, + 0x69, + 0x6e, + 0x61, + 0x72, + 0x79, + 0x5f, + 0x67, + 0x6c, + 0x54, + 0x46, + 0x22, + 0x2c, + 0x22, + 0x57, + 0x45, + 0x42, + 0x33, + 0x44, + 0x5f, + 0x71, + 0x75, + 0x61, + 0x6e, + 0x74, + 0x69, + 0x7a, + 0x65, + 0x64, + 0x5f, + 0x61, + 0x74, + 0x74, + 0x72, + 0x69, + 0x62, + 0x75, + 0x74, + 0x65, + 0x73, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x67, + 0x6c, + 0x45, + 0x78, + 0x74, + 0x65, + 0x6e, + 0x73, + 0x69, + 0x6f, + 0x6e, + 0x73, + 0x55, + 0x73, + 0x65, + 0x64, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x4f, + 0x45, + 0x53, + 0x5f, + 0x65, + 0x6c, + 0x65, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x5f, + 0x69, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x5f, + 0x75, + 0x69, + 0x6e, + 0x74, + 0x22, + 0x5d, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x63, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x37, + 0x22, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x69, + 0x6c, + 0x6c, + 0x46, + 0x6c, + 0x61, + 0x67, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x69, + 0x67, + 0x6e, + 0x6f, + 0x72, + 0x65, + 0x4c, + 0x69, + 0x67, + 0x68, + 0x74, + 0x69, + 0x6e, + 0x67, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x50, + 0x69, + 0x78, + 0x65, + 0x6c, + 0x73, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x6c, + 0x69, + 0x6e, + 0x65, + 0x57, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x62, + 0x43, + 0x61, + 0x74, + 0x65, + 0x67, + 0x6f, + 0x72, + 0x79, + 0x49, + 0x64, + 0x22, + 0x3a, + 0x22, + 0x30, + 0x78, + 0x31, + 0x38, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6d, + 0x65, + 0x73, + 0x68, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x70, + 0x72, + 0x69, + 0x6d, + 0x69, + 0x74, + 0x69, + 0x76, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x7b, + 0x22, + 0x65, + 0x64, + 0x67, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x73, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x65, + 0x67, + 0x6d, + 0x65, + 0x6e, + 0x74, + 0x73, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x65, + 0x6e, + 0x64, + 0x50, + 0x6f, + 0x69, + 0x6e, + 0x74, + 0x41, + 0x6e, + 0x64, + 0x51, + 0x75, + 0x61, + 0x64, + 0x49, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x6e, + 0x6f, + 0x72, + 0x6d, + 0x61, + 0x6c, + 0x50, + 0x61, + 0x69, + 0x72, + 0x73, + 0x30, + 0x53, + 0x69, + 0x6c, + 0x68, + 0x6f, + 0x75, + 0x65, + 0x74, + 0x74, + 0x65, + 0x73, + 0x22, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x69, + 0x73, + 0x50, + 0x6c, + 0x61, + 0x6e, + 0x61, + 0x72, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x6d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x61, + 0x74, + 0x65, + 0x72, + 0x69, + 0x61, + 0x6c, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x69, + 0x6e, + 0x64, + 0x69, + 0x63, + 0x65, + 0x73, + 0x30, + 0x53, + 0x75, + 0x72, + 0x66, + 0x61, + 0x63, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x7d, + 0x2c, + 0x22, + 0x74, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x76, + 0x65, + 0x72, + 0x74, + 0x69, + 0x63, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x62, + 0x75, + 0x66, + 0x66, + 0x65, + 0x72, + 0x56, + 0x69, + 0x65, + 0x77, + 0x22, + 0x3a, + 0x22, + 0x62, + 0x76, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x30, + 0x22, + 0x2c, + 0x22, + 0x63, + 0x6f, + 0x75, + 0x6e, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x34, + 0x36, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x44, + 0x22, + 0x3a, + 0x30, + 0x2c, + 0x22, + 0x66, + 0x65, + 0x61, + 0x74, + 0x75, + 0x72, + 0x65, + 0x49, + 0x6e, + 0x64, + 0x65, + 0x78, + 0x54, + 0x79, + 0x70, + 0x65, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x68, + 0x61, + 0x73, + 0x54, + 0x72, + 0x61, + 0x6e, + 0x73, + 0x6c, + 0x75, + 0x63, + 0x65, + 0x6e, + 0x63, + 0x79, + 0x22, + 0x3a, + 0x66, + 0x61, + 0x6c, + 0x73, + 0x65, + 0x2c, + 0x22, + 0x68, + 0x65, + 0x69, + 0x67, + 0x68, + 0x74, + 0x22, + 0x3a, + 0x31, + 0x2c, + 0x22, + 0x6e, + 0x75, + 0x6d, + 0x52, + 0x67, + 0x62, + 0x61, + 0x50, + 0x65, + 0x72, + 0x56, + 0x65, + 0x72, + 0x74, + 0x65, + 0x78, + 0x22, + 0x3a, + 0x34, + 0x2c, + 0x22, + 0x70, + 0x61, + 0x72, + 0x61, + 0x6d, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x4d, + 0x61, + 0x74, + 0x72, + 0x69, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x36, + 0x2e, + 0x31, + 0x30, + 0x34, + 0x35, + 0x32, + 0x34, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x32, + 0x33, + 0x37, + 0x30, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x39, + 0x2e, + 0x31, + 0x35, + 0x36, + 0x37, + 0x38, + 0x36, + 0x34, + 0x34, + 0x39, + 0x39, + 0x38, + 0x38, + 0x35, + 0x35, + 0x35, + 0x30, + 0x65, + 0x2d, + 0x30, + 0x35, + 0x2c, + 0x30, + 0x2e, + 0x30, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x2c, + 0x31, + 0x2e, + 0x30, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x61, + 0x78, + 0x22, + 0x3a, + 0x5b, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x2c, + 0x22, + 0x64, + 0x65, + 0x63, + 0x6f, + 0x64, + 0x65, + 0x64, + 0x4d, + 0x69, + 0x6e, + 0x22, + 0x3a, + 0x5b, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x32, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x32, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x37, + 0x2c, + 0x2d, + 0x33, + 0x2e, + 0x30, + 0x30, + 0x30, + 0x34, + 0x34, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x39, + 0x38, + 0x5d, + 0x7d, + 0x2c, + 0x22, + 0x75, + 0x6e, + 0x69, + 0x66, + 0x6f, + 0x72, + 0x6d, + 0x43, + 0x6f, + 0x6c, + 0x6f, + 0x72, + 0x22, + 0x3a, + 0x36, + 0x35, + 0x32, + 0x38, + 0x30, + 0x2c, + 0x22, + 0x77, + 0x69, + 0x64, + 0x74, + 0x68, + 0x22, + 0x3a, + 0x35, + 0x38, + 0x34, + 0x7d, + 0x7d, + 0x5d, + 0x7d, + 0x7d, + 0x2c, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x3a, + 0x22, + 0x4d, + 0x65, + 0x73, + 0x68, + 0x5f, + 0x52, + 0x6f, + 0x6f, + 0x74, + 0x22, + 0x7d, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x2c, + 0x22, + 0x73, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x64, + 0x65, + 0x66, + 0x61, + 0x75, + 0x6c, + 0x74, + 0x53, + 0x63, + 0x65, + 0x6e, + 0x65, + 0x22, + 0x3a, + 0x7b, + 0x22, + 0x6e, + 0x6f, + 0x64, + 0x65, + 0x73, + 0x22, + 0x3a, + 0x5b, + 0x22, + 0x72, + 0x6f, + 0x6f, + 0x74, + 0x4e, + 0x6f, + 0x64, + 0x65, + 0x22, + 0x5d, + 0x7d, + 0x7d, + 0x7d, + 0x0a, + 0x20, + 0x20, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0xff, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0xf8, + 0xff, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x80, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x93, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0xa2, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0xae, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0xba, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0xc5, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0xd0, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0xdd, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0xec, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xff, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0x07, + 0xfe, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0xec, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0x41, + 0xf8, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0xdd, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0xd3, + 0xee, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0xd0, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0x07, + 0xe2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0xc5, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0x41, + 0xd2, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0xba, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0xfb, + 0xbf, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0xae, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0xc3, + 0xab, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0xa2, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0x37, + 0x96, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x93, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0x03, + 0x00, + 0xfe, + 0x7f, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xf5, + 0x01, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x13, + 0x6c, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0xbb, + 0x07, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x22, + 0x5d, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0x29, + 0x11, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x51, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xf4, + 0x1d, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x45, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0xba, + 0x2d, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x45, + 0x3a, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x01, + 0x40, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x51, + 0x2f, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0x38, + 0x54, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x5d, + 0x22, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xc5, + 0x69, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x13, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0xfe, + 0x7f, + 0x03, + 0x00, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x7f, + 0x00, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0x37, + 0x96, + 0xf5, + 0x01, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x93, + 0x13, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xc3, + 0xab, + 0xbb, + 0x07, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xa2, + 0x22, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0xfb, + 0xbf, + 0x29, + 0x11, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xae, + 0x2f, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x41, + 0xd2, + 0xf4, + 0x1d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xba, + 0x3a, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0x07, + 0xe2, + 0xba, + 0x2d, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xc5, + 0x45, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0xd3, + 0xee, + 0x01, + 0x40, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xd0, + 0x51, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x41, + 0xf8, + 0x38, + 0x54, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xdd, + 0x5d, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x07, + 0xfe, + 0xc5, + 0x69, + 0xf8, + 0xff, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xec, + 0x6c, + 0xcc, + 0xcc, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x26, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x49, + 0x00, + 0x00, + 0x24, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x03, + 0x24, + 0x00, + 0x00, + 0x00, + 0x23, + 0x00, + 0x00, + 0x02, + 0x24, + 0x00, + 0x00, + 0x01, + 0x24, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x03, + 0x23, + 0x00, + 0x00, + 0x00, + 0x22, + 0x00, + 0x00, + 0x02, + 0x23, + 0x00, + 0x00, + 0x01, + 0x23, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x03, + 0x22, + 0x00, + 0x00, + 0x00, + 0x21, + 0x00, + 0x00, + 0x02, + 0x22, + 0x00, + 0x00, + 0x01, + 0x22, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x03, + 0x21, + 0x00, + 0x00, + 0x00, + 0x20, + 0x00, + 0x00, + 0x02, + 0x21, + 0x00, + 0x00, + 0x01, + 0x21, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x03, + 0x20, + 0x00, + 0x00, + 0x00, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x20, + 0x00, + 0x00, + 0x01, + 0x20, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x03, + 0x1f, + 0x00, + 0x00, + 0x00, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1f, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x03, + 0x1e, + 0x00, + 0x00, + 0x00, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1e, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x03, + 0x1d, + 0x00, + 0x00, + 0x00, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1d, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x03, + 0x1c, + 0x00, + 0x00, + 0x00, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1c, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x03, + 0x1b, + 0x00, + 0x00, + 0x00, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1b, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x03, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x19, + 0x00, + 0x00, + 0x02, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x1a, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x03, + 0x19, + 0x00, + 0x00, + 0x00, + 0x18, + 0x00, + 0x00, + 0x02, + 0x19, + 0x00, + 0x00, + 0x01, + 0x19, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x03, + 0x18, + 0x00, + 0x00, + 0x00, + 0x17, + 0x00, + 0x00, + 0x02, + 0x18, + 0x00, + 0x00, + 0x01, + 0x18, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x03, + 0x17, + 0x00, + 0x00, + 0x00, + 0x16, + 0x00, + 0x00, + 0x02, + 0x17, + 0x00, + 0x00, + 0x01, + 0x17, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x03, + 0x16, + 0x00, + 0x00, + 0x00, + 0x15, + 0x00, + 0x00, + 0x02, + 0x16, + 0x00, + 0x00, + 0x01, + 0x16, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x03, + 0x15, + 0x00, + 0x00, + 0x00, + 0x14, + 0x00, + 0x00, + 0x02, + 0x15, + 0x00, + 0x00, + 0x01, + 0x15, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x03, + 0x14, + 0x00, + 0x00, + 0x00, + 0x13, + 0x00, + 0x00, + 0x02, + 0x14, + 0x00, + 0x00, + 0x01, + 0x14, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x03, + 0x13, + 0x00, + 0x00, + 0x00, + 0x12, + 0x00, + 0x00, + 0x02, + 0x13, + 0x00, + 0x00, + 0x01, + 0x13, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x03, + 0x12, + 0x00, + 0x00, + 0x00, + 0x11, + 0x00, + 0x00, + 0x02, + 0x12, + 0x00, + 0x00, + 0x01, + 0x12, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x03, + 0x11, + 0x00, + 0x00, + 0x00, + 0x10, + 0x00, + 0x00, + 0x02, + 0x11, + 0x00, + 0x00, + 0x01, + 0x11, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x03, + 0x10, + 0x00, + 0x00, + 0x00, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x10, + 0x00, + 0x00, + 0x01, + 0x10, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x03, + 0x0f, + 0x00, + 0x00, + 0x00, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0f, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x03, + 0x0e, + 0x00, + 0x00, + 0x00, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0e, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x03, + 0x0d, + 0x00, + 0x00, + 0x00, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0d, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x03, + 0x0c, + 0x00, + 0x00, + 0x00, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0c, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x03, + 0x0b, + 0x00, + 0x00, + 0x00, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0b, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x03, + 0x0a, + 0x00, + 0x00, + 0x00, + 0x09, + 0x00, + 0x00, + 0x02, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x0a, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x03, + 0x09, + 0x00, + 0x00, + 0x00, + 0x08, + 0x00, + 0x00, + 0x02, + 0x09, + 0x00, + 0x00, + 0x01, + 0x09, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x03, + 0x08, + 0x00, + 0x00, + 0x00, + 0x07, + 0x00, + 0x00, + 0x02, + 0x08, + 0x00, + 0x00, + 0x01, + 0x08, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x03, + 0x07, + 0x00, + 0x00, + 0x00, + 0x06, + 0x00, + 0x00, + 0x02, + 0x07, + 0x00, + 0x00, + 0x01, + 0x07, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x03, + 0x06, + 0x00, + 0x00, + 0x00, + 0x05, + 0x00, + 0x00, + 0x02, + 0x06, + 0x00, + 0x00, + 0x01, + 0x06, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x03, + 0x05, + 0x00, + 0x00, + 0x00, + 0x04, + 0x00, + 0x00, + 0x02, + 0x05, + 0x00, + 0x00, + 0x01, + 0x05, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x03, + 0x04, + 0x00, + 0x00, + 0x00, + 0x03, + 0x00, + 0x00, + 0x02, + 0x04, + 0x00, + 0x00, + 0x01, + 0x04, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x03, + 0x03, + 0x00, + 0x00, + 0x00, + 0x02, + 0x00, + 0x00, + 0x02, + 0x03, + 0x00, + 0x00, + 0x01, + 0x03, + 0x00, + 0x00, + 0x01, + 0x02, + 0x00, + 0x00, + 0x02, + 0x02, + 0x00, + 0x00, + 0x03, + 0x27, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x25, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x25, + 0x00, + 0x00, + 0x02, + 0x25, + 0x00, + 0x00, + 0x03, + 0x28, + 0x00, + 0x00, + 0x00, + 0x27, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x01, + 0x27, + 0x00, + 0x00, + 0x02, + 0x27, + 0x00, + 0x00, + 0x03, + 0x29, + 0x00, + 0x00, + 0x00, + 0x28, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x01, + 0x28, + 0x00, + 0x00, + 0x02, + 0x28, + 0x00, + 0x00, + 0x03, + 0x2a, + 0x00, + 0x00, + 0x00, + 0x29, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x01, + 0x29, + 0x00, + 0x00, + 0x02, + 0x29, + 0x00, + 0x00, + 0x03, + 0x2b, + 0x00, + 0x00, + 0x00, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x01, + 0x2a, + 0x00, + 0x00, + 0x02, + 0x2a, + 0x00, + 0x00, + 0x03, + 0x2c, + 0x00, + 0x00, + 0x00, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x01, + 0x2b, + 0x00, + 0x00, + 0x02, + 0x2b, + 0x00, + 0x00, + 0x03, + 0x2d, + 0x00, + 0x00, + 0x00, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x01, + 0x2c, + 0x00, + 0x00, + 0x02, + 0x2c, + 0x00, + 0x00, + 0x03, + 0x2e, + 0x00, + 0x00, + 0x00, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x01, + 0x2d, + 0x00, + 0x00, + 0x02, + 0x2d, + 0x00, + 0x00, + 0x03, + 0x2f, + 0x00, + 0x00, + 0x00, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x01, + 0x2e, + 0x00, + 0x00, + 0x02, + 0x2e, + 0x00, + 0x00, + 0x03, + 0x30, + 0x00, + 0x00, + 0x00, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x01, + 0x2f, + 0x00, + 0x00, + 0x02, + 0x2f, + 0x00, + 0x00, + 0x03, + 0x31, + 0x00, + 0x00, + 0x00, + 0x30, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x01, + 0x30, + 0x00, + 0x00, + 0x02, + 0x30, + 0x00, + 0x00, + 0x03, + 0x32, + 0x00, + 0x00, + 0x00, + 0x31, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x01, + 0x31, + 0x00, + 0x00, + 0x02, + 0x31, + 0x00, + 0x00, + 0x03, + 0x33, + 0x00, + 0x00, + 0x00, + 0x32, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x01, + 0x32, + 0x00, + 0x00, + 0x02, + 0x32, + 0x00, + 0x00, + 0x03, + 0x34, + 0x00, + 0x00, + 0x00, + 0x33, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x01, + 0x33, + 0x00, + 0x00, + 0x02, + 0x33, + 0x00, + 0x00, + 0x03, + 0x35, + 0x00, + 0x00, + 0x00, + 0x34, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x02, + 0x34, + 0x00, + 0x00, + 0x03, + 0x36, + 0x00, + 0x00, + 0x00, + 0x35, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x01, + 0x35, + 0x00, + 0x00, + 0x02, + 0x35, + 0x00, + 0x00, + 0x03, + 0x37, + 0x00, + 0x00, + 0x00, + 0x36, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x01, + 0x36, + 0x00, + 0x00, + 0x02, + 0x36, + 0x00, + 0x00, + 0x03, + 0x38, + 0x00, + 0x00, + 0x00, + 0x37, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x01, + 0x37, + 0x00, + 0x00, + 0x02, + 0x37, + 0x00, + 0x00, + 0x03, + 0x39, + 0x00, + 0x00, + 0x00, + 0x38, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x01, + 0x38, + 0x00, + 0x00, + 0x02, + 0x38, + 0x00, + 0x00, + 0x03, + 0x3a, + 0x00, + 0x00, + 0x00, + 0x39, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x01, + 0x39, + 0x00, + 0x00, + 0x02, + 0x39, + 0x00, + 0x00, + 0x03, + 0x3b, + 0x00, + 0x00, + 0x00, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x01, + 0x3a, + 0x00, + 0x00, + 0x02, + 0x3a, + 0x00, + 0x00, + 0x03, + 0x3c, + 0x00, + 0x00, + 0x00, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x01, + 0x3b, + 0x00, + 0x00, + 0x02, + 0x3b, + 0x00, + 0x00, + 0x03, + 0x3d, + 0x00, + 0x00, + 0x00, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x01, + 0x3c, + 0x00, + 0x00, + 0x02, + 0x3c, + 0x00, + 0x00, + 0x03, + 0x3e, + 0x00, + 0x00, + 0x00, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x01, + 0x3d, + 0x00, + 0x00, + 0x02, + 0x3d, + 0x00, + 0x00, + 0x03, + 0x3f, + 0x00, + 0x00, + 0x00, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x01, + 0x3e, + 0x00, + 0x00, + 0x02, + 0x3e, + 0x00, + 0x00, + 0x03, + 0x40, + 0x00, + 0x00, + 0x00, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x01, + 0x3f, + 0x00, + 0x00, + 0x02, + 0x3f, + 0x00, + 0x00, + 0x03, + 0x41, + 0x00, + 0x00, + 0x00, + 0x40, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x01, + 0x40, + 0x00, + 0x00, + 0x02, + 0x40, + 0x00, + 0x00, + 0x03, + 0x42, + 0x00, + 0x00, + 0x00, + 0x41, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x01, + 0x41, + 0x00, + 0x00, + 0x02, + 0x41, + 0x00, + 0x00, + 0x03, + 0x43, + 0x00, + 0x00, + 0x00, + 0x42, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x01, + 0x42, + 0x00, + 0x00, + 0x02, + 0x42, + 0x00, + 0x00, + 0x03, + 0x44, + 0x00, + 0x00, + 0x00, + 0x43, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x01, + 0x43, + 0x00, + 0x00, + 0x02, + 0x43, + 0x00, + 0x00, + 0x03, + 0x45, + 0x00, + 0x00, + 0x00, + 0x44, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x01, + 0x44, + 0x00, + 0x00, + 0x02, + 0x44, + 0x00, + 0x00, + 0x03, + 0x46, + 0x00, + 0x00, + 0x00, + 0x45, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x01, + 0x45, + 0x00, + 0x00, + 0x02, + 0x45, + 0x00, + 0x00, + 0x03, + 0x47, + 0x00, + 0x00, + 0x00, + 0x46, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x01, + 0x46, + 0x00, + 0x00, + 0x02, + 0x46, + 0x00, + 0x00, + 0x03, + 0x48, + 0x00, + 0x00, + 0x00, + 0x47, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x01, + 0x47, + 0x00, + 0x00, + 0x02, + 0x47, + 0x00, + 0x00, + 0x03, + 0x49, + 0x00, + 0x00, + 0x00, + 0x48, + 0x00, + 0x00, + 0x02, + 0x49, + 0x00, + 0x00, + 0x01, + 0x49, + 0x00, + 0x00, + 0x01, + 0x48, + 0x00, + 0x00, + 0x02, + 0x48, + 0x00, + 0x00, + 0x03, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4d, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x4f, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x51, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x53, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x55, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x57, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x59, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5b, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5d, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x5f, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x61, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x63, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x65, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x67, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x69, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6b, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6d, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x6f, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x71, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x73, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x75, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x77, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x79, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7b, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7d, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x7f, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x81, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x83, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x85, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x87, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x89, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8b, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8d, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x8f, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x91, + 0x00, + 0x00, + 0x4b, + 0x00, + 0x00, + 0x00, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4b, + 0x00, + 0x00, + 0x01, + 0x4a, + 0x00, + 0x00, + 0x02, + 0x4a, + 0x00, + 0x00, + 0x03, + 0x4d, + 0x00, + 0x00, + 0x00, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4d, + 0x00, + 0x00, + 0x01, + 0x4c, + 0x00, + 0x00, + 0x02, + 0x4c, + 0x00, + 0x00, + 0x03, + 0x4f, + 0x00, + 0x00, + 0x00, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4f, + 0x00, + 0x00, + 0x01, + 0x4e, + 0x00, + 0x00, + 0x02, + 0x4e, + 0x00, + 0x00, + 0x03, + 0x51, + 0x00, + 0x00, + 0x00, + 0x50, + 0x00, + 0x00, + 0x02, + 0x51, + 0x00, + 0x00, + 0x01, + 0x51, + 0x00, + 0x00, + 0x01, + 0x50, + 0x00, + 0x00, + 0x02, + 0x50, + 0x00, + 0x00, + 0x03, + 0x53, + 0x00, + 0x00, + 0x00, + 0x52, + 0x00, + 0x00, + 0x02, + 0x53, + 0x00, + 0x00, + 0x01, + 0x53, + 0x00, + 0x00, + 0x01, + 0x52, + 0x00, + 0x00, + 0x02, + 0x52, + 0x00, + 0x00, + 0x03, + 0x55, + 0x00, + 0x00, + 0x00, + 0x54, + 0x00, + 0x00, + 0x02, + 0x55, + 0x00, + 0x00, + 0x01, + 0x55, + 0x00, + 0x00, + 0x01, + 0x54, + 0x00, + 0x00, + 0x02, + 0x54, + 0x00, + 0x00, + 0x03, + 0x57, + 0x00, + 0x00, + 0x00, + 0x56, + 0x00, + 0x00, + 0x02, + 0x57, + 0x00, + 0x00, + 0x01, + 0x57, + 0x00, + 0x00, + 0x01, + 0x56, + 0x00, + 0x00, + 0x02, + 0x56, + 0x00, + 0x00, + 0x03, + 0x59, + 0x00, + 0x00, + 0x00, + 0x58, + 0x00, + 0x00, + 0x02, + 0x59, + 0x00, + 0x00, + 0x01, + 0x59, + 0x00, + 0x00, + 0x01, + 0x58, + 0x00, + 0x00, + 0x02, + 0x58, + 0x00, + 0x00, + 0x03, + 0x5b, + 0x00, + 0x00, + 0x00, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5b, + 0x00, + 0x00, + 0x01, + 0x5a, + 0x00, + 0x00, + 0x02, + 0x5a, + 0x00, + 0x00, + 0x03, + 0x5d, + 0x00, + 0x00, + 0x00, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5d, + 0x00, + 0x00, + 0x01, + 0x5c, + 0x00, + 0x00, + 0x02, + 0x5c, + 0x00, + 0x00, + 0x03, + 0x5f, + 0x00, + 0x00, + 0x00, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5f, + 0x00, + 0x00, + 0x01, + 0x5e, + 0x00, + 0x00, + 0x02, + 0x5e, + 0x00, + 0x00, + 0x03, + 0x61, + 0x00, + 0x00, + 0x00, + 0x60, + 0x00, + 0x00, + 0x02, + 0x61, + 0x00, + 0x00, + 0x01, + 0x61, + 0x00, + 0x00, + 0x01, + 0x60, + 0x00, + 0x00, + 0x02, + 0x60, + 0x00, + 0x00, + 0x03, + 0x63, + 0x00, + 0x00, + 0x00, + 0x62, + 0x00, + 0x00, + 0x02, + 0x63, + 0x00, + 0x00, + 0x01, + 0x63, + 0x00, + 0x00, + 0x01, + 0x62, + 0x00, + 0x00, + 0x02, + 0x62, + 0x00, + 0x00, + 0x03, + 0x65, + 0x00, + 0x00, + 0x00, + 0x64, + 0x00, + 0x00, + 0x02, + 0x65, + 0x00, + 0x00, + 0x01, + 0x65, + 0x00, + 0x00, + 0x01, + 0x64, + 0x00, + 0x00, + 0x02, + 0x64, + 0x00, + 0x00, + 0x03, + 0x67, + 0x00, + 0x00, + 0x00, + 0x66, + 0x00, + 0x00, + 0x02, + 0x67, + 0x00, + 0x00, + 0x01, + 0x67, + 0x00, + 0x00, + 0x01, + 0x66, + 0x00, + 0x00, + 0x02, + 0x66, + 0x00, + 0x00, + 0x03, + 0x69, + 0x00, + 0x00, + 0x00, + 0x68, + 0x00, + 0x00, + 0x02, + 0x69, + 0x00, + 0x00, + 0x01, + 0x69, + 0x00, + 0x00, + 0x01, + 0x68, + 0x00, + 0x00, + 0x02, + 0x68, + 0x00, + 0x00, + 0x03, + 0x6b, + 0x00, + 0x00, + 0x00, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6b, + 0x00, + 0x00, + 0x01, + 0x6a, + 0x00, + 0x00, + 0x02, + 0x6a, + 0x00, + 0x00, + 0x03, + 0x6d, + 0x00, + 0x00, + 0x00, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6d, + 0x00, + 0x00, + 0x01, + 0x6c, + 0x00, + 0x00, + 0x02, + 0x6c, + 0x00, + 0x00, + 0x03, + 0x6f, + 0x00, + 0x00, + 0x00, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6f, + 0x00, + 0x00, + 0x01, + 0x6e, + 0x00, + 0x00, + 0x02, + 0x6e, + 0x00, + 0x00, + 0x03, + 0x71, + 0x00, + 0x00, + 0x00, + 0x70, + 0x00, + 0x00, + 0x02, + 0x71, + 0x00, + 0x00, + 0x01, + 0x71, + 0x00, + 0x00, + 0x01, + 0x70, + 0x00, + 0x00, + 0x02, + 0x70, + 0x00, + 0x00, + 0x03, + 0x73, + 0x00, + 0x00, + 0x00, + 0x72, + 0x00, + 0x00, + 0x02, + 0x73, + 0x00, + 0x00, + 0x01, + 0x73, + 0x00, + 0x00, + 0x01, + 0x72, + 0x00, + 0x00, + 0x02, + 0x72, + 0x00, + 0x00, + 0x03, + 0x75, + 0x00, + 0x00, + 0x00, + 0x74, + 0x00, + 0x00, + 0x02, + 0x75, + 0x00, + 0x00, + 0x01, + 0x75, + 0x00, + 0x00, + 0x01, + 0x74, + 0x00, + 0x00, + 0x02, + 0x74, + 0x00, + 0x00, + 0x03, + 0x77, + 0x00, + 0x00, + 0x00, + 0x76, + 0x00, + 0x00, + 0x02, + 0x77, + 0x00, + 0x00, + 0x01, + 0x77, + 0x00, + 0x00, + 0x01, + 0x76, + 0x00, + 0x00, + 0x02, + 0x76, + 0x00, + 0x00, + 0x03, + 0x79, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x02, + 0x79, + 0x00, + 0x00, + 0x01, + 0x79, + 0x00, + 0x00, + 0x01, + 0x78, + 0x00, + 0x00, + 0x02, + 0x78, + 0x00, + 0x00, + 0x03, + 0x7b, + 0x00, + 0x00, + 0x00, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7b, + 0x00, + 0x00, + 0x01, + 0x7a, + 0x00, + 0x00, + 0x02, + 0x7a, + 0x00, + 0x00, + 0x03, + 0x7d, + 0x00, + 0x00, + 0x00, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7d, + 0x00, + 0x00, + 0x01, + 0x7c, + 0x00, + 0x00, + 0x02, + 0x7c, + 0x00, + 0x00, + 0x03, + 0x7f, + 0x00, + 0x00, + 0x00, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7f, + 0x00, + 0x00, + 0x01, + 0x7e, + 0x00, + 0x00, + 0x02, + 0x7e, + 0x00, + 0x00, + 0x03, + 0x81, + 0x00, + 0x00, + 0x00, + 0x80, + 0x00, + 0x00, + 0x02, + 0x81, + 0x00, + 0x00, + 0x01, + 0x81, + 0x00, + 0x00, + 0x01, + 0x80, + 0x00, + 0x00, + 0x02, + 0x80, + 0x00, + 0x00, + 0x03, + 0x83, + 0x00, + 0x00, + 0x00, + 0x82, + 0x00, + 0x00, + 0x02, + 0x83, + 0x00, + 0x00, + 0x01, + 0x83, + 0x00, + 0x00, + 0x01, + 0x82, + 0x00, + 0x00, + 0x02, + 0x82, + 0x00, + 0x00, + 0x03, + 0x85, + 0x00, + 0x00, + 0x00, + 0x84, + 0x00, + 0x00, + 0x02, + 0x85, + 0x00, + 0x00, + 0x01, + 0x85, + 0x00, + 0x00, + 0x01, + 0x84, + 0x00, + 0x00, + 0x02, + 0x84, + 0x00, + 0x00, + 0x03, + 0x87, + 0x00, + 0x00, + 0x00, + 0x86, + 0x00, + 0x00, + 0x02, + 0x87, + 0x00, + 0x00, + 0x01, + 0x87, + 0x00, + 0x00, + 0x01, + 0x86, + 0x00, + 0x00, + 0x02, + 0x86, + 0x00, + 0x00, + 0x03, + 0x89, + 0x00, + 0x00, + 0x00, + 0x88, + 0x00, + 0x00, + 0x02, + 0x89, + 0x00, + 0x00, + 0x01, + 0x89, + 0x00, + 0x00, + 0x01, + 0x88, + 0x00, + 0x00, + 0x02, + 0x88, + 0x00, + 0x00, + 0x03, + 0x8b, + 0x00, + 0x00, + 0x00, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8b, + 0x00, + 0x00, + 0x01, + 0x8a, + 0x00, + 0x00, + 0x02, + 0x8a, + 0x00, + 0x00, + 0x03, + 0x8d, + 0x00, + 0x00, + 0x00, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8d, + 0x00, + 0x00, + 0x01, + 0x8c, + 0x00, + 0x00, + 0x02, + 0x8c, + 0x00, + 0x00, + 0x03, + 0x8f, + 0x00, + 0x00, + 0x00, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8f, + 0x00, + 0x00, + 0x01, + 0x8e, + 0x00, + 0x00, + 0x02, + 0x8e, + 0x00, + 0x00, + 0x03, + 0x91, + 0x00, + 0x00, + 0x00, + 0x90, + 0x00, + 0x00, + 0x02, + 0x91, + 0x00, + 0x00, + 0x01, + 0x91, + 0x00, + 0x00, + 0x01, + 0x90, + 0x00, + 0x00, + 0x02, + 0x90, + 0x00, + 0x00, + 0x03, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xf5, + 0x8a, + 0xe4, + 0x9a, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xe4, + 0x9a, + 0xd6, + 0xa8, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xd6, + 0xa8, + 0xca, + 0xb4, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xca, + 0xb4, + 0xbf, + 0xbf, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xbf, + 0xbf, + 0xb4, + 0xca, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xb4, + 0xca, + 0xa8, + 0xd6, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0xa8, + 0xd6, + 0x9a, + 0xe4, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x9a, + 0xe4, + 0x8a, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x8a, + 0xf5, + 0x75, + 0xf5, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x75, + 0xf5, + 0x65, + 0xe4, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x65, + 0xe4, + 0x57, + 0xd6, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x57, + 0xd6, + 0x4b, + 0xca, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x4b, + 0xca, + 0x40, + 0xbf, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x40, + 0xbf, + 0x35, + 0xb4, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x35, + 0xb4, + 0x29, + 0xa8, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x29, + 0xa8, + 0x1b, + 0x9a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x1b, + 0x9a, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x0a, + 0x75, + 0x1b, + 0x65, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x1b, + 0x65, + 0x29, + 0x57, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x29, + 0x57, + 0x35, + 0x4b, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x35, + 0x4b, + 0x40, + 0x40, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x40, + 0x40, + 0x4b, + 0x35, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x4b, + 0x35, + 0x57, + 0x29, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x57, + 0x29, + 0x65, + 0x1b, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x65, + 0x1b, + 0x75, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x75, + 0x0a, + 0x8a, + 0x0a, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x8a, + 0x0a, + 0x9a, + 0x1b, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0x9a, + 0x1b, + 0xa8, + 0x29, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xa8, + 0x29, + 0xb4, + 0x35, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xb4, + 0x35, + 0xbf, + 0x40, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xbf, + 0x40, + 0xca, + 0x4b, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xca, + 0x4b, + 0xd6, + 0x57, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xd6, + 0x57, + 0xe4, + 0x65, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, + 0xe4, + 0x65, + 0xf5, + 0x75, ]), }, }; diff --git a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.fake.ts b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.fake.ts index 1573ff586364..849d3da7e1ea 100644 --- a/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.fake.ts +++ b/full-stack-tests/core/src/frontend/standalone/tile/data/TileIO.data.fake.ts @@ -10,12 +10,12 @@ type TestCaseName = "rectangle" | "triangles" | "lineString" | "lineStrings" | " function changeVersionInPlace(bytes: Uint8Array, versionMajor?: number, versionMinor?: number): void { if (undefined !== versionMinor) { - bytes[4] = (versionMinor & 0x00ff); + bytes[4] = versionMinor & 0x00ff; bytes[5] = (versionMinor & 0xff00) >> 8; } if (undefined !== versionMajor) { - bytes[6] = (versionMajor & 0x00ff); + bytes[6] = versionMajor & 0x00ff; bytes[7] = (versionMajor & 0xff00) >> 8; } } @@ -64,14 +64,14 @@ export function changeMajorVersion(src: TileTestData, versionMajor: number): Til function changeHeaderLengthInPlace(bytes: Uint8Array, data: TileTestData, numPaddingBytes: number): void { // header length is 32-bit little-endian integer beginning at index 8. const headerLength = data.headerLength + numPaddingBytes; - bytes[8] = (headerLength & 0xff); + bytes[8] = headerLength & 0xff; bytes[9] = (headerLength & 0xff00) >>> 8; bytes[10] = (headerLength & 0xff0000) >>> 0x10; bytes[11] = (headerLength & 0xff000000) >>> 0x18; // tile length is 32-bit little-endian integer beginning at index 80 const tileLength = ((bytes[80] | (bytes[81] << 8) | (bytes[82] << 0x10) | (bytes[83] << 0x18)) >>> 0) + numPaddingBytes; - bytes[80] = (tileLength & 0xff); + bytes[80] = tileLength & 0xff; bytes[81] = (tileLength & 0xff00) >>> 8; bytes[82] = (tileLength & 0xff0000) >>> 0x10; bytes[83] = (tileLength & 0xff000000) >>> 0x18; diff --git a/full-stack-tests/core/tsconfig.json b/full-stack-tests/core/tsconfig.json index cf21acd419a2..c406425370a2 100644 --- a/full-stack-tests/core/tsconfig.json +++ b/full-stack-tests/core/tsconfig.json @@ -9,4 +9,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/full-stack-tests/core/webpack.config.js b/full-stack-tests/core/webpack.config.js index 99b43fcfa37f..3ebb96b6f769 100644 --- a/full-stack-tests/core/webpack.config.js +++ b/full-stack-tests/core/webpack.config.js @@ -50,8 +50,8 @@ function createConfig(shouldInstrument) { }, alias: { "@azure/storage-blob$": "@azure/storage-blob/dist-esm/storage-blob/src/index.browser.js", - "supports-color$": "supports-color/browser.js" - } + "supports-color$": "supports-color/browser.js", + }, }, module: { noParse: [ @@ -88,7 +88,7 @@ function createConfig(shouldInstrument) { }, externals: { electron: "commonjs electron", - fs + fs, }, plugins: [ // Makes some environment variables available to the JS code, for example: @@ -101,9 +101,9 @@ function createConfig(shouldInstrument) { }, { IMODELJS_CORE_DIRNAME: JSON.stringify( - path.join(__dirname, "../..") + path.join(__dirname, "../.."), ), - } + }, ), }), // certa doesn't like chunks @@ -137,5 +137,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/full-stack-tests/ecschema-rpc-interface/certa.json b/full-stack-tests/ecschema-rpc-interface/certa.json index 9a88146f577a..e00fb0c7d292 100644 --- a/full-stack-tests/ecschema-rpc-interface/certa.json +++ b/full-stack-tests/ecschema-rpc-interface/certa.json @@ -20,4 +20,4 @@ "mochaFile": "ecschema-rpcinterface-tests-result/ecschema-rpcinterface-tests-result.xml" } } -} \ No newline at end of file +} diff --git a/full-stack-tests/ecschema-rpc-interface/eslint.config.js b/full-stack-tests/ecschema-rpc-interface/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/full-stack-tests/ecschema-rpc-interface/eslint.config.js +++ b/full-stack-tests/ecschema-rpc-interface/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/full-stack-tests/ecschema-rpc-interface/src/common/Settings.ts b/full-stack-tests/ecschema-rpc-interface/src/common/Settings.ts index 71e73ecc41a1..1edfdda53ed8 100644 --- a/full-stack-tests/ecschema-rpc-interface/src/common/Settings.ts +++ b/full-stack-tests/ecschema-rpc-interface/src/common/Settings.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { LogLevel } from "@itwin/core-bentley"; import { IModelReadRpcInterface } from "@itwin/core-common"; -import { TestUserCredentials } from "@itwin/oidc-signin-tool"; import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common"; +import { TestUserCredentials } from "@itwin/oidc-signin-tool"; export interface Backend { version: string; @@ -44,13 +44,17 @@ export class Settings { public users: TestUserCredentials[] = []; // eslint-disable-next-line @typescript-eslint/naming-convention - public get Backend(): Backend { return this._backend; } - public get user(): TestUserCredentials { return this.users[0]; } + public get Backend(): Backend { + return this._backend; + } + public get user(): TestUserCredentials { + return this.users[0]; + } public iModel: IModelData = {} as IModelData; constructor(env: NodeJS.ProcessEnv) { - const isFrontend = (typeof (process) === "undefined"); + const isFrontend = typeof process === "undefined"; if (!isFrontend && undefined === env.TF_BUILD) { const path = require("path"); // eslint-disable-line @typescript-eslint/no-var-requires const dotenv = require("dotenv"); // eslint-disable-line @typescript-eslint/no-var-requires diff --git a/full-stack-tests/ecschema-rpc-interface/src/frontend/SchemaRpcInterface.test.ts b/full-stack-tests/ecschema-rpc-interface/src/frontend/SchemaRpcInterface.test.ts index 96edf1d48870..f0a3e6a546f6 100644 --- a/full-stack-tests/ecschema-rpc-interface/src/frontend/SchemaRpcInterface.test.ts +++ b/full-stack-tests/ecschema-rpc-interface/src/frontend/SchemaRpcInterface.test.ts @@ -6,12 +6,11 @@ import { expect } from "chai"; import { IModelConnection } from "@itwin/core-frontend"; +import { SchemaKey, SchemaKeyProps, SchemaProps } from "@itwin/ecschema-metadata"; import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common"; import { TestContext } from "./setup/TestContext"; -import { SchemaKey, SchemaKeyProps, SchemaProps } from "@itwin/ecschema-metadata"; describe("Schema RPC Interface", () => { - let iModel: IModelConnection; let testContext: TestContext; diff --git a/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/IModelSession.ts b/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/IModelSession.ts index fbaad37d55ad..87fb7eb873e7 100644 --- a/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/IModelSession.ts +++ b/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/IModelSession.ts @@ -2,16 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { AccessToken } from "@itwin/core-bentley"; import { CheckpointConnection } from "@itwin/core-frontend"; +import { AccessTokenAdapter } from "@itwin/imodels-access-frontend"; import { IModelsClient } from "@itwin/imodels-client-management"; import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; +import { expect } from "chai"; import { IModelData } from "../../common/Settings"; -import { AccessToken } from "@itwin/core-bentley"; -import { AccessTokenAdapter } from "@itwin/imodels-access-frontend"; export class IModelSession { - public iTwinId: string; public iModelId: string; public changesetId?: string; @@ -31,7 +30,7 @@ export class IModelSession { // Turn the iTwin name into an id if (iModelData.useITwinName && iModelData.iTwinName) { const client = new ITwinsAccessClient(); - const iTwinListResponse: ITwinsAPIResponse = await client.queryAsync(accessToken, ITwinSubClass.Project , { + const iTwinListResponse: ITwinsAPIResponse = await client.queryAsync(accessToken, ITwinSubClass.Project, { displayName: iModelData.iTwinName, }); const iTwinList = iTwinListResponse.data; @@ -48,7 +47,7 @@ export class IModelSession { iTwinId = iModelData.iTwinId!; if (iModelData.useName) { - const imodelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels`}}); + const imodelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); const iModels = imodelClient.iModels.getRepresentationList({ authorization: AccessTokenAdapter.toAuthorizationCallback(accessToken), urlParams: { diff --git a/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/TestContext.ts b/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/TestContext.ts index 713de72e2322..db8810436a81 100644 --- a/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/TestContext.ts +++ b/full-stack-tests/ecschema-rpc-interface/src/frontend/setup/TestContext.ts @@ -3,18 +3,21 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { AccessToken, Logger, LogLevel } from "@itwin/core-bentley"; +import { BentleyCloudRpcManager, OpenAPIInfo } from "@itwin/core-common"; import { NoRenderApp } from "@itwin/core-frontend"; +import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; +import { IModelsClient } from "@itwin/imodels-client-management"; import { - getAccessTokenFromBackend, TestBrowserAuthorizationClientConfiguration, TestFrontendAuthorizationClient, TestUserCredentials, + getAccessTokenFromBackend, + TestBrowserAuthorizationClientConfiguration, + TestFrontendAuthorizationClient, + TestUserCredentials, } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { expect } from "chai"; import { getRpcInterfaces, Settings } from "../../common/Settings"; import { getProcessEnvFromBackend } from "../../common/SideChannels"; import { IModelSession } from "./IModelSession"; -import { BentleyCloudRpcManager, OpenAPIInfo } from "@itwin/core-common"; -import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; -import { IModelsClient } from "@itwin/imodels-client-management"; export class TestContext { public adminUserAccessToken!: AccessToken; @@ -45,7 +48,10 @@ export class TestContext { } private async initialize() { - expect(this.settings.users.length).to.be.gte(1, `Unexpected number of users found in settings - got ${this.settings.users.length}, expected at least 2`); + expect(this.settings.users.length).to.be.gte( + 1, + `Unexpected number of users found in settings - got ${this.settings.users.length}, expected at least 2`, + ); // Print out the configuration console.log(this.settings.toString()); // eslint-disable-line @@ -81,6 +87,6 @@ export class TestContext { hubAccess: new FrontendIModelsAccess(iModelClient), }); - console.log("TestSetup: Done"); // eslint-disable-line + console.log("TestSetup: Done"); // eslint-disable-line } } diff --git a/full-stack-tests/ecschema-rpc-interface/src/test/backend.ts b/full-stack-tests/ecschema-rpc-interface/src/test/backend.ts index b180f698e4d7..fc43ebe48268 100644 --- a/full-stack-tests/ecschema-rpc-interface/src/test/backend.ts +++ b/full-stack-tests/ecschema-rpc-interface/src/test/backend.ts @@ -5,16 +5,16 @@ // Sets up a local backend to be used for testing within the iTwin.js Core repo. -import * as path from "path"; -import { IModelJsExpressServer } from "@itwin/express-server"; import { IModelHost } from "@itwin/core-backend"; import { BentleyCloudRpcManager, RpcConfiguration, RpcManager } from "@itwin/core-common"; -import { getRpcInterfaces } from "../common/Settings"; -import * as fs from "fs"; -import { IModelsClient } from "@itwin/imodels-client-authoring"; -import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; import { ECSchemaRpcInterface } from "@itwin/ecschema-rpcinterface-common"; import { ECSchemaRpcImpl } from "@itwin/ecschema-rpcinterface-impl"; +import { IModelJsExpressServer } from "@itwin/express-server"; +import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; +import { IModelsClient } from "@itwin/imodels-client-authoring"; +import * as fs from "fs"; +import * as path from "path"; +import { getRpcInterfaces } from "../common/Settings"; /** Loads the provided `.env` file into process.env */ function loadEnv(envFile: string) { diff --git a/full-stack-tests/ecschema-rpc-interface/tsconfig.json b/full-stack-tests/ecschema-rpc-interface/tsconfig.json index 15db7051e694..fcd45022271c 100644 --- a/full-stack-tests/ecschema-rpc-interface/tsconfig.json +++ b/full-stack-tests/ecschema-rpc-interface/tsconfig.json @@ -2,7 +2,7 @@ "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", "compilerOptions": { "resolveJsonModule": true, - "outDir": "./lib", + "outDir": "./lib" }, "include": [ "src/**/*.ts", @@ -12,4 +12,4 @@ "./lib", "node_modules" ] -} \ No newline at end of file +} diff --git a/full-stack-tests/presentation/public/locales/en/Test.json b/full-stack-tests/presentation/public/locales/en/Test.json index ae0f4684cbbe..3be510943d86 100644 --- a/full-stack-tests/presentation/public/locales/en/Test.json +++ b/full-stack-tests/presentation/public/locales/en/Test.json @@ -3,4 +3,4 @@ "nested": { "string": "test nested value" } -} \ No newline at end of file +} diff --git a/full-stack-tests/presentation/scripts/setup-tests.js b/full-stack-tests/presentation/scripts/setup-tests.js index d07e9b0267c5..a11fa361bc84 100644 --- a/full-stack-tests/presentation/scripts/setup-tests.js +++ b/full-stack-tests/presentation/scripts/setup-tests.js @@ -31,7 +31,7 @@ chai.use(chaiSubset); faker.seed(1); -beforeEach(function () { +beforeEach(function() { const currentTest = this.currentTest; // we want snapshot tests to use the same random data between runs diff --git a/full-stack-tests/presentation/src/ECClasHierarchy.ts b/full-stack-tests/presentation/src/ECClasHierarchy.ts index 3ee25121e40a..9848fe72a649 100644 --- a/full-stack-tests/presentation/src/ECClasHierarchy.ts +++ b/full-stack-tests/presentation/src/ECClasHierarchy.ts @@ -102,7 +102,8 @@ export class ECClassHierarchy { }; } public async getClassInfo(schemaName: string, className: string): Promise { - const classQuery = `SELECT c.ECInstanceId FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON s.ECInstanceId = c.Schema.Id WHERE c.Name = ? AND s.Name = ?`; + const classQuery = + `SELECT c.ECInstanceId FROM meta.ECClassDef c JOIN meta.ECSchemaDef s ON s.ECInstanceId = c.Schema.Id WHERE c.Name = ? AND s.Name = ?`; const result = await this._imodel .createQueryReader(classQuery, QueryBinder.from([className, schemaName]), { rowFormat: QueryRowFormat.UseJsPropertyNames }) .toArray(); diff --git a/full-stack-tests/presentation/src/IModelSetupUtils.ts b/full-stack-tests/presentation/src/IModelSetupUtils.ts index b481a727272b..b1ba2e95d198 100644 --- a/full-stack-tests/presentation/src/IModelSetupUtils.ts +++ b/full-stack-tests/presentation/src/IModelSetupUtils.ts @@ -2,8 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import path from "path"; -import sanitize from "sanitize-filename"; import { IModelDb, IModelJsFs, SnapshotDb } from "@itwin/core-backend"; import { GuidString, Id64String } from "@itwin/core-bentley"; import { @@ -19,6 +17,8 @@ import { } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { XMLParser } from "fast-xml-parser"; +import path from "path"; +import sanitize from "sanitize-filename"; export function createValidIModelFileName(imodelName: string) { return sanitize(imodelName.replace(/[ ]+/g, "-").replaceAll("`", "").replaceAll("'", "")).toLocaleLowerCase(); @@ -76,7 +76,7 @@ export function importSchema(mochaContext: Mocha.Context, imodel: { importSchema return { schemaName, schemaAlias, - items: schemaItems.reduce<{ [className: string]: { name: string; fullName: string; label: string } }>((classesObj, schemaItemDef) => { + items: schemaItems.reduce<{ [className: string]: { name: string, fullName: string, label: string } }>((classesObj, schemaItemDef) => { const name = schemaItemDef.typeName; return { ...classesObj, @@ -103,14 +103,14 @@ export function insertDocumentPartition(db: IModelDb, code: string, label?: stri return { className: "BisCore:DocumentPartition", id }; } -export function insertPhysicalModelWithPartition(props: { db: IModelDb; codeValue: string; partitionParentId?: Id64String }) { +export function insertPhysicalModelWithPartition(props: { db: IModelDb, codeValue: string, partitionParentId?: Id64String }) { const { codeValue, partitionParentId, ...baseProps } = props; const partitionKey = insertPhysicalPartition({ ...baseProps, codeValue, parentId: partitionParentId ?? IModel.rootSubjectId }); return insertPhysicalSubModel({ ...baseProps, modeledElementId: partitionKey.id }); } export function insertPhysicalPartition( - props: { db: IModelDb; codeValue: string; parentId: Id64String } & Partial>, + props: { db: IModelDb, codeValue: string, parentId: Id64String } & Partial>, ) { const { db, classFullName, codeValue, parentId, ...partitionProps } = props; const defaultModelClassName = `BisCore:PhysicalPartition`; @@ -129,7 +129,7 @@ export function insertPhysicalPartition( } export function insertPhysicalSubModel( - props: { db: IModelDb; modeledElementId: Id64String } & Partial>, + props: { db: IModelDb, modeledElementId: Id64String } & Partial>, ) { const { db, classFullName, modeledElementId, ...modelProps } = props; const defaultModelClassName = `BisCore:PhysicalModel`; @@ -144,7 +144,7 @@ export function insertPhysicalSubModel( /** Insert a spatial category element into created imodel. Return created element's className and Id. */ export function insertSpatialCategory( - props: { db: IModelDb; codeValue: string; modelId?: Id64String } & Partial>, + props: { db: IModelDb, codeValue: string, modelId?: Id64String } & Partial>, ) { const { db, classFullName, modelId, codeValue, ...categoryProps } = props; const defaultClassName = `BisCore:SpatialCategory`; @@ -161,10 +161,12 @@ export function insertSpatialCategory( /** Insert a physical element into created imodel. Return created element's className and Id. */ export function insertPhysicalElement( - props: { db: IModelDb; modelId: Id64String; categoryId: Id64String; parentId?: Id64String } & Partial< - Omit - > & - TAdditionalProps, + props: + & { db: IModelDb, modelId: Id64String, categoryId: Id64String, parentId?: Id64String } + & Partial< + Omit + > + & TAdditionalProps, ) { const { db, classFullName, modelId, categoryId, parentId, ...elementProps } = props; const defaultClassName = "Generic:PhysicalObject"; @@ -176,11 +178,11 @@ export function insertPhysicalElement( code: Code.createEmpty(), ...(parentId ? { - parent: { - id: parentId, - relClassName: `BisCore:PhysicalElementAssemblesElements`, - }, - } + parent: { + id: parentId, + relClassName: `BisCore:PhysicalElementAssemblesElements`, + }, + } : undefined), ...elementProps, } as PhysicalElementProps); @@ -189,7 +191,7 @@ export function insertPhysicalElement( /** Insert an aspect into created imodel, return its key */ export function insertElementAspect( - props: { db: IModelDb; elementId: Id64String } & Partial> & TAdditionalProps, + props: { db: IModelDb, elementId: Id64String } & Partial> & TAdditionalProps, ) { const { db, classFullName, elementId, ...aspectProps } = props; const defaultClassName = "BisCore:ElementMultiAspect"; diff --git a/full-stack-tests/presentation/src/IntegrationTests.ts b/full-stack-tests/presentation/src/IntegrationTests.ts index cf1ee80956aa..45e51c204ec9 100644 --- a/full-stack-tests/presentation/src/IntegrationTests.ts +++ b/full-stack-tests/presentation/src/IntegrationTests.ts @@ -3,12 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as cpx from "cpx2"; -import * as fs from "fs"; -import Backend from "i18next-http-backend"; -import * as path from "path"; -import rimraf from "rimraf"; -import sinon from "sinon"; import { IModelHost, IModelHostOptions, IModelJsFs } from "@itwin/core-backend"; import { Guid, Logger, LogLevel } from "@itwin/core-bentley"; import { @@ -33,6 +27,12 @@ import { } from "@itwin/presentation-backend"; import { PresentationRpcInterface } from "@itwin/presentation-common"; import { Presentation as PresentationFrontend, PresentationProps as PresentationFrontendProps } from "@itwin/presentation-frontend"; +import * as cpx from "cpx2"; +import * as fs from "fs"; +import Backend from "i18next-http-backend"; +import * as path from "path"; +import rimraf from "rimraf"; +import sinon from "sinon"; import { getOutputRoot } from "./Utils"; const DEFAULT_BACKEND_TIMEOUT: number = 0; @@ -165,7 +165,7 @@ const initializeCommon = async (props: { console.log(`[${new Date().toISOString()}] Tests initialized`); }; -export const initialize = async (props?: { backendTimeout?: number; frontendTimeout?: number; localization?: Localization }) => { +export const initialize = async (props?: { backendTimeout?: number, frontendTimeout?: number, localization?: Localization }) => { await initializeCommon({ backendTimeout: DEFAULT_BACKEND_TIMEOUT, ...props, diff --git a/full-stack-tests/presentation/src/Utils.ts b/full-stack-tests/presentation/src/Utils.ts index 317bf523acac..5f8dc711f7f8 100644 --- a/full-stack-tests/presentation/src/Utils.ts +++ b/full-stack-tests/presentation/src/Utils.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import path from "path"; import { IModelJsFs } from "@itwin/core-backend"; import { BeDuration, StopWatch } from "@itwin/core-bentley"; import { Field } from "@itwin/presentation-common"; +import path from "path"; /** * Simplified type for `sinon.SinonSpy`. diff --git a/full-stack-tests/presentation/src/backend/DefaultSupplementalRules.test.ts b/full-stack-tests/presentation/src/backend/DefaultSupplementalRules.test.ts index 6ae8c8a4d8d9..4fefc2e6315c 100644 --- a/full-stack-tests/presentation/src/backend/DefaultSupplementalRules.test.ts +++ b/full-stack-tests/presentation/src/backend/DefaultSupplementalRules.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelDb } from "@itwin/core-backend"; import { assert, Id64String } from "@itwin/core-bentley"; import { BisCodeSpec, Code, ElementAspectProps, ElementProps, IModel } from "@itwin/core-common"; import { Presentation } from "@itwin/presentation-backend"; import { DefaultContentDisplayTypes, InstanceKey, KeySet, Ruleset } from "@itwin/presentation-common"; +import { expect } from "chai"; +import { buildTestIModelDb } from "../IModelSetupUtils"; import { initialize, terminate } from "../IntegrationTests"; import { getFieldByLabel } from "../Utils"; -import { buildTestIModelDb } from "../IModelSetupUtils"; describe("Default supplemental rules", async () => { before(async () => { @@ -25,7 +25,7 @@ describe("Default supplemental rules", async () => { describe("Content modifiers", () => { describe("bis.Element", () => { describe("Related properties", () => { - it("loads `Element -> ExternalSourceAspect.Identifier` property into 'Source Information' group", async function () { + it("loads `Element -> ExternalSourceAspect.Identifier` property into 'Source Information' group", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { elementKey = insertPhysicalElement(db); @@ -76,7 +76,7 @@ describe("Default supplemental rules", async () => { }); }); - it("loads `Element -> ExternalSourceAspect -> ExternalSource -> RepositoryLink` properties into 'Source Information' group", async function () { + it("loads `Element -> ExternalSourceAspect -> ExternalSource -> RepositoryLink` properties into 'Source Information' group", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { const schema = ` @@ -175,7 +175,7 @@ describe("Default supplemental rules", async () => { }); }); - it("allows removing 'Source Element ID' property", async function () { + it("allows removing 'Source Element ID' property", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { elementKey = insertPhysicalElement(db); @@ -239,7 +239,7 @@ describe("Default supplemental rules", async () => { expect(() => getFieldByLabel(descriptor.fields, "Source Element ID")).to.throw(); }); - it("allows removing 'Source Information -> Model Source' properties", async function () { + it("allows removing 'Source Information -> Model Source' properties", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { const partitionId = db.elements.insertElement({ @@ -343,7 +343,7 @@ describe("Default supplemental rules", async () => { expect(() => getFieldByLabel(descriptor.fields, "Name")).to.throw(); }); - it("allows removing 'Source Information' ExternalSource properties", async function () { + it("allows removing 'Source Information' ExternalSource properties", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { elementKey = insertPhysicalElement(db); @@ -449,7 +449,7 @@ describe("Default supplemental rules", async () => { expect(() => getFieldByLabel(descriptor.fields, "Path")).to.throw(); }); - it("allows removing 'Source Information -> Secondary Sources' properties", async function () { + it("allows removing 'Source Information -> Secondary Sources' properties", async function() { let elementKey: InstanceKey | undefined; const { db: imodel } = await buildTestIModelDb(this.test!.fullTitle(), async (db) => { elementKey = insertPhysicalElement(db); diff --git a/full-stack-tests/presentation/src/backend/Diagnostics.test.ts b/full-stack-tests/presentation/src/backend/Diagnostics.test.ts index 21783288a54d..58b4367e7475 100644 --- a/full-stack-tests/presentation/src/backend/Diagnostics.test.ts +++ b/full-stack-tests/presentation/src/backend/Diagnostics.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; import { IModelDb, SnapshotDb } from "@itwin/core-backend"; import { using } from "@itwin/core-bentley"; import { Presentation, PresentationManager } from "@itwin/presentation-backend"; import { ChildNodeSpecificationTypes, Diagnostics, DiagnosticsLogEntry, PresentationError, Ruleset, RuleTypes } from "@itwin/presentation-common"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { initialize, terminate } from "../IntegrationTests"; describe("Diagnostics", async () => { @@ -40,7 +40,7 @@ describe("Diagnostics", async () => { it("includes diagnostics if request takes longer than minimum duration", async () => { const requestDiagnosticsSpy = sinon.spy(); - await using(new PresentationManager(), async (manager) => { + using(new PresentationManager(), async (manager) => { await manager.getNodes({ imodel, rulesetOrId: ruleset, @@ -55,7 +55,7 @@ describe("Diagnostics", async () => { it("doesn't include diagnostics if request takes less time than minimum duration", async () => { const requestDiagnosticsSpy = sinon.spy(); - await using(new PresentationManager(), async (manager) => { + using(new PresentationManager(), async (manager) => { await manager.getNodes({ imodel, rulesetOrId: ruleset, @@ -89,7 +89,7 @@ describe("Diagnostics", async () => { it("doesn't report request diagnostics if not requested when manager diagnostics requested", async () => { const managerDiagnosticsSpy = sinon.spy(); const requestDiagnosticsSpy = sinon.spy(); - await using(new PresentationManager({ diagnostics: { dev: true, editor: true, perf: true, handler: managerDiagnosticsSpy } }), async (manager) => { + using(new PresentationManager({ diagnostics: { dev: true, editor: true, perf: true, handler: managerDiagnosticsSpy } }), async (manager) => { await manager.getNodes({ imodel, rulesetOrId: ruleset, @@ -105,7 +105,7 @@ describe("Diagnostics", async () => { it("doesn't report manager diagnostics if not requested when request diagnostics requested", async () => { const managerDiagnosticsSpy = sinon.spy(); const requestDiagnosticsSpy = sinon.spy(); - await using(new PresentationManager({ diagnostics: { handler: managerDiagnosticsSpy } }), async (manager) => { + using(new PresentationManager({ diagnostics: { handler: managerDiagnosticsSpy } }), async (manager) => { await manager.getNodes({ imodel, rulesetOrId: ruleset, @@ -126,7 +126,7 @@ describe("Diagnostics", async () => { const managerDiagnosticsSpy = sinon.spy(); const requestDiagnosticsContext = {}; const requestDiagnosticsSpy = sinon.spy(); - await using( + using( new PresentationManager({ diagnostics: { perf: true, dev: "trace", handler: managerDiagnosticsSpy, requestContextSupplier: () => managerDiagnosticsContext }, }), diff --git a/full-stack-tests/presentation/src/backend/IModelUpdates.test.ts b/full-stack-tests/presentation/src/backend/IModelUpdates.test.ts index 31f8ebc14511..0843ad0e4067 100644 --- a/full-stack-tests/presentation/src/backend/IModelUpdates.test.ts +++ b/full-stack-tests/presentation/src/backend/IModelUpdates.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as fs from "fs"; -import path from "path"; -import * as sinon from "sinon"; import { IpcHost, StandaloneDb } from "@itwin/core-backend"; import { IpcSocketBackend } from "@itwin/core-common"; import { Presentation } from "@itwin/presentation-backend"; import { KeySet, PresentationIpcEvents } from "@itwin/presentation-common"; +import { expect } from "chai"; +import * as fs from "fs"; +import path from "path"; +import * as sinon from "sinon"; import { createValidIModelFileName } from "../IModelSetupUtils"; import { setupTestsOutputDirectory } from "../IntegrationTests"; import { getFieldByLabel, prepareOutputFilePath, waitFor } from "../Utils"; @@ -48,7 +48,7 @@ describe("Reacting to IModel data changes", () => { await IpcHost.shutdown(); }); - beforeEach(function () { + beforeEach(function() { imodelPath = prepareOutputFilePath(`${createValidIModelFileName(this.test!.fullTitle())}.bim`); if (fs.existsSync(imodelPath)) { fs.unlinkSync(imodelPath); diff --git a/full-stack-tests/presentation/src/backend/NativePlatform.test.ts b/full-stack-tests/presentation/src/backend/NativePlatform.test.ts index bba7a5e169f0..ceb135f2a9be 100644 --- a/full-stack-tests/presentation/src/backend/NativePlatform.test.ts +++ b/full-stack-tests/presentation/src/backend/NativePlatform.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { SnapshotDb } from "@itwin/core-backend"; import { HierarchyCacheMode } from "@itwin/presentation-backend"; import { createDefaultNativePlatform, NativePlatformDefinition } from "@itwin/presentation-backend/lib/cjs/presentation-backend/NativePlatform"; import { PresentationError } from "@itwin/presentation-common"; +import { expect } from "chai"; import { initialize, terminate } from "../IntegrationTests"; describe("NativePlatform", () => { @@ -54,7 +54,10 @@ describe("NativePlatform", () => { it("throws on empty request id", async () => { const db = nativePlatform.getImodelAddon(imodel); - await expect(nativePlatform.handleRequest(db, JSON.stringify({ requestId: "" }))).to.eventually.be.rejectedWith(PresentationError, "request.requestId"); + await expect(nativePlatform.handleRequest(db, JSON.stringify({ requestId: "" }))).to.eventually.be.rejectedWith( + PresentationError, + "request.requestId", + ); }); it("throws on not handled request id", async () => { diff --git a/full-stack-tests/presentation/src/backend/PresentationManager.test.ts b/full-stack-tests/presentation/src/backend/PresentationManager.test.ts index 6949f01ffd96..81816138e422 100644 --- a/full-stack-tests/presentation/src/backend/PresentationManager.test.ts +++ b/full-stack-tests/presentation/src/backend/PresentationManager.test.ts @@ -2,7 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelDb, SnapshotDb } from "@itwin/core-backend"; import { BeEvent, Guid, using } from "@itwin/core-bentley"; import { UnitSystemKey } from "@itwin/core-quantity"; @@ -22,6 +21,7 @@ import { Ruleset, RuleTypes, } from "@itwin/presentation-common"; +import { expect } from "chai"; import { initialize, terminate, testLocalization } from "../IntegrationTests"; import { getFieldByLabel } from "../Utils"; @@ -53,14 +53,22 @@ describe("PresentationManager", () => { getSchemaSync() { throw new Error(`getSchemaSync not implemented`); }, - async getSchemaInfo(key: Readonly, matchType: SchemaMatchType, schemaContext: SchemaContext): Promise { + async getSchemaInfo( + key: Readonly, + matchType: SchemaMatchType, + schemaContext: SchemaContext, + ): Promise { const schemaInfo = await Schema.startLoadingFromJson(schemaIModel.getSchemaProps(key.name), schemaContext); if (schemaInfo !== undefined && schemaInfo.schemaKey.matches(key, matchType)) { return schemaInfo; } return undefined; }, - async getSchema(key: Readonly, matchType: SchemaMatchType, schemaContext: SchemaContext): Promise { + async getSchema( + key: Readonly, + matchType: SchemaMatchType, + schemaContext: SchemaContext, + ): Promise { await this.getSchemaInfo(key, matchType, schemaContext); const schema = await schemaContext.getCachedSchema(key, matchType); return schema as T; @@ -170,7 +178,7 @@ describe("PresentationManager", () => { describe("getElementProperties", () => { it("returns properties for some elements of class 'PhysicalObject", async () => { - await using(new PresentationManager(), async (manager) => { + using(new PresentationManager(), async (manager) => { const properties: ElementProperties[] = []; const { iterator } = await manager.getElementProperties({ imodel, elementClasses: ["Generic:PhysicalObject"] }); for await (const items of iterator()) { @@ -183,7 +191,7 @@ describe("PresentationManager", () => { describe("Cancel request", () => { it("cancels 'getNodes' request", async () => { - await using(new PresentationManager(), async (manager) => { + using(new PresentationManager(), async (manager) => { const cancelEvent = new BeEvent<() => void>(); const promise = manager.getNodes({ imodel, diff --git a/full-stack-tests/presentation/src/backend/ReadWrite.test.ts b/full-stack-tests/presentation/src/backend/ReadWrite.test.ts index 7da130cedc45..345575e8dee2 100644 --- a/full-stack-tests/presentation/src/backend/ReadWrite.test.ts +++ b/full-stack-tests/presentation/src/backend/ReadWrite.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as fs from "fs"; import { IModelDb, StandaloneDb } from "@itwin/core-backend"; import { Logger, LogLevel } from "@itwin/core-bentley"; import { PresentationManager } from "@itwin/presentation-backend"; import { ChildNodeSpecificationTypes, Ruleset, RuleTypes } from "@itwin/presentation-common"; +import { expect } from "chai"; +import * as fs from "fs"; import { initialize, terminate } from "../IntegrationTests"; import { prepareOutputFilePath } from "../Utils"; diff --git a/full-stack-tests/presentation/src/backend/RulesetsEmbedding.test.ts b/full-stack-tests/presentation/src/backend/RulesetsEmbedding.test.ts index 31cf5595eff7..8cf880aba735 100644 --- a/full-stack-tests/presentation/src/backend/RulesetsEmbedding.test.ts +++ b/full-stack-tests/presentation/src/backend/RulesetsEmbedding.test.ts @@ -2,17 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import faker from "faker"; -import fs from "fs"; import { IModelDb, StandaloneDb, Subject } from "@itwin/core-backend"; import { Id64, Logger, LogLevel } from "@itwin/core-bentley"; +import { IModel, SubjectProps } from "@itwin/core-common"; import { Presentation, RulesetEmbedder } from "@itwin/presentation-backend"; import { ChildNodeSpecificationTypes, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { createRandomRuleset } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import faker from "faker"; +import fs from "fs"; import { initialize, terminate } from "../IntegrationTests"; import { prepareOutputFilePath } from "../Utils"; -import { IModel, SubjectProps } from "@itwin/core-common"; const RULESET_1: Ruleset = { id: "ruleset_1", diff --git a/full-stack-tests/presentation/src/frontend/Diagnostics.test.ts b/full-stack-tests/presentation/src/frontend/Diagnostics.test.ts index aea0a326159c..60823884946e 100644 --- a/full-stack-tests/presentation/src/frontend/Diagnostics.test.ts +++ b/full-stack-tests/presentation/src/frontend/Diagnostics.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ClientDiagnostics } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { initialize, terminate } from "../IntegrationTests"; describe("Diagnostics", async () => { diff --git a/full-stack-tests/presentation/src/frontend/Localization.test.ts b/full-stack-tests/presentation/src/frontend/Localization.test.ts index 2bd50b1e53f5..b709e1bab362 100644 --- a/full-stack-tests/presentation/src/frontend/Localization.test.ts +++ b/full-stack-tests/presentation/src/frontend/Localization.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelApp, IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ChildNodeSpecificationTypes, Content, DefaultContentDisplayTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation, PresentationManager } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate, testLocalization } from "../IntegrationTests"; import { collect, getFieldByLabel } from "../Utils"; @@ -309,7 +309,9 @@ describe("Localization", async () => { await Promise.all( Array.from({ length: 100 }).map(async () => { const [en, test] = await Promise.all( - frontends.map(async (frontend) => frontend.getNodesIterator({ imodel, rulesetOrId: CUSTOM_NODES_RULESET }).then(async (x) => collect(x.items))), + frontends.map(async (frontend) => + frontend.getNodesIterator({ imodel, rulesetOrId: CUSTOM_NODES_RULESET }).then(async (x) => collect(x.items)) + ), ); expect(en[0].label.displayValue).to.eq("test value"); diff --git a/full-stack-tests/presentation/src/frontend/RulesetVariables.test.ts b/full-stack-tests/presentation/src/frontend/RulesetVariables.test.ts index 8e4e70019eb8..07f4b31ee1ae 100644 --- a/full-stack-tests/presentation/src/frontend/RulesetVariables.test.ts +++ b/full-stack-tests/presentation/src/frontend/RulesetVariables.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; import { Guid, Id64 } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ChildNodeSpecificationTypes, Content, ContentSpecificationTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { createRandomId } from "@itwin/presentation-common/lib/cjs/test"; import { Presentation, PresentationManager, RulesetVariablesManager } from "@itwin/presentation-frontend"; +import { expect } from "chai"; +import * as faker from "faker"; import { initialize, resetBackend, terminate } from "../IntegrationTests"; import { collect } from "../Utils"; @@ -263,7 +263,9 @@ describe("Ruleset Variables", async () => { it("handles multiple simultaneous requests from different frontends with ruleset variables", async () => { for (let i = 0; i < 100; ++i) { frontends.forEach(async (f, fi) => f.vars(RULESET.id).setString("variable_id", `${i}_${fi}`)); - const nodes = await Promise.all(frontends.map(async (f) => f.getNodesIterator({ imodel, rulesetOrId: RULESET }).then(async (x) => collect(x.items)))); + const nodes = await Promise.all( + frontends.map(async (f) => f.getNodesIterator({ imodel, rulesetOrId: RULESET }).then(async (x) => collect(x.items))), + ); frontends.forEach((_f, fi) => { expect(nodes[fi][0].label.displayValue).to.eq(`${i}_${fi}`); }); diff --git a/full-stack-tests/presentation/src/frontend/Rulesets.test.ts b/full-stack-tests/presentation/src/frontend/Rulesets.test.ts index de96ab0d2fa5..0197e2a6fa98 100644 --- a/full-stack-tests/presentation/src/frontend/Rulesets.test.ts +++ b/full-stack-tests/presentation/src/frontend/Rulesets.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { using } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ChildNodeSpecificationTypes, RegisteredRuleset, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation, PresentationManager } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, resetBackend, terminate } from "../IntegrationTests"; import { collect } from "../Utils"; @@ -57,7 +57,7 @@ describe("Rulesets", async () => { }); it("creates ruleset from json and gets root node using it", async () => { - await using>(await Presentation.presentation.rulesets().add(RULESET_1), async () => { + using>(await Presentation.presentation.rulesets().add(RULESET_1), async () => { const rootNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: RULESET_1.id }).then(async (x) => collect(x.items)); expect(rootNodes.length).to.be.equal(1); expect(rootNodes[0].label.displayValue).to.equal("label 1"); @@ -120,7 +120,9 @@ describe("Rulesets", async () => { const registeredRulesets = await Promise.all(frontends.map(async (f, i) => f.rulesets().add(rulesets[i]))); - const nodes = await Promise.all(frontends.map(async (f) => f.getNodesIterator({ imodel, rulesetOrId: "test" }).then(async (x) => collect(x.items)))); + const nodes = await Promise.all( + frontends.map(async (f) => f.getNodesIterator({ imodel, rulesetOrId: "test" }).then(async (x) => collect(x.items))), + ); frontends.forEach((_f, i) => { expect(nodes[i][0].label.displayValue).to.eq(`label ${i + 1}`); }); @@ -142,7 +144,7 @@ describe("Rulesets", async () => { it("can use the same frontend-registered ruleset after backend is reset", async () => { const props = { imodel, rulesetOrId: RULESET_1.id }; - await using>(await frontend.rulesets().add(RULESET_1), async () => { + using>(await frontend.rulesets().add(RULESET_1), async () => { const rootNodes1 = await frontend.getNodesIterator(props).then(async (x) => collect(x.items)); expect(rootNodes1.length).to.be.equal(1); expect(rootNodes1[0].label.displayValue).to.be.equal("label 1"); diff --git a/full-stack-tests/presentation/src/frontend/SelectionScopes.test.ts b/full-stack-tests/presentation/src/frontend/SelectionScopes.test.ts index af98ece094b7..20e28c694b68 100644 --- a/full-stack-tests/presentation/src/frontend/SelectionScopes.test.ts +++ b/full-stack-tests/presentation/src/frontend/SelectionScopes.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../IntegrationTests"; import { waitFor } from "../Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/ArrayProperties.test.ts b/full-stack-tests/presentation/src/frontend/content/ArrayProperties.test.ts index f57e0381ff38..be61f4a7bc55 100644 --- a/full-stack-tests/presentation/src/frontend/content/ArrayProperties.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ArrayProperties.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, using } from "@itwin/core-bentley"; import { IModelConnection } from "@itwin/core-frontend"; import { Content, ContentSpecificationTypes, DefaultContentDisplayTypes, InstanceKey, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { PresentationManager } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { buildTestIModelConnection, importSchema, @@ -29,7 +29,7 @@ describeContentTestSuite("Array properties", () => { ], }; - it("returns content for arrays with null items", async function () { + it("returns content for arrays with null items", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( diff --git a/full-stack-tests/presentation/src/frontend/content/CalculatedProperties.test.ts b/full-stack-tests/presentation/src/frontend/content/CalculatedProperties.test.ts index 9a504fdf1898..809dd71ab2ae 100644 --- a/full-stack-tests/presentation/src/frontend/content/CalculatedProperties.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/CalculatedProperties.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { Content, ContentSpecificationTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { collect, getFieldByLabel } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/ClassDescriptor.test.ts b/full-stack-tests/presentation/src/frontend/content/ClassDescriptor.test.ts index 9daf2113a87e..61d042fb0e42 100644 --- a/full-stack-tests/presentation/src/frontend/content/ClassDescriptor.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ClassDescriptor.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { ContentSpecificationTypes, DefaultContentDisplayTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { ECClassHierarchy } from "../../ECClasHierarchy"; import { describeContentTestSuite, filterFieldsByClass, getFieldLabels } from "./Utils"; @@ -41,7 +41,10 @@ describeContentTestSuite("Class descriptor", ({ getDefaultSuiteIModel }) => { keys: new KeySet(), }); // sanity check - ensure filtering the fields by the class we used for request doesn't filter out anything - const fieldsGeometricElement = filterFieldsByClass(descriptorGeometricElement!.fields, await classHierarchy.getClassInfo("BisCore", "GeometricElement")); + const fieldsGeometricElement = filterFieldsByClass( + descriptorGeometricElement!.fields, + await classHierarchy.getClassInfo("BisCore", "GeometricElement"), + ); expect(getFieldLabels(fieldsGeometricElement)).to.deep.eq(getFieldLabels(descriptorGeometricElement!)); // request properties of Generic.PhysicalObject and ensure it's matches our filtered result of `descriptorGeometricElement` @@ -51,7 +54,10 @@ describeContentTestSuite("Class descriptor", ({ getDefaultSuiteIModel }) => { displayType: DefaultContentDisplayTypes.PropertyPane, keys: new KeySet(), }); - const fieldsPhysicalObject = filterFieldsByClass(descriptorGeometricElement!.fields, await classHierarchy.getClassInfo("Generic", "PhysicalObject")); + const fieldsPhysicalObject = filterFieldsByClass( + descriptorGeometricElement!.fields, + await classHierarchy.getClassInfo("Generic", "PhysicalObject"), + ); expect(getFieldLabels(fieldsPhysicalObject)).to.deep.eq(getFieldLabels(descriptorPhysicalObject!)); // request properties of PCJ_TestSchema.TestClass and ensure it's matches our filtered result of `descriptorGeometricElement` diff --git a/full-stack-tests/presentation/src/frontend/content/ContentDisplayLabels.test.ts b/full-stack-tests/presentation/src/frontend/content/ContentDisplayLabels.test.ts index 4907a3056d5c..a9b1f1a55783 100644 --- a/full-stack-tests/presentation/src/frontend/content/ContentDisplayLabels.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ContentDisplayLabels.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Presentation } from "@itwin/presentation-frontend"; -import { describeContentTestSuite } from "./Utils"; +import { Guid } from "@itwin/core-bentley"; +import { IModelConnection } from "@itwin/core-frontend"; import { ContentSpecificationTypes, DefaultContentDisplayTypes, @@ -16,8 +16,8 @@ import { RuleTypes, Value, } from "@itwin/presentation-common"; -import { Guid } from "@itwin/core-bentley"; -import { IModelConnection } from "@itwin/core-frontend"; +import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { buildTestIModelConnection, importSchema, @@ -26,8 +26,8 @@ import { insertPhysicalModelWithPartition, insertSpatialCategory, } from "../../IModelSetupUtils"; -import { expect } from "chai"; import { collect } from "../../Utils"; +import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Content Display Labels", () => { const EMPTY_LABEL = LabelDefinition.fromLabelString("@Presentation:label.notSpecified@"); @@ -37,7 +37,7 @@ describeContentTestSuite("Content Display Labels", () => { let schemaName: string; const elementClassName = "Generic.PhysicalObject"; - before(async function () { + before(async function() { const schemaXml = ` @@ -250,7 +250,10 @@ describeContentTestSuite("Content Display Labels", () => { }; } - function validateDeeplyNestedContent(nestedContent: Pick, expectedDisplayLabelsStack: Array) { + function validateDeeplyNestedContent( + nestedContent: Pick, + expectedDisplayLabelsStack: Array, + ) { const expectedLabel = LabelDefinition.fromLabelString(expectedDisplayLabelsStack.pop()!); expect(nestedContent.labelDefinition).to.deep.eq(expectedLabel); @@ -262,7 +265,7 @@ describeContentTestSuite("Content Display Labels", () => { validateDeeplyNestedContent(next[0], expectedDisplayLabelsStack); } - it("applies class name label override on nested content values", async function () { + it("applies class name label override on nested content values", async function() { imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const { id: modelId } = insertPhysicalModelWithPartition({ db, codeValue: "Model" }); const { id: categoryId } = insertSpatialCategory({ db, codeValue: "Category" }); @@ -306,7 +309,7 @@ describeContentTestSuite("Content Display Labels", () => { ); }); - it("applies specific property label override on nested content values", async function () { + it("applies specific property label override on nested content values", async function() { imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const { id: modelId } = insertPhysicalModelWithPartition({ db, codeValue: "Model" }); const { id: categoryId } = insertSpatialCategory({ db, codeValue: "Category" }); diff --git a/full-stack-tests/presentation/src/frontend/content/ContentInstanceKeys.test.ts b/full-stack-tests/presentation/src/frontend/content/ContentInstanceKeys.test.ts index 123c9c7acb45..4d2f84616b4f 100644 --- a/full-stack-tests/presentation/src/frontend/content/ContentInstanceKeys.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ContentInstanceKeys.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { ContentSpecificationTypes, KeySet, RelationshipDirection, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Content instance keys", ({ getDefaultSuiteIModel }) => { diff --git a/full-stack-tests/presentation/src/frontend/content/ContentSources.test.ts b/full-stack-tests/presentation/src/frontend/content/ContentSources.test.ts index f4f381ac81d2..956ac3c2cf49 100644 --- a/full-stack-tests/presentation/src/frontend/content/ContentSources.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ContentSources.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Presentation } from "@itwin/presentation-frontend"; import { expect } from "chai"; import * as chaiJestSnapshot from "chai-jest-snapshot"; -import { Presentation } from "@itwin/presentation-frontend"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Content sources", ({ getDefaultSuiteIModel }) => { - it("retrieves content sources for given class", async function () { + it("retrieves content sources for given class", async function() { // we want to compare against the same snapshot - that requires reconfiguring chai-jest-snapshot by resetting it's config // and supplying file name and snapshot name to `matchSnapshot`. otherwise each call to `matchSnapshot` generates a new snapshot // in the snapshot file. diff --git a/full-stack-tests/presentation/src/frontend/content/CustomCategories.test.ts b/full-stack-tests/presentation/src/frontend/content/CustomCategories.test.ts index 4e0a0b401c56..a381336145ea 100644 --- a/full-stack-tests/presentation/src/frontend/content/CustomCategories.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/CustomCategories.test.ts @@ -3,17 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; import { Content, ContentSpecificationTypes, DefaultContentDisplayTypes, InstanceKey, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { buildTestIModelConnection, importSchema, insertDocumentPartition, insertElementAspect, insertPhysicalPartition } from "../../IModelSetupUtils"; +import { expect } from "chai"; +import { + buildTestIModelConnection, + importSchema, + insertDocumentPartition, + insertElementAspect, + insertPhysicalPartition, +} from "../../IModelSetupUtils"; import { collect } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Custom categories", () => { - it("creates child class category", async function () { + it("creates child class category", async function() { let instanceKey: InstanceKey; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { instanceKey = insertDocumentPartition(db, "Test"); @@ -67,7 +73,7 @@ describeContentTestSuite("Custom categories", () => { ]); }); - it("moves calculated property into schema-based category", async function () { + it("moves calculated property into schema-based category", async function() { let elementKey!: InstanceKey; let schemaName!: string; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { diff --git a/full-stack-tests/presentation/src/frontend/content/DistinctValues.test.ts b/full-stack-tests/presentation/src/frontend/content/DistinctValues.test.ts index 1d5d6d9d1076..ce7061290130 100644 --- a/full-stack-tests/presentation/src/frontend/content/DistinctValues.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/DistinctValues.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert, Guid, Id64 } from "@itwin/core-bentley"; import { IModelConnection } from "@itwin/core-frontend"; import { @@ -18,7 +17,7 @@ import { RuleTypes, } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { collect, getFieldByLabel } from "../../Utils"; +import { expect } from "chai"; import { buildTestIModelConnection, insertDocumentPartition, @@ -26,6 +25,7 @@ import { insertPhysicalModelWithPartition, insertSpatialCategory, } from "../../IModelSetupUtils"; +import { collect, getFieldByLabel } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { @@ -238,7 +238,8 @@ describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { id: Id64.invalid, }, ]); - const descriptor = (await Presentation.presentation.getContentDescriptor({ imodel, rulesetOrId: ruleset, keys: consolidatedKeys, displayType: "" }))!; + const descriptor = + (await Presentation.presentation.getContentDescriptor({ imodel, rulesetOrId: ruleset, keys: consolidatedKeys, displayType: "" }))!; const field = getFieldByLabel(descriptor.fields, "User Label"); await validatePagedDistinctValuesResponse(imodel, ruleset, consolidatedKeys, descriptor, field.getFieldDescriptor(), [ @@ -279,7 +280,7 @@ describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { ]); }); - it("gets distinct content values based on hierarchy level descriptor", async function () { + it("gets distinct content values based on hierarchy level descriptor", async function() { // create an imodel with Model -> Elements relationship const testIModel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { const categoryKey = insertSpatialCategory({ db, codeValue: "Category" }); @@ -331,7 +332,9 @@ describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { }, ], }; - const rootNodes = await Presentation.presentation.getNodesIterator({ imodel: testIModel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const rootNodes = await Presentation.presentation.getNodesIterator({ imodel: testIModel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(rootNodes.length).to.eq(2); const descriptor = await Presentation.presentation.getNodesDescriptor({ imodel: testIModel, rulesetOrId: ruleset, parentKey: rootNodes[0].key }); assert(!!descriptor); @@ -359,27 +362,41 @@ describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { const userLabelField = getFieldByLabel(descriptor.fields, "User Label"); // user labels are different for every child element, expect 2 unique values - await validatePagedDistinctValuesResponse(testIModel, descriptor.ruleset!, new KeySet([rootNodes[0].key]), {}, userLabelField.getFieldDescriptor(), [ - { - displayValue: "Element A1", - groupedRawValues: ["Element A1"], - }, - { - displayValue: "Element A2", - groupedRawValues: ["Element A2"], - }, - ]); + await validatePagedDistinctValuesResponse( + testIModel, + descriptor.ruleset!, + new KeySet([rootNodes[0].key]), + {}, + userLabelField.getFieldDescriptor(), + [ + { + displayValue: "Element A1", + groupedRawValues: ["Element A1"], + }, + { + displayValue: "Element A2", + groupedRawValues: ["Element A2"], + }, + ], + ); // user label is the same for every child element, expect only 1 unique value - await validatePagedDistinctValuesResponse(testIModel, descriptor.ruleset!, new KeySet([rootNodes[1].key]), {}, userLabelField.getFieldDescriptor(), [ - { - displayValue: "Element B", - groupedRawValues: ["Element B"], - }, - ]); + await validatePagedDistinctValuesResponse( + testIModel, + descriptor.ruleset!, + new KeySet([rootNodes[1].key]), + {}, + userLabelField.getFieldDescriptor(), + [ + { + displayValue: "Element B", + groupedRawValues: ["Element B"], + }, + ], + ); }); - it("filters distinct content values using descriptor's instance filter", async function () { + it("filters distinct content values using descriptor's instance filter", async function() { const testIModel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { insertDocumentPartition(db, "A", "A"); insertDocumentPartition(db, "B1", "B"); @@ -423,7 +440,7 @@ describeContentTestSuite("Distinct Values", ({ getDefaultSuiteIModel }) => { ]); }); - it("filters distinct content values using descriptor's fields filter", async function () { + it("filters distinct content values using descriptor's fields filter", async function() { const testIModel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { insertDocumentPartition(db, "A", "A"); insertDocumentPartition(db, "B1", "B"); diff --git a/full-stack-tests/presentation/src/frontend/content/ElementProperties.test.ts b/full-stack-tests/presentation/src/frontend/content/ElementProperties.test.ts index 6bc4ef679e57..1a09ffa44403 100644 --- a/full-stack-tests/presentation/src/frontend/content/ElementProperties.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/ElementProperties.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { LabelDefinition } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { describeContentTestSuite, getFieldLabels } from "./Utils"; describeContentTestSuite("Element properties", ({ getDefaultSuiteIModel }) => { diff --git a/full-stack-tests/presentation/src/frontend/content/FieldsCustomization.test.ts b/full-stack-tests/presentation/src/frontend/content/FieldsCustomization.test.ts index ccceb5034080..1f2aba959544 100644 --- a/full-stack-tests/presentation/src/frontend/content/FieldsCustomization.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/FieldsCustomization.test.ts @@ -3,11 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert, Guid } from "@itwin/core-bentley"; import { InstanceKey, KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { getFieldByLabel } from "../../Utils"; +import { expect } from "chai"; import { buildTestIModelConnection, importSchema, @@ -15,10 +14,11 @@ import { insertPhysicalModelWithPartition, insertSpatialCategory, } from "../../IModelSetupUtils"; +import { getFieldByLabel } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Fields' customization", () => { - it("assigns custom renderer and editor to struct member property", async function () { + it("assigns custom renderer and editor to struct member property", async function() { let instanceKey: InstanceKey; let testSchema!: ReturnType; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -91,7 +91,7 @@ describeContentTestSuite("Fields' customization", () => { expect(structMemberField.editor).to.deep.eq({ name: "test-editor" }); }); - it("assigns custom renderer and editor to array item property", async function () { + it("assigns custom renderer and editor to array item property", async function() { let instanceKey: InstanceKey; let testSchema!: ReturnType; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -161,7 +161,7 @@ describeContentTestSuite("Fields' customization", () => { expect(arrayItemField.editor).to.deep.eq({ name: "test-editor" }); }); - it("assigns custom renderer and editor to struct-array member property", async function () { + it("assigns custom renderer and editor to struct-array member property", async function() { let instanceKey: InstanceKey; let testSchema!: ReturnType; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { diff --git a/full-stack-tests/presentation/src/frontend/content/FieldsSelector.test.ts b/full-stack-tests/presentation/src/frontend/content/FieldsSelector.test.ts index 785902b6581f..254823e59021 100644 --- a/full-stack-tests/presentation/src/frontend/content/FieldsSelector.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/FieldsSelector.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { Content, ContentSpecificationTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { collect } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/GuidProperties.test.ts b/full-stack-tests/presentation/src/frontend/content/GuidProperties.test.ts index c372ca2c5ad0..9d6f3f64d967 100644 --- a/full-stack-tests/presentation/src/frontend/content/GuidProperties.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/GuidProperties.test.ts @@ -3,16 +3,16 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { Content, ContentSpecificationTypes, InstanceKey, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { collect, getFieldByLabel } from "../../Utils"; +import { expect } from "chai"; import { buildTestIModelConnection, insertDocumentPartition } from "../../IModelSetupUtils"; +import { collect, getFieldByLabel } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; describeContentTestSuite("Guid properties", () => { - it("creates guid fields", async function () { + it("creates guid fields", async function() { const guid = Guid.createValue(); let instanceKey: InstanceKey; const imodelConnection = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { diff --git a/full-stack-tests/presentation/src/frontend/content/Infrastructure.test.ts b/full-stack-tests/presentation/src/frontend/content/Infrastructure.test.ts index 7d2d88230bd8..f10f05bdc9c5 100644 --- a/full-stack-tests/presentation/src/frontend/content/Infrastructure.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/Infrastructure.test.ts @@ -3,11 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; import { assert, BeDuration, BeTimePoint, Id64 } from "@itwin/core-bentley"; -import { ContentSpecificationTypes, InstanceKey, KeySet, PresentationError, PresentationStatus, Ruleset, RuleTypes } from "@itwin/presentation-common"; +import { + ContentSpecificationTypes, + InstanceKey, + KeySet, + PresentationError, + PresentationStatus, + Ruleset, + RuleTypes, +} from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { initialize, terminate } from "../../IntegrationTests"; import { collect } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; @@ -55,7 +63,9 @@ describeContentTestSuite("Error handling", ({ getDefaultSuiteIModel }) => { const keys = new KeySet([key1, key2]); const start = BeTimePoint.now(); await withRejectingPromiseRace(async () => { - await expect(Presentation.presentation.getContentDescriptor({ imodel: await getDefaultSuiteIModel(), rulesetOrId: ruleset, keys, displayType: "Grid" })) + await expect( + Presentation.presentation.getContentDescriptor({ imodel: await getDefaultSuiteIModel(), rulesetOrId: ruleset, keys, displayType: "Grid" }), + ) .to.be.eventually.rejectedWith(PresentationError) .and.have.property("errorNumber", PresentationStatus.BackendTimeout); }); @@ -85,7 +95,10 @@ describeContentTestSuite("Error handling", ({ getDefaultSuiteIModel }) => { }); assert(!!result); await withRejectingPromiseRace(async () => { - await expect(collect(result.items)).to.eventually.be.rejectedWith(PresentationError).and.have.property("errorNumber", PresentationStatus.BackendTimeout); + await expect(collect(result.items)).to.eventually.be.rejectedWith(PresentationError).and.have.property( + "errorNumber", + PresentationStatus.BackendTimeout, + ); }); }); }); diff --git a/full-stack-tests/presentation/src/frontend/content/InputKeys.test.ts b/full-stack-tests/presentation/src/frontend/content/InputKeys.test.ts index c8d86eeed1a8..f7208fdc2a51 100644 --- a/full-stack-tests/presentation/src/frontend/content/InputKeys.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/InputKeys.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { Content, ContentFlags, ContentSpecificationTypes, KeySet, RelationshipDirection, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { collect } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/InstanceFiltering.test.ts b/full-stack-tests/presentation/src/frontend/content/InstanceFiltering.test.ts index beaeb6dc4f7b..7aa9ee556c7f 100644 --- a/full-stack-tests/presentation/src/frontend/content/InstanceFiltering.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/InstanceFiltering.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { Content, ContentSpecificationTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { collect } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/NavigationProperties.test.ts b/full-stack-tests/presentation/src/frontend/content/NavigationProperties.test.ts index 24776627ce2f..9f69f01fe88b 100644 --- a/full-stack-tests/presentation/src/frontend/content/NavigationProperties.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/NavigationProperties.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert, Guid } from "@itwin/core-bentley"; import { ContentSpecificationTypes, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { getFieldByLabel } from "../../Utils"; import { describeContentTestSuite } from "./Utils"; diff --git a/full-stack-tests/presentation/src/frontend/content/PropertyValueFormatting.test.ts b/full-stack-tests/presentation/src/frontend/content/PropertyValueFormatting.test.ts index 75d32daaeca2..c2a31de0d471 100644 --- a/full-stack-tests/presentation/src/frontend/content/PropertyValueFormatting.test.ts +++ b/full-stack-tests/presentation/src/frontend/content/PropertyValueFormatting.test.ts @@ -3,12 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid, using } from "@itwin/core-bentley"; import { IModelConnection } from "@itwin/core-frontend"; +import { UnitSystemKey } from "@itwin/core-quantity"; +import { SchemaContext } from "@itwin/ecschema-metadata"; +import { ECSchemaRpcLocater } from "@itwin/ecschema-rpcinterface-common"; import { Content, ContentSpecificationTypes, DisplayValue, FormatsMap, InstanceKey, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { PresentationManager, PresentationManagerProps } from "@itwin/presentation-frontend"; -import { collect, getFieldByLabel } from "../../Utils"; +import { expect } from "chai"; import { buildTestIModelConnection, importSchema, @@ -17,9 +19,7 @@ import { insertPhysicalModelWithPartition, insertSpatialCategory, } from "../../IModelSetupUtils"; -import { UnitSystemKey } from "@itwin/core-quantity"; -import { SchemaContext } from "@itwin/ecschema-metadata"; -import { ECSchemaRpcLocater } from "@itwin/ecschema-rpcinterface-common"; +import { collect, getFieldByLabel } from "../../Utils"; import { describeContentTestSuite, getDisplayValue } from "./Utils"; describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel }) => { @@ -107,7 +107,7 @@ describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel } }); describe("of properties in different places of content", () => { - it("formats direct properties", async function () { + it("formats direct properties", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( @@ -139,7 +139,7 @@ describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel } expect(displayValue).to.eq("123.5 m"); }); - it("formats related properties", async function () { + it("formats related properties", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( @@ -175,11 +175,14 @@ describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel } }); }); const content = await getContent(imodel, elementKey); - const displayValue = getDisplayValue(content, [getFieldByLabel(content.descriptor.fields, "A"), getFieldByLabel(content.descriptor.fields, "Prop")]); + const displayValue = getDisplayValue(content, [ + getFieldByLabel(content.descriptor.fields, "A"), + getFieldByLabel(content.descriptor.fields, "Prop"), + ]); expect(displayValue).to.eq("123.5 m"); }); - it("formats array item properties", async function () { + it("formats array item properties", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( @@ -211,7 +214,7 @@ describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel } expect(displayValue).to.deep.eq(["123.5 m", "456.8 m"]); }); - it("formats struct member properties", async function () { + it("formats struct member properties", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( @@ -251,7 +254,7 @@ describeContentTestSuite("Property value formatting", ({ getDefaultSuiteIModel } expect(displayValue).to.eq("123.5 m"); }); - it("formats struct array member properties", async function () { + it("formats struct array member properties", async function() { let elementKey!: InstanceKey; const imodel = await buildTestIModelConnection(this.test!.title, async (db) => { const schema = importSchema( diff --git a/full-stack-tests/presentation/src/frontend/content/Utils.ts b/full-stack-tests/presentation/src/frontend/content/Utils.ts index 9c1b1a1a7cd1..698f82fffa1b 100644 --- a/full-stack-tests/presentation/src/frontend/content/Utils.ts +++ b/full-stack-tests/presentation/src/frontend/content/Utils.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Content, Descriptor, DisplayValue, Field, NestedContentField, Value } from "@itwin/presentation-common"; +import { expect } from "chai"; import { ECClassHierarchyInfo } from "../../ECClasHierarchy"; import { initialize, terminate, testLocalization } from "../../IntegrationTests"; @@ -60,7 +60,7 @@ export function createContentTestSuite(): ContentTestSuiteFunction { } export const describeContentTestSuite = createContentTestSuite(); -export type FieldLabels = Array; +export type FieldLabels = Array; export function getFieldLabels(fields: Descriptor | Field[]): FieldLabels { if (fields instanceof Descriptor) { fields = fields.fields; @@ -95,7 +95,9 @@ function cloneFilteredNestedContentField(field: NestedContentField, filterClassI function filterNestedContentFieldsByClass(fields: Field[], classInfo: ECClassHierarchyInfo) { const filteredFields = new Array(); fields.forEach((f) => { - if (f.isNestedContentField() && f.actualPrimaryClassIds.some((id) => classInfo.id === id || classInfo.derivedClasses.some((info) => info.id === id))) { + if ( + f.isNestedContentField() && f.actualPrimaryClassIds.some((id) => classInfo.id === id || classInfo.derivedClasses.some((info) => info.id === id)) + ) { const clone = cloneFilteredNestedContentField(f, classInfo); if (clone.nestedFields.length > 0) { filteredFields.push(clone); @@ -113,7 +115,9 @@ export function filterFieldsByClass(fields: Field[], classInfo: ECClassHierarchy // always include nested content field if its `actualPrimaryClassIds` contains either id of given class itself or one of its derived class ids // note: nested content fields might have more nested fields inside them and these deeply nested fields might not apply for given class - for // that we need to clone the field and pick only property fields and nested fields that apply. - const appliesForGivenClass = f.actualPrimaryClassIds.some((id) => classInfo.id === id || classInfo.derivedClasses.some((info) => info.id === id)); + const appliesForGivenClass = f.actualPrimaryClassIds.some((id) => + classInfo.id === id || classInfo.derivedClasses.some((info) => info.id === id) + ); if (appliesForGivenClass) { const clone = cloneFilteredNestedContentField(f, classInfo); if (clone.nestedFields.length > 0) { @@ -162,10 +166,12 @@ export function getDisplayValue(content: Content, fieldsPath: Field[]) { continue; } throw new Error( - `Failed to find a value for field "${currField.name} at path [${fieldsPath - .slice(0, i) - .map((f) => f.name) - .join(", ")}]. Current values: ${JSON.stringify(values)}"`, + `Failed to find a value for field "${currField.name} at path [${ + fieldsPath + .slice(0, i) + .map((f) => f.name) + .join(", ") + }]. Current values: ${JSON.stringify(values)}"`, ); } return displayValues[fieldsPath[fieldsPath.length - 1].name]; diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodeInstancesCount.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodeInstancesCount.test.ts index 201cc4759943..a5fdca69afb4 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodeInstancesCount.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodeInstancesCount.test.ts @@ -3,12 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; import { using } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; -import { ChildNodeSpecificationTypes, ECInstancesNodeKey, getInstancesCount, KeySet, RegisteredRuleset, Ruleset, RuleTypes } from "@itwin/presentation-common"; +import { + ChildNodeSpecificationTypes, + ECInstancesNodeKey, + getInstancesCount, + KeySet, + RegisteredRuleset, + Ruleset, + RuleTypes, +} from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; +import * as faker from "faker"; import { initialize, terminate } from "../../IntegrationTests"; import { collect } from "../../Utils"; @@ -51,7 +59,7 @@ describe("Hierarchies", () => { }, ], }; - await using>(await Presentation.presentation.rulesets().add(ruleset), async () => { + using>(await Presentation.presentation.rulesets().add(ruleset), async () => { const rootNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset.id }).then(async (x) => collect(x.items)); expect(rootNodes).to.matchSnapshot(); /* diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodePaths.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodePaths.test.ts index 9e559f36b0b9..fe46fd434a49 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodePaths.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/GettingNodePaths.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ChildNodeSpecificationTypes, InstanceKey, RelationshipDirection, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; describe("Hierarchies", () => { diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelDescriptors.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelDescriptors.test.ts index fd9c0e7c5168..a59ca297d621 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelDescriptors.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelDescriptors.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; import { @@ -17,8 +16,9 @@ import { RuleTypes, } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { initialize, terminate } from "../../IntegrationTests"; +import { expect } from "chai"; import { buildTestIModelConnection, insertDocumentPartition } from "../../IModelSetupUtils"; +import { initialize, terminate } from "../../IntegrationTests"; import { collect } from "../../Utils"; import { NodeValidators, validateHierarchy } from "./HierarchyValidation"; @@ -32,7 +32,7 @@ describe("Hierarchies", () => { }); describe("Getting hierarchy level descriptors", () => { - it("creates descriptor for root hierarchy level", async function () { + it("creates descriptor for root hierarchy level", async function() { // create an "empty" iModel - we'll use the root Subject for our test const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (_) => {}); @@ -88,7 +88,7 @@ describe("Hierarchies", () => { } as Partial); }); - it("creates descriptor for child hierarchy level", async function () { + it("creates descriptor for child hierarchy level", async function() { // create an "empty" iModel - we'll use the root Subject and default Models for our test const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (_) => {}); @@ -159,7 +159,7 @@ describe("Hierarchies", () => { } as Partial); }); - it("creates descriptor for hierarchy level that uses `parent` ECExpression symbol in instance filter", async function () { + it("creates descriptor for hierarchy level that uses `parent` ECExpression symbol in instance filter", async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" const imodelElementKeys: InstanceKey[] = []; const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -284,7 +284,7 @@ describe("Hierarchies", () => { } as Partial); }); - it("throws when attempting to get descriptor non-filterable hierarchy level", async function () { + it("throws when attempting to get descriptor non-filterable hierarchy level", async function() { // set up an empty imodel - we'll use the root Subject for this test const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (_) => {}); diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelFiltering.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelFiltering.test.ts index 5e5acd663389..a6ff50e0f09f 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelFiltering.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelFiltering.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; @@ -20,8 +19,9 @@ import { RuleTypes, } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { initialize, terminate } from "../../IntegrationTests"; +import { expect } from "chai"; import { buildTestIModelConnection, insertDocumentPartition } from "../../IModelSetupUtils"; +import { initialize, terminate } from "../../IntegrationTests"; import { NodeValidators, validateHierarchy } from "./HierarchyValidation"; describe("Hierarchies", () => { @@ -34,7 +34,7 @@ describe("Hierarchies", () => { }); describe("Hierarchy level filtering", () => { - it("filters root instance nodes hierarchy level", async function () { + it("filters root instance nodes hierarchy level", async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" const imodelElementKeys: InstanceKey[] = []; const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -118,7 +118,7 @@ describe("Hierarchies", () => { }); }); - it("filters child instance nodes hierarchy level", async function () { + it("filters child instance nodes hierarchy level", async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" const imodelElementKeys: InstanceKey[] = []; const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -255,7 +255,7 @@ describe("Hierarchies", () => { }); }); - it("filters guid properties", async function () { + it("filters guid properties", async function() { const imodelElementKeys: InstanceKey[] = []; const guidA = "814f3e14-63f2-4511-89a8-43ff3b527492"; const guidB = "182238d2-e836-4640-9b40-38be6ca49623"; @@ -352,7 +352,7 @@ describe("Hierarchies", () => { }); }); - it("filters grouped hierarchy levels", async function () { + it("filters grouped hierarchy levels", async function() { // set up imodel with 3 DocumentPartition elements: "a", "a" and "b" const imodelElementKeys: InstanceKey[] = []; const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -504,7 +504,7 @@ describe("Hierarchies", () => { }); }); - it("filters hierarchy levels that use `parent` ECExpression symbol in instance filter", async function () { + it("filters hierarchy levels that use `parent` ECExpression symbol in instance filter", async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" const imodelElementKeys: InstanceKey[] = []; const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -637,7 +637,7 @@ describe("Hierarchies", () => { }); }); - it("throws when attempting to filter non-filterable hierarchy level", async function () { + it("throws when attempting to filter non-filterable hierarchy level", async function() { // set up an empty imodel - we'll use the root Subject for this test const imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (_) => {}); diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelSizeLimiting.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelSizeLimiting.test.ts index 6575fb58e33c..a9176c8685df 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelSizeLimiting.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyLevelSizeLimiting.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Guid } from "@itwin/core-bentley"; import { IModel } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; @@ -17,8 +16,9 @@ import { RuleTypes, } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; -import { initialize, terminate } from "../../IntegrationTests"; +import { expect } from "chai"; import { buildTestIModelConnection, insertDocumentPartition } from "../../IModelSetupUtils"; +import { initialize, terminate } from "../../IntegrationTests"; import { collect } from "../../Utils"; import { NodeValidators, validateHierarchy } from "./HierarchyValidation"; @@ -37,7 +37,7 @@ describe("Hierarchies", () => { let ruleset: Ruleset; let expectedInstanceKeys: InstanceKey[]; - before(async function () { + before(async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" expectedInstanceKeys = []; imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -99,7 +99,7 @@ describe("Hierarchies", () => { let ruleset: Ruleset; let expectedInstanceKeys: InstanceKey[]; - before(async function () { + before(async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" expectedInstanceKeys = []; imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -180,7 +180,12 @@ describe("Hierarchies", () => { it("throws when result set size exceeds given limit", async () => { const rootNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); const rootSubject = rootNodes[0]; - const iteratorPromise = Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset, parentKey: rootSubject.key, sizeLimit: 1 }); + const iteratorPromise = Presentation.presentation.getNodesIterator({ + imodel, + rulesetOrId: ruleset, + parentKey: rootSubject.key, + sizeLimit: 1, + }); await expect(iteratorPromise).to.eventually.be.rejectedWith(PresentationError); }); }); @@ -190,7 +195,7 @@ describe("Hierarchies", () => { let ruleset: Ruleset; let expectedInstanceKeys: InstanceKey[]; - before(async function () { + before(async function() { // set up imodel with 2 DocumentPartition elements "a" and "b" expectedInstanceKeys = []; imodel = await buildTestIModelConnection(this.test!.fullTitle(), async (db) => { @@ -293,7 +298,9 @@ describe("Hierarchies", () => { }); it("throws when result set size exceeds given limit", async () => { - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); const classGroupingNode = classGroupingNodes[0]; await expect( Presentation.presentation diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyValidation.ts b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyValidation.ts index 2849ae67fb90..6490cd0ca5ef 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyValidation.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/HierarchyValidation.ts @@ -30,12 +30,16 @@ export namespace NodeValidators { } if (expectations.hasChildren !== undefined && node.hasChildren !== expectations.hasChildren) { throw new Error( - `Expected node's \`hasChildren\` flag to be ${optionalBooleanToString(expectations.hasChildren)}, got ${optionalBooleanToString(node.hasChildren)}`, + `Expected node's \`hasChildren\` flag to be ${optionalBooleanToString(expectations.hasChildren)}, got ${ + optionalBooleanToString(node.hasChildren) + }`, ); } if (expectations.supportsFiltering !== undefined && node.supportsFiltering !== expectations.supportsFiltering) { throw new Error( - `Expected node's \`supportsFiltering\` flag to be "${optionalBooleanToString(expectations.supportsFiltering)}", got "${optionalBooleanToString(node.supportsFiltering)}"`, + `Expected node's \`supportsFiltering\` flag to be "${optionalBooleanToString(expectations.supportsFiltering)}", got "${ + optionalBooleanToString(node.supportsFiltering) + }"`, ); } } @@ -55,7 +59,9 @@ export namespace NodeValidators { node.key.instanceKeys.length !== props.instanceKeys.length || !node.key.instanceKeys.every((nk) => props.instanceKeys.some((ek) => 0 === InstanceKey.compare(nk, ek))) ) { - throw new Error(`Expected node to represent instance keys ${JSON.stringify(props.instanceKeys)}, got ${JSON.stringify(node.key.instanceKeys)}`); + throw new Error( + `Expected node to represent instance keys ${JSON.stringify(props.instanceKeys)}, got ${JSON.stringify(node.key.instanceKeys)}`, + ); } validateBaseNodeAttributes(node, { label: props.label, diff --git a/full-stack-tests/presentation/src/frontend/hierarchies/Infrastructure.test.ts b/full-stack-tests/presentation/src/frontend/hierarchies/Infrastructure.test.ts index e109a3e239dd..60f9cd13ded6 100644 --- a/full-stack-tests/presentation/src/frontend/hierarchies/Infrastructure.test.ts +++ b/full-stack-tests/presentation/src/frontend/hierarchies/Infrastructure.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { ChildNodeSpecificationTypes, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { PresentationManager } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, resetBackend, terminate } from "../../IntegrationTests"; import { collect } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/ContentCustomization.test.ts b/full-stack-tests/presentation/src/learning-snippets/ContentCustomization.test.ts index 8fa23645560a..c6f513d95392 100644 --- a/full-stack-tests/presentation/src/learning-snippets/ContentCustomization.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/ContentCustomization.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Field, KeySet, NestedContentField, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../IntegrationTests"; import { getFieldByLabel } from "../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/PresentationManagerBackend.test.ts b/full-stack-tests/presentation/src/learning-snippets/PresentationManagerBackend.test.ts index 248ea7dd877a..04d5eb3e0ba8 100644 --- a/full-stack-tests/presentation/src/learning-snippets/PresentationManagerBackend.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/PresentationManagerBackend.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import { DisplayValue, IContentVisitor, ProcessPrimitiveValueProps, traverseContentItem, Value } from "@itwin/presentation-common"; -import { initialize, terminate } from "../IntegrationTests"; import { IModelDb, SnapshotDb } from "@itwin/core-backend"; import { Presentation } from "@itwin/presentation-backend"; +import { DisplayValue, IContentVisitor, ProcessPrimitiveValueProps, traverseContentItem, Value } from "@itwin/presentation-common"; +import { expect } from "chai"; +import { initialize, terminate } from "../IntegrationTests"; describe("Learning Snippets", () => { let imodel: IModelDb; @@ -28,9 +28,9 @@ describe("Learning Snippets", () => { interface PrimitivePropertiesSet { [propertyLabel: string]: | { - rawValue: string | number | boolean; - displayValue?: string; - } + rawValue: string | number | boolean; + displayValue?: string; + } | undefined; } class PrimitivePropertiesBuilder implements IContentVisitor { diff --git a/full-stack-tests/presentation/src/learning-snippets/RulesetVariables.test.ts b/full-stack-tests/presentation/src/learning-snippets/RulesetVariables.test.ts index 2974063a7bf9..2a20d075161a 100644 --- a/full-stack-tests/presentation/src/learning-snippets/RulesetVariables.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/RulesetVariables.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../IntegrationTests"; -import { printRuleset } from "./Utils"; import { collect } from "../Utils"; +import { printRuleset } from "./Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/common/MultiSchemaClasses.test.ts b/full-stack-tests/presentation/src/learning-snippets/common/MultiSchemaClasses.test.ts index a0b935f09ea7..918a3629d12c 100644 --- a/full-stack-tests/presentation/src/learning-snippets/common/MultiSchemaClasses.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/common/MultiSchemaClasses.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/common/RelatedInstanceSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/common/RelatedInstanceSpecification.test.ts index 0a0eb3942eb5..f602684bba34 100644 --- a/full-stack-tests/presentation/src/learning-snippets/common/RelatedInstanceSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/common/RelatedInstanceSpecification.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModel } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Node, Ruleset, StandardNodeTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; import { getFieldByLabel } from "../../Utils"; import { printRuleset } from "../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/common/RelationshipPathSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/common/RelationshipPathSpecification.test.ts index 2c7399277351..80dc90f41a40 100644 --- a/full-stack-tests/presentation/src/learning-snippets/common/RelationshipPathSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/common/RelationshipPathSpecification.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; import { printRuleset } from "../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/common/RepeatableRelationshipPathSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/common/RepeatableRelationshipPathSpecification.test.ts index 008b408b8377..b5ae2753ae91 100644 --- a/full-stack-tests/presentation/src/learning-snippets/common/RepeatableRelationshipPathSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/common/RepeatableRelationshipPathSpecification.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/customization/CalculatedPropertiesSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/customization/CalculatedPropertiesSpecification.test.ts index 4d3452a8bed2..50ec858b7686 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/customization/CalculatedPropertiesSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/customization/CalculatedPropertiesSpecification.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { getFieldByLabel } from "../../../Utils"; import { printRuleset } from "../../Utils"; @@ -177,7 +177,7 @@ describe("Learning Snippets", () => { value: "123", extendedData: { extendedDataInt: "2*2", - extendedDataStr: "\"xxx\"" + extendedDataStr: '"xxx"', }, }, ], @@ -202,7 +202,7 @@ describe("Learning Snippets", () => { label: "My Calculated Property", extendedData: { extendedDataInt: 4, - extendedDataStr: "xxx" + extendedDataStr: "xxx", }, }, ]); @@ -225,7 +225,7 @@ describe("Learning Snippets", () => { { label: "My Calculated Property", value: "2+2", - type: "int" + type: "int", }, ], }, diff --git a/full-stack-tests/presentation/src/learning-snippets/content/customization/DefaultPropertyCategoryOverride.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/customization/DefaultPropertyCategoryOverride.test.ts index 8a99549bdf74..3f50015f546a 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/customization/DefaultPropertyCategoryOverride.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/customization/DefaultPropertyCategoryOverride.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { printRuleset } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertyCategorySpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertyCategorySpecification.test.ts index bdb6d4f4c803..6706132fb46d 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertyCategorySpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertyCategorySpecification.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { printRuleset } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertySpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertySpecification.test.ts index 28481159d4f0..44ea4bb7f7f2 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertySpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/customization/PropertySpecification.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { printRuleset } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/customization/RelatedPropertiesSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/customization/RelatedPropertiesSpecification.test.ts index 6b5f69b06b30..e6074c5d5c40 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/customization/RelatedPropertiesSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/customization/RelatedPropertiesSpecification.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Field, KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { printRuleset } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentModifier.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentModifier.test.ts index 395c80b42214..5ad56b36c91f 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentModifier.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentModifier.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, NestedContentValue, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { collect, getFieldByLabel, getFieldsByLabel, tryGetFieldByLabel } from "../../../Utils"; import { printRuleset } from "../../Utils"; @@ -307,7 +307,8 @@ describe("Learning Snippets", () => { getFieldByLabel(content!.descriptor.fields, "Spatial View Definition").name ] as NestedContentValue[]; expect(spatialViewDefinition.length).to.eq(1); - expect(spatialViewDefinition[0].values[getFieldByLabel(content!.descriptor.fields, "Calculated for SpatialViewDefinition").name]).to.not.be.empty; + expect(spatialViewDefinition[0].values[getFieldByLabel(content!.descriptor.fields, "Calculated for SpatialViewDefinition").name]).to.not.be + .empty; const nestedDisplayStyle = getFieldsByLabel(content!.descriptor.fields, "Display Style").find((field) => field.isNestedContentField()); const displayStyle = spatialViewDefinition[0].values[nestedDisplayStyle!.name] as NestedContentValue[]; expect(displayStyle.length).to.eq(1); diff --git a/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentRule.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentRule.test.ts index 8492b7895dd1..a78903f02dda 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentRule.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/rules/ContentRule.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentInstancesOfSpecificClasses.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentInstancesOfSpecificClasses.test.ts index 967da64d4c41..778829efc171 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentInstancesOfSpecificClasses.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentInstancesOfSpecificClasses.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { collect, getFieldByLabel } from "../../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentRelatedInstances.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentRelatedInstances.test.ts index b4cbe59a6209..d232ffb6d8b4 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentRelatedInstances.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/specifications/ContentRelatedInstances.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { getFieldByLabel } from "../../../Utils"; import { printRuleset } from "../../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/specifications/SelectedNodeInstances.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/specifications/SelectedNodeInstances.test.ts index bcc9a3dc5c5f..d58758387283 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/specifications/SelectedNodeInstances.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/specifications/SelectedNodeInstances.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/content/specifications/Shared.test.ts b/full-stack-tests/presentation/src/learning-snippets/content/specifications/Shared.test.ts index 3dee8c101755..d9119aef3b55 100644 --- a/full-stack-tests/presentation/src/learning-snippets/content/specifications/Shared.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/content/specifications/Shared.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; import { getFieldByLabel } from "../../../Utils"; import { printRuleset } from "../../Utils"; @@ -316,7 +316,10 @@ describe("Learning Snippets", () => { classes: { schemaName: "BisCore", classNames: ["ModelSelector"], arePolymorphic: true }, relatedInstances: [ { - relationshipPath: { relationship: { schemaName: "BisCore", className: "SpatialViewDefinitionUsesModelSelector" }, direction: "Backward" }, + relationshipPath: { + relationship: { schemaName: "BisCore", className: "SpatialViewDefinitionUsesModelSelector" }, + direction: "Backward", + }, alias: "relatedInstance", }, ], diff --git a/full-stack-tests/presentation/src/learning-snippets/customization/DisabledSortingRule.test.ts b/full-stack-tests/presentation/src/learning-snippets/customization/DisabledSortingRule.test.ts index 1c16808298ee..e874ed803f22 100644 --- a/full-stack-tests/presentation/src/learning-snippets/customization/DisabledSortingRule.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/customization/DisabledSortingRule.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset, VariableValueTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; import { printRuleset } from "../Utils"; diff --git a/full-stack-tests/presentation/src/learning-snippets/customization/ExtendedDataRule.test.ts b/full-stack-tests/presentation/src/learning-snippets/customization/ExtendedDataRule.test.ts index 1a33a8df5d14..31e2528c6b94 100644 --- a/full-stack-tests/presentation/src/learning-snippets/customization/ExtendedDataRule.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/customization/ExtendedDataRule.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { KeySet, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/customization/InstanceLabelOverride.test.ts b/full-stack-tests/presentation/src/learning-snippets/customization/InstanceLabelOverride.test.ts index c0f28e410064..7027298ea63a 100644 --- a/full-stack-tests/presentation/src/learning-snippets/customization/InstanceLabelOverride.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/customization/InstanceLabelOverride.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate, testLocalization } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; @@ -659,7 +659,9 @@ describe("Learning Snippets", () => { .then(async (x) => collect(x.items)); expect(nodes) .to.be.lengthOf(2) - .and.to.containSubset([{ label: { displayValue: "Properties_60InstancesWithUrl2" } }, { label: { displayValue: "Properties_60InstancesWithUrl2" } }]); + .and.to.containSubset([{ label: { displayValue: "Properties_60InstancesWithUrl2" } }, { + label: { displayValue: "Properties_60InstancesWithUrl2" }, + }]); }); }); }); diff --git a/full-stack-tests/presentation/src/learning-snippets/customization/PropertySortingRule.test.ts b/full-stack-tests/presentation/src/learning-snippets/customization/PropertySortingRule.test.ts index b6a86acc4b6f..2338abc1feb5 100644 --- a/full-stack-tests/presentation/src/learning-snippets/customization/PropertySortingRule.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/customization/PropertySortingRule.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset, VariableValueTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/customization/SortingShared.test.ts b/full-stack-tests/presentation/src/learning-snippets/customization/SortingShared.test.ts index 33451a3fab47..ffe8aa8aa57f 100644 --- a/full-stack-tests/presentation/src/learning-snippets/customization/SortingShared.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/customization/SortingShared.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../IntegrationTests"; -import { printRuleset } from "../Utils"; import { collect } from "../../Utils"; +import { printRuleset } from "../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/ClassGroup.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/ClassGroup.test.ts index 96cf7bf93a1c..6e1e264f63fb 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/ClassGroup.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/ClassGroup.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset, StandardNodeTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/PropertyGroup.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/PropertyGroup.test.ts index 1f7eee9a1e29..05af7d08a67d 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/PropertyGroup.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/PropertyGroup.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset, StandardNodeTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/SameLabelInstanceGroup.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/SameLabelInstanceGroup.test.ts index 5435372932b8..7729bb6fb898 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/SameLabelInstanceGroup.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/SameLabelInstanceGroup.test.ts @@ -2,15 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import deepEqual from "deep-equal"; -import { sort } from "fast-sort"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { InstanceKey, NodeKey, Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; +import deepEqual from "deep-equal"; +import { sort } from "fast-sort"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/Shared.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/Shared.test.ts index 5bda7e8acf77..fdcba7c7d4ab 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/Shared.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/grouping/Shared.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset, StandardNodeTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeArtifacts.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeArtifacts.test.ts index ed0dee21cdc1..849ba4f63a53 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeArtifacts.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeArtifacts.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeRules.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeRules.test.ts index 78d69bab29d9..95c6a4c0d6b3 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeRules.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/rules/NodeRules.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomNodeSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomNodeSpecification.test.ts index b092e03ac8ab..fdb1fbce14d6 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomNodeSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomNodeSpecification.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomQueryInstanceNodesSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomQueryInstanceNodesSpecification.test.ts index b500156a822c..afcc15153ce1 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomQueryInstanceNodesSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/CustomQueryInstanceNodesSpecification.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; @@ -52,7 +52,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify that Model nodes are returned - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(classGroupingNodes) .to.have.lengthOf(7) .and.to.containSubset([ diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/InstanceNodesOfSpecificClassesSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/InstanceNodesOfSpecificClassesSpecification.test.ts index c2e449acbc2d..21e4b447b420 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/InstanceNodesOfSpecificClassesSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/InstanceNodesOfSpecificClassesSpecification.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; @@ -47,7 +47,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify that PhysicalModel nodes were returned, grouped by class - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(classGroupingNodes) .to.have.lengthOf(1) .and.to.containSubset([ @@ -91,7 +93,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify that DefinitionModel and GroupInformationModel nodes are not included - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(classGroupingNodes) .to.have.lengthOf(3) .and.to.containSubset([ @@ -130,7 +134,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify that ViewDefinition nodes ending with "View 1" are not included - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(classGroupingNodes) .to.have.lengthOf(1) .and.to.containSubset([ diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/RelatedInstanceNodesSpecification.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/RelatedInstanceNodesSpecification.test.ts index 1481083e1a30..16dff8fd9ac7 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/RelatedInstanceNodesSpecification.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/RelatedInstanceNodesSpecification.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { Ruleset } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; diff --git a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/Shared.test.ts b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/Shared.test.ts index c27086e238fa..02b323d9ecfe 100644 --- a/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/Shared.test.ts +++ b/full-stack-tests/presentation/src/learning-snippets/hierarchies/specifications/Shared.test.ts @@ -2,14 +2,14 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { assert } from "@itwin/core-bentley"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { NodeKey, Ruleset, StandardNodeTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { initialize, terminate } from "../../../IntegrationTests"; -import { printRuleset } from "../../Utils"; import { collect } from "../../../Utils"; +import { printRuleset } from "../../Utils"; describe("Learning Snippets", () => { let imodel: IModelConnection; @@ -59,7 +59,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify PhysicalModel's class grouping node is displayed, but the instance node - not - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); expect(classGroupingNodes) .to.have.lengthOf(1) .and.to.containSubset([ @@ -479,7 +481,9 @@ describe("Learning Snippets", () => { printRuleset(ruleset); // Verify that instances were not grouped by label - const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => collect(x.items)); + const classGroupingNodes = await Presentation.presentation.getNodesIterator({ imodel, rulesetOrId: ruleset }).then(async (x) => + collect(x.items) + ); const classGroupingNode = classGroupingNodes.find((node) => { assert(NodeKey.isClassGroupingNodeKey(node.key)); return node.key.className === "ECDbMeta:ECPropertyDef"; diff --git a/full-stack-tests/presentation/src/performance/DataViz.test.ts b/full-stack-tests/presentation/src/performance/DataViz.test.ts index 4cb63268140a..3a11221272e0 100644 --- a/full-stack-tests/presentation/src/performance/DataViz.test.ts +++ b/full-stack-tests/presentation/src/performance/DataViz.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable no-console */ -import { expect } from "chai"; import { assert, Guid, Id64String, OrderedId64Iterable, StopWatch } from "@itwin/core-bentley"; import { QueryBinder, QueryRowFormat } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; @@ -30,6 +29,7 @@ import { Value, } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { ECClassHierarchy, ECClassInfo } from "../ECClasHierarchy"; import { initialize, terminate } from "../IntegrationTests"; import { collect, getFieldsByLabel } from "../Utils"; @@ -310,7 +310,7 @@ describe("#performance DataViz requests", () => { `Suggested implementation took ${suggestedRequestsTime} s. with ${suggestedRequestsCount.elementIds} requests for direct element IDs and ${suggestedRequestsCount.childElementIds} for child element IDs.`, ); - const totals = [...suggestedEntries.values()].reduce<{ e: number; c: number }>( + const totals = [...suggestedEntries.values()].reduce<{ e: number, c: number }>( (t, curr) => ({ e: t.e + curr.elementIds.length, c: t.c + curr.childIds.length }), { e: 0, c: 0 }, ); @@ -368,7 +368,14 @@ describe("#performance DataViz requests", () => { // find and group all classes that have instances with each individual distinct value const displayValueEntries = new Map< string, - Set<{ contentClassId: Id64String; pathFromContentToPropertyClass: StrippedRelationshipPath; filteredProperty: PropertyInfo; rawValues: Value[] }> + Set< + { + contentClassId: Id64String; + pathFromContentToPropertyClass: StrippedRelationshipPath; + filteredProperty: PropertyInfo; + rawValues: Value[]; + } + > >(); const readEntries = async ( queryBase: string, @@ -379,7 +386,9 @@ describe("#performance DataViz requests", () => { for (const distinctValuesEntry of distinctValues) { const [displayValue, rawValues] = distinctValuesEntry; const filteredClassesQuery = `${queryBase}${createWhereClause(propertyClassAlias, filteredProperty, [...rawValues])}`; - for await (const { classId } of iModel.createQueryReader(filteredClassesQuery, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const { classId } of iModel.createQueryReader(filteredClassesQuery, undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }) + ) { pushValues(displayValueEntries, displayValue, [ { contentClassId: classId, pathFromContentToPropertyClass, filteredProperty, rawValues: [...rawValues] }, ]); @@ -433,24 +442,23 @@ describe("#performance DataViz requests", () => { { specType: ChildNodeSpecificationTypes.InstanceNodesOfSpecificClasses, classes: { schemaName: contentClassInfo.schemaName, classNames: [contentClassInfo.name], arePolymorphic: false }, - relatedInstances: - pathFromContentToPropertyClass.length > 0 - ? [ - { - relationshipPath: pathFromContentToPropertyClass.map((step) => { - const [relationshipSchemaName, relationshipClassName] = step.relationshipName.split(":"); - const [targetSchemaName, targetClassName] = step.targetClassName.split(":"); - return { - relationship: { schemaName: relationshipSchemaName, className: relationshipClassName }, - direction: step.isForwardRelationship ? RelationshipDirection.Forward : RelationshipDirection.Backward, - targetClass: { schemaName: targetSchemaName, className: targetClassName }, - }; - }), - isRequired: true, - alias: propertyClassAlias, - }, - ] - : [], + relatedInstances: pathFromContentToPropertyClass.length > 0 + ? [ + { + relationshipPath: pathFromContentToPropertyClass.map((step) => { + const [relationshipSchemaName, relationshipClassName] = step.relationshipName.split(":"); + const [targetSchemaName, targetClassName] = step.targetClassName.split(":"); + return { + relationship: { schemaName: relationshipSchemaName, className: relationshipClassName }, + direction: step.isForwardRelationship ? RelationshipDirection.Forward : RelationshipDirection.Backward, + targetClass: { schemaName: targetSchemaName, className: targetClassName }, + }; + }), + isRequired: true, + alias: propertyClassAlias, + }, + ] + : [], instanceFilter: rawValues.reduce((filter, rawValue) => { if (filter !== "") { filter += " OR "; @@ -490,7 +498,7 @@ describe("#performance DataViz requests", () => { elementIds: 0, childElementIds: 0, }; - const idEntries = new Map(); + const idEntries = new Map(); async function getNodeKeys(ruleset: Ruleset, node: Node) { const keys: InstanceKey[] = []; @@ -566,7 +574,7 @@ describe("#performance DataViz requests", () => { const timer = new StopWatch("", true); // group filtered fields by their root content classes - const selectClasses = new Map }>(); + const selectClasses = new Map }>(); for (const filteredField of filteredFields) { const { rootField, path: stack } = getRootField(filteredField); if (rootField.isNestedContentField()) { @@ -678,7 +686,7 @@ describe("#performance DataViz requests", () => { // Similar to the "current" approach, we need to recursively get child element IDs. But in this case // we request them per display value entry rather than per every unique class for the entry. - const entries = new Map(); + const entries = new Map(); await Promise.all( [...elementEntries].map(async (entry) => { const [displayValue, elementIds] = entry; @@ -748,7 +756,7 @@ function getRootField(field: PropertiesField) { }; } -function detectIntersections(distinctValueElementIds: Map) { +function detectIntersections(distinctValueElementIds: Map) { const arr = [...distinctValueElementIds]; for (let i = 0; i < arr.length; ++i) { for (let j = i + 1; j < arr.length; ++j) { diff --git a/full-stack-tests/presentation/src/performance/GetElementProperties.test.ts b/full-stack-tests/presentation/src/performance/GetElementProperties.test.ts index d10e9158227d..b6b4191b9bd5 100644 --- a/full-stack-tests/presentation/src/performance/GetElementProperties.test.ts +++ b/full-stack-tests/presentation/src/performance/GetElementProperties.test.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ /* eslint-disable no-console */ -import { expect } from "chai"; -import * as os from "os"; -import { join } from "path"; import { IModelDb, IModelHost, SnapshotDb } from "@itwin/core-backend"; import { StopWatch } from "@itwin/core-bentley"; import { DbResult, QueryRowFormat } from "@itwin/core-common"; import { Presentation } from "@itwin/presentation-backend"; +import { expect } from "chai"; +import * as os from "os"; +import { join } from "path"; describe("#performance Element properties loading", () => { let imodel: SnapshotDb; @@ -34,10 +34,14 @@ describe("#performance Element properties loading", () => { expect(imodel).is.not.null; }); - it("load properties using 'getElementProperties'", async function () { + it("load properties using 'getElementProperties'", async function() { const timer = new StopWatch(undefined, true); let itemsCount = 0; - const { total, iterator } = await Presentation.getManager().getElementProperties({ imodel, elementClasses: ["BisCore.GeometricElement"], batchSize: 1000 }); + const { total, iterator } = await Presentation.getManager().getElementProperties({ + imodel, + elementClasses: ["BisCore.GeometricElement"], + batchSize: 1000, + }); console.log(`Loading properties for ${total} elements...`); for await (const items of iterator()) { itemsCount += items.length; @@ -47,7 +51,7 @@ describe("#performance Element properties loading", () => { console.log(`Loaded ${itemsCount} elements properties in ${timer.currentSeconds.toFixed(2)} s`); }); - it("load properties using ECSQL", async function () { + it("load properties using ECSQL", async function() { const timer = new StopWatch(undefined, true); process.stdout.write(`Loading properties.`); let itemsCount = 0; diff --git a/full-stack-tests/presentation/src/rpc/PresentationRpcInterface.test.ts b/full-stack-tests/presentation/src/rpc/PresentationRpcInterface.test.ts index 044e45b42d3f..084840907439 100644 --- a/full-stack-tests/presentation/src/rpc/PresentationRpcInterface.test.ts +++ b/full-stack-tests/presentation/src/rpc/PresentationRpcInterface.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { RpcManager } from "@itwin/core-common"; import { IModelConnection, SnapshotConnection } from "@itwin/core-frontend"; import { PresentationRpcInterface } from "@itwin/presentation-common"; +import { expect } from "chai"; import { initialize, terminate } from "../IntegrationTests"; describe("PresentationRpcInterface", () => { diff --git a/full-stack-tests/rpc-interface/certa.json b/full-stack-tests/rpc-interface/certa.json index 4ca61fee2f10..93112a5bed7c 100644 --- a/full-stack-tests/rpc-interface/certa.json +++ b/full-stack-tests/rpc-interface/certa.json @@ -20,4 +20,4 @@ "mochaFile": "full_stack_test_results/full_stack_test_result.xml" } } -} \ No newline at end of file +} diff --git a/full-stack-tests/rpc-interface/eslint.config.js b/full-stack-tests/rpc-interface/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/full-stack-tests/rpc-interface/eslint.config.js +++ b/full-stack-tests/rpc-interface/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/full-stack-tests/rpc-interface/src/backend/BackendInit.ts b/full-stack-tests/rpc-interface/src/backend/BackendInit.ts index 7289692e36ac..4a0e730594f7 100644 --- a/full-stack-tests/rpc-interface/src/backend/BackendInit.ts +++ b/full-stack-tests/rpc-interface/src/backend/BackendInit.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import "@itwin/oidc-signin-tool/lib/cjs/certa/certaBackend"; // Sets up certa to allow a method on the frontend to get an access token +import * as fs from "fs"; import * as path from "path"; import { exposeBackendCallbacks } from "../common/SideChannels"; -import * as fs from "fs"; /* eslint-disable no-console */ diff --git a/full-stack-tests/rpc-interface/src/common/Settings.ts b/full-stack-tests/rpc-interface/src/common/Settings.ts index 8027f4a5701f..09553174d41e 100644 --- a/full-stack-tests/rpc-interface/src/common/Settings.ts +++ b/full-stack-tests/rpc-interface/src/common/Settings.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ServiceAuthorizationClientConfiguration } from "@itwin/service-authorization"; import { LogLevel } from "@itwin/core-bentley"; import { DevToolsRpcInterface, IModelReadRpcInterface, IModelTileRpcInterface } from "@itwin/core-common"; import { TestUserCredentials } from "@itwin/oidc-signin-tool"; import { PresentationRpcInterface } from "@itwin/presentation-common"; +import { ServiceAuthorizationClientConfiguration } from "@itwin/service-authorization"; /* eslint-disable @typescript-eslint/indent */ @@ -65,21 +65,39 @@ export class Settings { public clientConfiguration?: ServiceAuthorizationClientConfiguration; public iModels: IModelData[] = []; - public get iModel(): IModelData { return this.iModels[0]; } - public get writeIModel(): IModelData { return this.iModels[1]; } - public get user(): TestUserCredentials { return this.users[0]; } + public get iModel(): IModelData { + return this.iModels[0]; + } + public get writeIModel(): IModelData { + return this.iModels[1]; + } + public get user(): TestUserCredentials { + return this.users[0]; + } // eslint-disable-next-line @typescript-eslint/naming-convention - public get Backend(): Backend { return this._backend; } + public get Backend(): Backend { + return this._backend; + } - public get runiModelTileRpcTests(): boolean { return checkEnabled(process.env.RPC_IMODELTILE_ENABLE); } - public get runPresentationRpcTests(): boolean { return checkEnabled(process.env.RPC_PRESENTATION_ENABLE); } - public get runiModelReadRpcTests(): boolean { return checkEnabled(process.env.RPC_IMODELREAD_ENABLE); } - public get runiModelWriteRpcTests(): boolean { return checkEnabled(process.env.RPC_IMODELWRITE_ENABLE); } - public get runDevToolsRpcTests(): boolean { return checkEnabled(process.env.RPC_DEVTOOLS_ENABLE); } + public get runiModelTileRpcTests(): boolean { + return checkEnabled(process.env.RPC_IMODELTILE_ENABLE); + } + public get runPresentationRpcTests(): boolean { + return checkEnabled(process.env.RPC_PRESENTATION_ENABLE); + } + public get runiModelReadRpcTests(): boolean { + return checkEnabled(process.env.RPC_IMODELREAD_ENABLE); + } + public get runiModelWriteRpcTests(): boolean { + return checkEnabled(process.env.RPC_IMODELWRITE_ENABLE); + } + public get runDevToolsRpcTests(): boolean { + return checkEnabled(process.env.RPC_DEVTOOLS_ENABLE); + } constructor(env: NodeJS.ProcessEnv) { - const isFrontend = (typeof (process) === "undefined"); + const isFrontend = typeof process === "undefined"; if (!isFrontend && undefined === env.TF_BUILD) { const path = require("path"); // eslint-disable-line @typescript-eslint/no-var-requires const dotenv = require("dotenv"); // eslint-disable-line @typescript-eslint/no-var-requires @@ -188,7 +206,10 @@ export class Settings { password: process.env.USER_WITH_ACCESS_PASSWORD || "", }); - if (undefined !== process.env.CLIENT_WITH_ACCESS_ID && undefined !== process.env.CLIENT_WITH_ACCESS_SECRET && undefined !== process.env.CLIENT_WITH_ACCESS_SCOPES) { + if ( + undefined !== process.env.CLIENT_WITH_ACCESS_ID && undefined !== process.env.CLIENT_WITH_ACCESS_SECRET && + undefined !== process.env.CLIENT_WITH_ACCESS_SCOPES + ) { this.clientConfiguration = { clientId: process.env.CLIENT_WITH_ACCESS_ID, clientSecret: process.env.CLIENT_WITH_ACCESS_SECRET, diff --git a/full-stack-tests/rpc-interface/src/common/SideChannels.ts b/full-stack-tests/rpc-interface/src/common/SideChannels.ts index b09a7be9ef1d..66cf0b6aa625 100644 --- a/full-stack-tests/rpc-interface/src/common/SideChannels.ts +++ b/full-stack-tests/rpc-interface/src/common/SideChannels.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ // import { ServiceAuthorizationClient, ServiceAuthorizationClientConfiguration } from "@itwin/service-authorization"; -import { AccessToken } from "@itwin/core-bentley"; import { executeBackendCallback, registerBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; +import { AccessToken } from "@itwin/core-bentley"; const getEnvCallbackName = "getEnv"; const getClientAccessTokenCallbackName = "getClientAccessToken"; diff --git a/full-stack-tests/rpc-interface/src/frontend/CodeSpecs.test.ts b/full-stack-tests/rpc-interface/src/frontend/CodeSpecs.test.ts index baccfe04e5b2..695dfc68d9a9 100644 --- a/full-stack-tests/rpc-interface/src/frontend/CodeSpecs.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/CodeSpecs.test.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; import { BisCodeSpec, CodeSpec } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; const expect = chai.expect; @@ -13,7 +13,7 @@ const expect = chai.expect; describe("Get Code Specs", () => { let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) @@ -27,7 +27,6 @@ describe("Get Code Specs", () => { /** verify that given codespec has expected properties */ function verifyCodeSpec(codeSpec: CodeSpec, requestedIModel: IModelConnection, requestedName: string, requestedId: string) { - expect(codeSpec).to.exist; expect(codeSpec.id).to.exist; diff --git a/full-stack-tests/rpc-interface/src/frontend/DevToolsRpc.test.ts b/full-stack-tests/rpc-interface/src/frontend/DevToolsRpc.test.ts index b9d48f9c480f..f6d91d844661 100644 --- a/full-stack-tests/rpc-interface/src/frontend/DevToolsRpc.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/DevToolsRpc.test.ts @@ -2,16 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { LogLevel } from "@itwin/core-bentley"; import { DevTools, IModelConnection } from "@itwin/core-frontend"; +import { assert } from "chai"; import { TestContext } from "./setup/TestContext"; describe("DevTools", () => { let iModel: IModelConnection; let devTools: DevTools; - before(async function () { + before(async function() { const testContext = await TestContext.instance(); if (!testContext.settings.runDevToolsRpcTests) diff --git a/full-stack-tests/rpc-interface/src/frontend/Elements.test.ts b/full-stack-tests/rpc-interface/src/frontend/Elements.test.ts index d49e401bc67c..5a9b4d9ff0b4 100644 --- a/full-stack-tests/rpc-interface/src/frontend/Elements.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/Elements.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; import { Id64Set, Id64String } from "@itwin/core-bentley"; import { ElementProps, QueryRowFormat } from "@itwin/core-common"; import { IModelConnection, SpatialModelState } from "@itwin/core-frontend"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; const expect = chai.expect; @@ -15,7 +15,7 @@ describe("IModel Elements", () => { let iModel: IModelConnection; let elements: IModelConnection.Elements; - before(async function () { + before(async function() { const testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) @@ -46,7 +46,7 @@ describe("IModel Elements", () => { }); describe("Operational: Execute Query", () => { - it("should successfully execute a simple query", async function () { + it("should successfully execute a simple query", async function() { const testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) @@ -62,4 +62,3 @@ describe("Operational: Execute Query", () => { expect(rows).to.be.not.empty; }); }); - diff --git a/full-stack-tests/rpc-interface/src/frontend/IModel.test.ts b/full-stack-tests/rpc-interface/src/frontend/IModel.test.ts index 8a5658b9562d..2e480cf22865 100644 --- a/full-stack-tests/rpc-interface/src/frontend/IModel.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/IModel.test.ts @@ -3,18 +3,17 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; import { FontMap, GeometryContainmentRequestProps } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; const expect = chai.expect; describe("IModel Views", () => { - let iModel: IModelConnection; - before(async function () { + before(async function() { const testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) diff --git a/full-stack-tests/rpc-interface/src/frontend/IModelConnection.test.ts b/full-stack-tests/rpc-interface/src/frontend/IModelConnection.test.ts index 75038b69891f..6a02ecb75ef4 100644 --- a/full-stack-tests/rpc-interface/src/frontend/IModelConnection.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/IModelConnection.test.ts @@ -2,15 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Buffer } from "buffer"; -import * as chai from "chai"; import { AccessToken, BentleyStatus, CompressedId64Set, Id64, Id64Set } from "@itwin/core-bentley"; -import { Matrix4d, Point3d, XYZProps, YawPitchRollAngles } from "@itwin/core-geometry"; import { - EcefLocation, GeoCoordStatus, IModelReadRpcInterface, IModelVersion, MassPropertiesOperation, MassPropertiesPerCandidateRequestProps, MassPropertiesRequestProps, ModelQueryParams, + EcefLocation, + GeoCoordStatus, + IModelReadRpcInterface, + IModelVersion, + MassPropertiesOperation, + MassPropertiesPerCandidateRequestProps, + MassPropertiesRequestProps, + ModelQueryParams, } from "@itwin/core-common"; import { CheckpointConnection, IModelApp, IModelConnection, SpatialModelState, ViewState } from "@itwin/core-frontend"; +import { Matrix4d, Point3d, XYZProps, YawPitchRollAngles } from "@itwin/core-geometry"; import { TestFrontendAuthorizationClient } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { Buffer } from "buffer"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; /* eslint-disable deprecation/deprecation */ @@ -27,7 +34,7 @@ describe("IModel Connection", () => { let accessToken: AccessToken; let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) @@ -63,7 +70,7 @@ describe.skip("IModel Connection with client credentials", () => { let accessToken: AccessToken; let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); // If client credentials are not supplied or imodel read rpc tests are disabled skip test suite @@ -78,7 +85,11 @@ describe.skip("IModel Connection with client credentials", () => { const iModelId = testContext.iModelWithChangesets!.iModelId; const changeSetId = (await testContext.iModelWithChangesets!.getConnection()).changeset.id; - const iModel = await CheckpointConnection.openRemote(iTwinId, iModelId, undefined === changeSetId ? IModelVersion.latest() : IModelVersion.asOfChangeSet(changeSetId)); + const iModel = await CheckpointConnection.openRemote( + iTwinId, + iModelId, + undefined === changeSetId ? IModelVersion.latest() : IModelVersion.asOfChangeSet(changeSetId), + ); expect(iModel).to.exist.and.be.not.empty; @@ -93,7 +104,7 @@ describe("IModelReadRpcInterface Methods from an IModelConnection", () => { let accessToken: AccessToken; let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) { @@ -278,14 +289,17 @@ describe("IModelReadRpcInterface Methods from an IModelConnection", () => { ranges = await iModel.models.queryModelRanges(idSet); expect(ranges).to.not.be.undefined; expect(ranges.length).to.be.gte(1); - }); it("queryModelRanges should properly handle models that aren't geometric", async () => { // the below clause is created specifically for the test iModel, if that iModel were to be changed and it contained models that were geometricModels // but not PhysicalModels then the test may fail. let ranges; - let modelProps = await iModel.models.queryProps({ limit: 10, from: "BisCore.Model", where: "ec_classname(ECClassId) <> 'BisCore:PhysicalModel'" }); + let modelProps = await iModel.models.queryProps({ + limit: 10, + from: "BisCore.Model", + where: "ec_classname(ECClassId) <> 'BisCore:PhysicalModel'", + }); let idSet: Id64Set = new Set(); for (const modelProp of modelProps) { idSet.add(modelProp.id!.toString()); @@ -360,7 +374,7 @@ describe("Snapping", () => { let accessToken: AccessToken; let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) diff --git a/full-stack-tests/rpc-interface/src/frontend/Models.test.ts b/full-stack-tests/rpc-interface/src/frontend/Models.test.ts index 94bffc079e39..f6ec45b3c3fb 100644 --- a/full-stack-tests/rpc-interface/src/frontend/Models.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/Models.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; import { ModelProps } from "@itwin/core-common"; import { IModelConnection, SpatialModelState } from "@itwin/core-frontend"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; const expect = chai.expect; @@ -13,7 +13,7 @@ describe("IModel Models", () => { let iModel: IModelConnection; let testContext: TestContext; - before(async function () { + before(async function() { testContext = await TestContext.instance(); if (!testContext.settings.runiModelReadRpcTests) diff --git a/full-stack-tests/rpc-interface/src/frontend/PresentationRpc.test.ts b/full-stack-tests/rpc-interface/src/frontend/PresentationRpc.test.ts index bc9cde0a73a3..93b5ab5c31b2 100644 --- a/full-stack-tests/rpc-interface/src/frontend/PresentationRpc.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/PresentationRpc.test.ts @@ -2,19 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; import { CheckpointConnection, IModelApp, IModelConnection } from "@itwin/core-frontend"; import { TestFrontendAuthorizationClient } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; import { ChildNodeSpecificationTypes, ContentSpecificationTypes, InstanceKey, KeySet, Ruleset, RuleTypes } from "@itwin/presentation-common"; import { Presentation } from "@itwin/presentation-frontend"; +import { expect } from "chai"; import { TestContext } from "./setup/TestContext"; describe("PresentationRpcInterface tests", () => { - let imodel: IModelConnection; - before(async function () { + before(async function() { const testContext = await TestContext.instance(); if (!testContext.settings.runPresentationRpcTests) this.skip(); @@ -164,7 +163,6 @@ describe("PresentationRpcInterface tests", () => { const computedSelections = await Presentation.selection.scopes.computeSelection(imodel, ["0x1"], "element"); expect(computedSelections).to.not.be.undefined; }); - }); const createNodesRuleset = (): Ruleset => ({ diff --git a/full-stack-tests/rpc-interface/src/frontend/Views.test.ts b/full-stack-tests/rpc-interface/src/frontend/Views.test.ts index e2e49d92acdb..82e534f8e78c 100644 --- a/full-stack-tests/rpc-interface/src/frontend/Views.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/Views.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; import { IModelConnection, SpatialViewState, ViewCreator3d } from "@itwin/core-frontend"; +import * as chai from "chai"; import { TestContext } from "./setup/TestContext"; const expect = chai.expect; @@ -12,7 +12,7 @@ describe("IModel Views", () => { let iModel: IModelConnection; let views: IModelConnection.Views; - before(async function () { + before(async function() { // Ensure the singleton is setup const testContext = await TestContext.instance(); diff --git a/full-stack-tests/rpc-interface/src/frontend/setup/IModelSession.ts b/full-stack-tests/rpc-interface/src/frontend/setup/IModelSession.ts index f5ce2669b036..748550aee2d7 100644 --- a/full-stack-tests/rpc-interface/src/frontend/setup/IModelSession.ts +++ b/full-stack-tests/rpc-interface/src/frontend/setup/IModelSession.ts @@ -2,17 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; +import { AccessToken } from "@itwin/core-bentley"; +import { IModelVersion } from "@itwin/core-common"; import { CheckpointConnection, IModelApp } from "@itwin/core-frontend"; +import { AccessTokenAdapter } from "@itwin/imodels-access-frontend"; +import { IModelsClient } from "@itwin/imodels-client-management"; import { ITwin, ITwinsAccessClient, ITwinsAPIResponse, ITwinSubClass } from "@itwin/itwins-client"; +import { expect } from "chai"; import { IModelData } from "../../common/Settings"; -import { IModelVersion } from "@itwin/core-common"; -import { AccessToken } from "@itwin/core-bentley"; -import { IModelsClient } from "@itwin/imodels-client-management"; -import { AccessTokenAdapter } from "@itwin/imodels-access-frontend"; export class IModelSession { - public iTwinId: string; public iModelId: string; public changesetId?: string; @@ -38,7 +37,7 @@ export class IModelSession { throw new Error(`The iModel has no iTwin name, so it cannot get the iTwin.`); const client = new ITwinsAccessClient(); - const iTwinListResponse: ITwinsAPIResponse = await client.queryAsync(requestContext, ITwinSubClass.Project , { + const iTwinListResponse: ITwinsAPIResponse = await client.queryAsync(requestContext, ITwinSubClass.Project, { displayName: iModelData.iTwinName, }); const iTwinList = iTwinListResponse.data; @@ -55,7 +54,7 @@ export class IModelSession { iTwinId = iModelData.iTwinId!; if (iModelData.useName) { - const imodelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels`}}); + const imodelClient = new IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } }); const imodels = imodelClient.iModels.getRepresentationList({ authorization: AccessTokenAdapter.toAuthorizationCallback(await IModelApp.getAccessToken()), urlParams: { @@ -72,7 +71,9 @@ export class IModelSession { } else imodelId = iModelData.id!; - console.log(`Using iModel { name:${iModelData.name}, id:${iModelData.id}, iTwinId:${iModelData.iTwinId}, changesetId:${iModelData.changeSetId} }`); // eslint-disable-line no-console + console.log( + `Using iModel { name:${iModelData.name}, id:${iModelData.id}, iTwinId:${iModelData.iTwinId}, changesetId:${iModelData.changeSetId} }`, + ); // eslint-disable-line no-console return new IModelSession(iTwinId, imodelId, iModelData.changeSetId); } diff --git a/full-stack-tests/rpc-interface/src/frontend/setup/TestContext.ts b/full-stack-tests/rpc-interface/src/frontend/setup/TestContext.ts index 903d4822c09e..0c343eb31ec4 100644 --- a/full-stack-tests/rpc-interface/src/frontend/setup/TestContext.ts +++ b/full-stack-tests/rpc-interface/src/frontend/setup/TestContext.ts @@ -3,15 +3,18 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { AccessToken, Logger, LogLevel } from "@itwin/core-bentley"; import { BentleyCloudRpcManager, OpenAPIInfo } from "@itwin/core-common"; import { NoRenderApp } from "@itwin/core-frontend"; -import { - getAccessTokenFromBackend, TestBrowserAuthorizationClientConfiguration, TestFrontendAuthorizationClient, TestUserCredentials, -} from "@itwin/oidc-signin-tool/lib/cjs/frontend"; import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; import { IModelsClient } from "@itwin/imodels-client-management"; +import { + getAccessTokenFromBackend, + TestBrowserAuthorizationClientConfiguration, + TestFrontendAuthorizationClient, + TestUserCredentials, +} from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import { expect } from "chai"; import { getRpcInterfaces, Settings } from "../../common/Settings"; import { getClientAccessTokenFromBackend, getProcessEnvFromBackend } from "../../common/SideChannels"; import { IModelSession } from "./IModelSession"; @@ -52,8 +55,14 @@ export class TestContext { } private async initialize() { - expect(this.settings.users.length).to.be.gte(1, `Unexpected number of users found in settings - got ${this.settings.users.length}, expected at least 2`); - expect(this.settings.iModels.length).to.be.gte(1, `Unexpected number of iModels found in settings - got ${this.settings.iModels.length}, expected at least 1`); + expect(this.settings.users.length).to.be.gte( + 1, + `Unexpected number of users found in settings - got ${this.settings.users.length}, expected at least 2`, + ); + expect(this.settings.iModels.length).to.be.gte( + 1, + `Unexpected number of iModels found in settings - got ${this.settings.iModels.length}, expected at least 1`, + ); // Print out the configuration console.log(this.settings.toString()); diff --git a/full-stack-tests/rpc-interface/src/frontend/workflows/BasicScenarios.test.ts b/full-stack-tests/rpc-interface/src/frontend/workflows/BasicScenarios.test.ts index c16702912dfc..1ec60b428671 100644 --- a/full-stack-tests/rpc-interface/src/frontend/workflows/BasicScenarios.test.ts +++ b/full-stack-tests/rpc-interface/src/frontend/workflows/BasicScenarios.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as chai from "chai"; -import * as chaiAsPromised from "chai-as-promised"; import { QueryRowFormat } from "@itwin/core-common"; import { CheckpointConnection, IModelApp } from "@itwin/core-frontend"; import { TestFrontendAuthorizationClient } from "@itwin/oidc-signin-tool/lib/cjs/frontend"; +import * as chai from "chai"; +import * as chaiAsPromised from "chai-as-promised"; import { TestContext } from "../setup/TestContext"; const expect = chai.expect; @@ -45,10 +45,14 @@ describe("Basic Scenarios", async () => { const iModel = await testContext.iModelWithChangesets!.getConnection(); const rows = []; - for await (const row of iModel.createQueryReader("SELECT ECInstanceId AS id FROM BisCore.Element", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames, limit: { count: 10 } })) + for await ( + const row of iModel.createQueryReader("SELECT ECInstanceId AS id FROM BisCore.Element", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + limit: { count: 10 }, + }) + ) rows.push(row); expect(rows).not.to.be.empty; }); - }); diff --git a/full-stack-tests/rpc-interface/src/test/backend.ts b/full-stack-tests/rpc-interface/src/test/backend.ts index 00003f7c766e..54cbe01c3186 100644 --- a/full-stack-tests/rpc-interface/src/test/backend.ts +++ b/full-stack-tests/rpc-interface/src/test/backend.ts @@ -5,15 +5,15 @@ // Sets up a local backend to be used for testing within the iTwin.js Core repo. -import * as path from "path"; -import { IModelJsExpressServer } from "@itwin/express-server"; import { IModelHost } from "@itwin/core-backend"; import { BentleyCloudRpcManager, RpcConfiguration } from "@itwin/core-common"; -import { Presentation as PresentationBackend } from "@itwin/presentation-backend"; +import { IModelJsExpressServer } from "@itwin/express-server"; import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; import { IModelsClient } from "@itwin/imodels-client-authoring"; -import { getRpcInterfaces, Settings } from "../common/Settings"; +import { Presentation as PresentationBackend } from "@itwin/presentation-backend"; import * as fs from "fs"; +import * as path from "path"; +import { getRpcInterfaces, Settings } from "../common/Settings"; /** Loads the provided `.env` file into process.env */ function loadEnv(envFile: string) { diff --git a/full-stack-tests/rpc-interface/webpack.config.js b/full-stack-tests/rpc-interface/webpack.config.js index b21b5470dc86..722a7aeb200b 100644 --- a/full-stack-tests/rpc-interface/webpack.config.js +++ b/full-stack-tests/rpc-interface/webpack.config.js @@ -48,7 +48,7 @@ module.exports = { plugins: [ new webpack.DefinePlugin({ PACKAGE_VERSION: JSON.stringify( - require(path.join(__dirname, "package.json")).version + require(path.join(__dirname, "package.json")).version, ), }), ], diff --git a/full-stack-tests/rpc/certa.json b/full-stack-tests/rpc/certa.json index 71059305cf94..4879bcc7fb69 100644 --- a/full-stack-tests/rpc/certa.json +++ b/full-stack-tests/rpc/certa.json @@ -17,4 +17,4 @@ "mochaFile": "lib/test/junit_results.xml" } } -} \ No newline at end of file +} diff --git a/full-stack-tests/rpc/eslint.config.js b/full-stack-tests/rpc/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/full-stack-tests/rpc/eslint.config.js +++ b/full-stack-tests/rpc/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/full-stack-tests/rpc/src/backend/CommonBackendSetup.ts b/full-stack-tests/rpc/src/backend/CommonBackendSetup.ts index fce8d301dc58..b99058a4a702 100644 --- a/full-stack-tests/rpc/src/backend/CommonBackendSetup.ts +++ b/full-stack-tests/rpc/src/backend/CommonBackendSetup.ts @@ -2,15 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Logger, ProcessDetector } from "@itwin/core-bentley"; import { registerBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; -import { ElectronHost } from "@itwin/core-electron/lib/cjs/ElectronBackend"; import { IModelHost } from "@itwin/core-backend"; +import { Logger, ProcessDetector } from "@itwin/core-bentley"; import { IModelReadRpcInterface, RpcConfiguration } from "@itwin/core-common"; +import { ElectronHost } from "@itwin/core-electron/lib/cjs/ElectronBackend"; +import { join } from "path"; import { BackendTestCallbacks } from "../common/SideChannels"; import { rpcInterfaces } from "../common/TestRpcInterface"; import { resetOp8Initializer, TestRpcImpl2 } from "./TestRpcImpl"; -import { join } from "path"; export async function commonSetup(): Promise { RpcConfiguration.developmentMode = true; diff --git a/full-stack-tests/rpc/src/backend/TestRpcImpl.ts b/full-stack-tests/rpc/src/backend/TestRpcImpl.ts index 6c3c80e00a54..f1e6aa7a62c4 100644 --- a/full-stack-tests/rpc/src/backend/TestRpcImpl.ts +++ b/full-stack-tests/rpc/src/backend/TestRpcImpl.ts @@ -4,11 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import { BentleyError, BentleyStatus, Id64String } from "@itwin/core-bentley"; import { - IModelRpcProps, NoContentError, RpcInterface, RpcInvocation, RpcManager, RpcOperationsProfile, RpcPendingResponse, RpcRequest, + IModelRpcProps, + NoContentError, + RpcInterface, + RpcInvocation, + RpcManager, + RpcOperationsProfile, + RpcPendingResponse, + RpcRequest, } from "@itwin/core-common"; import { - AttachedInterface, MobileTestInterface, MultipleClientsInterface, RpcTransportTestImpl, TestNotFoundResponse, TestNotFoundResponseCode, - TestOp1Params, TestRpcInterface, TestRpcInterface2, TestRpcInterface3, TokenValues, WebRoutingInterface, ZeroMajorRpcInterface, + AttachedInterface, + MobileTestInterface, + MultipleClientsInterface, + RpcTransportTestImpl, + TestNotFoundResponse, + TestNotFoundResponseCode, + TestOp1Params, + TestRpcInterface, + TestRpcInterface2, + TestRpcInterface3, + TokenValues, + WebRoutingInterface, + ZeroMajorRpcInterface, } from "../common/TestRpcInterface"; /* eslint-disable deprecation/deprecation */ diff --git a/full-stack-tests/rpc/src/backend/electron.ts b/full-stack-tests/rpc/src/backend/electron.ts index 73a1872e2862..8a849516a0b6 100644 --- a/full-stack-tests/rpc/src/backend/electron.ts +++ b/full-stack-tests/rpc/src/backend/electron.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { registerBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; +import { ElectronHost } from "@itwin/core-electron/lib/cjs/ElectronBackend"; import { BackendTestCallbacks } from "../common/SideChannels"; import { commonSetup } from "./CommonBackendSetup"; -import { ElectronHost } from "@itwin/core-electron/lib/cjs/ElectronBackend"; import { setupIpcTestElectron } from "./ipc"; async function init() { diff --git a/full-stack-tests/rpc/src/backend/ipc.ts b/full-stack-tests/rpc/src/backend/ipc.ts index a78302e4af98..205921618b90 100644 --- a/full-stack-tests/rpc/src/backend/ipc.ts +++ b/full-stack-tests/rpc/src/backend/ipc.ts @@ -26,7 +26,7 @@ export function setupIpcTestElectron() { orderTest(require("electron").ipcMain); // eslint-disable-line @typescript-eslint/no-var-requires } -export async function setupIpcTest(before = async () => { }, socketOverride?: IpcWebSocketBackend) { +export async function setupIpcTest(before = async () => {}, socketOverride?: IpcWebSocketBackend) { let socket: IpcWebSocketBackend; let ready: () => void; const started = new Promise((resolve) => ready = resolve); diff --git a/full-stack-tests/rpc/src/common/SideChannels.ts b/full-stack-tests/rpc/src/common/SideChannels.ts index fe31eb96f8a4..d02adbbe7903 100644 --- a/full-stack-tests/rpc/src/common/SideChannels.ts +++ b/full-stack-tests/rpc/src/common/SideChannels.ts @@ -13,5 +13,5 @@ export enum BackendTestCallbacks { setChunkThreshold = "setChunkThreshold", // Only registered for electron! startIpcTest = "startIpcTest", startMockMobileTest = "startMockMobileTest", - sendIpcMessage = "sendIpcMessage" + sendIpcMessage = "sendIpcMessage", } diff --git a/full-stack-tests/rpc/src/common/TestRpcInterface.ts b/full-stack-tests/rpc/src/common/TestRpcInterface.ts index e0c262f005de..05b715e27828 100644 --- a/full-stack-tests/rpc/src/common/TestRpcInterface.ts +++ b/full-stack-tests/rpc/src/common/TestRpcInterface.ts @@ -4,8 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { Id64String } from "@itwin/core-bentley"; import { - IModelReadRpcInterface, IModelRpcProps, RpcInterface, RpcInterfaceDefinition, RpcManager, RpcNotFoundResponse, RpcOperation, RpcOperationsProfile, - RpcPushChannel, RpcResponseCacheControl, RpcRoutingToken, WipRpcInterface, + IModelReadRpcInterface, + IModelRpcProps, + RpcInterface, + RpcInterfaceDefinition, + RpcManager, + RpcNotFoundResponse, + RpcOperation, + RpcOperationsProfile, + RpcPushChannel, + RpcResponseCacheControl, + RpcRoutingToken, + WipRpcInterface, } from "@itwin/core-common"; /* eslint-disable deprecation/deprecation */ @@ -47,7 +57,7 @@ export abstract class ZeroMajorRpcInterface extends RpcInterface { } // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface TokenValues extends IModelRpcProps { } +export interface TokenValues extends IModelRpcProps {} export abstract class TestRpcInterface extends RpcInterface { public static readonly OP8_INITIALIZER = 5; @@ -184,11 +194,23 @@ export abstract class RpcTransportTest extends RpcInterface { public static readonly interfaceName = "RpcTransportTest"; public static interfaceVersion = "1.0.0"; - public static getClient(): RpcTransportTest { return RpcManager.getClientForInterface(RpcTransportTest); } - public async primitive(_value: string): Promise { return this.forward(arguments); } - public async binary(_value: Uint8Array): Promise { return this.forward(arguments); } - public async mixed(_value1: string, _value2: Uint8Array): Promise<{ 0: string, 1: Uint8Array }> { return this.forward(arguments); } - public async nested(_value: { a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }): Promise<{ a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }> { return this.forward(arguments); } + public static getClient(): RpcTransportTest { + return RpcManager.getClientForInterface(RpcTransportTest); + } + public async primitive(_value: string): Promise { + return this.forward(arguments); + } + public async binary(_value: Uint8Array): Promise { + return this.forward(arguments); + } + public async mixed(_value1: string, _value2: Uint8Array): Promise<{ 0: string, 1: Uint8Array }> { + return this.forward(arguments); + } + public async nested( + _value: { a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }, + ): Promise<{ a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }> { + return this.forward(arguments); + } } export class RpcTransportTestImpl extends RpcInterface implements RpcTransportTest { @@ -222,7 +244,9 @@ export class RpcTransportTestImpl extends RpcInterface implements RpcTransportTe return { 0: RpcTransportTestImpl.mutateString(value1), 1: RpcTransportTestImpl.mutateBits(value2) }; } - public async nested(value: { a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }): Promise<{ a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }> { + public async nested( + value: { a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }, + ): Promise<{ a: { x: Uint8Array, y: number }, b: string, c: Uint8Array }> { return { a: { x: RpcTransportTestImpl.mutateBits(value.a.x), diff --git a/full-stack-tests/rpc/src/frontend/Ipc.test.ts b/full-stack-tests/rpc/src/frontend/Ipc.test.ts index 09f942258da9..a91a5f26bbe6 100644 --- a/full-stack-tests/rpc/src/frontend/Ipc.test.ts +++ b/full-stack-tests/rpc/src/frontend/Ipc.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { executeBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; import { ProcessDetector } from "@itwin/core-bentley"; import { IpcWebSocketFrontend } from "@itwin/core-common"; -import { executeBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; import { assert } from "chai"; import { BackendTestCallbacks } from "../common/SideChannels"; diff --git a/full-stack-tests/rpc/src/frontend/Routing.test.ts b/full-stack-tests/rpc/src/frontend/Routing.test.ts index e770cb3303d9..56dfdfd3f183 100644 --- a/full-stack-tests/rpc/src/frontend/Routing.test.ts +++ b/full-stack-tests/rpc/src/frontend/Routing.test.ts @@ -4,13 +4,12 @@ import { assert } from "chai"; * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { ProcessDetector } from "@itwin/core-bentley"; -import { TestRpcInterface, WebRoutingInterface } from "../common/TestRpcInterface"; import { BentleyCloudRpcProtocol, RpcProtocol, RpcProtocolVersion, WebAppRpcProtocol, WebAppRpcRequest } from "@itwin/core-common"; +import { TestRpcInterface, WebRoutingInterface } from "../common/TestRpcInterface"; import { currentEnvironment } from "./_Setup.test"; if (!ProcessDetector.isElectronAppFrontend) { describe("Web Routing", () => { - it("should always send and recieve protocolVersion without prefectch", async () => { if (currentEnvironment === "websocket") { return; @@ -54,19 +53,24 @@ if (!ProcessDetector.isElectronAppFrontend) { const testParamsWithSuffix = async (suffix: string) => { const realParams = btoa(JSON.stringify([1, 10])); // eslint-disable-line deprecation/deprecation - assert.equal(realParams.indexOf("="), -1); // we don't want any padding in the real base64 value + assert.equal(realParams.indexOf("="), -1); // we don't want any padding in the real base64 value - const response = await fetch(`${protocol.pathPrefix}/${protocol.info.title}/${protocol.info.version}/mode/1/context/undefined/imodel/undefined/changeset/0/${TestRpcInterface.interfaceName}-${TestRpcInterface.interfaceVersion}-op1?parameters=${encodeURIComponent(realParams)}${suffix}`, { - method: "GET", - headers: { - "accept": "*/*", - "content-type": "text/plain", - [protocol.protocolVersionHeaderName]: String(RpcProtocolVersion.IntroducedStatusCategory), - [protocol.serializedClientRequestContextHeaderNames.id]: "foo", + const response = await fetch( + `${protocol.pathPrefix}/${protocol.info.title}/${protocol.info.version}/mode/1/context/undefined/imodel/undefined/changeset/0/${TestRpcInterface.interfaceName}-${TestRpcInterface.interfaceVersion}-op1?parameters=${ + encodeURIComponent(realParams) + }${suffix}`, + { + method: "GET", + headers: { + "accept": "*/*", + "content-type": "text/plain", + [protocol.protocolVersionHeaderName]: String(RpcProtocolVersion.IntroducedStatusCategory), + [protocol.serializedClientRequestContextHeaderNames.id]: "foo", + }, }, - }); + ); assert.equal(response.status, 400); - const result = (await (response.json())); + const result = await (response.json()); assert.isTrue(result.isError); assert.equal(result.message, "Error: Invalid request: Malformed URL parameters detected."); }; @@ -81,16 +85,21 @@ if (!ProcessDetector.isElectronAppFrontend) { const protocol = TestRpcInterface.getClient().configuration.protocol as BentleyCloudRpcProtocol; const realParams = btoa(JSON.stringify([1, 10])); // eslint-disable-line deprecation/deprecation - const response = await fetch(`${protocol.pathPrefix}/${protocol.info.title}/${protocol.info.version}/mode/1/context/undefined/imodel/undefined/changeset/0/${TestRpcInterface.interfaceName}-${TestRpcInterface.interfaceVersion}-op1?parameters=${encodeURIComponent(realParams)}`, { - method: "GET", - headers: { - "accept": "*/*", - "content-type": "text/plain", - [protocol.protocolVersionHeaderName]: String(RpcProtocolVersion.IntroducedStatusCategory), + const response = await fetch( + `${protocol.pathPrefix}/${protocol.info.title}/${protocol.info.version}/mode/1/context/undefined/imodel/undefined/changeset/0/${TestRpcInterface.interfaceName}-${TestRpcInterface.interfaceVersion}-op1?parameters=${ + encodeURIComponent(realParams) + }`, + { + method: "GET", + headers: { + "accept": "*/*", + "content-type": "text/plain", + [protocol.protocolVersionHeaderName]: String(RpcProtocolVersion.IntroducedStatusCategory), + }, }, - }); + ); assert.equal(response.status, 400); - const result = (await (response.json())); + const result = await (response.json()); assert.isTrue(result.isError); assert.equal(result.message, "Error: Invalid request: Missing required activity ID."); }); diff --git a/full-stack-tests/rpc/src/frontend/Rpc.ElectronProtocol.test.ts b/full-stack-tests/rpc/src/frontend/Rpc.ElectronProtocol.test.ts index a0ed1c0a3695..70a0e9e394c5 100644 --- a/full-stack-tests/rpc/src/frontend/Rpc.ElectronProtocol.test.ts +++ b/full-stack-tests/rpc/src/frontend/Rpc.ElectronProtocol.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { executeBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; +import { ProcessDetector } from "@itwin/core-bentley"; import { RpcProtocolEvent, RpcRequest } from "@itwin/core-common"; +import { assert } from "chai"; import { BackendTestCallbacks } from "../common/SideChannels"; import { TestRpcInterface3 } from "../common/TestRpcInterface"; -import { ProcessDetector } from "@itwin/core-bentley"; // N.B.: These tests only run in electron! if (ProcessDetector.isElectronAppFrontend) { @@ -32,10 +32,12 @@ if (ProcessDetector.isElectronAppFrontend) { const response = await client.op1(1); assert.equal(response, 1); - return new Promise((resolve, reject) => setTimeout(() => { - removeListener(); - (received === 1) ? resolve() : reject(new Error(`Received ${received} responses for 1 request`)); - }, 2000)); + return new Promise((resolve, reject) => + setTimeout(() => { + removeListener(); + (received === 1) ? resolve() : reject(new Error(`Received ${received} responses for 1 request`)); + }, 2000) + ); }); it("should chunk data larger than 64mb", async () => { diff --git a/full-stack-tests/rpc/src/frontend/Rpc.HttpProtocol.test.ts b/full-stack-tests/rpc/src/frontend/Rpc.HttpProtocol.test.ts index 2c0255d529c2..48644efe400e 100644 --- a/full-stack-tests/rpc/src/frontend/Rpc.HttpProtocol.test.ts +++ b/full-stack-tests/rpc/src/frontend/Rpc.HttpProtocol.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { assert } from "chai"; import { RpcOperation, RpcRequest, RpcRequestEvent, ServerError, ServerTimeoutError } from "@itwin/core-common"; +import { assert } from "chai"; import { TestOp1Params, TestRpcInterface } from "../common/TestRpcInterface"; if (false) { diff --git a/full-stack-tests/rpc/src/frontend/RpcInterface.test.ts b/full-stack-tests/rpc/src/frontend/RpcInterface.test.ts index dc0899f72a4c..37a1e850e18c 100644 --- a/full-stack-tests/rpc/src/frontend/RpcInterface.test.ts +++ b/full-stack-tests/rpc/src/frontend/RpcInterface.test.ts @@ -2,20 +2,46 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Buffer } from "buffer"; -import { assert } from "chai"; -import * as semver from "semver"; -import { BentleyError, ProcessDetector } from "@itwin/core-bentley"; import { executeBackendCallback } from "@itwin/certa/lib/utils/CallbackUtils"; +import { BentleyError, ProcessDetector } from "@itwin/core-bentley"; import { - ChangesetIdWithIndex, IModelReadRpcInterface, IModelRpcProps, NoContentError, RpcConfiguration, RpcInterface, RpcInterfaceDefinition, RpcManager, - RpcOperation, RpcOperationPolicy, RpcProtocol, RpcProtocolEvent, RpcRequest, RpcRequestEvent, RpcRequestStatus, RpcResponseCacheControl, RpcSerializedValue, - SerializedRpcActivity, WebAppRpcRequest, WipRpcInterface, + ChangesetIdWithIndex, + IModelReadRpcInterface, + IModelRpcProps, + NoContentError, + RpcConfiguration, + RpcInterface, + RpcInterfaceDefinition, + RpcManager, + RpcOperation, + RpcOperationPolicy, + RpcProtocol, + RpcProtocolEvent, + RpcRequest, + RpcRequestEvent, + RpcRequestStatus, + RpcResponseCacheControl, + RpcSerializedValue, + SerializedRpcActivity, + WebAppRpcRequest, + WipRpcInterface, } from "@itwin/core-common"; +import { Buffer } from "buffer"; +import { assert } from "chai"; +import * as semver from "semver"; import { BackendTestCallbacks } from "../common/SideChannels"; import { - AttachedInterface, MultipleClientsInterface, RpcTransportTest, RpcTransportTestImpl, TestNotFoundResponse, TestNotFoundResponseCode, TestOp1Params, - TestRpcInterface, TestRpcInterface2, TokenValues, ZeroMajorRpcInterface, + AttachedInterface, + MultipleClientsInterface, + RpcTransportTest, + RpcTransportTestImpl, + TestNotFoundResponse, + TestNotFoundResponseCode, + TestOp1Params, + TestRpcInterface, + TestRpcInterface2, + TokenValues, + ZeroMajorRpcInterface, } from "../common/TestRpcInterface"; import { currentEnvironment } from "./_Setup.test"; @@ -30,13 +56,20 @@ describe("RpcInterface", () => { class LocalInterface extends RpcInterface { public static readonly interfaceName = "LocalInterface"; public static interfaceVersion = "0.0.0"; - public async op(): Promise { return this.forward(arguments); } + public async op(): Promise { + return this.forward(arguments); + } } const initializeLocalInterface = () => { - RpcManager.registerImpl(LocalInterface, class extends RpcInterface { - public async op(): Promise { return undefined as any; } - }); + RpcManager.registerImpl( + LocalInterface, + class extends RpcInterface { + public async op(): Promise { + return undefined as any; + } + }, + ); RpcManager.initializeInterface(LocalInterface); }; @@ -237,11 +270,15 @@ describe("RpcInterface", () => { const simulateIncompatible = () => { const interfaces: string[] = []; ((controlChannel as any)._configuration as RpcConfiguration).interfaces().forEach((definition) => { - interfaces.push(definition.interfaceName === "IModelReadRpcInterface" ? `${definition.interfaceName}@0.0.0` : `${definition.interfaceName}@${definition.interfaceVersion}`); + interfaces.push( + definition.interfaceName === "IModelReadRpcInterface" + ? `${definition.interfaceName}@0.0.0` + : `${definition.interfaceName}@${definition.interfaceVersion}`, + ); }); const id = interfaces.sort().join(","); - if (typeof (btoa) !== "undefined") // eslint-disable-line deprecation/deprecation + if (typeof btoa !== "undefined") // eslint-disable-line deprecation/deprecation return btoa(id); // eslint-disable-line deprecation/deprecation return Buffer.from(id, "binary").toString("base64"); }; @@ -264,7 +301,7 @@ describe("RpcInterface", () => { assert.isFalse(endpointsMismatch[0].compatible); removeListener(); - controlPolicy.sentCallback = () => { }; + controlPolicy.sentCallback = () => {}; Object.defineProperty(controlInterface, "interfaceName", { value: originalName }); assert(await executeBackendCallback(BackendTestCallbacks.restoreIncompatibleInterfaceVersion)); @@ -481,7 +518,7 @@ describe("RpcInterface", () => { assert.isTrue((request as any)._request.method === "get", "Expected request to be a get request!"); }); - it("should set cache-control headers when applicable", async function () { + it("should set cache-control headers when applicable", async function() { if (currentEnvironment === "websocket") { return this.skip(); } @@ -566,17 +603,19 @@ describe("RpcInterface", () => { class TestInterface extends RpcInterface { public static interfaceName = "TestInterface"; public static interfaceVersion = "0.0.0"; - public req1() { } - public req2() { } - public req3() { } + public req1() {} + public req2() {} + public req3() {} } RpcManager.initializeInterface(TestInterface); class Resolver { public promise: Promise; - public resolve() { } - constructor(private _value: () => T) { this.promise = new Promise((callback, _) => this.resolve = () => callback(this._value())); } + public resolve() {} + constructor(private _value: () => T) { + this.promise = new Promise((callback, _) => this.resolve = () => callback(this._value())); + } } const backend: Map> = new Map(); @@ -586,7 +625,7 @@ describe("RpcInterface", () => { let completed = 0; class TestRequest extends RpcRequest { - protected setHeader(_name: string, _value: string): void { } + protected setHeader(_name: string, _value: string): void {} protected async send(): Promise { assert.isFalse(backend.has(this.id)); diff --git a/full-stack-tests/rpc/tsconfig.json b/full-stack-tests/rpc/tsconfig.json index fa9e0c9b95db..fb9e4848b8e8 100644 --- a/full-stack-tests/rpc/tsconfig.json +++ b/full-stack-tests/rpc/tsconfig.json @@ -6,4 +6,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/full-stack-tests/rpc/webpack.config.js b/full-stack-tests/rpc/webpack.config.js index f2e50bf98309..88d5076f92ec 100644 --- a/full-stack-tests/rpc/webpack.config.js +++ b/full-stack-tests/rpc/webpack.config.js @@ -68,4 +68,3 @@ module.exports = { }, }, }; - diff --git a/package.json b/package.json index ca548d5c84af..98212f0ac8d4 100644 --- a/package.json +++ b/package.json @@ -30,4 +30,4 @@ }, "//dependencies": "NOTE: dependencies will be empty here and instead specified in each package.", "//devDependencies": "NOTE: devDependencies will be empty here and instead specified in each package." -} \ No newline at end of file +} diff --git a/presentation/.mocharc.json b/presentation/.mocharc.json index 7abbc1d20d18..e64ccc7d70b1 100644 --- a/presentation/.mocharc.json +++ b/presentation/.mocharc.json @@ -17,4 +17,4 @@ "reporterOptions": [ "mochaFile=lib/test/junit_results.xml" ] -} \ No newline at end of file +} diff --git a/presentation/backend/src/presentation-backend/ElementPropertiesHelper.ts b/presentation/backend/src/presentation-backend/ElementPropertiesHelper.ts index 3348aff6f8d6..729af911c173 100644 --- a/presentation/backend/src/presentation-backend/ElementPropertiesHelper.ts +++ b/presentation/backend/src/presentation-backend/ElementPropertiesHelper.ts @@ -6,10 +6,10 @@ * @module Core */ -import { from, mergeAll, mergeMap, Observable, reduce } from "rxjs"; import { ECSqlStatement, IModelDb } from "@itwin/core-backend"; import { DbResult, Id64String } from "@itwin/core-bentley"; import { PresentationError, PresentationStatus } from "@itwin/presentation-common"; +import { from, mergeAll, mergeMap, Observable, reduce } from "rxjs"; /** @internal */ export function getElementsCount(db: IModelDb, classNames?: string[]) { @@ -63,7 +63,7 @@ export async function getBatchedClassElementIds( imodel: IModelDb, fullClassName: string, batchSize: number, -): Promise> { +): Promise> { const batches = []; const reader = imodel.createQueryReader(`SELECT ECInstanceId id FROM ${getECSqlName(fullClassName)} ORDER BY ECInstanceId`); let currId: Id64String | undefined; diff --git a/presentation/backend/src/presentation-backend/NativePlatform.ts b/presentation/backend/src/presentation-backend/NativePlatform.ts index 8e32d79e2c80..4beed3b62032 100644 --- a/presentation/backend/src/presentation-backend/NativePlatform.ts +++ b/presentation/backend/src/presentation-backend/NativePlatform.ts @@ -128,7 +128,7 @@ function getPresentationStatusFromNativeResponseStatus(nativeResponseStatus: IMo } /** @internal */ -export const createDefaultNativePlatform = (props: DefaultNativePlatformProps): new () => NativePlatformDefinition => { +export const createDefaultNativePlatform = (props: DefaultNativePlatformProps): new() => NativePlatformDefinition => { // note the implementation is constructed here to make PresentationManager // usable without loading the actual addon (if addon is set to something other) return class implements NativePlatformDefinition { diff --git a/presentation/backend/src/presentation-backend/Presentation.ts b/presentation/backend/src/presentation-backend/Presentation.ts index c6e315c78e8f..82598feb6f7f 100644 --- a/presentation/backend/src/presentation-backend/Presentation.ts +++ b/presentation/backend/src/presentation-backend/Presentation.ts @@ -175,10 +175,9 @@ export class Presentation { } private static createClientManager(clientId: string, onManagerUsed: () => void): ClientStoreItem { - const manager = - Presentation._initProps && Presentation._initProps.clientManagerFactory - ? Presentation._initProps.clientManagerFactory(clientId, Presentation._initProps) - : new PresentationManager({ ...Presentation._initProps, id: clientId }); + const manager = Presentation._initProps && Presentation._initProps.clientManagerFactory + ? Presentation._initProps.clientManagerFactory(clientId, Presentation._initProps) + : new PresentationManager({ ...Presentation._initProps, id: clientId }); manager.setOnManagerUsedHandler(onManagerUsed); Logger.logInfo( PresentationBackendLoggerCategory.PresentationManager, diff --git a/presentation/backend/src/presentation-backend/PresentationManager.ts b/presentation/backend/src/presentation-backend/PresentationManager.ts index 2dac78747302..14386d83744e 100644 --- a/presentation/backend/src/presentation-backend/PresentationManager.ts +++ b/presentation/backend/src/presentation-backend/PresentationManager.ts @@ -6,15 +6,12 @@ * @module Core */ -import { forkJoin, from, map, mergeMap, of } from "rxjs"; -import { eachValueFrom } from "rxjs-for-await"; import { IModelDb } from "@itwin/core-backend"; import { Id64String } from "@itwin/core-bentley"; import { UnitSystemKey } from "@itwin/core-quantity"; import { SchemaContext } from "@itwin/ecschema-metadata"; import { buildElementProperties, - UnitSystemFormat as CommonUnitSystemFormat, ComputeSelectionRequestOptions, Content, ContentDescriptorRequestOptions, @@ -62,8 +59,11 @@ import { SelectionScope, SelectionScopeRequestOptions, SingleElementPropertiesRequestOptions, + UnitSystemFormat as CommonUnitSystemFormat, WithCancelEvent, } from "@itwin/presentation-common"; +import { forkJoin, from, map, mergeMap, of } from "rxjs"; +import { eachValueFrom } from "rxjs-for-await"; import { getBatchedClassElementIds, getClassesWithInstances, getElementsCount, parseFullClassName } from "./ElementPropertiesHelper"; import { NativePlatformDefinition, NativePlatformRequestTypes } from "./NativePlatform"; import { getRulesetIdObject, PresentationManagerDetail } from "./PresentationManagerDetail"; @@ -520,7 +520,9 @@ export class PresentationManager { * @public */ public async getNodesDescriptor( - requestOptions: WithCancelEvent>> & BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { const response = await this._detail.getNodesDescriptor(requestOptions); const descriptor = Descriptor.fromJSON(JSON.parse(response)); @@ -533,7 +535,9 @@ export class PresentationManager { * @public */ public async getNodePaths( - requestOptions: WithCancelEvent>> & BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { const result = await this._detail.getNodePaths(requestOptions); return result.map((npe) => this._localizationHelper.getLocalizedNodePathElement(npe)); @@ -579,8 +583,9 @@ export class PresentationManager { * @public */ public async getContentSetSize( - requestOptions: WithCancelEvent>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { return this._detail.getContentSetSize(requestOptions); } @@ -590,7 +595,9 @@ export class PresentationManager { * @public */ public async getContentSet( - requestOptions: WithCancelEvent>>> & BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>>> + & BackendDiagnosticsAttribute, ): Promise { let items = await this._detail.getContentSet({ ...requestOptions, @@ -614,8 +621,9 @@ export class PresentationManager { * @public */ public async getContent( - requestOptions: WithCancelEvent>>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>>> + & BackendDiagnosticsAttribute, ): Promise { const content = await this._detail.getContent({ ...requestOptions, @@ -645,8 +653,9 @@ export class PresentationManager { * @public */ public async getPagedDistinctValues( - requestOptions: WithCancelEvent>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise> { const result = await this._detail.getPagedDistinctValues(requestOptions); return { @@ -672,10 +681,11 @@ export class PresentationManager { requestOptions: WithCancelEvent>> & BackendDiagnosticsAttribute, ): Promise>; public async getElementProperties( - requestOptions: WithCancelEvent< - Prioritized | MultiElementPropertiesRequestOptions> - > & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent< + Prioritized | MultiElementPropertiesRequestOptions> + > + & BackendDiagnosticsAttribute, ): Promise> { if (isSingleElementPropertiesRequestOptions(requestOptions)) { return this.getSingleElementProperties(requestOptions); @@ -841,7 +851,7 @@ export class PresentationManager { * @deprecated in 3.x. Use overload with `ComputeSelectionRequestOptions` parameter. */ public async computeSelection( - requestOptions: SelectionScopeRequestOptions & { ids: Id64String[]; scopeId: string } & BackendDiagnosticsAttribute, + requestOptions: SelectionScopeRequestOptions & { ids: Id64String[], scopeId: string } & BackendDiagnosticsAttribute, ): Promise; /** * Computes selection based on provided element IDs and selection scope. @@ -850,16 +860,17 @@ export class PresentationManager { // eslint-disable-next-line @typescript-eslint/unified-signatures public async computeSelection(requestOptions: ComputeSelectionRequestOptions & BackendDiagnosticsAttribute): Promise; public async computeSelection( - requestOptions: ((SelectionScopeRequestOptions & { ids: Id64String[]; scopeId: string }) | ComputeSelectionRequestOptions) & - BackendDiagnosticsAttribute, + requestOptions: + & ((SelectionScopeRequestOptions & { ids: Id64String[], scopeId: string }) | ComputeSelectionRequestOptions) + & BackendDiagnosticsAttribute, ): Promise { return SelectionScopesHelper.computeSelection( isComputeSelectionRequestOptions(requestOptions) ? requestOptions - : (function () { - const { ids, scopeId, ...rest } = requestOptions; - return { ...rest, elementIds: ids, scope: { id: scopeId } }; - })(), + : (function() { + const { ids, scopeId, ...rest } = requestOptions; + return { ...rest, elementIds: ids, scope: { id: scopeId } }; + })(), ); } diff --git a/presentation/backend/src/presentation-backend/PresentationManagerDetail.ts b/presentation/backend/src/presentation-backend/PresentationManagerDetail.ts index da9f4a40c2a2..2b0f48a69947 100644 --- a/presentation/backend/src/presentation-backend/PresentationManagerDetail.ts +++ b/presentation/backend/src/presentation-backend/PresentationManagerDetail.ts @@ -2,8 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as hash from "object-hash"; -import * as path from "path"; import { IModelDb, IModelJsNative, IpcHost } from "@itwin/core-backend"; import { BeEvent, IDisposable, Logger } from "@itwin/core-bentley"; import { UnitSystemKey } from "@itwin/core-quantity"; @@ -46,6 +44,8 @@ import { UpdateInfo, WithCancelEvent, } from "@itwin/presentation-common"; +import * as hash from "object-hash"; +import * as path from "path"; import { PresentationBackendLoggerCategory } from "./BackendLoggerCategory"; import { createDefaultNativePlatform, @@ -74,8 +74,7 @@ export class PresentationManagerDetail implements IDisposable { constructor(params: PresentationManagerProps) { this._disposed = false; - this._nativePlatform = - params.addon ?? + this._nativePlatform = params.addon ?? createNativePlatform( params.id ?? "", params.workerThreadsCount ?? 2, @@ -143,7 +142,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getNodesDescriptor( - requestOptions: WithCancelEvent>> & BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { const { rulesetOrId, parentKey, ...strippedOptions } = requestOptions; const params = { @@ -156,7 +157,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getNodePaths( - requestOptions: WithCancelEvent>> & BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { const { rulesetOrId, instancePaths, ...strippedOptions } = requestOptions; const params = { @@ -180,7 +183,9 @@ export class PresentationManagerDetail implements IDisposable { return JSON.parse(await this.request(params), NodePathElement.listReviver); } - public async getContentDescriptor(requestOptions: WithCancelEvent>>): Promise { + public async getContentDescriptor( + requestOptions: WithCancelEvent>>, + ): Promise { const { rulesetOrId, contentFlags, ...strippedOptions } = requestOptions; const params = { requestId: NativePlatformRequestTypes.GetContentDescriptor, @@ -207,8 +212,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getContentSetSize( - requestOptions: WithCancelEvent>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise { const { rulesetOrId, descriptor, ...strippedOptions } = requestOptions; const params = { @@ -222,8 +228,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getContentSet( - requestOptions: WithCancelEvent>>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>>> + & BackendDiagnosticsAttribute, ): Promise { const { rulesetOrId, descriptor, ...strippedOptions } = requestOptions; const params = { @@ -238,8 +245,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getContent( - requestOptions: WithCancelEvent>>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>>> + & BackendDiagnosticsAttribute, ): Promise { const { rulesetOrId, descriptor, ...strippedOptions } = requestOptions; const params = { @@ -253,8 +261,9 @@ export class PresentationManagerDetail implements IDisposable { } public async getPagedDistinctValues( - requestOptions: WithCancelEvent>> & - BackendDiagnosticsAttribute, + requestOptions: + & WithCancelEvent>> + & BackendDiagnosticsAttribute, ): Promise> { const { rulesetOrId, ...strippedOptions } = requestOptions; const { descriptor, keys, ...strippedOptionsNoDescriptorAndKeys } = strippedOptions; @@ -268,10 +277,10 @@ export class PresentationManagerDetail implements IDisposable { const reviver = (key: string, value: any) => { return key === "" ? { - total: value.total, - // eslint-disable-next-line deprecation/deprecation - items: value.items.map(DisplayValueGroup.fromJSON), - } + total: value.total, + // eslint-disable-next-line deprecation/deprecation + items: value.items.map(DisplayValueGroup.fromJSON), + } : value; }; return JSON.parse(await this.request(params), reviver); @@ -309,7 +318,9 @@ export class PresentationManagerDetail implements IDisposable { }; const content = await this.getContent(contentRequestOptions); return concreteKeys.map((key) => { - const item = content ? content.contentSet.find((it) => it.primaryKeys.length > 0 && InstanceKey.compare(it.primaryKeys[0], key) === 0) : undefined; + const item = content + ? content.contentSet.find((it) => it.primaryKeys.length > 0 && InstanceKey.compare(it.primaryKeys[0], key) === 0) + : undefined; if (!item) { return { displayValue: "", rawValue: "", typeName: "" }; } @@ -385,7 +396,11 @@ interface RequestParams { cancelEvent?: BeEvent<() => void>; } -function setupRulesets(nativePlatform: NativePlatformDefinition, supplementalRulesetDirectories: string[], primaryRulesetDirectories: string[]): void { +function setupRulesets( + nativePlatform: NativePlatformDefinition, + supplementalRulesetDirectories: string[], + primaryRulesetDirectories: string[], +): void { // eslint-disable-next-line @typescript-eslint/no-var-requires const elementPropertiesRuleset: Ruleset = require("./primary-presentation-rules/ElementProperties.PresentationRuleSet.json"); nativePlatform.addRuleset(JSON.stringify(elementPropertiesRuleset)); diff --git a/presentation/backend/src/presentation-backend/PresentationRpcImpl.ts b/presentation/backend/src/presentation-backend/PresentationRpcImpl.ts index e721fbdd5665..f8f9ad974459 100644 --- a/presentation/backend/src/presentation-backend/PresentationRpcImpl.ts +++ b/presentation/backend/src/presentation-backend/PresentationRpcImpl.ts @@ -163,9 +163,19 @@ export class PresentationRpcImpl extends PresentationRpcInterface implements IDi } private async makeRequest< - TRpcOptions extends { rulesetOrId?: Ruleset | string; clientId?: string; diagnostics?: RpcDiagnosticsOptions; rulesetVariables?: RulesetVariableJSON[] }, + TRpcOptions extends { + rulesetOrId?: Ruleset | string; + clientId?: string; + diagnostics?: RpcDiagnosticsOptions; + rulesetVariables?: RulesetVariableJSON[]; + }, TResult, - >(token: IModelRpcProps, requestId: string, requestOptions: TRpcOptions, request: ContentGetter>): PresentationRpcResponse { + >( + token: IModelRpcProps, + requestId: string, + requestOptions: TRpcOptions, + request: ContentGetter>, + ): PresentationRpcResponse { const requestKey = JSON.stringify({ iModelKey: token.key, requestId, requestOptions }); Logger.logInfo(PresentationBackendLoggerCategory.Rpc, `Received '${requestId}' request. Params: ${requestKey}`); @@ -382,7 +392,7 @@ export class PresentationRpcImpl extends PresentationRpcInterface implements IDi public override async getPagedContent( token: IModelRpcProps, requestOptions: Paged, - ): PresentationRpcResponse<{ descriptor: DescriptorJSON; contentSet: PagedResponse } | undefined> { + ): PresentationRpcResponse<{ descriptor: DescriptorJSON, contentSet: PagedResponse } | undefined> { return this.makeRequest(token, "getPagedContent", requestOptions, async (options) => { options = enforceValidPageSize({ ...options, @@ -417,7 +427,11 @@ export class PresentationRpcImpl extends PresentationRpcInterface implements IDi return this.errorResponse(response.statusCode, response.errorMessage, response.diagnostics); } if (!response.result) { - return this.errorResponse(PresentationStatus.Error, `Failed to get content set (received a success response with empty result)`, response.diagnostics); + return this.errorResponse( + PresentationStatus.Error, + `Failed to get content set (received a success response with empty result)`, + response.diagnostics, + ); } return { ...response, @@ -470,7 +484,7 @@ export class PresentationRpcImpl extends PresentationRpcInterface implements IDi public override async getContentInstanceKeys( token: IModelRpcProps, requestOptions: ContentInstanceKeysRpcRequestOptions, - ): PresentationRpcResponse<{ total: number; items: KeySetJSON }> { + ): PresentationRpcResponse<{ total: number, items: KeySetJSON }> { return this.makeRequest(token, "getContentInstanceKeys", requestOptions, async (options) => { const { displayType, ...optionsNoDisplayType } = options; options = enforceValidPageSize( @@ -530,9 +544,15 @@ export class PresentationRpcImpl extends PresentationRpcInterface implements IDi }); } - public override async getSelectionScopes(token: IModelRpcProps, requestOptions: SelectionScopeRpcRequestOptions): PresentationRpcResponse { - return this.makeRequest(token, "getSelectionScopes", requestOptions, async (options) => - this.getManager(requestOptions.clientId).getSelectionScopes(options), + public override async getSelectionScopes( + token: IModelRpcProps, + requestOptions: SelectionScopeRpcRequestOptions, + ): PresentationRpcResponse { + return this.makeRequest( + token, + "getSelectionScopes", + requestOptions, + async (options) => this.getManager(requestOptions.clientId).getSelectionScopes(options), ); } diff --git a/presentation/backend/src/presentation-backend/RulesetEmbedder.ts b/presentation/backend/src/presentation-backend/RulesetEmbedder.ts index 06354a8588b9..8cac90ff3335 100644 --- a/presentation/backend/src/presentation-backend/RulesetEmbedder.ts +++ b/presentation/backend/src/presentation-backend/RulesetEmbedder.ts @@ -6,8 +6,6 @@ * @module Core */ -import * as path from "path"; -import { gt as versionGt, gte as versionGte, lt as versionLt } from "semver"; import { DefinitionElement, DefinitionModel, @@ -36,6 +34,8 @@ import { SubjectProps, } from "@itwin/core-common"; import { Ruleset } from "@itwin/presentation-common"; +import * as path from "path"; +import { gt as versionGt, gte as versionGte, lt as versionLt } from "semver"; import { PresentationRules } from "./domain/PresentationRulesDomain"; import * as RulesetElements from "./domain/RulesetElements"; import { normalizeVersion } from "./Utils"; @@ -152,7 +152,9 @@ export class RulesetEmbedder { SELECT ECInstanceId, JsonProperties FROM ${RulesetElements.Ruleset.schema.name}.${RulesetElements.Ruleset.className} WHERE json_extract(JsonProperties, '$.jsonProperties.id') = :rulesetId`; - const reader = this._imodel.createQueryReader(query, QueryBinder.from({ rulesetId: ruleset.id }), { rowFormat: QueryRowFormat.UseJsPropertyNames }); + const reader = this._imodel.createQueryReader(query, QueryBinder.from({ rulesetId: ruleset.id }), { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }); while (await reader.step()) { const row = reader.current.toRow(); const existingRulesetElementId: Id64String = row.id; @@ -165,10 +167,10 @@ export class RulesetEmbedder { } // check if we need to do anything at all - const shouldSkip = - (normalizedOptions.skip === "same-id" && rulesetsWithSameId.length > 0) || + const shouldSkip = (normalizedOptions.skip === "same-id" && rulesetsWithSameId.length > 0) || (normalizedOptions.skip === "same-id-and-version-eq" && rulesetsWithSameId.some((entry) => entry.normalizedVersion === rulesetVersion)) || - (normalizedOptions.skip === "same-id-and-version-gte" && rulesetsWithSameId.some((entry) => versionGte(entry.normalizedVersion, rulesetVersion))); + (normalizedOptions.skip === "same-id-and-version-gte" && + rulesetsWithSameId.some((entry) => versionGte(entry.normalizedVersion, rulesetVersion))); if (shouldSkip) { // we're not inserting anything - return ID of the ruleset element with the highest version const rulesetEntryWithHighestVersion = rulesetsWithSameId.reduce((highest, curr) => { diff --git a/presentation/backend/src/presentation-backend/Utils.ts b/presentation/backend/src/presentation-backend/Utils.ts index bf73c730ffef..0735628fdb4d 100644 --- a/presentation/backend/src/presentation-backend/Utils.ts +++ b/presentation/backend/src/presentation-backend/Utils.ts @@ -6,7 +6,6 @@ * @module Core */ -import { parse as parseVersion } from "semver"; import { Element, IModelDb } from "@itwin/core-backend"; import { DbResult, Id64String } from "@itwin/core-bentley"; import { @@ -17,6 +16,7 @@ import { DiagnosticsOptions, InstanceKey, } from "@itwin/presentation-common"; +import { parse as parseVersion } from "semver"; const presentation = require("@itwin/presentation-common/lib/cjs/assets/locales/en/Presentation.json"); // eslint-disable-line @typescript-eslint/no-var-requires @@ -140,7 +140,10 @@ function stripDiagnostics(options: Diagnosti if (!strippedScope.logs) { delete strippedScope.logs; } - if (entry.duration !== undefined && (options.perf === true || (typeof options.perf === "object" && entry.duration >= options.perf.minimumDuration))) { + if ( + entry.duration !== undefined && + (options.perf === true || (typeof options.perf === "object" && entry.duration >= options.perf.minimumDuration)) + ) { stripped.push(strippedScope); } else if (scopeLogs) { delete strippedScope.duration; diff --git a/presentation/backend/src/presentation-backend/domain/RulesetElements.ts b/presentation/backend/src/presentation-backend/domain/RulesetElements.ts index d9116aaf5a9f..c64493faf5c0 100644 --- a/presentation/backend/src/presentation-backend/domain/RulesetElements.ts +++ b/presentation/backend/src/presentation-backend/domain/RulesetElements.ts @@ -6,8 +6,8 @@ * @module Core */ -import { Id64String } from "@itwin/core-bentley"; import { DefinitionElement, IModelDb } from "@itwin/core-backend"; +import { Id64String } from "@itwin/core-bentley"; import { Code } from "@itwin/core-common"; import { Ruleset as PresentationRuleset } from "@itwin/presentation-common"; import { normalizeVersion } from "../Utils"; diff --git a/presentation/backend/src/test/ElementPropertiesHelper.test.ts b/presentation/backend/src/test/ElementPropertiesHelper.test.ts index 6f65743877db..7abfe31ffe53 100644 --- a/presentation/backend/src/test/ElementPropertiesHelper.test.ts +++ b/presentation/backend/src/test/ElementPropertiesHelper.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as moq from "typemoq"; import { ECSqlStatement, ECSqlValue, IModelDb } from "@itwin/core-backend"; import { DbResult } from "@itwin/core-bentley"; import { PresentationError } from "@itwin/presentation-common"; +import { expect } from "chai"; +import * as moq from "typemoq"; import { getBatchedClassElementIds, getClassesWithInstances, getElementsCount } from "../presentation-backend/ElementPropertiesHelper"; import { stubECSqlReader } from "./Helpers"; @@ -48,7 +48,7 @@ describe("getElementsCount", () => { x.withPreparedStatement( moq.It.is((query) => query.includes("WHERE")), moq.It.isAny(), - ), + ) ) .returns(() => 0) .verifiable(); @@ -100,7 +100,7 @@ describe("getClassesWithInstances", () => { ["schema", "classB"], ["schema", "classA"], ["schema", "classB"], - ]), + ]) ); const result = new Array(); await getClassesWithInstances(imodelMock.object, ["x"]).forEach((value) => result.push(value)); diff --git a/presentation/backend/src/test/NativePlatform.test.ts b/presentation/backend/src/test/NativePlatform.test.ts index 9ee995797a06..629ca55a6267 100644 --- a/presentation/backend/src/test/NativePlatform.test.ts +++ b/presentation/backend/src/test/NativePlatform.test.ts @@ -2,15 +2,19 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { _nativeDb, IModelDb, IModelHost, IModelJsNative, IModelNative } from "@itwin/core-backend"; +import { BeEvent } from "@itwin/core-bentley"; +import { DiagnosticsScopeLogs, PresentationError, PresentationStatus, VariableValueTypes } from "@itwin/presentation-common"; import { expect } from "chai"; import * as faker from "faker"; import { join } from "path"; import sinon from "sinon"; import * as moq from "typemoq"; -import { _nativeDb, IModelDb, IModelHost, IModelJsNative, IModelNative } from "@itwin/core-backend"; -import { BeEvent } from "@itwin/core-bentley"; -import { DiagnosticsScopeLogs, PresentationError, PresentationStatus, VariableValueTypes } from "@itwin/presentation-common"; -import { createDefaultNativePlatform, NativePlatformDefinition, PresentationNativePlatformResponseError } from "../presentation-backend/NativePlatform"; +import { + createDefaultNativePlatform, + NativePlatformDefinition, + PresentationNativePlatformResponseError, +} from "../presentation-backend/NativePlatform"; describe("default NativePlatform", () => { let nativePlatform: NativePlatformDefinition; @@ -84,14 +88,20 @@ describe("default NativePlatform", () => { it("throws on cancellation response", async () => { addonMock .setup((x) => x.handleRequest(moq.It.isAny(), "")) - .returns(() => ({ result: Promise.resolve({ error: { status: IModelJsNative.ECPresentationStatus.Canceled, message: "test" } }), cancel: () => {} })); + .returns(() => ({ + result: Promise.resolve({ error: { status: IModelJsNative.ECPresentationStatus.Canceled, message: "test" } }), + cancel: () => {}, + })); await expect(nativePlatform.handleRequest(undefined, "")).to.eventually.be.rejectedWith(PresentationNativePlatformResponseError, "test"); }); it("throws on error response", async () => { addonMock .setup((x) => x.handleRequest(moq.It.isAny(), "")) - .returns(() => ({ result: Promise.resolve({ error: { status: IModelJsNative.ECPresentationStatus.Error, message: "test" } }), cancel: () => {} })); + .returns(() => ({ + result: Promise.resolve({ error: { status: IModelJsNative.ECPresentationStatus.Error, message: "test" } }), + cancel: () => {}, + })); await expect(nativePlatform.handleRequest(undefined, "")).to.eventually.be.rejectedWith(PresentationNativePlatformResponseError, "test"); }); diff --git a/presentation/backend/src/test/Presentation.test.ts b/presentation/backend/src/test/Presentation.test.ts index 55d061ff9cc6..babc769fae38 100644 --- a/presentation/backend/src/test/Presentation.test.ts +++ b/presentation/backend/src/test/Presentation.test.ts @@ -2,15 +2,15 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BriefcaseDb, IModelHost, IpcHost } from "@itwin/core-backend"; +import { assert } from "@itwin/core-bentley"; +import { RpcManager } from "@itwin/core-common"; +import { PresentationError } from "@itwin/presentation-common"; import { expect } from "chai"; import * as faker from "faker"; import { join } from "path"; import * as sinon from "sinon"; import * as moq from "typemoq"; -import { BriefcaseDb, IModelHost, IpcHost } from "@itwin/core-backend"; -import { assert } from "@itwin/core-bentley"; -import { RpcManager } from "@itwin/core-common"; -import { PresentationError } from "@itwin/presentation-common"; import { NativePlatformDefinition } from "../presentation-backend/NativePlatform"; import { Presentation } from "../presentation-backend/Presentation"; import { PresentationIpcHandler } from "../presentation-backend/PresentationIpcHandler"; diff --git a/presentation/backend/src/test/PresentationIpcHandler.test.ts b/presentation/backend/src/test/PresentationIpcHandler.test.ts index db0a786a28d2..4c3c11754f00 100644 --- a/presentation/backend/src/test/PresentationIpcHandler.test.ts +++ b/presentation/backend/src/test/PresentationIpcHandler.test.ts @@ -2,8 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as sinon from "sinon"; -import * as moq from "typemoq"; import { CompressedId64Set, OrderedId64Iterable } from "@itwin/core-bentley"; import { Id64sRulesetVariableJSON, @@ -14,6 +12,8 @@ import { VariableValueTypes, } from "@itwin/presentation-common"; import { createRandomId } from "@itwin/presentation-common/lib/cjs/test"; +import * as sinon from "sinon"; +import * as moq from "typemoq"; import { Presentation } from "../presentation-backend/Presentation"; import { PresentationIpcHandler } from "../presentation-backend/PresentationIpcHandler"; import { PresentationManager } from "../presentation-backend/PresentationManager"; diff --git a/presentation/backend/src/test/PresentationManager.test.ts b/presentation/backend/src/test/PresentationManager.test.ts index 31a9df2dda77..1fd2e121273f 100644 --- a/presentation/backend/src/test/PresentationManager.test.ts +++ b/presentation/backend/src/test/PresentationManager.test.ts @@ -3,11 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import "@itwin/presentation-common/lib/cjs/test/_helpers/Promises"; -import { expect } from "chai"; -import * as faker from "faker"; -import * as path from "path"; -import * as sinon from "sinon"; -import * as moq from "typemoq"; import { ECSqlStatement, ECSqlValue, IModelDb, IModelHost, IModelJsNative, IModelNative, IpcHost } from "@itwin/core-backend"; import { DbResult, Id64String, using } from "@itwin/core-bentley"; import { SchemaContext } from "@itwin/ecschema-metadata"; @@ -92,6 +87,11 @@ import { createTestSelectClassInfo, createTestSimpleContentField, } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as faker from "faker"; +import * as path from "path"; +import * as sinon from "sinon"; +import * as moq from "typemoq"; import { NativePlatformDefinition, NativePlatformRequestTypes, @@ -378,7 +378,7 @@ describe("PresentationManager", () => { const imodelMock = moq.Mock.ofType(); const rulesetId = faker.random.word(); const unitSystem = "metric"; - await using(new PresentationManager({ addon: addonMock.object }), async (manager) => { + using(new PresentationManager({ addon: addonMock.object }), async (manager) => { addonMock .setup(async (x) => x.handleRequest( @@ -388,7 +388,7 @@ describe("PresentationManager", () => { return request.params.unitSystem === NativePresentationUnitSystem.Metric; }), undefined, - ), + ) ) .returns(async () => ({ result: "null" })) .verifiable(moq.Times.once()); @@ -401,7 +401,7 @@ describe("PresentationManager", () => { const imodelMock = moq.Mock.ofType(); const rulesetId = faker.random.word(); const unitSystem = "usSurvey"; - await using(new PresentationManager({ addon: addonMock.object, defaultUnitSystem: unitSystem }), async (manager) => { + using(new PresentationManager({ addon: addonMock.object, defaultUnitSystem: unitSystem }), async (manager) => { addonMock .setup(async (x) => x.handleRequest( @@ -411,7 +411,7 @@ describe("PresentationManager", () => { return request.params.unitSystem === NativePresentationUnitSystem.UsSurvey; }), undefined, - ), + ) ) .returns(async () => ({ result: "null" })) .verifiable(moq.Times.once()); @@ -424,7 +424,7 @@ describe("PresentationManager", () => { const imodelMock = moq.Mock.ofType(); const rulesetId = faker.random.word(); const unitSystem = "usCustomary"; - await using(new PresentationManager({ addon: addonMock.object, defaultUnitSystem: "metric" }), async (manager) => { + using(new PresentationManager({ addon: addonMock.object, defaultUnitSystem: "metric" }), async (manager) => { expect(manager.activeUnitSystem).to.not.eq(unitSystem); addonMock .setup(async (x) => @@ -435,7 +435,7 @@ describe("PresentationManager", () => { return request.params.unitSystem === NativePresentationUnitSystem.UsCustomary; }), undefined, - ), + ) ) .returns(async () => ({ result: "null" })) .verifiable(moq.Times.once()); @@ -452,7 +452,9 @@ describe("PresentationManager", () => { const manager = new PresentationManager({ addon: addonMock.object }); const managerUsedSpy = sinon.spy(); - addonMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ result: `{"nodes":[]}` })); + addonMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ + result: `{"nodes":[]}`, + })); addonMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ result: "{}" })); @@ -587,7 +589,7 @@ describe("PresentationManager", () => { moq.It.isAny(), moq.It.is((reqStr) => sinon.match(JSON.parse(reqStr).params.diagnostics).test({ perf: true })), undefined, - ), + ) ) .returns(async () => ({ result: "{}", diagnostics: diagnosticsResult.logs[0] })) .verifiable(moq.Times.once()); @@ -632,7 +634,7 @@ describe("PresentationManager", () => { moq.It.isAny(), moq.It.is((reqStr) => sinon.match(JSON.parse(reqStr).params.diagnostics).test({ perf: true })), undefined, - ), + ) ) .returns(async () => ({ result: "{}", diagnostics: diagnosticsResult.logs[0] })) .verifiable(moq.Times.once()); @@ -669,7 +671,7 @@ describe("PresentationManager", () => { moq.It.isAny(), moq.It.is((reqStr) => sinon.match(JSON.parse(reqStr).params.diagnostics).test({ perf: true })), undefined, - ), + ) ) .returns(async () => { throw new PresentationNativePlatformResponseError({ @@ -728,7 +730,7 @@ describe("PresentationManager", () => { moq.It.isAny(), moq.It.is((reqStr) => sinon.match(JSON.parse(reqStr).params.diagnostics).test({ perf: true, dev: "debug" })), undefined, - ), + ) ) .returns(async () => ({ result: "{}", diagnostics: diagnosticsResult })) .verifiable(moq.Times.once()); @@ -780,11 +782,15 @@ describe("PresentationManager", () => { const setup = (addonResponse: any) => { if (addonResponse === undefined) { - nativePlatformMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ result: "null" })); + nativePlatformMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ + result: "null", + })); return undefined; } const serialized = JSON.stringify(addonResponse); - nativePlatformMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ result: serialized })); + nativePlatformMock.setup(async (x) => x.handleRequest(moq.It.isAny(), moq.It.isAnyString(), undefined)).returns(async () => ({ + result: serialized, + })); return JSON.parse(serialized); }; const verifyMockRequest = (expectedParams: any) => { @@ -1334,11 +1340,36 @@ describe("PresentationManager", () => { selectClassInfo: "0x123", isSelectPolymorphic: true, pathToPrimaryClass: [{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }], - pathFromInputToSelectClass: [{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }], - relatedPropertyPaths: [[{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }]], - navigationPropertyClasses: [{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }], - relatedInstanceClasses: [{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }], - relatedInstancePaths: [[{ sourceClassInfo: "0x123", relationshipInfo: "0x456", isForwardRelationship: true, targetClassInfo: "0x789" }]], + pathFromInputToSelectClass: [{ + sourceClassInfo: "0x123", + relationshipInfo: "0x456", + isForwardRelationship: true, + targetClassInfo: "0x789", + }], + relatedPropertyPaths: [[{ + sourceClassInfo: "0x123", + relationshipInfo: "0x456", + isForwardRelationship: true, + targetClassInfo: "0x789", + }]], + navigationPropertyClasses: [{ + sourceClassInfo: "0x123", + relationshipInfo: "0x456", + isForwardRelationship: true, + targetClassInfo: "0x789", + }], + relatedInstanceClasses: [{ + sourceClassInfo: "0x123", + relationshipInfo: "0x456", + isForwardRelationship: true, + targetClassInfo: "0x789", + }], + relatedInstancePaths: [[{ + sourceClassInfo: "0x123", + relationshipInfo: "0x456", + isForwardRelationship: true, + targetClassInfo: "0x789", + }]], } as SelectClassInfoJSON, ], classesMap: { @@ -2605,7 +2636,9 @@ describe("PresentationManager", () => { contentFlags: ContentFlags.ShowLabels, instanceFilter: { selectClassName: `TestSchema.TestClass`, - expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${Number.parseInt("0x124", 16).toString(10)}`, + expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${ + Number.parseInt("0x124", 16).toString(10) + }`, }, }, keys: new KeySet(), @@ -2735,7 +2768,9 @@ describe("PresentationManager", () => { contentFlags: ContentFlags.ShowLabels, instanceFilter: { selectClassName: `TestSchema.TestClass`, - expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${Number.parseInt("0x124", 16).toString(10)}`, + expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${ + Number.parseInt("0x124", 16).toString(10) + }`, }, }, keys: new KeySet(), @@ -2865,7 +2900,9 @@ describe("PresentationManager", () => { contentFlags: ContentFlags.ShowLabels, instanceFilter: { selectClassName: `TestSchema.TestClass`, - expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${Number.parseInt("0x124", 16).toString(10)}`, + expression: `this.ECInstanceId >= ${Number.parseInt("0x123", 16).toString(10)} AND this.ECInstanceId <= ${ + Number.parseInt("0x124", 16).toString(10) + }`, }, }, keys: new KeySet(), diff --git a/presentation/backend/src/test/PresentationRpcImpl.test.ts b/presentation/backend/src/test/PresentationRpcImpl.test.ts index 1571087c174c..c54ce44b65c2 100644 --- a/presentation/backend/src/test/PresentationRpcImpl.test.ts +++ b/presentation/backend/src/test/PresentationRpcImpl.test.ts @@ -2,10 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; -import * as sinon from "sinon"; -import * as moq from "typemoq"; import { IModelDb, RpcTrace } from "@itwin/core-backend"; import { BeEvent, Guid, using } from "@itwin/core-bentley"; import { IModelNotFoundResponse, IModelRpcProps } from "@itwin/core-common"; @@ -79,6 +75,10 @@ import { createTestSimpleContentField, ResolvablePromise, } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as faker from "faker"; +import * as sinon from "sinon"; +import * as moq from "typemoq"; import { BackendDiagnosticsAttribute } from "../presentation-backend"; import { NativePlatformDefinition } from "../presentation-backend/NativePlatform"; import { Presentation } from "../presentation-backend/Presentation"; @@ -139,7 +139,7 @@ describe("PresentationRpcImpl", () => { sinon.stub(IModelDb, "findByKey").returns(imodelMock.object); const impl = new PresentationRpcImpl({ requestTimeout: 10 }); - await using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { + using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { presentationManagerMock .setup(async (x) => x.getNodesCount(moq.It.isAny())) .callback((props: HierarchyRequestOptions & BackendDiagnosticsAttribute) => { @@ -178,7 +178,7 @@ describe("PresentationRpcImpl", () => { sinon.stub(IModelDb, "findByKey").returns(imodelMock.object); const impl = new PresentationRpcImpl({ requestTimeout: 10 }); - await using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { + using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { let callsCount = 0; const result = new ResolvablePromise(); presentationManagerMock @@ -212,7 +212,7 @@ describe("PresentationRpcImpl", () => { sinon.stub(IModelDb, "findByKey").returns(imodelMock.object); const impl = new PresentationRpcImpl({ requestTimeout: 10 }); - await using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { + using([{ dispose: () => Presentation.terminate() }, impl], async (_) => { presentationManagerMock.setup(async (x) => x.getNodesCount(moq.It.isAny())).returns(async () => 123); const response = await impl.getNodesCount(imodelTokenMock.object, { rulesetOrId: "", diagnostics: { backendVersion: true } }); expect(response.statusCode).to.eq(PresentationStatus.Success); diff --git a/presentation/backend/src/test/RulesetEmbedder.test.ts b/presentation/backend/src/test/RulesetEmbedder.test.ts index f4e76dced747..db601b3c9e28 100644 --- a/presentation/backend/src/test/RulesetEmbedder.test.ts +++ b/presentation/backend/src/test/RulesetEmbedder.test.ts @@ -2,10 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import faker from "faker"; -import sinon from "sinon"; -import * as moq from "typemoq"; import { BisCoreSchema, CodeSpecs, @@ -33,6 +29,10 @@ import { } from "@itwin/core-common"; import { Ruleset } from "@itwin/presentation-common"; import { configureForPromiseResult } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import faker from "faker"; +import sinon from "sinon"; +import * as moq from "typemoq"; import { PresentationRules } from "../presentation-backend/domain/PresentationRulesDomain"; import * as RulesetElements from "../presentation-backend/domain/RulesetElements"; import { RulesetEmbedder } from "../presentation-backend/RulesetEmbedder"; @@ -203,7 +203,7 @@ describe("RulesetEmbedder", () => { modelsMock.setup((x) => x.createModel(createModelProps)).returns(() => rulesetModelMock.object); } - function setupMocksForQueryingExistingRulesets(rulesetId: string, rulesets: Array<{ ruleset: Ruleset; elementId: Id64String }>) { + function setupMocksForQueryingExistingRulesets(rulesetId: string, rulesets: Array<{ ruleset: Ruleset, elementId: Id64String }>) { const results = rulesets.map((entry) => ({ id: entry.elementId, jsonProperties: JSON.stringify({ jsonProperties: entry.ruleset }), @@ -510,7 +510,7 @@ describe("RulesetEmbedder", () => { }); describe("getRulesets", () => { - function setupMocksForQueryingAllRulesets(rulesets: Array<{ ruleset: Ruleset; elementId: Id64String }>) { + function setupMocksForQueryingAllRulesets(rulesets: Array<{ ruleset: Ruleset, elementId: Id64String }>) { imodelMock .setup((x) => x.withPreparedStatement(moq.It.isAny(), moq.It.isAny())) .callback((_ecsql, callbackFun) => { diff --git a/presentation/backend/src/test/RulesetManager.test.ts b/presentation/backend/src/test/RulesetManager.test.ts index e88efcd77e63..9a4872ec3d52 100644 --- a/presentation/backend/src/test/RulesetManager.test.ts +++ b/presentation/backend/src/test/RulesetManager.test.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { RegisteredRuleset } from "@itwin/presentation-common"; import { expect } from "chai"; import * as faker from "faker"; import * as moq from "typemoq"; -import { RegisteredRuleset } from "@itwin/presentation-common"; import { NativePlatformDefinition } from "../presentation-backend/NativePlatform"; import { RulesetManagerImpl } from "../presentation-backend/RulesetManager"; diff --git a/presentation/backend/src/test/RulesetVariablesManager.test.ts b/presentation/backend/src/test/RulesetVariablesManager.test.ts index bb0392affe3b..f072e02bdbd0 100644 --- a/presentation/backend/src/test/RulesetVariablesManager.test.ts +++ b/presentation/backend/src/test/RulesetVariablesManager.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; -import * as moq from "typemoq"; import { Id64String, OrderedId64Iterable } from "@itwin/core-bentley"; import { VariableValueTypes } from "@itwin/presentation-common"; import { createRandomId } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as faker from "faker"; +import * as moq from "typemoq"; import { NativePlatformDefinition } from "../presentation-backend/NativePlatform"; import { RulesetVariablesManagerImpl } from "../presentation-backend/RulesetVariablesManager"; diff --git a/presentation/backend/src/test/SelectionScopesHelper.test.ts b/presentation/backend/src/test/SelectionScopesHelper.test.ts index d4ae948fd5a4..83f5ae2c073e 100644 --- a/presentation/backend/src/test/SelectionScopesHelper.test.ts +++ b/presentation/backend/src/test/SelectionScopesHelper.test.ts @@ -2,16 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; -import * as moq from "typemoq"; import { DrawingGraphic, ECSqlStatement, ECSqlValue, Element, IModelDb, IModelHost } from "@itwin/core-backend"; import { DbResult, Id64, Id64String } from "@itwin/core-bentley"; import { ElementProps, EntityMetaData, GeometricElement2dProps, IModelError, ModelProps } from "@itwin/core-common"; import { InstanceKey } from "@itwin/presentation-common"; import { createRandomECInstanceKey, createRandomId } from "@itwin/presentation-common/lib/cjs/test"; -import { SelectionScopesHelper } from "../presentation-backend/SelectionScopesHelper"; +import { expect } from "chai"; +import * as faker from "faker"; import { join } from "path"; +import * as moq from "typemoq"; +import { SelectionScopesHelper } from "../presentation-backend/SelectionScopesHelper"; describe("SelectionScopesHelper", () => { before(async () => { @@ -41,7 +41,7 @@ describe("SelectionScopesHelper", () => { x.withPreparedStatement( moq.It.is((q) => typeof q === "string" && q.includes("SELECT ECClassId FROM")), moq.It.isAny(), - ), + ) ) .callback((_q, cb) => { const valueMock = moq.Mock.ofType(); @@ -60,7 +60,7 @@ describe("SelectionScopesHelper", () => { x.withPreparedStatement( moq.It.is((q) => typeof q === "string" && q.includes("SELECT ECClassId FROM")), moq.It.isAny(), - ), + ) ) .callback((_q, cb) => { const stmtMock = moq.Mock.ofType(); @@ -116,14 +116,16 @@ describe("SelectionScopesHelper", () => { const createTransientElementId = () => Id64.fromLocalAndBriefcaseIds(faker.random.number(), 0xffffff); - const setupIModelForFunctionalKeyQuery = (props: { graphicalElementKey: InstanceKey; stepResult?: DbResult; functionalElementKey?: InstanceKey }) => { + const setupIModelForFunctionalKeyQuery = ( + props: { graphicalElementKey: InstanceKey, stepResult?: DbResult, functionalElementKey?: InstanceKey }, + ) => { const functionalKeyQueryIdentifier = "SELECT funcSchemaDef.Name || '.' || funcClassDef.Name funcElClassName, fe.ECInstanceId funcElId"; imodelMock .setup((x) => x.withPreparedStatement( moq.It.is((q) => typeof q === "string" && q.includes(functionalKeyQueryIdentifier)), moq.It.isAny(), - ), + ) ) .returns((_q, cb) => { const stmtMock = moq.Mock.ofType(); @@ -138,9 +140,13 @@ describe("SelectionScopesHelper", () => { }); }; - const setupIModelForElementProps = (props?: { key?: InstanceKey; parentKey?: InstanceKey; isRemoved?: boolean }) => { + const setupIModelForElementProps = (props?: { key?: InstanceKey, parentKey?: InstanceKey, isRemoved?: boolean }) => { const key = props?.key ?? createRandomECInstanceKey(); - const elementProps = props?.isRemoved ? undefined : props?.parentKey ? createRandomElementProps(props.parentKey.id) : createRandomTopmostElementProps(); + const elementProps = props?.isRemoved + ? undefined + : props?.parentKey + ? createRandomElementProps(props.parentKey.id) + : createRandomTopmostElementProps(); elementsMock.setup((x) => x.tryGetElementProps(key.id)).returns(() => elementProps); return { key, props: elementProps }; }; @@ -152,7 +158,7 @@ describe("SelectionScopesHelper", () => { x.withPreparedStatement( moq.It.is((q) => typeof q === "string" && q.includes(classDerivesFromQueryIdentifier)), moq.It.isAny(), - ), + ) ) .returns((_q, cb) => { const stmtMock = moq.Mock.ofType(); @@ -229,7 +235,11 @@ describe("SelectionScopesHelper", () => { setupIModelForInvalidId(); setupIModelForElementKey(validKeys[1]); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [validKeys[0].id, "not an id", validKeys[1].id], "element"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [validKeys[0].id, "not an id", validKeys[1].id], + "element", + ); expect(result.size).to.eq(2); validKeys.forEach((key) => expect(result.has(key))); }); @@ -784,7 +794,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementProps({ key: graphicalElementKey }); setupIModelForElementKey(graphicalElementKey); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(graphicalElementKey)).to.be.true; }); @@ -800,7 +814,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementKey(graphicalGrandParentElementKey); setupIModelForFunctionalKeyQuery({ graphicalElementKey: graphicalGrandParentElementKey }); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(graphicalGrandParentElementKey)).to.be.true; }); @@ -817,7 +835,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementKey(graphicalGrandParentElementKey); setupIModelForFunctionalKeyQuery({ graphicalElementKey: graphicalGrandParentElementKey, functionalElementKey }); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(functionalElementKey)).to.be.true; }); @@ -829,7 +851,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementProps({ key: graphicalElementKey }); setupIModelForElementKey(graphicalElementKey); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(graphicalElementKey)).to.be.true; }); @@ -850,7 +876,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementProps({ key: graphicalGrandParentElementKey }); setupIModelForElementKey(graphicalGrandParentElementKey); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(graphicalGrandParentElementKey)).to.be.true; }); @@ -869,7 +899,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementProps({ key: functionalElementKey }); setupIModelForElementKey(functionalElementKey); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(functionalElementKey)).to.be.true; }); @@ -892,7 +926,11 @@ describe("SelectionScopesHelper", () => { setupIModelForElementProps({ key: functionalGrandParentElementKey }); setupIModelForElementKey(functionalGrandParentElementKey); - const result = await SelectionScopesHelper.computeSelection({ imodel: imodelMock.object }, [graphicalElementKey.id], "functional-top-assembly"); + const result = await SelectionScopesHelper.computeSelection( + { imodel: imodelMock.object }, + [graphicalElementKey.id], + "functional-top-assembly", + ); expect(result.size).to.eq(1); expect(result.has(functionalGrandParentElementKey)).to.be.true; }); diff --git a/presentation/backend/src/test/TemporaryStorage.test.ts b/presentation/backend/src/test/TemporaryStorage.test.ts index 256a34c73c54..cf6c1ecf4edf 100644 --- a/presentation/backend/src/test/TemporaryStorage.test.ts +++ b/presentation/backend/src/test/TemporaryStorage.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as fakeTimers from "@sinonjs/fake-timers"; -import * as sinon from "sinon"; import { using } from "@itwin/core-bentley"; import { PresentationError } from "@itwin/presentation-common"; +import * as fakeTimers from "@sinonjs/fake-timers"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { FactoryBasedTemporaryStorage, FactoryBasedTemporaryStorageProps, TemporaryStorage } from "../presentation-backend/TemporaryStorage"; describe("TemporaryStorage", () => { diff --git a/presentation/backend/src/test/Utils.test.ts b/presentation/backend/src/test/Utils.test.ts index 8f3f557770ec..91aa1290092d 100644 --- a/presentation/backend/src/test/Utils.test.ts +++ b/presentation/backend/src/test/Utils.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; -import * as moq from "typemoq"; import { ECSqlStatement, ECSqlValue, IModelDb } from "@itwin/core-backend"; import { DbResult } from "@itwin/core-bentley"; import { createRandomId } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as sinon from "sinon"; +import * as moq from "typemoq"; import { combineDiagnosticsOptions, getElementKey, getLocalizedStringEN, normalizeVersion, reportDiagnostics } from "../presentation-backend/Utils"; describe("getElementKey", () => { @@ -102,8 +102,12 @@ describe("combineDiagnosticsOptions", () => { expect(combineDiagnosticsOptions({ perf: true, handler }, undefined)).to.deep.eq({ perf: true }); expect(combineDiagnosticsOptions({ perf: true, handler }, { perf: false, handler })).to.deep.eq({ perf: true }); expect(combineDiagnosticsOptions({ perf: false, handler }, { perf: true, handler })).to.deep.eq({ perf: true }); - expect(combineDiagnosticsOptions({ perf: { minimumDuration: 123 }, handler }, { perf: false, handler })).to.deep.eq({ perf: { minimumDuration: 123 } }); - expect(combineDiagnosticsOptions({ perf: false, handler }, { perf: { minimumDuration: 456 }, handler })).to.deep.eq({ perf: { minimumDuration: 456 } }); + expect(combineDiagnosticsOptions({ perf: { minimumDuration: 123 }, handler }, { perf: false, handler })).to.deep.eq({ + perf: { minimumDuration: 123 }, + }); + expect(combineDiagnosticsOptions({ perf: false, handler }, { perf: { minimumDuration: 456 }, handler })).to.deep.eq({ + perf: { minimumDuration: 456 }, + }); }); it("sets `perf` to lower requirement", () => { diff --git a/presentation/common/Ruleset.schema.json b/presentation/common/Ruleset.schema.json index f474b9052cfe..b23ea0f946bb 100644 --- a/presentation/common/Ruleset.schema.json +++ b/presentation/common/Ruleset.schema.json @@ -2875,4 +2875,4 @@ "rules" ], "type": "object" -} \ No newline at end of file +} diff --git a/presentation/common/scripts/post-process-json-schema.js b/presentation/common/scripts/post-process-json-schema.js index 7a73be94bbd9..e5cbca991e6a 100644 --- a/presentation/common/scripts/post-process-json-schema.js +++ b/presentation/common/scripts/post-process-json-schema.js @@ -50,7 +50,9 @@ if (isCI) { // break CI builds if the schema file changes during the build const schemaFileDiff = execSync(`git diff "${yargs.path}"`).toString().trim(); if (schemaFileDiff !== "") { - console.error(`JSON schema file was modified during a CI build. Please build the package locally and commit the changes. Diff:\n\n${schemaFileDiff}\n\n`); + console.error( + `JSON schema file was modified during a CI build. Please build the package locally and commit the changes. Diff:\n\n${schemaFileDiff}\n\n`, + ); process.exit(1); } } diff --git a/presentation/common/src/presentation-common/Diagnostics.ts b/presentation/common/src/presentation-common/Diagnostics.ts index 28dca1253619..3aee5f9f552e 100644 --- a/presentation/common/src/presentation-common/Diagnostics.ts +++ b/presentation/common/src/presentation-common/Diagnostics.ts @@ -21,20 +21,22 @@ export type DiagnosticsLoggerSeverity = "error" | "warning" | "info" | "debug" | * ``` * @internal */ -export function combineDiagnosticsSeverities(lhs: undefined | boolean | DiagnosticsLoggerSeverity, rhs: undefined | boolean | DiagnosticsLoggerSeverity) { +export function combineDiagnosticsSeverities( + lhs: undefined | boolean | DiagnosticsLoggerSeverity, + rhs: undefined | boolean | DiagnosticsLoggerSeverity, +) { if (!lhs && !rhs) { return undefined; } - const combinedSeverity: DiagnosticsLoggerSeverity = - lhs === "trace" || rhs === "trace" - ? "trace" - : lhs === "debug" || lhs === true || rhs === "debug" || rhs === true - ? "debug" - : lhs === "info" || rhs === "info" - ? "info" - : lhs === "warning" || rhs === "warning" - ? "warning" - : "error"; + const combinedSeverity: DiagnosticsLoggerSeverity = lhs === "trace" || rhs === "trace" + ? "trace" + : lhs === "debug" || lhs === true || rhs === "debug" || rhs === true + ? "debug" + : lhs === "info" || rhs === "info" + ? "info" + : lhs === "warning" || rhs === "warning" + ? "warning" + : "error"; return combinedSeverity; } @@ -50,7 +52,10 @@ export function combineDiagnosticsSeverities(lhs: undefined | boolean | Diagnost * ``` * @internal */ -export function compareDiagnosticsSeverities(lhs: undefined | boolean | DiagnosticsLoggerSeverity, rhs: undefined | boolean | DiagnosticsLoggerSeverity) { +export function compareDiagnosticsSeverities( + lhs: undefined | boolean | DiagnosticsLoggerSeverity, + rhs: undefined | boolean | DiagnosticsLoggerSeverity, +) { const normalizedLhs: DiagnosticsLoggerSeverity = lhs === undefined || lhs === false ? "error" : lhs === true ? "debug" : lhs; const normalizedRhs: DiagnosticsLoggerSeverity = rhs === undefined || rhs === false ? "error" : rhs === true ? "debug" : rhs; if (normalizedLhs === normalizedRhs) { diff --git a/presentation/common/src/presentation-common/EC.ts b/presentation/common/src/presentation-common/EC.ts index fe1d73344dff..8f808d6357d0 100644 --- a/presentation/common/src/presentation-common/EC.ts +++ b/presentation/common/src/presentation-common/EC.ts @@ -231,7 +231,10 @@ export namespace NavigationPropertyInfo { return { ...compressedNavigationPropertyInfoJSON, classInfo: { id: compressedNavigationPropertyInfoJSON.classInfo, ...classesMap[compressedNavigationPropertyInfoJSON.classInfo] }, - targetClassInfo: { id: compressedNavigationPropertyInfoJSON.targetClassInfo, ...classesMap[compressedNavigationPropertyInfoJSON.targetClassInfo] }, + targetClassInfo: { + id: compressedNavigationPropertyInfoJSON.targetClassInfo, + ...classesMap[compressedNavigationPropertyInfoJSON.targetClassInfo], + }, }; } } @@ -289,7 +292,9 @@ export namespace PropertyInfo { return { ...leftOverPropertyInfo, classInfo: propertyInfo.classInfo.id, - ...(navigationPropertyInfo ? { navigationPropertyInfo: NavigationPropertyInfo.toCompressedJSON(navigationPropertyInfo, classesMap) } : undefined), + ...(navigationPropertyInfo + ? { navigationPropertyInfo: NavigationPropertyInfo.toCompressedJSON(navigationPropertyInfo, classesMap) } + : undefined), }; } @@ -450,7 +455,10 @@ export interface RelatedClassInfoJSON { * an actual ECRelationship between them is optional. * @public */ -export type RelatedClassInfoWithOptionalRelationship = PartialBy; +export type RelatedClassInfoWithOptionalRelationship = PartialBy< + RelatedClassInfo, + "relationshipInfo" | "isForwardRelationship" | "isPolymorphicRelationship" +>; /** @public */ // eslint-disable-next-line deprecation/deprecation diff --git a/presentation/common/src/presentation-common/ElementProperties.ts b/presentation/common/src/presentation-common/ElementProperties.ts index 6a14cf0cea6f..33c9e806a5dd 100644 --- a/presentation/common/src/presentation-common/ElementProperties.ts +++ b/presentation/common/src/presentation-common/ElementProperties.ts @@ -141,7 +141,10 @@ export type ElementPropertiesPropertyValueType = "primitive" | "array" | "struct * Definition of a property value. * @public */ -export type ElementPropertiesPropertyItem = ElementPropertiesPrimitivePropertyItem | ElementPropertiesArrayPropertyItem | ElementPropertiesStructPropertyItem; +export type ElementPropertiesPropertyItem = + | ElementPropertiesPrimitivePropertyItem + | ElementPropertiesArrayPropertyItem + | ElementPropertiesStructPropertyItem; /** * Definition of a property item, including a property category. diff --git a/presentation/common/src/presentation-common/InstanceFilterDefinition.ts b/presentation/common/src/presentation-common/InstanceFilterDefinition.ts index 765848b3b8fc..940f6d4e840f 100644 --- a/presentation/common/src/presentation-common/InstanceFilterDefinition.ts +++ b/presentation/common/src/presentation-common/InstanceFilterDefinition.ts @@ -61,8 +61,9 @@ export interface InstanceFilterDefinition { * Related instance definition for accessing properties of a related instance in [[InstanceFilterDefinition.expression]]. * @public */ -export type InstanceFilterRelatedInstanceDefinition = InstanceFilterRelatedInstancePath & - (InstanceFilterRelatedInstanceTargetAlias | InstanceFilterRelatedInstanceRelationshipAlias); +export type InstanceFilterRelatedInstanceDefinition = + & InstanceFilterRelatedInstancePath + & (InstanceFilterRelatedInstanceTargetAlias | InstanceFilterRelatedInstanceRelationshipAlias); /** * Partial definition of common attributes for [[InstanceFilterRelatedInstanceDefinition]]. diff --git a/presentation/common/src/presentation-common/KeySet.ts b/presentation/common/src/presentation-common/KeySet.ts index da98fd9eab29..6b188053779d 100644 --- a/presentation/common/src/presentation-common/KeySet.ts +++ b/presentation/common/src/presentation-common/KeySet.ts @@ -196,8 +196,9 @@ export class KeySet { for (const entry of keyset.instanceKeys) { const lcClassName = normalizeClassName(entry["0"]); const idsJson: string | Id64String[] = entry["1"]; - const ids: Set = - typeof idsJson === "string" ? (idsJson === Id64.invalid ? new Set([Id64.invalid]) : CompressedId64Set.decompressSet(idsJson)) : new Set(idsJson); + const ids: Set = typeof idsJson === "string" + ? (idsJson === Id64.invalid ? new Set([Id64.invalid]) : CompressedId64Set.decompressSet(idsJson)) + : new Set(idsJson); this._instanceKeys.set(lcClassName, ids); this._lowerCaseMap.set(lcClassName, entry["0"]); } diff --git a/presentation/common/src/presentation-common/KoqPropertyValueFormatter.ts b/presentation/common/src/presentation-common/KoqPropertyValueFormatter.ts index c63c2d7b9ad6..c51043645f5e 100644 --- a/presentation/common/src/presentation-common/KoqPropertyValueFormatter.ts +++ b/presentation/common/src/presentation-common/KoqPropertyValueFormatter.ts @@ -80,7 +80,10 @@ export class KoqPropertyValueFormatter { ) { this._unitsProvider = new SchemaUnitProvider(_schemaContext); this._defaultFormats = defaultFormats - ? Object.entries(defaultFormats).reduce((acc, [phenomenon, unitSystemFormats]) => ({ ...acc, [phenomenon.toUpperCase()]: unitSystemFormats }), {}) + ? Object.entries(defaultFormats).reduce( + (acc, [phenomenon, unitSystemFormats]) => ({ ...acc, [phenomenon.toUpperCase()]: unitSystemFormats }), + {}, + ) : /* istanbul ignore next */ undefined; } @@ -171,14 +174,18 @@ async function getKoqFormatProps( // use one of the formats in default formats map if there is one for matching phenomena and requested unit // system combination if (defaultFormats && unitSystem) { - const actualPersistenceUnit = persistenceUnit instanceof InvertedUnit ? /* istanbul ignore next */ await persistenceUnit.invertsUnit : persistenceUnit; + const actualPersistenceUnit = persistenceUnit instanceof InvertedUnit + ? /* istanbul ignore next */ await persistenceUnit.invertsUnit + : persistenceUnit; const phenomenon = await actualPersistenceUnit?.phenomenon; // istanbul ignore else if (phenomenon && defaultFormats[phenomenon.name.toUpperCase()]) { const defaultPhenomenonFormats = defaultFormats[phenomenon.name.toUpperCase()]; - for (const defaultUnitSystemFormat of Array.isArray(defaultPhenomenonFormats) - ? /* istanbul ignore next */ defaultPhenomenonFormats - : [defaultPhenomenonFormats]) { + for ( + const defaultUnitSystemFormat of Array.isArray(defaultPhenomenonFormats) + ? /* istanbul ignore next */ defaultPhenomenonFormats + : [defaultPhenomenonFormats] + ) { if (defaultUnitSystemFormat.unitSystems.includes(unitSystem)) { return defaultUnitSystemFormat.format; } diff --git a/presentation/common/src/presentation-common/PresentationManagerOptions.ts b/presentation/common/src/presentation-common/PresentationManagerOptions.ts index 41fa1b68252e..f4e5780213f6 100644 --- a/presentation/common/src/presentation-common/PresentationManagerOptions.ts +++ b/presentation/common/src/presentation-common/PresentationManagerOptions.ts @@ -61,7 +61,8 @@ export interface RequestOptionsWithRuleset extends RequestOptionsWithRuleset { +export interface HierarchyRequestOptions + extends RequestOptionsWithRuleset { /** Key of the parent node to get children for */ parentKey?: TNodeKey; @@ -116,7 +117,8 @@ export interface FilterByInstancePathsHierarchyRequestOptions extends RequestOptionsWithRuleset { +export interface FilterByTextHierarchyRequestOptions + extends RequestOptionsWithRuleset { /** Text to filter the hierarchy by. */ filterText: string; } @@ -291,7 +293,8 @@ export function isComputeSelectionRequestOptions( * Data structure for comparing a hierarchy after ruleset or ruleset variable changes. * @public */ -export interface HierarchyCompareOptions extends RequestOptionsWithRuleset { +export interface HierarchyCompareOptions + extends RequestOptionsWithRuleset { prev: { rulesetOrId?: Ruleset | string; rulesetVariables?: TRulesetVariable[]; diff --git a/presentation/common/src/presentation-common/PresentationRpcInterface.ts b/presentation/common/src/presentation-common/PresentationRpcInterface.ts index 71076bbd9114..bbe89a9ec0bf 100644 --- a/presentation/common/src/presentation-common/PresentationRpcInterface.ts +++ b/presentation/common/src/presentation-common/PresentationRpcInterface.ts @@ -127,13 +127,17 @@ export interface ContentSourcesRpcResult { * Data structure for content descriptor RPC request options. * @public */ -export type ContentDescriptorRpcRequestOptions = PresentationRpcRequestOptions>; +export type ContentDescriptorRpcRequestOptions = PresentationRpcRequestOptions< + ContentDescriptorRequestOptions +>; /** * Data structure for content RPC request options. * @public */ -export type ContentRpcRequestOptions = PresentationRpcRequestOptions>; +export type ContentRpcRequestOptions = PresentationRpcRequestOptions< + ContentRequestOptions +>; /** * Data structure for single element properties RPC request options. @@ -155,7 +159,9 @@ export type DistinctValuesRpcRequestOptions = PresentationRpcRequestOptions< * Data structure for content instance keys' request options. * @public */ -export type ContentInstanceKeysRpcRequestOptions = PresentationRpcRequestOptions>; +export type ContentInstanceKeysRpcRequestOptions = PresentationRpcRequestOptions< + ContentInstanceKeysRequestOptions +>; /** * Data structure for label request options. @@ -216,21 +222,33 @@ export class PresentationRpcInterface extends RpcInterface { // TODO: add paged version of this (#387280) // eslint-disable-next-line deprecation/deprecation - public async getNodePaths(_token: IModelRpcProps, _options: FilterByInstancePathsHierarchyRpcRequestOptions): PresentationRpcResponse { + public async getNodePaths( + _token: IModelRpcProps, + _options: FilterByInstancePathsHierarchyRpcRequestOptions, + ): PresentationRpcResponse { return this.forward(arguments); } // TODO: add paged version of this (#387280) // eslint-disable-next-line deprecation/deprecation - public async getFilteredNodePaths(_token: IModelRpcProps, _options: FilterByTextHierarchyRpcRequestOptions): PresentationRpcResponse { + public async getFilteredNodePaths( + _token: IModelRpcProps, + _options: FilterByTextHierarchyRpcRequestOptions, + ): PresentationRpcResponse { return this.forward(arguments); } - public async getContentSources(_token: IModelRpcProps, _options: ContentSourcesRpcRequestOptions): PresentationRpcResponse { + public async getContentSources( + _token: IModelRpcProps, + _options: ContentSourcesRpcRequestOptions, + ): PresentationRpcResponse { return this.forward(arguments); } - public async getContentDescriptor(_token: IModelRpcProps, _options: ContentDescriptorRpcRequestOptions): PresentationRpcResponse { + public async getContentDescriptor( + _token: IModelRpcProps, + _options: ContentDescriptorRpcRequestOptions, + ): PresentationRpcResponse { arguments[1] = { ...arguments[1], transport: "unparsed-json" }; const response: PresentationRpcResponseData = await this.forward(arguments); if (response.statusCode === PresentationStatus.Success && typeof response.result === "string") { @@ -246,11 +264,14 @@ export class PresentationRpcInterface extends RpcInterface { public async getPagedContent( _token: IModelRpcProps, _options: Paged, - ): PresentationRpcResponse<{ descriptor: DescriptorJSON; contentSet: PagedResponse } | undefined> { + ): PresentationRpcResponse<{ descriptor: DescriptorJSON, contentSet: PagedResponse } | undefined> { return this.forward(arguments); } - public async getPagedContentSet(_token: IModelRpcProps, _options: Paged): PresentationRpcResponse> { + public async getPagedContentSet( + _token: IModelRpcProps, + _options: Paged, + ): PresentationRpcResponse> { return this.forward(arguments); } @@ -272,7 +293,7 @@ export class PresentationRpcInterface extends RpcInterface { public async getContentInstanceKeys( _token: IModelRpcProps, _options: ContentInstanceKeysRpcRequestOptions, - ): PresentationRpcResponse<{ total: number; items: KeySetJSON }> { + ): PresentationRpcResponse<{ total: number, items: KeySetJSON }> { return this.forward(arguments); } diff --git a/presentation/common/src/presentation-common/RpcRequestsHandler.ts b/presentation/common/src/presentation-common/RpcRequestsHandler.ts index eee9b15b42c0..e795a52101fc 100644 --- a/presentation/common/src/presentation-common/RpcRequestsHandler.ts +++ b/presentation/common/src/presentation-common/RpcRequestsHandler.ts @@ -38,7 +38,12 @@ import { RequestOptionsWithRuleset, SelectionScopeRequestOptions, } from "./PresentationManagerOptions"; -import { ContentSourcesRpcResult, PresentationRpcInterface, PresentationRpcRequestOptions, PresentationRpcResponse } from "./PresentationRpcInterface"; +import { + ContentSourcesRpcResult, + PresentationRpcInterface, + PresentationRpcRequestOptions, + PresentationRpcResponse, +} from "./PresentationRpcInterface"; import { Ruleset } from "./rules/Ruleset"; import { RulesetVariableJSON } from "./RulesetVariables"; import { SelectionScope } from "./selection/SelectionScope"; @@ -91,7 +96,10 @@ export class RpcRequestsHandler { return RpcManager.getClientForInterface(PresentationRpcInterface); } - private async requestWithTimeout(func: () => PresentationRpcResponse, diagnosticsHandler?: ClientDiagnosticsHandler): Promise { + private async requestWithTimeout( + func: () => PresentationRpcResponse, + diagnosticsHandler?: ClientDiagnosticsHandler, + ): Promise { const start = BeTimePoint.now(); const timeout = BeDuration.fromMilliseconds(this.timeout); let diagnostics: ClientDiagnostics | undefined; @@ -142,7 +150,9 @@ export class RpcRequestsHandler { return this.requestWithTimeout(doRequest, diagnosticsHandler); } - public async getNodesCount(options: HierarchyRequestOptions & ClientDiagnosticsAttribute): Promise { + public async getNodesCount( + options: HierarchyRequestOptions & ClientDiagnosticsAttribute, + ): Promise { return this.request(this.rpcClient.getNodesCount.bind(this.rpcClient), options); } @@ -157,7 +167,10 @@ export class RpcRequestsHandler { public async getNodesDescriptor( options: HierarchyLevelDescriptorRequestOptions & ClientDiagnosticsAttribute, ): Promise { - const response = await this.request(this.rpcClient.getNodesDescriptor.bind(this.rpcClient), options); + const response = await this.request( + this.rpcClient.getNodesDescriptor.bind(this.rpcClient), + options, + ); if (typeof response === "string") { return JSON.parse(response); } @@ -180,7 +193,9 @@ export class RpcRequestsHandler { return this.request(this.rpcClient.getFilteredNodePaths.bind(this.rpcClient), options); } - public async getContentSources(options: ContentSourcesRequestOptions & ClientDiagnosticsAttribute): Promise { + public async getContentSources( + options: ContentSourcesRequestOptions & ClientDiagnosticsAttribute, + ): Promise { return this.request(this.rpcClient.getContentSources.bind(this.rpcClient), options); } public async getContentDescriptor( @@ -196,7 +211,7 @@ export class RpcRequestsHandler { public async getPagedContent( options: Paged & ClientDiagnosticsAttribute>, ) { - return this.request<{ descriptor: DescriptorJSON; contentSet: PagedResponse } | undefined, typeof options>( + return this.request<{ descriptor: DescriptorJSON, contentSet: PagedResponse } | undefined, typeof options>( this.rpcClient.getPagedContent.bind(this.rpcClient), options, ); @@ -217,8 +232,8 @@ export class RpcRequestsHandler { public async getContentInstanceKeys( options: ContentInstanceKeysRequestOptions & ClientDiagnosticsAttribute, - ): Promise<{ total: number; items: KeySetJSON }> { - return this.request<{ total: number; items: KeySetJSON }, typeof options>(this.rpcClient.getContentInstanceKeys.bind(this.rpcClient), options); + ): Promise<{ total: number, items: KeySetJSON }> { + return this.request<{ total: number, items: KeySetJSON }, typeof options>(this.rpcClient.getContentInstanceKeys.bind(this.rpcClient), options); } public async getDisplayLabelDefinition( diff --git a/presentation/common/src/presentation-common/RulesetsFactory.ts b/presentation/common/src/presentation-common/RulesetsFactory.ts index e8b5902a3606..277580c57d1c 100644 --- a/presentation/common/src/presentation-common/RulesetsFactory.ts +++ b/presentation/common/src/presentation-common/RulesetsFactory.ts @@ -76,7 +76,7 @@ export class RulesetsFactory { field: Field, record: Item, computeDisplayValue?: ComputeDisplayValueCallback, - ): Promise<{ ruleset: Ruleset; description: string }> { + ): Promise<{ ruleset: Ruleset, description: string }> { const info = this.createSimilarInstancesRulesetInfo(field, record); const description = await createDescriptionAsync(record, info.relatedClass, field, info.propertyValue, computeDisplayValue); return { ruleset: info.ruleset, description }; @@ -101,7 +101,7 @@ interface PrimitiveValueDef { export type PrimitivePropertyValue = string | number | boolean | Point | InstanceKey | undefined; // eslint-disable-next-line @typescript-eslint/consistent-type-definitions -type Point = { x: number; y: number; z?: number }; +type Point = { x: number, y: number, z?: number }; const toString = (displayValue: string | undefined): string => { if (!displayValue) { @@ -261,7 +261,7 @@ const createSingleClassSpecification = (classInfo: Readonly): SingleS const createRelatedInstanceSpec = ( pathFromSelectToPropertyClass: RelationshipPath, index: number, -): { spec: RelatedInstanceSpecification; class: ClassInfo } => ({ +): { spec: RelatedInstanceSpecification, class: ClassInfo } => ({ spec: { relationshipPath: pathFromSelectToPropertyClass.map((step) => ({ relationship: createSingleClassSpecification(step.relationshipInfo), @@ -284,7 +284,7 @@ const createPathFromSelectToPropertyClass = (field: PropertiesField): Relationsh return RelationshipPath.reverse(pathFromPropertyToSelectClass); }; -const createRelatedInstanceSpecInfo = (field: PropertiesField): { spec: RelatedInstanceSpecification; class: ClassInfo } | undefined => { +const createRelatedInstanceSpecInfo = (field: PropertiesField): { spec: RelatedInstanceSpecification, class: ClassInfo } | undefined => { const path = createPathFromSelectToPropertyClass(field); return path.length ? createRelatedInstanceSpec(path, 0) : undefined; }; diff --git a/presentation/common/src/presentation-common/content/ContentTraverser.ts b/presentation/common/src/presentation-common/content/ContentTraverser.ts index 4cd594890847..71486919cbc3 100644 --- a/presentation/common/src/presentation-common/content/ContentTraverser.ts +++ b/presentation/common/src/presentation-common/content/ContentTraverser.ts @@ -7,6 +7,7 @@ */ import { assert, IDisposable, using } from "@itwin/core-bentley"; +import { LabelDefinition } from "../LabelDefinition"; import { CategoryDescription } from "./Category"; import { Content } from "./Content"; import { Descriptor } from "./Descriptor"; @@ -22,7 +23,6 @@ import { ValuesArray as PresentationValuesArray, ValuesMap as PresentationValuesMap, } from "./Value"; -import { LabelDefinition } from "../LabelDefinition"; const NESTED_CONTENT_LABEL_SYMBOL = Symbol(); @@ -717,7 +717,7 @@ function convertNestedContentItemToStructArrayItem(item: Readonly, field: return { emptyNestedItem: true, convertedItem: item }; } - const nextFieldValues: { raw: ValuesArray; display: DisplayValuesArray } = { raw: [], display: [] }; + const nextFieldValues: { raw: ValuesArray, display: DisplayValuesArray } = { raw: [], display: [] }; value.forEach((ncv) => { const nextRawValue = ncv.values[nextField.name]; const nextDisplayValue = ncv.displayValues[nextField.name]; diff --git a/presentation/common/src/presentation-common/content/Descriptor.ts b/presentation/common/src/presentation-common/content/Descriptor.ts index aaff848780df..acb41b13dedc 100644 --- a/presentation/common/src/presentation-common/content/Descriptor.ts +++ b/presentation/common/src/presentation-common/content/Descriptor.ts @@ -77,10 +77,10 @@ export namespace SelectClassInfo { : undefined), ...(json.pathFromInputToSelectClass ? { - pathFromInputToSelectClass: json.pathFromInputToSelectClass.map((item) => - RelatedClassInfoWithOptionalRelationship.fromCompressedJSON(item, classesMap), - ), - } + pathFromInputToSelectClass: json.pathFromInputToSelectClass.map((item) => + RelatedClassInfoWithOptionalRelationship.fromCompressedJSON(item, classesMap) + ), + } : undefined), ...(json.relatedPropertyPaths ? { relatedPropertyPaths: json.relatedPropertyPaths.map((path) => path.map((item) => RelatedClassInfo.fromCompressedJSON(item, classesMap))) } @@ -96,28 +96,30 @@ export namespace SelectClassInfo { selectClassInfo: id, isSelectPolymorphic: selectClass.isSelectPolymorphic, ...(selectClass.relatedInstancePaths - ? { relatedInstancePaths: selectClass.relatedInstancePaths.map((rip) => rip.map((item) => RelatedClassInfo.toCompressedJSON(item, classesMap))) } + ? { + relatedInstancePaths: selectClass.relatedInstancePaths.map((rip) => rip.map((item) => RelatedClassInfo.toCompressedJSON(item, classesMap))), + } : undefined), ...(selectClass.navigationPropertyClasses ? { - navigationPropertyClasses: selectClass.navigationPropertyClasses.map((propertyClass) => - RelatedClassInfo.toCompressedJSON(propertyClass, classesMap), - ), - } + navigationPropertyClasses: selectClass.navigationPropertyClasses.map((propertyClass) => + RelatedClassInfo.toCompressedJSON(propertyClass, classesMap) + ), + } : undefined), ...(selectClass.pathFromInputToSelectClass ? { - pathFromInputToSelectClass: selectClass.pathFromInputToSelectClass.map((item) => - RelatedClassInfoWithOptionalRelationship.toCompressedJSON(item, classesMap), - ), - } + pathFromInputToSelectClass: selectClass.pathFromInputToSelectClass.map((item) => + RelatedClassInfoWithOptionalRelationship.toCompressedJSON(item, classesMap) + ), + } : undefined), ...(selectClass.relatedPropertyPaths ? { - relatedPropertyPaths: selectClass.relatedPropertyPaths.map((path) => - path.map((relatedClass) => RelatedClassInfo.toCompressedJSON(relatedClass, classesMap)), - ), - } + relatedPropertyPaths: selectClass.relatedPropertyPaths.map((path) => + path.map((relatedClass) => RelatedClassInfo.toCompressedJSON(relatedClass, classesMap)) + ), + } : undefined), }; } @@ -129,7 +131,10 @@ export namespace SelectClassInfo { * * @internal */ - export function listFromCompressedJSON(json: SelectClassInfoJSON[], classesMap: { [id: string]: CompressedClassInfoJSON }): SelectClassInfo[] { + export function listFromCompressedJSON( + json: SelectClassInfoJSON[], + classesMap: { [id: string]: CompressedClassInfoJSON }, + ): SelectClassInfo[] { return json.map((sci) => fromCompressedJSON(sci, classesMap)); } } @@ -425,7 +430,9 @@ export class Descriptor implements DescriptorSource { /** Serialize [[Descriptor]] to JSON */ public toJSON(): DescriptorJSON { const classesMap: { [id: string]: CompressedClassInfoJSON } = {}; - const selectClasses: SelectClassInfoJSON[] = this.selectClasses.map((selectClass) => SelectClassInfo.toCompressedJSON(selectClass, classesMap)); + const selectClasses: SelectClassInfoJSON[] = this.selectClasses.map((selectClass) => + SelectClassInfo.toCompressedJSON(selectClass, classesMap) + ); const fields: FieldJSON[] = this.fields.map((field) => field.toCompressedJSON(classesMap)); return Object.assign( { diff --git a/presentation/common/src/presentation-common/content/Fields.ts b/presentation/common/src/presentation-common/content/Fields.ts index 45d004488ee8..c3f842f945c0 100644 --- a/presentation/common/src/presentation-common/content/Fields.ts +++ b/presentation/common/src/presentation-common/content/Fields.ts @@ -40,7 +40,7 @@ export interface BaseFieldJSON { priority: number; renderer?: RendererDescription; editor?: EditorDescription; - extendedData?: { [key: string]: unknown }; + extendedData?: { [key: string]: unknown }; } /** @@ -146,7 +146,7 @@ export class Field { /** Property editor used to edit values of this field */ public editor?: EditorDescription; /** Extended data associated with this field */ - public extendedData?: { [key: string]: unknown }; + public extendedData?: { [key: string]: unknown }; /** Parent field */ private _parent?: NestedContentField; @@ -171,7 +171,7 @@ export class Field { priority: number, editor?: EditorDescription, renderer?: RendererDescription, - extendedData?: { [key: string] : unknown } + extendedData?: { [key: string]: unknown }, ) { this.category = category; this.name = name; @@ -206,7 +206,17 @@ export class Field { } public clone() { - const clone = new Field(this.category, this.name, this.label, this.type, this.isReadonly, this.priority, this.editor, this.renderer, this.extendedData); + const clone = new Field( + this.category, + this.name, + this.label, + this.type, + this.isReadonly, + this.priority, + this.editor, + this.renderer, + this.extendedData, + ); clone.rebuildParentship(this.parent); return clone; } @@ -222,7 +232,7 @@ export class Field { priority: this.priority, renderer: this.renderer, editor: this.editor, - extendedData: this.extendedData + extendedData: this.extendedData, }; } @@ -465,7 +475,7 @@ export class PropertiesField extends Field { !this.properties.some(({ property: fieldProperty }) => descriptor.properties.some( (descriptorProperty) => fieldProperty.name === descriptorProperty.name && fieldProperty.classInfo.name === descriptorProperty.class, - ), + ) ) ) { return false; @@ -480,7 +490,9 @@ export class PropertiesField extends Field { if (descriptor.pathFromSelectToPropertyClass.length < stepsCount + 1) { return false; } - if (!RelatedClassInfo.equals(step, descriptor.pathFromSelectToPropertyClass[descriptor.pathFromSelectToPropertyClass.length - stepsCount - 1])) { + if ( + !RelatedClassInfo.equals(step, descriptor.pathFromSelectToPropertyClass[descriptor.pathFromSelectToPropertyClass.length - stepsCount - 1]) + ) { return false; } ++stepsCount; @@ -829,7 +841,10 @@ export class NestedContentField extends Field { } // eslint-disable-next-line deprecation/deprecation - private static fromCommonJSON(json: NestedContentFieldJSON, categories: CategoryDescription[]): Partial { + private static fromCommonJSON( + json: NestedContentFieldJSON, + categories: CategoryDescription[], + ): Partial { return { category: this.getCategoryFromFieldJson(json, categories), relationshipMeaning: json.relationshipMeaning ?? RelationshipMeaning.RelatedInstance, @@ -965,7 +980,10 @@ function fromCompressedPropertyJSON(compressedPropertyJSON: PropertyJSON }; } -function fromCompressedPropertyInfoJSON(compressedPropertyJSON: PropertyInfoJSON, classesMap: { [id: string]: CompressedClassInfoJSON }): PropertyInfo { +function fromCompressedPropertyInfoJSON( + compressedPropertyJSON: PropertyInfoJSON, + classesMap: { [id: string]: CompressedClassInfoJSON }, +): PropertyInfo { assert(classesMap.hasOwnProperty(compressedPropertyJSON.classInfo)); const { navigationPropertyInfo, ...leftOverPropertyJSON } = compressedPropertyJSON; @@ -973,6 +991,8 @@ function fromCompressedPropertyInfoJSON(compressedPropertyJSON: PropertyInfoJSON return { ...leftOverPropertyJSON, classInfo: { id: compressedPropertyJSON.classInfo, ...classesMap[compressedPropertyJSON.classInfo] }, - ...(navigationPropertyInfo ? { navigationPropertyInfo: NavigationPropertyInfo.fromCompressedJSON(navigationPropertyInfo, classesMap) } : undefined), + ...(navigationPropertyInfo + ? { navigationPropertyInfo: NavigationPropertyInfo.fromCompressedJSON(navigationPropertyInfo, classesMap) } + : undefined), }; } diff --git a/presentation/common/src/presentation-common/content/PropertyValueFormatter.ts b/presentation/common/src/presentation-common/content/PropertyValueFormatter.ts index 78fae6b4338d..95639cdb131b 100644 --- a/presentation/common/src/presentation-common/content/PropertyValueFormatter.ts +++ b/presentation/common/src/presentation-common/content/PropertyValueFormatter.ts @@ -39,7 +39,12 @@ export class ContentFormatter { ); } - private async formatValues(values: ValuesDictionary, displayValues: ValuesDictionary, fields: Field[], mergedFields: string[]) { + private async formatValues( + values: ValuesDictionary, + displayValues: ValuesDictionary, + fields: Field[], + mergedFields: string[], + ) { for (const field of fields) { const value = values[field.name]; @@ -106,13 +111,13 @@ export class ContentPropertyValueFormatter { public async formatPropertyValue(field: Field, value: Value, unitSystem?: UnitSystemKey): Promise { const doubleFormatter = isFieldWithKoq(field) ? async (rawValue: number) => { - const koq = field.properties[0].property.kindOfQuantity; - const formattedValue = await this._koqValueFormatter.format(rawValue, { koqName: koq.name, unitSystem }); - if (formattedValue !== undefined) { - return formattedValue; - } - return formatDouble(rawValue); + const koq = field.properties[0].property.kindOfQuantity; + const formattedValue = await this._koqValueFormatter.format(rawValue, { koqName: koq.name, unitSystem }); + if (formattedValue !== undefined) { + return formattedValue; } + return formatDouble(rawValue); + } : async (rawValue: number) => formatDouble(rawValue); return this.formatValue(field.type, value, { doubleFormatter }); @@ -206,11 +211,11 @@ function isFieldWithKoq(field: Field): field is FieldWithKoq { return field.isPropertiesField() && field.properties.length > 0 && field.properties[0].property.kindOfQuantity !== undefined; } -function isPoint2d(obj: Value): obj is { x: number; y: number } { +function isPoint2d(obj: Value): obj is { x: number, y: number } { return obj !== undefined && isNumber((obj as any).x) && isNumber((obj as any).y); } -function isPoint3d(obj: Value): obj is { x: number; y: number; z: number } { +function isPoint3d(obj: Value): obj is { x: number, y: number, z: number } { return isPoint2d(obj) && isNumber((obj as any).z); } diff --git a/presentation/common/src/presentation-common/content/Value.ts b/presentation/common/src/presentation-common/content/Value.ts index c38c4744286a..30a87eb75f38 100644 --- a/presentation/common/src/presentation-common/content/Value.ts +++ b/presentation/common/src/presentation-common/content/Value.ts @@ -376,7 +376,9 @@ function isArrayValue( return v !== undefined && Array.isArray(v); } // eslint-disable-next-line deprecation/deprecation -function isMapValue(v: Value | ValueJSON | DisplayValue | DisplayValueJSON): v is ValuesMap | ValuesMapJSON | DisplayValuesMap | DisplayValuesMapJSON { +function isMapValue( + v: Value | ValueJSON | DisplayValue | DisplayValueJSON, +): v is ValuesMap | ValuesMapJSON | DisplayValuesMap | DisplayValuesMapJSON { return v !== undefined && typeof v === "object" && !Array.isArray(v); } function isPrimitiveValue(v: Value | DisplayValue): v is string | number | boolean | undefined { diff --git a/presentation/common/src/presentation-common/hierarchy/Key.ts b/presentation/common/src/presentation-common/hierarchy/Key.ts index b0ffb9ad2dc2..c595891efbb4 100644 --- a/presentation/common/src/presentation-common/hierarchy/Key.ts +++ b/presentation/common/src/presentation-common/hierarchy/Key.ts @@ -306,7 +306,12 @@ export interface LabelGroupingNodeKeyJSON extends GroupingNodeKey { * @deprecated in 3.x. Use [[NodeKey]]. */ // eslint-disable-next-line deprecation/deprecation -export type NodeKeyJSON = BaseNodeKeyJSON | ECInstancesNodeKeyJSON | ECClassGroupingNodeKeyJSON | ECPropertyGroupingNodeKeyJSON | LabelGroupingNodeKeyJSON; +export type NodeKeyJSON = + | BaseNodeKeyJSON + | ECInstancesNodeKeyJSON + | ECClassGroupingNodeKeyJSON + | ECPropertyGroupingNodeKeyJSON + | LabelGroupingNodeKeyJSON; /** * Data structure that describes a presentation query diff --git a/presentation/common/src/presentation-common/rules/customization/InstanceLabelOverride.ts b/presentation/common/src/presentation-common/rules/customization/InstanceLabelOverride.ts index 797fe68fdd0e..2371823d8d1b 100644 --- a/presentation/common/src/presentation-common/rules/customization/InstanceLabelOverride.ts +++ b/presentation/common/src/presentation-common/rules/customization/InstanceLabelOverride.ts @@ -74,7 +74,7 @@ export interface InstanceLabelOverrideCompositeValueSpecification extends Instan * If any of the parts with `isRequired` flag evaluate to an empty string, the * result of this specification is also an empty string. */ - parts: Array<{ spec: InstanceLabelOverrideValueSpecification; isRequired?: boolean }>; + parts: Array<{ spec: InstanceLabelOverrideValueSpecification, isRequired?: boolean }>; /** Separator to use when joining the parts. Defaults to a space character. */ separator?: string; diff --git a/presentation/common/src/test/AsyncTasks.test.ts b/presentation/common/src/test/AsyncTasks.test.ts index 420394e451f8..07dc67976054 100644 --- a/presentation/common/src/test/AsyncTasks.test.ts +++ b/presentation/common/src/test/AsyncTasks.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { using } from "@itwin/core-bentley"; +import { expect } from "chai"; import { AsyncTasksTracker } from "../presentation-common"; describe("AsyncTasksTracker", () => { diff --git a/presentation/common/src/test/EC.test.ts b/presentation/common/src/test/EC.test.ts index 5224b826e2f5..f6c8fb50027c 100644 --- a/presentation/common/src/test/EC.test.ts +++ b/presentation/common/src/test/EC.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64, Id64String } from "@itwin/core-bentley"; +import { expect } from "chai"; import { InstanceKey, RelationshipPath } from "../presentation-common"; import { RelatedClassInfo, diff --git a/presentation/common/src/test/ElementProperties.test.ts b/presentation/common/src/test/ElementProperties.test.ts index 9ce0ca461d14..a395d703707c 100644 --- a/presentation/common/src/test/ElementProperties.test.ts +++ b/presentation/common/src/test/ElementProperties.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { Id64 } from "@itwin/core-bentley"; +import { expect } from "chai"; import { PropertyValueFormat } from "../presentation-common/content/TypeDescription"; import { buildElementProperties } from "../presentation-common/ElementProperties"; import { @@ -82,7 +82,6 @@ describe("buildElementProperties", () => { createTestSimpleContentField({ name: "prop2", label: "Prop Two", category: childCategory }), ], }), - createTestContentItem({ values: { prop1: "value1", @@ -133,7 +132,6 @@ describe("buildElementProperties", () => { createTestSimpleContentField({ name: "prop", label: "Prop", category }), ], }), - createTestContentItem({ values: { emptyProp: undefined, @@ -179,9 +177,10 @@ describe("buildElementProperties", () => { buildElementProperties( createTestContentDescriptor({ categories: [category], - fields: [createTestNestedContentField({ name: "nestedField", category, nestedFields: [createTestSimpleContentField({ name: "primitiveField" })] })], + fields: [ + createTestNestedContentField({ name: "nestedField", category, nestedFields: [createTestSimpleContentField({ name: "primitiveField" })] }), + ], }), - createTestContentItem({ values: { nestedField: [], @@ -207,7 +206,6 @@ describe("buildElementProperties", () => { categories: [category], fields: [createTestSimpleContentField({ name: "prop", label: "Prop", category })], }), - createTestContentItem({ values: { prop: "anything", @@ -272,7 +270,6 @@ describe("buildElementProperties", () => { }), ], }), - createTestContentItem({ values: { prop: { @@ -337,7 +334,6 @@ describe("buildElementProperties", () => { }), ], }), - createTestContentItem({ values: { prop: ["value1", "value2"], diff --git a/presentation/common/src/test/KeySet.test.ts b/presentation/common/src/test/KeySet.test.ts index 4d70083d5e04..cca1235c9d4d 100644 --- a/presentation/common/src/test/KeySet.test.ts +++ b/presentation/common/src/test/KeySet.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Guid, Id64 } from "@itwin/core-bentley"; import { expect } from "chai"; import * as sinon from "sinon"; -import { Guid, Id64 } from "@itwin/core-bentley"; import { InstanceKey, Key, KeySet, KeySetJSON, PresentationError } from "../presentation-common"; import { createTestECInstanceKey } from "./_helpers/EC"; import { diff --git a/presentation/common/src/test/KoqPropertyValueFormatter.test.ts b/presentation/common/src/test/KoqPropertyValueFormatter.test.ts index 1064ba24c603..301931c62f80 100644 --- a/presentation/common/src/test/KoqPropertyValueFormatter.test.ts +++ b/presentation/common/src/test/KoqPropertyValueFormatter.test.ts @@ -3,7 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { KindOfQuantityProps, PhenomenonProps, @@ -15,6 +14,7 @@ import { SchemaProps, UnitSystemProps, } from "@itwin/ecschema-metadata"; +import { expect } from "chai"; import { KoqPropertyValueFormatter } from "../presentation-common/KoqPropertyValueFormatter"; describe("KoqPropertyValueFormatter", () => { diff --git a/presentation/common/src/test/LocalizationHelper.test.ts b/presentation/common/src/test/LocalizationHelper.test.ts index 931238b2eb0d..ebbc7db9abe2 100644 --- a/presentation/common/src/test/LocalizationHelper.test.ts +++ b/presentation/common/src/test/LocalizationHelper.test.ts @@ -339,7 +339,12 @@ describe("LocalizationHelper", () => { }); it("translates element properties label", () => { - const elementProperties = localizationHelper.getLocalizedElementProperties({ class: "class", label: "@namespace:LocalizedLabel@", id: "id", items: {} }); + const elementProperties = localizationHelper.getLocalizedElementProperties({ + class: "class", + label: "@namespace:LocalizedLabel@", + id: "id", + items: {}, + }); expect(elementProperties.label).to.be.eq("LocalizedLabel"); }); }); diff --git a/presentation/common/src/test/PresentationRpcInterface.test.ts b/presentation/common/src/test/PresentationRpcInterface.test.ts index 80c0619c6e20..e9b60a2666de 100644 --- a/presentation/common/src/test/PresentationRpcInterface.test.ts +++ b/presentation/common/src/test/PresentationRpcInterface.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Id64String, using } from "@itwin/core-bentley"; +import { IModelRpcProps, RpcOperation, RpcRegistry, RpcRequest, RpcSerializedValue } from "@itwin/core-common"; import { expect } from "chai"; import * as faker from "faker"; import * as sinon from "sinon"; -import { Id64String, using } from "@itwin/core-bentley"; -import { IModelRpcProps, RpcOperation, RpcRegistry, RpcRequest, RpcSerializedValue } from "@itwin/core-common"; import { ContentDescriptorRpcRequestOptions, ContentRpcRequestOptions, diff --git a/presentation/common/src/test/RpcRequestsHandler.test.ts b/presentation/common/src/test/RpcRequestsHandler.test.ts index 2ba6c1089965..e016d6ca7961 100644 --- a/presentation/common/src/test/RpcRequestsHandler.test.ts +++ b/presentation/common/src/test/RpcRequestsHandler.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Id64, Logger } from "@itwin/core-bentley"; +import { IModelRpcProps, RpcInterface, RpcInterfaceDefinition, RpcManager } from "@itwin/core-common"; import { expect } from "chai"; import * as faker from "faker"; import * as sinon from "sinon"; import * as moq from "typemoq"; -import { Id64, Logger } from "@itwin/core-bentley"; -import { IModelRpcProps, RpcInterface, RpcInterfaceDefinition, RpcManager } from "@itwin/core-common"; import { DescriptorOverrides, DistinctValuesRpcRequestOptions, @@ -121,7 +121,10 @@ describe("RpcRequestsHandler", () => { handler: sinon.spy(), }; const diagnosticsResult: ClientDiagnostics = {}; - await handler.request(async () => successResponse(result, diagnosticsResult), { ...defaultRpcHandlerOptions, diagnostics: diagnosticsOptions }); + await handler.request(async () => successResponse(result, diagnosticsResult), { + ...defaultRpcHandlerOptions, + diagnostics: diagnosticsOptions, + }); expect(diagnosticsOptions.handler).to.be.calledOnceWith(diagnosticsResult); }); @@ -171,7 +174,9 @@ describe("RpcRequestsHandler", () => { }; const diagnosticsResult: ClientDiagnostics = {}; const func = sinon.fake(async () => errorResponse(PresentationStatus.Error, undefined, diagnosticsResult)); - await expect(handler.request(func, { ...defaultRpcHandlerOptions, diagnostics: diagnosticsOptions })).to.eventually.be.rejectedWith(PresentationError); + await expect(handler.request(func, { ...defaultRpcHandlerOptions, diagnostics: diagnosticsOptions })).to.eventually.be.rejectedWith( + PresentationError, + ); expect(diagnosticsOptions.handler).to.be.calledOnceWith(diagnosticsResult); }); }); diff --git a/presentation/common/src/test/RulesetVariable.test.ts b/presentation/common/src/test/RulesetVariable.test.ts index 94a43977a99a..61730539b7d4 100644 --- a/presentation/common/src/test/RulesetVariable.test.ts +++ b/presentation/common/src/test/RulesetVariable.test.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { CompressedId64Set, OrderedId64Iterable } from "@itwin/core-bentley"; +import { expect } from "chai"; import { BooleanRulesetVariable, BooleanRulesetVariableJSON, diff --git a/presentation/common/src/test/RulesetsFactory.test.ts b/presentation/common/src/test/RulesetsFactory.test.ts index 74eebb3aa635..4269cd4b7bfb 100644 --- a/presentation/common/src/test/RulesetsFactory.test.ts +++ b/presentation/common/src/test/RulesetsFactory.test.ts @@ -88,7 +88,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [ + property, + ]); const record = new Item( [], faker.random.word(), @@ -129,7 +131,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createBooleanTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createBooleanTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: true }, { ["MyProperty"]: "True" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -162,7 +166,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createBooleanTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createBooleanTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: false }, { ["MyProperty"]: "False" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -195,7 +201,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createIntTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createIntTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: 123 }, { ["MyProperty"]: "123" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -228,7 +236,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createDoubleTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createDoubleTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: 123.456 }, { ["MyProperty"]: "123.46" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -261,7 +271,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createDateTimeTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createDateTimeTypeDescription(), true, 1, [ + property, + ]); const record = new Item( [], faker.random.word(), @@ -302,7 +314,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: { x: 1, y: 2 } }, { ["MyProperty"]: "1, 2" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -335,7 +349,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: { x: 0, y: 0 } }, { ["MyProperty"]: "0, 0" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -368,7 +384,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint3dTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint3dTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: { x: 1, y: 2, z: 3 } }, { ["MyProperty"]: "1, 2, 3" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -379,7 +397,8 @@ describe("RulesetsFactory", () => { specType: ContentSpecificationTypes.ContentInstancesOfSpecificClasses, classes: { schemaName: "MySchema", classNames: ["MyClass"], arePolymorphic: true }, relatedInstances: [], - instanceFilter: `CompareDoubles(this.MyProperty.x, 1) = 0 AND CompareDoubles(this.MyProperty.y, 2) = 0 AND CompareDoubles(this.MyProperty.z, 3) = 0`, + instanceFilter: + `CompareDoubles(this.MyProperty.x, 1) = 0 AND CompareDoubles(this.MyProperty.y, 2) = 0 AND CompareDoubles(this.MyProperty.z, 3) = 0`, }, ], }, @@ -401,7 +420,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint3dTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint3dTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: { x: 1, y: 2, z: 0 } }, { ["MyProperty"]: "1, 2, 0" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -412,7 +433,8 @@ describe("RulesetsFactory", () => { specType: ContentSpecificationTypes.ContentInstancesOfSpecificClasses, classes: { schemaName: "MySchema", classNames: ["MyClass"], arePolymorphic: true }, relatedInstances: [], - instanceFilter: `CompareDoubles(this.MyProperty.x, 1) = 0 AND CompareDoubles(this.MyProperty.y, 2) = 0 AND CompareDoubles(this.MyProperty.z, 0) = 0`, + instanceFilter: + `CompareDoubles(this.MyProperty.x, 1) = 0 AND CompareDoubles(this.MyProperty.y, 2) = 0 AND CompareDoubles(this.MyProperty.z, 0) = 0`, }, ], }, @@ -434,7 +456,9 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [ + property, + ]); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: undefined }, { ["MyProperty"]: "" }, []); const result = await factory.createSimilarInstancesRuleset(field, record); const expectedRules: Rule[] = [ @@ -467,9 +491,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createNavigationPropertyTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + "MyProperty", + "My Property", + createNavigationPropertyTypeDescription(), + true, + 1, + [ + property, + ], + ); const record = new Item( [], faker.random.word(), @@ -529,9 +561,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), "Related Property", createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + "Related Property", + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), @@ -626,9 +666,17 @@ describe("RulesetsFactory", () => { name: "RelatedProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), "Related Property", createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + "Related Property", + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), @@ -740,9 +788,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), "Related Property", createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + "Related Property", + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), @@ -823,8 +879,18 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [property]); - const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test display value" }, []); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [ + property, + ]); + const record = new Item( + [], + faker.random.word(), + "", + recordClass, + { ["MyProperty"]: "test value" }, + { ["MyProperty"]: "test display value" }, + [], + ); const callback = sinon.fake(async () => "TEST"); const result = await factory.createSimilarInstancesRuleset(field, record, callback); expect(callback).to.be.calledOnceWithExactly(field.type.typeName, "test value", "test display value"); @@ -844,8 +910,18 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [property]); - const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test display value" }, []); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createStringTypeDescription(), true, 1, [ + property, + ]); + const record = new Item( + [], + faker.random.word(), + "", + recordClass, + { ["MyProperty"]: "test value" }, + { ["MyProperty"]: "test display value" }, + [], + ); const result = await factory.createSimilarInstancesRuleset(field, record); expect(result.description).to.eq(`[My Class].[My Property] = test display value`); }); @@ -865,9 +941,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", faker.random.word(), createBooleanTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + "MyProperty", + faker.random.word(), + createBooleanTypeDescription(), + true, + 1, + [ + property, + ], + ); const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: invalidValue }, { ["MyProperty"]: "" }, []); await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith( "Can only create 'similar instances' ruleset for primitive values", @@ -881,9 +965,27 @@ describe("RulesetsFactory", () => { name: "MySchema:MyClass", label: "My Class", }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", faker.random.word(), createBooleanTypeDescription(), true, 1, []); - const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test display value" }, []); - await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith("Invalid properties' field with no properties"); + const field = new PropertiesField( + createTestCategoryDescription(), + "MyProperty", + faker.random.word(), + createBooleanTypeDescription(), + true, + 1, + [], + ); + const record = new Item( + [], + faker.random.word(), + "", + recordClass, + { ["MyProperty"]: "test value" }, + { ["MyProperty"]: "test display value" }, + [], + ); + await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith( + "Invalid properties' field with no properties", + ); }); it("throws when nested content record contains invalid value", async () => { @@ -918,9 +1020,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + faker.random.word(), + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), @@ -958,9 +1068,21 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [property]); - const record = new Item([], faker.random.word(), "", recordClass, { ["MyProperty"]: "should be {x,y} object" }, { ["MyProperty"]: "1, 2" }, []); - await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith("Expecting point values to be supplied as objects"); + const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", "My Property", createPoint2dTypeDescription(), true, 1, [ + property, + ]); + const record = new Item( + [], + faker.random.word(), + "", + recordClass, + { ["MyProperty"]: "should be {x,y} object" }, + { ["MyProperty"]: "1, 2" }, + [], + ); + await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith( + "Expecting point values to be supplied as objects", + ); }); }); @@ -986,7 +1108,9 @@ describe("RulesetsFactory", () => { typeName: faker.random.word(), memberType: createStringTypeDescription(), }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), typeDescription, true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), typeDescription, true, 1, [ + property, + ]); const values = { [field.name]: ["some value 1", "some value 2"], }; @@ -1018,7 +1142,9 @@ describe("RulesetsFactory", () => { }, ], }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), typeDescription, true, 1, [property]); + const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), typeDescription, true, 1, [ + property, + ]); const values = { [field.name]: { [typeDescription.members[0].name]: "some value", @@ -1047,10 +1173,20 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", faker.random.word(), createStringTypeDescription(), true, 1, [ - property, + const field = new PropertiesField( + createTestCategoryDescription(), + "MyProperty", + faker.random.word(), + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); + const record = new Item([], faker.random.word(), "", undefined, { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test value" }, [ + "MyProperty", ]); - const record = new Item([], faker.random.word(), "", undefined, { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test value" }, ["MyProperty"]); await expect(factory.createSimilarInstancesRuleset(field, record)).to.eventually.be.rejectedWith( "Can't create 'similar instances' ruleset for merged values", ); @@ -1068,14 +1204,22 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), "MyProperty", faker.random.word(), createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + "MyProperty", + faker.random.word(), + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const record = new Item( [], faker.random.word(), "", - undefined /* this `undefined` means that record is based on multiple different classes */, + undefined, /* this `undefined` means that record is based on multiple different classes */ { ["MyProperty"]: "test value" }, { ["MyProperty"]: "test display value" }, [], @@ -1117,9 +1261,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + faker.random.word(), + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), @@ -1197,9 +1349,17 @@ describe("RulesetsFactory", () => { name: "MyProperty", }, }; - const field = new PropertiesField(createTestCategoryDescription(), faker.random.word(), faker.random.word(), createStringTypeDescription(), true, 1, [ - property, - ]); + const field = new PropertiesField( + createTestCategoryDescription(), + faker.random.word(), + faker.random.word(), + createStringTypeDescription(), + true, + 1, + [ + property, + ], + ); const parentField = new NestedContentField( createTestCategoryDescription(), faker.random.word(), diff --git a/presentation/common/src/test/_helpers/Content.ts b/presentation/common/src/test/_helpers/Content.ts index 514ea4701481..34b85c294b1d 100644 --- a/presentation/common/src/test/_helpers/Content.ts +++ b/presentation/common/src/test/_helpers/Content.ts @@ -178,7 +178,8 @@ export function createTestStructPropertiesContentField(props: { }, ], }, - props.memberFields ?? [createTestPropertiesContentField({ properties: [{ property: createTestPropertyInfo({ name: "member1", type: "string" }) }] })], + props.memberFields ?? + [createTestPropertiesContentField({ properties: [{ property: createTestPropertyInfo({ name: "member1", type: "string" }) }] })], props.isReadonly ?? false, props.priority ?? 0, props.properties, diff --git a/presentation/common/src/test/_helpers/random/IModelJs.ts b/presentation/common/src/test/_helpers/random/IModelJs.ts index 4eaaaa2dc91a..176fb2de9d70 100644 --- a/presentation/common/src/test/_helpers/random/IModelJs.ts +++ b/presentation/common/src/test/_helpers/random/IModelJs.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as faker from "faker"; import { Id64 } from "@itwin/core-bentley"; import { EntityProps } from "@itwin/core-common"; +import * as faker from "faker"; import { createRandomId } from "./Misc"; interface RandomEntityProps extends EntityProps { diff --git a/presentation/common/src/test/_helpers/random/Misc.ts b/presentation/common/src/test/_helpers/random/Misc.ts index c60e12825c2a..98f95c441165 100644 --- a/presentation/common/src/test/_helpers/random/Misc.ts +++ b/presentation/common/src/test/_helpers/random/Misc.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as faker from "faker"; import { Id64, Id64String } from "@itwin/core-bentley"; +import * as faker from "faker"; /** * @internal Used for testing only. diff --git a/presentation/common/src/test/content/ContentTraverser.test.ts b/presentation/common/src/test/content/ContentTraverser.test.ts index 63b9d04e1052..ddc9becde6e3 100644 --- a/presentation/common/src/test/content/ContentTraverser.test.ts +++ b/presentation/common/src/test/content/ContentTraverser.test.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import * as sinon from "sinon"; +import { NestedContentValue } from "../../presentation-common"; import { Content } from "../../presentation-common/content/Content"; import { addFieldHierarchy, @@ -35,7 +36,6 @@ import { createTestSimpleContentField, } from "../_helpers/Content"; import { createTestECInstanceKey } from "../_helpers/EC"; -import { NestedContentValue } from "../../presentation-common"; describe("ContentTraverser", () => { class TestContentVisitor implements IContentVisitor { @@ -565,7 +565,7 @@ describe("ContentTraverser", () => { ], }, parentFieldName: undefined, - }), + }) ); expect(processPrimitiveValueSpy.callCount).to.eq(4); expect(processPrimitiveValueSpy.getCall(0).firstArg).to.containSubset({ @@ -824,7 +824,7 @@ describe("ContentTraverser", () => { ], }, parentFieldName: parentField.name, - }), + }) ); expect(processPrimitiveValueSpy.callCount).to.eq(2); expect(processPrimitiveValueSpy.getCall(0).firstArg).to.containSubset({ @@ -985,7 +985,7 @@ describe("ContentTraverser", () => { }, }, parentFieldName: parentField.name, - }), + }) ); expect(startStructSpy.callCount).to.eq(4); [startStructSpy.getCall(0), startStructSpy.getCall(2)].forEach((call) => @@ -1029,7 +1029,7 @@ describe("ContentTraverser", () => { ], }, parentFieldName: undefined, - }), + }) ); [startStructSpy.getCall(1), startStructSpy.getCall(3)].forEach((call) => expect(call.firstArg).to.containSubset({ @@ -1053,7 +1053,7 @@ describe("ContentTraverser", () => { ], }, parentFieldName: parentField.name, - }), + }) ); expect(processPrimitiveValueSpy.callCount).to.eq(2); expect(processPrimitiveValueSpy.firstCall.firstArg).to.containSubset({ diff --git a/presentation/common/src/test/content/Descriptor.test.ts b/presentation/common/src/test/content/Descriptor.test.ts index 159f8350a7ba..20a82aea447b 100644 --- a/presentation/common/src/test/content/Descriptor.test.ts +++ b/presentation/common/src/test/content/Descriptor.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { Id64String } from "@itwin/core-bentley"; import { expect } from "chai"; import * as faker from "faker"; -import { Id64String } from "@itwin/core-bentley"; import { CategoryDescription } from "../../presentation-common/content/Category"; import { Descriptor, diff --git a/presentation/common/src/test/content/Item.test.ts b/presentation/common/src/test/content/Item.test.ts index 69639b546035..ae790e30b786 100644 --- a/presentation/common/src/test/content/Item.test.ts +++ b/presentation/common/src/test/content/Item.test.ts @@ -6,9 +6,9 @@ import { expect } from "chai"; import * as faker from "faker"; import { Item, ItemJSON } from "../../presentation-common/content/Item"; import { NestedContentValueJSON } from "../../presentation-common/content/Value"; +import { createTestContentItem } from "../_helpers"; import { createTestECInstanceKey } from "../_helpers/EC"; import { createRandomECClassInfo, createRandomECInstanceKey, createRandomLabelDefinition } from "../_helpers/random"; -import { createTestContentItem } from "../_helpers"; describe("Item", () => { describe("constructor", () => { @@ -18,7 +18,9 @@ describe("Item", () => { }); it("creates valid item with label definition", () => { - const item = new Item([], createRandomLabelDefinition(), faker.random.uuid(), undefined, { key: faker.random.word() }, { key: faker.random.word() }, []); + const item = new Item([], createRandomLabelDefinition(), faker.random.uuid(), undefined, { key: faker.random.word() }, { + key: faker.random.word(), + }, []); expect(item).to.matchSnapshot(); }); }); @@ -136,7 +138,9 @@ describe("Item", () => { }); it("returns true for merged field", () => { - const item = new Item([], faker.random.word(), faker.random.uuid(), undefined, { key: faker.random.word() }, { key: faker.random.word() }, ["key"]); + const item = new Item([], faker.random.word(), faker.random.uuid(), undefined, { key: faker.random.word() }, { key: faker.random.word() }, [ + "key", + ]); expect(item.isFieldMerged("key")).to.be.true; }); }); diff --git a/presentation/common/src/test/content/PropertyFormatter.test.ts b/presentation/common/src/test/content/PropertyFormatter.test.ts index d14f298e9261..140f58fd6d4b 100644 --- a/presentation/common/src/test/content/PropertyFormatter.test.ts +++ b/presentation/common/src/test/content/PropertyFormatter.test.ts @@ -357,7 +357,11 @@ describe("ContentPropertyValueFormatter", () => { valueFormat: PropertyValueFormat.Struct, typeName: "struct", members: [ - { name: "nestedDoubleProp", label: "Nested Double Property", type: { valueFormat: PropertyValueFormat.Primitive, typeName: "double" } }, + { + name: "nestedDoubleProp", + label: "Nested Double Property", + type: { valueFormat: PropertyValueFormat.Primitive, typeName: "double" }, + }, { name: "nestedIntProp", label: "Nested Int Property", type: { valueFormat: PropertyValueFormat.Primitive, typeName: "int" } }, ], }, diff --git a/presentation/common/tsconfig.cjs.json b/presentation/common/tsconfig.cjs.json index e68ca31df566..0be0cdc88fae 100644 --- a/presentation/common/tsconfig.cjs.json +++ b/presentation/common/tsconfig.cjs.json @@ -2,5 +2,5 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "lib/cjs" - }, -} \ No newline at end of file + } +} diff --git a/presentation/common/tsconfig.esm.json b/presentation/common/tsconfig.esm.json index 0377d56a6a36..550a66645264 100644 --- a/presentation/common/tsconfig.esm.json +++ b/presentation/common/tsconfig.esm.json @@ -2,6 +2,6 @@ "extends": "./tsconfig.json", "compilerOptions": { "module": "ES2020", - "outDir": "lib/esm", - }, -} \ No newline at end of file + "outDir": "lib/esm" + } +} diff --git a/presentation/frontend/src/presentation-frontend/ConnectivityInformationProvider.ts b/presentation/frontend/src/presentation-frontend/ConnectivityInformationProvider.ts index 943dd8112797..64168791ce49 100644 --- a/presentation/frontend/src/presentation-frontend/ConnectivityInformationProvider.ts +++ b/presentation/frontend/src/presentation-frontend/ConnectivityInformationProvider.ts @@ -29,7 +29,9 @@ export class ConnectivityInformationProvider implements IConnectivityInformation public constructor() { if (NativeApp.isValid) { - this._unsubscribeFromInternetConnectivityChangedEvent = NativeApp.onInternetConnectivityChanged.addListener(this.onNativeAppInternetConnectivityChanged); + this._unsubscribeFromInternetConnectivityChangedEvent = NativeApp.onInternetConnectivityChanged.addListener( + this.onNativeAppInternetConnectivityChanged, + ); // eslint-disable-next-line @typescript-eslint/no-floating-promises NativeApp.checkInternetConnectivity().then((status: InternetConnectivityStatus) => { if (undefined === this._currentStatus) { diff --git a/presentation/frontend/src/presentation-frontend/Presentation.ts b/presentation/frontend/src/presentation-frontend/Presentation.ts index a4525096f85f..65b69847d3f7 100644 --- a/presentation/frontend/src/presentation-frontend/Presentation.ts +++ b/presentation/frontend/src/presentation-frontend/Presentation.ts @@ -6,8 +6,8 @@ * @module Core */ -import { IModelApp } from "@itwin/core-frontend"; import { Localization } from "@itwin/core-common"; +import { IModelApp } from "@itwin/core-frontend"; import { PresentationError, PresentationStatus } from "@itwin/presentation-common"; import { FavoritePropertiesManager, FavoritePropertiesManagerProps } from "./favorite-properties/FavoritePropertiesManager"; import { createFavoritePropertiesStorage, DefaultFavoritePropertiesStorageTypes } from "./favorite-properties/FavoritePropertiesStorage"; @@ -79,8 +79,7 @@ export class Presentation { if (!selectionManager) { selectionManager = new SelectionManager({ ...props?.selection, - scopes: - props?.selection?.scopes ?? + scopes: props?.selection?.scopes ?? new SelectionScopesManager({ rpcRequestsHandler: presentationManager.rpcRequestsHandler, localeProvider: () => this.presentation.activeLocale, diff --git a/presentation/frontend/src/presentation-frontend/PresentationManager.ts b/presentation/frontend/src/presentation-frontend/PresentationManager.ts index 205c0cd9d722..7653c41802ae 100644 --- a/presentation/frontend/src/presentation-frontend/PresentationManager.ts +++ b/presentation/frontend/src/presentation-frontend/PresentationManager.ts @@ -120,15 +120,17 @@ export type GetNodesRequestOptions = HierarchyRequestOptions & - ClientDiagnosticsAttribute; +export type GetContentRequestOptions = + & ContentRequestOptions + & ClientDiagnosticsAttribute; /** * Options for requests that retrieve distinct values. * @public */ -export type GetDistinctValuesRequestOptions = DistinctValuesRequestOptions & - ClientDiagnosticsAttribute; +export type GetDistinctValuesRequestOptions = + & DistinctValuesRequestOptions + & ClientDiagnosticsAttribute; /** * Properties used to configure [[PresentationManager]] @@ -236,8 +238,8 @@ export class PresentationManager implements IDisposable { this._explicitActiveUnitSystem = props.activeUnitSystem; } - this._requestsHandler = - props?.rpcRequestsHandler ?? new RpcRequestsHandler(props ? { clientId: props.clientId, timeout: props.requestTimeout } : undefined); + this._requestsHandler = props?.rpcRequestsHandler ?? + new RpcRequestsHandler(props ? { clientId: props.clientId, timeout: props.requestTimeout } : undefined); this._rulesetVars = new Map(); this._rulesets = RulesetManagerImpl.create(); this._localizationHelper = new FrontendLocalizationHelper(props?.activeLocale); @@ -348,7 +350,9 @@ export class PresentationManager implements IDisposable { return this._rulesetVars.get(rulesetId)!; } - private toRpcTokenOptions( + private toRpcTokenOptions< + TOptions extends { imodel: IModelConnection, locale?: string, unitSystem?: UnitSystemKey, rulesetVariables?: RulesetVariable[] }, + >( requestOptions: TOptions, ) { // 1. put default `locale` and `unitSystem` @@ -369,7 +373,9 @@ export class PresentationManager implements IDisposable { }; } - private async addRulesetAndVariablesToOptions(options: TOptions) { + private async addRulesetAndVariablesToOptions( + options: TOptions, + ) { const { rulesetOrId, rulesetVariables } = options; let foundRulesetOrId: Ruleset | string; if (typeof rulesetOrId === "object") { @@ -401,7 +407,7 @@ export class PresentationManager implements IDisposable { /** Returns an iterator that polls nodes asynchronously. */ public async getNodesIterator( requestOptions: GetNodesRequestOptions & MultipleValuesRequestOptions, - ): Promise<{ total: number; items: AsyncIterableIterator }> { + ): Promise<{ total: number, items: AsyncIterableIterator }> { this.startIModelInitialization(requestOptions.imodel); const options = await this.addRulesetAndVariablesToOptions(requestOptions); const rpcOptions = this.toRpcTokenOptions({ ...options }); @@ -442,7 +448,7 @@ export class PresentationManager implements IDisposable { * Retrieves total nodes count and a single page of nodes. * @deprecated in 4.5. Use [[getNodesIterator]] instead. */ - public async getNodesAndCount(requestOptions: GetNodesRequestOptions & MultipleValuesRequestOptions): Promise<{ count: number; nodes: Node[] }> { + public async getNodesAndCount(requestOptions: GetNodesRequestOptions & MultipleValuesRequestOptions): Promise<{ count: number, nodes: Node[] }> { const result = await this.getNodesIterator(requestOptions); return { count: result.total, @@ -497,7 +503,9 @@ export class PresentationManager implements IDisposable { * its related instances for loading related and navigation properties. * @public */ - public async getContentSources(requestOptions: ContentSourcesRequestOptions & ClientDiagnosticsAttribute): Promise { + public async getContentSources( + requestOptions: ContentSourcesRequestOptions & ClientDiagnosticsAttribute, + ): Promise { this.startIModelInitialization(requestOptions.imodel); const rpcOptions = this.toRpcTokenOptions(requestOptions); const result = await this._requestsHandler.getContentSources(rpcOptions); @@ -537,7 +545,7 @@ export class PresentationManager implements IDisposable { private async getContentIteratorInternal( requestOptions: GetContentRequestOptions & MultipleValuesRequestOptions, - ): Promise<{ descriptor: Descriptor; total: number; items: AsyncIterableIterator } | undefined> { + ): Promise<{ descriptor: Descriptor, total: number, items: AsyncIterableIterator } | undefined> { const options = await this.addRulesetAndVariablesToOptions(requestOptions); const firstPageSize = options.batchSize ?? requestOptions.paging?.size; const rpcOptions = this.toRpcTokenOptions({ @@ -605,7 +613,7 @@ export class PresentationManager implements IDisposable { /** Retrieves a content descriptor, item count and async generator for the items themselves. */ public async getContentIterator( requestOptions: GetContentRequestOptions & MultipleValuesRequestOptions, - ): Promise<{ descriptor: Descriptor; total: number; items: AsyncIterableIterator } | undefined> { + ): Promise<{ descriptor: Descriptor, total: number, items: AsyncIterableIterator } | undefined> { this.startIModelInitialization(requestOptions.imodel); const response = await this.getContentIteratorInternal(requestOptions); if (!response) { @@ -631,7 +639,7 @@ export class PresentationManager implements IDisposable { */ public async getContentAndSize( requestOptions: GetContentRequestOptions & MultipleValuesRequestOptions, - ): Promise<{ content: Content; size: number } | undefined> { + ): Promise<{ content: Content, size: number } | undefined> { const response = await this.getContentIterator(requestOptions); if (!response) { return undefined; @@ -648,7 +656,7 @@ export class PresentationManager implements IDisposable { /** Returns an iterator that asynchronously polls distinct values of specific field from the content. */ public async getDistinctValuesIterator( requestOptions: GetDistinctValuesRequestOptions & MultipleValuesRequestOptions, - ): Promise<{ total: number; items: AsyncIterableIterator }> { + ): Promise<{ total: number, items: AsyncIterableIterator }> { this.startIModelInitialization(requestOptions.imodel); const options = await this.addRulesetAndVariablesToOptions(requestOptions); const rpcOptions = { @@ -717,8 +725,11 @@ export class PresentationManager implements IDisposable { * @public */ public async getContentInstanceKeys( - requestOptions: ContentInstanceKeysRequestOptions & ClientDiagnosticsAttribute & MultipleValuesRequestOptions, - ): Promise<{ total: number; items: () => AsyncGenerator }> { + requestOptions: + & ContentInstanceKeysRequestOptions + & ClientDiagnosticsAttribute + & MultipleValuesRequestOptions, + ): Promise<{ total: number, items: () => AsyncGenerator }> { this.startIModelInitialization(requestOptions.imodel); const options = await this.addRulesetAndVariablesToOptions(requestOptions); const rpcOptions = { @@ -764,7 +775,7 @@ export class PresentationManager implements IDisposable { /** Retrieves display label definition of specific items. */ public async getDisplayLabelDefinitionsIterator( requestOptions: DisplayLabelsRequestOptions & ClientDiagnosticsAttribute & MultipleValuesRequestOptions, - ): Promise<{ total: number; items: AsyncIterableIterator }> { + ): Promise<{ total: number, items: AsyncIterableIterator }> { this.startIModelInitialization(requestOptions.imodel); const rpcOptions = this.toRpcTokenOptions({ ...requestOptions }); const generator = new StreamedResponseGenerator({ @@ -809,8 +820,7 @@ const stripTransientElementKeys = (keys: KeySet) => { // the callback is not going to be called with EntityProps as KeySet converts them // to InstanceKeys, but we want to keep the EntityProps case for correctness // istanbul ignore next - const isTransient = - (Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME) || + const isTransient = (Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME) || (Key.isEntityProps(key) && key.classFullName === TRANSIENT_ELEMENT_CLASSNAME); return !isTransient; }); diff --git a/presentation/frontend/src/presentation-frontend/StreamedResponseGenerator.ts b/presentation/frontend/src/presentation-frontend/StreamedResponseGenerator.ts index 1f16df32db8d..0d5531819ca7 100644 --- a/presentation/frontend/src/presentation-frontend/StreamedResponseGenerator.ts +++ b/presentation/frontend/src/presentation-frontend/StreamedResponseGenerator.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { concat, concatAll, map, mergeMap, Observable, of, range, scan } from "rxjs"; -import { eachValueFrom } from "rxjs-for-await"; import { SortedArray } from "@itwin/core-bentley"; import { PagedResponse, PageOptions } from "@itwin/presentation-common"; +import { concat, concatAll, map, mergeMap, Observable, of, range, scan } from "rxjs"; +import { eachValueFrom } from "rxjs-for-await"; import { MultipleValuesRequestOptions } from "./PresentationManager"; /** @@ -26,7 +26,7 @@ export class StreamedResponseGenerator { constructor(private readonly _props: StreamedResponseGeneratorProps) {} /** Creates a response with the total item count and an async iterator. */ - public async createAsyncIteratorResponse(): Promise<{ total: number; items: AsyncIterableIterator }> { + public async createAsyncIteratorResponse(): Promise<{ total: number, items: AsyncIterableIterator }> { const firstPage = await this.fetchFirstPage(); return { total: firstPage.total, @@ -127,7 +127,7 @@ export class StreamedResponseGenerator { }, { lastEmitted: 0, - accumulatedBatches: new SortedArray<{ idx: number; items: TPagedResponseItem[] }>((a, b) => a.idx - b.idx), + accumulatedBatches: new SortedArray<{ idx: number, items: TPagedResponseItem[] }>((a, b) => a.idx - b.idx), itemsToEmit: new Array(), }, ), diff --git a/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesManager.ts b/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesManager.ts index 8c39f91778f2..22237acc8836 100644 --- a/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesManager.ts +++ b/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesManager.ts @@ -149,7 +149,7 @@ export class FavoritePropertiesManager implements IDisposable { parentClassName: getPropertyClassName(info), orderedTimestamp: new Date(), priority: 0, - }), + }) ); let priority = propertiesOrder.length; @@ -266,7 +266,7 @@ export class FavoritePropertiesManager implements IDisposable { const imodelId = imodel.iModelId!; const fieldInfos = getFieldInfos(field); - const workingScopes: Array<{ properties: Set; save: (properties: Set) => Promise }> = []; + const workingScopes: Array<{ properties: Set, save: (properties: Set) => Promise }> = []; workingScopes.push({ properties: this._globalProperties!, save: async (properties) => this._storage.saveProperties(properties), @@ -399,12 +399,12 @@ export class FavoritePropertiesManager implements IDisposable { return lp < rp ? 1 : lp > rp - ? -1 - : left.priority < right.priority - ? 1 // if favorite fields have equal priorities, sort by field priority - : left.priority > right.priority - ? -1 - : left.name.localeCompare(right.name); + ? -1 + : left.priority < right.priority + ? 1 // if favorite fields have equal priorities, sort by field priority + : left.priority > right.priority + ? -1 + : left.name.localeCompare(right.name); }; return fields.sort(sortFunction); @@ -441,7 +441,7 @@ export class FavoritePropertiesManager implements IDisposable { if (this._imodelBaseClassesByClass.has(imodelInfo)) { baseClasses = this._imodelBaseClassesByClass.get(imodelInfo)!; } else { - this._imodelBaseClassesByClass.set(imodelInfo, (baseClasses = {})); + this._imodelBaseClassesByClass.set(imodelInfo, baseClasses = {}); } const missingClasses = new Set(); @@ -619,7 +619,8 @@ const getiModelInfo = (iTwinId: string, imodelId: string) => `${iTwinId}/${imode const getPropertiesFieldPropertyNames = (field: PropertiesField) => { const nestingPrefix = getNestingPrefix(field.parent); return field.properties.map( - (property) => `${FavoritePropertiesManager.FAVORITES_IDENTIFIER_PREFIX}${nestingPrefix}${property.property.classInfo.name}:${property.property.name}`, + (property) => + `${FavoritePropertiesManager.FAVORITES_IDENTIFIER_PREFIX}${nestingPrefix}${property.property.classInfo.name}:${property.property.name}`, ); }; diff --git a/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesStorage.ts b/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesStorage.ts index 8ab45ddef3e0..063a38994604 100644 --- a/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesStorage.ts +++ b/presentation/frontend/src/presentation-frontend/favorite-properties/FavoritePropertiesStorage.ts @@ -191,7 +191,9 @@ export class OfflineCachingFavoritePropertiesStorage implements IFavoritePropert private _connectivityInfo: IConnectivityInformationProvider; private _impl: IFavoritePropertiesStorage; private _propertiesOfflineCache = new DictionaryWithReservations>(iTwinAndIModelIdsKeyComparer); - private _propertiesOrderOfflineCache = new DictionaryWithReservations(iTwinAndIModelIdsKeyComparer); + private _propertiesOrderOfflineCache = new DictionaryWithReservations( + iTwinAndIModelIdsKeyComparer, + ); public constructor(props: OfflineCachingFavoritePropertiesStorageProps) { this._impl = props.impl; @@ -217,11 +219,11 @@ export class OfflineCachingFavoritePropertiesStorage implements IFavoritePropert // note: we're copying the cached values to temp arrays because `saveProperties` and `savePropertiesOrder` both // attempt to modify cache dictionaries - const propertiesCache = new Array<{ properties: Set; iTwinId?: string; imodelId?: string }>(); + const propertiesCache = new Array<{ properties: Set, iTwinId?: string, imodelId?: string }>(); this._propertiesOfflineCache.forEach((key, value) => propertiesCache.push({ properties: value, iTwinId: key[0], imodelId: key[1] })); propertiesCache.forEach(async (cached) => this.saveProperties(cached.properties, cached.iTwinId, cached.imodelId)); - const ordersCache = new Array<{ order: FavoritePropertiesOrderInfo[]; iTwinId?: string; imodelId: string }>(); + const ordersCache = new Array<{ order: FavoritePropertiesOrderInfo[], iTwinId?: string, imodelId: string }>(); this._propertiesOrderOfflineCache.forEach((key, value) => ordersCache.push({ order: value, iTwinId: key[0], imodelId: key[1]! })); ordersCache.forEach(async (cached) => this.savePropertiesOrder(cached.order, cached.iTwinId, cached.imodelId)); } @@ -281,7 +283,7 @@ export class OfflineCachingFavoritePropertiesStorage implements IFavoritePropert } class DictionaryWithReservations { - private _impl: Dictionary; + private _impl: Dictionary; public constructor(compareKeys: OrderedComparator) { this._impl = new Dictionary(compareKeys); } diff --git a/presentation/frontend/src/presentation-frontend/selection/HiliteSetProvider.ts b/presentation/frontend/src/presentation-frontend/selection/HiliteSetProvider.ts index dfb53d855bf0..a1de23faeea8 100644 --- a/presentation/frontend/src/presentation-frontend/selection/HiliteSetProvider.ts +++ b/presentation/frontend/src/presentation-frontend/selection/HiliteSetProvider.ts @@ -6,14 +6,23 @@ * @module UnifiedSelection */ -import { from, Observable, shareReplay } from "rxjs"; -import { eachValueFrom } from "rxjs-for-await"; import { Id64String } from "@itwin/core-bentley"; import { IModelConnection } from "@itwin/core-frontend"; -import { ContentFlags, DEFAULT_KEYS_BATCH_SIZE, DefaultContentDisplayTypes, DescriptorOverrides, Item, Key, KeySet, Ruleset } from "@itwin/presentation-common"; +import { + ContentFlags, + DEFAULT_KEYS_BATCH_SIZE, + DefaultContentDisplayTypes, + DescriptorOverrides, + Item, + Key, + KeySet, + Ruleset, +} from "@itwin/presentation-common"; +import { from, Observable, shareReplay } from "rxjs"; +import { eachValueFrom } from "rxjs-for-await"; import { Presentation } from "../Presentation"; -import { TRANSIENT_ELEMENT_CLASSNAME } from "./SelectionManager"; import hiliteRuleset from "./HiliteRules.json"; +import { TRANSIENT_ELEMENT_CLASSNAME } from "./SelectionManager"; const HILITE_RULESET = hiliteRuleset as Ruleset; @@ -46,7 +55,7 @@ export interface HiliteSetProviderProps { */ export class HiliteSetProvider { private _imodel: IModelConnection; - private _cache: undefined | { keysGuid: string; observable: Observable }; + private _cache: undefined | { keysGuid: string, observable: Observable }; private constructor(props: HiliteSetProviderProps) { this._imodel = props.imodel; diff --git a/presentation/frontend/src/presentation-frontend/selection/SelectionManager.ts b/presentation/frontend/src/presentation-frontend/selection/SelectionManager.ts index 693b2cabd1b9..27d560367981 100644 --- a/presentation/frontend/src/presentation-frontend/selection/SelectionManager.ts +++ b/presentation/frontend/src/presentation-frontend/selection/SelectionManager.ts @@ -6,10 +6,19 @@ * @module UnifiedSelection */ -import { defer, EMPTY, mergeMap, Observable, of, Subject, Subscription, takeUntil, tap } from "rxjs"; import { Id64, Id64Arg, Id64Array, IDisposable, using } from "@itwin/core-bentley"; import { IModelConnection, SelectionSetEvent, SelectionSetEventType } from "@itwin/core-frontend"; -import { AsyncTasksTracker, BaseNodeKey, InstanceKey, Key, Keys, KeySet, NodeKey, SelectionScope, SelectionScopeProps } from "@itwin/presentation-common"; +import { + AsyncTasksTracker, + BaseNodeKey, + InstanceKey, + Key, + Keys, + KeySet, + NodeKey, + SelectionScope, + SelectionScopeProps, +} from "@itwin/presentation-common"; import { createStorage, CustomSelectable, @@ -19,6 +28,7 @@ import { StorageSelectionChangeEventArgs, StorageSelectionChangeType, } from "@itwin/unified-selection"; +import { defer, EMPTY, mergeMap, Observable, of, Subject, Subscription, takeUntil, tap } from "rxjs"; import { Presentation } from "../Presentation"; import { HiliteSet, HiliteSetProvider } from "./HiliteSetProvider"; import { ISelectionProvider } from "./ISelectionProvider"; @@ -45,7 +55,7 @@ export interface SelectionManagerProps { */ export class SelectionManager implements ISelectionProvider { private _selectionStorage: SelectionStorage; - private _imodelToolSelectionSyncHandlers = new Map(); + private _imodelToolSelectionSyncHandlers = new Map(); private _hiliteSetProviders = new Map(); private _ownsStorage: boolean; @@ -473,7 +483,7 @@ export class ToolSelectionSyncHandler implements IDisposable { } const parsedIds = parseIds(ids); - await using(this._asyncsTracker.trackAsyncTask(), async (_r) => { + using(this._asyncsTracker.trackAsyncTask(), async (_r) => { switch (ev.type) { case SelectionSetEventType.Add: await changer.add(parsedIds.transient, parsedIds.persistent, selectionLevel); @@ -489,7 +499,7 @@ export class ToolSelectionSyncHandler implements IDisposable { }; } -const parseIds = (ids: Id64Arg): { persistent: Id64Arg; transient: Id64Arg } => { +const parseIds = (ids: Id64Arg): { persistent: Id64Arg, transient: Id64Arg } => { let allPersistent = true; let allTransient = true; for (const id of Id64.iterable(ids)) { diff --git a/presentation/frontend/src/test/ConnectivityInformationProvider.test.ts b/presentation/frontend/src/test/ConnectivityInformationProvider.test.ts index 4a6352b9ffe5..22c10f004e5e 100644 --- a/presentation/frontend/src/test/ConnectivityInformationProvider.test.ts +++ b/presentation/frontend/src/test/ConnectivityInformationProvider.test.ts @@ -3,12 +3,12 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; import { BeDuration } from "@itwin/core-bentley"; import { InternetConnectivityStatus } from "@itwin/core-common"; import { NativeApp } from "@itwin/core-frontend"; import { ResolvablePromise } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { ConnectivityInformationProvider } from "../presentation-frontend/ConnectivityInformationProvider"; import { Presentation } from "../presentation-frontend/Presentation"; @@ -16,7 +16,9 @@ describe("ConnectivityInformationProvider", () => { let nativeAppCheckInternetConnectivityStub: sinon.SinonStub<[], PromiseLike>; beforeEach(() => { - nativeAppCheckInternetConnectivityStub = sinon.stub(NativeApp, "checkInternetConnectivity").returns(Promise.resolve(InternetConnectivityStatus.Offline)); + nativeAppCheckInternetConnectivityStub = sinon.stub(NativeApp, "checkInternetConnectivity").returns( + Promise.resolve(InternetConnectivityStatus.Offline), + ); }); afterEach(() => { diff --git a/presentation/frontend/src/test/Diagnostics.test.ts b/presentation/frontend/src/test/Diagnostics.test.ts index b009f19b3cf0..5cae29f964db 100644 --- a/presentation/frontend/src/test/Diagnostics.test.ts +++ b/presentation/frontend/src/test/Diagnostics.test.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ClientDiagnostics } from "@itwin/presentation-common"; import { expect } from "chai"; import * as sinon from "sinon"; -import { ClientDiagnostics } from "@itwin/presentation-common"; import { consoleDiagnosticsHandler, createCombinedDiagnosticsHandler } from "../presentation-frontend/Diagnostics"; describe("consoleDiagnosticsHandler", () => { diff --git a/presentation/frontend/src/test/IpcRequestsHandler.test.ts b/presentation/frontend/src/test/IpcRequestsHandler.test.ts index 9cbe7ea736d3..e293b05e91f3 100644 --- a/presentation/frontend/src/test/IpcRequestsHandler.test.ts +++ b/presentation/frontend/src/test/IpcRequestsHandler.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import sinon from "sinon"; import { _callIpcChannel, IpcApp } from "@itwin/core-frontend"; import { PRESENTATION_IPC_CHANNEL_NAME, RulesetVariable, VariableValueTypes } from "@itwin/presentation-common"; +import { expect } from "chai"; +import sinon from "sinon"; import { IpcRequestsHandler } from "../presentation-frontend/IpcRequestsHandler"; describe("IpcRequestsHandler", () => { diff --git a/presentation/frontend/src/test/Presentation.test.ts b/presentation/frontend/src/test/Presentation.test.ts index 308a99c1a51f..e44bd0d51c9c 100644 --- a/presentation/frontend/src/test/Presentation.test.ts +++ b/presentation/frontend/src/test/Presentation.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { IModelApp, IModelConnection, NoRenderApp } from "@itwin/core-frontend"; +import { PresentationError } from "@itwin/presentation-common"; import { expect } from "chai"; import * as sinon from "sinon"; import * as moq from "typemoq"; -import { IModelApp, IModelConnection, NoRenderApp } from "@itwin/core-frontend"; -import { PresentationError } from "@itwin/presentation-common"; import { Presentation, SelectionManager } from "../presentation-frontend"; import * as favorites from "../presentation-frontend/favorite-properties/FavoritePropertiesManager"; import { IFavoritePropertiesStorage, NoopFavoritePropertiesStorage } from "../presentation-frontend/favorite-properties/FavoritePropertiesStorage"; diff --git a/presentation/frontend/src/test/PresentationManager.test.ts b/presentation/frontend/src/test/PresentationManager.test.ts index b3325b611e74..cf59ef886dc1 100644 --- a/presentation/frontend/src/test/PresentationManager.test.ts +++ b/presentation/frontend/src/test/PresentationManager.test.ts @@ -2,10 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; -import sinon from "sinon"; -import * as moq from "typemoq"; import { BeDuration, BeEvent, CompressedId64Set, using } from "@itwin/core-bentley"; import { IModelRpcProps, IpcListener, RemoveFunction } from "@itwin/core-common"; import { IModelApp, IModelConnection, IpcApp, QuantityFormatter } from "@itwin/core-frontend"; @@ -67,6 +63,10 @@ import { createTestPropertiesContentField, createTestSimpleContentField, } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as faker from "faker"; +import sinon from "sinon"; +import * as moq from "typemoq"; import { IpcRequestsHandler } from "../presentation-frontend/IpcRequestsHandler"; import { Presentation } from "../presentation-frontend/Presentation"; import { @@ -134,7 +134,7 @@ describe("PresentationManager", () => { }; // use this when sending requests without ruleset-related attributes - const toIModelTokenOptions = (requestOptions: TOptions) => { + const toIModelTokenOptions = (requestOptions: TOptions) => { return { unitSystem: quantityFormatterUnitSystem, ...requestOptions, @@ -834,7 +834,9 @@ describe("PresentationManager", () => { keys: keyset, }; rpcRequestsHandlerMock - .setup(async (x) => x.getContentSetSize(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() }))) + .setup(async (x) => + x.getContentSetSize(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) + ) .returns(async () => result) .verifiable(); const actualResult = await manager.getContentSetSize(options); @@ -882,7 +884,7 @@ describe("PresentationManager", () => { }; rpcRequestsHandlerMock .setup(async (x) => - x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })), + x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) ) .returns(async () => ({ ...result, items: result.items.map((i) => i.toJSON()) })) .verifiable(); @@ -906,7 +908,7 @@ describe("PresentationManager", () => { }; rpcRequestsHandlerMock .setup(async (x) => - x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })), + x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) ) .returns(async () => ({ ...result, items: result.items.map((i) => i.toJSON()) })) .verifiable(); @@ -951,7 +953,9 @@ describe("PresentationManager", () => { keys: keyset, }; rpcRequestsHandlerMock - .setup(async (x) => x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() }))) + .setup(async (x) => + x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) + ) .returns(async () => undefined) .verifiable(); const actualResult = await manager.getContent(options); @@ -990,7 +994,7 @@ describe("PresentationManager", () => { }; rpcRequestsHandlerMock .setup(async (x) => - x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })), + x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) ) .returns(async () => ({ total: 1, items: [item.toJSON()] })) .verifiable(); @@ -1035,7 +1039,7 @@ describe("PresentationManager", () => { .setup(async (x) => x.getPagedContentSet( toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON(), omitFormattedValues: true }), - ), + ) ) .returns(async () => ({ total: 1, items: [item.toJSON()] })) .verifiable(); @@ -1068,7 +1072,7 @@ describe("PresentationManager", () => { }; rpcRequestsHandlerMock .setup(async (x) => - x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })), + x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) ) .returns(async () => ({ ...result, items: result.items.map((i) => i.toJSON()) })); @@ -1093,7 +1097,7 @@ describe("PresentationManager", () => { }; rpcRequestsHandlerMock .setup(async (x) => - x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })), + x.getPagedContentSet(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) ) .returns(async () => ({ ...result, items: result.items.map((i) => i.toJSON()) })) .verifiable(); @@ -1122,7 +1126,9 @@ describe("PresentationManager", () => { keys: keyset, }; rpcRequestsHandlerMock - .setup(async (x) => x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() }))) + .setup(async (x) => + x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) + ) .returns(async () => ({ descriptor: descriptor.toJSON(), contentSet: { ...result, items: result.items.map((i) => i.toJSON()) } })) .verifiable(); const actualResult = await manager.getContentAndSize(options); @@ -1151,16 +1157,26 @@ describe("PresentationManager", () => { rpcRequestsHandlerMock .setup(async (x) => x.getPagedContent( - toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON(), paging: { start: 0, size: 2 } }), - ), + toRulesetRpcOptions({ + ...options, + descriptor: descriptor.createDescriptorOverrides(), + keys: keyset.toJSON(), + paging: { start: 0, size: 2 }, + }), + ) ) .returns(async () => ({ descriptor: descriptor.toJSON(), contentSet: { total: 5, items: [item1.toJSON()] } })) .verifiable(); rpcRequestsHandlerMock .setup(async (x) => x.getPagedContentSet( - toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON(), paging: { start: 1, size: 1 } }), - ), + toRulesetRpcOptions({ + ...options, + descriptor: descriptor.createDescriptorOverrides(), + keys: keyset.toJSON(), + paging: { start: 1, size: 1 }, + }), + ) ) .returns(async () => ({ total: 5, items: [item2.toJSON()] })) .verifiable(); @@ -1187,7 +1203,9 @@ describe("PresentationManager", () => { keys: keyset, }; rpcRequestsHandlerMock - .setup(async (x) => x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() }))) + .setup(async (x) => + x.getPagedContent(toRulesetRpcOptions({ ...options, descriptor: descriptor.createDescriptorOverrides(), keys: keyset.toJSON() })) + ) .returns(async () => undefined) .verifiable(); const actualResult = await manager.getContentAndSize(options); @@ -1293,7 +1311,7 @@ describe("PresentationManager", () => { rulesetOrId: "ElementProperties", keys: new KeySet([{ className: "BisCore:Element", id: elementId }]).toJSON(), }), - ), + ) ) .returns(async () => undefined) .verifiable(); @@ -1362,7 +1380,7 @@ describe("PresentationManager", () => { rulesetOrId: "ElementProperties", keys: new KeySet([{ className: "BisCore:Element", id: elementId }]).toJSON(), }), - ), + ) ) .returns(async () => ({ descriptor: descriptor.toJSON(), diff --git a/presentation/frontend/src/test/RulesetManager.test.ts b/presentation/frontend/src/test/RulesetManager.test.ts index ffaf79aa142d..aa0e871f2ad4 100644 --- a/presentation/frontend/src/test/RulesetManager.test.ts +++ b/presentation/frontend/src/test/RulesetManager.test.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { RegisteredRuleset, Rule, Ruleset, RuleTypes } from "@itwin/presentation-common"; +import { createRandomRuleset } from "@itwin/presentation-common/lib/cjs/test"; import { expect } from "chai"; import * as faker from "faker"; import * as sinon from "sinon"; -import { RegisteredRuleset, Rule, Ruleset, RuleTypes } from "@itwin/presentation-common"; -import { createRandomRuleset } from "@itwin/presentation-common/lib/cjs/test"; import { RulesetManagerImpl } from "../presentation-frontend/RulesetManager"; describe("RulesetManager", () => { diff --git a/presentation/frontend/src/test/RulesetVariablesManager.test.ts b/presentation/frontend/src/test/RulesetVariablesManager.test.ts index 5f7b6b479658..9c32ab799d64 100644 --- a/presentation/frontend/src/test/RulesetVariablesManager.test.ts +++ b/presentation/frontend/src/test/RulesetVariablesManager.test.ts @@ -3,14 +3,14 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as faker from "faker"; -import sinon from "sinon"; -import * as moq from "typemoq"; import { Id64 } from "@itwin/core-bentley"; import { IpcApp } from "@itwin/core-frontend"; import { RulesetVariable, VariableValueTypes } from "@itwin/presentation-common"; import { createRandomId } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as faker from "faker"; +import sinon from "sinon"; +import * as moq from "typemoq"; import { IpcRequestsHandler } from "../presentation-frontend/IpcRequestsHandler"; import { RulesetVariablesManagerImpl } from "../presentation-frontend/RulesetVariablesManager"; @@ -35,7 +35,9 @@ describe("RulesetVariablesManager", () => { type: VariableValueTypes.String, value: "test-value", }; - ipcHandlerMock.setup(async (x) => x.setRulesetVariable(moq.It.isObjectWith({ rulesetId, variable: testVariable }))).verifiable(moq.Times.once()); + ipcHandlerMock.setup(async (x) => x.setRulesetVariable(moq.It.isObjectWith({ rulesetId, variable: testVariable }))).verifiable( + moq.Times.once(), + ); await vars.setString(testVariable.id, testVariable.value); ipcHandlerMock.verifyAll(); @@ -49,7 +51,9 @@ describe("RulesetVariablesManager", () => { vars = new RulesetVariablesManagerImpl(rulesetId, ipcHandlerMock.object); await vars.setString("test-id", "test-value"); - ipcHandlerMock.setup(async (x) => x.unsetRulesetVariable(moq.It.isObjectWith({ rulesetId, variableId: "test-id" }))).verifiable(moq.Times.once()); + ipcHandlerMock.setup(async (x) => x.unsetRulesetVariable(moq.It.isObjectWith({ rulesetId, variableId: "test-id" }))).verifiable( + moq.Times.once(), + ); await vars.unset("test-id"); ipcHandlerMock.verifyAll(); }); diff --git a/presentation/frontend/src/test/StreamedResponseGenerator.test.ts b/presentation/frontend/src/test/StreamedResponseGenerator.test.ts index ec790b4ea93f..824227aebc60 100644 --- a/presentation/frontend/src/test/StreamedResponseGenerator.test.ts +++ b/presentation/frontend/src/test/StreamedResponseGenerator.test.ts @@ -3,15 +3,15 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import sinon from "sinon"; import { PagedResponse, PageOptions } from "@itwin/presentation-common"; import { ResolvablePromise } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import sinon from "sinon"; import { StreamedResponseGenerator, StreamedResponseGeneratorProps } from "../presentation-frontend/StreamedResponseGenerator"; describe("StreamedResponseGenerator", () => { /** Creates a response with the total item count and an array of items for the requested page. */ - async function createItemsResponse(generator: StreamedResponseGenerator): Promise<{ total: number; items: T[] }> { + async function createItemsResponse(generator: StreamedResponseGenerator): Promise<{ total: number, items: T[] }> { const response = await generator.createAsyncIteratorResponse(); const items = new Array(); for await (const value of response.items) { @@ -53,10 +53,12 @@ describe("StreamedResponseGenerator", () => { it("returns values in correct order when requests resolve in different order than being made", async () => { const total = 4; - for (const ordering of [ - [2, 1, 0], - [2, 0, 1], - ]) { + for ( + const ordering of [ + [2, 1, 0], + [2, 0, 1], + ] + ) { const fakePromises: ResolvablePromise>[] = [...new Array(total - 1).keys()].map(() => new ResolvablePromise()); const generator = new StreamedResponseGenerator({ getBatch: async (_, idx) => { diff --git a/presentation/frontend/src/test/favorite-properties/FavoritePropertiesManager.test.ts b/presentation/frontend/src/test/favorite-properties/FavoritePropertiesManager.test.ts index 2ed80e59512b..fc74216e3d49 100644 --- a/presentation/frontend/src/test/favorite-properties/FavoritePropertiesManager.test.ts +++ b/presentation/frontend/src/test/favorite-properties/FavoritePropertiesManager.test.ts @@ -2,9 +2,6 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import sinon from "sinon"; -import * as moq from "typemoq"; import { ECSqlReader, QueryRowFormat, QueryRowProxy } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; import { Field, NestedContentField, PropertiesField, PropertyInfo } from "@itwin/presentation-common"; @@ -16,6 +13,9 @@ import { createTestRelatedClassInfo, createTestSimpleContentField, } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import sinon from "sinon"; +import * as moq from "typemoq"; import { createFieldOrderInfos, FavoritePropertiesManager, @@ -66,7 +66,7 @@ describe("FavoritePropertiesManager", () => { imodelMock.reset(); }); - function setupMocksForQueryingBaseClasses(classBaseClass: Array<{ classFullName: string; baseClassFullName: string }>) { + function setupMocksForQueryingBaseClasses(classBaseClass: Array<{ classFullName: string, baseClassFullName: string }>) { let currIndex = -1; const ecSqlReaderMock = moq.Mock.ofType(); ecSqlReaderMock.setup(async (x) => x.step()).returns(async () => ++currIndex < classBaseClass.length); @@ -553,7 +553,9 @@ describe("FavoritePropertiesManager", () => { const orderInfos = getFieldsOrderInfos(allFields); storageMock.setup(async (x) => x.loadPropertiesOrder(moq.It.isAny(), moq.It.isAny())).returns(async () => orderInfos); - await expect(manager.changeFieldPriority(imodelMock.object, a, a, allFields)).to.be.rejectedWith("`field` can not be the same as `afterField`."); + await expect(manager.changeFieldPriority(imodelMock.object, a, a, allFields)).to.be.rejectedWith( + "`field` can not be the same as `afterField`.", + ); }); it("throws if given non-visible field", async () => { @@ -568,7 +570,9 @@ describe("FavoritePropertiesManager", () => { storageMock.setup(async (x) => x.loadPropertiesOrder(moq.It.isAny(), moq.It.isAny())).returns(async () => orderInfos); const fakeField = createTestPropertiesContentField({ properties: [{ property: createTestPropertyInfo({ name: "does-not-exist" }) }] }); - await expect(manager.changeFieldPriority(imodelMock.object, fakeField, b, allFields)).to.be.rejectedWith("Field is not contained in visible fields."); + await expect(manager.changeFieldPriority(imodelMock.object, fakeField, b, allFields)).to.be.rejectedWith( + "Field is not contained in visible fields.", + ); }); it("throws if given non-favorite field", async () => { @@ -601,7 +605,9 @@ describe("FavoritePropertiesManager", () => { storageMock.setup(async (x) => x.loadPropertiesOrder(moq.It.isAny(), moq.It.isAny())).returns(async () => orderInfos); const fakeField = createTestPropertiesContentField({ properties: [{ property: createTestPropertyInfo({ name: "does-not-exist" }) }] }); - await expect(manager.changeFieldPriority(imodelMock.object, a, fakeField, allFields)).to.be.rejectedWith("Field is not contained in visible fields."); + await expect(manager.changeFieldPriority(imodelMock.object, a, fakeField, allFields)).to.be.rejectedWith( + "Field is not contained in visible fields.", + ); }); it("throws if given non-favorite afterField", async () => { @@ -651,7 +657,10 @@ describe("FavoritePropertiesManager", () => { await manager.changeFieldPriority(imodelMock.object, b, a, allFields); expect(orderInfos[0]).to.eq(oldOrderInfo[0]); // a expect(orderInfos[1]).to.eq(oldOrderInfo[1]); // b - imodelMock.verify((x) => x.createQueryReader(moq.It.isAnyString(), undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }), moq.Times.once()); + imodelMock.verify( + (x) => x.createQueryReader(moq.It.isAnyString(), undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames }), + moq.Times.once(), + ); }); it("does not change the order of irrelevant properties", async () => { @@ -947,7 +956,8 @@ describe("FavoritePropertiesManager", () => { }); }); -const getFieldsInfos = (fields: Field[]): PropertyFullName[] => fields.reduce((total: PropertyFullName[], field) => [...total, ...getFieldInfos(field)], []); +const getFieldsInfos = (fields: Field[]): PropertyFullName[] => + fields.reduce((total: PropertyFullName[], field) => [...total, ...getFieldInfos(field)], []); const getFieldsOrderInfos = (fields: Field[]): FavoritePropertiesOrderInfo[] => { const orderInfos = fields.reduce((total: FavoritePropertiesOrderInfo[], field) => [...total, ...createFieldOrderInfos(field)], []); diff --git a/presentation/frontend/src/test/favorite-properties/FavoritePropertiesStorage.test.ts b/presentation/frontend/src/test/favorite-properties/FavoritePropertiesStorage.test.ts index 5d34b2e7a392..1e57e59de845 100644 --- a/presentation/frontend/src/test/favorite-properties/FavoritePropertiesStorage.test.ts +++ b/presentation/frontend/src/test/favorite-properties/FavoritePropertiesStorage.test.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import sinon from "sinon"; -import * as moq from "typemoq"; import { AccessToken, BeEvent } from "@itwin/core-bentley"; import { AuthorizationClient, InternetConnectivityStatus } from "@itwin/core-common"; import { IModelApp, UserPreferencesAccess } from "@itwin/core-frontend"; import { ResolvablePromise } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import sinon from "sinon"; +import * as moq from "typemoq"; import { IConnectivityInformationProvider } from "../../presentation-frontend/ConnectivityInformationProvider"; import { FavoritePropertiesOrderInfo, PropertyFullName } from "../../presentation-frontend/favorite-properties/FavoritePropertiesManager"; import { @@ -96,7 +96,9 @@ describe("IModelAppFavoritePropertiesStorage", () => { describe("saveProperties", () => { it("saves favorite properties", async () => { settingsAdminMock - .setup(async (x) => x.save(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_SETTING_NAME }))) + .setup(async (x) => + x.save(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_SETTING_NAME })) + ) .returns(async () => {}); const properties = new Set(["propertyInfo1", "propertyInfo2"]); @@ -129,7 +131,7 @@ describe("IModelAppFavoritePropertiesStorage", () => { }; settingsAdminMock .setup(async (x) => - x.get(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_ORDER_INFO_SETTING_NAME })), + x.get(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_ORDER_INFO_SETTING_NAME })) ) .returns(async () => [orderInfo]); @@ -142,7 +144,7 @@ describe("IModelAppFavoritePropertiesStorage", () => { it("returns undefined", async () => { settingsAdminMock .setup(async (x) => - x.get(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_ORDER_INFO_SETTING_NAME })), + x.get(moq.It.isObjectWith({ namespace: IMODELJS_PRESENTATION_SETTING_NAMESPACE, key: FAVORITE_PROPERTIES_ORDER_INFO_SETTING_NAME })) ) .returns(async () => undefined); sinon.stub(IModelApp, "userPreferences").get(() => settingsAdminMock.object); @@ -185,7 +187,7 @@ describe("IModelAppFavoritePropertiesStorage", () => { key: FAVORITE_PROPERTIES_ORDER_INFO_SETTING_NAME, content: [orderInfo], }), - ), + ) ) .returns(async () => {}) .verifiable(); diff --git a/presentation/frontend/src/test/selection/HiliteSetProvider.test.ts b/presentation/frontend/src/test/selection/HiliteSetProvider.test.ts index e28a53a86ac1..c9aba6781d6e 100644 --- a/presentation/frontend/src/test/selection/HiliteSetProvider.test.ts +++ b/presentation/frontend/src/test/selection/HiliteSetProvider.test.ts @@ -3,22 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as moq from "typemoq"; import { IModelConnection } from "@itwin/core-frontend"; import { Content, DEFAULT_KEYS_BATCH_SIZE, Descriptor, Item, KeySet } from "@itwin/presentation-common"; import { createRandomECInstanceKey, createRandomTransientId, createTestContentDescriptor } from "@itwin/presentation-common/lib/cjs/test"; -import { HiliteSetProvider } from "../../presentation-frontend/selection/HiliteSetProvider"; -import { TRANSIENT_ELEMENT_CLASSNAME } from "../../presentation-frontend/selection/SelectionManager"; +import { expect } from "chai"; import sinon from "sinon"; -import { Presentation } from "../../presentation-frontend/Presentation"; +import * as moq from "typemoq"; import { GetContentRequestOptions, MultipleValuesRequestOptions, PresentationManager } from "../../presentation-frontend"; +import { Presentation } from "../../presentation-frontend/Presentation"; +import { HiliteSetProvider } from "../../presentation-frontend/selection/HiliteSetProvider"; +import { TRANSIENT_ELEMENT_CLASSNAME } from "../../presentation-frontend/selection/SelectionManager"; describe("HiliteSetProvider", () => { const imodelMock = moq.Mock.ofType(); const fakeGetContentIterator = sinon.stub< [GetContentRequestOptions & MultipleValuesRequestOptions], - Promise<{ descriptor: Descriptor; total: number; items: AsyncIterableIterator } | undefined> + Promise<{ descriptor: Descriptor, total: number, items: AsyncIterableIterator } | undefined> >(); before(() => { @@ -105,7 +105,9 @@ describe("HiliteSetProvider", () => { it("creates result for model keys", async () => { const persistentKey = createRandomECInstanceKey(); const resultKey = createRandomECInstanceKey(); - const resultContent = new Content(createTestContentDescriptor({ fields: [] }), [new Item([resultKey], "", "", undefined, {}, {}, [], { isModel: true })]); + const resultContent = new Content(createTestContentDescriptor({ fields: [] }), [ + new Item([resultKey], "", "", undefined, {}, {}, [], { isModel: true }), + ]); fakeGetContentIterator .onFirstCall() diff --git a/presentation/frontend/src/test/selection/SelectionHandler.test.ts b/presentation/frontend/src/test/selection/SelectionHandler.test.ts index 3b0d32430561..cb2d3b2e3ed2 100644 --- a/presentation/frontend/src/test/selection/SelectionHandler.test.ts +++ b/presentation/frontend/src/test/selection/SelectionHandler.test.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as moq from "typemoq"; import { IModelConnection } from "@itwin/core-frontend"; import { KeySet } from "@itwin/presentation-common"; +import { expect } from "chai"; +import * as moq from "typemoq"; import { ISelectionProvider, SelectionChangeEvent, diff --git a/presentation/frontend/src/test/selection/SelectionHelper.test.ts b/presentation/frontend/src/test/selection/SelectionHelper.test.ts index f9c2ade6646e..a727eedfe015 100644 --- a/presentation/frontend/src/test/selection/SelectionHelper.test.ts +++ b/presentation/frontend/src/test/selection/SelectionHelper.test.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; import { createRandomBaseNodeKey, createRandomECInstanceKey, createRandomECInstancesNodeKey } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; import { SelectionHelper } from "../../presentation-frontend"; describe("SelectionHelper", () => { diff --git a/presentation/frontend/src/test/selection/SelectionManager.test.ts b/presentation/frontend/src/test/selection/SelectionManager.test.ts index be30c21386c8..3848bd8286ea 100644 --- a/presentation/frontend/src/test/selection/SelectionManager.test.ts +++ b/presentation/frontend/src/test/selection/SelectionManager.test.ts @@ -3,8 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as sinon from "sinon"; import { assert, BeDuration, Id64, Id64Arg, Id64String, StopWatch, using } from "@itwin/core-bentley"; import { BlankConnection, IModelApp, IModelConnection, SelectionSet, SelectionSetEventType } from "@itwin/core-frontend"; import { InstanceKey, KeySet, NodeKey, SelectionScope, StandardNodeTypes } from "@itwin/presentation-common"; @@ -18,6 +16,8 @@ import { waitForPendingAsyncs, } from "@itwin/presentation-common/lib/cjs/test"; import { createStorage, CustomSelectable, SelectionStorage } from "@itwin/unified-selection"; +import { expect } from "chai"; +import * as sinon from "sinon"; import { Presentation } from "../../presentation-frontend/Presentation"; import { PresentationManager } from "../../presentation-frontend/PresentationManager"; import { HiliteSetProvider } from "../../presentation-frontend/selection/HiliteSetProvider"; @@ -39,7 +39,10 @@ describe("SelectionManager", () => { } as IModelConnection; const scopesManager = { - getSelectionScopes: sinon.stub, ReturnType>(), + getSelectionScopes: sinon.stub< + Parameters, + ReturnType + >(), computeSelection: sinon.stub, ReturnType>(), }; @@ -972,7 +975,7 @@ describe("SelectionManager", () => { it("custom selectable once", async () => { const instanceKeys = [createTestECInstanceKey({ id: "0x1" }), createTestECInstanceKey({ id: "0x2" })]; const loadInstanceKeys = sinon.fake, ReturnType>(() => - createAsyncGenerator(instanceKeys), + createAsyncGenerator(instanceKeys) ); storage.addToSelection({ iModelKey: imodel.key, @@ -1133,8 +1136,16 @@ describe("SelectionManager", () => { const selectable2instanceKeys = [createTestECInstanceKey({ id: "0x5" }), createTestECInstanceKey({ id: "0x6" })]; it("converts add event selectables", async () => { - const selectable1: CustomSelectable = { identifier: "custom-1", loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), data: {} }; - const selectable2: CustomSelectable = { identifier: "custom-2", loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), data: {} }; + const selectable1: CustomSelectable = { + identifier: "custom-1", + loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), + data: {}, + }; + const selectable2: CustomSelectable = { + identifier: "custom-2", + loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), + data: {}, + }; storage.addToSelection({ iModelKey: imodel.key, @@ -1173,8 +1184,16 @@ describe("SelectionManager", () => { }); it("converts replace event selectables", async () => { - const selectable1: CustomSelectable = { identifier: "custom-1", loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), data: {} }; - const selectable2: CustomSelectable = { identifier: "custom-2", loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), data: {} }; + const selectable1: CustomSelectable = { + identifier: "custom-1", + loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), + data: {}, + }; + const selectable2: CustomSelectable = { + identifier: "custom-2", + loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), + data: {}, + }; storage.replaceSelection({ iModelKey: imodel.key, @@ -1213,8 +1232,16 @@ describe("SelectionManager", () => { }); it("converts remove event selectables", async () => { - const selectable1: CustomSelectable = { identifier: "custom-1", loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), data: {} }; - const selectable2: CustomSelectable = { identifier: "custom-2", loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), data: {} }; + const selectable1: CustomSelectable = { + identifier: "custom-1", + loadInstanceKeys: () => createAsyncGenerator(selectable1instanceKeys), + data: {}, + }; + const selectable2: CustomSelectable = { + identifier: "custom-2", + loadInstanceKeys: () => createAsyncGenerator(selectable2instanceKeys), + data: {}, + }; storage.addToSelection({ iModelKey: imodel.key, @@ -1266,7 +1293,7 @@ describe("SelectionManager", () => { }); function createAsyncGenerator(values: T[], delay?: Promise): AsyncGenerator { - return (async function* () { + return (async function*() { await delay; for (const value of values) { yield value; diff --git a/presentation/frontend/src/test/selection/SelectionScopesManager.test.ts b/presentation/frontend/src/test/selection/SelectionScopesManager.test.ts index af3cdd82cda6..4abd96c5acaf 100644 --- a/presentation/frontend/src/test/selection/SelectionScopesManager.test.ts +++ b/presentation/frontend/src/test/selection/SelectionScopesManager.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as moq from "typemoq"; import { Id64String } from "@itwin/core-bentley"; import { IModelRpcProps } from "@itwin/core-common"; import { IModelConnection } from "@itwin/core-frontend"; import { DEFAULT_KEYS_BATCH_SIZE, ElementSelectionScopeProps, KeySet, RpcRequestsHandler } from "@itwin/presentation-common"; import { createRandomECInstanceKey, createRandomId, createRandomSelectionScope } from "@itwin/presentation-common/lib/cjs/test"; +import { expect } from "chai"; +import * as moq from "typemoq"; import { SelectionScopesManager, SelectionScopesManagerProps } from "../../presentation-frontend/selection/SelectionScopesManager"; describe("SelectionScopesManager", () => { @@ -103,7 +103,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === 1 && options.elementIds[0] === ids[0] && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result.toJSON()) .verifiable(); @@ -123,7 +123,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === 1 && options.elementIds[0] === ids[0] && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result.toJSON()) .verifiable(); @@ -151,7 +151,7 @@ describe("SelectionScopesManager", () => { (options.scope as ElementSelectionScopeProps).ancestorLevel === scope.ancestorLevel ); }), - ), + ) ) .returns(async () => result.toJSON()) .verifiable(); @@ -175,7 +175,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === DEFAULT_KEYS_BATCH_SIZE && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result1.toJSON()) .verifiable(); @@ -185,7 +185,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === 1 && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result2.toJSON()) .verifiable(); @@ -206,7 +206,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === 1 && options.elementIds[0] === id && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result.toJSON()) .verifiable(); @@ -226,7 +226,7 @@ describe("SelectionScopesManager", () => { moq.It.is((options) => { return options.elementIds.length === 1 && options.elementIds[0] === id && options.scope.id === scope.id; }), - ), + ) ) .returns(async () => result.toJSON()) .verifiable(); diff --git a/presentation/frontend/tsconfig.cjs.json b/presentation/frontend/tsconfig.cjs.json index e68ca31df566..0be0cdc88fae 100644 --- a/presentation/frontend/tsconfig.cjs.json +++ b/presentation/frontend/tsconfig.cjs.json @@ -2,5 +2,5 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "lib/cjs" - }, -} \ No newline at end of file + } +} diff --git a/presentation/frontend/tsconfig.esm.json b/presentation/frontend/tsconfig.esm.json index 0377d56a6a36..550a66645264 100644 --- a/presentation/frontend/tsconfig.esm.json +++ b/presentation/frontend/tsconfig.esm.json @@ -2,6 +2,6 @@ "extends": "./tsconfig.json", "compilerOptions": { "module": "ES2020", - "outDir": "lib/esm", - }, -} \ No newline at end of file + "outDir": "lib/esm" + } +} diff --git a/presentation/scripts/copy-test-setup.js b/presentation/scripts/copy-test-setup.js index 8e1c11231b7b..614ecbb5f332 100644 --- a/presentation/scripts/copy-test-setup.js +++ b/presentation/scripts/copy-test-setup.js @@ -6,7 +6,15 @@ // Node 15+ using MessageChannel prevents node.js process from exiting // This becomes an issue when testing React code within JSDOM environment, as the test process cannot exit properly. // https://github.com/facebook/react/issues/20756 -const commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; +const commonjsGlobal = typeof globalThis !== "undefined" + ? globalThis + : typeof window !== "undefined" + ? window + : typeof global !== "undefined" + ? global + : typeof self !== "undefined" + ? self + : {}; if (commonjsGlobal.MessageChannel) delete commonjsGlobal.MessageChannel; diff --git a/presentation/scripts/setup-tests.js b/presentation/scripts/setup-tests.js index 86f8a1714723..868906848135 100644 --- a/presentation/scripts/setup-tests.js +++ b/presentation/scripts/setup-tests.js @@ -29,13 +29,13 @@ chai.use(chaiAsPromised); chai.use(chaiJestSnapshot); chai.use(sinonChai); -before(function () { +before(function() { chaiJestSnapshot.resetSnapshotRegistry(); }); -after(function () { +after(function() { delete require.cache[__filename]; }); -beforeEach(function () { +beforeEach(function() { const currentTest = this.currentTest; // we want snapshot tests to use the same random data between runs diff --git a/test-apps/display-performance-test-app/eslint.config.js b/test-apps/display-performance-test-app/eslint.config.js index 64e753e73d4b..f26925f5c2b4 100644 --- a/test-apps/display-performance-test-app/eslint.config.js +++ b/test-apps/display-performance-test-app/eslint.config.js @@ -7,12 +7,12 @@ const customLanguageOptions = { project: [ "./tsconfig.json", "./tsconfig.backend.json", - "./vite.config.ts" + "./vite.config.ts", ], ecmaVersion: "latest", ecmaFeatures: { jsx: true, - modules: true + modules: true, }, }, }; @@ -21,6 +21,6 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - languageOptions: customLanguageOptions - } -]; \ No newline at end of file + languageOptions: customLanguageOptions, + }, +]; diff --git a/test-apps/display-performance-test-app/mobile.backend.webpack.config.js b/test-apps/display-performance-test-app/mobile.backend.webpack.config.js index 73dc1b619505..92e251b387d2 100644 --- a/test-apps/display-performance-test-app/mobile.backend.webpack.config.js +++ b/test-apps/display-performance-test-app/mobile.backend.webpack.config.js @@ -20,21 +20,21 @@ module.exports = { { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /growl\.js$/, - use: 'null-loader' + use: "null-loader", }, { test: /xunit\.js$/, - use: 'null-loader' + use: "null-loader", }, { test: /bunyan/, - use: 'null-loader' - } - ] + use: "null-loader", + }, + ], }, externals: { "@bentley/imodeljs-electronaddon": "throw new Error('should never happen')", @@ -44,9 +44,9 @@ module.exports = { "./IModelJsFs": "{IModelJsFs: IModelJsFs}", "../IModelJsFs": "{IModelJsFs: IModelJsFs}", "fs": "IModelJsFs", - "fs-extra": "IModelJsFs" + "fs-extra": "IModelJsFs", }, stats: { - warnings: false - } -} \ No newline at end of file + warnings: false, + }, +}; diff --git a/test-apps/display-performance-test-app/mobile.frontend.webpack.config.js b/test-apps/display-performance-test-app/mobile.frontend.webpack.config.js index bbb3c6160c10..5c54eb9ac0a3 100644 --- a/test-apps/display-performance-test-app/mobile.frontend.webpack.config.js +++ b/test-apps/display-performance-test-app/mobile.frontend.webpack.config.js @@ -10,8 +10,8 @@ module.exports = { entry: "./lib/frontend/DisplayPerformanceTestApp.js", output: { path: path.resolve(__dirname, "./lib/mobile/public"), - filename: '[name].bundle.js', - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + filename: "[name].bundle.js", + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "cheap-module-source-map", module: { @@ -19,13 +19,13 @@ module.exports = { { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /azure-storage|AzureFileHandler|UrlFileHandler/, - use: "null-loader" - } - ] + use: "null-loader", + }, + ], }, stats: "errors-only", externals: { @@ -34,6 +34,6 @@ module.exports = { "./IModelJsFs": "{IModelJsFs: IModelJsFs}", "../IModelJsFs": "{IModelJsFs: IModelJsFs}", "fs": "IModelJsFs", - "fs-extra": "IModelJsFs" + "fs-extra": "IModelJsFs", }, }; diff --git a/test-apps/display-performance-test-app/package.json b/test-apps/display-performance-test-app/package.json index 0a113c55cc24..f216ccd5b8ce 100644 --- a/test-apps/display-performance-test-app/package.json +++ b/test-apps/display-performance-test-app/package.json @@ -103,4 +103,4 @@ "not dead", "not <0.2%" ] -} \ No newline at end of file +} diff --git a/test-apps/display-performance-test-app/src/backend/CsvWriter.ts b/test-apps/display-performance-test-app/src/backend/CsvWriter.ts index 7ced34c7c810..ae1feff317c6 100644 --- a/test-apps/display-performance-test-app/src/backend/CsvWriter.ts +++ b/test-apps/display-performance-test-app/src/backend/CsvWriter.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import { IModelJsFs } from "@itwin/core-backend"; +import * as path from "path"; export function createFilePath(filePath: string) { // ###TODO: Make this function platform independent @@ -56,8 +56,11 @@ function addColumn(origFile: string, newName: string, columnsIndex: number): str if (pos < 0) pos = line.length; - newFile += `${line.slice(0, pos) + (pos !== 0 ? "," : "") + (lineIndex === 0 ? newName : (newName === "ReadPixels Selector" || newName === "Other Props" ? "" : 0)) - + (line[pos] !== "," ? "," : "") + line.slice(pos)}\r\n`; + newFile += `${ + line.slice(0, pos) + (pos !== 0 ? "," : "") + + (lineIndex === 0 ? newName : (newName === "ReadPixels Selector" || newName === "Other Props" ? "" : 0)) + + (line[pos] !== "," ? "," : "") + line.slice(pos) + }\r\n`; } }); return newFile; @@ -73,8 +76,10 @@ export function addColumnsToCsvFile(filePath: string, rowData: Map { - if (index >= 2 && arg !== "chrome" && arg !== "edge" && arg !== "firefox" && arg !== "safari" && arg !== "headless" && arg !== "no_debug" && arg.split(".").pop() !== "json") { + if ( + index >= 2 && arg !== "chrome" && arg !== "edge" && arg !== "firefox" && arg !== "safari" && arg !== "headless" && arg !== "no_debug" && + arg.split(".").pop() !== "json" + ) { while (arg.endsWith("\\") || arg.endsWith("\/")) arg = arg.slice(0, -1); argOutputPath = `"argOutputPath": "${arg}",`; diff --git a/test-apps/display-performance-test-app/src/backend/ElectronMain.ts b/test-apps/display-performance-test-app/src/backend/ElectronMain.ts index 3ae2bc33c392..d9395c0786ba 100644 --- a/test-apps/display-performance-test-app/src/backend/ElectronMain.ts +++ b/test-apps/display-performance-test-app/src/backend/ElectronMain.ts @@ -8,7 +8,6 @@ import DisplayPerfRpcInterface from "../common/DisplayPerfRpcInterface"; import { initializeBackend } from "./backend"; const dptaElectronMain = async () => { - // Start the backend await initializeBackend(); @@ -21,7 +20,7 @@ const dptaElectronMain = async () => { }); const autoOpenDevTools = (undefined === process.env.IMJS_NO_DEV_TOOLS) && debug; - const maximizeWindow = (undefined === process.env.IMJS_NO_MAXIMIZE_WINDOW); // Make max window the default + const maximizeWindow = undefined === process.env.IMJS_NO_MAXIMIZE_WINDOW; // Make max window the default await ElectronHost.openMainWindow({ width: 1280, height: 800, show: !maximizeWindow }); assert(ElectronHost.mainWindow !== undefined); diff --git a/test-apps/display-performance-test-app/src/backend/WebMain.ts b/test-apps/display-performance-test-app/src/backend/WebMain.ts index 81bbb2a31698..e53cec76de4d 100644 --- a/test-apps/display-performance-test-app/src/backend/WebMain.ts +++ b/test-apps/display-performance-test-app/src/backend/WebMain.ts @@ -2,11 +2,17 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { + BentleyCloudRpcConfiguration, + BentleyCloudRpcManager, + IModelReadRpcInterface, + IModelTileRpcInterface, + SnapshotIModelRpcInterface, +} from "@itwin/core-common"; import * as child_process from "child_process"; import * as chromeLauncher from "chrome-launcher"; import * as express from "express"; import * as path from "path"; -import { BentleyCloudRpcConfiguration, BentleyCloudRpcManager, IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface } from "@itwin/core-common"; import DisplayPerfRpcInterface from "../common/DisplayPerfRpcInterface"; import { initializeBackend } from "./backend"; @@ -36,7 +42,7 @@ function startWebServer() { }); // Run the server... appExp.set("port", 3000); - const announceWebServer = () => { }; + const announceWebServer = () => {}; DisplayPerfRpcInterface.webServer = appExp.listen(appExp.get("port"), announceWebServer); } @@ -58,7 +64,7 @@ function startWebServer() { browser = arg; else if (arg === "headless") chromeFlags.push("--headless"); - else if (arg === "egl"){ + else if (arg === "egl") { chromeFlags.push("--use-gl=angle"); chromeFlags.push("--use-angle=gl-egl"); } @@ -67,7 +73,6 @@ function startWebServer() { if (serverConfig === undefined) { serverConfig = { port: 3001, baseUrl: "https://localhost" }; } else { - } // Set up the ability to serve the supported rpcInterfaces via web requests @@ -106,12 +111,14 @@ function startWebServer() { switch (browser) { case "chrome": if (process.platform === "darwin") { // Ie, if running on Mac - child_process.execSync("open -a \"Google Chrome\" http://localhost:3000"); + child_process.execSync('open -a "Google Chrome" http://localhost:3000'); } else { chromeLauncher.launch({ // eslint-disable-line @typescript-eslint/no-floating-promises startingUrl: "http://localhost:3000", chromeFlags, - }).then((val) => { DisplayPerfRpcInterface.chrome = val; }); + }).then((val) => { + DisplayPerfRpcInterface.chrome = val; + }); } break; case "edge": diff --git a/test-apps/display-performance-test-app/src/backend/backend.ts b/test-apps/display-performance-test-app/src/backend/backend.ts index a8ecdae70ed8..c207921ddff2 100644 --- a/test-apps/display-performance-test-app/src/backend/backend.ts +++ b/test-apps/display-performance-test-app/src/backend/backend.ts @@ -2,16 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import * as path from "path"; +import { IModelHost, IModelHostOptions } from "@itwin/core-backend"; import { ProcessDetector } from "@itwin/core-bentley"; +import { AuthorizationClient, IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface } from "@itwin/core-common"; import { ElectronHost } from "@itwin/core-electron/lib/cjs/ElectronBackend"; import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; -import { IModelHost, IModelHostOptions } from "@itwin/core-backend"; import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; import { IModelsClient } from "@itwin/imodels-client-authoring"; -import { AuthorizationClient, IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface } from "@itwin/core-common"; import { TestBrowserAuthorizationClient } from "@itwin/oidc-signin-tool"; +import * as fs from "fs"; +import * as path from "path"; import DisplayPerfRpcInterface from "../common/DisplayPerfRpcInterface"; import "./DisplayPerfRpcImpl"; // just to get the RPC implementation registered @@ -56,13 +56,15 @@ export async function initializeBackend() { async function initializeAuthorizationClient(): Promise { if (process.env.IMJS_OIDC_HEADLESS) { - if (!checkEnvVars( - "IMJS_OIDC_CLIENT_ID", - "IMJS_OIDC_REDIRECT_URI", - "IMJS_OIDC_SCOPE", - "IMJS_OIDC_EMAIL", - "IMJS_OIDC_PASSWORD", - )) + if ( + !checkEnvVars( + "IMJS_OIDC_CLIENT_ID", + "IMJS_OIDC_REDIRECT_URI", + "IMJS_OIDC_SCOPE", + "IMJS_OIDC_EMAIL", + "IMJS_OIDC_PASSWORD", + ) + ) return undefined; return new TestBrowserAuthorizationClient({ clientId: process.env.IMJS_OIDC_CLIENT_ID!, @@ -80,7 +82,9 @@ async function initializeAuthorizationClient(): Promise { - envConfig = {}; if (undefined !== process.env.IMJS_NO_DEV_TOOLS) envConfig.noDevTools = true; diff --git a/test-apps/display-performance-test-app/src/common/DisplayPerfRpcInterface.ts b/test-apps/display-performance-test-app/src/common/DisplayPerfRpcInterface.ts index aec13e4a95d7..3bf23fd39dc9 100644 --- a/test-apps/display-performance-test-app/src/common/DisplayPerfRpcInterface.ts +++ b/test-apps/display-performance-test-app/src/common/DisplayPerfRpcInterface.ts @@ -2,10 +2,10 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { RpcInterface, RpcManager, RpcOperation, RpcRequestTokenSupplier_T } from "@itwin/core-common"; import * as chromeLauncher from "chrome-launcher"; import * as http from "http"; import * as https from "https"; -import { RpcInterface, RpcManager, RpcOperation, RpcRequestTokenSupplier_T } from "@itwin/core-common"; import { DptaEnvConfig } from "./DisplayPerfEnvConfig"; const localDeploymentOnly: RpcRequestTokenSupplier_T = () => ({ iModelId: "none", key: "" }); @@ -28,27 +28,51 @@ export default class DisplayPerfRpcInterface extends RpcInterface { // eslint-di /** A chrome browser window, when testing with chrome */ public static chrome?: chromeLauncher.LaunchedChrome; - public static getClient(): DisplayPerfRpcInterface { return RpcManager.getClientForInterface(DisplayPerfRpcInterface); } + public static getClient(): DisplayPerfRpcInterface { + return RpcManager.getClientForInterface(DisplayPerfRpcInterface); + } @RpcOperation.setRoutingProps(localDeploymentOnly) - public async getDefaultConfigs(): Promise { return this.forward(arguments); } + public async getDefaultConfigs(): Promise { + return this.forward(arguments); + } - public async saveCsv(_outputPath: string, _outputName: string, _rowDataJson: string, _csvFormat?: string): Promise { return this.forward(arguments); } - public async savePng(_fileName: string, _png: string): Promise { return this.forward(arguments); } + public async saveCsv(_outputPath: string, _outputName: string, _rowDataJson: string, _csvFormat?: string): Promise { + return this.forward(arguments); + } + public async savePng(_fileName: string, _png: string): Promise { + return this.forward(arguments); + } @RpcOperation.setRoutingProps(localDeploymentOnly) - public async writeExternalFile(_outputPath: string, _outputName: string, _append: boolean, _content: string): Promise { return this.forward(arguments); } + public async writeExternalFile(_outputPath: string, _outputName: string, _append: boolean, _content: string): Promise { + return this.forward(arguments); + } @RpcOperation.setRoutingProps(localDeploymentOnly) - public async consoleLog(_content: string): Promise { return this.forward(arguments); } + public async consoleLog(_content: string): Promise { + return this.forward(arguments); + } - public async finishCsv(_output: string, _outputPath?: string, _outputName?: string, _csvFormat?: string): Promise { return this.forward(arguments); } - public async terminate(): Promise { return this.forward(arguments); } + public async finishCsv(_output: string, _outputPath?: string, _outputName?: string, _csvFormat?: string): Promise { + return this.forward(arguments); + } + public async terminate(): Promise { + return this.forward(arguments); + } - public async readExternalSavedViews(_filename: string): Promise { return this.forward(arguments); } - public async getMatchingFiles(_rootDir: string, _pattern: string): Promise { return this.forward(arguments); } + public async readExternalSavedViews(_filename: string): Promise { + return this.forward(arguments); + } + public async getMatchingFiles(_rootDir: string, _pattern: string): Promise { + return this.forward(arguments); + } - public async getAccessToken(): Promise { return this.forward(arguments); } + public async getAccessToken(): Promise { + return this.forward(arguments); + } - public async getEnvConfig(): Promise { return this.forward(arguments); } + public async getEnvConfig(): Promise { + return this.forward(arguments); + } } diff --git a/test-apps/display-performance-test-app/src/frontend/DisplayPerformanceTestApp.ts b/test-apps/display-performance-test-app/src/frontend/DisplayPerformanceTestApp.ts index 79824933be63..bb393680ce65 100644 --- a/test-apps/display-performance-test-app/src/frontend/DisplayPerformanceTestApp.ts +++ b/test-apps/display-performance-test-app/src/frontend/DisplayPerformanceTestApp.ts @@ -2,21 +2,25 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { BrowserAuthorizationClient } from "@itwin/browser-authorization/lib/cjs/Client"; import { ProcessDetector } from "@itwin/core-bentley"; import { - BentleyCloudRpcManager, IModelReadRpcInterface, IModelTileRpcInterface, RpcConfiguration, SnapshotIModelRpcInterface, + BentleyCloudRpcManager, + IModelReadRpcInterface, + IModelTileRpcInterface, + RpcConfiguration, + SnapshotIModelRpcInterface, } from "@itwin/core-common"; import { ElectronApp } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; -import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; -import { BrowserAuthorizationClient } from "@itwin/browser-authorization/lib/cjs/Client"; import { IModelApp, IModelAppOptions } from "@itwin/core-frontend"; +import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; import { initializeFrontendTiles } from "@itwin/frontend-tiles"; import { HyperModeling, SectionMarker, SectionMarkerHandler } from "@itwin/hypermodeling-frontend"; import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; import { IModelsClient } from "@itwin/imodels-client-management"; +import { DptaEnvConfig } from "../common/DisplayPerfEnvConfig"; import DisplayPerfRpcInterface from "../common/DisplayPerfRpcInterface"; import { TestRunner, TestSetsProps } from "./TestRunner"; -import { DptaEnvConfig } from "../common/DisplayPerfEnvConfig"; export const envConfiguration: DptaEnvConfig = {}; let runner: TestRunner; @@ -87,9 +91,11 @@ export class DisplayPerfTestApp { const config = await DisplayPerfRpcInterface.getClient().getEnvConfig(); Object.assign(envConfiguration, config); - const frontendTilesNopFallback = (runner && runner.curConfig && runner.curConfig.frontendTilesNopFallback) ? runner.curConfig.frontendTilesNopFallback : false; + const frontendTilesNopFallback = (runner && runner.curConfig && runner.curConfig.frontendTilesNopFallback) + ? runner.curConfig.frontendTilesNopFallback + : false; - if(frontendTilesNopFallback){ + if (frontendTilesNopFallback) { await DisplayPerfRpcInterface.getClient().consoleLog("Nop fallback enabled for frontend tiles."); } @@ -131,7 +137,8 @@ export class DisplayPerfTestApp { if (logFile) await client.writeExternalFile(logFile.dir, logFile.name, true, msg); // test for exception messages that need to terminate app on and return true for any of those - return (msg.toLowerCase().includes("rendering context was lost") || + return ( + msg.toLowerCase().includes("rendering context was lost") || msg.toLowerCase().includes("enospc") // ENOSPC no space left on device ); } @@ -181,7 +188,12 @@ window.onload = async () => { if (!ProcessDetector.isElectronAppFrontend && !ProcessDetector.isMobileAppFrontend) { const uriPrefix = "http://localhost:3001"; - BentleyCloudRpcManager.initializeClient({ info: { title: "DisplayPerformanceTestApp", version: "v1.0" }, uriPrefix }, [DisplayPerfRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface, IModelReadRpcInterface]); + BentleyCloudRpcManager.initializeClient({ info: { title: "DisplayPerformanceTestApp", version: "v1.0" }, uriPrefix }, [ + DisplayPerfRpcInterface, + IModelTileRpcInterface, + SnapshotIModelRpcInterface, + IModelReadRpcInterface, + ]); } await DisplayPerfTestApp.startup(); diff --git a/test-apps/display-performance-test-app/src/frontend/SavedViewsFetcher.ts b/test-apps/display-performance-test-app/src/frontend/SavedViewsFetcher.ts index 08ff89494380..96b1b3551b43 100644 --- a/test-apps/display-performance-test-app/src/frontend/SavedViewsFetcher.ts +++ b/test-apps/display-performance-test-app/src/frontend/SavedViewsFetcher.ts @@ -6,14 +6,14 @@ import { ViewStateProps } from "@itwin/core-common"; import { ViewStateSpec } from "./TestConfig"; export class SavedViewsFetcher { - private readonly _cache: {[iModelId: string]: ViewStateSpec[]} = {}; + private readonly _cache: { [iModelId: string]: ViewStateSpec[] } = {}; public async getSavedViews( iTwinId: string, iModelId: string, accessToken: string, ): Promise { - if(this._cache[iModelId]) + if (this._cache[iModelId]) return this._cache[iModelId]; const savedViewsList = await fetchSavedViewsList(iTwinId, iModelId, accessToken); @@ -23,7 +23,7 @@ export class SavedViewsFetcher { ); // Sanity check for the future - if(savedViews[0].savedView.savedViewData.legacyView === undefined) + if (savedViews[0].savedView.savedViewData.legacyView === undefined) throw new Error("Saved views API no longer returns legacyView"); const viewStateSpecs = savedViews.map((sv) => ({ @@ -67,7 +67,7 @@ interface SavedViewResponse { /** * Returns all saved view descriptions. * To get complete saved view data, call {@link fetchSavedView} - * */ + */ async function fetchSavedViewsList(projectId: string, iModelId: string, accessToken: string): Promise { return fetch( `https://${process.env.IMJS_URL_PREFIX}api.bentley.com/savedviews/?projectId=${projectId}&iModelId=${iModelId}`, @@ -76,7 +76,8 @@ async function fetchSavedViewsList(projectId: string, iModelId: string, accessTo headers: { Authorization: accessToken, // eslint-disable-line @typescript-eslint/naming-convention }, - }).then(async (response) => response.json()); + }, + ).then(async (response) => response.json()); } /** Returns the saved view with the actual view data */ diff --git a/test-apps/display-performance-test-app/src/frontend/TestConfig.ts b/test-apps/display-performance-test-app/src/frontend/TestConfig.ts index 2c39bedf79fc..e1b5c2828a43 100644 --- a/test-apps/display-performance-test-app/src/frontend/TestConfig.ts +++ b/test-apps/display-performance-test-app/src/frontend/TestConfig.ts @@ -4,9 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { assert, Id64Array, Id64String } from "@itwin/core-bentley"; -import { - BackgroundMapProps, ColorDef, Hilite, RenderMode, ViewFlags, ViewStateProps, -} from "@itwin/core-common"; +import { BackgroundMapProps, ColorDef, Hilite, RenderMode, ViewFlags, ViewStateProps } from "@itwin/core-common"; import { ModelDisplayTransformProvider, RenderSystem, TileAdmin } from "@itwin/core-frontend"; import { TransformProps } from "@itwin/core-geometry"; @@ -39,7 +37,7 @@ export type TestType = "timing" | "readPixels" | "image" | "both"; /** Specifies symbology overrides to apply to elements in a TestConfig. */ export interface ElementOverrideProps { /** The Id of the affected element, or "-default-" to apply to all elements not otherwise overridden. */ - id: Id64String | "-default-"; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents + id: Id64String | "-default-"; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents /** The symbology overrides to apply. */ fsa: string; // A stringified FeatureAppearanceProps. Why is all the JSON double-stringified??? } @@ -273,7 +271,6 @@ export class TestConfig { if (prevConfig.viewFlags) this.viewFlags = { ...prevConfig.viewFlags }; - } else if (props.argOutputPath) { this.outputPath = props.argOutputPath; } @@ -355,7 +352,12 @@ export class TestConfigStack { function hiliteSettings(settings: Hilite.Settings, props: HiliteProps): Hilite.Settings { const colors = settings.color.colors; const color = ColorDef.from(props?.red ?? colors.r, props?.green ?? colors.g, props?.blue ?? colors.b, 0); - return new Hilite.Settings(color, props.visibleRatio ?? settings.visibleRatio, props.hiddenRatio ?? settings.hiddenRatio, props.silhouette ?? settings.silhouette); + return new Hilite.Settings( + color, + props.visibleRatio ?? settings.visibleRatio, + props.hiddenRatio ?? settings.hiddenRatio, + props.silhouette ?? settings.silhouette, + ); } /** Merge two objects of type T such that any property defined by second overrides the value supplied for that property by first. diff --git a/test-apps/display-performance-test-app/src/frontend/TestRunner.ts b/test-apps/display-performance-test-app/src/frontend/TestRunner.ts index 4e36a2ffb850..a9ee72c31631 100644 --- a/test-apps/display-performance-test-app/src/frontend/TestRunner.ts +++ b/test-apps/display-performance-test-app/src/frontend/TestRunner.ts @@ -3,30 +3,61 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { RealityDataAccessClient, RealityDataClientOptions } from "@itwin/reality-data-client"; -import { - assert, Dictionary, Id64, Id64Array, Id64String, ProcessDetector, SortedArray, StopWatch, -} from "@itwin/core-bentley"; +import { assert, Dictionary, Id64, Id64Array, Id64String, ProcessDetector, SortedArray, StopWatch } from "@itwin/core-bentley"; import { - BackgroundMapType, BaseMapLayerSettings, DisplayStyleProps, FeatureAppearance, Hilite, RenderMode, ViewStateProps, + BackgroundMapType, + BaseMapLayerSettings, + DisplayStyleProps, + FeatureAppearance, + Hilite, + RenderMode, + ViewStateProps, } from "@itwin/core-common"; import { CheckpointConnection, - DisplayStyle3dState, DisplayStyleState, EntityState, FeatureSymbology, GLTimerResult, GLTimerResultCallback, IModelApp, IModelConnection, + DisplayStyle3dState, + DisplayStyleState, + EntityState, + FeatureSymbology, + GLTimerResult, + GLTimerResultCallback, + IModelApp, + IModelConnection, ModelDisplayTransform, ModelDisplayTransformProvider, - PerformanceMetrics, Pixel, RenderMemory, RenderSystem, ScreenViewport, SnapshotConnection, Target, TileAdmin, ToolAdmin, ViewRect, ViewState, + PerformanceMetrics, + Pixel, + RenderMemory, + RenderSystem, + ScreenViewport, + SnapshotConnection, + Target, + TileAdmin, + ToolAdmin, + ViewRect, + ViewState, } from "@itwin/core-frontend"; import { System } from "@itwin/core-frontend/lib/cjs/webgl"; +import { Transform } from "@itwin/core-geometry"; import { HyperModeling } from "@itwin/hypermodeling-frontend"; import { TestFrontendAuthorizationClient } from "@itwin/oidc-signin-tool/lib/cjs/TestFrontendAuthorizationClient"; +import { RealityDataAccessClient, RealityDataClientOptions } from "@itwin/reality-data-client"; import DisplayPerfRpcInterface from "../common/DisplayPerfRpcInterface"; import { DisplayPerfTestApp } from "./DisplayPerformanceTestApp"; +import { SavedViewsFetcher } from "./SavedViewsFetcher"; import { - defaultEmphasis, defaultHilite, DisplayTransformProviderProps, ElementOverrideProps, HyperModelingProps, separator, TestConfig, TestConfigProps, TestConfigStack, ViewStateSpec, ViewStateSpecProps, + defaultEmphasis, + defaultHilite, + DisplayTransformProviderProps, + ElementOverrideProps, + HyperModelingProps, + separator, + TestConfig, + TestConfigProps, + TestConfigStack, + ViewStateSpec, + ViewStateSpecProps, } from "./TestConfig"; -import { SavedViewsFetcher } from "./SavedViewsFetcher"; -import { Transform } from "@itwin/core-geometry"; /** JSON representation of a set of tests. Each test in the set inherits the test set's configuration. */ export interface TestSetProps extends TestConfigProps { @@ -100,9 +131,10 @@ class Timings { const label = result.label; const timings = this.gpu.get(label); this.gpu.set(label, timings ? timings.concat(result.nanoseconds / 1e6) : [result.nanoseconds / 1e6]); // save as milliseconds - if (result.children) + if (result.children) { for (const child of result.children) this.callback(child); + } if ("Total" === label) ++this.gpuFramesCollected; @@ -145,7 +177,7 @@ class OverrideProvider { class DisplayTransformProvider implements ModelDisplayTransformProvider { private readonly _transforms = new Map(); - private constructor() { } + private constructor() {} public static fromJSON(props: DisplayTransformProviderProps): DisplayTransformProvider { const provider = new DisplayTransformProvider(); @@ -177,7 +209,9 @@ export class TestRunner { return this._config.top; } - public get lastRestartConfig(): TestConfig { return this._lastRestartConfig; } + public get lastRestartConfig(): TestConfig { + return this._lastRestartConfig; + } public set lastRestartConfig(config: TestConfig) { this._lastRestartConfig = config; } @@ -213,7 +247,9 @@ export class TestRunner { const renderOptions: RenderSystem.Options = this.curConfig.renderOptions ?? {}; if (!this.curConfig.useDisjointTimer) { const ext = this.curConfig.renderOptions?.disabledExtensions; - renderOptions.disabledExtensions = Array.isArray(ext) ? ext.concat(["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]) : ["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]; + renderOptions.disabledExtensions = Array.isArray(ext) + ? ext.concat(["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]) + : ["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]; needRestart = true; } if (IModelApp.initialized && needRestart) { @@ -274,7 +310,9 @@ export class TestRunner { const renderOptions: RenderSystem.Options = this.curConfig.renderOptions ?? {}; if (!this.curConfig.useDisjointTimer) { const ext = this.curConfig.renderOptions?.disabledExtensions; - renderOptions.disabledExtensions = Array.isArray(ext) ? ext.concat(["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]) : ["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]; + renderOptions.disabledExtensions = Array.isArray(ext) + ? ext.concat(["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]) + : ["EXT_disjoint_timer_query", "EXT_disjoint_timer_query_webgl2"]; } await DisplayPerfTestApp.startup({ renderSys: renderOptions, @@ -291,7 +329,9 @@ export class TestRunner { for (const iModelName of iModelNames) { this.curConfig.iModelName = iModelName; this.curConfig.viewName = originalViewName; - const iModelKey = this.curConfig.iModelId ? this.curConfig.iModelId : `${this.curConfig.iModelLocation}${separator}${this.curConfig.iModelName}`; + const iModelKey = this.curConfig.iModelId + ? this.curConfig.iModelId + : `${this.curConfig.iModelLocation}${separator}${this.curConfig.iModelName}`; try { const reuseContext = context && set.reuseContext && context.iModelKey === iModelKey; @@ -389,7 +429,7 @@ export class TestRunner { // Collect CPU timings. setPerformanceMetrics(vp, new PerformanceMetrics(true, false, undefined)); for (let i = 0; i < this.curConfig.numRendersToTime; ++i) { - vp.readPixels(viewRect, pixSelect, () => { }); + vp.readPixels(viewRect, pixSelect, () => {}); timings.cpu[i] = (vp.target as Target).performanceMetrics!.frameTimings; timings.cpu[i].delete("Scene Time"); } @@ -765,7 +805,7 @@ export class TestRunner { } private async finish(): Promise { - let renderData = "\"End of Tests-----------\r\n"; + let renderData = '"End of Tests-----------\r\n'; const renderComp = IModelApp.queryRenderCompatibility(); if (renderComp.userAgent) { renderData += `Browser: ${getBrowserName(renderComp.userAgent)}\r\n`; @@ -1150,11 +1190,16 @@ function removeOptsFromString(input: string, ignore: string[] | string | undefin function getRenderMode(vp: ScreenViewport): string { switch (vp.viewFlags.renderMode) { - case RenderMode.Wireframe: return "Wireframe"; - case RenderMode.HiddenLine: return "HiddenLine"; - case RenderMode.SolidFill: return "SolidFill"; - case RenderMode.SmoothShade: return "SmoothShade"; - default: return ""; + case RenderMode.Wireframe: + return "Wireframe"; + case RenderMode.HiddenLine: + return "HiddenLine"; + case RenderMode.SolidFill: + return "SolidFill"; + case RenderMode.SmoothShade: + return "SmoothShade"; + default: + return ""; } } @@ -1297,7 +1342,8 @@ function getBackgroundMapProps(vp: ScreenViewport): string { function hiliteSettingsStr(settings: Hilite.Settings): string { let hsStr = (settings.color.colors.r * 256 * 256 + settings.color.colors.g * 256 + settings.color.colors.b).toString(36).padStart(5, "0"); - hsStr += (settings.silhouette * 256 * 256 + Math.round(settings.visibleRatio * 255) * 256 + Math.round(settings.hiddenRatio * 255)).toString(36).padStart(4, "0"); + hsStr += (settings.silhouette * 256 * 256 + Math.round(settings.visibleRatio * 255) * 256 + Math.round(settings.hiddenRatio * 255)).toString(36) + .padStart(4, "0"); return hsStr.toUpperCase(); } diff --git a/test-apps/display-performance-test-app/tsconfig.json b/test-apps/display-performance-test-app/tsconfig.json index e3adbc43819c..0f57424a69b4 100644 --- a/test-apps/display-performance-test-app/tsconfig.json +++ b/test-apps/display-performance-test-app/tsconfig.json @@ -16,7 +16,7 @@ "dom.iterable", "esnext" ], - "types": ["vite/client"], + "types": ["vite/client"] }, "include": [ "./src/**/*.ts" diff --git a/test-apps/display-performance-test-app/vite.config.mts b/test-apps/display-performance-test-app/vite.config.mts index f594326f673b..f88c0decda65 100644 --- a/test-apps/display-performance-test-app/vite.config.mts +++ b/test-apps/display-performance-test-app/vite.config.mts @@ -2,22 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { defineConfig, loadEnv, searchForWorkspaceRoot } from "vite"; -import envCompatible from "vite-plugin-env-compatible"; import browserslistToEsbuild from "browserslist-to-esbuild"; -import viteInspect from "vite-plugin-inspect"; +import { createRequire } from "module"; +import path from "path"; import copy from "rollup-plugin-copy"; +import externalGlobals from "rollup-plugin-external-globals"; import ignore from "rollup-plugin-ignore"; import rollupVisualizer from "rollup-plugin-visualizer"; -import externalGlobals from "rollup-plugin-external-globals"; import { webpackStats } from "rollup-plugin-webpack-stats"; +import { defineConfig, loadEnv, searchForWorkspaceRoot } from "vite"; +import envCompatible from "vite-plugin-env-compatible"; +import viteInspect from "vite-plugin-inspect"; import * as packageJson from "./package.json"; -import path from "path"; -import { createRequire } from "module"; const require = createRequire(import.meta.url); -const mode = - process.env.NODE_ENV === "development" ? "development" : "production"; +const mode = process.env.NODE_ENV === "development" ? "development" : "production"; // array of public directories static assets from dependencies to copy const assets = ["./public/*"]; // assets for test-app @@ -89,19 +88,19 @@ export default defineConfig(() => { plugins: [ ...(process.env.OUTPUT_STATS !== undefined ? [ - rollupVisualizer({ - open: true, - filename: "stats.html", - template: "treemap", - sourcemap: true, - }), - webpackStats(), // needs to be the last plugin - ] + rollupVisualizer({ + open: true, + filename: "stats.html", + template: "treemap", + sourcemap: true, + }), + webpackStats(), // needs to be the last plugin + ] : []), externalGlobals({ // allow global `window` object to access electron as external global electron: "window['electron']", - }) + }), ], }, }, @@ -136,10 +135,8 @@ export default defineConfig(() => { resolve: { alias: { ...packageAliases, - "@itwin/core-electron/lib/cjs/ElectronFrontend": - "@itwin/core-electron/src/ElectronFrontend.ts", - "@itwin/core-mobile/lib/cjs/MobileFrontend": - "@itwin/core-mobile/src/MobileFrontend.ts", + "@itwin/core-electron/lib/cjs/ElectronFrontend": "@itwin/core-electron/src/ElectronFrontend.ts", + "@itwin/core-mobile/lib/cjs/MobileFrontend": "@itwin/core-mobile/src/MobileFrontend.ts", "../../package.json": "../package.json", // in core-frontend }, }, @@ -151,8 +148,8 @@ export default defineConfig(() => { "@itwin/core-mobile/lib/cjs/MobileFrontend", // import from module error ], exclude: [ - "@itwin/core-frontend", //prevents import not resolved errors - "@itwin/core-common", //prevents rpc errors + "@itwin/core-frontend", // prevents import not resolved errors + "@itwin/core-common", // prevents rpc errors ], }, }; diff --git a/test-apps/display-test-app/.vscode/settings.json b/test-apps/display-test-app/.vscode/settings.json index d20457a76f59..5eeef001fcd8 100644 --- a/test-apps/display-test-app/.vscode/settings.json +++ b/test-apps/display-test-app/.vscode/settings.json @@ -1,6 +1,6 @@ { - "search.exclude": { - "/build": true, - "/lib": true - } -} \ No newline at end of file + "search.exclude": { + "/build": true, + "/lib": true + } +} diff --git a/test-apps/display-test-app/buildEnvJson.ts b/test-apps/display-test-app/buildEnvJson.ts index 2e8411264c25..17db49cbd408 100644 --- a/test-apps/display-test-app/buildEnvJson.ts +++ b/test-apps/display-test-app/buildEnvJson.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ /* eslint-disable no-console */ -import * as fs from "fs"; -import * as path from "path"; import * as dotenv from "dotenv"; import dotenvExpand from "dotenv-expand"; +import * as fs from "fs"; +import * as path from "path"; /** Loads the provided `.env` file into process.env */ function loadEnv(envFile: string) { diff --git a/test-apps/display-test-app/eslint.config.js b/test-apps/display-test-app/eslint.config.js index d9db2a9ef05c..4cb1311a12ac 100644 --- a/test-apps/display-test-app/eslint.config.js +++ b/test-apps/display-test-app/eslint.config.js @@ -9,12 +9,12 @@ const customLanguageOptions = { "./tsconfig.json", "./tsconfig.backend.json", "./tsconfig.buildScripts.json", - "./vite.config.ts" + "./vite.config.ts", ], ecmaVersion: "latest", ecmaFeatures: { jsx: true, - modules: true + modules: true, }, }, }; @@ -23,7 +23,7 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - languageOptions: customLanguageOptions + languageOptions: customLanguageOptions, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json b/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d65fd79..c950192fe8ac 100644 --- a/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1,98 @@ { - "images" : [ + "images": [ { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "idiom": "iphone", + "size": "20x20", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "idiom": "iphone", + "size": "20x20", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "idiom": "iphone", + "size": "29x29", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "idiom": "iphone", + "size": "29x29", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "idiom": "iphone", + "size": "40x40", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "idiom": "iphone", + "size": "40x40", + "scale": "3x" }, { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "idiom": "iphone", + "size": "60x60", + "scale": "2x" }, { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "idiom": "iphone", + "size": "60x60", + "scale": "3x" }, { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "idiom": "ipad", + "size": "20x20", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "idiom": "ipad", + "size": "20x20", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "idiom": "ipad", + "size": "29x29", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "idiom": "ipad", + "size": "29x29", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "idiom": "ipad", + "size": "40x40", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "idiom": "ipad", + "size": "40x40", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "idiom": "ipad", + "size": "76x76", + "scale": "1x" }, { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "idiom": "ipad", + "size": "76x76", + "scale": "2x" }, { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "idiom": "ipad", + "size": "83.5x83.5", + "scale": "2x" }, { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" + "idiom": "ios-marketing", + "size": "1024x1024", + "scale": "1x" } ], - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/Contents.json b/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/Contents.json index da4a164c9186..97a8662ebdb4 100644 --- a/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/Contents.json +++ b/test-apps/display-test-app/ios/imodeljs-test-app/imodeljs-test-app/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "version" : 1, - "author" : "xcode" + "info": { + "version": 1, + "author": "xcode" } -} \ No newline at end of file +} diff --git a/test-apps/display-test-app/package.json b/test-apps/display-test-app/package.json index 870f5834b461..e4cdb5b1e7ac 100644 --- a/test-apps/display-test-app/package.json +++ b/test-apps/display-test-app/package.json @@ -126,4 +126,4 @@ "not dead", "not <0.2%" ] -} \ No newline at end of file +} diff --git a/test-apps/display-test-app/public/locales/en/SVTTools.json b/test-apps/display-test-app/public/locales/en/SVTTools.json index 82336cdd7394..5cfd982c0a76 100644 --- a/test-apps/display-test-app/public/locales/en/SVTTools.json +++ b/test-apps/display-test-app/public/locales/en/SVTTools.json @@ -204,4 +204,4 @@ "keyin": "dta imodel attach" } } -} \ No newline at end of file +} diff --git a/test-apps/display-test-app/runIosSimulator.ts b/test-apps/display-test-app/runIosSimulator.ts index 4928b555f978..f438b1711f1b 100644 --- a/test-apps/display-test-app/runIosSimulator.ts +++ b/test-apps/display-test-app/runIosSimulator.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { copyFile } from 'fs/promises'; +import { copyFile } from "fs/promises"; // Can't use import here otherwise Typescript complains: Could not find a declaration file for module 'node-simctl'. const Simctl = require("node-simctl").default; // Constants used in the script for convenience -const appName = "imodeljs-test-app" +const appName = "imodeljs-test-app"; const bundleId = `bentley.${appName}`; const assetsPath = `${__dirname}/test-models`; const bimFile = "JoesHouse.bim"; @@ -17,16 +17,16 @@ const bimFile = "JoesHouse.bim"; const numericCompareDescending = (a: string, b: string) => b.localeCompare(a, undefined, { numeric: true }); // Similar to the launchApp function but doesn't retry, adds options before the launch command, and allows for args. -Simctl.prototype.launchAppWithOptions = async function (bundleId: string, options: [string], args: [string]) { - const { stdout } = await this.exec('launch', { - args: [...options, this.requireUdid('launch'), bundleId, ...args], +Simctl.prototype.launchAppWithOptions = async function(bundleId: string, options: [string], args: [string]) { + const { stdout } = await this.exec("launch", { + args: [...options, this.requireUdid("launch"), bundleId, ...args], architectures: "x86_64", }); return stdout.trim(); -} +}; -Simctl.prototype.getLatestRuntimeVersion = async function (majorVersion: string, platform = 'iOS') { - const { stdout } = await this.exec('list', { args: ['runtimes', '--json'] }); +Simctl.prototype.getLatestRuntimeVersion = async function(majorVersion: string, platform = "iOS") { + const { stdout } = await this.exec("list", { args: ["runtimes", "--json"] }); const runtimes: [{ version: string, identifier: string, name: string }] = JSON.parse(stdout).runtimes; runtimes.sort((a, b) => numericCompareDescending(a.version, b.version)); for (const { version, name } of runtimes) { @@ -49,10 +49,10 @@ async function main() { // get all iOS devices log("Getting iOS devices"); - const allResults = await simctl.getDevices(undefined, 'iOS'); + const allResults = await simctl.getDevices(undefined, "iOS"); // If xcode-select picks an earlier Xcode, allResults can contain entries for newer iOS versions with // no actual data. The below filters out the empty entries. - const results = Object.assign({}, ...Object.entries(allResults).filter(([_k, v]) => (v as [any]).length > 0).map(([k, v]) => ({[k]:v}))); + const results = Object.assign({}, ...Object.entries(allResults).filter(([_k, v]) => (v as [any]).length > 0).map(([k, v]) => ({ [k]: v }))); var keys = Object.keys(results).sort(numericCompareDescending); // determine desired device and runtime @@ -60,18 +60,18 @@ async function main() { var desiredDevice = `${deviceBaseName} (2nd generation)`; var desiredRuntime = keys.length > 0 ? keys[0] : "16"; - keys = keys.filter(key => key.startsWith(desiredRuntime)); - var device: { name: string; sdk: string; udid: string; state: string; } | undefined; + keys = keys.filter((key) => key.startsWith(desiredRuntime)); + var device: { name: string, sdk: string, udid: string, state: string } | undefined; if (keys.length) { // Look for a booted simulator for (const key of keys) { - device = results[key].find((curr: { state: string; }) => curr.state === "Booted"); + device = results[key].find((curr: { state: string }) => curr.state === "Booted"); if (device) break; } // If none are booted, use the deviceBaseName or fall back to the first one if (!device) { - device = results[keys[0]].find((device: { name: string; }) => device.name.startsWith(deviceBaseName)) ?? results[keys[0]][0]; + device = results[keys[0]].find((device: { name: string }) => device.name.startsWith(deviceBaseName)) ?? results[keys[0]][0]; } } else { // try to create a simulator @@ -83,12 +83,12 @@ async function main() { log(`Creating simulator: ${desiredDevice} sdk: ${sdk}`); const udid = await simctl.createDevice(desiredDevice, desiredDevice, sdk); if (udid) { - device = { name: desiredDevice, sdk, udid, state: 'Inactive' }; + device = { name: desiredDevice, sdk, udid, state: "Inactive" }; } } if (!device) { - log(`Unable to find an iOS ${desiredRuntime} simulator.`) + log(`Unable to find an iOS ${desiredRuntime} simulator.`); return; } diff --git a/test-apps/display-test-app/src/backend/Backend.ts b/test-apps/display-test-app/src/backend/Backend.ts index 855916e36750..f6b4825171f3 100644 --- a/test-apps/display-test-app/src/backend/Backend.ts +++ b/test-apps/display-test-app/src/backend/Backend.ts @@ -2,22 +2,30 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import * as path from "path"; -import { Logger, LogLevel, ProcessDetector } from "@itwin/core-bentley"; -import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; -import { ElectronHost, ElectronHostOptions } from "@itwin/core-electron/lib/cjs/ElectronBackend"; -import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; -import { IModelsClient } from "@itwin/imodels-client-authoring"; import { IModelDb, IModelHost, IModelHostOptions, LocalhostIpcHost, produceTextAnnotationGeometry } from "@itwin/core-backend"; +import { Logger, LogLevel, ProcessDetector } from "@itwin/core-bentley"; import { - IModelReadRpcInterface, IModelRpcProps, IModelTileRpcInterface, RpcInterfaceDefinition, RpcManager, SnapshotIModelRpcInterface, TextAnnotation, TextAnnotationProps, TextBlockGeometryProps, + IModelReadRpcInterface, + IModelRpcProps, + IModelTileRpcInterface, + RpcInterfaceDefinition, + RpcManager, + SnapshotIModelRpcInterface, + TextAnnotation, + TextAnnotationProps, + TextBlockGeometryProps, } from "@itwin/core-common"; +import { ElectronHost, ElectronHostOptions } from "@itwin/core-electron/lib/cjs/ElectronBackend"; import { MobileHost, MobileHostOpts } from "@itwin/core-mobile/lib/cjs/MobileBackend"; -import { DtaConfiguration, getConfig } from "../common/DtaConfiguration"; -import { DtaRpcInterface } from "../common/DtaRpcInterface"; import { EditCommandAdmin } from "@itwin/editor-backend"; import * as editorBuiltInCommands from "@itwin/editor-backend"; +import { ElectronMainAuthorization } from "@itwin/electron-authorization/Main"; +import { BackendIModelsAccess } from "@itwin/imodels-access-backend"; +import { IModelsClient } from "@itwin/imodels-client-authoring"; +import * as fs from "fs"; +import * as path from "path"; +import { DtaConfiguration, getConfig } from "../common/DtaConfiguration"; +import { DtaRpcInterface } from "../common/DtaRpcInterface"; /** Loads the provided `.env` file into process.env */ function loadEnv(envFile: string) { @@ -35,7 +43,6 @@ function loadEnv(envFile: string) { } class DisplayTestAppRpc extends DtaRpcInterface { - public override async readExternalSavedViews(bimFileName: string): Promise { if (ProcessDetector.isMobileAppBackend && process.env.DOCS) { const docPath = process.env.DOCS; @@ -167,7 +174,6 @@ class DisplayTestAppRpc extends DtaRpcInterface { if (app !== undefined) app.exit(); } catch { - } // Browser only @@ -179,7 +185,11 @@ class DisplayTestAppRpc extends DtaRpcInterface { return (await IModelHost.authorizationClient?.getAccessToken()) ?? ""; } - public override async produceTextAnnotationGeometry(iModelToken: IModelRpcProps, annotationProps: TextAnnotationProps, debugAnchorPointAndRange?: boolean): Promise { + public override async produceTextAnnotationGeometry( + iModelToken: IModelRpcProps, + annotationProps: TextAnnotationProps, + debugAnchorPointAndRange?: boolean, + ): Promise { const iModel = IModelDb.findByKey(iModelToken.key); const annotation = TextAnnotation.fromJSON(annotationProps); return produceTextAnnotationGeometry({ iModel, annotation, debugAnchorPointAndRange }); @@ -266,9 +276,9 @@ async function initializeAuthorizationClient(): Promise { }; class DtaHandler extends IpcHandler implements DtaIpcInterface { - public get channelName() { return dtaChannel; } + public get channelName() { + return dtaChannel; + } public async sayHello() { return "Hello from backend"; } diff --git a/test-apps/display-test-app/src/backend/MobileMain.ts b/test-apps/display-test-app/src/backend/MobileMain.ts index ce2339cb9bf6..14e8e869d8c0 100644 --- a/test-apps/display-test-app/src/backend/MobileMain.ts +++ b/test-apps/display-test-app/src/backend/MobileMain.ts @@ -6,7 +6,7 @@ import { MobileHostOpts } from "@itwin/core-mobile/lib/cjs/MobileBackend"; import { getRpcInterfaces, initializeDtaBackend } from "./Backend"; -const dtaMobileMain = (async () => { +const dtaMobileMain = async () => { const opts: MobileHostOpts = { mobileHost: { rpcInterfaces: getRpcInterfaces(), @@ -15,7 +15,7 @@ const dtaMobileMain = (async () => { // Initialize the backend await initializeDtaBackend(opts); -}); +}; // eslint-disable-next-line @typescript-eslint/no-floating-promises dtaMobileMain(); diff --git a/test-apps/display-test-app/src/backend/SectionDrawingImpl.ts b/test-apps/display-test-app/src/backend/SectionDrawingImpl.ts index a7f6ea08685f..0402cc71d941 100644 --- a/test-apps/display-test-app/src/backend/SectionDrawingImpl.ts +++ b/test-apps/display-test-app/src/backend/SectionDrawingImpl.ts @@ -7,9 +7,17 @@ import { SectionDrawing, SpatialViewDefinition, } from "@itwin/core-backend"; -import { TransformProps } from "@itwin/core-geometry"; -import { DbResult, DisplayStyle3dProps, GeometricModel2dProps, RelatedElementProps, SectionDrawingProps, SectionType, SpatialViewDefinitionProps } from "@itwin/core-common"; import { Id64, Id64String } from "@itwin/core-bentley"; +import { + DbResult, + DisplayStyle3dProps, + GeometricModel2dProps, + RelatedElementProps, + SectionDrawingProps, + SectionType, + SpatialViewDefinitionProps, +} from "@itwin/core-common"; +import { TransformProps } from "@itwin/core-geometry"; import { CreateSectionDrawingViewArgs, CreateSectionDrawingViewResult } from "../common/DtaIpcInterface"; /** Find or create a document partition named" DrawingProductionDrawing" to contain all our section drawings. */ @@ -45,7 +53,12 @@ async function getDrawingProductionListModel(db: BriefcaseDb): Promise { +async function insertSectionDrawing( + db: BriefcaseDb, + spatialViewId: Id64String, + baseName: string, + drawingToSpatialTransform: TransformProps, +): Promise { const documentListModelId = await getDrawingProductionListModel(db); const sectionDrawingProps: SectionDrawingProps = { classFullName: "BisCore:SectionDrawing", @@ -82,7 +95,10 @@ async function insertSectionDrawing(db: BriefcaseDb, spatialViewId: Id64String, } /** Insert the spatial view and its related model+category selectors and display style. */ -function insertSpatialView(db: BriefcaseDb, args: Pick): Id64String { +function insertSpatialView( + db: BriefcaseDb, + args: Pick, +): Id64String { const dictionary = BriefcaseDb.dictionaryId; const modelSelectorId = ModelSelector.insert(db, dictionary, args.baseName, args.models); const categorySelectorId = CategorySelector.insert(db, dictionary, args.baseName, args.categories); @@ -117,7 +133,7 @@ export async function createSectionDrawing(args: CreateSectionDrawingViewArgs): try { // Our definition elements will all be inserted into the briefcase's dictionary model, so we must obtain a shared lock on it. - await db.locks.acquireLocks({ shared: [ BriefcaseDb.dictionaryId ] }); + await db.locks.acquireLocks({ shared: [BriefcaseDb.dictionaryId] }); const spatialViewId = insertSpatialView(db, args); const sectionDrawingId = await insertSectionDrawing(db, spatialViewId, args.baseName, args.drawingToSpatialTransform); diff --git a/test-apps/display-test-app/src/backend/SetToStandalone.ts b/test-apps/display-test-app/src/backend/SetToStandalone.ts index 864719b67758..fdb63e33cb13 100644 --- a/test-apps/display-test-app/src/backend/SetToStandalone.ts +++ b/test-apps/display-test-app/src/backend/SetToStandalone.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import * as path from "path"; -import { Guid, OpenMode } from "@itwin/core-bentley"; import { IModelHost, IModelNative } from "@itwin/core-backend"; +import { Guid, OpenMode } from "@itwin/core-bentley"; import { BriefcaseIdValue } from "@itwin/core-common"; +import * as fs from "fs"; +import * as path from "path"; let prefix = ""; diff --git a/test-apps/display-test-app/src/backend/WebMain.ts b/test-apps/display-test-app/src/backend/WebMain.ts index 15d34a2506ab..a4782690a222 100644 --- a/test-apps/display-test-app/src/backend/WebMain.ts +++ b/test-apps/display-test-app/src/backend/WebMain.ts @@ -2,20 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { LocalhostIpcHost } from "@itwin/core-backend"; +import { Logger } from "@itwin/core-bentley"; +import { BentleyCloudRpcConfiguration, BentleyCloudRpcManager } from "@itwin/core-common"; import * as express from "express"; +import * as enableWs from "express-ws"; import * as fs from "fs"; import * as https from "https"; -import * as enableWs from "express-ws"; -import { Logger } from "@itwin/core-bentley"; -import { BentleyCloudRpcConfiguration, BentleyCloudRpcManager } from "@itwin/core-common"; -import { getRpcInterfaces, initializeDtaBackend } from "./Backend"; -import { LocalhostIpcHost } from "@itwin/core-backend"; import { DtaRpcInterface } from "../common/DtaRpcInterface"; +import { getRpcInterfaces, initializeDtaBackend } from "./Backend"; /* eslint-disable no-console */ // function called when we start the backend webserver -const dtaWebMain = (async () => { +const dtaWebMain = async () => { // Initialize our backend await initializeDtaBackend(); @@ -31,7 +31,7 @@ const dtaWebMain = (async () => { key: fs.readFileSync(serverConfig.keyFile), cert: fs.readFileSync(serverConfig.certFile), }; - } catch (_err) { } + } catch (_err) {} } if (serverConfig === undefined) @@ -75,7 +75,7 @@ const dtaWebMain = (async () => { } else { DtaRpcInterface.backendServer = https.createServer(serverOptions, app).listen(app.get("port"), announce); } -}); +}; // eslint-disable-next-line @typescript-eslint/no-floating-promises dtaWebMain(); diff --git a/test-apps/display-test-app/src/common/DtaConfiguration.ts b/test-apps/display-test-app/src/common/DtaConfiguration.ts index 3d3699151c55..39e75fa88097 100644 --- a/test-apps/display-test-app/src/common/DtaConfiguration.ts +++ b/test-apps/display-test-app/src/common/DtaConfiguration.ts @@ -41,8 +41,8 @@ export interface DtaStringConfiguration { viewName?: string; iModelName?: string; filename?: string; - standalonePath?: string; // Used when run in the browser - a common base path for all standalone imodels - startupMacro?: string; // Used when running a macro at startup, specifies file path + standalonePath?: string; // Used when run in the browser - a common base path for all standalone imodels + startupMacro?: string; // Used when running a macro at startup, specifies file path iTwinId?: GuidString; // default is undefined, used by spatial classification to query reality data from context share, and by iModel download mapBoxKey?: string; // default undefined bingMapsKey?: string; // default undefined diff --git a/test-apps/display-test-app/src/common/DtaRpcInterface.ts b/test-apps/display-test-app/src/common/DtaRpcInterface.ts index 115b20b1901c..6372492b7692 100644 --- a/test-apps/display-test-app/src/common/DtaRpcInterface.ts +++ b/test-apps/display-test-app/src/common/DtaRpcInterface.ts @@ -21,15 +21,41 @@ export class DtaRpcInterface extends RpcInterface { // eslint-disable-line depre /** The backend server, when running on a browser */ public static backendServer: http.Server | https.Server | undefined; - public static getClient(): DtaRpcInterface { return RpcManager.getClientForInterface(DtaRpcInterface); } - public async readExternalSavedViews(_filename: string): Promise { return this.forward(arguments); } - public async writeExternalSavedViews(_filename: string, _namedViews: string): Promise { return this.forward(arguments); } - public async readExternalCameraPaths(_filename: string): Promise { return this.forward(arguments); } - public async writeExternalCameraPaths(_filename: string, _cameraPaths: string): Promise { return this.forward(arguments); } - public async readExternalFile(_filename: string): Promise { return this.forward(arguments); } - public async writeExternalFile(_filename: string, _content: string): Promise { return this.forward(arguments); } - public async terminate(): Promise { return this.forward(arguments); } - public async getEnvConfig(): Promise { return this.forward(arguments); } - public async getAccessToken(): Promise { return this.forward(arguments); } - public async produceTextAnnotationGeometry(_iModelToken: IModelRpcProps, _annotation: TextAnnotationProps, _debugAnchorPointAndRange?: boolean): Promise { return this.forward(arguments); } + public static getClient(): DtaRpcInterface { + return RpcManager.getClientForInterface(DtaRpcInterface); + } + public async readExternalSavedViews(_filename: string): Promise { + return this.forward(arguments); + } + public async writeExternalSavedViews(_filename: string, _namedViews: string): Promise { + return this.forward(arguments); + } + public async readExternalCameraPaths(_filename: string): Promise { + return this.forward(arguments); + } + public async writeExternalCameraPaths(_filename: string, _cameraPaths: string): Promise { + return this.forward(arguments); + } + public async readExternalFile(_filename: string): Promise { + return this.forward(arguments); + } + public async writeExternalFile(_filename: string, _content: string): Promise { + return this.forward(arguments); + } + public async terminate(): Promise { + return this.forward(arguments); + } + public async getEnvConfig(): Promise { + return this.forward(arguments); + } + public async getAccessToken(): Promise { + return this.forward(arguments); + } + public async produceTextAnnotationGeometry( + _iModelToken: IModelRpcProps, + _annotation: TextAnnotationProps, + _debugAnchorPointAndRange?: boolean, + ): Promise { + return this.forward(arguments); + } } diff --git a/test-apps/display-test-app/src/frontend/AmbientOcclusion.ts b/test-apps/display-test-app/src/frontend/AmbientOcclusion.ts index a55af75c19c1..c1cdc9fc2f71 100644 --- a/test-apps/display-test-app/src/frontend/AmbientOcclusion.ts +++ b/test-apps/display-test-app/src/frontend/AmbientOcclusion.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { createButton, createCheckBox, createSlider, Slider } from "@itwin/frontend-devtools"; import { AmbientOcclusion, RenderMode, ViewFlags } from "@itwin/core-common"; import { Viewport, ViewState, ViewState3d } from "@itwin/core-frontend"; +import { createButton, createCheckBox, createSlider, Slider } from "@itwin/frontend-devtools"; export class AmbientOcclusionEditor { private readonly _vp: Viewport; @@ -59,9 +59,10 @@ export class AmbientOcclusionEditor { max: "1.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.bias = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.bias = parseFloat(slider.value); + }), }); this._aoZLengthCap = createSlider({ @@ -73,9 +74,10 @@ export class AmbientOcclusionEditor { max: "0.25", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.zLengthCap = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.zLengthCap = parseFloat(slider.value); + }), }); this._aoMaxDistance = createSlider({ @@ -87,9 +89,10 @@ export class AmbientOcclusionEditor { max: "50000.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.maxDistance = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.maxDistance = parseFloat(slider.value); + }), }); this._aoIntensity = createSlider({ @@ -101,9 +104,10 @@ export class AmbientOcclusionEditor { max: "16.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.intensity = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.intensity = parseFloat(slider.value); + }), }); this._aoTexelStepSize = createSlider({ @@ -115,9 +119,10 @@ export class AmbientOcclusionEditor { max: "50.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.texelStepSize = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.texelStepSize = parseFloat(slider.value); + }), }); this._aoBlurDelta = createSlider({ @@ -129,9 +134,10 @@ export class AmbientOcclusionEditor { max: "1.5", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.blurDelta = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.blurDelta = parseFloat(slider.value); + }), }); this._aoBlurSigma = createSlider({ @@ -143,9 +149,10 @@ export class AmbientOcclusionEditor { max: "5.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.blurSigma = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.blurSigma = parseFloat(slider.value); + }), }); this._aoBlurTexelStepSize = createSlider({ @@ -157,9 +164,10 @@ export class AmbientOcclusionEditor { max: "5.0", value: "0.0", readout: "right", - handler: (slider) => this.updateAmbientOcclusion((aoProps) => { - aoProps.blurTexelStepSize = parseFloat(slider.value); - }), + handler: (slider) => + this.updateAmbientOcclusion((aoProps) => { + aoProps.blurTexelStepSize = parseFloat(slider.value); + }), }); const resetButton = createButton({ diff --git a/test-apps/display-test-app/src/frontend/AnalysisStyleExample.ts b/test-apps/display-test-app/src/frontend/AnalysisStyleExample.ts index 277084bf84d1..35cd3404008a 100644 --- a/test-apps/display-test-app/src/frontend/AnalysisStyleExample.ts +++ b/test-apps/display-test-app/src/frontend/AnalysisStyleExample.ts @@ -4,13 +4,31 @@ *--------------------------------------------------------------------------------------------*/ import { assert } from "@itwin/core-bentley"; -import { Angle, AuxChannel, AuxChannelData, AuxChannelDataType, IModelJson, Point3d, Polyface, PolyfaceAuxData, PolyfaceBuilder, StrokeOptions, Transform } from "@itwin/core-geometry"; import { - AnalysisStyle, AnalysisStyleProps, ColorByName, ColorDef, RenderMode, SkyBox, ThematicGradientColorScheme, ThematicGradientMode, ThematicGradientSettingsProps, + AnalysisStyle, + AnalysisStyleProps, + ColorByName, + ColorDef, + RenderMode, + SkyBox, + ThematicGradientColorScheme, + ThematicGradientMode, + ThematicGradientSettingsProps, } from "@itwin/core-common"; +import { DecorateContext, GraphicType, IModelApp, RenderGraphicOwner, StandardViewId, Viewport } from "@itwin/core-frontend"; import { - DecorateContext, GraphicType, IModelApp, RenderGraphicOwner, StandardViewId, Viewport, -} from "@itwin/core-frontend"; + Angle, + AuxChannel, + AuxChannelData, + AuxChannelDataType, + IModelJson, + Point3d, + Polyface, + PolyfaceAuxData, + PolyfaceBuilder, + StrokeOptions, + Transform, +} from "@itwin/core-geometry"; import { Viewer } from "./Viewer"; type AnalysisMeshType = "Cantilever" | "Flat with waves"; @@ -21,7 +39,14 @@ interface AnalysisMesh { readonly styles: Map; } -const seaMountain = [[0.0, 0, 255, 0, 0], [0.2, 72, 96, 160, 0x3f], [0.4, 152, 96, 160, 0x7f], [0.6, 128, 32, 104, 0xbf], [0.7, 148, 180, 128, 0xff], [1.0, 240, 240, 240, 0]]; +const seaMountain = [ + [0.0, 0, 255, 0, 0], + [0.2, 72, 96, 160, 0x3f], + [0.4, 152, 96, 160, 0x7f], + [0.6, 128, 32, 104, 0xbf], + [0.7, 148, 180, 128, 0xff], + [1.0, 240, 240, 240, 0], +]; function populateAnalysisStyles(mesh: AnalysisMesh, displacementScale: number): void { const auxdata = mesh.polyface.data.auxData; @@ -128,14 +153,30 @@ function createFlatMeshWithWaves(): Polyface { } // Static Channels. - auxChannels.push(new AuxChannel([new AuxChannelData(0.0, radialDisplacementData)], AuxChannelDataType.Vector, "Static Radial Displacement", "Radial: Static")); - auxChannels.push(new AuxChannel([new AuxChannelData(1.0, radialHeightData)], AuxChannelDataType.Distance, "Static Radial Height", "Radial: Static")); + auxChannels.push( + new AuxChannel([new AuxChannelData(0.0, radialDisplacementData)], AuxChannelDataType.Vector, "Static Radial Displacement", "Radial: Static"), + ); + auxChannels.push( + new AuxChannel([new AuxChannelData(1.0, radialHeightData)], AuxChannelDataType.Distance, "Static Radial Height", "Radial: Static"), + ); auxChannels.push(new AuxChannel([new AuxChannelData(1.0, radialSlopeData)], AuxChannelDataType.Scalar, "Static Radial Slope", "Radial: Static")); // Animated Channels. - const radialDisplacementDataVector = [new AuxChannelData(0.0, zeroDisplacementData), new AuxChannelData(1.0, radialDisplacementData), new AuxChannelData(2.0, zeroDisplacementData)]; - const radialHeightDataVector = [new AuxChannelData(0.0, zeroScalarData), new AuxChannelData(1.0, radialHeightData), new AuxChannelData(2.0, zeroScalarData)]; - const radialSlopeDataVector = [new AuxChannelData(0.0, zeroScalarData), new AuxChannelData(1.0, radialSlopeData), new AuxChannelData(2.0, zeroScalarData)]; + const radialDisplacementDataVector = [ + new AuxChannelData(0.0, zeroDisplacementData), + new AuxChannelData(1.0, radialDisplacementData), + new AuxChannelData(2.0, zeroDisplacementData), + ]; + const radialHeightDataVector = [ + new AuxChannelData(0.0, zeroScalarData), + new AuxChannelData(1.0, radialHeightData), + new AuxChannelData(2.0, zeroScalarData), + ]; + const radialSlopeDataVector = [ + new AuxChannelData(0.0, zeroScalarData), + new AuxChannelData(1.0, radialSlopeData), + new AuxChannelData(2.0, zeroScalarData), + ]; auxChannels.push(new AuxChannel(radialDisplacementDataVector, AuxChannelDataType.Vector, "Animated Radial Displacement", "Radial: Time")); auxChannels.push(new AuxChannel(radialHeightDataVector, AuxChannelDataType.Distance, "Animated Radial Height", "Radial: Time")); diff --git a/test-apps/display-test-app/src/frontend/App.ts b/test-apps/display-test-app/src/frontend/App.ts index 3dc0e7ed7213..ecb2d09a9d6f 100644 --- a/test-apps/display-test-app/src/frontend/App.ts +++ b/test-apps/display-test-app/src/frontend/App.ts @@ -3,76 +3,105 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import "@bentley/icons-generic-webfont/dist/bentley-icons-generic-webfont.css"; -import { GuidString, ProcessDetector } from "@itwin/core-bentley"; -import { ElectronApp, ElectronAppOpts } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { BrowserAuthorizationClient } from "@itwin/browser-authorization"; -import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; -import { IModelsClient } from "@itwin/imodels-client-management"; -import { FrontendDevTools } from "@itwin/frontend-devtools"; -import { HyperModeling } from "@itwin/hypermodeling-frontend"; +import { GuidString, ProcessDetector } from "@itwin/core-bentley"; import { - BentleyCloudRpcManager, BentleyCloudRpcParams, IModelReadRpcInterface, IModelTileRpcInterface, SnapshotIModelRpcInterface, + BentleyCloudRpcManager, + BentleyCloudRpcParams, + IModelReadRpcInterface, + IModelTileRpcInterface, + SnapshotIModelRpcInterface, } from "@itwin/core-common"; -import { EditTools } from "@itwin/editor-frontend"; +import { ElectronApp, ElectronAppOpts } from "@itwin/core-electron/lib/cjs/ElectronFrontend"; import { - AccuDrawHintBuilder, AccuDrawShortcuts, AccuSnap, IModelApp, IpcApp, LocalhostIpcApp, LocalHostIpcAppOpts, RenderSystem, SelectionTool, SnapMode, - TileAdmin, Tool, ToolAdmin, + AccuDrawHintBuilder, + AccuDrawShortcuts, + AccuSnap, + IModelApp, + IpcApp, + LocalhostIpcApp, + LocalHostIpcAppOpts, + RenderSystem, + SelectionTool, + SnapMode, + TileAdmin, + Tool, + ToolAdmin, } from "@itwin/core-frontend"; +import { ITwinLocalization } from "@itwin/core-i18n"; import { MobileApp, MobileAppOpts } from "@itwin/core-mobile/lib/cjs/MobileFrontend"; +import { EditTools } from "@itwin/editor-frontend"; +import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; +import { FrontendDevTools } from "@itwin/frontend-devtools"; +import { HyperModeling } from "@itwin/hypermodeling-frontend"; +import { FrontendIModelsAccess } from "@itwin/imodels-access-frontend"; +import { IModelsClient } from "@itwin/imodels-client-management"; +import { MapLayersFormats } from "@itwin/map-layers-formats"; import { RealityDataAccessClient, RealityDataClientOptions } from "@itwin/reality-data-client"; import { DtaConfiguration } from "../common/DtaConfiguration"; import { dtaChannel, DtaIpcInterface } from "../common/DtaIpcInterface"; import { DtaRpcInterface } from "../common/DtaRpcInterface"; import { ToggleAspectRatioSkewDecoratorTool } from "./AspectRatioSkewDecorator"; +import { BingTerrainMeshProvider } from "./BingTerrainProvider"; +import { CreateSectionDrawingTool } from "./CreateSectionDrawingTool"; import { ApplyModelDisplayScaleTool } from "./DisplayScale"; +import { getConfigurationString } from "./DisplayTestApp"; import { ApplyModelTransformTool, ClearModelTransformsTool, DisableModelTransformsTool } from "./DisplayTransform"; -import { ApplyModelClipTool } from "./ModelClipTools"; -import { GenerateElementGraphicsTool, GenerateTileContentTool } from "./TileContentTool"; -import { ViewClipByElementGeometryTool } from "./ViewClipByElementGeometryTool"; import { DrawingAidTestTool } from "./DrawingAidTestTool"; -import { EditingScopeTool, MoveElementTool, PlaceLineStringTool } from "./EditingTools"; import { DynamicClassifierTool, DynamicClipMaskTool } from "./DynamicClassifierTool"; +import { EditingScopeTool, MoveElementTool, PlaceLineStringTool } from "./EditingTools"; import { FenceClassifySelectedTool } from "./Fence"; import { RecordFpsTool } from "./FpsMonitor"; import { FrameStatsTool } from "./FrameStatsTool"; +import { GltfDecorationTool } from "./GltfDecoration"; import { ChangeGridSettingsTool } from "./Grid"; import { IncidentMarkerDemoTool } from "./IncidentMarkerDemo"; +import { MacroTool } from "./MacroTools"; import { MarkupSelectTestTool } from "./MarkupSelectTestTool"; +import { ApplyModelClipTool } from "./ModelClipTools"; import { Notifications } from "./Notifications"; import { OutputShadersTool } from "./OutputShadersTool"; import { PathDecorationTestTool } from "./PathDecorationTest"; -import { GltfDecorationTool } from "./GltfDecoration"; -import { TextDecorationTool } from "./TextDecoration"; +import { AddSeequentRealityModel } from "./RealityDataModel"; +import { AttachCustomRealityDataTool, registerRealityDataSourceProvider } from "./RealityDataProvider"; +import { OpenRealityModelSettingsTool } from "./RealityModelDisplaySettingsWidget"; +import { SaveImageTool } from "./SaveImageTool"; import { ToggleShadowMapTilesTool } from "./ShadowMapDecoration"; import { signIn, signOut } from "./signIn"; import { - CloneViewportTool, CloseIModelTool, CloseWindowTool, CreateWindowTool, DockWindowTool, FocusWindowTool, MaximizeWindowTool, OpenIModelTool, - ReopenIModelTool, ResizeWindowTool, RestoreWindowTool, Surface, + CloneViewportTool, + CloseIModelTool, + CloseWindowTool, + CreateWindowTool, + DockWindowTool, + FocusWindowTool, + MaximizeWindowTool, + OpenIModelTool, + ReopenIModelTool, + ResizeWindowTool, + RestoreWindowTool, + Surface, } from "./Surface"; -import { CreateSectionDrawingTool } from "./CreateSectionDrawingTool"; import { SyncViewportFrustaTool, SyncViewportsTool } from "./SyncViewportsTool"; +import { TerrainDrapeTool } from "./TerrainDrapeTool"; +import { TextDecorationTool } from "./TextDecoration"; +import { GenerateElementGraphicsTool, GenerateTileContentTool } from "./TileContentTool"; +import { ToggleSecondaryIModelTool } from "./TiledGraphics"; +import { RecordTileSizesTool } from "./TileSizeRecorder"; import { TimePointComparisonTool } from "./TimePointComparison"; import { UiManager } from "./UiManager"; +import { ViewClipByElementGeometryTool } from "./ViewClipByElementGeometryTool"; import { MarkupTool, ModelClipTool, ZoomToSelectedElementsTool } from "./Viewer"; -import { MacroTool } from "./MacroTools"; -import { RecordTileSizesTool } from "./TileSizeRecorder"; -import { TerrainDrapeTool } from "./TerrainDrapeTool"; -import { SaveImageTool } from "./SaveImageTool"; -import { ToggleSecondaryIModelTool } from "./TiledGraphics"; -import { BingTerrainMeshProvider } from "./BingTerrainProvider"; -import { AttachCustomRealityDataTool, registerRealityDataSourceProvider } from "./RealityDataProvider"; -import { MapLayersFormats } from "@itwin/map-layers-formats"; -import { OpenRealityModelSettingsTool } from "./RealityModelDisplaySettingsWidget"; -import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; -import { ITwinLocalization } from "@itwin/core-i18n"; -import { getConfigurationString } from "./DisplayTestApp"; -import { AddSeequentRealityModel } from "./RealityDataModel"; class DisplayTestAppAccuSnap extends AccuSnap { private readonly _activeSnaps: SnapMode[] = [SnapMode.NearestKeypoint]; - public override get keypointDivisor() { return 2; } - public override getActiveSnapModes(): SnapMode[] { return this._activeSnaps; } + public override get keypointDivisor() { + return 2; + } + public override getActiveSnapModes(): SnapMode[] { + return this._activeSnaps; + } public setActiveSnapModes(snaps: SnapMode[]): void { this._activeSnaps.length = snaps.length; for (let i = 0; i < snaps.length; i++) @@ -117,8 +146,12 @@ class SignOutTool extends Tool { class PushChangesTool extends Tool { public static override toolId = "PushChanges"; - public static override get maxArgs() { return 1; } - public static override get minArgs() { return 1; } + public static override get maxArgs() { + return 1; + } + public static override get minArgs() { + return 1; + } public override async run(description?: string): Promise { if (!description || "string" !== typeof description) @@ -154,7 +187,9 @@ export const dtaIpc = IpcApp.makeIpcProxy(dtaChannel); class RefreshTilesTool extends Tool { public static override toolId = "RefreshTiles"; - public static override get maxArgs() { return undefined; } + public static override get maxArgs() { + return undefined; + } public override async run(changedModelIds?: string[]): Promise { if (undefined !== changedModelIds && 0 === changedModelIds.length) @@ -171,8 +206,12 @@ class RefreshTilesTool extends Tool { class PurgeTileTreesTool extends Tool { public static override toolId = "PurgeTileTrees"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return undefined; + } public override async run(modelIds?: string[]): Promise { const vp = IModelApp.viewManager.selectedView; @@ -226,10 +265,16 @@ function createHubAccess(configuration: DtaConfiguration) { export class DisplayTestApp { private static _surface?: Surface; - public static get surface() { return this._surface!; } - public static set surface(surface: Surface) { this._surface = surface; } + public static get surface() { + return this._surface!; + } + public static set surface(surface: Surface) { + this._surface = surface; + } private static _iTwinId?: GuidString; - public static get iTwinId(): GuidString | undefined { return this._iTwinId; } + public static get iTwinId(): GuidString | undefined { + return this._iTwinId; + } public static async startup(configuration: DtaConfiguration, renderSys: RenderSystem.Options, tileAdmin: TileAdmin.Props): Promise { let socketUrl = new URL(configuration.customOrchestratorUri || "http://localhost:3001"); @@ -299,14 +344,17 @@ export class DisplayTestApp { await client.handleSigninCallback(); } - const rpcParams: BentleyCloudRpcParams = { info: { title: "ui-test-app", version: "v1.0" }, uriPrefix: configuration.customOrchestratorUri || "http://localhost:3001" }; + const rpcParams: BentleyCloudRpcParams = { + info: { title: "ui-test-app", version: "v1.0" }, + uriPrefix: configuration.customOrchestratorUri || "http://localhost:3001", + }; if (opts.iModelApp?.rpcInterfaces) // eslint-disable-line deprecation/deprecation BentleyCloudRpcManager.initializeClient(rpcParams, opts.iModelApp.rpcInterfaces); // eslint-disable-line deprecation/deprecation await LocalhostIpcApp.startup(opts); } - IModelApp.applicationLogoCard = - () => IModelApp.makeLogoCard({ iconSrc: "DTA.png", iconWidth: 100, heading: "Display Test App", notice: "For internal testing" }); + IModelApp.applicationLogoCard = () => + IModelApp.makeLogoCard({ iconSrc: "DTA.png", iconWidth: 100, heading: "Display Test App", notice: "For internal testing" }); const svtToolNamespace = "SVTTools"; await IModelApp.localization.registerNamespace(svtToolNamespace); @@ -394,5 +442,7 @@ export class DisplayTestApp { (IModelApp.accuSnap as DisplayTestAppAccuSnap).setActiveSnapModes(snaps); } - public static setActiveSnapMode(snap: SnapMode): void { this.setActiveSnapModes([snap]); } + public static setActiveSnapMode(snap: SnapMode): void { + this.setActiveSnapModes([snap]); + } } diff --git a/test-apps/display-test-app/src/frontend/AspectRatioSkewDecorator.ts b/test-apps/display-test-app/src/frontend/AspectRatioSkewDecorator.ts index 8243c2c09d10..d2b879a3e3d8 100644 --- a/test-apps/display-test-app/src/frontend/AspectRatioSkewDecorator.ts +++ b/test-apps/display-test-app/src/frontend/AspectRatioSkewDecorator.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import { assert } from "@itwin/core-bentley"; -import { IModelJson, Path } from "@itwin/core-geometry"; import { ColorDef, ViewDetails } from "@itwin/core-common"; import { DecorateContext, GraphicType, IModelApp, IModelConnection, Tool } from "@itwin/core-frontend"; +import { IModelJson, Path } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; class AspectRatioSkewDecorator { @@ -74,8 +74,12 @@ export class ToggleAspectRatioSkewDecoratorTool extends Tool { private _applyAspectRatioSkew = true; public static override toolId = "ToggleAspectRatioSkewDecorator"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(): Promise { const iModel = IModelApp.viewManager.selectedView?.iModel; diff --git a/test-apps/display-test-app/src/frontend/Atmosphere.ts b/test-apps/display-test-app/src/frontend/Atmosphere.ts index 0fe08ba00b40..f1995b59f170 100644 --- a/test-apps/display-test-app/src/frontend/Atmosphere.ts +++ b/test-apps/display-test-app/src/frontend/Atmosphere.ts @@ -4,12 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { assert } from "@itwin/core-bentley"; -import { createButton, createCheckBox, createLabeledNumericInput, createNestedMenu, LabeledNumericInput } from "@itwin/frontend-devtools"; import { Atmosphere } from "@itwin/core-common"; import { Viewport, ViewState, ViewState3d } from "@itwin/core-frontend"; +import { createButton, createCheckBox, createLabeledNumericInput, createNestedMenu, LabeledNumericInput } from "@itwin/frontend-devtools"; export class AtmosphereEditor { - private readonly _vp: Viewport; private readonly _update: (view: ViewState) => void; @@ -83,11 +82,12 @@ export class AtmosphereEditor { id: "atmosphere_exposure", parent: spanIntensity, value: 2.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.exposure = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.exposure = value; + return props; + }), min: 0.0, max: 1000.0, step: 0.1, @@ -102,11 +102,12 @@ export class AtmosphereEditor { id: "atmosphere_atmosphereHeightAboveEarth", parent: spanAtmosphereScale, value: 100000.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.atmosphereHeightAboveEarth = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.atmosphereHeightAboveEarth = value; + return props; + }), min: 0.0, max: 1000000.0, step: 10000.0, @@ -117,11 +118,12 @@ export class AtmosphereEditor { id: "atmosphere_depthBelowEarthForMaxDensity", parent: spanAtmosphereScale, value: 0.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.depthBelowEarthForMaxDensity = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.depthBelowEarthForMaxDensity = value; + return props; + }), min: 0.0, max: 1000000.0, step: 10000.0, @@ -136,11 +138,12 @@ export class AtmosphereEditor { id: "atmosphere_scatteringStrength", parent: spanScattering, value: 100.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.scatteringStrength = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.scatteringStrength = value; + return props; + }), min: 0.0, max: 1000.0, step: 1.0, @@ -152,13 +155,14 @@ export class AtmosphereEditor { id: "atmosphere_wavelengthR", parent: spanScattering, value: 700.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - const wavelenghts = props.wavelengths!; - wavelenghts.r = value; - props.wavelengths = wavelenghts; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + const wavelenghts = props.wavelengths!; + wavelenghts.r = value; + props.wavelengths = wavelenghts; + return props; + }), min: 0.0, max: 1000.0, step: 10, @@ -171,13 +175,14 @@ export class AtmosphereEditor { id: "atmosphere_wavelengthG", parent: spanScattering, value: 530.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - const wavelenghts = props.wavelengths!; - wavelenghts.g = value; - props.wavelengths = wavelenghts; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + const wavelenghts = props.wavelengths!; + wavelenghts.g = value; + props.wavelengths = wavelenghts; + return props; + }), min: 0.0, max: 1000.0, step: 10, @@ -190,13 +195,14 @@ export class AtmosphereEditor { id: "atmosphere_wavelengthB", parent: spanScattering, value: 400.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - const wavelenghts = props.wavelengths!; - wavelenghts.b = value; - props.wavelengths = wavelenghts; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + const wavelenghts = props.wavelengths!; + wavelenghts.b = value; + props.wavelengths = wavelenghts; + return props; + }), min: 0.0, max: 1000.0, step: 10, @@ -208,11 +214,12 @@ export class AtmosphereEditor { id: "atmosphere_densityFalloff", parent: atmosphereControlsDiv, value: 10.0, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.densityFalloff = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.densityFalloff = value; + return props; + }), min: 0.0, max: 1000.0, step: 1.0, @@ -228,11 +235,12 @@ export class AtmosphereEditor { id: "atmosphere_numViewRaySamples", parent: spanSamplePoints, value: 10, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.numViewRaySamples = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.numViewRaySamples = value; + return props; + }), min: 1, max: 40, step: 1, @@ -243,11 +251,12 @@ export class AtmosphereEditor { id: "atmosphere_numSunRaySamples", parent: spanSamplePoints, value: 5, - handler: (value, _) => this.updateAtmosphere((view): Atmosphere.Props => { - const props = this.getAtmosphereSettingsProps(view); - props.numSunRaySamples = value; - return props; - }), + handler: (value, _) => + this.updateAtmosphere((view): Atmosphere.Props => { + const props = this.getAtmosphereSettingsProps(view); + props.numSunRaySamples = value; + return props; + }), min: 1, max: 40, step: 1, @@ -305,7 +314,7 @@ export class AtmosphereEditor { private updateAtmosphere(updateFunction: (view: ViewState) => Atmosphere.Props) { const props = updateFunction(this._vp.view); assert(this._vp.view.is3d()); - const settings = (this._vp.view).getDisplayStyle3d().settings; + const settings = this._vp.view.getDisplayStyle3d().settings; settings.environment = settings.environment.clone({ atmosphere: Atmosphere.Settings.fromJSON(props) }); this.sync(); this.updateAtmosphereUI(this._vp.view); diff --git a/test-apps/display-test-app/src/frontend/BingTerrainProvider.ts b/test-apps/display-test-app/src/frontend/BingTerrainProvider.ts index 3baa33cc9b46..6dadefcb513f 100644 --- a/test-apps/display-test-app/src/frontend/BingTerrainProvider.ts +++ b/test-apps/display-test-app/src/frontend/BingTerrainProvider.ts @@ -4,12 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import { assert, Uint16ArrayBuilder } from "@itwin/core-bentley"; -import { Point2d, Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; import { OctEncodedNormal } from "@itwin/core-common"; import { - BingElevationProvider, GeographicTilingScheme, IModelApp, MapTileProjection, ReadMeshArgs, RealityMeshParams, RealityMeshParamsBuilder, - RealityMeshParamsBuilderOptions, RequestMeshDataArgs, TerrainMeshProvider, TerrainMeshProviderOptions, TerrainProvider, + BingElevationProvider, + GeographicTilingScheme, + IModelApp, + MapTileProjection, + ReadMeshArgs, + RealityMeshParams, + RealityMeshParamsBuilder, + RealityMeshParamsBuilderOptions, + RequestMeshDataArgs, + TerrainMeshProvider, + TerrainMeshProviderOptions, + TerrainProvider, } from "@itwin/core-frontend"; +import { Point2d, Point3d, Range1d, Vector3d } from "@itwin/core-geometry"; // The number of elevation values per row/column within each tile. const size = 16; @@ -194,14 +204,14 @@ export class BingTerrainMeshProvider extends TerrainMeshProvider { const p0 = builder.positions.unquantize(row * size + col, scratchP0); // This could be made more efficient with a loop that retains the output of the previous iteration, // but less readable. - addNormal(vertexNormal, p0, row+0, col+1, row+1, col+1); - addNormal(vertexNormal, p0, row+1, col+1, row+1, col+0); - addNormal(vertexNormal, p0, row+1, col+0, row+1, col-1); - addNormal(vertexNormal, p0, row+1, col-1, row+0, col-1); - addNormal(vertexNormal, p0, row+0, col-1, row-1, col-1); - addNormal(vertexNormal, p0, row-1, col-1, row-1, col+0); - addNormal(vertexNormal, p0, row-1, col+0, row-1, col+1); - addNormal(vertexNormal, p0, row-1, col+1, row+0, col+1); + addNormal(vertexNormal, p0, row + 0, col + 1, row + 1, col + 1); + addNormal(vertexNormal, p0, row + 1, col + 1, row + 1, col + 0); + addNormal(vertexNormal, p0, row + 1, col + 0, row + 1, col - 1); + addNormal(vertexNormal, p0, row + 1, col - 1, row + 0, col - 1); + addNormal(vertexNormal, p0, row + 0, col - 1, row - 1, col - 1); + addNormal(vertexNormal, p0, row - 1, col - 1, row - 1, col + 0); + addNormal(vertexNormal, p0, row - 1, col + 0, row - 1, col + 1); + addNormal(vertexNormal, p0, row - 1, col + 1, row + 0, col + 1); vertexNormal.normalizeInPlace(); builder.normals.push(OctEncodedNormal.encode(vertexNormal)); @@ -266,7 +276,7 @@ export class BingTerrainMeshProvider extends TerrainMeshProvider { // right side const right = c * size + sizeM1; - builder.addTriangle(right, right +size, rightIndex + 4); + builder.addTriangle(right, right + size, rightIndex + 4); builder.addTriangle(right, rightIndex + 4, rightIndex); } } diff --git a/test-apps/display-test-app/src/frontend/CameraPaths.ts b/test-apps/display-test-app/src/frontend/CameraPaths.ts index 16442c89504c..26ae9fe441ef 100644 --- a/test-apps/display-test-app/src/frontend/CameraPaths.ts +++ b/test-apps/display-test-app/src/frontend/CameraPaths.ts @@ -99,7 +99,8 @@ class Keyframe { Point3d.fromJSON(json.target), Vector3d.fromJSON(json.up), json.lensAngle !== undefined ? Angle.fromJSON(json.lensAngle) : undefined, - json.extents !== undefined ? Vector3d.fromJSON(json.extents) : undefined); + json.extents !== undefined ? Vector3d.fromJSON(json.extents) : undefined, + ); } public toJSON(): KeyframeProps { @@ -161,21 +162,27 @@ class CameraPath { let i = 1; while (i < this.keyframes.length - 1) { const [before, current, after] = this.keyframes.slice(i - 1, i + 2); - const fraction = (current.time - before.time) / (after.time - before.time); + const fraction = (current.time - before.time) / (after.time - before.time); const interpolated = before.interpolate(fraction, after); // Check if the distances between the reconstructed keyframe and the original is acceptable const sameCameraType = (interpolated.lensAngle === undefined) === (current.lensAngle === undefined); const locationDistance = interpolated.location.distance(current.location); const targetDistance = interpolated.target.distance(current.target); - const lensAngleDistance = (interpolated.lensAngle === undefined || !sameCameraType) ? 0 : Math.abs(interpolated.lensAngle.degrees - current.lensAngle!.degrees); - const extentDistance = (interpolated.extents !== undefined && current.extents !== undefined) ? interpolated.extents.distance(current.extents) : 0; - - if (sameCameraType + const lensAngleDistance = (interpolated.lensAngle === undefined || !sameCameraType) + ? 0 + : Math.abs(interpolated.lensAngle.degrees - current.lensAngle!.degrees); + const extentDistance = (interpolated.extents !== undefined && current.extents !== undefined) + ? interpolated.extents.distance(current.extents) + : 0; + + if ( + sameCameraType && locationDistance < distanceThreshold && targetDistance < distanceThreshold && lensAngleDistance < lensAngleThreshold.degrees - && extentDistance < extentThreshold) { + && extentDistance < extentThreshold + ) { this.keyframes.splice(i, 1); } else { i++; @@ -189,7 +196,7 @@ class CameraPath { * @returns the interpolated keyframe. */ public getKeyframeAtTime(time: number): Keyframe { - const {before, after} = this.getKeyframeRangeAtTime(time); + const { before, after } = this.getKeyframeRangeAtTime(time); // Only one keyframe, use it directly if (after === undefined) @@ -207,23 +214,23 @@ class CameraPath { * @param time In ms, the location in the timeline to get the keyframe at. * @returns an object with the keyframes. ``before`` will always be set, but ``after`` can be missing. */ - private getKeyframeRangeAtTime(time: number): {before: Keyframe, after?: Keyframe} { + private getKeyframeRangeAtTime(time: number): { before: Keyframe, after?: Keyframe } { if (this.keyframes.length <= 0) throw new Error("Selected path has no keyframes."); // Only one keyframe or before first keyframe if (this.keyframes.length === 1 || time < this.keyframes[0].time) { - return {before: this.keyframes[0]}; + return { before: this.keyframes[0] }; } // Between two keyframes for (let i = 1; i < this.keyframes.length; i++) { if (time < this.keyframes[i].time) - return {before: this.keyframes[i - 1], after: this.keyframes[i]}; + return { before: this.keyframes[i - 1], after: this.keyframes[i] }; } // After the last keyframe - return {before: this.keyframes[this.keyframes.length - 1]}; + return { before: this.keyframes[this.keyframes.length - 1] }; } public static fromJSON(json?: CameraPathProps): CameraPath { @@ -296,9 +303,15 @@ export class CameraPathsMenu extends ToolBarDropDown { parent.appendChild(this._element); } - public get isOpen() { return "none" !== this._element.style.display; } - protected _open() { this._element.style.display = "block"; } - protected _close() { this._element.style.display = "none"; } + public get isOpen() { + return "none" !== this._element.style.display; + } + protected _open() { + this._element.style.display = "block"; + } + protected _close() { + this._element.style.display = "none"; + } public override get onViewChanged(): Promise | undefined { if (this._imodel !== this._viewport.iModel) { @@ -433,7 +446,11 @@ export class CameraPathsMenu extends ToolBarDropDown { this._onStateChanged = () => { if (this.selectedPath === undefined) { - playButton.disabled = recordButton.disabled = stopButton.disabled = deletePathButton.disabled = true; + playButton.disabled = + recordButton.disabled = + stopButton.disabled = + deletePathButton.disabled = + true; pathsList.disabled = false; } else { const canRecord = this.selectedPath.duration === 0 || this.selectedPath.keyframes.length === 0; @@ -510,7 +527,6 @@ export class CameraPathsMenu extends ToolBarDropDown { private findPath(name: string): CameraPath | undefined { const index = this._paths.findIndex((path) => name === path.name); return -1 !== index ? this._paths[index] : undefined; - } public prepareView(record = false): void { @@ -561,7 +577,6 @@ export class CameraPathsMenu extends ToolBarDropDown { } public stop(): void { - if (this._animID) { cancelAnimationFrame(this._animID); } @@ -602,7 +617,6 @@ export class CameraPathsMenu extends ToolBarDropDown { if (this._currentAnimationTime > this.selectedPath.duration) this.endAnimation(); } - } private playAnimationFrame(): void { @@ -664,7 +678,6 @@ export class CameraPathsMenu extends ToolBarDropDown { lensAngle, }, ); - } else { if (keyframe.extents === undefined) throw new Error("Invalid keyframe for camera: path should specifies either lensAngle or extents."); @@ -680,6 +693,6 @@ export class CameraPathsMenu extends ToolBarDropDown { ); } - this._viewport.synchWithView({noSaveInUndo: true}); + this._viewport.synchWithView({ noSaveInUndo: true }); } } diff --git a/test-apps/display-test-app/src/frontend/Cantilever.ts b/test-apps/display-test-app/src/frontend/Cantilever.ts index 51fdb659159f..96897aeb19d8 100644 --- a/test-apps/display-test-app/src/frontend/Cantilever.ts +++ b/test-apps/display-test-app/src/frontend/Cantilever.ts @@ -3,4 +3,4 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ export const cantileverJsonString: string = -'{"indexedMesh":{"auxData":{"channels":[{"data":[{"input":0.0,"values":[0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00011059328906447410,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447519,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,0.0,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447519,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,0.0,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315]},{"input":1.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]},{"input":2.0,"values":[0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00011059328906447410,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447519,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,0.0,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447519,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,0.0,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315]}],"dataType":2,"inputName":"","name":"Displacement"},{"data":[{"input":0.0,"values":[3.5242919693700969e-12,2.3495279795800647e-12,1.1747639897900324e-12,0.0,132.16648443993822,132.16648443993705,132.16648443993589,132.16648443993469,264.33296887987410,264.33296887987291,264.33296887987058,264.33296887986938,396.49945331980996,396.49945331980882,396.49945331980643,396.49945331980530,528.66593775974468,528.66593775974354,528.66593775974115,528.66593775974115,660.83242219967940,660.83242219967826,660.83242219967701,660.83242219967588,792.99890663961412,792.99890663961287,792.99890663961173,792.99890663961060,925.16539107954986,925.16539107954986,925.16539107954759,925.16539107954520,1057.3318755194857,1057.3318755194846,1057.3318755194823,1057.3318755194809,1189.4983599594204,1189.4983599594193,1189.4983599594170,1189.4983599594170,1321.6648443993552,1321.6648443993540,1321.6648443993529,1321.6648443993518,1453.8313288392910,1453.8313288392887,1453.8313288392874,1453.8313288392874,1585.9978132792257,1585.9978132792257,1585.9978132792235,1585.9978132792221,1718.1642977191616,1718.1642977191605,1718.1642977191582,1718.1642977191568,1850.3307821590963,1850.3307821590952,1850.3307821590929,1850.3307821590929,1982.4972665990308,1982.4972665990299,1982.4972665990288,1982.4972665990274,2114.6637510389669,2114.6637510389646,2114.6637510389633,2114.6637510389633,2246.8302354789012,2246.8302354789012,2246.8302354788989,2246.8302354788971,2378.9967199188368,2378.9967199188354,2378.9967199188341,2378.9967199188336,2511.1632043587720,2511.1632043587711,2511.1632043587692,2511.1632043587679,2643.3296887987067,2643.3296887987067,2643.3296887987049,2643.3296887987035,2775.4961732386428,2775.4961732386409,2775.4961732386391,2775.4961732386391,2907.6626576785779,2907.6626576785770,2907.6626576785748,2907.6626576785739,3039.8291421185127,3039.8291421185113,3039.8291421185099,3039.8291421185090,3171.9956265584483,3171.9956265584469,3171.9956265584451,3171.9956265584451,3304.1621109983826,3304.1621109983826,3304.1621109983807,3304.1621109983785,3436.3285954383186,3436.3285954383164,3436.3285954383150,3436.3285954383150,3568.4950798782538,3568.4950798782529,3568.4950798782506,3568.4950798782497,3700.6615643181885,3700.6615643181872,3700.6615643181858,3700.6615643181849,3832.8280487581242,3832.8280487581233,3832.8280487581219,3832.8280487581210,3964.9945331980593,3964.9945331980575,3964.9945331980557,3964.9945331980548,4097.1610176379945,4097.1610176379936,4097.1610176379909,4097.161017637990,4229.3275020779301,4229.3275020779283,4229.3275020779265,4229.3275020779256,4361.4939865178658,4361.4939865178640,4361.4939865178621,4361.4939865178612,4493.6604709577987,4493.6604709577978,4493.6604709577960,4493.6604709577960,4625.8269553977343,4625.8269553977325,4625.8269553977316,4625.8269553977307,4757.9934398376699,4757.9934398376690,4757.9934398376672,4757.9934398376672,4890.1599242776065,4890.1599242776056,4890.1599242776028,4890.1599242776028,5022.3264087175403,5022.3264087175394,5022.3264087175367,5022.3264087175357,5154.4928931574750,5154.4928931574741,5154.4928931574714,5154.4928931574714,5286.6593775974115,5286.6593775974097,5286.6593775974079,5286.6593775974079,5418.8258620373454,5418.8258620373454,5418.8258620373426,5418.8258620373426,5550.9923464772810,5550.9923464772810,5550.9923464772783,5550.9923464772774,5683.1588309172166,5683.1588309172157,5683.1588309172130,5683.1588309172112,5815.3253153571522,5815.3253153571513,5815.3253153571486,5815.3253153571477,5947.4917997970870,5947.4917997970861,5947.4917997970833,5947.4917997970833,6079.6582842370217,6079.6582842370208,6079.6582842370199,6079.6582842370181,6211.8247686769564,6211.8247686769555,6211.8247686769546,6211.8247686769528,6343.9912531168929,6343.9912531168911,6343.9912531168902,6343.9912531168884,6476.1577375568268,6476.1577375568268,6476.1577375568249,6476.1577375568231,6608.3242219967633,6608.3242219967615,6608.3242219967588,6608.3242219967588,6740.4907064366971,6740.4907064366962,6740.4907064366944,6740.4907064366944,6872.6571908766327,6872.6571908766318,6872.657190876630,6872.6571908766291,7004.8236753165684,7004.8236753165675,7004.8236753165656,7004.8236753165647,7136.9901597565040,7136.9901597565031,7136.9901597565004,7136.9901597564995,7269.1566441964387,7269.1566441964378,7269.1566441964351,7269.1566441964342,7401.3231286363734,7401.3231286363716,7401.3231286363716,7401.3231286363698,7533.4896130763082,7533.4896130763082,7533.4896130763073,7533.4896130763054,-0.0,-1.1747639897900324e-12,-2.3495279795800647e-12,-3.5242919693700969e-12,-132.16648443993469,-132.16648443993589,-132.16648443993705,-132.16648443993822,-264.33296887986938,-264.33296887987058,-264.33296887987291,-264.33296887987410,-396.49945331980530,-396.49945331980643,-396.49945331980882,-396.49945331980996,-528.66593775974115,-528.66593775974115,-528.66593775974354,-528.66593775974468,-660.83242219967588,-660.83242219967701,-660.83242219967826,-660.83242219967940,-792.99890663961060,-792.99890663961173,-792.99890663961287,-792.99890663961412,-925.16539107954520,-925.16539107954759,-925.16539107954986,-925.16539107954986,-1057.3318755194809,-1057.3318755194823,-1057.3318755194846,-1057.3318755194857,-1189.4983599594170,-1189.4983599594170,-1189.4983599594193,-1189.4983599594204,-1321.6648443993518,-1321.6648443993529,-1321.6648443993540,-1321.6648443993552,-1453.8313288392874,-1453.8313288392874,-1453.8313288392887,-1453.8313288392910,-1585.9978132792221,-1585.9978132792235,-1585.9978132792257,-1585.9978132792257,-1718.1642977191568,-1718.1642977191582,-1718.1642977191605,-1718.1642977191616,-1850.3307821590929,-1850.3307821590929,-1850.3307821590952,-1850.3307821590963,-1982.4972665990274,-1982.4972665990288,-1982.4972665990299,-1982.4972665990308,-2114.6637510389633,-2114.6637510389633,-2114.6637510389646,-2114.6637510389669,-2246.8302354788971,-2246.8302354788989,-2246.8302354789012,-2246.8302354789012,-2378.9967199188336,-2378.9967199188341,-2378.9967199188354,-2378.9967199188368,-2511.1632043587679,-2511.1632043587692,-2511.1632043587711,-2511.1632043587720,-2643.3296887987035,-2643.3296887987049,-2643.3296887987067,-2643.3296887987067,-2775.4961732386391,-2775.4961732386391,-2775.4961732386409,-2775.4961732386428,-2907.6626576785739,-2907.6626576785748,-2907.6626576785770,-2907.6626576785779,-3039.8291421185090,-3039.8291421185099,-3039.8291421185113,-3039.8291421185127,-3171.9956265584451,-3171.9956265584451,-3171.9956265584469,-3171.9956265584483,-3304.1621109983785,-3304.1621109983807,-3304.1621109983826,-3304.1621109983826,-3436.3285954383150,-3436.3285954383150,-3436.3285954383164,-3436.3285954383186,-3568.4950798782497,-3568.4950798782506,-3568.4950798782529,-3568.4950798782538,-3700.6615643181849,-3700.6615643181858,-3700.6615643181872,-3700.6615643181885,-3832.8280487581210,-3832.8280487581219,-3832.8280487581233,-3832.8280487581242,-3964.9945331980548,-3964.9945331980557,-3964.9945331980575,-3964.9945331980593,-4097.161017637990,-4097.1610176379909,-4097.1610176379936,-4097.1610176379945,-4229.3275020779256,-4229.3275020779265,-4229.3275020779283,-4229.3275020779301,-4361.4939865178612,-4361.4939865178621,-4361.4939865178640,-4361.4939865178658,-4493.6604709577960,-4493.6604709577960,-4493.6604709577978,-4493.6604709577987,-4625.8269553977307,-4625.8269553977316,-4625.8269553977325,-4625.8269553977343,-4757.9934398376672,-4757.9934398376672,-4757.9934398376690,-4757.9934398376699,-4890.1599242776028,-4890.1599242776028,-4890.1599242776056,-4890.1599242776065,-5022.3264087175357,-5022.3264087175367,-5022.3264087175394,-5022.3264087175403,-5154.4928931574714,-5154.4928931574714,-5154.4928931574741,-5154.4928931574750,-5286.6593775974079,-5286.6593775974079,-5286.6593775974097,-5286.6593775974115,-5418.8258620373426,-5418.8258620373426,-5418.8258620373454,-5418.8258620373454,-5550.9923464772774,-5550.9923464772783,-5550.9923464772810,-5550.9923464772810,-5683.1588309172112,-5683.1588309172130,-5683.1588309172157,-5683.1588309172166,-5815.3253153571477,-5815.3253153571486,-5815.3253153571513,-5815.3253153571522,-5947.4917997970833,-5947.4917997970833,-5947.4917997970861,-5947.4917997970870,-6079.6582842370181,-6079.6582842370199,-6079.6582842370208,-6079.6582842370217,-6211.8247686769528,-6211.8247686769546,-6211.8247686769555,-6211.8247686769564,-6343.9912531168884,-6343.9912531168902,-6343.9912531168911,-6343.9912531168929,-6476.1577375568231,-6476.1577375568249,-6476.1577375568268,-6476.1577375568268,-6608.3242219967588,-6608.3242219967588,-6608.3242219967615,-6608.3242219967633,-6740.4907064366944,-6740.4907064366944,-6740.4907064366962,-6740.4907064366971,-6872.6571908766291,-6872.657190876630,-6872.6571908766318,-6872.6571908766327,-7004.8236753165647,-7004.8236753165656,-7004.8236753165675,-7004.8236753165684,-7136.9901597564995,-7136.9901597565004,-7136.9901597565031,-7136.9901597565040,-7269.1566441964342,-7269.1566441964351,-7269.1566441964378,-7269.1566441964387,-7401.3231286363698,-7401.3231286363716,-7401.3231286363716,-7401.3231286363734,-7533.4896130763054,-7533.4896130763073,-7533.4896130763082,-7533.4896130763082,0.0,9.1370532539224727e-13,1.8274106507844945e-12,2.7411159761767420e-12,0.0,6.5264666099446246e-13,1.3052933219889249e-12,1.9579399829833875e-12,0.0,3.9158799659667746e-13,7.8317599319335492e-13,1.1747639897900322e-12,0.0,1.3052933219889250e-13,2.6105866439778501e-13,3.9158799659667751e-13,-0.0,-1.3052933219889250e-13,-2.6105866439778501e-13,-3.9158799659667751e-13,-0.0,-3.9158799659667746e-13,-7.8317599319335492e-13,-1.1747639897900322e-12,-0.0,-6.5264666099446226e-13,-1.3052933219889245e-12,-1.9579399829833871e-12,-0.0,-9.1370532539224727e-13,-1.8274106507844945e-12,-2.7411159761767420e-12,102.79615456439639,205.59230912879093,308.38846369318549,411.18461825757913,513.98077282197278,616.77692738636642,719.57308195076098,822.36923651515554,925.16539107954918,1027.9615456439428,1130.7577002083374,1233.5538547727310,1336.3500093371256,1439.1461639015192,1541.9423184659129,1644.7384730303074,1747.5346275947006,1850.3307821590952,1953.1269367234893,2055.9230912878829,2158.7192458522777,2261.5154004166716,2364.3115549810655,2467.1077095454593,2569.9038641098532,2672.7000186742471,2775.4961732386414,2878.2923278030348,2981.0884823674296,3083.8846369318230,3186.6807914962169,3289.4769460606112,3392.2731006250060,3495.0692551893985,3597.8654097537928,3700.6615643181876,3803.4577188825820,3906.2538734469754,4009.0500280113697,4111.8461825757640,4214.6423371401570,4317.4384917045509,4420.2346462689457,4523.0308008333404,4625.8269553977334,4728.6231099621273,4831.4192645265211,4934.2154190909159,5037.0115736553089,5139.8077282197037,5242.6038827840976,5345.4000373484914,5448.1961919128853,5550.9923464772810,5653.7885010416740,5756.5846556060678,5859.3808101704617,73.425824688854561,146.85164937770782,220.27747406656110,293.70329875541370,367.12912344426627,440.55494813311890,513.98077282197221,587.40659751082535,660.83242219967804,734.25824688853061,807.68407157738386,881.10989626623643,954.53572095508980,1027.9615456439424,1101.3873703327952,1174.8131950216482,1248.2390197105005,1321.6648443993538,1395.0906690882068,1468.5164937770594,1541.9423184659126,1615.3681431547654,1688.7939678436180,1762.2197925324713,1835.6456172213236,1909.0714419101766,1982.4972665990299,2055.9230912878825,2129.3489159767355,2202.7747406655885,2276.2005653544411,2349.6263900432941,2423.0522147321471,2496.4780394209993,2569.9038641098523,2643.3296887987053,2716.7555134875588,2790.1813381764109,2863.6071628652639,2937.0329875541170,3010.458812242970,3083.8846369318226,3157.3104616206756,3230.7362863095286,3304.1621109983816,3377.5879356872342,3451.0137603760868,3524.4395850649403,3597.8654097537924,3671.2912344426459,3744.7170591314980,3818.1428838203510,3891.5687085092045,3964.9945331980575,4038.4203578869101,4111.8461825757631,4185.2720072646161,44.055494813312762,88.110989626624701,132.16648443993665,176.22197925324821,220.27747406655976,264.33296887987132,308.38846369318327,352.44395850649528,396.49945331980678,440.55494813311833,484.61044294643028,528.66593775974184,572.72143257305379,616.77692738636540,660.83242219967701,704.88791701298885,748.94341182630023,792.99890663961219,837.05440145292403,881.10989626623552,925.16539107954759,969.22088589285931,1013.2763807061709,1057.3318755194828,1101.3873703327940,1145.4428651461060,1189.4983599594177,1233.5538547727294,1277.6093495860414,1321.6648443993529,1365.7203392126644,1409.7758340259766,1453.8313288392885,1497.8868236525996,1541.9423184659113,1585.9978132792232,1630.0533080925352,1674.1088029058465,1718.1642977191582,1762.2197925324704,1806.2752873457819,1850.3307821590934,1894.3862769724051,1938.4417717857175,1982.4972665990288,2026.5527614123405,2070.6082562256520,2114.6637510389642,2158.7192458522754,2202.7747406655876,2246.8302354788989,2290.8857302922106,2334.9412251055223,2378.9967199188345,2423.0522147321462,2467.1077095454575,2511.1632043587697,14.685164937770940,29.370329875541564,44.055494813312215,58.740659751082738,73.425824688853268,88.110989626623791,102.79615456439444,117.48131950216509,132.16648443993563,146.85164937770614,161.53681431547679,176.22197925324733,190.90714419101798,205.59230912878849,220.27747406655902,234.96263900432967,249.64780394210015,264.33296887987075,279.01813381764134,293.70329875541188,308.38846369318253,323.07362863095312,337.75879356872366,352.44395850649425,367.12912344426474,381.81428838203544,396.49945331980598,411.18461825757652,425.86978319534717,440.55494813311765,455.24011307088819,469.92527800865884,484.61044294642954,499.29560788419985,513.98077282197050,528.66593775974115,543.35110269751181,558.03626763528223,572.72143257305277,587.40659751082353,602.09176244859407,616.77692738636460,631.46209232413526,646.14725726190579,660.83242219967633,675.51758713744687,690.20275207521740,704.88791701298805,719.57308195075859,734.25824688852924,748.94341182629978,763.62857676407032,778.31374170184097,792.99890663961162,807.68407157738216,822.36923651515258,837.05440145292323,-14.685164937770889,-29.370329875541564,-44.055494813312215,-58.740659751082738,-73.425824688853268,-88.110989626623791,-102.79615456439444,-117.48131950216509,-132.16648443993563,-146.85164937770614,-161.53681431547679,-176.22197925324733,-190.90714419101798,-205.59230912878849,-220.27747406655902,-234.96263900432967,-249.64780394210015,-264.33296887987075,-279.01813381764134,-293.70329875541188,-308.38846369318253,-323.07362863095312,-337.75879356872366,-352.44395850649425,-367.12912344426474,-381.81428838203544,-396.49945331980598,-411.18461825757652,-425.86978319534717,-440.55494813311765,-455.24011307088819,-469.92527800865884,-484.61044294642954,-499.29560788419985,-513.98077282197050,-528.66593775974115,-543.35110269751181,-558.03626763528223,-572.72143257305277,-587.40659751082353,-602.09176244859407,-616.77692738636460,-631.46209232413526,-646.14725726190579,-660.83242219967633,-675.51758713744687,-690.20275207521740,-704.88791701298805,-719.57308195075859,-734.25824688852924,-748.94341182629978,-763.62857676407032,-778.31374170184097,-792.99890663961162,-807.68407157738216,-822.36923651515258,-837.05440145292323,-44.055494813312691,-88.110989626624701,-132.16648443993665,-176.22197925324821,-220.27747406655976,-264.33296887987132,-308.38846369318327,-352.44395850649528,-396.49945331980678,-440.55494813311833,-484.61044294643028,-528.66593775974184,-572.72143257305379,-616.77692738636540,-660.83242219967701,-704.88791701298885,-748.94341182630023,-792.99890663961219,-837.05440145292403,-881.10989626623552,-925.16539107954759,-969.22088589285931,-1013.2763807061709,-1057.3318755194828,-1101.3873703327940,-1145.4428651461060,-1189.4983599594177,-1233.5538547727294,-1277.6093495860414,-1321.6648443993529,-1365.7203392126644,-1409.7758340259766,-1453.8313288392885,-1497.8868236525996,-1541.9423184659113,-1585.9978132792232,-1630.0533080925352,-1674.1088029058465,-1718.1642977191582,-1762.2197925324704,-1806.2752873457819,-1850.3307821590934,-1894.3862769724051,-1938.4417717857175,-1982.4972665990288,-2026.5527614123405,-2070.6082562256520,-2114.6637510389642,-2158.7192458522754,-2202.7747406655876,-2246.8302354788989,-2290.8857302922106,-2334.9412251055223,-2378.9967199188345,-2423.0522147321462,-2467.1077095454575,-2511.1632043587697,-73.425824688854476,-146.85164937770776,-220.27747406656101,-293.70329875541364,-367.12912344426621,-440.55494813311878,-513.98077282197210,-587.40659751082524,-660.83242219967781,-734.25824688853038,-807.68407157738363,-881.10989626623632,-954.53572095508946,-1027.9615456439419,-1101.3873703327947,-1174.8131950216480,-1248.2390197105001,-1321.6648443993533,-1395.0906690882064,-1468.5164937770589,-1541.9423184659122,-1615.3681431547650,-1688.7939678436176,-1762.2197925324708,-1835.6456172213232,-1909.0714419101764,-1982.4972665990292,-2055.9230912878820,-2129.3489159767350,-2202.7747406655876,-2276.2005653544402,-2349.6263900432932,-2423.0522147321467,-2496.4780394209984,-2569.9038641098518,-2643.3296887987049,-2716.7555134875583,-2790.181338176410,-2863.6071628652630,-2937.0329875541165,-3010.4588122429691,-3083.8846369318217,-3157.3104616206747,-3230.7362863095282,-3304.1621109983807,-3377.5879356872333,-3451.0137603760854,-3524.4395850649389,-3597.8654097537919,-3671.2912344426450,-3744.7170591314975,-3818.1428838203501,-3891.5687085092031,-3964.9945331980566,-4038.4203578869096,-4111.8461825757613,-4185.2720072646152,-102.79615456439635,-205.59230912879093,-308.38846369318549,-411.18461825757913,-513.98077282197278,-616.77692738636642,-719.57308195076098,-822.36923651515554,-925.16539107954918,-1027.9615456439428,-1130.7577002083374,-1233.5538547727310,-1336.3500093371256,-1439.1461639015192,-1541.9423184659129,-1644.7384730303074,-1747.5346275947006,-1850.3307821590952,-1953.1269367234893,-2055.9230912878829,-2158.7192458522777,-2261.5154004166716,-2364.3115549810655,-2467.1077095454593,-2569.9038641098532,-2672.7000186742471,-2775.4961732386414,-2878.2923278030348,-2981.0884823674296,-3083.8846369318230,-3186.6807914962169,-3289.4769460606112,-3392.2731006250060,-3495.0692551893985,-3597.8654097537928,-3700.6615643181876,-3803.4577188825820,-3906.2538734469754,-4009.0500280113697,-4111.8461825757640,-4214.6423371401570,-4317.4384917045509,-4420.2346462689457,-4523.0308008333404,-4625.8269553977334,-4728.6231099621273,-4831.4192645265211,-4934.2154190909159,-5037.0115736553089,-5139.8077282197037,-5242.6038827840976,-5345.4000373484914,-5448.1961919128853,-5550.9923464772810,-5653.7885010416740,-5756.5846556060678,-5859.3808101704617,5859.3808101704608,5859.3808101704599,5859.3808101704590,4185.2720072646152,4185.2720072646152,4185.2720072646143,2511.1632043587692,2511.1632043587688,2511.1632043587683,837.05440145292312,837.0544014529230,837.0544014529230,-837.05440145292312,-837.0544014529230,-837.0544014529230,-2511.1632043587692,-2511.1632043587688,-2511.1632043587683,-4185.2720072646143,-4185.2720072646134,-4185.2720072646125,-5859.3808101704608,-5859.3808101704599,-5859.3808101704590,5756.5846556060651,5653.7885010416712,5550.9923464772764,5448.1961919128835,5345.4000373484896,5242.6038827840948,5139.8077282197009,5037.0115736553080,4934.2154190909132,4831.4192645265193,4728.6231099621245,4625.8269553977316,4523.0308008333368,4420.2346462689429,4317.4384917045491,4214.6423371401552,4111.8461825757613,4009.0500280113665,3906.2538734469731,3803.4577188825788,3700.6615643181849,3597.8654097537906,3495.0692551893972,3392.2731006250024,3289.4769460606090,3186.6807914962146,3083.8846369318208,2981.0884823674269,2878.2923278030325,2775.4961732386387,2672.7000186742448,2569.9038641098505,2467.1077095454561,2364.3115549810627,2261.5154004166693,2158.7192458522745,2055.9230912878797,1953.1269367234868,1850.3307821590929,1747.5346275946983,1644.7384730303047,1541.9423184659111,1439.1461639015165,1336.3500093371219,1233.5538547727283,1130.7577002083347,1027.9615456439410,925.16539107954645,822.36923651515190,719.57308195075825,616.77692738636460,513.98077282197096,411.18461825757635,308.38846369318185,205.59230912878817,102.79615456439456,4111.8461825757604,4038.4203578869087,3964.9945331980548,3891.5687085092022,3818.1428838203501,3744.7170591314966,3671.2912344426441,3597.8654097537915,3524.4395850649380,3451.0137603760854,3377.5879356872324,3304.1621109983794,3230.7362863095263,3157.3104616206738,3083.8846369318212,3010.4588122429677,2937.0329875541156,2863.6071628652621,2790.1813381764096,2716.7555134875565,2643.3296887987040,2569.9038641098505,2496.4780394209979,2423.0522147321449,2349.6263900432918,2276.2005653544393,2202.7747406655863,2129.3489159767337,2055.9230912878802,1982.4972665990279,1909.0714419101751,1835.6456172213220,1762.2197925324688,1688.7939678436164,1615.3681431547639,1541.9423184659106,1468.5164937770573,1395.0906690882050,1321.6648443993520,1248.2390197104990,1174.8131950216462,1101.3873703327936,1027.9615456439403,954.53572095508719,881.10989626623450,807.68407157738193,734.25824688852924,660.83242219967599,587.40659751082285,513.98077282197016,440.55494813311759,367.12912344426502,293.70329875541171,220.27747406655848,146.85164937770585,73.425824688853268,2467.1077095454580,2423.0522147321449,2378.9967199188332,2334.9412251055214,2290.8857302922102,2246.8302354788980,2202.7747406655863,2158.7192458522745,2114.6637510389628,2070.6082562256511,2026.5527614123394,1982.4972665990274,1938.4417717857157,1894.3862769724044,1850.3307821590927,1806.2752873457805,1762.2197925324690,1718.1642977191573,1674.1088029058458,1630.0533080925338,1585.9978132792221,1541.9423184659104,1497.8868236525989,1453.8313288392867,1409.7758340259752,1365.7203392126635,1321.6648443993518,1277.609349586040,1233.5538547727283,1189.4983599594168,1145.4428651461051,1101.3873703327931,1057.3318755194812,1013.2763807061699,969.22088589285829,925.16539107954634,881.10989626623427,837.0544014529230,792.99890663961128,748.94341182629933,704.88791701298771,660.83242219967610,616.77692738636415,572.72143257305231,528.66593775974070,484.61044294642915,440.55494813311759,396.49945331980564,352.44395850649363,308.38846369318208,264.33296887987058,220.27747406655899,176.22197925324704,132.16648443993506,88.110989626623521,44.055494813311952,822.36923651515372,807.68407157738170,792.99890663961105,778.31374170184051,763.62857676406998,748.94341182629944,734.25824688852890,719.57308195075836,704.88791701298771,690.20275207521718,675.51758713744641,660.83242219967599,646.14725726190534,631.46209232413480,616.77692738636426,602.09176244859361,587.40659751082308,572.72143257305254,558.0362676352820,543.35110269751135,528.66593775974070,513.98077282197016,499.29560788419968,484.61044294642903,469.92527800865849,455.24011307088790,440.55494813311731,425.86978319534677,411.18461825757612,396.49945331980558,381.81428838203499,367.12912344426445,352.44395850649374,337.75879356872332,323.07362863095284,308.38846369318213,293.70329875541148,279.01813381764106,264.33296887987046,249.64780394209978,234.96263900432925,220.27747406655877,205.59230912878812,190.90714419101747,176.22197925324693,161.53681431547642,146.85164937770588,132.16648443993523,117.48131950216458,102.79615456439406,88.110989626623535,73.425824688853012,58.740659751082354,44.055494813311697,29.370329875541177,14.685164937770653,-822.36923651515076,-807.68407157738170,-792.99890663961105,-778.31374170184051,-763.62857676406998,-748.94341182629944,-734.25824688852890,-719.57308195075836,-704.88791701298771,-690.20275207521718,-675.51758713744641,-660.83242219967599,-646.14725726190534,-631.46209232413480,-616.77692738636426,-602.09176244859361,-587.40659751082308,-572.72143257305254,-558.0362676352820,-543.35110269751135,-528.66593775974070,-513.98077282197016,-499.29560788419968,-484.61044294642903,-469.92527800865849,-455.24011307088790,-440.55494813311731,-425.86978319534677,-411.18461825757612,-396.49945331980558,-381.81428838203499,-367.12912344426445,-352.44395850649374,-337.75879356872332,-323.07362863095284,-308.38846369318213,-293.70329875541148,-279.01813381764106,-264.33296887987046,-249.64780394209978,-234.96263900432925,-220.27747406655877,-205.59230912878812,-190.90714419101747,-176.22197925324693,-161.53681431547642,-146.85164937770588,-132.16648443993523,-117.48131950216458,-102.79615456439406,-88.110989626623535,-73.425824688853012,-58.740659751082354,-44.055494813311697,-29.370329875541177,-14.685164937770653,-2467.1077095454539,-2423.0522147321449,-2378.9967199188332,-2334.9412251055214,-2290.8857302922102,-2246.8302354788980,-2202.7747406655863,-2158.7192458522745,-2114.6637510389628,-2070.6082562256511,-2026.5527614123394,-1982.4972665990274,-1938.4417717857157,-1894.3862769724044,-1850.3307821590927,-1806.2752873457805,-1762.2197925324690,-1718.1642977191573,-1674.1088029058458,-1630.0533080925338,-1585.9978132792221,-1541.9423184659104,-1497.8868236525989,-1453.8313288392867,-1409.7758340259752,-1365.7203392126635,-1321.6648443993518,-1277.609349586040,-1233.5538547727283,-1189.4983599594168,-1145.4428651461051,-1101.3873703327931,-1057.3318755194812,-1013.2763807061699,-969.22088589285829,-925.16539107954634,-881.10989626623427,-837.0544014529230,-792.99890663961128,-748.94341182629933,-704.88791701298771,-660.83242219967610,-616.77692738636415,-572.72143257305231,-528.66593775974070,-484.61044294642915,-440.55494813311759,-396.49945331980564,-352.44395850649363,-308.38846369318208,-264.33296887987058,-220.27747406655899,-176.22197925324704,-132.16648443993506,-88.110989626623521,-44.055494813311952,-4111.8461825757568,-4038.4203578869069,-3964.9945331980543,-3891.5687085092013,-3818.1428838203487,-3744.7170591314957,-3671.2912344426427,-3597.8654097537906,-3524.4395850649371,-3451.0137603760845,-3377.5879356872310,-3304.1621109983789,-3230.7362863095254,-3157.3104616206729,-3083.8846369318203,-3010.4588122429673,-2937.0329875541147,-2863.6071628652612,-2790.1813381764086,-2716.7555134875556,-2643.3296887987030,-2569.903864109850,-2496.4780394209974,-2423.0522147321440,-2349.6263900432918,-2276.2005653544388,-2202.7747406655853,-2129.3489159767332,-2055.9230912878797,-1982.4972665990274,-1909.0714419101744,-1835.6456172213213,-1762.2197925324681,-1688.7939678436160,-1615.3681431547634,-1541.9423184659101,-1468.5164937770569,-1395.0906690882048,-1321.6648443993518,-1248.2390197104985,-1174.8131950216459,-1101.3873703327934,-1027.9615456439401,-954.53572095508696,-881.10989626623427,-807.68407157738170,-734.25824688852913,-660.83242219967588,-587.40659751082262,-513.98077282197005,-440.55494813311748,-367.12912344426491,-293.70329875541165,-220.27747406655840,-146.85164937770583,-73.425824688853240,-5756.5846556060624,-5653.7885010416712,-5550.9923464772764,-5448.1961919128835,-5345.4000373484896,-5242.6038827840948,-5139.8077282197009,-5037.0115736553080,-4934.2154190909132,-4831.4192645265193,-4728.6231099621245,-4625.8269553977316,-4523.0308008333368,-4420.2346462689429,-4317.4384917045491,-4214.6423371401552,-4111.8461825757613,-4009.0500280113665,-3906.2538734469731,-3803.4577188825788,-3700.6615643181849,-3597.8654097537906,-3495.0692551893972,-3392.2731006250024,-3289.4769460606090,-3186.6807914962146,-3083.8846369318208,-2981.0884823674269,-2878.2923278030325,-2775.4961732386387,-2672.7000186742448,-2569.9038641098505,-2467.1077095454561,-2364.3115549810627,-2261.5154004166693,-2158.7192458522745,-2055.9230912878797,-1953.1269367234868,-1850.3307821590929,-1747.5346275946983,-1644.7384730303047,-1541.9423184659111,-1439.1461639015165,-1336.3500093371219,-1233.5538547727283,-1130.7577002083347,-1027.9615456439410,-925.16539107954645,-822.36923651515190,-719.57308195075825,-616.77692738636460,-513.98077282197096,-411.18461825757635,-308.38846369318185,-205.59230912878817,-102.79615456439456]},{"input":1.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]},{"input":2.0,"values":[3.5242919693700969e-12,2.3495279795800647e-12,1.1747639897900324e-12,0.0,132.16648443993822,132.16648443993705,132.16648443993589,132.16648443993469,264.33296887987410,264.33296887987291,264.33296887987058,264.33296887986938,396.49945331980996,396.49945331980882,396.49945331980643,396.49945331980530,528.66593775974468,528.66593775974354,528.66593775974115,528.66593775974115,660.83242219967940,660.83242219967826,660.83242219967701,660.83242219967588,792.99890663961412,792.99890663961287,792.99890663961173,792.99890663961060,925.16539107954986,925.16539107954986,925.16539107954759,925.16539107954520,1057.3318755194857,1057.3318755194846,1057.3318755194823,1057.3318755194809,1189.4983599594204,1189.4983599594193,1189.4983599594170,1189.4983599594170,1321.6648443993552,1321.6648443993540,1321.6648443993529,1321.6648443993518,1453.8313288392910,1453.8313288392887,1453.8313288392874,1453.8313288392874,1585.9978132792257,1585.9978132792257,1585.9978132792235,1585.9978132792221,1718.1642977191616,1718.1642977191605,1718.1642977191582,1718.1642977191568,1850.3307821590963,1850.3307821590952,1850.3307821590929,1850.3307821590929,1982.4972665990308,1982.4972665990299,1982.4972665990288,1982.4972665990274,2114.6637510389669,2114.6637510389646,2114.6637510389633,2114.6637510389633,2246.8302354789012,2246.8302354789012,2246.8302354788989,2246.8302354788971,2378.9967199188368,2378.9967199188354,2378.9967199188341,2378.9967199188336,2511.1632043587720,2511.1632043587711,2511.1632043587692,2511.1632043587679,2643.3296887987067,2643.3296887987067,2643.3296887987049,2643.3296887987035,2775.4961732386428,2775.4961732386409,2775.4961732386391,2775.4961732386391,2907.6626576785779,2907.6626576785770,2907.6626576785748,2907.6626576785739,3039.8291421185127,3039.8291421185113,3039.8291421185099,3039.8291421185090,3171.9956265584483,3171.9956265584469,3171.9956265584451,3171.9956265584451,3304.1621109983826,3304.1621109983826,3304.1621109983807,3304.1621109983785,3436.3285954383186,3436.3285954383164,3436.3285954383150,3436.3285954383150,3568.4950798782538,3568.4950798782529,3568.4950798782506,3568.4950798782497,3700.6615643181885,3700.6615643181872,3700.6615643181858,3700.6615643181849,3832.8280487581242,3832.8280487581233,3832.8280487581219,3832.8280487581210,3964.9945331980593,3964.9945331980575,3964.9945331980557,3964.9945331980548,4097.1610176379945,4097.1610176379936,4097.1610176379909,4097.161017637990,4229.3275020779301,4229.3275020779283,4229.3275020779265,4229.3275020779256,4361.4939865178658,4361.4939865178640,4361.4939865178621,4361.4939865178612,4493.6604709577987,4493.6604709577978,4493.6604709577960,4493.6604709577960,4625.8269553977343,4625.8269553977325,4625.8269553977316,4625.8269553977307,4757.9934398376699,4757.9934398376690,4757.9934398376672,4757.9934398376672,4890.1599242776065,4890.1599242776056,4890.1599242776028,4890.1599242776028,5022.3264087175403,5022.3264087175394,5022.3264087175367,5022.3264087175357,5154.4928931574750,5154.4928931574741,5154.4928931574714,5154.4928931574714,5286.6593775974115,5286.6593775974097,5286.6593775974079,5286.6593775974079,5418.8258620373454,5418.8258620373454,5418.8258620373426,5418.8258620373426,5550.9923464772810,5550.9923464772810,5550.9923464772783,5550.9923464772774,5683.1588309172166,5683.1588309172157,5683.1588309172130,5683.1588309172112,5815.3253153571522,5815.3253153571513,5815.3253153571486,5815.3253153571477,5947.4917997970870,5947.4917997970861,5947.4917997970833,5947.4917997970833,6079.6582842370217,6079.6582842370208,6079.6582842370199,6079.6582842370181,6211.8247686769564,6211.8247686769555,6211.8247686769546,6211.8247686769528,6343.9912531168929,6343.9912531168911,6343.9912531168902,6343.9912531168884,6476.1577375568268,6476.1577375568268,6476.1577375568249,6476.1577375568231,6608.3242219967633,6608.3242219967615,6608.3242219967588,6608.3242219967588,6740.4907064366971,6740.4907064366962,6740.4907064366944,6740.4907064366944,6872.6571908766327,6872.6571908766318,6872.657190876630,6872.6571908766291,7004.8236753165684,7004.8236753165675,7004.8236753165656,7004.8236753165647,7136.9901597565040,7136.9901597565031,7136.9901597565004,7136.9901597564995,7269.1566441964387,7269.1566441964378,7269.1566441964351,7269.1566441964342,7401.3231286363734,7401.3231286363716,7401.3231286363716,7401.3231286363698,7533.4896130763082,7533.4896130763082,7533.4896130763073,7533.4896130763054,-0.0,-1.1747639897900324e-12,-2.3495279795800647e-12,-3.5242919693700969e-12,-132.16648443993469,-132.16648443993589,-132.16648443993705,-132.16648443993822,-264.33296887986938,-264.33296887987058,-264.33296887987291,-264.33296887987410,-396.49945331980530,-396.49945331980643,-396.49945331980882,-396.49945331980996,-528.66593775974115,-528.66593775974115,-528.66593775974354,-528.66593775974468,-660.83242219967588,-660.83242219967701,-660.83242219967826,-660.83242219967940,-792.99890663961060,-792.99890663961173,-792.99890663961287,-792.99890663961412,-925.16539107954520,-925.16539107954759,-925.16539107954986,-925.16539107954986,-1057.3318755194809,-1057.3318755194823,-1057.3318755194846,-1057.3318755194857,-1189.4983599594170,-1189.4983599594170,-1189.4983599594193,-1189.4983599594204,-1321.6648443993518,-1321.6648443993529,-1321.6648443993540,-1321.6648443993552,-1453.8313288392874,-1453.8313288392874,-1453.8313288392887,-1453.8313288392910,-1585.9978132792221,-1585.9978132792235,-1585.9978132792257,-1585.9978132792257,-1718.1642977191568,-1718.1642977191582,-1718.1642977191605,-1718.1642977191616,-1850.3307821590929,-1850.3307821590929,-1850.3307821590952,-1850.3307821590963,-1982.4972665990274,-1982.4972665990288,-1982.4972665990299,-1982.4972665990308,-2114.6637510389633,-2114.6637510389633,-2114.6637510389646,-2114.6637510389669,-2246.8302354788971,-2246.8302354788989,-2246.8302354789012,-2246.8302354789012,-2378.9967199188336,-2378.9967199188341,-2378.9967199188354,-2378.9967199188368,-2511.1632043587679,-2511.1632043587692,-2511.1632043587711,-2511.1632043587720,-2643.3296887987035,-2643.3296887987049,-2643.3296887987067,-2643.3296887987067,-2775.4961732386391,-2775.4961732386391,-2775.4961732386409,-2775.4961732386428,-2907.6626576785739,-2907.6626576785748,-2907.6626576785770,-2907.6626576785779,-3039.8291421185090,-3039.8291421185099,-3039.8291421185113,-3039.8291421185127,-3171.9956265584451,-3171.9956265584451,-3171.9956265584469,-3171.9956265584483,-3304.1621109983785,-3304.1621109983807,-3304.1621109983826,-3304.1621109983826,-3436.3285954383150,-3436.3285954383150,-3436.3285954383164,-3436.3285954383186,-3568.4950798782497,-3568.4950798782506,-3568.4950798782529,-3568.4950798782538,-3700.6615643181849,-3700.6615643181858,-3700.6615643181872,-3700.6615643181885,-3832.8280487581210,-3832.8280487581219,-3832.8280487581233,-3832.8280487581242,-3964.9945331980548,-3964.9945331980557,-3964.9945331980575,-3964.9945331980593,-4097.161017637990,-4097.1610176379909,-4097.1610176379936,-4097.1610176379945,-4229.3275020779256,-4229.3275020779265,-4229.3275020779283,-4229.3275020779301,-4361.4939865178612,-4361.4939865178621,-4361.4939865178640,-4361.4939865178658,-4493.6604709577960,-4493.6604709577960,-4493.6604709577978,-4493.6604709577987,-4625.8269553977307,-4625.8269553977316,-4625.8269553977325,-4625.8269553977343,-4757.9934398376672,-4757.9934398376672,-4757.9934398376690,-4757.9934398376699,-4890.1599242776028,-4890.1599242776028,-4890.1599242776056,-4890.1599242776065,-5022.3264087175357,-5022.3264087175367,-5022.3264087175394,-5022.3264087175403,-5154.4928931574714,-5154.4928931574714,-5154.4928931574741,-5154.4928931574750,-5286.6593775974079,-5286.6593775974079,-5286.6593775974097,-5286.6593775974115,-5418.8258620373426,-5418.8258620373426,-5418.8258620373454,-5418.8258620373454,-5550.9923464772774,-5550.9923464772783,-5550.9923464772810,-5550.9923464772810,-5683.1588309172112,-5683.1588309172130,-5683.1588309172157,-5683.1588309172166,-5815.3253153571477,-5815.3253153571486,-5815.3253153571513,-5815.3253153571522,-5947.4917997970833,-5947.4917997970833,-5947.4917997970861,-5947.4917997970870,-6079.6582842370181,-6079.6582842370199,-6079.6582842370208,-6079.6582842370217,-6211.8247686769528,-6211.8247686769546,-6211.8247686769555,-6211.8247686769564,-6343.9912531168884,-6343.9912531168902,-6343.9912531168911,-6343.9912531168929,-6476.1577375568231,-6476.1577375568249,-6476.1577375568268,-6476.1577375568268,-6608.3242219967588,-6608.3242219967588,-6608.3242219967615,-6608.3242219967633,-6740.4907064366944,-6740.4907064366944,-6740.4907064366962,-6740.4907064366971,-6872.6571908766291,-6872.657190876630,-6872.6571908766318,-6872.6571908766327,-7004.8236753165647,-7004.8236753165656,-7004.8236753165675,-7004.8236753165684,-7136.9901597564995,-7136.9901597565004,-7136.9901597565031,-7136.9901597565040,-7269.1566441964342,-7269.1566441964351,-7269.1566441964378,-7269.1566441964387,-7401.3231286363698,-7401.3231286363716,-7401.3231286363716,-7401.3231286363734,-7533.4896130763054,-7533.4896130763073,-7533.4896130763082,-7533.4896130763082,0.0,9.1370532539224727e-13,1.8274106507844945e-12,2.7411159761767420e-12,0.0,6.5264666099446246e-13,1.3052933219889249e-12,1.9579399829833875e-12,0.0,3.9158799659667746e-13,7.8317599319335492e-13,1.1747639897900322e-12,0.0,1.3052933219889250e-13,2.6105866439778501e-13,3.9158799659667751e-13,-0.0,-1.3052933219889250e-13,-2.6105866439778501e-13,-3.9158799659667751e-13,-0.0,-3.9158799659667746e-13,-7.8317599319335492e-13,-1.1747639897900322e-12,-0.0,-6.5264666099446226e-13,-1.3052933219889245e-12,-1.9579399829833871e-12,-0.0,-9.1370532539224727e-13,-1.8274106507844945e-12,-2.7411159761767420e-12,102.79615456439639,205.59230912879093,308.38846369318549,411.18461825757913,513.98077282197278,616.77692738636642,719.57308195076098,822.36923651515554,925.16539107954918,1027.9615456439428,1130.7577002083374,1233.5538547727310,1336.3500093371256,1439.1461639015192,1541.9423184659129,1644.7384730303074,1747.5346275947006,1850.3307821590952,1953.1269367234893,2055.9230912878829,2158.7192458522777,2261.5154004166716,2364.3115549810655,2467.1077095454593,2569.9038641098532,2672.7000186742471,2775.4961732386414,2878.2923278030348,2981.0884823674296,3083.8846369318230,3186.6807914962169,3289.4769460606112,3392.2731006250060,3495.0692551893985,3597.8654097537928,3700.6615643181876,3803.4577188825820,3906.2538734469754,4009.0500280113697,4111.8461825757640,4214.6423371401570,4317.4384917045509,4420.2346462689457,4523.0308008333404,4625.8269553977334,4728.6231099621273,4831.4192645265211,4934.2154190909159,5037.0115736553089,5139.8077282197037,5242.6038827840976,5345.4000373484914,5448.1961919128853,5550.9923464772810,5653.7885010416740,5756.5846556060678,5859.3808101704617,73.425824688854561,146.85164937770782,220.27747406656110,293.70329875541370,367.12912344426627,440.55494813311890,513.98077282197221,587.40659751082535,660.83242219967804,734.25824688853061,807.68407157738386,881.10989626623643,954.53572095508980,1027.9615456439424,1101.3873703327952,1174.8131950216482,1248.2390197105005,1321.6648443993538,1395.0906690882068,1468.5164937770594,1541.9423184659126,1615.3681431547654,1688.7939678436180,1762.2197925324713,1835.6456172213236,1909.0714419101766,1982.4972665990299,2055.9230912878825,2129.3489159767355,2202.7747406655885,2276.2005653544411,2349.6263900432941,2423.0522147321471,2496.4780394209993,2569.9038641098523,2643.3296887987053,2716.7555134875588,2790.1813381764109,2863.6071628652639,2937.0329875541170,3010.458812242970,3083.8846369318226,3157.3104616206756,3230.7362863095286,3304.1621109983816,3377.5879356872342,3451.0137603760868,3524.4395850649403,3597.8654097537924,3671.2912344426459,3744.7170591314980,3818.1428838203510,3891.5687085092045,3964.9945331980575,4038.4203578869101,4111.8461825757631,4185.2720072646161,44.055494813312762,88.110989626624701,132.16648443993665,176.22197925324821,220.27747406655976,264.33296887987132,308.38846369318327,352.44395850649528,396.49945331980678,440.55494813311833,484.61044294643028,528.66593775974184,572.72143257305379,616.77692738636540,660.83242219967701,704.88791701298885,748.94341182630023,792.99890663961219,837.05440145292403,881.10989626623552,925.16539107954759,969.22088589285931,1013.2763807061709,1057.3318755194828,1101.3873703327940,1145.4428651461060,1189.4983599594177,1233.5538547727294,1277.6093495860414,1321.6648443993529,1365.7203392126644,1409.7758340259766,1453.8313288392885,1497.8868236525996,1541.9423184659113,1585.9978132792232,1630.0533080925352,1674.1088029058465,1718.1642977191582,1762.2197925324704,1806.2752873457819,1850.3307821590934,1894.3862769724051,1938.4417717857175,1982.4972665990288,2026.5527614123405,2070.6082562256520,2114.6637510389642,2158.7192458522754,2202.7747406655876,2246.8302354788989,2290.8857302922106,2334.9412251055223,2378.9967199188345,2423.0522147321462,2467.1077095454575,2511.1632043587697,14.685164937770940,29.370329875541564,44.055494813312215,58.740659751082738,73.425824688853268,88.110989626623791,102.79615456439444,117.48131950216509,132.16648443993563,146.85164937770614,161.53681431547679,176.22197925324733,190.90714419101798,205.59230912878849,220.27747406655902,234.96263900432967,249.64780394210015,264.33296887987075,279.01813381764134,293.70329875541188,308.38846369318253,323.07362863095312,337.75879356872366,352.44395850649425,367.12912344426474,381.81428838203544,396.49945331980598,411.18461825757652,425.86978319534717,440.55494813311765,455.24011307088819,469.92527800865884,484.61044294642954,499.29560788419985,513.98077282197050,528.66593775974115,543.35110269751181,558.03626763528223,572.72143257305277,587.40659751082353,602.09176244859407,616.77692738636460,631.46209232413526,646.14725726190579,660.83242219967633,675.51758713744687,690.20275207521740,704.88791701298805,719.57308195075859,734.25824688852924,748.94341182629978,763.62857676407032,778.31374170184097,792.99890663961162,807.68407157738216,822.36923651515258,837.05440145292323,-14.685164937770889,-29.370329875541564,-44.055494813312215,-58.740659751082738,-73.425824688853268,-88.110989626623791,-102.79615456439444,-117.48131950216509,-132.16648443993563,-146.85164937770614,-161.53681431547679,-176.22197925324733,-190.90714419101798,-205.59230912878849,-220.27747406655902,-234.96263900432967,-249.64780394210015,-264.33296887987075,-279.01813381764134,-293.70329875541188,-308.38846369318253,-323.07362863095312,-337.75879356872366,-352.44395850649425,-367.12912344426474,-381.81428838203544,-396.49945331980598,-411.18461825757652,-425.86978319534717,-440.55494813311765,-455.24011307088819,-469.92527800865884,-484.61044294642954,-499.29560788419985,-513.98077282197050,-528.66593775974115,-543.35110269751181,-558.03626763528223,-572.72143257305277,-587.40659751082353,-602.09176244859407,-616.77692738636460,-631.46209232413526,-646.14725726190579,-660.83242219967633,-675.51758713744687,-690.20275207521740,-704.88791701298805,-719.57308195075859,-734.25824688852924,-748.94341182629978,-763.62857676407032,-778.31374170184097,-792.99890663961162,-807.68407157738216,-822.36923651515258,-837.05440145292323,-44.055494813312691,-88.110989626624701,-132.16648443993665,-176.22197925324821,-220.27747406655976,-264.33296887987132,-308.38846369318327,-352.44395850649528,-396.49945331980678,-440.55494813311833,-484.61044294643028,-528.66593775974184,-572.72143257305379,-616.77692738636540,-660.83242219967701,-704.88791701298885,-748.94341182630023,-792.99890663961219,-837.05440145292403,-881.10989626623552,-925.16539107954759,-969.22088589285931,-1013.2763807061709,-1057.3318755194828,-1101.3873703327940,-1145.4428651461060,-1189.4983599594177,-1233.5538547727294,-1277.6093495860414,-1321.6648443993529,-1365.7203392126644,-1409.7758340259766,-1453.8313288392885,-1497.8868236525996,-1541.9423184659113,-1585.9978132792232,-1630.0533080925352,-1674.1088029058465,-1718.1642977191582,-1762.2197925324704,-1806.2752873457819,-1850.3307821590934,-1894.3862769724051,-1938.4417717857175,-1982.4972665990288,-2026.5527614123405,-2070.6082562256520,-2114.6637510389642,-2158.7192458522754,-2202.7747406655876,-2246.8302354788989,-2290.8857302922106,-2334.9412251055223,-2378.9967199188345,-2423.0522147321462,-2467.1077095454575,-2511.1632043587697,-73.425824688854476,-146.85164937770776,-220.27747406656101,-293.70329875541364,-367.12912344426621,-440.55494813311878,-513.98077282197210,-587.40659751082524,-660.83242219967781,-734.25824688853038,-807.68407157738363,-881.10989626623632,-954.53572095508946,-1027.9615456439419,-1101.3873703327947,-1174.8131950216480,-1248.2390197105001,-1321.6648443993533,-1395.0906690882064,-1468.5164937770589,-1541.9423184659122,-1615.3681431547650,-1688.7939678436176,-1762.2197925324708,-1835.6456172213232,-1909.0714419101764,-1982.4972665990292,-2055.9230912878820,-2129.3489159767350,-2202.7747406655876,-2276.2005653544402,-2349.6263900432932,-2423.0522147321467,-2496.4780394209984,-2569.9038641098518,-2643.3296887987049,-2716.7555134875583,-2790.181338176410,-2863.6071628652630,-2937.0329875541165,-3010.4588122429691,-3083.8846369318217,-3157.3104616206747,-3230.7362863095282,-3304.1621109983807,-3377.5879356872333,-3451.0137603760854,-3524.4395850649389,-3597.8654097537919,-3671.2912344426450,-3744.7170591314975,-3818.1428838203501,-3891.5687085092031,-3964.9945331980566,-4038.4203578869096,-4111.8461825757613,-4185.2720072646152,-102.79615456439635,-205.59230912879093,-308.38846369318549,-411.18461825757913,-513.98077282197278,-616.77692738636642,-719.57308195076098,-822.36923651515554,-925.16539107954918,-1027.9615456439428,-1130.7577002083374,-1233.5538547727310,-1336.3500093371256,-1439.1461639015192,-1541.9423184659129,-1644.7384730303074,-1747.5346275947006,-1850.3307821590952,-1953.1269367234893,-2055.9230912878829,-2158.7192458522777,-2261.5154004166716,-2364.3115549810655,-2467.1077095454593,-2569.9038641098532,-2672.7000186742471,-2775.4961732386414,-2878.2923278030348,-2981.0884823674296,-3083.8846369318230,-3186.6807914962169,-3289.4769460606112,-3392.2731006250060,-3495.0692551893985,-3597.8654097537928,-3700.6615643181876,-3803.4577188825820,-3906.2538734469754,-4009.0500280113697,-4111.8461825757640,-4214.6423371401570,-4317.4384917045509,-4420.2346462689457,-4523.0308008333404,-4625.8269553977334,-4728.6231099621273,-4831.4192645265211,-4934.2154190909159,-5037.0115736553089,-5139.8077282197037,-5242.6038827840976,-5345.4000373484914,-5448.1961919128853,-5550.9923464772810,-5653.7885010416740,-5756.5846556060678,-5859.3808101704617,5859.3808101704608,5859.3808101704599,5859.3808101704590,4185.2720072646152,4185.2720072646152,4185.2720072646143,2511.1632043587692,2511.1632043587688,2511.1632043587683,837.05440145292312,837.0544014529230,837.0544014529230,-837.05440145292312,-837.0544014529230,-837.0544014529230,-2511.1632043587692,-2511.1632043587688,-2511.1632043587683,-4185.2720072646143,-4185.2720072646134,-4185.2720072646125,-5859.3808101704608,-5859.3808101704599,-5859.3808101704590,5756.5846556060651,5653.7885010416712,5550.9923464772764,5448.1961919128835,5345.4000373484896,5242.6038827840948,5139.8077282197009,5037.0115736553080,4934.2154190909132,4831.4192645265193,4728.6231099621245,4625.8269553977316,4523.0308008333368,4420.2346462689429,4317.4384917045491,4214.6423371401552,4111.8461825757613,4009.0500280113665,3906.2538734469731,3803.4577188825788,3700.6615643181849,3597.8654097537906,3495.0692551893972,3392.2731006250024,3289.4769460606090,3186.6807914962146,3083.8846369318208,2981.0884823674269,2878.2923278030325,2775.4961732386387,2672.7000186742448,2569.9038641098505,2467.1077095454561,2364.3115549810627,2261.5154004166693,2158.7192458522745,2055.9230912878797,1953.1269367234868,1850.3307821590929,1747.5346275946983,1644.7384730303047,1541.9423184659111,1439.1461639015165,1336.3500093371219,1233.5538547727283,1130.7577002083347,1027.9615456439410,925.16539107954645,822.36923651515190,719.57308195075825,616.77692738636460,513.98077282197096,411.18461825757635,308.38846369318185,205.59230912878817,102.79615456439456,4111.8461825757604,4038.4203578869087,3964.9945331980548,3891.5687085092022,3818.1428838203501,3744.7170591314966,3671.2912344426441,3597.8654097537915,3524.4395850649380,3451.0137603760854,3377.5879356872324,3304.1621109983794,3230.7362863095263,3157.3104616206738,3083.8846369318212,3010.4588122429677,2937.0329875541156,2863.6071628652621,2790.1813381764096,2716.7555134875565,2643.3296887987040,2569.9038641098505,2496.4780394209979,2423.0522147321449,2349.6263900432918,2276.2005653544393,2202.7747406655863,2129.3489159767337,2055.9230912878802,1982.4972665990279,1909.0714419101751,1835.6456172213220,1762.2197925324688,1688.7939678436164,1615.3681431547639,1541.9423184659106,1468.5164937770573,1395.0906690882050,1321.6648443993520,1248.2390197104990,1174.8131950216462,1101.3873703327936,1027.9615456439403,954.53572095508719,881.10989626623450,807.68407157738193,734.25824688852924,660.83242219967599,587.40659751082285,513.98077282197016,440.55494813311759,367.12912344426502,293.70329875541171,220.27747406655848,146.85164937770585,73.425824688853268,2467.1077095454580,2423.0522147321449,2378.9967199188332,2334.9412251055214,2290.8857302922102,2246.8302354788980,2202.7747406655863,2158.7192458522745,2114.6637510389628,2070.6082562256511,2026.5527614123394,1982.4972665990274,1938.4417717857157,1894.3862769724044,1850.3307821590927,1806.2752873457805,1762.2197925324690,1718.1642977191573,1674.1088029058458,1630.0533080925338,1585.9978132792221,1541.9423184659104,1497.8868236525989,1453.8313288392867,1409.7758340259752,1365.7203392126635,1321.6648443993518,1277.609349586040,1233.5538547727283,1189.4983599594168,1145.4428651461051,1101.3873703327931,1057.3318755194812,1013.2763807061699,969.22088589285829,925.16539107954634,881.10989626623427,837.0544014529230,792.99890663961128,748.94341182629933,704.88791701298771,660.83242219967610,616.77692738636415,572.72143257305231,528.66593775974070,484.61044294642915,440.55494813311759,396.49945331980564,352.44395850649363,308.38846369318208,264.33296887987058,220.27747406655899,176.22197925324704,132.16648443993506,88.110989626623521,44.055494813311952,822.36923651515372,807.68407157738170,792.99890663961105,778.31374170184051,763.62857676406998,748.94341182629944,734.25824688852890,719.57308195075836,704.88791701298771,690.20275207521718,675.51758713744641,660.83242219967599,646.14725726190534,631.46209232413480,616.77692738636426,602.09176244859361,587.40659751082308,572.72143257305254,558.0362676352820,543.35110269751135,528.66593775974070,513.98077282197016,499.29560788419968,484.61044294642903,469.92527800865849,455.24011307088790,440.55494813311731,425.86978319534677,411.18461825757612,396.49945331980558,381.81428838203499,367.12912344426445,352.44395850649374,337.75879356872332,323.07362863095284,308.38846369318213,293.70329875541148,279.01813381764106,264.33296887987046,249.64780394209978,234.96263900432925,220.27747406655877,205.59230912878812,190.90714419101747,176.22197925324693,161.53681431547642,146.85164937770588,132.16648443993523,117.48131950216458,102.79615456439406,88.110989626623535,73.425824688853012,58.740659751082354,44.055494813311697,29.370329875541177,14.685164937770653,-822.36923651515076,-807.68407157738170,-792.99890663961105,-778.31374170184051,-763.62857676406998,-748.94341182629944,-734.25824688852890,-719.57308195075836,-704.88791701298771,-690.20275207521718,-675.51758713744641,-660.83242219967599,-646.14725726190534,-631.46209232413480,-616.77692738636426,-602.09176244859361,-587.40659751082308,-572.72143257305254,-558.0362676352820,-543.35110269751135,-528.66593775974070,-513.98077282197016,-499.29560788419968,-484.61044294642903,-469.92527800865849,-455.24011307088790,-440.55494813311731,-425.86978319534677,-411.18461825757612,-396.49945331980558,-381.81428838203499,-367.12912344426445,-352.44395850649374,-337.75879356872332,-323.07362863095284,-308.38846369318213,-293.70329875541148,-279.01813381764106,-264.33296887987046,-249.64780394209978,-234.96263900432925,-220.27747406655877,-205.59230912878812,-190.90714419101747,-176.22197925324693,-161.53681431547642,-146.85164937770588,-132.16648443993523,-117.48131950216458,-102.79615456439406,-88.110989626623535,-73.425824688853012,-58.740659751082354,-44.055494813311697,-29.370329875541177,-14.685164937770653,-2467.1077095454539,-2423.0522147321449,-2378.9967199188332,-2334.9412251055214,-2290.8857302922102,-2246.8302354788980,-2202.7747406655863,-2158.7192458522745,-2114.6637510389628,-2070.6082562256511,-2026.5527614123394,-1982.4972665990274,-1938.4417717857157,-1894.3862769724044,-1850.3307821590927,-1806.2752873457805,-1762.2197925324690,-1718.1642977191573,-1674.1088029058458,-1630.0533080925338,-1585.9978132792221,-1541.9423184659104,-1497.8868236525989,-1453.8313288392867,-1409.7758340259752,-1365.7203392126635,-1321.6648443993518,-1277.609349586040,-1233.5538547727283,-1189.4983599594168,-1145.4428651461051,-1101.3873703327931,-1057.3318755194812,-1013.2763807061699,-969.22088589285829,-925.16539107954634,-881.10989626623427,-837.0544014529230,-792.99890663961128,-748.94341182629933,-704.88791701298771,-660.83242219967610,-616.77692738636415,-572.72143257305231,-528.66593775974070,-484.61044294642915,-440.55494813311759,-396.49945331980564,-352.44395850649363,-308.38846369318208,-264.33296887987058,-220.27747406655899,-176.22197925324704,-132.16648443993506,-88.110989626623521,-44.055494813311952,-4111.8461825757568,-4038.4203578869069,-3964.9945331980543,-3891.5687085092013,-3818.1428838203487,-3744.7170591314957,-3671.2912344426427,-3597.8654097537906,-3524.4395850649371,-3451.0137603760845,-3377.5879356872310,-3304.1621109983789,-3230.7362863095254,-3157.3104616206729,-3083.8846369318203,-3010.4588122429673,-2937.0329875541147,-2863.6071628652612,-2790.1813381764086,-2716.7555134875556,-2643.3296887987030,-2569.903864109850,-2496.4780394209974,-2423.0522147321440,-2349.6263900432918,-2276.2005653544388,-2202.7747406655853,-2129.3489159767332,-2055.9230912878797,-1982.4972665990274,-1909.0714419101744,-1835.6456172213213,-1762.2197925324681,-1688.7939678436160,-1615.3681431547634,-1541.9423184659101,-1468.5164937770569,-1395.0906690882048,-1321.6648443993518,-1248.2390197104985,-1174.8131950216459,-1101.3873703327934,-1027.9615456439401,-954.53572095508696,-881.10989626623427,-807.68407157738170,-734.25824688852913,-660.83242219967588,-587.40659751082262,-513.98077282197005,-440.55494813311748,-367.12912344426491,-293.70329875541165,-220.27747406655840,-146.85164937770583,-73.425824688853240,-5756.5846556060624,-5653.7885010416712,-5550.9923464772764,-5448.1961919128835,-5345.4000373484896,-5242.6038827840948,-5139.8077282197009,-5037.0115736553080,-4934.2154190909132,-4831.4192645265193,-4728.6231099621245,-4625.8269553977316,-4523.0308008333368,-4420.2346462689429,-4317.4384917045491,-4214.6423371401552,-4111.8461825757613,-4009.0500280113665,-3906.2538734469731,-3803.4577188825788,-3700.6615643181849,-3597.8654097537906,-3495.0692551893972,-3392.2731006250024,-3289.4769460606090,-3186.6807914962146,-3083.8846369318208,-2981.0884823674269,-2878.2923278030325,-2775.4961732386387,-2672.7000186742448,-2569.9038641098505,-2467.1077095454561,-2364.3115549810627,-2261.5154004166693,-2158.7192458522745,-2055.9230912878797,-1953.1269367234868,-1850.3307821590929,-1747.5346275946983,-1644.7384730303047,-1541.9423184659111,-1439.1461639015165,-1336.3500093371219,-1233.5538547727283,-1130.7577002083347,-1027.9615456439410,-925.16539107954645,-822.36923651515190,-719.57308195075825,-616.77692738636460,-513.98077282197096,-411.18461825757635,-308.38846369318185,-205.59230912878817,-102.79615456439456]}],"dataType":0,"inputName":"","name":"Stress"}],"indices":[1,2,6,5,0,2,3,7,6,0,3,4,8,7,0,5,6,10,9,0,6,7,11,10,0,7,8,12,11,0,9,10,14,13,0,10,11,15,14,0,11,12,16,15,0,13,14,18,17,0,14,15,19,18,0,15,16,20,19,0,17,18,22,21,0,18,19,23,22,0,19,20,24,23,0,21,22,26,25,0,22,23,27,26,0,23,24,28,27,0,25,26,30,29,0,26,27,31,30,0,27,28,32,31,0,29,30,34,33,0,30,31,35,34,0,31,32,36,35,0,33,34,38,37,0,34,35,39,38,0,35,36,40,39,0,37,38,42,41,0,38,39,43,42,0,39,40,44,43,0,41,42,46,45,0,42,43,47,46,0,43,44,48,47,0,45,46,50,49,0,46,47,51,50,0,47,48,52,51,0,49,50,54,53,0,50,51,55,54,0,51,52,56,55,0,53,54,58,57,0,54,55,59,58,0,55,56,60,59,0,57,58,62,61,0,58,59,63,62,0,59,60,64,63,0,61,62,66,65,0,62,63,67,66,0,63,64,68,67,0,65,66,70,69,0,66,67,71,70,0,67,68,72,71,0,69,70,74,73,0,70,71,75,74,0,71,72,76,75,0,73,74,78,77,0,74,75,79,78,0,75,76,80,79,0,77,78,82,81,0,78,79,83,82,0,79,80,84,83,0,81,82,86,85,0,82,83,87,86,0,83,84,88,87,0,85,86,90,89,0,86,87,91,90,0,87,88,92,91,0,89,90,94,93,0,90,91,95,94,0,91,92,96,95,0,93,94,98,97,0,94,95,99,98,0,95,96,100,99,0,97,98,102,101,0,98,99,103,102,0,99,100,104,103,0,101,102,106,105,0,102,103,107,106,0,103,104,108,107,0,105,106,110,109,0,106,107,111,110,0,107,108,112,111,0,109,110,114,113,0,110,111,115,114,0,111,112,116,115,0,113,114,118,117,0,114,115,119,118,0,115,116,120,119,0,117,118,122,121,0,118,119,123,122,0,119,120,124,123,0,121,122,126,125,0,122,123,127,126,0,123,124,128,127,0,125,126,130,129,0,126,127,131,130,0,127,128,132,131,0,129,130,134,133,0,130,131,135,134,0,131,132,136,135,0,133,134,138,137,0,134,135,139,138,0,135,136,140,139,0,137,138,142,141,0,138,139,143,142,0,139,140,144,143,0,141,142,146,145,0,142,143,147,146,0,143,144,148,147,0,145,146,150,149,0,146,147,151,150,0,147,148,152,151,0,149,150,154,153,0,150,151,155,154,0,151,152,156,155,0,153,154,158,157,0,154,155,159,158,0,155,156,160,159,0,157,158,162,161,0,158,159,163,162,0,159,160,164,163,0,161,162,166,165,0,162,163,167,166,0,163,164,168,167,0,165,166,170,169,0,166,167,171,170,0,167,168,172,171,0,169,170,174,173,0,170,171,175,174,0,171,172,176,175,0,173,174,178,177,0,174,175,179,178,0,175,176,180,179,0,177,178,182,181,0,178,179,183,182,0,179,180,184,183,0,181,182,186,185,0,182,183,187,186,0,183,184,188,187,0,185,186,190,189,0,186,187,191,190,0,187,188,192,191,0,189,190,194,193,0,190,191,195,194,0,191,192,196,195,0,193,194,198,197,0,194,195,199,198,0,195,196,200,199,0,197,198,202,201,0,198,199,203,202,0,199,200,204,203,0,201,202,206,205,0,202,203,207,206,0,203,204,208,207,0,205,206,210,209,0,206,207,211,210,0,207,208,212,211,0,209,210,214,213,0,210,211,215,214,0,211,212,216,215,0,213,214,218,217,0,214,215,219,218,0,215,216,220,219,0,217,218,222,221,0,218,219,223,222,0,219,220,224,223,0,221,222,226,225,0,222,223,227,226,0,223,224,228,227,0,225,226,230,229,0,226,227,231,230,0,227,228,232,231,0,233,234,238,237,0,234,235,239,238,0,235,236,240,239,0,237,238,242,241,0,238,239,243,242,0,239,240,244,243,0,241,242,246,245,0,242,243,247,246,0,243,244,248,247,0,245,246,250,249,0,246,247,251,250,0,247,248,252,251,0,249,250,254,253,0,250,251,255,254,0,251,252,256,255,0,253,254,258,257,0,254,255,259,258,0,255,256,260,259,0,257,258,262,261,0,258,259,263,262,0,259,260,264,263,0,261,262,266,265,0,262,263,267,266,0,263,264,268,267,0,265,266,270,269,0,266,267,271,270,0,267,268,272,271,0,269,270,274,273,0,270,271,275,274,0,271,272,276,275,0,273,274,278,277,0,274,275,279,278,0,275,276,280,279,0,277,278,282,281,0,278,279,283,282,0,279,280,284,283,0,281,282,286,285,0,282,283,287,286,0,283,284,288,287,0,285,286,290,289,0,286,287,291,290,0,287,288,292,291,0,289,290,294,293,0,290,291,295,294,0,291,292,296,295,0,293,294,298,297,0,294,295,299,298,0,295,296,300,299,0,297,298,302,301,0,298,299,303,302,0,299,300,304,303,0,301,302,306,305,0,302,303,307,306,0,303,304,308,307,0,305,306,310,309,0,306,307,311,310,0,307,308,312,311,0,309,310,314,313,0,310,311,315,314,0,311,312,316,315,0,313,314,318,317,0,314,315,319,318,0,315,316,320,319,0,317,318,322,321,0,318,319,323,322,0,319,320,324,323,0,321,322,326,325,0,322,323,327,326,0,323,324,328,327,0,325,326,330,329,0,326,327,331,330,0,327,328,332,331,0,329,330,334,333,0,330,331,335,334,0,331,332,336,335,0,333,334,338,337,0,334,335,339,338,0,335,336,340,339,0,337,338,342,341,0,338,339,343,342,0,339,340,344,343,0,341,342,346,345,0,342,343,347,346,0,343,344,348,347,0,345,346,350,349,0,346,347,351,350,0,347,348,352,351,0,349,350,354,353,0,350,351,355,354,0,351,352,356,355,0,353,354,358,357,0,354,355,359,358,0,355,356,360,359,0,357,358,362,361,0,358,359,363,362,0,359,360,364,363,0,361,362,366,365,0,362,363,367,366,0,363,364,368,367,0,365,366,370,369,0,366,367,371,370,0,367,368,372,371,0,369,370,374,373,0,370,371,375,374,0,371,372,376,375,0,373,374,378,377,0,374,375,379,378,0,375,376,380,379,0,377,378,382,381,0,378,379,383,382,0,379,380,384,383,0,381,382,386,385,0,382,383,387,386,0,383,384,388,387,0,385,386,390,389,0,386,387,391,390,0,387,388,392,391,0,389,390,394,393,0,390,391,395,394,0,391,392,396,395,0,393,394,398,397,0,394,395,399,398,0,395,396,400,399,0,397,398,402,401,0,398,399,403,402,0,399,400,404,403,0,401,402,406,405,0,402,403,407,406,0,403,404,408,407,0,405,406,410,409,0,406,407,411,410,0,407,408,412,411,0,409,410,414,413,0,410,411,415,414,0,411,412,416,415,0,413,414,418,417,0,414,415,419,418,0,415,416,420,419,0,417,418,422,421,0,418,419,423,422,0,419,420,424,423,0,421,422,426,425,0,422,423,427,426,0,423,424,428,427,0,425,426,430,429,0,426,427,431,430,0,427,428,432,431,0,429,430,434,433,0,430,431,435,434,0,431,432,436,435,0,433,434,438,437,0,434,435,439,438,0,435,436,440,439,0,437,438,442,441,0,438,439,443,442,0,439,440,444,443,0,441,442,446,445,0,442,443,447,446,0,443,444,448,447,0,445,446,450,449,0,446,447,451,450,0,447,448,452,451,0,449,450,454,453,0,450,451,455,454,0,451,452,456,455,0,453,454,458,457,0,454,455,459,458,0,455,456,460,459,0,457,458,462,461,0,458,459,463,462,0,459,460,464,463,0,4,3,466,465,0,3,2,467,466,0,2,1,468,467,0,465,466,470,469,0,466,467,471,470,0,467,468,472,471,0,469,470,474,473,0,470,471,475,474,0,471,472,476,475,0,473,474,478,477,0,474,475,479,478,0,475,476,480,479,0,477,478,482,481,0,478,479,483,482,0,479,480,484,483,0,481,482,486,485,0,482,483,487,486,0,483,484,488,487,0,485,486,490,489,0,486,487,491,490,0,487,488,492,491,0,489,490,494,493,0,490,491,495,494,0,491,492,496,495,0,493,494,234,233,0,494,495,235,234,0,495,496,236,235,0,1,5,497,468,0,5,9,498,497,0,9,13,499,498,0,13,17,500,499,0,17,21,501,500,0,21,25,502,501,0,25,29,503,502,0,29,33,504,503,0,33,37,505,504,0,37,41,506,505,0,41,45,507,506,0,45,49,508,507,0,49,53,509,508,0,53,57,510,509,0,57,61,511,510,0,61,65,512,511,0,65,69,513,512,0,69,73,514,513,0,73,77,515,514,0,77,81,516,515,0,81,85,517,516,0,85,89,518,517,0,89,93,519,518,0,93,97,520,519,0,97,101,521,520,0,101,105,522,521,0,105,109,523,522,0,109,113,524,523,0,113,117,525,524,0,117,121,526,525,0,121,125,527,526,0,125,129,528,527,0,129,133,529,528,0,133,137,530,529,0,137,141,531,530,0,141,145,532,531,0,145,149,533,532,0,149,153,534,533,0,153,157,535,534,0,157,161,536,535,0,161,165,537,536,0,165,169,538,537,0,169,173,539,538,0,173,177,540,539,0,177,181,541,540,0,181,185,542,541,0,185,189,543,542,0,189,193,544,543,0,193,197,545,544,0,197,201,546,545,0,201,205,547,546,0,205,209,548,547,0,209,213,549,548,0,213,217,550,549,0,217,221,551,550,0,221,225,552,551,0,225,229,553,552,0,468,497,554,472,0,497,498,555,554,0,498,499,556,555,0,499,500,557,556,0,500,501,558,557,0,501,502,559,558,0,502,503,560,559,0,503,504,561,560,0,504,505,562,561,0,505,506,563,562,0,506,507,564,563,0,507,508,565,564,0,508,509,566,565,0,509,510,567,566,0,510,511,568,567,0,511,512,569,568,0,512,513,570,569,0,513,514,571,570,0,514,515,572,571,0,515,516,573,572,0,516,517,574,573,0,517,518,575,574,0,518,519,576,575,0,519,520,577,576,0,520,521,578,577,0,521,522,579,578,0,522,523,580,579,0,523,524,581,580,0,524,525,582,581,0,525,526,583,582,0,526,527,584,583,0,527,528,585,584,0,528,529,586,585,0,529,530,587,586,0,530,531,588,587,0,531,532,589,588,0,532,533,590,589,0,533,534,591,590,0,534,535,592,591,0,535,536,593,592,0,536,537,594,593,0,537,538,595,594,0,538,539,596,595,0,539,540,597,596,0,540,541,598,597,0,541,542,599,598,0,542,543,600,599,0,543,544,601,600,0,544,545,602,601,0,545,546,603,602,0,546,547,604,603,0,547,548,605,604,0,548,549,606,605,0,549,550,607,606,0,550,551,608,607,0,551,552,609,608,0,552,553,610,609,0,472,554,611,476,0,554,555,612,611,0,555,556,613,612,0,556,557,614,613,0,557,558,615,614,0,558,559,616,615,0,559,560,617,616,0,560,561,618,617,0,561,562,619,618,0,562,563,620,619,0,563,564,621,620,0,564,565,622,621,0,565,566,623,622,0,566,567,624,623,0,567,568,625,624,0,568,569,626,625,0,569,570,627,626,0,570,571,628,627,0,571,572,629,628,0,572,573,630,629,0,573,574,631,630,0,574,575,632,631,0,575,576,633,632,0,576,577,634,633,0,577,578,635,634,0,578,579,636,635,0,579,580,637,636,0,580,581,638,637,0,581,582,639,638,0,582,583,640,639,0,583,584,641,640,0,584,585,642,641,0,585,586,643,642,0,586,587,644,643,0,587,588,645,644,0,588,589,646,645,0,589,590,647,646,0,590,591,648,647,0,591,592,649,648,0,592,593,650,649,0,593,594,651,650,0,594,595,652,651,0,595,596,653,652,0,596,597,654,653,0,597,598,655,654,0,598,599,656,655,0,599,600,657,656,0,600,601,658,657,0,601,602,659,658,0,602,603,660,659,0,603,604,661,660,0,604,605,662,661,0,605,606,663,662,0,606,607,664,663,0,607,608,665,664,0,608,609,666,665,0,609,610,667,666,0,476,611,668,480,0,611,612,669,668,0,612,613,670,669,0,613,614,671,670,0,614,615,672,671,0,615,616,673,672,0,616,617,674,673,0,617,618,675,674,0,618,619,676,675,0,619,620,677,676,0,620,621,678,677,0,621,622,679,678,0,622,623,680,679,0,623,624,681,680,0,624,625,682,681,0,625,626,683,682,0,626,627,684,683,0,627,628,685,684,0,628,629,686,685,0,629,630,687,686,0,630,631,688,687,0,631,632,689,688,0,632,633,690,689,0,633,634,691,690,0,634,635,692,691,0,635,636,693,692,0,636,637,694,693,0,637,638,695,694,0,638,639,696,695,0,639,640,697,696,0,640,641,698,697,0,641,642,699,698,0,642,643,700,699,0,643,644,701,700,0,644,645,702,701,0,645,646,703,702,0,646,647,704,703,0,647,648,705,704,0,648,649,706,705,0,649,650,707,706,0,650,651,708,707,0,651,652,709,708,0,652,653,710,709,0,653,654,711,710,0,654,655,712,711,0,655,656,713,712,0,656,657,714,713,0,657,658,715,714,0,658,659,716,715,0,659,660,717,716,0,660,661,718,717,0,661,662,719,718,0,662,663,720,719,0,663,664,721,720,0,664,665,722,721,0,665,666,723,722,0,666,667,724,723,0,480,668,725,484,0,668,669,726,725,0,669,670,727,726,0,670,671,728,727,0,671,672,729,728,0,672,673,730,729,0,673,674,731,730,0,674,675,732,731,0,675,676,733,732,0,676,677,734,733,0,677,678,735,734,0,678,679,736,735,0,679,680,737,736,0,680,681,738,737,0,681,682,739,738,0,682,683,740,739,0,683,684,741,740,0,684,685,742,741,0,685,686,743,742,0,686,687,744,743,0,687,688,745,744,0,688,689,746,745,0,689,690,747,746,0,690,691,748,747,0,691,692,749,748,0,692,693,750,749,0,693,694,751,750,0,694,695,752,751,0,695,696,753,752,0,696,697,754,753,0,697,698,755,754,0,698,699,756,755,0,699,700,757,756,0,700,701,758,757,0,701,702,759,758,0,702,703,760,759,0,703,704,761,760,0,704,705,762,761,0,705,706,763,762,0,706,707,764,763,0,707,708,765,764,0,708,709,766,765,0,709,710,767,766,0,710,711,768,767,0,711,712,769,768,0,712,713,770,769,0,713,714,771,770,0,714,715,772,771,0,715,716,773,772,0,716,717,774,773,0,717,718,775,774,0,718,719,776,775,0,719,720,777,776,0,720,721,778,777,0,721,722,779,778,0,722,723,780,779,0,723,724,781,780,0,484,725,782,488,0,725,726,783,782,0,726,727,784,783,0,727,728,785,784,0,728,729,786,785,0,729,730,787,786,0,730,731,788,787,0,731,732,789,788,0,732,733,790,789,0,733,734,791,790,0,734,735,792,791,0,735,736,793,792,0,736,737,794,793,0,737,738,795,794,0,738,739,796,795,0,739,740,797,796,0,740,741,798,797,0,741,742,799,798,0,742,743,800,799,0,743,744,801,800,0,744,745,802,801,0,745,746,803,802,0,746,747,804,803,0,747,748,805,804,0,748,749,806,805,0,749,750,807,806,0,750,751,808,807,0,751,752,809,808,0,752,753,810,809,0,753,754,811,810,0,754,755,812,811,0,755,756,813,812,0,756,757,814,813,0,757,758,815,814,0,758,759,816,815,0,759,760,817,816,0,760,761,818,817,0,761,762,819,818,0,762,763,820,819,0,763,764,821,820,0,764,765,822,821,0,765,766,823,822,0,766,767,824,823,0,767,768,825,824,0,768,769,826,825,0,769,770,827,826,0,770,771,828,827,0,771,772,829,828,0,772,773,830,829,0,773,774,831,830,0,774,775,832,831,0,775,776,833,832,0,776,777,834,833,0,777,778,835,834,0,778,779,836,835,0,779,780,837,836,0,780,781,838,837,0,488,782,839,492,0,782,783,840,839,0,783,784,841,840,0,784,785,842,841,0,785,786,843,842,0,786,787,844,843,0,787,788,845,844,0,788,789,846,845,0,789,790,847,846,0,790,791,848,847,0,791,792,849,848,0,792,793,850,849,0,793,794,851,850,0,794,795,852,851,0,795,796,853,852,0,796,797,854,853,0,797,798,855,854,0,798,799,856,855,0,799,800,857,856,0,800,801,858,857,0,801,802,859,858,0,802,803,860,859,0,803,804,861,860,0,804,805,862,861,0,805,806,863,862,0,806,807,864,863,0,807,808,865,864,0,808,809,866,865,0,809,810,867,866,0,810,811,868,867,0,811,812,869,868,0,812,813,870,869,0,813,814,871,870,0,814,815,872,871,0,815,816,873,872,0,816,817,874,873,0,817,818,875,874,0,818,819,876,875,0,819,820,877,876,0,820,821,878,877,0,821,822,879,878,0,822,823,880,879,0,823,824,881,880,0,824,825,882,881,0,825,826,883,882,0,826,827,884,883,0,827,828,885,884,0,828,829,886,885,0,829,830,887,886,0,830,831,888,887,0,831,832,889,888,0,832,833,890,889,0,833,834,891,890,0,834,835,892,891,0,835,836,893,892,0,836,837,894,893,0,837,838,895,894,0,492,839,896,496,0,839,840,897,896,0,840,841,898,897,0,841,842,899,898,0,842,843,900,899,0,843,844,901,900,0,844,845,902,901,0,845,846,903,902,0,846,847,904,903,0,847,848,905,904,0,848,849,906,905,0,849,850,907,906,0,850,851,908,907,0,851,852,909,908,0,852,853,910,909,0,853,854,911,910,0,854,855,912,911,0,855,856,913,912,0,856,857,914,913,0,857,858,915,914,0,858,859,916,915,0,859,860,917,916,0,860,861,918,917,0,861,862,919,918,0,862,863,920,919,0,863,864,921,920,0,864,865,922,921,0,865,866,923,922,0,866,867,924,923,0,867,868,925,924,0,868,869,926,925,0,869,870,927,926,0,870,871,928,927,0,871,872,929,928,0,872,873,930,929,0,873,874,931,930,0,874,875,932,931,0,875,876,933,932,0,876,877,934,933,0,877,878,935,934,0,878,879,936,935,0,879,880,937,936,0,880,881,938,937,0,881,882,939,938,0,882,883,940,939,0,883,884,941,940,0,884,885,942,941,0,885,886,943,942,0,886,887,944,943,0,887,888,945,944,0,888,889,946,945,0,889,890,947,946,0,890,891,948,947,0,891,892,949,948,0,892,893,950,949,0,893,894,951,950,0,894,895,952,951,0,496,896,240,236,0,896,897,244,240,0,897,898,248,244,0,898,899,252,248,0,899,900,256,252,0,900,901,260,256,0,901,902,264,260,0,902,903,268,264,0,903,904,272,268,0,904,905,276,272,0,905,906,280,276,0,906,907,284,280,0,907,908,288,284,0,908,909,292,288,0,909,910,296,292,0,910,911,300,296,0,911,912,304,300,0,912,913,308,304,0,913,914,312,308,0,914,915,316,312,0,915,916,320,316,0,916,917,324,320,0,917,918,328,324,0,918,919,332,328,0,919,920,336,332,0,920,921,340,336,0,921,922,344,340,0,922,923,348,344,0,923,924,352,348,0,924,925,356,352,0,925,926,360,356,0,926,927,364,360,0,927,928,368,364,0,928,929,372,368,0,929,930,376,372,0,930,931,380,376,0,931,932,384,380,0,932,933,388,384,0,933,934,392,388,0,934,935,396,392,0,935,936,400,396,0,936,937,404,400,0,937,938,408,404,0,938,939,412,408,0,939,940,416,412,0,940,941,420,416,0,941,942,424,420,0,942,943,428,424,0,943,944,432,428,0,944,945,436,432,0,945,946,440,436,0,946,947,444,440,0,947,948,448,444,0,948,949,452,448,0,949,950,456,452,0,950,951,460,456,0,951,952,464,460,0,229,230,953,553,0,230,231,954,953,0,231,232,955,954,0,553,953,956,610,0,953,954,957,956,0,954,955,958,957,0,610,956,959,667,0,956,957,960,959,0,957,958,961,960,0,667,959,962,724,0,959,960,963,962,0,960,961,964,963,0,724,962,965,781,0,962,963,966,965,0,963,964,967,966,0,781,965,968,838,0,965,966,969,968,0,966,967,970,969,0,838,968,971,895,0,968,969,972,971,0,969,970,973,972,0,895,971,974,952,0,971,972,975,974,0,972,973,976,975,0,952,974,463,464,0,974,975,462,463,0,975,976,461,462,0,232,228,977,955,0,228,224,978,977,0,224,220,979,978,0,220,216,980,979,0,216,212,981,980,0,212,208,982,981,0,208,204,983,982,0,204,200,984,983,0,200,196,985,984,0,196,192,986,985,0,192,188,987,986,0,188,184,988,987,0,184,180,989,988,0,180,176,990,989,0,176,172,991,990,0,172,168,992,991,0,168,164,993,992,0,164,160,994,993,0,160,156,995,994,0,156,152,996,995,0,152,148,997,996,0,148,144,998,997,0,144,140,999,998,0,140,136,1000,999,0,136,132,1001,1000,0,132,128,1002,1001,0,128,124,1003,1002,0,124,120,1004,1003,0,120,116,1005,1004,0,116,112,1006,1005,0,112,108,1007,1006,0,108,104,1008,1007,0,104,100,1009,1008,0,100,96,1010,1009,0,96,92,1011,1010,0,92,88,1012,1011,0,88,84,1013,1012,0,84,80,1014,1013,0,80,76,1015,1014,0,76,72,1016,1015,0,72,68,1017,1016,0,68,64,1018,1017,0,64,60,1019,1018,0,60,56,1020,1019,0,56,52,1021,1020,0,52,48,1022,1021,0,48,44,1023,1022,0,44,40,1024,1023,0,40,36,1025,1024,0,36,32,1026,1025,0,32,28,1027,1026,0,28,24,1028,1027,0,24,20,1029,1028,0,20,16,1030,1029,0,16,12,1031,1030,0,12,8,1032,1031,0,8,4,465,1032,0,955,977,1033,958,0,977,978,1034,1033,0,978,979,1035,1034,0,979,980,1036,1035,0,980,981,1037,1036,0,981,982,1038,1037,0,982,983,1039,1038,0,983,984,1040,1039,0,984,985,1041,1040,0,985,986,1042,1041,0,986,987,1043,1042,0,987,988,1044,1043,0,988,989,1045,1044,0,989,990,1046,1045,0,990,991,1047,1046,0,991,992,1048,1047,0,992,993,1049,1048,0,993,994,1050,1049,0,994,995,1051,1050,0,995,996,1052,1051,0,996,997,1053,1052,0,997,998,1054,1053,0,998,999,1055,1054,0,999,1000,1056,1055,0,1000,1001,1057,1056,0,1001,1002,1058,1057,0,1002,1003,1059,1058,0,1003,1004,1060,1059,0,1004,1005,1061,1060,0,1005,1006,1062,1061,0,1006,1007,1063,1062,0,1007,1008,1064,1063,0,1008,1009,1065,1064,0,1009,1010,1066,1065,0,1010,1011,1067,1066,0,1011,1012,1068,1067,0,1012,1013,1069,1068,0,1013,1014,1070,1069,0,1014,1015,1071,1070,0,1015,1016,1072,1071,0,1016,1017,1073,1072,0,1017,1018,1074,1073,0,1018,1019,1075,1074,0,1019,1020,1076,1075,0,1020,1021,1077,1076,0,1021,1022,1078,1077,0,1022,1023,1079,1078,0,1023,1024,1080,1079,0,1024,1025,1081,1080,0,1025,1026,1082,1081,0,1026,1027,1083,1082,0,1027,1028,1084,1083,0,1028,1029,1085,1084,0,1029,1030,1086,1085,0,1030,1031,1087,1086,0,1031,1032,1088,1087,0,1032,465,469,1088,0,958,1033,1089,961,0,1033,1034,1090,1089,0,1034,1035,1091,1090,0,1035,1036,1092,1091,0,1036,1037,1093,1092,0,1037,1038,1094,1093,0,1038,1039,1095,1094,0,1039,1040,1096,1095,0,1040,1041,1097,1096,0,1041,1042,1098,1097,0,1042,1043,1099,1098,0,1043,1044,1100,1099,0,1044,1045,1101,1100,0,1045,1046,1102,1101,0,1046,1047,1103,1102,0,1047,1048,1104,1103,0,1048,1049,1105,1104,0,1049,1050,1106,1105,0,1050,1051,1107,1106,0,1051,1052,1108,1107,0,1052,1053,1109,1108,0,1053,1054,1110,1109,0,1054,1055,1111,1110,0,1055,1056,1112,1111,0,1056,1057,1113,1112,0,1057,1058,1114,1113,0,1058,1059,1115,1114,0,1059,1060,1116,1115,0,1060,1061,1117,1116,0,1061,1062,1118,1117,0,1062,1063,1119,1118,0,1063,1064,1120,1119,0,1064,1065,1121,1120,0,1065,1066,1122,1121,0,1066,1067,1123,1122,0,1067,1068,1124,1123,0,1068,1069,1125,1124,0,1069,1070,1126,1125,0,1070,1071,1127,1126,0,1071,1072,1128,1127,0,1072,1073,1129,1128,0,1073,1074,1130,1129,0,1074,1075,1131,1130,0,1075,1076,1132,1131,0,1076,1077,1133,1132,0,1077,1078,1134,1133,0,1078,1079,1135,1134,0,1079,1080,1136,1135,0,1080,1081,1137,1136,0,1081,1082,1138,1137,0,1082,1083,1139,1138,0,1083,1084,1140,1139,0,1084,1085,1141,1140,0,1085,1086,1142,1141,0,1086,1087,1143,1142,0,1087,1088,1144,1143,0,1088,469,473,1144,0,961,1089,1145,964,0,1089,1090,1146,1145,0,1090,1091,1147,1146,0,1091,1092,1148,1147,0,1092,1093,1149,1148,0,1093,1094,1150,1149,0,1094,1095,1151,1150,0,1095,1096,1152,1151,0,1096,1097,1153,1152,0,1097,1098,1154,1153,0,1098,1099,1155,1154,0,1099,1100,1156,1155,0,1100,1101,1157,1156,0,1101,1102,1158,1157,0,1102,1103,1159,1158,0,1103,1104,1160,1159,0,1104,1105,1161,1160,0,1105,1106,1162,1161,0,1106,1107,1163,1162,0,1107,1108,1164,1163,0,1108,1109,1165,1164,0,1109,1110,1166,1165,0,1110,1111,1167,1166,0,1111,1112,1168,1167,0,1112,1113,1169,1168,0,1113,1114,1170,1169,0,1114,1115,1171,1170,0,1115,1116,1172,1171,0,1116,1117,1173,1172,0,1117,1118,1174,1173,0,1118,1119,1175,1174,0,1119,1120,1176,1175,0,1120,1121,1177,1176,0,1121,1122,1178,1177,0,1122,1123,1179,1178,0,1123,1124,1180,1179,0,1124,1125,1181,1180,0,1125,1126,1182,1181,0,1126,1127,1183,1182,0,1127,1128,1184,1183,0,1128,1129,1185,1184,0,1129,1130,1186,1185,0,1130,1131,1187,1186,0,1131,1132,1188,1187,0,1132,1133,1189,1188,0,1133,1134,1190,1189,0,1134,1135,1191,1190,0,1135,1136,1192,1191,0,1136,1137,1193,1192,0,1137,1138,1194,1193,0,1138,1139,1195,1194,0,1139,1140,1196,1195,0,1140,1141,1197,1196,0,1141,1142,1198,1197,0,1142,1143,1199,1198,0,1143,1144,1200,1199,0,1144,473,477,1200,0,964,1145,1201,967,0,1145,1146,1202,1201,0,1146,1147,1203,1202,0,1147,1148,1204,1203,0,1148,1149,1205,1204,0,1149,1150,1206,1205,0,1150,1151,1207,1206,0,1151,1152,1208,1207,0,1152,1153,1209,1208,0,1153,1154,1210,1209,0,1154,1155,1211,1210,0,1155,1156,1212,1211,0,1156,1157,1213,1212,0,1157,1158,1214,1213,0,1158,1159,1215,1214,0,1159,1160,1216,1215,0,1160,1161,1217,1216,0,1161,1162,1218,1217,0,1162,1163,1219,1218,0,1163,1164,1220,1219,0,1164,1165,1221,1220,0,1165,1166,1222,1221,0,1166,1167,1223,1222,0,1167,1168,1224,1223,0,1168,1169,1225,1224,0,1169,1170,1226,1225,0,1170,1171,1227,1226,0,1171,1172,1228,1227,0,1172,1173,1229,1228,0,1173,1174,1230,1229,0,1174,1175,1231,1230,0,1175,1176,1232,1231,0,1176,1177,1233,1232,0,1177,1178,1234,1233,0,1178,1179,1235,1234,0,1179,1180,1236,1235,0,1180,1181,1237,1236,0,1181,1182,1238,1237,0,1182,1183,1239,1238,0,1183,1184,1240,1239,0,1184,1185,1241,1240,0,1185,1186,1242,1241,0,1186,1187,1243,1242,0,1187,1188,1244,1243,0,1188,1189,1245,1244,0,1189,1190,1246,1245,0,1190,1191,1247,1246,0,1191,1192,1248,1247,0,1192,1193,1249,1248,0,1193,1194,1250,1249,0,1194,1195,1251,1250,0,1195,1196,1252,1251,0,1196,1197,1253,1252,0,1197,1198,1254,1253,0,1198,1199,1255,1254,0,1199,1200,1256,1255,0,1200,477,481,1256,0,967,1201,1257,970,0,1201,1202,1258,1257,0,1202,1203,1259,1258,0,1203,1204,1260,1259,0,1204,1205,1261,1260,0,1205,1206,1262,1261,0,1206,1207,1263,1262,0,1207,1208,1264,1263,0,1208,1209,1265,1264,0,1209,1210,1266,1265,0,1210,1211,1267,1266,0,1211,1212,1268,1267,0,1212,1213,1269,1268,0,1213,1214,1270,1269,0,1214,1215,1271,1270,0,1215,1216,1272,1271,0,1216,1217,1273,1272,0,1217,1218,1274,1273,0,1218,1219,1275,1274,0,1219,1220,1276,1275,0,1220,1221,1277,1276,0,1221,1222,1278,1277,0,1222,1223,1279,1278,0,1223,1224,1280,1279,0,1224,1225,1281,1280,0,1225,1226,1282,1281,0,1226,1227,1283,1282,0,1227,1228,1284,1283,0,1228,1229,1285,1284,0,1229,1230,1286,1285,0,1230,1231,1287,1286,0,1231,1232,1288,1287,0,1232,1233,1289,1288,0,1233,1234,1290,1289,0,1234,1235,1291,1290,0,1235,1236,1292,1291,0,1236,1237,1293,1292,0,1237,1238,1294,1293,0,1238,1239,1295,1294,0,1239,1240,1296,1295,0,1240,1241,1297,1296,0,1241,1242,1298,1297,0,1242,1243,1299,1298,0,1243,1244,1300,1299,0,1244,1245,1301,1300,0,1245,1246,1302,1301,0,1246,1247,1303,1302,0,1247,1248,1304,1303,0,1248,1249,1305,1304,0,1249,1250,1306,1305,0,1250,1251,1307,1306,0,1251,1252,1308,1307,0,1252,1253,1309,1308,0,1253,1254,1310,1309,0,1254,1255,1311,1310,0,1255,1256,1312,1311,0,1256,481,485,1312,0,970,1257,1313,973,0,1257,1258,1314,1313,0,1258,1259,1315,1314,0,1259,1260,1316,1315,0,1260,1261,1317,1316,0,1261,1262,1318,1317,0,1262,1263,1319,1318,0,1263,1264,1320,1319,0,1264,1265,1321,1320,0,1265,1266,1322,1321,0,1266,1267,1323,1322,0,1267,1268,1324,1323,0,1268,1269,1325,1324,0,1269,1270,1326,1325,0,1270,1271,1327,1326,0,1271,1272,1328,1327,0,1272,1273,1329,1328,0,1273,1274,1330,1329,0,1274,1275,1331,1330,0,1275,1276,1332,1331,0,1276,1277,1333,1332,0,1277,1278,1334,1333,0,1278,1279,1335,1334,0,1279,1280,1336,1335,0,1280,1281,1337,1336,0,1281,1282,1338,1337,0,1282,1283,1339,1338,0,1283,1284,1340,1339,0,1284,1285,1341,1340,0,1285,1286,1342,1341,0,1286,1287,1343,1342,0,1287,1288,1344,1343,0,1288,1289,1345,1344,0,1289,1290,1346,1345,0,1290,1291,1347,1346,0,1291,1292,1348,1347,0,1292,1293,1349,1348,0,1293,1294,1350,1349,0,1294,1295,1351,1350,0,1295,1296,1352,1351,0,1296,1297,1353,1352,0,1297,1298,1354,1353,0,1298,1299,1355,1354,0,1299,1300,1356,1355,0,1300,1301,1357,1356,0,1301,1302,1358,1357,0,1302,1303,1359,1358,0,1303,1304,1360,1359,0,1304,1305,1361,1360,0,1305,1306,1362,1361,0,1306,1307,1363,1362,0,1307,1308,1364,1363,0,1308,1309,1365,1364,0,1309,1310,1366,1365,0,1310,1311,1367,1366,0,1311,1312,1368,1367,0,1312,485,489,1368,0,973,1313,1369,976,0,1313,1314,1370,1369,0,1314,1315,1371,1370,0,1315,1316,1372,1371,0,1316,1317,1373,1372,0,1317,1318,1374,1373,0,1318,1319,1375,1374,0,1319,1320,1376,1375,0,1320,1321,1377,1376,0,1321,1322,1378,1377,0,1322,1323,1379,1378,0,1323,1324,1380,1379,0,1324,1325,1381,1380,0,1325,1326,1382,1381,0,1326,1327,1383,1382,0,1327,1328,1384,1383,0,1328,1329,1385,1384,0,1329,1330,1386,1385,0,1330,1331,1387,1386,0,1331,1332,1388,1387,0,1332,1333,1389,1388,0,1333,1334,1390,1389,0,1334,1335,1391,1390,0,1335,1336,1392,1391,0,1336,1337,1393,1392,0,1337,1338,1394,1393,0,1338,1339,1395,1394,0,1339,1340,1396,1395,0,1340,1341,1397,1396,0,1341,1342,1398,1397,0,1342,1343,1399,1398,0,1343,1344,1400,1399,0,1344,1345,1401,1400,0,1345,1346,1402,1401,0,1346,1347,1403,1402,0,1347,1348,1404,1403,0,1348,1349,1405,1404,0,1349,1350,1406,1405,0,1350,1351,1407,1406,0,1351,1352,1408,1407,0,1352,1353,1409,1408,0,1353,1354,1410,1409,0,1354,1355,1411,1410,0,1355,1356,1412,1411,0,1356,1357,1413,1412,0,1357,1358,1414,1413,0,1358,1359,1415,1414,0,1359,1360,1416,1415,0,1360,1361,1417,1416,0,1361,1362,1418,1417,0,1362,1363,1419,1418,0,1363,1364,1420,1419,0,1364,1365,1421,1420,0,1365,1366,1422,1421,0,1366,1367,1423,1422,0,1367,1368,1424,1423,0,1368,489,493,1424,0,976,1369,457,461,0,1369,1370,453,457,0,1370,1371,449,453,0,1371,1372,445,449,0,1372,1373,441,445,0,1373,1374,437,441,0,1374,1375,433,437,0,1375,1376,429,433,0,1376,1377,425,429,0,1377,1378,421,425,0,1378,1379,417,421,0,1379,1380,413,417,0,1380,1381,409,413,0,1381,1382,405,409,0,1382,1383,401,405,0,1383,1384,397,401,0,1384,1385,393,397,0,1385,1386,389,393,0,1386,1387,385,389,0,1387,1388,381,385,0,1388,1389,377,381,0,1389,1390,373,377,0,1390,1391,369,373,0,1391,1392,365,369,0,1392,1393,361,365,0,1393,1394,357,361,0,1394,1395,353,357,0,1395,1396,349,353,0,1396,1397,345,349,0,1397,1398,341,345,0,1398,1399,337,341,0,1399,1400,333,337,0,1400,1401,329,333,0,1401,1402,325,329,0,1402,1403,321,325,0,1403,1404,317,321,0,1404,1405,313,317,0,1405,1406,309,313,0,1406,1407,305,309,0,1407,1408,301,305,0,1408,1409,297,301,0,1409,1410,293,297,0,1410,1411,289,293,0,1411,1412,285,289,0,1412,1413,281,285,0,1413,1414,277,281,0,1414,1415,273,277,0,1415,1416,269,273,0,1416,1417,265,269,0,1417,1418,261,265,0,1418,1419,257,261,0,1419,1420,253,257,0,1420,1421,249,253,0,1421,1422,245,249,0,1422,1423,241,245,0,1423,1424,237,241,0,1424,493,233,237,0]},"point":[[2.9616995425820702,0.0,0.45720],[2.9616995425820707,0.050799999999999991,0.45720],[2.9616995425820711,0.10159999999999998,0.45720],[2.9616995425820716,0.15239999999999998,0.45720],[2.9113441120104548,0.0,0.45720],[2.9113441120104553,0.050799999999999991,0.45720],[2.9113441120104562,0.10159999999999998,0.45720],[2.9113441120104562,0.15239999999999998,0.45720],[2.8609886814388399,0.0,0.45720],[2.8609886814388399,0.050799999999999991,0.45720],[2.8609886814388408,0.10159999999999998,0.45720],[2.8609886814388412,0.15239999999999998,0.45720],[2.8106332508672240,0.0,0.45720],[2.8106332508672245,0.050799999999999991,0.45720],[2.8106332508672254,0.10159999999999998,0.45720],[2.8106332508672254,0.15239999999999998,0.45720],[2.7602778202956091,0.0,0.45720],[2.7602778202956091,0.050799999999999991,0.45720],[2.760277820295610,0.10159999999999998,0.45720],[2.7602778202956104,0.15239999999999998,0.45720],[2.7099223897239937,0.0,0.45720],[2.7099223897239941,0.050799999999999991,0.45720],[2.7099223897239946,0.10159999999999998,0.45720],[2.7099223897239950,0.15239999999999998,0.45720],[2.6595669591523783,0.0,0.45720],[2.6595669591523787,0.050799999999999991,0.45720],[2.6595669591523796,0.10159999999999998,0.45720],[2.6595669591523801,0.15239999999999998,0.45720],[2.6092115285807633,0.0,0.45720],[2.6092115285807633,0.050799999999999991,0.45720],[2.6092115285807638,0.10159999999999998,0.45720],[2.6092115285807647,0.15239999999999998,0.45720],[2.5588560980091475,0.0,0.45720],[2.5588560980091479,0.050799999999999991,0.45720],[2.5588560980091488,0.10159999999999998,0.45720],[2.5588560980091493,0.15239999999999998,0.45720],[2.5085006674375325,0.0,0.45720],[2.5085006674375330,0.050799999999999991,0.45720],[2.5085006674375334,0.10159999999999998,0.45720],[2.5085006674375339,0.15239999999999998,0.45720],[2.4581452368659171,0.0,0.45720],[2.4581452368659176,0.050799999999999991,0.45720],[2.4581452368659185,0.10159999999999998,0.45720],[2.4581452368659185,0.15239999999999998,0.45720],[2.4077898062943017,0.0,0.45720],[2.4077898062943022,0.050799999999999991,0.45720],[2.4077898062943031,0.10159999999999998,0.45720],[2.4077898062943031,0.15239999999999998,0.45720],[2.3574343757226863,0.0,0.45720],[2.3574343757226868,0.050799999999999991,0.45720],[2.3574343757226877,0.10159999999999998,0.45720],[2.3574343757226877,0.15239999999999998,0.45720],[2.3070789451510714,0.0,0.45720],[2.3070789451510714,0.050799999999999991,0.45720],[2.3070789451510723,0.10159999999999998,0.45720],[2.3070789451510727,0.15239999999999998,0.45720],[2.2567235145794560,0.0,0.45720],[2.2567235145794564,0.050799999999999991,0.45720],[2.2567235145794569,0.10159999999999998,0.45720],[2.2567235145794573,0.15239999999999998,0.45720],[2.2063680840078406,0.0,0.45720],[2.2063680840078410,0.050799999999999991,0.45720],[2.2063680840078419,0.10159999999999998,0.45720],[2.2063680840078423,0.15239999999999998,0.45720],[2.1560126534362252,0.0,0.45720],[2.1560126534362261,0.050799999999999991,0.45720],[2.1560126534362265,0.10159999999999998,0.45720],[2.1560126534362265,0.15239999999999998,0.45720],[2.1056572228646102,0.0,0.45720],[2.1056572228646102,0.050799999999999991,0.45720],[2.1056572228646111,0.10159999999999998,0.45720],[2.1056572228646120,0.15239999999999998,0.45720],[2.0553017922929948,0.0,0.45720],[2.0553017922929953,0.050799999999999991,0.45720],[2.0553017922929957,0.10159999999999998,0.45720],[2.0553017922929961,0.15239999999999998,0.45720],[2.0049463617213794,0.0,0.45720],[2.0049463617213799,0.050799999999999991,0.45720],[2.0049463617213807,0.10159999999999998,0.45720],[2.0049463617213812,0.15239999999999998,0.45720],[1.9545909311497642,0.0,0.45720],[1.9545909311497642,0.050799999999999991,0.45720],[1.9545909311497651,0.10159999999999998,0.45720],[1.9545909311497658,0.15239999999999998,0.45720],[1.9042355005781488,0.0,0.45720],[1.9042355005781495,0.050799999999999991,0.45720],[1.9042355005781502,0.10159999999999998,0.45720],[1.9042355005781502,0.15239999999999998,0.45720],[1.8538800700065334,0.0,0.45720],[1.8538800700065339,0.050799999999999991,0.45720],[1.8538800700065345,0.10159999999999998,0.45720],[1.8538800700065350,0.15239999999999998,0.45720],[1.8035246394349183,0.0,0.45720],[1.8035246394349187,0.050799999999999991,0.45720],[1.8035246394349194,0.10159999999999998,0.45720],[1.8035246394349198,0.15239999999999998,0.45720],[1.7531692088633026,0.0,0.45720],[1.7531692088633035,0.050799999999999991,0.45720],[1.7531692088633042,0.10159999999999998,0.45720],[1.7531692088633042,0.15239999999999998,0.45720],[1.7028137782916879,0.0,0.45720],[1.7028137782916879,0.050799999999999991,0.45720],[1.7028137782916886,0.10159999999999998,0.45720],[1.7028137782916892,0.15239999999999998,0.45720],[1.6524583477200723,0.0,0.45720],[1.6524583477200729,0.050799999999999991,0.45720],[1.6524583477200738,0.10159999999999998,0.45720],[1.6524583477200738,0.15239999999999998,0.45720],[1.6021029171484571,0.0,0.45720],[1.6021029171484573,0.050799999999999991,0.45720],[1.6021029171484582,0.10159999999999998,0.45720],[1.6021029171484584,0.15239999999999998,0.45720],[1.5517474865768419,0.0,0.45720],[1.5517474865768421,0.050799999999999991,0.45720],[1.5517474865768430,0.10159999999999998,0.45720],[1.5517474865768432,0.15239999999999998,0.45720],[1.5013920560052263,0.0,0.45720],[1.5013920560052265,0.050799999999999991,0.45720],[1.5013920560052274,0.10159999999999998,0.45720],[1.5013920560052276,0.15239999999999998,0.45720],[1.4510366254336111,0.0,0.45720],[1.4510366254336116,0.050799999999999991,0.45720],[1.4510366254336122,0.10159999999999998,0.45720],[1.4510366254336127,0.15239999999999998,0.45720],[1.4006811948619959,0.0,0.45720],[1.4006811948619964,0.050799999999999991,0.45720],[1.4006811948619970,0.10159999999999998,0.45720],[1.4006811948619975,0.15239999999999998,0.45720],[1.3503257642903805,0.0,0.45720],[1.3503257642903810,0.050799999999999991,0.45720],[1.3503257642903816,0.10159999999999998,0.45720],[1.3503257642903821,0.15239999999999998,0.45720],[1.2999703337187649,0.0,0.45720],[1.2999703337187654,0.050799999999999991,0.45720],[1.2999703337187660,0.10159999999999998,0.45720],[1.2999703337187665,0.15239999999999998,0.45720],[1.2496149031471502,0.0,0.45720],[1.2496149031471506,0.050799999999999991,0.45720],[1.2496149031471513,0.10159999999999998,0.45720],[1.2496149031471515,0.15239999999999998,0.45720],[1.1992594725755350,0.0,0.45720],[1.1992594725755352,0.050799999999999991,0.45720],[1.1992594725755361,0.10159999999999998,0.45720],[1.1992594725755363,0.15239999999999998,0.45720],[1.1489040420039194,0.0,0.45720],[1.1489040420039198,0.050799999999999991,0.45720],[1.1489040420039205,0.10159999999999998,0.45720],[1.1489040420039209,0.15239999999999998,0.45720],[1.0985486114323038,0.0,0.45720],[1.0985486114323042,0.050799999999999991,0.45720],[1.0985486114323049,0.10159999999999998,0.45720],[1.0985486114323053,0.15239999999999998,0.45720],[1.0481931808606890,0.0,0.45720],[1.0481931808606892,0.050799999999999991,0.45720],[1.0481931808606901,0.10159999999999998,0.45720],[1.0481931808606904,0.15239999999999998,0.45720],[0.99783775028907373,0.0,0.45720],[0.99783775028907407,0.050799999999999991,0.45720],[0.99783775028907484,0.10159999999999998,0.45720],[0.99783775028907518,0.15239999999999998,0.45720],[0.94748231971745811,0.0,0.45720],[0.94748231971745844,0.050799999999999991,0.45720],[0.94748231971745922,0.10159999999999998,0.45720],[0.94748231971745955,0.15239999999999998,0.45720],[0.89712688914584293,0.0,0.45720],[0.89712688914584326,0.050799999999999991,0.45720],[0.89712688914584404,0.10159999999999998,0.45720],[0.89712688914584438,0.15239999999999998,0.45720],[0.84677145857422764,0.0,0.45720],[0.84677145857422809,0.050799999999999991,0.45720],[0.84677145857422875,0.10159999999999998,0.45720],[0.84677145857422920,0.15239999999999998,0.45720],[0.79641602800261246,0.0,0.45720],[0.79641602800261280,0.050799999999999991,0.45720],[0.79641602800261357,0.10159999999999998,0.45720],[0.79641602800261391,0.15239999999999998,0.45720],[0.74606059743099684,0.0,0.45720],[0.74606059743099729,0.050799999999999991,0.45720],[0.74606059743099795,0.10159999999999998,0.45720],[0.74606059743099840,0.15239999999999998,0.45720],[0.69570516685938166,0.0,0.45720],[0.6957051668593820,0.050799999999999991,0.45720],[0.69570516685938277,0.10159999999999998,0.45720],[0.69570516685938311,0.15239999999999998,0.45720],[0.64534973628776648,0.0,0.45720],[0.64534973628776682,0.050799999999999991,0.45720],[0.64534973628776759,0.10159999999999998,0.45720],[0.64534973628776793,0.15239999999999998,0.45720],[0.59499430571615120,0.0,0.45720],[0.59499430571615164,0.050799999999999991,0.45720],[0.59499430571615231,0.10159999999999998,0.45720],[0.59499430571615275,0.15239999999999998,0.45720],[0.54463887514453568,0.0,0.45720],[0.54463887514453602,0.050799999999999991,0.45720],[0.54463887514453679,0.10159999999999998,0.45720],[0.54463887514453713,0.15239999999999998,0.45720],[0.49428344457292045,0.0,0.45720],[0.49428344457292078,0.050799999999999991,0.45720],[0.49428344457292150,0.10159999999999998,0.45720],[0.49428344457292189,0.15239999999999998,0.45720],[0.44392801400130522,0.0,0.45720],[0.44392801400130560,0.050799999999999991,0.45720],[0.44392801400130633,0.10159999999999998,0.45720],[0.44392801400130666,0.15239999999999998,0.45720],[0.39357258342968998,0.0,0.45720],[0.39357258342969037,0.050799999999999991,0.45720],[0.39357258342969109,0.10159999999999998,0.45720],[0.39357258342969148,0.15239999999999998,0.45720],[0.34321715285807480,0.0,0.45720],[0.34321715285807514,0.050799999999999991,0.45720],[0.34321715285807586,0.10159999999999998,0.45720],[0.34321715285807625,0.15239999999999998,0.45720],[0.29286172228645918,0.0,0.45720],[0.29286172228645957,0.050799999999999991,0.45720],[0.29286172228646029,0.10159999999999998,0.45720],[0.29286172228646068,0.15239999999999998,0.45720],[0.24250629171484397,0.0,0.45720],[0.24250629171484434,0.050799999999999991,0.45720],[0.24250629171484508,0.10159999999999998,0.45720],[0.24250629171484545,0.15239999999999998,0.45720],[0.19215086114322877,0.0,0.45720],[0.19215086114322913,0.050799999999999991,0.45720],[0.19215086114322985,0.10159999999999998,0.45720],[0.19215086114323021,0.15239999999999998,0.45720],[0.14179543057161356,0.0,0.45720],[0.14179543057161392,0.050799999999999991,0.45720],[0.14179543057161464,0.10159999999999998,0.45720],[0.14179543057161501,0.15239999999999998,0.45720],[0.091439999999997967,0.0,0.45720],[0.091439999999998328,0.050799999999999991,0.45720],[0.091439999999999064,0.10159999999999998,0.45720],[0.091439999999999425,0.15239999999999998,0.45720],[2.9616995425820716,0.15239999999999998,0.0],[2.9616995425820711,0.10160,0.0],[2.9616995425820707,0.050800000000000005,0.0],[2.9616995425820702,0.0,0.0],[2.9113441120104562,0.15239999999999998,0.0],[2.9113441120104562,0.10160,0.0],[2.9113441120104553,0.050800000000000005,0.0],[2.9113441120104548,0.0,0.0],[2.8609886814388412,0.15239999999999998,0.0],[2.8609886814388408,0.10160,0.0],[2.8609886814388399,0.050800000000000005,0.0],[2.8609886814388399,0.0,0.0],[2.8106332508672254,0.15239999999999998,0.0],[2.8106332508672254,0.10160,0.0],[2.8106332508672245,0.050800000000000005,0.0],[2.8106332508672240,0.0,0.0],[2.7602778202956104,0.15239999999999998,0.0],[2.760277820295610,0.10160,0.0],[2.7602778202956091,0.050800000000000005,0.0],[2.7602778202956091,0.0,0.0],[2.7099223897239950,0.15239999999999998,0.0],[2.7099223897239946,0.10160,0.0],[2.7099223897239941,0.050800000000000005,0.0],[2.7099223897239937,0.0,0.0],[2.6595669591523801,0.15239999999999998,0.0],[2.6595669591523796,0.10160,0.0],[2.6595669591523787,0.050800000000000005,0.0],[2.6595669591523783,0.0,0.0],[2.6092115285807647,0.15239999999999998,0.0],[2.6092115285807638,0.10160,0.0],[2.6092115285807633,0.050800000000000005,0.0],[2.6092115285807633,0.0,0.0],[2.5588560980091493,0.15239999999999998,0.0],[2.5588560980091488,0.10160,0.0],[2.5588560980091479,0.050800000000000005,0.0],[2.5588560980091475,0.0,0.0],[2.5085006674375339,0.15239999999999998,0.0],[2.5085006674375334,0.10160,0.0],[2.5085006674375330,0.050800000000000005,0.0],[2.5085006674375325,0.0,0.0],[2.4581452368659185,0.15239999999999998,0.0],[2.4581452368659185,0.10160,0.0],[2.4581452368659176,0.050800000000000005,0.0],[2.4581452368659171,0.0,0.0],[2.4077898062943031,0.15239999999999998,0.0],[2.4077898062943031,0.10160,0.0],[2.4077898062943022,0.050800000000000005,0.0],[2.4077898062943017,0.0,0.0],[2.3574343757226877,0.15239999999999998,0.0],[2.3574343757226877,0.10160,0.0],[2.3574343757226868,0.050800000000000005,0.0],[2.3574343757226863,0.0,0.0],[2.3070789451510727,0.15239999999999998,0.0],[2.3070789451510723,0.10160,0.0],[2.3070789451510714,0.050800000000000005,0.0],[2.3070789451510714,0.0,0.0],[2.2567235145794573,0.15239999999999998,0.0],[2.2567235145794569,0.10160,0.0],[2.2567235145794564,0.050800000000000005,0.0],[2.2567235145794560,0.0,0.0],[2.2063680840078423,0.15239999999999998,0.0],[2.2063680840078419,0.10160,0.0],[2.2063680840078410,0.050800000000000005,0.0],[2.2063680840078406,0.0,0.0],[2.1560126534362265,0.15239999999999998,0.0],[2.1560126534362265,0.10160,0.0],[2.1560126534362261,0.050800000000000005,0.0],[2.1560126534362252,0.0,0.0],[2.1056572228646120,0.15239999999999998,0.0],[2.1056572228646111,0.10160,0.0],[2.1056572228646102,0.050800000000000005,0.0],[2.1056572228646102,0.0,0.0],[2.0553017922929961,0.15239999999999998,0.0],[2.0553017922929957,0.10160,0.0],[2.0553017922929953,0.050800000000000005,0.0],[2.0553017922929948,0.0,0.0],[2.0049463617213812,0.15239999999999998,0.0],[2.0049463617213807,0.10160,0.0],[2.0049463617213799,0.050800000000000005,0.0],[2.0049463617213794,0.0,0.0],[1.9545909311497658,0.15239999999999998,0.0],[1.9545909311497651,0.10160,0.0],[1.9545909311497642,0.050800000000000005,0.0],[1.9545909311497642,0.0,0.0],[1.9042355005781502,0.15239999999999998,0.0],[1.9042355005781502,0.10160,0.0],[1.9042355005781495,0.050800000000000005,0.0],[1.9042355005781488,0.0,0.0],[1.8538800700065350,0.15239999999999998,0.0],[1.8538800700065345,0.10160,0.0],[1.8538800700065339,0.050800000000000005,0.0],[1.8538800700065334,0.0,0.0],[1.8035246394349198,0.15239999999999998,0.0],[1.8035246394349194,0.10160,0.0],[1.8035246394349187,0.050800000000000005,0.0],[1.8035246394349183,0.0,0.0],[1.7531692088633042,0.15239999999999998,0.0],[1.7531692088633042,0.10160,0.0],[1.7531692088633035,0.050800000000000005,0.0],[1.7531692088633026,0.0,0.0],[1.7028137782916892,0.15239999999999998,0.0],[1.7028137782916886,0.10160,0.0],[1.7028137782916879,0.050800000000000005,0.0],[1.7028137782916879,0.0,0.0],[1.6524583477200738,0.15239999999999998,0.0],[1.6524583477200738,0.10160,0.0],[1.6524583477200729,0.050800000000000005,0.0],[1.6524583477200723,0.0,0.0],[1.6021029171484584,0.15239999999999998,0.0],[1.6021029171484582,0.10160,0.0],[1.6021029171484573,0.050800000000000005,0.0],[1.6021029171484571,0.0,0.0],[1.5517474865768432,0.15239999999999998,0.0],[1.5517474865768430,0.10160,0.0],[1.5517474865768421,0.050800000000000005,0.0],[1.5517474865768419,0.0,0.0],[1.5013920560052276,0.15239999999999998,0.0],[1.5013920560052274,0.10160,0.0],[1.5013920560052265,0.050800000000000005,0.0],[1.5013920560052263,0.0,0.0],[1.4510366254336127,0.15239999999999998,0.0],[1.4510366254336122,0.10160,0.0],[1.4510366254336116,0.050800000000000005,0.0],[1.4510366254336111,0.0,0.0],[1.4006811948619975,0.15239999999999998,0.0],[1.4006811948619970,0.10160,0.0],[1.4006811948619964,0.050800000000000005,0.0],[1.4006811948619959,0.0,0.0],[1.3503257642903821,0.15239999999999998,0.0],[1.3503257642903816,0.10160,0.0],[1.3503257642903810,0.050800000000000005,0.0],[1.3503257642903805,0.0,0.0],[1.2999703337187665,0.15239999999999998,0.0],[1.2999703337187660,0.10160,0.0],[1.2999703337187654,0.050800000000000005,0.0],[1.2999703337187649,0.0,0.0],[1.2496149031471515,0.15239999999999998,0.0],[1.2496149031471513,0.10160,0.0],[1.2496149031471506,0.050800000000000005,0.0],[1.2496149031471502,0.0,0.0],[1.1992594725755363,0.15239999999999998,0.0],[1.1992594725755361,0.10160,0.0],[1.1992594725755352,0.050800000000000005,0.0],[1.1992594725755350,0.0,0.0],[1.1489040420039209,0.15239999999999998,0.0],[1.1489040420039205,0.10160,0.0],[1.1489040420039198,0.050800000000000005,0.0],[1.1489040420039194,0.0,0.0],[1.0985486114323053,0.15239999999999998,0.0],[1.0985486114323049,0.10160,0.0],[1.0985486114323042,0.050800000000000005,0.0],[1.0985486114323038,0.0,0.0],[1.0481931808606904,0.15239999999999998,0.0],[1.0481931808606901,0.10160,0.0],[1.0481931808606892,0.050800000000000005,0.0],[1.0481931808606890,0.0,0.0],[0.99783775028907518,0.15239999999999998,0.0],[0.99783775028907484,0.10160,0.0],[0.99783775028907407,0.050800000000000005,0.0],[0.99783775028907373,0.0,0.0],[0.94748231971745955,0.15239999999999998,0.0],[0.94748231971745922,0.10160,0.0],[0.94748231971745844,0.050800000000000005,0.0],[0.94748231971745811,0.0,0.0],[0.89712688914584438,0.15239999999999998,0.0],[0.89712688914584404,0.10160,0.0],[0.89712688914584326,0.050800000000000005,0.0],[0.89712688914584293,0.0,0.0],[0.84677145857422920,0.15239999999999998,0.0],[0.84677145857422875,0.10160,0.0],[0.84677145857422809,0.050800000000000005,0.0],[0.84677145857422764,0.0,0.0],[0.79641602800261391,0.15239999999999998,0.0],[0.79641602800261357,0.10160,0.0],[0.79641602800261280,0.050800000000000005,0.0],[0.79641602800261246,0.0,0.0],[0.74606059743099840,0.15239999999999998,0.0],[0.74606059743099795,0.10160,0.0],[0.74606059743099729,0.050800000000000005,0.0],[0.74606059743099684,0.0,0.0],[0.69570516685938311,0.15239999999999998,0.0],[0.69570516685938277,0.10160,0.0],[0.6957051668593820,0.050800000000000005,0.0],[0.69570516685938166,0.0,0.0],[0.64534973628776793,0.15239999999999998,0.0],[0.64534973628776759,0.10160,0.0],[0.64534973628776682,0.050800000000000005,0.0],[0.64534973628776648,0.0,0.0],[0.59499430571615275,0.15239999999999998,0.0],[0.59499430571615231,0.10160,0.0],[0.59499430571615164,0.050800000000000005,0.0],[0.59499430571615120,0.0,0.0],[0.54463887514453713,0.15239999999999998,0.0],[0.54463887514453679,0.10160,0.0],[0.54463887514453602,0.050800000000000005,0.0],[0.54463887514453568,0.0,0.0],[0.49428344457292189,0.15239999999999998,0.0],[0.49428344457292150,0.10160,0.0],[0.49428344457292078,0.050800000000000005,0.0],[0.49428344457292045,0.0,0.0],[0.44392801400130666,0.15239999999999998,0.0],[0.44392801400130633,0.10160,0.0],[0.44392801400130560,0.050800000000000005,0.0],[0.44392801400130522,0.0,0.0],[0.39357258342969148,0.15239999999999998,0.0],[0.39357258342969109,0.10160,0.0],[0.39357258342969037,0.050800000000000005,0.0],[0.39357258342968998,0.0,0.0],[0.34321715285807625,0.15239999999999998,0.0],[0.34321715285807586,0.10160,0.0],[0.34321715285807514,0.050800000000000005,0.0],[0.34321715285807480,0.0,0.0],[0.29286172228646068,0.15239999999999998,0.0],[0.29286172228646029,0.10160,0.0],[0.29286172228645957,0.050800000000000005,0.0],[0.29286172228645918,0.0,0.0],[0.24250629171484545,0.15239999999999998,0.0],[0.24250629171484508,0.10160,0.0],[0.24250629171484434,0.050800000000000005,0.0],[0.24250629171484397,0.0,0.0],[0.19215086114323021,0.15239999999999998,0.0],[0.19215086114322985,0.10160,0.0],[0.19215086114322913,0.050800000000000005,0.0],[0.19215086114322877,0.0,0.0],[0.14179543057161501,0.15239999999999998,0.0],[0.14179543057161464,0.10160,0.0],[0.14179543057161392,0.050800000000000005,0.0],[0.14179543057161356,0.0,0.0],[0.091439999999999425,0.15239999999999998,0.0],[0.091439999999999064,0.10160,0.0],[0.091439999999998328,0.050800000000000005,0.0],[0.091439999999997967,0.0,0.0],[2.9616995425820716,0.15239999999999998,0.40640000000000004],[2.9616995425820711,0.10160,0.40640000000000004],[2.9616995425820707,0.050800000000000005,0.40640000000000004],[2.9616995425820702,0.0,0.40640000000000004],[2.9616995425820716,0.15239999999999998,0.35560000000000003],[2.9616995425820711,0.10160,0.35560000000000003],[2.9616995425820707,0.050800000000000005,0.35560000000000003],[2.9616995425820702,0.0,0.35560000000000003],[2.9616995425820716,0.15239999999999998,0.30480000000000002],[2.9616995425820711,0.10160,0.30480000000000002],[2.9616995425820707,0.050800000000000005,0.30480000000000002],[2.9616995425820702,0.0,0.30480000000000002],[2.9616995425820716,0.15239999999999998,0.2540],[2.9616995425820711,0.10160,0.2540],[2.9616995425820707,0.050800000000000005,0.2540],[2.9616995425820702,0.0,0.2540],[2.9616995425820716,0.15239999999999998,0.20320000000000002],[2.9616995425820711,0.10160,0.20320000000000002],[2.9616995425820707,0.050800000000000005,0.20320000000000002],[2.9616995425820702,0.0,0.20320000000000002],[2.9616995425820716,0.15239999999999998,0.15240000000000001],[2.9616995425820711,0.10160,0.15240000000000001],[2.9616995425820707,0.050800000000000005,0.15240000000000001],[2.9616995425820702,0.0,0.15240000000000001],[2.9616995425820716,0.15239999999999998,0.10160000000000005],[2.9616995425820711,0.10160,0.10160000000000005],[2.9616995425820707,0.050800000000000005,0.10160000000000005],[2.9616995425820702,0.0,0.10160000000000005],[2.9616995425820716,0.15239999999999998,0.050800000000000005],[2.9616995425820711,0.10160,0.050800000000000005],[2.9616995425820707,0.050800000000000005,0.050800000000000005],[2.9616995425820702,0.0,0.050800000000000005],[2.9113441120104548,0.0,0.40640000000000004],[2.8609886814388399,0.0,0.40640000000000004],[2.8106332508672240,0.0,0.40640000000000004],[2.7602778202956091,0.0,0.40640000000000004],[2.7099223897239937,0.0,0.40640000000000004],[2.6595669591523783,0.0,0.40640000000000004],[2.6092115285807633,0.0,0.40640000000000004],[2.5588560980091475,0.0,0.40640000000000004],[2.5085006674375325,0.0,0.40640000000000004],[2.4581452368659171,0.0,0.40640000000000004],[2.4077898062943017,0.0,0.40640000000000004],[2.3574343757226863,0.0,0.40640000000000004],[2.3070789451510714,0.0,0.40640000000000004],[2.2567235145794560,0.0,0.40640000000000004],[2.2063680840078406,0.0,0.40640000000000004],[2.1560126534362252,0.0,0.40640000000000004],[2.1056572228646102,0.0,0.40640000000000004],[2.0553017922929948,0.0,0.40640000000000004],[2.0049463617213794,0.0,0.40640000000000004],[1.9545909311497642,0.0,0.40640000000000004],[1.9042355005781488,0.0,0.40640000000000004],[1.8538800700065334,0.0,0.40640000000000004],[1.8035246394349183,0.0,0.40640000000000004],[1.7531692088633026,0.0,0.40640000000000004],[1.7028137782916879,0.0,0.40640000000000004],[1.6524583477200723,0.0,0.40640000000000004],[1.6021029171484571,0.0,0.40640000000000004],[1.5517474865768419,0.0,0.40640000000000004],[1.5013920560052263,0.0,0.40640000000000004],[1.4510366254336111,0.0,0.40640000000000004],[1.4006811948619959,0.0,0.40640000000000004],[1.3503257642903805,0.0,0.40640000000000004],[1.2999703337187649,0.0,0.40640000000000004],[1.2496149031471502,0.0,0.40640000000000004],[1.1992594725755350,0.0,0.40640000000000004],[1.1489040420039194,0.0,0.40640000000000004],[1.0985486114323038,0.0,0.40640000000000004],[1.0481931808606890,0.0,0.40640000000000004],[0.99783775028907373,0.0,0.40640000000000004],[0.94748231971745811,0.0,0.40640000000000004],[0.89712688914584293,0.0,0.40640000000000004],[0.84677145857422764,0.0,0.40640000000000004],[0.79641602800261246,0.0,0.40640000000000004],[0.74606059743099684,0.0,0.40640000000000004],[0.69570516685938166,0.0,0.40640000000000004],[0.64534973628776648,0.0,0.40640000000000004],[0.59499430571615120,0.0,0.40640000000000004],[0.54463887514453568,0.0,0.40640000000000004],[0.49428344457292045,0.0,0.40640000000000004],[0.44392801400130522,0.0,0.40640000000000004],[0.39357258342968998,0.0,0.40640000000000004],[0.34321715285807480,0.0,0.40640000000000004],[0.29286172228645918,0.0,0.40640000000000004],[0.24250629171484397,0.0,0.40640000000000004],[0.19215086114322877,0.0,0.40640000000000004],[0.14179543057161356,0.0,0.40640000000000004],[0.091439999999997967,0.0,0.40640000000000004],[2.9113441120104548,0.0,0.35560000000000003],[2.8609886814388399,0.0,0.35560000000000003],[2.8106332508672240,0.0,0.35560000000000003],[2.7602778202956091,0.0,0.35560000000000003],[2.7099223897239937,0.0,0.35560000000000003],[2.6595669591523783,0.0,0.35560000000000003],[2.6092115285807633,0.0,0.35560000000000003],[2.5588560980091475,0.0,0.35560000000000003],[2.5085006674375325,0.0,0.35560000000000003],[2.4581452368659171,0.0,0.35560000000000003],[2.4077898062943017,0.0,0.35560000000000003],[2.3574343757226863,0.0,0.35560000000000003],[2.3070789451510714,0.0,0.35560000000000003],[2.2567235145794560,0.0,0.35560000000000003],[2.2063680840078406,0.0,0.35560000000000003],[2.1560126534362252,0.0,0.35560000000000003],[2.1056572228646102,0.0,0.35560000000000003],[2.0553017922929948,0.0,0.35560000000000003],[2.0049463617213794,0.0,0.35560000000000003],[1.9545909311497642,0.0,0.35560000000000003],[1.9042355005781488,0.0,0.35560000000000003],[1.8538800700065334,0.0,0.35560000000000003],[1.8035246394349183,0.0,0.35560000000000003],[1.7531692088633026,0.0,0.35560000000000003],[1.7028137782916879,0.0,0.35560000000000003],[1.6524583477200723,0.0,0.35560000000000003],[1.6021029171484571,0.0,0.35560000000000003],[1.5517474865768419,0.0,0.35560000000000003],[1.5013920560052263,0.0,0.35560000000000003],[1.4510366254336111,0.0,0.35560000000000003],[1.4006811948619959,0.0,0.35560000000000003],[1.3503257642903805,0.0,0.35560000000000003],[1.2999703337187649,0.0,0.35560000000000003],[1.2496149031471502,0.0,0.35560000000000003],[1.1992594725755350,0.0,0.35560000000000003],[1.1489040420039194,0.0,0.35560000000000003],[1.0985486114323038,0.0,0.35560000000000003],[1.0481931808606890,0.0,0.35560000000000003],[0.99783775028907373,0.0,0.35560000000000003],[0.94748231971745811,0.0,0.35560000000000003],[0.89712688914584293,0.0,0.35560000000000003],[0.84677145857422764,0.0,0.35560000000000003],[0.79641602800261246,0.0,0.35560000000000003],[0.74606059743099684,0.0,0.35560000000000003],[0.69570516685938166,0.0,0.35560000000000003],[0.64534973628776648,0.0,0.35560000000000003],[0.59499430571615120,0.0,0.35560000000000003],[0.54463887514453568,0.0,0.35560000000000003],[0.49428344457292045,0.0,0.35560000000000003],[0.44392801400130522,0.0,0.35560000000000003],[0.39357258342968998,0.0,0.35560000000000003],[0.34321715285807480,0.0,0.35560000000000003],[0.29286172228645918,0.0,0.35560000000000003],[0.24250629171484397,0.0,0.35560000000000003],[0.19215086114322877,0.0,0.35560000000000003],[0.14179543057161356,0.0,0.35560000000000003],[0.091439999999997967,0.0,0.35560000000000003],[2.9113441120104548,0.0,0.30480000000000007],[2.8609886814388399,0.0,0.30480000000000002],[2.8106332508672240,0.0,0.30480000000000002],[2.7602778202956091,0.0,0.30480000000000002],[2.7099223897239937,0.0,0.30480000000000002],[2.6595669591523783,0.0,0.30480000000000002],[2.6092115285807633,0.0,0.30480000000000002],[2.5588560980091475,0.0,0.30480000000000002],[2.5085006674375325,0.0,0.30480000000000002],[2.4581452368659171,0.0,0.30480000000000002],[2.4077898062943017,0.0,0.30480000000000002],[2.3574343757226863,0.0,0.30480000000000002],[2.3070789451510714,0.0,0.30480000000000002],[2.2567235145794560,0.0,0.30480000000000002],[2.2063680840078406,0.0,0.30480000000000002],[2.1560126534362252,0.0,0.30480000000000002],[2.1056572228646102,0.0,0.30480000000000002],[2.0553017922929948,0.0,0.30480000000000002],[2.0049463617213794,0.0,0.30480000000000002],[1.9545909311497642,0.0,0.30480000000000002],[1.9042355005781488,0.0,0.30480000000000002],[1.8538800700065334,0.0,0.30480000000000002],[1.8035246394349183,0.0,0.30480000000000002],[1.7531692088633026,0.0,0.30480000000000002],[1.7028137782916879,0.0,0.30480000000000002],[1.6524583477200723,0.0,0.30480000000000002],[1.6021029171484571,0.0,0.30480000000000002],[1.5517474865768419,0.0,0.30480000000000002],[1.5013920560052263,0.0,0.30480000000000002],[1.4510366254336111,0.0,0.30480000000000002],[1.4006811948619959,0.0,0.30480000000000002],[1.3503257642903805,0.0,0.30480000000000002],[1.2999703337187649,0.0,0.30480000000000002],[1.2496149031471502,0.0,0.30480000000000002],[1.1992594725755350,0.0,0.30480000000000002],[1.1489040420039194,0.0,0.30480000000000002],[1.0985486114323038,0.0,0.30480000000000002],[1.0481931808606890,0.0,0.30480000000000002],[0.99783775028907373,0.0,0.30480000000000002],[0.94748231971745811,0.0,0.30480000000000002],[0.89712688914584293,0.0,0.30480000000000002],[0.84677145857422764,0.0,0.30480000000000002],[0.79641602800261246,0.0,0.30480000000000002],[0.74606059743099684,0.0,0.30480000000000002],[0.69570516685938166,0.0,0.30480000000000002],[0.64534973628776648,0.0,0.30480000000000002],[0.59499430571615120,0.0,0.30480000000000002],[0.54463887514453568,0.0,0.30480000000000002],[0.49428344457292045,0.0,0.30480000000000002],[0.44392801400130522,0.0,0.30480000000000002],[0.39357258342968998,0.0,0.30480000000000002],[0.34321715285807480,0.0,0.30480000000000002],[0.29286172228645918,0.0,0.30480000000000002],[0.24250629171484397,0.0,0.30480000000000002],[0.19215086114322877,0.0,0.30480000000000002],[0.14179543057161356,0.0,0.30480000000000002],[0.091439999999997967,0.0,0.30480000000000002],[2.9113441120104548,0.0,0.25400000000000006],[2.8609886814388399,0.0,0.2540],[2.8106332508672240,0.0,0.2540],[2.7602778202956091,0.0,0.2540],[2.7099223897239937,0.0,0.2540],[2.6595669591523783,0.0,0.2540],[2.6092115285807633,0.0,0.2540],[2.5588560980091475,0.0,0.2540],[2.5085006674375325,0.0,0.2540],[2.4581452368659171,0.0,0.2540],[2.4077898062943017,0.0,0.2540],[2.3574343757226863,0.0,0.2540],[2.3070789451510714,0.0,0.2540],[2.2567235145794560,0.0,0.2540],[2.2063680840078406,0.0,0.2540],[2.1560126534362252,0.0,0.2540],[2.1056572228646102,0.0,0.2540],[2.0553017922929948,0.0,0.2540],[2.0049463617213794,0.0,0.2540],[1.9545909311497642,0.0,0.2540],[1.9042355005781488,0.0,0.2540],[1.8538800700065334,0.0,0.2540],[1.8035246394349183,0.0,0.2540],[1.7531692088633026,0.0,0.2540],[1.7028137782916879,0.0,0.2540],[1.6524583477200723,0.0,0.2540],[1.6021029171484571,0.0,0.2540],[1.5517474865768419,0.0,0.2540],[1.5013920560052263,0.0,0.2540],[1.4510366254336111,0.0,0.2540],[1.4006811948619959,0.0,0.2540],[1.3503257642903805,0.0,0.2540],[1.2999703337187649,0.0,0.2540],[1.2496149031471502,0.0,0.2540],[1.1992594725755350,0.0,0.2540],[1.1489040420039194,0.0,0.2540],[1.0985486114323038,0.0,0.2540],[1.0481931808606890,0.0,0.2540],[0.99783775028907373,0.0,0.2540],[0.94748231971745811,0.0,0.2540],[0.89712688914584293,0.0,0.2540],[0.84677145857422764,0.0,0.2540],[0.79641602800261246,0.0,0.2540],[0.74606059743099684,0.0,0.2540],[0.69570516685938166,0.0,0.2540],[0.64534973628776648,0.0,0.2540],[0.59499430571615120,0.0,0.2540],[0.54463887514453568,0.0,0.2540],[0.49428344457292045,0.0,0.2540],[0.44392801400130522,0.0,0.2540],[0.39357258342968998,0.0,0.2540],[0.34321715285807480,0.0,0.2540],[0.29286172228645918,0.0,0.2540],[0.24250629171484397,0.0,0.2540],[0.19215086114322877,0.0,0.2540],[0.14179543057161356,0.0,0.2540],[0.091439999999997967,0.0,0.2540],[2.9113441120104548,0.0,0.20320000000000005],[2.8609886814388399,0.0,0.20320000000000002],[2.8106332508672240,0.0,0.20320000000000002],[2.7602778202956091,0.0,0.20320000000000002],[2.7099223897239937,0.0,0.20320000000000002],[2.6595669591523783,0.0,0.20320000000000002],[2.6092115285807633,0.0,0.20320000000000002],[2.5588560980091475,0.0,0.20320000000000002],[2.5085006674375325,0.0,0.20320000000000002],[2.4581452368659171,0.0,0.20320000000000002],[2.4077898062943017,0.0,0.20320000000000002],[2.3574343757226863,0.0,0.20320000000000002],[2.3070789451510714,0.0,0.20320000000000002],[2.2567235145794560,0.0,0.20320000000000002],[2.2063680840078406,0.0,0.20320000000000002],[2.1560126534362252,0.0,0.20320000000000002],[2.1056572228646102,0.0,0.20320000000000002],[2.0553017922929948,0.0,0.20320000000000002],[2.0049463617213794,0.0,0.20320000000000002],[1.9545909311497642,0.0,0.20320000000000002],[1.9042355005781488,0.0,0.20320000000000002],[1.8538800700065334,0.0,0.20320000000000002],[1.8035246394349183,0.0,0.20320000000000002],[1.7531692088633026,0.0,0.20320000000000002],[1.7028137782916879,0.0,0.20320000000000002],[1.6524583477200723,0.0,0.20320000000000002],[1.6021029171484571,0.0,0.20320000000000002],[1.5517474865768419,0.0,0.20320000000000002],[1.5013920560052263,0.0,0.20320000000000002],[1.4510366254336111,0.0,0.20320000000000002],[1.4006811948619959,0.0,0.20320000000000002],[1.3503257642903805,0.0,0.20320000000000002],[1.2999703337187649,0.0,0.20320000000000002],[1.2496149031471502,0.0,0.20320000000000002],[1.1992594725755350,0.0,0.20320000000000002],[1.1489040420039194,0.0,0.20320000000000002],[1.0985486114323038,0.0,0.20320000000000002],[1.0481931808606890,0.0,0.20320000000000002],[0.99783775028907373,0.0,0.20320000000000002],[0.94748231971745811,0.0,0.20320000000000002],[0.89712688914584293,0.0,0.20320000000000002],[0.84677145857422764,0.0,0.20320000000000002],[0.79641602800261246,0.0,0.20320000000000002],[0.74606059743099684,0.0,0.20320000000000002],[0.69570516685938166,0.0,0.20320000000000002],[0.64534973628776648,0.0,0.20320000000000002],[0.59499430571615120,0.0,0.20320000000000002],[0.54463887514453568,0.0,0.20320000000000002],[0.49428344457292045,0.0,0.20320000000000002],[0.44392801400130522,0.0,0.20320000000000002],[0.39357258342968998,0.0,0.20320000000000002],[0.34321715285807480,0.0,0.20320000000000002],[0.29286172228645918,0.0,0.20320000000000002],[0.24250629171484397,0.0,0.20320000000000002],[0.19215086114322877,0.0,0.20320000000000002],[0.14179543057161356,0.0,0.20320000000000002],[0.091439999999997967,0.0,0.20320000000000002],[2.9113441120104548,0.0,0.15240000000000009],[2.8609886814388399,0.0,0.15240000000000001],[2.8106332508672240,0.0,0.15240000000000001],[2.7602778202956091,0.0,0.15240000000000001],[2.7099223897239937,0.0,0.15240000000000001],[2.6595669591523783,0.0,0.15240000000000001],[2.6092115285807633,0.0,0.15240000000000001],[2.5588560980091475,0.0,0.15240000000000001],[2.5085006674375325,0.0,0.15240000000000001],[2.4581452368659171,0.0,0.15240000000000001],[2.4077898062943017,0.0,0.15240000000000001],[2.3574343757226863,0.0,0.15240000000000001],[2.3070789451510714,0.0,0.15240000000000001],[2.2567235145794560,0.0,0.15240000000000001],[2.2063680840078406,0.0,0.15240000000000001],[2.1560126534362252,0.0,0.15240000000000001],[2.1056572228646102,0.0,0.15240000000000001],[2.0553017922929948,0.0,0.15240000000000001],[2.0049463617213794,0.0,0.15240000000000001],[1.9545909311497642,0.0,0.15240000000000001],[1.9042355005781488,0.0,0.15240000000000001],[1.8538800700065334,0.0,0.15240000000000001],[1.8035246394349183,0.0,0.15240000000000001],[1.7531692088633026,0.0,0.15240000000000001],[1.7028137782916879,0.0,0.15240000000000001],[1.6524583477200723,0.0,0.15240000000000001],[1.6021029171484571,0.0,0.15240000000000001],[1.5517474865768419,0.0,0.15240000000000001],[1.5013920560052263,0.0,0.15240000000000001],[1.4510366254336111,0.0,0.15240000000000001],[1.4006811948619959,0.0,0.15240000000000001],[1.3503257642903805,0.0,0.15240000000000001],[1.2999703337187649,0.0,0.15240000000000001],[1.2496149031471502,0.0,0.15240000000000001],[1.1992594725755350,0.0,0.15240000000000001],[1.1489040420039194,0.0,0.15240000000000001],[1.0985486114323038,0.0,0.15240000000000001],[1.0481931808606890,0.0,0.15240000000000001],[0.99783775028907373,0.0,0.15240000000000001],[0.94748231971745811,0.0,0.15240000000000001],[0.89712688914584293,0.0,0.15240000000000001],[0.84677145857422764,0.0,0.15240000000000001],[0.79641602800261246,0.0,0.15240000000000001],[0.74606059743099684,0.0,0.15240000000000001],[0.69570516685938166,0.0,0.15240000000000001],[0.64534973628776648,0.0,0.15240000000000001],[0.59499430571615120,0.0,0.15240000000000001],[0.54463887514453568,0.0,0.15240000000000001],[0.49428344457292045,0.0,0.15240000000000001],[0.44392801400130522,0.0,0.15240000000000001],[0.39357258342968998,0.0,0.15240000000000001],[0.34321715285807480,0.0,0.15240000000000001],[0.29286172228645918,0.0,0.15240000000000001],[0.24250629171484397,0.0,0.15240000000000001],[0.19215086114322877,0.0,0.15240000000000001],[0.14179543057161356,0.0,0.15240000000000001],[0.091439999999997967,0.0,0.15240000000000001],[2.9113441120104548,0.0,0.10160000000000013],[2.8609886814388399,0.0,0.10160000000000005],[2.8106332508672240,0.0,0.10160000000000005],[2.7602778202956091,0.0,0.10160000000000005],[2.7099223897239937,0.0,0.10160000000000005],[2.6595669591523783,0.0,0.10160000000000005],[2.6092115285807633,0.0,0.10160000000000005],[2.5588560980091475,0.0,0.10160000000000005],[2.5085006674375325,0.0,0.10160000000000005],[2.4581452368659171,0.0,0.10160000000000005],[2.4077898062943017,0.0,0.10160000000000005],[2.3574343757226863,0.0,0.10160000000000005],[2.3070789451510714,0.0,0.10160000000000005],[2.2567235145794560,0.0,0.10160000000000005],[2.2063680840078406,0.0,0.10160000000000005],[2.1560126534362252,0.0,0.10160000000000005],[2.1056572228646102,0.0,0.10160000000000005],[2.0553017922929948,0.0,0.10160000000000005],[2.0049463617213794,0.0,0.10160000000000005],[1.9545909311497642,0.0,0.10160000000000005],[1.9042355005781488,0.0,0.10160000000000005],[1.8538800700065334,0.0,0.10160000000000005],[1.8035246394349183,0.0,0.10160000000000005],[1.7531692088633026,0.0,0.10160000000000005],[1.7028137782916879,0.0,0.10160000000000005],[1.6524583477200723,0.0,0.10160000000000005],[1.6021029171484571,0.0,0.10160000000000005],[1.5517474865768419,0.0,0.10160000000000005],[1.5013920560052263,0.0,0.10160000000000005],[1.4510366254336111,0.0,0.10160000000000005],[1.4006811948619959,0.0,0.10160000000000005],[1.3503257642903805,0.0,0.10160000000000005],[1.2999703337187649,0.0,0.10160000000000005],[1.2496149031471502,0.0,0.10160000000000005],[1.1992594725755350,0.0,0.10160000000000005],[1.1489040420039194,0.0,0.10160000000000005],[1.0985486114323038,0.0,0.10160000000000005],[1.0481931808606890,0.0,0.10160000000000005],[0.99783775028907373,0.0,0.10160000000000005],[0.94748231971745811,0.0,0.10160000000000005],[0.89712688914584293,0.0,0.10160000000000005],[0.84677145857422764,0.0,0.10160000000000005],[0.79641602800261246,0.0,0.10160000000000005],[0.74606059743099684,0.0,0.10160000000000005],[0.69570516685938166,0.0,0.10160000000000005],[0.64534973628776648,0.0,0.10160000000000005],[0.59499430571615120,0.0,0.10160000000000005],[0.54463887514453568,0.0,0.10160000000000005],[0.49428344457292045,0.0,0.10160000000000005],[0.44392801400130522,0.0,0.10160000000000005],[0.39357258342968998,0.0,0.10160000000000005],[0.34321715285807480,0.0,0.10160000000000005],[0.29286172228645918,0.0,0.10160000000000005],[0.24250629171484397,0.0,0.10160000000000005],[0.19215086114322877,0.0,0.10160000000000005],[0.14179543057161356,0.0,0.10160000000000005],[0.091439999999997967,0.0,0.10160000000000005],[2.9113441120104548,0.0,0.050800000000000095],[2.8609886814388399,0.0,0.050800000000000005],[2.8106332508672240,0.0,0.050800000000000005],[2.7602778202956091,0.0,0.050800000000000005],[2.7099223897239937,0.0,0.050800000000000005],[2.6595669591523783,0.0,0.050800000000000005],[2.6092115285807633,0.0,0.050800000000000005],[2.5588560980091475,0.0,0.050800000000000005],[2.5085006674375325,0.0,0.050800000000000005],[2.4581452368659171,0.0,0.050800000000000005],[2.4077898062943017,0.0,0.050800000000000005],[2.3574343757226863,0.0,0.050800000000000005],[2.3070789451510714,0.0,0.050800000000000005],[2.2567235145794560,0.0,0.050800000000000005],[2.2063680840078406,0.0,0.050800000000000005],[2.1560126534362252,0.0,0.050800000000000005],[2.1056572228646102,0.0,0.050800000000000005],[2.0553017922929948,0.0,0.050800000000000005],[2.0049463617213794,0.0,0.050800000000000005],[1.9545909311497642,0.0,0.050800000000000005],[1.9042355005781488,0.0,0.050800000000000005],[1.8538800700065334,0.0,0.050800000000000005],[1.8035246394349183,0.0,0.050800000000000005],[1.7531692088633026,0.0,0.050800000000000005],[1.7028137782916879,0.0,0.050800000000000005],[1.6524583477200723,0.0,0.050800000000000005],[1.6021029171484571,0.0,0.050800000000000005],[1.5517474865768419,0.0,0.050800000000000005],[1.5013920560052263,0.0,0.050800000000000005],[1.4510366254336111,0.0,0.050800000000000005],[1.4006811948619959,0.0,0.050800000000000005],[1.3503257642903805,0.0,0.050800000000000005],[1.2999703337187649,0.0,0.050800000000000005],[1.2496149031471502,0.0,0.050800000000000005],[1.1992594725755350,0.0,0.050800000000000005],[1.1489040420039194,0.0,0.050800000000000005],[1.0985486114323038,0.0,0.050800000000000005],[1.0481931808606890,0.0,0.050800000000000005],[0.99783775028907373,0.0,0.050800000000000005],[0.94748231971745811,0.0,0.050800000000000005],[0.89712688914584293,0.0,0.050800000000000005],[0.84677145857422764,0.0,0.050800000000000005],[0.79641602800261246,0.0,0.050800000000000005],[0.74606059743099684,0.0,0.050800000000000005],[0.69570516685938166,0.0,0.050800000000000005],[0.64534973628776648,0.0,0.050800000000000005],[0.59499430571615120,0.0,0.050800000000000005],[0.54463887514453568,0.0,0.050800000000000005],[0.49428344457292045,0.0,0.050800000000000005],[0.44392801400130522,0.0,0.050800000000000005],[0.39357258342968998,0.0,0.050800000000000005],[0.34321715285807480,0.0,0.050800000000000005],[0.29286172228645918,0.0,0.050800000000000005],[0.24250629171484397,0.0,0.050800000000000005],[0.19215086114322877,0.0,0.050800000000000005],[0.14179543057161356,0.0,0.050800000000000005],[0.091439999999997967,0.0,0.050800000000000005],[0.091439999999998453,0.050799999999999991,0.40640000000000004],[0.091439999999998939,0.10159999999999998,0.40640000000000004],[0.091439999999999425,0.15239999999999998,0.40640000000000004],[0.091439999999998453,0.050799999999999991,0.35560000000000003],[0.091439999999998939,0.10159999999999998,0.35560000000000003],[0.091439999999999425,0.15239999999999998,0.35560000000000003],[0.091439999999998453,0.050799999999999991,0.30480000000000002],[0.091439999999998939,0.10159999999999998,0.30480000000000002],[0.091439999999999425,0.15239999999999998,0.30480000000000002],[0.091439999999998453,0.050799999999999991,0.2540],[0.091439999999998939,0.10159999999999998,0.2540],[0.091439999999999425,0.15239999999999998,0.2540],[0.091439999999998453,0.050799999999999991,0.20320000000000002],[0.091439999999998939,0.10159999999999998,0.20320000000000002],[0.091439999999999425,0.15239999999999998,0.20320000000000002],[0.091439999999998453,0.050799999999999991,0.15240000000000001],[0.091439999999998939,0.10159999999999998,0.15240000000000001],[0.091439999999999425,0.15239999999999998,0.15240000000000001],[0.091439999999998453,0.050799999999999991,0.10160000000000005],[0.091439999999998939,0.10159999999999998,0.10160000000000005],[0.091439999999999425,0.15239999999999998,0.10160000000000005],[0.091439999999998453,0.050799999999999991,0.050800000000000005],[0.091439999999998939,0.10159999999999998,0.050800000000000005],[0.091439999999999425,0.15239999999999998,0.050800000000000005],[0.14179543057161473,0.15239999999999998,0.40640000000000004],[0.19215086114323002,0.15239999999999998,0.40640000000000004],[0.24250629171484536,0.15239999999999998,0.40640000000000004],[0.29286172228646062,0.15239999999999998,0.40640000000000004],[0.34321715285807591,0.15239999999999998,0.40640000000000004],[0.39357258342969126,0.15239999999999998,0.40640000000000004],[0.44392801400130649,0.15239999999999998,0.40640000000000004],[0.49428344457292178,0.15239999999999998,0.40640000000000004],[0.54463887514453713,0.15239999999999998,0.40640000000000004],[0.59499430571615242,0.15239999999999998,0.40640000000000004],[0.64534973628776771,0.15239999999999998,0.40640000000000004],[0.6957051668593830,0.15239999999999998,0.40640000000000004],[0.74606059743099828,0.15239999999999998,0.40640000000000004],[0.79641602800261357,0.15239999999999998,0.40640000000000004],[0.84677145857422875,0.15239999999999998,0.40640000000000004],[0.89712688914584415,0.15239999999999998,0.40640000000000004],[0.94748231971745944,0.15239999999999998,0.40640000000000004],[0.99783775028907484,0.15239999999999998,0.40640000000000004],[1.0481931808606901,0.15239999999999998,0.40640000000000004],[1.0985486114323055,0.15239999999999998,0.40640000000000004],[1.1489040420039207,0.15239999999999998,0.40640000000000004],[1.1992594725755361,0.15239999999999998,0.40640000000000004],[1.2496149031471513,0.15239999999999998,0.40640000000000004],[1.2999703337187667,0.15239999999999998,0.40640000000000004],[1.3503257642903819,0.15239999999999998,0.40640000000000004],[1.4006811948619970,0.15239999999999998,0.40640000000000004],[1.4510366254336124,0.15239999999999998,0.40640000000000004],[1.5013920560052276,0.15239999999999998,0.40640000000000004],[1.5517474865768432,0.15239999999999998,0.40640000000000004],[1.6021029171484584,0.15239999999999998,0.40640000000000004],[1.6524583477200738,0.15239999999999998,0.40640000000000004],[1.7028137782916890,0.15239999999999998,0.40640000000000004],[1.7531692088633046,0.15239999999999998,0.40640000000000004],[1.8035246394349194,0.15239999999999998,0.40640000000000004],[1.8538800700065345,0.15239999999999998,0.40640000000000004],[1.9042355005781502,0.15239999999999998,0.40640000000000004],[1.9545909311497658,0.15239999999999998,0.40640000000000004],[2.0049463617213807,0.15239999999999998,0.40640000000000004],[2.0553017922929957,0.15239999999999998,0.40640000000000004],[2.1056572228646115,0.15239999999999998,0.40640000000000004],[2.1560126534362265,0.15239999999999998,0.40640000000000004],[2.2063680840078419,0.15239999999999998,0.40640000000000004],[2.2567235145794569,0.15239999999999998,0.40640000000000004],[2.3070789451510727,0.15239999999999998,0.40640000000000004],[2.3574343757226877,0.15239999999999998,0.40640000000000004],[2.4077898062943031,0.15239999999999998,0.40640000000000004],[2.4581452368659185,0.15239999999999998,0.40640000000000004],[2.5085006674375339,0.15239999999999998,0.40640000000000004],[2.5588560980091493,0.15239999999999998,0.40640000000000004],[2.6092115285807642,0.15239999999999998,0.40640000000000004],[2.6595669591523796,0.15239999999999998,0.40640000000000004],[2.7099223897239946,0.15239999999999998,0.40640000000000004],[2.7602778202956104,0.15239999999999998,0.40640000000000004],[2.8106332508672254,0.15239999999999998,0.40640000000000004],[2.8609886814388408,0.15239999999999998,0.40640000000000004],[2.9113441120104562,0.15239999999999998,0.40640000000000004],[0.14179543057161473,0.15239999999999998,0.35560000000000003],[0.19215086114323002,0.15239999999999998,0.35560000000000003],[0.24250629171484536,0.15239999999999998,0.35560000000000003],[0.29286172228646062,0.15239999999999998,0.35560000000000003],[0.34321715285807591,0.15239999999999998,0.35560000000000003],[0.39357258342969126,0.15239999999999998,0.35560000000000003],[0.44392801400130649,0.15239999999999998,0.35560000000000003],[0.49428344457292178,0.15239999999999998,0.35560000000000003],[0.54463887514453713,0.15239999999999998,0.35560000000000003],[0.59499430571615242,0.15239999999999998,0.35560000000000003],[0.64534973628776771,0.15239999999999998,0.35560000000000003],[0.6957051668593830,0.15239999999999998,0.35560000000000003],[0.74606059743099828,0.15239999999999998,0.35560000000000003],[0.79641602800261357,0.15239999999999998,0.35560000000000003],[0.84677145857422875,0.15239999999999998,0.35560000000000003],[0.89712688914584415,0.15239999999999998,0.35560000000000003],[0.94748231971745944,0.15239999999999998,0.35560000000000003],[0.99783775028907484,0.15239999999999998,0.35560000000000003],[1.0481931808606901,0.15239999999999998,0.35560000000000003],[1.0985486114323055,0.15239999999999998,0.35560000000000003],[1.1489040420039207,0.15239999999999998,0.35560000000000003],[1.1992594725755361,0.15239999999999998,0.35560000000000003],[1.2496149031471513,0.15239999999999998,0.35560000000000003],[1.2999703337187667,0.15239999999999998,0.35560000000000003],[1.3503257642903819,0.15239999999999998,0.35560000000000003],[1.4006811948619970,0.15239999999999998,0.35560000000000003],[1.4510366254336124,0.15239999999999998,0.35560000000000003],[1.5013920560052276,0.15239999999999998,0.35560000000000003],[1.5517474865768432,0.15239999999999998,0.35560000000000003],[1.6021029171484584,0.15239999999999998,0.35560000000000003],[1.6524583477200738,0.15239999999999998,0.35560000000000003],[1.7028137782916890,0.15239999999999998,0.35560000000000003],[1.7531692088633046,0.15239999999999998,0.35560000000000003],[1.8035246394349194,0.15239999999999998,0.35560000000000003],[1.8538800700065345,0.15239999999999998,0.35560000000000003],[1.9042355005781502,0.15239999999999998,0.35560000000000003],[1.9545909311497658,0.15239999999999998,0.35560000000000003],[2.0049463617213807,0.15239999999999998,0.35560000000000003],[2.0553017922929957,0.15239999999999998,0.35560000000000003],[2.1056572228646115,0.15239999999999998,0.35560000000000003],[2.1560126534362265,0.15239999999999998,0.35560000000000003],[2.2063680840078419,0.15239999999999998,0.35560000000000003],[2.2567235145794569,0.15239999999999998,0.35560000000000003],[2.3070789451510727,0.15239999999999998,0.35560000000000003],[2.3574343757226877,0.15239999999999998,0.35560000000000003],[2.4077898062943031,0.15239999999999998,0.35560000000000003],[2.4581452368659185,0.15239999999999998,0.35560000000000003],[2.5085006674375339,0.15239999999999998,0.35560000000000003],[2.5588560980091493,0.15239999999999998,0.35560000000000003],[2.6092115285807642,0.15239999999999998,0.35560000000000003],[2.6595669591523796,0.15239999999999998,0.35560000000000003],[2.7099223897239946,0.15239999999999998,0.35560000000000003],[2.7602778202956104,0.15239999999999998,0.35560000000000003],[2.8106332508672254,0.15239999999999998,0.35560000000000003],[2.8609886814388408,0.15239999999999998,0.35560000000000003],[2.9113441120104562,0.15239999999999998,0.35560000000000003],[0.14179543057161473,0.15239999999999998,0.30480000000000007],[0.19215086114323002,0.15239999999999998,0.30480000000000002],[0.24250629171484536,0.15239999999999998,0.30480000000000002],[0.29286172228646062,0.15239999999999998,0.30480000000000002],[0.34321715285807591,0.15239999999999998,0.30480000000000002],[0.39357258342969126,0.15239999999999998,0.30480000000000002],[0.44392801400130649,0.15239999999999998,0.30480000000000002],[0.49428344457292178,0.15239999999999998,0.30480000000000002],[0.54463887514453713,0.15239999999999998,0.30480000000000002],[0.59499430571615242,0.15239999999999998,0.30480000000000002],[0.64534973628776771,0.15239999999999998,0.30480000000000002],[0.6957051668593830,0.15239999999999998,0.30480000000000002],[0.74606059743099828,0.15239999999999998,0.30480000000000002],[0.79641602800261357,0.15239999999999998,0.30480000000000002],[0.84677145857422875,0.15239999999999998,0.30480000000000002],[0.89712688914584415,0.15239999999999998,0.30480000000000002],[0.94748231971745944,0.15239999999999998,0.30480000000000002],[0.99783775028907484,0.15239999999999998,0.30480000000000002],[1.0481931808606901,0.15239999999999998,0.30480000000000002],[1.0985486114323055,0.15239999999999998,0.30480000000000002],[1.1489040420039207,0.15239999999999998,0.30480000000000002],[1.1992594725755361,0.15239999999999998,0.30480000000000002],[1.2496149031471513,0.15239999999999998,0.30480000000000002],[1.2999703337187667,0.15239999999999998,0.30480000000000002],[1.3503257642903819,0.15239999999999998,0.30480000000000002],[1.4006811948619970,0.15239999999999998,0.30480000000000002],[1.4510366254336124,0.15239999999999998,0.30480000000000002],[1.5013920560052276,0.15239999999999998,0.30480000000000002],[1.5517474865768432,0.15239999999999998,0.30480000000000002],[1.6021029171484584,0.15239999999999998,0.30480000000000002],[1.6524583477200738,0.15239999999999998,0.30480000000000002],[1.7028137782916890,0.15239999999999998,0.30480000000000002],[1.7531692088633046,0.15239999999999998,0.30480000000000002],[1.8035246394349194,0.15239999999999998,0.30480000000000002],[1.8538800700065345,0.15239999999999998,0.30480000000000002],[1.9042355005781502,0.15239999999999998,0.30480000000000002],[1.9545909311497658,0.15239999999999998,0.30480000000000002],[2.0049463617213807,0.15239999999999998,0.30480000000000002],[2.0553017922929957,0.15239999999999998,0.30480000000000002],[2.1056572228646115,0.15239999999999998,0.30480000000000002],[2.1560126534362265,0.15239999999999998,0.30480000000000002],[2.2063680840078419,0.15239999999999998,0.30480000000000002],[2.2567235145794569,0.15239999999999998,0.30480000000000002],[2.3070789451510727,0.15239999999999998,0.30480000000000002],[2.3574343757226877,0.15239999999999998,0.30480000000000002],[2.4077898062943031,0.15239999999999998,0.30480000000000002],[2.4581452368659185,0.15239999999999998,0.30480000000000002],[2.5085006674375339,0.15239999999999998,0.30480000000000002],[2.5588560980091493,0.15239999999999998,0.30480000000000002],[2.6092115285807642,0.15239999999999998,0.30480000000000002],[2.6595669591523796,0.15239999999999998,0.30480000000000002],[2.7099223897239946,0.15239999999999998,0.30480000000000002],[2.7602778202956104,0.15239999999999998,0.30480000000000002],[2.8106332508672254,0.15239999999999998,0.30480000000000002],[2.8609886814388408,0.15239999999999998,0.30480000000000002],[2.9113441120104562,0.15239999999999998,0.30480000000000002],[0.14179543057161473,0.15239999999999998,0.25400000000000006],[0.19215086114323002,0.15239999999999998,0.2540],[0.24250629171484536,0.15239999999999998,0.2540],[0.29286172228646062,0.15239999999999998,0.2540],[0.34321715285807591,0.15239999999999998,0.2540],[0.39357258342969126,0.15239999999999998,0.2540],[0.44392801400130649,0.15239999999999998,0.2540],[0.49428344457292178,0.15239999999999998,0.2540],[0.54463887514453713,0.15239999999999998,0.2540],[0.59499430571615242,0.15239999999999998,0.2540],[0.64534973628776771,0.15239999999999998,0.2540],[0.6957051668593830,0.15239999999999998,0.2540],[0.74606059743099828,0.15239999999999998,0.2540],[0.79641602800261357,0.15239999999999998,0.2540],[0.84677145857422875,0.15239999999999998,0.2540],[0.89712688914584415,0.15239999999999998,0.2540],[0.94748231971745944,0.15239999999999998,0.2540],[0.99783775028907484,0.15239999999999998,0.2540],[1.0481931808606901,0.15239999999999998,0.2540],[1.0985486114323055,0.15239999999999998,0.2540],[1.1489040420039207,0.15239999999999998,0.2540],[1.1992594725755361,0.15239999999999998,0.2540],[1.2496149031471513,0.15239999999999998,0.2540],[1.2999703337187667,0.15239999999999998,0.2540],[1.3503257642903819,0.15239999999999998,0.2540],[1.4006811948619970,0.15239999999999998,0.2540],[1.4510366254336124,0.15239999999999998,0.2540],[1.5013920560052276,0.15239999999999998,0.2540],[1.5517474865768432,0.15239999999999998,0.2540],[1.6021029171484584,0.15239999999999998,0.2540],[1.6524583477200738,0.15239999999999998,0.2540],[1.7028137782916890,0.15239999999999998,0.2540],[1.7531692088633046,0.15239999999999998,0.2540],[1.8035246394349194,0.15239999999999998,0.2540],[1.8538800700065345,0.15239999999999998,0.2540],[1.9042355005781502,0.15239999999999998,0.2540],[1.9545909311497658,0.15239999999999998,0.2540],[2.0049463617213807,0.15239999999999998,0.2540],[2.0553017922929957,0.15239999999999998,0.2540],[2.1056572228646115,0.15239999999999998,0.2540],[2.1560126534362265,0.15239999999999998,0.2540],[2.2063680840078419,0.15239999999999998,0.2540],[2.2567235145794569,0.15239999999999998,0.2540],[2.3070789451510727,0.15239999999999998,0.2540],[2.3574343757226877,0.15239999999999998,0.2540],[2.4077898062943031,0.15239999999999998,0.2540],[2.4581452368659185,0.15239999999999998,0.2540],[2.5085006674375339,0.15239999999999998,0.2540],[2.5588560980091493,0.15239999999999998,0.2540],[2.6092115285807642,0.15239999999999998,0.2540],[2.6595669591523796,0.15239999999999998,0.2540],[2.7099223897239946,0.15239999999999998,0.2540],[2.7602778202956104,0.15239999999999998,0.2540],[2.8106332508672254,0.15239999999999998,0.2540],[2.8609886814388408,0.15239999999999998,0.2540],[2.9113441120104562,0.15239999999999998,0.2540],[0.14179543057161473,0.15239999999999998,0.20320000000000005],[0.19215086114323002,0.15239999999999998,0.20320000000000002],[0.24250629171484536,0.15239999999999998,0.20320000000000002],[0.29286172228646062,0.15239999999999998,0.20320000000000002],[0.34321715285807591,0.15239999999999998,0.20320000000000002],[0.39357258342969126,0.15239999999999998,0.20320000000000002],[0.44392801400130649,0.15239999999999998,0.20320000000000002],[0.49428344457292178,0.15239999999999998,0.20320000000000002],[0.54463887514453713,0.15239999999999998,0.20320000000000002],[0.59499430571615242,0.15239999999999998,0.20320000000000002],[0.64534973628776771,0.15239999999999998,0.20320000000000002],[0.6957051668593830,0.15239999999999998,0.20320000000000002],[0.74606059743099828,0.15239999999999998,0.20320000000000002],[0.79641602800261357,0.15239999999999998,0.20320000000000002],[0.84677145857422875,0.15239999999999998,0.20320000000000002],[0.89712688914584415,0.15239999999999998,0.20320000000000002],[0.94748231971745944,0.15239999999999998,0.20320000000000002],[0.99783775028907484,0.15239999999999998,0.20320000000000002],[1.0481931808606901,0.15239999999999998,0.20320000000000002],[1.0985486114323055,0.15239999999999998,0.20320000000000002],[1.1489040420039207,0.15239999999999998,0.20320000000000002],[1.1992594725755361,0.15239999999999998,0.20320000000000002],[1.2496149031471513,0.15239999999999998,0.20320000000000002],[1.2999703337187667,0.15239999999999998,0.20320000000000002],[1.3503257642903819,0.15239999999999998,0.20320000000000002],[1.4006811948619970,0.15239999999999998,0.20320000000000002],[1.4510366254336124,0.15239999999999998,0.20320000000000002],[1.5013920560052276,0.15239999999999998,0.20320000000000002],[1.5517474865768432,0.15239999999999998,0.20320000000000002],[1.6021029171484584,0.15239999999999998,0.20320000000000002],[1.6524583477200738,0.15239999999999998,0.20320000000000002],[1.7028137782916890,0.15239999999999998,0.20320000000000002],[1.7531692088633046,0.15239999999999998,0.20320000000000002],[1.8035246394349194,0.15239999999999998,0.20320000000000002],[1.8538800700065345,0.15239999999999998,0.20320000000000002],[1.9042355005781502,0.15239999999999998,0.20320000000000002],[1.9545909311497658,0.15239999999999998,0.20320000000000002],[2.0049463617213807,0.15239999999999998,0.20320000000000002],[2.0553017922929957,0.15239999999999998,0.20320000000000002],[2.1056572228646115,0.15239999999999998,0.20320000000000002],[2.1560126534362265,0.15239999999999998,0.20320000000000002],[2.2063680840078419,0.15239999999999998,0.20320000000000002],[2.2567235145794569,0.15239999999999998,0.20320000000000002],[2.3070789451510727,0.15239999999999998,0.20320000000000002],[2.3574343757226877,0.15239999999999998,0.20320000000000002],[2.4077898062943031,0.15239999999999998,0.20320000000000002],[2.4581452368659185,0.15239999999999998,0.20320000000000002],[2.5085006674375339,0.15239999999999998,0.20320000000000002],[2.5588560980091493,0.15239999999999998,0.20320000000000002],[2.6092115285807642,0.15239999999999998,0.20320000000000002],[2.6595669591523796,0.15239999999999998,0.20320000000000002],[2.7099223897239946,0.15239999999999998,0.20320000000000002],[2.7602778202956104,0.15239999999999998,0.20320000000000002],[2.8106332508672254,0.15239999999999998,0.20320000000000002],[2.8609886814388408,0.15239999999999998,0.20320000000000002],[2.9113441120104562,0.15239999999999998,0.20320000000000002],[0.14179543057161473,0.15239999999999998,0.15240000000000009],[0.19215086114323002,0.15239999999999998,0.15240000000000001],[0.24250629171484536,0.15239999999999998,0.15240000000000001],[0.29286172228646062,0.15239999999999998,0.15240000000000001],[0.34321715285807591,0.15239999999999998,0.15240000000000001],[0.39357258342969126,0.15239999999999998,0.15240000000000001],[0.44392801400130649,0.15239999999999998,0.15240000000000001],[0.49428344457292178,0.15239999999999998,0.15240000000000001],[0.54463887514453713,0.15239999999999998,0.15240000000000001],[0.59499430571615242,0.15239999999999998,0.15240000000000001],[0.64534973628776771,0.15239999999999998,0.15240000000000001],[0.6957051668593830,0.15239999999999998,0.15240000000000001],[0.74606059743099828,0.15239999999999998,0.15240000000000001],[0.79641602800261357,0.15239999999999998,0.15240000000000001],[0.84677145857422875,0.15239999999999998,0.15240000000000001],[0.89712688914584415,0.15239999999999998,0.15240000000000001],[0.94748231971745944,0.15239999999999998,0.15240000000000001],[0.99783775028907484,0.15239999999999998,0.15240000000000001],[1.0481931808606901,0.15239999999999998,0.15240000000000001],[1.0985486114323055,0.15239999999999998,0.15240000000000001],[1.1489040420039207,0.15239999999999998,0.15240000000000001],[1.1992594725755361,0.15239999999999998,0.15240000000000001],[1.2496149031471513,0.15239999999999998,0.15240000000000001],[1.2999703337187667,0.15239999999999998,0.15240000000000001],[1.3503257642903819,0.15239999999999998,0.15240000000000001],[1.4006811948619970,0.15239999999999998,0.15240000000000001],[1.4510366254336124,0.15239999999999998,0.15240000000000001],[1.5013920560052276,0.15239999999999998,0.15240000000000001],[1.5517474865768432,0.15239999999999998,0.15240000000000001],[1.6021029171484584,0.15239999999999998,0.15240000000000001],[1.6524583477200738,0.15239999999999998,0.15240000000000001],[1.7028137782916890,0.15239999999999998,0.15240000000000001],[1.7531692088633046,0.15239999999999998,0.15240000000000001],[1.8035246394349194,0.15239999999999998,0.15240000000000001],[1.8538800700065345,0.15239999999999998,0.15240000000000001],[1.9042355005781502,0.15239999999999998,0.15240000000000001],[1.9545909311497658,0.15239999999999998,0.15240000000000001],[2.0049463617213807,0.15239999999999998,0.15240000000000001],[2.0553017922929957,0.15239999999999998,0.15240000000000001],[2.1056572228646115,0.15239999999999998,0.15240000000000001],[2.1560126534362265,0.15239999999999998,0.15240000000000001],[2.2063680840078419,0.15239999999999998,0.15240000000000001],[2.2567235145794569,0.15239999999999998,0.15240000000000001],[2.3070789451510727,0.15239999999999998,0.15240000000000001],[2.3574343757226877,0.15239999999999998,0.15240000000000001],[2.4077898062943031,0.15239999999999998,0.15240000000000001],[2.4581452368659185,0.15239999999999998,0.15240000000000001],[2.5085006674375339,0.15239999999999998,0.15240000000000001],[2.5588560980091493,0.15239999999999998,0.15240000000000001],[2.6092115285807642,0.15239999999999998,0.15240000000000001],[2.6595669591523796,0.15239999999999998,0.15240000000000001],[2.7099223897239946,0.15239999999999998,0.15240000000000001],[2.7602778202956104,0.15239999999999998,0.15240000000000001],[2.8106332508672254,0.15239999999999998,0.15240000000000001],[2.8609886814388408,0.15239999999999998,0.15240000000000001],[2.9113441120104562,0.15239999999999998,0.15240000000000001],[0.14179543057161473,0.15239999999999998,0.10160000000000013],[0.19215086114323002,0.15239999999999998,0.10160000000000005],[0.24250629171484536,0.15239999999999998,0.10160000000000005],[0.29286172228646062,0.15239999999999998,0.10160000000000005],[0.34321715285807591,0.15239999999999998,0.10160000000000005],[0.39357258342969126,0.15239999999999998,0.10160000000000005],[0.44392801400130649,0.15239999999999998,0.10160000000000005],[0.49428344457292178,0.15239999999999998,0.10160000000000005],[0.54463887514453713,0.15239999999999998,0.10160000000000005],[0.59499430571615242,0.15239999999999998,0.10160000000000005],[0.64534973628776771,0.15239999999999998,0.10160000000000005],[0.6957051668593830,0.15239999999999998,0.10160000000000005],[0.74606059743099828,0.15239999999999998,0.10160000000000005],[0.79641602800261357,0.15239999999999998,0.10160000000000005],[0.84677145857422875,0.15239999999999998,0.10160000000000005],[0.89712688914584415,0.15239999999999998,0.10160000000000005],[0.94748231971745944,0.15239999999999998,0.10160000000000005],[0.99783775028907484,0.15239999999999998,0.10160000000000005],[1.0481931808606901,0.15239999999999998,0.10160000000000005],[1.0985486114323055,0.15239999999999998,0.10160000000000005],[1.1489040420039207,0.15239999999999998,0.10160000000000005],[1.1992594725755361,0.15239999999999998,0.10160000000000005],[1.2496149031471513,0.15239999999999998,0.10160000000000005],[1.2999703337187667,0.15239999999999998,0.10160000000000005],[1.3503257642903819,0.15239999999999998,0.10160000000000005],[1.4006811948619970,0.15239999999999998,0.10160000000000005],[1.4510366254336124,0.15239999999999998,0.10160000000000005],[1.5013920560052276,0.15239999999999998,0.10160000000000005],[1.5517474865768432,0.15239999999999998,0.10160000000000005],[1.6021029171484584,0.15239999999999998,0.10160000000000005],[1.6524583477200738,0.15239999999999998,0.10160000000000005],[1.7028137782916890,0.15239999999999998,0.10160000000000005],[1.7531692088633046,0.15239999999999998,0.10160000000000005],[1.8035246394349194,0.15239999999999998,0.10160000000000005],[1.8538800700065345,0.15239999999999998,0.10160000000000005],[1.9042355005781502,0.15239999999999998,0.10160000000000005],[1.9545909311497658,0.15239999999999998,0.10160000000000005],[2.0049463617213807,0.15239999999999998,0.10160000000000005],[2.0553017922929957,0.15239999999999998,0.10160000000000005],[2.1056572228646115,0.15239999999999998,0.10160000000000005],[2.1560126534362265,0.15239999999999998,0.10160000000000005],[2.2063680840078419,0.15239999999999998,0.10160000000000005],[2.2567235145794569,0.15239999999999998,0.10160000000000005],[2.3070789451510727,0.15239999999999998,0.10160000000000005],[2.3574343757226877,0.15239999999999998,0.10160000000000005],[2.4077898062943031,0.15239999999999998,0.10160000000000005],[2.4581452368659185,0.15239999999999998,0.10160000000000005],[2.5085006674375339,0.15239999999999998,0.10160000000000005],[2.5588560980091493,0.15239999999999998,0.10160000000000005],[2.6092115285807642,0.15239999999999998,0.10160000000000005],[2.6595669591523796,0.15239999999999998,0.10160000000000005],[2.7099223897239946,0.15239999999999998,0.10160000000000005],[2.7602778202956104,0.15239999999999998,0.10160000000000005],[2.8106332508672254,0.15239999999999998,0.10160000000000005],[2.8609886814388408,0.15239999999999998,0.10160000000000005],[2.9113441120104562,0.15239999999999998,0.10160000000000005],[0.14179543057161473,0.15239999999999998,0.050800000000000095],[0.19215086114323002,0.15239999999999998,0.050800000000000005],[0.24250629171484536,0.15239999999999998,0.050800000000000005],[0.29286172228646062,0.15239999999999998,0.050800000000000005],[0.34321715285807591,0.15239999999999998,0.050800000000000005],[0.39357258342969126,0.15239999999999998,0.050800000000000005],[0.44392801400130649,0.15239999999999998,0.050800000000000005],[0.49428344457292178,0.15239999999999998,0.050800000000000005],[0.54463887514453713,0.15239999999999998,0.050800000000000005],[0.59499430571615242,0.15239999999999998,0.050800000000000005],[0.64534973628776771,0.15239999999999998,0.050800000000000005],[0.6957051668593830,0.15239999999999998,0.050800000000000005],[0.74606059743099828,0.15239999999999998,0.050800000000000005],[0.79641602800261357,0.15239999999999998,0.050800000000000005],[0.84677145857422875,0.15239999999999998,0.050800000000000005],[0.89712688914584415,0.15239999999999998,0.050800000000000005],[0.94748231971745944,0.15239999999999998,0.050800000000000005],[0.99783775028907484,0.15239999999999998,0.050800000000000005],[1.0481931808606901,0.15239999999999998,0.050800000000000005],[1.0985486114323055,0.15239999999999998,0.050800000000000005],[1.1489040420039207,0.15239999999999998,0.050800000000000005],[1.1992594725755361,0.15239999999999998,0.050800000000000005],[1.2496149031471513,0.15239999999999998,0.050800000000000005],[1.2999703337187667,0.15239999999999998,0.050800000000000005],[1.3503257642903819,0.15239999999999998,0.050800000000000005],[1.4006811948619970,0.15239999999999998,0.050800000000000005],[1.4510366254336124,0.15239999999999998,0.050800000000000005],[1.5013920560052276,0.15239999999999998,0.050800000000000005],[1.5517474865768432,0.15239999999999998,0.050800000000000005],[1.6021029171484584,0.15239999999999998,0.050800000000000005],[1.6524583477200738,0.15239999999999998,0.050800000000000005],[1.7028137782916890,0.15239999999999998,0.050800000000000005],[1.7531692088633046,0.15239999999999998,0.050800000000000005],[1.8035246394349194,0.15239999999999998,0.050800000000000005],[1.8538800700065345,0.15239999999999998,0.050800000000000005],[1.9042355005781502,0.15239999999999998,0.050800000000000005],[1.9545909311497658,0.15239999999999998,0.050800000000000005],[2.0049463617213807,0.15239999999999998,0.050800000000000005],[2.0553017922929957,0.15239999999999998,0.050800000000000005],[2.1056572228646115,0.15239999999999998,0.050800000000000005],[2.1560126534362265,0.15239999999999998,0.050800000000000005],[2.2063680840078419,0.15239999999999998,0.050800000000000005],[2.2567235145794569,0.15239999999999998,0.050800000000000005],[2.3070789451510727,0.15239999999999998,0.050800000000000005],[2.3574343757226877,0.15239999999999998,0.050800000000000005],[2.4077898062943031,0.15239999999999998,0.050800000000000005],[2.4581452368659185,0.15239999999999998,0.050800000000000005],[2.5085006674375339,0.15239999999999998,0.050800000000000005],[2.5588560980091493,0.15239999999999998,0.050800000000000005],[2.6092115285807642,0.15239999999999998,0.050800000000000005],[2.6595669591523796,0.15239999999999998,0.050800000000000005],[2.7099223897239946,0.15239999999999998,0.050800000000000005],[2.7602778202956104,0.15239999999999998,0.050800000000000005],[2.8106332508672254,0.15239999999999998,0.050800000000000005],[2.8609886814388408,0.15239999999999998,0.050800000000000005],[2.9113441120104562,0.15239999999999998,0.050800000000000005]],"pointIndex":[1,2,6,5,0,2,3,7,6,0,3,4,8,7,0,5,6,10,9,0,6,7,11,10,0,7,8,12,11,0,9,10,14,13,0,10,11,15,14,0,11,12,16,15,0,13,14,18,17,0,14,15,19,18,0,15,16,20,19,0,17,18,22,21,0,18,19,23,22,0,19,20,24,23,0,21,22,26,25,0,22,23,27,26,0,23,24,28,27,0,25,26,30,29,0,26,27,31,30,0,27,28,32,31,0,29,30,34,33,0,30,31,35,34,0,31,32,36,35,0,33,34,38,37,0,34,35,39,38,0,35,36,40,39,0,37,38,42,41,0,38,39,43,42,0,39,40,44,43,0,41,42,46,45,0,42,43,47,46,0,43,44,48,47,0,45,46,50,49,0,46,47,51,50,0,47,48,52,51,0,49,50,54,53,0,50,51,55,54,0,51,52,56,55,0,53,54,58,57,0,54,55,59,58,0,55,56,60,59,0,57,58,62,61,0,58,59,63,62,0,59,60,64,63,0,61,62,66,65,0,62,63,67,66,0,63,64,68,67,0,65,66,70,69,0,66,67,71,70,0,67,68,72,71,0,69,70,74,73,0,70,71,75,74,0,71,72,76,75,0,73,74,78,77,0,74,75,79,78,0,75,76,80,79,0,77,78,82,81,0,78,79,83,82,0,79,80,84,83,0,81,82,86,85,0,82,83,87,86,0,83,84,88,87,0,85,86,90,89,0,86,87,91,90,0,87,88,92,91,0,89,90,94,93,0,90,91,95,94,0,91,92,96,95,0,93,94,98,97,0,94,95,99,98,0,95,96,100,99,0,97,98,102,101,0,98,99,103,102,0,99,100,104,103,0,101,102,106,105,0,102,103,107,106,0,103,104,108,107,0,105,106,110,109,0,106,107,111,110,0,107,108,112,111,0,109,110,114,113,0,110,111,115,114,0,111,112,116,115,0,113,114,118,117,0,114,115,119,118,0,115,116,120,119,0,117,118,122,121,0,118,119,123,122,0,119,120,124,123,0,121,122,126,125,0,122,123,127,126,0,123,124,128,127,0,125,126,130,129,0,126,127,131,130,0,127,128,132,131,0,129,130,134,133,0,130,131,135,134,0,131,132,136,135,0,133,134,138,137,0,134,135,139,138,0,135,136,140,139,0,137,138,142,141,0,138,139,143,142,0,139,140,144,143,0,141,142,146,145,0,142,143,147,146,0,143,144,148,147,0,145,146,150,149,0,146,147,151,150,0,147,148,152,151,0,149,150,154,153,0,150,151,155,154,0,151,152,156,155,0,153,154,158,157,0,154,155,159,158,0,155,156,160,159,0,157,158,162,161,0,158,159,163,162,0,159,160,164,163,0,161,162,166,165,0,162,163,167,166,0,163,164,168,167,0,165,166,170,169,0,166,167,171,170,0,167,168,172,171,0,169,170,174,173,0,170,171,175,174,0,171,172,176,175,0,173,174,178,177,0,174,175,179,178,0,175,176,180,179,0,177,178,182,181,0,178,179,183,182,0,179,180,184,183,0,181,182,186,185,0,182,183,187,186,0,183,184,188,187,0,185,186,190,189,0,186,187,191,190,0,187,188,192,191,0,189,190,194,193,0,190,191,195,194,0,191,192,196,195,0,193,194,198,197,0,194,195,199,198,0,195,196,200,199,0,197,198,202,201,0,198,199,203,202,0,199,200,204,203,0,201,202,206,205,0,202,203,207,206,0,203,204,208,207,0,205,206,210,209,0,206,207,211,210,0,207,208,212,211,0,209,210,214,213,0,210,211,215,214,0,211,212,216,215,0,213,214,218,217,0,214,215,219,218,0,215,216,220,219,0,217,218,222,221,0,218,219,223,222,0,219,220,224,223,0,221,222,226,225,0,222,223,227,226,0,223,224,228,227,0,225,226,230,229,0,226,227,231,230,0,227,228,232,231,0,233,234,238,237,0,234,235,239,238,0,235,236,240,239,0,237,238,242,241,0,238,239,243,242,0,239,240,244,243,0,241,242,246,245,0,242,243,247,246,0,243,244,248,247,0,245,246,250,249,0,246,247,251,250,0,247,248,252,251,0,249,250,254,253,0,250,251,255,254,0,251,252,256,255,0,253,254,258,257,0,254,255,259,258,0,255,256,260,259,0,257,258,262,261,0,258,259,263,262,0,259,260,264,263,0,261,262,266,265,0,262,263,267,266,0,263,264,268,267,0,265,266,270,269,0,266,267,271,270,0,267,268,272,271,0,269,270,274,273,0,270,271,275,274,0,271,272,276,275,0,273,274,278,277,0,274,275,279,278,0,275,276,280,279,0,277,278,282,281,0,278,279,283,282,0,279,280,284,283,0,281,282,286,285,0,282,283,287,286,0,283,284,288,287,0,285,286,290,289,0,286,287,291,290,0,287,288,292,291,0,289,290,294,293,0,290,291,295,294,0,291,292,296,295,0,293,294,298,297,0,294,295,299,298,0,295,296,300,299,0,297,298,302,301,0,298,299,303,302,0,299,300,304,303,0,301,302,306,305,0,302,303,307,306,0,303,304,308,307,0,305,306,310,309,0,306,307,311,310,0,307,308,312,311,0,309,310,314,313,0,310,311,315,314,0,311,312,316,315,0,313,314,318,317,0,314,315,319,318,0,315,316,320,319,0,317,318,322,321,0,318,319,323,322,0,319,320,324,323,0,321,322,326,325,0,322,323,327,326,0,323,324,328,327,0,325,326,330,329,0,326,327,331,330,0,327,328,332,331,0,329,330,334,333,0,330,331,335,334,0,331,332,336,335,0,333,334,338,337,0,334,335,339,338,0,335,336,340,339,0,337,338,342,341,0,338,339,343,342,0,339,340,344,343,0,341,342,346,345,0,342,343,347,346,0,343,344,348,347,0,345,346,350,349,0,346,347,351,350,0,347,348,352,351,0,349,350,354,353,0,350,351,355,354,0,351,352,356,355,0,353,354,358,357,0,354,355,359,358,0,355,356,360,359,0,357,358,362,361,0,358,359,363,362,0,359,360,364,363,0,361,362,366,365,0,362,363,367,366,0,363,364,368,367,0,365,366,370,369,0,366,367,371,370,0,367,368,372,371,0,369,370,374,373,0,370,371,375,374,0,371,372,376,375,0,373,374,378,377,0,374,375,379,378,0,375,376,380,379,0,377,378,382,381,0,378,379,383,382,0,379,380,384,383,0,381,382,386,385,0,382,383,387,386,0,383,384,388,387,0,385,386,390,389,0,386,387,391,390,0,387,388,392,391,0,389,390,394,393,0,390,391,395,394,0,391,392,396,395,0,393,394,398,397,0,394,395,399,398,0,395,396,400,399,0,397,398,402,401,0,398,399,403,402,0,399,400,404,403,0,401,402,406,405,0,402,403,407,406,0,403,404,408,407,0,405,406,410,409,0,406,407,411,410,0,407,408,412,411,0,409,410,414,413,0,410,411,415,414,0,411,412,416,415,0,413,414,418,417,0,414,415,419,418,0,415,416,420,419,0,417,418,422,421,0,418,419,423,422,0,419,420,424,423,0,421,422,426,425,0,422,423,427,426,0,423,424,428,427,0,425,426,430,429,0,426,427,431,430,0,427,428,432,431,0,429,430,434,433,0,430,431,435,434,0,431,432,436,435,0,433,434,438,437,0,434,435,439,438,0,435,436,440,439,0,437,438,442,441,0,438,439,443,442,0,439,440,444,443,0,441,442,446,445,0,442,443,447,446,0,443,444,448,447,0,445,446,450,449,0,446,447,451,450,0,447,448,452,451,0,449,450,454,453,0,450,451,455,454,0,451,452,456,455,0,453,454,458,457,0,454,455,459,458,0,455,456,460,459,0,457,458,462,461,0,458,459,463,462,0,459,460,464,463,0,4,3,466,465,0,3,2,467,466,0,2,1,468,467,0,465,466,470,469,0,466,467,471,470,0,467,468,472,471,0,469,470,474,473,0,470,471,475,474,0,471,472,476,475,0,473,474,478,477,0,474,475,479,478,0,475,476,480,479,0,477,478,482,481,0,478,479,483,482,0,479,480,484,483,0,481,482,486,485,0,482,483,487,486,0,483,484,488,487,0,485,486,490,489,0,486,487,491,490,0,487,488,492,491,0,489,490,494,493,0,490,491,495,494,0,491,492,496,495,0,493,494,234,233,0,494,495,235,234,0,495,496,236,235,0,1,5,497,468,0,5,9,498,497,0,9,13,499,498,0,13,17,500,499,0,17,21,501,500,0,21,25,502,501,0,25,29,503,502,0,29,33,504,503,0,33,37,505,504,0,37,41,506,505,0,41,45,507,506,0,45,49,508,507,0,49,53,509,508,0,53,57,510,509,0,57,61,511,510,0,61,65,512,511,0,65,69,513,512,0,69,73,514,513,0,73,77,515,514,0,77,81,516,515,0,81,85,517,516,0,85,89,518,517,0,89,93,519,518,0,93,97,520,519,0,97,101,521,520,0,101,105,522,521,0,105,109,523,522,0,109,113,524,523,0,113,117,525,524,0,117,121,526,525,0,121,125,527,526,0,125,129,528,527,0,129,133,529,528,0,133,137,530,529,0,137,141,531,530,0,141,145,532,531,0,145,149,533,532,0,149,153,534,533,0,153,157,535,534,0,157,161,536,535,0,161,165,537,536,0,165,169,538,537,0,169,173,539,538,0,173,177,540,539,0,177,181,541,540,0,181,185,542,541,0,185,189,543,542,0,189,193,544,543,0,193,197,545,544,0,197,201,546,545,0,201,205,547,546,0,205,209,548,547,0,209,213,549,548,0,213,217,550,549,0,217,221,551,550,0,221,225,552,551,0,225,229,553,552,0,468,497,554,472,0,497,498,555,554,0,498,499,556,555,0,499,500,557,556,0,500,501,558,557,0,501,502,559,558,0,502,503,560,559,0,503,504,561,560,0,504,505,562,561,0,505,506,563,562,0,506,507,564,563,0,507,508,565,564,0,508,509,566,565,0,509,510,567,566,0,510,511,568,567,0,511,512,569,568,0,512,513,570,569,0,513,514,571,570,0,514,515,572,571,0,515,516,573,572,0,516,517,574,573,0,517,518,575,574,0,518,519,576,575,0,519,520,577,576,0,520,521,578,577,0,521,522,579,578,0,522,523,580,579,0,523,524,581,580,0,524,525,582,581,0,525,526,583,582,0,526,527,584,583,0,527,528,585,584,0,528,529,586,585,0,529,530,587,586,0,530,531,588,587,0,531,532,589,588,0,532,533,590,589,0,533,534,591,590,0,534,535,592,591,0,535,536,593,592,0,536,537,594,593,0,537,538,595,594,0,538,539,596,595,0,539,540,597,596,0,540,541,598,597,0,541,542,599,598,0,542,543,600,599,0,543,544,601,600,0,544,545,602,601,0,545,546,603,602,0,546,547,604,603,0,547,548,605,604,0,548,549,606,605,0,549,550,607,606,0,550,551,608,607,0,551,552,609,608,0,552,553,610,609,0,472,554,611,476,0,554,555,612,611,0,555,556,613,612,0,556,557,614,613,0,557,558,615,614,0,558,559,616,615,0,559,560,617,616,0,560,561,618,617,0,561,562,619,618,0,562,563,620,619,0,563,564,621,620,0,564,565,622,621,0,565,566,623,622,0,566,567,624,623,0,567,568,625,624,0,568,569,626,625,0,569,570,627,626,0,570,571,628,627,0,571,572,629,628,0,572,573,630,629,0,573,574,631,630,0,574,575,632,631,0,575,576,633,632,0,576,577,634,633,0,577,578,635,634,0,578,579,636,635,0,579,580,637,636,0,580,581,638,637,0,581,582,639,638,0,582,583,640,639,0,583,584,641,640,0,584,585,642,641,0,585,586,643,642,0,586,587,644,643,0,587,588,645,644,0,588,589,646,645,0,589,590,647,646,0,590,591,648,647,0,591,592,649,648,0,592,593,650,649,0,593,594,651,650,0,594,595,652,651,0,595,596,653,652,0,596,597,654,653,0,597,598,655,654,0,598,599,656,655,0,599,600,657,656,0,600,601,658,657,0,601,602,659,658,0,602,603,660,659,0,603,604,661,660,0,604,605,662,661,0,605,606,663,662,0,606,607,664,663,0,607,608,665,664,0,608,609,666,665,0,609,610,667,666,0,476,611,668,480,0,611,612,669,668,0,612,613,670,669,0,613,614,671,670,0,614,615,672,671,0,615,616,673,672,0,616,617,674,673,0,617,618,675,674,0,618,619,676,675,0,619,620,677,676,0,620,621,678,677,0,621,622,679,678,0,622,623,680,679,0,623,624,681,680,0,624,625,682,681,0,625,626,683,682,0,626,627,684,683,0,627,628,685,684,0,628,629,686,685,0,629,630,687,686,0,630,631,688,687,0,631,632,689,688,0,632,633,690,689,0,633,634,691,690,0,634,635,692,691,0,635,636,693,692,0,636,637,694,693,0,637,638,695,694,0,638,639,696,695,0,639,640,697,696,0,640,641,698,697,0,641,642,699,698,0,642,643,700,699,0,643,644,701,700,0,644,645,702,701,0,645,646,703,702,0,646,647,704,703,0,647,648,705,704,0,648,649,706,705,0,649,650,707,706,0,650,651,708,707,0,651,652,709,708,0,652,653,710,709,0,653,654,711,710,0,654,655,712,711,0,655,656,713,712,0,656,657,714,713,0,657,658,715,714,0,658,659,716,715,0,659,660,717,716,0,660,661,718,717,0,661,662,719,718,0,662,663,720,719,0,663,664,721,720,0,664,665,722,721,0,665,666,723,722,0,666,667,724,723,0,480,668,725,484,0,668,669,726,725,0,669,670,727,726,0,670,671,728,727,0,671,672,729,728,0,672,673,730,729,0,673,674,731,730,0,674,675,732,731,0,675,676,733,732,0,676,677,734,733,0,677,678,735,734,0,678,679,736,735,0,679,680,737,736,0,680,681,738,737,0,681,682,739,738,0,682,683,740,739,0,683,684,741,740,0,684,685,742,741,0,685,686,743,742,0,686,687,744,743,0,687,688,745,744,0,688,689,746,745,0,689,690,747,746,0,690,691,748,747,0,691,692,749,748,0,692,693,750,749,0,693,694,751,750,0,694,695,752,751,0,695,696,753,752,0,696,697,754,753,0,697,698,755,754,0,698,699,756,755,0,699,700,757,756,0,700,701,758,757,0,701,702,759,758,0,702,703,760,759,0,703,704,761,760,0,704,705,762,761,0,705,706,763,762,0,706,707,764,763,0,707,708,765,764,0,708,709,766,765,0,709,710,767,766,0,710,711,768,767,0,711,712,769,768,0,712,713,770,769,0,713,714,771,770,0,714,715,772,771,0,715,716,773,772,0,716,717,774,773,0,717,718,775,774,0,718,719,776,775,0,719,720,777,776,0,720,721,778,777,0,721,722,779,778,0,722,723,780,779,0,723,724,781,780,0,484,725,782,488,0,725,726,783,782,0,726,727,784,783,0,727,728,785,784,0,728,729,786,785,0,729,730,787,786,0,730,731,788,787,0,731,732,789,788,0,732,733,790,789,0,733,734,791,790,0,734,735,792,791,0,735,736,793,792,0,736,737,794,793,0,737,738,795,794,0,738,739,796,795,0,739,740,797,796,0,740,741,798,797,0,741,742,799,798,0,742,743,800,799,0,743,744,801,800,0,744,745,802,801,0,745,746,803,802,0,746,747,804,803,0,747,748,805,804,0,748,749,806,805,0,749,750,807,806,0,750,751,808,807,0,751,752,809,808,0,752,753,810,809,0,753,754,811,810,0,754,755,812,811,0,755,756,813,812,0,756,757,814,813,0,757,758,815,814,0,758,759,816,815,0,759,760,817,816,0,760,761,818,817,0,761,762,819,818,0,762,763,820,819,0,763,764,821,820,0,764,765,822,821,0,765,766,823,822,0,766,767,824,823,0,767,768,825,824,0,768,769,826,825,0,769,770,827,826,0,770,771,828,827,0,771,772,829,828,0,772,773,830,829,0,773,774,831,830,0,774,775,832,831,0,775,776,833,832,0,776,777,834,833,0,777,778,835,834,0,778,779,836,835,0,779,780,837,836,0,780,781,838,837,0,488,782,839,492,0,782,783,840,839,0,783,784,841,840,0,784,785,842,841,0,785,786,843,842,0,786,787,844,843,0,787,788,845,844,0,788,789,846,845,0,789,790,847,846,0,790,791,848,847,0,791,792,849,848,0,792,793,850,849,0,793,794,851,850,0,794,795,852,851,0,795,796,853,852,0,796,797,854,853,0,797,798,855,854,0,798,799,856,855,0,799,800,857,856,0,800,801,858,857,0,801,802,859,858,0,802,803,860,859,0,803,804,861,860,0,804,805,862,861,0,805,806,863,862,0,806,807,864,863,0,807,808,865,864,0,808,809,866,865,0,809,810,867,866,0,810,811,868,867,0,811,812,869,868,0,812,813,870,869,0,813,814,871,870,0,814,815,872,871,0,815,816,873,872,0,816,817,874,873,0,817,818,875,874,0,818,819,876,875,0,819,820,877,876,0,820,821,878,877,0,821,822,879,878,0,822,823,880,879,0,823,824,881,880,0,824,825,882,881,0,825,826,883,882,0,826,827,884,883,0,827,828,885,884,0,828,829,886,885,0,829,830,887,886,0,830,831,888,887,0,831,832,889,888,0,832,833,890,889,0,833,834,891,890,0,834,835,892,891,0,835,836,893,892,0,836,837,894,893,0,837,838,895,894,0,492,839,896,496,0,839,840,897,896,0,840,841,898,897,0,841,842,899,898,0,842,843,900,899,0,843,844,901,900,0,844,845,902,901,0,845,846,903,902,0,846,847,904,903,0,847,848,905,904,0,848,849,906,905,0,849,850,907,906,0,850,851,908,907,0,851,852,909,908,0,852,853,910,909,0,853,854,911,910,0,854,855,912,911,0,855,856,913,912,0,856,857,914,913,0,857,858,915,914,0,858,859,916,915,0,859,860,917,916,0,860,861,918,917,0,861,862,919,918,0,862,863,920,919,0,863,864,921,920,0,864,865,922,921,0,865,866,923,922,0,866,867,924,923,0,867,868,925,924,0,868,869,926,925,0,869,870,927,926,0,870,871,928,927,0,871,872,929,928,0,872,873,930,929,0,873,874,931,930,0,874,875,932,931,0,875,876,933,932,0,876,877,934,933,0,877,878,935,934,0,878,879,936,935,0,879,880,937,936,0,880,881,938,937,0,881,882,939,938,0,882,883,940,939,0,883,884,941,940,0,884,885,942,941,0,885,886,943,942,0,886,887,944,943,0,887,888,945,944,0,888,889,946,945,0,889,890,947,946,0,890,891,948,947,0,891,892,949,948,0,892,893,950,949,0,893,894,951,950,0,894,895,952,951,0,496,896,240,236,0,896,897,244,240,0,897,898,248,244,0,898,899,252,248,0,899,900,256,252,0,900,901,260,256,0,901,902,264,260,0,902,903,268,264,0,903,904,272,268,0,904,905,276,272,0,905,906,280,276,0,906,907,284,280,0,907,908,288,284,0,908,909,292,288,0,909,910,296,292,0,910,911,300,296,0,911,912,304,300,0,912,913,308,304,0,913,914,312,308,0,914,915,316,312,0,915,916,320,316,0,916,917,324,320,0,917,918,328,324,0,918,919,332,328,0,919,920,336,332,0,920,921,340,336,0,921,922,344,340,0,922,923,348,344,0,923,924,352,348,0,924,925,356,352,0,925,926,360,356,0,926,927,364,360,0,927,928,368,364,0,928,929,372,368,0,929,930,376,372,0,930,931,380,376,0,931,932,384,380,0,932,933,388,384,0,933,934,392,388,0,934,935,396,392,0,935,936,400,396,0,936,937,404,400,0,937,938,408,404,0,938,939,412,408,0,939,940,416,412,0,940,941,420,416,0,941,942,424,420,0,942,943,428,424,0,943,944,432,428,0,944,945,436,432,0,945,946,440,436,0,946,947,444,440,0,947,948,448,444,0,948,949,452,448,0,949,950,456,452,0,950,951,460,456,0,951,952,464,460,0,229,230,953,553,0,230,231,954,953,0,231,232,955,954,0,553,953,956,610,0,953,954,957,956,0,954,955,958,957,0,610,956,959,667,0,956,957,960,959,0,957,958,961,960,0,667,959,962,724,0,959,960,963,962,0,960,961,964,963,0,724,962,965,781,0,962,963,966,965,0,963,964,967,966,0,781,965,968,838,0,965,966,969,968,0,966,967,970,969,0,838,968,971,895,0,968,969,972,971,0,969,970,973,972,0,895,971,974,952,0,971,972,975,974,0,972,973,976,975,0,952,974,463,464,0,974,975,462,463,0,975,976,461,462,0,232,228,977,955,0,228,224,978,977,0,224,220,979,978,0,220,216,980,979,0,216,212,981,980,0,212,208,982,981,0,208,204,983,982,0,204,200,984,983,0,200,196,985,984,0,196,192,986,985,0,192,188,987,986,0,188,184,988,987,0,184,180,989,988,0,180,176,990,989,0,176,172,991,990,0,172,168,992,991,0,168,164,993,992,0,164,160,994,993,0,160,156,995,994,0,156,152,996,995,0,152,148,997,996,0,148,144,998,997,0,144,140,999,998,0,140,136,1000,999,0,136,132,1001,1000,0,132,128,1002,1001,0,128,124,1003,1002,0,124,120,1004,1003,0,120,116,1005,1004,0,116,112,1006,1005,0,112,108,1007,1006,0,108,104,1008,1007,0,104,100,1009,1008,0,100,96,1010,1009,0,96,92,1011,1010,0,92,88,1012,1011,0,88,84,1013,1012,0,84,80,1014,1013,0,80,76,1015,1014,0,76,72,1016,1015,0,72,68,1017,1016,0,68,64,1018,1017,0,64,60,1019,1018,0,60,56,1020,1019,0,56,52,1021,1020,0,52,48,1022,1021,0,48,44,1023,1022,0,44,40,1024,1023,0,40,36,1025,1024,0,36,32,1026,1025,0,32,28,1027,1026,0,28,24,1028,1027,0,24,20,1029,1028,0,20,16,1030,1029,0,16,12,1031,1030,0,12,8,1032,1031,0,8,4,465,1032,0,955,977,1033,958,0,977,978,1034,1033,0,978,979,1035,1034,0,979,980,1036,1035,0,980,981,1037,1036,0,981,982,1038,1037,0,982,983,1039,1038,0,983,984,1040,1039,0,984,985,1041,1040,0,985,986,1042,1041,0,986,987,1043,1042,0,987,988,1044,1043,0,988,989,1045,1044,0,989,990,1046,1045,0,990,991,1047,1046,0,991,992,1048,1047,0,992,993,1049,1048,0,993,994,1050,1049,0,994,995,1051,1050,0,995,996,1052,1051,0,996,997,1053,1052,0,997,998,1054,1053,0,998,999,1055,1054,0,999,1000,1056,1055,0,1000,1001,1057,1056,0,1001,1002,1058,1057,0,1002,1003,1059,1058,0,1003,1004,1060,1059,0,1004,1005,1061,1060,0,1005,1006,1062,1061,0,1006,1007,1063,1062,0,1007,1008,1064,1063,0,1008,1009,1065,1064,0,1009,1010,1066,1065,0,1010,1011,1067,1066,0,1011,1012,1068,1067,0,1012,1013,1069,1068,0,1013,1014,1070,1069,0,1014,1015,1071,1070,0,1015,1016,1072,1071,0,1016,1017,1073,1072,0,1017,1018,1074,1073,0,1018,1019,1075,1074,0,1019,1020,1076,1075,0,1020,1021,1077,1076,0,1021,1022,1078,1077,0,1022,1023,1079,1078,0,1023,1024,1080,1079,0,1024,1025,1081,1080,0,1025,1026,1082,1081,0,1026,1027,1083,1082,0,1027,1028,1084,1083,0,1028,1029,1085,1084,0,1029,1030,1086,1085,0,1030,1031,1087,1086,0,1031,1032,1088,1087,0,1032,465,469,1088,0,958,1033,1089,961,0,1033,1034,1090,1089,0,1034,1035,1091,1090,0,1035,1036,1092,1091,0,1036,1037,1093,1092,0,1037,1038,1094,1093,0,1038,1039,1095,1094,0,1039,1040,1096,1095,0,1040,1041,1097,1096,0,1041,1042,1098,1097,0,1042,1043,1099,1098,0,1043,1044,1100,1099,0,1044,1045,1101,1100,0,1045,1046,1102,1101,0,1046,1047,1103,1102,0,1047,1048,1104,1103,0,1048,1049,1105,1104,0,1049,1050,1106,1105,0,1050,1051,1107,1106,0,1051,1052,1108,1107,0,1052,1053,1109,1108,0,1053,1054,1110,1109,0,1054,1055,1111,1110,0,1055,1056,1112,1111,0,1056,1057,1113,1112,0,1057,1058,1114,1113,0,1058,1059,1115,1114,0,1059,1060,1116,1115,0,1060,1061,1117,1116,0,1061,1062,1118,1117,0,1062,1063,1119,1118,0,1063,1064,1120,1119,0,1064,1065,1121,1120,0,1065,1066,1122,1121,0,1066,1067,1123,1122,0,1067,1068,1124,1123,0,1068,1069,1125,1124,0,1069,1070,1126,1125,0,1070,1071,1127,1126,0,1071,1072,1128,1127,0,1072,1073,1129,1128,0,1073,1074,1130,1129,0,1074,1075,1131,1130,0,1075,1076,1132,1131,0,1076,1077,1133,1132,0,1077,1078,1134,1133,0,1078,1079,1135,1134,0,1079,1080,1136,1135,0,1080,1081,1137,1136,0,1081,1082,1138,1137,0,1082,1083,1139,1138,0,1083,1084,1140,1139,0,1084,1085,1141,1140,0,1085,1086,1142,1141,0,1086,1087,1143,1142,0,1087,1088,1144,1143,0,1088,469,473,1144,0,961,1089,1145,964,0,1089,1090,1146,1145,0,1090,1091,1147,1146,0,1091,1092,1148,1147,0,1092,1093,1149,1148,0,1093,1094,1150,1149,0,1094,1095,1151,1150,0,1095,1096,1152,1151,0,1096,1097,1153,1152,0,1097,1098,1154,1153,0,1098,1099,1155,1154,0,1099,1100,1156,1155,0,1100,1101,1157,1156,0,1101,1102,1158,1157,0,1102,1103,1159,1158,0,1103,1104,1160,1159,0,1104,1105,1161,1160,0,1105,1106,1162,1161,0,1106,1107,1163,1162,0,1107,1108,1164,1163,0,1108,1109,1165,1164,0,1109,1110,1166,1165,0,1110,1111,1167,1166,0,1111,1112,1168,1167,0,1112,1113,1169,1168,0,1113,1114,1170,1169,0,1114,1115,1171,1170,0,1115,1116,1172,1171,0,1116,1117,1173,1172,0,1117,1118,1174,1173,0,1118,1119,1175,1174,0,1119,1120,1176,1175,0,1120,1121,1177,1176,0,1121,1122,1178,1177,0,1122,1123,1179,1178,0,1123,1124,1180,1179,0,1124,1125,1181,1180,0,1125,1126,1182,1181,0,1126,1127,1183,1182,0,1127,1128,1184,1183,0,1128,1129,1185,1184,0,1129,1130,1186,1185,0,1130,1131,1187,1186,0,1131,1132,1188,1187,0,1132,1133,1189,1188,0,1133,1134,1190,1189,0,1134,1135,1191,1190,0,1135,1136,1192,1191,0,1136,1137,1193,1192,0,1137,1138,1194,1193,0,1138,1139,1195,1194,0,1139,1140,1196,1195,0,1140,1141,1197,1196,0,1141,1142,1198,1197,0,1142,1143,1199,1198,0,1143,1144,1200,1199,0,1144,473,477,1200,0,964,1145,1201,967,0,1145,1146,1202,1201,0,1146,1147,1203,1202,0,1147,1148,1204,1203,0,1148,1149,1205,1204,0,1149,1150,1206,1205,0,1150,1151,1207,1206,0,1151,1152,1208,1207,0,1152,1153,1209,1208,0,1153,1154,1210,1209,0,1154,1155,1211,1210,0,1155,1156,1212,1211,0,1156,1157,1213,1212,0,1157,1158,1214,1213,0,1158,1159,1215,1214,0,1159,1160,1216,1215,0,1160,1161,1217,1216,0,1161,1162,1218,1217,0,1162,1163,1219,1218,0,1163,1164,1220,1219,0,1164,1165,1221,1220,0,1165,1166,1222,1221,0,1166,1167,1223,1222,0,1167,1168,1224,1223,0,1168,1169,1225,1224,0,1169,1170,1226,1225,0,1170,1171,1227,1226,0,1171,1172,1228,1227,0,1172,1173,1229,1228,0,1173,1174,1230,1229,0,1174,1175,1231,1230,0,1175,1176,1232,1231,0,1176,1177,1233,1232,0,1177,1178,1234,1233,0,1178,1179,1235,1234,0,1179,1180,1236,1235,0,1180,1181,1237,1236,0,1181,1182,1238,1237,0,1182,1183,1239,1238,0,1183,1184,1240,1239,0,1184,1185,1241,1240,0,1185,1186,1242,1241,0,1186,1187,1243,1242,0,1187,1188,1244,1243,0,1188,1189,1245,1244,0,1189,1190,1246,1245,0,1190,1191,1247,1246,0,1191,1192,1248,1247,0,1192,1193,1249,1248,0,1193,1194,1250,1249,0,1194,1195,1251,1250,0,1195,1196,1252,1251,0,1196,1197,1253,1252,0,1197,1198,1254,1253,0,1198,1199,1255,1254,0,1199,1200,1256,1255,0,1200,477,481,1256,0,967,1201,1257,970,0,1201,1202,1258,1257,0,1202,1203,1259,1258,0,1203,1204,1260,1259,0,1204,1205,1261,1260,0,1205,1206,1262,1261,0,1206,1207,1263,1262,0,1207,1208,1264,1263,0,1208,1209,1265,1264,0,1209,1210,1266,1265,0,1210,1211,1267,1266,0,1211,1212,1268,1267,0,1212,1213,1269,1268,0,1213,1214,1270,1269,0,1214,1215,1271,1270,0,1215,1216,1272,1271,0,1216,1217,1273,1272,0,1217,1218,1274,1273,0,1218,1219,1275,1274,0,1219,1220,1276,1275,0,1220,1221,1277,1276,0,1221,1222,1278,1277,0,1222,1223,1279,1278,0,1223,1224,1280,1279,0,1224,1225,1281,1280,0,1225,1226,1282,1281,0,1226,1227,1283,1282,0,1227,1228,1284,1283,0,1228,1229,1285,1284,0,1229,1230,1286,1285,0,1230,1231,1287,1286,0,1231,1232,1288,1287,0,1232,1233,1289,1288,0,1233,1234,1290,1289,0,1234,1235,1291,1290,0,1235,1236,1292,1291,0,1236,1237,1293,1292,0,1237,1238,1294,1293,0,1238,1239,1295,1294,0,1239,1240,1296,1295,0,1240,1241,1297,1296,0,1241,1242,1298,1297,0,1242,1243,1299,1298,0,1243,1244,1300,1299,0,1244,1245,1301,1300,0,1245,1246,1302,1301,0,1246,1247,1303,1302,0,1247,1248,1304,1303,0,1248,1249,1305,1304,0,1249,1250,1306,1305,0,1250,1251,1307,1306,0,1251,1252,1308,1307,0,1252,1253,1309,1308,0,1253,1254,1310,1309,0,1254,1255,1311,1310,0,1255,1256,1312,1311,0,1256,481,485,1312,0,970,1257,1313,973,0,1257,1258,1314,1313,0,1258,1259,1315,1314,0,1259,1260,1316,1315,0,1260,1261,1317,1316,0,1261,1262,1318,1317,0,1262,1263,1319,1318,0,1263,1264,1320,1319,0,1264,1265,1321,1320,0,1265,1266,1322,1321,0,1266,1267,1323,1322,0,1267,1268,1324,1323,0,1268,1269,1325,1324,0,1269,1270,1326,1325,0,1270,1271,1327,1326,0,1271,1272,1328,1327,0,1272,1273,1329,1328,0,1273,1274,1330,1329,0,1274,1275,1331,1330,0,1275,1276,1332,1331,0,1276,1277,1333,1332,0,1277,1278,1334,1333,0,1278,1279,1335,1334,0,1279,1280,1336,1335,0,1280,1281,1337,1336,0,1281,1282,1338,1337,0,1282,1283,1339,1338,0,1283,1284,1340,1339,0,1284,1285,1341,1340,0,1285,1286,1342,1341,0,1286,1287,1343,1342,0,1287,1288,1344,1343,0,1288,1289,1345,1344,0,1289,1290,1346,1345,0,1290,1291,1347,1346,0,1291,1292,1348,1347,0,1292,1293,1349,1348,0,1293,1294,1350,1349,0,1294,1295,1351,1350,0,1295,1296,1352,1351,0,1296,1297,1353,1352,0,1297,1298,1354,1353,0,1298,1299,1355,1354,0,1299,1300,1356,1355,0,1300,1301,1357,1356,0,1301,1302,1358,1357,0,1302,1303,1359,1358,0,1303,1304,1360,1359,0,1304,1305,1361,1360,0,1305,1306,1362,1361,0,1306,1307,1363,1362,0,1307,1308,1364,1363,0,1308,1309,1365,1364,0,1309,1310,1366,1365,0,1310,1311,1367,1366,0,1311,1312,1368,1367,0,1312,485,489,1368,0,973,1313,1369,976,0,1313,1314,1370,1369,0,1314,1315,1371,1370,0,1315,1316,1372,1371,0,1316,1317,1373,1372,0,1317,1318,1374,1373,0,1318,1319,1375,1374,0,1319,1320,1376,1375,0,1320,1321,1377,1376,0,1321,1322,1378,1377,0,1322,1323,1379,1378,0,1323,1324,1380,1379,0,1324,1325,1381,1380,0,1325,1326,1382,1381,0,1326,1327,1383,1382,0,1327,1328,1384,1383,0,1328,1329,1385,1384,0,1329,1330,1386,1385,0,1330,1331,1387,1386,0,1331,1332,1388,1387,0,1332,1333,1389,1388,0,1333,1334,1390,1389,0,1334,1335,1391,1390,0,1335,1336,1392,1391,0,1336,1337,1393,1392,0,1337,1338,1394,1393,0,1338,1339,1395,1394,0,1339,1340,1396,1395,0,1340,1341,1397,1396,0,1341,1342,1398,1397,0,1342,1343,1399,1398,0,1343,1344,1400,1399,0,1344,1345,1401,1400,0,1345,1346,1402,1401,0,1346,1347,1403,1402,0,1347,1348,1404,1403,0,1348,1349,1405,1404,0,1349,1350,1406,1405,0,1350,1351,1407,1406,0,1351,1352,1408,1407,0,1352,1353,1409,1408,0,1353,1354,1410,1409,0,1354,1355,1411,1410,0,1355,1356,1412,1411,0,1356,1357,1413,1412,0,1357,1358,1414,1413,0,1358,1359,1415,1414,0,1359,1360,1416,1415,0,1360,1361,1417,1416,0,1361,1362,1418,1417,0,1362,1363,1419,1418,0,1363,1364,1420,1419,0,1364,1365,1421,1420,0,1365,1366,1422,1421,0,1366,1367,1423,1422,0,1367,1368,1424,1423,0,1368,489,493,1424,0,976,1369,457,461,0,1369,1370,453,457,0,1370,1371,449,453,0,1371,1372,445,449,0,1372,1373,441,445,0,1373,1374,437,441,0,1374,1375,433,437,0,1375,1376,429,433,0,1376,1377,425,429,0,1377,1378,421,425,0,1378,1379,417,421,0,1379,1380,413,417,0,1380,1381,409,413,0,1381,1382,405,409,0,1382,1383,401,405,0,1383,1384,397,401,0,1384,1385,393,397,0,1385,1386,389,393,0,1386,1387,385,389,0,1387,1388,381,385,0,1388,1389,377,381,0,1389,1390,373,377,0,1390,1391,369,373,0,1391,1392,365,369,0,1392,1393,361,365,0,1393,1394,357,361,0,1394,1395,353,357,0,1395,1396,349,353,0,1396,1397,345,349,0,1397,1398,341,345,0,1398,1399,337,341,0,1399,1400,333,337,0,1400,1401,329,333,0,1401,1402,325,329,0,1402,1403,321,325,0,1403,1404,317,321,0,1404,1405,313,317,0,1405,1406,309,313,0,1406,1407,305,309,0,1407,1408,301,305,0,1408,1409,297,301,0,1409,1410,293,297,0,1410,1411,289,293,0,1411,1412,285,289,0,1412,1413,281,285,0,1413,1414,277,281,0,1414,1415,273,277,0,1415,1416,269,273,0,1416,1417,265,269,0,1417,1418,261,265,0,1418,1419,257,261,0,1419,1420,253,257,0,1420,1421,249,253,0,1421,1422,245,249,0,1422,1423,241,245,0,1423,1424,237,241,0,1424,493,233,237,0]}}'; + '{"indexedMesh":{"auxData":{"channels":[{"data":[{"input":0.0,"values":[0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00011059328906447410,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447519,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,0.0,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447519,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,0.0,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315]},{"input":1.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]},{"input":2.0,"values":[0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00011059328906447410,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447519,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,0.0,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178324,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178315,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0063520763664486083,0.0,0.0,-0.0063520763664486066,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0061712917137859737,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953224,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0059909539026953181,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696382,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0058111746435696356,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019223,0.0,0.0,-0.0056320656468019197,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0054537386227851634,0.0,0.0,-0.0054537386227851599,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.005276305281912360,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765124,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0050998773345765089,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0049245664911706025,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0047504844620876356,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.00457774295772060,0.0,0.0,-0.0045777429577205982,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0044064536884624904,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063081,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0042367283647063055,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0040686786968450357,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716805,0.0,0.0,-0.0039024163952716771,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792253,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0037380531703792223,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606708,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0035757007325606669,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0034154707922090079,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0032574750597172356,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783489,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0031018252454783450,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853367,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0029486330598853337,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311948,0.0,0.0,-0.0027980102133311926,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089221,0.0,0.0,-0.002650068416208920,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0025049193789115050,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319480,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0023626748118319449,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0022234464253632373,0.0,0.0,-0.0022234464253632360,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0020873459298983705,0.0,0.0,-0.0020873459298983688,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303445,0.0,0.0,-0.0019544850358303428,0.0,0.0,-0.0019544850358303410,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521487,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0018249754535521454,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567801,0.0,0.0,-0.0016989288934567790,0.0,0.0,-0.0016989288934567775,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372321,0.0,0.0,-0.0015764570659372310,0.0,0.0,-0.0015764570659372293,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813865017,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0014576716813864991,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975806,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0013426844501975782,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.0012316070827634625,0.0,0.0,-0.0012316070827634612,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771453,0.0,0.0,-0.0011245512894771446,0.0,0.0,-0.0011245512894771431,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316220,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0010216287807316199,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988602,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.00092295126691988385,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843493174,0.0,0.0,-0.00082863045843493098,0.0,0.0,-0.00082863045843492990,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975484,0.0,0.0,-0.00073877806566975419,0.0,0.0,-0.00073877806566975278,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734889,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00065350579901734705,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070856,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00057292536887070672,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282764,0.0,0.0,-0.00049714848562282732,0.0,0.0,-0.00049714848562282601,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966670176,0.0,0.0,-0.00042628685966670122,0.0,0.0,-0.00042628685966670024,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532455,0.0,0.0,-0.00036045220139532418,0.0,0.0,-0.00036045220139532315,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120169063,0.0,0.0,-0.00029975622120169025,0.0,0.0,-0.00029975622120168938,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00024431062947879355,0.0,0.0,-0.00024431062947879285,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962975,0.0,0.0,-0.00019422713661962942,0.0,0.0,-0.00019422713661962877,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719201,0.0,0.0,-0.00014961745301719174,0.0,0.0,-0.00014961745301719112,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447519,0.0,0.0,-0.00011059328906447490,0.0,0.0,-0.00011059328906447439,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154473622e-05,0.0,0.0,-7.7266355154473378e-05,0.0,0.0,-7.7266355154472958e-05,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680181619e-05,0.0,0.0,-4.9748361680181429e-05,0.0,0.0,-4.9748361680181070e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593944e-05,0.0,0.0,-2.8151019034593812e-05,0.0,0.0,-2.8151019034593544e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704854e-05,0.0,0.0,-1.2586037610704762e-05,0.0,0.0,-1.2586037610704584e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015087322e-06,0.0,0.0,-3.1651278015086856e-06,0.0,0.0,-3.1651278015085945e-06,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-1.4955765638266479e-33,0.0,0.0,-1.6617517375851644e-34,0.0,0.0,0.0,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0068959942699384335,0.0,0.0,-0.006895994269938430,0.0,0.0,-0.0068959942699384292,0.0,0.0,-0.0068959942699384274,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-0.0067145393549178280,0.0,0.0,-0.0065331961502902219,0.0,0.0,-0.0063520763664486040,0.0,0.0,-0.0061712917137859702,0.0,0.0,-0.0059909539026953163,0.0,0.0,-0.0058111746435696339,0.0,0.0,-0.0056320656468019153,0.0,0.0,-0.0054537386227851590,0.0,0.0,-0.0052763052819123574,0.0,0.0,-0.0050998773345765072,0.0,0.0,-0.0049245664911706007,0.0,0.0,-0.0047504844620876330,0.0,0.0,-0.0045777429577205965,0.0,0.0,-0.0044064536884624887,0.0,0.0,-0.0042367283647063037,0.0,0.0,-0.0040686786968450331,0.0,0.0,-0.0039024163952716749,0.0,0.0,-0.0037380531703792201,0.0,0.0,-0.0035757007325606660,0.0,0.0,-0.0034154707922090062,0.0,0.0,-0.0032574750597172335,0.0,0.0,-0.0031018252454783433,0.0,0.0,-0.0029486330598853328,0.0,0.0,-0.0027980102133311909,0.0,0.0,-0.0026500684162089178,0.0,0.0,-0.0025049193789115033,0.0,0.0,-0.0023626748118319441,0.0,0.0,-0.0022234464253632342,0.0,0.0,-0.0020873459298983675,0.0,0.0,-0.0019544850358303406,0.0,0.0,-0.0018249754535521452,0.0,0.0,-0.0016989288934567762,0.0,0.0,-0.0015764570659372282,0.0,0.0,-0.0014576716813864982,0.0,0.0,-0.0013426844501975774,0.0,0.0,-0.0012316070827634602,0.0,0.0,-0.0011245512894771422,0.0,0.0,-0.0010216287807316190,0.0,0.0,-0.00092295126691988331,0.0,0.0,-0.00082863045843492925,0.0,0.0,-0.00073877806566975224,0.0,0.0,-0.00065350579901734640,0.0,0.0,-0.00057292536887070629,0.0,0.0,-0.00049714848562282558,0.0,0.0,-0.00042628685966669970,0.0,0.0,-0.00036045220139532277,0.0,0.0,-0.00029975622120168895,0.0,0.0,-0.00024431062947879252,0.0,0.0,-0.00019422713661962839,0.0,0.0,-0.00014961745301719082,0.0,0.0,-0.00011059328906447410,0.0,0.0,-7.7266355154472741e-05,0.0,0.0,-4.9748361680180900e-05,0.0,0.0,-2.8151019034593412e-05,0.0,0.0,-1.2586037610704493e-05,0.0,0.0,-3.1651278015085488e-06,0.0,0.0,0.0,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.0005653933544613e-34,0.0,0.0,-1.1724762015676572e-33,0.0,0.0,-2.6588027801362626e-33,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315,0.0,0.0,-3.1651278015086974e-06,0.0,0.0,-1.2586037610704798e-05,0.0,0.0,-2.8151019034593917e-05,0.0,0.0,-4.9748361680181585e-05,0.0,0.0,-7.7266355154473405e-05,0.0,0.0,-0.0001105932890644750,0.0,0.0,-0.00014961745301719190,0.0,0.0,-0.00019422713661962961,0.0,0.0,-0.00024431062947879404,0.0,0.0,-0.00029975622120169035,0.0,0.0,-0.00036045220139532428,0.0,0.0,-0.00042628685966670154,0.0,0.0,-0.00049714848562282753,0.0,0.0,-0.00057292536887070791,0.0,0.0,-0.00065350579901734835,0.0,0.0,-0.00073877806566975451,0.0,0.0,-0.00082863045843493120,0.0,0.0,-0.00092295126691988548,0.0,0.0,-0.0010216287807316216,0.0,0.0,-0.0011245512894771455,0.0,0.0,-0.0012316070827634632,0.0,0.0,-0.001342684450197580,0.0,0.0,-0.0014576716813865004,0.0,0.0,-0.0015764570659372325,0.0,0.0,-0.0016989288934567792,0.0,0.0,-0.0018249754535521480,0.0,0.0,-0.0019544850358303436,0.0,0.0,-0.0020873459298983714,0.0,0.0,-0.0022234464253632381,0.0,0.0,-0.0023626748118319471,0.0,0.0,-0.0025049193789115063,0.0,0.0,-0.0026500684162089208,0.0,0.0,-0.0027980102133311965,0.0,0.0,-0.0029486330598853354,0.0,0.0,-0.0031018252454783472,0.0,0.0,-0.0032574750597172369,0.0,0.0,-0.0034154707922090105,0.0,0.0,-0.0035757007325606695,0.0,0.0,-0.0037380531703792236,0.0,0.0,-0.0039024163952716784,0.0,0.0,-0.0040686786968450383,0.0,0.0,-0.0042367283647063072,0.0,0.0,-0.0044064536884624930,0.0,0.0,-0.0045777429577206017,0.0,0.0,-0.0047504844620876374,0.0,0.0,-0.0049245664911706042,0.0,0.0,-0.0050998773345765115,0.0,0.0,-0.0052763052819123635,0.0,0.0,-0.0054537386227851660,0.0,0.0,-0.0056320656468019205,0.0,0.0,-0.0058111746435696365,0.0,0.0,-0.0059909539026953198,0.0,0.0,-0.0061712917137859754,0.0,0.0,-0.0063520763664486118,0.0,0.0,-0.0065331961502902280,0.0,0.0,-0.0067145393549178315]}],"dataType":2,"inputName":"","name":"Displacement"},{"data":[{"input":0.0,"values":[3.5242919693700969e-12,2.3495279795800647e-12,1.1747639897900324e-12,0.0,132.16648443993822,132.16648443993705,132.16648443993589,132.16648443993469,264.33296887987410,264.33296887987291,264.33296887987058,264.33296887986938,396.49945331980996,396.49945331980882,396.49945331980643,396.49945331980530,528.66593775974468,528.66593775974354,528.66593775974115,528.66593775974115,660.83242219967940,660.83242219967826,660.83242219967701,660.83242219967588,792.99890663961412,792.99890663961287,792.99890663961173,792.99890663961060,925.16539107954986,925.16539107954986,925.16539107954759,925.16539107954520,1057.3318755194857,1057.3318755194846,1057.3318755194823,1057.3318755194809,1189.4983599594204,1189.4983599594193,1189.4983599594170,1189.4983599594170,1321.6648443993552,1321.6648443993540,1321.6648443993529,1321.6648443993518,1453.8313288392910,1453.8313288392887,1453.8313288392874,1453.8313288392874,1585.9978132792257,1585.9978132792257,1585.9978132792235,1585.9978132792221,1718.1642977191616,1718.1642977191605,1718.1642977191582,1718.1642977191568,1850.3307821590963,1850.3307821590952,1850.3307821590929,1850.3307821590929,1982.4972665990308,1982.4972665990299,1982.4972665990288,1982.4972665990274,2114.6637510389669,2114.6637510389646,2114.6637510389633,2114.6637510389633,2246.8302354789012,2246.8302354789012,2246.8302354788989,2246.8302354788971,2378.9967199188368,2378.9967199188354,2378.9967199188341,2378.9967199188336,2511.1632043587720,2511.1632043587711,2511.1632043587692,2511.1632043587679,2643.3296887987067,2643.3296887987067,2643.3296887987049,2643.3296887987035,2775.4961732386428,2775.4961732386409,2775.4961732386391,2775.4961732386391,2907.6626576785779,2907.6626576785770,2907.6626576785748,2907.6626576785739,3039.8291421185127,3039.8291421185113,3039.8291421185099,3039.8291421185090,3171.9956265584483,3171.9956265584469,3171.9956265584451,3171.9956265584451,3304.1621109983826,3304.1621109983826,3304.1621109983807,3304.1621109983785,3436.3285954383186,3436.3285954383164,3436.3285954383150,3436.3285954383150,3568.4950798782538,3568.4950798782529,3568.4950798782506,3568.4950798782497,3700.6615643181885,3700.6615643181872,3700.6615643181858,3700.6615643181849,3832.8280487581242,3832.8280487581233,3832.8280487581219,3832.8280487581210,3964.9945331980593,3964.9945331980575,3964.9945331980557,3964.9945331980548,4097.1610176379945,4097.1610176379936,4097.1610176379909,4097.161017637990,4229.3275020779301,4229.3275020779283,4229.3275020779265,4229.3275020779256,4361.4939865178658,4361.4939865178640,4361.4939865178621,4361.4939865178612,4493.6604709577987,4493.6604709577978,4493.6604709577960,4493.6604709577960,4625.8269553977343,4625.8269553977325,4625.8269553977316,4625.8269553977307,4757.9934398376699,4757.9934398376690,4757.9934398376672,4757.9934398376672,4890.1599242776065,4890.1599242776056,4890.1599242776028,4890.1599242776028,5022.3264087175403,5022.3264087175394,5022.3264087175367,5022.3264087175357,5154.4928931574750,5154.4928931574741,5154.4928931574714,5154.4928931574714,5286.6593775974115,5286.6593775974097,5286.6593775974079,5286.6593775974079,5418.8258620373454,5418.8258620373454,5418.8258620373426,5418.8258620373426,5550.9923464772810,5550.9923464772810,5550.9923464772783,5550.9923464772774,5683.1588309172166,5683.1588309172157,5683.1588309172130,5683.1588309172112,5815.3253153571522,5815.3253153571513,5815.3253153571486,5815.3253153571477,5947.4917997970870,5947.4917997970861,5947.4917997970833,5947.4917997970833,6079.6582842370217,6079.6582842370208,6079.6582842370199,6079.6582842370181,6211.8247686769564,6211.8247686769555,6211.8247686769546,6211.8247686769528,6343.9912531168929,6343.9912531168911,6343.9912531168902,6343.9912531168884,6476.1577375568268,6476.1577375568268,6476.1577375568249,6476.1577375568231,6608.3242219967633,6608.3242219967615,6608.3242219967588,6608.3242219967588,6740.4907064366971,6740.4907064366962,6740.4907064366944,6740.4907064366944,6872.6571908766327,6872.6571908766318,6872.657190876630,6872.6571908766291,7004.8236753165684,7004.8236753165675,7004.8236753165656,7004.8236753165647,7136.9901597565040,7136.9901597565031,7136.9901597565004,7136.9901597564995,7269.1566441964387,7269.1566441964378,7269.1566441964351,7269.1566441964342,7401.3231286363734,7401.3231286363716,7401.3231286363716,7401.3231286363698,7533.4896130763082,7533.4896130763082,7533.4896130763073,7533.4896130763054,-0.0,-1.1747639897900324e-12,-2.3495279795800647e-12,-3.5242919693700969e-12,-132.16648443993469,-132.16648443993589,-132.16648443993705,-132.16648443993822,-264.33296887986938,-264.33296887987058,-264.33296887987291,-264.33296887987410,-396.49945331980530,-396.49945331980643,-396.49945331980882,-396.49945331980996,-528.66593775974115,-528.66593775974115,-528.66593775974354,-528.66593775974468,-660.83242219967588,-660.83242219967701,-660.83242219967826,-660.83242219967940,-792.99890663961060,-792.99890663961173,-792.99890663961287,-792.99890663961412,-925.16539107954520,-925.16539107954759,-925.16539107954986,-925.16539107954986,-1057.3318755194809,-1057.3318755194823,-1057.3318755194846,-1057.3318755194857,-1189.4983599594170,-1189.4983599594170,-1189.4983599594193,-1189.4983599594204,-1321.6648443993518,-1321.6648443993529,-1321.6648443993540,-1321.6648443993552,-1453.8313288392874,-1453.8313288392874,-1453.8313288392887,-1453.8313288392910,-1585.9978132792221,-1585.9978132792235,-1585.9978132792257,-1585.9978132792257,-1718.1642977191568,-1718.1642977191582,-1718.1642977191605,-1718.1642977191616,-1850.3307821590929,-1850.3307821590929,-1850.3307821590952,-1850.3307821590963,-1982.4972665990274,-1982.4972665990288,-1982.4972665990299,-1982.4972665990308,-2114.6637510389633,-2114.6637510389633,-2114.6637510389646,-2114.6637510389669,-2246.8302354788971,-2246.8302354788989,-2246.8302354789012,-2246.8302354789012,-2378.9967199188336,-2378.9967199188341,-2378.9967199188354,-2378.9967199188368,-2511.1632043587679,-2511.1632043587692,-2511.1632043587711,-2511.1632043587720,-2643.3296887987035,-2643.3296887987049,-2643.3296887987067,-2643.3296887987067,-2775.4961732386391,-2775.4961732386391,-2775.4961732386409,-2775.4961732386428,-2907.6626576785739,-2907.6626576785748,-2907.6626576785770,-2907.6626576785779,-3039.8291421185090,-3039.8291421185099,-3039.8291421185113,-3039.8291421185127,-3171.9956265584451,-3171.9956265584451,-3171.9956265584469,-3171.9956265584483,-3304.1621109983785,-3304.1621109983807,-3304.1621109983826,-3304.1621109983826,-3436.3285954383150,-3436.3285954383150,-3436.3285954383164,-3436.3285954383186,-3568.4950798782497,-3568.4950798782506,-3568.4950798782529,-3568.4950798782538,-3700.6615643181849,-3700.6615643181858,-3700.6615643181872,-3700.6615643181885,-3832.8280487581210,-3832.8280487581219,-3832.8280487581233,-3832.8280487581242,-3964.9945331980548,-3964.9945331980557,-3964.9945331980575,-3964.9945331980593,-4097.161017637990,-4097.1610176379909,-4097.1610176379936,-4097.1610176379945,-4229.3275020779256,-4229.3275020779265,-4229.3275020779283,-4229.3275020779301,-4361.4939865178612,-4361.4939865178621,-4361.4939865178640,-4361.4939865178658,-4493.6604709577960,-4493.6604709577960,-4493.6604709577978,-4493.6604709577987,-4625.8269553977307,-4625.8269553977316,-4625.8269553977325,-4625.8269553977343,-4757.9934398376672,-4757.9934398376672,-4757.9934398376690,-4757.9934398376699,-4890.1599242776028,-4890.1599242776028,-4890.1599242776056,-4890.1599242776065,-5022.3264087175357,-5022.3264087175367,-5022.3264087175394,-5022.3264087175403,-5154.4928931574714,-5154.4928931574714,-5154.4928931574741,-5154.4928931574750,-5286.6593775974079,-5286.6593775974079,-5286.6593775974097,-5286.6593775974115,-5418.8258620373426,-5418.8258620373426,-5418.8258620373454,-5418.8258620373454,-5550.9923464772774,-5550.9923464772783,-5550.9923464772810,-5550.9923464772810,-5683.1588309172112,-5683.1588309172130,-5683.1588309172157,-5683.1588309172166,-5815.3253153571477,-5815.3253153571486,-5815.3253153571513,-5815.3253153571522,-5947.4917997970833,-5947.4917997970833,-5947.4917997970861,-5947.4917997970870,-6079.6582842370181,-6079.6582842370199,-6079.6582842370208,-6079.6582842370217,-6211.8247686769528,-6211.8247686769546,-6211.8247686769555,-6211.8247686769564,-6343.9912531168884,-6343.9912531168902,-6343.9912531168911,-6343.9912531168929,-6476.1577375568231,-6476.1577375568249,-6476.1577375568268,-6476.1577375568268,-6608.3242219967588,-6608.3242219967588,-6608.3242219967615,-6608.3242219967633,-6740.4907064366944,-6740.4907064366944,-6740.4907064366962,-6740.4907064366971,-6872.6571908766291,-6872.657190876630,-6872.6571908766318,-6872.6571908766327,-7004.8236753165647,-7004.8236753165656,-7004.8236753165675,-7004.8236753165684,-7136.9901597564995,-7136.9901597565004,-7136.9901597565031,-7136.9901597565040,-7269.1566441964342,-7269.1566441964351,-7269.1566441964378,-7269.1566441964387,-7401.3231286363698,-7401.3231286363716,-7401.3231286363716,-7401.3231286363734,-7533.4896130763054,-7533.4896130763073,-7533.4896130763082,-7533.4896130763082,0.0,9.1370532539224727e-13,1.8274106507844945e-12,2.7411159761767420e-12,0.0,6.5264666099446246e-13,1.3052933219889249e-12,1.9579399829833875e-12,0.0,3.9158799659667746e-13,7.8317599319335492e-13,1.1747639897900322e-12,0.0,1.3052933219889250e-13,2.6105866439778501e-13,3.9158799659667751e-13,-0.0,-1.3052933219889250e-13,-2.6105866439778501e-13,-3.9158799659667751e-13,-0.0,-3.9158799659667746e-13,-7.8317599319335492e-13,-1.1747639897900322e-12,-0.0,-6.5264666099446226e-13,-1.3052933219889245e-12,-1.9579399829833871e-12,-0.0,-9.1370532539224727e-13,-1.8274106507844945e-12,-2.7411159761767420e-12,102.79615456439639,205.59230912879093,308.38846369318549,411.18461825757913,513.98077282197278,616.77692738636642,719.57308195076098,822.36923651515554,925.16539107954918,1027.9615456439428,1130.7577002083374,1233.5538547727310,1336.3500093371256,1439.1461639015192,1541.9423184659129,1644.7384730303074,1747.5346275947006,1850.3307821590952,1953.1269367234893,2055.9230912878829,2158.7192458522777,2261.5154004166716,2364.3115549810655,2467.1077095454593,2569.9038641098532,2672.7000186742471,2775.4961732386414,2878.2923278030348,2981.0884823674296,3083.8846369318230,3186.6807914962169,3289.4769460606112,3392.2731006250060,3495.0692551893985,3597.8654097537928,3700.6615643181876,3803.4577188825820,3906.2538734469754,4009.0500280113697,4111.8461825757640,4214.6423371401570,4317.4384917045509,4420.2346462689457,4523.0308008333404,4625.8269553977334,4728.6231099621273,4831.4192645265211,4934.2154190909159,5037.0115736553089,5139.8077282197037,5242.6038827840976,5345.4000373484914,5448.1961919128853,5550.9923464772810,5653.7885010416740,5756.5846556060678,5859.3808101704617,73.425824688854561,146.85164937770782,220.27747406656110,293.70329875541370,367.12912344426627,440.55494813311890,513.98077282197221,587.40659751082535,660.83242219967804,734.25824688853061,807.68407157738386,881.10989626623643,954.53572095508980,1027.9615456439424,1101.3873703327952,1174.8131950216482,1248.2390197105005,1321.6648443993538,1395.0906690882068,1468.5164937770594,1541.9423184659126,1615.3681431547654,1688.7939678436180,1762.2197925324713,1835.6456172213236,1909.0714419101766,1982.4972665990299,2055.9230912878825,2129.3489159767355,2202.7747406655885,2276.2005653544411,2349.6263900432941,2423.0522147321471,2496.4780394209993,2569.9038641098523,2643.3296887987053,2716.7555134875588,2790.1813381764109,2863.6071628652639,2937.0329875541170,3010.458812242970,3083.8846369318226,3157.3104616206756,3230.7362863095286,3304.1621109983816,3377.5879356872342,3451.0137603760868,3524.4395850649403,3597.8654097537924,3671.2912344426459,3744.7170591314980,3818.1428838203510,3891.5687085092045,3964.9945331980575,4038.4203578869101,4111.8461825757631,4185.2720072646161,44.055494813312762,88.110989626624701,132.16648443993665,176.22197925324821,220.27747406655976,264.33296887987132,308.38846369318327,352.44395850649528,396.49945331980678,440.55494813311833,484.61044294643028,528.66593775974184,572.72143257305379,616.77692738636540,660.83242219967701,704.88791701298885,748.94341182630023,792.99890663961219,837.05440145292403,881.10989626623552,925.16539107954759,969.22088589285931,1013.2763807061709,1057.3318755194828,1101.3873703327940,1145.4428651461060,1189.4983599594177,1233.5538547727294,1277.6093495860414,1321.6648443993529,1365.7203392126644,1409.7758340259766,1453.8313288392885,1497.8868236525996,1541.9423184659113,1585.9978132792232,1630.0533080925352,1674.1088029058465,1718.1642977191582,1762.2197925324704,1806.2752873457819,1850.3307821590934,1894.3862769724051,1938.4417717857175,1982.4972665990288,2026.5527614123405,2070.6082562256520,2114.6637510389642,2158.7192458522754,2202.7747406655876,2246.8302354788989,2290.8857302922106,2334.9412251055223,2378.9967199188345,2423.0522147321462,2467.1077095454575,2511.1632043587697,14.685164937770940,29.370329875541564,44.055494813312215,58.740659751082738,73.425824688853268,88.110989626623791,102.79615456439444,117.48131950216509,132.16648443993563,146.85164937770614,161.53681431547679,176.22197925324733,190.90714419101798,205.59230912878849,220.27747406655902,234.96263900432967,249.64780394210015,264.33296887987075,279.01813381764134,293.70329875541188,308.38846369318253,323.07362863095312,337.75879356872366,352.44395850649425,367.12912344426474,381.81428838203544,396.49945331980598,411.18461825757652,425.86978319534717,440.55494813311765,455.24011307088819,469.92527800865884,484.61044294642954,499.29560788419985,513.98077282197050,528.66593775974115,543.35110269751181,558.03626763528223,572.72143257305277,587.40659751082353,602.09176244859407,616.77692738636460,631.46209232413526,646.14725726190579,660.83242219967633,675.51758713744687,690.20275207521740,704.88791701298805,719.57308195075859,734.25824688852924,748.94341182629978,763.62857676407032,778.31374170184097,792.99890663961162,807.68407157738216,822.36923651515258,837.05440145292323,-14.685164937770889,-29.370329875541564,-44.055494813312215,-58.740659751082738,-73.425824688853268,-88.110989626623791,-102.79615456439444,-117.48131950216509,-132.16648443993563,-146.85164937770614,-161.53681431547679,-176.22197925324733,-190.90714419101798,-205.59230912878849,-220.27747406655902,-234.96263900432967,-249.64780394210015,-264.33296887987075,-279.01813381764134,-293.70329875541188,-308.38846369318253,-323.07362863095312,-337.75879356872366,-352.44395850649425,-367.12912344426474,-381.81428838203544,-396.49945331980598,-411.18461825757652,-425.86978319534717,-440.55494813311765,-455.24011307088819,-469.92527800865884,-484.61044294642954,-499.29560788419985,-513.98077282197050,-528.66593775974115,-543.35110269751181,-558.03626763528223,-572.72143257305277,-587.40659751082353,-602.09176244859407,-616.77692738636460,-631.46209232413526,-646.14725726190579,-660.83242219967633,-675.51758713744687,-690.20275207521740,-704.88791701298805,-719.57308195075859,-734.25824688852924,-748.94341182629978,-763.62857676407032,-778.31374170184097,-792.99890663961162,-807.68407157738216,-822.36923651515258,-837.05440145292323,-44.055494813312691,-88.110989626624701,-132.16648443993665,-176.22197925324821,-220.27747406655976,-264.33296887987132,-308.38846369318327,-352.44395850649528,-396.49945331980678,-440.55494813311833,-484.61044294643028,-528.66593775974184,-572.72143257305379,-616.77692738636540,-660.83242219967701,-704.88791701298885,-748.94341182630023,-792.99890663961219,-837.05440145292403,-881.10989626623552,-925.16539107954759,-969.22088589285931,-1013.2763807061709,-1057.3318755194828,-1101.3873703327940,-1145.4428651461060,-1189.4983599594177,-1233.5538547727294,-1277.6093495860414,-1321.6648443993529,-1365.7203392126644,-1409.7758340259766,-1453.8313288392885,-1497.8868236525996,-1541.9423184659113,-1585.9978132792232,-1630.0533080925352,-1674.1088029058465,-1718.1642977191582,-1762.2197925324704,-1806.2752873457819,-1850.3307821590934,-1894.3862769724051,-1938.4417717857175,-1982.4972665990288,-2026.5527614123405,-2070.6082562256520,-2114.6637510389642,-2158.7192458522754,-2202.7747406655876,-2246.8302354788989,-2290.8857302922106,-2334.9412251055223,-2378.9967199188345,-2423.0522147321462,-2467.1077095454575,-2511.1632043587697,-73.425824688854476,-146.85164937770776,-220.27747406656101,-293.70329875541364,-367.12912344426621,-440.55494813311878,-513.98077282197210,-587.40659751082524,-660.83242219967781,-734.25824688853038,-807.68407157738363,-881.10989626623632,-954.53572095508946,-1027.9615456439419,-1101.3873703327947,-1174.8131950216480,-1248.2390197105001,-1321.6648443993533,-1395.0906690882064,-1468.5164937770589,-1541.9423184659122,-1615.3681431547650,-1688.7939678436176,-1762.2197925324708,-1835.6456172213232,-1909.0714419101764,-1982.4972665990292,-2055.9230912878820,-2129.3489159767350,-2202.7747406655876,-2276.2005653544402,-2349.6263900432932,-2423.0522147321467,-2496.4780394209984,-2569.9038641098518,-2643.3296887987049,-2716.7555134875583,-2790.181338176410,-2863.6071628652630,-2937.0329875541165,-3010.4588122429691,-3083.8846369318217,-3157.3104616206747,-3230.7362863095282,-3304.1621109983807,-3377.5879356872333,-3451.0137603760854,-3524.4395850649389,-3597.8654097537919,-3671.2912344426450,-3744.7170591314975,-3818.1428838203501,-3891.5687085092031,-3964.9945331980566,-4038.4203578869096,-4111.8461825757613,-4185.2720072646152,-102.79615456439635,-205.59230912879093,-308.38846369318549,-411.18461825757913,-513.98077282197278,-616.77692738636642,-719.57308195076098,-822.36923651515554,-925.16539107954918,-1027.9615456439428,-1130.7577002083374,-1233.5538547727310,-1336.3500093371256,-1439.1461639015192,-1541.9423184659129,-1644.7384730303074,-1747.5346275947006,-1850.3307821590952,-1953.1269367234893,-2055.9230912878829,-2158.7192458522777,-2261.5154004166716,-2364.3115549810655,-2467.1077095454593,-2569.9038641098532,-2672.7000186742471,-2775.4961732386414,-2878.2923278030348,-2981.0884823674296,-3083.8846369318230,-3186.6807914962169,-3289.4769460606112,-3392.2731006250060,-3495.0692551893985,-3597.8654097537928,-3700.6615643181876,-3803.4577188825820,-3906.2538734469754,-4009.0500280113697,-4111.8461825757640,-4214.6423371401570,-4317.4384917045509,-4420.2346462689457,-4523.0308008333404,-4625.8269553977334,-4728.6231099621273,-4831.4192645265211,-4934.2154190909159,-5037.0115736553089,-5139.8077282197037,-5242.6038827840976,-5345.4000373484914,-5448.1961919128853,-5550.9923464772810,-5653.7885010416740,-5756.5846556060678,-5859.3808101704617,5859.3808101704608,5859.3808101704599,5859.3808101704590,4185.2720072646152,4185.2720072646152,4185.2720072646143,2511.1632043587692,2511.1632043587688,2511.1632043587683,837.05440145292312,837.0544014529230,837.0544014529230,-837.05440145292312,-837.0544014529230,-837.0544014529230,-2511.1632043587692,-2511.1632043587688,-2511.1632043587683,-4185.2720072646143,-4185.2720072646134,-4185.2720072646125,-5859.3808101704608,-5859.3808101704599,-5859.3808101704590,5756.5846556060651,5653.7885010416712,5550.9923464772764,5448.1961919128835,5345.4000373484896,5242.6038827840948,5139.8077282197009,5037.0115736553080,4934.2154190909132,4831.4192645265193,4728.6231099621245,4625.8269553977316,4523.0308008333368,4420.2346462689429,4317.4384917045491,4214.6423371401552,4111.8461825757613,4009.0500280113665,3906.2538734469731,3803.4577188825788,3700.6615643181849,3597.8654097537906,3495.0692551893972,3392.2731006250024,3289.4769460606090,3186.6807914962146,3083.8846369318208,2981.0884823674269,2878.2923278030325,2775.4961732386387,2672.7000186742448,2569.9038641098505,2467.1077095454561,2364.3115549810627,2261.5154004166693,2158.7192458522745,2055.9230912878797,1953.1269367234868,1850.3307821590929,1747.5346275946983,1644.7384730303047,1541.9423184659111,1439.1461639015165,1336.3500093371219,1233.5538547727283,1130.7577002083347,1027.9615456439410,925.16539107954645,822.36923651515190,719.57308195075825,616.77692738636460,513.98077282197096,411.18461825757635,308.38846369318185,205.59230912878817,102.79615456439456,4111.8461825757604,4038.4203578869087,3964.9945331980548,3891.5687085092022,3818.1428838203501,3744.7170591314966,3671.2912344426441,3597.8654097537915,3524.4395850649380,3451.0137603760854,3377.5879356872324,3304.1621109983794,3230.7362863095263,3157.3104616206738,3083.8846369318212,3010.4588122429677,2937.0329875541156,2863.6071628652621,2790.1813381764096,2716.7555134875565,2643.3296887987040,2569.9038641098505,2496.4780394209979,2423.0522147321449,2349.6263900432918,2276.2005653544393,2202.7747406655863,2129.3489159767337,2055.9230912878802,1982.4972665990279,1909.0714419101751,1835.6456172213220,1762.2197925324688,1688.7939678436164,1615.3681431547639,1541.9423184659106,1468.5164937770573,1395.0906690882050,1321.6648443993520,1248.2390197104990,1174.8131950216462,1101.3873703327936,1027.9615456439403,954.53572095508719,881.10989626623450,807.68407157738193,734.25824688852924,660.83242219967599,587.40659751082285,513.98077282197016,440.55494813311759,367.12912344426502,293.70329875541171,220.27747406655848,146.85164937770585,73.425824688853268,2467.1077095454580,2423.0522147321449,2378.9967199188332,2334.9412251055214,2290.8857302922102,2246.8302354788980,2202.7747406655863,2158.7192458522745,2114.6637510389628,2070.6082562256511,2026.5527614123394,1982.4972665990274,1938.4417717857157,1894.3862769724044,1850.3307821590927,1806.2752873457805,1762.2197925324690,1718.1642977191573,1674.1088029058458,1630.0533080925338,1585.9978132792221,1541.9423184659104,1497.8868236525989,1453.8313288392867,1409.7758340259752,1365.7203392126635,1321.6648443993518,1277.609349586040,1233.5538547727283,1189.4983599594168,1145.4428651461051,1101.3873703327931,1057.3318755194812,1013.2763807061699,969.22088589285829,925.16539107954634,881.10989626623427,837.0544014529230,792.99890663961128,748.94341182629933,704.88791701298771,660.83242219967610,616.77692738636415,572.72143257305231,528.66593775974070,484.61044294642915,440.55494813311759,396.49945331980564,352.44395850649363,308.38846369318208,264.33296887987058,220.27747406655899,176.22197925324704,132.16648443993506,88.110989626623521,44.055494813311952,822.36923651515372,807.68407157738170,792.99890663961105,778.31374170184051,763.62857676406998,748.94341182629944,734.25824688852890,719.57308195075836,704.88791701298771,690.20275207521718,675.51758713744641,660.83242219967599,646.14725726190534,631.46209232413480,616.77692738636426,602.09176244859361,587.40659751082308,572.72143257305254,558.0362676352820,543.35110269751135,528.66593775974070,513.98077282197016,499.29560788419968,484.61044294642903,469.92527800865849,455.24011307088790,440.55494813311731,425.86978319534677,411.18461825757612,396.49945331980558,381.81428838203499,367.12912344426445,352.44395850649374,337.75879356872332,323.07362863095284,308.38846369318213,293.70329875541148,279.01813381764106,264.33296887987046,249.64780394209978,234.96263900432925,220.27747406655877,205.59230912878812,190.90714419101747,176.22197925324693,161.53681431547642,146.85164937770588,132.16648443993523,117.48131950216458,102.79615456439406,88.110989626623535,73.425824688853012,58.740659751082354,44.055494813311697,29.370329875541177,14.685164937770653,-822.36923651515076,-807.68407157738170,-792.99890663961105,-778.31374170184051,-763.62857676406998,-748.94341182629944,-734.25824688852890,-719.57308195075836,-704.88791701298771,-690.20275207521718,-675.51758713744641,-660.83242219967599,-646.14725726190534,-631.46209232413480,-616.77692738636426,-602.09176244859361,-587.40659751082308,-572.72143257305254,-558.0362676352820,-543.35110269751135,-528.66593775974070,-513.98077282197016,-499.29560788419968,-484.61044294642903,-469.92527800865849,-455.24011307088790,-440.55494813311731,-425.86978319534677,-411.18461825757612,-396.49945331980558,-381.81428838203499,-367.12912344426445,-352.44395850649374,-337.75879356872332,-323.07362863095284,-308.38846369318213,-293.70329875541148,-279.01813381764106,-264.33296887987046,-249.64780394209978,-234.96263900432925,-220.27747406655877,-205.59230912878812,-190.90714419101747,-176.22197925324693,-161.53681431547642,-146.85164937770588,-132.16648443993523,-117.48131950216458,-102.79615456439406,-88.110989626623535,-73.425824688853012,-58.740659751082354,-44.055494813311697,-29.370329875541177,-14.685164937770653,-2467.1077095454539,-2423.0522147321449,-2378.9967199188332,-2334.9412251055214,-2290.8857302922102,-2246.8302354788980,-2202.7747406655863,-2158.7192458522745,-2114.6637510389628,-2070.6082562256511,-2026.5527614123394,-1982.4972665990274,-1938.4417717857157,-1894.3862769724044,-1850.3307821590927,-1806.2752873457805,-1762.2197925324690,-1718.1642977191573,-1674.1088029058458,-1630.0533080925338,-1585.9978132792221,-1541.9423184659104,-1497.8868236525989,-1453.8313288392867,-1409.7758340259752,-1365.7203392126635,-1321.6648443993518,-1277.609349586040,-1233.5538547727283,-1189.4983599594168,-1145.4428651461051,-1101.3873703327931,-1057.3318755194812,-1013.2763807061699,-969.22088589285829,-925.16539107954634,-881.10989626623427,-837.0544014529230,-792.99890663961128,-748.94341182629933,-704.88791701298771,-660.83242219967610,-616.77692738636415,-572.72143257305231,-528.66593775974070,-484.61044294642915,-440.55494813311759,-396.49945331980564,-352.44395850649363,-308.38846369318208,-264.33296887987058,-220.27747406655899,-176.22197925324704,-132.16648443993506,-88.110989626623521,-44.055494813311952,-4111.8461825757568,-4038.4203578869069,-3964.9945331980543,-3891.5687085092013,-3818.1428838203487,-3744.7170591314957,-3671.2912344426427,-3597.8654097537906,-3524.4395850649371,-3451.0137603760845,-3377.5879356872310,-3304.1621109983789,-3230.7362863095254,-3157.3104616206729,-3083.8846369318203,-3010.4588122429673,-2937.0329875541147,-2863.6071628652612,-2790.1813381764086,-2716.7555134875556,-2643.3296887987030,-2569.903864109850,-2496.4780394209974,-2423.0522147321440,-2349.6263900432918,-2276.2005653544388,-2202.7747406655853,-2129.3489159767332,-2055.9230912878797,-1982.4972665990274,-1909.0714419101744,-1835.6456172213213,-1762.2197925324681,-1688.7939678436160,-1615.3681431547634,-1541.9423184659101,-1468.5164937770569,-1395.0906690882048,-1321.6648443993518,-1248.2390197104985,-1174.8131950216459,-1101.3873703327934,-1027.9615456439401,-954.53572095508696,-881.10989626623427,-807.68407157738170,-734.25824688852913,-660.83242219967588,-587.40659751082262,-513.98077282197005,-440.55494813311748,-367.12912344426491,-293.70329875541165,-220.27747406655840,-146.85164937770583,-73.425824688853240,-5756.5846556060624,-5653.7885010416712,-5550.9923464772764,-5448.1961919128835,-5345.4000373484896,-5242.6038827840948,-5139.8077282197009,-5037.0115736553080,-4934.2154190909132,-4831.4192645265193,-4728.6231099621245,-4625.8269553977316,-4523.0308008333368,-4420.2346462689429,-4317.4384917045491,-4214.6423371401552,-4111.8461825757613,-4009.0500280113665,-3906.2538734469731,-3803.4577188825788,-3700.6615643181849,-3597.8654097537906,-3495.0692551893972,-3392.2731006250024,-3289.4769460606090,-3186.6807914962146,-3083.8846369318208,-2981.0884823674269,-2878.2923278030325,-2775.4961732386387,-2672.7000186742448,-2569.9038641098505,-2467.1077095454561,-2364.3115549810627,-2261.5154004166693,-2158.7192458522745,-2055.9230912878797,-1953.1269367234868,-1850.3307821590929,-1747.5346275946983,-1644.7384730303047,-1541.9423184659111,-1439.1461639015165,-1336.3500093371219,-1233.5538547727283,-1130.7577002083347,-1027.9615456439410,-925.16539107954645,-822.36923651515190,-719.57308195075825,-616.77692738636460,-513.98077282197096,-411.18461825757635,-308.38846369318185,-205.59230912878817,-102.79615456439456]},{"input":1.0,"values":[0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0]},{"input":2.0,"values":[3.5242919693700969e-12,2.3495279795800647e-12,1.1747639897900324e-12,0.0,132.16648443993822,132.16648443993705,132.16648443993589,132.16648443993469,264.33296887987410,264.33296887987291,264.33296887987058,264.33296887986938,396.49945331980996,396.49945331980882,396.49945331980643,396.49945331980530,528.66593775974468,528.66593775974354,528.66593775974115,528.66593775974115,660.83242219967940,660.83242219967826,660.83242219967701,660.83242219967588,792.99890663961412,792.99890663961287,792.99890663961173,792.99890663961060,925.16539107954986,925.16539107954986,925.16539107954759,925.16539107954520,1057.3318755194857,1057.3318755194846,1057.3318755194823,1057.3318755194809,1189.4983599594204,1189.4983599594193,1189.4983599594170,1189.4983599594170,1321.6648443993552,1321.6648443993540,1321.6648443993529,1321.6648443993518,1453.8313288392910,1453.8313288392887,1453.8313288392874,1453.8313288392874,1585.9978132792257,1585.9978132792257,1585.9978132792235,1585.9978132792221,1718.1642977191616,1718.1642977191605,1718.1642977191582,1718.1642977191568,1850.3307821590963,1850.3307821590952,1850.3307821590929,1850.3307821590929,1982.4972665990308,1982.4972665990299,1982.4972665990288,1982.4972665990274,2114.6637510389669,2114.6637510389646,2114.6637510389633,2114.6637510389633,2246.8302354789012,2246.8302354789012,2246.8302354788989,2246.8302354788971,2378.9967199188368,2378.9967199188354,2378.9967199188341,2378.9967199188336,2511.1632043587720,2511.1632043587711,2511.1632043587692,2511.1632043587679,2643.3296887987067,2643.3296887987067,2643.3296887987049,2643.3296887987035,2775.4961732386428,2775.4961732386409,2775.4961732386391,2775.4961732386391,2907.6626576785779,2907.6626576785770,2907.6626576785748,2907.6626576785739,3039.8291421185127,3039.8291421185113,3039.8291421185099,3039.8291421185090,3171.9956265584483,3171.9956265584469,3171.9956265584451,3171.9956265584451,3304.1621109983826,3304.1621109983826,3304.1621109983807,3304.1621109983785,3436.3285954383186,3436.3285954383164,3436.3285954383150,3436.3285954383150,3568.4950798782538,3568.4950798782529,3568.4950798782506,3568.4950798782497,3700.6615643181885,3700.6615643181872,3700.6615643181858,3700.6615643181849,3832.8280487581242,3832.8280487581233,3832.8280487581219,3832.8280487581210,3964.9945331980593,3964.9945331980575,3964.9945331980557,3964.9945331980548,4097.1610176379945,4097.1610176379936,4097.1610176379909,4097.161017637990,4229.3275020779301,4229.3275020779283,4229.3275020779265,4229.3275020779256,4361.4939865178658,4361.4939865178640,4361.4939865178621,4361.4939865178612,4493.6604709577987,4493.6604709577978,4493.6604709577960,4493.6604709577960,4625.8269553977343,4625.8269553977325,4625.8269553977316,4625.8269553977307,4757.9934398376699,4757.9934398376690,4757.9934398376672,4757.9934398376672,4890.1599242776065,4890.1599242776056,4890.1599242776028,4890.1599242776028,5022.3264087175403,5022.3264087175394,5022.3264087175367,5022.3264087175357,5154.4928931574750,5154.4928931574741,5154.4928931574714,5154.4928931574714,5286.6593775974115,5286.6593775974097,5286.6593775974079,5286.6593775974079,5418.8258620373454,5418.8258620373454,5418.8258620373426,5418.8258620373426,5550.9923464772810,5550.9923464772810,5550.9923464772783,5550.9923464772774,5683.1588309172166,5683.1588309172157,5683.1588309172130,5683.1588309172112,5815.3253153571522,5815.3253153571513,5815.3253153571486,5815.3253153571477,5947.4917997970870,5947.4917997970861,5947.4917997970833,5947.4917997970833,6079.6582842370217,6079.6582842370208,6079.6582842370199,6079.6582842370181,6211.8247686769564,6211.8247686769555,6211.8247686769546,6211.8247686769528,6343.9912531168929,6343.9912531168911,6343.9912531168902,6343.9912531168884,6476.1577375568268,6476.1577375568268,6476.1577375568249,6476.1577375568231,6608.3242219967633,6608.3242219967615,6608.3242219967588,6608.3242219967588,6740.4907064366971,6740.4907064366962,6740.4907064366944,6740.4907064366944,6872.6571908766327,6872.6571908766318,6872.657190876630,6872.6571908766291,7004.8236753165684,7004.8236753165675,7004.8236753165656,7004.8236753165647,7136.9901597565040,7136.9901597565031,7136.9901597565004,7136.9901597564995,7269.1566441964387,7269.1566441964378,7269.1566441964351,7269.1566441964342,7401.3231286363734,7401.3231286363716,7401.3231286363716,7401.3231286363698,7533.4896130763082,7533.4896130763082,7533.4896130763073,7533.4896130763054,-0.0,-1.1747639897900324e-12,-2.3495279795800647e-12,-3.5242919693700969e-12,-132.16648443993469,-132.16648443993589,-132.16648443993705,-132.16648443993822,-264.33296887986938,-264.33296887987058,-264.33296887987291,-264.33296887987410,-396.49945331980530,-396.49945331980643,-396.49945331980882,-396.49945331980996,-528.66593775974115,-528.66593775974115,-528.66593775974354,-528.66593775974468,-660.83242219967588,-660.83242219967701,-660.83242219967826,-660.83242219967940,-792.99890663961060,-792.99890663961173,-792.99890663961287,-792.99890663961412,-925.16539107954520,-925.16539107954759,-925.16539107954986,-925.16539107954986,-1057.3318755194809,-1057.3318755194823,-1057.3318755194846,-1057.3318755194857,-1189.4983599594170,-1189.4983599594170,-1189.4983599594193,-1189.4983599594204,-1321.6648443993518,-1321.6648443993529,-1321.6648443993540,-1321.6648443993552,-1453.8313288392874,-1453.8313288392874,-1453.8313288392887,-1453.8313288392910,-1585.9978132792221,-1585.9978132792235,-1585.9978132792257,-1585.9978132792257,-1718.1642977191568,-1718.1642977191582,-1718.1642977191605,-1718.1642977191616,-1850.3307821590929,-1850.3307821590929,-1850.3307821590952,-1850.3307821590963,-1982.4972665990274,-1982.4972665990288,-1982.4972665990299,-1982.4972665990308,-2114.6637510389633,-2114.6637510389633,-2114.6637510389646,-2114.6637510389669,-2246.8302354788971,-2246.8302354788989,-2246.8302354789012,-2246.8302354789012,-2378.9967199188336,-2378.9967199188341,-2378.9967199188354,-2378.9967199188368,-2511.1632043587679,-2511.1632043587692,-2511.1632043587711,-2511.1632043587720,-2643.3296887987035,-2643.3296887987049,-2643.3296887987067,-2643.3296887987067,-2775.4961732386391,-2775.4961732386391,-2775.4961732386409,-2775.4961732386428,-2907.6626576785739,-2907.6626576785748,-2907.6626576785770,-2907.6626576785779,-3039.8291421185090,-3039.8291421185099,-3039.8291421185113,-3039.8291421185127,-3171.9956265584451,-3171.9956265584451,-3171.9956265584469,-3171.9956265584483,-3304.1621109983785,-3304.1621109983807,-3304.1621109983826,-3304.1621109983826,-3436.3285954383150,-3436.3285954383150,-3436.3285954383164,-3436.3285954383186,-3568.4950798782497,-3568.4950798782506,-3568.4950798782529,-3568.4950798782538,-3700.6615643181849,-3700.6615643181858,-3700.6615643181872,-3700.6615643181885,-3832.8280487581210,-3832.8280487581219,-3832.8280487581233,-3832.8280487581242,-3964.9945331980548,-3964.9945331980557,-3964.9945331980575,-3964.9945331980593,-4097.161017637990,-4097.1610176379909,-4097.1610176379936,-4097.1610176379945,-4229.3275020779256,-4229.3275020779265,-4229.3275020779283,-4229.3275020779301,-4361.4939865178612,-4361.4939865178621,-4361.4939865178640,-4361.4939865178658,-4493.6604709577960,-4493.6604709577960,-4493.6604709577978,-4493.6604709577987,-4625.8269553977307,-4625.8269553977316,-4625.8269553977325,-4625.8269553977343,-4757.9934398376672,-4757.9934398376672,-4757.9934398376690,-4757.9934398376699,-4890.1599242776028,-4890.1599242776028,-4890.1599242776056,-4890.1599242776065,-5022.3264087175357,-5022.3264087175367,-5022.3264087175394,-5022.3264087175403,-5154.4928931574714,-5154.4928931574714,-5154.4928931574741,-5154.4928931574750,-5286.6593775974079,-5286.6593775974079,-5286.6593775974097,-5286.6593775974115,-5418.8258620373426,-5418.8258620373426,-5418.8258620373454,-5418.8258620373454,-5550.9923464772774,-5550.9923464772783,-5550.9923464772810,-5550.9923464772810,-5683.1588309172112,-5683.1588309172130,-5683.1588309172157,-5683.1588309172166,-5815.3253153571477,-5815.3253153571486,-5815.3253153571513,-5815.3253153571522,-5947.4917997970833,-5947.4917997970833,-5947.4917997970861,-5947.4917997970870,-6079.6582842370181,-6079.6582842370199,-6079.6582842370208,-6079.6582842370217,-6211.8247686769528,-6211.8247686769546,-6211.8247686769555,-6211.8247686769564,-6343.9912531168884,-6343.9912531168902,-6343.9912531168911,-6343.9912531168929,-6476.1577375568231,-6476.1577375568249,-6476.1577375568268,-6476.1577375568268,-6608.3242219967588,-6608.3242219967588,-6608.3242219967615,-6608.3242219967633,-6740.4907064366944,-6740.4907064366944,-6740.4907064366962,-6740.4907064366971,-6872.6571908766291,-6872.657190876630,-6872.6571908766318,-6872.6571908766327,-7004.8236753165647,-7004.8236753165656,-7004.8236753165675,-7004.8236753165684,-7136.9901597564995,-7136.9901597565004,-7136.9901597565031,-7136.9901597565040,-7269.1566441964342,-7269.1566441964351,-7269.1566441964378,-7269.1566441964387,-7401.3231286363698,-7401.3231286363716,-7401.3231286363716,-7401.3231286363734,-7533.4896130763054,-7533.4896130763073,-7533.4896130763082,-7533.4896130763082,0.0,9.1370532539224727e-13,1.8274106507844945e-12,2.7411159761767420e-12,0.0,6.5264666099446246e-13,1.3052933219889249e-12,1.9579399829833875e-12,0.0,3.9158799659667746e-13,7.8317599319335492e-13,1.1747639897900322e-12,0.0,1.3052933219889250e-13,2.6105866439778501e-13,3.9158799659667751e-13,-0.0,-1.3052933219889250e-13,-2.6105866439778501e-13,-3.9158799659667751e-13,-0.0,-3.9158799659667746e-13,-7.8317599319335492e-13,-1.1747639897900322e-12,-0.0,-6.5264666099446226e-13,-1.3052933219889245e-12,-1.9579399829833871e-12,-0.0,-9.1370532539224727e-13,-1.8274106507844945e-12,-2.7411159761767420e-12,102.79615456439639,205.59230912879093,308.38846369318549,411.18461825757913,513.98077282197278,616.77692738636642,719.57308195076098,822.36923651515554,925.16539107954918,1027.9615456439428,1130.7577002083374,1233.5538547727310,1336.3500093371256,1439.1461639015192,1541.9423184659129,1644.7384730303074,1747.5346275947006,1850.3307821590952,1953.1269367234893,2055.9230912878829,2158.7192458522777,2261.5154004166716,2364.3115549810655,2467.1077095454593,2569.9038641098532,2672.7000186742471,2775.4961732386414,2878.2923278030348,2981.0884823674296,3083.8846369318230,3186.6807914962169,3289.4769460606112,3392.2731006250060,3495.0692551893985,3597.8654097537928,3700.6615643181876,3803.4577188825820,3906.2538734469754,4009.0500280113697,4111.8461825757640,4214.6423371401570,4317.4384917045509,4420.2346462689457,4523.0308008333404,4625.8269553977334,4728.6231099621273,4831.4192645265211,4934.2154190909159,5037.0115736553089,5139.8077282197037,5242.6038827840976,5345.4000373484914,5448.1961919128853,5550.9923464772810,5653.7885010416740,5756.5846556060678,5859.3808101704617,73.425824688854561,146.85164937770782,220.27747406656110,293.70329875541370,367.12912344426627,440.55494813311890,513.98077282197221,587.40659751082535,660.83242219967804,734.25824688853061,807.68407157738386,881.10989626623643,954.53572095508980,1027.9615456439424,1101.3873703327952,1174.8131950216482,1248.2390197105005,1321.6648443993538,1395.0906690882068,1468.5164937770594,1541.9423184659126,1615.3681431547654,1688.7939678436180,1762.2197925324713,1835.6456172213236,1909.0714419101766,1982.4972665990299,2055.9230912878825,2129.3489159767355,2202.7747406655885,2276.2005653544411,2349.6263900432941,2423.0522147321471,2496.4780394209993,2569.9038641098523,2643.3296887987053,2716.7555134875588,2790.1813381764109,2863.6071628652639,2937.0329875541170,3010.458812242970,3083.8846369318226,3157.3104616206756,3230.7362863095286,3304.1621109983816,3377.5879356872342,3451.0137603760868,3524.4395850649403,3597.8654097537924,3671.2912344426459,3744.7170591314980,3818.1428838203510,3891.5687085092045,3964.9945331980575,4038.4203578869101,4111.8461825757631,4185.2720072646161,44.055494813312762,88.110989626624701,132.16648443993665,176.22197925324821,220.27747406655976,264.33296887987132,308.38846369318327,352.44395850649528,396.49945331980678,440.55494813311833,484.61044294643028,528.66593775974184,572.72143257305379,616.77692738636540,660.83242219967701,704.88791701298885,748.94341182630023,792.99890663961219,837.05440145292403,881.10989626623552,925.16539107954759,969.22088589285931,1013.2763807061709,1057.3318755194828,1101.3873703327940,1145.4428651461060,1189.4983599594177,1233.5538547727294,1277.6093495860414,1321.6648443993529,1365.7203392126644,1409.7758340259766,1453.8313288392885,1497.8868236525996,1541.9423184659113,1585.9978132792232,1630.0533080925352,1674.1088029058465,1718.1642977191582,1762.2197925324704,1806.2752873457819,1850.3307821590934,1894.3862769724051,1938.4417717857175,1982.4972665990288,2026.5527614123405,2070.6082562256520,2114.6637510389642,2158.7192458522754,2202.7747406655876,2246.8302354788989,2290.8857302922106,2334.9412251055223,2378.9967199188345,2423.0522147321462,2467.1077095454575,2511.1632043587697,14.685164937770940,29.370329875541564,44.055494813312215,58.740659751082738,73.425824688853268,88.110989626623791,102.79615456439444,117.48131950216509,132.16648443993563,146.85164937770614,161.53681431547679,176.22197925324733,190.90714419101798,205.59230912878849,220.27747406655902,234.96263900432967,249.64780394210015,264.33296887987075,279.01813381764134,293.70329875541188,308.38846369318253,323.07362863095312,337.75879356872366,352.44395850649425,367.12912344426474,381.81428838203544,396.49945331980598,411.18461825757652,425.86978319534717,440.55494813311765,455.24011307088819,469.92527800865884,484.61044294642954,499.29560788419985,513.98077282197050,528.66593775974115,543.35110269751181,558.03626763528223,572.72143257305277,587.40659751082353,602.09176244859407,616.77692738636460,631.46209232413526,646.14725726190579,660.83242219967633,675.51758713744687,690.20275207521740,704.88791701298805,719.57308195075859,734.25824688852924,748.94341182629978,763.62857676407032,778.31374170184097,792.99890663961162,807.68407157738216,822.36923651515258,837.05440145292323,-14.685164937770889,-29.370329875541564,-44.055494813312215,-58.740659751082738,-73.425824688853268,-88.110989626623791,-102.79615456439444,-117.48131950216509,-132.16648443993563,-146.85164937770614,-161.53681431547679,-176.22197925324733,-190.90714419101798,-205.59230912878849,-220.27747406655902,-234.96263900432967,-249.64780394210015,-264.33296887987075,-279.01813381764134,-293.70329875541188,-308.38846369318253,-323.07362863095312,-337.75879356872366,-352.44395850649425,-367.12912344426474,-381.81428838203544,-396.49945331980598,-411.18461825757652,-425.86978319534717,-440.55494813311765,-455.24011307088819,-469.92527800865884,-484.61044294642954,-499.29560788419985,-513.98077282197050,-528.66593775974115,-543.35110269751181,-558.03626763528223,-572.72143257305277,-587.40659751082353,-602.09176244859407,-616.77692738636460,-631.46209232413526,-646.14725726190579,-660.83242219967633,-675.51758713744687,-690.20275207521740,-704.88791701298805,-719.57308195075859,-734.25824688852924,-748.94341182629978,-763.62857676407032,-778.31374170184097,-792.99890663961162,-807.68407157738216,-822.36923651515258,-837.05440145292323,-44.055494813312691,-88.110989626624701,-132.16648443993665,-176.22197925324821,-220.27747406655976,-264.33296887987132,-308.38846369318327,-352.44395850649528,-396.49945331980678,-440.55494813311833,-484.61044294643028,-528.66593775974184,-572.72143257305379,-616.77692738636540,-660.83242219967701,-704.88791701298885,-748.94341182630023,-792.99890663961219,-837.05440145292403,-881.10989626623552,-925.16539107954759,-969.22088589285931,-1013.2763807061709,-1057.3318755194828,-1101.3873703327940,-1145.4428651461060,-1189.4983599594177,-1233.5538547727294,-1277.6093495860414,-1321.6648443993529,-1365.7203392126644,-1409.7758340259766,-1453.8313288392885,-1497.8868236525996,-1541.9423184659113,-1585.9978132792232,-1630.0533080925352,-1674.1088029058465,-1718.1642977191582,-1762.2197925324704,-1806.2752873457819,-1850.3307821590934,-1894.3862769724051,-1938.4417717857175,-1982.4972665990288,-2026.5527614123405,-2070.6082562256520,-2114.6637510389642,-2158.7192458522754,-2202.7747406655876,-2246.8302354788989,-2290.8857302922106,-2334.9412251055223,-2378.9967199188345,-2423.0522147321462,-2467.1077095454575,-2511.1632043587697,-73.425824688854476,-146.85164937770776,-220.27747406656101,-293.70329875541364,-367.12912344426621,-440.55494813311878,-513.98077282197210,-587.40659751082524,-660.83242219967781,-734.25824688853038,-807.68407157738363,-881.10989626623632,-954.53572095508946,-1027.9615456439419,-1101.3873703327947,-1174.8131950216480,-1248.2390197105001,-1321.6648443993533,-1395.0906690882064,-1468.5164937770589,-1541.9423184659122,-1615.3681431547650,-1688.7939678436176,-1762.2197925324708,-1835.6456172213232,-1909.0714419101764,-1982.4972665990292,-2055.9230912878820,-2129.3489159767350,-2202.7747406655876,-2276.2005653544402,-2349.6263900432932,-2423.0522147321467,-2496.4780394209984,-2569.9038641098518,-2643.3296887987049,-2716.7555134875583,-2790.181338176410,-2863.6071628652630,-2937.0329875541165,-3010.4588122429691,-3083.8846369318217,-3157.3104616206747,-3230.7362863095282,-3304.1621109983807,-3377.5879356872333,-3451.0137603760854,-3524.4395850649389,-3597.8654097537919,-3671.2912344426450,-3744.7170591314975,-3818.1428838203501,-3891.5687085092031,-3964.9945331980566,-4038.4203578869096,-4111.8461825757613,-4185.2720072646152,-102.79615456439635,-205.59230912879093,-308.38846369318549,-411.18461825757913,-513.98077282197278,-616.77692738636642,-719.57308195076098,-822.36923651515554,-925.16539107954918,-1027.9615456439428,-1130.7577002083374,-1233.5538547727310,-1336.3500093371256,-1439.1461639015192,-1541.9423184659129,-1644.7384730303074,-1747.5346275947006,-1850.3307821590952,-1953.1269367234893,-2055.9230912878829,-2158.7192458522777,-2261.5154004166716,-2364.3115549810655,-2467.1077095454593,-2569.9038641098532,-2672.7000186742471,-2775.4961732386414,-2878.2923278030348,-2981.0884823674296,-3083.8846369318230,-3186.6807914962169,-3289.4769460606112,-3392.2731006250060,-3495.0692551893985,-3597.8654097537928,-3700.6615643181876,-3803.4577188825820,-3906.2538734469754,-4009.0500280113697,-4111.8461825757640,-4214.6423371401570,-4317.4384917045509,-4420.2346462689457,-4523.0308008333404,-4625.8269553977334,-4728.6231099621273,-4831.4192645265211,-4934.2154190909159,-5037.0115736553089,-5139.8077282197037,-5242.6038827840976,-5345.4000373484914,-5448.1961919128853,-5550.9923464772810,-5653.7885010416740,-5756.5846556060678,-5859.3808101704617,5859.3808101704608,5859.3808101704599,5859.3808101704590,4185.2720072646152,4185.2720072646152,4185.2720072646143,2511.1632043587692,2511.1632043587688,2511.1632043587683,837.05440145292312,837.0544014529230,837.0544014529230,-837.05440145292312,-837.0544014529230,-837.0544014529230,-2511.1632043587692,-2511.1632043587688,-2511.1632043587683,-4185.2720072646143,-4185.2720072646134,-4185.2720072646125,-5859.3808101704608,-5859.3808101704599,-5859.3808101704590,5756.5846556060651,5653.7885010416712,5550.9923464772764,5448.1961919128835,5345.4000373484896,5242.6038827840948,5139.8077282197009,5037.0115736553080,4934.2154190909132,4831.4192645265193,4728.6231099621245,4625.8269553977316,4523.0308008333368,4420.2346462689429,4317.4384917045491,4214.6423371401552,4111.8461825757613,4009.0500280113665,3906.2538734469731,3803.4577188825788,3700.6615643181849,3597.8654097537906,3495.0692551893972,3392.2731006250024,3289.4769460606090,3186.6807914962146,3083.8846369318208,2981.0884823674269,2878.2923278030325,2775.4961732386387,2672.7000186742448,2569.9038641098505,2467.1077095454561,2364.3115549810627,2261.5154004166693,2158.7192458522745,2055.9230912878797,1953.1269367234868,1850.3307821590929,1747.5346275946983,1644.7384730303047,1541.9423184659111,1439.1461639015165,1336.3500093371219,1233.5538547727283,1130.7577002083347,1027.9615456439410,925.16539107954645,822.36923651515190,719.57308195075825,616.77692738636460,513.98077282197096,411.18461825757635,308.38846369318185,205.59230912878817,102.79615456439456,4111.8461825757604,4038.4203578869087,3964.9945331980548,3891.5687085092022,3818.1428838203501,3744.7170591314966,3671.2912344426441,3597.8654097537915,3524.4395850649380,3451.0137603760854,3377.5879356872324,3304.1621109983794,3230.7362863095263,3157.3104616206738,3083.8846369318212,3010.4588122429677,2937.0329875541156,2863.6071628652621,2790.1813381764096,2716.7555134875565,2643.3296887987040,2569.9038641098505,2496.4780394209979,2423.0522147321449,2349.6263900432918,2276.2005653544393,2202.7747406655863,2129.3489159767337,2055.9230912878802,1982.4972665990279,1909.0714419101751,1835.6456172213220,1762.2197925324688,1688.7939678436164,1615.3681431547639,1541.9423184659106,1468.5164937770573,1395.0906690882050,1321.6648443993520,1248.2390197104990,1174.8131950216462,1101.3873703327936,1027.9615456439403,954.53572095508719,881.10989626623450,807.68407157738193,734.25824688852924,660.83242219967599,587.40659751082285,513.98077282197016,440.55494813311759,367.12912344426502,293.70329875541171,220.27747406655848,146.85164937770585,73.425824688853268,2467.1077095454580,2423.0522147321449,2378.9967199188332,2334.9412251055214,2290.8857302922102,2246.8302354788980,2202.7747406655863,2158.7192458522745,2114.6637510389628,2070.6082562256511,2026.5527614123394,1982.4972665990274,1938.4417717857157,1894.3862769724044,1850.3307821590927,1806.2752873457805,1762.2197925324690,1718.1642977191573,1674.1088029058458,1630.0533080925338,1585.9978132792221,1541.9423184659104,1497.8868236525989,1453.8313288392867,1409.7758340259752,1365.7203392126635,1321.6648443993518,1277.609349586040,1233.5538547727283,1189.4983599594168,1145.4428651461051,1101.3873703327931,1057.3318755194812,1013.2763807061699,969.22088589285829,925.16539107954634,881.10989626623427,837.0544014529230,792.99890663961128,748.94341182629933,704.88791701298771,660.83242219967610,616.77692738636415,572.72143257305231,528.66593775974070,484.61044294642915,440.55494813311759,396.49945331980564,352.44395850649363,308.38846369318208,264.33296887987058,220.27747406655899,176.22197925324704,132.16648443993506,88.110989626623521,44.055494813311952,822.36923651515372,807.68407157738170,792.99890663961105,778.31374170184051,763.62857676406998,748.94341182629944,734.25824688852890,719.57308195075836,704.88791701298771,690.20275207521718,675.51758713744641,660.83242219967599,646.14725726190534,631.46209232413480,616.77692738636426,602.09176244859361,587.40659751082308,572.72143257305254,558.0362676352820,543.35110269751135,528.66593775974070,513.98077282197016,499.29560788419968,484.61044294642903,469.92527800865849,455.24011307088790,440.55494813311731,425.86978319534677,411.18461825757612,396.49945331980558,381.81428838203499,367.12912344426445,352.44395850649374,337.75879356872332,323.07362863095284,308.38846369318213,293.70329875541148,279.01813381764106,264.33296887987046,249.64780394209978,234.96263900432925,220.27747406655877,205.59230912878812,190.90714419101747,176.22197925324693,161.53681431547642,146.85164937770588,132.16648443993523,117.48131950216458,102.79615456439406,88.110989626623535,73.425824688853012,58.740659751082354,44.055494813311697,29.370329875541177,14.685164937770653,-822.36923651515076,-807.68407157738170,-792.99890663961105,-778.31374170184051,-763.62857676406998,-748.94341182629944,-734.25824688852890,-719.57308195075836,-704.88791701298771,-690.20275207521718,-675.51758713744641,-660.83242219967599,-646.14725726190534,-631.46209232413480,-616.77692738636426,-602.09176244859361,-587.40659751082308,-572.72143257305254,-558.0362676352820,-543.35110269751135,-528.66593775974070,-513.98077282197016,-499.29560788419968,-484.61044294642903,-469.92527800865849,-455.24011307088790,-440.55494813311731,-425.86978319534677,-411.18461825757612,-396.49945331980558,-381.81428838203499,-367.12912344426445,-352.44395850649374,-337.75879356872332,-323.07362863095284,-308.38846369318213,-293.70329875541148,-279.01813381764106,-264.33296887987046,-249.64780394209978,-234.96263900432925,-220.27747406655877,-205.59230912878812,-190.90714419101747,-176.22197925324693,-161.53681431547642,-146.85164937770588,-132.16648443993523,-117.48131950216458,-102.79615456439406,-88.110989626623535,-73.425824688853012,-58.740659751082354,-44.055494813311697,-29.370329875541177,-14.685164937770653,-2467.1077095454539,-2423.0522147321449,-2378.9967199188332,-2334.9412251055214,-2290.8857302922102,-2246.8302354788980,-2202.7747406655863,-2158.7192458522745,-2114.6637510389628,-2070.6082562256511,-2026.5527614123394,-1982.4972665990274,-1938.4417717857157,-1894.3862769724044,-1850.3307821590927,-1806.2752873457805,-1762.2197925324690,-1718.1642977191573,-1674.1088029058458,-1630.0533080925338,-1585.9978132792221,-1541.9423184659104,-1497.8868236525989,-1453.8313288392867,-1409.7758340259752,-1365.7203392126635,-1321.6648443993518,-1277.609349586040,-1233.5538547727283,-1189.4983599594168,-1145.4428651461051,-1101.3873703327931,-1057.3318755194812,-1013.2763807061699,-969.22088589285829,-925.16539107954634,-881.10989626623427,-837.0544014529230,-792.99890663961128,-748.94341182629933,-704.88791701298771,-660.83242219967610,-616.77692738636415,-572.72143257305231,-528.66593775974070,-484.61044294642915,-440.55494813311759,-396.49945331980564,-352.44395850649363,-308.38846369318208,-264.33296887987058,-220.27747406655899,-176.22197925324704,-132.16648443993506,-88.110989626623521,-44.055494813311952,-4111.8461825757568,-4038.4203578869069,-3964.9945331980543,-3891.5687085092013,-3818.1428838203487,-3744.7170591314957,-3671.2912344426427,-3597.8654097537906,-3524.4395850649371,-3451.0137603760845,-3377.5879356872310,-3304.1621109983789,-3230.7362863095254,-3157.3104616206729,-3083.8846369318203,-3010.4588122429673,-2937.0329875541147,-2863.6071628652612,-2790.1813381764086,-2716.7555134875556,-2643.3296887987030,-2569.903864109850,-2496.4780394209974,-2423.0522147321440,-2349.6263900432918,-2276.2005653544388,-2202.7747406655853,-2129.3489159767332,-2055.9230912878797,-1982.4972665990274,-1909.0714419101744,-1835.6456172213213,-1762.2197925324681,-1688.7939678436160,-1615.3681431547634,-1541.9423184659101,-1468.5164937770569,-1395.0906690882048,-1321.6648443993518,-1248.2390197104985,-1174.8131950216459,-1101.3873703327934,-1027.9615456439401,-954.53572095508696,-881.10989626623427,-807.68407157738170,-734.25824688852913,-660.83242219967588,-587.40659751082262,-513.98077282197005,-440.55494813311748,-367.12912344426491,-293.70329875541165,-220.27747406655840,-146.85164937770583,-73.425824688853240,-5756.5846556060624,-5653.7885010416712,-5550.9923464772764,-5448.1961919128835,-5345.4000373484896,-5242.6038827840948,-5139.8077282197009,-5037.0115736553080,-4934.2154190909132,-4831.4192645265193,-4728.6231099621245,-4625.8269553977316,-4523.0308008333368,-4420.2346462689429,-4317.4384917045491,-4214.6423371401552,-4111.8461825757613,-4009.0500280113665,-3906.2538734469731,-3803.4577188825788,-3700.6615643181849,-3597.8654097537906,-3495.0692551893972,-3392.2731006250024,-3289.4769460606090,-3186.6807914962146,-3083.8846369318208,-2981.0884823674269,-2878.2923278030325,-2775.4961732386387,-2672.7000186742448,-2569.9038641098505,-2467.1077095454561,-2364.3115549810627,-2261.5154004166693,-2158.7192458522745,-2055.9230912878797,-1953.1269367234868,-1850.3307821590929,-1747.5346275946983,-1644.7384730303047,-1541.9423184659111,-1439.1461639015165,-1336.3500093371219,-1233.5538547727283,-1130.7577002083347,-1027.9615456439410,-925.16539107954645,-822.36923651515190,-719.57308195075825,-616.77692738636460,-513.98077282197096,-411.18461825757635,-308.38846369318185,-205.59230912878817,-102.79615456439456]}],"dataType":0,"inputName":"","name":"Stress"}],"indices":[1,2,6,5,0,2,3,7,6,0,3,4,8,7,0,5,6,10,9,0,6,7,11,10,0,7,8,12,11,0,9,10,14,13,0,10,11,15,14,0,11,12,16,15,0,13,14,18,17,0,14,15,19,18,0,15,16,20,19,0,17,18,22,21,0,18,19,23,22,0,19,20,24,23,0,21,22,26,25,0,22,23,27,26,0,23,24,28,27,0,25,26,30,29,0,26,27,31,30,0,27,28,32,31,0,29,30,34,33,0,30,31,35,34,0,31,32,36,35,0,33,34,38,37,0,34,35,39,38,0,35,36,40,39,0,37,38,42,41,0,38,39,43,42,0,39,40,44,43,0,41,42,46,45,0,42,43,47,46,0,43,44,48,47,0,45,46,50,49,0,46,47,51,50,0,47,48,52,51,0,49,50,54,53,0,50,51,55,54,0,51,52,56,55,0,53,54,58,57,0,54,55,59,58,0,55,56,60,59,0,57,58,62,61,0,58,59,63,62,0,59,60,64,63,0,61,62,66,65,0,62,63,67,66,0,63,64,68,67,0,65,66,70,69,0,66,67,71,70,0,67,68,72,71,0,69,70,74,73,0,70,71,75,74,0,71,72,76,75,0,73,74,78,77,0,74,75,79,78,0,75,76,80,79,0,77,78,82,81,0,78,79,83,82,0,79,80,84,83,0,81,82,86,85,0,82,83,87,86,0,83,84,88,87,0,85,86,90,89,0,86,87,91,90,0,87,88,92,91,0,89,90,94,93,0,90,91,95,94,0,91,92,96,95,0,93,94,98,97,0,94,95,99,98,0,95,96,100,99,0,97,98,102,101,0,98,99,103,102,0,99,100,104,103,0,101,102,106,105,0,102,103,107,106,0,103,104,108,107,0,105,106,110,109,0,106,107,111,110,0,107,108,112,111,0,109,110,114,113,0,110,111,115,114,0,111,112,116,115,0,113,114,118,117,0,114,115,119,118,0,115,116,120,119,0,117,118,122,121,0,118,119,123,122,0,119,120,124,123,0,121,122,126,125,0,122,123,127,126,0,123,124,128,127,0,125,126,130,129,0,126,127,131,130,0,127,128,132,131,0,129,130,134,133,0,130,131,135,134,0,131,132,136,135,0,133,134,138,137,0,134,135,139,138,0,135,136,140,139,0,137,138,142,141,0,138,139,143,142,0,139,140,144,143,0,141,142,146,145,0,142,143,147,146,0,143,144,148,147,0,145,146,150,149,0,146,147,151,150,0,147,148,152,151,0,149,150,154,153,0,150,151,155,154,0,151,152,156,155,0,153,154,158,157,0,154,155,159,158,0,155,156,160,159,0,157,158,162,161,0,158,159,163,162,0,159,160,164,163,0,161,162,166,165,0,162,163,167,166,0,163,164,168,167,0,165,166,170,169,0,166,167,171,170,0,167,168,172,171,0,169,170,174,173,0,170,171,175,174,0,171,172,176,175,0,173,174,178,177,0,174,175,179,178,0,175,176,180,179,0,177,178,182,181,0,178,179,183,182,0,179,180,184,183,0,181,182,186,185,0,182,183,187,186,0,183,184,188,187,0,185,186,190,189,0,186,187,191,190,0,187,188,192,191,0,189,190,194,193,0,190,191,195,194,0,191,192,196,195,0,193,194,198,197,0,194,195,199,198,0,195,196,200,199,0,197,198,202,201,0,198,199,203,202,0,199,200,204,203,0,201,202,206,205,0,202,203,207,206,0,203,204,208,207,0,205,206,210,209,0,206,207,211,210,0,207,208,212,211,0,209,210,214,213,0,210,211,215,214,0,211,212,216,215,0,213,214,218,217,0,214,215,219,218,0,215,216,220,219,0,217,218,222,221,0,218,219,223,222,0,219,220,224,223,0,221,222,226,225,0,222,223,227,226,0,223,224,228,227,0,225,226,230,229,0,226,227,231,230,0,227,228,232,231,0,233,234,238,237,0,234,235,239,238,0,235,236,240,239,0,237,238,242,241,0,238,239,243,242,0,239,240,244,243,0,241,242,246,245,0,242,243,247,246,0,243,244,248,247,0,245,246,250,249,0,246,247,251,250,0,247,248,252,251,0,249,250,254,253,0,250,251,255,254,0,251,252,256,255,0,253,254,258,257,0,254,255,259,258,0,255,256,260,259,0,257,258,262,261,0,258,259,263,262,0,259,260,264,263,0,261,262,266,265,0,262,263,267,266,0,263,264,268,267,0,265,266,270,269,0,266,267,271,270,0,267,268,272,271,0,269,270,274,273,0,270,271,275,274,0,271,272,276,275,0,273,274,278,277,0,274,275,279,278,0,275,276,280,279,0,277,278,282,281,0,278,279,283,282,0,279,280,284,283,0,281,282,286,285,0,282,283,287,286,0,283,284,288,287,0,285,286,290,289,0,286,287,291,290,0,287,288,292,291,0,289,290,294,293,0,290,291,295,294,0,291,292,296,295,0,293,294,298,297,0,294,295,299,298,0,295,296,300,299,0,297,298,302,301,0,298,299,303,302,0,299,300,304,303,0,301,302,306,305,0,302,303,307,306,0,303,304,308,307,0,305,306,310,309,0,306,307,311,310,0,307,308,312,311,0,309,310,314,313,0,310,311,315,314,0,311,312,316,315,0,313,314,318,317,0,314,315,319,318,0,315,316,320,319,0,317,318,322,321,0,318,319,323,322,0,319,320,324,323,0,321,322,326,325,0,322,323,327,326,0,323,324,328,327,0,325,326,330,329,0,326,327,331,330,0,327,328,332,331,0,329,330,334,333,0,330,331,335,334,0,331,332,336,335,0,333,334,338,337,0,334,335,339,338,0,335,336,340,339,0,337,338,342,341,0,338,339,343,342,0,339,340,344,343,0,341,342,346,345,0,342,343,347,346,0,343,344,348,347,0,345,346,350,349,0,346,347,351,350,0,347,348,352,351,0,349,350,354,353,0,350,351,355,354,0,351,352,356,355,0,353,354,358,357,0,354,355,359,358,0,355,356,360,359,0,357,358,362,361,0,358,359,363,362,0,359,360,364,363,0,361,362,366,365,0,362,363,367,366,0,363,364,368,367,0,365,366,370,369,0,366,367,371,370,0,367,368,372,371,0,369,370,374,373,0,370,371,375,374,0,371,372,376,375,0,373,374,378,377,0,374,375,379,378,0,375,376,380,379,0,377,378,382,381,0,378,379,383,382,0,379,380,384,383,0,381,382,386,385,0,382,383,387,386,0,383,384,388,387,0,385,386,390,389,0,386,387,391,390,0,387,388,392,391,0,389,390,394,393,0,390,391,395,394,0,391,392,396,395,0,393,394,398,397,0,394,395,399,398,0,395,396,400,399,0,397,398,402,401,0,398,399,403,402,0,399,400,404,403,0,401,402,406,405,0,402,403,407,406,0,403,404,408,407,0,405,406,410,409,0,406,407,411,410,0,407,408,412,411,0,409,410,414,413,0,410,411,415,414,0,411,412,416,415,0,413,414,418,417,0,414,415,419,418,0,415,416,420,419,0,417,418,422,421,0,418,419,423,422,0,419,420,424,423,0,421,422,426,425,0,422,423,427,426,0,423,424,428,427,0,425,426,430,429,0,426,427,431,430,0,427,428,432,431,0,429,430,434,433,0,430,431,435,434,0,431,432,436,435,0,433,434,438,437,0,434,435,439,438,0,435,436,440,439,0,437,438,442,441,0,438,439,443,442,0,439,440,444,443,0,441,442,446,445,0,442,443,447,446,0,443,444,448,447,0,445,446,450,449,0,446,447,451,450,0,447,448,452,451,0,449,450,454,453,0,450,451,455,454,0,451,452,456,455,0,453,454,458,457,0,454,455,459,458,0,455,456,460,459,0,457,458,462,461,0,458,459,463,462,0,459,460,464,463,0,4,3,466,465,0,3,2,467,466,0,2,1,468,467,0,465,466,470,469,0,466,467,471,470,0,467,468,472,471,0,469,470,474,473,0,470,471,475,474,0,471,472,476,475,0,473,474,478,477,0,474,475,479,478,0,475,476,480,479,0,477,478,482,481,0,478,479,483,482,0,479,480,484,483,0,481,482,486,485,0,482,483,487,486,0,483,484,488,487,0,485,486,490,489,0,486,487,491,490,0,487,488,492,491,0,489,490,494,493,0,490,491,495,494,0,491,492,496,495,0,493,494,234,233,0,494,495,235,234,0,495,496,236,235,0,1,5,497,468,0,5,9,498,497,0,9,13,499,498,0,13,17,500,499,0,17,21,501,500,0,21,25,502,501,0,25,29,503,502,0,29,33,504,503,0,33,37,505,504,0,37,41,506,505,0,41,45,507,506,0,45,49,508,507,0,49,53,509,508,0,53,57,510,509,0,57,61,511,510,0,61,65,512,511,0,65,69,513,512,0,69,73,514,513,0,73,77,515,514,0,77,81,516,515,0,81,85,517,516,0,85,89,518,517,0,89,93,519,518,0,93,97,520,519,0,97,101,521,520,0,101,105,522,521,0,105,109,523,522,0,109,113,524,523,0,113,117,525,524,0,117,121,526,525,0,121,125,527,526,0,125,129,528,527,0,129,133,529,528,0,133,137,530,529,0,137,141,531,530,0,141,145,532,531,0,145,149,533,532,0,149,153,534,533,0,153,157,535,534,0,157,161,536,535,0,161,165,537,536,0,165,169,538,537,0,169,173,539,538,0,173,177,540,539,0,177,181,541,540,0,181,185,542,541,0,185,189,543,542,0,189,193,544,543,0,193,197,545,544,0,197,201,546,545,0,201,205,547,546,0,205,209,548,547,0,209,213,549,548,0,213,217,550,549,0,217,221,551,550,0,221,225,552,551,0,225,229,553,552,0,468,497,554,472,0,497,498,555,554,0,498,499,556,555,0,499,500,557,556,0,500,501,558,557,0,501,502,559,558,0,502,503,560,559,0,503,504,561,560,0,504,505,562,561,0,505,506,563,562,0,506,507,564,563,0,507,508,565,564,0,508,509,566,565,0,509,510,567,566,0,510,511,568,567,0,511,512,569,568,0,512,513,570,569,0,513,514,571,570,0,514,515,572,571,0,515,516,573,572,0,516,517,574,573,0,517,518,575,574,0,518,519,576,575,0,519,520,577,576,0,520,521,578,577,0,521,522,579,578,0,522,523,580,579,0,523,524,581,580,0,524,525,582,581,0,525,526,583,582,0,526,527,584,583,0,527,528,585,584,0,528,529,586,585,0,529,530,587,586,0,530,531,588,587,0,531,532,589,588,0,532,533,590,589,0,533,534,591,590,0,534,535,592,591,0,535,536,593,592,0,536,537,594,593,0,537,538,595,594,0,538,539,596,595,0,539,540,597,596,0,540,541,598,597,0,541,542,599,598,0,542,543,600,599,0,543,544,601,600,0,544,545,602,601,0,545,546,603,602,0,546,547,604,603,0,547,548,605,604,0,548,549,606,605,0,549,550,607,606,0,550,551,608,607,0,551,552,609,608,0,552,553,610,609,0,472,554,611,476,0,554,555,612,611,0,555,556,613,612,0,556,557,614,613,0,557,558,615,614,0,558,559,616,615,0,559,560,617,616,0,560,561,618,617,0,561,562,619,618,0,562,563,620,619,0,563,564,621,620,0,564,565,622,621,0,565,566,623,622,0,566,567,624,623,0,567,568,625,624,0,568,569,626,625,0,569,570,627,626,0,570,571,628,627,0,571,572,629,628,0,572,573,630,629,0,573,574,631,630,0,574,575,632,631,0,575,576,633,632,0,576,577,634,633,0,577,578,635,634,0,578,579,636,635,0,579,580,637,636,0,580,581,638,637,0,581,582,639,638,0,582,583,640,639,0,583,584,641,640,0,584,585,642,641,0,585,586,643,642,0,586,587,644,643,0,587,588,645,644,0,588,589,646,645,0,589,590,647,646,0,590,591,648,647,0,591,592,649,648,0,592,593,650,649,0,593,594,651,650,0,594,595,652,651,0,595,596,653,652,0,596,597,654,653,0,597,598,655,654,0,598,599,656,655,0,599,600,657,656,0,600,601,658,657,0,601,602,659,658,0,602,603,660,659,0,603,604,661,660,0,604,605,662,661,0,605,606,663,662,0,606,607,664,663,0,607,608,665,664,0,608,609,666,665,0,609,610,667,666,0,476,611,668,480,0,611,612,669,668,0,612,613,670,669,0,613,614,671,670,0,614,615,672,671,0,615,616,673,672,0,616,617,674,673,0,617,618,675,674,0,618,619,676,675,0,619,620,677,676,0,620,621,678,677,0,621,622,679,678,0,622,623,680,679,0,623,624,681,680,0,624,625,682,681,0,625,626,683,682,0,626,627,684,683,0,627,628,685,684,0,628,629,686,685,0,629,630,687,686,0,630,631,688,687,0,631,632,689,688,0,632,633,690,689,0,633,634,691,690,0,634,635,692,691,0,635,636,693,692,0,636,637,694,693,0,637,638,695,694,0,638,639,696,695,0,639,640,697,696,0,640,641,698,697,0,641,642,699,698,0,642,643,700,699,0,643,644,701,700,0,644,645,702,701,0,645,646,703,702,0,646,647,704,703,0,647,648,705,704,0,648,649,706,705,0,649,650,707,706,0,650,651,708,707,0,651,652,709,708,0,652,653,710,709,0,653,654,711,710,0,654,655,712,711,0,655,656,713,712,0,656,657,714,713,0,657,658,715,714,0,658,659,716,715,0,659,660,717,716,0,660,661,718,717,0,661,662,719,718,0,662,663,720,719,0,663,664,721,720,0,664,665,722,721,0,665,666,723,722,0,666,667,724,723,0,480,668,725,484,0,668,669,726,725,0,669,670,727,726,0,670,671,728,727,0,671,672,729,728,0,672,673,730,729,0,673,674,731,730,0,674,675,732,731,0,675,676,733,732,0,676,677,734,733,0,677,678,735,734,0,678,679,736,735,0,679,680,737,736,0,680,681,738,737,0,681,682,739,738,0,682,683,740,739,0,683,684,741,740,0,684,685,742,741,0,685,686,743,742,0,686,687,744,743,0,687,688,745,744,0,688,689,746,745,0,689,690,747,746,0,690,691,748,747,0,691,692,749,748,0,692,693,750,749,0,693,694,751,750,0,694,695,752,751,0,695,696,753,752,0,696,697,754,753,0,697,698,755,754,0,698,699,756,755,0,699,700,757,756,0,700,701,758,757,0,701,702,759,758,0,702,703,760,759,0,703,704,761,760,0,704,705,762,761,0,705,706,763,762,0,706,707,764,763,0,707,708,765,764,0,708,709,766,765,0,709,710,767,766,0,710,711,768,767,0,711,712,769,768,0,712,713,770,769,0,713,714,771,770,0,714,715,772,771,0,715,716,773,772,0,716,717,774,773,0,717,718,775,774,0,718,719,776,775,0,719,720,777,776,0,720,721,778,777,0,721,722,779,778,0,722,723,780,779,0,723,724,781,780,0,484,725,782,488,0,725,726,783,782,0,726,727,784,783,0,727,728,785,784,0,728,729,786,785,0,729,730,787,786,0,730,731,788,787,0,731,732,789,788,0,732,733,790,789,0,733,734,791,790,0,734,735,792,791,0,735,736,793,792,0,736,737,794,793,0,737,738,795,794,0,738,739,796,795,0,739,740,797,796,0,740,741,798,797,0,741,742,799,798,0,742,743,800,799,0,743,744,801,800,0,744,745,802,801,0,745,746,803,802,0,746,747,804,803,0,747,748,805,804,0,748,749,806,805,0,749,750,807,806,0,750,751,808,807,0,751,752,809,808,0,752,753,810,809,0,753,754,811,810,0,754,755,812,811,0,755,756,813,812,0,756,757,814,813,0,757,758,815,814,0,758,759,816,815,0,759,760,817,816,0,760,761,818,817,0,761,762,819,818,0,762,763,820,819,0,763,764,821,820,0,764,765,822,821,0,765,766,823,822,0,766,767,824,823,0,767,768,825,824,0,768,769,826,825,0,769,770,827,826,0,770,771,828,827,0,771,772,829,828,0,772,773,830,829,0,773,774,831,830,0,774,775,832,831,0,775,776,833,832,0,776,777,834,833,0,777,778,835,834,0,778,779,836,835,0,779,780,837,836,0,780,781,838,837,0,488,782,839,492,0,782,783,840,839,0,783,784,841,840,0,784,785,842,841,0,785,786,843,842,0,786,787,844,843,0,787,788,845,844,0,788,789,846,845,0,789,790,847,846,0,790,791,848,847,0,791,792,849,848,0,792,793,850,849,0,793,794,851,850,0,794,795,852,851,0,795,796,853,852,0,796,797,854,853,0,797,798,855,854,0,798,799,856,855,0,799,800,857,856,0,800,801,858,857,0,801,802,859,858,0,802,803,860,859,0,803,804,861,860,0,804,805,862,861,0,805,806,863,862,0,806,807,864,863,0,807,808,865,864,0,808,809,866,865,0,809,810,867,866,0,810,811,868,867,0,811,812,869,868,0,812,813,870,869,0,813,814,871,870,0,814,815,872,871,0,815,816,873,872,0,816,817,874,873,0,817,818,875,874,0,818,819,876,875,0,819,820,877,876,0,820,821,878,877,0,821,822,879,878,0,822,823,880,879,0,823,824,881,880,0,824,825,882,881,0,825,826,883,882,0,826,827,884,883,0,827,828,885,884,0,828,829,886,885,0,829,830,887,886,0,830,831,888,887,0,831,832,889,888,0,832,833,890,889,0,833,834,891,890,0,834,835,892,891,0,835,836,893,892,0,836,837,894,893,0,837,838,895,894,0,492,839,896,496,0,839,840,897,896,0,840,841,898,897,0,841,842,899,898,0,842,843,900,899,0,843,844,901,900,0,844,845,902,901,0,845,846,903,902,0,846,847,904,903,0,847,848,905,904,0,848,849,906,905,0,849,850,907,906,0,850,851,908,907,0,851,852,909,908,0,852,853,910,909,0,853,854,911,910,0,854,855,912,911,0,855,856,913,912,0,856,857,914,913,0,857,858,915,914,0,858,859,916,915,0,859,860,917,916,0,860,861,918,917,0,861,862,919,918,0,862,863,920,919,0,863,864,921,920,0,864,865,922,921,0,865,866,923,922,0,866,867,924,923,0,867,868,925,924,0,868,869,926,925,0,869,870,927,926,0,870,871,928,927,0,871,872,929,928,0,872,873,930,929,0,873,874,931,930,0,874,875,932,931,0,875,876,933,932,0,876,877,934,933,0,877,878,935,934,0,878,879,936,935,0,879,880,937,936,0,880,881,938,937,0,881,882,939,938,0,882,883,940,939,0,883,884,941,940,0,884,885,942,941,0,885,886,943,942,0,886,887,944,943,0,887,888,945,944,0,888,889,946,945,0,889,890,947,946,0,890,891,948,947,0,891,892,949,948,0,892,893,950,949,0,893,894,951,950,0,894,895,952,951,0,496,896,240,236,0,896,897,244,240,0,897,898,248,244,0,898,899,252,248,0,899,900,256,252,0,900,901,260,256,0,901,902,264,260,0,902,903,268,264,0,903,904,272,268,0,904,905,276,272,0,905,906,280,276,0,906,907,284,280,0,907,908,288,284,0,908,909,292,288,0,909,910,296,292,0,910,911,300,296,0,911,912,304,300,0,912,913,308,304,0,913,914,312,308,0,914,915,316,312,0,915,916,320,316,0,916,917,324,320,0,917,918,328,324,0,918,919,332,328,0,919,920,336,332,0,920,921,340,336,0,921,922,344,340,0,922,923,348,344,0,923,924,352,348,0,924,925,356,352,0,925,926,360,356,0,926,927,364,360,0,927,928,368,364,0,928,929,372,368,0,929,930,376,372,0,930,931,380,376,0,931,932,384,380,0,932,933,388,384,0,933,934,392,388,0,934,935,396,392,0,935,936,400,396,0,936,937,404,400,0,937,938,408,404,0,938,939,412,408,0,939,940,416,412,0,940,941,420,416,0,941,942,424,420,0,942,943,428,424,0,943,944,432,428,0,944,945,436,432,0,945,946,440,436,0,946,947,444,440,0,947,948,448,444,0,948,949,452,448,0,949,950,456,452,0,950,951,460,456,0,951,952,464,460,0,229,230,953,553,0,230,231,954,953,0,231,232,955,954,0,553,953,956,610,0,953,954,957,956,0,954,955,958,957,0,610,956,959,667,0,956,957,960,959,0,957,958,961,960,0,667,959,962,724,0,959,960,963,962,0,960,961,964,963,0,724,962,965,781,0,962,963,966,965,0,963,964,967,966,0,781,965,968,838,0,965,966,969,968,0,966,967,970,969,0,838,968,971,895,0,968,969,972,971,0,969,970,973,972,0,895,971,974,952,0,971,972,975,974,0,972,973,976,975,0,952,974,463,464,0,974,975,462,463,0,975,976,461,462,0,232,228,977,955,0,228,224,978,977,0,224,220,979,978,0,220,216,980,979,0,216,212,981,980,0,212,208,982,981,0,208,204,983,982,0,204,200,984,983,0,200,196,985,984,0,196,192,986,985,0,192,188,987,986,0,188,184,988,987,0,184,180,989,988,0,180,176,990,989,0,176,172,991,990,0,172,168,992,991,0,168,164,993,992,0,164,160,994,993,0,160,156,995,994,0,156,152,996,995,0,152,148,997,996,0,148,144,998,997,0,144,140,999,998,0,140,136,1000,999,0,136,132,1001,1000,0,132,128,1002,1001,0,128,124,1003,1002,0,124,120,1004,1003,0,120,116,1005,1004,0,116,112,1006,1005,0,112,108,1007,1006,0,108,104,1008,1007,0,104,100,1009,1008,0,100,96,1010,1009,0,96,92,1011,1010,0,92,88,1012,1011,0,88,84,1013,1012,0,84,80,1014,1013,0,80,76,1015,1014,0,76,72,1016,1015,0,72,68,1017,1016,0,68,64,1018,1017,0,64,60,1019,1018,0,60,56,1020,1019,0,56,52,1021,1020,0,52,48,1022,1021,0,48,44,1023,1022,0,44,40,1024,1023,0,40,36,1025,1024,0,36,32,1026,1025,0,32,28,1027,1026,0,28,24,1028,1027,0,24,20,1029,1028,0,20,16,1030,1029,0,16,12,1031,1030,0,12,8,1032,1031,0,8,4,465,1032,0,955,977,1033,958,0,977,978,1034,1033,0,978,979,1035,1034,0,979,980,1036,1035,0,980,981,1037,1036,0,981,982,1038,1037,0,982,983,1039,1038,0,983,984,1040,1039,0,984,985,1041,1040,0,985,986,1042,1041,0,986,987,1043,1042,0,987,988,1044,1043,0,988,989,1045,1044,0,989,990,1046,1045,0,990,991,1047,1046,0,991,992,1048,1047,0,992,993,1049,1048,0,993,994,1050,1049,0,994,995,1051,1050,0,995,996,1052,1051,0,996,997,1053,1052,0,997,998,1054,1053,0,998,999,1055,1054,0,999,1000,1056,1055,0,1000,1001,1057,1056,0,1001,1002,1058,1057,0,1002,1003,1059,1058,0,1003,1004,1060,1059,0,1004,1005,1061,1060,0,1005,1006,1062,1061,0,1006,1007,1063,1062,0,1007,1008,1064,1063,0,1008,1009,1065,1064,0,1009,1010,1066,1065,0,1010,1011,1067,1066,0,1011,1012,1068,1067,0,1012,1013,1069,1068,0,1013,1014,1070,1069,0,1014,1015,1071,1070,0,1015,1016,1072,1071,0,1016,1017,1073,1072,0,1017,1018,1074,1073,0,1018,1019,1075,1074,0,1019,1020,1076,1075,0,1020,1021,1077,1076,0,1021,1022,1078,1077,0,1022,1023,1079,1078,0,1023,1024,1080,1079,0,1024,1025,1081,1080,0,1025,1026,1082,1081,0,1026,1027,1083,1082,0,1027,1028,1084,1083,0,1028,1029,1085,1084,0,1029,1030,1086,1085,0,1030,1031,1087,1086,0,1031,1032,1088,1087,0,1032,465,469,1088,0,958,1033,1089,961,0,1033,1034,1090,1089,0,1034,1035,1091,1090,0,1035,1036,1092,1091,0,1036,1037,1093,1092,0,1037,1038,1094,1093,0,1038,1039,1095,1094,0,1039,1040,1096,1095,0,1040,1041,1097,1096,0,1041,1042,1098,1097,0,1042,1043,1099,1098,0,1043,1044,1100,1099,0,1044,1045,1101,1100,0,1045,1046,1102,1101,0,1046,1047,1103,1102,0,1047,1048,1104,1103,0,1048,1049,1105,1104,0,1049,1050,1106,1105,0,1050,1051,1107,1106,0,1051,1052,1108,1107,0,1052,1053,1109,1108,0,1053,1054,1110,1109,0,1054,1055,1111,1110,0,1055,1056,1112,1111,0,1056,1057,1113,1112,0,1057,1058,1114,1113,0,1058,1059,1115,1114,0,1059,1060,1116,1115,0,1060,1061,1117,1116,0,1061,1062,1118,1117,0,1062,1063,1119,1118,0,1063,1064,1120,1119,0,1064,1065,1121,1120,0,1065,1066,1122,1121,0,1066,1067,1123,1122,0,1067,1068,1124,1123,0,1068,1069,1125,1124,0,1069,1070,1126,1125,0,1070,1071,1127,1126,0,1071,1072,1128,1127,0,1072,1073,1129,1128,0,1073,1074,1130,1129,0,1074,1075,1131,1130,0,1075,1076,1132,1131,0,1076,1077,1133,1132,0,1077,1078,1134,1133,0,1078,1079,1135,1134,0,1079,1080,1136,1135,0,1080,1081,1137,1136,0,1081,1082,1138,1137,0,1082,1083,1139,1138,0,1083,1084,1140,1139,0,1084,1085,1141,1140,0,1085,1086,1142,1141,0,1086,1087,1143,1142,0,1087,1088,1144,1143,0,1088,469,473,1144,0,961,1089,1145,964,0,1089,1090,1146,1145,0,1090,1091,1147,1146,0,1091,1092,1148,1147,0,1092,1093,1149,1148,0,1093,1094,1150,1149,0,1094,1095,1151,1150,0,1095,1096,1152,1151,0,1096,1097,1153,1152,0,1097,1098,1154,1153,0,1098,1099,1155,1154,0,1099,1100,1156,1155,0,1100,1101,1157,1156,0,1101,1102,1158,1157,0,1102,1103,1159,1158,0,1103,1104,1160,1159,0,1104,1105,1161,1160,0,1105,1106,1162,1161,0,1106,1107,1163,1162,0,1107,1108,1164,1163,0,1108,1109,1165,1164,0,1109,1110,1166,1165,0,1110,1111,1167,1166,0,1111,1112,1168,1167,0,1112,1113,1169,1168,0,1113,1114,1170,1169,0,1114,1115,1171,1170,0,1115,1116,1172,1171,0,1116,1117,1173,1172,0,1117,1118,1174,1173,0,1118,1119,1175,1174,0,1119,1120,1176,1175,0,1120,1121,1177,1176,0,1121,1122,1178,1177,0,1122,1123,1179,1178,0,1123,1124,1180,1179,0,1124,1125,1181,1180,0,1125,1126,1182,1181,0,1126,1127,1183,1182,0,1127,1128,1184,1183,0,1128,1129,1185,1184,0,1129,1130,1186,1185,0,1130,1131,1187,1186,0,1131,1132,1188,1187,0,1132,1133,1189,1188,0,1133,1134,1190,1189,0,1134,1135,1191,1190,0,1135,1136,1192,1191,0,1136,1137,1193,1192,0,1137,1138,1194,1193,0,1138,1139,1195,1194,0,1139,1140,1196,1195,0,1140,1141,1197,1196,0,1141,1142,1198,1197,0,1142,1143,1199,1198,0,1143,1144,1200,1199,0,1144,473,477,1200,0,964,1145,1201,967,0,1145,1146,1202,1201,0,1146,1147,1203,1202,0,1147,1148,1204,1203,0,1148,1149,1205,1204,0,1149,1150,1206,1205,0,1150,1151,1207,1206,0,1151,1152,1208,1207,0,1152,1153,1209,1208,0,1153,1154,1210,1209,0,1154,1155,1211,1210,0,1155,1156,1212,1211,0,1156,1157,1213,1212,0,1157,1158,1214,1213,0,1158,1159,1215,1214,0,1159,1160,1216,1215,0,1160,1161,1217,1216,0,1161,1162,1218,1217,0,1162,1163,1219,1218,0,1163,1164,1220,1219,0,1164,1165,1221,1220,0,1165,1166,1222,1221,0,1166,1167,1223,1222,0,1167,1168,1224,1223,0,1168,1169,1225,1224,0,1169,1170,1226,1225,0,1170,1171,1227,1226,0,1171,1172,1228,1227,0,1172,1173,1229,1228,0,1173,1174,1230,1229,0,1174,1175,1231,1230,0,1175,1176,1232,1231,0,1176,1177,1233,1232,0,1177,1178,1234,1233,0,1178,1179,1235,1234,0,1179,1180,1236,1235,0,1180,1181,1237,1236,0,1181,1182,1238,1237,0,1182,1183,1239,1238,0,1183,1184,1240,1239,0,1184,1185,1241,1240,0,1185,1186,1242,1241,0,1186,1187,1243,1242,0,1187,1188,1244,1243,0,1188,1189,1245,1244,0,1189,1190,1246,1245,0,1190,1191,1247,1246,0,1191,1192,1248,1247,0,1192,1193,1249,1248,0,1193,1194,1250,1249,0,1194,1195,1251,1250,0,1195,1196,1252,1251,0,1196,1197,1253,1252,0,1197,1198,1254,1253,0,1198,1199,1255,1254,0,1199,1200,1256,1255,0,1200,477,481,1256,0,967,1201,1257,970,0,1201,1202,1258,1257,0,1202,1203,1259,1258,0,1203,1204,1260,1259,0,1204,1205,1261,1260,0,1205,1206,1262,1261,0,1206,1207,1263,1262,0,1207,1208,1264,1263,0,1208,1209,1265,1264,0,1209,1210,1266,1265,0,1210,1211,1267,1266,0,1211,1212,1268,1267,0,1212,1213,1269,1268,0,1213,1214,1270,1269,0,1214,1215,1271,1270,0,1215,1216,1272,1271,0,1216,1217,1273,1272,0,1217,1218,1274,1273,0,1218,1219,1275,1274,0,1219,1220,1276,1275,0,1220,1221,1277,1276,0,1221,1222,1278,1277,0,1222,1223,1279,1278,0,1223,1224,1280,1279,0,1224,1225,1281,1280,0,1225,1226,1282,1281,0,1226,1227,1283,1282,0,1227,1228,1284,1283,0,1228,1229,1285,1284,0,1229,1230,1286,1285,0,1230,1231,1287,1286,0,1231,1232,1288,1287,0,1232,1233,1289,1288,0,1233,1234,1290,1289,0,1234,1235,1291,1290,0,1235,1236,1292,1291,0,1236,1237,1293,1292,0,1237,1238,1294,1293,0,1238,1239,1295,1294,0,1239,1240,1296,1295,0,1240,1241,1297,1296,0,1241,1242,1298,1297,0,1242,1243,1299,1298,0,1243,1244,1300,1299,0,1244,1245,1301,1300,0,1245,1246,1302,1301,0,1246,1247,1303,1302,0,1247,1248,1304,1303,0,1248,1249,1305,1304,0,1249,1250,1306,1305,0,1250,1251,1307,1306,0,1251,1252,1308,1307,0,1252,1253,1309,1308,0,1253,1254,1310,1309,0,1254,1255,1311,1310,0,1255,1256,1312,1311,0,1256,481,485,1312,0,970,1257,1313,973,0,1257,1258,1314,1313,0,1258,1259,1315,1314,0,1259,1260,1316,1315,0,1260,1261,1317,1316,0,1261,1262,1318,1317,0,1262,1263,1319,1318,0,1263,1264,1320,1319,0,1264,1265,1321,1320,0,1265,1266,1322,1321,0,1266,1267,1323,1322,0,1267,1268,1324,1323,0,1268,1269,1325,1324,0,1269,1270,1326,1325,0,1270,1271,1327,1326,0,1271,1272,1328,1327,0,1272,1273,1329,1328,0,1273,1274,1330,1329,0,1274,1275,1331,1330,0,1275,1276,1332,1331,0,1276,1277,1333,1332,0,1277,1278,1334,1333,0,1278,1279,1335,1334,0,1279,1280,1336,1335,0,1280,1281,1337,1336,0,1281,1282,1338,1337,0,1282,1283,1339,1338,0,1283,1284,1340,1339,0,1284,1285,1341,1340,0,1285,1286,1342,1341,0,1286,1287,1343,1342,0,1287,1288,1344,1343,0,1288,1289,1345,1344,0,1289,1290,1346,1345,0,1290,1291,1347,1346,0,1291,1292,1348,1347,0,1292,1293,1349,1348,0,1293,1294,1350,1349,0,1294,1295,1351,1350,0,1295,1296,1352,1351,0,1296,1297,1353,1352,0,1297,1298,1354,1353,0,1298,1299,1355,1354,0,1299,1300,1356,1355,0,1300,1301,1357,1356,0,1301,1302,1358,1357,0,1302,1303,1359,1358,0,1303,1304,1360,1359,0,1304,1305,1361,1360,0,1305,1306,1362,1361,0,1306,1307,1363,1362,0,1307,1308,1364,1363,0,1308,1309,1365,1364,0,1309,1310,1366,1365,0,1310,1311,1367,1366,0,1311,1312,1368,1367,0,1312,485,489,1368,0,973,1313,1369,976,0,1313,1314,1370,1369,0,1314,1315,1371,1370,0,1315,1316,1372,1371,0,1316,1317,1373,1372,0,1317,1318,1374,1373,0,1318,1319,1375,1374,0,1319,1320,1376,1375,0,1320,1321,1377,1376,0,1321,1322,1378,1377,0,1322,1323,1379,1378,0,1323,1324,1380,1379,0,1324,1325,1381,1380,0,1325,1326,1382,1381,0,1326,1327,1383,1382,0,1327,1328,1384,1383,0,1328,1329,1385,1384,0,1329,1330,1386,1385,0,1330,1331,1387,1386,0,1331,1332,1388,1387,0,1332,1333,1389,1388,0,1333,1334,1390,1389,0,1334,1335,1391,1390,0,1335,1336,1392,1391,0,1336,1337,1393,1392,0,1337,1338,1394,1393,0,1338,1339,1395,1394,0,1339,1340,1396,1395,0,1340,1341,1397,1396,0,1341,1342,1398,1397,0,1342,1343,1399,1398,0,1343,1344,1400,1399,0,1344,1345,1401,1400,0,1345,1346,1402,1401,0,1346,1347,1403,1402,0,1347,1348,1404,1403,0,1348,1349,1405,1404,0,1349,1350,1406,1405,0,1350,1351,1407,1406,0,1351,1352,1408,1407,0,1352,1353,1409,1408,0,1353,1354,1410,1409,0,1354,1355,1411,1410,0,1355,1356,1412,1411,0,1356,1357,1413,1412,0,1357,1358,1414,1413,0,1358,1359,1415,1414,0,1359,1360,1416,1415,0,1360,1361,1417,1416,0,1361,1362,1418,1417,0,1362,1363,1419,1418,0,1363,1364,1420,1419,0,1364,1365,1421,1420,0,1365,1366,1422,1421,0,1366,1367,1423,1422,0,1367,1368,1424,1423,0,1368,489,493,1424,0,976,1369,457,461,0,1369,1370,453,457,0,1370,1371,449,453,0,1371,1372,445,449,0,1372,1373,441,445,0,1373,1374,437,441,0,1374,1375,433,437,0,1375,1376,429,433,0,1376,1377,425,429,0,1377,1378,421,425,0,1378,1379,417,421,0,1379,1380,413,417,0,1380,1381,409,413,0,1381,1382,405,409,0,1382,1383,401,405,0,1383,1384,397,401,0,1384,1385,393,397,0,1385,1386,389,393,0,1386,1387,385,389,0,1387,1388,381,385,0,1388,1389,377,381,0,1389,1390,373,377,0,1390,1391,369,373,0,1391,1392,365,369,0,1392,1393,361,365,0,1393,1394,357,361,0,1394,1395,353,357,0,1395,1396,349,353,0,1396,1397,345,349,0,1397,1398,341,345,0,1398,1399,337,341,0,1399,1400,333,337,0,1400,1401,329,333,0,1401,1402,325,329,0,1402,1403,321,325,0,1403,1404,317,321,0,1404,1405,313,317,0,1405,1406,309,313,0,1406,1407,305,309,0,1407,1408,301,305,0,1408,1409,297,301,0,1409,1410,293,297,0,1410,1411,289,293,0,1411,1412,285,289,0,1412,1413,281,285,0,1413,1414,277,281,0,1414,1415,273,277,0,1415,1416,269,273,0,1416,1417,265,269,0,1417,1418,261,265,0,1418,1419,257,261,0,1419,1420,253,257,0,1420,1421,249,253,0,1421,1422,245,249,0,1422,1423,241,245,0,1423,1424,237,241,0,1424,493,233,237,0]},"point":[[2.9616995425820702,0.0,0.45720],[2.9616995425820707,0.050799999999999991,0.45720],[2.9616995425820711,0.10159999999999998,0.45720],[2.9616995425820716,0.15239999999999998,0.45720],[2.9113441120104548,0.0,0.45720],[2.9113441120104553,0.050799999999999991,0.45720],[2.9113441120104562,0.10159999999999998,0.45720],[2.9113441120104562,0.15239999999999998,0.45720],[2.8609886814388399,0.0,0.45720],[2.8609886814388399,0.050799999999999991,0.45720],[2.8609886814388408,0.10159999999999998,0.45720],[2.8609886814388412,0.15239999999999998,0.45720],[2.8106332508672240,0.0,0.45720],[2.8106332508672245,0.050799999999999991,0.45720],[2.8106332508672254,0.10159999999999998,0.45720],[2.8106332508672254,0.15239999999999998,0.45720],[2.7602778202956091,0.0,0.45720],[2.7602778202956091,0.050799999999999991,0.45720],[2.760277820295610,0.10159999999999998,0.45720],[2.7602778202956104,0.15239999999999998,0.45720],[2.7099223897239937,0.0,0.45720],[2.7099223897239941,0.050799999999999991,0.45720],[2.7099223897239946,0.10159999999999998,0.45720],[2.7099223897239950,0.15239999999999998,0.45720],[2.6595669591523783,0.0,0.45720],[2.6595669591523787,0.050799999999999991,0.45720],[2.6595669591523796,0.10159999999999998,0.45720],[2.6595669591523801,0.15239999999999998,0.45720],[2.6092115285807633,0.0,0.45720],[2.6092115285807633,0.050799999999999991,0.45720],[2.6092115285807638,0.10159999999999998,0.45720],[2.6092115285807647,0.15239999999999998,0.45720],[2.5588560980091475,0.0,0.45720],[2.5588560980091479,0.050799999999999991,0.45720],[2.5588560980091488,0.10159999999999998,0.45720],[2.5588560980091493,0.15239999999999998,0.45720],[2.5085006674375325,0.0,0.45720],[2.5085006674375330,0.050799999999999991,0.45720],[2.5085006674375334,0.10159999999999998,0.45720],[2.5085006674375339,0.15239999999999998,0.45720],[2.4581452368659171,0.0,0.45720],[2.4581452368659176,0.050799999999999991,0.45720],[2.4581452368659185,0.10159999999999998,0.45720],[2.4581452368659185,0.15239999999999998,0.45720],[2.4077898062943017,0.0,0.45720],[2.4077898062943022,0.050799999999999991,0.45720],[2.4077898062943031,0.10159999999999998,0.45720],[2.4077898062943031,0.15239999999999998,0.45720],[2.3574343757226863,0.0,0.45720],[2.3574343757226868,0.050799999999999991,0.45720],[2.3574343757226877,0.10159999999999998,0.45720],[2.3574343757226877,0.15239999999999998,0.45720],[2.3070789451510714,0.0,0.45720],[2.3070789451510714,0.050799999999999991,0.45720],[2.3070789451510723,0.10159999999999998,0.45720],[2.3070789451510727,0.15239999999999998,0.45720],[2.2567235145794560,0.0,0.45720],[2.2567235145794564,0.050799999999999991,0.45720],[2.2567235145794569,0.10159999999999998,0.45720],[2.2567235145794573,0.15239999999999998,0.45720],[2.2063680840078406,0.0,0.45720],[2.2063680840078410,0.050799999999999991,0.45720],[2.2063680840078419,0.10159999999999998,0.45720],[2.2063680840078423,0.15239999999999998,0.45720],[2.1560126534362252,0.0,0.45720],[2.1560126534362261,0.050799999999999991,0.45720],[2.1560126534362265,0.10159999999999998,0.45720],[2.1560126534362265,0.15239999999999998,0.45720],[2.1056572228646102,0.0,0.45720],[2.1056572228646102,0.050799999999999991,0.45720],[2.1056572228646111,0.10159999999999998,0.45720],[2.1056572228646120,0.15239999999999998,0.45720],[2.0553017922929948,0.0,0.45720],[2.0553017922929953,0.050799999999999991,0.45720],[2.0553017922929957,0.10159999999999998,0.45720],[2.0553017922929961,0.15239999999999998,0.45720],[2.0049463617213794,0.0,0.45720],[2.0049463617213799,0.050799999999999991,0.45720],[2.0049463617213807,0.10159999999999998,0.45720],[2.0049463617213812,0.15239999999999998,0.45720],[1.9545909311497642,0.0,0.45720],[1.9545909311497642,0.050799999999999991,0.45720],[1.9545909311497651,0.10159999999999998,0.45720],[1.9545909311497658,0.15239999999999998,0.45720],[1.9042355005781488,0.0,0.45720],[1.9042355005781495,0.050799999999999991,0.45720],[1.9042355005781502,0.10159999999999998,0.45720],[1.9042355005781502,0.15239999999999998,0.45720],[1.8538800700065334,0.0,0.45720],[1.8538800700065339,0.050799999999999991,0.45720],[1.8538800700065345,0.10159999999999998,0.45720],[1.8538800700065350,0.15239999999999998,0.45720],[1.8035246394349183,0.0,0.45720],[1.8035246394349187,0.050799999999999991,0.45720],[1.8035246394349194,0.10159999999999998,0.45720],[1.8035246394349198,0.15239999999999998,0.45720],[1.7531692088633026,0.0,0.45720],[1.7531692088633035,0.050799999999999991,0.45720],[1.7531692088633042,0.10159999999999998,0.45720],[1.7531692088633042,0.15239999999999998,0.45720],[1.7028137782916879,0.0,0.45720],[1.7028137782916879,0.050799999999999991,0.45720],[1.7028137782916886,0.10159999999999998,0.45720],[1.7028137782916892,0.15239999999999998,0.45720],[1.6524583477200723,0.0,0.45720],[1.6524583477200729,0.050799999999999991,0.45720],[1.6524583477200738,0.10159999999999998,0.45720],[1.6524583477200738,0.15239999999999998,0.45720],[1.6021029171484571,0.0,0.45720],[1.6021029171484573,0.050799999999999991,0.45720],[1.6021029171484582,0.10159999999999998,0.45720],[1.6021029171484584,0.15239999999999998,0.45720],[1.5517474865768419,0.0,0.45720],[1.5517474865768421,0.050799999999999991,0.45720],[1.5517474865768430,0.10159999999999998,0.45720],[1.5517474865768432,0.15239999999999998,0.45720],[1.5013920560052263,0.0,0.45720],[1.5013920560052265,0.050799999999999991,0.45720],[1.5013920560052274,0.10159999999999998,0.45720],[1.5013920560052276,0.15239999999999998,0.45720],[1.4510366254336111,0.0,0.45720],[1.4510366254336116,0.050799999999999991,0.45720],[1.4510366254336122,0.10159999999999998,0.45720],[1.4510366254336127,0.15239999999999998,0.45720],[1.4006811948619959,0.0,0.45720],[1.4006811948619964,0.050799999999999991,0.45720],[1.4006811948619970,0.10159999999999998,0.45720],[1.4006811948619975,0.15239999999999998,0.45720],[1.3503257642903805,0.0,0.45720],[1.3503257642903810,0.050799999999999991,0.45720],[1.3503257642903816,0.10159999999999998,0.45720],[1.3503257642903821,0.15239999999999998,0.45720],[1.2999703337187649,0.0,0.45720],[1.2999703337187654,0.050799999999999991,0.45720],[1.2999703337187660,0.10159999999999998,0.45720],[1.2999703337187665,0.15239999999999998,0.45720],[1.2496149031471502,0.0,0.45720],[1.2496149031471506,0.050799999999999991,0.45720],[1.2496149031471513,0.10159999999999998,0.45720],[1.2496149031471515,0.15239999999999998,0.45720],[1.1992594725755350,0.0,0.45720],[1.1992594725755352,0.050799999999999991,0.45720],[1.1992594725755361,0.10159999999999998,0.45720],[1.1992594725755363,0.15239999999999998,0.45720],[1.1489040420039194,0.0,0.45720],[1.1489040420039198,0.050799999999999991,0.45720],[1.1489040420039205,0.10159999999999998,0.45720],[1.1489040420039209,0.15239999999999998,0.45720],[1.0985486114323038,0.0,0.45720],[1.0985486114323042,0.050799999999999991,0.45720],[1.0985486114323049,0.10159999999999998,0.45720],[1.0985486114323053,0.15239999999999998,0.45720],[1.0481931808606890,0.0,0.45720],[1.0481931808606892,0.050799999999999991,0.45720],[1.0481931808606901,0.10159999999999998,0.45720],[1.0481931808606904,0.15239999999999998,0.45720],[0.99783775028907373,0.0,0.45720],[0.99783775028907407,0.050799999999999991,0.45720],[0.99783775028907484,0.10159999999999998,0.45720],[0.99783775028907518,0.15239999999999998,0.45720],[0.94748231971745811,0.0,0.45720],[0.94748231971745844,0.050799999999999991,0.45720],[0.94748231971745922,0.10159999999999998,0.45720],[0.94748231971745955,0.15239999999999998,0.45720],[0.89712688914584293,0.0,0.45720],[0.89712688914584326,0.050799999999999991,0.45720],[0.89712688914584404,0.10159999999999998,0.45720],[0.89712688914584438,0.15239999999999998,0.45720],[0.84677145857422764,0.0,0.45720],[0.84677145857422809,0.050799999999999991,0.45720],[0.84677145857422875,0.10159999999999998,0.45720],[0.84677145857422920,0.15239999999999998,0.45720],[0.79641602800261246,0.0,0.45720],[0.79641602800261280,0.050799999999999991,0.45720],[0.79641602800261357,0.10159999999999998,0.45720],[0.79641602800261391,0.15239999999999998,0.45720],[0.74606059743099684,0.0,0.45720],[0.74606059743099729,0.050799999999999991,0.45720],[0.74606059743099795,0.10159999999999998,0.45720],[0.74606059743099840,0.15239999999999998,0.45720],[0.69570516685938166,0.0,0.45720],[0.6957051668593820,0.050799999999999991,0.45720],[0.69570516685938277,0.10159999999999998,0.45720],[0.69570516685938311,0.15239999999999998,0.45720],[0.64534973628776648,0.0,0.45720],[0.64534973628776682,0.050799999999999991,0.45720],[0.64534973628776759,0.10159999999999998,0.45720],[0.64534973628776793,0.15239999999999998,0.45720],[0.59499430571615120,0.0,0.45720],[0.59499430571615164,0.050799999999999991,0.45720],[0.59499430571615231,0.10159999999999998,0.45720],[0.59499430571615275,0.15239999999999998,0.45720],[0.54463887514453568,0.0,0.45720],[0.54463887514453602,0.050799999999999991,0.45720],[0.54463887514453679,0.10159999999999998,0.45720],[0.54463887514453713,0.15239999999999998,0.45720],[0.49428344457292045,0.0,0.45720],[0.49428344457292078,0.050799999999999991,0.45720],[0.49428344457292150,0.10159999999999998,0.45720],[0.49428344457292189,0.15239999999999998,0.45720],[0.44392801400130522,0.0,0.45720],[0.44392801400130560,0.050799999999999991,0.45720],[0.44392801400130633,0.10159999999999998,0.45720],[0.44392801400130666,0.15239999999999998,0.45720],[0.39357258342968998,0.0,0.45720],[0.39357258342969037,0.050799999999999991,0.45720],[0.39357258342969109,0.10159999999999998,0.45720],[0.39357258342969148,0.15239999999999998,0.45720],[0.34321715285807480,0.0,0.45720],[0.34321715285807514,0.050799999999999991,0.45720],[0.34321715285807586,0.10159999999999998,0.45720],[0.34321715285807625,0.15239999999999998,0.45720],[0.29286172228645918,0.0,0.45720],[0.29286172228645957,0.050799999999999991,0.45720],[0.29286172228646029,0.10159999999999998,0.45720],[0.29286172228646068,0.15239999999999998,0.45720],[0.24250629171484397,0.0,0.45720],[0.24250629171484434,0.050799999999999991,0.45720],[0.24250629171484508,0.10159999999999998,0.45720],[0.24250629171484545,0.15239999999999998,0.45720],[0.19215086114322877,0.0,0.45720],[0.19215086114322913,0.050799999999999991,0.45720],[0.19215086114322985,0.10159999999999998,0.45720],[0.19215086114323021,0.15239999999999998,0.45720],[0.14179543057161356,0.0,0.45720],[0.14179543057161392,0.050799999999999991,0.45720],[0.14179543057161464,0.10159999999999998,0.45720],[0.14179543057161501,0.15239999999999998,0.45720],[0.091439999999997967,0.0,0.45720],[0.091439999999998328,0.050799999999999991,0.45720],[0.091439999999999064,0.10159999999999998,0.45720],[0.091439999999999425,0.15239999999999998,0.45720],[2.9616995425820716,0.15239999999999998,0.0],[2.9616995425820711,0.10160,0.0],[2.9616995425820707,0.050800000000000005,0.0],[2.9616995425820702,0.0,0.0],[2.9113441120104562,0.15239999999999998,0.0],[2.9113441120104562,0.10160,0.0],[2.9113441120104553,0.050800000000000005,0.0],[2.9113441120104548,0.0,0.0],[2.8609886814388412,0.15239999999999998,0.0],[2.8609886814388408,0.10160,0.0],[2.8609886814388399,0.050800000000000005,0.0],[2.8609886814388399,0.0,0.0],[2.8106332508672254,0.15239999999999998,0.0],[2.8106332508672254,0.10160,0.0],[2.8106332508672245,0.050800000000000005,0.0],[2.8106332508672240,0.0,0.0],[2.7602778202956104,0.15239999999999998,0.0],[2.760277820295610,0.10160,0.0],[2.7602778202956091,0.050800000000000005,0.0],[2.7602778202956091,0.0,0.0],[2.7099223897239950,0.15239999999999998,0.0],[2.7099223897239946,0.10160,0.0],[2.7099223897239941,0.050800000000000005,0.0],[2.7099223897239937,0.0,0.0],[2.6595669591523801,0.15239999999999998,0.0],[2.6595669591523796,0.10160,0.0],[2.6595669591523787,0.050800000000000005,0.0],[2.6595669591523783,0.0,0.0],[2.6092115285807647,0.15239999999999998,0.0],[2.6092115285807638,0.10160,0.0],[2.6092115285807633,0.050800000000000005,0.0],[2.6092115285807633,0.0,0.0],[2.5588560980091493,0.15239999999999998,0.0],[2.5588560980091488,0.10160,0.0],[2.5588560980091479,0.050800000000000005,0.0],[2.5588560980091475,0.0,0.0],[2.5085006674375339,0.15239999999999998,0.0],[2.5085006674375334,0.10160,0.0],[2.5085006674375330,0.050800000000000005,0.0],[2.5085006674375325,0.0,0.0],[2.4581452368659185,0.15239999999999998,0.0],[2.4581452368659185,0.10160,0.0],[2.4581452368659176,0.050800000000000005,0.0],[2.4581452368659171,0.0,0.0],[2.4077898062943031,0.15239999999999998,0.0],[2.4077898062943031,0.10160,0.0],[2.4077898062943022,0.050800000000000005,0.0],[2.4077898062943017,0.0,0.0],[2.3574343757226877,0.15239999999999998,0.0],[2.3574343757226877,0.10160,0.0],[2.3574343757226868,0.050800000000000005,0.0],[2.3574343757226863,0.0,0.0],[2.3070789451510727,0.15239999999999998,0.0],[2.3070789451510723,0.10160,0.0],[2.3070789451510714,0.050800000000000005,0.0],[2.3070789451510714,0.0,0.0],[2.2567235145794573,0.15239999999999998,0.0],[2.2567235145794569,0.10160,0.0],[2.2567235145794564,0.050800000000000005,0.0],[2.2567235145794560,0.0,0.0],[2.2063680840078423,0.15239999999999998,0.0],[2.2063680840078419,0.10160,0.0],[2.2063680840078410,0.050800000000000005,0.0],[2.2063680840078406,0.0,0.0],[2.1560126534362265,0.15239999999999998,0.0],[2.1560126534362265,0.10160,0.0],[2.1560126534362261,0.050800000000000005,0.0],[2.1560126534362252,0.0,0.0],[2.1056572228646120,0.15239999999999998,0.0],[2.1056572228646111,0.10160,0.0],[2.1056572228646102,0.050800000000000005,0.0],[2.1056572228646102,0.0,0.0],[2.0553017922929961,0.15239999999999998,0.0],[2.0553017922929957,0.10160,0.0],[2.0553017922929953,0.050800000000000005,0.0],[2.0553017922929948,0.0,0.0],[2.0049463617213812,0.15239999999999998,0.0],[2.0049463617213807,0.10160,0.0],[2.0049463617213799,0.050800000000000005,0.0],[2.0049463617213794,0.0,0.0],[1.9545909311497658,0.15239999999999998,0.0],[1.9545909311497651,0.10160,0.0],[1.9545909311497642,0.050800000000000005,0.0],[1.9545909311497642,0.0,0.0],[1.9042355005781502,0.15239999999999998,0.0],[1.9042355005781502,0.10160,0.0],[1.9042355005781495,0.050800000000000005,0.0],[1.9042355005781488,0.0,0.0],[1.8538800700065350,0.15239999999999998,0.0],[1.8538800700065345,0.10160,0.0],[1.8538800700065339,0.050800000000000005,0.0],[1.8538800700065334,0.0,0.0],[1.8035246394349198,0.15239999999999998,0.0],[1.8035246394349194,0.10160,0.0],[1.8035246394349187,0.050800000000000005,0.0],[1.8035246394349183,0.0,0.0],[1.7531692088633042,0.15239999999999998,0.0],[1.7531692088633042,0.10160,0.0],[1.7531692088633035,0.050800000000000005,0.0],[1.7531692088633026,0.0,0.0],[1.7028137782916892,0.15239999999999998,0.0],[1.7028137782916886,0.10160,0.0],[1.7028137782916879,0.050800000000000005,0.0],[1.7028137782916879,0.0,0.0],[1.6524583477200738,0.15239999999999998,0.0],[1.6524583477200738,0.10160,0.0],[1.6524583477200729,0.050800000000000005,0.0],[1.6524583477200723,0.0,0.0],[1.6021029171484584,0.15239999999999998,0.0],[1.6021029171484582,0.10160,0.0],[1.6021029171484573,0.050800000000000005,0.0],[1.6021029171484571,0.0,0.0],[1.5517474865768432,0.15239999999999998,0.0],[1.5517474865768430,0.10160,0.0],[1.5517474865768421,0.050800000000000005,0.0],[1.5517474865768419,0.0,0.0],[1.5013920560052276,0.15239999999999998,0.0],[1.5013920560052274,0.10160,0.0],[1.5013920560052265,0.050800000000000005,0.0],[1.5013920560052263,0.0,0.0],[1.4510366254336127,0.15239999999999998,0.0],[1.4510366254336122,0.10160,0.0],[1.4510366254336116,0.050800000000000005,0.0],[1.4510366254336111,0.0,0.0],[1.4006811948619975,0.15239999999999998,0.0],[1.4006811948619970,0.10160,0.0],[1.4006811948619964,0.050800000000000005,0.0],[1.4006811948619959,0.0,0.0],[1.3503257642903821,0.15239999999999998,0.0],[1.3503257642903816,0.10160,0.0],[1.3503257642903810,0.050800000000000005,0.0],[1.3503257642903805,0.0,0.0],[1.2999703337187665,0.15239999999999998,0.0],[1.2999703337187660,0.10160,0.0],[1.2999703337187654,0.050800000000000005,0.0],[1.2999703337187649,0.0,0.0],[1.2496149031471515,0.15239999999999998,0.0],[1.2496149031471513,0.10160,0.0],[1.2496149031471506,0.050800000000000005,0.0],[1.2496149031471502,0.0,0.0],[1.1992594725755363,0.15239999999999998,0.0],[1.1992594725755361,0.10160,0.0],[1.1992594725755352,0.050800000000000005,0.0],[1.1992594725755350,0.0,0.0],[1.1489040420039209,0.15239999999999998,0.0],[1.1489040420039205,0.10160,0.0],[1.1489040420039198,0.050800000000000005,0.0],[1.1489040420039194,0.0,0.0],[1.0985486114323053,0.15239999999999998,0.0],[1.0985486114323049,0.10160,0.0],[1.0985486114323042,0.050800000000000005,0.0],[1.0985486114323038,0.0,0.0],[1.0481931808606904,0.15239999999999998,0.0],[1.0481931808606901,0.10160,0.0],[1.0481931808606892,0.050800000000000005,0.0],[1.0481931808606890,0.0,0.0],[0.99783775028907518,0.15239999999999998,0.0],[0.99783775028907484,0.10160,0.0],[0.99783775028907407,0.050800000000000005,0.0],[0.99783775028907373,0.0,0.0],[0.94748231971745955,0.15239999999999998,0.0],[0.94748231971745922,0.10160,0.0],[0.94748231971745844,0.050800000000000005,0.0],[0.94748231971745811,0.0,0.0],[0.89712688914584438,0.15239999999999998,0.0],[0.89712688914584404,0.10160,0.0],[0.89712688914584326,0.050800000000000005,0.0],[0.89712688914584293,0.0,0.0],[0.84677145857422920,0.15239999999999998,0.0],[0.84677145857422875,0.10160,0.0],[0.84677145857422809,0.050800000000000005,0.0],[0.84677145857422764,0.0,0.0],[0.79641602800261391,0.15239999999999998,0.0],[0.79641602800261357,0.10160,0.0],[0.79641602800261280,0.050800000000000005,0.0],[0.79641602800261246,0.0,0.0],[0.74606059743099840,0.15239999999999998,0.0],[0.74606059743099795,0.10160,0.0],[0.74606059743099729,0.050800000000000005,0.0],[0.74606059743099684,0.0,0.0],[0.69570516685938311,0.15239999999999998,0.0],[0.69570516685938277,0.10160,0.0],[0.6957051668593820,0.050800000000000005,0.0],[0.69570516685938166,0.0,0.0],[0.64534973628776793,0.15239999999999998,0.0],[0.64534973628776759,0.10160,0.0],[0.64534973628776682,0.050800000000000005,0.0],[0.64534973628776648,0.0,0.0],[0.59499430571615275,0.15239999999999998,0.0],[0.59499430571615231,0.10160,0.0],[0.59499430571615164,0.050800000000000005,0.0],[0.59499430571615120,0.0,0.0],[0.54463887514453713,0.15239999999999998,0.0],[0.54463887514453679,0.10160,0.0],[0.54463887514453602,0.050800000000000005,0.0],[0.54463887514453568,0.0,0.0],[0.49428344457292189,0.15239999999999998,0.0],[0.49428344457292150,0.10160,0.0],[0.49428344457292078,0.050800000000000005,0.0],[0.49428344457292045,0.0,0.0],[0.44392801400130666,0.15239999999999998,0.0],[0.44392801400130633,0.10160,0.0],[0.44392801400130560,0.050800000000000005,0.0],[0.44392801400130522,0.0,0.0],[0.39357258342969148,0.15239999999999998,0.0],[0.39357258342969109,0.10160,0.0],[0.39357258342969037,0.050800000000000005,0.0],[0.39357258342968998,0.0,0.0],[0.34321715285807625,0.15239999999999998,0.0],[0.34321715285807586,0.10160,0.0],[0.34321715285807514,0.050800000000000005,0.0],[0.34321715285807480,0.0,0.0],[0.29286172228646068,0.15239999999999998,0.0],[0.29286172228646029,0.10160,0.0],[0.29286172228645957,0.050800000000000005,0.0],[0.29286172228645918,0.0,0.0],[0.24250629171484545,0.15239999999999998,0.0],[0.24250629171484508,0.10160,0.0],[0.24250629171484434,0.050800000000000005,0.0],[0.24250629171484397,0.0,0.0],[0.19215086114323021,0.15239999999999998,0.0],[0.19215086114322985,0.10160,0.0],[0.19215086114322913,0.050800000000000005,0.0],[0.19215086114322877,0.0,0.0],[0.14179543057161501,0.15239999999999998,0.0],[0.14179543057161464,0.10160,0.0],[0.14179543057161392,0.050800000000000005,0.0],[0.14179543057161356,0.0,0.0],[0.091439999999999425,0.15239999999999998,0.0],[0.091439999999999064,0.10160,0.0],[0.091439999999998328,0.050800000000000005,0.0],[0.091439999999997967,0.0,0.0],[2.9616995425820716,0.15239999999999998,0.40640000000000004],[2.9616995425820711,0.10160,0.40640000000000004],[2.9616995425820707,0.050800000000000005,0.40640000000000004],[2.9616995425820702,0.0,0.40640000000000004],[2.9616995425820716,0.15239999999999998,0.35560000000000003],[2.9616995425820711,0.10160,0.35560000000000003],[2.9616995425820707,0.050800000000000005,0.35560000000000003],[2.9616995425820702,0.0,0.35560000000000003],[2.9616995425820716,0.15239999999999998,0.30480000000000002],[2.9616995425820711,0.10160,0.30480000000000002],[2.9616995425820707,0.050800000000000005,0.30480000000000002],[2.9616995425820702,0.0,0.30480000000000002],[2.9616995425820716,0.15239999999999998,0.2540],[2.9616995425820711,0.10160,0.2540],[2.9616995425820707,0.050800000000000005,0.2540],[2.9616995425820702,0.0,0.2540],[2.9616995425820716,0.15239999999999998,0.20320000000000002],[2.9616995425820711,0.10160,0.20320000000000002],[2.9616995425820707,0.050800000000000005,0.20320000000000002],[2.9616995425820702,0.0,0.20320000000000002],[2.9616995425820716,0.15239999999999998,0.15240000000000001],[2.9616995425820711,0.10160,0.15240000000000001],[2.9616995425820707,0.050800000000000005,0.15240000000000001],[2.9616995425820702,0.0,0.15240000000000001],[2.9616995425820716,0.15239999999999998,0.10160000000000005],[2.9616995425820711,0.10160,0.10160000000000005],[2.9616995425820707,0.050800000000000005,0.10160000000000005],[2.9616995425820702,0.0,0.10160000000000005],[2.9616995425820716,0.15239999999999998,0.050800000000000005],[2.9616995425820711,0.10160,0.050800000000000005],[2.9616995425820707,0.050800000000000005,0.050800000000000005],[2.9616995425820702,0.0,0.050800000000000005],[2.9113441120104548,0.0,0.40640000000000004],[2.8609886814388399,0.0,0.40640000000000004],[2.8106332508672240,0.0,0.40640000000000004],[2.7602778202956091,0.0,0.40640000000000004],[2.7099223897239937,0.0,0.40640000000000004],[2.6595669591523783,0.0,0.40640000000000004],[2.6092115285807633,0.0,0.40640000000000004],[2.5588560980091475,0.0,0.40640000000000004],[2.5085006674375325,0.0,0.40640000000000004],[2.4581452368659171,0.0,0.40640000000000004],[2.4077898062943017,0.0,0.40640000000000004],[2.3574343757226863,0.0,0.40640000000000004],[2.3070789451510714,0.0,0.40640000000000004],[2.2567235145794560,0.0,0.40640000000000004],[2.2063680840078406,0.0,0.40640000000000004],[2.1560126534362252,0.0,0.40640000000000004],[2.1056572228646102,0.0,0.40640000000000004],[2.0553017922929948,0.0,0.40640000000000004],[2.0049463617213794,0.0,0.40640000000000004],[1.9545909311497642,0.0,0.40640000000000004],[1.9042355005781488,0.0,0.40640000000000004],[1.8538800700065334,0.0,0.40640000000000004],[1.8035246394349183,0.0,0.40640000000000004],[1.7531692088633026,0.0,0.40640000000000004],[1.7028137782916879,0.0,0.40640000000000004],[1.6524583477200723,0.0,0.40640000000000004],[1.6021029171484571,0.0,0.40640000000000004],[1.5517474865768419,0.0,0.40640000000000004],[1.5013920560052263,0.0,0.40640000000000004],[1.4510366254336111,0.0,0.40640000000000004],[1.4006811948619959,0.0,0.40640000000000004],[1.3503257642903805,0.0,0.40640000000000004],[1.2999703337187649,0.0,0.40640000000000004],[1.2496149031471502,0.0,0.40640000000000004],[1.1992594725755350,0.0,0.40640000000000004],[1.1489040420039194,0.0,0.40640000000000004],[1.0985486114323038,0.0,0.40640000000000004],[1.0481931808606890,0.0,0.40640000000000004],[0.99783775028907373,0.0,0.40640000000000004],[0.94748231971745811,0.0,0.40640000000000004],[0.89712688914584293,0.0,0.40640000000000004],[0.84677145857422764,0.0,0.40640000000000004],[0.79641602800261246,0.0,0.40640000000000004],[0.74606059743099684,0.0,0.40640000000000004],[0.69570516685938166,0.0,0.40640000000000004],[0.64534973628776648,0.0,0.40640000000000004],[0.59499430571615120,0.0,0.40640000000000004],[0.54463887514453568,0.0,0.40640000000000004],[0.49428344457292045,0.0,0.40640000000000004],[0.44392801400130522,0.0,0.40640000000000004],[0.39357258342968998,0.0,0.40640000000000004],[0.34321715285807480,0.0,0.40640000000000004],[0.29286172228645918,0.0,0.40640000000000004],[0.24250629171484397,0.0,0.40640000000000004],[0.19215086114322877,0.0,0.40640000000000004],[0.14179543057161356,0.0,0.40640000000000004],[0.091439999999997967,0.0,0.40640000000000004],[2.9113441120104548,0.0,0.35560000000000003],[2.8609886814388399,0.0,0.35560000000000003],[2.8106332508672240,0.0,0.35560000000000003],[2.7602778202956091,0.0,0.35560000000000003],[2.7099223897239937,0.0,0.35560000000000003],[2.6595669591523783,0.0,0.35560000000000003],[2.6092115285807633,0.0,0.35560000000000003],[2.5588560980091475,0.0,0.35560000000000003],[2.5085006674375325,0.0,0.35560000000000003],[2.4581452368659171,0.0,0.35560000000000003],[2.4077898062943017,0.0,0.35560000000000003],[2.3574343757226863,0.0,0.35560000000000003],[2.3070789451510714,0.0,0.35560000000000003],[2.2567235145794560,0.0,0.35560000000000003],[2.2063680840078406,0.0,0.35560000000000003],[2.1560126534362252,0.0,0.35560000000000003],[2.1056572228646102,0.0,0.35560000000000003],[2.0553017922929948,0.0,0.35560000000000003],[2.0049463617213794,0.0,0.35560000000000003],[1.9545909311497642,0.0,0.35560000000000003],[1.9042355005781488,0.0,0.35560000000000003],[1.8538800700065334,0.0,0.35560000000000003],[1.8035246394349183,0.0,0.35560000000000003],[1.7531692088633026,0.0,0.35560000000000003],[1.7028137782916879,0.0,0.35560000000000003],[1.6524583477200723,0.0,0.35560000000000003],[1.6021029171484571,0.0,0.35560000000000003],[1.5517474865768419,0.0,0.35560000000000003],[1.5013920560052263,0.0,0.35560000000000003],[1.4510366254336111,0.0,0.35560000000000003],[1.4006811948619959,0.0,0.35560000000000003],[1.3503257642903805,0.0,0.35560000000000003],[1.2999703337187649,0.0,0.35560000000000003],[1.2496149031471502,0.0,0.35560000000000003],[1.1992594725755350,0.0,0.35560000000000003],[1.1489040420039194,0.0,0.35560000000000003],[1.0985486114323038,0.0,0.35560000000000003],[1.0481931808606890,0.0,0.35560000000000003],[0.99783775028907373,0.0,0.35560000000000003],[0.94748231971745811,0.0,0.35560000000000003],[0.89712688914584293,0.0,0.35560000000000003],[0.84677145857422764,0.0,0.35560000000000003],[0.79641602800261246,0.0,0.35560000000000003],[0.74606059743099684,0.0,0.35560000000000003],[0.69570516685938166,0.0,0.35560000000000003],[0.64534973628776648,0.0,0.35560000000000003],[0.59499430571615120,0.0,0.35560000000000003],[0.54463887514453568,0.0,0.35560000000000003],[0.49428344457292045,0.0,0.35560000000000003],[0.44392801400130522,0.0,0.35560000000000003],[0.39357258342968998,0.0,0.35560000000000003],[0.34321715285807480,0.0,0.35560000000000003],[0.29286172228645918,0.0,0.35560000000000003],[0.24250629171484397,0.0,0.35560000000000003],[0.19215086114322877,0.0,0.35560000000000003],[0.14179543057161356,0.0,0.35560000000000003],[0.091439999999997967,0.0,0.35560000000000003],[2.9113441120104548,0.0,0.30480000000000007],[2.8609886814388399,0.0,0.30480000000000002],[2.8106332508672240,0.0,0.30480000000000002],[2.7602778202956091,0.0,0.30480000000000002],[2.7099223897239937,0.0,0.30480000000000002],[2.6595669591523783,0.0,0.30480000000000002],[2.6092115285807633,0.0,0.30480000000000002],[2.5588560980091475,0.0,0.30480000000000002],[2.5085006674375325,0.0,0.30480000000000002],[2.4581452368659171,0.0,0.30480000000000002],[2.4077898062943017,0.0,0.30480000000000002],[2.3574343757226863,0.0,0.30480000000000002],[2.3070789451510714,0.0,0.30480000000000002],[2.2567235145794560,0.0,0.30480000000000002],[2.2063680840078406,0.0,0.30480000000000002],[2.1560126534362252,0.0,0.30480000000000002],[2.1056572228646102,0.0,0.30480000000000002],[2.0553017922929948,0.0,0.30480000000000002],[2.0049463617213794,0.0,0.30480000000000002],[1.9545909311497642,0.0,0.30480000000000002],[1.9042355005781488,0.0,0.30480000000000002],[1.8538800700065334,0.0,0.30480000000000002],[1.8035246394349183,0.0,0.30480000000000002],[1.7531692088633026,0.0,0.30480000000000002],[1.7028137782916879,0.0,0.30480000000000002],[1.6524583477200723,0.0,0.30480000000000002],[1.6021029171484571,0.0,0.30480000000000002],[1.5517474865768419,0.0,0.30480000000000002],[1.5013920560052263,0.0,0.30480000000000002],[1.4510366254336111,0.0,0.30480000000000002],[1.4006811948619959,0.0,0.30480000000000002],[1.3503257642903805,0.0,0.30480000000000002],[1.2999703337187649,0.0,0.30480000000000002],[1.2496149031471502,0.0,0.30480000000000002],[1.1992594725755350,0.0,0.30480000000000002],[1.1489040420039194,0.0,0.30480000000000002],[1.0985486114323038,0.0,0.30480000000000002],[1.0481931808606890,0.0,0.30480000000000002],[0.99783775028907373,0.0,0.30480000000000002],[0.94748231971745811,0.0,0.30480000000000002],[0.89712688914584293,0.0,0.30480000000000002],[0.84677145857422764,0.0,0.30480000000000002],[0.79641602800261246,0.0,0.30480000000000002],[0.74606059743099684,0.0,0.30480000000000002],[0.69570516685938166,0.0,0.30480000000000002],[0.64534973628776648,0.0,0.30480000000000002],[0.59499430571615120,0.0,0.30480000000000002],[0.54463887514453568,0.0,0.30480000000000002],[0.49428344457292045,0.0,0.30480000000000002],[0.44392801400130522,0.0,0.30480000000000002],[0.39357258342968998,0.0,0.30480000000000002],[0.34321715285807480,0.0,0.30480000000000002],[0.29286172228645918,0.0,0.30480000000000002],[0.24250629171484397,0.0,0.30480000000000002],[0.19215086114322877,0.0,0.30480000000000002],[0.14179543057161356,0.0,0.30480000000000002],[0.091439999999997967,0.0,0.30480000000000002],[2.9113441120104548,0.0,0.25400000000000006],[2.8609886814388399,0.0,0.2540],[2.8106332508672240,0.0,0.2540],[2.7602778202956091,0.0,0.2540],[2.7099223897239937,0.0,0.2540],[2.6595669591523783,0.0,0.2540],[2.6092115285807633,0.0,0.2540],[2.5588560980091475,0.0,0.2540],[2.5085006674375325,0.0,0.2540],[2.4581452368659171,0.0,0.2540],[2.4077898062943017,0.0,0.2540],[2.3574343757226863,0.0,0.2540],[2.3070789451510714,0.0,0.2540],[2.2567235145794560,0.0,0.2540],[2.2063680840078406,0.0,0.2540],[2.1560126534362252,0.0,0.2540],[2.1056572228646102,0.0,0.2540],[2.0553017922929948,0.0,0.2540],[2.0049463617213794,0.0,0.2540],[1.9545909311497642,0.0,0.2540],[1.9042355005781488,0.0,0.2540],[1.8538800700065334,0.0,0.2540],[1.8035246394349183,0.0,0.2540],[1.7531692088633026,0.0,0.2540],[1.7028137782916879,0.0,0.2540],[1.6524583477200723,0.0,0.2540],[1.6021029171484571,0.0,0.2540],[1.5517474865768419,0.0,0.2540],[1.5013920560052263,0.0,0.2540],[1.4510366254336111,0.0,0.2540],[1.4006811948619959,0.0,0.2540],[1.3503257642903805,0.0,0.2540],[1.2999703337187649,0.0,0.2540],[1.2496149031471502,0.0,0.2540],[1.1992594725755350,0.0,0.2540],[1.1489040420039194,0.0,0.2540],[1.0985486114323038,0.0,0.2540],[1.0481931808606890,0.0,0.2540],[0.99783775028907373,0.0,0.2540],[0.94748231971745811,0.0,0.2540],[0.89712688914584293,0.0,0.2540],[0.84677145857422764,0.0,0.2540],[0.79641602800261246,0.0,0.2540],[0.74606059743099684,0.0,0.2540],[0.69570516685938166,0.0,0.2540],[0.64534973628776648,0.0,0.2540],[0.59499430571615120,0.0,0.2540],[0.54463887514453568,0.0,0.2540],[0.49428344457292045,0.0,0.2540],[0.44392801400130522,0.0,0.2540],[0.39357258342968998,0.0,0.2540],[0.34321715285807480,0.0,0.2540],[0.29286172228645918,0.0,0.2540],[0.24250629171484397,0.0,0.2540],[0.19215086114322877,0.0,0.2540],[0.14179543057161356,0.0,0.2540],[0.091439999999997967,0.0,0.2540],[2.9113441120104548,0.0,0.20320000000000005],[2.8609886814388399,0.0,0.20320000000000002],[2.8106332508672240,0.0,0.20320000000000002],[2.7602778202956091,0.0,0.20320000000000002],[2.7099223897239937,0.0,0.20320000000000002],[2.6595669591523783,0.0,0.20320000000000002],[2.6092115285807633,0.0,0.20320000000000002],[2.5588560980091475,0.0,0.20320000000000002],[2.5085006674375325,0.0,0.20320000000000002],[2.4581452368659171,0.0,0.20320000000000002],[2.4077898062943017,0.0,0.20320000000000002],[2.3574343757226863,0.0,0.20320000000000002],[2.3070789451510714,0.0,0.20320000000000002],[2.2567235145794560,0.0,0.20320000000000002],[2.2063680840078406,0.0,0.20320000000000002],[2.1560126534362252,0.0,0.20320000000000002],[2.1056572228646102,0.0,0.20320000000000002],[2.0553017922929948,0.0,0.20320000000000002],[2.0049463617213794,0.0,0.20320000000000002],[1.9545909311497642,0.0,0.20320000000000002],[1.9042355005781488,0.0,0.20320000000000002],[1.8538800700065334,0.0,0.20320000000000002],[1.8035246394349183,0.0,0.20320000000000002],[1.7531692088633026,0.0,0.20320000000000002],[1.7028137782916879,0.0,0.20320000000000002],[1.6524583477200723,0.0,0.20320000000000002],[1.6021029171484571,0.0,0.20320000000000002],[1.5517474865768419,0.0,0.20320000000000002],[1.5013920560052263,0.0,0.20320000000000002],[1.4510366254336111,0.0,0.20320000000000002],[1.4006811948619959,0.0,0.20320000000000002],[1.3503257642903805,0.0,0.20320000000000002],[1.2999703337187649,0.0,0.20320000000000002],[1.2496149031471502,0.0,0.20320000000000002],[1.1992594725755350,0.0,0.20320000000000002],[1.1489040420039194,0.0,0.20320000000000002],[1.0985486114323038,0.0,0.20320000000000002],[1.0481931808606890,0.0,0.20320000000000002],[0.99783775028907373,0.0,0.20320000000000002],[0.94748231971745811,0.0,0.20320000000000002],[0.89712688914584293,0.0,0.20320000000000002],[0.84677145857422764,0.0,0.20320000000000002],[0.79641602800261246,0.0,0.20320000000000002],[0.74606059743099684,0.0,0.20320000000000002],[0.69570516685938166,0.0,0.20320000000000002],[0.64534973628776648,0.0,0.20320000000000002],[0.59499430571615120,0.0,0.20320000000000002],[0.54463887514453568,0.0,0.20320000000000002],[0.49428344457292045,0.0,0.20320000000000002],[0.44392801400130522,0.0,0.20320000000000002],[0.39357258342968998,0.0,0.20320000000000002],[0.34321715285807480,0.0,0.20320000000000002],[0.29286172228645918,0.0,0.20320000000000002],[0.24250629171484397,0.0,0.20320000000000002],[0.19215086114322877,0.0,0.20320000000000002],[0.14179543057161356,0.0,0.20320000000000002],[0.091439999999997967,0.0,0.20320000000000002],[2.9113441120104548,0.0,0.15240000000000009],[2.8609886814388399,0.0,0.15240000000000001],[2.8106332508672240,0.0,0.15240000000000001],[2.7602778202956091,0.0,0.15240000000000001],[2.7099223897239937,0.0,0.15240000000000001],[2.6595669591523783,0.0,0.15240000000000001],[2.6092115285807633,0.0,0.15240000000000001],[2.5588560980091475,0.0,0.15240000000000001],[2.5085006674375325,0.0,0.15240000000000001],[2.4581452368659171,0.0,0.15240000000000001],[2.4077898062943017,0.0,0.15240000000000001],[2.3574343757226863,0.0,0.15240000000000001],[2.3070789451510714,0.0,0.15240000000000001],[2.2567235145794560,0.0,0.15240000000000001],[2.2063680840078406,0.0,0.15240000000000001],[2.1560126534362252,0.0,0.15240000000000001],[2.1056572228646102,0.0,0.15240000000000001],[2.0553017922929948,0.0,0.15240000000000001],[2.0049463617213794,0.0,0.15240000000000001],[1.9545909311497642,0.0,0.15240000000000001],[1.9042355005781488,0.0,0.15240000000000001],[1.8538800700065334,0.0,0.15240000000000001],[1.8035246394349183,0.0,0.15240000000000001],[1.7531692088633026,0.0,0.15240000000000001],[1.7028137782916879,0.0,0.15240000000000001],[1.6524583477200723,0.0,0.15240000000000001],[1.6021029171484571,0.0,0.15240000000000001],[1.5517474865768419,0.0,0.15240000000000001],[1.5013920560052263,0.0,0.15240000000000001],[1.4510366254336111,0.0,0.15240000000000001],[1.4006811948619959,0.0,0.15240000000000001],[1.3503257642903805,0.0,0.15240000000000001],[1.2999703337187649,0.0,0.15240000000000001],[1.2496149031471502,0.0,0.15240000000000001],[1.1992594725755350,0.0,0.15240000000000001],[1.1489040420039194,0.0,0.15240000000000001],[1.0985486114323038,0.0,0.15240000000000001],[1.0481931808606890,0.0,0.15240000000000001],[0.99783775028907373,0.0,0.15240000000000001],[0.94748231971745811,0.0,0.15240000000000001],[0.89712688914584293,0.0,0.15240000000000001],[0.84677145857422764,0.0,0.15240000000000001],[0.79641602800261246,0.0,0.15240000000000001],[0.74606059743099684,0.0,0.15240000000000001],[0.69570516685938166,0.0,0.15240000000000001],[0.64534973628776648,0.0,0.15240000000000001],[0.59499430571615120,0.0,0.15240000000000001],[0.54463887514453568,0.0,0.15240000000000001],[0.49428344457292045,0.0,0.15240000000000001],[0.44392801400130522,0.0,0.15240000000000001],[0.39357258342968998,0.0,0.15240000000000001],[0.34321715285807480,0.0,0.15240000000000001],[0.29286172228645918,0.0,0.15240000000000001],[0.24250629171484397,0.0,0.15240000000000001],[0.19215086114322877,0.0,0.15240000000000001],[0.14179543057161356,0.0,0.15240000000000001],[0.091439999999997967,0.0,0.15240000000000001],[2.9113441120104548,0.0,0.10160000000000013],[2.8609886814388399,0.0,0.10160000000000005],[2.8106332508672240,0.0,0.10160000000000005],[2.7602778202956091,0.0,0.10160000000000005],[2.7099223897239937,0.0,0.10160000000000005],[2.6595669591523783,0.0,0.10160000000000005],[2.6092115285807633,0.0,0.10160000000000005],[2.5588560980091475,0.0,0.10160000000000005],[2.5085006674375325,0.0,0.10160000000000005],[2.4581452368659171,0.0,0.10160000000000005],[2.4077898062943017,0.0,0.10160000000000005],[2.3574343757226863,0.0,0.10160000000000005],[2.3070789451510714,0.0,0.10160000000000005],[2.2567235145794560,0.0,0.10160000000000005],[2.2063680840078406,0.0,0.10160000000000005],[2.1560126534362252,0.0,0.10160000000000005],[2.1056572228646102,0.0,0.10160000000000005],[2.0553017922929948,0.0,0.10160000000000005],[2.0049463617213794,0.0,0.10160000000000005],[1.9545909311497642,0.0,0.10160000000000005],[1.9042355005781488,0.0,0.10160000000000005],[1.8538800700065334,0.0,0.10160000000000005],[1.8035246394349183,0.0,0.10160000000000005],[1.7531692088633026,0.0,0.10160000000000005],[1.7028137782916879,0.0,0.10160000000000005],[1.6524583477200723,0.0,0.10160000000000005],[1.6021029171484571,0.0,0.10160000000000005],[1.5517474865768419,0.0,0.10160000000000005],[1.5013920560052263,0.0,0.10160000000000005],[1.4510366254336111,0.0,0.10160000000000005],[1.4006811948619959,0.0,0.10160000000000005],[1.3503257642903805,0.0,0.10160000000000005],[1.2999703337187649,0.0,0.10160000000000005],[1.2496149031471502,0.0,0.10160000000000005],[1.1992594725755350,0.0,0.10160000000000005],[1.1489040420039194,0.0,0.10160000000000005],[1.0985486114323038,0.0,0.10160000000000005],[1.0481931808606890,0.0,0.10160000000000005],[0.99783775028907373,0.0,0.10160000000000005],[0.94748231971745811,0.0,0.10160000000000005],[0.89712688914584293,0.0,0.10160000000000005],[0.84677145857422764,0.0,0.10160000000000005],[0.79641602800261246,0.0,0.10160000000000005],[0.74606059743099684,0.0,0.10160000000000005],[0.69570516685938166,0.0,0.10160000000000005],[0.64534973628776648,0.0,0.10160000000000005],[0.59499430571615120,0.0,0.10160000000000005],[0.54463887514453568,0.0,0.10160000000000005],[0.49428344457292045,0.0,0.10160000000000005],[0.44392801400130522,0.0,0.10160000000000005],[0.39357258342968998,0.0,0.10160000000000005],[0.34321715285807480,0.0,0.10160000000000005],[0.29286172228645918,0.0,0.10160000000000005],[0.24250629171484397,0.0,0.10160000000000005],[0.19215086114322877,0.0,0.10160000000000005],[0.14179543057161356,0.0,0.10160000000000005],[0.091439999999997967,0.0,0.10160000000000005],[2.9113441120104548,0.0,0.050800000000000095],[2.8609886814388399,0.0,0.050800000000000005],[2.8106332508672240,0.0,0.050800000000000005],[2.7602778202956091,0.0,0.050800000000000005],[2.7099223897239937,0.0,0.050800000000000005],[2.6595669591523783,0.0,0.050800000000000005],[2.6092115285807633,0.0,0.050800000000000005],[2.5588560980091475,0.0,0.050800000000000005],[2.5085006674375325,0.0,0.050800000000000005],[2.4581452368659171,0.0,0.050800000000000005],[2.4077898062943017,0.0,0.050800000000000005],[2.3574343757226863,0.0,0.050800000000000005],[2.3070789451510714,0.0,0.050800000000000005],[2.2567235145794560,0.0,0.050800000000000005],[2.2063680840078406,0.0,0.050800000000000005],[2.1560126534362252,0.0,0.050800000000000005],[2.1056572228646102,0.0,0.050800000000000005],[2.0553017922929948,0.0,0.050800000000000005],[2.0049463617213794,0.0,0.050800000000000005],[1.9545909311497642,0.0,0.050800000000000005],[1.9042355005781488,0.0,0.050800000000000005],[1.8538800700065334,0.0,0.050800000000000005],[1.8035246394349183,0.0,0.050800000000000005],[1.7531692088633026,0.0,0.050800000000000005],[1.7028137782916879,0.0,0.050800000000000005],[1.6524583477200723,0.0,0.050800000000000005],[1.6021029171484571,0.0,0.050800000000000005],[1.5517474865768419,0.0,0.050800000000000005],[1.5013920560052263,0.0,0.050800000000000005],[1.4510366254336111,0.0,0.050800000000000005],[1.4006811948619959,0.0,0.050800000000000005],[1.3503257642903805,0.0,0.050800000000000005],[1.2999703337187649,0.0,0.050800000000000005],[1.2496149031471502,0.0,0.050800000000000005],[1.1992594725755350,0.0,0.050800000000000005],[1.1489040420039194,0.0,0.050800000000000005],[1.0985486114323038,0.0,0.050800000000000005],[1.0481931808606890,0.0,0.050800000000000005],[0.99783775028907373,0.0,0.050800000000000005],[0.94748231971745811,0.0,0.050800000000000005],[0.89712688914584293,0.0,0.050800000000000005],[0.84677145857422764,0.0,0.050800000000000005],[0.79641602800261246,0.0,0.050800000000000005],[0.74606059743099684,0.0,0.050800000000000005],[0.69570516685938166,0.0,0.050800000000000005],[0.64534973628776648,0.0,0.050800000000000005],[0.59499430571615120,0.0,0.050800000000000005],[0.54463887514453568,0.0,0.050800000000000005],[0.49428344457292045,0.0,0.050800000000000005],[0.44392801400130522,0.0,0.050800000000000005],[0.39357258342968998,0.0,0.050800000000000005],[0.34321715285807480,0.0,0.050800000000000005],[0.29286172228645918,0.0,0.050800000000000005],[0.24250629171484397,0.0,0.050800000000000005],[0.19215086114322877,0.0,0.050800000000000005],[0.14179543057161356,0.0,0.050800000000000005],[0.091439999999997967,0.0,0.050800000000000005],[0.091439999999998453,0.050799999999999991,0.40640000000000004],[0.091439999999998939,0.10159999999999998,0.40640000000000004],[0.091439999999999425,0.15239999999999998,0.40640000000000004],[0.091439999999998453,0.050799999999999991,0.35560000000000003],[0.091439999999998939,0.10159999999999998,0.35560000000000003],[0.091439999999999425,0.15239999999999998,0.35560000000000003],[0.091439999999998453,0.050799999999999991,0.30480000000000002],[0.091439999999998939,0.10159999999999998,0.30480000000000002],[0.091439999999999425,0.15239999999999998,0.30480000000000002],[0.091439999999998453,0.050799999999999991,0.2540],[0.091439999999998939,0.10159999999999998,0.2540],[0.091439999999999425,0.15239999999999998,0.2540],[0.091439999999998453,0.050799999999999991,0.20320000000000002],[0.091439999999998939,0.10159999999999998,0.20320000000000002],[0.091439999999999425,0.15239999999999998,0.20320000000000002],[0.091439999999998453,0.050799999999999991,0.15240000000000001],[0.091439999999998939,0.10159999999999998,0.15240000000000001],[0.091439999999999425,0.15239999999999998,0.15240000000000001],[0.091439999999998453,0.050799999999999991,0.10160000000000005],[0.091439999999998939,0.10159999999999998,0.10160000000000005],[0.091439999999999425,0.15239999999999998,0.10160000000000005],[0.091439999999998453,0.050799999999999991,0.050800000000000005],[0.091439999999998939,0.10159999999999998,0.050800000000000005],[0.091439999999999425,0.15239999999999998,0.050800000000000005],[0.14179543057161473,0.15239999999999998,0.40640000000000004],[0.19215086114323002,0.15239999999999998,0.40640000000000004],[0.24250629171484536,0.15239999999999998,0.40640000000000004],[0.29286172228646062,0.15239999999999998,0.40640000000000004],[0.34321715285807591,0.15239999999999998,0.40640000000000004],[0.39357258342969126,0.15239999999999998,0.40640000000000004],[0.44392801400130649,0.15239999999999998,0.40640000000000004],[0.49428344457292178,0.15239999999999998,0.40640000000000004],[0.54463887514453713,0.15239999999999998,0.40640000000000004],[0.59499430571615242,0.15239999999999998,0.40640000000000004],[0.64534973628776771,0.15239999999999998,0.40640000000000004],[0.6957051668593830,0.15239999999999998,0.40640000000000004],[0.74606059743099828,0.15239999999999998,0.40640000000000004],[0.79641602800261357,0.15239999999999998,0.40640000000000004],[0.84677145857422875,0.15239999999999998,0.40640000000000004],[0.89712688914584415,0.15239999999999998,0.40640000000000004],[0.94748231971745944,0.15239999999999998,0.40640000000000004],[0.99783775028907484,0.15239999999999998,0.40640000000000004],[1.0481931808606901,0.15239999999999998,0.40640000000000004],[1.0985486114323055,0.15239999999999998,0.40640000000000004],[1.1489040420039207,0.15239999999999998,0.40640000000000004],[1.1992594725755361,0.15239999999999998,0.40640000000000004],[1.2496149031471513,0.15239999999999998,0.40640000000000004],[1.2999703337187667,0.15239999999999998,0.40640000000000004],[1.3503257642903819,0.15239999999999998,0.40640000000000004],[1.4006811948619970,0.15239999999999998,0.40640000000000004],[1.4510366254336124,0.15239999999999998,0.40640000000000004],[1.5013920560052276,0.15239999999999998,0.40640000000000004],[1.5517474865768432,0.15239999999999998,0.40640000000000004],[1.6021029171484584,0.15239999999999998,0.40640000000000004],[1.6524583477200738,0.15239999999999998,0.40640000000000004],[1.7028137782916890,0.15239999999999998,0.40640000000000004],[1.7531692088633046,0.15239999999999998,0.40640000000000004],[1.8035246394349194,0.15239999999999998,0.40640000000000004],[1.8538800700065345,0.15239999999999998,0.40640000000000004],[1.9042355005781502,0.15239999999999998,0.40640000000000004],[1.9545909311497658,0.15239999999999998,0.40640000000000004],[2.0049463617213807,0.15239999999999998,0.40640000000000004],[2.0553017922929957,0.15239999999999998,0.40640000000000004],[2.1056572228646115,0.15239999999999998,0.40640000000000004],[2.1560126534362265,0.15239999999999998,0.40640000000000004],[2.2063680840078419,0.15239999999999998,0.40640000000000004],[2.2567235145794569,0.15239999999999998,0.40640000000000004],[2.3070789451510727,0.15239999999999998,0.40640000000000004],[2.3574343757226877,0.15239999999999998,0.40640000000000004],[2.4077898062943031,0.15239999999999998,0.40640000000000004],[2.4581452368659185,0.15239999999999998,0.40640000000000004],[2.5085006674375339,0.15239999999999998,0.40640000000000004],[2.5588560980091493,0.15239999999999998,0.40640000000000004],[2.6092115285807642,0.15239999999999998,0.40640000000000004],[2.6595669591523796,0.15239999999999998,0.40640000000000004],[2.7099223897239946,0.15239999999999998,0.40640000000000004],[2.7602778202956104,0.15239999999999998,0.40640000000000004],[2.8106332508672254,0.15239999999999998,0.40640000000000004],[2.8609886814388408,0.15239999999999998,0.40640000000000004],[2.9113441120104562,0.15239999999999998,0.40640000000000004],[0.14179543057161473,0.15239999999999998,0.35560000000000003],[0.19215086114323002,0.15239999999999998,0.35560000000000003],[0.24250629171484536,0.15239999999999998,0.35560000000000003],[0.29286172228646062,0.15239999999999998,0.35560000000000003],[0.34321715285807591,0.15239999999999998,0.35560000000000003],[0.39357258342969126,0.15239999999999998,0.35560000000000003],[0.44392801400130649,0.15239999999999998,0.35560000000000003],[0.49428344457292178,0.15239999999999998,0.35560000000000003],[0.54463887514453713,0.15239999999999998,0.35560000000000003],[0.59499430571615242,0.15239999999999998,0.35560000000000003],[0.64534973628776771,0.15239999999999998,0.35560000000000003],[0.6957051668593830,0.15239999999999998,0.35560000000000003],[0.74606059743099828,0.15239999999999998,0.35560000000000003],[0.79641602800261357,0.15239999999999998,0.35560000000000003],[0.84677145857422875,0.15239999999999998,0.35560000000000003],[0.89712688914584415,0.15239999999999998,0.35560000000000003],[0.94748231971745944,0.15239999999999998,0.35560000000000003],[0.99783775028907484,0.15239999999999998,0.35560000000000003],[1.0481931808606901,0.15239999999999998,0.35560000000000003],[1.0985486114323055,0.15239999999999998,0.35560000000000003],[1.1489040420039207,0.15239999999999998,0.35560000000000003],[1.1992594725755361,0.15239999999999998,0.35560000000000003],[1.2496149031471513,0.15239999999999998,0.35560000000000003],[1.2999703337187667,0.15239999999999998,0.35560000000000003],[1.3503257642903819,0.15239999999999998,0.35560000000000003],[1.4006811948619970,0.15239999999999998,0.35560000000000003],[1.4510366254336124,0.15239999999999998,0.35560000000000003],[1.5013920560052276,0.15239999999999998,0.35560000000000003],[1.5517474865768432,0.15239999999999998,0.35560000000000003],[1.6021029171484584,0.15239999999999998,0.35560000000000003],[1.6524583477200738,0.15239999999999998,0.35560000000000003],[1.7028137782916890,0.15239999999999998,0.35560000000000003],[1.7531692088633046,0.15239999999999998,0.35560000000000003],[1.8035246394349194,0.15239999999999998,0.35560000000000003],[1.8538800700065345,0.15239999999999998,0.35560000000000003],[1.9042355005781502,0.15239999999999998,0.35560000000000003],[1.9545909311497658,0.15239999999999998,0.35560000000000003],[2.0049463617213807,0.15239999999999998,0.35560000000000003],[2.0553017922929957,0.15239999999999998,0.35560000000000003],[2.1056572228646115,0.15239999999999998,0.35560000000000003],[2.1560126534362265,0.15239999999999998,0.35560000000000003],[2.2063680840078419,0.15239999999999998,0.35560000000000003],[2.2567235145794569,0.15239999999999998,0.35560000000000003],[2.3070789451510727,0.15239999999999998,0.35560000000000003],[2.3574343757226877,0.15239999999999998,0.35560000000000003],[2.4077898062943031,0.15239999999999998,0.35560000000000003],[2.4581452368659185,0.15239999999999998,0.35560000000000003],[2.5085006674375339,0.15239999999999998,0.35560000000000003],[2.5588560980091493,0.15239999999999998,0.35560000000000003],[2.6092115285807642,0.15239999999999998,0.35560000000000003],[2.6595669591523796,0.15239999999999998,0.35560000000000003],[2.7099223897239946,0.15239999999999998,0.35560000000000003],[2.7602778202956104,0.15239999999999998,0.35560000000000003],[2.8106332508672254,0.15239999999999998,0.35560000000000003],[2.8609886814388408,0.15239999999999998,0.35560000000000003],[2.9113441120104562,0.15239999999999998,0.35560000000000003],[0.14179543057161473,0.15239999999999998,0.30480000000000007],[0.19215086114323002,0.15239999999999998,0.30480000000000002],[0.24250629171484536,0.15239999999999998,0.30480000000000002],[0.29286172228646062,0.15239999999999998,0.30480000000000002],[0.34321715285807591,0.15239999999999998,0.30480000000000002],[0.39357258342969126,0.15239999999999998,0.30480000000000002],[0.44392801400130649,0.15239999999999998,0.30480000000000002],[0.49428344457292178,0.15239999999999998,0.30480000000000002],[0.54463887514453713,0.15239999999999998,0.30480000000000002],[0.59499430571615242,0.15239999999999998,0.30480000000000002],[0.64534973628776771,0.15239999999999998,0.30480000000000002],[0.6957051668593830,0.15239999999999998,0.30480000000000002],[0.74606059743099828,0.15239999999999998,0.30480000000000002],[0.79641602800261357,0.15239999999999998,0.30480000000000002],[0.84677145857422875,0.15239999999999998,0.30480000000000002],[0.89712688914584415,0.15239999999999998,0.30480000000000002],[0.94748231971745944,0.15239999999999998,0.30480000000000002],[0.99783775028907484,0.15239999999999998,0.30480000000000002],[1.0481931808606901,0.15239999999999998,0.30480000000000002],[1.0985486114323055,0.15239999999999998,0.30480000000000002],[1.1489040420039207,0.15239999999999998,0.30480000000000002],[1.1992594725755361,0.15239999999999998,0.30480000000000002],[1.2496149031471513,0.15239999999999998,0.30480000000000002],[1.2999703337187667,0.15239999999999998,0.30480000000000002],[1.3503257642903819,0.15239999999999998,0.30480000000000002],[1.4006811948619970,0.15239999999999998,0.30480000000000002],[1.4510366254336124,0.15239999999999998,0.30480000000000002],[1.5013920560052276,0.15239999999999998,0.30480000000000002],[1.5517474865768432,0.15239999999999998,0.30480000000000002],[1.6021029171484584,0.15239999999999998,0.30480000000000002],[1.6524583477200738,0.15239999999999998,0.30480000000000002],[1.7028137782916890,0.15239999999999998,0.30480000000000002],[1.7531692088633046,0.15239999999999998,0.30480000000000002],[1.8035246394349194,0.15239999999999998,0.30480000000000002],[1.8538800700065345,0.15239999999999998,0.30480000000000002],[1.9042355005781502,0.15239999999999998,0.30480000000000002],[1.9545909311497658,0.15239999999999998,0.30480000000000002],[2.0049463617213807,0.15239999999999998,0.30480000000000002],[2.0553017922929957,0.15239999999999998,0.30480000000000002],[2.1056572228646115,0.15239999999999998,0.30480000000000002],[2.1560126534362265,0.15239999999999998,0.30480000000000002],[2.2063680840078419,0.15239999999999998,0.30480000000000002],[2.2567235145794569,0.15239999999999998,0.30480000000000002],[2.3070789451510727,0.15239999999999998,0.30480000000000002],[2.3574343757226877,0.15239999999999998,0.30480000000000002],[2.4077898062943031,0.15239999999999998,0.30480000000000002],[2.4581452368659185,0.15239999999999998,0.30480000000000002],[2.5085006674375339,0.15239999999999998,0.30480000000000002],[2.5588560980091493,0.15239999999999998,0.30480000000000002],[2.6092115285807642,0.15239999999999998,0.30480000000000002],[2.6595669591523796,0.15239999999999998,0.30480000000000002],[2.7099223897239946,0.15239999999999998,0.30480000000000002],[2.7602778202956104,0.15239999999999998,0.30480000000000002],[2.8106332508672254,0.15239999999999998,0.30480000000000002],[2.8609886814388408,0.15239999999999998,0.30480000000000002],[2.9113441120104562,0.15239999999999998,0.30480000000000002],[0.14179543057161473,0.15239999999999998,0.25400000000000006],[0.19215086114323002,0.15239999999999998,0.2540],[0.24250629171484536,0.15239999999999998,0.2540],[0.29286172228646062,0.15239999999999998,0.2540],[0.34321715285807591,0.15239999999999998,0.2540],[0.39357258342969126,0.15239999999999998,0.2540],[0.44392801400130649,0.15239999999999998,0.2540],[0.49428344457292178,0.15239999999999998,0.2540],[0.54463887514453713,0.15239999999999998,0.2540],[0.59499430571615242,0.15239999999999998,0.2540],[0.64534973628776771,0.15239999999999998,0.2540],[0.6957051668593830,0.15239999999999998,0.2540],[0.74606059743099828,0.15239999999999998,0.2540],[0.79641602800261357,0.15239999999999998,0.2540],[0.84677145857422875,0.15239999999999998,0.2540],[0.89712688914584415,0.15239999999999998,0.2540],[0.94748231971745944,0.15239999999999998,0.2540],[0.99783775028907484,0.15239999999999998,0.2540],[1.0481931808606901,0.15239999999999998,0.2540],[1.0985486114323055,0.15239999999999998,0.2540],[1.1489040420039207,0.15239999999999998,0.2540],[1.1992594725755361,0.15239999999999998,0.2540],[1.2496149031471513,0.15239999999999998,0.2540],[1.2999703337187667,0.15239999999999998,0.2540],[1.3503257642903819,0.15239999999999998,0.2540],[1.4006811948619970,0.15239999999999998,0.2540],[1.4510366254336124,0.15239999999999998,0.2540],[1.5013920560052276,0.15239999999999998,0.2540],[1.5517474865768432,0.15239999999999998,0.2540],[1.6021029171484584,0.15239999999999998,0.2540],[1.6524583477200738,0.15239999999999998,0.2540],[1.7028137782916890,0.15239999999999998,0.2540],[1.7531692088633046,0.15239999999999998,0.2540],[1.8035246394349194,0.15239999999999998,0.2540],[1.8538800700065345,0.15239999999999998,0.2540],[1.9042355005781502,0.15239999999999998,0.2540],[1.9545909311497658,0.15239999999999998,0.2540],[2.0049463617213807,0.15239999999999998,0.2540],[2.0553017922929957,0.15239999999999998,0.2540],[2.1056572228646115,0.15239999999999998,0.2540],[2.1560126534362265,0.15239999999999998,0.2540],[2.2063680840078419,0.15239999999999998,0.2540],[2.2567235145794569,0.15239999999999998,0.2540],[2.3070789451510727,0.15239999999999998,0.2540],[2.3574343757226877,0.15239999999999998,0.2540],[2.4077898062943031,0.15239999999999998,0.2540],[2.4581452368659185,0.15239999999999998,0.2540],[2.5085006674375339,0.15239999999999998,0.2540],[2.5588560980091493,0.15239999999999998,0.2540],[2.6092115285807642,0.15239999999999998,0.2540],[2.6595669591523796,0.15239999999999998,0.2540],[2.7099223897239946,0.15239999999999998,0.2540],[2.7602778202956104,0.15239999999999998,0.2540],[2.8106332508672254,0.15239999999999998,0.2540],[2.8609886814388408,0.15239999999999998,0.2540],[2.9113441120104562,0.15239999999999998,0.2540],[0.14179543057161473,0.15239999999999998,0.20320000000000005],[0.19215086114323002,0.15239999999999998,0.20320000000000002],[0.24250629171484536,0.15239999999999998,0.20320000000000002],[0.29286172228646062,0.15239999999999998,0.20320000000000002],[0.34321715285807591,0.15239999999999998,0.20320000000000002],[0.39357258342969126,0.15239999999999998,0.20320000000000002],[0.44392801400130649,0.15239999999999998,0.20320000000000002],[0.49428344457292178,0.15239999999999998,0.20320000000000002],[0.54463887514453713,0.15239999999999998,0.20320000000000002],[0.59499430571615242,0.15239999999999998,0.20320000000000002],[0.64534973628776771,0.15239999999999998,0.20320000000000002],[0.6957051668593830,0.15239999999999998,0.20320000000000002],[0.74606059743099828,0.15239999999999998,0.20320000000000002],[0.79641602800261357,0.15239999999999998,0.20320000000000002],[0.84677145857422875,0.15239999999999998,0.20320000000000002],[0.89712688914584415,0.15239999999999998,0.20320000000000002],[0.94748231971745944,0.15239999999999998,0.20320000000000002],[0.99783775028907484,0.15239999999999998,0.20320000000000002],[1.0481931808606901,0.15239999999999998,0.20320000000000002],[1.0985486114323055,0.15239999999999998,0.20320000000000002],[1.1489040420039207,0.15239999999999998,0.20320000000000002],[1.1992594725755361,0.15239999999999998,0.20320000000000002],[1.2496149031471513,0.15239999999999998,0.20320000000000002],[1.2999703337187667,0.15239999999999998,0.20320000000000002],[1.3503257642903819,0.15239999999999998,0.20320000000000002],[1.4006811948619970,0.15239999999999998,0.20320000000000002],[1.4510366254336124,0.15239999999999998,0.20320000000000002],[1.5013920560052276,0.15239999999999998,0.20320000000000002],[1.5517474865768432,0.15239999999999998,0.20320000000000002],[1.6021029171484584,0.15239999999999998,0.20320000000000002],[1.6524583477200738,0.15239999999999998,0.20320000000000002],[1.7028137782916890,0.15239999999999998,0.20320000000000002],[1.7531692088633046,0.15239999999999998,0.20320000000000002],[1.8035246394349194,0.15239999999999998,0.20320000000000002],[1.8538800700065345,0.15239999999999998,0.20320000000000002],[1.9042355005781502,0.15239999999999998,0.20320000000000002],[1.9545909311497658,0.15239999999999998,0.20320000000000002],[2.0049463617213807,0.15239999999999998,0.20320000000000002],[2.0553017922929957,0.15239999999999998,0.20320000000000002],[2.1056572228646115,0.15239999999999998,0.20320000000000002],[2.1560126534362265,0.15239999999999998,0.20320000000000002],[2.2063680840078419,0.15239999999999998,0.20320000000000002],[2.2567235145794569,0.15239999999999998,0.20320000000000002],[2.3070789451510727,0.15239999999999998,0.20320000000000002],[2.3574343757226877,0.15239999999999998,0.20320000000000002],[2.4077898062943031,0.15239999999999998,0.20320000000000002],[2.4581452368659185,0.15239999999999998,0.20320000000000002],[2.5085006674375339,0.15239999999999998,0.20320000000000002],[2.5588560980091493,0.15239999999999998,0.20320000000000002],[2.6092115285807642,0.15239999999999998,0.20320000000000002],[2.6595669591523796,0.15239999999999998,0.20320000000000002],[2.7099223897239946,0.15239999999999998,0.20320000000000002],[2.7602778202956104,0.15239999999999998,0.20320000000000002],[2.8106332508672254,0.15239999999999998,0.20320000000000002],[2.8609886814388408,0.15239999999999998,0.20320000000000002],[2.9113441120104562,0.15239999999999998,0.20320000000000002],[0.14179543057161473,0.15239999999999998,0.15240000000000009],[0.19215086114323002,0.15239999999999998,0.15240000000000001],[0.24250629171484536,0.15239999999999998,0.15240000000000001],[0.29286172228646062,0.15239999999999998,0.15240000000000001],[0.34321715285807591,0.15239999999999998,0.15240000000000001],[0.39357258342969126,0.15239999999999998,0.15240000000000001],[0.44392801400130649,0.15239999999999998,0.15240000000000001],[0.49428344457292178,0.15239999999999998,0.15240000000000001],[0.54463887514453713,0.15239999999999998,0.15240000000000001],[0.59499430571615242,0.15239999999999998,0.15240000000000001],[0.64534973628776771,0.15239999999999998,0.15240000000000001],[0.6957051668593830,0.15239999999999998,0.15240000000000001],[0.74606059743099828,0.15239999999999998,0.15240000000000001],[0.79641602800261357,0.15239999999999998,0.15240000000000001],[0.84677145857422875,0.15239999999999998,0.15240000000000001],[0.89712688914584415,0.15239999999999998,0.15240000000000001],[0.94748231971745944,0.15239999999999998,0.15240000000000001],[0.99783775028907484,0.15239999999999998,0.15240000000000001],[1.0481931808606901,0.15239999999999998,0.15240000000000001],[1.0985486114323055,0.15239999999999998,0.15240000000000001],[1.1489040420039207,0.15239999999999998,0.15240000000000001],[1.1992594725755361,0.15239999999999998,0.15240000000000001],[1.2496149031471513,0.15239999999999998,0.15240000000000001],[1.2999703337187667,0.15239999999999998,0.15240000000000001],[1.3503257642903819,0.15239999999999998,0.15240000000000001],[1.4006811948619970,0.15239999999999998,0.15240000000000001],[1.4510366254336124,0.15239999999999998,0.15240000000000001],[1.5013920560052276,0.15239999999999998,0.15240000000000001],[1.5517474865768432,0.15239999999999998,0.15240000000000001],[1.6021029171484584,0.15239999999999998,0.15240000000000001],[1.6524583477200738,0.15239999999999998,0.15240000000000001],[1.7028137782916890,0.15239999999999998,0.15240000000000001],[1.7531692088633046,0.15239999999999998,0.15240000000000001],[1.8035246394349194,0.15239999999999998,0.15240000000000001],[1.8538800700065345,0.15239999999999998,0.15240000000000001],[1.9042355005781502,0.15239999999999998,0.15240000000000001],[1.9545909311497658,0.15239999999999998,0.15240000000000001],[2.0049463617213807,0.15239999999999998,0.15240000000000001],[2.0553017922929957,0.15239999999999998,0.15240000000000001],[2.1056572228646115,0.15239999999999998,0.15240000000000001],[2.1560126534362265,0.15239999999999998,0.15240000000000001],[2.2063680840078419,0.15239999999999998,0.15240000000000001],[2.2567235145794569,0.15239999999999998,0.15240000000000001],[2.3070789451510727,0.15239999999999998,0.15240000000000001],[2.3574343757226877,0.15239999999999998,0.15240000000000001],[2.4077898062943031,0.15239999999999998,0.15240000000000001],[2.4581452368659185,0.15239999999999998,0.15240000000000001],[2.5085006674375339,0.15239999999999998,0.15240000000000001],[2.5588560980091493,0.15239999999999998,0.15240000000000001],[2.6092115285807642,0.15239999999999998,0.15240000000000001],[2.6595669591523796,0.15239999999999998,0.15240000000000001],[2.7099223897239946,0.15239999999999998,0.15240000000000001],[2.7602778202956104,0.15239999999999998,0.15240000000000001],[2.8106332508672254,0.15239999999999998,0.15240000000000001],[2.8609886814388408,0.15239999999999998,0.15240000000000001],[2.9113441120104562,0.15239999999999998,0.15240000000000001],[0.14179543057161473,0.15239999999999998,0.10160000000000013],[0.19215086114323002,0.15239999999999998,0.10160000000000005],[0.24250629171484536,0.15239999999999998,0.10160000000000005],[0.29286172228646062,0.15239999999999998,0.10160000000000005],[0.34321715285807591,0.15239999999999998,0.10160000000000005],[0.39357258342969126,0.15239999999999998,0.10160000000000005],[0.44392801400130649,0.15239999999999998,0.10160000000000005],[0.49428344457292178,0.15239999999999998,0.10160000000000005],[0.54463887514453713,0.15239999999999998,0.10160000000000005],[0.59499430571615242,0.15239999999999998,0.10160000000000005],[0.64534973628776771,0.15239999999999998,0.10160000000000005],[0.6957051668593830,0.15239999999999998,0.10160000000000005],[0.74606059743099828,0.15239999999999998,0.10160000000000005],[0.79641602800261357,0.15239999999999998,0.10160000000000005],[0.84677145857422875,0.15239999999999998,0.10160000000000005],[0.89712688914584415,0.15239999999999998,0.10160000000000005],[0.94748231971745944,0.15239999999999998,0.10160000000000005],[0.99783775028907484,0.15239999999999998,0.10160000000000005],[1.0481931808606901,0.15239999999999998,0.10160000000000005],[1.0985486114323055,0.15239999999999998,0.10160000000000005],[1.1489040420039207,0.15239999999999998,0.10160000000000005],[1.1992594725755361,0.15239999999999998,0.10160000000000005],[1.2496149031471513,0.15239999999999998,0.10160000000000005],[1.2999703337187667,0.15239999999999998,0.10160000000000005],[1.3503257642903819,0.15239999999999998,0.10160000000000005],[1.4006811948619970,0.15239999999999998,0.10160000000000005],[1.4510366254336124,0.15239999999999998,0.10160000000000005],[1.5013920560052276,0.15239999999999998,0.10160000000000005],[1.5517474865768432,0.15239999999999998,0.10160000000000005],[1.6021029171484584,0.15239999999999998,0.10160000000000005],[1.6524583477200738,0.15239999999999998,0.10160000000000005],[1.7028137782916890,0.15239999999999998,0.10160000000000005],[1.7531692088633046,0.15239999999999998,0.10160000000000005],[1.8035246394349194,0.15239999999999998,0.10160000000000005],[1.8538800700065345,0.15239999999999998,0.10160000000000005],[1.9042355005781502,0.15239999999999998,0.10160000000000005],[1.9545909311497658,0.15239999999999998,0.10160000000000005],[2.0049463617213807,0.15239999999999998,0.10160000000000005],[2.0553017922929957,0.15239999999999998,0.10160000000000005],[2.1056572228646115,0.15239999999999998,0.10160000000000005],[2.1560126534362265,0.15239999999999998,0.10160000000000005],[2.2063680840078419,0.15239999999999998,0.10160000000000005],[2.2567235145794569,0.15239999999999998,0.10160000000000005],[2.3070789451510727,0.15239999999999998,0.10160000000000005],[2.3574343757226877,0.15239999999999998,0.10160000000000005],[2.4077898062943031,0.15239999999999998,0.10160000000000005],[2.4581452368659185,0.15239999999999998,0.10160000000000005],[2.5085006674375339,0.15239999999999998,0.10160000000000005],[2.5588560980091493,0.15239999999999998,0.10160000000000005],[2.6092115285807642,0.15239999999999998,0.10160000000000005],[2.6595669591523796,0.15239999999999998,0.10160000000000005],[2.7099223897239946,0.15239999999999998,0.10160000000000005],[2.7602778202956104,0.15239999999999998,0.10160000000000005],[2.8106332508672254,0.15239999999999998,0.10160000000000005],[2.8609886814388408,0.15239999999999998,0.10160000000000005],[2.9113441120104562,0.15239999999999998,0.10160000000000005],[0.14179543057161473,0.15239999999999998,0.050800000000000095],[0.19215086114323002,0.15239999999999998,0.050800000000000005],[0.24250629171484536,0.15239999999999998,0.050800000000000005],[0.29286172228646062,0.15239999999999998,0.050800000000000005],[0.34321715285807591,0.15239999999999998,0.050800000000000005],[0.39357258342969126,0.15239999999999998,0.050800000000000005],[0.44392801400130649,0.15239999999999998,0.050800000000000005],[0.49428344457292178,0.15239999999999998,0.050800000000000005],[0.54463887514453713,0.15239999999999998,0.050800000000000005],[0.59499430571615242,0.15239999999999998,0.050800000000000005],[0.64534973628776771,0.15239999999999998,0.050800000000000005],[0.6957051668593830,0.15239999999999998,0.050800000000000005],[0.74606059743099828,0.15239999999999998,0.050800000000000005],[0.79641602800261357,0.15239999999999998,0.050800000000000005],[0.84677145857422875,0.15239999999999998,0.050800000000000005],[0.89712688914584415,0.15239999999999998,0.050800000000000005],[0.94748231971745944,0.15239999999999998,0.050800000000000005],[0.99783775028907484,0.15239999999999998,0.050800000000000005],[1.0481931808606901,0.15239999999999998,0.050800000000000005],[1.0985486114323055,0.15239999999999998,0.050800000000000005],[1.1489040420039207,0.15239999999999998,0.050800000000000005],[1.1992594725755361,0.15239999999999998,0.050800000000000005],[1.2496149031471513,0.15239999999999998,0.050800000000000005],[1.2999703337187667,0.15239999999999998,0.050800000000000005],[1.3503257642903819,0.15239999999999998,0.050800000000000005],[1.4006811948619970,0.15239999999999998,0.050800000000000005],[1.4510366254336124,0.15239999999999998,0.050800000000000005],[1.5013920560052276,0.15239999999999998,0.050800000000000005],[1.5517474865768432,0.15239999999999998,0.050800000000000005],[1.6021029171484584,0.15239999999999998,0.050800000000000005],[1.6524583477200738,0.15239999999999998,0.050800000000000005],[1.7028137782916890,0.15239999999999998,0.050800000000000005],[1.7531692088633046,0.15239999999999998,0.050800000000000005],[1.8035246394349194,0.15239999999999998,0.050800000000000005],[1.8538800700065345,0.15239999999999998,0.050800000000000005],[1.9042355005781502,0.15239999999999998,0.050800000000000005],[1.9545909311497658,0.15239999999999998,0.050800000000000005],[2.0049463617213807,0.15239999999999998,0.050800000000000005],[2.0553017922929957,0.15239999999999998,0.050800000000000005],[2.1056572228646115,0.15239999999999998,0.050800000000000005],[2.1560126534362265,0.15239999999999998,0.050800000000000005],[2.2063680840078419,0.15239999999999998,0.050800000000000005],[2.2567235145794569,0.15239999999999998,0.050800000000000005],[2.3070789451510727,0.15239999999999998,0.050800000000000005],[2.3574343757226877,0.15239999999999998,0.050800000000000005],[2.4077898062943031,0.15239999999999998,0.050800000000000005],[2.4581452368659185,0.15239999999999998,0.050800000000000005],[2.5085006674375339,0.15239999999999998,0.050800000000000005],[2.5588560980091493,0.15239999999999998,0.050800000000000005],[2.6092115285807642,0.15239999999999998,0.050800000000000005],[2.6595669591523796,0.15239999999999998,0.050800000000000005],[2.7099223897239946,0.15239999999999998,0.050800000000000005],[2.7602778202956104,0.15239999999999998,0.050800000000000005],[2.8106332508672254,0.15239999999999998,0.050800000000000005],[2.8609886814388408,0.15239999999999998,0.050800000000000005],[2.9113441120104562,0.15239999999999998,0.050800000000000005]],"pointIndex":[1,2,6,5,0,2,3,7,6,0,3,4,8,7,0,5,6,10,9,0,6,7,11,10,0,7,8,12,11,0,9,10,14,13,0,10,11,15,14,0,11,12,16,15,0,13,14,18,17,0,14,15,19,18,0,15,16,20,19,0,17,18,22,21,0,18,19,23,22,0,19,20,24,23,0,21,22,26,25,0,22,23,27,26,0,23,24,28,27,0,25,26,30,29,0,26,27,31,30,0,27,28,32,31,0,29,30,34,33,0,30,31,35,34,0,31,32,36,35,0,33,34,38,37,0,34,35,39,38,0,35,36,40,39,0,37,38,42,41,0,38,39,43,42,0,39,40,44,43,0,41,42,46,45,0,42,43,47,46,0,43,44,48,47,0,45,46,50,49,0,46,47,51,50,0,47,48,52,51,0,49,50,54,53,0,50,51,55,54,0,51,52,56,55,0,53,54,58,57,0,54,55,59,58,0,55,56,60,59,0,57,58,62,61,0,58,59,63,62,0,59,60,64,63,0,61,62,66,65,0,62,63,67,66,0,63,64,68,67,0,65,66,70,69,0,66,67,71,70,0,67,68,72,71,0,69,70,74,73,0,70,71,75,74,0,71,72,76,75,0,73,74,78,77,0,74,75,79,78,0,75,76,80,79,0,77,78,82,81,0,78,79,83,82,0,79,80,84,83,0,81,82,86,85,0,82,83,87,86,0,83,84,88,87,0,85,86,90,89,0,86,87,91,90,0,87,88,92,91,0,89,90,94,93,0,90,91,95,94,0,91,92,96,95,0,93,94,98,97,0,94,95,99,98,0,95,96,100,99,0,97,98,102,101,0,98,99,103,102,0,99,100,104,103,0,101,102,106,105,0,102,103,107,106,0,103,104,108,107,0,105,106,110,109,0,106,107,111,110,0,107,108,112,111,0,109,110,114,113,0,110,111,115,114,0,111,112,116,115,0,113,114,118,117,0,114,115,119,118,0,115,116,120,119,0,117,118,122,121,0,118,119,123,122,0,119,120,124,123,0,121,122,126,125,0,122,123,127,126,0,123,124,128,127,0,125,126,130,129,0,126,127,131,130,0,127,128,132,131,0,129,130,134,133,0,130,131,135,134,0,131,132,136,135,0,133,134,138,137,0,134,135,139,138,0,135,136,140,139,0,137,138,142,141,0,138,139,143,142,0,139,140,144,143,0,141,142,146,145,0,142,143,147,146,0,143,144,148,147,0,145,146,150,149,0,146,147,151,150,0,147,148,152,151,0,149,150,154,153,0,150,151,155,154,0,151,152,156,155,0,153,154,158,157,0,154,155,159,158,0,155,156,160,159,0,157,158,162,161,0,158,159,163,162,0,159,160,164,163,0,161,162,166,165,0,162,163,167,166,0,163,164,168,167,0,165,166,170,169,0,166,167,171,170,0,167,168,172,171,0,169,170,174,173,0,170,171,175,174,0,171,172,176,175,0,173,174,178,177,0,174,175,179,178,0,175,176,180,179,0,177,178,182,181,0,178,179,183,182,0,179,180,184,183,0,181,182,186,185,0,182,183,187,186,0,183,184,188,187,0,185,186,190,189,0,186,187,191,190,0,187,188,192,191,0,189,190,194,193,0,190,191,195,194,0,191,192,196,195,0,193,194,198,197,0,194,195,199,198,0,195,196,200,199,0,197,198,202,201,0,198,199,203,202,0,199,200,204,203,0,201,202,206,205,0,202,203,207,206,0,203,204,208,207,0,205,206,210,209,0,206,207,211,210,0,207,208,212,211,0,209,210,214,213,0,210,211,215,214,0,211,212,216,215,0,213,214,218,217,0,214,215,219,218,0,215,216,220,219,0,217,218,222,221,0,218,219,223,222,0,219,220,224,223,0,221,222,226,225,0,222,223,227,226,0,223,224,228,227,0,225,226,230,229,0,226,227,231,230,0,227,228,232,231,0,233,234,238,237,0,234,235,239,238,0,235,236,240,239,0,237,238,242,241,0,238,239,243,242,0,239,240,244,243,0,241,242,246,245,0,242,243,247,246,0,243,244,248,247,0,245,246,250,249,0,246,247,251,250,0,247,248,252,251,0,249,250,254,253,0,250,251,255,254,0,251,252,256,255,0,253,254,258,257,0,254,255,259,258,0,255,256,260,259,0,257,258,262,261,0,258,259,263,262,0,259,260,264,263,0,261,262,266,265,0,262,263,267,266,0,263,264,268,267,0,265,266,270,269,0,266,267,271,270,0,267,268,272,271,0,269,270,274,273,0,270,271,275,274,0,271,272,276,275,0,273,274,278,277,0,274,275,279,278,0,275,276,280,279,0,277,278,282,281,0,278,279,283,282,0,279,280,284,283,0,281,282,286,285,0,282,283,287,286,0,283,284,288,287,0,285,286,290,289,0,286,287,291,290,0,287,288,292,291,0,289,290,294,293,0,290,291,295,294,0,291,292,296,295,0,293,294,298,297,0,294,295,299,298,0,295,296,300,299,0,297,298,302,301,0,298,299,303,302,0,299,300,304,303,0,301,302,306,305,0,302,303,307,306,0,303,304,308,307,0,305,306,310,309,0,306,307,311,310,0,307,308,312,311,0,309,310,314,313,0,310,311,315,314,0,311,312,316,315,0,313,314,318,317,0,314,315,319,318,0,315,316,320,319,0,317,318,322,321,0,318,319,323,322,0,319,320,324,323,0,321,322,326,325,0,322,323,327,326,0,323,324,328,327,0,325,326,330,329,0,326,327,331,330,0,327,328,332,331,0,329,330,334,333,0,330,331,335,334,0,331,332,336,335,0,333,334,338,337,0,334,335,339,338,0,335,336,340,339,0,337,338,342,341,0,338,339,343,342,0,339,340,344,343,0,341,342,346,345,0,342,343,347,346,0,343,344,348,347,0,345,346,350,349,0,346,347,351,350,0,347,348,352,351,0,349,350,354,353,0,350,351,355,354,0,351,352,356,355,0,353,354,358,357,0,354,355,359,358,0,355,356,360,359,0,357,358,362,361,0,358,359,363,362,0,359,360,364,363,0,361,362,366,365,0,362,363,367,366,0,363,364,368,367,0,365,366,370,369,0,366,367,371,370,0,367,368,372,371,0,369,370,374,373,0,370,371,375,374,0,371,372,376,375,0,373,374,378,377,0,374,375,379,378,0,375,376,380,379,0,377,378,382,381,0,378,379,383,382,0,379,380,384,383,0,381,382,386,385,0,382,383,387,386,0,383,384,388,387,0,385,386,390,389,0,386,387,391,390,0,387,388,392,391,0,389,390,394,393,0,390,391,395,394,0,391,392,396,395,0,393,394,398,397,0,394,395,399,398,0,395,396,400,399,0,397,398,402,401,0,398,399,403,402,0,399,400,404,403,0,401,402,406,405,0,402,403,407,406,0,403,404,408,407,0,405,406,410,409,0,406,407,411,410,0,407,408,412,411,0,409,410,414,413,0,410,411,415,414,0,411,412,416,415,0,413,414,418,417,0,414,415,419,418,0,415,416,420,419,0,417,418,422,421,0,418,419,423,422,0,419,420,424,423,0,421,422,426,425,0,422,423,427,426,0,423,424,428,427,0,425,426,430,429,0,426,427,431,430,0,427,428,432,431,0,429,430,434,433,0,430,431,435,434,0,431,432,436,435,0,433,434,438,437,0,434,435,439,438,0,435,436,440,439,0,437,438,442,441,0,438,439,443,442,0,439,440,444,443,0,441,442,446,445,0,442,443,447,446,0,443,444,448,447,0,445,446,450,449,0,446,447,451,450,0,447,448,452,451,0,449,450,454,453,0,450,451,455,454,0,451,452,456,455,0,453,454,458,457,0,454,455,459,458,0,455,456,460,459,0,457,458,462,461,0,458,459,463,462,0,459,460,464,463,0,4,3,466,465,0,3,2,467,466,0,2,1,468,467,0,465,466,470,469,0,466,467,471,470,0,467,468,472,471,0,469,470,474,473,0,470,471,475,474,0,471,472,476,475,0,473,474,478,477,0,474,475,479,478,0,475,476,480,479,0,477,478,482,481,0,478,479,483,482,0,479,480,484,483,0,481,482,486,485,0,482,483,487,486,0,483,484,488,487,0,485,486,490,489,0,486,487,491,490,0,487,488,492,491,0,489,490,494,493,0,490,491,495,494,0,491,492,496,495,0,493,494,234,233,0,494,495,235,234,0,495,496,236,235,0,1,5,497,468,0,5,9,498,497,0,9,13,499,498,0,13,17,500,499,0,17,21,501,500,0,21,25,502,501,0,25,29,503,502,0,29,33,504,503,0,33,37,505,504,0,37,41,506,505,0,41,45,507,506,0,45,49,508,507,0,49,53,509,508,0,53,57,510,509,0,57,61,511,510,0,61,65,512,511,0,65,69,513,512,0,69,73,514,513,0,73,77,515,514,0,77,81,516,515,0,81,85,517,516,0,85,89,518,517,0,89,93,519,518,0,93,97,520,519,0,97,101,521,520,0,101,105,522,521,0,105,109,523,522,0,109,113,524,523,0,113,117,525,524,0,117,121,526,525,0,121,125,527,526,0,125,129,528,527,0,129,133,529,528,0,133,137,530,529,0,137,141,531,530,0,141,145,532,531,0,145,149,533,532,0,149,153,534,533,0,153,157,535,534,0,157,161,536,535,0,161,165,537,536,0,165,169,538,537,0,169,173,539,538,0,173,177,540,539,0,177,181,541,540,0,181,185,542,541,0,185,189,543,542,0,189,193,544,543,0,193,197,545,544,0,197,201,546,545,0,201,205,547,546,0,205,209,548,547,0,209,213,549,548,0,213,217,550,549,0,217,221,551,550,0,221,225,552,551,0,225,229,553,552,0,468,497,554,472,0,497,498,555,554,0,498,499,556,555,0,499,500,557,556,0,500,501,558,557,0,501,502,559,558,0,502,503,560,559,0,503,504,561,560,0,504,505,562,561,0,505,506,563,562,0,506,507,564,563,0,507,508,565,564,0,508,509,566,565,0,509,510,567,566,0,510,511,568,567,0,511,512,569,568,0,512,513,570,569,0,513,514,571,570,0,514,515,572,571,0,515,516,573,572,0,516,517,574,573,0,517,518,575,574,0,518,519,576,575,0,519,520,577,576,0,520,521,578,577,0,521,522,579,578,0,522,523,580,579,0,523,524,581,580,0,524,525,582,581,0,525,526,583,582,0,526,527,584,583,0,527,528,585,584,0,528,529,586,585,0,529,530,587,586,0,530,531,588,587,0,531,532,589,588,0,532,533,590,589,0,533,534,591,590,0,534,535,592,591,0,535,536,593,592,0,536,537,594,593,0,537,538,595,594,0,538,539,596,595,0,539,540,597,596,0,540,541,598,597,0,541,542,599,598,0,542,543,600,599,0,543,544,601,600,0,544,545,602,601,0,545,546,603,602,0,546,547,604,603,0,547,548,605,604,0,548,549,606,605,0,549,550,607,606,0,550,551,608,607,0,551,552,609,608,0,552,553,610,609,0,472,554,611,476,0,554,555,612,611,0,555,556,613,612,0,556,557,614,613,0,557,558,615,614,0,558,559,616,615,0,559,560,617,616,0,560,561,618,617,0,561,562,619,618,0,562,563,620,619,0,563,564,621,620,0,564,565,622,621,0,565,566,623,622,0,566,567,624,623,0,567,568,625,624,0,568,569,626,625,0,569,570,627,626,0,570,571,628,627,0,571,572,629,628,0,572,573,630,629,0,573,574,631,630,0,574,575,632,631,0,575,576,633,632,0,576,577,634,633,0,577,578,635,634,0,578,579,636,635,0,579,580,637,636,0,580,581,638,637,0,581,582,639,638,0,582,583,640,639,0,583,584,641,640,0,584,585,642,641,0,585,586,643,642,0,586,587,644,643,0,587,588,645,644,0,588,589,646,645,0,589,590,647,646,0,590,591,648,647,0,591,592,649,648,0,592,593,650,649,0,593,594,651,650,0,594,595,652,651,0,595,596,653,652,0,596,597,654,653,0,597,598,655,654,0,598,599,656,655,0,599,600,657,656,0,600,601,658,657,0,601,602,659,658,0,602,603,660,659,0,603,604,661,660,0,604,605,662,661,0,605,606,663,662,0,606,607,664,663,0,607,608,665,664,0,608,609,666,665,0,609,610,667,666,0,476,611,668,480,0,611,612,669,668,0,612,613,670,669,0,613,614,671,670,0,614,615,672,671,0,615,616,673,672,0,616,617,674,673,0,617,618,675,674,0,618,619,676,675,0,619,620,677,676,0,620,621,678,677,0,621,622,679,678,0,622,623,680,679,0,623,624,681,680,0,624,625,682,681,0,625,626,683,682,0,626,627,684,683,0,627,628,685,684,0,628,629,686,685,0,629,630,687,686,0,630,631,688,687,0,631,632,689,688,0,632,633,690,689,0,633,634,691,690,0,634,635,692,691,0,635,636,693,692,0,636,637,694,693,0,637,638,695,694,0,638,639,696,695,0,639,640,697,696,0,640,641,698,697,0,641,642,699,698,0,642,643,700,699,0,643,644,701,700,0,644,645,702,701,0,645,646,703,702,0,646,647,704,703,0,647,648,705,704,0,648,649,706,705,0,649,650,707,706,0,650,651,708,707,0,651,652,709,708,0,652,653,710,709,0,653,654,711,710,0,654,655,712,711,0,655,656,713,712,0,656,657,714,713,0,657,658,715,714,0,658,659,716,715,0,659,660,717,716,0,660,661,718,717,0,661,662,719,718,0,662,663,720,719,0,663,664,721,720,0,664,665,722,721,0,665,666,723,722,0,666,667,724,723,0,480,668,725,484,0,668,669,726,725,0,669,670,727,726,0,670,671,728,727,0,671,672,729,728,0,672,673,730,729,0,673,674,731,730,0,674,675,732,731,0,675,676,733,732,0,676,677,734,733,0,677,678,735,734,0,678,679,736,735,0,679,680,737,736,0,680,681,738,737,0,681,682,739,738,0,682,683,740,739,0,683,684,741,740,0,684,685,742,741,0,685,686,743,742,0,686,687,744,743,0,687,688,745,744,0,688,689,746,745,0,689,690,747,746,0,690,691,748,747,0,691,692,749,748,0,692,693,750,749,0,693,694,751,750,0,694,695,752,751,0,695,696,753,752,0,696,697,754,753,0,697,698,755,754,0,698,699,756,755,0,699,700,757,756,0,700,701,758,757,0,701,702,759,758,0,702,703,760,759,0,703,704,761,760,0,704,705,762,761,0,705,706,763,762,0,706,707,764,763,0,707,708,765,764,0,708,709,766,765,0,709,710,767,766,0,710,711,768,767,0,711,712,769,768,0,712,713,770,769,0,713,714,771,770,0,714,715,772,771,0,715,716,773,772,0,716,717,774,773,0,717,718,775,774,0,718,719,776,775,0,719,720,777,776,0,720,721,778,777,0,721,722,779,778,0,722,723,780,779,0,723,724,781,780,0,484,725,782,488,0,725,726,783,782,0,726,727,784,783,0,727,728,785,784,0,728,729,786,785,0,729,730,787,786,0,730,731,788,787,0,731,732,789,788,0,732,733,790,789,0,733,734,791,790,0,734,735,792,791,0,735,736,793,792,0,736,737,794,793,0,737,738,795,794,0,738,739,796,795,0,739,740,797,796,0,740,741,798,797,0,741,742,799,798,0,742,743,800,799,0,743,744,801,800,0,744,745,802,801,0,745,746,803,802,0,746,747,804,803,0,747,748,805,804,0,748,749,806,805,0,749,750,807,806,0,750,751,808,807,0,751,752,809,808,0,752,753,810,809,0,753,754,811,810,0,754,755,812,811,0,755,756,813,812,0,756,757,814,813,0,757,758,815,814,0,758,759,816,815,0,759,760,817,816,0,760,761,818,817,0,761,762,819,818,0,762,763,820,819,0,763,764,821,820,0,764,765,822,821,0,765,766,823,822,0,766,767,824,823,0,767,768,825,824,0,768,769,826,825,0,769,770,827,826,0,770,771,828,827,0,771,772,829,828,0,772,773,830,829,0,773,774,831,830,0,774,775,832,831,0,775,776,833,832,0,776,777,834,833,0,777,778,835,834,0,778,779,836,835,0,779,780,837,836,0,780,781,838,837,0,488,782,839,492,0,782,783,840,839,0,783,784,841,840,0,784,785,842,841,0,785,786,843,842,0,786,787,844,843,0,787,788,845,844,0,788,789,846,845,0,789,790,847,846,0,790,791,848,847,0,791,792,849,848,0,792,793,850,849,0,793,794,851,850,0,794,795,852,851,0,795,796,853,852,0,796,797,854,853,0,797,798,855,854,0,798,799,856,855,0,799,800,857,856,0,800,801,858,857,0,801,802,859,858,0,802,803,860,859,0,803,804,861,860,0,804,805,862,861,0,805,806,863,862,0,806,807,864,863,0,807,808,865,864,0,808,809,866,865,0,809,810,867,866,0,810,811,868,867,0,811,812,869,868,0,812,813,870,869,0,813,814,871,870,0,814,815,872,871,0,815,816,873,872,0,816,817,874,873,0,817,818,875,874,0,818,819,876,875,0,819,820,877,876,0,820,821,878,877,0,821,822,879,878,0,822,823,880,879,0,823,824,881,880,0,824,825,882,881,0,825,826,883,882,0,826,827,884,883,0,827,828,885,884,0,828,829,886,885,0,829,830,887,886,0,830,831,888,887,0,831,832,889,888,0,832,833,890,889,0,833,834,891,890,0,834,835,892,891,0,835,836,893,892,0,836,837,894,893,0,837,838,895,894,0,492,839,896,496,0,839,840,897,896,0,840,841,898,897,0,841,842,899,898,0,842,843,900,899,0,843,844,901,900,0,844,845,902,901,0,845,846,903,902,0,846,847,904,903,0,847,848,905,904,0,848,849,906,905,0,849,850,907,906,0,850,851,908,907,0,851,852,909,908,0,852,853,910,909,0,853,854,911,910,0,854,855,912,911,0,855,856,913,912,0,856,857,914,913,0,857,858,915,914,0,858,859,916,915,0,859,860,917,916,0,860,861,918,917,0,861,862,919,918,0,862,863,920,919,0,863,864,921,920,0,864,865,922,921,0,865,866,923,922,0,866,867,924,923,0,867,868,925,924,0,868,869,926,925,0,869,870,927,926,0,870,871,928,927,0,871,872,929,928,0,872,873,930,929,0,873,874,931,930,0,874,875,932,931,0,875,876,933,932,0,876,877,934,933,0,877,878,935,934,0,878,879,936,935,0,879,880,937,936,0,880,881,938,937,0,881,882,939,938,0,882,883,940,939,0,883,884,941,940,0,884,885,942,941,0,885,886,943,942,0,886,887,944,943,0,887,888,945,944,0,888,889,946,945,0,889,890,947,946,0,890,891,948,947,0,891,892,949,948,0,892,893,950,949,0,893,894,951,950,0,894,895,952,951,0,496,896,240,236,0,896,897,244,240,0,897,898,248,244,0,898,899,252,248,0,899,900,256,252,0,900,901,260,256,0,901,902,264,260,0,902,903,268,264,0,903,904,272,268,0,904,905,276,272,0,905,906,280,276,0,906,907,284,280,0,907,908,288,284,0,908,909,292,288,0,909,910,296,292,0,910,911,300,296,0,911,912,304,300,0,912,913,308,304,0,913,914,312,308,0,914,915,316,312,0,915,916,320,316,0,916,917,324,320,0,917,918,328,324,0,918,919,332,328,0,919,920,336,332,0,920,921,340,336,0,921,922,344,340,0,922,923,348,344,0,923,924,352,348,0,924,925,356,352,0,925,926,360,356,0,926,927,364,360,0,927,928,368,364,0,928,929,372,368,0,929,930,376,372,0,930,931,380,376,0,931,932,384,380,0,932,933,388,384,0,933,934,392,388,0,934,935,396,392,0,935,936,400,396,0,936,937,404,400,0,937,938,408,404,0,938,939,412,408,0,939,940,416,412,0,940,941,420,416,0,941,942,424,420,0,942,943,428,424,0,943,944,432,428,0,944,945,436,432,0,945,946,440,436,0,946,947,444,440,0,947,948,448,444,0,948,949,452,448,0,949,950,456,452,0,950,951,460,456,0,951,952,464,460,0,229,230,953,553,0,230,231,954,953,0,231,232,955,954,0,553,953,956,610,0,953,954,957,956,0,954,955,958,957,0,610,956,959,667,0,956,957,960,959,0,957,958,961,960,0,667,959,962,724,0,959,960,963,962,0,960,961,964,963,0,724,962,965,781,0,962,963,966,965,0,963,964,967,966,0,781,965,968,838,0,965,966,969,968,0,966,967,970,969,0,838,968,971,895,0,968,969,972,971,0,969,970,973,972,0,895,971,974,952,0,971,972,975,974,0,972,973,976,975,0,952,974,463,464,0,974,975,462,463,0,975,976,461,462,0,232,228,977,955,0,228,224,978,977,0,224,220,979,978,0,220,216,980,979,0,216,212,981,980,0,212,208,982,981,0,208,204,983,982,0,204,200,984,983,0,200,196,985,984,0,196,192,986,985,0,192,188,987,986,0,188,184,988,987,0,184,180,989,988,0,180,176,990,989,0,176,172,991,990,0,172,168,992,991,0,168,164,993,992,0,164,160,994,993,0,160,156,995,994,0,156,152,996,995,0,152,148,997,996,0,148,144,998,997,0,144,140,999,998,0,140,136,1000,999,0,136,132,1001,1000,0,132,128,1002,1001,0,128,124,1003,1002,0,124,120,1004,1003,0,120,116,1005,1004,0,116,112,1006,1005,0,112,108,1007,1006,0,108,104,1008,1007,0,104,100,1009,1008,0,100,96,1010,1009,0,96,92,1011,1010,0,92,88,1012,1011,0,88,84,1013,1012,0,84,80,1014,1013,0,80,76,1015,1014,0,76,72,1016,1015,0,72,68,1017,1016,0,68,64,1018,1017,0,64,60,1019,1018,0,60,56,1020,1019,0,56,52,1021,1020,0,52,48,1022,1021,0,48,44,1023,1022,0,44,40,1024,1023,0,40,36,1025,1024,0,36,32,1026,1025,0,32,28,1027,1026,0,28,24,1028,1027,0,24,20,1029,1028,0,20,16,1030,1029,0,16,12,1031,1030,0,12,8,1032,1031,0,8,4,465,1032,0,955,977,1033,958,0,977,978,1034,1033,0,978,979,1035,1034,0,979,980,1036,1035,0,980,981,1037,1036,0,981,982,1038,1037,0,982,983,1039,1038,0,983,984,1040,1039,0,984,985,1041,1040,0,985,986,1042,1041,0,986,987,1043,1042,0,987,988,1044,1043,0,988,989,1045,1044,0,989,990,1046,1045,0,990,991,1047,1046,0,991,992,1048,1047,0,992,993,1049,1048,0,993,994,1050,1049,0,994,995,1051,1050,0,995,996,1052,1051,0,996,997,1053,1052,0,997,998,1054,1053,0,998,999,1055,1054,0,999,1000,1056,1055,0,1000,1001,1057,1056,0,1001,1002,1058,1057,0,1002,1003,1059,1058,0,1003,1004,1060,1059,0,1004,1005,1061,1060,0,1005,1006,1062,1061,0,1006,1007,1063,1062,0,1007,1008,1064,1063,0,1008,1009,1065,1064,0,1009,1010,1066,1065,0,1010,1011,1067,1066,0,1011,1012,1068,1067,0,1012,1013,1069,1068,0,1013,1014,1070,1069,0,1014,1015,1071,1070,0,1015,1016,1072,1071,0,1016,1017,1073,1072,0,1017,1018,1074,1073,0,1018,1019,1075,1074,0,1019,1020,1076,1075,0,1020,1021,1077,1076,0,1021,1022,1078,1077,0,1022,1023,1079,1078,0,1023,1024,1080,1079,0,1024,1025,1081,1080,0,1025,1026,1082,1081,0,1026,1027,1083,1082,0,1027,1028,1084,1083,0,1028,1029,1085,1084,0,1029,1030,1086,1085,0,1030,1031,1087,1086,0,1031,1032,1088,1087,0,1032,465,469,1088,0,958,1033,1089,961,0,1033,1034,1090,1089,0,1034,1035,1091,1090,0,1035,1036,1092,1091,0,1036,1037,1093,1092,0,1037,1038,1094,1093,0,1038,1039,1095,1094,0,1039,1040,1096,1095,0,1040,1041,1097,1096,0,1041,1042,1098,1097,0,1042,1043,1099,1098,0,1043,1044,1100,1099,0,1044,1045,1101,1100,0,1045,1046,1102,1101,0,1046,1047,1103,1102,0,1047,1048,1104,1103,0,1048,1049,1105,1104,0,1049,1050,1106,1105,0,1050,1051,1107,1106,0,1051,1052,1108,1107,0,1052,1053,1109,1108,0,1053,1054,1110,1109,0,1054,1055,1111,1110,0,1055,1056,1112,1111,0,1056,1057,1113,1112,0,1057,1058,1114,1113,0,1058,1059,1115,1114,0,1059,1060,1116,1115,0,1060,1061,1117,1116,0,1061,1062,1118,1117,0,1062,1063,1119,1118,0,1063,1064,1120,1119,0,1064,1065,1121,1120,0,1065,1066,1122,1121,0,1066,1067,1123,1122,0,1067,1068,1124,1123,0,1068,1069,1125,1124,0,1069,1070,1126,1125,0,1070,1071,1127,1126,0,1071,1072,1128,1127,0,1072,1073,1129,1128,0,1073,1074,1130,1129,0,1074,1075,1131,1130,0,1075,1076,1132,1131,0,1076,1077,1133,1132,0,1077,1078,1134,1133,0,1078,1079,1135,1134,0,1079,1080,1136,1135,0,1080,1081,1137,1136,0,1081,1082,1138,1137,0,1082,1083,1139,1138,0,1083,1084,1140,1139,0,1084,1085,1141,1140,0,1085,1086,1142,1141,0,1086,1087,1143,1142,0,1087,1088,1144,1143,0,1088,469,473,1144,0,961,1089,1145,964,0,1089,1090,1146,1145,0,1090,1091,1147,1146,0,1091,1092,1148,1147,0,1092,1093,1149,1148,0,1093,1094,1150,1149,0,1094,1095,1151,1150,0,1095,1096,1152,1151,0,1096,1097,1153,1152,0,1097,1098,1154,1153,0,1098,1099,1155,1154,0,1099,1100,1156,1155,0,1100,1101,1157,1156,0,1101,1102,1158,1157,0,1102,1103,1159,1158,0,1103,1104,1160,1159,0,1104,1105,1161,1160,0,1105,1106,1162,1161,0,1106,1107,1163,1162,0,1107,1108,1164,1163,0,1108,1109,1165,1164,0,1109,1110,1166,1165,0,1110,1111,1167,1166,0,1111,1112,1168,1167,0,1112,1113,1169,1168,0,1113,1114,1170,1169,0,1114,1115,1171,1170,0,1115,1116,1172,1171,0,1116,1117,1173,1172,0,1117,1118,1174,1173,0,1118,1119,1175,1174,0,1119,1120,1176,1175,0,1120,1121,1177,1176,0,1121,1122,1178,1177,0,1122,1123,1179,1178,0,1123,1124,1180,1179,0,1124,1125,1181,1180,0,1125,1126,1182,1181,0,1126,1127,1183,1182,0,1127,1128,1184,1183,0,1128,1129,1185,1184,0,1129,1130,1186,1185,0,1130,1131,1187,1186,0,1131,1132,1188,1187,0,1132,1133,1189,1188,0,1133,1134,1190,1189,0,1134,1135,1191,1190,0,1135,1136,1192,1191,0,1136,1137,1193,1192,0,1137,1138,1194,1193,0,1138,1139,1195,1194,0,1139,1140,1196,1195,0,1140,1141,1197,1196,0,1141,1142,1198,1197,0,1142,1143,1199,1198,0,1143,1144,1200,1199,0,1144,473,477,1200,0,964,1145,1201,967,0,1145,1146,1202,1201,0,1146,1147,1203,1202,0,1147,1148,1204,1203,0,1148,1149,1205,1204,0,1149,1150,1206,1205,0,1150,1151,1207,1206,0,1151,1152,1208,1207,0,1152,1153,1209,1208,0,1153,1154,1210,1209,0,1154,1155,1211,1210,0,1155,1156,1212,1211,0,1156,1157,1213,1212,0,1157,1158,1214,1213,0,1158,1159,1215,1214,0,1159,1160,1216,1215,0,1160,1161,1217,1216,0,1161,1162,1218,1217,0,1162,1163,1219,1218,0,1163,1164,1220,1219,0,1164,1165,1221,1220,0,1165,1166,1222,1221,0,1166,1167,1223,1222,0,1167,1168,1224,1223,0,1168,1169,1225,1224,0,1169,1170,1226,1225,0,1170,1171,1227,1226,0,1171,1172,1228,1227,0,1172,1173,1229,1228,0,1173,1174,1230,1229,0,1174,1175,1231,1230,0,1175,1176,1232,1231,0,1176,1177,1233,1232,0,1177,1178,1234,1233,0,1178,1179,1235,1234,0,1179,1180,1236,1235,0,1180,1181,1237,1236,0,1181,1182,1238,1237,0,1182,1183,1239,1238,0,1183,1184,1240,1239,0,1184,1185,1241,1240,0,1185,1186,1242,1241,0,1186,1187,1243,1242,0,1187,1188,1244,1243,0,1188,1189,1245,1244,0,1189,1190,1246,1245,0,1190,1191,1247,1246,0,1191,1192,1248,1247,0,1192,1193,1249,1248,0,1193,1194,1250,1249,0,1194,1195,1251,1250,0,1195,1196,1252,1251,0,1196,1197,1253,1252,0,1197,1198,1254,1253,0,1198,1199,1255,1254,0,1199,1200,1256,1255,0,1200,477,481,1256,0,967,1201,1257,970,0,1201,1202,1258,1257,0,1202,1203,1259,1258,0,1203,1204,1260,1259,0,1204,1205,1261,1260,0,1205,1206,1262,1261,0,1206,1207,1263,1262,0,1207,1208,1264,1263,0,1208,1209,1265,1264,0,1209,1210,1266,1265,0,1210,1211,1267,1266,0,1211,1212,1268,1267,0,1212,1213,1269,1268,0,1213,1214,1270,1269,0,1214,1215,1271,1270,0,1215,1216,1272,1271,0,1216,1217,1273,1272,0,1217,1218,1274,1273,0,1218,1219,1275,1274,0,1219,1220,1276,1275,0,1220,1221,1277,1276,0,1221,1222,1278,1277,0,1222,1223,1279,1278,0,1223,1224,1280,1279,0,1224,1225,1281,1280,0,1225,1226,1282,1281,0,1226,1227,1283,1282,0,1227,1228,1284,1283,0,1228,1229,1285,1284,0,1229,1230,1286,1285,0,1230,1231,1287,1286,0,1231,1232,1288,1287,0,1232,1233,1289,1288,0,1233,1234,1290,1289,0,1234,1235,1291,1290,0,1235,1236,1292,1291,0,1236,1237,1293,1292,0,1237,1238,1294,1293,0,1238,1239,1295,1294,0,1239,1240,1296,1295,0,1240,1241,1297,1296,0,1241,1242,1298,1297,0,1242,1243,1299,1298,0,1243,1244,1300,1299,0,1244,1245,1301,1300,0,1245,1246,1302,1301,0,1246,1247,1303,1302,0,1247,1248,1304,1303,0,1248,1249,1305,1304,0,1249,1250,1306,1305,0,1250,1251,1307,1306,0,1251,1252,1308,1307,0,1252,1253,1309,1308,0,1253,1254,1310,1309,0,1254,1255,1311,1310,0,1255,1256,1312,1311,0,1256,481,485,1312,0,970,1257,1313,973,0,1257,1258,1314,1313,0,1258,1259,1315,1314,0,1259,1260,1316,1315,0,1260,1261,1317,1316,0,1261,1262,1318,1317,0,1262,1263,1319,1318,0,1263,1264,1320,1319,0,1264,1265,1321,1320,0,1265,1266,1322,1321,0,1266,1267,1323,1322,0,1267,1268,1324,1323,0,1268,1269,1325,1324,0,1269,1270,1326,1325,0,1270,1271,1327,1326,0,1271,1272,1328,1327,0,1272,1273,1329,1328,0,1273,1274,1330,1329,0,1274,1275,1331,1330,0,1275,1276,1332,1331,0,1276,1277,1333,1332,0,1277,1278,1334,1333,0,1278,1279,1335,1334,0,1279,1280,1336,1335,0,1280,1281,1337,1336,0,1281,1282,1338,1337,0,1282,1283,1339,1338,0,1283,1284,1340,1339,0,1284,1285,1341,1340,0,1285,1286,1342,1341,0,1286,1287,1343,1342,0,1287,1288,1344,1343,0,1288,1289,1345,1344,0,1289,1290,1346,1345,0,1290,1291,1347,1346,0,1291,1292,1348,1347,0,1292,1293,1349,1348,0,1293,1294,1350,1349,0,1294,1295,1351,1350,0,1295,1296,1352,1351,0,1296,1297,1353,1352,0,1297,1298,1354,1353,0,1298,1299,1355,1354,0,1299,1300,1356,1355,0,1300,1301,1357,1356,0,1301,1302,1358,1357,0,1302,1303,1359,1358,0,1303,1304,1360,1359,0,1304,1305,1361,1360,0,1305,1306,1362,1361,0,1306,1307,1363,1362,0,1307,1308,1364,1363,0,1308,1309,1365,1364,0,1309,1310,1366,1365,0,1310,1311,1367,1366,0,1311,1312,1368,1367,0,1312,485,489,1368,0,973,1313,1369,976,0,1313,1314,1370,1369,0,1314,1315,1371,1370,0,1315,1316,1372,1371,0,1316,1317,1373,1372,0,1317,1318,1374,1373,0,1318,1319,1375,1374,0,1319,1320,1376,1375,0,1320,1321,1377,1376,0,1321,1322,1378,1377,0,1322,1323,1379,1378,0,1323,1324,1380,1379,0,1324,1325,1381,1380,0,1325,1326,1382,1381,0,1326,1327,1383,1382,0,1327,1328,1384,1383,0,1328,1329,1385,1384,0,1329,1330,1386,1385,0,1330,1331,1387,1386,0,1331,1332,1388,1387,0,1332,1333,1389,1388,0,1333,1334,1390,1389,0,1334,1335,1391,1390,0,1335,1336,1392,1391,0,1336,1337,1393,1392,0,1337,1338,1394,1393,0,1338,1339,1395,1394,0,1339,1340,1396,1395,0,1340,1341,1397,1396,0,1341,1342,1398,1397,0,1342,1343,1399,1398,0,1343,1344,1400,1399,0,1344,1345,1401,1400,0,1345,1346,1402,1401,0,1346,1347,1403,1402,0,1347,1348,1404,1403,0,1348,1349,1405,1404,0,1349,1350,1406,1405,0,1350,1351,1407,1406,0,1351,1352,1408,1407,0,1352,1353,1409,1408,0,1353,1354,1410,1409,0,1354,1355,1411,1410,0,1355,1356,1412,1411,0,1356,1357,1413,1412,0,1357,1358,1414,1413,0,1358,1359,1415,1414,0,1359,1360,1416,1415,0,1360,1361,1417,1416,0,1361,1362,1418,1417,0,1362,1363,1419,1418,0,1363,1364,1420,1419,0,1364,1365,1421,1420,0,1365,1366,1422,1421,0,1366,1367,1423,1422,0,1367,1368,1424,1423,0,1368,489,493,1424,0,976,1369,457,461,0,1369,1370,453,457,0,1370,1371,449,453,0,1371,1372,445,449,0,1372,1373,441,445,0,1373,1374,437,441,0,1374,1375,433,437,0,1375,1376,429,433,0,1376,1377,425,429,0,1377,1378,421,425,0,1378,1379,417,421,0,1379,1380,413,417,0,1380,1381,409,413,0,1381,1382,405,409,0,1382,1383,401,405,0,1383,1384,397,401,0,1384,1385,393,397,0,1385,1386,389,393,0,1386,1387,385,389,0,1387,1388,381,385,0,1388,1389,377,381,0,1389,1390,373,377,0,1390,1391,369,373,0,1391,1392,365,369,0,1392,1393,361,365,0,1393,1394,357,361,0,1394,1395,353,357,0,1395,1396,349,353,0,1396,1397,345,349,0,1397,1398,341,345,0,1398,1399,337,341,0,1399,1400,333,337,0,1400,1401,329,333,0,1401,1402,325,329,0,1402,1403,321,325,0,1403,1404,317,321,0,1404,1405,313,317,0,1405,1406,309,313,0,1406,1407,305,309,0,1407,1408,301,305,0,1408,1409,297,301,0,1409,1410,293,297,0,1410,1411,289,293,0,1411,1412,285,289,0,1412,1413,281,285,0,1413,1414,277,281,0,1414,1415,273,277,0,1415,1416,269,273,0,1416,1417,265,269,0,1417,1418,261,265,0,1418,1419,257,261,0,1419,1420,253,257,0,1420,1421,249,253,0,1421,1422,245,249,0,1422,1423,241,245,0,1423,1424,237,241,0,1424,493,233,237,0]}}'; diff --git a/test-apps/display-test-app/src/frontend/ClassificationsPanel.ts b/test-apps/display-test-app/src/frontend/ClassificationsPanel.ts index 548c9b6df0fe..3379fd1b9a8c 100644 --- a/test-apps/display-test-app/src/frontend/ClassificationsPanel.ts +++ b/test-apps/display-test-app/src/frontend/ClassificationsPanel.ts @@ -4,17 +4,30 @@ *--------------------------------------------------------------------------------------------*/ import { assert, compareStringsOrUndefined, GuidString } from "@itwin/core-bentley"; -import { ComboBox, ComboBoxEntry, createCheckBox, createComboBox, createNestedMenu, createNumericInput, NestedMenu } from "@itwin/frontend-devtools"; import { - CartographicRange, ContextRealityModelProps, ModelProps, RealityDataFormat, RealityDataProvider, RealityDataSourceKey, SpatialClassifier, SpatialClassifierFlagsProps, SpatialClassifierInsideDisplay, - SpatialClassifierOutsideDisplay, SpatialClassifiers, + CartographicRange, + ContextRealityModelProps, + ModelProps, + RealityDataFormat, + RealityDataProvider, + RealityDataSourceKey, + SpatialClassifier, + SpatialClassifierFlagsProps, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + SpatialClassifiers, } from "@itwin/core-common"; +import { ContextRealityModelState, DisplayStyle3dState, IModelApp, SpatialModelState, SpatialViewState, Viewport } from "@itwin/core-frontend"; +import { ComboBox, ComboBoxEntry, createCheckBox, createComboBox, createNestedMenu, createNumericInput, NestedMenu } from "@itwin/frontend-devtools"; import { - ContextRealityModelState, DisplayStyle3dState, IModelApp, SpatialModelState, SpatialViewState, Viewport, -} from "@itwin/core-frontend"; + ITwinRealityData, + RealityDataAccessClient, + RealityDataClientOptions, + RealityDataQueryCriteria, + RealityDataResponse, +} from "@itwin/reality-data-client"; import { DisplayTestApp } from "./App"; import { ToolBarDropDown } from "./ToolBar"; -import { ITwinRealityData, RealityDataAccessClient, RealityDataClientOptions, RealityDataQueryCriteria, RealityDataResponse } from "@itwin/reality-data-client"; function clearElement(element: HTMLElement): void { while (element.hasChildNodes()) @@ -24,7 +37,7 @@ function clearElement(element: HTMLElement): void { const NO_MODEL_ID = "-1"; enum RealityDataType { - REALITYMESH3DTILES = "REALITYMESH3DTILES", + REALITYMESH3DTILES = "REALITYMESH3DTILES", OSMBUILDINGS = "OSMBUILDINGS", OPC = "OPC", TERRAIN3DTILES = "TERRAIN3DTILES", // Terrain3DTiles @@ -103,8 +116,9 @@ export class ClassificationsPanel extends ToolBarDropDown { }; } - private hasAttachedRealityModelFromKey(style: DisplayStyle3dState, rdSourceKey: RealityDataSourceKey ): boolean { - return undefined !== style.settings.contextRealityModels.models.find((x) => x.rdSourceKey && RealityDataSourceKey.isEqual(rdSourceKey,x.rdSourceKey)); + private hasAttachedRealityModelFromKey(style: DisplayStyle3dState, rdSourceKey: RealityDataSourceKey): boolean { + return undefined !== + style.settings.contextRealityModels.models.find((x) => x.rdSourceKey && RealityDataSourceKey.isEqual(rdSourceKey, x.rdSourceKey)); } private isSupportedType(type: string | undefined): boolean { @@ -153,7 +167,7 @@ export class ClassificationsPanel extends ToolBarDropDown { } const range = new CartographicRange(this._vp.iModel.projectExtents, ecef.getTransform()); - let available: RealityDataResponse = {realityDatas: []}; + let available: RealityDataResponse = { realityDatas: [] }; try { if (this._iTwinId !== undefined && IModelApp.authorizationClient) { const accessToken = await IModelApp.authorizationClient.getAccessToken(); @@ -178,7 +192,7 @@ export class ClassificationsPanel extends ToolBarDropDown { for (const rdEntry of available.realityDatas) { const name = undefined !== rdEntry.displayName ? rdEntry.displayName : rdEntry.id; const rdSourceKey = this.createRealityDataSourceKeyFromITwinRealityData(rdEntry); - const tilesetUrl = await IModelApp.realityDataAccess?.getRealityDataUrl(this._iTwinId,rdSourceKey.id); + const tilesetUrl = await IModelApp.realityDataAccess?.getRealityDataUrl(this._iTwinId, rdSourceKey.id); const isDisplaySupported = this.isSupportedDisplayType(rdEntry.type); if (tilesetUrl && isDisplaySupported) { const entry: ContextRealityModelProps = { @@ -288,13 +302,19 @@ export class ClassificationsPanel extends ToolBarDropDown { await this.populateModelList(); } - public get isOpen(): boolean { return "none" !== this._element.style.display; } + public get isOpen(): boolean { + return "none" !== this._element.style.display; + } protected _open(): void { this.populateRealityModelList(); this._element.style.display = "block"; } - protected _close(): void { this._element.style.display = "none"; } - public override get onViewChanged(): Promise { return this.populate(); } + protected _close(): void { + this._element.style.display = "none"; + } + public override get onViewChanged(): Promise { + return this.populate(); + } private updateModelComboBox(modelId: string): void { if (undefined !== this._modelComboBox) @@ -302,7 +322,7 @@ export class ClassificationsPanel extends ToolBarDropDown { } private detachRealityModelByKey(style: DisplayStyle3dState, rdSourceKey: RealityDataSourceKey): boolean { - const model = style.settings.contextRealityModels.models.find((x) => x.rdSourceKey && RealityDataSourceKey.isEqual(rdSourceKey,x.rdSourceKey)); + const model = style.settings.contextRealityModels.models.find((x) => x.rdSourceKey && RealityDataSourceKey.isEqual(rdSourceKey, x.rdSourceKey)); return undefined !== model && style.settings.contextRealityModels.delete(model); } @@ -312,7 +332,9 @@ export class ClassificationsPanel extends ToolBarDropDown { if (enabled) style.attachRealityModel(entry); else - entry.rdSourceKey ? this.detachRealityModelByKey(style, entry.rdSourceKey) : style.detachRealityModelByNameAndUrl(entry.name!, entry.tilesetUrl); + entry.rdSourceKey + ? this.detachRealityModelByKey(style, entry.rdSourceKey) + : style.detachRealityModelByNameAndUrl(entry.name!, entry.tilesetUrl); this.populateRealityModelList(); this._vp.invalidateScene(); diff --git a/test-apps/display-test-app/src/frontend/Contours.ts b/test-apps/display-test-app/src/frontend/Contours.ts index 5b698eb977dc..672684fc2dab 100644 --- a/test-apps/display-test-app/src/frontend/Contours.ts +++ b/test-apps/display-test-app/src/frontend/Contours.ts @@ -4,18 +4,29 @@ *--------------------------------------------------------------------------------------------*/ import { assert, CompressedId64Set, dispose, IDisposable } from "@itwin/core-bentley"; +import { ColorDef, Contour, ContourDisplay, ContourDisplayProps, ContourGroupProps, LinePixels, RgbColor } from "@itwin/core-common"; +import { Viewport, ViewState3d } from "@itwin/core-frontend"; import { CheckBox, ColorInput, - ColorInputProps, ComboBox, ComboBoxEntry, ComboBoxProps, createButton, createCheckBox, createColorInput, createComboBox, createLabeledNumericInput, - createSlider, createTextBox, LabeledNumericInput, Slider, + ColorInputProps, + ComboBox, + ComboBoxEntry, + ComboBoxProps, + createButton, + createCheckBox, + createColorInput, + createComboBox, + createLabeledNumericInput, + createSlider, + createTextBox, + LabeledNumericInput, + Slider, SliderProps, TextBox, TextBoxProps, updateSliderValue, } from "@itwin/frontend-devtools"; -import { ColorDef, Contour, ContourDisplay, ContourDisplayProps, ContourGroupProps, LinePixels, RgbColor } from "@itwin/core-common"; -import { Viewport, ViewState3d } from "@itwin/core-frontend"; import { ToolBarDropDown } from "./ToolBar"; // size of widget or panel @@ -181,21 +192,27 @@ export class ContoursSettings implements IDisposable { buttonDiv.style.textAlign = "center"; createButton({ value: "Add", - handler: () => { this.addContourDef(); }, + handler: () => { + this.addContourDef(); + }, parent: buttonDiv, inline: true, tooltip: "Add a new contour grouping", }); createButton({ value: "Apply", - handler: () => { this.applyContourDef(); }, + handler: () => { + this.applyContourDef(); + }, parent: buttonDiv, inline: true, tooltip: "Apply contour settings for this definition", }); createButton({ value: "Delete", - handler: () => { this.deleteContourDef(); }, + handler: () => { + this.deleteContourDef(); + }, parent: buttonDiv, inline: true, tooltip: "Delete contour settings for this definition", @@ -217,7 +234,7 @@ export class ContoursSettings implements IDisposable { } private getContourDisplayProps(view: ViewState3d): ContourDisplayProps { - const contours = view.displayStyle.settings.contours; + const contours = view.displayStyle.settings.contours; return contours.toJSON(); } @@ -232,7 +249,7 @@ export class ContoursSettings implements IDisposable { return { subCategories: CompressedId64Set.sortAndCompress(this._subCatTextBox.textbox.value.split(",")), name: this._nameTextBox.textbox.value, - contourDef:{ + contourDef: { majorStyle: { color: majorColor ? RgbColor.fromColorDef(majorColor) : undefined, pixelWidth: this.tryParseFloat(this._majorWidth.slider.value), @@ -266,7 +283,7 @@ export class ContoursSettings implements IDisposable { const subCats = groups[index].subCategories; this._subCatTextBox.textbox.value = (subCats ? [...subCats] : []).join(",") ?? ""; this._nameTextBox.textbox.value = groups[index].name; - const curContourDef = groups[index].contourDef ?? Contour.fromJSON({}); + const curContourDef = groups[index].contourDef ?? Contour.fromJSON({}); this._majorColor.input.value = curContourDef.majorStyle.color.toHexString(); this._minorColor.input.value = curContourDef.minorStyle.color.toHexString(); updateSliderValue(this._majorWidth, curContourDef.majorStyle.pixelWidth.toString()); @@ -357,7 +374,7 @@ export class ContoursSettings implements IDisposable { return numericIn; } - private addColor(parent: HTMLElement, major: boolean): ColorInput{ + private addColor(parent: HTMLElement, major: boolean): ColorInput { const div = document.createElement("div"); const props: ColorInputProps = { @@ -380,10 +397,16 @@ export class ContoursSettings implements IDisposable { private addWidth(parent1: HTMLElement, major: boolean): Slider { const props: SliderProps = { - name: " Width ", id: major ? "major_width" : "minor_width", parent: parent1, - min: "1.0", max: "8.5", step: "0.5", + name: " Width ", + id: major ? "major_width" : "minor_width", + parent: parent1, + min: "1.0", + max: "8.5", + step: "0.5", value: "1.5", - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: () => {}, }; const widthSlider = createSlider(props); @@ -448,7 +471,13 @@ export class ContoursPanel extends ToolBarDropDown { return Promise.resolve(); } - protected _open(): void { this._settings = new ContoursSettings(this._vp, this._parent); } - protected _close(): void { this._settings = dispose(this._settings); } - public get isOpen(): boolean { return undefined !== this._settings; } + protected _open(): void { + this._settings = new ContoursSettings(this._vp, this._parent); + } + protected _close(): void { + this._settings = dispose(this._settings); + } + public get isOpen(): boolean { + return undefined !== this._settings; + } } diff --git a/test-apps/display-test-app/src/frontend/CreateSectionDrawingTool.ts b/test-apps/display-test-app/src/frontend/CreateSectionDrawingTool.ts index d59700e97f54..1e0e92bad279 100644 --- a/test-apps/display-test-app/src/frontend/CreateSectionDrawingTool.ts +++ b/test-apps/display-test-app/src/frontend/CreateSectionDrawingTool.ts @@ -3,12 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { DrawingViewState, IModelApp, Tool } from "@itwin/core-frontend"; import { Id64 } from "@itwin/core-bentley"; +import { + CategorySelectorProps, + Code, + ColorDef, + DisplayStyleProps, + IModel, + Npc, + QueryRowFormat, + SectionDrawingViewProps, + ViewDefinition2dProps, + ViewStateProps, +} from "@itwin/core-common"; +import { DrawingViewState, IModelApp, Tool } from "@itwin/core-frontend"; +import { Range3d, Transform } from "@itwin/core-geometry"; import { CreateSectionDrawingViewArgs } from "../common/DtaIpcInterface"; import { dtaIpc } from "./App"; -import { Range3d, Transform } from "@itwin/core-geometry"; -import { CategorySelectorProps, Code, ColorDef, DisplayStyleProps, IModel, Npc, QueryRowFormat, SectionDrawingViewProps, ViewDefinition2dProps, ViewStateProps } from "@itwin/core-common"; /** Creates a section drawing model that references a copy of the active viewport's spatial view, * then changes the viewport to render a (non-persistent) drawing view displaying the drawing model along @@ -16,8 +27,12 @@ import { CategorySelectorProps, Code, ColorDef, DisplayStyleProps, IModel, Npc, */ export class CreateSectionDrawingTool extends Tool { public static override toolId = "CreateSectionDrawing"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async parseAndRun(...args: string[]): Promise { return this.run(args[0]); @@ -70,7 +85,11 @@ export class CreateSectionDrawingTool extends Tool { // Enable all 2d categories. const categories = []; - for await (const row of spatialView.iModel.createQueryReader("SELECT ECInstanceId from BisCore.DrawingCategory", undefined, { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const row of spatialView.iModel.createQueryReader("SELECT ECInstanceId from BisCore.DrawingCategory", undefined, { + rowFormat: QueryRowFormat.UseJsPropertyNames, + }) + ) { categories.push(row.id); } @@ -124,4 +143,3 @@ export class CreateSectionDrawingTool extends Tool { return true; } } - diff --git a/test-apps/display-test-app/src/frontend/DebugWindow.ts b/test-apps/display-test-app/src/frontend/DebugWindow.ts index a8511c245b3c..c8a864054f0d 100644 --- a/test-apps/display-test-app/src/frontend/DebugWindow.ts +++ b/test-apps/display-test-app/src/frontend/DebugWindow.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert } from "@itwin/core-bentley"; -import { DiagnosticsPanel } from "@itwin/frontend-devtools"; import { IModelApp, Viewport } from "@itwin/core-frontend"; +import { DiagnosticsPanel } from "@itwin/frontend-devtools"; import { Surface } from "./Surface"; import { Window } from "./Window"; @@ -42,8 +42,12 @@ export class DebugWindow extends Window { this._dispose(); } - public override get isResizable() { return false; } - public get windowId() { return this._windowId; } + public override get isResizable() { + return false; + } + public get windowId() { + return this._windowId; + } public toggle(): void { if (this._isOpen) diff --git a/test-apps/display-test-app/src/frontend/DecorationGeometryExample.ts b/test-apps/display-test-app/src/frontend/DecorationGeometryExample.ts index 45fd1baec052..eaa95ee3dd64 100644 --- a/test-apps/display-test-app/src/frontend/DecorationGeometryExample.ts +++ b/test-apps/display-test-app/src/frontend/DecorationGeometryExample.ts @@ -3,9 +3,31 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { assert } from "@itwin/core-bentley"; +import { + ColorDef, + Feature, + GeometryClass, + GraphicParams, + RenderMode, + RenderTexture, + SkyBox, + TextureMapping, + TextureTransparency, +} from "@itwin/core-common"; +import { + CreateRenderMaterialArgs, + DecorateContext, + GraphicBranch, + GraphicBuilder, + GraphicType, + imageElementFromUrl, + IModelApp, + IModelConnection, + MaterialTextureMappingProps, + StandardViewId, + Viewport, +} from "@itwin/core-frontend"; import { Box, Cone, Point3d, Range3d, Sphere, Transform } from "@itwin/core-geometry"; -import { ColorDef, Feature, GeometryClass, GraphicParams, RenderMode, RenderTexture, SkyBox, TextureMapping, TextureTransparency } from "@itwin/core-common"; -import { CreateRenderMaterialArgs, DecorateContext, GraphicBranch, GraphicBuilder, GraphicType, imageElementFromUrl, IModelApp, IModelConnection, MaterialTextureMappingProps, StandardViewId, Viewport } from "@itwin/core-frontend"; import { Viewer } from "./Viewer"; class GeometryDecorator { @@ -94,7 +116,7 @@ class GeometryDecorator { builder.setSymbology(color, color, 1); - const ndx = Math.floor(textureIndex++/4); + const ndx = Math.floor(textureIndex++ / 4); const tx = textures[ndx]; const nm = nMaps[ndx]; let textureMapping: MaterialTextureMappingProps | undefined; @@ -103,9 +125,9 @@ class GeometryDecorator { textureMapping = { texture: tx, transform, mode, worldMapping }; } else { if (undefined !== tx) - textureMapping = { texture:tx, transform, mode, worldMapping, normalMapParams: { normalMap: nm }}; + textureMapping = { texture: tx, transform, mode, worldMapping, normalMapParams: { normalMap: nm } }; else - textureMapping = { texture:nm, transform, mode, worldMapping, normalMapParams: {}}; + textureMapping = { texture: nm, transform, mode, worldMapping, normalMapParams: {} }; } const gp = GraphicParams.fromSymbology(color, color, 1); @@ -133,7 +155,11 @@ class GeometryDecorator { private addShape(ox: number, oy: number = 0): void { const points = [ - new Point3d(ox, oy, 0), new Point3d(ox + 1, oy, 0), new Point3d(ox + 1, oy + 1, 1), new Point3d(ox, oy + 1, 1), new Point3d(ox, oy, 0), + new Point3d(ox, oy, 0), + new Point3d(ox + 1, oy, 0), + new Point3d(ox + 1, oy + 1, 1), + new Point3d(ox, oy + 1, 1), + new Point3d(ox, oy, 0), ]; this._decorators.set(this._iModel.transientIds.getNext(), (builder) => builder.addShape(points)); } @@ -166,7 +192,7 @@ class GeometryDecorator { coneId = this._iModel.transientIds.getNext(); this._decorators.set(this._iModel.transientIds.getNext(), (builder) => { - builder.addShape([ new Point3d(0, y, 0), new Point3d(1, y, 0), new Point3d(1, y + 1, 1), new Point3d(0, y + 1, 1), new Point3d(0, y, 0) ]); + builder.addShape([new Point3d(0, y, 0), new Point3d(1, y, 0), new Point3d(1, y + 1, 1), new Point3d(0, y + 1, 1), new Point3d(0, y, 0)]); builder.activatePickableId(boxId); const box = Box.createRange(new Range3d(3, y, 0, 4, y + 1, 1), true); @@ -213,7 +239,10 @@ export async function openDecorationGeometryExample(viewer: Viewer) { const texture = IModelApp.renderSystem.createTexture({ image: { source: txrEl, transparency: TextureTransparency.Opaque }, ownership: "external" }); const nMapEl = await imageElementFromUrl("brick05normal.jpg"); - const normalMap = IModelApp.renderSystem.createTexture({ image: { source: nMapEl, transparency: TextureTransparency.Opaque }, ownership: "external" }); + const normalMap = IModelApp.renderSystem.createTexture({ + image: { source: nMapEl, transparency: TextureTransparency.Opaque }, + ownership: "external", + }); gd.setTextures(texture, normalMap); } diff --git a/test-apps/display-test-app/src/frontend/DisplayScale.ts b/test-apps/display-test-app/src/frontend/DisplayScale.ts index c0d9ce39642e..a22d95b492bb 100644 --- a/test-apps/display-test-app/src/frontend/DisplayScale.ts +++ b/test-apps/display-test-app/src/frontend/DisplayScale.ts @@ -3,25 +3,31 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Matrix3d, Point3d, Transform } from "@itwin/core-geometry"; import { IModelApp, ModelDisplayTransformProvider, Tool } from "@itwin/core-frontend"; +import { Matrix3d, Point3d, Transform } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; class DisplayScaleTransformProvider implements ModelDisplayTransformProvider { - public constructor(private readonly _models: Set, private readonly _scaleTransform: Transform) { } + public constructor(private readonly _models: Set, private readonly _scaleTransform: Transform) {} public getModelDisplayTransform(modelId: string): Transform | undefined { return this._models.has(modelId) ? this._scaleTransform.clone() : undefined; } - public get transform(): Transform { return this._scaleTransform.clone(); } + public get transform(): Transform { + return this._scaleTransform.clone(); + } } /** Apply a display transform to all currently displayed models. */ export class ApplyModelDisplayScaleTool extends Tool { public static override toolId = "ApplyModelDisplayScale"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } public override async run(scale: Point3d): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/DisplayTestApp.ts b/test-apps/display-test-app/src/frontend/DisplayTestApp.ts index 74ff54d20a6d..ae1675c2db1e 100644 --- a/test-apps/display-test-app/src/frontend/DisplayTestApp.ts +++ b/test-apps/display-test-app/src/frontend/DisplayTestApp.ts @@ -4,10 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Logger, LogLevel, ProcessDetector } from "@itwin/core-bentley"; import { RpcConfiguration } from "@itwin/core-common"; -import { - GpuMemoryLimit, - IModelApp, IModelConnection, RenderDiagnostics, RenderSystem, TileAdmin, -} from "@itwin/core-frontend"; +import { GpuMemoryLimit, IModelApp, IModelConnection, RenderDiagnostics, RenderSystem, TileAdmin } from "@itwin/core-frontend"; import { initializeFrontendTiles } from "@itwin/frontend-tiles"; import { WebGLExtensionName } from "@itwin/webgl-compatibility"; import { DtaBooleanConfiguration, DtaConfiguration, DtaNumberConfiguration, DtaStringConfiguration, getConfig } from "../common/DtaConfiguration"; @@ -133,8 +130,8 @@ function setConfigurationResults(): [renderSystemOptions: RenderSystem.Options, if (true === configuration.noImdlWorker) tileAdminProps.decodeImdlInWorker = false; - tileAdminProps.enableExternalTextures = (configuration.enableExternalTextures !== false); - tileAdminProps.enableFrontendScheduleScripts = (configuration.enableFrontendScheduleScripts !== false); + tileAdminProps.enableExternalTextures = configuration.enableExternalTextures !== false; + tileAdminProps.enableFrontendScheduleScripts = configuration.enableFrontendScheduleScripts !== false; tileAdminProps.tileTreeExpirationTime = configuration.tileTreeExpirationSeconds; tileAdminProps.tileExpirationTime = configuration.tileExpirationSeconds; tileAdminProps.maximumLevelsToSkip = configuration.maxTilesToSkip; @@ -314,12 +311,19 @@ async function initView(iModel: IModelConnection | undefined) { // open the specified view showStatus("opening View", configuration.viewName); - const fileSelector = undefined !== configuration.standalonePath ? { - directory: configuration.standalonePath, - input: document.getElementById("browserFileSelector") as HTMLInputElement, - } : undefined; - - DisplayTestApp.surface = new Surface(document.getElementById("app-surface")!, document.getElementById("toolBar")!, fileSelector, configuration.openReadWrite ?? false); + const fileSelector = undefined !== configuration.standalonePath ? + { + directory: configuration.standalonePath, + input: document.getElementById("browserFileSelector") as HTMLInputElement, + } : + undefined; + + DisplayTestApp.surface = new Surface( + document.getElementById("app-surface")!, + document.getElementById("toolBar")!, + fileSelector, + configuration.openReadWrite ?? false, + ); // We need layout to complete so that the div we want to stick our viewport into has non-zero dimensions. // Consistently reproducible for some folks, not others... diff --git a/test-apps/display-test-app/src/frontend/DisplayTransform.ts b/test-apps/display-test-app/src/frontend/DisplayTransform.ts index febd5058a217..10d59b7e1f0b 100644 --- a/test-apps/display-test-app/src/frontend/DisplayTransform.ts +++ b/test-apps/display-test-app/src/frontend/DisplayTransform.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { Id64Set, Id64String } from "@itwin/core-bentley"; -import { Matrix3d, Point3d, Transform, TransformProps, YawPitchRollAngles } from "@itwin/core-geometry"; import { IModelApp, ModelDisplayTransform, ModelDisplayTransformProvider, Tool, Viewport } from "@itwin/core-frontend"; +import { Matrix3d, Point3d, Transform, TransformProps, YawPitchRollAngles } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; export interface DisplayTransformProps { @@ -19,7 +19,7 @@ export type DisplayTransformProviderProps = DisplayTransformProps[]; export class DisplayTransformProvider implements ModelDisplayTransformProvider { private readonly _transforms = new Map(); - private constructor() { } + private constructor() {} public static get(vp: Viewport): DisplayTransformProvider | undefined { return vp.view.modelDisplayTransformProvider instanceof DisplayTransformProvider ? vp.view.modelDisplayTransformProvider : undefined; @@ -34,7 +34,7 @@ export class DisplayTransformProvider implements ModelDisplayTransformProvider { return provider; } - public getModelDisplayTransform(modelId: string): ModelDisplayTransform | undefined{ + public getModelDisplayTransform(modelId: string): ModelDisplayTransform | undefined { return this._transforms.get(modelId); } @@ -82,18 +82,24 @@ export class DisplayTransformProvider implements ModelDisplayTransformProvider { /** Apply a display transform to all currently displayed models. */ export class ApplyModelTransformTool extends Tool { public static override toolId = "ApplyModelTransform"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 7; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 7; + } public override async run(origin?: Point3d, ypr?: YawPitchRollAngles, scale?: number, premultiply?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; if (!vp) return false; - if (!origin || origin.isAlmostZero) - if (!ypr || ypr.isIdentity()) + if (!origin || origin.isAlmostZero) { + if (!ypr || ypr.isIdentity()) { if (!scale) return false; + } + } const models = new Set(); vp.view.forEachModel((model) => models.add(model.id)); diff --git a/test-apps/display-test-app/src/frontend/DrawingAidTestTool.ts b/test-apps/display-test-app/src/frontend/DrawingAidTestTool.ts index af3d7701ee2f..98a0afdcc339 100644 --- a/test-apps/display-test-app/src/frontend/DrawingAidTestTool.ts +++ b/test-apps/display-test-app/src/frontend/DrawingAidTestTool.ts @@ -3,18 +3,29 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { IModelJson as GeomJson, LineString3d, Point3d, Vector3d } from "@itwin/core-geometry"; import { ColorDef, GeometryStreamProps } from "@itwin/core-common"; import { - AccuDrawHintBuilder, BeButtonEvent, DecorateContext, DynamicsContext, EventHandled, GraphicType, HitDetail, IModelApp, PrimitiveTool, SnapStatus, + AccuDrawHintBuilder, + BeButtonEvent, + DecorateContext, + DynamicsContext, + EventHandled, + GraphicType, + HitDetail, + IModelApp, + PrimitiveTool, + SnapStatus, } from "@itwin/core-frontend"; +import { IModelJson as GeomJson, LineString3d, Point3d, Vector3d } from "@itwin/core-geometry"; export class DrawingAidTestTool extends PrimitiveTool { public static override toolId = "DrawingAidTest.Points"; public readonly points: Point3d[] = []; protected _snapGeomId?: string; - public override requireWriteableTarget(): boolean { return false; } + public override requireWriteableTarget(): boolean { + return false; + } public override async onPostInstall() { await super.onPostInstall(); this.setupAndPromptForNextAction(); @@ -36,7 +47,9 @@ export class DrawingAidTestTool extends PrimitiveTool { hints.sendHints(); } - public override testDecorationHit(id: string): boolean { return id === this._snapGeomId; } + public override testDecorationHit(id: string): boolean { + return id === this._snapGeomId; + } public override getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined { if (this.points.length < 2) diff --git a/test-apps/display-test-app/src/frontend/DynamicClassifierTool.ts b/test-apps/display-test-app/src/frontend/DynamicClassifierTool.ts index 8573cb19167f..fdf8ac8c81d6 100644 --- a/test-apps/display-test-app/src/frontend/DynamicClassifierTool.ts +++ b/test-apps/display-test-app/src/frontend/DynamicClassifierTool.ts @@ -4,8 +4,33 @@ *--------------------------------------------------------------------------------------------*/ import { Id64 } from "@itwin/core-bentley"; -import { ColorDef, Feature, PlanarClipMaskMode, PlanarClipMaskPriority, SpatialClassifierFlags, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay } from "@itwin/core-common"; -import { BeButtonEvent, DecorateContext, EventHandled, GraphicType, HitDetail, IModelApp, IModelConnection, LocateFilterStatus, LocateResponse, PrimitiveTool, RenderGraphic, SpatialClassifiersState, SpatialModelState, TiledGraphicsProvider, TileTreeReference, Viewport } from "@itwin/core-frontend"; +import { + ColorDef, + Feature, + PlanarClipMaskMode, + PlanarClipMaskPriority, + SpatialClassifierFlags, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, +} from "@itwin/core-common"; +import { + BeButtonEvent, + DecorateContext, + EventHandled, + GraphicType, + HitDetail, + IModelApp, + IModelConnection, + LocateFilterStatus, + LocateResponse, + PrimitiveTool, + RenderGraphic, + SpatialClassifiersState, + SpatialModelState, + TiledGraphicsProvider, + TileTreeReference, + Viewport, +} from "@itwin/core-frontend"; import { Point3d, Sphere as SpherePrimitive } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; @@ -71,8 +96,12 @@ export class DynamicClassifierTool extends PrimitiveTool { private _isVolume = false; public static override toolId = "DtaClassify"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } public override requireWriteableTarget(): boolean { return false; @@ -246,8 +275,12 @@ export class DynamicClipMaskTool extends PrimitiveTool { private _priority?: number; public static override toolId = "DtaClipMask"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } public override requireWriteableTarget(): boolean { return false; diff --git a/test-apps/display-test-app/src/frontend/EditingTools.ts b/test-apps/display-test-app/src/frontend/EditingTools.ts index 0d90bdb73be6..2dc4daffe414 100644 --- a/test-apps/display-test-app/src/frontend/EditingTools.ts +++ b/test-apps/display-test-app/src/frontend/EditingTools.ts @@ -5,11 +5,33 @@ import { assert, CompressedId64Set, Id64String } from "@itwin/core-bentley"; import { - Code, ColorDef, ElementGeometry, GeometryPartProps, GeometryStreamBuilder, GeometryStreamProps, IModel, PhysicalElementProps, + Code, + ColorDef, + ElementGeometry, + GeometryPartProps, + GeometryStreamBuilder, + GeometryStreamProps, + IModel, + PhysicalElementProps, } from "@itwin/core-common"; import { - AccuDrawHintBuilder, BeButtonEvent, BriefcaseConnection, CoreTools, DecorateContext, DynamicsContext, EventHandled, GraphicType, HitDetail, IModelApp, - NotifyMessageDetails, OutputMessagePriority, Tool, ToolAssistance, ToolAssistanceImage, ToolAssistanceInputMethod, ToolAssistanceInstruction, + AccuDrawHintBuilder, + BeButtonEvent, + BriefcaseConnection, + CoreTools, + DecorateContext, + DynamicsContext, + EventHandled, + GraphicType, + HitDetail, + IModelApp, + NotifyMessageDetails, + OutputMessagePriority, + Tool, + ToolAssistance, + ToolAssistanceImage, + ToolAssistanceInputMethod, + ToolAssistanceInstruction, ToolAssistanceSection, } from "@itwin/core-frontend"; import { IModelJson, LineString3d, Point3d, Sphere, Transform, Vector3d, YawPitchRollAngles } from "@itwin/core-geometry"; @@ -22,8 +44,12 @@ import { setTitle } from "./Title"; /** If an editing scope is currently in progress, end it; otherwise, begin a new one. */ export class EditingScopeTool extends Tool { public static override toolId = "EditingSession"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } public override async run(): Promise { await this._run(); @@ -54,8 +80,12 @@ export class PlaceLineStringTool extends CreateElementTool { private _testGeomParts = false; protected _startedCmd?: string; - protected override get wantAccuSnap(): boolean { return true; } - protected override get wantDynamics(): boolean { return true; } + protected override get wantAccuSnap(): boolean { + return true; + } + protected override get wantDynamics(): boolean { + return true; + } protected async startCommand(): Promise { if (undefined !== this._startedCmd) @@ -90,11 +120,19 @@ export class PlaceLineStringTool extends CreateElementTool { const touchInstructions: ToolAssistanceInstruction[] = []; if (!ToolAssistance.createTouchCursorInstructions(touchInstructions)) - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse)); - - touchInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch)); - mouseInstructions.push(ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse)); + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.OneTouchTap, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.LeftClick, CoreTools.translate(leftMsg), false, ToolAssistanceInputMethod.Mouse), + ); + + touchInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.TwoTouchTap, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Touch), + ); + mouseInstructions.push( + ToolAssistance.createInstruction(ToolAssistanceImage.RightClick, CoreTools.translate(rightMsg), false, ToolAssistanceInputMethod.Mouse), + ); const sections: ToolAssistanceSection[] = []; sections.push(ToolAssistance.createSection(mouseInstructions, ToolAssistance.inputsLabel)); @@ -178,7 +216,12 @@ export class PlaceLineStringTool extends CreateElementTool { if (!partBuilder.appendGeometry(sphere)) return; - const partProps: GeometryPartProps = { classFullName: "BisCore:GeometryPart", model: IModel.dictionaryId, code: Code.createEmpty(), geom: partBuilder.geometryStream }; + const partProps: GeometryPartProps = { + classFullName: "BisCore:GeometryPart", + model: IModel.dictionaryId, + code: Code.createEmpty(), + geom: partBuilder.geometryStream, + }; const partId = await basicManipulationIpc.insertGeometryPart(partProps); for (const pt of this._points) { @@ -187,7 +230,14 @@ export class PlaceLineStringTool extends CreateElementTool { } } - const elemProps: PhysicalElementProps = { classFullName: "Generic:PhysicalObject", model, category, code: Code.createEmpty(), placement: { origin, angles }, geom: builder.geometryStream }; + const elemProps: PhysicalElementProps = { + classFullName: "Generic:PhysicalObject", + model, + category, + code: Code.createEmpty(), + placement: { origin, angles }, + geom: builder.geometryStream, + }; await basicManipulationIpc.insertGeometricElement(elemProps); await this.saveChanges(); } else { @@ -215,7 +265,13 @@ export class PlaceLineStringTool extends CreateElementTool { } } - const elemProps: PhysicalElementProps = { classFullName: "Generic:PhysicalObject", model, category, code: Code.createEmpty(), placement: { origin, angles } }; + const elemProps: PhysicalElementProps = { + classFullName: "Generic:PhysicalObject", + model, + category, + code: Code.createEmpty(), + placement: { origin, angles }, + }; elemProps.elementGeometryBuilderParams = { entryArray: builder.entries }; await basicManipulationIpc.insertGeometricElement(elemProps); await this.saveChanges(); @@ -270,11 +326,14 @@ export async function transformElements(imodel: BriefcaseConnection, ids: string /** This tool moves an element relative to its current position. */ export class MoveElementTool extends Tool { public static override toolId = "MoveElement"; - public static override get minArgs() { return 2; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 2; + } + public static override get maxArgs() { + return 4; + } public override async run(elementId: string, x: number, y: number, z: number): Promise { - if (!IModelApp.viewManager.selectedView) { return false; } diff --git a/test-apps/display-test-app/src/frontend/EnvironmentEditor.ts b/test-apps/display-test-app/src/frontend/EnvironmentEditor.ts index fd26ff1dbe47..24f5e4e0965f 100644 --- a/test-apps/display-test-app/src/frontend/EnvironmentEditor.ts +++ b/test-apps/display-test-app/src/frontend/EnvironmentEditor.ts @@ -3,13 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - CheckBox, ColorInput, createButton, createCheckBox, createColorInput, createNestedMenu, createRadioBox, createSlider, RadioBox, Slider, -} from "@itwin/frontend-devtools"; import { ColorDef, Environment, RenderMode, SkyBox, SkyBoxProps, SkyGradient } from "@itwin/core-common"; import { Viewport, ViewState, ViewState3d } from "@itwin/core-frontend"; -import { LightingEditor } from "./LightingEditor"; +import { + CheckBox, + ColorInput, + createButton, + createCheckBox, + createColorInput, + createNestedMenu, + createRadioBox, + createSlider, + RadioBox, + Slider, +} from "@itwin/frontend-devtools"; import { AtmosphereEditor } from "./Atmosphere"; +import { LightingEditor } from "./LightingEditor"; type UpdateAttribute = (view: ViewState) => void; @@ -199,7 +208,9 @@ export class EnvironmentEditor { const env = (this._vp.view as ViewState3d).getDisplayStyle3d().environment.sky.gradient; let msg = `Zenith Color: ${env.zenithColor.toRgbString()}\nNadir Color: ${env.nadirColor.toRgbString()}`; if (!env.twoColor) - msg = msg.concat(`\nSky Color: ${env.skyColor.toRgbString()}\nGround Color: ${env.groundColor.toRgbString()}\nSky Exponent: ${env.skyExponent}\nGround Exponent: ${env.groundExponent}`); + msg = msg.concat( + `\nSky Color: ${env.skyColor.toRgbString()}\nGround Color: ${env.groundColor.toRgbString()}\nSky Exponent: ${env.skyExponent}\nGround Exponent: ${env.groundExponent}`, + ); alert(msg); }, }); @@ -304,16 +315,21 @@ export class EnvironmentEditor { } private addEnvAttribute(parent: HTMLElement, label: string, which: "sky" | "ground", updateHandler?: (enabled: boolean) => void): void { - const elems = this.addCheckbox(label, (enabled: boolean) => { - const view3d = this._vp.view as ViewState3d; - const style = view3d.getDisplayStyle3d(); - style.environment = style.environment.withDisplay("sky" === which ? { sky: enabled } : { ground: enabled }); + const elems = this.addCheckbox( + label, + (enabled: boolean) => { + const view3d = this._vp.view as ViewState3d; + const style = view3d.getDisplayStyle3d(); + style.environment = style.environment.withDisplay("sky" === which ? { sky: enabled } : { ground: enabled }); - if (undefined !== updateHandler) - updateHandler(enabled); + if (undefined !== updateHandler) + updateHandler(enabled); - this.sync(); - }, parent, this._nextId); + this.sync(); + }, + parent, + this._nextId, + ); const update = (view: ViewState) => { const visible = view.is3d(); diff --git a/test-apps/display-test-app/src/frontend/FeatureOverrides.ts b/test-apps/display-test-app/src/frontend/FeatureOverrides.ts index cdb1c3fa355b..a13833e6be5f 100644 --- a/test-apps/display-test-app/src/frontend/FeatureOverrides.ts +++ b/test-apps/display-test-app/src/frontend/FeatureOverrides.ts @@ -4,11 +4,18 @@ *--------------------------------------------------------------------------------------------*/ import { dispose, Id64String, IDisposable } from "@itwin/core-bentley"; -import { - ComboBox, ComboBoxHandler, convertHexToRgb, createButton, createCheckBox, createColorInput, createComboBox, createNumericInput, -} from "@itwin/frontend-devtools"; import { FeatureAppearance, FeatureAppearanceProps, LinePixels } from "@itwin/core-common"; import { FeatureOverrideProvider, FeatureSymbology, Viewport } from "@itwin/core-frontend"; +import { + ComboBox, + ComboBoxHandler, + convertHexToRgb, + createButton, + createCheckBox, + createColorInput, + createComboBox, + createNumericInput, +} from "@itwin/frontend-devtools"; import { ToolBarDropDown } from "./ToolBar"; export class Provider implements FeatureOverrideProvider { @@ -16,7 +23,9 @@ export class Provider implements FeatureOverrideProvider { private _defaultOvrs: FeatureAppearance | undefined; private readonly _vp: Viewport; - private constructor(vp: Viewport) { this._vp = vp; } + private constructor(vp: Viewport) { + this._vp = vp; + } public addFeatureOverrides(ovrs: FeatureSymbology.Overrides, _vp: Viewport): void { this._elementOvrs.forEach((appearance, elementId) => ovrs.override({ elementId, appearance })); @@ -73,7 +82,9 @@ export class Provider implements FeatureOverrideProvider { this.sync(); } - private sync(): void { this._vp.setFeatureOverrideProviderChanged(); } + private sync(): void { + this._vp.setFeatureOverrideProviderChanged(); + } public static get(vp: Viewport): Provider | undefined { return vp.findFeatureOverrideProvider((x) => x instanceof Provider) as Provider | undefined; @@ -171,19 +182,40 @@ export class Settings implements IDisposable { this._parent.removeChild(this._element); } - private get _provider() { return Provider.getOrCreate(this._vp); } + private get _provider() { + return Provider.getOrCreate(this._vp); + } // private reset() { this._appearance = FeatureSymbology.Appearance.defaults; } - private updateAppearance(field: "rgb" | "transparency" | "lineRgb" | "lineTransparency" | "linePixels" | "weight" | "ignoresMaterial" | "nonLocatable" | "emphasized" | "viewDependentTransparency", value: any): void { + private updateAppearance( + field: + | "rgb" + | "transparency" + | "lineRgb" + | "lineTransparency" + | "linePixels" + | "weight" + | "ignoresMaterial" + | "nonLocatable" + | "emphasized" + | "viewDependentTransparency", + value: any, + ): void { const props = this._appearance.toJSON(); props[field] = value; this._appearance = FeatureAppearance.fromJSON(props); } - private updateWeight(weight: number | undefined): void { this.updateAppearance("weight", weight); } - private updateIgnoreMaterial(ignoresMaterial: true | undefined): void { this.updateAppearance("ignoresMaterial", ignoresMaterial); } - private updateNonLocatable(nonLocatable: true | undefined): void { this.updateAppearance("nonLocatable", nonLocatable); } + private updateWeight(weight: number | undefined): void { + this.updateAppearance("weight", weight); + } + private updateIgnoreMaterial(ignoresMaterial: true | undefined): void { + this.updateAppearance("ignoresMaterial", ignoresMaterial); + } + private updateNonLocatable(nonLocatable: true | undefined): void { + this.updateAppearance("nonLocatable", nonLocatable); + } private updateStyle(style: LinePixels): void { const linePixels = LinePixels.Invalid !== style ? style : undefined; this.updateAppearance("linePixels", linePixels); @@ -427,7 +459,13 @@ export class FeatureOverridesPanel extends ToolBarDropDown { return Promise.resolve(); } - protected _open(): void { this._settings = new Settings(this._vp, this._parent); } - protected _close(): void { this._settings = dispose(this._settings); } - public get isOpen(): boolean { return undefined !== this._settings; } + protected _open(): void { + this._settings = new Settings(this._vp, this._parent); + } + protected _close(): void { + this._settings = dispose(this._settings); + } + public get isOpen(): boolean { + return undefined !== this._settings; + } } diff --git a/test-apps/display-test-app/src/frontend/Fence.ts b/test-apps/display-test-app/src/frontend/Fence.ts index 354545b90fbf..1563c486cec1 100644 --- a/test-apps/display-test-app/src/frontend/Fence.ts +++ b/test-apps/display-test-app/src/frontend/Fence.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { EmphasizeElements, IModelApp, ScreenViewport, Tool } from "@itwin/core-frontend"; import { BentleyStatus, Id64, Id64Array } from "@itwin/core-bentley"; -import { ClipPlaneContainment, ClipVector } from "@itwin/core-geometry"; import { ColorDef, GeometryContainmentRequestProps } from "@itwin/core-common"; +import { EmphasizeElements, IModelApp, ScreenViewport, Tool } from "@itwin/core-frontend"; +import { ClipPlaneContainment, ClipVector } from "@itwin/core-geometry"; /** Color code current selection set based on containment with current view clip. * For selecting elements outside clip, turn off clipvolume in view settings dialog. @@ -14,8 +14,12 @@ import { ColorDef, GeometryContainmentRequestProps } from "@itwin/core-common"; */ export class FenceClassifySelectedTool extends Tool { public static override toolId = "Fence.ClassifySelected"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public async doClassify(vp: ScreenViewport, candidates: Id64Array, clip: ClipVector, allowOverlaps: boolean): Promise { const requestProps: GeometryContainmentRequestProps = { diff --git a/test-apps/display-test-app/src/frontend/FileOpen.ts b/test-apps/display-test-app/src/frontend/FileOpen.ts index 5fef01121fc0..3216534aa770 100644 --- a/test-apps/display-test-app/src/frontend/FileOpen.ts +++ b/test-apps/display-test-app/src/frontend/FileOpen.ts @@ -74,7 +74,6 @@ export async function selectFileName(selector: BrowserFileSelector | undefined): properties: ["openFile"], title: "Open iModel", filters: [{ name: "iModels", extensions: ["ibim", "bim"] }], - }; const val = await ElectronApp.dialogIpc.showOpenDialog(opts); return val.canceled ? undefined : val.filePaths[0]; diff --git a/test-apps/display-test-app/src/frontend/FpsMonitor.ts b/test-apps/display-test-app/src/frontend/FpsMonitor.ts index 388a7ad49cd2..e187238c02c5 100644 --- a/test-apps/display-test-app/src/frontend/FpsMonitor.ts +++ b/test-apps/display-test-app/src/frontend/FpsMonitor.ts @@ -4,7 +4,14 @@ *--------------------------------------------------------------------------------------------*/ import { - IModelApp, NotifyMessageDetails, OutputMessagePriority, PerformanceMetrics, ScreenViewport, Target, Tool, Viewport, + IModelApp, + NotifyMessageDetails, + OutputMessagePriority, + PerformanceMetrics, + ScreenViewport, + Target, + Tool, + Viewport, } from "@itwin/core-frontend"; export interface FpsMonitorProps { @@ -35,7 +42,9 @@ export class FpsMonitor { vp.continuousRendering = true; } - public get enabled() { return this._enabled; } + public get enabled() { + return this._enabled; + } public set enabled(enabled: boolean) { if (enabled === this.enabled) return; @@ -73,8 +82,12 @@ export class FpsMonitor { export class RecordFpsTool extends Tool { public static override toolId = "RecordFps"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } private _hadContinuousRendering = false; private _numFramesToRecord = 0; diff --git a/test-apps/display-test-app/src/frontend/FrameStatsTool.ts b/test-apps/display-test-app/src/frontend/FrameStatsTool.ts index 21f0235d1a1f..bdea180b624a 100644 --- a/test-apps/display-test-app/src/frontend/FrameStatsTool.ts +++ b/test-apps/display-test-app/src/frontend/FrameStatsTool.ts @@ -8,8 +8,12 @@ import { FrameStats, IModelApp, Tool } from "@itwin/core-frontend"; /** Enable or disable (toggle) frame statistics reporting for all viewports. */ export class FrameStatsTool extends Tool { public static override toolId = "FrameStats"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 0; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 0; + } public override async run(): Promise { for (const vp of IModelApp.viewManager) { diff --git a/test-apps/display-test-app/src/frontend/GltfDecoration.ts b/test-apps/display-test-app/src/frontend/GltfDecoration.ts index eb9c6a977526..d6136c1134fd 100644 --- a/test-apps/display-test-app/src/frontend/GltfDecoration.ts +++ b/test-apps/display-test-app/src/frontend/GltfDecoration.ts @@ -3,13 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Angle, AxisIndex, Matrix3d, Point3d, Range3d, Transform } from "@itwin/core-geometry"; +import { Id64String } from "@itwin/core-bentley"; +import { ColorByName, ColorDef, RgbColor } from "@itwin/core-common"; import { - DecorateContext, GraphicBranch, GraphicType, IModelApp, IModelConnection, readGltfTemplate, RenderGraphic, RenderInstances, RenderInstancesParamsBuilder, Tool, + DecorateContext, + GraphicBranch, + GraphicType, + IModelApp, + IModelConnection, + readGltfTemplate, + RenderGraphic, + RenderInstances, + RenderInstancesParamsBuilder, + Tool, } from "@itwin/core-frontend"; +import { Angle, AxisIndex, Matrix3d, Point3d, Range3d, Transform } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; -import { Id64String } from "@itwin/core-bentley"; -import { ColorByName, ColorDef, RgbColor } from "@itwin/core-common"; class GltfDecoration { private readonly _graphic: RenderGraphic; @@ -66,7 +75,14 @@ function createTransform(maxExtent: number, wantScale: boolean, wantRotate: bool return translation.multiplyTransformTransform(scale).multiplyTransformTransform(rotation); } -function createInstances(numInstances: number, iModel: IModelConnection, modelId: Id64String, wantScale: boolean, wantColor: boolean, wantRotate: boolean): RenderInstances | undefined { +function createInstances( + numInstances: number, + iModel: IModelConnection, + modelId: Id64String, + wantScale: boolean, + wantColor: boolean, + wantRotate: boolean, +): RenderInstances | undefined { if (numInstances <= 1) { return undefined; } @@ -102,8 +118,12 @@ function createInstances(numInstances: number, iModel: IModelConnection, modelId */ export class GltfDecorationTool extends Tool { public static override toolId = "AddGltfDecoration"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 6; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 6; + } private _url?: string; private _numInstances = 1; diff --git a/test-apps/display-test-app/src/frontend/Grid.ts b/test-apps/display-test-app/src/frontend/Grid.ts index 5936779cf21c..47c5c27fa0e4 100644 --- a/test-apps/display-test-app/src/frontend/Grid.ts +++ b/test-apps/display-test-app/src/frontend/Grid.ts @@ -3,15 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { parseArgs } from "@itwin/frontend-devtools"; import { GridOrientationType } from "@itwin/core-common"; import { IModelApp, Tool } from "@itwin/core-frontend"; +import { parseArgs } from "@itwin/frontend-devtools"; /** Change grid settings for testing. */ export class ChangeGridSettingsTool extends Tool { public static override toolId = "GridSettings"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 4; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 4; + } public override async run(spacing?: number, ratio?: number, gridsPerRef?: number, orientation?: GridOrientationType): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/HubPicker.ts b/test-apps/display-test-app/src/frontend/HubPicker.ts index 4af6cc608e2d..cc7bcf99418c 100644 --- a/test-apps/display-test-app/src/frontend/HubPicker.ts +++ b/test-apps/display-test-app/src/frontend/HubPicker.ts @@ -38,9 +38,15 @@ export class HubPicker extends ToolBarDropDown { } } - protected _open(): void { this._element.style.display = "block"; } - protected _close(): void { this._element.style.display = "none"; } - public get isOpen(): boolean { return "none" !== this._element.style.display; } + protected _open(): void { + this._element.style.display = "block"; + } + protected _close(): void { + this._element.style.display = "none"; + } + public get isOpen(): boolean { + return "none" !== this._element.style.display; + } private _createTextBox(props: TextBoxProps, defaultValue: string | undefined) { const div = this._element.appendChild(document.createElement("div")); diff --git a/test-apps/display-test-app/src/frontend/IdPicker.ts b/test-apps/display-test-app/src/frontend/IdPicker.ts index b891df3275d4..11384b691f26 100644 --- a/test-apps/display-test-app/src/frontend/IdPicker.ts +++ b/test-apps/display-test-app/src/frontend/IdPicker.ts @@ -18,8 +18,12 @@ export abstract class IdPicker extends ToolBarDropDown { protected readonly _availableIds = new Set(); protected abstract get _elementType(): "Model" | "Category"; - protected get _settingsType(): "model" | "category" { return this._elementType.toLowerCase() as "model" | "category"; } - protected get _showIn2d(): boolean { return true; } + protected get _settingsType(): "model" | "category" { + return this._elementType.toLowerCase() as "model" | "category"; + } + protected get _showIn2d(): boolean { + return true; + } protected abstract get _enabledIds(): Set; protected abstract changeDisplay(ids: Id64Arg, enabled: boolean): void; @@ -121,10 +125,18 @@ export abstract class IdPicker extends ToolBarDropDown { parent.appendChild(this._element); } - public get isOpen(): boolean { return "none" !== this._element.style.display; } - protected _open(): void { this._element.style.display = "block"; } - protected _close(): void { this._element.style.display = "none"; } - public override get onViewChanged(): Promise { return this.populate(); } + public get isOpen(): boolean { + return "none" !== this._element.style.display; + } + protected _open(): void { + this._element.style.display = "block"; + } + protected _close(): void { + this._element.style.display = "none"; + } + public override get onViewChanged(): Promise { + return this.populate(); + } protected showOrHide(element: HTMLElement, show: boolean) { if (element) @@ -228,18 +240,28 @@ function getCategoryName(row: any): string { return undefined !== row.label ? row.label : row.code; } -const selectUsedSpatialCategoryIds = "SELECT DISTINCT Category.Id as CategoryId from BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId from BisCore.SpatialCategory)"; -const selectUsedDrawingCategoryIds = "SELECT DISTINCT Category.Id as CategoryId from BisCore.GeometricElement2d WHERE Model.Id=? AND Category.Id IN (SELECT ECInstanceId from BisCore.DrawingCategory)"; +const selectUsedSpatialCategoryIds = + "SELECT DISTINCT Category.Id as CategoryId from BisCore.GeometricElement3d WHERE Category.Id IN (SELECT ECInstanceId from BisCore.SpatialCategory)"; +const selectUsedDrawingCategoryIds = + "SELECT DISTINCT Category.Id as CategoryId from BisCore.GeometricElement2d WHERE Model.Id=? AND Category.Id IN (SELECT ECInstanceId from BisCore.DrawingCategory)"; const selectCategoryProps = "SELECT ECInstanceId as id, CodeValue as code, UserLabel as label FROM "; const selectSpatialCategoryProps = `${selectCategoryProps}BisCore.SpatialCategory WHERE ECInstanceId IN (${selectUsedSpatialCategoryIds})`; const selectDrawingCategoryProps = `${selectCategoryProps}BisCore.DrawingCategory WHERE ECInstanceId IN (${selectUsedDrawingCategoryIds})`; export class CategoryPicker extends IdPicker { - public constructor(vp: ScreenViewport, parent: HTMLElement) { super(vp, parent); } + public constructor(vp: ScreenViewport, parent: HTMLElement) { + super(vp, parent); + } - protected get _elementType(): "Category" { return "Category"; } - protected get _enabledIds() { return this._vp.view.categorySelector.categories; } - protected changeDisplay(ids: Id64Arg, enabled: boolean) { this._vp.changeCategoryDisplay(ids, enabled); } + protected get _elementType(): "Category" { + return "Category"; + } + protected get _enabledIds() { + return this._vp.view.categorySelector.categories; + } + protected changeDisplay(ids: Id64Arg, enabled: boolean) { + this._vp.changeCategoryDisplay(ids, enabled); + } protected override get _comboBoxEntries(): ComboBoxEntry[] { const entries = super._comboBoxEntries; @@ -257,7 +279,9 @@ export class CategoryPicker extends IdPicker { const ecsql = view.is3d() ? selectSpatialCategoryProps : selectDrawingCategoryProps; const bindings = view.is2d() ? [view.baseModelId] : undefined; const rows: any[] = []; - for await (const queryRow of view.iModel.createQueryReader(`${ecsql}`, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames })) { + for await ( + const queryRow of view.iModel.createQueryReader(`${ecsql}`, QueryBinder.from(bindings), { rowFormat: QueryRowFormat.UseJsPropertyNames }) + ) { rows.push(queryRow.toRow()); } rows.sort((lhs, rhs) => { @@ -322,11 +346,19 @@ export class ModelPicker extends IdPicker { private _fitOnStep = true; private _planProjectionIds: string[] = []; - public constructor(vp: ScreenViewport, parent: HTMLElement) { super(vp, parent); } + public constructor(vp: ScreenViewport, parent: HTMLElement) { + super(vp, parent); + } - protected get _elementType(): "Model" { return "Model"; } - protected get _enabledIds() { return (this._vp.view as SpatialViewState).modelSelector.models; } - protected override get _showIn2d() { return false; } + protected get _elementType(): "Model" { + return "Model"; + } + protected get _enabledIds() { + return (this._vp.view as SpatialViewState).modelSelector.models; + } + protected override get _showIn2d() { + return false; + } protected changeDisplay(ids: Id64Arg, enabled: boolean) { if (enabled) this._vp.addViewedModels(ids); // eslint-disable-line @typescript-eslint/no-floating-promises diff --git a/test-apps/display-test-app/src/frontend/IncidentMarkerDemo.ts b/test-apps/display-test-app/src/frontend/IncidentMarkerDemo.ts index 643846f57b6a..0a52d8ff4821 100644 --- a/test-apps/display-test-app/src/frontend/IncidentMarkerDemo.ts +++ b/test-apps/display-test-app/src/frontend/IncidentMarkerDemo.ts @@ -3,12 +3,23 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Logger } from "@itwin/core-bentley"; -import { AngleSweep, Arc3d, Point2d, Point3d, XAndY, XYAndZ } from "@itwin/core-geometry"; import { AxisAlignedBox3d, ColorByName, ColorDef } from "@itwin/core-common"; import { - BeButton, BeButtonEvent, Cluster, DecorateContext, GraphicType, imageElementFromUrl, IModelApp, Marker, MarkerImage, MarkerSet, MessageBoxIconType, - MessageBoxType, Tool, + BeButton, + BeButtonEvent, + Cluster, + DecorateContext, + GraphicType, + imageElementFromUrl, + IModelApp, + Marker, + MarkerImage, + MarkerSet, + MessageBoxIconType, + MessageBoxType, + Tool, } from "@itwin/core-frontend"; +import { AngleSweep, Arc3d, Point2d, Point3d, XAndY, XYAndZ } from "@itwin/core-geometry"; // cspell:ignore lerp @@ -26,7 +37,8 @@ class IncidentMarker extends Marker { /** Get a color based on severity by interpolating Green(0) -> Amber(15) -> Red(30) */ public static makeColor(severity: number): ColorDef { - return (severity <= 16 ? ColorDef.green.lerp(this._amber, (severity - 1) / 15.) : + return (severity <= 16 ? + ColorDef.green.lerp(this._amber, (severity - 1) / 15.) : this._amber.lerp(ColorDef.red, (severity - 16) / 14.)); } @@ -59,7 +71,6 @@ class IncidentMarker extends Marker { * but that effect isn't always desireable. * * World decorations for markers are completely optional. If you don't want anything drawn with WorldDecorations, don't follow this example. - * */ public override addMarker(context: DecorateContext) { super.addMarker(context); @@ -155,7 +166,9 @@ export class IncidentMarkerDemo { private static _numMarkers = 500; public static decorator?: IncidentMarkerDemo; // static variable so we can tell if the demo is active. - public get warningSign() { return this._images[0]; } + public get warningSign() { + return this._images[0]; + } // Load one image, logging if there was an error private async loadOne(src: string) { diff --git a/test-apps/display-test-app/src/frontend/LightingEditor.ts b/test-apps/display-test-app/src/frontend/LightingEditor.ts index 2f3a4ad04f9c..1afa0070ccf9 100644 --- a/test-apps/display-test-app/src/frontend/LightingEditor.ts +++ b/test-apps/display-test-app/src/frontend/LightingEditor.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CheckBox, createButton, createCheckBox, createColorInput, createLabeledNumericInput } from "@itwin/frontend-devtools"; import { ColorDef, LightSettings, LightSettingsProps, RenderMode, RgbColor, SolarShadowSettings } from "@itwin/core-common"; import { Viewport, ViewState } from "@itwin/core-frontend"; +import { CheckBox, createButton, createCheckBox, createColorInput, createLabeledNumericInput } from "@itwin/frontend-devtools"; // cspell:ignore cels sundir textbox hemi lighteditor @@ -101,7 +101,12 @@ export class LightingEditor { const span = document.createElement("span"); span.style.display = "flex"; parent.appendChild(span); - const intensityInput = this.addIntensityInput(span, "Solar", this._vp.lightSettings?.solar.intensity ?? 0, (intensity) => this.updateSettings({ solar: { intensity } })); + const intensityInput = this.addIntensityInput( + span, + "Solar", + this._vp.lightSettings?.solar.intensity ?? 0, + (intensity) => this.updateSettings({ solar: { intensity } }), + ); intensityInput.style.marginRight = "0.67em"; createButton({ @@ -134,8 +139,18 @@ export class LightingEditor { parent.appendChild(span); const lights = this._vp.lightSettings; - const portrait = this.addIntensityInput(span, "Portrait", lights?.portraitIntensity ?? 0, (intensity) => this.updateSettings({ portrait: { intensity } })); - const specular = this.addIntensityInput(span, "Specular", lights?.specularIntensity ?? 0, (specularIntensity) => this.updateSettings({ specularIntensity })); + const portrait = this.addIntensityInput( + span, + "Portrait", + lights?.portraitIntensity ?? 0, + (intensity) => this.updateSettings({ portrait: { intensity } }), + ); + const specular = this.addIntensityInput( + span, + "Specular", + lights?.specularIntensity ?? 0, + (specularIntensity) => this.updateSettings({ specularIntensity }), + ); portrait.style.marginRight = "0.67em"; this._updates.push((_view: ViewState) => { @@ -152,7 +167,12 @@ export class LightingEditor { span.style.display = "flex"; parent.appendChild(span); - const intensityInput = this.addIntensityInput(span, "Fresnel", this._vp.lightSettings?.fresnel.intensity ?? 0, (intensity) => this.updateSettings({ fresnel: { intensity } })); + const intensityInput = this.addIntensityInput( + span, + "Fresnel", + this._vp.lightSettings?.fresnel.intensity ?? 0, + (intensity) => this.updateSettings({ fresnel: { intensity } }), + ); intensityInput.style.marginRight = "0.67em"; const cb = this.addCheckBox("Invert", (invert: boolean) => this.updateSettings({ fresnel: { invert } }), span); @@ -171,7 +191,12 @@ export class LightingEditor { parent.appendChild(span); const amb = this._vp.lightSettings?.ambient; - const intensityInput = this.addIntensityInput(span, "Ambient", amb?.intensity ?? 0, (intensity) => this.updateSettings({ ambient: { intensity } })); + const intensityInput = this.addIntensityInput( + span, + "Ambient", + amb?.intensity ?? 0, + (intensity) => this.updateSettings({ ambient: { intensity } }), + ); const colorInput = createColorInput({ parent: span, display: "inline", @@ -196,7 +221,12 @@ export class LightingEditor { parent.appendChild(span); const hemi = this._vp.lightSettings?.hemisphere; - const intensityInput = this.addIntensityInput(span, "Hemisphere", hemi?.intensity ?? 0, (intensity) => this.updateSettings({ hemisphere: { intensity } })); + const intensityInput = this.addIntensityInput( + span, + "Hemisphere", + hemi?.intensity ?? 0, + (intensity) => this.updateSettings({ hemisphere: { intensity } }), + ); intensityInput.style.marginRight = "0.67em"; const skyInput = createColorInput({ diff --git a/test-apps/display-test-app/src/frontend/MacroTools.ts b/test-apps/display-test-app/src/frontend/MacroTools.ts index 9a1f0faee260..678ec85098d5 100644 --- a/test-apps/display-test-app/src/frontend/MacroTools.ts +++ b/test-apps/display-test-app/src/frontend/MacroTools.ts @@ -2,22 +2,34 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { IModelApp, MessageBoxIconType, MessageBoxType, NotifyMessageDetails, OutputMessagePriority, ParseAndRunResult, Tool } from "@itwin/core-frontend"; +import { + IModelApp, + MessageBoxIconType, + MessageBoxType, + NotifyMessageDetails, + OutputMessagePriority, + ParseAndRunResult, + Tool, +} from "@itwin/core-frontend"; import { DtaRpcInterface } from "../common/DtaRpcInterface"; export class MacroTool extends Tool { public static override toolId = "Macro"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async run(macroFile: string): Promise { const macroString = await DtaRpcInterface.getClient().readExternalFile(macroFile); const re = /\r/g; - const macroStr2 = macroString.replace (re, ""); - const commands = macroStr2.split ("\n"); + const macroStr2 = macroString.replace(re, ""); + const commands = macroStr2.split("\n"); commands.forEach((item, index) => { - if(item === "") - commands.splice(index,1); + if (item === "") + commands.splice(index, 1); }); if (commands.length === 0) { @@ -48,7 +60,7 @@ export class MacroTool extends Tool { } public override async parseAndRun(...args: string[]): Promise { - const macroFile=args[0]; + const macroFile = args[0]; return this.run(macroFile); } } diff --git a/test-apps/display-test-app/src/frontend/NamedViews.ts b/test-apps/display-test-app/src/frontend/NamedViews.ts index 1d990b44b498..ec43ebf2b8be 100644 --- a/test-apps/display-test-app/src/frontend/NamedViews.ts +++ b/test-apps/display-test-app/src/frontend/NamedViews.ts @@ -33,15 +33,24 @@ export class NamedViewStatePropsString { this._displayTransforms = props._displayTransforms; } - public get name(): string { return this._name; } - public get viewStatePropsString(): string { return this._viewStatePropsString; } - public get selectedElements(): string | undefined { return this._selectedElements; } - public get overrideElements(): string | undefined { return this._overrideElements; } - public get displayTransforms(): string | undefined { return this._displayTransforms; } + public get name(): string { + return this._name; + } + public get viewStatePropsString(): string { + return this._viewStatePropsString; + } + public get selectedElements(): string | undefined { + return this._selectedElements; + } + public get overrideElements(): string | undefined { + return this._overrideElements; + } + public get displayTransforms(): string | undefined { + return this._displayTransforms; + } } export class NamedVSPSList extends SortedArray { - private constructor() { super((lhs, rhs) => compareStrings(lhs.name, rhs.name)); } diff --git a/test-apps/display-test-app/src/frontend/Notifications.ts b/test-apps/display-test-app/src/frontend/Notifications.ts index 9798c172075c..d158c43121c0 100644 --- a/test-apps/display-test-app/src/frontend/Notifications.ts +++ b/test-apps/display-test-app/src/frontend/Notifications.ts @@ -2,10 +2,16 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { XAndY } from "@itwin/core-geometry"; import { - IModelApp, MessageBoxIconType, MessageBoxType, MessageBoxValue, NotificationManager, NotifyMessageDetails, ToolTipOptions, + IModelApp, + MessageBoxIconType, + MessageBoxType, + MessageBoxValue, + NotificationManager, + NotifyMessageDetails, + ToolTipOptions, } from "@itwin/core-frontend"; +import { XAndY } from "@itwin/core-geometry"; import { Surface } from "./Surface"; import { showError, showStatus } from "./Utils"; import { Window, WindowProps } from "./Window"; @@ -19,8 +25,12 @@ export interface NotificationsWindowProps extends WindowProps { export class NotificationsWindow extends Window { private readonly _maxMessages: number; - public override get isCloseable() { return false; } - public get windowId() { return "notifications"; } + public override get isCloseable() { + return false; + } + public get windowId() { + return "notifications"; + } public constructor(surface: Surface, props: NotificationsWindowProps) { super(surface, props); @@ -51,7 +61,9 @@ export class NotificationsWindow extends Window { export class Notifications extends NotificationManager { private _tooltipDiv?: HTMLDivElement; - public override outputPrompt(prompt: string) { showStatus(prompt); } + public override outputPrompt(prompt: string) { + showStatus(prompt); + } /** Output a message and/or alert to the user. */ public override outputMessage(message: NotifyMessageDetails) { @@ -91,7 +103,9 @@ export class Notifications extends NotificationManager { return promise; } - public override get isToolTipSupported() { return true; } + public override get isToolTipSupported() { + return true; + } public override get isToolTipOpen() { return undefined !== this._tooltipDiv; } diff --git a/test-apps/display-test-app/src/frontend/OutputShadersTool.ts b/test-apps/display-test-app/src/frontend/OutputShadersTool.ts index 08abeb711054..9ae65a7614da 100644 --- a/test-apps/display-test-app/src/frontend/OutputShadersTool.ts +++ b/test-apps/display-test-app/src/frontend/OutputShadersTool.ts @@ -321,13 +321,22 @@ async function outputShaders(dsf: DebugShaderFile[], usedFlag: string, typeFlag: export class OutputShadersTool extends Tool { public static override toolId = "OutputShaders"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 2; + } public override async run(compile: boolean, usedFlag: string, typeFlag: string, langFlag: string, outputDir: string): Promise { if (compile) { const compiled = IModelApp.renderSystem.debugControl?.compileAllShaders(); - IModelApp.notifications.outputMessage(new NotifyMessageDetails(compiled ? OutputMessagePriority.Info : OutputMessagePriority.Error, `${compiled ? "No" : "Some"} compilation errors occurred.`)); + IModelApp.notifications.outputMessage( + new NotifyMessageDetails( + compiled ? OutputMessagePriority.Info : OutputMessagePriority.Error, + `${compiled ? "No" : "Some"} compilation errors occurred.`, + ), + ); } const dsf = IModelApp.renderSystem.debugControl?.debugShaderFiles; if (undefined !== dsf && dsf.length > 0) diff --git a/test-apps/display-test-app/src/frontend/PathDecorationTest.ts b/test-apps/display-test-app/src/frontend/PathDecorationTest.ts index 234da8940967..4bee95f1a403 100644 --- a/test-apps/display-test-app/src/frontend/PathDecorationTest.ts +++ b/test-apps/display-test-app/src/frontend/PathDecorationTest.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { CanvasDecoration, DecorateContext, GraphicType, HitDetail, IModelApp, Tool } from "@itwin/core-frontend"; import { AxisAlignedBox3d, GeometryStreamProps } from "@itwin/core-common"; +import { CanvasDecoration, DecorateContext, GraphicType, HitDetail, IModelApp, Tool } from "@itwin/core-frontend"; import { AngleSweep, Arc3d, Path, Range1d, Range3d } from "@itwin/core-geometry"; class PathCanvasDecoration implements CanvasDecoration { @@ -44,10 +44,14 @@ export class PathDecorationTest { } /** Test any hits against this id. */ - public testDecorationHit(id: string): boolean { return id === this._pickId; } + public testDecorationHit(id: string): boolean { + return id === this._pickId; + } /** Return no decoration geometry for picking. */ - public getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined { return undefined; } + public getDecorationGeometry(_hit: HitDetail): GeometryStreamProps | undefined { + return undefined; + } /** Create the PathDecorationTest object and adding it as a ViewManager decorator. */ private static start(extents: AxisAlignedBox3d) { diff --git a/test-apps/display-test-app/src/frontend/RealityDataModel.ts b/test-apps/display-test-app/src/frontend/RealityDataModel.ts index b55f9e57c9e8..58dd0c407152 100644 --- a/test-apps/display-test-app/src/frontend/RealityDataModel.ts +++ b/test-apps/display-test-app/src/frontend/RealityDataModel.ts @@ -11,14 +11,23 @@ import { attachGeoscienceTileset } from "@itwin/frontend-tiles"; */ export class AddSeequentRealityModel extends Tool { public static override toolId = "AddSeequentRealityModel"; - public static override get minArgs() { return 5; } - public static override get maxArgs() { return 5; } + public static override get minArgs() { + return 5; + } + public static override get maxArgs() { + return 5; + } /** This method runs the tool, adding a reality model to the viewport * @param url the URL which points to the reality model tileset */ - public override async run(endpointUrl: string, organizationId: string, workspaceId: string, geoscienceObjectId: string, accessToken: string): Promise { - + public override async run( + endpointUrl: string, + organizationId: string, + workspaceId: string, + geoscienceObjectId: string, + accessToken: string, + ): Promise { const args = { endpointUrl, accessToken, diff --git a/test-apps/display-test-app/src/frontend/RealityDataProvider.ts b/test-apps/display-test-app/src/frontend/RealityDataProvider.ts index ec0e4dc127f5..a8610b5a4e78 100644 --- a/test-apps/display-test-app/src/frontend/RealityDataProvider.ts +++ b/test-apps/display-test-app/src/frontend/RealityDataProvider.ts @@ -25,13 +25,27 @@ class CustomRealityDataSource implements RealityDataSource { this._baseUrl = url.origin; } - public get isContextShare() { return false; } - public get realityData() { return undefined; } - public get realityDataId() { return undefined; } - public get realityDataType() { return "ThreeDTile"; } - public async getServiceUrl() { return Promise.resolve(this._tilesetUrl); } - public async getSpatialLocationAndExtents() { return Promise.resolve(undefined); } - public async getPublisherProductInfo() { return Promise.resolve(undefined); } + public get isContextShare() { + return false; + } + public get realityData() { + return undefined; + } + public get realityDataId() { + return undefined; + } + public get realityDataType() { + return "ThreeDTile"; + } + public async getServiceUrl() { + return Promise.resolve(this._tilesetUrl); + } + public async getSpatialLocationAndExtents() { + return Promise.resolve(undefined); + } + public async getPublisherProductInfo() { + return Promise.resolve(undefined); + } public async getRootDocument(): Promise { const response = await fetch(`${this._tilesetUrl}?key=${this._apiKey}`); @@ -64,8 +78,12 @@ export function registerRealityDataSourceProvider(apiKey: string): void { export class AttachCustomRealityDataTool extends Tool { public static override toolId = "AttachCustomRealityData"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 1; + } public override async run(url: string): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/RealityModelDisplaySettingsWidget.ts b/test-apps/display-test-app/src/frontend/RealityModelDisplaySettingsWidget.ts index c75bcfc1125c..12f93e89f03b 100644 --- a/test-apps/display-test-app/src/frontend/RealityModelDisplaySettingsWidget.ts +++ b/test-apps/display-test-app/src/frontend/RealityModelDisplaySettingsWidget.ts @@ -3,14 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { - DisplayStyleSettings, FeatureAppearance, FeatureAppearanceProps, PointCloudDisplayProps, RealityModelDisplayProps, RealityModelDisplaySettings, + DisplayStyleSettings, + FeatureAppearance, + FeatureAppearanceProps, + PointCloudDisplayProps, + RealityModelDisplayProps, + RealityModelDisplaySettings, } from "@itwin/core-common"; -import { - ContextRealityModelState, IModelApp, ScreenViewport, SpatialModelState, Tool, Viewport, -} from "@itwin/core-frontend"; +import { ContextRealityModelState, IModelApp, ScreenViewport, SpatialModelState, Tool, Viewport } from "@itwin/core-frontend"; import { ComboBoxEntry, - convertHexToRgb, createCheckBox, createColorInput, createComboBox, createRadioBox, createSlider, + convertHexToRgb, + createCheckBox, + createColorInput, + createComboBox, + createRadioBox, + createSlider, } from "@itwin/frontend-devtools"; import { Surface } from "./Surface"; import { ToolBarDropDown } from "./ToolBar"; @@ -29,13 +37,23 @@ class ContextModel implements RealityModel { this._state = state; } - public get name() { return this._state.name || this._state.orbitGtBlob?.blobFileName || this._state.url; } + public get name() { + return this._state.name || this._state.orbitGtBlob?.blobFileName || this._state.url; + } - public get settings() { return this._state.displaySettings; } - public set settings(value: RealityModelDisplaySettings) { this._state.displaySettings = value; } + public get settings() { + return this._state.displaySettings; + } + public set settings(value: RealityModelDisplaySettings) { + this._state.displaySettings = value; + } - public get appearance() { return this._state.appearanceOverrides; } - public set appearance(value: FeatureAppearance | undefined) { this._state.appearanceOverrides = value; } + public get appearance() { + return this._state.appearanceOverrides; + } + public set appearance(value: FeatureAppearance | undefined) { + this._state.appearanceOverrides = value; + } } class PersistentModel implements RealityModel { @@ -47,12 +65,20 @@ class PersistentModel implements RealityModel { this._settings = settings; } - public get name() { return this._model.name ?? this._model.jsonProperties.tilesetUrl; } + public get name() { + return this._model.name ?? this._model.jsonProperties.tilesetUrl; + } - public get settings() { return this._settings.getRealityModelDisplaySettings(this._model.id) ?? RealityModelDisplaySettings.defaults; } - public set settings(value: RealityModelDisplaySettings) { this._settings.setRealityModelDisplaySettings(this._model.id, value); } + public get settings() { + return this._settings.getRealityModelDisplaySettings(this._model.id) ?? RealityModelDisplaySettings.defaults; + } + public set settings(value: RealityModelDisplaySettings) { + this._settings.setRealityModelDisplaySettings(this._model.id, value); + } - public get appearance() { return this._settings.getModelAppearanceOverride(this._model.id); } + public get appearance() { + return this._settings.getModelAppearanceOverride(this._model.id); + } public set appearance(value: FeatureAppearance | undefined) { if (value) this._settings.overrideModelAppearance(this._model.id, value); @@ -99,10 +125,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme }); const colorRatio = createSlider({ - parent: colorDiv, id: "rms_ratio", name: " Ratio ", - min: "0", max: "1", step: "0.05", + parent: colorDiv, + id: "rms_ratio", + name: " Ratio ", + min: "0", + max: "1", + step: "0.05", value: model.settings.overrideColorRatio.toString(), - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const overrideColorRatio = Number.parseFloat(slider.value); if (!Number.isNaN(overrideColorRatio)) @@ -115,7 +147,8 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme // Point shape const updatePointCloud = (props: PointCloudDisplayProps) => updateSettings(model.settings.clone({ pointCloud: props })); createCheckBox({ - name: "Square points:", id: "rms_square", + name: "Square points:", + id: "rms_square", parent: element, isChecked: model.settings.pointCloud.shape === "square", handler: (cb) => updatePointCloud({ shape: cb.checked ? "square" : "round" }), @@ -143,10 +176,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme // Pixel size const voxelSizeSlider = createSlider({ - name: " Size ", id: "rms_scale", parent: sizeMode.div, - min: "0.25", max: "10", step: "0.25", + name: " Size ", + id: "rms_scale", + parent: sizeMode.div, + min: "0.25", + max: "10", + step: "0.25", value: model.settings.pointCloud.voxelScale.toString(), - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -155,10 +194,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme }).div; const pixelSizeSlider = createSlider({ - name: " Size ", id: "rms_size", parent: sizeMode.div, - min: "1", max: "64", step: "1", + name: " Size ", + id: "rms_size", + parent: sizeMode.div, + min: "1", + max: "64", + step: "1", value: model.settings.pointCloud.pixelSize.toString(), - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const pixelSize = Number.parseInt(slider.value, 10); if (!Number.isNaN(pixelSize)) @@ -207,10 +252,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme // EDL strength const edlStrengthSlider = createSlider({ - name: " Strength ", id: "pcs_strength", parent: element, - min: "0.0", max: "25", step: "0.25", + name: " Strength ", + id: "pcs_strength", + parent: element, + min: "0.0", + max: "25", + step: "0.25", value: model.settings.pointCloud.edlStrength.toString(), - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -221,10 +272,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme // EDL radius const edlRadiusSlider = createSlider({ - name: " Radius ", id: "pcs_radius", parent: element, - min: "0.0", max: "25", step: "0.25", + name: " Radius ", + id: "pcs_radius", + parent: element, + min: "0.0", + max: "25", + step: "0.25", value: model.settings.pointCloud.edlRadius.toString(), - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -234,17 +291,24 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme edlRadiusSlider.style.display = ""; const edlFilter = createCheckBox({ - name: " Filter", id: "pcs_filter", + name: " Filter", + id: "pcs_filter", parent: element, isChecked: model.settings.pointCloud.edlFilter === 1, handler: (cb) => updatePointCloud({ edlFilter: cb.checked ? 1 : 0 }), }).div; const edlMixWt1Slider = createSlider({ - name: " Mix Wt 1 ", id: "pcs_mixwt1", parent: element, - min: "0.0", max: "1", step: "0.01", + name: " Mix Wt 1 ", + id: "pcs_mixwt1", + parent: element, + min: "0.0", + max: "1", + step: "0.01", value: model.settings.pointCloud.edlMixWts1?.toString() ?? "1", - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -254,10 +318,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme edlMixWt1Slider.style.display = ""; const edlMixWt2Slider = createSlider({ - name: " Mix Wt 2 ", id: "pcs_mixwt2", parent: element, - min: "0.0", max: "1", step: "0.01", + name: " Mix Wt 2 ", + id: "pcs_mixwt2", + parent: element, + min: "0.0", + max: "1", + step: "0.01", value: model.settings.pointCloud.edlMixWts2?.toString() ?? "0.5", - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -267,10 +337,16 @@ function createRealityModelSettingsPanel(model: RealityModel, element: HTMLEleme edlMixWt2Slider.style.display = ""; const edlMixWt4Slider = createSlider({ - name: " Mix Wt 4 ", id: "pcs_mixwt4", parent: element, - min: "0.0", max: "1", step: "0.01", + name: " Mix Wt 4 ", + id: "pcs_mixwt4", + parent: element, + min: "0.0", + max: "1", + step: "0.01", value: model.settings.pointCloud.edlMixWts4?.toString() ?? "0.25", - readout: "right", verticalAlign: false, textAlign: false, + readout: "right", + verticalAlign: false, + textAlign: false, handler: (slider) => { const scale = Number.parseFloat(slider.value); if (!Number.isNaN(scale)) @@ -329,14 +405,22 @@ class RealityModelSettingsWidget extends Window { viewportIdsWithOpenWidgets.delete(this._viewport.viewportId); } - public get windowId() { return this._windowId; } - public override get isResizable() { return false; } + public get windowId() { + return this._windowId; + } + public override get isResizable() { + return false; + } } export class OpenRealityModelSettingsTool extends Tool { public static override toolId = "OpenRealityModelSettings"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(vp?: Viewport, model?: RealityModel): Promise { if (!vp || !model) @@ -470,7 +554,13 @@ export class RealityModelSettingsPanel extends ToolBarDropDown { createRealityModelSettingsPanel(realityModel, this._element); } - public get isOpen(): boolean { return "none" !== this._element.style.display; } - protected _open(): void { this._element.style.display = "block"; } - protected _close(): void { this._element.style.display = "none"; } + public get isOpen(): boolean { + return "none" !== this._element.style.display; + } + protected _open(): void { + this._element.style.display = "block"; + } + protected _close(): void { + this._element.style.display = "none"; + } } diff --git a/test-apps/display-test-app/src/frontend/SaveImageTool.ts b/test-apps/display-test-app/src/frontend/SaveImageTool.ts index 24563eabce39..429efe38ae58 100644 --- a/test-apps/display-test-app/src/frontend/SaveImageTool.ts +++ b/test-apps/display-test-app/src/frontend/SaveImageTool.ts @@ -4,8 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import { ProcessDetector } from "@itwin/core-bentley"; -import { Point2d } from "@itwin/core-geometry"; import { imageBufferToPngDataUrl, IModelApp, openImageDataUrlInNewWindow, Tool } from "@itwin/core-frontend"; +import { Point2d } from "@itwin/core-geometry"; import { parseArgs } from "@itwin/frontend-devtools"; interface SaveImageOptions { @@ -16,8 +16,12 @@ interface SaveImageOptions { export class SaveImageTool extends Tool { public static override toolId = "SaveImage"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 3; + } public override async run(opts?: SaveImageOptions): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/SavedViews.ts b/test-apps/display-test-app/src/frontend/SavedViews.ts index 44168a98204e..9e18f9270c35 100644 --- a/test-apps/display-test-app/src/frontend/SavedViews.ts +++ b/test-apps/display-test-app/src/frontend/SavedViews.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import { Id64Arg } from "@itwin/core-bentley"; -import { createButton, createTextBox, deserializeViewState, serializeViewState } from "@itwin/frontend-devtools"; import { IModelConnection, Viewport, ViewState } from "@itwin/core-frontend"; +import { createButton, createTextBox, deserializeViewState, serializeViewState } from "@itwin/frontend-devtools"; import { DtaRpcInterface } from "../common/DtaRpcInterface"; +import { DisplayTransformProvider } from "./DisplayTransform"; import { Provider } from "./FeatureOverrides"; import { NamedViewStatePropsString, NamedVSPSList } from "./NamedViews"; import { ToolBarDropDown } from "./ToolBar"; -import { DisplayTransformProvider } from "./DisplayTransform"; export interface ApplySavedView { applySavedView(view: ViewState): Promise; @@ -48,9 +48,15 @@ export class SavedViewPicker extends ToolBarDropDown { parent.appendChild(this._element); } - public get isOpen() { return "none" !== this._element.style.display; } - protected _open() { this._element.style.display = "block"; } - protected _close() { this._element.style.display = "none"; } + public get isOpen() { + return "none" !== this._element.style.display; + } + protected _open() { + this._element.style.display = "block"; + } + protected _close() { + this._element.style.display = "none"; + } public override get onViewChanged(): Promise | undefined { if (this._imodel !== this._vp.iModel) { @@ -174,7 +180,11 @@ export class SavedViewPicker extends ToolBarDropDown { textBox.textbox.style.color = viewExists ? "red" : ""; }; - newButton.disabled = recallButton.disabled = updateButton.disabled = deleteButton.disabled = true; + newButton.disabled = + recallButton.disabled = + updateButton.disabled = + deleteButton.disabled = + true; } private async recallView(): Promise { diff --git a/test-apps/display-test-app/src/frontend/SectionTools.ts b/test-apps/display-test-app/src/frontend/SectionTools.ts index c2c84bf05763..eb2ddb3b712f 100644 --- a/test-apps/display-test-app/src/frontend/SectionTools.ts +++ b/test-apps/display-test-app/src/frontend/SectionTools.ts @@ -3,10 +3,10 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { BeEvent } from "@itwin/core-bentley"; -import { createButton, createComboBox } from "@itwin/frontend-devtools"; -import { ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Point3d, Vector3d } from "@itwin/core-geometry"; import { ModelClipGroup, ModelClipGroups } from "@itwin/core-common"; import { AccuDrawHintBuilder, IModelApp, ScreenViewport, ViewClipDecorationProvider, Viewport } from "@itwin/core-frontend"; +import { ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Point3d, Vector3d } from "@itwin/core-geometry"; +import { createButton, createComboBox } from "@itwin/frontend-devtools"; import { ToolBarDropDown } from "./ToolBar"; import { ViewClipByElementGeometryTool } from "./ViewClipByElementGeometryTool"; @@ -82,7 +82,7 @@ export class SectionsPanel extends ToolBarDropDown { bounds: vp.getClientRect(), buffer: 10, parent: vp.canvas.parentElement!, - onDragged: (left, _right) => ModelClipTool.applyModelClipping(vp, new Point3d(left, (vp.getClientRect().height / 2), 0), negate), + onDragged: (left, _right) => ModelClipTool.applyModelClipping(vp, new Point3d(left, vp.getClientRect().height / 2, 0), negate), }; const divider = new TwoPanelDivider(props); divider.dividerElem.style.zIndex = "10"; @@ -93,16 +93,24 @@ export class SectionsPanel extends ToolBarDropDown { }); createButton({ value: "Negate Plane", - handler: () => { negate = !negate; }, + handler: () => { + negate = !negate; + }, parent: div, inline: true, tooltip: "Negate Plane", }); } - protected _open(): void { this._element.style.display = "block"; } - protected _close(): void { this._element.style.display = "none"; } - public get isOpen(): boolean { return "block" === this._element.style.display; } + protected _open(): void { + this._element.style.display = "block"; + } + protected _close(): void { + this._element.style.display = "none"; + } + public get isOpen(): boolean { + return "block" === this._element.style.display; + } } class ModelClipTool { @@ -191,7 +199,10 @@ export class TwoPanelDivider { left = props.bounds.width / 2; this.dividerElem = IModelApp.makeHTMLElement("div"); - this.dividerElem.setAttribute("style", "width: 4px; position: fixed; display: flex; background-color: #f1f1f1; border: 1px solid #d3d3d3; /*dde0e3*/ pointer-events: visible;"); + this.dividerElem.setAttribute( + "style", + "width: 4px; position: fixed; display: flex; background-color: #f1f1f1; border: 1px solid #d3d3d3; /*dde0e3*/ pointer-events: visible;", + ); if (props.id !== undefined) this.dividerElem.id = props.id; @@ -203,7 +214,10 @@ export class TwoPanelDivider { props.parent.appendChild(this.dividerElem); const handle = IModelApp.makeHTMLElement("div"); - handle.setAttribute("style", "position: relative; box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.25); left: -10px; padding: 12px; height: 32px; border-radius: 1.5px; cursor: col-resize; align-self: center; background-color: #69ade3; /* dde0e3 */ /* dots c8ccd0*/ color: #fff;"); + handle.setAttribute( + "style", + "position: relative; box-shadow: 0px 1px 5px 0px rgba(0, 0, 0, 0.25); left: -10px; padding: 12px; height: 32px; border-radius: 1.5px; cursor: col-resize; align-self: center; background-color: #69ade3; /* dde0e3 */ /* dots c8ccd0*/ color: #fff;", + ); this.dividerElem.appendChild(handle); if (props.onDragged) diff --git a/test-apps/display-test-app/src/frontend/ShadowMapDecoration.ts b/test-apps/display-test-app/src/frontend/ShadowMapDecoration.ts index 2c648fbfb2ff..91384e72753b 100644 --- a/test-apps/display-test-app/src/frontend/ShadowMapDecoration.ts +++ b/test-apps/display-test-app/src/frontend/ShadowMapDecoration.ts @@ -2,10 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { parseToggle } from "@itwin/frontend-devtools"; import { - DecorateContext, GraphicBranch, GraphicType, IModelApp, RenderGraphic, RenderGraphicOwner, Target, Tool, Viewport, + DecorateContext, + GraphicBranch, + GraphicType, + IModelApp, + RenderGraphic, + RenderGraphicOwner, + Target, + Tool, + Viewport, } from "@itwin/core-frontend"; +import { parseToggle } from "@itwin/frontend-devtools"; class ShadowMapDecoration { private static _instance?: ShadowMapDecoration; @@ -13,7 +21,9 @@ class ShadowMapDecoration { private readonly _graphics: RenderGraphic[] = []; private _removeMe?: () => void; - private get _target(): Target { return this._vp.target as Target; } + private get _target(): Target { + return this._vp.target as Target; + } private constructor(vp: Viewport) { this._vp = vp; @@ -101,8 +111,12 @@ class ShadowMapDecoration { /** Decorates all other viewports with the tiles selected for drawing the selected viewport's shadow map. */ export class ToggleShadowMapTilesTool extends Tool { public static override toolId = "ToggleShadowMapTiles"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(enable?: boolean): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/SimpleViewState.ts b/test-apps/display-test-app/src/frontend/SimpleViewState.ts index ee62aace033f..390a41ac5710 100644 --- a/test-apps/display-test-app/src/frontend/SimpleViewState.ts +++ b/test-apps/display-test-app/src/frontend/SimpleViewState.ts @@ -7,5 +7,5 @@ import { BrowserAuthorizationClient } from "@itwin/browser-authorization"; /** Global information on the currently opened iModel and the state of the view. */ export class SimpleViewState { public oidcClient?: BrowserAuthorizationClient; - constructor() { } + constructor() {} } diff --git a/test-apps/display-test-app/src/frontend/SnapModes.ts b/test-apps/display-test-app/src/frontend/SnapModes.ts index 81ae655d9466..3444a8ee7570 100644 --- a/test-apps/display-test-app/src/frontend/SnapModes.ts +++ b/test-apps/display-test-app/src/frontend/SnapModes.ts @@ -3,8 +3,8 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { createComboBox } from "@itwin/frontend-devtools"; import { SnapMode } from "@itwin/core-frontend"; +import { createComboBox } from "@itwin/frontend-devtools"; import { DisplayTestApp } from "./App"; const multiSnapModes = [ diff --git a/test-apps/display-test-app/src/frontend/StandardRotations.ts b/test-apps/display-test-app/src/frontend/StandardRotations.ts index 4462f83cfd11..b262fb984bad 100644 --- a/test-apps/display-test-app/src/frontend/StandardRotations.ts +++ b/test-apps/display-test-app/src/frontend/StandardRotations.ts @@ -50,9 +50,15 @@ export class StandardRotations extends ToolBarDropDown { parent.appendChild(this._element); } - public get isOpen() { return "none" !== this._element.style.display; } - protected _open() { this._element.style.display = "block"; } - protected _close() { this._element.style.display = "none"; } + public get isOpen() { + return "none" !== this._element.style.display; + } + protected _open() { + this._element.style.display = "block"; + } + protected _close() { + this._element.style.display = "none"; + } public override get onViewChanged(): Promise { this._parent.style.display = this._vp.view.allow3dManipulations() ? "block" : "none"; diff --git a/test-apps/display-test-app/src/frontend/Surface.ts b/test-apps/display-test-app/src/frontend/Surface.ts index 9f497db0763a..823496d5f5cd 100644 --- a/test-apps/display-test-app/src/frontend/Surface.ts +++ b/test-apps/display-test-app/src/frontend/Surface.ts @@ -2,23 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { KeyinField, parseArgs } from "@itwin/frontend-devtools"; -import { Range3d } from "@itwin/core-geometry"; import { Cartographic } from "@itwin/core-common"; import { BlankConnection, BlankConnectionProps, IModelApp, Tool } from "@itwin/core-frontend"; +import { Range3d } from "@itwin/core-geometry"; +import { KeyinField, parseArgs } from "@itwin/frontend-devtools"; +import { openAnalysisStyleExample } from "./AnalysisStyleExample"; import { DisplayTestApp } from "./App"; +import { openDecorationGeometryExample } from "./DecorationGeometryExample"; import { BrowserFileSelector, selectFileName } from "./FileOpen"; import { FpsMonitor } from "./FpsMonitor"; import { NotificationsWindow } from "./Notifications"; +import { openIModel, OpenIModelProps } from "./openIModel"; import { addSnapModes } from "./SnapModes"; import { TileLoadIndicator } from "./TileLoadIndicator"; +import { setTitle } from "./Title"; import { createToolButton, ToolBar } from "./ToolBar"; import { Viewer, ViewerProps } from "./Viewer"; import { Dock, NamedWindow, NamedWindowProps, Window, WindowProps } from "./Window"; -import { openIModel, OpenIModelProps } from "./openIModel"; -import { setTitle } from "./Title"; -import { openAnalysisStyleExample } from "./AnalysisStyleExample"; -import { openDecorationGeometryExample } from "./DecorationGeometryExample"; // cspell:ignore textbox topdiv @@ -33,7 +33,9 @@ export class Surface { public readonly browserFileSelector?: BrowserFileSelector; public readonly openReadWrite: boolean; - public static get instance() { return DisplayTestApp.surface; } + public static get instance() { + return DisplayTestApp.surface; + } public constructor(surfaceDiv: HTMLElement, toolbarDiv: HTMLElement, browserFileSelector: BrowserFileSelector | undefined, openReadWrite: boolean) { // Ensure iModel gets closed on page close/reload @@ -166,7 +168,7 @@ export class Surface { // create a new blank connection for testing backgroundMap and reality models. private async openBlankConnection(props?: Partial): Promise { const iModel = BlankConnection.create({ - location: props?.location ?? Cartographic.fromDegrees({longitude: -75.686694, latitude: 40.065757, height: 0}), // near Exton pa + location: props?.location ?? Cartographic.fromDegrees({ longitude: -75.686694, latitude: 40.065757, height: 0 }), // near Exton pa extents: props?.extents ?? new Range3d(-1000, -1000, -100, 1000, 1000, 100), name: props?.name ?? "blank connection test", }); @@ -321,8 +323,12 @@ export class Surface { this.keyinField.loseFocus(); } - public focusNext() { this.focusNextOrPrevious(true); } - public focusPrevious() { this.focusNextOrPrevious(false); } + public focusNext() { + this.focusNextOrPrevious(true); + } + public focusPrevious() { + this.focusNextOrPrevious(false); + } private focusNextOrPrevious(next: boolean): void { // Focusing a window moves it to the front of the _windows array. So that array is ordered by most-recently- to least-recently-focused. if (next) { @@ -430,8 +436,12 @@ export class Surface { export class CreateWindowTool extends Tool { public static override toolId = "CreateWindow"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return undefined; + } public override async run(props: NamedWindowProps): Promise { DisplayTestApp.surface.createNamedWindow(props); @@ -468,8 +478,12 @@ export class CreateWindowTool extends Tool { } export abstract class WindowIdTool extends Tool { - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public abstract execute(_window: Window): void; @@ -516,8 +530,12 @@ export class CloseWindowTool extends WindowIdTool { } export class ResizeWindowTool extends Tool { public static override toolId = "ResizeWindow"; - public static override get minArgs() { return 2; } - public static override get maxArgs() { return 3; } + public static override get minArgs() { + return 2; + } + public static override get maxArgs() { + return 3; + } public override async run(width: number, height: number, id?: string): Promise { const window = undefined !== id ? Surface.instance.findWindowById(id) : Surface.instance.focusedWindow; @@ -540,8 +558,12 @@ export class ResizeWindowTool extends Tool { export class DockWindowTool extends Tool { public static override toolId = "DockWindow"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(dock: Dock, windowId?: string): Promise { const window = undefined !== windowId ? Surface.instance.findWindowById(windowId) : Surface.instance.focusedWindow; @@ -581,8 +603,12 @@ export class DockWindowTool extends Tool { export class CloneViewportTool extends Tool { public static override toolId = "CloneViewport"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(viewportId?: number): Promise { if (undefined === viewportId) { @@ -609,8 +635,12 @@ export class CloneViewportTool extends Tool { export class OpenIModelTool extends Tool { public static override toolId = "OpenIModel"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(filename?: string): Promise { await Surface.instance.openFile(filename); diff --git a/test-apps/display-test-app/src/frontend/SyncViewportsTool.ts b/test-apps/display-test-app/src/frontend/SyncViewportsTool.ts index fc374d43604a..ed927d6fd76d 100644 --- a/test-apps/display-test-app/src/frontend/SyncViewportsTool.ts +++ b/test-apps/display-test-app/src/frontend/SyncViewportsTool.ts @@ -3,9 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - connectViewportFrusta, connectViewportViews, IModelApp, Tool, Viewport, -} from "@itwin/core-frontend"; +import { connectViewportFrusta, connectViewportViews, IModelApp, Tool, Viewport } from "@itwin/core-frontend"; class State { private readonly _viewportIds: number[]; @@ -26,10 +24,16 @@ class State { /** Connect or disconnect two or more viewports using connectViewports. */ export class SyncViewportsTool extends Tool { public static override toolId = "SyncViewports"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return undefined; + } - protected get syncType(): "frustum" | "view" { return "view"; } + protected get syncType(): "frustum" | "view" { + return "view"; + } private static _state?: State; private static _removeListeners?: VoidFunction; @@ -95,5 +99,7 @@ export class SyncViewportsTool extends Tool { export class SyncViewportFrustaTool extends SyncViewportsTool { public static override toolId = "SyncFrusta"; - protected override get syncType() { return "frustum" as const; } + protected override get syncType() { + return "frustum" as const; + } } diff --git a/test-apps/display-test-app/src/frontend/TerrainDrapeTool.ts b/test-apps/display-test-app/src/frontend/TerrainDrapeTool.ts index c780cf9eb65a..49f2a6623fda 100644 --- a/test-apps/display-test-app/src/frontend/TerrainDrapeTool.ts +++ b/test-apps/display-test-app/src/frontend/TerrainDrapeTool.ts @@ -3,12 +3,42 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ConvexClipPlaneSet, CurvePrimitive, Geometry, GrowableXYZArray, LineString3d, Loop, Matrix3d, Point3d, Polyface, PolyfaceClip, PolyfaceQuery, Range3d, SweepLineStringToFacetsOptions, Transform, Vector3d } from "@itwin/core-geometry"; import { ColorDef, LinePixels } from "@itwin/core-common"; import { - BeButtonEvent, CollectTileStatus, DecorateContext, DisclosedTileTreeSet, EventHandled, GeometryTileTreeReference, GraphicType, HitDetail, IModelApp, - LocateFilterStatus, LocateResponse, PrimitiveTool, Tile, TileGeometryCollector, TileUser, Viewport, + BeButtonEvent, + CollectTileStatus, + DecorateContext, + DisclosedTileTreeSet, + EventHandled, + GeometryTileTreeReference, + GraphicType, + HitDetail, + IModelApp, + LocateFilterStatus, + LocateResponse, + PrimitiveTool, + Tile, + TileGeometryCollector, + TileUser, + Viewport, } from "@itwin/core-frontend"; +import { + ConvexClipPlaneSet, + CurvePrimitive, + Geometry, + GrowableXYZArray, + LineString3d, + Loop, + Matrix3d, + Point3d, + Polyface, + PolyfaceClip, + PolyfaceQuery, + Range3d, + SweepLineStringToFacetsOptions, + Transform, + Vector3d, +} from "@itwin/core-geometry"; /** A TileGeometryCollector that restricts collection to tiles that overlap a line string. */ class DrapeLineStringCollector extends TileGeometryCollector { @@ -31,7 +61,12 @@ class DrapeLineStringCollector extends TileGeometryCollector { clipper.transformInPlace(this._options.transform); for (let i = 0; i < this._points.length - 1 && !inside; i++) - inside = clipper.announceClippedSegmentIntervals(0, 1, this._points.getPoint3dAtUncheckedPointIndex(i), this._points.getPoint3dAtUncheckedPointIndex(i + 1)); + inside = clipper.announceClippedSegmentIntervals( + 0, + 1, + this._points.getPoint3dAtUncheckedPointIndex(i), + this._points.getPoint3dAtUncheckedPointIndex(i + 1), + ); return inside; } @@ -49,7 +84,9 @@ class TerrainDraper implements TileUser { IModelApp.tileAdmin.forgetUser(this); } - public get iModel() { return this.viewport.iModel; } + public get iModel() { + return this.viewport.iModel; + } public onRequestStateChanged() { this.viewport.invalidateDecorations(); @@ -59,14 +96,20 @@ class TerrainDraper implements TileUser { trees.disclose(this.treeRef); } - public drapeLinear(outStrings: CurvePrimitive[], outMeshes: Polyface[], inPoints: GrowableXYZArray, tolerance: number, maxDistance = 1.0E5): "loading" | "complete" { + public drapeLinear( + outStrings: CurvePrimitive[], + outMeshes: Polyface[], + inPoints: GrowableXYZArray, + tolerance: number, + maxDistance = 1.0E5, + ): "loading" | "complete" { const tree = this.treeRef.treeOwner.load(); if (!tree) return "loading"; const range = Range3d.createNull(); range.extendArray(inPoints); - range.extendZOnly(-maxDistance); // Expand - but not so much that we get opposite side of globe. + range.extendZOnly(-maxDistance); // Expand - but not so much that we get opposite side of globe. range.extendZOnly(maxDistance); // when current point is near start point, create a polygon to drape @@ -181,12 +224,14 @@ export class TerrainDrapeTool extends PrimitiveTool { private setupAndPromptForNextAction(): void { this.initLocateElements(undefined === this._draper); - IModelApp.locateManager.options.allowDecorations = true; // So we can select "contextual" reality models. + IModelApp.locateManager.options.allowDecorations = true; // So we can select "contextual" reality models. this.showPrompt(); } private showPrompt(): void { - IModelApp.notifications.outputPromptByKey(`SVTTools:tools.TerrainDrape.Prompts.${undefined === this._draper ? "SelectDrapeRealityModel" : "EnterDrapePoint"}`); + IModelApp.notifications.outputPromptByKey( + `SVTTools:tools.TerrainDrape.Prompts.${undefined === this._draper ? "SelectDrapeRealityModel" : "EnterDrapePoint"}`, + ); } private getGeometryTreeRef(vp: Viewport, modelId: string): GeometryTileTreeReference | undefined { diff --git a/test-apps/display-test-app/src/frontend/TextDecoration.ts b/test-apps/display-test-app/src/frontend/TextDecoration.ts index 269a4d8793ec..dc2216190534 100644 --- a/test-apps/display-test-app/src/frontend/TextDecoration.ts +++ b/test-apps/display-test-app/src/frontend/TextDecoration.ts @@ -3,11 +3,33 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { BaselineShift, ColorDef, FractionRun, GeometryStreamBuilder, IModelTileRpcInterface, LineBreakRun, TextAnnotation, TextAnnotationAnchor, TextBlock, TextBlockJustification, TextRun, TextStyleSettingsProps } from "@itwin/core-common"; -import { DecorateContext, Decorator, GraphicType, IModelApp, IModelConnection, readElementGraphics, RenderGraphicOwner, Tool } from "@itwin/core-frontend"; -import { DtaRpcInterface } from "../common/DtaRpcInterface"; import { Guid, Id64, Id64String } from "@itwin/core-bentley"; +import { + BaselineShift, + ColorDef, + FractionRun, + GeometryStreamBuilder, + IModelTileRpcInterface, + LineBreakRun, + TextAnnotation, + TextAnnotationAnchor, + TextBlock, + TextBlockJustification, + TextRun, + TextStyleSettingsProps, +} from "@itwin/core-common"; +import { + DecorateContext, + Decorator, + GraphicType, + IModelApp, + IModelConnection, + readElementGraphics, + RenderGraphicOwner, + Tool, +} from "@itwin/core-frontend"; import { Point3d, YawPitchRollAngles } from "@itwin/core-geometry"; +import { DtaRpcInterface } from "../common/DtaRpcInterface"; class TextEditor implements Decorator { // Geometry properties @@ -140,7 +162,9 @@ class TextEditor implements Decorator { IModelApp.viewManager.invalidateCachedDecorationsAllViews(this); } - public get useCachedDecorations(): true { return true; } + public get useCachedDecorations(): true { + return true; + } public decorate(context: DecorateContext): void { if (this._graphic) { context.addDecoration(GraphicType.Scene, this._graphic); @@ -152,8 +176,12 @@ const editor = new TextEditor(); export class TextDecorationTool extends Tool { public static override toolId = "AddTextDecoration"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return undefined; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return undefined; + } public override async parseAndRun(...inArgs: string[]): Promise { const vp = IModelApp.viewManager.selectedView; diff --git a/test-apps/display-test-app/src/frontend/ThematicDisplay.ts b/test-apps/display-test-app/src/frontend/ThematicDisplay.ts index 00d503b3aeb8..63f3e39c8885 100644 --- a/test-apps/display-test-app/src/frontend/ThematicDisplay.ts +++ b/test-apps/display-test-app/src/frontend/ThematicDisplay.ts @@ -5,14 +5,32 @@ import { assert } from "@itwin/core-bentley"; import { - CheckBox, ComboBox, ComboBoxEntry, createButton, createCheckBox, createComboBox, createLabeledNumericInput, createSlider, LabeledNumericInput, Slider, -} from "@itwin/frontend-devtools"; -import { Point3d, Range1d } from "@itwin/core-geometry"; -import { - calculateSolarDirectionFromAngles, ColorByName, ColorDef, ThematicDisplay, ThematicDisplayMode, ThematicDisplayProps, - ThematicDisplaySensorProps, ThematicGradientColorScheme, ThematicGradientMode, ThematicGradientTransparencyMode, ViewFlags, + calculateSolarDirectionFromAngles, + ColorByName, + ColorDef, + ThematicDisplay, + ThematicDisplayMode, + ThematicDisplayProps, + ThematicDisplaySensorProps, + ThematicGradientColorScheme, + ThematicGradientMode, + ThematicGradientTransparencyMode, + ViewFlags, } from "@itwin/core-common"; import { Viewport, ViewState, ViewState3d } from "@itwin/core-frontend"; +import { Point3d, Range1d } from "@itwin/core-geometry"; +import { + CheckBox, + ComboBox, + ComboBoxEntry, + createButton, + createCheckBox, + createComboBox, + createLabeledNumericInput, + createSlider, + LabeledNumericInput, + Slider, +} from "@itwin/frontend-devtools"; type Required = { [P in keyof T]-?: T[P]; @@ -228,19 +246,20 @@ export class ThematicDisplayEditor { entries: displayModeEntries, id: "thematic_displayMode", value: 0, - handler: (thing) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const prevDisplayMode = props.displayMode; - const newDisplayMode = props.displayMode = Number.parseInt(thing.value, 10); - if (ThematicDisplayMode.Slope === newDisplayMode) { - props.range = { low: 0.0, high: 90.0 }; - } else if (ThematicDisplayMode.Slope === prevDisplayMode) { - this.updateDefaultRange(); - const range1d = Range1d.fromJSON(defaultSettings.range); - props.range = { low: range1d.low, high: range1d.high }; - } - return props; - }), + handler: (thing) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const prevDisplayMode = props.displayMode; + const newDisplayMode = props.displayMode = Number.parseInt(thing.value, 10); + if (ThematicDisplayMode.Slope === newDisplayMode) { + props.range = { low: 0.0, high: 90.0 }; + } else if (ThematicDisplayMode.Slope === prevDisplayMode) { + this.updateDefaultRange(); + const range1d = Range1d.fromJSON(defaultSettings.range); + props.range = { low: range1d.low, high: range1d.high }; + } + return props; + }), }); this._thematicGradientMode = createComboBox({ @@ -249,11 +268,12 @@ export class ThematicDisplayEditor { entries: ThematicDisplayEditor._gradientModeEntriesForHeight, id: "thematic_gradientMode", value: 0, - handler: (thing) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - props.gradientSettings!.mode = Number.parseInt(thing.value, 10); - return props; - }), + handler: (thing) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + props.gradientSettings!.mode = Number.parseInt(thing.value, 10); + return props; + }), }); const spanStepAndColor = document.createElement("span"); @@ -263,11 +283,12 @@ export class ThematicDisplayEditor { id: "thematic_stepCount", parent: spanStepAndColor, value: 1, - handler: (value) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - props.gradientSettings!.stepCount = value; - return props; - }), + handler: (value) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + props.gradientSettings!.stepCount = value; + return props; + }), min: 2, max: 65536, step: 1, @@ -301,31 +322,33 @@ export class ThematicDisplayEditor { entries: colorSchemeEntries, id: "thematic_colorScheme", value: 0, - handler: (thing) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const mode = Number.parseInt(thing.value, 10); - if (mode < ThematicGradientColorScheme.Custom) { - props.gradientSettings!.colorScheme = mode; - } else { - props.gradientSettings!.colorScheme = ThematicGradientColorScheme.Custom; - const customKeyValues = customColorSchemes[mode - ThematicGradientColorScheme.Custom]; - props.gradientSettings!.customKeys = customKeyValues.map((key) => { - return { value: key[0], color: ColorDef.computeTbgrFromComponents(key[1], key[2], key[3], key[4]) }; - }); - } - return props; - }), + handler: (thing) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const mode = Number.parseInt(thing.value, 10); + if (mode < ThematicGradientColorScheme.Custom) { + props.gradientSettings!.colorScheme = mode; + } else { + props.gradientSettings!.colorScheme = ThematicGradientColorScheme.Custom; + const customKeyValues = customColorSchemes[mode - ThematicGradientColorScheme.Custom]; + props.gradientSettings!.customKeys = customKeyValues.map((key) => { + return { value: key[0], color: ColorDef.computeTbgrFromComponents(key[1], key[2], key[3], key[4]) }; + }); + } + return props; + }), }); this._alphaCheckbox = createCheckBox({ parent: thematicControlsDiv, name: "Multiply gradient alpha", id: "thematic_alpha", - handler: (cb) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - props.gradientSettings!.transparencyMode = ThematicGradientTransparencyMode[cb.checked ? "MultiplySurfaceAndGradient" : "SurfaceOnly"]; - return props; - }), + handler: (cb) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + props.gradientSettings!.transparencyMode = ThematicGradientTransparencyMode[cb.checked ? "MultiplySurfaceAndGradient" : "SurfaceOnly"]; + return props; + }), }); this._alphaCheckbox.div.style.textAlign = "left"; @@ -336,12 +359,13 @@ export class ThematicDisplayEditor { id: "thematic_rangeHigh", parent: spanRange, value: -1.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const oldRange = Range1d.fromJSON(props.range); - props.range = { low: oldRange.low, high: value }; - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const oldRange = Range1d.fromJSON(props.range); + props.range = { low: oldRange.low, high: value }; + return props; + }), min: -100000.0, max: 100000.0, step: 1.0, @@ -354,12 +378,13 @@ export class ThematicDisplayEditor { id: "thematic_rangeLow", parent: spanRange, value: 1.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const oldRange = Range1d.fromJSON(props.range); - props.range = { low: value, high: oldRange.high }; - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const oldRange = Range1d.fromJSON(props.range); + props.range = { low: value, high: oldRange.high }; + return props; + }), min: -100000.0, max: 100000.0, step: 1.0, @@ -376,13 +401,14 @@ export class ThematicDisplayEditor { id: "thematic_axisX", parent: spanAxis, value: defaultAxis.x, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const axis = Point3d.fromJSON(props.axis); - axis.x = value; - props.axis = axis.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const axis = Point3d.fromJSON(props.axis); + axis.x = value; + props.axis = axis.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -395,13 +421,14 @@ export class ThematicDisplayEditor { id: "thematic_axisY", parent: spanAxis, value: defaultAxis.y, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const axis = Point3d.fromJSON(props.axis); - axis.y = value; - props.axis = axis.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const axis = Point3d.fromJSON(props.axis); + axis.y = value; + props.axis = axis.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -414,13 +441,14 @@ export class ThematicDisplayEditor { id: "thematic_axisZ", parent: spanAxis, value: defaultAxis.z, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const axis = Point3d.fromJSON(props.axis); - axis.z = value; - props.axis = axis.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const axis = Point3d.fromJSON(props.axis); + axis.z = value; + props.axis = axis.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -437,11 +465,12 @@ export class ThematicDisplayEditor { step: "0.05", value: "0.0", readout: "right", - handler: (_) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - props.gradientSettings!.colorMix = parseFloat(this._thematicColorMix.slider.value); - return props; - }), + handler: (_) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + props.gradientSettings!.colorMix = parseFloat(this._thematicColorMix.slider.value); + return props; + }), }); this._thematicColorMix.div.style.textAlign = "left"; @@ -452,13 +481,14 @@ export class ThematicDisplayEditor { id: "thematic_sunDirX", parent: spanSunDir, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const sunDir = Point3d.fromJSON(props.sunDirection); - sunDir.x = value; - props.sunDirection = sunDir.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const sunDir = Point3d.fromJSON(props.sunDirection); + sunDir.x = value; + props.sunDirection = sunDir.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -471,13 +501,14 @@ export class ThematicDisplayEditor { id: "thematic_sunDirY", parent: spanSunDir, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const sunDir = Point3d.fromJSON(props.sunDirection); - sunDir.y = value; - props.sunDirection = sunDir.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const sunDir = Point3d.fromJSON(props.sunDirection); + sunDir.y = value; + props.sunDirection = sunDir.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -490,13 +521,14 @@ export class ThematicDisplayEditor { id: "thematic_sunDirZ", parent: spanSunDir, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const sunDir = Point3d.fromJSON(props.sunDirection); - sunDir.z = value; - props.sunDirection = sunDir.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const sunDir = Point3d.fromJSON(props.sunDirection); + sunDir.z = value; + props.sunDirection = sunDir.toJSON(); + return props; + }), min: -1.0, max: 1.0, step: 0.1, @@ -508,11 +540,12 @@ export class ThematicDisplayEditor { id: "thematic_distanceCutoff", parent: thematicControlsDiv, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - props.sensorSettings!.distanceCutoff = value; - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + props.sensorSettings!.distanceCutoff = value; + return props; + }), min: -999999.0, max: 999999.0, step: 0.1, @@ -526,9 +559,10 @@ export class ThematicDisplayEditor { entries: [], id: "thematic_sensor", value: 0, - handler: (_thing) => this.updateThematicDisplay((view): ThematicDisplayProps => { - return this.getThematicSettingsProps(view); - }), + handler: (_thing) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + return this.getThematicSettingsProps(view); + }), }); const spanSensor = document.createElement("span"); @@ -538,14 +572,15 @@ export class ThematicDisplayEditor { id: "thematic_sensorX", parent: spanSensor, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const selectedSensor = this._thematicSensor.select.options.selectedIndex; - const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); - pos.x = value; - props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const selectedSensor = this._thematicSensor.select.options.selectedIndex; + const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); + pos.x = value; + props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); + return props; + }), min: -999999.0, max: 999999.0, step: 0.1, @@ -558,14 +593,15 @@ export class ThematicDisplayEditor { id: "thematic_sensorY", parent: spanSensor, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const selectedSensor = this._thematicSensor.select.options.selectedIndex; - const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); - pos.y = value; - props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const selectedSensor = this._thematicSensor.select.options.selectedIndex; + const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); + pos.y = value; + props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); + return props; + }), min: -999999.0, max: 999999.0, step: 0.1, @@ -578,14 +614,15 @@ export class ThematicDisplayEditor { id: "thematic_sensorZ", parent: spanSensor, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const selectedSensor = this._thematicSensor.select.options.selectedIndex; - const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); - pos.z = value; - props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const selectedSensor = this._thematicSensor.select.options.selectedIndex; + const pos = Point3d.fromJSON(props.sensorSettings!.sensors![selectedSensor].position); + pos.z = value; + props.sensorSettings!.sensors![selectedSensor].position = pos.toJSON(); + return props; + }), min: -999999.0, max: 999999.0, step: 0.1, @@ -597,12 +634,13 @@ export class ThematicDisplayEditor { id: "thematic_sensorValue", parent: thematicControlsDiv, value: 0.0, - handler: (value, _) => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - const selectedSensor = this._thematicSensor.select.options.selectedIndex; - props.sensorSettings!.sensors![selectedSensor].value = value; - return props; - }), + handler: (value, _) => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + const selectedSensor = this._thematicSensor.select.options.selectedIndex; + props.sensorSettings!.sensors![selectedSensor].value = value; + return props; + }), min: 0.0, max: 1.0, step: 0.025, @@ -617,15 +655,16 @@ export class ThematicDisplayEditor { id: "thematic_addSensor", value: "Add Sensor", inline: true, - handler: () => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - if (props.sensorSettings!.sensors !== undefined) { - this._pushNewSensor(props.sensorSettings!.sensors); - this._resetSensorEntries(props.sensorSettings!.sensors.length); - this._thematicSensor.select.selectedIndex = props.sensorSettings!.sensors.length - 1; - } - return props; - }), + handler: () => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + if (props.sensorSettings!.sensors !== undefined) { + this._pushNewSensor(props.sensorSettings!.sensors); + this._resetSensorEntries(props.sensorSettings!.sensors.length); + this._thematicSensor.select.selectedIndex = props.sensorSettings!.sensors.length - 1; + } + return props; + }), }); createButton({ @@ -633,17 +672,18 @@ export class ThematicDisplayEditor { id: "thematic_deleteSensor", value: "Delete Sensor", inline: true, - handler: () => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - if (props.sensorSettings!.sensors !== undefined && props.sensorSettings!.sensors.length > 1) { - const selectedSensorIndex = this._thematicSensor.select.options.selectedIndex; - props.sensorSettings!.sensors.splice(selectedSensorIndex, 1); - if (props.sensorSettings!.sensors === undefined) - props.sensorSettings!.sensors = []; - this._thematicSensor.select.options.remove(selectedSensorIndex); - } - return props; - }), + handler: () => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + if (props.sensorSettings!.sensors !== undefined && props.sensorSettings!.sensors.length > 1) { + const selectedSensorIndex = this._thematicSensor.select.options.selectedIndex; + props.sensorSettings!.sensors.splice(selectedSensorIndex, 1); + if (props.sensorSettings!.sensors === undefined) + props.sensorSettings!.sensors = []; + this._thematicSensor.select.options.remove(selectedSensorIndex); + } + return props; + }), }); createButton({ @@ -651,16 +691,17 @@ export class ThematicDisplayEditor { id: "thematic_createSensorGrid", value: "Create Sensor Grid", inline: true, - handler: () => this.updateThematicDisplay((view): ThematicDisplayProps => { - const props = this.getThematicSettingsProps(view); - if (props.sensorSettings!.sensors !== undefined) { - props.sensorSettings!.sensors = []; - this._createSensorGrid(props.sensorSettings!.sensors); - this._resetSensorEntries(props.sensorSettings!.sensors.length); - this._thematicSensor.select.selectedIndex = props.sensorSettings!.sensors.length - 1; - } - return props; - }), + handler: () => + this.updateThematicDisplay((view): ThematicDisplayProps => { + const props = this.getThematicSettingsProps(view); + if (props.sensorSettings!.sensors !== undefined) { + props.sensorSettings!.sensors = []; + this._createSensorGrid(props.sensorSettings!.sensors); + this._resetSensorEntries(props.sensorSettings!.sensors.length); + this._thematicSensor.select.selectedIndex = props.sensorSettings!.sensors.length - 1; + } + return props; + }), }); sensorsControlsDiv.style.textAlign = "center"; diff --git a/test-apps/display-test-app/src/frontend/TileContentTool.ts b/test-apps/display-test-app/src/frontend/TileContentTool.ts index 9c95843dcc3a..3c5342f33f62 100644 --- a/test-apps/display-test-app/src/frontend/TileContentTool.ts +++ b/test-apps/display-test-app/src/frontend/TileContentTool.ts @@ -5,15 +5,17 @@ import { assert, ByteStream, Guid } from "@itwin/core-bentley"; import { PersistentGraphicsRequestProps } from "@itwin/core-common"; -import { - ImdlReader, IModelApp, IModelConnection, IModelTileTree, Tool, -} from "@itwin/core-frontend"; +import { ImdlReader, IModelApp, IModelConnection, IModelTileTree, Tool } from "@itwin/core-frontend"; import { parseArgs } from "@itwin/frontend-devtools"; export class GenerateTileContentTool extends Tool { public static override toolId = "GenerateTileContent"; - public static override get minArgs() { return 2; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 2; + } + public static override get maxArgs() { + return 2; + } public override async run(args?: { tree: IModelTileTree, contentId: string }) { if (!args) @@ -25,7 +27,11 @@ export class GenerateTileContentTool extends Tool { const stream = ByteStream.fromUint8Array(bytes); const { iModel, modelId, is3d, containsTransformNodes } = tree; const reader = ImdlReader.create({ - stream, iModel, modelId, is3d, containsTransformNodes, + stream, + iModel, + modelId, + is3d, + containsTransformNodes, system: IModelApp.renderSystem, type: tree.batchType, loadEdges: false !== tree.edgeOptions, @@ -66,8 +72,12 @@ export class GenerateTileContentTool extends Tool { export class GenerateElementGraphicsTool extends Tool { public static override toolId = "GenerateElementGraphics"; - public static override get minArgs() { return 1; } - public static override get maxArgs() { return 2; } + public static override get minArgs() { + return 1; + } + public static override get maxArgs() { + return 2; + } public override async run(props?: PersistentGraphicsRequestProps, iModel?: IModelConnection): Promise { if (!props || !iModel) diff --git a/test-apps/display-test-app/src/frontend/TileSizeRecorder.ts b/test-apps/display-test-app/src/frontend/TileSizeRecorder.ts index 1d5ff583d8ce..6ed0192020cf 100644 --- a/test-apps/display-test-app/src/frontend/TileSizeRecorder.ts +++ b/test-apps/display-test-app/src/frontend/TileSizeRecorder.ts @@ -75,8 +75,12 @@ const generateTileContent = TileAdmin.prototype.generateTileContent; */ export class RecordTileSizesTool extends Tool { public static override toolId = "RecordTileSizes"; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async parseAndRun(...args: string[]): Promise { const enable = parseToggle(args[0]); @@ -94,7 +98,9 @@ export class RecordTileSizesTool extends Tool { if (enable) { recorder = new TileSizeRecorder(); - IModelApp.tileAdmin.generateTileContent = async (tile: { iModelTree: IModelTileTree, contentId: string, request?: { isCanceled: boolean } }): Promise => { + IModelApp.tileAdmin.generateTileContent = async ( + tile: { iModelTree: IModelTileTree, contentId: string, request?: { isCanceled: boolean } }, + ): Promise => { const content = await generateTileContent.bind(IModelApp.tileAdmin, tile)(); recorder?.record({ contentId: tile.contentId, modelId: tile.iModelTree.modelId }, tile.iModelTree, content.byteLength); return content; diff --git a/test-apps/display-test-app/src/frontend/TiledGraphics.ts b/test-apps/display-test-app/src/frontend/TiledGraphics.ts index 59884d0deeef..5e7417c5d18f 100644 --- a/test-apps/display-test-app/src/frontend/TiledGraphics.ts +++ b/test-apps/display-test-app/src/frontend/TiledGraphics.ts @@ -5,10 +5,20 @@ import { BriefcaseConnection, - FeatureSymbology, HitDetail, IModelApp, IModelConnection, TiledGraphicsProvider, TileTree, TileTreeReference, Tool, ViewCreator3d, Viewport, ViewState, + FeatureSymbology, + HitDetail, + IModelApp, + IModelConnection, + TiledGraphicsProvider, + TileTree, + TileTreeReference, + Tool, + ViewCreator3d, + Viewport, + ViewState, } from "@itwin/core-frontend"; -import { DisplayTestApp } from "./App"; import { Transform } from "@itwin/core-geometry"; +import { DisplayTestApp } from "./App"; class Reference extends TileTreeReference { private readonly _ref: TileTreeReference; @@ -21,13 +31,25 @@ class Reference extends TileTreeReference { this._provider = provider; } - public override get castsShadows() { return this._ref.castsShadows; } - public override get treeOwner() { return this._ref.treeOwner; } - public override async getToolTip(hit: HitDetail) { return this._ref.getToolTip(hit); } - public override canSupplyToolTip(hit: HitDetail) { return this._ref.canSupplyToolTip(hit); } - public override async getToolTipPromise(hit: HitDetail) { return this._ref.getToolTipPromise(hit); } + public override get castsShadows() { + return this._ref.castsShadows; + } + public override get treeOwner() { + return this._ref.treeOwner; + } + public override async getToolTip(hit: HitDetail) { + return this._ref.getToolTip(hit); + } + public override canSupplyToolTip(hit: HitDetail) { + return this._ref.canSupplyToolTip(hit); + } + public override async getToolTipPromise(hit: HitDetail) { + return this._ref.getToolTipPromise(hit); + } - protected override getSymbologyOverrides() { return this._provider.ovrs; } + protected override getSymbologyOverrides() { + return this._provider.ovrs; + } protected override computeTransform(tree: TileTree): Transform { return this._transform ?? (this._transform = this._provider.computeTransform(tree)); @@ -45,7 +67,9 @@ class Provider implements TiledGraphicsProvider { public readonly toViewport: Transform; private readonly _refs: Reference[]; - public get iModel() { return this.view.iModel; } + public get iModel() { + return this.view.iModel; + } private constructor(view: ViewState, vp: Viewport, transform: Transform) { this.view = view; @@ -81,7 +105,9 @@ class Provider implements TiledGraphicsProvider { } } -function computeTransformFromSecondaryIModel(args: { primary: IModelConnection, secondary: IModelConnection, tileTreeToWorld?: Transform }): Transform { +function computeTransformFromSecondaryIModel( + args: { primary: IModelConnection, secondary: IModelConnection, tileTreeToWorld?: Transform }, +): Transform { const { primary, secondary } = args; const tileTreeToWorld = args.tileTreeToWorld ?? Transform.createIdentity(); @@ -113,7 +139,7 @@ export async function toggleExternalTiledGraphicsProvider(vp: Viewport): Promise let iModel; try { - iModel = await BriefcaseConnection.openFile( { fileName, key: fileName }); + iModel = await BriefcaseConnection.openFile({ fileName, key: fileName }); const provider = await Provider.create(iModel, vp); providersByViewport.set(vp, provider); vp.addTiledGraphicsProvider(provider); diff --git a/test-apps/display-test-app/src/frontend/TimePointComparison.ts b/test-apps/display-test-app/src/frontend/TimePointComparison.ts index 810abb8ec65f..9c9033f8bcee 100644 --- a/test-apps/display-test-app/src/frontend/TimePointComparison.ts +++ b/test-apps/display-test-app/src/frontend/TimePointComparison.ts @@ -3,13 +3,18 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Point3d, Transform, Vector3d, -} from "@itwin/core-geometry"; import { AccuDrawHintBuilder, - FeatureSymbology, GraphicBranch, IModelApp, RenderClipVolume, SceneContext, ScreenViewport, TileTreeReference, Tool, + FeatureSymbology, + GraphicBranch, + IModelApp, + RenderClipVolume, + SceneContext, + ScreenViewport, + TileTreeReference, + Tool, } from "@itwin/core-frontend"; +import { ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Point3d, Transform, Vector3d } from "@itwin/core-geometry"; /** Prototype for SYNCHRO feature. Split the viewport down the middle. Left-hand side remains frozen at current time point. Right-hand side updates when time point changes. */ class TimePointComparison { diff --git a/test-apps/display-test-app/src/frontend/Timeline.ts b/test-apps/display-test-app/src/frontend/Timeline.ts index 419606fd0b49..14832fe70867 100644 --- a/test-apps/display-test-app/src/frontend/Timeline.ts +++ b/test-apps/display-test-app/src/frontend/Timeline.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Point3d, Range1d } from "@itwin/core-geometry"; import { calculateSunriseOrSunset, Cartographic } from "@itwin/core-common"; import { Viewport } from "@itwin/core-frontend"; +import { Point3d, Range1d } from "@itwin/core-geometry"; import { createToolButton, ToolBarDropDown } from "./ToolBar"; interface TimelineProvider { @@ -48,7 +48,7 @@ class SolarTimelineProvider { const projectCenter = Point3d.createAdd2Scaled(projectExtents.low, .5, projectExtents.high, .5); cartoCenter = vp.iModel.spatialToCartographicFromEcef(projectCenter); } else { - cartoCenter = Cartographic.fromDegrees({longitude: -75.17035, latitude: 39.954927, height: 0.0}); + cartoCenter = Cartographic.fromDegrees({ longitude: -75.17035, latitude: 39.954927, height: 0.0 }); } const today = new Date(Date.now()); @@ -105,7 +105,7 @@ class NoOpTimelineProvider { return "No animation available for this view."; } - public update(_time: number, _vp: Viewport): void { } + public update(_time: number, _vp: Viewport): void {} public getCurrentTime(_vp: Viewport): number { return this.duration.low; diff --git a/test-apps/display-test-app/src/frontend/ToolBar.ts b/test-apps/display-test-app/src/frontend/ToolBar.ts index 8e5953edbc9f..46bfc895db2d 100644 --- a/test-apps/display-test-app/src/frontend/ToolBar.ts +++ b/test-apps/display-test-app/src/frontend/ToolBar.ts @@ -50,11 +50,13 @@ export function createImageButton(props: ImageButtonProps) { export abstract class ToolBarDropDown { protected _isPinned: boolean = false; - public get onViewChanged(): Promise | undefined { return undefined; } + public get onViewChanged(): Promise | undefined { + return undefined; + } protected abstract _open(): void; protected abstract _close(): void; - public dispose(): void { } + public dispose(): void {} public abstract get isOpen(): boolean; diff --git a/test-apps/display-test-app/src/frontend/UiManager.ts b/test-apps/display-test-app/src/frontend/UiManager.ts index 2fb6f6415250..c56fb144ed3d 100644 --- a/test-apps/display-test-app/src/frontend/UiManager.ts +++ b/test-apps/display-test-app/src/frontend/UiManager.ts @@ -3,9 +3,6 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { - XAndY, -} from "@itwin/core-geometry"; import { AbstractToolbarProps, ActionButton, @@ -15,14 +12,10 @@ import { RelativePosition, UiAdmin, } from "@itwin/appui-abstract"; -import { - IModelApp, -} from "@itwin/core-frontend"; -import { - Window, - WindowProps, -} from "./Window"; +import { IModelApp } from "@itwin/core-frontend"; +import { XAndY } from "@itwin/core-geometry"; import { Surface } from "./Surface"; +import { Window, WindowProps } from "./Window"; interface ToolbarWindowProps extends WindowProps { items: CommonToolbarItem[]; @@ -30,8 +23,12 @@ interface ToolbarWindowProps extends WindowProps { } class ToolbarWindow extends Window { - public override get isCloseable() { return false; } - public get windowId() { return "toolbar"; } + public override get isCloseable() { + return false; + } + public get windowId() { + return "toolbar"; + } public constructor(surface: Surface, props: ToolbarWindowProps) { super(surface, props); @@ -81,7 +78,15 @@ export class UiManager extends UiAdmin { return super.cursorPosition; } - public override showToolbar(tbProps: AbstractToolbarProps, location: XAndY, offset: XAndY, onItemExecuted: OnItemExecutedFunc, _onCancel: OnCancelFunc, _relPos?: RelativePosition, _elem?: HTMLElement): boolean { + public override showToolbar( + tbProps: AbstractToolbarProps, + location: XAndY, + offset: XAndY, + onItemExecuted: OnItemExecutedFunc, + _onCancel: OnCancelFunc, + _relPos?: RelativePosition, + _elem?: HTMLElement, + ): boolean { const surface = Surface.instance; if (undefined !== surface.findWindowById("toolbar")) return false; diff --git a/test-apps/display-test-app/src/frontend/ViewAttributes.ts b/test-apps/display-test-app/src/frontend/ViewAttributes.ts index fd0a51262f12..1a6c79fbe4b5 100644 --- a/test-apps/display-test-app/src/frontend/ViewAttributes.ts +++ b/test-apps/display-test-app/src/frontend/ViewAttributes.ts @@ -4,13 +4,37 @@ *--------------------------------------------------------------------------------------------*/ import { Id64String } from "@itwin/core-bentley"; import { - CheckBox, ComboBox, ComboBoxEntry, createCheckBox, createColorInput, createComboBox, createNestedMenu, createNumericInput, createSlider, Slider, -} from "@itwin/frontend-devtools"; -import { - BackgroundMapProps, BackgroundMapProviderName, BackgroundMapProviderProps, BackgroundMapType, BaseMapLayerSettings, CesiumTerrainAssetId, ColorDef, DisplayStyle3dSettingsProps, - GlobeMode, HiddenLine, LinePixels, MonochromeMode, RenderMode, TerrainProps, ThematicDisplayMode, ThematicGradientColorScheme, ThematicGradientMode, + BackgroundMapProps, + BackgroundMapProviderName, + BackgroundMapProviderProps, + BackgroundMapType, + BaseMapLayerSettings, + CesiumTerrainAssetId, + ColorDef, + DisplayStyle3dSettingsProps, + GlobeMode, + HiddenLine, + LinePixels, + MonochromeMode, + RenderMode, + TerrainProps, + ThematicDisplayMode, + ThematicGradientColorScheme, + ThematicGradientMode, } from "@itwin/core-common"; import { DisplayStyle2dState, DisplayStyle3dState, DisplayStyleState, IModelApp, Viewport, ViewState, ViewState3d } from "@itwin/core-frontend"; +import { + CheckBox, + ComboBox, + ComboBoxEntry, + createCheckBox, + createColorInput, + createComboBox, + createNestedMenu, + createNumericInput, + createSlider, + Slider, +} from "@itwin/frontend-devtools"; import { AmbientOcclusionEditor } from "./AmbientOcclusion"; import { EnvironmentEditor } from "./EnvironmentEditor"; import { Settings } from "./FeatureOverrides"; @@ -21,7 +45,22 @@ import { ToolBarDropDown } from "./ToolBar"; type UpdateAttribute = (view: ViewState) => void; -type ViewFlag = "acsTriad" | "grid" | "fill" | "materials" | "textures" | "visibleEdges" | "hiddenEdges" | "monochrome" | "constructions" | "transparency" | "weights" | "styles" | "clipVolume" | "forceSurfaceDiscard" | "whiteOnWhiteReversal"; +type ViewFlag = + | "acsTriad" + | "grid" + | "fill" + | "materials" + | "textures" + | "visibleEdges" + | "hiddenEdges" + | "monochrome" + | "constructions" + | "transparency" + | "weights" + | "styles" + | "clipVolume" + | "forceSurfaceDiscard" + | "whiteOnWhiteReversal"; interface RenderingStyle extends DisplayStyle3dSettingsProps { name: string; @@ -46,10 +85,17 @@ const renderingStyles: RenderingStyle[] = [{ name: "Default", environment: { sky: { - display: true, groundColor: 8228728, zenithColor: 16741686, nadirColor: 3880, skyColor: 16764303, + display: true, + groundColor: 8228728, + zenithColor: 16741686, + nadirColor: 3880, + skyColor: 16764303, }, ground: { - display: false, elevation: -0.01, aboveColor: 32768, belowColor: 1262987, + display: false, + elevation: -0.01, + aboveColor: 32768, + belowColor: 1262987, }, }, viewflags: renderingStyleViewFlags, @@ -88,10 +134,17 @@ const renderingStyles: RenderingStyle[] = [{ name: "Sun-dappled", environment: { sky: { - display: true, groundColor: 8228728, zenithColor: 16741686, nadirColor: 3880, skyColor: 16764303, + display: true, + groundColor: 8228728, + zenithColor: 16741686, + nadirColor: 3880, + skyColor: 16764303, }, ground: { - display: false, elevation: -0.01, aboveColor: 32768, belowColor: 1262987, + display: false, + elevation: -0.01, + aboveColor: 32768, + belowColor: 1262987, }, }, viewflags: { ...renderingStyleViewFlags, shadows: true }, @@ -485,7 +538,9 @@ export class ViewAttributes { this._updates.push((view) => thematic.update(view)); } - private getBackgroundMap(view: ViewState) { return view.displayStyle.settings.backgroundMap; } + private getBackgroundMap(view: ViewState) { + return view.displayStyle.settings.backgroundMap; + } private addBackgroundMapOrTerrain(): void { const isMapSupported = (view: ViewState) => view.is3d() && view.iModel.isGeoLocated; @@ -552,8 +607,11 @@ export class ViewAttributes { }; const terrainCheckbox = this.addCheckbox("Terrain", enableTerrain, backgroundSettingsDiv).checkbox; - const transCheckbox = this.addCheckbox("Transparency", (enabled: boolean) => this.updateBackgroundMap({ transparency: enabled ? 0.5 : false }), backgroundSettingsDiv).checkbox; - const locatable = this.addCheckbox("Locatable", (enabled) => this.updateBackgroundMap({ nonLocatable: !enabled }), backgroundSettingsDiv).checkbox; + const transCheckbox = + this.addCheckbox("Transparency", (enabled: boolean) => this.updateBackgroundMap({ transparency: enabled ? 0.5 : false }), backgroundSettingsDiv) + .checkbox; + const locatable = + this.addCheckbox("Locatable", (enabled) => this.updateBackgroundMap({ nonLocatable: !enabled }), backgroundSettingsDiv).checkbox; backgroundSettingsDiv.appendChild(document.createElement("hr")); backgroundSettingsDiv.appendChild(mapSettings); backgroundSettingsDiv.appendChild(terrainSettings); @@ -608,7 +666,8 @@ export class ViewAttributes { groundBiasDiv.style.textAlign = "left"; mapSettingsDiv.appendChild(groundBiasDiv); - const depthCheckbox = this.addCheckbox("Depth", (enabled: boolean) => this.updateBackgroundMap({ useDepthBuffer: enabled }), mapSettingsDiv).checkbox; + const depthCheckbox = + this.addCheckbox("Depth", (enabled: boolean) => this.updateBackgroundMap({ useDepthBuffer: enabled }), mapSettingsDiv).checkbox; this._updates.push((view) => { const map = this.getBackgroundMap(view); @@ -642,7 +701,9 @@ export class ViewAttributes { { name: "Sea Level (Geoid)", value: "1" }, { name: "Ground", value: "2" }, ], - handler: (select) => { updateTerrainSettings({ heightOriginMode: parseInt(select.value, 10) }); }, + handler: (select) => { + updateTerrainSettings({ heightOriginMode: parseInt(select.value, 10) }); + }, }).select; const heightOriginDiv = document.createElement("div"); @@ -678,12 +739,14 @@ export class ViewAttributes { exaggerationDiv.style.textAlign = "left"; settingsDiv.appendChild(exaggerationDiv); - const bingCheckbox = this.addCheckbox("Use Bing elevation", + const bingCheckbox = this.addCheckbox( + "Use Bing elevation", (enabled: boolean) => updateTerrainSettings({ providerName: enabled ? "DtaBingTerrain" : "CesiumWorldTerrain" }), settingsDiv, ).checkbox; - const bathyCheckbox = this.addCheckbox("Bathymetry", + const bathyCheckbox = this.addCheckbox( + "Bathymetry", (enabled: boolean) => updateTerrainSettings({ dataSource: enabled ? CesiumTerrainAssetId.Bathymetry : CesiumTerrainAssetId.Default }), settingsDiv, ).checkbox; @@ -732,7 +795,9 @@ export class ViewAttributes { return `viewAttributesPanel_${this._id}`; } - private get _edgeSettings() { return (this._vp.view as ViewState3d).getDisplayStyle3d().settings.hiddenLineSettings; } + private get _edgeSettings() { + return (this._vp.view as ViewState3d).getDisplayStyle3d().settings.hiddenLineSettings; + } private overrideEdgeSettings(props: HiddenLine.SettingsProps) { (this._vp.view as ViewState3d).getDisplayStyle3d().settings.hiddenLineSettings = this._edgeSettings.override(props); this.sync(); @@ -825,7 +890,8 @@ export class ViewAttributes { div.hidden = forHiddenEdges ? !this._vp.view.viewFlags.hiddenEdges : !this._vp.view.viewFlags.visibleEdges; const getSettings = () => forHiddenEdges ? this._edgeSettings.hidden : this._edgeSettings.visible; - const overrideSettings = (newSettings: HiddenLine.Style) => this.overrideEdgeSettings(forHiddenEdges ? { hidden: newSettings.toJSON() } : { visible: newSettings.toJSON() }); + const overrideSettings = (newSettings: HiddenLine.Style) => + this.overrideEdgeSettings(forHiddenEdges ? { hidden: newSettings.toJSON() } : { visible: newSettings.toJSON() }); // Color override (visible only) let colorCb: HTMLInputElement | undefined; @@ -851,7 +917,10 @@ export class ViewAttributes { handler: (value: string) => overrideSettings(getSettings().overrideColor(ColorDef.create(value))), }).input; - colorCb.addEventListener("click", () => overrideSettings(getSettings().overrideColor(colorCb!.checked ? ColorDef.create(colorInput!.value) : undefined))); + colorCb.addEventListener( + "click", + () => overrideSettings(getSettings().overrideColor(colorCb!.checked ? ColorDef.create(colorInput!.value) : undefined)), + ); } // Width override @@ -974,7 +1043,9 @@ export class ViewAttributesPanel extends ToolBarDropDown { return this.populate(); } - public get isOpen() { return undefined !== this._attributes; } + public get isOpen() { + return undefined !== this._attributes; + } protected _open(): void { this._attributes = new ViewAttributes(this._vp, this._parent, this._disableEdges); const loadingComboBox = createComboBox({ diff --git a/test-apps/display-test-app/src/frontend/ViewClipByElementGeometryTool.ts b/test-apps/display-test-app/src/frontend/ViewClipByElementGeometryTool.ts index 887c1def0baf..17dd9212e7ce 100644 --- a/test-apps/display-test-app/src/frontend/ViewClipByElementGeometryTool.ts +++ b/test-apps/display-test-app/src/frontend/ViewClipByElementGeometryTool.ts @@ -2,18 +2,19 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ElementMeshOptions, readElementMeshes } from "@itwin/core-common"; +import { BeButtonEvent, CoordinateLockOverrides, EventHandled, IModelApp, LocateResponse, ViewClipTool, Viewport } from "@itwin/core-frontend"; import { - ClipPrimitive, ClipVector, ConvexClipPlaneSet, IndexedPolyface, Point3d, PolyfaceBuilder, PolyfaceQuery, UnionOfConvexClipPlaneSets, + ClipPrimitive, + ClipVector, + ConvexClipPlaneSet, + IndexedPolyface, + Point3d, + PolyfaceBuilder, + PolyfaceQuery, + UnionOfConvexClipPlaneSets, } from "@itwin/core-geometry"; -import { - ElementMeshOptions, readElementMeshes, -} from "@itwin/core-common"; -import { - BeButtonEvent, CoordinateLockOverrides, EventHandled, IModelApp, LocateResponse, ViewClipTool, Viewport, -} from "@itwin/core-frontend"; -import { - ConvexMeshDecomposition, Options as DecompositionOptions, -} from "vhacd-js"; +import { ConvexMeshDecomposition, Options as DecompositionOptions } from "vhacd-js"; /** Settings that control the behavior of the ViewClipByElementGeometryTool. */ interface Settings extends ElementMeshOptions { diff --git a/test-apps/display-test-app/src/frontend/ViewPicker.ts b/test-apps/display-test-app/src/frontend/ViewPicker.ts index 6409b4005915..ac42063014df 100644 --- a/test-apps/display-test-app/src/frontend/ViewPicker.ts +++ b/test-apps/display-test-app/src/frontend/ViewPicker.ts @@ -29,7 +29,9 @@ export class ViewList extends SortedArray { }); } - public get defaultViewId(): Id64String { return this._defaultViewId; } + public get defaultViewId(): Id64String { + return this._defaultViewId; + } public async getView(id: Id64String, iModel: IModelConnection): Promise { let view = this._views.get(id); @@ -145,7 +147,9 @@ export class ViewPicker { private readonly _select: HTMLSelectElement; public readonly onSelectedViewChanged = new BeEvent<(viewId: Id64String) => void>(); - public get element(): HTMLElement { return this._select; } + public get element(): HTMLElement { + return this._select; + } public constructor(parent: HTMLElement, views: ViewList) { this._select = document.createElement("select"); diff --git a/test-apps/display-test-app/src/frontend/Viewer.ts b/test-apps/display-test-app/src/frontend/Viewer.ts index 6ec4203e7502..c30b379becd3 100644 --- a/test-apps/display-test-app/src/frontend/Viewer.ts +++ b/test-apps/display-test-app/src/frontend/Viewer.ts @@ -3,20 +3,34 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { Id64String } from "@itwin/core-bentley"; -import { ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Vector3d } from "@itwin/core-geometry"; import { ModelClipGroup, ModelClipGroups } from "@itwin/core-common"; import { - IModelApp, IModelConnection, MarginOptions, MarginPercent, NotifyMessageDetails, openImageDataUrlInNewWindow, OutputMessagePriority, - PaddingPercent, ScreenViewport, Tool, Viewport, ViewState, + IModelApp, + IModelConnection, + MarginOptions, + MarginPercent, + NotifyMessageDetails, + openImageDataUrlInNewWindow, + OutputMessagePriority, + PaddingPercent, + ScreenViewport, + Tool, + Viewport, + ViewState, } from "@itwin/core-frontend"; -import { parseArgs } from "@itwin/frontend-devtools"; +import { ClipPlane, ClipPrimitive, ClipVector, ConvexClipPlaneSet, Vector3d } from "@itwin/core-geometry"; import { MarkupApp, MarkupData } from "@itwin/core-markup"; +import { parseArgs } from "@itwin/frontend-devtools"; +import { CameraPathsMenu } from "./CameraPaths"; import { ClassificationsPanel } from "./ClassificationsPanel"; +import { ContoursPanel } from "./Contours"; import { DebugWindow } from "./DebugWindow"; import { FeatureOverridesPanel } from "./FeatureOverrides"; +import { HubPicker } from "./HubPicker"; import { CategoryPicker, ModelPicker } from "./IdPicker"; +import { openIModel, OpenIModelProps } from "./openIModel"; +import { RealityModelSettingsPanel } from "./RealityModelDisplaySettingsWidget"; import { SavedViewPicker } from "./SavedViews"; -import { CameraPathsMenu } from "./CameraPaths"; import { SectionsPanel } from "./SectionTools"; import { StandardRotations } from "./StandardRotations"; import { Surface } from "./Surface"; @@ -26,10 +40,6 @@ import { createImageButton, createToolButton, ToolBar } from "./ToolBar"; import { ViewAttributesPanel } from "./ViewAttributes"; import { ViewList, ViewPicker } from "./ViewPicker"; import { Window } from "./Window"; -import { openIModel, OpenIModelProps } from "./openIModel"; -import { HubPicker } from "./HubPicker"; -import { RealityModelSettingsPanel } from "./RealityModelDisplaySettingsWidget"; -import { ContoursPanel } from "./Contours"; // cspell:ignore savedata topdiv savedview viewtop @@ -44,7 +54,9 @@ export class ZoomToSelectedElementsTool extends Tool { private _padding?: PaddingPercent | number; public static override toolId = "ZoomToSelectedElements"; - public static override get maxArgs() { return 4; } + public static override get maxArgs() { + return 4; + } public override async run(): Promise { const vp = IModelApp.viewManager.selectedView; @@ -118,8 +130,12 @@ export class ModelClipTool extends Tool { export class MarkupTool extends Tool { public static override toolId = "Markup"; public static savedData?: MarkupData; - public static override get minArgs() { return 0; } - public static override get maxArgs() { return 1; } + public static override get minArgs() { + return 0; + } + public static override get maxArgs() { + return 1; + } public override async run(wantSavedData: boolean): Promise { const vp = IModelApp.viewManager.selectedView; @@ -128,7 +144,8 @@ export class MarkupTool extends Tool { if (MarkupApp.isActive) { // NOTE: Because we don't have separate START and STOP buttons in the test app, exit markup mode only when the Markup Select tool is active, otherwise start the Markup Select tool... - const startMarkupSelect = IModelApp.toolAdmin.defaultToolId === MarkupApp.markupSelectToolId && (undefined === IModelApp.toolAdmin.activeTool || MarkupApp.markupSelectToolId !== IModelApp.toolAdmin.activeTool.toolId); + const startMarkupSelect = IModelApp.toolAdmin.defaultToolId === MarkupApp.markupSelectToolId && + (undefined === IModelApp.toolAdmin.activeTool || MarkupApp.markupSelectToolId !== IModelApp.toolAdmin.activeTool.toolId); if (startMarkupSelect) { await IModelApp.toolAdmin.startDefaultTool(); return true; @@ -139,7 +156,7 @@ export class MarkupTool extends Tool { MarkupTool.savedData = markupData; if (undefined !== markupData.image) openImageDataUrlInNewWindow(markupData.image, "Markup"); - }).catch((_) => { }); + }).catch((_) => {}); } else { MarkupApp.props.active.element.stroke = "white"; // as an example, set default color for elements MarkupApp.markupSelectToolId = "Markup.TestSelect"; // as an example override the default markup select tool to launch redline tools using key events @@ -562,7 +579,9 @@ export class Viewer extends Window { this.container.classList.remove("viewport-selected"); } - public get windowId(): string { return this.viewport.viewportId.toString(); } + public get windowId(): string { + return this.viewport.viewportId.toString(); + } public override onClosing(): void { this.toolBar.dispose(); diff --git a/test-apps/display-test-app/src/frontend/Window.ts b/test-apps/display-test-app/src/frontend/Window.ts index 1f5078b33321..06ff59b65e6b 100644 --- a/test-apps/display-test-app/src/frontend/Window.ts +++ b/test-apps/display-test-app/src/frontend/Window.ts @@ -258,7 +258,7 @@ class WindowHeader { // assure the window above of the surface boarder if (windowBottom >= surfaceBottom) - windowTop = (surfaceBottom - windowHeight); + windowTop = surfaceBottom - windowHeight; if (windowTop < surfaceTop) windowTop = surfaceTop; style.top = `${windowTop}px`; @@ -267,7 +267,7 @@ class WindowHeader { // assure the window left of the surface boarder if (windowRight >= surfaceRight) - windowLeft = (surfaceRight - windowWidth); + windowLeft = surfaceRight - windowWidth; if (windowLeft < surfaceLeft) windowLeft = surfaceLeft; style.left = `${windowLeft}px`; @@ -299,8 +299,12 @@ class WindowHeader { this.applyDock(); } - public get isDocked() { return undefined !== this._dockState; } - public invalidateDock() { this._dockState = undefined; } + public get isDocked() { + return undefined !== this._dockState; + } + public invalidateDock() { + this._dockState = undefined; + } public resizeContent(w: number, h: number): void { // ###TODO kludge for 2px borders... @@ -380,7 +384,9 @@ export abstract class Window { } // Do not set directly - use Surface.togglePin(window) - public get isPinned(): boolean { return this._isPinned; } + public get isPinned(): boolean { + return this._isPinned; + } public set isPinned(value: boolean) { this._header.markAsPinned(value); this._isPinned = value; @@ -394,14 +400,30 @@ export abstract class Window { this.surface.focus(this); } - public get isDocked() { return this._header.isDocked; } - public dock(dock: Dock) { this._header.dock(dock); } - public updateDock() { this._header.applyDock(); } - public undock() { this._header.undock(); } - public ensureInSurface() { this._header.ensureInSurface(); } - public invalidateDock() { this._header.invalidateDock(); } - public addDock(dock: Dock) { this._header.addDock(dock); } - public updateUi(): void { this._header.hideCloseWidget(!this.isCloseable); } + public get isDocked() { + return this._header.isDocked; + } + public dock(dock: Dock) { + this._header.dock(dock); + } + public updateDock() { + this._header.applyDock(); + } + public undock() { + this._header.undock(); + } + public ensureInSurface() { + this._header.ensureInSurface(); + } + public invalidateDock() { + this._header.invalidateDock(); + } + public addDock(dock: Dock) { + this._header.addDock(dock); + } + public updateUi(): void { + this._header.hideCloseWidget(!this.isCloseable); + } public onFocus(): void { this.container.classList.add("window-focused"); @@ -413,10 +435,14 @@ export abstract class Window { this._header.element.classList.remove("window-header-focused"); } - public onClosing(): void { } - public onClosed(): void { } - public get isCloseable(): boolean { return true; } - public get isResizable(): boolean { return true; } + public onClosing(): void {} + public onClosed(): void {} + public get isCloseable(): boolean { + return true; + } + public get isResizable(): boolean { + return true; + } public resizeContent(w: number, h: number): void { this._header.resizeContent(w, h); @@ -441,5 +467,7 @@ export class NamedWindow extends Window { this._header.setTitle(this.windowId); } - public get windowId() { return this._windowId; } + public get windowId() { + return this._windowId; + } } diff --git a/test-apps/display-test-app/src/frontend/signIn.ts b/test-apps/display-test-app/src/frontend/signIn.ts index a9f7ce687d47..f3f2167fb823 100644 --- a/test-apps/display-test-app/src/frontend/signIn.ts +++ b/test-apps/display-test-app/src/frontend/signIn.ts @@ -2,17 +2,20 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; -import { IModelApp } from "@itwin/core-frontend"; import { BrowserAuthorizationClient } from "@itwin/browser-authorization"; import { AccessToken, ProcessDetector } from "@itwin/core-bentley"; +import { IModelApp } from "@itwin/core-frontend"; +import { ElectronRendererAuthorization } from "@itwin/electron-authorization/Renderer"; import { getConfigurationString } from "./DisplayTestApp"; // Wraps the signIn process // @return Promise that resolves to true after signIn is complete export async function signIn(): Promise { const existingAuthClient = IModelApp.authorizationClient; - if (undefined !== existingAuthClient && (existingAuthClient instanceof BrowserAuthorizationClient || existingAuthClient instanceof ElectronRendererAuthorization)) { + if ( + undefined !== existingAuthClient && + (existingAuthClient instanceof BrowserAuthorizationClient || existingAuthClient instanceof ElectronRendererAuthorization) + ) { if (existingAuthClient.isAuthorized) { return (await existingAuthClient.getAccessToken()) !== undefined; } @@ -45,7 +48,7 @@ export async function signIn(): Promise { }); try { await authClient.signInSilent(); - } catch (err) { } + } catch (err) {} } if (typeof authClient === "undefined") { @@ -64,7 +67,7 @@ export async function signIn(): Promise { export async function signOut(): Promise { const auth = IModelApp.authorizationClient; - if (auth instanceof ElectronRendererAuthorization || auth instanceof BrowserAuthorizationClient){ + if (auth instanceof ElectronRendererAuthorization || auth instanceof BrowserAuthorizationClient) { await auth.signOut(); IModelApp.authorizationClient = undefined; } diff --git a/test-apps/display-test-app/tsconfig.buildScripts.json b/test-apps/display-test-app/tsconfig.buildScripts.json index 0445ec28fd59..5c4b9360fa9a 100644 --- a/test-apps/display-test-app/tsconfig.buildScripts.json +++ b/test-apps/display-test-app/tsconfig.buildScripts.json @@ -2,7 +2,7 @@ "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", "compilerOptions": { "module": "commonjs", - "outDir": "./lib", + "outDir": "./lib" }, "include": ["./build*.ts"] } diff --git a/test-apps/display-test-app/tsconfig.json b/test-apps/display-test-app/tsconfig.json index 58105f5684ff..e9e7333ab097 100644 --- a/test-apps/display-test-app/tsconfig.json +++ b/test-apps/display-test-app/tsconfig.json @@ -16,10 +16,10 @@ "dom.iterable", "esnext" ], - "types": ["vite/client"], + "types": ["vite/client"] }, "include": [ - "./src/**/*.ts", + "./src/**/*.ts" ], "exclude": [ "lib", diff --git a/test-apps/display-test-app/vite.config.mts b/test-apps/display-test-app/vite.config.mts index 1510d1c5e570..5d9bd2c7ca67 100644 --- a/test-apps/display-test-app/vite.config.mts +++ b/test-apps/display-test-app/vite.config.mts @@ -2,22 +2,21 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { defineConfig, loadEnv, searchForWorkspaceRoot } from "vite"; -import envCompatible from "vite-plugin-env-compatible"; import browserslistToEsbuild from "browserslist-to-esbuild"; -import viteInspect from "vite-plugin-inspect"; +import { createRequire } from "module"; +import path from "path"; import copy from "rollup-plugin-copy"; +import externalGlobals from "rollup-plugin-external-globals"; import ignore from "rollup-plugin-ignore"; import rollupVisualizer from "rollup-plugin-visualizer"; -import externalGlobals from "rollup-plugin-external-globals"; import { webpackStats } from "rollup-plugin-webpack-stats"; +import { defineConfig, loadEnv, searchForWorkspaceRoot } from "vite"; +import envCompatible from "vite-plugin-env-compatible"; +import viteInspect from "vite-plugin-inspect"; import * as packageJson from "./package.json"; -import path from "path"; -import { createRequire } from "module"; const require = createRequire(import.meta.url); -const mode = - process.env.NODE_ENV === "development" ? "development" : "production"; +const mode = process.env.NODE_ENV === "development" ? "development" : "production"; // array of public directories static assets from dependencies to copy const assets = ["./public/*"]; // assets for test-app @@ -88,19 +87,19 @@ export default defineConfig(() => { plugins: [ ...(process.env.OUTPUT_STATS !== undefined ? [ - rollupVisualizer({ - open: true, - filename: "stats.html", - template: "treemap", - sourcemap: true, - }), - webpackStats(), // needs to be the last plugin - ] + rollupVisualizer({ + open: true, + filename: "stats.html", + template: "treemap", + sourcemap: true, + }), + webpackStats(), // needs to be the last plugin + ] : []), externalGlobals({ // allow global `window` object to access electron as external global electron: "window['electron']", - }) + }), ], }, }, @@ -135,12 +134,9 @@ export default defineConfig(() => { resolve: { alias: { ...packageAliases, - "@itwin/core-electron/lib/cjs/ElectronFrontend": - "@itwin/core-electron/src/ElectronFrontend.ts", - "@itwin/core-mobile/lib/cjs/MobileFrontend": - "@itwin/core-mobile/src/MobileFrontend.ts", + "@itwin/core-electron/lib/cjs/ElectronFrontend": "@itwin/core-electron/src/ElectronFrontend.ts", + "@itwin/core-mobile/lib/cjs/MobileFrontend": "@itwin/core-mobile/src/MobileFrontend.ts", "../../package.json": "../package.json", // in core-frontend - }, }, optimizeDeps: { @@ -151,8 +147,8 @@ export default defineConfig(() => { "@itwin/core-mobile/lib/cjs/MobileFrontend", // import from module error ], exclude: [ - "@itwin/core-frontend", //prevents import not resolved errors - "@itwin/core-common", //prevents rpc errors + "@itwin/core-frontend", // prevents import not resolved errors + "@itwin/core-common", // prevents rpc errors ], }, }; diff --git a/test-apps/export-gltf/eslint.config.js b/test-apps/export-gltf/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/test-apps/export-gltf/eslint.config.js +++ b/test-apps/export-gltf/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/test-apps/export-gltf/package.json b/test-apps/export-gltf/package.json index 3f11c9833ff5..97928055b81e 100644 --- a/test-apps/export-gltf/package.json +++ b/test-apps/export-gltf/package.json @@ -29,4 +29,4 @@ "rimraf": "^3.0.2", "typescript": "~5.3.3" } -} \ No newline at end of file +} diff --git a/test-apps/export-gltf/src/ExportGltf.ts b/test-apps/export-gltf/src/ExportGltf.ts index 9befdc58b5e5..f0f6a6aa2e40 100644 --- a/test-apps/export-gltf/src/ExportGltf.ts +++ b/test-apps/export-gltf/src/ExportGltf.ts @@ -2,16 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import * as path from "path"; -import * as yargs from "yargs"; -import { DbResult, Id64Array, Id64String, Logger, LogLevel } from "@itwin/core-bentley"; -import { Angle, Geometry, Matrix3d, Point3d } from "@itwin/core-geometry"; import { - ECSqlStatement, ExportGraphics, ExportGraphicsInfo, ExportGraphicsLines, ExportGraphicsMesh, ExportLinesInfo, ExportPartInfo, - ExportPartInstanceInfo, ExportPartLinesInfo, IModelHost, SnapshotDb, Texture, + ECSqlStatement, + ExportGraphics, + ExportGraphicsInfo, + ExportGraphicsLines, + ExportGraphicsMesh, + ExportLinesInfo, + ExportPartInfo, + ExportPartInstanceInfo, + ExportPartLinesInfo, + IModelHost, + SnapshotDb, + Texture, } from "@itwin/core-backend"; +import { DbResult, Id64Array, Id64String, Logger, LogLevel } from "@itwin/core-bentley"; import { ColorDef, ImageSourceFormat } from "@itwin/core-common"; +import { Angle, Geometry, Matrix3d, Point3d } from "@itwin/core-geometry"; +import * as fs from "fs"; +import * as path from "path"; +import * as yargs from "yargs"; const exportGraphicsDetailOptions = { chordTol: 0.001, @@ -75,7 +85,7 @@ function findOrAddMaterialIndexForTexture(textureId: Id64String): number { const textureInfo = GltfGlobals.iModel.elements.getElement(textureId); const textureName = textureId + (textureInfo.format === ImageSourceFormat.Jpeg ? ".jpg" : ".png"); const texturePath = path.join(GltfGlobals.texturesDir, textureName); - fs.writeFile(texturePath, textureInfo.data, () => { }); // async is fine + fs.writeFile(texturePath, textureInfo.data, () => {}); // async is fine const texture: GltfTexture = { source: GltfGlobals.gltf.images!.length, sampler: 0 }; GltfGlobals.gltf.textures.push(texture); @@ -87,7 +97,7 @@ function findOrAddMaterialIndexForTexture(textureId: Id64String): number { metallicFactor: 0, roughnessFactor: 1, }; - const material: GltfMaterial = ({ pbrMetallicRoughness, doubleSided: true }); + const material: GltfMaterial = { pbrMetallicRoughness, doubleSided: true }; result = GltfGlobals.gltf.materials.length; GltfGlobals.gltf.materials.push(material); @@ -106,7 +116,7 @@ function findOrAddMaterialIndexForColor(color: number): number { metallicFactor: 0, roughnessFactor: 1, }; - const material: GltfMaterial = ({ pbrMetallicRoughness, doubleSided: true }); + const material: GltfMaterial = { pbrMetallicRoughness, doubleSided: true }; if (rgb.t > 10) material.alphaMode = "BLEND"; @@ -216,7 +226,8 @@ function addMeshParams(params: Float32Array) { } function addMesh(mesh: ExportGraphicsMesh, translation: Point3d, color: number, textureId?: Id64String) { - const material = textureId !== undefined ? findOrAddMaterialIndexForTexture(textureId) : + const material = textureId !== undefined ? + findOrAddMaterialIndexForTexture(textureId) : findOrAddMaterialIndexForColor(color); const primitive: GltfMeshPrimitive = { @@ -358,9 +369,16 @@ class TranslationRotationScale { const invScale = 1.0 / xColumnMagnitude; const matrix = Matrix3d.createRowValues( - xform[0] * invScale, xform[1] * invScale, xform[2] * invScale, - xform[4] * invScale, xform[5] * invScale, xform[6] * invScale, - xform[8] * invScale, xform[9] * invScale, xform[10] * invScale); + xform[0] * invScale, + xform[1] * invScale, + xform[2] * invScale, + xform[4] * invScale, + xform[5] * invScale, + xform[6] * invScale, + xform[8] * invScale, + xform[9] * invScale, + xform[10] * invScale, + ); if (!matrix.isIdentity) { const q = matrix.toQuaternion(); this.rotation = [q.x, q.z, -q.y, -q.w]; // GLTF = RHS Y-up, iModel.js = RHS Z-up @@ -437,7 +455,8 @@ const exportGltfArgs = yargs const elementIdArray: Id64Array = []; // Get all 3D elements that aren't part of template definitions or in private models. - const sql = "SELECT e.ECInstanceId FROM bis.GeometricElement3d e JOIN bis.Model m ON e.Model.Id=m.ECInstanceId WHERE m.isTemplate=false AND m.isPrivate=false"; + const sql = + "SELECT e.ECInstanceId FROM bis.GeometricElement3d e JOIN bis.Model m ON e.Model.Id=m.ECInstanceId WHERE m.isTemplate=false AND m.isPrivate=false"; GltfGlobals.iModel.withPreparedStatement(sql, (stmt: ECSqlStatement) => { while (stmt.step() === DbResult.BE_SQLITE_ROW) elementIdArray.push(stmt.getValue(0).getId()); diff --git a/test-apps/export-gltf/src/GltfTypes.ts b/test-apps/export-gltf/src/GltfTypes.ts index b816d50c52a8..f7146e606fb8 100644 --- a/test-apps/export-gltf/src/GltfTypes.ts +++ b/test-apps/export-gltf/src/GltfTypes.ts @@ -77,7 +77,7 @@ interface GltfMaterial { interface GltfMaterialPbrMetallicRoughness { baseColorTexture?: GltfBaseColorTexture; baseColorFactor: number[]; - metallicFactor: 0; // Completely diffuse for now + metallicFactor: 0; // Completely diffuse for now roughnessFactor: 1; } diff --git a/test-apps/export-gltf/tsconfig.json b/test-apps/export-gltf/tsconfig.json index f3aaf7bbd3fa..371f16361e85 100644 --- a/test-apps/export-gltf/tsconfig.json +++ b/test-apps/export-gltf/tsconfig.json @@ -6,5 +6,5 @@ }, "include": [ "./src/**/*.ts" - ], -} \ No newline at end of file + ] +} diff --git a/test-apps/imjs-importer/eslint.config.js b/test-apps/imjs-importer/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/test-apps/imjs-importer/eslint.config.js +++ b/test-apps/imjs-importer/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/test-apps/imjs-importer/package.json b/test-apps/imjs-importer/package.json index e37ae7517fea..7bdd25f6aa77 100644 --- a/test-apps/imjs-importer/package.json +++ b/test-apps/imjs-importer/package.json @@ -44,4 +44,4 @@ "rimraf": "^3.0.2", "typescript": "~5.3.3" } -} \ No newline at end of file +} diff --git a/test-apps/imjs-importer/src/ImportIMJS.ts b/test-apps/imjs-importer/src/ImportIMJS.ts index a2f9cd01a250..f3215f4405dd 100644 --- a/test-apps/imjs-importer/src/ImportIMJS.ts +++ b/test-apps/imjs-importer/src/ImportIMJS.ts @@ -2,14 +2,23 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import { Id64, Id64String } from "@itwin/core-bentley"; -import { GeometryQuery, IModelJson, Point3d, Range3d, StandardViewIndex, Transform } from "@itwin/core-geometry"; import { - CategorySelector, DefinitionModel, DisplayStyle3d, IModelDb, ModelSelector, OrthographicViewDefinition, PhysicalModel, PhysicalObject, SnapshotDb, - SpatialCategory, SpatialModel, + CategorySelector, + DefinitionModel, + DisplayStyle3d, + IModelDb, + ModelSelector, + OrthographicViewDefinition, + PhysicalModel, + PhysicalObject, + SnapshotDb, + SpatialCategory, + SpatialModel, } from "@itwin/core-backend"; +import { Id64, Id64String } from "@itwin/core-bentley"; import { AxisAlignedBox3d, Code, ColorDef, PhysicalElementProps, RenderMode, ViewFlags } from "@itwin/core-common"; +import { GeometryQuery, IModelJson, Point3d, Range3d, StandardViewIndex, Transform } from "@itwin/core-geometry"; +import * as fs from "fs"; /* eslint-disable no-console */ function collectRange(g: any, rangeToExtend: Range3d) { if (g instanceof GeometryQuery) { @@ -67,7 +76,6 @@ export class ModelIdGroup { } } export class ImportIMJS { - public iModelDb: IModelDb; public definitionModelId: Id64String = Id64.invalid; public featureCategoryId: Id64String = Id64.invalid; @@ -78,7 +86,7 @@ export class ImportIMJS { this._viewFlags = new ViewFlags({ renderMode: RenderMode.SmoothShade, lighting: true }); } public static create(databasePath: string, rootSubject: string): ImportIMJS | undefined { - fs.unlink(databasePath, (_err) => { }); + fs.unlink(databasePath, (_err) => {}); const db = SnapshotDb.createEmpty(databasePath, { rootSubject: { name: rootSubject } }); if (db) return new ImportIMJS(db); @@ -149,7 +157,6 @@ export class ImportIMJS { for (const group of modelGroups) { if (group.modelNames.length > 0) this.insertSpatialView(group.groupName, group.range, group.modelNames); - } this.iModelDb.updateProjectExtents(globalRange); } @@ -161,13 +168,37 @@ export class ImportIMJS { protected insertSpatialView(viewName: string, range: AxisAlignedBox3d, models: string[]): Id64String { const modelSelectorId: Id64String = ModelSelector.insert(this.iModelDb, this.definitionModelId, viewName, models); const categorySelectorId: Id64String = CategorySelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.featureCategoryId]); - const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { viewFlags: this._viewFlags, backgroundColor: ColorDef.blue }); - return OrthographicViewDefinition.insert(this.iModelDb, this.definitionModelId, viewName, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Top); + const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { + viewFlags: this._viewFlags, + backgroundColor: ColorDef.blue, + }); + return OrthographicViewDefinition.insert( + this.iModelDb, + this.definitionModelId, + viewName, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Top, + ); } protected insertSpatialViewOneModel(viewName: string, range: AxisAlignedBox3d, physicalModelId: string): Id64String { const modelSelectorId: Id64String = ModelSelector.insert(this.iModelDb, this.definitionModelId, viewName, [physicalModelId]); const categorySelectorId: Id64String = CategorySelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.featureCategoryId]); - const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { viewFlags: this._viewFlags, backgroundColor: ColorDef.blue }); - return OrthographicViewDefinition.insert(this.iModelDb, this.definitionModelId, viewName, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Top); + const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { + viewFlags: this._viewFlags, + backgroundColor: ColorDef.blue, + }); + return OrthographicViewDefinition.insert( + this.iModelDb, + this.definitionModelId, + viewName, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Top, + ); } } diff --git a/test-apps/imjs-importer/src/byDirectory.ts b/test-apps/imjs-importer/src/byDirectory.ts index 324cece066b3..241a1ea7b129 100644 --- a/test-apps/imjs-importer/src/byDirectory.ts +++ b/test-apps/imjs-importer/src/byDirectory.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as yargs from "yargs"; -import * as path from "path"; import { IModelHost } from "@itwin/core-backend"; +import * as path from "path"; +import * as yargs from "yargs"; import { ImportIMJS } from "./ImportIMJS"; /* eslint-disable no-console */ @@ -28,8 +28,7 @@ IModelHost.startup().then(async () => { if (directoryTail) { const fullBimName = path.isAbsolute(outputFileName) ? outputFileName : `d:\\bfiles\\importIMJS\\${directoryTail}.bim`; console.log({ outputFile: fullBimName }); - const importer = ImportIMJS.create(fullBimName, - "testSubject"); + const importer = ImportIMJS.create(fullBimName, "testSubject"); if (!importer) { console.log("Failed to create bim file"); @@ -44,7 +43,8 @@ IModelHost.startup().then(async () => { for (const group of modelGroups) { if (group.modelNames.length > 0) { console.log({ - groupName: group.groupName, numModel: group.modelNames.length, + groupName: group.groupName, + numModel: group.modelNames.length, range: Math.floor(0.999999 + group.range.maxAbs()), }); } @@ -53,4 +53,4 @@ IModelHost.startup().then(async () => { } await IModelHost.shutdown(); console.log("goodbye"); -}).catch(() => { }); +}).catch(() => {}); diff --git a/test-apps/imjs-importer/src/main.ts b/test-apps/imjs-importer/src/main.ts index e8ab10d7b550..f1f0f622c5a3 100644 --- a/test-apps/imjs-importer/src/main.ts +++ b/test-apps/imjs-importer/src/main.ts @@ -3,17 +3,18 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import { IModelHost } from "@itwin/core-backend"; +import * as path from "path"; import { ImportIMJS } from "./ImportIMJS"; /* eslint-disable no-console */ IModelHost.startup().then(async () => { console.log("start .."); - for (const directoryTail of [ - "TaggedGeometryData", - /* + for ( + const directoryTail of [ + "TaggedGeometryData", + /* "AlternatingConvexClipTree", "Angle", "Arc3d", @@ -67,7 +68,8 @@ IModelHost.startup().then(async () => { "ViewWidget", "XYPointBuckets", */ - ]) { + ] + ) { console.log(`input from${directoryTail}`); const importer = ImportIMJS.create(path.join("d:", "bfiles", "importIMJS", `${directoryTail}.bim`), "testSubject"); @@ -83,7 +85,8 @@ IModelHost.startup().then(async () => { for (const group of modelGroups) { if (group.modelNames.length > 0) { console.log({ - groupName: group.groupName, numModel: group.modelNames.length, + groupName: group.groupName, + numModel: group.modelNames.length, range: Math.floor(0.999999 + group.range.maxAbs()), }); } @@ -92,4 +95,4 @@ IModelHost.startup().then(async () => { } await IModelHost.shutdown(); console.log("goodbye"); -}).catch(() => { }); +}).catch(() => {}); diff --git a/test-apps/imjs-importer/test/unit/ImportIMJS.test.ts b/test-apps/imjs-importer/test/unit/ImportIMJS.test.ts index a7755a08c678..078859f359c6 100644 --- a/test-apps/imjs-importer/test/unit/ImportIMJS.test.ts +++ b/test-apps/imjs-importer/test/unit/ImportIMJS.test.ts @@ -3,121 +3,123 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import "mocha"; -import { expect } from "chai"; import { IModelHost } from "@itwin/core-backend"; +import { expect } from "chai"; import { ImportIMJS } from "../../src/ImportIMJS"; describe("ImportIMJS", () => { - beforeEach(() => { - IModelHost.startup(); - }); - - afterEach(() => { - IModelHost.shutdown(); - }); + beforeEach(() => { + IModelHost.startup(); + }); - it("imjsFromNative", async () => { - const importer = ImportIMJS.create("d:\\bfiles\\importIMJS\\imjsFromNative.bim", "testSubject"); - let ok = true; + afterEach(() => { + IModelHost.shutdown(); + }); - if (importer) { - const modelGroups = importer.importFilesFromDirectory("d:/git20B/imodeljs/core/geometry/src/test/iModelJsonSamples/fromNative/"); - console.log("Imported model groups", modelGroups.length); - let totalModels = 0; - for (const group of modelGroups) { - totalModels += group.modelNames.length; - console.log({ - groupName: group.groupName, numModel: group.modelNames.length, - range: Math.floor(0.999999 + group.range.maxAbs()), - }); - } - ok = totalModels > 0; + it("imjsFromNative", async () => { + const importer = ImportIMJS.create("d:\\bfiles\\importIMJS\\imjsFromNative.bim", "testSubject"); + let ok = true; - } + if (importer) { + const modelGroups = importer.importFilesFromDirectory("d:/git20B/imodeljs/core/geometry/src/test/iModelJsonSamples/fromNative/"); + console.log("Imported model groups", modelGroups.length); + let totalModels = 0; + for (const group of modelGroups) { + totalModels += group.modelNames.length; + console.log({ + groupName: group.groupName, + numModel: group.modelNames.length, + range: Math.floor(0.999999 + group.range.maxAbs()), + }); + } + ok = totalModels > 0; + } - expect(ok) - }); - it.only("imodeljsUnitTest", async () => { - for (const directoryTail of [ - "AlternatingConvexClipTree", - "Angle", - "Arc3d", - "ArnoldasEarthWorks", - "Bezier", - "BezierCurve3d", - "BSpline", - "BSplineCurve", - "BSplineSurface", - "ClipNode", - "ClipPlane", - "CoincidentGeometryQuery", - "ConsolidateAdjacentPrimitives", - "CurveCurveIntersection", - "CurveCurveXY", - "CurveFactory", - "CurveOffset", - "CurvePrimitive", - "Ellipsoid", - "EllipsoidPatch", - "FrameBuilder", - "Geometry3d", - "Geometry4d", - "Graph", - "GreedyTriangulationBetweenLineStrings", - "GriddedRaggedRange2dSet", - "GridSampling", - "iModelJsonSamples", - "InsertAndRetriangulateContext", - "LinearSearchRange2dArray", - "Linestring3d", - "MarkVisibility", - "Moments", - "Point3dArray", - "PolarData", - "Polyface", - "PolyfaceClip", - "PolyfaceQuery", - "PolygonAreas", - "PolygonOffset", - "PolygonOps", - "PolylineCompression", - "RegionBoolean", - "RegionOps", - "ReorientFacets", - "Solids", - "SortablePolygon", - "SphereImplicit", - "TransformedSolids", - "Triangulation", - "ViewWidget", - "XYPointBuckets", - ]) { - const importer = ImportIMJS.create("d:\\bfiles\\importIMJS\\" + directoryTail + ".bim", - "testSubject"); - let ok = true; + expect(ok); + }); + it.only("imodeljsUnitTest", async () => { + for ( + const directoryTail of [ + "AlternatingConvexClipTree", + "Angle", + "Arc3d", + "ArnoldasEarthWorks", + "Bezier", + "BezierCurve3d", + "BSpline", + "BSplineCurve", + "BSplineSurface", + "ClipNode", + "ClipPlane", + "CoincidentGeometryQuery", + "ConsolidateAdjacentPrimitives", + "CurveCurveIntersection", + "CurveCurveXY", + "CurveFactory", + "CurveOffset", + "CurvePrimitive", + "Ellipsoid", + "EllipsoidPatch", + "FrameBuilder", + "Geometry3d", + "Geometry4d", + "Graph", + "GreedyTriangulationBetweenLineStrings", + "GriddedRaggedRange2dSet", + "GridSampling", + "iModelJsonSamples", + "InsertAndRetriangulateContext", + "LinearSearchRange2dArray", + "Linestring3d", + "MarkVisibility", + "Moments", + "Point3dArray", + "PolarData", + "Polyface", + "PolyfaceClip", + "PolyfaceQuery", + "PolygonAreas", + "PolygonOffset", + "PolygonOps", + "PolylineCompression", + "RegionBoolean", + "RegionOps", + "ReorientFacets", + "Solids", + "SortablePolygon", + "SphereImplicit", + "TransformedSolids", + "Triangulation", + "ViewWidget", + "XYPointBuckets", + ] + ) { + const importer = ImportIMJS.create("d:\\bfiles\\importIMJS\\" + directoryTail + ".bim", "testSubject"); + let ok = true; - if (importer) { - const modelGroups = importer.importFilesFromDirectory( - "d:\\git20B\\imodeljs\\core\\geometry\\src\\test\\output\\" + directoryTail + "\\"); - let numModel = 0; - for (const group of modelGroups) { - numModel += group.modelNames.length; - } - console.log({ directoryName: directoryTail, models: numModel }); - let totalModels = 0; - for (const group of modelGroups) { - if (group.modelNames.length > 0) { - totalModels += group.modelNames.length; - console.log({ - groupName: group.groupName, numModel: group.modelNames.length, - range: Math.floor(0.999999 + group.range.maxAbs()), - }); - } - } - ok = totalModels > 0; - } - expect(ok) + if (importer) { + const modelGroups = importer.importFilesFromDirectory( + "d:\\git20B\\imodeljs\\core\\geometry\\src\\test\\output\\" + directoryTail + "\\", + ); + let numModel = 0; + for (const group of modelGroups) { + numModel += group.modelNames.length; } - }); - + console.log({ directoryName: directoryTail, models: numModel }); + let totalModels = 0; + for (const group of modelGroups) { + if (group.modelNames.length > 0) { + totalModels += group.modelNames.length; + console.log({ + groupName: group.groupName, + numModel: group.modelNames.length, + range: Math.floor(0.999999 + group.range.maxAbs()), + }); + } + } + ok = totalModels > 0; + } + expect(ok); + } + }); }); diff --git a/test-apps/imjs-importer/tsconfig.json b/test-apps/imjs-importer/tsconfig.json index 72a599b48000..e871752f0408 100644 --- a/test-apps/imjs-importer/tsconfig.json +++ b/test-apps/imjs-importer/tsconfig.json @@ -1,15 +1,15 @@ { - "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", - "compilerOptions": { - "baseUrl": "./node_modules", - "outDir": "./lib" - }, - "include": [ - "./**/*.ts", - ], - "exclude": [ - "lib", - "node_modules", - "test" - ] - } \ No newline at end of file + "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", + "compilerOptions": { + "baseUrl": "./node_modules", + "outDir": "./lib" + }, + "include": [ + "./**/*.ts" + ], + "exclude": [ + "lib", + "node_modules", + "test" + ] +} diff --git a/test-apps/imodel-from-geojson/.vscode/launch.json b/test-apps/imodel-from-geojson/.vscode/launch.json index 25a640d5d36d..e89171b5b927 100644 --- a/test-apps/imodel-from-geojson/.vscode/launch.json +++ b/test-apps/imodel-from-geojson/.vscode/launch.json @@ -21,5 +21,5 @@ ], "protocol": "inspector" } - ], -} \ No newline at end of file + ] +} diff --git a/test-apps/imodel-from-geojson/.vscode/settings.json b/test-apps/imodel-from-geojson/.vscode/settings.json index 3a175b1f3b29..58e0fa0749a9 100644 --- a/test-apps/imodel-from-geojson/.vscode/settings.json +++ b/test-apps/imodel-from-geojson/.vscode/settings.json @@ -10,4 +10,4 @@ "guid", "imodeljs" ] -} \ No newline at end of file +} diff --git a/test-apps/imodel-from-geojson/eslint.config.js b/test-apps/imodel-from-geojson/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/test-apps/imodel-from-geojson/eslint.config.js +++ b/test-apps/imodel-from-geojson/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/test-apps/imodel-from-geojson/package.json b/test-apps/imodel-from-geojson/package.json index 183adcbdbb0c..8f5ad233643f 100644 --- a/test-apps/imodel-from-geojson/package.json +++ b/test-apps/imodel-from-geojson/package.json @@ -32,4 +32,4 @@ "rimraf": "^3.0.2", "typescript": "~5.3.3" } -} \ No newline at end of file +} diff --git a/test-apps/imodel-from-geojson/src/ClassifyRealityModel.ts b/test-apps/imodel-from-geojson/src/ClassifyRealityModel.ts index 79a72d6a3fee..7e6b48a58d37 100644 --- a/test-apps/imodel-from-geojson/src/ClassifyRealityModel.ts +++ b/test-apps/imodel-from-geojson/src/ClassifyRealityModel.ts @@ -2,12 +2,18 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Id64String, JsonUtils } from "@itwin/core-bentley"; -import { Matrix3d, Point3d, Range3d, StandardViewIndex, Transform, Vector3d } from "@itwin/core-geometry"; import { CategorySelector, DisplayStyle3d, IModelDb, ModelSelector, OrthographicViewDefinition } from "@itwin/core-backend"; +import { Id64String, JsonUtils } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, Cartographic, IModel, PersistentBackgroundMapProps, SpatialClassifierInsideDisplay, SpatialClassifierOutsideDisplay, ViewFlags, + AxisAlignedBox3d, + Cartographic, + IModel, + PersistentBackgroundMapProps, + SpatialClassifierInsideDisplay, + SpatialClassifierOutsideDisplay, + ViewFlags, } from "@itwin/core-common"; +import { Matrix3d, Point3d, Range3d, StandardViewIndex, Transform, Vector3d } from "@itwin/core-geometry"; class RealityModelTileUtils { public static rangeFromBoundingVolume(boundingVolume: any): Range3d | undefined { @@ -23,7 +29,7 @@ class RealityModelTileUtils { for (let j = 0; j < 2; j++) { for (let k = 0; k < 2; k++) { for (let l = 0; l < 2; l++) { - corners.push(center.plus3Scaled(ux, (j ? -1.0 : 1.0), uy, (k ? -1.0 : 1.0), uz, (l ? -1.0 : 1.0))); + corners.push(center.plus3Scaled(ux, j ? -1.0 : 1.0, uy, k ? -1.0 : 1.0, uz, l ? -1.0 : 1.0)); } } } @@ -38,11 +44,16 @@ class RealityModelTileUtils { } public static maximumSizeFromGeometricTolerance(range: Range3d, geometricError: number): number { - const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. + const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. return minToleranceRatio * range.diagonal().magnitude() / geometricError; } public static transformFromJson(jTrans: number[] | undefined): Transform | undefined { - return (jTrans === undefined) ? undefined : Transform.createOriginAndMatrix(Point3d.create(jTrans[12], jTrans[13], jTrans[14]), Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10])); + return (jTrans === undefined) + ? undefined + : Transform.createOriginAndMatrix( + Point3d.create(jTrans[12], jTrans[13], jTrans[14]), + Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10]), + ); } public static rangeFromJson(json: any): AxisAlignedBox3d { if (undefined !== json.root.boundingVolume.region) { @@ -91,7 +102,18 @@ function parseDisplayMode(defaultDisplay: number, option?: string) { } } -export async function insertClassifiedRealityModel(url: string, classifierModelId: Id64String, classifierCategoryId: Id64String, iModelDb: IModelDb, viewFlags: ViewFlags, isPlanar: boolean, backgroundMap?: PersistentBackgroundMapProps, inputName?: string, inside?: string, outside?: string): Promise { +export async function insertClassifiedRealityModel( + url: string, + classifierModelId: Id64String, + classifierCategoryId: Id64String, + iModelDb: IModelDb, + viewFlags: ViewFlags, + isPlanar: boolean, + backgroundMap?: PersistentBackgroundMapProps, + inputName?: string, + inside?: string, + outside?: string, +): Promise { const name = inputName ? inputName : url; const classificationFlags = { inside: parseDisplayMode(SpatialClassifierInsideDisplay.ElementColor, inside), @@ -101,7 +123,11 @@ export async function insertClassifiedRealityModel(url: string, classifierModelI const classifier = { modelId: classifierModelId, name, flags: classificationFlags, isActive: true, expand: 1.0 }; const realityModel = { tilesetUrl: url, name, classifiers: [classifier] }; - const displayStyleId = DisplayStyle3d.insert(iModelDb, IModel.dictionaryId, name, { viewFlags, backgroundMap, contextRealityModels: [realityModel] }); + const displayStyleId = DisplayStyle3d.insert(iModelDb, IModel.dictionaryId, name, { + viewFlags, + backgroundMap, + contextRealityModels: [realityModel], + }); const projectExtents = Range3d.createFrom(iModelDb.projectExtents); let range; @@ -119,5 +145,14 @@ export async function insertClassifiedRealityModel(url: string, classifierModelI const modelSelectorId: Id64String = ModelSelector.insert(iModelDb, IModel.dictionaryId, name, []); const categorySelectorId: Id64String = CategorySelector.insert(iModelDb, IModel.dictionaryId, name, [classifierCategoryId]); - OrthographicViewDefinition.insert(iModelDb, IModel.dictionaryId, name, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Iso); + OrthographicViewDefinition.insert( + iModelDb, + IModel.dictionaryId, + name, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Iso, + ); } diff --git a/test-apps/imodel-from-geojson/src/GeoJsonImporter.ts b/test-apps/imodel-from-geojson/src/GeoJsonImporter.ts index 8313870f178b..c565ff3f755e 100644 --- a/test-apps/imodel-from-geojson/src/GeoJsonImporter.ts +++ b/test-apps/imodel-from-geojson/src/GeoJsonImporter.ts @@ -2,16 +2,39 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { Id64, Id64String, OpenMode } from "@itwin/core-bentley"; -import { Angle, Arc3d, GeometryQuery, LineString3d, Loop, Range3d, StandardViewIndex } from "@itwin/core-geometry"; import { - CategorySelector, DefinitionModel, DisplayStyle3d, IModelDb, ModelSelector, OrthographicViewDefinition, PhysicalModel, SnapshotDb, SpatialCategory, - SpatialModel, StandaloneDb, ViewDefinition, + CategorySelector, + DefinitionModel, + DisplayStyle3d, + IModelDb, + ModelSelector, + OrthographicViewDefinition, + PhysicalModel, + SnapshotDb, + SpatialCategory, + SpatialModel, + StandaloneDb, + ViewDefinition, } from "@itwin/core-backend"; +import { Id64, Id64String, OpenMode } from "@itwin/core-bentley"; import { - AxisAlignedBox3d, BackgroundMapType, Cartographic, Code, ColorByName, ColorDef, EcefLocation, GeometricElement3dProps, - GeometryParams, GeometryStreamBuilder, GeometryStreamProps, IModel, PersistentBackgroundMapProps, RenderMode, ViewFlags, + AxisAlignedBox3d, + BackgroundMapType, + Cartographic, + Code, + ColorByName, + ColorDef, + EcefLocation, + GeometricElement3dProps, + GeometryParams, + GeometryStreamBuilder, + GeometryStreamProps, + IModel, + PersistentBackgroundMapProps, + RenderMode, + ViewFlags, } from "@itwin/core-common"; +import { Angle, Arc3d, GeometryQuery, LineString3d, Loop, Range3d, StandardViewIndex } from "@itwin/core-geometry"; import { insertClassifiedRealityModel } from "./ClassifyRealityModel"; import { GeoJson } from "./GeoJson"; @@ -36,9 +59,24 @@ export class GeoJsonImporter { * @param iModelFileName the output iModel file name * @param geoJson the input GeoJson data */ - public constructor(iModelFileName: string, geoJson: GeoJson, appendToExisting: boolean, modelName?: string, labelProperty?: string, pointRadius?: number, pseudoColor?: boolean, mapTypeString?: string, mapGroundBias?: number, - private _classifiedURL?: string, private _classifiedName?: string, private _classifiedOutside?: string, private _classifiedInside?: string) { - this.iModelDb = appendToExisting ? StandaloneDb.openFile(iModelFileName, OpenMode.ReadWrite) : SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: geoJson.title } }); + public constructor( + iModelFileName: string, + geoJson: GeoJson, + appendToExisting: boolean, + modelName?: string, + labelProperty?: string, + pointRadius?: number, + pseudoColor?: boolean, + mapTypeString?: string, + mapGroundBias?: number, + private _classifiedURL?: string, + private _classifiedName?: string, + private _classifiedOutside?: string, + private _classifiedInside?: string, + ) { + this.iModelDb = appendToExisting + ? StandaloneDb.openFile(iModelFileName, OpenMode.ReadWrite) + : SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: geoJson.title } }); this._geoJson = geoJson; this._appendToExisting = appendToExisting; this._modelName = modelName; @@ -90,7 +128,10 @@ export class GeoJsonImporter { const featureMin = Cartographic.createZero(), featureMax = Cartographic.createZero(); if (!this.getFeatureRange(featureMin, featureMax)) return; - const featureCenter = Cartographic.fromRadians({ longitude: (featureMin.longitude + featureMax.longitude) / 2, latitude: (featureMin.latitude + featureMax.latitude) / 2 }); + const featureCenter = Cartographic.fromRadians({ + longitude: (featureMin.longitude + featureMax.longitude) / 2, + latitude: (featureMin.latitude + featureMax.latitude) / 2, + }); this.iModelDb.setEcefLocation(EcefLocation.createFromCartographicOrigin(featureCenter)); this.convertFeatureCollection(); @@ -104,7 +145,18 @@ export class GeoJsonImporter { if (this._classifiedURL) { const isPlanar = (featureModelExtents.high.z - featureModelExtents.low.z) < 1.0E-2; - await insertClassifiedRealityModel(this._classifiedURL, this.physicalModelId, this.featureCategoryId, this.iModelDb, this._viewFlags, isPlanar, this._backgroundMap, this._classifiedName ? this._classifiedName : this._modelName, this._classifiedInside, this._classifiedOutside); + await insertClassifiedRealityModel( + this._classifiedURL, + this.physicalModelId, + this.featureCategoryId, + this.iModelDb, + this._viewFlags, + isPlanar, + this._backgroundMap, + this._classifiedName ? this._classifiedName : this._modelName, + this._classifiedInside, + this._classifiedOutside, + ); } this.iModelDb.saveChanges(); @@ -112,13 +164,13 @@ export class GeoJsonImporter { private addCategoryToExistingDb(categoryName: string) { const categoryId = SpatialCategory.insert(this.iModelDb, IModel.dictionaryId, categoryName, { color: ColorDef.white.tbgr }); // eslint-disable-next-line deprecation/deprecation - this.iModelDb.views.iterateViews({ from: "BisCore.SpatialViewDefinition" }, ((view: ViewDefinition) => { + this.iModelDb.views.iterateViews({ from: "BisCore.SpatialViewDefinition" }, (view: ViewDefinition) => { const categorySelector = this.iModelDb.elements.getElement(view.categorySelectorId); categorySelector.categories.push(categoryId); this.iModelDb.elements.updateElement(categorySelector.toJSON()); return true; - })); + }); return categoryId; } @@ -195,7 +247,19 @@ export class GeoJsonImporter { const builder = new GeometryStreamBuilder(); if (this._colorIndex !== undefined) { - const colorValues = [ColorByName.blue, ColorByName.red, ColorByName.green, ColorByName.yellow, ColorByName.cyan, ColorByName.magenta, ColorByName.cornSilk, ColorByName.blueViolet, ColorByName.deepSkyBlue, ColorByName.indigo, ColorByName.fuchsia]; + const colorValues = [ + ColorByName.blue, + ColorByName.red, + ColorByName.green, + ColorByName.yellow, + ColorByName.cyan, + ColorByName.magenta, + ColorByName.cornSilk, + ColorByName.blueViolet, + ColorByName.deepSkyBlue, + ColorByName.indigo, + ColorByName.fuchsia, + ]; const geomParams = new GeometryParams(this.featureCategoryId); geomParams.lineColor = ColorDef.create(colorValues[this._colorIndex++ % colorValues.length]); builder.appendGeometryParamsChange(geomParams); @@ -244,7 +308,6 @@ export class GeoJsonImporter { } private convertPoint(inPoint: GeoJson.Point): Loop { return Loop.create(Arc3d.createXY(this.pointFromCoordinate(inPoint), this._pointRadius)); - } /** Convert a GeoJSON LineString into an @itwin/core-geometry lineString */ @@ -277,7 +340,7 @@ export class GeoJsonImporter { case 1: return outLoops[0]; default: - return undefined; // TBD... Multi-loop Regions, + return undefined; // TBD... Multi-loop Regions, } } private static _scratchCartographic = Cartographic.createZero(); @@ -292,7 +355,19 @@ export class GeoJsonImporter { protected insertSpatialView(viewName: string, range: AxisAlignedBox3d): Id64String { const modelSelectorId: Id64String = ModelSelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.physicalModelId]); const categorySelectorId: Id64String = CategorySelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.featureCategoryId]); - const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { viewFlags: this._viewFlags, backgroundMap: this._backgroundMap }); - return OrthographicViewDefinition.insert(this.iModelDb, this.definitionModelId, viewName, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Top); + const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { + viewFlags: this._viewFlags, + backgroundMap: this._backgroundMap, + }); + return OrthographicViewDefinition.insert( + this.iModelDb, + this.definitionModelId, + viewName, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Top, + ); } } diff --git a/test-apps/imodel-from-geojson/src/Main.ts b/test-apps/imodel-from-geojson/src/Main.ts index 4f191c86ed2a..c10c27c74808 100644 --- a/test-apps/imodel-from-geojson/src/Main.ts +++ b/test-apps/imodel-from-geojson/src/Main.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as yargs from "yargs"; -import { Logger } from "@itwin/core-bentley"; import { IModelHost } from "@itwin/core-backend"; +import { Logger } from "@itwin/core-bentley"; +import * as yargs from "yargs"; import { GeoJson } from "./GeoJson"; import { GeoJsonImporter } from "./GeoJsonImporter"; @@ -52,9 +52,21 @@ const argv = yargs Logger.initializeToConsole(); const geoJson = new GeoJson(argv.input); - const importer = new GeoJsonImporter(argv.output, geoJson, argv.append as boolean, argv.model_name as string, argv.label as string, argv.point_radius as number, argv.color as boolean, - argv.map as string, argv.mapBias as number, - argv.classifiedURL as string, argv.classifiedName as string, argv.classifiedOutside as string, argv.classifiedInside as string); + const importer = new GeoJsonImporter( + argv.output, + geoJson, + argv.append as boolean, + argv.model_name as string, + argv.label as string, + argv.point_radius as number, + argv.color as boolean, + argv.map as string, + argv.mapBias as number, + argv.classifiedURL as string, + argv.classifiedName as string, + argv.classifiedOutside as string, + argv.classifiedInside as string, + ); try { await importer.import(); diff --git a/test-apps/imodel-from-orbitgt/eslint.config.js b/test-apps/imodel-from-orbitgt/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/test-apps/imodel-from-orbitgt/eslint.config.js +++ b/test-apps/imodel-from-orbitgt/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/test-apps/imodel-from-orbitgt/package.json b/test-apps/imodel-from-orbitgt/package.json index b83d42fe299a..32624ad02f61 100644 --- a/test-apps/imodel-from-orbitgt/package.json +++ b/test-apps/imodel-from-orbitgt/package.json @@ -31,4 +31,4 @@ "rimraf": "^3.0.2", "typescript": "~5.3.3" } -} \ No newline at end of file +} diff --git a/test-apps/imodel-from-orbitgt/src/Main.ts b/test-apps/imodel-from-orbitgt/src/Main.ts index 0e7f9510c0bb..21693748c927 100644 --- a/test-apps/imodel-from-orbitgt/src/Main.ts +++ b/test-apps/imodel-from-orbitgt/src/Main.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as yargs from "yargs"; -import { Logger } from "@itwin/core-bentley"; import { IModelHost } from "@itwin/core-backend"; +import { Logger } from "@itwin/core-bentley"; +import * as yargs from "yargs"; import { OrbitGtContextIModelCreator } from "./OrbitGtContextModelCreator"; /** Use [yargs](https://www.npmjs.com/package/yargs) to validate and extract command line options. */ diff --git a/test-apps/imodel-from-orbitgt/src/OrbitGtContextModelCreator.ts b/test-apps/imodel-from-orbitgt/src/OrbitGtContextModelCreator.ts index 3fa4285e2257..7447ec0960f5 100644 --- a/test-apps/imodel-from-orbitgt/src/OrbitGtContextModelCreator.ts +++ b/test-apps/imodel-from-orbitgt/src/OrbitGtContextModelCreator.ts @@ -2,17 +2,22 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import { Id64, Id64String } from "@itwin/core-bentley"; -import { Range3d, StandardViewIndex } from "@itwin/core-geometry"; import { - CategorySelector, DefinitionModel, DisplayStyle3d, IModelDb, ModelSelector, PhysicalModel, SnapshotDb, SpatialViewDefinition, + CategorySelector, + DefinitionModel, + DisplayStyle3d, + IModelDb, + ModelSelector, + PhysicalModel, + SnapshotDb, + SpatialViewDefinition, } from "@itwin/core-backend"; +import { Id64, Id64String } from "@itwin/core-bentley"; import { AxisAlignedBox3d, Cartographic, ContextRealityModelProps, EcefLocation, RenderMode, ViewFlags } from "@itwin/core-common"; -import { - ALong, CRSManager, Downloader, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, PointCloudReader, UrlFS, -} from "@itwin/core-orbitgt"; +import { Range3d, StandardViewIndex } from "@itwin/core-geometry"; +import { ALong, CRSManager, Downloader, OnlineEngine, OPCReader, OrbitGtBounds, PageCachedFile, PointCloudReader, UrlFS } from "@itwin/core-orbitgt"; import { DownloaderNode } from "@itwin/core-orbitgt/lib/cjs/system/runtime/DownloaderNode"; +import * as fs from "fs"; interface OrbitGtPointCloudProps { rdsUrl?: string; @@ -34,7 +39,7 @@ export class OrbitGtContextIModelCreator { * @param url the reality model URL */ public constructor(private _props: OrbitGtPointCloudProps, iModelFileName: string, private _name: string) { - fs.unlink(iModelFileName, ((_err) => { })); + fs.unlink(iModelFileName, (_err) => {}); this.iModelDb = SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: "Reality Model Context" } }); } /** Perform the import */ @@ -57,14 +62,21 @@ export class OrbitGtContextIModelCreator { // wrap a caching layer (16 MB) around the blob file const blobFileSize: ALong = await urlFS.getFileLength(blobFileURL); - const blobFile: PageCachedFile = new PageCachedFile(urlFS, blobFileURL, blobFileSize, 128 * 1024 /* pageSize */, 128 /* maxPageCount */); - const fileReader: PointCloudReader = await OPCReader.openFile(blobFile, blobFileURL, true/* lazyLoading */); + const blobFile: PageCachedFile = new PageCachedFile(urlFS, blobFileURL, blobFileSize, 128 * 1024, /* pageSize */ 128 /* maxPageCount */); + const fileReader: PointCloudReader = await OPCReader.openFile(blobFile, blobFileURL, true /* lazyLoading */); let fileCrs = fileReader.getFileCRS(); if (fileCrs == null) fileCrs = ""; const bounds = fileReader.getFileBounds(); - let worldRange = Range3d.createXYZXYZ(bounds.getMinX(), bounds.getMinY(), bounds.getMinZ(), bounds.getMaxX(), bounds.getMaxY(), bounds.getMaxZ()); + let worldRange = Range3d.createXYZXYZ( + bounds.getMinX(), + bounds.getMinY(), + bounds.getMinZ(), + bounds.getMaxX(), + bounds.getMaxY(), + bounds.getMaxZ(), + ); let geoLocated = false; // the CRS 9300 is not defined in the CRS registry database, so we cannot use CRSManager // Check to isGeographicCRS and isProjectedCRS are both going to return false in that case and we will fallback to @@ -77,7 +89,14 @@ export class OrbitGtContextIModelCreator { await CRSManager.ENGINE.prepareForArea(wgs84Crs, new OrbitGtBounds()); const ecefBounds = CRSManager.transformBounds(bounds, fileCrs, wgs84Crs); - const ecefRange = Range3d.createXYZXYZ(ecefBounds.getMinX(), ecefBounds.getMinY(), ecefBounds.getMinZ(), ecefBounds.getMaxX(), ecefBounds.getMaxY(), ecefBounds.getMaxZ()); + const ecefRange = Range3d.createXYZXYZ( + ecefBounds.getMinX(), + ecefBounds.getMinY(), + ecefBounds.getMinZ(), + ecefBounds.getMaxX(), + ecefBounds.getMaxY(), + ecefBounds.getMaxZ(), + ); const ecefCenter = ecefRange.localXYZToWorld(.5, .5, .5)!; const cartoCenter = Cartographic.fromEcef(ecefCenter)!; cartoCenter.height = 0; @@ -101,7 +120,19 @@ export class OrbitGtContextIModelCreator { const modelSelectorId: Id64String = ModelSelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.physicalModelId]); const categorySelectorId: Id64String = CategorySelector.insert(this.iModelDb, this.definitionModelId, viewName, []); const vf = new ViewFlags({ backgroundMap: geoLocated, renderMode: RenderMode.SmoothShade, lighting: true }); - const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { viewFlags: vf, contextRealityModels: realityModels }); - return SpatialViewDefinition.insertWithCamera(this.iModelDb, this.definitionModelId, viewName, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Iso); + const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { + viewFlags: vf, + contextRealityModels: realityModels, + }); + return SpatialViewDefinition.insertWithCamera( + this.iModelDb, + this.definitionModelId, + viewName, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Iso, + ); } } diff --git a/test-apps/imodel-from-reality-model/eslint.config.js b/test-apps/imodel-from-reality-model/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/test-apps/imodel-from-reality-model/eslint.config.js +++ b/test-apps/imodel-from-reality-model/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/test-apps/imodel-from-reality-model/package.json b/test-apps/imodel-from-reality-model/package.json index 7a4a1512363a..27738ee2db16 100644 --- a/test-apps/imodel-from-reality-model/package.json +++ b/test-apps/imodel-from-reality-model/package.json @@ -32,4 +32,4 @@ "rimraf": "^3.0.2", "typescript": "~5.3.3" } -} \ No newline at end of file +} diff --git a/test-apps/imodel-from-reality-model/src/Main.ts b/test-apps/imodel-from-reality-model/src/Main.ts index df23875aeb49..c23b4c152063 100644 --- a/test-apps/imodel-from-reality-model/src/Main.ts +++ b/test-apps/imodel-from-reality-model/src/Main.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as yargs from "yargs"; -import { Logger } from "@itwin/core-bentley"; import { IModelHost } from "@itwin/core-backend"; +import { Logger } from "@itwin/core-bentley"; +import * as yargs from "yargs"; import { RealityModelContextIModelCreator } from "./RealityModelContextIModelCreator"; /** Use [yargs](https://www.npmjs.com/package/yargs) to validate and extract command line options. */ diff --git a/test-apps/imodel-from-reality-model/src/RealityModelContextIModelCreator.ts b/test-apps/imodel-from-reality-model/src/RealityModelContextIModelCreator.ts index 34d4bf452528..a3295b80d9fe 100644 --- a/test-apps/imodel-from-reality-model/src/RealityModelContextIModelCreator.ts +++ b/test-apps/imodel-from-reality-model/src/RealityModelContextIModelCreator.ts @@ -3,13 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import { Id64, Id64String, JsonUtils } from "@itwin/core-bentley"; -import { Matrix3d, Point3d, Range3d, StandardViewIndex, Transform, Vector3d } from "@itwin/core-geometry"; import { - CategorySelector, DefinitionModel, DisplayStyle3d, IModelDb, ModelSelector, OrthographicViewDefinition, PhysicalModel, SnapshotDb, + CategorySelector, + DefinitionModel, + DisplayStyle3d, + IModelDb, + ModelSelector, + OrthographicViewDefinition, + PhysicalModel, + SnapshotDb, } from "@itwin/core-backend"; +import { Id64, Id64String, JsonUtils } from "@itwin/core-bentley"; import { AxisAlignedBox3d, Cartographic, ContextRealityModelProps, EcefLocation, RenderMode, ViewFlags } from "@itwin/core-common"; +import { Matrix3d, Point3d, Range3d, StandardViewIndex, Transform, Vector3d } from "@itwin/core-geometry"; +import * as fs from "fs"; class RealityModelTileUtils { public static rangeFromBoundingVolume(boundingVolume: any): Range3d | undefined { @@ -25,7 +32,7 @@ class RealityModelTileUtils { for (let j = 0; j < 2; j++) { for (let k = 0; k < 2; k++) { for (let l = 0; l < 2; l++) { - corners.push(center.plus3Scaled(ux, (j ? -1.0 : 1.0), uy, (k ? -1.0 : 1.0), uz, (l ? -1.0 : 1.0))); + corners.push(center.plus3Scaled(ux, j ? -1.0 : 1.0, uy, k ? -1.0 : 1.0, uz, l ? -1.0 : 1.0)); } } } @@ -40,11 +47,16 @@ class RealityModelTileUtils { } public static maximumSizeFromGeometricTolerance(range: Range3d, geometricError: number): number { - const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. + const minToleranceRatio = .5; // Nominally the error on screen size of a tile. Increasing generally increases performance (fewer draw calls) at expense of higher load times. return minToleranceRatio * range.diagonal().magnitude() / geometricError; } public static transformFromJson(jTrans: number[] | undefined): Transform | undefined { - return (jTrans === undefined) ? undefined : Transform.createOriginAndMatrix(Point3d.create(jTrans[12], jTrans[13], jTrans[14]), Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10])); + return (jTrans === undefined) + ? undefined + : Transform.createOriginAndMatrix( + Point3d.create(jTrans[12], jTrans[13], jTrans[14]), + Matrix3d.createRowValues(jTrans[0], jTrans[4], jTrans[8], jTrans[1], jTrans[5], jTrans[9], jTrans[2], jTrans[6], jTrans[10]), + ); } } @@ -61,7 +73,7 @@ export class RealityModelContextIModelCreator { * @param url the reality model URL */ public constructor(iModelFileName: string, url: string, private _name: string) { - fs.unlink(iModelFileName, ((_err) => { })); + fs.unlink(iModelFileName, (_err) => {}); this.iModelDb = SnapshotDb.createEmpty(iModelFileName, { rootSubject: { name: "Reality Model Context" } }); this.url = url; } @@ -74,7 +86,11 @@ export class RealityModelContextIModelCreator { const ecefLow = (Cartographic.fromRadians({ longitude: region[0], latitude: region[1], height: region[4] })).toEcef(); const ecefHigh = (Cartographic.fromRadians({ longitude: region[2], latitude: region[3], height: region[5] })).toEcef(); const ecefRange = Range3d.create(ecefLow, ecefHigh); - const cartoCenter = Cartographic.fromRadians({ longitude: (region[0] + region[2]) / 2.0, latitude: (region[1] + region[3]) / 2.0, height: (region[4] + region[5]) / 2.0 }); + const cartoCenter = Cartographic.fromRadians({ + longitude: (region[0] + region[2]) / 2.0, + latitude: (region[1] + region[3]) / 2.0, + height: (region[4] + region[5]) / 2.0, + }); const ecefLocation = EcefLocation.createFromCartographicOrigin(cartoCenter); this.iModelDb.setEcefLocation(ecefLocation); const ecefToWorld = ecefLocation.getTransform().inverse()!; @@ -128,8 +144,10 @@ export class RealityModelContextIModelCreator { let worldToEcef: Transform | undefined; for (const modelValue of Object.values(json.models)) { const model = modelValue as any; - if (model.tilesetUrl !== undefined && - model.type === "spatial") { + if ( + model.tilesetUrl !== undefined && + model.type === "spatial" + ) { let modelUrl = prefix + model.tilesetUrl.replace(/\/\//g, "/"); modelUrl = modelUrl.replace(/ /g, "%20"); const ecefRange = Range3d.fromJSON(model.extents); @@ -166,7 +184,19 @@ export class RealityModelContextIModelCreator { const modelSelectorId: Id64String = ModelSelector.insert(this.iModelDb, this.definitionModelId, viewName, [this.physicalModelId]); const categorySelectorId: Id64String = CategorySelector.insert(this.iModelDb, this.definitionModelId, viewName, []); const vf = new ViewFlags({ backgroundMap: geoLocated, renderMode: RenderMode.SmoothShade, lighting: true }); - const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { viewFlags: vf, contextRealityModels: realityModels }); - return OrthographicViewDefinition.insert(this.iModelDb, this.definitionModelId, viewName, modelSelectorId, categorySelectorId, displayStyleId, range, StandardViewIndex.Iso); + const displayStyleId: Id64String = DisplayStyle3d.insert(this.iModelDb, this.definitionModelId, viewName, { + viewFlags: vf, + contextRealityModels: realityModels, + }); + return OrthographicViewDefinition.insert( + this.iModelDb, + this.definitionModelId, + viewName, + modelSelectorId, + categorySelectorId, + displayStyleId, + range, + StandardViewIndex.Iso, + ); } } diff --git a/tools/backend-webpack/bin/backend-webpack-tools.js b/tools/backend-webpack/bin/backend-webpack-tools.js index e30363f97eff..c4ebd6644deb 100755 --- a/tools/backend-webpack/bin/backend-webpack-tools.js +++ b/tools/backend-webpack/bin/backend-webpack-tools.js @@ -7,12 +7,12 @@ "use strict"; -require('yargonaut') - .style('green') - .style('yellow', "required") - .style('cyan', "Positionals:") - .helpStyle('cyan') - .errorsStyle('red.bold'); +require("yargonaut") + .style("green") + .style("yellow", "required") + .style("cyan", "Positionals:") + .helpStyle("cyan") + .errorsStyle("red.bold"); const chalk = require("chalk"); const yargs = require("yargs"); @@ -22,5 +22,9 @@ const argv = yargs .usage(`\n${chalk.bold("$0")} ${chalk.yellow("")}`) .command(require("../scripts/start")) .command(require("../scripts/build")) - .epilogue(`${chalk.cyan("For more information on a particular command, run:")}\n\n ${chalk.bold("backend-webpack-tools")} ${chalk.yellow("")} ${chalk.green("--help")}`) + .epilogue( + `${chalk.cyan("For more information on a particular command, run:")}\n\n ${chalk.bold("backend-webpack-tools")} ${chalk.yellow("")} ${ + chalk.green("--help") + }`, + ) .argv; diff --git a/tools/backend-webpack/config/getWebpackConfig.js b/tools/backend-webpack/config/getWebpackConfig.js index 83b89f13e8a7..108fdbfa0f32 100644 --- a/tools/backend-webpack/config/getWebpackConfig.js +++ b/tools/backend-webpack/config/getWebpackConfig.js @@ -45,8 +45,8 @@ function getWebpackConfig(srcFile, outDir, profile) { electron: true, }, }; -}; +} module.exports = { getWebpackConfig, -} \ No newline at end of file +}; diff --git a/tools/backend-webpack/scripts/build.js b/tools/backend-webpack/scripts/build.js index 3a3058127a9b..82d6c953ece2 100644 --- a/tools/backend-webpack/scripts/build.js +++ b/tools/backend-webpack/scripts/build.js @@ -6,28 +6,30 @@ const chalk = require("chalk"); exports.command = "build"; -exports.describe = chalk.bold(`Runs a production webpack build. This means bundling JavaScript and copying "external" modules to the output directory.`); +exports.describe = chalk.bold( + `Runs a production webpack build. This means bundling JavaScript and copying "external" modules to the output directory.`, +); exports.builder = (yargs) => yargs.strict(true) .options({ "source": { alias: "s", type: "string", - describe: "The main entrypoint for webpack." + describe: "The main entrypoint for webpack.", }, "outDir": { alias: "o", type: "string", - describe: "The directory where bundle should be emitted." + describe: "The directory where bundle should be emitted.", }, "sourceMap": { type: "boolean", - describe: "Create sourcemaps for bundle." + describe: "Create sourcemaps for bundle.", }, "profile": { type: "boolean", - describe: "Enable webpack profiling and output stats files for analyzing bundle." - } + describe: "Enable webpack profiling and output stats files for analyzing bundle.", + }, }) .demandOption(["source", "outDir"]); diff --git a/tools/backend-webpack/scripts/start.js b/tools/backend-webpack/scripts/start.js index 2f5d029014fb..772bdb819c78 100644 --- a/tools/backend-webpack/scripts/start.js +++ b/tools/backend-webpack/scripts/start.js @@ -8,7 +8,7 @@ const path = require("path"); const chalk = require("chalk"); const { spawn, - handleInterrupts + handleInterrupts, } = require("@itwin/build-tools/scripts/utils/simpleSpawn"); exports.command = "start"; @@ -18,26 +18,26 @@ exports.builder = (yargs) => "source": { alias: "s", type: "string", - describe: "The main entrypoint for webpack." + describe: "The main entrypoint for webpack.", }, "outDir": { alias: "o", type: "string", - describe: "The directory where bundle should be emitted." + describe: "The directory where bundle should be emitted.", }, "electron": { alias: "e", type: "boolean", - describe: `Launch the output bundle with electron.` + describe: `Launch the output bundle with electron.`, }, "node": { alias: "n", type: "boolean", - describe: `Launch the output bundle with node.` + describe: `Launch the output bundle with node.`, }, "execArgs": { type: "string", - describe: `Additional arguments to be passed to node (or electron).` + describe: `Additional arguments to be passed to node (or electron).`, }, }) .demandOption(["source", "outDir"]); @@ -62,13 +62,32 @@ exports.handler = async (argv) => { const quote = (s) => `"${s}"`; if (argv.node) { - args.push(["node", require.resolve("nodemon/bin/nodemon"), "--max-http-header-size=16000", "--no-colors", "--watch", outFile, ...execArgs, outFile]); + args.push([ + "node", + require.resolve("nodemon/bin/nodemon"), + "--max-http-header-size=16000", + "--no-colors", + "--watch", + outFile, + ...execArgs, + outFile, + ]); names.push("node"); colors.push("cyan"); } if (argv.electron) { - args.push(["node", require.resolve("nodemon/bin/nodemon"), "--max-http-header-size=16000", "--no-colors", "--watch", outFile, "node_modules/electron/cli.js", ...execArgs, outFile]); + args.push([ + "node", + require.resolve("nodemon/bin/nodemon"), + "--max-http-header-size=16000", + "--no-colors", + "--watch", + outFile, + "node_modules/electron/cli.js", + ...execArgs, + outFile, + ]); names.push("electron"); colors.push("magenta"); } @@ -77,11 +96,14 @@ exports.handler = async (argv) => { spawn("node", [ require.resolve("concurrently"), ...args.map((a) => quote(a.join(" "))), - "--color", "-c", colors.join(","), - "--names", names.join(",") + "--color", + "-c", + colors.join(","), + "--names", + names.join(","), ]); } }; // This is required to correctly handle SIGINT on windows. -handleInterrupts(); \ No newline at end of file +handleInterrupts(); diff --git a/tools/backend-webpack/scripts/utils/initialize.js b/tools/backend-webpack/scripts/utils/initialize.js index 65df76eed1fe..a42f76ada3ef 100644 --- a/tools/backend-webpack/scripts/utils/initialize.js +++ b/tools/backend-webpack/scripts/utils/initialize.js @@ -17,9 +17,9 @@ function init(NODE_ENV) { // Makes the script crash on unhandled rejections instead of silently // ignoring them. In the future, promise rejections that are not handled will // terminate the Node.js process with a non-zero exit code. - process.on("unhandledRejection", err => { + process.on("unhandledRejection", (err) => { throw err; }); } -module.exports = init; \ No newline at end of file +module.exports = init; diff --git a/tools/backend-webpack/scripts/utils/webpackWrappers.js b/tools/backend-webpack/scripts/utils/webpackWrappers.js index e5f9fa20410c..e4c27ea9178f 100644 --- a/tools/backend-webpack/scripts/utils/webpackWrappers.js +++ b/tools/backend-webpack/scripts/utils/webpackWrappers.js @@ -7,7 +7,7 @@ const webpack = require("webpack"); const chalk = require("chalk"); const { PrettyLoggingPlugin } = require("@itwin/core-webpack-tools"); -function createCompiler(webpack, config, name, description, onSuccess = function () { }) { +function createCompiler(webpack, config, name, description, onSuccess = function() {}) { try { config.plugins.push(new PrettyLoggingPlugin(name, description, onSuccess)); compiler = webpack(config); @@ -34,7 +34,7 @@ async function watchBackend(config) { function runWebpackAsync(compiler) { return new Promise((resolve, reject) => { - compiler.run((err, stats) => (err) ? reject(err) : resolve(stats)) + compiler.run((err, stats) => err ? reject(err) : resolve(stats)); }); } @@ -58,4 +58,4 @@ module.exports = { buildBackend, watchBackend, saveJsonStats, -}; \ No newline at end of file +}; diff --git a/tools/build/bin/betools.js b/tools/build/bin/betools.js index 7439f3e1f74a..64078dff3cb7 100755 --- a/tools/build/bin/betools.js +++ b/tools/build/bin/betools.js @@ -5,7 +5,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -"use strict" +"use strict"; const yargs = require("yargs"); var path = require("path"); var child_process = require("child_process"); @@ -14,115 +14,130 @@ yargs.strict(true) .wrap(Math.min(150, yargs.terminalWidth())) .version("2.0.0") .usage("Bentley Scripts Utility\n\n These scripts consist of several standard npm tasks an app may want to make use of.") - .command("test", false, {}, () => { testCommand() }) - .command("test-tsnode", false, {}, () => { testCommand() }) - .command("docs", "Generate TypeDoc documentation by using the provided parameters to pass to TypeDoc. Supports generating html TypeScript documentation as well as a json representation of the documentation.", - function (yargs) { + .command("test", false, {}, () => { + testCommand(); + }) + .command("test-tsnode", false, {}, () => { + testCommand(); + }) + .command( + "docs", + "Generate TypeDoc documentation by using the provided parameters to pass to TypeDoc. Supports generating html TypeScript documentation as well as a json representation of the documentation.", + function(yargs) { return yargs.options({ "source": { - describe: "Specify the TypeScript source directory" + describe: "Specify the TypeScript source directory", }, "out": { - describe: "Specify the directory of the html output" + describe: "Specify the directory of the html output", }, "json": { - describe: "Specify the directory and filename of the json output" + describe: "Specify the directory and filename of the json output", }, "baseUrl": { - describe: "Specify a baseUrl to resolve modules" + describe: "Specify a baseUrl to resolve modules", }, "includes": { - describe: "Specify a baseUrl to resolve modules" + describe: "Specify a baseUrl to resolve modules", }, "excludes": { - describe: "Specify a directory, filename, or pattern to be excluded" + describe: "Specify a directory, filename, or pattern to be excluded", }, "excludeGlob": { - describe: "Specify a directory, filename, or pattern to be excluded" + describe: "Specify a directory, filename, or pattern to be excluded", }, "testExcludeGlob": { - describe: "Specify a directory, filename, or pattern to exclude tests. Default value: '**/*test*/**/*'" + describe: "Specify a directory, filename, or pattern to exclude tests. Default value: '**/*test*/**/*'", }, "tsIndexFile": { - describe: "The barrel file containing the module documentation. This file is copied to the output folder for parsing." + describe: "The barrel file containing the module documentation. This file is copied to the output folder for parsing.", }, "onlyJson": { - describe: "Specify a baseUrl to resolve modules" - } - }) - }, - (argv) => { docsCommand(argv) }) - .command("extract", "Extract sample code from test files in a specific directory", - function (yargs) { - return yargs.options({ - "extractFrom": { - describe: "The path at which the sample code files are located" - }, - "out": { - describe: "The path at which to output the selected code" + describe: "Specify a baseUrl to resolve modules", }, - "fileExt": { - describe: "The extension of the files to include" - }, - "recursive": { - alias: "r", - describe: "Recursively search subdirectories from" - } - }) + }); + }, + (argv) => { + docsCommand(argv); }, - (argv) => { extractCommand(argv) }) - .command("extract-api", "Extracts the API of the Typescript library starting from an entry file with a default presets. Powered by @microsoft/api-extractor (https://api-extractor.com)", - function (yargs) { + ) + .command("extract", "Extract sample code from test files in a specific directory", function(yargs) { + return yargs.options({ + "extractFrom": { + describe: "The path at which the sample code files are located", + }, + "out": { + describe: "The path at which to output the selected code", + }, + "fileExt": { + describe: "The extension of the files to include", + }, + "recursive": { + alias: "r", + describe: "Recursively search subdirectories from", + }, + }); + }, (argv) => { + extractCommand(argv); + }) + .command( + "extract-api", + "Extracts the API of the Typescript library starting from an entry file with a default presets. Powered by @microsoft/api-extractor (https://api-extractor.com)", + function(yargs) { return yargs.options({ "entry": { - describe: "The main Typescript entry point for the library which is compiled to the 'main' field in the package.json" + describe: "The main Typescript entry point for the library which is compiled to the 'main' field in the package.json", }, "ignoreMissingTags": { - describe: "Turns off the 'ae-missing-release-tag' option which returns an error when a missing release tag is detected" + describe: "Turns off the 'ae-missing-release-tag' option which returns an error when a missing release tag is detected", }, "apiReportFolder": { - describe: "Directory for the API report. Defaults to `/common/api`." + describe: "Directory for the API report. Defaults to `/common/api`.", }, "apiReportTempFolder": { - describe: "Directory for the API report. Defaults to `/temp/api`." + describe: "Directory for the API report. Defaults to `/temp/api`.", }, "apiSummaryFolder": { - describe: "Directory for the API summary. Defaults to `/common/api/summary`." + describe: "Directory for the API summary. Defaults to `/common/api/summary`.", }, "includeUnexportedApis": { boolean: true, - describe: "If this flag is set, then APIs that are unexported, but still indirectly accessible via exported APIs, will also be included to the API report. Defaults to `false`" - }, - }) - }, - (argv) => { extractApiCommand(argv) }) - .command("pseudolocalize", "Pseudo-localizes an english localization JSON file.", - function (yargs) { - return yargs.options({ - "englishDir": { - describe: "The path to the English localization folder. Default is `./public/locales/en`" + describe: + "If this flag is set, then APIs that are unexported, but still indirectly accessible via exported APIs, will also be included to the API report. Defaults to `false`", }, - "out": { - describe: "The output path to put the pseudo-localized files. Default is `./public/locales/en-pseudo`" - } - }) + }); }, - (argv) => { pseudolocalizeCommand(argv) }) - .command("copy-assets", "copy assets from @itwin or @bentley dependencies into a destination directory", - function (yargs) { - return yargs.options({ - "packageJsonDir": { - describe: "The path at which the package.json listing deps that need their assets copied can be found. defaults to '.'" - }, - "nodeModulesDir": { - describe: "The path to the node_modules directory where the deps that need their assets copied can be found. defaults to '.'" - }, - "destinationDir": { - describe: "the location to copy the assets to. defaults to './lib/assets'" - }, - }) + (argv) => { + extractApiCommand(argv); }, - (argv) => { copyAssetsCommand(argv) }) + ) + .command("pseudolocalize", "Pseudo-localizes an english localization JSON file.", function(yargs) { + return yargs.options({ + "englishDir": { + describe: "The path to the English localization folder. Default is `./public/locales/en`", + }, + "out": { + describe: "The output path to put the pseudo-localized files. Default is `./public/locales/en-pseudo`", + }, + }); + }, (argv) => { + pseudolocalizeCommand(argv); + }) + .command("copy-assets", "copy assets from @itwin or @bentley dependencies into a destination directory", function(yargs) { + return yargs.options({ + "packageJsonDir": { + describe: "The path at which the package.json listing deps that need their assets copied can be found. defaults to '.'", + }, + "nodeModulesDir": { + describe: "The path to the node_modules directory where the deps that need their assets copied can be found. defaults to '.'", + }, + "destinationDir": { + describe: "the location to copy the assets to. defaults to './lib/assets'", + }, + }); + }, (argv) => { + copyAssetsCommand(argv); + }) .help() .argv; @@ -146,9 +161,19 @@ function docsCommand(options) { const testExcludeGlobOpt = options.testExcludeGlob ? ["--testExcludeGlob", options.testExcludeGlob] : []; const indexFileOpt = options.tsIndexFile ? ["--tsIndexFile", options.tsIndexFile] : []; const onlyJsonOpt = options.onlyJson ? ["--onlyJson"] : []; - exec("node", [getScriptPath("docs.js"), - ...sourceOpt, ...outOpt, ...jsonOpt, ...baseUrlOpt, ...includesOpt, - ...excludesOpt, ...excludesGlobOpt, ...testExcludeGlobOpt, ...indexFileOpt, ...onlyJsonOpt]); + exec("node", [ + getScriptPath("docs.js"), + ...sourceOpt, + ...outOpt, + ...jsonOpt, + ...baseUrlOpt, + ...includesOpt, + ...excludesOpt, + ...excludesGlobOpt, + ...testExcludeGlobOpt, + ...indexFileOpt, + ...onlyJsonOpt, + ]); } function extractCommand(options) { @@ -166,7 +191,15 @@ function extractApiCommand(options) { const apiReportTempFolderOpt = options.apiReportTempFolder ? ["--apiReportTempFolder", options.apiReportTempFolder] : []; const apiSummaryFolderOpt = options.apiSummaryFolder ? ["--apiSummaryFolder", options.apiSummaryFolder] : []; const includeUnexportedApisOpt = options.includeUnexportedApis ? ["--includeUnexportedApis"] : []; - exec("node", [getScriptPath("extract-api.js"), ...entryOpt, ...ignoreTagsOpt, ...apiReportFolderOpt, ...apiReportTempFolderOpt, ...apiSummaryFolderOpt, ...includeUnexportedApisOpt]); + exec("node", [ + getScriptPath("extract-api.js"), + ...entryOpt, + ...ignoreTagsOpt, + ...apiReportFolderOpt, + ...apiReportTempFolderOpt, + ...apiSummaryFolderOpt, + ...includeUnexportedApisOpt, + ]); } function pseudolocalizeCommand(options) { @@ -184,9 +217,9 @@ function copyAssetsCommand(options) { function exec(cmd, args) { console.log("Running command:"); - console.log(`${cmd} ${args.join(' ')}`); + console.log(`${cmd} ${args.join(" ")}`); try { - return child_process.execFileSync(cmd, args, { encoding: "utf8", stdio: 'inherit' }); + return child_process.execFileSync(cmd, args, { encoding: "utf8", stdio: "inherit" }); } catch (error) { if (error.status) process.exit(error.status); diff --git a/tools/build/eslint.config.js b/tools/build/eslint.config.js index 555828931b3c..7f912c1bed11 100644 --- a/tools/build/eslint.config.js +++ b/tools/build/eslint.config.js @@ -8,7 +8,7 @@ module.exports = [ { files: ["**/*.ts"], rules: { - "deprecation/deprecation": "off" - } - } + "deprecation/deprecation": "off", + }, + }, ]; diff --git a/tools/build/scripts/config/paths.js b/tools/build/scripts/config/paths.js index 3db77391865c..281f5644aae6 100644 --- a/tools/build/scripts/config/paths.js +++ b/tools/build/scripts/config/paths.js @@ -2,26 +2,26 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -'use strict'; +"use strict"; -const path = require('path'); -const fs = require('fs-extra'); +const path = require("path"); +const fs = require("fs-extra"); // Make sure any symlinks in the project folder are resolved: const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = relativePath => path.resolve(appDirectory, relativePath); +const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath); module.exports = { - appSrc: resolveApp('src'), - appTest: resolveApp('src/test'), - appLib: resolveApp('lib'), - appLibPublic: resolveApp('lib/cjs/public'), - appLibTests: resolveApp('lib/cjs/test'), - appPublic: resolveApp('public'), - appDocs: resolveApp('lib/cjs/docs'), - appJsonDocs: resolveApp('lib/cjs/docs/json/file.json'), - appJUnitTestResults: resolveApp('lib/test/junit_results.xml'), - libExtract: resolveApp('lib/cjs/extract'), - appLocalesEnglish: resolveApp('public/locales/en'), - appLocalesPseudolocalize: resolveApp('public/locales/en-pseudo'), + appSrc: resolveApp("src"), + appTest: resolveApp("src/test"), + appLib: resolveApp("lib"), + appLibPublic: resolveApp("lib/cjs/public"), + appLibTests: resolveApp("lib/cjs/test"), + appPublic: resolveApp("public"), + appDocs: resolveApp("lib/cjs/docs"), + appJsonDocs: resolveApp("lib/cjs/docs/json/file.json"), + appJUnitTestResults: resolveApp("lib/test/junit_results.xml"), + libExtract: resolveApp("lib/cjs/extract"), + appLocalesEnglish: resolveApp("public/locales/en"), + appLocalesPseudolocalize: resolveApp("public/locales/en-pseudo"), }; diff --git a/tools/build/scripts/copy-assets.js b/tools/build/scripts/copy-assets.js index aee1fe23dd01..512cf91d1520 100644 --- a/tools/build/scripts/copy-assets.js +++ b/tools/build/scripts/copy-assets.js @@ -3,7 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -"use strict" +"use strict"; const argv = require("yargs").argv; const fs = require("fs-extra"); @@ -31,18 +31,18 @@ const getBentleyPackageDeps = () => { } return Array.from(deps); -} +}; const copySync = (fromPath, toPath) => { if (fs.existsSync(fromPath)) { try { fs.copySync(fromPath, toPath); - console.log(`successfully copied from ${fromPath} to ${toPath}`) + console.log(`successfully copied from ${fromPath} to ${toPath}`); } catch (ex) { console.error(`failed to copy from ${fromPath} to ${toPath}`, ex); } } -} +}; // finds all applicable dependences with assets and copies them into the destination folder const copyBentleyPackageDepAssets = () => { @@ -55,7 +55,7 @@ const copyBentleyPackageDepAssets = () => { copySync(path.join(nodeModulesDir, "node_modules", target, "lib/assets"), destinationDir); copySync(path.join(nodeModulesDir, "node_modules", target, "lib/cjs/assets"), destinationDir); } -} +}; copyBentleyPackageDepAssets(); console.log("finished copying assets"); diff --git a/tools/build/scripts/docs.js b/tools/build/scripts/docs.js index 2f042d49c59d..1b9bc0fff1d3 100644 --- a/tools/build/scripts/docs.js +++ b/tools/build/scripts/docs.js @@ -18,7 +18,7 @@ const argv = require("yargs").argv; // Makes the script crash on unhandled rejections instead of silently // ignoring them. In the future, promise rejections that are not handled will // terminate the Node.js process with a non-zero exit code. -process.on("unhandledRejection", err => { +process.on("unhandledRejection", (err) => { throw err; }); @@ -30,19 +30,20 @@ const baseUrlOptions = (argv.baseUrl === undefined) ? [] : ["--baseUrl", argv.ba const includeOptions = (argv.includes === undefined) ? [] : ["--includes", argv.includes]; const testExclude = argv.testExcludeGlob ?? "**/*test*/**/*"; -const excludeInternalFolders = "**/internal/**/*" +const excludeInternalFolders = "**/internal/**/*"; let excludeList = `**/node_modules/**/*,${testExclude},${excludeInternalFolders}`; if (argv.excludes !== undefined) excludeList += ",**/" + argv.excludes + "/**/*"; if (argv.excludeGlob !== undefined) excludeList += "," + argv.excludeGlob; -excludeList = excludeList.replace(/,/g, ',--exclude,') +excludeList = excludeList.replace(/,/g, ",--exclude,"); const excludeArray = excludeList.split(","); excludeArray.unshift("--exclude"); let outputOptions = [ - "--json", json + "--json", + json, ]; if (argv.onlyJson === undefined) @@ -54,12 +55,14 @@ const options = [ "--excludePrivate", "--hideGenerator", "--logLevel", - "Error" + "Error", ]; const pluginOptions = [ - "--plugin", "typedoc-plugin-merge-modules", - "--mergeModulesMergeMode", "module", + "--plugin", + "typedoc-plugin-merge-modules", + "--mergeModulesMergeMode", + "module", ]; if (argv.name) options.push("--name", argv.name); @@ -67,14 +70,17 @@ if (argv.name) options.push("--name", argv.name); if (argv.theme) options.push("--theme", argv.theme); const args = [ - "--entryPointStrategy", "expand", path.resolve(process.cwd(), source), + "--entryPointStrategy", + "expand", + path.resolve(process.cwd(), source), ...options, ...excludeArray, ...outputOptions, - "--readme", readmeOption, + "--readme", + readmeOption, ...pluginOptions, ...baseUrlOptions, - ...includeOptions + ...includeOptions, ]; console.log("Arguments to TypeDoc: " + JSON.stringify(args, null, 2)); @@ -84,12 +90,12 @@ spawn(require.resolve(".bin/typedoc"), args).then((code) => { const outputDir = path.parse(json).dir; if (argv.tsIndexFile) { cpx.copySync(path.join(source, argv.tsIndexFile), outputDir); - fs.renameSync(path.join(outputDir, argv.tsIndexFile), path.join(outputDir, 'index.ts')); + fs.renameSync(path.join(outputDir, argv.tsIndexFile), path.join(outputDir, "index.ts")); } // Copy CHANGELOG.json to json output folder - if (fs.existsSync(path.join(process.cwd(), 'CHANGELOG.json'))) { - cpx.copySync(path.join(process.cwd(), 'CHANGELOG.json'), outputDir); + if (fs.existsSync(path.join(process.cwd(), "CHANGELOG.json"))) { + cpx.copySync(path.join(process.cwd(), "CHANGELOG.json"), outputDir); } // Append the directory of the package, version and repository URL to the output @@ -100,10 +106,10 @@ spawn(require.resolve(".bin/typedoc"), args).then((code) => { if (tagErrors.toString()) { console.error(`JSON contains invalid tags: ${JSON.stringify(tagErrors)}`); fs.unlink(json); - console.log(`JSON removed from ${json}`) + console.log(`JSON removed from ${json}`); code = 5; } } - process.exit(code) + process.exit(code); }); handleInterrupts(); diff --git a/tools/build/scripts/extract-api-summary.js b/tools/build/scripts/extract-api-summary.js index 10ae766decb0..b905d12012e0 100644 --- a/tools/build/scripts/extract-api-summary.js +++ b/tools/build/scripts/extract-api-summary.js @@ -7,7 +7,7 @@ // The script parses api.md files, generated by the extract-api.js script (and subsequently the api-extractor.com tool), and extracts the high level API items // into a csv format for easier review. -const path = require('path'); +const path = require("path"); const argv = require("yargs").argv; const fs = require("fs-extra"); @@ -17,7 +17,7 @@ if (undefined === argv.apiSignature) { } if (!fs.existsSync(argv.apiSignature)) { - console.log("The api signature file does not exist.") + console.log("The api signature file does not exist."); return; } @@ -34,7 +34,7 @@ if (undefined !== argv.gatherFullReport) // create output file const apiSignatureFileName = path.parse(argv.apiSignature).name; -const sigFileName = apiSignatureFileName.substring(0, apiSignatureFileName.lastIndexOf('.')); +const sigFileName = apiSignatureFileName.substring(0, apiSignatureFileName.lastIndexOf(".")); const sigFilePath = path.join(argv.outDir, `${shouldGenerateFullReport ? "summary" : sigFileName}.exports.csv`); const outputLines = []; @@ -52,11 +52,11 @@ if (shouldGenerateFullReport) { } // Open up the signature file -fs.readFile(argv.apiSignature, function (error, data) { +fs.readFile(argv.apiSignature, function(error, data) { if (error) { throw error; } let previousLines = []; - data.toString().split("\n").forEach(function (line, index, arr) { + data.toString().split("\n").forEach(function(line, index, arr) { if (index === arr.length - 1 && line === "") { return; } if (previousLines.length !== 0) { diff --git a/tools/build/scripts/extract-api.js b/tools/build/scripts/extract-api.js index 58fd5739bdf1..95ea9c743240 100644 --- a/tools/build/scripts/extract-api.js +++ b/tools/build/scripts/extract-api.js @@ -15,13 +15,13 @@ if (argv.entry === undefined) { return; } -const isCI = (process.env.TF_BUILD); +const isCI = process.env.TF_BUILD; const entryPointFileName = argv.entry; const ignoreMissingTags = argv.ignoreMissingTags; const includeUnexportedApis = argv.includeUnexportedApis; // Resolves the root of the Rush repo -const resolveRoot = relativePath => { +const resolveRoot = (relativePath) => { // recurse until you find the "rush.json" const parts = paths.appSrc.split(path.sep).reverse(); while (parts.length > 0) { @@ -47,7 +47,7 @@ const config = { $schema: "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", projectFolder: "../../", compiler: { - tsconfigFilePath: "/tsconfig.json" + tsconfigFilePath: "/tsconfig.json", }, mainEntryPointFilePath: `${entryPointFileName}.d.ts`, apiReport: { @@ -57,51 +57,51 @@ const config = { includeForgottenExports: !!includeUnexportedApis, }, docModel: { - enabled: false + enabled: false, }, dtsRollup: { - enabled: false + enabled: false, }, tsdocMetadata: { - enabled: false + enabled: false, }, messages: { tsdocMessageReporting: { default: { - logLevel: "none" - } + logLevel: "none", + }, }, extractorMessageReporting: { default: { logLevel: "error", - addToApiReportFile: false + addToApiReportFile: false, }, "ae-incompatible-release-tags": { logLevel: "error", - addToApiReportFile: false + addToApiReportFile: false, }, "ae-missing-release-tag": { logLevel: ignoreMissingTags ? "none" : "error", - addToApiReportFile: false + addToApiReportFile: false, }, "ae-internal-missing-underscore": { logLevel: "none", - addToApiReportFile: false + addToApiReportFile: false, }, "ae-forgotten-export": { logLevel: "none", - addToApiReportFile: false + addToApiReportFile: false, }, "ae-unresolved-inheritdoc-reference": { logLevel: "error", - addToApiReportFile: true + addToApiReportFile: true, }, "ae-unresolved-inheritdoc-base": { logLevel: "error", - addToApiReportFile: true - } - } - } + addToApiReportFile: true, + }, + }, + }, }; if (!fs.existsSync("lib")) { @@ -114,7 +114,8 @@ fs.writeFileSync(configFileName, JSON.stringify(config, null, 2)); const args = [ "run", - "-c", configFileName + "-c", + configFileName, ]; if (!isCI) args.push("-l"); @@ -129,8 +130,10 @@ spawn(require.resolve(".bin/api-extractor"), args).then((code) => { const extractSummaryArgs = [ path.resolve(__dirname, "extract-api-summary.js"), - "--apiSignature", path.resolve(path.join(apiReportFolder, `${entryPointFileName}.api.md`)), - "--outDir", path.resolve(apiSummaryFolder), + "--apiSignature", + path.resolve(path.join(apiReportFolder, `${entryPointFileName}.api.md`)), + "--outDir", + path.resolve(apiSummaryFolder), ]; spawn("node", extractSummaryArgs).then((code) => { diff --git a/tools/build/scripts/pseudolocalize.js b/tools/build/scripts/pseudolocalize.js index b1f736be2747..03d5a2be1036 100644 --- a/tools/build/scripts/pseudolocalize.js +++ b/tools/build/scripts/pseudolocalize.js @@ -5,15 +5,15 @@ "use strict"; /** Generates pseudo localization files from the en localization JSON files. -*/ + */ function pseudoLocalizeObject(objIn) { let objOut = {}; for (let prop in objIn) { if (objIn.hasOwnProperty(prop)) { if (typeof objIn[prop] === "string") { - objOut[prop] = pseudoLocalize(objIn[prop]) + objOut[prop] = pseudoLocalize(objIn[prop]); } else if (typeof objIn[prop] === "object") { - objOut[prop] = pseudoLocalizeObject(objIn[prop]) + objOut[prop] = pseudoLocalizeObject(objIn[prop]); } } } @@ -54,11 +54,11 @@ function pseudoLocalize(inputString) { let nextChar = ((iChar + 1) < inputString.length) ? inputString.charAt(iChar + 1) : 0; // handle the {{ and }} delimiters for placeholders - don't want to do anything to characters in between. - if (('{' === thisChar) && ('{' === nextChar)) { + if (("{" === thisChar) && ("{" === nextChar)) { inReplace++; iChar++; outString = outString.concat("{{"); - } else if (('}' === thisChar) && ('}' === nextChar) && (inReplace > 0)) { + } else if (("}" === thisChar) && ("}" === nextChar) && (inReplace > 0)) { inReplace--; iChar++; outString = outString.concat("}}"); @@ -91,7 +91,7 @@ const outDir = (argv.out === undefined) ? paths.appLocalesPseudolocalize : argv. try { fs.mkdirpSync(outDir); } catch (e) { - console.log(e);// do nothing + console.log(e); // do nothing } for (const inputFileName of inputFileNames) { diff --git a/tools/build/scripts/utils/addPackageMetadata.js b/tools/build/scripts/utils/addPackageMetadata.js index 1bdcf31ce569..1860e1420eb4 100644 --- a/tools/build/scripts/utils/addPackageMetadata.js +++ b/tools/build/scripts/utils/addPackageMetadata.js @@ -12,13 +12,13 @@ const rootPackageJson = path.join( process.env.NODE_PROJECT_ROOT_DIRECTORY || process.env.RUSHSTACK_FILE_ERROR_BASE_FOLDER || "../../../../", - "package.json" + "package.json", ); // Check if path to root package.json is valid. const rootPackageJsonPath = require.resolve(rootPackageJson); -//Find the package.json of the project and retrieve the version and repository URL +// Find the package.json of the project and retrieve the version and repository URL const packageJsonPath = path.join(process.cwd(), "package.json"); const packageJson = JSON.parse(FS.readFileSync(packageJsonPath)); const version = packageJson.version; diff --git a/tools/build/scripts/utils/recursiveReaddir.js b/tools/build/scripts/utils/recursiveReaddir.js index fb853048dc79..61ee331d933f 100644 --- a/tools/build/scripts/utils/recursiveReaddir.js +++ b/tools/build/scripts/utils/recursiveReaddir.js @@ -2,7 +2,7 @@ const fs = require("fs"); const p = require("path"); function matchesFile(ignorePath) { - return function (path, stats) { + return function(path, stats) { return stats.isFile() && ignorePath === path; }; } @@ -22,8 +22,8 @@ function readdir(path, ignores, callback) { } if (!callback) { - return new Promise(function (resolve, reject) { - readdir(path, ignores || [], function (err, data) { + return new Promise(function(resolve, reject) { + readdir(path, ignores || [], function(err, data) { if (err) { reject(err); } else { @@ -37,7 +37,7 @@ function readdir(path, ignores, callback) { let list = []; - fs.readdir(path, function (err, files) { + fs.readdir(path, function(err, files) { if (err) { return callback(err); } @@ -48,15 +48,15 @@ function readdir(path, ignores, callback) { return callback(null, list); } - files.forEach(function (file) { + files.forEach(function(file) { const filePath = p.join(path, file); - fs.stat(filePath, function (_err, stats) { + fs.stat(filePath, function(_err, stats) { if (_err) { return callback(_err); } if ( - ignores.some(function (matcher) { + ignores.some(function(matcher) { return matcher(filePath, stats); }) ) { @@ -68,7 +68,7 @@ function readdir(path, ignores, callback) { } if (stats.isDirectory()) { - readdir(filePath, ignores, function (__err, res) { + readdir(filePath, ignores, function(__err, res) { if (__err) { return callback(__err); } @@ -92,5 +92,5 @@ function readdir(path, ignores, callback) { } module.exports = { - readDirectory: readdir + readDirectory: readdir, }; diff --git a/tools/build/scripts/utils/simpleSpawn.js b/tools/build/scripts/utils/simpleSpawn.js index 35adc7fc6a67..93b227dc711b 100644 --- a/tools/build/scripts/utils/simpleSpawn.js +++ b/tools/build/scripts/utils/simpleSpawn.js @@ -15,16 +15,18 @@ function simpleSpawn(cmd, args, cwd, env = {}) { const child = spawn(cmd, args, { cwd: cwd, env: { FORCE_COLOR: "1", ...env, ...process.env }, - stdio: "pipe" + stdio: "pipe", }); child.stdout.on("data", (data) => { process.stdout.write(data); - }) + }); child.stderr.on("data", (data) => { process.stderr.write(data); - }) - child.on("error", function (data) { console.log(chalk.red(data)); }); + }); + child.on("error", function(data) { + console.log(chalk.red(data)); + }); child.on("close", (code) => resolve(code)); simpleSpawn.children.push(child); }); @@ -37,7 +39,7 @@ function simpleSpawnSync(cmd, args, cwd, env = {}) { const child = spawn.sync(cmd, args, { cwd: cwd, env: { FORCE_COLOR: "1", ...env, ...process.env }, - stdio: "inherit" + stdio: "inherit", }); if (child.status !== 0) { @@ -46,15 +48,17 @@ function simpleSpawnSync(cmd, args, cwd, env = {}) { } simpleSpawn.children = []; -simpleSpawn.killAll = async function () { +simpleSpawn.killAll = async function() { const promises = []; simpleSpawn.children.forEach((proc) => { - promises.push(new Promise((resolve) => { - kill(proc.pid, undefined, resolve); - })); + promises.push( + new Promise((resolve) => { + kill(proc.pid, undefined, resolve); + }), + ); }); await Promise.all(promises); -} +}; function handleInterrupts(callback) { if (!callback) { @@ -68,12 +72,12 @@ function handleInterrupts(callback) { require("readline") .createInterface({ input: process.stdin, - output: process.stdout + output: process.stdout, }); } - ["SIGINT", "SIGTERM"].forEach(function (sig) { - process.on(sig, function () { + ["SIGINT", "SIGTERM"].forEach(function(sig) { + process.on(sig, function() { callback(); }); }); @@ -82,5 +86,5 @@ function handleInterrupts(callback) { module.exports = { spawn: simpleSpawn, spawnSync: simpleSpawnSync, - handleInterrupts -}; \ No newline at end of file + handleInterrupts, +}; diff --git a/tools/build/scripts/utils/utils.js b/tools/build/scripts/utils/utils.js index 4845b681ccf7..a4bd672e3a9b 100644 --- a/tools/build/scripts/utils/utils.js +++ b/tools/build/scripts/utils/utils.js @@ -18,7 +18,7 @@ function logBuildError(msg) { function failBuild() { if (process.env.TF_BUILD) { - console.error("##vso[task.complete result=Failed;]DONE") + console.error("##vso[task.complete result=Failed;]DONE"); process.exit(0); } else { process.exit(1); @@ -35,5 +35,5 @@ module.exports = { logBuildWarning, logBuildError, failBuild, - throwAfterTimeout -} \ No newline at end of file + throwAfterTimeout, +}; diff --git a/tools/build/scripts/utils/validateTags.js b/tools/build/scripts/utils/validateTags.js index 8542c9eeb0bd..637e887cfbc8 100644 --- a/tools/build/scripts/utils/validateTags.js +++ b/tools/build/scripts/utils/validateTags.js @@ -3,7 +3,7 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -const FS = require('fs-extra'); +const FS = require("fs-extra"); const validTags = [ "see", "note", @@ -38,20 +38,20 @@ function parseFile(path) { let allTags = {}; if (FS.existsSync(path) && FS.statSync(path).isFile()) { - const contents = FS.readFileSync(path, 'utf-8'); + const contents = FS.readFileSync(path, "utf-8"); let jsonContents = JSON.parse(contents); - let tags = findValues(jsonContents, 'tags'); + let tags = findValues(jsonContents, "tags"); for (let j = 0; j < tags.length; j++) { for (let i = 0; i < tags[j].length; i++) - allTags[tags[j][i]['tag']] = allTags[tags[j][i]['tag']] ? allTags[tags[j][i]['tag']] + 1 : 1; + allTags[tags[j][i]["tag"]] = allTags[tags[j][i]["tag"]] ? allTags[tags[j][i]["tag"]] + 1 : 1; } let invalidTagObjects = []; for (tag in allTags) { if (!validTags.includes(tag)) - invalidTagObjects.push(tag, findSource(jsonContents, 'tag', tag)); + invalidTagObjects.push(tag, findSource(jsonContents, "tag", tag)); } return invalidTagObjects; } @@ -93,20 +93,20 @@ function findSourceHelper(obj, key, value, list) { return list; } - //Look for tag in signature or in comment - if (obj['signatures']) { - if (obj['signatures'][0] && obj['signatures'][0]['comment'] && obj['signatures'][0]['comment']['tags']) { - for (let tag in obj['signatures'][0]['comment']['tags']) { - if (obj['signatures'][0]['comment']['tags'][tag].tag === value && obj['sources'] && obj['sources'][0]) - list.push(obj['sources'][0]); + // Look for tag in signature or in comment + if (obj["signatures"]) { + if (obj["signatures"][0] && obj["signatures"][0]["comment"] && obj["signatures"][0]["comment"]["tags"]) { + for (let tag in obj["signatures"][0]["comment"]["tags"]) { + if (obj["signatures"][0]["comment"]["tags"][tag].tag === value && obj["sources"] && obj["sources"][0]) + list.push(obj["sources"][0]); } } } - if (obj['comment'] && obj['comment']['tags']) { - for (let tag in obj['comment']['tags']) { - if (obj['comment']['tags'][tag].tag === value && obj['sources'] && obj['sources'][0]) - list.push(obj['sources'][0]); + if (obj["comment"] && obj["comment"]["tags"]) { + for (let tag in obj["comment"]["tags"]) { + if (obj["comment"]["tags"][tag].tag === value && obj["sources"] && obj["sources"][0]) + list.push(obj["sources"][0]); } } diff --git a/tools/build/src/mocha-reporter/index.ts b/tools/build/src/mocha-reporter/index.ts index 0401d89c9ac2..23d022a1d939 100644 --- a/tools/build/src/mocha-reporter/index.ts +++ b/tools/build/src/mocha-reporter/index.ts @@ -19,7 +19,7 @@ function setupAsyncHooks() { const init = (asyncId: number, type: string, triggerAsyncId: number, _resource: any) => { const eid = async_hooks.executionAsyncId(); // (An executionAsyncId() of 0 means that it is being executed from C++ with no JavaScript stack above it.) const stack = new Error().stack; - asyncResourceStats.set(asyncId, {type, eid, triggerAsyncId, initStack: stack}); + asyncResourceStats.set(asyncId, { type, eid, triggerAsyncId, initStack: stack }); }; const destroy = (asyncId: number) => { if (asyncResourceStats.get(asyncId) === undefined) { @@ -28,7 +28,7 @@ function setupAsyncHooks() { asyncResourceStats.delete(asyncId); }; - const asyncHook = async_hooks.createHook({init, destroy}); + const asyncHook = async_hooks.createHook({ init, destroy }); asyncHook.enable(); } const fs = require("fs-extra"); @@ -52,7 +52,7 @@ const isCI = process.env.CI || process.env.TF_BUILD; // Force rush test to fail CI builds if describe.only or it.only is used. // These should only be used for debugging and must not be committed, otherwise we may be accidentally skipping lots of tests. if (isCI) { - if (typeof (mocha) !== "undefined") + if (typeof mocha !== "undefined") mocha.forbidOnly(); else require.cache[require.resolve("mocha/lib/mocharc.json", { paths: require.main?.paths ?? module.paths })]!.exports.forbidOnly = true; @@ -61,7 +61,7 @@ if (isCI) { // This is necessary to enable colored output when running in rush test: Object.defineProperty(Base, "color", { get: () => process.env.FORCE_COLOR !== "false" && process.env.FORCE_COLOR !== "0", - set: () => { }, + set: () => {}, }); class BentleyMochaReporter extends Spec { @@ -80,9 +80,11 @@ class BentleyMochaReporter extends Spec { super.epilogue(...args); if (0 === this.stats.passes) { - logBuildError("There were 0 passing tests. That doesn't seem right." - + "\nIf there are really no passing tests and no failures, then what was even the point?" - + "\nIt seems likely that tests were skipped by it.only, it.skip, or grep filters, so I'm going to fail now."); + logBuildError( + "There were 0 passing tests. That doesn't seem right." + + "\nIf there are really no passing tests and no failures, then what was even the point?" + + "\nIt seems likely that tests were skipped by it.only, it.skip, or grep filters, so I'm going to fail now.", + ); failBuild(); } } @@ -105,7 +107,9 @@ class BentleyMochaReporter extends Spec { // asyncResourceStats.set(asyncId, {before: 0, after: 0, type, eid, triggerAsyncId, initStack: stack}); asyncResourceStats.forEach((value, key) => { if (activeResourcesInfo.includes(value.type.toLowerCase())) { - console.error(`asyncId: ${key}: type: ${value.type}, eid: ${value.eid},triggerAsyncId: ${value.triggerAsyncId}, initStack: ${value.initStack}`); + console.error( + `asyncId: ${key}: type: ${value.type}, eid: ${value.eid},triggerAsyncId: ${value.triggerAsyncId}, initStack: ${value.initStack}`, + ); } }); } else { diff --git a/tools/certa/bin/certa.js b/tools/certa/bin/certa.js index 1595bcd5fc45..93cee3ce57f7 100755 --- a/tools/certa/bin/certa.js +++ b/tools/certa/bin/certa.js @@ -21,34 +21,34 @@ yargs.strict(true) "backend": { alias: "b", describe: `The path to a javascript file containing backend initialization logic.`, - type: "string" + type: "string", }, "config": { alias: "c", describe: `Path to a certa.json config file.`, type: "string", - default: "./certa.json" + default: "./certa.json", }, "cover": { describe: `Measure code coverage using nyc.`, type: "boolean", - default: undefined + default: undefined, }, "debug": { describe: `Run in debug mode.`, type: "boolean", - default: undefined + default: undefined, }, "debug-electron": { describe: `Run in debug mode (alias to '--debug').`, type: "boolean", default: undefined, - hidden: true + hidden: true, }, "testBundle": { alias: "t", describe: `The path to a javascript file containing all mocha tests to be run.`, - type: "string" + type: "string", }, "grep": { alias: "g", @@ -84,7 +84,7 @@ const opts = { grep: yargs.argv.grep, fgrep: yargs.argv.fgrep, invert: yargs.argv.invert, - } + }, }; const configFilePath = path.resolve(process.cwd(), yargs.argv.config); diff --git a/tools/certa/certa.schema.json b/tools/certa/certa.schema.json index ca38999e32cd..f32ce888c3b9 100644 --- a/tools/certa/certa.schema.json +++ b/tools/certa/certa.schema.json @@ -126,4 +126,4 @@ } } } -} \ No newline at end of file +} diff --git a/tools/certa/eslint.config.js b/tools/certa/eslint.config.js index 1a2a72d15661..6d0c87341fe1 100644 --- a/tools/certa/eslint.config.js +++ b/tools/certa/eslint.config.js @@ -11,7 +11,7 @@ module.exports = [ "@typescript-eslint/no-misused-promises": "off", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/unbound-method": "off", - "no-console": "off" - } - } -]; \ No newline at end of file + "no-console": "off", + }, + }, +]; diff --git a/tools/certa/src/CertaConfig.ts b/tools/certa/src/CertaConfig.ts index 0709a0fc209b..78a5d0b3b962 100644 --- a/tools/certa/src/CertaConfig.ts +++ b/tools/certa/src/CertaConfig.ts @@ -3,9 +3,9 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import * as fs from "fs"; -import * as path from "path"; -import * as lodash from "lodash"; import { parse } from "jsonc-parser"; +import * as lodash from "lodash"; +import * as path from "path"; /** Defines mocha options common to all test runners. */ export interface CertaMochaOpts { @@ -55,7 +55,6 @@ export interface PartialCertaConfig { /** Certa configuration options. */ export interface CertaConfig { - /** The absolute path to a JavaScript file containing all mocha tests to be run. */ readonly testBundle: string; diff --git a/tools/certa/src/CertaCore.ts b/tools/certa/src/CertaCore.ts index 8408f46ae5f6..96d592a2fd7e 100644 --- a/tools/certa/src/CertaCore.ts +++ b/tools/certa/src/CertaCore.ts @@ -2,9 +2,9 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ElectronTestRunner } from "./runners/electron/ElectronTestRunner"; -import { ChromeTestRunner } from "./runners/chrome/ChromeTestRunner"; import { CertaConfig } from "./CertaConfig"; +import { ChromeTestRunner } from "./runners/chrome/ChromeTestRunner"; +import { ElectronTestRunner } from "./runners/electron/ElectronTestRunner"; import { NodeTestRunner } from "./runners/node/NodeTestRunner"; import { relaunchForCoverage } from "./utils/CoverageUtils"; import { startDebugger } from "./utils/SpawnUtils"; diff --git a/tools/certa/src/runners/chrome/ChromeTestRunner.ts b/tools/certa/src/runners/chrome/ChromeTestRunner.ts index 15f1bf0c8d66..2d710e4f67be 100644 --- a/tools/certa/src/runners/chrome/ChromeTestRunner.ts +++ b/tools/certa/src/runners/chrome/ChromeTestRunner.ts @@ -2,13 +2,13 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ +import { ChildProcess } from "child_process"; import * as path from "path"; import { Browser, chromium, LaunchOptions, Page } from "playwright"; -import { ChildProcess } from "child_process"; -import { spawnChildProcess } from "../../utils/SpawnUtils"; -import { executeRegisteredCallback } from "../../utils/CallbackUtils"; import { CertaConfig } from "../../CertaConfig"; +import { executeRegisteredCallback } from "../../utils/CallbackUtils"; import { writeCoverageData } from "../../utils/CoverageUtils"; +import { spawnChildProcess } from "../../utils/SpawnUtils"; import { configureRemoteReporter } from "./MochaRemoteReporter"; interface ChromeTestResults { diff --git a/tools/certa/src/runners/chrome/MochaSerializer.ts b/tools/certa/src/runners/chrome/MochaSerializer.ts index bf1a31a733e0..40e130093274 100644 --- a/tools/certa/src/runners/chrome/MochaSerializer.ts +++ b/tools/certa/src/runners/chrome/MochaSerializer.ts @@ -42,7 +42,7 @@ class MochaSerializer { isPrimary = true; } - return (isPrimary) ? { $$index, $$typeName, ...raw } : { $$index, $$typeName }; + return isPrimary ? { $$index, $$typeName, ...raw } : { $$index, $$typeName }; } /** diff --git a/tools/certa/src/runners/chrome/webserver.ts b/tools/certa/src/runners/chrome/webserver.ts index 96486cea1f68..23ca725d9dc8 100644 --- a/tools/certa/src/runners/chrome/webserver.ts +++ b/tools/certa/src/runners/chrome/webserver.ts @@ -14,7 +14,10 @@ const app = express(); app.all("/*", (_req, res, next) => { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS"); - res.header("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-Correlation-Id, X-Session-Id, X-Application-Id, X-Application-Version, X-User-Id, X-Protocol-Version"); + res.header( + "Access-Control-Allow-Headers", + "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-Correlation-Id, X-Session-Id, X-Application-Id, X-Application-Version, X-User-Id, X-Protocol-Version", + ); next(); }); @@ -33,7 +36,7 @@ app.use("/@/", (_req, resp) => { const sourceMap = require("source-map-support").retrieveSourceMap(filePath); const fullPath = path.resolve("/", filePath); resp.sendFile(canonicalPath.normalize(fullPath), { - headers: (sourceMap) && { + headers: sourceMap && { "X-SourceMap": `/@/${sourceMap.url}`, // eslint-disable-line @typescript-eslint/naming-convention }, }); diff --git a/tools/certa/src/runners/electron/ElectronTestRunner.ts b/tools/certa/src/runners/electron/ElectronTestRunner.ts index fb135dce1e36..f71d0fa97e33 100644 --- a/tools/certa/src/runners/electron/ElectronTestRunner.ts +++ b/tools/certa/src/runners/electron/ElectronTestRunner.ts @@ -3,11 +3,11 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/naming-convention */ -import * as path from "path"; import { WebPreferences } from "electron"; +import * as path from "path"; +import { CertaConfig } from "../../CertaConfig"; import { executeRegisteredCallback } from "../../utils/CallbackUtils"; import { relaunchInElectron } from "../../utils/SpawnUtils"; -import { CertaConfig } from "../../CertaConfig"; export class ElectronTestRunner { public static readonly supportsCoverage = false; @@ -75,7 +75,8 @@ export class ElectronTestRunner { rendererWindow.webContents.once("did-finish-load", async () => { const initScriptPath = require.resolve("./initElectronTests.js"); - const startTests = async () => rendererWindow.webContents.executeJavaScript(` + const startTests = async () => + rendererWindow.webContents.executeJavaScript(` var _CERTA_CONFIG = ${JSON.stringify(config)}; require(${JSON.stringify(initScriptPath)}); startCertaTests(${JSON.stringify(config.testBundle)});`); diff --git a/tools/certa/src/utils/CallbackUtils.ts b/tools/certa/src/utils/CallbackUtils.ts index 090d2f36e51a..f29b7cb62fd9 100644 --- a/tools/certa/src/utils/CallbackUtils.ts +++ b/tools/certa/src/utils/CallbackUtils.ts @@ -5,8 +5,22 @@ declare const window: any; declare const global: any; -const isFrontend = (typeof (window) !== "undefined"); -export type CertaBackendCallback = (...args: any[]) => void | null | undefined | number | string | boolean | Promise | Promise | Promise | Promise | Promise | Promise; +const isFrontend = typeof window !== "undefined"; +export type CertaBackendCallback = ( + ...args: any[] +) => + | void + | null + | undefined + | number + | string + | boolean + | Promise + | Promise + | Promise + | Promise + | Promise + | Promise; /** @internal */ export function getCallbacksRegisteredOnBackend(): { [name: string]: CertaBackendCallback } { diff --git a/tools/certa/src/utils/SpawnUtils.ts b/tools/certa/src/utils/SpawnUtils.ts index c4b07c128426..05aac494275f 100644 --- a/tools/certa/src/utils/SpawnUtils.ts +++ b/tools/certa/src/utils/SpawnUtils.ts @@ -18,7 +18,7 @@ export function spawnChildProcess(command: string, args: ReadonlyArray, // FIXME: We should be able to remove the useIpc param and just always enable it, // but it's not safe to spawn electron with IPC enabled until https://github.com/electron/electron/issues/17044 is fixed. - const stdio: StdioOptions = (useIpc) ? ["ipc", "pipe", "pipe"] : "pipe"; + const stdio: StdioOptions = useIpc ? ["ipc", "pipe", "pipe"] : "pipe"; const childProcess = spawn(command, args, { stdio, cwd: process.cwd(), env: childEnv }); // For some reason, spawning using `stdio: "inherit"` results in some garbled output (for example, "✓" is printed as "ΓêÜ"). // Using `stdio: "pipe"` and manually redirecting the output here seems to work though. diff --git a/tools/certa/src/utils/initMocha.ts b/tools/certa/src/utils/initMocha.ts index 1660b8dbdb5f..e2005d8c272c 100644 --- a/tools/certa/src/utils/initMocha.ts +++ b/tools/certa/src/utils/initMocha.ts @@ -12,7 +12,7 @@ declare let _CERTA_CONFIG: CertaConfig; // eslint-disable-line @typescript-eslin // This is essentially equivalent to `mocha.setup("bdd")`, except it works in both node and browser environments. mocha.ui("bdd"); - mocha.suite.emit("pre-require", typeof (window) === "undefined" ? global : window, null, mocha); + mocha.suite.emit("pre-require", typeof window === "undefined" ? global : window, null, mocha); mocha.reporter(mochaOpts.reporter, mochaOpts.reporterOptions); // TODO: Come back and fix useColors to color diff --git a/tools/certa/src/utils/initSourceMaps.ts b/tools/certa/src/utils/initSourceMaps.ts index 8f514fe7632d..f0999b6609b3 100644 --- a/tools/certa/src/utils/initSourceMaps.ts +++ b/tools/certa/src/utils/initSourceMaps.ts @@ -11,7 +11,7 @@ sourceMapSupport.install(); // The source-map-support package does not correctly format stack traces from the browser. // It gets pretty close though, so we'll just monkey-patch here to fix them. const originalPrepareStackTrace = Error.prepareStackTrace; -Error.prepareStackTrace = function (...args) { +Error.prepareStackTrace = function(...args) { const res = originalPrepareStackTrace!.call(this, ...args); return res.replace(/\(.*file:(\/|\\)/g, "(").replace(/at .*file:(\/|\\)/g, "at "); }; diff --git a/tools/certa/tsconfig.json b/tools/certa/tsconfig.json index fa9e0c9b95db..fb9e4848b8e8 100644 --- a/tools/certa/tsconfig.json +++ b/tools/certa/tsconfig.json @@ -6,4 +6,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/tools/ecschema2ts/eslint.config.js b/tools/ecschema2ts/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/tools/ecschema2ts/eslint.config.js +++ b/tools/ecschema2ts/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/tools/ecschema2ts/src/ecschema2ts.ts b/tools/ecschema2ts/src/ecschema2ts.ts index 9a182d7c16a4..270761e2bfaf 100644 --- a/tools/ecschema2ts/src/ecschema2ts.ts +++ b/tools/ecschema2ts/src/ecschema2ts.ts @@ -4,7 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { - ECClass, ECClassModifier, EntityClass, Enumeration, EnumerationProperty, Mixin, PrimitiveProperty, PrimitiveType, Schema, SchemaItem, SchemaItemType, StructClass, StructProperty, + ECClass, + ECClassModifier, + EntityClass, + Enumeration, + EnumerationProperty, + Mixin, + PrimitiveProperty, + PrimitiveType, + Schema, + SchemaItem, + SchemaItemType, + StructClass, + StructProperty, } from "@itwin/ecschema-metadata"; interface TsBentleyModule { @@ -120,7 +132,7 @@ export class ECSchemaToTs { let outputString: string = ""; // import modules - outputString += "import { ClassRegistry, Schema, Schemas } from \"@itwin/core-backend\";\n"; + outputString += 'import { ClassRegistry, Schema, Schemas } from "@itwin/core-backend";\n'; outputString += `import * as elementsModule from "./${schemaName}Elements";\n\n`; // create new schema class @@ -354,7 +366,6 @@ export class ECSchemaToTs { varDeclarationLine += this.addImportClass(classNameToModule, `${structClass.schema.schemaKey.name}ElementProps`, structClass.name); else varDeclarationLine += structClass.name; - } else if (ecProperty.isNavigation()) varDeclarationLine += this.addImportClass(classNameToModule, tsBentleyModules.tsIModelJsCommon.moduleName, "RelatedElementProps"); diff --git a/tools/ecschema2ts/src/ecschema2ts_cli.ts b/tools/ecschema2ts/src/ecschema2ts_cli.ts index 5240726a1c99..c6cd2a912228 100644 --- a/tools/ecschema2ts/src/ecschema2ts_cli.ts +++ b/tools/ecschema2ts/src/ecschema2ts_cli.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ /* eslint-disable no-console */ -import * as path from "path"; -import * as commander from "commander"; import * as chalk from "chalk"; +import * as commander from "commander"; import * as fs from "fs-extra"; +import * as path from "path"; -import { ECSchemaToTsXmlWriter } from "./ecschema2ts_io"; import { SchemaContext } from "@itwin/ecschema-metadata"; +import { ECSchemaToTsXmlWriter } from "./ecschema2ts_io"; function commaSeparatedList(value: string): string[] { return value.split(","); diff --git a/tools/ecschema2ts/src/ecschema2ts_io.ts b/tools/ecschema2ts/src/ecschema2ts_io.ts index 4dcbd25f099d..9b7893733113 100644 --- a/tools/ecschema2ts/src/ecschema2ts_io.ts +++ b/tools/ecschema2ts/src/ecschema2ts_io.ts @@ -3,12 +3,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; -import * as fs from "fs"; -import { ECObjectsError, ECObjectsStatus, ECVersion, ISchemaLocater, Schema, SchemaContext, SchemaInfo, SchemaKey, SchemaMatchType } from "@itwin/ecschema-metadata"; +import { ECSchemaXmlContext, IModelHost } from "@itwin/core-backend"; import { FileSchemaKey, SchemaFileLocater, SchemaJsonFileLocater } from "@itwin/ecschema-locaters"; +import { + ECObjectsError, + ECObjectsStatus, + ECVersion, + ISchemaLocater, + Schema, + SchemaContext, + SchemaInfo, + SchemaKey, + SchemaMatchType, +} from "@itwin/ecschema-metadata"; import { DOMParser } from "@xmldom/xmldom"; -import { ECSchemaXmlContext, IModelHost } from "@itwin/core-backend"; +import * as fs from "fs"; +import * as path from "path"; import { ECSchemaToTs } from "./ecschema2ts"; const unitsSchemaKey = new SchemaKey("Units", 1, 0, 0); @@ -83,7 +93,12 @@ class SchemaBackendFileLocater extends SchemaFileLocater implements ISchemaLocat * @param context The schema context used to parse schema * @param localPath The path of the recursion is following used to detect cyclic dependency */ - private getSchemaRecursively(key: Readonly, matchType: SchemaMatchType, context: SchemaContext, localPath: Set): T | undefined { + private getSchemaRecursively( + key: Readonly, + matchType: SchemaMatchType, + context: SchemaContext, + localPath: Set, + ): T | undefined { // load the schema file const candidates: FileSchemaKey[] = this.findEligibleSchemaKeys(key, matchType, "xml"); if (0 === candidates.length) @@ -109,8 +124,10 @@ class SchemaBackendFileLocater extends SchemaFileLocater implements ISchemaLocat if (undefined === context.getSchemaSync(referenceKey, matchType)) { const referenceSchema = this.getSchemaRecursively(referenceKey, SchemaMatchType.LatestWriteCompatible, context, localPath); if (!referenceSchema) { - throw new ECObjectsError(ECObjectsStatus.UnableToLocateSchema, - `Could not locate reference schema, ${referenceKey.name}.${referenceKey.version.toString()} of schema ${key.name}.${key.version.toString()}`); + throw new ECObjectsError( + ECObjectsStatus.UnableToLocateSchema, + `Could not locate reference schema, ${referenceKey.name}.${referenceKey.version.toString()} of schema ${key.name}.${key.version.toString()}`, + ); } } else if (localPath.has(referenceKeyName)) { throw new ECObjectsError(ECObjectsStatus.InvalidSchemaXML, `Schema ${schemaKeyName} and ${referenceKeyName} form cyclic dependency`); @@ -136,10 +153,16 @@ class SchemaBackendFileLocater extends SchemaFileLocater implements ISchemaLocat // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < referenceDocuments.length; ++i) { const element = referenceDocuments[i]; - const name = this.getRequiredXmlAttribute(element, "name", - "The schema has an invalid ECSchemaReference attribute. One of the reference is missing the 'name' attribute"); - let version = this.getRequiredXmlAttribute(element, "version", - "The schema has an invalid ECSchemaReference attribute. One of the reference is missing the 'version' attribute"); + const name = this.getRequiredXmlAttribute( + element, + "name", + "The schema has an invalid ECSchemaReference attribute. One of the reference is missing the 'name' attribute", + ); + let version = this.getRequiredXmlAttribute( + element, + "version", + "The schema has an invalid ECSchemaReference attribute. One of the reference is missing the 'version' attribute", + ); version = this.resolveECVersionString(version); const key = new SchemaKey(name, ECVersion.fromString(version)); diff --git a/tools/ecschema2ts/src/test/bis.test.ts b/tools/ecschema2ts/src/test/bis.test.ts index 125a1cfaf410..b816816e2fe0 100644 --- a/tools/ecschema2ts/src/test/bis.test.ts +++ b/tools/ecschema2ts/src/test/bis.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ECSchemaToTs } from "../ecschema2ts"; +import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; +import { SchemaContext } from "@itwin/ecschema-metadata"; import { assert } from "chai"; +import { ECSchemaToTs } from "../ecschema2ts"; import * as utils from "./utilities/utils"; -import { SchemaContext } from "@itwin/ecschema-metadata"; -import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; describe("BisCore test correct inheritance", () => { let ecschema2ts: ECSchemaToTs; @@ -43,8 +43,7 @@ describe("BisCore test correct inheritance", () => { `; - const expectedElementSchemaString = - `import { Entity, IModelDb } from "@itwin/core-backend"; + const expectedElementSchemaString = `import { Entity, IModelDb } from "@itwin/core-backend"; import { EntityProps } from "@itwin/core-common"; import { DerivedElementProps } from "./BisCoreElementProps"; @@ -74,8 +73,7 @@ export class DerivedElement extends Element implements DerivedElementProps { } }\n\n`; - const expectedPropsSchemaString = - `import { ElementProps } from "@itwin/core-common"; + const expectedPropsSchemaString = `import { ElementProps } from "@itwin/core-common"; export interface DerivedElementProps extends ElementProps { derivedTestProp?: string; @@ -90,8 +88,7 @@ export interface DerivedElementProps extends ElementProps { }); it("of class that subclasses Element without additional properties", () => { - const schemaXml = - ` + const schemaXml = ` @@ -117,8 +114,7 @@ export interface DerivedElementProps extends ElementProps { `; - const expectedElementSchemaString = - `import { Entity, IModelDb } from "@itwin/core-backend"; + const expectedElementSchemaString = `import { Entity, IModelDb } from "@itwin/core-backend"; import { EntityProps, ElementProps } from "@itwin/core-common"; export abstract class Element extends Entity { @@ -201,8 +197,7 @@ export class DerivedElement extends Element { `; - const expectedElementSchemaString = - `import { Entity, IModelDb } from "@itwin/core-backend"; + const expectedElementSchemaString = `import { Entity, IModelDb } from "@itwin/core-backend"; import { EntityProps, ElementProps } from "@itwin/core-common"; import { SubjectProps } from "./BisCoreElementProps"; @@ -248,8 +243,7 @@ export class Subject extends InformationReferenceElement implements SubjectProps } }\n\n`; - const expectedPropSchemaString = - `import { ElementProps } from "@itwin/core-common"; + const expectedPropSchemaString = `import { ElementProps } from "@itwin/core-common"; export interface IParentElement { } @@ -283,8 +277,7 @@ describe("Referencing BisCore", () => { `; - const expectedElementSchemaString = - `import { DefinitionModel, IModelDb } from "@itwin/core-backend"; + const expectedElementSchemaString = `import { DefinitionModel, IModelDb } from "@itwin/core-backend"; import { ModelProps } from "@itwin/core-common"; /** diff --git a/tools/ecschema2ts/src/test/ecschema2ts.test.ts b/tools/ecschema2ts/src/test/ecschema2ts.test.ts index ca0f339e65f4..c7180cacdd63 100644 --- a/tools/ecschema2ts/src/test/ecschema2ts.test.ts +++ b/tools/ecschema2ts/src/test/ecschema2ts.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ECSchemaToTs } from "../ecschema2ts"; +import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; +import { SchemaContext } from "@itwin/ecschema-metadata"; import { assert } from "chai"; +import { ECSchemaToTs } from "../ecschema2ts"; import * as utils from "./utilities/utils"; -import { SchemaContext } from "@itwin/ecschema-metadata"; -import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; describe("Convert schema xml string to typescript string", () => { let ecschema2ts: ECSchemaToTs; @@ -131,11 +131,9 @@ describe("ecxml to typescript string", () => { const testCases: utils.SchemaTestCase[] = [ // Test Case: Basic Entity { - testName: - `Basic entity`, + testName: `Basic entity`, referenceXmls: [], - schemaXml: - ` + schemaXml: ` @@ -155,8 +153,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity with description @@ -186,8 +183,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity with abstract modifier @@ -214,8 +210,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity with base class @@ -239,8 +234,7 @@ describe("ecxml to typescript string", () => { expectedPropsTs: [utils.dedent` export interface EntityTestProps extends EntityProps { testProp?: number; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { EntityProps } from "@itwin/core-common";`), @@ -261,8 +255,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity with multiple base classes should assume the second is a mixin @@ -305,8 +298,7 @@ describe("ecxml to typescript string", () => { export interface EntityTestProps extends BaseEntityTestProps, IMixin { testEntityIntProp?: number; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { (?=.*\\b(EntityTestProps)\\b)(?=.*\\b(BaseEntityTestProps)\\b).* } from "./TestSchemaElementProps";`), @@ -326,8 +318,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity with base class in a reference schema @@ -358,8 +349,7 @@ describe("ecxml to typescript string", () => { expectedPropsTs: [utils.dedent` export interface EntityTestProps extends BaseEntityTestProps { testEntityIntProp?: number; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { IModelDb } from "@itwin/core-backend";`), new RegExp(`import { EntityTestProps } from "./TestSchemaElementProps";`), @@ -372,8 +362,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, ]; @@ -405,8 +394,7 @@ describe("ecxml to typescript string", () => { expectedPropsTs: [utils.dedent` export interface MixinTest { mixinIntProp?: number; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [], }, @@ -447,8 +435,7 @@ describe("ecxml to typescript string", () => { export interface MixinTest extends BaseMixinTest { mixinIntProp?: number; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [], }, @@ -486,8 +473,7 @@ describe("ecxml to typescript string", () => { export interface StructTest { primitiveProp?: string; enumProp?: IntEnumeration; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [utils.dedent` /** @@ -497,8 +483,7 @@ describe("ecxml to typescript string", () => { First = 1, Second = 2, Third = 3, - }`, - ], + }`], }, // Test Case: Basic struct with description @@ -531,8 +516,7 @@ describe("ecxml to typescript string", () => { export interface StructTest { primitiveProp?: string; enumProp?: IntEnumeration; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [utils.dedent` /** @@ -542,8 +526,7 @@ describe("ecxml to typescript string", () => { First = 1, Second = 2, Third = 3, - }`, - ], + }`], }, // Test Case: Struct has base class @@ -572,8 +555,7 @@ describe("ecxml to typescript string", () => { export interface StructTest extends BaseStructTest { primitiveProp?: string; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [], }, @@ -609,8 +591,7 @@ describe("ecxml to typescript string", () => { expectedPropsTs: [utils.dedent` export interface StructTest extends BaseStructTest { primitiveProp?: string; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [], }, @@ -656,8 +637,7 @@ describe("ecxml to typescript string", () => { public constructor (props: TestBaseProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: 2 References with 2 classes to import @@ -699,14 +679,16 @@ describe("ecxml to typescript string", () => { new RegExp(`import { TestBaseProps } from "./RefSchemaElementProps";`), new RegExp(`import { TestBaseProps as SecondRefSchemaElementPropsTestBaseProps } from "./SecondRefSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class TestClass extends TestBase { public static get className(): string { return "TestClass"; } public constructor (props: TestBaseProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class TestClass2 extends SecondRefSchemaElementsTestBase { public static get className(): string { return "TestClass2"; } @@ -763,21 +745,24 @@ describe("ecxml to typescript string", () => { new RegExp(`import { (?=.*\\b(TestBaseProps)\\b)(?=.*\\b(TestBase2Props)\\b).* } from "./RefSchemaElementProps";`), new RegExp(`import { TestBaseProps as SecondRefSchemaElementPropsTestBaseProps } from "./SecondRefSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class TestClass extends TestBase { public static get className(): string { return "TestClass"; } public constructor (props: TestBaseProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class TestClass2 extends TestBase2 { public static get className(): string { return "TestClass2"; } public constructor (props: TestBase2Props, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class TestClass3 extends SecondRefSchemaElementsTestBase { public static get className(): string { return "TestClass3"; } @@ -830,8 +815,7 @@ describe("ecxml to typescript string", () => { point3dProp?: Point3d; testProp2?: GuidString; testStructProp?: StructClass; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(IModelDb)\\b)(?=.*\\b(Entity)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { TestClassProps } from "./TestSchemaElementProps";`), @@ -843,8 +827,7 @@ describe("ecxml to typescript string", () => { public constructor (props: TestClassProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Duplicate classes are not imported @@ -864,14 +847,16 @@ describe("ecxml to typescript string", () => { new RegExp(`import { (?=.*\\b(IModelDb)\\b)(?=.*\\b(Entity)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { EntityProps } from "@itwin/core-common";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class TestClass extends Entity { public static get className(): string { return "TestClass"; } public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class TestClass2 extends Entity { public static get className(): string { return "TestClass2"; } @@ -908,11 +893,13 @@ describe("ecxml to typescript string", () => { expectedPropsImportTs: [], expectedPropsTs: [], expectedElemImportTs: [], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export const enum TestEnum { TestEnumerator1 = 1, TestEnumerator2 = 2, - }`, utils.dedent` + }`, + utils.dedent` export const enum TestEnum2 { TestEnumerator1 = "testing", TestEnumerator2 = "testing2", @@ -935,8 +922,7 @@ describe("ecxml to typescript string", () => { expectedElemImportTs: [], expectedElemTs: [utils.dedent` export const enum TestEnum { - }`, - ], + }`], }, // Test Case: Schema with enum description @@ -962,8 +948,7 @@ describe("ecxml to typescript string", () => { export const enum TestEnum { TestEnumerator1 = 1, TestEnumerator2 = 2, - }`, - ], + }`], }, ]; @@ -998,8 +983,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, ]; @@ -1033,8 +1017,7 @@ describe("ecxml to typescript string", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Package references no longer look in the lib directory @@ -1065,8 +1048,7 @@ describe("ecxml to typescript string", () => { public constructor (props: GeometricElement3dProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, ]; @@ -1102,8 +1084,7 @@ describe("ecxml to typescript string", () => { public constructor (props: SheetProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, ]; diff --git a/tools/ecschema2ts/src/test/ecschema2ts_cache.test.ts b/tools/ecschema2ts/src/test/ecschema2ts_cache.test.ts index 9640962e01ee..bd250ea48651 100644 --- a/tools/ecschema2ts/src/test/ecschema2ts_cache.test.ts +++ b/tools/ecschema2ts/src/test/ecschema2ts_cache.test.ts @@ -2,11 +2,11 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ECSchemaToTs } from "../ecschema2ts"; +import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; +import { SchemaContext } from "@itwin/ecschema-metadata"; import { assert } from "chai"; +import { ECSchemaToTs } from "../ecschema2ts"; import * as utils from "./utilities/utils"; -import { SchemaContext } from "@itwin/ecschema-metadata"; -import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; describe("BisCore Cache test", () => { it("For ECEntity class with BaseClass in BisCore, find the correct BisCore props interface to extend", () => { @@ -22,8 +22,7 @@ describe("BisCore Cache test", () => { `; - const expectedSchemaString = - `import { ClassRegistry, Schema, Schemas } from "@itwin/core-backend"; + const expectedSchemaString = `import { ClassRegistry, Schema, Schemas } from "@itwin/core-backend"; import * as elementsModule from "./MyDomainElements"; export class MyDomain extends Schema { @@ -40,8 +39,7 @@ export class MyDomain extends Schema { } }\n\n`; - const expectedElementString = - `import { SpatialLocationElement, IModelDb } from "@itwin/core-backend"; + const expectedElementString = `import { SpatialLocationElement, IModelDb } from "@itwin/core-backend"; import { GeometricElement3dProps } from "@itwin/core-common"; export class Building extends SpatialLocationElement { diff --git a/tools/ecschema2ts/src/test/ecschema2ts_file.test.ts b/tools/ecschema2ts/src/test/ecschema2ts_file.test.ts index 593313f50194..a5ec803a7cf5 100644 --- a/tools/ecschema2ts/src/test/ecschema2ts_file.test.ts +++ b/tools/ecschema2ts/src/test/ecschema2ts_file.test.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { ECSchemaToTsXmlWriter } from "../ecschema2ts_io"; +import { SchemaContext } from "@itwin/ecschema-metadata"; import { assert } from "chai"; import * as fs from "fs-extra"; import * as path from "path"; +import { ECSchemaToTsXmlWriter } from "../ecschema2ts_io"; import * as utils from "./utilities/utils"; -import { SchemaContext } from "@itwin/ecschema-metadata"; const assetDir: string = utils.getAssetsDir(); const ec32ReferenceDir: string = path.join(assetDir, "schema3.2"); @@ -29,7 +29,13 @@ async function testFileConverterFailure(context: SchemaContext, schemaFileName: } } -async function testFileConverterSuccess(context: SchemaContext, schemaFileName: string, schemaName: string, outputDir: string, referenceDir: string[]): Promise { +async function testFileConverterSuccess( + context: SchemaContext, + schemaFileName: string, + schemaName: string, + outputDir: string, + referenceDir: string[], +): Promise { const writer = new ECSchemaToTsXmlWriter(outputDir); await writer.convertSchemaFile(context, schemaFileName, referenceDir); assert.isTrue(fs.existsSync(path.join(outputDir, `${schemaName}.ts`))); diff --git a/tools/ecschema2ts/src/test/ecschema2ts_property.test.ts b/tools/ecschema2ts/src/test/ecschema2ts_property.test.ts index 8821a0f4379f..627039491a78 100644 --- a/tools/ecschema2ts/src/test/ecschema2ts_property.test.ts +++ b/tools/ecschema2ts/src/test/ecschema2ts_property.test.ts @@ -23,8 +23,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { binaryProp?: any; - }`, - ], + }`], }, // Test Case: Class with point3d type @@ -44,8 +43,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { point3dProp?: Point3d; - }`, - ], + }`], }, // Test Case: Class with point2d type @@ -65,8 +63,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { point2dProp?: Point2d; - }`, - ], + }`], }, // Test Case: Class with bool type @@ -85,8 +82,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { boolProp?: boolean; - }`, - ], + }`], }, // Test Case: Class with int type @@ -105,8 +101,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { intProp?: number; - }`, - ], + }`], }, // Test Case: Class with double type @@ -125,8 +120,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { doubleProp?: number; - }`, - ], + }`], }, // Test Case: Class with datetime @@ -145,8 +139,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { dateTimeProp?: Date; - }`, - ], + }`], }, // Test Case: Class with string @@ -165,8 +158,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { stringProp?: string; - }`, - ], + }`], }, // Test Case: Class with long @@ -185,9 +177,9 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { longProp?: any; - }`, - ], - }]; + }`], + }, + ]; utils.testGeneratedTypescriptProperty(testCases); }); @@ -212,9 +204,9 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { navProp?: RelatedElementProps; - }`, - ], - }]; + }`], + }, + ]; utils.testGeneratedTypescriptProperty(testCases); }); @@ -241,8 +233,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { structProp?: DerivedStruct; - }`, - ], + }`], }, // Test Case: Class with struct in reference schema @@ -271,8 +262,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { structProp?: DerivedStruct; - }`, - ], + }`], }, ]; @@ -310,9 +300,9 @@ describe("ecjson properties to ts", () => { point2dArrayProp?: Point2d[]; point3dArrayProp?: Point3d[]; stringArrayProp?: string[]; - }`, - ], - }]; + }`], + }, + ]; utils.testGeneratedTypescriptProperty(testCases); }); @@ -339,8 +329,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { structArrayProp?: TestStruct[]; - }`, - ], + }`], }, // Test Case: Class with struct array property in reference schema @@ -369,8 +358,7 @@ describe("ecjson properties to ts", () => { expectedPropsTs: [utils.dedent` export interface TestClassProps extends EntityProps { structArrayProp?: TestStruct[]; - }`, - ], + }`], }, ]; @@ -417,9 +405,9 @@ describe("ecjson properties to ts", () => { export interface TestClassProps extends EntityProps { intProp?: number; structArrayProp?: TestStruct[]; - }`, - ], - }]; + }`], + }, + ]; utils.testGeneratedTypescriptProperty(testCases); }); diff --git a/tools/ecschema2ts/src/test/ecschema2ts_xml.test.ts b/tools/ecschema2ts/src/test/ecschema2ts_xml.test.ts index 4be0ffc98985..7ddd32da686f 100644 --- a/tools/ecschema2ts/src/test/ecschema2ts_xml.test.ts +++ b/tools/ecschema2ts/src/test/ecschema2ts_xml.test.ts @@ -21,13 +21,12 @@ describe("convert schema xml string to ts", () => { `, expectedSchemaImportTs: utils.createExpectedSchemaImportTs("TestSchema"), expectedSchemaTs: utils.createExpectedSchemaTsString("TestSchema"), - expectedPropsImportTs: [ new RegExp(`import { EntityProps } from "@itwin/core-common";`) ], + expectedPropsImportTs: [new RegExp(`import { EntityProps } from "@itwin/core-common";`)], expectedPropsTs: [utils.dedent` export interface EntityTestProps extends EntityProps { booleanProps?: boolean; stringProps?: string; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { EntityTestProps } from "./TestSchemaElementProps";`), @@ -43,8 +42,7 @@ describe("convert schema xml string to ts", () => { public constructor (props: EntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Entity class with only primitive properties @@ -80,8 +78,7 @@ describe("convert schema xml string to ts", () => { longProps?: any; point2DProps?: Point2d; point3DProps?: Point3d; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { EntityTestProps } from "./TestSchemaElementProps";`), @@ -93,8 +90,7 @@ describe("convert schema xml string to ts", () => { public constructor (props: EntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Struct class with only primitive properties @@ -113,7 +109,7 @@ describe("convert schema xml string to ts", () => { `, expectedSchemaImportTs: utils.createExpectedSchemaImportTs("TestSchema"), expectedSchemaTs: utils.createExpectedSchemaTsString("TestSchema"), - expectedPropsImportTs: [ new RegExp(`import { (?=.*\\b(Point2d)\\b)(?=.*\\b(Point3d)\\b).* } from "@itwin/core-geometry";`) ], + expectedPropsImportTs: [new RegExp(`import { (?=.*\\b(Point2d)\\b)(?=.*\\b(Point3d)\\b).* } from "@itwin/core-geometry";`)], expectedPropsTs: [utils.dedent` export interface StructTest { booleanProps?: boolean; @@ -121,8 +117,7 @@ describe("convert schema xml string to ts", () => { binaryProps?: any; point2DProps?: Point2d; point3DProps?: Point3d; - }`, - ], + }`], expectedElemImportTs: [], expectedElemTs: [], }, @@ -157,8 +152,7 @@ describe("convert schema xml string to ts", () => { stringProps?: string; binaryProps?: any; doubleProps?: number; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), ], @@ -169,8 +163,7 @@ describe("convert schema xml string to ts", () => { public constructor (props: EntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Enumeration @@ -205,24 +198,26 @@ describe("convert schema xml string to ts", () => { export interface BaseEntityProps extends EntityProps { intEnumProps?: IntEnumeration; stringEnumProps?: StringEnumeration; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { BaseEntityProps } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export const enum IntEnumeration { First = 1, Second = 2, Third = 3, - }`, utils.dedent` + }`, + utils.dedent` export const enum StringEnumeration { FirstSeason = "spring", SecondSeason = "summer", ThirdSeason = "fall", FourthSeason = "winter", - }`, utils.dedent` + }`, + utils.dedent` export class BaseEntity extends Entity implements BaseEntityProps { public static get className(): string { return "BaseEntity"; } @@ -272,14 +267,16 @@ describe("convert schema xml string to ts", () => { new RegExp(`import { (?=.*\\b(Point2d)\\b)(?=.*\\b(Point3d)\\b).* } from "@itwin/core-geometry";`), new RegExp(`import { (?=.*\\b(IntEnumeration)\\b)(?=.*\\b(StringEnumeration)\\b).* } from "./TestSchemaElements";`), ], - expectedPropsTs: [utils.dedent` + expectedPropsTs: [ + utils.dedent` export interface StructTest { booleanProps?: boolean; stringProps?: string; binaryProps?: any; point2DProps?: Point2d; point3DProps?: Point3d; - }`, utils.dedent` + }`, + utils.dedent` export interface EntityTestProps extends EntityProps { structProps?: StructTest; intEnumProps?: IntEnumeration; @@ -292,18 +289,21 @@ describe("convert schema xml string to ts", () => { new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { (?=.*\\b(EntityTestProps)\\b).* } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export const enum IntEnumeration { First = 1, Second = 2, Third = 3, - }`, utils.dedent` + }`, + utils.dedent` export const enum StringEnumeration { FirstSeason = "spring", SecondSeason = "summer", ThirdSeason = "fall", FourthSeason = "winter", - }`, utils.dedent` + }`, + utils.dedent` export class EntityTest extends Entity implements EntityTestProps { public static get className(): string { return "EntityTest"; } @@ -334,11 +334,13 @@ describe("convert schema xml string to ts", () => { expectedPropsImportTs: [ new RegExp(`import { EntityProps } from "@itwin/core-common";`), ], - expectedPropsTs: [utils.dedent` + expectedPropsTs: [ + utils.dedent` export interface BaseEntityTestProps extends EntityProps { intProps?: number; stringProps?: string; - }`, utils.dedent` + }`, + utils.dedent` export interface DerivedEntityTestProps extends BaseEntityTestProps { derivedIntProps?: number; }`, @@ -347,14 +349,16 @@ describe("convert schema xml string to ts", () => { new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { (?=.*\\b(DerivedEntityTestProps)\\b)(?=.*\\b(BaseEntityTestProps)\\b).* } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class BaseEntityTest extends Entity implements BaseEntityTestProps { public static get className(): string { return "BaseEntityTest"; } public constructor (props: BaseEntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class DerivedEntityTest extends BaseEntityTest implements DerivedEntityTestProps { public static get className(): string { return "DerivedEntityTest"; } @@ -408,21 +412,25 @@ describe("convert schema xml string to ts", () => { expectedPropsImportTs: [ new RegExp(`import { EntityProps } from "@itwin/core-common";`), ], - expectedPropsTs: [utils.dedent` + expectedPropsTs: [ + utils.dedent` export interface MixinTest { booleanProps?: boolean; stringProps?: string; binaryProps?: any; doubleProps?: number; - }`, utils.dedent` + }`, + utils.dedent` export interface DerivedMixinTest extends MixinTest { binaryProps?: any; doubleProps?: number; - }`, utils.dedent` + }`, + utils.dedent` export interface BaseEntityTestProps extends EntityProps { intProps?: number; stringProps?: string; - }`, utils.dedent` + }`, + utils.dedent` export interface DerivedEntityTestProps extends BaseEntityTestProps, MixinTest, DerivedMixinTest { derivedIntProps?: number; }`, @@ -431,14 +439,16 @@ describe("convert schema xml string to ts", () => { new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { (?=.*\\b(DerivedEntityTestProps)\\b)(?=.*\\b(BaseEntityTestProps)\\b).* } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class BaseEntityTest extends Entity implements BaseEntityTestProps { public static get className(): string { return "BaseEntityTest"; } public constructor (props: BaseEntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class DerivedEntityTest extends BaseEntityTest implements DerivedEntityTestProps { public static get className(): string { return "DerivedEntityTest"; } @@ -472,14 +482,16 @@ describe("convert schema xml string to ts", () => { expectedPropsImportTs: [ new RegExp(`import { (?=.*\\b(Point2d)\\b)(?=.*\\b(Point3d)\\b).* } from "@itwin/core-geometry";`), ], - expectedPropsTs: [utils.dedent` + expectedPropsTs: [ + utils.dedent` export interface StructTest { booleanProps?: boolean; stringProps?: string; binaryProps?: any; point2DProps?: Point2d; point3DProps?: Point3d; - }`, utils.dedent` + }`, + utils.dedent` export interface DerivedStructTest extends StructTest { derivedIntProps?: number; }`, @@ -514,35 +526,42 @@ describe("convert schema xml string to ts", () => { expectedPropsImportTs: [ new RegExp(`import { (?=.*\\b(GeometricElement2dProps)\\b)(?=.*\\b(ElementProps)\\b).* } from "@itwin/core-common";`), ], - expectedPropsTs: [utils.dedent` + expectedPropsTs: [ + utils.dedent` export interface DerivedGeometricElement2dProps extends GeometricElement2dProps { intProps?: number; doubleProps?: number; - }`, utils.dedent` + }`, + utils.dedent` export interface DerivedElementProps extends ElementProps { intProps?: number; }`, ], expectedElemImportTs: [ - new RegExp(`import { (?=.*\\b(IModelDb)\\b)(?=.*\\b(Element)\\b)(?=.*\\b(AnnotationElement2d)\\b)(?=.*\\b(GeometricElement2d)\\b).* } from "@itwin/core-backend";`), + new RegExp( + `import { (?=.*\\b(IModelDb)\\b)(?=.*\\b(Element)\\b)(?=.*\\b(AnnotationElement2d)\\b)(?=.*\\b(GeometricElement2d)\\b).* } from "@itwin/core-backend";`, + ), new RegExp(`import { (?=.*\\b(GeometricElement2dProps)\\b).* } from "@itwin/core-common";`), new RegExp(`import { (?=.*\\b(DerivedGeometricElement2dProps)\\b)(?=.*\\b(DerivedElementProps)\\b).* } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class DerivedGeometricElement2d extends GeometricElement2d implements DerivedGeometricElement2dProps { public static get className(): string { return "DerivedGeometricElement2d"; } public constructor (props: DerivedGeometricElement2dProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class DerivedElement extends Element implements DerivedElementProps { public static get className(): string { return "DerivedElement"; } public constructor (props: DerivedElementProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class DerivedAnnotationElement2d extends AnnotationElement2d { public static get className(): string { return "DerivedAnnotationElement2d"; } @@ -581,28 +600,30 @@ describe("convert schema xml string to ts", () => { export interface BaseEntityTestProps extends EntityProps { intProps?: number; stringProps?: string; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b)(?=.*\\b(Element)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { (?=.*\\b(ElementProps)\\b).* } from "@itwin/core-common";`), new RegExp(`import { (?=.*\\b(BaseEntityTestProps)\\b).* } from "./TestSchemaElementProps";`), ], - expectedElemTs: [utils.dedent` + expectedElemTs: [ + utils.dedent` export class DerivedElementTest extends Element { public static get className(): string { return "DerivedElementTest"; } public constructor (props: ElementProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class BaseEntityTest extends Entity implements BaseEntityTestProps { public static get className(): string { return "BaseEntityTest"; } public constructor (props: BaseEntityTestProps, iModel: IModelDb) { super(props, iModel); } - }`, utils.dedent` + }`, + utils.dedent` export class DerivedEntityTest extends BaseEntityTest { public static get className(): string { return "DerivedEntityTest"; } @@ -674,11 +695,12 @@ describe("convert schema xml string to ts", () => { export interface DerivedElementTestProps extends BaseEntityProps { stringProps?: string; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(AnnotationElement2d)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), - new RegExp(`import { (?=.*\\b(NormalEntityProps)\\b)(?=.*\\b(BaseEntityProps)\\b)(?=.*\\b(DerivedElementTestProps)\\b).* } from "./TestSchemaElementProps";`), + new RegExp( + `import { (?=.*\\b(NormalEntityProps)\\b)(?=.*\\b(BaseEntityProps)\\b)(?=.*\\b(DerivedElementTestProps)\\b).* } from "./TestSchemaElementProps";`, + ), ], expectedElemTs: [utils.dedent` /** @@ -712,8 +734,7 @@ describe("convert schema xml string to ts", () => { public constructor (props: DerivedElementTestProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, // Test Case: Xml Deserialization should not crash when references Units and Formats @@ -767,8 +788,7 @@ describe("convert schema xml string to ts", () => { export interface TestEntityProps extends EntityProps { intArrayProp?: number[]; doubleProp?: number; - }`, - ], + }`], expectedElemImportTs: [ new RegExp(`import { (?=.*\\b(Entity)\\b)(?=.*\\b(IModelDb)\\b).* } from "@itwin/core-backend";`), new RegExp(`import { TestEntityProps } from "./TestSchemaElementProps";`), @@ -780,8 +800,7 @@ describe("convert schema xml string to ts", () => { public constructor (props: TestEntityProps, iModel: IModelDb) { super(props, iModel); } - }`, - ], + }`], }, ]; diff --git a/tools/ecschema2ts/src/test/utilities/utils.ts b/tools/ecschema2ts/src/test/utilities/utils.ts index 4502adcde5c1..b8113d51ef8b 100644 --- a/tools/ecschema2ts/src/test/utilities/utils.ts +++ b/tools/ecschema2ts/src/test/utilities/utils.ts @@ -2,12 +2,12 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import { expect } from "chai"; -import * as fs from "fs-extra"; -import * as path from "path"; import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; import { Schema, SchemaContext, SchemaReadHelper, XmlParser } from "@itwin/ecschema-metadata"; import { DOMParser } from "@xmldom/xmldom"; +import { expect } from "chai"; +import * as fs from "fs-extra"; +import * as path from "path"; import { ECSchemaToTs } from "../../ecschema2ts"; declare const __dirname: string; // eslint-disable-line @typescript-eslint/naming-convention @@ -134,8 +134,7 @@ export function testGeneratedSchemaTypescript(testCases: SchemaTestCase[]): void } export function createExpectedSchemaTsString(schemaName: string): string { - const schemaTsString: string = - `export class ${schemaName} extends Schema { + const schemaTsString: string = `export class ${schemaName} extends Schema { public static get schemaName(): string { return "${schemaName}"; } public static registerSchema() { diff --git a/tools/ecschema2ts/tsconfig.json b/tools/ecschema2ts/tsconfig.json index f4993dee2ed7..7555dcce6b22 100644 --- a/tools/ecschema2ts/tsconfig.json +++ b/tools/ecschema2ts/tsconfig.json @@ -3,4 +3,4 @@ "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} diff --git a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AccentColor.colorset/Contents.json b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AccentColor.colorset/Contents.json index eb8789700816..0afb3cf0eec8 100644 --- a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AccentColor.colorset/Contents.json +++ b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AccentColor.colorset/Contents.json @@ -1,11 +1,11 @@ { - "colors" : [ + "colors": [ { - "idiom" : "universal" + "idiom": "universal" } ], - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AppIcon.appiconset/Contents.json index 9221b9bb1a35..faeb2bbbb0fc 100644 --- a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1,98 @@ { - "images" : [ + "images": [ { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" + "idiom": "iphone", + "scale": "2x", + "size": "20x20" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" + "idiom": "iphone", + "scale": "3x", + "size": "20x20" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" + "idiom": "iphone", + "scale": "2x", + "size": "29x29" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" + "idiom": "iphone", + "scale": "3x", + "size": "29x29" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" + "idiom": "iphone", + "scale": "2x", + "size": "40x40" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" + "idiom": "iphone", + "scale": "3x", + "size": "40x40" }, { - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" + "idiom": "iphone", + "scale": "2x", + "size": "60x60" }, { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" + "idiom": "iphone", + "scale": "3x", + "size": "60x60" }, { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" + "idiom": "ipad", + "scale": "1x", + "size": "20x20" }, { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" + "idiom": "ipad", + "scale": "2x", + "size": "20x20" }, { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" + "idiom": "ipad", + "scale": "1x", + "size": "29x29" }, { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" + "idiom": "ipad", + "scale": "2x", + "size": "29x29" }, { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" + "idiom": "ipad", + "scale": "1x", + "size": "40x40" }, { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" + "idiom": "ipad", + "scale": "2x", + "size": "40x40" }, { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" + "idiom": "ipad", + "scale": "1x", + "size": "76x76" }, { - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" + "idiom": "ipad", + "scale": "2x", + "size": "76x76" }, { - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" + "idiom": "ipad", + "scale": "2x", + "size": "83.5x83.5" }, { - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" + "idiom": "ios-marketing", + "scale": "1x", + "size": "1024x1024" } ], - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/Contents.json b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/Contents.json index 73c00596a7fc..74d6a722cf39 100644 --- a/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/Contents.json +++ b/tools/internal/ios/core-test-runner/core-test-runner/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/tools/internal/ios/core-test-runner/core-test-runner/Preview Content/Preview Assets.xcassets/Contents.json b/tools/internal/ios/core-test-runner/core-test-runner/Preview Content/Preview Assets.xcassets/Contents.json index 73c00596a7fc..74d6a722cf39 100644 --- a/tools/internal/ios/core-test-runner/core-test-runner/Preview Content/Preview Assets.xcassets/Contents.json +++ b/tools/internal/ios/core-test-runner/core-test-runner/Preview Content/Preview Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { - "info" : { - "author" : "xcode", - "version" : 1 + "info": { + "author": "xcode", + "version": 1 } } diff --git a/tools/internal/ios/ios.webpack.config.js b/tools/internal/ios/ios.webpack.config.js index fc514d7eac20..53054625582e 100644 --- a/tools/internal/ios/ios.webpack.config.js +++ b/tools/internal/ios/ios.webpack.config.js @@ -11,7 +11,7 @@ module.exports = { entry: [ path.resolve(__dirname, "scripts/configureMocha.js"), ...globSync(path.resolve(__dirname, path.relative(__dirname, process.env.TESTS_GLOB))), - path.resolve(__dirname, "scripts/runMocha.js") + path.resolve(__dirname, "scripts/runMocha.js"), ], output: { path: path.resolve(__dirname, "../lib/ios/assets"), @@ -24,7 +24,7 @@ module.exports = { resolve: { mainFields: ["main"], aliasFields: ["browser"], - alias: { mocha$: "mocha/lib/mocha" } + alias: { mocha$: "mocha/lib/mocha" }, }, module: { // don't parse @bentley/imodeljs-native/NativeLibrary.js, @@ -35,24 +35,24 @@ module.exports = { { test: /\.js$/, use: "source-map-loader", - enforce: "pre" + enforce: "pre", }, { test: /growl\.js$/, - use: 'null-loader' + use: "null-loader", }, { test: /xunit\.js$/, - use: 'null-loader' + use: "null-loader", }, { test: /bunyan/, - use: 'null-loader' - } - ] + use: "null-loader", + }, + ], }, node: { __filename: false, - __dirname: false - } -} \ No newline at end of file + __dirname: false, + }, +}; diff --git a/tools/internal/ios/scripts/configureMocha.js b/tools/internal/ios/scripts/configureMocha.js index 974ae9038b2f..0782627c6276 100644 --- a/tools/internal/ios/scripts/configureMocha.js +++ b/tools/internal/ios/scripts/configureMocha.js @@ -11,4 +11,4 @@ const BentleyMochaReporter = require("@itwin/build-tools/mocha-reporter"); mocha.ui("bdd"); mocha.suite.emit("pre-require", global, null, mocha); mocha.timeout(9999999); -mocha.reporter(BentleyMochaReporter, { mochaFile: process.env.TEST_RESULTS_PATH }); \ No newline at end of file +mocha.reporter(BentleyMochaReporter, { mochaFile: process.env.TEST_RESULTS_PATH }); diff --git a/tools/internal/ios/scripts/processAppCenterLogs.js b/tools/internal/ios/scripts/processAppCenterLogs.js index 592ac2b56902..260af2633db2 100644 --- a/tools/internal/ios/scripts/processAppCenterLogs.js +++ b/tools/internal/ios/scripts/processAppCenterLogs.js @@ -3,46 +3,46 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -const https = require('https'); -const fs = require('fs'); -const readline = require('readline'); -const path = require('path'); +const https = require("https"); +const fs = require("fs"); +const readline = require("readline"); +const path = require("path"); -const app_center_host = 'api.appcenter.ms'; +const app_center_host = "api.appcenter.ms"; const app_center_api_ver = "v0.1"; -const owner_name = process.argv[2]; // app_center_owner; -const app_name = process.argv[3]; // app_center_app; -const api_token = process.argv[4]; // app_center_token; -const lib_directory = process.argv[5]; // lib_directory (for output) +const owner_name = process.argv[2]; // app_center_owner; +const app_name = process.argv[3]; // app_center_app; +const api_token = process.argv[4]; // app_center_token; +const lib_directory = process.argv[5]; // lib_directory (for output) const test_id = require(path.relative(__dirname, `${lib_directory}/run_output.json`))[0].testRunId; const xmlFilter = "[Mocha_Result_XML]: "; -const deviceLogsPath = "device_logs.txt" -const resultsPath = `${lib_directory}/junit_results.xml` +const deviceLogsPath = "device_logs.txt"; +const resultsPath = `${lib_directory}/junit_results.xml`; async function fetchTestReportInfo() { return new Promise((resolve, reject) => { const options = { host: app_center_host, path: `/${app_center_api_ver}/apps/${owner_name}/${app_name}/test_runs/${test_id}/report`, - method: 'GET', + method: "GET", headers: { - 'Content-Type': 'application/json; charset=utf-8', - 'X-API-Token': api_token, + "Content-Type": "application/json; charset=utf-8", + "X-API-Token": api_token, }, }; - const req = https.request(options, function (res) { - res.setEncoding('utf-8'); - let responseString = ''; + const req = https.request(options, function(res) { + res.setEncoding("utf-8"); + let responseString = ""; - res.on('data', (data) => { + res.on("data", (data) => { responseString += data; }); res.on("error", (err) => { reject(err); }); - res.on('end', () => { + res.on("end", () => { const responseObject = JSON.parse(responseString); resolve(responseObject); }); @@ -57,19 +57,19 @@ async function downloadDeviceLogs(url, dest, cb) { try { console.info(`Downloading device log from app-center ${url}`); if (fs.existsSync(dest)) { - fs.unlinkSync(dest) + fs.unlinkSync(dest); } const file = fs.createWriteStream(dest); - https.get(url, function (response) { + https.get(url, function(response) { response.pipe(file); - file.on('finish', () => { + file.on("finish", () => { console.info(`Device log saved to ${dest}`); file.close(cb); resolve(); }); - response.on('error', err => { + response.on("error", (err) => { reject(err); - }) + }); }); } catch (err) { reject(err); @@ -80,11 +80,11 @@ async function downloadDeviceLogs(url, dest, cb) { function extractXML(xmlFilter, inputLogFile, outputXmlFile) { const rl = readline.createInterface({ input: fs.createReadStream(inputLogFile), - crlfDelay: Infinity + crlfDelay: Infinity, }); - const outputStream = fs.createWriteStream(outputXmlFile) + const outputStream = fs.createWriteStream(outputXmlFile); - rl.on('line', (line) => { + rl.on("line", (line) => { if (line.includes(xmlFilter)) { let xmlLine = line.substring(line.indexOf(xmlFilter) + xmlFilter.length); @@ -97,15 +97,15 @@ function extractXML(xmlFilter, inputLogFile, outputXmlFile) { }); } -(async function () { +(async function() { const testReport = await fetchTestReportInfo(); - console.log("Fetched test report info.") + console.log("Fetched test report info."); console.info(JSON.stringify(testReport, undefined, 2)); const deviceLogUrl = testReport.device_logs[0].device_log; await downloadDeviceLogs(deviceLogUrl, deviceLogsPath); - console.log("Downloaded device logs.") + console.log("Downloaded device logs."); extractXML(xmlFilter, deviceLogsPath, resultsPath); - console.log("Extracted XML from device logs.") -})(); \ No newline at end of file + console.log("Extracted XML from device logs."); +})(); diff --git a/tools/internal/ios/scripts/runMocha.js b/tools/internal/ios/scripts/runMocha.js index bc6b46f6fbbc..42c95e35d4b8 100644 --- a/tools/internal/ios/scripts/runMocha.js +++ b/tools/internal/ios/scripts/runMocha.js @@ -5,10 +5,10 @@ var numFailed = -1; -mocha.run(function (numTestsFailed) { +mocha.run(function(numTestsFailed) { numFailed = numTestsFailed; }); -process.on('exit', function () { +process.on("exit", function() { process._linkedBinding("iModelJsMobile").notifyListening(numFailed); -}); \ No newline at end of file +}); diff --git a/tools/internal/scripts/copyConfig.js b/tools/internal/scripts/copyConfig.js index bd9ea36868bc..10584ca892a0 100644 --- a/tools/internal/scripts/copyConfig.js +++ b/tools/internal/scripts/copyConfig.js @@ -14,9 +14,9 @@ exports.builder = (yargs) => alias: "o", describe: "Directory of the output.", type: "array", - default: process.cwd() + default: process.cwd(), }, - }) + }); exports.handler = async (argv) => { const rootDir = __dirname.split("tools")[0]; @@ -35,16 +35,16 @@ exports.handler = async (argv) => { } for (const destination of argv.out) { - const destRoot = path.resolve(rootDir, destination) + const destRoot = path.resolve(rootDir, destination); if (!fs.existsSync(destRoot)) { - console.log(`Cannot find the root directory of the destination: ${destRoot}`) + console.log(`Cannot find the root directory of the destination: ${destRoot}`); return; } // copy '.env' file fs.copyFile(envFile, path.resolve(destRoot, ".env"), (error) => { if (error) throw error; - console.log(`Copied '${envFile}' to '${destRoot}`) - }) + console.log(`Copied '${envFile}' to '${destRoot}`); + }); } -} +}; diff --git a/tools/internal/scripts/linkextensions.js b/tools/internal/scripts/linkextensions.js index f5704ed054d9..53c715302b25 100644 --- a/tools/internal/scripts/linkextensions.js +++ b/tools/internal/scripts/linkextensions.js @@ -19,7 +19,7 @@ exports.builder = (yargs) => alias: "t", describe: "Directory of the test-app.", type: "array", - default: process.cwd() + default: process.cwd(), }, }) .demandOption(["extension", "testApp"]); @@ -27,27 +27,26 @@ exports.builder = (yargs) => exports.handler = async (argv) => { const rootDir = __dirname.split("tools")[0]; - //go through every testApp specified in the arguments + // go through every testApp specified in the arguments for (let testApp of argv.testApp) { - - //get path to test-app directories - const destRoot = path.resolve(rootDir, "test-apps", testApp) + // get path to test-app directories + const destRoot = path.resolve(rootDir, "test-apps", testApp); if (!fs.existsSync(destRoot)) { - console.log(`Cannot find the root directory of the destination: ${destRoot}`) + console.log(`Cannot find the root directory of the destination: ${destRoot}`); return; } - //check if './build/imjs_extensions' exists + // check if './build/imjs_extensions' exists const extensionDirectory = path.join(destRoot, "build", "imjs_extensions"); if (!fs.existsSync(extensionDirectory)) { fs.mkdirSync(extensionDirectory); } - //symlink extensions + // symlink extensions for (let extension of argv.extension) { const buildDir = path.resolve(rootDir, "extensions", extension, "lib", "extension"); if (!fs.existsSync(buildDir)) { - console.log(`Cannot find the target path: ${buildDir}`) + console.log(`Cannot find the target path: ${buildDir}`); } const outDir = path.resolve(extensionDirectory, extension); if (fs.existsSync(outDir)) { @@ -57,4 +56,4 @@ exports.handler = async (argv) => { fs.symlinkSync(buildDir, outDir, "junction"); } } -} +}; diff --git a/tools/perf-tools/eslint.config.js b/tools/perf-tools/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/tools/perf-tools/eslint.config.js +++ b/tools/perf-tools/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/tools/perf-tools/tsconfig.json b/tools/perf-tools/tsconfig.json index 67be9deac4ee..baa950b82605 100644 --- a/tools/perf-tools/tsconfig.json +++ b/tools/perf-tools/tsconfig.json @@ -3,4 +3,4 @@ "compilerOptions": { "outDir": "./lib" } -} \ No newline at end of file +} diff --git a/tools/webpack-core/eslint.config.js b/tools/webpack-core/eslint.config.js index 1a2a72d15661..6d0c87341fe1 100644 --- a/tools/webpack-core/eslint.config.js +++ b/tools/webpack-core/eslint.config.js @@ -11,7 +11,7 @@ module.exports = [ "@typescript-eslint/no-misused-promises": "off", "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/unbound-method": "off", - "no-console": "off" - } - } -]; \ No newline at end of file + "no-console": "off", + }, + }, +]; diff --git a/tools/webpack-core/src/plugins/BackendDefaultsPlugin.ts b/tools/webpack-core/src/plugins/BackendDefaultsPlugin.ts index 67d51a8b9330..b1619f8343e4 100644 --- a/tools/webpack-core/src/plugins/BackendDefaultsPlugin.ts +++ b/tools/webpack-core/src/plugins/BackendDefaultsPlugin.ts @@ -7,7 +7,13 @@ import { AssetInfo, Compiler, DefinePlugin, ExternalsPlugin, RuleSetRule } from import { CopyAppAssetsPlugin, CopyStaticAssetsPlugin } from "./CopyBentleyStaticResourcesPlugin"; import { CopyExternalsPlugin } from "./CopyExternalsPlugin"; import { IgnoreOptionalDependenciesPlugin } from "./OptionalDependenciesPlugin"; -import { addCopyFilesSuffix, addExternalPrefix, copyFilesRule, handlePrefixedExternals, RequireMagicCommentsPlugin } from "./RequireMagicCommentsPlugin"; +import { + addCopyFilesSuffix, + addExternalPrefix, + copyFilesRule, + handlePrefixedExternals, + RequireMagicCommentsPlugin, +} from "./RequireMagicCommentsPlugin"; export class BackendDefaultsPlugin { public apply(compiler: Compiler) { @@ -28,8 +34,7 @@ export class BackendDefaultsPlugin { }, ]; - const isProductionLikeMode = - compiler.options.mode === "production" || !compiler.options.mode; + const isProductionLikeMode = compiler.options.mode === "production" || !compiler.options.mode; if (isProductionLikeMode) { defaultRules.push({ diff --git a/tools/webpack-core/src/plugins/FrontendDefaultsPlugin.ts b/tools/webpack-core/src/plugins/FrontendDefaultsPlugin.ts index ead1e23108ca..f7d36bef7e62 100644 --- a/tools/webpack-core/src/plugins/FrontendDefaultsPlugin.ts +++ b/tools/webpack-core/src/plugins/FrontendDefaultsPlugin.ts @@ -12,7 +12,7 @@ const isProductionLikeMode = ( }; export class FrontendDefaultsPlugin { - constructor(private _enableSourcemaps = true) { } + constructor(private _enableSourcemaps = true) {} public apply(compiler: Compiler) { // Add a loader to remove all asserts in production builds. const defaultRules: RuleSetRule[] = [ diff --git a/tools/webpack-core/src/plugins/PrettyLoggingPlugin.ts b/tools/webpack-core/src/plugins/PrettyLoggingPlugin.ts index 0ac79499edc1..e329771074a2 100644 --- a/tools/webpack-core/src/plugins/PrettyLoggingPlugin.ts +++ b/tools/webpack-core/src/plugins/PrettyLoggingPlugin.ts @@ -32,16 +32,18 @@ export class PrettyLoggingPlugin { this._startMessage = startMessage; this._startTime = Date.now(); this._successCount = 0; - this._onSuccess = onSuccess || (() => { }); + this._onSuccess = onSuccess || (() => {}); this._formatter = formatter || ((s) => s); } - public get isInteractive() { return process.stdout.isTTY && this._isWatch; } + public get isInteractive() { + return process.stdout.isTTY && this._isWatch; + } private clearIfInteractive() { if (this.isInteractive) { const isWindows = process.platform === "win32"; - process.stdout.write((isWindows) ? "\x1B[2J\x1B[0f" : "\x1B[2J\x1B[3J\x1B[H"); + process.stdout.write(isWindows ? "\x1B[2J\x1B[0f" : "\x1B[2J\x1B[3J\x1B[H"); } } @@ -50,9 +52,11 @@ export class PrettyLoggingPlugin { console.groupEnd(); const newline = (this.isInteractive) ? "\n" : ""; - const myChalk: chalk.Chalk = (color) ? (chalk as any)[color] : chalk; + const myChalk: chalk.Chalk = color ? (chalk as any)[color] : chalk; if (elapsed) - console.log(`${newline}${myChalk.inverse(this._name)} ${myChalk.bold(message)}${chalk.gray(` (in ${elapsed.toLocaleString()} ms)`)}${newline}`); + console.log( + `${newline}${myChalk.inverse(this._name)} ${myChalk.bold(message)}${chalk.gray(` (in ${elapsed.toLocaleString()} ms)`)}${newline}`, + ); else console.log(`${newline}${myChalk.inverse(this._name)} ${myChalk.bold(message)}${newline}`); diff --git a/tools/webpack-core/src/plugins/RequireMagicCommentsPlugin.ts b/tools/webpack-core/src/plugins/RequireMagicCommentsPlugin.ts index ed45941f3083..6621a0ff8081 100644 --- a/tools/webpack-core/src/plugins/RequireMagicCommentsPlugin.ts +++ b/tools/webpack-core/src/plugins/RequireMagicCommentsPlugin.ts @@ -49,13 +49,19 @@ interface MagicCommentHandlerConfig { * Will result in webpack treating `require(/* foo */"bar")` as if it had been `require("bar?foo")`. */ export class RequireMagicCommentsPlugin { - constructor(private _configs: MagicCommentHandlerConfig[]) { } + constructor(private _configs: MagicCommentHandlerConfig[]) {} public apply(compiler: Compiler) { compiler.hooks.normalModuleFactory.tap("RequireMagicCommentsPlugin", (nmf) => { nmf.hooks.parser.for("javascript/auto").tap("RequireMagicCommentsPlugin", (parser: any) => { - parser.hooks.call.for("require").tap("RequireMagicCommentsPlugin", this.handleCommonJs(parser, CommonJsRequireDependency, RequireHeaderDependency)); - parser.hooks.call.for("require.resolve").tap("RequireMagicCommentsPlugin", this.handleCommonJs(parser, RequireResolveDependency, RequireResolveHeaderDependency)); + parser.hooks.call.for("require").tap( + "RequireMagicCommentsPlugin", + this.handleCommonJs(parser, CommonJsRequireDependency, RequireHeaderDependency), + ); + parser.hooks.call.for("require.resolve").tap( + "RequireMagicCommentsPlugin", + this.handleCommonJs(parser, RequireResolveDependency, RequireResolveHeaderDependency), + ); }); }); } @@ -95,7 +101,11 @@ export class RequireMagicCommentsPlugin { logger.log(`Converting require.resolve => require for "${param.string}" at ${getSourcePosition(parser.state.current, expr.loc)}`); } request = handler(request, comment.value); - logger.log(`Handler for /*${comment.value}*/ - transformed "${param.string}" => "${request}" at ${getSourcePosition(parser.state.current, expr.loc)}`); + logger.log( + `Handler for /*${comment.value}*/ - transformed "${param.string}" => "${request}" at ${ + getSourcePosition(parser.state.current, expr.loc) + }`, + ); } } diff --git a/tools/webpack-core/src/plugins/WatchBackendPlugin.ts b/tools/webpack-core/src/plugins/WatchBackendPlugin.ts index b85058cdaeca..91b148c458f7 100644 --- a/tools/webpack-core/src/plugins/WatchBackendPlugin.ts +++ b/tools/webpack-core/src/plugins/WatchBackendPlugin.ts @@ -10,7 +10,7 @@ import { Compiler } from "webpack"; export class WatchBackendPlugin { private _prevTimestamp = Date.now(); - constructor(private _backendOutputPath: string) { } + constructor(private _backendOutputPath: string) {} public apply(compiler: Compiler) { compiler.hooks.emit.tap("WatchBackendPlugin", (compilation: any) => { diff --git a/tools/webpack-core/src/test/CopyBentleyStaticResourcesPlugin.test.ts b/tools/webpack-core/src/test/CopyBentleyStaticResourcesPlugin.test.ts index f0f934716f0e..0d36ba89d4a5 100644 --- a/tools/webpack-core/src/test/CopyBentleyStaticResourcesPlugin.test.ts +++ b/tools/webpack-core/src/test/CopyBentleyStaticResourcesPlugin.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/naming-convention */ +import { expect } from "chai"; +import * as fs from "fs-extra"; import { Volume } from "memfs"; import * as path from "path"; -import * as fs from "fs-extra"; +import { CopyBentleyStaticResourcesPlugin } from "../plugins/CopyBentleyStaticResourcesPlugin"; import { resetPaths, setApplicationDir } from "../utils/paths"; import { clearCache, clearFileSystem, fsFromJson, getTestConfig, runWebpack } from "./TestUtils"; -import { CopyBentleyStaticResourcesPlugin } from "../plugins/CopyBentleyStaticResourcesPlugin"; -import { expect } from "chai"; describe("CopyBentleyStaticResourcesPlugin", () => { let testConfig: any; @@ -22,7 +22,8 @@ describe("CopyBentleyStaticResourcesPlugin", () => { }); // memfs (vol) doesn't work if plugins being tested grab files from actual file system fsFromJson({ - "lib/test/assets/copy-bentley-static-resources-plugin-test/node_modules/@bentley/resource/lib/assets/staticResourcePlugin.js": `console.log("Fake resource");`, + "lib/test/assets/copy-bentley-static-resources-plugin-test/node_modules/@bentley/resource/lib/assets/staticResourcePlugin.js": + `console.log("Fake resource");`, }); }); diff --git a/tools/webpack-core/src/test/CopyExternalsPlugin.test.ts b/tools/webpack-core/src/test/CopyExternalsPlugin.test.ts index fabd6c75ca9c..e1807e5c48c0 100644 --- a/tools/webpack-core/src/test/CopyExternalsPlugin.test.ts +++ b/tools/webpack-core/src/test/CopyExternalsPlugin.test.ts @@ -3,13 +3,13 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/naming-convention */ -import { Volume } from "memfs"; import { expect } from "chai"; -import * as path from "path"; import * as fs from "fs-extra"; -import { clearCache, clearFileSystem, fsFromJson, getTestConfig, runWebpack } from "./TestUtils"; +import { Volume } from "memfs"; +import * as path from "path"; import { CopyExternalsPlugin } from "../plugins/CopyExternalsPlugin"; import { setApplicationDir } from "../utils/paths"; +import { clearCache, clearFileSystem, fsFromJson, getTestConfig, runWebpack } from "./TestUtils"; describe("CopyExternalsPlugin", () => { let testConfig: any; diff --git a/tools/webpack-core/src/test/OptionalDependenciesPlugin.test.ts b/tools/webpack-core/src/test/OptionalDependenciesPlugin.test.ts index 46468704ff52..52c167043c18 100644 --- a/tools/webpack-core/src/test/OptionalDependenciesPlugin.test.ts +++ b/tools/webpack-core/src/test/OptionalDependenciesPlugin.test.ts @@ -3,19 +3,19 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/naming-convention */ -import { Volume } from "memfs"; import { expect } from "chai"; -import * as path from "path"; import * as fs from "fs-extra"; -import { clearCache, clearFileSystem, getTestConfig, runWebpack } from "./TestUtils"; +import { Volume } from "memfs"; +import * as path from "path"; import { IgnoreOptionalDependenciesPlugin } from "../plugins/OptionalDependenciesPlugin"; import { resetPaths, setApplicationDir } from "../utils/paths"; +import { clearCache, clearFileSystem, getTestConfig, runWebpack } from "./TestUtils"; describe("OptionalDependenciesPlugin", () => { let testConfig: any; const vol = new Volume(); - beforeEach(function () { + beforeEach(function() { setApplicationDir(path.join(__dirname, "assets/optional-dependencies-plugin-test")); testConfig = getTestConfig("assets/optional-dependencies-plugin-test/test.js", [new IgnoreOptionalDependenciesPlugin(["foo"])]); }); @@ -58,7 +58,8 @@ describe("OptionalDependenciesPlugin", () => { it("should ignore non-call use of require", async () => { vol.fromJSON({ "lib/test/assets/optional-dependencies-plugin-test/test.js": `const foo = require("foo");`, - "lib/test/assets/optional-dependencies-plugin-test/node_modules/foo/index.js": `const optional = true;let req = (optional) ? require : console.log;const bar = req("./bar");`, + "lib/test/assets/optional-dependencies-plugin-test/node_modules/foo/index.js": + `const optional = true;let req = (optional) ? require : console.log;const bar = req("./bar");`, "lib/test/assets/optional-dependencies-plugin-test/node_modules/foo/bar.js": `console.log("This is bar");`, }); diff --git a/tools/webpack-core/src/test/RequireMagicCommentsPlugin.test.ts b/tools/webpack-core/src/test/RequireMagicCommentsPlugin.test.ts index 1c11bb12f335..477e9bd39e09 100644 --- a/tools/webpack-core/src/test/RequireMagicCommentsPlugin.test.ts +++ b/tools/webpack-core/src/test/RequireMagicCommentsPlugin.test.ts @@ -3,14 +3,20 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ /* eslint-disable @typescript-eslint/no-var-requires, @typescript-eslint/naming-convention */ -import { Volume } from "memfs"; import { expect } from "chai"; -import * as path from "path"; import * as fs from "fs-extra"; -import { clearCache, clearFileSystem, fsFromJson, getTestConfig, runWebpack } from "./TestUtils"; -import { addCopyFilesSuffix, addExternalPrefix, copyFilesRule, handlePrefixedExternals, RequireMagicCommentsPlugin } from "../plugins/RequireMagicCommentsPlugin"; +import { Volume } from "memfs"; +import * as path from "path"; import { ExternalsPlugin } from "webpack"; +import { + addCopyFilesSuffix, + addExternalPrefix, + copyFilesRule, + handlePrefixedExternals, + RequireMagicCommentsPlugin, +} from "../plugins/RequireMagicCommentsPlugin"; import { setApplicationDir } from "../utils/paths"; +import { clearCache, clearFileSystem, fsFromJson, getTestConfig, runWebpack } from "./TestUtils"; describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse let testConfig: any; @@ -37,11 +43,16 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse vol.fromJSON({ "lib/test/assets/require-magic-comments-plugin-test/test.js": `require(/*webpack: external*/"foo");`, }); - const pluginsToTest = [new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix }]), new ExternalsPlugin("commonjs", handlePrefixedExternals)]; + const pluginsToTest = [ + new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix }]), + new ExternalsPlugin("commonjs", handlePrefixedExternals), + ]; testConfig = getTestConfig("assets/require-magic-comments-plugin-test/test.js", pluginsToTest); const { logging } = await runWebpack(testConfig, vol); - expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`); + expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include( + `Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8")).to.matchSnapshot(); }); @@ -76,11 +87,16 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse vol.fromJSON({ "lib/test/assets/require-magic-comments-plugin-test/test.js": `require.resolve(/*webpack: external*/"foo");`, }); - const pluginsToTest = [new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix }]), new ExternalsPlugin("commonjs", handlePrefixedExternals)]; + const pluginsToTest = [ + new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix }]), + new ExternalsPlugin("commonjs", handlePrefixedExternals), + ]; testConfig = getTestConfig("assets/require-magic-comments-plugin-test/test.js", pluginsToTest); const { logging } = await runWebpack(testConfig, vol); - expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`); + expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include( + `Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8")).to.matchSnapshot(); }); @@ -88,12 +104,17 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse vol.fromJSON({ "lib/test/assets/require-magic-comments-plugin-test/test.js": `require.resolve(/*webpack: external*/"foo");`, }); - const pluginsToTest = [new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix, convertResolve: true }]), new ExternalsPlugin("commonjs", handlePrefixedExternals)]; + const pluginsToTest = [ + new RequireMagicCommentsPlugin([{ test: /webpack: *external/i, handler: addExternalPrefix, convertResolve: true }]), + new ExternalsPlugin("commonjs", handlePrefixedExternals), + ]; testConfig = getTestConfig("assets/require-magic-comments-plugin-test/test.js", pluginsToTest); const { logging } = await runWebpack(testConfig, vol); expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Converting require.resolve => require for "foo"`); - expect(logging?.RequireMagicCommentsPlugin.entries[1].message).to.include(`Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`); + expect(logging?.RequireMagicCommentsPlugin.entries[1].message).to.include( + `Handler for /*webpack: external*/ - transformed "foo" => "BeWebpack-EXTERNAL:foo"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8")).to.matchSnapshot(); }); @@ -106,7 +127,9 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse testConfig = getTestConfig("assets/require-magic-comments-plugin-test/test.js", pluginsToTest, undefined, [copyFilesRule]); const { logging } = await runWebpack(testConfig); - expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`); + expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include( + `Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8").split(`\* 3 \*`)[0]).to.matchSnapshot(); expect(fs.readFileSync(path.join(__dirname, "dist/static/bar.d9b9bf.txt"), "utf8")).to.equal("This is bar.txt"); }); @@ -121,7 +144,9 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse const { logging } = await runWebpack(testConfig); expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Converting require.resolve => require for "./bar.txt"`); - expect(logging?.RequireMagicCommentsPlugin.entries[1].message).to.include(`Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`); + expect(logging?.RequireMagicCommentsPlugin.entries[1].message).to.include( + `Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8").split(`\* 3 \*`)[0]).to.matchSnapshot(); expect(fs.readFileSync(path.join(__dirname, "dist/static/bar.d9b9bf.txt"), "utf8")).to.equal("This is bar.txt"); }); @@ -135,7 +160,9 @@ describe("RequireMagicCommentsPlugin", () => { // Issue #4354 @aruniverse testConfig = getTestConfig("assets/require-magic-comments-plugin-test/test.js", pluginsToTest, undefined, [copyFilesRule]); const { logging } = await runWebpack(testConfig); - expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include(`Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`); + expect(logging?.RequireMagicCommentsPlugin.entries[0].message).to.include( + `Handler for /*webpack: copyfile*/ - transformed "./bar.txt" => "./bar.txt?BeWebpack-COPYFILE}"`, + ); expect(fs.readFileSync(path.join(__dirname, "dist/main.js"), "utf8").split(`\* 3 \*`)[0]).to.matchSnapshot(); expect(fs.readFileSync(path.join(__dirname, "dist/static/bar.d9b9bf.txt"), "utf8")).to.equal("This is bar.txt"); }); diff --git a/tools/webpack-core/src/test/TestUtils.ts b/tools/webpack-core/src/test/TestUtils.ts index efc61ecdeab5..3625637561a4 100644 --- a/tools/webpack-core/src/test/TestUtils.ts +++ b/tools/webpack-core/src/test/TestUtils.ts @@ -2,8 +2,8 @@ * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as path from "path"; import * as fs from "fs-extra"; +import * as path from "path"; import { Compiler, Configuration, Stats, StatsCompilation, webpack } from "webpack"; const MODULE = require("module"); const { usedDeps } = require("../utils/resolve-recurse/resolve"); @@ -19,7 +19,7 @@ function createTestCompiler(config: Configuration, vol?: any): Compiler { export async function runWebpack(config: Configuration, vol?: any): Promise { const compiler = createTestCompiler(config, vol); return new Promise((resolve, reject) => { - compiler.run((err?: Error | null, stats?: Stats) => (err) ? reject(err) : resolve(stats?.toJson({ logging: true }))); + compiler.run((err?: Error | null, stats?: Stats) => err ? reject(err) : resolve(stats?.toJson({ logging: true }))); }); } diff --git a/tools/webpack-core/src/test/setup.test.ts b/tools/webpack-core/src/test/setup.test.ts index 6b68d7caca83..b821c80bc4f1 100644 --- a/tools/webpack-core/src/test/setup.test.ts +++ b/tools/webpack-core/src/test/setup.test.ts @@ -7,11 +7,11 @@ import * as chaiJestSnapshot from "chai-jest-snapshot"; chai.use(chaiJestSnapshot); -before(function () { +before(function() { chaiJestSnapshot.resetSnapshotRegistry(); }); -beforeEach(function () { +beforeEach(function() { const currentTest = (this as any).currentTest; const sourceFilePath = currentTest.file.replace("lib\\test", "src\\test").replace(/\.(jsx?|tsx?)$/, ""); const snapPath = `${sourceFilePath}.snap`; diff --git a/tools/webpack-core/src/utils/resolve-recurse/resolve.d.ts b/tools/webpack-core/src/utils/resolve-recurse/resolve.d.ts index 81b8e1f5e079..6d93415a702f 100644 --- a/tools/webpack-core/src/utils/resolve-recurse/resolve.d.ts +++ b/tools/webpack-core/src/utils/resolve-recurse/resolve.d.ts @@ -18,4 +18,3 @@ export interface ResolveOptions { relative?: string; // Path to the file that path should be resolved relative to. filter?: (pkg: any) => boolean; // Determine whether or not to resolve a dependency. } - diff --git a/tools/webpack-core/src/utils/resolve-recurse/resolve.js b/tools/webpack-core/src/utils/resolve-recurse/resolve.js index 62b6fbf5c82b..94e155fef2d4 100644 --- a/tools/webpack-core/src/utils/resolve-recurse/resolve.js +++ b/tools/webpack-core/src/utils/resolve-recurse/resolve.js @@ -18,7 +18,7 @@ const usedDeps = new Set(); // given the name of a module, and the directory of the module which referenced // it, resolve to the module base directory function moduleDirectory(name, dir) { - return resolve(`${name}/package.json`, { basedir: dir }).then(function (filePath) { + return resolve(`${name}/package.json`, { basedir: dir }).then(function(filePath) { return findup(path.dirname(filePath), "package.json"); }); } @@ -26,7 +26,6 @@ function moduleDirectory(name, dir) { // given use-input options, it will resolve an options object // with the defaults in place, and options.path resolved function mergeDefaultOptions(options) { - // apply simple defaults const trueOptions = { filter: options.filter || null, @@ -45,7 +44,7 @@ function mergeDefaultOptions(options) { } // return a promise that resolves to the true path - return modulePromise.then(function (modPath) { + return modulePromise.then(function(modPath) { trueOptions.path = modPath; return trueOptions; }); @@ -57,7 +56,7 @@ function mergeDefaultOptions(options) { // return acc // for use with _.reduce function unzipObject(acc, value) { - _.each(value, function (val, key) { + _.each(value, function(val, key) { acc.push({ name: key, version: val }); }); return acc; @@ -97,15 +96,15 @@ async function dependentModules(dir, allowedVersion, options) { }); // for each dependency, make a promise that calls dependentModules // on its directory - const depPromises = _.map(deps, function (dep) { - return moduleDirectory(dep.name, dir).then(async function (directory) { + const depPromises = _.map(deps, function(dep) { + return moduleDirectory(dep.name, dir).then(async function(directory) { return dependentModules(directory, dep.version, options); }); }); // return a promise that will give an array of objects representing each dep // call _.compact because filtered-out dependencies return null - return Promise.all(depPromises).then(function (depObjects) { + return Promise.all(depPromises).then(function(depObjects) { return { name: pkg.name, path: dir, @@ -127,7 +126,7 @@ async function resolveRecurse(options) { // get the default options, and then get the dependent modules // nodify it, to conform to a typical node API but still return a promise - return mergeDefaultOptions(options).then(async function (opts) { + return mergeDefaultOptions(options).then(async function(opts) { return dependentModules(opts.path, null, opts); }); } diff --git a/tools/webpack-core/tsconfig.json b/tools/webpack-core/tsconfig.json index 90379b451916..8ec21e527a48 100644 --- a/tools/webpack-core/tsconfig.json +++ b/tools/webpack-core/tsconfig.json @@ -2,10 +2,10 @@ "extends": "./node_modules/@itwin/build-tools/tsconfig-base.json", "compilerOptions": { "outDir": "./lib", - "allowJs": true, + "allowJs": true }, "include": [ "src/**/*.ts", "src/**/*.js" ] -} \ No newline at end of file +} diff --git a/ui/appui-abstract/certa.json b/ui/appui-abstract/certa.json index aa2e43630798..1b2bd18c5e54 100644 --- a/ui/appui-abstract/certa.json +++ b/ui/appui-abstract/certa.json @@ -23,4 +23,4 @@ "--no-sandbox" ] } -} \ No newline at end of file +} diff --git a/ui/appui-abstract/eslint.config.js b/ui/appui-abstract/eslint.config.js index 319ad07b8ff2..2eef229a59a1 100644 --- a/ui/appui-abstract/eslint.config.js +++ b/ui/appui-abstract/eslint.config.js @@ -13,14 +13,14 @@ module.exports = [ { files: ["**/*.ts"], rules: { - "max-statements-per-line": "off" - } + "max-statements-per-line": "off", + }, }, { files: ["src/test/**/*"], rules: { - "deprecation/deprecation": "off" - } + "deprecation/deprecation": "off", + }, }, ...eslintBaseConfig, -]; \ No newline at end of file +]; diff --git a/ui/appui-abstract/src/appui-abstract/BaseUiItemsProvider.ts b/ui/appui-abstract/src/appui-abstract/BaseUiItemsProvider.ts index cd6450646edf..c31b9ad337eb 100644 --- a/ui/appui-abstract/src/appui-abstract/BaseUiItemsProvider.ts +++ b/ui/appui-abstract/src/appui-abstract/BaseUiItemsProvider.ts @@ -8,13 +8,13 @@ */ import { BackstageItem } from "./backstage/BackstageItem"; +import { StageUsage } from "./items/StageUsage"; import { CommonStatusBarItem } from "./statusbar/StatusBarItem"; import { CommonToolbarItem, ToolbarOrientation, ToolbarUsage } from "./toolbars/ToolbarItem"; +import { UiItemsManager } from "./UiItemsManager"; +import { UiItemsProvider } from "./UiItemsProvider"; import { AbstractWidgetProps } from "./widget/AbstractWidgetProps"; import { AbstractZoneLocation, StagePanelLocation, StagePanelSection } from "./widget/StagePanel"; -import { StageUsage } from "./items/StageUsage"; -import { UiItemsProvider } from "./UiItemsProvider"; -import { UiItemsManager } from "./UiItemsManager"; /** Base implementation of a UiItemsProvider. The base class allows the user to pass in a function that is used to determine if the * active stage should be provided items. Derived provider classes should override the `xxxInternal` methods to provide items. @@ -28,10 +28,15 @@ export class BaseUiItemsProvider implements UiItemsProvider { * @param isSupportedStage - optional function that will be called to determine if tools should be added to current stage. If not set and * the current stage's `usage` is set to `StageUsage.General` then the provider will add items to frontstage. */ - constructor(protected _providerId: string, public isSupportedStage?: (stageId: string, stageUsage: string, stageAppData?: any, provider?: UiItemsProvider) => boolean) { } + constructor( + protected _providerId: string, + public isSupportedStage?: (stageId: string, stageUsage: string, stageAppData?: any, provider?: UiItemsProvider) => boolean, + ) {} - public get id(): string { return this._providerId; } - public onUnregister(): void { } + public get id(): string { + return this._providerId; + } + public onUnregister(): void {} public unregister() { UiItemsManager.unregister(this._providerId); @@ -42,16 +47,28 @@ export class BaseUiItemsProvider implements UiItemsProvider { return []; } - public provideToolbarButtonItemsInternal(_stageId: string, _stageUsage: string, _toolbarUsage: ToolbarUsage, _toolbarOrientation: ToolbarOrientation, _stageAppData?: any): CommonToolbarItem[] { + public provideToolbarButtonItemsInternal( + _stageId: string, + _stageUsage: string, + _toolbarUsage: ToolbarUsage, + _toolbarOrientation: ToolbarOrientation, + _stageAppData?: any, + ): CommonToolbarItem[] { return []; } - public provideToolbarButtonItems(stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation, stageAppData?: any): CommonToolbarItem[] { + public provideToolbarButtonItems( + stageId: string, + stageUsage: string, + toolbarUsage: ToolbarUsage, + toolbarOrientation: ToolbarOrientation, + stageAppData?: any, + ): CommonToolbarItem[] { let provideToStage = false; if (this.isSupportedStage) { provideToStage = this.isSupportedStage(stageId, stageUsage, stageAppData, this); } else { - provideToStage = (stageUsage === StageUsage.General); + provideToStage = stageUsage === StageUsage.General; } return provideToStage ? this.provideToolbarButtonItemsInternal(stageId, stageUsage, toolbarUsage, toolbarOrientation, stageAppData) : []; @@ -66,24 +83,37 @@ export class BaseUiItemsProvider implements UiItemsProvider { if (this.isSupportedStage) { provideToStage = this.isSupportedStage(stageId, stageUsage, stageAppData, this); } else { - provideToStage = (stageUsage === StageUsage.General); + provideToStage = stageUsage === StageUsage.General; } return provideToStage ? this.provideStatusBarItemsInternal(stageId, stageUsage, stageAppData) : []; } - public provideWidgetsInternal(_stageId: string, _stageUsage: string, _location: StagePanelLocation, _section?: StagePanelSection, _zoneLocation?: AbstractZoneLocation, _stageAppData?: any): AbstractWidgetProps[] { + public provideWidgetsInternal( + _stageId: string, + _stageUsage: string, + _location: StagePanelLocation, + _section?: StagePanelSection, + _zoneLocation?: AbstractZoneLocation, + _stageAppData?: any, + ): AbstractWidgetProps[] { return []; } - public provideWidgets(stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection, - _zoneLocation?: AbstractZoneLocation, stageAppData?: any): ReadonlyArray { + public provideWidgets( + stageId: string, + stageUsage: string, + location: StagePanelLocation, + section?: StagePanelSection, + _zoneLocation?: AbstractZoneLocation, + stageAppData?: any, + ): ReadonlyArray { let provideToStage = false; if (this.isSupportedStage) { provideToStage = this.isSupportedStage(stageId, stageUsage, stageAppData, this); } else { - provideToStage = (stageUsage === StageUsage.General); + provideToStage = stageUsage === StageUsage.General; } return provideToStage ? this.provideWidgetsInternal(stageId, stageUsage, location, section, _zoneLocation, stageAppData) : []; diff --git a/ui/appui-abstract/src/appui-abstract/UiAdmin.ts b/ui/appui-abstract/src/appui-abstract/UiAdmin.ts index 6140d7da69b9..8720cb370c60 100644 --- a/ui/appui-abstract/src/appui-abstract/UiAdmin.ts +++ b/ui/appui-abstract/src/appui-abstract/UiAdmin.ts @@ -7,18 +7,21 @@ */ import { BentleyError, BentleyStatus, BeUiEvent } from "@itwin/core-bentley"; +import { UiDataProvider } from "./dialogs/UiDataProvider"; +import { DialogLayoutDataProvider } from "./dialogs/UiLayoutDataProvider"; import { AbstractMenuItemProps } from "./items/AbstractMenuItemProps"; import { AbstractToolbarProps } from "./items/AbstractToolbarProps"; import { RelativePosition } from "./items/RelativePosition"; +import { MessagePresenter } from "./notification/MessagePresenter"; import { PropertyDescription } from "./properties/Description"; import { Primitives } from "./properties/PrimitiveTypes"; -import { OnCancelFunc, OnItemExecutedFunc, OnNumberCommitFunc, OnValueCommitFunc } from "./utils/callbacks"; import { PropertyRecord } from "./properties/Record"; -import { UiDataProvider } from "./dialogs/UiDataProvider"; -import { DialogLayoutDataProvider } from "./dialogs/UiLayoutDataProvider"; -import { MessagePresenter } from "./notification/MessagePresenter"; +import { OnCancelFunc, OnItemExecutedFunc, OnNumberCommitFunc, OnValueCommitFunc } from "./utils/callbacks"; -interface XAndY { readonly x: number, readonly y: number } +interface XAndY { + readonly x: number; + readonly y: number; +} interface BentleyErrorWithCategory extends BentleyError { category: string; @@ -56,7 +59,7 @@ export interface DialogProps { /** The GenericUiEvent is the base event class for UI events that target a specific component, as identified in uiComponentId. * @public */ -export class GenericUiEvent extends BeUiEvent { } +export class GenericUiEvent extends BeUiEvent {} /** Flags that control enabling/disabling certain UI features * @public @@ -96,21 +99,27 @@ export class UiAdmin { } /** @internal */ - public onInitialized() { } + public onInitialized() {} /** Get the cursor X and Y position. */ - public get cursorPosition(): XAndY { return { x: 0, y: 0 }; } + public get cursorPosition(): XAndY { + return { x: 0, y: 0 }; + } /** Create a PointProps object. - * @deprecated in 4.2.x. Please use @core/geometry [[XAndY]] or a custom implementation. - */ - public createXAndY(x: number, y: number): XAndY { return { x, y }; } + * @deprecated in 4.2.x. Please use @core/geometry [[XAndY]] or a custom implementation. + */ + public createXAndY(x: number, y: number): XAndY { + return { x, y }; + } /** Determines if focus is set to Home */ - public get isFocusOnHome(): boolean { return false; } + public get isFocusOnHome(): boolean { + return false; + } /** Sets focus to Home */ - public setFocusToHome(): void { } + public setFocusToHome(): void {} /** Show a context menu at a particular location. * @param _menuItemsProps Properties of the menu items to display. @@ -133,13 +142,21 @@ export class UiAdmin { * @return true if the Toolbar was displayed, false if the Toolbar could not be displayed. */ public showToolbar( - _toolbarProps: AbstractToolbarProps, _location: XAndY, _offset: XAndY, _onItemExecuted: OnItemExecutedFunc, _onCancel: OnCancelFunc, - _relativePosition?: RelativePosition, _htmlElement?: HTMLElement): boolean { + _toolbarProps: AbstractToolbarProps, + _location: XAndY, + _offset: XAndY, + _onItemExecuted: OnItemExecutedFunc, + _onCancel: OnCancelFunc, + _relativePosition?: RelativePosition, + _htmlElement?: HTMLElement, + ): boolean { return false; } /** Hides the toolbar. */ - public hideToolbar(): boolean { return false; } + public hideToolbar(): boolean { + return false; + } /** Show a menu button at a particular location. A menu button opens a context menu. * @param _id Id of the menu button. Multiple menu buttons may be displayed. @@ -156,7 +173,9 @@ export class UiAdmin { * @param _id Id of the menu button. Multiple menu buttons may be displayed. * @return true if the menu was hidden, false if the menu could not be hidden. */ - public hideMenuButton(_id: string): boolean { return false; } + public hideMenuButton(_id: string): boolean { + return false; + } /** Show a calculator at a particular location. * @param _initialValue Value initially displayed in the calculator. @@ -167,12 +186,21 @@ export class UiAdmin { * @param _htmlElement The HTMLElement that anchors the context menu. If undefined, the location is relative to the overall window. * @return true if the calculator was displayed, false if the calculator could not be displayed. */ - public showCalculator(_initialValue: number, _resultIcon: string, _location: XAndY, _onCommit: OnNumberCommitFunc, _onCancel: OnCancelFunc, _htmlElement?: HTMLElement): boolean { + public showCalculator( + _initialValue: number, + _resultIcon: string, + _location: XAndY, + _onCommit: OnNumberCommitFunc, + _onCancel: OnCancelFunc, + _htmlElement?: HTMLElement, + ): boolean { return false; } /** Hides the calculator. */ - public hideCalculator(): boolean { return false; } + public hideCalculator(): boolean { + return false; + } /** Show an input editor for an angle value at a particular location. * @param _initialValue Value initially displayed in the editor. @@ -182,7 +210,13 @@ export class UiAdmin { * @param _htmlElement The HTMLElement that anchors the context menu. If undefined, the location is relative to the overall window. * @return true if the editor was displayed, false if the editor could not be displayed. */ - public showAngleEditor(_initialValue: number, _location: XAndY, _onCommit: OnNumberCommitFunc, _onCancel: OnCancelFunc, _htmlElement?: HTMLElement): boolean { + public showAngleEditor( + _initialValue: number, + _location: XAndY, + _onCommit: OnNumberCommitFunc, + _onCancel: OnCancelFunc, + _htmlElement?: HTMLElement, + ): boolean { return false; } @@ -194,7 +228,13 @@ export class UiAdmin { * @param _htmlElement The HTMLElement that anchors the context menu. If undefined, the location is relative to the overall window. * @return true if the editor was displayed, false if the editor could not be displayed. */ - public showLengthEditor(_initialValue: number, _location: XAndY, _onCommit: OnNumberCommitFunc, _onCancel: OnCancelFunc, _htmlElement?: HTMLElement): boolean { + public showLengthEditor( + _initialValue: number, + _location: XAndY, + _onCommit: OnNumberCommitFunc, + _onCancel: OnCancelFunc, + _htmlElement?: HTMLElement, + ): boolean { return false; } @@ -206,7 +246,13 @@ export class UiAdmin { * @param _htmlElement The HTMLElement that anchors the context menu. If undefined, the location is relative to the overall window. * @return true if the editor was displayed, false if the editor could not be displayed. */ - public showHeightEditor(_initialValue: number, _location: XAndY, _onCommit: OnNumberCommitFunc, _onCancel: OnCancelFunc, _htmlElement?: HTMLElement): boolean { + public showHeightEditor( + _initialValue: number, + _location: XAndY, + _onCommit: OnNumberCommitFunc, + _onCancel: OnCancelFunc, + _htmlElement?: HTMLElement, + ): boolean { return false; } @@ -219,12 +265,21 @@ export class UiAdmin { * @param _htmlElement The HTMLElement that anchors the context menu. If undefined, the location is relative to the overall window. * @return true if the editor was displayed, false if the editor could not be displayed. */ - public showInputEditor(_initialValue: Primitives.Value, _propertyDescription: PropertyDescription, _location: XAndY, _onCommit: OnValueCommitFunc, _onCancel: OnCancelFunc, _htmlElement?: HTMLElement): boolean { + public showInputEditor( + _initialValue: Primitives.Value, + _propertyDescription: PropertyDescription, + _location: XAndY, + _onCommit: OnValueCommitFunc, + _onCancel: OnCancelFunc, + _htmlElement?: HTMLElement, + ): boolean { return false; } /** Hides the input editor. */ - public hideInputEditor(): boolean { return false; } + public hideInputEditor(): boolean { + return false; + } /** Show an HTML element at a particular location. * @param _displayElement The HTMLElement to display @@ -236,13 +291,20 @@ export class UiAdmin { * @return true if the display element was displayed, false if the display element could not be displayed. */ public showHTMLElement( - _displayElement: HTMLElement, _location: XAndY, _offset: XAndY, _onCancel: OnCancelFunc, - _relativePosition?: RelativePosition, _anchorElement?: HTMLElement): boolean { + _displayElement: HTMLElement, + _location: XAndY, + _offset: XAndY, + _onCancel: OnCancelFunc, + _relativePosition?: RelativePosition, + _anchorElement?: HTMLElement, + ): boolean { return false; } /** Hides the HTML Element. */ - public hideHTMLElement(): boolean { return false; } + public hideHTMLElement(): boolean { + return false; + } /** Show a Card containing content, a title and a toolbar at a particular location. * @param _content The HTMLElement of the content to display @@ -257,14 +319,23 @@ export class UiAdmin { * @return true if the Card was displayed, false if the Card could not be displayed. */ public showCard( - _content: HTMLElement, _title: string | PropertyRecord | undefined, _toolbarProps: AbstractToolbarProps | undefined, - _location: XAndY, _offset: XAndY, _onItemExecuted: OnItemExecutedFunc, _onCancel: OnCancelFunc, - _relativePosition?: RelativePosition, _anchorElement?: HTMLElement): boolean { + _content: HTMLElement, + _title: string | PropertyRecord | undefined, + _toolbarProps: AbstractToolbarProps | undefined, + _location: XAndY, + _offset: XAndY, + _onItemExecuted: OnItemExecutedFunc, + _onCancel: OnCancelFunc, + _relativePosition?: RelativePosition, + _anchorElement?: HTMLElement, + ): boolean { return false; } /** Hides the Card. */ - public hideCard(): boolean { return false; } + public hideCard(): boolean { + return false; + } /** Opens a Tool Settings Ui popup at a particular location. * @param _dataProvider The UiDataProvider for the tool settings @@ -276,22 +347,33 @@ export class UiAdmin { * @return true if the tool settings were displayed, false if the tool settings could not be displayed. */ public openToolSettingsPopup( - _dataProvider: UiDataProvider, _location: XAndY, _offset: XAndY, _onCancel: OnCancelFunc, - _relativePosition?: RelativePosition, _anchorElement?: HTMLElement): boolean { + _dataProvider: UiDataProvider, + _location: XAndY, + _offset: XAndY, + _onCancel: OnCancelFunc, + _relativePosition?: RelativePosition, + _anchorElement?: HTMLElement, + ): boolean { return false; } /** Closes the Tool Settings Ui popup. */ - public closeToolSettingsPopup(): boolean { return false; } + public closeToolSettingsPopup(): boolean { + return false; + } /** Show the Keyin Palette to display all support Tool key-ins. * @param _htmlElement The HTMLElement that anchors the Keyin Palette. If undefined, the location is relative to the overall window. * @return true if the Keyin Palette was displayed, false if it could not be displayed. */ - public showKeyinPalette(_htmlElement?: HTMLElement): boolean { return false; } + public showKeyinPalette(_htmlElement?: HTMLElement): boolean { + return false; + } /** Hides the Keyin Palette. */ - public hideKeyinPalette(): boolean { return false; } + public hideKeyinPalette(): boolean { + return false; + } /** Send a UI event */ public static sendUiEvent(args: GenericUiEventArgs) { @@ -308,11 +390,18 @@ export class UiAdmin { * @param _optionalProps Optional props for Dialog construction. * @return true if the tool settings were displayed, false if the tool settings could not be displayed. */ - public openDialog(_uiDataProvider: DialogLayoutDataProvider, _title: string, _isModal: boolean, _id: string, - _optionalProps?: DialogProps): boolean { + public openDialog( + _uiDataProvider: DialogLayoutDataProvider, + _title: string, + _isModal: boolean, + _id: string, + _optionalProps?: DialogProps, + ): boolean { return false; } /** Closes the Dialog with a given Id. */ - public closeDialog(_dialogId: string): boolean { return false; } + public closeDialog(_dialogId: string): boolean { + return false; + } } diff --git a/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts b/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts index f60230a69911..db424811ade0 100644 --- a/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts +++ b/ui/appui-abstract/src/appui-abstract/UiItemsManager.ts @@ -11,9 +11,9 @@ import { BeEvent, Logger, MarkRequired } from "@itwin/core-bentley"; import { BackstageItem } from "./backstage/BackstageItem"; import { CommonStatusBarItem } from "./statusbar/StatusBarItem"; import { CommonToolbarItem, ToolbarOrientation, ToolbarUsage } from "./toolbars/ToolbarItem"; +import { UiItemsProvider } from "./UiItemsProvider"; import { AbstractWidgetProps } from "./widget/AbstractWidgetProps"; import { AbstractZoneLocation, StagePanelLocation, StagePanelSection } from "./widget/StagePanel"; -import { UiItemsProvider } from "./UiItemsProvider"; const loggerCategory = "appui-abstract.UiItemsManager"; /** Action taken by the application on item provided by a UiItemsProvider @@ -51,7 +51,7 @@ export interface AllowedUiItemProviderOverrides { stageUsages?: string[]; /** if specified then the current stage's Id will be compared before allowing any items to be provided * @beta - */ + */ stageIds?: string[]; } @@ -61,11 +61,15 @@ export interface AllowedUiItemProviderOverrides { * @deprecated in 3.6. Use [UiItemsProviderOverrides]($appui-react) instead. * @public */ -export type UiItemProviderOverrides = MarkRequired | - MarkRequired | // eslint-disable-line @typescript-eslint/indent - MarkRequired | // eslint-disable-line @typescript-eslint/indent - MarkRequired | // eslint-disable-line @typescript-eslint/indent - MarkRequired; // eslint-disable-line @typescript-eslint/indent +export type UiItemProviderOverrides = + | MarkRequired + | MarkRequired + | // eslint-disable-line @typescript-eslint/indent + MarkRequired + | // eslint-disable-line @typescript-eslint/indent + MarkRequired + | // eslint-disable-line @typescript-eslint/indent + MarkRequired; // eslint-disable-line @typescript-eslint/indent /** Interface that defines an instance of a UiItemsProvider and its application specified overrides. */ interface UiItemProviderEntry { @@ -162,8 +166,13 @@ export class UiItemsManager { * @param toolbarOrientation orientation of the toolbar * @returns an array of error messages. The array will be empty if the load is successful, otherwise it is a list of one or more problems. */ - public static getToolbarButtonItems(stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, - toolbarOrientation: ToolbarOrientation, stageAppData?: any): CommonToolbarItem[] { + public static getToolbarButtonItems( + stageId: string, + stageUsage: string, + toolbarUsage: ToolbarUsage, + toolbarOrientation: ToolbarOrientation, + stageAppData?: any, + ): CommonToolbarItem[] { const buttonItems: CommonToolbarItem[] = []; if (0 === UiItemsManager._registeredUiItemsProviders.size) return buttonItems; @@ -229,7 +238,7 @@ export class UiItemsManager { // istanbul ignore else if (uiProvider.provideBackstageItems) { // Note: We do not call this.allowItemsFromProvider here as backstage items - uiProvider.provideBackstageItems() // should not be considered stage specific. If they need to be hidden + uiProvider.provideBackstageItems() // should not be considered stage specific. If they need to be hidden .forEach((item: BackstageItem) => { // the isHidden property should be set to a ConditionalBooleanValue // ignore duplicate ids if (-1 === backstageItems.findIndex((existingItem) => item.id === existingItem.id)) @@ -247,7 +256,14 @@ export class UiItemsManager { * @param section the section within location. * @returns An array of AbstractWidgetProps that will be used to create widgets. */ - public static getWidgets(stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection, zoneLocation?: AbstractZoneLocation, stageAppData?: any): ReadonlyArray { + public static getWidgets( + stageId: string, + stageUsage: string, + location: StagePanelLocation, + section?: StagePanelSection, + zoneLocation?: AbstractZoneLocation, + stageAppData?: any, + ): ReadonlyArray { const widgets: AbstractWidgetProps[] = []; if (0 === UiItemsManager._registeredUiItemsProviders.size) @@ -269,5 +285,4 @@ export class UiItemsManager { }); return widgets; } - } diff --git a/ui/appui-abstract/src/appui-abstract/UiItemsProvider.ts b/ui/appui-abstract/src/appui-abstract/UiItemsProvider.ts index 261106156694..f15f8d543e75 100644 --- a/ui/appui-abstract/src/appui-abstract/UiItemsProvider.ts +++ b/ui/appui-abstract/src/appui-abstract/UiItemsProvider.ts @@ -21,7 +21,13 @@ export interface UiItemsProvider { readonly id: string; /** UiItemsManager calls following method to get items to populate specific toolbars */ - provideToolbarButtonItems?: (stageId: string, stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation, stageAppData?: any) => CommonToolbarItem[]; // eslint-disable-line deprecation/deprecation + provideToolbarButtonItems?: ( + stageId: string, + stageUsage: string, + toolbarUsage: ToolbarUsage, + toolbarOrientation: ToolbarOrientation, + stageAppData?: any, + ) => CommonToolbarItem[]; // eslint-disable-line deprecation/deprecation /** UiItemsManager calls following method to augment base statusbar for stages that allow it. */ provideStatusBarItems?: (stageId: string, stageUsage: string, stageAppData?: any) => CommonStatusBarItem[]; // eslint-disable-line deprecation/deprecation /** UiItemsManager calls following method to augment backstage items. */ @@ -29,8 +35,14 @@ export interface UiItemsProvider { /** UiItemsManager calls following method to augment Widget lists. * @note Returned widgets must provide unique `AbstractWidgetProps["id"]` to correctly save/restore App layout. */ - provideWidgets?: (stageId: string, stageUsage: string, location: StagePanelLocation, section?: StagePanelSection, // eslint-disable-line deprecation/deprecation - zoneLocation?: AbstractZoneLocation, stageAppData?: any) => ReadonlyArray; // eslint-disable-line deprecation/deprecation + provideWidgets?: ( + stageId: string, + stageUsage: string, + location: StagePanelLocation, + section?: StagePanelSection, // eslint-disable-line deprecation/deprecation + zoneLocation?: AbstractZoneLocation, + stageAppData?: any, + ) => ReadonlyArray; // eslint-disable-line deprecation/deprecation /** Function called when the provider is unregistered via `ItemsManager.unregister` to allow provider to do cleanup. */ onUnregister?: () => void; } diff --git a/ui/appui-abstract/src/appui-abstract/backstage/BackstageItem.ts b/ui/appui-abstract/src/appui-abstract/backstage/BackstageItem.ts index 48fab0d3f8c7..82ea6ebfe40a 100644 --- a/ui/appui-abstract/src/appui-abstract/backstage/BackstageItem.ts +++ b/ui/appui-abstract/src/appui-abstract/backstage/BackstageItem.ts @@ -103,8 +103,13 @@ export const isStageLauncher = (item: BackstageItem): item is BackstageStageLaun export class BackstageItemUtilities { /** Creates a stage launcher backstage item */ public static createStageLauncher = ( - frontstageId: string, groupPriority: number, itemPriority: number, label: string | ConditionalStringValue, - subtitle?: string | ConditionalStringValue, icon?: string | ConditionalStringValue, overrides?: Partial, // eslint-disable-line deprecation/deprecation + frontstageId: string, + groupPriority: number, + itemPriority: number, + label: string | ConditionalStringValue, + subtitle?: string | ConditionalStringValue, + icon?: string | ConditionalStringValue, + overrides?: Partial, // eslint-disable-line deprecation/deprecation ): BackstageStageLauncher => ({ // eslint-disable-line deprecation/deprecation groupPriority, icon, @@ -119,8 +124,14 @@ export class BackstageItemUtilities { /** Creates an action backstage item */ public static createActionItem = ( - itemId: string, groupPriority: number, itemPriority: number, execute: () => void, label: string | ConditionalStringValue, - subtitle?: string | ConditionalStringValue, icon?: string | ConditionalStringValue, overrides?: Partial, // eslint-disable-line deprecation/deprecation + itemId: string, + groupPriority: number, + itemPriority: number, + execute: () => void, + label: string | ConditionalStringValue, + subtitle?: string | ConditionalStringValue, + icon?: string | ConditionalStringValue, + overrides?: Partial, // eslint-disable-line deprecation/deprecation ): BackstageActionItem => ({ // eslint-disable-line deprecation/deprecation execute, groupPriority, diff --git a/ui/appui-abstract/src/appui-abstract/backstage/BackstageItemsManager.ts b/ui/appui-abstract/src/appui-abstract/backstage/BackstageItemsManager.ts index 65d3e3763f00..1b856dc458f6 100644 --- a/ui/appui-abstract/src/appui-abstract/backstage/BackstageItemsManager.ts +++ b/ui/appui-abstract/src/appui-abstract/backstage/BackstageItemsManager.ts @@ -115,7 +115,7 @@ export class BackstageItemsManager { for (const [, entry] of Object.entries(item)) { if (entry instanceof ConditionalBooleanValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); } } @@ -123,7 +123,10 @@ export class BackstageItemsManager { return [...eventIds.values()]; } - private internalRefreshAffectedItems(items: readonly BackstageItem[], eventIds: Set): { itemsUpdated: boolean, updatedItems: BackstageItem[] } { + private internalRefreshAffectedItems( + items: readonly BackstageItem[], + eventIds: Set, + ): { itemsUpdated: boolean, updatedItems: BackstageItem[] } { // istanbul ignore next if (0 === eventIds.size) return { itemsUpdated: false, updatedItems: [] }; @@ -139,7 +142,7 @@ export class BackstageItemsManager { // istanbul ignore else if (ConditionalBooleanValue.refreshValue(entry, eventIds)) updateRequired = true; - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { // istanbul ignore else if (ConditionalStringValue.refreshValue(entry, eventIds)) updateRequired = true; @@ -163,5 +166,4 @@ export class BackstageItemsManager { if (itemsUpdated) this.loadItemsInternal(updatedItems, false, true); } - } diff --git a/ui/appui-abstract/src/appui-abstract/content/StandardContentLayouts.ts b/ui/appui-abstract/src/appui-abstract/content/StandardContentLayouts.ts index cd356391ae21..3af97341e43c 100644 --- a/ui/appui-abstract/src/appui-abstract/content/StandardContentLayouts.ts +++ b/ui/appui-abstract/src/appui-abstract/content/StandardContentLayouts.ts @@ -30,8 +30,28 @@ export class StandardContentLayouts { lock: false, minSizeLeft: 100, minSizeRight: 100, - left: { horizontalSplit: { id: "uia:fourQuadrantsLeftHorizontal", percentage: 0.50, top: 0, bottom: 1, lock: false, minSizeTop: 50, minSizeBottom: 50 } }, - right: { horizontalSplit: { id: "uia:fourQuadrantsRightHorizontal", percentage: 0.50, top: 2, bottom: 3, lock: false, minSizeTop: 50, minSizeBottom: 50 } }, + left: { + horizontalSplit: { + id: "uia:fourQuadrantsLeftHorizontal", + percentage: 0.50, + top: 0, + bottom: 1, + lock: false, + minSizeTop: 50, + minSizeBottom: 50, + }, + }, + right: { + horizontalSplit: { + id: "uia:fourQuadrantsRightHorizontal", + percentage: 0.50, + top: 2, + bottom: 3, + lock: false, + minSizeTop: 50, + minSizeBottom: 50, + }, + }, }, }; @@ -63,7 +83,9 @@ export class StandardContentLayouts { verticalSplit: { id: "uia:twoViewsOnLeftSplit", percentage: 0.50, - left: { horizontalSplit: { id: "uia:twoViewsOnLeftHorizontal", percentage: 0.50, top: 0, bottom: 1, lock: false, minSizeTop: 50, minSizeBottom: 50 } }, + left: { + horizontalSplit: { id: "uia:twoViewsOnLeftHorizontal", percentage: 0.50, top: 0, bottom: 1, lock: false, minSizeTop: 50, minSizeBottom: 50 }, + }, right: 2, }, }; @@ -75,7 +97,9 @@ export class StandardContentLayouts { id: "uia:twoViewsOnRightSplit", percentage: 0.50, left: 0, - right: { horizontalSplit: { id: "uia:twoViewsOnRightHorizontal", percentage: 0.50, top: 1, bottom: 2, lock: false, minSizeTop: 50, minSizeBottom: 50 } }, + right: { + horizontalSplit: { id: "uia:twoViewsOnRightHorizontal", percentage: 0.50, top: 1, bottom: 2, lock: false, minSizeTop: 50, minSizeBottom: 50 }, + }, }, }; @@ -87,7 +111,9 @@ export class StandardContentLayouts { percentage: 0.50, lock: false, top: 0, - bottom: { verticalSplit: { id: "uia:twoViewsOnBottomVertical", percentage: 0.50, left: 1, right: 2, lock: false, minSizeLeft: 50, minSizeRight: 50 } }, + bottom: { + verticalSplit: { id: "uia:twoViewsOnBottomVertical", percentage: 0.50, left: 1, right: 2, lock: false, minSizeLeft: 50, minSizeRight: 50 }, + }, }, }; @@ -98,7 +124,9 @@ export class StandardContentLayouts { id: "uia:twoViewsOnTopHorizontal", percentage: 0.50, lock: false, - top: { verticalSplit: { id: "uia:twoViewsOnTopVertical", percentage: 0.50, left: 0, right: 1, lock: false, minSizeLeft: 50, minSizeRight: 50 } }, + top: { + verticalSplit: { id: "uia:twoViewsOnTopVertical", percentage: 0.50, left: 0, right: 1, lock: false, minSizeLeft: 50, minSizeRight: 50 }, + }, bottom: 2, }, }; @@ -114,5 +142,4 @@ export class StandardContentLayouts { StandardContentLayouts.threeViewsTwoOnBottom, StandardContentLayouts.threeViewsTwoOnTop, ]; - } diff --git a/ui/appui-abstract/src/appui-abstract/dialogs/DialogItem.ts b/ui/appui-abstract/src/appui-abstract/dialogs/DialogItem.ts index 6883185f17f5..a386c05b1551 100644 --- a/ui/appui-abstract/src/appui-abstract/dialogs/DialogItem.ts +++ b/ui/appui-abstract/src/appui-abstract/dialogs/DialogItem.ts @@ -65,7 +65,7 @@ export interface DialogPropertySyncItem extends DialogPropertyItem { * @public */ export class DialogProperty { - constructor(public description: PropertyDescription, private _value: T, private _displayValue?: string, private _isDisabled?: boolean) { } + constructor(public description: PropertyDescription, private _value: T, private _displayValue?: string, private _isDisabled?: boolean) {} public get isDisabled() { return !!this._isDisabled; @@ -97,7 +97,10 @@ export class DialogProperty { public get dialogItemValue() { // istanbul ignore else - if (typeof this._value === "string" || typeof this._value === "number" || typeof this._value === "undefined" || typeof this._value === "boolean" || this._value instanceof Date) + if ( + typeof this._value === "string" || typeof this._value === "number" || typeof this._value === "undefined" || typeof this._value === "boolean" || + this._value instanceof Date + ) return { value: this._value, displayValue: this._displayValue, diff --git a/ui/appui-abstract/src/appui-abstract/dialogs/UiDataProvider.ts b/ui/appui-abstract/src/appui-abstract/dialogs/UiDataProvider.ts index 5ceaf8f7c699..4c2a0d0c47e0 100644 --- a/ui/appui-abstract/src/appui-abstract/dialogs/UiDataProvider.ts +++ b/ui/appui-abstract/src/appui-abstract/dialogs/UiDataProvider.ts @@ -12,7 +12,7 @@ import { DialogPropertyItem, DialogPropertySyncItem } from "./DialogItem"; /** Sync UI Control Properties Event class. * @public */ -export class SyncPropertiesChangeEvent extends BeUiEvent { } +export class SyncPropertiesChangeEvent extends BeUiEvent {} /** [[UiDataProvider]] Abstract class that allows property values to be passed between hosting API and UI. * @public @@ -54,7 +54,9 @@ export abstract class UiDataProvider { * properties that will be used to dynamically create and layout control in a Dialog or Widget. */ public supplyAvailableProperties(): DialogPropertyItem[] { - throw (new Error("Derived UiDataProvider that want to use DialogPropertyItems must implement this method. Not for use with dynamic UI controls.")); + throw (new Error( + "Derived UiDataProvider that want to use DialogPropertyItems must implement this method. Not for use with dynamic UI controls.", + )); } } diff --git a/ui/appui-abstract/src/appui-abstract/dialogs/UiLayoutDataProvider.ts b/ui/appui-abstract/src/appui-abstract/dialogs/UiLayoutDataProvider.ts index fb87ef9d59d9..48e47a5fe3e0 100644 --- a/ui/appui-abstract/src/appui-abstract/dialogs/UiLayoutDataProvider.ts +++ b/ui/appui-abstract/src/appui-abstract/dialogs/UiLayoutDataProvider.ts @@ -25,7 +25,7 @@ export enum DialogButtonType { No = "no", Retry = "retry", Next = "next", - Previous = "previous" + Previous = "previous", } /** Enum for button style. @@ -144,7 +144,9 @@ export abstract class UiLayoutDataProvider extends UiDataProvider { /** Determines if a dialog item editor wants a label */ public static editorWantsLabel(item: DialogItem): boolean { if (item.property.editor && item.property.editor.params) { - const params = item.property.editor.params.find((param: PropertyEditorParams) => param.type === PropertyEditorParamTypes.SuppressEditorLabel) as SuppressLabelEditorParams; + const params = item.property.editor.params.find((param: PropertyEditorParams) => + param.type === PropertyEditorParamTypes.SuppressEditorLabel + ) as SuppressLabelEditorParams; // istanbul ignore else if (params) return false; @@ -183,7 +185,10 @@ export abstract class UiLayoutDataProvider extends UiDataProvider { public static onlyContainButtonGroupEditors(row: DialogRow): boolean { for (const item of row.items) { // istanbul ignore else - if (UiLayoutDataProvider.hasAssociatedLockProperty(item) || undefined === item.property.editor || "enum-buttongroup" !== item.property.editor.name || UiLayoutDataProvider.editorWantsLabel(item)) + if ( + UiLayoutDataProvider.hasAssociatedLockProperty(item) || undefined === item.property.editor || + "enum-buttongroup" !== item.property.editor.name || UiLayoutDataProvider.editorWantsLabel(item) + ) return false; } return true; @@ -206,9 +211,9 @@ export abstract class DialogLayoutDataProvider extends UiLayoutDataProvider { // Derived class should override const buttons: DialogButtonDef[] = []; // istanbul ignore next - buttons.push({ type: DialogButtonType.OK, onClick: () => { } }); + buttons.push({ type: DialogButtonType.OK, onClick: () => {} }); // istanbul ignore next - buttons.push({ type: DialogButtonType.Cancel, onClick: () => { } }); + buttons.push({ type: DialogButtonType.Cancel, onClick: () => {} }); return buttons; } } diff --git a/ui/appui-abstract/src/appui-abstract/items/AbstractItemProps.ts b/ui/appui-abstract/src/appui-abstract/items/AbstractItemProps.ts index f0378cb595a4..970afd22aaab 100644 --- a/ui/appui-abstract/src/appui-abstract/items/AbstractItemProps.ts +++ b/ui/appui-abstract/src/appui-abstract/items/AbstractItemProps.ts @@ -17,7 +17,7 @@ export type StringGetter = () => string; /** Definition that specifies properties shared between many ConfigurableUi components. * @public - */ + */ export interface CommonItemProps { /** can be used by application to store miscellaneous data. */ applicationData?: any; @@ -46,7 +46,7 @@ export interface CommonItemProps { /** Definition for a command handler. * @public - */ + */ export interface CommandHandler { /** Function to execute */ execute?: (args?: any) => any; diff --git a/ui/appui-abstract/src/appui-abstract/items/AbstractToolbarProps.ts b/ui/appui-abstract/src/appui-abstract/items/AbstractToolbarProps.ts index 57c4f99536b1..6689a8a732c4 100644 --- a/ui/appui-abstract/src/appui-abstract/items/AbstractToolbarProps.ts +++ b/ui/appui-abstract/src/appui-abstract/items/AbstractToolbarProps.ts @@ -10,7 +10,7 @@ import { CommonToolbarItem } from "../toolbars/ToolbarItem"; /** Definition for a Toolbar. * @public - */ + */ export interface AbstractToolbarProps { /** Id of Toolbar */ toolbarId?: string; diff --git a/ui/appui-abstract/src/appui-abstract/notification/MessagePresenter.ts b/ui/appui-abstract/src/appui-abstract/notification/MessagePresenter.ts index 88d060a02cb5..9272aa97356f 100644 --- a/ui/appui-abstract/src/appui-abstract/notification/MessagePresenter.ts +++ b/ui/appui-abstract/src/appui-abstract/notification/MessagePresenter.ts @@ -33,7 +33,12 @@ export interface MessagePresenter { * @param detailedMessage An optional comprehensive message that explains the issue in detail and potentially offers a solution. * @param messageType The type of message. Defaults to Toast. */ - displayMessage(severity: MessageSeverity, briefMessage: HTMLElement | string, detailedMessage?: HTMLElement | string, messageType?: DisplayMessageType): void; + displayMessage( + severity: MessageSeverity, + briefMessage: HTMLElement | string, + detailedMessage?: HTMLElement | string, + messageType?: DisplayMessageType, + ): void; /** * Displays an input field message. @@ -42,7 +47,12 @@ export interface MessagePresenter { * @param briefMessage A short message that conveys the simplest explanation of the issue. * @param detailedMessage An optional comprehensive message that explains the issue in detail and potentially offers a solution. */ - displayInputFieldMessage(inputField: HTMLElement, severity: MessageSeverity, briefMessage: HTMLElement | string, detailedMessage?: HTMLElement | string): void; + displayInputFieldMessage( + inputField: HTMLElement, + severity: MessageSeverity, + briefMessage: HTMLElement | string, + detailedMessage?: HTMLElement | string, + ): void; /** * Close message created with `displayInputFieldMessage`. diff --git a/ui/appui-abstract/src/appui-abstract/notification/MessageSeverity.ts b/ui/appui-abstract/src/appui-abstract/notification/MessageSeverity.ts index e076b7fbb2e1..7d533fce0aa4 100644 --- a/ui/appui-abstract/src/appui-abstract/notification/MessageSeverity.ts +++ b/ui/appui-abstract/src/appui-abstract/notification/MessageSeverity.ts @@ -7,8 +7,8 @@ */ /** Message Severity enum for display messages. - * @public - */ + * @public + */ export enum MessageSeverity { None = 0, Information = 1, diff --git a/ui/appui-abstract/src/appui-abstract/properties/Description.ts b/ui/appui-abstract/src/appui-abstract/properties/Description.ts index 85c3d75151c7..1f851a82a808 100644 --- a/ui/appui-abstract/src/appui-abstract/properties/Description.ts +++ b/ui/appui-abstract/src/appui-abstract/properties/Description.ts @@ -7,7 +7,12 @@ */ import { - BasePropertyEditorParams, ColorEditorParams, ImageCheckBoxParams, PropertyEditorParams, PropertyEditorParamTypes, RangeEditorParams, + BasePropertyEditorParams, + ColorEditorParams, + ImageCheckBoxParams, + PropertyEditorParams, + PropertyEditorParamTypes, + RangeEditorParams, SuppressLabelEditorParams, } from "./EditorParams"; import { StandardEditorNames } from "./StandardEditorNames"; @@ -116,7 +121,12 @@ export class PropertyDescriptionHelper { /** Builds an editor that uses [NumberInput]($core-react) control * @public */ - public static buildNumberEditorDescription(name: string, label: string, overrideParams?: RangeEditorParams, additionalParams: BasePropertyEditorParams[] = []): PropertyDescription { + public static buildNumberEditorDescription( + name: string, + label: string, + overrideParams?: RangeEditorParams, + additionalParams: BasePropertyEditorParams[] = [], + ): PropertyDescription { const editorParams = [{ type: PropertyEditorParamTypes.Range, step: 1, @@ -156,12 +166,17 @@ export class PropertyDescriptionHelper { /** Builds an enum description * @public */ - public static buildEnumPicklistEditorDescription(name: string, label: string, + public static buildEnumPicklistEditorDescription( + name: string, + label: string, choices: Promise | EnumerationChoice[], - additionalParams: BasePropertyEditorParams[] = []): PropertyDescription { - const editor = additionalParams.length ? { - params: additionalParams, - } : undefined; + additionalParams: BasePropertyEditorParams[] = [], + ): PropertyDescription { + const editor = additionalParams.length ? + { + params: additionalParams, + } : + undefined; return { name, @@ -177,8 +192,13 @@ export class PropertyDescriptionHelper { /** Builds a number description for a tool settings or dialog property that will display a "color-picker" control. * @public */ - public static buildColorPickerDescription(name: string, label: string, colorValues: number[], numColumns: number, - additionalParams: BasePropertyEditorParams[] = []): PropertyDescription { + public static buildColorPickerDescription( + name: string, + label: string, + colorValues: number[], + numColumns: number, + additionalParams: BasePropertyEditorParams[] = [], + ): PropertyDescription { const editorParams = [ { type: PropertyEditorParamTypes.ColorData, @@ -217,7 +237,13 @@ export class PropertyDescriptionHelper { /** Builds a boolean description for a tool settings or dialog property that will display a "image-check-box" control. * @public */ - public static buildImageCheckBoxDescription(name: string, label: string, imageOff: string, imageOn: string, additionalParams: BasePropertyEditorParams[] = []): PropertyDescription { + public static buildImageCheckBoxDescription( + name: string, + label: string, + imageOff: string, + imageOn: string, + additionalParams: BasePropertyEditorParams[] = [], + ): PropertyDescription { const editorParams = [{ type: PropertyEditorParamTypes.CheckBoxImages, imageOff, diff --git a/ui/appui-abstract/src/appui-abstract/properties/EditorParams.ts b/ui/appui-abstract/src/appui-abstract/properties/EditorParams.ts index 05f867e4eb43..c7ce8e744796 100644 --- a/ui/appui-abstract/src/appui-abstract/properties/EditorParams.ts +++ b/ui/appui-abstract/src/appui-abstract/properties/EditorParams.ts @@ -295,7 +295,6 @@ export interface ImageCheckBoxParams extends BasePropertyEditorParams { type: PropertyEditorParamTypes.CheckBoxImages; imageOn: string; imageOff: string; - } // /** diff --git a/ui/appui-abstract/src/appui-abstract/properties/StandardTypeNames.ts b/ui/appui-abstract/src/appui-abstract/properties/StandardTypeNames.ts index 735dbd67e355..7bcedd12ed08 100644 --- a/ui/appui-abstract/src/appui-abstract/properties/StandardTypeNames.ts +++ b/ui/appui-abstract/src/appui-abstract/properties/StandardTypeNames.ts @@ -15,7 +15,7 @@ export enum StandardTypeNames { Text = "text", String = "string", - DateTime = "dateTime", // locale specific + DateTime = "dateTime", // locale specific ShortDate = "shortdate", // locale specific Boolean = "boolean", Bool = "bool", diff --git a/ui/appui-abstract/src/appui-abstract/quantity/BaseQuantityDescription.ts b/ui/appui-abstract/src/appui-abstract/quantity/BaseQuantityDescription.ts index 3f81ca9abc57..3f9f54ae0de8 100644 --- a/ui/appui-abstract/src/appui-abstract/quantity/BaseQuantityDescription.ts +++ b/ui/appui-abstract/src/appui-abstract/quantity/BaseQuantityDescription.ts @@ -8,8 +8,8 @@ import { PropertyDescription, PropertyEditorInfo } from "../properties/Description"; import { CustomFormattedNumberParams, IconEditorParams, ParseResults, PropertyEditorParamTypes } from "../properties/EditorParams"; -import { StandardTypeNames } from "../properties/StandardTypeNames"; import { StandardEditorNames } from "../properties/StandardEditorNames"; +import { StandardTypeNames } from "../properties/StandardTypeNames"; /** * Base Quantity Property Description @@ -31,8 +31,7 @@ export abstract class BaseQuantityDescription implements PropertyDescription { type: PropertyEditorParamTypes.CustomFormattedNumber, formatFunction: this.format, parseFunction: this.parse, - } as CustomFormattedNumberParams, - ], + } as CustomFormattedNumberParams], }; // istanbul ignore else @@ -59,5 +58,4 @@ export abstract class BaseQuantityDescription implements PropertyDescription { public abstract get quantityType(): string; public abstract get parseError(): string; - } diff --git a/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItem.ts b/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItem.ts index d19414e185ee..0eb5749bb85d 100644 --- a/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItem.ts +++ b/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItem.ts @@ -19,15 +19,15 @@ export enum StatusBarSection { /** area for tool assistance and messages */ Message = 0, /** area for tool assistance and messages */ - Left = 0, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values + Left = 0, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values /** items specific to stage/task */ Stage = 1, /** items specific to stage/task */ - Center = 1, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values + Center = 1, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values /** Select scope and selection info */ Selection = 2, /** Select scope and selection info */ - Right = 2, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values + Right = 2, // eslint-disable-line @typescript-eslint/no-duplicate-enum-values /** items that only show based on context */ Context = 3, } @@ -145,17 +145,39 @@ export const isAbstractStatusBarCustomItem = (item: CommonStatusBarItem): item i */ export class AbstractStatusBarItemUtilities { /** Creates a StatusBar item to perform an action */ - public static createActionItem = (id: string, section: StatusBarSection, itemPriority: number, icon: string | ConditionalStringValue, tooltip: string | ConditionalStringValue, execute: () => void, overrides?: Partial): AbstractStatusBarActionItem => ({ // eslint-disable-line deprecation/deprecation - id, section, itemPriority, - icon, tooltip, + public static createActionItem = ( + id: string, + section: StatusBarSection, + itemPriority: number, + icon: string | ConditionalStringValue, + tooltip: string | ConditionalStringValue, + execute: () => void, + overrides?: Partial, + ): AbstractStatusBarActionItem => ({ // eslint-disable-line deprecation/deprecation + id, + section, + itemPriority, + icon, + tooltip, execute, ...overrides, }); /** Creates a StatusBar item to display a label */ - public static createLabelItem = (id: string, section: StatusBarSection, itemPriority: number, icon: string | ConditionalStringValue, label: string | ConditionalStringValue, labelSide = StatusBarLabelSide.Right, overrides?: Partial): AbstractStatusBarLabelItem => ({ // eslint-disable-line deprecation/deprecation - id, section, itemPriority, - icon, label, + public static createLabelItem = ( + id: string, + section: StatusBarSection, + itemPriority: number, + icon: string | ConditionalStringValue, + label: string | ConditionalStringValue, + labelSide = StatusBarLabelSide.Right, + overrides?: Partial, + ): AbstractStatusBarLabelItem => ({ // eslint-disable-line deprecation/deprecation + id, + section, + itemPriority, + icon, + label, labelSide, ...overrides, }); diff --git a/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItemsManager.ts b/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItemsManager.ts index 344de57aa87e..832095374eba 100644 --- a/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItemsManager.ts +++ b/ui/appui-abstract/src/appui-abstract/statusbar/StatusBarItemsManager.ts @@ -96,8 +96,7 @@ export class StatusBarItemsManager { } /** Remove StatusBar items based on id */ - public remove(itemIdOrItemIds: StatusBarItemId | ReadonlyArray) { + public remove(itemIdOrItemIds: StatusBarItemId | ReadonlyArray) { const items = this._items.filter((item) => { return isInstance(itemIdOrItemIds) ? item.id !== itemIdOrItemIds : !itemIdOrItemIds.find((itemId) => itemId === item.id); }); @@ -115,7 +114,7 @@ export class StatusBarItemsManager { for (const [, entry] of Object.entries(item)) { if (entry instanceof ConditionalBooleanValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); } } @@ -123,7 +122,10 @@ export class StatusBarItemsManager { return [...eventIds.values()]; } - private internalRefreshAffectedItems(items: readonly CommonStatusBarItem[], eventIds: Set): { itemsUpdated: boolean, updatedItems: CommonStatusBarItem[] } { + private internalRefreshAffectedItems( + items: readonly CommonStatusBarItem[], + eventIds: Set, + ): { itemsUpdated: boolean, updatedItems: CommonStatusBarItem[] } { // istanbul ignore next if (0 === eventIds.size) return { itemsUpdated: false, updatedItems: [] }; @@ -139,7 +141,7 @@ export class StatusBarItemsManager { // istanbul ignore else if (ConditionalBooleanValue.refreshValue(entry, eventIds)) updateRequired = true; - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { // istanbul ignore else if (ConditionalStringValue.refreshValue(entry, eventIds)) updateRequired = true; diff --git a/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItem.ts b/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItem.ts index d6b6e2177ede..15aa685dd24e 100644 --- a/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItem.ts +++ b/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItem.ts @@ -123,17 +123,35 @@ export type ToolbarItemId = CommonToolbarItem["id"]; // eslint-disable-line depr */ export class ToolbarItemUtilities { /** Creates an Action Button */ - public static createActionButton = (id: string, itemPriority: number, icon: string | ConditionalStringValue, label: string | ConditionalStringValue, execute: () => void, overrides?: Partial): ActionButton => ({ - id, itemPriority, - icon, label, + public static createActionButton = ( + id: string, + itemPriority: number, + icon: string | ConditionalStringValue, + label: string | ConditionalStringValue, + execute: () => void, + overrides?: Partial, + ): ActionButton => ({ + id, + itemPriority, + icon, + label, execute, ...overrides, }); /** Creates a Group button. */ - public static createGroupButton = (id: string, itemPriority: number, icon: string | ConditionalStringValue, label: string | ConditionalStringValue, items: ReadonlyArray, overrides?: Partial): GroupButton => ({ - id, itemPriority, - icon, label, + public static createGroupButton = ( + id: string, + itemPriority: number, + icon: string | ConditionalStringValue, + label: string | ConditionalStringValue, + items: ReadonlyArray, + overrides?: Partial, + ): GroupButton => ({ + id, + itemPriority, + icon, + label, items, ...overrides, }); diff --git a/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItemsManager.ts b/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItemsManager.ts index 6dd914b4a8b3..3d44baac1090 100644 --- a/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItemsManager.ts +++ b/ui/appui-abstract/src/appui-abstract/toolbars/ToolbarItemsManager.ts @@ -96,8 +96,7 @@ export class ToolbarItemsManager { } /** Remove Toolbar items based on id */ - public remove(itemIdOrItemIds: ToolbarItemId | ReadonlyArray) { + public remove(itemIdOrItemIds: ToolbarItemId | ReadonlyArray) { const items = this._items.filter((item) => { return isInstance(itemIdOrItemIds) ? item.id !== itemIdOrItemIds : !itemIdOrItemIds.find((itemId) => itemId === item.id); }); @@ -114,7 +113,7 @@ export class ToolbarItemsManager { for (const [, entry] of Object.entries(item)) { if (entry instanceof ConditionalBooleanValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { entry.syncEventIds.forEach((eventId: string) => eventIds.add(eventId.toLowerCase())); } } @@ -132,7 +131,10 @@ export class ToolbarItemsManager { return [...eventIds.values()]; } - private static refreshChildItems(parentItem: GroupButton, eventIds: Set): { childrenUpdated: boolean, childItems: ReadonlyArray } { + private static refreshChildItems( + parentItem: GroupButton, + eventIds: Set, + ): { childrenUpdated: boolean, childItems: ReadonlyArray } { const updatedItems: Array = []; let itemsUpdated = false; @@ -153,7 +155,7 @@ export class ToolbarItemsManager { // istanbul ignore else if (ConditionalBooleanValue.refreshValue(entry, eventIds)) itemsUpdated = true; - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { // istanbul ignore else if (ConditionalStringValue.refreshValue(entry, eventIds)) itemsUpdated = true; @@ -165,7 +167,10 @@ export class ToolbarItemsManager { return { childrenUpdated: itemsUpdated, childItems: updatedItems }; } - private internalRefreshAffectedItems(items: readonly CommonToolbarItem[], eventIds: Set): { itemsUpdated: boolean, updatedItems: CommonToolbarItem[] } { + private internalRefreshAffectedItems( + items: readonly CommonToolbarItem[], + eventIds: Set, + ): { itemsUpdated: boolean, updatedItems: CommonToolbarItem[] } { // istanbul ignore next if (0 === eventIds.size) return { itemsUpdated: false, updatedItems: [] }; @@ -190,7 +195,7 @@ export class ToolbarItemsManager { // istanbul ignore else if (ConditionalBooleanValue.refreshValue(entry, eventIds)) updateRequired = true; - } else /* istanbul ignore else */ if (entry instanceof ConditionalStringValue) { + } /* istanbul ignore else */ else if (entry instanceof ConditionalStringValue) { // istanbul ignore else if (ConditionalStringValue.refreshValue(entry, eventIds)) updateRequired = true; @@ -253,7 +258,7 @@ export class ToolbarItemsManager { updatedItem.items = ToolbarItemsManager.refreshActiveToolIdInChildItems(updatedItem, toolId); } - updatedItem.isActive = (updatedItem.id === toolId); + updatedItem.isActive = updatedItem.id === toolId; newChildren.push(updatedItem); } return newChildren; @@ -272,11 +277,10 @@ export class ToolbarItemsManager { updatedItem.items = ToolbarItemsManager.refreshActiveToolIdInChildItems(updatedItem, toolId); } - updatedItem.isActive = (updatedItem.id === toolId); + updatedItem.isActive = updatedItem.id === toolId; newItems.push(updatedItem); } this.items = newItems; } - } diff --git a/ui/appui-abstract/src/appui-abstract/utils/IconSpecUtilities.ts b/ui/appui-abstract/src/appui-abstract/utils/IconSpecUtilities.ts index cfab2e5e37b5..fd0c8f23d809 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/IconSpecUtilities.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/IconSpecUtilities.ts @@ -19,13 +19,13 @@ export class IconSpecUtilities { /** Create an IconSpec for an SVG loaded into web component with sprite loader * This method is deprecated -- use createWebComponentIconSpec() * @public @deprecated in 3.2. Please avoid using the Sprite loader and use IconSpecUtilities.createWebComponentIconSpec() instead. - */ + */ public static createSvgIconSpec(svgSrc: string): string { return `${IconSpecUtilities.SVG_PREFIX}${svgSrc}`; } /** Create an IconSpec for an SVG loaded into web component with svg-loader * @public @deprecated in 4.3. AppUI libraries > 4.7.x support loading SVGs sources without prefixes, eliminating the need for this utility. - */ + */ public static createWebComponentIconSpec(srcString: string): string { return `${IconSpecUtilities.WEB_COMPONENT_PREFIX}${srcString}`; } @@ -33,7 +33,7 @@ export class IconSpecUtilities { /** Get the SVG Source from an sprite IconSpec * This method is deprecated -- use getWebComponentSource() * @public @deprecated in 3.2. avoid using the Sprite loader and use IconSpecUtilities.getWebComponentSource() instead. - */ + */ public static getSvgSource(iconSpec: string): string | undefined { if (iconSpec.startsWith(IconSpecUtilities.SVG_PREFIX) && iconSpec.length > 4) { return iconSpec.slice(4); @@ -43,7 +43,7 @@ export class IconSpecUtilities { } /** Get the SVG Source from an svg-loader IconSpec * @public @deprecated in 4.3. AppUI libraries > 4.7.x support loading SVGs sources without prefixes, eliminating the need for this utility. - */ + */ public static getWebComponentSource(iconSpec: string): string | undefined { if (iconSpec.startsWith(IconSpecUtilities.WEB_COMPONENT_PREFIX) && iconSpec.length > 7) { @@ -51,6 +51,5 @@ export class IconSpecUtilities { } return undefined; - } } diff --git a/ui/appui-abstract/src/appui-abstract/utils/UiError.ts b/ui/appui-abstract/src/appui-abstract/utils/UiError.ts index 7635401dec05..21b6d8ef1ed9 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/UiError.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/UiError.ts @@ -12,7 +12,6 @@ import { BentleyError, BentleyStatus, GetMetaDataFunction } from "@itwin/core-be * @public @deprecated in 4.3. Use [[Bentley.BentleyError]] instead. */ export class UiError extends BentleyError { - /** Constructs UiError using BentleyError. */ public constructor(public category: string, message: string, errorNumber: number = BentleyStatus.ERROR, getMetaData?: GetMetaDataFunction) { super(errorNumber, message, getMetaData); diff --git a/ui/appui-abstract/src/appui-abstract/utils/UiEvent.ts b/ui/appui-abstract/src/appui-abstract/utils/UiEvent.ts index 0b6212fc0e9d..577d98eff0b0 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/UiEvent.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/UiEvent.ts @@ -12,4 +12,4 @@ import { BeUiEvent } from "@itwin/core-bentley"; * @public * @deprecated in 4.2. This type is a duplicate of [[BeUiEvent]], which should be used instead. */ -export class UiEvent extends BeUiEvent { } +export class UiEvent extends BeUiEvent {} diff --git a/ui/appui-abstract/src/appui-abstract/utils/UiEventDispatcher.ts b/ui/appui-abstract/src/appui-abstract/utils/UiEventDispatcher.ts index b1864b685e5c..8a4e654693c2 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/UiEventDispatcher.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/UiEventDispatcher.ts @@ -21,7 +21,7 @@ export interface UiSyncEventArgs { * @deprecated in 4.2.x Use [[UiSyncEvent]] from @itwin/appui-react. */ // eslint-disable-next-line deprecation/deprecation -export class UiSyncEvent extends BeUiEvent { } +export class UiSyncEvent extends BeUiEvent {} /** This class is used to send eventIds to interested UI components so the component can determine if it needs * to refresh its display by calling setState on itself. @@ -93,8 +93,10 @@ export class UiEventDispatcher { } this.syncEventIds.add(eventId.toLowerCase()); - if (!this._syncEventTimerId) { // if there is not a timer active, create one - this._syncEventTimerId = window.setTimeout(() => { this.checkForAdditionalIds(); }, this._timeoutPeriod); + if (!this._syncEventTimerId) { // if there is not a timer active, create one + this._syncEventTimerId = window.setTimeout(() => { + this.checkForAdditionalIds(); + }, this._timeoutPeriod); } else { this._eventIdAdded = true; } @@ -109,8 +111,10 @@ export class UiEventDispatcher { eventIds.forEach((id) => this.syncEventIds.add(id.toLowerCase())); // istanbul ignore else - if (!this._syncEventTimerId) { // if there is not a timer active, create one - this._syncEventTimerId = window.setTimeout(() => { this.checkForAdditionalIds(); }, this._timeoutPeriod); + if (!this._syncEventTimerId) { // if there is not a timer active, create one + this._syncEventTimerId = window.setTimeout(() => { + this.checkForAdditionalIds(); + }, this._timeoutPeriod); } else { this._eventIdAdded = true; } @@ -145,7 +149,9 @@ export class UiEventDispatcher { this._eventIdAdded = false; // if events have been added before the initial timer expired wait half that time to see if events are still being added. // istanbul ignore next - this._syncEventTimerId = window.setTimeout(() => { this.checkForAdditionalIds(); }, this._secondaryTimeoutPeriod); + this._syncEventTimerId = window.setTimeout(() => { + this.checkForAdditionalIds(); + }, this._secondaryTimeoutPeriod); } /** Checks to see if an eventId of interest is contained in the set of eventIds */ diff --git a/ui/appui-abstract/src/appui-abstract/utils/filter/filters.ts b/ui/appui-abstract/src/appui-abstract/utils/filter/filters.ts index 165d66292b01..86f8bfd36280 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/filter/filters.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/filter/filters.ts @@ -21,7 +21,7 @@ enum CharCode { Space = 32, Tab = 9, LineFeed = 10, - CarriageReturn = 13 + CarriageReturn = 13, } function isWhitespace(code: number): boolean { @@ -33,7 +33,7 @@ function isWhitespace(code: number): boolean { ); } const wordSeparators = new Set(); -'`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?' +"`~!@#$%^&*()-=+[{]}\\|;:'\",.<>/?" .split("") .forEach((s) => wordSeparators.add(s.charCodeAt(0))); @@ -106,8 +106,10 @@ function _matchesWords(word: string, target: string, i: number, j: number, conti function nextWord(word: string, start: number): number { for (let i = start; i < word.length; i++) { - if (isWordSeparator(word.charCodeAt(i)) || - (i > 0 && isWordSeparator(word.charCodeAt(i - 1)))) { + if ( + isWordSeparator(word.charCodeAt(i)) || + (i > 0 && isWordSeparator(word.charCodeAt(i - 1))) + ) { return i; } } diff --git a/ui/appui-abstract/src/appui-abstract/utils/misc.ts b/ui/appui-abstract/src/appui-abstract/utils/misc.ts index 5790e3b113de..9c6dd074082c 100644 --- a/ui/appui-abstract/src/appui-abstract/utils/misc.ts +++ b/ui/appui-abstract/src/appui-abstract/utils/misc.ts @@ -25,4 +25,3 @@ export const getClassName = (obj: any): string => { return className; }; - diff --git a/ui/appui-abstract/src/appui-abstract/widget/AbstractWidgetProps.ts b/ui/appui-abstract/src/appui-abstract/widget/AbstractWidgetProps.ts index 532c4eaf4747..27ff13afa937 100644 --- a/ui/appui-abstract/src/appui-abstract/widget/AbstractWidgetProps.ts +++ b/ui/appui-abstract/src/appui-abstract/widget/AbstractWidgetProps.ts @@ -6,8 +6,8 @@ * @module Widget */ -import { ConditionalStringValue } from "../items/ConditionalStringValue"; import { BadgeType } from "../items/BadgeType"; +import { ConditionalStringValue } from "../items/ConditionalStringValue"; import { ProvidedItem } from "../items/ProvidedItem"; import { WidgetState } from "./WidgetState"; @@ -32,7 +32,7 @@ export interface AbstractWidgetProps extends ProvidedItem { // eslint-disable-li readonly tooltip?: string | ConditionalStringValue; /** Indicates whether the Widget is free-form or rectangular. Defaults to false for rectangular. The default is false. * @deprecated in 3.0. Free-form widgets are obsolete. - * */ + */ readonly isFreeform?: boolean; /** Application data attached to the Widget. */ readonly applicationData?: any; @@ -62,7 +62,7 @@ export interface AbstractWidgetProps extends ProvidedItem { // eslint-disable-li /** Function executed to determine the state of the widget. * Used by UI 1.0 widgets ONLY. * @deprecated in 3.3. UI 1.0 support will be removed in AppUi 4.0. - */ + */ readonly stateFunc?: (state: Readonly) => WidgetState; // eslint-disable-line deprecation/deprecation /** Badge to be overlaid on the widget tab. */ readonly badgeType?: BadgeType; @@ -82,5 +82,5 @@ export interface AbstractWidgetProps extends ProvidedItem { // eslint-disable-li hideWithUiWhenFloating?: boolean; /** Optional prop specifying which Panel sides can be docking targets for this widget. If this prop is not specified, all sides are allowed. * An empty array is treated the same as an undefined prop, allowing all targets. */ - readonly allowedPanelTargets?: ReadonlyArray<"left"|"right"|"bottom"|"top">; + readonly allowedPanelTargets?: ReadonlyArray<"left" | "right" | "bottom" | "top">; } diff --git a/ui/appui-abstract/src/appui-abstract/widget/WidgetState.ts b/ui/appui-abstract/src/appui-abstract/widget/WidgetState.ts index a7d049bc2290..7891bd2c21d9 100644 --- a/ui/appui-abstract/src/appui-abstract/widget/WidgetState.ts +++ b/ui/appui-abstract/src/appui-abstract/widget/WidgetState.ts @@ -9,7 +9,7 @@ /** Widget state enum. * @deprecated in 3.6. Use [WidgetState]($appui-react) instead. * @public - */ + */ export enum WidgetState { /** Widget tab is visible and active and its contents are visible */ Open, diff --git a/ui/appui-abstract/src/test/BaseUiItemsProvider.test.ts b/ui/appui-abstract/src/test/BaseUiItemsProvider.test.ts index cb1504961be7..33c2cc7a2477 100644 --- a/ui/appui-abstract/src/test/BaseUiItemsProvider.test.ts +++ b/ui/appui-abstract/src/test/BaseUiItemsProvider.test.ts @@ -6,25 +6,48 @@ import { expect } from "chai"; import * as sinon from "sinon"; import { - AbstractStatusBarItemUtilities, AbstractWidgetProps, BackstageItem, BackstageItemUtilities, BaseUiItemsProvider, CommonStatusBarItem, CommonToolbarItem, - StagePanelLocation, StagePanelSection, StageUsage, StatusBarSection, ToolbarItemUtilities, ToolbarOrientation, ToolbarUsage, UiItemsManager, + AbstractStatusBarItemUtilities, + AbstractWidgetProps, + BackstageItem, + BackstageItemUtilities, + BaseUiItemsProvider, + CommonStatusBarItem, + CommonToolbarItem, + StagePanelLocation, + StagePanelSection, + StageUsage, + StatusBarSection, + ToolbarItemUtilities, + ToolbarOrientation, + ToolbarUsage, + UiItemsManager, } from "../appui-abstract"; const testStageUsage = StageUsage.General; /** TestDerivedUiItemsProvider that provides tools and status bar items */ class TestUiItemsProvider extends BaseUiItemsProvider { - constructor(providerId: string, isSupportedStage?: ((stageId: string, stageUsage: string, stageAppData?: any) => boolean)) { + constructor(providerId: string, isSupportedStage?: (stageId: string, stageUsage: string, stageAppData?: any) => boolean) { super(providerId, isSupportedStage); } - public override provideToolbarButtonItemsInternal(_stageId: string, _stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation): CommonToolbarItem[] { + public override provideToolbarButtonItemsInternal( + _stageId: string, + _stageUsage: string, + toolbarUsage: ToolbarUsage, + toolbarOrientation: ToolbarOrientation, + ): CommonToolbarItem[] { if (toolbarUsage === ToolbarUsage.ContentManipulation && toolbarOrientation === ToolbarOrientation.Horizontal) { - const simpleActionSpec = ToolbarItemUtilities.createActionButton("simple-test-action-tool", 200, "icon-developer", "simple-test-action-tool", + const simpleActionSpec = ToolbarItemUtilities.createActionButton( + "simple-test-action-tool", + 200, + "icon-developer", + "simple-test-action-tool", (): void => { // eslint-disable-next-line no-console console.log("Got Here!"); - }); + }, + ); return [simpleActionSpec]; } return []; @@ -35,13 +58,29 @@ class TestUiItemsProvider extends BaseUiItemsProvider { const statusBarItems: CommonStatusBarItem[] = []; statusBarItems.push( - AbstractStatusBarItemUtilities.createActionItem("UiItemsProviderTest:StatusBarItem1", StatusBarSection.Center, 100, "icon-developer", "test status bar from extension", + AbstractStatusBarItemUtilities.createActionItem( + "UiItemsProviderTest:StatusBarItem1", + StatusBarSection.Center, + 100, + "icon-developer", + "test status bar from extension", () => { // eslint-disable-next-line no-console console.log("Got Here!"); - })); + }, + ), + ); - statusBarItems.push(AbstractStatusBarItemUtilities.createLabelItem("UiItemsProviderTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello", undefined)); + statusBarItems.push( + AbstractStatusBarItemUtilities.createLabelItem( + "UiItemsProviderTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + undefined, + ), + ); return statusBarItems; } @@ -49,11 +88,19 @@ class TestUiItemsProvider extends BaseUiItemsProvider { public override provideBackstageItems(): BackstageItem[] { return [ - BackstageItemUtilities.createActionItem("UiItemsProviderTest:backstage1", 500, 50, () => { }, "Dynamic Action", undefined, undefined, { isHidden: !TestUiItemsProvider.sampleStatusVisible }), + BackstageItemUtilities.createActionItem("UiItemsProviderTest:backstage1", 500, 50, () => {}, "Dynamic Action", undefined, undefined, { + isHidden: !TestUiItemsProvider.sampleStatusVisible, + }), ]; } - public override provideWidgetsInternal(_stageId: string, _stageUsage: string, _location: StagePanelLocation, _section?: StagePanelSection, _stageAppData?: any): AbstractWidgetProps[] { + public override provideWidgetsInternal( + _stageId: string, + _stageUsage: string, + _location: StagePanelLocation, + _section?: StagePanelSection, + _stageAppData?: any, + ): AbstractWidgetProps[] { const widgets: AbstractWidgetProps[] = []; widgets.push({ id: "test", @@ -199,5 +246,4 @@ describe("UiItemsManager", () => { expect(backstageItems.length).to.be.eq(1); UiItemsManager.unregister(testUiProvider.id); }); - }); diff --git a/ui/appui-abstract/src/test/UiAdmin.test.ts b/ui/appui-abstract/src/test/UiAdmin.test.ts index 2346e69647a4..c3011094fed0 100644 --- a/ui/appui-abstract/src/test/UiAdmin.test.ts +++ b/ui/appui-abstract/src/test/UiAdmin.test.ts @@ -4,20 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import * as sinon from "sinon"; +import { DialogItem, DialogPropertySyncItem } from "../appui-abstract/dialogs/DialogItem"; +import { UiDataProvider } from "../appui-abstract/dialogs/UiDataProvider"; +import { DialogLayoutDataProvider } from "../appui-abstract/dialogs/UiLayoutDataProvider"; import { AbstractMenuItemProps } from "../appui-abstract/items/AbstractMenuItemProps"; import { AbstractToolbarProps } from "../appui-abstract/items/AbstractToolbarProps"; import { RelativePosition } from "../appui-abstract/items/RelativePosition"; -import { PropertyDescription } from "../appui-abstract/properties/Description"; -import { UiAdmin } from "../appui-abstract/UiAdmin"; -import { UiDataProvider } from "../appui-abstract/dialogs/UiDataProvider"; -import { StandardTypeNames } from "../appui-abstract/properties/StandardTypeNames"; -import { DialogLayoutDataProvider } from "../appui-abstract/dialogs/UiLayoutDataProvider"; -import { DialogItem, DialogPropertySyncItem } from "../appui-abstract/dialogs/DialogItem"; import { DisplayMessageType, MessagePresenter } from "../appui-abstract/notification/MessagePresenter"; import { MessageSeverity } from "../appui-abstract/notification/MessageSeverity"; +import { PropertyDescription } from "../appui-abstract/properties/Description"; +import { StandardTypeNames } from "../appui-abstract/properties/StandardTypeNames"; +import { UiAdmin } from "../appui-abstract/UiAdmin"; describe("UiAdmin", () => { - let uiAdmin: UiAdmin; before(() => { @@ -34,9 +33,19 @@ describe("UiAdmin", () => { it("messagePresenter should return set object", () => { const mp: MessagePresenter = { - displayMessage: (_severity: MessageSeverity, _briefMessage: HTMLElement | string, _detailedMessage?: HTMLElement | string, _messageType?: DisplayMessageType.Toast): void => { }, - displayInputFieldMessage: (_inputField: HTMLElement, _severity: MessageSeverity, _briefMessage: HTMLElement | string, _detailedMessage?: HTMLElement | string): void => { }, - closeInputFieldMessage: (): void => { }, + displayMessage: ( + _severity: MessageSeverity, + _briefMessage: HTMLElement | string, + _detailedMessage?: HTMLElement | string, + _messageType?: DisplayMessageType.Toast, + ): void => {}, + displayInputFieldMessage: ( + _inputField: HTMLElement, + _severity: MessageSeverity, + _briefMessage: HTMLElement | string, + _detailedMessage?: HTMLElement | string, + ): void => {}, + closeInputFieldMessage: (): void => {}, }; UiAdmin.messagePresenter = mp; expect(UiAdmin.messagePresenter).to.eq(mp); @@ -55,8 +64,8 @@ describe("UiAdmin", () => { it("showContextMenu should return false by default", () => { const menuItemProps: AbstractMenuItemProps[] = [ - { id: "test", item: { label: "test label", icon: "icon-placeholder", execute: () => { } } }, - { id: "test2", item: { label: "test label", icon: "icon-placeholder", execute: () => { } } }, + { id: "test", item: { label: "test label", icon: "icon-placeholder", execute: () => {} } }, + { id: "test2", item: { label: "test label", icon: "icon-placeholder", execute: () => {} } }, ]; const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); @@ -67,23 +76,33 @@ describe("UiAdmin", () => { const toolbarProps: AbstractToolbarProps = { toolbarId: "test", items: [ - { id: "tool", itemPriority: 10, label: "tool label", icon: "icon-placeholder", execute: () => { } }, - { id: "command", itemPriority: 20, label: "command label", icon: "icon-placeholder", execute: () => { } }, - { id: "command2", itemPriority: 30, label: "command label", icon: "icon-placeholder", execute: () => { } }, + { id: "tool", itemPriority: 10, label: "tool label", icon: "icon-placeholder", execute: () => {} }, + { id: "command", itemPriority: 20, label: "command label", icon: "icon-placeholder", execute: () => {} }, + { id: "command2", itemPriority: 30, label: "command label", icon: "icon-placeholder", execute: () => {} }, ], }; const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); const spySelect = sinon.fake(); const spyCancel = sinon.fake(); - expect(uiAdmin.showToolbar(toolbarProps, uiAdmin.createXAndY(150, 250), uiAdmin.createXAndY(8, 8), spySelect, spyCancel, RelativePosition.BottomRight, doc.documentElement)).to.be.false; + expect( + uiAdmin.showToolbar( + toolbarProps, + uiAdmin.createXAndY(150, 250), + uiAdmin.createXAndY(8, 8), + spySelect, + spyCancel, + RelativePosition.BottomRight, + doc.documentElement, + ), + ).to.be.false; expect(uiAdmin.hideToolbar()).to.be.false; }); it("showMenuButton should return false by default", () => { const menuItemProps: AbstractMenuItemProps[] = [ - { id: "test", item: { label: "test label", icon: "icon-placeholder", execute: () => { } } }, - { id: "test2", item: { label: "test label", icon: "icon-placeholder", execute: () => { } } }, + { id: "test", item: { label: "test label", icon: "icon-placeholder", execute: () => {} } }, + { id: "test2", item: { label: "test label", icon: "icon-placeholder", execute: () => {} } }, ]; const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); @@ -144,41 +163,73 @@ describe("UiAdmin", () => { }); it("showHTMLElement should return false by default", () => { - const html = '
    Hello World!
    '; + const html = + '
    Hello World!
    '; const display = new DOMParser().parseFromString(html, "text/html"); const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); const spyCancel = sinon.fake(); - expect(uiAdmin.showHTMLElement(display.documentElement, uiAdmin.createXAndY(150, 250), uiAdmin.createXAndY(8, 8), spyCancel, RelativePosition.BottomRight, doc.documentElement)).to.be.false; + expect( + uiAdmin.showHTMLElement( + display.documentElement, + uiAdmin.createXAndY(150, 250), + uiAdmin.createXAndY(8, 8), + spyCancel, + RelativePosition.BottomRight, + doc.documentElement, + ), + ).to.be.false; expect(uiAdmin.hideHTMLElement()).to.be.false; }); it("showCard should return false by default", () => { - const html = '
    Hello World!
    '; + const html = + '
    Hello World!
    '; const content = new DOMParser().parseFromString(html, "text/html"); const toolbarProps: AbstractToolbarProps = { toolbarId: "test", items: [ - { id: "tool", itemPriority: 10, label: "tool label", icon: "icon-placeholder", execute: () => { } }, - { id: "command", itemPriority: 20, label: "command label", icon: "icon-placeholder", execute: () => { } }, - { id: "command2", itemPriority: 30, label: "command label", icon: "icon-placeholder", execute: () => { } }, + { id: "tool", itemPriority: 10, label: "tool label", icon: "icon-placeholder", execute: () => {} }, + { id: "command", itemPriority: 20, label: "command label", icon: "icon-placeholder", execute: () => {} }, + { id: "command2", itemPriority: 30, label: "command label", icon: "icon-placeholder", execute: () => {} }, ], }; const spySelect = sinon.fake(); const spyCancel = sinon.fake(); const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); - expect(uiAdmin.showCard(content.documentElement, "Title", toolbarProps, uiAdmin.createXAndY(150, 250), uiAdmin.createXAndY(8, 8), spySelect, spyCancel, RelativePosition.BottomRight, doc.documentElement)).to.be.false; + expect( + uiAdmin.showCard( + content.documentElement, + "Title", + toolbarProps, + uiAdmin.createXAndY(150, 250), + uiAdmin.createXAndY(8, 8), + spySelect, + spyCancel, + RelativePosition.BottomRight, + doc.documentElement, + ), + ).to.be.false; expect(uiAdmin.hideCard()).to.be.false; }); it("openToolSettingsPopup should return false by default", () => { - class TestUiDataProvider extends UiDataProvider { } + class TestUiDataProvider extends UiDataProvider {} const uiDataProvider = new TestUiDataProvider(); const doc = new DOMParser().parseFromString("
    xyz
    ", "text/html"); const spyCancel = sinon.fake(); - expect(uiAdmin.openToolSettingsPopup(uiDataProvider, uiAdmin.createXAndY(150, 250), uiAdmin.createXAndY(8, 8), spyCancel, RelativePosition.BottomRight, doc.documentElement)).to.be.false; + expect( + uiAdmin.openToolSettingsPopup( + uiDataProvider, + uiAdmin.createXAndY(150, 250), + uiAdmin.createXAndY(8, 8), + spyCancel, + RelativePosition.BottomRight, + doc.documentElement, + ), + ).to.be.false; expect(uiAdmin.closeToolSettingsPopup()).to.be.false; }); @@ -227,5 +278,4 @@ describe("UiAdmin", () => { expect(uiAdmin.openDialog(new TestDialogDynamicUiDataProvider(), "test-title", true, "test-modal")).to.be.false; expect(uiAdmin.closeDialog("test-modal")).to.be.false; }); - }); diff --git a/ui/appui-abstract/src/test/UiItemsManager.test.ts b/ui/appui-abstract/src/test/UiItemsManager.test.ts index c0e5ec8c6be3..8ae179f90bfb 100644 --- a/ui/appui-abstract/src/test/UiItemsManager.test.ts +++ b/ui/appui-abstract/src/test/UiItemsManager.test.ts @@ -6,24 +6,48 @@ import { expect } from "chai"; import * as sinon from "sinon"; import { - AbstractStatusBarItemUtilities, AbstractWidgetProps, BackstageItem, BackstageItemUtilities, CommonStatusBarItem, CommonToolbarItem, - StagePanelLocation, StagePanelSection, StageUsage, StatusBarSection, ToolbarItemUtilities, ToolbarOrientation, ToolbarUsage, - UiItemsManager, UiItemsProvider, + AbstractStatusBarItemUtilities, + AbstractWidgetProps, + BackstageItem, + BackstageItemUtilities, + CommonStatusBarItem, + CommonToolbarItem, + StagePanelLocation, + StagePanelSection, + StageUsage, + StatusBarSection, + ToolbarItemUtilities, + ToolbarOrientation, + ToolbarUsage, + UiItemsManager, + UiItemsProvider, } from "../appui-abstract"; const testStageUsage = StageUsage.General; /** TestUiItemsProvider that provides tools and status bar items */ class TestUiItemsProvider implements UiItemsProvider { - public get id(): string { return "unitTest:TestUiItemsProvider"; } + public get id(): string { + return "unitTest:TestUiItemsProvider"; + } - public provideToolbarButtonItems(_stageId: string, _stageUsage: string, toolbarUsage: ToolbarUsage, toolbarOrientation: ToolbarOrientation): CommonToolbarItem[] { + public provideToolbarButtonItems( + _stageId: string, + _stageUsage: string, + toolbarUsage: ToolbarUsage, + toolbarOrientation: ToolbarOrientation, + ): CommonToolbarItem[] { if (toolbarUsage === ToolbarUsage.ContentManipulation && toolbarOrientation === ToolbarOrientation.Horizontal) { - const simpleActionSpec = ToolbarItemUtilities.createActionButton("simple-test-action-tool", 200, "icon-developer", "simple-test-action-tool", + const simpleActionSpec = ToolbarItemUtilities.createActionButton( + "simple-test-action-tool", + 200, + "icon-developer", + "simple-test-action-tool", (): void => { // eslint-disable-next-line no-console console.log("Got Here!"); - }); + }, + ); return [simpleActionSpec]; } return []; @@ -34,13 +58,29 @@ class TestUiItemsProvider implements UiItemsProvider { const statusBarItems: CommonStatusBarItem[] = []; statusBarItems.push( - AbstractStatusBarItemUtilities.createActionItem("UiItemsProviderTest:StatusBarItem1", StatusBarSection.Center, 100, "icon-developer", "test status bar from extension", + AbstractStatusBarItemUtilities.createActionItem( + "UiItemsProviderTest:StatusBarItem1", + StatusBarSection.Center, + 100, + "icon-developer", + "test status bar from extension", () => { // eslint-disable-next-line no-console console.log("Got Here!"); - })); + }, + ), + ); - statusBarItems.push(AbstractStatusBarItemUtilities.createLabelItem("UiItemsProviderTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello", undefined)); + statusBarItems.push( + AbstractStatusBarItemUtilities.createLabelItem( + "UiItemsProviderTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + undefined, + ), + ); return statusBarItems; } @@ -48,11 +88,19 @@ class TestUiItemsProvider implements UiItemsProvider { public provideBackstageItems(): BackstageItem[] { return [ - BackstageItemUtilities.createActionItem("UiItemsProviderTest:backstage1", 500, 50, () => { }, "Dynamic Action", undefined, undefined, { isHidden: !TestUiItemsProvider.sampleStatusVisible }), + BackstageItemUtilities.createActionItem("UiItemsProviderTest:backstage1", 500, 50, () => {}, "Dynamic Action", undefined, undefined, { + isHidden: !TestUiItemsProvider.sampleStatusVisible, + }), ]; } - public provideWidgets(_stageId: string, _stageUsage: string, _location: StagePanelLocation, _section?: StagePanelSection, _stageAppData?: any): AbstractWidgetProps[] { + public provideWidgets( + _stageId: string, + _stageUsage: string, + _location: StagePanelLocation, + _section?: StagePanelSection, + _stageAppData?: any, + ): AbstractWidgetProps[] { const widgets: AbstractWidgetProps[] = []; widgets.push({ id: "test", @@ -129,7 +177,7 @@ describe("UiItemsManager", () => { expect(UiItemsManager.hasRegisteredProviders).to.be.false; UiItemsManager.register(testUiProvider); expect(UiItemsManager.hasRegisteredProviders).to.be.true; - UiItemsManager.register(testUiProvider, {providerId: "secondInstance", stageIds: ["test"]}); + UiItemsManager.register(testUiProvider, { providerId: "secondInstance", stageIds: ["test"] }); const providerIds = UiItemsManager.registeredProviderIds; expect(providerIds.length).to.eq(2); expect(providerIds[0]).to.eq(testUiProvider.id); @@ -155,7 +203,7 @@ describe("UiItemsManager", () => { it("Registered UiProvider should return items since stage is supported ", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageIds: ["stage"]}); + UiItemsManager.register(testUiProvider, { stageIds: ["stage"] }); const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(1); const statusbarItems = UiItemsManager.getStatusBarItems("stage", testStageUsage); @@ -169,7 +217,7 @@ describe("UiItemsManager", () => { it("Registered UiProvider should return items since stage usage is supported ", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageUsages: ["private"]}); + UiItemsManager.register(testUiProvider, { stageUsages: ["private"] }); const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", "private", ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(1); const statusbarItems = UiItemsManager.getStatusBarItems("stage", "private"); @@ -183,7 +231,7 @@ describe("UiItemsManager", () => { it("Registered UiProvider should NOT return items since stage usage does not match allowed", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageUsages: ["private"]}); + UiItemsManager.register(testUiProvider, { stageUsages: ["private"] }); const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(0); const statusbarItems = UiItemsManager.getStatusBarItems("stage", testStageUsage); @@ -198,8 +246,8 @@ describe("UiItemsManager", () => { it("Should return provider specific items per stage ", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageIds: ["stage"]}); - UiItemsManager.register(testUiProvider, {providerId: "stage2:testProvider", stageIds: ["stage2"]}); + UiItemsManager.register(testUiProvider, { stageIds: ["stage"] }); + UiItemsManager.register(testUiProvider, { providerId: "stage2:testProvider", stageIds: ["stage2"] }); const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(1); const statusbarItems = UiItemsManager.getStatusBarItems("stage", testStageUsage); @@ -209,7 +257,12 @@ describe("UiItemsManager", () => { const widgets = UiItemsManager.getWidgets("stage", testStageUsage, StagePanelLocation.Right); expect(widgets.length).to.be.eq(1); - const toolSpecs2 = UiItemsManager.getToolbarButtonItems("stage2", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); + const toolSpecs2 = UiItemsManager.getToolbarButtonItems( + "stage2", + testStageUsage, + ToolbarUsage.ContentManipulation, + ToolbarOrientation.Horizontal, + ); expect(toolSpecs2.length).to.be.eq(1); const statusbarItems2 = UiItemsManager.getStatusBarItems("stage2", testStageUsage); expect(statusbarItems2.length).to.be.eq(2); @@ -224,8 +277,8 @@ describe("UiItemsManager", () => { it("Should return provider specific items per stage and avoid duplicate", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageIds: ["stage"]}); - UiItemsManager.register(testUiProvider, {providerId: "stage:testProvider", stageIds: ["stage"]}); // alternate provider but wrongly targets same stage + UiItemsManager.register(testUiProvider, { stageIds: ["stage"] }); + UiItemsManager.register(testUiProvider, { providerId: "stage:testProvider", stageIds: ["stage"] }); // alternate provider but wrongly targets same stage const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(1); const statusbarItems = UiItemsManager.getStatusBarItems("stage", testStageUsage); @@ -241,7 +294,7 @@ describe("UiItemsManager", () => { it("Registered UiProvider should NOT return items since stage is NOT in supported list", () => { const testUiProvider = new TestUiItemsProvider(); - UiItemsManager.register(testUiProvider, {stageIds: ["stage2"]}); + UiItemsManager.register(testUiProvider, { stageIds: ["stage2"] }); const toolSpecs = UiItemsManager.getToolbarButtonItems("stage", testStageUsage, ToolbarUsage.ContentManipulation, ToolbarOrientation.Horizontal); expect(toolSpecs.length).to.be.eq(0); const statusbarItems = UiItemsManager.getStatusBarItems("stage", testStageUsage); @@ -253,5 +306,4 @@ describe("UiItemsManager", () => { expect(widgets.length).to.be.eq(0); UiItemsManager.unregister(testUiProvider.id); }); - }); diff --git a/ui/appui-abstract/src/test/backstage/BackstageItemsManager.test.ts b/ui/appui-abstract/src/test/backstage/BackstageItemsManager.test.ts index 246fcf41b5ec..ce533252ad26 100644 --- a/ui/appui-abstract/src/test/backstage/BackstageItemsManager.test.ts +++ b/ui/appui-abstract/src/test/backstage/BackstageItemsManager.test.ts @@ -5,10 +5,15 @@ import { expect } from "chai"; import * as sinon from "sinon"; import { - BackstageItemsManager, BackstageItemUtilities, ConditionalBooleanValue, ConditionalStringValue, isActionItem, isStageLauncher, + BackstageItemsManager, + BackstageItemUtilities, + ConditionalBooleanValue, + ConditionalStringValue, + isActionItem, + isStageLauncher, } from "../../appui-abstract"; -const getActionItem = () => BackstageItemUtilities.createActionItem("Action", 100, 50, () => { }, "Custom Label", "subtitle", "icon-placeholder"); +const getActionItem = () => BackstageItemUtilities.createActionItem("Action", 100, 50, () => {}, "Custom Label", "subtitle", "icon-placeholder"); const getStageLauncherItem = () => BackstageItemUtilities.createStageLauncher("stageId", 100, 50, "Custom Label", "subtitle", "icon-placeholder"); describe("isActionItem", () => { @@ -149,8 +154,12 @@ describe("BackstageItemsManager", () => { it("uisync", () => { let isVisible = true; let isEnabled = true; - const setVisibility = (value: boolean) => { isVisible = value; }; - const setEnabled = (value: boolean) => { isEnabled = value; }; + const setVisibility = (value: boolean) => { + isVisible = value; + }; + const setEnabled = (value: boolean) => { + isEnabled = value; + }; const syncId = "test-on-display-changed"; const hiddenCondition = new ConditionalBooleanValue(() => !isVisible, [syncId]); const disabledCondition = new ConditionalBooleanValue(() => !isEnabled, [syncId]); @@ -158,16 +167,27 @@ describe("BackstageItemsManager", () => { const conditionalIcon = new ConditionalStringValue(() => isVisible ? "icon-hand-2" : "icon-hand", [syncId]); const subTitleConditional = new ConditionalStringValue(() => isVisible ? "default subtitle" : "new subtitle", [syncId]); - const getActionItemWithNoConditions = () => BackstageItemUtilities.createActionItem("Action-NC", 100, 50, () => { }, "Custom Label", "subtitle", "icon-placeholder"); // try to init isVisible to false but this should be reset when loaded due to condition function - const getActionItemWithConditions = () => BackstageItemUtilities.createActionItem("Action-C", 100, 50, () => { }, conditionalLabel, subTitleConditional, conditionalIcon, - { isHidden: hiddenCondition }); // try to init isVisible to false but this should be reset when loaded due to condition function - const getStageLauncherItemWithNoConditions = () => BackstageItemUtilities.createStageLauncher("stageId-NC", 100, 50, "Custom Label", "subtitle", "icon-placeholder"); - const getStageLauncherItemWithConditions = () => BackstageItemUtilities.createStageLauncher("stageId-C", 100, 50, conditionalLabel, subTitleConditional, conditionalIcon, - { isDisabled: disabledCondition }); + const getActionItemWithNoConditions = () => + BackstageItemUtilities.createActionItem("Action-NC", 100, 50, () => {}, "Custom Label", "subtitle", "icon-placeholder"); // try to init isVisible to false but this should be reset when loaded due to condition function + const getActionItemWithConditions = () => + BackstageItemUtilities.createActionItem("Action-C", 100, 50, () => {}, conditionalLabel, subTitleConditional, conditionalIcon, { + isHidden: hiddenCondition, + }); // try to init isVisible to false but this should be reset when loaded due to condition function + const getStageLauncherItemWithNoConditions = () => + BackstageItemUtilities.createStageLauncher("stageId-NC", 100, 50, "Custom Label", "subtitle", "icon-placeholder"); + const getStageLauncherItemWithConditions = () => + BackstageItemUtilities.createStageLauncher("stageId-C", 100, 50, conditionalLabel, subTitleConditional, conditionalIcon, { + isDisabled: disabledCondition, + }); const sut = new BackstageItemsManager(); - sut.add([getActionItemWithNoConditions(), getActionItemWithConditions(), getStageLauncherItemWithNoConditions(), getStageLauncherItemWithConditions()]); + sut.add([ + getActionItemWithNoConditions(), + getActionItemWithConditions(), + getStageLauncherItemWithNoConditions(), + getStageLauncherItemWithConditions(), + ]); const syncIds = BackstageItemsManager.getSyncIdsOfInterest(sut.items); expect(syncIds.length).to.be.eq(1); @@ -215,7 +235,7 @@ describe("BackstageItemsManager", () => { it("should convert SyncEventIds to lowercase", () => { const isHidden = new ConditionalBooleanValue(() => true, ["Test:CustomId"]); - const action = BackstageItemUtilities.createActionItem("TestAction", 100, 50, () => { }, "", undefined, undefined, { isHidden }); + const action = BackstageItemUtilities.createActionItem("TestAction", 100, 50, () => {}, "", undefined, undefined, { isHidden }); const sut = new BackstageItemsManager(); sut.add(action); const syncIds = BackstageItemsManager.getSyncIdsOfInterest(sut.items); diff --git a/ui/appui-abstract/src/test/dialogs/DialogItem.test.ts b/ui/appui-abstract/src/test/dialogs/DialogItem.test.ts index 9f451ad97747..2903765445cf 100644 --- a/ui/appui-abstract/src/test/dialogs/DialogItem.test.ts +++ b/ui/appui-abstract/src/test/dialogs/DialogItem.test.ts @@ -45,7 +45,6 @@ describe("DialogProperty", () => { expect(item.value.value).to.eq("yellow"); expect(item.value.displayValue).to.eq("Yellow"); }); - }); describe("Non-string types", () => { it("Number property test", () => { @@ -53,11 +52,19 @@ describe("DialogProperty", () => { expect(numberProperty.dialogItemValue.value).to.eq(1); }); it("Boolean property test", () => { - const booleanProperty = new DialogProperty(PropertyDescriptionHelper.buildTextEditorDescription("boolean", "Boolean"), true, undefined); + const booleanProperty = new DialogProperty( + PropertyDescriptionHelper.buildTextEditorDescription("boolean", "Boolean"), + true, + undefined, + ); expect(booleanProperty.dialogItemValue.value).to.eq(true); }); it("Undefined property test", () => { - const undefinedProperty = new DialogProperty(PropertyDescriptionHelper.buildTextEditorDescription("undefined", "Undefined"), undefined, undefined); + const undefinedProperty = new DialogProperty( + PropertyDescriptionHelper.buildTextEditorDescription("undefined", "Undefined"), + undefined, + undefined, + ); expect(undefinedProperty.dialogItemValue.value).to.be.undefined; }); it("Date property test", () => { diff --git a/ui/appui-abstract/src/test/dialogs/UiLayoutDataProvider.test.ts b/ui/appui-abstract/src/test/dialogs/UiLayoutDataProvider.test.ts index 050696bcf738..6e69785f4b4a 100644 --- a/ui/appui-abstract/src/test/dialogs/UiLayoutDataProvider.test.ts +++ b/ui/appui-abstract/src/test/dialogs/UiLayoutDataProvider.test.ts @@ -4,9 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import { assert, expect } from "chai"; import { - ButtonGroupEditorParams, DialogItem, DialogItemValue, DialogLayoutDataProvider, DialogPropertyItem, DialogPropertySyncItem, DialogRow, - PrimitiveValue, PropertyDescription, PropertyEditorParamTypes, StandardEditorNames, - StandardTypeNames, SuppressLabelEditorParams, UiLayoutDataProvider, + ButtonGroupEditorParams, + DialogItem, + DialogItemValue, + DialogLayoutDataProvider, + DialogPropertyItem, + DialogPropertySyncItem, + DialogRow, + PrimitiveValue, + PropertyDescription, + PropertyEditorParamTypes, + StandardEditorNames, + StandardTypeNames, + SuppressLabelEditorParams, + UiLayoutDataProvider, } from "../../appui-abstract"; const value1: DialogItemValue = { value: 3 }; @@ -56,8 +67,7 @@ const getButtonGroupItemDescription = (): PropertyDescription => { } as ButtonGroupEditorParams, { type: PropertyEditorParamTypes.SuppressEditorLabel, suppressLabelPlaceholder: true, - } as SuppressLabelEditorParams, - ], + } as SuppressLabelEditorParams], }, enum: { choices: [ @@ -70,9 +80,18 @@ const getButtonGroupItemDescription = (): PropertyDescription => { }; const lockItem: DialogItem = { value: lockValue, property: getLockToggleDescription(), editorPosition: { rowPriority: 0, columnIndex: 0 } }; -const item1: DialogItem = { value: value1, property: getItem1Description(), editorPosition: { rowPriority: 0, columnIndex: 1 }, lockProperty: lockItem }; +const item1: DialogItem = { + value: value1, + property: getItem1Description(), + editorPosition: { rowPriority: 0, columnIndex: 1 }, + lockProperty: lockItem, +}; const item2: DialogItem = { value: value2, property: getItem2Description(), editorPosition: { rowPriority: 0, columnIndex: 2 }, isDisabled: true }; -const buttonGroupItem: DialogItem = { value: buttonGroupValue, property: getButtonGroupItemDescription(), editorPosition: { rowPriority: 1, columnIndex: 0 } }; +const buttonGroupItem: DialogItem = { + value: buttonGroupValue, + property: getButtonGroupItemDescription(), + editorPosition: { rowPriority: 1, columnIndex: 0 }, +}; const dialogItems: DialogItem[] = [item1, item2, buttonGroupItem]; class TestDynamicUiDataProvider extends UiLayoutDataProvider { @@ -188,7 +207,6 @@ describe("DialogLayoutDataProvider", () => { expect(emptySut.items.length).to.be.eq(0); expect(emptySut.rows.length).to.be.eq(0); }); - }); describe("buttons", () => { it("should contain defaults", () => { @@ -197,5 +215,4 @@ describe("DialogLayoutDataProvider", () => { expect(buttonData && buttonData.length).to.be.eq(2); }); }); - }); diff --git a/ui/appui-abstract/src/test/properties/EditorParams.test.ts b/ui/appui-abstract/src/test/properties/EditorParams.test.ts index 0654dcd7b1cd..d074ab0b8622 100644 --- a/ui/appui-abstract/src/test/properties/EditorParams.test.ts +++ b/ui/appui-abstract/src/test/properties/EditorParams.test.ts @@ -4,9 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { - ButtonGroupEditorParams, ColorEditorParams, CustomFormattedNumberParams, IconListEditorParams, InputEditorSizeParams, isButtonGroupEditorParams, - isColorEditorParams, isCustomFormattedNumberParams, isIconListEditorParams, isInputEditorSizeParams, isSuppressLabelEditorParams, - PropertyEditorParamTypes, SuppressLabelEditorParams, + ButtonGroupEditorParams, + ColorEditorParams, + CustomFormattedNumberParams, + IconListEditorParams, + InputEditorSizeParams, + isButtonGroupEditorParams, + isColorEditorParams, + isCustomFormattedNumberParams, + isIconListEditorParams, + isInputEditorSizeParams, + isSuppressLabelEditorParams, + PropertyEditorParamTypes, + SuppressLabelEditorParams, } from "../../appui-abstract"; describe("EditorParams", () => { @@ -17,10 +27,18 @@ describe("EditorParams", () => { const colorParams: ColorEditorParams = { type: PropertyEditorParamTypes.ColorData, colorValues: [5, 6, 7], numColumns: 3 }; expect(isColorEditorParams(colorParams)).to.be.true; - const iconListParams: IconListEditorParams = { type: PropertyEditorParamTypes.IconListData, iconValue: "icon-placeholder", iconValues: ["icon-placeholder", "icon-2", "icon-3"], numColumns: 1 }; + const iconListParams: IconListEditorParams = { + type: PropertyEditorParamTypes.IconListData, + iconValue: "icon-placeholder", + iconValues: ["icon-placeholder", "icon-2", "icon-3"], + numColumns: 1, + }; expect(isIconListEditorParams(iconListParams)).to.be.true; - const bgParams: ButtonGroupEditorParams = { type: PropertyEditorParamTypes.ButtonGroupData, buttons: [{ iconSpec: "iconspec-1" }, { iconSpec: "iconspec-2" }] }; + const bgParams: ButtonGroupEditorParams = { + type: PropertyEditorParamTypes.ButtonGroupData, + buttons: [{ iconSpec: "iconspec-1" }, { iconSpec: "iconspec-2" }], + }; expect(isButtonGroupEditorParams(bgParams)).to.be.true; const suppressParams: SuppressLabelEditorParams = { type: PropertyEditorParamTypes.SuppressEditorLabel }; @@ -29,7 +47,9 @@ describe("EditorParams", () => { const customParams: CustomFormattedNumberParams = { type: PropertyEditorParamTypes.CustomFormattedNumber, formatFunction: (numberValue: number) => `${numberValue}`, - parseFunction: (_stringValue: string) => { return { value: 1.0 }; }, // eslint-disable-line arrow-body-style + parseFunction: (_stringValue: string) => { + return { value: 1.0 }; + }, // eslint-disable-line arrow-body-style }; expect(isCustomFormattedNumberParams(customParams)).to.be.true; }); diff --git a/ui/appui-abstract/src/test/properties/PropertyDescriptionHelper.test.ts b/ui/appui-abstract/src/test/properties/PropertyDescriptionHelper.test.ts index 016662755a99..729a231aa4f4 100644 --- a/ui/appui-abstract/src/test/properties/PropertyDescriptionHelper.test.ts +++ b/ui/appui-abstract/src/test/properties/PropertyDescriptionHelper.test.ts @@ -4,7 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import { expect } from "chai"; import { - EnumerationChoice, IconEditorParams, PropertyDescriptionHelper, PropertyEditorParamTypes, RangeEditorParams, SuppressLabelEditorParams, + EnumerationChoice, + IconEditorParams, + PropertyDescriptionHelper, + PropertyEditorParamTypes, + RangeEditorParams, + SuppressLabelEditorParams, } from "../../appui-abstract"; // cSpell:ignore Picklist @@ -78,7 +83,6 @@ describe("PropertyDescriptionHelper", () => { expect(editorDescription.editor?.name).to.eq(editor); expect(editorDescription.editor?.params?.length).to.eq(1); expect(editorDescription.editor?.params?.[0].type).to.eq(PropertyEditorParamTypes.Range); - }); it("should build with additional editor params correctly", () => { @@ -267,8 +271,7 @@ describe("PropertyDescriptionHelper", () => { }); describe("bumpEnumProperty", () => { - const noChoices: EnumerationChoice[] = [ - ]; + const noChoices: EnumerationChoice[] = []; const choices = [ { label: "Red", value: 1 }, @@ -324,5 +327,4 @@ describe("PropertyDescriptionHelper", () => { expect(newValue).to.eq(1); }); }); - }); diff --git a/ui/appui-abstract/src/test/properties/PropertyRecord.test.ts b/ui/appui-abstract/src/test/properties/PropertyRecord.test.ts index e9e27ea05d90..3037b9c1e4d7 100644 --- a/ui/appui-abstract/src/test/properties/PropertyRecord.test.ts +++ b/ui/appui-abstract/src/test/properties/PropertyRecord.test.ts @@ -26,9 +26,7 @@ const getUpdatedPropertyDescription = (): PropertyDescription => { }; describe("PropertyRecord", () => { - describe("copyWithNewValue", () => { - it("should have new value", () => { const sut = new PropertyRecord(value1, getPropertyDescription()); const newRecord = sut.copyWithNewValue(value2); @@ -54,16 +52,14 @@ describe("PropertyRecord", () => { src.isReadonly = true; src.links = { matcher: () => [], - onClick: () => { }, + onClick: () => {}, }; const newRecord = src.copyWithNewValue(value2); expect(newRecord).to.deep.eq({ ...src, value: value2 }); }); - }); describe("fromString", () => { - it("should create a valid PropertyRecord with provided description name", () => { const record = PropertyRecord.fromString("test value", "test description"); assert(record.property.name === "test description"); @@ -74,7 +70,6 @@ describe("PropertyRecord", () => { const record = PropertyRecord.fromString("test"); expect(record.description).to.be.undefined; }); - }); describe("getChildrenRecords", () => { diff --git a/ui/appui-abstract/src/test/quantity/BaseQuantityDescription.test.ts b/ui/appui-abstract/src/test/quantity/BaseQuantityDescription.test.ts index a0f02ba6d33b..a83c3c2b48aa 100644 --- a/ui/appui-abstract/src/test/quantity/BaseQuantityDescription.test.ts +++ b/ui/appui-abstract/src/test/quantity/BaseQuantityDescription.test.ts @@ -21,8 +21,12 @@ describe("BaseQuantityDescription", () => { return { value: 10 }; } - public get quantityType(): string { return "MockType"; } - public get parseError(): string { return "MockError"; } + public get quantityType(): string { + return "MockType"; + } + public get parseError(): string { + return "MockError"; + } } const sut = new QuantityDescription("mockQuantity", "Mock Quantity", "icon-placeholder"); const formattedValue = sut.format(5); diff --git a/ui/appui-abstract/src/test/statusbar/StatusBarItemsManager.test.ts b/ui/appui-abstract/src/test/statusbar/StatusBarItemsManager.test.ts index 88cec58ffd1f..673ddbc07bfb 100644 --- a/ui/appui-abstract/src/test/statusbar/StatusBarItemsManager.test.ts +++ b/ui/appui-abstract/src/test/statusbar/StatusBarItemsManager.test.ts @@ -5,13 +5,28 @@ import { expect } from "chai"; import * as sinon from "sinon"; import { - AbstractStatusBarCustomItem, AbstractStatusBarItemUtilities, CommonStatusBarItem, ConditionalBooleanValue, ConditionalStringValue, - isAbstractStatusBarActionItem, isAbstractStatusBarCustomItem, isAbstractStatusBarLabelItem, StatusBarItemsManager, StatusBarSection, + AbstractStatusBarCustomItem, + AbstractStatusBarItemUtilities, + CommonStatusBarItem, + ConditionalBooleanValue, + ConditionalStringValue, + isAbstractStatusBarActionItem, + isAbstractStatusBarCustomItem, + isAbstractStatusBarLabelItem, + StatusBarItemsManager, + StatusBarSection, } from "../../appui-abstract"; describe("StatusBarItemsManager", () => { - const createCustomItem = (id: string, section: StatusBarSection, itemPriority: number, itemProps?: Partial): AbstractStatusBarCustomItem => ({ - id, section, itemPriority, + const createCustomItem = ( + id: string, + section: StatusBarSection, + itemPriority: number, + itemProps?: Partial, + ): AbstractStatusBarCustomItem => ({ + id, + section, + itemPriority, isCustom: true, ...itemProps ? itemProps : {}, }); @@ -27,7 +42,15 @@ describe("StatusBarItemsManager", () => { describe("type guards", () => { it("should identify label item", () => { - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello", undefined, { isDisabled: true, isHidden: true }); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + undefined, + { isDisabled: true, isHidden: true }, + ); expect(isAbstractStatusBarLabelItem(item)).to.be.true; expect(isAbstractStatusBarActionItem(item)).to.be.false; expect(isAbstractStatusBarCustomItem(item)).to.be.false; @@ -36,7 +59,14 @@ describe("StatusBarItemsManager", () => { }); it("should identify action item", () => { - const item = AbstractStatusBarItemUtilities.createActionItem("ExtensionTest:StatusBarItem1", StatusBarSection.Center, 100, "icon-developer", "test status bar from extension", () => { }); + const item = AbstractStatusBarItemUtilities.createActionItem( + "ExtensionTest:StatusBarItem1", + StatusBarSection.Center, + 100, + "icon-developer", + "test status bar from extension", + () => {}, + ); expect(isAbstractStatusBarActionItem(item)).to.be.true; expect(isAbstractStatusBarLabelItem(item)).to.be.false; expect(isAbstractStatusBarCustomItem(item)).to.be.false; @@ -52,13 +82,25 @@ describe("StatusBarItemsManager", () => { describe("add & remove", () => { it("should instantiate with item", () => { - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); const sut = new StatusBarItemsManager([item]); expect(sut.items.length).to.eq(1); }); it("should add item without callback", () => { - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); const sut = new StatusBarItemsManager(); const spy = sinon.spy(); @@ -72,7 +114,13 @@ describe("StatusBarItemsManager", () => { it("should add & remove one item", () => { const sut = new StatusBarItemsManager(); - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); expect(isAbstractStatusBarLabelItem(item)).to.be.true; expect(isAbstractStatusBarActionItem(item)).to.be.false; @@ -86,7 +134,13 @@ describe("StatusBarItemsManager", () => { it("attempt to set duplicate items ignores it", () => { const sut = new StatusBarItemsManager(); - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); sut.add(item); expect(sut.items.length).to.eq(1); @@ -98,8 +152,20 @@ describe("StatusBarItemsManager", () => { it("add ignores duplicate items", () => { const sut = new StatusBarItemsManager(); - const item1 = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); - const item2 = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item1 = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); + const item2 = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); sut.add([item1, item2]); expect(sut.items.length).to.eq(1); }); @@ -107,7 +173,13 @@ describe("StatusBarItemsManager", () => { it("attempt to add duplicate item ignores it", () => { const sut = new StatusBarItemsManager(); - const item = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"); + const item = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + "Hello", + ); sut.add(item); expect(sut.items.length).to.eq(1); @@ -121,7 +193,14 @@ describe("StatusBarItemsManager", () => { const items: CommonStatusBarItem[] = [ AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"), - AbstractStatusBarItemUtilities.createActionItem("ExtensionTest:StatusBarItem2", StatusBarSection.Center, 100, "icon-developer", "test status bar from extension", () => { }), + AbstractStatusBarItemUtilities.createActionItem( + "ExtensionTest:StatusBarItem2", + StatusBarSection.Center, + 100, + "icon-developer", + "test status bar from extension", + () => {}, + ), createCustomItem("ExtensionTest:StatusBarItem3", StatusBarSection.Center, 100), ]; @@ -138,7 +217,14 @@ describe("StatusBarItemsManager", () => { const items: CommonStatusBarItem[] = [ AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", "Hello"), - AbstractStatusBarItemUtilities.createActionItem("ExtensionTest:StatusBarItem2", StatusBarSection.Center, 100, "icon-developer", "test status bar from extension", () => { }), + AbstractStatusBarItemUtilities.createActionItem( + "ExtensionTest:StatusBarItem2", + StatusBarSection.Center, + 100, + "icon-developer", + "test status bar from extension", + () => {}, + ), createCustomItem("ExtensionTest:StatusBarItem3", StatusBarSection.Center, 100), ]; @@ -159,8 +245,12 @@ describe("StatusBarItemsManager", () => { describe("uisync", () => { let isVisible = true; let isEnabled = true; - const setVisibility = (value: boolean) => { isVisible = value; }; - const setEnabled = (value: boolean) => { isEnabled = value; }; + const setVisibility = (value: boolean) => { + isVisible = value; + }; + const setEnabled = (value: boolean) => { + isEnabled = value; + }; const syncId = "test-on-display-changed"; const hiddenCondition = new ConditionalBooleanValue(() => !isVisible, [syncId]); const disabledCondition = new ConditionalBooleanValue(() => !isEnabled, [syncId]); @@ -170,11 +260,32 @@ describe("StatusBarItemsManager", () => { const sut = new StatusBarItemsManager(); - const item1 = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel1", StatusBarSection.Center, 100, "icon-hand-2", conditionalLabel, undefined, - { isHidden: hiddenCondition }); // try to init isVisible to false but this should be reset when loaded due to condition function - const item2 = AbstractStatusBarItemUtilities.createLabelItem("ExtensionTest:StatusBarLabel2", StatusBarSection.Center, 110, conditionalIcon, "Hello", undefined, - { isDisabled: disabledCondition }); - const sb3 = AbstractStatusBarItemUtilities.createActionItem("ExtensionTest:StatusBarItem3", StatusBarSection.Center, 120, "icon-developer", toolTipConditional, () => { }); + const item1 = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel1", + StatusBarSection.Center, + 100, + "icon-hand-2", + conditionalLabel, + undefined, + { isHidden: hiddenCondition }, + ); // try to init isVisible to false but this should be reset when loaded due to condition function + const item2 = AbstractStatusBarItemUtilities.createLabelItem( + "ExtensionTest:StatusBarLabel2", + StatusBarSection.Center, + 110, + conditionalIcon, + "Hello", + undefined, + { isDisabled: disabledCondition }, + ); + const sb3 = AbstractStatusBarItemUtilities.createActionItem( + "ExtensionTest:StatusBarItem3", + StatusBarSection.Center, + 120, + "icon-developer", + toolTipConditional, + () => {}, + ); sut.add([item1, item2, sb3]); @@ -223,7 +334,5 @@ describe("StatusBarItemsManager", () => { if (isAbstractStatusBarActionItem(item3!)) { expect(ConditionalStringValue.getValue(item3.tooltip)).to.be.equal("new tooltip"); } - }); - }); diff --git a/ui/appui-abstract/src/test/toolbar/ToolbarItemsManager.test.ts b/ui/appui-abstract/src/test/toolbar/ToolbarItemsManager.test.ts index edd117620144..bab9dc215c11 100644 --- a/ui/appui-abstract/src/test/toolbar/ToolbarItemsManager.test.ts +++ b/ui/appui-abstract/src/test/toolbar/ToolbarItemsManager.test.ts @@ -5,22 +5,34 @@ import { expect } from "chai"; import * as sinon from "sinon"; import { - BadgeType, CommonToolbarItem, ConditionalBooleanValue, ConditionalStringValue, CustomButtonDefinition, ToolbarItemsManager, ToolbarItemUtilities, + BadgeType, + CommonToolbarItem, + ConditionalBooleanValue, + ConditionalStringValue, + CustomButtonDefinition, + ToolbarItemsManager, + ToolbarItemUtilities, } from "../../appui-abstract"; describe("ToolbarItemsManager", () => { - const customSpec: CustomButtonDefinition = { - id: "custom", itemPriority: 1, + id: "custom", + itemPriority: 1, isCustom: true, }; let isChildVisible = true; let isVisible = true; let isEnabled = true; - const setChildVisibility = (value: boolean) => { isChildVisible = value; }; - const setVisibility = (value: boolean) => { isVisible = value; }; - const setEnabled = (value: boolean) => { isEnabled = value; }; + const setChildVisibility = (value: boolean) => { + isChildVisible = value; + }; + const setVisibility = (value: boolean) => { + isVisible = value; + }; + const setEnabled = (value: boolean) => { + isEnabled = value; + }; const syncId = "test-on-display-changed"; const childSyncId = "child-test-on-display-changed"; const hiddenCondition = () => new ConditionalBooleanValue(() => !isVisible, [syncId]); @@ -32,14 +44,57 @@ describe("ToolbarItemsManager", () => { const nestedConditionalLabel = new ConditionalStringValue(() => isVisible ? "nested-Hello" : "nested-Goodbye", [syncId]); const nestedConditionalIcon = new ConditionalStringValue(() => isVisible ? "nested-icon-developer" : "nested-icon-home", [syncId]); - const simpleActionSpec = ToolbarItemUtilities.createActionButton("simple-test-action1-tool", 100, "icon-developer", "simple-test-action-tool", (): void => { }); - const simpleAction2Spec = ToolbarItemUtilities.createActionButton("simple-test-action2-tool", 100, conditionalIcon, conditionalLabel, (): void => { }, { isHidden: hiddenCondition() }); - const child1ActionSpec = ToolbarItemUtilities.createActionButton("child1-test-action-tool", 100, "icon-developer", "child1", (): void => { }, { isHidden: childHiddenCondition() }); - const child2ActionSpec = ToolbarItemUtilities.createActionButton("child2-test-action-tool", 110, conditionalIcon, conditionalLabel, (): void => { }, { isDisabled: disabledCondition() }); - const nestedChild1ActionSpec = ToolbarItemUtilities.createActionButton("child1-test-action-tool-nested", 100, "icon-developer", "child1", (): void => { }, { isHidden: nestChildHiddenCondition() }); - const nestedChild2ActionSpec = ToolbarItemUtilities.createActionButton("child2-test-action-tool-nested", 110, nestedConditionalIcon, nestedConditionalLabel, (): void => { }, { isDisabled: disabledCondition() }); - const nestedGroupItem = ToolbarItemUtilities.createGroupButton("tool-formatting-setting-nested", 110, "icon-placeholder", "set formatting units", [nestedChild1ActionSpec, nestedChild2ActionSpec], { badgeType: BadgeType.New }); - const groupItem = ToolbarItemUtilities.createGroupButton("tool-formatting-setting", 110, "icon-placeholder", "set formatting units", [child1ActionSpec, child2ActionSpec, nestedGroupItem], { badgeType: BadgeType.New, isDisabled: disabledCondition() }); + const simpleActionSpec = ToolbarItemUtilities.createActionButton( + "simple-test-action1-tool", + 100, + "icon-developer", + "simple-test-action-tool", + (): void => {}, + ); + const simpleAction2Spec = ToolbarItemUtilities.createActionButton( + "simple-test-action2-tool", + 100, + conditionalIcon, + conditionalLabel, + (): void => {}, + { isHidden: hiddenCondition() }, + ); + const child1ActionSpec = ToolbarItemUtilities.createActionButton("child1-test-action-tool", 100, "icon-developer", "child1", (): void => {}, { + isHidden: childHiddenCondition(), + }); + const child2ActionSpec = ToolbarItemUtilities.createActionButton( + "child2-test-action-tool", + 110, + conditionalIcon, + conditionalLabel, + (): void => {}, + { isDisabled: disabledCondition() }, + ); + const nestedChild1ActionSpec = ToolbarItemUtilities.createActionButton( + "child1-test-action-tool-nested", + 100, + "icon-developer", + "child1", + (): void => {}, + { isHidden: nestChildHiddenCondition() }, + ); + const nestedChild2ActionSpec = ToolbarItemUtilities.createActionButton( + "child2-test-action-tool-nested", + 110, + nestedConditionalIcon, + nestedConditionalLabel, + (): void => {}, + { isDisabled: disabledCondition() }, + ); + const nestedGroupItem = ToolbarItemUtilities.createGroupButton("tool-formatting-setting-nested", 110, "icon-placeholder", "set formatting units", [ + nestedChild1ActionSpec, + nestedChild2ActionSpec, + ], { badgeType: BadgeType.New }); + const groupItem = ToolbarItemUtilities.createGroupButton("tool-formatting-setting", 110, "icon-placeholder", "set formatting units", [ + child1ActionSpec, + child2ActionSpec, + nestedGroupItem, + ], { badgeType: BadgeType.New, isDisabled: disabledCondition() }); afterEach(() => sinon.restore()); @@ -204,7 +259,14 @@ describe("ToolbarItemsManager", () => { describe("set active tool", () => { it("root tool already active", () => { - const initiallyActiveSpec = ToolbarItemUtilities.createActionButton("simple-test-action-tool-active", 100, "icon-developer", "simple-test-action-tool", (): void => { }, { isActive: true }); + const initiallyActiveSpec = ToolbarItemUtilities.createActionButton( + "simple-test-action-tool-active", + 100, + "icon-developer", + "simple-test-action-tool", + (): void => {}, + { isActive: true }, + ); const sut = new ToolbarItemsManager([simpleActionSpec, simpleAction2Spec, groupItem, initiallyActiveSpec]); const items = sut.items; @@ -228,5 +290,4 @@ describe("ToolbarItemsManager", () => { expect(items).not.to.equal(sut.items); }); }); - }); diff --git a/ui/appui-abstract/src/test/utils/IconSpecUtilities.test.ts b/ui/appui-abstract/src/test/utils/IconSpecUtilities.test.ts index 2798095fe338..e797c2d66152 100644 --- a/ui/appui-abstract/src/test/utils/IconSpecUtilities.test.ts +++ b/ui/appui-abstract/src/test/utils/IconSpecUtilities.test.ts @@ -7,7 +7,6 @@ import { expect } from "chai"; import { IconSpecUtilities } from "../../appui-abstract/utils/IconSpecUtilities"; describe("IconSpecUtilities", () => { - it("should correctly create iconSpec for svg", () => { const iconSpec = IconSpecUtilities.createSvgIconSpec("test"); expect(iconSpec).to.eq(`${IconSpecUtilities.SVG_PREFIX}test`); diff --git a/ui/appui-abstract/src/test/utils/UiEvent.test.ts b/ui/appui-abstract/src/test/utils/UiEvent.test.ts index 2d4e4ad0b0c7..f77c3118adee 100644 --- a/ui/appui-abstract/src/test/utils/UiEvent.test.ts +++ b/ui/appui-abstract/src/test/utils/UiEvent.test.ts @@ -7,13 +7,12 @@ import * as sinon from "sinon"; import { UiEvent } from "../../appui-abstract"; describe("UIEvent", () => { - interface TestEventArgs { testId: string; testNum: number; } - class TestEvent extends UiEvent { } + class TestEvent extends UiEvent {} it("should call handler", () => { const testEvent: TestEvent = new TestEvent(); @@ -31,5 +30,4 @@ describe("UIEvent", () => { expect(spyMethod.calledOnce).to.be.true; }); - }); diff --git a/ui/appui-abstract/src/test/utils/UiEventDispatcher.test.ts b/ui/appui-abstract/src/test/utils/UiEventDispatcher.test.ts index 9b896a8fcfd2..05d5a7ad9c1d 100644 --- a/ui/appui-abstract/src/test/utils/UiEventDispatcher.test.ts +++ b/ui/appui-abstract/src/test/utils/UiEventDispatcher.test.ts @@ -147,5 +147,4 @@ describe("UiEventDispatcher", () => { expect(callbackHasExpectedEventIds).to.be.true; eventDispatcher.onSyncUiEvent.removeListener(handleSyncUiEvent); }); - }); diff --git a/ui/appui-abstract/src/test/utils/filter.test.ts b/ui/appui-abstract/src/test/utils/filter.test.ts index 25e8d04c5d04..0df6703277bf 100644 --- a/ui/appui-abstract/src/test/utils/filter.test.ts +++ b/ui/appui-abstract/src/test/utils/filter.test.ts @@ -5,10 +5,7 @@ import { assert } from "chai"; // based on file https://github.com/microsoft/vscode/blob/master/src/vs/base/test/common/filters.test.ts -import { - IMatch, - matchesWords, -} from "../../appui-abstract/utils/filter/filters"; +import { IMatch, matchesWords } from "../../appui-abstract/utils/filter/filters"; type IFilter = (word: string, wordToMatchAgainst: string) => IMatch[] | null; @@ -69,9 +66,8 @@ describe("Filters", () => { }); describe("string tests", () => { - it("matchesWords returns null", function () { + it("matchesWords returns null", function() { assert.ok(matchesWords("A", "") === null); }); - }); }); diff --git a/ui/appui-abstract/src/test/utils/getClassName.test.ts b/ui/appui-abstract/src/test/utils/getClassName.test.ts index a8ce035ef71b..821a08b7734b 100644 --- a/ui/appui-abstract/src/test/utils/getClassName.test.ts +++ b/ui/appui-abstract/src/test/utils/getClassName.test.ts @@ -43,5 +43,4 @@ describe("getClassName", () => { it("should be Number if passed a numeric value", () => { expect(getClassName(123)).to.eq("Number"); }); - }); diff --git a/ui/appui-abstract/src/test/utils/webpack.config.js b/ui/appui-abstract/src/test/utils/webpack.config.js index e9dd5d7de99b..b087bbfa504f 100644 --- a/ui/appui-abstract/src/test/utils/webpack.config.js +++ b/ui/appui-abstract/src/test/utils/webpack.config.js @@ -18,7 +18,7 @@ function createConfig(shouldInstrument) { output: { path: path.resolve(frontendLib, "test/webpack/"), filename: "bundled-tests.js", - devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]" + devtoolModuleFilenameTemplate: "file:///[absolute-resource-path]", }, devtool: "nosources-source-map", module: { @@ -26,13 +26,13 @@ function createConfig(shouldInstrument) { { test: /\.js$/, use: "source-map-loader", - enforce: "pre" - } - ] + enforce: "pre", + }, + ], }, stats: "errors-only", optimization: { - nodeEnv: "production" + nodeEnv: "production", }, plugins: [ // Makes some environment variables available to the JS code, for example: @@ -43,8 +43,8 @@ function createConfig(shouldInstrument) { env[key] = JSON.stringify(process.env[key]); return env; }, {}), - }) - ] + }), + ], }; if (shouldInstrument) { @@ -54,10 +54,10 @@ function createConfig(shouldInstrument) { include: frontendLib, exclude: path.join(frontendLib, "test"), use: { - loader: 'babel-loader', + loader: "babel-loader", options: { - plugins: ['babel-plugin-istanbul'] - } + plugins: ["babel-plugin-istanbul"], + }, }, enforce: "post", }); @@ -69,5 +69,5 @@ function createConfig(shouldInstrument) { // Runs webpack once for each config in the export array module.exports = [ createConfig(false), - createConfig(true) -] + createConfig(true), +]; diff --git a/utils/workspace-editor/eslint.config.js b/utils/workspace-editor/eslint.config.js index 77cd687cf0f6..d03a47abe740 100644 --- a/utils/workspace-editor/eslint.config.js +++ b/utils/workspace-editor/eslint.config.js @@ -4,5 +4,5 @@ module.exports = [ { files: ["**/*.ts"], ...iTwinPlugin.configs.iTwinjsRecommendedConfig, - } -]; \ No newline at end of file + }, +]; diff --git a/utils/workspace-editor/src/WorkspaceEditor.ts b/utils/workspace-editor/src/WorkspaceEditor.ts index 31f85d389a1c..e3a144b182bd 100644 --- a/utils/workspace-editor/src/WorkspaceEditor.ts +++ b/utils/workspace-editor/src/WorkspaceEditor.ts @@ -5,13 +5,22 @@ * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ -import * as fs from "fs"; -import { globSync } from "glob"; -import { extname, join } from "path"; -import * as readline from "readline"; -import * as Yargs from "yargs"; import { - _nativeDb, CloudSqlite, EditableWorkspaceContainer, EditableWorkspaceDb, IModelHost, IModelJsFs, SQLiteDb, SqliteStatement, WorkspaceContainerProps, WorkspaceDb, WorkspaceDbFullName, WorkspaceDbName, WorkspaceDbVersionIncrement, WorkspaceEditor, WorkspaceResourceName, + _nativeDb, + CloudSqlite, + EditableWorkspaceContainer, + EditableWorkspaceDb, + IModelHost, + IModelJsFs, + SQLiteDb, + SqliteStatement, + WorkspaceContainerProps, + WorkspaceDb, + WorkspaceDbFullName, + WorkspaceDbName, + WorkspaceDbVersionIncrement, + WorkspaceEditor, + WorkspaceResourceName, } from "@itwin/core-backend"; import { constructWorkspaceDb, @@ -23,6 +32,11 @@ import { } from "@itwin/core-backend/lib/cjs/internal/workspace/WorkspaceImpl"; import { AccessToken, BentleyError, DbResult, Logger, LogLevel, OpenMode, StopWatch } from "@itwin/core-bentley"; import { IModelError, LocalDirName, LocalFileName } from "@itwin/core-common"; +import * as fs from "fs"; +import { globSync } from "glob"; +import { extname, join } from "path"; +import * as readline from "readline"; +import * as Yargs from "yargs"; // cspell:ignore nodir nocase /* eslint-disable id-blacklist,no-console */ @@ -124,10 +138,12 @@ interface UploadOptions extends TransferOptions { async function askQuestion(query: string) { const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); - return new Promise((resolve) => rl.question(query, (ans) => { - rl.close(); - resolve(ans); - })); + return new Promise((resolve) => + rl.question(query, (ans) => { + rl.close(); + resolve(ans); + }) + ); } /** show a message */ @@ -161,7 +177,11 @@ async function createWorkspaceDb(args: CreateWorkspaceDbOpt) { } /** open, call a function to process, then close a WorkspaceDb */ -async function processWorkspace(args: T, ws: W, fn: (ws: W, args: T) => Promise) { +async function processWorkspace( + args: T, + ws: W, + fn: (ws: W, args: T) => Promise, +) { ws.open(); showMessage(`WorkspaceDb [${ws.sqliteDb[_nativeDb].getFilePath()}]`); try { @@ -242,7 +262,6 @@ async function listWorkspaceDb(args: ListOptions) { while (DbResult.BE_SQLITE_ROW === stmt.step()) nameAndSize(stmt); }); - } if (args.files) { @@ -542,7 +561,11 @@ async function queryWorkspaceDbs(args: WorkspaceDbOpt) { if (db) { const dirty = db.dirtyBlocks ? `, ${db.dirtyBlocks} dirty` : ""; const editable = db.state === "copied" ? ", editable" : ""; - showMessage(` "${dbName}", size=${friendlyFileSize(db.totalBlocks * blockSize)}, ${friendlyFileSize(db.localBlocks * blockSize)} downloaded (${(100 * db.localBlocks / db.totalBlocks).toFixed(0)}%)${editable}${dirty}`); + showMessage( + ` "${dbName}", size=${friendlyFileSize(db.totalBlocks * blockSize)}, ${friendlyFileSize(db.localBlocks * blockSize)} downloaded (${ + (100 * db.localBlocks / db.totalBlocks).toFixed(0) + }%)${editable}${dirty}`, + ); } } @@ -666,8 +689,13 @@ Yargs.command({ command: "versionDb ", describe: "make a new version of a WorkspaceDb", builder: { - versionType: { describe: "the type of version to create", default: "patch", string: true, choices: ["major" , "minor" , "patch" , "premajor" , "preminor" , "prepatch" , "prerelease"] }, - includePrerelease:{describe: "version prereleased Db", boolean:true, default:false}, + versionType: { + describe: "the type of version to create", + default: "patch", + string: true, + choices: ["major", "minor", "patch", "premajor", "preminor", "prepatch", "prerelease"], + }, + includePrerelease: { describe: "version prereleased Db", boolean: true, default: false }, }, handler: runCommand(versionWorkspaceDb), });